summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 13:14:46 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 13:14:46 +0000
commit025c439e829e0db9ac511cd9c1b8d5fd53475ead (patch)
treefa6986b4690f991613ffb97cea1f6942427baf5d
parentInitial commit. (diff)
downloadsudo-025c439e829e0db9ac511cd9c1b8d5fd53475ead.tar.xz
sudo-025c439e829e0db9ac511cd9c1b8d5fd53475ead.zip
Adding upstream version 1.9.15p5.upstream/1.9.15p5upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--ChangeLog78828
-rw-r--r--INSTALL.configure368
-rw-r--r--INSTALL.md1083
-rw-r--r--LICENSE.md351
-rw-r--r--MANIFEST1339
-rw-r--r--Makefile.in462
-rw-r--r--NEWS4494
-rw-r--r--README.LDAP.md209
-rw-r--r--README.md105
-rw-r--r--aclocal.m436
-rwxr-xr-xautogen.sh20
-rw-r--r--config.h.in1709
-rwxr-xr-xconfigure38690
-rw-r--r--configure.ac4937
-rw-r--r--docker/README45
-rw-r--r--docker/debian/latest/Dockerfile10
-rw-r--r--docker/debian/testing/Dockerfile10
-rw-r--r--docker/fedora/latest/Dockerfile8
-rw-r--r--docker/fedora/rawhide/Dockerfile8
-rw-r--r--docker/ubuntu/devel/Dockerfile10
-rw-r--r--docker/ubuntu/latest/Dockerfile10
-rw-r--r--docker/ubuntu/rolling/Dockerfile10
-rw-r--r--docs/CONTRIBUTING.md88
-rw-r--r--docs/CONTRIBUTORS.md252
-rw-r--r--docs/HISTORY.md77
-rw-r--r--docs/Makefile.in434
-rw-r--r--docs/SECURITY.md43
-rw-r--r--docs/TROUBLESHOOTING.md359
-rw-r--r--docs/UPGRADE.md636
-rw-r--r--docs/cvtsudoers.man.in1391
-rw-r--r--docs/cvtsudoers.mdoc.in1207
-rwxr-xr-xdocs/fixman.sh39
-rw-r--r--docs/fixmdoc.sed5
-rw-r--r--docs/schema.ActiveDirectory255
-rw-r--r--docs/schema.OpenLDAP78
-rw-r--r--docs/schema.iPlanet12
-rw-r--r--docs/schema.olcSudo79
-rw-r--r--docs/sudo.conf.man.in929
-rw-r--r--docs/sudo.conf.man.in.sed15
-rw-r--r--docs/sudo.conf.mdoc.in859
-rw-r--r--docs/sudo.man.in1739
-rw-r--r--docs/sudo.man.in.sed76
-rw-r--r--docs/sudo.mdoc.in1628
-rw-r--r--docs/sudo_logsrv.proto.man.in911
-rw-r--r--docs/sudo_logsrv.proto.mdoc.in828
-rw-r--r--docs/sudo_logsrvd.conf.man.in1114
-rw-r--r--docs/sudo_logsrvd.conf.mdoc.in1038
-rw-r--r--docs/sudo_logsrvd.man.in479
-rw-r--r--docs/sudo_logsrvd.mdoc.in435
-rw-r--r--docs/sudo_plugin.man.in5512
-rw-r--r--docs/sudo_plugin.mdoc.in4895
-rw-r--r--docs/sudo_plugin_python.man.in1905
-rw-r--r--docs/sudo_plugin_python.mdoc.in1556
-rw-r--r--docs/sudo_sendlog.man.in204
-rw-r--r--docs/sudo_sendlog.mdoc.in189
-rw-r--r--docs/sudoers.ldap.man.in1801
-rw-r--r--docs/sudoers.ldap.mdoc.in1653
-rw-r--r--docs/sudoers.man.in8031
-rw-r--r--docs/sudoers.man.in.sed150
-rw-r--r--docs/sudoers.mdoc.in7443
-rw-r--r--docs/sudoers_timestamp.man.in318
-rw-r--r--docs/sudoers_timestamp.mdoc.in295
-rw-r--r--docs/sudoreplay.man.in534
-rw-r--r--docs/sudoreplay.mdoc.in477
-rw-r--r--docs/visudo.man.in548
-rw-r--r--docs/visudo.mdoc.in525
-rw-r--r--etc/codespell.exclude35
-rw-r--r--etc/codespell.ignore19
-rw-r--r--etc/codespell.skip25
-rw-r--r--etc/init.d/aix.sh.in25
-rw-r--r--etc/init.d/hpux.sh.in27
-rw-r--r--etc/init.d/sudo.conf.in6
-rw-r--r--etc/macos-background.pngbin0 -> 17896 bytes
-rw-r--r--etc/sudo-logsrvd.pp272
-rw-r--r--etc/sudo-python.pp161
-rw-r--r--etc/sudo.pp571
-rw-r--r--examples/Makefile.in138
-rw-r--r--examples/cvtsudoers.conf82
-rw-r--r--examples/pam.conf30
-rw-r--r--examples/sudo.conf.in131
-rw-r--r--examples/sudo_logsrvd.conf.in251
-rw-r--r--examples/sudoers.in133
-rw-r--r--examples/syslog.conf.in26
-rw-r--r--include/Makefile.in115
-rw-r--r--include/compat/charclass.h41
-rw-r--r--include/compat/endian.h80
-rw-r--r--include/compat/fnmatch.h34
-rw-r--r--include/compat/getaddrinfo.h83
-rw-r--r--include/compat/getopt.h83
-rw-r--r--include/compat/glob.h78
-rw-r--r--include/compat/nss_dbdefs.h110
-rw-r--r--include/compat/sha2.h100
-rw-r--r--include/compat/stdbool.h44
-rw-r--r--include/hostcheck.h37
-rw-r--r--include/intercept.pb-c.h369
-rw-r--r--include/log_server.pb-c.h790
-rw-r--r--include/protobuf-c/protobuf-c.h1110
-rw-r--r--include/sudo_compat.h566
-rw-r--r--include/sudo_conf.h97
-rw-r--r--include/sudo_debug.h435
-rw-r--r--include/sudo_digest.h47
-rw-r--r--include/sudo_dso.h57
-rw-r--r--include/sudo_event.h216
-rw-r--r--include/sudo_eventlog.h175
-rw-r--r--include/sudo_fatal.h211
-rw-r--r--include/sudo_gettext.h77
-rw-r--r--include/sudo_iolog.h158
-rw-r--r--include/sudo_json.h100
-rw-r--r--include/sudo_lbuf.h62
-rw-r--r--include/sudo_plugin.h288
-rw-r--r--include/sudo_queue.h823
-rw-r--r--include/sudo_rand.h57
-rw-r--r--include/sudo_ssl_compat.h46
-rw-r--r--include/sudo_util.h358
-rw-r--r--lib/eventlog/Makefile.in350
-rw-r--r--lib/eventlog/eventlog.c1462
-rw-r--r--lib/eventlog/eventlog_conf.c226
-rw-r--r--lib/eventlog/eventlog_free.c86
-rw-r--r--lib/eventlog/logwrap.c90
-rw-r--r--lib/eventlog/parse_json.c1071
-rw-r--r--lib/eventlog/parse_json.h46
-rw-r--r--lib/eventlog/regress/eventlog_store/store_json_test.c199
-rw-r--r--lib/eventlog/regress/eventlog_store/store_sudo_test.c209
-rw-r--r--lib/eventlog/regress/eventlog_store/test1.json.in52
-rw-r--r--lib/eventlog/regress/eventlog_store/test1.json.out.ok31
-rw-r--r--lib/eventlog/regress/eventlog_store/test1.sudo.out.ok2
-rw-r--r--lib/eventlog/regress/eventlog_store/test2.json.in48
-rw-r--r--lib/eventlog/regress/eventlog_store/test2.json.out.ok29
-rw-r--r--lib/eventlog/regress/eventlog_store/test2.sudo.out.ok2
-rw-r--r--lib/eventlog/regress/eventlog_store/test3.json.in49
-rw-r--r--lib/eventlog/regress/eventlog_store/test3.json.out.ok30
-rw-r--r--lib/eventlog/regress/eventlog_store/test3.sudo.out.ok2
-rw-r--r--lib/eventlog/regress/eventlog_store/test4.json.in47
-rw-r--r--lib/eventlog/regress/eventlog_store/test4.json.out.ok31
-rw-r--r--lib/eventlog/regress/eventlog_store/test4.sudo.out.ok2
-rw-r--r--lib/eventlog/regress/logwrap/check_wrap.c124
-rw-r--r--lib/eventlog/regress/logwrap/check_wrap.in4
-rw-r--r--lib/eventlog/regress/logwrap/check_wrap.out.ok179
-rw-r--r--lib/eventlog/regress/parse_json/check_parse_json.c270
-rw-r--r--lib/eventlog/regress/parse_json/test1.in34
-rw-r--r--lib/eventlog/regress/parse_json/test2.in28
-rw-r--r--lib/eventlog/regress/parse_json/test2.out.ok34
-rw-r--r--lib/eventlog/regress/parse_json/test3.in22
-rw-r--r--lib/eventlog/regress/parse_json/test3.out.ok22
-rw-r--r--lib/fuzzstub/Makefile.in176
-rw-r--r--lib/fuzzstub/fuzzstub.c133
-rw-r--r--lib/iolog/Makefile.in823
-rw-r--r--lib/iolog/host_port.c109
-rw-r--r--lib/iolog/hostcheck.c400
-rw-r--r--lib/iolog/iolog_clearerr.c45
-rw-r--r--lib/iolog/iolog_close.c80
-rw-r--r--lib/iolog/iolog_conf.c202
-rw-r--r--lib/iolog/iolog_eof.c54
-rw-r--r--lib/iolog/iolog_filter.c248
-rw-r--r--lib/iolog/iolog_flush.c66
-rw-r--r--lib/iolog/iolog_gets.c78
-rw-r--r--lib/iolog/iolog_json.c56
-rw-r--r--lib/iolog/iolog_legacy.c169
-rw-r--r--lib/iolog/iolog_loginfo.c238
-rw-r--r--lib/iolog/iolog_mkdirs.c145
-rw-r--r--lib/iolog/iolog_mkdtemp.c100
-rw-r--r--lib/iolog/iolog_mkpath.c65
-rw-r--r--lib/iolog/iolog_nextid.c151
-rw-r--r--lib/iolog/iolog_open.c127
-rw-r--r--lib/iolog/iolog_openat.c90
-rw-r--r--lib/iolog/iolog_path.c130
-rw-r--r--lib/iolog/iolog_read.c79
-rw-r--r--lib/iolog/iolog_seek.c69
-rw-r--r--lib/iolog/iolog_swapids.c102
-rw-r--r--lib/iolog/iolog_timing.c273
-rw-r--r--lib/iolog/iolog_util.c74
-rw-r--r--lib/iolog/iolog_write.c105
-rw-r--r--lib/iolog/regress/corpus/seed/log_json/id.json36
-rw-r--r--lib/iolog/regress/corpus/seed/log_json/ls.json31
-rw-r--r--lib/iolog/regress/corpus/seed/log_json/mailq.json31
-rw-r--r--lib/iolog/regress/corpus/seed/log_json/make.json36
-rw-r--r--lib/iolog/regress/corpus/seed/log_json/pkg_add.json34
-rw-r--r--lib/iolog/regress/corpus/seed/log_json/pkg_delete.json34
-rw-r--r--lib/iolog/regress/corpus/seed/log_json/printenv.json34
-rw-r--r--lib/iolog/regress/corpus/seed/log_legacy/id.log3
-rw-r--r--lib/iolog/regress/corpus/seed/log_legacy/less.log3
-rw-r--r--lib/iolog/regress/corpus/seed/log_legacy/ls.log3
-rw-r--r--lib/iolog/regress/corpus/seed/log_legacy/mailq.log3
-rw-r--r--lib/iolog/regress/corpus/seed/log_legacy/make.log3
-rw-r--r--lib/iolog/regress/corpus/seed/log_legacy/pkg_add.log3
-rw-r--r--lib/iolog/regress/corpus/seed/log_legacy/pkg_delete.log3
-rw-r--r--lib/iolog/regress/corpus/seed/log_legacy/printenv.log3
-rw-r--r--lib/iolog/regress/corpus/seed/log_legacy/smtpctl.log3
-rw-r--r--lib/iolog/regress/corpus/seed/log_legacy/vi.log3
-rw-r--r--lib/iolog/regress/corpus/seed/timing/timing.151
-rw-r--r--lib/iolog/regress/corpus/seed/timing/timing.2196
-rw-r--r--lib/iolog/regress/corpus/seed/timing/timing.3988
-rw-r--r--lib/iolog/regress/corpus/seed/timing/timing.48
-rw-r--r--lib/iolog/regress/corpus/seed/timing/timing.5110
-rw-r--r--lib/iolog/regress/corpus/seed/timing/timing.615185
-rw-r--r--lib/iolog/regress/corpus/seed/timing/timing.710
-rw-r--r--lib/iolog/regress/corpus/seed/timing/timing.8891
-rw-r--r--lib/iolog/regress/corpus/seed/timing/timing.9416
-rw-r--r--lib/iolog/regress/fuzz/fuzz_iolog_json.c121
-rw-r--r--lib/iolog/regress/fuzz/fuzz_iolog_json.dict21
-rw-r--r--lib/iolog/regress/fuzz/fuzz_iolog_legacy.c119
-rw-r--r--lib/iolog/regress/fuzz/fuzz_iolog_legacy.dict42
-rw-r--r--lib/iolog/regress/fuzz/fuzz_iolog_timing.c132
-rw-r--r--lib/iolog/regress/fuzz/fuzz_iolog_timing.dict89
-rw-r--r--lib/iolog/regress/host_port/host_port_test.c158
-rw-r--r--lib/iolog/regress/iolog_filter/check_iolog_filter.c203
-rw-r--r--lib/iolog/regress/iolog_filter/test1/log3
-rw-r--r--lib/iolog/regress/iolog_filter/test1/timing44
-rw-r--r--lib/iolog/regress/iolog_filter/test1/ttyin1
-rw-r--r--lib/iolog/regress/iolog_filter/test1/ttyin.filtered1
-rw-r--r--lib/iolog/regress/iolog_filter/test1/ttyout7
-rw-r--r--lib/iolog/regress/iolog_filter/test2/log3
-rw-r--r--lib/iolog/regress/iolog_filter/test2/timing73
-rw-r--r--lib/iolog/regress/iolog_filter/test2/ttyin1
-rw-r--r--lib/iolog/regress/iolog_filter/test2/ttyin.filtered1
-rw-r--r--lib/iolog/regress/iolog_filter/test2/ttyout4
-rw-r--r--lib/iolog/regress/iolog_filter/test3/log3
-rw-r--r--lib/iolog/regress/iolog_filter/test3/timing54
-rw-r--r--lib/iolog/regress/iolog_filter/test3/ttyin1
-rw-r--r--lib/iolog/regress/iolog_filter/test3/ttyin.filtered1
-rw-r--r--lib/iolog/regress/iolog_filter/test3/ttyout6
-rw-r--r--lib/iolog/regress/iolog_mkpath/check_iolog_mkpath.c115
-rw-r--r--lib/iolog/regress/iolog_path/check_iolog_path.c296
-rw-r--r--lib/iolog/regress/iolog_path/data96
-rw-r--r--lib/iolog/regress/iolog_timing/check_iolog_timing.c161
-rw-r--r--lib/logsrv/Makefile.in186
-rw-r--r--lib/logsrv/log_server.pb-c.c1766
-rw-r--r--lib/logsrv/log_server.proto136
-rw-r--r--lib/protobuf-c/Makefile.in180
-rw-r--r--lib/protobuf-c/protobuf-c.c3687
-rw-r--r--lib/ssl_compat/Makefile.in189
-rw-r--r--lib/ssl_compat/ssl_compat.c64
-rw-r--r--lib/util/Makefile.in1730
-rw-r--r--lib/util/aix.c290
-rw-r--r--lib/util/arc4random.c206
-rw-r--r--lib/util/arc4random_buf.c70
-rw-r--r--lib/util/arc4random_uniform.c76
-rw-r--r--lib/util/basename.c52
-rw-r--r--lib/util/cfmakeraw.c58
-rw-r--r--lib/util/chacha_private.h222
-rw-r--r--lib/util/closefrom.c183
-rw-r--r--lib/util/digest.c172
-rw-r--r--lib/util/digest_gcrypt.c167
-rw-r--r--lib/util/digest_openssl.c159
-rw-r--r--lib/util/dup3.c74
-rw-r--r--lib/util/event.c881
-rw-r--r--lib/util/event_poll.c236
-rw-r--r--lib/util/event_select.c250
-rw-r--r--lib/util/explicit_bzero.c77
-rw-r--r--lib/util/fatal.c345
-rw-r--r--lib/util/fchmodat.c69
-rw-r--r--lib/util/fchownat.c67
-rw-r--r--lib/util/fnmatch.c499
-rw-r--r--lib/util/freezero.c38
-rw-r--r--lib/util/fstatat.c70
-rw-r--r--lib/util/getaddrinfo.c406
-rw-r--r--lib/util/getdelim.c83
-rw-r--r--lib/util/getentropy.c649
-rw-r--r--lib/util/getgrouplist.c530
-rw-r--r--lib/util/gethostname.c59
-rw-r--r--lib/util/getopt_long.c624
-rw-r--r--lib/util/gettime.c224
-rw-r--r--lib/util/getusershell.c145
-rw-r--r--lib/util/gidlist.c87
-rw-r--r--lib/util/glob.c953
-rw-r--r--lib/util/gmtime_r.c49
-rw-r--r--lib/util/hexchar.c103
-rw-r--r--lib/util/inet_ntop.c229
-rw-r--r--lib/util/inet_pton.c252
-rw-r--r--lib/util/isblank.c37
-rw-r--r--lib/util/json.c423
-rw-r--r--lib/util/key_val.c56
-rw-r--r--lib/util/lbuf.c496
-rw-r--r--lib/util/localtime_r.c49
-rw-r--r--lib/util/locking.c143
-rw-r--r--lib/util/logfac.c90
-rw-r--r--lib/util/logpri.c85
-rw-r--r--lib/util/memrchr.c51
-rw-r--r--lib/util/mkdir_parents.c199
-rw-r--r--lib/util/mkdirat.c61
-rw-r--r--lib/util/mksiglist.c57
-rw-r--r--lib/util/mksigname.c57
-rw-r--r--lib/util/mktemp.c172
-rw-r--r--lib/util/mmap_alloc.c160
-rw-r--r--lib/util/multiarch.c103
-rw-r--r--lib/util/nanosleep.c74
-rw-r--r--lib/util/openat.c63
-rw-r--r--lib/util/parseln.c130
-rw-r--r--lib/util/pipe2.c64
-rw-r--r--lib/util/pread.c48
-rw-r--r--lib/util/progname.c100
-rw-r--r--lib/util/pw_dup.c99
-rw-r--r--lib/util/pwrite.c48
-rw-r--r--lib/util/rcstr.c103
-rw-r--r--lib/util/reallocarray.c57
-rw-r--r--lib/util/realpath.c205
-rw-r--r--lib/util/regex.c194
-rw-r--r--lib/util/regress/closefrom/closefrom_test.c121
-rw-r--r--lib/util/regress/corpus/seed/sudo_conf/sudo.conf.1116
-rw-r--r--lib/util/regress/corpus/seed/sudo_conf/sudo.conf.2116
-rw-r--r--lib/util/regress/corpus/seed/sudo_conf/sudo.conf.3126
-rw-r--r--lib/util/regress/digest/digest_test.c1179
-rw-r--r--lib/util/regress/fnmatch/fnm_test.c92
-rw-r--r--lib/util/regress/fnmatch/fnm_test.in6
-rw-r--r--lib/util/regress/fuzz/fuzz_sudo_conf.c149
-rw-r--r--lib/util/regress/fuzz/fuzz_sudo_conf.dict18
-rw-r--r--lib/util/regress/getdelim/getdelim_test.c186
-rw-r--r--lib/util/regress/getgrouplist/getgids.c91
-rw-r--r--lib/util/regress/getgrouplist/getgrouplist_test.c117
-rw-r--r--lib/util/regress/glob/files47
-rw-r--r--lib/util/regress/glob/globtest.c224
-rw-r--r--lib/util/regress/glob/globtest.in64
-rwxr-xr-xlib/util/regress/harness.in109
-rw-r--r--lib/util/regress/hexchar/hexchar_test.c81
-rw-r--r--lib/util/regress/json/json_test.c235
-rw-r--r--lib/util/regress/mktemp/mktemp_test.c205
-rw-r--r--lib/util/regress/multiarch/multiarch_test.c184
-rw-r--r--lib/util/regress/open_parent_dir/open_parent_dir_test.c166
-rw-r--r--lib/util/regress/parse_gids/parse_gids_test.c124
-rw-r--r--lib/util/regress/progname/progname_test.c67
-rw-r--r--lib/util/regress/regex/regex_test.c126
-rw-r--r--lib/util/regress/strsig/strsig_test.c319
-rw-r--r--lib/util/regress/strsplit/strsplit_test.c117
-rw-r--r--lib/util/regress/strtofoo/strtobool_test.c98
-rw-r--r--lib/util/regress/strtofoo/strtoid_test.c118
-rw-r--r--lib/util/regress/strtofoo/strtomode_test.c91
-rw-r--r--lib/util/regress/strtofoo/strtonum_test.c135
-rw-r--r--lib/util/regress/sudo_conf/conf_test.c126
-rw-r--r--lib/util/regress/sudo_conf/test1.in73
-rw-r--r--lib/util/regress/sudo_conf/test1.out.ok8
-rw-r--r--lib/util/regress/sudo_conf/test2.in0
-rw-r--r--lib/util/regress/sudo_conf/test2.out.ok4
-rw-r--r--lib/util/regress/sudo_conf/test3.in2
-rw-r--r--lib/util/regress/sudo_conf/test3.out.ok6
-rw-r--r--lib/util/regress/sudo_conf/test4.err.ok1
-rw-r--r--lib/util/regress/sudo_conf/test4.in1
-rw-r--r--lib/util/regress/sudo_conf/test4.out.ok4
-rw-r--r--lib/util/regress/sudo_conf/test5.err.ok1
-rw-r--r--lib/util/regress/sudo_conf/test5.in1
-rw-r--r--lib/util/regress/sudo_conf/test5.out.ok4
-rw-r--r--lib/util/regress/sudo_conf/test6.in1
-rw-r--r--lib/util/regress/sudo_conf/test6.out.ok4
-rw-r--r--lib/util/regress/sudo_conf/test7.in4
-rw-r--r--lib/util/regress/sudo_conf/test7.out.ok8
-rw-r--r--lib/util/regress/sudo_parseln/parseln_test.c64
-rw-r--r--lib/util/regress/sudo_parseln/test1.in72
-rw-r--r--lib/util/regress/sudo_parseln/test1.out.ok72
-rw-r--r--lib/util/regress/sudo_parseln/test2.in8
-rw-r--r--lib/util/regress/sudo_parseln/test2.out.ok3
-rw-r--r--lib/util/regress/sudo_parseln/test3.in1
-rw-r--r--lib/util/regress/sudo_parseln/test3.out.ok1
-rw-r--r--lib/util/regress/sudo_parseln/test4.in4
-rw-r--r--lib/util/regress/sudo_parseln/test4.out.ok2
-rw-r--r--lib/util/regress/sudo_parseln/test5.in1
-rw-r--r--lib/util/regress/sudo_parseln/test5.out.ok0
-rw-r--r--lib/util/regress/sudo_parseln/test6.in3
-rw-r--r--lib/util/regress/sudo_parseln/test6.out.ok2
-rw-r--r--lib/util/regress/tailq/hltq_test.c205
-rw-r--r--lib/util/regress/uuid/uuid_test.c105
-rw-r--r--lib/util/roundup.c81
-rw-r--r--lib/util/secure_path.c203
-rw-r--r--lib/util/setgroups.c56
-rw-r--r--lib/util/sha2.c515
-rw-r--r--lib/util/sig2str.c100
-rw-r--r--lib/util/siglist.in56
-rw-r--r--lib/util/snprintf.c1546
-rw-r--r--lib/util/str2sig.c174
-rw-r--r--lib/util/strlcat.c69
-rw-r--r--lib/util/strlcpy.c64
-rw-r--r--lib/util/strndup.c51
-rw-r--r--lib/util/strnlen.c45
-rw-r--r--lib/util/strsignal.c52
-rw-r--r--lib/util/strsplit.c73
-rw-r--r--lib/util/strtobool.c77
-rw-r--r--lib/util/strtoid.c108
-rw-r--r--lib/util/strtomode.c71
-rw-r--r--lib/util/strtonum.c192
-rw-r--r--lib/util/sudo_conf.c809
-rw-r--r--lib/util/sudo_debug.c1184
-rw-r--r--lib/util/sudo_dso.c432
-rw-r--r--lib/util/sys_siglist.h182
-rw-r--r--lib/util/sys_signame.h182
-rw-r--r--lib/util/term.c491
-rw-r--r--lib/util/timegm.c99
-rw-r--r--lib/util/ttyname_dev.c311
-rw-r--r--lib/util/ttysize.c80
-rw-r--r--lib/util/unlinkat.c60
-rw-r--r--lib/util/util.exp.in178
-rw-r--r--lib/util/utimens.c200
-rw-r--r--lib/util/uuid.c99
-rw-r--r--lib/zlib/Makefile.in231
-rw-r--r--lib/zlib/adler32.c164
-rw-r--r--lib/zlib/compress.c75
-rw-r--r--lib/zlib/crc32.c1049
-rw-r--r--lib/zlib/crc32.h9446
-rw-r--r--lib/zlib/deflate.c2116
-rw-r--r--lib/zlib/deflate.h346
-rw-r--r--lib/zlib/gzclose.c23
-rw-r--r--lib/zlib/gzguts.h218
-rw-r--r--lib/zlib/gzlib.c582
-rw-r--r--lib/zlib/gzread.c602
-rw-r--r--lib/zlib/gzwrite.c631
-rw-r--r--lib/zlib/infback.c628
-rw-r--r--lib/zlib/inffast.c320
-rw-r--r--lib/zlib/inffast.h11
-rw-r--r--lib/zlib/inffixed.h94
-rw-r--r--lib/zlib/inflate.c1525
-rw-r--r--lib/zlib/inflate.h126
-rw-r--r--lib/zlib/inftrees.c299
-rw-r--r--lib/zlib/inftrees.h62
-rw-r--r--lib/zlib/trees.c1103
-rw-r--r--lib/zlib/trees.h128
-rw-r--r--lib/zlib/uncompr.c85
-rw-r--r--lib/zlib/zconf.h.in580
-rw-r--r--lib/zlib/zlib.exp88
-rw-r--r--lib/zlib/zlib.h1938
-rw-r--r--lib/zlib/zutil.c299
-rw-r--r--lib/zlib/zutil.h275
-rw-r--r--logsrvd/Makefile.in610
-rw-r--r--logsrvd/iolog_writer.c914
-rw-r--r--logsrvd/logsrv_util.c191
-rw-r--r--logsrvd/logsrv_util.h63
-rw-r--r--logsrvd/logsrvd.c2059
-rw-r--r--logsrvd/logsrvd.h266
-rw-r--r--logsrvd/logsrvd_conf.c1918
-rw-r--r--logsrvd/logsrvd_journal.c622
-rw-r--r--logsrvd/logsrvd_local.c715
-rw-r--r--logsrvd/logsrvd_queue.c287
-rw-r--r--logsrvd/logsrvd_relay.c1261
-rw-r--r--logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.1253
-rw-r--r--logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.2255
-rw-r--r--logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.3253
-rw-r--r--logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.4255
-rw-r--r--logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.5255
-rw-r--r--logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.6255
-rw-r--r--logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.7255
-rw-r--r--logsrvd/regress/fuzz/fuzz_logsrvd_conf.c225
-rw-r--r--logsrvd/regress/fuzz/fuzz_logsrvd_conf.dict44
-rw-r--r--logsrvd/regress/logsrvd_conf/cacert.pem34
-rw-r--r--logsrvd/regress/logsrvd_conf/logsrvd_cert.pem28
-rw-r--r--logsrvd/regress/logsrvd_conf/logsrvd_conf_test.c90
-rw-r--r--logsrvd/regress/logsrvd_conf/logsrvd_dhparams.pem8
-rw-r--r--logsrvd/regress/logsrvd_conf/logsrvd_key.pem28
-rw-r--r--logsrvd/regress/logsrvd_conf/sudo_logsrvd.conf.1.in252
-rw-r--r--logsrvd/regress/logsrvd_conf/sudo_logsrvd.conf.2.in252
-rw-r--r--logsrvd/regress/logsrvd_conf/tls/sudo_logsrvd.conf.1.in252
-rw-r--r--logsrvd/regress/logsrvd_conf/tls/sudo_logsrvd.conf.2.in252
-rw-r--r--logsrvd/sendlog.c1927
-rw-r--r--logsrvd/sendlog.h82
-rw-r--r--logsrvd/tls_client.c251
-rw-r--r--logsrvd/tls_common.h53
-rw-r--r--logsrvd/tls_init.c383
-rw-r--r--m4/ax_append_flag.m450
-rw-r--r--m4/ax_check_compile_flag.m453
-rw-r--r--m4/ax_check_link_flag.m471
-rw-r--r--m4/ax_func_getaddrinfo.m470
-rw-r--r--m4/ax_func_snprintf.m485
-rw-r--r--m4/ax_gcc_builtin.m4176
-rw-r--r--m4/ax_prog_cc_for_build.m4155
-rw-r--r--m4/gettext.m461
-rw-r--r--m4/hardening.m4119
-rw-r--r--m4/ldap.m4130
-rw-r--r--m4/libtool.m48459
-rw-r--r--m4/ltoptions.m4437
-rw-r--r--m4/ltsugar.m4124
-rw-r--r--m4/ltversion.m424
-rw-r--r--m4/lt~obsolete.m499
-rw-r--r--m4/openssl.m4309
-rw-r--r--m4/pie.m486
-rw-r--r--m4/python.m4244
-rw-r--r--m4/runlog.m417
-rw-r--r--m4/sanitizer.m463
-rw-r--r--m4/sudo.m4713
-rw-r--r--m4/visibility.m4140
-rw-r--r--pathnames.h.in265
-rw-r--r--plugins/audit_json/Makefile.in232
-rw-r--r--plugins/audit_json/audit_json.c737
-rw-r--r--plugins/audit_json/audit_json.exp1
-rw-r--r--plugins/group_file/Makefile.in234
-rw-r--r--plugins/group_file/getgrent.c193
-rw-r--r--plugins/group_file/group_file.c129
-rw-r--r--plugins/group_file/group_file.exp1
-rw-r--r--plugins/group_file/plugin_test.c222
-rw-r--r--plugins/python/Makefile.in540
-rw-r--r--plugins/python/example_approval_plugin.py18
-rw-r--r--plugins/python/example_audit_plugin.py84
-rw-r--r--plugins/python/example_conversation.py98
-rw-r--r--plugins/python/example_debugging.py85
-rw-r--r--plugins/python/example_group_plugin.py45
-rw-r--r--plugins/python/example_io_plugin.py153
-rw-r--r--plugins/python/example_policy_plugin.py172
-rw-r--r--plugins/python/lsan_suppr.txt1
-rw-r--r--plugins/python/pyhelpers.c587
-rw-r--r--plugins/python/pyhelpers.h108
-rw-r--r--plugins/python/pyhelpers_cpychecker.h45
-rw-r--r--plugins/python/python_baseplugin.c88
-rw-r--r--plugins/python/python_convmessage.c155
-rw-r--r--plugins/python/python_loghandler.c182
-rw-r--r--plugins/python/python_plugin.exp8
-rw-r--r--plugins/python/python_plugin_approval.c196
-rw-r--r--plugins/python/python_plugin_approval_multi.inc57
-rw-r--r--plugins/python/python_plugin_audit.c281
-rw-r--r--plugins/python/python_plugin_audit_multi.inc78
-rw-r--r--plugins/python/python_plugin_common.c781
-rw-r--r--plugins/python/python_plugin_common.h85
-rw-r--r--plugins/python/python_plugin_group.c114
-rw-r--r--plugins/python/python_plugin_io.c276
-rw-r--r--plugins/python/python_plugin_io_multi.inc99
-rw-r--r--plugins/python/python_plugin_policy.c289
-rw-r--r--plugins/python/regress/check_python_examples.c1619
-rw-r--r--plugins/python/regress/iohelpers.c182
-rw-r--r--plugins/python/regress/iohelpers.h58
-rw-r--r--plugins/python/regress/plugin_approval_test.py22
-rw-r--r--plugins/python/regress/plugin_conflict.py11
-rw-r--r--plugins/python/regress/plugin_errorstr.py18
-rw-r--r--plugins/python/regress/testdata/check_example_audit_plugin_receives_accept.stdout7
-rw-r--r--plugins/python/regress/testdata/check_example_audit_plugin_receives_error.stdout5
-rw-r--r--plugins/python/regress/testdata/check_example_audit_plugin_receives_reject.stdout5
-rw-r--r--plugins/python/regress/testdata/check_example_audit_plugin_version_display.stdout6
-rw-r--r--plugins/python/regress/testdata/check_example_audit_plugin_workflow_multiple.stderr1
-rw-r--r--plugins/python/regress/testdata/check_example_audit_plugin_workflow_multiple.stdout14
-rw-r--r--plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.conversation3
-rw-r--r--plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.stderr0
-rw-r--r--plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.stdout3
-rw-r--r--plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.stored3
-rw-r--r--plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.conversation3
-rw-r--r--plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.stderr0
-rw-r--r--plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.stdout1
-rw-r--r--plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.stored3
-rw-r--r--plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.conv2
-rw-r--r--plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.conversation2
-rw-r--r--plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.stderr1
-rw-r--r--plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.stdout1
-rw-r--r--plugins/python/regress/testdata/check_example_debugging_c_calls@diag.log6
-rw-r--r--plugins/python/regress/testdata/check_example_debugging_c_calls@info.log11
-rw-r--r--plugins/python/regress/testdata/check_example_debugging_load@diag.log3
-rw-r--r--plugins/python/regress/testdata/check_example_debugging_plugin@err.log2
-rw-r--r--plugins/python/regress/testdata/check_example_debugging_plugin@info.log8
-rw-r--r--plugins/python/regress/testdata/check_example_debugging_py_calls@diag.log2
-rw-r--r--plugins/python/regress/testdata/check_example_debugging_py_calls@info.log9
-rw-r--r--plugins/python/regress/testdata/check_example_debugging_sudo_cb@info.log1
-rw-r--r--plugins/python/regress/testdata/check_example_group_plugin_is_able_to_debug.log4
-rw-r--r--plugins/python/regress/testdata/check_example_io_plugin_command_log.stderr0
-rw-r--r--plugins/python/regress/testdata/check_example_io_plugin_command_log.stdout1
-rw-r--r--plugins/python/regress/testdata/check_example_io_plugin_command_log.stored16
-rw-r--r--plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stderr1
-rw-r--r--plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stdout2
-rw-r--r--plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple1.stored16
-rw-r--r--plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple2.stored16
-rw-r--r--plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stderr0
-rw-r--r--plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stdout1
-rw-r--r--plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stored8
-rw-r--r--plugins/python/regress/testdata/check_example_io_plugin_fails_with_python_backtrace.stderr1
-rw-r--r--plugins/python/regress/testdata/check_example_io_plugin_fails_with_python_backtrace.stdout7
-rw-r--r--plugins/python/regress/testdata/check_example_io_plugin_version_display.stderr0
-rw-r--r--plugins/python/regress/testdata/check_example_io_plugin_version_display.stdout2
-rw-r--r--plugins/python/regress/testdata/check_example_io_plugin_version_display.stored2
-rw-r--r--plugins/python/regress/testdata/check_example_io_plugin_version_display_full.stdout3
-rw-r--r--plugins/python/regress/testdata/check_example_policy_plugin_accepted_execution.stderr0
-rw-r--r--plugins/python/regress/testdata/check_example_policy_plugin_accepted_execution.stdout1
-rw-r--r--plugins/python/regress/testdata/check_example_policy_plugin_denied_execution.stderr1
-rw-r--r--plugins/python/regress/testdata/check_example_policy_plugin_denied_execution.stdout0
-rw-r--r--plugins/python/regress/testdata/check_example_policy_plugin_failed_execution.stderr1
-rw-r--r--plugins/python/regress/testdata/check_example_policy_plugin_failed_execution.stdout0
-rw-r--r--plugins/python/regress/testdata/check_example_policy_plugin_list.stderr0
-rw-r--r--plugins/python/regress/testdata/check_example_policy_plugin_list.stdout25
-rw-r--r--plugins/python/regress/testdata/check_example_policy_plugin_validate_invalidate.log8
-rw-r--r--plugins/python/regress/testdata/check_example_policy_plugin_version_display.stderr0
-rw-r--r--plugins/python/regress/testdata/check_example_policy_plugin_version_display.stdout1
-rw-r--r--plugins/python/regress/testdata/check_example_policy_plugin_version_display_full.stdout2
-rw-r--r--plugins/python/regress/testdata/check_loading_fails_missing_classname.stderr3
-rw-r--r--plugins/python/regress/testdata/check_loading_fails_missing_classname.stdout0
-rw-r--r--plugins/python/regress/testdata/check_loading_fails_missing_path.stderr2
-rw-r--r--plugins/python/regress/testdata/check_loading_fails_missing_path.stdout0
-rw-r--r--plugins/python/regress/testdata/check_loading_fails_not_owned_by_root.stderr1
-rw-r--r--plugins/python/regress/testdata/check_loading_fails_not_owned_by_root.stdout0
-rw-r--r--plugins/python/regress/testdata/check_loading_fails_wrong_classname.stderr2
-rw-r--r--plugins/python/regress/testdata/check_loading_fails_wrong_classname.stdout0
-rw-r--r--plugins/python/regress/testdata/check_loading_fails_wrong_path.stderr1
-rw-r--r--plugins/python/regress/testdata/check_loading_fails_wrong_path.stdout0
-rw-r--r--plugins/python/regress/testdata/check_loading_succeeds_with_missing_classname.stdout1
-rw-r--r--plugins/python/regress/testdata/check_multiple_approval_plugin_and_arguments.stderr1
-rw-r--r--plugins/python/regress/testdata/check_multiple_approval_plugin_and_arguments.stdout67
-rw-r--r--plugins/python/regress/testdata/check_python_plugins_do_not_affect_each_other.stdout4
-rw-r--r--plugins/python/regress/testhelpers.c356
-rw-r--r--plugins/python/regress/testhelpers.h175
-rw-r--r--plugins/python/sudo_python_debug.c129
-rw-r--r--plugins/python/sudo_python_debug.h46
-rw-r--r--plugins/python/sudo_python_module.c631
-rw-r--r--plugins/python/sudo_python_module.h56
-rw-r--r--plugins/sample/Makefile.in221
-rw-r--r--plugins/sample/README22
-rw-r--r--plugins/sample/sample_plugin.c517
-rw-r--r--plugins/sample/sample_plugin.exp2
-rw-r--r--plugins/sample_approval/Makefile.in232
-rw-r--r--plugins/sample_approval/sample_approval.c169
-rw-r--r--plugins/sample_approval/sample_approval.exp1
-rw-r--r--plugins/sudoers/Makefile.in3546
-rw-r--r--plugins/sudoers/alias.c380
-rw-r--r--plugins/sudoers/audit.c494
-rw-r--r--plugins/sudoers/auth/API148
-rw-r--r--plugins/sudoers/auth/afs.c88
-rw-r--r--plugins/sudoers/auth/aix_auth.c314
-rw-r--r--plugins/sudoers/auth/bsdauth.c224
-rw-r--r--plugins/sudoers/auth/dce.c202
-rw-r--r--plugins/sudoers/auth/fwtk.c161
-rw-r--r--plugins/sudoers/auth/kerb5.c345
-rw-r--r--plugins/sudoers/auth/pam.c776
-rw-r--r--plugins/sudoers/auth/passwd.c141
-rw-r--r--plugins/sudoers/auth/rfc1938.c141
-rw-r--r--plugins/sudoers/auth/secureware.c116
-rw-r--r--plugins/sudoers/auth/securid5.c237
-rw-r--r--plugins/sudoers/auth/sia.c160
-rw-r--r--plugins/sudoers/auth/sudo_auth.c557
-rw-r--r--plugins/sudoers/auth/sudo_auth.h106
-rw-r--r--plugins/sudoers/b64_decode.c83
-rw-r--r--plugins/sudoers/b64_encode.c64
-rw-r--r--plugins/sudoers/boottime.c167
-rw-r--r--plugins/sudoers/bsm_audit.c284
-rw-r--r--plugins/sudoers/bsm_audit.h26
-rw-r--r--plugins/sudoers/canon_path.c200
-rw-r--r--plugins/sudoers/check.c325
-rw-r--r--plugins/sudoers/check_aliases.c186
-rw-r--r--plugins/sudoers/check_util.c88
-rw-r--r--plugins/sudoers/cvtsudoers.c1556
-rw-r--r--plugins/sudoers/cvtsudoers.h110
-rw-r--r--plugins/sudoers/cvtsudoers_csv.c720
-rw-r--r--plugins/sudoers/cvtsudoers_json.c937
-rw-r--r--plugins/sudoers/cvtsudoers_ldif.c735
-rw-r--r--plugins/sudoers/cvtsudoers_merge.c1247
-rw-r--r--plugins/sudoers/cvtsudoers_pwutil.c484
-rw-r--r--plugins/sudoers/def_data.c701
-rw-r--r--plugins/sudoers/def_data.h341
-rw-r--r--plugins/sudoers/def_data.in502
-rw-r--r--plugins/sudoers/defaults.c1310
-rw-r--r--plugins/sudoers/defaults.h157
-rw-r--r--plugins/sudoers/digestname.c55
-rw-r--r--plugins/sudoers/display.c661
-rw-r--r--plugins/sudoers/editor.c275
-rw-r--r--plugins/sudoers/env.c1444
-rw-r--r--plugins/sudoers/env_pattern.c93
-rw-r--r--plugins/sudoers/exptilde.c99
-rw-r--r--plugins/sudoers/file.c153
-rw-r--r--plugins/sudoers/filedigest.c91
-rw-r--r--plugins/sudoers/find_path.c168
-rw-r--r--plugins/sudoers/fmtsudoers.c322
-rw-r--r--plugins/sudoers/fmtsudoers_cvt.c219
-rw-r--r--plugins/sudoers/gc.c154
-rw-r--r--plugins/sudoers/gentime.c171
-rw-r--r--plugins/sudoers/getdate.c2455
-rw-r--r--plugins/sudoers/getdate.y921
-rw-r--r--plugins/sudoers/getspwuid.c139
-rw-r--r--plugins/sudoers/goodpath.c61
-rw-r--r--plugins/sudoers/gram.c4308
-rw-r--r--plugins/sudoers/gram.h206
-rw-r--r--plugins/sudoers/gram.y2125
-rw-r--r--plugins/sudoers/group_plugin.c313
-rw-r--r--plugins/sudoers/ins_2001.h35
-rw-r--r--plugins/sudoers/ins_classic.h39
-rw-r--r--plugins/sudoers/ins_csops.h41
-rw-r--r--plugins/sudoers/ins_goons.h50
-rw-r--r--plugins/sudoers/ins_python.h39
-rw-r--r--plugins/sudoers/insults.h69
-rw-r--r--plugins/sudoers/interfaces.c134
-rw-r--r--plugins/sudoers/interfaces.h57
-rw-r--r--plugins/sudoers/iolog.c1388
-rw-r--r--plugins/sudoers/iolog_path_escapes.c170
-rw-r--r--plugins/sudoers/ldap.c2045
-rw-r--r--plugins/sudoers/ldap_conf.c960
-rw-r--r--plugins/sudoers/ldap_innetgr.c264
-rw-r--r--plugins/sudoers/ldap_util.c750
-rw-r--r--plugins/sudoers/linux_audit.c117
-rw-r--r--plugins/sudoers/linux_audit.h24
-rw-r--r--plugins/sudoers/locale.c155
-rw-r--r--plugins/sudoers/log_client.c2102
-rw-r--r--plugins/sudoers/log_client.h124
-rw-r--r--plugins/sudoers/logging.c1158
-rw-r--r--plugins/sudoers/logging.h94
-rw-r--r--plugins/sudoers/lookup.c569
-rw-r--r--plugins/sudoers/match.c812
-rw-r--r--plugins/sudoers/match_addr.c209
-rw-r--r--plugins/sudoers/match_command.c898
-rw-r--r--plugins/sudoers/match_digest.c134
-rwxr-xr-xplugins/sudoers/mkdefaults163
-rw-r--r--plugins/sudoers/parse.h505
-rw-r--r--plugins/sudoers/parse_ldif.c778
-rw-r--r--plugins/sudoers/parser_warnx.c82
-rw-r--r--plugins/sudoers/pivot.c87
-rw-r--r--plugins/sudoers/pivot.h32
-rw-r--r--plugins/sudoers/po/README14
-rw-r--r--plugins/sudoers/po/ast.mobin0 -> 34264 bytes
-rw-r--r--plugins/sudoers/po/ast.po2343
-rw-r--r--plugins/sudoers/po/ca.mobin0 -> 67494 bytes
-rw-r--r--plugins/sudoers/po/ca.po3260
-rw-r--r--plugins/sudoers/po/cs.mobin0 -> 78152 bytes
-rw-r--r--plugins/sudoers/po/cs.po4144
-rw-r--r--plugins/sudoers/po/da.mobin0 -> 46504 bytes
-rw-r--r--plugins/sudoers/po/da.po2344
-rw-r--r--plugins/sudoers/po/de.mobin0 -> 81080 bytes
-rw-r--r--plugins/sudoers/po/de.po3867
-rw-r--r--plugins/sudoers/po/el.mobin0 -> 51009 bytes
-rw-r--r--plugins/sudoers/po/el.po1718
-rw-r--r--plugins/sudoers/po/eo.mobin0 -> 75146 bytes
-rw-r--r--plugins/sudoers/po/eo.po3850
-rw-r--r--plugins/sudoers/po/es.mobin0 -> 14341 bytes
-rw-r--r--plugins/sudoers/po/es.po1882
-rw-r--r--plugins/sudoers/po/eu.mobin0 -> 6404 bytes
-rw-r--r--plugins/sudoers/po/eu.po1679
-rw-r--r--plugins/sudoers/po/fi.mobin0 -> 73935 bytes
-rw-r--r--plugins/sudoers/po/fi.po4136
-rw-r--r--plugins/sudoers/po/fr.mobin0 -> 85635 bytes
-rw-r--r--plugins/sudoers/po/fr.po4195
-rw-r--r--plugins/sudoers/po/fur.mobin0 -> 9485 bytes
-rw-r--r--plugins/sudoers/po/fur.po2119
-rw-r--r--plugins/sudoers/po/hr.mobin0 -> 78894 bytes
-rw-r--r--plugins/sudoers/po/hr.po4233
-rw-r--r--plugins/sudoers/po/hu.mobin0 -> 26073 bytes
-rw-r--r--plugins/sudoers/po/hu.po2152
-rw-r--r--plugins/sudoers/po/it.mobin0 -> 68062 bytes
-rw-r--r--plugins/sudoers/po/it.po3271
-rw-r--r--plugins/sudoers/po/ja.mobin0 -> 87830 bytes
-rw-r--r--plugins/sudoers/po/ja.po4210
-rw-r--r--plugins/sudoers/po/ka.mobin0 -> 14862 bytes
-rw-r--r--plugins/sudoers/po/ka.po3715
-rw-r--r--plugins/sudoers/po/ko.mobin0 -> 80907 bytes
-rw-r--r--plugins/sudoers/po/ko.po3849
-rw-r--r--plugins/sudoers/po/lt.mobin0 -> 1994 bytes
-rw-r--r--plugins/sudoers/po/lt.po1682
-rw-r--r--plugins/sudoers/po/nb.mobin0 -> 49008 bytes
-rw-r--r--plugins/sudoers/po/nb.po2444
-rw-r--r--plugins/sudoers/po/nl.mobin0 -> 39096 bytes
-rw-r--r--plugins/sudoers/po/nl.po2282
-rw-r--r--plugins/sudoers/po/pl.mobin0 -> 78954 bytes
-rw-r--r--plugins/sudoers/po/pl.po3850
-rw-r--r--plugins/sudoers/po/pt.mobin0 -> 70925 bytes
-rw-r--r--plugins/sudoers/po/pt.po3681
-rw-r--r--plugins/sudoers/po/pt_BR.mobin0 -> 73478 bytes
-rw-r--r--plugins/sudoers/po/pt_BR.po3801
-rw-r--r--plugins/sudoers/po/ro.mobin0 -> 82180 bytes
-rw-r--r--plugins/sudoers/po/ro.po4144
-rw-r--r--plugins/sudoers/po/ru.mobin0 -> 104642 bytes
-rw-r--r--plugins/sudoers/po/ru.po3869
-rw-r--r--plugins/sudoers/po/sk.mobin0 -> 4927 bytes
-rw-r--r--plugins/sudoers/po/sk.po1892
-rw-r--r--plugins/sudoers/po/sl.mobin0 -> 36413 bytes
-rw-r--r--plugins/sudoers/po/sl.po1758
-rw-r--r--plugins/sudoers/po/sr.mobin0 -> 101345 bytes
-rw-r--r--plugins/sudoers/po/sr.po4094
-rw-r--r--plugins/sudoers/po/sudoers.pot3797
-rw-r--r--plugins/sudoers/po/sv.mobin0 -> 75681 bytes
-rw-r--r--plugins/sudoers/po/sv.po4178
-rw-r--r--plugins/sudoers/po/tr.mobin0 -> 13979 bytes
-rw-r--r--plugins/sudoers/po/tr.po1721
-rw-r--r--plugins/sudoers/po/uk.mobin0 -> 107117 bytes
-rw-r--r--plugins/sudoers/po/uk.po3926
-rw-r--r--plugins/sudoers/po/vi.mobin0 -> 54696 bytes
-rw-r--r--plugins/sudoers/po/vi.po2502
-rw-r--r--plugins/sudoers/po/zh_CN.mobin0 -> 63567 bytes
-rw-r--r--plugins/sudoers/po/zh_CN.po4134
-rw-r--r--plugins/sudoers/po/zh_TW.mobin0 -> 72034 bytes
-rw-r--r--plugins/sudoers/po/zh_TW.po4076
-rw-r--r--plugins/sudoers/policy.c1406
-rw-r--r--plugins/sudoers/prompt.c171
-rw-r--r--plugins/sudoers/pwutil.c1224
-rw-r--r--plugins/sudoers/pwutil.h78
-rw-r--r--plugins/sudoers/pwutil_impl.c473
-rw-r--r--plugins/sudoers/redblack.c479
-rw-r--r--plugins/sudoers/redblack.h60
-rw-r--r--plugins/sudoers/regress/check_symbols/check_symbols.c114
-rw-r--r--plugins/sudoers/regress/corpus/seed/ldif/invalid_b64.ldif33
-rw-r--r--plugins/sudoers/regress/corpus/seed/ldif/pr196.ldif6
-rw-r--r--plugins/sudoers/regress/corpus/seed/ldif/sample.ldif295
-rw-r--r--plugins/sudoers/regress/corpus/seed/ldif/valid_b64.ldif44
-rw-r--r--plugins/sudoers/regress/corpus/seed/policy/policy.11
-rw-r--r--plugins/sudoers/regress/corpus/seed/policy/policy.25
-rw-r--r--plugins/sudoers/regress/corpus/seed/policy/policy.311
-rw-r--r--plugins/sudoers/regress/corpus/seed/policy/policy.436
-rw-r--r--plugins/sudoers/regress/corpus/seed/policy/policy.536
-rw-r--r--plugins/sudoers/regress/cvtsudoers/sudoers126
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/sudoers.defs19
-rw-r--r--plugins/sudoers/regress/cvtsudoers/sudoers197
-rw-r--r--plugins/sudoers/regress/cvtsudoers/sudoers297
-rw-r--r--plugins/sudoers/regress/cvtsudoers/sudoers397
-rw-r--r--plugins/sudoers/regress/cvtsudoers/sudoers497
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test1.out.ok14
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test1.sh10
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test10.out.ok1
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test10.sh10
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test11.out.ok7
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test11.sh8
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test12.out.ok8
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test12.sh8
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test13.out.ok7
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test13.sh8
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test14.out.ok7
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test14.sh8
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test15.out.ok1
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test15.sh10
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test16.out.ok1
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test16.sh10
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test17.out.ok1
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test17.sh10
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test18.out.ok1
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test18.sh10
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test19.out.ok11
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test19.sh8
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test2.out.ok10
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test2.sh10
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test20.conf6
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test20.out.ok1
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test20.sh13
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test21.conf8
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test21.out.ok24
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test21.sh14
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test22.out.ok31
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test22.sh73
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test23.out.ok20
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test23.sh9
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test24.out.ok89
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test24.sh9
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test25.out.ok31
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test25.sh53
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test26.err.ok3
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test26.out.ok0
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test26.sh49
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test27.out.ok16
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test27.sh12
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test28.out.ok10
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test28.sh74
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test29.out.ok4
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test29.sh61
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test3.out.ok7
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test3.sh10
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test30.out.ok26
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test30.sh15
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test31.conf9
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test31.out.ok24
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test31.sh14
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test32.err.ok1
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test32.out.ok119
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test32.sh22
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test33.out.ok7
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test33.sh62
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test34.out.ok18
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test34.sh9
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test35.out.ok18
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test35.sh9
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test36.out.ok17
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test36.sh9
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test37.out.ok17
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test37.sh10
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test38.out.ok14
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test38.sh10
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test39.out.ok0
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test39.sh12
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test4.out.ok5
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test4.sh10
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test40.out.ok10
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test40.sh29
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test5.out.ok6
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test5.sh10
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test6.out.ok1
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test6.sh10
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test7.out.ok2
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test7.sh10
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test8.out.ok1
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test8.sh10
-rw-r--r--plugins/sudoers/regress/cvtsudoers/test9.out.ok1
-rwxr-xr-xplugins/sudoers/regress/cvtsudoers/test9.sh10
-rw-r--r--plugins/sudoers/regress/editor/check_editor.c174
-rw-r--r--plugins/sudoers/regress/env_match/check_env_pattern.c96
-rw-r--r--plugins/sudoers/regress/env_match/data22
-rw-r--r--plugins/sudoers/regress/exptilde/check_exptilde.c113
-rw-r--r--plugins/sudoers/regress/fuzz/fuzz_policy.c932
-rw-r--r--plugins/sudoers/regress/fuzz/fuzz_policy.dict56
-rw-r--r--plugins/sudoers/regress/fuzz/fuzz_stubs.c100
-rw-r--r--plugins/sudoers/regress/fuzz/fuzz_sudoers.c419
-rw-r--r--plugins/sudoers/regress/fuzz/fuzz_sudoers.dict221
-rw-r--r--plugins/sudoers/regress/fuzz/fuzz_sudoers.out.ok577
-rw-r--r--plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c151
-rw-r--r--plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.dict14
-rwxr-xr-xplugins/sudoers/regress/harness.in217
-rw-r--r--plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c455
-rw-r--r--plugins/sudoers/regress/parser/check_addr.c152
-rw-r--r--plugins/sudoers/regress/parser/check_addr.in13
-rw-r--r--plugins/sudoers/regress/parser/check_base64.c130
-rw-r--r--plugins/sudoers/regress/parser/check_digest.c140
-rw-r--r--plugins/sudoers/regress/parser/check_digest.out.ok36
-rw-r--r--plugins/sudoers/regress/parser/check_fill.c225
-rw-r--r--plugins/sudoers/regress/parser/check_gentime.c98
-rw-r--r--plugins/sudoers/regress/serialize_list/check_serialize_list.c96
-rw-r--r--plugins/sudoers/regress/starttime/check_starttime.c154
-rw-r--r--plugins/sudoers/regress/sudoers/test1.in12
-rw-r--r--plugins/sudoers/regress/sudoers/test1.json.ok154
-rw-r--r--plugins/sudoers/regress/sudoers/test1.ldif.ok88
-rw-r--r--plugins/sudoers/regress/sudoers/test1.ldif2sudo.ok13
-rw-r--r--plugins/sudoers/regress/sudoers/test1.out.ok6
-rw-r--r--plugins/sudoers/regress/sudoers/test1.toke.ok8
-rw-r--r--plugins/sudoers/regress/sudoers/test10.in1
-rw-r--r--plugins/sudoers/regress/sudoers/test10.json.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test10.ldif.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test10.out.ok2
-rw-r--r--plugins/sudoers/regress/sudoers/test10.toke.ok1
-rw-r--r--plugins/sudoers/regress/sudoers/test11.in1
-rw-r--r--plugins/sudoers/regress/sudoers/test11.json.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test11.ldif.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test11.out.ok1
-rw-r--r--plugins/sudoers/regress/sudoers/test11.toke.ok2
-rw-r--r--plugins/sudoers/regress/sudoers/test12.in1
-rw-r--r--plugins/sudoers/regress/sudoers/test12.json.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test12.ldif.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test12.out.ok1
-rw-r--r--plugins/sudoers/regress/sudoers/test12.toke.ok2
-rw-r--r--plugins/sudoers/regress/sudoers/test13.in1
-rw-r--r--plugins/sudoers/regress/sudoers/test13.json.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test13.ldif.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test13.out.ok1
-rw-r--r--plugins/sudoers/regress/sudoers/test13.toke.ok2
-rw-r--r--plugins/sudoers/regress/sudoers/test14.in6
-rw-r--r--plugins/sudoers/regress/sudoers/test14.json.ok62
-rw-r--r--plugins/sudoers/regress/sudoers/test14.ldif.ok20
-rw-r--r--plugins/sudoers/regress/sudoers/test14.ldif2sudo.ok12
-rw-r--r--plugins/sudoers/regress/sudoers/test14.out.ok7
-rw-r--r--plugins/sudoers/regress/sudoers/test14.toke.ok6
-rw-r--r--plugins/sudoers/regress/sudoers/test15.in2
-rw-r--r--plugins/sudoers/regress/sudoers/test15.json.ok19
-rw-r--r--plugins/sudoers/regress/sudoers/test15.ldif.ok9
-rw-r--r--plugins/sudoers/regress/sudoers/test15.ldif2sudo.ok2
-rw-r--r--plugins/sudoers/regress/sudoers/test15.out.ok3
-rw-r--r--plugins/sudoers/regress/sudoers/test15.toke.ok2
-rw-r--r--plugins/sudoers/regress/sudoers/test16.in3
-rw-r--r--plugins/sudoers/regress/sudoers/test16.json.ok24
-rw-r--r--plugins/sudoers/regress/sudoers/test16.ldif.ok9
-rw-r--r--plugins/sudoers/regress/sudoers/test16.ldif2sudo.ok2
-rw-r--r--plugins/sudoers/regress/sudoers/test16.out.ok5
-rw-r--r--plugins/sudoers/regress/sudoers/test16.toke.ok3
-rw-r--r--plugins/sudoers/regress/sudoers/test17.in13
-rw-r--r--plugins/sudoers/regress/sudoers/test17.json.ok180
-rw-r--r--plugins/sudoers/regress/sudoers/test17.ldif.ok104
-rw-r--r--plugins/sudoers/regress/sudoers/test17.ldif2sudo.ok29
-rw-r--r--plugins/sudoers/regress/sudoers/test17.out.ok13
-rw-r--r--plugins/sudoers/regress/sudoers/test17.toke.ok11
-rw-r--r--plugins/sudoers/regress/sudoers/test18.in8
-rw-r--r--plugins/sudoers/regress/sudoers/test18.json.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test18.ldif.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test18.out.ok3
-rw-r--r--plugins/sudoers/regress/sudoers/test18.toke.ok10
-rw-r--r--plugins/sudoers/regress/sudoers/test19.in12
-rw-r--r--plugins/sudoers/regress/sudoers/test19.json.ok187
-rw-r--r--plugins/sudoers/regress/sudoers/test19.ldif.ok103
-rw-r--r--plugins/sudoers/regress/sudoers/test19.ldif2sudo.ok30
-rw-r--r--plugins/sudoers/regress/sudoers/test19.out.ok12
-rw-r--r--plugins/sudoers/regress/sudoers/test19.toke.ok12
-rw-r--r--plugins/sudoers/regress/sudoers/test2.in63
-rw-r--r--plugins/sudoers/regress/sudoers/test2.json.ok420
-rw-r--r--plugins/sudoers/regress/sudoers/test2.ldif.ok168
-rw-r--r--plugins/sudoers/regress/sudoers/test2.ldif2sudo.ok41
-rw-r--r--plugins/sudoers/regress/sudoers/test2.out.ok43
-rw-r--r--plugins/sudoers/regress/sudoers/test2.toke.ok63
-rw-r--r--plugins/sudoers/regress/sudoers/test20.in26
-rw-r--r--plugins/sudoers/regress/sudoers/test20.json.ok114
-rw-r--r--plugins/sudoers/regress/sudoers/test20.ldif.ok28
-rw-r--r--plugins/sudoers/regress/sudoers/test20.ldif2sudo.ok22
-rw-r--r--plugins/sudoers/regress/sudoers/test20.out.ok24
-rw-r--r--plugins/sudoers/regress/sudoers/test20.toke.ok26
-rw-r--r--plugins/sudoers/regress/sudoers/test21.in36
-rw-r--r--plugins/sudoers/regress/sudoers/test21.json.ok169
-rw-r--r--plugins/sudoers/regress/sudoers/test21.ldif.ok39
-rw-r--r--plugins/sudoers/regress/sudoers/test21.ldif2sudo.ok33
-rw-r--r--plugins/sudoers/regress/sudoers/test21.out.ok35
-rw-r--r--plugins/sudoers/regress/sudoers/test21.toke.ok36
-rw-r--r--plugins/sudoers/regress/sudoers/test22.in6
-rw-r--r--plugins/sudoers/regress/sudoers/test22.json.ok88
-rw-r--r--plugins/sudoers/regress/sudoers/test22.ldif.ok40
-rw-r--r--plugins/sudoers/regress/sudoers/test22.ldif2sudo.ok11
-rw-r--r--plugins/sudoers/regress/sudoers/test22.out.ok6
-rw-r--r--plugins/sudoers/regress/sudoers/test22.toke.ok6
-rw-r--r--plugins/sudoers/regress/sudoers/test23.in11
-rw-r--r--plugins/sudoers/regress/sudoers/test23.json.ok102
-rw-r--r--plugins/sudoers/regress/sudoers/test23.ldif.ok14
-rw-r--r--plugins/sudoers/regress/sudoers/test23.ldif2sudo.ok8
-rw-r--r--plugins/sudoers/regress/sudoers/test23.out.ok10
-rw-r--r--plugins/sudoers/regress/sudoers/test23.toke.ok11
-rw-r--r--plugins/sudoers/regress/sudoers/test24.in6
-rw-r--r--plugins/sudoers/regress/sudoers/test24.json.ok61
-rw-r--r--plugins/sudoers/regress/sudoers/test24.ldif.ok39
-rw-r--r--plugins/sudoers/regress/sudoers/test24.ldif2sudo.ok8
-rw-r--r--plugins/sudoers/regress/sudoers/test24.out.ok7
-rw-r--r--plugins/sudoers/regress/sudoers/test24.toke.ok6
-rw-r--r--plugins/sudoers/regress/sudoers/test25.in3
-rw-r--r--plugins/sudoers/regress/sudoers/test25.json.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test25.ldif.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test25.out.ok1
-rw-r--r--plugins/sudoers/regress/sudoers/test25.toke.ok3
-rw-r--r--plugins/sudoers/regress/sudoers/test26.in128
-rw-r--r--plugins/sudoers/regress/sudoers/test26.json.ok626
-rw-r--r--plugins/sudoers/regress/sudoers/test26.ldif.ok134
-rw-r--r--plugins/sudoers/regress/sudoers/test26.ldif2sudo.ok128
-rw-r--r--plugins/sudoers/regress/sudoers/test26.out.ok122
-rw-r--r--plugins/sudoers/regress/sudoers/test26.toke.ok128
-rw-r--r--plugins/sudoers/regress/sudoers/test27.in13
-rw-r--r--plugins/sudoers/regress/sudoers/test27.json.ok125
-rw-r--r--plugins/sudoers/regress/sudoers/test27.ldif.ok60
-rw-r--r--plugins/sudoers/regress/sudoers/test27.ldif2sudo.ok16
-rw-r--r--plugins/sudoers/regress/sudoers/test27.out.ok9
-rw-r--r--plugins/sudoers/regress/sudoers/test27.toke.ok13
-rw-r--r--plugins/sudoers/regress/sudoers/test28.in36
-rw-r--r--plugins/sudoers/regress/sudoers/test28.json.ok199
-rw-r--r--plugins/sudoers/regress/sudoers/test28.ldif.ok117
-rw-r--r--plugins/sudoers/regress/sudoers/test28.ldif2sudo.ok12
-rw-r--r--plugins/sudoers/regress/sudoers/test28.out.ok14
-rw-r--r--plugins/sudoers/regress/sudoers/test28.toke.ok32
-rw-r--r--plugins/sudoers/regress/sudoers/test29.in11
-rw-r--r--plugins/sudoers/regress/sudoers/test29.json.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test29.ldif.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test29.out.ok1
-rw-r--r--plugins/sudoers/regress/sudoers/test29.toke.ok11
-rw-r--r--plugins/sudoers/regress/sudoers/test3.in6
-rw-r--r--plugins/sudoers/regress/sudoers/test3.json.ok45
-rw-r--r--plugins/sudoers/regress/sudoers/test3.ldif.ok12
-rw-r--r--plugins/sudoers/regress/sudoers/test3.ldif2sudo.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test3.out.ok8
-rw-r--r--plugins/sudoers/regress/sudoers/test3.toke.ok6
-rw-r--r--plugins/sudoers/regress/sudoers/test30.in10
-rw-r--r--plugins/sudoers/regress/sudoers/test30.json.ok79
-rw-r--r--plugins/sudoers/regress/sudoers/test30.ldif.ok38
-rw-r--r--plugins/sudoers/regress/sudoers/test30.ldif2sudo.ok11
-rw-r--r--plugins/sudoers/regress/sudoers/test30.out.ok6
-rw-r--r--plugins/sudoers/regress/sudoers/test30.sudo.ok7
-rw-r--r--plugins/sudoers/regress/sudoers/test30.toke.ok10
-rw-r--r--plugins/sudoers/regress/sudoers/test4.in7
-rw-r--r--plugins/sudoers/regress/sudoers/test4.json.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test4.ldif.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test4.out.ok3
-rw-r--r--plugins/sudoers/regress/sudoers/test4.toke.ok5
-rw-r--r--plugins/sudoers/regress/sudoers/test5.in3
-rw-r--r--plugins/sudoers/regress/sudoers/test5.json.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test5.ldif.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test5.out.ok1
-rw-r--r--plugins/sudoers/regress/sudoers/test5.toke.ok3
-rw-r--r--plugins/sudoers/regress/sudoers/test6.in15
-rw-r--r--plugins/sudoers/regress/sudoers/test6.json.ok158
-rw-r--r--plugins/sudoers/regress/sudoers/test6.ldif.ok70
-rw-r--r--plugins/sudoers/regress/sudoers/test6.ldif2sudo.ok5
-rw-r--r--plugins/sudoers/regress/sudoers/test6.out.ok13
-rw-r--r--plugins/sudoers/regress/sudoers/test6.toke.ok15
-rw-r--r--plugins/sudoers/regress/sudoers/test7.in7
-rw-r--r--plugins/sudoers/regress/sudoers/test7.json.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test7.ldif.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test7.out.ok1
-rw-r--r--plugins/sudoers/regress/sudoers/test7.toke.ok7
-rw-r--r--plugins/sudoers/regress/sudoers/test8.in8
-rw-r--r--plugins/sudoers/regress/sudoers/test8.json.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test8.ldif.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test8.out.ok4
-rw-r--r--plugins/sudoers/regress/sudoers/test8.toke.ok7
-rw-r--r--plugins/sudoers/regress/sudoers/test9.in0
-rw-r--r--plugins/sudoers/regress/sudoers/test9.json.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test9.ldif.ok0
-rw-r--r--plugins/sudoers/regress/sudoers/test9.out.ok2
-rw-r--r--plugins/sudoers/regress/sudoers/test9.toke.ok0
-rw-r--r--plugins/sudoers/regress/testsudoers/group17
-rw-r--r--plugins/sudoers/regress/testsudoers/passwd7
-rw-r--r--plugins/sudoers/regress/testsudoers/test1.out.ok11
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test1.sh15
-rw-r--r--plugins/sudoers/regress/testsudoers/test10.out.ok59
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test10.sh46
-rw-r--r--plugins/sudoers/regress/testsudoers/test11.out.ok25
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test11.sh25
-rw-r--r--plugins/sudoers/regress/testsudoers/test12.out.ok18
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test12.sh19
-rw-r--r--plugins/sudoers/regress/testsudoers/test13.out.ok22
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test13.sh22
-rw-r--r--plugins/sudoers/regress/testsudoers/test14.out.ok18
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test14.sh25
-rw-r--r--plugins/sudoers/regress/testsudoers/test15.out.ok19
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test15.sh24
-rw-r--r--plugins/sudoers/regress/testsudoers/test16.out.ok12
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test16.sh41
-rw-r--r--plugins/sudoers/regress/testsudoers/test17.out.ok12
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test17.sh51
-rw-r--r--plugins/sudoers/regress/testsudoers/test18.out.ok72
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test18.sh40
-rw-r--r--plugins/sudoers/regress/testsudoers/test19.out.ok24
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test19.sh20
-rw-r--r--plugins/sudoers/regress/testsudoers/test2.inc1
-rw-r--r--plugins/sudoers/regress/testsudoers/test2.out.ok29
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test2.sh25
-rw-r--r--plugins/sudoers/regress/testsudoers/test20.out.ok12
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test20.sh18
-rw-r--r--plugins/sudoers/regress/testsudoers/test21.out.ok12
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test21.sh20
-rw-r--r--plugins/sudoers/regress/testsudoers/test22.out.ok11
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test22.sh18
-rw-r--r--plugins/sudoers/regress/testsudoers/test23.out.ok11
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test23.sh17
-rw-r--r--plugins/sudoers/regress/testsudoers/test24.out.ok48
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test24.sh42
-rw-r--r--plugins/sudoers/regress/testsudoers/test25.out.ok59
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test25.sh48
-rw-r--r--plugins/sudoers/regress/testsudoers/test26.out.ok57
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test26.sh50
-rw-r--r--plugins/sudoers/regress/testsudoers/test27.out.ok14
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test27.sh22
-rw-r--r--plugins/sudoers/regress/testsudoers/test28.out.ok125
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test28.sh99
-rw-r--r--plugins/sudoers/regress/testsudoers/test29.out.ok133
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test29.sh71
-rw-r--r--plugins/sudoers/regress/testsudoers/test3.out.ok59
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test3.sh48
-rw-r--r--plugins/sudoers/regress/testsudoers/test30.out.ok133
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test30.sh71
-rw-r--r--plugins/sudoers/regress/testsudoers/test31.out.ok131
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test31.sh71
-rw-r--r--plugins/sudoers/regress/testsudoers/test4.out.ok7
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test4.sh13
-rw-r--r--plugins/sudoers/regress/testsudoers/test5.out.ok14
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test5.sh31
-rw-r--r--plugins/sudoers/regress/testsudoers/test6.out.ok12
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test6.sh13
-rw-r--r--plugins/sudoers/regress/testsudoers/test7.out.ok12
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test7.sh13
-rw-r--r--plugins/sudoers/regress/testsudoers/test8.out.ok29
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test8.sh24
-rw-r--r--plugins/sudoers/regress/testsudoers/test9.out.ok12
-rwxr-xr-xplugins/sudoers/regress/testsudoers/test9.sh15
-rw-r--r--plugins/sudoers/regress/unescape/check_unesc.c203
-rw-r--r--plugins/sudoers/regress/visudo/test1.out.ok1
-rwxr-xr-xplugins/sudoers/regress/visudo/test1.sh14
-rw-r--r--plugins/sudoers/regress/visudo/test10.out.ok1
-rwxr-xr-xplugins/sudoers/regress/visudo/test10.sh13
-rw-r--r--plugins/sudoers/regress/visudo/test2.err.ok1
-rw-r--r--plugins/sudoers/regress/visudo/test2.out.ok0
-rwxr-xr-xplugins/sudoers/regress/visudo/test2.sh17
-rw-r--r--plugins/sudoers/regress/visudo/test3.err.ok2
-rw-r--r--plugins/sudoers/regress/visudo/test3.out.ok1
-rwxr-xr-xplugins/sudoers/regress/visudo/test3.sh37
-rw-r--r--plugins/sudoers/regress/visudo/test4.out.ok1
-rwxr-xr-xplugins/sudoers/regress/visudo/test4.sh16
-rw-r--r--plugins/sudoers/regress/visudo/test5.out.ok1
-rwxr-xr-xplugins/sudoers/regress/visudo/test5.sh10
-rw-r--r--plugins/sudoers/regress/visudo/test6.out.ok1
-rwxr-xr-xplugins/sudoers/regress/visudo/test6.sh27
-rw-r--r--plugins/sudoers/regress/visudo/test7.out.ok1
-rwxr-xr-xplugins/sudoers/regress/visudo/test7.sh31
-rw-r--r--plugins/sudoers/regress/visudo/test8.err.ok1
-rw-r--r--plugins/sudoers/regress/visudo/test8.out.ok1
-rwxr-xr-xplugins/sudoers/regress/visudo/test8.sh32
-rw-r--r--plugins/sudoers/regress/visudo/test9.out.ok1
-rwxr-xr-xplugins/sudoers/regress/visudo/test9.sh14
-rw-r--r--plugins/sudoers/resolve_cmnd.c59
-rw-r--r--plugins/sudoers/serialize_list.c82
-rw-r--r--plugins/sudoers/set_perms.c1643
-rw-r--r--plugins/sudoers/sethost.c91
-rw-r--r--plugins/sudoers/solaris_audit.c141
-rw-r--r--plugins/sudoers/solaris_audit.h26
-rw-r--r--plugins/sudoers/sssd.c817
-rw-r--r--plugins/sudoers/starttime.c342
-rw-r--r--plugins/sudoers/strlcpy_unesc.c55
-rw-r--r--plugins/sudoers/strlist.c92
-rw-r--r--plugins/sudoers/strlist.h40
-rw-r--r--plugins/sudoers/strvec_join.c74
-rw-r--r--plugins/sudoers/stubs.c110
-rw-r--r--plugins/sudoers/sudo_ldap.h109
-rw-r--r--plugins/sudoers/sudo_ldap_conf.h100
-rw-r--r--plugins/sudoers/sudo_nss.c264
-rw-r--r--plugins/sudoers/sudo_nss.h50
-rw-r--r--plugins/sudoers/sudo_printf.c90
-rw-r--r--plugins/sudoers/sudoers.c1556
-rw-r--r--plugins/sudoers/sudoers.exp7
-rw-r--r--plugins/sudoers/sudoers.h518
-rw-r--r--plugins/sudoers/sudoers.in122
-rw-r--r--plugins/sudoers/sudoers_cb.c508
-rw-r--r--plugins/sudoers/sudoers_ctx_free.c94
-rw-r--r--plugins/sudoers/sudoers_debug.c135
-rw-r--r--plugins/sudoers/sudoers_debug.h52
-rw-r--r--plugins/sudoers/sudoers_hooks.c155
-rw-r--r--plugins/sudoers/sudoers_version.h81
-rw-r--r--plugins/sudoers/sudoreplay.c1721
-rw-r--r--plugins/sudoers/testsudoers.c782
-rw-r--r--plugins/sudoers/testsudoers_pwutil.c10
-rw-r--r--plugins/sudoers/testsudoers_pwutil.h38
-rw-r--r--plugins/sudoers/timeout.c109
-rw-r--r--plugins/sudoers/timestamp.c1276
-rw-r--r--plugins/sudoers/timestamp.h104
-rw-r--r--plugins/sudoers/timestr.c50
-rw-r--r--plugins/sudoers/toke.c6373
-rw-r--r--plugins/sudoers/toke.h59
-rw-r--r--plugins/sudoers/toke.l1593
-rw-r--r--plugins/sudoers/toke_util.c252
-rw-r--r--plugins/sudoers/tsdump.c311
-rw-r--r--plugins/sudoers/tsgetgrpw.c422
-rw-r--r--plugins/sudoers/tsgetgrpw.h52
-rw-r--r--plugins/sudoers/unesc_str.c46
-rw-r--r--plugins/sudoers/visudo.c1352
-rw-r--r--plugins/sudoers/visudo_cb.c40
-rw-r--r--plugins/system_group/Makefile.in226
-rw-r--r--plugins/system_group/system_group.c144
-rw-r--r--plugins/system_group/system_group.exp1
-rw-r--r--po/README14
-rw-r--r--po/ast.mobin0 -> 19623 bytes
-rw-r--r--po/ast.po928
-rw-r--r--po/ca.mobin0 -> 22121 bytes
-rw-r--r--po/ca.po1088
-rw-r--r--po/cs.mobin0 -> 25377 bytes
-rw-r--r--po/cs.po1295
-rw-r--r--po/da.mobin0 -> 18722 bytes
-rw-r--r--po/da.po946
-rw-r--r--po/de.mobin0 -> 27108 bytes
-rw-r--r--po/de.po1212
-rw-r--r--po/eo.mobin0 -> 24779 bytes
-rw-r--r--po/eo.po1203
-rw-r--r--po/es.mobin0 -> 19418 bytes
-rw-r--r--po/es.po1002
-rw-r--r--po/eu.mobin0 -> 6771 bytes
-rw-r--r--po/eu.po742
-rw-r--r--po/fa.mobin0 -> 14867 bytes
-rw-r--r--po/fa.po1085
-rw-r--r--po/fi.mobin0 -> 23168 bytes
-rw-r--r--po/fi.po1196
-rw-r--r--po/fr.mobin0 -> 26938 bytes
-rw-r--r--po/fr.po1293
-rw-r--r--po/fur.mobin0 -> 25313 bytes
-rw-r--r--po/fur.po1212
-rw-r--r--po/gl.mobin0 -> 17612 bytes
-rw-r--r--po/gl.po898
-rw-r--r--po/hr.mobin0 -> 25661 bytes
-rw-r--r--po/hr.po1319
-rw-r--r--po/hu.mobin0 -> 20126 bytes
-rw-r--r--po/hu.po883
-rw-r--r--po/id.mobin0 -> 25107 bytes
-rw-r--r--po/id.po1201
-rw-r--r--po/it.mobin0 -> 22085 bytes
-rw-r--r--po/it.po1038
-rw-r--r--po/ja.mobin0 -> 29844 bytes
-rw-r--r--po/ja.po1313
-rw-r--r--po/ka.mobin0 -> 40144 bytes
-rw-r--r--po/ka.po1180
-rw-r--r--po/ko.mobin0 -> 27580 bytes
-rw-r--r--po/ko.po1255
-rw-r--r--po/nb.mobin0 -> 20434 bytes
-rw-r--r--po/nb.po1035
-rw-r--r--po/nl.mobin0 -> 17715 bytes
-rw-r--r--po/nl.po856
-rw-r--r--po/nn.mobin0 -> 3017 bytes
-rw-r--r--po/nn.po934
-rw-r--r--po/pl.mobin0 -> 25972 bytes
-rw-r--r--po/pl.po1200
-rw-r--r--po/pt.mobin0 -> 22166 bytes
-rw-r--r--po/pt.po1094
-rw-r--r--po/pt_BR.mobin0 -> 22896 bytes
-rw-r--r--po/pt_BR.po1147
-rw-r--r--po/ro.mobin0 -> 26284 bytes
-rw-r--r--po/ro.po1362
-rw-r--r--po/ru.mobin0 -> 33957 bytes
-rw-r--r--po/ru.po1307
-rw-r--r--po/sk.mobin0 -> 15495 bytes
-rw-r--r--po/sk.po858
-rw-r--r--po/sl.mobin0 -> 16463 bytes
-rw-r--r--po/sl.po810
-rw-r--r--po/sq.mobin0 -> 3497 bytes
-rw-r--r--po/sq.po1179
-rw-r--r--po/sr.mobin0 -> 33163 bytes
-rw-r--r--po/sr.po1292
-rw-r--r--po/sudo.pot1206
-rw-r--r--po/sv.mobin0 -> 24354 bytes
-rw-r--r--po/sv.po1247
-rw-r--r--po/tr.mobin0 -> 21647 bytes
-rw-r--r--po/tr.po1143
-rw-r--r--po/uk.mobin0 -> 34840 bytes
-rw-r--r--po/uk.po1247
-rw-r--r--po/vi.mobin0 -> 28513 bytes
-rw-r--r--po/vi.po1307
-rw-r--r--po/zh_CN.mobin0 -> 23005 bytes
-rw-r--r--po/zh_CN.po1310
-rw-r--r--po/zh_TW.mobin0 -> 23670 bytes
-rw-r--r--po/zh_TW.po1218
-rwxr-xr-xscripts/config.guess1774
-rwxr-xr-xscripts/config.sub1907
-rwxr-xr-xscripts/generate_test_coverage.sh30
-rwxr-xr-xscripts/install-sh239
-rwxr-xr-xscripts/log2cl.pl115
-rw-r--r--scripts/ltmain.sh11453
-rwxr-xr-xscripts/mkdep.pl328
-rwxr-xr-xscripts/mkinstalldirs84
-rwxr-xr-xscripts/mkpkg591
-rwxr-xr-xscripts/pp9142
-rwxr-xr-xscripts/unanon50
-rw-r--r--src/Makefile.in1099
-rw-r--r--src/apparmor.c118
-rw-r--r--src/conversation.c239
-rw-r--r--src/copy_file.c169
-rw-r--r--src/edit_open.c538
-rw-r--r--src/env_hooks.c315
-rw-r--r--src/exec.c586
-rw-r--r--src/exec_common.c136
-rw-r--r--src/exec_intercept.c1109
-rw-r--r--src/exec_intercept.h55
-rw-r--r--src/exec_iolog.c612
-rw-r--r--src/exec_monitor.c727
-rw-r--r--src/exec_nopty.c812
-rw-r--r--src/exec_preload.c419
-rw-r--r--src/exec_ptrace.c2135
-rw-r--r--src/exec_ptrace.h532
-rw-r--r--src/exec_pty.c1452
-rw-r--r--src/get_pty.c189
-rw-r--r--src/hooks.c245
-rw-r--r--src/intercept.exp.in7
-rw-r--r--src/intercept.pb-c.c842
-rw-r--r--src/intercept.proto71
-rw-r--r--src/limits.c714
-rw-r--r--src/load_plugins.c488
-rw-r--r--src/net_ifs.c876
-rw-r--r--src/openbsd.c36
-rw-r--r--src/parse_args.c881
-rw-r--r--src/preload.c77
-rw-r--r--src/preserve_fds.c216
-rw-r--r--src/regress/intercept/test_ptrace.c235
-rw-r--r--src/regress/net_ifs/check_net_ifs.c87
-rw-r--r--src/regress/noexec/check_noexec.c232
-rw-r--r--src/regress/ttyname/check_ttyname.c122
-rw-r--r--src/selinux.c515
-rw-r--r--src/sesh.c489
-rw-r--r--src/signal.c196
-rw-r--r--src/solaris.c117
-rw-r--r--src/sudo.c2255
-rw-r--r--src/sudo.h352
-rw-r--r--src/sudo_edit.c796
-rw-r--r--src/sudo_edit.h55
-rw-r--r--src/sudo_exec.h236
-rw-r--r--src/sudo_intercept.c595
-rw-r--r--src/sudo_intercept_common.c509
-rw-r--r--src/sudo_noexec.c251
-rw-r--r--src/sudo_plugin_int.h133
-rw-r--r--src/sudo_usage.h.in78
-rw-r--r--src/suspend_parent.c170
-rw-r--r--src/tgetpass.c466
-rw-r--r--src/ttyname.c378
-rw-r--r--src/utmp.c385
1339 files changed, 613485 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..cf97cea
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,78828 @@
+2023-12-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_15p5 for changeset 4418cfdc5b2a
+ [c1df7aef0fa8] [tip] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.15p5
+ [4418cfdc5b2a] [SUDO_1_9_15p5] <1.9>
+
+2023-12-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/pwutil_impl.c:
+ Properly handle sysconf(_SC_LOGIN_NAME_MAX) returning -1 on failure.
+
+ The cast to size_t needs to be outside the MAX() macro or the -1
+ will get cast to unsigned.
+ [343b22c1fc59] <1.9>
+
+2023-12-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, plugins/sudoers/timestamp.c:
+ Automatically migrate lecture file path from name-based to uid-
+ based.
+
+ GitHub issue #342.
+ [cfa82cf5ac29] <1.9>
+
+2023-12-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/ldap_conf.c:
+ Disable netgroup_query when netgroup_base is not set.
+
+ The logic was inverted when support for netgroup_query was added.
+ This supercedes PR #341.
+ [a575b106220e] <1.9>
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ In the NOEXEC example make it clear that "shanty" is a host. Bug
+ #1064
+ [18e3b6a981d4] <1.9>
+
+2023-12-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/defaults.c:
+ Fix printing of warning when a Defaults setting is missing a value.
+
+ This is a bug in parse_default_entry() introduced in sudo 1.8.19
+ when support for using the default syslog facility was added at the
+ wrong place in a switch().
+ [f9de87a2f501] <1.9>
+
+2023-12-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/defaults.c:
+ Fix evaluation of a tuple used in "true" boolean context.
+
+ Previously, a tuple in boolean context was always treated as a
+ negated entry, which doesn't match the documentation. We assume that
+ there are at least two tuple entries where the first maps to boolean
+ false and the second maps to boolean true.
+ [39a6e634c9d6] <1.9>
+
+ * .hgtags:
+ Added tag SUDO_1_9_15p4 for changeset cc9d22d261de
+ [382e15393814] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.15p4
+ [cc9d22d261de] [SUDO_1_9_15p4] <1.9>
+
+ * plugins/sudoers/lookup.c:
+ sudoers_lookup_pseudo: init match to UNSPEC for
+ sudo_nss_can_continue().
+
+ Otherwise, processing will stop after the first sudoers nsswitch
+ service specification where [SUCCESS=return] is present.
+ [053be548771c] <1.9>
+
+2023-12-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_15p3 for changeset 20d368229c6a
+ [e01ee9945d11] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.15p3
+ [20d368229c6a] [SUDO_1_9_15p3] <1.9>
+
+2023-12-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/policy.c:
+ Pass back Solaris privs as "runas_privs" and "runas_limitprivs".
+
+ The "runas_" prefix got inadvertantly removed in the big
+ sudoers_context refactor.
+ [25f183bdd61e] <1.9>
+
+2023-12-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_util.h, lib/util/term.c, lib/util/ttysize.c,
+ lib/util/util.exp.in, src/sudo.h, src/ttyname.c:
+ sudo_term_is_raw: only try to lock the fd if it is a tty
+
+ This moves sudo_isatty() to libsudo_util so sudo_term_is_raw() can
+ use it. Fixes GitHub issue #335
+ [5e7dd2580c9b] <1.9>
+
+2023-12-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoreplay.c:
+ setup_terminal: fix an editing error introduced in 1.9.15.
+ [690c82d4ebd4] <1.9>
+
+2023-12-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sethost.c:
+ Fall back to "localhost" if gethostname() fails.
+
+ GitHub issue #332
+ [c6993fd61aac] <1.9>
+
+ * plugins/sudoers/match_command.c:
+ command_matches_glob: fix comparison of canonicalized parent
+ directories
+
+ Bug #1062
+ [78b789de1df8] <1.9>
+
+2023-11-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sudo.c:
+ Always disable core dumps when sudo sends itself a fatal signal.
+
+ When a command exits due to a fatal signal, sudo will re-send that
+ signal to itself so the shell does not ignore keyboard-generated
+ signals. However, now that sudo disables core dumps by default for
+ the command, we cannot rely on WCOREDUMP() telling us whether or not
+ the signal will lead to a core dump. It is safest to always disable
+ core dumps before sending the signal to ourself.
+ [4ce4bedf84fe] <1.9>
+
+ * .hgtags:
+ Added tag SUDO_1_9_15p2 for changeset 4d03c1608a23
+ [b46c7b3c67b4] <1.9>
+
+2023-11-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, configure, configure.ac, lib/util/term.c:
+ Merge sudo 1.9.15p2 from tip.
+ [4d03c1608a23] [SUDO_1_9_15p2] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.15p2
+ [7a5afe66a935]
+
+ * scripts/pp:
+ Update PolyPkg from upstream.
+ [fef8f49977c3]
+
+ * lib/util/term.c:
+ sudo_term_restore: don't check c_cflag on systems with TCSASOFT.
+
+ If TCSASOFT is present, tcsetattr() will ignore c_cflag. Fixes a bug
+ where sudo_term_restore() would refuse to change the terminal
+ settings back if the PARENB control flag was set. GitHub issue #326.
+ [bcd3c9f5736a]
+
+ * scripts/mkpkg:
+ Quote $osversion since it may include whitespace.
+ [fb4aac7003c6]
+
+2023-11-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.h:
+ Use C99 designated struct initializers.
+
+ This is less error-prone and would have avoided GitHub issue #325.
+ [f7fad7f54d1b]
+
+ * .hgtags:
+ Added tag SUDO_1_9_15p1 for changeset d23f72517e07
+ [f67d129d3e36] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Merge sudo 1.9.15p1 from tip.
+ [d23f72517e07] [SUDO_1_9_15p1] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.15p1
+ [9aae361b70ef]
+
+ * plugins/sudoers/sudoers.h:
+ Correct the order of the strings in SUDOERS_CONTEXT_INITIALIZER.
+
+ Fixes GitHub issue #325, a bug introduced in sudo 1.9.15.
+ [0266ed6c95f9]
+
+2023-11-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ In the sudo 1.9.14p3 section, "Python python" should be "Python
+ plugin".
+ [dee39187deda]
+
+ * .hgtags:
+ Added tag SUDO_1_9_15 for changeset 277833c12efb
+ [3517bf78fcf5] <1.9>
+
+ * MANIFEST, NEWS, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, include/sudo_util.h, lib/util/hexchar.c,
+ lib/util/regress/hexchar/hexchar_test.c, lib/util/term.c,
+ logsrvd/iolog_writer.c, logsrvd/tls_init.c,
+ plugins/python/pyhelpers.c, plugins/python/python_convmessage.c,
+ plugins/python/python_loghandler.c,
+ plugins/python/python_plugin_common.c,
+ plugins/python/regress/testhelpers.c,
+ plugins/python/sudo_python_module.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/log_client.c, plugins/sudoers/logging.c,
+ plugins/sudoers/lookup.c, plugins/sudoers/match_command.c,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/cvtsudoers/test31.sh,
+ plugins/sudoers/regress/cvtsudoers/test32.sh,
+ plugins/sudoers/regress/cvtsudoers/test35.sh,
+ plugins/sudoers/regress/cvtsudoers/test36.sh,
+ plugins/sudoers/regress/cvtsudoers/test39.sh,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/testsudoers/test20.sh,
+ plugins/sudoers/regress/testsudoers/test21.sh,
+ plugins/sudoers/regress/testsudoers/test22.sh,
+ plugins/sudoers/regress/testsudoers/test23.sh,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ src/exec_monitor.c, src/exec_nopty.c, src/exec_ptrace.c,
+ src/exec_pty.c:
+ Merge sudo 1.9.15 from tip.
+ [277833c12efb] [SUDO_1_9_15] <1.9>
+
+ * NEWS:
+ Sudo now logs the submitenv in the JSON logs.
+ [c1a5e609352f]
+
+ * docs/sudo.conf.man.in, docs/sudo.conf.mdoc.in, docs/sudoers.man.in,
+ docs/sudoers.mdoc.in:
+ Document special cases for AIX-style shared libraries.
+
+ The shared object is a member of an archive file that is specified
+ in parentheses.
+ [bb9a50249072]
+
+2023-11-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudo.conf.man.in, docs/sudo.conf.mdoc.in:
+ Add sudoers plugin Debug example and x-ref sudoers man page for
+ details.
+ [ef23f00ac8ad]
+
+ * docs/sudo.conf.man.in, docs/sudo.conf.mdoc.in:
+ The HP-UX getgrouplist() code has been disabled due to bugs.
+ [0bc060c69389]
+
+2023-11-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/sudo_conf.c:
+ sudo_conf_debug_files: special handling of DSO members for AIX
+
+ When matching debug files for AIX-style DSOs like
+ sudoers.a(sudoers.so) we want to match on the full name, the name
+ without the member and on the member itself. This makes it possible
+ to use the existing examples in the sudo.conf fiile on AIX.
+ [2ec138dbc507]
+
+ * plugins/sudoers/pwutil.c:
+ sudo_set_grlist and sudo_set_gidlist: set auth registry based on
+ username
+
+ Previously we used the global registry but since we have the user's
+ passwd info we should use that when storing the group and gid lists.
+ [71b6647d4cb0]
+
+2023-11-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/parse_ldif.c:
+ role_to_sudoers: only try to reuse a privilege if one is present
+ [91207af2554c]
+
+ * plugins/sudoers/defaults.c:
+ store_plugin: avoid potential NULL deref in boolean context
+
+ Coverity CID 330466
+ [5c7ebbaf83c4]
+
+ * plugins/sudoers/sudoreplay.c, src/conversation.c:
+ Avoid passing sudo_term_is_raw() -1 for the fd.
+
+ Coverity CID 330472 Coverity CID 330468
+ [b28a472152ab]
+
+ * logsrvd/sendlog.c:
+ fmt_info_messages: bump info_msgs_size for submitenv
+ [e36bfd74abb9]
+
+ * NEWS:
+ Better log message when rejecting a setid command in intercept mode.
+ [06d161998e22]
+
+ * plugins/sudoers/logging.c, plugins/sudoers/lookup.c,
+ plugins/sudoers/match_command.c, plugins/sudoers/parse.h,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Move the check for running setid commands in intercept mode to
+ later.
+
+ Checking for setid commands in intercept mode after command matching
+ allows us to log a proper error message. Previously, we simply
+ ignored setid commands when matching and the only indication of why
+ was in the debug logs.
+ [b07b8fcff911]
+
+ * plugins/sudoers/timestamp.c:
+ timestamp_open: add some debugging
+ [dc7070cbadd9]
+
+2023-10-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/sia.c:
+ sudo_sia_begin_session: add missing struct sudoers_context * arg.
+ [4caf619af53b]
+
+ * plugins/sudoers/auth/kerb5.c:
+ verify_krb_v5_tgt: auth name must be const to match struct
+ sudo_auth.
+ [e4d6a0b15003]
+
+ * .circleci/config.yml:
+ Disable PAM before enabling Kerberos V.
+ [55523956e9ff]
+
+ * .circleci/config.yml, docker/debian/latest/Dockerfile,
+ docker/debian/testing/Dockerfile, docker/fedora/latest/Dockerfile,
+ docker/fedora/rawhide/Dockerfile, docker/ubuntu/devel/Dockerfile,
+ docker/ubuntu/latest/Dockerfile, docker/ubuntu/rolling/Dockerfile:
+ Add Kerberos V build and test to CI.
+ [7cf8ab128064]
+
+2023-10-31 Renato Botelho <garga@FreeBSD.org>
+
+ * plugins/sudoers/auth/kerb5.c:
+ Add missing sudoers_context to verify_krb_v5_tgt()
+
+ Commit 244017495421 added ctx variable to log_warningx() call but
+ that variable was not declared in that context, breaking the build.
+ [7b89c1b61e19]
+
+2023-10-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po:
+ Updated translations from translationproject.org
+ [2a5a4f1350ee]
+
+2023-10-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd.c:
+ Set the open file descriptor limit to the maximum allowed value.
+
+ Each connection can require up to 9 descriptors.
+ [72b6593b631d]
+
+2023-10-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Mention new Indonesian translation and sudo_logsrvd fd limit change.
+ [753002967fc0]
+
+ * plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/ro.mo, plugins/sudoers/po/ro.po,
+ plugins/sudoers/po/ru.mo, plugins/sudoers/po/ru.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/zh_TW.mo, plugins/sudoers/po/zh_TW.po, po/hr.mo,
+ po/hr.po, po/ja.mo, po/ja.po, po/sr.mo, po/sr.po, po/zh_CN.mo,
+ po/zh_CN.po:
+ Updated translations from translationproject.org
+ [619098603afe]
+
+ * docs/CONTRIBUTORS.md:
+ Add Andika Triwidada
+ [7e6293a4a00a]
+
+ * MANIFEST, po/id.mo, po/id.po:
+ New Indonesian translation from translationproject.org
+ [568e33cb694c]
+
+2023-10-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Mention GitHub issue #318
+ [4b4c1d8da478]
+
+ * plugins/sudoers/env.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Avoid a double-free in fuzz_policy caused by the early
+ env_init(NULL).
+
+ This adds an env_free() function to explicitly free both the old and
+ new copies of the environment. It is really only needed by
+ fuzz_policy, which calls the policy module multiple times.
+ [9cb4400fe76c]
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c,
+ lib/eventlog/eventlog_free.c, lib/eventlog/parse_json.c,
+ logsrvd/iolog_writer.c, logsrvd/sendlog.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/log_client.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h:
+ Store submitenv in eventlog and pass it to sudo_logsrvd.
+ [3ef684a6f888]
+
+2023-10-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c,
+ lib/eventlog/eventlog_free.c, lib/eventlog/parse_json.c,
+ lib/iolog/iolog_loginfo.c, logsrvd/iolog_writer.c,
+ logsrvd/sendlog.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/log_client.c, plugins/sudoers/logging.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/sudoreplay.c:
+ struct eventlog: rename argv/env to runargv/runenv.
+
+ This matches the JSON logs.
+ [df2ac695bcf7]
+
+ * plugins/sudoers/logging.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ struct sudoers_user_context: rename env_vars to env_add
+ [f57859bca061]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/logging.c:
+ Only log the run environment for commands that are allowed.
+
+ It may not be available otherwise and unless the command is being
+ run it has no real meaning.
+ [98b79f16e06e]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c:
+ Free the private copy of the environment in sudoers_check_cmnd().
+
+ This reverts 5118eb5797fb, which had the side-effect of the PAM
+ session code running with the run environment instead of the
+ invoking user's environment. Issue #318
+ [6b4abada2e55]
+
+2023-10-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/iolog_swapids.c:
+ iolog_swapids: short circuit if effective ids match iolog ids.
+ [6871a2a50eae]
+
+ * lib/iolog/iolog_mkdirs.c, logsrvd/iolog_writer.c:
+ logsrvd: display error string in message if iolog_mkpath() fails
+ [4a601c7e1248]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ Update .pot files for 1.9.15
+ [39ac757a80c9]
+
+2023-10-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.in:
+ Add example for disabling intercept/log_subcmds for certain
+ commands.
+ [52d01bcd6e3a]
+
+ * lib/util/mksiglist.c, lib/util/mksigname.c:
+ Use NSIG instead of nitems(array) for the loop bound.
+
+ This matches the sudo_sys_siglist[] and sudo_sys_signame[]
+ declarations.
+ [d515abb232ae]
+
+ * plugins/sudoers/tsdump.c:
+ tsdump: fix compiler warnings
+ [4e5d80f29845]
+
+2023-10-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/eventlog/regress/logwrap/check_wrap.c, lib/util/mksiglist.c,
+ lib/util/mksigname.c, logsrvd/sendlog.c,
+ plugins/python/regress/iohelpers.c, plugins/sudoers/tsdump.c:
+ Avoid using %zu or %zd with printf() and fprintf().
+
+ This prevents problems on systems where the system printf(3) is not
+ C99-compliant. We use our own snprintf() on such systems so that is
+ safe.
+ [7ff250c66e05]
+
+ * plugins/sudoers/sudo_printf.c, src/conversation.c:
+ Use vsnprintf() instead of vfprintf() for sudo_printf() to avoid
+ problems on systems where the system printf(3) is not C99-compliant.
+ We use our own snprintf() on such systems.
+ [053c94c3db03]
+
+ * include/sudo_compat.h, lib/util/getdelim.c, lib/util/realpath.c,
+ lib/util/regress/getdelim/getdelim_test.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l:
+ strlcpy_expand_host, sudo_getdelim, sudo_realpath: add restrict
+ qualifier
+ [8669d4d9b4d9]
+
+ * NEWS:
+ Fixed GitHub issue #312.
+ [b6e269e7eeaa]
+
+2023-10-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/term.c:
+ Better handling of multiple sudo processes modifying terminal
+ settings. 1. Lock the terminal before tcgetattr/tcsetattr 2. Don't
+ restore terminal settings if changed by another process 3. Don't set
+ terminal to raw mode if it is already raw GitHub issue #312
+ [8d5664300c7e]
+
+2023-10-16 Rose <83477269+AtariDreams@users.noreply.github.com>
+
+ * plugins/sudoers/prompt.c, plugins/sudoers/strlcpy_unesc.c,
+ plugins/sudoers/sudoers.h:
+ Add restrict to strlcpy and expand_prompt
+ [b26d50f82d2f]
+
+2023-10-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_pty.c:
+ Add a little extra debugging info.
+ [b2533548f50b]
+
+2023-10-15 Rose <83477269+AtariDreams@users.noreply.github.com>
+
+ * lib/util/regress/hexchar/hexchar_test.c,
+ lib/util/regress/parse_gids/parse_gids_test.c, lib/util/sudo_conf.c:
+ Swap calloc arguments to use them properly.
+ [1d4877da5233]
+
+2023-10-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.c:
+ ptrace_intercept_execve: make flags unsigned to match
+ command_details
+ [97ee796e74ec]
+
+2023-10-13 Rose <83477269+AtariDreams@users.noreply.github.com>
+
+ * include/sudo_util.h, src/exec_ptrace.h:
+ Specify 1U over 1 for bitmaps
+ [8eaecce2e3c6]
+
+2023-10-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/sudo_auth.h, plugins/sudoers/parse.h,
+ plugins/sudoers/sudoers.h:
+ Fix spelling: resistent -> resistant
+ [df6b986b8d31]
+
+2023-10-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .gitignore, .hgignore:
+ Add plugins/sudoers/tsgetusershell.c to ignore files.
+ [5e9538b2aaae]
+
+2023-10-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/mkdefaults:
+ Fix compatibility with older versions of (new) awk.
+
+ Do not rely on awk supporting "-f -" to read the program from stdin.
+ Avoid using POSIX character classes in regular expressions.
+ [0e67e9ba4ddf]
+
+2023-10-02 Alexander F. Rødseth <alexander.fet.rodseth@schibsted.com>
+
+ * plugins/sudoers/visudo.c:
+ Add Orbiton ("o") to the list of editors that supports +lineno
+ [28e192d4be9b]
+
+ * plugins/sudoers/visudo.c:
+ Sort the list of editors that supports +lineno
+ [6467309f5ac3]
+
+2023-09-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ Mention potential problems with log_subcmds and intercept.
+ [9c93f9315924]
+
+ * src/sudo.c:
+ Add more user info to the list of objects to be garbage-collected at
+ exit.
+ [caeb35967cd2]
+
+2023-09-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/pyhelpers.c, plugins/python/pyhelpers.h:
+ Use long, not long long, when getting/setting numeric attributes.
+
+ We use int or long, not long long, in the Python plugin.
+ [d1008ce69cf6]
+
+ * plugins/sudoers/file.c:
+ sudo_file_open: initialize parser before calling open_sudoers().
+
+ Otherwise, the parser_conf settings in the context passed to
+ sudo_file_open() will not be honored by open_sudoers(). Affected
+ settings include ignore_perms, sudoers mode, uid and gid.
+ [21e56d49521a]
+
+ * lib/eventlog/parse_json.c, lib/iolog/iolog_legacy.c,
+ lib/iolog/iolog_timing.c, logsrvd/iolog_writer.c,
+ logsrvd/logsrvd_conf.c, logsrvd/logsrvd_journal.c,
+ logsrvd/logsrvd_local.c, logsrvd/sendlog.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/log_client.c:
+ Add casts when storing values in a struct timespec.
+
+ Fixes -Wconversion warnings on some 32-bit systems where time_t is
+ still 32-bit.
+ [b090ed40a1d0]
+
+2023-09-27 Rose <83477269+AtariDreams@users.noreply.github.com>
+
+ * lib/util/roundup.c:
+ Use U, not UL, for 32-bit platforms
+
+ size_t is an unsigned int on 32-bit platforms, not an unsigned long.
+ [9f4a9b73c954]
+
+2023-09-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/match_digest.c:
+ digest_matches: actually use fd2 in place of fd as needed.
+ [9db51e4a8521]
+
+ * plugins/sudoers/match_digest.c:
+ digest_matches: if fd argument is -1, try to open path before
+ failing
+ [5b323859cbd0]
+
+ * plugins/sudoers/regress/cvtsudoers/test31.sh,
+ plugins/sudoers/regress/cvtsudoers/test32.sh,
+ plugins/sudoers/regress/cvtsudoers/test35.sh,
+ plugins/sudoers/regress/cvtsudoers/test36.sh,
+ plugins/sudoers/regress/cvtsudoers/test39.sh,
+ plugins/sudoers/regress/testsudoers/test20.sh,
+ plugins/sudoers/regress/testsudoers/test21.sh,
+ plugins/sudoers/regress/testsudoers/test22.sh,
+ plugins/sudoers/regress/testsudoers/test23.sh,
+ plugins/sudoers/regress/testsudoers/test24.sh,
+ plugins/sudoers/regress/testsudoers/test25.sh,
+ plugins/sudoers/regress/testsudoers/test26.sh,
+ plugins/sudoers/regress/testsudoers/test27.sh,
+ plugins/sudoers/regress/testsudoers/test28.sh,
+ plugins/sudoers/regress/testsudoers/test29.sh,
+ plugins/sudoers/regress/testsudoers/test30.sh,
+ plugins/sudoers/regress/testsudoers/test31.sh:
+ Add missing execute bit on some test scripts.
+ [07af3341fc1a]
+
+2023-09-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.h:
+ max_groups in sudoers_plugin_settings is no longer used.
+ [99848d0ee951]
+
+ * include/sudo_conf.h, include/sudo_debug.h, include/sudo_event.h,
+ include/sudo_eventlog.h, include/sudo_fatal.h, include/sudo_json.h,
+ include/sudo_util.h, lib/eventlog/eventlog.c,
+ lib/eventlog/eventlog_conf.c, lib/eventlog/eventlog_free.c,
+ lib/eventlog/logwrap.c, lib/eventlog/parse_json.c,
+ lib/eventlog/parse_json.h,
+ lib/eventlog/regress/eventlog_store/store_json_test.c,
+ lib/eventlog/regress/eventlog_store/store_sudo_test.c,
+ lib/eventlog/regress/logwrap/check_wrap.c,
+ lib/eventlog/regress/parse_json/check_parse_json.c,
+ lib/fuzzstub/fuzzstub.c, lib/iolog/host_port.c,
+ lib/iolog/hostcheck.c, lib/iolog/iolog_clearerr.c,
+ lib/iolog/iolog_close.c, lib/iolog/iolog_conf.c,
+ lib/iolog/iolog_eof.c, lib/iolog/iolog_filter.c,
+ lib/iolog/iolog_flush.c, lib/iolog/iolog_gets.c,
+ lib/iolog/iolog_json.c, lib/iolog/iolog_legacy.c,
+ lib/iolog/iolog_loginfo.c, lib/iolog/iolog_mkdirs.c,
+ lib/iolog/iolog_mkdtemp.c, lib/iolog/iolog_mkpath.c,
+ lib/iolog/iolog_nextid.c, lib/iolog/iolog_open.c,
+ lib/iolog/iolog_openat.c, lib/iolog/iolog_path.c,
+ lib/iolog/iolog_read.c, lib/iolog/iolog_seek.c,
+ lib/iolog/iolog_swapids.c, lib/iolog/iolog_timing.c,
+ lib/iolog/iolog_util.c, lib/iolog/iolog_write.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_json.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_legacy.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_timing.c,
+ lib/iolog/regress/host_port/host_port_test.c,
+ lib/iolog/regress/iolog_filter/check_iolog_filter.c,
+ lib/iolog/regress/iolog_mkpath/check_iolog_mkpath.c,
+ lib/iolog/regress/iolog_path/check_iolog_path.c,
+ lib/iolog/regress/iolog_timing/check_iolog_timing.c,
+ lib/logsrv/log_server.pb-c.c, lib/protobuf-c/protobuf-c.c,
+ lib/ssl_compat/ssl_compat.c, lib/util/aix.c, lib/util/arc4random.c,
+ lib/util/arc4random_buf.c, lib/util/arc4random_uniform.c,
+ lib/util/basename.c, lib/util/cfmakeraw.c, lib/util/closefrom.c,
+ lib/util/digest.c, lib/util/digest_gcrypt.c,
+ lib/util/digest_openssl.c, lib/util/dup3.c, lib/util/event.c,
+ lib/util/event_poll.c, lib/util/event_select.c,
+ lib/util/explicit_bzero.c, lib/util/fatal.c, lib/util/fchmodat.c,
+ lib/util/fchownat.c, lib/util/fnmatch.c, lib/util/freezero.c,
+ lib/util/fstatat.c, lib/util/getaddrinfo.c, lib/util/getdelim.c,
+ lib/util/getentropy.c, lib/util/getgrouplist.c,
+ lib/util/gethostname.c, lib/util/getopt_long.c, lib/util/gettime.c,
+ lib/util/getusershell.c, lib/util/gidlist.c, lib/util/glob.c,
+ lib/util/gmtime_r.c, lib/util/hexchar.c, lib/util/inet_ntop.c,
+ lib/util/inet_pton.c, lib/util/isblank.c, lib/util/json.c,
+ lib/util/key_val.c, lib/util/lbuf.c, lib/util/localtime_r.c,
+ lib/util/locking.c, lib/util/logfac.c, lib/util/logpri.c,
+ lib/util/memrchr.c, lib/util/mkdir_parents.c, lib/util/mkdirat.c,
+ lib/util/mksiglist.c, lib/util/mksigname.c, lib/util/mktemp.c,
+ lib/util/mmap_alloc.c, lib/util/multiarch.c, lib/util/nanosleep.c,
+ lib/util/openat.c, lib/util/parseln.c, lib/util/pipe2.c,
+ lib/util/pread.c, lib/util/progname.c, lib/util/pw_dup.c,
+ lib/util/pwrite.c, lib/util/rcstr.c, lib/util/reallocarray.c,
+ lib/util/regex.c, lib/util/regress/closefrom/closefrom_test.c,
+ lib/util/regress/digest/digest_test.c,
+ lib/util/regress/fnmatch/fnm_test.c,
+ lib/util/regress/fuzz/fuzz_sudo_conf.c,
+ lib/util/regress/getdelim/getdelim_test.c,
+ lib/util/regress/getgrouplist/getgids.c,
+ lib/util/regress/getgrouplist/getgrouplist_test.c,
+ lib/util/regress/glob/globtest.c,
+ lib/util/regress/hexchar/hexchar_test.c,
+ lib/util/regress/json/json_test.c,
+ lib/util/regress/mktemp/mktemp_test.c,
+ lib/util/regress/multiarch/multiarch_test.c,
+ lib/util/regress/open_parent_dir/open_parent_dir_test.c,
+ lib/util/regress/parse_gids/parse_gids_test.c,
+ lib/util/regress/progname/progname_test.c,
+ lib/util/regress/regex/regex_test.c,
+ lib/util/regress/strsig/strsig_test.c,
+ lib/util/regress/strsplit/strsplit_test.c,
+ lib/util/regress/strtofoo/strtobool_test.c,
+ lib/util/regress/strtofoo/strtoid_test.c,
+ lib/util/regress/strtofoo/strtomode_test.c,
+ lib/util/regress/strtofoo/strtonum_test.c,
+ lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_parseln/parseln_test.c,
+ lib/util/regress/tailq/hltq_test.c,
+ lib/util/regress/uuid/uuid_test.c, lib/util/roundup.c,
+ lib/util/secure_path.c, lib/util/setgroups.c, lib/util/sha2.c,
+ lib/util/sig2str.c, lib/util/snprintf.c, lib/util/str2sig.c,
+ lib/util/strlcat.c, lib/util/strlcpy.c, lib/util/strndup.c,
+ lib/util/strnlen.c, lib/util/strsignal.c, lib/util/strsplit.c,
+ lib/util/strtobool.c, lib/util/strtoid.c, lib/util/strtomode.c,
+ lib/util/strtonum.c, lib/util/sudo_conf.c, lib/util/sudo_debug.c,
+ lib/util/sudo_dso.c, lib/util/sys_siglist.h, lib/util/sys_signame.h,
+ lib/util/term.c, lib/util/timegm.c, lib/util/ttyname_dev.c,
+ lib/util/ttysize.c, lib/util/unlinkat.c, lib/util/utimens.c,
+ lib/util/uuid.c, logsrvd/iolog_writer.c, logsrvd/logsrv_util.c,
+ logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c,
+ logsrvd/logsrvd_journal.c, logsrvd/logsrvd_local.c,
+ logsrvd/logsrvd_queue.c, logsrvd/logsrvd_relay.c,
+ logsrvd/regress/fuzz/fuzz_logsrvd_conf.c,
+ logsrvd/regress/logsrvd_conf/logsrvd_conf_test.c, logsrvd/sendlog.c,
+ logsrvd/sendlog.h, logsrvd/tls_client.c, logsrvd/tls_common.h,
+ logsrvd/tls_init.c, plugins/audit_json/audit_json.c,
+ plugins/group_file/getgrent.c, plugins/group_file/group_file.c,
+ plugins/group_file/plugin_test.c, plugins/python/pyhelpers.c,
+ plugins/python/pyhelpers.h, plugins/python/python_plugin_common.c,
+ plugins/python/regress/check_python_examples.c,
+ plugins/python/regress/iohelpers.h,
+ plugins/python/regress/testhelpers.h,
+ plugins/python/sudo_python_debug.c,
+ plugins/python/sudo_python_debug.h, plugins/sample/sample_plugin.c,
+ plugins/sample_approval/sample_approval.c, plugins/sudoers/alias.c,
+ plugins/sudoers/audit.c, plugins/sudoers/auth/afs.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/b64_decode.c, plugins/sudoers/b64_encode.c,
+ plugins/sudoers/boottime.c, plugins/sudoers/bsm_audit.c,
+ plugins/sudoers/canon_path.c, plugins/sudoers/check.c,
+ plugins/sudoers/check_aliases.c, plugins/sudoers/check_util.c,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers.h,
+ plugins/sudoers/cvtsudoers_csv.c, plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/cvtsudoers_merge.c,
+ plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/defaults.h, plugins/sudoers/digestname.c,
+ plugins/sudoers/display.c, plugins/sudoers/editor.c,
+ plugins/sudoers/env.c, plugins/sudoers/env_pattern.c,
+ plugins/sudoers/exptilde.c, plugins/sudoers/file.c,
+ plugins/sudoers/filedigest.c, plugins/sudoers/find_path.c,
+ plugins/sudoers/fmtsudoers.c, plugins/sudoers/fmtsudoers_cvt.c,
+ plugins/sudoers/gc.c, plugins/sudoers/gentime.c,
+ plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/getspwuid.c, plugins/sudoers/goodpath.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/insults.h,
+ plugins/sudoers/interfaces.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_path_escapes.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/ldap_conf.c, plugins/sudoers/ldap_innetgr.c,
+ plugins/sudoers/ldap_util.c, plugins/sudoers/linux_audit.c,
+ plugins/sudoers/locale.c, plugins/sudoers/log_client.c,
+ plugins/sudoers/log_client.h, plugins/sudoers/logging.c,
+ plugins/sudoers/lookup.c, plugins/sudoers/match.c,
+ plugins/sudoers/match_addr.c, plugins/sudoers/match_command.c,
+ plugins/sudoers/match_digest.c, plugins/sudoers/parse.h,
+ plugins/sudoers/parse_ldif.c, plugins/sudoers/parser_warnx.c,
+ plugins/sudoers/pivot.c, plugins/sudoers/policy.c,
+ plugins/sudoers/prompt.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/pwutil_impl.c, plugins/sudoers/redblack.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/editor/check_editor.c,
+ plugins/sudoers/regress/env_match/check_env_pattern.c,
+ plugins/sudoers/regress/exptilde/check_exptilde.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_stubs.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/regress/parser/check_gentime.c,
+ plugins/sudoers/regress/serialize_list/check_serialize_list.c,
+ plugins/sudoers/regress/starttime/check_starttime.c,
+ plugins/sudoers/regress/unescape/check_unesc.c,
+ plugins/sudoers/resolve_cmnd.c, plugins/sudoers/serialize_list.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sethost.c,
+ plugins/sudoers/solaris_audit.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/starttime.c, plugins/sudoers/strlcpy_unesc.c,
+ plugins/sudoers/strlist.c, plugins/sudoers/strvec_join.c,
+ plugins/sudoers/stubs.c, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudo_printf.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoers_cb.c,
+ plugins/sudoers/sudoers_ctx_free.c, plugins/sudoers/sudoers_debug.c,
+ plugins/sudoers/sudoers_debug.h, plugins/sudoers/sudoers_hooks.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/testsudoers_pwutil.c,
+ plugins/sudoers/testsudoers_pwutil.h, plugins/sudoers/timeout.c,
+ plugins/sudoers/timestamp.c, plugins/sudoers/timestr.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/tsdump.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/unesc_str.c,
+ plugins/sudoers/visudo.c, plugins/sudoers/visudo_cb.c,
+ plugins/system_group/system_group.c, src/apparmor.c,
+ src/conversation.c, src/copy_file.c, src/edit_open.c,
+ src/env_hooks.c, src/exec.c, src/exec_common.c,
+ src/exec_intercept.c, src/exec_iolog.c, src/exec_monitor.c,
+ src/exec_nopty.c, src/exec_preload.c, src/exec_ptrace.c,
+ src/exec_pty.c, src/get_pty.c, src/hooks.c, src/intercept.pb-c.c,
+ src/limits.c, src/load_plugins.c, src/openbsd.c, src/parse_args.c,
+ src/preload.c, src/preserve_fds.c,
+ src/regress/net_ifs/check_net_ifs.c,
+ src/regress/noexec/check_noexec.c,
+ src/regress/ttyname/check_ttyname.c, src/selinux.c, src/sesh.c,
+ src/signal.c, src/solaris.c, src/sudo.c, src/sudo.h,
+ src/sudo_edit.c, src/sudo_intercept.c, src/sudo_intercept_common.c,
+ src/sudo_noexec.c, src/suspend_parent.c, src/tgetpass.c,
+ src/ttyname.c, src/utmp.c:
+ Use #include <foo.h> instead of #include "foo.h" in most cases.
+
+ We rely on the include path to find many of these headers. It
+ especially doesn't make sense to use #include "foo.h" for headers in
+ the top-level include directory.
+ [4a7d27e429e9]
+
+ * .circleci/config.yml:
+ Bump xcode to 14.2.0
+ [f4775577c9b0]
+
+2023-09-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/mkdefaults:
+ Add support for "plugin" defaults type.
+ [423dc640d220]
+
+ * plugins/sudoers/mkdefaults:
+ Support multiple input files.
+ [1fff41f962f5]
+
+2023-09-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_monitor.c, src/exec_pty.c:
+ No need to loop reading from/writing to a blocking socketpair.
+
+ This removes some infinite loops that can cause static analyzer
+ warnings. The fds are not in non-blocking mode and we use
+ restartable system calls so there is no need to loop.
+ [132aad609392]
+
+ * plugins/sudoers/check.c:
+ check_user: fix return value for intercept mode
+
+ Also use early return on error to quiet a PVS-Studio warning.
+ [ecd721208013]
+
+2023-09-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_pty.c:
+ Set ec->term_raw to false even if sudo_term_restore() fails.
+
+ Either the fd is not a terminal or we don't have the controlling
+ terminal. Either way, we can't know the current status of the
+ terminal and will need to set to raw mode again (if possible). Also
+ make sure to set ec->term_raw to false if sudo_term_raw() fails.
+ [6287218771a9]
+
+2023-09-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * pathnames.h.in, plugins/sudoers/env.c, plugins/sudoers/sudoers.c:
+ Only define _PATH_ENVIRONMENT on systems where we use
+ /etc/environment.
+ [5a3752401dc9]
+
+ * config.h.in, configure, configure.ac:
+ Sudo assumes that a uid_t can be cast to unsigned int without
+ problems.
+
+ Add a configure check and error out if sizeof(uid_t) > 4.
+ [4b7657e4ce3d]
+
+ * docs/UPGRADE.md:
+ Mention the time stamp and lecture file name changes in 1.9.15.
+ [8c23b36928ad]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in,
+ plugins/sudoers/iolog_path_escapes.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l:
+ Replace '/' with '_' in paths using the user, group or host name.
+ [2862df9bcab7]
+
+2023-09-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, m4/sudo.m4,
+ plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/env.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/policy.c, src/sudo.c, src/sudo_edit.c:
+ Replace MAX_UID_T_LEN with calls to STRLEN_MAX_UNSIGNED.
+ [f2f1ee9c5a16]
+
+ * include/sudo_util.h, lib/eventlog/eventlog.c,
+ lib/iolog/iolog_timing.c, lib/util/json.c, lib/util/lbuf.c,
+ lib/util/sudo_debug.c, plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/display.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/logging.c, src/exec_preload.c, src/limits.c:
+ Add macros to determine the length of an integer type in string
+ form.
+
+ Adapted from answer #6 in:
+ https://stackoverflow.com/questions/10536207/ansi-c-maximum-number-
+ of-characters-printing-a-decimal-int
+ [e62734abe89c]
+
+2023-09-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/visudo.c:
+ visudo: use verbose and strict in parser_conf
+
+ Where the sudoers_context is available we can use the values of
+ verbose and strict instead of passing around quiet and strict flags.
+ [bc7a60ce0e36]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/callbacks.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoers_cb.c:
+ Rename callbacks.c -> sudoers_cb.c.
+ [558d6896ebfa]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/visudo.c,
+ plugins/sudoers/visudo_cb.c:
+ Add a separate file for visudo callbacks.
+ [72e491607a4e]
+
+ * MANIFEST, plugins/sudoers/Makefile.in,
+ plugins/sudoers/check_aliases.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/parse.h, plugins/sudoers/parser_warnx.c:
+ Add parser_warnx() and parser_vwarnx() that displays file:line:col
+
+ Used by defaults.c and check_aliases.c.
+ [1b4eff914e92]
+
+ * plugins/sudoers/sudoers.h, plugins/sudoers/visudo.c:
+ Promote strict field in sudoers_parser_config from bool to int.
+
+ This will be used by visudo to indicate when "visudo -s" is run.
+ [d0f6c8c37e4a]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/find_path.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/resolve_cmnd.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Add resolve_cmnd(), a wrapper around find_path().
+
+ This is a convenience function that sets PERM_RUNAS and calls
+ find_path(). If the command is not found it will retry with
+ PERM_USER instead.
+ [c7831c462fb9]
+
+ * src/exec_monitor.c:
+ Wait on a socketpair for the parent to grant child the controlling
+ tty.
+
+ This upgrades the error pipe to a bi-directional socketpair that the
+ parent will write to after it has granted the child process the
+ controlling terminal. That fixes an issue where the child could end
+ up in a tight CPU loop waiting on the parent which may not be
+ scheduled immediately.
+ [36e87999dae1]
+
+2023-09-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.h:
+ Undefine AUTH_{SUCCESS,FAILURE,ERROR} before defining them.
+
+ Quiets a warning on AIX where usersec.h defines AUTH_SUCCESS and
+ AUTH_FAILURE. We avoided this problem in the past because the old
+ values for AUTH_SUCCESS and AUTH_FAILURE match what AIX defines.
+ [c37c51f861f1]
+
+ * config.h.in, configure, configure.ac, lib/util/term.c, m4/sudo.m4,
+ src/exec_pty.c:
+ Only cast TIOCSWINSZ to int on systems that might require it (AIX).
+
+ Otherwise we end up with a -Wconversion warning on systems where the
+ ioctl() request argument is unsigned long.
+ [a467e228981f]
+
+ * plugins/sudoers/display.c, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Promote verbose flag to int for display_privs and display_cmnd.
+
+ A negative verbosity will prevent non-error output from being
+ displayed.
+ [c7646497b580]
+
+2023-09-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/stubs.c:
+ No need to include cvtsudoers.h here.
+ [d838f2ed5483]
+
+ * plugins/sudoers/match_command.c, plugins/sudoers/pivot.c,
+ plugins/sudoers/pivot.h, plugins/sudoers/regress/fuzz/fuzz_stubs.c,
+ plugins/sudoers/stubs.c, plugins/sudoers/testsudoers.c:
+ Remove pivot_get_root() and pivot_get_cwd().
+
+ They are unnecessary since struct sudoers_pivot is not opaque. The
+ implementation details are private to match_command.c.
+ [ca522bffdf37]
+
+ * plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/regress/parser/check_fill.c:
+ Quiet some -Wconversion warnings in the tests.
+ [ebe02fc397e7]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/editor.c, plugins/sudoers/find_path.c,
+ plugins/sudoers/regress/editor/check_editor.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.h:
+ Make flag in union sudo_defs_val bool to match how it is used.
+
+ Adjust find_path()'s ignore_dot function argument to match.
+ [52d5311ca360]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/bsm_audit.c,
+ plugins/sudoers/bsm_audit.h, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.h:
+ Parse euid and egid from sudo front-end.
+
+ These are needed by bsm_audit.c.
+ [ca240f519b46]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/timestamp.c:
+ Parse pid and ppid from sudo front-end.
+
+ We can now use the stored ppid in ts_init_key().
+ [4955c478f849]
+
+ * plugins/sudoers/match_command.c, plugins/sudoers/pivot.c,
+ plugins/sudoers/pivot.h, plugins/sudoers/regress/fuzz/fuzz_stubs.c,
+ plugins/sudoers/stubs.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/testsudoers.c:
+ Use struct sudoers_pivot instead of defining sudoers_pivot_t.
+
+ We want to pass around a pointer, not the struct itself.
+ [8c6806cee428]
+
+2023-09-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/pivot.h:
+ Don't expose the implementation of the pivot_root state.
+ [1d1696c7ad78]
+
+ * plugins/sudoers/match_command.c, plugins/sudoers/pivot.c,
+ plugins/sudoers/regress/fuzz/fuzz_stubs.c, plugins/sudoers/stubs.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c:
+ Don't expose the implementation of the pivot_root state.
+ [efaa8955cbf0]
+
+ * src/exec_ptrace.c:
+ Only call ptrace_verify_post_exec() for intercept, not log_subcmds.
+
+ This fixes a logic goof introduced in sudo 1.9.14.
+ [49df34bb0494]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in,
+ docs/sudoers_timestamp.man.in, docs/sudoers_timestamp.mdoc.in,
+ plugins/sudoers/check.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/timestamp.h:
+ Use the user-ID instead of user-name for the timestamp and lecture
+ file.
+
+ This avoids problems if the user name itself contains a path
+ separator.
+ [c93459e59f30]
+
+2023-09-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/Makefile.in:
+ tsgetusershell.c: don't rely on GNU sed extensions.
+ [65e7d8099122]
+
+ * plugins/sudoers/testsudoers.c:
+ testsudoers: add -S option to specify /etc/shells path.
+ [2efe9b01120a]
+
+ * Makefile.in, lib/util/getusershell.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/pwutil_impl.c, plugins/sudoers/tsgetgrpw.h:
+ Add testsudoers_setshellfile() and use it in testsudoers.
+ [4065e0f1c9ac]
+
+ * plugins/sudoers/Makefile.in:
+ regen
+ [044181c21564]
+
+ * lib/util/Makefile.in, lib/util/getusershell.c:
+ Remove unnecessary sudo_gettext.h include and add missing const.
+ [ca4266370ff6]
+
+2023-09-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/sudo_auth.h, plugins/sudoers/check.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/timestamp.h:
+ Return AUTH_* flags from check_user() instead of 1/0/-1.
+ [824e8943fa47]
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/pwutil.h, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/testsudoers_pwutil.h:
+ Wrap valid_shell and add to sudo_pwutil_set_backend().
+
+ This will make it possible to support a different getusershell()
+ implementation for testsudoers in the future.
+ [03da23d61efe]
+
+ * plugins/sudoers/check_util.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/pwutil.h, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c:
+ Move check_user_shell() to pwutil.c as user_shell_valid()
+
+ This will make it possible to support a different backend which may
+ be used by testsudoers in the future.
+ [44a7540fb761]
+
+ * plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/check.c,
+ plugins/sudoers/timestamp.h:
+ Merge check_user() and check_user_interactive(), move getpass
+ callbacks.
+
+ The getpass callbacks are now defined in sudo_auth.c, which
+ implements auth_getpass(). As a result, struct getpass_closure is
+ now public and defined in timestamp.h.
+ [1babbb56de42]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h, plugins/sudoers/check.c,
+ plugins/sudoers/timestamp.h:
+ Make most sudo_auth functions return AUTH_{SUCCESS,FAILURE,FATAL}.
+ [54471c0a890d]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/lookup.c,
+ plugins/sudoers/match.c, plugins/sudoers/match_addr.c,
+ plugins/sudoers/match_command.c, plugins/sudoers/match_digest.c,
+ plugins/sudoers/parse.h,
+ plugins/sudoers/regress/parser/check_addr.c, plugins/sudoers/sssd.c:
+ Make all match functions return ALLOW/DENY not true/false.
+ [d22f1dc85b40]
+
+ * plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h, plugins/sudoers/lookup.c,
+ plugins/sudoers/match.c, plugins/sudoers/parse.h:
+ Try to make sudo less vulnerable to ROWHAMMER attacks.
+
+ We now use ROWHAMMER-resistent values for ALLOW, DENY, AUTH_SUCCESS,
+ AUTH_FAILURE, AUTH_ERROR and AUTH_NONINTERACTIVE. In addition, we
+ explicitly test for expected values instead of using a negated test
+ against an error value. In the parser match functions this means
+ explicitly checking for ALLOW or DENY instead of accepting anything
+ that is not set to UNSPEC.
+
+ Thanks to Andrew J. Adiletta, M. Caner Tol, Yarkin Doroz, and Berk
+ Sunar, all affiliated with the Vernam Applied Cryptography and
+ Cybersecurity Lab at Worcester Polytechnic Institute, for the
+ report. Paper preprint: https://arxiv.org/abs/2309.02545
+ [df81a335db65]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.h,
+ plugins/sudoers/toke.l:
+ Honor ignore_perms plugin argument for @include and @includedir.
+ [55307bdf721d]
+
+2023-09-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/check.c:
+ Don't set on_suspend and on_resume twice.
+ [f1db05f66740]
+
+2023-09-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers.h, plugins/sudoers/policy.c,
+ plugins/sudoers/sethost.c, plugins/sudoers/stubs.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c:
+ sudoers_sethost: refactor code to set host names in sudoers_context.
+
+ The sudoers_sethost() function can be shared by the sudoers plugin,
+ visudo, cvtsudoers and testsudoers.
+ [6cece4f67add]
+
+2023-09-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ sudoers_trace_print: use debug_decl_vars instead of doing it by
+ hand.
+ [0baf94e3e380]
+
+ * include/sudo_compat.h:
+ sudo_realpath() returns char *, not void *.
+ [96746a992f65]
+
+2023-08-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.c:
+ Only print "no valid sudoers sources found, quitting" for multiple
+ sources.
+
+ If there is only a single source (usually the sudoers file), the
+ open function provide enough of an error message. Printing two error
+ messages is just confusing.
+ [99a282277084]
+
+2023-08-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/pwutil.c:
+ user_in_group: the user's group vector already includes the primary
+ group.
+
+ There's no need to look up the name of user's primary group
+ (pw_gid), we always include the primary group ID in the group
+ vector.
+ [53f36984ebc8]
+
+2023-08-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.h, plugins/sudoers/sudoers_debug.h:
+ Move sudoers_debug.c prototypes to sudoers_debug.h.
+ [3d4c971912a3]
+
+ * plugins/sudoers/sudoers.h:
+ sudo_conv, sudo_printf and plugin_event_alloc live in policy.c.
+ [52bced1bff2a]
+
+ * include/sudo_iolog.h, plugins/sudoers/defaults.c:
+ Move default value for "iolog_file" to sudo_iolog.h.
+ [489101c36995]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/auth/afs.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/callbacks.c, plugins/sudoers/check.c,
+ plugins/sudoers/check.h, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_stubs.c,
+ plugins/sudoers/regress/starttime/check_starttime.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/starttime.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/timestamp.c, plugins/sudoers/timestamp.h,
+ plugins/sudoers/tsdump.c:
+ Rename check.h -> timestamp.h and add remaining timestamp.c
+ prototypes.
+ [402c837776df]
+
+ * plugins/sudoers/auth/API, plugins/sudoers/auth/aix_auth.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/auth/sudo_auth.h:
+ Restore AUTH_INTR support, it is still needed.
+
+ We still need AUTH_INTR to know when to break out of the password
+ prompt loop.
+ [618807782033]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Add ignore_perms plugin argument to skip the sudoers file security
+ checks.
+
+ This is not intended to be used in a production environment.
+ [92ae0335ee5b]
+
+2023-08-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, m4/sudo.m4:
+ Fix test for unsetenv() returning void with clang 16.
+
+ Clang has dropped support for K&R function definitions so rewrite
+ the test to require a unsetenv() prototype in stdlib.h. Fixes GitHub
+ issue #302.
+ [1a0ce3a79ee2]
+
+ * plugins/sudoers/defaults.c:
+ Disable fast_glob and fdexec if SUDOERS_NAME_MATCH is defined.
+
+ We use SUDOERS_NAME_MATCH for fuzzing when we want to avoid
+ searching the file system for commands.
+ [2e6bc1f8fb22]
+
+2023-08-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/API, plugins/sudoers/auth/aix_auth.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h:
+ Rename AUTH_FATAL -> AUTH_ERROR.
+ [1da161db2f0f]
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/match.c:
+ Do not rely on the definition of ALLOW/DENY being true/false.
+
+ We now explicitly check for ALLOW and DENY when checking return
+ values and negating values.
+ [1e4420b64b5d]
+
+ * plugins/sudoers/auth/API, plugins/sudoers/auth/aix_auth.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/auth/sudo_auth.h:
+ Replace AUTH_INTR return with AUTH_FAILURE.
+
+ The two were treated identically by the caller.
+ [e54b06561de1]
+
+2023-08-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Move tty_present() into policy.c as sudoers_tty_present().
+
+ This function is policy-dependent. For the modern sudo front-end it
+ will simply check tcpgid and/or ttypath.
+ [36a5ece4027a]
+
+ * plugins/sudoers/callbacks.c:
+ Only set I/O logging callbacks if SESSID_MAX is defined.
+ [3cec54b1fe9a]
+
+ * plugins/sudoers/defaults.c:
+ Don't set defaults values for features that are not present.
+
+ This means that lecture_status_dir and timestampdir are only set if
+ _PATH_SUDO_LECTURE_DIR and _PATH_SUDO_TIMEDIR respectively are set.
+ Also, the log server defaults are only set when SUDOERS_LOG_CLIENT
+ is defined.
+ [bb328fffe142]
+
+ * plugins/sudoers/audit.c:
+ Call log_allowed() even when "log_allowed" is disabled.
+
+ Otherwise, sudo will not send mail if "mail_always" or
+ "mail_all_cmnds" is set.
+ [71d3f06fbee5]
+
+2023-08-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, configure, configure.ac:
+ sudo 1.9.15
+ [9e7aa0238aca]
+
+2023-08-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/event_poll.c, lib/util/getentropy.c,
+ plugins/sudoers/ldap.c:
+ Silence a few remaining -Wconversion warnings.
+ [8f1180e72c0b]
+
+ * plugins/sudoers/sudoers.c:
+ No need to inclue auth/sudo_auth.h
+ [61ec4a47c885]
+
+ * configure, m4/sudo.m4:
+ --enable-pvs-studio: check for license file in the default location
+ [35e596d1fdb7]
+
+2023-08-23 ken <41325712+rtczza@users.noreply.github.com>
+
+ * plugins/sudoers/timestamp.c:
+ modify ret type from int to bool (#298)
+
+ * modify ret type from int to bool
+
+ * change debug_return_int to debug_return_bool
+
+ * modify ret type
+ [cf8c33ecdce0]
+
+2023-08-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/callbacks.c, plugins/sudoers/check.h,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_stubs.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/timestamp.c:
+ Move timestampowner sudoers callback to timestamp.c.
+ [34520a083145]
+
+ * plugins/sudoers/set_perms.c:
+ Quiet a PVS-Studio false positive about possible NULL dereference.
+
+ set_perms() is only called with a NULL ctx for PERM_ROOT,
+ PERM_SUDOERS and PERM_TIMESTAMP.
+ [0ec4b81df902]
+
+2023-08-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/set_perms.c:
+ set_perms: ctx may be NULL for PERM_ROOT, PERM_SUDOERS,
+ PERM_TIMESTAMP.
+ [299c5cacb05a]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/iolog_path_escapes.c,
+ plugins/sudoers/logging.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/sudoers_ctx_free.c:
+ Move a few fields from sudoers_user_contect to sudoers_context.
+
+ They are not really specific to the user or user-specified.
+ [0e166cff8c3b]
+
+ * plugins/sudoers/policy.c:
+ Remove dead code dealing with unknown user and MODE_INVALIDATE.
+
+ The timestamp unlink code does not need the user's struct passwd
+ pointer, just the user name (which we already have). Found by PVS-
+ Studio.
+ [dd41395692e5]
+
+ * lib/iolog/iolog_read.c, lib/iolog/iolog_write.c,
+ lib/util/sudo_dso.c:
+ Suppress some other PVS-Studio false positives.
+ [36d0f8d41e6e]
+
+ * plugins/sudoers/set_perms.c:
+ Quiet a PVS-Studio false positive about possible NULL dereference.
+
+ set_perms() is only called with a NULL ctx for PERM_ROOT,
+ PERM_SUDOERS and PERM_TIMESTAMP.
+ [a6f38a82c80c]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.h:
+ MODE_KILL is never set in the sudoers plugin, remove it.
+ [5a64ba098c4f]
+
+ * plugins/sample/sample_plugin.c, plugins/sudoers/editor.c,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoreplay.c, src/exec_ptrace.c:
+ Cast int to size_t before adding instead of casting the result.
+
+ Quiets PVS-Studio warning V1028.
+ [39b9d54ae277]
+
+ * plugins/sudoers/audit.c:
+ Fix log_server_accept() definition for --disable-log-client builds.
+ [9ef55e556801]
+
+ * src/exec_pty.c:
+ Use a global static struct exec_closure for the cleanup hook.
+
+ This is safer than storing a pointer to a stack variable in the
+ cleanup function since we don't need to worry about it ever going
+ out of scope. Quiets a clang 15 analyzer warning.
+ [bfb06721d43f]
+
+ * lib/eventlog/eventlog.c, plugins/sudoers/testsudoers.c:
+ Eliminate some clang analyzer false positives.
+ [ded09455af48]
+
+ * plugins/sudoers/logging.c:
+ Plug memory leak if journal_parse_error() fails.
+
+ Found by the clang 15 analyzer.
+ [0d7e0567187e]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Move sudoedit_nfiles into struct sudoers_context.
+ [0f67b3c5c5b2]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/check.c, plugins/sudoers/env.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/lookup.c, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c:
+ Move sudo_mode into struct sudoers_context.
+ [649e74125300]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoers_ctx_free.c:
+ Move NewArgv, NewArgc and saved_argv into struct sudoers_context.
+ [46db0662eaf7]
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/file.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.h, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Add struct sudoers_conf to struct sudoers_plugin_context.
+
+ There's now no need to pass this directly to init_parser() since we
+ already pass in a pointer to a sudoers_context struct.
+ [4a60e7b19a1a]
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/ldap_conf.c,
+ plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c,
+ plugins/sudoers/sudo_ldap_conf.h, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c:
+ Store policy paths in struct sudoers_context.
+
+ This removes the need for the getters in policy.c.
+ [8ff3016dc8ad]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/stubs.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoers_ctx_free.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Add sudoers_ctx_free() and use it for freeing struct sudoers
+ context.
+
+ This replaces sudoers_user_ctx_free() and sudoers_runas_ctx_free().
+ [ba25344753c3]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/auth/afs.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h, plugins/sudoers/callbacks.c,
+ plugins/sudoers/check.c, plugins/sudoers/check.h,
+ plugins/sudoers/check_aliases.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers.h, plugins/sudoers/cvtsudoers_pwutil.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/display.c, plugins/sudoers/env.c,
+ plugins/sudoers/file.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_path_escapes.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/locale.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/lookup.c, plugins/sudoers/match.c,
+ plugins/sudoers/match_command.c, plugins/sudoers/parse.h,
+ plugins/sudoers/policy.c, plugins/sudoers/prompt.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/pwutil.h,
+ plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/regress/exptilde/check_exptilde.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_stubs.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/solaris_audit.c,
+ plugins/sudoers/solaris_audit.h, plugins/sudoers/sssd.c,
+ plugins/sudoers/stubs.c, plugins/sudoers/sudo_nss.h,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/testsudoers_pwutil.h,
+ plugins/sudoers/timestamp.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.h, plugins/sudoers/toke.l,
+ plugins/sudoers/visudo.c:
+ Make struct sudoers_context private to sudoers.c.
+
+ We now pass a pointer to the context where necessary. There are a
+ few cases where we need to request the context from sudoers via
+ sudoers_get_context() for the plugin API functions. If the plugin
+ API was able to pass around a closure pointer this would not be
+ necessary.
+ [534d55781084]
+
+2023-08-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/audit.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/passwd.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/callbacks.c,
+ plugins/sudoers/check.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/display.c,
+ plugins/sudoers/env.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/iolog_path_escapes.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/logging.c, plugins/sudoers/lookup.c,
+ plugins/sudoers/match.c, plugins/sudoers/match_command.c,
+ plugins/sudoers/policy.c, plugins/sudoers/prompt.c,
+ plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/regress/exptilde/check_exptilde.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/solaris_audit.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/stubs.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/visudo.c:
+ Add a sudoers_context struct that embeds the user and runas structs.
+ [7c72e0c26dc0]
+
+2023-08-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ free_parse_tree: clear the nss pointer when freeing.
+ [658fef1bd3c0]
+
+ * plugins/sudoers/parse_ldif.c:
+ sudoers_parse_ldif: do not free parse_tree before using
+
+ The user is expected to pass in an initialized and empty parse_tree
+ so there is no need to free it first.
+ [4d6371e98087]
+
+ * lib/zlib/adler32.c, lib/zlib/compress.c, lib/zlib/crc32.c,
+ lib/zlib/deflate.c, lib/zlib/deflate.h, lib/zlib/gzclose.c,
+ lib/zlib/gzguts.h, lib/zlib/gzlib.c, lib/zlib/gzread.c,
+ lib/zlib/gzwrite.c, lib/zlib/infback.c, lib/zlib/inffast.c,
+ lib/zlib/inffast.h, lib/zlib/inflate.c, lib/zlib/inftrees.c,
+ lib/zlib/inftrees.h, lib/zlib/trees.c, lib/zlib/uncompr.c,
+ lib/zlib/zconf.h.in, lib/zlib/zlib.h, lib/zlib/zutil.c,
+ lib/zlib/zutil.h:
+ Update embedded copy of zlib to version 1.3.
+ [bfd6de199f8a]
+
+2023-08-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/pwutil_impl.c:
+ We still need to clamp ngids if getgrouplist2() returns -1.
+
+ Otherwise, we end up with ngids set to the number of gids the user
+ belongs to which may be larger than what the front-end specified.
+ Fixes a regression introduced in the last commit here.
+ [4a2aeaf67236]
+
+2023-08-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/policy.c:
+ No need to clear errno when using sudo_strtonum().
+ [f62f2580c6a5]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/pwutil_impl.c, plugins/sudoers/sudoers.h:
+ Move max_groups out of sudoers_user_context and into pwutil.c.
+
+ It is only used by the local password pwutil implementation.
+ [c33497cc3291]
+
+ * plugins/sudoers/check_util.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c:
+ Pass in directory to check_user_runchroot() and check_user_runcwd().
+
+ This way we do not rely on the runas_ctx global.
+ [f70888bdedf6]
+
+ * plugins/sudoers/regress/exptilde/check_exptilde.c:
+ check_exptilde: don't need runas_ctx here
+ [520483cdb2ae]
+
+ * plugins/sudoers/match.c, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c:
+ Move RUNAS_{USER,GROUP}_SPECIFIED flags into struct
+ sudoers_runas_context.
+ [2024629414ed]
+
+2023-08-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/group_plugin.c, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c:
+ Make path_plugin_dir private to policy.c and add getter.
+ [2bf12c839083]
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/logging.c, plugins/sudoers/lookup.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Move list_pw global into struct runas_context.
+ [32faa515c324]
+
+2023-08-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/bsdauth.c, plugins/sudoers/callbacks.c,
+ plugins/sudoers/check.c, plugins/sudoers/check_util.c,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/display.c,
+ plugins/sudoers/env.c, plugins/sudoers/iolog_path_escapes.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/logging.c,
+ plugins/sudoers/lookup.c, plugins/sudoers/match.c,
+ plugins/sudoers/match_command.c, plugins/sudoers/policy.c,
+ plugins/sudoers/prompt.c,
+ plugins/sudoers/regress/exptilde/check_exptilde.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/stubs.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c:
+ Add struct sudoers_runas_context and move runas-specific bits into
+ it.
+ [d6a5f5b3c136]
+
+ * plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/callbacks.c, plugins/sudoers/check.c,
+ plugins/sudoers/check_util.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/display.c, plugins/sudoers/env.c,
+ plugins/sudoers/fmtsudoers.c, plugins/sudoers/iolog_path_escapes.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/logging.c,
+ plugins/sudoers/lookup.c, plugins/sudoers/match.c,
+ plugins/sudoers/match_command.c, plugins/sudoers/policy.c,
+ plugins/sudoers/prompt.c, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/solaris_audit.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/stubs.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/visudo.c:
+ Expand the user_* (and more) macros to user_ctx.foo.
+ [b62e24d53e3f]
+
+ * plugins/sudoers/check.h, plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/timestamp.c:
+ Pass explicit struct passwd * to create_admin_success_flag().
+ [120bb08f53bb]
+
+ * plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Make sudoers_user_ctx_free() private to sudoers.c
+ [ed512916a444]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/callbacks.c,
+ plugins/sudoers/check.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/display.c,
+ plugins/sudoers/logging.c, plugins/sudoers/lookup.c,
+ plugins/sudoers/match.c, plugins/sudoers/policy.c,
+ plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/regress/exptilde/check_exptilde.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timestamp.c, plugins/sudoers/visudo.c:
+ Rename struct sudo_user -> struct sudo_user_context.
+
+ Also rename the sudo_user global to user_ctx.
+ [d4b68657a430]
+
+ * src/exec.c:
+ fd_matches_tty: only zero out fd_sb if fstat(2) fails.
+
+ We need to preserve the contents of the struct stat if the fd is
+ some other type so the check for piped output works correctly. Bug
+ #1057
+ [ac80d75699d1]
+
+2023-08-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/callbacks.c:
+ Leave the I/O log callbacks in iolog.c
+
+ Otherwise, check_iolog_plugin will not link.
+ [4e2304f22e89]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/callbacks.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c:
+ Move sudoers parser callbacks to callbacks.c.
+ [396d1dcdb35a]
+
+2023-08-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/sendlog.c:
+ Bump info_msgs_size to make room for the source.
+ [627f659fc180]
+
+ * .circleci/config.yml:
+ Update Xcode version from 13.2.1 to 13.4.1.
+ [6c32e86975be]
+
+ * include/sudo_event.h, lib/util/event.c, lib/util/event_poll.c,
+ lib/util/event_select.c, lib/util/util.exp.in:
+ Use int, not short for events in the event API.
+
+ This fixes some -Wconversion warnings and fixes an inconsistency
+ between the libsudo_util event API and the plugin event API. The
+ actual struct internals still use shorts to avoid changing the ABI.
+ [2d7fcd66f7e7]
+
+ * plugins/sudoers/display.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/fmtsudoers_cvt.c, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/testsudoers.c:
+ Use const pointers where possible in the display code.
+ [87fd1def96b6]
+
+ * docs/sudo.man.in, docs/sudo.mdoc.in:
+ Document "sudo -ll command" output.
+ [3e837165e978]
+
+ * plugins/sudoers/display.c, plugins/sudoers/lookup.c,
+ plugins/sudoers/parse.h, plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/testsudoers.c:
+ Add verbose version of "sudo -l command" by using an extra -l.
+
+ The output of "sudo -ll command" consists of the matching sudoers
+ rule (in long form) with the addition of a "Matched" entry that
+ shows the fully-qualfied path along with any arguments.
+ [038d8555e50c]
+
+ * plugins/sudoers/display.c:
+ Move code to display a cmndspec in long form to
+ display_cmndspec_long().
+ [a9887101de7c]
+
+ * plugins/sudoers/display.c:
+ sudo -ll: display the sudoers file the rule came from.
+ [ca6d31966f5c]
+
+2023-08-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/ssl_compat/ssl_compat.c, logsrvd/logsrvd.c,
+ logsrvd/logsrvd_relay.c, logsrvd/sendlog.c,
+ plugins/sudoers/log_client.c:
+ Fix checking of SSL_{read,write}_ex() return value.
+
+ These have a boolean-style return value. However, our emulated
+ versions can return -1 on error, which we need to preserve for older
+ versions of SSL_get_error() which expect it.
+ [4e812f2456f1]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/log_client.c,
+ plugins/sudoers/logging.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Store the source of the matching rule and store in the event log.
+
+ The JSON logs will store the matching rule source.
+ [c7ee4ab87610]
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c,
+ lib/eventlog/eventlog_free.c, lib/eventlog/parse_json.c,
+ lib/eventlog/regress/eventlog_store/test1.json.in,
+ lib/eventlog/regress/eventlog_store/test1.json.out.ok,
+ lib/eventlog/regress/eventlog_store/test2.json.in,
+ lib/eventlog/regress/eventlog_store/test2.json.out.ok,
+ lib/eventlog/regress/eventlog_store/test3.json.in,
+ lib/eventlog/regress/eventlog_store/test3.json.out.ok,
+ lib/eventlog/regress/eventlog_store/test4.json.in,
+ lib/eventlog/regress/eventlog_store/test4.json.out.ok,
+ logsrvd/iolog_writer.c, logsrvd/sendlog.c:
+ Log source in JSON logs
+
+ This makes it possible to tell which rule resulted in a match.
+ [a2573ce8ce3f]
+
+2023-08-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/lookup.c, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/testsudoers.c:
+ Use a single callback for sudoers_lookup() and add a closure
+ pointer.
+
+ The single callback now receives all the match info (or UNSPEC if no
+ match was attempted). This makes it possible to use the callback for
+ more than just printing testsudoers output.
+ [547d0256f22a]
+
+ * lib/util/regress/digest/digest_test.c:
+ Fix printf format string mismatch now that 'i' is size_t.
+ [366084860303]
+
+ * include/sudo_digest.h, lib/util/digest.c, lib/util/digest_gcrypt.c,
+ lib/util/digest_openssl.c, lib/util/getentropy.c,
+ lib/util/regress/digest/digest_test.c, lib/util/util.exp.in,
+ plugins/sudoers/filedigest.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l:
+ sudo_digest_getlen: return size_t, and 0 on error instead of -1
+
+ This is an API change, sudo_digest_getlen_v1 remains for binary
+ compatibility.
+ [5866df2f4aab]
+
+ * logsrvd/logsrvd_relay.c, logsrvd/sendlog.c,
+ plugins/sudoers/log_client.c:
+ ERR_get_error() returns unsigned long, not int.
+ [94b2d963f279]
+
+ * plugins/sudoers/log_client.c:
+ We now must pass "err" SSL_get_error(), not "nread".
+ [b4cc206a2cf8]
+
+2023-08-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/hostcheck.h, lib/iolog/hostcheck.c:
+ Move compat definition of ASN1_STRING_get0_data to hostcheck.c. It
+ is not used anywhere else.
+ [39984513eb00]
+
+2023-08-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/hostcheck.h, include/sudo_compat.h,
+ include/sudo_ssl_compat.h:
+ Move OpenSSL compat defines to sudo_ssl_compat.h
+ [ad6b8bc3f054]
+
+ * MANIFEST, Makefile.in, configure, configure.ac,
+ include/sudo_ssl_compat.h, lib/ssl_compat/Makefile.in,
+ lib/ssl_compat/ssl_compat.c, logsrvd/Makefile.in,
+ logsrvd/tls_common.h, m4/openssl.m4, plugins/sudoers/Makefile.in,
+ plugins/sudoers/log_client.h, src/Makefile.in:
+ Add implementation of SSL_read_ex/SSL_write_ex for those without.
+ [9456c3c5c91c]
+
+ * config.h.in, configure, logsrvd/logsrvd.c, logsrvd/logsrvd_relay.c,
+ logsrvd/sendlog.c, m4/openssl.m4, plugins/sudoers/log_client.c:
+ Use SSL_read_ex() and SSL_write_ex() instead of SSL_read() and
+ SSL_write().
+ [5ac82bf78109]
+
+2023-08-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * etc/sudo-logsrvd.pp, etc/sudo-python.pp, etc/sudo.pp:
+ Don't use sudo when building AIX packages
+
+ PolyPkg uses "sudo installp -l" to list the built package by default
+ but we may not have sudo privileges on the build host.
+ [e8ed6064193d]
+
+ * scripts/mkpkg:
+ Add --configure-only option to quit after the configure run.
+
+ This will be used to avoid building the entire package when we just
+ want the 32 or 64 bit sudo_intercept.so and sudo_noexec.so.
+ [22c7cec5a6a1]
+
+ * scripts/mkpkg:
+ Parse --disable-python in mkpkg and don't override -m32 for Solaris.
+
+ We want to be able to build without python and to specify the memory
+ model when building 32-bit .so's for Solaris.
+ [bf21f6e67ff5]
+
+2023-07-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * INSTALL.md, Makefile.in, configure, configure.ac:
+ Add --enable-postinstall, an optional phase when building packages.
+
+ This makes it possible to run an arbitrary script between "make
+ install" and the polypkg run. This will be used to copy different
+ word size versions of sudo_intercept.so and sudo_noexec.so.
+ [d4e84fa16ccf]
+
+ * INSTALL.md, config.h.in, configure, configure.ac,
+ docs/sudo.conf.man.in, docs/sudo.conf.mdoc.in, src/exec_preload.c:
+ Add basic support for 32-bit and 64-bit LD_PRELOAD equivalents.
+
+ The noexec and intercept DSO settings may now include both a 32-bit
+ DSO and a 64-bit DSO specified by a colon. For example: /usr/libexe
+ c/sudo/sudo_intercept.so:/usr/libexec/sudo/sudo_intercept_64.so.
+ [9489d8625acb]
+
+ * lib/util/term.c, src/exec_pty.c:
+ Cast TIOCSWINSZ to int to avoid overflow warning on 64-bit AIX.
+ [20919db351c1]
+
+2023-07-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sudo_intercept_common.c:
+ Read path section of sudo.conf for sudo_conf_intercept_path().
+ [d5748f68b9cb]
+
+2023-07-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/visudo.man.in, docs/visudo.mdoc.in:
+ visudo: document that a new file is only created if the editor
+ writes it.
+
+ If visudo is used to create a new file, the file will only be
+ created if the user writes to the file via the editor. Simply
+ running visudo and exiting the editor will no longer cause the file
+ to be created. There is an exception for file created due to the
+ addition of a @include directive, which need to be present for the
+ sudoers file to parse properly. GitHub issue #294.
+ [21e4d5cc5f43]
+
+ * plugins/sudoers/visudo.c:
+ visudo: do not create a new file if the user made no changes
+
+ This prevents visudo from creating a new zero-length sudoers file if
+ the user exited the editor without making any changes. Files created
+ via a @include directive are preserved, even if empty, to avoid a
+ parse error. GitHub issue #294.
+ [4f086bb7ecdd]
+
+ * README.md, docs/CONTRIBUTING.md:
+ Make the sections on bug reporting consistent with each other.
+
+ GitHub issue #292
+ [d02253b4533d]
+
+2023-07-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec.c:
+ Remove unused variable introduced in last commit.
+ [94e0708ad331]
+
+ * src/exec.c, src/exec_nopty.c, src/exec_pty.c, src/sudo_exec.h:
+ Don't assume that if std{in,out,err} is a tty, it is the user's tty.
+
+ Previously, sudo only checked that the fd was a terminal, not that
+ it matched sudo's idea of the user's terminal. This matters when
+ input or output is redirected to a different terminal. In that case
+ we want to interpose the fd with a pipe even if it refers to a
+ terminal. Bug #1056.
+ [42838100b526]
+
+ * MANIFEST, plugins/sudoers/regress/testsudoers/test29.out.ok,
+ plugins/sudoers/regress/testsudoers/test29.sh,
+ plugins/sudoers/regress/testsudoers/test30.out.ok,
+ plugins/sudoers/regress/testsudoers/test30.sh,
+ plugins/sudoers/regress/testsudoers/test31.out.ok,
+ plugins/sudoers/regress/testsudoers/test31.sh:
+ testsudoers: add -L, -l and -v tests
+ [250e9abba14e]
+
+ * plugins/sudoers/regress/testsudoers/test1.out.ok,
+ plugins/sudoers/regress/testsudoers/test10.out.ok,
+ plugins/sudoers/regress/testsudoers/test11.out.ok,
+ plugins/sudoers/regress/testsudoers/test15.out.ok,
+ plugins/sudoers/regress/testsudoers/test16.out.ok,
+ plugins/sudoers/regress/testsudoers/test17.out.ok,
+ plugins/sudoers/regress/testsudoers/test18.out.ok,
+ plugins/sudoers/regress/testsudoers/test19.out.ok,
+ plugins/sudoers/regress/testsudoers/test2.out.ok,
+ plugins/sudoers/regress/testsudoers/test20.out.ok,
+ plugins/sudoers/regress/testsudoers/test21.out.ok,
+ plugins/sudoers/regress/testsudoers/test22.out.ok,
+ plugins/sudoers/regress/testsudoers/test23.out.ok,
+ plugins/sudoers/regress/testsudoers/test24.out.ok,
+ plugins/sudoers/regress/testsudoers/test25.out.ok,
+ plugins/sudoers/regress/testsudoers/test26.out.ok,
+ plugins/sudoers/regress/testsudoers/test27.out.ok,
+ plugins/sudoers/regress/testsudoers/test28.out.ok,
+ plugins/sudoers/regress/testsudoers/test3.out.ok,
+ plugins/sudoers/regress/testsudoers/test4.out.ok,
+ plugins/sudoers/regress/testsudoers/test5.out.ok,
+ plugins/sudoers/regress/testsudoers/test6.out.ok,
+ plugins/sudoers/regress/testsudoers/test7.out.ok,
+ plugins/sudoers/regress/testsudoers/test8.out.ok,
+ plugins/sudoers/regress/testsudoers/test9.out.ok,
+ plugins/sudoers/testsudoers.c:
+ testsudoers: display when a password is required
+ [bf540275b47d]
+
+ * plugins/sudoers/testsudoers.c:
+ testsudoers: add -L, -l and -v options.
+
+ This makes it possible to test "sudo -l" and "sudo -v" using
+ testsudoers.
+ [871563fd71f0]
+
+2023-07-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/lookup.c:
+ sudoers_lookup_pseudo: sync with sudoers_lookup_check
+
+ This makes sudoers_lookup_pseudo(), which is used for pseudo-command
+ like "list" and "validate" a bit more like sudoers_lookup_check().
+ Time of day checks are performed, and callbacks are supported. We
+ cannot use the same code for regular commands and pseudo-commands
+ due to the "pwcheck == all" case.
+ [534b5e02dc34]
+
+ * plugins/sudoers/logging.c:
+ Fix user warning message for "sudo -l command" when not allowed.
+ Reported by the sudo-rs project.
+
+ There was a missing space between "list" and the actual command.
+ This also changes the output to include the command as specified by
+ the user, not the path found in the path. Previously, if the command
+ did not exist it would not be included in the message.
+ [f509188ce041]
+
+ * plugins/python/python_convmessage.c,
+ plugins/python/python_loghandler.c,
+ plugins/python/python_plugin_common.c,
+ plugins/python/sudo_python_module.c,
+ plugins/python/sudo_python_module.h:
+ Add free function for sudo Python module.
+
+ This reduces the amount of memory leaked on unload.
+ [71e459d071be]
+
+2023-07-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_14p3 for changeset 6902151970b6
+ [0083fdf4fc08] <1.9>
+
+ * configure, configure.ac:
+ sudo 1.9.14p3
+ [6902151970b6] [SUDO_1_9_14p3] <1.9>
+
+ * NEWS:
+ Document bug fixes in 1.9.14p3.
+ [538b0d8db69d] <1.9>
+
+ * NEWS:
+ Document bug fixes in 1.9.14p3.
+ [01b3a5943678]
+
+ * plugins/python/python_loghandler.c,
+ plugins/python/python_plugin_common.c,
+ plugins/python/sudo_python_module.c,
+ plugins/python/sudo_python_module.h:
+ Merge sudo_module_register_loghandler and
+ sudo_module_set_default_loghandler.
+
+ We now create the LogHandler class for each interpreter in
+ python_plugin_init() instead of just once in sudo_module_init().
+ This fixes the crash seen in Py_EndInterpreter() with Python 3.12
+ and significantly reduces the number of leaked objects tracked by
+ MemorySanitizer.
+ [92156e042c81] <1.9>
+
+ * plugins/python/python_loghandler.c,
+ plugins/python/python_plugin_common.c,
+ plugins/python/sudo_python_module.c,
+ plugins/python/sudo_python_module.h:
+ Merge sudo_module_register_loghandler and
+ sudo_module_set_default_loghandler.
+
+ We now create the LogHandler class for each interpreter in
+ python_plugin_init() instead of just once in sudo_module_init().
+ This fixes the crash seen in Py_EndInterpreter() with Python 3.12
+ and significantly reduces the number of leaked objects tracked by
+ MemorySanitizer.
+ [d257e01240c1]
+
+ * plugins/python/python_convmessage.c:
+ sudo_module_register_conv_message: fix copy pasta in debug_decl
+ [de399cdf465c]
+
+2023-07-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/python_baseplugin.c,
+ plugins/python/python_convmessage.c,
+ plugins/python/python_loghandler.c,
+ plugins/python/sudo_python_module.c:
+ sudo_module_register_loghandler: clear sudo_type_LogHandler on error
+ Also add comments about PyModule_AddObject stealing a ref on
+ success.
+ [8f500926c894] <1.9>
+
+ * plugins/python/python_baseplugin.c,
+ plugins/python/python_convmessage.c,
+ plugins/python/python_loghandler.c,
+ plugins/python/sudo_python_module.c:
+ sudo_module_register_loghandler: clear sudo_type_LogHandler on error
+ Also add comments about PyModule_AddObject stealing a ref on
+ success.
+ [cd6ffb5ec1be]
+
+ * plugins/python/pyhelpers.c:
+ Use Py_XDECREF instead of manual NULL check + Py_DECREF
+ [9dababbb90ab]
+
+2023-07-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/python_loghandler.c:
+ Work around a crash with Python 3.12.
+
+ In sudo_module_set_default_loghandler() if we don't leak the
+ reference to py_loghandler we get a crash in Py_EndInterpreter()
+ with Python 3.12. This probably indicates a reference counting bug
+ elsewhere.
+ [77e8641b7b40] <1.9>
+
+ * plugins/python/python_loghandler.c:
+ Work around a crash with Python 3.12.
+
+ In sudo_module_set_default_loghandler() if we don't leak the
+ reference to py_loghandler we get a crash in Py_EndInterpreter()
+ with Python 3.12. This probably indicates a reference counting bug
+ elsewhere.
+ [89fb0311367c]
+
+ * plugins/python/regress/check_python_examples.c:
+ Unbuffer stdout so we don't miss output during a crash.
+ [07222dfccfe2]
+
+ * plugins/python/python_loghandler.c:
+ Use PyObject_CallNoArgs() where possible.
+ [abd4dcbee072] <1.9>
+
+ * plugins/python/python_loghandler.c:
+ Use PyObject_CallNoArgs() where possible.
+ [5a1bef07358a]
+
+ * plugins/python/python_convmessage.c,
+ plugins/python/python_loghandler.c,
+ plugins/python/sudo_python_module.h:
+ Make sudo_type_ConvMessage and sudo_type_LogHandler static.
+
+ They are not used outside their respective compilation units.
+ [c8dfb695dba1] <1.9>
+
+ * plugins/python/python_convmessage.c,
+ plugins/python/python_loghandler.c,
+ plugins/python/sudo_python_module.h:
+ Make sudo_type_ConvMessage and sudo_type_LogHandler static.
+
+ They are not used outside their respective compilation units.
+ [9ec37d3a2f64]
+
+2023-07-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/eventlog/Makefile.in, lib/iolog/Makefile.in,
+ lib/util/Makefile.in, plugins/python/Makefile.in,
+ plugins/sudoers/Makefile.in:
+ Pass TEST_VERBOSE to all test programs.
+ [39c17a66b02e]
+
+ * lib/iolog/regress/host_port/host_port_test.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/editor/check_editor.c,
+ plugins/sudoers/regress/env_match/check_env_pattern.c,
+ plugins/sudoers/regress/exptilde/check_exptilde.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/regress/parser/check_gentime.c,
+ plugins/sudoers/regress/serialize_list/check_serialize_list.c,
+ plugins/sudoers/regress/starttime/check_starttime.c,
+ plugins/sudoers/regress/unescape/check_unesc.c:
+ All test programs should accept the -v option, even if it is
+ ignored.
+ [d4cb95054f73]
+
+ * plugins/python/python_plugin_common.c:
+ Revert last change, wrong diff committed.
+ [d266c05853ce]
+
+ * plugins/python/regress/testhelpers.c:
+ Adapt to changed formatting of a rejected result in Python 3.12
+ [2f89b9e6a104] <1.9>
+
+ * plugins/python/regress/testhelpers.c:
+ Adapt to changed formatting of a rejected result in Python 3.12
+ [138957911238]
+
+ * plugins/python/python_plugin_common.c:
+ _python_plugin_new_interpreter switches to the new interpreter
+
+ No need to do PyThreadState_Swap in the caller.
+ [c848e20f3e93]
+
+ * plugins/python/example_audit_plugin.py, plugins/python/pyhelpers.c,
+ p
+ lugins/python/regress/testdata/check_example_audit_plugin_receives_a
+ ccept.stdout, plugins/python/regress/testdata/check_example_audit_pl
+ ugin_receives_error.stdout, plugins/python/regress/testdata/check_ex
+ ample_audit_plugin_receives_reject.stdout, plugins/python/regress/te
+ stdata/check_example_audit_plugin_version_display.stdout, plugins/py
+ thon/regress/testdata/check_example_audit_plugin_workflow_multiple.s
+ tdout, plugins/python/regress/testdata/check_example_debugging_c_cal
+ ls@diag.log, plugins/python/regress/testdata/check_example_debugging
+ _c_calls@info.log, plugins/python/regress/testdata/check_example_gro
+ up_plugin_is_able_to_debug.log, plugins/python/regress/testdata/chec
+ k_example_policy_plugin_validate_invalidate.log:
+ Remove trailing whitespace from test output.
+ [11db46e923fc] <1.9>
+
+ * plugins/python/example_audit_plugin.py, plugins/python/pyhelpers.c,
+ p
+ lugins/python/regress/testdata/check_example_audit_plugin_receives_a
+ ccept.stdout, plugins/python/regress/testdata/check_example_audit_pl
+ ugin_receives_error.stdout, plugins/python/regress/testdata/check_ex
+ ample_audit_plugin_receives_reject.stdout, plugins/python/regress/te
+ stdata/check_example_audit_plugin_version_display.stdout, plugins/py
+ thon/regress/testdata/check_example_audit_plugin_workflow_multiple.s
+ tdout, plugins/python/regress/testdata/check_example_debugging_c_cal
+ ls@diag.log, plugins/python/regress/testdata/check_example_debugging
+ _c_calls@info.log, plugins/python/regress/testdata/check_example_gro
+ up_plugin_is_able_to_debug.log, plugins/python/regress/testdata/chec
+ k_example_policy_plugin_validate_invalidate.log:
+ Remove trailing whitespace from test output.
+ [38f03683001d]
+
+2023-07-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/python_plugin_common.c:
+ We can rely on Py_FinalizeEx() to free sub-interpreters.
+ [0c84c411a6a0]
+
+ * plugins/python/python_plugin_common.c:
+ Call PyImport_AppendInittab after pre-initialization.
+
+ Also remove redundant PyConfig settings.
+ [e4f463e1094a]
+
+2023-07-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/python_plugin_common.c:
+ Use Py_InitializeFromConfig() not Py_InitializeEx() for Python >=
+ 3.8.
+
+ Avoids deprecation warnings on Python 3.12.
+ [99dc5948416d] <1.9>
+
+ * plugins/python/python_plugin_common.c:
+ Use Py_InitializeFromConfig() not Py_InitializeEx() for Python >=
+ 3.8.
+
+ Avoids deprecation warnings on Python 3.12.
+ [56e4c7111744]
+
+2023-07-18 Rose <83477269+AtariDreams@users.noreply.github.com>
+
+ * lib/eventlog/regress/logwrap/check_wrap.c, lib/util/glob.c,
+ lib/util/mksiglist.c, lib/util/mksigname.c,
+ lib/util/regress/glob/globtest.c, logsrvd/sendlog.c,
+ plugins/group_file/plugin_test.c,
+ plugins/python/regress/check_python_examples.c,
+ plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/tsdump.c:
+ Prefer fputs over fprintf where possible
+
+ fprintf does extra work and meant for formatting strings.
+ [c31cdbe6f23f]
+
+2023-07-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ The sudoers option is "use_pty", not "log_pty"
+
+ GitHub issue #291
+ [08b582beb2c9] <1.9>
+
+ * NEWS:
+ The sudoers option is "use_pty", not "log_pty"
+
+ GitHub issue #291
+ [31cf599c73d5]
+
+2023-07-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/term.c:
+ Quiet a warning false positive with older versions of gcc.
+ [8556d6c1cd37]
+
+ * plugins/sudoers/sudoers.c:
+ sudoers_check_common: MODE_PRESERVE_ENV is not valid with
+ MODE_CHECK.
+
+ We should only check for MODE_PRESERVE_ENV when running a command.
+ [8fc6f392cc43]
+
+2023-07-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_14p2 for changeset 47c0bf9a7ebb
+ [6bbe51d30496] <1.9>
+
+ * configure, configure.ac:
+ sudo 1.9.14p2
+ [47c0bf9a7ebb] [SUDO_1_9_14p2] <1.9>
+
+ * plugins/sudoers/match.c:
+ runas_userlist_matches: fix matching a Runas_Spec with an empty
+ runas user.
+
+ We should only match a rule with an empty runas user if a group was
+ specified on the command line (sudo -g) without a user (no -u
+ option) or the user specified their own name on the command line.
+ GitHub issue #290
+ [164428126ee6] <1.9>
+
+ * MANIFEST, plugins/sudoers/match.c,
+ plugins/sudoers/regress/testsudoers/test28.out.ok,
+ plugins/sudoers/regress/testsudoers/test28.sh:
+ runas_userlist_matches: fix matching a Runas_Spec with an empty
+ runas user.
+
+ We should only match a rule with an empty runas user if a group was
+ specified on the command line (sudo -g) without a user (no -u
+ option) or the user specified their own name on the command line.
+ GitHub issue #290
+ [ba9da369370e]
+
+2023-07-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Document bug fixes in 1.9.14p2.
+ [e5cd975816b8] <1.9>
+
+ * NEWS:
+ Document bug fixes in 1.9.14p2.
+ [cb5ece49ad53]
+
+ * src/exec_pty.c:
+ Pass SUDO_TERM_OFLAG to sudo_term_raw() when sudo output is piped.
+
+ This fixes a problem with "stair-stepped" output when the sudo-run
+ command's output is piped to another program and the command reads
+ input from the terminal.
+ [17009f9817b0] <1.9>
+
+ * src/exec_pty.c:
+ Pass SUDO_TERM_OFLAG to sudo_term_raw() when sudo output is piped.
+
+ This fixes a problem with "stair-stepped" output when the sudo-run
+ command's output is piped to another program and the command reads
+ input from the terminal.
+ [faa06b1e8913]
+
+ * src/exec_monitor.c, src/exec_pty.c:
+ Simplify the exec_monitor() foreground flag.
+
+ Add cmnd_foreground flag that is only true if sudo is the foreground
+ process and the CD_EXEC_BG flag is not set and pass it to
+ exec_monitor(). This means exec_monitor() no longer needs to check
+ for CD_EXEC_BG.
+ [6cc420fea368] <1.9>
+
+ * src/exec_monitor.c, src/exec_pty.c:
+ Simplify the exec_monitor() foreground flag.
+
+ Add cmnd_foreground flag that is only true if sudo is the foreground
+ process and the CD_EXEC_BG flag is not set and pass it to
+ exec_monitor(). This means exec_monitor() no longer needs to check
+ for CD_EXEC_BG.
+ [65ac52524254]
+
+ * include/sudo_util.h, lib/util/term.c, plugins/sudoers/sudoreplay.c:
+ sudo_term_raw: change the isig argument into a flags field
+
+ There are current two flags: SUDO_TERM_ISIG (enable terminal
+ signals) and SUDO_TERM_OFLAG (preserve output flags).
+ [15fdaae9fa3b] <1.9>
+
+ * include/sudo_util.h, lib/util/term.c, plugins/sudoers/sudoreplay.c:
+ sudo_term_raw: change the isig argument into a flags field
+
+ There are current two flags: SUDO_TERM_ISIG (enable terminal
+ signals) and SUDO_TERM_OFLAG (preserve output flags).
+ [09eced2fb202]
+
+2023-07-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.c:
+ Fix a crash in intercept mode running a command with NULL argv[0].
+
+ Newer Linux kernels replace a NULL argv[0] with the empty string, we
+ should as well.
+ [74e81e6d373a] <1.9>
+
+ * src/exec_ptrace.c:
+ Fix a crash in intercept mode running a command with NULL argv[0].
+
+ Newer Linux kernels replace a NULL argv[0] with the empty string, we
+ should as well.
+ [d1cb1882d7e8]
+
+ * src/conversation.c:
+ sudo_conversation_printf: simplify \n -> \r\n handling
+ [de2ddc08f262]
+
+ * src/conversation.c:
+ sudo_conversation: zero out reply even if no password is requested.
+
+ This avoids a potential invalid free in the err label and provides
+ more predictable behavior when mixing message types in a
+ conversation.
+ [79cc9efe3dbf]
+
+2023-07-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_14p1 for changeset fc033946b1a9
+ [ee6033290e91] <1.9>
+
+ * configure, configure.ac:
+ sudo 1.9.14p1
+ [fc033946b1a9] [SUDO_1_9_14p1] <1.9>
+
+ * NEWS:
+ Docume bug fixes in 1.9.14p1.
+ [f526fda905de] <1.9>
+
+ * NEWS:
+ Docume bug fixes in 1.9.14p1.
+ [7e4a4b7ed53b]
+
+ * plugins/sudoers/log_client.c:
+ fmt_info_messages: don't include ttyname if it is NULL
+
+ The NULL check was commented out for testing but should have been
+ restored. Fixes a potential protocol error message from
+ sudo_logsrvd.
+ [12cf2b87355a] <1.9>
+
+ * plugins/sudoers/log_client.c:
+ fmt_info_messages: don't include ttyname if it is NULL
+
+ The NULL check was commented out for testing but should have been
+ restored. Fixes a potential protocol error message from
+ sudo_logsrvd.
+ [c983428b3ad8]
+
+ * logsrvd/iolog_writer.c:
+ evlog_new: store a new copy of peeraddr, not a pointer to a buffer.
+
+ Starting in sudo 1.9.14, eventlog_free() will free the peeraddr
+ member too so it needs to be dynamically allocated.
+ [4c984e3e6aef] <1.9>
+
+ * logsrvd/iolog_writer.c:
+ evlog_new: store a new copy of peeraddr, not a pointer to a buffer.
+
+ Starting in sudo 1.9.14, eventlog_free() will free the peeraddr
+ member too so it needs to be dynamically allocated.
+ [846cf82b8eab]
+
+2023-07-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h,
+ lib/util/realpath.c:
+ realpath.c: include limits.h and use sysconf(_SC_SYMLOOP_MAX)
+
+ This is more portable and eliminates the need to check for
+ SYMLOOP_MAX (and provide it if missing) in configure. Also quiet
+ some -Wconversion warnings.
+ [beabc1e73e11]
+
+ * plugins/sudoers/ldap_conf.c:
+ sudo_krb5_ccname_path: avoid gcc false positive for ccname being
+ NULL
+
+ The callers all verify that they don't pass a NULL ccname so I'm not
+ sure how the compiler is getting confused (and why now?).
+ [93043879e7f2]
+
+ * include/sudo_debug.h:
+ Work around unused variable warning when fuzzing in enabled.
+ [ac4bd3bfeb71]
+
+ * plugins/sudoers/check_util.c,
+ plugins/sudoers/regress/testsudoers/test25.out.ok,
+ plugins/sudoers/regress/testsudoers/test25.sh,
+ plugins/sudoers/regress/testsudoers/test26.out.ok,
+ plugins/sudoers/regress/testsudoers/test26.sh:
+ Only allow the user to specify -D or -R for the special "*" value.
+
+ The sudoers file must now explicitly allow the user to specify a
+ directory (sudo -D) or chroot (sudo -R) by setting cwd or chroot to
+ "*". If a specific cwd or chroot value is set in sudoers, the user
+ may not use the -D or -R options, even if they match the value in
+ sudoers.
+ [790d60c6ed4b]
+
+ * docs/sudo_plugin.man.in, docs/sudo_plugin.mdoc.in:
+ Add restrict keyword to sudo_printf_t in plugin docs.
+ [46c15d2647cc]
+
+ * include/sudo_debug.h, lib/util/sudo_debug.c:
+ Convert sudo_debug_enter and sudo_debug_exit into macros.
+
+ In most cases, these simply expand to a call to
+ sudo_debug_printf2(). We need to keep the function versions around
+ in libsudo_util for backwards compatibility.
+ [b76b35e12afa]
+
+ * lib/util/sudo_debug.c:
+ Fix sudo_debug_exit_uint_v1 declaration for fuzzers.
+ [d4edc2fb3299]
+
+ * lib/util/sudo_debug.c:
+ Add missing sudo_debug_exit_uint_v1 stub for fuzzers.
+ [71a4a37fbc90]
+
+ * src/conversation.c, src/edit_open.c, src/exec_common.c,
+ src/parse_args.c, src/selinux.c, src/sesh.c, src/sudo.c, src/sudo.h,
+ src/sudo_edit.h, src/sudo_exec.h, src/tgetpass.c:
+ sudo frontend: make more bit flags unsigned.
+ [f353bc889b26]
+
+ * plugins/sudoers/auth/API, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h, plugins/sudoers/check.c,
+ plugins/sudoers/check.h, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers.h, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h, plugins/sudoers/lookup.c,
+ plugins/sudoers/parse.h, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c:
+ sudoers plugin: make more bit flags unsigned.
+ [77a583ebe2e7]
+
+ * include/sudo_debug.h, include/sudo_event.h, lib/util/event.c,
+ lib/util/event_poll.c, lib/util/event_select.c,
+ lib/util/sudo_debug.c, lib/util/util.exp.in:
+ libsudo_util: make more bit flags unsigned.
+ [005d0be694f5]
+
+2023-07-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/timeout.c:
+ parse_timeout: move overflow check to the correct location
+
+ It was not covering all cases in its original location. Fixes oss-
+ fuzz issue 60454 with fuzz_sudoers.
+ [e40119f18e83]
+
+2023-07-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #287 from AtariDreams/restrict
+
+ Give every printf-like function restrict qualifiers
+ [4945ab27d6c4]
+
+ * src/exec_nopty.c, src/exec_pty.c, src/sudo_exec.h:
+ struct exec_closure: make rows and cols int, not short
+
+ There's no real space saved by using short and using int avoids a
+ few casts.
+ [8385add04ed2]
+
+ * plugins/sudoers/testsudoers.c:
+ testsudoers: avoid extern definitions where possible
+ [ef4bed9a6a41]
+
+ * include/sudo_json.h, include/sudo_lbuf.h, lib/util/closefrom.c,
+ lib/util/digest.c, lib/util/event_poll.c, lib/util/fatal.c,
+ lib/util/getentropy.c, lib/util/getgrouplist.c, lib/util/gidlist.c,
+ lib/util/json.c, lib/util/lbuf.c, lib/util/mkdir_parents.c,
+ lib/util/parseln.c, lib/util/regex.c,
+ lib/util/regress/fuzz/fuzz_sudo_conf.c,
+ lib/util/regress/hexchar/hexchar_test.c,
+ lib/util/regress/mktemp/mktemp_test.c,
+ lib/util/regress/strtofoo/strtoid_test.c, lib/util/secure_path.c,
+ lib/util/setgroups.c, lib/util/sig2str.c, lib/util/str2sig.c,
+ lib/util/strlcat.c, lib/util/strlcpy.c, lib/util/strtoid.c,
+ lib/util/strtonum.c, lib/util/sudo_conf.c, lib/util/sudo_debug.c,
+ lib/util/ttysize.c:
+ libsudo_util: silence most -Wconversion warnings.
+ [420705f9796a]
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c,
+ lib/eventlog/eventlog_conf.c, lib/eventlog/logwrap.c,
+ lib/eventlog/parse_json.c,
+ lib/eventlog/regress/eventlog_store/store_json_test.c,
+ lib/eventlog/regress/eventlog_store/store_sudo_test.c,
+ lib/eventlog/regress/logwrap/check_wrap.c,
+ lib/eventlog/regress/parse_json/check_parse_json.c:
+ libevent: silence -Wconversion warnings.
+ [f00cb5679a19]
+
+ * lib/fuzzstub/fuzzstub.c:
+ libfuzzstub: silence -Wconversion warnings.
+ [164d2412d209]
+
+ * include/sudo_iolog.h, lib/iolog/hostcheck.c,
+ lib/iolog/iolog_filter.c, lib/iolog/iolog_legacy.c,
+ lib/iolog/iolog_mkdirs.c, lib/iolog/iolog_mkdtemp.c,
+ lib/iolog/iolog_read.c, lib/iolog/iolog_timing.c,
+ lib/iolog/iolog_write.c,
+ lib/iolog/regress/iolog_path/check_iolog_path.c,
+ lib/iolog/regress/iolog_timing/check_iolog_timing.c:
+ libiolog: silence -Wconversion warnings.
+ [d8c1a0869ef4]
+
+ * logsrvd/iolog_writer.c, logsrvd/logsrv_util.c, logsrvd/logsrvd.c,
+ logsrvd/logsrvd_conf.c, logsrvd/logsrvd_journal.c,
+ logsrvd/logsrvd_local.c, logsrvd/logsrvd_queue.c,
+ logsrvd/logsrvd_relay.c, logsrvd/regress/fuzz/fuzz_logsrvd_conf.c,
+ logsrvd/sendlog.c:
+ sudo_logsrvd: silence most -Wconversion warnings.
+ [bf3f40ec4645]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/b64_encode.c,
+ plugins/sudoers/check_aliases.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers.h, plugins/sudoers/cvtsudoers_csv.c,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/cvtsudoers_merge.c,
+ plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/defaults.h, plugins/sudoers/display.c,
+ plugins/sudoers/editor.c, plugins/sudoers/env.c,
+ plugins/sudoers/filedigest.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/fmtsudoers_cvt.c, plugins/sudoers/getdate.c,
+ plugins/sudoers/getdate.y, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_path_escapes.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/ldap_conf.c,
+ plugins/sudoers/ldap_innetgr.c, plugins/sudoers/ldap_util.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/log_client.c,
+ plugins/sudoers/logging.c, plugins/sudoers/match_addr.c,
+ plugins/sudoers/match_command.c, plugins/sudoers/parse.h,
+ plugins/sudoers/parse_ldif.c, plugins/sudoers/policy.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/starttime.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timeout.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.h,
+ plugins/sudoers/toke.l, plugins/sudoers/toke_util.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/visudo.c:
+ sudoers plugin: silence most -Wconversion warnings.
+ [074179cbc3a8]
+
+ * plugins/python/pyhelpers.c, plugins/python/python_convmessage.c,
+ plugins/python/regress/iohelpers.c,
+ plugins/python/regress/testhelpers.c,
+ plugins/python/sudo_python_module.c:
+ python plugin: silence -Wconversion warnings.
+ [a59d980f2793]
+
+ * plugins/sample/sample_plugin.c, src/conversation.c, src/copy_file.c,
+ src/env_hooks.c, src/exec.c, src/exec_common.c,
+ src/exec_intercept.c, src/exec_monitor.c, src/exec_nopty.c,
+ src/exec_preload.c, src/exec_ptrace.c, src/exec_pty.c,
+ src/net_ifs.c, src/parse_args.c, src/preserve_fds.c, src/sudo.c,
+ src/sudo.h, src/sudo_edit.c, src/sudo_exec.h, src/sudo_intercept.c,
+ src/sudo_intercept_common.c, src/tgetpass.c, src/ttyname.c:
+ sudo frontend: silence most -Wconversion warnings.
+ [0dbece7ccb47]
+
+ * config.h.in, configure, configure.ac:
+ Add configure check for restrict keyword.
+ [f02ab280d8df]
+
+ * plugins/sudoers/sudoers.c:
+ sudoers_check_common: remove extraneous return statement.
+ [0df4297873b9]
+
+2023-07-07 Rose <83477269+AtariDreams@users.noreply.github.com>
+
+ * include/sudo_compat.h, include/sudo_debug.h, include/sudo_fatal.h,
+ include/sudo_lbuf.h, include/sudo_plugin.h, include/sudo_util.h,
+ lib/eventlog/logwrap.c, lib/util/fatal.c, lib/util/inet_ntop.c,
+ lib/util/lbuf.c, lib/util/snprintf.c, lib/util/strlcat.c,
+ lib/util/strlcpy.c, lib/util/sudo_debug.c, lib/util/ttyname_dev.c,
+ logsrvd/iolog_writer.c, logsrvd/logsrvd_journal.c,
+ plugins/audit_json/audit_json.c, plugins/group_file/plugin_test.c,
+ plugins/python/pyhelpers.c, plugins/python/regress/iohelpers.c,
+ plugins/python/regress/iohelpers.h,
+ plugins/python/regress/testhelpers.c,
+ plugins/python/regress/testhelpers.h, plugins/sudoers/audit.c,
+ plugins/sudoers/check_aliases.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers.h, plugins/sudoers/cvtsudoers_csv.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/ldap_util.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/parse.h, plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/sudo_ldap.h, plugins/sudoers/sudo_printf.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ src/conversation.c, src/exec_preload.c, src/parse_args.c,
+ src/sudo_plugin_int.h:
+ Give every printf-like function restrict qualifiers
+
+ The format value has to be a string literal, every time.
+
+ Otherwise, you are not using these functions correctly. To reinforce
+ this fact, I putrestrict over every non-contrib example of this I
+ could find.
+ [e0f8bc0d596a]
+
+2023-07-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_digest.h, lib/util/digest.c, lib/util/digest_gcrypt.c,
+ lib/util/digest_openssl.c, lib/util/regress/digest/digest_test.c:
+ Make the remaining instances of digest_type unsigned.
+ [409adc30cce2]
+
+2023-07-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog_path_escapes.c:
+ Copy, don't append group ID in fill_group() and fill_runas_group()
+
+ This only affects the case where a group ID cannot be resolved.
+ [74cc29b9f7f0]
+
+ * lib/iolog/Makefile.in:
+ Remove regress corpus directories correctly
+ [406b862a7f2f]
+
+ * include/sudo_debug.h, include/sudo_util.h, lib/util/strtomode.c,
+ lib/util/sudo_debug.c, lib/util/util.exp.in:
+ Change sudo_strtomode() to return mode_t.
+ [5dc42fb5c2ad]
+
+2023-07-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/sudoreplay.c:
+ Rename print_usage() to display_usage()
+ [9e8390bb1ed0]
+
+ * logsrvd/logsrvd.c, logsrvd/sendlog.c:
+ Move display of usage text into display_usage() so usage() always
+ exits.
+ [ded72aceb6f4]
+
+ * lib/util/parseln.c, logsrvd/logsrvd_journal.c:
+ Fix some indentation.
+ [bb84e5596d9c]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers.h, plugins/sudoers/testsudoers.c:
+ Include testsudoers_pwutil.h for testsudoers_pwutil.c prototypes.
+ [8f494aca5cd9]
+
+ * MANIFEST, plugins/sudoers/Makefile.in,
+ plugins/sudoers/pwutil_impl.c, plugins/sudoers/testsudoers_pwutil.c,
+ plugins/sudoers/testsudoers_pwutil.h, plugins/sudoers/tsgetgrpw.c,
+ plugins/sudoers/tsgetgrpw.h:
+ Fix wrapping of libc getpwnam/getpwuid/getgrnam/getgrgid on NetBSD.
+ [be23d201add2]
+
+ * MANIFEST, aclocal.m4, config.h.in, configure, configure.ac,
+ lib/util/roundup.c, m4/ax_gcc_builtin.m4:
+ Add configure tests for __builtin_clz/__builtin_clzl
+ [d7b341700a0a]
+
+ * lib/util/roundup.c:
+ Add fallback for compilers without __builtin_clz/__builtin_clzl
+ [d9f23c7a8fc0]
+
+ * lib/util/roundup.c:
+ sudo_pow2_roundup: fix 64-bit version when shifting 31 or more
+ places
+
+ Shift 1UL instead of 1 to avoid overflowing an int.
+ [4d45af829af0]
+
+ * Merge pull request #286 from AtariDreams/one-more
+
+ Optimize sudo_pow2_roundup_v1
+ [5cff0594a45c]
+
+2023-07-03 Rose <83477269+AtariDreams@users.noreply.github.com>
+
+ * lib/util/roundup.c:
+ Optimize sudo_pow2_roundup_v1
+
+ No need to call sudo_pow2_roundup_v2.
+ [0bcd411174c0]
+
+2023-07-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/roundup.c:
+ Merge pull request #285 from AtariDreams/bug
+
+ Remove comment about algorithm being from bit-twiddling hacks
+ [869552550451]
+
+2023-07-03 Rose <83477269+AtariDreams@users.noreply.github.com>
+
+ * lib/util/roundup.c:
+ Remove comment about algorithm being from bit-twiddling hacks
+
+ Said comment no longer applies.
+ [e2fc0106c79f]
+
+2023-07-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #284 from AtariDreams/fix
+
+ Fix fuzzing errors
+ [4abff6645036]
+
+ * Merge pull request #283 from AtariDreams/bug
+
+ Fixed even more signedness and conversion issues
+ [bbf1887a5132]
+
+2023-07-03 Rose <83477269+AtariDreams@users.noreply.github.com>
+
+ * lib/util/parseln.c, lib/util/roundup.c, logsrvd/logsrvd_journal.c:
+ Fix fuzzing errors
+
+ We should be checking for integer overflow, rather than checking if
+ size is 0.
+
+ Additionally, we should set errno to ENOMEM when this overflow
+ happens.
+
+ Finally, the most efficient implementation of the round-up-to-2
+ algorithm involves the clz intrinsic.
+ [db08a808004d]
+
+2023-07-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/lbuf.c:
+ sudo_lbuf_expand: limit allocation to UINT_MAX
+ [1cb5a458baaa]
+
+ * lib/util/parseln.c:
+ sudo_parseln: use sudo_pow2_roundup() instead of hand-rolling it.
+ [0582d18df65a]
+
+ * logsrvd/logsrv_util.c, logsrvd/logsrv_util.h, logsrvd/logsrvd.c,
+ logsrvd/logsrvd_relay.c, logsrvd/sendlog.c,
+ plugins/sudoers/log_client.c, plugins/sudoers/log_client.h:
+ Promote length/size/offset in struct connection_buffer to size_t.
+ [5e5a2a39c8e5]
+
+ * include/sudo_util.h, lib/util/lbuf.c, lib/util/roundup.c,
+ lib/util/util.exp.in, logsrvd/logsrv_util.c, logsrvd/logsrvd.c,
+ plugins/sudoers/log_client.c:
+ Make sudo_pow2_roundup() operate on size_t.
+ [cbae7a651a94]
+
+2023-07-03 Rose <83477269+AtariDreams@users.noreply.github.com>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/timestamp.c, plugins/sudoers/tsgetgrpw.c,
+ src/sudo.c:
+ Fixed even more signedness and conversion issues
+
+ This should be the last of them.
+ [ccd65d72c6ac]
+
+2023-07-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_debug.h, lib/util/sudo_debug.c,
+ plugins/python/pyhelpers.c, plugins/python/pyhelpers.h,
+ plugins/python/python_loghandler.c,
+ plugins/python/sudo_python_debug.c,
+ plugins/python/sudo_python_debug.h:
+ Make the debug subsystem unsigned.
+
+ It was already unsigned in sudoers but not in the front-end or the
+ python plugin. Making this consistent resolves a lot of -Wconversion
+ warnings. Also clean up some other -Wconversion warnings in
+ sudo_debug.c.
+ [c6d20404141c]
+
+ * lib/eventlog/eventlog.c,
+ lib/eventlog/regress/eventlog_store/store_json_test.c,
+ lib/eventlog/regress/eventlog_store/store_sudo_test.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ src/exec_monitor.c, src/sudo.c:
+ Fix up indentation.
+ [d4ed4eaf46bd]
+
+ * Merge pull request #280 from AtariDreams/bug
+
+ Mark functions not returning as sudo_noreturn
+ [eaa69a6d85c6]
+
+2023-07-01 Rose <83477269+AtariDreams@users.noreply.github.com>
+
+ * lib/eventlog/eventlog.c,
+ lib/eventlog/regress/eventlog_store/store_json_test.c,
+ lib/eventlog/regress/eventlog_store/store_sudo_test.c,
+ lib/eventlog/regress/logwrap/check_wrap.c,
+ lib/eventlog/regress/parse_json/check_parse_json.c,
+ lib/iolog/regress/iolog_path/check_iolog_path.c,
+ lib/util/regress/hexchar/hexchar_test.c,
+ lib/util/regress/strsplit/strsplit_test.c,
+ lib/util/regress/sudo_conf/conf_test.c, logsrvd/logsrvd.c,
+ logsrvd/regress/logsrvd_conf/logsrvd_conf_test.c, logsrvd/sendlog.c,
+ plugins/group_file/plugin_test.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ src/exec_monitor.c, src/exec_nopty.c, src/exec_pty.c, src/sesh.c,
+ src/sudo.c:
+ Mark functions not returning as sudo_noreturn
+
+ We also put NOTREACHED where it applies.
+ [d688d55f3c4c]
+
+2023-07-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l, src/limits.c:
+ Avoid passing debug_return_size_t() a negative number.
+ [7876d918030c]
+
+ * Merge pull request #279 from AtariDreams/bison
+
+ Regenerate toke.c using updated flex
+ [3fc1517ec05d]
+
+2023-06-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/exptilde/check_exptilde.c,
+ plugins/sudoers/testsudoers.c:
+ Fix a few memory leaks in the tests.
+ [c76134b329b3]
+
+ * MANIFEST, plugins/sudoers/regress/testsudoers/group,
+ plugins/sudoers/regress/testsudoers/passwd,
+ plugins/sudoers/regress/testsudoers/test27.out.ok,
+ plugins/sudoers/regress/testsudoers/test27.sh,
+ plugins/sudoers/testsudoers.c:
+ Add test for runas_check_shell and check_user_shell()
+ [8e220e34840d]
+
+ * MANIFEST, plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/testsudoers/test25.out.ok,
+ plugins/sudoers/regress/testsudoers/test25.sh,
+ plugins/sudoers/regress/testsudoers/test26.out.ok,
+ plugins/sudoers/regress/testsudoers/test26.sh,
+ plugins/sudoers/testsudoers.c:
+ testsudoers: add -D and -R options to set cwd and chroot like sudo
+ [a34c5ca239ca]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/check.c,
+ plugins/sudoers/check_util.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Move check_user_* functions to check_util.c so testsudoers can use
+ them.
+ [109830a316ee]
+
+2023-06-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/testsudoers.c:
+ testsudoers: make lbuf private to dump_sudoers()
+
+ It is no longer used directly in main.
+ [c2c5e7b3db6b]
+
+ * plugins/sudoers/regress/testsudoers/test11.out.ok,
+ plugins/sudoers/regress/testsudoers/test4.out.ok,
+ plugins/sudoers/regress/testsudoers/test5.out.ok,
+ plugins/sudoers/testsudoers.c:
+ testsudoers: display "Parse error" if there was a parse error.
+
+ Previously, we just printed "Command unmatched" which makes it
+ harder to see that an error occurred.
+ [099360b56cc6]
+
+ * plugins/sudoers/regress/testsudoers/test1.out.ok,
+ plugins/sudoers/regress/testsudoers/test10.out.ok,
+ plugins/sudoers/regress/testsudoers/test15.out.ok,
+ plugins/sudoers/regress/testsudoers/test16.out.ok,
+ plugins/sudoers/regress/testsudoers/test17.out.ok,
+ plugins/sudoers/regress/testsudoers/test18.out.ok,
+ plugins/sudoers/regress/testsudoers/test19.out.ok,
+ plugins/sudoers/regress/testsudoers/test2.out.ok,
+ plugins/sudoers/regress/testsudoers/test20.out.ok,
+ plugins/sudoers/regress/testsudoers/test21.out.ok,
+ plugins/sudoers/regress/testsudoers/test22.out.ok,
+ plugins/sudoers/regress/testsudoers/test23.out.ok,
+ plugins/sudoers/regress/testsudoers/test24.out.ok,
+ plugins/sudoers/regress/testsudoers/test3.out.ok,
+ plugins/sudoers/regress/testsudoers/test6.out.ok,
+ plugins/sudoers/regress/testsudoers/test7.out.ok,
+ plugins/sudoers/regress/testsudoers/test8.out.ok,
+ plugins/sudoers/regress/testsudoers/test9.out.ok,
+ plugins/sudoers/testsudoers.c:
+ testsudoers: use allowed/denied/unmatched instead of just
+ matched/unmatched
+
+ This makes it possible to tell whether an entry was rejected due to
+ a negative match (explicitly denied) as opposed to a non-match. Also
+ fixes a bug where the runas status was only printed for positive
+ matches.
+ [3e9fc5fd7bb9]
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/testsudoers/test20.out.ok,
+ plugins/sudoers/testsudoers.c:
+ testsudoers: use sudoers_lookup() instead of a custom loop.
+ [a0ca73d81fa4]
+
+ * plugins/sudoers/lookup.c, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/sudoers.c:
+ Add callbacks to sudoers_lookup() so we can use it in testsudoers.
+
+ Also pass in the time to be used for NOTBEFORE/NOTAFTER checks.
+ [bcd59528055a]
+
+2023-06-29 Rose <83477269+AtariDreams@users.noreply.github.com>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Regenerate toke.c using updated flex
+
+ Use the current version of flex to generate toke.c
+ [118d001d189c]
+
+2023-06-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/testsudoers.c:
+ Merge pull request #278 from AtariDreams/types
+
+ Avoid compiler casting warnings Part 2
+ [894767f88afa]
+
+ * plugins/sudoers/sudoers.c:
+ check_user_runcwd: only allow sudo's -D option if sudoers specifies
+ a runcwd.
+
+ Previously, the user could specify the runas user's home dir for
+ "sudo -i" or the user's existing cwd when -i is not specified. This
+ behavior was never documented and is inconsistent with how the -R
+ option is handled.
+ [e79eddc35325]
+
+ * MANIFEST, plugins/sudoers/regress/testsudoers/test24.out.ok,
+ plugins/sudoers/regress/testsudoers/test24.sh,
+ plugins/sudoers/testsudoers.c:
+ testsudoers: add support for NOTBEFORE and NOTAFTER
+
+ Also adds -T option to set the value of "now".
+ [b2d95b4a131d]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/lookup.c,
+ plugins/sudoers/parse.c:
+ Rename parse.c -> lookup.c now that it only contains sudoers_lookup.
+ [141000ce5f24]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/display.c,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h:
+ Split display_privs() and display_cmnd() out of parse.c into
+ display.c
+ [d654dd871e43]
+
+ * lib/util/snprintf.c:
+ No need to round up to page size with sudo_mmap_alloc().
+ [a57803434010]
+
+ * logsrvd/logsrvd.c:
+ Merge pull request #265 from AtariDreams/types
+
+ Avoid compiler casting warnings by assigning to variables of the
+ same type where possible
+ [16d8e7383e3e]
+
+ * Merge pull request #277 from AtariDreams/debug_return_int(1);
+
+ We should be returning 0, not 1, when logservd finishes without
+ errors
+ [19289d607981]
+
+2023-06-28 Rose <83477269+AtariDreams@users.noreply.github.com>
+
+ * logsrvd/logsrvd.c:
+ We should be returning 0, not 1, when logservd finishes without
+ errors
+
+ 1 is for failure, 0 is for no failure, and this does not look like a
+ failure.
+ [7a0d2f4bf5d3]
+
+2023-06-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, src/sudo_intercept.c,
+ src/sudo_intercept_common.c:
+ Fix undefined symbol on macOS for intercept mode and log_subcmds.
+
+ macOS does not support direct access to the environ pointer from a
+ shared object. We need to redirect through _NSGetEnviron() instead.
+ Fixes GitHub issue #276.
+ [2cbebcb8082c]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c:
+ check_user_runcwd: allow -D option if it matches the cwd in sudoers
+
+ Previously, check_user_runcwd() would return true if the runcwd
+ matched the user's cwd, even if sudoers specified a different one.
+ The user-specified runcwd was ignored but it is better to error out
+ in this case. It is now also possible to use "sudo -D" with the
+ directory specified in sudoers.
+ [d32e07966e0e]
+
+2023-06-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_14 for changeset 8010d7515347
+ [ff70094a18c0] <1.9>
+
+ * MANIFEST, NEWS, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, plugins/sudoers/Makefile.in,
+ plugins/sudoers/logging.c, plugins/sudoers/match_command.c,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c, src/exec_nopty.c:
+ Merge sudo 1.9.14 from tip.
+ [8010d7515347] [SUDO_1_9_14] <1.9>
+
+2023-06-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #275 from AtariDreams/emergency
+
+ Set command_info to NULL once it is freed
+ [6d1e55f4e7b9]
+
+2023-06-26 Rose <83477269+AtariDreams@users.noreply.github.com>
+
+ * plugins/sudoers/policy.c:
+ Set command_info to NULL once it is freed
+
+ The lack of setting to NULL is a holdover from when command_info was
+ a local variable and not a global one. However, we given how other
+ global variables are set to NULL, it is best that we do the same
+ here to avoid potential issues should sudoers_policy_store_result be
+ called again after the first time failed, otherwise we could get a
+ double-free.
+ [a1a462a52a98]
+
+2023-06-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #274 from bin-ly/main
+
+ Modify the is_script function for match_command.c
+ [05675d16bd52]
+
+2023-06-25 binlingyu <binlingyu@uniontech.com>
+
+ * plugins/sudoers/match_command.c:
+ Modify the is_script function for match_command.c
+ [ce944a838c33]
+
+2023-06-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Mention C99 requirement.
+ [f12a7b68e0b2]
+
+2023-06-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ Reference SETENV-related settings in the command environment
+ section.
+
+ Based on GitHub PR #273 from Ilya Kulakov.
+ [f8b5ef533800]
+
+ * INSTALL.md:
+ Sudo requires a C99 compiler due to the use of flexible array
+ members.
+ [bb80666c7382]
+
+ * Merge pull request #266 from AtariDreams/c99
+
+ Do variable length arrays the C99 way
+ [690561b17683]
+
+2023-06-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #269 from trackers-lover/main
+
+ correct the return value type of function alias_find_used
+ [30dc3eb4a59a]
+
+2023-06-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ Clarify that use_pty is on by default starting with 1.9.14.
+ [984048215229]
+
+ * docs/sudo.man.in, docs/sudo.mdoc.in:
+ Sudo runs the command in a pty by default in 1.9.14 and above.
+ [92ec41fdf7c9]
+
+ * plugins/sudoers/sudoers.in:
+ Add commented out example for disabling use_pty.
+ [9a59b831f363]
+
+2023-06-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .circleci/config.yml:
+ Update Xcode version from 13.2.1 to 13.4.1.
+ [10bbb25b415e]
+
+2023-06-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST:
+ Add plugins/sudoers/regress/testsudoers/passwd to MANIFEST.
+ [016644afd8ae]
+
+ * plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po, po/eo.mo,
+ po/eo.po, po/pl.mo, po/pl.po:
+ Updated translations from translationproject.org
+ [97167b63ffbd]
+
+ * NEWS:
+ Document recent bug fixes.
+ [34d8ffa919c6]
+
+ * MANIFEST, plugins/sudoers/regress/testsudoers/group,
+ plugins/sudoers/regress/testsudoers/passwd,
+ plugins/sudoers/regress/testsudoers/test22.out.ok,
+ plugins/sudoers/regress/testsudoers/test22.sh,
+ plugins/sudoers/regress/testsudoers/test23.out.ok,
+ plugins/sudoers/regress/testsudoers/test23.sh:
+ Add tests to exercise recent runas user and group bug fixes.
+ [20f19831ed34]
+
+ * MANIFEST, plugins/sudoers/regress/testsudoers/passwd,
+ plugins/sudoers/regress/testsudoers/test21.out.ok,
+ plugins/sudoers/regress/testsudoers/test21.sh:
+ Add test to exercise the bug that prevented the group specified via
+ "sudo -g" from matching when a Runas_Alias was used in the user or
+ group portion of a Runas_Spec.
+ [16c0668b5c4b]
+
+2023-06-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/match.c:
+ runaslist_matches: split out user_list and group_list matching.
+
+ This makes it possible to call the appropriate runas user or group
+ list match function when resolving aliases instead of calling
+ runaslist_matches() itself. Fixes a bug that prevented the group
+ specified via "sudo -g" from matching when a Runas_Alias was used in
+ the user or group portion of a Runas_Spec.
+ [3e0885e96418]
+
+ * plugins/sudoers/match.c:
+ runaslist_matches: remove special case to handle "sudo -g group"
+
+ Now that we are guaranteed to have a runas user list for all sudoers
+ rules that contain a runas list, we can remove support for the
+ special case where user_matched is set in the runas group matching
+ conditional. This fixes a bug where "sudo -u myuser -g mygroup" was
+ permitted by a rule like "myuser ALL = (root) ALL".
+ [d80e907efe77]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/regress/sudoers/test27.json.ok,
+ plugins/sudoers/regress/sudoers/test27.ldif.ok,
+ plugins/sudoers/regress/sudoers/test27.out.ok:
+ Populate runasusers even when only a grouplist is specified.
+
+ When a sudoers rule permits the user to run commands as a group, not
+ a user, we should set the runasusers to single member with the
+ special MYSELF token. This guarantees that the only time runasusers
+ will be NULL is when no runaslist is present.
+ [25c293ae5053]
+
+ * plugins/sudoers/match.c:
+ runaslist_matches: fix bug when no runas list is specified in
+ sudoers.
+
+ If a sudoers rule has no runas list, a user-specified runas group
+ should only be allowed if it matches a group that the default runas
+ user belongs to. Instead, a missing group check allowed the user run
+ commands as the default runas user with an arbitrary group.
+
+ This means that a rule like "somebody host = ALL", which should be
+ equivalent to "somebody host = (root) ALL", had the same effect as
+ "somebody host = (root:ALL) ALL".
+ [eeb075b3b79c]
+
+2023-06-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/pyhelpers.h:
+ Python may be built with 32-bit time_t support on 32-bit platforms.
+ We need to undef the SIZEOF_TIME_T from pyconfig.h so it does not
+ conflict with our own.
+ [c8bf985eb777]
+
+2023-06-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #272 from millert/main
+
+ Avoid use of variable length arrays and add ctype(3) casts.
+ [806b2266f6ab]
+
+ * lib/util/lbuf.c:
+ Avoid use of variable length arrays and add ctype(3) casts.
+ [d8c80d4905b3]
+
+ * Merge pull request #270 from moehanabi/main
+
+ Add %n$s support for sudo_lbuf_append_v1
+ [53ad2cdaaabe]
+
+2023-06-09 Brilliant Hanabi <130747944+moehanabi@users.noreply.github.com>
+
+ * lib/util/lbuf.c:
+ Add %n$s support for sudo_lbuf_append_v1
+ [f48fa0250fdc]
+
+2023-06-09 bianguangze <bianguangze@uniontech.com>
+
+ * plugins/sudoers/alias.c:
+ correct the return value type of function alias_find_used
+ [f689f55fef3f]
+
+2023-06-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/ro.mo, plugins/sudoers/po/ro.po,
+ plugins/sudoers/po/ru.mo, plugins/sudoers/po/ru.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po, po/cs.mo,
+ po/cs.po, po/de.mo, po/de.po, po/eo.mo, po/eo.po, po/fr.mo,
+ po/fr.po, po/hr.mo, po/hr.po, po/ko.mo, po/ko.po, po/ro.mo,
+ po/ro.po, po/ru.mo, po/ru.po, po/sr.mo, po/sr.po, po/uk.mo,
+ po/uk.po, po/vi.mo, po/vi.po:
+ Updated translations from translationproject.org
+ [966147718ed3]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ Update .pot files for 1.9.14
+ [b79b44520c46]
+
+ * NEWS:
+ Mention Bug #1050 fix.
+ [c4af7e56a515]
+
+ * docs/sudoers.ldap.man.in, docs/sudoers.ldap.mdoc.in,
+ plugins/sudoers/ldap.c, plugins/sudoers/ldap_conf.c,
+ plugins/sudoers/sudo_ldap_conf.h:
+ Add NETGROUP_QUERY option for servers that can't match
+ nisNetgroupTriple. This can be used to support netgroup queries on
+ systems that lack the innetgr() function and where the LDAP server
+ cannot query the nisNetgroup by nisNetgroupTriple.
+ [98b293bee424]
+
+2023-06-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/match.c, plugins/sudoers/parse.h:
+ sudo_ldap_check_non_unix_group: pass nss pointer to netgr_matches()
+ This allows us to use the LDAP-specific version of innetgr() when
+ possible. Also enable "use_netgroups" by default even on systems
+ without innetgr() since we can now query netgroups directly via
+ LDAP.
+ [a443919be48c]
+
+2023-06-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.c:
+ Only call ptrace_verify_post_exec() for intercept, not log_subcmds.
+ [9f55dcdd66cd]
+
+ * NEWS, configure, configure.ac:
+ sudo 1.9.14
+ [73c25828ffc8]
+
+2023-06-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/visudo.c:
+ run_command: back out changes to run editor in its own process
+ group. It unnecessarily complicates things to work around bugs in an
+ OS almost no one runs.
+ [8790d32a4f99]
+
+ * MANIFEST, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/suspend_parent.c, lib/util/util.exp.in,
+ plugins/sudoers/Makefile.in, src/Makefile.in, src/sudo_exec.h,
+ src/suspend_parent.c:
+ Make suspend_parent.c out of lib/util and into src. Nothing else
+ uses it now.
+ [69eda3d690e4]
+
+2023-06-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/digestname.c, plugins/sudoers/filedigest.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.h,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Initialize digest_type to SUDO_DIGEST_INVALID, not -1 and make it
+ unsigned. This makes the digest type consistently unsigned instead
+ of a mix of signed (for the -1 value in the tokenizer) and unsigned.
+ [49ef7c33450f]
+
+2023-05-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudo_plugin_python.man.in, docs/sudo_plugin_python.mdoc.in,
+ etc/codespell.exclude, etc/codespell.ignore,
+ plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/pivot.c, plugins/sudoers/visudo.c:
+ Fix typos and update excluded/ignored codespell lists.
+ [bdb70620b4e4]
+
+2023-05-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/visudo.c:
+ run_command: check that ttyfd is not -1 before using it
+ [990cbd169a37]
+
+2023-05-18 Rose <83477269+AtariDreams@users.noreply.github.com>
+
+ * include/sudo_event.h, lib/util/event.c, lib/util/rcstr.c,
+ plugins/sudoers/canon_path.c, plugins/sudoers/ldap_conf.c,
+ plugins/sudoers/sudo_ldap_conf.h:
+ Do variable length arrays the C99 way
+
+ Variable length arrays are supported by C99, but having it denoted
+ as "1" confused the compiler and is not defined.
+
+ Note that because we don't get the inferred NULL terminator, we have
+ to increase the malloc size by one.
+ [4e33419e940e]
+
+ * lib/eventlog/eventlog.c, lib/eventlog/eventlog_free.c,
+ lib/eventlog/parse_json.c, lib/iolog/hostcheck.c,
+ lib/iolog/regress/iolog_path/check_iolog_path.c, lib/util/event.c,
+ lib/util/explicit_bzero.c, lib/util/fatal.c, lib/util/getaddrinfo.c,
+ lib/util/getentropy.c, lib/util/hexchar.c, lib/util/inet_ntop.c,
+ lib/util/json.c, lib/util/lbuf.c, lib/util/mksiglist.c,
+ lib/util/mksigname.c, lib/util/multiarch.c, lib/util/progname.c,
+ lib/util/sig2str.c, lib/util/snprintf.c, lib/util/sudo_conf.c,
+ lib/util/term.c, lib/util/uuid.c, logsrvd/iolog_writer.c,
+ logsrvd/logsrvd.c, logsrvd/sendlog.c,
+ plugins/audit_json/audit_json.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/editor.c,
+ plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/iolog.c, plugins/sudoers/parse.c,
+ plugins/sudoers/policy.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/starttime/check_starttime.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/timestr.c, plugins/sudoers/tsdump.c,
+ plugins/sudoers/visudo.c, src/conversation.c, src/exec_monitor.c,
+ src/limits.c, src/parse_args.c, src/sesh.c, src/sudo.c, src/sudo.h:
+ Avoid compiler casting warnings by assigning to the same type where
+ possible
+
+ This saves instructions that are related to casting as well as
+ compiler warnings.
+ [d47033551fca]
+
+ * lib/util/mktemp.c, lib/util/regress/tailq/hltq_test.c,
+ lib/util/sudo_debug.c, lib/util/ttyname_dev.c,
+ plugins/group_file/plugin_test.c, plugins/sudoers/editor.c,
+ plugins/sudoers/filedigest.c, plugins/sudoers/match_addr.c,
+ plugins/sudoers/match_digest.c,
+ plugins/sudoers/regress/env_match/check_env_pattern.c,
+ plugins/sudoers/regress/exptilde/check_exptilde.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/tsdump.c, plugins/sudoers/visudo.c,
+ src/exec_monitor.c, src/limits.c, src/sesh.c, src/sudo.c,
+ src/sudo.h, src/sudo_edit.c:
+ Avoid compiler casting warnings Part 2
+
+ This saves instructions that are related to casting as well as
+ compiler warnings.
+ [685a954b019f]
+
+2023-05-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/visudo.c:
+ Work around a macOS a kernel bug where tcsetpgrp() does not restart.
+
+ I reported this bug to Apple over 12 years ago.
+ [77871464e563]
+
+ * plugins/sudoers/visudo.c:
+ run_command: run editor in foreground if visudo is the foreground
+ process
+
+ The command is now always run in its own process group. If visudo is
+ run in the foreground, the command is run in the foreground too.
+ Otherwise, run the command in the background. There is a race
+ between the tcsetpgrp() call in the parent and the execve() in the
+ child. If we lose the race and the command needs the controlling
+ terminal, it will be stopped with SIGTTOU or SIGTTIN, which the
+ waitpid() loop will handle.
+ [e8e14e0024da]
+
+ * plugins/sudoers/visudo.c:
+ Accept carriage return for EOL in addition to newline.
+
+ Since visudo doesn't alter the terminal settings it is possible for
+ the terminal to have the ONLCR bit set in the output control flags.
+ In that case, we will get a CR, not a NL when the user presses
+ enter/return. One way this can happen is if visudo is run in the
+ background from a shell that supports line editing and the editor
+ restores the (cbreak-style) terminal mode when it finishes.
+ [14538e74fd02]
+
+2023-05-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/parser/check_fill.c:
+ check_fill: sudoers_strict() is now a function, not a global
+ variable
+ [8b8e72d283df]
+
+ * plugins/sudoers/parse.h, plugins/sudoers/sudoers.h,
+ plugins/sudoers/toke.h:
+ Move parser prototypes / externs from sudoers.h to parse.h or
+ toke.h.
+ [79a52390c46b]
+
+ * plugins/sudoers/file.c, plugins/sudoers/sudoers.c:
+ parse.h is already included by sudoers.h.
+ [f6faa3f782a2]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c:
+ Rename parser_conf -> sudoers_conf in all but the parser itself.
+ [61614621341e]
+
+2023-05-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/file.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.h, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c:
+ Move sudoers search path to struct sudoers_parser_config.
+
+ That way we can avoid passing it to init_parser() directly. We still
+ need sudoers_search_path to be shared between the lexer and the
+ parser.
+ [5e6c6a08aded]
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/file.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.h, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/visudo.c:
+ Add struct sudoers_parser_config and pass it to init_parser().
+
+ This struct contains parser configuration such as the sudoers file
+ uid/gid/mode and parse flags such as verbose, strict and recovery.
+ [ed8042e7a49a]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ push_include_int: Avoid passing close(2) a negative value on error.
+ Coverity CID 314108
+ [bbbdfa87543e]
+
+ * plugins/sudoers/ldap.c:
+ Eliminate dead store. Coverity CID 315032.
+ [6b48998e4db1]
+
+2023-05-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_iolog.h, lib/iolog/iolog_gets.c:
+ iolog_gets: change size parameter to int to match fgets/gzgets
+
+ Return an error, setting errno to EINVAL, for negative sizes.
+ [27534bcb58a7]
+
+2023-05-05 Rose <83477269+AtariDreams@users.noreply.github.com>
+
+ * plugins/sudoers/sudoers_hooks.c:
+ Redundant cast removal in sudoers_hooks
+
+ def_sudoers_locale is already a char*
+ [2f79add9136d]
+
+2023-05-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Rename force_umask to override_umask and make it private to
+ sudoers.c.
+
+ Add getter for policy.c.
+ [1c8a56c767f3]
+
+ * plugins/sudoers/check.h, plugins/sudoers/regress/fuzz/fuzz_stubs.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/timestamp.c:
+ Make timestamp_uid and timestamp_gid private to timestamp.c.
+
+ Add getter (for set_perms.c) and setter (for sudoers.c).
+ [ad49d0ee7e6f]
+
+ * plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/sudo_auth.h,
+ plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.h:
+ Make login_style private to bsdauth.c
+
+ Add a setter for policy.c to handle auth_type from the front-end.
+ [962af1d3d0fd]
+
+2023-05-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/sudo_debug.c:
+ Back out last change, len must be int, not size_t, for %.*s.
+ [a82bbd86fa29]
+
+ * src/exec_pty.c:
+ Use a "%s" format instead of using a translated string as the
+ format.
+ [1a73a1b4fa94]
+
+ * Merge pull request #260 from AtariDreams/size_t
+
+ Prefer size_t over int, as casting can take extra instructions
+ [c0fd1027e105]
+
+2023-05-03 Rose <83477269+AtariDreams@users.noreply.github.com>
+
+ * lib/eventlog/parse_json.c, lib/util/sudo_debug.c,
+ plugins/sudoers/fmtsudoers.c:
+ Prefer size_t over int, as casting can take extra instructions
+ [96fc138b2009]
+
+2023-05-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Rename init_parser_ext() to init_parser() and remove old wrapper.
+
+ There was only one consumer of the init_parser() wrapper now that
+ reset_parser() has been introduced.
+ [4be1b8965ce6]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.h,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/sudoers.c:
+ Add reset_parser() and use in place of init_parser(NULL).
+ [f85227ac1182]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/ldap_conf.c,
+ plugins/sudoers/policy.c, plugins/sudoers/sudoers.h:
+ Make path_ldap_conf and path_ldap_secret private to policy.c.
+
+ Add getters for both so the ldap code can access them.
+ [90a2107d6ec7]
+
+ * plugins/sudoers/file.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/visudo.c:
+ Make sudoers_file private to policy.c and visudo.c.
+
+ We just need a way for the policy (and visudo) to override the
+ default sudoers path. This adds a getter to be used in file.c when
+ sudoers is first opened.
+ [657aa80f3af8]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.h,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/visudo.c:
+ Support adminconfdir for relative include paths in sudoers.
+ [7ebdbd46b47b]
+
+ * plugins/sudoers/visudo.c:
+ Track the destination sudoers path for each parsed file.
+
+ When adminconfdir is enabled, the destination pathh may be different
+ from the path we opened. We always store an edited file in the
+ adminconfdir (if enabled). This makes it possible to use visudo when
+ /etc/sudoers is located on a read-only file system.
+ [de896a012d81]
+
+ * INSTALL.md, Makefile.in, configure, configure.ac, docs/Makefile.in,
+ examples/Makefile.in, include/Makefile.in, lib/util/Makefile.in,
+ lib/zlib/Makefile.in, logsrvd/Makefile.in, m4/sudo.m4,
+ plugins/audit_json/Makefile.in, plugins/group_file/Makefile.in,
+ plugins/python/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sample_approval/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/Makefile.in:
+ Add adminconfdir and --enable-adminconf to set it. Configuration
+ paths in sudo are now a colon-separated list of files with the
+ adminconfdir instance first (if enabled), followed by a sysconfdir
+ instance.
+ [be1f672878ae]
+
+ * configure, configure.ac, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/secure_path.c, lib/util/sudo_conf.c, lib/util/util.exp.in,
+ logsrvd/Makefile.in, logsrvd/logsrvd.c, logsrvd/logsrvd_conf.c,
+ plugins/sudoers/Makefile.in, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/sudoers.c, src/Makefile.in:
+ Convert config file paths to colon-separated path list. This means
+ that _PATH_SUDO_CONF, _PATH_SUDOERS, _PATH_SUDO_LOGSRVD_CONF, and
+ _PATH_CVTSUDOERS_CONF can now specify multiple files. The first file
+ that exists is used.
+ [902d9da6a941]
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/file.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/visudo.c:
+ Support sudoers_file being a colon-separated path of files. The
+ first file found is used.
+ [bebe005e2d32]
+
+2023-05-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure:
+ Regenerate with latest autoconf from git.
+ [0996570205bf]
+
+2023-04-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd_conf.c:
+ No longer need to set AI_NUMERICSERV while fuzzing.
+
+ Now that getaddrinfo() is stubbed out while fuzzing we can remove
+ the hack that set AI_NUMERICSERV.
+ [8e3deb584c1c]
+
+2023-04-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/regress/fuzz/fuzz_logsrvd_conf.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ getaddrinfo stub: set sin_port
+ [019eb2da9944]
+
+ * logsrvd/regress/fuzz/fuzz_logsrvd_conf.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Avoid NULL deref in stub getaddrinfo() when nodename is NULL. Also
+ add support for parsing servname. We only need to support a subset
+ of getaddrinfo() functionality in the fuzzer.
+ [a605cc43bbaf]
+
+ * configure, m4/hardening.m4:
+ Add missing stdio.h include for the _FORTIFY_SOURCE=2 check.
+ Implementations of _FORTIFY_SOURCE require the header file to be
+ included. Also remove the useless test of an empty program with
+ _FORTIFY_SOURCE defined. Pointed out by Florian Weimer.
+ [511b9bdddbdc]
+
+ * configure, m4/ldap.m4:
+ Use ldap_msgfree() instead of ldap_init() for the lber.h test. The
+ ldap_init() function is marked as deprecated and not defined by
+ default on some systems. This can cause an error for compilers that
+ do not support implicit function declarations. From Florian Weimer.
+ [1b1ce2072403]
+
+2023-04-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/regress/fuzz/fuzz_logsrvd_conf.c:
+ Include arpa/inet.h for inet_pton() prototype.
+ [50d3b09376f7]
+
+ * logsrvd/regress/fuzz/fuzz_logsrvd_conf.c:
+ Add netdb.h for struct addrinfo and EAI_* error codes.
+ [92d33c6f8a23]
+
+ * logsrvd/regress/fuzz/fuzz_logsrvd_conf.c:
+ Stub out getaddrinfo() and freeaddrinfo(). We may not be able have
+ access to DNS in the fuzzing environment.
+ [b3d2e6c04076]
+
+ * lib/eventlog/regress/eventlog_store/store_sudo_test.c:
+ Plug memory leaks in store_sudo_test found by LSAN.
+ [5f1d68d01c0c]
+
+2023-04-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/limits.c:
+ disable_coredump: only change the soft limit, leave the hard limit
+ as-is This should avoid problems on Linux in cases where sudo does
+ not have CAP_SYS_RESOURCE which may be the case in an unprivileged
+ container. GitHub issue #42
+ [4e65c3923119]
+
+2023-04-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/build_pkgs:
+ Add basic support for remote power on/off via net-snmp.
+ [ca021941fd58]
+
+ * src/exec.c:
+ More accurate description of what happens for "sudo -b".
+ [a9158169fcac]
+
+ * src/exec_pty.c:
+ Better support for "sudo -b" when running the command in a pty.
+
+ When a command is run via "sudo -b" it has no access to terminal
+ input. In non-pty mode, the command runs in an orphaned process
+ group and reads from the controlling terminal fail with EIO. We
+ cannot do the same while running in a pty but if we set stdin to a
+ half-closed pipe, reads from it will get EOF. That is close enough.
+ [a284611a18fd]
+
+2023-04-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_nopty.c, src/exec_pty.c, src/selinux.c, src/sudo.h,
+ src/ttyname.c:
+ Avoid calling isatty()/ttyname() on std{in,out,err} if not a char
+ dev.
+
+ The user controls these fds so we should avoid calling ioctl(2) on
+ them unless they correspond to actual character device files.
+ [745430b563db]
+
+ * src/parse_args.c, src/sudo_usage.h.in:
+ Hard-code usage() and help() for an 80-column terminal.
+
+ Trying to tailor the help and usage output to the terminal width is
+ simply not worth it and could be abused to mark a socket as
+ "trusted" on Linux if there are additional kernel bugs like
+ CVE-2023-2002.
+ [d06fa6322ffb]
+
+ * config.h.in, configure, configure.ac, src/sudo.c,
+ src/sudo_usage.h.in:
+ Move CONFIGURE_ARGS from sudo_usage.h.in to config.h.in.
+ [e3149b6f4392]
+
+2023-04-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/ttysize.c, src/sudo.c:
+ get_user_info: call sudo_get_ttysize() even if no /dev/tty We still
+ want to initialize rows and cols based on the environment if
+ possible.
+ [4f3801c2f264]
+
+2023-04-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/parse_args.c:
+ Get the tty size using stdout, not stderr, when printing help
+ output. While usage() prints to stderr, help() prints to stdout.
+ [0bdf411ebc7f]
+
+ * src/sudo.c:
+ get_user_info: pass sudo_get_ttysize() the fd of /dev/tty, not
+ stderr. Both the plugin API and the main event loop expect
+ lines/cols to refer to the user's terminal, so using /dev/tty is
+ better here.
+ [2e7ba199f4c7]
+
+ * include/sudo_util.h, lib/util/ttysize.c, lib/util/util.exp.in,
+ plugins/sudoers/sudoreplay.c, src/parse_args.c, src/sudo.c:
+ Add an fd argument to sudo_get_ttysize() instead of always using
+ stderr.
+
+ For sudoreplay we open /dev/tty, so use that instead of stderr when
+ determining the terminal size.
+ [4afc292d3cf4]
+
+ * lib/util/ttysize.c:
+ Check whether stderr is a tty before trying TIOCGWINSZ.
+ [4a0d367e49c6]
+
+2023-04-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Use -no-undefined on macOS to avoid "-undefined dynamic_lookup"
+ warnings.
+
+ Starting with macOS 13, the linker warns when "-undefined
+ dynamic_lookup" is used. This is added by libtool by default on
+ macOS but we can suppress it by passing -no-undefined to libtool.
+ [afeb9acd894c]
+
+2023-04-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docker/debian/latest/Dockerfile, docker/debian/testing/Dockerfile,
+ docker/fedora/latest/Dockerfile, docker/fedora/rawhide/Dockerfile,
+ docker/ubuntu/devel/Dockerfile, docker/ubuntu/latest/Dockerfile,
+ docker/ubuntu/rolling/Dockerfile:
+ Add make to Dockerfile and sort packages.
+ [fa937cbf8a23]
+
+2023-04-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/UPGRADE.md, docs/sudoers.man.in, docs/sudoers.mdoc.in,
+ plugins/sudoers/defaults.c:
+ Enable the use_pty option by default for sudo 1.9.14.
+
+ GitHub issue #258
+ [86a1a6da1878]
+
+2023-04-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Split up the monolithic sudoers_policy_main() function.
+
+ This splits the code to find the command, perform a sudoers lookup,
+ ask for a password as needed, and perform post-lokup checks out into
+ sudoers_check_common(). The old sudoers_policy_main() has been
+ replaced by sudoers_check_cmnd() (called by sudoers_policy_check()),
+ sudoers_validate_user() (called by sudoers_policy_validate()) and
+ sudoers_list() (called by sudoers_policy_list()). The list_user
+ lookup is now performed in sudoers_list().
+ [59e0b245c776]
+
+ * plugins/sudoers/sudoers.c:
+ Move the root_sudo check until after we apply per-command Defaults.
+
+ It is possible, though unlikely, for "root_sudo" to be used in a
+ per-command Defaults statement.
+ [ca1903576e0d]
+
+2023-04-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.c:
+ sudoers_policy_main: restore locale if sudoers_lookup() fails.
+
+ Previously, if sudoers_lookup() set VALIDATE_ERROR, the sudoers
+ locale would still be in effect instead of the original locale.
+ [24df4eebbfc8]
+
+ * plugins/sudoers/parse.c:
+ sudoers_lookup_pseudo: remove validated function argument
+
+ This was always set to FLAG_NO_USER|FLAG_NO_HOST which are cleared
+ at the top of the fuction. Make validated a local variables,
+ initialized to 0, instead. No change in behavior.
+ [72e6207850fc]
+
+2023-03-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/audit.c, plugins/sudoers/iolog.c:
+ The I/O log file name is not just the basename of the full
+ iolog_path. The audit plugin already has the correct value for
+ iolog_file, don't overwrite it with basename(iolog_path). In the
+ future we may wish to pass in iolog_file and iolog_dir in addition
+ to iolog_path. Fixes Bug #1046.
+ [f272de885273]
+
+2023-03-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.c:
+ Warn with "unknown user" not "unknown uid" if user cannot be
+ resolved. Prior to sudo 1.8 this was after a getpwuid() but now we
+ use getpwnam().
+ [9a523881df41]
+
+ * plugins/sudoers/sudoers.c:
+ Set timestamp_uid and timestamp_gid via a callback. This also makes
+ it possible to include the location of the line in the sudoers file
+ in the warning message (and mail).
+ [5588cf3cb55b]
+
+2023-03-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudoers.ldap.man.in, docs/sudoers.ldap.mdoc.in:
+ Fix display of escape sequencees in ldapsearch example.
+ [08dc98162160]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ White space is not allowed between Defaults and '@', ':', '!', '>'.
+ The EBNF made it appear that this is allowed when it really is not.
+ [74bba755afaf]
+
+2023-03-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/edit_open.c, src/exec.c, src/exec_intercept.c,
+ src/exec_intercept.h, src/exec_monitor.c, src/exec_nopty.c,
+ src/exec_pty.c, src/sudo.c, src/sudo.h, src/sudo_edit.c,
+ src/sudo_edit.h, src/sudo_exec.h, src/tgetpass.c:
+ Make struct {command,user}_details pointers const where possible.
+ [dcfa95a24789]
+
+ * src/sudo.c, src/sudo.h, src/sudo_edit.c, src/tgetpass.c:
+ Make user_details private to main.
+ [43477263455b]
+
+ * src/exec.c, src/exec_nopty.c, src/exec_pty.c, src/parse_args.c,
+ src/sudo.c, src/sudo.h, src/sudo_edit.c, src/sudo_exec.h,
+ src/tgetpass.c:
+ Make user_details private to sudo.c.
+ [fec5df7605dc]
+
+ * configure, scripts/config.sub:
+ Regenerate with the autoconf 2.72c snapshot.
+ [6dda0f9323b1]
+
+2023-03-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/parse_args.c:
+ Use sudo_get_ttysize() in help() and usage(). This eliminates a
+ dependency on the user_details global.
+ [ecbc8afc1630]
+
+ * src/exec.c, src/sudo.c, src/sudo.h:
+ Store submitcwd (from user_details) in struct command_details. This
+ eliminates use of the user_details global from exec_setup().
+ [ed37b2a451f8]
+
+2023-03-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/utmp.c:
+ utmp_fill: user is now always non-NULL, no need for user_details.
+ [76bdecaaad07]
+
+ * src/parse_args.c, src/sudo.c, src/sudo.h:
+ Remove list_user global.
+ [fd397db04688]
+
+ * src/conversation.c:
+ No need to declare tgetpass_flags, it is already in sudo.h.
+ [c7e1b8ef75c8]
+
+ * src/sudo.c:
+ No need for sudo_mode to be global anymore.
+ [f746eba12bd9]
+
+ * src/sudo.c:
+ Make command_details private to main().
+ [311fd705cce4]
+
+ * src/exec_iolog.c, src/exec_nopty.c, src/exec_pty.c, src/sudo_exec.h:
+ Make iobufs private to exec_iolog.c.
+ [80861a209ddd]
+
+ * src/sudo_exec.h:
+ Remove ttymode and its associated values.
+ [efb4e04097ab]
+
+ * src/exec.c, src/exec_pty.c, src/get_pty.c, src/sudo.h,
+ src/sudo_exec.h:
+ Move ptyname to struct exec_closure
+ [d4080a4262bd]
+
+ * src/exec_monitor.c, src/exec_pty.c, src/sudo_exec.h:
+ Move pty_make_controlling() to exec_monitor.c where it is called. We
+ can use details->tty to access the pty follower path.
+ [9875f0b136f4]
+
+ * src/exec_pty.c, src/sudo.c:
+ Eliminate utmp_user global, just use the value in struct command
+ details.
+ [95b28adcb0f3]
+
+ * src/exec_iolog.c, src/exec_nopty.c, src/exec_pty.c, src/sudo_exec.h:
+ Replace tty_mode global with term_raw flag in struct exec_closure.
+
+ The pty_cleanup hook needs access to the closure so add
+ pty_cleanup_init() to store a pointer to the closure for use by
+ pty_cleanup_hook().
+ [cc01f0da46d9]
+
+ * src/exec_monitor.c, src/exec_pty.c, src/sudo_exec.h:
+ Register pty cleanup function in exec_pty(), not exec_cmnd_pty(). We
+ want it to execute in the main sudo process, not the monitor.
+ [279e370adc01]
+
+ * src/exec_iolog.c:
+ Make ttyblock private to exec_iolog.c
+ [61243eba350d]
+
+2023-03-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_pty.c, src/sudo_exec.h:
+ exec_pty.c: move foreground flag to struct exec_closure. Also make
+ pipeline flag private to exec_pty() and remove the unneeded
+ check_foreground() prototype.
+ [dd25f1d91008]
+
+ * src/exec_pty.c:
+ On resume, always sync the pty terminal settings with /dev/tty.
+
+ Changes made to the terminal settings while the command is suspended
+ are now reflected in the pty when the command is resumed. This is
+ more consistent with the non-pty behavior and allows for the removal
+ of the "tty_initialized" global. One downside to this change is that
+ if a terminal-based program using the pty is stopped with SIGSTOP it
+ may have the wrong terminal settings on resume. However, this is no
+ different from the non-pty case.
+ [3e59765dea31]
+
+ * lib/util/suspend_parent.c, lib/util/term.c:
+ Correct a comment.
+ [393a4d472507]
+
+2023-03-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .github/FUNDING.yml:
+ GitHub sponsor settings.
+ [7bd778b9adef]
+
+ * config.h.in, configure, configure.ac:
+ Use built-in tests for bit types instead of using AC_CHECK_TYPES.
+ This should be more portable as it handles the quirks of some older
+ systems.
+ [7e471f2a914d]
+
+ * plugins/sudoers/visudo.c, src/regress/intercept/test_ptrace.c:
+ Quiet compiler warnings on systems where pid_t is not an int.
+ Historically, pid_t was a long on some 32-bit systems like Solaris.
+ [c31393da893d]
+
+ * plugins/sudoers/visudo.c:
+ Silence "used uninitialized" false positives with older gcc
+ versions.
+ [40f0ee142249]
+
+ * src/exec_pty.c:
+ exec_pty: always copy the terminal settings from /dev/tty the pty.
+ Previously, we only did this when running in the foreground but this
+ can cause problems when running a program that reads the terminal
+ settings or window size in the background. If sudo is running in the
+ background, the terminal settings will be updated if it transitions
+ to the foreground process. Based on a suggestion from From Duncan
+ Overbruck.
+ [51a70eadc7fc]
+
+ * src/exec_pty.c:
+ check_foreground: use SFD_LEADER not SFD_FOLLOWER (which was
+ closed). Also use SFD_LEADER for sudo_term_copy() in exec_pty() for
+ consistency. From Duncan Overbruck.
+ [172962b90aa6]
+
+ * src/exec_pty.c:
+ suspend_sudo_pty: fix cut & pasto in last commit to catch SIGCONT.
+ Also set sa.sa_handler to SIG_DFL instead of SIG_IGN. There is no
+ difference for SIGCONT but it means we can re-use sa as-is later.
+ [e07725c8c939]
+
+2023-03-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_pty.c:
+ Catch SIGCONT and restore terminal settings on resume from SIGSTOP.
+ While we cannot catch SIGSTOP, we _can_ catch SIGCONT and set
+ /dev/tty to raw mode when running in the foreground. Ignore SIGCONT
+ in suspend_sudo_pty() so we don't call resume_terminal() twice.
+ [b5b2d739e44d]
+
+ * src/exec_monitor.c, src/exec_pty.c:
+ Only convert a signal number to a name if we are going to use it. It
+ is mostly used for debug logging.
+ [225c3630ffff]
+
+ * src/exec_monitor.c, src/exec_pty.c, src/sudo.h:
+ Move updating of the window size back to the main sudo process. We
+ can use the leader file descriptor with TIOCGWINSZ to set the window
+ size of the pty. Thanks to Duncan Overbruck for the hint.
+ [6e3f7622038a]
+
+ * plugins/sudoers/visudo.c:
+ visudo: restore controlling terminal after running the editor.
+ Otherwise, visudo will get SIGTTOU if it tries to write to the
+ terminal after the editor finishes. Also avoid races by setting the
+ process group ID in both the parent and child, and grant the
+ controlling terminal in the parent, not the child.
+ [c0f339a84be8]
+
+2023-03-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/visudo.man.in, docs/visudo.mdoc.in, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/sudoers.h,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.h,
+ plugins/sudoers/toke.l:
+ Warn about ignored files in sudoers.d in visudo.
+ [61f8def2d666]
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/visudo.c:
+ Replace sudoers_warnings with sudoers_verbose. This is now an int,
+ with values > 1 reserved for visudo.
+ [d1d7b559b904]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.h,
+ plugins/sudoers/toke.l:
+ Split push_include() into push_include() and push_includedir(). This
+ moves the "isdir" function argument to the internal version.
+ [d454beb6eebf]
+
+2023-03-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/file.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_stubs.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudo_nss.h:
+ Pass around const struct sudo_nss pointers where possible.
+ [d13437078d19]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers.h, plugins/sudoers/cvtsudoers_csv.c,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/defaults.h, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/fmtsudoers_cvt.c, plugins/sudoers/match.c,
+ plugins/sudoers/parse.h:
+ Pass around const struct sudoers_parse_tree pointers where possible.
+ [1aa8b9069b39]
+
+ * plugins/sudoers/sudo_ldap.h, plugins/sudoers/sudo_ldap_conf.h:
+ Move non-config-related macros to from sudo_ldap_conf.h to
+ sudo_ldap.h.
+ [16e67a765a30]
+
+2023-03-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, lib/util/Makefile.in, lib/util/getcwd.c,
+ scripts/mkdep.pl:
+ Remove portable getcwd.c, nothing uses it anymore. Any operating
+ system supported by sudo already includes getcwd(3).
+ [8f0584066f6f]
+
+ * src/Makefile.in:
+ Use LIBPROTOBUF_C and LIBUTIL variables and use them.
+ [062142fa5ae8]
+
+2023-03-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_util.h:
+ Remove now-unused sudo_timeval* macros.
+ [3448dce21b9c]
+
+ * lib/util/nanosleep.c:
+ nanosleep: clear remainder on successful completion Also switch to
+ doing everything in terms of struct timespec except for the actual
+ select(2) call.
+ [d67451eb618e]
+
+ * lib/eventlog/Makefile.in, lib/iolog/Makefile.in:
+ Add lib dependencies for fuzzer and test targets.
+ [60605bcc3905]
+
+ * lib/eventlog/eventlog_free.c:
+ eventlog_free: free peeraddr
+ [42670e45e57f]
+
+ * plugins/sudoers/ldap_innetgr.c:
+ sudo_ldap_netgroup_match_str: "-" in a netgroup can never match. We
+ already check for a NULL value above so "str == NULL" is always
+ false. Found by PVS-Studio.
+ [c9cfdd013e92]
+
+2023-03-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/Makefile.in:
+ Fix static compilation.
+ [5a18337c03d3]
+
+ * MANIFEST:
+ Replace eventlog_json.h with parse_json.h.
+ [cc68fe24ee0d]
+
+ * lib/eventlog/eventlog_free.c, lib/eventlog/parse_json.c:
+ Add support for parsing all fields of struct eventlog.
+ [3828e55bdaff]
+
+2023-03-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, lib/eventlog/Makefile.in,
+ lib/eventlog/regress/eventlog_store/store_json_test.c,
+ lib/eventlog/regress/eventlog_store/store_sudo_test.c,
+ lib/eventlog/regress/eventlog_store/test1.json.in,
+ lib/eventlog/regress/eventlog_store/test1.json.out.ok,
+ lib/eventlog/regress/eventlog_store/test1.sudo.out.ok,
+ lib/eventlog/regress/eventlog_store/test2.json.in,
+ lib/eventlog/regress/eventlog_store/test2.json.out.ok,
+ lib/eventlog/regress/eventlog_store/test2.sudo.out.ok,
+ lib/eventlog/regress/eventlog_store/test3.json.in,
+ lib/eventlog/regress/eventlog_store/test3.json.out.ok,
+ lib/eventlog/regress/eventlog_store/test3.sudo.out.ok,
+ lib/eventlog/regress/eventlog_store/test4.json.in,
+ lib/eventlog/regress/eventlog_store/test4.json.out.ok,
+ lib/eventlog/regress/eventlog_store/test4.sudo.out.ok,
+ lib/eventlog/regress/parse_json/check_parse_json.c:
+ Add tests for JSON and sudo-style log output.
+ [3a923f86fff2]
+
+ * plugins/sudoers/match.c:
+ Declare domain even if the system lacks innetgr(). Fixes a build
+ error on musl-based systems like Alpine.
+ [34cfa5ad4cdc]
+
+ * lib/eventlog/Makefile.in:
+ Add missing definition of $(SED).
+ [9a614b90c852]
+
+ * MANIFEST, include/sudo_eventlog.h, lib/eventlog/Makefile.in,
+ lib/eventlog/parse_json.c, lib/eventlog/parse_json.h,
+ lib/eventlog/regress/parse_json/check_parse_json.c,
+ lib/eventlog/regress/parse_json/test1.in,
+ lib/eventlog/regress/parse_json/test2.in,
+ lib/eventlog/regress/parse_json/test2.out.ok,
+ lib/eventlog/regress/parse_json/test3.in,
+ lib/eventlog/regress/parse_json/test3.out.ok, lib/iolog/Makefile.in,
+ lib/iolog/iolog_json.c, lib/iolog/iolog_json.h,
+ lib/iolog/regress/fuzz/fuzz_iolog_json.c,
+ lib/iolog/regress/iolog_json/check_iolog_json.c,
+ lib/iolog/regress/iolog_json/test1.in,
+ lib/iolog/regress/iolog_json/test2.in,
+ lib/iolog/regress/iolog_json/test2.out.ok,
+ lib/iolog/regress/iolog_json/test3.in,
+ lib/iolog/regress/iolog_json/test3.out.ok:
+ Move JSON log parsing from libsudo_iolog.la to libsudo_eventlog.la
+ It will be used in the upcoming log output tests.
+ [1a8dd741b666]
+
+ * lib/eventlog/eventlog.c:
+ Add missing " ; " separator between environment variables and
+ command. This is a regression introduced in sudo 1.9.13. GitHub
+ issue #254.
+ [a3c09b724b7a]
+
+2023-03-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudoers.ldap.man.in, docs/sudoers.ldap.mdoc.in:
+ Add example to verify support for searching by nisNetgroupTriple.
+ [090ffa785e56]
+
+2023-03-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/gc.c:
+ Remove unused sudoers_gc_init() function.
+ [b2ee61f8f11d]
+
+2023-03-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudoers.ldap.man.in, docs/sudoers.ldap.mdoc.in:
+ Sudo now does its own netgroup lookups if NETGROUP_BASE is set.
+ Previously, it only performed netgroup queries to determine the list
+ of netgroups a user was a member of.
+ [932613f6868a]
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c:
+ sudoers_cleanup: free cached environment before running g/c. Avoids
+ a double free in fuzz_policy.
+ [e616d4a038b6]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c:
+ sudoers_cleanup: run the garbage collector at the end
+ [cbc28a012f8b]
+
+ * plugins/sudoers/sudoers.c:
+ Plugin a memory leak in intercept mode.
+ [f63fb51ff972]
+
+ * src/exec_intercept.c:
+ Sync non-intercept version of intercept_cleanup() declaration.
+ [712ff6c2f6bd]
+
+ * plugins/sudoers/ldap_innetgr.c:
+ Plug memory leak if ldap_get_option() fails with LDAP_NO_MEMORY.
+ [0be36e3e9473]
+
+ * src/exec.c, src/exec_intercept.c, src/sudo_exec.h:
+ Plug a memory leak with ptrace-based intercept.
+ [3b411be9fe37]
+
+ * src/exec_intercept.c:
+ Plug memory leak when log_subcmds is enabled.
+ [1d5b21665ced]
+
+ * lib/util/suspend_parent.c:
+ Pass closure to callback, not the callback pointer itself.
+ [a4e433840f16]
+
+ * MANIFEST, configure, m4/ldap.m4, plugins/sudoers/Makefile.in,
+ plugins/sudoers/ldap.c, plugins/sudoers/ldap_innetgr.c,
+ plugins/sudoers/sudo_ldap.h, scripts/mkdep.pl:
+ Add LDAP-specific innetgr() implementation. Wheh netgroup_base is
+ set we now do out own netgroup lookups using LDAP. Previously, LDAP
+ was queried directly to get a list of the netgroups the user belongs
+ to but other netgroups queries went through innetgr(3). This makes
+ it possible to use netgroups in LDAP sudoers on systems that don't
+ have an innetgr() function. GitHub issue #251.
+ [aa7304a533e0]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/ldap_conf.c,
+ plugins/sudoers/ldap_util.c, plugins/sudoers/sudo_ldap.h:
+ Move some functions from ldap.c to ldap_util.c. These will be used
+ by the LDAP innetgr() implementation.
+ [70fd74041c5d]
+
+2023-03-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/zlib/Makefile.in:
+ fix typo in uninstall target
+ [e3c1b8427d01]
+
+ * Merge pull request #252 from bin-ly/main
+
+ fix typo in uninstall target
+ [4a1d3542345c]
+
+2023-03-09 bin-ly <binlingyu@uniontech.com>
+
+ * lib/util/Makefile.in:
+ fix command error for lib/util/Makefile.in
+ [7dd4e9e6d976]
+
+2023-03-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/file.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/ldap.c, plugins/sudoers/match.c,
+ plugins/sudoers/parse.h,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudo_nss.h:
+ Add per-source innetgr function pointer and use it in
+ netgr_matches(). This will be used to implement LDAP-specific
+ netgroup lookups when netgroup_base is set in ldap.conf.
+ [f7c89d6e8d6b]
+
+2023-03-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, lib/util/Makefile.in,
+ lib/util/regress/digest/digest_test.c:
+ Add tests for SHA2 digest support. This uses the NIST byte-oriented
+ short message test vectors.
+ [06e01abf7943]
+
+2023-03-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_13p3 for changeset 0bdd0b8469e3
+ [fc4e872d6d89] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.13p3
+ [0bdd0b8469e3] [SUDO_1_9_13p3] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.13p3
+ [0c4b7112dde9]
+
+2023-03-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/match.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h:
+ A user with "list" privs for root may not list all users. A user
+ with "sudo ALL" for root _is_ allowed to list any user.
+ [a3f7301ba4d3] <1.9>
+
+ * plugins/sudoers/match.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h:
+ A user with "list" privs for root may not list all users. A user
+ with "sudo ALL" for root _is_ allowed to list any user.
+ [fe758ae9d0bb]
+
+ * plugins/sudoers/policy.c:
+ sudoers_policy_list: do not set runas_pw to list_pw when listing
+ This change introduced in sudo 1.9.13 is not actually needed. The
+ "list" pseudo-command checks are performed via runas_matches_pw()
+ which does not use runas_pw. GitHub issue #248
+ [84effa5ffaa1] <1.9>
+
+ * plugins/sudoers/policy.c:
+ sudoers_policy_list: do not set runas_pw to list_pw when listing
+ This change introduced in sudo 1.9.13 is not actually needed. The
+ "list" pseudo-command checks are performed via runas_matches_pw()
+ which does not use runas_pw. GitHub issue #248
+ [94c1f6d9bc6d]
+
+ * plugins/sudoers/logging.c, plugins/sudoers/parse.c,
+ plugins/sudoers/sudoers.c:
+ Fix "sudo -l command args", broken in sudo 1.9.13. The value of
+ user_args should not contain the command to be run in "sudo -l
+ command args", only the arguments of the command being checked. This
+ restores the pre-1.9.13 behavior. GitHub issue #249
+ [3e1225e7bf33] <1.9>
+
+ * plugins/sudoers/logging.c, plugins/sudoers/parse.c,
+ plugins/sudoers/sudoers.c:
+ Fix "sudo -l command args", broken in sudo 1.9.13. The value of
+ user_args should not contain the command to be run in "sudo -l
+ command args", only the arguments of the command being checked. This
+ restores the pre-1.9.13 behavior. GitHub issue #249
+ [2773b6d91cf1]
+
+2023-03-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrv_util.c, logsrvd/logsrvd.c, logsrvd/logsrvd_journal.c,
+ logsrvd/sendlog.c, plugins/sudoers/log_client.c:
+ Check for sudo_pow2_roundup() overflow. Calling
+ sudo_pow2_roundup(INT_MAX+2) will return since there is no power of
+ 2 larger than INT_MAX+1 that fits in an unsigned int. This is not an
+ issue in practice since we restrict messages to 2Mib.
+ [d76de48704d0]
+
+ * src/exec_nopty.c, src/exec_pty.c:
+ write_callback: only enable /dev/tty reader if the command is
+ running This fixes a hang when there is /dev/tty data in a buffer to
+ be flushed by the final call to del_io_events(). We do not want to
+ re-enable the reader when flushing the buffers as part of
+ pty_finish(). See PR #247 for analysis of the problem and how to
+ reproduce it.
+ [b7ea5b5e6a88] <1.9>
+
+ * src/exec_nopty.c, src/exec_pty.c:
+ write_callback: only enable /dev/tty reader if the command is
+ running This fixes a hang when there is /dev/tty data in a buffer to
+ be flushed by the final call to del_io_events(). We do not want to
+ re-enable the reader when flushing the buffers as part of
+ pty_finish(). See PR #247 for analysis of the problem and how to
+ reproduce it.
+ [2cf041ccbd98]
+
+2023-02-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/testsudoers/test12.out.ok,
+ plugins/sudoers/regress/testsudoers/test12.sh:
+ Test non-fully qualified path name.
+ [0a9e6e83fe15] <1.9>
+
+ * plugins/sudoers/regress/testsudoers/test12.out.ok,
+ plugins/sudoers/regress/testsudoers/test12.sh:
+ Test non-fully qualified path name.
+ [b653458b1758]
+
+ * plugins/sudoers/Makefile.in:
+ Fix removal of y.tab.[ch] when generating gram.[ch].
+ [f69c86ecae66] <1.9>
+
+ * plugins/sudoers/Makefile.in:
+ Fix removal of y.tab.[ch] when generating gram.[ch].
+ [9c5f5be26ad0]
+
+ * MANIFEST, plugins/sudoers/regress/sudoers/test30.in,
+ plugins/sudoers/regress/sudoers/test30.json.ok,
+ plugins/sudoers/regress/sudoers/test30.ldif.ok,
+ plugins/sudoers/regress/sudoers/test30.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test30.out.ok,
+ plugins/sudoers/regress/sudoers/test30.sudo.ok,
+ plugins/sudoers/regress/sudoers/test30.toke.ok:
+ Add test for using "list" as user, runas and host.
+ [ae2c84c73371] <1.9>
+
+ * MANIFEST, plugins/sudoers/regress/sudoers/test30.in,
+ plugins/sudoers/regress/sudoers/test30.json.ok,
+ plugins/sudoers/regress/sudoers/test30.ldif.ok,
+ plugins/sudoers/regress/sudoers/test30.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test30.out.ok,
+ plugins/sudoers/regress/sudoers/test30.sudo.ok,
+ plugins/sudoers/regress/sudoers/test30.toke.ok:
+ Add test for using "list" as user, runas and host.
+ [712c96af942d]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Move handling of the "list" pseudo-command from lexer to parser. The
+ special handling of "list" in the lexer meant it could not be used
+ as a user, group or host, which was unintentional. GitHub issue
+ #246.
+ [efb3a4dea1da] <1.9>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Move handling of the "list" pseudo-command from lexer to parser. The
+ special handling of "list" in the lexer meant it could not be used
+ as a user, group or host, which was unintentional. GitHub issue
+ #246.
+ [d36f1d686343]
+
+2023-02-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_compat.h:
+ Make the check for HAVE_DECL_NSIG consistent with other decl checks.
+ [616c42c4adce] <1.9>
+
+ * include/sudo_compat.h:
+ Make the check for HAVE_DECL_NSIG consistent with other decl checks.
+ [4e6e627062af]
+
+ * plugins/sudoers/match_command.c:
+ Plug memory leak with multiple matching CHROOT= entries. Found by
+ oss-fuzz.
+ [a4982b468985]
+
+2023-02-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_13p2 for changeset 2db7cee1cb77
+ [b0af73801130] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.13p2.
+ [2db7cee1cb77] [SUDO_1_9_13p2] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.13p2.
+ [251788b2308b]
+
+2023-02-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/logging.c:
+ Include error string when formatting a SLOG_PARSE_ERROR message if
+ present.
+ [b4254bf84300]
+
+ * lib/util/lbuf.c:
+ Add missing include of errno.h.
+ [65ddd70d0c18] <1.9>
+
+ * lib/util/lbuf.c:
+ Add missing include of errno.h.
+ [669e4a4ab3ad]
+
+ * lib/util/lbuf.c:
+ sudo_lbuf_expand: check for overflow when rounding to the nearest
+ power of 2. Problem deteced by oss-fuzz using the fuzz_sudoers
+ fuzzer.
+ [9357396fdaa0] <1.9>
+
+ * lib/util/lbuf.c:
+ sudo_lbuf_expand: check for overflow when rounding to the nearest
+ power of 2. Problem deteced by oss-fuzz using the fuzz_sudoers
+ fuzzer.
+ [7d433e75c858]
+
+ * src/load_plugins.c:
+ Fix --enable-static-sudoers, broken in sudo 1.9.13.
+ sudo_qualify_plugin() should not try to fully-qualify the path to a
+ statically-compiled plugin. GitHub issue #245
+ [eca5f1f6555e] <1.9>
+
+ * src/load_plugins.c:
+ Fix --enable-static-sudoers, broken in sudo 1.9.13.
+ sudo_qualify_plugin() should not try to fully-qualify the path to a
+ statically-compiled plugin. GitHub issue #245
+ [f323e3f0a5c0]
+
+2023-02-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/sudoers.c:
+ Add sudoers open errors to the list of parse errors sent via mail.
+ Previously there would be one email for the open failure and a
+ separate one describing the parse error. Now a single email message
+ contains everything.
+ [b81299ccdad8]
+
+ * plugins/sudoers/visudo.c:
+ visudo: quiet a compiler warning on Solaris 10. Also explicitly
+ close /dev/tty fd instead of relying on closefrom() in case the fd
+ ends up being a value 0-2.
+ [d839cc458245]
+
+ * Merge pull request #244 from ffontaine/main
+
+ configure.ac: fix openssl static build
+ [af40f67e9771]
+
+ * configure, configure.ac, lib/util/Makefile.in:
+ Replace LIBMD with LIBCRYPTO display crypto/tls libs in summary. We
+ can only have one of either -lmd, -lgcrypt or -lcrypto so there is
+ no need to have more than one variable.
+ [da65125af8c6]
+
+2023-02-22 Fabrice Fontaine <fontaine.fabrice@gmail.com>
+
+ * m4/openssl.m4:
+ configure.ac: fix openssl static build
+
+ Do not use AX_APPEND_FLAG as it will break static builds by removing
+ duplicates such as -lz or -latomic which are needed by -lssl and
+ -lcrypto. This will fix the following build failure with sparc which
+ needs -latomic:
+
+ Checking for X509_STORE_CTX_get0_cert configure:21215:
+ /home/thomas/autobuild/instance-3/output-1/host/bin/sparc-buildroot-
+ linux-uclibc-gcc -o conftest -D_LARGEFILE_SOURCE
+ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Os -g0 -static
+ -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+ -DZLIB_CONST -static conftest.c
+ -L/home/thomas/autobuild/instance-3/output-1/host/bin/../sparc-
+ buildroot-linux-uclibc/sysroot/usr/lib -lssl -lz -pthread -latomic
+ -lcrypto >&5
+ /home/thomas/autobuild/instance-3/output-1/host/lib/gcc/sparc-
+ buildroot-linux-uclibc/10.4.0/../../../../sparc-buildroot-linux-
+ uclibc/bin/ld:
+ /home/thomas/autobuild/instance-3/output-1/host/bin/../sparc-
+ buildroot-linux-uclibc/sysroot/usr/lib/libcrypto.a(x509cset.o): in
+ function `X509_CRL_up_ref': x509cset.c:(.text+0x108): undefined
+ reference to `__atomic_fetch_add_4'
+
+ [...]
+
+ In file included from ./hostcheck.c:38:
+ ../../include/sudo_compat.h:342:41: error: conflicting types for
+ 'ASN1_STRING_data' 342 | # define ASN1_STRING_get0_data(x)
+ ASN1_STRING_data(x) | ^~~~~~~~~~~~~~~~
+
+ Fixes:
+ - http://autobuild.buildroot.org/results/8be59dd94e4916f9457cb435104e3
+ 6e62a28373b
+
+ Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
+ [487cfc17c742]
+
+2023-02-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/match_command.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/testsudoers/test20.out.ok,
+ plugins/sudoers/regress/testsudoers/test20.sh,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Fix potential double free for rules that include a CHROOT= option.
+ If a rule with a CHROOT= option matches the user, host and runas,
+ the user_cmnd variable could be freed twice.
+ [2c1477233f48] <1.9>
+
+ * MANIFEST, plugins/sudoers/match_command.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/testsudoers/test20.out.ok,
+ plugins/sudoers/regress/testsudoers/test20.sh,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Fix potential double free for rules that include a CHROOT= option.
+ If a rule with a CHROOT= option matches the user, host and runas,
+ the user_cmnd variable could be freed twice.
+ [a988ae0045a2]
+
+ * plugins/sudoers/visudo.c:
+ Check tcsetpgrp() return value.
+ [5d9bdb2fea15]
+
+ * MANIFEST, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/suspend_parent.c, lib/util/util.exp.in,
+ plugins/sudoers/visudo.c, src/Makefile.in, src/exec_iolog.c,
+ src/exec_nopty.c, src/regress/intercept/test_ptrace.c, src/sudo.h,
+ src/sudo_exec.h, src/suspend_nopty.c, src/tcsetpgrp_nobg.c:
+ Run the editor in its own process group. This fixes suspending the
+ editor on GNU Hurd which doesn't seem to have proper process group
+ signal handling.
+ [210e058101af]
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/fuzz/fuzz_stubs.c, plugins/sudoers/stubs.c,
+ plugins/sudoers/testsudoers.c:
+ Stub out pivot_root() and unpivot_root() for all but the sudoers
+ module.
+ [967f706e6bff]
+
+ * plugins/sudoers/match_command.c:
+ Fix build when SUDOERS_NAME_MATCH is defined.
+ [79e4613fbd85]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/pivot.c,
+ plugins/sudoers/sudoers.h:
+ Add pivot_root() and unpivot_root() to switch the root dir and
+ restore it. This will be used to more accurately handling command
+ resolution and path matching when a new root directory is specified.
+ [77300a0e1537]
+
+ * plugins/sudoers/editor.c, plugins/sudoers/find_path.c,
+ plugins/sudoers/goodpath.c,
+ plugins/sudoers/regress/editor/check_editor.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ set_cmnd_path: apply runchroot if set when finding the command path
+ Previously we would prepend runchroot to the path we were checking
+ but that does not properly handle symbolic links.
+ [3fb7ca4631c0]
+
+ * plugins/sudoers/match_command.c, plugins/sudoers/match_digest.c,
+ plugins/sudoers/parse.h:
+ match_command: apply runchroot if set when matching the command
+ Previously we would prepend runchroot to the path we were checking
+ but that does not properly handle symbolic links.
+ [41dc8f445f78]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/canon_path.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Add canon_path(), a realpath() wrapper that performs caching. This
+ also adds a new user_cmnd_dir variable that stores the canonicalized
+ parent directory of the command to be run.
+ [6065f5e76387]
+
+ * plugins/sudoers/match_command.c:
+ Match using canonicalized directories where possible.
+ [020d4ad53d07]
+
+ * src/exec_ptrace.c:
+ ptrace_intercept_execve: preserve old argv[0] after policy check. We
+ have to replace argv[0] with the pathname for the policy check but
+ want to restore it afterwards if the policy has not changed the
+ command's path name to avoid a mismatch later on.
+ [5dcd96a5c369]
+
+ * configure, configure.ac:
+ Move initial values into AC_SUBST() where possible.
+ [3db7feb16577]
+
+ * configure, configure.ac:
+ No need to AC_SUBST() standard autoconf variables.
+ [48ce145c9e40]
+
+2023-02-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * INSTALL.md:
+ Document --disable-largefile and --disable-year2038.
+ [424d17d1b83d]
+
+ * configure, configure.ac:
+ Fix indentation of intercept file in summary output.
+ [3cf0104bd2e5]
+
+ * plugins/sudoers/regress/starttime/check_starttime.c,
+ plugins/sudoers/starttime.c:
+ get_starttime: add support for GNU Hurd using the mach task_info
+ call. This is currently Hurd-specific but could be made Mach-generic
+ as long as the equivalent of pid2task() is available.
+ [a81de7fb1f83]
+
+2023-02-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/starttime/check_starttime.c:
+ Only test get_starttime() on platforms where we support it. Fixes a
+ test failure on systems where we have no way to determine a
+ process's start time.
+ [bf8dbe59b2c6]
+
+2023-02-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_13p1 for changeset 49e64402924f
+ [97ae12488007] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Merge sudo 1.9.13p1 from tip.
+ [49e64402924f] [SUDO_1_9_13p1] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.13p1
+ [0a9817096e03]
+
+ * configure.ac:
+ Use m4_bmatch, m4_case does not support shell-style globbing.
+ [b7a743baf22e]
+
+ * configure, configure.ac:
+ Allow configure.ac to be processed by autoconf 2.69. AC_PROG_CC_STDC
+ is deprecated in autoconf 2.70 and above but it is necessary for
+ autoconf 2.69.
+ [324ba83acd63]
+
+ * configure.ac:
+ Only use AC_SYS_YEAR2038 if it is defined. Otherwise, use the method
+ from 1.9.12. GitHub issue #242
+ [16fcec5264cc]
+
+2023-02-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/mkpkg:
+ Sudo-specific executables moved to /usr/libexec/sudo starting in
+ Debian 12 (Bookworm) and Ubuntu 22.04 (Jammy Jellyfish). Previously,
+ they were stored in /usr/lib/sudo.
+ [a2aa15b72312]
+
+ * lib/eventlog/Makefile.in, lib/iolog/Makefile.in,
+ lib/util/Makefile.in, logsrvd/Makefile.in,
+ plugins/python/Makefile.in, plugins/sudoers/Makefile.in,
+ src/Makefile.in:
+ Handle "locale -a" returning both C.UTF-8 and C.utf8. It is possible
+ to have mutiple matches from the output of "locale
+ -a". Just take the first one. Fixes GitHub issue #241.
+ [aeba71610439]
+
+ * lib/util/Makefile.in, logsrvd/Makefile.in,
+ plugins/sudoers/Makefile.in, src/Makefile.in:
+ Add some missing files to the clean and distclean targets.
+ [5dedbe519db1]
+
+ * Merge pull request #240 from thesamesam/c23
+
+ sudo_fatal: Fix build where compiler recognises [[noreturn]]
+ attribut…
+ [22ae0d4402ac]
+
+2023-02-15 Sam James <sam@gentoo.org>
+
+ * include/sudo_fatal.h:
+ sudo_fatal: Fix build where compiler recognises [[noreturn]]
+ attribute (C23)
+
+ If the compiler supports [[noreturn]] as a attribute as in C23, then
+ we define sudo_noreturn to be it. When that's the case, we must
+ place it at the beginning of the declaration, before any other
+ *extension* attributes (__attribute(...)).
+
+ A bug has been filed with GCC regarding rejecting/accepting mixed
+ attribute styles.
+
+ sudo_dso_public is always an extension attribute, while
+ sudo_noreturn only might be, so put it first.
+
+ This only shows up with GCC 13 so far (see the linked GCC bug for a
+ bit more exploration). Clang 16 does support the attribute but
+ doesn't let you use it for earlier language versions (need to pass
+ explicit -std=c2x, unlike with GCC here).
+
+ This is essentially a followup to
+ e707ffe58b3ccfe5c72f54c38eac1d7069d5021e.
+
+ Tested with GCC 13.0.1 20230212 (unreleased), GCC 12.2.1 20230211,
+ Clang 16.0.0_rc2, and Clang 15.0.7.
+
+ Bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108796 Closes:
+ https://github.com/sudo-project/sudo/issues/239 Fixes:
+ e707ffe58b3ccfe5c72f54c38eac1d7069d5021e Fixes:
+ 16ae61dcd7d3cd8bf6eb10a22fa742d4505da4e9
+ [806b5f3a6485]
+
+2023-02-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Add missing '[' to AS_IF() call. Fixes GitHub issue #238.
+ [48372d73d4bb]
+
+ * .hgtags:
+ Added tag SUDO_1_9_13 for changeset 813f6addf7cf
+ [8df54fde3b7a] <1.9>
+
+ * NEWS, config.h.in, configure, configure.ac, include/sudo_compat.h,
+ lib/util/hexchar.c, lib/util/regress/hexchar/hexchar_test.c,
+ plugins/sudoers/parse.c, plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/visudo.c:
+ Merge sudo 1.9.13 from tip.
+ [813f6addf7cf] [SUDO_1_9_13] <1.9>
+
+ * MANIFEST, plugins/sudoers/po/ka.mo:
+ Add compiled version of the sudoers Georgian translation.
+ [35007cc1c867]
+
+ * .gitignore, .hgignore:
+ Do not ignore .mo files. Otherwise we are likely to miss uncommitted
+ changes in them.
+ [d76a98baaf15]
+
+ * plugins/sudoers/po/ru.mo, plugins/sudoers/po/zh_CN.mo, po/zh_CN.mo:
+ Regenerate .mo files.
+ [a7a708d8bf34]
+
+2023-02-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, lib/util/Makefile.in, lib/util/realpath.c,
+ scripts/mkdep.pl:
+ Add checks for realpath(3) and a version from NetBSD for those
+ without it.
+ [121fb2ed88de]
+
+2023-02-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ No longer need to define sudoers_recovery here.
+ [11a365a8a218]
+
+ * NEWS:
+ Mention that a missing include file is no longer fatal.
+ [ba0bd554435e]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y, plugins/sudoers/policy.c:
+ Recover from missing include file unless error_recovery is disabled.
+ It is still treated as an error from a logging perspective, and mail
+ is still sent.
+ [e1cac68917cc]
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c,
+ plugins/sudoers/logging.c:
+ Add eventlog_mail() to send a log message via mail. This is used by
+ mail_parse_errors() to send multi-line messages. Previously, the
+ newlines would be escaped as control characters.
+ [97e516576212]
+
+ * lib/eventlog/eventlog.c:
+ send_mail: pass a single string instead of using varargs These days
+ we only ever pass in a const string.
+ [700e72ca42c0]
+
+2023-02-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac, m4/sudo.m4, pathnames.h.in,
+ plugins/sudoers/visudo.c:
+ Substitute for _PATH_SUDO* variables in pathnames.h. Previously
+ these were hard-coded with Makefile overrides.
+ [53c8be4b6af3]
+
+2023-02-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Use AS_IF instead of if; then where possible.
+ [56946f4ac23a]
+
+2023-02-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Mention the fix for GitHub #237.
+ [70aafdaced09]
+
+ * plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/zh_TW.mo, plugins/sudoers/po/zh_TW.po, po/fur.mo,
+ po/fur.po, po/ja.mo, po/ja.po, po/zh_TW.mo, po/zh_TW.po:
+ Updated translations from translationproject.org
+ [c3be19c34043]
+
+ * src/exec_pty.c, src/tgetpass.c:
+ Display error in error message if we can't restore the terminal.
+ [aa2c60802b33]
+
+2023-02-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_pty.c, src/tgetpass.c:
+ Display an error message if unable to restore terminal settings.
+ [a1efb1dca169]
+
+ * Makefile.in, etc/sudo.pp, plugins/sudoers/Makefile.in:
+ Get rid of sudoersdir and just use sysconfdir. There is no need for
+ sudoersdir when it is always just set to sysconfdir.
+ [690b44edcec2]
+
+ * src/exec_pty.c:
+ pty_finish: only restore the terminal if sudo is the foreground
+ process
+ [357d90f11750]
+
+ * src/exec_pty.c:
+ Better background job detection when running a command in a pty. If
+ sudo is not the process group leader and stdin is not a tty, we may
+ be running as a background job via a shell script. Start the command
+ in the background to avoid changing the terminal mode from a
+ background process. GitHub issue #237
+ [6c74910ea869]
+
+ * src/exec_pty.c:
+ suspend_sudo_pty: stop the process group even if sudo is not the
+ leader. When sudo is not the process group leader, we still need to
+ stop sudo's process group and not just the sudo process itself. If
+ we only send the signal to sudo itself, the shell will not notice if
+ it is not in monitor mode. This can happen when sudo is run from a
+ shell script, for example. In this case we need to signal the shell
+ itself. If the process group leader is no longer present, we must
+ kill the command since there will be no one to resume us.
+ [44bb3267a55e]
+
+ * lib/util/term.c:
+ Add debug tracing to tcsetattr_nobg().
+ [b7a17174f1cf]
+
+2023-01-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Avoid compilation errors if getaddrinfo() or freeaddrinfo() are
+ macros. If this is the case we probably can't stub out the functions
+ but at least the fuzzer will compile.
+ [2482db79d3b9]
+
+ * src/net_ifs.c:
+ Initialize the integer result parameter passed to SIOCGIFANUM. It
+ appears that passing in a non-zero value causes the ioctl() to fail.
+ From Tim Rice.
+ [071633f9929c]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd_relay.c,
+ plugins/sudoers/log_client.c:
+ Protect use of AF_INET6 with HAVE_STRUCT_IN6_ADDR guards. From Tim
+ Rice.
+ [661c26064544]
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h:
+ Add configure test for NSIG, _NSIG or __NSIG. This is better than
+ just defining NSIG in sudo_compat.h if it is not defined since
+ signal.h may not have been included.
+ [f1c94c5f825b]
+
+ * logsrvd/logsrvd_conf.c:
+ Avoid DNS lookups when fuzzing.
+ [384ffdead655]
+
+2023-01-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * etc/sudo-logsrvd.pp, etc/sudo-python.pp, etc/sudo.pp, scripts/mkpkg,
+ scripts/pp:
+ No longer need to treat Rocky or Alma Linux specially. We now treat
+ them the same as RHEL.
+ [190afa102ca6]
+
+2023-01-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #230 from trackers-lover/main
+
+ Return value does not match
+ [1dc4317beaf7]
+
+2023-01-29 bianguangze@uniontech.com <bianguangze@uniontech.com>
+
+ * lib/util/sudo_conf.c:
+ Modify return value parameter
+ [eb1e78bb2f91]
+
+2023-01-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/build_pkgs:
+ Store conf hash in vm_servers instead of vmid. Add a shutdown
+ command fallback to the conf file.
+ [2f7eeb5c3f04]
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/ro.mo, plugins/sudoers/po/ro.po,
+ plugins/sudoers/po/ru.po, plugins/sudoers/po/sv.mo,
+ plugins/sudoers/po/sv.po, plugins/sudoers/po/uk.mo,
+ plugins/sudoers/po/uk.po, plugins/sudoers/po/zh_CN.po,
+ plugins/sudoers/po/zh_TW.po, po/cs.mo, po/cs.po, po/de.mo, po/de.po,
+ po/eo.mo, po/eo.po, po/fr.mo, po/fr.po, po/hr.mo, po/hr.po,
+ po/ko.mo, po/ko.po, po/pl.mo, po/pl.po, po/ro.mo, po/ro.po,
+ po/sv.mo, po/sv.po, po/uk.mo, po/uk.po, po/zh_CN.po, po/zh_TW.po:
+ Updated translations from translationproject.org
+ [fa9569203e16]
+
+ * configure, m4/hardening.m4:
+ Fix a typo.
+ [ebf4c16e0079]
+
+ * config.h.in, configure, scripts/config.guess, scripts/config.sub:
+ Regen with latest autoconf git.
+ [9a0bbbb682fc]
+
+ * etc/sudo-logsrvd.pp, etc/sudo-python.pp, etc/sudo.pp, scripts/mkpkg,
+ scripts/pp:
+ Recognize Alma Linux and Rocky Linux (Open Source RHEL clones)
+ [b1dbb7b75824]
+
+ * NEWS:
+ Mention the recent intercept/log_subcmds fix.
+ [cbd60701de52]
+
+ * scripts/mkpkg:
+ Fix determination of the number of CPU cores on Linux.
+ [6ac6a9b074bf]
+
+2023-01-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/po/ka.po:
+ New Georgian translation from translationproject.org
+ [17681b870666]
+
+ * Merge pull request #235 from kernelmethod/apparmor_dependencies
+
+ Replace the Debian libselinux1 dependency with libapparmor1
+ [ca29638c5c34]
+
+2023-01-26 kernelmethod <17100608+kernelmethod@users.noreply.github.com>
+
+ * etc/sudo.pp:
+ Replace the Debian libselinux1 dependency with libapparmor1
+
+ Debian >= 10 uses AppArmor by default instead of SELinux, so
+ SELinux-related sudo features are typically going to be unusable in
+ Debian installs. This changes the dependency on libselinux1 to be a
+ dependency on libapparmor1 for .deb packages built with `make
+ package`.
+ [5779ce23a161]
+
+2023-01-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.c:
+ get_execve_info: defer setting pathname until argbuf is finalized If
+ we reallocate the buffer (via growbuf()) in ptrace_read_vec(), the
+ address of argbuf may change. If so, the value stored in pathname
+ will no longer be valid. GitHub issue #194.
+ [f75aa1eb5d95]
+
+ * src/exec_intercept.c, src/exec_ptrace.c:
+ Correct error message when command doesn't exist in intercept mode.
+ Previously, we would always use EACCES, even when ENOENT was
+ appropriate. This also affected log_subcmds.
+ [5bc0ecd5d4e6]
+
+2023-01-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ Update .pot files for 1.9.13
+ [c6a247e05a91]
+
+2023-01-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Update for 1.9.13.
+ [c9c5b6af5ea5]
+
+ * src/exec_ptrace.h:
+ Include elf.h, not linux/elf.h but define NT_ARM_SYSTEM_CALL if
+ missing. Older kernel headers are missing the definition of EM_ARM
+ in linux/elf.h. GitHub issue #232
+ [8bed5e7f8857]
+
+ * lib/util/regress/regex/regex_test.c:
+ Add tests for escaped digits.
+ [7e5b7e5e2409]
+
+ * lib/util/regex.c:
+ check_pattern: handle escaped digits since GNU libc accepts them.
+ [a20d5a047963]
+
+2023-01-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c,
+ plugins/sudoers/sudoreplay.c:
+ Add eventlog_store_sudo() and use it in sudoreplay. This replaces
+ the custom log formatting used by "sudoreplay -l".
+ [26dd2367fbdd]
+
+2023-01-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/build_pkgs, scripts/mkpkg:
+ Add --build-only flag to skip building packages.
+ [46c0213b2668]
+
+2023-01-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/mkpkg, scripts/pp:
+ Suport building packages on DragonFly BSD.
+ [65920923add2]
+
+ * configure, configure.ac, m4/visibility.m4:
+ Try to link a simple shared object with -Wl,--no-undefined. This
+ only works for gcc-style compilers, which should not be a problem.
+ The source uses environ (FreeBSD) and errno (OpenBSD).
+ [1c2d9f90bc6d]
+
+ * scripts/build_pkgs:
+ Pass the name to the config.cache file to the build script. If
+ --cache-file is not specified, no config.cache file will be used.
+ Add an "omit_artifacts" setting for platforms where we don't publish
+ artifacts.
+ [c87221f36bf4]
+
+2023-01-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/regex.c:
+ check_pattern: accept a backslash before the numeric bound like
+ glibc. This helps avoid out-of-memory conditions when fuzzing on
+ Linux.
+ [07f14dba22ed]
+
+ * configure, configure.ac:
+ Don't use -Wl,--no-undefined with the sanitizers/fuzzers. It breaks
+ linking when using -fsanitize with clang at least.
+ [a6331135bd73]
+
+ * docs/SECURITY.md:
+ Add a link to the sudo security advisories archive.
+ [7137d1d214e5]
+
+ * config.h.in, configure, configure.ac:
+ Eliminate usage of obsolete 2-argument AC_CHECK_TYPE macro.
+ [96b37c574fc2]
+
+ * config.h.in, configure, configure.ac, plugins/sudoers/starttime.c,
+ src/regress/ttyname/check_ttyname.c, src/ttyname.c:
+ Add support for the struct kinfo_proc on Dragonfly BSD.
+ [4c1a7d223d66]
+
+ * configure, configure.ac:
+ Need to link sudo and sudoers with -lutil on Dragonfly BSD. It is
+ safer to just search for setusercontext() in libc and libutil
+ instead of matching on the operating system.
+ [b91a288c9968]
+
+ * configure, configure.ac:
+ Elminate the $OS variable, we can just use $host_os instead.
+ [0293bf9d4dd4]
+
+ * plugins/sudoers/editor.c:
+ Restore the line that set errno to ENOENT when find_path() fails.
+ This was inadvertently removed when the "goto bad" was added.
+ [b957909a1a75]
+
+ * configure, configure.ac, m4/ldap.m4:
+ Add -Wl,--no-undefined to LDFLAGS if it is supported. This will find
+ missing symbols at build-time instead of run-time. Don't use it on
+ FreeBSD where environ is filled in by the dynamic loader. We also
+ need to pull in -llber with -lldap where possible (instead of
+ relying on DT_NEEDED) to avoid undefined symbol errors when building
+ with LDAP support.
+ [c88bd9fd05c9]
+
+ * plugins/sample/README:
+ The sample plugin is now built by default to avoid bit rot. GitHub
+ issue #234.
+ [aac2a29136e1]
+
+ * plugins/sample/sample_plugin.c:
+ The change from sudo_printf -> sudo_plugin_printf was incomplete.
+ Fixes GitHub issue #234.
+ [4f8333e3f7b8]
+
+2023-01-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, m4/pie.m4:
+ Solaris: use lt_prog_compiler_pic instead of assuming -KPIC
+ [36b94699ad63]
+
+ * configure, m4/hardening.m4, m4/pie.m4:
+ Solaris: the aslr, nxheap and nxstack link options are only for
+ executables. Move them back to PIE_LDFLAGS, which is only used when
+ linking a binary.
+ [970d533cd9b2]
+
+ * configure, m4/hardening.m4, m4/pie.m4:
+ Solaris: move aslr linker option to hardening and try to build real
+ PIEs These flags are specific to the Solaris linker.
+ [c5439fec5cb3]
+
+ * configure, m4/hardening.m4, m4/pie.m4:
+ Enable non-executable heap and stack options for Solaris ld.
+ [5be638b9bd79]
+
+ * configure, configure.ac, m4/hardening.m4:
+ Limit some of the hardening tests to compilers that define __GNUC__.
+ This should avoid false positives on other compilers.
+ [1b3b36a2ff2b]
+
+ * plugins/python/regress/testdata/check_multiple_approval_plugin_and_a
+ rguments.stdout:
+ Update expected plugin version.
+ [19b2963008a2]
+
+ * docs/sudo_plugin.man.in, docs/sudo_plugin.mdoc.in,
+ include/sudo_plugin.h, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h, src/sudo.c,
+ src/sudo.h, src/sudo_edit.c:
+ Pass back the number of files to edit when using sudoedit. The sudo
+ front-end can use this to determine where the list of files to edit
+ begins.
+ [c9c1e6e81438]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in, docs/sudoreplay.man.in,
+ docs/sudoreplay.mdoc.in, include/sudo_lbuf.h,
+ lib/eventlog/eventlog.c, lib/iolog/iolog_json.c, lib/util/lbuf.c,
+ lib/util/util.exp.in, plugins/sudoers/sudoreplay.c:
+ Escape control characters in log messages and "sudoreplay -l"
+ output. The log message contains user-controlled strings that could
+ include things like terminal control characters. Space characters in
+ the command path are now also escaped.
+
+ Command line arguments that contain spaces are surrounded with
+ single quotes and any literal single quote or backslash characters
+ are escaped with a backslash. This makes it possible to distinguish
+ multiple command line arguments from a single argument that contains
+ spaces.
+
+ Issue found by Matthieu Barjole and Victor Cutillas of Synacktiv
+ (https://synacktiv.com).
+ [1cd37144190c]
+
+ * NEWS:
+ Merge in sudo 1.9.12p2 changes.
+ [d5a2cd780f27]
+
+ * .hgtags:
+ Added tag SUDO_1_9_12p2 for changeset 05149e3ee7db
+ [8763a9e70ddd] <1.9>
+
+2023-01-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Add back the linker check for -fstack-clash-protection. This is
+ expected to fix GitHub issue #231.
+ [40bda374ae08] <1.9>
+
+ * configure, m4/hardening.m4:
+ Add back the linker check for -fstack-clash-protection. This is
+ expected to fix GitHub issue #231.
+ [c08c0a7c8613]
+
+2023-01-17 trackers-love <bianguangze@uniontech.com>
+
+ * lib/util/sudo_conf.c:
+ Return value does not match
+ [2c7c350c3d97]
+
+2023-01-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/cvtsudoers.man.in, docs/cvtsudoers.mdoc.in,
+ docs/sudo.conf.man.in, docs/sudo.conf.mdoc.in,
+ docs/sudo_logsrvd.conf.man.in, docs/sudo_logsrvd.conf.mdoc.in,
+ docs/sudoers.ldap.man.in, docs/sudoers.ldap.mdoc.in,
+ docs/sudoers.man.in, docs/sudoers.mdoc.in, docs/visudo.man.in,
+ docs/visudo.mdoc.in:
+ Stop using 8n width in tagged lists. Use either 4n, when the body is
+ expected to wrap or the width of the longest tag when no wrapping is
+ expected.
+ [2b1bc5d31250]
+
+ * docs/cvtsudoers.man.in, docs/cvtsudoers.mdoc.in, docs/sudo.man.in,
+ docs/sudo.mdoc.in, docs/sudo_logsrvd.man.in,
+ docs/sudo_logsrvd.mdoc.in, docs/sudo_sendlog.man.in,
+ docs/sudo_sendlog.mdoc.in, docs/sudoreplay.man.in,
+ docs/sudoreplay.mdoc.in, docs/visudo.man.in, docs/visudo.mdoc.in:
+ Use -width Ds for the options list, not -width Fl.
+ [598dbf3d2fea]
+
+ * docs/sudo.man.in, docs/sudo.mdoc.in, docs/sudo_logsrvd.conf.man.in,
+ docs/sudo_logsrvd.conf.mdoc.in, docs/sudo_plugin_python.man.in,
+ docs/sudo_plugin_python.mdoc.in:
+ Reduce the offset of bullet lists to 1n.
+ [893b6fd25564]
+
+ * INSTALL.md:
+ Shorten --with-passprompt and --with-mailsubject arguments to a
+ single word. The script that generates the web version of this file
+ doesn't expect options to include whitespace.
+ [063dc2c168aa]
+
+2023-01-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * INSTALL.md:
+ Shorten --with-badpass-message argument to a single word. The
+ fix_install script can't deal with whitespace in options.
+ [17761c19a4b8]
+
+ * LICENSE.md:
+ Make numbered lists more markdown-friendly. Also add line breaks
+ when there are multiple authors.
+ [d22146e06e27]
+
+ * INSTALL.md:
+ Make lists of directories more markdown-friendly.
+ [b3295e422b33]
+
+2023-01-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/regress/iolog_mkpath/check_iolog_mkpath.c:
+ Check for errors when removing the temp directory. If we cannot
+ remove the directory tree that may indicate a file or directory mode
+ problem.
+ [4a162644b61f]
+
+ * lib/iolog/iolog_mkdtemp.c:
+ iolog_mkdtemp: fix pasto in last commit Set mode to iolog_dirmode,
+ not iolog_filemode
+ [9926f1c92729] <1.9>
+
+ * lib/iolog/iolog_mkdtemp.c:
+ iolog_mkdtemp: fix pasto in last commit Set mode to iolog_dirmode,
+ not iolog_filemode
+ [713773e23472]
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.2p2
+ [05149e3ee7db] [SUDO_1_9_12p2] <1.9>
+
+ * plugins/sudoers/editor.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/visudo.c:
+ sudoedit: do not permit editor arguments to include "--"
+ (CVE-2023-22809) We use "--" to separate the editor and arguments
+ from the files to edit. If the editor arguments include "--", sudo
+ can be tricked into allowing the user to edit a file not permitted
+ by the security policy. Thanks to Matthieu Barjole and Victor
+ Cutillas of Synacktiv (https://synacktiv.com) for finding this bug.
+ [eb7f573a4a92] <1.9>
+
+ * plugins/sudoers/editor.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/visudo.c:
+ sudoedit: do not permit editor arguments to include "--"
+ (CVE-2023-22809) We use "--" to separate the editor and arguments
+ from the files to edit. If the editor arguments include "--", sudo
+ can be tricked into allowing the user to edit a file not permitted
+ by the security policy. Thanks to Matthieu Barjole and Victor
+ Cutillas of Synacktiv (https://synacktiv.com) for finding this bug.
+ [2ca90805f471]
+
+2023-01-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/sha2.c:
+ In SHA256Pad and SHA512Pad use 511 and 1023 respectively for bitwise
+ AND. Previously we were using 504 and 1016 which still produces the
+ correct result since padding is done in 8-bit bytes. However, using
+ size-1 for the bitwise AND makes the intent clearer and likely would
+ have prevented the previous bug in SHA512Pad. From Matthieu Barjole
+ and Victor Cutillas of Synacktiv (https://synacktiv.com)
+ [4b6a50800ecd]
+
+ * plugins/sudoers/env.c:
+ env_file_next_local: change the order of the val_len check. It makes
+ more sense to verify that val_len > 1 before using it. This is not a
+ problem in practice because val[val_len - 1] is guaranteed not to
+ underflow but it can confuse reviewers and static analyzers.
+ [9d6bed4e3fd0]
+
+ * plugins/sudoers/env.c:
+ Fix typo in check for environment variables that start with '='.
+ [6dc466c8bf82]
+
+ * lib/util/lbuf.c:
+ sudo_lbuf_print: no longer need to check for lbuf->len > 0. Now that
+ lbuf length is unsigned the earlier check for len == 0 is
+ sufficient.
+ [bdfc863f5b5c]
+
+ * lib/util/lbuf.c:
+ Increase minimum allocation size from 256 to 1024 bytes.
+ [0f49c8728151]
+
+ * plugins/sudoers/sudoreplay.c:
+ Fix IS_IDLOG macro, it was testing the wrong byte for the NUL. This
+ causes the macro to evaluate to false even for valid TSIDs.
+ [77686e4508d3]
+
+2023-01-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ sudoers_trace_print: this is a no-op if not debugging
+ [df34de2e60f4]
+
+ * lib/util/lbuf.c:
+ sudo_lbuf_expand: don't allocate less than 256 bytes at a time.
+ [a747682156e6]
+
+2023-01-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/lbuf.c:
+ sudo_lbuf_expand: round nearest power of two instead of multiple of
+ 256.
+ [840855b501de]
+
+ * LICENSE.md:
+ Update copyright year.
+ [5ff97b5e6bcd]
+
+ * include/sudo_lbuf.h, lib/util/lbuf.c:
+ sudo_lbuf_expand: check for possible integer overflow The numeric
+ fields in struct sudo_lbuf are now unsigned so that wraparound is
+ defined, this make the overflow checks simpler. Problem deteced by
+ oss-fuzz using the fuzz_sudoers fuzzer.
+ [6dc670d15276]
+
+ * MANIFEST, lib/iolog/iolog_json.c,
+ lib/iolog/regress/iolog_json/test3.in,
+ lib/iolog/regress/iolog_json/test3.out.ok:
+ Decode \u00XX in a JSON string now that we escape control chars. We
+ don't write Unicode to the log.json file, only 8-bit ASCII.
+ [83dcacb35309]
+
+ * MANIFEST, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/hexchar.c, lib/util/regress/hexchar/hexchar_test.c,
+ lib/util/util.exp.in, plugins/sudoers/Makefile.in,
+ plugins/sudoers/hexchar.c, plugins/sudoers/match_digest.c,
+ plugins/sudoers/parse.h,
+ plugins/sudoers/regress/parser/check_hexchar.c,
+ plugins/sudoers/toke_util.c:
+ Move hexchar() from the sudoers plugin to lib/util.
+ [4a6c57c1b66a]
+
+ * lib/util/mkdir_parents.c:
+ sudo_open_parent_dir: adjust loop terminating condition Checking for
+ ep < pathend should be a bit clearer than ep != '\0' and has the
+ advantage of working when pathend doesn't point to a NUL byte. No
+ intended change in behavior.
+ [cee4e0c71070]
+
+ * lib/iolog/iolog_mkdtemp.c:
+ iolog_mkdtemp: fix failure when the specified path contains
+ subdirectories. This fixes a bug introduced in sudo 1.9.12.
+ [ac86f3b0d94b] <1.9>
+
+ * lib/iolog/iolog_mkdtemp.c:
+ iolog_mkdtemp: fix failure when the specified path contains
+ subdirectories. This fixes a bug introduced in sudo 1.9.12.
+ [3a1d5b01b446]
+
+ * lib/iolog/regress/iolog_mkpath/check_iolog_mkpath.c:
+ check_iolog_mkpath: fix exit value
+ [9ac13d6657f6]
+
+2023-01-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #227 from sohomdatta1/integer_underflow
+
+ Prevent integer underflow due to environment variable
+ [c6c716352077]
+
+2023-01-02 Sohom <sohomdatta1+git@gmail.com>
+
+ * plugins/sudoers/env.c:
+ Prevent integer underflow due to environment variable
+
+ Gaurd against replacing quotes when the environment variable val_len
+ is 1.
+ [1b926824dcf8]
+
+2023-01-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/regex.c:
+ glibc allows the ',' in {low,high} to be escaped with a backslash.
+ Adjust bound parsing to match this.
+ [b2bbac2bab6a]
+
+2022-12-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Fix logic goof in 05781ba6f1f3, disable replacements when fuzzing.
+ Not the other way around.
+ [abcf2deb9d0e]
+
+2022-12-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac, docs/sudo_plugin_python.man.in,
+ docs/sudo_plugin_python.mdoc.in, docs/sudoers.man.in,
+ docs/sudoers.mdoc.in:
+ Substitute python plugin file name in sudo_plugin_python
+ documentation. Also use prefix for group plugin fallback path
+ section in sudoers manual.
+ [e245808fbe74]
+
+ * lib/iolog/Makefile.in,
+ lib/iolog/regress/fuzz/fuzz_iolog_legacy.dict,
+ lib/iolog/regress/fuzz/fuzz_iolog_timing.dict:
+ Use correct dictionary file format. Also use the new dictionaries in
+ the Makefile fuzz target.
+ [c39e699cb9b6]
+
+ * MANIFEST, lib/iolog/regress/corpus/seed/log_legacy/less.log,
+ lib/iolog/regress/corpus/seed/log_legacy/smtpctl.log,
+ lib/iolog/regress/corpus/seed/log_legacy/vi.log,
+ lib/iolog/regress/corpus/seed/timing/timing.5,
+ lib/iolog/regress/corpus/seed/timing/timing.6,
+ lib/iolog/regress/corpus/seed/timing/timing.7,
+ lib/iolog/regress/corpus/seed/timing/timing.8,
+ lib/iolog/regress/corpus/seed/timing/timing.9:
+ Add some addition entries for the I/O log fuzzer seed corpus.
+ [51d4bf5f014c]
+
+ * MANIFEST, lib/iolog/regress/fuzz/fuzz_iolog_legacy.dict,
+ lib/iolog/regress/fuzz/fuzz_iolog_timing.dict:
+ Add dictionaries for fuzz_iolog_legacy and fuzz_iolog_timing.
+ [84d1e53ea8eb]
+
+ * include/sudo_fatal.h:
+ Don't send warn/fatal output to the debug file when fuzzing.
+ [968fedf79f23]
+
+ * lib/util/getentropy.c:
+ Back out the genentropy.c portion of c648cfe9ff0f We don't need to
+ special-case FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION now that we
+ use the glibc arc4random() where available.
+ [7d69e44e3e9b]
+
+2022-12-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/regress/fuzz/fuzz_iolog_json.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_legacy.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_timing.c,
+ lib/util/regress/fuzz/fuzz_sudo_conf.c,
+ logsrvd/regress/fuzz/fuzz_logsrvd_conf.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c:
+ Use initprogname(), not setprogname() in the fuzzers. This results
+ in better coverage for progname.c.
+ [dede53f4b0db]
+
+ * lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_conf/test1.out.ok,
+ lib/util/regress/sudo_conf/test2.out.ok,
+ lib/util/regress/sudo_conf/test3.out.ok,
+ lib/util/regress/sudo_conf/test4.out.ok,
+ lib/util/regress/sudo_conf/test5.out.ok,
+ lib/util/regress/sudo_conf/test6.out.ok,
+ lib/util/regress/sudo_conf/test7.out.ok:
+ Add probe_interfaces and intercept_path.
+ [f00ecf67a5e1]
+
+ * lib/util/regress/fuzz/fuzz_sudo_conf.c:
+ Exercise getter functions.
+ [3208a9508724]
+
+ * configure, configure.ac:
+ Avoid using our function replacements when fuzzing (where possible).
+ We don't want to fuzz the function replacements themselves as this
+ can skew the coverage reports.
+ [05781ba6f1f3]
+
+ * plugins/python/regress/check_python_examples.c:
+ Disable sudo_debug tests when fuzzing. The debug code is disable
+ when fuzzing is enabled to avoid coverage issues.
+ [2c90549a0918]
+
+ * lib/util/fatal.c, lib/util/getentropy.c, lib/util/sudo_conf.c:
+ Avoid compiling some code paths that are unreachable when fuzzing.
+ [c648cfe9ff0f]
+
+ * plugins/sudoers/regress/serialize_list/check_serialize_list.c:
+ Plug memory leak.
+ [6189ff1db193]
+
+2022-12-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.dict:
+ Update fuzz_policy keywords to match current policy settings.
+ [0db960f83cf1]
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.dict:
+ Add example users and groups to the dictionary.
+ [6fd8ad758aed]
+
+ * plugins/sudoers/env.c, plugins/sudoers/sudoers.c, src/parse_args.c:
+ parse_args: an environment variable may not start with '='. Also
+ check VAR=val format in validate_env_vars() and add an error message
+ if insert_env_vars() fails.
+ [b9b9acae1671]
+
+ * plugins/sudoers/env.c:
+ rebuild_env: avoid a potential NULL dereference in fuzz_policy
+ [90f5d579dd69]
+
+ * plugins/sudoers/sudoers.c:
+ sudoers_policy_main: plug memory leak of iolog_path on error.
+ [99cbe3d513e6]
+
+ * plugins/sudoers/env.c:
+ rebuild_env: avoid a potential NULL dereference in fuzz_policy
+ [de05b4f00f35]
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ The contents of the env_add array should not include the leading
+ "env=" prefix. The previous fix for this was incomplete.
+ [849fee26133a]
+
+ * plugins/sudoers/env.c:
+ validate_env_vars: more efficient errbuf handling Also avoid
+ appending to errbuf if it is already full.
+ [1ffd174fa0ea]
+
+2022-12-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudo.man.in, docs/sudo.mdoc.in:
+ Document that -k does not interfere with sudo on other terminals.
+ This should help clarify the difference between "sudo -k" and "sudo
+ -K".
+ [589d750faf30]
+
+ * lib/util/regex.c, lib/util/regress/regex/regex_test.c:
+ Check for bound values larger than 255 and reject them. This is to
+ prevent the fuzzers from running out of memory.
+ [f172a6d64a34]
+
+ * scripts/pp:
+ Use the POSIX shell "command -v" instead of "which" to find
+ programs. Fix false detection of init.d/service status.
+ [aee53eddfc18]
+
+ * etc/sudo.pp:
+ Fix example dir mode on RedHat/Fedora.
+ [f5fd86f35bc5]
+
+ * etc/sudo.pp:
+ Use sed instead of ed to modify the packaged sudoers file. Some
+ Linux distros do not include /bin/ed by default.
+ [217ef1afaacb]
+
+2022-12-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudo.conf.man.in, docs/sudo.conf.mdoc.in:
+ Use @intercept_file@ and @noexec_file@ like the example file.
+ [726e060da20e]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ There is a @pam_login_service@ substitution but no @pam_service@.
+ Just use sudo instead of @pam_service@.
+ [b16f28ccc847]
+
+ * examples/sudo.conf.in:
+ Use @sudoers_plugin@ instead of @sudoers_module@.
+ [4c92b9ef93b5]
+
+ * docs/sudo.conf.man.in, docs/sudo.conf.mdoc.in, docs/sudoers.man.in,
+ docs/sudoers.mdoc.in, docs/visudo.man.in, docs/visudo.mdoc.in:
+ Use @sudoers_plugin@ instead of @sudoers_module@.
+ [3c50a97c1bbd]
+
+ * INSTALL.md, NEWS, config.h.in, configure, configure.ac,
+ docs/UPGRADE.md, scripts/config.guess, scripts/config.sub:
+ sudo 1.9.13 Document the changes to AIX plugins in docs/UPGRADE.md
+ and regenerate configure using the latest autoconf from git.
+ [b897ca965a0f]
+
+ * scripts/build_pkgs:
+ Remove anything after whitespace in MANIFEST when building tarball.
+ This is consistent with how sudo's Makefile builds the tarball.
+ [db48ecf91964]
+
+ * MANIFEST:
+ Zap trailing whitespace.
+ [7be2d953e0ca]
+
+ * configure, configure.ac, docs/sudo.conf.man.in,
+ docs/sudo.conf.mdoc.in, docs/sudoers.man.in, docs/sudoers.mdoc.in,
+ docs/visudo.man.in, docs/visudo.mdoc.in, examples/sudo.conf.in,
+ pathnames.h.in, src/load_plugins.c, src/preload.c:
+ Use AIX-style shared libraries on AIX by default instead of
+ SVR4-style. This removes the need to use the -brtl linker flag which
+ can cause problems when there are both a .so and .a version of the
+ same library but with different versions. This was particularly
+ problematic when using the AIX freeware version of OpenSSL. The
+ --with-aix-soname=svr4 option can be used to build SVR4-style shared
+ libs instead.
+ [268bd3bc7717]
+
+ * lib/util/sudo_dso.c, src/load_plugins.c:
+ sudo_dso_load: add AIX fallback path from shlib.so to
+ shlib.a(shlib.so). If the .so file is missing but the .a file
+ exists, try to dlopen() the AIX .a file using the .so name as the
+ member. We need to avoid breaking existing configurations if the
+ type of AIX shared library changes when sudo is upgraded.
+ [f64cf05bb2c2]
+
+ * plugins/sudoers/group_plugin.c, src/load_plugins.c:
+ Remove the owner and mode checks when loading a sudo plugin. The
+ sudo.conf file is considered a trusted source of information and
+ these checks suffer from TOCTOU issues anyway. The checks complicate
+ loading of shared objects since we need to perform fallback
+ processing twice.
+ [60a811d58138]
+
+ * MANIFEST, plugins/python/Makefile.in,
+ plugins/python/python_importblocker.c,
+ plugins/python/python_plugin_common.c,
+ plugins/python/regress/check_python_examples.c,
+ plugins/python/regress/testdata/sudo.conf.developer_mode,
+ plugins/python/regress/testdata/sudo.conf.normal_mode,
+ plugins/python/regress/testhelpers.c,
+ plugins/python/regress/testhelpers.h,
+ plugins/python/sudo_python_module.h:
+ Remove the Python plugin import blocker code. The sudo.conf file is
+ considered a trusted source of information and these checks suffer
+ from TOCTOU issues anyway.
+ [1d261d802b82]
+
+ * MANIFEST, docs/sudo.conf.man.in, docs/sudo.conf.mdoc.in,
+ docs/sudo_plugin_python.man.in, docs/sudo_plugin_python.mdoc.in,
+ examples/sudo.conf.in,
+ lib/util/regress/corpus/seed/sudo_conf/sudo.conf.1,
+ lib/util/regress/corpus/seed/sudo_conf/sudo.conf.2,
+ lib/util/regress/corpus/seed/sudo_conf/sudo.conf.3,
+ lib/util/regress/fuzz/fuzz_sudo_conf.dict,
+ lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_conf/test1.in,
+ lib/util/regress/sudo_conf/test1.out.ok,
+ lib/util/regress/sudo_conf/test2.out.ok,
+ lib/util/regress/sudo_conf/test3.out.ok,
+ lib/util/regress/sudo_conf/test4.out.ok,
+ lib/util/regress/sudo_conf/test5.out.ok,
+ lib/util/regress/sudo_conf/test6.out.ok,
+ lib/util/regress/sudo_conf/test7.out.ok,
+ lib/util/regress/sudo_conf/test8.err.ok,
+ lib/util/regress/sudo_conf/test8.in,
+ lib/util/regress/sudo_conf/test8.out.ok, lib/util/sudo_conf.c:
+ Remove developer mode from sudo.conf, it is no longer used.
+ [2b350bfe4d7c]
+
+ * plugins/sudoers/sudoers_version.h:
+ Bump SUDOERS_GRAMMAR_VERSION to 50 for the new list pseudo-command.
+ [60e6e3b59b1e]
+
+2022-12-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/Makefile.in, docs/sudo.man.in, docs/sudo.mdoc.in,
+ docs/sudo_plugin_python.man.in, docs/sudo_plugin_python.mdoc.in,
+ docs/sudoreplay.man.in, docs/sudoreplay.mdoc.in:
+ Use ".Sy root" instead of ".Em root" when talking about the root
+ user. Replace MANDOCPROG with "mandoc" now that MANDOCPROG has been
+ removed.
+ [a0b80a88eb7c]
+
+2022-12-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #226 from rtczza/main
+
+ debug_return_int use error
+ [7743f67838ae]
+
+2022-12-23 wanglujun <wanglujun@uniontech.com>
+
+ * src/exec_pty.c:
+ debug_return_int use error
+ [b69796b9b10b]
+
+2022-12-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/sudo_dso.c, src/load_plugins.c:
+ Fix support for AIX-style path(module) syntax in sudo.conf Plugin
+ lines.
+ [b8666283d2f2]
+
+2022-12-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudo.man.in, docs/sudo.mdoc.in:
+ Mention the "list" privilege in the description of the -U option.
+ [f5416004ef2e]
+
+ * docs/sudo.man.in, docs/sudo.mdoc.in, src/parse_args.c,
+ src/sudo_usage.h.in:
+ Add [arg ...] after command in SYNOPSIS and usage output. Use Ar
+ markup when referring to the command and args.
+ [40fca0824680]
+
+2022-12-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_preload.c:
+ fmtstr: call va_arg() for %c when computing length. Even though we
+ don't need to read the actual char to know its length, we do need to
+ consume it to get the correct value for the next format.
+ [fadd0047868b]
+
+ * configure, m4/sanitizer.m4:
+ SUDO_CHECK_SANITIZER: quote "$3" in awk script so m4 doesn't eat it.
+ [fcf1661bfebd]
+
+ * lib/util/regress/json/json_test.c:
+ Add missing sudo_json_free().
+ [fa5e5af55927]
+
+ * MANIFEST, lib/util/Makefile.in, lib/util/regex.c,
+ lib/util/regress/regex/regex_test.c:
+ check_pattern: check bounds as a repetition operator too. Add regess
+ to verify check_pattern() via sudo_regex_compile().
+ [48cbddf476a5]
+
+ * lib/util/regex.c:
+ Instead of collapsing duplicate repetition characters, reject them.
+ This is implementation-specific behavior--some regcomp(3) will
+ reject duplicate repetition characters (BSD), others will try to
+ support them (Glibc) but may allocate excessive amounts of memory.
+ [a0cb75d9b5e5]
+
+ * MANIFEST, docs/CONTRIBUTORS.md, po/sq.mo, po/sq.po:
+ New Albanian translation from translationproject.org
+ [4a8dedc6500d]
+
+2022-12-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, include/sudo_json.h, lib/eventlog/eventlog.c,
+ lib/iolog/iolog_loginfo.c,
+ lib/iolog/regress/iolog_json/check_iolog_json.c,
+ lib/util/Makefile.in, lib/util/json.c,
+ lib/util/regress/json/json_test.c, lib/util/util.exp.in,
+ logsrvd/logsrvd_local.c, plugins/audit_json/audit_json.c,
+ plugins/sudoers/cvtsudoers_json.c:
+ Add basic regress for JSON functions. Fix a bug in escaped control
+ character handling. Roll back changes to buffer if
+ sudo_json_add_value() fails.
+ [8b61266511fe]
+
+ * plugins/python/regress/iohelpers.c,
+ plugins/python/regress/testhelpers.c:
+ Add missing memory allocation failure checks. Inspired by GitHub PR
+ #221
+ [9f09479191e9]
+
+2022-12-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/json.c:
+ Escape control characters in strings.
+ [9668cd68daee]
+
+2022-12-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudo.man.in, docs/sudo.mdoc.in:
+ Mention the audit plugin in the "Process model" section. Remove
+ extraneous information describing how sudo may exec the command
+ directly, this is already included in the non-pty section.
+ [9d01a9682ed2]
+
+2022-12-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/sudoers.c:
+ Plug a memory leak of list_cmnd in the fuzzers.
+ [b413becfb8db]
+
+ * plugins/sudoers/cvtsudoers.c:
+ Suppress PVS Studio watning about reassigning a variable the same
+ value. Working around the warning would result in more fragile code.
+ [b4227e531fb7]
+
+ * lib/util/regress/multiarch/multiarch_test.c:
+ Fix memory leak in multiarch_test to quiet leak sanitizer.
+ [1491ce67725c]
+
+ * plugins/python/python_plugin_audit.c,
+ plugins/python/python_plugin_common.c,
+ plugins/python/python_plugin_io.c,
+ plugins/python/python_plugin_policy.c:
+ Fix some dead stores noted by PVS Studio. Since rc is initialized to
+ SUDO_RC_ERROR there is no need to set it to SUDO_RC_ERROR again on
+ failure if rc has not been changed since initialization.
+ [f6c075dedfe3]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in,
+ plugins/sudoers/logging.c, plugins/sudoers/match_command.c,
+ plugins/sudoers/parse.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l:
+ Add "list" pseudo-command to allow a user to list another user's
+ privs. Previously, only root or a user with the ability to run any
+ command as either root or the target user on the current host could
+ use the -U option. For "sudo -l [-U otheruser] command", NewArgv[0]
+ is now set to "list" (just like "sudo -l") and the actual command to
+ be checked starts with NewArgv[1].
+ [225eac96d11f]
+
+2022-12-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * etc/codespell.exclude:
+ Adjust a line to quiet codespell warning.
+ [f920076a902d]
+
+2022-12-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Makefile.in:
+ Only build ChangeLog from a repo checkout, not a release tarball.
+ The CODEOWNERS file is not present in the release tarball so we can
+ use that when determining what is (or is not) a repo checkout.
+ [290ce43f0f66]
+
+ * docs/CODEOWNERS:
+ Add CODEOWNERS file, currently all owned by @millert.
+ [3becb02b5cd6]
+
+ * .gitignore, .hgignore, Makefile.in:
+ Only regenerate ChangeLog if there have been changes. Also check
+ that "hg --version" or "git --version" works before using hg or git.
+ Bug #1043.
+ [d9a28bb02621]
+
+2022-12-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/parse.c:
+ Fix potential crash introduced in the fix for GitHub issue #134. If
+ a user's sudoers entry did not have any RunAs user's set, running
+ "sudo -U otheruser -l" would dereference a NULL pointer. We need to
+ compare the default RunAs user if the sudoers entry does not specify
+ one explicitly. Problem reported by Andreas Mueller who also
+ suggested a different solution in PR #219.
+ [360e04f13024] <1.9>
+
+ * plugins/sudoers/parse.c:
+ Fix potential crash introduced in the fix for GitHub issue #134. If
+ a user's sudoers entry did not have any RunAs user's set, running
+ "sudo -U otheruser -l" would dereference a NULL pointer. We need to
+ compare the default RunAs user if the sudoers entry does not specify
+ one explicitly. Problem reported by Andreas Mueller who also
+ suggested a different solution in PR #219.
+ [3d12dfeef26b]
+
+ * scripts/build_pkgs:
+ Defer installing the SIGCHLD handler until after non-job commands
+ run. Lock the socket dir to avoid races in
+ open_persistent_connection(). Also avoid using "ssh -f" since that
+ may return before the socket is created. Strip carriage returns from
+ log when running in a pty.
+ [d0da1a261fbc]
+
+2022-12-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, m4/sudo.m4:
+ Fix a typo in SUDO_CHECK_NET_FUNC.
+ [08cb2ba84897]
+
+ * lib/util/inet_ntop.c:
+ Fix -Wsign-compare warning.
+ [45e2716ece56]
+
+ * configure, m4/sudo.m4:
+ Initialize "found" in SUDO_CHECK_NET_FUNC.
+ [a5daeb77e6bb]
+
+ * configure, m4/sudo.m4:
+ Fix pasto introduced in last commit.
+ [7e1b09977be3]
+
+ * lib/eventlog/Makefile.in, lib/iolog/Makefile.in,
+ lib/util/Makefile.in, logsrvd/Makefile.in,
+ plugins/python/Makefile.in, plugins/sudoers/Makefile.in,
+ src/Makefile.in:
+ Fix failure in check targets when there is no UTF-8 C locale.
+ [721c8bdff28f]
+
+ * configure, configure.ac, m4/sudo.m4:
+ Add SUDO_CHECK_NET_FUNC to check functions in the network libraries.
+ If a function is not found, check again with "-lsocket", "-linet",
+ "-lsocket -lnsl", or "-lresolv". Also display network libs in final
+ summary as well as the different linker flags.
+ [a0ce3347cd8d]
+
+ * configure, m4/sudo.m4:
+ Make sure HAVE_MAILLOCK_H is defined on Solaris 10.
+ [bb9f3a1beff5]
+
+ * configure, configure.ac:
+ Remove extraneous "(cached)" line when the -C option is used. We do
+ not need to call AC_CACHE_VAL() to ensure that a variable is cached,
+ its name just needs to match the pattern *_cv_*.
+ [b8ffa09d0cd7]
+
+ * configure, m4/sudo.m4:
+ Make path checks in sudo.m4 cachable.
+ [0bcfa73702d3]
+
+ * configure, configure.ac:
+ Use AC_PATH_PROGS_FEATURE_CHECK to find mandoc/nroff. We don't use
+ the NROFFPROG or MANDOCPROG any longer so no need to set those.
+ [7d96680046a6]
+
+ * configure, configure.ac:
+ Don't check for _sys_siglist if sys_siglist is found.
+ [2c70aba3935c]
+
+ * configure, configure.ac:
+ Fix check for sys_sigabbrev.
+ [b8537a76815f]
+
+2022-12-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Skip test for __func__ on C99 and above, avoid extra _sys_signame
+ test.
+ [71f3497a6a3a]
+
+ * MANIFEST, aclocal.m4, configure, configure.ac, m4/gettext.m4:
+ Move gettext checks to m4/gettext.m4
+ [693029542e06]
+
+ * MANIFEST, aclocal.m4, configure, configure.ac, m4/ldap.m4:
+ Move LDAP library checks to m4/ldap.m4 and make more tests
+ cacheable.
+ [85fa1f49298a]
+
+ * MANIFEST, aclocal.m4, configure, configure.ac, m4/openssl.m4:
+ Move OpenSSL/wolfSSL checks to m4/openssl.m4
+ [08b90f3cef52]
+
+ * MANIFEST, aclocal.m4, configure, configure.ac, m4/pie.m4:
+ Move PIE executable checks to m4/pie.m4
+ [6b5cac6cecd5]
+
+ * MANIFEST, aclocal.m4, configure, configure.ac, m4/sanitizer.m4:
+ Move address sanitizer and fuzzer checks to m4/sanitizer.m4
+ [a6372917d53b]
+
+ * MANIFEST, aclocal.m4, configure, configure.ac, m4/visibility.m4:
+ Move symbol visibility checks to m4/visibility.m4
+ [4684049c2d2c]
+
+ * MANIFEST, aclocal.m4, configure, configure.ac, m4/hardening.m4:
+ Move hardening checks to m4/hardening.m4
+ [c03abb3c9f55]
+
+ * configure, configure.ac, m4/sudo.m4:
+ Make cpp variadic arguments check into a macro and move to sudo.m4.
+ Also move the PVS-Studio.cfg generation to sudo.m4.
+ [c1a8d3b46be1]
+
+2022-12-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/snprintf.c:
+ Sync with OpenBSD.
+ [157439118867]
+
+ * Merge pull request #218 from sohomdatta1/snprintf
+
+ [snprintf] Check for '\0' to prevent undef memory read
+ [050882923c98]
+
+2022-12-03 Sohom <sohomdatta1+git@gmail.com>
+
+ * lib/util/snprintf.c:
+ [snprintf] Check for '\0' to prevent undef memory read
+ [aff60c479c10]
+
+2022-12-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/eventlog/eventlog.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/tsdump.c, plugins/sudoers/visudo.c,
+ src/parse_args.c, src/regress/noexec/check_noexec.c:
+ Place C23 attributes before keywords in function declarations. In
+ practice this means we must use "sudo_noreturn static foo(void)"
+ instead of "static sudo_noreturn foo(void)".
+ [6c1836dcb2d6]
+
+2022-11-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/build_pkgs:
+ Convert from using IPC::Open3 to IPC::Run. Run tests in a pty so
+ check_ttyname works as expected. Explicitly set short command line
+ options letters in GetOptions(). Add a debug flag to help see what
+ is going on internally. Add hook for die() to kill running jobs when
+ we are dying. SSH_AGENT_PID will not be present if the agent is
+ forwarded. In close_persistent_connections() only close active
+ connections.
+ [d49e1ac7e2f2]
+
+2022-11-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure.ac, include/sudo_compat.h:
+ Use C23 [[__fallthrough__]] and [[__noreturn__]] attributes if
+ supported. If the C23 attributes are not supported, use gcc-style
+ attributes where possible.
+ [57676068e9a9]
+
+ * configure, configure.ac:
+ Move the check for the fallthrough attribute outside the warnings
+ block. Use AX_APPEND_FLAG instead of addind to CFLAGS directly.
+ [dc22d8238827]
+
+2022-11-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/build_pkgs:
+ The distributed package build script I use to build all sudo
+ packages. This is not included in the release tarball because it is
+ of limited use to other people.
+ [94c58cc272c8]
+
+2022-11-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Makefile.in:
+ Pass the list of files to include in the tarball on stdin. This
+ avoids any limit on the size of argv.
+ [0af8578c89fe]
+
+2022-11-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #214 from BornThisWay/1124_repeated_invocation
+
+ check_syntax(): Remove duplicate calls to init_defaults()
+ [3383fb0a6f5f]
+
+2022-11-24 modric <pioneerbtw7@163.com>
+
+ * plugins/sudoers/visudo.c:
+ check_syntax(): Remove duplicate calls to init_defaults()
+ [048ccd968df9]
+
+2022-11-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sample/sample_plugin.c:
+ build_command_info: free command_info on failure. Once upon a time,
+ command_info was a stack variable, now it is dynamically allocated.
+ Coverity CID 299987.
+ [a80110e49952]
+
+ * plugins/sample/sample_plugin.c:
+ Better handling of out-of-memory conditions.
+ [ee3e47c4d272]
+
+ * plugins/group_file/group_file.c:
+ Keep group file open until the call to myendgrent(). This restores
+ the previous behavior.
+ [79751f7308d7]
+
+ * lib/util/json.c, plugins/group_file/getgrent.c,
+ plugins/sudoers/cvtsudoers_merge.c, plugins/sudoers/env.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/ldap_conf.c, plugins/sudoers/log_client.c,
+ plugins/sudoers/match_command.c, plugins/sudoers/strvec_join.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/visudo.c, src/sudo.c:
+ Eliminate a few harmless dead stores. Quiets warnings from Infer.
+ [8bed7579b75d]
+
+ * plugins/sudoers/ldap_util.c:
+ sudo_ldap_parse_option: add explicit NULL check for strchr(). This
+ should not be needed since we only use the returned pointer if it is
+ larger than the string passed to strchr(). Quiets a warning from
+ Infer.
+ [852aec3e0450]
+
+ * logsrvd/logsrvd_journal.c:
+ journal_fdopen: free journal_path and close journal before setting
+ Fixes a potential resource leak that currently cannot happen. Quiets
+ a warning from Infer.
+ [bfe41e247c35]
+
+ * plugins/sudoers/ldap.c:
+ sudo_ldap_result_add_entry: check sudo_ldap_get_values_len() return
+ value. Previously, we just compared the error code with
+ LDAP_NO_MEMORY when checking for sudoOrder since this is the only
+ error we care about. We now return NULL for LDAP_NO_MEMORY and
+ ignore other errors. Quiets a warning from Infer.
+ [6e5a490b735c]
+
+ * plugins/group_file/getgrent.c, plugins/sudoers/tsgetgrpw.c,
+ plugins/sudoers/tsgetgrpw.h:
+ Refactor code to open passwd/group file and add
+ setpassent/setgroupent. This makes the "stayopen" semantics match
+ the system passwd/group functions. The getpwent/getgrent functions
+ now open the database if it is not already open.
+ [27bfa97ad47c]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/gram.h:
+ gram.h: #line directives should reference gram.h not y.tab.h.
+ [7a2d4a24d839]
+
+ * scripts/mkpkg:
+ Use clang, not /usr/bin/cc on FreeBSD and macOS. While /usr/bin/cc
+ _is_ clang on those platforms, some static analyzers get confused if
+ we don't run it as clang.
+ [d0c1f5940789]
+
+2022-11-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #212 from BornThisWay/1122_null_deref
+
+ sudo_rcstr_dup: Fix potential NULL pointer deref
+ [58fcefa888fa]
+
+2022-11-22 modric <pioneerbtw7@163.com>
+
+ * lib/util/rcstr.c:
+ sudo_rcstr_dup: Fix potential NULL pointer deref
+ [f45acaded1e5]
+
+2022-11-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/check.c:
+ Add a reminder to the default lecture that the password will not
+ echo. This line is only displayed when the pwfeedback option is
+ disabled. GitHub issue #195.
+ [7bc25043c760]
+
+ * Merge pull request #210 from BornThisWay/1121_typo
+
+ Fix some typos
+ [9d1e9278effb]
+
+2022-11-21 modric <pioneerbtw7@163.com>
+
+ * plugins/python/regress/testhelpers.h, plugins/sudoers/parse.c:
+ Fix some typos
+ [d7d1c3ade748]
+
+2022-11-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #208 from BornThisWay/1121_return
+
+ intercept_read: Print and then return.
+ [615c2d5fca36]
+
+2022-11-21 modric <pioneerbtw7@163.com>
+
+ * src/exec_intercept.c:
+ intercept_read: Print and then return.
+ [049547eb7ac0]
+
+2022-11-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #205 from BornThisWay/1119_access_null_pointer
+
+ sudo_mmap_strdup_v1: Fix potential NULL pointer deref
+ [bad55afc72bb]
+
+2022-11-19 modric <pioneerbtw7@163.com>
+
+ * lib/util/mmap_alloc.c:
+ sudo_mmap_strdup_v1: Fix potential NULL pointer deref
+ [f8da23aff2ec]
+
+2022-11-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sudo_intercept.c:
+ copy_vector: plug memory leak in error path Only the array was being
+ freed, not the contents. GitHub issue #202.
+ [cd1407dbe65f]
+
+2022-11-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/mkpkg:
+ Better matching of macOS version to SDK path.
+ [db7f2cbdb023]
+
+ * Merge pull request #200 from BornThisWay/fix_mem_leak_converse
+
+ Fix memory leak of pass in converse().
+ [b411801abdf7]
+
+ * plugins/sudoers/auth/passwd.c:
+ sudo_passwd_cleanup: Set auth->data to NULL after freeing. GitHub
+ issue #201
+ [e558188bd99d]
+
+2022-11-17 modric <pioneerbtw7@163.com>
+
+ * plugins/sudoers/auth/pam.c:
+ Fix memory leak of pass in converse().
+ [052c99eaad8f]
+
+2022-11-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac:
+ Use AC_SYS_YEAR2038 instead of setting _TIME_BITS by hand.
+ [049113d798e9]
+
+ * configure, m4/ax_append_flag.m4, m4/ax_check_compile_flag.m4,
+ m4/ax_func_snprintf.m4, m4/ax_prog_cc_for_build.m4:
+ Update macros from autoconf-archive.
+ [48b960c883df]
+
+ * plugins/sudoers/regress/corpus/seed/ldif/pr196.ldif,
+ plugins/sudoers/regress/visudo/test3.sh:
+ Fix typo; excerise -> exercise
+ [42cdb396b72b]
+
+ * config.h.in, configure, scripts/config.guess, scripts/config.sub:
+ Regenerate with the autoconf 2.72a pre-release.
+ [51d043878181]
+
+ * configure.ac:
+ Fix insufficient quoting in AC_CHECK_LIB() calls.
+ [78d37b60a912]
+
+ * autogen.sh:
+ If AUTOCONF_VERSION is unset, use version 2.71 not 2.69.
+ [108faf700aa7]
+
+ * configure.ac, m4/ax_func_getaddrinfo.m4, m4/sudo.m4:
+ Replace `foo` in descriptions with 'foo'
+ [ba63cef7bbe8]
+
+2022-11-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Add -Wvla and -Walloca to --enable-warnings
+ [7b9b59e35905]
+
+2022-11-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/pwutil.c:
+ sudo_debug_group_list: short-circuit if groups is NULL
+ [0f8f11ef82b6]
+
+ * configure, configure.ac:
+ configure: only check for getauxval() if getentropy() is missing.
+ [c056c2fc3898]
+
+ * config.h.in, configure, configure.ac:
+ Remove checks for random() and lrand48(), they are no longer used.
+ Also remove duplicate checks for arc4random() and getentropy().
+ [e3433874211d]
+
+ * configure, configure.ac:
+ Skip check for cpp variadic macro support if the compiler supports
+ C99.
+ [42efc9934ef5]
+
+ * configure, configure.ac:
+ HI-UX/MPP is based on OSF-1, not HP-UX Completely untested.
+ [c55ba59cd24d]
+
+ * configure, configure.ac:
+ Only check for utmps.h on HP-UX.
+ [682bb16545cf]
+
+ * configure, configure.ac:
+ Only check for sys/syscall.h on Linux. We only use it in the Linux-
+ specific getentropy() emulation code.
+ [eac313bfc142]
+
+ * config.h.in, configure, configure.ac:
+ configure: avoid running unnecessary tests on modern systems. Remove
+ AC_SYS_POSIX_TERMIOS, AC_TYPE_MODE_T, AC_TYPE_UID_T. Add missing
+ checks for int16_t, uint16_t, int32_t, and int64_t. Only check for
+ intmax_t, uintmax_t and bit-width types if missing both inttypes.h
+ and stdint.h. Remove unused clockid_t replacement.
+ [9f1f9d365f60]
+
+ * MANIFEST, plugins/sudoers/regress/cvtsudoers/test40.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test40.sh:
+ Add a regress check for the cvtsudoers filter crash. GitHub issue
+ #198.
+ [f0abea1f10d0]
+
+ * Makefile.in, lib/eventlog/Makefile.in, lib/iolog/Makefile.in,
+ lib/util/Makefile.in, logsrvd/Makefile.in,
+ plugins/python/Makefile.in, plugins/sudoers/Makefile.in,
+ src/Makefile.in:
+ The name of the C locale w/ UTF-8 support is not always C.UTF-8. Use
+ a pattern to find it (if present) and use that value instead of
+ hard-coding C.UTF-8. This works around a leak sanitizer crash on
+ certain inputs.
+ [99aeb5a875f7]
+
+2022-11-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/parse_ldif.c:
+ Fix a potential use-after-free bug with cvtsudoers filtering. In
+ role_to_sudoers() when merging a privilege to the previous one where
+ the runas lists are the same we need to re-use the runas lists of
+ the last command in the previous privilege, not the first.
+ Otherwise, the check in free_cmndspec() will not notice the re-used
+ runas lists. Reported/analyzed by Sohom Datta. GitHub issue #198.
+ [29d1380d2fe0]
+
+ * MANIFEST, plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/corpus/seed/ldif/invalid_b64.ldif,
+ plugins/sudoers/regress/corpus/seed/ldif/pr196.ldif,
+ plugins/sudoers/regress/corpus/seed/ldif/sample.ldif,
+ plugins/sudoers/regress/corpus/seed/ldif/valid_b64.ldif,
+ plugins/sudoers/regress/cvtsudoers/test39.sh:
+ Copy some LDIF test data from the cvtsudoers tests to the seed
+ corpus. This includes a test to exercise the fix in PR #196.
+ [f74d65cf34d1]
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c:
+ Set LDAP base for sudoers_parse_ldif(). Without this set the fuzzer
+ will not exercise the dn parsing.
+ [c154b1a5d287]
+
+ * src/exec_ptrace.h:
+ Include linux/elf.h, not elf.h to make sure we get
+ NT_ARM_SYSTEM_CALL. The NT_PRSTATUS define is present in both files.
+ [161f41f644ca] <1.9>
+
+ * src/exec_ptrace.h:
+ Include linux/elf.h, not elf.h to make sure we get
+ NT_ARM_SYSTEM_CALL. The NT_PRSTATUS define is present in both files.
+ [4a4e3142381a]
+
+2022-11-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_compat.h:
+ Remove CMSG_* compatibility macros, they are no longer used.
+ [5914434ecb5c]
+
+ * lib/util/multiarch.c, lib/util/sudo_dso.c:
+ Add missing include of sys/stat.h
+ [d3b0f701c75f]
+
+ * include/sudo_util.h:
+ Move forward declaration of struct stat before its first use.
+ [f3cc645d197c]
+
+ * plugins/sudoers/regress/cvtsudoers/test28.sh,
+ plugins/sudoers/regress/cvtsudoers/test29.sh,
+ plugins/sudoers/regress/cvtsudoers/test33.sh,
+ plugins/sudoers/regress/cvtsudoers/test39.sh:
+ Use a consistent base when testing cvtsudoers conversion from ldif.
+ [a22cb486b2a3]
+
+ * MANIFEST, plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/cvtsudoers/test39.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test39.sh,
+ plugins/sudoers/regress/harness.in:
+ Test parsing LDIF when a backslash is the last char of the file. If
+ run with address sanitizer, this test will crash when the fix in
+ ceaf706ab74b is reverted.
+ [f50c78b7ed32]
+
+ * Merge pull request #196 from sohomdatta1/main
+
+ Prevent cvtsudoers from reading into undefined memory
+ [f21c417bbbb3]
+
+2022-11-09 Sohom <sohom.datta@learner.manipal.edu>
+
+ * plugins/sudoers/parse_ldif.c:
+ [cvtsudoers]: Prevent sudo from reading into undefined memory
+ [ceaf706ab74b]
+
+2022-11-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/passwd.c:
+ sudo_passwd_verify: zero out des_pass before returning.
+ [c809232fdb7d]
+
+2022-11-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_pty.c:
+ Don't kill the parent process group on suspend if it is not sudo's
+ pid. If sudo is not the process group leader we must only send the
+ suspend signal to sudo itself. When sudo is run via a shell script,
+ it usually has the same process group as the shell script
+ interpreter. We do not want to suspend the script itself when the
+ command run by sudo is suspended.
+ [e6715ec62335]
+
+ * src/exec_nopty.c, src/regress/intercept/test_ptrace.c,
+ src/sudo_exec.h, src/suspend_nopty.c:
+ Pass sudo's process ID to suspend_sudo_nopty() since we already know
+ it. Saves an unnecessary getpid(2) call.
+ [1e12d9b0ce53]
+
+ * src/exec_nopty.c:
+ Call terminate_command() with use_pgrp = false when not running in a
+ pty. When sudo runs a command in the user's existing terminal the
+ command is run in the same process group as sudo itself. The proper
+ way to terminate it is to use kill(2), not killpg(3)
+ [3d9862963e92]
+
+ * src/exec_monitor.c, src/exec_nopty.c, src/exec_pty.c,
+ src/sudo_exec.h:
+ Fix handling of signal forwarding when running commands in a script.
+ We need to forward signals from a process in the same pgrp if the
+ pgrp leader is not either sudo or the command itself.
+ [d1bf60eac57f]
+
+ * src/regress/intercept/test_ptrace.c:
+ Make test_ptrace compile again after recent changes.
+ [e766db5aa9d4]
+
+ * src/exec_intercept.c, src/exec_intercept.h, src/exec_ptrace.c:
+ Update the cwd for log_subcmds too. Fixes a problem for
+ intercept_method=trace when running a relative command from a
+ different directory than what sudo ws started from. GitHub issue
+ #194
+ [b831f2397d9f]
+
+2022-11-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_12p1 for changeset 39cf4d8052ff
+ [28ed2d994f40] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Merge sudo 1.9.12p1 from tip.
+ [39cf4d8052ff] [SUDO_1_9_12p1] <1.9>
+
+ * NEWS, aclocal.m4, configure, configure.ac:
+ sudo 1.9.12p1
+ [6268fbabdb16]
+
+2022-11-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/host_port.c:
+ Include time.h for struct timespec used by sudo_iolog.h.
+ [369c8e799652]
+
+ * src/sudo.c:
+ Display sudo_mode in hex in debug log. This makes it easier to match
+ against the MODE_ defines.
+ [971e8f88bc12]
+
+2022-11-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/bsdauth.c:
+ bsdauth_verify: do not write to prompt, it is now const
+ [1969a562cf14]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Store raw sudoers lines in the debug log. Also add a "sudoerslex"
+ prefix to the token debug info in sudoers_trace_print().
+ [be03aef496cb]
+
+2022-10-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ The line numbers in sudoers_trace_print() were off by one. The line
+ counter is incremented when a newline is seen so the output actually
+ refers to the previous line.
+ [a97182a63419]
+
+ * plugins/sudoers/auth/API, plugins/sudoers/auth/afs.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.h:
+ Make the second arg to the sudo auth verify function const. This may
+ be either a plaintext password or a password prompt. Either way it
+ should not be modified by the verify function.
+ [11aefc2bc3da]
+
+2022-10-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/match.c:
+ Move debugging info from hostname_matches() to host_matches().
+ [2a53d2dcd1f5]
+
+2022-10-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/pwutil.c:
+ Add debugging to sudo_set_grlist() and sudo_set_gidlist().
+ [620d6f7fb4f8]
+
+ * plugins/sudoers/auth/passwd.c:
+ Fix CVE-2022-43995, potential heap overflow for passwords < 8
+ characters. Starting with sudo 1.8.0 the plaintext password buffer
+ is dynamically sized so it is not safe to assume that it is at least
+ 9 bytes in size. Found by Hugo Lefeuvre (University of Manchester)
+ with ConfFuzz.
+ [a6229aa26fbf]
+
+2022-10-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ configure: better test for -fstack-clash-protection The gcc front-
+ end may accept -fstack-clash-protection even if the machine-specific
+ code does not support it. We use a test program with a large stack
+ allocation to try to cause the compiler to insert the stack clash
+ protection code, or fail if not supported. GitHub issue #191
+ [bbfbe758258c]
+
+ * configure, configure.ac:
+ Check that compiler accepts -fstack-clash-protection and -fcf-
+ protection. Previously, we only checked that linker accepted them.
+ GitHub issue #191
+ [7d36b89b6e4d]
+
+2022-10-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.c:
+ Fix compilation error on Linux/mips.
+ [ae4c28d8a050]
+
+2022-10-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_12 for changeset b53d725f7c88
+ [dd962ed18037] <1.9>
+
+ * NEWS, config.h.in, configure, configure.ac, include/sudo_compat.h,
+ logsrvd/tls_init.c, plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Merge sudo 1.9.12 from tip.
+ [b53d725f7c88] [SUDO_1_9_12] <1.9>
+
+ * src/Makefile.in:
+ Regenerate dependencies for src/sesh.c.
+ [ada8f04afc6d]
+
+ * plugins/audit_json/Makefile.in, plugins/sample_approval/Makefile.in:
+ Sync clean target with other Makefile.in files.
+ [8048628a554e]
+
+ * Makefile.in, plugins/sample/Makefile.in:
+ Build the sample plugin but do not install it by default. We no
+ longer install the sample approval plugin.
+ [a8644924b6a1]
+
+ * plugins/sample/sample_plugin.c:
+ Adapt to current plugin API and fix warnings.
+ [d822f1a10361]
+
+2022-10-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.c:
+ Disable admin_flag by setting to NULL, not false. Found by cppcheck.
+ [6e32481e0555]
+
+ * NEWS:
+ Bug #1042.
+ [85d508b6d5e5]
+
+ * include/sudo_util.h, lib/util/fatal.c, lib/util/term.c,
+ lib/util/util.exp.in, src/conversation.c:
+ Only add trailing carriage return to messages if output is a raw
+ tty. If output is being written to a terminal in "raw" mode, we need
+ to add a carriage return after the newline to avoid "stair-step"
+ output. However, we should not write the carriage return if the
+ terminal is in "cooked" mode, output to a pipe, or output redirected
+ to a file. Bug #1042.
+ [14f5bf04245f]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ Make it clear that runas_default sets the default user for
+ Runas_Spec. Also use mention runas_default in other parts of the
+ manual, use @runas_default@ instead of root and add markup around
+ user names. GitHub issue #186.
+ [73f0b82a2b22]
+
+ * lib/util/multiarch.c, lib/util/sudo_dso.c:
+ Fix a typo, muti-arch -> multi-arch GitHub issue #185
+ [d88270b9e98f]
+
+2022-10-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Mention log_servers eventlog fix.
+ [484b76589309]
+
+ * plugins/sudoers/policy.c:
+ Don't NULL out the plugin close function when logging to a log
+ server. If sudo calls execve(2) directly the accept info will not be
+ sent. We also need the sudo front-end to wait until the command
+ finishes to send the exit status.
+ [11976aa84040]
+
+2022-10-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * INSTALL.md:
+ Fix numbering in "Simple sudo installation"
+ [695bec2a6223]
+
+2022-10-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ zlib 1.2.13 update
+ [2119981787f0]
+
+ * plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/ro.mo, plugins/sudoers/po/ro.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po, po/cs.mo,
+ po/cs.po, po/de.mo, po/de.po, po/fr.mo, po/fr.po, po/ja.mo,
+ po/ja.po, po/ka.mo, po/ka.po, po/ko.mo, po/ko.po, po/pl.mo,
+ po/pl.po, po/ro.mo, po/ro.po, po/sr.mo, po/sr.po, po/sv.mo,
+ po/sv.po, po/uk.mo, po/uk.po:
+ Updated translations from translationproject.org
+ [b1f28405c58d]
+
+ * lib/zlib/zconf.h.in:
+ Don't define _LARGEFILE64_SOURCE or _LFS64_LARGEFILE. We don't need
+ them and the missing prototype for crc32_combine_gen64() issue has
+ been fixed upstream.
+ [39eb41f1dba4]
+
+2022-10-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/zlib/compress.c, lib/zlib/crc32.c, lib/zlib/deflate.c,
+ lib/zlib/deflate.h, lib/zlib/gzlib.c, lib/zlib/gzread.c,
+ lib/zlib/gzwrite.c, lib/zlib/infback.c, lib/zlib/inflate.c,
+ lib/zlib/inftrees.c, lib/zlib/inftrees.h, lib/zlib/trees.c,
+ lib/zlib/uncompr.c, lib/zlib/zconf.h.in, lib/zlib/zlib.h,
+ lib/zlib/zutil.c, lib/zlib/zutil.h:
+ Update embedded copy of zlib to version 1.2.13. Fixes
+ CVE-2022-37434.
+ [737d6de5253c]
+
+ * lib/util/fchownat.c:
+ Add fchownat() for systems without it.
+ [7c4aeda51522]
+
+2022-10-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Update NEWS for 1.9.12.
+ [a4b090f3f6c8]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ Update .pot files for 1.9.12
+ [179fba83936d]
+
+ * src/selinux.c, src/sesh.c, src/sudo_edit.c:
+ Use getopt() and getopt_long() for sesh command line options.
+ [fbaa6c75e2ef]
+
+ * plugins/sudoers/def_data.c, plugins/sudoers/def_data.in:
+ Update the description of intercept_verify
+ [63f80a7cd4a6]
+
+2022-10-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/load_plugins.c:
+ Silence a warning from the Solaris Studio compiler.
+ [49a3c72cb539]
+
+ * docs/sudo_plugin.man.in, docs/sudo_plugin.mdoc.in,
+ include/sudo_eventlog.h, include/sudo_json.h, include/sudo_plugin.h,
+ lib/eventlog/eventlog.c, lib/iolog/iolog_loginfo.c,
+ lib/iolog/regress/iolog_json/check_iolog_json.c, lib/util/json.c,
+ logsrvd/logsrvd_local.c, plugins/audit_json/audit_json.c,
+ plugins/sudoers/sudoers.h, src/env_hooks.c, src/exec_intercept.c,
+ src/net_ifs.c, src/sudo_intercept_common.c, src/sudo_plugin_int.h:
+ Avoid a -Wshadow warning on Solaris 9.
+ [e6bc419fa976]
+
+ * lib/util/mmap_alloc.c:
+ Fix a build error on Solaris 9.
+ [679b60caf5a3]
+
+2022-10-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/parse.c:
+ Fix display of command tags and options in "sudo -l" when RunAs
+ changes. A new line is started when RunAs changes which means we
+ need to display the command tags and options again. GitHub issue
+ #184
+ [3180777986de]
+
+ * plugins/sudoers/fmtsudoers.c:
+ Fix printing of MYSELF when listing another user's privileges. We
+ need to use list_pw if it is set instead of user_name. GitHub issue
+ #183
+ [268044635b44]
+
+ * NEWS:
+ Update NEWS file with recent changes.
+ [200ac32d330b]
+
+ * MANIFEST, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/multiarch.c, lib/util/regress/multiarch/multiarch_test.c,
+ lib/util/sudo_dso.c, lib/util/util.exp.in, src/load_plugins.c:
+ Apply multiarch rules when loading plugins too.
+ [f53fe06fce06]
+
+2022-10-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/sudo_dso.c:
+ sudo_dso_load: try multi-arch on Linux if we can't load the path.
+ For example, if loading /usr/lib/libsss_sudo.so fails, try again
+ with /usr/lib/x86_64-linux-gnu/libsss_sudo.so.
+ [4eabffa486b5]
+
+ * MANIFEST, lib/util/Makefile.in,
+ lib/util/regress/open_parent_dir/open_parent_dir_test.c:
+ Add test for sudo open_parent_dir()
+ [2d6b1be616c9]
+
+ * MANIFEST, plugins/sudoers/regress/testsudoers/test19.out.ok,
+ plugins/sudoers/regress/testsudoers/test19.sh:
+ Add test for matching a literal "" command line argument as "" in
+ sudoers. GitHub issue #182.
+ [ccb5dc8b23ee]
+
+2022-10-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/visudo.man.in, docs/visudo.mdoc.in, plugins/sudoers/visudo.c:
+ Add -I flag to disable editing include files unless there is an
+ error. This can be used when you only want to edit a single sudoers
+ file unless there is a pre-existing syntax error.
+ [18fbf720fdbf]
+
+ * plugins/sudoers/match_command.c:
+ Do not match a literal "" command line argument as "" in sudoers. If
+ the empty string is specified in sudoers, no user args are allowed.
+ GitHub issue #182.
+ [5de0370eddcb]
+
+ * lib/util/sudo_conf.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/timestamp.c:
+ sudo_secure_open_{file,dir}: always check thatreturn value is not
+ -1. Avoids false positives from static analyzers that can't figure
+ out that the fd is always valid when error is SUDO_PATH_SECURE.
+ [f0ebb2b836b9]
+
+ * lib/iolog/iolog_mkdtemp.c:
+ Correct return value when mkdtempat() fails.
+ [5a491fac8f49]
+
+ * lib/util/mkdir_parents.c:
+ sudo_open_parent_dir: stop before creating the last path component
+ Fix a regression introduced in sudo 1.9.9 where the entire directory
+ path was created instead of just the parent directory.
+ [fdaa5aeb744b]
+
+2022-10-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Makefile.in, scripts/log2cl.pl:
+ Use "hg log --template" instead of "hg log --style".
+ [63f020404fbb]
+
+2022-09-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/strlcpy_unesc.c, plugins/sudoers/sudoers.c,
+ src/parse_args.c:
+ Mark code that escapes/unescapes "sudo -s cmd args..." for removal.
+ A future version of the plugin API will defer any such escaping to
+ the policy plugin so it can be configurable.
+ [658d1bba4319]
+
+ * NEWS:
+ Update with recent changes.
+ [4a739e30c77f]
+
+ * docs/cvtsudoers.man.in, docs/cvtsudoers.mdoc.in:
+ Improve the description of JSON output.
+ [258b57ce22ab]
+
+2022-09-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * INSTALL.md, etc/codespell.ignore, lib/eventlog/eventlog.c,
+ plugins/group_file/getgrent.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/tsgetgrpw.h,
+ src/exec_nopty.c:
+ Fix typos found by codespell 2.2.1.
+ [3beaf856c861]
+
+ * logsrvd/iolog_writer.c:
+ Change max user-ID and group-ID from INT_MAX to UINT_MAX.
+ [0971e5f9f398]
+
+ * logsrvd/logsrvd_local.c:
+ Add support for NumberList stored in an InfoMessage.
+ [a762fe45e5cc]
+
+ * logsrvd/iolog_writer.c, logsrvd/logsrvd.c, logsrvd/logsrvd_local.c,
+ plugins/sudoers/log_client.c:
+ Add missing NULL checks for mandatory fields in protobuf messages.
+ Also no longer reject an InfoMessage with an unknown value_case,
+ just log and ignore it.
+ [41c38e7f075b]
+
+2022-09-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/log_client.c:
+ Don't send ttyname to log server if it is NULL. Otherwise the log
+ server will reject the AcceptMessage because a NULL string is not
+ allowed.
+ [df7fea4bef26]
+
+ * src/exec_nopty.c:
+ HP-UX has struct winsize in termios.h.
+ [5827a1f234fe]
+
+ * plugins/python/Makefile.in, src/Makefile.in:
+ Regen dependencies
+ [817623addc62]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in, src/exec.c,
+ src/exec_nopty.c, src/exec_pty.c,
+ src/regress/intercept/test_ptrace.c, src/sudo_exec.h,
+ src/suspend_nopty.c:
+ Add support for logging stdin/stdout/stderr in the non-pty exec
+ path. If we are logging I/O but not terminal input/output (either
+ because no terminal is present or because that is what the plugin
+ requested), the non-pty exec path is now taken.
+ [205c68d452df]
+
+ * MANIFEST, src/Makefile.in, src/exec.c, src/exec_iolog.c,
+ src/exec_nopty.c, src/exec_pty.c, src/regress/noexec/check_noexec.c,
+ src/sudo_exec.h, src/sudo_intercept_common.c:
+ Move exec code to call into I/O log plugin to exec_iolog.c. This
+ will be shared with exec_nopty.c in the future to log
+ stdin/stdout/stderr without running the command in a pty. Both
+ exec_pty.c and exec_nopty.c now use the same closure.
+ [45a19e8e3721]
+
+ * plugins/python/python_importblocker.c:
+ Implement find_spec, not the deprecated find_module. Fixes a test
+ failure due to find_module having removed from setuptools.
+ [cc1e68c0ee1e]
+
+2022-09-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/editor.c,
+ plugins/sudoers/regress/editor/check_editor.c:
+ copy_arg: fix copying an escaped backslash GitHub issue #179
+ [d21d95ec5cb0]
+
+2022-09-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h,
+ lib/util/mktemp.c:
+ Use mkdtempat_np() and mkostempsat_np() on macOS
+ [ad0cd430347e]
+
+2022-09-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_iolog.h, lib/iolog/iolog_mkdirs.c,
+ lib/iolog/iolog_mkdtemp.c, lib/util/mkdir_parents.c,
+ logsrvd/logsrvd.c, logsrvd/logsrvd_journal.c:
+ Convert remaining uses of sudo_mkdir_parents() to
+ sudo_open_parent_dir().
+ [62fd9644a605]
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, lib/util/Makefile.in, scripts/mkdep.pl:
+ Add fchownat() systems without it.
+ [d51316f1026d]
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h,
+ lib/util/mktemp.c, plugins/python/regress/iohelpers.h:
+ Add mkdtempat() and mkostempsat() for systems without them.
+ [099468742d16]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in, include/sudo_util.h,
+ lib/util/secure_path.c, lib/util/sudo_conf.c,
+ plugins/sudoers/regress/testsudoers/test11.out.ok,
+ plugins/sudoers/sudoers.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timestamp.c:
+ Use sudo_secure_open_file() instead of sudo_secure_file() where
+ possible. Both sudo_secure_open_file() and sudo_secure_open_dir()
+ are now passed a struct stat pointer like sudo_secure_file() and
+ sudo_secure_dir().
+ [c4e4c3f74ea4]
+
+ * include/sudo_util.h, lib/util/mkdir_parents.c,
+ lib/util/secure_path.c, lib/util/util.exp.in,
+ plugins/sudoers/timestamp.c:
+ Fix potential TOCTOU when creating time stamp directory and file.
+ [d36591f966c5]
+
+ * lib/util/mkdir_parents.c:
+ sudo_mkdir_parents: just use memcpy() to copy the path component.
+ Using snprintf() for this is overkill, we need to do the same length
+ check either way.
+ [8ea754871a54]
+
+ * lib/util/Makefile.in:
+ regen
+ [ab40def3376c]
+
+2022-09-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/digest_gcrypt.c:
+ Quiet libgcrypt run-time warning about not being initialized. Fixes
+ Debian bug #1019428 and Ubuntu bug #1397663.
+ [ebf9a6477d5d]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in, plugins/sudoers/audit.c,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.h,
+ plugins/sudoers/parse.c, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Split log_{input,output} into log_{stdin,ttyin} and
+ log_{ttyout,stdout,stderr} If log_input is set, log_{stdin,ttyin}
+ will be set as well. If log_output is set,
+ log_{stdout,stderr,ttyout} will be set as well. This provides more
+ fine-grained control over I/O logging and makes it possible to
+ disable logging piped or redirected intput or output.
+ [5b7ea42ac63b]
+
+ * LICENSE.md, include/protobuf-c/protobuf-c.h,
+ lib/protobuf-c/protobuf-c.c:
+ Update to protobuf-c 1.4.1 We already had all the relevant fixes so
+ this is just cosmetic.
+ [aa51e48afe49]
+
+ * src/load_plugins.c:
+ new_container: no need to initialize container pointer in
+ declaration. From Li zeming.
+ [729a8a417d88]
+
+2022-09-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Use tcpgid if passed from sudo front-end and use it in
+ tty_present(). This can be used as another indicator that a terminal
+ is present without having to open /dev/tty.
+ [b804b8b7fc03]
+
+2022-09-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/cvtsudoers.man.in, docs/cvtsudoers.mdoc.in,
+ docs/sudo.conf.man.in, docs/sudo.conf.mdoc.in, docs/sudo.man.in,
+ docs/sudo.mdoc.in, docs/sudo_logsrv.proto.man.in,
+ docs/sudo_logsrv.proto.mdoc.in, docs/sudo_logsrvd.conf.man.in,
+ docs/sudo_logsrvd.conf.mdoc.in, docs/sudo_logsrvd.man.in,
+ docs/sudo_logsrvd.mdoc.in, docs/sudo_plugin.man.in,
+ docs/sudo_plugin.mdoc.in, docs/sudo_sendlog.man.in,
+ docs/sudo_sendlog.mdoc.in, docs/sudoers.ldap.man.in,
+ docs/sudoers.ldap.mdoc.in, docs/sudoers.man.in,
+ docs/sudoers.mdoc.in, docs/sudoers_timestamp.man.in,
+ docs/sudoers_timestamp.mdoc.in, docs/sudoreplay.man.in,
+ docs/sudoreplay.mdoc.in, docs/visudo.man.in, docs/visudo.mdoc.in:
+ Remove most uses of the deprecated Li macro which has no effect.
+ Also fix some other incorrect markup.
+ [8f94cc555092]
+
+2022-09-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Makefile.in, lib/eventlog/Makefile.in, lib/iolog/Makefile.in,
+ lib/util/Makefile.in, logsrvd/Makefile.in,
+ plugins/python/Makefile.in, plugins/sudoers/Makefile.in,
+ src/Makefile.in:
+ Use $(GREP) and $(EGREP) variables in Makefile.in files.
+ [cf8d7fb45169]
+
+ * Merge pull request #177 from a1346054/fixes
+
+ Makefile.in: replace `egrep` and fix target name
+ [751aa03eb470]
+
+2022-09-12 a1346054 <36859588+a1346054@users.noreply.github.com>
+
+ * Makefile.in:
+ Fix incorrect makefile target name
+ [318288fb712f]
+
+ * Makefile.in:
+ Use `grep -E` instead of `egrep`
+ [4a2d9543643c]
+
+2022-09-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudo_plugin.man.in, docs/sudo_plugin.mdoc.in:
+ Document apparmor_profile, intercept_verify, and update_ticket.
+ [d55caa1af788]
+
+ * docs/sudo_plugin_python.man.in, docs/sudo_plugin_python.mdoc.in:
+ Fix some of the markup to be more consistent with
+ sudo_plugin.mdoc.in. Also reword a few awkward phrases.
+ [8682c067c38b]
+
+ * docs/sudo_plugin.man.in, docs/sudo_plugin.mdoc.in:
+ Use correct markup of function arguments and struct members. Also
+ remove most uses of the deprecated Li macro which has no effect.
+ [59b01b9ff183]
+
+ * docs/sudo_plugin.man.in, docs/sudo_plugin.mdoc.in:
+ Move the init_session() errstr description to where it belongs.
+ [8c1e7cb23d1f]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ Fix a typo
+ [591b75013070]
+
+2022-09-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/logging.c:
+ log_parse_error: make errstr const to quiet a -Wwrite-strings
+ warning
+ [9827a2a01316]
+
+ * config.h.in, configure.ac, include/sudo_compat.h,
+ include/sudo_debug.h, include/sudo_fatal.h, include/sudo_lbuf.h,
+ include/sudo_util.h, lib/eventlog/eventlog.c,
+ plugins/sudoers/check_aliases.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers.h, plugins/sudoers/defaults.c,
+ plugins/sudoers/logging.h, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/toke.h,
+ plugins/sudoers/tsdump.c, plugins/sudoers/visudo.c,
+ src/parse_args.c, src/regress/noexec/check_noexec.c, src/sudo.h:
+ Move gcc-style __attribute__ macros to config.h.in Renamed __malloc
+ -> sudo_malloclike, __printflike -> sudo_printflike, __printf0like
+ -> sudo_printf0like. Add sudo_noreturn instead of
+ __attribute__((__noreturn__)). We do not use stdnoreturn.h since it
+ has been deprecated in C23 in favor of the [[noreturn]] attribute.
+ [ad3c04a1bbb0]
+
+ * plugins/sudoers/visudo.c:
+ Add __printf0like to visudo_track_error().
+ [7a118c40d360]
+
+2022-09-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/gram.y:
+ Back out unintended change in last commit.
+ [5d52c966212d]
+
+ * plugins/sudoers/gram.y, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h:
+ It is possibble for sudoerserrorf() to be called with a NULL format.
+ So log_parse_error() needs to check fmt for NULL before using it.
+ [5b779a6888c9]
+
+2022-09-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/UPGRADE.md:
+ Mention how to restore the historic core resource limit behavior.
+ [bfd792bd9d07]
+
+ * plugins/sudoers/audit.c:
+ Set MODE_POLICY_INTERCEPTED for log_subcmds too. This fixes a
+ problem where sub-commands were not being logged to the remote log
+ server, if configured. Since we don't go through
+ sudoers_policy_main() again for log_subcmds, we set the flag in
+ sudoers_audit_accept() instead. The reason this is complicated is
+ that when I/O logging is enabled the initial accept message gets
+ sent as part of the remote logging handshake. GitHub issue #174
+ [297fa6bbd769]
+
+2022-09-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Update with latest changes.
+ [d7ca5db7adc7]
+
+ * docs/cvtsudoers.mdoc.in:
+ Fix typo.
+ [7629516758e2]
+
+ * plugins/sudoers/sudoers.c:
+ Only check the admin flag file once in intercept mode.
+ [c439914e08e1]
+
+ * docs/cvtsudoers.man.in, docs/cvtsudoers.mdoc.in:
+ Document cvtsudoers CSV output format
+ [c5164466cae2]
+
+2022-08-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/cvtsudoers.man.in, docs/cvtsudoers.mdoc.in:
+ Document cvtsudoers JSON output format
+ [9fce227c2c61]
+
+2022-08-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.c:
+ Zero out register struct before calling ptrace_getregs(). Quiets a
+ spurious valgrind warning.
+ [32f19e2e508f]
+
+2022-08-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ intercept_verify is fast, but the policy check is (relatively) slow.
+ [0a120a78bd37]
+
+ * src/exec_ptrace.c:
+ Realloc the buffer used to store argv and envp as needed. We now
+ store the vector immediately after the string table. It is possible
+ for argv and its contents to be invalidated by realloc() when
+ reading envp so we store the pointers as offsets until we are done
+ allocating.
+ [7620f3dceac4]
+
+2022-08-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.c, src/exec_ptrace.h:
+ ptrace_verify_post_exec: use /proc/PID/cmdline and /proc/PID/environ
+ There is no reason to read these directly from the tracee when we
+ rely on /proc being mounted to access /proc/PID/exe.
+ [5da938210647]
+
+ * src/exec_ptrace.c:
+ Protect ptrace_readv_string() with #ifdef HAVE_PROCESS_VM_READV
+ [cc8e71c4c529]
+
+2022-08-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ Rework the intercept section in "Preventing shell escapes".
+ [5e5b1ea90ce1]
+
+ * .github/workflows/codeql-analysis.yml:
+ Update CodeQL Action to v2 using current example config.
+ [d0aa8b4dda28]
+
+ * lib/util/arc4random.c:
+ Suppress PVS-Studio false positive.
+ [32fd02734378]
+
+ * src/exec_intercept.c:
+ intercept_check_policy_req: an empty argv[] is now supported
+ [a668708cc0a9]
+
+ * config.h.in, configure, configure.ac, src/exec_ptrace.c:
+ Use process_vm_readv(2) and process_vm_writev(2) if available. This
+ is faster than reading/writing from/to the remote process one word
+ at a time using PTRACE_PEEKDATA and PTRACE_POKEDATA.
+ [d0c5ed82738c]
+
+ * plugins/sudoers/check.c:
+ Skip all of check_user() for intercept unless intercept_authenticate
+ set. Previously we were calling the PAM approval modules even in
+ intercept mode which can take a lot of time. We may wish to make PAM
+ approval configurable in intercept mode in the future.
+ [e06fbc7e4ca6]
+
+ * plugins/sudoers/sudoers.c:
+ Only set MODE_POLICY_INTERCEPTED on subsequent policy checks. This
+ fixes a bug where MODE_POLICY_INTERCEPTED was set too early if the
+ intercept option was set globally in sudoers. It should only be set
+ after the original command has executed.
+ [8f5d47c2635a]
+
+2022-08-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ intercept_verify also compares the environment. Also mention the
+ overhead involved in checking things.
+ [44da04558285]
+
+2022-08-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.c:
+ ptrace_getregs: make compat check more generic No need to use
+ different checks for mips and non-mips, the compiler will optimize
+ away the superfluous check.
+ [0f2ff0f3f388]
+
+ * src/preload.c:
+ Correct type of sudoers_audit. GitHub issue #61
+ [17a7806ad3ba]
+
+2022-08-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sesh.c:
+ Fix shadowed variable warning.
+ [e200b6b5b4fd]
+
+2022-08-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.h:
+ Fix shadowed variable warning on aarch64.
+ [84169692bd1c]
+
+ * src/regress/intercept/test_ptrace.c:
+ Quiet another -Wwrite-strings warning.
+ [ff2860056976]
+
+ * src/exec_ptrace.c:
+ ptrace_getregs: try to determine compat mode if caller doesn't know.
+ In ptrace_verify_post_exec(), we don't know whether the executable
+ that is now running is a native or compat binary. In most cases
+ ptrace_getregs() will be able to figure it out for us.
+ [fb0fa29ff554]
+
+ * src/exec_ptrace.c:
+ ptrace_intercept_execve: fail syscall rather than killing process on
+ error. If the execve(2) args are bogus pointers, we should just
+ return an error instead of killing the process. For consistency with
+ the kernel, convert EIO from ptrace(2) to EFAULT. Also convert some
+ ptrace(2) warnings to debug printfs so sudo is less chatty.
+ [3d30c6d28005]
+
+2022-08-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.c:
+ Treat argv and closure->run_argv of different sizes as a mismatch.
+ If argv and closure->run_argv match up to the point where we hit a
+ NULL but one of them has additional entries, we still need to
+ rewrite argv.
+ [91d522d9c3b6]
+
+ * src/exec_ptrace.c:
+ Handle the case where argc is 0 when allocating space for argv. We
+ need to pass the pathname to the policy plugin in argv[0] so we must
+ be sure to allocate space for it even if argc is 0.
+ [953f92c9e7a5]
+
+ * src/sudo_intercept.c:
+ copy_vector: treat a NULL pointer as an empty vector. Linux
+ execve(2) allows argv to be NULL so we must allocate an empty vector
+ in this case and not return an error.
+ [cf30608ed6cb]
+
+ * src/exec_preload.c:
+ Update debug_decl name for sudo_preload_dso ->
+ sudo_preload_dso_alloc change.
+ [b0db53a62c7a]
+
+ * src/exec_intercept.c:
+ Handle the case where argc is 0 when rebuilding argv. We need to
+ pass the pathname to the policy plugin in argv[0] so we must be sure
+ to allocate space for it even if argc is 0.
+ [10358fc408a1]
+
+ * src/exec_ptrace.c:
+ Handle sysconf(_SC_ARG_MAX) failure, Coverity CID 276504.
+ [ddb88da56bd7]
+
+ * plugins/sudoers/match_digest.c:
+ Avoid a Coverity false positive.
+ [dd9fd747bd7f]
+
+ * plugins/sudoers/getdate.c, plugins/sudoers/getdate.y:
+ Remove cast from time_t to int to avoid a Coverity false positive.
+ The cast should not be required.
+ [a305b10eb17e]
+
+2022-08-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in,
+ plugins/sudoers/group_plugin.c:
+ Use multilib rules to look for a 64-bit group plugin on failure. If
+ sudo_dso_load() fails on a 64-bit system, try to load a 64-bit
+ native version of the file using system-dependent multilib rules. If
+ we don't support multilib on the platform, check for a version of
+ the file that ends in "64" before the .so suffix.
+ [d36bcc89ee34]
+
+ * docs/sudo_plugin.man.in:
+ regen
+ [c14c0882a07d]
+
+2022-08-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/env.c, src/env_hooks.c:
+ In putenv(3) replacement reject a string with no '=' or that starts
+ with one.
+ [59c6e6e5232b]
+
+2022-08-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * LICENSE.md:
+ Update copyright year for embedded zlib.
+ [2c52d016e583]
+
+2022-08-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Use our own arc4random() in preference to the glibc version. The
+ glibc arc4random() may fail in chroot on older kernels and exit.
+ [9b4a62c9f468]
+
+ * lib/util/sudo_dso.c:
+ sudo_dso_load: restore original error for AIX on failure. For AIX,
+ if dlopen() fails we try again with RTLD_MEMBER set and a default
+ member (shr.o or shr_64.o). However, if that also fails, the user
+ will receive a useless error message that doesn't correspond to the
+ actual problem. We now retry the original dlopen() if the fallback
+ to RTLD_MEMBER fails, which has the effect of restoring the original
+ error message.
+ [ec539996a4aa]
+
+2022-08-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #165 from bdrung/xdg-current-desktop
+
+ Add XDG_CURRENT_DESKTOP to initial_keepenv_table
+ [3d2e82e32ea8]
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.12.
+ [08c096ada8b2]
+
+ * docs/sudo_plugin.mdoc.in, include/sudo_plugin.h, plugins/python/regr
+ ess/testdata/check_multiple_approval_plugin_and_arguments.stdout,
+ src/exec.c:
+ Bump the sudo plugin minor version. The "update_ticket" entry was
+ added to the settings list and the "intercept_verify" entry was
+ added to the command_info list.
+ [3259f3199798]
+
+ * docs/sudo.man.in, docs/sudo.mdoc.in, plugins/sudoers/check.c,
+ plugins/sudoers/policy.c, plugins/sudoers/sudoers.h,
+ src/parse_args.c, src/sudo.c, src/sudo.h, src/sudo_usage.h.in:
+ Add a way to run a command without updating the cached credentials.
+ This can also be used to test for whether or not the user's
+ credentials are currently cached.
+ [f5825a6f881b]
+
+ * Merge pull request #168 from likunyur/lky
+
+ Remove unnecessary initialization and casts.
+ [fcb251c895ce]
+
+ * Merge pull request #169 from kempstonjoystick/main
+
+ Fix incorrect SHA384/512 digest calculation.
+ [f016c3a37255]
+
+2022-08-02 Tim Shearer <timtimminz@gmail.com>
+
+ * lib/util/sha2.c:
+ Fix incorrect SHA384/512 digest calculation.
+
+ Resolves an issue where certain message sizes result in an incorrect
+ checksum. Specifically, when: (n*8) mod 1024 == 896 where n is the
+ file size in bytes.
+ [e9f235a8d432]
+
+2022-08-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec.c, src/selinux.c, src/sesh.c, src/sudo.c, src/sudo.h:
+ Defer chdir(2) until sesh when running with SELinux. We need to be
+ running with the correct security context or the chdir(2) may fail.
+ GitHub issue #160.
+ [a8713dd21be9]
+
+2022-08-01 Li zeming <zeming@nfschina.com>
+
+ * lib/util/arc4random.c:
+ util/arc4random: (void*) type pointer passing address could remove
+ cast
+
+ Signed-off-by: Li zeming <zeming@nfschina.com>
+ [aa4e8c73f131]
+
+ * lib/iolog/hostcheck.c:
+ iolog/hostcheck: These two parameters do not need to be initialized
+ and assigned, the following code is directly assigned
+
+ Signed-off-by: Li zeming <zeming@nfschina.com>
+ [dd657435f277]
+
+2022-07-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #166 from c4rlo/patch-1
+
+ visudo.c: add nvim (Neovim) to lineno_editor list
+ [97e0a7b00daa]
+
+2022-07-31 Carlo Teubner <435950+c4rlo@users.noreply.github.com>
+
+ * plugins/sudoers/visudo.c:
+ visudo.c: add nvim (Neovim) to lineno_editor list
+
+ Neovim supports it: https://neovim.io/doc/user/starting.html#-+
+ [020b59cf0f6b]
+
+2022-07-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ Document the TOCTOU issue with intercept mode. Describe how
+ intercept_verify attempts to reduce the risk.
+ [b118de8d4c66]
+
+ * etc/codespell.exclude, etc/codespell.ignore:
+ Update a codespell exclude pattern.
+ [3193ffb4c938]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/policy.c, src/exec_ptrace.c, src/sudo.c, src/sudo.h:
+ Add intercept_verify sudoers option to control execve(2) argument
+ checking.
+ [79131cfb0125]
+
+ * src/exec_ptrace.c:
+ Use PTRACE_EVENT_EXEC to stop execution before return from
+ execve(2). We can now verify that the arguments match what we
+ accepted before the command actually runs. If there is a mismatch,
+ the process is killed. Shell scripts must be handled specially since
+ the path executed will be the interpreter, not the script name.
+ Linux allows interpreters to be nested up to 4 deep.
+ [5e7b1828dbb0]
+
+ * plugins/sudoers/sudoers.c:
+ Only set MODE_POLICY_INTERCEPTED if we are running a command. Fixes
+ an error with "sudo -l" when intercept is enabled globally.
+ [7a1d0ff5a498]
+
+2022-07-29 Benjamin Drung <bdrung@ubuntu.com>
+
+ * plugins/sudoers/env.c:
+ Add XDG_CURRENT_DESKTOP to initial_keepenv_table
+
+ Qt needs `XDG_CURRENT_DESKTOP` to be set to determine the correct
+ theme.
+
+ Since `DISPLAY` and `XAUTHORITY` are already in the default table of
+ variables to preserve in the environment, just add
+ `XDG_CURRENT_DESKTOP` to it.
+
+ Bug: https://launchpad.net/bugs/1958055 Signed-off-by: Benjamin
+ Drung <bdrung@ubuntu.com>
+ [aa5132684c89]
+
+2022-07-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.c:
+ The length returned by ptrace_read_string() include the NUL. We were
+ wasting a extra byte in the string table for each entry.
+ [b1220aae7141]
+
+2022-07-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_compat.h, include/sudo_util.h:
+ Use gcc's malloc attribute for malloc-like allocation functions.
+ [bff3b0ab89c5]
+
+ * lib/util/mmap_alloc.c:
+ Avoid a Coverity positive.
+ [81f526688296]
+
+ * src/exec_preload.c:
+ fmtstr: add missing va_end() for the overflow case Coverity CID
+ 275335
+ [42a4f4467ca5]
+
+ * lib/util/sudo_debug.c:
+ Fix potential NULL pointer deference found by clang-analyzer.
+ [5b0a9c0f2e71]
+
+ * src/sudo.c, src/sudo_intercept_common.c:
+ Quiet some harmless PVS-Studio warnings.
+ [9b9cc92f0585]
+
+ * src/exec_intercept.c:
+ Reject relative command paths if runcwd is not set. This is now
+ treated as a policy rejection.
+ [bf35a6818c77]
+
+ * src/exec_intercept.c:
+ intercept_check_policy: close saved_dir before returning
+ [04adba5e85fa]
+
+ * src/exec_intercept.c:
+ Change to runcwd during the policy check where possible. Otherwise,
+ attempts to run "./command" from a shell with intercept set will
+ fail if the current working directory is different from the main
+ sudo process.
+ [cd218f081cf2]
+
+2022-07-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_util.h, lib/util/mmap_alloc.c, lib/util/util.exp.in,
+ src/sudo_intercept.c:
+ For preload DSO make copies of cmnd, argv, envp and map them read-
+ only.
+ [56a160c55e4c]
+
+ * src/exec_preload.c, src/sudo_exec.h, src/sudo_intercept.c,
+ src/sudo_intercept_common.c:
+ Use sudo_mmap_alloc functions in DSO-based intercept code.
+ [806dacd141ad]
+
+ * lib/util/snprintf.c:
+ Use sudo_mmap_alloc functions instead of private versions. We no
+ longer need to keep track of the allocation size.
+ [6f375ed7a927]
+
+ * MANIFEST, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/mmap_alloc.c, lib/util/util.exp.in:
+ Add sudo_mmap_{alloc,allocarrary,strdup,free} functions. These
+ allocate memory via mmap anonymous regions and store the mapped size
+ immediately before the returned pointer as an unsigned long. They
+ are intended to be used in cases where malloc(3) and free(3) are
+ unsuitable due to concerns about corrupting global state in multi-
+ threaded programs or signal handlers.
+ [803b4a82bedd]
+
+ * docs/sudoers.ldap.man.in, docs/sudoers.ldap.mdoc.in:
+ Sync with schema.OpenLDAP for user/group utf8 support.
+ [14705b52a4f9]
+
+ * Merge pull request #163 from Firstyear/20220725-sudo-ldap-schema
+
+ Update sudoUser to be utf8 in ldap schemas
+ [91354fc2ed23]
+
+ * src/sudo_intercept.c:
+ resolve_path: skip non-regular files
+ [2ed5efdb48ea]
+
+2022-07-25 William Brown <wbrown@suse.de>
+
+ * docs/schema.OpenLDAP, docs/schema.iPlanet, docs/schema.olcSudo:
+ Update sudoUser to be utf8 in ldap schemas
+
+ In most unix-style LDAP servers, uid is a utf8 string defined by OID
+ 1.3.6.1.4.1.1466.115.121.1.15. However, sudoUser was defined as an
+ IA5 String (OID 1.3.6.1.4.1.1466.115.121.1.26) which meant that
+ sudoUser could only represent a subset of possible values.
+
+ In some cases when using sudoers.ldap, the uid from the machine
+ which was utf8 was fed back into sudo which would then issue a
+ search for sudoUsers. If this uid contained utf8 characters, the
+ ldap server would refuse to match into sudoUsers because these were
+ limited to IA5.
+
+ This is a safe-forward upgrade as IA5 is a subset of UTF8 meaning
+ that this change will not impact existing deployments and their
+ rules.
+ [7a47e711ca88]
+
+2022-07-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_intercept.c, src/sudo.c:
+ Make sure the plugin provides a command, argv and envp.
+ [7e4e93118622]
+
+ * lib/util/sudo_debug.c, src/exec_intercept.c, src/exec_preload.c,
+ src/exec_ptrace.c, src/sudo_intercept.c,
+ src/sudo_intercept_common.c:
+ Linux execve(2) allows argv or envp to be NULL. Add checks to make
+ sure we don't deference a NULL pointer.
+ [be380b71df62]
+
+2022-07-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_intercept.c:
+ intercept_check_policy: add oom label and fix approval failure case.
+ If the approval plugin fails we need to set the state to
+ POLICY_REJECT just like we do if the policy rejected the command.
+ [e7ba37e32af7]
+
+2022-07-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers_csv.c, plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/cvtsudoers_merge.c, plugins/sudoers/def_data.in,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/policy.c, src/apparmor.c:
+ Fix a few whitespace issues.
+ [deb6391a3ba0]
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Increase the realloc increment from 128 to 1024. The contents of the
+ env_add array should not include the leading "env=" prefix.
+ [d8c0067fc3fd]
+
+ * plugins/sudoers/env.c:
+ sudo_putenv_nodebug: require that the environment string include a
+ '='
+ [fb200f301070]
+
+2022-07-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/visudo.c:
+ If update_defaults() fails, treat it as a parse error.
+ [d9860eb2257a]
+
+ * plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Add additional PVS-studio suppression comments for generated code.
+ [dfb89944dcce]
+
+2022-07-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/match_command.c:
+ Fix compilation error when SUDOERS_NAME_MATCH is defined.
+ [3b76707bc5fa]
+
+ * plugins/sudoers/match_command.c:
+ Fix a NOPASSWD issue with a non-existent command when fdexec=always
+ In command_matches_all(), if the command is fully-qualified and
+ open_cmnd() return false, only treat it as an error if we are able
+ to stat(2) the command. For "sudo ALL" a non-existent command is not
+ an error.
+ [e2d756137ce9]
+
+ * plugins/sudoers/regress/testsudoers/test18.sh:
+ Quote ^foo$ on command line to protect it from the shell.
+ [0f1274e0be93]
+
+2022-07-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/eventlog/regress/logwrap/check_wrap.c,
+ lib/util/regress/closefrom/closefrom_test.c,
+ lib/util/regress/fnmatch/fnm_test.c,
+ lib/util/regress/getgrouplist/getgrouplist_test.c,
+ lib/util/regress/glob/globtest.c,
+ lib/util/regress/parse_gids/parse_gids_test.c,
+ lib/util/regress/progname/progname_test.c,
+ lib/util/regress/strsig/strsig_test.c,
+ lib/util/regress/strsplit/strsplit_test.c,
+ lib/util/regress/strtofoo/strtobool_test.c,
+ lib/util/regress/strtofoo/strtoid_test.c,
+ lib/util/regress/strtofoo/strtomode_test.c,
+ lib/util/regress/strtofoo/strtonum_test.c,
+ lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_parseln/parseln_test.c,
+ lib/util/regress/tailq/hltq_test.c,
+ lib/util/regress/uuid/uuid_test.c,
+ logsrvd/regress/logsrvd_conf/logsrvd_conf_test.c,
+ plugins/python/regress/check_python_examples.c, src/exec_ptrace.c:
+ Add explicit include of unistd.h for getopt(3) and related
+ variables.
+ [e1c369cd5ae8]
+
+2022-07-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers.c, src/sudo_intercept_common.c:
+ Merge pull request #161 from likunyur/lky
+
+ sudoers/cvtsudoers: Remove the repeated ';' from code
+ [9b961a3b9c86]
+
+2022-07-04 Li kunyu <kunyu@nfschina.com>
+
+ * src/sudo_intercept_common.c:
+ src/send: Remove the repeated ';' from code
+
+ Signed-off-by: Li kunyu <kunyu@nfschina.com>
+ [6fc809eac0b1]
+
+ * plugins/sudoers/cvtsudoers.c:
+ sudoers/cvtsudoers: Remove the repeated ';' from code
+
+ Signed-off-by: Li kunyu <kunyu@nfschina.com>
+ [75582c880c30]
+
+2022-07-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/timegm.c:
+ In timegm() initialize tm_isdst to 0 like tzcode does.
+ [d3f2d10c3559]
+
+2022-06-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/intercept.pb-c.h, include/sudo_event.h,
+ src/exec_intercept.c, src/exec_intercept.h, src/intercept.pb-c.c,
+ src/intercept.proto, src/sudo_intercept_common.c:
+ Stop sending an InterceptResponse to a PolicyCheckRequest for
+ log_subcmds. There's no real reason for the command to wait for sudo
+ send back a response that will always be a PolicyAcceptMessage.
+ [d2fe28a652d0]
+
+ * plugins/sudoers/sudoers.c:
+ sudoers_main: defer setting return value until the end when running
+ a command Otherwise, we could return success when there was an error
+ from a system call or memory allocation failure.
+ [bd993a2948ce]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Save the initial command run via sudo and use it when logging exit
+ status. Otherwise, if we are in intercept mode or logging sub-
+ commands the exit status will be logged with the wrong command.
+ [54e3494473ac]
+
+2022-06-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/zlib/zconf.h.in:
+ Define _LARGEFILE64_SOURCE if _FILE_OFFSET_BITS == 64. Fixes a
+ -Wwrite-strings warning on 32-bit systems.
+ [61eff691496f]
+
+ * lib/util/strsignal.c:
+ Quiet another -Wwrite-strings warning.
+ [a03bb85d581d]
+
+ * lib/protobuf-c/protobuf-c.c:
+ Fix a clang analyzer 14 warning about a possible NULL deref.
+ [4c0db4ac3e1d]
+
+ * lib/iolog/Makefile.in, lib/logsrv/Makefile.in,
+ lib/protobuf-c/Makefile.in, plugins/sudoers/Makefile.in,
+ src/Makefile.in:
+ Regenerate dependencies
+ [ff7de2b59097]
+
+ * scripts/mkdep.pl:
+ Do not check files generated by protbuf-c with PVS-Studio
+ [86f56c21339f]
+
+ * logsrvd/logsrv_util.c, logsrvd/logsrvd.c, logsrvd/logsrvd_conf.c,
+ logsrvd/logsrvd_queue.c, logsrvd/sendlog.c, logsrvd/tls_client.c,
+ plugins/sudoers/log_client.c, src/sudo_intercept_common.c:
+ Quiet some harmless PVS Studio warnings.
+ [476fbef7a0c4]
+
+ * logsrvd/logsrvd_conf.c, logsrvd/sendlog.c:
+ Use "unable to allocate memory" warning on malloc failure. This is
+ consistent with the rest of the sudo source code.
+ [5954fc067647]
+
+ * lib/eventlog/Makefile.in, lib/fuzzstub/Makefile.in,
+ lib/iolog/Makefile.in, lib/iolog/host_port.c,
+ lib/logsrv/Makefile.in, lib/protobuf-c/Makefile.in,
+ lib/util/Makefile.in, lib/util/getentropy.c, lib/util/roundup.c,
+ logsrvd/iolog_writer.c, logsrvd/logsrv_util.c, logsrvd/logsrvd.c,
+ logsrvd/logsrvd_conf.c, logsrvd/logsrvd_journal.c,
+ logsrvd/logsrvd_local.c, logsrvd/logsrvd_queue.c,
+ logsrvd/logsrvd_relay.c, logsrvd/sendlog.c, logsrvd/tls_client.c,
+ logsrvd/tls_init.c, plugins/sudoers/log_client.c, src/Makefile.in,
+ src/apparmor.c:
+ Add missing PVS Studio Open Source comments. Also avoid checking
+ protobuf-c source and protobuf-c generated files.
+ [e1277c1f6585]
+
+ * lib/iolog/host_port.c, lib/iolog/hostcheck.c, lib/util/roundup.c,
+ logsrvd/iolog_writer.c, logsrvd/logsrv_util.c, logsrvd/logsrvd.c,
+ logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c,
+ logsrvd/logsrvd_journal.c, logsrvd/logsrvd_local.c,
+ logsrvd/logsrvd_queue.c, logsrvd/logsrvd_relay.c, logsrvd/sendlog.c,
+ logsrvd/sendlog.h, logsrvd/tls_client.c, logsrvd/tls_common.h,
+ logsrvd/tls_init.c, plugins/python/pyhelpers.h,
+ plugins/python/regress/iohelpers.h, plugins/sudoers/log_client.c:
+ Use #include <config.h> not #include "config.h" for consistency.
+ Otherwise, some compilers may do the wrong thing in a build dir if
+ there is a config.h file in the source dir too.
+ [79aaab18dc6d]
+
+2022-06-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/group_plugin.c:
+ Update group_plugin_load() stub to match its prototype.
+ [9ea7126e6d5c]
+
+ * configure, configure.ac, include/sudo_iolog.h,
+ lib/eventlog/eventlog.c, lib/eventlog/logwrap.c,
+ lib/iolog/host_port.c, lib/iolog/regress/host_port/host_port_test.c,
+ lib/iolog/regress/iolog_mkpath/check_iolog_mkpath.c, lib/util/aix.c,
+ lib/util/getgrouplist.c, lib/util/getopt_long.c, lib/util/lbuf.c,
+ lib/util/logfac.c, lib/util/logpri.c,
+ lib/util/regress/progname/progname_test.c, lib/util/snprintf.c,
+ lib/util/sudo_conf.c, lib/util/sudo_debug.c, logsrvd/logsrvd_conf.c,
+ logsrvd/logsrvd_local.c, logsrvd/logsrvd_relay.c, logsrvd/sendlog.c,
+ plugins/audit_json/audit_json.c,
+ plugins/python/python_convmessage.c,
+ plugins/python/python_plugin_common.c,
+ plugins/python/regress/check_python_examples.c,
+ plugins/python/sudo_python_module.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/sudo_auth.h,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers_csv.c,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/defaults.h, plugins/sudoers/editor.c,
+ plugins/sudoers/env.c, plugins/sudoers/exptilde.c,
+ plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/insults.h, plugins/sudoers/iolog.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/ldap_conf.c,
+ plugins/sudoers/log_client.c, plugins/sudoers/logging.c,
+ plugins/sudoers/parse.c, plugins/sudoers/policy.c,
+ plugins/sudoers/pwutil.c,
+ plugins/sudoers/regress/editor/check_editor.c,
+ plugins/sudoers/regress/exptilde/check_exptilde.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/regress/parser/check_gentime.c,
+ plugins/sudoers/regress/serialize_list/check_serialize_list.c,
+ plugins/sudoers/regress/unescape/check_unesc.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/sudoers_hooks.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ src/edit_open.c, src/exec_common.c, src/parse_args.c,
+ src/regress/noexec/check_noexec.c, src/selinux.c, src/sudo.c,
+ src/sudo_edit.c, src/sudo_intercept.c:
+ Make sudo pass -Wwrite-strings
+ [7ac3dd7b1634]
+
+ * configure, configure.ac:
+ A typo prevented -Wno-deprecated-declarations from being used on
+ macOS.
+ [4d6d4b9e7191]
+
+2022-06-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/preload.c:
+ Fix missing prototype warning.
+ [66e460d3c1d2]
+
+ * lib/zlib/zconf.h.in:
+ Define _LFS64_LARGEFILE, _LARGEFILE64_SOURCE if 64-bit or
+ _LARGE_FILES set. autoconf does not define _LARGEFILE64_SOURCE by
+ default but zlib expects it (its own configure script will define
+ it). Fixes a missing prototype for crc32_combine_gen64() on AIX and
+ HP-UX.
+ [c5b314bebbcb]
+
+ * configure, configure.ac, include/sudo_iolog.h, include/sudo_util.h,
+ lib/iolog/host_port.c, lib/iolog/regress/fuzz/fuzz_iolog_json.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_legacy.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_timing.c,
+ lib/iolog/regress/iolog_json/check_iolog_json.c,
+ lib/iolog/regress/iolog_timing/check_iolog_timing.c,
+ lib/util/regress/fuzz/fuzz_sudo_conf.c,
+ lib/util/regress/glob/globtest.c,
+ lib/util/regress/mktemp/mktemp_test.c, lib/util/strtoid.c,
+ logsrvd/logsrvd.c, logsrvd/logsrvd_relay.c,
+ logsrvd/regress/fuzz/fuzz_logsrvd_conf.c, logsrvd/sendlog.c,
+ plugins/python/pyhelpers.c, plugins/python/python_plugin_approval.c,
+ plugins/python/python_plugin_approval_multi.inc,
+ plugins/python/python_plugin_audit.c,
+ plugins/python/python_plugin_audit_multi.inc,
+ plugins/python/python_plugin_common.c,
+ plugins/python/python_plugin_group.c,
+ plugins/python/python_plugin_io.c,
+ plugins/python/python_plugin_io_multi.inc,
+ plugins/python/python_plugin_policy.c,
+ plugins/python/regress/check_python_examples.c,
+ plugins/python/sudo_python_module.c, plugins/sudoers/audit.c,
+ plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/iolog.c, plugins/sudoers/log_client.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_stubs.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/stubs.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/timestr.c, plugins/sudoers/tsgetgrpw.h,
+ plugins/sudoers/unesc_str.c, src/copy_file.c, src/exec_ptrace.c,
+ src/load_plugins.c, src/net_ifs.c, src/sudo.h, src/sudo_intercept.c,
+ src/sudo_intercept_common.c, src/sudo_noexec.c:
+ Make sudo pass -Wmissing-prototypes
+ [195b024b9f54]
+
+ * src/exec_ptrace.c:
+ Include inttypes.h if stdint.h is not present. Bug #1035
+ [da6185c4c418]
+
+2022-06-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.c:
+ readlink(2) does NUL-terminate the buffer, do it manually. Fixes a
+ bug where the current working directory could include garbage in
+ intercept mode using ptrace(2).
+ [dc7c547f518f]
+
+ * src/exec_preload.c, src/sudo_exec.h, src/sudo_intercept_common.c:
+ sudo_preload_dso: make the envp function argument const This lets us
+ fix an inappropriate cast in sudo_intercept_common.c.
+ [c2fa860b684e]
+
+ * src/exec_intercept.c:
+ intercept_write: remove unused CD_USE_PTRACE code. It is not
+ possible to end up in intercept_write when CD_USE_PTRACE is set.
+ [f8bdc5e37294]
+
+2022-06-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_11p3 for changeset 6e671475b373
+ [59e5766213e9] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Merge sudo 1.9.11p3 from tip.
+ [6e671475b373] [SUDO_1_9_11p3] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.11p3
+ [c96ded63ae46]
+
+ * src/exec_intercept.c, src/sudo_intercept_common.c:
+ Set TCP_NODELAY on the socket used for intercept IPC to reduce
+ latency. On some systems, Nagle's algorithm was delaying receipt of
+ the data, causing commands with intercept or log_subcmds to run
+ slowly. Related to Bug #1034.
+ [11b129850ac1]
+
+ * src/sudo_intercept_common.c:
+ Use blocking I/O when talking to the sudo process. Also check for
+ EAGAIN/EINTR when reading the message size. Fixes a problem seen on
+ AIX where recv_intercept_response() could fail unexpectedly. Bug
+ #1034.
+ [8554618665a2]
+
+ * src/exec_intercept.c:
+ Add debug printfs when send/recv return EAGAIN or EINTR. These are
+ not actually errors but can help gain insight into what is going on
+ and, in the case of EAGAIN, whether or not there may be a kernel
+ resource starvation problem.
+ [fd2dee906d2f]
+
+2022-06-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/logging.c:
+ log_exit_status: make local variables match struct evlog members.
+ [f93d5141e818]
+
+2022-06-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/getgrouplist.c:
+ Quiet a compiler warning on macOS. The getgrouplist() groups array
+ on macOS is int * instead of gid_t *.
+ [c64bf72a1416]
+
+2022-06-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_11p2 for changeset 9e4705cb1db5
+ [2a4b6b814432] <1.9>
+
+ * NEWS, configure, configure.ac, include/sudo_compat.h:
+ Merge sudo 1.9.11p2 from tip.
+ [9e4705cb1db5] [SUDO_1_9_11p2] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.11p2
+ [9505276e5c97]
+
+2022-06-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.h:
+ Fix compilation on Linux/x32; GitHub issue #158
+ [8cebfdd49205]
+
+2022-06-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/policy.c:
+ Fix pasto in comment after HAVE_PRIV_SET #endif
+ [2275ab3b016d]
+
+ * include/sudo_compat.h:
+ Fix typo, we should define SSIZE_MAX if it is not defined.
+ [51c68f801479]
+
+2022-06-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/env.c:
+ Change black list -> blocklist This was missed in the previous
+ conversion.
+ [da610ebb5cb1]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/log_client.c, plugins/sudoers/log_client.h,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/policy.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/sudoers.h:
+ Save a pointer to the event_alloc parameter in the plugin open
+ function. That way we don't need to pass event_alloc around to the
+ log client functions.
+ [a8a47f3770b3]
+
+ * lib/protobuf-c/protobuf-c.c:
+ Fix regression with zero-length messages introduced in protobuf-c PR
+ 500.
+ [42062b9f75d5]
+
+2022-06-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_11p1 for changeset 06b0f12fe91c
+ [feb8ae553833] <1.9>
+
+ * NEWS, config.h.in, configure, configure.ac:
+ Merge sudo 1.9.11p1 from tip.
+ [06b0f12fe91c] [SUDO_1_9_11p1] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.11p1
+ [7fcfdaacb15e]
+
+2022-06-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_pty.c:
+ Make read and write events persistent and disable as needed. For the
+ read callback, disable reader when the buffer is full. For the write
+ callback, disable writer when the buffer is consumed.
+ [2b6953dc4224]
+
+ * config.h.in, configure, configure.ac, src/sudo_exec.h,
+ src/sudo_noexec.c:
+ Check for SECCOMP_MODE_FILTER not SECCOMP_SET_MODE_FILTER. This
+ matches the actual prctl() call we use.
+ [4222768293d1]
+
+ * Merge pull request #157 from 0x2b3bfa0/improve-tag-spec-ebnf-docs
+
+ Improve Tag_Spec EBNF documentation
+ [f528335aded5]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd_relay.c, logsrvd/sendlog.c:
+ Treat EINTR in a callback like we do EAGAIN. We shouldn't get EINTR
+ in practice since we set SA_RESTART when registering signal handlers
+ but it doesn't hurt to be consistent.
+ [acf3394e2df2]
+
+ * Merge pull request #156 from delroth/aarch64-build
+
+ exec_ptrace: fix missing sudo_pt_regs on aarch64
+ [a7062c609a96]
+
+2022-06-07 Pierre Bourdon <delroth@gmail.com>
+
+ * src/exec_ptrace.h:
+ exec_ptrace: fix missing sudo_pt_regs on aarch64
+
+ AArch64 already had an existing "user_pt_regs" struct and didn't
+ need a struct alias before the renaming to "sudo_pt_regs". Make the
+ code build again by adding the now missing alias.
+
+ Fixes: 2eb8ff17
+ [3b55f40e9b83]
+
+2022-06-07 Helio Machado <0x2b3bfa0+git@googlemail.com>
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ Improve Tag_Spec EBNF documentation
+ [7e23ec31d124]
+
+2022-06-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #154 from 0x2b3bfa0/fix-tag-spec-docs
+
+ Add missing colon in Tag_Spec documentation
+ [ec8f4610b677]
+
+ * Merge pull request #152 from particleflux/fix-sudoers-typo
+
+ Fix typo in sudoers comment
+ [bbbcff4c14ba]
+
+2022-06-07 Helio Machado <0x2b3bfa0+git@googlemail.com>
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ Add missing colon in Tag_Spec documentation
+ [e6f4c612e22a]
+
+2022-06-07 Stefan Linke <particleflux@gmail.com>
+
+ * plugins/sudoers/sudoers.in:
+ Fix typo in sudoers comment
+
+ Fix a typo in the sudoers comment about `maxseq` param.
+
+ Introduced by 906eb19ece47023c659b4b3db2e7a6bb57dff0d9 in 1.9.11.
+ [b38fae41b3eb]
+
+2022-06-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/protobuf-c/protobuf-c.c:
+ Only shift unsigned values to avoid implementation-specific
+ behavior. This converts the arithmetic shifts to logical shifts.
+ [e25aa8e9891a]
+
+ * lib/protobuf-c/protobuf-c.c:
+ Fix issue protobuf-c#499: unsigned integer overflow Signed-off-by:
+ 10054172 <hui.zhang@thalesgroup.com>
+ [f3637be4df4f]
+
+ * include/sudo_event.h, lib/util/event_select.c:
+ Fix building with select (not poll) when fd_set is not defined in
+ sys/types.h. We can use a void * for the fd_set arrays and just add
+ a cast when using the FD_SET macros.
+ [5c636cbc11f0]
+
+ * src/exec_pty.c:
+ Reinstall the event handler if we get EAGAIN from read/write
+ callback. The read and write events do not set SUDO_EV_PERSIST so we
+ need to explicitly re-enable the event if there is still data to be
+ read. Bug #963.
+ [0006cb6531f4]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd_relay.c, logsrvd/sendlog.c:
+ If write(2) returns EAGAIN just re-enter the event loop. This is
+ consistent with how we handle EAGAIN for read(2).
+ [e6478d917a0f]
+
+ * .hgtags:
+ Added tag SUDO_1_9_11 for changeset d495c99554f7
+ [74c59bc5c323] <1.9>
+
+ * NEWS, config.h.in, configure, configure.ac, include/sudo_compat.h,
+ logsrvd/tls_init.c, plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Merge sudo 1.9.11 from tip.
+ [d495c99554f7] [SUDO_1_9_11] <1.9>
+
+ * docs/sudo_plugin_python.man.in, docs/sudo_plugin_python.mdoc.in:
+ Document how setting ModulePath affects the Python search path. Also
+ advise the user to use a unique prefix to avoid name space
+ collisions with installed Python modules. Bug #1031.
+ [68a9d50d7806]
+
+ * configure, configure.ac, docs/sudo_plugin_python.man.in,
+ docs/sudo_plugin_python.mdoc.in:
+ Add EXAMPLES variables for use in the man pages for the examples
+ directory.
+ [148272d9a6d3]
+
+2022-06-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po:
+ Updated translations from translationproject.org
+ [985902730e5b]
+
+ * plugins/sudoers/po/hr.mo, po/hr.mo:
+ Rebuild Croatian message catalog.
+ [438136f65c13]
+
+2022-06-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .gitignore, .hgignore:
+ Add new test binaries to the ignore files.
+ [ea9de2ded48d]
+
+ * po/cs.mo, po/cs.po:
+ Updated translations from translationproject.org
+ [eac0aba546ed]
+
+ * lib/protobuf-c/protobuf-c.c:
+ Define WORDS_BIGENDIAN on big endian systems. Instead of a configure
+ check, we use endian.h (or a fallback).
+ [4d5603a9528c]
+
+ * include/intercept.pb-c.h, include/log_server.pb-c.h,
+ include/protobuf-c/protobuf-c.h, lib/protobuf-c/protobuf-c.c,
+ scripts/unanon:
+ Update to protobuf-c 1.4.0
+ [47ff9b8bab21]
+
+ * logsrvd/logsrvd.c, plugins/sudoers/cvtsudoers_csv.c:
+ Quiet two clang analyzer false positives.
+ [2c878f7853cc]
+
+ * src/exec_intercept.c:
+ Move a comment to the correct location.
+ [caacb3fae078]
+
+ * logsrvd/logsrvd.c:
+ union sockaddr_union: pass in sockaddr_union * instead of sockaddr
+ *. This eliminates the need for a few casts and is consistent with
+ how create_listener() is written.
+ [4def05f8d895]
+
+ * src/exec_ptrace.c:
+ Eliminate some dead stores that clang-analyzer complains about.
+ [3aac29fe0101]
+
+ * src/exec_ptrace.c:
+ ptrace_read_vec: don't try to free memory on the error path This is
+ leftover from when ptrace_read_string() allocated its own memory.
+ [7f5b5d21bce9]
+
+ * config.h.in, configure, configure.ac, src/sudo_intercept.c:
+ Avoid using vfork(2) in the DSO system(3) wrapper. Traditional
+ vfork(2) semantics make it unsafe for use for more than just
+ vfork(2) + execve(2).
+ [9a8ce7aef55d]
+
+2022-06-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * po/vi.mo, po/vi.po:
+ Updated translations from translationproject.org
+ [e3197ef8a98d]
+
+ * NEWS:
+ Mention sudo_logsrvd.conf "log_server" parsing fix.
+ [575a31b83bfd]
+
+ * MANIFEST, logsrvd/Makefile.in,
+ logsrvd/regress/logsrvd_conf/sudo_logsrvd.conf.1.in,
+ logsrvd/regress/logsrvd_conf/sudo_logsrvd.conf.2.in,
+ logsrvd/regress/logsrvd_conf/tls/sudo_logsrvd.conf.1.in,
+ logsrvd/regress/logsrvd_conf/tls/sudo_logsrvd.conf.2.in:
+ For logsrvd_conf_test include both tls and non-tls configs.
+ [ec1815793aab]
+
+ * MANIFEST, logsrvd/Makefile.in,
+ logsrvd/regress/logsrvd_conf/cacert.pem,
+ logsrvd/regress/logsrvd_conf/logsrvd_cert.pem,
+ logsrvd/regress/logsrvd_conf/logsrvd_conf_test.c,
+ logsrvd/regress/logsrvd_conf/logsrvd_dhparams.pem,
+ logsrvd/regress/logsrvd_conf/logsrvd_key.pem,
+ logsrvd/regress/logsrvd_conf/sudo_logsrvd.conf.1.in,
+ logsrvd/regress/logsrvd_conf/sudo_logsrvd.conf.2.in:
+ Add a simple regression test for logsrvd.conf parser. Unlike the
+ parser fuzzer, this includes sample certs and keys. This test would
+ have detected the BIO_new_file() bug in set_dhparams().
+ [7ddabb9d022f]
+
+ * logsrvd/logsrvd_conf.c:
+ Fix inverted logic when setting server_log. A value that starts with
+ a '/' should be treated as a path.
+ [8941fd924fbf]
+
+ * plugins/audit_json/Makefile.in, plugins/sample_approval/Makefile.in:
+ Use abs_top_builddir instead of `pwd`/$(top_builddir).
+ [0f4e20a7aeed]
+
+2022-06-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/regress/parse_gids/parse_gids_test.c:
+ Plug a memory leak.
+ [8a9eb498ed55]
+
+ * plugins/sudoers/parse_ldif.c:
+ Fix bug in last commit, need to reinitialize role to NULL.
+ [1e454b967993]
+
+ * plugins/sudoers/parse_ldif.c:
+ Simplify the check for when we can reuse the previous user and host
+ specs. This makes the code easier to read and quiets a cppcheck
+ false positive.
+ [037c4943f1ac]
+
+ * docs/Makefile.in:
+ Install the plugin man pages in section 5 (or 4 for System V). The
+ manual had the correct section in the text but was installed in the
+ wrong directory.
+ [5df7d3f9a010]
+
+ * plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/ro.mo, plugins/sudoers/po/ro.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po, po/de.mo,
+ po/de.po, po/eo.mo, po/eo.po, po/fr.mo, po/fr.po, po/hr.mo,
+ po/hr.po, po/ko.mo, po/ko.po, po/pl.mo, po/pl.po, po/ro.mo,
+ po/ro.po, po/uk.mo, po/uk.po:
+ Updated translations from translationproject.org
+ [9ac84e5c9250]
+
+ * NEWS:
+ Sudo now supports intercepting system(3).
+ [a46db96a3b03]
+
+2022-05-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/log_client.c:
+ Only display "unable to connect to log server" warning once.
+ Previously, in intercept mode, if the log server is unreachable the
+ message would be printed for each sub-command.
+ [df4c53518bb7]
+
+ * src/exec.c, src/exec_monitor.c, src/exec_nopty.c, src/sudo_exec.h:
+ When using ptrace(2), push the point where we suspend into
+ exec_cmnd(). This should reduce the amount of time the child has to
+ wait for the parent to use PTRACE_SEIZE to seize control and then
+ PTRACE_CONT to continue the child.
+ [f9caab4bf18b]
+
+ * config.h.in, configure, configure.ac, src/sudo_intercept.c:
+ Add configure check for vfork(2) and fall back to fork(2) if
+ missing.
+ [ddfaba8d2a09]
+
+ * docs/sudo.conf.man.in, docs/sudo.conf.mdoc.in, docs/sudoers.man.in,
+ docs/sudoers.mdoc.in, src/intercept.exp.in, src/sudo_intercept.c:
+ Add support for intercepting the system(3) function. This also means
+ we can log system(3) with log_subcmds.
+ [aca241d96c0b]
+
+ * include/compat/endian.h:
+ Newer compilers define __BYTE_ORDER__ and
+ __ORDER_{BIG,LITTLE}_ENDIAN__ Also add riscv the little endian list.
+ [55731e5517fc]
+
+2022-05-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ On AIX, fmemopen(3) has a bug where feof() returns false at EOF. See
+ https://www.ibm.com/support/pages/apar/IJ11845
+ [a703278bceed]
+
+2022-05-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/defaults.c:
+ Fix potential signed integer overflow on 32-bit CPUs. Converting
+ fractional minutes to nanoseconds could overflow a 32-bit integer,
+ use long long instead.
+ [b1d2afc0cc4d]
+
+ * plugins/sudoers/Makefile.in:
+ Fix path to example sudoers file, it is now in the build dir.
+ [899850a04adf]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ init_options: initialize apparmor_profile to NULL
+ [ad0de9e0474f]
+
+ * NEWS:
+ Update with latest 1.9.11 changes.
+ [12650d2b6184]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ Fix typo
+ [ce83f628330c]
+
+ * docs/CONTRIBUTORS.md:
+ Update contributors.
+ [5b69f27ea398]
+
+ * logsrvd/tls_init.c:
+ Fix uninitialized use of ca_store when building with wolfSSL.
+ [e7cc6d8d9f7e]
+
+ * docker/debian/testing/Dockerfile, docker/ubuntu/devel/Dockerfile,
+ docker/ubuntu/latest/Dockerfile, docker/ubuntu/rolling/Dockerfile:
+ Newer Debian/Ubuntu uses libsepol-dev not libsepol1-dev.
+ [b2c1326bfb0d]
+
+ * configure, configure.ac, plugins/sudoers/def_data.h,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/toke.c, src/Makefile.in:
+ Regenerate files after merging AppArmor integration.
+ [d24fcec2cb87]
+
+ * Merge pull request #148 from kernelmethod/apparmor_support
+
+ Add AppArmor support to sudo
+ [fcbfb2410afd]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ src/parse_args.c, src/sudo.c, src/sudo.h:
+ Merge branch 'main' into apparmor_support
+ [7832ecc5eb7f]
+
+2022-05-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sudo_intercept.c:
+ Pass envp, not environ, to real execve() from exec_wrapper() if
+ possible. The replacement execve() function was passing the global
+ environ to exec_wrapper() instead of the envp parameter. This caused
+ the command to be run with the wrong environment on AIX systems, and
+ possibly others, when intercept or log_subcmds was enabled. Bug
+ #1030.
+ [dc0187c68c1b]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ Update .pot files for 1.9.11
+ [b4c8ec57842f]
+
+ * src/exec_ptrace.c:
+ Consolidate some translatable strings.
+ [05dae7c3c8da]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd_journal.c,
+ logsrvd/logsrvd_relay.c, logsrvd/sendlog.c,
+ plugins/sudoers/log_client.c, src/exec_intercept.c:
+ Standardize protobuf "unable to unpack" warning messages.
+ [6f4e026c7a02]
+
+ * docs/sudo_plugin.man.in, docs/sudo_plugin.mdoc.in,
+ include/sudo_plugin.h, plugins/python/regress/testdata/check_multipl
+ e_approval_plugin_and_arguments.stdout, src/exec.c:
+ Bump plugin minor version and document new intercept-related
+ settings. There should have been a minor version bump for sudo 1.9.8
+ when intercept was originally implemented.
+ [2b7591704df4]
+
+2022-05-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Reset intercept_allow_setid if intercept_type changes from trace to
+ dso. But only reset intercept_allow_setid if the user didn't
+ explicitly set it.
+ [e398111d824e]
+
+2022-05-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * etc/sudo-logsrvd.pp, etc/sudo-python.pp, etc/sudo.pp:
+ CentOS Stream only uses a major version number, no minor version.
+ This prevents the packages from being created as foo.el.arch.rpm
+ since we were assuming that the version number was two digits.
+ [a3caed91ea8c]
+
+ * src/exec_ptrace.c, src/exec_ptrace.h:
+ Add support for running o32 and n32 binaries on mips64.
+ [887ab363f2a4]
+
+ * src/exec_ptrace.c, src/exec_ptrace.h, src/sudo_exec.h:
+ Enable ptrace support for MIPS but only for log_subcmds. It is not
+ possible to change the syscall return value on MIPS so we cannot
+ support full intercept mode. Another complication on MIPS is that if
+ a system call is invoked via syscall(__NR_###), v0 holds
+ __NR_O32_Linux and the real syscall is in the first arg (a0) and
+ other args are shifted by one.
+ [0345a4137047]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/policy.c, plugins/sudoers/sudoers.h,
+ src/exec_ptrace.c, src/parse_args.c, src/sudo.c, src/sudo.h,
+ src/sudo_exec.h:
+ Add intercept_type sudoers option to set intercept/log_subcmds
+ mechanism.
+ [b97e461f7da1]
+
+2022-05-23 kernelmethod <wss2ec@virginia.edu>
+
+ * MANIFEST, include/sudo_debug.h, src/Makefile.in, src/apparmor.c,
+ src/parse_args.c, src/sudo.c, src/sudo.h:
+ Add an apparmor_profile sudo setting
+
+ Define a new sudo setting, `apparmor_profile`, that can be used to
+ pass in an AppArmor profile that should be used to confine commands.
+ If apparmor_profile is specified, sudo will execute the command
+ using the new `apparmor_execve` function, which confines the command
+ under the provided profile before exec'ing it.
+ [a54897efe031]
+
+ * plugins/sudoers/check.c, plugins/sudoers/cvtsudoers_csv.c,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/cvtsudoers_merge.c, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/fmtsudoers.c, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.dict,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.dict,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/toke.l:
+ Add an APPARMOR_PROFILE user spec option to sudoers
+
+ sudoers now supports an APPARMOR_PROFILE option, which can be
+ specified as e.g.
+
+ alice ALL=(ALL:ALL) APPARMOR_PROFILE=foo ALL
+
+ The line above says "user alice can run any command as any
+ user/group, under confinement by the AppArmor profile 'foo'."
+ Profiles can be specified in any way that complies with the rules of
+ aa_change_profile(2). For instance, the sudoers configuration
+
+ alice ALL=(ALL:ALL) APPARMOR_PROFILE=unconfined ALL
+
+ allows alice to run any command unconfined (i.e., without an
+ AppArmor profile), while
+
+ alice ALL=(ALL:ALL) APPARMOR_PROFILE=foo//&bar ALL
+
+ tells sudoers that alice can run any command under the stacked
+ AppArmor profiles 'foo' and 'bar'.
+
+ The intention of this option is to give sysadmins on Linux distros
+ supporting AppArmor better options for fine-grained access control.
+ Among other things, this option can enforce mandatory access control
+ (MAC) over the operations that a privileged user is able to perform
+ to ensure that they cannot privesc past the boundaries of a
+ specified profile. It can also be used to limit which users are able
+ to get unconfined system access, by enforcing a default AppArmor
+ profile on all users and then specifying
+ 'APPARMOR_PROFILE=unconfined' for a privileged subset of users.
+ [2afe8c910959]
+
+ * config.h.in, configure.ac, scripts/mkdep.pl, scripts/mkpkg:
+ Add a --with-apparmor build flag
+
+ Add a new build flag, --with-apparmor, that builds sudo with
+ AppArmor support. Modify the build script for Debian and Ubuntu to
+ enable this flag by default.
+ [596b4e6dce4d]
+
+ * INSTALL.md, docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ Add documentation for AppArmor support
+
+ - Document the AppArmor userspec option in the sudoers man pages.
+ - Add information about the --with-apparmor build configuration option
+ to INSTALL.md.
+ [524dde965b94]
+
+2022-05-22 kernelmethod <wss2ec@virginia.edu>
+
+ * docker/debian/latest/Dockerfile, docker/debian/testing/Dockerfile,
+ docker/ubuntu/devel/Dockerfile, docker/ubuntu/latest/Dockerfile,
+ docker/ubuntu/rolling/Dockerfile:
+ Add libapparmor-dev to the Debian and Ubuntu Dockerfiles
+
+ Install libapparmor-dev on Debian- and Ubuntu-based Docker images so
+ that they can build sudo with AppArmor support.
+ [8491c8b6d240]
+
+2022-05-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_nopty.c, src/exec_pty.c:
+ Pass the WUNTRACED flag to waitpid() even if __WALL is present.
+ Otherwise, we won't get the wait status of a suspended command that
+ is not being traced.
+ [7c2b46ec73be]
+
+ * configure, configure.ac, lib/iolog/Makefile.in,
+ lib/logsrv/Makefile.in, logsrvd/Makefile.in,
+ plugins/sudoers/Makefile.in:
+ Use explicit library dependencies instead of implicit. We now
+ include all the dependent libraries when linking. Fixes a linking
+ problem on CentOS Stream 9.
+ [6f06cdbb1552]
+
+ * plugins/sudoers/logging.c:
+ mail_parse_errors: allocate the correct amount of space for mail
+ body. Use strlen(), not sizeof(), on "problem parsing sudoers" since
+ it is a tranlated string and not a constant. This was caught by the
+ existing overflow checks.
+ [5aa53136cd9d]
+
+2022-05-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, src/Makefile.in, src/exec_nopty.c, src/exec_pty.c,
+ src/regress/intercept/test_ptrace.c, src/sudo_exec.h,
+ src/suspend_nopty.c:
+ Move code to suspend sudo when no pty is in use to separate file.
+ Use this in test_ptrace.c to be able to suspend just like sudo does.
+ [ddef421918b7]
+
+2022-05-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_nopty.c, src/exec_ptrace.c, src/exec_pty.c,
+ src/regress/intercept/test_ptrace.c, src/sudo_exec.h:
+ Fix suspending a sudo-run shell in ptrace intercept mode with no
+ pty. When ptracing a process, we receive the signal-delivery-stop
+ signal before the group-stop signal. If sudo is running the command
+ in the same terminal, we need to wait until the stop signal is
+ actually delivered to the command before we can suspend sudo itself.
+ If we suspend sudo before receiving the group-stop, the command will
+ be restarted with PTRACE_LISTEN too late and will miss the SIGCONT
+ from sudo.
+ [bf9a482ecddd]
+
+ * docs/TROUBLESHOOTING.md, docs/sudo_logsrvd.man.in,
+ docs/sudo_logsrvd.mdoc.in:
+ OpenSSL 3.x requires the key usage extension be present in CA and
+ certs. Certificates generated with a CA that doesn't set the key
+ usage extension will fail to validate if "tls_verify" is enabled.
+ [3ae4ef1ecf57]
+
+ * logsrvd/tls_init.c:
+ Include the cert or ca file in error messages where applicable.
+ [3e0558886a3d]
+
+ * logsrvd/tls_init.c:
+ Add missing include of string.h for strerror(3).
+ [253a5634d441]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd_relay.c, logsrvd/sendlog.c,
+ logsrvd/tls_client.c, logsrvd/tls_init.c,
+ plugins/sudoers/log_client.c:
+ If ERR_reason_error_string() returns NULL, fall back on
+ strerror(errno). That way we get reasonable error messages for
+ missing files, etc.
+ [d2423ef0e284]
+
+ * logsrvd/tls_init.c:
+ set_dhparams: pass BIO_new_file() "r" for the file mode, not
+ O_RDONLY. Unlike BIO_new_fp(), BIO_new_file() takes an fopen-style
+ mode string.
+ [7a67aec88cb4]
+
+ * src/exec_ptrace.c:
+ The set_sc_arg3, get_sc_arg3 and set_sc_arg4 functions are not used.
+ Use ifdef notyet to disable for now since they may be used in the
+ future.
+ [99d2f2a42da5]
+
+2022-05-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.h, src/sudo_exec.h:
+ Use __x86_64__ preprocessor symbol, not __amd64__ Also clarify a
+ comment about MIPS ptrace.
+ [b02ad513eb64]
+
+ * src/exec_ptrace.h, src/sudo_exec.h:
+ ptrace support has been tested on Debian/s390x. It should also work
+ on s390 but this has not been tested. I have not added a compat mode
+ to trace 31-bit binaries on s390x due to the lack of a test system.
+ [3176433e7456]
+
+ * src/exec_ptrace.h:
+ Define sudo_pt_regs instead of user_pt_regs and include the struct
+ keyword. On s390, the struct is typedef'd without a name.
+ [b2b74f378eef]
+
+ * src/exec_ptrace.h, src/sudo_exec.h:
+ ptrace support has been tested on Debian/riscv64.
+ [e1011074d984]
+
+2022-05-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.in:
+ Add maxseq setting to log_output example. This should make it more
+ obvious that you need to adjust maxseq unless you have (virtually)
+ unlimited disk space.
+ [5203240a248b]
+
+ * scripts/mkpkg:
+ Fix dependency check for libssl on Debian/Ubuntu with OpenSSL 3.
+ Also add check for python 3.10 and 3.11 and remove versions < 3.4.
+ Fixes building on Ubuntu 22.04.
+ [c9114582911c]
+
+2022-05-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.h:
+ Tracing 32-bit arm binaries from a 64-bit sudo works.
+ [c1e1602874ed]
+
+ * src/exec_ptrace.c:
+ ptrace_write_string: the terminating NUL fix was reverted by
+ mistake.
+ [587dd11b2783]
+
+ * src/exec_ptrace.h, src/sudo_exec.h:
+ ptrace-based intercept has now been tested on 32-bit arm
+ [493b17a89e63]
+
+2022-05-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.h:
+ Don't use PTRACE_SET_SYSCALL for 32-bit arm binaries running on
+ aarch64. Use PTRACE_SETREGSET with NT_ARM_SYSTEM_CALL instead just
+ like we would for a 64-bit binary. Newer Linux headers don't define
+ PTRACE_SET_SYSCALL for aarch64.
+ [5930846e9c9e]
+
+ * src/regress/intercept/test_ptrace.c:
+ Replace verbose flag with debug flag. This is more accurate since it
+ actually uses the debug subsystem.
+ [dda8b8af8bd2]
+
+ * src/exec_ptrace.h:
+ Initial cut at MIPS support, untested. Mips is a bit different in
+ that most Linux distros appear to use the n32 ABI on 64-bit CPUs. We
+ don't currently support tracing a 64-bit binary from a 32-bit sudo.
+ We could suport tracing o32 ABI binaries in compat mode, though.
+ [05e5e246463a]
+
+2022-05-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/regress/intercept/test_ptrace.c:
+ Add have_seccomp_action("trap") call to check for
+ SECCOMP_MODE_FILTER.
+ [250c6b72c4f4]
+
+ * src/exec_ptrace.c, src/exec_ptrace.h:
+ Add arm-specific code to set the system call number. Fixes rejection
+ of commands due to policy on arm when in intercept mode.
+ [74c5bd26713b]
+
+ * scripts/mkpkg:
+ Fix OS major version detection on CentOS Stream
+ [cd4d5aaf59a7]
+
+ * src/exec_ptrace.c:
+ Repair ptrace_write_vec() for compat binaries.
+ [77ee302b0631]
+
+ * src/regress/intercept/test_ptrace.c:
+ Fix a crash when not run in verbose mode.
+ [adf481623228]
+
+ * src/exec_ptrace.c:
+ ptrace_intercept_execve: read back the updated syscall args in test
+ mode. This makes it easier to detect problems with the syscall
+ rewrite code when testing with test_ptrace.
+ [4eb9e09d90d9]
+
+2022-05-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.c, src/exec_ptrace.h, src/sudo_exec.h:
+ Enable ptrace intercept on powerpc. Tested on ppc64 and ppc64le.
+ [fbd12baa1a02]
+
+ * src/exec_ptrace.c:
+ Fix tracing compat binaries on big endian systems. We need to swap
+ the order of the two 32-bit addresses for big-endian.
+ [375004a3ef09]
+
+ * src/exec_ptrace.c:
+ Move code to write a string vector to ptrace_write_vec().
+ [8401e0397f11]
+
+ * src/exec_ptrace.c:
+ Fix compilation error on systems with no compat arch. Currently only
+ affects i386.
+ [b95c707298c5]
+
+ * MANIFEST, src/Makefile.in, src/exec_intercept.h, src/exec_ptrace.c,
+ src/regress/intercept/test_ptrace.c, src/sudo_exec.h:
+ Add test_ptrace program to test ptrace-based intercept support.
+ [5f7162bcdbfd]
+
+ * src/exec_ptrace.c:
+ Use unsigned long for addresses so we don't have to worry about sign
+ extension.
+ [7a0d4ea2fa70]
+
+2022-05-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.c:
+ ptrace_write_string: make sure we always write the terminating NUL.
+ We can't check *str for NUL since it may not have been written yet.
+ [9d95217981ac]
+
+ * src/exec_ptrace.c:
+ Fix compilation error when SECCOMP_AUDIT_ARCH_COMPAT is not defined.
+ [3162054bac24]
+
+2022-05-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.c, src/exec_ptrace.h:
+ It is now safe to make WORDALIGN use compat (not native) aligment.
+ We allocate space for an extra pointer between argv and the string
+ table for compat binaries so there is no need to align address to
+ sizeof(long).
+ [898626f1cdf6]
+
+ * src/exec_ptrace.c, src/exec_ptrace.h:
+ Use the entire word in ptrace_get_vec_len() and ptrace_read_vec().
+ For compat binaries, use the upper 32-bits as the next word instead
+ of calling ptrace(2) to get it. This reduces the number of ptrace(2)
+ calls when reading argv and envp for compat binaries.
+ [cf5d1ae47dbe]
+
+2022-05-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.c:
+ We don't need to align strings in the string table. We align the
+ start of the string table to a word boundary to help prevent overlap
+ when writing the pointers. However, the actual strings themselves
+ don't need to be aligned.
+ [219a1a07fc2e]
+
+2022-05-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.c:
+ Avoid potentially overwriting string table when writing argv. In
+ compat mode, if argc is odd, writing the last pointer of argv will
+ overlap with the address of argv[0], so leave an extra word in
+ between. Also remove incorrect comments about PTRACE_PEEKDATA
+ unaligned access.
+ [13f7e63a31bd]
+
+ * src/exec_ptrace.c, src/exec_ptrace.h:
+ Use native word size for padding and when reading/writing strings.
+ If we try to use the compat word size we can end up in a situation
+ where a subsequent PTRACE_POKEDATA overwrites part of what we've
+ already written since it always writes in sizeof(long) units.
+ [e0d7fdc3f8e2]
+
+2022-05-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_ptrace.c:
+ ptrace_intercept_execve: rewrite path to exec if changed by the
+ policy
+ [089f0e32cf2a]
+
+ * src/exec_ptrace.c:
+ ptrace_intercept_execve: plug memory leak of get_execve_info()
+ buffer
+ [5ce2cf252c80]
+
+ * MANIFEST, src/Makefile.in, src/exec_intercept.h, src/exec_ptrace.c,
+ src/exec_ptrace.h:
+ Move register definitions to exec_ptrace.h
+ [59cc9bec6925]
+
+ * src/exec_ptrace.c:
+ Add support for intercepting 32-bit binaries on 64-bit systems. We
+ need to define the ptrace register struct ourselves for the 32-bit
+ system since there is no good way to get it from the system headers.
+ Currently only implemented for x86_64 and aarch64.
+ [a0407bb1fee0]
+
+ * src/exec_ptrace.c:
+ Add setters and getters for ptrace(2) register access. This will be
+ used when running 32-bit binaries from a 64-bit sudo.
+ [f7da9453d9fa]
+
+ * src/exec_ptrace.c:
+ exec_ptrace_handled: don't return early if ptrace_intercept_execve()
+ fails. We need to continue the traced process even if there is a
+ fatal error. Otherwise, sudo will appear to hang as the running
+ process is left in PTRACE_EVENT stop.
+ [5b3bd75c4486]
+
+ * src/exec_ptrace.c:
+ Don't use PTRACE_GETREGS, it is too complicated when runing compat
+ binaries. Unlike PTRACE_GETREGSET, PTRACE_GETREGS requires that we
+ manually map registers from 64-bit to 32-bit layouts when running,
+ e.g. a 32-bit binary from a 64-bit sudo process.
+ [bb3476230373]
+
+2022-05-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.h, src/exec_nopty.c, src/exec_pty.c,
+ src/parse_args.c, src/sudo.c, src/sudo.h, src/sudo_exec.h:
+ Initialize intercept_allow_setid to true if we use ptrace(2) and
+ seccomp(2).
+ [57e58c0ada44]
+
+2022-05-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_nopty.c, src/exec_ptrace.c, src/exec_pty.c,
+ src/sudo_exec.h:
+ If the process is already being traced, just resume it and clear
+ flags. This makes it possible to run sudo in ptrace intercept mode
+ from within a shell (or other process) that is already being traced
+ by sudo.
+ [db4d7cd5f673]
+
+ * src/exec_ptrace.c:
+ exec_ptrace_handled: fix delivery of non-stop signals. We need to
+ deliver signals to the tracee as long as it is not a group stop.
+ Fixes a hang while tracing another sudo process.
+ [4ede8b4cfbd9]
+
+ * src/exec_nopty.c:
+ Make SIGCHLD handler more consistent with the pty version. No real
+ change other than a few debug statements.
+ [bd52284b1e2a]
+
+ * plugins/sudoers/parse.c:
+ sudoers_lookup_check: preserve intercepted flag when reinitializing
+ cmnd_info Otherwise we may not reject an attempt to run a set-user-
+ ID command.
+ [43d72d1537b2]
+
+ * src/exec_nopty.c, src/exec_pty.c:
+ Kill the command if intercept_setup() or ptrace_seize() fail.
+ [1037f81b327b]
+
+2022-05-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/match_command.c:
+ Move intercept setid check out of do_stat() and into its own
+ function. For command_matches_all() we should only perform the setid
+ check if the file exists and intercept is enabled. Otherwise, we can
+ end up returning an error if the fully-qualified command does not
+ exist. Fixes a regression introduced in sudo 1.9.0 with the support
+ for digests in conjunction with "sudo ALL".
+ [1b5f9ed2160a]
+
+ * src/exec_ptrace.c:
+ Add support for intercepting x32 binaries on Linux x64_64.
+ [c5fc89f38c43]
+
+2022-04-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.11
+ [d3e832f94348]
+
+ * plugins/sudoers/auth/kerb5.c, src/exec_ptrace.c:
+ Fix typos
+ [8ef3e84fc62e]
+
+ * MANIFEST, docs/CONTRIBUTORS.md, po/ka.mo, po/ka.po:
+ New Georgian translation from translationproject.org
+ [f6b9c7d2192c]
+
+ * src/exec_ptrace.c:
+ Short-circuit the policy check if the command doesn't exist.
+ Otherwise, both sudo and the shell will report the error.
+ [f16f1b6705d9]
+
+ * src/exec_ptrace.c:
+ Add support for replacing argv in ptrace intecept mode. The new argv
+ is written below the tracee's stack and the system call argument is
+ replaced with the new argv address.
+ [3974c784be8b]
+
+ * src/exec_ptrace.c:
+ Check architecture in the seccomp filter. Currently only supports
+ the native architecture.
+ [13f88e436ae0]
+
+ * src/exec_common.c, src/exec_monitor.c, src/exec_nopty.c,
+ src/exec_ptrace.c:
+ Suspend the child process and wait for SIGUSR when using ptrace.
+ This fixes a race condition in ptrace-based intercept mode when
+ running the command in a pty. It was possible for the monitor to
+ receive SIGCHLD when the command sent itself SIGSTOP before the main
+ sudo process did.
+ [cf1f0bea9931]
+
+ * plugins/sudoers/parse.c, src/exec.c, src/selinux.c, src/sudo.h:
+ Enable intercept and log_subcmds for SELinux using ptrace and
+ seccomp.
+ [5d7a3df4457e]
+
+ * src/exec_intercept.c, src/exec_intercept.h, src/exec_ptrace.c,
+ src/sudo.c, src/sudo.h:
+ For ptrace intercept mode, do not do a policy check for the initial
+ command. We can skip the policy check for the execve(2) of the
+ initial command since it has already been check. Otherwise, we would
+ log the command twice. When using fexecve(2) due to a digest check,
+ there should be no need to skip the initial command since it will be
+ executed via execveat(2) not execve(2). However, on older kernels
+ without execveat(2), glibc will emulate fexecve(2) using /proc which
+ will result in the extra log entry.
+ [e411d6bc3855]
+
+ * docs/sudo.conf.man.in, docs/sudo.conf.mdoc.in, docs/sudoers.man.in,
+ docs/sudoers.mdoc.in:
+ Update intercept documentation.
+ [f44f1cb2a5d2]
+
+ * src/exec_intercept.c, src/exec_ptrace.c:
+ In ptrace(2) intercept mode, add execveat to the seccomp(2) filter.
+ This allows us to avoid logging the initial command twice regardless
+ of whether the kernel supports execveat(2) or not.
+ [d39bd5adac13]
+
+ * src/exec_ptrace.c:
+ Use PTRACE_GETREGS/PTRACE_SETREGS on platforms that support it. This
+ has a better chance of working on things like user-mode Linux.
+ [c53475bd4020]
+
+ * MANIFEST, src/Makefile.in, src/exec_intercept.c,
+ src/exec_intercept.h, src/exec_nopty.c, src/exec_ptrace.c,
+ src/exec_pty.c, src/sudo_exec.h:
+ Check the policy for ptrace-based intercept mode.
+ [6eadd667ca6d]
+
+ * src/exec_ptrace.c:
+ Add support for getting the execve(2) arguments via ptrace(2). This
+ will be used to perform a policy check in intercept mode.
+ [84b23ae53e2f]
+
+ * MANIFEST, src/Makefile.in, src/exec.c, src/exec_common.c,
+ src/exec_intercept.c, src/exec_nopty.c, src/exec_ptrace.c,
+ src/exec_pty.c, src/sudo.h, src/sudo_exec.h:
+ Add scaffolding for ptrace-based intercept mode.
+ [34a6269ac4eb]
+
+ * include/sudo_compat.h, src/exec_monitor.c, src/exec_nopty.c,
+ src/exec_pty.c:
+ Stop using the WCONTINUED flag with waitpid(2). We don't use it for
+ anything other than a debug message and it will cause problems when
+ intercept mode starts using ptrace(2).
+ [1f55993d68eb]
+
+ * src/exec_nopty.c, src/exec_pty.c:
+ Handle multiple child processes in the SIGCHLD handler. This is
+ required by the uncoming ptrace intercept code.
+ [6dd72fb8f53f]
+
+2022-04-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/iolog_writer.c, logsrvd/logsrvd_journal.c,
+ plugins/sudoers/log_client.c:
+ sudo_logsrvd: update elapsed time for winsize and suspend in journal
+ mode Fixes a bug in store-first relay mode where the commit point
+ messages sent by the server were incorrect.
+ [5607e8c7b559]
+
+2022-04-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/visudo.man.in, docs/visudo.mdoc.in:
+ Fix typo; GitHub issue #144
+ [fb1a539569b4]
+
+2022-04-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/TROUBLESHOOTING.md:
+ Expand section about expired accounts to include /etc/shadow info.
+ GitHub issue #143
+ [78368dadddfb]
+
+ * src/exec_monitor.c:
+ Add struct command details * to struct monitor_closure. This will be
+ used in the future by the ptrace intercept code.
+ [0603acf1ff96]
+
+ * src/exec.c:
+ Translate "unable to set limit privileges" strings.
+ [a8426e224497]
+
+ * ABOUT-NLS, MANIFEST, docs/CONTRIBUTING.md:
+ Remove ABOUT-NLS file, it is no longer maintained as part of GNU
+ gettext. Expand the Translations section in CONTRIBUTING.md.
+ [b4f0269a8f13]
+
+ * src/exec.c, src/exec_intercept.c:
+ Don't require a pty for intercept or log_subcmmds. The code to take
+ back control of the tty before a policy check doesn't appear to be
+ needed. If the command is run in its own pty, sudo has control over
+ the user's tty. If the command is run in the user's tty, sudo should
+ be in the foreground process group.
+ [bddcc0d9fee6]
+
+2022-04-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac:
+ Define _TIME_BITS=64 on systems that define __TIMESIZE, like GNU
+ libc. This should be replaced by a specialized autoconf macro when
+ one becomes available.
+ [f63b7f9ea5c2]
+
+2022-04-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/regress/testdata/check_example_group_plugin_is_able_t
+ o_debug.log, plugins/python/regress/testhelpers.c:
+ clean_output: prune lines that consisting of '^' characters and
+ whitespace. Starting with Python 3.11, backtraces may contain a line
+ with '^' characters to bring attention to the important part of the
+ line. Also replace "REJECT" with "0" in backtrace output for Python
+ 3.11.
+ [f6a5d1c05b2b]
+
+2022-04-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Fix check for EVP_MD_CTX_new() when -pthread is in Libs.private.
+ [4f3fd0d1fd34]
+
+2022-04-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac, lib/eventlog/Makefile.in,
+ lib/fuzzstub/Makefile.in, lib/iolog/Makefile.in,
+ lib/logsrv/Makefile.in, lib/protobuf-c/Makefile.in,
+ lib/util/Makefile.in, lib/zlib/Makefile.in, logsrvd/Makefile.in,
+ plugins/audit_json/Makefile.in, plugins/group_file/Makefile.in,
+ plugins/python/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sample_approval/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/Makefile.in:
+ Rename SSP_(C|LD)FLAGS -> HARDENING_(C|LD)FLAGS
+ [92aa57606481]
+
+ * INSTALL.md:
+ Mention other hardening compilation and linker options.
+ [7da9cf428e39]
+
+2022-03-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Fix check for EVP_MD_CTX_new using static libcrypto with
+ dependencies.
+ [c02d6b6e474c]
+
+ * configure, m4/libtool.m4, m4/ltoptions.m4, m4/ltsugar.m4,
+ m4/ltversion.m4, m4/lt~obsolete.m4, scripts/ltmain.sh:
+ Update to libtool 2.4.7.
+ [b8824f6b792c]
+
+2022-03-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ --enable-openssl: don't add non-existent directories to
+ PKG_CONFIG_LIBDIR
+ [daa9cab172da]
+
+2022-03-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/mkpkg:
+ Fix a typo in the AIX section.
+ [4d122a222632]
+
+2022-03-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/zlib/crc32.c, lib/zlib/crc32.h, lib/zlib/deflate.c,
+ lib/zlib/deflate.h, lib/zlib/gzguts.h, lib/zlib/gzlib.c,
+ lib/zlib/gzread.c, lib/zlib/gzwrite.c, lib/zlib/infback.c,
+ lib/zlib/inffast.c, lib/zlib/inflate.c, lib/zlib/inflate.h,
+ lib/zlib/inftrees.c, lib/zlib/trees.c, lib/zlib/zlib.exp,
+ lib/zlib/zlib.h, lib/zlib/zutil.c, lib/zlib/zutil.h:
+ Update embedded copy of zlib to version 1.2.12. Fixes CVE-2018-25032
+ [3e2517079d86]
+
+2022-03-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/kerb5.c:
+ Minor style nit.
+ [9bdde2c81a3d]
+
+ * Merge pull request #138 from dfskoll/main
+
+ If we're using Kerberos, don't overwrite a custom prompt
+ [266b04c9ee0a]
+
+2022-03-16 Dianne Skoll <dianne@skoll.ca>
+
+ * plugins/sudoers/auth/kerb5.c:
+ If we're using Kerberos, don't overwrite a custom prompt if one was
+ given with -p
+
+ Thanks to @thend20 for testing this patch.
+ [e62136f88c3e]
+
+2022-03-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/conversation.c:
+ Write the \r\n pair to ttyfp if possible, falling back on fp. This
+ is consistent with the vfprintf() call and fixes a problem
+ introduced by the last commit where the newline could be written
+ before the message instead of after.
+ [3aaebbec4ee5]
+
+ * include/sudo_util.h,
+ plugins/sudoers/regress/starttime/check_starttime.c:
+ Adjust starttime test when run under Debian faketime. Bug #1026
+ [b8ac7dec6e11]
+
+2022-03-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/conversation.c:
+ sudo_conversation_printf: convert trailing nl to cr + nl combo. This
+ fixes output when the terminal is in raw mode and is consistent with
+ how sudo_conversation() behaves.
+ [e377f2a71021]
+
+ * lib/eventlog/eventlog.c, src/exec_monitor.c, src/exec_nopty.c,
+ src/exec_pty.c, src/tgetpass.c:
+ Block SIGCHLD when forking the mailer. Otherwise, it may be picked
+ up by the signal handler instead of our waitpid(2) call. Don't warn
+ if waitpid() returns 0 in a SIGCHLD handler.
+ [e34a3f90de5b]
+
+ * plugins/sudoers/sudoers.c:
+ Do not warn, log or send mail for errors when reinitializing
+ defaults. If there is a problem, we would have already warned,
+ logged or mailed it. The one exception is the initial defaults,
+ which should never fail.
+ [0d273f4d307d]
+
+ * plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/parse.c, plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/sudoers.c:
+ If there are multiple parse errors, send them in a single mail
+ message.
+ [5de37ad1101f]
+
+ * lib/eventlog/Makefile.in, lib/iolog/Makefile.in,
+ lib/util/Makefile.in, logsrvd/Makefile.in,
+ plugins/python/Makefile.in, plugins/sudoers/Makefile.in,
+ src/Makefile.in:
+ Unset LANGUAGE when running tests, otherwise it may override LC_ALL.
+ Bug #1025.
+ [87573102f25b]
+
+2022-03-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/visudo.c:
+ Looser owner/permission checks for an uninstalled sudoers file. We
+ don't check the owner or permissions on a sudoers file that is
+ specified as an argument to visudo by default. However, the owner
+ and mode of files included via @includedir were still checked. This
+ commit makes the owner and permissions checks for filed included via
+ @includedir follow the same as for the original sudoers file.
+ [db78857306d4]
+
+ * lib/util/regress/getdelim/getdelim_test.c:
+ getdelim_test: increase longstr to check end pointer after realloc
+ This would have caught the recent bug in our getdelim replacement
+ when run under address-sanitizer or valgrind.
+ [6559a42a3205]
+
+ * plugins/sudoers/check_aliases.c:
+ Add missing va_start/va_end around call to sudoers_error_hook().
+ Coverity CID 250885
+ [49d026ba67b2]
+
+ * lib/util/getdelim.c:
+ Correctly update the end pointer when we expand the buffer. From
+ Robert Manner.
+ [99617ae8332d]
+
+2022-03-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/secure_path.c:
+ sudo_secure_path: pass the struct stat * argument directly to
+ stat(2) Set the pointer to a struct stat on the stack if st is NULL.
+ Avoids a needless memcpy() at the end.
+ [11636745ce29]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Fix off-by-one when storing line number in userspec. We store the
+ line number *after* parsing the newline so we need to subtract one.
+ [40d6521a966e]
+
+ * lib/eventlog/eventlog.c:
+ For alert messages, the command or runuser may not be set. This
+ fixes the logging of parse errors when JSON logging is enabled.
+ [cfde228ef422]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/locale.c, plugins/sudoers/logging.h,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c:
+ Pass file, line and column to sudoers defaults callbacks.
+ [04a26b1a224c]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/check_aliases.c,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/file.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.h, plugins/sudoers/gram.y,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/parse.h, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/sudoers/test18.toke.ok,
+ plugins/sudoers/regress/visudo/test2.err.ok,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/visudo.c:
+ Add a hook for sudoers parse errors (including defaults and
+ aliases). The hook can be used to log parser errors (sudoers module)
+ or keep track of which files have an error (visudo). Previously, we
+ only kept track of a single parse error.
+ [601915bb6265]
+
+2022-03-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/file.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/sudoers/test18.out.ok,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudo_nss.h,
+ plugins/sudoers/sudoers.c, plugins/sudoers/testsudoers.c:
+ Add a source to struct sudo_nss and use it if getdefs() fails. Also
+ remove useless "Problem with defaults entries" warning in
+ testsudoers.
+ [f9ba65e975a0]
+
+2022-03-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/regress/iolog_path/check_iolog_path.c,
+ lib/util/regress/getgrouplist/getgrouplist_test.c:
+ Plug a few test memory leaks now that they return from main().
+ [dc4db97a1d57]
+
+2022-03-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/eventlog/regress/logwrap/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c:
+ Remove extra newline in sudo_warnx() calls.
+ [3366401671fc]
+
+ * plugins/sudoers/check_aliases.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/file.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.h, plugins/sudoers/gram.y,
+ plugins/sudoers/sudoers.h, plugins/sudoers/visudo.c:
+ Preserve the column and error message when there is a syntax error.
+ This information is now included in the error mail sent to root.
+ [a224b006bfb3]
+
+ * plugins/python/python_plugin_common.c:
+ Deinit python subinterpreters in reverse order (last to first). This
+ appears to work around a crash on OpenBSD with Python 3.9.10.
+ [ad4d7b33da9b]
+
+2022-03-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_10 for changeset 3557db693da4
+ [edcb9bf4d4c3] <1.9>
+
+ * NEWS, config.h.in, configure, configure.ac, include/sudo_compat.h,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Merge sudo 1.9.10 from tip.
+ [3557db693da4] [SUDO_1_9_10] <1.9>
+
+ * lib/eventlog/Makefile.in, lib/iolog/Makefile.in,
+ lib/util/Makefile.in, logsrvd/Makefile.in,
+ plugins/python/Makefile.in, plugins/sudoers/Makefile.in,
+ src/Makefile.in:
+ For 'make check-verbose' run fuzzers with -verbose=1 This is the
+ default for libFuzzer but not for the stub fuzzer lib.
+ [7f2551a87c08]
+
+2022-03-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * INSTALL.md:
+ INSTALL.md: Mention "make check" and "make check-verbose"
+ [17a30e329ba7]
+
+ * scripts/generate_test_coverage.sh:
+ Repair generate_test_coverage.sh after move to scripts directory.
+ [ffef93da0436]
+
+ * Makefile.in, docs/Makefile.in, examples/Makefile.in,
+ include/Makefile.in, lib/eventlog/Makefile.in,
+ lib/fuzzstub/Makefile.in, lib/iolog/Makefile.in,
+ lib/logsrv/Makefile.in, lib/protobuf-c/Makefile.in,
+ lib/util/Makefile.in, lib/zlib/Makefile.in, logsrvd/Makefile.in,
+ plugins/audit_json/Makefile.in, plugins/group_file/Makefile.in,
+ plugins/python/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sample_approval/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/Makefile.in:
+ Add check-verbose Makefile target that runs tests in verbose mode.
+ [929d079dbfc7]
+
+ * lib/eventlog/regress/logwrap/check_wrap.c,
+ lib/iolog/regress/host_port/host_port_test.c,
+ lib/iolog/regress/iolog_filter/check_iolog_filter.c,
+ lib/iolog/regress/iolog_json/check_iolog_json.c,
+ lib/iolog/regress/iolog_mkpath/check_iolog_mkpath.c,
+ lib/iolog/regress/iolog_path/check_iolog_path.c,
+ lib/iolog/regress/iolog_timing/check_iolog_timing.c,
+ lib/util/regress/closefrom/closefrom_test.c,
+ lib/util/regress/fnmatch/fnm_test.c,
+ lib/util/regress/getdelim/getdelim_test.c,
+ lib/util/regress/getgrouplist/getgids.c,
+ lib/util/regress/getgrouplist/getgrouplist_test.c,
+ lib/util/regress/glob/globtest.c,
+ lib/util/regress/mktemp/mktemp_test.c,
+ lib/util/regress/parse_gids/parse_gids_test.c,
+ lib/util/regress/progname/progname_test.c,
+ lib/util/regress/strsig/strsig_test.c,
+ lib/util/regress/strsplit/strsplit_test.c,
+ lib/util/regress/strtofoo/strtobool_test.c,
+ lib/util/regress/strtofoo/strtoid_test.c,
+ lib/util/regress/strtofoo/strtomode_test.c,
+ lib/util/regress/strtofoo/strtonum_test.c,
+ lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_parseln/parseln_test.c,
+ lib/util/regress/tailq/hltq_test.c,
+ lib/util/regress/uuid/uuid_test.c:
+ Add -v option parsing to regress tests, currently a no-op. This will
+ be used by a "check-verbose" target in the future.
+ [9cdcc23e6a70]
+
+2022-03-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/regress/check_python_examples.c,
+ plugins/python/regress/testhelpers.h:
+ Less verbose output unless the -v option is used. Also display a
+ test summary at the end.
+ [b18a8f6526e9]
+
+ * src/regress/net_ifs/check_net_ifs.c,
+ src/regress/noexec/check_noexec.c,
+ src/regress/ttyname/check_ttyname.c:
+ verbose flag is boolean, not int
+ [8663ac48be27]
+
+ * configure.ac:
+ Update copyright year.
+ [461698b72a64]
+
+ * plugins/sudoers/Makefile.in, src/Makefile.in:
+ Regenerate dependencies.
+ [f007ec225986]
+
+ * MANIFEST, configure, configure.ac, lib/util/Makefile.in,
+ lib/util/regress/closefrom/closefrom_test.c:
+ Add sudo_closefrom() regression test.
+ [14f4439a8437]
+
+ * NEWS, config.h.in, configure, configure.ac, lib/util/closefrom.c:
+ Use close_range(2) in closefrom() emulation if available. On Linux,
+ prefer our own closefrom() emulation since the glibc version may
+ fail if /proc is not present and close_range() is not supported. On
+ FreeBSD, closefrom(3) will either call the closefrom or close_range
+ system call, depending on which is available.
+ [d84eff07783f]
+
+ * configure, configure.ac:
+ Repair --enable-pvs-studio on Linux.
+ [add3c7fff7f5]
+
+ * configure, configure.ac:
+ Mention apple radar 3710161 in the comment about broken macOS
+ poll(2).
+ [ffb6c8c070dc]
+
+2022-02-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/regress/net_ifs/check_net_ifs.c,
+ src/regress/noexec/check_noexec.c,
+ src/regress/ttyname/check_ttyname.c:
+ Only display test totals unless run in verbose mode.
+ [f543b41f226e]
+
+ * lib/util/regress/harness.in, plugins/sudoers/regress/harness.in:
+ Allow test harness to be run from any directory. Also add missing
+ copyright notice.
+ [5e60bc5beb52]
+
+ * lib/util/regress/harness.in:
+ Adapt test harness for lib/util and move to regress directory.
+ [f415d958bca7]
+
+ * .gitignore, .hgignore, MANIFEST, configure, configure.ac,
+ lib/util/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/sudoers/harness.in, plugins/sudoers/regress/harness.in:
+ Adapt test harness for lib/util and move to regress directory.
+ [5f488712f797]
+
+ * lib/fuzzstub/fuzzstub.c:
+ Make fuzzer stub main() quiet by default. LLVM LibFuzzer displays
+ the input and running time by default but we don't care about that
+ for the stub fuzzer library.
+ [728005c2de78]
+
+ * .gitignore, .hgignore, MANIFEST, configure, configure.ac,
+ plugins/sudoers/Makefile.in, plugins/sudoers/harness.in:
+ Move the cvtsudoers/sudoers/testsudoers/visudo tests into a script.
+ It is easier to maintain these tests in script form. The output now
+ more closely matches that of the other tests. The harness script can
+ be invoked directly and supports running specific tests.
+ [fbad6e93201e]
+
+2022-02-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po:
+ Updated translations from translationproject.org
+ [b2622a56fcbc]
+
+2022-02-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/regress/fuzz/fuzz_logsrvd_conf.c:
+ sudo_regex_compile_v1 stub: set errstr on error
+ [2da61535e60d]
+
+ * logsrvd/Makefile.in, logsrvd/regress/fuzz/fuzz_logsrvd_conf.c:
+ fuzz_logsrvd_conf: add stub version of sudo_regex_compile_v1(). We
+ want to fuzz our parser, not the libc regular expression code.
+ [2662a181acc8]
+
+ * plugins/sudoers/regress/testsudoers/test18.out.ok,
+ plugins/sudoers/regress/testsudoers/test18.sh:
+ testsudoers/test18: don't rely on /usr/bin/w being present Fixes a
+ test failure on Alpine Linux.
+ [5b3915cef32b]
+
+2022-02-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Add configure check for gzclearerr() when using system zlib.
+ [388dd60cd577]
+
+ * configure, configure.ac:
+ Fix PVS-Studio platform check for macOS.
+ [cc46ae5d60a3]
+
+ * plugins/sudoers/ldap.c:
+ sudo_ldap_parse_options: fix memory leak of sudoRole cn string.
+ Coverity CID 249976
+ [bcf86c362e05]
+
+ * src/sudo_intercept_common.c:
+ command_allowed: plug memory leak on strdup() failure. Coverity CID
+ 249972
+ [f15a58ed68d6]
+
+2022-02-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/check.c:
+ display_lecture: just return if callback is NULL
+ [3e7352fbc28b]
+
+ * lib/eventlog/eventlog.c:
+ For alert messages it is possible for evlog to be NULL. Coverity CID
+ 238641
+ [3e89523699fd]
+
+ * logsrvd/logsrv_util.c:
+ iolog_seekto: initialize struct timing_closure before using.
+ Coverity CID 249977
+ [ea53680a2367]
+
+ * logsrvd/iolog_writer.c:
+ iolog_rewrite: initialize struct timing_closure before using.
+ Coverity CID 249971
+ [d214237f3ce8]
+
+ * scripts/mkpkg:
+ Allow ARCH_FLAGS to be overridden and handle macOS 12.
+ [f04f3405fa50]
+
+ * scripts/mkpkg:
+ Prefer if [ ... ]; then over if test ...; then.
+ [4ba3e6ed7280]
+
+ * .circleci/config.yml:
+ Do not build with -Werror on macOS. Some macOS warnings are bogus,
+ for instance it has an incorrect getgrouplist(3) definition.
+ [7e5f469cb0ec]
+
+ * .circleci/config.yml:
+ Build and test macos with circleci.
+ [fc62dc986646]
+
+2022-02-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Mention lecture behavior change.
+ [cc034a54eb11]
+
+ * lib/iolog/regress/iolog_filter/check_iolog_filter.c:
+ Fix compilation on systems without a real openat(2).
+ [25067ad6772b]
+
+ * plugins/sudoers/match_digest.c:
+ Better warning message when the digest in sudoers is the wrong
+ length.
+ [c2043906f356]
+
+ * lib/iolog/regress/fuzz/fuzz_iolog_json.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_legacy.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_timing.c,
+ lib/util/regress/fuzz/fuzz_sudo_conf.c,
+ logsrvd/regress/fuzz/fuzz_logsrvd_conf.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c:
+ Do not disable fuzzer output if SUDO_FUZZ_VERBOSE env variable is
+ set.
+ [fd3d5706ffda]
+
+2022-02-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/afs.c, plugins/sudoers/auth/dce.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/check.c,
+ plugins/sudoers/check.h, plugins/sudoers/timestamp.c:
+ Display the lecture immediately before prompting for a password.
+ This means we no longer display the lecture unless the user is going
+ to enter a password. Authentication methods that don't interact with
+ the user via the terminal don't trigger the lecture.
+ [17ef981664c3]
+
+ * NEWS, plugins/sudoers/logging.c:
+ Add back warning when a user is not allowed to run a command.
+ Previously, the warning was displayed when a user was not in the
+ sudoers file, or was present but not listed for the local host. The
+ new behavior is to display the warning if a command is denied and
+ mail is sent to the administrator. Whether or not mail is sent is
+ controlled by the "mail_*" flags in sudoers. The warning text is now
+ "This incident has been reported to the administrator." which is
+ hopefully less confusing. The message will not be printed if either
+ the "mailto" or "mailerpath" sudoers settings are disabled.
+ [dcaeadb7e558]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ Document that negating mailto or mailerpath disables sending mail.
+ [02d8aabd9af3]
+
+ * TODO:
+ Remove obsolete TODO file.
+ [98e112abab92]
+
+2022-02-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/logging.c:
+ Don't try to send mail if mailto not set or the mailer is not
+ present.
+ [37166e692a9c]
+
+2022-02-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ plugins/sudoers/po/zh_TW.mo, plugins/sudoers/po/zh_TW.po, po/cs.mo,
+ po/cs.po, po/de.mo, po/de.po, po/eo.mo, po/eo.po, po/fi.mo,
+ po/fi.po, po/fr.mo, po/fr.po, po/hr.mo, po/hr.po, po/ja.mo,
+ po/ja.po, po/ko.mo, po/ko.po, po/pl.mo, po/pl.po, po/ro.mo,
+ po/ro.po, po/sr.mo, po/sr.po, po/uk.mo, po/uk.po, po/vi.mo,
+ po/vi.po, po/zh_CN.mo, po/zh_CN.po, po/zh_TW.mo, po/zh_TW.po:
+ Updated translations from translationproject.org
+ [194b42011062]
+
+ * MANIFEST, lib/iolog/Makefile.in,
+ lib/iolog/regress/iolog_filter/check_iolog_filter.c,
+ lib/iolog/regress/iolog_filter/test1/log,
+ lib/iolog/regress/iolog_filter/test1/timing,
+ lib/iolog/regress/iolog_filter/test1/ttyin,
+ lib/iolog/regress/iolog_filter/test1/ttyin.filtered,
+ lib/iolog/regress/iolog_filter/test1/ttyout,
+ lib/iolog/regress/iolog_filter/test2/log,
+ lib/iolog/regress/iolog_filter/test2/timing,
+ lib/iolog/regress/iolog_filter/test2/ttyin,
+ lib/iolog/regress/iolog_filter/test2/ttyin.filtered,
+ lib/iolog/regress/iolog_filter/test2/ttyout,
+ lib/iolog/regress/iolog_filter/test3/log,
+ lib/iolog/regress/iolog_filter/test3/timing,
+ lib/iolog/regress/iolog_filter/test3/ttyin,
+ lib/iolog/regress/iolog_filter/test3/ttyin.filtered,
+ lib/iolog/regress/iolog_filter/test3/ttyout:
+ Add tests for iolog filtering. This is the functionality used by the
+ log_passwords and passprompt_regex options.
+ [07e587dfd765]
+
+ * lib/iolog/iolog_filter.c:
+ iolog_pwfilt_run: apply regex on ttyout even if we disabled
+ filtering. The heuristic used to decide when to disable filtering is
+ when we see another ttyout buffer or find a cr or nl in the ttyin
+ buffer. However, we should also check the buffer that caused us to
+ disable filtering for a matching regex that would re-enable
+ filtering. Programs that prompt for a password twice might otherwise
+ not have the second password filtered.
+ [f34bf167c3b4]
+
+2022-02-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * INSTALL.md, README.LDAP.md, docs/TROUBLESHOOTING.md,
+ docs/UPGRADE.md, docs/sudo.conf.man.in, docs/sudo.conf.mdoc.in,
+ docs/sudo.man.in, docs/sudo.mdoc.in, docs/sudo_logsrv.proto.man.in,
+ docs/sudo_logsrv.proto.mdoc.in, docs/sudo_logsrvd.conf.man.in,
+ docs/sudo_logsrvd.conf.mdoc.in, docs/sudo_plugin.man.in,
+ docs/sudo_plugin.mdoc.in, docs/sudo_plugin_python.man.in,
+ docs/sudo_plugin_python.mdoc.in, docs/sudoers.ldap.man.in,
+ docs/sudoers.ldap.mdoc.in, docs/sudoers.man.in,
+ docs/sudoers.mdoc.in, docs/sudoreplay.man.in,
+ docs/sudoreplay.mdoc.in, docs/visudo.man.in, docs/visudo.mdoc.in,
+ examples/sudo_logsrvd.conf.in:
+ Avoid using "note that" and "note: " in documentation.
+ [d75995c86fe0]
+
+ * INSTALL.md, README.LDAP.md, README.md, docs/CONTRIBUTING.md,
+ docs/CONTRIBUTORS.md, docs/SECURITY.md, docs/TROUBLESHOOTING.md,
+ docs/UPGRADE.md, docs/cvtsudoers.man.in, docs/cvtsudoers.mdoc.in,
+ docs/sudo.conf.man.in, docs/sudo.conf.mdoc.in, docs/sudo.man.in,
+ docs/sudo.mdoc.in, docs/sudo_logsrv.proto.man.in,
+ docs/sudo_logsrv.proto.mdoc.in, docs/sudo_logsrvd.conf.man.in,
+ docs/sudo_logsrvd.conf.mdoc.in, docs/sudo_logsrvd.man.in,
+ docs/sudo_logsrvd.mdoc.in, docs/sudo_plugin.man.in,
+ docs/sudo_plugin.mdoc.in, docs/sudo_plugin_python.man.in,
+ docs/sudo_plugin_python.mdoc.in, docs/sudo_sendlog.man.in,
+ docs/sudo_sendlog.mdoc.in, docs/sudoers.ldap.man.in,
+ docs/sudoers.ldap.mdoc.in, docs/sudoers.man.in,
+ docs/sudoers.mdoc.in, docs/sudoers_timestamp.man.in,
+ docs/sudoers_timestamp.mdoc.in, docs/sudoreplay.man.in,
+ docs/sudoreplay.mdoc.in, docs/visudo.man.in, docs/visudo.mdoc.in:
+ Remove "please" from the documentation, it is considered bad style.
+ [9c4a7bc1b48c]
+
+ * docs/UPGRADE.md:
+ Mention regular expressions and "sudo -l -U user" behavior change.
+ [9bf947ed3e30]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ Add security notes about regular expressions in sudoers rules.
+ [1748e3a05906]
+
+ * NEWS:
+ Update NEWS for GitHub issue #134.
+ [c69636554901]
+
+2022-02-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/eventlog/eventlog.c:
+ do_logfile_sudo: plug memory leak of full_line Coverity CID 249329
+ [d1d2bc51077a]
+
+ * plugins/sudoers/logging.c:
+ log_server_alert: plug potential memory leak Coverity CID 249328
+ [4d01a8e7dffb]
+
+ * plugins/sudoers/logging.c:
+ fmt_authfail_message: compute the exact amount of space needed.
+ Instead of truncating on overflow, warn and return NULL.
+ [96542ddc9674]
+
+ * plugins/sudoers/parse.c:
+ Fix potential NULL deref if getpwuid(0) fails. Coverity CID 249326
+ [23249273cd01]
+
+2022-02-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudo.man.in, docs/sudo.mdoc.in, plugins/sudoers/parse.c,
+ plugins/sudoers/policy.c:
+ Restrict "sudo -U other -l" to users with sudo ALL for root or
+ "other". Having "sudo ALL" permissions in no longer sufficient to be
+ able to list another user's privileges. The invoking user must now
+ have "sudo ALL" for root or the target user. GitHub issue #134
+ [e2b4f8400599]
+
+2022-02-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Reword some of the NEWS items for 1.9.10.
+ [b2d757e7889c]
+
+2022-02-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudo_logsrvd.conf.man.in, docs/sudo_logsrvd.conf.mdoc.in,
+ docs/sudoers.man.in, docs/sudoers.mdoc.in, lib/util/regex.c,
+ po/sudo.pot:
+ Limit regular expressions to 1024 characters each. Avoids a problem
+ with the fuzzer creating large regular expressions that blow up the
+ glibc regcomp().
+ [83b1cac11c79]
+
+2022-02-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .gitignore, .hgignore, MANIFEST, configure, configure.ac,
+ examples/Makefile.in, examples/sudo.conf.in, examples/syslog.conf,
+ examples/syslog.conf.in:
+ Substitute values in the example syslog.conf too. Also update ignore
+ files for example changes
+ [b13a7e6a630c]
+
+ * MANIFEST, configure, configure.ac, docs/sudo.conf.man.in,
+ docs/sudo.conf.mdoc.in, docs/sudo.man.in, docs/sudo.mdoc.in,
+ docs/sudo_logsrvd.conf.man.in, docs/sudo_logsrvd.conf.mdoc.in,
+ docs/sudo_plugin_python.man.in, docs/sudo_plugin_python.mdoc.in,
+ docs/sudoers.man.in, docs/sudoers.mdoc.in, examples/Makefile.in,
+ examples/sudo_logsrvd.conf, examples/sudo_logsrvd.conf.in,
+ examples/sudoers, examples/sudoers.in:
+ Substitute paths set by configure in examples. Bug #1023
+ [f528fe7a8f88]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ Update Project-Id-Version to 1.9.10.
+ [0ad7934baa9f]
+
+ * plugins/sudoers/po/sudoers.pot:
+ Update .pot files for 1.9.10
+ [c7a477455e2e]
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.10
+ [b437c4c37971]
+
+ * MANIFEST, docs/sudo_logsrvd.conf.man.in,
+ docs/sudo_logsrvd.conf.mdoc.in, docs/sudoers.man.in,
+ docs/sudoers.mdoc.in, include/sudo_util.h, lib/iolog/iolog_filter.c,
+ lib/util/Makefile.in, lib/util/regex.c, lib/util/util.exp.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/match_command.c,
+ plugins/sudoers/regress/sudoers/test28.in,
+ plugins/sudoers/regress/sudoers/test28.json.ok,
+ plugins/sudoers/regress/sudoers/test28.ldif.ok,
+ plugins/sudoers/regress/sudoers/test28.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test28.out.ok,
+ plugins/sudoers/regress/sudoers/test28.toke.ok,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.h, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c:
+ Add helper function to compile a regex that supports (?i).
+ [d680d423d2df]
+
+2022-02-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, configure, configure.ac, docs/sudoers.man.in,
+ docs/sudoers.mdoc.in, examples/sudoers,
+ plugins/sudoers/fmtsudoers.c, plugins/sudoers/match_command.c,
+ plugins/sudoers/parse.h, plugins/sudoers/regress/sudoers/test28.in,
+ plugins/sudoers/regress/sudoers/test28.json.ok,
+ plugins/sudoers/regress/sudoers/test28.ldif.ok,
+ plugins/sudoers/regress/sudoers/test28.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test28.out.ok,
+ plugins/sudoers/regress/sudoers/test28.toke.ok,
+ plugins/sudoers/regress/sudoers/test29.in,
+ plugins/sudoers/regress/sudoers/test29.json.ok,
+ plugins/sudoers/regress/sudoers/test29.ldif.ok,
+ plugins/sudoers/regress/sudoers/test29.out.ok,
+ plugins/sudoers/regress/sudoers/test29.toke.ok,
+ plugins/sudoers/regress/testsudoers/test18.out.ok,
+ plugins/sudoers/regress/testsudoers/test18.sh,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.h,
+ plugins/sudoers/toke.l, plugins/sudoers/toke_util.c:
+ Add support for matching command and args using regular expressions.
+ Either the command, its arguments or both may be (separate) regular
+ expressions.
+ [bef0b1a14771]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Clear sudoers_errstr after it is used. This way we avoid printing
+ the same error message more than once if there are multiple ERROR
+ tokens returned from the lexer.
+ [8a7509cd1c46]
+
+ * logsrvd/logsrvd_local.c:
+ store_iobuf_local: fix potential double free on the error path.
+ [f9a0e3cb3c7f]
+
+ * docs/cvtsudoers.man.in, docs/cvtsudoers.mdoc.in,
+ docs/sudo.conf.man.in, docs/sudo.conf.mdoc.in, docs/sudo.man.in,
+ docs/sudo.mdoc.in, docs/sudo_logsrv.proto.man.in,
+ docs/sudo_logsrv.proto.mdoc.in, docs/sudo_logsrvd.conf.man.in,
+ docs/sudo_logsrvd.conf.mdoc.in, docs/sudo_logsrvd.man.in,
+ docs/sudo_logsrvd.mdoc.in, docs/sudo_plugin.man.in,
+ docs/sudo_plugin.mdoc.in, docs/sudo_plugin_python.man.in,
+ docs/sudo_plugin_python.mdoc.in, docs/sudo_sendlog.man.in,
+ docs/sudo_sendlog.mdoc.in, docs/sudoers.ldap.man.in,
+ docs/sudoers.ldap.mdoc.in, docs/sudoers.man.in,
+ docs/sudoers.mdoc.in, docs/sudoers_timestamp.man.in,
+ docs/sudoers_timestamp.mdoc.in, docs/sudoreplay.man.in,
+ docs/sudoreplay.mdoc.in, docs/visudo.man.in, docs/visudo.mdoc.in:
+ Update links to sudo web site and reference markdown docs.
+ [da9a9eb04f04]
+
+ * docs/cvtsudoers.man.in, docs/cvtsudoers.mdoc.in,
+ docs/sudo.conf.man.in, docs/sudo.conf.mdoc.in, docs/sudo.man.in,
+ docs/sudo.mdoc.in, docs/sudo_logsrvd.man.in,
+ docs/sudo_logsrvd.mdoc.in, docs/sudo_plugin_python.man.in,
+ docs/sudo_plugin_python.mdoc.in, docs/sudoers.man.in,
+ docs/sudoers.mdoc.in, docs/sudoreplay.man.in,
+ docs/sudoreplay.mdoc.in, docs/visudo.man.in, docs/visudo.mdoc.in:
+ Use a 4n indent for code blocks instead of the default 6n.
+ [7322dd26a3d4]
+
+ * plugins/sudoers/testsudoers.c:
+ testsudoers: disable argument permutation in GNU getopt This makes
+ it easier to test commands with arguments.
+ [fb005b03a75e]
+
+ * lib/iolog/iolog_filter.c:
+ iolog_pwfilt_run: fix types in error return
+ [663deea257d0]
+
+ * lib/iolog/iolog_filter.c, plugins/sudoers/iolog.c:
+ Free potential leaks of passprompt_regex_handle. Coverity CID 249057
+ [d562ea42ab66]
+
+2022-02-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #133 from Dzejrou/main
+
+ Do not unset user timeout when no default timeout is set.
+ [58504381014e]
+
+2022-02-09 Jaroslav Jindrak <dzejrou@gmail.com>
+
+ * plugins/sudoers/policy.c:
+ Do not unset user timeout when no default timeout is set.
+ [25f32be7d18d]
+
+2022-02-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/fmtsudoers.c, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/sudoers/test2.in,
+ plugins/sudoers/regress/sudoers/test2.json.ok,
+ plugins/sudoers/regress/sudoers/test2.ldif.ok,
+ plugins/sudoers/regress/sudoers/test2.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test2.out.ok,
+ plugins/sudoers/regress/sudoers/test2.toke.ok:
+ Don't escape double quotes (") in a command when printing it.
+ Previously, cvtsudoers and "sudo -l" would escape double quotes in a
+ command or command line argument, which is not valid sudoers syntax.
+ [3bd0505b03e2]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in:
+ A few minor (mostly cosmetic) fixes. Add missing ALL to Runas_Member
+ and Host. Replace some tabs with spaces. Fix the syntax of a
+ sudoedit example.
+ [a943116eb35b]
+
+2022-02-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #132 from ninedotnine/patch-1
+
+ Sync example sudoers with default sudoers
+ [8c903452e624]
+
+2022-02-04 dan soucy <ninedotnine@users.noreply.github.com>
+
+ * examples/sudoers:
+ Sync example sudoers with default sudoers
+
+ `sudoers.in` was changed by 1d13533
+ [f34657ff9345]
+
+2022-02-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * ABOUT-NLS, INSTALL.md, NEWS, README.LDAP.md, docs/CONTRIBUTING.md,
+ plugins/sudoers/po/README, po/README:
+ Upgrade http links to https where possible and fix some broken
+ links.
+ [e33d61fdafdb]
+
+2022-02-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/logging.c:
+ Remove "This incident will be reported." from user warnings. This
+ used to indicate that email had been sent to the administrator
+ telling them that someone tried to run sudo. Whether or not sudo
+ sends email is now configurable, so the warning may not be accurate.
+ It is also confusing to the user since they will not know who the
+ incident is being reported to. See also https://xkcd.com/838/
+ [b2860bb51393]
+
+ * plugins/sudoers/sssd.c:
+ Log fn_get_values() return code in the debug log on error. Also move
+ a nested switch() statement out of 'case 0' for improved
+ readability.
+ [ad609804a70c]
+
+ * plugins/sudoers/sssd.c:
+ Do not return an error if we cannot connect to the SSSD connector.
+ This may simply mean that nsswitch.conf lists sss as a sudoers
+ source but SSSD is not configured for sudo. Otherwise, the user will
+ receive a useless "problem with defaults entries" when the sssd
+ backend tries to fetch the global defaults. Bug #1022.
+ [60bb147ed3e6]
+
+ * plugins/sudoers/log_client.c, plugins/sudoers/logging.c:
+ Set client_closure to NULL after freeing it.
+ [20da8f0c9226]
+
+ * plugins/sudoers/log_client.c:
+ client_closure_alloc: init write_bufs/free_bufs before other
+ allocations. We must initialize the tail queues before any possible
+ call to client_closure_free(), such as due to malloc() failure.
+ [5dd7d1ba2b76]
+
+ * logsrvd/logsrvd_journal.c:
+ Add missing default return in last commit.
+ [e17820ba6ff8]
+
+ * logsrvd/logsrvd_journal.c:
+ sudo_logsrvd: make sure journal exists before writing the alert
+ message. Fixes a potential NULL dereference when journaling an alert
+ message.
+ [19d109fb1420]
+
+ * include/sudo_compat.h:
+ Fix compilation on Debian kFreeBSD. The configure script correctly
+ detects that utimensat() and futimens() are missing but the headers
+ define stub versions of the functions. Including sys/stat.h pulls in
+ the system definitions so we can override them safely. Bug #1021.
+ [10775e14164a]
+
+2022-02-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/ttyname.c:
+ Add fallback if /proc/self/stat or /proc/pid/psinfo is missing or
+ invalid. If the /proc file indicates no terminal is present there is
+ no fallback. Bug #1020
+ [c32620c9f115]
+
+2022-02-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in, plugins/sudoers/check.c,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c:
+ Add sudoers option to perform authentication even in non-interative
+ mode. If noninteractive_auth is set, authentication methods that do
+ not require input from the user's terminal may proceed. It is off by
+ default, which restores the pre-1.9.9 behavior of "sudo -n".
+ [f06dcd0957d0]
+
+ * MANIFEST, lib/iolog/iolog_filter.c,
+ logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.7:
+ Work around a glibc regcomp() bug with repeated '+' operators. Glibc
+ regcomp() has a bug where it uses excessive memory for repeated '+'
+ ops. Collapse them to avoid running the fuzzer out of memory.
+ [db423326311f]
+
+ * logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.1,
+ logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.2,
+ logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.3,
+ logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.4,
+ logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.5,
+ logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.6:
+ Rebase seed corpus on updated sudo_logsrvd.conf example.
+ [1f30b95c6ce6]
+
+ * logsrvd/logsrvd_conf.c:
+ Fix parsing of "retry_interval" in the relay section. The setting
+ was present but the callback was missing so it could not be parsed
+ in the conf file.
+ [09666425a392]
+
+ * logsrvd/logsrvd_conf.c:
+ Use TIME_T_MAX as the upper limit when parsing timeouts.
+ [989eaa812d4e]
+
+ * plugins/sudoers/auth/pam.c:
+ converse: don't set response pointer on error Linux pam_conv(3) says
+ not to set the pointer on PAM_CONV_ERR.
+ [79934c8631c0]
+
+2022-01-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/regress/cvtsudoers/sudoers4:
+ Add missing sudoers4 test file for new cvtsudoers test.
+ [5b9f3084d9e9]
+
+ * MANIFEST, plugins/sudoers/cvtsudoers_merge.c,
+ plugins/sudoers/regress/cvtsudoers/test38.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test38.sh:
+ defaults_check_conflict: it is only really a conflict if the binding
+ match If the Defaults name matched but the binding does not, we can
+ simply leave it be. Fixes a problem where given two sudoers sources
+ that have a host specified, if they contain conflicting Defaults
+ entries we would drop one of the Defaults instead of keeping both
+ after making them host-specific.
+ [9b8ad3d1e163]
+
+ * MANIFEST, plugins/sudoers/cvtsudoers_merge.c,
+ plugins/sudoers/regress/cvtsudoers/sudoers1,
+ plugins/sudoers/regress/cvtsudoers/sudoers2,
+ plugins/sudoers/regress/cvtsudoers/sudoers3,
+ plugins/sudoers/regress/cvtsudoers/test34.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test34.sh,
+ plugins/sudoers/regress/cvtsudoers/test35.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test35.sh,
+ plugins/sudoers/regress/cvtsudoers/test36.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test36.sh,
+ plugins/sudoers/regress/cvtsudoers/test37.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test37.sh:
+ Make it possible to merge a host-based Defaults with a global one.
+ We convert the global Defaults to a host-based one with a single
+ "ALL" member. Later, when we simplify the host list, we'll convert
+ this back to a global Defaults.
+ [152c16a608c1]
+
+2022-01-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd_conf.c:
+ Check for garbage after [section] in sudo_logsrvd.conf.
+ [46a222b60747]
+
+ * logsrvd/regress/fuzz/fuzz_logsrvd_conf.dict,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.dict:
+ Sync fuzzing dictionary with current configuration keyword list.
+ [9af3929a2f6a]
+
+2022-01-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudo_logsrvd.conf.man.in, docs/sudo_logsrvd.conf.mdoc.in,
+ examples/sudo_logsrvd.conf, logsrvd/logsrvd.h,
+ logsrvd/logsrvd_conf.c, logsrvd/logsrvd_local.c:
+ Add new log_passwords and passprompt_regex settings. When logging
+ terminal input, if log_passwords is false and any of the regular
+ expressions in the passprompt_regex list are found in the terminal
+ output, terminal input will be replaced with '*' characters until a
+ newline or carriage return is found in the input or an output
+ character is received.
+ [1d07eaada99c]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/iolog.c,
+ plugins/sudoers/policy.c,
+ plugins/sudoers/regress/serialize_list/check_serialize_list.c,
+ plugins/sudoers/regress/unescape/check_unesc.c,
+ plugins/sudoers/serialize_list.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/unesc_str.c:
+ Escape/unescape commas when serializing/deserializing a stringlist.
+ [17c422c0b236]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/locale.c, plugins/sudoers/logging.h,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c:
+ Pass the operator to the Defaults callback too. That way we can tell
+ what to do in callbacks for lists.
+ [d541809b62bf]
+
+ * MANIFEST, include/sudo_iolog.h, lib/iolog/Makefile.in,
+ lib/iolog/iolog_filter.c:
+ lib/iolog: add support for filtering password out of tty input If a
+ password regex is found in the tty output, tty input will be
+ replaced with '*' chars until a newline or another tty output
+ character is received.
+ [19c3a58dfe29]
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/iolog.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c:
+ Add a new sudoers settings log_passwords and passprompt_regex. When
+ logging terminal input, if log_passwords is disabled and any of the
+ regular expressions in the passprompt_regex list are found in the
+ terminal output, terminal input will be replaced with '*' characters
+ until a newline or carriage return is found in the input or an
+ output character is received.
+ [5fa969cfdef4]
+
+ * plugins/sudoers/def_data.c, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/defaults.h:
+ Add a flag to avoid splitting list entries on white space.
+ [32ac4cd5eae7]
+
+2022-01-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_9 for changeset 296f4f986a7a
+ [cba838829505] <1.9>
+
+ * NEWS, config.h.in, configure, configure.ac, include/sudo_compat.h,
+ logsrvd/tls_init.c, plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Merge sudo 1.9.9 from tip.
+ [296f4f986a7a] [SUDO_1_9_9] <1.9>
+
+ * docs/sudoers.ldap.man.in, docs/sudoers.ldap.mdoc.in:
+ "plain text" -> "plaintext" for consistency.
+ [6cbefac27286]
+
+2022-01-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * po/ro.mo, po/ro.po:
+ Updated translations from translationproject.org
+ [c264de490846]
+
+ * INSTALL.configure:
+ Sync with autoconf git.
+ [efd6e2df1b4f]
+
+ * scripts/mkdep.pl:
+ Fix potential infinite loop when trying to format long lines.
+ [e17a3b7b657b]
+
+2022-01-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudo.man.in, docs/sudo.mdoc.in:
+ Document how commands are passed to the shell for the -i and -s
+ options. The concatenation of command and arguments and escaping of
+ special characters was not documented. Text adapted from GitHub
+ issue #121 from Kris Rinzwind
+ [852f803234af]
+
+ * docs/TROUBLESHOOTING.md:
+ Also mention no_new_privs error in the troubleshooting guide.
+ [70cc0679098f]
+
+ * INSTALL.md, docs/TROUBLESHOOTING.md, docs/sudo.conf.man.in,
+ docs/sudo.conf.mdoc.in, docs/sudo.man.in, docs/sudo.mdoc.in,
+ docs/sudo_plugin.man.in, docs/sudo_plugin.mdoc.in,
+ docs/sudo_plugin_python.man.in, docs/sudo_plugin_python.mdoc.in,
+ docs/sudoers.ldap.man.in, docs/sudoers.ldap.mdoc.in,
+ docs/sudoers.man.in, docs/sudoers.mdoc.in, docs/visudo.man.in,
+ docs/visudo.mdoc.in:
+ Replace uid and gid with user-ID and group-ID in more places.
+ [2b6bc95509fd]
+
+2022-01-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * INSTALL.md:
+ PAM is enabled on NetBSD by default too.
+ [3bc31511f687]
+
+ * INSTALL.md, README.LDAP.md, docs/HISTORY.md,
+ docs/TROUBLESHOOTING.md, docs/UPGRADE.md:
+ Use the Oxford comma consistently, it is helpful in technical
+ documents.
+ [3df4b26d035e]
+
+ * docs/sudo.man.in, docs/sudo.mdoc.in:
+ Document the error message when no_new_privs is set.
+ [492a154dec10]
+
+ * docs/sudoers.ldap.man.in, docs/sudoers.ldap.mdoc.in:
+ Sudo now recovers from sudoers syntax errors.
+ [77d457c4e722]
+
+ * docs/cvtsudoers.man.in, docs/cvtsudoers.mdoc.in,
+ docs/sudo.conf.man.in, docs/sudo.conf.mdoc.in, docs/sudo.man.in,
+ docs/sudo.mdoc.in, docs/sudo_logsrv.proto.man.in,
+ docs/sudo_logsrv.proto.mdoc.in, docs/sudo_logsrvd.conf.man.in,
+ docs/sudo_logsrvd.conf.mdoc.in, docs/sudo_plugin.man.in,
+ docs/sudo_plugin.mdoc.in, docs/sudo_plugin_python.man.in,
+ docs/sudo_plugin_python.mdoc.in, docs/sudoers.ldap.man.in,
+ docs/sudoers.ldap.mdoc.in, docs/sudoers.man.in,
+ docs/sudoers.mdoc.in, docs/sudoreplay.man.in,
+ docs/sudoreplay.mdoc.in, docs/visudo.man.in, docs/visudo.mdoc.in,
+ examples/sudo.conf.in, examples/sudo_logsrvd.conf:
+ Use the Oxford comma consistently, it is helpful in technical
+ documents.
+ [e8d29c772963]
+
+ * INSTALL.md:
+ Mention docker configuration.
+ [8312350518cb]
+
+ * plugins/sudoers/ldap_util.c:
+ Quiet a cppcheck false positive.
+ [023468af3269]
+
+ * docs/CONTRIBUTING.md:
+ Mention https://www.sudo.ws/security/fuzzing/ in the fuzzing
+ section.
+ [87767f7b89ad]
+
+ * plugins/sudoers/sssd.c:
+ Fix logic inversion when setting negated flag.
+ [3e4051bc9f30]
+
+ * src/sudo.c:
+ Quiet a PVS-Studio format string warning.
+ [77e953f3c46f]
+
+2022-01-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ Regen .pot files.
+ [b999972bc90d]
+
+ * NEWS:
+ Bug #1016, #1017 and negated sudoUser in LDAP.
+ [4ec54e728437]
+
+ * plugins/sudoers/defaults.c:
+ Don't set/run early Defaults if a custom defaults_list is specified.
+ Defaults settings passed in by the front end are already "early" so
+ there is no need to treat any of them as special.
+
+ Otherwise, we end up running the early defaults callbacks before
+ sudoers has been parsed. This means that, for instance, it is not
+ possible to disable the fqdn flag before its callback is run if sudo
+ is build with the --with-fqdn option. Bug #1016.
+ [8c6eaa503793]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h:
+ Mark is_early_default(), run_early_defaults(), set_early_default()
+ static. They are not used outside of defaults.c.
+ [1045e8c7a92e]
+
+ * plugins/sudoers/sssd.c:
+ Add support in SSSD for negated users.
+ [bca3d02cdd8b]
+
+ * docs/sudoers.ldap.man.in, docs/sudoers.ldap.mdoc.in,
+ plugins/sudoers/ldap.c:
+ Add support in the LDAP filter for negated users. Based on a diff
+ from Simon Lees
+ [e1d48d44229e]
+
+2022-01-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/mkdir_parents.c:
+ Use PATH_MAX, not NAME_MAX+1 for the directory entry length. On some
+ systems, such as Solaris, the max length of a directory entry is
+ filesystem-dependent. We could use fpathconf() and dynamically
+ allocate the name but it is simpler to just use PATH_MAX here.
+ [d1a097783717]
+
+ * plugins/python/python_plugin_common.c:
+ Only emulate Py_FinalizeEx for Python 3.[0-5].
+ [b314942c0f2f]
+
+ * lib/util/getcwd.c, lib/util/mkdir_parents.c:
+ Use POSIX NAME_MAX, not the obsolete MAXNAMLEN define. Fixes
+ compilation with musl libc.
+ [a1609b2d968f]
+
+2022-01-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/limits.c:
+ When applying fallback limits, make sure we don't reduce rlim_max.
+ Fixes a problem where sudo could reduce the max stack size on some
+ systems if the original limit was higher than the fallback limit,
+ but not unlimited/infinity.
+ [1fef77204f17]
+
+ * src/limits.c:
+ Don't modify the stack limit if it is >= SUDO_STACK_MIN.
+ [b9e473780083]
+
+ * plugins/sudoers/Makefile.in:
+ The pre-install target requires visudo, add an explicit dependency.
+ [b5b073d2fc9b]
+
+2022-01-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sudo.c:
+ If sudo is not set-user-ID root, check for the no_new_privs flag on
+ Linux. This flag disables set-user-ID at execve(2) time and may be
+ set by default for some containers. GitHub issue #129.
+ [462249058274]
+
+2022-01-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/sudoers.man.in, docs/sudoers.mdoc.in,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/policy.c, plugins/sudoers/sudoers.h,
+ src/parse_args.c:
+ Add pam_askpass_service sudoers setting for "sudo -A". This makes it
+ possible to use a different PAM configuration for when "sudo -A" is
+ used. The main use case is to only use PAM modules that can interact
+ with the askpass program. GitHub issue #112.
+ [5f59bc3f9d81]
+
+2022-01-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/iolog_loginfo.c:
+ Improve debugging info when fdopen() fails.
+ [0d9711d8564a]
+
+2022-01-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sssd.c:
+ sss_sudo_free_values() checks for NULL, no need to do it manually.
+ [ccf012907a01]
+
+ * plugins/sudoers/getdate.c, plugins/sudoers/getdate.y:
+ Quiet a clang analyzer false positive.
+ [90b6791616b0]
+
+2022-01-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/getdate.c, plugins/sudoers/getdate.y:
+ Quiet a clang analyzer false positive.
+ [3c66e9be5f24]
+
+ * plugins/sudoers/auth/sudo_auth.c:
+ Fix return value for non-interactive mode for non-standalone auth
+ methods. AUTH_NONINTERACTIVE was being stored in the wrong variable.
+ [199a180e7fab]
+
+ * plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po, po/fi.mo,
+ po/fi.po, po/ko.mo, po/ko.po, po/tr.mo, po/tr.po:
+ Updated translations from translationproject.org
+ [032877650fe6]
+
+ * plugins/sudoers/cvtsudoers_merge.c:
+ defaults_var_matches() should return bool, not enum match_result.
+ Remove enum match_result as it is no longer used.
+ [6559769ddcd1]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/auth/sudo_auth.c:
+ Quiet two PVS-studio warnings.
+ [3a7c89cff3d6]
+
+ * plugins/sudoers/auth/pam.c:
+ Remove PAM_TTY workaround for old, buggy PAM modules. In the past,
+ some PAM modules assumed that PAM_TTY was set and would misbehave
+ (or crash) if not. This was primarily obsolete versions of Linux-
+ PAM, so it should now be safe to remove this. Setting PAM_TTY to an
+ empty string can cause its own set of issues. GitHub issue #74
+ [491cb67ea43b]
+
+2022-01-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Mention fix for Bug #956 and GitHub issue #83.
+ [8692b9985381]
+
+ * plugins/sudoers/auth/API, plugins/sudoers/auth/afs.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h, plugins/sudoers/check.c,
+ plugins/sudoers/logging.c, plugins/sudoers/sudoers.h:
+ Push non-interactive mode checking down into the auth methods. For
+ "sudo -n" we only want to reject a command if user input is actually
+ required. In the case of PAM at least, we may not need to interact
+ with the user. Bug #956, GitHub issue #83
+ [bc9653ffe82f]
+
+2022-01-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers_merge.c,
+ plugins/sudoers/regress/cvtsudoers/sudoers1,
+ plugins/sudoers/regress/cvtsudoers/sudoers2,
+ plugins/sudoers/regress/cvtsudoers/sudoers3,
+ plugins/sudoers/regress/cvtsudoers/test34.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test35.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test36.out.ok:
+ userspec_overridden: fix checks when there is more than one userspec
+ [199996d29f50]
+
+ * MANIFEST, plugins/sudoers/cvtsudoers_merge.c,
+ plugins/sudoers/regress/cvtsudoers/test35.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test36.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test36.sh:
+ Fix merging of global/ALL entries when each input file has a host.
+ If a host is specified for the input file, cvtsudoers will bind
+ global Defaults to that host and change host "ALL" in a userspec to
+ the host name. However, if all the input files have matching hosts
+ we can simplify the merged file by converting back to ALL after
+ resolving conflicts.
+ [bfdb2edfca71]
+
+ * LICENSE.md:
+ Welcome to 2022.
+ [039e8c0efd7e]
+
+ * docs/Makefile.in:
+ LICENSE.md moved to the top-level src dir.
+ [b1c2687eef9d]
+
+2021-12-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #127 from Tyler887/main
+
+ Typo
+ [c4780c2a3056]
+
+2021-12-22 Tyler887 <tylermageeshields@gmail.com>
+
+ * INSTALL.md:
+ Typo
+ [b650bec9f275]
+
+2021-12-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, docs/UPGRADE.md, plugins/sudoers/policy.c, src/selinux.c,
+ src/sudo.c:
+ Back out changes to enable SELinux by default. This may return in a
+ future release in a different form.
+ [73e46fbe5c27]
+
+ * LICENSE.md, MANIFEST, README.md, docs/LICENSE.md:
+ Move LICENSE.md out of docs and back to the top-level. GitHub
+ expects it to be in the top-level directory.
+ [3c62dd396aff]
+
+2021-12-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/cvtsudoers_merge.c,
+ plugins/sudoers/regress/cvtsudoers/test35.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test35.sh:
+ cvtsudoers: fix a regression when merging matching Defaults. If a
+ host is specified with a sudoers file, we have to treat Defaults as
+ Defaults@host checking for duplicates.
+ [9db413953938]
+
+2021-12-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ add_defaults: add defs == NULL check to quiet coverity false
+ positive
+ [a534eee04069]
+
+2021-12-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers_merge.c,
+ plugins/sudoers/regress/cvtsudoers/test34.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test34.sh:
+ When merging Defaults, allow a subsequent global Defaults (no
+ binding) to override a prior Defaults setting with a binding.
+ [0be52fa6d4d8]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ add_defaults: defs can never be NULL
+ [9ba97823b757]
+
+ * plugins/sudoers/cvtsudoers_merge.c:
+ Plug memory leak when making a default host-specific. We don't need
+ to allocate new space for the binding list, just the members of the
+ list.
+ [5667d09136f2]
+
+2021-12-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, examples/Makefile.in, examples/cvtsudoers.conf:
+ Add an example cvtsudoers.conf file.
+ [aa738148e712]
+
+ * docs/cvtsudoers.man.in, docs/cvtsudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers.h:
+ Add group_file, match_local, and passwd_file to cvtsudoers.conf.
+ Previously, these were only settable via command line options.
+ [a7a8b0af3c42]
+
+2021-12-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/TROUBLESHOOTING.md:
+ Remove question about running Solaris 11 binaries on Solaris 10.
+ Current versions of sudo use many APIs that are not present on
+ Solaris 10. If you want a sudo Solaris 10 binary, build it on
+ Solaris 10, not 11.
+ [0346a46cf595]
+
+ * MANIFEST, plugins/sudoers/regress/cvtsudoers/test34.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test34.sh:
+ Add simple test for cvtsudoers merge functionality.
+ [fda86b17249a]
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ plugins/sudoers/po/zh_TW.mo, plugins/sudoers/po/zh_TW.po, po/cs.mo,
+ po/cs.po, po/de.mo, po/de.po, po/eo.mo, po/eo.po, po/fr.mo,
+ po/fr.po, po/hr.mo, po/hr.po, po/ja.mo, po/ja.po, po/pl.mo,
+ po/pl.po, po/sr.mo, po/sr.po, po/uk.mo, po/uk.po, po/zh_CN.mo,
+ po/zh_CN.po, po/zh_TW.mo, po/zh_TW.po:
+ Updated translations from translationproject.org
+ [edfdaac9b1e7]
+
+ * MANIFEST, plugins/sudoers/po/es.mo, plugins/sudoers/po/es.po:
+ Add sudoers Spanish translation from translationproject.org
+ [502d45c0af5f]
+
+2021-12-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Bugs #1013 and #1014
+ [1a7b533c5829]
+
+ * lib/util/mkdir_parents.c:
+ sudo_mkdir_parents: make sure the path we created is a directory For
+ extra paranoia, verify that the directory we created is still a
+ directory before we fchown() it.
+ [75c23aaa9fca]
+
+ * docs/sudo.man.in, docs/sudo.mdoc.in:
+ In SECURITY NOTES, clarify that PATH may be overridden by the
+ policy. Bug #1014
+ [4f7035d6b921]
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/mkdir_parents.c, lib/util/mkdirat.c, logsrvd/logsrvd.c,
+ plugins/sudoers/timestamp.c, scripts/mkdep.pl:
+ Avoid TOCTOU in sudo_mkdir_parents() using openat(2) and mkdirat(2).
+ This also allows us to make path const as it should be.
+ [46db77e4afb8]
+
+ * plugins/sudoers/ldap_conf.c, plugins/sudoers/sudo_ldap_conf.h:
+ Sudo parsed "deref" and "tls_reqcert" in ldap.conf but didn't set
+ the options. The switch() in the sudo_ldap_set_options_table()
+ function needed to be updated to treat CONF_DEREF_VAL and
+ CONF_REQCERT_VAL data types as int. Fix from Dennis Filder. Bug
+ #1013.
+ [5f5bdf9010d7]
+
+2021-12-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/SECURITY.md:
+ Minor formatting tweak so we can import into the sudo web site.
+ [220c647b6635]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/pwutil_impl.c:
+ Fix CodeQL "Multiplication result converted to larger type"
+ warnings.
+ [a17db0b94018]
+
+2021-12-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/SECURITY.md:
+ Surround email addresses with angle brackets, not square backets.
+ [b9514c0165f2]
+
+2021-12-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po, po/fa.mo,
+ po/fa.po, po/fi.mo, po/fi.po, po/ja.mo, po/ja.po, po/sr.mo,
+ po/sr.po, po/zh_CN.mo, po/zh_CN.po, po/zh_TW.mo, po/zh_TW.po:
+ Updated translations from translationproject.org
+ [b2815226875b]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ Update .pot files for 1.9.9
+ [e4e903808160]
+
+2021-12-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * README.LDAP.md, docs/CONTRIBUTING.md, docs/TROUBLESHOOTING.md,
+ docs/UPGRADE.md:
+ Minor formatting tweaks.
+ [eee91b1fc68c]
+
+2021-12-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * INSTALL, INSTALL.md, MANIFEST, README, README.LDAP, README.LDAP.md,
+ README.md, docs/CONTRIBUTING.md, docs/CONTRIBUTORS,
+ docs/CONTRIBUTORS.md, docs/HISTORY, docs/HISTORY.md, docs/LICENSE,
+ docs/LICENSE.md, docs/Makefile.in, docs/TROUBLESHOOTING,
+ docs/TROUBLESHOOTING.md, docs/UPGRADE, docs/UPGRADE.md, etc/sudo-
+ logsrvd.pp, etc/sudo-python.pp, etc/sudo.pp:
+ Convert README and docs files to markdown. This makes things look
+ better on GitHub and we can use the markdown version directly in the
+ new sudo web site.
+ [1cdcbce74a73]
+
+2021-12-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/SECURITY.md:
+ Policy -> Disclosure Policy
+ [13f278869e03]
+
+ * Merge pull request #124 from juspence/main
+
+ Allow sudo -g anyone and sudo -u anyone -g anytwo
+ [1a000f5aaba1]
+
+2021-12-04 juspence <87657842+juspence@users.noreply.github.com>
+
+ * plugins/sudoers/sudoers.in:
+ Allow sudo -g anyone and sudo -u anyone -g anytwo
+
+ When only the user (ALL) is specified explicitly, and the group is
+ implied, only sudo -u works. Specifying both the user and group,
+ like (ALL:ALL), is required to:
+
+ 1) Use sudo -g by itself (with no -u user) 2) Use sudo -u and -g
+ together, with a -g group that is different from the -u user's
+ primary group
+ [ca31aaa0b074]
+
+2021-12-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/Makefile.in:
+ Add build dir to include search path for mksiglist.h and mksigname.h
+ Fixes out of tree builds on systems without sys_siglist[] or
+ sys_signame[]. GitHub issue #123.
+ [fccd76813052]
+
+2021-11-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/cvtsudoers_merge.c,
+ plugins/sudoers/regress/cvtsudoers/sudoers1,
+ plugins/sudoers/regress/cvtsudoers/sudoers2,
+ plugins/sudoers/regress/cvtsudoers/sudoers3:
+ cvtsudoers: better merging of lists that are not exact duplicates
+ When merging rules, if one list would be overridden by another,
+ remove the overridden rule and continue merging.
+ [19dc52bd9c6f]
+
+2021-11-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Update NEWS with latest changes.
+ [fafe74e0b20f]
+
+2021-11-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/edit_open.c:
+ dir_is_writable: don't treat EPERM from faccessat() as a fatal
+ error. We can get EPERM on Linux with SELinux. GitHub issue #122.
+ [25bbc56b2f6d]
+
+2021-11-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docs/cvtsudoers.man.in, docs/cvtsudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers.h,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_merge.c:
+ cvtsudoers: add -l option to log merge actions The "-l logfile"
+ option can be used to store a log of what actions cvtsudoers took
+ when merging multiple files. For example, which aliases were
+ renamed, which entries were overriden or removed as duplicated.
+ [fa96976882aa]
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.9
+ [dad415a982bc]
+
+2021-11-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, docs/CONTRIBUTORS, po/fa.mo, po/fa.po:
+ New Persian (Farsi) translation from translationproject.org
+ [3665533a7219]
+
+2021-11-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers_csv.c:
+ Quiet a PVS Studio warning. The warning that need_comma is always
+ false is correct but in this case it is better to use a consistent
+ construct so that if the code is re-ordered no bugs are introduced.
+ [5109a34444f5]
+
+ * lib/util/getentropy.c:
+ Pass correct size to free_zero(). Coverity CID 241233
+ [2ba51f57deb5]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers_csv.c, plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_merge.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/fmtsudoers_cvt.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h, plugins/sudoers/parse_ldif.c:
+ Add reference counting to Defaults bindings. Previously, we checked
+ that the previous entry's binding pointer was not the same while
+ freeing. However, to be able to merge Defaults records we cannot
+ rely on Defaults entries with the same binding being immediately
+ adjacent. This removes the prev_binding checks in favor of a
+ reference count which allows us to plug the memory leak in
+ cvtsudoers when merging Defaults.
+ [0a789516622b]
+
+2021-11-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/alias.c,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers.h,
+ plugins/sudoers/cvtsudoers_merge.c, plugins/sudoers/parse.h:
+ cvtsudoers: merge aliases when multiple sudoers files are specified
+ Duplicate aliases are remove. If there are conflicting alias names,
+ the conflicts are renamed by appending a numerical suffix. For
+ example, if there are two SERVERS Host_Aliases, the second one will
+ be renamed to SERVERS_1.
+ [d9b602626b8c]
+
+ * plugins/sudoers/cvtsudoers_merge.c:
+ cvtsudoers: merge Defaults when multiple sudoers files are specified
+ If a hostname is specified with the sudoers file, it will be used to
+ make the Defaults setting host-specific, if possible. Duplicate
+ Defaults settings are removed and conflicts are warned about. It is
+ not possible to resolve all conflicts automatically.
+ [756b05304ccb]
+
+ * plugins/sudoers/cvtsudoers_merge.c:
+ cvtsudoers: merge userspecs when multiple sudoers files are
+ specified If a hostname is specified with the sudoers file, it will
+ be used to make the userspec host-specific, if possible. Duplicate
+ userspecs are removed but conflicting entries are not currently
+ pruned.
+ [643b533bb4f4]
+
+ * docs/cvtsudoers.man.in, docs/cvtsudoers.mdoc.in:
+ Document how to merge sudoers files with cvtsudoers.
+ [241c3786f5a8]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.h,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c, plugins/sudoers/sssd.c:
+ init_parse_tree() now takes ownership of lhost and shost, if any.
+ This means that lhost and shost in struct sudoers_parse_tree are no
+ longer const and that free_parse_tree() will free lhost/shost. The
+ only consumer that passed in lho.st/shost was the SSSD back-end
+ which has been updated to avoid a double-free.
+ [650bb75666fb]
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers_merge.c:
+ cvtsudoers: use init_parse_tree() to initialize a parse tree. Also
+ free the parse tree before exit.
+ [9d8f8bb88192]
+
+ * MANIFEST, Makefile.in, etc/macos-background.png, etc/sudo-
+ logsrvd.pp, etc/sudo-python.pp, etc/sudo.pp:
+ Add a background image for the macOS installer.
+ [39889307b278]
+
+ * scripts/pp:
+ Update PolyPkg
+ [44b1d08be1b0]
+
+2021-11-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/mkpkg:
+ mkpkg: handle a macOS SDK that just uses the major version. For
+ example, MacOSX11.sdk instead of MacOSX11.3.sdk.
+ [ce41fc5aa672]
+
+ * lib/util/Makefile.in:
+ Add missing dependencies for timegm.
+ [b20c4936504b]
+
+2021-11-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers.c:
+ Add support for specifying the hostname as a prefix to the sudoers
+ file. If present, the host name is copied into the struct
+ sudoers_parse_tree.
+ [e87e11cccb6e]
+
+2021-11-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers.c:
+ cvtsudoers: parse multiple sudoers files and store them in a tail
+ queue In the future the parsed files will be merged before they are
+ output.
+ [89c77b3f4157]
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.h, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.h:
+ Add sudoers_parse_tree_list, a tail queue of struct
+ sudoers_parse_tree. This will be used to store multiple parse trees
+ and merge them into a single sudoers_parse_tree.
+ [073ada18f18b]
+
+ * docs/CONTRIBUTING.md:
+ Fix formatting of links.
+ [df50208b3f70]
+
+ * MANIFEST, docs/CONTRIBUTING.md:
+ Add contributing guide.
+ [a99f3a0757f6]
+
+ * .github/workflows/codeql-analysis.yml:
+ Create codeql-analysis.yml
+ [efab25dab29c]
+
+2021-11-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, docs/SECURITY.md:
+ Add security doc, inspired by the Microsoft template.
+ [0a8012f8ee35]
+
+ * .gitignore, .hgignore, INSTALL, MANIFEST, Makefile.in, README,
+ configure, configure.ac, doc/CONTRIBUTORS, doc/HISTORY, doc/LICENSE,
+ doc/Makefile.in, doc/TROUBLESHOOTING, doc/UPGRADE,
+ doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in, doc/fixman.sh,
+ doc/fixmdoc.sed, doc/schema.ActiveDirectory, doc/schema.OpenLDAP,
+ doc/schema.iPlanet, doc/schema.olcSudo, doc/sudo.conf.man.in,
+ doc/sudo.conf.man.in.sed, doc/sudo.conf.mdoc.in, doc/sudo.man.in,
+ doc/sudo.man.in.sed, doc/sudo.mdoc.in, doc/sudo_logsrv.proto.man.in,
+ doc/sudo_logsrv.proto.mdoc.in, doc/sudo_logsrvd.conf.man.in,
+ doc/sudo_logsrvd.conf.mdoc.in, doc/sudo_logsrvd.man.in,
+ doc/sudo_logsrvd.mdoc.in, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudo_plugin_python.man.in,
+ doc/sudo_plugin_python.mdoc.in, doc/sudo_sendlog.man.in,
+ doc/sudo_sendlog.mdoc.in, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in, doc/sudoers.man.in,
+ doc/sudoers.man.in.sed, doc/sudoers.mdoc.in,
+ doc/sudoers_timestamp.man.in, doc/sudoers_timestamp.mdoc.in,
+ doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in, doc/visudo.man.in,
+ doc/visudo.mdoc.in, docs/CONTRIBUTORS, docs/HISTORY, docs/LICENSE,
+ docs/Makefile.in, docs/TROUBLESHOOTING, docs/UPGRADE,
+ docs/cvtsudoers.man.in, docs/cvtsudoers.mdoc.in, docs/fixman.sh,
+ docs/fixmdoc.sed, docs/schema.ActiveDirectory, docs/schema.OpenLDAP,
+ docs/schema.iPlanet, docs/schema.olcSudo, docs/sudo.conf.man.in,
+ docs/sudo.conf.man.in.sed, docs/sudo.conf.mdoc.in, docs/sudo.man.in,
+ docs/sudo.man.in.sed, docs/sudo.mdoc.in,
+ docs/sudo_logsrv.proto.man.in, docs/sudo_logsrv.proto.mdoc.in,
+ docs/sudo_logsrvd.conf.man.in, docs/sudo_logsrvd.conf.mdoc.in,
+ docs/sudo_logsrvd.man.in, docs/sudo_logsrvd.mdoc.in,
+ docs/sudo_plugin.man.in, docs/sudo_plugin.mdoc.in,
+ docs/sudo_plugin_python.man.in, docs/sudo_plugin_python.mdoc.in,
+ docs/sudo_sendlog.man.in, docs/sudo_sendlog.mdoc.in,
+ docs/sudoers.ldap.man.in, docs/sudoers.ldap.mdoc.in,
+ docs/sudoers.man.in, docs/sudoers.man.in.sed, docs/sudoers.mdoc.in,
+ docs/sudoers_timestamp.man.in, docs/sudoers_timestamp.mdoc.in,
+ docs/sudoreplay.man.in, docs/sudoreplay.mdoc.in, docs/visudo.man.in,
+ docs/visudo.mdoc.in, etc/codespell.skip:
+ Rename "doc" directory to "docs" for better GitHub compatibility.
+ [1268c3ae0916]
+
+ * lib/util/Makefile.in:
+ Use $(SED), not sed, when generating mksiglist.h/mksigname.h
+ [7a7b636a3f32]
+
+ * configure, configure.ac, lib/iolog/Makefile.in,
+ lib/util/Makefile.in, logsrvd/Makefile.in,
+ plugins/sudoers/Makefile.in:
+ Add configure check for sha1sum and use "openssh dgst -sha1" if
+ missing. Only needed when building the seed corpus zip files.
+ [3c74ceba0446]
+
+ * include/sudo_compat.h:
+ sudo_compat.h: include unistd.h regardless of OS type This helps to
+ avoid issues with mismatched headers and libraries.
+ [4a22435a2832]
+
+2021-11-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/visudo.c:
+ install_sudoers: fix return value when there is no temp file to
+ install This can happen when no changes were made. Also preserve the
+ edited temp file on error if we are unable to move it into place.
+ [01c1052ac874]
+
+ * plugins/python/regress/testdata/check_multiple_approval_plugin_and_a
+ rguments.stdout:
+ Bump plugin version in test data to 1.18.
+ [138b9f6a6143]
+
+ * plugins/sudoers/defaults.c:
+ free_defs_val: free rlimits like strings (which they are).
+ [ade32de829cb]
+
+ * plugins/sudoers/visudo.c:
+ Rename {check,set}_perms variable to {check,set}_mode. Avoids a name
+ clash with the set_perms() function.
+ [a2dfa0d36690]
+
+ * src/edit_open.c:
+ Avoid symbol name clash with is_writable() function variable. Rename
+ "is_writable" variable to "writable".
+ [a52bd106933b]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document new resource limit settings.
+ [022e51bff860]
+
+ * doc/UPGRADE:
+ Mention that the core dump size resource limit now defaults to 0.
+ [22997e8008c9]
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ include/sudo_plugin.h, src/exec.c:
+ Document resource limit support in command_info[] and Bump plugin
+ API minor. This is supported beginning with sudo 1.9.9 and plugin
+ API 1.17.
+ [2004a71a11b3]
+
+2021-11-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, plugins/sudoers/defaults.c,
+ src/limits.c:
+ Use strtoul() on systems without strtoull(). We can assume that
+ systems without strtoull() have 32-bit resource limits.
+ [59c1be5a0387]
+
+ * src/exec.c, src/limits.c, src/sudo.c, src/sudo.h:
+ Add front-end support for setting resouce limits. The special value
+ "user" means preserve the invoking user's limit. The value "default"
+ means don't override the default limit for the user as assigned by
+ the system (PAM, loging.conf, userdb, etc).
+ [7ad6961d5d72]
+
+ * plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/defaults.h, plugins/sudoers/mkdefaults,
+ plugins/sudoers/policy.c:
+ Add basic support for setting resource limits in sudoers. The
+ default for rlimit_core is "0,0" Resource limits are passed back to
+ the front-end in command_info[] when set.
+ [298d5e228635]
+
+ * src/edit_open.c:
+ switch_user_nonfatal: only define if using faccessat()
+ [1a6b2c0240f5]
+
+2021-11-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/visudo.man.in, doc/visudo.mdoc.in, plugins/sudoers/visudo.c:
+ visudo: add -O and -P options to check/set owner and permissions.
+ This can be used in conjunction with the -c option to check that the
+ sudoers file ownership and permissions are correct. Bug #1007
+ [1f20721148b0]
+
+2021-11-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/UPGRADE:
+ UPGRADE: mention SELinux behavior change.
+ [0b8cef633225]
+
+ * src/selinux.c, src/sudo.h, src/sudo_edit.c:
+ Rename selinux_setcon -> selinux_setexeccon
+ [50bde2e4d922]
+
+ * src/selinux.c:
+ In the SELinux role is "unconfined_r", disable SELinux support. We
+ only want to apply SELinux to confined users. This is a bit of a
+ hack as unconfined_r is specific to the targeted policy.
+ [aaa8ee97f31e]
+
+ * src/exec_monitor.c, src/exec_nopty.c, src/selinux.c, src/sudo.c,
+ src/sudo.h, src/sudo_edit.c:
+ Separate out the code to compute the context from selinux_setup().
+ This makes it possible to determine whether we really need to
+ execute the command via the sesh helper. What was left of
+ selinux_setup() is now selinux_relabel_tty() and
+ selinux_audit_role_change().
+ [687a81e59fdd]
+
+ * plugins/sudoers/policy.c, src/selinux.c, src/sudo.c:
+ Pass status of selinux sudoers setting to front-end as selinux-rbac.
+ The front-end uses this to decide whether or not to enable SELinux.
+ If selinux-rbac is true _or_ if it is not present and selinux_role
+ or selinux_type are set, SELinux support is enabled. Previously,
+ SELinux support was only enabled if a role was specified.
+ [2f21ae08ebbd]
+
+ * src/edit_open.c:
+ dir_is_writable: add fallback if changing UIDs fails The SELinux
+ policy may not allow uid/gid changes which will break the
+ writability checks and cause sudoedit to fail.
+ [5c5928a0c314]
+
+2021-11-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/mkpkg:
+ Build python package on Fedora
+ [7261434fc60c]
+
+2021-11-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/selinux.c:
+ Make get_exec_context static, it is unused outside selinux.c.
+ [be59f91e53dd]
+
+ * doc/sudo.conf.mdoc.in:
+ Fix lint warning: skipping paragraph macro: Pp before Bd
+ [f84297a652d8]
+
+2021-10-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ doc/sudo_plugin_python.man.in, doc/sudo_plugin_python.mdoc.in:
+ Escape some minus signs ('-') as required by newer groff.
+ [4a1a2d6d5c19]
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, lib/util/timegm.c,
+ plugins/sudoers/Makefile.in, plugins/sudoers/gentime.c,
+ plugins/sudoers/gmtoff.c, plugins/sudoers/parse.h, scripts/mkdep.pl:
+ parse_gentime: use timegm() to generate time since the epoch The
+ timegm() function is non-standard but widely available. Provide an
+ implementation for those systems that lack it. Bug #1006
+ [3ca20dfdb44c]
+
+ * include/sudo_compat.h, lib/util/Makefile.in, scripts/mkdep.pl:
+ Fix pasto in gmtime_r and localtime_r macros. Also add missing
+ Makefile targets for them.
+ [2310e188fdd4]
+
+ * plugins/sudoers/gmtoff.c:
+ Take daylight saving time into consideration when computing offset.
+ Otherwise, the resulting time may be off by and hour, depending on
+ whether DST is currently active compared to the target time.
+ [20c60fe8e8fc]
+
+2021-10-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/mkpkg:
+ Back out f2d82771e7dd, arm64e on macOS is still in preview state.
+ Until arm64e on macOS is finalized, continue to build arm64
+ packages.
+ [6c3bbd6ffc3a]
+
+2021-10-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/mkpkg:
+ Build arm64e ABI binaries on macOS 11 and above. We originally used
+ arm64 here but the correct ABI is arm64e. The arm64 arch will be
+ removed in a future release.
+ [f2d82771e7dd]
+
+ * logsrvd/logsrvd_local.c:
+ Use iolog_openat() when opening the log.json file in the I/O log
+ dir.
+ [9041b20b8d01]
+
+2021-10-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/tls_init.c:
+ Use BIO_new_file() not BIO_new_fd() to read dhparams file. Older
+ versions of OpenSSL and wolfSSL lack BIO_new_fd(). Also explicitly
+ include openssl/bio.h and openssl/dh.h for wolfSSL.
+ [8338f58d5ba0]
+
+ * INSTALL, config.h.in, configure, configure.ac:
+ wolfSSL not WolfSSL
+ [4ee7f96ef87c]
+
+ * .circleci/config.yml:
+ Add wolfSSL variant to continuous integration tests.
+ [dbbab23e069c]
+
+ * docker/debian/latest/Dockerfile, docker/debian/testing/Dockerfile,
+ docker/ubuntu/devel/Dockerfile, docker/ubuntu/latest/Dockerfile,
+ docker/ubuntu/rolling/Dockerfile:
+ Add libwolfssl-dev to Debian and Ubuntu Dockerfiles Fedora does not
+ appear to have an official wolfssl package.
+ [12c0feaa0ebb]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ White space in an include file path supported by sudo 1.9.1 or
+ higher.
+ [9a22034de181]
+
+2021-10-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * INSTALL, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, lib/iolog/hostcheck.c,
+ lib/util/digest_openssl.c, lib/util/getentropy.c, logsrvd/logsrvd.c,
+ logsrvd/logsrvd.h, logsrvd/logsrvd_relay.c, logsrvd/sendlog.c,
+ logsrvd/sendlog.h, logsrvd/tls_client.c, logsrvd/tls_common.h,
+ logsrvd/tls_init.c, plugins/sudoers/log_client.c,
+ plugins/sudoers/log_client.h:
+ Add support for WolfSSL's OpenSSL compatibility layer. Based on
+ changes from Hayden Roche
+ [568557ecb77b]
+
+ * lib/util/Makefile.in, plugins/sudoers/Makefile.in:
+ regenerate dependencies
+ [d36bf7724e49]
+
+ * logsrvd/iolog_writer.c, logsrvd/logsrvd.c, logsrvd/logsrvd.h,
+ logsrvd/logsrvd_conf.c, logsrvd/logsrvd_journal.c,
+ logsrvd/logsrvd_local.c, logsrvd/logsrvd_queue.c,
+ logsrvd/logsrvd_relay.c, logsrvd/regress/fuzz/fuzz_logsrvd_conf.c,
+ logsrvd/sendlog.c, logsrvd/sendlog.h:
+ Move include of log_server.pb-c.h into logsrvd.h and sendlog.h This
+ way there is no include file order issue with the
+ PROTOBUF_C_VERSION_NUMBER check.
+ [23678487ffaf]
+
+ * docker/debian/latest/Dockerfile, docker/debian/testing/Dockerfile,
+ docker/fedora/latest/Dockerfile, docker/fedora/rawhide/Dockerfile,
+ docker/ubuntu/devel/Dockerfile, docker/ubuntu/latest/Dockerfile,
+ docker/ubuntu/rolling/Dockerfile:
+ Add pkg-config to all Dockerfile
+ [63457bb84c4d]
+
+2021-10-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/tls_init.c:
+ Use SSL_FILETYPE_PEM with SSL_CTX_use_PrivateKey_file, not
+ X509_FILETYPE_PEM While they are defined to the same value in
+ OpenSSL one should not rely on this.
+ [1a1557931dbf]
+
+2021-10-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Fix setting _PATH_ASAN_LIB, need to double up the square brackets.
+ [98143164620a]
+
+ * logsrvd/sendlog.c:
+ sudo_sendlog: send runenv, rungid and runuid from log.json too With
+ this change, sudo_sendlog can now round-trip sudo-style I/O logs
+ that use the newer log.json format without losing any information.
+ [d9d3dad6cca3]
+
+2021-10-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, lib/util/arc4random.c:
+ arc4random: need to include sys/random.h on Solaris too. This was
+ removed when Linux genentropy() was disabled.
+ [18ea9b386950]
+
+2021-10-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/hostcheck.c, lib/util/inet_ntop.c, logsrvd/logsrv_util.h,
+ plugins/sudoers/log_client.h:
+ Make sure INET_ADDRSTRLEN and INET6_ADDRSTRLEN are defined.
+ [e347465e0a05]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/log_client.c, plugins/sudoers/log_client.h,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h:
+ Only include log_client.h if SUDOERS_LOG_CLIENT is defined.
+ [c318f74cf2a8]
+
+ * Merge pull request #118 from larb0b/main
+
+ Define MAP_FAILED where relevant if undefined
+ [74f3e9f1a1f4]
+
+2021-10-21 Larkin Nickle <me@larbob.org>
+
+ * lib/util/getentropy.c, lib/util/regress/mktemp/mktemp_test.c,
+ lib/util/snprintf.c:
+ Define MAP_FAILED where relevant if undefined
+
+ On systems such as HP-UX 10.20, MAP_FAILED is not defined.
+ [9f4976caa567]
+
+2021-10-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, m4/libtool.m4:
+ Improve macOS version detection to support macOS 11 and simplify
+ legacy logic From Jeremy Huddleston Sequoia
+ [f09b45ab460a]
+
+ * logsrvd/sendlog.c:
+ sudo_sendlog: send multiple I/O log records together if possible Try
+ to fill the write buffer and then send to the server instead of
+ sending records one at a time.
+ [0b084cd75d64]
+
+ * logsrvd/sendlog.c, logsrvd/sendlog.h:
+ sudo_sendlog: support multiple write buffers like sudo_logsrvd
+ [a46b88eff200]
+
+ * configure, configure.ac, lib/util/Makefile.in:
+ Always link libsudo_util.so with libcrypto.so if using OpenSSL. We
+ may need to use RAND_bytes() in the getentropy() emulation.
+ [9c805a008d76]
+
+ * config.h.in, configure, configure.ac, lib/util/getentropy.c,
+ plugins/sudoers/boottime.c:
+ Add an explicit check for sys/sysctl.h. This test needs to be done
+ after AC_LANG_WERROR to avoid including sys/sysctl.h on systems
+ where it is marked as deprecated via a #warning directive.
+ [d9f1f97b0f37]
+
+ * config.h.in, configure, configure.ac, lib/util/arc4random.c:
+ Use our own getentropy() by default on Linux. The glibc getentropy()
+ emulation will fail on older kernels that don't support getrandom().
+ Also use sudo_fatal() instead of sending SIGKILL on getentropy()
+ failure. GitHub issue #117.
+ [1ca9d10ff780]
+
+ * lib/util/getentropy.c:
+ Use the OpenSSL RAND_bytes() function if getrandom() fails.
+ [5f82f6d2ea36]
+
+ * lib/util/Makefile.in, lib/util/arc4random_buf.c, scripts/mkdep.pl:
+ Fix compilation of standalone arc4random_buf(). Apparently this code
+ was never compiled anywhere.
+ [a66c68c3a976]
+
+ * lib/util/uuid.c:
+ sudo_uuid_create: no longer need a union for the uuid.
+ [a9277bf0078c]
+
+2021-10-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/eventlog/eventlog_free.c:
+ eventlog_free: free signal_name too
+ [1da686483f2a]
+
+ * lib/iolog/regress/fuzz/fuzz_iolog_json.dict:
+ Add new log.json keywords
+ [f4a30fc6c4ed]
+
+ * lib/iolog/regress/fuzz/fuzz_iolog_json.c:
+ fuzz_iolog_json: initialize exit_value to -1
+ [bac9826b95a1]
+
+ * logsrvd/logsrvd.c:
+ Fix potential use-after-free when calling iolog_flush_all(). We need
+ to call iolog_flush_all() _before_ scheduling the commit point. If
+ we fail to schedule to commit point, the closure will be freed.
+ Coverity CID 220557
+ [364736f15a06]
+
+ * logsrvd/sendlog.c:
+ sendlog: use runargv from log.json if available
+ [88a0f4d7bb94]
+
+ * logsrvd/sendlog.c:
+ sudo_sendlog: send exit data in eventlog if present
+ [fdacc0f68c56]
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c,
+ logsrvd/logsrvd_local.c, plugins/sudoers/logging.c:
+ No longer need to pass exit params to eventlog_exit(), use struct
+ eventlog. Now that struct eventlog includes the exit parameters we
+ can simplify how eventlog_exit() is called.
+ [8580c0e8334d]
+
+ * include/sudo_eventlog.h, lib/iolog/iolog_json.c,
+ lib/iolog/iolog_loginfo.c, logsrvd/iolog_writer.c:
+ Read command run_time, signal and exit_value from I/O log log.json
+ file.
+ [05223c4cca0c]
+
+ * logsrvd/logsrvd_local.c:
+ Log the command run-time and exit status in the I/O log.
+ [8b02b373f79b]
+
+ * lib/eventlog/eventlog.c:
+ format_json: fix pasto when setting dumped_core boolean
+ [ca11285c088a]
+
+2021-10-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/eventlog/eventlog.c, logsrvd/logsrvd_local.c:
+ Handle a missing run_time in an ExitMessage. It is now possible to
+ pass a NULL run_time to eventlog_exit().
+ [f3e989682931]
+
+2021-10-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ logsrvd/logsrvd.c:
+ No need to flush logs before commit point if we flush after each
+ write. Also document that logs are flushed before sending a commit
+ point even when flushing is disabled.
+ [50323241569d]
+
+2021-10-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, include/sudo_iolog.h, lib/iolog/Makefile.in,
+ lib/iolog/iolog_conf.c, lib/iolog/iolog_flush.c,
+ logsrvd/iolog_writer.c, logsrvd/logsrvd.c, logsrvd/logsrvd.h:
+ Flush I/O logs before we send a commit point. The commit point
+ message means we have written the data to disk so we should not be
+ buffering it any longer. We do not currently fsync(2) the data after
+ flushing, perhaps we should.
+ [5233172b7531]
+
+ * logsrvd/logsrv_util.c:
+ Do not treat a resume point of [0, 0] as an error. If the connecton
+ is interrupted before sudo sends back a commit_point message,
+ resuming at [0, 0] is correct. Also add a warning on unexpected EOF
+ parsing the timing file.
+ [105f29878ad7]
+
+2021-10-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.c:
+ Display a more helpful message if the user tries to run "sudo cd".
+ Since "cd" is a shell built-in command it cannot be run directly via
+ sudo. The user either needs to spawn a shell via "sudo -s" or use
+ the -D option to run a command in a specific directory.
+ [4d45797dfb11]
+
+ * configure, configure.ac:
+ Don't install sudoers.a when configured with --enable-static-
+ sudoers. We already avoid installing it when --disable-shared-util
+ is specified.
+ [0d2022bc07cb]
+
+2021-10-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/mkpkg:
+ mkpkg: preserve make exit value on exit Fixes a problem where the
+ exit value from mkpkg was 0 even on error.
+ [0d0f15bf10cf]
+
+ * plugins/sudoers/cvtsudoers_csv.c:
+ Fix typos in SELinux and Solaris priv support.
+ [16b9a1459f1d]
+
+ * MANIFEST, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers.h, plugins/sudoers/cvtsudoers_csv.c:
+ cvtsudoers: initial support for CSV output For CSV output we double
+ quotes strings that contain commas. For each literal double quote
+ character present inside the string, two double quotes are output.
+ [8f7763b74563]
+
+ * lib/iolog/Makefile.in, lib/util/Makefile.in, logsrvd/Makefile.in,
+ plugins/sudoers/Makefile.in:
+ regenerate dependencies
+ [09d11b5c7d41]
+
+ * docker/README, etc/codespell.ignore:
+ Fix typo and avoid a codespell false positive.
+ [81a365b29c3c]
+
+2021-10-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .circleci/config.yml:
+ Add build-nointercept and test-nointercept
+ [d39877327ccc]
+
+2021-10-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .circleci/config.yml:
+ circleci: test multiple build options We now do separate builds with
+ LDAP/SSSD enabled, logsrv client/server disabled, and static-sudoers
+ enabled.
+ [4d8a9b45156c]
+
+ * configure, configure.ac, plugins/sudoers/Makefile.in:
+ Fix fuzzer build with when --enable-static-sudoers is used. This
+ introduces a sudoers-specific version of LT_STATIC instead of
+ appending the --tag=disable-shared to SUDOERS_LDFLAGS. I've also
+ removed the -static flag as it should not be needed.
+ [864a2fd4e3f7]
+
+2021-10-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * docker/README:
+ Mention --security-opt=seccomp=unconfined workaround for bleeding
+ edge. May be needed for Fedora rawhide and Ubuntu testing, among
+ others.
+ [a465fdb0a7de]
+
+ * configure, configure.ac:
+ Try to handle the case where libasan.so is a linker script. Fixes
+ check_noexec with ASAN on Fedora where libasan.so just includes the
+ actual library file.
+ [f96d1d0cea53]
+
+ * .circleci/config.yml, docker/README,
+ docker/fedora/latest/Dockerfile, docker/fedora/rawhide/Dockerfile:
+ Enable address and undefined behavior sanitizers in CI builds. We
+ need to disable leak sanitizer during "make check" because it uses
+ ptrace which is not allowed for unprivileged containers.
+ [9378e3856a60]
+
+2021-10-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .circleci/config.yml:
+ Switch to Ubuntu latest for circleci build.
+ [1270ca1ba47d]
+
+ * .circleci/config.yml, docker/debian/latest/Dockerfile,
+ docker/debian/testing/Dockerfile, docker/fedora/latest/Dockerfile,
+ docker/fedora/rawhide/Dockerfile, docker/ubuntu/devel/Dockerfile,
+ docker/ubuntu/latest/Dockerfile, docker/ubuntu/rolling/Dockerfile:
+ Add build user for circleci instead of running as root.
+ [27dcb5218cb2]
+
+ * .circleci/config.yml, MANIFEST, docker/README,
+ docker/debian/latest/Dockerfile, docker/debian/testing/Dockerfile,
+ docker/fedora/latest/Dockerfile, docker/fedora/rawhide/Dockerfile,
+ docker/ubuntu/devel/Dockerfile, docker/ubuntu/latest/Dockerfile,
+ docker/ubuntu/rolling/Dockerfile:
+ Use circleci for continuous integegration. Build container
+ descriptions are in the new docker directory.
+ [d5b5b16b0624]
+
+2021-10-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .gitignore, .hgignore:
+ Update ignore file.
+ [7fe8afa88e96]
+
+2021-10-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoreplay.c:
+ Sync "sudo -l" output with normal sudo log format. It now prints
+ runchroot and runcwd (falling back on cwd). As a result, submithost
+ is now printed first, matching sudo. Also avoid printing NULL
+ pointers and skip entries that don't have at least command,
+ submituser and runuser set.
+ [0d6b96ec88a1]
+
+ * lib/iolog/iolog_json.c:
+ iolog_parse_json_object: optimize for large argv
+ [5fa1929189a3]
+
+2021-09-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Add "-fcf-protection" to SSP_CFLAGS and SSP_LDFLAGS if supported.
+ Can be disabled via --disable-hardening.
+ [589507ecadf4]
+
+ * configure, configure.ac:
+ Add "-z now" to hardened link options if supported. Can be disabled
+ via --disable-hardening.
+ [11ff1d86440b]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/editor.c,
+ plugins/sudoers/regress/editor/check_editor.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/visudo.c:
+ find_editor: remove the env_error argument There is no case where we
+ should fail to find an editor just because the values of EDITOR,
+ VISUAL and SUDO_EDITOR are unavailable. Both sudoedit and the
+ "env_editor" sudoers setting are documented as falling back on the
+ hard-coded list of editors in the "editors" sudoers setting. Bug
+ #1000
+ [caa529a0cab6]
+
+ * plugins/sudoers/check_aliases.c:
+ Use sudo_printf(SUDO_CONV_ERROR_MSG) instead of fprintf(stderr).
+ Avoids extraneous output in the fuzzer.
+ [981d3abd96c7]
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c:
+ Stub out sudo_printf() and avoid other use of stderr in fuzzers.
+ This makes it possible to parse sudoers without using quiet mode,
+ resulting in better coverage.
+ [3215cad4174f]
+
+2021-09-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/regress/fuzz/fuzz_iolog_json.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_legacy.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_timing.c,
+ lib/util/regress/fuzz/fuzz_sudo_conf.c,
+ logsrvd/regress/fuzz/fuzz_logsrvd_conf.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c:
+ Use a consistent version of fuzz_conversation() with all fuzzers.
+ Also undo a change to fuzz_sudoers.c that snuck in to the last
+ commit.
+ [8a94b06302b7]
+
+ * lib/iolog/regress/fuzz/fuzz_iolog_json.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_legacy.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_timing.c,
+ lib/util/regress/fuzz/fuzz_sudo_conf.c,
+ logsrvd/regress/fuzz/fuzz_logsrvd_conf.c,
+ plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ Fuzzers should not produce output. Excessive output makes the fuzzer
+ runs much less efficient.
+ [b9c485009c0f]
+
+ * logsrvd/logsrv_util.c:
+ expand_buf: fix conditional for when we need to preserve existing
+ data It is possible for the buffer offset to be zero when the length
+ is non-zero. The proper value to use is the same as is used for the
+ memcpy/memmove size. Fixes buffer corruption caused by a very long
+ command line that usually results in a dropped connection.
+ [59a4319b3463]
+
+2021-09-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, lib/util/closefrom.c:
+ Emulate closefrom() on macOS using proc_pidinfo(). This avoids
+ relying on /dev/fd which may not exist in a chroot jail. Adapted
+ from a change in OpenSSH by likan_999.student AT sina.com
+ [2e86d4150ce5]
+
+2021-09-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/edit_open.c:
+ Handle EMLINK and EFTYPE errno values for O_NOFOLLOW failure.
+ FreeBSD returns EMLINK and NetBSD returns EFTYPE instead of ELOOP.
+ This is only used to present the user with a more appropriate error
+ message.
+ [ca5499c8c40f]
+
+2021-09-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers.c:
+ Fix typo in last commit, use boolean AND not bitwise.
+ [685bd5d9ce6f]
+
+ * doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers.h,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.h:
+ Add the ability to filter/match by command via the -m option. For
+ example "cvtsudoers -m cmd=/bin/ls" would only display entries that
+ would allow /bin/ls to be allowed or denied.
+ [3534a0170c59]
+
+2021-09-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers.h, plugins/sudoers/pwutil.c:
+ Add --group-file and --passwd-file options to cvtsudoers. These are
+ based on the code in testsudoers.
+ [3286dd5dd0bf]
+
+2021-09-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/mkdir_parents.c:
+ Move cppcheck suppression annotation to where it needs to be.
+ [17d601bc91f3]
+
+ * lib/util/mksigname.c:
+ format string fix: print signal number as unsigned. Quiets a
+ cppcheck warning; mksiglist.c already has this fixed.
+ [a28b72dceec4]
+
+ * plugins/sudoers/ldap_util.c:
+ Fix memory leak on error path if snprintf() overflows. Coverity CID
+ 188804
+ [73872d2e2cd0]
+
+2021-09-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/passwd.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid5.c:
+ Avoid reinitializing other auth methods.
+ [af0495460943]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ expand_include: add bounds checking when expanding %h escape.
+ [3c0ca1f0d4e5]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Check snprintf() return values even if we preallocated the correct
+ amount. There are no remaining unchecked snprintf() that can
+ actually overflow.
+ [0eaf1d4daa84]
+
+ * include/sudo_iolog.h, lib/iolog/iolog_nextid.c:
+ iolog_nextid(): make iolog_dir argument const. We make a copy of the
+ directory so there's no real reason that parameter can't be const.
+ [f278847ca9aa]
+
+ * plugins/sudoers/ldap_util.c:
+ Amend truncation fix, the real problem was the size passed to
+ snprintf(). sudo_rcstr_alloc() takes a length (not a size) parameter
+ so when calling snprintf() we need to add one to the length.
+ [92f8a8b86d20]
+
+ * plugins/sudoers/ldap_util.c:
+ Fix truncation of the last char of the sudoRole cn passed to
+ append_default(). This string is primarily used for warning
+ messages. Also check the snprintf() return value to avoid silent
+ truncation. GitHub issue #115
+ [22b8d7bc62f8]
+
+2021-09-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_8p2 for changeset 9edebc604c58
+ [67357c8687d3] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.8p2
+ [9edebc604c58] [SUDO_1_9_8p2] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.8p2
+ [f29fdeb8ae5b]
+
+ * etc/codespell.exclude:
+ Standardize on "front-end" not "front end" in the man pages.
+ [b0ad634852e7]
+
+ * configure, configure.ac:
+ fix typo
+ [4d8738449daa]
+
+ * logsrvd/logsrvd_journal.c:
+ Reuse existing journal file for an accepted/rejected sub-command.
+ Otherwise we end up with zero-length files in the incoming queue dir
+ and may end up relaying one of those instead of the actual journal
+ file.
+ [4789371a43f3] <1.9>
+
+ * logsrvd/logsrvd_journal.c:
+ Reuse existing journal file for an accepted/rejected sub-command.
+ Otherwise we end up with zero-length files in the incoming queue dir
+ and may end up relaying one of those instead of the actual journal
+ file.
+ [545897a2761c]
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ Re-enable error output for the sudoers parser. It is only the alias
+ and defaults warnings we need to suppress.
+ [114bd7756a7c]
+
+ * src/exec_intercept.c:
+ Add intercept_cleanup() stub for when building w/o intercept
+ support.
+ [bd6f32a90787]
+
+ * src/exec_intercept.c, src/exec_nopty.c, src/exec_pty.c,
+ src/sudo_exec.h:
+ Add intercept_cleanup() to free the closure used by
+ intercept_accept_cb().
+ [55f6aea8b517]
+
+ * plugins/sudoers/auth/pam.c:
+ Don't re-initialize PAM for sub-commands.
+ [41d7d61e4ac5] <1.9>
+
+ * plugins/sudoers/auth/pam.c:
+ Don't re-initialize PAM for sub-commands.
+ [faa7aec4d145]
+
+ * logsrvd/logsrvd_local.c:
+ sudo_logsrvd: only send log ID for first command of a session There
+ is no need to send the log ID for each sub-command.
+ [e21b40af74f2] <1.9>
+
+ * logsrvd/logsrvd_local.c:
+ sudo_logsrvd: only send log ID for first command of a session There
+ is no need to send the log ID for each sub-command.
+ [625b18c5f821]
+
+ * plugins/sudoers/log_client.c:
+ Only store the first log id received from the server. Plugs a small
+ memory leak in intercept mode if the log server sends the log ID
+ again for sub-commands.
+ [e20563f3e152] <1.9>
+
+ * plugins/sudoers/log_client.c:
+ Only store the first log id received from the server. Plugs a small
+ memory leak in intercept mode if the log server sends the log ID
+ again for sub-commands.
+ [ca2ad5b219cd]
+
+2021-09-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ fuzz_sudoers: don't warn about unknown defaults entries Some fuzzing
+ inputs cause a huge number of warnings and displaying them all can
+ result in the fuzz run timing out. If we disable the warnings we can
+ avoid the timeout.
+ [4823ee305937]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.h, plugins/sudoers/gram.y,
+ plugins/sudoers/policy.c:
+ Limit paths for command, cwd and chroot to PATH_MAX bytes. This
+ helps prevent the fuzzer from going off the rails.
+ [9550fa76a645]
+
+ * plugins/sudoers/sudoers.c:
+ sudo -i: missing NULL terminator when moving argv to make room for
+ --login Fixes a potential crash for "sudo -i" when the target user
+ has bash as the shell (which needs the --login option). Bug #998.
+ [32644aae1eab] <1.9>
+
+ * plugins/sudoers/sudoers.c:
+ sudo -i: missing NULL terminator when moving argv to make room for
+ --login Fixes a potential crash for "sudo -i" when the target user
+ has bash as the shell (which needs the --login option). Bug #998.
+ [4b297f2ead15]
+
+ * lib/eventlog/eventlog.c:
+ Only append argv[] to the log line if argv[0] is not NULL. It should
+ not be possible to reach this point with a command defined but
+ argv[] empty but it doesn't hurt to check.
+ [61f9cf744673]
+
+2021-09-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/check_aliases.c:
+ Only warn about an undefined alias or a cycle a single time. There's
+ no point in warning about the same problem multiple times. This
+ implementation assumes a small number of warnings and so just uses a
+ simple listed link.
+ [4461f65d1bad]
+
+ * configure, configure.ac:
+ Remove now-unused CHECK_INTERCEPT variable.
+ [447dbf8bea48]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Quiet pvs-studio false positive: V557 Array overrun is possible.
+ Make the zero length check explicit so as not to confuse static (or
+ human) analyzers.
+ [512ab29a9f28]
+
+2021-09-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/regress/testsudoers/test17.out.ok,
+ plugins/sudoers/regress/testsudoers/test17.sh:
+ Test that digest matching works with LDAP sudoCommand: ALL
+ [f7ec49401d4f]
+
+ * plugins/sudoers/ldap_util.c:
+ Allow a digest to be specified with the "ALL" command for ldap/sssd
+ back-ends. This has been possible with sudoers file entries since
+ sudo 1.9.0 but no corresponding change was made for ldap/sssd.
+ [89a30bbd7dac]
+
+ * lib/eventlog/eventlog.c:
+ Use localtime_r() not gmtime_r() when formatting the local time.
+ This is consistent with how sudo formatted time stamps prior to the
+ logging code being split off into libeventlog. We only need to use
+ gmtime_r() for ISO 8601 time.
+ [aee6e29ba9d6]
+
+ * lib/eventlog/eventlog.c,
+ lib/iolog/regress/iolog_path/check_iolog_path.c,
+ lib/util/sudo_debug.c, plugins/audit_json/audit_json.c,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/parse.c,
+ plugins/sudoers/timestr.c:
+ Check strftime(3) return value in all cases. Old versions of
+ strftime(3) didn't guarantee to NUL-terminate the buffer so we
+ explicitly clear the last byte of the buffer and check it.
+ [bc402e4bd4d2]
+
+ * config.h.in, configure, configure.ac, logsrvd/tls_init.c:
+ tls_init.c: use SSL_CTX_set0_tmp_dh_pkey if present. Fixes a warning
+ on OpenSSL 3.0 and plugs a memory leak of dhparams on config reload.
+ [02027ea86d3b]
+
+ * configure, configure.ac, lib/util/digest_openssl.c:
+ Use the EVP digest routines instead of calling SHA2 functions
+ directly. Avoids compiler warnings with OpenSSL 3.0.
+ EVP_MD_CTX_new() is only available for OpenSSL 1.1 and higher--we
+ will fall back to sudo's SHA2 code if necessary.
+ [6fbac28175f9]
+
+ * configure, configure.ac:
+ When using pkg-config, don't assume the names of the ssl and crypto
+ libs. On the HP-UX build machines these are named libssl_pic.a and
+ libcrypto_pic.a to avoid conflicting with the system libs.
+ [a8eb772b3a4d]
+
+ * lib/util/sudo_debug.c:
+ Store milliseconds in the debug file timestamp. Sometime second
+ granularity is not enough.
+ [1df3e75f1133]
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, lib/util/gmtime_r.c, lib/util/localtime_r.c:
+ Add gmtime_r and localtime_r tests and compat if missing.
+ [709671c493a3]
+
+ * lib/eventlog/eventlog.c, lib/iolog/iolog_path.c,
+ lib/iolog/regress/iolog_path/check_iolog_path.c,
+ lib/util/sudo_debug.c, plugins/audit_json/audit_json.c,
+ plugins/sample_approval/sample_approval.c,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/gmtoff.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/parse.c, plugins/sudoers/timestr.c:
+ Use gmtime_r() and localtime_r() instead of gmtime() and
+ localtime().
+ [5758514b25cb]
+
+ * doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in:
+ Plugin lines are for approval and audit plugins too.
+ [67bb7c0687f2]
+
+ * doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in, doc/sudo.man.in,
+ doc/sudo.mdoc.in, doc/sudo_logsrvd.man.in, doc/sudo_logsrvd.mdoc.in,
+ doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ doc/sudo_plugin_python.man.in, doc/sudo_plugin_python.mdoc.in,
+ doc/sudo_sendlog.man.in, doc/sudo_sendlog.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, doc/visudo.man.in,
+ doc/visudo.mdoc.in:
+ Standardize on "front-end" not "front end" in the man pages.
+ [68748f8cc8a6]
+
+ * MANIFEST, plugins/sudoers/regress/testsudoers/test16.out.ok,
+ plugins/sudoers/regress/testsudoers/test16.sh:
+ Add a test to exercise Bug #994
+ [eef2ece0e8d4]
+
+ * scripts/mkpkg:
+ mkpkg: limit the number of cores used to 16
+ [5b8f2aa834b8]
+
+2021-09-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ fix typo
+ [120b1e7d2aca]
+
+ * .hgtags:
+ Added tag SUDO_1_9_8p1 for changeset feb396a0d60d
+ [e5f560a935fc] <1.9>
+
+ * configure, configure.ac:
+ Merge sudo 1.9.8p1 from tip
+ [feb396a0d60d] [SUDO_1_9_8p1] <1.9>
+
+ * NEWS:
+ Bug #994.
+ [14ea3a741b25]
+
+ * plugins/sudoers/ldap_util.c:
+ Always allocate a struct sudo_command for the command, even for ALL.
+ This was missed in the previous set of changes, resulting in a crash
+ for LDAP and SSSD rules that give sudo "ALL" privileges. Bug #994.
+ [91d0379b068a]
+
+ * plugins/sudoers/Makefile.in:
+ Add SUDOERS_LDFLAGS to FUZZ_LDFLAGS Fixes a fuzzer link error when
+ building with ldap if the ldap libs are not in the default library
+ search path.
+ [a450881f9763]
+
+ * configure, configure.ac:
+ Fix the OpenSSL link order for the non-pkg-config case. Since -lssl
+ depends on -lcrypto, -lcrypto must be listed after -lssl. Fixes
+ linking of non-dynamic OpenSSL libs.
+ [787724ab6e87]
+
+2021-09-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.8p1
+ [fc8c69d55348]
+
+ * src/sudo_intercept_common.c:
+ sudo_interposer_init: verify message type from sudo We should only
+ get a HelloResponse from sudo at this point.
+ [a021319260b3]
+
+ * include/intercept.pb-c.h, src/exec_intercept.c,
+ src/intercept.pb-c.c, src/intercept.proto,
+ src/sudo_intercept_common.c:
+ Avoid symbol name clash to fix --enable-static-sudoers linking.
+ [5cc5e415844f]
+
+2021-09-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/policy.c:
+ append_defaults() should not be passed a value for boolean flags.
+ The operation should simply be set to true/false. Also treat a NULL
+ file as coming from the front-end. Bug #993.
+ [86e69d358916]
+
+2021-09-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac, plugins/python/Makefile.in,
+ scripts/mkdep.pl, src/Makefile.in:
+ Teach mkdep.pl about --tag=disable-static in LTFLAGS. If static objs
+ are disabled we need to add explicit dependencies for .o files. The
+ OpenBSD libtool doesn't use a pic object file when linking
+ executables so we need to build the non-pic objects too.
+ [cdefeeb41a64]
+
+ * configure, configure.ac:
+ Use SUDO_APPEND_LIBPATH when appending to LIBTLS and LIBMD. The
+ OpenSSL pkgconfig files only include -L paths, not -R paths. Using
+ SUDO_APPEND_LIBPATH ensures the rpath is set correctly so the
+ binaries will run (not just link).
+ [29d051972287]
+
+ * INSTALL, configure, configure.ac:
+ Add --enable-openssl-pkgconfig-template option. This can be used to
+ find the correct openssl pkg-config file if it is not named
+ "openssl" (also libcrypto).
+ [77cd3463cefa]
+
+ * plugins/sudoers/getdate.c, plugins/sudoers/getdate.y:
+ Some POSIX yacc fixes for bison 3.8 yyerror() must be extern void
+ declare tokens with type instead of using separate %type lines
+ [c4e57f9e7df5]
+
+2021-09-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_8 for changeset e25cff5d148b
+ [4067d7a889fa] <1.9>
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h,
+ logsrvd/tls_init.c, plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Merge sudo 1.9.8 from tip
+ [e25cff5d148b] [SUDO_1_9_8] <1.9>
+
+ * .gitignore, .hgignore:
+ Add src/intercept.exp to ignore files.
+ [4eaa182a8808]
+
+2021-09-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/cs.mo:
+ regen
+ [8c168099301b]
+
+ * NEWS:
+ Mention --enable-static-sudoers fix.
+ [c93a42253fd0]
+
+ * configure, configure.ac:
+ Fix typo introduced in 1.9.7 that set SUDO_LDFLAGS to
+ SUDOERS_LDFLAGS. Copy pasta is not always the best kind of pasta.
+ [08188442f77b]
+
+ * MANIFEST, configure, configure.ac, m4/sudo.m4, src/Makefile.in,
+ src/intercept.exp, src/intercept.exp.in, src/sudo_intercept.c:
+ sudo_intercept.so: only replace execvpe() if it is present.
+ execvpe() is a GNU extension also found on *BSD (but not macOS).
+ [26153ad9c6ca]
+
+ * NEWS:
+ We now intercept more than just execve().
+ [33e453f035f8]
+
+2021-09-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sudo_intercept.c:
+ Implement simple PATH resolution for execvp(). We want to use PATH
+ from the current value of the environment, not the initial value of
+ PATH when the policy was opened. This is a little different from how
+ real execvp() works since we use stat() instead of just execve().
+ [fae58e1962cc]
+
+ * doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in, src/intercept.exp, src/sudo_intercept.c:
+ Add support for execl, execle, execlp, execvp, and execvpe.
+ Currently, PATH traversal is handled by sudoers which uses the
+ original PATH, not the one updated by the shell.
+ [59dfbbd39bf6]
+
+2021-09-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y:
+ Remove conditional include of alloca.h, we don't define
+ HAVE_ALLOCA_H. The configure check for alloca() was removed long ago
+ but this got missed.
+ [4c64529df149]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Define RBAC and mention incompatibility with intercept/log_subcmds.
+ [a44d8f96cad6]
+
+2021-09-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_intercept.c:
+ Fix computation of the token address when handling a partial read.
+ We want to treat it as an array of bytes, not an array of tokens.
+ Coverity CID 240011
+ [0bb3fb3315ce]
+
+ * plugins/sudoers/parse.c:
+ Quiet a PVS-Studio format string warning.
+ [4e445c646dc8]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ Regen .pot files.
+ [4cec17bc24da]
+
+ * plugins/sudoers/po/cs.po:
+ Updated translations from translationproject.org
+ [62fdbab57411]
+
+2021-09-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/Makefile.in:
+ regen
+ [a2f37ca5473b]
+
+ * configure, configure.ac, lib/util/sudo_conf.c, scripts/mkdep.pl,
+ src/Makefile.in, src/exec_common.c, src/exec_intercept.c:
+ Do not compile intercept code if --disable-intercept is specified.
+ [9d31e2822c24]
+
+ * doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in:
+ We now intercept execv() too.
+ [f0eac891cb5c]
+
+ * INSTALL:
+ INSTALL: --disable-intercept will also disable "log_subcmds"
+ [55ddfdae455d]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/parse.c:
+ Can't use intercept or log_subcmds with SELinux RBAC. SELinux policy
+ will prevent the inherited socket from sudo from being used and may
+ also restrict the ability to connect back to the sudo process.
+ [b73409172859]
+
+ * m4/ax_prog_cc_for_build.m4:
+ Fix typo in comment.
+ [3259f09e6952]
+
+ * po/cs.mo, po/cs.po:
+ Updated translations from translationproject.org
+ [7543d0d50ee2]
+
+ * include/intercept.pb-c.h, src/exec_intercept.c,
+ src/intercept.pb-c.c, src/intercept.proto, src/sudo_exec.h,
+ src/sudo_intercept_common.c:
+ Switch to a 128-bit token instead of a 64-bit secret. Protobuf
+ doesn't have a 128-bit type so use two u64s. We now support partial
+ reads of the token.
+ [e39ece25fb3b]
+
+2021-08-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, lib/util/Makefile.in, lib/util/regress/uuid/uuid_test.c,
+ lib/util/uuid.c:
+ Fix random uuid generation, no need to convert between byte order.
+ Also add regression test.
+ [fd2940acffc2]
+
+ * include/intercept.pb-c.h, src/exec_intercept.c,
+ src/intercept.pb-c.c, src/intercept.proto,
+ src/sudo_intercept_common.c:
+ sudo_intercept.so: send the secret immediately after connecting.
+ Sending the secret out of band, before the message size is read,
+ should make it harder to mount a DoS attack.
+ [4c8b6577bd8c]
+
+ * src/sudo_intercept_common.c:
+ Handle reading large messages that don't fit in a single recv(). We
+ know the length of what we are receiving so just loop until we have
+ it all, get EOF or an error.
+ [1b8aa927ea83]
+
+ * configure, configure.ac:
+ Add checks for -fstack-clash-protection and -Wl,-z,noexecstack We
+ use -Wc,-fstack-clash-protection as the linker flag to prevent
+ libtool from removing it from the link line.
+ [7cd701b5039e]
+
+ * src/exec_intercept.c:
+ Make the sudo side of the intercept socket non-blocking.
+ [3fe7129ea1f2]
+
+ * src/exec_intercept.c:
+ Handle partial read/write by dropping back into the event loop.
+ [fa216d963e18]
+
+ * src/exec_intercept.c:
+ intercept_check_policy: Fix double free introduced in last commit If
+ the command is not accepted we don't rebuild command_info[] and must
+ not free it. It will be freed by the policy instead.
+ [8bbd2af0924b]
+
+2021-08-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/intercept.pb-c.h, src/exec_intercept.c,
+ src/intercept.pb-c.c, src/intercept.proto,
+ src/sudo_intercept_common.c:
+ Update runcwd in command_info[] before passing it to the audit
+ plugin. Since sudoers does rejected commands itself the runcwd will
+ still not be correct for those.
+ [5462a5e1d760]
+
+ * src/exec_preload.c:
+ Fix LD_PRELOAD formatting when there is an existing LD_PRELOAD var.
+ [04d8d7750ff6]
+
+2021-08-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_intercept.c:
+ intercept_check_policy: fix potential NUL dereference on the error
+ path.
+ [4d1b3f39ccb1]
+
+ * NEWS, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/policy.c, src/exec.c,
+ src/exec_common.c, src/exec_nopty.c, src/exec_pty.c, src/sudo.c,
+ src/sudo.h:
+ Rename log_children -> log_subcmds
+ [abd73fc939c3]
+
+ * plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt.mo, plugins/sudoers/po/pt.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ plugins/sudoers/po/zh_TW.mo, plugins/sudoers/po/zh_TW.po, po/eo.mo,
+ po/eo.po, po/fr.mo, po/fr.po, po/hr.mo, po/hr.po, po/ko.mo,
+ po/ko.po, po/pl.mo, po/pl.po, po/pt.mo, po/pt.po, po/pt_BR.mo,
+ po/pt_BR.po, po/tr.mo, po/tr.po, po/uk.mo, po/uk.po, po/zh_CN.mo,
+ po/zh_CN.po, po/zh_TW.mo, po/zh_TW.po:
+ Updated translations from translationproject.org
+ [f948528780fb]
+
+ * lib/util/sudo_debug.c:
+ Add sudo_debug_register_v2() stub for fuzzing build.
+ [ba522c0c2075]
+
+ * src/exec_intercept.c:
+ Fix use-after-free on error. Also remove useless free of a ptr that
+ is always NULL on the error path.
+ [75200535be80]
+
+ * src/exec_common.c:
+ No longer need to remap intercept fd but we do need to remap debug
+ fd. The intercept fd is closed in the ctor but the debug fd will
+ still be open.
+ [b48125b884f3]
+
+ * include/sudo_debug.h, lib/util/sudo_debug.c, lib/util/util.exp.in,
+ logsrvd/logsrvd.c, logsrvd/sendlog.c,
+ plugins/audit_json/audit_json.c, plugins/python/sudo_python_debug.c,
+ plugins/sample_approval/sample_approval.c,
+ plugins/sudoers/sudoers_debug.c, plugins/sudoers/sudoreplay.c,
+ src/sesh.c, src/sudo.c, src/sudo_intercept_common.c:
+ sudo_debug_register: add minfd argument to specify lowest fd number
+ Use this in sudo_intercept.so to avoid allocating a low-numbered fd
+ which the shell reserves for use by scripts.
+ [50b23c4d0531]
+
+ * src/exec_intercept.c:
+ Fix command name of sub-command in logs when log_children is set.
+ [c1b35686d8b4]
+
+2021-08-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/audit.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h:
+ log_allowed: pass struct eventlog * instead of argv[] and envp[].
+ This lets us log based on the command_info[] list passed in from the
+ front-end. Previously, much of the struct eventlog was constructed
+ from internal sudoers state instead.
+ [4c4a7ddfeba3]
+
+ * include/sudo_compat.h:
+ sudo_compat.h: include unistd.h on HP-UX to safely redefine
+ pread/pwrite HP-UX 11.31 defines static functions for pread() and
+ pwrite() which will conflict with our macros.
+ [2dd64cdc261f]
+
+ * config.h.in, configure, configure.ac, include/intercept.pb-c.h,
+ src/exec_intercept.c, src/exec_nopty.c, src/exec_pty.c,
+ src/intercept.pb-c.c, src/intercept.proto, src/sudo_exec.h,
+ src/sudo_intercept_common.c:
+ Change intercept IPC to use a localhost socket instead of inherited
+ fd. This allows intercept mode to work with shells that close all
+ open fds upon startup. The ctor in sudo_intercept.so requests the
+ port number and secret over the socket inherited from the parent
+ then closes it. For each policy request, a TCP connection is made to
+ the sudo parent process to perform the policy check. Child processes
+ re-use the TCP socket to request the port number and secret just
+ like the initial process started by sudo does.
+ [7e7e4a389f11]
+
+ * src/exec_intercept.c:
+ Add a state variable to intercept_closure, replaces policy_result.
+ [60fae103a4cd]
+
+ * plugins/sudoers/match_command.c:
+ command_matches: avoid printf("%s") of NULL in debug for sudo ALL.
+ [5c81c2c32b4c]
+
+ * Merge pull request #111 from commodo/fix-cflags
+
+ lib/util/Makefile.in: use host CFLAGS and CPPFLAGS for
+ mksig{name,list}
+ [ee86d28da792]
+
+2021-08-25 Alexandru Ardelean <ardeleanalex@gmail.com>
+
+ * lib/util/Makefile.in:
+ lib: util: Makefile.in: use host CFLAGS and CPPFLAGS for
+ mksig{name,list}
+
+ When cross-build support was added for mkig{name,list} was added,
+ the CFLAGS and CPPFLAGS should have been updated to the
+ HOSTCFLAGS/HOSTCPPFLAGS vars.
+
+ In a cross-build scenario, some of these flags don't match what the
+ compiler can understand (because they may be architecture specific)
+ and may fail the build.
+
+ Using the HOSTCFLAGS/HOSTCPPFLAGS works and builds successfully.
+ Also the output binary works on the target.
+
+ This is in continuation of
+ - https://github.com/sudo-project/sudo/pull/104
+ - https://github.com/sudo-project/sudo/pull/109
+
+ Signed-off-by: Alexandru Ardelean <ardeleanalex@gmail.com>
+ [f76870e1a6c5]
+
+2021-08-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_intercept.c:
+ Fold intercept_closure_reset() into intercept_close().
+ [ff00ab240672]
+
+ * src/exec_preload.c:
+ Fix typo that caused SUDO_INTERCEPT_FD to overwrite LD_PRELOAD.
+ [e4cd1043c7bb]
+
+ * src/exec_preload.c:
+ Fix off-by-one that could result in duplicate SUDO_INTERCEPT_FD
+ vars.
+ [9044d0dff708]
+
+ * src/sudo_intercept.c:
+ Fix typo in macOS execv change.
+ [1c637d909382]
+
+2021-08-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in, src/intercept.exp, src/sudo_intercept.c:
+ Add execv(3) support to sudo_intercept.so. This allows intercept to
+ work with csh which uses execv(3) not execve(2).
+ [690ebf72b6f8]
+
+2021-08-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in:
+ Sync the list of functions trapped by sudo_noexec.so.
+ [b1f7799209ff]
+
+ * doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in:
+ Add a Debug example for sudo_intercept.so Don't try to enumerate all
+ the sudo programs that support debugging since all of them do.
+ [9c1201eaaca2]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Update sudoers Debug example to match the debug changes from sudo
+ 1.8.12.
+ [7c831aa9b6d5]
+
+ * doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in:
+ sudo_intercept.so only intercepts execve(2) for now.
+ [7314abc72fb9]
+
+ * plugins/sudoers/parse.c:
+ Fix formatting for bound defaults with multiple entries in the
+ binding. The entries in the binding were separated with " ," instead
+ of ", ".
+ [14442701f793]
+
+ * MANIFEST, src/Makefile.in, src/intercept.exp:
+ Add exports file for sudo_intercept.so that only exports execve()
+ [ac97417435ab]
+
+ * src/Makefile.in, src/sudo_intercept.c, src/sudo_intercept_common.c:
+ Add some debugging to the sudo_intercept.so.
+ [2dee003b5cc7]
+
+ * config.h.in, configure, configure.ac:
+ Use AC_FUNC_FSEEKO instead of AC_CHECK_FUNCS_ONCE([fseeko]). This
+ will define _LARGEFILE_SOURCE, if needed, to make the prototype
+ visible on older systems.
+ [3f4314f6a795]
+
+2021-08-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h:
+ We still need the pread/pwrite hack for HP-UX 11.11 at least. This
+ time around, avoid defining _LARGEFILE64_SOURCE and just declare
+ pread64/pwrite64 ourselves.
+ [66e01b14a10f]
+
+ * include/sudo_compat.h:
+ Fix prototypes for sudo_pread() and sudo_pwrite().
+ [15acfc576a71]
+
+ * src/exec_intercept.c:
+ intercept_fd_cb: store the passed fd in newfd, not fd only affects
+ the old BSD-style fd passing code, not POSIX-style.
+ [4b13aa4593ba]
+
+ * lib/util/Makefile.in:
+ Fix mksiglist and mksigname dependencies.
+ [31519cc5ec2b]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ set-user-ID and set-group-ID not set user-ID and set group-ID.
+ [0ddf5fedc896]
+
+ * NEWS:
+ The fix for bug #989 will make sudo 1.9.8. Also mention
+ intercept_authenticate and intercept_allow_setid.
+ [fa8b7444486b]
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [c8993c070218]
+
+ * .gitignore, .hgignore, MANIFEST, aclocal.m4, configure,
+ configure.ac, lib/util/Makefile.in, lib/util/mksiglist.c,
+ lib/util/mksiglist.h, lib/util/mksigname.c, lib/util/mksigname.h,
+ lib/util/sys_siglist.h, lib/util/sys_signame.h,
+ m4/ax_prog_cc_for_build.m4:
+ Cross-build support for mksigname and mksiglist We must build these
+ with the host C compiler but use the target preprocessor to generate
+ the output.
+ [bf2919b63fb9]
+
+2021-08-19 a1346054 <36859588+a1346054@users.noreply.github.com>
+
+ * .clang-format, INSTALL, MANIFEST, autogen.sh, doc/LICENSE,
+ etc/sudo.pp, examples/Makefile.in:
+ Minor cleanup (#110)
+
+ * fix trivial shell script issues
+ * remove trailing whitespace
+ [f9d4de3dee50]
+
+2021-08-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd_conf.c, plugins/sudoers/check.c,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/exptilde.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/logging.c,
+ plugins/sudoers/mkdefaults, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/tsdump.c:
+ Replace messages like "unknown foo: %s" with "unknown foo %s". The
+ colon really doesn't belong there; we generally use a colon to
+ separate a message from the warning detail.
+ [a1b99c8821ae]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ log_server_peer_cert and log_server_peer_key are not required by
+ default. They are only required if sudo_logsrvd has tls_checkpeer
+ enabled.
+ [0d9099ce5d74]
+
+ * logsrvd/logsrvd_conf.c:
+ Sync warning messages with sudoers/logging.c Avoids 3 translation
+ strings that were effectively duplicated.
+ [eb058a820998]
+
+2021-08-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/protobuf-c/Makefile.in, src/Makefile.in:
+ regen
+ [ab9d4b22d7cb]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/match_command.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ Add intercept_allow_setid sudoers option, disabled by default. With
+ this change, a shell in intercept mode cannot run a setuid or setgid
+ binary by default. On most systems, the dynamic loader will ignore
+ LD_PRELOAD for setuid/setgid binaries such as sudo which would
+ effectively disable intercept mode.
+ [cdb876f62882]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/match.c:
+ Always allocate a struct sudo_command for the command, even for ALL.
+ Previously we special-cased handling of ALL but this complicates
+ some upcoming changes.
+ [d552109d739c]
+
+2021-08-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * etc/codespell.exclude:
+ Update TAGS_CHANGED macro based on parse.h
+ [261e4bad3f55]
+
+ * doc/sudo.man.in, doc/sudo.mdoc.in, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in:
+ Better document the limitations of intercept mode. Also mention
+ log_children under "Preventing shell escapes"
+ [0dfca8d0672d]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ Update .pot files for 1.9.8.
+ [ed2582c37765]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Try to clarify log_server_peer_key and log_server_peer_cert. These
+ are client-side not server-side.
+ [ffa4ee3e2557]
+
+ * logsrvd/logsrvd_conf.c:
+ Print the section when warning about an illegal key in the conf
+ file. This should make it easier to tell when a setting is present
+ in the wrong section.
+ [8150a7775155]
+
+2021-08-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/eventlog/eventlog.c:
+ new_logline: limit offset to two significant digits after the
+ decimal Now instead of TSID=0001L3@5.168230749 we would log
+ TSID=0001L3@5.16.
+ [089f7a1285cb]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c,
+ logsrvd/logsrvd_journal.c:
+ Set umask to be less restrictive before creating parent directories.
+ Otherwise we could end up creating them with a more restrictive mode
+ than indended. Coverity CID 221592
+ [1bbb3621106a]
+
+ * lib/eventlog/eventlog.c:
+ new_logline: handle case where evlog is NULL
+ [e14ded2179e8]
+
+ * logsrvd/logsrvd_local.c:
+ store_alert_local: fix memory leak on error path Coverity CID 238642
+ [2a3c7fb50c38]
+
+ * plugins/sudoers/audit.c:
+ log_server_accept: fix memory leak of evlog when logging a sub-
+ command. Coverity CID 238643
+ [36a7325b3dc2]
+
+ * src/exec_intercept.c:
+ Fix memory leak when client requests secret. Move closure allocation
+ closer to where it is used.
+ [773ffe0cb216]
+
+ * logsrvd/logsrvd_local.c:
+ store_accept_local: fix return value on error
+ [de0d06a1ade2]
+
+2021-08-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/eventlog/eventlog.c:
+ Cast iolog_offset.tv_sec to long long for %lld printf format. Quiets
+ a compiler warning on systems where tv_sec in struct timeval is not
+ long long.
+ [54d757357a00]
+
+ * doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in,
+ lib/iolog/iolog_timing.c, plugins/sudoers/sudoreplay.c:
+ Add support for an optional offset when parsing the ID to replay.
+ The offset is a suffix in the form of @sec[.nanosec]
+ [f8cda41ea0ae]
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c,
+ logsrvd/logsrvd_local.c, plugins/sudoers/logging.c:
+ For intercepted commands, log an offset into the current I/O log.
+ This can be used with sudoreplay to jump to when a specific command
+ was executed within a session log.
+ [fd9431d7c878]
+
+ * logsrvd/logsrvd_local.c:
+ Don't overwrite closure->evlog for sub-commands.
+ [925c97582b1d]
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h:
+ Older Solaris has getusershell() et al but does not declare it.
+ [df4cd6a5e07f]
+
+ * src/exec_intercept.c, src/exec_nopty.c, src/exec_pty.c,
+ src/sudo_intercept_common.c:
+ Add missing stdint.h and sudo_rand.h includes. Needed for
+ arc4random() and uin64_t.
+ [47fd965524fe]
+
+ * include/intercept.pb-c.h, src/exec_intercept.c, src/exec_nopty.c,
+ src/exec_pty.c, src/intercept.pb-c.c, src/intercept.proto,
+ src/sudo_exec.h, src/sudo_intercept_common.c:
+ Pass a secret value to sudo_intercept.so and verify after policy
+ check. The goal is to make it harder for someone to have a fake
+ policy checker. This will not stop a determined adversary since the
+ secret is present in the address space of the running process.
+ [7938c63384df]
+
+2021-08-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, src/Makefile.in, src/exec.c, src/exec_intercept.c:
+ Split off intercept code into exec_intercept.c.
+ [2c05715c4885]
+
+ * scripts/mkpkg:
+ Add trivial support for FreeBSD packages. The actual FreeBSD port
+ supports multiple options but this is sufficient for testing
+ purposes.
+ [6bb8a1cdf26c]
+
+ * scripts/pp:
+ FreeBSD: Set default directory and file mode if not specified in
+ %files Otherwise, a mode of 0 will be used, potentially rendering
+ the system unusable.
+ [a3be86a5f85f]
+
+ * plugins/sudoers/logging.c:
+ Use same check for intercepted commands as log_server_accept().
+ Previously, log_server_reject() and log_server_alert() just checked
+ whether client_closure has been set.
+ [41177f7c32f4]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd_relay.c, logsrvd/sendlog.c,
+ plugins/sudoers/log_client.c:
+ Call shutdown() on sockets before closing() if they are connected.
+ This should ensure that the other side sees any queued data before
+ the connection is dropped.
+ [beaafc6c17cf]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd_relay.c, logsrvd/sendlog.c,
+ plugins/sudoers/log_client.c:
+ If SSL_shutdown() returns 0 it needs to be called one more time.
+ [52bb0acfb659]
+
+ * plugins/sudoers/editor.c:
+ resolve_editor: sudoers_gc_remove(editor) before freeing it.
+ [534cc939264f]
+
+2021-08-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/mksigname.h, lib/util/siglist.in:
+ Sync siglist.in with the generated files. The change to prefer
+ SIGSYS over SIGUNUSED wasn't made to siglist.in. Also, mksigname.c
+ doesn't need to explicitly set sudo_sys_signame[0].
+ [c331b05f8fc5]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/editor.c,
+ plugins/sudoers/gc.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Add garbage collection to resolve_editor(). Fixes a leak when
+ evaluating the policy multiple times if sudoedit is set.
+ [ab011d864e87]
+
+2021-08-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_common.c:
+ Fix compilation when configure option --disable-shared is specified.
+ [98687e01c8e4]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/check.c,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Add intercept_authenticate sudoers option, defaults to false. By
+ default, sudoers will not require authentication of commands run via
+ an intercepted session. To require authenticaton of subsequent
+ commands, enable intercept_authenticate in sudoers.
+ [b428c75da1ad]
+
+ * config.h.in, configure, configure.ac, src/exec.c,
+ src/sudo_intercept_common.c:
+ If msg_control is not present in struct msghdr use msg_accrights
+ instead. Fixes building on Solaris and probably others. It is
+ possible to expose msg_control on Solaris but this requires a
+ specific set of feature flag defines which can cause other
+ complications.
+ [6ee77b869a8c]
+
+ * configure, configure.ac, src/exec_preload.c:
+ Require that our dso be first in the list to make sure it takes
+ effect. Otherwise, another dso could take precedence and ours would
+ not be run.
+ [58ba4086357c]
+
+ * configure, configure.ac, pathnames.h.in, src/Makefile.in,
+ src/exec_preload.c:
+ If building with address sanitizer make sure its DSO is first.
+ Address sanitizer requires that it be preloaded before any other DSO
+ in LD_PRELOAD. This should not be required for clang, which links in
+ asan statically by default.
+ [a812062f42a8]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c:
+ Plug some memory leaks when sudoers_policy_main is called multiple
+ times. These would get cleaned up a policy close time but we don't
+ want to bloat sudo's memory footprint when running a shell with
+ multiple commands.
+ [7fee001ffeae]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/log_client.c, plugins/sudoers/log_client.h,
+ plugins/sudoers/logging.c:
+ Fix logging intercepted commands to a log server in sudoers. Only
+ available when the server supports the subcommands capability.
+ [5975770561de]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h:
+ Use a separate uuid for intercepted commands. We use the uuid to
+ match the command with its exit status.
+ [467f0db6e2c6]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c:
+ Avoid some double frees in the fuzzer Now that sudoers free old
+ values of NewArgv and command_info the fuzzer needs to reset those
+ values. Otherwise we end up with stashed values that have already
+ been garbage collected.
+ [2a1b5808d272]
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.8
+ [bc96c8f95abf]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/fmtsudoers.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.h, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/policy.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l:
+ Add "intercept" Defaults setting to allow interception of sub-
+ commands. This causes "intercept" to be set to true in
+ command_info[] which the sudo front-end will use to determine
+ whether or not to intercept attempts to run further commands, such
+ as from a shell. Also add "log_children" which will use the same
+ mechanism but only log (audit) further commands.
+ [f42e11c0fde9]
+
+ * INSTALL, configure, configure.ac, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in, examples/sudo.conf.in, include/sudo_conf.h,
+ lib/util/sudo_conf.c, lib/util/util.exp.in, pathnames.h.in,
+ src/Makefile.in, src/exec.c, src/exec_common.c, src/selinux.c,
+ src/sesh.c, src/sudo.c, src/sudo.h, src/sudo_exec.h:
+ Add support for loading the sudo_intercept.so DSO.
+ [47d84cc8a8ed]
+
+ * include/sudo_compat.h, src/exec.c, src/exec_common.c,
+ src/exec_monitor.c, src/exec_nopty.c, src/exec_pty.c, src/selinux.c,
+ src/sesh.c, src/sudo_exec.h:
+ Allocate a socketpair to communicate with sudo_intercept.so over.
+ This is used for the intercept and log_children options.
+ [b40091760952]
+
+ * plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/file.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/ldap_util.c, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudo_ldap.h, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Make it possible to call the sudoers policy check function multiple
+ times. We need to reset the Defaults values to their original state.
+ [3187e87d7fb6]
+
+ * plugins/sudoers/set_perms.c:
+ Allow set_perms(PERM_INITIAL) to be called more than once. If the
+ perm stack depth is non-zero when set_perms(PERM_INITIAL) is called,
+ rewind it first and re-initialize the stack depth to 0. Fixes a
+ user-after-free bug if set_perms(PERM_INITIAL) is called multiple
+ times.
+ [fdf9a2e07eb1]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h:
+ Use run_argv and run_envp passed into the audit plugin for event
+ logging. Previously we used NewArgv[] and env_get() but now that
+ logging is performed via an audit plugin we should use the values
+ passed in.
+ [d8e031fc2389]
+
+ * doc/sudo_logsrv.proto.man.in, doc/sudo_logsrv.proto.mdoc.in,
+ include/log_server.pb-c.h, lib/logsrv/log_server.pb-c.c,
+ lib/logsrv/log_server.proto, logsrvd/logsrvd.c:
+ Allow multiple accept/reject messages during a logsrv conversation.
+ The log server now advertises a subcommands flag if it supports
+ logging subcommands (e.g. commands run from a sudo-spawned program
+ like a shell). The client should only log additional commands during
+ a session if this flag is set in the ServerHello message.
+ [5b88982604e8]
+
+ * MANIFEST, Makefile.in, configure, configure.ac,
+ lib/logsrv/Makefile.in, lib/logsrv/protobuf-c.c,
+ lib/protobuf-c/Makefile.in, lib/protobuf-c/protobuf-c.c:
+ Add separate convenience lib for protobuf-c We need to use it for
+ sudo <-> sudo_intercept.so communication.
+ [9529d7f9db18]
+
+ * MANIFEST, include/intercept.pb-c.h, src/Makefile.in,
+ src/intercept.pb-c.c, src/intercept.proto:
+ Define protocol for sudo <-> sudo_intercept.so communication. Uses
+ google protocol buffers.
+ [139ba292e226]
+
+ * src/exec.c, src/sudo.c, src/sudo.h:
+ Implement the sudo side of the sudo_intercept.so communication.
+ [4a7face9ed17]
+
+ * MANIFEST, src/Makefile.in, src/exec.c, src/exec_common.c,
+ src/sudo_exec.h, src/sudo_intercept.c, src/sudo_intercept_common.c:
+ Implement sudo_intercept.so. Uses protobuf to talk to main sudo
+ process over a socketpair.
+ [fc21ae0f663e]
+
+ * src/sudo.c, src/sudo.h:
+ Add return values for most of the plugin function wrappers that
+ returned void. Previously, they would just exit if there was an
+ error. Now the error is passed back up the stack so we can use them
+ in sudo_intercept.so.
+ [87cb4b0e7dff]
+
+ * src/sudo.c:
+ Reduce the number of function args passed to plugin wrappers. This
+ makes sudo_settings, user_info, submit_argv, submit_envp and
+ submit_optind global. This will be required for calling the wrapper
+ from outside of sudo.c where we may not have access to those
+ variables.
+ [525bffcf911c]
+
+ * src/exec.c, src/sudo.c, src/sudo.h:
+ Call the approval plugin after the policy plugin accepts a command.
+ Previously, for intercepted commands we only called the policy
+ plugin.
+ [4df18aaa8708]
+
+ * src/exec.c:
+ Take control of the tty and save its settings before doing a policy
+ check. Otherwise the policy plugin won't be able to read the
+ password.
+ [6a422974d472]
+
+ * MANIFEST, src/Makefile.in, src/exec_common.c, src/exec_preload.c,
+ src/sudo_exec.h, src/sudo_intercept.c, src/sudo_intercept_common.c:
+ Move preload_dso() to its own file and rename to sudo_preload_dso().
+ It now takes an intercept fd as an optional argument instead of a
+ list of extra variables to add. This lets us check whether it is
+ already set to the expected value (and add it if not).
+ sudo_intercept.so now uses sudo_preload_dso() to make sure that
+ LD_PRELOAD and SUDO_INTERCEPT_FD are set properly before executing.
+ [447e96378d01]
+
+ * src/exec_preload.c, src/sudo_intercept_common.c:
+ Add debug support to sudo_intercept.so
+ [586ea125cebb]
+
+ * src/exec.c, src/exec_nopty.c, src/exec_pty.c:
+ Make the log_children option only log and not check policy.
+ [0524c7e87174]
+
+ * plugins/sudoers/prompt.c:
+ expand_prompt: use correct strlcpy() size parameter The available
+ size passed to strlcpy() was computed incorrectly. Switch to
+ updating the length after writing to the new prompt instead of
+ computing it each time. The actual buffer size is computed and
+ allocated correctly so there is no real consequence to this bug.
+ Found by Qualys.
+ [c03f1c2f8f35]
+
+2021-08-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ examples/sudo_logsrvd.conf:
+ The tls_verify setting only affects server behavior, not the client.
+ Originally, there was a flag in the ServerHello message to indicate
+ that the client should verify the server cert, but this was removed
+ TLS was moved to a separate port. Client validation of the server
+ certificate is now configured in the sudoers file instead.
+ [344b51f3eee3]
+
+2021-08-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/mkpkg:
+ On macOS, don't disable tty tickets and set password timeout to 0.
+ This more closely matches the options used by the macOS version of
+ sudo.
+ [bd21c492921c]
+
+ * plugins/sudoers/find_path.c:
+ Add some debugging info to find_path()
+ [dd7aebb432d6]
+
+2021-07-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/iolog_mkdtemp.c:
+ iolog_mkdtemp: umask must not be more restrictive than the file
+ modes. We need this even though we will be calling mkdtemp() since
+ the umask affects the mode of any parent directories.
+ [c545b3369eae]
+
+2021-07-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/visudo.c:
+ Plug memory leak in error path when sudoers cannot be opened.
+ [3df6b32149b8]
+
+ * plugins/sudoers/defaults.c:
+ Trying to use "+=" or "-=" operators on a non-list is an error.
+ Previously, they were simply treated as "=" for non-lists.
+ [3e0d47d0b4ea]
+
+ * src/regress/net_ifs/check_net_ifs.c:
+ Plug a memory leak in check_net_ifs found by address sanitizer.
+ [bff1ad993476]
+
+ * configure, configure.ac:
+ Prefix sanitizer and fuzzer options with -XCClinker in ASAN_LDFLAGS.
+ Otherwise libtool may ignore the options when linking.
+ [ed1120f3813d]
+
+2021-07-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/tls_init.c:
+ Display the correct error message if X509_verify_cert() fails. We
+ must use X509_STORE_CTX_get_error() and
+ X509_verify_cert_error_string() instead of the generic OpenSSL error
+ functions.
+ [778bbbe68e28]
+
+ * lib/eventlog/eventlog.c:
+ In new_logline check for NULL args->reason for EVLOG_RAW. This can't
+ happen in practice since we never set EVLOG_RAW without passing in a
+ reason. Coverity CID 237142 237143
+ [83f9038151db]
+
+ * lib/eventlog/eventlog.c:
+ format_json: don't dereference evlog if it is NULL. Also silence a
+ PVS Studio false positive.
+ [150039f65d26]
+
+2021-07-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_7p2 for changeset 590e06825ec4
+ [cf3865846c94] <1.9>
+
+ * configure, configure.ac:
+ Bump version to 1.9.7p2
+ [590e06825ec4] [SUDO_1_9_7p2] <1.9>
+
+ * configure, configure.ac:
+ Bump version to 1.9.7p2
+ [388bf6af8434]
+
+ * NEWS:
+ Sudo 1.9.7p2
+ [c3bd2eb0d779] <1.9>
+
+ * NEWS:
+ Sudo 1.9.7p2
+ [153a6c96a8ec]
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h,
+ logsrvd/tls_client.c, logsrvd/tls_init.c,
+ plugins/sudoers/log_client.c:
+ Use TLS_method() instead of TLS_client_method() throughout. OpenSSL
+ returns an error for SSL_accept() if TLS_client_method() was used to
+ generate the context (LibreSSL doesn't care).
+
+ Prior to sudo 1.9.7, TLS_client_method() and TLS_server_method()
+ were used in the TLS client and server initialization code
+ respectively. This was refactored in sudo 1.9.7 to allow the code to
+ be shared. Bug #988
+ [f2bf4aca30d4] <1.9>
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h,
+ logsrvd/tls_client.c, logsrvd/tls_init.c,
+ plugins/sudoers/log_client.c:
+ Use TLS_method() instead of TLS_client_method() throughout. OpenSSL
+ returns an error for SSL_accept() if TLS_client_method() was used to
+ generate the context (LibreSSL doesn't care).
+
+ Prior to sudo 1.9.7, TLS_client_method() and TLS_server_method()
+ were used in the TLS client and server initialization code
+ respectively. This was refactored in sudo 1.9.7 to allow the code to
+ be shared. Bug #988
+ [1ca00726b4d6]
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Only replace getaddrinfo for
+ FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION. This works around an issue
+ on SCO which uses inline functions in the header files which call
+ the actual, versioned, library function.
+ [f010d83f0168] <1.9>
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Only replace getaddrinfo for
+ FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION. This works around an issue
+ on SCO which uses inline functions in the header files which call
+ the actual, versioned, library function.
+ [64cbf884b7f9]
+
+2021-07-26 MertsA <andrewmerts@gmail.com>
+
+ * src/utmp.c:
+ Rewind utmp file pointer after searching for entry (#108)
+
+ getutline() advances the file pointer until it matches or reaches
+ EOF. pututline() starts from the current position in utmp. This
+ rewinds the file pointer to the beginning to avoid allocating
+ additional spurious utmp entries.
+ [af1463026fd1] <1.9>
+
+ * src/utmp.c:
+ Rewind utmp file pointer after searching for entry (#108)
+
+ getutline() advances the file pointer until it matches or reaches
+ EOF. pututline() starts from the current position in utmp. This
+ rewinds the file pointer to the beginning to avoid allocating
+ additional spurious utmp entries.
+ [142555f7a47e]
+
+2021-07-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac, m4/sudo.m4:
+ Use AC_CACHE_CHECK in place of AC_MSG_CHECKING + AC_CACHE_VAL where
+ possible.
+ [7b0fb8de8276]
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h:
+ Add configure check for va_copy instead of using #ifdef This
+ prevents the va_copy compat #define from being used if sudo_compat.h
+ is somehow included before stdarg.h.
+ [6d283753e47b] <1.9>
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h:
+ Add configure check for va_copy instead of using #ifdef This
+ prevents the va_copy compat #define from being used if sudo_compat.h
+ is somehow included before stdarg.h.
+ [fcfd53b859ac]
+
+2021-07-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/limits.c:
+ Avoid using RLIM_INFINITY for the nofile soft limit to prevent
+ closefrom_fallback() from closing too many file descriptors.
+ [edbcd5c82d4d] <1.9>
+
+ * src/limits.c:
+ Avoid using RLIM_INFINITY for the nofile soft limit to prevent
+ closefrom_fallback() from closing too many file descriptors.
+ [e807ca9bfb6a]
+
+ * plugins/sudoers/logging.c:
+ Include signal.h for SIG2STR_MAX and sig2str().
+ [ad17a1be07e2]
+
+2021-07-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c,
+ logsrvd/iolog_writer.c, plugins/sudoers/logging.c,
+ plugins/sudoers/policy.c, plugins/sudoers/sudoers.h:
+ Create a UUID and log it in the JSON version of the event log.
+ [8a1ad98fac51]
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c,
+ logsrvd/logsrvd_local.c, plugins/sudoers/logging.c:
+ Remove unused info_cb and info arguments from eventlog_exit()
+ [c614ef1afa12]
+
+2021-07-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c:
+ Add support for logging exit status events. For sudo-formatted logs,
+ this is a record with "EXIT=number" and potentially "SIGNAL=name"
+ after the command. For JSON-format logs, a new "exit" record is
+ logged which contains an "exit_value" and potentially "signal" and
+ "core_dumped". JSON-format logs now incude a UUID to associate the
+ "exit" record with the "accept" record.
+ [52e40ae4b79a]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Add log_exit_status sudoers option to log when a command exits. This
+ option defaults to off.
+ [cac3ca7ad193]
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ examples/sudo_logsrvd.conf, logsrvd/logsrvd.h,
+ logsrvd/logsrvd_conf.c, logsrvd/logsrvd_local.c:
+ Add log_exit setting in the sudo_logsrvd.conf eventlog stanza This
+ causes sudo_logsrvd to log a record with the exit status or
+ terminating signal in response to an ExitMessage.
+ [1a15f676974a]
+
+2021-07-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/python_plugin_common.c:
+ Check that the python module we actually loaded is what we intended.
+ This is intended to provide a more useful error message if the user
+ defines a module which conflicts with a system python module. For
+ example, a module called test.py would conflicts with the system
+ python test module.
+ [345523b6e87d] <1.9>
+
+ * plugins/python/python_plugin_common.c:
+ Check that the python module we actually loaded is what we intended.
+ This is intended to provide a more useful error message if the user
+ defines a module which conflicts with a system python module. For
+ example, a module called test.py would conflicts with the system
+ python test module.
+ [0676191e4741]
+
+2021-07-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/CONTRIBUTORS:
+ Mention that xkcd inspired the sandwich logo.
+ [c7839328e21f]
+
+ * doc/HISTORY:
+ Mention log server and fuzzers under Quest contributions.
+ [f4a081f75cd0]
+
+2021-06-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sesh.c, src/sudo.c, src/sudo_edit.c:
+ Don't assume that the number of groups returned by getgroups() is
+ static. On systems where getgroups() returns results based on more
+ than just the per-process group vector in the kernel it is possible
+ for the number of groups to change in between invocations. Based on
+ GitHub PR #106 from Pierre-Olivier Martel.
+ [832fa2480024] <1.9>
+
+ * src/sesh.c, src/sudo.c, src/sudo_edit.c:
+ Don't assume that the number of groups returned by getgroups() is
+ static. On systems where getgroups() returns results based on more
+ than just the per-process group vector in the kernel it is possible
+ for the number of groups to change in between invocations. Based on
+ GitHub PR #106 from Pierre-Olivier Martel.
+ [dbc7a173a7b8]
+
+ * doc/Makefile.in:
+ Use "mandoc -Tlint -Wwarning" instead of -Wstyle. The style checks
+ now include "referenced manual not found" warnings which is not
+ helpful.
+ [251757f22498]
+
+2021-06-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/Makefile.in, src/Makefile.in:
+ regen
+ [c6a21b385d57]
+
+2021-06-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/fuzzstub/fuzzstub.c:
+ Change ms from size_t to long. Avoids a spurious test failure on
+ Solaris 9
+ [5e204b959000] <1.9>
+
+ * lib/fuzzstub/fuzzstub.c:
+ Change ms from size_t to long. Avoids a spurious test failure on
+ Solaris 9
+ [c26f8d233ea9]
+
+ * plugins/sudoers/interfaces.c, src/net_ifs.c:
+ Move definition of INADDR_NONE from interfaces.c to net_ifs.c. Fixes
+ compilation on Solaris 9.
+ [d05bca21f145] <1.9>
+
+ * plugins/sudoers/interfaces.c, src/net_ifs.c:
+ Move definition of INADDR_NONE from interfaces.c to net_ifs.c. Fixes
+ compilation on Solaris 9.
+ [9da2276cf944]
+
+2021-06-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd.c:
+ Fix dead store found by clang analyzer.
+ [5c85aeef651e]
+
+ * logsrvd/logsrvd_conf.c:
+ Fix prefix skipping when the prefix is embedded and not separate.
+ This doesn't currently matter since the progname and the ": " are
+ stored in separate messages. Found by clang analyzer.
+ [321e90e1b347]
+
+ * logsrvd/logsrvd_relay.c:
+ Remove dead store found by clang analyzer.
+ [5fd56f26e1ba]
+
+2021-06-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/audit_json/audit_json.c:
+ Make sure we store an octal number (like umask) as a string. JSON
+ doesn't (portably) support octal numbers with a leading zero.
+ [a0c8392f2f7a] <1.9>
+
+ * plugins/audit_json/audit_json.c:
+ Make sure we store an octal number (like umask) as a string. JSON
+ doesn't (portably) support octal numbers with a leading zero.
+ [3ac37bb42f1e]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c,
+ logsrvd/regress/fuzz/fuzz_logsrvd_conf.c:
+ Replace logsrvd_is_early() with logsrvd_warn_stderr(). This is now
+ defined in logsrvd_conf.c which removes a dependency on another
+ compilation unit for the fuzzer.
+ [3594cf3ec397]
+
+2021-06-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd_local.c:
+ Silence a compiler warning on Solaris.
+ [fd9ba461b601]
+
+ * logsrvd/logsrvd.c:
+ Reduce scope of errstr variable so it is only declared for OpenSSL.
+ [eebe09a17f4b]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [05b8391c6d13]
+
+ * logsrvd/iolog_writer.c, logsrvd/logsrv_util.c, logsrvd/logsrvd.c,
+ logsrvd/logsrvd_conf.c, logsrvd/logsrvd_journal.c,
+ logsrvd/logsrvd_local.c, logsrvd/logsrvd_queue.c,
+ logsrvd/logsrvd_relay.c, logsrvd/sendlog.c, logsrvd/tls_init.c:
+ Use sudo_warnx?() instead of sudo_debug_printf for errors. We now
+ hook the warn functions so the messages are logged. The messages
+ still show up in the debug log too.
+ [9e25dc71b4cc]
+
+2021-06-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, lib/util/Makefile.in,
+ lib/util/regress/vsyslog/vsyslog_test.c, lib/util/vsyslog.c,
+ scripts/mkdep.pl:
+ Remove vsyslog(3) emulation, it is no longer used.
+ [7d1b78c2037a]
+
+2021-06-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd_conf.c, logsrvd/regress/fuzz/fuzz_logsrvd_conf.c:
+ If logsrvd_config not set fall back to using stderr for warnings.
+ Also fix fuzz_logsrvd_conf link error.
+ [eeaafe1b3e09]
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ examples/sudo_logsrvd.conf, logsrvd/logsrvd.c, logsrvd/logsrvd.h,
+ logsrvd/logsrvd_conf.c:
+ Add support for logging server warning/error messages. We can use
+ sudo_warn_set_conversation() to set a conversation function that
+ either writes to a log file or calls syslog().
+ [5d8e13f053d0]
+
+2021-06-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_7p1 for changeset d936a99e842d
+ [9bc246c519f3] <1.9>
+
+ * Merge sudo 1.9.7p1 from tip
+ [d936a99e842d] [SUDO_1_9_7p1] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.7p1
+ [29f478993ef3]
+
+2021-06-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/audit_json/audit_json.c:
+ Check arrays that are passed in for NULL before using them.
+ [925ba5b0f2cb]
+
+ * configure, configure.ac:
+ Disable nss_search()-based group lookups on HP-UX for now. There is
+ a crash when "group: compat" is used in /etc/nsswitch.conf that I
+ haven't been able to debug. Since HP-UX doesn't ship the appropriate
+ headers it is likely that there is a mismatch between
+ include/compat/nss_dbdefs.h and what HP actually uses.
+ [28b00005c785]
+
+2021-06-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h:
+ Remove logsrvd closure ERROR state and use a boolean flag instead.
+ Fixes a bug where we would not insert a journal file that failed to
+ relay into the queue because its state was changed from CONNECTING
+ to ERROR after failing to connect.
+ [638285a4bedb]
+
+ * include/compat/nss_dbdefs.h, lib/util/getgrouplist.c:
+ Add NSS_TRYAGAIN and correct buflen in struct nss_XbyY_buf_t. Add
+ some function argument names. Also use struct nss_db_state * instead
+ of void * in nss_db_root_t. We don't define struct nss_db_state but
+ since it is a pointer all we need is a forward declaration.
+ [bc848fb97671]
+
+2021-06-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/fuzzstub/fuzzstub.c, lib/iolog/Makefile.in,
+ lib/util/Makefile.in, logsrvd/Makefile.in:
+ Make sure we link with libsudo_util *after* libfuzzstub. This only
+ affects builds with a static libsudo_util. Also fix a warning on HP-
+ UX about main not being public.
+ [18ff1f108c4e]
+
+ * MANIFEST, lib/util/Makefile.in,
+ lib/util/regress/getgrouplist/getgids.c:
+ Add getgids utility to simular "id -G" using sudo_getgrouplist2()
+ [aed11065818d]
+
+ * lib/util/getgrouplist.c:
+ Make sure we don't read or write past the end of the group buffer.
+ We need to leave room for the terminating NULL in gr_mem. It is
+ possible for gbm->numgids > gbm->maxgids if we ran out of room.
+ [25a3ee849fd4]
+
+2021-06-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/getgrouplist.c:
+ Add some debugging to sudo_getgrouplist2().
+ [4d79e92c8ee8]
+
+2021-06-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/load_plugins.c:
+ Fix some debug_decl typos and remove an unneeded cast.
+ [fafa91ac3def]
+
+ * plugins/sudoers/defaults.h:
+ T_TIMEOUT is not a bitwise flag so doesn't need to be a power of 2.
+ [66019af6d642]
+
+2021-05-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/load_plugins.c:
+ sudo_stat_plugin(): set errno but do not warn if plugin path too
+ long. The caller will display the warning (using errno) so there is
+ no need to do it twice.
+ [c8614b374a35]
+
+2021-05-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in:
+ sudoreplay does not parse sudoers to find the value of iolog_dir.
+ The default value for the I/O log directory is set at build time.
+ [3cf72612e992]
+
+ * plugins/sudoers/policy.c:
+ Fix group list ref leak in sudoers_policy_store_result() on error
+ path.
+ [34785448a275]
+
+2021-05-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/policy.c:
+ Update comment to match reality.
+ [ec3e0a40d1ec]
+
+2021-05-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac, scripts/ltmain.sh, src/Makefile.in:
+ Build sudo_noexec.so as a module on systems other then Darwin. On
+ Darwin, shared modules and shared libraries are not interchangable
+ and since we preload sudo_noexec.so via DYLD_INSERT_LIBRARIES it
+ must be a library, not a module. We must relax the requirement that
+ libraries begin with a "lib" prefix to work around this difference.
+ This does mean you must use sudo's libtool on Darwin (macOS) but
+ that is already a requirement on other systems (notably HP-UX and
+ SCO) due to a number of libtool patches we require that haven't be
+ accepted upstream. This is a different fix for PR #102.
+ [2e5454c56d3c]
+
+ * configure, configure.ac:
+ Use -Wno-deprecated-declarations on macOS This quiets warnings about
+ LDAP and audit libraries being deprecated. We will use them until
+ they are removed in a future version of macOS.
+ [6fbdf644865c]
+
+2021-05-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/mkpkg:
+ Use /usr/bin/cc on FreeBSD and macOS.
+ [7d6bcea0e544]
+
+ * plugins/sudoers/log_client.c:
+ Don't include errno in "unable to connect to log server" message.
+ There should be a more specific message, usually with an error
+ string, displayed earlier.
+ [e599f9b0fd1c]
+
+ * src/ttyname.c:
+ Fix compiler warning on FreeBSD.
+ [2c6fc866fb5b]
+
+ * lib/iolog/hostcheck.c:
+ Explicitly include netinet/in.h for struct sockaddr_in and
+ sockaddr+_in6. Fixes a compilation problem on FreeBSD.
+ [2277c8f37c34]
+
+2021-05-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_7 for changeset f0ce54d4288c
+ [58968ec7a457] <1.9>
+
+ * Merge sudo 1.9.7 from tip
+ [f0ce54d4288c] [SUDO_1_9_7] <1.9>
+
+2021-05-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/zh_TW.mo, plugins/sudoers/po/zh_TW.po:
+ Updated translations from translationproject.org
+ [3d6d49097b98]
+
+ * plugins/sudoers/log_client.c:
+ Better warning when close function is passed a non-terminal signal.
+ [8b8628249e4d]
+
+ * logsrvd/logsrvd_local.c:
+ Remove line causing store_suspend_local() to return false on
+ success. This is something that should have been removed as part of
+ the local I/O logging refactor.
+ [e8ae1e61b8b2]
+
+ * src/exec_pty.c:
+ Don't set the command status in the closure when the command is
+ suspended. This should only be set for signals that terminate the
+ process. Fixes a bug where the sudo front-end could call the plugin
+ close function with a non-terminal signal argument.
+ [a95024bfb6e8]
+
+2021-05-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/pyhelpers.c, plugins/python/python_plugin_policy.c:
+ Quiet -Wshadow warnings from gcc.
+ [7ff2985ba650]
+
+ * NEWS, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ The -g option may also be used with any group the target user
+ belongs to. The description in the Runas_Spec section incorrectly
+ stated that the -g option could not be used if no runas group was
+ set. Bug #975.
+ [67d1948d1aa8]
+
+ * configure, configure.ac:
+ Remove redundant "configuring Sudo version X.YY" line. We now
+ display this along with the summary info at the end.
+ [0d7c908f8d4c]
+
+ * configure, configure.ac:
+ Don't check for -Wl,-z,relro twice.
+ [a30dce71fb26]
+
+2021-05-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt.mo, plugins/sudoers/po/pt.po,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po:
+ Updated translations from translationproject.org
+ [9303a20fe480]
+
+ * scripts/mkpkg:
+ Build python plugin for RHEL 6 as well.
+ [edaa6ec0e255]
+
+ * configure, configure.ac:
+ Remove shell-style quotes in configure warning/error/notice
+ messages. Square bracket quotes are used, no need for shell-style
+ double quotes.
+ [e6de284df511]
+
+ * NEWS, configure, configure.ac:
+ Summarize configure settings after all tests have run. This makes it
+ a lot easier to see what features have been enabled.
+ [12ea96affed5]
+
+2021-05-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * INSTALL, configure, configure.ac:
+ Remove --with-efence option, there are better options available.
+ [78fd5ceb2c52]
+
+ * NEWS:
+ Move misplaced changes into the 1.9.7 section where they belong.
+ [1519f7a4669b]
+
+ * lib/util/regress/sudo_conf/conf_test.c:
+ Awful hack to pass on macOS where group_source=dynamic by default.
+ [b038bfab8c34]
+
+ * plugins/sudoers/po/ca.mo, plugins/sudoers/po/ca.po,
+ plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po, po/ca.mo,
+ po/ca.po, po/it.mo, po/it.po, po/sr.mo, po/sr.po:
+ Updated translations from translationproject.org
+ [7b156da85d13]
+
+ * NEWS:
+ Document late stage 1.9.7 changes.
+ [28756df7dcb4]
+
+ * doc/sudo_sendlog.man.in, doc/sudo_sendlog.mdoc.in,
+ logsrvd/sendlog.c, logsrvd/sendlog.h:
+ sudo_sendlog: rename -m (max-time) to -s (stop-after).
+ [4f016111b242]
+
+ * logsrvd/logsrv_util.c, logsrvd/logsrvd.c, logsrvd/logsrvd_journal.c:
+ Update closure->elapsed_time in journal_seek(). Otherwise the commit
+ point messages won't be accurate when restarting.
+ [6cd4db44b8ee]
+
+ * doc/sudo_sendlog.man.in, doc/sudo_sendlog.mdoc.in,
+ logsrvd/sendlog.c, logsrvd/sendlog.h:
+ Add "-m elapsed" option to specify the max elapsed time of records
+ to send. Useful for testing the ability of the server to handle
+ restarted log transfers.
+ [cd9c9235e320]
+
+2021-05-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd_relay.c:
+ Disable reading from client or relay when sending error to client.
+ We treat an error from the relay as fatal and must stop processing
+ data from both client and relay to make sure we don't get out of
+ sync.
+ [258f9691b3d9]
+
+ * logsrvd/iolog_writer.c, logsrvd/logsrvd.c, logsrvd/logsrvd_local.c:
+ Fix I/O log restart of locally-store logs. This got broken a while
+ ago when evlog in struct connection_closure was changed to a
+ pointer.
+ [8b59122891f9]
+
+ * scripts/pp:
+ Fix detection of the volatile flag when other flags are present.
+ Otherwise flags fields like "volatile,ignore-other" will be ignored
+ by the Debian and BSD back ends.
+ [0d120b9eab71]
+
+ * src/limits.c:
+ Fix debug message when prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) fails.
+ GitHub issue #101
+ [7d266c174457]
+
+ * logsrvd/logsrvd_relay.c, logsrvd/sendlog.c, logsrvd/tls_client.c,
+ logsrvd/tls_common.h, plugins/sudoers/log_client.c:
+ Don't hard-code the TLS connect timeout, use normal connect timeout.
+ For sudo_logsrvd, this is the relay connect_timeout setting. For
+ sudoers, this is the log_server_timeout setting.
+ [49e29f187f5a]
+
+2021-05-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd_queue.c:
+ Add missing closedir(3) in logsrvd_queue_scan(). Coverity CID 221591
+ [e9745c64a721]
+
+ * NEWS:
+ Mention "log_server_verify" bug fix.
+ [a70060c34e7a]
+
+ * configure, configure.ac, doc/sudo_logsrvd.conf.man.in,
+ doc/sudo_logsrvd.conf.mdoc.in, examples/sudo_logsrvd.conf,
+ m4/sudo.m4, pathnames.h.in:
+ Rename logsrvd log dir to /var/log/sudo_logsrvd.
+ [fb979be9927e]
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ examples/sudo_logsrvd.conf, logsrvd/logsrvd.h,
+ logsrvd/logsrvd_conf.c, logsrvd/logsrvd_queue.c:
+ Make the failed relay retry interval configurable. This is the
+ amount of time to wait before trying to resend a journal to the
+ relay server after a connection error.
+ [cbc04201a63e]
+
+2021-05-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, logsrvd/Makefile.in, logsrvd/logsrvd.c, logsrvd/logsrvd.h,
+ logsrvd/logsrvd_journal.c, logsrvd/logsrvd_queue.c,
+ logsrvd/logsrvd_relay.c:
+ Send outgoing messages to the relay server on startup. Also attempt
+ to retry messages that could not be relayed periodically.
+ [7ed12983af85]
+
+ * lib/util/fatal.c:
+ Avoid clobbering errno in warning().
+ [3282a7db7f51]
+
+ * logsrvd/logsrvd_relay.c:
+ Set relay name string to NULL after dropping the reference.
+ Otherwise it is possible to decrement the reference more than once.
+ [245d4e60ea21]
+
+2021-04-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog.c:
+ Fix cut & pasto that prevented the verify_server option from being
+ set. The "log_server_verify" setting passed from the policy plugin
+ was applied to the "keepalive" option instead of "verify_server".
+ From Krisztian Kovacs.
+ [06f716981ad0]
+
+2021-04-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_logsrvd.man.in, doc/sudo_logsrvd.mdoc.in,
+ logsrvd/logsrvd.c:
+ Write client and server information to debug file on SIGUSR1 This
+ can be used to debug client problems such as a connection not being
+ closed as expected.
+ [e6e3a4ba02f4]
+
+ * doc/sudo_logsrvd.man.in, doc/sudo_logsrvd.mdoc.in:
+ Document journal file directories in store_first mode.
+ [a08de0c20127]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_journal.c:
+ Create journal files in an incoming directory, move to outgoing when
+ complete. This will make it possible to process completed journal
+ files periodically if the relay server is down.
+ [5ced00c6eb7e]
+
+ * logsrvd/logsrvd_relay.c:
+ Add missing connection_close() call for relay-only connections. For
+ an immediate relay we will close the connection when the client
+ disconnects (or there is a timeout). However, for store-and-forward
+ mode the client has already disconnected at the time we are
+ relaying.
+ [e51e98489c6d]
+
+2021-04-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [4aa3f848b223]
+
+ * logsrvd/logsrvd_conf.c:
+ Replace non-ascii characters in warning string.
+ [5e99ac170a15]
+
+ * lib/util/regress/getgrouplist/getgrouplist_test.c,
+ lib/util/regress/tailq/hltq_test.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/editor/check_editor.c,
+ plugins/sudoers/regress/exptilde/check_exptilde.c,
+ plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/regress/parser/check_gentime.c,
+ plugins/sudoers/regress/parser/check_hexchar.c,
+ plugins/sudoers/regress/starttime/check_starttime.c,
+ plugins/sudoers/regress/unescape/check_unesc.c:
+ Quiet clang analyzer false positive in regress tests.
+ [190ad1f287d8]
+
+ * MANIFEST, logsrvd/Makefile.in, logsrvd/iolog_writer.c,
+ logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_local.c:
+ Move local iolog log functions to logsrvd_local.c
+ [e16e2a1d8209]
+
+ * logsrvd/logsrvd_relay.c:
+ Better client error reporting on relay server connection error. More
+ detailed error messages may be found in the debug log.
+ [d0807790327d]
+
+ * logsrvd/logsrvd.c:
+ Update debug pid string when sudo_logsrvd becomes a daemon.
+ [33069e2da7d5]
+
+2021-04-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd.c:
+ Must call SSL_shutdown() before closing the underlying socket. This
+ got broken by some code rearrangement when relay mode was added.
+ [a3a8c4d10565]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd_relay.c:
+ Recover if the client or relay server closes the TLS connection
+ uncleanly. The other end of the connection should perform a proper
+ TLS shutdown but as long as we are in the correct state there is no
+ need to treat this as a user-visible error.
+ [90887bc2235f]
+
+ * NEWS, aclocal.m4, configure, configure.ac:
+ Sudo 1.9.7
+ [c1ea457eca11]
+
+ * MANIFEST, plugins/python/Makefile.in, plugins/python/lsan_suppr.txt:
+ Add a suppression file for the libpython leaks. This is a big hammer
+ but it seems like the best we can do for now. Allows "make check" to
+ succeed when address sanitizer is used.
+ [4500cd1e835e]
+
+2021-04-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/editor.c,
+ plugins/sudoers/regress/editor/check_editor.c:
+ When spliting EDITOR check for escaped quote characters. Also add
+ check_editor to sudoers "make check".
+ [0d8001299358]
+
+2021-04-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/editor.c,
+ plugins/sudoers/regress/editor/check_editor.c:
+ Treat a lone backslash at the end of a string as a literal
+ backslash. GitHub issue #99
+ [40a53e523003]
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in:
+ Fix typo.
+ [614379733a17]
+
+2021-04-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/pyhelpers.c:
+ Avoid a potential NULL dereference when mutating args_str. Coverit
+ CID 221401
+ [69f3c7f8e524]
+
+ * logsrvd/logsrvd_journal.c:
+ Avoid calling fread() with a NUL buffer if msg_len is 0. Coverity
+ CID 221399
+ [ed605b7a3186]
+
+ * logsrvd/logsrvd.c:
+ Set a restrictive umask so new files are only read/write by owner.
+ Coverity CID 221402
+ [595465e4baa2]
+
+ * logsrvd/logsrvd.c:
+ In connection_closure_free() only close sock if it is not -1. When
+ relaying from a journal there will be no socket. Coverity CID 221403
+ [fd4f27067c3f]
+
+ * logsrvd/logsrvd.c:
+ Avoid potential NULL dereference in get_free_buf(). Coverity CID
+ 221400
+ [6cb5491bf812]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd_relay.c:
+ Remove some now-dead code in the error path. Coverity CID 221397 and
+ 221398
+ [edc860f72f98]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_journal.c,
+ logsrvd/logsrvd_relay.c:
+ Use function pointers for each client message type instead of
+ conditionals. This separats out the message handler from the
+ functions that store or relay the message contents.
+ [f596480880fa]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_relay.c:
+ Add enqueue_error_message() helper function. Formats and enqueues an
+ error message and enables the write event.
+ [122bd89fe5e3]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_journal.c,
+ logsrvd/logsrvd_relay.c:
+ Forward the journaled entry after it has been stored locally.
+ [a187d5a7ea28]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_journal.c:
+ Stash the value of the store_first config setting in
+ connection_closure. If the configuration changes it should not
+ affect a connection that is already in progress.
+ [6617c2b7ece5]
+
+ * MANIFEST, logsrvd/Makefile.in, logsrvd/iolog_writer.c,
+ logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c,
+ logsrvd/logsrvd_journal.c, logsrvd/logsrvd_relay.c:
+ Journal messages to disk when store_first is set in the relay
+ section. Instead of forwarding messages immediately, they are
+ journaled locally in wire format. This will be used to implement
+ relay store-and-forward mode.
+ [aa0c537258e7]
+
+ * INSTALL, configure, configure.ac, doc/sudo_logsrvd.conf.man.in,
+ doc/sudo_logsrvd.conf.mdoc.in, doc/sudo_logsrvd.mdoc.in,
+ logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c, m4/sudo.m4,
+ pathnames.h.in:
+ Add configuration for sudo_logsrvd store-and-forward mode. Adds
+ "relay_dir" and "store_first" settings to sudo_logsrvd.conf in the
+ [relay] section. Also adds a --with-relaydir configure argument to
+ change the default value (usually /var/log/logsrvd-relay.
+ [6f064ed6d20e]
+
+ * src/signal.c:
+ Make sure SIGCHLD is not ignored when sudo is executed. If SIGCHLD
+ is ignored there is a race condition between when the process is
+ executed and when the SIGCHLD handler is installed. This fixes the
+ bug described by GitHub PR #98
+ [b4c91a0f72e7]
+
+2021-04-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac:
+ Remove the HP-UX 11.0 pread64() hack, it causes problems on modern
+ HP-UX.
+ [fea8ebd0b88d]
+
+ * src/limits.c:
+ Add minimum value to consider when overriding resource limits.
+ Currently only used for RLIMIT_DATA and RLIMIT_AS.
+
+ This works around a problem on HP-UX where setting RLIMIT_DATA
+ changes the resource limits for both 32-bit and 64-bit processes.
+ HP-UX processes start out with RLIMIT_DATA set based on the values
+ of the maxdsiz and maxdsiz_64bit kernel tunables, depending on
+ whether they are 32-bit or 64-bit. By default this limit is 1GB for
+ 32-bit processes and 4GB for 64-bit. However, once RLIMIT_DATA is
+ changed, it does not appear to be possible to restore the old
+ values. This can result in a 64-bit process that is executed by a
+ 32-bit shell getting the 32-bit RLIMIT_DATA instead of the 64-bit
+ one. Bug #973
+ [8778a27abfaf]
+
+2021-04-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd_relay.c:
+ Don't use msg_len as a length after converting it to network byte
+ order.
+ [3f2496be1130]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_relay.c:
+ Use the packed message buffer when relaying if possible. There's no
+ need to rebuild the message buffer for anything but RestartMessage
+ and ClientHello.
+ [903fa50f48c9]
+
+2021-04-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_relay.c:
+ Allocate the data buffer in get_free_buf() too. We always know the
+ size of the data buffer we need at allocation time.
+ [c02dc245aa40]
+
+2021-04-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_relay.c:
+ Relay ChangeWindowSize and CommandSuspend events too.
+ [cb20a1de47e3]
+
+2021-04-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/pyhelpers.c, plugins/python/regress/testdata/check_ex
+ ample_debugging_c_calls@diag.log, plugins/python/regress/testdata/ch
+ eck_example_debugging_c_calls@info.log, plugins/python/regress/testd
+ ata/check_example_group_plugin_is_able_to_debug.log:
+ Regenerate test output with python 3.10a7 Also adjust debug tests so
+ they pass on older python versions
+ [03aeda971872]
+
+ * configure, m4/python.m4:
+ determine Python (3.10) version number correctly. from upstream
+ automake
+ [1f4136509aca]
+
+ * MANIFEST, aclocal.m4, m4/python.m4, m4/runlog.m4:
+ Move python.m4 and runlog.m4 to the m4 directory. Previously they
+ were inline in aclocal.m4.
+ [6ec4c92539a7]
+
+2021-04-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Add hiuxmpp where we have hpux for special cases. Also move the HP-
+ UX 11.00 pread(2) workaround into the section where pread(2) is
+ tested for, not before it.
+ [f6cc1820e0fb]
+
+ * etc/sudo-logsrvd.pp, etc/sudo-python.pp:
+ Only replace the last instance of "sudo" in example and doc dir.
+ Otherwise we end up with weird paths for a prefix like /opt/sudo.
+ [113bdf79f00f]
+
+2021-04-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.ldap.mdoc.in:
+ Fix lint warning.
+ [aa4a4f0b0da1]
+
+ * doc/sudo_logsrvd.man.in, doc/sudo_logsrvd.mdoc.in:
+ Mention relay mode and update TLS example.
+ [a50a23542c05]
+
+ * etc/sudo-logsrvd.pp, etc/sudo.pp:
+ If libssl_dep was not passed in, use ldd to determine its value.
+ Normally, mkpkg will figure this out, but if the user does "make
+ package" outside of the mkpkg script, libssl_dep will not be set.
+ [87329797daca]
+
+2021-04-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * INSTALL, configure, configure.ac, doc/UPGRADE:
+ Enable the use of OpenSSL if log client/server not disabled. This
+ adds a dependency on OpenSSL unless it is explicitly disabled
+ (--disable-openssl) or the sudo log client and server are disabled
+ (--disable-log-client and --disable-log-server).
+ [618f504240d2]
+
+2021-04-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * etc/codespell.skip:
+ configure aux scripts moved to the scripts directory
+ [1cfcbfd128ed]
+
+ * logsrvd/Makefile.in, logsrvd/logsrvd_conf.c:
+ Set logsrvd_config to NULL in logsrvd_conf_cleanup() after freeing
+ it. Fixes a double free in fuzz_logsrvd_conf (but not sudo_logsrvd
+ itself). Also fix linking fuzz_logsrvd_conf with OpenSSL.
+ [ad78729467d4]
+
+ * logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.1,
+ logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.2,
+ logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.3,
+ logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.4,
+ logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.5,
+ logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.6,
+ logsrvd/regress/fuzz/fuzz_logsrvd_conf.c,
+ logsrvd/regress/fuzz/fuzz_logsrvd_conf.dict:
+ Update sudo_logsrvd.conf fuzzer to match configuration changes.
+ [85ae32ce6f44]
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ examples/sudo_logsrvd.conf:
+ Document relay configuration changes.
+ [d66eb842a6ef]
+
+2021-04-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c,
+ logsrvd/logsrvd_relay.c:
+ Move relay configuration into its own section and add TLS options.
+ TLS options in the relay section will be used if specified,
+ otherwise the TLS options from the server section are used.
+ [0695e9b9b067]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c,
+ logsrvd/logsrvd_relay.c:
+ Add "server" and "relay" to getters/callbacks specific to server and
+ relay.
+ [618b4fa5325c]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c,
+ logsrvd/logsrvd_relay.c:
+ Remove struct logsrvd_tls_config. Now that the SSL context is
+ initialized in logsrvd_conf.c there's no need to export TLS
+ configuration other than tls_check_peer.
+ [4fb0fdc417e1]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c,
+ logsrvd/logsrvd_relay.c:
+ No longer need struct logsrvd_tls_runtime, use SSL_CTX instead.
+ [61e0bdf1499d]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd_conf.c:
+ Move allocation of the TLS context to logsrvd_conf_apply(). This way
+ we get certificate errors at configuration time, not after. It also
+ means that a change to the config file that renders the TLS settings
+ invalid will no longer cause the server to exit. The new config will
+ just be ignored as if there was a syntax error.
+ [352ecb58618f]
+
+ * logsrvd/tls_init.c:
+ Only initialize the SSL library once.
+ [e17215eec1d6]
+
+2021-04-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/timestamp.c:
+ Sanity check struct timespec in timestamp file. Coverity CID 220564
+ [68dfceeb105e]
+
+ * plugins/sudoers/timestamp.c:
+ Check lseek(fd, 0, SEEK_CUR) for -1 return value. Not actually
+ possible in practice. Coverity CID 220568.
+ [27105922d3be]
+
+ * src/net_ifs.c:
+ Check for NULL ifa->ifa_addr and ifa->ifa_netmask in both loops.
+ [373961966099]
+
+2021-04-07 Radovan Sroka <rsroka@redhat.com>
+
+ * src/sudo_edit.c:
+ Fixed bad condition for sesh args
+
+ In selinux_edit_copy_tfiles() when there is only one file and the
+ open() fails then number of arguments is lower than expected. Sudo
+ should return error with or without "Defaults !sudoedit_checkdir"
+ set.
+
+ This was found with regression testing of CVE-2021-23240.
+
+ Signed-off-by: Radovan Sroka <rsroka@redhat.com>
+ [947ce862c0bf]
+
+2021-04-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/net_ifs.c:
+ Plug memory leak on overflow; Coverity CID 220556
+ [86b71e5dec5c]
+
+ * logsrvd/logsrvd.c:
+ In schedule_commit_point() do not free the closure on error. It is
+ the caller's responsibility to free resources on error. Coverity CID
+ 220557
+ [e6629496ab03]
+
+ * plugins/sudoers/pwutil.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ Cast NULL terminator argument to char * when calling sudo_mkgrent().
+ Avoids a portability issue on systems where NULL is not a pointer.
+ [cdb9cf0ad2ea]
+
+ * logsrvd/tls_init.c:
+ Rename LOGSRVD_DEFAULT_CIPHER_LST13 to DEFAULT_CIPHER_LST13
+ [a5d7da05cf09]
+
+ * logsrvd/tls_client.c:
+ Include string.h for strerror(3) prototype.
+ [57f5cfe43a89]
+
+ * logsrvd/logsrvd_relay.c:
+ Move connect_relay_tls() so we don't need a prototype for it. Fixes
+ a warning when sudo is not configured to use OpenSSL.
+ [0c73cfebf32b]
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ examples/sudo_logsrvd.conf:
+ Document relay and connect_timeout server settings.
+ [a101d54b451e]
+
+ * MANIFEST, logsrvd/Makefile.in, logsrvd/logsrv_util.h,
+ logsrvd/sendlog.c, logsrvd/sendlog.h, logsrvd/tls_client.c,
+ logsrvd/tls_common.h:
+ Move common TLS client code to tls_client.c and use it in sendlog.c.
+ [5334b6c4bef8]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c:
+ Rename listen_address -> server_address and add reference counting.
+ This will be used by the upcoming relay mode.
+ [f8ef9c83c3c8]
+
+ * logsrvd/logsrvd.c:
+ Try to send an error message to client for some client_msg_cb()
+ failures.
+ [0805636e8114]
+
+ * logsrvd/logsrvd.c:
+ Split most of server_commit_cb() out into schedule_commit_point().
+ This allows it to be used by the relay code too.
+ [c985c2f9e5d5]
+
+ * MANIFEST, logsrvd/Makefile.in, logsrvd/logsrvd.c, logsrvd/logsrvd.h,
+ logsrvd/logsrvd_conf.c, logsrvd/logsrvd_relay.c:
+ Add a relay mode to sudo_logsrvd where it forwards instead of
+ stores. Relay hosts are be specified in the server section of
+ sudo_logsrvd.conf.
+ [071c231e76a9]
+
+ * logsrvd/Makefile.in, logsrvd/logsrvd.h, logsrvd/logsrvd_relay.c,
+ logsrvd/sendlog.c, logsrvd/tls_common.h:
+ Add support for relaying to another sudo_logsrvd via TLS.
+ [c47397ce4098]
+
+ * MANIFEST, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/rcstr.c, lib/util/util.exp.in, plugins/sudoers/Makefile.in,
+ plugins/sudoers/alias.c, plugins/sudoers/check_aliases.c,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/ldap.c,
+ plugins/sudoers/ldap_util.c, plugins/sudoers/rcstr.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/visudo.c:
+ Move reference-counted string code from sudoers to libsudo_util. It
+ will be used by sudo_logsrvd too.
+ [d228aaf9b6fa]
+
+ * logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c, logsrvd/logsrvd_relay.c:
+ Add sa_host to struct server_address as a ref counted string. Also
+ convert sa_str to ref counted string.
+ [4e8abb84c11d]
+
+ * logsrvd/logsrvd_conf.c:
+ Don't allow a wildcard address for the relay parameter.
+ [4a80d18d025b]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c:
+ Add logsrvd_conf_cleanup() to free the conf data structures on exit.
+ There is no longer a need to do anything in shutdown_cb() other than
+ break out of the event loop.
+ [9e4d7456fb7a]
+
+ * src/tgetpass.c:
+ Set user group list when executing the askpass helper. Under normal
+ circumstances the existing group list will match the list fetched by
+ sudo. However, if sudo is executed by a process that has changed the
+ group list via setgroups(2) and "group_source" in sudo.conf is set
+ to "dynamic" it is possible for them to be different.
+
+ If group_source in sudo.conf is set to "dynamic" it is possible for
+ the group list
+ [2b1d4ffb9cf6]
+
+ * logsrvd/logsrv_util.h, logsrvd/logsrvd.c, logsrvd/logsrvd.h:
+ Use a tailq of write buffers instead of a single one per connection.
+ This allows us to queue up multiple messages for writing like the
+ sudoers client supports. Currently, each connection has its own free
+ list. In the future we may want a single free list with low and high
+ water marks.
+ [b5df1b4d79c7]
+
+ * configure.ac:
+ Increase autoconf minimum version to 2.70. Some of the macros
+ deprecated in 2.70 are required by older versions. For example,
+ AC_PROG_CC now does the work of AC_PROG_CC_STDC. Bug #972
+ [223a584b6241]
+
+ * MANIFEST, Makefile.in, config.guess, config.sub, configure,
+ configure.ac, doc/Makefile.in, examples/Makefile.in,
+ include/Makefile.in, install-sh, lib/util/Makefile.in,
+ lib/zlib/Makefile.in, logsrvd/Makefile.in, ltmain.sh,
+ plugins/audit_json/Makefile.in, plugins/group_file/Makefile.in,
+ plugins/python/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sample_approval/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, scripts/config.guess,
+ scripts/config.sub, scripts/install-sh, scripts/ltmain.sh,
+ src/Makefile.in:
+ Move autoconf auxiliary files to the scripts directory.
+ [5ea8182c11d9]
+
+2021-04-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.ldap.man.in, doc/sudoers.ldap.mdoc.in:
+ Document SUCCESS=return support in sudoers nsswitch.conf entries.
+ Based on a patch from Dennis Filder. Bug #971.
+ [1d631d1b6244]
+
+2021-04-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/audit.c:
+ Move log_server_accept() out from under the #ifdef
+ SUDOERS_LOG_CLIENT Fixes a link error when sudo is configured with
+ --disable-log-client.
+ [1bb7efdbddd5]
+
+2021-04-01 Radovan Sroka <rsroka@redhat.com>
+
+ * src/selinux.c:
+ Removed depricated security_context_t
+
+ Signed-off-by: Radovan Sroka <rsroka@redhat.com>
+ [14aba55909fc]
+
+2021-03-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/sendlog.c:
+ Return NULL if init_tls_client_context() fails. Otherwise, we will
+ call SSL_new with a freed SSL context. Bug #970
+ [5fbadce88524]
+
+2021-03-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/parse_args.c:
+ Use separate getopt config for sudoedit. Avoids a problem where the
+ user gets an exclusive usage error message when using a sudo-
+ specific option. GitHub issue #95
+ [b6207568e50a]
+
+ * src/parse_args.c, src/sudo_usage.h.in:
+ Add -h and -V to sudoedit usage and customize help output for
+ sudoedit. Also add missing -B option to usage strings.
+ [0d8fa214f8c3]
+
+ * src/parse_args.c:
+ Don't report a usage error for "sudo -V". GitHub issue #95
+ [a18573251751]
+
+ * etc/sudo-logsrvd.pp, etc/sudo-python.pp, etc/sudo.pp:
+ Do not include parent directories in rpm and deb files. Fixes a
+ directory conflict with the AIX sudo rpm package. Other deb/rpm
+ packages were not affected because parent dirs are omitted for a
+ prefix of /usr.
+ [f7d8db9670bb]
+
+2021-03-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/net_ifs.c:
+ SCO OpenServer uses SIOCGIFANUM, not SIOCGIFNUM. On OpenServer,
+ SIOCGIFNUM is the number of network interfaces, not the number of
+ ifreq structs.
+ [a992ea37b071]
+
+2021-03-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/net_ifs.c:
+ Add support for HP-UX SIOCGLIFNUM and SIOCGLIFCONF ioctls. We need
+ to use both SIOCGIFCONF and SIOCGLIFCONF since SIOCGLIFCONF only
+ returns IPv6 addresses.
+ [7a53304872b9]
+
+2021-03-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/net_ifs.c:
+ Move get_net_ifs stub to the top and remove unused INET_ADDRSTRLEN
+ def.
+ [15bb7bc0ecb8]
+
+ * src/net_ifs.c:
+ No longer need ifr_tmp variable, just reuse ifr. Now that we store
+ the string version of the address before fetching the netmask we can
+ just re-use ifr. This simplifies things and is safer since if there
+ is space for the address there must also be space for the mask.
+ [89ade84d0a6d]
+
+ * src/net_ifs.c:
+ SCO OpenServer 5 returns a bogus value for SIOCGIFNUM. Gleaned from
+ sendmail.
+ [0616f2103f0b]
+
+ * src/net_ifs.c:
+ Use SIOCGSIZIFCONF or SIOCGIFNUM where available. Still falls back
+ to a loop if not but now maxes out at 2048 interfaces instead of
+ potentially looping forever.
+ [f19cd2f827d5]
+
+ * configure, configure.ac, src/net_ifs.c:
+ Remove support for obsolete ISC UNIX and MIPS RISC/OS systems. They
+ were getting in the way of net_its.c simplification.
+ [4e2b7ce2fb7b]
+
+2021-03-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/net_ifs.c:
+ Use SIOCGLIFCONF to get interface list where supported (Solaris).
+ HP-UX has a SIOCGLIFCONF but it is incompatible (and appears to only
+ return IPv6 addresses). Also add IPv6 support using SIOCGIFCONF
+ (probably AIX only) and make sure ifr_tmpbuf[] is properly aligned.
+ [d2eebba41618]
+
+ * MANIFEST, src/Makefile.in, src/regress/net_ifs/check_net_ifs.c:
+ Add simple regress check to display the network interfaces found.
+ [6c1a5a50056e]
+
+2021-03-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * INSTALL:
+ Suggest clang 11 or higher, some fuzzers may hang when used with
+ clang 10.
+ [abcf94949ca2]
+
+2021-03-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, logsrvd/Makefile.in,
+ logsrvd/regress/fuzz/fuzz_logsrvd_conf.dict:
+ Add dictionary file for fuzz_logsrvd_conf.
+ [f9e154751a5f]
+
+ * Makefile.in, doc/Makefile.in, examples/Makefile.in,
+ include/Makefile.in, lib/eventlog/Makefile.in,
+ lib/fuzzstub/Makefile.in, lib/iolog/Makefile.in,
+ lib/logsrv/Makefile.in, lib/util/Makefile.in, lib/zlib/Makefile.in,
+ logsrvd/Makefile.in, plugins/audit_json/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/python/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sample_approval/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in,
+ src/Makefile.in:
+ Add a new "fuzz" target that executes the fuzzers for 8192 runs
+ each. To run indefinately, set FUZZ_RUNS=-1, e.g. "make FUZZ_RUNS=-1
+ fuzz"
+ [5fd3d7e9430f]
+
+ * MANIFEST, lib/iolog/Makefile.in,
+ lib/iolog/regress/corpus/log_json/id.json,
+ lib/iolog/regress/corpus/log_json/ls.json,
+ lib/iolog/regress/corpus/log_json/mailq.json,
+ lib/iolog/regress/corpus/log_json/make.json,
+ lib/iolog/regress/corpus/log_json/pkg_add.json,
+ lib/iolog/regress/corpus/log_json/pkg_delete.json,
+ lib/iolog/regress/corpus/log_json/printenv.json,
+ lib/iolog/regress/corpus/log_legacy/id.log,
+ lib/iolog/regress/corpus/log_legacy/ls.log,
+ lib/iolog/regress/corpus/log_legacy/mailq.log,
+ lib/iolog/regress/corpus/log_legacy/make.log,
+ lib/iolog/regress/corpus/log_legacy/pkg_add.log,
+ lib/iolog/regress/corpus/log_legacy/pkg_delete.log,
+ lib/iolog/regress/corpus/log_legacy/printenv.log,
+ lib/iolog/regress/corpus/seed/log_json/id.json,
+ lib/iolog/regress/corpus/seed/log_json/ls.json,
+ lib/iolog/regress/corpus/seed/log_json/mailq.json,
+ lib/iolog/regress/corpus/seed/log_json/make.json,
+ lib/iolog/regress/corpus/seed/log_json/pkg_add.json,
+ lib/iolog/regress/corpus/seed/log_json/pkg_delete.json,
+ lib/iolog/regress/corpus/seed/log_json/printenv.json,
+ lib/iolog/regress/corpus/seed/log_legacy/id.log,
+ lib/iolog/regress/corpus/seed/log_legacy/ls.log,
+ lib/iolog/regress/corpus/seed/log_legacy/mailq.log,
+ lib/iolog/regress/corpus/seed/log_legacy/make.log,
+ lib/iolog/regress/corpus/seed/log_legacy/pkg_add.log,
+ lib/iolog/regress/corpus/seed/log_legacy/pkg_delete.log,
+ lib/iolog/regress/corpus/seed/log_legacy/printenv.log,
+ lib/iolog/regress/corpus/seed/timing/timing.1,
+ lib/iolog/regress/corpus/seed/timing/timing.2,
+ lib/iolog/regress/corpus/seed/timing/timing.3,
+ lib/iolog/regress/corpus/seed/timing/timing.4,
+ lib/iolog/regress/corpus/timing/timing.1,
+ lib/iolog/regress/corpus/timing/timing.2,
+ lib/iolog/regress/corpus/timing/timing.3,
+ lib/iolog/regress/corpus/timing/timing.4, lib/util/Makefile.in,
+ lib/util/regress/corpus/seed/sudo_conf/sudo.conf.1,
+ lib/util/regress/corpus/seed/sudo_conf/sudo.conf.2,
+ lib/util/regress/corpus/seed/sudo_conf/sudo.conf.3,
+ lib/util/regress/corpus/sudo_conf/sudo.conf.1,
+ lib/util/regress/corpus/sudo_conf/sudo.conf.2,
+ lib/util/regress/corpus/sudo_conf/sudo.conf.3, logsrvd/Makefile.in,
+ logsrvd/regress/corpus/logsrvd_conf/logsrvd.conf.1,
+ logsrvd/regress/corpus/logsrvd_conf/logsrvd.conf.2,
+ logsrvd/regress/corpus/logsrvd_conf/logsrvd.conf.3,
+ logsrvd/regress/corpus/logsrvd_conf/logsrvd.conf.4,
+ logsrvd/regress/corpus/logsrvd_conf/logsrvd.conf.5,
+ logsrvd/regress/corpus/logsrvd_conf/logsrvd.conf.6,
+ logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.1,
+ logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.2,
+ logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.3,
+ logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.4,
+ logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.5,
+ logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.6,
+ plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/corpus/policy/policy.1,
+ plugins/sudoers/regress/corpus/policy/policy.2,
+ plugins/sudoers/regress/corpus/policy/policy.3,
+ plugins/sudoers/regress/corpus/policy/policy.4,
+ plugins/sudoers/regress/corpus/policy/policy.5,
+ plugins/sudoers/regress/corpus/seed/policy/policy.1,
+ plugins/sudoers/regress/corpus/seed/policy/policy.2,
+ plugins/sudoers/regress/corpus/seed/policy/policy.3,
+ plugins/sudoers/regress/corpus/seed/policy/policy.4,
+ plugins/sudoers/regress/corpus/seed/policy/policy.5:
+ Move corpus files to a seed subdirectory.
+ [ba6dd7f30d22]
+
+ * lib/fuzzstub/fuzzstub.c:
+ We can now rely on LLVMFuzzerTestOneInput to flush stdout.
+ [f20f353eeb87]
+
+ * plugins/sudoers/Makefile.in:
+ Fix fuzz_sudoers output comparison when fuzzing is enabled.
+ libFuzzer outputs additional info to stderr that our stub doesn't.
+ [49434e4eceaa]
+
+ * lib/iolog/regress/fuzz/fuzz_iolog_json.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_legacy.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_timing.c,
+ lib/util/regress/fuzz/fuzz_sudo_conf.c,
+ logsrvd/regress/fuzz/fuzz_logsrvd_conf.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c:
+ Flush stdout before successful return from LLVMFuzzerTestOneInput().
+ Fixes a problem with diag lines from libFuzzer being interspersed
+ with test output.
+ [f0b701120128]
+
+ * configure, configure.ac:
+ Use --allow-multiple-definition to work around an issue with ld.lld.
+ For fuzz_policy we redefine getaddrinfo/freeaddrinfo to work around
+ a DNS timeout problem with name resolution and CIfuzz. However, this
+ causes a link failure when sanitizers are enabled on systems that
+ use ld.lld as their linker. Use a big hammer to avoid the link
+ error.
+ [2b9df5329c0e]
+
+ * MANIFEST, plugins/sudoers/Makefile.in,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/testsudoers_pwutil.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/tsgetgrpw.h:
+ Do not redefine system group and passwd functions for testsudoers.
+ Instead, prefix the replacements with "testsudoers_" and use a
+ custom pwutil backend so they get used.
+ [6bfd2f8d01c0]
+
+ * Makefile.in, doc/Makefile.in, examples/Makefile.in,
+ include/Makefile.in, lib/eventlog/Makefile.in,
+ lib/fuzzstub/Makefile.in, lib/iolog/Makefile.in,
+ lib/logsrv/Makefile.in, lib/util/Makefile.in, lib/zlib/Makefile.in,
+ logsrvd/Makefile.in, plugins/audit_json/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/python/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sample_approval/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in,
+ src/Makefile.in:
+ Rename "fuzz" makefile target to "check-fuzzer". It's purpose is to
+ run the fuzzers are part of a normal "make check" to avoid bit rot,
+ not to perform a fuzzer run. The fuzz_logsrvd_conf fuzzer was not
+ wired up to "make check" previously.
+ [01c03ccfd3f0]
+
+2021-03-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_6p1 for changeset 055f2a618604
+ [5376bc9e3b85] <1.9>
+
+ * Merge sudo 1.9.6p1 from tip
+ [055f2a618604] [SUDO_1_9_6p1] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.6p1
+ [93d95d3f23b1]
+
+2021-03-15 Alexandru Ardelean <aardelean@deviqon.com>
+
+ * plugins/sudoers/policy.c:
+ plugins: sudoers: policy: add MODE_IMPLIED_SHELL to RUN_VALID_FLAGS
+
+ Since this flag isn't set, the sudo_mode variable gets invalidated
+ and running the 'sudo' command seems to error out with message
+ 'sudoers_policy_check: invalid mode flags from sudo front end:
+ 0x80001"'
+ [b98b418f1997]
+
+2021-03-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_6 for changeset e3e96490e48f
+ [2e377fa2b87c] <1.9>
+
+ * config.guess, config.sub:
+ Merge sudo 1.9.6 from tip
+ [e3e96490e48f] [SUDO_1_9_6] <1.9>
+
+ * NEWS:
+ fix typo
+ [c7367647bd7c]
+
+2021-03-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Bug #968
+ [e08853fca88e]
+
+ * MANIFEST, logsrvd/Makefile.in, logsrvd/logsrvd.c, logsrvd/logsrvd.h,
+ logsrvd/sendlog.c, logsrvd/sendlog.h, logsrvd/tls_common.h,
+ logsrvd/tls_init.c:
+ Move common TLS initialization code to tls_init.c.
+ [118c7d41ad48]
+
+ * plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po, po/tr.mo,
+ po/tr.po:
+ Updated translations from translationproject.org
+ [cbc05710d6ba]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/gram.c:
+ Use HAVE_STDINT_H instead of trying to guess based on
+ __STDC_VERSION__. Fixes compilation with pre-C99 headers when the
+ compiler supports C99.
+ [05ebf79d02c7]
+
+ * include/sudo_compat.h, lib/util/secure_path.c:
+ Remove compatibility defines for POSIX sys/stat.h macros. Modern
+ systems have them and we no longer support pre-POSIX systems. This
+ fixes potential redefinition of the macros if sys/stat.h is included
+ after sudo_compat.h. Bug #968.
+ [d10d0b9b60e1]
+
+ * lib/eventlog/logwrap.c,
+ plugins/python/python_plugin_approval_multi.inc,
+ plugins/python/python_plugin_audit_multi.inc,
+ plugins/python/python_plugin_io_multi.inc, src/get_pty.c:
+ Quiet a few Solaris Studio compiler warnings.
+ [1d82509f2e44]
+
+ * configure, configure.ac:
+ Add -Wno-unknown-pragmas along with -Wall. We don't want warnings
+ about unknown pragmas in system headers.
+ [ac15fa0e3d95]
+
+ * scripts/pp:
+ Solaris 11.4 removed /usr/bin/optisa, use /usr/bin/isainfo instead.
+ [97d8bb91cf02]
+
+2021-03-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Compare OS name against freebsd* and netbsd* not freebsd and netbsd.
+ Fixes an issue on NetBSD where host_os starts with netbsdelf.
+ [2e813d52a7d6]
+
+ * plugins/sudoers/Makefile.in:
+ Add @SUDOERS_LIBS@ to FUZZ_LIBS for -lutil on FreeBSD and NetBSD
+ [38a7b3a9eb90]
+
+ * lib/util/Makefile.in, plugins/python/Makefile.in, src/Makefile.in:
+ Set locale for all "make check" targets.
+ [1a80048486d4]
+
+2021-03-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ AIX 6.1 may have a broken fmemopen(). We only use it for the fuzzers
+ so ignore it for AIX < 7.1.
+ [ad909c1479ff]
+
+2021-03-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/pp:
+ Only put specific directories in the ROOT section of the AIX
+ package. Previously, /usr and /opt were placed in USR and everything
+ else went in ROOT. Now, only /dev, /etc, /sbin and /var go in ROOT.
+ [6f1fbe8fea31]
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt.mo, plugins/sudoers/po/pt.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ plugins/sudoers/po/zh_TW.mo, plugins/sudoers/po/zh_TW.po, po/cs.mo,
+ po/cs.po, po/de.mo, po/de.po, po/eo.mo, po/eo.po, po/fi.mo,
+ po/fi.po, po/fr.mo, po/fr.po, po/hr.mo, po/hr.po, po/ja.mo,
+ po/ja.po, po/ko.mo, po/ko.po, po/pl.mo, po/pl.po, po/pt.mo,
+ po/pt.po, po/pt_BR.mo, po/pt_BR.po, po/uk.mo, po/uk.po, po/zh_CN.mo,
+ po/zh_CN.po, po/zh_TW.mo, po/zh_TW.po:
+ Updated translations from translationproject.org
+ [53c17c8d56e9]
+
+2021-03-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd_conf.c:
+ Remove unused tls parameter, we now use a per-address tls flag.
+ [2be727a37b9c]
+
+2021-03-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document double escaping of backslashes. Bug #961.
+ [ae51e4899555]
+
+ * NEWS, configure, configure.ac:
+ No longer need to define _DARWIN_UNLIMITED_GETGROUPS on macOS. We
+ now define _DARWIN_C_SOURCE which accomplishes the same thing.
+ [c233df4c1ae4]
+
+ * plugins/sudoers/auth/pam.c:
+ Fix a potential use-after-free in conversation function. The prompt
+ passed in to sudo_pam_verify() will be freed later by
+ check_user_interactive() so we need to reset the stashed value. From
+ Pavel Heimlich. Bug #967.
+ [86bc6ee3c493]
+
+ * plugins/sudoers/pwutil.c:
+ No need to update cp after storing gr->gr_name, it is not used,
+ Coverity CID 219314
+ [27bace364dc9]
+
+2021-03-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Mention GitHub issue #56.
+ [47b8b9fac52b]
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [923899bcc63d]
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c,
+ logsrvd/iolog_writer.c, logsrvd/logsrvd.c, logsrvd/logsrvd.h:
+ Log peer address in sudo_logsrvd JSON-format logs. The peer that
+ connected to us might not be the same host where the log entry
+ originated.
+ [4e2488efaf97]
+
+ * NEWS, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in,
+ lib/util/sudo_conf.c:
+ Make "group_source=dynamic" the default on macOS. Recent versions of
+ macOS do not reliably return all of a user's non-local groups via
+ getgroups(2), even when _DARWIN_UNLIMITED_GETGROUPS is defined. Bug
+ #946.
+ [491720b06a68]
+
+ * lib/eventlog/Makefile.in, lib/iolog/Makefile.in,
+ lib/util/Makefile.in, logsrvd/Makefile.in,
+ plugins/sudoers/Makefile.in:
+ For regess/fuzz set LC_ALL to C.UTF-8 if possible, falling back on
+ C. Works around a crash in leak sanitizer when the locale is set to
+ C and TLS support is enabled.
+ [4345912b9bd8]
+
+2021-03-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Initialize the lbuf used by sudoers_trace_print() in init_lexer().
+ Free the old buffer if there is one, otherwise it would never be
+ freed.
+ [1893ecc06718]
+
+ * lib/util/lbuf.c:
+ In sudo_lbuf_destroy(), reset error, len and size.
+ [7a6f980c2215]
+
+ * NEWS:
+ Mention the integer overflow check in store_timespec().
+ [f41519e1dae9]
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ In find_path() stub only make a copy in outfile if returning FOUND.
+ Fixed a recently-introduced memory leak in the fuzzer.
+ [2045b1afc0b5]
+
+2021-02-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/sudo_debug.c:
+ Disable debug code for FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION It
+ will not be used and just confuses the coverage stats.
+ [3307c855b77d]
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Expand stub getaddrinfo() to resolve "localhost".
+ [e1035616ad99]
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Improve fuzz_policy coverage and set defaults in setdefs not parse.
+ Now exercises session open/close and set additional defaults to
+ exercise more code paths.
+ [2843a0b930fd]
+
+ * plugins/sudoers/match_command.c, plugins/sudoers/match_digest.c:
+ Improve SUDOERS_NAME_MATCH support. Now supports digests and
+ performs better directory matching.
+ [2f2d63596256]
+
+ * plugins/sudoers/policy.c:
+ Add MODE_CHECK to LIST_VALID_FLAGS, fixes "sudo -l command".
+ [eff4cbe95d75]
+
+2021-02-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, include/sudo_iolog.h, lib/iolog/Makefile.in,
+ lib/iolog/iolog_clearerr.c, lib/iolog/iolog_close.c,
+ lib/iolog/iolog_eof.c, lib/iolog/iolog_fileio.c,
+ lib/iolog/iolog_gets.c, lib/iolog/iolog_mkdirs.c,
+ lib/iolog/iolog_mkdtemp.c, lib/iolog/iolog_mkpath.c,
+ lib/iolog/iolog_nextid.c, lib/iolog/iolog_open.c,
+ lib/iolog/iolog_openat.c, lib/iolog/iolog_read.c,
+ lib/iolog/iolog_seek.c, lib/iolog/iolog_swapids.c,
+ lib/iolog/iolog_util.c, lib/iolog/iolog_write.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_timing.c, logsrvd/iolog_writer.c,
+ logsrvd/regress/fuzz/fuzz_logsrvd_conf.c:
+ Split iolog_fileio.c into multiple files.
+ [9b7c4f1b781f]
+
+ * plugins/sudoers/defaults.c:
+ Correct the integer overflow check in store_timespec(). Fixes oss-
+ fuzz issue #31463
+ [3765d5c4ecd3]
+
+ * plugins/sudoers/regress/sudoers/test27.ldif2sudo.ok:
+ Update file that was missed in test27 changes.
+ [5824f54afa88]
+
+ * MANIFEST, include/sudo_iolog.h, lib/iolog/Makefile.in,
+ lib/iolog/iolog_conf.c, lib/iolog/iolog_fileio.c,
+ lib/iolog/iolog_loginfo.c:
+ Break out I/O log config handling into iolog_conf.c.
+ [546f503f9bb4]
+
+ * lib/fuzzstub/Makefile.in, lib/iolog/Makefile.in,
+ logsrvd/Makefile.in, plugins/sudoers/Makefile.in:
+ regen Makefile.in
+ [43c54f94e9c8]
+
+ * examples/Makefile.in, lib/eventlog/Makefile.in,
+ plugins/sudoers/Makefile.in:
+ Add some missing files to the clean target
+ [20754fec5ff1]
+
+ * plugins/sudoers/regress/sudoers/test27.in,
+ plugins/sudoers/regress/sudoers/test27.json.ok,
+ plugins/sudoers/regress/sudoers/test27.ldif.ok,
+ plugins/sudoers/regress/sudoers/test27.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test27.out.ok,
+ plugins/sudoers/regress/sudoers/test27.toke.ok:
+ Add netgroup check to sudoers test27
+ [1b45a6794b2d]
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.out.ok:
+ Sync with fuzz_sudoers changes.
+ [1481cef048ad]
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ Fuzz with runuser and rungroup specified too.
+ [2d8ceb465cea]
+
+ * MANIFEST, plugins/sudoers/regress/sudoers/test27.in,
+ plugins/sudoers/regress/sudoers/test27.json.ok,
+ plugins/sudoers/regress/sudoers/test27.ldif.ok,
+ plugins/sudoers/regress/sudoers/test27.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test27.out.ok,
+ plugins/sudoers/regress/sudoers/test27.toke.ok:
+ Add test to exercise RunasSpec without a RunasUser.
+ [ee22ac488aca]
+
+ * MANIFEST, plugins/sudoers/regress/sudoers/test22.sudo.ok,
+ plugins/sudoers/regress/sudoers/test23.sudo.ok,
+ plugins/sudoers/regress/sudoers/test24.sudo.ok,
+ plugins/sudoers/regress/sudoers/test26.sudo.ok:
+ Remove unused regress files.
+ [71d943734bb8]
+
+ * logsrvd/regress/fuzz/fuzz_logsrvd_conf.c:
+ Don't try to run getters if we failed to parse the config file.
+ [734bb56c24ed]
+
+2021-02-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Add a stub getaddrinfo(3) to avoid a DNS timeout in CIfuzz.
+ [5f725de1e3ad]
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Fix runchroot, runcwd, tty_tickets. Add timestampowner.
+ [d8a945bea98d]
+
+ * plugins/sudoers/policy.c:
+ Only add command_info to garbage collector on successful return.
+ Otherwise it will be freed on failure.
+ [c3d0461efaa1]
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ Add user millert to group sudo, which is often the exempt group.
+ [fac833a2cf3b]
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Add some defaults settings in sudo_file_parse(). We don't have a
+ real policy file but we still want to exercise callbacks in
+ sudoers.c.
+ [9f3d3f668973]
+
+ * plugins/sudoers/sudoers.c:
+ Do not free sudo_user.iolog_{file,path} in sudo_user_free(). They
+ are not dynamically allocated.
+ [59c102ba67cf]
+
+ * lib/iolog/regress/fuzz/fuzz_iolog_timing.c:
+ Remove unnecessary warnings, we want to fail silently.
+ [4b1ee5dd2cb4]
+
+ * logsrvd/regress/fuzz/fuzz_logsrvd_conf.c:
+ No longer need to stub out eventlog config functions.
+ [08c40b6a63c9]
+
+ * MANIFEST, logsrvd/Makefile.in,
+ logsrvd/regress/corpus/logsrvd_conf/logsrvd.conf.4,
+ logsrvd/regress/corpus/logsrvd_conf/logsrvd.conf.5,
+ logsrvd/regress/corpus/logsrvd_conf/logsrvd.conf.6,
+ logsrvd/regress/fuzz/fuzz_logsrvd_conf.c:
+ Call public getters in logsrvd.conf fuzzer and add to corpus. Now
+ exercises the syslog config erorr path.
+ [0b314e4e0696]
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Add more passes to policy fuzzer Now execises list, list other user
+ and show_version.
+ [21a1cc9665ec]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Implement sudoers_policy_deregister_hooks() Register/deregister
+ hooks in fuzz_policy and also call show_version().
+ [8849644a75de]
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c:
+ Add sudoers debug register/deregister.
+ [5fba9b19c6fa]
+
+ * plugins/sudoers/defaults.c:
+ Remove unnecessary break statement.
+ [aa18c2957f82]
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.out.ok,
+ plugins/sudoers/regress/sudoers/test14.in,
+ plugins/sudoers/regress/sudoers/test14.json.ok,
+ plugins/sudoers/regress/sudoers/test14.ldif.ok,
+ plugins/sudoers/regress/sudoers/test14.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test14.out.ok,
+ plugins/sudoers/regress/sudoers/test14.toke.ok:
+ Include a sha384 digest in the test corpus.
+ [6c405febff10]
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ Parse sudoers file in the C locale.
+ [82d6afbe499b]
+
+ * MANIFEST, plugins/sudoers/regress/sudoers/test26.in,
+ plugins/sudoers/regress/sudoers/test26.json.ok,
+ plugins/sudoers/regress/sudoers/test26.ldif.ok,
+ plugins/sudoers/regress/sudoers/test26.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test26.out.ok,
+ plugins/sudoers/regress/sudoers/test26.sudo.ok,
+ plugins/sudoers/regress/sudoers/test26.toke.ok:
+ Add regress test with all current Defaults settings. Currently skips
+ SELinux and Solaris privilege settings.
+ [79e82a58ccde]
+
+2021-02-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/env.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoers_hooks.c:
+ Move env hooks into sudoers_hooks.c.
+ [7296d05b9206]
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ No need to call check_defaults() and check_aliases() in quiet mode.
+ [0d0f93849388]
+
+ * plugins/sudoers/gc.c:
+ sudoers_gc_init() is not currently used
+ [e74d2870ae25]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/fmtsudoers_cvt.c:
+ Split fmtsudoers.c into the parts used by sudoers plugin and
+ cvtsudoers. Only testsudoers and cvtsudoers use the full set of
+ formatting functions.
+ [8c57e80ae655]
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ Check defaults settings too.
+ [7dc7d66f47e7]
+
+ * MANIFEST, plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_stubs.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c:
+ Add fuzzer-specific stubs source file.
+ [815c28958d42]
+
+ * Makefile.in:
+ Do not overwrite existing ChangeLog file if there is no hg/git dir.
+ We don't want "make install" from a source tarball to nuke the
+ ChangeLog.
+ [f7aba6a01d85]
+
+ * lib/iolog/Makefile.in, lib/util/Makefile.in, logsrvd/Makefile.in,
+ plugins/sudoers/Makefile.in:
+ Remove fuzzer targets in "make clean"
+ [25b068bc254b]
+
+ * .gitignore, .hgignore:
+ Ignore fuzzer targets
+ [d920254ce731]
+
+ * lib/iolog/regress/fuzz/fuzz_iolog_json.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_legacy.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_timing.c,
+ lib/util/regress/fuzz/fuzz_sudo_conf.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c:
+ Set program name in fuzzers so we get consisten warnings.
+ [1ee4b5478d1c]
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Use real eventlog config fuctions instead of stubs.
+ [eed6fc4df1f6]
+
+ * include/sudo_iolog.h, lib/iolog/iolog_fileio.c,
+ lib/iolog/iolog_loginfo.c:
+ Move iolog info log writing to iolog_loginfo.c
+ [292915dae440]
+
+ * MANIFEST, lib/iolog/Makefile.in, lib/iolog/iolog_loginfo.c,
+ lib/iolog/iolog_timing.c, lib/iolog/iolog_util.c,
+ lib/iolog/regress/iolog_timing/check_iolog_timing.c,
+ lib/iolog/regress/iolog_util/check_iolog_util.c:
+ Split iolog_util.c into iolog_loginfo.c and iolog_timing.c. Also
+ rename check_iolog_util -> check_iolog_timing.
+ [5b5249e4aa96]
+
+ * MANIFEST, lib/iolog/Makefile.in, lib/iolog/iolog_legacy.c,
+ lib/iolog/iolog_util.c:
+ Move legacy I/O log info file parsing to iolog_legacy.c
+ [94b767bb56c7]
+
+ * MANIFEST, include/sudo_eventlog.h, lib/eventlog/Makefile.in,
+ lib/eventlog/eventlog.c, lib/eventlog/eventlog_conf.c:
+ Move eventlog config code into eventlog_conf.c
+ [656d65215e50]
+
+ * MANIFEST, lib/eventlog/Makefile.in, lib/eventlog/eventlog.c,
+ lib/eventlog/eventlog_free.c:
+ Move eventlog_free() into its own file.
+ [a5ff36ac0ebb]
+
+ * logsrvd/regress/fuzz/fuzz_logsrvd_conf.c:
+ Stub out eventlog and iolog configuration setters.
+ [cc32ba7436cd]
+
+ * MANIFEST, plugins/sudoers/defaults.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.out.ok:
+ Update Defaults settings after parsing sudoers. Also stub out
+ dump_defaults when fuzzing as it is not used.
+ [fa1e7c7b42c2]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/b64_decode.c,
+ plugins/sudoers/b64_encode.c, plugins/sudoers/base64.c:
+ Split base64 encode/decode functions into separate source files.
+ They are independent functions.
+ [ab0904c5122c]
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ fuzz_printf and fuzz_conversation can be stubs.
+ [9b11c9a3f3c3]
+
+2021-02-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ Exercise tilde expansion if used in runcwd or runchroot.
+ [a6f0995c6a55]
+
+ * plugins/sudoers/check_aliases.c:
+ Move alias checking code out of visudo.c and into check_aliases.c.
+ [5c0a91978441]
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ Check aliases in fuzz_sudoers if the policy parsed correctly.
+ [b272e634f204]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/parse.h,
+ plugins/sudoers/visudo.c:
+ Move alias checking code out of visudo.c and into check_aliases.c.
+ [b9c23c958935]
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ We don't need to link fuzz_sudoers with file.c.
+ [4fcd15e8cdcf]
+
+ * lib/iolog/regress/fuzz/fuzz_iolog_json.dict,
+ lib/util/regress/fuzz/fuzz_sudo_conf.dict,
+ plugins/sudoers/regress/fuzz/fuzz_policy.dict,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.dict,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.dict:
+ Strings in dictionary files need to be quoted.
+ [8a95ea335d2d]
+
+ * MANIFEST, lib/iolog/Makefile.in,
+ lib/iolog/regress/fuzz/fuzz_iolog_json.dict, lib/util/Makefile.in,
+ lib/util/regress/fuzz/fuzz_sudo_conf.dict,
+ plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/fuzz/fuzz_policy.dict,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.dict,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.dict:
+ Add dictionary files for fuzzers where possible.
+ [4d9147fd50fd]
+
+2021-02-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ Also free safe_cmnd so it doesn't leak.
+ [5071a1ffa5d0]
+
+ * plugins/sudoers/stubs.c, plugins/sudoers/testsudoers.c:
+ Return NOT_FOUND from the set_cmnd_path() stub since we don't set
+ user_cmnd. The purpose of set_cmnd_path() is to reset user_cmnd
+ based on a new runchroot. For the stub version we don't modify
+ user_cmnd and so must not return a status of FOUND. Fixes oss-fuzz
+ issue #31250 which only affected the fuzzer and not sudo.
+ [36fe416668df]
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.out.ok:
+ Fix fuzz_sudoers output matching.
+ [6cec1e5aa799]
+
+ * lib/fuzzstub/fuzzstub.c:
+ Print "running" and "executed" lines to stderr like libfuzzer does.
+ [b76b7a4a6ff3]
+
+ * plugins/sudoers/pwutil_impl.c:
+ Support passing sudo_make_gidlist_item() an array of gids. The gids
+ are formatted as strings, not gid_t.
+ [d1608f63ae91]
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.out.ok:
+ Prime user/group cached and set the interface list. Also match
+ parsed policy against multiple users.
+ [ec19b5658a2a]
+
+ * plugins/sudoers/pwutil.c, plugins/sudoers/sudoers.h:
+ Add sudo_mkgrent(), to be used to prime the group cache in
+ tests/fuzzers.
+ [333f0887abbc]
+
+2021-02-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ Perform matching in fuzz_sudoers for inputs that parse correctly.
+ The fuzzer now exercised the normal match code as well as the
+ pseudo-command (list, validate, etc) match code. Privileges are also
+ listed for well-formed sudoers file.
+ [8caf505d7341]
+
+ * plugins/sudoers/match_command.c, plugins/sudoers/match_digest.c,
+ plugins/sudoers/parse.h:
+ Add back SUDOERS_NAME_MATCH and enable it when fuzzing. This avoids
+ the test environment from influencing sudoers matching.
+ [496b3a7184a8]
+
+ * plugins/sudoers/match_command.c:
+ Add missing globfree(3) in command_matches_glob() when matching a
+ directory.
+ [1d6d28d6eb61]
+
+2021-02-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/sudo_dso.c:
+ Add support on AIX for loading plugins that are .a (not .so) files.
+ It is possible to specify the member name in parens after the path,
+ e.g. sudoers.a(shr.o) for 32-bit or sudoers.a(shr_64.o) for 64-bit.
+ If no member is specified in the path and dlopen() fails with
+ ENOEXEC, try again with an explicit member, either shr.o or
+ shr_64.o.
+ [90d975989148]
+
+ * Makefile.in, doc/Makefile.in, examples/Makefile.in,
+ include/Makefile.in, lib/eventlog/Makefile.in,
+ lib/fuzzstub/Makefile.in, lib/iolog/Makefile.in,
+ lib/logsrv/Makefile.in, lib/util/Makefile.in, lib/zlib/Makefile.in,
+ logsrvd/Makefile.in, plugins/audit_json/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/python/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sample_approval/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in,
+ src/Makefile.in:
+ Add clean rules to .PHONY target.
+ [dea3468f3f7b]
+
+2021-02-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Makefile.in, doc/Makefile.in, examples/Makefile.in,
+ include/Makefile.in, lib/eventlog/Makefile.in,
+ lib/fuzzstub/Makefile.in, lib/iolog/Makefile.in,
+ lib/logsrv/Makefile.in, lib/util/Makefile.in, lib/zlib/Makefile.in,
+ logsrvd/Makefile.in, plugins/audit_json/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/python/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sample_approval/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in,
+ src/Makefile.in:
+ Add install-fuzz Makefile target to install the fuzzers and seed
+ corpus. The FUZZ_DESTDIR make variable needs to be set in the
+ environment or on the command line.
+ [89c4dc1e8cb0]
+
+ * plugins/sudoers/Makefile.in:
+ Only display fuzz_policy output if the fuzzer exits with an error.
+ [c6927227be4a]
+
+ * plugins/sudoers/regress/corpus/policy/policy.1,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Call list, validate and invalidate entry points too. We need a
+ separate open/close for each one.
+ [fbbc5bdb4541]
+
+ * INSTALL, configure, configure.ac:
+ Add --disable-ssp configure option. This allows for disabling
+ -fstack-protector without turning off the other hardening options.
+ [1d9ca18e4fa9]
+
+ * lib/util/regress/getdelim/getdelim_test.c:
+ Test the error case by closing the underlying fd. Note that we don't
+ use ferror() here since our getdelim() has no way to set the error
+ flag if there is a memory allocation error.
+ [df0464968e2c]
+
+ * lib/util/regress/getdelim/getdelim_test.c:
+ Test the case where getdelim() must reallocate the buffer.
+ Reproduces Bug #960.
+ [df4dbc0830be]
+
+ * lib/eventlog/eventlog.c:
+ When logging JSON to syslog, wrap the contents in a "sudo" object.
+ This makes it easier for log parsers to identify what is a sudo log
+ entry.
+ [2c96aeaabc8e]
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Restore the check for sudoers_policy.close == NULL. The fuzzers run
+ as part of "make check" too in which case NO_LEAKS won't be defined
+ and the close function will be set to NULL.
+ [8418ff5f6dfb]
+
+ * lib/iolog/iolog_json.c:
+ Use %td when printing the difference of two pointers.
+ [608de9ab3902]
+
+ * plugins/sudoers/parse.c:
+ Don't print a NULL as a string if role/type/privs/limitprivs is not
+ set. We can't rely on printf("%s", NULL) not crashing.
+ [4a04efbcbff9]
+
+ * plugins/sudoers/sudoers.c:
+ Fix compilation error on Solaris introduced with sudo_user_free().
+ [0ce4e0ac807e]
+
+2021-02-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Bug #960.
+ [82303f217d8b]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Distinguish between EOF and error using feof(3), not ferror(3). Our
+ getdelim(3) emulation won't set the error flag if the error is due
+ to an allocation failure. This explains the premature EOF without
+ error seen in Bug #960.
+ [5a70875f92fa]
+
+ * lib/util/getdelim.c:
+ Reset end pointer when reallocing the line buffer in getdelim().
+ Fixes excessive memory allocations for long lines. Bug #960.
+ [d6dd6893b38a]
+
+ * lib/eventlog/Makefile.in, lib/iolog/Makefile.in,
+ plugins/sudoers/Makefile.in:
+ Remove duplicated MALLOC_OPTIONS and MALLOC_CONF env variables.
+ [2f7695aadad9]
+
+ * lib/iolog/iolog_json.c:
+ On parse error, display line and column instead of the offending
+ line.
+ [bbda04a5b05d]
+
+ * logsrvd/Makefile.in, plugins/sudoers/Makefile.in:
+ regen
+ [20e093fd76f0]
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.6
+ [1c76fe52426f]
+
+2021-02-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/iolog_json.c, lib/iolog/iolog_util.c:
+ Pass I/O log memory allocation errors up to the caller.
+ [4777add71679]
+
+ * INSTALL, config.h.in, configure, configure.ac, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in, pathnames.h.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/timestamp.c:
+ Add admin_flag sudoers option and make --enable-admin-flag take a
+ path. It is now possible to disable the Ubuntu admin flag in sudoers
+ or change its location. GitHub issue #56
+ [d77c3876fa95]
+
+ * plugins/sudoers/exptilde.c,
+ plugins/sudoers/regress/exptilde/check_exptilde.c:
+ Fix tilde expansion of paths with no user like ~/foo. The '/'
+ separator was missing in the resulting path.
+ [dbba61f76d6c]
+
+ * doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in, lib/util/sudo_conf.c,
+ plugins/sudoers/policy.c:
+ Limit max_groups in sudo.conf to 1024. The max_groups setting should
+ no longer be needed anyway.
+ [aee7843e0c7d]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c:
+ In sudoers_policy_close() call sudoers_cleanup() instead of
+ sudo_user_free(). If we didn't call sudoers_policy_main() due to an
+ early error there may be more things to clean up.
+ [683d69d84aa6]
+
+ * plugins/sudoers/policy.c:
+ Check for invalid flag combinations from front-end for all cases.
+ The checks are now performed in the check_policy, list, validate and
+ invalidate functions instead of as part of the open function. We
+ can't perform the checks in open because we don't yet know what
+ operation is going to be performed.
+ [b09105b3bb42]
+
+ * plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c:
+ Always dynamically allocate user_cmnd, it is freed in
+ sudo_user_free(). Instead of setting user_cmnd in the policy
+ functions, always set argv. Calling sudoers_policy_main() with argc
+ of 0 is no longer allowed.
+ [820f1f4e5c44]
+
+ * plugins/sudoers/policy.c:
+ No need for sudoers_cleanup() in sudoers_policy_invalidate(). The
+ sudoers close() function is now called even for "sudo -k". Also no
+ need to set user_cmnd, it is not used in this code path.
+ [c2c9832c32f4]
+
+2021-02-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, logsrvd/Makefile.in, logsrvd/logsrvd_conf.c,
+ logsrvd/regress/corpus/logsrvd_conf/logsrvd.conf.1,
+ logsrvd/regress/corpus/logsrvd_conf/logsrvd.conf.2,
+ logsrvd/regress/corpus/logsrvd_conf/logsrvd.conf.3,
+ logsrvd/regress/fuzz/fuzz_logsrvd_conf.c:
+ Add simple fuzzer for sudo_logsrvd.conf parser.
+ [8b5cd9e24656]
+
+ * lib/iolog/regress/fuzz/fuzz_iolog_timing.c:
+ Fix unlinking of timing temp file.
+ [8b0ce6d777c8]
+
+ * lib/eventlog/Makefile.in, lib/iolog/Makefile.in,
+ plugins/python/Makefile.in, plugins/sudoers/Makefile.in:
+ Set MALLOC_OPTIONS and MALLOC_CONF for all regress targets.
+ [47e8b85d1d9a]
+
+ * MANIFEST, lib/util/Makefile.in,
+ lib/util/regress/corpus/sudo_conf/sudo.conf.1,
+ lib/util/regress/corpus/sudo_conf/sudo.conf.2,
+ lib/util/regress/corpus/sudo_conf/sudo.conf.3,
+ lib/util/regress/fuzz/fuzz_sudo_conf.c:
+ Add simple fuzzer for sudo.conf parser.
+ [8a530402f936]
+
+ * plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Free struct sudo_user in sudoers_policy_close() and
+ sudoers_cleanup(). Also, do not NULL out the close function if
+ NO_LEAKS is defined.
+ [f3fbf78e6e41]
+
+ * MANIFEST, lib/iolog/Makefile.in,
+ lib/iolog/regress/corpus/log_legacy/id,
+ lib/iolog/regress/corpus/log_legacy/id.log,
+ lib/iolog/regress/corpus/log_legacy/ls,
+ lib/iolog/regress/corpus/log_legacy/ls.log,
+ lib/iolog/regress/corpus/log_legacy/mailq,
+ lib/iolog/regress/corpus/log_legacy/mailq.log,
+ lib/iolog/regress/corpus/log_legacy/make,
+ lib/iolog/regress/corpus/log_legacy/make.log,
+ lib/iolog/regress/corpus/log_legacy/pkg_add,
+ lib/iolog/regress/corpus/log_legacy/pkg_add.log,
+ lib/iolog/regress/corpus/log_legacy/pkg_delete,
+ lib/iolog/regress/corpus/log_legacy/pkg_delete.log,
+ lib/iolog/regress/corpus/log_legacy/printenv,
+ lib/iolog/regress/corpus/log_legacy/printenv.log,
+ plugins/sudoers/Makefile.in:
+ For "make fuzz" only fuzz the seed corpus. This way we avoid files
+ generated by the fuzzer itself.
+ [42ace1dec313]
+
+2021-02-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/env.c, plugins/sudoers/gc.c,
+ plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Fix sudoers garbage collection and run it in policy fuzzer.
+ [c0d572fd9921]
+
+ * .github/workflows/main.yml:
+ Rename master -> main
+ [57000edd1aff]
+
+ * plugins/sudoers/policy.c:
+ Do not include errno string for invalid params from front-end.
+ [2d0b55b3041f]
+
+ * plugins/sudoers/parse.c, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ Always dynamically allocate user_role, user_type, user_privs,
+ user_limitprivs
+ [f5992824219d]
+
+ * plugins/sudoers/policy.c:
+ Remove dead code, front-end does not set runas_privs or
+ runas_limitprivs
+ [6ce3da323452]
+
+ * plugins/sudoers/iolog.c:
+ Plug memory leak if there are duplicate user_info or command_info
+ entries.
+ [21865246a4dc]
+
+2021-02-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .github/workflows/main.yml:
+ Add CIFuzz workflow to run fuzzers on push or PR.
+ https://google.github.io/oss-fuzz/getting-started/continuous-
+ integration/
+ [47f1c8015ec5]
+
+ * plugins/sudoers/check.h, plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/timestamp.c:
+ Move create_admin_success_flag() to timestamp.c.
+ [0675f230288c]
+
+ * configure, configure.ac:
+ Error out if fuzzer/sanitizer enabled but not supported by the
+ compiler.
+ [289afba93f79]
+
+ * plugins/sudoers/regress/fuzz/fuzz_policy.c:
+ The push() function was not updating the size after reallocating.
+ [e089aaeee3b2]
+
+ * plugins/sudoers/pwutil_impl.c, src/sudo.c:
+ If sudo_getgrouplist2() returns -1, clamp ngroups based on
+ max_groups. The ngroups parameter is an out parameter that is filled
+ in with the actual number of groups, which may be less than the
+ static number allocated when max_groups is set in sudo.conf. Fixes a
+ potential out of bounds read found by LLVM libFuzzer.
+ [a26461ccf891]
+
+2021-02-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/policy.c:
+ Reset sudoers path, owner and mode before parsing plugin arguments.
+ This is only needed when calling sudoers_policy_deserialize_info()
+ more than once, which is true for the policy fuzzer.
+ [a25a6210f48c]
+
+ * plugins/sudoers/sudoers.c:
+ Cleanup sudoers sources on denial and error too.
+ [454b7adcfa21]
+
+ * plugins/sudoers/pwutil.c:
+ Fix sudo_getgrgid reference count bug when gid doesn't exist. This
+ one was missed when the other user/group lookup functions were
+ fixed.
+ [20e3fad6768b]
+
+ * plugins/sudoers/policy.c:
+ Plug memory leak if there are duplicate user_info entries.
+ [b8ddcfa0a051]
+
+ * MANIFEST, plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/corpus/policy/policy.1,
+ plugins/sudoers/regress/corpus/policy/policy.2,
+ plugins/sudoers/regress/corpus/policy/policy.3,
+ plugins/sudoers/regress/corpus/policy/policy.4,
+ plugins/sudoers/regress/corpus/policy/policy.5,
+ plugins/sudoers/regress/fuzz/fuzz_policy.c,
+ plugins/sudoers/sudoers.c:
+ Fuzz sudoers policy module API. Includes a test case to reproduce
+ CVE-2021-3156.
+ [576d065759cf]
+
+ * lib/iolog/Makefile.in, plugins/sudoers/Makefile.in:
+ Make fuzz targets depend on fuzzer stub library. We really want a
+ dependency on $(LIB_FUZZING_ENGINE) but that could be a flag like
+ "-fsanitize=fuzzer" instead of a path.
+ [0963418f1cf9]
+
+ * lib/util/Makefile.in:
+ regen
+ [dd872eceb19e]
+
+ * MANIFEST, plugins/sudoers/Makefile.in:
+ Move audit.c from libparsesudoers to the sudoers module itself. Now
+ that audit.c contains the audit module it doesn't belong in
+ libparsesudoers.
+ [3df4f6e10f54]
+
+ * configure, configure.ac:
+ Do not pass AX_APPEND_FLAG more than a single flag. GitHub issue #92
+ [ed9ccdd41231]
+
+2021-02-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/eventlog/Makefile.in, lib/iolog/Makefile.in,
+ logsrvd/Makefile.in, plugins/sudoers/Makefile.in:
+ Fix up some .la file library dependencies. libsudo_iolog.la already
+ depends on libsudo_util.la and libsudo_eventlog.la so we don't need
+ to list those explicitly when libsudo_iolog.la is listed.
+ [d8b55cf698b5]
+
+ * lib/eventlog/eventlog.c, lib/util/Makefile.in, lib/util/progname.c,
+ lib/util/regress/progname/progname_test.c, lib/util/sudo_conf.c,
+ lib/util/util.exp.in, plugins/sudoers/audit.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/match_command.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ src/sudo_edit.c, src/sudo_noexec.c:
+ Use sudo_basename() instead of doing the equivalent manually.
+ [67e2b5d68a73]
+
+ * MANIFEST, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/basename.c, lib/util/util.exp.in:
+ Add a GNU-compatible version of basename(3). Unlike POSIX
+ basename(3), the GNU variant does not modify its argument. Note that
+ basename of a path ending in "/" returns an empty string.
+ [693e1d39718a]
+
+2021-02-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/iolog_fileio.c:
+ feof(3) returns non-zero at EOF, not necessarily 1. On Illumos at
+ least it returns a value other than 1.
+ [fc2242fe7c6e]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Portable workaround for getdelim(3) implementations modify buf on
+ EOF. We should assume that the contents of buf are undefined when
+ getdelim(3) returns -1. We now peek ahead one char and skip the
+ getdelim(3) call if EOF is detected. This will preserve the original
+ value of the last line.
+ [1e353f05a0fa]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Some getdelim(3) implementations write a NUL to the buffer on EOF.
+ AIX and Illumos appear to have this behavior. We now preserve the
+ first character of the buffer on EOF to work around this. Fixes
+ reporting of syntax errors on the last line of a file.
+ [22611c14c1d1]
+
+ * plugins/sudoers/Makefile.in:
+ Fuzz the example sudoers file, not the default one. The default
+ sudoers uses @includedir which can result in different output,
+ depending on the permissions of /etc/sudoers.d.
+ [1b325a1d0e0a]
+
+ * configure, configure.ac:
+ illumos has a broken fmemopen(3), don't use it.
+ [d297ee0339e6]
+
+2021-02-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h:
+ Add configure check for SSIZE_MAX
+ [ca7699154705]
+
+ * lib/iolog/iolog_json.c:
+ Suppress PVS Studio false positives.
+ [6d8fcec047e5]
+
+ * src/sesh.c:
+ Silence a clang analyzer false positive.
+ [8bc3e89f6fbb]
+
+ * plugins/sudoers/toke_util.c:
+ Silence a clang analyzer false positive.
+ [2489166fc372]
+
+ * lib/fuzzstub/fuzzstub.c:
+ Fix CID 217123, size check always false on 64-bit systems.
+ [3c018b5d43a8]
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c:
+ Make open_sudoers() always return NULL like fuzz_sudoers.c
+ [042de90307ae]
+
+ * plugins/sudoers/regress/sudoers/test4.toke.ok,
+ plugins/sudoers/regress/sudoers/test5.toke.ok,
+ plugins/sudoers/regress/sudoers/test7.toke.ok,
+ plugins/sudoers/regress/sudoers/test8.toke.ok:
+ Update *.toke.ok now that lexer doesn't call sudoerserror() itself.
+ [d60c0d33b5b4]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.h, plugins/sudoers/toke.l:
+ The lexer now sets an error string before returning ERROR. The
+ parser will use that when reporting on an ERROR state. This prevents
+ the lexer from reporting errors about tokens that are not actually
+ consumed by the parser and we don't have to worry about both the
+ lexer and the parser reporting errors. It also means we only get one
+ error per sudoers line.
+ [7ffb0d28862f]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l:
+ Go back to storing the last error file/line in sudoerserrorf(). This
+ is still the best way to avoid displaying more than one error per
+ line.
+ [21da59d69c5f]
+
+ * configure, configure.ac:
+ Add -fsanitize=fuzzer-no-link to ASAN_LDFLAGS too, not just
+ ASAN_CFLAGS.
+ [d3c719c72d79]
+
+ * MANIFEST, Makefile.in, doc/Makefile.in, examples/Makefile.in,
+ include/Makefile.in, lib/eventlog/Makefile.in,
+ lib/fuzzstub/Makefile.in, lib/iolog/Makefile.in,
+ lib/logsrv/Makefile.in, lib/util/Makefile.in, lib/zlib/Makefile.in,
+ logsrvd/Makefile.in, plugins/audit_json/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/python/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sample_approval/Makefile.in,
+ plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.out.ok,
+ plugins/system_group/Makefile.in, src/Makefile.in:
+ Add fuzz Makefile target and run fuzzer corpus in make check.
+ [a66085f05dea]
+
+2021-02-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, Makefile.in, configure, configure.ac,
+ lib/fuzzstub/Makefile.in, lib/fuzzstub/fuzzstub.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_json.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_legacy.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_timing.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c:
+ Add stub library that just feeds files to the fuzzing target. This
+ will allow the fuzzers to be run as part of "make check".
+ [aa8fda20c3f8]
+
+ * scripts/mkpkg:
+ Append to CFLAGS and LDFLAGS instead of overriding them when adding
+ -m64.
+ [d02cf3c28198]
+
+ * config.h.in, configure, configure.ac,
+ lib/iolog/regress/fuzz/fuzz_iolog_json.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_legacy.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_timing.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c:
+ Fall back to a temp file if fmemopen() is not available().
+ [87f804b98c18]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Add missing return statement when NO_LEAKS is not defined.
+ [25b8e1041b62]
+
+ * lib/eventlog/Makefile.in:
+ Remove remnants of liblogsrv.
+ [5030114bb12f]
+
+ * INSTALL, configure, configure.ac, lib/iolog/Makefile.in,
+ plugins/sudoers/Makefile.in:
+ Add --enable-fuzzer-linker and --enable-fuzzer-engine options. These
+ will allow the fuzzers to be built as part of oss-fuzz.
+ [c3176bd8b95b]
+
+2021-02-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .gitignore, .hgignore:
+ Sync ignore files.
+ [ddf136d412f7]
+
+ * plugins/sudoers/Makefile.in:
+ Fix linking of sudoers fuzzers with static libsudo_util.
+ [86d07a5a671d]
+
+ * INSTALL, configure, configure.ac, lib/iolog/Makefile.in,
+ plugins/sudoers/Makefile.in:
+ Add --enable-fuzzer option to use when building fuzzers
+ [01e31362c2b0]
+
+ * INSTALL, configure, configure.ac:
+ Replace --enable-asan with --enable-sanitizer It is not possible to
+ set the sanitizer flags at configure time.
+ [115d869e1d55]
+
+2021-02-06 Anton Bershanskiy <45960703+bershanskiy@users.noreply.github.com>
+
+ * src/copy_file.c:
+ Fix comment typo in src/copy_file.c
+ [60dbf6da4712]
+
+2021-02-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/Makefile.in, lib/iolog/regress/fuzz/fuzz_iolog_json.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_legacy.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_timing.c,
+ plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c:
+ Build (but don't run) fuzzers as part of "make check". Uses a stub
+ to make it possible to link w/o libfuzzer. The goal is to ensure the
+ fuzzers are always buildable and avoid bit rot.
+ [9186e252b8bf]
+
+ * lib/iolog/Makefile.in, plugins/sudoers/Makefile.in:
+ Add libsudo_eventlog.la as a dependency of libsudo_iolog.la No
+ longer need to link against libsudo_eventlog.la in sudoers.
+ [508097f86035]
+
+2021-02-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, lib/iolog/regress/corpus/log_json/id.json,
+ lib/iolog/regress/corpus/log_json/ls.json,
+ lib/iolog/regress/corpus/log_json/mailq.json,
+ lib/iolog/regress/corpus/log_json/make.json,
+ lib/iolog/regress/corpus/log_json/pkg_add.json,
+ lib/iolog/regress/corpus/log_json/pkg_delete.json,
+ lib/iolog/regress/corpus/log_json/printenv.json,
+ lib/iolog/regress/corpus/log_legacy/id,
+ lib/iolog/regress/corpus/log_legacy/ls,
+ lib/iolog/regress/corpus/log_legacy/mailq,
+ lib/iolog/regress/corpus/log_legacy/make,
+ lib/iolog/regress/corpus/log_legacy/pkg_add,
+ lib/iolog/regress/corpus/log_legacy/pkg_delete,
+ lib/iolog/regress/corpus/log_legacy/printenv,
+ lib/iolog/regress/corpus/timing/timing.1,
+ lib/iolog/regress/corpus/timing/timing.2,
+ lib/iolog/regress/corpus/timing/timing.3,
+ lib/iolog/regress/corpus/timing/timing.4:
+ Add more test files for fuzzers.
+ [22256acfbe23]
+
+2021-02-05 Daniel Milnes <thebeanogamer@gmail.com>
+
+ * doc/sudo.mdoc.in:
+ Fix the typo in the mdoc
+ [e0ad7f93e678]
+
+ * doc/sudo.man.in:
+ Fix a tiny typo in the Sudo manpage
+ [d52c308677bf]
+
+2021-02-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, lib/iolog/regress/fuzz/fuzz_iolog_timing.c:
+ fuzzer for I/O log timing files
+ [7b32f8eecfd6]
+
+ * lib/iolog/iolog_json.c:
+ In JSON, name/value pairs must be separated by a comma. Previously
+ we didn't require the comma to be there.
+ [bb70cecf6360]
+
+ * lib/iolog/iolog_json.c:
+ Detect integer overflow when converting JSON_ARRAY to string vector.
+ Extremely unlikely to happen but better safe than sorry.
+ [60a7a4d3a1d8]
+
+2021-02-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Only strip double quotes from an include path if len >= 2. Found
+ locally using libfuzzer/oss-fuzz.
+ [274d0a05081b]
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ Don't allow the sudoers fuzzer to open include files. If we allow
+ the fuzzer to choose include paths it will include random files in
+ the file system. This leads to bug reports that cannot be
+ reproduced.
+ [b8ffce94f30a]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ If getdelim() returns a string with embedded NULs, truncate on first
+ one. This should avoid some issues with the fuzzer.
+ [e90e61d4bb0e]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Reallocate the buffer correctly when appending a newline. Fixes a
+ potential buffer overflow introduced in the last commit.
+ [50b0f77aed5f]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y:
+ Don't free the alias name in alias_add() if the alias already
+ exists. We need to be able to display it using alias_error(). Only
+ free what we actually allocated in alias_add() on error and let the
+ caller handle cleanup. Note that we cannot completely fill in the
+ alias until it is inserted. Otherwise, we will have modified the
+ file and members parameters even if there was an error. As a result,
+ we have to remove those from the leak list after alias_add(), not
+ before.
+ [6a920646d7d1]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Fix NUL termination when parsing a sudoers file with no ending
+ newline. oss-fuzz issue #30252
+ [5c75d8e15966]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ sudoersrestart() does not reset state to INITIAL, do it in
+ init_lexer(). Fixes spurious errors from fuzz_sudoers, which calls
+ the parser multiple times.
+ [bf2c1c3b82e6]
+
+ * plugins/sudoers/regress/parser/check_fill.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.h, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c:
+ Push lexer leak tracking down into check_fill.c. This lets us track
+ things correctly when buffers are realloc()d. Rewrote fill() and
+ append() to be more readable.
+ [a1e61a4a7aad]
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/visudo.c:
+ Use sudoersrestart() in fuzz_sudoers.c Since we run the parser
+ multiple times we need to restart it each time.
+ [64792d363f62]
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ Parser needs user_shost for the %h escape in @include expansion.
+ Fixes oss-fuzz issue #30238
+ [b043e413be31]
+
+ * INSTALL:
+ The --disable-leaks option is not recommended for production use.
+ [cb37a56f4e99]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Remove options from the leak list before freeing them. Should fix
+ oss-fuzz issue #30236
+ [1ee6dac8c027]
+
+ * MANIFEST, include/sudo_iolog.h, lib/iolog/iolog_util.c,
+ lib/iolog/regress/fuzz/fuzz_iolog_legacy.c:
+ Add fuzzer for legacy I/O log info file.
+ [3f4ed83660ca]
+
+ * doc/Makefile.in, plugins/sudoers/Makefile.in:
+ Fix uninstall target; there were missing line continuation chars.
+ GitHub issue #87
+ [02cffb51c15c]
+
+2021-02-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/parse_ldif.c:
+ Don't close fp in sudoers_parse_ldif() The caller should be the one
+ to handle this.
+ [e8d830851379]
+
+ * .gitignore, .hgignore:
+ Update ignore files.
+ [0c8245d8097c]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y:
+ Got back to calling alias_free() on alias_add() failure. We now need
+ to remove the name and members from the leak list
+ *before* calling alias_add() since alias_add() will consume them for
+ both success and failure.
+ [65c95a84f8ca]
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ close sudoersin, not fp, and reset it to be safe
+ [f616d1c7c09a]
+
+ * lib/iolog/regress/fuzz/fuzz_iolog_json.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c:
+ Add missing fclose(3) of fmemopen(3) stream; it does not modify the
+ data.
+ [9207901dcccd]
+
+ * lib/iolog/iolog_json.c:
+ Check for unexpected value after checking the name, not before.
+ [6f973cc4378d]
+
+ * lib/util/progname.c:
+ Allow getprogname() to succeed as long as __progname is present.
+ Also simplify the progname code so we only need a single
+ implementation.
+ [300a29bd117e]
+
+ * lib/iolog/iolog_json.c:
+ Fix potential leak of evlog->runuser. Also warn if we find an
+ unexpected JSON type.
+ [0ec615b3d4e0]
+
+2021-02-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c:
+ Parse into a local parse_tree and add missing cleanup. Since
+ parsed_policy is for the sudoers parser we should declare our own.
+ [c418d65e7bb4]
+
+ * plugins/sudoers/regress/fuzz/fuzz_sudoers.c:
+ Call init_parser() after parsing to clean up completely.
+ [2063d26ab401]
+
+ * MANIFEST, plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/regress/sudoers/test25.in,
+ plugins/sudoers/regress/sudoers/test25.json.ok,
+ plugins/sudoers/regress/sudoers/test25.ldif.ok,
+ plugins/sudoers/regress/sudoers/test25.out.ok,
+ plugins/sudoers/regress/sudoers/test25.toke.ok,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c:
+ Plug a few more parser leaks.
+ [c9478efdd65d]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Make parser_leak_remove(type, NULL) a no-op.
+ [7699e99a028a]
+
+ * MANIFEST, lib/iolog/regress/fuzz/fuzz_iolog_json.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers.c,
+ plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c:
+ Add initial fuzzers to be used by oss-fuzz. These are not yet hooked
+ up to the sudo build.
+ [5593a755f359]
+
+ * plugins/sudoers/gc.c, plugins/sudoers/sudoers.h:
+ Garbage collect unused gc_remove() function.
+ [ff561edd846e]
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/testsudoers/test11.sh,
+ plugins/sudoers/regress/testsudoers/test12.sh,
+ plugins/sudoers/regress/testsudoers/test13.sh,
+ plugins/sudoers/regress/testsudoers/test4.sh,
+ plugins/sudoers/regress/testsudoers/test5.sh:
+ The parser should be leak free, re-enable leak detection in ASAN.
+ [a89599540a5a]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.h, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.h, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/toke_util.c:
+ Add garbage collection to the sudoers parser to clean up on error.
+ This makes it possible to avoid memory leaks when there is a parse
+ error.
+ [ef739da324bb]
+
+2021-01-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/ldap.c, plugins/sudoers/ldap_util.c,
+ plugins/sudoers/parse.h, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudo_ldap.h:
+ Move new_member_all to ldap_util.c, it is only used by ldap/sssd.
+ [9df2efb6956a]
+
+2021-01-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/iolog_json.c:
+ Fix crashes trying to parse invalid JSON. Found locally using
+ libfuzzer/oss-fuzz.
+ [b74c8c260d60]
+
+ * lib/iolog/iolog_json.c:
+ Plug memory leak if a key is listed more than once in the log.json
+ file.
+ [764ef247f13e]
+
+ * lib/iolog/regress/iolog_json/check_iolog_json.c:
+ Fix crash when file does not exist.
+ [55a46b75e6ed]
+
+ * plugins/sudoers/gentime.c:
+ Strict tz offset parsing. Fixes an out of bounds read found locally
+ using libfuzzer/oss-fuzz.
+ [72266f1af75d]
+
+ * plugins/sudoers/ldap_util.c:
+ Don't leak memory for duplicate command options. The last option
+ wins but we also now warn about the duplicate. Found locally using
+ libfuzzer/oss-fuzz.
+ [f1cd342e62f7]
+
+ * plugins/sudoers/ldap_util.c:
+ Copy command options when converting a sudoRole with multiple
+ sudoCommands. A sudoRole with multiple sudoCommands is converted to
+ a privilege with multiple cmndspecs. However, we were not copying
+ some of the command options to subsequent cmndspecs in the list.
+ [d8309574a756]
+
+ * plugins/sudoers/parse_ldif.c:
+ Fix memory leak if the last line is folded. Fixes issue 30080 by
+ ClusterFuzz-External
+ [404f38aa19a6]
+
+ * INSTALL, configure, configure.ac:
+ Add --disable-leaks configure option. This enables the extra freeing
+ of memory before exit also enabled by --enable-asan. To be used by
+ oss-fuzz.
+ [faddd42273a4]
+
+ * plugins/sudoers/gentime.c:
+ Stricter parsing of generalized time. Fixes potential out of bounds
+ read found by libfuzzer/oss-fuzz.
+ [4548e29ea5e0]
+
+2021-01-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/parse_ldif.c:
+ Don't bother calling ldif_to_sudoers() if there are no roles to
+ convert.
+ [242394d46fb1]
+
+ * lib/iolog/iolog_json.c:
+ In json_stack_push() treat stack exhaustion like memory allocation
+ failure. Return NULL instead of treating as a fatal error. This
+ should make life a little easier for oss-fuzz.
+ [84c7c3b7971a]
+
+ * plugins/sudoers/sudoers.c:
+ Update comment about return values for resolve_host().
+ [0e92fe582db1]
+
+ * plugins/sudoers/logging.c, plugins/sudoers/policy.c:
+ Fix NO_ROOT_MAILER, broken by the eventlog refactor in sudo 1.9.4.
+ init_eventlog_config() is called immediately after initializing the
+ Defaults settings, which is before struct sudo_user is setup. This
+ adds a call to eventlog_set_mailuid() if NO_ROOT_MAILER is defined
+ after the invoking user is determined. Reported by Roman Fiedler.
+ [e0d4f196ba02]
+
+2021-01-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST:
+ Add plugins/sudoers/strvec_join.c
+ [1dfeb8ab9fdb]
+
+ * plugins/sudoers/strvec_join.c, plugins/sudoers/sudoers.c:
+ Fix compilation on systems without a native strlcpy() function.
+ [7b28feb4350a]
+
+ * logsrvd/logsrvd.c, logsrvd/sendlog.c:
+ Break up the long help string into multiple printf() statements. AIX
+ xlc compiler doesn't like cpp directives in between strings. Also
+ fixes a complaint from cppcheck and makes translation easier.
+ [e55b4061f598]
+
+ * plugins/sudoers/regress/unescape/check_unesc.c,
+ plugins/sudoers/strvec_join.c, plugins/sudoers/sudoers.h:
+ strvec_join: free result on error and actually use separator char
+ [801546807a8a]
+
+2021-01-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/unescape/check_unesc.c:
+ Test strvec_join() using strlcpy_unesc(). Emulates an overflow like:
+ sudoedit -s '\' `perl -e 'print "A" x 65536'`
+ [8d9a063adde5]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/strvec_join.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Refactor code to flatten an argument vector into a string. This is
+ used when building up the user_args string.
+ [a6ae655d91a1]
+
+ * MANIFEST, plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/unescape/check_unesc.c,
+ plugins/sudoers/strlcpy_unesc.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Add strlcpy_unescape() function to undo escaping from front-end.
+ Includes unit test.
+ [abfaa390d275]
+
+ * plugins/sudoers/parse_ldif.c:
+ Add missing check for reallocarray() failure. Found by OSS-Fuzz.
+ [fcda06966ed7]
+
+2021-01-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/pyhelpers.c, plugins/python/pyhelpers.h,
+ plugins/python/python_convmessage.c,
+ plugins/python/sudo_python_module.c:
+ Remove Py_SSIZE2SIZE to quiet cppcheck warnings. Tuple size cannot
+ be negative and we already handle the case where it is zero.
+ [d6ec5e558a0e]
+
+ * src/parse_args.c:
+ The program name may now only be "sudo" or "sudoedit". We no longer
+ need to check for any string that ends in "edit".
+ [caed524c6ba0]
+
+2021-01-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_5p2 for changeset 83685ffbc4df
+ [74a2ddc3e4a4] <1.9>
+
+ * Merge sudo 1.9.5p2 from tip
+ [83685ffbc4df] [SUDO_1_9_5p2] <1.9>
+
+ * plugins/sudoers/timestamp.c:
+ Fix the memset offset when converting a v1 timestamp to TS_LOCKEXCL.
+ We want to zero the struct starting at flags, not type (which was
+ just set). Found by Qualys.
+ [09f98816fc89]
+
+ * src/parse_args.c:
+ Don't assume that argv is allocated as a single flat buffer. While
+ this is how the kernel behaves it is not a portable assumption. The
+ assumption may also be violated if getopt_long(3) permutes
+ arguments. Found by Qualys.
+ [c125fbe68783]
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.5p2
+ [89a357d8da4e]
+
+ * src/parse_args.c:
+ Reset valid_flags to MODE_NONINTERACTIVE for sudoedit. This is
+ consistent with how the -e option is handled. Also reject -H and -P
+ flags for sudoedit as was done in sudo 1.7. Found by Qualys, this is
+ part of the fix for CVE-2021-3156.
+ [9b97f1787804]
+
+ * plugins/sudoers/policy.c:
+ Add sudoedit flag checks in plugin that are consistent with front-
+ end. Don't assume the sudo front-end is sending reasonable mode
+ flags. These checks need to be kept consistent between the sudo
+ front-end and the sudoers plugin.
+ [a97dc92eae6b]
+
+ * plugins/sudoers/sudoers.c:
+ Fix potential buffer overflow when unescaping backslashes in
+ user_args. Also, do not try to unescaping backslashes unless in run
+ mode *and* we are running the command via a shell. Found by Qualys,
+ this fixes CVE-2021-3156.
+ [049ad90590be]
+
+2021-01-22 Fabrice Fontaine <fontaine.fabrice@gmail.com>
+
+ * lib/eventlog/Makefile.in:
+ lib/eventlog/Makefile.in: fix static build without closefrom
+
+ Since version 1.9.4 and https://github.com/sudo-
+ project/sudo/commit/bd1ca79cca827a92e904f022e49df121931d4ff5, when
+ closefrom is not available, libsudo_eventlog.a depends on
+ libsudo_util.a. So reflect this dependency in the libtool file to
+ avoid the following static build failure of logsrvd:
+
+ /bin/bash ../libtool --tag=disable-static --mode=link
+ /home/buildroot/autobuild/instance-1/output-1/host/bin/powerpc-
+ linux-gcc -o sudo_logsrvd logsrv_util.o iolog_writer.o logsrvd.o
+ logsrvd_conf.o -static -Wl,--enable-new-dtags -Wl,-z,relro
+ ../lib/iolog/libsudo_iolog.la ../lib/eventlog/libsudo_eventlog.la
+ ../lib/logsrv/liblogsrv.la /bin/bash ../libtool --tag=disable-static
+ --mode=link
+ /home/buildroot/autobuild/instance-1/output-1/host/bin/powerpc-
+ linux-gcc -o sudo_sendlog logsrv_util.o sendlog.o -static -Wl,--
+ enable-new-dtags -Wl,-z,relro ../lib/iolog/libsudo_iolog.la
+ ../lib/eventlog/libsudo_eventlog.la ../lib/logsrv/liblogsrv.la
+ libtool: link:
+ /home/buildroot/autobuild/instance-1/output-1/host/bin/powerpc-
+ linux-gcc -o sudo_logsrvd logsrv_util.o iolog_writer.o logsrvd.o
+ logsrvd_conf.o -static -Wl,--enable-new-dtags -Wl,-z -Wl,relro
+ ../lib/iolog/.libs/libsudo_iolog.a /home/buildroot/autobuild/instanc
+ e-1/output-1/build/sudo-1.9.5p1/lib/util/.libs/libsudo_util.a
+ -lpthread -lz ../lib/eventlog/.libs/libsudo_eventlog.a
+ ../lib/logsrv/.libs/liblogsrv.a
+ /home/buildroot/autobuild/instance-1/output-1/host/opt/ext-
+ toolchain/bin/../lib/gcc/powerpc-buildroot-linux-
+ uclibc/8.3.0/../../../../powerpc-buildroot-linux-uclibc/bin/ld:
+ ../lib/eventlog/.libs/libsudo_eventlog.a(eventlog.o): in function
+ `send_mail.constprop.1': eventlog.c:(.text+0x149c): undefined
+ reference to `sudo_closefrom' collect2: error: ld returned 1 exit
+ status
+
+ Fixes:
+ - http://autobuild.buildroot.org/results/515b45f876fa9de03c9235f86017f
+ 4dc10eb3b54
+
+ Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
+ [4e42d276c336]
+
+2021-01-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/log_client.c:
+ Do not add an unfinished write buffer to the queue if it is already
+ present. In client_msg_cb() we only remove a buffer from the queue
+ when it is finished. Inserting the buf again can cause a cycle in
+ the queue.
+ [b398dcc0933d]
+
+2021-01-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/log_client.c:
+ Fix problem when SSL_read() returns SSL_ERROR_WANT_WRITE. This can
+ happen when the socket cannot be written to immediately. We need to
+ set the read_instead_of_write flag in that case, _not_
+ write_instead_of_read. Also sync comments with sendlog.c. Bug #954
+ [e4239bb932aa]
+
+2021-01-18 Pavel Březina <pbrezina@redhat.com>
+
+ * plugins/sudoers/auth/pam.c:
+ pam: pass KRB5CCNAME to pam_authenticate environment if available
+
+ If a PAM module wants to authenticate user using GSSAPI, the
+ authentication is broken if non-default ccache name is used in
+ KRB5CCNAME environment variable.
+
+ One way to mitigate this would be to add this to env_keep, but this
+ also makes the variable available in the executed command which may
+ not be always desirable.
+
+ This patch sets KRB5CCNAME for pam_authenticate only, if it is
+ available and not yet set.
+ [90aba6ba6e03]
+
+2021-01-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/progname.c:
+ Fix setprogname() emulation on systems without it. For fully-
+ qualified paths, store the string starting after the last slash, not
+ at the slash itself.
+ [111fde52d116]
+
+2021-01-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_5p1 for changeset 3a873a732416
+ [e837c76279bc] <1.9>
+
+ * Merge sudo 1.9.5p1 from tip
+ [3a873a732416] [SUDO_1_9_5p1] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.5p1
+ [2dbbab94d4b6]
+
+ * src/sudo_edit.c:
+ Run the editor with the user's real and effective uid and gid. Fixes
+ a bug introduced in sudo 1.9.5 where the editor was run setuid root
+ unless SELinux RBAC was in use.
+ [30fe53c07aa7]
+
+ * NEWS:
+ fix typo
+ [52e7767881ba]
+
+ * src/copy_file.c, src/edit_open.c:
+ Add casts to quiet two warnings on Solaris.
+ [f76126f6d68d]
+
+2021-01-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_5 for changeset 4059f5520d9d
+ [ee76c8a938de] <1.9>
+
+ * Merge sudo 1.9.5 from tip
+ [4059f5520d9d] [SUDO_1_9_5] <1.9>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ Update .pot files for 1.9.5.
+ [49dae07bda23]
+
+2021-01-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, configure, configure.ac, doc/LICENSE, etc/sudo-logsrvd.pp,
+ etc/sudo-python.pp, etc/sudo.pp:
+ Sudo 1.9.5
+ [3a0e500981a8]
+
+ * doc/sudoers.man.in, doc/sudoers.man.in.sed, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/policy.c:
+ Allow SELinux support to be disabled via the sudoers file. Defaults
+ to true if sudo is built with SELinux support and SELinux is not
+ disabled on the system.
+ [c457eaae8692]
+
+2021-01-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/python_importblocker.c:
+ Add a comment to verify_import() to clarify its purpose.
+ [30ef680f4104]
+
+ * lib/eventlog/eventlog.c, lib/util/arc4random.c,
+ lib/util/sudo_debug.c, plugins/audit_json/audit_json.c,
+ plugins/python/python_convmessage.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/goodpath.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.h, plugins/sudoers/gram.y,
+ plugins/sudoers/rcstr.c, plugins/sudoers/redblack.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/visudo.c,
+ src/exec_common.c, src/sesh.c, src/sudo.c, src/sudo_edit.c:
+ Suppress PVS Studio false positives.
+ [077f46549351]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Plug a memory leak in sudoerserrorf().
+ [a3c14cf0283e]
+
+ * plugins/sudoers/editor.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/ldap_util.c, plugins/sudoers/parse.h,
+ plugins/sudoers/starttime.c, plugins/sudoers/tsgetgrpw.c,
+ src/ttyname.c:
+ Quiet a few harmless cppcheck warnings.
+ [ab123790b3fd]
+
+ * src/copy_file.c, src/sudo_edit.c:
+ In sudoedit, use sudo_check_temp_file() for non-SELinux too.
+ [b5d5bd506487]
+
+ * MANIFEST, src/Makefile.in, src/edit_open.c, src/sesh.c,
+ src/sudo_edit.c, src/sudo_edit.h, src/sudo_exec.h:
+ Move safe open code out of sudo_edit.c and into edit_open.c.
+ [108fcca05798]
+
+ * src/Makefile.in, src/edit_open.c, src/sesh.c, src/sudo_edit.c,
+ src/sudo_edit.h:
+ Add directory writability checks for SELinux RBAC sudoedit. These
+ were never added to the SELinux RBAC path.
+ [0d4f28b5a8e2]
+
+ * src/edit_open.c, src/exec.c, src/exec_pty.c, src/sesh.c, src/sudo.c,
+ src/sudo.h, src/sudo_edit.c, src/sudo_edit.h, src/tgetpass.c:
+ Add struct sudo_cred to hold the invoking or runas user credentials.
+ We can use this when we need to pass around credential info instead
+ of the user_details and command_details structs.
+ [20594f3f00c1]
+
+ * src/edit_open.c, src/sesh.c, src/sudo_edit.c, src/sudo_edit.h:
+ Rename run_cred -> cur_cred and stash existing creds in
+ set_tmpdir(). For sudo_edit_open() et al what we need is a copy of
+ the current cred to restore after dir_is_writable() changes to the
+ user cred.
+ [dcfce8a11282]
+
+ * configure, configure.ac, include/sudo_compat.h, lib/util/progname.c:
+ Add setprogname(3) for those without it.
+ [e2f1d1ecedb0]
+
+ * src/sesh.c, src/sudo_edit.c:
+ Split up sesh_sudoedit() so it is organized more like sudo_edit.c.
+ The new sesh_edit_create_tfiles() and sesh_edit_copy_tfiles()
+ functions are analogous to sudo_edit_create_tfiles() and
+ sudo_edit_copy_tfiles(). Also use "sudoedit" in the warning/error
+ messages from sesh_sudoedit(). Otherwise, the user gets a mix of
+ messages from sudoedit and sesh.
+ [5510be4b2129]
+
+ * Makefile.in, lib/eventlog/Makefile.in, lib/iolog/Makefile.in,
+ lib/logsrv/Makefile.in, lib/util/Makefile.in, logsrvd/Makefile.in,
+ plugins/audit_json/Makefile.in, plugins/group_file/Makefile.in,
+ plugins/python/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sample_approval/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/Makefile.in:
+ Remove the --force option from the cppcheck args, it causes errors.
+ [57f2ad72e874]
+
+ * include/sudo_util.h, lib/util/progname.c, lib/util/util.exp.in,
+ src/sudo.c:
+ For sudo, only allow "sudo" or "sudoedit" as the program name. The
+ program name is also used when matching Debug lines in sudo.conf. We
+ don't want the user to be able to influence sudo.conf Debug
+ matching. The string "sudoedit" is treated the same as "sudo" in
+ sudo.conf. Problem reported by Matthias Gerstner of SUSE.
+ [1d32c53859f9]
+
+ * lib/iolog/iolog_fileio.c, lib/util/sudo_debug.c,
+ plugins/group_file/getgrent.c, plugins/sudoers/linux_audit.c,
+ plugins/sudoers/tsgetgrpw.c:
+ Check the return value of fcntl() when setting FD_CLOEXEC. This
+ should never fail unless the fd is invalid. Problem reported by
+ Matthias Gerstner of SUSE.
+ [f1ca39a0d870]
+
+ * src/sudo_edit.c:
+ Fix potential directory existing info leak in sudoedit. When
+ creating a new file, sudoedit checks to make sure the parent
+ directory exists so it can provide the user with a sensible error
+ message. However, this could be used to test for the existence of
+ directories not normally accessible to the user by pointing to them
+ with a symbolic link when the parent directory is controlled by the
+ user. Problem reported by Matthias Gerstner of SUSE.
+ [ea19d0073c02]
+
+ * src/copy_file.c, src/sesh.c, src/sudo_edit.c, src/sudo_exec.h:
+ Add security checks before using temp files for SELinux RBAC
+ sudoedit. Otherwise, it may be possible for the user running
+ sudoedit to replace the newly-created temporary files with a
+ symbolic link and have sudoedit set the owner of an arbitrary file.
+ Problem reported by Matthias Gerstner of SUSE.
+ [8fcb36ef422a]
+
+ * plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po, po/ko.mo,
+ po/ko.po, po/sr.mo, po/sr.po, po/sv.mo, po/sv.po:
+ Updated translations from translationproject.org
+ [e68c92c767f1]
+
+2021-01-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.c:
+ Use debug_return_int() not debug_return_bool() to return -1. Found
+ by PVS Studio.
+ [f1f67ca51aeb]
+
+ * plugins/sudoers/logging.c:
+ Fix a crash introduced in 1.9.4 when running "sudo -i" as an unknown
+ user.
+ [d1a3f0f4d0f9]
+
+2021-01-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/check.c:
+ Make sure lecture file is a regular file before reading it.
+ [c9c68eff1e45]
+
+2021-01-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Makefile.in, lib/eventlog/Makefile.in, lib/iolog/Makefile.in,
+ lib/logsrv/Makefile.in, lib/util/Makefile.in, logsrvd/Makefile.in,
+ plugins/audit_json/Makefile.in, plugins/group_file/Makefile.in,
+ plugins/group_file/plugin_test.c, plugins/python/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sample_approval/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/parse.h,
+ plugins/system_group/Makefile.in, src/Makefile.in:
+ Minor fixes pointed out by cppcheck. Also add
+ compareBoolExpressionWithInt to suppression list.
+ [52316819700e]
+
+ * logsrvd/logsrvd.c:
+ Avoid potential use after free with eventlog-only connections.
+ Coverity CID 215884.
+ [cca5cffabe42]
+
+ * src/exec.c:
+ Cannot do direct exec of a command when SELinux RBAC is enabled.
+ [2706b0fc1451]
+
+ * MANIFEST, configure, configure.ac, include/sudo_compat.h,
+ lib/util/Makefile.in, lib/util/pread.c, lib/util/pwrite.c,
+ scripts/mkdep.pl:
+ Add emulation of pread(3) and pwrite(3) for systems without them.
+ This makes it possible to remove some ugly #ifdefs and only affects
+ very old systems.
+ [1c2a31bda598]
+
+ * lib/iolog/iolog_fileio.c, plugins/sudoers/match_command.c,
+ plugins/sudoers/timestamp.c:
+ Remove #ifdefs around code using pread(3) and pwrite(3).
+ [3830fdf650df]
+
+ * plugins/sudoers/Makefile.in:
+ Regen now that ldap.c and sssd.c no longer need gram.h
+ [5cc4e107f301]
+
+2020-12-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/fatal.c:
+ Fix deregistration of a callback that is not at the head of the
+ list. The SLIST_FOREACH_PREVPTR macro doesn't work the way I thought
+ it did. Just store our own prev pointer and use that instead.
+ [04c290fe1fcb]
+
+2020-12-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/net_ifs.c:
+ Fix the buffer size parameter when serializing the interface list.
+ Problem reported by Matthias Gerstner of SUSE.
+ [b0cae3ac8e46]
+
+2020-12-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_4p2 for changeset 8aed5221ede9
+ [a74faf363dbb] <1.9>
+
+ * merge sudo 1.9.4p2 from tip
+ [8aed5221ede9] [SUDO_1_9_4p2] <1.9>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.4p2
+ [8bb8ec358990]
+
+ * plugins/sudoers/sudoers.c:
+ The runas user must be set before applying runas-based Defaults.
+ This effectively backs out changeset f738f5ac5350, which made it
+ possible to log the command when an invalid user was specified. The
+ policy plugin API doesn't supply the command until the check
+ function, at which point we've already denied the command due to the
+ invalid user. Bug #951.
+ [8a415f555cf9]
+
+2020-12-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * etc/uncrustify-small.cfg, etc/uncrustify.cfg:
+ Don't enable mod_remove_empty_return We like to use an empty return
+ for stub functions.
+ [018ef129dc24]
+
+2020-12-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_4p1 for changeset 8f65fd9f0f57
+ [e27e424f9f56] <1.9>
+
+ * merge sudo 1.9.4p1 from tip
+ [8f65fd9f0f57] [SUDO_1_9_4p1] <1.9>
+
+ * plugins/sudoers/policy.c:
+ The lower bounds for the "closefrom" option is 3, not 4. This is a
+ regression introduced in sudo 1.8.9 with the strtonum() conversion.
+ Bug #950.
+ [fb06603b9a12]
+
+2020-12-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.4p1
+ [59c37ec1a128]
+
+2020-12-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Direct execution of a command is incompatible with using a log
+ server.
+ [91afbbde217a]
+
+ * plugins/sudoers/audit.c:
+ Set sudoers_audit.close to NULL if not using a log server.
+ [231abb92a3b2]
+
+2020-12-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.guess, config.h.in, config.sub, configure, configure.ac:
+ Regenerate configure script with autoconf 2.71. Also fix some
+ warnings from the new version.
+ [cd1c7615e861]
+
+2020-12-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, src/sudo.c:
+ Define _DARWIN_UNLIMITED_GETGROUPS on macOS to suport > 16 groups.
+ On macOS 10.6 and above, getgroups(2) can return more than
+ NGROUPS_MAX if _DARWIN_UNLIMITED_GETGROUPS or _DARWIN_C_SOURCE is
+ defined. Bug #946
+ [2e7d3c3cf18b]
+
+2020-12-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in, examples/sudo.conf.in:
+ Comment out the default plugin lines in the example sudo.conf. Fixes
+ a problem when there are multiple versions of sudo installed and not
+ all suport the audit plugin, such as on macOS. GitHub issue #75
+ [aaed5d7a3471]
+
+ * plugins/sudoers/logging.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Store the user-provided runas user and group name in struct
+ sudo_user. This makes it available for event logging in case the
+ name doesn't resolve.
+ [98d70ba8a2a6]
+
+ * plugins/sudoers/logging.c:
+ Log submit group to event log.
+ [3e7ace99f7f8]
+
+ * plugins/sudoers/logging.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Store iolog_path in struct sudo_user for use in the event log.
+ [35bc39ec8ad5]
+
+2020-12-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/logging.c, plugins/sudoers/sudoers.c:
+ Defer lookup of runas user until sudoers_main() for better logging.
+ The log message now includes user info and the command attempted.
+ [f738f5ac5350]
+
+ * lib/eventlog/eventlog.c:
+ Don't assume that just because command is non-NULL, argv is non-
+ NULL.
+ [4fac4ae88e4e]
+
+ * plugins/sudoers/logging.c:
+ Fix a crash introduced in 1.9.4 when running command as an unknown
+ user. Bug #948
+ [8b24c140ec7c]
+
+2020-12-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd.c:
+ When shutting down the server, close non-I/O log connections
+ immediately. Avoids a timeout during server shutdown while the
+ server waits for active connections to close.
+ [26bfda2c8f67]
+
+ * src/sudo.c:
+ Audit errors from policy_init_session(), audit_accept(), and
+ audit_reject().
+ [638e583754ac]
+
+ * src/sudo.c:
+ Do not run the command if the audit accept function fails. Also add
+ warnings if the audit reject or error functions fail.
+ [ca94ef438961]
+
+ * plugins/sudoers/log_client.c:
+ Reduce the number of error messages when we can't connect to the
+ audit server. Add the error string to "unable to connect to log
+ server" instead of using an extra error message for the connect(2)
+ failure.
+ [25ac7ac5bfdf]
+
+ * plugins/sudoers/log_client.c:
+ Use correct error message when the TLS connection is dropped. Was:
+ "recv: Unknown error 0", now: "lost connection to log server".
+ [5c3f319b1f75]
+
+2020-12-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/alias.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.h, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.h:
+ Change alias_add() to return bool and set errno on failure. This
+ fixes a localization problem where the error message could have been
+ reported in the wrong locale.
+ [1859fe3da40c]
+
+2020-11-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/eventlog/eventlog.c:
+ Fix build when configured using --without-sendmail Bug #947
+ [41db1aad85bb]
+
+2020-11-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_4 for changeset 74705fb3b956
+ [45a5e742496e] <1.9>
+
+ * merge sudo 1.9.4 from tip
+ [74705fb3b956] [SUDO_1_9_4] <1.9>
+
+ * plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po, po/hr.mo,
+ po/hr.po:
+ Updated translations from translationproject.org
+ [96a5cfe3c66b]
+
+2020-11-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ sudo_logsrvd.conf pid_file change.
+ [fdc0276c7e0e]
+
+ * logsrvd/logsrvd.c:
+ Don't try to unlink a NULL pointer.
+ [95babad9636a]
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ logsrvd/logsrvd.c, logsrvd/logsrvd_conf.c:
+ If pid_file is set to an empty value, disable the use of a pid file.
+ [d4462105ab4b]
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ logsrvd/logsrvd.c:
+ Don't overwrite sudo_logsrvd.pid if it is a symbolic link.
+ [d79f97a0a533]
+
+ * INSTALL, configure, configure.ac, etc/codespell.exclude,
+ plugins/sudoers/env.c:
+ Fix typo detected by codespell 2.0.0 Also avoid some new false
+ positives
+ [d973f44e2396]
+
+2020-11-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * etc/uncrustify-small.cfg, etc/uncrustify.cfg,
+ plugins/python/regress/testhelpers.h, plugins/sudoers/env.c,
+ plugins/sudoers/sudo_ldap_conf.h:
+ Set pp_ignore_define_body=false in uncrustify config. Need to work
+ around a bug that produces closed brace errors, see
+ https://github.com/uncrustify/uncrustify/issues/2569
+ [5e4692fca707]
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt.mo, plugins/sudoers/po/pt.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/zh_TW.mo, plugins/sudoers/po/zh_TW.po, po/hr.mo,
+ po/hr.po, po/it.mo, po/it.po:
+ Updated translations from translationproject.org
+ [156162e6e07e]
+
+2020-11-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/sudo_conf.c:
+ Fix calling sudo_conf_read() multiple times with different
+ conf_types. The change to reinitialize the configuration data when
+ sudo_conf_read() is called again didn't take into account that sudo
+ calls sudo_conf_read() twice--once for the debug info and once for
+ everything else.
+ [b6869b7da3c2]
+
+2020-11-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c:
+ Don't free the private copy of the environment until the close
+ function. We may need to use it when logging from the audit reject
+ function.
+ [5118eb5797fb]
+
+ * plugins/sudoers/log_client.c:
+ It is possible for evlog->argv or evlog->envp to be NULL.
+ [798ff96301bf]
+
+ * src/exec_pty.c, src/sudo.c, src/sudo.h:
+ Pass command_info[] to audit plugin on I/O log plugin reject or
+ error. The audit plugin should cope with a NULL command_info but
+ there's no reason not to pass the info when we have it.
+ [e361897d0192]
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ plugins/sudoers/audit.c:
+ For the audit plugin, command_info may be NULL. Fixes a NULL
+ dereference in sudoers_audit when an I/O logging plugin rejects
+ input/output or returns an error.
+ [9abee774e7e1]
+
+ * plugins/sudoers/defaults.c:
+ Add missing initialization of def_log_format to sudo.
+ [8c824f6dcfdd]
+
+2020-11-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac:
+ Newer LibreSSL has SSL_CTX_set_ciphersuites but it is not enabled.
+ Add a check for the function declaration in openssl/ssl.h.
+ [d6d0665572ec]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Event log data is sent to sudo_logsrvd even when not I/O logging.
+ [d720f4ad3d40]
+
+2020-11-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/sudoers.pot:
+ Regenerate sudoers.pot for 1.9.4
+ [127283726e97]
+
+ * NEWS, configure, configure.ac:
+ Update for sudo 1.9.4.
+ [2cb747911aef]
+
+ * plugins/sudoers/audit.c:
+ Update struct eventlog based on command_info[] from front-end. The
+ I/O log path is not known until the I/O log plugins have run and
+ other plugins may alter the execution environment.
+ [3ad14a88052e]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/logging.h,
+ plugins/sudoers/regress/testsudoers/test13.out.ok,
+ plugins/sudoers/toke.h:
+ Add sudoerserrorf(), a printf-style yyerror() function. Use this to
+ display a better error message when using a reserved work in an
+ alias definition.
+ [1bb3915f61b6]
+
+2020-11-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/mkpkg:
+ Build universal binaries on macOS 11.0 and higher. The resulting
+ package should work on Macs based on Apple Silicon.
+ [91cdeda79e66]
+
+2020-11-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/editor.c:
+ Support EDITOR environment variable that includes quotes. Quote
+ support is limited to the beginning of a word. Also handles
+ characters escaped with a backslash.
+ [ebb7f3c6240c]
+
+2020-11-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/Makefile.in, plugins/python/pyhelpers.c,
+ plugins/python/python_plugin_common.c,
+ plugins/python/regress/iohelpers.h, plugins/python/regress/testdata/
+ check_example_debugging_c_calls@diag.log, plugins/python/regress/tes
+ tdata/check_example_debugging_c_calls@info.log, plugins/python/regre
+ ss/testdata/check_example_debugging_plugin@info.log, plugins/python/
+ regress/testdata/check_example_debugging_py_calls@diag.log, plugins/
+ python/regress/testdata/check_example_debugging_py_calls@info.log, p
+ lugins/python/regress/testdata/check_example_group_plugin_is_able_to
+ _debug.log, plugins/python/regress/testdata/check_example_io_plugin_
+ command_log.stored, plugins/python/regress/testdata/check_example_io
+ _plugin_command_log_multiple1.stored, plugins/python/regress/testdat
+ a/check_example_io_plugin_command_log_multiple2.stored, plugins/pyth
+ on/regress/testdata/check_example_io_plugin_failed_to_start_command.
+ stored, plugins/python/regress/testdata/check_example_io_plugin_fail
+ s_with_python_backtrace.stderr, plugins/python/regress/testdata/chec
+ k_example_policy_plugin_validate_invalidate.log, plugins/python/regr
+ ess/testdata/check_loading_fails_not_owned_by_root.stderr, plugins/p
+ ython/regress/testdata/check_loading_fails_wrong_classname.stderr, p
+ lugins/python/regress/testdata/check_loading_fails_wrong_path.stderr
+ , plugins/python/regress/testdata/check_multiple_approval_plugin_and
+ _arguments.stdout, plugins/python/regress/testdata/check_python_plug
+ ins_do_not_affect_each_other.stdout,
+ plugins/python/regress/testhelpers.c,
+ plugins/python/regress/testhelpers.h:
+ Back out regex use in python tests, filter the output instead. This
+ makes it possible to regenerate the test output again. Also adds an
+ update_test_data target to the Makefile.
+ [3837f51a8072]
+
+ * plugins/sudoers/ldap.c:
+ Ignore sudoNotBefore and sudoNotAfter unless ldap.conf contains
+ SUDOERS_TIMED This is consistent with the pre-1.8.24 behavior. Bug
+ #945
+ [d1e1bb5a6cc1]
+
+ * src/sudo.c:
+ Stay setuid until just before executing the command. Fixes a problem
+ with pam_xauth which checks effective and real uids to get the real
+ identity of the user.
+ [2c6fef0107c8]
+
+2020-11-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/ldap.c, plugins/sudoers/ldap_util.c,
+ plugins/sudoers/parse.h, plugins/sudoers/sssd.c:
+ Introduce new_member_all() for code that doesn't include gram.h. The
+ ldap and sssd back-ends no longer require gram.h which fixes a
+ compilation issue with IBM LDAP.
+ [1729532cda27]
+
+ * lib/util/sudo_conf.c, lib/util/sudo_debug.c, logsrvd/logsrvd.c:
+ On SIGHUP, deregister the old debug instance before registering a
+ new one. Otherwise, if debugging is enabled we will get an extra log
+ instance each time sudo_logsrvd reeives SIGHUP which results in
+ duplicate lines in the debug log.
+ [538633994d8a]
+
+2020-11-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/log_client.c, plugins/sudoers/log_client.h:
+ Refactor code to format the client message after the hello.
+ [12d29d129166]
+
+ * doc/sudo_logsrv.proto.man.in, doc/sudo_logsrv.proto.mdoc.in,
+ include/log_server.pb-c.h, lib/eventlog/eventlog.c,
+ lib/logsrv/log_server.pb-c.c, lib/logsrv/log_server.proto,
+ logsrvd/iolog_writer.c, logsrvd/logsrvd.c,
+ plugins/sudoers/log_client.c:
+ Add info_msgs to AlertMessage and populate it. This lets us log
+ eventlog info along with the alert if it is available.
+ [493a047a4463]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h:
+ Use sudoers_to_eventlog() and init_log_details() in
+ sudoers_audit_accept(). log_deserialize_info() can be private to
+ iolog.c again.
+ [0b4e03904f3d]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/audit.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/log_client.c,
+ plugins/sudoers/log_client.h, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h:
+ Log reject and alert messages to the log server if one is defined.
+ [087cf87d10af]
+
+ * plugins/sudoers/logging.c:
+ Treat an authentication failure as a reject, not an alert. This
+ matters when logging via sudo_logsrvd. It also lets us remove a
+ special case in vlog_warning().
+ [ae489d3f20a8]
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ plugins/sudoers/Makefile.in, plugins/sudoers/audit.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_client.c,
+ plugins/sudoers/iolog_plugin.h, plugins/sudoers/log_client.c,
+ plugins/sudoers/sudoers.c:
+ Rename iolog_client -> log_client. The logsrvd client code is now
+ used for more than just I/O logging.
+ [ea47ce43bbee]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/audit.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_plugin.h,
+ plugins/sudoers/log_client.c, plugins/sudoers/log_client.h:
+ Rename iolog_plugin.h to log_client.h. It is no longer I/O log
+ specific and is used by sudoers_audit too.
+ [cde784a59490]
+
+ * configure, configure.ac:
+ Remove hack to define YYTOKENTYPE, it breaks newer bison.
+ [8b919ef33db7]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.h:
+ Regenerate with bison 3.7.3
+ [9fb81b933c43]
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c:
+ Use struct eventlog *evlog, not struct eventlog *details.
+ [a9b5f3c2902f]
+
+2020-11-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/eventlog/eventlog.c:
+ For logsrvd AlertMessages, evlog will be NULL.
+ [d048f7b429d5]
+
+ * lib/eventlog/eventlog.c:
+ Append errstr to reason for alert and reject events if specified.
+ Previously, we logged the error string separately but this is not
+ consistent with how it is logged in other formats.
+ [68c76e530248]
+
+ * plugins/sudoers/logging.c:
+ Fix cut & pasto in debug subsystem.
+ [c39dd60b6d2d]
+
+2020-11-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog_client.c:
+ Refactor code to format InfoMesage array into fmt_info_messages().
+ Add free_info_messages() to free the array.
+ [e6223d325c77]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/audit.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_client.c,
+ plugins/sudoers/iolog_plugin.h:
+ Log accept messages in sudoers_audit if not I/O logging.
+ [cdb5c443c97d]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/iolog_client.c,
+ plugins/sudoers/iolog_plugin.h:
+ Refactor sudoers_io_open_remote() into log_server_open(). Also
+ rename client_close() to log_server_close(). This keeps more of the
+ client code details out of iolog.c and will be used when logging
+ accept messages from the audit plugin.
+ [e3f6ba6768b8]
+
+ * plugins/sudoers/iolog.c:
+ Move argv and envp setting into iolog_deserialize_info().
+ [613b97f1d7bc]
+
+ * logsrvd/logsrvd.c:
+ Avoid early return in handle_accept() if expect_iobufs not set.
+ [918adc8234f0]
+
+2020-11-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ include/sudo_plugin.h, plugins/python/regress/testdata/check_multipl
+ e_approval_plugin_and_arguments.stdout, src/exec.c,
+ src/load_plugins.c:
+ Add event_alloc to the audit plugin API. The sudoers audit plugin
+ will use this to communicate with sudo_logsrvd.
+ [c2fc2911476b]
+
+ * logsrvd/sendlog.c, plugins/sudoers/iolog_client.c:
+ Set server_name before initiating TLS connection so verify function
+ works. Fixes a crash in the SSL_VERIFY_PEER callback. Also call
+ inet_ntop(3) with addr pointer, not sockaddr pointer so we get the
+ correct IP address.
+ [7a7dcebbe889]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h,
+ plugins/sudoers/regress/sudoers/test18.toke.ok,
+ plugins/sudoers/regress/sudoers/test2.ldif.ok,
+ plugins/sudoers/regress/sudoers/test3.ldif.ok,
+ plugins/sudoers/regress/sudoers/test6.ldif.ok,
+ plugins/sudoers/regress/visudo/test2.err.ok,
+ plugins/sudoers/regress/visudo/test3.err.ok,
+ plugins/sudoers/visudo.c:
+ Store column number for aliases, defaults and userspecs too. This is
+ used to provided the column number along with the line number in
+ error messages. For aliases we store the column of the alias name,
+ not the value since that is what visudo generally needs.
+ [1c9d86b88517]
+
+2020-11-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/regress/testsudoers/test11.out.ok,
+ plugins/sudoers/regress/testsudoers/test12.out.ok,
+ plugins/sudoers/regress/testsudoers/test13.out.ok:
+ Display column number in parse error messages too. Bug #841
+ [0aea28dec8f2]
+
+ * plugins/sudoers/iolog_client.c, plugins/sudoers/iolog_plugin.h:
+ Move tls initialized flag into client_closure. We may call
+ tls_init() from multiple places in the future so a static
+ initialized flag will cause problems.
+ [00b2b02c24c5]
+
+ * plugins/sudoers/cvtsudoers_json.c:
+ Fix -Wshadow warnings caused by json enum member.
+ [ea336980bb6a]
+
+2020-10-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * ABOUT-NLS, INSTALL, NEWS, configure.ac, doc/UPGRADE,
+ doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ doc/sudoers_timestamp.man.in, doc/sudoers_timestamp.mdoc.in,
+ doc/visudo.man.in, doc/visudo.mdoc.in, examples/sudo.conf.in,
+ include/compat/getaddrinfo.h, install-sh, lib/util/getaddrinfo.c,
+ lib/util/getentropy.c, lib/util/regress/sudo_conf/test1.in,
+ lib/util/regress/sudo_parseln/test1.in,
+ lib/util/regress/vsyslog/vsyslog_test.c, lib/util/strtoid.c,
+ logsrvd/logsrvd.c, logsrvd/logsrvd_conf.c, logsrvd/sendlog.c,
+ m4/sudo.m4, plugins/group_file/group_file.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.in,
+ plugins/sudoers/editor.c, plugins/sudoers/env.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/gram.y,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/iolog_client.c,
+ plugins/sudoers/stubs.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/timestamp.c,
+ plugins/sudoers/visudo.c, src/load_plugins.c, src/sudo.c,
+ src/sudo_noexec.c, src/tgetpass.c:
+ Apply Google inclusive language guidelines. Also replace backwards
+ with backward.
+ [678fbce6054f]
+
+2020-10-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.ldap.man.in, doc/sudoers.ldap.mdoc.in:
+ Refernce IBM LDAP libs, not Tivoli since that is how it is packaged.
+ We still use Tivoli when talking about the server itself but refer
+ to it as the "IBM Tivoli Directory Server".
+ [9f97a7e6b67a]
+
+ * doc/sudoers.ldap.man.in, doc/sudoers.ldap.mdoc.in:
+ Add a newline before "This option is ..."
+ [853f819f0241]
+
+ * doc/sudoers.man.in:
+ regen
+ [8b29097f2cd1]
+
+2020-10-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/eventlog/regress/logwrap/check_wrap.c,
+ lib/eventlog/regress/logwrap/check_wrap.in,
+ lib/eventlog/regress/logwrap/check_wrap.out.ok:
+ Test eventlog_writeln() when word wrap is disabled.
+ [73acb7fbef59]
+
+ * configure, configure.ac:
+ Bison generates an extra enum containing the parser tokens. This
+ conflicts with the IBM ldap.h at least. Prevent it from being
+ exposed by defining YYTOKENTYPE.
+ [f3445ad76687]
+
+ * configure, configure.ac:
+ IBM LDAP packages use a lib64 directory for 64-bit libraries. We
+ need to add this to LDFLAGS so the linker is able to find the
+ correct libs when building 64-bit binaries.
+ [701b83f6cd13]
+
+ * config.h.in, configure, configure.ac, plugins/sudoers/ldap.c:
+ Use ssl_err2string() in message on ldap_ssl_client_init() failure.
+ Displaying SSL reason code directly is not user-friendly.
+ [aaf272403f3e]
+
+2020-10-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/eventlog/eventlog.c:
+ For JSON logs, write the most important log elements first. This is
+ important for syslog where the record could be truncated.
+ [58fc957c41bb]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/logging.c, plugins/sudoers/sudoers.c:
+ Add log_format sudoers setting to select sudo or json format logs.
+ Defaults to sudo-format logs.
+ [2936d2750af0]
+
+ * include/sudo_json.h, lib/eventlog/eventlog.c, lib/util/json.c:
+ Support "minimal" JSON which skips all non-essention whitespace.
+ This replaces the old "compact" mode which is only used for syslog.
+ [be07bca67019]
+
+ * plugins/sudoers/logging.c:
+ Don't warn about log failure more than once.
+ [b4dc59a58d1d]
+
+2020-10-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/eventlog/eventlog.c:
+ Check for fdopen(3) failure in send_mail().
+ [e08b17bf26ce]
+
+ * MANIFEST, include/sudo_eventlog.h, lib/eventlog/Makefile.in,
+ lib/eventlog/eventlog.c, lib/eventlog/logwrap.c,
+ lib/eventlog/regress/logwrap/check_wrap.c,
+ lib/eventlog/regress/logwrap/check_wrap.in,
+ lib/eventlog/regress/logwrap/check_wrap.out.ok,
+ plugins/sudoers/Makefile.in, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h, plugins/sudoers/logwrap.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/logging/check_wrap.in,
+ plugins/sudoers/regress/logging/check_wrap.out.ok,
+ plugins/sudoers/sudoers.c:
+ Add support for file log line wrapping in libeventlog.
+ [935c30cf7633]
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c,
+ logsrvd/logsrvd_conf.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/stubs.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/testsudoers.c:
+ Use real setters for the eventlog config. This makes it possible to
+ have a base config that the callers can modify instead of replacing
+ the config wholesale.
+ [2ca1e7d376c2]
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c,
+ plugins/sudoers/Makefile.in, plugins/sudoers/audit.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/locale.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/policy.c, plugins/sudoers/stubs.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c:
+ Use libeventlog in sudoers instead of doing our own logging.
+ [d8306755201a]
+
+ * lib/eventlog/eventlog.c, plugins/sudoers/logging.c:
+ Log the short version of the tty in sudoers-format logs. This is
+ consistent with historical practice.
+ [69440e4659a8]
+
+ * lib/eventlog/eventlog.c:
+ Add default values in eventlog_setconf().
+ [582d359a8ec0]
+
+ * include/sudo_eventlog.h, lib/eventlog/Makefile.in,
+ lib/eventlog/eventlog.c, logsrvd/logsrvd.c,
+ plugins/sudoers/Makefile.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/logging.h:
+ Add support for mailing eventlog entries and for logging raw
+ messages. These will be used by the sudoers plugin.
+ [acab8209ddd0]
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c,
+ lib/iolog/iolog_fileio.c:
+ If no JSON callback is provided, store the contents of struct
+ eventlog. This moves the JSON formatting of struct eventlog out of
+ libsudo_iolog and into libsudo_eventlog where it belongs.
+ [260a7ec65485]
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c, logsrvd/logsrvd.c:
+ struct eventlog contains submit_time, no need to pass it in
+ directly.
+ [a3ac404e6a59]
+
+ * include/sudo_eventlog.h, lib/eventlog/eventlog.c, logsrvd/logsrvd.c:
+ Add an errstr argument to eventlog_alert().
+ [e2afd2f1c092]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_client.c, plugins/sudoers/iolog_plugin.h:
+ Make a copy of the strings stored in iolog_details and struct
+ eventlog. Previously, we just made the strings const and relied on
+ the front-end not changing them. Now the sudoers I/O log plugin
+ behavior is consistent with the policy plugin.
+ [406632298bd5]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_client.c, plugins/sudoers/iolog_plugin.h:
+ Use struct eventlog in iolog_details.
+ [c22e05f420fe]
+
+ * include/sudo_eventlog.h, include/sudo_iolog.h,
+ lib/eventlog/eventlog.c, lib/iolog/Makefile.in,
+ lib/iolog/iolog_fileio.c, lib/iolog/iolog_json.c,
+ lib/iolog/iolog_util.c, logsrvd/Makefile.in, logsrvd/iolog_writer.c,
+ logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/sendlog.c,
+ logsrvd/sendlog.h, plugins/sudoers/Makefile.in,
+ plugins/sudoers/iolog.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/sudoreplay.c:
+ Use struct eventlog in place of struct iolog_info.
+ [9fef7a5f077b]
+
+ * logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c:
+ No longer need eventlog-related getters in logsrvd.c
+ [e3ab80a9a892]
+
+ * MANIFEST, logsrvd/Makefile.in, logsrvd/eventlog.c,
+ logsrvd/iolog_writer.c, logsrvd/logsrvd.c, logsrvd/logsrvd.h,
+ logsrvd/logsrvd_conf.c:
+ Use libeventlog in sudo_logsrvd.
+ [3dd22be50c30]
+
+ * MANIFEST, Makefile.in, configure, configure.ac,
+ include/sudo_eventlog.h, lib/eventlog/Makefile.in,
+ lib/eventlog/eventlog.c, logsrvd/logsrvd.h:
+ Refactor eventlog code into a library
+ [2e02c25be009]
+
+2020-10-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/Makefile.in, lib/logsrv/Makefile.in, lib/util/Makefile.in,
+ logsrvd/Makefile.in, plugins/python/Makefile.in,
+ plugins/sudoers/Makefile.in, src/Makefile.in:
+ regen Makefiles
+ [d9064a0c53ae]
+
+ * scripts/mkpkg:
+ Build 64-bit binaries on HP-UX ia64
+ [3f8b599e7d7f]
+
+2020-10-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/Makefile.in:
+ Explicitly set umask when running tests. Some tests create files
+ that must not be world-writable.
+ [9186ea1d2696]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ sudoers_policy_store() -> sudoers_policy_store_result()
+ [3dad5322916b]
+
+2020-10-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Rename sudoers_policy_exec_setup() -> sudoers_policy_store(). It is
+ called even when there is no command to execute. Also pass in status
+ of whether or not the command was accepted.
+ [a0ded23e81c4]
+
+2020-10-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/cvtsudoers/test1.sh,
+ plugins/sudoers/regress/cvtsudoers/test10.sh,
+ plugins/sudoers/regress/cvtsudoers/test11.sh,
+ plugins/sudoers/regress/cvtsudoers/test12.sh,
+ plugins/sudoers/regress/cvtsudoers/test13.sh,
+ plugins/sudoers/regress/cvtsudoers/test14.sh,
+ plugins/sudoers/regress/cvtsudoers/test15.sh,
+ plugins/sudoers/regress/cvtsudoers/test16.sh,
+ plugins/sudoers/regress/cvtsudoers/test17.sh,
+ plugins/sudoers/regress/cvtsudoers/test18.sh,
+ plugins/sudoers/regress/cvtsudoers/test19.sh,
+ plugins/sudoers/regress/cvtsudoers/test2.sh,
+ plugins/sudoers/regress/cvtsudoers/test20.sh,
+ plugins/sudoers/regress/cvtsudoers/test21.sh,
+ plugins/sudoers/regress/cvtsudoers/test22.sh,
+ plugins/sudoers/regress/cvtsudoers/test23.sh,
+ plugins/sudoers/regress/cvtsudoers/test24.sh,
+ plugins/sudoers/regress/cvtsudoers/test25.sh,
+ plugins/sudoers/regress/cvtsudoers/test26.sh,
+ plugins/sudoers/regress/cvtsudoers/test27.sh,
+ plugins/sudoers/regress/cvtsudoers/test28.sh,
+ plugins/sudoers/regress/cvtsudoers/test29.sh,
+ plugins/sudoers/regress/cvtsudoers/test3.sh,
+ plugins/sudoers/regress/cvtsudoers/test30.sh,
+ plugins/sudoers/regress/cvtsudoers/test31.sh,
+ plugins/sudoers/regress/cvtsudoers/test32.sh,
+ plugins/sudoers/regress/cvtsudoers/test33.sh,
+ plugins/sudoers/regress/cvtsudoers/test4.sh,
+ plugins/sudoers/regress/cvtsudoers/test5.sh,
+ plugins/sudoers/regress/cvtsudoers/test6.sh,
+ plugins/sudoers/regress/cvtsudoers/test7.sh,
+ plugins/sudoers/regress/cvtsudoers/test8.sh,
+ plugins/sudoers/regress/cvtsudoers/test9.sh,
+ plugins/sudoers/regress/testsudoers/test1.sh,
+ plugins/sudoers/regress/testsudoers/test10.sh,
+ plugins/sudoers/regress/testsudoers/test11.sh,
+ plugins/sudoers/regress/testsudoers/test12.sh,
+ plugins/sudoers/regress/testsudoers/test13.sh,
+ plugins/sudoers/regress/testsudoers/test14.sh,
+ plugins/sudoers/regress/testsudoers/test15.sh,
+ plugins/sudoers/regress/testsudoers/test2.sh,
+ plugins/sudoers/regress/testsudoers/test3.sh,
+ plugins/sudoers/regress/testsudoers/test4.sh,
+ plugins/sudoers/regress/testsudoers/test5.sh,
+ plugins/sudoers/regress/testsudoers/test6.sh,
+ plugins/sudoers/regress/testsudoers/test7.sh,
+ plugins/sudoers/regress/testsudoers/test8.sh,
+ plugins/sudoers/regress/testsudoers/test9.sh,
+ plugins/sudoers/regress/visudo/test1.sh,
+ plugins/sudoers/regress/visudo/test10.sh,
+ plugins/sudoers/regress/visudo/test2.sh,
+ plugins/sudoers/regress/visudo/test3.sh,
+ plugins/sudoers/regress/visudo/test4.sh,
+ plugins/sudoers/regress/visudo/test5.sh,
+ plugins/sudoers/regress/visudo/test6.sh,
+ plugins/sudoers/regress/visudo/test7.sh,
+ plugins/sudoers/regress/visudo/test8.sh,
+ plugins/sudoers/regress/visudo/test9.sh:
+ Pass path to testsudoers, visudo or cvtsudoers in the environment.
+ Falls back on the unqualified command if the environment variable is
+ not set.
+ [a7b8c413b66d]
+
+2020-10-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sssd.c:
+ Init cmnds to NULL in rule_to_priv() so we don't free a bogus
+ pointer. In the sssd backend, the rule_to_priv() cleanup code
+ assumes cmnds can be passed to fn_free_values(), which was not the
+ case if we receive an error getting values for "sudoCommand". This
+ is a regression introduced in sudo 1.9.1. Fix from Ron Bowes. GitHub
+ issue #67.
+ [a3fe4615f039]
+
+2020-10-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/match_command.c, plugins/sudoers/match_digest.c,
+ plugins/sudoers/parse.h:
+ Pass runchroot to match_digest() too. We use the open fd for the
+ actual I/O but having runchroot makes it possible to report the
+ correct file name in error messages.
+ [2e1d142e2fe5]
+
+2020-10-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ GitHub issue #61 was fixed in sudo 1.9.3.
+ [55e54b3111f0]
+
+2020-09-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/def_data.h, plugins/sudoers/mkdefaults:
+ Fix indentation of enum def_tuple.
+ [237db08cc1a3]
+
+2020-09-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Remove special case EOF handling; lines now always end in a newline.
+ Previously we needed to emulate some of the state transitions that
+ happen at end-of-line at end-of-file as well. Those are no longer
+ needed now that we are guaranteed to always have a newline at the
+ end.
+ [4c0c21b081f7]
+
+2020-09-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Increment sudolinebuf.size after realloc().
+ [b871905c3442]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y,
+ plugins/sudoers/regress/sudoers/test13.toke.ok,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Add a newline at end of line if one is missing. This is simpler than
+ having to support entries that end at EOF too.
+ [cb335acb1064]
+
+ * MANIFEST, plugins/sudoers/regress/testsudoers/test14.out.ok,
+ plugins/sudoers/regress/testsudoers/test14.sh,
+ plugins/sudoers/regress/testsudoers/test15.out.ok,
+ plugins/sudoers/regress/testsudoers/test15.sh:
+ Add tests for entries without a newline.
+ [98a50d8301a8]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Fix handling of a command spec without a newline at the end. For
+ include files, we may need to inject a newline token now that the
+ grammar requires lines to end with a newline or EOF. There is no END
+ (EOF) token processed after popping off an include file since
+ everything is just treated as one big file.
+ [3e6c62ea7237]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Mark sudoerserror() messages for translation.
+ [d6a173cea48b]
+
+ * plugins/sudoers/regress/sudoers/test8.toke.ok,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Fix line number accounting when a string contains a newline. Strings
+ are not allowed to span multiple lines without a continuation
+ character. Also provide a better error message if we are in the
+ middle of a string and hit EOF.
+ [cf34b0a3beba]
+
+2020-09-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/sudoers.h, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l:
+ Use sudoerschar (yychar) instead of last_token. The parser already
+ provides a way to examing the last token processed, we don't need to
+ add our own.
+ [ba35fe36bd56]
+
+2020-09-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/closefrom.c, lib/util/getentropy.c, lib/util/pipe2.c,
+ lib/util/term.c, lib/util/ttyname_dev.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/env.c,
+ plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/gmtoff.c, plugins/sudoers/locale.c,
+ plugins/sudoers/logging.h, plugins/sudoers/policy.c,
+ plugins/sudoers/starttime.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ plugins/system_group/system_group.c, src/load_plugins.c, src/sudo.c,
+ src/sudo_plugin_int.h, src/tgetpass.c, src/ttyname.c:
+ Fix -Wshadow warnings.
+ [5480e97a1160]
+
+ * configure, configure.ac:
+ Add -Wshadow to warning flags if the compiler supports it.
+ [6f29b5ebc2b8]
+
+ * MANIFEST, plugins/sudoers/regress/testsudoers/test13.out.ok,
+ plugins/sudoers/regress/testsudoers/test13.sh:
+ Add test for syntax error when defining an alias using a reserved
+ word.
+ [4c90b3952ed1]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Fix pasto, TIMEOUT not CMND_TIMEOUT.
+ [842ad3a578f2]
+
+ * NEWS, doc/UPGRADE, doc/sudoers.man.in, doc/sudoers.man.in.sed,
+ doc/sudoers.mdoc.in:
+ Document reserved words that cannot be used as alias names. Bug #941
+ [4b37a2174cd2]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/sudoers_version.h:
+ Detect when a reserved word is used when declaring an alias. Now
+ instead of "syntax error, unexpected CHROOT, expecting ALIAS" the
+ message is "syntax error, reserved word used as an alias name" Bug
+ #941
+ [dfc55de5526c]
+
+2020-09-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_3p1 for changeset 02c47b39359e
+ [23bf4d95356d] <1.9>
+
+ * merge sudo 1.9.3p1 from tip
+ [02c47b39359e] [SUDO_1_9_3p1] <1.9>
+
+ * plugins/sudoers/sudoers.c:
+ Fix potential NULL deref in debug code.
+ [c6b8910ac7dc]
+
+ * plugins/sudoers/getspwuid.c:
+ Close the passwd db before calling getpwnam_shadow(3). Otherwise, we
+ will get the non-shadow passwd entry ("*") since we called
+ setpassent(3) earlier to keep the passwd db open.
+ [71ee5e16e4c5]
+
+ * configure, configure.ac:
+ Fix configure test for crypt(3) when it is present in libc. Fixes a
+ regression introduced in sudo 1.9.3.
+ [0d77733de667]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h, plugins/sudoers/sudoers.c:
+ Add SLOG_AUDIT flag for log_warningx() to also audit the message.
+ This lets us combine audit_failure() and log_warningx() calls with
+ the same message.
+ [23a8a5eab2ff]
+
+ * plugins/sudoers/sudoers.c:
+ Log when user-specified command line options are rejected by
+ sudoers. We already audit those but in some cases they were not
+ logged as well.
+ [30d991993763]
+
+ * NEWS, configure, configure.ac:
+ Update for sudo 1.9.3p1
+ [0cbbb7608c3f]
+
+2020-09-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_3 for changeset bdd40c087bec
+ [eca7e986d20f] <1.9>
+
+ * merge sudo 1.9.3 from tip
+ [bdd40c087bec] [SUDO_1_9_3] <1.9>
+
+2020-09-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Move warning about plaintext password to the end of configure. It is
+ unlikely to be noticed at the beginning of the output.
+ [b3b5abcedc73]
+
+2020-09-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt.mo, plugins/sudoers/po/pt.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ plugins/sudoers/po/zh_TW.mo, plugins/sudoers/po/zh_TW.po, po/eo.mo,
+ po/eo.po, po/fi.mo, po/fi.po, po/fr.mo, po/fr.po:
+ Updated translations from translationproject.org
+ [54b5484b2756]
+
+2020-09-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, plugins/sudoers/auth/passwd.c:
+ Use a simple string compare on systems without crypt(3). This is
+ only used on systems without PAM, BSD authentication or AIX
+ authentication. Bug #940.
+ [aed39197f364]
+
+ * src/utmp.c:
+ Fix typo in last commit.
+ [30a77a50f7b2]
+
+2020-09-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sudo_edit.c:
+ Only use faccessat(3) if AT_EACCESS is defined. Apparently Android
+ (bionic) has faccessat() but not AT_EACCESS. Bug #940.
+ [18604919a023]
+
+ * src/utmp.c:
+ Guard use of ttyslot() with HAVE_TTYSLOT, fix guard for
+ utmp_setid(). This should make it easier to compile sudo on Android
+ which doesn't provide a way to write to the utmp file. Bug #940.
+ [69fe5b8426cd]
+
+2020-09-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * po/zh_CN.mo, po/zh_CN.po:
+ Updated translations from translationproject.org
+ [ef72535d71a5]
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt.mo, plugins/sudoers/po/pt.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/zh_TW.mo, plugins/sudoers/po/zh_TW.po, po/cs.mo,
+ po/cs.po, po/de.mo, po/de.po, po/eo.mo, po/eo.po, po/fi.mo,
+ po/fi.po, po/fr.mo, po/fr.po, po/hr.mo, po/hr.po, po/it.mo,
+ po/it.po, po/ja.mo, po/ja.po, po/pl.mo, po/pl.po, po/pt.mo,
+ po/pt.po, po/pt_BR.mo, po/pt_BR.po, po/sr.mo, po/sr.po, po/tr.mo,
+ po/tr.po, po/uk.mo, po/uk.po, po/zh_TW.mo, po/zh_TW.po:
+ Updated translations from translationproject.org
+ [48fdb293a803]
+
+ * configure, configure.ac, plugins/sudoers/po/sudoers.pot:
+ Back out sudo 1.9.3b1 version change.
+ [70cee88da8b1]
+
+2020-09-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, configure, configure.ac, plugins/sudoers/defaults.c,
+ plugins/sudoers/po/sudoers.pot:
+ Fix typo in warning for T_CHPATH, list '~' not '*' twice. Bug #938
+ [d516bebe9644]
+
+2020-09-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ Update .pot files for 1.9.3.
+ [47cedd231dd6]
+
+2020-09-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog_client.c:
+ Add missing check for strdup() failure. Coverity CID 214243
+ [86cf4da0cd81]
+
+ * examples/sudoers:
+ Sync example sudoers with manual page.
+ [1ccf32907f11]
+
+2020-09-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Add simple runchroot and runcwd examples. Also document the
+ limitation of command-based Defaults settings.
+ [6a610884670c]
+
+ * plugins/sudoers/sudoers.c:
+ Add callback for runchroot Defaults and require password -D/-R
+ checks. Using a command-based Default for runchroot will still only
+ work for paths that exist both in and outside the chroot.
+ [a50148e16b89]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/match.c,
+ plugins/sudoers/match_command.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h, plugins/sudoers/sudoers.c,
+ plugins/sudoers/testsudoers.c:
+ Pass a struct to the match functions to track the resolved command.
+ This makes it possible to update user_cmnd and cmnd_status modified
+ by per-rule CHROOT settings.
+ [c71faa1f5ea1]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/editor.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/goodpath.c,
+ plugins/sudoers/match.c, plugins/sudoers/match_command.c,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/stubs.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c:
+ Take the chroot into account when search for the command. This could
+ a a user-specific chroot via the -R option, a runchroot Defaults
+ value, or a per-command CHROOT spec in the sudoers rule.
+ [d8765611b48c]
+
+2020-09-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Remove closefrom_fallback() from lib/util/util.exp. It is a static
+ function and should not be exported.
+ [dc09dc563197]
+
+2020-09-06 Evan Anderson <evan@eaanderson.com>
+
+ * configure, m4/sudo.m4:
+ configure: Fix runstatedir handling for distros that do not support
+ it
+
+ runstatedir was added in yet-to-be released autoconf 2.70. Some
+ distros are shipping this addition in their autoconf packages, but
+ others, such as Fedora, are not. This causes the rundir variable to
+ be set incorrectly if the configure script is regenerated with an
+ unpatched autoconf since the runstatedir variable set is deleted
+ after regeneration. This change works around that problem by
+ checking that runstatedir is non-empty before potentially using it
+ to set the rundir variable
+ [35c1eb25dd9d]
+
+2020-09-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/Makefile.in:
+ We need to link with NET_LIBS for gai_strerror() on some systems.
+ From Tim Rice
+ [b10aeb7ec2ed]
+
+ * ltmain.sh:
+ Fix sco library versioning; fallout from frebsd-elf reorg. From Tim
+ Rice
+ [072a37c2d3cb]
+
+ * configure, configure.ac:
+ SVR4/5 fixes and long password support for OpenServer 6 & 5. From
+ Tim Rice
+ [8622970c77c3]
+
+ * lib/logsrv/protobuf-c.c:
+ Use config.h to handle systems without inline function support.
+ [1ba5301de713]
+
+ * configure, configure.ac:
+ Prefer dlopen() over shl_load() on HP-UX 11.11 and higher.
+ [065316970f79]
+
+ * include/sudo_fatal.h, lib/util/fatal.c:
+ Define sudo_warn_setlocale_t and use sudo_conv_t in sudo_fatal.h.
+ Works around a bug in older versions of the HP ANSI C compiler and
+ results in more readable code.
+ [0e53ec783100]
+
+ * configure, configure.ac:
+ HP-UX cc may not allow __declspec(dllexport) to be used in
+ conjunction with "#pragma HP_DEFINED_EXTERNAL" when redefining
+ standard libc functions.
+ [7190082c3a09]
+
+2020-09-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Fix check for hiding unexported symbols on HP-UX. We need to pass
+ the -b option to the compiler, not just the linker, so it will
+ choose the PIC C runtime.
+ [bc1b9351cbce]
+
+ * src/regress/ttyname/check_ttyname.c:
+ Check that the files are character devices before comparing st_rdev.
+ [d9f8b730d131]
+
+ * src/regress/ttyname/check_ttyname.c:
+ Fix regress when ttyname(3) returns the same device under a
+ different name. On systems that have both new and old pty names we
+ can end up with a name mismatch even though the underlying device is
+ the same.
+ [3760f44d81d4]
+
+ * plugins/sudoers/regress/testsudoers/test3.sh:
+ Use the same pattern of redefining TESTDIR as test10.sh. Adapted
+ from a diff from Tim Rice.
+ [378590625bfd]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c:
+ Rename sa_len -> sa_size to avoid a conflict on UnixWare and others.
+ On some systems, sa_len is a #define for 4.4BSD compatibility.
+ [a369d15175dd]
+
+ * plugins/sudoers/pwutil.c:
+ Include strings.h for strcasecmp(3). From Tim Rice
+ [27be3ee47426]
+
+ * lib/util/getentropy.c:
+ Add missing #ifdef HAVE_CLOCK_GETTIME in getentropy_fallback() From
+ Tim Rice
+ [4bdcf1048196]
+
+ * plugins/sudoers/Makefile.in:
+ Regen for check_exptilde.o
+ [b3e2a87b5144]
+
+ * lib/util/Makefile.in, scripts/mkdep.pl:
+ Add missing dependency info for cfmakeraw.lo in lib/util/Makefile.in
+ From Tim Rice
+ [18d953844745]
+
+ * plugins/sudoers/auth/pam.c:
+ Be consistent and use __hpux not __hpux__ like the rest of sudo.
+ [dd5ef59dc980]
+
+ * lib/logsrv/protobuf-c.c:
+ Replace "static inline" with "static __inline" for older compilers.
+ [a09412277d0f]
+
+ * MANIFEST, include/log_server.pb-c.h, lib/logsrv/Makefile.in,
+ lib/logsrv/log_server.pb-c.c, logsrvd/eventlog.c,
+ logsrvd/iolog_writer.c, logsrvd/logsrvd.c, logsrvd/sendlog.c,
+ plugins/sudoers/iolog_client.c, scripts/unanon:
+ Post-process protoc-c files to avoid depending on anonymous unions.
+ Based on a patch from Michael Osipov. GitHub issue #60
+ [13ab1ec22477]
+
+ * src/preload.c:
+ Add sudoers_audit to sudo_sudoers_plugin_symbols[] array. Fixes
+ loading of sudoers_audit when configured with --enable-static-
+ sudoers. GitHub issue #61
+ [f0bd4b5cd7b3]
+
+2020-09-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Fix copy and paste error; Coverity CID 214191
+ [49044d66dffc]
+
+ * plugins/sudoers/visudo.c:
+ Fix memory leak on error found by the clang 10.01 analyzer.
+ [12de4dd014eb]
+
+ * src/limits.c:
+ Use correct size for curlim and maxlim.
+ [1fc6aea5ece0]
+
+ * configure, configure.ac, doc/Makefile.in:
+ Only install man pages for logsrvd and python plugin if we build
+ them. GitHub issue #58
+ [e92799dd4886]
+
+ * Makefile.in, configure, configure.ac, doc/Makefile.in:
+ Remove obsolete mansrcdir variable, add _SRC suffix to LOGSRV and
+ LOGSRVD
+ [aa9c0f8cb227]
+
+2020-09-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/eventlog.c, plugins/sudoers/logging.c:
+ If the command was run in a chroot, add it to the log.
+ [0cda78f7ed40]
+
+ * MANIFEST, plugins/sudoers/regress/testsudoers/test12.out.ok,
+ plugins/sudoers/regress/testsudoers/test12.sh:
+ Add test of multiple syntax errors. Where possible, the portion of
+ the line before the error should be still be interpreted.
+ [3af61a54586f]
+
+ * logsrvd/eventlog.c, logsrvd/iolog_writer.c,
+ plugins/sudoers/logging.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Log the runcwd not submitcwd in the sudo-style log file. The log
+ entry should reflect the working directory the command actually ran
+ in.
+ [a477dee74683]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Fix error recovery in a privilege after a ':' separator.
+ [02c4b5872a38]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Initialize runchroot and runcwd in init_options()
+ [13bebf71955d]
+
+ * MANIFEST:
+ Fix path to check_exptilde.c
+ [7dc831cbd59d]
+
+ * include/log_server.pb-c.h, include/protobuf-c/protobuf-c.h,
+ lib/logsrv/protobuf-c.c:
+ Update to protobuf-c 1.3.3
+ [22a88bccb611]
+
+2020-09-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.h:
+ Regenerate the parser with "bison -y" for verbose syntax error
+ messages.
+ [e1530c5b8960]
+
+ * NEWS:
+ Add chroot/chdir changes.
+ [9367855da7d1]
+
+ * doc/sudo.man.in, doc/sudo.mdoc.in, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/policy.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, src/parse_args.c, src/sudo_usage.h.in:
+ Support "*" for CWD/CHROOT to allow user to specify cwd or chroot.
+ Adds two new command line options, -D (--chdir) and -R (--chroot)
+ that can only be used when sudoers sets runcwd or runchroot to "*".
+ [afeb73867b66]
+
+ * MANIFEST, lib/util/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/sudoers/exptilde.c,
+ plugins/sudoers/regress/exptilde/check_exptilde.c:
+ Unit test for exptilde
+ [f0d7b0031fea]
+
+ * MANIFEST, plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/ldap_util.c, plugins/sudoers/parse.c,
+ plugins/sudoers/regress/sudoers/test24.in,
+ plugins/sudoers/regress/sudoers/test24.json.ok,
+ plugins/sudoers/regress/sudoers/test24.ldif.ok,
+ plugins/sudoers/regress/sudoers/test24.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test24.out.ok,
+ plugins/sudoers/regress/sudoers/test24.sudo.ok,
+ plugins/sudoers/regress/sudoers/test24.toke.ok:
+ Add support for runchroot and runcwd to "sudo -l" and cvtsudoers.
+ [9f5ecd22d822]
+
+ * include/sudo_iolog.h, lib/iolog/iolog_fileio.c,
+ lib/iolog/iolog_json.c, lib/iolog/iolog_util.c,
+ logsrvd/iolog_writer.c, logsrvd/logsrvd.h, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_client.c, plugins/sudoers/iolog_plugin.h:
+ Read/write runchroot and runcwd entries in the JSON event log.
+ [3edb8305abe9]
+
+ * MANIFEST, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/exptilde.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.h, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/policy.c,
+ plugins/sudoers/regress/sudoers/test1.toke.ok,
+ plugins/sudoers/regress/sudoers/test11.toke.ok,
+ plugins/sudoers/regress/sudoers/test12.toke.ok,
+ plugins/sudoers/regress/sudoers/test13.toke.ok,
+ plugins/sudoers/regress/sudoers/test14.toke.ok,
+ plugins/sudoers/regress/sudoers/test15.toke.ok,
+ plugins/sudoers/regress/sudoers/test16.toke.ok,
+ plugins/sudoers/regress/sudoers/test17.toke.ok,
+ plugins/sudoers/regress/sudoers/test18.toke.ok,
+ plugins/sudoers/regress/sudoers/test19.toke.ok,
+ plugins/sudoers/regress/sudoers/test22.toke.ok,
+ plugins/sudoers/regress/sudoers/test3.toke.ok,
+ plugins/sudoers/regress/sudoers/test4.toke.ok,
+ plugins/sudoers/regress/sudoers/test6.toke.ok,
+ plugins/sudoers/regress/sudoers/test8.toke.ok,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoers_version.h,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Add CHROOT and CWD sudoers options. Also matching runchroot and
+ runcwd Defaults settings.
+ [2f0aca92c360]
+
+2020-08-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ include/sudo_plugin.h, plugins/python/regress/testdata/check_multipl
+ e_approval_plugin_and_arguments.stdout, src/exec.c, src/limits.c,
+ src/sudo.c, src/sudo.h:
+ Pass resource limits values to the plugin in user_info[] Sudo resets
+ the resource limits early in its execution so the plugin cannot tell
+ what the original limits were itself.
+ [64957c5875f3]
+
+ * doc/Makefile.in, doc/sudo_logsrvd.man.in,
+ doc/sudo_plugin_python.man.in, doc/sudo_plugin_python.mdoc.in,
+ lib/logsrv/Makefile.in, lib/util/cfmakeraw.c, lib/util/fchmodat.c,
+ lib/util/fstatat.c, lib/util/getdelim.c, lib/util/getusershell.c,
+ lib/util/openat.c, lib/util/regress/getdelim/getdelim_test.c,
+ lib/util/regress/strsig/strsig_test.c,
+ lib/util/regress/strtofoo/strtobool_test.c,
+ lib/util/regress/strtofoo/strtoid_test.c,
+ lib/util/regress/strtofoo/strtomode_test.c,
+ lib/util/regress/strtofoo/strtonum_test.c,
+ lib/util/regress/vsyslog/vsyslog_test.c, lib/util/roundup.c,
+ lib/util/strtoid.c, lib/util/strtonum.c, lib/util/term.c,
+ lib/util/unlinkat.c, logsrvd/Makefile.in, logsrvd/eventlog.c,
+ logsrvd/iolog_writer.c, logsrvd/logsrv_util.c,
+ plugins/python/Makefile.in, plugins/python/pyhelpers.c,
+ plugins/python/pyhelpers.h, plugins/python/python_baseplugin.c,
+ plugins/python/python_convmessage.c,
+ plugins/python/python_importblocker.c,
+ plugins/python/python_loghandler.c,
+ plugins/python/python_plugin_approval.c,
+ plugins/python/python_plugin_audit.c,
+ plugins/python/python_plugin_common.c,
+ plugins/python/python_plugin_common.h,
+ plugins/python/python_plugin_group.c,
+ plugins/python/python_plugin_io.c,
+ plugins/python/python_plugin_policy.c,
+ plugins/python/sudo_python_debug.c,
+ plugins/python/sudo_python_module.c,
+ plugins/python/sudo_python_module.h, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/ldap_conf.c,
+ plugins/sudoers/parse.c, plugins/sudoers/parse_ldif.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/starttime.c,
+ plugins/sudoers/tsdump.c, src/exec_monitor.c, src/exec_nopty.c,
+ src/limits.c, src/ttyname.c:
+ Update copyright year on some files where it was out of date.
+ [2086262cd012]
+
+2020-08-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in, doc/visudo.man.in,
+ doc/visudo.mdoc.in:
+ Refer to "syntax error" instead of "parse error". This is the term
+ the parser uses when there is an actual error.
+ [7134b6869432]
+
+ * plugins/sudoers/visudo.c:
+ Remove superfluous "parse error in sudoers near line N" message. The
+ sudoers parser now produces better syntax error messages so we don't
+ need visudo to print its own.
+ [9c32131fb6ac]
+
+ * plugins/sudoers/visudo.c:
+ Don't override errorfile and errorlineno set by check_aliases(). Now
+ that alias parsing stores the file and line number, visudo can use
+ that information to go to the line with an error when re-editing.
+ [896d1f73ca02]
+
+2020-08-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, lib/util/sig2str.c,
+ lib/util/str2sig.c:
+ Use sigabbrev_np(3) to access signal abbreviations if supported.
+ glibc-2.32 has removed sys_sigabbrev[], we can use sigabbrev_np(3)
+ instead.
+ [e30482f26924]
+
+2020-08-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Briefly describe how to restore historical parse error behavior.
+ [1ede927d99b3]
+
+ * NEWS, doc/UPGRADE:
+ Mention eof-of-line terminator and plugin argument changes.
+ [96cd7a3477fa]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in, src/load_plugins.c:
+ Fix sudoers_policy plugin options when sudoers_audit is not listed.
+ As of sudo 1.9.1 the sudoers file is opened by the audit plugin, not
+ the policy plugin. As a result, plugin options set for
+ sudoers_policy have no effect. If sudoers_policy has plugin options
+ in sudo.conf and sudoers_audit is not listed, move the options to
+ sudoers_audit so they will have an effect.
+ [839a9a9c0cc3]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/file.c,
+ plugins/sudoers/policy.c, plugins/sudoers/sudoers.h:
+ sudoers error recovery can be configured via an "error_recovery"
+ setting. This setting is an argument to the sudoers plugin, similar
+ to how sudoers_file, sudoers_mode, sudoers_uid, etc. are
+ implemented. The default value is true.
+ [86f7059f9e45]
+
+ * plugins/sudoers/regress/testsudoers/test11.sh:
+ Make this test pass with bison's verbose error messages.
+ [a2a8e4ca3f63]
+
+2020-08-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Recover from a syntax error after the ':' in a privilege spec. For
+ compound privilege specs, don't throw away the entire thing if we
+ have a syntax error, only the part after the error is encountered.
+ [d6ef4e6ca624]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/regress/sudoers/test5.toke.ok:
+ Add explicit end-of-line matching in the parser for better error
+ messages. A valid line in sudoers must end in a newline or EOF.
+ Previously, it was possible (though not documented) to have multiple
+ user specs on a single line. Now, each must be on its own line.
+ [9f513e9b10ee]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l:
+ Add NOMATCH token and use it in the lexer for an unmatched pattern.
+ The ERROR token is now only used for errors detected by the lexer
+ and for which we've already printed an error. This lets us remove
+ the hack in sudoerserror() and just check last_token to determine
+ whether or not to display the error.
+ [0ca11ad5b7f3]
+
+2020-08-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Enable error recovery for syntax erorrs that don't end with a
+ newline. A syntax error on the last line of a sudoers file with no
+ trailing newline is now recoverable.
+ [020f76d7f369]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/regress/testsudoers/test11.out.ok:
+ Add error recovery for unexpected tokens after include/includedir.
+ [1aedd819916d]
+
+ * NEWS:
+ Sudo 1.9.3 changes so far.
+ [bc6c6321a065]
+
+ * configure, configure.ac:
+ sudo 1.9.3
+ [432950d9f778]
+
+2020-08-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/pp:
+ Format the macOS minor version number with two digits. This way we
+ get consistent 4-digit version numbers even for macOS verions like
+ 10.3 or 11.0 where the minor number is a single digit. For example.
+ 10.3 will be formatted as 1003 and 11.0 will be 1100.
+ [7f48e10be9ae]
+
+2020-08-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/zlib/infback.c, lib/zlib/inflate.c:
+ Add missing ZFALLTHROUGH and use spaces not tabs.
+ [4b1c71cfb8a9]
+
+ * scripts/pp:
+ Fix probe for macOS Big Sur "sw_vers -productName" now returns
+ "macOS", not "Mac OS X"
+ [4caad8ca5b0c]
+
+2020-08-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/pyhelpers.c, plugins/python/python_plugin_common.h,
+ plugins/python/sudo_python_module.c, src/parse_args.c,
+ src/selinux.c:
+ Fix some warnings from pvs-studio
+ [fa83bb619209]
+
+ * Makefile.in, lib/iolog/iolog_fileio.c, lib/iolog/iolog_json.c,
+ lib/util/aix.c, lib/util/sudo_debug.c, logsrvd/logsrvd.c,
+ logsrvd/sendlog.c, plugins/audit_json/audit_json.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/securid5.c, plugins/sudoers/bsm_audit.c,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c, plugins/sudoers/env.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_client.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/ldap_conf.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/logging.c,
+ plugins/sudoers/parse.c, plugins/sudoers/policy.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ src/copy_file.c, src/exec.c, src/exec_common.c, src/exec_monitor.c,
+ src/exec_nopty.c, src/exec_pty.c, src/load_plugins.c,
+ src/parse_args.c, src/selinux.c, src/sesh.c, src/solaris.c,
+ src/sudo.c, src/sudo_edit.c, src/tgetpass.c, src/utmp.c:
+ Fix some warnings from pvs-studio
+ [164a51c446da]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/ldap_util.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/sssd.c:
+ Use angle quotes when including gram.h and def_data.c. Otherwise, we
+ can include the wrong file when doing an out-of-source build when
+ configured using --with-devel.
+ [105e52a86e22]
+
+ * lib/util/fatal.c, lib/util/regress/fnmatch/fnm_test.c,
+ logsrvd/logsrvd.c, logsrvd/logsrvd_conf.c, logsrvd/sendlog.c,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/iolog_client.c,
+ plugins/sudoers/logging.c, plugins/sudoers/match.c,
+ plugins/sudoers/match_command.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/visudo.c,
+ src/parse_args.c:
+ Move inclusion of compat headers up with the system headers. Now
+ that sudo_dso_public is defined in config.h we don't need
+ sudo_compat.h before including the compat headers.
+ [da2103ee7ba8]
+
+ * config.h.in, configure.ac, include/compat/fnmatch.h,
+ include/compat/getaddrinfo.h, include/compat/getopt.h,
+ include/compat/glob.h, include/compat/sha2.h, include/sudo_compat.h,
+ include/sudo_conf.h, include/sudo_debug.h, include/sudo_digest.h,
+ include/sudo_dso.h, include/sudo_event.h, include/sudo_fatal.h,
+ include/sudo_json.h, include/sudo_lbuf.h, include/sudo_rand.h,
+ include/sudo_util.h, lib/iolog/regress/host_port/host_port_test.c,
+ lib/iolog/regress/iolog_json/check_iolog_json.c,
+ lib/iolog/regress/iolog_mkpath/check_iolog_mkpath.c,
+ lib/iolog/regress/iolog_path/check_iolog_path.c,
+ lib/iolog/regress/iolog_util/check_iolog_util.c,
+ lib/util/mksiglist.c, lib/util/mksigname.c,
+ lib/util/regress/fnmatch/fnm_test.c,
+ lib/util/regress/getdelim/getdelim_test.c,
+ lib/util/regress/getgrouplist/getgrouplist_test.c,
+ lib/util/regress/glob/globtest.c,
+ lib/util/regress/mktemp/mktemp_test.c,
+ lib/util/regress/parse_gids/parse_gids_test.c,
+ lib/util/regress/progname/progname_test.c,
+ lib/util/regress/strsig/strsig_test.c,
+ lib/util/regress/strsplit/strsplit_test.c,
+ lib/util/regress/strtofoo/strtobool_test.c,
+ lib/util/regress/strtofoo/strtoid_test.c,
+ lib/util/regress/strtofoo/strtomode_test.c,
+ lib/util/regress/strtofoo/strtonum_test.c,
+ lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_parseln/parseln_test.c,
+ lib/util/regress/tailq/hltq_test.c,
+ lib/util/regress/vsyslog/vsyslog_test.c, lib/util/term.c,
+ logsrvd/logsrvd.c, logsrvd/sendlog.c,
+ plugins/audit_json/audit_json.c, plugins/group_file/group_file.c,
+ plugins/group_file/plugin_test.c,
+ plugins/python/python_plugin_approval.c,
+ plugins/python/python_plugin_audit.c,
+ plugins/python/python_plugin_group.c,
+ plugins/python/python_plugin_io.c,
+ plugins/python/python_plugin_policy.c,
+ plugins/sample/sample_plugin.c,
+ plugins/sample_approval/sample_approval.c, plugins/sudoers/audit.c,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/policy.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/env_match/check_env_pattern.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/regress/parser/check_gentime.c,
+ plugins/sudoers/regress/parser/check_hexchar.c,
+ plugins/sudoers/regress/starttime/check_starttime.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/tsdump.c,
+ plugins/sudoers/visudo.c, plugins/system_group/system_group.c,
+ src/env_hooks.c, src/regress/noexec/check_noexec.c,
+ src/regress/ttyname/check_ttyname.c, src/sesh.c, src/sudo.c,
+ src/sudo_noexec.c:
+ Rename __dso_public -> sudo_dso_public and move to config.h.
+ [12550ec04e3a]
+
+ * lib/iolog/host_port.c, lib/iolog/iolog_fileio.c,
+ lib/iolog/iolog_json.c, lib/iolog/iolog_path.c,
+ lib/iolog/iolog_util.c, lib/util/ttyname_dev.c, logsrvd/eventlog.c,
+ logsrvd/iolog_writer.c, logsrvd/logsrv_util.c, logsrvd/logsrvd.c,
+ logsrvd/logsrvd_conf.c, logsrvd/sendlog.c,
+ plugins/audit_json/audit_json.c, plugins/sample/sample_plugin.c,
+ plugins/sample_approval/sample_approval.c, plugins/sudoers/locale.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoreplay.c,
+ src/net_ifs.c, src/sesh.c, src/sudo.h:
+ We no longer need to include sudo_gettext.h before sudo_compat.h
+ [660770ab7e7b]
+
+ * .gitignore, .hgignore:
+ Add *.map to the ignore file.
+ [e96b46d418db]
+
+2020-08-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * etc/uncrustify.cfg:
+ Update to uncrustify 0.71.0
+ [dabd7b24c0d9]
+
+ * doc/sudo.man.in, doc/sudo.mdoc.in, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in:
+ Mention visudo in sudo(8) and document sudoers error recovery.
+ [44acd34811fb]
+
+2020-08-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, lib/util/Makefile.in, lib/util/freezero.c,
+ lib/util/getentropy.c, plugins/sudoers/auth/aix_auth.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/passwd.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ scripts/mkdep.pl, src/conversation.c:
+ Use OpenBSD-compatible freezero() in place of explicit_bzero() +
+ free()
+ [af0a9ed1e259]
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ include/sudo_compat.h, include/sudo_plugin.h, lib/util/Makefile.in,
+ lib/util/arc4random.c, lib/util/explicit_bzero.c,
+ lib/util/getentropy.c, lib/util/memset_s.c, lib/util/sha2.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/secureware.c,
+ plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, scripts/mkdep.pl,
+ src/conversation.c:
+ Switch from memset_s() -> explicit_bzero(). memset_s() (and all of
+ Annex K) is likely to be removed from the a future version of the
+ standard.
+ [c0f81ef1ee3c]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l:
+ Define YYERROR_VERBOSE for bison and rename COMMENT -> '\n' This
+ results in better error messages when there is a parse error
+ [7ba896f285a9]
+
+ * plugins/sudoers/mkdefaults:
+ Some minor cleanup. Use ntuples instead of tuple_last Strip leading
+ and trailing double quotes using a single gsub() ntuples will never
+ be zero so don't bother checking No need to explicitly close files
+ in END
+ [b841147900df]
+
+2020-08-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/event.c, plugins/sudoers/cvtsudoers_pwutil.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/linux_audit.c,
+ plugins/sudoers/logging.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/pwutil_impl.c, src/selinux.c:
+ Quiet some clang 10 analyzer warnings.
+ [4147311f6278]
+
+ * logsrvd/sendlog.c:
+ Refactor freeing of InfoMessage list into free_info_messages(). Also
+ fixes a false positive from the clang analyzer.
+ [25a6f0035a33]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y,
+ plugins/sudoers/regress/testsudoers/test11.out.ok,
+ plugins/sudoers/regress/testsudoers/test11.sh:
+ Require that a @include line end with a newline or EOF. We now parse
+ the entire line before reading the include file. This is less
+ surprising behavior and results in better error messages.
+ [ad6a2c991db6]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/parse.c,
+ plugins/sudoers/regress/sudoers/test1.out.ok,
+ plugins/sudoers/regress/sudoers/test10.out.ok,
+ plugins/sudoers/regress/sudoers/test11.out.ok,
+ plugins/sudoers/regress/sudoers/test12.out.ok,
+ plugins/sudoers/regress/sudoers/test13.out.ok,
+ plugins/sudoers/regress/sudoers/test14.out.ok,
+ plugins/sudoers/regress/sudoers/test15.out.ok,
+ plugins/sudoers/regress/sudoers/test16.out.ok,
+ plugins/sudoers/regress/sudoers/test17.out.ok,
+ plugins/sudoers/regress/sudoers/test18.out.ok,
+ plugins/sudoers/regress/sudoers/test18.toke.ok,
+ plugins/sudoers/regress/sudoers/test19.out.ok,
+ plugins/sudoers/regress/sudoers/test2.out.ok,
+ plugins/sudoers/regress/sudoers/test20.out.ok,
+ plugins/sudoers/regress/sudoers/test21.out.ok,
+ plugins/sudoers/regress/sudoers/test22.out.ok,
+ plugins/sudoers/regress/sudoers/test23.out.ok,
+ plugins/sudoers/regress/sudoers/test3.out.ok,
+ plugins/sudoers/regress/sudoers/test4.out.ok,
+ plugins/sudoers/regress/sudoers/test4.toke.ok,
+ plugins/sudoers/regress/sudoers/test5.out.ok,
+ plugins/sudoers/regress/sudoers/test5.toke.ok,
+ plugins/sudoers/regress/sudoers/test6.out.ok,
+ plugins/sudoers/regress/sudoers/test7.out.ok,
+ plugins/sudoers/regress/sudoers/test7.toke.ok,
+ plugins/sudoers/regress/sudoers/test8.out.ok,
+ plugins/sudoers/regress/sudoers/test8.toke.ok,
+ plugins/sudoers/regress/sudoers/test9.out.ok,
+ plugins/sudoers/regress/testsudoers/test1.out.ok,
+ plugins/sudoers/regress/testsudoers/test10.out.ok,
+ plugins/sudoers/regress/testsudoers/test11.out.ok,
+ plugins/sudoers/regress/testsudoers/test2.out.ok,
+ plugins/sudoers/regress/testsudoers/test3.out.ok,
+ plugins/sudoers/regress/testsudoers/test4.out.ok,
+ plugins/sudoers/regress/testsudoers/test5.out.ok,
+ plugins/sudoers/regress/testsudoers/test6.out.ok,
+ plugins/sudoers/regress/testsudoers/test7.out.ok,
+ plugins/sudoers/regress/testsudoers/test8.out.ok,
+ plugins/sudoers/regress/testsudoers/test9.out.ok,
+ plugins/sudoers/regress/visudo/test2.err.ok,
+ plugins/sudoers/regress/visudo/test3.err.ok,
+ plugins/sudoers/regress/visudo/test8.err.ok,
+ plugins/sudoers/regress/visudo/test8.sh,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/visudo.c:
+ Display more specific parser error messages when possible.
+ [91dd5d67bb83]
+
+ * plugins/sudoers/file.c:
+ Let the sudoers parser recover after a parse error. We currently
+ just discard the line with the error.
+ [712537665215]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/regress/testsudoers/test11.out.ok,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.h,
+ plugins/sudoers/toke.l:
+ Keep track of the position of the current token for error messages.
+ [a5f6bd38267e]
+
+2020-08-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/Makefile.in:
+ regen
+ [28026a042255]
+
+ * plugins/sample_approval/sample_approval.exp:
+ Sync sample_approval.exp with sample_approval.c
+ [e810da8a6772]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/regress/testsudoers/test11.out.ok,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.h,
+ plugins/sudoers/toke.l:
+ Store the current line in our own buffer for better error messages.
+ [33b2042e0028]
+
+2020-08-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * etc/sudo-logsrvd.pp, etc/sudo.pp, scripts/mkpkg:
+ Fix libssl dependency on Debian-based systems. Older systems may
+ still have libssl1.0.0, not libssl1.1.
+ [0de802ec595a]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Add workaround for yyless() not resetting yy_at_bol.
+ [5defcd893f6a]
+
+2020-08-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Always use a linker script to hide symbols if it is supported. We
+ use this even if the compiler has symbol visibility support so we
+ will notice mismatches between the exports file and __dso_public
+ annotations in the source code.
+ [1679ac3124b1]
+
+ * MANIFEST, configure, configure.ac, plugins/python/python_plugin.exp,
+ plugins/python/python_plugin.exp.in:
+ Rename python_plugin.exp.in -> python_plugin.exp There is nothing
+ dynamic in this file.
+ [f34cc08c026c]
+
+ * MANIFEST, configure, configure.ac,
+ plugins/python/python_plugin.exp.in,
+ plugins/python/python_plugin_approval_multi.inc,
+ plugins/python/python_plugin_audit_multi.inc:
+ Add missing python_plugin.exp.in file and remove unneeded
+ __dso_public This fixes building the python plugin on systems where
+ the compiler doesn't support symbol hiding (but wherethe linker
+ does).
+ [e0305faf8282]
+
+2020-08-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/mkdefaults:
+ Use "foo in bar" syntax for testing existence of a key.
+ [0807ae0db0a7]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/toke.c:
+ Replace /*FALLTHROUGH*/ in generated code.
+ [a7590ec10b16]
+
+2020-08-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/zlib/infback.c, lib/zlib/inflate.c, lib/zlib/zconf.h.in:
+ Add ZFALLTHROUGH macro to use instead of /* FALLTHROUGH */ comments.
+ [92ec8a466095]
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h,
+ lib/util/arc4random_buf.c, lib/util/glob.c, lib/util/snprintf.c,
+ lib/util/strtonum.c, logsrvd/sendlog.c, plugins/python/pyhelpers.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/check.c,
+ plugins/sudoers/cvtsudoers_ldif.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/fmtsudoers.c, plugins/sudoers/ldap_util.c,
+ plugins/sudoers/match.c, plugins/sudoers/parse_ldif.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudo_printf.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/visudo.c, src/conversation.c, src/exec_monitor.c,
+ src/exec_pty.c, src/parse_args.c, src/regress/noexec/check_noexec.c,
+ src/tgetpass.c:
+ Use the fallthrough attribute instead of /* FALLTHROUGH */ comments.
+ [ce33e87ddfd6]
+
+2020-07-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/mkdefaults:
+ Rewrite mkdefaults in awk.
+ [f069ca4eae59]
+
+2020-07-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/CONTRIBUTORS:
+ Update translators.
+ [5252e2d1a61a]
+
+ * doc/sudo.man.in, doc/sudo.mdoc.in, src/copy_file.c:
+ Prompt user before truncating a file to zero bytes. Bug #922.
+ [8bfaa57d5bd4]
+
+2020-07-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_2 for changeset a411d532a5f4
+ [84e81d1fe48f] <1.9>
+
+ * merge sudo 1.9.2 from tip
+ [a411d532a5f4] [SUDO_1_9_2] <1.9>
+
+2020-07-21 kuberlog <collinalexbell@gmail.com>
+
+ * config.h.in, configure.ac:
+ configure.ac: fix documentation about lecture
+ [382c2809eda1]
+
+2020-07-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt.mo, plugins/sudoers/po/pt.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/ro.mo, plugins/sudoers/po/ro.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ plugins/sudoers/po/zh_TW.mo, plugins/sudoers/po/zh_TW.po, po/cs.mo,
+ po/cs.po, po/de.mo, po/de.po, po/eo.mo, po/eo.po, po/ja.mo,
+ po/ja.po, po/ko.mo, po/ko.po, po/pl.mo, po/pl.po, po/pt.mo,
+ po/pt.po, po/pt_BR.mo, po/pt_BR.po, po/ro.mo, po/ro.po, po/tr.mo,
+ po/tr.po, po/uk.mo, po/uk.po, po/zh_CN.mo, po/zh_CN.po, po/zh_TW.mo,
+ po/zh_TW.po:
+ Updated translations from translationproject.org
+ [74fbf2ca39e1]
+
+2020-07-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Handle openssl where there is no separate libcrypto pkgconfig file.
+ In this case, just use the full openssl libs to get the sha2
+ functions.
+ [f724510bb416]
+
+ * INSTALL, configure, configure.ac:
+ Ignore --enable-gcrypt if --enable-openssl is also specified.
+ [39d493d7e549]
+
+2020-07-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.2
+ [9af764b239c2]
+
+ * config.h.in, configure, configure.ac:
+ Fix some warnings displayed by autoconf 2.69b This fixes the missing
+ HAVE_GSSAPI_GSSAPI_H define in config.h.in. TODO: replace
+ shadow_funcs variable in function checks with literals
+ [9d8f67e1f8fe]
+
+2020-07-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/audit.c:
+ Initialize sudo_conv and sudo_printf in sudoers_audit_open(). We
+ will need them if there is an error parsing sudoers and leaving them
+ unset can result in NULL deref. Also set the text domain to
+ "sudoers" like we do for the policy and I/O logging open functions.
+ Bug #934.
+ [e88919ff4900]
+
+2020-07-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/ro.mo, plugins/sudoers/po/ro.po, po/it.mo,
+ po/it.po, po/ko.mo, po/ko.po, po/ro.mo, po/ro.po:
+ Updated translations from translationproject.org
+ [2488a1479208]
+
+2020-07-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.exp:
+ Export sudoers_audit symbol for compilers without symbol visibility.
+ [081f6729cb38]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document the contents of the log.json file.
+ [b1ea749fffc2]
+
+ * lib/iolog/iolog_fileio.c:
+ Fix typo, runas_uid should be runas_gid.
+ [7b2c0fd84a60]
+
+ * examples/sudo.conf.in:
+ Add sudoers_audit line for completeness, matching the documentation.
+ When sudoers is loaded as a policy plugin, it will be loaded
+ automatically as an audit plugin. Listing it explicitly in the
+ default sudo.conf file helps bring attention to the fact that
+ sudoers now supports the audit plugin type.
+ [7145a02ed280]
+
+ * plugins/sudoers/defaults.c:
+ Add some debugging statements around Defaults lookup.
+ [b95e2a9b6555]
+
+ * plugins/sudoers/sudoers.in:
+ Replace #includedir with @includedir in default sudoers file.
+ [d18945ec728e]
+
+2020-06-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, m4/libtool.m4:
+ Allow HP-UX share libs and modules to link against static libs.
+ hppa64 and ia64 use PIC by default
+ [0553c60b922a]
+
+2020-06-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Use pkg-config to find the openssl cflags and libs if possible. We
+ support linking against static openssl libs too.
+ [55442f4fea5e]
+
+2020-06-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/pp:
+ Fix parsing of /etc/redhat-release on RHEL 8. RedHat dropped the
+ word "server" from the release name in redhat-release which results
+ in the awk script printing the wrong field. Instead of using awk,
+ just use sed to pull out the version number immediately following
+ the word "release".
+ [a283acb4622a]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen without `scare quotes'
+ [31f021892137]
+
+ * plugins/sudoers/def_data.c, plugins/sudoers/def_data.in,
+ src/parse_args.c, src/sudo.c:
+ Replace or remove use of `scare quotes' These don't translate well
+ and look odd in many fonts.
+ [3c7fa8f93543]
+
+2020-06-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/zlib/infback.c, lib/zlib/inflate.c:
+ Add FALLTHROUGH comments to quiet -Wimplicit-fallthrough
+ [f724957b7cae]
+
+ * src/solaris.c:
+ Fix implicit fallthrough warning and add break to default cases.
+ [74d8c68eb160]
+
+ * configure, configure.ac, m4/ax_func_snprintf.m4, m4/sudo.m4:
+ Fix some warnings from configure test programs.
+ [6cff0cdb066a]
+
+ * configure, configure.ac:
+ Add -Wimplicit-fallthrough to --enable-warnings if available. Note
+ that clang 10 has support for -Wimplicit-fallthrough in C code but
+ doesn't recognize lint-style FALLTHROUGH comments like gcc does so
+ we can't use it.
+ [cf70a1ab3ea9]
+
+ * configure, configure.ac:
+ Drop old test for -lcposix for ISC Unix.
+ [1bfd474c8819]
+
+2020-06-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * README:
+ Mention sudo-blog announce list.
+ [526dc0cc1e83]
+
+ * NEWS:
+ Bugs #860 and #917 were fixed in 1.9.0.
+ [51a347785dbf]
+
+2020-06-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_1 for changeset 06b47089122a
+ [94c1c10ddbbd] <1.9>
+
+ * merge sudo 1.9.1 from tip
+ [06b47089122a] [SUDO_1_9_1] <1.9>
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen to fix a typo
+ [9755e76fcd8b]
+
+ * MANIFEST, lib/iolog/Makefile.in,
+ lib/iolog/regress/iolog_mkpath/check_iolog_mkpath.c:
+ Add regress test to catch swapids() bug when called by
+ iolog_mkdtemp()
+ [deff1dc2f144]
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po, po/ro.mo,
+ po/ro.po:
+ Updated translations from translationproject.org
+ [9007c89029ea]
+
+2020-06-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in:
+ Document the order in which the plugin open/close functions are
+ called.
+ [48ec66882e1a]
+
+ * NEWS, lib/iolog/iolog_fileio.c:
+ Fix a typo that prevented swapids() from restoring the original gid.
+ This led to a regression when the iolog_file setting ends in six or
+ more X's or when the I/O logs are stored on NFS.
+ [522d8ec470cb]
+
+2020-06-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_monitor.c, src/exec_pty.c, src/get_pty.c, src/sudo.h,
+ src/sudo_exec.h:
+ Replace master/slave in code with leader/follower.
+ [230f5343d961]
+
+ * NEWS, doc/sudoers.man.in, doc/sudoers.mdoc.in, examples/sudoers,
+ plugins/sudoers/regress/cvtsudoers/sudoers,
+ plugins/sudoers/regress/cvtsudoers/sudoers.defs,
+ plugins/sudoers/regress/cvtsudoers/test13.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test19.out.ok,
+ plugins/sudoers/regress/visudo/test6.sh:
+ Replace terms master and blacklist in docs and examples.
+ [2908ac6c0fe0]
+
+ * NEWS:
+ Bug #929
+ [c1f5a01d1af6]
+
+2020-06-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sudo_edit.c:
+ Clean up temporary sudoedit files on success; Bug #929 This is a
+ regression introduced in sudo 1.9.0.
+ [2bc4822b7382]
+
+2020-06-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ New Romanian translation
+ [fd753dfa0a84]
+
+2020-06-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt.mo, plugins/sudoers/po/pt.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ plugins/sudoers/po/zh_TW.mo, plugins/sudoers/po/zh_TW.po, po/cs.mo,
+ po/cs.po, po/de.mo, po/de.po, po/eo.mo, po/eo.po, po/fi.mo,
+ po/fi.po, po/fr.mo, po/fr.po, po/hr.mo, po/hr.po, po/pl.mo,
+ po/pl.po, po/pt.mo, po/pt.po, po/pt_BR.mo, po/pt_BR.po, po/sv.mo,
+ po/sv.po, po/tr.mo, po/tr.po, po/uk.mo, po/uk.po, po/zh_CN.mo,
+ po/zh_CN.po, po/zh_TW.mo, po/zh_TW.po:
+ Updated translations from translationproject.org
+ [570aacc81015]
+
+ * MANIFEST, doc/CONTRIBUTORS, plugins/sudoers/po/ro.mo,
+ plugins/sudoers/po/ro.po, po/ro.mo, po/ro.po:
+ Romanian translation from translationproject.org.
+ [1e277907378e]
+
+ * NEWS:
+ Add missing entry for the LDAP/SSSD sudoHost regression. Also add
+ new Romanian translation
+ [624eb5e8e612]
+
+2020-06-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.c:
+ Fix a typo in the audit string when "sudo -E" is not allowed.
+ [85bcb3b1f7d8]
+
+2020-06-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/regress/testhelpers.c:
+ Check asprintf() return value.
+ [456bb2d7c37f]
+
+ * scripts/mkpkg:
+ Prefer the python3 in /usr/bin on Solaris. The /opt/csw version, if
+ it exists, may be a 32-bit version which we can't link with. Also
+ handle the case where the /usr/bin/python3 link is missing.
+ [2ed7715e6b2e]
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h:
+ Declare getdelim(3) if it exists in libc but is not prototyped in
+ stdio.h. This can happen on systems with a gcc packages that was
+ built on and older versions of the OS where getdelim(3) was not
+ present.
+ [e78803280641]
+
+ * aclocal.m4, configure, configure.ac:
+ For python3-config, only use -I and -L/-l from --cflags and
+ --ldflags output. Otherwise we may get other flags used to build
+ python that conflict with what sudo uses.
+ [7a8d3c5fd2ae]
+
+ * scripts/mkpkg:
+ Build 64-bit binaries and the python package on Solaris 11 and
+ above. No longer prefer the Solaris Studio C compiler over gcc, it
+ causes issues with the Python plugin.
+ [a92f9641bd07]
+
+ * logsrvd/sendlog.c:
+ Fix memory leak on error in fmt_info_messages().
+ [511ac9ba6819]
+
+ * NEWS:
+ Update for 1.9.1b1
+ [562b0add8e04]
+
+2020-06-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen for sudo 1.9.1
+ [8960aceb2519]
+
+2020-06-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/audit.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h:
+ Add basic support for reject and error audit events to sudoers. This
+ is only used when logging events from plugins other than sudoers,
+ such as an approval plugin. With this change, if an approval plugin
+ rejects the command the denial will be logged in the sudoers log
+ file using the message from the approval plugin.
+ [c7abc39b0e37]
+
+ * plugins/sudoers/bsm_audit.c, plugins/sudoers/solaris_audit.c,
+ scripts/mkpkg:
+ Fix Solaris and BSM audit warnings. Use BSM audit on Illumos, which
+ lacks Solaris audit.
+ [3844e8a24f59]
+
+ * plugins/sudoers/policy.c:
+ Track whether the session was opened in sudoers. In
+ sudoers_policy_close() only warn about being unable to run the
+ command if we actually opened the session (and thus passed all
+ approval plugins).
+ [f99b434d121b]
+
+ * src/sudo.c:
+ Only display an error in the built-in policy close if command is
+ set. If a policy or approval plugin denies the command,
+ command_details will not have been filled out.
+ [245024004df2]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/parse.c,
+ plugins/sudoers/sssd.c:
+ Avoid passing NULL to printf in match debug code for LDAP/SSSD. The
+ file name in struct userspec was not set for the LDAP and SSSD
+ backends. There is no actual file in this case so set the name to
+ LDAP/SSSD. Also add a guard to make sure we don't try to print NULL
+ in sudoers_lookup_check() if name is left unset.
+ [240efcda496e]
+
+2020-06-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/linux_audit.c, plugins/sudoers/linux_audit.h:
+ Add missing const to linux_audit_command()'s argv function argument.
+ [cb219f1ccb6e]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ When converting LDAP to sudoers, ignore entries with no sudoHost
+ attribute. Otherwise, sudo_ldap_role_to_priv() will treat a NULL
+ host list as as the "ALL" wildcard. This regression was introduced
+ in sudo 1.8.23, which was the first version to convert LDAP sudoRole
+ objects to sudoers internal data structures. Thanks to Andreas
+ Mueller for reporting and debugging this problem.
+ [484d0d3b892e]
+
+2020-06-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in, src/load_plugins.c:
+ Load the sudoers module as an audit plugin if loaded as a policy
+ plugin. Now that logging of successful commands is performed by
+ sudoers as an audit plugin we need to load sudoers_audit if
+ sudoers_policy is also loaded. Otherwise, accpted commands will not
+ be logged.
+ [f20bee20f4c7]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/bsm_audit.c, plugins/sudoers/bsm_audit.h,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/policy.c, plugins/sudoers/solaris_audit.c,
+ plugins/sudoers/solaris_audit.h, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Defer logging of the successful command until approval plugins have
+ run. This adds audit plugin support to the sudoers module, currently
+ only used for accept events. As a result, the sudoers file is now
+ initially parsed as an audit plugin.
+ [552c13bd0287]
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ doc/sudo_plugin_python.man.in, doc/sudo_plugin_python.mdoc.in,
+ include/sudo_plugin.h, plugins/audit_json/audit_json.c,
+ plugins/python/sudo_python_module.c, src/sudo.c:
+ Add support for "accept" audit events sent by the sudo front-end.
+ With this change, the sudo front-end will send an "accept" audit
+ event to the audit plugins after all the I/O logging plugins have
+ been initialized. This can be used by an audit plugin that does not
+ care about the result of the individual policy and approval plugins
+ and only wants to receive a single "accept" event if all policy and
+ approval plugins have succeeded. The plugin_type argument for events
+ sent by the front-end is SUDO_FRONT_END (0).
+ [6b3cb94fedb9]
+
+ * src/exec_pty.c:
+ If event loop fails due to ENXIO, remove /dev/tty events and
+ recover. This fixes an issue on Solaris 11.4 (and probably others)
+ with "sudo reboot" when I/O logging is enabled. Previously, sudo
+ would kill the command if it was still running after the event loop
+ terminated, leaving the system in a half-dead state.
+ [e12e3040b067]
+
+2020-06-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_pty.c:
+ Don't try to suspend sudo if the user's tty has gone away. Fixes a
+ problem on Solaris 11.4 (and possibly others) where sudo continually
+ tries to put itself in the background after the user's terminal has
+ been revoked.
+ [92f172b46b9c]
+
+ * src/exec_pty.c:
+ Back out WIP code that was mistakenly committed.
+ [41f57239b2c4]
+
+ * scripts/mkpkg:
+ Don't enable BSM audit on Solaris 10, it is missing AUE_sudo
+ [3b32087b1ed3]
+
+ * src/exec_pty.c, src/get_pty.c:
+ On Solaris 11.4 the openpty(3) prototype lives in termios.h.
+ [d6e353e8b9df]
+
+ * plugins/sudoers/solaris_audit.c:
+ Add missing stdlib.h include and fix solaris_audit_failure() error
+ return.
+ [5748d8fd24c4]
+
+ * scripts/mkpkg:
+ Use Solaris audit for Solaris 11, not BSM audit. BSM audit is no
+ longer supported in Solaris 11.4.
+ [01f2189f439d]
+
+2020-05-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec.c:
+ Check audit plugins for a close function too before execing command
+ directly. We cannot exec the command directly if any of the policy
+ or audit plugins use a close function.
+ [5aa6db56ce32]
+
+2020-05-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Mention Bug #927.
+ [0fd9e757d80b]
+
+2020-05-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac, m4/sudo.m4:
+ Add basic support for --runstatedir If the user specifies
+ --runstatedir but not --with-rundir, use runstatdir as the parent
+ directory of the sudo rundir.
+
+ In the future we may deprecate --with-rundir in favor of
+ --runstatedir but that will require changes for systems with no
+ /var/run directory.
+ [14879831fe6e]
+
+ * MANIFEST, NEWS, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y,
+ plugins/sudoers/regress/testsudoers/test10.out.ok,
+ plugins/sudoers/regress/testsudoers/test10.sh,
+ plugins/sudoers/regress/testsudoers/test11.out.ok,
+ plugins/sudoers/regress/testsudoers/test11.sh,
+ plugins/sudoers/regress/testsudoers/test2.out.ok,
+ plugins/sudoers/regress/testsudoers/test2.sh,
+ plugins/sudoers/regress/testsudoers/test3.out.ok,
+ plugins/sudoers/regress/testsudoers/test3.sh,
+ plugins/sudoers/regress/testsudoers/test4.sh,
+ plugins/sudoers/regress/testsudoers/test5.sh,
+ plugins/sudoers/regress/testsudoers/test8.out.ok,
+ plugins/sudoers/regress/testsudoers/test8.sh,
+ plugins/sudoers/regress/testsudoers/test9.out.ok,
+ plugins/sudoers/regress/testsudoers/test9.sh,
+ plugins/sudoers/sudoers_version.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.h,
+ plugins/sudoers/toke.l:
+ Add support for @include and @includedir These are less confusing
+ than #include and #includedir when the hash character is also the
+ comment character.
+
+ This commit also adds real parsing of include directives as opposed
+ to the pure lexer approach used previously. As a result, it is now
+ possible to include files with spaces by either using a double-
+ quoted string or escaping the space characters with a backslash.
+ [c422a5c8ea5d]
+
+2020-05-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/iolog_fileio.c:
+ In iolog_openat() enable the write bit on pre-existing files if
+ needed. This prevents problems caused by the change to strip the
+ write bit from the timing file when it is finished.
+ [a6b0da3f7b94]
+
+ * plugins/sudoers/visudo.c:
+ In visudo check that an include file is regular file before using
+ it. Avoids a generic "input in flex scanner failed" error message.
+ [287d90d359a6]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Fix a memory leak on error when including a file or directory.
+ [02db03f7b565]
+
+2020-05-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.9.1
+ [57a1a5f05500]
+
+ * doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in,
+ plugins/sudoers/sudoreplay.c:
+ Add a follow option (-F) to support replaying a live session. By
+ default, sudoreplay will exit when it reaches the end of the timing
+ file. With the -F option, it will keep going until the timing file
+ is finished and its write bit is cleared.
+ [12ab27768cad]
+
+ * include/sudo_iolog.h, lib/iolog/iolog_fileio.c:
+ Add iolog_clearerr() that acts like clearerr(3). Works for both
+ compressed and uncompressed I/O logs.
+ [c83b88285c2c]
+
+ * plugins/sudoers/iolog.c:
+ Clear the write bit from the I/O log timing file when it is
+ complete. This matches the behavior of sudo_logsrvd.
+ [0bc8a012db26]
+
+ * logsrvd/logsrvd.c, logsrvd/sendlog.c:
+ Use PACKAGE_VERSION instead of 0.1 as the client and server version.
+ [d1e3ac049cf7]
+
+ * lib/util/Makefile.in, lib/util/aix.c, lib/util/fatal.c,
+ lib/util/getusershell.c, lib/util/gidlist.c, lib/util/json.c,
+ lib/util/mkdir_parents.c, lib/util/strsignal.c, lib/util/strtoid.c,
+ lib/util/strtomode.c, lib/util/strtonum.c, lib/util/sudo_conf.c,
+ lib/util/sudo_debug.c:
+ Set DEFAULT_TEXT_DOMAIN in lib/util's Makefile not individual .c
+ files. We no longer need to include sudo_gettext.h before
+ sudo_compat.h
+ [ead9b6a434b8]
+
+ * lib/iolog/iolog_fileio.c, lib/iolog/iolog_json.c,
+ lib/iolog/iolog_path.c, lib/iolog/iolog_util.c,
+ lib/iolog/regress/host_port/host_port_test.c,
+ lib/iolog/regress/iolog_json/check_iolog_json.c,
+ lib/iolog/regress/iolog_path/check_iolog_path.c,
+ lib/iolog/regress/iolog_util/check_iolog_util.c,
+ lib/util/digest_gcrypt.c, lib/util/event.c, lib/util/event_select.c,
+ lib/util/fnmatch.c, lib/util/getaddrinfo.c, lib/util/getcwd.c,
+ lib/util/getdelim.c, lib/util/getgrouplist.c,
+ lib/util/getopt_long.c, lib/util/glob.c, lib/util/inet_pton.c,
+ lib/util/json.c, lib/util/key_val.c, lib/util/lbuf.c,
+ lib/util/locking.c, lib/util/mkdir_parents.c, lib/util/mktemp.c,
+ lib/util/parseln.c, lib/util/progname.c, lib/util/pw_dup.c,
+ lib/util/regress/fnmatch/fnm_test.c,
+ lib/util/regress/getdelim/getdelim_test.c,
+ lib/util/regress/getgrouplist/getgrouplist_test.c,
+ lib/util/regress/glob/globtest.c,
+ lib/util/regress/mktemp/mktemp_test.c,
+ lib/util/regress/parse_gids/parse_gids_test.c,
+ lib/util/regress/progname/progname_test.c,
+ lib/util/regress/strsplit/strsplit_test.c,
+ lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_parseln/parseln_test.c,
+ lib/util/regress/tailq/hltq_test.c,
+ lib/util/regress/vsyslog/vsyslog_test.c, lib/util/secure_path.c,
+ lib/util/sha2.c, lib/util/sig2str.c, lib/util/snprintf.c,
+ lib/util/str2sig.c, lib/util/strndup.c, lib/util/strtobool.c,
+ lib/util/sudo_conf.c, lib/util/sudo_debug.c, lib/util/sudo_dso.c,
+ lib/util/term.c, lib/util/ttyname_dev.c, lib/util/vsyslog.c,
+ plugins/audit_json/audit_json.c, plugins/group_file/getgrent.c,
+ plugins/group_file/group_file.c, plugins/python/sudo_python_debug.c,
+ plugins/sample/sample_plugin.c,
+ plugins/sample_approval/sample_approval.c, plugins/sudoers/alias.c,
+ plugins/sudoers/auth/afs.c, plugins/sudoers/auth/aix_auth.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/dce.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/passwd.c,
+ plugins/sudoers/auth/rfc1938.c, plugins/sudoers/auth/secureware.c,
+ plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/boottime.c,
+ plugins/sudoers/check.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/editor.c, plugins/sudoers/env.c,
+ plugins/sudoers/env_pattern.c, plugins/sudoers/filedigest.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/gentime.c, plugins/sudoers/getdate.c,
+ plugins/sudoers/getdate.y, plugins/sudoers/getspwuid.c,
+ plugins/sudoers/goodpath.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/interfaces.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_path_escapes.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/ldap_conf.c, plugins/sudoers/ldap_util.c,
+ plugins/sudoers/locale.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logwrap.c, plugins/sudoers/match.c,
+ plugins/sudoers/match_addr.c, plugins/sudoers/match_command.c,
+ plugins/sudoers/match_digest.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse_ldif.c, plugins/sudoers/policy.c,
+ plugins/sudoers/prompt.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/pwutil_impl.c, plugins/sudoers/rcstr.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/env_match/check_env_pattern.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/regress/parser/check_gentime.c,
+ plugins/sudoers/regress/parser/check_hexchar.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/starttime.c, plugins/sudoers/strlist.c,
+ plugins/sudoers/stubs.c, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers_debug.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timeout.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/tsdump.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/visudo.c,
+ plugins/system_group/system_group.c, src/conversation.c,
+ src/env_hooks.c, src/exec.c, src/exec_common.c, src/exec_monitor.c,
+ src/exec_nopty.c, src/exec_pty.c, src/get_pty.c, src/hooks.c,
+ src/limits.c, src/load_plugins.c, src/net_ifs.c, src/parse_args.c,
+ src/preserve_fds.c, src/regress/noexec/check_noexec.c,
+ src/regress/ttyname/check_ttyname.c, src/signal.c, src/sudo.c,
+ src/sudo_edit.c, src/sudo_noexec.c, src/tcsetpgrp_nobg.c,
+ src/tgetpass.c, src/ttyname.c, src/utmp.c:
+ Include string.h unconditionally and only use strings.h for
+ strn?casecmp() In the pre-POSIX days BSD had strings.h, not
+ string.h. Now strings.h is only used for non-ANSI string functions.
+ [f7f633de570a]
+
+ * lib/iolog/host_port.c, lib/iolog/iolog_fileio.c,
+ lib/iolog/iolog_json.c, lib/iolog/iolog_path.c,
+ lib/iolog/iolog_util.c,
+ lib/iolog/regress/host_port/host_port_test.c,
+ lib/iolog/regress/iolog_json/check_iolog_json.c,
+ lib/iolog/regress/iolog_path/check_iolog_path.c,
+ lib/iolog/regress/iolog_util/check_iolog_util.c, lib/util/aix.c,
+ lib/util/arc4random.c, lib/util/arc4random_buf.c,
+ lib/util/arc4random_uniform.c, lib/util/cfmakeraw.c,
+ lib/util/closefrom.c, lib/util/digest.c, lib/util/digest_gcrypt.c,
+ lib/util/digest_openssl.c, lib/util/dup3.c, lib/util/event_poll.c,
+ lib/util/event_select.c, lib/util/fatal.c, lib/util/fchmodat.c,
+ lib/util/fnmatch.c, lib/util/fstatat.c, lib/util/getaddrinfo.c,
+ lib/util/getcwd.c, lib/util/getdelim.c, lib/util/getgrouplist.c,
+ lib/util/gethostname.c, lib/util/getopt_long.c, lib/util/gettime.c,
+ lib/util/getusershell.c, lib/util/gidlist.c, lib/util/glob.c,
+ lib/util/isblank.c, lib/util/json.c, lib/util/key_val.c,
+ lib/util/lbuf.c, lib/util/locking.c, lib/util/logfac.c,
+ lib/util/logpri.c, lib/util/memset_s.c, lib/util/mkdir_parents.c,
+ lib/util/mksiglist.c, lib/util/mksigname.c, lib/util/mktemp.c,
+ lib/util/openat.c, lib/util/parseln.c, lib/util/pipe2.c,
+ lib/util/progname.c, lib/util/pw_dup.c, lib/util/reallocarray.c,
+ lib/util/regress/fnmatch/fnm_test.c,
+ lib/util/regress/getgrouplist/getgrouplist_test.c,
+ lib/util/regress/glob/globtest.c,
+ lib/util/regress/mktemp/mktemp_test.c,
+ lib/util/regress/parse_gids/parse_gids_test.c,
+ lib/util/regress/progname/progname_test.c,
+ lib/util/regress/strsig/strsig_test.c,
+ lib/util/regress/strsplit/strsplit_test.c,
+ lib/util/regress/strtofoo/strtobool_test.c,
+ lib/util/regress/strtofoo/strtoid_test.c,
+ lib/util/regress/strtofoo/strtomode_test.c,
+ lib/util/regress/strtofoo/strtonum_test.c,
+ lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_parseln/parseln_test.c,
+ lib/util/regress/tailq/hltq_test.c,
+ lib/util/regress/vsyslog/vsyslog_test.c, lib/util/roundup.c,
+ lib/util/secure_path.c, lib/util/setgroups.c, lib/util/sha2.c,
+ lib/util/sig2str.c, lib/util/snprintf.c, lib/util/str2sig.c,
+ lib/util/strlcat.c, lib/util/strlcpy.c, lib/util/strndup.c,
+ lib/util/strsignal.c, lib/util/strsplit.c, lib/util/strtobool.c,
+ lib/util/strtoid.c, lib/util/strtomode.c, lib/util/strtonum.c,
+ lib/util/sudo_conf.c, lib/util/sudo_debug.c, lib/util/sudo_dso.c,
+ lib/util/term.c, lib/util/ttysize.c, lib/util/unlinkat.c,
+ lib/util/utimens.c, lib/util/uuid.c,
+ plugins/audit_json/audit_json.c, plugins/group_file/getgrent.c,
+ plugins/group_file/group_file.c, plugins/group_file/plugin_test.c,
+ plugins/python/regress/testhelpers.h,
+ plugins/python/sudo_python_debug.h, plugins/sample/sample_plugin.c,
+ plugins/sample_approval/sample_approval.c, plugins/sudoers/alias.c,
+ plugins/sudoers/audit.c, plugins/sudoers/base64.c,
+ plugins/sudoers/boottime.c, plugins/sudoers/bsm_audit.c,
+ plugins/sudoers/check.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/digestname.c, plugins/sudoers/editor.c,
+ plugins/sudoers/env.c, plugins/sudoers/env_pattern.c,
+ plugins/sudoers/file.c, plugins/sudoers/filedigest.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/gc.c, plugins/sudoers/gentime.c,
+ plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/getspwuid.c, plugins/sudoers/gmtoff.c,
+ plugins/sudoers/goodpath.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/hexchar.c, plugins/sudoers/interfaces.c,
+ plugins/sudoers/iolog_client.c,
+ plugins/sudoers/iolog_path_escapes.c, plugins/sudoers/ldap_conf.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/locale.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logwrap.c,
+ plugins/sudoers/match.c, plugins/sudoers/match_command.c,
+ plugins/sudoers/match_digest.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse_ldif.c, plugins/sudoers/prompt.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/rcstr.c, plugins/sudoers/redblack.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/env_match/check_env_pattern.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/regress/parser/check_gentime.c,
+ plugins/sudoers/regress/parser/check_hexchar.c,
+ plugins/sudoers/regress/starttime/check_starttime.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/solaris_audit.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/strlist.c,
+ plugins/sudoers/stubs.c, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudo_printf.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers_debug.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/timeout.c,
+ plugins/sudoers/timestamp.c, plugins/sudoers/timestr.c,
+ plugins/sudoers/toke_util.c, plugins/sudoers/tsdump.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/visudo.c,
+ plugins/system_group/system_group.c, src/conversation.c,
+ src/copy_file.c, src/env_hooks.c, src/exec.c, src/exec_common.c,
+ src/exec_nopty.c, src/get_pty.c, src/hooks.c, src/limits.c,
+ src/load_plugins.c, src/openbsd.c, src/parse_args.c, src/preload.c,
+ src/preserve_fds.c, src/selinux.c, src/sesh.c, src/signal.c,
+ src/solaris.c, src/sudo_edit.c, src/tcsetpgrp_nobg.c,
+ src/tgetpass.c, src/utmp.c:
+ We no longer need to include headers we don't use for sudo*.h files.
+ Previously we needed to include headers required by the various
+ sudo*h files. Now those files are more self-sufficient and we should
+ only include headers needed by code in the various .c files.
+ [72cbeae218e7]
+
+ * include/sudo_compat.h, include/sudo_conf.h, include/sudo_debug.h,
+ include/sudo_iolog.h, include/sudo_json.h, include/sudo_util.h,
+ plugins/sudoers/sudoers.h:
+ Add dependent system includes to make sudo_*.h more standalone. In
+ the past we've relied on the various .c files to include the system
+ headers that define types that the sudo_*.h headers require. This is
+ fragile and can cause issues when includes get re-ordered.
+ [a9fb765c0fba]
+
+ * plugins/sudoers/env.c:
+ Fix typo in PERLIO_DEBUG (trailing whitespace). This has no effect
+ unless env_reset is disabled. From Allan Wirth
+ [bdf9c9e7f455]
+
+2020-05-17 Sebastian Rasmussen <sebras@gmail.com>
+
+ * plugins/sudoers/visudo.c:
+ Fix typo in warning message.
+ [01b8fab9fdf5]
+
+2020-05-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/mksiglist.h, lib/util/mksigname.h:
+ Prefer SIGSYS if SIGUNUSED is defined to the same value. Fixes a
+ regress failure on musl libc where SIGSYS and SIGUNUSED share the
+ same value.
+ [e030acf8a670]
+
+ * plugins/python/regress/testhelpers.h:
+ Add missing sys/wait.h include; fixes a compilation problem on musl
+ libc.
+ [9a6a09e74a14]
+
+ * lib/iolog/hostcheck.c:
+ Add missing sys/types.h include; fixes a compilation problem on musl
+ libc.
+ [7c8ea831203b]
+
+ * include/sudo_compat.h:
+ Only define WCONTINUED and WIFCONTINUED if neither are already
+ defined. Fixes a warning on musl libc where WIFCONTINUED is defined
+ in stdlib.h for some reason.
+ [9f55ae24b479]
+
+2020-05-16 Dan Robertson <dan@dlrobertson.com>
+
+ * include/sudo_debug.h:
+ Fix includes when building with musl
+
+ Include sys/types.h for mode_t and id_t in sudo_debug.h
+ [15abb56a1edf]
+
+2020-05-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/mkpkg:
+ Enable OpenSSL on RHEL 6 too. The version of OpenSSL in RHEL 6 is
+ new enough for the log server to use.
+ [853fd8a74207]
+
+ * logsrvd/logsrvd_conf.c:
+ Don't print errno for the "TLS not supported" message.
+ [c94540d3d632]
+
+2020-05-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * etc/sudo-logsrvd.pp, etc/sudo-python.pp:
+ Fix macOS bundle IDs for sudo-logsrvd and sudo-python packages
+ [a9f6aea56e40]
+
+2020-05-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/eventlog.c:
+ Add iolog_path to the JSON-format event log
+ [924d8836ead0]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h:
+ Rename FLUSHED state to FINISHED This makes more sense when
+ receiving event-only logs.
+ [9e2736246e0d]
+
+2020-05-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h:
+ Fix handling of connections without associated I/O logs. This fixes
+ reject events as well as accept events without the expect_iobufs
+ flag set.
+ [3ddb52ae0af4]
+
+ * logsrvd/sendlog.c:
+ Fix handling of accept and reject messages without an I/O log. Only
+ set expect_iobufs in AcceptMessage if sending I/O logs. Set state to
+ FINISHED immediately after sending a RejectMessage.
+ [767e75944d4f]
+
+ * doc/sudo_sendlog.man.in, doc/sudo_sendlog.mdoc.in,
+ logsrvd/sendlog.c, logsrvd/sendlog.h:
+ Add -A and -R options to test logging of accept and reject events.
+ If -A is specified, no I/O will be sent, only the accept event. For
+ -R, a reject event with the specified reason is sent.
+ [90db0e6f9b68]
+
+ * configure, configure.ac:
+ cfmakeraw(3) is broken on AIX, don't use it there The cfmakeraw(3)
+ function exists but does not set VMIN to 1 or VTIME to 0 in c_cc[]
+ in struct termios, which makes it useless. The AIX version also
+ doesn't clear the CSIZE and PARENB flags from c_cflag.
+ [bbdcae2c5fb5]
+
+ * NEWS:
+ fix pastos
+ [cbf517081e74]
+
+2020-05-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgtags:
+ Added tag SUDO_1_9_0 for changeset 706d726a2f8e
+ [d1f2b4ee59d5] <1.9>
+
+ * MANIFEST, include/sudo_iolog.h, include/sudo_util.h,
+ lib/iolog/Makefile.in, lib/iolog/host_port.c,
+ lib/iolog/regress/host_port/host_port_test.c, lib/util/Makefile.in,
+ lib/util/host_port.c, lib/util/regress/host_port/host_port_test.c,
+ lib/util/util.exp.in, logsrvd/logsrvd_conf.c,
+ plugins/sudoers/iolog_client.c:
+ Rename sudo_parse_host_port -> iolog_parse_host_port and mv to
+ lib/iolog It is not used outside of the I/O log client and server
+ and the host:port syntax may change in the future.
+ [706d726a2f8e] [SUDO_1_9_0]
+
+ * plugins/sudoers/sudoreplay.c:
+ Remove duplicate inclusion of time.h
+ [f560858325d5]
+
+2020-05-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ logsrvd/logsrvd.c, logsrvd/logsrvd_conf.c,
+ plugins/sudoers/iolog_client.c:
+ Only enable TLS listener by default if we have a cert for it. We
+ want the log server to work with the default configuration. If the
+ default certificate path exists, it will be used with the default
+ listener. If the user explicitly enabled a TLS listener we always
+ attempt to use it. If TLS was specified but no cert file was set,
+ the default location will be used (and an error will occur if the
+ cert cannot be loaded).
+ [16ade34c38ee]
+
+2020-05-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen for 1.9.0 final
+ [99e507035253]
+
+ * logsrvd/Makefile.in:
+ regen
+ [555d817825b0]
+
+ * doc/sudo.man.in, doc/sudo.mdoc.in, src/parse_args.c:
+ The --preserve-env=list option may be specified more than once.
+ [8066a9d1b04b]
+
+ * doc/sudo_logsrv.proto.man.in, doc/sudo_logsrv.proto.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Quiet some warnings from igor.
+ [4df4fd274023]
+
+ * MANIFEST, Makefile.in, etc/codespell.exclude, etc/codespell.ignore,
+ etc/codespell.skip:
+ Plumb in codespell with a "make spell" target.
+ [4b1de7ee8648]
+
+ * configure, configure.ac, install-sh:
+ Fix a few more typos.
+ [d22a8c46c743]
+
+2020-05-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, doc/sudo.man.in, doc/sudo.mdoc.in, src/parse_args.c:
+ Don't allow duplicate values for command line options that take an
+ argument. Previously, if multiple instances of the same command line
+ option were specified, the last one would be used. This meant that,
+ for example, "sudo -u someuser -u otheruser id" would run the
+ command as "otheruser". This has the potential to cause problems for
+ programs that run sudo with a user-specified command that do not use
+ the "--" option to indicate that no more options should be
+ processed. While this is a bug in the calling program, there is
+ little downside to erroring out when multiple options of the same
+ type are specified on the command line. Bug #924
+ [66e2612e7672]
+
+ * NEWS:
+ Debian bug #734752
+ [d3285c45ac4b]
+
+ * src/sudo.c, src/sudo.h:
+ Look up runas user by name, not euid, where possible. Fixes a
+ problem when there are multiple users with the same user-ID where
+ the PAM session modules could be called with the wrong user name.
+ Debian bug #734752
+ [b45608f29a02]
+
+ * src/sesh.c:
+ Fix ironic typo in spelling fixes. Bug #925
+ [73de90df6ff9]
+
+ * scripts/pp:
+ Sync PolyPkg from upstream.
+ [ac5e4b830177]
+
+ * NEWS, TODO, config.h.in, configure.ac,
+ doc/sudo_plugin_python.man.in, doc/sudo_plugin_python.mdoc.in,
+ etc/sudo.pp, include/compat/getaddrinfo.h, include/sudo_event.h,
+ include/sudo_util.h, lib/util/fnmatch.c, lib/util/getaddrinfo.c,
+ lib/util/regress/vsyslog/vsyslog_test.c, logsrvd/logsrvd.c,
+ plugins/audit_json/audit_json.c,
+ plugins/python/example_debugging.py,
+ plugins/python/regress/check_python_examples.c,
+ plugins/python/regress/testhelpers.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_client.c, plugins/sudoers/parse.h,
+ plugins/sudoers/pwutil.h,
+ plugins/sudoers/regress/cvtsudoers/test30.sh, scripts/mkdep.pl,
+ src/exec.c, src/exec_monitor.c, src/exec_pty.c, src/sesh.c:
+ Apply spelling fixes. Fixes from PR #30 (ka7) and Bug #925
+ (fossies.org codespell)
+ [1fb13dc3991b]
+
+2020-05-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Makefile.in, etc/sudo-python.pp:
+ Use the proper python version in the libpython dependency on Debian.
+ The configure script already detects the python version, we just
+ need to use it.
+ [4e49c53f206f]
+
+ * plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po, po/ja.mo,
+ po/ja.po, po/sv.mo, po/sv.po:
+ Updated translations from translationproject.org
+ [abdb2d6fe7cb]
+
+ * NEWS:
+ Bug #922 and Bug #923
+ [7a77f74c436f]
+
+2020-05-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * etc/sudo.pp:
+ Fix Debian ldap dependency broken in last commit.
+ [4980b1b653ef]
+
+ * etc/sudo.pp:
+ Fix "make package" on Debian when linux_audit is not set.
+ [a00d7dec5821]
+
+ * doc/sudo_logsrv.proto.man.in, doc/sudo_logsrv.proto.mdoc.in,
+ include/log_server.pb-c.h, lib/logsrv/log_server.pb-c.c,
+ lib/logsrv/log_server.proto, logsrvd/logsrvd.c, logsrvd/sendlog.c,
+ plugins/sudoers/iolog_client.c:
+ Add a ClientHello message that client sends to the server. This
+ makes it easier to detect a plaintext client sending to a TLS port.
+ Without this, the TLS server will be silent as it waits for the
+ client to initiate the TLS connection.
+ [22c033bcf456]
+
+ * logsrvd/sendlog.c, plugins/sudoers/iolog_client.c:
+ Better error messages when there is a problem with the TLS
+ connection. If SSL_read, SSL_write or SSL_connect fails we can use
+ the reason string to let the user know what the problem is.
+ [92f603e37e40]
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ logsrvd/logsrvd_conf.c:
+ Make the default certificate and key paths match the example file.
+ [f642836bfcf0]
+
+ * logsrvd/logsrvd.c, plugins/sudoers/iolog_client.c:
+ Warn about tls errors during startup so the user has a clue. We
+ write messages to stderr until we become a daemon.
+ [25ad61aa7dab]
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ doc/sudo_sendlog.man.in, doc/sudo_sendlog.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, include/log_server.pb-c.h,
+ lib/logsrv/log_server.pb-c.c, lib/logsrv/log_server.proto,
+ logsrvd/logsrvd.c, logsrvd/sendlog.c:
+ Remove the tls parameter from the ServerHello message. The TLS
+ connection is now initiated before ServerHello is received.
+ [9d8b76f14cda]
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_client.c, plugins/sudoers/iolog_plugin.h,
+ plugins/sudoers/policy.c:
+ Adapt sudoers iolog client to log server dual port changes. The TLS
+ handshake now occurs before the ServerHello message is read. This
+ fixes potential man-in-the-middle attacks and works better with TLS
+ 1.3.
+ [8137b029a3fe]
+
+ * doc/sudo_logsrv.proto.man.in, doc/sudo_logsrv.proto.mdoc.in,
+ doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ examples/sudo_logsrvd.conf, logsrvd/logsrv_util.h,
+ logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c,
+ logsrvd/sendlog.c:
+ Use port 30343 for plaintext and port 30344 for TLS. For TLS
+ connections we now do the TLS handshake immediately before the
+ ServerHello message. This lets the client recieve an alert from the
+ server is there is a handshake error after the TLS connect has
+ succeeded. It also means that the contents of the ServerHello are
+ protected from a man-in-the-middle attack.
+ [bb4d8b57b3dd]
+
+ * include/sudo_util.h, lib/util/host_port.c,
+ lib/util/regress/host_port/host_port_test.c, logsrvd/logsrvd_conf.c,
+ plugins/sudoers/iolog_client.c:
+ Add support for a tls flag in sudo_parse_host_port(). If the string
+ "(tls)" appears at the end, the tls flag is set to true and the
+ default tls port is used if necessary.
+ [f0d9a225cd75]
+
+ * logsrvd/sendlog.c, plugins/sudoers/iolog_client.c:
+ Plug memory leaks in sudo_sendlog
+ [886254bcae6a]
+
+ * lib/util/event.c, lib/util/event_poll.c, lib/util/event_select.c:
+ Handle EAGAIN like we do ENOMEM from poll() and select(). On some
+ systems, poll() and select() can return EAGAIN instead of ENOMEM if
+ there is a kernel resource shortage. In this case we just re-enter
+ the event loop and retry.
+ [048df2548dcc]
+
+2020-05-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Use the --embed when running "python3-config --ldflags" if
+ supported. Newer versions of python3-config only include libpython
+ in the output when the --embed is used. Otherwise, "python3-config
+ --libs" and "python3-config --ldflags" only list the libraries
+ python is dependent on and not the python library itself.
+ [d90dc892c726]
+
+2020-04-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/sendlog.c, plugins/sudoers/iolog_client.c:
+ On error, remove the connection with an error without freeing the
+ closure. Fixes the final message at the end when there is a network
+ error.
+ [0e1952eb707b]
+
+ * lib/util/event_poll.c:
+ Do not call poll(2) or ppoll(2) with nfds > RLIMIT_NOFILE. Both
+ poll(2) and ppoll(2) will return EINVAL if the nfds function
+ argument is larger than the max files per process resource limit.
+ Prevent this by limiting the max number entries in the pfds[] array
+ to the RLIMIT_NOFILE soft limit.
+ [ab0f798bb024]
+
+2020-04-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_event.h, lib/util/event.c:
+ The timeout parameter of sudo_ev_add() should be const.
+ [de85c8897aad]
+
+2020-04-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog_client.c:
+ Don't free TLS on error in tls_init(), it is freed in
+ client_closure_free(). Fixes a double free on error introduced with
+ the TLS state cleanup in client_closure_free().
+ [f1b478f2ec13]
+
+ * logsrvd/logsrvd.c:
+ Check for tls_config->dhparams_path being non-NULL before using it.
+ [09348a25bfd2]
+
+2020-04-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_sendlog.man.in, doc/sudo_sendlog.mdoc.in:
+ Document the TLS and test options.
+ [e5f6b6c46c25]
+
+ * logsrvd/sendlog.c:
+ Allow -t option even without OpenSSL Also add -t to the usage
+ message
+ [d874c9a67ed6]
+
+ * logsrvd/sendlog.c:
+ Use sudo_strtonum() instead of relying on strtoll(). Older, pre-C99,
+ systems may not include strtoll() in their C library.
+ [a1a610bbe022]
+
+ * include/protobuf-c/protobuf-c.h:
+ Allow this to build on systems without stdint.h by using config.h.
+ Old, pre-C99, systems may have inttypes.h but not stdint.h.
+ [72e603875b82]
+
+2020-04-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * etc/sudo-logsrvd.pp, scripts/pp:
+ Fix support for pp_systemd_disabled and check for systemd existence.
+ On our build schroots we don't have systemctl installed but do have
+ the /etc/systemd and /lib/systemd (or /usr/lib/systemd) directories.
+ [93917f4130b0]
+
+ * etc/sudo-logsrvd.pp:
+ Set pp_macos_service_id instead of
+ pp_macos_default_service_id_prefix. It is only effective to set
+ pp_macos_default_service_id_prefix in the indivisual %service
+ sections (and not %set) so we may was well use pp_macos_service_id
+ which includes the service name.
+ [84ccf13e7076]
+
+ * etc/sudo-logsrvd.pp:
+ Set launchd service id prefix to "ws.sudo." The default value in
+ PolyPkg is "com.quest.rc."
+ [eb581d74573e]
+
+ * scripts/pp:
+ Fix macOS package creation.
+ [556c0051c0fc]
+
+2020-04-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog_client.c:
+ Shut down the TLS connection cleanly in client_closure_free(). Also
+ free the SSL data which is part of the client closure.
+ [258ec8832cbd]
+
+ * src/exec_monitor.c, src/exec_nopty.c, src/selinux.c, src/sudo.c,
+ src/sudo.h, src/sudo_edit.c, src/sudo_exec.h:
+ Fix sudoedit when running with SELinux RBAC mode. We can't use
+ run_command() to run sesh, that will use the sudo event loop (and
+ might run it in a pty!). There's no need to relabel the tty when
+ copying files. Get the path to sesh from sudo.conf.
+
+ Currently, for SELinux RBAC, the editor runs with the target user's
+ security context. This defeats the purpose of sudoedit. Fixing that
+ requires passing file descriptors between the main sudo process
+ (running with the invoking user's security context) and sesh
+ (runnning with the target user's security context).
+ [81c9ec600894]
+
+ * MANIFEST, src/Makefile.in, src/copy_file.c, src/sesh.c,
+ src/sudo_edit.c, src/sudo_exec.h:
+ Refactor the sudoedit code to copy files so it can be shared. The
+ SELinux sudoedit code now extends the destination file the same way
+ the non-SELinux version does.
+ [82c44299309e]
+
+ * src/sudo_edit.c:
+ Do not remove sudoedit temporary files if we cannot overwrite the
+ real file. The warning message says the files were preserved but
+ they actually got removed.
+ [685f2de6bb2e]
+
+ * include/compat/glob.h, lib/util/glob.c:
+ Make gl_pathc, gl_matchc and gl_offs size_t in glob_t to match
+ POSIX.
+ [c3586082d3ea]
+
+ * scripts/pp:
+ Only remove the systemd unit service file if we copied it manually.
+ If the service file was installed as part of the package it will be
+ removed automatically when the package is uninstalled.
+ [e98e1493c5bf]
+
+2020-04-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_logsrv.proto.man.in, doc/sudo_logsrv.proto.mdoc.in:
+ Document TLS settings in ServerHello
+ [22ae16f41585]
+
+2020-04-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sudo_edit.c:
+ Extend the original file before to the new size before updating it.
+ Instead of opening the original file for writing w/ tuncation, we
+ first extend the file with zeroes (by writing, not seeking), then
+ overwrite it. This should allow sudo to fail early if the disk is
+ out of space before it overwrites the original file.
+ [aef4db03e9e1]
+
+ * src/sudo.c:
+ I/O log plugins should be closed *before* the policy plugin, not
+ after.
+ [dec6fccf63d4]
+
+ * plugins/sudoers/set_perms.c:
+ Fix typo
+ [82b0efbb6c26]
+
+ * plugins/sudoers/iolog.c:
+ Only display error string once on I/O error. We already include the
+ error string in the format so no need to use errno too.
+ [59795855d6a2]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/policy.c:
+ Free passwd and group caches in I/O plugin after log_warning(), not
+ before. The logging functions may try to use the cache via
+ set_perms(PERM_ROOT).
+ [652b925b9658]
+
+2020-04-17 Laszlo Orban <laszlo.orban@quest.com>
+
+ * logsrvd/logsrvd.c:
+ add missing shudown of TLS connection
+ [14b25a0f4f6b]
+
+2020-04-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * etc/sudo-logsrvd.pp, scripts/pp:
+ Disable systemd support on Linux systems that don't use it.
+ [3c01c91dbfb2]
+
+2020-04-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ 1.9.0 final
+ [acf3b4592384]
+
+ * etc/sudo-logsrvd.pp, scripts/pp:
+ Update PolyPkg from my branch with systemd support.
+ [a7a487496209]
+
+2020-04-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/example_conversation.py,
+ plugins/python/example_io_plugin.py, plugins/python/regress/testdata
+ /check_example_io_plugin_fails_with_python_backtrace.stdout:
+ If the signal.Signals enum is not present, search the dictionary.
+ The Signals enum was added in Python 3.5. If it is not present we
+ need to iterate over the dictionary items, looking for signal name
+ to number mappings. Fixes the signal tests with Python 3.4.
+ [22811794ed46]
+
+ * plugins/python/regress/check_python_examples.c,
+ plugins/python/sudo_python_module.c:
+ Python dictionaries are sparse so we cannot use pos as an index.
+ When converting sudo options from a dictionary to a tuple we need to
+ track the current index into the tuple separately from the position
+ of the dictionary entry.
+ [07cb8a0c7f21]
+
+2020-04-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * etc/sudo-logsrvd.pp:
+ Fix handling of /etc/sudo_logsrvd.conf in the sudo-logsrvd package.
+ For rpm and deb we include the file directly and mark it volatile.
+ For all others we copy it in the postinstall script from the example
+ dir if the file doesn't already exist.
+ [83264a96b923]
+
+ * scripts/mkpkg:
+ Check for the Sun Studio C compiler on Solaris under /opt. Also
+ intialize with_python to false.
+ [52e28d55f9a6]
+
+ * po/sudo.pot:
+ regen
+ [faaacb7777d4]
+
+ * lib/util/parseln.c:
+ Explicitly include stdio.h for getdelim(3)
+ [3b0bff3ef388]
+
+ * logsrvd/logsrvd.c:
+ Reload sudo.conf upon SIGUP This makes it possible to update the
+ Debug settings in sudo.conf and have them take effect on reload.
+ [9fb7baf9a3ad]
+
+ * logsrvd/logsrvd.c, logsrvd/sendlog.c,
+ plugins/sudoers/iolog_client.c:
+ Store the result of ERR_get_error() so we can use it for both warn
+ and debug. Otherwise, only the debug framework gets the actual error
+ and the user won't see the problem.
+ [039565f16d13]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c:
+ Disable IPv4-mapped IPv6 addresses in the listener. Also store the
+ host + port string and use it in error messages.
+ [3fbac477ef6b]
+
+ * configure, configure.ac, examples/Makefile.in:
+ Install the example sudo_logsrvd.conf unless one already exists
+ [89c41b936c44]
+
+2020-04-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * examples/sudo_logsrvd.conf:
+ Make the path to logsrvd_cert.pem match the documentation.
+ [b2a45e7c9cdb]
+
+ * etc/sudo-logsrvd.pp, logsrvd/logsrvd.c:
+ Create the pid file parent directory if it doesn't already exist.
+ Also package the run directory in the sudo_logsrvd PolyPkg file.
+ [ac8b573e8545]
+
+ * configure, configure.ac:
+ Sudo 1.9.0rc1
+ [7d437646afc2]
+
+ * MANIFEST:
+ Include all python plugin files in MANIFEST, not the directory
+ itself.
+ [4aa09dd70b9e]
+
+ * plugins/python/example_approval_plugin.py,
+ plugins/python/example_audit_plugin.py,
+ plugins/python/example_group_plugin.py,
+ plugins/python/example_io_plugin.py,
+ plugins/python/example_policy_plugin.py, plugins/python/regress/test
+ data/check_example_io_plugin_fails_with_python_backtrace.stdout:
+ Avoid using typing annotations so tests run with Python 3.4.
+ [88b7048bc4a6]
+
+ * plugins/python/python_plugin_common.c, plugins/python/regress/testda
+ ta/check_loading_fails_missing_classname.stderr:
+ Sort the list of possible plugins before printing it. This gives
+ more reproducible error messages for the tests.
+ [ea33f4970268]
+
+ * plugins/python/regress/iohelpers.h, plugins/python/regress/testdata/
+ check_example_group_plugin_is_able_to_debug.log, plugins/python/regr
+ ess/testdata/check_example_io_plugin_command_log.stored, plugins/pyt
+ hon/regress/testdata/check_example_io_plugin_command_log_multiple1.s
+ tored, plugins/python/regress/testdata/check_example_io_plugin_comma
+ nd_log_multiple2.stored, plugins/python/regress/testdata/check_examp
+ le_io_plugin_failed_to_start_command.stored, plugins/python/regress/
+ testdata/check_example_io_plugin_fails_with_python_backtrace.stderr,
+ plugins/python/regress/testdata/check_loading_fails_wrong_path.stder
+ r, plugins/python/regress/testdata/check_multiple_approval_plugin_an
+ d_arguments.stdout, plugins/python/regress/testdata/check_python_plu
+ gins_do_not_affect_each_other.stdout,
+ plugins/python/regress/testhelpers.h:
+ Use regular expressions when matching expected and actual text.
+ [f2562728481a]
+
+ * plugins/python/regress/iohelpers.h, plugins/python/regress/testdata/
+ check_example_debugging_c_calls@info.log, plugins/python/regress/tes
+ tdata/check_example_debugging_plugin@info.log,
+ plugins/python/regress/testhelpers.c:
+ Use regex to match __init__.py instead of hacking it in
+ verify_log_lines()
+ [8bf71289e585]
+
+ * plugins/python/pyhelpers.c, plugins/python/python_plugin_common.c,
+ plugins/python/regress/check_python_examples.c,
+ plugins/python/regress/iohelpers.c,
+ plugins/python/regress/plugin_approval_test.py, plugins/python/regre
+ ss/testdata/check_example_debugging_c_calls@diag.log, plugins/python
+ /regress/testdata/check_example_debugging_c_calls@info.log, plugins/
+ python/regress/testdata/check_example_debugging_py_calls@diag.log, p
+ lugins/python/regress/testdata/check_example_debugging_py_calls@info
+ .log, plugins/python/regress/testdata/check_example_policy_plugin_va
+ lidate_invalidate.log, plugins/python/regress/testdata/check_loading
+ _fails_wrong_classname.stderr, plugins/python/regress/testdata/check
+ _multiple_approval_plugin_and_arguments.stdout,
+ plugins/python/regress/testhelpers.h:
+ Make most python tests pass with Python 3.4 Dictionary order is not
+ stable in Python < 3.6 so we need to sort by key to have consistent
+ results. The LogHandler output is also different on older Python
+ versions. Also, don't stop running python tests after the first
+ error.
+ [aaa06cb5fac1]
+
+ * plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c:
+ Increase the maximum delay again for slower systems. Otherwise we
+ may get a spurious test failure.
+ [6660908aa93d]
+
+ * plugins/python/Makefile.in, plugins/sudoers/Makefile.in,
+ scripts/mkdep.pl:
+ Handle dependencies for .h files in the same directory as the
+ source. Fixes missing header dependencies for the sudoers and python
+ plugins.
+ [3109dd5cf61e]
+
+ * etc/sudo.pp:
+ Remove bits for Tru64 kit-style packages
+ [0e9a9580d76c]
+
+ * MANIFEST, Makefile.in, configure, configure.ac, etc/sudo-logsrvd.pp,
+ etc/sudo-python.pp, etc/sudo.pp:
+ Split sudo_logsrvd and the python plugin into their own packages.
+ [9aee8247f0ba]
+
+ * scripts/mkpkg:
+ Build python packages where possible.
+ [7a2b993bb8ac]
+
+2020-04-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog_client.c:
+ Don't pass a NULL submitcwd or ttyname value to the server. It is
+ possible for the cwd and/or tty to be missing. If we send a NULL
+ pointer to the server where it expects a string the AcceptMessage
+ will fail to parse.
+ [4f96d1c6e41c]
+
+ * include/sudo_plugin.h:
+ Disable -Wstrict-prototypes for sudo_hook_fn_t typedef.
+ [15d2a1332865]
+
+ * plugins/python/python_plugin_common.c:
+ Fall back to using Py_Finalize() for Python version < 3.6
+ [e7ad63e57c79]
+
+2020-04-06 Robert Manner <robert.manner@balabit.com>
+
+ * logsrvd/eventlog.c:
+ logsrvd/eventlog.c: add a newline after each log message for logfile
+ output
+ [457f77b8f3be]
+
+ * lib/iolog/iolog_fileio.c:
+ lib/iolog/iolog_fileio.c: do not call fchown on invalid fd
+
+ Fixes the warning in the log: iolog_write_info_file_json: unable to
+ fchown 0:0 /var/log/...: Bad file descriptor
+ [bccdaf007db8]
+
+ * logsrvd/iolog_writer.c:
+ logsrvd/iolog_writer.c: treat runuid, rungid 0 as valid (usually
+ ==root)
+ [5a7c447e9619]
+
+2020-04-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * po/eo.mo, po/eo.po, po/sr.mo, po/sr.po:
+ Updated translations from translationproject.org
+ [6e47dbfdba2c]
+
+2020-04-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * examples/Makefile.in:
+ Install example sudo_logsrvd.conf file
+ [c1c6f4c8119d]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Make it clear in the sudoers grammar that sudoedit needs file args.
+ Debian bug #571621
+ [b6358b602623]
+
+2020-04-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Fixed Debian bugs #571621, #596631 and #669687
+ [6058c1c46739]
+
+ * doc/sudo.man.in, doc/sudo.mdoc.in, plugins/sudoers/env.c:
+ Truncate the command args at 4096 chars when formatting
+ SUDO_COMMAND. We have to limit the length of SUDO_COMMAND to avoid
+ getting E2BIG from execve(2) for very long argument vectors. The
+ command's environment also counts against the ARG_MAX limit. Debian
+ bug #596631
+ [ff1fa8e3377f]
+
+ * plugins/sudoers/auth/pam.c:
+ Do not try to delete creds we did not set. If pam_setcred() fails
+ when opening the PAM session, we don't want to call it with
+ PAM_DELETE_CRED when closing the session.
+ [c31039431c46]
+
+2020-04-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/API, plugins/sudoers/auth/aix_auth.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/secureware.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h, plugins/sudoers/check.c,
+ plugins/sudoers/sudoers.h:
+ Add a force flag to sudo_auth_cleanup() to force immediate cleanup.
+ This is used for PAM authentication to make sure pam_end() is called
+ via sudo_auth_cleanup() when the user authenticates successfully but
+ sudoers denies the command. Debian bug #669687
+ [98cb9d98f547]
+
+ * plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c:
+ Increase the maximum delay for slower systems. Otherwise we may get
+ a spurious test failure.
+ [e4c1fffd427c]
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in:
+ Document when cwd_optional was added.
+ [165447e1d7fa]
+
+2020-03-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ plugins/sudoers/policy.c, src/exec.c, src/sudo.c, src/sudo.h:
+ Add cwd_optional to command details and enable it in the sudoers
+ plugin. If cwd_optional is set to true, a failure to set the cwd
+ will be a warning, not an error, and the command will still run.
+ Debian bug #598519
+ [a6694704d92f]
+
+ * doc/sudo.man.in, doc/sudo.mdoc.in:
+ The policy close function is responsible for closing the PAM
+ session.
+ [db4af211ff75]
+
+ * .clang-format:
+ Config file for clang-format 8.x and higher based on webkit style.
+ This approximates what I want the sudo coding style to look like.
+ Only deviations from webkit style are included.
+ [d3ec3a8401cf]
+
+ * src/exec_pty.c:
+ Don't kill the command just because the loop exited unexpectedly. We
+ currently have no good way to distinguish between an error executing
+ the command and an error while the command is running.
+
+ In the future, we should have additional status codes so we can tell
+ what type of condition caused the loop to exit.
+
+ For now, only kill the command if cstat is left uninitialized.
+ [9492d60783fe]
+
+2020-03-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd.c:
+ Write process ID as an unsigned int (with a cast). On Solaris, pid_t
+ may be typedef'd as a long but the actual range is 32 bits at most.
+ [b9a818d77142]
+
+ * doc/LICENSE:
+ Add license info for a few other files. These are all ISC licensed
+ but it is still best to have them all listed in one place.
+ [dd37dc484ea5]
+
+ * plugins/sudoers/po/ca.mo, plugins/sudoers/po/ca.po,
+ plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt.mo, plugins/sudoers/po/pt.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ plugins/sudoers/po/zh_TW.mo, plugins/sudoers/po/zh_TW.po, po/ca.mo,
+ po/ca.po, po/cs.mo, po/cs.po, po/de.mo, po/de.po, po/eo.mo,
+ po/eo.po, po/fi.mo, po/fi.po, po/fr.mo, po/fr.po, po/hr.mo,
+ po/hr.po, po/it.mo, po/it.po, po/ja.mo, po/ja.po, po/ko.mo,
+ po/ko.po, po/nb.mo, po/nb.po, po/pl.mo, po/pl.po, po/pt.mo,
+ po/pt.po, po/pt_BR.mo, po/pt_BR.po, po/sv.mo, po/sv.po, po/tr.mo,
+ po/tr.po, po/uk.mo, po/uk.po, po/vi.mo, po/vi.po, po/zh_CN.mo,
+ po/zh_CN.po, po/zh_TW.mo, po/zh_TW.po:
+ Updated translations from translationproject.org
+ [58d62352abff]
+
+ * lib/util/getusershell.c, lib/util/host_port.c, lib/util/roundup.c,
+ logsrvd/iolog_writer.c, logsrvd/logsrv_util.c,
+ logsrvd/logsrv_util.h, logsrvd/logsrvd.c, logsrvd/logsrvd.h,
+ logsrvd/logsrvd_conf.c, logsrvd/sendlog.c, logsrvd/sendlog.h,
+ plugins/sudoers/iolog_client.c, plugins/sudoers/iolog_plugin.h:
+ Some new source files got created with my old email address.
+ [ede435f55f5c]
+
+ * .gitignore, .hgignore:
+ Ignore __pycache__ directories.
+ [5901cfb35a74]
+
+ * include/sudo_iolog.h, lib/iolog/iolog_util.c, logsrvd/sendlog.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/sudoreplay.c:
+ iolog_parse_loginfo() now opens the log file itself.
+ [bf03f505fc94]
+
+ * include/sudo_iolog.h, lib/iolog/Makefile.in,
+ lib/iolog/iolog_fileio.c, lib/iolog/iolog_util.c,
+ logsrvd/eventlog.c, logsrvd/iolog_writer.c, logsrvd/logsrvd.h,
+ logsrvd/sendlog.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/iolog.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/sudoreplay.c:
+ Write an extended I/O info log in JSON format. This will be used by
+ sudoreplay if it exists to get more information about the command
+ being replayed.
+ [5fc89148c214]
+
+ * MANIFEST, doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in,
+ include/sudo_iolog.h, lib/iolog/Makefile.in, lib/iolog/iolog_json.c,
+ lib/iolog/iolog_util.c, plugins/sudoers/sudoreplay.c:
+ Parse I/O JSON info file in JSON if present. The JSON version
+ includes more information than the original "log" file in the I/O
+ log dir.
+ [269ae210ea34]
+
+ * logsrvd/iolog_writer.c, logsrvd/logsrvd.h:
+ Store runenv in the I/O log info file too.
+ [15f90fb3748f]
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c:
+ Create files for check_iolog_plugin in the build dir, not src dir.
+ [bdaea95b47fc]
+
+ * include/sudo_json.h, lib/iolog/iolog_fileio.c, lib/util/json.c,
+ logsrvd/eventlog.c, logsrvd/iolog_writer.c, logsrvd/logsrvd.h,
+ plugins/audit_json/audit_json.c:
+ Do not use JSON_ARRAY with sudo_json_add_value()
+ [c74b75adb90f]
+
+ * MANIFEST, lib/iolog/Makefile.in, lib/iolog/iolog_json.c,
+ lib/iolog/iolog_json.h,
+ lib/iolog/regress/iolog_json/check_iolog_json.c,
+ lib/iolog/regress/iolog_json/test1.in,
+ lib/iolog/regress/iolog_json/test2.in,
+ lib/iolog/regress/iolog_json/test2.out.ok,
+ lib/iolog/regress/iolog_json/test3.in, lib/util/json.c:
+ Add tests for the simple json parser.
+ [9ede5000f4c7]
+
+ * lib/iolog/iolog_json.c:
+ Simply the JSON parsing code a bit. We can use a single stack for
+ nested objects and arrays. There is also no need to track the
+ current object and array separately. This allows us to remove the
+ array special case when assigning a value.
+ [4a34e528d9f0]
+
+ * NEWS:
+ Update NEWS for 1.9.0b5 changes
+ [bf8db62788d3]
+
+ * logsrvd/logsrvd.c:
+ sudo_logsrvd now exits with an error if it cannot open any listen
+ sockets.
+ [47a22f71e286]
+
+ * configure, doc/sudo_logsrvd.conf.man.in,
+ doc/sudo_logsrvd.conf.mdoc.in, doc/sudo_logsrvd.man.in,
+ doc/sudo_logsrvd.mdoc.in, examples/sudo_logsrvd.conf,
+ logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c,
+ m4/sudo.m4, pathnames.h.in:
+ Create a pidfile for sudo_logsrvd when not run with the -n flag.
+ [9f1b8edff6cc]
+
+ * etc/sudo.pp:
+ Add sudo_logsrvd as a service so it gets started at boot.
+ [d2ac9eb87dbf]
+
+ * plugins/sudoers/po/sudoers.pot:
+ Update sudoers.pot with json parser warnings.
+ [2b277f799d2e]
+
+2020-03-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * scripts/mkpkg:
+ Enable OpenSSL on systems that can support it.
+ [976370b9d9db]
+
+2020-03-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, logsrvd/logsrvd.c:
+ Add configure check for SSL_CTX_get0_certificate(). Dummy out
+ verify_server_cert() if it is not present to allow building on older
+ OpenSSL versions. Rewriting this to work with old OpenSSL is not
+ worth the trouble.
+ [61349d2533fe]
+
+ * lib/iolog/hostcheck.c:
+ Include stdlib.h for malloc(3) prototype. We shouldn't rely on it to
+ be implicitly included via OpenSSL headers.
+ [9f4f7d3d3662]
+
+2020-03-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/policy.c:
+ Only set errstr for plugin API version 1.15 and above.
+ [780722091e9f]
+
+2020-03-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Sudo 1.8.31p1
+ [40629e6fd692]
+
+ * src/limits.c:
+ Ignore a failure to restore the RLIMIT_CORE resource limit. Linux
+ containers don't allow RLIMIT_CORE to be set back to RLIM_INFINITY
+ if we set the limit to zero, even for root. This is not a problem
+ outside the container.
+ [1064b906ca68]
+
+2020-03-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [72ca06a294b4]
+
+ * include/sudo_event.h, lib/util/event.c:
+ Add SUDO_EV_MASK to mask off invalid event values. Now used by
+ sudo_ev_init() to avoid bogus events.
+ [10a5d1afa1c9]
+
+2020-03-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/python/regress/iohelpers.c,
+ plugins/python/regress/testhelpers.c:
+ Avoid using sprintf(), vsprintf(), strcat(), and strncat(). It is
+ less error-prone to use functions with a return value that indicates
+ when truncation ocurred.
+ [21938a3b1548]
+
+ * plugins/sudoers/match_digest.c:
+ Work around two Coverity false positives; CID 208813 208815
+ [389bf3749ed2]
+
+ * logsrvd/logsrvd.c:
+ Fix potential use-after-free; Coverity CID 208814
+ [e575532efe35]
+
+ * plugins/python/regress/iohelpers.h, plugins/python/regress/testdata/
+ check_example_debugging_c_calls@info.log, plugins/python/regress/tes
+ tdata/check_example_debugging_plugin@info.log,
+ plugins/python/regress/testhelpers.c:
+ Don't hard-code path to logging/__init__.py or line numbers. Allows
+ python plugin tests to success on versions other than 3.7.
+ [659d3d3fcb8b]
+
+ * doc/LICENSE:
+ Add copyright for the Python bindings.
+ [cc64df1f85f2]
+
+ * plugins/sudoers/match_command.c:
+ Fix typo introduced on systems with O_PATH or O_EXEC
+ [e8fea3eabf99]
+
+ * NEWS:
+ Update for sudo 1.9.0
+ [39158cb4af26]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/match.c, plugins/sudoers/match_command.c,
+ plugins/sudoers/regress/sudoers/test14.in,
+ plugins/sudoers/regress/sudoers/test14.json.ok,
+ plugins/sudoers/regress/sudoers/test14.ldif.ok,
+ plugins/sudoers/regress/sudoers/test14.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test14.out.ok,
+ plugins/sudoers/regress/sudoers/test14.toke.ok,
+ plugins/sudoers/sudoers_version.h:
+ Allow the ALL keyword to be specified with a digest list.
+ [9856ed3cde7f]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/ldap_util.c, plugins/sudoers/match.c,
+ plugins/sudoers/match_command.c, plugins/sudoers/match_digest.c,
+ plugins/sudoers/parse.h, plugins/sudoers/regress/sudoers/test14.in,
+ plugins/sudoers/regress/sudoers/test14.json.ok,
+ plugins/sudoers/regress/sudoers/test14.ldif.ok,
+ plugins/sudoers/regress/sudoers/test14.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test14.out.ok,
+ plugins/sudoers/regress/sudoers/test14.toke.ok,
+ plugins/sudoers/sudo_ldap.h:
+ Allow a list of digests to be specified for a command.
+ [e0e9ecee870b]
+
+ * plugins/sudoers/ldap_util.c, plugins/sudoers/parse_ldif.c:
+ A struct member of type ALL should have its name field set to NULL.
+ [484b9af004af]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l:
+ Allow Cmd_Alias in addition to Cmnd_Alias. Some people find using
+ Cmd_Alias more natural.
+ [55edb5057091]
+
+2020-03-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c:
+ Add pam_ruser and pam_rhost sudoers flags.
+ [b1d494440004]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/sendlog.c,
+ logsrvd/sendlog.h:
+ Store the event base in the client closure. Explicitly passing the
+ event base removes the need to set a default base.
+ [0e4ae8d810f8]
+
+ * plugins/sudoers/iolog.c:
+ Revert change to initialize io_operations earlier. Instead, check
+ io_operations.open for NULL which is the case for "sudo -V". Also
+ move the early return in sudoers_io_open() for "sudo -V" until after
+ we have initialized debugging.
+ [0e9e7a99725d]
+
+2020-02-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog.c:
+ Initialize io_operations earlier.
+ [ab235d88f8ae]
+
+2020-02-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog_client.c:
+ Mark up some remaining TODOs
+ [847c9328a7b5]
+
+ * src/conversation.c:
+ Sudo's -S option should override the SUDO_CONV_PREFER_TTY flag.
+ [f5737b68c0bf]
+
+ * plugins/python/pyhelpers.c, plugins/python/python_plugin_policy.c,
+ plugins/python/sudo_python_module.c:
+ Use C99 __func__ instead of gcc-specific __PRETTY_FUNCTION__
+ [db4f5d7c200e]
+
+2020-02-27 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/example_debugging.py, plugins/python/regress/testdata
+ /check_example_debugging_c_calls@diag.log, plugins/python/regress/te
+ stdata/check_example_debugging_c_calls@info.log, plugins/python/regr
+ ess/testdata/check_example_debugging_plugin@err.log, plugins/python/
+ regress/testdata/check_example_debugging_plugin@info.log:
+ plugins/python/regress: add a test and example of using the python
+ logger
+ [ed23b3ba375f]
+
+ * MANIFEST, doc/sudo_plugin_python.man.in,
+ doc/sudo_plugin_python.mdoc.in, plugins/python/Makefile.in,
+ plugins/python/python_baseplugin.c,
+ plugins/python/python_convmessage.c,
+ plugins/python/python_importblocker.c,
+ plugins/python/python_loghandler.c,
+ plugins/python/python_plugin_common.c,
+ plugins/python/sudo_python_module.c,
+ plugins/python/sudo_python_module.h:
+ plugins/python/sudo_module: add sudo.LogHandler
+
+ so python log system can be used with sudo logsystem. Loggers use it
+ by default (the handler is set on the root logger). If that is not
+ the intent, it can be overridden explicitly.
+ [45b8902ce188]
+
+2020-02-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * INSTALL, Makefile.in, config.h.in, configure, configure.ac,
+ lib/iolog/iolog_fileio.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_client.c,
+ plugins/sudoers/iolog_plugin.h, plugins/sudoers/sudoers.c:
+ Add --disable-log-server and --disable-log-client configure options.
+ These can be used to optionally disable building sudo_logsrvd and
+ support for remote I/O logging in the sudoers plugin respectively.
+ [bc802e022f22]
+
+2020-02-26 Robert Manner <robert.manner@balabit.com>
+
+ * doc/sudo_plugin_python.man.in, doc/sudo_plugin_python.mdoc.in,
+ plugins/python/python_plugin_common.c,
+ plugins/python/regress/check_python_examples.c, plugins/python/regre
+ ss/testdata/check_loading_fails_missing_classname.stderr, plugins/py
+ thon/regress/testdata/check_loading_succeeds_with_missing_classname.
+ stdout:
+ plugins/python: autodetect ClassName field
+
+ If "ClassName" is not specified, load the one and only sudo.Plugin
+ from the module (if so), otherwise display which plugins are
+ available from which the system admin can choose.
+ [b9dbbf1b6e97]
+
+ * doc/sudo_plugin_python.man.in, doc/sudo_plugin_python.mdoc.in,
+ plugins/python/Makefile.in, plugins/python/python_plugin_common.c:
+ plugins/python/plugin_common: add a default search path for python
+ plugins
+
+ If the ModulePath is relative, assume it is under
+ "/usr/local/libexec/sudo/python" or wherever the sudo plugins are in
+ a "python" subdirectory.
+ [5f75db882754]
+
+ * plugins/python/regress/check_python_examples.c, plugins/python/regre
+ ss/testdata/check_example_audit_plugin_version_display.stdout, plugi
+ ns/python/regress/testdata/check_example_debugging_py_calls@info.log
+ , plugins/python/regress/testdata/check_example_io_plugin_version_di
+ splay_full.stdout, plugins/python/regress/testdata/check_example_pol
+ icy_plugin_version_display_full.stdout, plugins/python/regress/testd
+ ata/check_multiple_approval_plugin_and_arguments.stdout:
+ plugins/python/regress: update tests for show_version changes
+
+ - plugin->show_version is not marked NULL any more.
+ - if verbose, it also displays which python class was loaded from
+ which file
+ [e30a1e43e3c2]
+
+ * plugins/python/python_plugin_approval.c,
+ plugins/python/python_plugin_audit.c,
+ plugins/python/python_plugin_common.c,
+ plugins/python/python_plugin_common.h,
+ plugins/python/python_plugin_io.c,
+ plugins/python/python_plugin_policy.c:
+ plugins/python: make show_version display the plugin in verbose mode
+
+ Before it only displayed the plugin version, now it also displays
+ which python plugin is loaded to be more useful.
+ [8c94175ead70]
+
+ * plugins/python/python_plugin_approval.c,
+ plugins/python/python_plugin_common.c:
+ plugins/python/approval: fix show_version crash when it is not
+ implemented
+
+ For approval plugins show_version is not optional.
+ [61f6b4679d6b]
+
+2020-02-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c:
+ Avoid calling sudoers_policy_exec_setup() on error. We only want to
+ pass the execution environment back for commands that are accepted
+ or rejected. Also avoid potentially freeing the wrong pointer when
+ garbage collection is enabled.
+ [a3a202e89951]
+
+2020-02-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/eventlog.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c:
+ Open event log at config time instead of open/close for each entry.
+ If logging via syslog, do the openlog() at config time instead. We
+ still lock the log file prior to writing to it but unlock
+ immediately after.
+ [3236bd001160]
+
+ * lib/util/locking.c:
+ Fix unlocking of an entire file with lockf(). Since lockf() uses the
+ files's current offset, we need to seek to the start of the file to
+ unlock the entire file.
+ [e415af1de6ca]
+
+2020-02-21 Robert Manner <robert.manner@balabit.com>
+
+ * doc/sudo_plugin_python.man.in, doc/sudo_plugin_python.mdoc.in:
+ doc/sudo_plugin_python: add approval plugin to supported plugins
+ [5034917e6902]
+
+2020-02-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/util.exp.in:
+ Add sudo_json_free_v1 to symbol exports file too.
+ [0a91a2986952]
+
+ * lib/util/Makefile.in, logsrvd/Makefile.in,
+ plugins/sudoers/Makefile.in:
+ Regenerate dependencies to match the recent JSON changes.
+ [5da86c77629c]
+
+ * plugins/python/python_convmessage.c:
+ Add missing check for calloc(3) failure.
+ [589c32ff2cf1]
+
+2020-02-19 Robert Manner <robert.manner@balabit.com>
+
+ * doc/sudo_plugin_python.man.in, doc/sudo_plugin_python.mdoc.in:
+ doc/sudo_plugin_python: document approval plugin and PluginReject
+ [9e61203dcb8d]
+
+ * plugins/python/sudo_python_module.c:
+ plugins/python/sudo_python_module.c: remove unused declaration
+
+ We do not use structsequence any more.
+ [a5570ba5ad8b]
+
+2020-02-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h:
+ Re-register listeners on SIGHUP. Previously, a config reload would
+ refresh the listener address list but the changes had no effect on
+ the actual addresses being listened on.
+ [c1c0ada6c594]
+
+ * logsrvd/logsrvd.c:
+ Fix compilation error when not built with OpenSSL support. Adds a
+ missing #ifdef HAVE_OPENSSL and reorders code to avoid the need for
+ a static init_tls_server_context() prototype.
+ [976c469eeb57]
+
+2020-02-18 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/python_plugin_common.c:
+ plugins/python: restore the original python inittab after
+ interpreter deinit
+ [b78a5d995de9]
+
+2020-02-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ include/sudo_json.h, lib/util/json.c, logsrvd/eventlog.c:
+ Add support for JSON structured logging using syslog. Note that
+ depending on the system, the default syslog buffer may not be large
+ enough to store all the logging data.
+ [15a6667b1198]
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ examples/sudo_logsrvd.conf, logsrvd/eventlog.c,
+ logsrvd/iolog_writer.c, logsrvd/logsrvd.c, logsrvd/logsrvd.h,
+ logsrvd/logsrvd_conf.c:
+ Add support for JSON logging in sudo_logsrvd.
+ [8b013b899e3b]
+
+ * include/sudo_json.h, lib/util/json.c, lib/util/util.exp.in,
+ plugins/audit_json/audit_json.c, plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/regress/sudoers/test10.json.ok,
+ plugins/sudoers/regress/sudoers/test9.json.ok:
+ Rework the JSON API to write to a memory buffer, not a stdio stream.
+ [ec4e4053e95e]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd_conf.c:
+ Fix support for reloading the config in sudo_logsrvd. We need to re-
+ initialize the TLS server context. Also fix a memory leak of the TLS
+ parameters on reload.
+ [c4ca45502f3e]
+
+2020-02-17 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/pyhelpers.c, plugins/python/pyhelpers.h,
+ plugins/python/python_plugin_common.c,
+ plugins/python/regress/check_python_examples.c, plugins/python/regre
+ ss/testdata/check_example_debugging_load@diag.log,
+ plugins/python/regress/testhelpers.c:
+ plugins/python: only deinit interpreters when sudo unlinks the
+ plugin
+
+ This only happens when sudo unloads the last python plugin. The
+ reason doing so is because there are some python modules which does
+ not support importing them again after destroying the interpreter
+ which has imported them previously.
+
+ Another solution would be to just leak the interpreters (let the
+ kernel free up), but then there might be some python resources like
+ open files would not get cleaned up correctly if the plugin is badly
+ written.
+
+ Tests are meant to test the scenario sudo does, so I have modified
+ them to generally do not unlink but only a few times (~per plugin
+ type) so it does not use 48 interpreters (one gets started on every
+ plugin->open) and it is visible at least which type of plugin fails
+ deinit if there is an error.
+ [13cdead652aa]
+
+ * plugins/python/python_plugin_common.c,
+ plugins/python/sudo_python_debug.c:
+ plugins/python/debug: adapt debug refcount solution of sudoers
+ plugin
+ [dc815e383c39]
+
+2020-02-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog_client.c:
+ The environment in the accept message is runenv not submitenv. The
+ I/O logging plugin is passed the environment the command will run
+ with, not the user's original environment.
+ [b3e1ee513001]
+
+2020-02-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_compat.h, lib/iolog/iolog_fileio.c,
+ plugins/audit_json/audit_json.c, src/utmp.c:
+ Add compatibility define for fseeko(3). This is better than
+ cluttering up the code with #ifdefs for obsolete systems.
+ [a9123f768fe0]
+
+2020-02-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/regress/testsudoers/test8.out.ok,
+ plugins/sudoers/regress/testsudoers/test8.sh:
+ Add test for #include directive without a trailing newline.
+ [dfcfad5c7c41]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Don't require a newline at the end of include or includedir
+ directives.
+ [3d6aa5531609]
+
+2020-02-14 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/regress/testhelpers.c:
+ plugins/python/regress/testhelpers.c: replace fromisoformat
+
+ fromisoformat is only supported from python >=3.7
+ [86bf6de82376]
+
+2020-02-13 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/python_plugin_common.h,
+ plugins/python/sudo_python_module.c:
+ plugins/python: add missing annotations to help cpychecker
+ [fd66659bd681]
+
+ * plugins/python/python_plugin_common.c:
+ plugins/python/python_plugin_common.c: release py_args in close
+
+ even if the arguments are not used (eg. when there is no "close"
+ call in the plugin).
+
+ It was not really a memleak, because interpreter is deinitialized
+ anyway, which frees the object.
+ [5de8c111d40d]
+
+ * plugins/python/python_plugin_approval.c:
+ plugins/python/python_plugin_approval: fix negative ref count
+
+ The python_plugin_api_rc_call function already decrements the
+ refcount of py_args. Python avoids the double free, but the error
+ gets shown if using python debug build.
+ [4370af5b9092]
+
+2020-02-12 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/regress/check_python_examples.c:
+ plugins/python/regress: still some memleak fix
+ [c60050b79a5e]
+
+ * plugins/python/python_plugin_audit.c,
+ plugins/python/python_plugin_common.c,
+ plugins/python/python_plugin_common.h,
+ plugins/python/python_plugin_io.c,
+ plugins/python/python_plugin_policy.c:
+ plugins/python: make storing errstr more explicit
+
+ The error is always stored in plugin_ctx, but it is only set into
+ errstr if the API version is enough. (Previously it worked the
+ opposite: we only stored the error if API level was enough.)
+ [5b4fa733c876]
+
+ * plugins/python/regress/check_python_examples.c:
+ plugins/python/regress: strengthen errstr verification
+
+ Tests did not catch the issue where errstr was not set correctly,
+ but its pointer contained the expected data, because the memory
+ allocator reused the same space for storing the string.
+
+ Now it is either verified to be NULL, or reset to NULL.
+ [973e52ed3f68]
+
+ * plugins/python/regress/check_python_examples.c:
+ plugins/python/regress: simplify plugin option creation
+ [628142f39c63]
+
+2020-02-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_debug.h, lib/util/sudo_debug.c, lib/util/util.exp.in,
+ plugins/audit_json/audit_json.c, plugins/python/sudo_python_debug.c,
+ plugins/sample_approval/sample_approval.c,
+ plugins/sudoers/sudoers_debug.c:
+ Move duplicated code to parse plugin debug flags to libsudo_util.
+ There's no need for four copies of sudo_debug_parse_flags().
+ [cfd9d624d8b1]
+
+2020-02-11 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/python_plugin_common.c,
+ plugins/python/sudo_python_module.c,
+ plugins/python/sudo_python_module.h:
+ plugins/python/sudo_module: let a reject also supply error message
+
+ Same as sudo.PluginError exception, have a sudo.PluginReject
+ exception as well. Added common base exception as well.
+ [e2e36f4778d4]
+
+ * plugins/python/regress/check_python_examples.c,
+ plugins/python/regress/plugin_approval_test.py, plugins/python/regre
+ ss/testdata/check_multiple_approval_plugin_and_arguments.stderr, plu
+ gins/python/regress/testdata/check_multiple_approval_plugin_and_argu
+ ments.stdout, plugins/python/regress/testhelpers.c,
+ plugins/python/regress/testhelpers.h:
+ plugins/python/regress: add tests for approval plugin
+ [31bd830a36fa]
+
+ * MANIFEST, plugins/python/Makefile.in,
+ plugins/python/python_plugin_approval.c,
+ plugins/python/python_plugin_approval_multi.inc,
+ plugins/python/python_plugin_common.c,
+ plugins/python/python_plugin_common.h,
+ plugins/python/sudo_python_module.c:
+ plugins/python: add python approval plugin wrapper
+ [489ef35ac957]
+
+ * MANIFEST, plugins/python/Makefile.in,
+ plugins/python/example_approval_plugin.py:
+ plugins/python: add python approval plugin example
+ [4ed865e04c0a]
+
+2020-02-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/regress/sudoers/test23.in,
+ plugins/sudoers/regress/sudoers/test23.json.ok,
+ plugins/sudoers/regress/sudoers/test23.ldif.ok,
+ plugins/sudoers/regress/sudoers/test23.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test23.out.ok,
+ plugins/sudoers/regress/sudoers/test23.sudo.ok,
+ plugins/sudoers/regress/sudoers/test23.toke.ok:
+ Add regress test for parsing Defaults lists. Currently only
+ env_check, env_delete, env_keep and log_servers are lists.
+ [dfda2dec37d3]
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in:
+ Clarify that approval close happens after auditing. Also fix a few
+ typos.
+ [8f9fb2f0b5a7]
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ include/sudo_plugin.h, plugins/sample_approval/sample_approval.c,
+ src/sudo.c:
+ Add open and close functions to the approval plugin API. We need a
+ close function to be able to to free memory allocated for errstr.
+ Unlike the other plugins, the close function is called immediately
+ after the plugin's check or show_version function. The plugin does
+ not remain open until the command completes.
+ [6611bafc8ace]
+
+ * plugins/audit_json/audit_json.c:
+ Use unique function names to avoid confusion with front-end
+ functions. Also add a missing sudo_debug_enter() after debug
+ registration.
+ [b127b0997ecb]
+
+ * scripts/log2cl.pl:
+ Use Text::Wrap instead of perl's built-in format function. This
+ still breaks log filename incorrectly but is a step in the right
+ direction.
+ [2184fe794ecb]
+
+ * Makefile.in, scripts/log2cl.pl:
+ Avoid changing directory when generating the ChangeLog file.
+ Instead, pass the repo path to either hg or log2cl.pl
+ [736e90c9fe6d]
+
+2020-02-10 Robert Manner <robert.manner@balabit.com>
+
+ * src/sudo.c:
+ src/sudo.c: call audit plugin close when result is a wait status
+ [0bfe6bc588a3]
+
+ * Makefile.in:
+ Makefile.in: fix install target for out of source build
+
+ The scriptdir contained a path relative to where the target was
+ started. The scripts are called like "$scriptdir/script_name" which
+ is fine with relative path as well, until the current directory is
+ not changed. But things like cd $srcdir && $scriptdir/script_name
+ fails (if building in separate build directory).
+ [7c0958b47925]
+
+ * doc/sudo_plugin_python.man.in, doc/sudo_plugin_python.mdoc.in:
+ doc/sudo_plugin_python: document python audit plugin support
+ [2a2f6227bae0]
+
+ * doc/sudo_plugin_python.man.in, doc/sudo_plugin_python.mdoc.in:
+ doc/sudo_plugin_python: document returning error string
+ [cf32faa3805f]
+
+ * doc/sudo_plugin_python.man.in, doc/sudo_plugin_python.mdoc.in:
+ doc/sudo_plugin_python: update python manual for constant -> enum
+ changes
+ [e2cd8737978c]
+
+2020-02-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/regress/iolog_path/check_iolog_path.c,
+ lib/util/mksiglist.c, lib/util/mksigname.c,
+ lib/util/regress/fnmatch/fnm_test.c,
+ lib/util/regress/getdelim/getdelim_test.c,
+ lib/util/regress/glob/globtest.c,
+ lib/util/regress/parse_gids/parse_gids_test.c,
+ lib/util/regress/progname/progname_test.c,
+ lib/util/regress/sudo_parseln/parseln_test.c, logsrvd/logsrvd.c,
+ logsrvd/sendlog.c, plugins/group_file/plugin_test.c,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/logging.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/env_match/check_env_pattern.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/tsdump.c, plugins/sudoers/visudo.c, src/exec.c,
+ src/exec_monitor.c, src/exec_nopty.c, src/exec_pty.c,
+ src/parse_args.c, src/regress/noexec/check_noexec.c:
+ Use EXIT_SUCCESS and EXIT_FAILURE more consistently.
+ [1b78154a35f3]
+
+ * src/parse_args.c, src/sudo.c, src/sudo.h:
+ Mark main sudo usage() function __noreturn__. This splits the usage
+ printing out into display_usage().
+ [400d23c2a6f1]
+
+ * include/sudo_json.h, lib/util/json.c, lib/util/util.exp.in,
+ plugins/sudoers/cvtsudoers_json.c:
+ Use json functions from libsudo_util in cvtsudoers.
+ [c4316ce76fe6]
+
+2020-02-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sample_approval/sample_approval.c:
+ Check localtime() return value; coverity CID 208156
+ [e2697b46f7e2]
+
+ * plugins/audit_json/audit_json.c:
+ Check fseeko() return value; coverity CID 207993
+ [3abd610ae63b]
+
+ * logsrvd/sendlog.c, logsrvd/sendlog.h:
+ Make restart and elapsed members of the closure structs not
+ pointers. Fixes coverity CID 207992
+ [2dbace19cb6a]
+
+ * lib/iolog/iolog_fileio.c:
+ Check return value of sudo_lock_file(); coverity CID 207991
+ [e2862d70dea8]
+
+ * logsrvd/logsrvd.c:
+ Only keepalive if accept() succeeded; coverity CID 207990
+ [0c35e46495a2]
+
+2020-02-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, Makefile.in, doc/Makefile.in, examples/Makefile.in,
+ generate_test_coverage.sh, include/Makefile.in,
+ lib/iolog/Makefile.in, lib/logsrv/Makefile.in, lib/util/Makefile.in,
+ lib/zlib/Makefile.in, log2cl.pl, logsrvd/Makefile.in, mkdep.pl,
+ mkinstalldirs, mkpkg, plugins/audit_json/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/python/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sample_approval/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in, pp,
+ scripts/generate_test_coverage.sh, scripts/log2cl.pl,
+ scripts/mkdep.pl, scripts/mkinstalldirs, scripts/mkpkg, scripts/pp,
+ src/Makefile.in:
+ Move some scripts from the top level src dir to a scripts dir.
+ [0be8e958cbc2]
+
+ * MANIFEST, plugins/sample_approval/Makefile.in,
+ plugins/sample_approval/sample_approval.c,
+ plugins/sample_approval/sample_approval.exp:
+ Add sample approval plugin that simply tests for "business hours"
+ [8005b14fd0c7]
+
+ * Makefile.in, configure, configure.ac:
+ Add sample approval plugin that simply tests for "business hours"
+ [9d7370fea2c3]
+
+ * src/load_plugins.c:
+ Refactor code to alloc and insert a new plugin_container. The only
+ outlier is the policy plugin which is not part of a list since there
+ can only be a single policy plugin.
+ [610c6e01eb0b]
+
+ * plugins/audit_json/audit_json.c:
+ Tech audit_json about approval plugin accept/reject
+ [b1e568bacd87]
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ include/sudo_plugin.h, src/load_plugins.c, src/sudo.c,
+ src/sudo_plugin_int.h:
+ Add an approval plugin type that runs after the policy plugin. The
+ basic idea is that the approval plugin adds an additional layer of
+ policy. There can be multiple approval plugins.
+ [2b57fac1ad0b]
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in:
+ plugin documentation fixes: o whitespace cleanup o show_version
+ doesn't have an errstr argument o document runas_user and
+ runas_group in command_info[] o add missing .El at before start of
+ audit section
+ [73cb9ca71ef7]
+
+2020-02-06 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/sudo_python_module.c:
+ plugins/python/sudo_python_module.c: fix options_as_dict if no equal
+ sign
+
+ The intented behaviour was that those get skipped, but the
+ PyList_GetItem sets the interpreter into error state, so python has
+ raised exception.
+ [4f99dd186eb9]
+
+ * plugins/python/regress/check_python_examples.c, plugins/python/regre
+ ss/testdata/check_example_audit_plugin_receives_accept.stdout, plugi
+ ns/python/regress/testdata/check_example_audit_plugin_receives_error
+ .stdout, plugins/python/regress/testdata/check_example_audit_plugin_
+ receives_reject.stdout, plugins/python/regress/testdata/check_exampl
+ e_audit_plugin_version_display.stdout, plugins/python/regress/testda
+ ta/check_example_audit_plugin_workflow_multiple.stderr, plugins/pyth
+ on/regress/testdata/check_example_audit_plugin_workflow_multiple.std
+ out:
+ plugins/python/regress/check_python_examples: add audit_plugin tests
+ [fcc483a569ff]
+
+ * plugins/python/python_plugin_common.c,
+ plugins/python/python_plugin_common.h,
+ plugins/python/python_plugin_io.c,
+ plugins/python/python_plugin_policy.c:
+ plugins/python/python_plugin_common: close can get custom arguments
+
+ For the audit plugin. Ensure we do not fail if
+ plugin_ctx->py_instance is NULL (because plugin init has failed).
+ [dd1c0be3d8e7]
+
+ * plugins/python/example_group_plugin.py,
+ plugins/python/example_io_plugin.py,
+ plugins/python/example_policy_plugin.py, plugins/python/regress/test
+ data/check_example_io_plugin_fails_with_python_backtrace.stdout:
+ plugins/python/example_*.py: document returning error string
+ [ee55ef4a3cb6]
+
+ * plugins/python/example_conversation.py,
+ plugins/python/example_debugging.py,
+ plugins/python/example_group_plugin.py,
+ plugins/python/example_io_plugin.py,
+ plugins/python/example_policy_plugin.py, plugins/python/regress/test
+ data/check_example_debugging_c_calls@info.log, plugins/python/regres
+ s/testdata/check_example_debugging_plugin@info.log, plugins/python/r
+ egress/testdata/check_example_io_plugin_fails_with_python_backtrace.
+ stdout:
+ plugins/python/example*.py: pep8 fixes (mainly line too long)
+ [56b15859cc9a]
+
+2020-02-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/audit_json/audit_json.exp:
+ Exported symbol is audit_json
+ [a39e9cc1047b]
+
+ * doc/sudo_plugin_python.man.in, doc/sudo_plugin_python.mdoc.in:
+ Silence lint warning.
+ [fbba7f8dc3ef]
+
+ * plugins/sudoers/policy.c:
+ Add runas_user and runas_group (if set) to command_info for audit
+ plugin. Otherwise, the audit plugin has to look up the runas name
+ and group by user or group ID.
+ [711731384693]
+
+ * src/tgetpass.c:
+ Only enable pwfeedback when reading password from /dev/tty. This
+ effectively disables pwfeedback when the -S or -A options are used.
+ [71da469aab20]
+
+2020-02-05 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/regress/check_python_examples.c:
+ plugins/python/regress: load/unload module for each testcase
+
+ so they can start from clean state. (My problem was optional
+ argument tests has destroyed the callbacks.)
+ [ab90adbb9328]
+
+ * plugins/python/python_plugin_common.c,
+ plugins/python/python_plugin_common.h,
+ plugins/python/python_plugin_group.c,
+ plugins/python/python_plugin_io.c,
+ plugins/python/python_plugin_policy.c,
+ plugins/python/sudo_python_module.c,
+ plugins/python/sudo_python_module.h:
+ plugins/python: add support for callback errstr arguments
+
+ Plugins can raise a sudo.PluginError exception to add context
+ message for the failure.
+
+ The callback's errstr gets filled up with the specified message.
+ But, as sudo expects a string constant (will not free the string),
+ we store it in the plugin context at least until next callback
+ invocation.
+ [240bf4c627f0]
+
+ * plugins/python/regress/check_python_examples.c,
+ plugins/python/regress/plugin_errorstr.py:
+ plugins/python/regress: add test for callback error msg return
+ [44a71a20f94c]
+
+ * plugins/python/python_plugin_io.c,
+ plugins/python/python_plugin_policy.c:
+ plugins/python_plugin_io,policy: fix version display in verbose mode
+
+ Unfortunately the test did not catch this mistake, because it only
+ searches that "Python policy plugin API version" string is present
+ and does not check the version.
+ [7da28d01063f]
+
+2020-02-04 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/example_conversation.py,
+ plugins/python/example_debugging.py,
+ plugins/python/example_group_plugin.py,
+ plugins/python/example_io_plugin.py,
+ plugins/python/example_policy_plugin.py, plugins/python/pyhelpers.c,
+ plugins/python/pyhelpers.h, plugins/python/python_plugin_common.c, p
+ lugins/python/regress/testdata/check_example_debugging_c_calls@diag.
+ log, plugins/python/regress/testdata/check_example_debugging_c_calls
+ @info.log, plugins/python/regress/testdata/check_example_group_plugi
+ n_is_able_to_debug.log, plugins/python/sudo_python_module.c:
+ plugins/python/sudo_python_module.c: use IntEnums instead of
+ constants
+
+ It is a bit more code, but it is more "pythonic" and easier to debug
+ as the enum values also know their names.
+
+ It is also an API break, eg. sudo.RC_OK becomes sudo.RC.OK as
+ sudo.RC will be the "type" of the enum, but I guess that is
+ acceptable before the initial release.
+ [2a0845428e2b]
+
+2020-02-03 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/python_plugin_policy.c:
+ plugins/python/python_plugin_policy: add missing debug return
+ [2bf4cc35de9c]
+
+2020-02-03 Laszlo Orban <laszlo.orban@quest.com>
+
+ * logsrvd/sendlog.c:
+ fixed compiler error when sudo is configured without --enable-
+ openssl
+ [fb19fb96c41d]
+
+2020-02-03 Robert Manner <robert.manner@balabit.com>
+
+ * MANIFEST, plugins/python/Makefile.in,
+ plugins/python/python_plugin_audit.c,
+ plugins/python/python_plugin_audit_multi.inc,
+ plugins/python/sudo_python_module.c:
+ plugins/python: add python audit plugin wrapper
+ [92bf3ccbd35d]
+
+ * MANIFEST, plugins/python/Makefile.in,
+ plugins/python/example_audit_plugin.py:
+ plugins/python: add example python audit plugin
+ [15abd19f6fdb]
+
+2020-02-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_plugin.man.in:
+ Regenerate .man.in files from .mdoc.in
+ [6d04628b3bbb]
+
+ * doc/sudo_plugin.mdoc.in:
+ Update documentation for setbase when the given base is NULL.
+ [03054c46d322]
+
+ * plugins/sudoers/iolog_client.c, src/sudo.c:
+ For plugin events, set the sudo event base for setbase(NULL). This
+ makes it possible for a plugin to change the event base to a local
+ one and then reset it back to its original value.
+ [f95ab1a5fd5a]
+
+2020-02-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog_client.c:
+ Don't display "error in event loop" on loop break reading
+ ServerHello. We should already have displayed a more useful error
+ message. Otherwise, we can get two "error in event loop" warnings if
+ the TLS handshake fails (in addition to other error messages).
+ [c42b8158ab36]
+
+2020-01-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/iolog_client.c,
+ plugins/sudoers/iolog_plugin.h:
+ Read ServerHello message synchronously before the command is
+ executed. Otherwise, the command could be run before the TLS
+ handshake completes.
+ [4dab1676ae41]
+
+2020-01-31 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/pyhelpers.c, plugins/python/pyhelpers.h,
+ plugins/python/python_convmessage.c:
+ plugins/python/pyhelpers: add helpers for attribute handling
+
+ to simplify code a bit.
+ [c3eb52c88a04]
+
+2020-01-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_plugin.mdoc.in:
+ Document audit plugin in the sudo_plugin manual.
+ [e2aab376bae1]
+
+ * include/sudo_plugin.h, plugins/audit_json/audit_json.c, src/sudo.c:
+ Change audit close arguments to a type and value. That way we can
+ distinguish between different error types.
+ [37abbe9f39b5]
+
+ * MANIFEST, Makefile.in, configure, configure.ac, m4/sudo.m4,
+ pathnames.h.in, plugins/audit_json/Makefile.in,
+ plugins/audit_json/audit_json.c, plugins/audit_json/audit_json.exp:
+ Example audit plugin that writes JSON output to a log file.
+ [295d9d1a1209]
+
+ * plugins/python/python_plugin_io.c,
+ plugins/python/python_plugin_io_multi.inc,
+ plugins/python/python_plugin_policy.c,
+ plugins/python/regress/check_python_examples.c:
+ Adapt python plugin to new plugin API changes
+ [974e76db3a3a]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/policy.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Pass back a failure or error string to the front end. The
+ audit_failure() function now stores the failure string. This will
+ allow an audit plugin to log the reason if the user's request is a
+ rejected.
+ [5bb4e000a7ec]
+
+ * doc/sudo_plugin.mdoc.in, include/sudo_plugin.h, src/exec_pty.c,
+ src/load_plugins.c, src/parse_args.c, src/sudo.c, src/sudo.h,
+ src/sudo_plugin_int.h:
+ Define a new plugin type that receives accept and reject messages.
+ This can be used to implement logging-only plugins. The plugin
+ functions now take an errstr argument that can be used to return an
+ error string to be logged on failure or error.
+ [361aab49325f]
+
+ * MANIFEST, config.h.in, configure, configure.ac, include/sudo_rand.h,
+ lib/util/arc4random.c, lib/util/arc4random_buf.c:
+ Add tests for arc4random_buf() and an implementation for those
+ without.
+ [e89dabfd5a41]
+
+ * MANIFEST, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/util.exp.in, lib/util/uuid.c:
+ Add code to generate universally unique identifiers. We create type
+ 4, variant 1 uuids (random).
+ [22aff362662e]
+
+ * MANIFEST, include/sudo_json.h, lib/util/Makefile.in,
+ lib/util/json.c, lib/util/util.exp.in:
+ Add a simple API for writing JSON records. To be used by the
+ upcoming JSON audit module.
+ [734b29194a82]
+
+2020-01-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Sudo 1.8.31 changes.
+ [3d12f4cb4d9f]
+
+ * src/tgetpass.c:
+ Fix a buffer overflow when pwfeedback is enabled and input is a not
+ a tty. In getln() if the user enters ^U (erase line) and the
+ write(2) fails, the remaining buffer size is reset but the current
+ pointer is not. While here, fix an incorrect break for erase when
+ write(2) fails. Also disable pwfeedback when input is not a tty as
+ it cannot work. CVE-2019-18634 Credit: Joe Vennix from Apple
+ Information Security.
+ [4830bdf1a683]
+
+2020-01-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.c:
+ Fix warning about unresolved host name with "sudo -l -h hostname".
+ The resolve_host() function returns 0 on success, not bool.
+ [9af5bb6e4036]
+
+ * configure, configure.ac:
+ Check for presence of fseeko() regardless of utmp type.
+ [d0c254ba8311]
+
+ * plugins/python/regress/check_python_examples.c:
+ Fix typo in a test: python_policy->close not python_io->close
+ [34d8631cc501]
+
+ * lib/util/getentropy.c:
+ Allow getentropy.c to compile when MAP_ANON is unavailable.
+ [d707e07f1a9c]
+
+ * MANIFEST, lib/util/Makefile.in, lib/util/arc4random.c,
+ lib/util/arc4random.h:
+ Remove multi-thread support from arc4random. Sudo is not multi-
+ threaded so we don't need the added complexity.
+ [77c1795e0aaa]
+
+2020-01-28 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/sudo_python_module.c:
+ plugins/sudo_python_module: Fix double free in sudo.options_as_dict
+ function
+
+ PyArg_ParseTuple sets the py_config_tuple pointer, but it does not
+ increment the reference count, so by decrementing, we end up freeing
+ the argument passed in.
+ [511aeb75a905]
+
+ * plugins/python/example_io_plugin.py, plugins/python/regress/testdata
+ /check_example_io_plugin_fails_with_python_backtrace.stdout:
+ plugins/python/example_io_plugin: close the file at destroy
+
+ to avoid warning of debug python build.
+ [6730352ab2d8]
+
+2020-01-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/arc4random.h, lib/util/getentropy.c:
+ Backed out changeset 9dce3ebb2c37 MAP_SGI_ANYADDR cannot be used in
+ place of MAP_ANON
+ [b261d200435a]
+
+2020-01-28 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/Makefile.in,
+ plugins/python/regress/check_python_examples.c,
+ plugins/python/regress/testhelpers.c,
+ plugins/python/regress/testhelpers.h:
+ plugins/python: memleak fixes in test
+
+ The main problem was that string array objects were constructed
+ differently:
+ - if constructed by the test, then the elements were constant
+ - if constructed by the plugin, then the elements were allocated
+
+ Modified it so that now each array contains allocated strings so
+ they can be handled similarly. For freeing, I have used the
+ str_array_free function from the plugin, so I have linked its object
+ into the test runner.
+
+ Happy path is now free of "definitely lost" memleaks, so the test
+ can be used for valgrind.
+ [657ffd948be5]
+
+2020-01-28 Laszlo Orban <laszlo.orban@quest.com>
+
+ * logsrvd/sendlog.c, logsrvd/sendlog.h:
+ Refactor sudo_sendlog in order to be able to send one I/O log
+ multiple times in parallel (for testing purposes)
+ [c9afea455ab6]
+
+2020-01-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/arc4random.h, lib/util/getentropy.c:
+ Fix compilation on IRIX; Bug #915 IRIX lacks MAP_ANON (and
+ MAP_ANONYMOUS) but we can use the IRIX-specific flag MAP_SGI_ANYADDR
+ instead. From Kazuo Kuroi
+ [9dce3ebb2c37]
+
+2020-01-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/check.c:
+ Fix crash in sudo 1.8.30 when suspending sudo at the password
+ prompt. The closure pointer in sudo_conv_callback was being filled
+ in with a struct getpass_closure ** instead of a struct
+ getpass_closure *. The bug was introduced in the fix for Bug #910;
+ previously the closure variable was a struct getpass_closure, not a
+ pointer. Fix from Michael Norton; Bug #914.
+ [011b6a7663ef]
+
+2020-01-24 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/pyhelpers.c, plugins/python/pyhelpers.h,
+ plugins/python/python_plugin_common.c,
+ plugins/python/python_plugin_common.h,
+ plugins/python/python_plugin_group.c,
+ plugins/python/python_plugin_io.c,
+ plugins/python/python_plugin_policy.c:
+ plugins/python: use separate python interpreter for each plugin
+
+ On each plugin initialization we create a separate python
+ interpreter which gets stored in the plugin_ctx. The main
+ interpreter is stored in py_ctx and is used for creating more
+ interpreters (if more plugins get loaded) and final python
+ deinitialization.
+
+ The "traceback" module import and the ImportBlocker initialization
+ was moved, because it has to happen inside the plugin specific
+ interpreters.
+ [eb9308e5eacb]
+
+ * plugins/python/regress/check_python_examples.c,
+ plugins/python/regress/plugin_conflict.py, plugins/python/regress/te
+ stdata/check_python_plugins_do_not_affect_each_other.stdout:
+ plugins/python/regress: add a failing textcase about python plugins
+ affect each other
+
+ Since python plugins are run inside the same interpreter, they
+ affect each other's state, which would be better to avoid.
+ [1628425d608c]
+
+2020-01-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in:
+ Document new tls_verify setting.
+ [3e4bc6e4d301]
+
+ * config.h.in, configure, configure.ac:
+ Use AC_CHECK_DECLS when checking for SSL_CTX_set_min_proto_version
+ Also use AC_CHECK_FUNCS to check for the other OpenSSL functions
+ [f3e36090a31e]
+
+2020-01-23 Robert Manner <robert.manner@balabit.com>
+
+ * doc/sudo_plugin_python.man.in, doc/sudo_plugin_python.mdoc.in:
+ doc/sudo_plugin_python: update doc about the multiple I/O plugin
+ loading
+ [08e7c479954b]
+
+ * plugins/python/Makefile.in:
+ plugins/python/Makefile.in: update autogenerated header dependencies
+ [54c0c7f11046]
+
+ * plugins/python/pyhelpers.c, plugins/python/pyhelpers.h,
+ plugins/python/python_plugin_common.c,
+ plugins/python/regress/check_python_examples.c, plugins/python/regre
+ ss/testdata/check_example_io_plugin_command_log_multiple.stderr,
+ plugins/python/sudo_python_module.c:
+ plugins/python/pyhelpers: have a default sudo_printf function
+
+ Adapted the default sudo_printf from sudoers plugin to be able to
+ print errors before plugin open() gets called. (This is used by the
+ multiple io plugin loading to display error for too much plugin
+ load.)
+
+ Since this makes us always have a sudo_log, I have removed the logic
+ about whether it is available or not.
+ [fdd4842b3ba2]
+
+ * src/load_plugins.c:
+ src/load_plugins.c: plugins can supply a clone function
+
+ if they want to support getting loaded multiple times.
+ [33ff0027f686]
+
+2020-01-23 Laszlo Orban <laszlo.orban@quest.com>
+
+ * examples/sudo_logsrvd.conf, include/log_server.pb-c.h,
+ lib/logsrv/log_server.pb-c.c, lib/logsrv/log_server.proto,
+ logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c,
+ plugins/sudoers/iolog_client.c:
+ logserver option to disable certificate verification on server side
+ and server authentication on client side
+ [9b171f3af727]
+
+2020-01-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/load_plugins.c:
+ Refactor code to allocate and fill struct plugin_container. This
+ will help avoid duplicate code in the audit and approval plugins.
+ [8ad9ba987131]
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, examples/sudo_logsrvd.conf:
+ Document TCP keepalive options in the manual pages.
+ [7afe9293b503]
+
+ * doc/CONTRIBUTORS:
+ Add proper diacritical to Róbert's name.
+ [9ca9ea59cdd4]
+
+2020-01-22 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/regress/check_python_examples.c, plugins/python/regre
+ ss/testdata/check_example_io_plugin_command_log_multiple.stderr, plu
+ gins/python/regress/testdata/check_example_io_plugin_command_log_mul
+ tiple.stdout, plugins/python/regress/testdata/check_example_io_plugi
+ n_command_log_multiple1.stored, plugins/python/regress/testdata/chec
+ k_example_io_plugin_command_log_multiple2.stored,
+ plugins/python/regress/testhelpers.c,
+ plugins/python/regress/testhelpers.h:
+ plugins/python/regress: add a testcase for multiple io plugin
+ loading
+
+ to verify 2 python plugins can work next to each other.
+ [916dd4f44bcf]
+
+2020-01-22 Laszlo Orban <laszlo.orban@quest.com>
+
+ * include/log_server.pb-c.h, lib/logsrv/log_server.pb-c.c,
+ lib/logsrv/log_server.proto, logsrvd/logsrvd.c, logsrvd/sendlog.c,
+ plugins/sudoers/iolog_client.c:
+ Rename tls_checkpeer to tls_reqcert in ServerHello message
+ [b69630f1f5b4]
+
+2020-01-22 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/python_baseplugin.c,
+ plugins/python/python_convmessage.c:
+ plugins/python: fix return value typo for the error case
+ [a7088391d8fb]
+
+2020-01-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * etc/sudo.pp, examples/Makefile.in, examples/sudo.conf.in:
+ Install a default sudo.conf file.
+ [e2b4613cced9]
+
+ * aclocal.m4, autogen.sh, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, logsrvd/logsrvd.c, logsrvd/sendlog.c,
+ plugins/sudoers/iolog_client.c:
+ Add support for building on OpenSSL 1.0.2. This adds compatibility
+ defines for some OpenSSL 1.1.x functions.
+ [17e50378c8ee]
+
+2020-01-21 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/python_plugin_io.c,
+ plugins/python/python_plugin_io_multi.inc:
+ plugins/python/plugin_io: enable loading of multiple io plugins
+
+ Separate sudo io plugin symbols are created which stores wrapper
+ functions adding the context of which python plugin the callback is
+ about.
+
+ These sudo io plugin "slots" get generated with macros by the
+ preprocessor.
+
+ This makes sudo support loading multiple python IO plugins like
+ this: (note the differences in the symbol names)
+
+ Plugin python_io python_plugin.so ModulePath=...
+ ClassName=SudoIOPlugin1 Plugin python_io1 python_plugin.so
+ ModulePath=... ClassName=SudoIOPlugin2 Plugin python_io2
+ python_plugin.so ModulePath=... ClassName=SudoIOPlugin3
+ [cb45052d227a]
+
+2020-01-21 Laszlo Orban <laszlo.orban@quest.com>
+
+ * plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_client.c,
+ plugins/sudoers/iolog_plugin.h, plugins/sudoers/policy.c:
+ sudoers: disable SO_KEEPALIVE socket option based on
+ log_server_disable_keepalive flag in sudoers
+ [ad48ee6fbcb7]
+
+ * examples/sudo_logsrvd.conf, logsrvd/logsrvd.c, logsrvd/logsrvd.h,
+ logsrvd/logsrvd_conf.c:
+ logserver: enable/disable SO_KEEPALIVE socket option based on
+ tcp_keepalive configuration option in sudo_logsrvd.conf
+ [c0d919468e95]
+
+2020-01-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/hostcheck.h:
+ No need to export the validate_hostname() symbol. We don't export
+ symbols in convenience libraries, only installed DSOs.
+ [f26897793700]
+
+ * lib/iolog/hostcheck.c:
+ Fix a few pointer signedness warnings on Linux.
+ [6a4f68430e69]
+
+ * include/sudo_compat.h, lib/iolog/hostcheck.c, logsrvd/logsrvd.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_client.c,
+ plugins/sudoers/iolog_plugin.h, src/net_ifs.c:
+ Store the server host name and IP in client_closure_fill(). Also
+ check for getpeername() and inet_ntop() failure.
+ [22df6ff5fcaf]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/sendlog.c,
+ logsrvd/sendlog.h, plugins/sudoers/iolog_client.c,
+ plugins/sudoers/iolog_plugin.h:
+ Fix handling of SSL_ERROR_WANT_{READ,WRITE} during normal I/O. If we
+ get SSL_ERROR_WANT_WRITE during SSL_read(), we need to resume the
+ SSL_read(), not call SSL_write() as we were doing. Likewise for
+ SSL_ERROR_WANT_READ received from SSL_write(). This introduces a
+ flag so we call the proper callback even when the I/O direction
+ doesn't match the read/write calls.
+ [7162125ad7b7]
+
+ * lib/util/Makefile.in:
+ Add siglist.c and signame.c as dependencies for depend target. Fixes
+ running "make depend" in lib/util dir when siglist.c or signame.c
+ are not already present.
+ [9d7aa4107136]
+
+ * Makefile.in, doc/Makefile.in, examples/Makefile.in,
+ include/Makefile.in, lib/iolog/Makefile.in, lib/logsrv/Makefile.in,
+ lib/util/Makefile.in, lib/zlib/Makefile.in, logsrvd/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/python/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/Makefile.in:
+ Add abs_top_srcdir and abs_top_builddir and use them. Configure
+ provides absolution versions of srcdir, builddir, top_srcdir and
+ top_builddir. We can use these instead of calling pwd.
+ [597ba26af997]
+
+2020-01-20 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/Makefile.in:
+ plugins/python/Makefile.in: remove path prefix from examples to make
+ install target work
+ [ba31bde08e17]
+
+2020-01-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/iolog/Makefile.in:
+ Rebuild dependencies after hostcheck.c include changes.
+ [3a4e808e5038]
+
+2020-01-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/hostcheck.h, lib/iolog/hostcheck.c, logsrvd/logsrvd.c,
+ plugins/sudoers/iolog_client.c:
+ Add debugging statements to certificate checks.
+ [81f813c8c1f1]
+
+ * MANIFEST, lib/iolog/Makefile.in, lib/iolog/hostcheck.c,
+ plugins/sudoers/iolog.c:
+ Portability fixes and correct path to hostcheck.h in MANIFEST.
+ Include sys/socket.h for getpeername(). Link with -lnsl on Solaris
+ to get inet_pton().
+ [060371a21669]
+
+ * lib/iolog/Makefile.in, lib/logsrv/Makefile.in, lib/util/Makefile.in,
+ lib/zlib/Makefile.in, logsrvd/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/python/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/Makefile.in:
+ Using "libtool --clean" to remove regular files is slow. We only
+ need to use libtool's clean mode to remove files created by libtool.
+ [510af2b052c6]
+
+2020-01-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .gitignore, .hgignore:
+ Add examples/sudo.conf to ignore files.
+ [9eb86d1b8661]
+
+ * doc/sudo.conf.mdoc.in, examples/sudo.conf.in:
+ Remove whitespace at the end of the line in example sudo.conf
+ [88b0ae1f8a18]
+
+ * doc/sudo_plugin_python.mdoc.in:
+ Fix mdoc lint warnings by removing .Pp before and after .Ss.
+ [e59218682d7f]
+
+2020-01-17 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/regress/check_python_examples.c,
+ plugins/python/regress/iohelpers.c,
+ plugins/python/regress/iohelpers.h,
+ plugins/python/regress/testhelpers.c,
+ plugins/python/regress/testhelpers.h:
+ plugins/python/regress: add missing license texts
+ [b0e4b41b2834]
+
+2020-01-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd.c:
+ Fix TLS accept when SSL_accept() returns SSL_ERROR_WANT_WRITE. We
+ need to switch from SUDO_EV_READ to SUDO_EV_WRITE for this case.
+ [71ada9bfa056]
+
+ * logsrvd/sendlog.c, plugins/sudoers/iolog_client.c,
+ plugins/sudoers/iolog_plugin.h:
+ Fix TLS connect when SSL_connect returns SSL_ERROR_WANT_READ. We
+ need to switch from SUDO_EV_WRITE to SUDO_EV_READ for this case.
+ Also make the tls connect events private to tls_timed_connect() with
+ their own closure. There is no need to store them in the client
+ closure.
+ [afda37d1dd26]
+
+ * logsrvd/iolog_writer.c:
+ Store submit time in struct iolog_info. Fixes missing time stamp in
+ remote I/O log info file.
+ [dcd1dfa00646]
+
+ * src/sudo_edit.c:
+ Treat EROFS (like EACCES) as a non-fatal error in dir_is_writable().
+ Fixes sudoedit on macOS 10.15 and above where the root file system
+ is mounted read-only. See https://support.apple.com/en-us/HT210650.
+ From Dan Villiom Podlaski Christiansen. Bug #913
+ [cc636a1af1b6]
+
+2020-01-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/event.c, plugins/sudoers/iolog_client.c:
+ Really fix flushing of data in client_close(). Now that we call
+ fmt_exit_message() from client_close() we do not need to try to
+ determine whether the read or write events were pending in the old
+ base.
+
+ We can't tell anyway because the active flag in the event was
+ cleared when the old sudo event base was destroyed. It is correct to
+ enable both the read and write events after formatting the
+ ExitMessage.
+ [c59e77060c37]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/iolog_client.c,
+ plugins/sudoers/iolog_path_escapes.c:
+ Use SUDOERS_DEBUG_* not SUDO_DEBUG_* in debug_decl() for the sudoers
+ plugin.
+ [2d0c049e689e]
+
+ * src/sudo.c, src/sudo_plugin_int.h:
+ Wrap calls to plugin event callbacks to use the plugin's debug
+ instance. Otherwise, the debug output in a plugin's event callback
+ will go to the sudo debug file, not sudoers.
+ [02e227cfc715]
+
+ * lib/util/regress/strsig/strsig_test.c:
+ FreeBSD is missing SIGLWP (aka SIGTHR) in sys_signame[]. Don't test
+ SIGLWP on FreeBSD where it is reserved for the thread library and is
+ not listed in sys_signame[].
+ [95cbafc79b4d]
+
+ * configure, configure.ac:
+ We want to use DT_RUNPATH in preference to DT_RPATH in ELF binaries.
+ Otherwise, LD_LIBRARY_PATH does not work when running the tests. The
+ GNU linker's --enable-new-dtags can be used to do this. We don't do
+ this on NetBSD where RPATH already supports LD_LIBRARY_PATH.
+ [2c6c9a348d81]
+
+2020-01-15 Laszlo Orban <laszlo.orban@quest.com>
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/iolog_client.c:
+ do server identity validation in iolog plugin
+ [b1bec55bbed6]
+
+ * logsrvd/Makefile.in, logsrvd/logsrvd.c, logsrvd/logsrvd.h:
+ do client identity validation in logserver
+ [e415409dfe0b]
+
+ * MANIFEST, include/hostcheck.h, lib/iolog/Makefile.in,
+ lib/iolog/hostcheck.c:
+ implement host validation for the audit server SSL certificates
+ [7f48e57bece2]
+
+2020-01-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers_debug.c:
+ Fix reference counting when both sudoers policy and I/O log are
+ loaded. If both sudoers policy and I/O log plugins are loaded,
+ debug_files will be empty when the I/O plugin is initialized. This
+ changes the logic to always increase the reference count if the
+ instance is valid.
+ [18adfeb3727b]
+
+ * src/load_plugins.c:
+ Fix handling of duplicate policy and I/O plugins. The warning
+ message said the later I/O plugin was ignored but it actually
+ overwrote the existing one instead. The first registered plugin of
+ the same name now is used, as was intended. Specifying more than one
+ policy plugin is no longer a fatal error; this allows the admin to
+ fix the situation.
+ [dde476072346]
+
+2020-01-14 Robert Manner <robert.manner@balabit.com>
+
+ * aclocal.m4, configure, configure.ac,
+ plugins/python/regress/check_python_examples.c,
+ plugins/python/regress/testhelpers.c,
+ plugins/python/regress/testhelpers.h,
+ plugins/python/sudo_python_debug.h:
+ plugins/python: various portability improvements
+ [d6aa5e2585ef]
+
+ * plugins/python/example_conversation.py,
+ plugins/python/example_io_plugin.py, plugins/python/regress/testdata
+ /check_example_conversation_plugin_reason_log_with_suspend.stdout, p
+ lugins/python/regress/testdata/check_example_io_plugin_command_log.s
+ tored, plugins/python/regress/testdata/check_example_io_plugin_fails
+ _with_python_backtrace.stdout:
+ plugins/python/example_{io,conversation}: avoid printing signal
+ number
+
+ They are platform dependant, so their test would fail on some
+ platforms. While we could create separate plugin for the tests, I
+ like the idea that the examples are ensured to be working.
+
+ I believe this is a good compromise for being able to auto update
+ the test cases.
+ [7b46d305e7d9]
+
+ * plugins/python/Makefile.in,
+ plugins/python/regress/check_python_examples.c:
+ plugins/python/regress: load the python plugin dynamically
+
+ instead of linking with it.
+ [084c61e7d565]
+
+2020-01-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sudo_edit.c:
+ For sudoedit_checkdir consider a user-owner directory to be
+ writable. The non-faccessat() code already did this so this just
+ brings the faccessat() path into alignment. Bug #912
+ [91a1a9c0ba40]
+
+2020-01-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/CONTRIBUTORS:
+ Add newline before list of artwork authors.
+ [1be0fe5f7d7a]
+
+ * doc/LICENSE:
+ Update copyright year.
+ [f4ef4c1990af]
+
+2020-01-10 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/example_policy_plugin.py:
+ plugins/python/example_policy_plugin.py: extend user env changing
+ example
+
+ Make the demonstration extend the environment with a new variable.
+ Easier to read, and makes the testing able to check for that it is
+ working.
+ [77c09cc38298]
+
+ * generate_test_coverage.sh:
+ generate_test_coverage.sh: example script to ease test coverage
+ generation
+
+ Uses lcov and genhtml to generate test coverage. It is meant to be
+ run in a clean directory. Extra configure options can be added as
+ script arguments.
+
+ Example execution:
+
+ mkdir build cd build ../generate_test_coverage.sh --enable-python
+ [a52c480639aa]
+
+2020-01-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/logging.c:
+ Remove MAXSYSLOGTRIES, it is no longer used.
+ [dbd274fd8330]
+
+2020-01-09 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/python_plugin_common.c,
+ plugins/python/python_plugin_policy.c:
+ plugins/python/python_plugin_policy: fix validate() call
+
+ When calling validate() python function, TypeError exception was
+ thrown ("argument list must be a tuple"), because the call does not
+ have arguments, and python does not accept empty tuple for
+ execution. NULL must be used instead, which was handled as argument
+ construction failure previously.
+ [5ac3c2acee9b]
+
+ * plugins/python/example_policy_plugin.py:
+ plugins/python/example_policy_plugin.py: make allowed_commands
+ ordered
+
+ Storing them as "tuple" instead of "set", so they have a fix order.
+ This makes the output of the list() example stable. ("set" is
+ printed out in random order)
+ [470ccf46a088]
+
+ * plugins/python/example_io_plugin.py,
+ plugins/python/example_policy_plugin.py,
+ plugins/python/python_plugin_common.c,
+ plugins/python/python_plugin_io.c,
+ plugins/python/python_plugin_policy.c:
+ plugins/python: fix confusing version display
+
+ IO/Group/Policy Python API version is displayed instead of sudo
+ version, because that is not very meaningful in this context.
+
+ They are only displayed in verbose mode.
+
+ Example plugins express it more concrete that they are displaying
+ their version, not the API version.
+ [af9d969231a9]
+
+2020-01-08 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/example_conversation.py:
+ plugins/python/example_conversation.py: make log path configurable
+
+ Similarly to IO plugin example. (It is easier to test it this way.)
+ [6526a842ee21]
+
+2020-01-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sudo.c:
+ Iterate over io_plugins list in the iolog_* wrappers. Moving the
+ iteration into the wrapper functions simplifies the calling code.
+ [1e803fb8fd1f]
+
+ * src/sudo.c:
+ policy_plugin is global, no need to pass it to policy_* functions.
+ [676c85f87b3c]
+
+ * configure, configure.ac:
+ If --enable-openssl or --enable-gcrypt is given a path, append to
+ LDFLAGS. Previously we appended the path to SUDOERS_LDFLAGS but now
+ that we use OpenSSL in the log server, LDFLAGS is the correct one to
+ use.
+ [8b30cffe500f]
+
+ * doc/CONTRIBUTORS:
+ Add Robert Manner
+ [fe8bb27dcff3]
+
+2020-01-07 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/example_io_plugin.py:
+ plugins/python/example_io_plugin.py: fix backtrace during destructor
+
+ If the plugin fails to open the file for writing, constructor will
+ raise an exception and exit before creating the "_log" member
+ variable. So the destructor will also raise a backtrace. (Which
+ python ignores, but dumps out to stderr.)
+ [09cfa2edb38c]
+
+ * plugins/python/python_plugin_common.c:
+ plugins/python/python_plugin_common: raise debug level for module
+ import
+ [b261d22e3c2e]
+
+ * plugins/python/regress/testdata/check_example_conversation_plugin_re
+ ason_log_with_suspend.conversation, plugins/python/regress/testdata/
+ check_example_conversation_plugin_reason_log_with_suspend.stderr, pl
+ ugins/python/regress/testdata/check_example_conversation_plugin_reas
+ on_log_with_suspend.stdout, plugins/python/regress/testdata/check_ex
+ ample_conversation_plugin_reason_log_with_suspend.stored, plugins/py
+ thon/regress/testdata/check_example_conversation_plugin_reason_log_w
+ ithout_suspend.conversation, plugins/python/regress/testdata/check_e
+ xample_conversation_plugin_reason_log_without_suspend.stderr, plugin
+ s/python/regress/testdata/check_example_conversation_plugin_reason_l
+ og_without_suspend.stdout, plugins/python/regress/testdata/check_exa
+ mple_conversation_plugin_reason_log_without_suspend.stored, plugins/
+ python/regress/testdata/check_example_conversation_plugin_user_inter
+ rupts.conv, plugins/python/regress/testdata/check_example_conversati
+ on_plugin_user_interrupts.conversation, plugins/python/regress/testd
+ ata/check_example_conversation_plugin_user_interrupts.stderr, plugin
+ s/python/regress/testdata/check_example_conversation_plugin_user_int
+ errupts.stdout, plugins/python/regress/testdata/check_example_debugg
+ ing_c_calls@diag.log, plugins/python/regress/testdata/check_example_
+ debugging_c_calls@info.log, plugins/python/regress/testdata/check_ex
+ ample_debugging_load@diag.log, plugins/python/regress/testdata/check
+ _example_debugging_plugin@err.log, plugins/python/regress/testdata/c
+ heck_example_debugging_plugin@info.log, plugins/python/regress/testd
+ ata/check_example_debugging_py_calls@diag.log, plugins/python/regres
+ s/testdata/check_example_debugging_py_calls@info.log, plugins/python
+ /regress/testdata/check_example_debugging_sudo_cb@info.log, plugins/
+ python/regress/testdata/check_example_group_plugin_is_able_to_debug.
+ log, plugins/python/regress/testdata/check_example_io_plugin_command
+ _log.stderr, plugins/python/regress/testdata/check_example_io_plugin
+ _command_log.stdout, plugins/python/regress/testdata/check_example_i
+ o_plugin_command_log.stored, plugins/python/regress/testdata/check_e
+ xample_io_plugin_failed_to_start_command.stderr, plugins/python/regr
+ ess/testdata/check_example_io_plugin_failed_to_start_command.stdout,
+ plugins/python/regress/testdata/check_example_io_plugin_failed_to_st
+ art_command.stored, plugins/python/regress/testdata/check_example_io
+ _plugin_fails_with_python_backtrace.stderr, plugins/python/regress/t
+ estdata/check_example_io_plugin_fails_with_python_backtrace.stdout,
+ p
+ lugins/python/regress/testdata/check_example_io_plugin_version_displ
+ ay.stderr, plugins/python/regress/testdata/check_example_io_plugin_v
+ ersion_display.stdout, plugins/python/regress/testdata/check_example
+ _io_plugin_version_display.stored, plugins/python/regress/testdata/c
+ heck_example_policy_plugin_accepted_execution.stderr, plugins/python
+ /regress/testdata/check_example_policy_plugin_accepted_execution.std
+ out, plugins/python/regress/testdata/check_example_policy_plugin_den
+ ied_execution.stderr, plugins/python/regress/testdata/check_example_
+ policy_plugin_denied_execution.stdout, plugins/python/regress/testda
+ ta/check_example_policy_plugin_failed_execution.stderr, plugins/pyth
+ on/regress/testdata/check_example_policy_plugin_failed_execution.std
+ out, plugins/python/regress/testdata/check_example_policy_plugin_lis
+ t.stderr, plugins/python/regress/testdata/check_example_policy_plugi
+ n_list.stdout, plugins/python/regress/testdata/check_example_policy_
+ plugin_validate_invalidate.log, plugins/python/regress/testdata/chec
+ k_example_policy_plugin_version_display.stderr, plugins/python/regre
+ ss/testdata/check_example_policy_plugin_version_display.stdout, plug
+ ins/python/regress/testdata/check_loading_fails_missing_classname.st
+ derr, plugins/python/regress/testdata/check_loading_fails_missing_cl
+ assname.stdout, plugins/python/regress/testdata/check_loading_fails_
+ missing_path.stderr, plugins/python/regress/testdata/check_loading_f
+ ails_missing_path.stdout, plugins/python/regress/testdata/check_load
+ ing_fails_not_owned_by_root.stderr, plugins/python/regress/testdata/
+ check_loading_fails_not_owned_by_root.stdout, plugins/python/regress
+ /testdata/check_loading_fails_wrong_classname.stderr, plugins/python
+ /regress/testdata/check_loading_fails_wrong_classname.stdout, plugin
+ s/python/regress/testdata/check_loading_fails_wrong_path.stderr, plu
+ gins/python/regress/testdata/check_loading_fails_wrong_path.stdout:
+ plugins/python/regress/testdata: generated data for the pyplugin
+ tests
+ [cec6c9036644]
+
+ * plugins/python/example_debugging.py:
+ plugins/python/example_debugging: fix typo in comment
+ [38de8ea0b0e9]
+
+2020-01-06 Laszlo Orban <laszlo.orban@quest.com>
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/iolog_client.c,
+ plugins/sudoers/iolog_plugin.h:
+ save a pointer to the currently connected audit server in the
+ closure object
+ [f1c14c43ab40]
+
+2020-01-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/timestamp.c:
+ Sanity check size when converting the first record to TS_LOCKEXCL
+ Coverity CID 206591
+ [5b94873c4051]
+
+ * include/sudo_iolog.h, lib/iolog/iolog_fileio.c:
+ Fix coverity CID 206586. Potential use after free calling
+ gzstrerror() after gzclose().
+ [4bcba58004c8]
+
+ * plugins/sudoers/cvtsudoers.c:
+ Use canonical pattern when freeing a tail queue. Avoids some
+ coverity false positives when using TAILQ_FOREACH_SAFE to free the
+ tail queue.
+ [9019d7ad9958]
+
+2020-01-03 Robert Manner <robert.manner@balabit.com>
+
+ * MANIFEST, plugins/python/Makefile.in,
+ plugins/python/regress/check_python_examples.c,
+ plugins/python/regress/iohelpers.c,
+ plugins/python/regress/iohelpers.h,
+ plugins/python/regress/testdata/sudo.conf.developer_mode,
+ plugins/python/regress/testdata/sudo.conf.normal_mode,
+ plugins/python/regress/testhelpers.c,
+ plugins/python/regress/testhelpers.h:
+ plugins/python/regress: adds tests for python plugin feature and
+ examples
+ [7ab4daed9558]
+
+2020-01-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog_client.c:
+ Avoid potential NULL deref in tls_timed_connect() error path.
+ Coverity CID 206396
+ [730687307b24]
+
+ * logsrvd/sendlog.c:
+ Check for sudo_ev_add() failure; Coverity CID 206395 206397
+ [7008560eac95]
+
+2020-01-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in, examples/sudo.conf.in:
+ Update sample sudo.conf with all supported settings. The deprecated
+ "max_groups" setting is not documented.
+ [e17f7bf95578]
+
+ * doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in, examples/sudo.conf.in,
+ lib/util/regress/sudo_conf/test1.in,
+ lib/util/regress/sudo_parseln/test1.in:
+ Remove POD-style C<> markup (typewriter font) from sudo.conf
+ [b69d4743c860]
+
+ * MANIFEST, configure, configure.ac, examples/Makefile.in,
+ examples/sudo.conf, examples/sudo.conf.in:
+ Substitute plugin dir into examples/sudo.conf
+ [8c481a21c098]
+
+2020-01-02 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/sudoers/sudoers_debug.c:
+ plugins/sudoers/sudoers_debug.c: fix harmless debug deregistration
+ warning
+
+ If the debug sudoers subsystem is not registered, because it does
+ not get any file names to deal with (TAILQ_EMPTY(debug_files)),
+ deregistration of the subsystem outputs a warning:
+
+ sudo: sudo_debug_deregister_v1: invalid instance ID -1, max -1
+
+ This patch prevents that by only increasing the refcount if the
+ debug_instance was registered successfully.
+ [939042599498]
+
+ * plugins/python/Makefile.in:
+ plugins/python/Makefile.in: fix the install path of examples
+
+ Examples are installed by default to "docdir", which refers to
+ PACKAGE_TARNAME variable which was empty for the python plugin
+ Makefile.in
+
+ So the examples were installed to '.../share/doc/examples' instead
+ of '.../share/doc/sudo/examples'. This also made them be skipped
+ from the package.
+
+ Also the install target now depends on install-doc so the examples
+ gets installed also (similarly as other examples).
+ [e4c07404a3fc]
+
+ * doc/sudo_plugin_python.man.in, doc/sudo_plugin_python.mdoc.in:
+ doc/sudo_plugin_python: indent code examples for easier readability
+ [c91ee22bfc83]
+
+ * doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in:
+ doc/sudo.conf: document developer_mode option
+ [127215dca183]
+
+2019-12-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/UPGRADE:
+ fix typo in previous
+ [3031418fba2b]
+
+ * Makefile.in:
+ In update-pot match *.c not *c.
+ [77a1139fef99]
+
+ * NEWS, doc/UPGRADE:
+ Changes in sudo 1.8.30
+ [dfaac62074f4]
+
+2019-12-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Makefile.in:
+ Add check for up to date def_data.[ch] in check-dist target.
+ [ffaf150e76a5]
+
+2019-12-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/limits.c:
+ Use 64-bit resource limits on AIX.
+ [b8b76c47c8a7]
+
+ * src/limits.c:
+ When restoring old resource limits, try to recover if we receive
+ EINVAL. On NetBSD, setrlimit(2) can return EINVAL if the new soft
+ limit is lower than the current resource usage. This can be a
+ problem when restoring the old stack limit if sudo has raised it.
+ [50bdbdbea1b7]
+
+ * src/limits.c:
+ Sudo doesn't require such a large stack.
+ [f93eb9e0c105]
+
+ * plugins/sudoers/Makefile.in:
+ Restore check for readable /etc/sudoers in pre-install target. If
+ there is no installed sudoers there is nothing to check...
+ [99e65bc54052]
+
+ * config.h.in, configure, configure.ac:
+ Enable OpenBSD extensions on NetBSD to get reallocarray(3)
+ prototype.
+ [e303dca0c1cb]
+
+ * include/sudo_event.h:
+ Add forward declaration of struct timeval for deprecated APIs.
+ [e41bdbbbc067]
+
+ * lib/util/sig2str.c, lib/util/str2sig.c:
+ Fix compilation on systems with SIGRTMIN/SIGRTMAX but not
+ _SC_RTSIG_MAX.
+ [8e40c62e00f8]
+
+ * include/sudo_compat.h:
+ Older systems may not support WCONTINUED.
+ [730bede52ff0]
+
+ * plugins/sudoers/logging.c:
+ Support systems that have nl_langinfo(3) but not the CODESET define.
+ Fixes compilation on old NetBSD versions.
+ [03e7cff93172]
+
+ * plugins/sudoers/starttime.c:
+ Fix a typo; HAVE_KINFO_PROC2_NETBSD not HAVE_KINFO_PROC2_NETBSD2
+ [0c46a062f888]
+
+2019-12-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, Makefile.in, configure, configure.ac,
+ etc/init.d/aix.sh.in, etc/init.d/hpux.sh.in,
+ etc/init.d/sudo.conf.in, etc/sudo.pp, init.d/aix.sh.in,
+ init.d/hpux.sh.in, init.d/sudo.conf.in, src/Makefile.in, sudo.pp:
+ Move init.d and sudo.pp to the etc dir.
+ [81c9cbbc8ea9]
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, lib/util/cfmakeraw.c:
+ Add cfmakeraw() for systems without it.
+ [48f48eaf2a68]
+
+ * MANIFEST:
+ Remove indent.pro from MANIFEST
+ [2b6a24282b8c]
+
+ * .gitignore, .hgignore:
+ Add uncrustify.files to ignore file.
+ [056b0df738a9]
+
+ * doc/sudo_plugin_python.man.in, doc/sudo_plugin_python.mdoc.in:
+ Substitute @prefix@ in for the example paths. We can't use
+ @exampledir@ here since it contains Makefile variables.
+ [1744e2bcc813]
+
+2019-12-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_debug.h, lib/iolog/iolog_fileio.c,
+ lib/iolog/iolog_path.c, lib/iolog/iolog_util.c, lib/util/aix.c,
+ lib/util/digest.c, lib/util/digest_gcrypt.c,
+ lib/util/digest_openssl.c, lib/util/event.c, lib/util/event_poll.c,
+ lib/util/event_select.c, lib/util/gettime.c,
+ lib/util/getusershell.c, lib/util/gidlist.c, lib/util/host_port.c,
+ lib/util/key_val.c, lib/util/lbuf.c, lib/util/locking.c,
+ lib/util/logfac.c, lib/util/logpri.c, lib/util/mkdir_parents.c,
+ lib/util/parseln.c, lib/util/secure_path.c, lib/util/setgroups.c,
+ lib/util/strsplit.c, lib/util/strtobool.c, lib/util/strtoid.c,
+ lib/util/strtomode.c, lib/util/sudo_conf.c, lib/util/term.c,
+ lib/util/ttyname_dev.c, lib/util/ttysize.c, logsrvd/eventlog.c,
+ logsrvd/iolog_writer.c, logsrvd/logsrv_util.c, logsrvd/logsrvd.c,
+ logsrvd/logsrvd_conf.c, logsrvd/sendlog.c,
+ plugins/python/python_plugin_common.c,
+ plugins/python/sudo_python_debug.c, plugins/sudoers/alias.c,
+ plugins/sudoers/audit.c, plugins/sudoers/auth/afs.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/base64.c, plugins/sudoers/boottime.c,
+ plugins/sudoers/bsm_audit.c, plugins/sudoers/check.c,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/digestname.c, plugins/sudoers/editor.c,
+ plugins/sudoers/env.c, plugins/sudoers/env_pattern.c,
+ plugins/sudoers/file.c, plugins/sudoers/filedigest.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/gc.c, plugins/sudoers/gentime.c,
+ plugins/sudoers/getspwuid.c, plugins/sudoers/goodpath.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/hexchar.c,
+ plugins/sudoers/interfaces.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_client.c,
+ plugins/sudoers/iolog_path_escapes.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/ldap_conf.c, plugins/sudoers/ldap_util.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/locale.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logwrap.c,
+ plugins/sudoers/match.c, plugins/sudoers/match_addr.c,
+ plugins/sudoers/match_command.c, plugins/sudoers/match_digest.c,
+ plugins/sudoers/parse.c, plugins/sudoers/parse_ldif.c,
+ plugins/sudoers/policy.c, plugins/sudoers/prompt.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/rcstr.c, plugins/sudoers/redblack.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/starttime.c, plugins/sudoers/strlist.c,
+ plugins/sudoers/stubs.c, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers_debug.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timeout.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/tsdump.c,
+ plugins/sudoers/visudo.c, src/exec.c, src/exec_common.c,
+ src/exec_nopty.c, src/exec_pty.c, src/get_pty.c, src/hooks.c,
+ src/limits.c, src/load_plugins.c, src/net_ifs.c, src/parse_args.c,
+ src/preserve_fds.c, src/selinux.c, src/sesh.c, src/signal.c,
+ src/solaris.c, src/sudo.c, src/sudo_edit.c, src/tgetpass.c,
+ src/ttyname.c, src/utmp.c:
+ debug_decl and debug_decl_vars now require a semicolon at the end.
+ [c05890653007]
+
+2019-12-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, doc/Makefile.in, doc/sudo_plugin_python.man.in,
+ doc/sudo_plugin_python.mdoc.in:
+ Add sudo_plugin_python manual page. Based on markdown docs from
+ Robert Manner.
+ [65f2af21832d]
+
+2019-12-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.c, src/limits.c:
+ Output the name of the limit when warning about setrlimit or
+ getrlimit. From Kimmo Suominen.
+ [92ed66b5cc1f]
+
+2019-12-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * aclocal.m4, config.h.in, configure:
+ regen
+ [81961af46679]
+
+ * MANIFEST:
+ Add python module files to MANIFEST
+ [f223a19117bb]
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in:
+ Update SUDO_CONV_REPL_MAX in docs.
+ [120970879b36]
+
+ * Makefile.in:
+ Remove uncrustify.files in clean target
+ [ba843b8f2e80]
+
+2019-12-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Makefile.in, etc/uncrustify-small.cfg, etc/uncrustify.cfg,
+ indent.pro:
+ Add uncrustify config file for new sudo code style.
+ [7c3b3f733134]
+
+ * include/sudo_plugin.h:
+ Bump SUDO_CONV_REPL_MAX from 255 to 1023
+ [9127fb27eb55]
+
+ * lib/util/digest_gcrypt.c, plugins/sudoers/auth/passwd.c,
+ plugins/sudoers/auth/secureware.c:
+ Minor style cleanups. Remove extraneous break after return
+ statement. Convert two old K&R function declarations.
+ [19f8b7a3d2d1]
+
+2019-12-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/selinux.c:
+ Save/restore the raw form of the file context in case mctrans is not
+ available.
+ [786a04ba33ab]
+
+2019-12-10 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/python_plugin_common.c:
+ plugins/python: make group plugin able to debug
+
+ It does not get the debug settings, so it looks them up through
+ sudo_conf.
+ [fe4dbf8345b6]
+
+ * include/sudo_conf.h, lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_conf/test1.in,
+ lib/util/regress/sudo_conf/test1.out.ok,
+ lib/util/regress/sudo_conf/test2.out.ok,
+ lib/util/regress/sudo_conf/test3.out.ok,
+ lib/util/regress/sudo_conf/test4.out.ok,
+ lib/util/regress/sudo_conf/test5.out.ok,
+ lib/util/regress/sudo_conf/test6.out.ok,
+ lib/util/regress/sudo_conf/test7.out.ok,
+ lib/util/regress/sudo_conf/test8.err.ok,
+ lib/util/regress/sudo_conf/test8.in,
+ lib/util/regress/sudo_conf/test8.out.ok, lib/util/sudo_conf.c,
+ lib/util/util.exp.in, plugins/sudoers/group_plugin.c,
+ src/load_plugins.c:
+ src/load_plugins, plugins/sudoers: added developer_mode sudo.conf
+ option
+
+ It can be used to disable the enforcement that a plugin (shared
+ object or an imported python module) must be owned by root and not
+ modifiable by others. This can make plugin development easier.
+ [a9f86943d30c]
+
+2019-12-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, config.h.in, configure, configure.ac, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in, include/sudo_compat.h, lib/util/Makefile.in,
+ lib/util/getusershell.c, mkdep.pl, plugins/sudoers/check.c,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Add runas_check_shell flag to require a runas user to have a valid
+ shell. Not enabled by default.
+ [9e7936e0ccfe]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/sudoers.c:
+ Add a new flag "allow_unknown_runas_id" to control matching of
+ unknown IDs. Previous, sudo would always allow unknown user or group
+ IDs if the sudoers entry permitted it. This included the "ALL"
+ alias. With this change, the admin must explicitly enable support
+ for unknown IDs.
+ [ebdbb5c7f60b]
+
+2019-12-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/term.c:
+ Use cfmakeraw() in sudo_term_raw() instead of doing it manually.
+ [b8ff5f81399f]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/iolog_client.c,
+ plugins/sudoers/iolog_plugin.h:
+ Fix event loop called via I/O log close function. We need to set
+ events that were pending in the old base in the new one. Fixes
+ sending the final I/O log data and the ExitMessage to the server.
+ [dcba4ce2196c]
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ include/sudo_plugin.h, src/sudo.c:
+ Replace timeleft with pending in sudo plugin event API.
+ [5f49af23af38]
+
+ * plugins/sudoers/sudoreplay.c:
+ Use sudo_ev_pending() instead of the deprecated sudo_ev_timeleft().
+ [c6cce5275f1e]
+
+ * include/sudo_event.h, lib/util/event.c, lib/util/util.exp.in:
+ Add sudo_ev_pending(), used to check whether an event is pending.
+ [edcea66bda32]
+
+ * plugins/sudoers/Makefile.in:
+ Add TLS libs when linking check_iolog_plugin
+ [d84a5f5c6bc1]
+
+2019-12-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog_client.c:
+ Remove extraneous newlines in some sudo_warnx() calls.
+ [d3dbf0f93372]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document log_server_cabundle, log_server_peer_cert and
+ log_server_peer_key
+ [edea4d048221]
+
+ * Merge pull request #16 from laczau/master
+
+ Proper handling of certificate chain file
+ [44939e511321]
+
+2019-12-06 Laszlo Orban <laszlo.orban@quest.com>
+
+ * logsrvd/logsrvd.c:
+ cert files can contain the full chain of trust, so load all certs in
+ every case for verification
+ [ca26bb970ef5]
+
+2019-12-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in:
+ Sync init_session() prototype with sudo_plugin.h and fix a typo.
+ [1501cdfa8e76]
+
+2019-12-05 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/example_conversation.py,
+ plugins/python/example_debugging.py:
+ plugins/python: example plugin demonstrating conversation and debug
+ API
+ [e487d2240607]
+
+ * include/sudo_debug.h, lib/util/sudo_debug.c, lib/util/util.exp.in:
+ lib/util/sudo_debug.c: add a function for querying if debugging is
+ needed
+
+ for a level. Rationale: this way we can avoid computing details for
+ the log which will not happen at all if the computation is slow.
+ [d636c26d192d]
+
+2019-12-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/check.c:
+ Only update the time stamp entry after the approval function has
+ succeeded. Bug #910
+ [9b2022e6f11d]
+
+2019-12-04 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/sudo_python_debug.c,
+ plugins/python/sudo_python_debug.h:
+ plugins/python: add sudo debug helpers
+ [1d48021e86ad]
+
+2019-12-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Merge pull request #14 from sudo-project/tls-config-default-values
+
+ Audit Server - add default values for cert paths
+ [f30a48f8b5d5]
+
+2019-12-04 Laszlo Orban <laszlo.orban@quest.com>
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd_conf.c:
+ add default values for cert paths
+ [a76ca8a3ca9f]
+
+2019-12-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/sudo_debug.c:
+ Add reference counting to debug register/deregister. Fixes a
+ potential problem when an instance is re-registered.
+ [270e739fd0b3]
+
+ * plugins/sudoers/sudoers_debug.c:
+ Only deregister the sudoers debug instance on last close. Reference
+ count calls to sudoers_debug_register and only deregister
+ sudoers_debug_instance when refcnt reaches 0. Fixes a problem where
+ the debug system was deregistered when the sudoers policy is closed
+ even though the iolog plugin is active.
+ [2b73f3e9fc32]
+
+2019-12-02 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/python_importblocker.c:
+ plugins/python: add ImportBlocker which forbids loading unsafe
+ python modules
+
+ If non root can alter any imported python modules, he is able to run
+ anything he would like to as root user. This class is a helper to
+ avoid such situation.
+
+ This feature can be disabled with 'DeveloperMode=1' plugin option.
+ [26be6228724f]
+
+2019-11-28 Laszlo Orban <laszlo.orban@quest.com>
+
+ * plugins/sudoers/iolog_client.c, plugins/sudoers/iolog_plugin.h:
+ implement tls layer in iolog plugin
+ [c25837909952]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/policy.c:
+ process tls config options
+ [510fdfd39d71]
+
+ * plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in:
+ add audit server tls related configuration options to sudoers
+ [f4135025ff1d]
+
+ * plugins/sudoers/Makefile.in:
+ optionally link sudoers with openssl libs
+ [750f87200eab]
+
+2019-11-27 Laszlo Orban <43516882+laczau@users.noreply.github.com>
+
+ * logsrvd/logsrvd.c:
+ Merge pull request #11 from sudo-project/audit-server-tls-async
+
+ Sudo audit Server - TLS protocol update
+ [923f6d914ec5]
+
+2019-11-26 Laszlo Orban <laszlo.orban@quest.com>
+
+ * logsrvd/logsrvd.c:
+ disable timeout for the reader after ServerHello message
+ [e579450aafa1]
+
+2019-11-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd.c:
+ Exit if the first call to logsrvd_conf_read() fails. It is not fatal
+ if subsequent calls fail (due to SIGHUP) since we keep a copy of the
+ old config before installing the new one.
+ [c20866ea9d03]
+
+ * Makefile.in, plugins/sudoers/Makefile.in:
+ Add some missing files to "make clean" and "make distclean"
+ [d1b559e9e1ab]
+
+ * .gitignore, .hgignore:
+ Update .hgignore and convert to .gitignore
+ [c8b92b55e74a]
+
+2019-11-22 Laszlo Orban <laszlo.orban@quest.com>
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c:
+ use event timeout instead of socket timeout
+ [5c72d1d18aec]
+
+ * logsrvd/sendlog.c, logsrvd/sendlog.h:
+ adapt sudo sendlog (async communication, unencrypted ServerHello
+ message)
+ [0269d852f6c6]
+
+ * logsrvd/logsrvd.c, logsrvd/logsrvd.h:
+ ServerHello message is now unencrypted, TLS communication has been
+ refactored to full async
+ [d138cbe2253e]
+
+ * include/log_server.pb-c.h, lib/logsrv/log_server.pb-c.c,
+ lib/logsrv/log_server.proto, logsrvd/logsrvd.c:
+ extend ServerHello message with two fields (tls, tls_checkpeer)
+ [6d7965d29cd4]
+
+2019-11-21 Robert Manner <robert.manner@balabit.com>
+
+ * Makefile.in:
+ Makefile.in: fix calling log2cl when doing out of source build
+
+ If doing build out of source and not calling configure by absolute
+ path, $(top_srcdir) variable will contain a path relative to the
+ directory we stand in. So, after changing the current directory "cd
+ $(srcdir)", this path will point to somewhere else making the
+ install step fail.
+ [58a22fce613f]
+
+ * plugins/python/python_baseplugin.c,
+ plugins/python/python_convmessage.c,
+ plugins/python/sudo_python_module.c,
+ plugins/python/sudo_python_module.h:
+ plugins/python: add a sudo python module
+ [c512c48170ae]
+
+2019-11-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ plugins/sudoers/policy.c, src/sudo.c:
+ For plugin API 1.15 and up, always call the plugin close function.
+ Previously, it was only called when a command was run (including
+ sudoedit). Now, plugin operations list, validate, invalidate, and
+ show_version are also closed.
+ [6cdcb5624908]
+
+2019-11-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog_client.c:
+ Avoid NULL deref on an error path if calloc() fails. Coverity CID
+ 205873
+ [bad732813149]
+
+ * src/conversation.c:
+ Fix potential fd leak when converting trailing newline to cr + nl.
+ Coverity CID 205872
+ [4597abb8ee1f]
+
+ * doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ doc/sudo_logsrvd.man.in, doc/sudo_logsrvd.mdoc.in,
+ examples/sudo_logsrvd.conf:
+ Document the process of creating self-signed certificates for
+ sudo_logsrvd. Based on a document from Laszlo Orban.
+ [0be730e58f17]
+
+ * plugins/group_file/plugin_test.c:
+ Sync with argument handling in group_plugin.c
+ [937475aa2c3f]
+
+ * plugins/sudoers/group_plugin.c:
+ If a group plugin has optional arguments, NULL terminate the vector.
+ Otherwise, the plugin cannot determine the end of arguments. The
+ behavior now matches the plugin documentation.
+ [51e02f75a447]
+
+2019-11-19 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/example_group_plugin.py:
+ plugins/python: add example python group plugin
+ [9f9d7cc2d5db]
+
+ * plugins/python/example_policy_plugin.py:
+ plugins/python: add example python policy plugin
+ [6cc0d47edae0]
+
+ * plugins/python/example_io_plugin.py:
+ plugins/python: add example io python plugin
+ [d22532c34748]
+
+2019-11-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in, src/sudo.c:
+ If there is no session or terminal group ID, pass the plugin a value
+ of 0. This behavior already matches what is documented in the
+ sudo_plugin manual for "sid" but the "tcpgid" entry needed to be
+ updated.
+ [2d720153c4cf]
+
+ * plugins/sudoers/sudoers.c:
+ Don't touch the local iolog sequence file if we are logging remotely
+ [3c5dc60a9d11]
+
+ * plugins/sudoers/iolog_client.c:
+ Plug a memory leak found by leak sanitizer
+ [13aac57d0506]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/iolog_client.c,
+ plugins/sudoers/iolog_plugin.h:
+ Make a shallow copy of user_env in I/O plugin in case it is
+ reallocated. The policy plugin's session init function may
+ reallocate the user environment pointer. Fixes a use after free when
+ PAM is used.
+ [3eb35dac2743]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/policy.c:
+ Rename "log_server" in sudoers to "log_servers" to match I/O plugin.
+ [1dbe79c18760]
+
+2019-11-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/logsrvd.c:
+ Check closure->ssl for non-NULL instead of
+ logsrvd_conf_get_tls_opt(). It's a little more obvious this way and
+ ssl is only non-NULL when the tls option is enabled anyway.
+ [3436430c064b]
+
+ * logsrvd/logsrvd.c:
+ Init iolog_dir_fd and sock in connection_closure before adding to
+ list. Otherwise we could close the wrong fds in the error path.
+ [1643211f8b46]
+
+ * doc/CONTRIBUTORS:
+ Add Laszlo Orban
+ [2836214cd4b8]
+
+2019-11-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_logsrvd.conf.man.in:
+ regen
+ [4a44bfc42b4b]
+
+ * doc/sudo_logsrvd.conf.mdoc.in, examples/sudo_logsrvd.conf:
+ Change TLS example file locations to be under /etc/ssl/sudo.
+ [f4c302a3bcb9]
+
+ * doc/sudo_logsrvd.conf.mdoc.in, examples/sudo_logsrvd.conf:
+ Document sudo_logsrvd TLS configuration.
+ [97260e6acfaf]
+
+2019-11-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_event.h:
+ Include time.h for struct timespec.
+ [8bd80773d0fa]
+
+ * lib/util/util.exp.in:
+ Add sudo_ev_set_v1 to the exports file.
+ [fd6b66378e5d]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document the log_server and log_server_timeout options
+ [7d7429b73d25]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_client.c, plugins/sudoers/iolog_plugin.h,
+ plugins/sudoers/policy.c, src/exec_nopty.c, src/exec_pty.c,
+ src/sudo.c:
+ Add support for logging to the log server
+ [158a8e80faab]
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ include/sudo_event.h, include/sudo_plugin.h, lib/util/event.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/policy.c, src/Makefile.in,
+ src/exec.c, src/exec_monitor.c, src/exec_nopty.c, src/exec_pty.c,
+ src/load_plugins.c, src/preload.c, src/sudo.c, src/sudo.h,
+ src/sudo_plugin_int.h:
+ Add a plugin interface to sudo main event loop.
+ [123662f454da]
+
+ * MANIFEST, Makefile.in, configure, configure.ac,
+ include/log_server.pb-c.h, include/protobuf-c/protobuf-c.h,
+ lib/logsrv/Makefile.in, lib/logsrv/log_server.pb-c.c,
+ lib/logsrv/log_server.proto, lib/logsrv/protobuf-c.c,
+ logsrvd/Makefile.in, logsrvd/log_server.pb-c.c,
+ logsrvd/log_server.pb-c.h, logsrvd/log_server.proto,
+ logsrvd/protobuf-c/protobuf-c.c, logsrvd/protobuf-c/protobuf-c.h:
+ Move protobuf-c.c, log_server.proto, log_server.pb-c.[ch] to
+ lib/logsrv
+ [6772a775471f]
+
+ * lib/util/event.c:
+ When freeing an event base, reset ev->base to NULL for associated
+ events.
+ [7199d3967059]
+
+ * logsrvd/logsrvd_conf.c:
+ Move cb_timeout() out from under the HAVE_OPENSSL ifdef.
+ [c7fc294ce21a]
+
+ * INSTALL, config.h.in, configure, configure.ac, logsrvd/Makefile.in,
+ logsrvd/logsrvd.c:
+ LibreSSL and older OpenSSL don't support SSL_CTX_set_ciphersuites().
+ Add a configure test and skip TLS 1.3 setup if it is missing. We
+ still accept the tls_ciphers13 config setting but it will be
+ ignored.
+ [06d478442971]
+
+ * logsrvd/logsrvd.c, logsrvd/sendlog.c:
+ Minor style nits that I missed during review.
+ [7209ccc5a3cf]
+
+ * logsrvd/sendlog.c:
+ Avoid calling SSL_CTX_free() on an uninitialized pointer in an error
+ path.
+ [2df423e30773]
+
+ * Merge pull request #9 from sudo-project/audit-server-tls-support
+
+ Audit server tls support
+ [0aded6c1deec]
+
+2019-11-13 Laszlo Orban <laszlo.orban@quest.com>
+
+ * logsrvd/Makefile.in, logsrvd/sendlog.c:
+ update sudo_sendlog to support openssl tls
+ [ab4be8367862]
+
+2019-11-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/limits.c:
+ Simplify resource limit fallback logic a bit.
+ [cdab60b50079]
+
+2019-11-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/CONTRIBUTORS:
+ Add sudo logo designers
+ [94c841c8bc28]
+
+ * src/limits.c:
+ Don't set the RLIMIT_STACK soft/hard limits to unlimited. Use 8Mb
+ for soft and 64Mb for hard. Works around issues on macOS and docker.
+ See also Bug #908
+ [1d7f52c32360]
+
+ * src/tgetpass.c:
+ Restore resource limits before executing the askpass program. Linux
+ with docker seems to have issues executing a program when the stack
+ size is unlimited. Bug #908
+ [28cb58a5ac94]
+
+ * src/conversation.c:
+ Check for replies pointer being NULL just in case.
+ [7c0c4c6b001e]
+
+2019-11-11 Laszlo Orban <laszlo.orban@quest.com>
+
+ * examples/sudo_logsrvd.conf, logsrvd/logsrvd.c, logsrvd/logsrvd.h,
+ logsrvd/logsrvd_conf.c:
+ set timeout value for the socket
+ [e884292ab6c9]
+
+2019-11-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/conversation.c:
+ Convert trailing newline to carriage return + newline for tty. Does
+ not currently handle embedded newlines.
+ [ad195e045150]
+
+2019-11-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/fatal.c:
+ Only write a carriage return if output is to a tty.
+ [f605335649ea]
+
+ * lib/util/fatal.c:
+ Include a carriage return when printing warning messages. Otherwise,
+ if the command is running in a pty the output is stair-stepped.
+ [f23d4f0ed902]
+
+2019-11-08 Laszlo Orban <laszlo.orban@quest.com>
+
+ * configure, logsrvd/Makefile.in, logsrvd/logsrvd.c,
+ logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c:
+ make audit server openssl dependency optional; tls layer is compiled
+ only if sudo is built with --enable-openssl feature switch
+ [c360a34c89c0]
+
+2019-11-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/util.exp.in:
+ Add sudo_parse_host_port_v1 and sudo_pow2_roundup_v1 to exports
+ file.
+ [e8b529115871]
+
+2019-11-07 Laszlo Orban <laszlo.orban@quest.com>
+
+ * logsrvd/logsrvd.c:
+ fixed segfault when connection_closure_free() tries to remove a non-
+ existent connection object from the list
+ [4d6dd38d59f6]
+
+2019-11-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/closefrom.c:
+ Fix typo in closefrom emulation.
+ [b23a6c512d4a]
+
+ * plugins/sudoers/env.c:
+ Do not warn about a missing /etc/environment file on Linux without
+ PAM. Bug #907
+ [f85ff5ee2caf]
+
+2019-11-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/toke_util.c,
+ plugins/sudoers/visudo.c:
+ Transparently handle the "sudo sudoedit" problem. Some admin are
+ confused about how to give users sudoedit permission and many users
+ try to run sudoedit via sudo instead of directly. If the user runs
+ "sudo sudoedit" sudo will now treat it as plain "sudoedit" after
+ issuing a warning. If the admin has specified a fully-qualified path
+ for sudoedit in sudoers, sudo will treat it as just "sudoedit" and
+ match accordingly. In visudo (but not sudo), a fully-qualified path
+ for sudoedit is now treated as an error.
+ [5cdcfd9a6c33]
+
+ * logsrvd/iolog_writer.c, logsrvd/sendlog.c:
+ Rename cwd -> submitcwd to match man page.
+ [bc9ea396055a]
+
+2019-11-05 Laszlo Orban <laszlo.orban@quest.com>
+
+ * logsrvd/logsrvd.c:
+ verify server/client certs with CA certificate chain file
+ [a177af7d7bbf]
+
+2019-11-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, lib/util/Makefile.in, lib/util/host_port.c,
+ lib/util/regress/host_port/host_port_test.c:
+ Add unit test for parse_host_port and make an empty port an error.
+ [b6b895cdc010]
+
+2019-11-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/host_port.c:
+ Fill in host and port pointers on success.
+ [794368ebd367]
+
+2019-11-04 Laszlo Orban <laszlo.orban@quest.com>
+
+ * logsrvd/logsrvd.c:
+ fix copy-paste mistake
+ [2fe897c77485]
+
+2019-11-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/host_port.c, logsrvd/logsrvd_conf.c:
+ Split out code to parse host:port into a utility function.
+ [d8331e72394d]
+
+ * MANIFEST, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/roundup.c, logsrvd/logsrv_util.c, logsrvd/logsrv_util.h,
+ logsrvd/logsrvd.c, logsrvd/sendlog.c:
+ Move bufsize_roundup() -> sudo_pow2_roundup() in libsudo_util.
+ [791f5c353ef1]
+
+ * lib/iolog/Makefile.in, logsrvd/Makefile.in:
+ Add missing depend target
+ [75107bcfff3d]
+
+ * lib/iolog/Makefile.in, lib/util/Makefile.in, logsrvd/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in,
+ src/Makefile.in:
+ We haven't needed -I$(top_srcdir) for a long time.
+ [6974ea4a6c8c]
+
+ * lib/util/closefrom.c:
+ In closefrom_fallback() use the interval [OPEN_MAX, INT_MAX]. We
+ want to try closing at least OPEN_MAX fds but no more than INT_MAX.
+ On 64-bit systems it is possible for sysconf(_SC_OPEN_MAX) to return
+ a value larger than INT_MAX when the number of open files is
+ unlimited.
+ [08d6fea1c894]
+
+ * plugins/sudoers/logging.c, src/exec_monitor.c, src/selinux.c,
+ src/tgetpass.c:
+ Use dup3() instead of dup2(). This is less error prone since dup3()
+ returns an error if old == new. Sudo guarantees that fds 0-2 are
+ already open.
+ [a9ffaa8a8a55]
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, lib/util/Makefile.in, lib/util/dup3.c,
+ mkdep.pl:
+ Add dup3() emulation.
+ [7bd8864dee7e]
+
+ * plugins/sudoers/logging.c, src/exec_monitor.c, src/exec_pty.c,
+ src/tgetpass.c:
+ Open all pipes using pipe2() with O_CLOEXEC. We no longer depend on
+ calling closefrom() before exec.
+ [176ae5cf1d94]
+
+ * src/exec.c, src/tgetpass.c:
+ Call closefrom() before we change to a non-root UID. This prevents
+ another process from changing the NOFILE resource limit of the child
+ process and defeating the closefrom() call. Reported by Joe Vennix
+ from Apple Information Security.
+ [f93d52b24976]
+
+ * MANIFEST, logsrvd/Makefile.in:
+ Regenerate Makefile and sort MANIFEST
+ [24664d6c9d47]
+
+2019-11-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo.man.in, doc/sudo.mdoc.in:
+ Reference timestamp_type and timestamp_timeout in sudoers. This
+ should help users find details on how time stamp files work.
+ [d5aa7c0b404c]
+
+2019-10-31 Laszlo Orban <laszlo.orban@quest.com>
+
+ * logsrvd/logsrvd.c:
+ process tls config params in the audit server and establish TLS
+ connection accordingly
+ [33ce32c140af]
+
+2019-10-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/limits.c:
+ macOS does not allow rlim_cur to be set to RLIM_INFINITY for
+ RLIMIT_NOFILE. We need to use OPEN_MAX instead as per the macOS
+ setrlimit manual. Bug #904
+ [2a00e62eaeb0]
+
+2019-10-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Makefile.in:
+ Fix ChangeLog generation on a branch.
+ [69409e5b1179]
+
+2019-10-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * logsrvd/sendlog.c:
+ Remove unused copy of iolog_seekto().
+ [1d730d414cd9]
+
+2019-10-25 Laszlo Orban <laszlo.orban@quest.com>
+
+ * examples/sudo_logsrvd.conf, logsrvd/logsrvd.h,
+ logsrvd/logsrvd_conf.c:
+ add configuration options for TLS
+ [291a9986d6e9]
+
+2019-10-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, doc/Makefile.in, doc/sudo_logsrv.proto.man.in,
+ doc/sudo_logsrv.proto.mdoc.in, doc/sudo_logsrvd.conf.man.in,
+ doc/sudo_logsrvd.conf.mdoc.in, examples/sudo_logsrvd.conf,
+ logsrvd/iolog_writer.c:
+ Document the sudo log server protocol
+ [46de0934987c]
+
+ * include/sudo_iolog.h, lib/iolog/iolog_fileio.c,
+ logsrvd/logsrvd_conf.c, plugins/sudoers/iolog.c:
+ Read logsrvd.conf in two steps: first read, then apply if OK. This
+ fixes a problem where when logsrvd.conf was reloaded while running
+ (due to SIGHUP) and there was an error we could end up with a
+ partial config.
+ [d3244c318c5b]
+
+ * include/sudo_iolog.h, lib/iolog/iolog_util.c,
+ lib/iolog/regress/iolog_util/check_iolog_util.c,
+ logsrvd/iolog_writer.c, logsrvd/logsrv_util.c, logsrvd/sendlog.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/sudoreplay.c:
+ Add iolog_ prefix to exported functions in iolog_util.c
+ [62027c8e1abd]
+
+ * include/sudo_iolog.h, lib/iolog/iolog_fileio.c,
+ logsrvd/logsrvd_conf.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c:
+ Simplify iolog_set_user and iolog_set_group
+ [e82c5078b02c]
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, lib/util/Makefile.in, lib/util/fchmodat.c,
+ lib/util/fstatat.c, mkdep.pl:
+ Add fchmodat() and fstatat() emulation. Note that fchmodat()
+ emulation does not support AT_SYMLINK_NOFOLLOW
+ [8232c22e71c7]
+
+ * doc/sudo_logsrvd.man.in, doc/sudo_logsrvd.mdoc.in,
+ logsrvd/iolog_writer.c, logsrvd/logsrvd.c, logsrvd/logsrvd.h,
+ logsrvd/logsrvd_conf.c:
+ Clear the write bit on the timing file for completed logs. This
+ allows us to tell whether or not a log can be restarted.
+ [b2180b6ef53b]
+
+ * logsrvd/logsrvd.c:
+ Redirect std{in,out,err} to /dev/null even when given the -n option.
+ [376186a8d9cc]
+
+ * include/sudo_iolog.h, lib/iolog/iolog_fileio.c,
+ lib/iolog/iolog_path.c,
+ lib/iolog/regress/iolog_path/check_iolog_path.c,
+ lib/iolog/regress/iolog_path/data, logsrvd/iolog_writer.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_path_escapes.c,
+ plugins/sudoers/sudoers.c:
+ Simplify expand_iolog_path()
+ [4f0f85f659d1]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [e268d56da49c]
+
+ * examples/sudo_logsrvd.conf, include/sudo_iolog.h,
+ lib/iolog/iolog_fileio.c, logsrvd/Makefile.in, logsrvd/logsrvd.c,
+ logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c:
+ Make the logsrvd port and list address configurable.
+ [69d73358888d]
+
+ * Makefile.in, logsrvd/Makefile.in, logsrvd/iolog_writer.c,
+ logsrvd/logsrvd.c, logsrvd/logsrvd_conf.c, logsrvd/sendlog.c:
+ Mark logsrvd and sendlog strings for translation in the sudoers
+ domain
+ [24b1fd6250fb]
+
+ * logsrvd/Makefile.in, logsrvd/logsrvd.c, logsrvd/sendlog.c:
+ Add long option support to logsrvd and sendlog.
+ [ecb2fae83abb]
+
+ * logsrvd/iolog_writer.c, logsrvd/logsrvd.c, logsrvd/logsrvd.h:
+ Return an error to the client on error instead of dropping the
+ connection.
+ [2e40ca902100]
+
+ * examples/sudo_logsrvd.conf, logsrvd/logsrvd_conf.c:
+ Convert sudo_logsrvd.conf to ini file format
+ [91dff03d0795]
+
+ * MANIFEST, examples/sudo_logsrvd.conf, include/sudo_util.h,
+ lib/util/Makefile.in, lib/util/logfac.c, lib/util/logpri.c,
+ lib/util/util.exp.in, logsrvd/Makefile.in, logsrvd/eventlog.c,
+ logsrvd/iolog_writer.c, logsrvd/logsrvd.c, logsrvd/logsrvd.h,
+ logsrvd/logsrvd_conf.c, plugins/sudoers/defaults.c:
+ Add basic support for event logging using a sudo-style log format.
+ [eb6aa3672e6f]
+
+ * logsrvd/logsrvd.c, logsrvd/sendlog.c:
+ Add OpenBSD malloc options.
+ [a0d79af0c430]
+
+ * MANIFEST, logsrvd/Makefile.in, logsrvd/buffer.c, logsrvd/buffer.h,
+ logsrvd/iolog_writer.c, logsrvd/logsrvd.c, logsrvd/logsrvd.h,
+ logsrvd/sendlog.c, logsrvd/sendlog.h:
+ Allow messages up to 2Mb in size.
+ [af79754aaf53]
+
+ * MANIFEST, configure, configure.ac, doc/Makefile.in,
+ doc/sudo_logsrvd.conf.man.in, doc/sudo_logsrvd.conf.mdoc.in,
+ doc/sudo_logsrvd.man.in, doc/sudo_logsrvd.mdoc.in,
+ doc/sudo_sendlog.man.in, doc/sudo_sendlog.mdoc.in,
+ examples/sudo_logsrvd.conf, m4/sudo.m4:
+ Add manual pages for logsrvd and sendlog.
+ [f437259d81ae]
+
+ * include/sudo_iolog.h, lib/iolog/iolog_fileio.c,
+ logsrvd/iolog_writer.c, logsrvd/logsrvd.c:
+ Add restart support for compresses I/O logs.
+ [1191fac5ff52]
+
+ * logsrvd/sendlog.c, logsrvd/sendlog.h:
+ Fix client side of restart. Seek to the target point there too so we
+ start sending from the right place.
+ [403bf22a6dad]
+
+ * include/sudo_iolog.h, lib/iolog/iolog_util.c,
+ logsrvd/iolog_writer.c, logsrvd/sendlog.c,
+ plugins/sudoers/sudoreplay.c:
+ Move read_timing_record() into libsudo_iolog
+ [65a984f7fa7a]
+
+ * MANIFEST, lib/iolog/iolog_fileio.c, logsrvd/Makefile.in,
+ logsrvd/buffer.c, logsrvd/buffer.h, logsrvd/iolog_writer.c,
+ logsrvd/logsrv_util.c, logsrvd/logsrv_util.h, logsrvd/logsrvd.h,
+ logsrvd/sendlog.c, logsrvd/sendlog.h:
+ Rename buffer.c -> logsrv_util.c and add iolog_seekto()
+ [0ff1a6fdaecd]
+
+ * logsrvd/logsrvd.c, logsrvd/sendlog.c:
+ Fix some warnings from the clang static analyzer.
+ [95de486cfb65]
+
+ * logsrvd/sendlog.c:
+ Fix Coverity CID 204353, fd leak on error path.
+ [3519d910c777]
+
+ * logsrvd/logsrvd_conf.c:
+ Fix Coverity CID 204355, resource leak on error path.
+ [c5c50c6bae16]
+
+ * lib/iolog/iolog_fileio.c:
+ Avoid TOCTOU in iolog_mkdirs; Coverity CID 204356
+ [0c8679a731f5]
+
+ * lib/util/mkdir_parents.c:
+ Avoid TOCTOU in sudo_mkdir_parents; Coverity CID 204357
+ [e9eeae60dff2]
+
+ * logsrvd/log_server.pb-c.c, logsrvd/log_server.pb-c.h,
+ logsrvd/log_server.proto:
+ Add NumberList to InfoMessage. Also make comments fit in 80 columns
+ when formatted as a man page.
+ [fd7af0bb2477]
+
+ * configure, configure.ac, include/sudo_rand.h, logsrvd/Makefile.in,
+ logsrvd/logsrvd.c:
+ Command line option processing for logsrvd
+ [0f2248532960]
+
+ * MANIFEST, examples/sudo_logsrvd.conf, logsrvd/Makefile.in,
+ logsrvd/iolog_writer.c, logsrvd/logsrvd.c, logsrvd/logsrvd.h,
+ logsrvd/logsrvd_conf.c, pathnames.h.in:
+ Add config file support for logsrvd
+ [4e643a95c88b]
+
+ * MANIFEST, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/mkdir_parents.c, lib/util/util.exp.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/mkdir_parents.c,
+ plugins/sudoers/sudoers.h:
+ Move mkdir_parents to libsudo_util.
+ [3f540eb94282]
+
+ * MANIFEST, Makefile.in, configure, configure.ac,
+ include/sudo_iolog.h, include/sudo_util.h, lib/iolog/Makefile.in,
+ lib/iolog/iolog_fileio.c, lib/iolog/iolog_path.c,
+ lib/iolog/iolog_util.c,
+ lib/iolog/regress/iolog_path/check_iolog_path.c,
+ lib/iolog/regress/iolog_path/data,
+ lib/iolog/regress/iolog_util/check_iolog_util.c,
+ lib/util/sudo_conf.c, logsrvd/Makefile.in, logsrvd/iolog_writer.c,
+ logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c,
+ logsrvd/sendlog.c, logsrvd/sendlog.h,
+ plugins/sample/sample_plugin.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog.h, plugins/sudoers/iolog_files.h,
+ plugins/sudoers/iolog_path.c, plugins/sudoers/iolog_path_escapes.c,
+ plugins/sudoers/iolog_util.c, plugins/sudoers/iolog_util.h,
+ plugins/sudoers/policy.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/iolog_path/data,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/regress/iolog_util/check_iolog_util.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoreplay.c, src/sudo.h:
+ Refactor code in sudoers that creates I/O log files to share with
+ logsrvd.
+ [3aa1fa95650d]
+
+ * Makefile.in, include/sudo_iolog.h, lib/iolog/iolog_path.c,
+ lib/iolog/regress/iolog_path/check_iolog_path.c,
+ logsrvd/iolog_writer.c, logsrvd/logsrvd.h, logsrvd/logsrvd_conf.c,
+ plugins/sudoers/iolog_path_escapes.c, plugins/sudoers/sudoers.c:
+ Enable sudo_logsrvd.conf settings.
+ [8e7b37d1d2a9]
+
+ * include/sudo_iolog.h, lib/iolog/iolog_fileio.c,
+ lib/iolog/iolog_util.c, logsrvd/iolog_writer.c, logsrvd/logsrvd.h,
+ logsrvd/sendlog.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/sudoreplay.c:
+ Use openat(2) when opening files in the I/O log directory.
+ [1ab2e278e1d9]
+
+ * logsrvd/Makefile.in, sudo.pp:
+ Add sudo_ prefix to logsrvd and sendlog.
+ [acbaed157ae5]
+
+ * logsrvd/iolog_writer.c, logsrvd/log_server.pb-c.c,
+ logsrvd/log_server.pb-c.h, logsrvd/log_server.proto,
+ logsrvd/logsrvd.c, logsrvd/logsrvd.h, logsrvd/sendlog.c,
+ logsrvd/sendlog.h:
+ Rename ExecMessage -> AcceptMessage and add RejectMessage
+ [a080c4eb7c4b]
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, lib/util/openat.c, lib/util/unlinkat.c,
+ src/sudo_edit.c:
+ Move openat() emulation to lib/util and at unlinkat() emulation.
+ [756ace7fdf38]
+
+ * logsrvd/iolog_writer.c, logsrvd/logsrvd.c, logsrvd/sendlog.c:
+ Add debugging for logsrvd and sendlog
+ [4c86dbceb611]
+
+ * MANIFEST, doc/LICENSE, logsrvd/Makefile.in,
+ logsrvd/protobuf-c/protobuf-c.c, logsrvd/protobuf-c/protobuf-c.h:
+ Import protobuf-c source since to avoid an external dependency. The
+ files generated with protoc-c are not standalone. We need to include
+ protobuf-c.c and protobuf-c.h from the protobuf-c distribution too.
+ Building protoc-c requires a relative recent version of gcc which
+ limits its portability.
+ [0ea50a59cab7]
+
+ * logsrvd/Makefile.in, logsrvd/iolog_writer.c, logsrvd/logsrvd.c,
+ logsrvd/logsrvd.h, logsrvd/sendlog.c, logsrvd/sendlog.h:
+ Add support for restarting I/O log transfers.
+ [748e8f4f7fec]
+
+ * MANIFEST, Makefile.in, configure, configure.ac, logsrvd/Makefile.in,
+ logsrvd/iolog.h, logsrvd/iolog_reader.c, logsrvd/iolog_writer.c,
+ logsrvd/log_server.pb-c.c, logsrvd/log_server.pb-c.h,
+ logsrvd/log_server.proto, logsrvd/logsrvd.c, logsrvd/logsrvd.h,
+ logsrvd/sendlog.c, logsrvd/sendlog.h, sudo.pp:
+ Import proof of concept sudo log server.
+ [a0687ba66feb]
+
+ * MANIFEST, logsrvd/Makefile.in, logsrvd/iolog.h,
+ logsrvd/iolog_reader.c, logsrvd/iolog_writer.c, logsrvd/logsrvd.h,
+ logsrvd/sendlog.c, logsrvd/sendlog.h, mkdep.pl,
+ plugins/sudoers/Makefile.in, plugins/sudoers/iolog.h,
+ plugins/sudoers/iolog_util.c, plugins/sudoers/iolog_util.h,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/regress/iolog_util/check_iolog_util.c,
+ plugins/sudoers/sudoreplay.c:
+ Refactor I/O log code so it can be shared between sudoers and
+ logsrvd
+ [b6608769ba8a]
+
+ * lib/util/strtonum.c:
+ Avoid invalid read when minval > maxval
+ [7f1a6f992e4f]
+
+2019-10-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, plugins/sudoers/policy.c, src/sudo.c:
+ Don't pass an invalid session or process group ID to the plugin.
+ Fixes a regression in 1.8.28 when there is no terminal session
+ leader.
+ [d9c626167b3c]
+
+2019-10-22 Robert Manner <robert.manner@balabit.com>
+
+ * plugins/python/pyhelpers.c, plugins/python/pyhelpers.h,
+ plugins/python/pyhelpers_cpychecker.h,
+ plugins/python/python_plugin_common.c,
+ plugins/python/python_plugin_common.h,
+ plugins/python/python_plugin_group.c,
+ plugins/python/python_plugin_io.c,
+ plugins/python/python_plugin_policy.c:
+ plugins/python: a plugin which can load policy/io plugin written in
+ python
+ [2c7620c8052f]
+
+ * Makefile.in, configure.ac, plugins/python/Makefile.in:
+ Makefile.in, configure.ac: add python plugin build
+ [09b305e2cd54]
+
+2019-10-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [70f4543f177c]
+
+ * src/limits.c:
+ Not all systems support RLIMIT_NPROC and RLIMIT_RSS
+ [26b8e2afe755]
+
+ * doc/Makefile.in, examples/Makefile.in, include/Makefile.in,
+ lib/util/Makefile.in, lib/zlib/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in,
+ src/Makefile.in:
+ Add depend target to all Makefile.in files.
+ [0a22d80ef716]
+
+ * NEWS, configure, configure.ac, doc/UPGRADE:
+ Sudo 1.8.29
+ [736c9a5c3720]
+
+ * MANIFEST, lib/util/Makefile.in, src/Makefile.in, src/exec.c,
+ src/limits.c, src/sudo.c, src/sudo.h:
+ Set resource limits in the sudo process to unlimited. We don't want
+ sudo to be limited by the caller's resource limits. The original
+ resource limits are restore before session setup.
+ [6c3bf214caf0]
+
+2019-10-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/starttime.c, src/ttyname.c:
+ Older FreeBSD needs sys/param.h included before sys/user.h. From
+ Darren Tucker
+ [88c060df0439]
+
+ * include/sudo_util.h, lib/util/getgrouplist.c, lib/util/gidlist.c,
+ lib/util/regress/strtofoo/strtoid_test.c, lib/util/strtoid.c,
+ lib/util/util.exp.in, plugins/group_file/getgrent.c,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/match.c, plugins/sudoers/policy.c,
+ plugins/sudoers/pwutil.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/visudo.c,
+ plugins/system_group/system_group.c, src/sudo.c:
+ Rename sudo_strtoid() to sudo_strtoidx() and add simplified
+ sudo_strtoid()
+ [94a418cdbae6]
+
+2019-10-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/UPGRADE, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in,
+ doc/sudo.man.in, doc/sudo.mdoc.in, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ doc/sudoers_timestamp.man.in, doc/sudoers_timestamp.mdoc.in,
+ doc/visudo.man.in, doc/visudo.mdoc.in,
+ plugins/sudoers/cvtsudoers_json.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/policy.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/testsudoers.c, src/exec.c:
+ Refer to user-ID and group-ID instead of "user ID" and "group ID"
+ [36d7bd4ab52d]
+
+2019-10-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ sudoedit doesn't create a new PAM session so PAM umask does not
+ apply.
+ [8ae167d0ae7c]
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in, include/sudo_plugin.h,
+ plugins/sudoers/policy.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, src/exec.c, src/sudo.c, src/sudo.h:
+ Change how the umask is handled with PAM and login.conf. If the
+ umask is explicitly set in sudoers, use that value regardless of
+ what is in PAM or login.conf. If using the default umask from
+ sudoers, allow PAM or login.conf to override it. Bug #900
+ [7c0a835ac512]
+
+2019-10-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/audit.c,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/logging.c:
+ Add log_allowed and log_denied sudoers flags, defaulting to true.
+ [fb1e188a3d05]
+
+ * lib/util/Makefile.in, plugins/sudoers/Makefile.in, src/Makefile.in:
+ Enable security auditing malloc options for "make check".
+ [333632dd3134]
+
+2019-10-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Be more consistent with how we talk about sudoers Defaults settings.
+ Use "flag" not "option" when referring to boolean flags. Use
+ "setting" in place of "Defaults setting" in most places. Use "the
+ foo option" instead of "sudo's foo option" for command line options.
+ [8058378c4b35]
+
+ * plugins/sudoers/Makefile.in:
+ No need to check existing sudoers file when installing to DESTDIR
+ This check can cause problems on systems where /etc/sudoers.d is not
+ readable.
+ [2ec01e9fe408]
+
+ * lib/util/str2sig.c:
+ Inclue sudo_util.h to get sudo_strtonum() prototype.
+ [8b0b4ee28d5f]
+
+ * lib/util/str2sig.c:
+ strtonum -> sudo_strtonum
+ [4d2363678583]
+
+ * MANIFEST:
+ Add split out strtofoo tests.
+ [0cc598502faf]
+
+ * lib/util/strtonum.c:
+ Make sure we don't go past the end of the string when out of range.
+ [2b89961c524a]
+
+ * lib/util/regress/strtofoo/strtonum_test.c, lib/util/strtonum.c:
+ Fix stronum() regress test and the errno value for out of range
+ numbers.
+ [3547d022bead]
+
+ * lib/util/Makefile.in, lib/util/regress/atofoo/atofoo_test.c,
+ lib/util/regress/strtofoo/strtobool_test.c,
+ lib/util/regress/strtofoo/strtoid_test.c,
+ lib/util/regress/strtofoo/strtomode_test.c,
+ lib/util/regress/strtofoo/strtonum_test.c:
+ Split atofoo.c regress into multiple tests.
+ [75b7547e33bd]
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.8.28p1
+ [09ceaddc94f9]
+
+2019-10-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/parse.c:
+ The fix for bug #869 broke "sudo -v" when verifypw=all (the default)
+ [aac35bcd8584]
+
+2019-10-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_compat.h, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/closefrom.c, lib/util/getaddrinfo.c, lib/util/strtonum.c,
+ lib/util/sudo_conf.c, lib/util/ttysize.c,
+ plugins/sudoers/boottime.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_util.c, plugins/sudoers/ldap_conf.c,
+ plugins/sudoers/match_addr.c, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/starttime/check_starttime.c,
+ src/parse_args.c, src/sesh.c, src/sudo.c, src/ttyname.c:
+ Use sudo_strtonum() explicitly instead of via a macro.
+ [f75f786eddd5]
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h,
+ lib/util/Makefile.in, lib/util/strtoid.c, lib/util/strtonum.c,
+ lib/util/util.exp.in, mkdep.pl:
+ Always use our own strtonum and implement sudo_strtoid in terms of
+ it.
+ [94b1114ef79d]
+
+ * plugins/sudoers/pwutil.c:
+ Use errno in warning when sudo_make_*_item() fails. Previously we
+ always said "out of memory" if not ENOENT.
+ [68e5a208c242]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/parse_ldif.c,
+ plugins/sudoers/regress/cvtsudoers/test26.err.ok,
+ plugins/sudoers/regress/cvtsudoers/test26.sh:
+ Reject non-LDIF input when converting from LDIF to sudoers or JSON.
+ [2d08d4aa0e01]
+
+2019-10-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/ca.mo, plugins/sudoers/po/da.mo,
+ plugins/sudoers/po/el.mo, plugins/sudoers/po/eu.mo,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fur.mo,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hu.mo,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/lt.mo,
+ plugins/sudoers/po/nl.mo, plugins/sudoers/po/ru.mo,
+ plugins/sudoers/po/sk.mo, plugins/sudoers/po/sl.mo,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/tr.mo,
+ plugins/sudoers/po/zh_CN.mo, po/ast.mo, po/ca.mo, po/es.mo,
+ po/eu.mo, po/fi.mo, po/fur.mo, po/gl.mo, po/hr.mo, po/hu.mo,
+ po/ko.mo, po/nl.mo, po/nn.mo, po/ru.mo, po/sk.mo, po/sl.mo,
+ po/sr.mo, po/sudo.pot, po/vi.mo, po/zh_CN.mo:
+ regen
+ [362645d256b7]
+
+ * NEWS, lib/util/strtoid.c:
+ Treat an ID of -1 as invalid since that means "no change". Fixes
+ CVE-2019-14287. Found by Joe Vennix from Apple Information Security.
+ [83db8dba09e7]
+
+ * lib/util/regress/atofoo/atofoo_test.c,
+ plugins/sudoers/regress/testsudoers/test5.out.ok,
+ plugins/sudoers/regress/testsudoers/test5.sh:
+ Add sudo_strtoid() tests for -1 and range errors. Also adjust
+ testsudoers/test5 which relied upon gid -1 parsing.
+ [db06a8336c09]
+
+2019-10-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * INSTALL, configure, configure.ac:
+ Back out compiler override for now.
+ [f03f7fd7ff8b]
+
+ * configure, configure.ac:
+ Only prefer clang over gcc on BSD systems.
+ [2309baa23a00]
+
+2019-10-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Makefile.in:
+ Fix "make pvs-studio" run in a build dir
+ [a49635de3777]
+
+2019-09-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [430d45f3b461]
+
+ * NEWS:
+ Bug #898
+ [3d07895888e8]
+
+ * src/exec.c, src/exec_monitor.c, src/exec_nopty.c, src/exec_pty.c,
+ src/selinux.c, src/sudo.c, src/sudo.h:
+ Fix restoring the file context of the user's tty with SELinux. Also
+ fix broken tty labeling when running a command in a pty. Includes a
+ fix for a typo introduced in the last change set.
+ [eb3f547b08f8]
+
+ * lib/util/arc4random.c:
+ _rs_random_buf is currently unused
+ [e384fc3625e8]
+
+ * src/selinux.c:
+ Add some debugging around context setting and tty labeling Also be
+ more extact with error return values
+ [ed66480282c7]
+
+2019-09-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/sudo_debug.c:
+ Better error message when debug log file cannot be opened.
+ [09e0cdff0c49]
+
+2019-09-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgignore:
+ Ignore in-tree build directory.
+ [66577c63f097]
+
+ * configure, configure.ac:
+ Set CC before AC_USE_SYSTEM_EXTENSIONS to get our preferred
+ compiler.
+ [6a318eeffb30]
+
+2019-09-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * pp:
+ Update Polypkg to the latest version from git.
+ [68bbecc25007]
+
+ * configure, configure.ac:
+ If no mandoc or nroff is present, install mdoc format manuals. If
+ there is no installed nroff/mandoc they will need to install groff
+ or heirloom doctools to format the manual pages.
+ [6dd386c1a378]
+
+2019-09-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in, include/sudo_plugin.h:
+ Refer to number of terminal lines, not rows, for consistency.
+ [566e3e38058f]
+
+2019-09-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * INSTALL, configure, configure.ac:
+ Prefer clang over gcc. We want to use clang on systems where clang
+ is the system compiler. It is less common to have clang installed on
+ systems where gcc is the system compiler.
+ [d29d764a4938]
+
+ * INSTALL:
+ No longer need bypass_last_login on HP-UX, warnings work with clang.
+ Also add deb package names for pam and ldap devel on Linux.
+ [6aff480b1f4b]
+
+ * src/parse_args.c:
+ Silence a warning from clang about string concatenation.
+ [cadba1a4d86d]
+
+2019-09-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, doc/UPGRADE:
+ sudoedit umask fix
+ [4bfc0e393e2a]
+
+2019-09-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/event.c:
+ Fix sorting of the time-based event queue.
+ [f12e5a877c8a]
+
+ * lib/util/event.c:
+ Support default base in got_exit, got_break, loopexit, loopbreak,
+ loopcontinue
+ [da02194b5ba9]
+
+2019-09-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sudo_edit.c:
+ Create new files with the umask specified in sudoers.
+ [4d0b6152834b]
+
+2019-09-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/parse_ldif.c:
+ More case-insensitive compare for LDAP attributes and string lists.
+ Only the ALL keyword should be compared case-sensitive.
+ [87cd688b2648]
+
+2019-08-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sudo.h:
+ Enable asserts for Coverity too.
+ [b830f200a8bd]
+
+ * src/parse_args.c, src/sudo.h:
+ Add asserts() to avoid static analyzer false positives.
+ [860aca50028d]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Plug memory leak on malloc failure.
+ [1b35743703d4]
+
+ * plugins/sudoers/ldap_util.c:
+ Plug memory leak on malloc failure.
+ [c2257637d659]
+
+2019-08-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/pam.c:
+ Add sudo_pam_strerror(), like pam_strerror() but never returns NULL.
+ It also uses strerror(errno) for PAM_SYSTEM_ERR.
+ [b070d1702112]
+
+ * plugins/sudoers/auth/pam.c:
+ If pam_start() fails, display the PAM error using pam_strerror(). It
+ is legal to pass pam_strerror() a NULL handle.
+ [6403fa1479d8]
+
+2019-08-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in,
+ plugins/sudoers/sudoreplay.c:
+ If the sudoreplay ID option is a fully-qualified path, use it
+ directly. Previously, one had to use the -d option to override the
+ I/O log directory.
+ [9fddb3ffc760]
+
+ * plugins/sudoers/Makefile.in:
+ regen
+ [f70579d2972b]
+
+ * MANIFEST, doc/sudo.conf.man.in.sed:
+ Add conditional for sesh path in sudo.conf manual.
+ [93b5c6fcf8f4]
+
+2019-08-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Bug #895
+ [d69984bccd0e]
+
+ * plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/dce.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/check.c, plugins/sudoers/sudo_printf.c,
+ src/conversation.c:
+ Use the SUDO_CONV_PREFER_TTY flag during authentication. This
+ prevents the password and PAM prompts from being redirected. Bug
+ #895
+ [546082c674b7]
+
+2019-08-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * mkpkg:
+ Fix typo that prevented a missing linux audit lib from being
+ detected.
+ [b9412151615d]
+
+2019-08-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoreplay.c:
+ Use fputs(), not printf() for plain strings.
+ [b102ae1cb6da]
+
+ * NEWS:
+ Recent fixes.
+ [8249e98a05c8]
+
+ * plugins/sudoers/ldap.c:
+ Add user ID to the search filter when matching sudoUser. We already
+ support group IDs but the user ID was missing. From
+ sudo-1.8.23-ldapsearchuidfix.patch in RHEL 7.
+ [3da7b9f990be]
+
+ * plugins/sudoers/regress/sudoers/test2.json.ok,
+ plugins/sudoers/regress/sudoers/test2.toke.ok,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Fix parsing of double-quoted Defaults bindings that start with % or
+ +. From sudo-1.8.23-fix-double-quote-parsing-for-Defaults-
+ values.patch in RHEL 7.
+ [df613e67ef45]
+
+ * src/exec.c:
+ Restore core dump resource limit before the PAM session module is
+ run. Otherwise, we may override the limits set by PAM. Bug #894
+ [f35441098234]
+
+2019-08-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/sig2str.c, lib/util/str2sig.c:
+ sys_signame on macOS contains lower-cases names
+ [d7af71311b3d]
+
+ * MANIFEST, configure, configure.ac, lib/util/Makefile.in,
+ lib/util/regress/strsig/strsig_test.c:
+ Add regress tests for str2sig() and sig2str().
+ [fb73303699fb]
+
+ * lib/util/str2sig.c:
+ SIGIOT and SIGABRT are aliases on BSD systems.
+ [d35f75aba04a]
+
+ * lib/util/sig2str.c, lib/util/str2sig.c:
+ Fix handling of real-time signals.
+ [39066a5eabcb]
+
+2019-08-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ ipa_hostname fix
+ [54245ed09830]
+
+2019-08-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/file.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/ldap.c,
+ plugins/sudoers/match.c, plugins/sudoers/parse.h,
+ plugins/sudoers/sssd.c:
+ Fix special handling of ipa_hostname that was lost in sudo 1.8.24.
+ We now include the long and short hostname in sudo parser container.
+ [b4f31dbe3109]
+
+2019-08-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog_event.h:
+ Remove unused include file.
+ [0731078e72b1]
+
+2019-08-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, doc/UPGRADE:
+ Mention I/O log signal change in NEWS and UPGRADE files.
+ [ac7969640146]
+
+ * MANIFEST, NEWS, plugins/sudoers/po/ast.mo,
+ plugins/sudoers/po/ast.po:
+ Asturian translation for sudoers from translationproject.org.
+ [4f011f10129e]
+
+ * mkdep.pl:
+ Check source dir if source file is not listed in MANIFEST.
+ Previously, we just used the file name without $(srcdir).
+ [cd17ca929217]
+
+ * MANIFEST, config.h.in, configure, configure.ac, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in, include/sudo_compat.h, lib/util/Makefile.in,
+ lib/util/str2sig.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_util.c:
+ Store signal name, not number in I/O log timing file. The "SIG"
+ prefix is not used so, e.g. SIGTERM -> "TERM". This makes the I/O
+ log files portable from one system to another. Older I/O log files
+ with signal numbers can still be replayed.
+ [5652f831b715]
+
+2019-07-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/utmp.c:
+ Disable stringop-truncation false positive warnings on gcc 8.
+ Strings in struct utmp/utmpx are not guaranteed to be NUL-
+ terminated.
+ [644b97bba318]
+
+ * plugins/group_file/plugin_test.c, src/net_ifs.c:
+ Replace non-essential strncpy() calls.
+ [2377cad6e155]
+
+2019-07-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Revert version back to 1.8.28
+ [4e2deb0b4925]
+
+ * lib/util/Makefile.in:
+ Link util functions being tested directly with the test harness.
+ Otherwise we may get the version from the installed libsudo_util.so.
+ [46c833080d13]
+
+2019-07-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt.mo, plugins/sudoers/po/pt.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/zh_TW.mo,
+ plugins/sudoers/po/zh_TW.po, po/cs.mo, po/cs.po, po/da.mo, po/da.po,
+ po/de.mo, po/de.po, po/eo.mo, po/eo.po, po/fr.mo, po/fr.po,
+ po/it.mo, po/it.po, po/ja.mo, po/ja.po, po/nb.mo, po/nb.po,
+ po/pl.mo, po/pl.po, po/pt.mo, po/pt.po, po/pt_BR.mo, po/pt_BR.po,
+ po/sv.mo, po/sv.po, po/tr.mo, po/tr.po, po/uk.mo, po/uk.po,
+ po/zh_TW.mo, po/zh_TW.po:
+ Updated translations from translationproject.org
+ [a5aa41ab05cb]
+
+2019-07-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/parse.c:
+ Use strftime(3) instead of formatting struct tm by hand. Fixes a
+ warning on newer versions of gcc.
+ [4a2fdb51bbe5]
+
+ * doc/sudo.man.in, doc/sudo.mdoc.in:
+ Update error message when the password cannot be read from the
+ terminal.
+ [9b329f92e8a0]
+
+ * NEWS:
+ Fix for Bug #888
+ [d64fc43adfdd]
+
+ * plugins/sudoers/match_command.c, plugins/sudoers/match_digest.c:
+ If the command in sudoers does not exist on the file system, match
+ by name. We still want to match the command even if it doesn't exist
+ so that the NOPASSWD flag on sudoers entries with non-existant paths
+ works as expected. Bug #888.
+ [0879054870be]
+
+ * NEWS, doc/TROUBLESHOOTING, po/sudo.pot, src/tgetpass.c:
+ More verbose error message when a password is required and no
+ terminal is present. Bug #828.
+ [f15ffeffff32]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [8e0fdf8e4cd5]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document that PAM session modules are now run with the silent flag.
+ [b67b769a0532]
+
+2019-07-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.c:
+ Simpler change to retry sudo_secure_file() as root as needed.
+ [feb0c2309366]
+
+ * plugins/sudoers/sudoers.c:
+ If we are unable to stat() sudoers as non-root, try again as root.
+ By default, sudo relies soley on group permissions to read sudoers
+ to make it possible to store sudoers on NFS. However, if
+ /etc/sudoers is not accessible to non-root uids for some reason,
+ sudo will fail. Bug #880.
+ [6a50adb25f2e]
+
+2019-07-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Clarify that ttyin contains raw terminal input.
+ [eea9d33f85bd]
+
+2019-07-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Expand the description of the I/O log files.
+ [f15cefc9bbd8]
+
+ * doc/sudo.conf.mdoc.in:
+ Remove trailing whitespace.
+ [421e9f481c1d]
+
+2019-07-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in:
+ Rename PLUGINDIR -> plugindir
+ [75cc43534ee1]
+
+ * configure, configure.ac:
+ Use $libexecdir in default settings used by the documentation. The
+ web and pdf pages will substitute /usr/local/libexec for
+ $noexec_file. Also do substitution of variables using exec_prefix
+ even if we don't use them in the Makefile since the documentation
+ may reference them.
+ [b7a37b03b6db]
+
+ * doc/Makefile.in, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in:
+ Add conditional for sesh path in sudo.conf manual.
+ [ec1f8f559bad]
+
+ * configure, configure.ac:
+ Update plugindir even when --disable-shared is specified. Otherwise,
+ the default value is substituted into the Makefiles and
+ documentation which may not match --prefix. Bug #886
+ [0f6c9a4af739]
+
+2019-06-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_util.h, lib/util/fatal.c, lib/util/inet_ntop.c,
+ lib/util/regress/vsyslog/vsyslog_test.c, lib/util/sudo_debug.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/ldap_conf.c, plugins/sudoers/logging.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/timestamp.c, src/load_plugins.c, src/net_ifs.c,
+ src/sudo.c:
+ Add ssizeof macro that returns ssize_t. We can use this instead of
+ casting the result of size_t to int. Also change checks for
+ snprintf() returning <=0 to <0.
+ [da4a95a5d8ec]
+
+2019-06-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/TROUBLESHOOTING, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ sudoedit should be used for editing files instead of "sudo editor"
+ That way the user's editor config files are used by the editor.
+ [24bb1e6326ee]
+
+ * doc/TROUBLESHOOTING:
+ Move the section on HOME to be after the environment section. Also
+ strongly discourage the disabling of env_reset.
+ [7a41bddf5fde]
+
+2019-06-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/TROUBLESHOOTING:
+ Remove the Solaris last login question, add one about HOME. The PAM
+ session is opened with PAM_SILENT so last login info is not printed.
+ It is dangerous to preserve HOME from the user's environment.
+ [99be2cd98556]
+
+ * doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Use the term pseudo-terminal more consistently.
+ [129a0d2e5a33]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document why HOME should not be preserved from the user's
+ environment. Text was adapted from what is already present in the
+ UPGRADE file. Also mark set_home and always_set_home as obsolete.
+ [3cddca2f78de]
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in:
+ Refer to command line options, not flags.
+ [5caa383e1f9b]
+
+ * NEWS:
+ sync
+ [fd7e952e3e43]
+
+ * doc/TROUBLESHOOTING:
+ sudo will now prompt for a password as long as /dev/tty is
+ available.
+ [a4241d432e63]
+
+ * MANIFEST, configure, configure.ac, doc/Makefile.in,
+ doc/cvtsudoers.cat, doc/sudo.cat, doc/sudo.conf.cat,
+ doc/sudo_plugin.cat, doc/sudoers.cat, doc/sudoers.ldap.cat,
+ doc/sudoers_timestamp.cat, doc/sudoreplay.cat, doc/visudo.cat:
+ Remove .cat pages, there is no need for them in the modern world.
+ Sudo only shipped .cat pages for Irix, which lacked nroff. Irix is
+ long dead and there are multiple open source nroff options.
+ [b7a48dc22bdb]
+
+ * INSTALL, configure.ac, doc/sudoers.cat, doc/visudo.cat:
+ Make env_editor the default. It is already the default in the
+ package script.
+ [a4f0c46ef5d6]
+
+ * INSTALL, doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in:
+ Don't describe env_editor as a security hole. Users that are able to
+ edit sudoers can grant themselves permissions so the fact that
+ visudo runs the editor as root is not a security issue.
+ [627f0a96ccc9]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in:
+ Fix details of how EDITOR, VISUAL and SUDO_EDITOR are (or are not)
+ preserved. The description in the editor option was incorrect and
+ didn't mention env_keep. Reported by Sander Bos
+ [1b498d610672]
+
+ * doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in:
+ Modern visudo locks the actual sudoers file, not the sudoers.tmp
+ file. Refer to sudoers.tmp as a temporary file, not a lock file.
+ Reported by Sander Bos
+ [3a449f316304]
+
+2019-06-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.c:
+ In tty_present(), check for /dev/tty if sudo was unable to get the
+ tty name. For requiretty it is enough to check that /dev/tty is
+ available. If sudo can't get the tty from the kernel (missing
+ /proc?) that is OK.
+ [2102ffa0fa7e]
+
+ * src/tgetpass.c:
+ Don't refuse to use the tty unless /dev/tty is unavailable. We don't
+ care whether sudo was able to get the tty name from the kernel. All
+ that really matters is whether we are able to disable echo as
+ needed.
+ [a3376277883f]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Use of "they" was ambiguous.
+ [a39f42aa21ca]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Better description of secure_path. The secure_path option affects
+ the resolution of unqualified commands as well as the environment
+ that commands run with.
+ [e0534efa8271]
+
+ * doc/CONTRIBUTORS:
+ Add Sander Bos
+ [75f6f90c2f24]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Fix a few typos and awkward wording. Use the singular "they" instead
+ of he/she. Add back missing text in description of variables
+ starting with (). Based on changes from Sander Bos.
+ [d6b5068ae2ca]
+
+2019-06-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Clarify which environment variables are set based on the target
+ user.
+ [1e6ac7e5ef32]
+
+2019-06-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/Makefile.in:
+ libsudo_util depends on LT_DEP_LIBS even when building a static lib
+ [232370d6af88]
+
+ * aclocal.m4, config.h.in, configure, configure.ac,
+ lib/util/arc4random.c:
+ Solaris getentropy() requires that sys/random.h be included.
+ [f1ec0a7290a6]
+
+2019-05-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/parse.c:
+ Use the runhost for "User foo is not allowed to run sudo on bar."
+ Otherwise, if the -h option is specified sudo will print the local
+ host name instead of the host specified via -h.
+ [8e6836ff952c]
+
+2019-05-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/TROUBLESHOOTING:
+ Document that "no tty present and no askpass program specified" may
+ happen when /proc is not accessible.
+ [b551c47e55aa]
+
+2019-05-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/CONTRIBUTORS:
+ Add Sangamesh Mallayya and Michael Spradling
+ [73b3acddc973]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in, src/parse_args.c,
+ src/sudo.h, src/tgetpass.c:
+ Add -B option to ring the bell before the password prompt.
+ [b2181b069809]
+
+ * plugins/sudoers/auth/aix_auth.c:
+ Allow the user to change their password if expired on AIX. Bug #883
+ [b1def2572198]
+
+2019-05-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/aix_auth.c:
+ When using AIX auth, don't display the AIX password incorrect
+ message. Avoids a "3004-300 You entered an invalid login name or
+ password" message in addition to sudo's own "Sorry, try again"
+ message.
+ [ee606cfc3c8c]
+
+2019-05-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * mkpkg:
+ AIX packages were not being build with optimization enabled.
+ [41563464b897]
+
+2019-05-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/parse.c, plugins/sudoers/parse.h:
+ Fix a typo.
+ [6cd3fdc40b13]
+
+ * mkpkg:
+ Support using macOS SDKs from
+ /Library/Developer/CommandLineTools/SDKs
+ [98399af73e06]
+
+2019-05-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/term.c:
+ It is safe to assume _POSIX_VDISABLE is defined. The old compat
+ defines were to support pre-termios systems.
+ [82153896cede]
+
+2019-05-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/pam.c:
+ Remove second catopen() which is never called.
+ [8a3db9d71297]
+
+2019-05-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/TROUBLESHOOTING:
+ Sudo's conversation functions now filters out the last login
+ information.
+ [ac21b18ba6bf]
+
+2019-04-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c:
+ Add pam_acct_mgmt setting to enable/disable PAM account validation.
+ [ec657af6eeb8]
+
+ * doc/cvtsudoers.cat, doc/sudo.cat, doc/sudo.conf.cat,
+ doc/sudo_plugin.cat, doc/sudoers.cat, doc/sudoers.ldap.cat,
+ doc/sudoers_timestamp.cat, doc/sudoreplay.cat, doc/visudo.cat:
+ regen
+ [d39b0636806f]
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.8.28
+ [dd02af1b71e1]
+
+ * Makefile.in, configure.ac, doc/Makefile.in, doc/cvtsudoers.man.in,
+ doc/cvtsudoers.mdoc.in, doc/fixman.sh, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ doc/sudoers.ldap.man.in, doc/sudoers.ldap.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ doc/sudoers_timestamp.man.in, doc/sudoers_timestamp.mdoc.in,
+ doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in, doc/visudo.man.in,
+ doc/visudo.mdoc.in, examples/Makefile.in, include/Makefile.in,
+ include/compat/charclass.h, include/compat/endian.h,
+ include/compat/fnmatch.h, include/compat/getopt.h,
+ include/compat/glob.h, include/compat/nss_dbdefs.h,
+ include/compat/sha2.h, include/sudo_compat.h, include/sudo_conf.h,
+ include/sudo_debug.h, include/sudo_digest.h, include/sudo_dso.h,
+ include/sudo_event.h, include/sudo_fatal.h, include/sudo_gettext.h,
+ include/sudo_lbuf.h, include/sudo_plugin.h, include/sudo_queue.h,
+ include/sudo_rand.h, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/aix.c, lib/util/arc4random.c, lib/util/arc4random.h,
+ lib/util/arc4random_uniform.c, lib/util/closefrom.c,
+ lib/util/digest.c, lib/util/digest_gcrypt.c,
+ lib/util/digest_openssl.c, lib/util/event.c, lib/util/event_poll.c,
+ lib/util/event_select.c, lib/util/fatal.c, lib/util/fnmatch.c,
+ lib/util/getcwd.c, lib/util/getdelim.c, lib/util/getentropy.c,
+ lib/util/getgrouplist.c, lib/util/gethostname.c,
+ lib/util/getopt_long.c, lib/util/gettime.c, lib/util/gidlist.c,
+ lib/util/glob.c, lib/util/inet_ntop.c, lib/util/inet_pton.c,
+ lib/util/isblank.c, lib/util/key_val.c, lib/util/lbuf.c,
+ lib/util/locking.c, lib/util/memrchr.c, lib/util/memset_s.c,
+ lib/util/mksiglist.c, lib/util/mksigname.c, lib/util/mktemp.c,
+ lib/util/nanosleep.c, lib/util/parseln.c, lib/util/pipe2.c,
+ lib/util/progname.c, lib/util/pw_dup.c, lib/util/reallocarray.c,
+ lib/util/regress/atofoo/atofoo_test.c,
+ lib/util/regress/getdelim/getdelim_test.c,
+ lib/util/regress/getgrouplist/getgrouplist_test.c,
+ lib/util/regress/parse_gids/parse_gids_test.c,
+ lib/util/regress/progname/progname_test.c,
+ lib/util/regress/strsplit/strsplit_test.c,
+ lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_parseln/parseln_test.c,
+ lib/util/regress/tailq/hltq_test.c,
+ lib/util/regress/vsyslog/vsyslog_test.c, lib/util/secure_path.c,
+ lib/util/setgroups.c, lib/util/sha2.c, lib/util/sig2str.c,
+ lib/util/snprintf.c, lib/util/strlcat.c, lib/util/strlcpy.c,
+ lib/util/strndup.c, lib/util/strnlen.c, lib/util/strsignal.c,
+ lib/util/strsplit.c, lib/util/strtobool.c, lib/util/strtoid.c,
+ lib/util/strtomode.c, lib/util/strtonum.c, lib/util/sudo_conf.c,
+ lib/util/sudo_debug.c, lib/util/sudo_dso.c, lib/util/term.c,
+ lib/util/ttyname_dev.c, lib/util/ttysize.c, lib/util/utimens.c,
+ lib/util/vsyslog.c, lib/zlib/Makefile.in, log2cl.pl, m4/sudo.m4,
+ mkdep.pl, mkpkg, pathnames.h.in, plugins/group_file/Makefile.in,
+ plugins/group_file/getgrent.c, plugins/group_file/group_file.c,
+ plugins/group_file/plugin_test.c, plugins/sample/Makefile.in,
+ plugins/sample/sample_plugin.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/alias.c, plugins/sudoers/audit.c,
+ plugins/sudoers/auth/afs.c, plugins/sudoers/auth/aix_auth.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/dce.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/passwd.c,
+ plugins/sudoers/auth/rfc1938.c, plugins/sudoers/auth/secureware.c,
+ plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/auth/sudo_auth.h,
+ plugins/sudoers/base64.c, plugins/sudoers/boottime.c,
+ plugins/sudoers/bsm_audit.c, plugins/sudoers/bsm_audit.h,
+ plugins/sudoers/check.c, plugins/sudoers/check.h,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers.h,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/defaults.h, plugins/sudoers/digestname.c,
+ plugins/sudoers/editor.c, plugins/sudoers/env.c,
+ plugins/sudoers/env_pattern.c, plugins/sudoers/file.c,
+ plugins/sudoers/filedigest.c, plugins/sudoers/find_path.c,
+ plugins/sudoers/fmtsudoers.c, plugins/sudoers/gc.c,
+ plugins/sudoers/gentime.c, plugins/sudoers/getspwuid.c,
+ plugins/sudoers/gmtoff.c, plugins/sudoers/goodpath.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/hexchar.c,
+ plugins/sudoers/ins_2001.h, plugins/sudoers/ins_classic.h,
+ plugins/sudoers/ins_csops.h, plugins/sudoers/ins_goons.h,
+ plugins/sudoers/ins_python.h, plugins/sudoers/insults.h,
+ plugins/sudoers/interfaces.c, plugins/sudoers/interfaces.h,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog.h,
+ plugins/sudoers/iolog_event.h, plugins/sudoers/iolog_files.h,
+ plugins/sudoers/iolog_path.c, plugins/sudoers/iolog_util.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/ldap_conf.c,
+ plugins/sudoers/ldap_util.c, plugins/sudoers/linux_audit.c,
+ plugins/sudoers/linux_audit.h, plugins/sudoers/locale.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/logwrap.c, plugins/sudoers/match.c,
+ plugins/sudoers/match_addr.c, plugins/sudoers/match_command.c,
+ plugins/sudoers/match_digest.c, plugins/sudoers/mkdir_parents.c,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/parse_ldif.c, plugins/sudoers/policy.c,
+ plugins/sudoers/prompt.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/pwutil.h, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/rcstr.c, plugins/sudoers/redblack.c,
+ plugins/sudoers/redblack.h,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/env_match/check_env_pattern.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/regress/iolog_util/check_iolog_util.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/regress/parser/check_gentime.c,
+ plugins/sudoers/regress/parser/check_hexchar.c,
+ plugins/sudoers/regress/starttime/check_starttime.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/solaris_audit.c,
+ plugins/sudoers/solaris_audit.h, plugins/sudoers/sssd.c,
+ plugins/sudoers/starttime.c, plugins/sudoers/strlist.c,
+ plugins/sudoers/strlist.h, plugins/sudoers/stubs.c,
+ plugins/sudoers/sudo_ldap.h, plugins/sudoers/sudo_ldap_conf.h,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudo_nss.h,
+ plugins/sudoers/sudo_printf.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoers_debug.c,
+ plugins/sudoers/sudoers_debug.h, plugins/sudoers/sudoers_version.h,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timeout.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/timestr.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.h, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/tsdump.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/tsgetgrpw.h,
+ plugins/sudoers/visudo.c, plugins/system_group/Makefile.in,
+ plugins/system_group/system_group.c, src/Makefile.in,
+ src/conversation.c, src/env_hooks.c, src/exec.c, src/exec_common.c,
+ src/exec_monitor.c, src/exec_nopty.c, src/exec_pty.c, src/get_pty.c,
+ src/hooks.c, src/load_plugins.c, src/net_ifs.c, src/openbsd.c,
+ src/parse_args.c, src/preload.c, src/preserve_fds.c,
+ src/regress/noexec/check_noexec.c,
+ src/regress/ttyname/check_ttyname.c, src/selinux.c, src/sesh.c,
+ src/signal.c, src/solaris.c, src/sudo.c, src/sudo.h,
+ src/sudo_edit.c, src/sudo_exec.h, src/sudo_noexec.c,
+ src/sudo_plugin_int.h, src/sudo_usage.h.in, src/tcsetpgrp_nobg.c,
+ src/tgetpass.c, src/ttyname.c, src/utmp.c:
+ Add SPDX-License-Identifier to files.
+ [db66decfad24]
+
+2019-04-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/pam.c:
+ Filter out last login messages on HP-UX unless running a shell. HP-
+ UX in trusted mode will display last login messages as part of the
+ PAM account management module by libpam_comsec. There is no way to
+ suppress these messages from the PAM configuration in trusted mode
+ so we need to filter them in the conversation function. In regular
+ mode, similar (but different) messages may be produced by
+ libpam_hpsec.
+ [5bbb02c69b46]
+
+2019-04-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/closefrom.c:
+ FreeBSD's /dev/fd only contains fds 0-2 unless fdescfs is mounted.
+ In practice this doesn't matter since FreeBSD >= 8 has a native
+ closefrom
+ [bbeeb52550f1]
+
+2019-04-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/logging.c:
+ Keep debug fds open in send_mail() to aid in debugging. Adds
+ closefrom_nodebug() which acts like closefrom(3) but doesn't close
+ debug fds for use by send_mail(). Also moves the code to exec the
+ mailer to its own function.
+ [b1892425667a]
+
+2019-04-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/defaults.c:
+ Set def_mailerflags even if sendmail was not found at configure
+ time. Fixes a NULL dereference when mailerpath is set but
+ mailerflags is not. Bug #878
+ [6c57f5ddca54]
+
+2019-04-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, lib/util/Makefile.in, lib/util/getdelim.c,
+ lib/util/getline.c, lib/util/parseln.c,
+ lib/util/regress/getdelim/getdelim_test.c, mkdep.pl,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/boottime.c,
+ plugins/sudoers/iolog_util.c, plugins/sudoers/ldap_conf.c,
+ plugins/sudoers/parse_ldif.c, plugins/sudoers/sssd.c:
+ Add a proper getdelim(3) replacement and use it instead of
+ getline(3).
+ [2e06e45ffbd6]
+
+ * plugins/sudoers/auth/pam.c:
+ Restrict the PAM_TTY kludge to Solaris and Linux-PAM. Setting
+ PAM_TTY to the empty string causes problems with some modules on HP-
+ UX so restrict it to systems where it is fixes known issues.
+ [d61f4e20dc67]
+
+2019-03-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/getgrouplist.c:
+ Fix the counting of supplementary groups on AIX. We should not
+ assume that basegid will be present in the list of gids returned by
+ getgrset().
+ [6b5fa2805840]
+
+2019-03-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/pwutil.c:
+ Plug a memory leak on user/group lookup failure found by ASAN.
+ [aff673f310d0]
+
+2019-03-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/regress/testsudoers/test3.d/root,
+ plugins/sudoers/regress/testsudoers/test3.sh:
+ Fix test failure when run by a user other than the file owner.
+ [c41ea7cfedf8]
+
+ * MANIFEST, plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/zh_TW.mo, plugins/sudoers/po/zh_TW.po, po/da.mo,
+ po/da.po, po/eo.mo, po/eo.po, po/es.mo, po/es.po, po/zh_TW.mo,
+ po/zh_TW.po:
+ Updated translations from translationproject.org
+ [484d7b28bdd6]
+
+ * MANIFEST, plugins/sudoers/regress/cvtsudoers/test1.sh,
+ plugins/sudoers/regress/cvtsudoers/test10.sh,
+ plugins/sudoers/regress/cvtsudoers/test11.sh,
+ plugins/sudoers/regress/cvtsudoers/test12.sh,
+ plugins/sudoers/regress/cvtsudoers/test13.sh,
+ plugins/sudoers/regress/cvtsudoers/test14.sh,
+ plugins/sudoers/regress/cvtsudoers/test15.sh,
+ plugins/sudoers/regress/cvtsudoers/test16.sh,
+ plugins/sudoers/regress/cvtsudoers/test17.sh,
+ plugins/sudoers/regress/cvtsudoers/test18.sh,
+ plugins/sudoers/regress/cvtsudoers/test19.sh,
+ plugins/sudoers/regress/cvtsudoers/test2.sh,
+ plugins/sudoers/regress/cvtsudoers/test20.sh,
+ plugins/sudoers/regress/cvtsudoers/test21.sh,
+ plugins/sudoers/regress/cvtsudoers/test22.sh,
+ plugins/sudoers/regress/cvtsudoers/test23.sh,
+ plugins/sudoers/regress/cvtsudoers/test24.sh,
+ plugins/sudoers/regress/cvtsudoers/test25.sh,
+ plugins/sudoers/regress/cvtsudoers/test26.err.ok,
+ plugins/sudoers/regress/cvtsudoers/test26.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test26.sh,
+ plugins/sudoers/regress/cvtsudoers/test27.sh,
+ plugins/sudoers/regress/cvtsudoers/test28.sh,
+ plugins/sudoers/regress/cvtsudoers/test29.sh,
+ plugins/sudoers/regress/cvtsudoers/test3.sh,
+ plugins/sudoers/regress/cvtsudoers/test30.sh,
+ plugins/sudoers/regress/cvtsudoers/test31.sh,
+ plugins/sudoers/regress/cvtsudoers/test32.err.ok,
+ plugins/sudoers/regress/cvtsudoers/test32.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test32.sh,
+ plugins/sudoers/regress/cvtsudoers/test33.sh,
+ plugins/sudoers/regress/cvtsudoers/test4.sh,
+ plugins/sudoers/regress/cvtsudoers/test5.sh,
+ plugins/sudoers/regress/cvtsudoers/test6.sh,
+ plugins/sudoers/regress/cvtsudoers/test7.sh,
+ plugins/sudoers/regress/cvtsudoers/test8.sh,
+ plugins/sudoers/regress/cvtsudoers/test9.sh:
+ Test cvtsudoers stdout and stderr separately. Fixes a test failure
+ on systems with musl libc. Bug #873
+ [e82a381f4f3d]
+
+2019-03-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/starttime.c, src/ttyname.c:
+ Better comment about EOVERFLOW and pstat_getproc(). Also remove some
+ useless casts.
+ [09a915110812]
+
+ * lib/util/closefrom.c:
+ Ignore EOVERFLOW from pstat_getproc(), it is not a fatal error. It
+ just means that one of the fields in pstat lacks the precision to
+ store a value. That's not an issue for pst_highestfd.
+ [bb7ed18e360b]
+
+ * sudo.pp:
+ update copyright year
+ [cff8184aeb11]
+
+2019-03-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/load_plugins.c:
+ Fix error message when a fully-qualified plugin path does not exist.
+ [318f7511c9bc]
+
+2019-03-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Fix unescaped '\' and remove an extra '[' in the definition of
+ digest.
+ [9ea1a400ebc9]
+
+2019-03-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Ignore carriage return before a linefeed. This allows sudo to parse
+ files with DOS-style line endings.
+ [65882b63a84d]
+
+2019-02-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ For sssd, the nsswitch.conf setting should be "sss" not "sssd". From
+ Johnathan Smith.
+ [5c07130d1bbc]
+
+2019-02-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/env.c, plugins/sudoers/sudoers.h:
+ Add simple API for to allow reading environment data from different
+ sources. Currently, this is used to read a file like
+ /etc/environment.
+ [ce9161899719]
+
+2019-02-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.c:
+ Fix pasto; the unrestricted env file was read when we want the
+ restricted one.
+ [23b0b3c473db]
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/parse.h, plugins/sudoers/strlist.c, src/sudo.h:
+ Be sure to include sudo_queue.h where needed instead of relying on
+ other headers.
+ [fe9418a9b378]
+
+2019-02-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/util.exp.in:
+ Only export sudo_arc4random_uniform() if arc4random_uniform() is
+ missing.
+ [e32a7243976d]
+
+ * lib/util/regress/vsyslog/vsyslog_test.c:
+ Quiet a warning on gcc 8
+ [fe8cad6564e2]
+
+ * include/sudo_compat.h:
+ AIX 7.1 defines O_CLOEXEC but it can't be used outside the kernel.
+ Redefine O_CLOEXEC if it doesn't fit in an int and pipe2() is
+ missing.
+ [3ef0220351ca]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/match.c,
+ plugins/sudoers/match_command.c, plugins/sudoers/match_digest.c,
+ plugins/sudoers/parse.h:
+ Split command match code out into match_command.c. Also remove
+ unused SUDOERS_NAME_MATCH code.
+ [2a7adb93a65e]
+
+2019-02-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/match_digest.c:
+ Split out digest matching into its own file.
+ [93863918f934]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/match.c,
+ plugins/sudoers/parse.h:
+ Split out digest matching into its own file.
+ [aafdc9b976ed]
+
+2019-02-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l:
+ Rename FOLLOW and NOFOLLOW tokens FOLLOWLNK and NOFOLLOWLNK. Fixes a
+ namespace collision on Solaris when bison is used.
+ [707b94b7c1e9]
+
+2019-02-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/match.c:
+ Add stub definition of digest_matches() for SUDOERS_NAME_MATCH
+ [a322e57c85e0]
+
+ * plugins/sudoers/sudo_nss.c:
+ No longer need to include sudo_lbuf.h
+ [db110422b24c]
+
+ * mkpkg:
+ On RedHat/CentOS get the OS major version from /etc/redhat-release.
+ We cannot determine this from the output of "pp --probe" since it
+ doesn't contain a period to separate the major and minor numbers.
+ [78a27d62de0c]
+
+2019-02-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/policy.c:
+ Use SET macro instead of bitwise OR.
+ [b523937e8da8]
+
+ * plugins/sudoers/pwutil_impl.c:
+ In sudo_make_grlist_item() the calculation of total did not include
+ space for pointers to the group names.
+ [7c438dd62f45]
+
+ * plugins/sudoers/cvtsudoers_pwutil.c:
+ Use correct debug_decl() names.
+ [d0f02db8be20]
+
+ * plugins/sudoers/sudoers.h:
+ Add fallback values for sudoers uid, gid and mode if not set in
+ Makefile.
+ [21e41ed7a06c]
+
+2019-02-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/memset_s.c:
+ include stddef.h to make sure we get NULL
+ [d42b4c325c0c]
+
+2019-02-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/net_ifs.c:
+ Fix memory leak when there are no network interfaces or an error
+ occurs.
+ [7ba525ee9233]
+
+2019-01-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ Use $ac_cv_search_FUNCTION instead of $ac_lib and $ac_res. Fixes a
+ problem where libcrypt is not used with autoconf caching. Adapted
+ from a diff from Adam Labbe.
+ [5cfcade6ce3e]
+
+2019-01-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * po/de.mo, po/de.po, po/ko.mo, po/ko.po:
+ Updated translations from translationproject.org
+ [4995f6542a2c]
+
+2019-01-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/parse.c:
+ Fix listpw=never and verifypw=never. Bug #869
+ [ecb89088a884]
+
+2019-01-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/regress/vsyslog/vsyslog_test.c, lib/util/sig2str.c,
+ plugins/sudoers/alias.c, plugins/sudoers/cvtsudoers_pwutil.c,
+ plugins/sudoers/env.c, plugins/sudoers/find_path.c,
+ plugins/sudoers/fmtsudoers.c, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/ldap_conf.c, plugins/sudoers/ldap_util.c,
+ plugins/sudoers/logging.c, plugins/sudoers/match.c,
+ plugins/sudoers/parse.c, plugins/sudoers/set_perms.c,
+ plugins/sudoers/starttime.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/tsdump.c, src/exec_monitor.c, src/exec_nopty.c,
+ src/exec_pty.c, src/sudo.c, src/ttyname.c:
+ Minor snprintf() usage tweaks: 1) don't assume snprintf() returns -1
+ on error, check for <0 2) when comparing return value of
+ sizeof(foo), cast the sizeof, not the len 3) cast return value to
+ void in cases where snprintf cannot fail
+ [2af6dfb31a49]
+
+2019-01-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ The AIX nofiles hard limit fix and bug #867 will make 1.8.27.
+ [a8b4710ff907]
+
+ * plugins/sudoers/auth/pam.c:
+ Use PAM_SILENT to prevent pam_lastlog from printing last login
+ information on RedHat except when explicitly running a shell.
+ Adapted from a patch from Nir Soffer. Bug #867
+ [b8b5d3445a3c]
+
+ * lib/util/aix.c:
+ Fix the default nofiles and stack hard limits. The table of default
+ hard limits in /etc/security/limits was out of date with respect to
+ the current documentation. The default hard limit for nofiles should
+ be unlimited, not 8196. The default hard limit for stack should be
+ 4194304 blocks (which fits in an unsigned long on 32-bit platforms).
+ [68c8c05a0b9b]
+
+2019-01-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [3000c62ed0ba]
+
+ * NEWS:
+ Final updates for sudo 1.8.27.
+ [40d6ecb1f739]
+
+ * src/exec_pty.c:
+ Update copyright year
+ [adc9f4046585]
+
+ * doc/LICENSE:
+ Update for 2019
+ [ccbbad25d7c7]
+
+2019-01-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_pty.c:
+ Fix setting of utmp entry when running command in a pty. Regression
+ introduced in sudo 1.8.22.
+ [cf81f3fa1f3a]
+
+2018-12-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.c:
+ Use debug_return_int not debug_return_bool in resolve_host
+ [490241e14e68]
+
+ * NEWS, configure, configure.ac:
+ sudo 1.8.27
+ [f59a4a391a44]
+
+ * doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in,
+ plugins/sudoers/visudo.c:
+ Allow the sudoers file to be specified without the -f option. Bug
+ #864
+ [eb3d4c4461ba]
+
+2018-12-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ The iolog_dir section is below the maxseq section, not above.
+ [35534e4f23d9]
+
+2018-12-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po, po/ja.mo,
+ po/ja.po:
+ Updated translations from translationproject.org
+ [270660da2de4]
+
+2018-12-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoreplay.c:
+ Add -n and -R options to help; reported by Radovan Sroka
+ [683df32eb950]
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in:
+ Add missing description of padding option and missing argument to
+ -c.
+ [c762020f1694]
+
+ * plugins/sudoers/cvtsudoers.c:
+ The -c option was missing from the help info; from Radovan Sroka
+ [aa36d5c05b0b]
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in:
+ Fix some typos; reported by Radovan Sroka
+ [d6137224dd47]
+
+2018-12-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/pam.c:
+ In sudo_pam_approval(), for the exempt case, only overwrite pam
+ status when the passwd is expired or needs to be updated.
+ [2c2d1ed1bb7e]
+
+2018-12-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/pam.c:
+ The fix for bug #843 was incomplete and caused pam_end() to be
+ called early. sudo_pam_approval() must not set the global pam status
+ to an error value if it returns AUTH_SUCCESS. Otherwise,
+ sudo_pam_cleanup() will call pam_end() before
+ sudo_pam_begin_session(). This resulted in a NULL PAM handle being
+ used in sudo_pam_begin_session().
+ [656aa910fbaf]
+
+2018-12-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec.c:
+ Don't run the command in a pty if no I/O plugins are logging
+ anything. That way an I/O plugin that doesn't actually log anything
+ won't cause the command to be run in a pty.
+ [ef83f35c9cb0]
+
+2018-11-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgignore:
+ Update ignore patterns to match doc changes.
+ [7438cdacc0e1]
+
+ * doc/fixmdoc.sed:
+ fix mode fixmdoc.sed
+ [d74c0b7c5932]
+
+2018-11-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/Makefile.in, doc/sudo.conf.man.in, doc/sudo.man.in,
+ doc/sudoers.ldap.man.in, doc/sudoers.man.in,
+ doc/sudoers_timestamp.man.in, doc/sudoreplay.man.in,
+ doc/visudo.man.in:
+ Fix section in the .TH line of *.man.in file. The substitution for
+ @mansectsu@ and @mansectform@ was broken. No longer need to strip
+ out OpenBSD from the header line.
+ [cb02c8496b21]
+
+ * doc/sudoers.man.in.sed:
+ Add sudoers.man.in.sed, missed from previous commit.
+ [a2113a52e6a7]
+
+ * doc/CONTRIBUTORS:
+ Add Guillem Jover
+ [db7a39f9726a]
+
+ * NEWS:
+ recent changes
+ [0c07a0cdf2ff]
+
+ * MANIFEST, doc/Makefile.in, doc/fixman.sh, doc/fixmdoc.sed,
+ doc/fixmdoc.sh, doc/sudo.cat, doc/sudo.man.in, doc/sudo.man.in.sed,
+ doc/sudo.mdoc.in, doc/sudoers.cat, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in:
+ Use roff conditionals in the manuals instead of post-processing. We
+ still need to process the resulting .man.in files to add back the
+ conditionals but this should be easier to debug as the changes are
+ visible in the .in file. Some minor postprocessing is still used to
+ make the manuals HP-UX friendly and to change "0 seconds" ->
+ unlimited after substitution.
+ [44316d271ab8]
+
+2018-11-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in:
+ Sudo plugin manual updates and clarification from Guillem Jover:
+ - Add missing return information for show_version().
+ - Fix prototypes for several function pointers.
+ - Update SUDO_API_VERSION_MINOR.
+ - Add missing references to log_suspend() and change_winsize().
+ - Add missing "array.".
+ - Clarify that argc can be zero on sudo -V.
+ - Clarify size requirements for conversation array arguments.
+ - Clarify timeout zero value for struct sudo_conv_message.
+ - Clarify initial and final state of reply in struct sudo_conv_reply.
+ [1241cff4dd51]
+
+ * doc/fixmdoc.sh, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Revert changes to give arguments to the .Bx macro. This is intended
+ for things like .Bx 4.3 to generate "4.3BSD" so the argument ends up
+ before the BSD, not after. Just go back to using "BSD
+ authentication" and "BSD login classes" so fixmdoc.sh can operate
+ correctly. Bug #861
+ [c58965343318]
+
+2018-11-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/fixmdoc.sh, doc/sudo.mdoc.in, doc/sudoers.mdoc.in:
+ Update fixmdoc.sh to match the BSD -> .Bx changes in the manuals.
+ Bug #861
+ [7ddfb74781a1]
+
+2018-11-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, m4/sudo.m4, src/utmp.c:
+ Add support for utmps as found in HP-UX.
+ [f55312948139]
+
+2018-11-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, include/sudo_util.h,
+ lib/util/utimens.c:
+ Support st_nmtime in struct stat as found in HP-UX.
+ [0854b34cd2ea]
+
+ * lib/util/closefrom.c:
+ If fcntl fails, fall back to the /proc implementation.
+ [59a03e0d3148]
+
+2018-11-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Mention schema.olcSudo
+ [320adcd29a61]
+
+2018-11-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ Mention schema.olcSudo here too.
+ [a19dff54603b]
+
+ * MANIFEST, README.LDAP, doc/CONTRIBUTORS, doc/schema.OpenLDAP,
+ doc/schema.olcSudo:
+ OpenLDAP schema file for Sudo in on-line configuration (OLC) format.
+ From Frederic Pasteleurs.
+ [1fcfa9f307a2]
+
+ * po/ast.mo, po/ast.po:
+ Updated translations from translationproject.org
+ [70f0ec8c721c]
+
+2018-11-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/closefrom.c:
+ Only use closefrom_fallback() if no better method exists. The
+ previous logic was too fragile.
+ [2510928e291f]
+
+2018-11-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po, po/cs.mo,
+ po/cs.po, po/fr.mo, po/fr.po, po/hr.mo, po/hr.po, po/it.mo,
+ po/it.po, po/nb.mo, po/nb.po, po/pl.mo, po/pl.po, po/pt_BR.mo,
+ po/pt_BR.po, po/sv.mo, po/sv.po, po/tr.mo, po/tr.po, po/uk.mo,
+ po/uk.po, po/vi.mo, po/vi.po, po/zh_CN.mo, po/zh_CN.po:
+ Updated translations from translationproject.org
+ [898154804015]
+
+ * MANIFEST, NEWS, doc/CONTRIBUTORS, plugins/sudoers/po/pt.mo,
+ plugins/sudoers/po/pt.po, po/pt.mo, po/pt.po:
+ Portuguese translation for sudo and sudoers from
+ translationproject.org.
+ [4c49e5cf8936]
+
+2018-11-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, configure, configure.ac, include/sudo_fatal.h,
+ lib/util/Makefile.in, lib/util/fatal.c, lib/util/util.exp.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h, plugins/sudoers/sudoers.c:
+ Add sudo_gai_fatal, sudo_gai_vfatal, sudo_gai_vwarn, sudo_gai_warn
+ and gai_log_warning that use gai_strerror() instead of strerror().
+ [9c37c5db3293]
+
+2018-10-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/match.c:
+ Fix memory leak in runaslist_matches().
+ [f1366ad50eb3]
+
+2018-10-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ typo
+ [fc8aa243672a]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [f333405eb06c]
+
+ * NEWS:
+ More updates for 1.8.26
+ [1941961b232f]
+
+2018-10-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in, plugins/sudoers/ldap_util.c,
+ plugins/sudoers/regress/cvtsudoers/test33.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test33.sh:
+ Add support for negated sudoRunAsUser and sudoRunAsGroup entries.
+ [d0368336d92b]
+
+2018-10-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document that the target user's groups may be specified via the -g
+ option.
+ [67b7643e3bcb]
+
+ * plugins/sudoers/tsgetgrpw.c:
+ Include getpwent() version of sudo_getgrouplist2_v1() from
+ getgrouplist.c
+ [60aa493504d1]
+
+ * MANIFEST, plugins/sudoers/regress/testsudoers/group,
+ plugins/sudoers/regress/testsudoers/test1.sh:
+ Use a testsudoers group file with known contents instead of the
+ system one.
+ [7a4499c92acd]
+
+ * plugins/sudoers/match.c, plugins/sudoers/parse.h,
+ plugins/sudoers/set_perms.c:
+ Allow the group set by "sudo -g" to be any of the target user's
+ groups. Previously, this was only allowed if the group matched the
+ target user's primary group ID (from the passwd database entry). The
+ sudoers policy will now allow the group if it is one of the target
+ user's supplemental groups as well.
+ [c43fedc19a01]
+
+2018-10-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/regress/getgrouplist/getgrouplist_test.c:
+ Skip sudo_getgrouplist2() check on systems with getgrouplist_2().
+ sudo_getgrouplist2() is just a wrapper on such systems and this
+ avoids a test failure on macOS where a user is automatically a
+ member of certain groups.
+ [26ba0c363b80]
+
+ * lib/util/util.exp.in:
+ Add missing exported symbol sudo_term_eof
+ [2d8e0438eba4]
+
+ * plugins/sudoers/ldap_conf.c:
+ Add missing #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT Fixes problems
+ building on older LDAP sdks.
+ [1effb0f19867]
+
+ * MANIFEST:
+ add getgrouplist_test.c
+ [ca5bae341846]
+
+ * lib/util/regress/getgrouplist/getgrouplist_test.c:
+ Check the user's primary gid from the passwd file too.
+ [60ba98074d75]
+
+ * .hgignore:
+ ignore prologue
+ [589222ec2717]
+
+ * lib/util/aix.c, lib/util/arc4random.c,
+ lib/util/arc4random_uniform.c, lib/util/closefrom.c,
+ lib/util/digest.c, lib/util/digest_gcrypt.c,
+ lib/util/digest_openssl.c, lib/util/event.c, lib/util/event_poll.c,
+ lib/util/event_select.c, lib/util/fatal.c, lib/util/fnmatch.c,
+ lib/util/getentropy.c, lib/util/getgrouplist.c,
+ lib/util/gethostname.c, lib/util/getline.c, lib/util/getopt_long.c,
+ lib/util/gettime.c, lib/util/gidlist.c, lib/util/isblank.c,
+ lib/util/key_val.c, lib/util/lbuf.c, lib/util/locking.c,
+ lib/util/memrchr.c, lib/util/memset_s.c, lib/util/mksiglist.c,
+ lib/util/mksigname.c, lib/util/mktemp.c, lib/util/nanosleep.c,
+ lib/util/parseln.c, lib/util/pipe2.c, lib/util/progname.c,
+ lib/util/pw_dup.c, lib/util/reallocarray.c,
+ lib/util/regress/atofoo/atofoo_test.c,
+ lib/util/regress/getgrouplist/getgrouplist_test.c,
+ lib/util/regress/parse_gids/parse_gids_test.c,
+ lib/util/regress/progname/progname_test.c,
+ lib/util/regress/strsplit/strsplit_test.c,
+ lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_parseln/parseln_test.c,
+ lib/util/regress/tailq/hltq_test.c,
+ lib/util/regress/vsyslog/vsyslog_test.c, lib/util/secure_path.c,
+ lib/util/setgroups.c, lib/util/sha2.c, lib/util/sig2str.c,
+ lib/util/strlcat.c, lib/util/strlcpy.c, lib/util/strndup.c,
+ lib/util/strnlen.c, lib/util/strsignal.c, lib/util/strsplit.c,
+ lib/util/strtobool.c, lib/util/strtoid.c, lib/util/strtomode.c,
+ lib/util/strtonum.c, lib/util/sudo_conf.c, lib/util/sudo_debug.c,
+ lib/util/sudo_dso.c, lib/util/term.c, lib/util/ttyname_dev.c,
+ lib/util/ttysize.c, lib/util/utimens.c, lib/util/vsyslog.c,
+ plugins/group_file/getgrent.c, plugins/group_file/group_file.c,
+ plugins/group_file/plugin_test.c, plugins/sample/sample_plugin.c,
+ plugins/sudoers/Makefile.in, plugins/sudoers/alias.c,
+ plugins/sudoers/audit.c, plugins/sudoers/auth/afs.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/base64.c, plugins/sudoers/boottime.c,
+ plugins/sudoers/bsm_audit.c, plugins/sudoers/check.c,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/digestname.c, plugins/sudoers/editor.c,
+ plugins/sudoers/env.c, plugins/sudoers/env_pattern.c,
+ plugins/sudoers/file.c, plugins/sudoers/filedigest.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/gc.c, plugins/sudoers/gentime.c,
+ plugins/sudoers/getdate.c, plugins/sudoers/getspwuid.c,
+ plugins/sudoers/gmtoff.c, plugins/sudoers/goodpath.c,
+ plugins/sudoers/gram.c, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/hexchar.c, plugins/sudoers/interfaces.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_path.c,
+ plugins/sudoers/iolog_util.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/ldap_conf.c, plugins/sudoers/ldap_util.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/locale.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logwrap.c,
+ plugins/sudoers/match.c, plugins/sudoers/match_addr.c,
+ plugins/sudoers/mkdir_parents.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse_ldif.c, plugins/sudoers/policy.c,
+ plugins/sudoers/prompt.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/pwutil_impl.c, plugins/sudoers/rcstr.c,
+ plugins/sudoers/redblack.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/env_match/check_env_pattern.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/regress/iolog_util/check_iolog_util.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/regress/parser/check_gentime.c,
+ plugins/sudoers/regress/parser/check_hexchar.c,
+ plugins/sudoers/regress/starttime/check_starttime.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/solaris_audit.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/starttime.c,
+ plugins/sudoers/strlist.c, plugins/sudoers/stubs.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudo_printf.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers_debug.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timeout.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/timestr.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke_util.c, plugins/sudoers/tsdump.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/visudo.c,
+ plugins/system_group/system_group.c, src/conversation.c,
+ src/env_hooks.c, src/exec.c, src/exec_common.c, src/exec_monitor.c,
+ src/exec_nopty.c, src/exec_pty.c, src/get_pty.c, src/hooks.c,
+ src/load_plugins.c, src/net_ifs.c, src/openbsd.c, src/parse_args.c,
+ src/preload.c, src/preserve_fds.c,
+ src/regress/noexec/check_noexec.c,
+ src/regress/ttyname/check_ttyname.c, src/selinux.c, src/sesh.c,
+ src/signal.c, src/solaris.c, src/sudo.c, src/sudo_edit.c,
+ src/sudo_noexec.c, src/tcsetpgrp_nobg.c, src/tgetpass.c,
+ src/ttyname.c, src/utmp.c:
+ Convert PVS-Studio comment to ANSI C.
+ [31f2aefe6d9b]
+
+ * Makefile.in, doc/Makefile.in, doc/cvtsudoers.man.in,
+ doc/cvtsudoers.mdoc.in, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in,
+ doc/sudo.man.in, doc/sudo.mdoc.in, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ doc/sudoers_timestamp.man.in, doc/sudoers_timestamp.mdoc.in,
+ doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in, doc/visudo.man.in,
+ doc/visudo.mdoc.in, examples/Makefile.in, include/Makefile.in,
+ include/sudo_lbuf.h, lib/util/Makefile.in, lib/util/digest.c,
+ lib/util/digest_gcrypt.c, lib/util/digest_openssl.c,
+ lib/util/lbuf.c, lib/util/setgroups.c, lib/util/ttysize.c,
+ lib/zlib/Makefile.in, plugins/group_file/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/sudoers/alias.c, plugins/sudoers/auth/dce.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/base64.c,
+ plugins/sudoers/file.c, plugins/sudoers/filedigest.c,
+ plugins/sudoers/gentime.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/match.c,
+ plugins/sudoers/match_addr.c, plugins/sudoers/parse.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/timeout.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/tsdump.c,
+ plugins/system_group/Makefile.in, src/Makefile.in, src/sesh.c,
+ src/sudo_usage.h.in:
+ Fix some mangled text in the license block.
+ [86b88fbda4b4]
+
+ * lib/util/Makefile.in,
+ lib/util/regress/getgrouplist/getgrouplist_test.c,
+ lib/util/regress/parse_gids/parse_gids_test.c:
+ Add regress test for sudo_getgrouplist2(). This test assumes all the
+ groups in root's group list can be resolved by group ID.
+ [48564f85b7ed]
+
+2018-10-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ More changes in 1.8.26
+ [fe81e3e4b653]
+
+ * MANIFEST, doc/cvtsudoers.cat, doc/cvtsudoers.man.in,
+ doc/cvtsudoers.mdoc.in, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers.h, plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/regress/cvtsudoers/test31.conf,
+ plugins/sudoers/regress/cvtsudoers/test31.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test31.sh,
+ plugins/sudoers/regress/cvtsudoers/test32.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test32.sh:
+ Add padding option to cvtsudoers. Bug #856
+ [6e31b0e37ba1]
+
+ * lib/util/getgrouplist.c:
+ Remove an errant grset++ in the AIX version of sudo_getgrouplist2().
+ Bug #857
+ [03b19227cab2]
+
+2018-10-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/Makefile.in, plugins/group_file/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/Makefile.in:
+ Pass --sourcetree-root to pvs-studio and don't check sudo_noexec.c.
+ Since we don't auto-generate dependencies for sudo_noexec.c we can't
+ easily check it from outside the source tree. This is not a problem
+ as it just contains stub functions.
+ [3cf842d30e45]
+
+ * MANIFEST, doc/CONTRIBUTORS, po/ast.mo, po/ast.po:
+ Asturian translation for sudo from translationproject.org
+ [dc0b31fa013c]
+
+2018-10-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/gettime.c:
+ Add support for CLOCK_MONOTONIC_RAW and CLOCK_UPTIME_RAW, present on
+ macOS.
+ [5f34c8de0707]
+
+ * INSTALL, configure, configure.ac:
+ Add --enable-pvs-studio configure option to create PVS-Studio.cfg.
+ [772e86227c11]
+
+ * lib/util/aix.c, lib/util/arc4random.c,
+ lib/util/arc4random_uniform.c, lib/util/closefrom.c,
+ lib/util/digest.c, lib/util/digest_gcrypt.c,
+ lib/util/digest_openssl.c, lib/util/event.c, lib/util/event_poll.c,
+ lib/util/event_select.c, lib/util/fatal.c, lib/util/fnmatch.c,
+ lib/util/getentropy.c, lib/util/getgrouplist.c,
+ lib/util/gethostname.c, lib/util/getline.c, lib/util/getopt_long.c,
+ lib/util/gettime.c, lib/util/gidlist.c, lib/util/isblank.c,
+ lib/util/key_val.c, lib/util/lbuf.c, lib/util/locking.c,
+ lib/util/memrchr.c, lib/util/memset_s.c, lib/util/mksiglist.c,
+ lib/util/mksigname.c, lib/util/mktemp.c, lib/util/nanosleep.c,
+ lib/util/parseln.c, lib/util/pipe2.c, lib/util/progname.c,
+ lib/util/pw_dup.c, lib/util/reallocarray.c,
+ lib/util/regress/atofoo/atofoo_test.c,
+ lib/util/regress/parse_gids/parse_gids_test.c,
+ lib/util/regress/progname/progname_test.c,
+ lib/util/regress/strsplit/strsplit_test.c,
+ lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_parseln/parseln_test.c,
+ lib/util/regress/tailq/hltq_test.c,
+ lib/util/regress/vsyslog/vsyslog_test.c, lib/util/secure_path.c,
+ lib/util/setgroups.c, lib/util/sha2.c, lib/util/sig2str.c,
+ lib/util/strlcat.c, lib/util/strlcpy.c, lib/util/strndup.c,
+ lib/util/strnlen.c, lib/util/strsignal.c, lib/util/strsplit.c,
+ lib/util/strtobool.c, lib/util/strtoid.c, lib/util/strtomode.c,
+ lib/util/strtonum.c, lib/util/sudo_conf.c, lib/util/sudo_debug.c,
+ lib/util/sudo_dso.c, lib/util/term.c, lib/util/ttyname_dev.c,
+ lib/util/ttysize.c, lib/util/utimens.c, lib/util/vsyslog.c,
+ plugins/group_file/getgrent.c, plugins/group_file/group_file.c,
+ plugins/group_file/plugin_test.c, plugins/sample/sample_plugin.c,
+ plugins/sudoers/alias.c, plugins/sudoers/audit.c,
+ plugins/sudoers/auth/afs.c, plugins/sudoers/auth/aix_auth.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/dce.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/passwd.c,
+ plugins/sudoers/auth/rfc1938.c, plugins/sudoers/auth/secureware.c,
+ plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/base64.c,
+ plugins/sudoers/boottime.c, plugins/sudoers/bsm_audit.c,
+ plugins/sudoers/check.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/digestname.c, plugins/sudoers/editor.c,
+ plugins/sudoers/env.c, plugins/sudoers/env_pattern.c,
+ plugins/sudoers/file.c, plugins/sudoers/filedigest.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/gc.c, plugins/sudoers/gentime.c,
+ plugins/sudoers/getdate.c, plugins/sudoers/getspwuid.c,
+ plugins/sudoers/gmtoff.c, plugins/sudoers/goodpath.c,
+ plugins/sudoers/gram.c, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/hexchar.c, plugins/sudoers/interfaces.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_path.c,
+ plugins/sudoers/iolog_util.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/ldap_conf.c, plugins/sudoers/ldap_util.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/locale.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logwrap.c,
+ plugins/sudoers/match.c, plugins/sudoers/match_addr.c,
+ plugins/sudoers/mkdir_parents.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse_ldif.c, plugins/sudoers/policy.c,
+ plugins/sudoers/prompt.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/pwutil_impl.c, plugins/sudoers/rcstr.c,
+ plugins/sudoers/redblack.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/env_match/check_env_pattern.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/regress/iolog_util/check_iolog_util.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/regress/parser/check_gentime.c,
+ plugins/sudoers/regress/parser/check_hexchar.c,
+ plugins/sudoers/regress/starttime/check_starttime.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/solaris_audit.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/starttime.c,
+ plugins/sudoers/strlist.c, plugins/sudoers/stubs.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudo_printf.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers_debug.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timeout.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/timestr.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke_util.c, plugins/sudoers/tsdump.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/visudo.c,
+ plugins/system_group/system_group.c, src/conversation.c,
+ src/env_hooks.c, src/exec.c, src/exec_common.c, src/exec_monitor.c,
+ src/exec_nopty.c, src/exec_pty.c, src/get_pty.c, src/hooks.c,
+ src/load_plugins.c, src/net_ifs.c, src/openbsd.c, src/parse_args.c,
+ src/preload.c, src/preserve_fds.c,
+ src/regress/noexec/check_noexec.c,
+ src/regress/ttyname/check_ttyname.c, src/selinux.c, src/sesh.c,
+ src/signal.c, src/solaris.c, src/sudo.c, src/sudo_edit.c,
+ src/sudo_noexec.c, src/tcsetpgrp_nobg.c, src/tgetpass.c,
+ src/ttyname.c, src/utmp.c:
+ Add comments in .c files so PVS-Studio will check them.
+ [b42b6dcb48a6]
+
+ * .hgignore, Makefile.in, doc/Makefile.in, examples/Makefile.in,
+ include/Makefile.in, lib/util/Makefile.in, lib/zlib/Makefile.in,
+ mkdep.pl, plugins/group_file/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/Makefile.in:
+ Add pvs-studio target and associated production rules.
+ [3dbcef5ac205]
+
+2018-10-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog_util.c:
+ Simplify range checks. No need to check for ERANGE in the cases
+ where we also check that the value is <= INT_MAX. Found by PVS-
+ Studio.
+ [45810a8437b6]
+
+2018-10-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/key_val.c, plugins/sudoers/iolog_path.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/toke_util.c,
+ src/preserve_fds.c:
+ Avoid some PVS-Studio false positives.
+ [e4d8ce94fda7]
+
+ * src/sudo.c:
+ Remove some calls to sudo_fatalx(); just propagate the error return.
+ [bc9eefbf0cdf]
+
+ * src/sesh.c:
+ No need to check if fd_dst is -1 in sudoedit mode. Failure to open
+ the destination sudoedit file is fatal so there's no need to check
+ that fd_dst != -1 later on. Found by PVS-Studio.
+ [5530586ace16]
+
+ * plugins/sudoers/timestamp.c:
+ In timestamp_open() no need to free cookie on error, it is NULL.
+ Found by PVS-Studio.
+ [becfe97c72f8]
+
+2018-10-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/ldap_util.c:
+ Fix a memory leak on malloc() error in sudo_ldap_role_to_priv().
+ Coverity CID 188804
+ [1bea56670410]
+
+ * plugins/sudoers/parse_ldif.c:
+ Move the allocation of role to be immediately before in_role is set.
+ This makes it clear that when in_role == true, role is non-NULL.
+ Also remove two dead stores.
+ [790d90c578c8]
+
+ * plugins/sudoers/parse_ldif.c:
+ Fix trimming of non-escaped trailing space in
+ ldif_parse_attribute(). Found by PVS-Studio.
+ [37fded3c77a4]
+
+ * plugins/sudoers/match.c:
+ Simplify the logic surrounding sudoers_args in command_args_match().
+ We only need to check that sudoers_args is non-NULL once. Found by
+ PVS-Studio.
+ [93c967145e82]
+
+ * plugins/sudoers/ldap.c:
+ If sudo_ldap_get_values_len() fails goto cleanup instead of oom.
+ This is not strictly necessary as there's not anything to cleanup in
+ this case but it is more consistent with the code that follows.
+ [d0d8b8b8dca8]
+
+ * plugins/sudoers/policy.c:
+ Fix handling of timeout values in sudoers. When passing the timeout
+ back to the front end, ignore the user-specified timeout if it is
+ not set (initialized to 0). Otherwise, sudo would choose a zero
+ user-specified timeout over the sudoers-specified timeout (non-
+ zero).
+ [6b08b3b918b7]
+
+2018-10-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers_pwutil.c:
+ Fix cut & pastos in cvtsudoers_make_gritem()
+ [bd901c0394ba]
+
+ * plugins/sudoers/regress/sudoers/test17.ldif2sudo.ok:
+ Fix expected test output now that command_timeout is parsed
+ correctly in LDIF.
+ [ba6cfd26330e]
+
+ * lib/util/event.c, lib/util/event_poll.c, lib/util/event_select.c:
+ tv_nsec can never be negative after timespecsub. Found by PVS Studio
+ [ecfb93c9463c]
+
+2018-10-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.c:
+ Avoid potentially undefined behavior. Found by PVS Studio.
+ [ae76c69e0d6f]
+
+ * plugins/sudoers/ldap_util.c:
+ sudo_ldap_parse_option() never returns '=' as the operator. When
+ parsing command_timeout, role, type, privs and limitprivs, check
+ that val is non-NULL instead. Found by PVS Studio.
+ [10f8cff7cce7]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/toke.c:
+ Fix up #line entries that reference lex.sudoers.c.
+ [c724cef37b66]
+
+2018-10-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog.h, plugins/sudoers/iolog_util.c:
+ Fix workaround for broken sudo 1.8.7 timing files.
+ [78ef3625c650]
+
+ * plugins/sudoers/parse_ldif.c:
+ Fix memory leak when reusing the runas list. We need to free the
+ member list itself as well as its contents.
+ [62fb86a5c83f]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Some DIAGNOSTICS updates: Update error message for when the user's
+ uid does not exist in passwd. Remove "This error indicates" and some
+ other cosmetic cleanups.
+ [c73841e03014]
+
+ * src/sudo.c:
+ If the user's passwd entry cannot be resolved via the uid, use the
+ same error message as visudo.
+ [ce596b32dfbb]
+
+2018-10-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Add a DIAGNOSTICS section with an explanation of the more non-
+ trivial error messages.
+ [775419794f7d]
+
+ * plugins/sudoers/sudoreplay.c, src/exec_monitor.c, src/exec_nopty.c,
+ src/exec_pty.c:
+ Replace sudo_fatal(NULL) with an "unable to allocate memory" message
+ that includes the function name.
+ [26e19bcc0ce8]
+
+2018-10-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in, src/tgetpass.c:
+ Make EOF handling while reading the password prompt more like
+ getpass(3). We now return the password as long as at least one
+ character has been read. Previously, EOF at the password prompt was
+ treated as if nothing was entered.
+ [fc2ed4a87e6f]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in:
+ regen
+ [2aee8680abc3]
+
+ * src/tgetpass.c:
+ Print a warning for password read issues. Issues include: timeout at
+ the password prompt, read error while reading the password, and EOF
+ reading the password.
+ [df1dcebe9ffa]
+
+2018-10-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/term.c, src/tgetpass.c:
+ Handle EOF on password input when pwfedback is enabled.
+ [4958978fc967]
+
+2018-10-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.ldap.mdoc.in:
+ Fix remaining instances of "e.g." without a trailing ','.
+ [8cbf11c04b3c]
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in, doc/sudoers.cat,
+ doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ doc/sudoers_timestamp.cat, doc/sudoers_timestamp.man.in,
+ doc/sudoers_timestamp.mdoc.in:
+ Use mdoc macros for BSD systems. All manuals now pass "make lint"
+ [7f23209a5e1c]
+
+ * doc/Makefile.in:
+ Use -Wstyle with -Tlint since sudo is not part of the base system.
+ This avoids "referenced manual not found" and "operating system
+ explicitly specified" warnings.
+ [e417e972a88a]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in:
+ Document log_suspend() and fix the description of the
+ change_winsize() return value.
+ [be02b0fb26a9]
+
+2018-10-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.cat, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in, doc/sudoers_timestamp.cat,
+ doc/sudoers_timestamp.man.in, doc/sudoers_timestamp.mdoc.in,
+ doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in,
+ doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in:
+ Fix problems found by igor. Bug #854
+ [4ddcb625f3b7]
+
+ * doc/Makefile.in:
+ Sort DOCS and DEVDOCS and remove extra sudoers entry (it was listed
+ twice).
+ [abb2baac9373]
+
+ * doc/Makefile.in:
+ Add igor target to run igor(1) on the manuals.
+ [64be7fb868b3]
+
+2018-10-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in,
+ plugins/sudoers/sudoreplay.c:
+ Add new -S option to sleep while the command was suspended. The
+ default behavior is now to not consider the time the command was
+ suspended as part of the normal inter-event delay.
+ [bb30f7b28126]
+
+ * MANIFEST, include/sudo_plugin.h, plugins/sudoers/Makefile.in,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog.h,
+ plugins/sudoers/iolog_event.h, plugins/sudoers/iolog_files.h,
+ plugins/sudoers/iolog_util.c, plugins/sudoers/iolog_util.h,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/regress/iolog_util/check_iolog_util.c,
+ plugins/sudoers/sudoreplay.c, src/exec_pty.c:
+ Add a suspend event type to the I/O log to log suspend/resume of the
+ command so we can skip that delay during replay.
+ [8091d1835a31]
+
+ * src/exec_pty.c, src/sudo.c, src/sudo.h:
+ Initialize the pty rows/cols based on the values we stored in
+ user_details. This fixes a minor issue where we would send an extra
+ window size change event the first time the command was suspended.
+ [b2ae9be4d1d6]
+
+2018-09-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in, plugins/sudoers/ldap_conf.c,
+ plugins/sudoers/sudo_ldap_conf.h:
+ Add support for OpenLDAP's TLS_REQCERT setting in ldap.conf.
+ [f07a14ae05cb]
+
+2018-09-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_util.h, plugins/sudoers/defaults.c,
+ plugins/sudoers/iolog_util.c,
+ plugins/sudoers/regress/starttime/check_starttime.c:
+ Move definition of TIME_T_MAX to sudo_util.h
+ [469c36d44950]
+
+ * NEWS, doc/UPGRADE:
+ Changes in 1.8.26 (so far).
+ [5c73b0d8c676]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/env.c:
+ Treat LOGIN, LOGNAME and USER specially. If one is preserved or
+ deleted we want to preserve or delete all of them.
+ [ea1782686195]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/env.c,
+ plugins/sudoers/logging.c, plugins/sudoers/regress/visudo/test6.sh:
+ Remove special handling of the USERNAME environment variable. It
+ used to be set on old versions of Fedora but that hasn't been the
+ case for some time. It's worth noting that ssh doesn't set USERNAME
+ either.
+ [5141bebd99c4]
+
+ * configure, configure.ac:
+ sudo 1.8.26
+ [cfe8d540328e]
+
+2018-09-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sudo.c:
+ Remove unused system_maxgroups argument from fill_group_list().
+ [debc4ca9d35f]
+
+ * lib/util/getgrouplist.c:
+ Pass getgrouplist() NGROUPS_MAX+1, not NGROUPS_MAX so we have room
+ for the primary gid.
+ [fccf07f2e8cf]
+
+2018-09-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers_json.c:
+ In print_member_json_int() eliminate the need_newline variable and
+ just move the non-alias expansion printing bits into the else
+ clause, including the newline and comma printing.
+ [b40224fc6090]
+
+ * MANIFEST, plugins/sudoers/regress/cvtsudoers/test30.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test30.sh:
+ Add regress test for bug #853
+ [31544afc6013]
+
+ * plugins/sudoers/cvtsudoers_json.c:
+ When expanding an alias in print_member_json_int() avoid printing an
+ extra comma at the end of the entry. Bug #853.
+ [e73e09f8569a]
+
+2018-09-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/CONTRIBUTORS:
+ Add Kan Sasaki
+ [ff277fb5b0c9]
+
+ * NEWS, configure, configure.ac:
+ sudo 1.8.25p1
+ [c4f0a69e6356]
+
+ * lib/util/event_poll.c:
+ Fix a crash in the event system's poll() backend introduced with
+ support for nanosecond timers. Only affects systems without ppoll().
+ Bug #851
+ [54e561b11a0f]
+
+2018-09-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [04afa00445ef]
+
+2018-08-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c:
+ Allow for some clock drift due to ntpd, etc.
+ [2d72989fe7b1]
+
+ * plugins/sudoers/visudo.c:
+ If sudo_lock_file() fails for a reason other than the file already
+ being locked, give the user a chance to edit anyway.
+ [e5a963ecc083]
+
+2018-08-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/cvtsudoers/test28.sh:
+ Quick sort is not a stable sort; use distinct sudoOrder values so
+ the output is predictable.
+ [46ebc1169c0c]
+
+ * lib/util/regress/atofoo/atofoo_test.c,
+ lib/util/regress/parse_gids/parse_gids_test.c,
+ plugins/sudoers/ldap.c,
+ plugins/sudoers/regress/parser/check_base64.c:
+ Fix warnings on OpenIndiana (Illumos)
+ [1b45d303b338]
+
+ * plugins/sudoers/ldap.c:
+ Correct ldap_to_sudoers() return value.
+ [16b0d144b196]
+
+ * NEWS:
+ Bug #849
+ [3e05bad00a44]
+
+ * plugins/sudoers/sssd.c:
+ The sssd backend used to take the first match, assuming that entries
+ were sorted in descending order by sudoOrder. That allowed it to
+ avoid iterating over the entire list of rules. Now that we convert
+ to a sudoers parse tree, we need to convert rules in ascending
+ order, not descending. The simplest way to accomplish this is to
+ simply iterate over the rules from last to first, reversing the sort
+ order. Bug #849
+ [63627909bb10]
+
+ * MANIFEST, plugins/sudoers/regress/cvtsudoers/test28.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test28.sh,
+ plugins/sudoers/regress/cvtsudoers/test29.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test29.sh:
+ Add some more ldif -> sudoers tests to verify sudoOrder.
+ [f41358fbd066]
+
+ * plugins/sudoers/ldap.c:
+ For conversion to a sudoers parse tree, ldap_entry_compare() now
+ needs to sort in ascending order, not descending. Bug #849
+ [9f23126cded8]
+
+2018-08-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers.c:
+ No need to set input_file for stdin in parse_ldif(); noted by clang
+ analyzer.
+ [c852e1c92dd2]
+
+ * plugins/sudoers/iolog_util.c:
+ Use TIME_T_MAX when parsing the I/O log file timestamp and disallow
+ negative times.
+ [bfb17118e584]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/iolog_util.c,
+ plugins/sudoers/iolog_util.h,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/regress/iolog_util/check_iolog_util.c,
+ plugins/sudoers/sudoreplay.c:
+ When parsing an I/O log timing line, store the result in a timespec,
+ not a double. The speed factor (for scaling the delay) in sudoreplay
+ is still a double but we only need to adjust the delay if the factor
+ is something other than 1.0.
+ [39077129d1f9]
+
+ * plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c:
+ Fix memory leak in test.
+ [94fb9f39dfee]
+
+ * doc/cvtsudoers.cat, doc/sudo.cat, doc/sudo.conf.cat,
+ doc/sudo_plugin.cat, doc/sudoers.cat, doc/sudoers.ldap.cat,
+ doc/sudoers_timestamp.cat, doc/sudoreplay.cat, doc/visudo.cat:
+ regen
+ [f2850c2f733a]
+
+2018-08-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/env.c:
+ Update conversion of DID_* to KEPT_* to match the new values of
+ DID_* and KEPT_*.
+ [6ce1bc30a4d1]
+
+ * NEWS, plugins/sudoers/env.c:
+ Set the LOGIN environment variable on AIX like we do LOGNAME.
+ [e6afb82d918c]
+
+2018-08-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, m4/sudo.m4,
+ plugins/sudoers/bsm_audit.c:
+ Add a test for the 4-argument au_close() function found in Solaris
+ 11 instead of assuming it is present if __sun is defined. Fixes a
+ compilation error on OpenIndiana and older Solaris versions.
+ [4a4f91e28bbc]
+
+ * doc/CONTRIBUTORS:
+ Add Miguel Sanders and Scott Cheloha
+ [14aca7309a0a]
+
+ * NEWS:
+ testsudoers changes
+ [f008d473c933]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/testsudoers.c:
+ Add ldif support to testsudoers
+ [321f11b7badd]
+
+2018-08-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers.h, plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/parse.h, plugins/sudoers/parse_ldif.c:
+ Move ldif -> sudoers conversion code into parse_ldif.c
+ [497d55799d5b]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers.h, plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/strlist.c,
+ plugins/sudoers/strlist.h:
+ Move string list functions to their own file.
+ [a15902cde4eb]
+
+ * lib/util/Makefile.in:
+ sync
+ [9b1f98d4335f]
+
+2018-08-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_event.h, lib/util/event.c, lib/util/util.exp.in:
+ Backward ABI compatibility for even functions that use a timeval.
+ [01d9e617a923]
+
+ * lib/util/event.c, lib/util/event_poll.c, lib/util/event_select.c:
+ Use a monotonic timer for the event subsystem.
+ [acf30905a275]
+
+ * config.h.in, configure, configure.ac, include/sudo_event.h,
+ lib/util/event.c, lib/util/event_poll.c, lib/util/event_select.c,
+ plugins/sudoers/iolog_util.h, plugins/sudoers/sudoers.h,
+ plugins/sudoers/sudoreplay.c:
+ Use struct timespec, not struct timeval in the event subsystem. Use
+ ppoll() or pselect() if avaialble which use timespec.
+ [b1bfccec8b13]
+
+2018-08-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgignore:
+ sync
+ [193fd33e9864]
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers.h,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c:
+ Eliminate most use of parsed_sudoers in cvtsudoers
+ [0d0504f61e3e]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers_json.c, plugins/sudoers/parse.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Make alias_apply() take 3 arguments, the first being a pointer to
+ the struct sudoers_parse_tree.
+ [7802295c07fa]
+
+2018-08-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c:
+ Handle systems where root's gid is not 0.
+ [1fc92bad715a]
+
+ * plugins/sudoers/iolog_util.c, plugins/sudoers/iolog_util.h:
+ Add missing files from last commit.
+ [a155e07bb191]
+
+ * .hgignore, MANIFEST, plugins/sudoers/Makefile.in,
+ plugins/sudoers/po/sudoers.pot,
+ plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c,
+ plugins/sudoers/sudoreplay.c:
+ Add regress test for I/O log plugin endpoints
+ [bf9fbe5ff2a6]
+
+ * plugins/sudoers/iolog.c:
+ We cannot reuse last_time for the I/O log info file now that it is a
+ monotonic timer. Just call time(3) in write_info_log() directly.
+ [f2e1de732a91]
+
+ * src/exec_pty.c:
+ Move the loop to free the monitor_messages list into
+ free_exec_closure_pty()
+ [d6edc1a94e7e]
+
+ * po/sudo.pot:
+ regen
+ [6467f05a2fd0]
+
+2018-08-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * lib/util/getentropy.c:
+ Fix typo in last commit.
+ [38f3450b57fb]
+
+ * config.h.in, configure, configure.ac, lib/util/getentropy.c:
+ Do not assume all Linux has linux/random.h. Add missing
+ sys/syscall.h include
+ [8460f258e1af]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/visudo.c, src/sudo_edit.c:
+ Cast uid/gid to unsigned int before printing.
+ [37fcab8b4f97]
+
+ * include/sudo_compat.h:
+ Only include stdarg.h if we need it.
+ [c266d34454ba]
+
+ * plugins/sudoers/bsm_audit.c, plugins/sudoers/timestamp.c:
+ fix compiler warnings on Solaris 11
+ [6c92c438a38e]
+
+ * lib/util/getentropy.c:
+ Fix setting of errno when gotdata() fails.
+ [4fab71fa575f]
+
+ * plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/rcstr.c, plugins/sudoers/timestamp.c,
+ src/sudo_noexec.c:
+ Include stddef.h for offsetof() definition.
+ [15d13ae1ba46]
+
+ * NEWS:
+ Bugs 846 and 847
+ [a0ba7ad24812]
+
+ * include/sudo_compat.h:
+ We still need to include string.h for AIX (and possibly others) when
+ we are not using the system memset_r() function and rsize_t is
+ defined by the system headers.
+ [e1f8f7537209]
+
+ * configure, configure.ac, include/sudo_compat.h, mkpkg:
+ Add --enable-package-build to give configure a hint that we are
+ building a package. This can be used to avoid relying on libc
+ functions that may not be present in all libc versions for a
+ particular system. For instance, AIX 7.1 may or may not have
+ memset_s() and getline() present.
+ [7e843bed8435]
+
+ * include/sudo_compat.h:
+ AIX defines rsize_t in string.h, not stddef.h for use by the
+ memset_s() prototype. We use our own memset_s() on AIX since it is
+ not available on all BOS levels which makes package building
+ problematic.
+ [3724b47eadd8]
+
+2018-08-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/defaults.c:
+ Fix printing of T_TIMESPEC values.
+ [8775c17229a4]
+
+ * plugins/sudoers/iolog.c:
+ Remove unused struct script_buf
+ [fd27f67123b3]
+
+2018-08-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Document when the I/O log timing file entry bug was introduced.
+ [09a75d80487e]
+
+ * NEWS:
+ sync
+ [95fd54c61719]
+
+ * config.h.in, configure, configure.ac, lib/util/gettime.c:
+ HP-UX doesn't suport CLOCK_MONOTONIC but we can use gethrtime()
+ instead.
+ [3ec7d99444c0]
+
+ * src/exec_monitor.c, src/exec_pty.c:
+ Close the pty slave in the parent so that when the command and
+ monitor exit, the pty gets recycled without our having to close it
+ directly.
+ [fec53753cf52]
+
+ * lib/util/term.c, src/exec_monitor.c, src/exec_pty.c, src/sudo.h:
+ Move updating of the window size to the monitor process. This will
+ allow us to close the slave in the main sudo process in the future
+ so only the command and monitor have it open.
+ [07108a1c2edc]
+
+ * configure, configure.ac:
+ sudo 1.8.25
+ [4938ba570787]
+
+ * plugins/sudoers/regress/sudoers/test19.ldif2sudo.ok:
+ Fix test output for bug #845
+ [ee6f2d615bd8]
+
+ * plugins/sudoers/ldap_util.c:
+ Fix pasto when converting sudoNotAfter; from Miguel Sanders Bug #845
+ [69638cd6da60]
+
+2018-08-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * aclocal.m4, config.h.in, configure, configure.ac,
+ include/sudo_util.h, lib/util/gettime.c, lib/util/util.exp.in:
+ Add sudo_gettime_uptime() to measure time while not sleeping.
+ [a128e7d51740]
+
+ * plugins/sudoers/iolog.c:
+ Use a monotonic timer that only runs while not suspended for the
+ iolog timing values and write nsec-precision entries.
+ [7f37f0b24ce7]
+
+2018-08-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * mkpkg:
+ Detect number of CPUs on AIX.
+ [2b7c62b42da2]
+
+ * plugins/sudoers/iolog.c:
+ Fix I/O log timing file on systems without a C99-compatible
+ snprintf(). On those systems we use our own snprintf() that doesn't
+ support floating point. We don't actually need floating point in
+ this case since the we can print seconds and microseconds without
+ using it.
+ [4ea419ac5bee]
+
+ * NEWS:
+ Fix for Bug #844
+ [51cfeb79669c]
+
+ * src/sudo_edit.c:
+ Handle the case where O_PATH or O_SEARCH is defined but O_DIRECTORY
+ is not. In theory, O_DIRECTORY is redundant when O_SEARCH is
+ specified but it is legal for O_EXEC and O_SEARCH to have the same
+ value. Bug #844
+ [fb75d75c7249]
+
+2018-08-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ sync
+ [2be1b619a06a]
+
+ * plugins/sudoers/starttime.c:
+ Fix get_starttime() on HP-UX.
+ [329a4ad9f4ef]
+
+ * mkpkg:
+ Detect number of CPUs on HP-UX. Use MAKE environment variable if
+ set.
+ [c95ab5d6d392]
+
+ * src/net_ifs.c:
+ Avoid a compilation problem on HP-UX 11.31 with gcc and
+ machine/sys/getppdp.h
+ [b861e894271b]
+
+2018-08-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/Makefile.in:
+ Add CHECK_SYMBOLS_LDFLAGS to check_symbols target. Non-ELF HP-UX
+ executables don't support SHLIB_PATH or LD_LIBRARY_PATH unless ld is
+ passed the +s flag. This lets the check_symbols test pass on systems
+ where the ldap libraries aren't installed in the standard location.
+ [c2d6d3248fa4]
+
+2018-08-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/Makefile.in:
+ For the lint target, don't stop after the first manual that fails
+ lint.
+ [8a80d8e7b540]
+
+ * plugins/sudoers/timestamp.c:
+ Add debugging info so we can tell why a timestamp record doesn't
+ match.
+ [99ede76f9835]
+
+2018-08-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ typo
+ [8a5a11b921ea]
+
+ * plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po, po/da.mo,
+ po/da.po:
+ sync with translationproject.org
+ [19f7eba39013]
+
+2018-08-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/iolog.c:
+ Fix the return value of sudoers_io_change_winsize() on success.
+ Otherwise, we only log a single window size change.
+ [d6cdab99f6f9]
+
+ * plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po:
+ sync with translationproject.org
+ [4109b52f393f]
+
+2018-08-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ sync
+ [1448675b44aa]
+
+2018-08-07 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Fix ambiguity when talking about Aliases. We can't use User_Alias in
+ the grammar as both the definition of the Alias as well as its name.
+ This adds {User,Runas,Host,Cmnd}_Alias_Spec to help differentiate
+ between the name of the alias and its definition. Bug #834
+ [06678d12306f]
+
+ * doc/cvtsudoers.cat, doc/sudoreplay.cat:
+ regen
+ [d7237381675a]
+
+ * Makefile.in:
+ Warn if unable to run xgettext or msgfmt.
+ [d0cbba35cd49]
+
+2018-08-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/hr.mo,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/ja.mo,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pt_BR.mo,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/uk.mo,
+ plugins/sudoers/po/vi.mo:
+ sync with translationproject.org
+ [d1deb5cb5eb3]
+
+2018-08-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/fmtsudoers.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/ldap_util.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h, plugins/sudoers/policy.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Refactor code to convert defaults to tags and do conversion on
+ output for "sudo -l".
+
+ Remove the short_list (was long_list) global in favor of a verbose
+ argument.
+ [eae1e1e814e0]
+
+2018-08-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/policy.c:
+ Assign short_list true, not 1 now that it is a boolean.
+ [10354cd29439]
+
+ * plugins/sudoers/fmtsudoers.c:
+ fix typo
+ [ad7e93f375ba]
+
+2018-08-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/rcstr.c:
+ Fix a warning on FreeBSD which has a fancier __containerof
+ implementation.
+ [b5106a524232]
+
+ * plugins/sudoers/po/de.po, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/it.po, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/pl.po, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/sv.po, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.po:
+ sync with translationproject.org
+ [ae5353cbeac4]
+
+2018-08-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * aclocal.m4, autogen.sh, config.h.in, configure:
+ Regen with aclocal 1.15.1.
+ [22c02e451333]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/parse.c,
+ plugins/sudoers/policy.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ For ldap/sssd, include defaults in the generate privilege unless we
+ are listing in short mode (in which case we convert them to tags if
+ possible). Fixes a problem where sudoOptions were not being applied
+ to the command.
+ [b21267488971]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/parse.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ update_defaults() needs to be able to take a defaults_list for the
+ ldap/sssd backends which support per-role defaults.
+ [ddbb07881a46]
+
+2018-07-31 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [29c5a09aaeaf]
+
+2018-07-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Update
+ [045b535f84b9]
+
+2018-07-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/alias.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/defaults.h, plugins/sudoers/file.c,
+ plugins/sudoers/fmtsudoers.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/ldap.c,
+ plugins/sudoers/match.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudo_nss.h, plugins/sudoers/sudoers.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ o Move userspecs, defaults and aliases into a new struct
+ sudoers_parse_tree. o The parse tree is now passed to the alias,
+ match and defaults functions. o The nss API has been changed so that
+ the nss parse() function returns a pointer to a struct
+ sudoers_parse_tree which will be filled in by the getdefs() and
+ query() functions.
+ [bddb4676ad0e]
+
+ * lib/util/getgrouplist.c:
+ Don't need to preallocate 4 x NGROUP_MAX on AIX or BSD/Linux. For
+ BSD/Linux, getgrouplist(3) will tell us the number of groups if we
+ don't have enough. For AIX, we can count the entries in the group
+ set before allocating the group vector.
+ [c278fd947af4]
+
+ * plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/auth/sudo_auth.h,
+ plugins/sudoers/check.c, plugins/sudoers/sudoers.h:
+ Ignore PAM_NEW_AUTHTOK_REQD and PAM_AUTHTOK_EXPIRED errors from
+ pam_acct_mgmt() if authentication is disabled for the user. Bug #843
+ [1dc39794cf0d]
+
+2018-07-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_pty.c:
+ Work around a bug on AIX where closing the pty slave causes the main
+ sudo process to lose its controlling tty (which was *not* the pty
+ slave).
+ [649a25b7f864]
+
+ * src/sudo.c:
+ Add missing aix_restoreauthdb() call to match the aix_setauthdb()
+ added in b8a011be9af7. Fixes issues on AIX where local users/groups
+ may not be resolved when some NIS/AD/LDAP is used for users.
+ [16e196a7a337]
+
+ * lib/util/getgrouplist.c:
+ Linux getgrouplist(3) returns the number of groups on success
+ instead of 0 like BSD.
+ [599a89afa4f5]
+
+2018-07-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * mkdep.pl, plugins/sudoers/Makefile.in:
+ When both a .o and .lo file was used in a Makefile, we used to make
+ the .o depend on the .lo. Unfortunately, this creates a race
+ condition for parallel make since libtool is not atomic (it creates
+ a .o and then renames it when building PIC objects for shared libs).
+
+ We always link with libtool so the only reason to prefer the .o over
+ the .lo file is to avoid mixing .o and .lo in the dependencies.
+ That's not a good enough reason so change mkdep.pl to warn when both
+ a .o and .lo are referenced in a Makefile and do nothing else.
+
+ Bug #842
+ [a8d94e6aed9f]
+
+2018-07-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/ldap.c:
+ Avoid duplicate free when netgroup_base is invalid.
+ [5ce39dff77ba]
+
+2018-07-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/arc4random.h:
+ Use madvise(2) with MADV_WIPEONFORK if available.
+ [a11461409569]
+
+2018-07-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po, po/eo.mo,
+ po/eo.po:
+ sync with translationproject.org
+ [01bcfe7b30e5]
+
+ * NEWS:
+ Update.
+ [f5e0b1f909bb]
+
+2018-06-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ sync with schema.OpenLDAP
+ [d83420d8228d]
+
+ * doc/schema.OpenLDAP:
+ RFC 2849 specifies whitespace as the space character only so replace
+ tabs with spaces. Bug #840
+ [e9d5de6365ba]
+
+ * doc/schema.OpenLDAP:
+ Fix typo; bug #839
+ [dee2dad738de]
+
+2018-06-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo.conf.cat, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in:
+ Should no longer need to set max_groups.
+ [459119b11265]
+
+2018-06-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/pwutil_impl.c,
+ src/sudo.c:
+ Use new sudo_getgrouplist2() function instead of getgrouplist().
+ [8e88b6d3ea6f]
+
+ * configure, configure.ac, include/sudo_compat.h, include/sudo_util.h,
+ lib/util/Makefile.in, lib/util/getgrouplist.c, lib/util/util.exp.in:
+ Add sudo_getgrouplist2() to dynamically allocate the group vector.
+ This allows us to avoid repeatedly calling getgrouplist() with a
+ statically sized vector on macOS, Solaris, HP-UX, and AIX.
+ [55480e2ec7c2]
+
+ * src/conversation.c:
+ Fix fd leak introduced by SUDO_CONV_PREFER_TTY commit. Coverity CID
+ 186605.
+ [fb6eb518bc4c]
+
+2018-06-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in, doc/sudoers.cat,
+ doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ doc/sudoers_timestamp.cat, doc/sudoers_timestamp.man.in,
+ doc/sudoers_timestamp.mdoc.in, doc/visudo.cat, doc/visudo.man.in,
+ doc/visudo.mdoc.in:
+ Fix some issues pointed out by mandoc -Tlint
+ [7ace981c7334]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, include/sudo_plugin.h, src/conversation.c:
+ Add SUDO_CONV_PREFER_TTY flag for conversation function to tell sudo
+ to try writing to /dev/tty first. Can be used in conjunction with
+ SUDO_CONV_INFO_MSG and SUDO_CONV_ERROR_MSG.
+ [a1e9420a7c5e]
+
+2018-06-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/LICENSE:
+ Update for arc4random.c, arc4random_uniform.c and getentropy.c
+ [168db3c8d590]
+
+2018-06-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/regress/noexec/check_noexec.c:
+ FreeBSD wordexp() returns WRDE_SYNTAX if it can't write to the shell
+ process. Since we've prevented execve() from succeeding this is the
+ error we get back from wordexp() on FreeBSD.
+ [2a7a73de30cf]
+
+2018-06-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/starttime.c:
+ Fix conversion of usec to nsec; from Scott Cheloha
+ [26fa756ea623]
+
+2018-06-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * include/sudo_plugin.h:
+ Fix typo.
+ [504256dc4ccc]
+
+2018-05-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ The getdefs() function now get called multiple times so use the
+ cached data if present.
+ [042be7ccab3c]
+
+ * plugins/sudoers/sssd.c, plugins/sudoers/sudoers.c:
+ Return an empty defaults list, not NULL if there is no global
+ sudoers defaults entry in sss.
+ [8e16de465ee2]
+
+ * plugins/sudoers/file.c:
+ Fix memory leak of handle pointer on close.
+ [e4eb30e611d4]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Remove a needless copy when parsing options.
+ [60fe50b736a9]
+
+ * plugins/sudoers/file.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/parse.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudo_nss.h,
+ plugins/sudoers/sudoers.c:
+ Move cached userspecs and defaults into the handle object.
+ [37e4df73907d]
+
+2018-05-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Quiet a clang analyzer warning. It should not be possible for
+ pop_include() to be called when YY_CURRENT_BUFFER is NULL.
+ [148d79e5a44e]
+
+ * plugins/sudoers/file.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/sssd.c:
+ Reorder things to avoid the need to declare static functions.
+ [8f27e69fa9cb]
+
+2018-05-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, config.h.in, configure, configure.ac, include/sudo_rand.h,
+ lib/util/Makefile.in, lib/util/arc4random.c, lib/util/arc4random.h,
+ lib/util/arc4random_uniform.c, lib/util/chacha_private.h,
+ lib/util/getentropy.c, lib/util/util.exp.in, mkdep.pl:
+ Import arc4random() from libressl. This takes an all-in-one approach
+ instead of the one-file-per-OS approach that libressl takes. The
+ fallback code does not have as many OS-specific bits as libressl.
+ [310d65e466bd]
+
+ * lib/util/Makefile.in, lib/util/mktemp.c,
+ plugins/sudoers/Makefile.in, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/insults.h:
+ Use arc4random for mkstemp() and insults.
+ [b8c7447756f2]
+
+ * MANIFEST, configure, configure.ac, include/sudo_digest.h,
+ lib/util/Makefile.in, lib/util/digest.c, lib/util/digest_gcrypt.c,
+ lib/util/digest_openssl.c, lib/util/util.exp.in, mkdep.pl,
+ plugins/sudoers/Makefile.in, plugins/sudoers/digestname.c,
+ plugins/sudoers/filedigest.c, plugins/sudoers/filedigest_gcrypt.c,
+ plugins/sudoers/filedigest_openssl.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.h, plugins/sudoers/gram.y,
+ plugins/sudoers/ldap_util.c, plugins/sudoers/match.c,
+ plugins/sudoers/parse.h,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/sudo_ldap.h, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l:
+ Move digest code into libutil
+ [c53cf5c508eb]
+
+2018-05-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/regress/cvtsudoers/test25.sh,
+ plugins/sudoers/regress/cvtsudoers/test26.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test26.sh,
+ plugins/sudoers/regress/cvtsudoers/test27.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test27.sh:
+ Check for invalid bas64 attributes.
+ [4218d11c8205]
+
+ * plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/regress/parser/check_base64.c:
+ Fix pointer sign warnings.
+ [5ee724e3956e]
+
+ * plugins/sudoers/cvtsudoers_ldif.c:
+ Add missing variable declaration for SELinux and Solaris.
+ [c8084f0508e5]
+
+ * plugins/sudoers/cvtsudoers_ldif.c:
+ Handle empty string and treat it as safe.
+ [8029b97d8f4a]
+
+ * MANIFEST, plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/regress/cvtsudoers/test26.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test26.sh:
+ Add support for base64-encoding non-safe strings in LDIF output.
+ [b9fd1795f4ee]
+
+2018-05-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/base64.c, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/parser/check_base64.c:
+ Add base64_encode() by Jon Mayo.
+ [a893ec3dc667]
+
+2018-05-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/regress/cvtsudoers/test25.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test25.sh:
+ Add support for parsing base64-encoded attributes
+ [262dd9a526de]
+
+2018-05-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/regress/sudoers/test2.ldif.ok:
+ rfc2253 says we need to escape " and leading and trailing space.
+ [1c0105a5eb1b]
+
+ * configure, configure.ac:
+ Define ZLIB_CONST so we get the const version of the API.
+ [71a629d0eb4b]
+
+2018-05-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/parse.c:
+ Fix logic inversion when handing the authenticate Defaults option
+ for "sudo -l" and "sudo -v" in long list mode.
+ [f8157d4c4f03]
+
+ * plugins/sudoers/sssd.c:
+ Set handle->pw before sss_to_sudoers() since sss_check_user() uses
+ it. Coverity CID 185651
+ [fa646e569352]
+
+ * plugins/sudoers/ldap_util.c:
+ Fix memory leak on error, CID 185602
+ [31c1ab085985]
+
+ * plugins/sudoers/ldap.c:
+ Some ldap_get_values_len -> sudo_ldap_get_values_len that were
+ missed before.
+ [d7f1877531be]
+
+ * plugins/sudoers/ldap_util.c:
+ When building up the cmndspec, add the actual command member last.
+ This simplifies the logic regarding the SETENV tag and alsomakes
+ "out of memory" cleanup simpler.
+ [d704f3b09ac1]
+
+ * plugins/sudoers/cvtsudoers_ldif.c:
+ Fix format string mismatch, sudo_order is unsigned.
+ [ecc398e45b0a]
+
+ * plugins/sudoers/pwutil.c:
+ Add cppcheck annotation to suppress memory leak false positive.
+ [d4a0ae57c372]
+
+ * plugins/sudoers/ldap_util.c:
+ Sudo "ALL" implies the SETENV tag.
+ [7abc653b4d39]
+
+ * src/parse_args.c:
+ Only set MODE_PRESERVE_ENV when preserving the entire environment.
+ Fixes a problem introduced in 1.8.23 where "sudo -i" could not be
+ used in conjunction with --preserve-env=VARIABLE. Bug #835
+ [8ea75ca8fbd2]
+
+2018-05-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/file.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/ldap.c,
+ plugins/sudoers/parse.h, plugins/sudoers/sssd.c:
+ Add free_userspecs() and free_default() and use them instead of
+ looping over the lists and calling free_userspec() and
+ free_default().
+ [797221539242]
+
+ * configure, configure.ac:
+ Depending on the bos level, AIX 6.1 may or may not include
+ getline/getdelim and AIX 7.1 may or may not include memset_s. Since
+ we need to build packages that will work on all AIX 6.1 and 7.1
+ machines, use our getline() and memset_s emulation.
+ [f5c427076b2c]
+
+2018-05-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/ldap_util.c:
+ Do not leak struct sudo_command when the command is ALL. Coverity
+ CID 185602.
+ [d71ca4bc06bc]
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.8.24
+ [7df3df9a3907]
+
+ * plugins/sudoers/sssd.c:
+ Improve comments about why we need to do a user check and how it
+ related to netgroups.
+ [605234ed0935]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Add checks for ldap/sss functions failing due to memory allocation
+ errors.
+ [0dfeb0d8ecf5]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Let the main sudoers lookup code check the host name. We still check
+ the user name so it is possible to use a single userspec but this
+ may change in the future.
+ [a74699b90213]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/defaults.h, plugins/sudoers/file.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/ldap_util.c,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudo_ldap.h,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudo_nss.h,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Simplify the nss interface such that each sudoers provider fills in
+ a per-nss list of userspecs and defaults instead of using separate
+ lookup and list functions. This makes it possible to have a single
+ implementation of the code for sudoers lookup and listing.
+ [50de9302de01]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/filedigest.c, plugins/sudoers/filedigest_gcrypt.c,
+ plugins/sudoers/filedigest_openssl.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/ldap.c, plugins/sudoers/ldap_conf.c,
+ plugins/sudoers/ldap_util.c, plugins/sudoers/match.c,
+ plugins/sudoers/parse.c, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/parser/check_addr.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/visudo.c:
+ Include parse.h in sudoers.h since it will soon be required.
+ [196abb590d96]
+
+ * plugins/sudoers/ldap_util.c:
+ Parse "ALL" as a command correctly.
+ [d969e7dfdbbc]
+
+2018-05-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/match.c:
+ Add debug warning if lseek() fails (should not be possible).
+ [d568dc923c7d]
+
+ * plugins/sudoers/match.c:
+ Fix swapped args of lseek() when rewinding. This didn't cause a
+ problem because the value of SEEK_SET is 0.
+ [142591a3f333]
+
+2018-05-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/parser/check_hexchar.c:
+ Fix a format-truncation warning in newer gcc by avoiding using %0x
+ and %0X in the test. We are formatting a single byte so just do it
+ one nybble at a time.
+ [7c594a63598f]
+
+ * configure:
+ Regen with autoconf git commit
+ e17a30e987d7ee695fb4294a82d987ec3dc9b974 AC_HEADER_MAJOR: port to
+ glibc 2.25
+ [9fe77765c768]
+
+2018-05-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers_ldif.c:
+ No need to explicitly free role on EOF, it will be freed after the
+ loop is done.
+ [8d08c06b7622]
+
+ * plugins/sudoers/policy.c:
+ Garbage collect the command argv, envp and info vectors since they
+ are not available at policy close time.
+ [de22290a8ec5]
+
+ * plugins/sudoers/cvtsudoers_ldif.c:
+ Plug memory leaks on parse error or when an LDIF entry doesn't match
+ the dn filter.
+ [4f48e740eed1]
+
+ * plugins/sudoers/cvtsudoers.c:
+ Rename variables now that the string list functions are not ldap-
+ specific.
+ [640497f70551]
+
+2018-04-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ Fix typo
+ [6466295ba962]
+
+2018-04-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * configure, configure.ac:
+ fix version
+ [bfed601130b5]
+
+ * NEWS:
+ sync
+ [1c382f2aff27]
+
+ * configure, configure.ac, plugins/sudoers/po/zh_CN.mo,
+ plugins/sudoers/po/zh_CN.po, po/zh_CN.mo, po/zh_CN.po:
+ sync with translationproject.org
+ [ec28ff5acbd6]
+
+2018-04-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/match.c:
+ O_EXEC for fexecve() not O_SEARCH.
+ [a156d8b38f31]
+
+ * doc/TROUBLESHOOTING:
+ Document how to suppress the last login message on Solaris.
+ [2926b670aca4]
+
+2018-04-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers_json.c:
+ Fix compilation error with older Sun Studio compilers.
+ [0f735611642d]
+
+ * NEWS:
+ Update Bug #831 decription.
+ [d5e6a2a807b8]
+
+ * MANIFEST, doc/CONTRIBUTORS, po/zh_TW.mo, po/zh_TW.po:
+ Add Chinese(Taiwan) translation for sudo.
+ [5a4ba6769cca]
+
+ * plugins/sudoers/match.c:
+ Move the check for /dev/fd/N until *after* the digest has been
+ checked. We still need to be able to check the digest even if there
+ is no /dev/fd/N or fexecve().
+ [e0e086b4e764]
+
+2018-04-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/match.c:
+ Rewind the fd after calling sudo_filedigest(). Otherwise, when
+ running a script via fexecve(), the interpreter may get EOF when
+ reading /dev/fd/N. This only appears to affect BSD systems with
+ fdescfs. Bug #831.
+ [d79f5125cc73]
+
+ * plugins/sudoers/match.c:
+ In open_cmnd(), return true, not false, if we the /dev/fd/N pathname
+ is not present. We don't want to fail a match because of this.
+ [72c4b499c019]
+
+ * NEWS:
+ Bug #831.
+ [700646725f45]
+
+ * plugins/sudoers/match.c:
+ We can only use fexecve() on a script if /dev/fd/N exists. Some
+ systems, such as FreeBSD, don't have /dev/fd mounted by default. Bug
+ #831
+ [30f7c5d64104]
+
+2018-04-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/ca.mo, plugins/sudoers/po/ca.po,
+ plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/el.mo, plugins/sudoers/po/el.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/eu.mo, plugins/sudoers/po/eu.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/fur.mo, plugins/sudoers/po/fur.po,
+ plugins/sudoers/po/hu.mo, plugins/sudoers/po/hu.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/lt.mo, plugins/sudoers/po/lt.po,
+ plugins/sudoers/po/nl.mo, plugins/sudoers/po/nl.po,
+ plugins/sudoers/po/ru.mo, plugins/sudoers/po/ru.po,
+ plugins/sudoers/po/sk.mo, plugins/sudoers/po/sk.po,
+ plugins/sudoers/po/sl.mo, plugins/sudoers/po/sl.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po,
+ plugins/sudoers/po/tr.mo, plugins/sudoers/po/tr.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po, po/ca.mo,
+ po/ca.po, po/da.mo, po/da.po, po/de.mo, po/de.po, po/eo.mo,
+ po/eo.po, po/es.mo, po/es.po, po/eu.mo, po/eu.po, po/fi.mo,
+ po/fi.po, po/fur.mo, po/fur.po, po/gl.mo, po/gl.po, po/hu.mo,
+ po/hu.po, po/ko.mo, po/ko.po, po/nl.mo, po/nl.po, po/nn.mo,
+ po/nn.po, po/ru.mo, po/ru.po, po/sk.mo, po/sk.po, po/sl.mo,
+ po/sl.po, po/sr.mo, po/sr.po, po/vi.mo, po/vi.po, po/zh_CN.mo,
+ po/zh_CN.po:
+ sync with translationproject.org
+ [a786a841f30a]
+
+2018-04-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/ca.mo, plugins/sudoers/po/ca.po,
+ plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/el.mo, plugins/sudoers/po/el.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/eu.mo, plugins/sudoers/po/eu.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/fur.mo, plugins/sudoers/po/fur.po,
+ plugins/sudoers/po/hu.mo, plugins/sudoers/po/hu.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/lt.mo, plugins/sudoers/po/lt.po,
+ plugins/sudoers/po/nl.mo, plugins/sudoers/po/nl.po,
+ plugins/sudoers/po/ru.mo, plugins/sudoers/po/ru.po,
+ plugins/sudoers/po/sk.mo, plugins/sudoers/po/sk.po,
+ plugins/sudoers/po/sl.mo, plugins/sudoers/po/sl.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po,
+ plugins/sudoers/po/tr.mo, plugins/sudoers/po/tr.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po, po/ca.mo,
+ po/ca.po, po/da.mo, po/da.po, po/de.mo, po/de.po, po/eo.mo,
+ po/eo.po, po/es.mo, po/es.po, po/eu.mo, po/eu.po, po/fi.mo,
+ po/fi.po, po/fur.mo, po/fur.po, po/gl.mo, po/gl.po, po/hu.mo,
+ po/hu.po, po/ko.mo, po/ko.po, po/nl.mo, po/nl.po, po/nn.mo,
+ po/nn.po, po/ru.mo, po/ru.po, po/sk.mo, po/sk.po, po/sl.mo,
+ po/sl.po, po/sr.mo, po/sr.po, po/vi.mo, po/vi.po, po/zh_CN.mo,
+ po/zh_CN.po:
+ sync with translationproject.org
+ [268a65ce44cb]
+
+ * MANIFEST, plugins/sudoers/regress/cvtsudoers/test23.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test23.sh,
+ plugins/sudoers/regress/cvtsudoers/test24.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test24.sh:
+ Add tests for round-tripping cvtsudoers, sudoers -> LDIF -> sudoers
+ and LDIF -> sudoers -> LDIF.
+ [370d4ba4dbb8]
+
+2018-04-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/regress/cvtsudoers/test22.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test22.sh:
+ Test the -b option when converting from LDIF.
+ [4d65c7c2ed01]
+
+ * plugins/sudoers/cvtsudoers_ldif.c:
+ Fix the -b option when converting from LDIF.
+ [f3c1e4dbd61e]
+
+2018-04-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po, po/it.mo,
+ po/it.po:
+ sync with translationproject.org
+ [1953956c60fe]
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ doc/sudo.conf.cat, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in,
+ doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.ldap.cat,
+ doc/sudoers.ldap.man.in, doc/sudoers.ldap.mdoc.in,
+ doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in:
+ Fix some more typos.
+ [87fde92a1fa4]
+
+ * doc/Makefile.in:
+ mandoc now preserves the copyright notice, no need to do it
+ ourselves
+ [2c3f6841941a]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Describe the special handling of LOGNAME, USER and USERNAME. Fix
+ typos reported by aspell.
+ [e89bd28f4530]
+
+ * src/load_plugins.c:
+ Fix a memory leak on the error path.
+ [db5a4678e0e4]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document that the editor setting is also used by sudoedit.
+ [2ae14439efd7]
+
+2018-04-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/load_plugins.c, src/sudo.c, src/sudo_plugin_int.h:
+ Plug memory leak when an I/O plugin is specified in sudo.conf but
+ the I/O plugin is not configured.
+ [5b5086d7152a]
+
+ * INSTALL, MANIFEST, NEWS, config.h.in, configure, configure.ac,
+ plugins/sudoers/Makefile.in, plugins/sudoers/ins_python.h,
+ plugins/sudoers/insults.h:
+ Monty Python insults from Philip Hudson
+ [8330cfc5ea19]
+
+2018-04-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in:
+ add examples
+ [830ff26a0dbc]
+
+ * doc/sudo.conf.man.in, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ doc/sudoers.ldap.man.in, doc/sudoers.man.in,
+ doc/sudoers_timestamp.man.in, doc/sudoreplay.man.in,
+ doc/visudo.man.in:
+ Update copyright year and regen man pages.
+ [6385891ebaa3]
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po, po/cs.mo,
+ po/cs.po, po/fr.mo, po/fr.po, po/hr.mo, po/hr.po, po/ja.mo,
+ po/ja.po, po/nb.mo, po/nb.po, po/pl.mo, po/pl.po, po/pt_BR.mo,
+ po/pt_BR.po, po/sv.mo, po/sv.po, po/tr.mo, po/tr.po, po/uk.mo,
+ po/uk.po:
+ sync with translationproject.org
+ [3495b17becb0]
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/match.c:
+ Prune alias contents when pruning and expanding aliases. This abuses
+ the userlist_matches_filter() and hostlist_matches_filter()
+ functions. A better approach would be to call the correct function
+ from user_matches() and host_matches().
+ [0ae5f351b09f]
+
+ * MANIFEST, examples/sudoers, plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/cvtsudoers/sudoers,
+ plugins/sudoers/regress/cvtsudoers/sudoers.defs,
+ plugins/sudoers/regress/cvtsudoers/test1.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test1.sh,
+ plugins/sudoers/regress/cvtsudoers/test10.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test10.sh,
+ plugins/sudoers/regress/cvtsudoers/test11.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test11.sh,
+ plugins/sudoers/regress/cvtsudoers/test12.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test12.sh,
+ plugins/sudoers/regress/cvtsudoers/test13.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test13.sh,
+ plugins/sudoers/regress/cvtsudoers/test14.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test14.sh,
+ plugins/sudoers/regress/cvtsudoers/test15.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test15.sh,
+ plugins/sudoers/regress/cvtsudoers/test16.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test16.sh,
+ plugins/sudoers/regress/cvtsudoers/test17.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test17.sh,
+ plugins/sudoers/regress/cvtsudoers/test18.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test18.sh,
+ plugins/sudoers/regress/cvtsudoers/test19.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test19.sh,
+ plugins/sudoers/regress/cvtsudoers/test2.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test2.sh,
+ plugins/sudoers/regress/cvtsudoers/test20.conf,
+ plugins/sudoers/regress/cvtsudoers/test20.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test20.sh,
+ plugins/sudoers/regress/cvtsudoers/test21.conf,
+ plugins/sudoers/regress/cvtsudoers/test21.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test21.sh,
+ plugins/sudoers/regress/cvtsudoers/test3.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test3.sh,
+ plugins/sudoers/regress/cvtsudoers/test4.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test4.sh,
+ plugins/sudoers/regress/cvtsudoers/test5.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test5.sh,
+ plugins/sudoers/regress/cvtsudoers/test6.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test6.sh,
+ plugins/sudoers/regress/cvtsudoers/test7.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test7.sh,
+ plugins/sudoers/regress/cvtsudoers/test8.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test8.sh,
+ plugins/sudoers/regress/cvtsudoers/test9.out.ok,
+ plugins/sudoers/regress/cvtsudoers/test9.sh:
+ cvtsudoers regress tests
+ [72fd218b5036]
+
+2018-04-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in:
+ Fix typo
+ [e572c36919b7]
+
+ * plugins/sudoers/cvtsudoers.c:
+ Fix cut & pasto that prevented "-d command" from working.
+ [6e4ff7f23d0a]
+
+2018-04-13 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y:
+ Fix a user after free crash as well as a memory leak when filtering
+ Defaults.
+ [9bdd404ae6a4]
+
+2018-04-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in:
+ Document that a User_Alias or Host_Alias may be used in the match
+ filter.
+ [49b9306a6a6d]
+
+ * plugins/sudoers/fmtsudoers.c:
+ Don't always expand aliases when formatting a host-based Defaults
+ line. This was missed when expand_aliases support was added.
+ [ef12a033306c]
+
+ * plugins/sudoers/cvtsudoers.c:
+ Allow host and user aliases to be specified in match filters.
+ [6bc8c0da4578]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ Update copyright year.
+ [e9c2eb23def1]
+
+2018-04-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/hu.mo, plugins/sudoers/po/hu.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po, po/da.mo,
+ po/da.po, po/hr.mo, po/hr.po, po/hu.mo, po/hu.po, po/pt_BR.mo,
+ po/pt_BR.po, po/tr.mo, po/tr.po:
+ sync with translationproject.org
+ [4a0811073374]
+
+2018-04-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/alias.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/parse.h:
+ When the -d option is used, remove aliases used by the non-converted
+ Defaults settings if the aliases are not also referenced by
+ userspecs.
+ [d07c4254b3dd]
+
+2018-04-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [9a4d88b2a965]
+
+ * NEWS:
+ update
+ [6ef9dde8fc9a]
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in:
+ Mention -p and -M options in the description of -m.
+ [b20abfd14164]
+
+2018-04-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sudo_edit.c:
+ Check sudoedit temporary directory for writability before using it.
+ [1e29ade3f4b2]
+
+ * plugins/sudoers/regress/starttime/check_starttime.c:
+ Use btime in /proc/stat to determine system start time instead of
+ /proc/uptime. Fixes the process start time test when run from a
+ container where /proc/uptime is the uptime of the container but the
+ process start time is relative to the host system boot time. Bug
+ #829
+ [65ba61e55011]
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers.h,
+ plugins/sudoers/match.c, plugins/sudoers/parse.h:
+ Add option to prune non-matching entries from cvtsudoers output with
+ -m option is used.
+ [9a69ba35389d]
+
+2018-04-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers.h:
+ Allow defaults types and suppression list to be specified in the
+ config file.
+ [62dd7a96ac9b]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/parse.h, plugins/sudoers/visudo.c:
+ Refactor common alias code out of cvtsudoers and visudo and into
+ alias.c.
+ [b3ba3e6f24d2]
+
+2018-03-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/cvtsudoers.c:
+ Avoid NULL deref in an error path. CID 183467
+ [38ea56670f18]
+
+ * plugins/sudoers/cvtsudoers.c:
+ No need to initialize the last pointer passed to strtok_r(). This
+ was originally added to appease newer gcc but no longer seems to be
+ required. CID 183466, CID 183468, CID 183469
+ [b0a9b90603e1]
+
+ * plugins/sudoers/cvtsudoers_json.c:
+ Avoid false positive NULL dereference by uses value.u.string instead
+ of name as the former is guaranteed not to be NULL. Fixes CID
+ 183465.
+ [c896d10f5626]
+
+2018-03-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [8a88e162fd0b]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ Add a section on convertion from file-based sudoers.
+ [033c797b229d]
+
+2018-03-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers.c:
+ Add support for "cvtsudoers -d all"
+ [62e748b70105]
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers.h:
+ Add -d option to control what type of Defaults entries are
+ converted.
+ [b723f0dae5c7]
+
+2018-03-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_pty.c:
+ In pty_close() we still need to check whether the pty master and
+ slave fds are open before closing them. When no tty is present but
+ we are I/O logging pty_close() will be called when there is no
+ actual pty in use.
+ [59201fb78427]
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/sudo.conf.cat,
+ doc/sudoers_timestamp.cat, doc/visudo.cat:
+ regen
+ [186f3b58daf5]
+
+2018-03-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgignore:
+ ignore *.ldif2sudo regress output
+ [8d57e8a0013f]
+
+ * src/exec_pty.c:
+ In pty_close() there is no need to remove events associated with the
+ pty slave as there are none. We also don't need to check for the pty
+ fds being -1 since they are not closed elsewhere and pty_close() is
+ only called if pty_setup() succeeds.
+ [585a47fb5a8b]
+
+2018-03-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/Makefile.in, doc/cvtsudoers.mdoc.in:
+ Move cvtsudoers to section 1.
+ [69adcb2d24ff]
+
+ * src/exec_pty.c:
+ In pty_close() close the slave and remove any events associated with
+ it. Fixes a potential hang when performing the final flush on non-
+ BSD systems.
+ [40159d852c2d]
+
+2018-03-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/ldap_util.c:
+ Fix typo in strcmp(), we are comparing var not val.
+ [07ccd7bae4f6]
+
+ * MANIFEST:
+ sync
+ [7960511e39dd]
+
+ * NEWS:
+ sync
+ [c655e7111ce9]
+
+2018-03-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [ff7b545844fb]
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers.h,
+ plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/sudoers.h:
+ Add -M option to cvtsudoers to force the use of the local passwd and
+ group databases when matching.
+ [ea58e2765a40]
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers.h,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c:
+ Add cvtsudoers command line option to suppress certain parts of the
+ security policy. Can be used to suppress displaying of Defaults
+ entries, aliases or privileges.
+ [b243efa695e6]
+
+2018-03-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/parser/check_gentime.c:
+ Silence a false positive from the clang static analyzer.
+ [bfde0594783e]
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/parse.h:
+ Silence a false positive from the clang static analyzer.
+ [5257e321158d]
+
+ * plugins/sudoers/cvtsudoers.c:
+ Fix memory leak on error path.
+ [1a13732abfd5]
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [c139b8bed3c1]
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers.h,
+ plugins/sudoers/cvtsudoers_ldif.c:
+ Move cvtsudoers string functions into cvtsudoers.c
+ [4b5b799e7abc]
+
+ * plugins/sudoers/Makefile.in:
+ regen
+ [6ecb37e35c9f]
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/alias.c,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers.h,
+ plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/cvtsudoers_pwutil.c, plugins/sudoers/parse.h:
+ Initial support filtering by user, group and host in cvtsudoers.
+ Currently forces alias expansion when a filter is applied and the
+ entire matching user or host list is printed, even the non-matching
+ entries. This effectively allows you to grep sudoers by user, group
+ and host.
+ [0adbf8d38eb4]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/parse.h:
+ Add free_default() to free a struct defaults pointer so we have a
+ single place where we free the defaults. A pointer to the previous
+ Default's binding may be passed in to avoid freeing an already free
+ binding.
+ [9d9ef007ee88]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.cat, doc/sudoers.ldap.cat,
+ doc/sudoers.ldap.man.in, doc/sudoers.ldap.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Decrease bullet width to 1n.
+ [e6f3776fd72e]
+
+2018-03-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/sudo.c:
+ Add aix_setauthdb() before the initial getpwuid() call.
+ [b8a011be9af7]
+
+2018-03-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers_ldif.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.h:
+ fix compilation on Solaris
+ [e31019b5f545]
+
+2018-03-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in,
+ plugins/sudoers/sudoreplay.c:
+ Make "sudoreplay -m 0" skip the pauses entirely.
+ [d9a7fc9f5720]
+
+ * doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in:
+ Document that a negative value for -m will elmininate the pauses.
+ [a025e96abb47]
+
+2018-03-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/testsudoers.c:
+ Update copyright date, remove unneeded include and add a few
+ comments.
+ [ac1bccd631e5]
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/sudoers/test1.out.ok,
+ plugins/sudoers/regress/sudoers/test10.out.ok,
+ plugins/sudoers/regress/sudoers/test11.out.ok,
+ plugins/sudoers/regress/sudoers/test12.out.ok,
+ plugins/sudoers/regress/sudoers/test13.out.ok,
+ plugins/sudoers/regress/sudoers/test14.out.ok,
+ plugins/sudoers/regress/sudoers/test15.out.ok,
+ plugins/sudoers/regress/sudoers/test16.out.ok,
+ plugins/sudoers/regress/sudoers/test17.out.ok,
+ plugins/sudoers/regress/sudoers/test18.out.ok,
+ plugins/sudoers/regress/sudoers/test19.out.ok,
+ plugins/sudoers/regress/sudoers/test2.out.ok,
+ plugins/sudoers/regress/sudoers/test20.out.ok,
+ plugins/sudoers/regress/sudoers/test21.out.ok,
+ plugins/sudoers/regress/sudoers/test22.out.ok,
+ plugins/sudoers/regress/sudoers/test3.out.ok,
+ plugins/sudoers/regress/sudoers/test4.out.ok,
+ plugins/sudoers/regress/sudoers/test5.out.ok,
+ plugins/sudoers/regress/sudoers/test6.out.ok,
+ plugins/sudoers/regress/sudoers/test7.out.ok,
+ plugins/sudoers/regress/sudoers/test8.out.ok,
+ plugins/sudoers/regress/sudoers/test9.out.ok,
+ plugins/sudoers/testsudoers.c:
+ Use fmtsudoers functions in testsudoers.
+ [be27df4a5291]
+
+ * MANIFEST, plugins/sudoers/regress/sudoers/test22.in,
+ plugins/sudoers/regress/sudoers/test22.json.ok,
+ plugins/sudoers/regress/sudoers/test22.ldif.ok,
+ plugins/sudoers/regress/sudoers/test22.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test22.out.ok,
+ plugins/sudoers/regress/sudoers/test22.sudo.ok,
+ plugins/sudoers/regress/sudoers/test22.toke.ok:
+ Add test for empty runas user list.
+ [5598cf4c3329]
+
+ * plugins/sudoers/testsudoers.c:
+ Don't print an empty user list as ALL.
+ [806ee09f854d]
+
+ * plugins/sudoers/fmtsudoers.c, plugins/sudoers/parse.h:
+ In sudoers_format_userspecs make the separator optional and silence
+ a printf format warning.
+ [62c576cbec4b]
+
+ * plugins/sudoers/starttime.c:
+ Use correct defines when checking for sysctl kinfo_proc support.
+ [6017e45d14b9]
+
+ * plugins/sudoers/cvtsudoers_json.c:
+ Fix crash when converting sudoers entry with a runas list that is
+ present but empty.
+ [ff6b9ef53c6b]
+
+2018-03-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, plugins/sudoers/starttime.c,
+ plugins/sudoers/sudoers.c, src/regress/ttyname/check_ttyname.c,
+ src/tgetpass.c, src/ttyname.c:
+ Less confusing sysctl checks for kinfo_proc.
+ [553f6b3f9c3b]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/match.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/sssd.c:
+ Add case_insensitive_group and case_insensitive_user sudoers
+ options, which are enabled by default.
+ [bd74d8b7fe83]
+
+2018-03-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/fmtsudoers.c:
+ Kill dead store found by clang-analyzer.
+ [af2021d3d396]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers_ldif.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/ldap.c, plugins/sudoers/ldap_util.c,
+ plugins/sudoers/parse.h,
+ plugins/sudoers/regress/sudoers/test2.ldif.ok,
+ plugins/sudoers/regress/sudoers/test3.ldif.ok,
+ plugins/sudoers/regress/sudoers/test6.ldif.ok,
+ plugins/sudoers/sssd.c:
+ Initial support for adding comments that will be emitted when
+ sudoers is formatted. Currently adds a comment for the source
+ sudoRole when converting from ldif -> sudoers.
+ [bf2e7f48f452]
+
+ * lib/util/lbuf.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/fmtsudoers.c, plugins/sudoers/parse.h:
+ Special case comment lines in lbufs.
+ [10d6d229ffae]
+
+ * plugins/sudoers/cvtsudoers_ldif.c:
+ Handle escaped commas when skipping over the cn.
+ [61aed7ff5e1c]
+
+2018-03-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/fmtsudoers.c,
+ plugins/sudoers/parse.h:
+ When formatting as sudoers, flush the lbuf after each userspec.
+ [060266dd440c]
+
+2018-03-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/sudoers/test1.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test14.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test15.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test16.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test17.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test19.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test2.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test20.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test21.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test3.ldif2sudo.ok,
+ plugins/sudoers/regress/sudoers/test6.ldif2sudo.ok:
+ Add tests for round-tripping sudoers -> ldif -> sudoers
+ [72e3e73fb612]
+
+ * plugins/sudoers/cvtsudoers_ldif.c:
+ Add missing sudoOrder support to parse_ldif().
+ [8c5e9f22f0da]
+
+ * plugins/sudoers/ldap_util.c:
+ Add missing support for converting LOG_INPUT/LOG_OUTPUT tags and
+ expand support for NOMAIL tags.
+ [2820c8333381]
+
+ * plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/regress/sudoers/test2.ldif.ok,
+ plugins/sudoers/regress/sudoers/test3.ldif.ok,
+ plugins/sudoers/regress/sudoers/test6.ldif.ok:
+ Don't emit an empty sudoRole for global defaults if there are none.
+ [2a69dccb7071]
+
+ * plugins/sudoers/ldap_util.c:
+ Avoid changing the order of non-negated hosts and commands. We still
+ put negated hosts/commands at the end of the list.
+ [e1aea92dd6dc]
+
+ * plugins/sudoers/cvtsudoers_ldif.c:
+ Handle parsing boolean options that have no explicit value.
+ [b5d597faa23d]
+
+ * plugins/sudoers/cvtsudoers_ldif.c:
+ Refactor the code that actually converts the role to sudoers format
+ into role_to_sudoers() now that it is more involved than just
+ calling sudo_ldap_role_to_priv().
+ [b876171ff96e]
+
+ * plugins/sudoers/cvtsudoers_ldif.c:
+ When merging two privileges, use the runas lists of the previous
+ privilege when possible. Otherwise, the generated sudoers line will
+ include a runas list for commands that is not necessary.
+ [337b49451947]
+
+2018-03-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/match.c:
+ Use a case-insensitive comparison when matching user and group names
+ in sudoers with the passwd or group database. This can be necessary
+ when users and groups are stored in AD or LDAP.
+ [bfccb8acc3e9]
+
+ * plugins/sudoers/Makefile.in:
+ Fix clean target for *.sudo regress files
+ [6f52a4aef93a]
+
+ * .hgignore:
+ ignore more binaries
+ [9adf244d0e9e]
+
+ * plugins/sudoers/cvtsudoers.c:
+ Fix use of uninitialized variable (conf) if sudoers_debug_register()
+ happens to fail.
+ [0ef1765f14f4]
+
+2018-02-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers_ldif.c:
+ Split conversion code out of parse_ldif() and into
+ ldif_to_sudoers().
+ [27c8b7001735]
+
+ * plugins/sudoers/cvtsudoers_ldif.c:
+ Quiet a clang analyzer warning.
+ [21102c27dcce]
+
+ * MANIFEST, configure, configure.ac, mkdep.pl,
+ plugins/sudoers/Makefile.in, plugins/sudoers/ldap_common.c,
+ plugins/sudoers/ldap_util.c:
+ rename ldap_common.c -> ldap_util.c
+ [3093bdbb8a9b]
+
+ * plugins/sudoers/cvtsudoers_ldif.c:
+ When converting from ldif to sudoers, sudoRole objects with the same
+ user if possible. If both user and host are the same, merge into a
+ single privilege. This makes it possible to convert a sudoers entry
+ like:
+
+ aaron shanty = NOEXEC: /usr/bin/vi, /usr/bin/more, EXEC: /bin/sh
+
+ to ldif and then back to sudoers as a single line. Currently, the
+ ldif entries to be merged must have the same or adjacent sudoOrder
+ attributes.
+ [74e5cef2e849]
+
+ * plugins/sudoers/cvtsudoers_ldif.c:
+ plug memory leaks
+ [a5268668c397]
+
+ * src/parse_args.c:
+ Restore line to set MODE_PRESERVE_ENV in flags when the -E command
+ line option is used. The caller doesn't check MODE_PRESERVE_ENV
+ these days but parse_args uses it to detect usage errors when -E is
+ used along with a mutually excusive option. Problem found by Yuriy
+ Vostrikov.
+ [b511e35d9be4]
+
+2018-02-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Add missing close parenthesis in "Including other files from within
+ sudoers" section. Bug #824
+ [3335cb2ce29f]
+
+2018-02-25 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/ldap_common.c:
+ When converting from LDAP to sudoers, put negated hosts and commands
+ at the end of the list. Since LDAP doesn't guarantee attribute order
+ we need to make sure negated entries always override non- negated
+ ones.
+ [0ebff259c521]
+
+2018-02-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers.c:
+ We may need the hostname to resolve %h escapes in include files.
+ [3e57710762d3]
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers_ldif.c:
+ Setting a sudoOrder start point of 0 will disable creation of
+ sudoOrder attributes in the resulting LDIF output.
+ [4107f61b431b]
+
+ * plugins/sudoers/cvtsudoers.c:
+ Don't need to fill in struct sudo_user since we don't do matching.
+ [cdc876d298b5]
+
+ * MANIFEST, doc/cvtsudoers.cat, doc/cvtsudoers.man.in,
+ doc/cvtsudoers.mdoc.in, pathnames.h.in, plugins/sudoers/Makefile.in,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers.h,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c:
+ Add support for setting default options in a config file. In
+ addition to expand_aliases, input_format and output_format, both the
+ initial sudoOrder and the increment when updating sudoOrder for
+ subsequent sudoRole objects can be specified. Command line options
+ have also been added for the start order and increment.
+ [d3121c039ddf]
+
+2018-02-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ cvtsudoers can now read LDIF
+ [99b7ed30c754]
+
+ * doc/UPGRADE:
+ Fix a typo.
+ [87f635970a5d]
+
+ * plugins/sudoers/fmtsudoers.c:
+ Deal with user_name not being set in cvtsudoers.
+ [421bb1dbff57]
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/ldap_common.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudo_ldap.h:
+ Initial support for parsing sudoers LDIF files in cvtsudoers. This
+ makes it possible to convert from LDAP sudoers to a traditional
+ sudoers file. Semantic differences between file sudoers and LDAP
+ sudoers mean that LDIF -> sudoers is not completely equivalent.
+ [ddf513e2778f]
+
+2018-02-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/regress/sudoers/test14.ldif.ok:
+ Fix LDIF conversion of commands with an associated digest.
+ [590ab0cb58e4]
+
+ * plugins/sudoers/ldap_common.c:
+ In array_to_member_list() use the correct type for netgroups and
+ user groups.
+ [359947d19131]
+
+ * plugins/sudoers/fmtsudoers.c:
+ Prepend digest to command if present. Fix printing of group IDs and
+ non-unix groups.
+ [5f9834b4bcbc]
+
+ * plugins/sudoers/cvtsudoers_json.c:
+ Fix gcc false positive for uninitialized variable
+ [d250b862c1ed]
+
+2018-02-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * pp:
+ Update Polypkg to the latest version from git.
+ [204ebffb502f]
+
+ * config.h.in, configure, configure.ac, src/sudo.c:
+ Use setpassent() and setgroupent() on systems that support it to
+ keep the passwd and group database open. Sudo does a lot of passwd
+ and group lookups so it can be beneficial to just leave the file
+ open.
+ [3d2d5bca9670]
+
+2018-02-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c, plugins/sudoers/fmtsudoers.c:
+ Add option to cvtsudoers to expand aliases in the output.
+ [1af56459fd7d]
+
+ * plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/regress/sudoers/test1.json.ok,
+ plugins/sudoers/regress/sudoers/test14.json.ok,
+ plugins/sudoers/regress/sudoers/test15.json.ok,
+ plugins/sudoers/regress/sudoers/test16.json.ok,
+ plugins/sudoers/regress/sudoers/test17.json.ok,
+ plugins/sudoers/regress/sudoers/test19.json.ok,
+ plugins/sudoers/regress/sudoers/test2.json.ok,
+ plugins/sudoers/regress/sudoers/test6.json.ok:
+ Fix conversion of "ALL" in the JSON output format, which was being
+ printed as an alias.
+ [3f7869688820]
+
+ * INSTALL, configure, configure.ac:
+ Clarify that --with-rundir and --with-vardir take sudo-specific
+ directory, e.g. /var/run/sudo and not just /var/run. Bug #823
+ [e1913085e544]
+
+ * src/exec_pty.c:
+ In pty_cleanup() we need to call sudo_term_restore() even if no I/O
+ plugins are present as long as /dev/tty exists. Fixes the use_pty
+ case with no I/O plugins.
+ [82fecef72998]
+
+ * include/sudo_event.h, lib/util/event.c, lib/util/util.exp.in,
+ plugins/sudoers/sudoreplay.c, src/exec_monitor.c, src/exec_nopty.c,
+ src/exec_pty.c:
+ Add sudo_ev_dispatch(), a wrapper for ev_loop() with no flags.
+ Similar the dispatch function in libevent.
+ [61e588fd50d0]
+
+ * INSTALL, configure, configure.ac, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, m4/sudo.m4:
+ Use /run in preference to /var/run if it exists. Bug #822
+ [ec2febe6f8a3]
+
+2018-02-14 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ mention common sudoers formatting changes
+ [b32825ca3e2f]
+
+2018-02-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, configure, configure.ac, mkdep.pl,
+ plugins/sudoers/Makefile.in, plugins/sudoers/ldap.c,
+ plugins/sudoers/ldap_conf.c, plugins/sudoers/sudo_ldap.h,
+ plugins/sudoers/sudo_ldap_conf.h:
+ Move LDAP configuration bits into ldap_conf.c
+ [1673e3c7855a]
+
+2018-02-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/ldap_common.c:
+ No longer need to include stddef.h
+ [a10a13dc73c7]
+
+ * plugins/sudoers/iolog.c:
+ Remove dead store, found by cppcheck.
+ [744e99ffc82e]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/ldap_common.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudo_ldap.h:
+ simplify iterator
+ [944fd546ec98]
+
+ * plugins/sudoers/mkdir_parents.c:
+ Silence a false positive from cppcheck.
+ [f94421968d8e]
+
+ * plugins/sudoers/tsdump.c:
+ Cast version to int when printing. Avoids a cppcheck warning.
+ [3312bec4f1e3]
+
+2018-02-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/ldap_common.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudo_ldap.h:
+ Use an iterator instead of fragile pointer arithmetic to iterate
+ over value arrays in sudo_ldap_role_to_priv().
+ [61752c5f3427]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/fmtsudoers.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/sssd.c:
+ Move sudoers formatting code into fmtsudoers.
+ [ff25291c99f4]
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/parse.c:
+ Clean up some XXX in parse.c
+ [19854e7d8ac7]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h, plugins/sudoers/sssd.c:
+ Rename sudo_file_append_default() -> sudo_lbuf_append_default() and
+ use it for ldap and sssd too.
+ [dae22810f2dd]
+
+ * MANIFEST, configure, configure.ac, mkdep.pl,
+ plugins/sudoers/Makefile.in, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/ldap.c,
+ plugins/sudoers/ldap_common.c, plugins/sudoers/parse.h,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudo_ldap.h:
+ Move common bits of ldap to sudoers conversion into ldap_common.c
+ and use it in sssd.c.
+ [5cca03f64b77]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/ldap.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h:
+ Convert ldap results into a sudoers userspec so we can use the "sudo
+ -l" output functions in parse.c.
+ [1422e10dc274]
+
+2018-02-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * sudo.pp:
+ Don't mark sudoers.dist volatile, it only gets used on systems that
+ don't have the concept of volatile files.
+ [c47fd17e62e3]
+
+2018-02-05 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.h:
+ Refactor member freeing code into free_member(). Refactor userspec
+ freeing code into free_userspec().
+ [ccc95e8b9f69]
+
+ * plugins/sudoers/cvtsudoers.c:
+ Fix compilation with glibc where stdout is not constant.
+ [97a0302c29c8]
+
+2018-02-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/ldap.c:
+ For "sudo -l", if a word includes spaces, print it in double quotes.
+ Also escape spaces in the command path. This matches the sudoers
+ quoting rules.
+ [04ace6decf3a]
+
+2018-02-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/ldap.c:
+ Display sudoNotBefore and sudoNotAfter in "sudo -l"
+ [ef7de4c8aa9e]
+
+ * plugins/sudoers/parse.c:
+ For "sudo -l", if a word includes spaces, print it in double quotes.
+ Also escape spaces in the command path. This matches the sudoers
+ quoting rules.
+ [fa12a254657c]
+
+ * plugins/sudoers/cvtsudoers.c:
+ Add back printing of negation operator ('!') when printing a word
+ with spaces in it.
+ [c69706a91817]
+
+ * plugins/sudoers/Makefile.in:
+ Use visudo to validate "cvtsudoers -f sudoers" output.
+ [06bae7204926]
+
+ * plugins/sudoers/regress/sudoers/test21.in,
+ plugins/sudoers/regress/sudoers/test21.json.ok,
+ plugins/sudoers/regress/sudoers/test21.ldif.ok,
+ plugins/sudoers/regress/sudoers/test21.out.ok,
+ plugins/sudoers/regress/sudoers/test21.toke.ok:
+ Remove syslog_goodpri and syslog_badpri without a value that causes
+ visudo to report an error.
+ [c1f696e49f49]
+
+ * plugins/sudoers/cvtsudoers.c:
+ When outputting sudoers, if a word includes spaces, print it in
+ double quotes. Also escape spaces in the command path.
+ [d040c1a21277]
+
+2018-02-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/alias.c, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/parse.h, plugins/sudoers/visudo.c:
+ Add sudoers output format to cvtsudoers. In the future this may be
+ used with filters to emit a partial sudoers file instead of a full
+ one.
+ [533d2c389213]
+
+ * plugins/sudoers/parse.c:
+ When printing a member name, quote sudoers special characters unless
+ it is a UID/GID, in which case we print the '#' unquoted.
+ [e4e8154c4fe9]
+
+ * plugins/sudoers/parse.c, plugins/sudoers/parse.h:
+ Move SUDOERS_QUOTED define to parse.h
+ [a813ec4acb5f]
+
+2018-01-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/timestamp.c:
+ Remove extraneous break statement and fix some whitespace.
+ [39df566c33e3]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ The max timeout for kernel time stamps is 60 minutes, not 3600
+ minutes.
+ [95be88c4f106]
+
+2018-01-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/testsudoers.c:
+ Check the return value of sudoers_debug_register(). Coverity CID
+ 182574
+ [fb5449acdafd]
+
+ * plugins/sudoers/cvtsudoers_ldif.c:
+ Fix memory leak, su->count is now 0 when it is unused, not 1.
+ Covertity CID 182573
+ [77019ded8f84]
+
+ * plugins/sudoers/cvtsudoers_ldif.c:
+ Quiet a clang analyzer false positive.
+ [ef04f7069df4]
+
+ * plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/regress/sudoers/test2.ldif.ok,
+ plugins/sudoers/regress/sudoers/test6.ldif.ok:
+ Quote special characters when creating the cn as per RFC2253
+ [e49ff28c1fd7]
+
+ * NEWS, configure, configure.ac, doc/UPGRADE:
+ Sudo 1.8.23
+ [e364ed057d1d]
+
+ * doc/LICENSE:
+ Remove the C-style comment charactes from the getopt_long.c and
+ inet_pton.c license text as it was inconsistent with the rest of the
+ file and messed up the html formatting.
+ [a26679d2d0a7]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/sudoers2ldif,
+ sudo.pp:
+ Remove sudoers2ldif, it has been replaced by cvtsudoers.
+ [7563cc3768c2]
+
+2018-01-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers_ldif.c:
+ Add -b option to specify the base dn.
+ [7cd4c46c33bf]
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in:
+ Document limitations of LDIF conversion.
+ [e8c84362f084]
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers.c:
+ Switch the default output format to LDIF
+ [a677c7b72a90]
+
+ * plugins/sudoers/visudo.c:
+ Execute cvtsudoers if the user runs "visudo -x" but also emit a
+ warning.
+ [53ec45a847d2]
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/stubs.c,
+ plugins/sudoers/visudo.c:
+ Revert 04ec05108b2b, change the default input source back to stdin.
+ [df8d94f1bab4]
+
+ * MANIFEST, plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/sudoers/test1.ldif.ok,
+ plugins/sudoers/regress/sudoers/test10.ldif.ok,
+ plugins/sudoers/regress/sudoers/test11.ldif.ok,
+ plugins/sudoers/regress/sudoers/test12.ldif.ok,
+ plugins/sudoers/regress/sudoers/test13.ldif.ok,
+ plugins/sudoers/regress/sudoers/test14.ldif.ok,
+ plugins/sudoers/regress/sudoers/test15.ldif.ok,
+ plugins/sudoers/regress/sudoers/test16.ldif.ok,
+ plugins/sudoers/regress/sudoers/test17.ldif.ok,
+ plugins/sudoers/regress/sudoers/test18.ldif.ok,
+ plugins/sudoers/regress/sudoers/test19.ldif.ok,
+ plugins/sudoers/regress/sudoers/test2.ldif.ok,
+ plugins/sudoers/regress/sudoers/test20.ldif.ok,
+ plugins/sudoers/regress/sudoers/test21.ldif.ok,
+ plugins/sudoers/regress/sudoers/test3.ldif.ok,
+ plugins/sudoers/regress/sudoers/test4.ldif.ok,
+ plugins/sudoers/regress/sudoers/test5.ldif.ok,
+ plugins/sudoers/regress/sudoers/test6.ldif.ok,
+ plugins/sudoers/regress/sudoers/test7.ldif.ok,
+ plugins/sudoers/regress/sudoers/test8.ldif.ok,
+ plugins/sudoers/regress/sudoers/test9.ldif.ok:
+ Add LDIF conversion to sudoers tests
+ [997b79da8874]
+
+ * plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/cvtsudoers_ldif.c,
+ plugins/sudoers/regress/sudoers/test19.json.ok:
+ Add notbefore and notafter support to the backends.
+ [be50db300eda]
+
+2018-01-27 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * README.LDAP:
+ cvtsudoers instead of sudoers2ldif
+ [3909ea2c29c1]
+
+ * MANIFEST, doc/cvtsudoers.cat, doc/cvtsudoers.man.in,
+ doc/cvtsudoers.mdoc.in, plugins/sudoers/Makefile.in,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers_ldif.c:
+ Add ldif backend to cvtsudoers, to replace sudoers2ldif
+ [f0e039c63488]
+
+ * plugins/sudoers/Makefile.in:
+ fix make check
+ [2cbedce72e3a]
+
+2018-01-26 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers_json.c:
+ Parse sudoers in the front end, not the back end.
+ [30d4e40ed69a]
+
+ * doc/Makefile.in:
+ install the cvtsudoers manual
+ [243d319fed1c]
+
+ * doc/cvtsudoers.cat, doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/stubs.c,
+ plugins/sudoers/visudo.c:
+ Use the built-in sudoers file location as the default sudoers file
+ for cvtsudoers and move parse_sudoers_options() to stubs.c since it
+ is shared between visudo.c and cvtsudoers.c.
+ [04ec05108b2b]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/cvtsudoers.c,
+ plugins/sudoers/stubs.c, plugins/sudoers/visudo.c:
+ Move common stub functions required by the parser out of visudo.c
+ and cvtsudoers.c and into stubs.c.
+ [a324cbde55a3]
+
+ * plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers_json.c:
+ Rename export_sudoers() to convert_sudoers_json() and move the check
+ for the same input and output file to the front-end.
+ [7c83c21ea479]
+
+ * sudo.pp:
+ add cvtsudoers
+ [e8ba851cafb4]
+
+ * MANIFEST, doc/Makefile.in, doc/cvtsudoers.cat,
+ doc/cvtsudoers.man.in, doc/cvtsudoers.mdoc.in, doc/visudo.cat,
+ doc/visudo.man.in, doc/visudo.mdoc.in, plugins/sudoers/Makefile.in,
+ plugins/sudoers/cvtsudoers.c, plugins/sudoers/cvtsudoers_json.c,
+ plugins/sudoers/visudo.c, plugins/sudoers/visudo_json.c:
+ Move sudoers JSON conversion to cvtsudoers which will eventually
+ output to other formats too.
+ [e64a50657a88]
+
+ * plugins/sudoers/defaults.c:
+ Convert from time in minutes to timespec directly instead of
+ converting to double via strtod(). This makes it easier to catch
+ overflow.
+ [0d6ab7c21a15]
+
+2018-01-24 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ document that kernel tty timestamps don't support negative timeouts
+ [4ff726cf2010]
+
+2018-01-23 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/timestamp.c:
+ Fall back to ppid time stamps if timestamp_type == kernel and no tty
+ is present. This is consistent with timestamp_type == tty.
+ [26c527166a0c]
+
+ * plugins/sudoers/timestamp.c:
+ Do not call the TIOCSETVERAUTH ioctl with a negative number of
+ seconds. Also cap the max number of seconds at 3600 to avoid getting
+ EINVAL from TIOCSETVERAUTH.
+ [371744874743]
+
+2018-01-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/defaults.c:
+ Better conversion from double to nanoseconds.
+ [2f54790801c8]
+
+ * plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/auth/sudo_auth.h,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/defaults.h, plugins/sudoers/mkdefaults,
+ plugins/sudoers/timestamp.c:
+ Store passwd_timeout and timestamp_timeout as a struct timespec
+ instead of as a float. Remove timeout argument to auth_getpass() as
+ it was never used.
+ [c4a3c60d0284]
+
+2018-01-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/mkdefaults:
+ Don't rely on perl being installed in /usr/local/bin
+ [e3274f56df43]
+
+2018-01-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * config.h.in, configure, configure.ac, lib/util/gettime.c,
+ lib/util/mktemp.c, lib/util/nanosleep.c, lib/util/utimens.c,
+ plugins/sudoers/boottime.c, plugins/sudoers/check.c,
+ plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/visudo.c, src/net_ifs.c, src/sesh.c, src/sudo.c,
+ src/sudo_edit.c, src/utmp.c:
+ Remove use of AC_HEADER_TIME, only obsolete platforms actually need
+ this. Also stop removing sys/time.h unless the source file uses
+ struct timeval.
+ [a744b8a07685]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Remove duplicate options %type
+ [3ea3c3d477bf]
+
+2018-01-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/auth/API, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h, plugins/sudoers/check.c,
+ plugins/sudoers/sudoers.h:
+ Add an approval function to the sudo auth API which is run after the
+ user's password has been verified. The approval function is run even
+ if no password is required. This is currently only used for PAM (use
+ pam_acct_mgmt) and BSD auth (auth_approval).
+ [cab448ac8633]
+
+2018-01-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/tsdump.c:
+ treat uid as unsigned in error message
+ [2672d4ca3479]
+
+ * MANIFEST, plugins/sudoers/po/fur.mo:
+ Add missing plugins/sudoers/po/fur.mo file to repo.
+ [cfa503d7fcd4]
+
+ * NEWS:
+ Mention new sudoers_timestamp manual.
+ [f96ad00c4ba4]
+
+2018-01-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * .hgignore:
+ ignore tsdump
+ [39306d37c846]
+
+ * plugins/sudoers/tsdump.c:
+ Convert from mono time to real time before displaying time stamps.
+ [12f9e1f5e8e5]
+
+2018-01-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/solaris_audit.c:
+ Use PATH_MAX, not MAXPATHLEN.
+ [d3c7466aad1d]
+
+ * MANIFEST, config.h.in, configure, configure.ac, include/sudo_util.h,
+ lib/util/Makefile.in, lib/util/ttyname_dev.c, lib/util/util.exp.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/check.h,
+ plugins/sudoers/tsdump.c, src/ttyname.c:
+ Add tsdump, a simple utility to dump a timestamp file. To build, run
+ "make tsdump" in the plugins/sudoers directory (it is not built by
+ default). In order to map the tty device number to a name,
+ sudo_ttyname_dev() has been moved into libsudo_util.
+ [b79ae30fe6a4]
+
+2018-01-04 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po, po/uk.mo,
+ po/uk.po:
+ sync with translationproject.org
+ [71140a551c60]
+
+ * doc/LICENSE:
+ Welcome to 2018
+ [3ddea360d414]
+
+2017-12-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/fur.po, plugins/sudoers/po/nb.mo,
+ plugins/sudoers/po/nb.po, plugins/sudoers/po/zh_CN.mo,
+ plugins/sudoers/po/zh_CN.po:
+ sync with translationproject.org
+ [fbd54c7f59f1]
+
+2017-12-22 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/logging.c:
+ Silence a clang analyzer false positive.
+ [bfcdfe2c1376]
+
+ * doc/Makefile.in:
+ Remove extra $(srcdir)/sudoreplay.man.in target added by mistake.
+ [7e83806cc17e]
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po,
+ plugins/sudoers/po/nl.mo, plugins/sudoers/po/nl.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po, po/ja.mo,
+ po/ja.po:
+ sync with translationproject.org
+ [27cf5abeeb1a]
+
+ * plugins/sudoers/timestamp.c:
+ Use a tty lock even for kernel time stamps so we can avoid
+ simultaneous password prompts.
+ [90a55098176b]
+
+ * NEWS:
+ visudo changes
+ [06c99aab6f7a]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in,
+ plugins/sudoers/editor.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/visudo.c:
+ Also honor SUDO_EDITOR in visudo. Previously is was only used by
+ sudoedit.
+ [9bccc7171a53]
+
+2017-12-21 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoers.c:
+ Stop looking for an editor as soon as we find one. A similar fix was
+ made to visudo some time ago.
+ [c6c5d968612a]
+
+ * doc/sudoers_timestamp.cat, doc/sudoers_timestamp.man.in,
+ doc/sudoers_timestamp.mdoc.in:
+ The session ID was added in 1.8.6p7 to prevent a user in another
+ session from re-using the time stamp file. Other minor cleanups.
+ [f733f7ea97a7]
+
+ * plugins/sudoers/check.h:
+ "time stamp" not "timestamp"
+ [af0f2d8b6d52]
+
+2017-12-20 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS, doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/timestamp.c:
+ Add "kernel" as a possible value of timestamp_type. Currently only
+ supported on OpenBSD.
+ [ca1a2a03e37d]
+
+ * MANIFEST, doc/Makefile.in, doc/sudoers.cat, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in, doc/sudoers_timestamp.cat,
+ doc/sudoers_timestamp.man.in, doc/sudoers_timestamp.mdoc.in,
+ plugins/sudoers/check.h:
+ Document the sudoers time stamp file format.
+ [d3470da8fde9]
+
+2017-12-19 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/starttime/check_starttime.c:
+ Verify start time of the current process, allowing for some clock
+ drift. For Linux, process start time is relative to boot time, not
+ wallclock time.
+ [4928645eaa1c]
+
+2017-12-18 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * NEWS:
+ sync
+ [aeffb7f82e10]
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [8be51858eec1]
+
+ * MANIFEST, plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/starttime/check_starttime.c:
+ Trivial test for process start time. We don't try to check the
+ resulting timespec as it differs by platform. On most it is
+ wallclock time, on others it is relative to boot time (Linux).
+ [e74cf3bd4c87]
+
+ * lib/util/Makefile.in:
+ regen
+ [6de26735d666]
+
+2017-12-17 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/starttime.c:
+ Support start time on macOS and 4.4BSD
+ [81f2eebc7edb]
+
+2017-12-16 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/regress/env_match/check_env_pattern.c:
+ Include sys/types.h for mode_t used in sudoers.h.
+ [bdff1606f111]
+
+ * plugins/sudoers/starttime.c:
+ Fix compilation error on FreeBSD
+ [2c4962a7812c]
+
+ * plugins/sudoers/starttime.c:
+ Fix debug_decl(), it should be SUDOERS_DEBUG_UTIL Add debugging for
+ the successful case For Linux, don't NUL out *ep before parsing with
+ strtoull().
+ * * * Add missing debug info for the System V /proc version.
+ [2394c6d9375d]
+
+ * MANIFEST, doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/check.h,
+ plugins/sudoers/starttime.c, plugins/sudoers/timestamp.c:
+ In the timestamp record, include the start time of the terminal
+ session leader for tty-based timestamps or the start time of the
+ parent process for ppid-based timestamps. Idea from Duncan
+ Overbruck.
+ [f0964b4cf4ac]
+
+2017-12-15 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/timestamp.c:
+ If the lock record doesn't match the expected record size we need to
+ seek to the end of the record as we otherwise may have gone too far
+ (or not far enough). Fixes interop problems when the time stamp
+ record changes size.
+ [e8e4c3815db5]
+
+2017-12-12 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_pty.c:
+ No need for a loop around the recv() now that we don't have to worry
+ about EINTR. CID 180697
+ [7cb966d69bc6]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Try to be clearer about sudo's exit value when the -l option is
+ used.
+ [efbddaa576a7]
+
+ * NEWS:
+ sync
+ [99fc4b347250]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in, plugins/sudoers/ldap.c,
+ plugins/sudoers/sssd.c:
+ An empty RunAsUser means run as the invoking user, similar to how
+ the sudoers files works.
+ [576172386594]
+
+ * doc/sudoers.cat, doc/sudoers.man.in:
+ regen
+ [9b6d0064f410]
+
+2017-12-11 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/logging.c:
+ Add authfail_message sudoers option to allow the user to override
+ the default message of %d incorrect password attempt(s).
+ [f11e9d64a6da]
+
+ * plugins/sudoers/policy.c, src/parse_args.c:
+ Allow the plugin to determine whether or not an empty timeout is
+ allowed. For sudoers, an error will be returned for an empty
+ timeout.
+ [26511c049fb1]
+
+ * plugins/sudoers/timeout.c:
+ Return an error for an empty timeout string. Just use strtol() for
+ syntax checking instead of scanning with strspn().
+ [1fa1b712fbcc]
+
+ * src/parse_args.c, src/sudo_edit.c:
+ Change some _() into U_() since they are used for warn/fatal. We
+ always want to issue warnings in the user's locale.
+ [684331aee66e]
+
+ * Makefile.in:
+ update my email address
+ [b4ec26be6203]
+
+2017-12-10 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * log2cl.pl:
+ Don't print mercurial branch info for merges.
+ [489881774e52]
+
+ * log2cl.pl:
+ Use log size instead of using a separator between the log entry and
+ the file names.
+ [620c231f789b]
+
+ * src/parse_args.c:
+ Print usage and return an error when an empty argument is given for
+ all command line arguments other than -p and -E. Bug #817
+ [143be1bc8316]
+
+ * plugins/sudoers/policy.c:
+ Better input validation of settings passed by the sudo front-end.
+ Instead of ignoring an empty setting, throw an error.
+ [93cc4f4761f3]
+
+ * log2cl.pl:
+ Treat a blank line in a commit message as a line break. There
+ doesn't appear to be a way to make perl's format use a blank field
+ but at least the line break happens now.
+ [fbc3ff819341]
+
+2017-12-09 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * MANIFEST, Makefile.in, log2cl.pl:
+ Add script to generate ChangeLog from git log output.
+ [e8bfbd1ae6ef]
+
+2017-12-08 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h:
+ Don't include syslog.h from logging.h, just include it in the two .c
+ files it is actually needed.
+ [9ffc5ca9eb49]
+
+2017-12-06 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in:
+ Document that in check mode, visudo does not check the owner/mode on
+ files specified with the -f flag.
+ [f5d86019e4c7]
+
+2017-12-03 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * Makefile.in, configure.ac, doc/HISTORY, doc/LICENSE,
+ doc/Makefile.in, doc/fixman.sh, doc/fixmdoc.sh,
+ doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in, doc/sudo.man.in,
+ doc/sudo.mdoc.in, doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ doc/sudoers.ldap.man.in, doc/sudoers.ldap.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, doc/sudoreplay.man.in,
+ doc/sudoreplay.mdoc.in, doc/visudo.man.in, doc/visudo.mdoc.in,
+ examples/Makefile.in, include/Makefile.in,
+ include/compat/charclass.h, include/compat/endian.h,
+ include/compat/fnmatch.h, include/compat/nss_dbdefs.h,
+ include/compat/sha2.h, include/sudo_compat.h, include/sudo_conf.h,
+ include/sudo_debug.h, include/sudo_dso.h, include/sudo_event.h,
+ include/sudo_fatal.h, include/sudo_gettext.h, include/sudo_lbuf.h,
+ include/sudo_plugin.h, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/aix.c, lib/util/closefrom.c, lib/util/event.c,
+ lib/util/event_poll.c, lib/util/event_select.c, lib/util/fatal.c,
+ lib/util/getgrouplist.c, lib/util/gethostname.c, lib/util/getline.c,
+ lib/util/getopt_long.c, lib/util/gettime.c, lib/util/gidlist.c,
+ lib/util/glob.c, lib/util/isblank.c, lib/util/key_val.c,
+ lib/util/lbuf.c, lib/util/locking.c, lib/util/memrchr.c,
+ lib/util/memset_s.c, lib/util/mksiglist.c, lib/util/mksigname.c,
+ lib/util/mktemp.c, lib/util/nanosleep.c, lib/util/parseln.c,
+ lib/util/pipe2.c, lib/util/progname.c, lib/util/pw_dup.c,
+ lib/util/regress/atofoo/atofoo_test.c,
+ lib/util/regress/fnmatch/fnm_test.c,
+ lib/util/regress/glob/globtest.c,
+ lib/util/regress/parse_gids/parse_gids_test.c,
+ lib/util/regress/progname/progname_test.c,
+ lib/util/regress/strsplit/strsplit_test.c,
+ lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_parseln/parseln_test.c,
+ lib/util/regress/tailq/hltq_test.c,
+ lib/util/regress/vsyslog/vsyslog_test.c, lib/util/secure_path.c,
+ lib/util/setgroups.c, lib/util/sha2.c, lib/util/sig2str.c,
+ lib/util/snprintf.c, lib/util/strlcat.c, lib/util/strlcpy.c,
+ lib/util/strndup.c, lib/util/strnlen.c, lib/util/strsignal.c,
+ lib/util/strsplit.c, lib/util/strtobool.c, lib/util/strtoid.c,
+ lib/util/strtomode.c, lib/util/strtonum.c, lib/util/sudo_conf.c,
+ lib/util/sudo_debug.c, lib/util/sudo_dso.c, lib/util/term.c,
+ lib/util/ttysize.c, lib/util/utimens.c, lib/util/vsyslog.c,
+ lib/zlib/Makefile.in, m4/sudo.m4, mkdep.pl, mkpkg, pathnames.h.in,
+ plugins/group_file/Makefile.in, plugins/group_file/getgrent.c,
+ plugins/group_file/group_file.c, plugins/group_file/plugin_test.c,
+ plugins/sample/Makefile.in, plugins/sample/sample_plugin.c,
+ plugins/sudoers/Makefile.in, plugins/sudoers/alias.c,
+ plugins/sudoers/audit.c, plugins/sudoers/auth/afs.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h, plugins/sudoers/base64.c,
+ plugins/sudoers/boottime.c, plugins/sudoers/bsm_audit.c,
+ plugins/sudoers/bsm_audit.h, plugins/sudoers/check.c,
+ plugins/sudoers/check.h, plugins/sudoers/defaults.c,
+ plugins/sudoers/defaults.h, plugins/sudoers/digestname.c,
+ plugins/sudoers/editor.c, plugins/sudoers/env.c,
+ plugins/sudoers/env_pattern.c, plugins/sudoers/filedigest.c,
+ plugins/sudoers/filedigest_gcrypt.c,
+ plugins/sudoers/filedigest_openssl.c, plugins/sudoers/find_path.c,
+ plugins/sudoers/gc.c, plugins/sudoers/gentime.c,
+ plugins/sudoers/getspwuid.c, plugins/sudoers/gmtoff.c,
+ plugins/sudoers/goodpath.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/hexchar.c, plugins/sudoers/ins_2001.h,
+ plugins/sudoers/ins_classic.h, plugins/sudoers/ins_csops.h,
+ plugins/sudoers/ins_goons.h, plugins/sudoers/insults.h,
+ plugins/sudoers/interfaces.c, plugins/sudoers/interfaces.h,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog.h,
+ plugins/sudoers/iolog_path.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/linux_audit.h,
+ plugins/sudoers/locale.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h, plugins/sudoers/logwrap.c,
+ plugins/sudoers/match.c, plugins/sudoers/match_addr.c,
+ plugins/sudoers/mkdir_parents.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h, plugins/sudoers/po/sudoers.pot,
+ plugins/sudoers/policy.c, plugins/sudoers/prompt.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/pwutil.h,
+ plugins/sudoers/pwutil_impl.c, plugins/sudoers/rcstr.c,
+ plugins/sudoers/redblack.c, plugins/sudoers/redblack.h,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/env_match/check_env_pattern.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/regress/parser/check_gentime.c,
+ plugins/sudoers/regress/parser/check_hexchar.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudo_nss.h,
+ plugins/sudoers/sudo_printf.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoers2ldif,
+ plugins/sudoers/sudoers_debug.c, plugins/sudoers/sudoers_debug.h,
+ plugins/sudoers/sudoers_version.h, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/timeout.c,
+ plugins/sudoers/timestamp.c, plugins/sudoers/timestr.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.h,
+ plugins/sudoers/toke.l, plugins/sudoers/toke_util.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/tsgetgrpw.h,
+ plugins/sudoers/visudo.c, plugins/sudoers/visudo_json.c,
+ plugins/system_group/Makefile.in,
+ plugins/system_group/system_group.c, po/sudo.pot, src/Makefile.in,
+ src/conversation.c, src/env_hooks.c, src/exec.c, src/exec_common.c,
+ src/exec_monitor.c, src/exec_nopty.c, src/exec_pty.c, src/get_pty.c,
+ src/hooks.c, src/load_plugins.c, src/net_ifs.c, src/openbsd.c,
+ src/parse_args.c, src/preload.c, src/preserve_fds.c,
+ src/regress/noexec/check_noexec.c,
+ src/regress/ttyname/check_ttyname.c, src/selinux.c, src/sesh.c,
+ src/signal.c, src/solaris.c, src/sudo.c, src/sudo.h,
+ src/sudo_edit.c, src/sudo_exec.h, src/sudo_noexec.c,
+ src/sudo_plugin_int.h, src/sudo_usage.h.in, src/tcsetpgrp_nobg.c,
+ src/tgetpass.c, src/ttyname.c, src/utmp.c, sudo.pp:
+ update my email to Todd.Miller@sudo.ws
+ [96110003e904]
+
+2017-12-02 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sudoreplay.c:
+ Add missing carriage return before prompt when replay is done.
+ [cf4b8bfcb3dd]
+
+ * src/exec_pty.c:
+ Track window size changes that happen while sudo is suspended
+ [cae06f75bde9]
+
+2017-12-01 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [26ae754b8416]
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo_plugin.cat,
+ doc/sudoers.cat, doc/sudoers.ldap.cat, doc/sudoreplay.cat,
+ doc/visudo.cat:
+ regen for sudo 1.8.22
+ [596d82da0158]
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.8.22
+ [6b32c2f5d020]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Background processes started by the command will no longer receive
+ SIGHUP.
+ [47bcc3ae4362]
+
+ * src/exec_monitor.c:
+ When the command completes, make the monitor the foreground process
+ group before informing the main sudo process of the command's exit
+ status. This will prevent processes started by the command (which
+ runs in a different process group) from receiving SIGHUP since the
+ kernel sends SIGHUP to the foreground process group associated with
+ the terminal session. The monitor has a SIGHUP handler installed so
+ the signal is effectively ignored.
+ [9e163efe4afb]
+
+ * src/sudo.c:
+ Add debug printfs around group list retrieval.
+ [5f307b00153b]
+
+2017-11-30 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_pty.c:
+ Move call to sudo_ev_loopcontinue() into schedule_signal() itself.
+ We always want to prioritize signal forwarding.
+ [4b25dc24038b]
+
+ * src/exec_monitor.c, src/exec_nopty.c, src/exec_pty.c:
+ Don't loop over read/write, recv/send or tcgetpgrp/tcsetpgrp trying
+ to handle EINTR. We now use SA_RESTART with signals so this is not
+ needed and is potentially dangerous if it is possible to receive
+ SIGTTIN or SIGTTOU (which it currently is not).
+ [ba6885b57891]
+
+2017-11-29 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * src/exec_monitor.c, src/signal.c:
+ Sprinkle some extra debugging printfs
+ [bf33574bc603]
+
+ * src/exec_pty.c:
+ We don't need to be the foreground process to be able to write to
+ the terminal in most cases. If the background process tries to
+ modify the terminal flags it will receive SIGTTOU which is relayed
+ to the sudo front-end. This currently mishandles terminals with the
+ TOSTOP local flag set.
+ [3fc25570d482]
+
+ * src/exec_pty.c:
+ Handle receipt of SIGTTIN/SIGTTOU when reading/writing from/to the
+ tty. We can't use a signal event for these since that would restart
+ the system call after the signal was handled and the callback would
+ not get a chance to run. Fixes running a command in the background
+ that write to the tty when the TOSTOP terminal flag is set.
+ [5ac68f05249a]
+
+2017-11-28 Todd C. Miller <Todd.Miller@sudo.ws>
+
+ * plugins/sudoers/sssd.c:
+ Avoid a double free when ipa_hostname is set in sssd.conf and it is
+ an unqualified host name. From Daniel Kopecek.
+
+ Also move the "unable to allocate memory" warning into
+ get_ipa_hostname() itself to make it easier to see where the
+ allocation failed in the debug log.
+ [14dacdea3319]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/policy.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/pwutil.h,
+ plugins/sudoers/pwutil_impl.c, plugins/sudoers/set_perms.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ When running a command as the invoking user we cannot use the gid
+ list from the front-end since it may not correspond to the user's
+ aux group vector as defined by the group database.
+ [b456101fe509]
+
+ * lib/util/regress/fnmatch/fnm_test.c,
+ lib/util/regress/glob/globtest.c,
+ plugins/sudoers/regress/env_match/check_env_pattern.c,
+ plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/parser/check_gentime.c,
+ plugins/sudoers/regress/parser/check_hexchar.c:
+ Add missing initprogname() calls.
+ [ad4f8d236d89]
+
+2017-11-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Better describe things when a command is run in a pty.
+ [0f34fc342ab5]
+
+2017-11-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Plug some memory leaks on error, some found by the clang static
+ analyzer.
+ [62844cc145b6]
+
+2017-11-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/parse.c:
+ Avoid calling cmnd_matches() in list/verify mode if we already have
+ a match.
+ [5bddfc911065]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/parse.c,
+ plugins/sudoers/sssd.c:
+ In list (-l) or verify (-v) mode, if we have a match but
+ authentication is required, clear FLAG_NOPASSWD so that when
+ listpw/verifypw is set to "all" and there are multiple sudoers
+ sources a password will be required unless none of the entries in
+ all sources require authentication. From Radovan Sroka of RedHat
+ [edac7222600a]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ When checking the results for "sudo -l" and "sudo -v", keep checking
+ even after we get a match since the value of doauth may depend on
+ evaluating all the results. From Radovan Sroka of RedHat.
+ [ae0704445bd4]
+
+2017-11-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ If passwd_tries is less than 1, check_user() will always return
+ false (since the user didn't authenticate). The normal reason for
+ this is an authentication error but in this case no authentication
+ was tries so no warning message has been displayed to the user. If
+ the user wasn't given a chance to authenticate, set inform_user to
+ true when calling log_denial() from sudoers_policy_main().
+
+ An alternate approach would be for check_user() to return true in
+ this case but seems more confusing.
+ [c8be95b46e9d]
+
+2017-10-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/TROUBLESHOOTING:
+ Document bash shell alias issue with "sudo -i".
+ [8affa5376277]
+
+2017-10-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/policy.c:
+ Return an error if the sudo front end doesn't set the user name,
+ user ID, group ID or host name. Bug #807
+ [03e281d93fff]
+
+ * lib/util/gethostname.c:
+ Treat an empty hostname as a failure and return NULL.
+ [fafb3a3083cb]
+
+2017-10-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers2ldif:
+ Add support for #include and #includedir from Natale Vinto.
+ [926deea0d506]
+
+2017-10-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS:
+ Minor corrections from Tae Wong
+ [dbc5ee98ffa6]
+
+2017-10-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Add a warning that for "sudo -i command" and "sudo -s command" the
+ shell is not run in interactive mode which may change its behavior.
+ [76c19db05a1e]
+
+2017-09-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/sudo_compat.h, src/exec_pty.c:
+ Fix stair-stepped output when the output of a sudo command is piped
+ to another command and use_pty is set.
+ [e91e3f12d2d4]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ env_keep and env_check are also taken into account with "sudo -i".
+ Bug #806
+ [5f5568c6fdd9]
+
+2017-09-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, config.h.in, configure, configure.ac,
+ plugins/sudoers/ins_classic.h:
+ Make PC insults the default and add new configure option, enable-
+ offensive-insults, to enable the offensive insults.
+ [eb264d342601]
+
+2017-09-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS:
+ Add missing translators from recent updates and one name change.
+ [20828c25ad92]
+
+2017-09-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/po/fur.po, plugins/sudoers/po/hr.mo,
+ plugins/sudoers/po/hr.po, plugins/sudoers/po/sv.mo,
+ plugins/sudoers/po/sv.po, po/hr.mo, po/hr.po, po/sv.mo, po/sv.po:
+ sync with translationproject.org
+ * * * sync with translationproject.org
+ [24bb066fa19f]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ More accurately describe the use_pty option now that its behavior
+ has changed with respect to interposition with a pipe. Also describe
+ some caveats with log_input.
+ [a87056499931]
+
+ * doc/UPGRADE:
+ Document changes in use_pty behavior when no terminal is present.
+ [a4b978693178]
+
+ * src/exec_pty.c:
+ Set ec->cmnd_pid to the correct value when receiving the command's
+ process ID from the monitor.
+ [a624309ba848]
+
+ * src/exec.c, src/exec_nopty.c, src/exec_pty.c, src/sudo_exec.h:
+ If /dev/tty is not available and no I/O logging plugins are
+ configured, fall back on exec_nopty() even if the policy plugin
+ requested a pty. We never allocate a pty when sudo is not run from a
+ terminal anyway.
+ [c9b9c6c4e0ad]
+
+ * src/exec_pty.c:
+ Do not set utmp_user if we did not actually allocate a pty.
+ [aa8e0fdea32b]
+
+2017-09-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, configure, configure.ac:
+ sudo 1.8.21p2
+ [94d18888e7c4]
+
+ * src/exec.c:
+ sudo_terminated() should not return true when SIGCHLD is pending.
+ Bug #801
+ [57f636b6489f]
+
+ * src/tgetpass.c:
+ Set SIGCHLD handler to SIG_DFL before forking the askpass command
+ and restore after. Otherwise, SIGCHLD will end up in the list of
+ pending signals and sudo_execute() will not execute the command.
+ [c171eeabdc72]
+
+ * lib/util/event.c:
+ The read and write sides of signal_pipe[] were swapped, resulting in
+ EBADF reading from and writing to the signal pipe on Linux and
+ probably others. On systems with bidirectional pipes this was not an
+ issue.
+ [7668f93e6544]
+
+2017-09-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/pam.c:
+ Fix a logic error in 96651906de42 which prevented sudo from using
+ the PAM-supplied prompt. Bug #799
+ [6ee5cc13af69]
+
+2017-09-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.8.21p1
+ [7e6bf56cb06c]
+
+ * mkpkg:
+ The Fedora sudo package uses /etc/ldap.conf not /etc/sudo-ldap.conf.
+ [7b4e6f50e138]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ The fix for matching when no sudoRunAsUser is present in a sudoRole
+ was incomplete. If no -g option was specified on the command line
+ but sudoRunAsGroup is present in a sudoRole, we need to treat the
+ group match as failed instead of missing.
+ [3aaeeebd924c]
+
+ * plugins/sudoers/check.c, plugins/sudoers/defaults.c:
+ Sprinkle a few more debugging printfs.
+ [f7a40f9985cf]
+
+ * plugins/sudoers/sudoreplay.c:
+ Fix replaying sessions that contain input logs. When the inter-
+ record timeout expires we need to read the next record if there is
+ nothing to output.
+ [443b329ddc60]
+
+ * doc/visudo.cat:
+ regen
+ [7ace4ac32116]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Fix typo (Auguest vs. August). From David Pocock.
+ [98a792ff1c90]
+
+2017-08-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudo_nss.c:
+ Go back to returning true from display_privs() on non-error. This
+ results in "sudo -U otheruser -l" exiting with a status of 0 even
+ when otheruser is not allowed to run commands. This is appropriate
+ since the "sudo -l" command was successful. This does not change the
+ exit value when otheruser runs "sudo -l" themselves, the exit status
+ will be 1 since that user is not allowed to run commands. Requested
+ by Radovan Sroka.
+ [055b78015fcb]
+
+ * plugins/sudoers/ldap.c:
+ Fix the pass2 ldap query string when no search filter is defined.
+ Due to the addition of "(sudoUser=*)" to the query we always need
+ the AND operator, even if no search filter is present.
+ [631243487d27]
+
+2017-08-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_nopty.c:
+ Don't forward SIGINFO to the child when it is send by the kernel
+ (not another user process). This is consistent with the handling of
+ other keyboard-generated signals such as SIGINT, SIGQUIT and
+ SIGTSTP. Bug #796
+ [29603b0a4315]
+
+2017-08-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Fix path to LICENSE and NEWS files that get used in the installer.
+ Previously, the installed versions were used instead of the ones in
+ the destdir.
+ [689a5806f2de]
+
+2017-08-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po, po/fi.mo,
+ po/fi.po:
+ sync with translationproject.org
+ [32a0f3bbba31]
+
+2017-08-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * po/es.mo, po/es.po:
+ sync with translationproject.org
+ [bfa5659d66f2]
+
+2017-08-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po, po/it.mo,
+ po/it.po:
+ sync with translationproject.org
+ [05cd6ff68a4b]
+
+2017-08-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Preserving environment variables on the command line was bug #279
+ [46f2c7931a84]
+
+2017-08-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, NEWS, doc/CONTRIBUTORS, po/fur.mo, po/fur.po:
+ Add Friulian translation for sudo from Fabio Tomat via
+ translationproject.org
+ [77fdb76e83c8]
+
+2017-08-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po, po/cs.mo,
+ po/cs.po, po/fr.mo, po/fr.po, po/ko.mo, po/ko.po, po/nb.mo,
+ po/nb.po, po/pl.mo, po/pl.po, po/pt_BR.mo, po/pt_BR.po, po/sr.mo,
+ po/sr.po, po/sv.mo, po/sv.po, po/vi.mo, po/vi.po, po/zh_CN.mo,
+ po/zh_CN.po:
+ sync with translationproject.org
+ [0f18e2f30ff5]
+
+2017-08-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ In the Runas example that uses "boulder" make it clear that
+ "boulder" is a host name.
+ [6bca59aa5579]
+
+2017-08-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [9bb78048656f]
+
+ * NEWS, doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in,
+ src/parse_args.c:
+ Allow the user to specify a list of environment variables to
+ preserve. This adds an option paramter to the --preserve-env option,
+ a comma-separated list of variable names.
+ [a6bc511a2e81]
+
+2017-08-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, NEWS, config.h.in, configure, configure.ac,
+ doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/timestamp.c:
+ Replace tty_tickets option with timestamp_type which can be global,
+ ppid or tty. Defaults to tty (no change in behavior). Some users
+ want the ppid behavior.
+ [426161a2e06f]
+
+ * lib/util/Makefile.in, plugins/sudoers/Makefile.in:
+ regen
+ [b396e70a4a8b]
+
+ * plugins/sudoers/sudoers.c:
+ Don't send email about an unresolvable host name if fqdn is enabled
+ and the user specified the run host via the -h flag.
+ [59d7a8743943]
+
+2017-07-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c:
+ fix playback of stdout/stderr without embedded carriage returns
+ [f1a5b47be2db]
+
+2017-07-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Avoid unused variable warning when sasl is not used.
+ [3010fd3c5a7f]
+
+ * INSTALL, configure, configure.ac:
+ Add support for --enable-sasl and --disable-sasl to make it possible
+ to enable/disable support for LDAP with SASL authentication. Sudo
+ compiles in support for SASL authentiation by default if the
+ ldap_sasl_interactive_bind_s() function is detected. Bug #788
+ [cf94d407d576]
+
+ * NEWS:
+ List the correct pattern ("*=()*") in the env_delete description.
+ Use pseudo-tty instead of pseudo terminal for consistency.
+ [f2df0baea2f0]
+
+2017-07-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/closefrom.c:
+ Include pathnames.h for /dev/fd on FreeBSD and Mac OS X.
+ [b190dc607277]
+
+ * NEWS:
+ update for 1.8.21
+ [a3a38f6cba66]
+
+ * src/exec_pty.c:
+ No need to call sudo_ev_del() before sudo_ev_free(); sudo_ev_free()
+ will delete the event from its base before freeing it.
+ [ebf3dedcba5c]
+
+ * src/exec_pty.c:
+ Terminate the command if an I/O log function returns 0 or -1. This
+ was mistakenly removed by 25b7fd056614 in Sudo 1.8.18 with the
+ removal of the ignore_iolog_errors variable.
+ [e1dd18d95815]
+
+ * plugins/sudoers/sudoreplay.c:
+ Quiet a coverity false positive.
+ [b7a9c9e35fd0]
+
+ * plugins/sudoers/sudoreplay.c:
+ Change to a single event loop in sudoreplay and use signal events.
+ [7320de46cf48]
+
+2017-07-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.conf.cat, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in:
+ start new sentences on a new line
+ [ae35ab253de5]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Clarify how the variable prompt options interact with each other and
+ PAM.
+ [342b936c4aaa]
+
+ * plugins/sudoers/sudoers.c:
+ Don't set passprompt_override when SUDO_PROMPT is present. This
+ effectively reverts ed77d255f383.
+
+ We treat the SUDO_PROMPT environment variable similar to passprompt
+ in sudoers: it will only override a PAM prompt if the PAM prompt is
+ either "Password:" or "username's Password:".
+ [6dad2bd126d1]
+
+2017-07-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/logging.c:
+ Add syslog_pid sudoers option to log sudo's process ID when logging
+ via syslog. This is disabled by default to match historic behavior.
+ [f4dc29b0052c]
+
+ * plugins/sudoers/auth/pam.c:
+ When deciding which prompt to use (PAM's or sudo's) treat the PAM
+ prompt "username's Password:" as equivalent to "Password:". Some PAM
+ modules (on AIX at least) use this prompt.
+ [96651906de42]
+
+ * plugins/sudoers/def_data.c, plugins/sudoers/def_data.in:
+ Add missing argument to a few of the defaults strings in the "sudo
+ -V" output.
+ [44546c4b87c3]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/visudo.c:
+ When examining environment variables or variables passed in from the
+ front-end, ignore variables with no value specified.
+ [8537a7fc6190]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Document that "-p prompt" overrides SUDO_PROMPT.
+ [d2e6b518d00d]
+
+ * plugins/sudoers/sudoers.c:
+ Enable passprompt_override by default if SUDO_PROMPT is present in
+ the environment. This is consistent with how "sudo -p prompt" is
+ handled.
+ [ed77d255f383]
+
+2017-07-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c:
+ When reading a single character via a switch() use "default: instead
+ of "case 1:" to quiet a coverity warning.
+ [ddcfc40159e4]
+
+ * plugins/sudoers/sudoreplay.c:
+ Initialize ch in getsize_cb() in case we are called with the wrong
+ initial state.
+ [a31431c59e14]
+
+ * plugins/sudoers/sudoreplay.c:
+ remove unused variable
+ [488054411049]
+
+ * plugins/sudoers/visudo.c:
+ Call install_sudoers() even when doedit is false. If a file in a
+ #includedir has a syntax error it will still have been edited and we
+ need to install the edited temp file.
+ [ab833e2d1791]
+
+ * plugins/sudoers/visudo.c:
+ Reparse sudoers if a new #include file was added. Otherwise the new
+ file will not get its syntax checked. Bug #791
+ [e584dc8bf306]
+
+2017-07-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c:
+ don't restore the cursor when setting terminal size, we don't want
+ the cursor to move
+ [9cbcb3372bcd]
+
+ * plugins/sudoers/sudoreplay.c:
+ Read the xterm terminal size using an event so we can easily time
+ out if needed.
+ [634524476741]
+
+ * lib/util/event.c, src/exec_nopty.c, src/exec_pty.c:
+ If we free the default base in sudo_ev_base_free(), reset the
+ default base to NULL.
+ [2a8f7938618b]
+
+2017-07-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/sudo_event.h, lib/util/event.c, lib/util/util.exp.in,
+ src/exec_monitor.c, src/exec_nopty.c, src/exec_pty.c:
+ Add the ability to set a default event base, to be used by plugins
+ which don't have access to the event base.
+ [dc159ea98b25]
+
+ * doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in,
+ plugins/sudoers/sudoreplay.c:
+ Allow sudoreplay to adjust the window size on xterm-like terminals.
+ [3358b1a9f01c]
+
+2017-07-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/term.c:
+ Clear input, output, control and local flags before copying them
+ from the source terminal. Otherwise, flags that are disabled in the
+ source terminal may still be enabled in the destination.
+ [ead41242b820]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, include/sudo_plugin.h, src/exec_pty.c:
+ Pass window size change events to the plugin.
+ [529b5c9d16a4]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/sudoreplay.c:
+ Log window size change events in the sudoers I/O plugin. Let
+ sudoreplay parse a timing file with window change events (currently
+ ignored).
+ [a67f4627dfa7]
+
+ * Makefile.in, doc/Makefile.in, examples/Makefile.in,
+ include/Makefile.in, lib/util/Makefile.in, lib/zlib/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in,
+ src/Makefile.in:
+ Remove pointless subshells in targets that simply change the
+ directory and execute a command. The command is already run in a
+ shell so there is no need to execute a subshell in this case.
+ [e57639cb2f97]
+
+2017-07-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo.c:
+ Store the debug instance ID for I/O plugins too. Now iolog_open() is
+ consistent with policy_open().
+ [519abb3c09d0]
+
+2017-06-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.ac, lib/util/mktemp.c:
+ Use getentropy() in mkstemp/mkdtemp replacement.
+ [8d8e45266858]
+
+ * configure, configure.ac, lib/util/closefrom.c, lib/util/mktemp.c,
+ pathnames.h.in, src/exec_pty.c, src/get_pty.c, src/ttyname.c:
+ Use _PATH_DEV consistently
+ [ca10a91539e0]
+
+2017-06-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/term.c:
+ When copying terminal settings from one tty to another only copy a
+ subset of the flags. Sudo now copies the same set of flags that
+ OpenSSH uses, which should be safe.
+ [2f12bc7a87d1]
+
+ * src/exec_monitor.c, src/exec_nopty.c:
+ Add debug warning when we have wait status but don't overwrite the
+ existing cstat.
+ [5ae8f8e75104]
+
+ * src/exec_monitor.c:
+ Better handling of SIGCONT from in command in the monitor. It is
+ useful to know when the command continued but we don't want to
+ inform the parent or store the wait status in this case. Fixes a
+ hang after multiple suspends on Linux.
+ [9cdbbb7ff3dd]
+
+2017-06-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/parse.h:
+ avoid padding in struct cmndspec
+ [2529551a9c2d]
+
+2017-06-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudoers.cat, doc/sudoers.ldap.cat, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in:
+ Fix the man section of sudo_plugin in cross-references.
+ [f964de570403]
+
+2017-06-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo_edit.c:
+ Don't treat an unchanged file as an error. From Xin Li.
+ [503e04f7856e]
+
+ * src/sudo_edit.c:
+ sudo_edit() must return a wait status but if there is an error, or
+ even if no changes were made to the file, it was returning 1 instead
+ which would be interpreted as the command having received SIGHUP.
+ Use the W_EXITCODE() to construct a proper wait status in the error
+ case too.
+ [62515bd6c64c]
+
+2017-06-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/ttyname.c:
+ Avoid sign extension when assigning the value of tty_nr in
+ /proc/self/stat on Linux. It is an unsigned int value that is
+ printed as a signed int but dev_t is unsigned long long. We need to
+ cast to unsigned int before assigning to a dev_t.
+ [c198d1317560]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/env.c:
+ Instead of hard-coding a check for bash functions in
+ env_should_delete(), use a "*=()* " pattern in
+ initial_badenv_table[] to match them instead. This allows the user
+ to remove the check via env_delete.
+ [90c4dfd1d3a3]
+
+2017-06-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL.configure, configure.ac, doc/sudo_plugin.cat,
+ doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, mkpkg, sudo.pp:
+ Mac OS X -> macOS
+ [08f793d1f496]
+
+ * doc/sudo.conf.cat, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in:
+ devsearch is ignored on BSD, macOS and Solaris
+ [b041a1d64eda]
+
+2017-06-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/event.c:
+ Move the bits to fill in the new event base to sudo_ev_base_init(),
+ which is not currently exported.
+ [9be46693bed1]
+
+2017-05-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/ttyname.c:
+ A command name may also contain newline characters so read
+ /proc/self/stat until EOF. It is not legal for /proc/self/stat to
+ contain embedded NUL bytes so treat the file as corrupt if we see
+ any. With help from Qualys.
+
+ This is not exploitable due to the /dev traversal changes in sudo
+ 1.8.20p1 (thanks Solar!).
+ [9ad60fe663e5]
+
+ * NEWS:
+ Sudo 1.8.20p2
+ [39f199a38383]
+
+2017-05-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/selinux.c:
+ After opening a tty device, fstat() and error out if it is not a
+ character device.
+ [e03cfa98f2b6]
+
+ * INSTALL, configure, configure.ac, doc/sudo.conf.cat,
+ doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in, include/sudo_conf.h,
+ lib/util/sudo_conf.c, lib/util/util.exp.in, pathnames.h.in,
+ src/ttyname.c:
+ Add a new "devsearch" Path setting to sudo.conf for configuring the
+ /dev paths to traverse instead of hard-coding a list in ttyname.c
+ The default value can be set at configure time.
+ [7ab1be502dc3]
+
+ * src/ttyname.c:
+ Use /proc/self consistently on Linux. As far as I know, only AIX
+ doesn't support /proc/self.
+ [ef737b5d4ed8]
+
+2017-05-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, configure:
+ Sudo 1.8.20p1
+ [c34da84ae8e4]
+
+ * src/ttyname.c:
+ Fix for CVE-2017-1000367, parsing of /proc/pid/stat on Linux when
+ the process name contains spaces. Since the user has control over
+ the command name this could be used by a user with sudo access to
+ overwrite an arbitrary file. Thanks to Qualys for investigating and
+ reporting this bug.
+
+ Also stop performing a breadth-first traversal of /dev when looking
+ for the device. Only the directories specified in search_devs[] are
+ checked.
+ [b5460cbbb11b]
+
+2017-05-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/event_select.c:
+ Fix potential memory leak on reallocarray() error. Coverity CID
+ 169639
+ [c303e6eecc78]
+
+ * plugins/sudoers/bsm_audit.c:
+ Only fall back to deprecated getaudit() on FreeBSD. Fixes compiler
+ warnings on macOS.
+ [18f4699e417c]
+
+ * mkpkg:
+ Use clang on macOS if present
+ [a963454d1b9e]
+
+ * sudo.pp:
+ fix paths to LICENSE and NEWS files for macOS packages
+ [47103614311b]
+
+2017-05-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_monitor.c, src/exec_nopty.c, src/exec_pty.c:
+ To avoid overwriting existing command status, check for CMD_INVALID
+ instead of CMD_ERRNO or CMD_WSTATUS.
+ [5fec1fa81482]
+
+ * plugins/sudoers/regress/env_match/data:
+ Add some patterns that could result in exponential run time for
+ poorly written '*' matching.
+ [98f4d085c919]
+
+2017-05-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/ttysize.c, src/exec_pty.c:
+ On HP-UX 11.0, sys/ioctl.h is not sufficient to make struct winsize
+ visisble, we need termios.h too.
+ [211510123ad6]
+
+ * lib/util/ttysize.c:
+ Always used TIOCGWINSZ.
+ [82e679b8cd00]
+
+ * src/exec.c, src/sudo.c, src/sudo.h:
+ Move exec_setup(), unlimit_nproc() and restore_nproc() from sudo.c
+ to exec.c.
+ [9127e50cf4ec]
+
+ * src/sudo_edit.c:
+ No need to include selinux.h here.
+ [8bb07a8f4203]
+
+ * plugins/sudoers/regress/env_match/check_env_pattern.c:
+ Fix compilation error on macOS
+ [bc5e5c3d44f2]
+
+2017-05-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h,
+ lib/util/term.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/visudo.c, src/exec_monitor.c, src/exec_nopty.c,
+ src/exec_pty.c, src/signal.c, src/sudo.c, src/tcsetpgrp_nobg.c,
+ src/tgetpass.c:
+ Remove use of non-standard sigaction_t
+ [81a57af4c7a9]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/mkdir_parents.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/visudo.c:
+ Use debug logging instead of ignore_result() where possible.
+ [9c9fde5b52cc]
+
+ * Makefile.in:
+ Add cov-build and cov-submit targets for checking with coverity.
+ [bf88b4439c7b]
+
+ * plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/ldap.c:
+ Avoid a clang analyzer false positive.
+ [9f4f915a2e28]
+
+ * plugins/sudoers/sudoreplay.c:
+ Restore the error message for sudo_ev_add() failure.
+ [267305606577]
+
+ * include/sudo_event.h, lib/util/event.c:
+ Add support for signal events in sudo's event subsystem
+ [0d48fab2dec8]
+
+ * include/sudo_event.h, lib/util/event.c:
+ Handle the possibility of the siginfo parameter in sa_sigaction
+ handler being NULL.
+ [0835ca553426]
+
+ * src/exec.c, src/exec_monitor.c, src/exec_nopty.c, src/exec_pty.c,
+ src/signal.c, src/sudo.h, src/sudo_exec.h:
+ Use SUDO_EV_SIGNAL and SUDO_EV_SIGINFO instead of managing the
+ signal_pipe explicitly.
+ [841e2ca6a4a6]
+
+ * lib/util/event.c:
+ Activate the sigevents inside the signal pipe callback itself and
+ call signal_pipe_cb() directly if the backend returns EINTR and the
+ signal_caught flag is set. This has the side effect of processing
+ signal events in the current pass of the event loop instead of the
+ next one.
+ [d94e202b8e57]
+
+ * src/signal.c:
+ Add SIGCHLD to the list of signals we install sudo_handler() for.
+ Otherwise, it is possible for the command to exit before the SIGCHLD
+ handler is installed. POSIX says that signals that are ignored by
+ default are still ignored even if the signal mask would block them.
+ We need to have a handler installed for SIGCHLD before the fork().
+ [a26f04459c37]
+
+ * MANIFEST, doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/env.c,
+ plugins/sudoers/env_pattern.c,
+ plugins/sudoers/regress/env_match/check_env_pattern.c,
+ plugins/sudoers/regress/env_match/data, plugins/sudoers/sudoers.h:
+ Add support for multiple '*' in env_keep, env_check and env_delete
+ entries.
+ [b55270a8ecc4]
+
+ * configure, configure.ac:
+ sudo 1.8.21
+ [76aa5455903e]
+
+ * include/sudo_compat.h, plugins/sudoers/timestamp.c,
+ src/tcsetpgrp_nobg.c, src/tgetpass.c:
+ Remove use of the non-standard SA_INTERRUPT
+ [3ec05ffb0dcb]
+
+ * include/sudo_queue.h:
+ Add workaround for clang static analyzer being confused by
+ LIST_REMOVE and TAILQ_REMOVE.
+ [ff8d278e8526]
+
+2017-05-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ Fix "make check" when openssl or gcrypt is used. Bug #787
+ [7968686742e2]
+
+2017-05-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c:
+ Only display string version of errno if sudo_ev_add() fails for now
+ [24244a02c93f]
+
+2017-05-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ update
+ [8e3359235e24]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Be clear that #includedir diverts control to the files in the
+ specified directory and, when parsing of those files is complete,
+ returns control to the original file. Bug #775
+ [f68769f15356]
+
+2017-05-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po, po/sr.mo,
+ po/sr.po:
+ sync with translationproject.org
+ [4552eaf8fabf]
+
+2017-05-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ update
+ [53d1c9424816]
+
+ * src/exec_monitor.c:
+ Fix a hang introduced in the last commit. Don't close the pty slave
+ until after we have the controlling tty.
+ [c9c19beb60ed]
+
+ * src/exec_monitor.c, src/exec_pty.c:
+ If any of std{in,out,err} are not hooked up to a tty only interpose
+ ourselves with a pipe if the plugin will actually log the data. This
+ avoids a problem with non-interactive commands where no tty is
+ present where sudo will consume stdin even when log_input is not
+ enabled in sudoers.
+ [a79edafdd307]
+
+ * NEWS:
+ update
+ [144ff056cd01]
+
+ * doc/TROUBLESHOOTING:
+ Update based on information from Michael Felt.
+ [7ea34380ba1d]
+
+2017-05-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c:
+ In check_input() when switch()ing on the return value of read(), use
+ the default label instead of 1 for the success case. It is only
+ reading a single byte so the two are equivalent but it reads better
+ using default.
+ [860682b86af5]
+
+ * plugins/sudoers/sudoreplay.c:
+ Check sudo_ev_add() return value. Coverity CID 168362
+ [b69779d3801f]
+
+ * plugins/sudoers/iolog.c:
+ Add io_open() wrapper for open(2) that retries with PERM_IOLOG if
+ open(2) fails with EACCES. Use io_open() instead of duplicate copies
+ of the same fallback code.
+ [09f7992f681b]
+
+ * plugins/sudoers/iolog.c:
+ Don't retry the open() if set_perms() fails.
+ [0808a9157037]
+
+ * plugins/sudoers/iolog.c:
+ Fix typo (fd2 vs. fd) caught by coverity, CID 168359.
+ [f68df770e06f]
+
+ * po/hu.mo, po/hu.po:
+ sync with translationproject.org
+ [ebef76dc27be]
+
+2017-05-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ Warn people not to use --enable-asan in production.
+ [ecb5c1143ef4]
+
+ * configure, configure.ac, src/Makefile.in:
+ Move the invocation of check_noexec into the main "check" target but
+ only run it if not cross compiling and whe CHECK_NOEXEC is not
+ empty.
+ [cba8fd3337c2]
+
+ * src/Makefile.in:
+ Move @CHECK_NOEXEC@ to TEST_PROGS so it gets cleaned up properly.
+ [efaa9c44e749]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Move syslog_maxlen to the "Integers" section. Move syslog_goodpri
+ and syslog_badpri to the "Strings at can be used in a boolean
+ context" section.
+ [342dfe9dd37c]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Fix a pasto that resulted in an extra (empty) syslog_goodpri list
+ entry.
+ [eb0563c5b8dc]
+
+ * MANIFEST, plugins/sudoers/regress/sudoers/test20.in,
+ plugins/sudoers/regress/sudoers/test20.json.ok,
+ plugins/sudoers/regress/sudoers/test20.out.ok,
+ plugins/sudoers/regress/sudoers/test20.toke.ok,
+ plugins/sudoers/regress/sudoers/test21.in,
+ plugins/sudoers/regress/sudoers/test21.json.ok,
+ plugins/sudoers/regress/sudoers/test21.out.ok,
+ plugins/sudoers/regress/sudoers/test21.toke.ok:
+ Add tests for parsing tuples and syslog options.
+ [86f3da23b4df]
+
+ * plugins/sudoers/defaults.c:
+ Allow the syslog Defaults option to be used in a "true" boolean
+ context and use the compiled in default log facility in this case.
+ [4fab25217602]
+
+ * plugins/sudoers/defaults.c:
+ Allow a tuple to be set to boolean true. Regression introduced by
+ refactor of set_default_entry() in sudo 1.8.18.
+ [9b38728deb27]
+
+2017-05-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/TROUBLESHOOTING:
+ Replace the list of "dangerous" environment variables and explain
+ how sudo handles the environment instead.
+ [966cf87d1bed]
+
+2017-04-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/glob.c:
+ Fix exponential behavior in glob() with respect to multiple '*'. See
+ https://research.swtch.com/glob Adapted from https://perl5.git.perl.
+ org/perl.git/commit/33252c318625f3c6c89b816ee88481940e3e6f95
+ [3d187b0fb764]
+
+ * src/exec_pty.c:
+ We no longer need to write to the tty if the command was killed by a
+ signal. Sudo will terminate itself with the same signal the command
+ died from. Unfortunately, we lose the "core dumped" bit since sudo
+ itself will not dump core, but there doesn't appear to be a way
+ around that.
+ [1be331e0c4d4]
+
+2017-04-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo.c:
+ On Linux, if the command we ran dumped core, set PR_SET_DUMPABLE to
+ 0. This will prevent sudo itself from dumping core in this case.
+ [cf5a5793ebf4]
+
+ * INSTALL:
+ Update path to sudo_noexec.so
+ [14e995667c8b]
+
+ * src/sudo.c:
+ If the command terminated due to a signal, sudo will send that same
+ signal to itself so the parent shell knows the command died from a
+ signal. However, we don't want sudo itself to dump core.
+ [8d823e6ec41e]
+
+2017-04-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ sync
+ [1704e6005b07]
+
+ * src/sudo.c:
+ The fix for Bug #722 contained a typo/thinko that resulted in the
+ exit status being 0 when a command was killed by a signal other than
+ SIGINT. This fixes the signal handler setup so sudo will terminate
+ with the same signal as the command. Bug #784.
+ [50b988d0c97f]
+
+ * sudo.pp:
+ Better check for /etc/rc.d/rc2.d/S90sudo on AIX
+ [93de5e34a6a3]
+
+ * src/Makefile.in:
+ Don't install the rc.d link when installing to a DESTDIR. DESTDIR is
+ generally only set when installing to a temporary directory for
+ packaging in which case the link should be made in a post-install
+ script.
+ [4200ef757b56]
+
+ * plugins/sudoers/Makefile.in, sudo.pp:
+ In "make install", install sample sudoers file as /etc/sudoers.dist
+ and copy it to /etc/sudoers if there is no existing /etc/sudoers.
+ Packages either contain /etc/sudoers (RPM and Debian) or
+ /etc/sudoers.dist (everything else).
+ [40f8e5806d71]
+
+ * Makefile.in, mkdep.pl:
+ Allow "make dist" and "make depend" to work for out of tree builds.
+ [7b7ba3f38abb]
+
+2017-04-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/zlib/Makefile.in:
+ Add missing $(srcdir) prefix to shlib_exp definition.
+ [c63e8e73507e]
+
+2017-04-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/sudo_compat.h:
+ Fix typo in killpg macro.
+ [f7392d21c915]
+
+ * include/sudo_compat.h:
+ Fix the killpg macro for systems without killpg() in libc.
+ [ba0c5162bc4a]
+
+2017-04-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c:
+ Use the standard idiom for popping all entries from a tail queue.
+ The llvm checker gets confused by TAILQ_REMOVE and generate use-
+ after-free false positives.
+ [a88cacd23f09]
+
+ * src/exec_monitor.c, src/exec_nopty.c:
+ rewrite errpipe callbacks
+ [5c75729cea19]
+
+ * src/exec_monitor.c, src/exec_nopty.c:
+ use pipe2() with O_CLOEXEC instead of pipe() + fcntl() and
+ FD_CLOEXEC
+ [c8c9cc31c43a]
+
+ * src/exec_pty.c:
+ init io_pipe[][] to -1, not 0
+ [71012940a8f1]
+
+2017-04-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sssd.c:
+ In sudo_sss_check_user() it is not possible for handle to be NULL.
+ [de41ba76a4ce]
+
+ * plugins/sudoers/sssd.c:
+ Fix a use after free when the fqdn sudoOption is set and no hostname
+ value is present in sssd.conf.
+ [716a7c502cc0]
+
+ * src/sudo.c:
+ Avoid unused variable when getgrouplist_2() is available. It would
+ be nicer to just provide getgrouplist_2() (or the equivalent) and
+ avoid the ugly #ifdefs.
+ [2c7ac21feb5f]
+
+ * plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po, po/nb.mo,
+ po/nb.po:
+ sync with translationproject.org
+ [e91a983f9de6]
+
+2017-04-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ regen
+ [790d9a05f585]
+
+2017-04-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/ttyname.c:
+ In sudo_ttyname_scan() if dir is the empty string, set errno to
+ ENOENT before returning.
+ [f531ea6e489e]
+
+2017-04-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Try to make it clear that when match_group_by_gid is enabled, groups
+ in sudoers are looked up by group name instead of group ID. This
+ doesn't usually cause problems, but if there are conflicting group
+ entries (for example, from a local /etc/group file and an LDAP or AD
+ group database), whether the group is resolved by name or ID can be
+ used to work around conflicts.
+ [fe3bfca4fcce]
+
+2017-04-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po, po/ja.mo,
+ po/ja.po:
+ sync with translationproject.org
+ [94d36c45e345]
+
+ * plugins/sudoers/regress/parser/check_digest.c:
+ plug memory leak in check_digest
+ [40aab9e6e365]
+
+ * src/exec.c:
+ Check return value of dispatch_pending_signals() in case we received
+ SIGINT or SIGQUIT before executing the command.
+ [218758d1560d]
+
+2017-03-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ back out unintentional change to the version number
+ [799b396c1c69]
+
+2017-03-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po, po/cs.mo,
+ po/cs.po, po/da.mo, po/da.po, po/de.mo, po/de.po, po/fr.mo,
+ po/fr.po, po/hr.mo, po/hr.po, po/it.mo, po/it.po, po/pl.mo,
+ po/pl.po, po/pt_BR.mo, po/pt_BR.po, po/tr.mo, po/tr.po, po/uk.mo,
+ po/uk.po, po/vi.mo, po/vi.po, po/zh_CN.mo, po/zh_CN.po:
+ sync with translationproject.org
+ [04c4a3ec233d]
+
+2017-03-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac, plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/parser/check_digest.out.ok:
+ Make check_digest test sudo_filedigest() itself instead of the
+ underlying SHA2 functions. That way we can test it regardless of
+ whether we use sudo's SHA2 functions or a library version.
+ [9834b37f1fb0]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document that commands matched by "sudo ALL" are not affected by
+ fdexec.
+ [7cc3b770a2ff]
+
+2017-03-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Update for 1.8.20
+ [14a09000c1dc]
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen for restricted_env_file
+ [81290b370c95]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Mention that iolog_user is useful for NFS.
+ [9c8f9dfdebf0]
+
+2017-03-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ Only retry mkdir or create with PERM_IOLOG if errno is EACCES. Also
+ always use PERM_IOLOG for mkdtemp() since we cannot retry if it
+ fails. Since we are guaranteed to create a new directory there's no
+ real need to try w/o PERM_IOLOG in this case.
+ [c3c67d78e46a]
+
+2017-03-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ Add fallback to PERM_IOLOG when making the final componenet of
+ iolog_dir.
+ [72924e4c8f5d]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/env.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Add restricted_env_file which is like env_file but subject to the
+ same restrictions as the user's own environment.
+ [ec887cc57a8b]
+
+ * plugins/sudoers/iolog.c:
+ quiet a warning on older zlib
+ [bcd3cac968a2]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/timestamp.c:
+ cast mode_t to unsigned int when printing with %o
+ [f9ca9ead134e]
+
+2017-03-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [f62e81f74d10]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/mkdir_parents.c,
+ plugins/sudoers/timestamp.c:
+ Set umask temporarily when creating files instead of changing the
+ mode after the fact. This is slightly less error prone.
+ [a9b4cf336b73]
+
+ * plugins/sudoers/iolog.c:
+ remove now-useless variable
+ [9a36b2449ac4]
+
+ * plugins/sudoers/mkdir_parents.c:
+ Don't set owner/mode on directories that already exist, only on
+ newly-created ones.
+ [2b616be0e165]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/mkdir_parents.c:
+ Explicitly set the file mode of I/O log files so the mode is not
+ affected by the invoking user's umask.
+ [ec7d5dd47b6b]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/iolog.c, plugins/sudoers/mkdir_parents.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/timestamp.c:
+ Add PERM_IOLOG so we can create I/O log files on an NFS-mounted
+ filesystem where root is remapped to an unprivileged user.
+ [01804a971cd5]
+
+ * plugins/sudoers/mkdir_parents.c:
+ Restore the '/' in the path before returning if we encounter an
+ error.
+ [bb12cfce16fd]
+
+ * plugins/sudoers/sssd.c:
+ zero out nss->handle after it has been freed to make sure we cannot
+ free it twice
+ [00d5340b7541]
+
+2017-03-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/timestamp.c:
+ When creating the timestamp directory, use the group of the
+ timestamp owner instead of inheriting the group of the parent
+ directory.
+ [7a4a10cafe08]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/iolog.c:
+ Add iolog_flush option.
+ [96baa17409cf]
+
+2017-03-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/iolog.c:
+ Don't allow the user to specify an I/O log file mode that sudo can't
+ read or write to. I/O logs must always be readable and writable by
+ the owner.
+ [b32e2ef04905]
+
+2017-03-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo_plugin.cat,
+ doc/sudoers.cat, doc/sudoers.ldap.cat, doc/sudoreplay.cat,
+ doc/visudo.cat:
+ Regenerate the cat pages with newer mandoc which formats double
+ quotes as "foo" instead of ``foo''.
+ [5f14e527ae05]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Make it clear that I/O logs will be complete even if the command run
+ by sudo is terminated by a signal. The I/O log buffering just
+ prevents the logs from being displayed in real-time as the command
+ is running.
+ [072fd419ac1e]
+
+2017-03-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c, src/exec_monitor.c, src/signal.c, src/sudo.h:
+ Replace pipe_nonblock() with pipe2()
+ [c106b62d7835]
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, lib/util/Makefile.in, lib/util/pipe2.c,
+ mkdep.pl:
+ Emulate pipe2() on systems without it.
+ [5a183dd380f0]
+
+2017-03-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/kerb5.c:
+ Fix declaration of sudo_krb5_verify() in the case where
+ krb5_verify_user() is not present. Bug #777
+ [eafd4e2d7c7f]
+
+ * plugins/sudoers/rcstr.c:
+ Use HAVE_STDBOOL_H to detect systems w/o stdbool.h. Bug #778
+ [dbac86777429]
+
+2017-03-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [2fc489ddc143]
+
+ * src/exec_monitor.c, src/exec_nopty.c, src/exec_pty.c:
+ Move SIGCHLD handling into handle_sigchld() functions and move the
+ remaining bits of dispatch_signal() into signal_pipe_cb()
+ [b120f5cfa8cc]
+
+2017-03-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/utmp.c:
+ e_termination should be set to the value of WTERMSIG not WEXITSTATUS
+ [95f37078ae8f]
+
+2017-03-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, src/Makefile.in, src/exec_nopty.c, src/sudo.h,
+ src/tcsetpgrp_nobg.c:
+ Add tcsetpgrp_nobg() which acts like tcsetpgrp() but returns -1 for
+ a background process. This is safer than blocking SIGTTOU which
+ would cause tcsetpgrp() to succeed in the background.
+ [7ab75c47b8bf]
+
+2017-03-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_nopty.c:
+ Prevent sudo from receiving SIGTTOU when it tries to restore the
+ controlling terminal. There appears to be a race with the shell
+ (bash) which we may lose.
+ [aab018fb9940]
+
+2017-03-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/timestamp.c, src/exec_monitor.c:
+ Add some casts to quiet gcc warnings on Solaris and remove a now-
+ useless debug printf.
+ [16c862eab0ce]
+
+ * src/exec_pty.c:
+ change debug info when suspending sudo
+ [f5c5ee07f8e3]
+
+ * MANIFEST, src/Makefile.in, src/exec.c, src/exec_monitor.c,
+ src/exec_nopty.c, src/exec_pty.c, src/sudo_exec.h:
+ Reorganize the command execution code to separate out the pty and
+ non-pty code paths into their own event loops. The non-pty exec code
+ is now contained in exec_nopty.c and the pty exec code is split
+ between exec_pty.c (parent process) and exec_monitor.c (session
+ leader). This results in a small bit of duplicated code but improves
+ readability. Some of the duplicated code will fall out in future
+ changes to the event subsystem (the signal pipe).
+ [fe239d2a3cbd]
+
+2017-02-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/ttysize.c, src/exec_pty.c:
+ Remove support for the TIOCGSIZE ioctl. Systems that use this rather
+ than TIOCGWINSZ are too old for sudo to build on anyway.
+ [0179b16c70f9]
+
+2017-02-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c, src/exec_pty.c:
+ Set the child pid to -1 after we've waited for it and take care to
+ avoid killing pid -1. This makes it a bit more explicit and removes
+ the need for a separate variable to track the child's status. Sudo
+ already stops processing signals after it receives SIGCHLD so it is
+ not vulnerable to CVE-2017-2616.
+ [1123704858ae]
+
+2017-02-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in:
+ Update the description of strict mode to current reality. Aliases
+ haven't needed to be defined before they are used since sudo 1.7.
+ [9dc4ce4ec538]
+
+ * doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in,
+ plugins/sudoers/regress/visudo/test2.err.ok,
+ plugins/sudoers/regress/visudo/test3.err.ok,
+ plugins/sudoers/visudo.c:
+ Go back to using a Warning/Error prefix in the message printed to
+ stderr for alias problems. Requested by Tomas Sykora.
+ [ad4dc6e34222]
+
+2017-02-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/filedigest.c, plugins/sudoers/filedigest_openssl.c:
+ fix copyright years
+ [b9f013f95bb2]
+
+2017-02-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/digestname.c,
+ plugins/sudoers/filedigest.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/match.c, plugins/sudoers/parse.h,
+ plugins/sudoers/sssd.c, plugins/sudoers/visudo_json.c:
+ Move the file digest code out of match.c and into filedigest.c.
+ Inspired by RedHat changes that used libgcrypt. Also add
+ digest_type_to_name() to map a sudo digest type (int) to a name
+ (string) and use it.
+ [9213d8c94b8f]
+
+ * INSTALL, MANIFEST, configure, configure.ac, mkdep.pl,
+ plugins/sudoers/Makefile.in, plugins/sudoers/filedigest_openssl.c:
+ Add support for using the message digest functions in OpenSSL
+ instead of sudo's own SHA2 implementation.
+ [d77639c97e43]
+
+ * INSTALL, MANIFEST, configure, configure.ac, mkdep.pl,
+ plugins/sudoers/Makefile.in, plugins/sudoers/filedigest_gcrypt.c:
+ Add support for using the message digest functions in libgcrypt
+ instead of sudo's own SHA2 implementation.
+ [0259467c38dd]
+
+ * plugins/sudoers/gmtoff.c:
+ Check for gmtime() or localtime() returning NULL and just use a zero
+ offset in that case. Should not be possible.
+ [ed210dd8bf46]
+
+2017-02-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers2ldif:
+ Add support for ROLE, TYPE, PRIVS, LIMITPRIVS, TIMEOUT, NOTBEFORE
+ and NOTAFTER.
+ [d0310b017c78]
+
+ * config.h.in, configure, configure.ac, plugins/sudoers/timestr.c:
+ strftime() was in C89 so use it unconditionally.
+ [87bf66aa18fd]
+
+ * MANIFEST, config.h.in, configure, configure.ac, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, include/sudo_debug.h,
+ lib/util/sudo_debug.c, lib/util/util.exp.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/gentime.c,
+ plugins/sudoers/gmtoff.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.h, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/parser/check_gentime.c,
+ plugins/sudoers/regress/sudoers/test19.in,
+ plugins/sudoers/regress/sudoers/test19.json.ok,
+ plugins/sudoers/regress/sudoers/test19.out.ok,
+ plugins/sudoers/regress/sudoers/test19.toke.ok,
+ plugins/sudoers/regress/visudo/test10.out.ok,
+ plugins/sudoers/regress/visudo/test10.sh,
+ plugins/sudoers/sudoers_version.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Add NOTBEFORE and NOTAFTER command options similar to what is
+ already available in LDAP.
+ [3ba0f9567f83]
+
+2017-02-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [f2876eadc1f5]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, include/sudo_plugin.h:
+ Bump version to 1.11 for timeout entry in settings[]
+ [7b288e4bab93]
+
+ * doc/sudo.conf.cat, doc/sudo_plugin.cat, doc/sudoers.ldap.cat,
+ doc/sudoreplay.cat, doc/visudo.cat:
+ regen
+ [8c059a57d367]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/policy.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, src/parse_args.c, src/sudo_usage.h.in:
+ Add a command line option to specify the command timeout, as long as
+ sudoers does not specify a shorter time limit.
+ [a8ef7f923d0a]
+
+2017-02-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Better error message when the timeout value does not parse.
+ [2360fb093e3e]
+
+ * plugins/sudoers/timeout.c:
+ set errno to ERANGE not EOVERFLOW on range error
+ [9654e1acab0d]
+
+2017-02-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ regen
+ [46a124dd72aa]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y, plugins/sudoers/parse.h:
+ Merge command tags, SELinux type/role and Solaris privs settings
+ into "command options". This relaxes the order of things so tags and
+ other options can be interspersed.
+ [0970fd78cbe8]
+
+ * MANIFEST, doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y, plugins/sudoers/ldap.c,
+ plugins/sudoers/mkdefaults, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/sudoers/test17.in,
+ plugins/sudoers/regress/sudoers/test17.json.ok,
+ plugins/sudoers/regress/sudoers/test17.out.ok,
+ plugins/sudoers/regress/sudoers/test17.toke.ok,
+ plugins/sudoers/regress/sudoers/test18.in,
+ plugins/sudoers/regress/sudoers/test18.json.ok,
+ plugins/sudoers/regress/sudoers/test18.out.ok,
+ plugins/sudoers/regress/sudoers/test18.toke.ok,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/timeout.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/visudo_json.c:
+ Add support for command timeouts in sudoers. After the timeout, the
+ command will be terminated.
+ [a36a748e9324]
+
+ * doc/fixman.sh, doc/fixmdoc.sh, doc/sudoers.cat, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in, plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y, plugins/sudoers/parse.h:
+ Split out tags again so they must precede the command and not allow
+ them to be mixed in with options.
+ [e7e7d60316cc]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Only inherit SELinux role/type and Solaris privilege sets if the
+ command does not include any. Previously, a command with only a role
+ would inherit a type from the previous command which is not what was
+ intended.
+ [171a3ad972e7]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ List SELinux role/type for "sudo -l" with LDAP and SSSd backends.
+ Also fix printing of the timeout.
+ [740723a49ab5]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Plug some memory leaks found by ASAN.
+ [08189098a5b6]
+
+ * plugins/sudoers/Makefile.in:
+ Only inhibit ASAN leak detector for tests that result in a parse
+ error. The parser cannot currently clean up completely on error.
+ [b2f82dcd2545]
+
+ * plugins/sudoers/rcstr.c:
+ supress cppcheck memory leak false positive
+ [e0caf2275a44]
+
+ * lib/util/strtoid.c:
+ fix typo that prevented compilation on FreeBSD
+ [27866f6a2b5e]
+
+2017-02-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/Makefile.in:
+ Link vsyslog.lo directly into vsyslog_test to make sure the syslog()
+ stub gets called. Otherwise, the real syslog will get called via
+ libutil on AIX.
+ [693bc8411a98]
+
+ * lib/util/regress/vsyslog/vsyslog_test.c:
+ Fix final test with a format > 2048 bytes. Keep track of tests run
+ in the syslog() stub so we can detect if the stub is not being
+ called.
+ [d10d784446c1]
+
+ * lib/zlib/deflate.c:
+ avoid redefining the MIN macro
+ [45b7b0ba0f01]
+
+ * plugins/sudoers/parse.h, plugins/sudoers/timestr.c:
+ Include parse.h in timestr.c which is where function prototype
+ lives.
+ [3ec9ec84a84c]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Fix for including a sudoers file that begins with the letter 'i'.
+ The hack to determine whether we are parsing an include or
+ includedir is no longer safe now that relative include paths are
+ permitted. Bug #776.
+ [4d9691a43867]
+
+2017-02-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/def_data.c, plugins/sudoers/def_data.in:
+ Display the value of syslog_maxlen in sudo -V output.
+ [0841ad36531c]
+
+2017-02-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c:
+ Add ignore_unknown_defaults flag to ignore unknown Defaults entries
+ in sudoers instead of producing a warning.
+ [a7fdb44677dd]
+
+2017-01-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/match.c:
+ Always set the close-on-exec bit on the fd used to generate the
+ digest (i.e. the command to run) on systems that lack fexecve(2).
+ That way we don't need to explicitly close it using #ifdefs.
+ [f840a22fac1c]
+
+ * plugins/sudoers/po/ca.mo, plugins/sudoers/po/ca.po,
+ plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po, po/ca.mo,
+ po/ca.po, po/eo.mo, po/eo.po, po/sv.mo, po/sv.po:
+ sync with translationproject.org
+ [57e877674892]
+
+ * NEWS:
+ first updates for 1.8.20
+ [118208688b08]
+
+ * configure, configure.ac:
+ sudo 1.8.20
+ [6cba125ea903]
+
+2017-01-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/LICENSE, lib/zlib/adler32.c, lib/zlib/compress.c,
+ lib/zlib/crc32.c, lib/zlib/deflate.c, lib/zlib/deflate.h,
+ lib/zlib/gzguts.h, lib/zlib/gzlib.c, lib/zlib/gzread.c,
+ lib/zlib/gzwrite.c, lib/zlib/infback.c, lib/zlib/inffast.c,
+ lib/zlib/inflate.c, lib/zlib/inflate.h, lib/zlib/inftrees.c,
+ lib/zlib/trees.c, lib/zlib/uncompr.c, lib/zlib/zconf.h.in,
+ lib/zlib/zlib.exp, lib/zlib/zlib.h, lib/zlib/zutil.c,
+ lib/zlib/zutil.h:
+ update zlib to version 1.2.11
+ [75a563663083]
+
+2017-01-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/match.c:
+ Fix fdexec=never when a digest is present.
+ [49d3ab5baad0]
+
+2017-01-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/match.c:
+ Add new fdexec sudoers setting to allow choose whether execve() or
+ fexecve() is used.
+ [6a7623aa9a64]
+
+ * src/exec.c, src/exec_pty.c:
+ Close execfd in parent processes where it is not needed.
+ [f44e334d43e2]
+
+2017-01-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/match.c:
+ Add support for digest matching when the command is a glob-style
+ pattern or a directory. For example:
+
+ millert ALL = sha224:TmUvLkp3a2txliSC2X6CiK42626qdKsH72m/PQ== /bin/
+ millert ALL = sha224:TmUvLkp3a2txliSC2X6CiK42626qdKsH72m/PQ== /bin/*
+
+ would only match /bin/ls (assuming the digest matches).
+
+ Previously, only explicit path matches checked the digest.
+ [d4f6822ba9bb]
+
+2017-01-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in, plugins/sudoers/ldap.c:
+ Add support for SASL_MECH in ldap.conf; Bug #764
+ [d057bb7f2ddc]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Fix documentation bug, the contents of env_file have never been
+ subject to env_keep or env_check. However, variables are only added
+ if they have not already been preserved.
+ [4483b1b44709]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ examples/sudoers:
+ Safer example for rule that can change non-root passwords. GNU
+ getopts allows options to follow arguments so we need to be able to
+ deny things like "passwd root -q". From Paul "Joey" Clark. Bug #772
+ [c809f1372811]
+
+2017-01-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Don't overwrite the return value of ldap_sasl_interactive_bind_s()
+ by the subsequent call to sudo_set_krb5_ccache_name(). From Paul
+ Zirnik of SUSE.
+ [448baff2b586]
+
+ * plugins/sudoers/env.c:
+ In sudo_unsetenv_nodebug(), decrement envp.env_len after removing
+ the variable. From Paul Zirnik of SUSE.
+ [3d87a008671c]
+
+2017-01-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/Makefile.in:
+ only run vsyslog_test if it exists
+ [5323dfcfb009]
+
+ * MANIFEST, configure, configure.ac, lib/util/Makefile.in,
+ lib/util/regress/vsyslog/vsyslog_test.c:
+ Add regress for vsyslog replacement.
+ [1f767b8f5940]
+
+2017-01-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ Define HAVE_NANOSLEEP if we find nanosleep in librt
+ [ec8d949bf411]
+
+ * configure, configure.ac:
+ sudo_nanosleep not nanosleep in util.exp.in
+ [18a3bca78962]
+
+ * configure, configure.ac:
+ add nanosleep to util.exp.in if needed
+ [6ac2e9266d67]
+
+ * NEWS, configure, configure.ac:
+ sudo 1.8.19p2
+ [9c15593a007a]
+
+ * lib/util/vsyslog.c:
+ Double the size of new_fmt[] and remove an extraneous break in the
+ %m handling that was leftover from an earlier edit.
+ [fcb28dc9cd4e]
+
+ * lib/util/vsyslog.c:
+ Fix typo, want vsnprintf not snprintf.
+ [2717f2125ecd]
+
+ * plugins/sudoers/logging.c:
+ move va_start() in mysyslog()
+ [b58ec40bbfc3]
+
+ * plugins/sudoers/sudoers.c:
+ Only treat failure of expand_iolog_path() as fatal if
+ ignore_iolog_errors is not set.
+ [1ba009311cf7]
+
+2017-01-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, lib/util/Makefile.in, lib/util/nanosleep.c,
+ mkdep.pl, src/exec_pty.c:
+ When waiting for the parent to grant us the tty, use nanosleep
+ instead of spinning to avoid hogging the CPU.
+ [76335b380d7c]
+
+ * src/sudo.c:
+ Use ROOT_UID instead of 0
+ [5ed03a4e0b0b]
+
+2017-01-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ regen
+ [99b26e2c523d]
+
+2017-01-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/interfaces.c,
+ plugins/sudoers/regress/visudo/test9.out.ok,
+ plugins/sudoers/regress/visudo/test9.sh, plugins/sudoers/visudo.c:
+ Fix crash in visudo introduced in sudo 1.8.9 when an IP address or
+ network is used in a host-based Defaults entry. Bug #766
+ [ff9001f126b5]
+
+2017-01-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac, doc/LICENSE:
+ Avoid using the system strnlen/strndup on AIX < 6. Even if configure
+ correctly detects it is working on the build machine, the sudo
+ package may be run on a system with an old libc were it is broken.
+ [28d148db0aaa]
+
+2016-12-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, configure, configure.ac:
+ sudo 1.8.19p1
+ [7bfd43fa5caf]
+
+ * plugins/sudoers/defaults.c:
+ Fix logic bug when matching syslog priority and facility.
+ [576cc9eb850f]
+
+ * doc/HISTORY:
+ Dell spun off Quest so simplify the history by just talking about
+ Quest and not Dell.
+ [a66120495435]
+
+2016-12-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/LICENSE:
+ Fix copyright year
+ [3122e55195a6]
+
+ * NEWS:
+ typo
+ [ffe9e84928b6]
+
+2016-12-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/sudo_compat.h:
+ HAVE_DECL_GETGROUPLIST_2 is always defined if HAVE_GETGROUPLIST_2
+ is, we need to check its value, not whether it is defined.
+ [849eb3113149]
+
+2016-12-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po:
+ sync with translationproject.org
+ [abf5d356a33b]
+
+2016-12-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po, po/sr.mo,
+ po/sr.po:
+ sync with translationproject.org
+ [fec672d5a4c7]
+
+ * config.h.in, configure.ac, include/sudo_compat.h,
+ plugins/sudoers/pwutil_impl.c, src/sudo.c:
+ Use getgrouplist_2() on macOS if available.
+ [3bf58af56d18]
+
+2016-12-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [3f4d52230317]
+
+ * plugins/sudoers/interfaces.c:
+ In set_interfaces() treat a parse error as fatal.
+ [7d0048108b1d]
+
+2016-12-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/regress/atofoo/atofoo_test.c:
+ Fix a clang warning on macOS
+ [58e9d192e907]
+
+2016-12-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po, po/ko.mo,
+ po/ko.po, po/vi.mo, po/vi.po:
+ sync with translationproject.org
+ [99cce0f5fddc]
+
+ * NEWS:
+ update for 1.8.19b2
+ [18cfc9b8b8e7]
+
+ * plugins/sudoers/timestamp.c:
+ Ignore a boot time that is in the future, which can happen when the
+ clock is corrected down after boot. Otherwise, the timestamp file
+ will be unlinked each time sudo is run and a password is always
+ required.
+ [dd3b2b7ae709]
+
+2016-11-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/logging.c:
+ Allow syslog priority to be negated or set to "none" to disable
+ logging successes or failures.
+ [624eddac4ab1]
+
+ * doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in,
+ plugins/sudoers/sudoreplay.c:
+ Allow stdin and ttyin to be displayed too. The only one that is
+ really useful in sudoreplay is stdin when input is from a pipe.
+ [5aa8b3a90c84]
+
+ * src/regress/noexec/check_noexec.c:
+ Solaris 10 wordexp() returns 127 on execve() failure like popen()
+ does.
+ [f927c50dda17]
+
+ * config.h.in, configure, configure.ac, include/sudo_debug.h,
+ lib/util/regress/atofoo/atofoo_test.c, lib/util/strtoid.c,
+ lib/util/sudo_debug.c, lib/util/util.exp.in:
+ id_t is 64-bits on FreeBSD so use strtoll() there. Fixes the strtoid
+ regress.
+ [448a9857e89f]
+
+2016-11-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ fix typo
+ [92ea657a87f5]
+
+ * plugins/sudoers/sudoers.c:
+ Fix the "all" setting for verifypw and listpw; nopass would never be
+ true even if all the user's entries had the NOPASSWD tag. Regression
+ introduce in sudo 1.8.17. Bug #762
+ [c672e3ebfbe2]
+
+2016-11-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/ca.mo, plugins/sudoers/po/cs.mo,
+ plugins/sudoers/po/cs.po, plugins/sudoers/po/da.mo,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/el.mo, plugins/sudoers/po/eo.mo,
+ plugins/sudoers/po/eu.mo, plugins/sudoers/po/fi.mo,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/hr.mo,
+ plugins/sudoers/po/hr.po, plugins/sudoers/po/hu.mo,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/ko.mo, plugins/sudoers/po/ko.po,
+ plugins/sudoers/po/lt.mo, plugins/sudoers/po/nb.mo,
+ plugins/sudoers/po/nb.po, plugins/sudoers/po/nl.mo,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/ru.mo, plugins/sudoers/po/sk.mo,
+ plugins/sudoers/po/sl.mo, plugins/sudoers/po/sr.mo,
+ plugins/sudoers/po/tr.mo, plugins/sudoers/po/uk.mo,
+ plugins/sudoers/po/uk.po, plugins/sudoers/po/zh_CN.mo,
+ plugins/sudoers/po/zh_CN.po, po/cs.mo, po/cs.po, po/de.mo, po/de.po,
+ po/es.mo, po/es.po, po/fr.mo, po/fr.po, po/hr.mo, po/hr.po,
+ po/it.mo, po/it.po, po/ja.mo, po/ja.po, po/ko.mo, po/ko.po,
+ po/nb.mo, po/nb.po, po/pl.mo, po/pl.po, po/pt_BR.mo, po/pt_BR.po,
+ po/tr.mo, po/tr.po, po/uk.mo, po/uk.po, po/zh_CN.mo, po/zh_CN.po:
+ sync with translationproject.org
+ [8a4ab570d132]
+
+2016-11-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c, src/openbsd.c:
+ Just use malloc_options "S" on OpenBSD instead of "AFGJPR".
+ [2851cd2da1c7]
+
+2016-11-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ Update year in license
+ [e370bf3d1035]
+
+2016-11-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [d524f0306467]
+
+ * doc/sudo.conf.cat, doc/sudoers.ldap.cat, doc/sudoreplay.cat:
+ regen
+ [185328ea20c3]
+
+ * include/sudo_debug.h, lib/util/sudo_debug.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoers_debug.c,
+ plugins/sudoers/visudo.c, src/sudo.c:
+ Add SUDO_DEBUG_INSTANCE_ERROR return value for sudo_debug_register()
+ and check for it in places where we check the return value of
+ sudo_debug_register().
+ [d1e74c5f21a6]
+
+2016-11-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ update for 1.8.19
+ [b248866c511d]
+
+2016-11-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.ac, plugins/sudoers/getspwuid.c:
+ Add support for getpwnam_shadow() on OpenBSD
+ [4db7ed374c33]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, plugins/sudoers/policy.c, src/sudo.c:
+ Add umask to user_info passed in from the front end to the plugin.
+ [4a4eee52a717]
+
+ * plugins/sudoers/auth/rfc1938.c:
+ Fix sign compare warning.
+ [8732d632cbff]
+
+ * MANIFEST, aclocal.m4, configure, configure.ac, m4/ax_append_flag.m4,
+ m4/sudo.m4:
+ Use AX_APPEND_FLAG instead of SUDO_APPEND_CPPFLAGS and direct
+ modification of LDFLAGS.
+ [c1464dcd45e0]
+
+ * MANIFEST, configure, configure.ac, plugins/sudoers/aixcrypt.exp:
+ Remove aixcrypt.exp, it was a remnant of the 90's crypto wars where
+ crypt() was not exported.
+ [785d57666d41]
+
+ * doc/TROUBLESHOOTING:
+ Remove obsolete solaris issue with snprintf
+ [3ce6cc899026]
+
+ * INSTALL:
+ SunOS 4.x is no longer supported
+ [2239eb30ff2c]
+
+2016-11-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/regress/sudo_conf/test1.in, lib/util/sudo_conf.c:
+ Plug memory leak when a particular Path is set more than once.
+ [debc97dac01d]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Add sudo_ldap_is_negated() and sudo_ldap_is_negated() functions and
+ use them to parse negated entries instead of doing it manually.
+ [12010b64afe5]
+
+ * plugins/sudoers/ldap.c:
+ Fix printing of sudoedit_follow in "sudo -l"
+ [2094a8f880c4]
+
+ * plugins/sudoers/sssd.c:
+ For "sudo -l" print sudoOption sudoedit_follow as FOLLOW.
+ [9c860b1fa721]
+
+ * config.h.in, configure, configure.ac, include/sudo_conf.h,
+ lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_conf/test1.out.ok, lib/util/sudo_conf.c,
+ lib/util/util.exp.in, plugins/sudoers/policy.c, src/exec_common.c,
+ src/load_plugins.c, src/parse_args.c:
+ Always define _PATH_SUDO_NOEXEC, _PATH_SUDO_SESH,
+ _PATH_SUDO_PLUGIN_DIR, even if only defined to NULL. This means the
+ accessors can always be present.
+
+ Use RTLD_PRELOAD_VAR instead of _PATH_SUDO_NOEXEC to tell when
+ noexec is available.
+
+ Add ENABLE_SUDO_PLUGIN_API and use it instead of
+ _PATH_SUDO_PLUGIN_DIR to tell when the plugin API is available.
+
+ Add sudo_conf_clear_paths() to clear the path values so the regress
+ tests are not affected by compile-time settings.
+ [2b05e4a143d9]
+
+ * plugins/sudoers/ldap.c:
+ Use readline() in sudo_ldap_read_secret()
+ [3f0506e5cbe3]
+
+2016-11-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/sudo_conf.c:
+ Get rid of struct sudo_conf_paths and just use #defined index values
+ to access the path values. Make all accessors available even when
+ the feature is not enabled.
+ [58d1ec6170a8]
+
+ * configure, configure.ac, lib/util/Makefile.in, lib/zlib/Makefile.in,
+ mkdep.pl, plugins/group_file/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/Makefile.in:
+ Add ASAN_CFLAGS and ASAN_LDFLAGS and use -Wc prefix in ASAN_LDFLAGS
+ to prevent libtool from strippign them out. Avoid using ASAN flags
+ when building sudo_noexec.so.
+ [9644dd92e586]
+
+2016-11-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ Disable noexec for HP-UX 10.x which probably doesn't support
+ LD_PRELOAD
+ [d87bc5ea4688]
+
+ * config.h.in, configure, configure.ac, plugins/sudoers/getspwuid.c:
+ Remove SunOS 4 support, it is not modern enough to run sudo.
+ [b6e15f8360b6]
+
+ * config.h.in, configure, configure.ac, plugins/sudoers/getspwuid.c:
+ Remove HP-UX 9 support, it is not modern enough for sudo.
+ [226dda48c1e1]
+
+ * config.h.in, configure, configure.ac, plugins/sudoers/auth/passwd.c,
+ plugins/sudoers/getspwuid.c:
+ Remove Ultrix support, modern sudo can't run on Ultrix anyway.
+ [95a11ef29a2b]
+
+ * MANIFEST, configure, configure.ac, lib/util/sudo_conf.c,
+ src/Makefile.in, src/exec_common.c,
+ src/regress/noexec/check_noexec.c, src/sudo_exec.h:
+ Add regress for noexec functionality
+ [2cadd8e04677]
+
+ * src/Makefile.in:
+ Unbreak sudo_noexec on macOS where shared libraries and dynamic
+ modules are different. We still want to install sudo_noexec.so
+ without the "lib" prefix so some hackery is required.
+ [93d7b69491a1]
+
+ * configure, configure.ac:
+ Don't enable noexec for AIX 5.0-5.2, we need 5.3 and above.
+ [92cad0180239]
+
+2016-11-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/Makefile.in:
+ Need to link sudo_noexec.so with -ldl for dlsym() on some platforms.
+ Otherwise, the wordexp(3) wrapper will fail due to an undefined
+ symbol. Bug #761
+ [120a317ce25b]
+
+ * plugins/sudoers/visudo.c:
+ In strict mode, go to the file/line with an undefined aliases or
+ aliases cycle directly.
+ [b4f51b79bd9e]
+
+2016-11-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in,
+ plugins/sudoers/alias.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/visudo/test2.err.ok,
+ plugins/sudoers/regress/visudo/test3.err.ok,
+ plugins/sudoers/visudo.c:
+ Store the file/lineno for alias and userspec entries so we can
+ provide that info if there is an error.
+ [7deb4e41ca7b]
+
+2016-11-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/rcstr.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/visudo.c,
+ plugins/sudoers/visudo_json.c:
+ Add simple reference-counted string allocator and use it for passing
+ around references to the sudoers path. This lets us avoid making
+ copies of the sudoers path for the errorfile as well as each
+ Defaults entry.
+ [afcff7b5b647]
+
+ * lib/util/sha2.c:
+ Cast len from size_t to uint64_t before bit shifting since we are
+ adding to count which is also uint64_t. Quiets a PVS-Studio warning.
+ [167210670b30]
+
+2016-11-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/regress/visudo/test7.out.ok,
+ plugins/sudoers/regress/visudo/test7.sh,
+ plugins/sudoers/regress/visudo/test8.err.ok,
+ plugins/sudoers/regress/visudo/test8.out.ok,
+ plugins/sudoers/regress/visudo/test8.sh:
+ Add checks for sudoers_locale early Defaults
+ [582c08c9418c]
+
+ * src/parse_args.c, src/sudo.c, src/sudo.h:
+ Add the argument vector allocated for -s and -i mode to the garbage
+ collector list. Avoids an ASAN warning on exit when the -s or -i
+ flags are used.
+ [652691a5216b]
+
+2016-11-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ add missing sudo_pw_delref/sudo_gr_delref to plug memory leak
+ [c4ba4c26e0c1]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/ldap.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h,
+ plugins/sudoers/regress/parser/check_fill.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ plugins/sudoers/visudo_json.c:
+ Go back to parsing Defaults entries in update_defaults instead of as
+ sudoers is read. Otherwise, we cannot properly support early
+ defaults like sudoers_locale.
+ [ff1328a86b97]
+
+ * mkpkg:
+ Use expr instead of POSIX sh numerical expression to avoid a syntax
+ error on older shells.
+ [638383bb40d5]
+
+2016-11-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, include/sudo_plugin.h:
+ Bump plugin minor version to 10 for sudo_mode, sudo_group and
+ sudo_user.
+ [0c65dc1f2874]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Fix a bug in host matching where a negated sudoHost entry would
+ prevent other sudoHosts following it from matching.
+ [40cbd5790106]
+
+ * plugins/sudoers/defaults.c:
+ Zero out sd_un before calling parse_default() so we don't try to
+ free stack garbage in the ldap/sssd backends.
+ [6b64a8e3a19d]
+
+2016-11-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Use "ret", not "rc" for the function return value.
+ [fdfe637adee6]
+
+ * include/sudo_compat.h, lib/util/strtomode.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/goodpath.c,
+ plugins/sudoers/logging.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/visudo.c, src/sesh.c, src/sudo.c, src/sudo_edit.c:
+ Use sys/stat.h defines instead of bare octal values.
+ [215c80e09830]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.cat, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in, plugins/sudoers/iolog.c,
+ plugins/sudoers/policy.c:
+ Pass iolog mode, group and user from policy plugin to I/O log
+ plugin.
+ [1ed4967771c8]
+
+2016-11-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/ldap.c, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/parser/check_fill.c, plugins/sudoers/sssd.c:
+ Instead of parsing sudoers Defaults twice, parse once while reading
+ sudoers and then just set the parsed value in update_defaults().
+ [370d51681c6e]
+
+ * plugins/sudoers/defaults.c:
+ Use "struct defaults *d" instead of "struct defaults *def"
+ throughout for consistency and to avoid confusino with "struct
+ def_values *def". Use "str" not "var" for the string argument to
+ convert and store in sd_un for the store_* functions.
+ [5cc3efc609df]
+
+ * plugins/sudoers/parse.c:
+ In display_bound_defaults() rename dtype arg -> deftype.
+ [b3323960e1db]
+
+2016-11-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/regress/sudo_conf/test4.err.ok,
+ lib/util/regress/sudo_conf/test5.err.ok,
+ plugins/sudoers/regress/visudo/test2.err.ok,
+ plugins/sudoers/regress/visudo/test3.err.ok:
+ Update error output to match quoting changes.
+ [27bbf5004d1e]
+
+ * plugins/sudoers/defaults.c:
+ Avoid passing in a struct sudo_defs_types pointer to the store
+ functions. Pass in a pointer to the union to fill instead.
+ [ea956d00aae3]
+
+ * plugins/sudoers/defaults.h:
+ no longer need struct defaults forward referebce
+ [21e34ca85de5]
+
+2016-11-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/sudo_conf.c, plugins/sudoers/alias.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/logging.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/visudo.c,
+ plugins/sudoers/visudo_json.c, src/load_plugins.c:
+ Use "double quotes" in messages instead of a combination of the
+ accent (grave) mark and apostrophe.
+ [10dee3ecf3e1]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Add file:linenumber prefix to all Defaults warnings so we can see
+ them when running sudo too. For LDAP/SSSD we print the sudoRole
+ instead of the file name and omit the line number.
+ [5c6b95cd3792]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Use sudoedit in examples instead of "sudo vi"
+ [6008c208682c]
+
+2016-11-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ plugins/sudoers/visudo_json.c:
+ Only treat an unknown Defaults entry as a parse error in visudo, not
+ in sudo itself.
+ [8d8aa7ac5a32]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/visudo.c:
+ Instead of checking Defaults values after the fact, check them at
+ sudoers parse time. This makes it possible to display the file and
+ line number with the problem and for visudo to go right to the
+ error.
+ [ac66bd690d05]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/parse.h:
+ Refactor freeing of a member_list into free_members().
+ [d29daa01bb9c]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ add_defaults() now calls sudoerserror() itself instead of the caller
+ assuming any error means out of member.
+ [a25e51321e0b]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/mkdir_parents.c:
+ s/rval/ret/g -- old habits die hard
+ [fa55d08b233a]
+
+2016-10-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ Remove inaccurate XXX comment, sudo_file_parse() sends mail on parse
+ error.
+ [052b0e112839]
+
+ * plugins/sudoers/visudo.c:
+ The fix for Bug #408 broke editing of files in an include dir that
+ have a syntax error. Normally, visudo does not edit those files, but
+ if a syntax error is detected in one, the user gets a chance to fix
+ it.
+ [6b00f9bfff31]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/sudoers.h, plugins/sudoers/visudo.c,
+ plugins/sudoers/visudo_json.c:
+ Make a copy of the current sudoers path when assigning errorfile.
+ Fixes a potential use after free in visudo when there is an error in
+ one of the include files.
+ [eb6db5d15b61]
+
+ * plugins/sudoers/sudoers_debug.c:
+ sudoers_debug_register() was not setting the active debug instance
+ to sudoers_debug_instance when called from the I/O log plugin. This
+ is because it relied on sudo_debug_register to do that but
+ sudoers_debug_parse_flags() doesn't set debug_files[]
+ sudoers_debug_instance is already set (we can only init sudoers
+ debug once).
+
+ To work around this, just make sudoers_debug_instance the active
+ debug instance in sudoers_debug_register() when it is already set.
+ [71b0221c8c28]
+
+ * src/load_plugins.c:
+ Fix pasto when setting I/O plugin debug files
+ [03c3aab22e65]
+
+ * plugins/sudoers/iolog.c:
+ use cp instead of *cur when comparing against plugin_path
+ [f2dfe69549f5]
+
+2016-10-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/mkdir_parents.c:
+ In sudo_mkdir_parents() inherit the gid of / instead of using gid 0
+ for the first component.
+ [5f2bf33bccb5]
+
+ * plugins/sudoers/iolog.c:
+ We want to inherit the gid from the parent directory when not
+ setting permissions on intermerdiate directories.
+ [845f5a20b5fa]
+
+2016-10-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/iolog.c,
+ plugins/sudoers/mkdir_parents.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/timestamp.c:
+ Move io_mkdir_parents() to its own file and use it in ts_mkdirs().
+ [c1d55f588a60]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Make the I/O log file/dir permissions and owner configurable.
+ [e7a74f3dfa56]
+
+ * lib/util/Makefile.in, mkdep.pl:
+ Add vsyslog.lo
+ [18362a9ae32e]
+
+ * configure, configure.ac:
+ sudo 1.8.19
+ [97743604e6e3]
+
+2016-10-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/defaults.c:
+ Don't try to syntax check an unrecognized Defaults value in visudo.
+ [e4972655b5d3]
+
+2016-10-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ Create I/O log files with the same gid as the parent directory.
+ [0da5824e006d]
+
+ * plugins/sudoers/ldap.c:
+ Check for sudo_ldap_result_last_search() returning NULL. This can't
+ happen in practice because we always call
+ sudo_ldap_result_add_search() first which guarantees there is a
+ result to be found. Quiets a PVS-Studio warning.
+ [4f6074f40fbc]
+
+ * src/exec_pty.c:
+ Quiet a PVS-Studio warning about the spin loop when waiting for the
+ parent to assign us the terminal pgrp.
+ [d063a283477b]
+
+ * plugins/sudoers/env.c:
+ Fix incorrect strncmp() lengths. The check for USERNAME was only
+ looking at the first 5 characters (copy and paste error). The check
+ for SUDO_PS1 was not checking the trailing '=' character (off by one
+ error). Found by PVS-Studio.
+ [297380eb6940]
+
+ * plugins/sudoers/env.c:
+ When checking for old-style bash functions in the environment, check
+ for values starting with "() " (note the trailing space) rather than
+ "()". Bash will only treat the value as a function if the space
+ after "()" is present. The trailing space was already present in the
+ compare string but when it was added, the length passed to strncmp()
+ was not updated from 3 to 4. Found by PVS-Studio. No security
+ impact.
+ [7e35f39d356b]
+
+ * plugins/sudoers/set_perms.c:
+ Add some missing casts from uid_t/gid_t to int when printing uid/gid
+ values. We print these as signed so a value of -1 (no change) is
+ obvious. Quiets PVS-Studio warnings.
+ [9773e5b166e1]
+
+ * plugins/sudoers/timestamp.c:
+ def_timestamp_timeout is a double so compare against 0.0 not 0 to
+ avoid making it appear to be an integer type.
+ [8675db470ab7]
+
+ * plugins/sudoers/defaults.c:
+ When checking syslog facility or priority, move the string compare
+ into the body of the loop and return if it matches. If we finish the
+ loop it means we didn't find a match. This makes the code a little
+ bit more readable.
+ [d1df1649a01e]
+
+ * lib/util/strlcpy.c, lib/util/strnlen.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/env.c, plugins/sudoers/logging.c,
+ plugins/sudoers/visudo_json.c, src/env_hooks.c, src/exec_pty.c:
+ Replace bare ";" in the body of for() loops with "continue;" for
+ improved readability.
+ [92eff8dbe5f8]
+
+2016-10-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.guess, config.sub:
+ Update from http://git.savannah.gnu.org/gitweb/?p=config.git
+ [86e6144dfdd7]
+
+ * config.guess, config.sub, configure, ltmain.sh, m4/libtool.m4,
+ m4/ltoptions.m4, m4/ltsugar.m4, m4/ltversion.m4, m4/lt~obsolete.m4:
+ Update to libtool 2.4.6
+ [8d85d9e8687b]
+
+2016-10-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/vsyslog.c:
+ Use a static buffer if possible.
+ [758ce6478994]
+
+ * MANIFEST, configure, configure.ac, include/sudo_compat.h,
+ lib/util/vsyslog.c, plugins/sudoers/logging.c:
+ add vsyslog() for systems without it.
+ [c6457f333252]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ There are now 14 tag values, not 10. Don't bother mentioning the
+ number since it keeps increasing. Bug #759
+ [17e4c900dc12]
+
+2016-10-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.ac, plugins/sudoers/logging.c:
+ Use vsyslog() if available.
+ [ea9b7a51eaec]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/logging.c:
+ Add syslog_maxlen to control the max size of syslog messages.
+ [5f9872d2073f]
+
+2016-10-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/tgetpass.c:
+ Don't generate SIGTOU when restoring the terminal modes. It doen't
+ make sense to suspend the process only to restore the terminal
+ settings since in this case the shell has already taken ownership of
+ the tty.
+ [981c26f3fc8f]
+
+ * plugins/sudoers/sudoreplay.c, src/exec_pty.c, src/tgetpass.c:
+ The flush parameter of sudo_term_restore() is bool, not int.
+ [c2597f1881f3]
+
+2016-10-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.conf.cat, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in:
+ Add wordexp() to the list of functions wrapped by sudo_noexec.so.
+ [2e847ce3f02f]
+
+2016-10-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo_noexec.c:
+ Need RTLD_NEXT for wordexp() on dlopen() systems. It is missing on
+ AIX 5.1 at least.
+ [167a518d8129]
+
+ * src/sudo_noexec.c:
+ add missing guard around wordexp()
+ [7b8357b0a358]
+
+ * NEWS:
+ expand on 1.8.18p1 changes
+ [f560e06ad584]
+
+2016-10-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, configure, configure.ac:
+ sudo 1.8.18p1
+ [a36e17d1c5db]
+
+ * config.h.in, configure, configure.ac, src/sudo_noexec.c:
+ Fix configure check for seccomp filter on Linux
+ [5d88d7cda853]
+
+2016-10-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.ac, src/sudo_noexec.c:
+ Use a seccomp filter on Linux to disable execve(2) and execveat(2).
+ This still relies on LD_PRELOAD to work so it has the same issues as
+ the existing mether with respect to running 32-bit binaries on a
+ 64-bit kernel.
+ [59d76bdc0f0c]
+
+ * src/Makefile.in:
+ regen
+ [9e313cb0900b]
+
+ * plugins/sudoers/Makefile.in:
+ regen
+ [5ca77049e5cd]
+
+2016-10-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aclocal.m4, config.h.in, configure, configure.ac, src/sudo_noexec.c:
+ Wrap wordexp(3) in sudo_noexec.
+ [e7d09243e51b]
+
+2016-09-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ Clean .json files created by "make check"
+ [d214117fbda1]
+
+2016-09-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * po/ca.mo, po/da.mo, po/eo.mo, po/es.mo, po/eu.mo, po/fi.mo,
+ po/gl.mo, po/hr.mo, po/hu.mo, po/ko.mo, po/nl.mo, po/ru.mo,
+ po/sk.mo, po/sl.mo, po/sr.mo, po/tr.mo:
+ recompile .po files
+ [3d91cbf75744]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Fix matching when no sudoRunAsUser is present in a sudoRole. If only
+ a sudoRunAsGroup is present, match on the invoking user if the -g
+ option was specified and the group matched. If no sudoRunAsGroup is
+ present and the -g option was specified, allow it if it matches the
+ passwd gid of the runas user. This matches the behavior of the
+ sudoers backend.
+ [e1a52c34da5e]
+
+ * plugins/sudoers/match.c:
+ runas_pw can no longer be NULL
+ [020c6ddcae11]
+
+2016-09-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ RunAsGroup without RunAsUser issues
+ [52d1547c9d3a]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ user_matched and group_matched must be type int, not bool
+ [204d8de97a05]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/match.c,
+ plugins/sudoers/parse.h, plugins/sudoers/sssd.c:
+ Use RUNAS_USER_SPECIFIED and RUNAS_GROUP_SPECIFIED when deciding
+ whether to check runas user/group instead of checking runas_pw or
+ runas_gr.
+ [d17f223e8313]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ When matching against runas_default use userpw_matches() instead of
+ just strcasecmp().
+ [ce70077c5861]
+
+ * plugins/sudoers/testsudoers.c:
+ Set RUNAS_USER_SPECIFIED when -u is specified and/or
+ RUNAS_GROUP_SPECIFIED when -g is specified.
+ [fa7a1035a058]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Fix printing of the default runas user when a RunAsGroup is
+ specified but no RunAsUser is present.
+ [c05dabd194a1]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Only match against runas_default if both sudoRunAsUser and
+ sudoRunAsGroup are missing.
+ [019084f428b2]
+
+ * plugins/sudoers/match.c:
+ runas_pw can no longer be NULL here
+ [e73dcebafa15]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/match.c,
+ plugins/sudoers/parse.h, plugins/sudoers/sssd.c:
+ Update check for whether or not the runas user was set in the ldap
+ and sssd backends to match the sudoers file backend. Introduces the
+ runas_user_set() macro to improve readability. Previously, runas_pw
+ was set late, now it is set before checking sudoers.
+ [d8280d8a96c9]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ Document that negated sudoHosts are only supported by 1.8.18 and
+ higher.
+ [f56824fe61bc]
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/testsudoers/test4.sh,
+ plugins/sudoers/regress/testsudoers/test5.sh:
+ Disable Address Sanitizer leak detection for tests which generate
+ parse errors. The parser leaks a bit on error.
+ [4b0ddb11df3a]
+
+ * plugins/sudoers/sssd.c:
+ Fix underflow in get_ipa_hostname() when trimming trailing
+ whitespace.
+ [875f2f5cd363]
+
+2016-09-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Document negated sudoHost entries.
+ [41d9853f89f7]
+
+ * plugins/sudoers/sssd.c:
+ Support negated sudoHost entries.
+ [7c25f9111633]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ Document negated sudoHost entries.
+ [6c8444c6bc6c]
+
+ * plugins/sudoers/ldap.c:
+ Support negated sudoHost entries.
+ [1899906b8ef4]
+
+2016-09-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/match.c:
+ Don't check the username when matching a host netgroup unless
+ def_netgroup_tuple is enabled.
+ [238c8064542f]
+
+ * plugins/sudoers/match.c:
+ Move valid domain name check into a new valid_domain() function. Fix
+ memory leak if getdomainname(2) fails and avoid using heap garbage
+ for the domain name matching in this case.
+ [946f2441c90a]
+
+2016-09-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po, po/it.mo,
+ po/it.po:
+ sync with translationproject.org
+ [40eab0801eae]
+
+2016-09-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c:
+ Add back line mistakenly removed in 0cf2a9351740
+ [8622c83c1474]
+
+ * plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po, po/nb.mo,
+ po/nb.po:
+ sync with translationproject.org
+ [f180826bb77b]
+
+2016-09-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Bug #757
+ [de67bc9e26f8]
+
+ * plugins/sudoers/sudoers.c:
+ Fix typo that broke short host name matching when the fqdn flag is
+ enabled. Bug #757
+ [605c03afc80f]
+
+2016-09-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/sudo_debug.h, lib/util/aix.c, lib/util/fnmatch.c,
+ lib/util/getgrouplist.c, lib/util/secure_path.c,
+ lib/util/setgroups.c, lib/util/strtoid.c, lib/util/sudo_conf.c,
+ lib/util/sudo_debug.c, plugins/sample/sample_plugin.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/check.c,
+ plugins/sudoers/env.c, plugins/sudoers/goodpath.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/interfaces.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/logging.c,
+ plugins/sudoers/match.c, plugins/sudoers/parse.c,
+ plugins/sudoers/policy.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/timestamp.c, plugins/sudoers/visudo.c,
+ plugins/sudoers/visudo_json.c, src/env_hooks.c, src/exec.c,
+ src/exec_pty.c, src/get_pty.c, src/hooks.c, src/load_plugins.c,
+ src/regress/ttyname/check_ttyname.c, src/selinux.c, src/signal.c,
+ src/sudo.c, src/sudo_edit.c, src/tgetpass.c, src/ttyname.c,
+ src/utmp.c:
+ Be consistent with the naming of the variable used to store the
+ function return value. Previously, some code used "rval", some used
+ "ret". This standardizes on "ret" and uses "rc" for temporary return
+ codes.
+ [017866310d24]
+
+2016-09-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/ca.po, plugins/sudoers/po/cs.mo,
+ plugins/sudoers/po/cs.po, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/el.po, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/eu.po, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/fr.po, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/hu.po, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/ko.po, plugins/sudoers/po/lt.po,
+ plugins/sudoers/po/nb.po, plugins/sudoers/po/nl.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/ru.po, plugins/sudoers/po/sk.po,
+ plugins/sudoers/po/sl.po, plugins/sudoers/po/sr.po,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po,
+ plugins/sudoers/po/tr.po, plugins/sudoers/po/uk.mo,
+ plugins/sudoers/po/uk.po, plugins/sudoers/po/vi.mo,
+ plugins/sudoers/po/vi.po, plugins/sudoers/po/zh_CN.mo,
+ plugins/sudoers/po/zh_CN.po, po/ca.po, po/cs.mo, po/cs.po, po/da.po,
+ po/de.mo, po/de.po, po/eo.po, po/es.po, po/eu.po, po/fi.po,
+ po/fr.mo, po/fr.po, po/gl.po, po/hr.po, po/hu.po, po/it.po,
+ po/ja.mo, po/ja.po, po/ko.po, po/nb.po, po/nl.po, po/pl.mo,
+ po/pl.po, po/pt_BR.mo, po/pt_BR.po, po/ru.po, po/sk.po, po/sl.po,
+ po/sr.po, po/sv.mo, po/sv.po, po/tr.po, po/uk.mo, po/uk.po,
+ po/vi.mo, po/vi.po, po/zh_CN.mo, po/zh_CN.po:
+ sync with translationproject.org
+ [6312962695df]
+
+ * MANIFEST, NEWS, doc/CONTRIBUTORS, po/nn.mo, po/nn.po:
+ Norwegian Nynorsk translation of sudo from translationproject.org
+ [05203a266265]
+
+ * NEWS:
+ Fix for Bug #756
+ [89ff21579216]
+
+2016-09-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ In sudoers_main() avoid setting rval prematurely. Prevents a crash
+ when auditing fails after successfully authenticating. Bug #756
+ [d17a06bce04c]
+
+ * plugins/sudoers/defaults.c:
+ Apply match_group_by_gid early.
+ [1259c7fd66ca]
+
+2016-09-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ update
+ [292a9e21474e]
+
+ * src/ttyname.c:
+ Don't disable large file support for Linux, just SVR4-style /proc.
+ Otherwise, stat(2) may fail on Linux when running a 32-bit sudo on a
+ 64-bit machine. Bug #755
+ [09450ce8b8a8]
+
+2016-09-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/sudo_util.h:
+ Make sudo_parseln() flags hex to make it more obvious that they are
+ bit flags.
+ [b912a078047e]
+
+ * plugins/sudoers/env.c:
+ Don't try to support line continuation in /etc/environment.
+ [d7e30e821c0e]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in, plugins/sudoers/ldap.c:
+ No line continuation support in ldap.conf.
+ [211caaba2395]
+
+ * include/sudo_util.h, lib/util/parseln.c:
+ Add flag to sudo_parseln() to disable line continuation support.
+ [d2820247fc07]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ A comment character ('#') is only special at the beginning of the
+ line.
+ [b3b67b7e4fc0]
+
+ * include/sudo_util.h, lib/util/parseln.c,
+ lib/util/regress/sudo_parseln/parseln_test.c, lib/util/sudo_conf.c,
+ lib/util/util.exp.in, plugins/sudoers/env.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/sudo_nss.c:
+ Add a flags option to sudo_parseln() and a flag to only mach
+ comments at the beginning of the line. Use the flag when parsing
+ ldap.conf.
+ [40c560fc9a10]
+
+ * src/sudo.c:
+ If get_process_ttyname() fails for errno != ENOENT, just warn
+ instead of making it a fatal error. Bug #755
+ [1a028b861801]
+
+2016-08-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/mkdefaults:
+ use strict
+ [681281bc0f6d]
+
+ * plugins/sudoers/def_data.h, plugins/sudoers/mkdefaults:
+ Define def_foo in terms of the I_FOO index instead of a bare number.
+ [abb119f84ae6]
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po:
+ sync with translationproject.org
+ [d339717f8692]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Mention that match_group_by_gid has no effect when sudoers is stored
+ in LDAP.
+ [5eb6ae45c699]
+
+ * include/sudo_compat.h, src/sudo.c:
+ Use W_EXITCODE to construct the wait status if sudo could not
+ execute the command. Fixes the sudo exit value for exec(3) failure.
+ [95eae2d60292]
+
+ * src/exec.c:
+ fix brace style
+ [54448c10b6b5]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [794b06ba727b]
+
+ * src/sudo.c:
+ It is possible for get_user_info() to fail for reasons other than
+ ENOMEM so print the warning message there rather than in main().
+ [8c24df8d6b78]
+
+2016-08-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ match_group_by_gid is only available in sudo 1.8.18 and above
+ [dd237eb540d0]
+
+ * doc/UPGRADE:
+ Mention match_group_by_gid
+ [417f27e9059a]
+
+ * NEWS, doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document match_group_by_gid
+ [2234997acb8d]
+
+ * plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/pwutil.c:
+ Add match_group_by_gid Defaults option to allow sites with slow
+ group lookups and a small number of groups in sudoers to match
+ groups by group ID instead of by group name.
+ [20714580da96]
+
+2016-08-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Mention "sudo -l command" bug fix.
+ [cb8ade186880]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Fix "sudo -l command" in the LDAP and SSS backends when the command
+ is not allowed.
+ [631038350b2a]
+
+2016-08-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/defaults.c:
+ Use sudo_strsplit() instead of doing the equivalent manually.
+ [9eb6d1cc78bd]
+
+2016-08-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Move SIGPIPE bug fix to 1.8.18 where it belongs
+ [52509fd0100e]
+
+ * plugins/sudoers/defaults.c:
+ Fix memset size typo in previous commit.
+ [e00299f7c50f]
+
+ * plugins/sudoers/regress/visudo/test6.out.ok,
+ plugins/sudoers/regress/visudo/test6.sh:
+ Add regress for check_defaults() use-after-free bug.
+ [0b362678ca10]
+
+ * MANIFEST, plugins/sudoers/defaults.c:
+ Fix use-after-free in check_defaults(), reported by Radovan Sroka of
+ RedHat.
+ [ab3a4227c12f]
+
+2016-08-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ SIGPIPE bug fix
+ [24c9a12f7e59]
+
+ * src/signal.c:
+ Now that we ignore SIGPIPE in sudo we need to restore it at exec
+ time. Problem reported by Radovan Sroka of RedHat.
+ [3cfa7e3510ff]
+
+2016-08-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg:
+ Fix appending to make_opts
+ [abe28b6b7663]
+
+ * NEWS:
+ Add Bug #753 and fix reference to Bug #752.
+ [e8c959e1cd6c]
+
+2016-08-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po, po/da.mo,
+ po/da.po, po/pt_BR.mo, po/pt_BR.po:
+ sync with translationproject.org
+ [219c3f0aeee7]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen pot files
+ [d0c56a4ff553]
+
+2016-08-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Update with logging changes.
+ [f41beca23b99]
+
+ * plugins/sudoers/logging.c:
+ Avoid duplicate warnings when we cannot write to the log file. Also
+ send the warning in mail if possible.
+ [9b8509cff137]
+
+ * plugins/sudoers/iolog.c, src/exec_pty.c, src/sudo.c, src/sudo.h:
+ Move the ignoring of I/O log plugin errors into the I/O log plugin
+ itself.
+ [25b7fd056614]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c, src/exec_pty.c, src/sudo.c, src/sudo.h:
+ Make the behavior when we cannot write to a log or audit file
+ configurable. File log failures are ignored by default for
+ consistency with syslog. Audit errors are ignored by default to
+ allow the admin to fix the issue. I/O log file errors are still
+ fatal by default since if I/O logging is activated it is usually to
+ have an audit trail. Bug #751
+ [dbd085e7c736]
+
+2016-08-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/logging.c:
+ Make sure we print an error message to stderr (and not just send
+ mail) if do_logfile() fails. Bug #751
+ [7884a23a0cdc]
+
+2016-08-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/pwutil.c:
+ Separate out the supplemental group ID checks from the supplemental
+ group name checks in user_in_group(). We now call sudo_get_gidlist()
+ only when the group name in sudoers begins with a '#' (which is
+ seldom used).
+ [80534785d8b7]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/policy.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/pwutil.h,
+ plugins/sudoers/pwutil_impl.c, plugins/sudoers/set_perms.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Cache the user's group IDs and group names separately and only
+ resolve group IDs -> names when needed. If the sudoers file doesn't
+ contain groups we will no longer try to resolve all the user's group
+ IDs to names, which can be expensive on some systems.
+ [8ce3564e896e]
+
+2016-08-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/defaults.c:
+ Remove the "op" parameter from all the store_foo() functions except
+ store_list() where it is actually needed. For the others, a NULL
+ value indicates the setting was negated. This unconfuses static
+ analyzers (and perhaps humans too).
+ [fca031b57f15]
+
+ * plugins/sudoers/defaults.c:
+ Flags always have a NULL value. Regression introduced by refactor of
+ set_default_entry().
+ [71fe4fad097b]
+
+ * plugins/sudoers/defaults.c:
+ Set rc to true when setting a flag Defaults value.
+ [cf016b6aedd4]
+
+ * src/utmp.c:
+ suppress a cppcheck false positive
+ [0d44aa7cf05c]
+
+ * plugins/sudoers/defaults.c:
+ Refactor the error parts of set_default_entry() so the switch() is
+ mostly just calls to store_foo() functions. Avoids a lot of
+ duplicated error checking and silences a cppcheck false positive.
+ [1112b894007c]
+
+ * plugins/sudoers/defaults.c:
+ In set_default_entry() check for unsupported Defaults type.
+ [beb1ae20179f]
+
+ * lib/util/aix.c:
+ Add missing break in switch that sets the max limit for
+ RLIMIT_NOFILE. Found by cppcheck.
+ [39b1979b1b92]
+
+ * plugins/sudoers/defaults.c:
+ Check sudoers_initlocale return value and treat as oom. Coverity CID
+ 141832
+ [b1cad9d6c49d]
+
+2016-08-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/match.c, plugins/sudoers/parse.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/testsudoers.c:
+ Set runas_pw early and adjust runaslist_matches() to deal. Since we
+ now set runas_default early there is no need to call update_defaults
+ with SETDEF_RUNAS after sudoers has been parsed.
+ [35e0b08219a8]
+
+2016-08-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c:
+ Load sudoers group plugin via an early callback.
+ [0fc4382cd6e4]
+
+ * sudo.pp:
+ System Integrity Protection on Mac OS X won't allow us to write
+ directly to /etc or /var. We must install in /private/{etc,var}
+ instead.
+ [831c78241e78]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document that fqdn, runas_default and sudoers_locale are parsed
+ early.
+ [beb4868c449e]
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo_plugin.cat,
+ doc/sudoers.cat, doc/sudoers.ldap.cat, doc/sudoreplay.cat,
+ doc/visudo.cat:
+ Regen for 1.8.18
+ [eb4feabb8fee]
+
+2016-08-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/defaults.h, plugins/sudoers/ldap.c,
+ plugins/sudoers/sssd.c:
+ Avoid passing around struct defaults when it is not needed. As a
+ result, we no longer need to include gram.h in the LDAP and SSSD
+ backends.
+ [14d0bfdc8bd2]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Instead of deferring setting early defaults until we have traversed
+ the entire defaults list, just defer running the callbacks.
+ Otherwise, if the last early default setting we see has a bad value
+ we won't set any defaults of that type even if there was an earlier
+ one that was valid.
+ [552863e5a097]
+
+ * plugins/sudoers/defaults.c:
+ Run callbacks once in set_default_entry() instead of each of the
+ store_foo() functions.
+ [b92b51c67845]
+
+2016-08-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg:
+ Use /proc/cpuinfo on Linux instead of running lscpu
+ [450ea436dbe4]
+
+ * mkpkg:
+ If using GNU make on a multi-cpu system, use the -j flag to run make
+ jobs in parallel, up to the number of cpus/cores.
+ [7a6670de96dc]
+
+2016-07-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo.c:
+ Only check SUDO_USER if euid is 0
+ [f42d00c94817]
+
+2016-07-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo.c:
+ Initialize sudo_user based on the SUDO_USER environment variable if
+ present. This allows things like :Defaults:username editor=foo" to
+ work when visudo is run via sudo.
+ [a526d6f74198]
+
+2016-07-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c:
+ Add function name in "command resumed" debug message
+ [e209f199a79f]
+
+ * src/exec_pty.c:
+ If waitpid() returns 0 or -1, display a warning, this should never
+ happen. Add a check for unhandled wait status (also should never
+ happen).
+ [983a0b79b527]
+
+ * plugins/sudoers/defaults.c:
+ Flag settings have a NULL value so we can't use that to test whether
+ an entry in struct early_default is set or not. Add a "set" member
+ and use that instead.
+ [68a7c0de9b0e]
+
+2016-07-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c:
+ Explicitly check for a continued process with waitpid(2). Otherwise,
+ waitpid() will return 0 when the command is resumed after being
+ suspended, which we were treating the same as -1. Fixes suspend and
+ resume on Linux and probably others.
+ [54a464b116ad]
+
+ * plugins/sudoers/defaults.c:
+ Fix --with-fqdn, the value should be NULL since it is a flag.
+ [95bc8b82911e]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Add support for early defaults to the ldap and sssd backends.
+ [3a034360c177]
+
+2016-07-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo_edit.c:
+ Repair symlink check in sudo_edit_openat_nofollow() on systems
+ without O_NOFOLLOW, it must be done relative to dfd. Previously the
+ lstat() would always fail, possibly leading to a false positive.
+ Also add an early symlink check like in sudo_edit() while here.
+ [f72901c7f7cc]
+
+ * src/sudo_edit.c:
+ On systems that lack the O_NOFOLLOW open(2) flag, check in
+ sudo_edit_open() whether the path to be opened is symlink before
+ opening it. This is racey but we detect losing the last post-open
+ and it is better to fail early if possible. When editing a link to a
+ non-existent file, a zero-length file will be left behind but it is
+ too dangerous to try and remove it after the fact. Bug #753
+ [dac04f305262]
+
+ * src/sudo_edit.c:
+ Update debug_decl for sudo_edit_openat_nofollow() Remove unused
+ variables when O_NOFOLLOW is not present.
+ [8dc0afb1de58]
+
+2016-07-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/visudo.c:
+ Split set_default_entry() out of set_default() so we can call it
+ from check_defaults() to validate the defaults value. In visudo,
+ suppress warnings from update_defaults() and rely on
+ check_defaults() to provide warnings.
+ [7d9b50f42d0b]
+
+ * plugins/sudoers/defaults.c:
+ Split binding match code out of default_type_matches() into
+ default_binding_matches(). We can now use default_type_matches() in
+ check_defaults().
+ [c158768b12c5]
+
+ * plugins/sudoers/visudo.c:
+ Pass quiet flag to init_parser() and update_defaults() when doing
+ first parse of sudoers.
+ [3af76c1a0d84]
+
+2016-07-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/ldap.c, plugins/sudoers/parse.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Update defaults in visudo after sudoers has been edited so we pick
+ up locale changes. The init_defaults() function will now re-init the
+ sudoers locale.
+ [ceb099392289]
+
+2016-07-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/testsudoers.c:
+ Set sudoers locale before calling sudoersparse(). We don't need to
+ restore the user's locale since warnings are displayed in the user's
+ locale anyway.
+ [c44a38a496d1]
+
+ * plugins/sudoers/visudo.c:
+ Set the locale to the sudoers locale when parsing and restore the
+ user's locale afterward. Also set the warn/fatal locale helper
+ function so warning messages during a sudoers parse are displayed in
+ the user's own locale.
+ [a0b2cdb69d43]
+
+ * plugins/sudoers/logging.h:
+ Add forward decl of union sudo_defs_val to silence a gcc warning.
+ [9e717510f132]
+
+ * plugins/sudoers/sudoers.c:
+ Set the warn/fatal locale helper function in sudoers_policy_init()
+ so warning messages during sudoers loading are displayed in the
+ user's own locale.
+ [b6c7bab1ca80]
+
+ * plugins/sudoers/locale.c, plugins/sudoers/logging.h,
+ plugins/sudoers/sudoers.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c:
+ Move sudoers locale callback function to locale.c and user it in
+ visudo and testsudoers.
+ [7c4e9a71e252]
+
+ * plugins/sudoers/sudoers.c:
+ In cb_sudoers_locale() actually set the locale in addition to
+ storing its name. Otherwise, it won't take effect until sudoers
+ lookup time.
+ [ceb446c2168b]
+
+ * plugins/sudoers/defaults.c:
+ Fix regression that would cause early defaults entries to be set
+ multiple times.
+ [5f5cd02d5f0f]
+
+ * NEWS, configure, configure.ac:
+ sudo 1.8.18
+ [7c778904c39b]
+
+2016-07-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/sudoers.c:
+ Only set early defaults once, regardless of how many times the
+ variable is set in sudoers. This avoids running an early callback
+ more than once. For example, we don't want to call cb_fqdn() if sudo
+ is compiled with FQDN set but sudoers has "Defaults !fqdn".
+ [0c5d80939ea2]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h:
+ Make strings const in functions that set defaults as they are not
+ modified.
+ [d01f22ab1902]
+
+ * plugins/sudoers/sudoers.c:
+ In cb_fqdn() just return if the fqdn flag is set to false.
+ [0cb3d78aa944]
+
+2016-07-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/defaults.c:
+ Implement callbacks for defaults flags (T_FLAG).
+ [936adcc98800]
+
+ * plugins/sudoers/sudoers.c:
+ add debug_decl for cb_runas_default and cb_sudoers_locale
+ [4667b1e14172]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/sudoers.c:
+ Convert fqdn to a callback and add it to the list of early defaults.
+ [df863787cf5e]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c:
+ Change defaults callbacks to take a union sudo_defs_val * instead of
+ a char *.
+ [c7730fa19e46]
+
+ * plugins/sudoers/defaults.c:
+ When updating defaults, process certain values fist since they can
+ influence how other defaults are parsed. Currently, runas_default
+ and sudoers_locale are processed early.
+ [32062737a1ae]
+
+2016-07-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/toke_util.c:
+ Fix typo introduced in last commit to fix fill_args() overflow
+ check.
+ [535d13b81c5d]
+
+ * plugins/sudoers/toke_util.c:
+ Fix underflow checl in fill_args().
+ [2c6852e65ad6]
+
+ * plugins/sudoers/toke_util.c:
+ Make sure we account for the trailing NUL when computing arg_size in
+ fill_args(). Bug #752
+ [c73c1ea4b230]
+
+ * plugins/sudoers/toke_util.c:
+ Make arg_size and arg_len unsigned since we do bitwise operations on
+ them.
+ [0a551c7a5e67]
+
+2016-07-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/Makefile.in, lib/zlib/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in,
+ src/Makefile.in:
+ Only remove backup files as part of "make uninstall" when
+ INSTALL_BACKUP is set.
+ [c2541d2de89c]
+
+ * configure, configure.ac, lib/util/Makefile.in, lib/zlib/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in,
+ src/Makefile.in:
+ Only keep backups of installed files on HP-UX where you cannot
+ unlink a shared library that is in use.
+ [8763a1d0d515]
+
+2016-07-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Ignore a missing or insecure #includedir, it is not a fatal error.
+ [8a82818c9f0d]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Make sure we always call sudoerserror() on error in
+ read_dir_files(), otherwise sudo will not treat it as a fatal error.
+ [1a38da425ca0]
+
+2016-06-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ Set the sudoers locale before opening the sudoers file. Previously
+ the sudoers locale was used when evaluating sudoers but not during
+ the inital parse. Bug #748
+ [c8deb0da75b4]
+
+ * plugins/sudoers/locale.c:
+ Add debugging
+ [5fbe2f109b92]
+
+ * plugins/sudoers/Makefile.in:
+ Don't link test programs with the sudoers-specific locale code if we
+ don't need to.
+ [41224154534e]
+
+ * plugins/sudoers/Makefile.in:
+ sudoreplay does not need to link with the sudoers-specific locale
+ code.
+ [348638a68f69]
+
+2016-06-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ new_digest was prototyped as static but not explicitly declared
+ static.
+ [52949a024acb]
+
+ * configure, configure.ac:
+ Some versions of HP-UX 11.11 do not expose struct sockaddr_ext if
+ _XOPEN_SOURCE_EXTENDED is defined. Only define
+ _XOPEN_SOURCE_EXTENDED if we can still compile net/if.h.
+ [0189ff7daa63]
+
+ * plugins/sudoers/Makefile.in:
+ Some versions of HP-UX make will ignore suffix rules if they are
+ empty.
+ [cffeee232752]
+
+2016-06-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c:
+ Don't skip debug printfs in handle_sigchld() just because execve()
+ returned an error.
+ [0cf2a9351740]
+
+ * include/compat/charclass.h, include/sudo_compat.h, lib/util/aix.c,
+ lib/util/getaddrinfo.c, lib/util/sudo_debug.c,
+ plugins/sudoers/insults.h,
+ plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/sudoers_debug.c:
+ Add definition of nitems for those without it and use it throughout.
+ [4b30c8834fdd]
+
+2016-06-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Update copyright year.
+ [638c964e44fd]
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.8.17p1
+ [bc30a172370c]
+
+ * src/sudo.c, src/sudo.h:
+ Set user groups in exec_setup() if they were not already set by
+ policy_init_session(). Bug #749
+ [3bf16489800c]
+
+2016-06-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.conf.cat, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in:
+ Point the reader to the sudoers manual for the list of supported
+ arguments after the plugin path.
+ [40cbfa5deeb1]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ forgot to update date in last commit
+ [3872a46e229b]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ Fix typo; cn=default should be cn=defaults
+ [06e097667465]
+
+2016-06-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/Makefile.in, lib/zlib/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in,
+ src/Makefile.in:
+ Fold lines at 80 characters for the clean: target
+ [651623231cd8]
+
+ * lib/util/Makefile.in:
+ Remove mksiglist, siglist.c, mksigname, signame.c as part of
+ "distclean"
+ [ed7f58685633]
+
+2016-06-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po:
+ sync with translationproject.org
+ [a3bb8c15ef3d]
+
+ * plugins/sudoers/sssd.c:
+ LDAP sudoers doesn't support negated users, groups or netgroups.
+ [d6585245c24d]
+
+2016-06-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Bug #746
+ [e0bba3ae78c2]
+
+ * plugins/sudoers/match.c:
+ When matching paths with glob(3), check returned matches against
+ user_cmnd first if it is fully-qualified. This avoids a lot of
+ needless stat(2) calls and avoids a mismatch between safe_cmnd and
+ argv[0] if there are multiple matches with the same inode/dev due to
+ links. Bug #746.
+ [29bdba0cf2eb]
+
+ * NEWS:
+ Add execve failure in pty bug fix.
+ [941672cc6793]
+
+ * plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po:
+ sync with translationproject.org
+ [a4f789cedecc]
+
+ * src/exec_pty.c:
+ In handle_sigchld() fix the return value when we've already received
+ an exec error. We don't want to overwrite the error status but we do
+ need to indicate that the command is no longer running. Fixes as
+ hang on execve(2) error when running in a pty.
+ [797bed2c39a7]
+
+ * src/exec.c, src/exec_common.c:
+ Move sudo_debug_execve() call into sudo_execve().
+ [ab2ea3459a7c]
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po, po/sr.mo,
+ po/sr.po, po/sv.mo, po/sv.po:
+ sync with translationproject.org
+ [046ba9a0fca8]
+
+2016-06-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ update for 1.8.17 final
+ [a2f02775aba5]
+
+ * lib/util/aix.c:
+ Fix setting of hard stack limit when stack_hard is not specified in
+ /etc/security/limits. When 64-bit resource limits are supported we
+ can use the default value of 8388608 512-byte blocks directly. We
+ should only resort to using RLIM_SAVED_MAX for 32-bit resource
+ limits.
+ [cc4933fc41bd]
+
+2016-06-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [4ab85a46cf63]
+
+2016-06-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sssd.c:
+ Ignore empty ipa_hostname
+ [9421ade7b47f]
+
+ * plugins/sudoers/sssd.c:
+ Better martching of ipa_hostname in sssd.conf
+ [abd53491cb4b]
+
+2016-06-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, configure, configure.ac, pathnames.h.in,
+ plugins/sudoers/sssd.c:
+ Use the value of ipa_hostname from /etc/sssd/sssd.conf if present
+ instead of the system hostname.
+ [3f5cffcd8432]
+
+2016-06-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sssd.c:
+ When matching host, short-circuit the loop when we get a match. Only
+ check username as part of the netgroup when netgroup_tuple is
+ enabled.
+ [2eab4070dcf7]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Avoid using !strcmp()
+ [f976b3d973e0]
+
+2016-06-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sssd.c:
+ SSSD doesn't handle netgroups, we have to ensure they are correctly
+ filtered in sudo. The rules may contain mixed sudoUser specification
+ so we have to check not only for netgroup membership but also for
+ user and group matches. Adapted from a patch from Daniel Kopecek.
+ [50d8d88bcc28]
+
+2016-06-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/pam.c:
+ Return PAM_CONV_ERR from the conversation function if getpass
+ returns NULL or the user pressed ^C.
+ [bec7e2ec26ff]
+
+ * plugins/sudoers/base64.c:
+ Make base64 decoding table-driven.
+ [2d001c111552]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Back out cfa26b99228f, it was already fixed differently. Caught by
+ regress checks.
+ [0584f80e9951]
+
+2016-05-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Allow double-quoted groups and netgroups to be part of a Defaults
+ spec. From Daniel Kopecek.
+ [cfa26b99228f]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ The sudoers.ldap manual is installed in section 4 or 5, not 1m or 8.
+ Also fix the section for ldap.conf cross-references.
+ [eb1c0a2b84a1]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ Fix copy pasta, "sudoNotAfter" not "sudoNotBefore". Add missing word
+ "order" in a sentence describing sudoOrder.
+ [653cb783f89b]
+
+ * plugins/sudoers/sssd.c:
+ For sudo -ll (long list) print the SSSD role just like we do for the
+ LDAP backend. Adapted from sudo-1.8.6p3-sssdrulenames.patch
+ [46f962b1f3ef]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Setting timestamp_timeout less than zero only lasts until the next
+ reboot. Adapted from a RedHat patch.
+ [f8ce1dfebfe9]
+
+ * po/it.mo, po/it.po, po/nb.mo, po/nb.po:
+ sync with translationproject.org
+ [31b55426358b]
+
+2016-05-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/conversation.c:
+ fputs() is now specified as returning non-negative on success, not
+ explicitly zero. Fixes a failure on glibc.
+ [55f8a25d4af4]
+
+ * src/conversation.c:
+ Don't try to dereference replies[] if it is a NULL pointer.
+ [c4fdd838f2f5]
+
+ * plugins/sudoers/policy.c:
+ sudo_version should be unsigned
+ [7719d425c65a]
+
+ * plugins/sudoers/po/ca.mo, plugins/sudoers/po/ca.po,
+ plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po, po/ca.mo,
+ po/ca.po, po/cs.mo, po/cs.po, po/da.mo, po/da.po, po/de.mo,
+ po/de.po, po/fr.mo, po/fr.po, po/hr.mo, po/hr.po, po/ja.mo,
+ po/ja.po, po/pl.mo, po/pl.po, po/sk.mo, po/sk.po, po/sv.mo,
+ po/sv.po, po/uk.mo, po/uk.po, po/vi.mo, po/vi.po, po/zh_CN.mo,
+ po/zh_CN.po:
+ sync with translationproject.org
+ [e40cdc972d19]
+
+ * MANIFEST, NEWS, doc/CONTRIBUTORS, plugins/sudoers/po/ko.mo,
+ plugins/sudoers/po/ko.po, po/ko.mo, po/ko.po:
+ Korean translation for sudo and sudoers from translationproject.org.
+ [188ffbed5bf2]
+
+ * NEWS, plugins/sudoers/auth/pam.c:
+ Ignore PAM_SESSION_ERR from pam_open_session() since this can
+ apparently happen on systems using Solaris-derived PAM. Other errors
+ from pam_open_session() are treated as fatal. This avoids the
+ "policy plugin failed session initialization" error message seen on
+ some systems.
+ [0f7f3e7ead21]
+
+2016-05-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, src/exec_pty.c:
+ Don't read from stdin when flushing final buffers in blocking mode.
+ Reading from the pipe can block too if the other end is not closed.
+ [a651f913a1ef]
+
+2016-05-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Mention visudo -x change.
+ [2fd35df055b2]
+
+ * plugins/sudoers/regress/sudoers/test1.json.ok,
+ plugins/sudoers/regress/sudoers/test14.json.ok,
+ plugins/sudoers/regress/sudoers/test15.json.ok,
+ plugins/sudoers/regress/sudoers/test16.json.ok,
+ plugins/sudoers/regress/sudoers/test2.json.ok,
+ plugins/sudoers/visudo_json.c:
+ There's no need to escape forward slashes in JSON output. While it
+ is legal to escape a forward slash, it is not required.
+ [044710f516a9]
+
+ * doc/UPGRADE:
+ Document that in 1.8.12 sudo started being able to check the NIS
+ domain on Solaris.
+ [bced94478c0e]
+
+2016-05-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Better description of the I/O logging pipe issue.
+ [6eee2f8a1fae]
+
+ * src/exec_pty.c:
+ In del_io_events(), avoid reading from the pty master in blocking
+ mode. We now do two passes, one with SUDO_EVLOOP_NONBLOCK and
+ another that could block if stdin is a pipe. This ensures we consume
+ the pipe until EOF.
+ [564ae2b4c305]
+
+ * lib/util/event.c:
+ Improve debug info in sudo_ev_add() and sudo_ev_del()
+ [ca839439ff22]
+
+ * src/exec_pty.c:
+ In pty_close(), call del_io_events with the SUDO_EVLOOP_ONCE flag so
+ the event loop will exit after a single run through. Otherwise, we
+ may hang at exit on non-BSD systems.
+ [e6c38d5a341b]
+
+2016-05-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * po/sudo.pot:
+ regen
+ [18a4570be506]
+
+2016-05-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c:
+ Bump I/O buffer size to 64K. We don't use PIPE_BUF or _PC_PIPE_BUF
+ for this because that corresponds to the value for atomic pipe
+ writes. The actual pipe buffer is much larger on modern systems and
+ 64K is what BSD and Linux support for large pipe buffers.
+ [3b5d995966ef]
+
+ * NEWS:
+ I/O logging bug fix
+ [934d755ac12c]
+
+ * src/exec_pty.c:
+ Don't use SUDO_EVLOOP_NONBLOCK when flushing buffers at pty close
+ time, only when the user suspends sudo. Fixes a problem where all
+ buffers might not get flushed at exit when logging I/O. Reproducible
+ via "sudo tar cf - foo | (cd /tmp && sudo tar xf -)" on OpenBSD.
+ [bbe0e18739ec]
+
+2016-05-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo_json.c:
+ Don't try to fflush(export_fp) or ferror(export_fp) if export_fp is
+ NULL, which can happen on the error path.
+ [ccfb4dd260fa]
+
+ * plugins/sudoers/sudoers.c, src/exec.c, src/exec_pty.c, src/sudo.c,
+ src/tgetpass.c:
+ O_NOCTTY has no effect when opening /dev/tty as the open can only
+ succeed if there is already a controlling tty.
+ [9ca106c499b2]
+
+ * src/sudo.c:
+ Do not need to open /dev/tty with O_NONBLOCK, it doesn't block on
+ first open like a physical terminal. By definition, if you have a
+ controlling tty, the first open (which might block) has already
+ occurred.
+ [15a5f006836a]
+
+ * src/selinux.c:
+ Use O_NOCTTY when opening a tty.
+ [5f9fd6458be4]
+
+ * src/Makefile.in:
+ regen
+ [105ef4533724]
+
+ * plugins/sudoers/auth/sudo_auth.c:
+ No need to set pass to NULL after freeing at the end of the loop it
+ since it is already set to NULL each time through the loop.
+ [2657b0b4260d]
+
+2016-05-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ SELinux fixes in 1.8.17.
+ [f743cf0d9c62]
+
+ * plugins/sudoers/logging.h, plugins/sudoers/logwrap.c:
+ Check fprintf() return value in writeln_wrap() and return the number
+ of characters actually written, or -1 on error.
+ [4739e0f58fa3]
+
+ * src/conversation.c:
+ Check fputs() return value.
+ [e85778cbe0e3]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Do not write directly to stdout/stderr, use sudo_printf which calls
+ the conversation function.
+ [e86d5ed4dca7]
+
+ * plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/securid5.c:
+ Do not write directly to stdout/stderr, use sudo_printf which calls
+ the conversation function.
+ [002a30fdb4e0]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/visudo_json.c:
+ Use ferror() after fflush() to check the error status of the stdio
+ stream we wrote to.
+ [fa1db13fe9ac]
+
+2016-05-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/parse.c:
+ printf() returns < 0 on error, not explicitly -1
+ [2a2385b941de]
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo_plugin.cat,
+ doc/sudoers.ldap.cat, doc/sudoreplay.cat, doc/visudo.cat:
+ Regen for 1.8.17
+ [e24b0f944000]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document that you need to preserve EDITOR and/or VISUAL for
+ env_editor to be useful.
+ [ef0ce8917307]
+
+ * src/selinux.c:
+ Fix last commit, now that argc is not reset we need to explicitly
+ start the copy from argv[1]. From Daniel Kopecek
+ [f52403ef587a]
+
+2016-05-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/selinux.c:
+ cosmetic change to warning string
+ [a2893e3f9b70]
+
+ * plugins/sudoers/auth/pam.c:
+ Avoid adding an extraneous warning string to sudoers.pot.
+ [6b07043b48f7]
+
+ * lib/util/snprintf.c:
+ Use EOVERFLOW, not ENOMEM for overflow conditions. For snprintf()
+ and vsnprintf(), POSIX says we should return -1 and set errno to
+ EOVERFLOW if the size param is > INT_MAX; also zero out the string
+ in this case (not mandated by POSIX) for safety.
+ [294720fc981a]
+
+2016-05-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/pam.c:
+ Now that pam_open_session() failure is fatal we should print and log
+ an error from it. Bug #744
+ [0e98a92ef910]
+
+ * src/selinux.c:
+ Repair SELinux support, broken by 397722cdd7ec. From Daniel Kopecek.
+ [1246583c7c1f]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Remove sudo_mkpwcache() and sudo_mkgrcache(). We now create the
+ caches as needed on demand. Also remove calls to sudo_freepwcache()
+ and sudo_freegrcache() that are immediately followed by execve(),
+ they are not needed.
+ [60448afe813d]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/logging.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c:
+ Eliminate use of setpwent()/endpwent() and setgrent()/endgrent().
+ Sudo never iterates over the passwd or group file. Rename
+ sudo_set{pw,gr}ent() -> sudo_mk{pw,gr}cache() and use
+ sudo_free{pw,gr}cache() instead of sudo_end{pw,gr}ent().
+ [66e6f5e7b51b]
+
+2016-05-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/parse.h:
+ Remove unnecessary NULL checks in the RUNAS_CHANGED macro. The only
+ place where the pointers could be NULL is in visudo_json.c but we
+ already check for "next" being NULL there. Quiets a cppcheck
+ warning.
+ [a0d84832c154]
+
+2016-05-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c:
+ In replay_session() free iov at the end of the function (if needed)
+ instead of after processing each line from the timing file. Coverity
+ CID 104843.
+ [5112f514af87]
+
+ * plugins/sudoers/sudoreplay.c:
+ Add io_log_read() and io_log_gets() to hide differences between
+ gzread/fread and gzgets/fgets. Check for premature EOF and error
+ from io_log_read(). Also sanity check the index in the timing file.
+ Coverity CID 104630.
+ [6a3b9932f567]
+
+ * src/exec_pty.c:
+ Break up io_callback() into read_callback() and write_callback() to
+ make it clear that we can't get an event with both read and write
+ set.
+ [cd3a1e182dd4]
+
+2016-05-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c:
+ In io_callback() make sure we clear SUDO_EV_READ if we close the fd.
+ It should not be possible for SUDO_EV_READ to be set when revent is
+ non-NULL but this makes static analyzers happier. Coverity CID
+ 104124.
+ [7acc249fa098]
+
+ * plugins/sudoers/ldap.c:
+ In sudo_krb5_copy_cc_file() move the close(ofd) to the done: label
+ so we only have to cleanup in one place. Coverity CID 104577.
+ [0f189e70c59d]
+
+ * plugins/sudoers/ldap.c:
+ Fix memory leak in sudo_netgroup_lookup() in the non-error case.
+ Coverity CID 104572, 104573, 104574, 104575.
+ [7f9fb7a360b7]
+
+ * plugins/sudoers/ldap.c:
+ Fix fd leak in sudo_krb5_copy_cc_file() if restore_perms() fails.
+ Coverity CID 104571.
+ [d9434cdfb73c]
+
+ * plugins/sudoers/sudoreplay.c:
+ Free the events and event base before returning from
+ replay_session(). Coverity CID 104116, 104117.
+ [321216089e4a]
+
+ * src/sudo_edit.c:
+ In sudo_edit_create_tfiles(), fix fd leak if sudo_edit_mktemp()
+ fails. Coverity CID 104114.
+ [713de09ff956]
+
+ * src/sudo_edit.c:
+ Fix fd leak in sudo_edit_open_nonwritable() if dir_is_writable()
+ returns an error. Coverity CID 104113.
+ [314a57004f00]
+
+ * src/sudo_edit.c:
+ Fix memory leak of sesh_args in selinux_edit_copy_tfiles(). Coverity
+ CID 104112.
+ [ac7f0cbd07c9]
+
+ * plugins/sudoers/visudo.c:
+ Fix memory leak in get_editor() if resolve_editor() fails with an
+ error. Coverity CID 104107.
+ [e355b1f45bcb]
+
+ * src/sudo.c:
+ Fix memory leak on error if sudo_new_key_val() fails. Coverity CID
+ 104103.
+ [c2ee1557aef2]
+
+ * plugins/sudoers/visudo.c:
+ Ignore the return value of the initial sudoersparse(), before we
+ have actually edited any files. Coverity CID 104078.
+ [184d9c6aec65]
+
+ * src/exec.c:
+ Ignore the result of send() on exec error, if it fails the other end
+ of the pipe is gone and we are headed for exit. Coverity CID 104066.
+ [cdcd7dfcbca1]
+
+ * plugins/sudoers/toke_util.c:
+ In fill_args() clean up properly if there is an internal overflow
+ (which should not be possible). Coverity CID 104569.
+ [0bc710e91ec4]
+
+ * plugins/sudoers/gc.c:
+ Fix logic inversion in sudoers_gc_remove(), currently unused.
+ Coverity CID 104568
+ [e29df8da11ea]
+
+2016-05-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ In io_mkdirs(), change the order from stat then mkdir, to mkdir then
+ stat. This more closely matches what "mkdir -p" does. Coverity CID
+ 104120.
+ [e462528ff7ea]
+
+ * plugins/sudoers/timestamp.c:
+ In ts_mkdirs(), change the order from stat then mkdir, to mkdir then
+ stat. This more closely matches what "mkdir -p" does. Coverity CID
+ 104119.
+ [c0c0e2662883]
+
+ * plugins/sudoers/sudoers.c:
+ Newer versions of Ubuntu have switched from using the "admin" group
+ to the "sudo" group to align with Debian.
+ create_admin_success_flag() now accepts either one.
+ https://bugs.launchpad.net/ubuntu/+source/sudo/+bug/1387347
+ [17b4d725dac4]
+
+ * plugins/sudoers/timestamp.c:
+ Cast off_t printed via printf(3) instead of assuming it is long
+ long.
+ [b1d398f4a8dc]
+
+ * plugins/sudoers/sudoers.c:
+ Instead of using stat(2) to see if the admin flag file exists and
+ creating it if not, just try to create the file and treat EEXIST as
+ a non-error. Coverity CID 104121.
+ [bd58b0a35a3c]
+
+ * MANIFEST, plugins/sample/README:
+ README file for the sample plugin that tells the user how to build,
+ install and enable it.
+ [8d7096ce78cc]
+
+ * plugins/sample/sample_plugin.c:
+ Fix compilation error and export sample_policy struct. From Michael
+ Evans
+ [5280c1576e7f]
+
+ * NEWS:
+ Update for 1.8.17
+ [979688a5ef13]
+
+ * configure, configure.ac:
+ Sudo 1.8.17
+ [09311b2e9697]
+
+ * plugins/sudoers/logging.c:
+ Check return value of restore_perms() in vlog_warning(). Coverity
+ CID 104079.
+ [86555dd0942d]
+
+ * plugins/sudoers/editor.c:
+ Fix memory leaks in resolve_editor() in the error path. Coverity CID
+ 104109, 104110
+ [6ac3f7e3ada9]
+
+ * plugins/sudoers/policy.c:
+ Fix memory leak of gid_list in sudoers_policy_exec_setup() in the
+ error path. Coverity CID 104111.
+ [eac1e9489367]
+
+ * plugins/sudoers/logging.c:
+ Fix fd leak in do_logfile() if we fail to lock the log file.
+ Coverity CID 104115.
+ [164a693207a8]
+
+ * plugins/sudoers/sssd.c:
+ Fix memory leak of sss_result in sudo_sss_lookup() Coverity CID
+ 104106
+ [7dcee1e6d76f]
+
+ * plugins/sudoers/iolog.c:
+ Fix fd leak in open_io_fd() if gzdopen/fdopen fails. Coverity CID
+ 104105
+ [c4c2848c1167]
+
+ * plugins/sudoers/iolog.c:
+ Fix fd leak in io_nextid() in error path. Coverity CID 104104
+ [8920cdaab5bd]
+
+2016-05-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/timestamp.c:
+ Check lseek() return value. Coverity CID 104061.
+ [bf3bb4c80cfc]
+
+ * plugins/sudoers/timestamp.c:
+ Ignore ts_write() return value when disabling an entry with a bogus
+ timestamp. We ignore the timestamp entry even it doesn't succeed.
+ Coverity CID 104062.
+ [5e5925ebbc75]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/match.c,
+ plugins/sudoers/tsgetgrpw.c, src/exec.c, src/exec_pty.c, src/sudo.c:
+ Cast the return value of fcntl() to void when setting FD_CLOEXEC.
+ Coverity CID 104063, 104064, 104069, 104070, 104071, 104072, 104073,
+ 104074
+ [48720d2f6658]
+
+ * plugins/group_file/getgrent.c:
+ Cast the return value of fcntl() to void when setting FD_CLOEXEC.
+ Coverity CID 104075, 104076, 104077.
+ [7fe1d9f97321]
+
+ * plugins/sudoers/env.c:
+ Avoid a false positive. Coverity CID 104056.
+ [0256978219a6]
+
+ * plugins/sudoers/visudo_json.c:
+ Avoid calling fclose(NULL) on error in export_sudoers(). Coverity
+ CID 104091.
+ [2f73d86ab929]
+
+ * plugins/sudoers/toke_util.c:
+ In fill_args(), check for "arg_size == 0" instead of
+ "sudoerslval.command.args == NULL" since the latter leads Coverity
+ to imply that sudoerslval.command.args could be NULL later on.
+ Coverity CID 104093.
+ [bab505438881]
+
+ * plugins/sudoers/sudoers.c:
+ Avoid calling fclose(NULL) if the sudoers file is not secure and
+ restore_perms() fails. Coverity CID 104090.
+ [150db126c221]
+
+2016-05-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/toke.h, plugins/sudoers/toke_util.c:
+ In fill_args(), replace loop that increments arg_size() with a
+ simple add and mask. Should prevent a false positive from Coverity
+ CID 104094.
+ [411c7e398286]
+
+ * plugins/sudoers/sudoreplay.c:
+ In parse_expr(), move the "bad" label after the "default" case in
+ the switch(), not before it. This seemed to confuse Covertity,
+ resulting in a false positive, CID 104095.
+ [4371f26995fb]
+
+ * doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in:
+ For "sudoreplay -l", not all predicates may be shortened to a single
+ character. Both 'c' and 't' have more than one possibility.
+ [29a5a9a313e2]
+
+ * src/exec.c, src/exec_pty.c, src/sudo.c:
+ pid_t is defined by POSIX as a signed integer type so we don't need
+ a cast when comparing to -1.
+ [98f0a86260a0]
+
+ * src/exec.c:
+ In dispatch_signal() for stopped processes check for tcgetpgrp()
+ returning -1. Also change checks from "saved_pgrp != -1" to "fd !=
+ -1". Coverity CID 104098.
+ [42ac4ad85900]
+
+ * src/selinux.c:
+ In relabel_tty() always jump to bad: on error, regardless of the
+ value of se_state.enforcing. On error, return -1 if enforcing, else
+ 0. Coverity CID 104099.
+ [db1a54d718f1]
+
+ * config.h.in, configure.ac:
+ Define NO_LEAKS when sudo is built with Coverity.
+ [f4209b9ade8c]
+
+ * src/exec_pty.c:
+ In io_callback() if we write the complete buffer and find that there
+ is no associated reader just return as there is nothing else to be
+ done. In practice is it not possible for SUDO_EV_READ to be set if
+ revent is NULL but an early return is harmless and possibly easier
+ to understand. Coverity CID 104124.
+ [3b3eb45b701e]
+
+ * src/sudo_edit.c:
+ Handle read() returning -1 when creating temporary files. Coverity
+ CID 104100
+ [e82af51e4f48]
+
+ * plugins/sudoers/policy.c:
+ Fix cut and paste error when checking cols for 0. Coverity CID
+ 104081
+ [22a3b7d9bce1]
+
+ * plugins/sudoers/pwutil.c:
+ Use a single debug message for cache hit or store to avoid another
+ situation where they get out of sync. Bug #743
+ [4cf484e9b016]
+
+ * plugins/sudoers/pwutil.c:
+ Sync the "cache hit" debug messages with the "cached" debug
+ messages. This fixes a bug where we could dereference a NULL pointer
+ when we look up a negative cached entry which is stored as a NULL
+ passwd or group struct pointer. Bug #743.
+ [1d13341d53ec]
+
+2016-04-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ Remove the check for __sprintf_chk when checking for
+ _FORTIFY_SOURCE, Some implementations are purely header-file based.
+ As long as we can link a test program using sprintf() when
+ _FORTIFY_SOURCE=2 it should be safe to use.
+ [910af8ba4666]
+
+ * config.h.in, configure, configure.ac:
+ Remove configure checks for dev_t, id_t, ino_t, ptrdiff_t, size_t
+ and ssize_t. These have been specified by either ANSI C or POSIX for
+ long enough that if the system doesn't support them, it is unlikely
+ to be able to compile sudo anyway.
+ [c9fd433cfe27]
+
+ * src/sudo.c:
+ Do group setup in policy_init_session() before calling out to the
+ plugin. This makes it possible for the pam_group module to change
+ the group in pam_setcred(). It's a bit bogus since pam_setcred() is
+ documented as not changing the group or user ID, but pam_group is
+ shipped with stock Linux-PAM so we need to support it.
+ [814cda602541]
+
+2016-04-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/logging.c:
+ Add missing newline when logging to a file (not syslog) and
+ loglinelen is set to a non-positive number. Bug #742
+ [ef0a5428a574]
+
+2016-04-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c:
+ style fix; fork_cmnd should start on a new line
+ [e8211fe0f8d7]
+
+2016-04-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, plugins/sudoers/ldap.c,
+ plugins/sudoers/logging.c, src/signal.c, src/sudo.c, src/tgetpass.c:
+ Ignore SIGPIPE for the duration of sudo and not just in a few select
+ places. We have no control over what nss, PAM modules or sudo
+ plugins might do so ignoring SIGPIPE is safest.
+ [7c919101b8ec]
+
+ * src/selinux.c:
+ Use string_to_security_class() instead of pulling SECCLASS_CHR_FILE
+ from flask.h. Avoids a warning with new SELinux includes.
+ [24f357b419c4]
+
+2016-04-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/parse.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ When determining whether or not "sudo -l" or "sudo -b" should prompt
+ for a password, take all sudoers sources into account. In other
+ words, if both file and ldap sudoers sources are in use, "sudo -v"
+ will now require that all entries in both sources be have NOPASSWD
+ (file) or !authenticate (ldap) in the entries.
+ [51e2a5ecacc6]
+
+2016-03-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/sudo_auth.h:
+ If the auth_type setting in /etc/security/login.cfg is set to
+ PAM_AUTH but pam_start() fails, fall back to use AIX authentication.
+ Skip the auth_type check if sudo is not compiled with PAM support.
+ [cdbe432c465c]
+
+2016-03-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.conf.cat, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in:
+ The header for sudo.conf(5) should be SUDO.CONF(5) not SUDO(5).
+ [d3afd5bd550f]
+
+2016-03-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/policy.c:
+ hook_version and hook_type are unsigned so use 0, not -1 in the
+ final (empty) entry. Quiets a warning on Solaris Studio 12.2.
+ [4947de8e35b7]
+
+2016-03-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, config.h.in, configure, configure.ac,
+ plugins/sudoers/auth/pam.c:
+ Work around an ambiguity in the PAM spec with respect to the
+ conversation function. It is not clear whether the "struct
+ pam_message **msg" is an array of pointers or a pointer to an array.
+ Linux-PAM and OpenPAM use an array of pointers while Solaris/HP-
+ UX/AIX uses a pointer to an array. Bug #726.
+ [d2b926e2f7d6]
+
+2016-03-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po, po/eo.mo,
+ po/eo.po, po/it.mo, po/it.po, po/ja.mo, po/ja.po, po/ru.mo,
+ po/ru.po, po/sr.mo, po/sr.po:
+ sync with translationproject.org
+ [271c6738213d]
+
+2016-02-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Bug #738
+ [9e7974480cdc]
+
+2016-02-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po, po/nb.mo,
+ po/nb.po:
+ sync with translationproject.org
+ [6aa32f6e5240]
+
+ * lib/util/regress/fnmatch/fnm_test.in:
+ Better test for negated character classes.
+ [635e3c17bca1]
+
+ * lib/util/regress/fnmatch/fnm_test.in:
+ Add test for negated character class
+ [0d813e098864]
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po, po/cs.mo,
+ po/cs.po, po/de.mo, po/de.po, po/fr.mo, po/fr.po, po/pl.mo,
+ po/pl.po, po/pt_BR.mo, po/pt_BR.po, po/uk.mo, po/uk.po, po/vi.mo,
+ po/vi.po, po/zh_CN.mo, po/zh_CN.po:
+ sync with translationproject.org
+ [9398ffdc7719]
+
+ * NEWS:
+ sync
+ [a27a7d40491e]
+
+ * lib/util/fnmatch.c:
+ Fix negation of character classes.
+ [aed07c013a41]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Fix the check for whether a user is allowed to lists another user's
+ privileges. The "matched" variable is not boolean, it can also have
+ the value UNSPEC so we need to check explicitly for true. Bug #738
+ [e8ed706fda03]
+
+ * plugins/sudoers/auth/pam.c:
+ Log the number of PAM messages in the conversation function at debug
+ level.
+ [3f16eea5875f]
+
+2016-02-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ Don't check for posix_spawn() or posix_spawnp() if we were unable to
+ find spawn.h. This should only be a problem on systems with broken
+ headers. Bug #730
+ [5e5b0646dca4]
+
+2016-02-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ update for 1.8.16
+ [bad5e6534f39]
+
+ * doc/CONTRIBUTORS, plugins/sudoers/sudoers2ldif:
+ Fix documented bug with duplicate role names and turn on perl
+ warnings. Based on a diff from Aaron Peschel
+ [344a1c1f5c93]
+
+2016-02-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/aix.c:
+ Add declaration of getauthdb() for AIX 5.1
+ [f758960bcfd6]
+
+2016-02-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [e61e1241f15f]
+
+ * plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po:
+ sync with translationproject.org
+ [2f3dea24199b]
+
+ * INSTALL:
+ Add a note that --with-solaris-audit is only for Solaris 11 and
+ above. Bug #737
+ [6722331c2830]
+
+2016-02-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ Remove last remnants of the deprecated --with-stow option.
+ [8616d6de7ecd]
+
+ * src/Makefile.in:
+ src/load_plugins.c needs _PATH_SUDO_CONF so allow it to be
+ overridden via the Makefile like other consumers of _PATH_SUDO_CONF.
+ Bug #735
+ [10148ef883ec]
+
+2016-02-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac, include/sudo_util.h, lib/util/aix.c,
+ lib/util/getgrouplist.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/pwutil.h, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/set_perms.c, src/sudo.c:
+ Add an administrative domain to the passwd/group cache key for AIX
+ which can have different name <-> ID mappings depending on whether
+ the database is local, LDAP, etc.
+ [5319c11aefe9]
+
+ * mkpkg, sudo.pp:
+ Fedora dropped "core" from the name some time ago so just match on
+ f[0-9] for the rpm distro name provided by pp. Since the version
+ numbers of Fedora and RHEL are so different switch to defining
+ variables to indicate which features should be enabled. Works for
+ Fedora 23.
+ [4ec50b352293]
+
+2016-01-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg, sudo.pp:
+ Treat fedora core like centos/rhel for package building.
+ [0dfc607d07a1]
+
+2016-01-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/parser/check_fill.c:
+ Plug some memory leaks in the tests.
+ [ce76ba538867]
+
+ * plugins/sudoers/toke_util.c:
+ If realloc of sudoerslval.command.args fails, reset
+ sudoerslval.command.args as well as arg_len and arg_size after
+ freeing sudoerslval.command.args.
+ [6481bad56e6a]
+
+ * src/exec_pty.c:
+ When freeing the iobs after pty tear-down, also free the associated
+ event structures. Quiets a memory leak warnings from address
+ sanitizer and valgrind.
+ [f19c689a2ded]
+
+2016-01-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ iolog_compress should be bool, not int
+ [b437123a242b]
+
+ * plugins/sudoers/visudo.c:
+ Quiet address sanitizer leak detector.
+ [b7ce672331f6]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/env.c,
+ plugins/sudoers/gc.c, plugins/sudoers/sudoers.h:
+ Simple garbage collection (really a to-be-freed list) for the
+ sudoers plugin. Almost identical to what sudo.c uses. Currenly only
+ the environment strings are collected at exit time which is enough
+ to quiet address sanitizer's leak detector.
+ [47f32e047b1a]
+
+ * src/sudo.c:
+ Rename gc_cleanup to gc_run and remove I/O plugins from the plugin
+ list when freeing them.
+ [ea640f0b46f9]
+
+ * src/sudo.c:
+ Free up the garbage via an atexit() handler instead of requiring a
+ call to gc_exit.
+ [cc9c96d88595]
+
+ * src/sudo_edit.c:
+ Plug a memory leak in sudo_edit.
+ [cab9a13a669b]
+
+2016-01-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ mention --enable-asan
+ [ee2bc0f60c8b]
+
+ * plugins/sudoers/auth/sudo_auth.c:
+ Try to deconfuse static analyzers a bit.
+ [7e728c76f5df]
+
+ * plugins/sudoers/sssd.c:
+ Avoid possible NULL deref found by clang analyzer.
+ [8bb3cbfe0446]
+
+ * config.h.in, configure, configure.ac:
+ Add --enable-asan configure flag to enable address sanitizer
+ [8aae250fb68e]
+
+ * src/sudo.c, src/sudo_plugin_int.h, src/ttyname.c:
+ Add support for garbage collecting info passed to the plugin before
+ exit to appease address sanitizer's leak detector (and valgrind's
+ leak checker). We can't free these sooner since the plugin may be
+ using the memory. For plugin API 2.0 it should be make clear that
+ the plugin must make a copy of the data in the arrays passed in to
+ the plugin's open() function. Only enabled if NO_LEAKS is defined.
+ [8458bcb165d8]
+
+ * plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c:
+ auth_getpass() returns a dynamically allocated copy of the plaintext
+ password which needs to be freed after checking (and clearing) it.
+ [28d2c83c3ac4]
+
+ * src/sudo.c:
+ Remove sudo_fatalx() calls from format_plugin_settings().
+ [96a18a3ccc49]
+
+ * plugins/sudoers/sssd.c:
+ fn_free_result() (aka sss_sudo_free_result() in sss_sudo.c) handles
+ a NULL poiner so there's no need to check before calling it. Add
+ missing initialization of sss_sudo_result to NULL in
+ sudo_sss_setdefs().
+ [fa1c8eaed6ac]
+
+ * plugins/sudoers/sssd.c:
+ Add missing return when user is not found in sudo_sss_result_get().
+ Previously we fell through to the default case which just logged a
+ debug message and returned so this just avoids the extra (generic)
+ debug message.
+ [68c2201f3a85]
+
+2016-01-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/gettime.c:
+ Fix a warning on AIX.
+ [4ebc19a143ff]
+
+ * src/sudo.c:
+ Pass updated user_env_out, not envp, to the I/O open function.
+ [f02e6f32f189]
+
+ * src/sudo.c:
+ Pass updated argv/envp to the I/O open function like the plugin API
+ documents.
+ [ff9f4fae5cf3]
+
+2016-01-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ Add check for I/O log file handle being NULL. This could only happen
+ if the front-end calls iolog_open with argc == 0 but actually runs a
+ command.
+ [5113a3c04494]
+
+2016-01-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/pwutil.c:
+ Additional debugging for pwutil functions.
+ [908b83c3acbb]
+
+ * config.h.in, configure, configure.ac, lib/util/aix.c:
+ When calling setauthdb(), save the old registry value so we can
+ restore it properly. Previously we were setting the registry to
+ unrestricted instead of actually restoring it.
+ [5a2921412663]
+
+ * plugins/sudoers/sudoers.c:
+ Use SUDOERS_DEBUG_UTIL not SUDO_DEBUG_UTIL in the plugin.
+ [79b012777e71]
+
+2016-01-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/sudo_debug.c:
+ When parsing debug entries, don't make a lower value override a
+ higher one. For example, for "pcomm@debug,all@warn" the "all@warn"
+ should not set pcomm to "warn" when it is already at "debug".
+ [031037a56e51]
+
+2016-01-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/policy.c:
+ Set sudoedit_checkdir=false in command_details when it is disabled
+ in sudoers.
+ [811dd43b29f5]
+
+ * include/sudo_compat.h, lib/util/strtobool.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/sssd.c, src/sudo_edit.c:
+ Update copyright year
+ [5ec484920763]
+
+ * src/sudo_edit.c:
+ If the user runs "sudoedit /" we will receive ENOENT from openat(2)
+ and sudoedit will try to create a file with the null string. If path
+ is empty, open the cwd instead so sudoedit can give a sensible error
+ message.
+ [fc39d5804f1f]
+
+ * lib/util/strtobool.c:
+ Log an error for invalid boolean strings.
+ [004afa5e05c5]
+
+ * src/sudo.c:
+ Fix off by one error in new SET_FLAG macro.
+ [5bdce4edf8b9]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document the race with sudoedit_checkdir in 1.8.15.
+ [cb7aed3367e9]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in:
+ Document sudoedit_checkdir
+ [89f2452272ad]
+
+2016-01-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo_edit.c:
+ There are no systems that support O_SEARCH/O_PATH that do not also
+ support O_DIRECTORY so simplify the definition of DIR_OPEN_FLAGS a
+ bit.
+ [a48f11ea53b3]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [8ae4d883ac59]
+
+ * NEWS, doc/UPGRADE:
+ Add 1.8.16 changes
+ [8d3a3f5cdf59]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/defaults.c,
+ src/sudo.c:
+ Make sudoedit_checkdir the default and update the documentation
+ accordingly.
+ [84bbc1b73411]
+
+ * src/sudo.c:
+ Add a SET_FLAG macro to simplify parsing command details boolean
+ flags. Previously, flags were only set and never cleared even if the
+ boolean value was false. This was not a problem as there were no
+ default flags for the plugin to enable. That will change in the
+ future.
+ [75f24ca13f41]
+
+2016-01-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo_edit.c:
+ Need to be root when switching to a different user.
+ [06d5f010b607]
+
+ * src/sudo_edit.c:
+ Use O_SEARCH on systems without O_PATH if present. It can be used
+ for a similar purpose.
+ [3f559a389bf9]
+
+ * config.h.in, configure, configure.ac, src/sudo_edit.c:
+ Use faccessat(2) for directory writability instead of doing the
+ checks manually where possible. This also allows us to remove the
+ #ifdef __linux__ bits since we no longer use fstat(2) on Linux with
+ an O_PATH fd.
+ [fe50d0c1f1b9]
+
+2016-01-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Add "I/O LOG FILES" section to the manual and move many of the
+ details from the log_input and log_output descriptions to it.
+ [a604903f5ae3]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Use "Nm sudoers" when talking about the plugin and "Em sudoers" when
+ talking about the sudoers file.
+ [727a68b02de7]
+
+2016-01-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/zlib/zlib.exp:
+ Remove gzopen_w which is only defined on Windows.
+ [a73236903e7b]
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h:
+ Work around the buggy pread(2) on 32-bit HP-UX 11.00 by using
+ pread64() on that platform.
+ [31c4be934115]
+
+2016-01-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/match.c,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/sssd.c, plugins/sudoers/testsudoers.c:
+ Add support for matching the entire netgroup tuple (user, host,
+ domain).
+ [9f694ba7c86d]
+
+ * plugins/sudoers/ldap.c:
+ Use asprintf() to generate the netgroup filter instead of using lots
+ of concatenation.
+ [f8290c040aea]
+
+ * lib/util/util.exp.in:
+ Add missing sudo_debug_exit_ssize_t_v1 symbol.
+ [9407fb25dfa4]
+
+2016-01-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/match.c:
+ Silence warning in digest_matches() on systems with no fexecve(2).
+ [0cd3cc8fa195]
+
+ * plugins/sudoers/sssd.c:
+ Fix free() of invalid pointer introduced in the commit that stripped
+ whitespace between a '!' and the name in a sudoOption.
+ [4d2c1761c752]
+
+ * plugins/sudoers/ldap.c:
+ Fix free() of invalid pointer introduced in the commit that stripped
+ whitespace between a '!' and the name in a sudoOption.
+ [14391603a9e5]
+
+ * src/sudo_edit.c:
+ Add missing dfd argument to the version of
+ sudo_edit_openat_nofollow() for systems without O_NOFOLLOW.
+ [574e4a840879]
+
+ * plugins/sudoers/ldap.c:
+ In sudo_netgroup_lookup() only build up the search filter once
+ instead of once per netgroup_base.
+ [a03440237078]
+
+ * plugins/sudoers/ldap.c:
+ It is safe to pass ldap_msgfree() a NULL pointer.
+ [abc2eaddbf83]
+
+ * plugins/sudoers/ldap.c:
+ On overflow, warn before freeing anything.
+ [2e3bcfa4a8f9]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Use user_runhost and user_srunhost instead of user_host and
+ user_shost. Fixes "sudo -l -h other_host" for LDAP and sssd.
+ [e1abfdc82242]
+
+ * plugins/sudoers/def_data.c, plugins/sudoers/def_data.in:
+ Update description of sudoedit_checkdir. Reported by Sander Bos.
+ [ee44e7255096]
+
+ * src/sudo_edit.c:
+ No need to check whether the fd we opened is really a directory in
+ sudo_edit_open_nonwritable() since if not, the openat() will fail
+ with ENOTDIR anyway.
+ [b41c5b289f35]
+
+2016-01-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS, doc/UPGRADE, doc/sudoers.cat, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in, include/sudo_compat.h, src/sudo_edit.c:
+ Rewritten sudoedit_checkdir support that checks all the dirs in the
+ path and refuses to follow symlinks in writable directories. This is
+ a better fix for CVE-2015-5602. Adapted from a diff by Ben
+ Hutchings. Bug #707
+ [c2e36a80a279]
+
+2016-01-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/po/ca.mo, plugins/sudoers/po/ca.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po, po/ca.mo,
+ po/ca.po, po/fi.mo, po/fi.po, po/hu.mo, po/hu.po, po/sr.mo,
+ po/sr.po:
+ sync with translationproject.org
+ [94ffd6b18431]
+
+ * configure, configure.ac, doc/sudo_plugin.cat,
+ doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, include/sudo_plugin.h,
+ plugins/sudoers/match.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.h, src/exec.c, src/exec_common.c,
+ src/selinux.c, src/sesh.c, src/sudo.c, src/sudo.h, src/sudo_exec.h:
+ Add support for using fexecve() if supported on commands that are
+ checksummed.
+ [397722cdd7ec]
+
+2015-12-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo_edit.c:
+ Call openat() with the basename not the full path. From Ben
+ Hutchings.
+ [33272418bb10]
+
+2015-12-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/group_plugin.c, plugins/sudoers/policy.c:
+ Fix compilation with --disable-shared
+ [84c084618676]
+
+2015-12-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_common.c:
+ Check for existing dso in LD_PRELOAD and only add it if it is not
+ already present.
+ [15042e8999f7]
+
+2015-12-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Clarify when SIGINT and SIGQUIT are relayed by sudo to the command.
+ [8efed5784393]
+
+ * plugins/sudoers/group_plugin.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.h, src/load_plugins.c:
+ Actually use the plugin_dir Path setting in sudo.conf.
+ [bccc548127a2]
+
+ * lib/util/sudo_conf.c:
+ The Path setting for the plugin directory is "plugin_dir" not
+ "plugin".
+ [07c2677bbce5]
+
+ * doc/sudo.conf.cat, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in,
+ lib/util/sudo_conf.c, src/exec_common.c:
+ Allow sudo.conf Path settings to disable path names (by setting the
+ value of NULL).
+ [81a44e011a40]
+
+2015-12-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/selinux.c, src/sudo.h:
+ Change noexec flag in selinux_execve() from int to bool.
+ [7cb872aac155]
+
+ * src/exec_common.c, src/sudo_exec.h:
+ Refactor code to set LD_PRELOAD (or the equivalent) in the
+ environment into a preload_dso() function. Also avoid allocating a
+ new copy of the environment array if the size of the array does not
+ change.
+ [72194b0b51f7]
+
+ * configure, configure.ac:
+ Add missing square brackets in configure option descriptions.
+ [6e25685c6349]
+
+2015-12-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document the names of the I/O log files and mention buffering.
+ Document that I/O logs are in gzip format by default.
+ [474838e7b365]
+
+2015-12-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/env.c:
+ Add BASHOPTS to initial_badenv_table[]; from Stephane Chazelas
+ [f206a9089a69]
+
+2015-12-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ When parsing sudoOptions that include an operator (!, +, +=, -=)
+ strip out any whitespace on either side of the operator.
+ [62041b5888e5]
+
+2015-12-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers2ldif:
+ Strip whitespace around '!', '=', '+=' and '-=' in Defaults entries.
+ [dcc9d15b0f3c]
+
+2015-12-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document the race condition between the digest check and command
+ execution.
+ [24a3d9215c64]
+
+2015-12-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ When checking the query results, don't set user_matches in the
+ netgroup pass unless sudo_ldap_check_non_unix_group() returns true.
+ This was preventing the mail_no_user sudoOption from being
+ effective.
+ [31004144421b]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ In list mode, we always want to clear FLAG_NO_USER and FLAG_NO_HOST
+ regardless of whether or not there was an actual match. Otherwise,
+ warning mail may be sent which is not what we want in list mode.
+ This is consistent with what the sudoers file backend does.
+ [2809338a7b21]
+
+2015-11-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/toke.h, plugins/sudoers/toke_util.c:
+ Use size_t for length parameters in the fill functions used by the
+ lexer.
+ [0428c9067182]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Use yy_size_t for digest_len since newer flex uses yy_size_t for
+ yyleng. Old flex uses int for yyleng so we need to use a cast to
+ avoid a sign compare warning.
+ [4a3dc6fb8f99]
+
+2015-11-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, README, configure, configure.ac,
+ plugins/sudoers/regress/sudoers/test1.in, sudo.pp:
+ Use https in sudo.ws urls
+ [04e5177022d3]
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.cat, doc/sudoers.ldap.cat,
+ doc/sudoers.ldap.man.in, doc/sudoers.ldap.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, doc/sudoreplay.cat,
+ doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in, doc/visudo.cat,
+ doc/visudo.man.in, doc/visudo.mdoc.in:
+ Use https in urls.
+ [855b05943b2d]
+
+ * configure, configure.ac:
+ sudo 1.8.16
+ [b745f7031aeb]
+
+ * plugins/sudoers/env.c:
+ When preserving variables from the invoking user's environment, if
+ there are duplicates only keep the first instance.
+ [d4dfb05db5d7]
+
+2015-11-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/sudo_debug.h, lib/util/parseln.c, lib/util/sudo_debug.c,
+ plugins/sudoers/timestamp.c:
+ Add debug_return_ssize_t
+ [d491ed281726]
+
+ * plugins/sudoers/timestamp.c:
+ Avoid compilation error on Solaris 10 with Stun Studio 12. Bug #727
+ [facd8ff1ee6c]
+
+2015-10-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po, po/da.mo,
+ po/da.po:
+ sync with translationproject.org
+ [6711d740d3d0]
+
+ * NEWS:
+ Mention ssp configure fix.
+ [92d64fd724cc]
+
+2015-10-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po,
+ plugins/sudoers/po/nl.mo, plugins/sudoers/po/nl.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po, po/cs.mo,
+ po/cs.po, po/de.mo, po/de.po, po/fr.mo, po/fr.po, po/it.mo,
+ po/it.po, po/ja.mo, po/ja.po, po/nb.mo, po/nb.po, po/pl.mo,
+ po/pl.po, po/pt_BR.mo, po/pt_BR.po, po/uk.mo, po/uk.po, po/vi.mo,
+ po/vi.po, po/zh_CN.mo, po/zh_CN.po:
+ sync with translationproject.org
+ [9c8eb0062d8c]
+
+ * configure, configure.ac:
+ Don't use CPPFLAGS for the -fstack-protector check. Otherwise on
+ systems with _FORTIFY_SOURCE support we'll get an error due to the
+ lack of optimization flags. Bug #725
+ [1a9f8571a82d]
+
+ * configure, configure.ac:
+ When checking for stack protector support we need to actually link
+ the test program.
+ [ab4f94aac7de]
+
+2015-10-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ Preserve LDFLAGS when checking for stack protector as they may
+ include rpath settings to allow the stack protector lib to be found.
+ Avoid using existing CFLAGS since we don't want the compiler to
+ optimize away the stack variable.
+ [e6bc59225c06]
+
+ * configure, configure.ac:
+ Better configure test for -fstack-protector. Some gcc installations
+ may be missing the ssp library even though the compiler supports it.
+ [4ade5d1249f4]
+
+2015-10-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo_edit.c:
+ Set errno to EISDIR instead of ENOTDIR if directory is writable
+ since ENOTDIR can be a legitimate errno. This avoids a bogus
+ "directory is writable" error in that case.
+ [97ee37d905ce]
+
+ * mkpkg:
+ Fix the check for whether to include 32-bit arch in Mac OS X
+ packages.
+ [a76654512f6b]
+
+2015-10-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [58277a8f418b]
+
+ * NEWS, src/sudo_edit.c:
+ When creating a new file, sudoedit will now check that the file's
+ parent directory exists before running the editor.
+ [65bc45510fb2]
+
+ * NEWS, doc/UPGRADE, doc/sudoers.cat, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/match.c:
+ Add always_query_group_plugin
+ [7e9060d4c13a]
+
+2015-10-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ABOUT-NLS, MANIFEST:
+ Add ABOUT-NLS from GNU gettext.
+ [971c168c065a]
+
+ * NEWS, config.h.in, configure, configure.ac, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/policy.c, plugins/sudoers/sudoers_version.h,
+ src/sudo.c, src/sudo.h, src/sudo_edit.c:
+ Add directory writability checks for sudoedit.
+ [f5349d059a98]
+
+2015-10-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Latest.
+ [9aae49302c60]
+
+ * src/conversation.c:
+ Ignore the SUDO_CONV_PROMPT_ECHO_OK flag when echo is enabled. This
+ was preventing a match of SUDO_CONV_PROMPT_ECHO_ON which resulted in
+ a masked password instead of an echoed one.
+ [53f6a78d79e3]
+
+ * plugins/sudoers/auth/bsdauth.c:
+ Repair challenge/response prompting for BSD authentication which got
+ broken while it was converted to use the conversation function.
+ [2d0b0cec5e4f]
+
+ * plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h:
+ Use the auth_getpass (and the plugin conversation fuction) for Tru64
+ SIA. This prevents sudo from sleeping while holding the tty ticket
+ lock.
+ [9221eec812cf]
+
+ * NEWS, doc/UPGRADE, plugins/sudoers/env.c:
+ For env_reset, SHELL should be set based on the target user, not the
+ invoking user unless preserved via env_keep.
+ [b77adbc08c91]
+
+ * plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po:
+ sync with translationproject.org
+ [adb927ad5e86]
+
+2015-10-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Hungarian and Slovak translations
+ [d3b6acece125]
+
+ * MANIFEST, doc/CONTRIBUTORS, plugins/sudoers/po/hu.mo,
+ plugins/sudoers/po/hu.po, plugins/sudoers/po/sk.mo,
+ plugins/sudoers/po/sk.po, po/sk.mo, po/sk.po:
+ Add new Slovak and Hungarian translations from
+ translationproject.org
+ [132ec9b7a927]
+
+2015-10-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo_edit.c:
+ Remove S_ISREG check from sudo_edit_open(), it is already done in
+ the caller.
+ [9fff8c0bb1f7]
+
+ * src/sudo_edit.c:
+ Open sudoedit files with O_NONBLOCK and fail if they are not regular
+ files.
+ [56b01164869c]
+
+ * plugins/sudoers/logging.c, plugins/sudoers/visudo.c, src/tgetpass.c:
+ It is possible for WIFSTOPPED to be true even if waitpid() is not
+ given WUNTRACED if the child is ptraced. Don't exit the waitpid()
+ loop if WIFSTOPPED is true, just in case.
+ [a2cab04a03da]
+
+2015-09-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/de.mo,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/it.mo,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/nb.mo,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pt_BR.mo,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/vi.mo,
+ plugins/sudoers/po/zh_CN.mo, po/cs.mo, po/de.mo, po/fi.mo, po/fr.mo,
+ po/gl.mo, po/it.mo, po/ja.mo, po/nb.mo, po/pl.mo, po/pt_BR.mo,
+ po/uk.mo, po/vi.mo, po/zh_CN.mo:
+ rebuild .mo files
+ [676362ed6061]
+
+ * plugins/sudoers/po/pt_BR.po, po/pt_BR.po:
+ sync with translationproject.org
+ [be932694e600]
+
+2015-09-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.ac, src/sudo_noexec.c:
+ There's no point in trying to interpose protected versions of the
+ exec family of functions. Many modern C libraries use hidden symbols
+ for the functions and syscalls defined in libc such that they cannot
+ be overridden inside libc itself. We have to just wrap all the exec
+ variants plus system and popen.
+ [30aa4bd6c15b]
+
+ * doc/sudo.conf.cat, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in:
+ List all the functions wrapped by sudo_noexec.so.
+ [57a9db56f4e0]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ The section is now called "EXEC and NOEXEC" and it is above, not
+ below.
+ [9b0a2537f65d]
+
+ * src/sudo_noexec.c:
+ Also wrap popen(3).
+ [a826cd7787e9]
+
+ * src/sudo_noexec.c:
+ Also interpose system(3). On glibc systems you cannot interpose the
+ syscalls used internally by libc.
+ [58a5c06b5257]
+
+ * src/conversation.c:
+ Set active debug instance to sudo_debug_instance() during the
+ conversation function.
+ [22fb750d92a9]
+
+2015-09-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ LOGNAME and USERNAME are set the same way as USER
+ [54f170cf2536]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Document behavior when the command dies from a signal in EXIT
+ STATUS.
+ [3c93d682e5e6]
+
+2015-09-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Bug #722
+ [5cca49bb0e02]
+
+ * src/sudo.c:
+ When the command sudo is running is killed by a signal, sudo will
+ now send itself the same signal with the default signal handler
+ instead of exiting. The bash shell appears to ignore some signals,
+ e.g. SIGINT, unless the command is killed by that signal. This makes
+ the behavior of commands run under sudo the same as without sudo
+ when bash is the shell. Bug #722
+ [153f016db8f1]
+
+2015-09-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Adjust set_logname description to new behavior when any of LOGNAME,
+ USER or USERNAME are preserved.
+ [89009c2dcf38]
+
+ * NEWS, plugins/sudoers/env.c:
+ If some, but not all, of the LOGNAME, USER or USERNAME environment
+ variables have been preserved from the invoking user's environment,
+ sudo will now use the preserved value to set the remaining variables
+ instead of using the runas user. This ensures that if, for example,
+ only LOGNAME is present in the env_keep list, that sudo will not set
+ USER and USERNAME to the runas user.
+ [54a60fe72b9a]
+
+2015-09-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/pam.c:
+ Fix passing of the callback pointer to the conversation function.
+ This was preventing the on_suspend and on_resume functions from
+ being called on PAM systems.
+ [611246ded4ff]
+
+ * include/sudo_plugin.h:
+ Explicitly mark large hex constants unsigned.
+ [5b67b0090814]
+
+ * plugins/sudoers/timestamp.c:
+ Cast sizeof(entry) to off_t before making it a negative offset for
+ lseek(). Fixes "sudo -k" on Solaris and probably others.
+ [ed5d312f6baa]
+
+2015-09-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Add explicit mention of sudo's netgroup semantics since they differ
+ from most other netgroup consumers.
+ [0e9030f8cf56]
+
+ * plugins/sudoers/po/fi.po, po/fi.po:
+ sync with translationproject.org
+ [f9236f25a616]
+
+ * plugins/sudoers/check.c:
+ Fix potential double free of the cookie when sudo is suspended at
+ the password prompt.
+ [cbecb3136155]
+
+2015-09-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/cs.po, plugins/sudoers/po/zh_CN.po, po/cs.po,
+ po/zh_CN.po:
+ sync with translationproject.org
+ [21138f16a3a6]
+
+2015-09-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/de.po, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/ja.po, plugins/sudoers/po/nb.po,
+ plugins/sudoers/po/pl.po, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.po, po/de.po, po/fr.po, po/gl.po, po/it.po,
+ po/ja.po, po/nb.po, po/pl.po, po/uk.po, po/vi.po:
+ sync with translationproject.org
+ [2d9f3e4c3ccf]
+
+ * NEWS:
+ Bug #719
+ [cfa393164a0f]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ SIGHUP is now relayed to the command. Bug #719
+ [8db7c492c52a]
+
+ * src/exec.c:
+ When a terminal device is closed, SIGHUP is sent to the controlling
+ process associated with that terminal. It is not sent to the entire
+ process group so sudo needs to relay SIGHUP to the command when it
+ is not being run in a new pty. Bug #719
+ [b408a792f31a]
+
+ * NEWS:
+ Mention visudo bug in 1.8.14
+ [0fec829807fd]
+
+ * plugins/sudoers/visudo.c:
+ We reserved two slots at the end of the editor argv for the line
+ number and the file name. However, resolve_editor() adds "--" before
+ the file names so the +line_number is interpreted as a file name,
+ not a line number so we need to overwrite the "--" as well.
+ [ff107430ee4b]
+
+2015-09-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.ac, lib/util/sig2str.c,
+ lib/util/strsignal.c:
+ Remove checks for __sys_siglist and __sys_signame. They are internal
+ to libc and there are no known systems that export those symbols
+ that do not already export the single underbar or no- underbar
+ versions.
+ [2b3efe0a91f2]
+
+ * plugins/sudoers/po/ru.mo, plugins/sudoers/po/ru.po, po/es.mo,
+ po/es.po:
+ Sync with translationproject.org
+ [feb5eb934a9e]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [947e8320c557]
+
+2015-09-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/tgetpass.c:
+ Restore old signal handlers before tty settings. That way SIGTTOU is
+ at its original value if sudo_term_restore() should fail.
+ [69d2cc6c0702]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in:
+ Document what happens when the on_suspend/on_resume callbacks return
+ an error.
+ [d8c9dcf7a926]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, include/sudo_plugin.h,
+ plugins/group_file/group_file.c, plugins/group_file/plugin_test.c,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/policy.c,
+ plugins/system_group/system_group.c, src/hooks.c:
+ No need to have version macros for hooks, callbacks and the sudoers
+ group plugin. We can just use the main sudo API macros. The sudoers
+ group plugin macros are preserved for source compatibility but are
+ not documented.
+ [8c52bb83f991]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Properly escape the backslash before a comma in an example so the
+ example rule is parsable by visudo.
+ [6745d38e9876]
+
+ * src/tgetpass.c:
+ Ignore callbacks if major version doesn't match.
+ [f852e6ebff01]
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/compat/timespec.h, lib/util/Makefile.in, lib/util/gettime.c,
+ lib/util/utimens.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/visudo.c, src/Makefile.in, src/sudo_edit.c:
+ Remove include/compat/timespec.h. Systems old enough to lack struct
+ timespec are too old to build a modern sudo.
+ [37812e10a449]
+
+ * NEWS:
+ Bug #713
+ [8a7245d76799]
+
+ * src/exec.c:
+ Fill in cstat if exec_setup() fails. Previously it was only filled
+ in for an execve() failure. Fixes an unkillable sudo process when
+ exec_setup() fails and I/O logging is enabled.
+ [ff1d39d9e505]
+
+ * src/sudo.c:
+ Fix running commands as non-root when neither setresuid() not
+ setreuid() are available. At this point we are already root so
+ setuid() must succeed. Bug #713
+ [34754ad586c7]
+
+ * src/sudo.c:
+ Cast uid_t to unsigned int when printing as %u
+ [669e2d5244a6]
+
+ * doc/UPGRADE:
+ Mention time stamp file locking changes, fix some spelling.
+ [c4563ea85e3a]
+
+ * NEWS:
+ Update with latest changes.
+ [2cbd50e7c158]
+
+2015-09-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, include/sudo_fatal.h,
+ include/sudo_plugin.h, lib/util/fatal.c, plugins/sudoers/auth/afs.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h, plugins/sudoers/check.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoers.h,
+ src/conversation.c, src/sudo.c, src/sudo.h, src/sudo_plugin_int.h,
+ src/tgetpass.c:
+ Add a struct sudo_conv_callback that contains on_suspend and
+ on_resume function pointer args plus a closure pointer and at it to
+ the conversation function.
+ [5608cb4c18f2]
+
+ * config.h.in, configure, configure.ac, include/sudo_util.h,
+ lib/util/locking.c, lib/util/util.exp.in, plugins/sudoers/check.c,
+ plugins/sudoers/check.h, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/timestamp.c:
+ Lock individual records in the timestamp file instead of the entire
+ file. This will make it possible for multiple sudo processes using
+ the same tty to serialize their timestamp lookups.
+ [f4ad82e36d90]
+
+ * lib/util/term.c, plugins/sudoers/check.c,
+ plugins/sudoers/sudoreplay.c, src/tgetpass.c:
+ Implement suspend/resume callbacks for the conversation function. If
+ suspended, close the timestamp file (dropping all locks). On resume,
+ lock the record before reading the password.
+
+ For this to work properly we need to be able to run th callback when
+ tsetattr() suspends us, not just when the user does. To accomplish
+ this the term_* functions now return EINTR if SIGTTOU would be
+ generated. The caller now has to restart the term_* function (and
+ send itself SIGTTOU) instead of it being done automatically.
+ [572374035897]
+
+ * plugins/sudoers/timestamp.c:
+ Allow the time stamp lock to be interrupted by signals.
+ [aa5017f86210]
+
+ * plugins/sudoers/timestamp.c:
+ Adjust new locking to work when tty_tickets is disabled. We need to
+ use per-tty/ppid locking to gain exclusive access to the tty for the
+ password prompt but use a separate (short term) lock that is shared
+ among all sudo processes for the user.
+ [d6d7a0bb6bd0]
+
+ * lib/util/locking.c:
+ Set errno to EINVAL if sudo_lock_* is called with a bad type.
+ [cfba014f1c1a]
+
+ * src/exec_pty.c:
+ sudo_term_* already restart themselve for all but SIGTTOU so we
+ don't need to use our own restart loops.
+ [113924cd05c0]
+
+ * config.h.in, configure, configure.ac, plugins/sudoers/iolog.c,
+ plugins/sudoers/timestamp.c:
+ Use pread(2) and pwrite(2) where possible.
+ [86cd3f6bab9e]
+
+ * plugins/sudoers/timestamp.c:
+ Bring back the check for time stamp files that predate the boot
+ time. Instead of truncating we now unlink the file since another
+ process may be sleeping on the lock.
+ [9cdf7468d0f2]
+
+ * plugins/sudoers/check.c:
+ Avoid touching the time stamp directory for "sudo -k command"
+ [391d20c17775]
+
+2015-09-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, include/sudo_plugin.h:
+ Make hook_version and hook_type unsigned.
+ [77cb84793f07]
+
+2015-09-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/base64.c, plugins/sudoers/match.c,
+ plugins/sudoers/regress/parser/check_base64.c:
+ When decoding base64, avoid using '=' in the decoded temporary array
+ as a sentinel as it can legitimately be present. Instead, just use
+ the count of bytes stored in the temp array to determine which bytes
+ to fold into the destination.
+ [6abef15d3954]
+
+2015-08-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, plugins/sudoers/sudoers.c, plugins/sudoers/visudo.c:
+ When parsing def_editor, break out of the loop when we find the
+ first valid editor. Bug #714
+ [c7508ed075c2]
+
+2015-08-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo.c:
+ The condition for adding a missing newline at the end of sudoers was
+ never reached. Keep track of the last character and write a newline
+ character if when copying to the temp file. Found by Radovan Sroka.
+ [86c20e7fc6bd]
+
+ * plugins/sudoers/sudoers.c, plugins/sudoers/visudo.c:
+ Remove extraneous while() from botched do {} while() loop conversion
+ to use sudo_strsplit. Noticed by Radovan Sroka.
+ [cd2d25510129]
+
+2015-08-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/pam.c, plugins/sudoers/auth/sudo_auth.c:
+ In sudo_pam_begin_session() and sudo_pam_end_session() return
+ AUTH_FATAL on error, not AUTH_FAILURE. In sudo_auth_begin_session()
+ treat anything other than AUTH_SUCCESS as a fatal error.
+ [3ad7296390f2]
+
+ * doc/CONTRIBUTORS, src/exec.c, src/exec_pty.c:
+ Linux sets si_pid in struct siginfo to 0 when the process that sent
+ the signal is in a different container since the PID namespaces in
+ different conatiners are separate. Avoid looking up the process
+ group by id when si_pid is 0 since getpgid(0) returns the process
+ group of the current process. Since sudo ignores signals sent by
+ processes in its own process group, this had the effect of ignoring
+ signals sent from other containers. From Maarten de Vries
+ [6d3f43b95a1f]
+
+ * plugins/sudoers/auth/pam.c:
+ Sprinkle some debugging.
+ [f5a94a3a1192]
+
+2015-08-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.man.in, doc/sudo.mdoc.in:
+ Document that sudo uses the real uid to map from uid to passwd file
+ user name.
+ [04f6709675cc]
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in, doc/sudo.man.in, doc/sudo.mdoc.in:
+ disable_coredump can be set to no on modern OSes without security
+ consequences.
+ [ebe6d5bb2274]
+
+2015-08-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Emphasis on the never.
+ [39ca000281c7]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Explicitly tell people not to grant sudoedit to directories the user
+ can write to. While sudoedit will no longer open symbolic links,
+ hard links are still an issue.
+ [26e0afae9bae]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Add warning about writable directories and sudo/sudoedit.
+ [701ff725af42]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Emphasize that wildcards are not regexps. Bug #692
+ [1e071810c4cb]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Emphasize that wildcards in command line arguments are dangerous.
+ Document the failings of the passwd example on GNU systems. Bug #691
+ [54d793aea6b2]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Escape the colons in [[:alpha:]] as required by sudoers.
+ [ad875dd5ca64]
+
+ * po/sudo.pot, src/sudo_edit.c:
+ Change warning when user tries to sudoedit a symbolic link.
+ [b8f44e834c2f]
+
+2015-08-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST:
+ add .json regress files to MANIFEST
+ [03ddb3a9671b]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [5abaa0eeab86]
+
+ * doc/sudo.conf.cat, doc/sudoers.ldap.cat, doc/sudoreplay.cat,
+ doc/visudo.cat:
+ regen
+ [43e6b445734c]
+
+ * doc/UPGRADE, doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.cat, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in, include/sudo_compat.h, include/sudo_plugin.h,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.h, plugins/sudoers/gram.y,
+ plugins/sudoers/ldap.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/sudoers/test1.in,
+ plugins/sudoers/regress/sudoers/test1.json.ok,
+ plugins/sudoers/regress/sudoers/test1.out.ok,
+ plugins/sudoers/regress/sudoers/test1.toke.ok,
+ plugins/sudoers/sudoers_version.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/visudo_json.c, src/sesh.c, src/sudo.c, src/sudo.h,
+ src/sudo_edit.c:
+ Do not follow symbolic links in sudoedit by default. This behavior
+ can be controlled by the sudoedit_follow Defaults flag as well as
+ the FOLLOW/NOFOLLOW tags.
+ [9636fd256325]
+
+ * NEWS, aclocal.m4, configure, configure.ac:
+ Sudo 1.8.15
+ [bf18da363b06]
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/sudoers/test1.json.ok,
+ plugins/sudoers/regress/sudoers/test10.json.ok,
+ plugins/sudoers/regress/sudoers/test11.json.ok,
+ plugins/sudoers/regress/sudoers/test12.json.ok,
+ plugins/sudoers/regress/sudoers/test13.json.ok,
+ plugins/sudoers/regress/sudoers/test14.json.ok,
+ plugins/sudoers/regress/sudoers/test15.json.ok,
+ plugins/sudoers/regress/sudoers/test16.json.ok,
+ plugins/sudoers/regress/sudoers/test2.json.ok,
+ plugins/sudoers/regress/sudoers/test3.json.ok,
+ plugins/sudoers/regress/sudoers/test4.json.ok,
+ plugins/sudoers/regress/sudoers/test5.json.ok,
+ plugins/sudoers/regress/sudoers/test6.json.ok,
+ plugins/sudoers/regress/sudoers/test7.json.ok,
+ plugins/sudoers/regress/sudoers/test8.json.ok,
+ plugins/sudoers/regress/sudoers/test9.json.ok:
+ Check JSON output of sudoers test files too.
+ [3d8517812b80]
+
+2015-08-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ Move comment to match moved code.
+ [7a30f06462a8]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ maxseq is an int not a string
+ [bffd97d22064]
+
+2015-08-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/preserve_fds.c:
+ Include sys/types.h for id_t. Bug #711
+ [fda95d9ca1e9]
+
+2015-07-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/fnmatch.c:
+ Avoid a potential out of bounds read found by enh while fuzzing with
+ address sanitizer enabled.
+ [52d6b9916593]
+
+2015-07-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg:
+ Set sssd lib location to /usr/lib64 on 64-bit RHEL/Centos. Bug #710
+ [428421925a20]
+
+2015-07-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS, src/Makefile.in:
+ The init.d files are generated from a .in file so we need to install
+ from top_builddir not top_srcdir. From Ross Burton. Bug #708
+ [df1e7a0d3182]
+
+2015-07-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/term.c:
+ Replace two "return 0" with debug_return_bool(false).
+ [49f8fb3dcd36]
+
+ * src/ttyname.c:
+ fix typo in previous commit
+ [094488696f2c]
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.8.14p3
+ [0079c43d8247]
+
+2015-07-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/ttyname.c:
+ Fix errno value from get_process_ttyname() when no tty is present.
+ [ff7b12bb0638]
+
+ * src/ttyname.c:
+ On AIX, only convert the tty device number from dev64_t to dev32_t
+ if dev_t is 32-bits.
+ [0e728a1eb07a]
+
+2015-07-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.8.14p2
+ [55fe56b28c7b]
+
+ * plugins/sudoers/timestamp.c:
+ Fix creation of the timestamp file; bug #704
+ [1ff77fd5cc8f]
+
+2015-07-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/regress/ttyname/check_ttyname.c, src/sudo.c, src/sudo.h,
+ src/ttyname.c:
+ Avoid needless memory allocation when resolving the tty name.
+ [c58cce92d5e0]
+
+2015-07-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.8.14p1
+ [973705806759]
+
+ * plugins/sudoers/sssd.c:
+ Fix typo in sudo_sss_attrcpy() that caused a memory allocation
+ error.
+ [0fa324a7bb56]
+
+2015-07-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/ja.mo, plugins/sudoers/po/uk.mo,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/zh_CN.mo:
+ rebuild
+ [e4c7cda46475]
+
+2015-07-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/lbuf.c, plugins/sudoers/env.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/interfaces.c,
+ plugins/sudoers/match.c, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/redblack.c, src/hooks.c, src/net_ifs.c, src/sudo.c:
+ Add some debugging printfs when malloc fails and we don't have an
+ explicit call to sudo_warnx().
+ [07aebb5839c3]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c:
+ Add missing warnings for memory allocation failure. Add function
+ name to memory allocation warnings.
+ [4f6027786a28]
+
+ * lib/util/parseln.c:
+ Return -1 if realloc() fails.
+ [707632291eac]
+
+ * lib/util/event.c, lib/util/event_poll.c, lib/util/event_select.c:
+ Add line number to debug log for memory allocation errors.
+ [f4f3debdfcc5]
+
+ * plugins/sudoers/auth/pam.c:
+ Add warning if calloc() fails. Add debugging for other unexpected
+ errors.
+ [a1e0945237d8]
+
+ * plugins/sudoers/ldap.c:
+ Add missing check for calloc(3) return value.
+ [37fe3ca78e8e]
+
+2015-07-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document that the values printed by "sudo -V" are affected by
+ Defaults settings in sudoers.
+ [80ec2572861b]
+
+2015-07-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/group_plugin.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/sssd.c, src/load_plugins.c:
+ Avoid calling dlerror() multiple times since it clear the error
+ status after printing the error. Problem caused by
+ sudo_warn/sudo_fatal being macros...
+ [c0fd3b0fb9c3]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Attempt to clarify the conditions under which MAIL and HOME are set
+ to the target user.
+ [ebd269bebe64]
+
+2015-07-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg:
+ Better checks for the libaudit package for Debian and error out if
+ we can't figure it out.
+ [225c1bfcb629]
+
+ * mkpkg:
+ Fix linux_audit setting on non-multiarch Debian.
+ [0a38e9d158f4]
+
+ * sudo.pp:
+ Fix typo that broke the linux_audit dependency on Debian.
+ [0917bd45acf1]
+
+ * NEWS:
+ Mention /proc/stat btime fix.
+ [754050a340e2]
+
+ * config.h.in, configure, configure.ac, lib/util/getaddrinfo.c,
+ plugins/sudoers/interfaces.c, plugins/sudoers/match_addr.c,
+ src/net_ifs.c:
+ Solaris 2.6 has the prototypes for inet_pton() and inet_ntop() in
+ resolv.h.
+ [dc0f62743845]
+
+ * plugins/sudoers/boottime.c:
+ Sprinkle debugging for boottime.
+ [dfb45c763179]
+
+ * mkpkg:
+ The old Solaris /bin/sh doesn't support POSIX $( .. ) syntax, use
+ backquotes instead.
+ [c9e33ffef2b1]
+
+2015-07-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg, sudo.pp:
+ Only use --with-sssd-lib on Debian/Ubuntu w/ multipackage. Use dpkg-
+ query to determine the name of the audit package for proper
+ dependencies.
+ [e9669389aa2f]
+
+ * mkpkg, plugins/sudoers/sudoers.in, sudo.pp:
+ Update Debian/Ubuntu packages to be more like the vendor ones. One
+ notable exception is that sudo.ws packages use /var/run, not
+ /var/lib for timestamp files.
+ [0f4c49a3768e]
+
+ * doc/CONTRIBUTORS:
+ Add Jakub Wilk
+ [78bfdf2e441b]
+
+ * plugins/sudoers/boottime.c:
+ Strip newline from /proc/stat btime line to avoid a strtonum()
+ failure. From Jakub Wilk.
+ [8a04f85a070f]
+
+ * src/exec_pty.c:
+ In io_callback() service writes before reads. That way, if both
+ SUDO_EV_READ and SUDO_EV_WRITE are set and read() returns 0 (EOF) we
+ don't close the fd before the write() is performed.
+
+ If the write() returns EPIPE, ENXIO, EIO or EBADF, clear
+ SUDO_EV_READ before we close the fd to avoid calling read() on a
+ closed fd.
+ [167548fd8af2]
+
+2015-07-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/regress/sudo_conf/conf_test.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c, src/sesh.c, src/sudo.c:
+ Check sudo_conf_read() return value and exit on fatal error (a
+ warning was already printed by sudo_conf_read()).
+ [d05797f4f197]
+
+ * NEWS:
+ Mention double-quoted sudoOption value support.
+ [55684a73f097]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Add support for parsing quoted strings in a sudoOption just like
+ sudoers Defaults settings.
+ [fe8291414179]
+
+ * plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po, po/da.mo,
+ po/da.po:
+ Sync with translationproject.org
+ [1c15d1a3dbdd]
+
+2015-07-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ Update year.
+ [6ca660e4a957]
+
+ * plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po, po/de.mo,
+ po/de.po, po/nb.mo, po/nb.po:
+ Sync with translationproject.org
+ [d7ede74dcb19]
+
+ * src/sudo.c:
+ Fix utmp setup broken by commit be0ca60facf8
+ [cd8a06f57f2b]
+
+2015-07-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/ja.po, plugins/sudoers/po/pl.mo,
+ plugins/sudoers/po/pl.po, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.po, plugins/sudoers/po/zh_CN.po, po/cs.mo,
+ po/cs.po, po/fr.mo, po/fr.po, po/it.mo, po/it.po, po/pl.mo,
+ po/pl.po:
+ Sync with translationproject.org
+ [aa473519e66d]
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [8f8aa321f043]
+
+ * plugins/sudoers/logging.c:
+ Fix typo in error message.
+ [220832711826]
+
+2015-07-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Bug #702 is the AIX timespec issue.
+ [c597a312e816]
+
+ * config.h.in, configure, configure.ac, lib/util/closefrom.c,
+ lib/util/getcwd.c, lib/util/glob.c, plugins/sudoers/match.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, src/ttyname.c:
+ We require POSIX so no need to conditionally include dirent.h. Add a
+ check for d_namlen and use the result in the NAMLEN macro.
+ [2728194cb6cf]
+
+ * lib/util/event.c, lib/util/event_poll.c, lib/util/event_select.c,
+ lib/util/getcwd.c, lib/util/gettime.c, lib/util/glob.c,
+ lib/util/lbuf.c, lib/util/locking.c, lib/util/mktemp.c,
+ lib/util/parseln.c, lib/util/secure_path.c, lib/util/setgroups.c,
+ lib/util/sudo_conf.c, lib/util/sudo_debug.c, lib/util/ttysize.c,
+ plugins/group_file/group_file.c, plugins/sample/sample_plugin.c,
+ plugins/sudoers/alias.c, plugins/sudoers/auth/afs.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/check.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/editor.c, plugins/sudoers/env.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/getspwuid.c,
+ plugins/sudoers/goodpath.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/interfaces.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/logging.c,
+ plugins/sudoers/match.c, plugins/sudoers/match_addr.c,
+ plugins/sudoers/parse.c, plugins/sudoers/policy.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers_debug.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/visudo.c,
+ plugins/sudoers/visudo_json.c, plugins/system_group/system_group.c,
+ src/conversation.c, src/exec.c, src/exec_common.c, src/exec_pty.c,
+ src/get_pty.c, src/hooks.c, src/load_plugins.c, src/net_ifs.c,
+ src/openbsd.c, src/parse_args.c, src/preserve_fds.c, src/signal.c,
+ src/solaris.c, src/sudo.c, src/sudo_edit.c, src/sudo_noexec.c,
+ src/tgetpass.c, src/ttyname.c, src/utmp.c:
+ There's no need to conditionalize the #include <unistd.h>, we
+ require a POSIX system.
+ [79389c527c08]
+
+ * include/sudo_compat.h:
+ Remove some compatibilty defines that should no longer be needed.
+ [e9136646d1c6]
+
+2015-06-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Final changes in 1.8.14
+ [3a5cd4f2875a]
+
+ * include/sudo_compat.h:
+ Need to include stddef.h to get rsize_t on Mac OS X for
+ sudo_memset_s() prototype.
+ [9615efed4a9a]
+
+ * lib/util/regress/parse_gids/parse_gids_test.c,
+ lib/util/regress/strsplit/strsplit_test.c:
+ Add missing exit value.
+ [484202b53893]
+
+ * lib/util/regress/mktemp/mktemp_test.c:
+ Add missing fcntl.h include.
+ [020fe6252d96]
+
+ * configure, configure.ac:
+ Do check for inet_pton before inet_ntop since we may need to record
+ dependent libraries for inet_pton when linking our getaddrinfo
+ replacement.
+ [fde03eefd88d]
+
+ * include/sudo_debug.h, lib/util/sudo_debug.c:
+ Fix build on compilers w/o __func__ or __FUNCTION__
+ [196d75416cd5]
+
+ * lib/util/util.exp.in:
+ Remove sudo_evasprintf_v1, missed during alloc.c removal.
+ [7d0ac7e5909d]
+
+ * lib/util/snprintf.c:
+ Add missing fcntl.h include.
+ [23b886deb879]
+
+ * config.h.in, configure, configure.ac:
+ Add check for inline support.
+ [061dab0e411c]
+
+2015-06-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/LICENSE:
+ Add reallocarray.c license.
+ [b4b4d46309f3]
+
+2015-06-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS:
+ Fix entry for Joel Pelaez Jorge.
+ [386434049903]
+
+2015-06-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/sudo_lbuf.h, lib/util/lbuf.c, lib/util/util.exp.in,
+ plugins/sudoers/ldap.c, plugins/sudoers/parse.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudo_nss.c:
+ Add an error flag to the lbuf struct to simplify error checking.
+ Callers of the lbuf functions now check the error flag to tell if a
+ memory allocation error ocurred.
+ [bc44b0fbc03b]
+
+ * plugins/sudoers/parse.c, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudo_nss.h, plugins/sudoers/sudoers.h:
+ display_privs() and display_cmnd() may need to return -1 on error.
+ [b6d8826900bb]
+
+2015-06-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c, plugins/sudoers/check.h,
+ plugins/sudoers/ldap.c, plugins/sudoers/logging.c,
+ plugins/sudoers/parse.c, plugins/sudoers/policy.c,
+ plugins/sudoers/prompt.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/timestamp.c:
+ Check restore_perms() return value in all cases, pushing the return
+ value back up the call stack.
+ [c9beeed2b614]
+
+ * plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Return -1, not 0 from sudoers when there is an error (as opposed to
+ a policy denial).
+ [5d197fe29e0e]
+
+ * doc/CONTRIBUTORS:
+ Add Joel Pelaez Jorge
+ [55387b44d6e9]
+
+ * plugins/sudoers/auth/pam.c:
+ When checking whether the PAM prompt matches "Password:", also check
+ for the untranslated version. The PAM module might not be using the
+ localized string even though it exists. From Joel Pelaez Jorge.
+ Fixes Bug #701
+ [d87f6f2ccb42]
+
+2015-06-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Silence clang analyzer warning on glibc systems where the first
+ argument to qsort() is marked as non-NULL. Also change some counters
+ from into to unsigned int and two flags from int to bool.
+ [09e400445ca2]
+
+2015-06-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c:
+ Silence clang analyzer warning on glibc systems where the first
+ argument to qsort() is marked as non-NULL.
+ [34fa7256f1e2]
+
+ * include/sudo_compat.h, include/sudo_debug.h, include/sudo_util.h,
+ src/preserve_fds.c:
+ Use our own bitmap macros instead of borrowing the ones from select.
+ [51ef403511d9]
+
+ * lib/util/sudo_debug.c:
+ Must call round_nfds() with fd+1 since it takes a count not the fd
+ number. In other words, the lowest value is 1, not 0.
+ [cc175cba5371]
+
+ * src/ttyname.c:
+ Quiet clang analyzer false positive.
+ [9ebecd6b6b29]
+
+ * src/sesh.c:
+ Fix uninitialized variables warnings in error case when src file
+ cannot be opened. At least one of these is a false positive.
+ [98b417c1307a]
+
+2015-06-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/getline.c, plugins/sudoers/toke_util.c:
+ It's safe to rely on C89 semantics for realloc(NULL, size).
+ [b633582413ac]
+
+ * plugins/sudoers/env.c:
+ malloc() sets errno to ENOMEM on failure so we don't need to set it
+ explicitly.
+ [09cb5ceaaec3]
+
+ * include/sudo_compat.h:
+ No longer need __malloc_like
+ [a41b69f256f6]
+
+ * lib/util/util.exp.in:
+ Remove symbols from the now-removed alloc.c.
+ [da0753d85d20]
+
+ * include/sudo_compat.h, lib/util/aix.c, lib/util/closefrom.c,
+ lib/util/event.c, lib/util/event_poll.c, lib/util/event_select.c,
+ lib/util/getaddrinfo.c, lib/util/getcwd.c, lib/util/getgrouplist.c,
+ lib/util/gethostname.c, lib/util/getline.c, lib/util/getopt_long.c,
+ lib/util/gettime.c, lib/util/gidlist.c, lib/util/glob.c,
+ lib/util/key_val.c, lib/util/lbuf.c, lib/util/locking.c,
+ lib/util/mksiglist.c, lib/util/mksigname.c, lib/util/parseln.c,
+ lib/util/progname.c, lib/util/pw_dup.c, lib/util/reallocarray.c,
+ lib/util/regress/atofoo/atofoo_test.c,
+ lib/util/regress/parse_gids/parse_gids_test.c,
+ lib/util/regress/progname/progname_test.c,
+ lib/util/regress/strsplit/strsplit_test.c,
+ lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_parseln/parseln_test.c, lib/util/setgroups.c,
+ lib/util/sha2.c, lib/util/sig2str.c, lib/util/snprintf.c,
+ lib/util/strndup.c, lib/util/strsplit.c, lib/util/strtobool.c,
+ lib/util/strtoid.c, lib/util/strtomode.c, lib/util/strtonum.c,
+ lib/util/sudo_conf.c, lib/util/sudo_debug.c, lib/util/sudo_dso.c,
+ lib/util/term.c, lib/util/ttysize.c, plugins/group_file/getgrent.c,
+ plugins/group_file/group_file.c, plugins/group_file/plugin_test.c,
+ plugins/sample/sample_plugin.c, plugins/sudoers/alias.c,
+ plugins/sudoers/audit.c, plugins/sudoers/auth/afs.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/base64.c, plugins/sudoers/boottime.c,
+ plugins/sudoers/check.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/editor.c, plugins/sudoers/env.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/getdate.c,
+ plugins/sudoers/getdate.y, plugins/sudoers/getspwuid.c,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/interfaces.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_path.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/locale.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logwrap.c,
+ plugins/sudoers/match.c, plugins/sudoers/match_addr.c,
+ plugins/sudoers/parse.c, plugins/sudoers/policy.c,
+ plugins/sudoers/prompt.c, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/redblack.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/regress/parser/check_hexchar.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudo_printf.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers_debug.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timestamp.c, plugins/sudoers/timestr.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/tsgetgrpw.c,
+ plugins/sudoers/visudo.c, plugins/sudoers/visudo_json.c,
+ plugins/system_group/system_group.c, src/conversation.c,
+ src/env_hooks.c, src/exec.c, src/exec_common.c, src/exec_pty.c,
+ src/get_pty.c, src/hooks.c, src/load_plugins.c, src/net_ifs.c,
+ src/openbsd.c, src/parse_args.c, src/preserve_fds.c,
+ src/regress/ttyname/check_ttyname.c, src/selinux.c, src/signal.c,
+ src/solaris.c, src/sudo.c, src/sudo_edit.c, src/tgetpass.c,
+ src/ttyname.c, src/utmp.c:
+ Only include stddef.h where it is needed.
+ [ce597fb7ffb9]
+
+2015-06-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [cad83b927f4e]
+
+ * lib/util/sudo_conf.c, plugins/sudoers/locale.c:
+ Better handling of setlocale() returning NULL.
+ [7cd4fcdb528c]
+
+ * lib/util/aix.c, lib/util/gidlist.c, lib/util/sudo_conf.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/editor.c,
+ plugins/sudoers/env.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_path.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/linux_audit.c,
+ plugins/sudoers/logging.c, plugins/sudoers/match.c,
+ plugins/sudoers/parse.c, plugins/sudoers/policy.c,
+ plugins/sudoers/prompt.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers_debug.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c, src/conversation.c, src/exec.c,
+ src/exec_common.c, src/exec_pty.c, src/load_plugins.c,
+ src/parse_args.c, src/preserve_fds.c, src/selinux.c, src/sesh.c,
+ src/sudo.c, src/sudo_edit.c:
+ Add function name to "unable to allocate memory" warnings.
+ [98c07e26a13e]
+
+ * configure, configure.ac, include/sudo_compat.h, lib/util/aix.c,
+ lib/util/closefrom.c, lib/util/event.c, lib/util/event_poll.c,
+ lib/util/event_select.c, lib/util/getaddrinfo.c, lib/util/getcwd.c,
+ lib/util/getgrouplist.c, lib/util/gethostname.c, lib/util/getline.c,
+ lib/util/getopt_long.c, lib/util/gettime.c, lib/util/gidlist.c,
+ lib/util/glob.c, lib/util/key_val.c, lib/util/lbuf.c,
+ lib/util/locking.c, lib/util/mksiglist.c, lib/util/mksigname.c,
+ lib/util/parseln.c, lib/util/progname.c, lib/util/pw_dup.c,
+ lib/util/reallocarray.c, lib/util/regress/atofoo/atofoo_test.c,
+ lib/util/regress/parse_gids/parse_gids_test.c,
+ lib/util/regress/progname/progname_test.c,
+ lib/util/regress/strsplit/strsplit_test.c,
+ lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_parseln/parseln_test.c,
+ lib/util/regress/tailq/hltq_test.c, lib/util/setgroups.c,
+ lib/util/sha2.c, lib/util/sig2str.c, lib/util/snprintf.c,
+ lib/util/strndup.c, lib/util/strsplit.c, lib/util/strtobool.c,
+ lib/util/strtoid.c, lib/util/strtomode.c, lib/util/strtonum.c,
+ lib/util/sudo_conf.c, lib/util/sudo_debug.c, lib/util/sudo_dso.c,
+ lib/util/term.c, lib/util/ttysize.c, plugins/group_file/getgrent.c,
+ plugins/group_file/group_file.c, plugins/sample/sample_plugin.c,
+ plugins/sudoers/alias.c, plugins/sudoers/audit.c,
+ plugins/sudoers/auth/afs.c, plugins/sudoers/auth/aix_auth.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/dce.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/passwd.c,
+ plugins/sudoers/auth/rfc1938.c, plugins/sudoers/auth/secureware.c,
+ plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/base64.c,
+ plugins/sudoers/boottime.c, plugins/sudoers/check.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/editor.c,
+ plugins/sudoers/env.c, plugins/sudoers/find_path.c,
+ plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/getspwuid.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/interfaces.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_path.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/locale.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logwrap.c,
+ plugins/sudoers/match.c, plugins/sudoers/match_addr.c,
+ plugins/sudoers/parse.c, plugins/sudoers/policy.c,
+ plugins/sudoers/prompt.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/pwutil_impl.c, plugins/sudoers/redblack.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/regress/parser/check_hexchar.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudo_printf.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers_debug.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timestamp.c, plugins/sudoers/timestr.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/tsgetgrpw.c,
+ plugins/sudoers/visudo.c, plugins/sudoers/visudo_json.c,
+ plugins/system_group/system_group.c, src/conversation.c,
+ src/env_hooks.c, src/exec.c, src/exec_common.c, src/exec_pty.c,
+ src/get_pty.c, src/hooks.c, src/load_plugins.c, src/net_ifs.c,
+ src/openbsd.c, src/parse_args.c, src/preserve_fds.c,
+ src/regress/ttyname/check_ttyname.c, src/signal.c, src/solaris.c,
+ src/sudo.c, src/sudo_edit.c, src/tgetpass.c, src/ttyname.c,
+ src/utmp.c:
+ We require ANSI C so stop using the obsolete STDC_HEADERS.
+ [35a5a680e5fe]
+
+ * lib/util/getgrouplist.c, lib/util/regress/glob/globtest.c,
+ lib/util/sudo_debug.c, plugins/group_file/getgrent.c,
+ plugins/group_file/plugin_test.c, plugins/sample/sample_plugin.c,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/interfaces.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/logging.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/tsgetgrpw.c:
+ Use strtok_r() instead of strtok()
+ [6b8e3c253dcf]
+
+ * config.h.in, configure, configure.ac:
+ Add back _REENTRANT define on HP-UX to expose strtok_r on some
+ versions. We may need to define it on other systems too.
+ [12c36f12eed2]
+
+ * configure, configure.ac:
+ Fix check for strnlen() when cross-compiling.
+ [e501c508891a]
+
+ * plugins/sudoers/interfaces.c:
+ Use sudo_strsplit() in dump_interfaces.
+ [b76ee2f47f37]
+
+2015-06-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/inet_pton.c, lib/util/key_val.c, lib/util/lbuf.c,
+ lib/util/locking.c, lib/util/parseln.c,
+ lib/util/regress/parse_gids/parse_gids_test.c,
+ lib/util/regress/progname/progname_test.c,
+ lib/util/regress/strsplit/strsplit_test.c,
+ lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_parseln/parseln_test.c,
+ lib/util/regress/tailq/hltq_test.c, lib/util/sha2.c,
+ lib/util/snprintf.c, lib/util/strtobool.c, lib/util/term.c,
+ plugins/group_file/getgrent.c, plugins/group_file/group_file.c,
+ plugins/sample/sample_plugin.c, plugins/sudoers/boottime.c,
+ plugins/sudoers/editor.c, plugins/sudoers/getdate.c,
+ plugins/sudoers/getdate.y, plugins/sudoers/interfaces.c,
+ plugins/sudoers/iolog_path.c, plugins/sudoers/policy.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/parser/check_hexchar.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/system_group/system_group.c,
+ src/conversation.c, src/exec_pty.c, src/net_ifs.c, src/openbsd.c,
+ src/preserve_fds.c, src/regress/ttyname/check_ttyname.c,
+ src/solaris.c, src/sudo.c, src/tgetpass.c, src/ttyname.c,
+ src/utmp.c:
+ Remove obsolete memory.h include.
+ [0c1351d614a9]
+
+ * config.h.in, configure, configure.ac, lib/util/getcwd.c,
+ lib/util/gethostname.c, lib/util/glob.c, lib/util/locking.c,
+ lib/util/parseln.c, lib/util/pw_dup.c, lib/util/reallocarray.c,
+ lib/util/snprintf.c, lib/util/strndup.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/toke_util.c,
+ src/env_hooks.c:
+ Remove support for the obsolete malloc.h header.
+ [2a118de27d4e]
+
+ * config.h.in, configure, configure.ac, plugins/sudoers/defaults.c,
+ plugins/sudoers/logging.c:
+ Remove BROKEN_SYSLOG define which was for obsolete versions of HP-
+ UX. Remove last remnants of 4.2BSD syslog support.
+ [e234515f515d]
+
+ * lib/util/sudo_conf.c:
+ Use sudo_strsplit() instead of doing the equivalent manually.
+ [220f2e4a0e68]
+
+ * lib/util/regress/strsplit/strsplit_test.c:
+ Test strsplit behavior with an empty string.
+ [62ae80dcee4a]
+
+ * lib/util/Makefile.in, lib/zlib/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in,
+ src/Makefile.in:
+ Allow "make LIBTOOL=/path/to/libtool" to work properly.
+ [f9e5f7109107]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/editor.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/goodpath.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/visudo.c:
+ Use a common function for resolviong the user's editor in sudoedit
+ and visudo. The find_path() function now returns a dynamically
+ allocated path instead of using a static string.
+ [97fe58966144]
+
+ * config.h.in, configure, configure.ac, lib/util/Makefile.in,
+ lib/zlib/Makefile.in, plugins/group_file/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/Makefile.in:
+ Replace use of OSDEFS with config.h defines. Rename DEFS in
+ Makefile.in to CPPDEFS and include in CPPFLAGS. Bring back
+ _BSD_SOURCE as a config.h define. Remove obsolescent _REENTRANT
+ define.
+ [0d76a12adca8]
+
+2015-06-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, include/sudo_alloc.h, lib/util/Makefile.in,
+ lib/util/alloc.c:
+ Remove now-unused sudo_alloc.h and alloc.c
+ [0fe70085c75c]
+
+ * plugins/sudoers/Makefile.in, src/Makefile.in, src/conversation.c,
+ src/env_hooks.c, src/exec.c, src/exec_common.c, src/exec_pty.c,
+ src/hooks.c, src/load_plugins.c, src/net_ifs.c, src/parse_args.c,
+ src/preserve_fds.c, src/regress/ttyname/check_ttyname.c,
+ src/selinux.c, src/sesh.c, src/sudo.c, src/sudo.h, src/sudo_edit.c,
+ src/ttyname.c:
+ Avoid using exiting allocators in the front end.
+ [be0ca60facf8]
+
+ * include/sudo_conf.h, include/sudo_lbuf.h, lib/util/Makefile.in,
+ lib/util/aix.c, lib/util/gidlist.c, lib/util/lbuf.c,
+ lib/util/sudo_conf.c, lib/util/sudo_debug.c:
+ Use non-exiting allocators in libsudo_util.
+ [d9b7cf17b9b4]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/logging.c:
+ Remove asprintf() return value warnings.
+ [fe25ce11f96a]
+
+ * config.h.in, configure, configure.ac:
+ Use AC_FUNC_STRNLEN to check for broken strnlen() on AIX. This
+ requires that we use AC_USE_SYSTEM_EXTENSIONS so remove things from
+ OSDEFS that are enabled by AC_USE_SYSTEM_EXTENSIONS.
+ [1f64269cab6e]
+
+ * plugins/sudoers/ldap.c:
+ Remove extraneous semicolons in CHECK_* macros.
+ [ef99aa3c9d70]
+
+ * plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c:
+ Remove remaining SUDO_MAIN remnants.
+ [1c077699f444]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/alias.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/check.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/defaults.h, plugins/sudoers/env.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/getspwuid.c,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/interfaces.c,
+ plugins/sudoers/interfaces.h, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_path.c, plugins/sudoers/linux_audit.c,
+ plugins/sudoers/locale.c, plugins/sudoers/logging.h,
+ plugins/sudoers/match.c, plugins/sudoers/parse.c,
+ plugins/sudoers/policy.c, plugins/sudoers/prompt.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/sudoers_debug.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Use non-exiting allocatings in the sudoers plugin.
+ [a5668cb9c516]
+
+2015-06-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sssd.c:
+ Use non-exiting allocators in the sudoers SSSD backend.
+ [dba29b55ac0b]
+
+ * plugins/sudoers/ldap.c:
+ Use non-exiting allocators in the sudoers LDAP backend.
+ [37bfa441345a]
+
+ * lib/util/Makefile.in:
+ regen dependencies
+ [5be6eb005946]
+
+2015-06-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, lib/util/Makefile.in, mkdep.pl:
+ Add missing dependency info for reallocarray.lo in
+ lib/util/Makefile.in and regen configure to match last configure.ac
+ change.
+ [da1fc49b53dc]
+
+ * plugins/sudoers/ldap.c:
+ Use \28 and \29 instead of \( and \) in the ldap query as per RFC
+ 2254. Fixes netgroup queries on AIX. From Steven Soulen.
+ [33267d6243aa]
+
+2015-06-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/glob.c:
+ Move pattern length check until after we have initialized the glob_t
+ so we can call globfree() even on error. From Frank Denis.
+ [a246f9054395]
+
+2015-06-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c, src/sudo.c:
+ We need to unlimit RLIMIT_NPROC in sudoers as well as the sudo front
+ end since set_perms() and restore_perms change the read uid and may
+ fail with EAGAIN on Linux kernels prior to 3.1.
+ [e6a03c31f4e5]
+
+2015-06-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Fix underlining of "root" in -u option descriptions. Bug #699
+ [b3afe47d9798]
+
+ * doc/UPGRADE, src/load_plugins.c:
+ Remove support for converting plugin.so -> plugin.sl on HP-UX when
+ plugin.so can not be found. This was a temporary hack for using an
+ older (pre 1.8.7) sudoers plugin with a newer sudo front-end.
+ [561e2ce444ed]
+
+2015-06-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/event.c, lib/util/event_select.c:
+ Add debugging output on memory alloc failure. Add missing checks in
+ event_select.c for reallocarray() failure.
+ [0853c7bcbeaa]
+
+ * lib/util/event_poll.c:
+ Use non-exiting allocators.
+ [5ed0e276b551]
+
+2015-06-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/logging.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Bring back VALIDATE_ERROR which will be used in the case of memory
+ allocation errors.
+ [784c885db95c]
+
+2015-06-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/snprintf.c:
+ If asprintf() or vasprintf() fail, set the dest pointer to NULL like
+ BSD and Solaris do. This appears to be the direction glibc is going
+ as well.
+ [92fb2283dc9a]
+
+2015-05-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/env.c:
+ Use a stack buffer for the validate_env_vars() error message.
+ [69df3a0cbc2b]
+
+2015-05-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/fatal.c:
+ Fix typo/thinko in static buffer conversion; use vsnprintf() not
+ snprintf()
+ [9d42fb3a94f6]
+
+ * plugins/sudoers/ldap.c:
+ Fix old gcc2 variadic macro support.
+ [fd951ed8865e]
+
+ * plugins/sudoers/visudo.c:
+ Restore old behavior where visudo prevents you from making the main
+ sudoers file zero length.
+ [b03ef908120f]
+
+ * plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/sudoers.c:
+ Non-exiting allocators for log functions. If log_allowed() fails the
+ user may not run the command. We don't try to return early for
+ log_failure(), log_auth_failure() or log_denial() as we would not
+ run the command in that case.
+ [40c3d0dd75bc]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/toke_util.c:
+ Use non-exiting allocators in the parser (much of it already did).
+ [f14222e5ad1b]
+
+ * lib/util/aix.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/pwutil_impl.c:
+ Use non-existing allocators in the passwd/group cache functions.
+ [86bbe840f348]
+
+ * MANIFEST, configure.ac, lib/util/alloc.c, lib/util/reallocarray.c:
+ Add standalone reallocarray.c from OpenBSD instead of rolling our
+ own.
+ [36ec5840729e]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/iolog.c,
+ plugins/sudoers/parse.h, plugins/sudoers/pwutil.c,
+ plugins/sudoers/redblack.c, plugins/sudoers/redblack.h,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Use non-exiting allocators in the redblack tree and fix the fallout.
+ Also switch to non-exiting allocators in affected code blocks.
+ [bca56cf769cb]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/parse.h:
+ The error string returned by alias_add should be const.
+ [b378188a0a8f]
+
+ * plugins/sudoers/policy.c:
+ Fix typo, efree vs. free.
+ [9146ba7473ca]
+
+ * plugins/sudoers/policy.c, src/exec_common.c, src/sudo.c:
+ Add a few missing sudo_new_key_val() return value checks. Also use
+ non-exiting allocators for consistency.
+ [2ae76a679052]
+
+2015-05-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, lib/util/Makefile.in,
+ lib/util/regress/parse_gids/parse_gids_test.c,
+ lib/util/regress/strsplit/strsplit_test.c:
+ Add unit tests for strsplit and parse_gid_list.
+ [e08c5ff7b5f0]
+
+ * MANIFEST, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/strsplit.c, lib/util/util.exp.in,
+ plugins/sudoers/sudoers.c:
+ Add sudo_strsplit(), similar to strtok_r() but non-destructive and
+ operates on non-C strings (requires a length parameter).
+ [45fb50775249]
+
+ * lib/util/fatal.c:
+ Use a static buffer for sudo_warn/sudo_fatal messages where
+ possible.
+ [6e1d6ecc022d]
+
+ * include/sudo_compat.h:
+ Fix sudo_strnlen() prototype.
+ [1367bd9227b3]
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, lib/util/Makefile.in, lib/util/strndup.c,
+ mkdep.pl:
+ Add strndup() for those without it. As strndup.c uses strnlen(), use
+ our own if it is missing.
+ [cf904a9c68f7]
+
+ * lib/util/strnlen.c:
+ Add missing sudo_ prefix and include sudo_compat.h.
+ [d5e5dfc3fd20]
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, lib/util/strnlen.c:
+ Add strnlen() replacement needed for glob.c. Only used if no glob()
+ and no strnlen().
+ [bb6b7c4549b1]
+
+2015-05-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/logging.h, plugins/sudoers/sudoers.h:
+ Get rid of SUDO_MAIN. Modern compilers don't warn about mixing
+ extern and auto declarations unless they conflict.
+ [a273b73bca6d]
+
+ * config.h.in, configure.ac, include/compat/endian.h,
+ include/compat/fnmatch.h, include/compat/getaddrinfo.h,
+ include/compat/getopt.h, include/compat/glob.h,
+ include/compat/nss_dbdefs.h, include/compat/sha2.h,
+ include/compat/stdbool.h, include/compat/timespec.h,
+ include/sudo_alloc.h, include/sudo_compat.h, include/sudo_conf.h,
+ include/sudo_debug.h, include/sudo_dso.h, include/sudo_event.h,
+ include/sudo_fatal.h, include/sudo_gettext.h, include/sudo_lbuf.h,
+ include/sudo_plugin.h, include/sudo_queue.h, include/sudo_util.h,
+ lib/util/fatal.c, plugins/sudoers/bsm_audit.h,
+ plugins/sudoers/check.h, plugins/sudoers/defaults.h,
+ plugins/sudoers/ins_2001.h, plugins/sudoers/ins_classic.h,
+ plugins/sudoers/ins_csops.h, plugins/sudoers/ins_goons.h,
+ plugins/sudoers/insults.h, plugins/sudoers/interfaces.h,
+ plugins/sudoers/iolog.h, plugins/sudoers/linux_audit.h,
+ plugins/sudoers/logging.h, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h, plugins/sudoers/pwutil.h,
+ plugins/sudoers/redblack.c, plugins/sudoers/redblack.h,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/solaris_audit.h, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudo_nss.h, plugins/sudoers/sudo_printf.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/sudoers_debug.h, plugins/sudoers/sudoers_version.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.h, plugins/sudoers/toke.l,
+ plugins/sudoers/visudo.c, src/net_ifs.c, src/sudo.h,
+ src/sudo_exec.h, src/sudo_plugin_int.h, src/sudo_usage.h.in:
+ Avoid using a leading underbar in defines as they are reserved in
+ ISO C.
+ [a442d88c6490]
+
+ * Makefile.in, doc/Makefile.in, examples/Makefile.in,
+ include/Makefile.in, lib/util/Makefile.in, lib/zlib/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/auth/afs.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/rfc1938.c, plugins/sudoers/auth/secureware.c,
+ plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/bsm_audit.c, plugins/sudoers/linux_audit.c,
+ plugins/sudoers/solaris_audit.c, plugins/sudoers/sssd.c,
+ plugins/system_group/Makefile.in, src/Makefile.in, src/selinux.c:
+ Add target for "make splint". A few files need extra guards to avoid
+ errors on systems where they would not otherwise be compiled. No
+ warnings from splint.
+ [64fc04debc58]
+
+2015-05-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/sia.c:
+ Use reallocarray() instead of sudo_emallocarray() and return an
+ error on allocation failure.
+ [fee12ac1e0c8]
+
+ * plugins/sudoers/auth/kerb5.c:
+ In our krb5_get_init_creds_opt_alloc() replacement use malloc()
+ instead of sudo_emalloc() and return KRB5_CC_NOMEM on allocation
+ failure. Only old versions of Kerberos V will need this.
+ [95ac6c5b7b60]
+
+ * lib/util/event.c, lib/util/event_select.c:
+ Use non-exiting allocators.
+ [91bbc657901d]
+
+2015-05-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.ac, src/sudo.c:
+ There should be no need to check for tzset() as it is POSIX.
+ [50825eb75c97]
+
+ * configure, configure.ac:
+ Add sudo_reallocarrary to util.exp.in if reallocarray is not found.
+ [32588e00bb33]
+
+2015-05-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ NLS now works on Mac OS X properly.
+ [1485c9e51b04]
+
+ * configure, configure.ac, src/Makefile.in:
+ Force flat namespace on darwin to make the getenv() hooking work as
+ it does on ELF.
+ [0837cc3559ce]
+
+2015-05-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/alloc.c, lib/util/snprintf.c,
+ plugins/sample/sample_plugin.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/redblack.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/toke_util.c:
+ No need to cast malloc() return value.
+ [09c7236d3e1a]
+
+ * lib/util/getcwd.c, lib/util/getline.c, lib/util/glob.c,
+ plugins/sudoers/env.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l:
+ Use reallocarray where possible.
+ [2b5957a38baa]
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h,
+ lib/util/alloc.c:
+ Add reallocarray() for those without it.
+ [3ac5a4abe077]
+
+2015-05-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ The getenv() hook still doesn't work on Mac OS X.
+ [d9297b9ff54c]
+
+2015-05-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/sudo_fatal.h, lib/util/fatal.c:
+ In sudo_warn_gettext_v1() call dgettext() not gettext() to make sure
+ the domain is set correctly. The sudoers plugin uses its own text
+ domain.
+ [f7ce0100ff5c]
+
+2015-05-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/Makefile.in:
+ man pages should explicitly depend on config.status since it is used
+ to substitute in variables/settings.
+ [bebe8e19d767]
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo_plugin.cat,
+ doc/sudoers.cat, doc/sudoers.ldap.cat, doc/sudoers.man.in,
+ doc/sudoreplay.cat, doc/visudo.cat:
+ regen
+ [2e613d7bb477]
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.8.14
+ [66e33bc0d18e]
+
+ * INSTALL, MANIFEST, aclocal.m4, config.h.in, configure, configure.ac,
+ include/sudo_fatal.h, lib/util/Makefile.in, lib/util/fatal.c,
+ lib/util/locale_weak.c, lib/util/util.exp.in,
+ m4/ax_sys_weak_alias.m4, mkdep.pl, plugins/sudoers/Makefile.in,
+ plugins/sudoers/locale.c, plugins/sudoers/logging.h,
+ plugins/sudoers/sudoers.c, src/Makefile.in, src/locale_stub.c:
+ Instead of trying to make weak functions work on all platforms, just
+ use a registration function for a plugin-specific setlocale
+ function. The sudoers version just wraps sudoers_setlocale().
+ [0eef64f41cdf]
+
+ * src/parse_args.c:
+ Fix indentation of -a flag help line.
+ [a2ed556b6454]
+
+ * include/sudo_compat.h:
+ Fix compilation when HAVE_DECL_SIG2STR_MAX is not defined.
+ [31aa465affaa]
+
+ * doc/Makefile.in:
+ Add lint target to run "mandoc -Tlint" over the manuals.
+ [63ed14d91adc]
+
+2015-05-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/sudo_compat.h:
+ HAVE_DECL_SIG2STR_MAX is always defined so use a
+ !HAVE_DECL_SIG2STR_MAX check instead of #ifndef.
+ [65cc03302d39]
+
+2015-05-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/tgetpass.c:
+ Sync tty_present() with sudoers version.
+ [040c05e68627]
+
+ * src/load_plugins.c:
+ sudo_check_plugin() returns bool.
+ [15b2851bfb90]
+
+ * plugins/sudoers/match.c:
+ In usergr_matches() matched should be bool but we have to take care
+ to handle group_plugin_query() returning a value other than 0/1.
+ [c120901f71c7]
+
+ * plugins/sudoers/ldap.c:
+ sudo_ldap_check_non_unix_group() returns bool, not int.
+ [d12e9242454f]
+
+ * plugins/sudoers/logging.c:
+ Convert two debug_return_int to debug_return_bool.
+ [594d0fc8efda]
+
+ * include/sudo_debug.h, lib/util/sudo_debug.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/check.c,
+ plugins/sudoers/env.c, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/match.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c, src/sudo.c:
+ Previously, debug_return_bool was the same as debug_return_int
+ except that it logged true/false for 1/0. However, this appears to
+ trigger a bug in some compilers. To avoid this, debug_return_bool
+ now uses bool, not int. Callers that were passing it an int have
+ been converted to use debug_return_int instead.
+ [ca142b5a9433]
+
+ * src/get_pty.c, src/sudo.h:
+ get_pty() should return bool
+ [2c72c8d3603b]
+
+ * src/sudo.h, src/tgetpass.c:
+ Make tty_present static to tgetpass.c
+ [bb73a2cc8754]
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h:
+ Add configure check for SIG2STR_MAX, which may be missing on
+ UnixWare.
+ [e9dcac23c639]
+
+ * m4/ax_sys_weak_alias.m4:
+ Need to quote $GCC as it may include arguments. From Tim Rice.
+ [9ed8a3be94bf]
+
+ * MANIFEST:
+ Add missing m4/ax_sys_weak_alias.m4
+ [269a8d5bfb49]
+
+2015-04-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg:
+ There's no point in building i386 binaries for Mac OS X 10.7 and
+ higher.
+ [e8876ea36d14]
+
+2015-04-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/fr.mo, plugins/sudoers/po/fr.po, po/ja.mo,
+ po/ja.po:
+ Sync with translationproject.org
+ [414c51286530]
+
+2015-04-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/bsm_audit.c:
+ Only fall back on AUE_DARWIN_sudo if au_preselect() fails.
+ [aea2f3a60b46]
+
+2015-04-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/bsm_audit.c:
+ Work around a problem on Mac OS X 10.10 which defines AUE_sudo but
+ where au_preselect() only accepts AUE_DARWIN_sudo (the old value).
+ [b5d32d6453d1]
+
+2015-04-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/env_hooks.c:
+ Don't use dlsym() to find the libc getenv() since this may allocate
+ memory on some systems (glibc) which leads to a hang if malloc()
+ calls getenv() (jemalloc).
+ [441846664820]
+
+ * include/sudo_debug.h, src/sudo.c:
+ Split variable declaration out of debug_decl into debug_decl_vars()
+ so we can use it in main() when we know sudo_debug_enter() cannot
+ succeed.
+ [6931948a57f8]
+
+ * src/sudo.c:
+ Defer conversation initialization until right before plugins are
+ initialized.
+ [83db53d4945c]
+
+2015-04-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c, plugins/sudoers/testsudoers.c:
+ When creating a passwd struct from a uid that is not in the passwd
+ database, set pw_gid to the user's gid instead of whatever the user
+ specified via the -g flag (or 0 if no -g).
+ [4154970432df]
+
+2015-04-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Add some ldap_err2string() debugging when the LDAP search fails.
+ Adapted from a diff from Steven Soulen.
+ [e08d38481041]
+
+2015-04-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po, po/sr.mo,
+ po/sr.po:
+ Sync with translationproject.org
+ [cbf24072ad07]
+
+2015-04-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS:
+ Add David Michael and Andrey Klyachkin.
+ [e153a9b46e1f]
+
+ * sudo.pp:
+ Sync tmpfiles.d/sudo.conf with init.d/sudo.conf.in
+ [9e3945c1fe6e]
+
+ * include/sudo_util.h:
+ Avoid struct assignment when stashing mtime since AIX at least uses
+ a struct st_timespec that differs from struct timespec. From Andrey
+ Klyachkin.
+ [e267ea5b019e]
+
+2015-04-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Work around a bug in pp that caused a warning when exampledir is a
+ subdir of docdir.
+ [d81db98f215f]
+
+ * plugins/sudoers/solaris_audit.c:
+ Add sys/types.h
+ [e0794f05e95c]
+
+ * lib/util/getopt_long.c, lib/util/mksiglist.c, lib/util/mksigname.c,
+ lib/util/regress/fnmatch/fnm_test.c,
+ lib/util/regress/glob/globtest.c, lib/util/sha2.c,
+ plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/parser/check_hexchar.c:
+ Include sys/types.h instead of unistd.h to get uid_t and gid_t. Add
+ missing include of sys/types.h to a few places.
+ [86eb67f3c41a]
+
+2015-04-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg:
+ Remove unintended commit
+ [2eeeb74b9174]
+
+ * init.d/sudo.conf.in:
+ Add tmpfiles.d/sudo.conf template.
+ [ead9bb7b5328]
+
+2015-04-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * .hgignore, INSTALL, MANIFEST, Makefile.in, configure, configure.ac,
+ mkpkg, src/Makefile.in, sudo.pp:
+ Create template tmpfiles.d/sudo.conf for installation instead of
+ creating one via echo commands in the Makefile.
+
+ Add --enable-tmpfiles.d configure option to enable/disable use of
+ tmpfiles.d and override the default directory.
+
+ Use --disable-tmpfiles.d in mkpkg so we no longer need to ignore
+ tmpfiles.d/sudo.conf in sudo.pp.
+ [930983f88927]
+
+ * sudo.pp:
+ Fix setting of pp_rpm_version when there is no patchlevel present.
+ Also tighten up the regexp for pp_rpm_release.
+ [d6a89aafd99d]
+
+2015-04-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, Makefile.in, configure, configure.ac, doc/sudoers.mdoc.in,
+ examples/Makefile.in, mkpkg, sudo.pp:
+ Make exampledir configurable and default to
+ DATAROOTDIR/examples/sudo on BSD systems.
+ [4c1271298712]
+
+ * src/Makefile.in, sudo.pp:
+ Install /usr/lib/tmpfiles.d/sudo.conf on systems with systemd but do
+ not package it. For packages we create /usr/lib/tmpfiles.d/sudo.conf
+ as needed in the postinstall script.
+ [522666bc079f]
+
+2015-03-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.cat, doc/sudoers.ldap.cat,
+ doc/sudoers.ldap.man.in, doc/sudoers.ldap.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, doc/sudoreplay.cat,
+ doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in, doc/visudo.cat,
+ doc/visudo.man.in, doc/visudo.mdoc.in:
+ Fix "mandoc -Tlint" warnings. Sync AUTHORS section in man pages.
+ Regenerate all man pages.
+ [34e4149bb225]
+
+ * lib/util/Makefile.in, plugins/sudoers/Makefile.in, src/Makefile.in:
+ Make libsudo_util depend on libintl instead of requiring users of
+ libsudo_util to link with libintl directly. Bug #690
+ [f2508d1a21ee]
+
+2015-03-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/logging.c:
+ Use saved errno in vlog_warning() before calling
+ sudo_vwarn_nodebug(). Fixes the error message printed if set_perms()
+ fails.
+ [68bd7297137e]
+
+2015-03-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Update for 1.8.13 final.
+ [4c03db3a740f]
+
+2015-03-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/env.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ For sudoedit, run the editor with the user's original environment as
+ per the documentation (and as in sudo 1.7.x). Bug #688
+ [a5081c8f6950]
+
+ * plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po, po/fr.mo,
+ po/fr.po:
+ Sync with translationproject.org
+ [0b820c5ecb0c]
+
+2015-03-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/term.c:
+ Update function names in debug_decl.
+ [b83f153b2f43]
+
+ * lib/util/term.c:
+ Use TCSAFLUSH instead of TCSANOW in sudo_term_copy(). Be consistent
+ with where we put TCSASOFT in the action flags.
+ [6ffeec3aa184]
+
+2015-03-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po, po/da.mo,
+ po/da.po, po/fi.mo, po/fi.po, po/zh_CN.mo, po/zh_CN.po:
+ Sync with translationproject.org
+ [0d20f88c0a83]
+
+2015-03-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/sha2.c:
+ Include unistd.h since sudo_compat.h uses gid_t.
+ [da491d83e5dc]
+
+2015-03-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, configure, configure.ac:
+ Add --disable-weak-symbols option to disable use of weak symbols in
+ libsudo_util.
+ [3edf2bccb4d8]
+
+ * configure:
+ regen
+ [ff1abfcd2b61]
+
+ * m4/ax_sys_weak_alias.m4:
+ When checking for weak aliases, check the gcc attribute format last
+ since some C compilers just ignore unsupported attributes.
+ [e172cbbfa615]
+
+ * sudo.pp:
+ Update copyright year.
+ [67bcd24c6477]
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po, po/cs.mo,
+ po/cs.po, po/de.mo, po/de.po, po/eo.mo, po/eo.po, po/it.mo,
+ po/it.po, po/nb.mo, po/nb.po, po/pl.mo, po/pl.po, po/pt_BR.mo,
+ po/pt_BR.po, po/uk.mo, po/uk.po, po/vi.mo, po/vi.po:
+ Sync with translationproject.org
+ [ceb62f98364c]
+
+ * configure, configure.ac, include/compat/sha2.h:
+ Fix symbol name collision with systems that have their own sha2
+ implementation. This can result in PAM using the wrong sha2
+ implementation on Solaris systems configured to use SHA512 for
+ passwords.
+ [3a25c4896804]
+
+ * src/Makefile.in:
+ Use SSP_LDFLAGS when linking sudo_noexec.la
+ [6187b17fad90]
+
+2015-03-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/compat/utime.h, lib/util/Makefile.in, lib/util/utimens.c:
+ Remove compat/utime.h, it was only useful for ancient systems that
+ are no longer capable of compiling sudo.
+ [94e4f02868db]
+
+2015-03-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac, lib/util/Makefile.in:
+ Link libsudo_util with -lrt on systems where clock_gettime is in
+ -lrt.
+ [44a9a0d0af69]
+
+ * NEWS:
+ Update.
+ [811c8d7090c0]
+
+ * lib/util/strlcat.c, lib/util/strlcpy.c:
+ Update OpenBSD CVS Ids
+ [933788497ee4]
+
+ * lib/util/strlcat.c:
+ Make comment match code.
+ [b1b68810929d]
+
+ * lib/util/utimens.c:
+ Fix compilation error on systems without futimes().
+ [4d55a58ea12e]
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/gettime.c, lib/util/util.exp.in, lib/util/utimens.c,
+ lib/util/utimes.c, mkdep.pl, plugins/sudoers/Makefile.in,
+ plugins/sudoers/boottime.c, plugins/sudoers/gettime.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/timestamp.c,
+ plugins/sudoers/visudo.c, src/Makefile.in, src/sesh.c,
+ src/sudo_edit.c:
+ Use futimens() and utimensat() instead of futimes() and utimes().
+ [8400f91466d8]
+
+ * plugins/sudoers/visudo.c:
+ Fix compiler warning on systems where mode_t is not unsigned int,
+ such as 32-bit Solaris.
+ [1eeeea1c203d]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Fix logic for verifypw/listpw all in sudoers LDAP and sssd.
+ [5bc60a34a477]
+
+ * src/tgetpass.c:
+ Fix cut & pasto that prevented the SIGPIPE handler from being
+ restored before returning from tgetpass(). From mancha
+ [230b0a86876e]
+
+2015-02-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sesh.c, src/sudo_edit.c:
+ Our utimes() emulation support futime() too.
+ [439851535285]
+
+2015-02-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [40aa9164563f]
+
+ * plugins/sudoers/testsudoers.c:
+ Define YYDEBUG to 0 if not already defined so we can protect use of
+ sudoersdebug with "#if YYDEBUG" like the generated parser does. From
+ David Michael.
+ [394e1c237aac]
+
+2015-02-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document that Aliases may not be redefined and that "sudo -f
+ /etc/sudo.d/foo" will not catch the redefinition.
+ [3bff3b5f7eb1]
+
+ * sudo.pp:
+ Only create /usr/lib/tmpfiles.d/sudo.conf if
+ /usr/lib/tmpfiles.d/systemd.conf also exists. Some other package may
+ have created /usr/lib/tmpfiles.d even though it is not used.
+ [cf013d95b7d7]
+
+ * plugins/sudoers/Makefile.in:
+ regen
+ [4dde632c35cd]
+
+ * sudo.pp:
+ Clear the ts dir instead of just making sure it exists.
+ [c49b6e3e2360]
+
+ * configure, configure.ac:
+ Only substiture init.d scripts that we are going to use.
+ [301f16bd04c5]
+
+2015-02-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in, sudo.pp:
+ Create /usr/lib/tmpfiles.d/sudo.conf when systemd is used.
+ [532dc61e7bb7]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/visudo.c, src/sudo_edit.c,
+ src/utmp.c:
+ Check the return value of gettimeofday(), even though it should
+ never fail.
+ [747715d8a11c]
+
+2015-02-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, configure, configure.ac, include/sudo_compat.h,
+ lib/util/Makefile.in, lib/util/clock_gettime.c, mkdep.pl,
+ plugins/sudoers/Makefile.in, plugins/sudoers/gettime.c,
+ plugins/sudoers/po/sudoers.pot, plugins/sudoers/sudoers.h,
+ plugins/sudoers/timestamp.c:
+ We cannot (easily) use clock_gettime(CLOCK_MONOTONIC) directly as it
+ may be present but not implemented. Add sudo_gettime_real() and
+ sudo_gettime_mono() functions to get the real and monotonic times
+ respectively. Now sudo_gettime_mono() checks the value of
+ sysconf(_SC_MONOTONIC_CLOCK) before calling
+ clock_gettime(CLOCK_MONOTONIC) and falls back on sudo_gettime_real()
+ as needed. The Mach version of sudo_gettime_mono() uses
+ mach_absolute_time().
+
+ This should fix problems with timestamp files on systems where the
+ CLOCK_MONOTONIC is defined but not actually implemented.
+ [cd04a21af4c5]
+
+ * include/sudo_compat.h, plugins/sudoers/timestamp.c:
+ Check clock_gettime() return value and warn if it fails. Currently,
+ the timestamp will be ignored if clock_gettime() fails.
+ [3658154638da]
+
+2015-02-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/sudo_debug.c:
+ Plug memory leak when debug file cannot be opened. Use %zu printf
+ format now that our snprintf support it.
+ [a168a002cd19]
+
+ * plugins/sudoers/auth/pam.c:
+ Pam conversation function changes: o use PAM_BUF_ERR as the return
+ value when calloc() fails. o sanity check the value of num_msg o
+ remove the workaround for old Apple PAM o PAM_AUTH_ERR is not a
+ valid PAM conversation function return value
+
+ If getpass_error is set after a call to pam_verify (usually because
+ the user pressed ^C), return AUTH_INTR immediately instead of
+ checking the pam_verify return value.
+ [8d378f40fe1f]
+
+ * INSTALL, NEWS, configure, configure.ac,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h:
+ On AIX use the value of auth_type in /etc/security/login.cfg to
+ determine whether to use LAM or PAM unless the user specified the
+ --with-pam or --with-aixauth configure flags.
+ [cb314c1ed5f8]
+
+ * lib/util/parseln.c:
+ Fix cast.
+ [4f56047e2bc4]
+
+2015-02-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.ac, lib/util/snprintf.c:
+ Update snprintf.c from OpenBSD. The floating point and wide
+ character code has been retained but is not compiled by default.
+ [6801a77398fc]
+
+2015-02-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/regress/sudoers/test1.in,
+ plugins/sudoers/regress/sudoers/test1.out.ok,
+ plugins/sudoers/regress/sudoers/test1.toke.ok:
+ Update the regression test that check that all tags are parsed.
+ [d0f9af2f9d45]
+
+ * MANIFEST, configure, configure.ac, lib/util/Makefile.in,
+ lib/util/mktemp.c, lib/util/regress/mktemp/mktemp_test.c, mkdep.pl:
+ Add regress for mkdtemp and mkstemps from OpenBSD
+ [18714ae9bffd]
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [b77490dd9b33]
+
+ * plugins/sudoers/po/nl.mo, plugins/sudoers/po/nl.po, po/tr.mo,
+ po/tr.po:
+ Sync with translationproject.org
+ [b2946065653d]
+
+ * config.h.in, configure.ac:
+ Correct SECURE_PATH comment.
+ [3fd6132d5dba]
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.8.13
+ [32c1183b0666]
+
+2015-02-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ include/sudo_compat.h, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/gethostname.c, lib/util/util.exp.in,
+ plugins/sudoers/match.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c, src/sudo.c:
+ Avoid using HOST_NAME_MAX directly and use
+ sysconf(_SC_HOST_NAME_MAX) instead.
+ [97036b819d58]
+
+ * plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/secureware.c:
+ Historically, crypt() returned the empty string on error, which
+ ensured that crypt("", "") would return "", which supported matcing
+ empty encrypted passwords with no additional code. Some modern
+ versions of crypt() (such as glibc) return NULL on error so we need
+ an explicit test to match an empty plaintext password and an empty
+ encrypted password.
+ [b88eb9da5e57]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Sort tags lexically in the sudoers manual
+ [66716c0b7a13]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y, plugins/sudoers/ldap.c,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/sudoers/test1.out.ok,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudoers_version.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/visudo_json.c:
+ Add support for MAIL and NOMAIL command tags to toggle mail sending
+ behavior on a per-command (or Cmnd_Alias) basis.
+ [04f30a064c25]
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h,
+ lib/util/closefrom.c, lib/util/setgroups.c,
+ plugins/sudoers/pwutil_impl.c, src/sudo.c:
+ Almost no systems actually define OPEN_MAX since it is dynamic on
+ modern OSes. If sysconf(_SC_OPEN_MAX) ever fails, fall back on
+ _POSIX_OPEN_MAX instead. We can assume modern systems have
+ sysconf(). Also remove checks for strrchr() and strtoll() for which
+ the HAVE_* defines are no longer used.
+ [c3058a6cca86]
+
+ * lib/util/getline.c, plugins/group_file/getgrent.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/tsgetgrpw.c:
+ All modern systems should have LINE_MAX.
+ [117322b6d86c]
+
+ * Makefile.in, sudo.pp:
+ Don't need to pass exampledir to polypkg now that it is just under
+ docdir.
+ [9f24f0184a78]
+
+2015-02-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Fix packaging of the example dir.
+ [4c7cbc3fc190]
+
+ * lib/util/mktemp.c:
+ Fix mkstemps() extension handling. Sudoedit will now preserve the
+ extension properly when the system libc lacks mkstemps().
+ [b86f54331972]
+
+2015-02-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, aclocal.m4, config.h.in, configure, configure.ac,
+ lib/util/Makefile.in, lib/util/locale_weak.c,
+ m4/ax_sys_weak_alias.m4, mkdep.pl, src/Makefile.in,
+ src/locale_stub.c:
+ Use weak symbols for sudo_warn_gettext() and sudo_warn_strerror() so
+ distros using "-Wl,--no-undefined" in LDFLAGS don't run into
+ problems.
+ [708418615aae]
+
+ * lib/util/mksiglist.c, lib/util/mksigname.c:
+ Include unistd.h in siglist.c and signame.c to get gid_t which is
+ used by sudo_compat.h. Bug #686
+ [0ab6450a96ec]
+
+2015-02-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/logging.c:
+ Add mail_all_cmnds to always mail when a user runs a command (or
+ tries to) including sudoedit. The mail_always flag goes back to its
+ old semantic of always mailing when sudo is run.
+ [edc904502061]
+
+2015-02-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Minor change in description of TZ path handling.
+ [579b02f0dbe0]
+
+ * Makefile.in, examples/Makefile.in:
+ Move example dir under the doc dir to conform to Debian guidelines.
+ Bug #682.
+ [494d9a0484b6]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document that a leading ':' is skipped when checking TZ for a fully-
+ qualified path name.
+ [91859f613b88]
+
+2015-02-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Typo.
+ [b9257ea66116]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Fix typos.
+ [ac1467f71ac0]
+
+ * plugins/sample/sample_plugin.c:
+ Fix compilation on systems w/o __dso_public
+ [b773ef9127fa]
+
+2015-02-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, plugins/sudoers/po/ru.mo, plugins/sudoers/po/ru.po:
+ Russian translation for sudoers from translationproject.org.
+ [8a7fc2e00072]
+
+2015-02-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, doc/CONTRIBUTORS, plugins/sudoers/po/ru.mo,
+ plugins/sudoers/po/ru.po:
+ Russian translation for sudoers from translationproject.org.
+ [1d5869e4d4af]
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h:
+ Add check for getresuid() declaration, which may be missing on HP-
+ UX. When checking for getdomainname() prototype, look in netdb.h
+ too.
+ [0ba583590b17]
+
+ * INSTALL, NEWS, configure, configure.ac, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, m4/sudo.m4, pathnames.h.in,
+ plugins/sudoers/env.c:
+ Sanity check the TZ environment variable by special casing it in
+ env_check. The --with-tzdir configure option can be used to specify
+ the zoneinfo directory if configure doesn't find it.
+ [650ac6938b59]
+
+ * NEWS:
+ Mention crash fixes.
+ [f759c993e172]
+
+ * src/parse_args.c:
+ Bail with usage() early if argc <= 0.
+ [aaba56c9a797]
+
+2015-02-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/pwutil.c:
+ Remove extraneous casts of node->data (which is void *).
+ [950749570a00]
+
+ * doc/CONTRIBUTORS:
+ Add Stephane Chazelas
+ [a6c7becabee7]
+
+ * plugins/sudoers/pwutil.c:
+ Fix a potential crash when getpwnam() of the running user fails and
+ we don't replace the negative cached entry with a faked up one. From
+ Stephane Chazelas
+ [9088f041bbad]
+
+ * src/parse_args.c, src/sudo.c:
+ Don't assume argv[0] is set without first checking argc.
+ [aabdc9d0ba26]
+
+ * lib/util/progname.c:
+ Call setprogname("sudo") if getprogname() returns NULL or the empty
+ string.
+ [45438f7227b1]
+
+ * plugins/sudoers/set_perms.c:
+ Handle sudo_get_grlist() returning NULL which can happen if
+ getgrouplist() fails even after allocating the appropriate amount of
+ memory. From Stephane Chazelas
+ [25747a0ead7c]
+
+ * config.h.in, configure, configure.ac:
+ Remove configure checks for strrchr() and strtoll() for which the
+ HAVE_* defines are no longer used.
+ [f04216435aba]
+
+ * config.h.in, configure, configure.ac, doc/sudoreplay.cat,
+ doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in,
+ plugins/sudoers/sudoreplay.c:
+ Require POSIX regular expression support for sudoreplay.
+ [1486747cd470]
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h:
+ Check whether getdomainname(), innetgr(), setresuid() and
+ setresgid() are declared and add prototypes in sudo_compat.h as
+ needed.
+ [03aa144afce4]
+
+ * plugins/sudoers/policy.c:
+ The plugin no longer needs to call initprogname() now that it links
+ with the same libsudo_util as sudo.
+ [78b65a352ac5]
+
+2015-02-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Add /usr/local/share/examples/ directory to parentdirs so it is
+ explicitly added to the package.
+ [ef1aa52b0aad]
+
+ * plugins/sudoers/po/da.mo, po/da.mo:
+ Sync with translationproject.org
+ [943986acd31c]
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po,
+ plugins/sudoers/po/nl.mo, plugins/sudoers/po/nl.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po, po/nl.mo,
+ po/nl.po:
+ Sync with translationproject.org
+ [4977ac967bdd]
+
+2015-02-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/getdate.c, plugins/sudoers/gram.c:
+ Regen with yacc skeleton that the clang analyzer doesn't complain
+ about.
+ [e15991fd4ab1]
+
+ * configure, configure.ac, lib/util/alloc.c, lib/util/glob.c,
+ plugins/sudoers/env.c, plugins/sudoers/getdate.c,
+ plugins/sudoers/getdate.y, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y:
+ Use stdint.h to get SIZE_MAX as inttypes.h on some pre-C99 HP-UX
+ systems doesn't include stdint.h itself.
+ [9fbd35811743]
+
+ * configure, configure.ac:
+ SIZE_MAX may be in limits.h on pre-C99 compilers.
+ [d3b554f7e0e5]
+
+ * config.h.in, configure, configure.ac, lib/util/aix.c:
+ Add missing prototypes for usrinfo() and setauthdb() for AIX.
+ [aa4b205296cf]
+
+ * config.h.in, configure, configure.ac, plugins/sudoers/match.c:
+ Solaris uses sysinfo(SI_SRPC_DOMAIN) instead of getdomainname() to
+ get the host's NIS domain.
+ [9234c62a1469]
+
+2015-02-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ Remove AC_PROG_GCC_TRADITIONAL and add AC_PROG_CC_STDC since we need
+ C99.
+ [005775f5662b]
+
+ * plugins/sudoers/match.c:
+ Actually use the check for prior initialization in
+ sudo_getdomainname().
+ [06368385ad0d]
+
+ * configure, configure.ac:
+ We need to add OSDEFS to CFLAGS to expose LLONG_MAX et al on glibc
+ when not explicitly asking for c99.
+ [ae9435631600]
+
+ * NEWS, doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/logging.c:
+ Don't send mail about pseudo-command failure unless it is an
+ authentication failure.
+ [deddcfc1f2ab]
+
+ * configure, configure.ac:
+ Fix check for SIZE_MAX, which should be in stdint.h not limits.h.
+ [47bf0ab7dfca]
+
+ * lib/util/glob.c:
+ Need to include inttypes.h for SIZE_MAX
+ [a11f42f40294]
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [d35b24f95ef8]
+
+2015-02-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/sudo_debug.h, lib/util/aix.c, lib/util/event.c,
+ lib/util/event_poll.c, lib/util/event_select.c, lib/util/gidlist.c,
+ lib/util/key_val.c, lib/util/lbuf.c, lib/util/locking.c,
+ lib/util/parseln.c, lib/util/secure_path.c, lib/util/setgroups.c,
+ lib/util/strtobool.c, lib/util/strtoid.c, lib/util/strtomode.c,
+ lib/util/sudo_conf.c, lib/util/sudo_debug.c, lib/util/term.c,
+ lib/util/ttysize.c, lib/util/util.exp.in, plugins/sudoers/alias.c,
+ plugins/sudoers/audit.c, plugins/sudoers/auth/afs.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/base64.c, plugins/sudoers/boottime.c,
+ plugins/sudoers/bsm_audit.c, plugins/sudoers/check.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/env.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/getspwuid.c,
+ plugins/sudoers/goodpath.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/hexchar.c, plugins/sudoers/interfaces.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_path.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/linux_audit.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logwrap.c,
+ plugins/sudoers/match.c, plugins/sudoers/match_addr.c,
+ plugins/sudoers/parse.c, plugins/sudoers/policy.c,
+ plugins/sudoers/prompt.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/pwutil_impl.c, plugins/sudoers/redblack.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoers_debug.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timestamp.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/toke_util.c,
+ plugins/sudoers/visudo.c, plugins/sudoers/visudo_json.c, src/exec.c,
+ src/exec_common.c, src/exec_pty.c, src/get_pty.c, src/hooks.c,
+ src/load_plugins.c, src/net_ifs.c, src/parse_args.c,
+ src/preserve_fds.c, src/selinux.c, src/sesh.c, src/signal.c,
+ src/solaris.c, src/sudo.c, src/sudo_edit.c, src/tgetpass.c,
+ src/ttyname.c, src/utmp.c:
+ Go back to a 2 args debug_decl and just use the "default" instance,
+ now renamed "active".
+ [7130b7478355]
+
+2015-01-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/LICENSE:
+ Update copyright year.
+ [e1dad7b195e4]
+
+2015-01-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in, plugins/sudoers/ldap.c,
+ plugins/sudoers/match.c, plugins/sudoers/parse.h:
+ When querying LDAP netgroups, use the NIS domain if it is sent but
+ also match nisNetgroupTriple entries that have no domain.
+ [5a0fa3ac26f7]
+
+ * plugins/sudoers/sudoreplay.c:
+ Avoid setting the tty to non-blocking mode so "sudoreplay | cat"
+ (for example) works as expected. We only read a single byte from the
+ keyboard and only when interactive anyway so this should be fine.
+ [9615a932545b]
+
+ * lib/zlib/Makefile.in, plugins/sudoers/Makefile.in:
+ regen
+ [f19c6e000850]
+
+ * plugins/sudoers/sudoreplay.c:
+ Avoid a cppcheck warning about undefined behavior (using the address
+ of a stack buffer - 1) and fix a memory leak of the iov when doing
+ nl->crnl conversion.
+ [e26f9008c2e4]
+
+ * doc/CONTRIBUTORS:
+ Add Steven Soulen
+ [17a47303d5fe]
+
+ * plugins/sudoers/sudoreplay.c:
+ Fix handling of partial writes from writev() which can occur with
+ large output buffers.
+ [1065dbeaa13d]
+
+2015-01-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in, plugins/sudoers/ldap.c:
+ Add support for querying netgroups directly via LDAP since there is
+ no other way to look up all the netgroups for a user (unlike regular
+ groups). This introduces netgroup_base and netgroup_search_filter
+ options to ldap.conf. Based on a diff from Steven Soulen.
+ [7e3d55983e71]
+
+2015-01-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ Sort ldap.conf options.
+ [264608124698]
+
+2015-01-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Add macros to ease the checking of strlcpy, strlcat and
+ sudo_ldap_value_cat return values.
+ [e9122413d4fa]
+
+2015-01-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/logging.c, plugins/sudoers/parse.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Rename VALIDATE_OK -> VALIDATE_SUCCESS Rename VALIDATE_NOT_OK ->
+ VALIDATE_FAILURE
+ [4379cac9f75d]
+
+ * plugins/sudoers/logging.c, plugins/sudoers/sudoers.h:
+ Remove now-unused VALIDATE_ERROR define.
+ [569d4936b761]
+
+ * plugins/sudoers/logging.c:
+ should_mail() now returns bool.
+ [0316d1fb08c3]
+
+ * lib/util/sudo_debug.c:
+ If sudo_debug_register() fails return
+ SUDO_DEBUG_INSTANCE_INITIALIZER, not -1. Otherwise we could end up
+ setting the instance to -1 which is invalid.
+ [032bb1db6db5]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Fix typo.
+ [014be972780c]
+
+ * doc/Makefile.in:
+ Use "mandoc -Tascii" to generate .cat pages to avoid locale-specific
+ characters.
+ [0ec42d8924fc]
+
+2015-01-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, m4/sudo.m4:
+ Use AC_PATH_PROG to find programs instead of checking the path
+ manually.
+ [2b5d9893a7a7]
+
+2015-01-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/strlcat.c, lib/util/strlcpy.c:
+ Sync with OpenBSD version
+ [22c073c42a9e]
+
+2015-01-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ Use AC_CHECK_HEADERS_ONCE and AC_CHECK_FUNCS_ONCE where possible and
+ quote the first args in AC_CHECK_FUNCS calls.
+ [84aa40ab410a]
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h:
+ Avoid inadvertantly defining things like PATH_MAX simply because the
+ source file doesn't include limits.h.
+ [d2e7c4093f55]
+
+2015-01-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, ltmain.sh, m4/libtool.m4, m4/ltoptions.m4,
+ m4/ltversion.m4:
+ Update to libtool 2.4.4 + HP-UX patches
+ [859b7378bc37]
+
+ * src/ttyname.c:
+ Document why we need sys/param.h.
+ [f21a4d7122f0]
+
+ * configure, m4/sudo.m4:
+ Don't need sys/param.h.
+ [6aa24ecfc9d4]
+
+ * lib/util/closefrom.c:
+ Don't appear to need sys/param.h for pstat_getproc() on HP-UX even
+ though the man page lists it.
+ [47d75f3db288]
+
+ * lib/util/inet_ntop.c, lib/util/inet_pton.c:
+ Should not need sys/param.h here.
+ [5c83cebcd75f]
+
+2014-12-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/match_addr.c:
+ Use standard CIDR -> netmask conversion and disallow 0-bit CIDRs.
+ [d30313d726eb]
+
+2014-12-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * README.LDAP:
+ Update link to gq LDAP editor, now on sourceforge.
+ [706dadea1abb]
+
+2014-12-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/compat/glob.h, lib/util/glob.c:
+ Add support for GLOB_LIMIT from OpenBSD (not currently used) and
+ also a limit on the max recursion depth for glob().
+ [6f9e26b88612]
+
+ * lib/util/glob.c:
+ Quiet compiler sign compare warning.
+ [c4f35c02122c]
+
+2014-12-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ fnmatch fix
+ [07542b07ac67]
+
+ * lib/util/fnmatch.c:
+ Remove artificial limit on length of pattern and string. It is
+ possible to use fnmatch() on things other than paths (such as
+ arguments) so a limit of PATH_MAX does not make sense. Fixes a bug
+ where rules would fail to match if the length of the arguments were
+ larger than PATH_MAX (usually 1024).
+ [942770c20422]
+
+2014-12-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.cat, doc/sudoers.ldap.cat,
+ doc/sudoers.ldap.man.in, doc/sudoers.ldap.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, doc/sudoreplay.cat,
+ doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in, doc/visudo.cat,
+ doc/visudo.man.in, doc/visudo.mdoc.in:
+ Remove the extra /sudo in sudo.ws urls
+ [0b804e3a1008]
+
+2014-11-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.cat, doc/sudoers.ldap.cat,
+ doc/sudoers.ldap.man.in, doc/sudoers.ldap.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, doc/sudoreplay.cat,
+ doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in, doc/visudo.cat,
+ doc/visudo.man.in, doc/visudo.mdoc.in:
+ Reference bugzilla.sudo.ws
+ [7dc11bbe6f13]
+
+2014-11-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ sync
+ [da17d5a611ce]
+
+2014-11-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Require that a digest be specified with a real command, not an alias
+ or pseudo-command. Found via a crash by afl.
+ [55f6166cab63]
+
+ * NEWS:
+ sync
+ [4b31247735c4]
+
+ * MANIFEST, doc/CONTRIBUTORS, plugins/sudoers/po/fr.mo,
+ plugins/sudoers/po/fr.po:
+ French translation for sudoers from translationproject.org.
+ [5c592350c4b0]
+
+2014-11-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c, src/exec_pty.c, src/tgetpass.c:
+ Defer registration of the SIGCHLD handler until just before we exec
+ the command. Fixes a problem where pam_gnome_keyring installs its
+ own SIGCHLD handler and may not restore the original one. As a
+ result, we now have to explicitly wait for the askpass helper to
+ finish. Bug #657
+ [f499500fef71]
+
+2014-11-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ Mention sssd support in the sudoers.ldap manual and cross-reference
+ sssd-sudo(5).
+ [32f84fbf210c]
+
+2014-11-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS:
+ Reorder an entry.
+ [5d15735294f1]
+
+2014-11-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, lib/util/Makefile.in, plugins/group_file/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/Makefile.in:
+ Prevent cppcheck from getting confused by our compat definition of
+ the va_copy macro for pre-C99.
+ [61d94525be2e]
+
+2014-11-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog_path.c:
+ Fix potential NULL pointer deref found by cppcheck.
+ [668967e031e0]
+
+ * plugins/sudoers/alias.c:
+ Quiet a cppcheck false positive.
+ [35a16ae4660c]
+
+ * lib/util/sudo_debug.c:
+ If there are multiple outputs, ap will be re-used so make a copy and
+ operate on it instead.
+ [f4f19df43c93]
+
+ * src/hooks.c:
+ Fix typo in hook return value check.
+ [b12839dc6e78]
+
+ * NEWS:
+ Mention visudo use of sudoers plugin args to set default sudoers
+ file name and owner/mode.
+ [7f2733b53431]
+
+ * NEWS:
+ Mention fix for bug #678
+ [7f7a6d8b985b]
+
+2014-11-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ In set_fqdn() we neeed to set user_runhost/user_srunhost at the same
+ time we set user_host/user_shost since that is what
+ hostlist_matches() uses. Bug #678
+ [4f75b01d4884]
+
+2014-11-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/hooks.c:
+ Do not call sudo_warnx() on invalid value from the env hook
+ functions as the printf() family may call getenv() for locale
+ reasons.
+ [547fc25acb7c]
+
+ * doc/sudo.conf.mdoc.in, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudo_plugin.man.in, doc/sudoers.cat, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in, doc/sudoreplay.mdoc.in, doc/visudo.cat,
+ doc/visudo.man.in, doc/visudo.mdoc.in:
+ No need to keep specifying ".Nm foo" since the Nm macro remembers
+ the argument it was first called with and uses it if none is
+ specified. Also fix a few minor formatting errors and regen bulleted
+ lists in the .man.in files.
+ [d2669e94add4]
+
+ * doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in:
+ Add sudo.conf to SEE ALSO and rename section on sudo.conf
+ [d4cc8ad2c2b4]
+
+ * doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in:
+ Mention sudo.conf use for debugging
+ [9393fb061bcd]
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo_plugin.cat,
+ doc/sudoers.cat, doc/sudoers.ldap.cat, doc/sudoers.man.in,
+ doc/sudoreplay.cat:
+ regen
+ [1d34d21b2136]
+
+ * doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in:
+ Document sudo.conf usage now that visudo will parse the sudoers
+ arguments.
+ [78a413c019a9]
+
+2014-11-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo.c:
+ Use sudoers.so args from sudo.conf to set sudoers_file, sudoers_uid,
+ sudoers_gid, and sudoers_mode in visudo.
+ [1c7408b5ff7e]
+
+ * plugins/sudoers/visudo.c:
+ Use sudoers_file, sudoers_uid, sudoers_gid, and sudoers_mode symbols
+ from toke.l instead of the upper case defines.
+ [21ba15518c7d]
+
+ * lib/util/Makefile.in, lib/zlib/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in:
+ Use SSP_LDFLAGS when creating shared objects.
+ [2428de97d2c2]
+
+ * lib/util/Makefile.in:
+ We only build .lo (not .o) files for libsudo_util
+ [2c1e0475cddc]
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po, po/cs.mo,
+ po/cs.po, po/da.mo, po/da.po, po/de.mo, po/de.po, po/eo.mo,
+ po/eo.po, po/fi.mo, po/fi.po, po/it.mo, po/it.po, po/nb.mo,
+ po/nb.po, po/pl.mo, po/pl.po, po/pt_BR.mo, po/pt_BR.po, po/ru.mo,
+ po/ru.po, po/uk.mo, po/uk.po, po/vi.mo, po/vi.po, po/zh_CN.mo,
+ po/zh_CN.po:
+ Sync with translationproject.org
+ [e51055fdffe1]
+
+2014-11-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ sync
+ [aab14a9942e0]
+
+2014-11-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c, src/exec_pty.c:
+ Make sure that SIGCHLD is not treated as a user-generated signal in
+ which case it could be ignored. Bug #676
+ [a4caaaaa47a8]
+
+2014-10-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.ac, lib/util/mktemp.c:
+ Use arc4random() for mkstemp/mkdtemp if available. If not, try to
+ seed from /dev/urandom before falling back to the gettimeofday seed.
+ [7a7096ab82c9]
+
+ * lib/util/sudo_debug.c:
+ Use a static buffer for sudo_debug_execve2() if possible.
+ [abf1fd5891ab]
+
+2014-10-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, ltmain.sh, m4/libtool.m4, m4/ltoptions.m4, m4/ltsugar.m4,
+ m4/ltversion.m4, m4/lt~obsolete.m4:
+ Update to libtool 2.4.3 + HP-UX patches
+ [9ddfd96f3bea]
+
+2014-10-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac, include/sudo_compat.h, lib/util/mktemp.c:
+ If a system lacks mkdtemp() or mkstemps(), use our own mkdtemp() and
+ mkstemps(). Previously we only exposed the missing one but since the
+ guts are the same we might as well use them.
+ [12d4ac64462f]
+
+ * src/env_hooks.c:
+ Mark the putenv(), setenv() and unsetenv() symbols as global, not
+ hidden. Fixes a mismatch where a plugin (or its loaded dso) would
+ call setenv() to set a variables but be unable to find it later with
+ getenv().
+ [96127ac4bbb3]
+
+2014-10-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ Fix install-nls target from builddir.
+ [da63bc37f6c5]
+
+ * Makefile.in:
+ Fix dependency on sudo.pp, it needs to relative to srcdir.
+ [c76088da98e8]
+
+ * src/sesh.c:
+ Adapt to new debug subsystem registration.
+ [8e13b349b44b]
+
+2014-10-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/zlib/Makefile.in, lib/zlib/zlib.exp:
+ Add missing zlib.exp file and common LT_LDFLAGS Makefile.in.
+ [0bc0092d3e03]
+
+ * lib/util/sudo_conf.c:
+ Fix path settings broken in rev 9731.
+ [2b33916eb287]
+
+ * MANIFEST, lib/util/regress/sudo_conf/test4.err.ok:
+ Adjust regress test now that boolean settings display an error for
+ invalid input.
+ [73a7365f492e]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoers_debug.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Add sudoers_debug_deregister() and use it instead of calling
+ sudo_debug_deregister() directly.
+ [819b0e08196e]
+
+ * configure, configure.ac, lib/util/Makefile.in, lib/zlib/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in:
+ Use AC_PROG_AWK
+ [945cf6deb18d]
+
+ * NEWS:
+ Mention shared zlib.
+ [094bdada1106]
+
+ * MANIFEST:
+ Add lib/zlib/zlib.exp
+ [7b5011e3eea9]
+
+ * INSTALL, configure, configure.ac, lib/zlib/Makefile.in,
+ lib/zlib/zconf.h.in:
+ Add support for installing a shared zlib
+ [6875ab6ca44f]
+
+ * lib/util/Makefile.in:
+ fix comment typo
+ [35c3dda27eec]
+
+ * configure, configure.ac, lib/zlib/Makefile.in:
+ Newer zlib uses HAVE_HIDDEN to turn on symbol hiding so we don't
+ need to disable it with NO_VIS.
+ [b3eee86f015f]
+
+ * po/sudo.pot:
+ regen
+ [687bc1ea88ac]
+
+ * configure.ac, include/sudo_debug.h, lib/util/sudo_debug.c,
+ lib/util/util.exp.in:
+ Version the symbols for sudo_debug.c now that the API is stable.
+ [873850a062a8]
+
+2014-10-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/sudo_conf.c:
+ Go back to parsing sudo.conf in place for settings and paths and
+ improve debugging info for unsupported entries and parse errors.
+ [264e1f7d6551]
+
+ * include/sudo_conf.h, lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/sudo_conf.c, lib/util/util.exp.in,
+ plugins/sudoers/sudoers_debug.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ src/load_plugins.c, src/sudo.c, src/sudo_plugin_int.h:
+ Add a flag argument to sudo_conf_read() so we can decide which bits
+ get parsed. This lets us parse Debug statements first and init the
+ debug subsystem early.
+ [56dbf1e671de]
+
+2014-10-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/zlib/gzguts.h:
+ Include stdio.h after zlib.h, not before. We need the large file
+ defines to come first.
+ [b42b53d10252]
+
+ * doc/LICENSE, lib/zlib/compress.c, lib/zlib/crc32.c,
+ lib/zlib/crc32.h, lib/zlib/deflate.c, lib/zlib/deflate.h,
+ lib/zlib/gzguts.h, lib/zlib/gzlib.c, lib/zlib/gzread.c,
+ lib/zlib/gzwrite.c, lib/zlib/infback.c, lib/zlib/inffast.c,
+ lib/zlib/inflate.c, lib/zlib/inftrees.c, lib/zlib/trees.c,
+ lib/zlib/uncompr.c, lib/zlib/zconf.h.in, lib/zlib/zlib.h,
+ lib/zlib/zutil.c, lib/zlib/zutil.h:
+ Update zlib to version 1.2.8
+ [f95280e0448d]
+
+ * configure, configure.ac:
+ Don't add -Wold-style-definition to CFLAGS as it causes problems
+ with 3rd party libraries such as zlib.
+ [1d7613d1c177]
+
+ * src/load_plugins.c:
+ Free up plugin info structs after converting to plugin containers.
+ [1168e873d778]
+
+ * INSTALL, MANIFEST, Makefile.in, configure, configure.ac,
+ doc/Makefile.in, doc/TROUBLESHOOTING, doc/UPGRADE, doc/sample.pam,
+ doc/sample.sudo.conf, doc/sample.sudoers, doc/sample.syslog.conf,
+ examples/Makefile.in, examples/pam.conf, examples/sudo.conf,
+ examples/sudoers, examples/syslog.conf, sudo.pp:
+ Move sample.* files to a sudo examples dir
+ [b53e3df56c66]
+
+ * sudo.pp:
+ Fix a packaging problem with the sudoedit man page link on Debian.
+ [8ad77a37048e]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/policy.c:
+ Initialize the debug subsystem in sudoers early. Currently this
+ means iterating over the settings list twice.
+ [93b12ea08405]
+
+ * lib/util/sudo_debug.c:
+ No need to convert sudoedit -> sudo in sudo_debug_get_instance() as
+ we store the actual program name and only do the sudoedit -> sudo
+ conversion when reading the sudo.conf file. Fixes debugging when
+ invoked as sudoedit.
+ [535c01d83b14]
+
+ * lib/util/sudo_conf.c, lib/util/sudo_debug.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/policy.c, src/exec_pty.c,
+ src/load_plugins.c, src/sudo.c, src/sudo_plugin_int.h:
+ In the plugin registers with the debug framework at open time, the
+ sudo front-end will now set the default debug instance appropriately
+ before calling into the plugin. This means the plugin no longer
+ needs to do the sudo_debug_set_default_instance() dance.
+ [10dd45a7884f]
+
+ * Makefile.in:
+ Remove duplicate -U__NBBY in CPPCHECK_OPTS
+ [ad518cb36279]
+
+2014-10-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ Older shells don't support unset.
+ [8762e40871ab]
+
+ * configure, configure.ac, include/sudo_compat.h,
+ lib/util/inet_ntop.c, src/net_ifs.c:
+ Fix inet_ntop() replacement on older systems without it. We only
+ expose the prototype for net_ifs.c due to the use of socklen_t.
+ [18b95ca378ab]
+
+ * lib/util/sudo_debug.c:
+ Dynamically allocate debug_fds bitmap and realloc as needed.
+ [e858199414f6]
+
+ * Makefile.in, include/sudo_debug.h, lib/util/Makefile.in,
+ lib/util/sudo_debug.c, plugins/group_file/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/sudoers/sudoers_debug.c, plugins/sudoers/sudoers_debug.h,
+ plugins/system_group/Makefile.in, src/Makefile.in, src/exec.c:
+ Use generic bitmap macros instead of select-style fd_set.
+ [c382edc413be]
+
+ * lib/util/sudo_debug.c:
+ Replace sudo_debug_num_instances with sudo_debug_max_instance
+ [12625fd174a4]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/policy.c:
+ Don't call into the debug subsystem after we've deregistered the
+ plugin's instance.
+ [fca7279d2f40]
+
+ * lib/util/sudo_debug.c:
+ Only fill in subsystem_ids[] for the instance if the caller passed
+ in an array for it. If the caller only wants the default subsystems
+ we don't actually need ids[].
+ [07939da6d3a5]
+
+ * lib/util/Makefile.in:
+ Link with -ldl if needed when built with --disable-shared-libutil/
+ [542eeffaf57d]
+
+ * src/regress/ttyname/check_ttyname.c:
+ Fix includes order.
+ [ddd58edba5af]
+
+ * lib/util/util.exp.in:
+ Remove extra newline mistakenly introduced in rev 9682.
+ [36a40e308bbc]
+
+ * plugins/sudoers/Makefile.in:
+ Fix typo in unset.
+ [2c5fbe4c9a54]
+
+ * plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c, src/sesh.c:
+ Set debug instance for standalone programs.
+ [306225438408]
+
+ * plugins/sudoers/bsm_audit.c, plugins/sudoers/linux_audit.c,
+ src/net_ifs.c:
+ Fix compilation issues, fallout from the debug changes.
+ [aff5bb3d0322]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ regen
+ [bbb69f299d1f]
+
+ * configure, configure.ac:
+ Sudo 1.8.12
+ [8d9b15c1de44]
+
+ * NEWS:
+ Update with debug system changes and revent bug fixes.
+ [44133de1dee2]
+
+ * include/sudo_debug.h, lib/util/sudo_conf.c, lib/util/sudo_debug.c,
+ plugins/sudoers/sudoers_debug.c, plugins/sudoers/sudoers_debug.h:
+ When registering with the debug subsystem, the caller now passes in
+ an arrary of ints that gets filled in with the subsytem IDs to be
+ used in debug_decl.
+ [80e80ba194f7]
+
+ * plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ sudoers_debug_instance is now included in libparsesudoers so we
+ don't need to declare it here.
+ [a56f79e6fcf8]
+
+2014-10-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, include/sudo_debug.h, lib/util/sudo_debug.c,
+ lib/util/ttysize.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/alias.c, plugins/sudoers/audit.c,
+ plugins/sudoers/auth/afs.c, plugins/sudoers/auth/aix_auth.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/dce.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/passwd.c,
+ plugins/sudoers/auth/rfc1938.c, plugins/sudoers/auth/secureware.c,
+ plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/base64.c,
+ plugins/sudoers/boottime.c, plugins/sudoers/bsm_audit.c,
+ plugins/sudoers/check.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/env.c, plugins/sudoers/find_path.c,
+ plugins/sudoers/getspwuid.c, plugins/sudoers/goodpath.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/hexchar.c,
+ plugins/sudoers/interfaces.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_path.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logwrap.c, plugins/sudoers/match.c,
+ plugins/sudoers/match_addr.c, plugins/sudoers/parse.c,
+ plugins/sudoers/policy.c, plugins/sudoers/prompt.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/redblack.c, plugins/sudoers/set_perms.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/sudoers_debug.c, plugins/sudoers/sudoers_debug.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/visudo.c,
+ plugins/sudoers/visudo_json.c:
+ The sudoers plugin now defines its own list of debugging subsystem
+ names and defines.
+ [e85d0375e059]
+
+ * MANIFEST, include/sudo_debug.h, lib/util/aix.c, lib/util/event.c,
+ lib/util/event_poll.c, lib/util/event_select.c, lib/util/gidlist.c,
+ lib/util/key_val.c, lib/util/lbuf.c, lib/util/locking.c,
+ lib/util/parseln.c, lib/util/secure_path.c, lib/util/setgroups.c,
+ lib/util/strtobool.c, lib/util/strtoid.c, lib/util/strtomode.c,
+ lib/util/sudo_conf.c, lib/util/sudo_debug.c, lib/util/term.c,
+ lib/util/ttysize.c, lib/util/util.exp.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/alias.c,
+ plugins/sudoers/audit.c, plugins/sudoers/auth/afs.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/base64.c, plugins/sudoers/boottime.c,
+ plugins/sudoers/bsm_audit.c, plugins/sudoers/check.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/env.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/getspwuid.c,
+ plugins/sudoers/goodpath.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/hexchar.c, plugins/sudoers/interfaces.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_path.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/linux_audit.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logwrap.c,
+ plugins/sudoers/match.c, plugins/sudoers/match_addr.c,
+ plugins/sudoers/parse.c, plugins/sudoers/policy.c,
+ plugins/sudoers/prompt.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/pwutil_impl.c, plugins/sudoers/redblack.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoers_debug.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timestamp.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/toke_util.c,
+ plugins/sudoers/visudo.c, plugins/sudoers/visudo_json.c,
+ src/Makefile.in, src/exec.c, src/exec_common.c, src/exec_pty.c,
+ src/get_pty.c, src/hooks.c, src/load_plugins.c, src/net_ifs.c,
+ src/parse_args.c, src/preserve_fds.c,
+ src/regress/ttyname/check_ttyname.c, src/selinux.c, src/sesh.c,
+ src/signal.c, src/solaris.c, src/sudo.c, src/sudo.h,
+ src/sudo_edit.c, src/tgetpass.c, src/ttyname.c, src/utmp.c:
+ Add support for multiple Debug lines per program. Callers may
+ register arbitrary debug facilities or use built-in defaults. We now
+ use separate Debug statements for plugins and programs.
+ [5e553cbbfbb1]
+
+ * MANIFEST, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in, doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, include/sudo_conf.h, include/sudo_debug.h,
+ lib/util/Makefile.in, lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_conf/test7.in,
+ lib/util/regress/sudo_conf/test7.out.ok, lib/util/sudo_conf.c,
+ lib/util/sudo_debug.c, lib/util/util.exp.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/solaris_audit.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudoers.h, src/hooks.c,
+ src/load_plugins.c, src/parse_args.c, src/sudo.c,
+ src/sudo_plugin_int.h:
+ Change how sudo.conf is parsed. We now do a quick parse and then set
+ the values after the entire file has been parsed. This lets us init
+ the debug system earlier. Plugin-specific debug flags are now stored
+ in struct plugin_info and struct plugin_container and passed to the
+ plugin via one or more debug_flags settings.
+ [62fb1102e1e2]
+
+ * src/parse_args.c, src/sudo.c, src/sudo.h:
+ Return settings from parse_args as struct sudo_settings and format
+ for the plugin at plugin open time. This will allow for additional,
+ plugin-specific settings to be added to the array.
+ [167929871b94]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, include/sudo_plugin.h, src/load_plugins.c,
+ src/sudo.c, src/sudo_plugin_int.h:
+ Pass plugin path in the settings array.
+ [45bc2d087115]
+
+ * plugins/sudoers/parse.c:
+ Remove an unneeded NULL check to quiet a cppcheck warning.
+ [64cb92122658]
+
+2014-10-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ Set locale to C for visudo and testsudoers regression tests. Bug
+ #672
+ [adf7997a0a65]
+
+2014-10-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/linux_audit.c:
+ Fix logic bug. We only want to return -1 from linux_audit_open()
+ when audit_open() fails and errno is not one of EINVAL,
+ EPROTONOSUPPORT, or EAFNOSUPPORT. For those errno values, we return
+ AUDIT_NOT_CONFIGURED which is not a fatal error. Bug #671
+ [6f0d8f1c7648]
+
+2014-10-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Add back fix for Bug #663
+ [a3dfc76ee776]
+
+2014-10-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ The older style bash function exporting is not used by post-
+ shellshock versions of bash.
+ [223efe328e86]
+
+ * plugins/sudoers/env.c:
+ Apple uses a different variant of the BASH_FUNC prefix for bash
+ functions.
+ [ea13c8c2a716]
+
+2014-10-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Remove change that is part of 1.8.12 not 1.8.11p1
+ [8fdad4c4f314]
+
+ * NEWS, configure, configure.ac:
+ Update for sudo 1.8.11p1
+ [80e9898f7c04]
+
+ * src/regress/ttyname/check_ttyname.c:
+ Only check stdin for the tty and avoid the check entirely if we
+ don't have a way to get the tty from the kernel. Bug #643
+ [deb799e16416]
+
+ * lib/util/sudo_debug.c:
+ Make a copy of ap in sudo_debug_vprintf2() in case the static buffer
+ is not big enough and we need to call vasprintf().
+ [a5d32b9d63be]
+
+ * src/sudo.c:
+ Avoid comparing new cwd with old one if getcwd() failed. Bug #670
+ [e99093578ca7]
+
+ * plugins/sudoers/env.c:
+ Fix debugging printout output for env_should_keep()
+ [a9e7ea4b6751]
+
+2014-10-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, include/Makefile.in:
+ Use INSTALL_OWNER instead of -O/-G flags so we can work with the
+ autotools install-sh too. Bug #669
+ [a5f87f6a52b7]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c:
+ Move sudo_printf to policy.c to match sudo_conv.
+ [f2d6065c3daf]
+
+2014-10-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, include/sudo_fatal.h, lib/util/Makefile.in,
+ lib/util/fatal.c, lib/util/sudo_printf.c, lib/util/util.exp.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/sudo_printf.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ src/conversation.c, src/sudo.c, src/sudo_plugin_int.h:
+ Add sudo_warn_set_conversation() to specify a conversation function
+ to use for warn/fatal. If no conversation function is specified, the
+ standard error will be used. We now only need sudo_printf() for
+ things that use the parser.
+ [d6049e53e3e3]
+
+2014-10-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Use correct names when referring to subsections in the sudoers
+ manual.
+ [7a016916f0ab]
+
+2014-10-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, config.h.in, configure, configure.ac,
+ lib/util/inet_ntop.c, src/net_ifs.c:
+ Use inet_ntop() instead of inet_ntoa() and include a version for
+ systems that are missing it.
+ [1a1a70dba9c0]
+
+2014-10-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ Fix detection of functions in network libs like -lsocket, -lnsl and
+ -linet when we have already added those libs to NET_LIBS. Fixes a
+ problem where inet_pton() was not detected on Solaris.
+ [27e10183649e]
+
+ * NEWS:
+ Mention --disable-shared-libutil fix.
+ [7efe70688237]
+
+ * src/Makefile.in:
+ Always use --tag=disable-static to avoid installing a static
+ sudo_noexec.
+ [5d7d58879f99]
+
+ * configure, configure.ac, lib/util/Makefile.in,
+ plugins/sudoers/Makefile.in:
+ Instead of building libutil statically for --disable-shared-libutil,
+ just treat it as a convenience library. Do the same with sudoers for
+ --enable-static-sudoers. Fixes link errors on Solaris among others
+ when --disable-shared-libutil is used.
+ [c5357fe78ab7]
+
+ * configure, configure.ac, lib/util/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in:
+ Remove LT_LDMAP and LT_LDOPT and just use LT_LDEXPORTS for the
+ compiler-specific option to restrict symbol exporting.
+ [09e8dab6f528]
+
+ * src/preload.c:
+ Include sys/types.h to get gid_t, etc used in sudo_compat.h. Fixes a
+ build issue on Solaris.
+ [b8917967df41]
+
+2014-09-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/regress/ttyname/check_ttyname.c:
+ Fix cust & pasto in error message when there is a mismatch between
+ the sudo and libc ttys. From Diego Elio Petteno'. Bug #643
+ [87d5f1a49535]
+
+2014-09-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/env.c:
+ Add BASH_FUNC_* to environment blacklist for newer-style bash
+ functions.
+ [b6e66c4a782e]
+
+ * Makefile.in:
+ Pull additional password prompts out of mkpkg instead of hard-coding
+ them.
+ [d2a6da883b34]
+
+ * NEWS:
+ Add post-1.8.11 changes
+ [11169ace8fa4]
+
+ * Makefile.in, configure.ac, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/po/sudoers.pot:
+ Add a space after "Password:" in default password prompt so it is
+ easier to read when pwfeedback is enabled.
+ [a7750d845b5b]
+
+ * plugins/sudoers/auth/sudo_auth.c:
+ Simplify how we count the password tries
+ [71b9f2021561]
+
+ * plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c:
+ Block SIGINT and SIGQUIT while verifying passwords so that
+ authentication modules that use sleep() are not interrupted. If the
+ user interrupted authentication, exit the loop.
+ [1cfafd7fcb13]
+
+ * configure, configure.ac:
+ Remove Convex support; it is not modern enough to run sudo 1.8.
+ [c3bdfbb2ee11]
+
+ * configure, configure.ac:
+ Only check for -lshadow if we haven't already found getspnam() in
+ libc. Rather than treat this specially, just add -lshadow as another
+ place to search in addition to -lgen.
+ [fdf06757f25d]
+
+2014-09-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/sudo_auth.c:
+ If all authentication methods fail init/setup, fail with an error.
+ [4cd0481bf05e]
+
+ * plugins/sudoers/auth/sudo_auth.c:
+ Move pass_warn() so that it is defined before it is called().
+ [6ea697e89fef]
+
+2014-09-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pp:
+ Remove duplicate Requires: line in generated rpm spec file.
+ [335703b110c7]
+
+ * pp:
+ In pp_files_expand() set _target to be empty. Fixes a problem with
+ Solaris sh where simply using typeset doesn't causes the variable to
+ be treated as local so we can inadvertantly inherit a value from a
+ previous call.
+ [f3cecca3c7b0]
+
+2014-09-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ Fix version for release.
+ [39f6a2e9a098]
+
+2014-09-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac, pathnames.h.in:
+ Only redefine _PATH_BSHELL on AIX if we included paths.h.
+ [2dd4e808f69f]
+
+ * NEWS:
+ Bug 661
+ [7f2b278086b2]
+
+ * pathnames.h.in, src/exec_common.c, src/sudo.c:
+ On AIX, _PATH_BSHELL is /usr/bin/bsh but we want to use /usr/bin/sh
+ (which is usually ksh). This makes sudo's behavior when executing a
+ shell without the #! magic number match execvp() on AIX.
+ [2b438ff99991]
+
+ * pathnames.h.in:
+ Whitespace changes.
+ [107f66ecfa54]
+
+ * configure, m4/sudo.m4:
+ Prefer /usr/bin/sh to /bin/sh to match modern systems.
+ [9e2ccb5b239f]
+
+ * NEWS, lib/util/Makefile.in:
+ Don't use SSP_CFLAGS or PIE_CFLAGS when building mksiglist/mksigname
+ as they are built with the host compiler which may be different when
+ cross-compiling. From Gustavo Zacarias. Bug 662.
+ [f1a6d58c0baa]
+
+2014-09-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po, po/cs.mo,
+ po/cs.po, po/de.mo, po/de.po, po/eo.mo, po/eo.po, po/fi.mo,
+ po/fi.po, po/nb.mo, po/nb.po, po/pl.mo, po/pl.po, po/pt_BR.mo,
+ po/pt_BR.po, po/ru.mo, po/ru.po, po/sr.mo, po/sr.po, po/uk.mo,
+ po/uk.po, po/vi.mo, po/vi.po, po/zh_CN.mo, po/zh_CN.po:
+ Sync with translationproject.org
+ [588c41d2eab5]
+
+2014-09-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudo_nss.c:
+ Make sure we can't insert an nss entry in the list that has already
+ been used before.
+ [b5fab945991b]
+
+ * plugins/sudoers/visudo_json.c:
+ Use correct gettext macro with sudo_warnx()
+ [0a532986b016]
+
+ * NEWS:
+ Make nsswitch.conf bug fix description more accurrate. It affects
+ the "files" nsswitch source too.
+ [a29cce3a3ee9]
+
+ * NEWS:
+ Mention nsswitch.conf duplicate entry fix.
+ [f8a45b59a577]
+
+2014-09-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/parse.c, plugins/sudoers/sudoers.h:
+ Make sudoers file nsswitch functions static to parse.c since they
+ are self-contained.
+ [cf22385d0659]
+
+ * plugins/sudoers/sudo_nss.c:
+ Fix infinite loop when mulitple sudoers entries are present in
+ nsswitch.conf. From Daniel Kopecek.
+ [e773e0eee736]
+
+2014-09-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Fix for bug #660
+ [e25192ad79cc]
+
+ * src/get_pty.c:
+ Fix compilation on systems without openpty(), _getpty() or
+ grantpt(). From Vasilyy Balyasnyy
+ [897280412e3e]
+
+2014-09-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/conversation.c:
+ Remove remaining use of SUDO_CONV_DEBUG_MSG.
+ [4ee756b687ea]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, include/sudo_plugin.h:
+ SUDO_CONV_DEBUG_MSG is no longer supported.
+ [7bf46cf06578]
+
+ * doc/sudo.conf.cat, doc/sudoers.cat:
+ regen
+ [5bff0d4d3956]
+
+ * include/sudo_debug.h, lib/util/sudo_debug.c, lib/util/sudo_printf.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/policy.c:
+ There is no longer a reason for the plugin to init the debug
+ subsystem itself. It will always be initialized by the front-end if
+ needed.
+ [970dd80a9e3c]
+
+ * include/sudo_alloc.h, include/sudo_compat.h, include/sudo_fatal.h:
+ Add function arg names to prototypes where missing.
+ [e78dc4c48521]
+
+ * lib/util/alloc.c:
+ Remove obsolete definition of SIZE_T which is now handled by
+ sudo_compat.h and rename the format arg to fmt in
+ sudo_evasprintf_v1() for consistency with sudo_easprintf_v1().
+ [72c0fc5e5114]
+
+ * src/parse_args.c:
+ If we were invoked with any name ending in "edit", treat as
+ sudoedit.
+ [d307572f08bc]
+
+2014-09-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * po/sudo.pot:
+ regen
+ [31c115ffbba8]
+
+ * src/exec.c, src/exec_pty.c, src/signal.c:
+ Check return value of sigaction(), even though it should never fail.
+ [75c578e6a07c]
+
+2014-09-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/Makefile.in, src/Makefile.in:
+ regen
+ [2fcb390e8e89]
+
+ * MANIFEST, plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/parser/check_hexchar.c:
+ Add hexchar unit test
+ [de65e0ded4a2]
+
+ * plugins/sudoers/regress/parser/check_addr.c:
+ Avoid division by zero if there was no test data.
+ [de3324077ba0]
+
+2014-09-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/event.c:
+ Remove confusing comment.
+ [ee1765a06b94]
+
+ * lib/util/sudo_debug.c:
+ Use a stack buffer for the debug message when possible, most are
+ small.
+ [945fb94a7aaf]
+
+2014-09-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/ca.mo, plugins/sudoers/po/ca.po, po/ca.mo,
+ po/ca.po:
+ Sync with translationproject.org
+ [661d536a7599]
+
+2014-08-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c:
+ Convert a debug printf to a user-visible warning.
+ [c3866eaea3ec]
+
+ * include/sudo_fatal.h, include/sudo_util.h, lib/util/fatal.c:
+ Move sudo_printf extern to sudo_util.h
+ [50275ef999e9]
+
+ * include/sudo_fatal.h, include/sudo_lbuf.h, lib/util/fatal.c,
+ lib/util/lbuf.c:
+ Some versions of the HP C Compiler don't export functions that take
+ function pointers as arguments unless a typedef is used.
+ [97cc0525dbd7]
+
+ * include/sudo_lbuf.h:
+ Work around a bug in the HP C compiler.
+ [5c902aefeba6]
+
+ * lib/util/lbuf.c:
+ Don't need sudo_fatal.h
+ [bccfe4df4794]
+
+2014-08-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * po/da.mo, po/da.po:
+ Sync with translationproject.org
+ [7910e3fc0f3e]
+
+ * src/exec.c:
+ Remove signal_event from evbase before calling sudo_ev_loopexit()
+ when the command has exited or been killed. It is possible that we
+ could receive another signal on the pipe if they are delivered out
+ of order.
+ [b8ed1c9482b4]
+
+2014-08-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c:
+ Treat EOF on signal pipe (which should never happen) as ECONNRESET.
+ [eb57e9047a2c]
+
+ * include/sudo_event.h, lib/util/event.c, src/exec_pty.c:
+ Don't allow sudo_ev_loopcont() to override sudo_ev_loopexit()
+ [b6b53eacbc61]
+
+ * include/sudo_event.h, lib/util/event.c, lib/util/event_poll.c,
+ lib/util/event_select.c:
+ Add some internal convenience functions.
+ [b01063d82347]
+
+2014-08-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Fix osrelease sed expression. It wasn't matching distros with a
+ single digit version such as sles9.
+ [44f3e9b7e6c0]
+
+ * plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po, po/cs.mo,
+ po/cs.po, po/de.mo, po/de.po, po/eo.mo, po/eo.po, po/fi.mo,
+ po/fi.po, po/it.mo, po/it.po, po/nb.mo, po/nb.po, po/pl.mo,
+ po/pl.po, po/pt_BR.mo, po/pt_BR.po, po/ru.mo, po/ru.po, po/uk.mo,
+ po/uk.po, po/vi.mo, po/vi.po, po/zh_CN.mo, po/zh_CN.po:
+ Sync with translationproject.org
+ [5b2c6063db75]
+
+ * plugins/sudoers/iolog.c:
+ Return -1 from logging functions if we get a write error.
+ [a3ae43d54101]
+
+ * NEWS:
+ Mention I/O plugin changes.
+ [0bd2e99fe87a]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, include/sudo_plugin.h, src/exec_pty.c:
+ Change behavior when plugin I/O logging function returns 0 or -1.
+ For -1 (error) return, we now kill the command and disable the I/O
+ logging function that returned the error. For a 0 (reject) return,
+ we no longer display the rejected output to the user's terminal. The
+ plugin API revision is now 1.6.
+ [27bb504860f3]
+
+ * doc/sudoers.cat:
+ regen to fix version.
+ [641ea29b7dd3]
+
+ * plugins/sample/sample_plugin.c:
+ Add trivial dirty word check to the sample output logging function.
+ [a14494b87b4d]
+
+2014-08-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Update for 1.8.11b2
+ [72ac1f26ba78]
+
+ * src/sudo_edit.c:
+ Fix restoration of effective uid/gid in command_details. This masked
+ the effects an unset (really zero) egid. Bug 656
+ [b75eed459386]
+
+ * src/sudo.c:
+ Set runas egid to the same value as runas gid if egid not specified
+ by the plugin. Only affects new files created by sudoedit. Bug #656
+ [f2daabba4912]
+
+ * src/sudo_edit.c:
+ Don't leak temp fd in sudo_edit_copy_tfiles(). Fix fd leak in error
+ path in sudo_edit_copy_tfiles().
+ [465d6a79b5cf]
+
+2014-08-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ fix typo
+ [a4659abcbc1d]
+
+ * src/signal.c:
+ We write an unsigned char, not an int, to the signal pipe.
+ [fae4217be608]
+
+2014-08-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo_edit.c:
+ Sprinkle some debugging around uid/gid setting in sudoedit.
+ [15e4a337f0b0]
+
+ * src/sesh.c, src/sudo.c, src/sudo.h, src/sudo_edit.c,
+ src/sudo_exec.h:
+ Make sudoedit work with SELinux RBAC. Adapted from RedHat patches
+ (Daniel Kopecek) but made to behave a bit more like the non-SELinux
+ bits.
+ [8f3f7969220f]
+
+ * src/sudo_edit.c:
+ Refactor code that copies temp files into separate functions.
+ [b1057f4bee87]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in:
+ Fix typo, .em should be .Em
+ [ec28aa3bdd6a]
+
+2014-08-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sesh.c:
+ Add missing call to initprogname().
+ [71040679765f]
+
+ * lib/util/sudo_debug.c, lib/util/sudo_printf.c:
+ Don't recurse infinitely until we blow the stack when the debug file
+ can't be opened in the front-end. The conversation-type debug mode
+ will be removed in the future.
+ [38cd1a6343c2]
+
+2014-08-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Only use the first two digits of the version number. Fixes a problem
+ on RHEL 7 which has version numbers like 7.0.1406
+ [272727fd57fb]
+
+ * plugins/sudoers/linux_audit.c:
+ Fix return value when kernel has no audit support.
+ [7ca1c9857058]
+
+ * lib/util/progname.c:
+ remove unused label
+ [4179ea1ffa3a]
+
+2014-08-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aclocal.m4, autogen.sh:
+ Update to automake 1.14 (no code changes).
+ [5e04db4f7c5d]
+
+2014-08-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document the interaction between sudoers environment handling and
+ the pam_env module.
+ [bd56868f078c]
+
+ * plugins/sudoers/env.c:
+ Don't allow pam_env to overwrite existing variables when env_reset
+ is disabled unless the variables match the black list and would
+ normally be removed. It may just be better to never overwrite when
+ env_reset is disabled.
+ [e0ae88fce535]
+
+2014-08-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ Update year range to include 2014
+ [6b3b5f3fa791]
+
+2014-08-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/Makefile.in:
+ Remove regress .err files in distclean target.
+ [d66a4f1db130]
+
+ * lib/util/Makefile.in, plugins/group_file/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in:
+ Remove generated files for linker as part of distclean.
+ [5d1bf6c32c6b]
+
+ * .hgignore:
+ Ignore .out and .err files in lib/util regress
+ [9f4d91e77c0f]
+
+ * NEWS:
+ Add additional 1.8.11 changes and fix typos.
+ [7980e2abb6ea]
+
+ * configure, configure.ac, plugins/sudoers/Makefile.in:
+ Avoid building/running the check_symbols test program unless we are
+ building a shared sudoers plugin.
+ [a6bde1a12111]
+
+ * plugins/sudoers/Makefile.in, src/Makefile.in:
+ Remove two instances of -no-fast-install that were missed before.
+ [8a2c89cdf252]
+
+ * INSTALL, NEWS, configure, configure.ac, lib/util/Makefile.in:
+ Add --disable-shared-libutil configure option. It may only be used
+ in conjunction with the --enable-static-sudoers option.
+ [e19c71464399]
+
+2014-08-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/Makefile.in:
+ Remove noop man.sed files Use full path instead of $@.in when
+ calling config.status with --file=-
+ [53c69928427e]
+
+ * src/preserve_fds.c:
+ Fix "sudo -C" when we have internal fds to preserve from
+ closefrom().
+ [942db66345ea]
+
+2014-08-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/env.c:
+ Add explicit support for matching the full environment string
+ (name=value). Bash functions may now be preserved for full matches,
+ but not for name-only matches.
+ [f4d816e11f66]
+
+2014-08-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * .hgignore:
+ Ignore lib/util/util.exp
+ [e08306ca6a6d]
+
+2014-07-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ Fix exporting of asprintf/vasprintf symbols.
+ [5ff59bdeb501]
+
+ * configure, configure.ac:
+ Don't export getaddrinfo symbols if we found the function in a
+ library.
+ [3bf4a5d3cfdb]
+
+ * src/sudo_edit.c:
+ It is now sudo_efree() not efree(). Don't try to free a pointer to
+ garbage on error.
+ [51a1ddaa220d]
+
+ * plugins/sudoers/po/sudoers.pot, po/sudo.pot:
+ Regen .pot files
+ [8c46fe51d32e]
+
+2014-07-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo_edit.c:
+ Plug memory leak, even though we are headed for exit.
+ [e2b28ddffabe]
+
+ * configure, configure.ac, lib/util/Makefile.in,
+ plugins/sudoers/Makefile.in:
+ If getaddrinfo() is missing libsudoutil may need to pull in
+ networking libraries.
+ [4d6724d54927]
+
+ * MANIFEST, configure, configure.ac, include/sudo_compat.h,
+ lib/util/Makefile.in, lib/util/util.exp, lib/util/util.exp.in,
+ m4/sudo.m4:
+ Only include functions in util.exp that are actually in the library.
+ Fixes a problem on Solaris where undefined functions that are listed
+ as exported in the map file result in a link error. Also make sure
+ we use our glob.c if the system is missing glob().
+ [3121ad215f1e]
+
+ * configure, configure.ac:
+ Make sure shadow libs don't end up in LIBS, only SUDOERS_LIBS (and
+ SUDO_LIBS if set_auth_parameters() or initprivs() are present.
+ [fb084b157c76]
+
+ * configure.ac:
+ No need to AC_SUBST HAVE_BSM_AUDIT and HAVE_SOLARIS_AUDIT
+ [5d73ccf3a7b9]
+
+2014-07-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c, src/exec_pty.c, src/sudo_exec.h:
+ Attempt to handle systems with SA_SIGINFO but that lack SI_USER.
+ [0c8b09861ad5]
+
+ * config.h.in, configure, configure.ac, include/sudo_compat.h:
+ Replace use of HAVE_GETCWD with PREFER_PORTABLE_GETCWD. It is safe
+ to assume getcwd() exists, we just need to handle broken ones.
+ [e897223a8f38]
+
+ * config.h.in, configure, configure.ac, plugins/sudoers/Makefile.in:
+ Add check for inet_ntoa() since it may live in libnsl. Make getcwd()
+ replacement private to the SunOS 4 section.
+ [8e2cd0fdd6cd]
+
+ * plugins/sudoers/match.c:
+ Avoid mixing declarations and code for non-C99 compilers.
+ [1fa5cf2356fd]
+
+ * include/sudo_debug.h:
+ For C89, use "const char __func__[]" instead of "const char
+ *__func__".
+ [c4e9f9d6691b]
+
+ * plugins/sudoers/match.c:
+ Fix compilation on systems w/o netgroups.
+ [57deb66ef8ff]
+
+2014-07-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/preserve_fds.c:
+ Back out old workaround for sudoedit hang when debugging was
+ enabled.
+ [f547bf80c436]
+
+ * src/sudo_edit.c:
+ Don't memcpy() the preserved_fds TAILQ as the pointers into the head
+ will be wrong. All we need to do is save the old command details and
+ restore them after calling run_command(). Fixes a hang with sudoedit
+ when debugging is enabled.
+ [84ff8e1f490a]
+
+2014-07-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo.c:
+ The default policy close function should only print an error message
+ if the error_code is non-zero.
+ [2032c9e33e3f]
+
+ * src/preserve_fds.c:
+ If there the preserved fds list is empty, add a new element with
+ TAILQ_INSERT_HEAD instead of TAILQ_INSERT_TAIL to avoid an infinite
+ loop on AIX, Solaris and possibly others when debug mode is active.
+ [63cefe22c515]
+
+ * lib/util/progname.c:
+ Remove support for getting program name via /proc as pr_fname is
+ usually filled in after symbolic links have been processed, even on
+ Solaris.
+ [0460c613753c]
+
+ * lib/util/Makefile.in:
+ Use shlib_enable instead of soext when determining whether to
+ install the library.
+ [d46640a7733c]
+
+ * lib/util/regress/atofoo/atofoo_test.c:
+ Avoid potential division by zero
+ [6411d276a138]
+
+ * lib/util/Makefile.in:
+ Don't link progname test with libsudo_util, just link in progname.lo
+ directly since that is all we need. Avoid a linker issue on darwin.
+ [ee6210ee5cc0]
+
+ * lib/util/progname.c:
+ Remove pstat_getproc() path as pst_ucomm on HP-UX will return the
+ target of a symbolic link and not the name of the link itself. Avoid
+ using pr_fname on AIX for the same reason. Bug 654
+ [36aced8e3714]
+
+ * MANIFEST, lib/util/Makefile.in,
+ lib/util/regress/progname/progname_test.c:
+ Add test for getprogname() and symbolic links; bug 654
+ [fbbe9faeda46]
+
+2014-07-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.conf.cat, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in:
+ Document tracing
+ [cfd7f14d596d]
+
+2014-07-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lib/util/util.exp:
+ sudo_term_{erase,kill} are regular symbols not functions.
+ [3454a9c1328b]
+
+2014-07-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Fix NULL deref if base64_decode returns -1.
+ [d03e207b1bb8]
+
+ * MANIFEST, include/missing.h, include/sudo_compat.h,
+ lib/util/Makefile.in, lib/util/aix.c, lib/util/alloc.c,
+ lib/util/clock_gettime.c, lib/util/closefrom.c, lib/util/event.c,
+ lib/util/event_poll.c, lib/util/event_select.c, lib/util/fatal.c,
+ lib/util/fnmatch.c, lib/util/getaddrinfo.c, lib/util/getcwd.c,
+ lib/util/getgrouplist.c, lib/util/getline.c, lib/util/getopt_long.c,
+ lib/util/gidlist.c, lib/util/glob.c, lib/util/inet_pton.c,
+ lib/util/isblank.c, lib/util/key_val.c, lib/util/lbuf.c,
+ lib/util/locking.c, lib/util/memrchr.c, lib/util/memset_s.c,
+ lib/util/mksiglist.c, lib/util/mksigname.c, lib/util/mktemp.c,
+ lib/util/parseln.c, lib/util/progname.c, lib/util/pw_dup.c,
+ lib/util/regress/atofoo/atofoo_test.c,
+ lib/util/regress/fnmatch/fnm_test.c,
+ lib/util/regress/glob/globtest.c,
+ lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_parseln/parseln_test.c,
+ lib/util/regress/tailq/hltq_test.c, lib/util/secure_path.c,
+ lib/util/setgroups.c, lib/util/sha2.c, lib/util/sig2str.c,
+ lib/util/snprintf.c, lib/util/strlcat.c, lib/util/strlcpy.c,
+ lib/util/strsignal.c, lib/util/strtobool.c, lib/util/strtoid.c,
+ lib/util/strtomode.c, lib/util/strtonum.c, lib/util/sudo_conf.c,
+ lib/util/sudo_debug.c, lib/util/sudo_dso.c, lib/util/sudo_printf.c,
+ lib/util/term.c, lib/util/ttysize.c, lib/util/utimes.c,
+ plugins/group_file/Makefile.in, plugins/group_file/getgrent.c,
+ plugins/group_file/group_file.c, plugins/sample/Makefile.in,
+ plugins/sample/sample_plugin.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/audit.c, plugins/sudoers/base64.c,
+ plugins/sudoers/boottime.c, plugins/sudoers/bsm_audit.c,
+ plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/hexchar.c, plugins/sudoers/linux_audit.c,
+ plugins/sudoers/locale.c, plugins/sudoers/redblack.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/timestr.c, plugins/system_group/Makefile.in,
+ plugins/system_group/system_group.c, src/Makefile.in,
+ src/locale_stub.c, src/net_ifs.c, src/preload.c,
+ src/regress/ttyname/check_ttyname.c, src/sesh.c, src/sudo.h,
+ src/sudo_noexec.c:
+ Rename missing.h -> sudo_compat.h
+ [ddcc945a0f87]
+
+ * MANIFEST, include/secure_path.h, include/sudo_util.h,
+ lib/util/Makefile.in, lib/util/secure_path.c, lib/util/sudo_conf.c,
+ plugins/sudoers/Makefile.in, plugins/sudoers/sudoers.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Merge secure_path.h -> sudo_util.h
+ [0385dfbf2e2d]
+
+ * include/secure_path.h, include/sudo_alloc.h, include/sudo_conf.h,
+ include/sudo_dso.h, include/sudo_event.h, include/sudo_fatal.h,
+ include/sudo_lbuf.h, include/sudo_util.h, lib/util/aix.c,
+ lib/util/alloc.c, lib/util/event.c, lib/util/fatal.c,
+ lib/util/gidlist.c, lib/util/key_val.c, lib/util/lbuf.c,
+ lib/util/locking.c, lib/util/parseln.c, lib/util/secure_path.c,
+ lib/util/setgroups.c, lib/util/strtobool.c, lib/util/strtoid.c,
+ lib/util/strtomode.c, lib/util/sudo_conf.c, lib/util/sudo_dso.c,
+ lib/util/term.c, lib/util/ttysize.c, lib/util/util.exp,
+ plugins/sudoers/locale.c, src/locale_stub.c:
+ Version the functions in libsudo_util
+ [c6d6eba95bb4]
+
+2014-07-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/gettext.h, include/sudo_gettext.h, lib/util/Makefile.in,
+ lib/util/aix.c, lib/util/alloc.c, lib/util/fatal.c,
+ lib/util/gidlist.c, lib/util/strsignal.c, lib/util/strtoid.c,
+ lib/util/strtomode.c, lib/util/strtonum.c, lib/util/sudo_conf.c,
+ lib/util/sudo_debug.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/audit.c, plugins/sudoers/bsm_audit.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/locale.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoreplay.c,
+ src/Makefile.in, src/locale_stub.c, src/net_ifs.c, src/sesh.c,
+ src/sudo.h:
+ Rename gettext.h -> sudo_gettext.h
+ [7f6b44473b8f]
+
+ * include/fatal.h, include/sudo_fatal.h, lib/util/Makefile.in,
+ lib/util/aix.c, lib/util/alloc.c, lib/util/event.c,
+ lib/util/event_poll.c, lib/util/event_select.c, lib/util/fatal.c,
+ lib/util/getopt_long.c, lib/util/gidlist.c, lib/util/lbuf.c,
+ lib/util/regress/atofoo/atofoo_test.c,
+ lib/util/regress/tailq/hltq_test.c, lib/util/sudo_conf.c,
+ lib/util/sudo_debug.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/bsm_audit.c, plugins/sudoers/linux_audit.c,
+ plugins/sudoers/locale.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoreplay.c,
+ src/Makefile.in, src/locale_stub.c, src/net_ifs.c,
+ src/regress/ttyname/check_ttyname.c, src/sesh.c, src/sudo.h:
+ Rename fatal.h -> sudo_fatal.h
+ [bef3401dbb24]
+
+ * include/queue.h, include/sudo_conf.h, include/sudo_event.h,
+ include/sudo_queue.h, lib/util/Makefile.in, lib/util/fatal.c,
+ lib/util/regress/tailq/hltq_test.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoreplay.c,
+ src/Makefile.in, src/hooks.c:
+ Rename queue.h -> sudo_queue.h to avoid collisions with the system
+ version.
+ [473614fdde5a]
+
+ * include/sudo_debug.h, lib/util/sudo_debug.c:
+ Conver sudo_debug_write() to a macro
+ [0f110f27a23c]
+
+2014-07-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/fixman.sh, doc/fixmdoc.sh:
+ Fix man page post-processing; it was deleting more than intended.
+ [716af03dcfb7]
+
+2014-07-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/Makefile.in:
+ Remove double $(srcdir) when running sed scripts.
+ [16add67ae550]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ "an EXEC tag" not "a EXEC tag"
+ [9ac1b8e322f9]
+
+ * doc/sudoers.cat:
+ Document that I/O logging is not enabled by default.
+ [08fca95dd5a4]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document that exec_background is off by default.
+ [87fe5defff58]
+
+2014-07-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sesh.c:
+ Error out if sesh is run as a login shell but the shell it needs to
+ run has no slash. This shouldn't happen in practice.
+ [10ff502888ee]
+
+ * MANIFEST, include/compat/mksiglist.h, include/compat/mksigname.h,
+ lib/util/Makefile.in, lib/util/mksiglist.c, lib/util/mksiglist.h,
+ lib/util/mksigname.c, lib/util/mksigname.h:
+ Move mksiglist.h and mksigname.h to lib/util where they belong.
+ [d01046c69060]
+
+ * config.h.in, configure, configure.ac, include/missing.h,
+ lib/util/progname.c, lib/util/util.exp, plugins/sudoers/Makefile.in:
+ Avoid passing -no-fast-install to libtool as this results in the
+ build dir being left in the library path of the installed
+ executable. Instead, we remove the "lt-" prefix from the program
+ name in initprogname() so that the regress test output is unaffected
+ by libtool's binary wrapper.
+ [75d1563e95b4]
+
+ * sudo.pp:
+ Fix syntax error with some shells.
+ [91e8da7702c5]
+
+2014-07-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ Force libtool to use runtime linking on AIX so that it installs the
+ plugins as .so files and not .a files.
+ [ae66488bd9ca]
+
+ * plugins/sudoers/ldap.c:
+ Be sure to NUL-terminate the decoded secret when converting from
+ base64.
+ [b3dc463c8882]
+
+ * plugins/sudoers/ldap.c:
+ Fix a pointer signednes warning calling base64_decode().
+ [74f7354867a3]
+
+ * lib/util/getgrouplist.c:
+ Use sudo_strtoid() now that it is located in the same library.
+ [4868532e2d65]
+
+ * lib/util/strtoid.c:
+ Skip leading space (ala strtol) so that we can pick up the sign even
+ if it is not the first character of the string.
+ [148ee633c6a4]
+
+2014-07-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ For sudoedit, audit the actual editor being run, not just the
+ sudoedit command.
+ [59a5b0ad36af]
+
+ * src/selinux.c:
+ Audit failed user role changes. RedHat bz #665131
+ [cf9777687124]
+
+ * plugins/sudoers/Makefile.in:
+ Avoid running check_symbols for static sudoers
+ [71b13bada1ce]
+
+ * plugins/sudoers/regress/visudo/test3.err.ok,
+ plugins/sudoers/regress/visudo/test3.sh:
+ Adapt to unused alias changes.
+ [4b58e36c3d8f]
+
+ * doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in,
+ plugins/sudoers/visudo.c:
+ An unused alias is not really an error, even in strict mode. RedHat
+ bz #604297
+ [f10b3b7ec5a6]
+
+ * src/sesh.c:
+ When running a login shell via sesh, make new argv[0] -shell, not
+ /path/to-shell. RedHat bz #1065418
+ [414cb512f102]
+
+2014-07-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ The RHEL sudo package allows users in group wheel to run sudo.
+ [9f22020a57cf]
+
+ * Makefile.in, sudo.pp:
+ Avoid packaging parent directories when they are system directories.
+ Currently we just skip this when prefix is /usr
+ [93ccede545cd]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Fix typo: sudo.d -> sudoers.d. From RedHat bz #726634
+ [1c99a4fd9c7d]
+
+ * mkpkg:
+ RHEL 6 and above use /etc/sudo-ldap.conf not /etc/ldap.conf
+ [ce3216e4390a]
+
+ * pp:
+ For rpm, do not specify a mode in %attr for symbolic links. Avoids
+ the warning "Explicit %attr() mode not applicaple to symlink"
+ [3f5a80ed5081]
+
+2014-07-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/sudo_alloc.h, lib/util/aix.c, lib/util/event.c,
+ lib/util/event_poll.c, lib/util/event_select.c, lib/util/fatal.c,
+ lib/util/lbuf.c, lib/util/sudo_conf.c, plugins/sudoers/alias.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/passwd.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/check.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/env.c, plugins/sudoers/find_path.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/interfaces.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_path.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/linux_audit.c,
+ plugins/sudoers/locale.c, plugins/sudoers/logging.c,
+ plugins/sudoers/match.c, plugins/sudoers/policy.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/redblack.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/visudo.c, src/exec.c,
+ src/exec_common.c, src/exec_pty.c, src/hooks.c, src/load_plugins.c,
+ src/net_ifs.c, src/preserve_fds.c,
+ src/regress/ttyname/check_ttyname.c, src/selinux.c, src/sudo.c,
+ src/ttyname.c:
+ efree -> sudo_efree for consistency
+ [7dfd16fbb6cf]
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo_plugin.cat,
+ doc/sudoers.cat, doc/sudoreplay.cat, doc/visudo.cat:
+ regen
+ [a1d38600d34c]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in, plugins/sudoers/ldap.c:
+ Add support for base64 secrets in ldap.conf and ldap.secret. Based
+ on an idea from anthony AT rlost DOT com
+ [4999b78f8b6d]
+
+2014-07-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg:
+ Don't use the HP compiler in preference to gcc. Some versions have
+ trouble compiling lbuf.c.
+ [322daf03ab6f]
+
+2014-07-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac, plugins/group_file/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/Makefile.in:
+ Remove @SOEXT@ and @SHLIB_EXT@ now that we use libtool to install
+ shared objects. Instead, use the new @SHLIB_ENABLE@ that is set to
+ the value of $enable_dlopen. For sudo_noexec.so there is nothing
+ special to do since the install-noexec target is only called when
+ noexec is enabled by configure.
+ [4447190f212b]
+
+ * configure, configure.ac:
+ Make dynamic shared objects non-writable on HP-UX. Using writable
+ DSOs can substantially increase the load time.
+ [8715aff11063]
+
+ * include/fatal.h, lib/util/fatal.c, lib/util/util.exp,
+ plugins/sudoers/locale.c, src/locale_stub.c:
+ Add sudo_warn_strerror() that wraps strerror() with calls to
+ setlocale() in sudoers so we always get the error string in the
+ user's locale. Also change _warning() to take the error number as a
+ parameter instead of examining errno.
+ [cc38a8389a7b]
+
+2014-07-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, lib/util/Makefile.in, plugins/group_file/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/Makefile.in:
+ Avoid a cppcheck warning when NSIG is not defined.
+ [f8e5e92bab60]
+
+ * include/missing.h:
+ Fix typos in utimes/futimes macros.
+ [10f022d933c2]
+
+2014-07-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [e351d905c0c9]
+
+ * configure.ac:
+ Fix sudo when --disable-shared configure option was specified.
+ [07899f6b43f0]
+
+ * configure, m4/libtool.m4:
+ Do not set an internal name for HP-UX modules, only archives. This
+ works around a problem with some versions of HP-UX ld where setting
+ an internal name that doesn't end in .sl causes link errors.
+ [9a049adb22aa]
+
+ * plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/system_group/Makefile.in:
+ Never build build static versions of other plugins.
+ [52123c4c17bc]
+
+ * lib/util/Makefile.in:
+ Don't build a static libsudo_util.a unless we are linking sudoers
+ statically.
+ [9c3327977dff]
+
+2014-06-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac, lib/util/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in,
+ src/Makefile.in:
+ Use libtool to install/uninstall the plugins and sudo_noexec.
+ [18ae09c53f2e]
+
+ * configure, ltmain.sh, m4/libtool.m4:
+ Fix my typos in the HP-UX libtool patch
+ [6e70066d86bb]
+
+2014-06-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Mention Solaris audit.
+ [d90efa19ca16]
+
+ * INSTALL, MANIFEST, config.h.in, configure, configure.ac, mkdep.pl,
+ plugins/sudoers/Makefile.in, plugins/sudoers/audit.c,
+ plugins/sudoers/solaris_audit.c, plugins/sudoers/solaris_audit.h:
+ Add Solaris audit support; from Gary Winiger at Oracle.
+ [6f68a27e53f5]
+
+ * MANIFEST:
+ Sync MANIFEST with file name changes.
+ [d9958df5f9da]
+
+ * plugins/sudoers/toke.c:
+ regen
+ [ad82b20093c3]
+
+ * include/sudo_util.h, lib/util/Makefile.in, lib/util/atobool.c,
+ lib/util/atoid.c, lib/util/atomode.c, lib/util/getgrouplist.c,
+ lib/util/gidlist.c, lib/util/regress/atofoo/atofoo_test.c,
+ lib/util/strtobool.c, lib/util/strtoid.c, lib/util/strtomode.c,
+ lib/util/sudo_conf.c, lib/util/util.exp,
+ plugins/group_file/getgrent.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/match.c, plugins/sudoers/policy.c,
+ plugins/sudoers/pwutil.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/visudo_json.c,
+ plugins/system_group/system_group.c, src/sudo.c:
+ atobool -> sudo_strtobool atoid-> sudo_strtoid atomode ->
+ sudo_strtomode
+ [aefe6f09f4a4]
+
+ * lib/util/alloc.c, lib/util/event_select.c:
+ Fix regexp damage when renaming erecalloc() -> sudo_erecalloc()
+ [d772a34032cc]
+
+ * src/sudo_edit.c:
+ Handle systems like AIX that lack a way to set the modification time
+ on open fds.
+ [b93c0a55c21b]
+
+ * MANIFEST:
+ update MANIFEST for alloc.h -> sudo_alloc.h change
+ [ce240c682554]
+
+ * include/alloc.h, include/sudo_alloc.h, lib/util/Makefile.in,
+ lib/util/aix.c, lib/util/alloc.c, lib/util/event.c,
+ lib/util/event_poll.c, lib/util/event_select.c, lib/util/fatal.c,
+ lib/util/gidlist.c, lib/util/lbuf.c, lib/util/sudo_conf.c,
+ lib/util/sudo_debug.c, lib/util/util.exp,
+ plugins/sudoers/Makefile.in, plugins/sudoers/alias.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/env.c, plugins/sudoers/find_path.c,
+ plugins/sudoers/getspwuid.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/interfaces.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_path.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/locale.c,
+ plugins/sudoers/logging.c, plugins/sudoers/match.c,
+ plugins/sudoers/parse.c, plugins/sudoers/policy.c,
+ plugins/sudoers/prompt.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/pwutil_impl.c, plugins/sudoers/redblack.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ src/Makefile.in, src/conversation.c, src/env_hooks.c, src/exec.c,
+ src/exec_common.c, src/exec_pty.c, src/hooks.c, src/load_plugins.c,
+ src/net_ifs.c, src/parse_args.c, src/preserve_fds.c,
+ src/regress/ttyname/check_ttyname.c, src/selinux.c, src/sesh.c,
+ src/sudo.c, src/sudo.h, src/sudo_edit.c, src/ttyname.c:
+ Add sudo_ prefix to alloc.c functions and rename alloc.h ->
+ sudo_alloc.h
+ [3a19f5391442]
+
+ * lib/util/fatal.c:
+ Remove extra sudo_ prefix from vfatalxnodebug and vfatalx_nodebug.
+ [819ad8075005]
+
+ * MANIFEST, include/fileops.h, include/sudo_util.h,
+ lib/util/Makefile.in, lib/util/fileops.c, lib/util/locking.c,
+ lib/util/parseln.c, lib/util/regress/sudo_parseln/parseln_test.c,
+ lib/util/sudo_conf.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/sudoers.h, src/Makefile.in, src/sudo.h:
+ Split fileops.c into parseln.c and locking.c
+ [361ea81e88d9]
+
+ * include/fatal.h, include/gettext.h, lib/util/aix.c,
+ lib/util/alloc.c, lib/util/fatal.c, lib/util/getopt_long.c,
+ lib/util/gidlist.c, lib/util/regress/atofoo/atofoo_test.c,
+ lib/util/regress/tailq/hltq_test.c, lib/util/sudo_conf.c,
+ lib/util/util.exp, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/rfc1938.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/bsm_audit.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/env.c, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/locale.c,
+ plugins/sudoers/logging.c, plugins/sudoers/match.c,
+ plugins/sudoers/policy.c, plugins/sudoers/prompt.c,
+ plugins/sudoers/pwutil.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/visudo.c,
+ plugins/sudoers/visudo_json.c, src/exec.c, src/exec_common.c,
+ src/exec_pty.c, src/hooks.c, src/load_plugins.c, src/locale_stub.c,
+ src/net_ifs.c, src/parse_args.c, src/selinux.c, src/sesh.c,
+ src/signal.c, src/solaris.c, src/sudo.c, src/sudo_edit.c,
+ src/tgetpass.c, src/ttyname.c, src/utmp.c:
+ Rename warning/fatal -> sudo_warn/sudo_fatal to avoid namespace
+ pollution in libsudo_util.so.
+ [4eb69f501113]
+
+2014-06-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/sudo_util.h, lib/util/term.c, lib/util/ttysize.c,
+ lib/util/util.exp, plugins/sudoers/sudoreplay.c, src/exec_pty.c,
+ src/sudo.c, src/tgetpass.c:
+ Reduce name space pollution in libsudo_util.so
+ [215e4413529a]
+
+ * src/solaris.c:
+ Use sudo_dso_load() from libsudo_util.so instead of dlopen() since
+ we no longer link sudo directly with libdl.so.
+ [fe6942873c2d]
+
+ * MANIFEST, Makefile.in, doc/Makefile.in, include/alloc.h,
+ include/compat/fnmatch.h, include/compat/getaddrinfo.h,
+ include/compat/getopt.h, include/compat/glob.h,
+ include/compat/sha2.h, include/fatal.h, include/fileops.h,
+ include/lbuf.h, include/missing.h, include/secure_path.h,
+ include/sudo_conf.h, include/sudo_debug.h, include/sudo_dso.h,
+ include/sudo_event.h, include/sudo_util.h, install-sh,
+ lib/util/Makefile.in, lib/util/fatal.c, lib/util/getaddrinfo.c,
+ lib/util/pw_dup.c, lib/util/regress/fnmatch/fnm_test.c,
+ lib/util/sudo_dso.c, lib/util/sudo_printf.c, lib/util/term.c,
+ lib/util/util.exp, plugins/group_file/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/sudoers/match.c,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/visudo.c,
+ plugins/system_group/Makefile.in, src/Makefile.in, src/parse_args.c,
+ src/preload.c:
+ Add exported libsudo_util functions to util.exp and mark in headers
+ using __dso_public.
+ [18faff6ab915]
+
+ * include/fatal.h, lib/util/fatal.c, lib/util/util.exp,
+ plugins/sudoers/iolog.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c:
+ Remove use of setjmp/longjmp in the sudoers plugin. We no longer
+ call fatal() except in the malloc wrappers and due to libsudo_util
+ there is now a single copy of fatal/fatalx.
+ [109407210f9c]
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.8.11
+ [5fb775825aab]
+
+ * include/fileops.h, lib/util/fileops.c, lib/util/util.exp,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/logging.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/visudo.c, src/sudo_edit.c:
+ Remove touch() from fileops.c and just call utimes/futimes directly.
+ Rename lock_file -> sudo_lock_file to avoid namespace pollution
+ [ec08128b6900]
+
+ * MANIFEST, include/sudo_util.h, lib/util/Makefile.in,
+ lib/util/fmt_string.c, lib/util/key_val.c, lib/util/util.exp,
+ plugins/sample/sample_plugin.c, plugins/sudoers/policy.c,
+ src/Makefile.in, src/exec_common.c, src/parse_args.c, src/sudo.c:
+ Rename fmt_string -> sudo_new_key_val to better describe its
+ function.
+ [f9061e319cc3]
+
+ * include/sudo_util.h, lib/util/gidlist.c, lib/util/util.exp,
+ plugins/sudoers/policy.c, src/sudo.c:
+ Rename parse_gid_list -> sudo_parse_gids to avoid namespace
+ pollution.
+ [d88f3cab97e1]
+
+ * MANIFEST, Makefile.in, include/lbuf.h, include/sudo_lbuf.h,
+ lib/util/Makefile.in, lib/util/lbuf.c, lib/util/util.exp,
+ plugins/sudoers/Makefile.in, plugins/sudoers/ldap.c,
+ plugins/sudoers/parse.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudo_nss.h,
+ plugins/sudoers/sudoers.h, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, src/Makefile.in, src/parse_args.c:
+ Don't pollute the namespace with lbuf struct and functions
+ [7859e3c22fb9]
+
+ * config.h.in, configure, configure.ac, include/compat/fnmatch.h,
+ include/compat/getaddrinfo.h, include/compat/getopt.h,
+ include/compat/glob.h, include/missing.h, lib/util/clock_gettime.c,
+ lib/util/closefrom.c, lib/util/fnmatch.c, lib/util/getaddrinfo.c,
+ lib/util/getcwd.c, lib/util/getgrouplist.c, lib/util/getline.c,
+ lib/util/getopt_long.c, lib/util/glob.c, lib/util/inet_pton.c,
+ lib/util/memrchr.c, lib/util/memset_s.c, lib/util/mktemp.c,
+ lib/util/pw_dup.c, lib/util/sig2str.c, lib/util/snprintf.c,
+ lib/util/strlcat.c, lib/util/strlcpy.c, lib/util/strsignal.c,
+ lib/util/strtonum.c, lib/util/utimes.c:
+ Prefix all libc replacements with sudo_ and #define the real name to
+ the sudo_ version. That way we don't pollute the libc namespace.
+ [5cf7101479b8]
+
+ * .hgignore, MANIFEST, Makefile.in, common/Makefile.in, common/aix.c,
+ common/alloc.c, common/atobool.c, common/atoid.c, common/atomode.c,
+ common/event.c, common/event_poll.c, common/event_select.c,
+ common/fatal.c, common/fileops.c, common/fmt_string.c,
+ common/gidlist.c, common/lbuf.c, common/progname.c,
+ common/regress/atofoo/atofoo_test.c,
+ common/regress/sudo_conf/conf_test.c,
+ common/regress/sudo_conf/test1.in,
+ common/regress/sudo_conf/test1.out.ok,
+ common/regress/sudo_conf/test2.in,
+ common/regress/sudo_conf/test2.out.ok,
+ common/regress/sudo_conf/test3.in,
+ common/regress/sudo_conf/test3.out.ok,
+ common/regress/sudo_conf/test4.in,
+ common/regress/sudo_conf/test4.out.ok,
+ common/regress/sudo_conf/test5.err.ok,
+ common/regress/sudo_conf/test5.in,
+ common/regress/sudo_conf/test5.out.ok,
+ common/regress/sudo_conf/test6.in,
+ common/regress/sudo_conf/test6.out.ok,
+ common/regress/sudo_parseln/parseln_test.c,
+ common/regress/sudo_parseln/test1.in,
+ common/regress/sudo_parseln/test1.out.ok,
+ common/regress/sudo_parseln/test2.in,
+ common/regress/sudo_parseln/test2.out.ok,
+ common/regress/sudo_parseln/test3.in,
+ common/regress/sudo_parseln/test3.out.ok,
+ common/regress/sudo_parseln/test4.in,
+ common/regress/sudo_parseln/test4.out.ok,
+ common/regress/sudo_parseln/test5.in,
+ common/regress/sudo_parseln/test5.out.ok,
+ common/regress/sudo_parseln/test6.in,
+ common/regress/sudo_parseln/test6.out.ok,
+ common/regress/tailq/hltq_test.c, common/secure_path.c,
+ common/setgroups.c, common/sudo_conf.c, common/sudo_debug.c,
+ common/sudo_dso.c, common/sudo_printf.c, common/term.c,
+ common/ttysize.c, compat/Makefile.in, compat/charclass.h,
+ compat/clock_gettime.c, compat/closefrom.c, compat/endian.h,
+ compat/fnmatch.c, compat/fnmatch.h, compat/getaddrinfo.c,
+ compat/getaddrinfo.h, compat/getcwd.c, compat/getgrouplist.c,
+ compat/getline.c, compat/getopt.h, compat/getopt_long.c,
+ compat/glob.c, compat/glob.h, compat/inet_pton.c, compat/isblank.c,
+ compat/memrchr.c, compat/memset_s.c, compat/mksiglist.c,
+ compat/mksiglist.h, compat/mksigname.c, compat/mksigname.h,
+ compat/mktemp.c, compat/nss_dbdefs.h, compat/pw_dup.c,
+ compat/regress/fnmatch/fnm_test.c,
+ compat/regress/fnmatch/fnm_test.in, compat/regress/glob/files,
+ compat/regress/glob/globtest.c, compat/regress/glob/globtest.in,
+ compat/sha2.c, compat/sha2.h, compat/sig2str.c, compat/siglist.in,
+ compat/snprintf.c, compat/stdbool.h, compat/strlcat.c,
+ compat/strlcpy.c, compat/strsignal.c, compat/strtonum.c,
+ compat/timespec.h, compat/utime.h, compat/utimes.c, configure,
+ configure.ac, include/compat/charclass.h, include/compat/endian.h,
+ include/compat/fnmatch.h, include/compat/getaddrinfo.h,
+ include/compat/getopt.h, include/compat/glob.h,
+ include/compat/mksiglist.h, include/compat/mksigname.h,
+ include/compat/nss_dbdefs.h, include/compat/sha2.h,
+ include/compat/stdbool.h, include/compat/timespec.h,
+ include/compat/utime.h, lib/util/Makefile.in, lib/util/aix.c,
+ lib/util/alloc.c, lib/util/atobool.c, lib/util/atoid.c,
+ lib/util/atomode.c, lib/util/clock_gettime.c, lib/util/closefrom.c,
+ lib/util/event.c, lib/util/event_poll.c, lib/util/event_select.c,
+ lib/util/fatal.c, lib/util/fileops.c, lib/util/fmt_string.c,
+ lib/util/fnmatch.c, lib/util/getaddrinfo.c, lib/util/getcwd.c,
+ lib/util/getgrouplist.c, lib/util/getline.c, lib/util/getopt_long.c,
+ lib/util/gidlist.c, lib/util/glob.c, lib/util/inet_pton.c,
+ lib/util/isblank.c, lib/util/lbuf.c, lib/util/memrchr.c,
+ lib/util/memset_s.c, lib/util/mksiglist.c, lib/util/mksigname.c,
+ lib/util/mktemp.c, lib/util/progname.c, lib/util/pw_dup.c,
+ lib/util/regress/atofoo/atofoo_test.c,
+ lib/util/regress/fnmatch/fnm_test.c,
+ lib/util/regress/fnmatch/fnm_test.in, lib/util/regress/glob/files,
+ lib/util/regress/glob/globtest.c, lib/util/regress/glob/globtest.in,
+ lib/util/regress/sudo_conf/conf_test.c,
+ lib/util/regress/sudo_conf/test1.in,
+ lib/util/regress/sudo_conf/test1.out.ok,
+ lib/util/regress/sudo_conf/test2.in,
+ lib/util/regress/sudo_conf/test2.out.ok,
+ lib/util/regress/sudo_conf/test3.in,
+ lib/util/regress/sudo_conf/test3.out.ok,
+ lib/util/regress/sudo_conf/test4.in,
+ lib/util/regress/sudo_conf/test4.out.ok,
+ lib/util/regress/sudo_conf/test5.err.ok,
+ lib/util/regress/sudo_conf/test5.in,
+ lib/util/regress/sudo_conf/test5.out.ok,
+ lib/util/regress/sudo_conf/test6.in,
+ lib/util/regress/sudo_conf/test6.out.ok,
+ lib/util/regress/sudo_parseln/parseln_test.c,
+ lib/util/regress/sudo_parseln/test1.in,
+ lib/util/regress/sudo_parseln/test1.out.ok,
+ lib/util/regress/sudo_parseln/test2.in,
+ lib/util/regress/sudo_parseln/test2.out.ok,
+ lib/util/regress/sudo_parseln/test3.in,
+ lib/util/regress/sudo_parseln/test3.out.ok,
+ lib/util/regress/sudo_parseln/test4.in,
+ lib/util/regress/sudo_parseln/test4.out.ok,
+ lib/util/regress/sudo_parseln/test5.in,
+ lib/util/regress/sudo_parseln/test5.out.ok,
+ lib/util/regress/sudo_parseln/test6.in,
+ lib/util/regress/sudo_parseln/test6.out.ok,
+ lib/util/regress/tailq/hltq_test.c, lib/util/secure_path.c,
+ lib/util/setgroups.c, lib/util/sha2.c, lib/util/sig2str.c,
+ lib/util/siglist.in, lib/util/snprintf.c, lib/util/strlcat.c,
+ lib/util/strlcpy.c, lib/util/strsignal.c, lib/util/strtonum.c,
+ lib/util/sudo_conf.c, lib/util/sudo_debug.c, lib/util/sudo_dso.c,
+ lib/util/sudo_printf.c, lib/util/term.c, lib/util/ttysize.c,
+ lib/util/utimes.c, lib/zlib/Makefile.in, lib/zlib/adler32.c,
+ lib/zlib/compress.c, lib/zlib/crc32.c, lib/zlib/crc32.h,
+ lib/zlib/deflate.c, lib/zlib/deflate.h, lib/zlib/gzclose.c,
+ lib/zlib/gzguts.h, lib/zlib/gzlib.c, lib/zlib/gzread.c,
+ lib/zlib/gzwrite.c, lib/zlib/infback.c, lib/zlib/inffast.c,
+ lib/zlib/inffast.h, lib/zlib/inffixed.h, lib/zlib/inflate.c,
+ lib/zlib/inflate.h, lib/zlib/inftrees.c, lib/zlib/inftrees.h,
+ lib/zlib/trees.c, lib/zlib/trees.h, lib/zlib/uncompr.c,
+ lib/zlib/zconf.h.in, lib/zlib/zlib.h, lib/zlib/zutil.c,
+ lib/zlib/zutil.h, plugins/group_file/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, po/README, po/ca.mo, po/ca.po,
+ po/cs.mo, po/cs.po, po/da.mo, po/da.po, po/de.mo, po/de.po,
+ po/eo.mo, po/eo.po, po/es.mo, po/es.po, po/eu.mo, po/eu.po,
+ po/fi.mo, po/fi.po, po/fr.mo, po/fr.po, po/gl.mo, po/gl.po,
+ po/hr.mo, po/hr.po, po/it.mo, po/it.po, po/ja.mo, po/ja.po,
+ po/nb.mo, po/nb.po, po/nl.mo, po/nl.po, po/pl.mo, po/pl.po,
+ po/pt_BR.mo, po/pt_BR.po, po/ru.mo, po/ru.po, po/sl.mo, po/sl.po,
+ po/sr.mo, po/sr.po, po/sudo.pot, po/sv.mo, po/sv.po, po/tr.mo,
+ po/tr.po, po/uk.mo, po/uk.po, po/vi.mo, po/vi.po, po/zh_CN.mo,
+ po/zh_CN.po, src/Makefile.in, src/po/README, src/po/ca.mo,
+ src/po/ca.po, src/po/cs.mo, src/po/cs.po, src/po/da.mo,
+ src/po/da.po, src/po/de.mo, src/po/de.po, src/po/eo.mo,
+ src/po/eo.po, src/po/es.mo, src/po/es.po, src/po/eu.mo,
+ src/po/eu.po, src/po/fi.mo, src/po/fi.po, src/po/fr.mo,
+ src/po/fr.po, src/po/gl.mo, src/po/gl.po, src/po/hr.mo,
+ src/po/hr.po, src/po/it.mo, src/po/it.po, src/po/ja.mo,
+ src/po/ja.po, src/po/nb.mo, src/po/nb.po, src/po/nl.mo,
+ src/po/nl.po, src/po/pl.mo, src/po/pl.po, src/po/pt_BR.mo,
+ src/po/pt_BR.po, src/po/ru.mo, src/po/ru.po, src/po/sl.mo,
+ src/po/sl.po, src/po/sr.mo, src/po/sr.po, src/po/sudo.pot,
+ src/po/sv.mo, src/po/sv.po, src/po/tr.mo, src/po/tr.po,
+ src/po/uk.mo, src/po/uk.po, src/po/vi.mo, src/po/vi.po,
+ src/po/zh_CN.mo, src/po/zh_CN.po, zlib/Makefile.in, zlib/adler32.c,
+ zlib/compress.c, zlib/crc32.c, zlib/crc32.h, zlib/deflate.c,
+ zlib/deflate.h, zlib/gzclose.c, zlib/gzguts.h, zlib/gzlib.c,
+ zlib/gzread.c, zlib/gzwrite.c, zlib/infback.c, zlib/inffast.c,
+ zlib/inffast.h, zlib/inffixed.h, zlib/inflate.c, zlib/inflate.h,
+ zlib/inftrees.c, zlib/inftrees.h, zlib/trees.c, zlib/trees.h,
+ zlib/uncompr.c, zlib/zconf.h.in, zlib/zlib.h, zlib/zutil.c,
+ zlib/zutil.h:
+ Top level directory reorg Move src/po -> po Combine common and
+ compat -> lib/util Move zlib -> lib/zlib
+ [d699ccb60e7e]
+
+ * configure, ltmain.sh, m4/libtool.m4:
+ libtool patches for HP-UX to support DESTDIR
+ [9df98a9582bd]
+
+ * pp:
+ Update polypkg from trunk.
+ [4dc362248196]
+
+ * plugins/sudoers/sssd.c, plugins/sudoers/sudo_nss.c:
+ Fix sssd compiler warnings and fix the sha2 digest support.
+ [2975b030b298]
+
+2014-06-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Don't call gss_krb5_ccache_name() with a NULL pointer when restoring
+ the old credential cache file name. This can happen if there was no
+ old name returned by gss_krb5_ccache_name(). Fixes a crash on
+ kerberized LDAP on some platforms.
+ [4090029e463e]
+
+2014-06-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, doc/CONTRIBUTORS, plugins/sudoers/po/el.mo,
+ plugins/sudoers/po/el.po:
+ Add Greek PO file for sudoers from translationproject.org
+ [6c0cc2def911]
+
+2014-05-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c, src/exec_pty.c:
+ Ignore signals sent by the command's process group, not just the
+ command itself. If we cannot determine the process group ID of the
+ sender (as it may no longer exist), just check the process ID.
+ [7ffa2eefd3c0]
+
+2014-05-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c:
+ In handler_user_only() only forward the signal if it was not
+ generated by the command. This should fix a problem with programs
+ that catch SIGTSTP, perform cleanup, and then re-send the signal to
+ their process group (of which sudo is the leader).
+ [d590c899e194]
+
+ * src/exec.c, src/exec_pty.c, src/signal.c:
+ Handle EINTR from write(2) when writing to pipes and socket pairs.
+ [d26a40d21d7a]
+
+2014-05-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/po/nb.mo, plugins/sudoers/po/nb.po:
+ Norwegian Bokmaal translation for sudoers from
+ translationproject.com
+ [92e4aea46c1e]
+
+2014-05-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, doc/CONTRIBUTORS, src/po/nb.mo, src/po/nb.po:
+ Norwegian Bokmaal translation for sudo from translationproject.com
+ [3497f74028fe]
+
+2014-05-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in,
+ plugins/sudoers/visudo.c:
+ Try to be clearer about which are the input and output files in
+ export mode.
+ [66167511a410]
+
+ * plugins/sudoers/visudo_json.c:
+ In -x mode, require that the input and output files be different.
+ This won't currently catch collisions between the output file and an
+ include file.
+ [0c19b82a75e7]
+
+ * plugins/sudoers/bsm_audit.h, plugins/sudoers/linux_audit.h:
+ BSM and Linux audit do not yet use the argc function argument.
+ [3291695d1dfb]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/bsm_audit.c,
+ plugins/sudoers/bsm_audit.h, plugins/sudoers/linux_audit.h,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/sudoers.c:
+ Pass argc to audit functions too. Will be needed for Solaris audit
+ support.
+ [d2114897a44e]
+
+2014-05-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/fatal.c, include/fatal.h, plugins/sudoers/policy.c:
+ Do not allow the same callback function to be registered more that
+ once in fatal_callback_register(). Add fatal_callback_deregister()
+ to deregister a callback.
+ [eff74fb9d274]
+
+ * MANIFEST, plugins/sudoers/regress/sudoers/test15.in,
+ plugins/sudoers/regress/sudoers/test15.out.ok,
+ plugins/sudoers/regress/sudoers/test15.toke.ok,
+ plugins/sudoers/regress/sudoers/test16.in,
+ plugins/sudoers/regress/sudoers/test16.out.ok,
+ plugins/sudoers/regress/sudoers/test16.toke.ok:
+ Add trivial sudoedit parsing tests.
+ [291ba6f4d6fd]
+
+ * MANIFEST, plugins/sudoers/po/ca.mo, plugins/sudoers/po/ca.po:
+ Catalan translation for sudoers from translationproject.org.
+ [b102f8cfeed1]
+
+2014-05-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ src/po/ca.mo, src/po/ca.po, src/po/gl.mo, src/po/gl.po:
+ Sync with translationproject.org
+ [62e5b4842834]
+
+2014-05-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ lockf() is broken on the Hurd -- use flock instead Bug #647
+ [7b8935a0c8b9]
+
+ * plugins/sudoers/visudo.c:
+ Don't try to install the temporary sudoers file if we didn't edit
+ it. By default, visudo does not edit files in a #includedir. Fixes a
+ NULL pointer defef on GNU hurd; Bug #647
+ [3a677c4773e5]
+
+2014-05-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/regress/ttyname/check_ttyname.c:
+ When comparing tty names, resolve the tty for fds 0-3 and compare
+ each one instead of just using the first that resolves.
+ [c37946b280a5]
+
+ * compat/getgrouplist.c, configure, configure.ac:
+ Solaris 8 doesn't export _nss_initf_group() so we need to provide
+ out own for getgrouplist().
+ [d494b39e9376]
+
+2014-05-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/getgrouplist.c, plugins/group_file/group_file.c,
+ plugins/system_group/system_group.c:
+ deal with NULL gr_mem here too
+ [0db43ed71001]
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.8.10p3
+ [3f415a180023]
+
+2014-05-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/check.c,
+ plugins/sudoers/env.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/parse.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/timestamp.c:
+ Rename log_warning flags and only send mail if SLOG_SEND_MAIL is set
+ instead of mailing by default like we used to.
+ [5b3882833aa1]
+
+ * plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/check.c,
+ plugins/sudoers/env.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/parse.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/timestamp.c:
+ Add log_warningx
+ [feef646cb8b1]
+
+ * src/exec_pty.c:
+ Add debugging info for when we delete I/O events that still have
+ buffered data in them.
+ [7f17992cdf22]
+
+ * common/event.c:
+ Fix non-blocking mode. We only want to exit the event loop when
+ poll() or select() returns 0 and there are no active events. This
+ fixes a problem on some systems where the last buffer was not being
+ written when the command exited.
+ [deb6b1a7b241]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Change return value of switch_dir() to an int so we can distinguish
+ between an error and an empty dir in push_includedir().
+ [d0462b84782e]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Move code to fill in the list of dirs out of switch_dir and into its
+ own function. Quiets a false positive from cppcheck which got
+ confused due to variable reuse.
+ [6d6296f46255]
+
+ * plugins/sudoers/audit.c:
+ Avoid unused variable warning if auditing is not supported.
+ [5e6fd2ffe039]
+
+2014-05-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ Fix library order when linking binaries.
+ [3fec51f98ae1]
+
+ * plugins/sudoers/getdate.c, plugins/sudoers/getdate.y:
+ Include limits.h and inttypes.h for SIZE_MAX define.
+ [41f8be660384]
+
+ * include/missing.h, plugins/sudoers/env.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y:
+ Move SIZE_MAX compat define into missing.h where it belongs.
+ [1bb108cf9df3]
+
+2014-04-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c:
+ Remove now-unused log_fatal()
+ [53478df3bb1e]
+
+ * plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/env.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Eliminate calls to fatal()/fatalx()/log_fatal() in env.c and just
+ pass back a return value.
+ [d7f2be8f2740]
+
+2014-04-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/boottime.c, plugins/sudoers/sudoers.h:
+ Make get_boottime() return bool.
+ [9ff15a995d01]
+
+ * doc/CONTRIBUTORS, plugins/sudoers/boottime.c:
+ Fix fd leak on Linux when determing boot time. This is usually
+ masked by the closefrom() call in sudo. From Jamie Anderson. Bug
+ #645
+ [0b4c430e8b88]
+
+2014-04-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/audit.c:
+ Handle the (currently impossible) case where both BSM and Linux
+ auditing are supported. Pacifies cppcheck.
+ [899cd6b5e487]
+
+ * plugins/sudoers/iolog.c:
+ Don't call ferror() on a closed stream, just check the return value
+ of fclose() instead. Found by cppcheck.
+ [e843f3c8f5d8]
+
+2014-04-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS, plugins/sudoers/auth/pam.c:
+ Use calloc() instead of malloc(n * s) followed by memset(). From
+ Jean-Philippe Ouellet.
+ [f416cebd3d8e]
+
+ * plugins/sudoers/sudoers.c:
+ Format string safety in error path.
+ [956fd6dbba80]
+
+ * common/alloc.c, common/event_poll.c, common/gidlist.c,
+ common/sudo_conf.c, include/alloc.h, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/env.c, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/visudo.c,
+ src/env_hooks.c, src/exec_common.c, src/parse_args.c, src/selinux.c,
+ src/sudo.c, src/sudo_edit.c, src/ttyname.c:
+ Rename emalloc2() -> emallocarray() and erealloc3() ->
+ ereallocarray().
+ [db3941093c68]
+
+ * compat/Makefile.in, mkdep.pl, plugins/sudoers/Makefile.in:
+ Add missing rule for building sha2.lo when not supported by libc or
+ libmd.
+ [70a16e10ddcd]
+
+2014-04-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.in:
+ Disable I/O logging for halt and poweroff in addition to reboot in
+ commented out example.
+ [40a7f11686ce]
+
+ * doc/CONTRIBUTORS, plugins/sudoers/auth/pam.c:
+ Use PAM_REINITIALIZE_CRED instead of PAM_ESTABLISH_CRED when
+ changing the user. This is the correct flag to use with a program
+ that changes the uid like su or sudo and fixes a role problem on
+ Solaris. From Gary Winiger; Bug #642
+ [ec23c3bf41bb]
+
+ * plugins/sudoers/defaults.c:
+ pam_setcred should default to true; from Gary Winiger Bug #642
+ [23e6628ec546]
+
+2014-04-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/logging.c,
+ plugins/sudoers/parse.c, plugins/sudoers/policy.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timestamp.c:
+ Make set_perms() and restore_perms() return an error instead of
+ calling exit() on failure.
+ [b1a1a36abdb4]
+
+ * plugins/sudoers/sudoers.c:
+ Eliminate calls to fatal() in sudoers.c and just pass back a return
+ value.
+ [e4d87a036f6d]
+
+ * plugins/sudoers/logging.c:
+ Elimate calls to fatal() in the logging code.
+ [9847acdf7066]
+
+2014-04-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/regress/atofoo/atofoo_test.c:
+ Quiet a compiler warning on Solaris.
+ [3b9827834800]
+
+ * MANIFEST, common/Makefile.in, compat/Makefile.in, compat/sha2.c,
+ compat/sha2.h, config.h.in, configure, configure.ac, m4/sudo.m4,
+ plugins/sudoers/Makefile.in, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.h, plugins/sudoers/gram.y,
+ plugins/sudoers/match.c,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/sudoers/test14.toke.ok,
+ plugins/sudoers/sha2.c, plugins/sudoers/sha2.h,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Move the sha2 code into libreplace and add configure checks for
+ SHA224Update in libc and libmd. Solaris uses "void *" where we use
+ "unsigned char *" so we need a check for that too. Solaris sha2.h
+ defines SHA224, SHA256, SHA384, and SHA512 so rename those tokens.
+ Adapted from changes from Vladimir Marek in bug #641.
+ [cd02732f0704]
+
+ * MANIFEST, plugins/sudoers/match.c,
+ plugins/sudoers/regress/testsudoers/test6.out.ok,
+ plugins/sudoers/regress/testsudoers/test6.sh,
+ plugins/sudoers/regress/testsudoers/test7.out.ok,
+ plugins/sudoers/regress/testsudoers/test7.sh:
+ Fix matching of uids and gids broken in sudo 1.8.9.
+ [315eff4add59]
+
+ * plugins/sudoers/testsudoers.c:
+ Fix -P option in usage()
+ [50753b6222b7]
+
+2014-04-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c, plugins/sudoers/prompt.c,
+ plugins/sudoers/set_perms.c:
+ Remove a few more unnecessary uses of fatal().
+ [8cfb205831dc]
+
+ * plugins/sudoers/auth/sudo_auth.c:
+ Use log_warning() not log_fatal() for the "Invalid authentication
+ methods compiled into sudo" message. We return -1 on error anyway.
+ [c8da5cf74348]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Return MODE_ERROR from sudoers_policy_deserialize_info() instead of
+ calling fatalx().
+ [6faefdd188f2]
+
+ * common/gidlist.c, src/sudo.c:
+ parse_gid_list() now returns -1 on error instead of calling
+ fatalx().
+ [ccf19c4a0d5b]
+
+2014-04-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c:
+ Forward SIGINFO to running command if supported. If the command is
+ being run in the background (or exec_background is set in sudoers),
+ it is the sudo process, not the actual command, that receives the
+ ^T.
+ [d2b020bdf0d5]
+
+ * plugins/sudoers/defaults.h, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_path.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c:
+ Remove calls to log_fatal() in I/O log functions and just pass an
+ error back to the caller.
+ [e89593d9dc35]
+
+2014-04-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/alloc.c, plugins/sudoers/env.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/policy.c,
+ plugins/sudoers/prompt.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/testsudoers.c:
+ Make "internal error, %s overflow" arguments consistent, using
+ __func__ where possible (when debugging is allowed).
+ [84e2c40d101b]
+
+2014-03-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/toke_util.c, src/net_ifs.c:
+ Use common printf format when warning of buffer overflow prevention.
+ [8b0d732b0eae]
+
+ * Makefile.in:
+ Remove init.d/*.sh in distclean
+ [99cd1eaf4684]
+
+ * .hgignore:
+ Correctly ignore init.d/*.sh
+ [04aabe1893e5]
+
+ * plugins/sudoers/ldap.c:
+ Remove remaining calls to fatalx(); just pass the error to the
+ caller.
+ [a8bcf903d84b]
+
+2014-03-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/pwutil.c, plugins/sudoers/sudoers.h:
+ Make a password/group cache collision a warning rather than fatal.
+ This should not be possible in practice and we can safely return the
+ new (potentially duplicate) item as it will be freed by the caller.
+ Make sudo_set_grlist() return an error on failure instead of calling
+ fatalx().
+ [5e8d3006862d]
+
+ * plugins/sudoers/timestamp.c:
+ Use log_warning() instead of log_fatal() if the ticket or lecture
+ path is too long and just return an error. This can only happen from
+ a misconfiguration so just ignoring the ticket/lecture file is safe.
+ [864c5de8345b]
+
+ * plugins/sudoers/find_path.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ In find_path(), return NOT_FOUND_ERROR instead of calling fatal() if
+ the path is too long. Remove an extraneous check against PATH_MAX in
+ set_cmnd() since find_path() already contains such a check.
+ [183106753690]
+
+ * plugins/sudoers/sudoers.h:
+ Remove unused MODE_LISTDEFS define and correct a comment.
+ [fb47e59ce5fe]
+
+ * plugins/sudoers/hexchar.c, plugins/sudoers/match.c,
+ plugins/sudoers/toke_util.c:
+ Make hexchar() return -1 on invalid input instead of calling
+ fatalx(). Callers used to check that the string was hex before
+ calling hexchar(). Now callers must check for a -1 return value
+ instead.
+ [1be217c71ce7]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/bsm_audit.c,
+ plugins/sudoers/bsm_audit.h, plugins/sudoers/linux_audit.c,
+ plugins/sudoers/logging.h, plugins/sudoers/sudoers.c:
+ Propagate errors in audit code to caller instead of using fatal().
+ If we fail to audit an otherwise successful command, return an error
+ from the policy. For Linux audit, sudo may be compiled with audit
+ support but auditing may not be setup, so we don't consider that an
+ error.
+ [9a5753bfcb95]
+
+ * plugins/sudoers/boottime.c:
+ Remove unused variable on Linux.
+ [f63d7b86797d]
+
+ * plugins/sudoers/timestamp.c:
+ Fix warning on systems where mode_t is not unsigned int (Solaris).
+ [acd1457c23ec]
+
+2014-03-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/env.c, plugins/sudoers/sudoers.c:
+ Audit path too long errror. Add comments about non-audit events and
+ placeholders for future audit hooks.
+ [434ee47c83dc]
+
+ * src/net_ifs.c:
+ Fix aliasing warning in old-style interface probe code.
+ [1d6ce6f46da1]
+
+ * plugins/sudoers/set_perms.c:
+ Fix some sign comparision warnings.
+ [20c6068db104]
+
+ * common/aix.c, common/gidlist.c, compat/getgrouplist.c,
+ include/sudo_util.h, src/sudo.c:
+ Don't call fatal/fatalx in common/*.c
+ [ebf5e55a1ec1]
+
+2014-03-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c, plugins/sudoers/prompt.c,
+ plugins/sudoers/sudoers.h:
+ Fix expansion of %p in the prompt for "sudo -l" when rootpw, runaspw
+ or targetpw is set. Bug #639
+ [dff0208d1194]
+
+2014-03-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.8.10p2
+ [774ebec63b41]
+
+ * plugins/sudoers/timestamp.c:
+ Don't write an empty timestamp record when timestamp_timeout is
+ zero. If we find an empty record in the timestamp file, overwrite it
+ with a good one, truncating the file as needed.
+ [9c226d81b660]
+
+2014-03-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in:
+ Fix typos in description of the -x option. Bug #637
+ [6ff2bfaaf99d]
+
+2014-03-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, configure, configure.ac:
+ Sudo 1.8.10p1
+ [33828a3385ad]
+
+ * plugins/sudoers/timestamp.c:
+ Fix typo/thinko that prevented "Defaults !tty_tickets" from working.
+ [f65cc29dbcc7]
+
+ * plugins/sudoers/parse.c:
+ Fix "sudo -l command" output when the matching command is negated.
+ Bug #636
+ [b4a92803f733]
+
+2014-03-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, common/Makefile.in, common/regress/atofoo/atofoo_test.c,
+ common/regress/sudo_conf/test5.err.ok,
+ common/regress/tailq/hltq_test.c:
+ The atofoo_test and hltq_test tests now display their own test error
+ rate. Display pass/fail count separately for sudo_conf and
+ sudo_parseln tests. Check stderr output for the sudo_conf test.
+ [5c814709ac70]
+
+ * src/Makefile.in:
+ Don't run the check_ttyname test if cross compiling.
+ [874ecc1c3db0]
+
+ * plugins/sudoers/Makefile.in:
+ CWD no longer used.
+ [13b2f3c4269b]
+
+ * plugins/sudoers/Makefile.in:
+ Fix diff of toke and err output files in "make check"
+ [485cdf3c75e7]
+
+2014-03-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/po/de.mo, src/po/de.po:
+ sync with translationproject.org
+ [d246c72a2350]
+
+2014-03-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ Check whether ber.h is needed before ldap.h even if we are not using
+ any ber functions. Needed for older versions of nss ldap.
+ [c2310324dc34]
+
+ * plugins/sudoers/sssd.c:
+ Fix compiler warning in debug code.
+ [8ee4cb6cafad]
+
+ * MANIFEST, NEWS, doc/CONTRIBUTORS, src/po/ca.mo, src/po/ca.po:
+ Catalan translation for sudo from translationproject.org.
+ [d6af7d06ee36]
+
+2014-03-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Document negation fix in JSON output.
+ [37a85423ae49]
+
+2014-03-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo_json.c:
+ Fix handling of '!' operator when converting sudoers. We now add a
+ "negated" boolean flag to objects that have the '!' operator.
+ [071926c10280]
+
+2014-03-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, NEWS, plugins/sudoers/po/cs.mo, plugins/sudoers/po/cs.po:
+ Czech translation for sudoers from translationproject.org
+ [c0aae297f7c1]
+
+2014-02-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ Try -libmldap before -lldap in case there is no link from
+ libibmldap.so to libldap.so. Since IBM ldap is installed under /opt
+ we should only be able to reach it if --with-ldap was given an
+ explicit path.
+
+ Only check for ber_set_option() if LBER_OPT_DEBUG_LEVEL is defined.
+ [89d50c29d737]
+
+2014-02-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/set_perms.c:
+ Fix typo in setreuid() PERM_ROOT error message.
+ [533415f53165]
+
+ * plugins/sudoers/auth/API, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h:
+ Remove unused FLAG_USER auth flag. We have no auth methods that
+ require that authentication be run as the invoking user.
+ [4a9a9f557cb1]
+
+ * mkpkg:
+ No longer need to disable setresuid() on debian.
+ [96ba687c35f0]
+
+2014-02-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/timestamp.c:
+ Fix conversion of timestamp_timeout from double to struct timeval.
+ Also quiet a printf format warning on 32-bit systems.
+ [59d1f3094dda]
+
+2014-02-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, NEWS, plugins/sudoers/po/sr.mo, plugins/sudoers/po/sr.po:
+ Serbian translation for sudoers from translationproject.org.
+ [7134b386d658]
+
+2014-02-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS:
+ Add Ingo Schwarze
+ [114cdf286987]
+
+ * NEWS, plugins/sudoers/visudo_json.c:
+ When exporting sudoers in JSON format, use the same type of Options
+ object for both Defaults and Cmnd_Specs.
+ [caa57043e197]
+
+2014-02-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/inet_pton.c:
+ Silence cppcheck false positive.
+ [b2781c42a80f]
+
+ * plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po:
+ sync with translationproject.org
+ [baba43a6d682]
+
+ * NEWS, doc/UPGRADE:
+ Mention init.d scripts on AIX and HP-UX Mention sudoers group
+ mismatch fix
+ [0259cb1f7cae]
+
+ * INSTALL:
+ Talk about clearing files at boot time, not reboot time since it
+ happens when the system comes up, not down.
+ [e8e480bc34fd]
+
+ * plugins/sudoers/sudoers.c:
+ We also need to open the sudoers file as root if there is a GID
+ mismatch.
+ [2fb2ba6fc4e6]
+
+ * sudo.pp:
+ Install /etc/rc.d/init.d/sudo and /etc/rc.d/rc2.d/S90sudo for AIX
+ rpm packages.
+ [4aca1d318599]
+
+2014-02-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/Makefile.in:
+ Remove init.d file and link in uninstall target.
+ [249a9f105cdd]
+
+ * configure, configure.ac, sudo.pp:
+ Fix INIT_DIR for real this time.
+ [5444eb1afbc5]
+
+ * configure, configure.ac, sudo.pp:
+ Use correct init.d dir on HP-UX. Fix pp warnings from rc.d and
+ init.d dirs.
+ [809b54ef95f8]
+
+ * .hgignore, MANIFEST, configure, configure.ac, init.d/aix.sh.in,
+ init.d/hpux.sh.in, src/Makefile.in, sudo.pp:
+ First cut add installing an init.d file for HP-UX and AIX to remove
+ old sudo timestamp files at boot time.
+ [ec6d35c62d88]
+
+2014-02-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Use .Ar macro instead of "file ..." Use ".Cm -" instead of ".Li -"
+ for the default login class. From Ingo Schwarze.
+ [f13ea603760e]
+
+ * doc/sudo.conf.mdoc.in, doc/sudo.mdoc.in, doc/sudo_plugin.mdoc.in,
+ doc/sudoers.ldap.mdoc.in, doc/sudoers.mdoc.in,
+ doc/sudoreplay.mdoc.in, doc/visudo.mdoc.in:
+ Remove some extraneous markup; from Ingo Schwarze
+ * No need to explicitly end a macro with No before | because | counts
+ as middle punctuation and falls out of the macro, anyway.
+ * No need to explicitly re-open in-line macros after | because |
+ counts as middle punctuation and the macros resume afterwards,
+ anyway.
+ * Simplify the mnemonic remarks regarding the option letters, no need
+ for manual font and spacing control with No and Ns.
+ * Trim Ns No to just Ns, it already implies No.
+ [cc63d66c6655]
+
+ * doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Move zerowidth space in :alpha: after the colon for consistency.
+ [799f6656c6e8]
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.man.in, doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudoers.cat, doc/sudoers.ldap.man.in, doc/sudoers.man.in,
+ doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/visudo.cat,
+ doc/visudo.man.in:
+ regen
+ [14d682732b6f]
+
+ * doc/sudo.mdoc.in, doc/sudoreplay.mdoc.in, doc/visudo.mdoc.in:
+ Remove extraneous keeps in SYNOPSIS now that mandoc does implied
+ keeps when converting from mdoc to man.
+ [0f48fc289f29]
+
+ * doc/sudoers.mdoc.in:
+ Properly escape the : in :alpha:
+ [e41d4533a55f]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Replace some uses of .Sy with .Ar, .Ev and .Pa as appropriate. From
+ Jan Stary.
+ [90ec488905de]
+
+2014-02-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo_json.c:
+ Fix indentation of Defaults entries. The initial indent should be
+ outside the loop iterating over the entries.
+ [dc493c888fb2]
+
+2014-02-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po:
+ sync with translationproject.org
+ [fc517bc0908e]
+
+ * common/aix.c, common/alloc.c, common/atoid.c, common/atomode.c,
+ common/fatal.c, common/gidlist.c, common/sudo_conf.c,
+ common/sudo_debug.c, compat/strsignal.c, compat/strtonum.c,
+ plugins/sudoers/audit.c, plugins/sudoers/bsm_audit.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/locale.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/visudo.c, plugins/sudoers/visudo_json.c,
+ src/locale_stub.c, src/net_ifs.c, src/sesh.c, src/sudo.h:
+ We must include gettext.h before missing.h as it includes system
+ headers. Also add missing DEFAULT_TEXT_DOMAIN defines in sudoers
+ audit code that does not include sudoers.h.
+ [3ac4aa43ce40]
+
+ * common/sudo_dso.c:
+ When emulating DSO_NEXT with shl_get() we need to skip the program's
+ handle. This used to be documented as being index -2 but now it
+ seems to be index 0. As this is not guaranteed we need to look up
+ the real handle value for PROG_HANDLE and skip it when interating
+ through all the DSOs. Fixes infinite recursion on HP-UX in the
+ getenv() replacement.
+ [ade1b3045232]
+
+ * src/env_hooks.c:
+ Export getenv() so it is visible to shared objects we link with.
+ [1ac08446a3a7]
+
+2014-02-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/regress/atofoo/atofoo_test.c,
+ common/regress/sudo_conf/conf_test.c,
+ common/regress/sudo_parseln/parseln_test.c,
+ common/regress/tailq/hltq_test.c,
+ plugins/sudoers/regress/parser/check_fill.c:
+ Add some initprogname() calls to the test programs.
+ [e4320585a88b]
+
+2014-02-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [038d066a866d]
+
+ * doc/UPGRADE:
+ Mention that there is now a default LDAP search filter.
+ [6351da3f8377]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ Minor word choice change.
+ [7e59ab3eb453]
+
+ * NEWS, doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/match.c:
+ Add use_netgroups sudoers option. For LDAP-based sudoers, netgroup
+ support requires an expensive substring match on the server. If
+ netgroups are not needed, this option can be disabled to reduce the
+ load on the LDAP server.
+ [e6bd6c103390]
+
+2014-02-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Update copyright year.
+ [1299eed430a5]
+
+ * NEWS:
+ Mention LDAP changes.
+ [512b1e363587]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in, plugins/sudoers/ldap.c:
+ Use a default LDAP search filter of (objectClass=sudoRole). When
+ constructing the netgroup query, add (sudoUser=*) to the query so we
+ don't fall below the 3 character OpenLDAP substring threshold.
+ Otherwise the index for sudoUser will never be used for that query.
+ Pointed out by Michael Stroeder.
+ [54856973af41]
+
+ * plugins/sudoers/timestamp.c:
+ Don't warn about an insecure lecture dir twice. Display warnings in
+ the user's locale.
+ [2c56b8b6d6f9]
+
+2014-02-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Mention the fix for ^Z at the password prompt when sudo was started
+ in the background.
+ [352d52ad1f7d]
+
+ * common/term.c, src/exec_pty.c:
+ In term_restore(), only restores the terminal if we are in the
+ foregroup process group. Instead of calling tcgetpgrp(), which is
+ racy, we set a temporary handler for SIGTTOU and check whether it
+ was received after a failed call to tcsetattr().
+ [94979d51daa2]
+
+ * MANIFEST, compat/getaddrinfo.c, compat/inet_pton.c, config.h.in,
+ configure, configure.ac, doc/LICENSE, include/missing.h, mkdep.pl,
+ plugins/sudoers/interfaces.c, plugins/sudoers/match_addr.c:
+ Use inet_pton() instead of inet_aton() and include a version from
+ BIND for those without it.
+ [fe61a27c76d3]
+
+ * common/regress/atofoo/atofoo_test.c:
+ Quiet a gcc warning.
+ [f197821892ea]
+
+ * compat/getaddrinfo.c:
+ Need to include limits.h for USHRT_MAX.
+ [d1d8bd9a0e01]
+
+2014-02-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/term.c, include/sudo_util.h:
+ Use bool for function return values instead of 1 or 0.
+ [99e357c0800b]
+
+ * configure, configure.ac:
+ Warn the user if the rundir needs to be cleared in the rc files.
+ Neither AIX not HP-UX clear /var/run (if it even exists).
+ [6cdbf57a2f9e]
+
+ * NEWS:
+ Update for sudo 1.8.9p5
+ [efb737c32615]
+
+ * src/preserve_fds.c:
+ When the closefrom limit is greater than any of the preserved fds,
+ the pfds list will be non-empty but lastfd will be -1 triggering an
+ ecalloc(0) assertion. Instead, test for lastfd being -1 and make
+ sure we always update it, even if dup() fails. Also restore initial
+ value of lowfd after we are done relocating. Fixes bug #633
+ [a11206a31f28]
+
+ * common/term.c:
+ Document function return values.
+ [267bc85f6fbb]
+
+2014-02-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c:
+ term_restore() now restarts itself so we don't need to do it
+ ourselves.
+ [a17e885d0b0a]
+
+ * common/term.c:
+ syscall restarting is broken on Mac OS X when interrupted by a tty
+ signal so restart tcsetattr() by hand. For details, see.
+ http://openradar.appspot.com/radar?id=6402578615107584
+ [3997b2a0577e]
+
+ * MANIFEST, common/Makefile.in, common/regress/atofoo/atofoo_test.c:
+ Add regress for atobool(), atoid() and atomode()
+ [e1cbdf86d6e2]
+
+ * plugins/sudoers/Makefile.in:
+ Add back boottime.lo
+ [0b7ddc31e13e]
+
+ * INSTALL:
+ Mention that rundir and vardir may be the same and what to do if
+ they are.
+ [301df9a31d43]
+
+ * MANIFEST, doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/boottime.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/timestamp.c:
+ Bring back boot time checking code and zero out time stamp files
+ that predate the boot time. This should help systems w/o /var/run
+ where the admin has setup rc.d to clear the timestamp directory.
+ [e09389a8b1ca]
+
+ * configure, configure.ac:
+ Check libraries for inet_pton() if not in libc.
+ [9f9bd83895e8]
+
+2014-02-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ Fix clock_gettime() detection when it lives in librt. Some systems
+ have inet_aton() in libresolv (older Solaris).
+ [e5f7c8bc9a81]
+
+ * sudo.pp:
+ Avoid duplicate directories if vardir and rundir are the same.
+ [c5df5ebc191b]
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [740b2cc42fea]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Elaborate on time stamp error message causes.
+ [2838fea2e21a]
+
+2014-02-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Remove the time stamp dir and its contents when uninstalling. We
+ currently leave the lecture status files installed until there is a
+ better way to detect upgrades.
+ [61532b7113ff]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Update time stamp error messages and regen.
+ [edf570c98cd5]
+
+ * plugins/sudoers/timestamp.c:
+ Restore warning when sudoers is unable to update the time stamp
+ file.
+ [86648a771250]
+
+ * INSTALL, Makefile.in, configure, configure.ac, doc/sudoers.mdoc.in,
+ m4/sudo.m4, plugins/sudoers/Makefile.in, sudo.pp:
+ Replace --with-timedir and --with-lecture_dir with --with-rundir and
+ --with-vardir which are the parent directories of the time stamp and
+ lecture dirs. These directories need to be searchable by non-root so
+ that the timestampowner setting can function.
+ [5c38d77a2d0c]
+
+ * plugins/sudoers/timestamp.c:
+ Fix use of timestampowner in the new time stamp world order. Parent
+ directories for timestampdir and lecture_dir are now created with
+ the execute bit set so that we can traverse them as non-root.
+ [9ff6f07c0a5d]
+
+2014-01-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in:
+ Regen Makefiles.
+ [59542bcdb222]
+
+ * common/sudo_debug.c, config.h.in, include/sudo_util.h,
+ plugins/sample/sample_plugin.c:
+ Move ctim_get and mtim_get to sudo_util.h
+ [d565391f5491]
+
+ * plugins/sudoers/timestamp.c:
+ sprinkle some debug printfs and add function header comments
+ [1842d9b8170d]
+
+ * plugins/sudoers/timestamp.c:
+ Properly handle the case where /var/run/sudo/ts doesn't exist.
+ [895f3ad6ad60]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ fix typo
+ [50041ebb6ce6]
+
+ * NEWS:
+ Mention "sudo -K" change.
+ [e99bd7657aae]
+
+ * doc/UPGRADE:
+ Upgrade info for 1.8.10
+ [0867718b9af5]
+
+2014-01-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/timestamp.c:
+ Warn on ftruncate failure().
+ [d2081876da25]
+
+ * plugins/sudoers/timestamp.c:
+ Fix checking of lecture status.
+ [e12d78234d17]
+
+ * mkpkg:
+ Do not override timedir on Debian.
+ [283fa2e69a0a]
+
+ * common/event.c, common/event_select.c, include/missing.h,
+ plugins/sudoers/iolog.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/visudo.c, src/sudo_edit.c:
+ Use sudo_timeval macros and remove compat macros from missing.h
+ [1de76d8b811e]
+
+ * INSTALL, MANIFEST, NEWS, compat/Makefile.in, compat/clock_gettime.c,
+ config.h.in, configure, configure.ac, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, include/missing.h,
+ include/sudo_util.h, m4/sudo.m4, mkdep.pl, pathnames.h.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/boottime.c,
+ plugins/sudoers/check.h, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/timestamp.c, src/Makefile.in:
+ Switch to new time stamp file format. Each user now has a single
+ file which may contain multiple records when per-tty time stamps are
+ in use (the default). The time stamps use a monotonic timer where
+ available and are once again stored in /var/run/sudo. The lecture
+ status is now stored separately from the time stamps in a different
+ directory.
+ [7e16eb37bacc]
+
+ * common/atomode.c:
+ Zero out errstr when there is no error; fixes bug #632
+ [74950ef1a0dc]
+
+2014-01-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/check.c:
+ When listing a user's privileges, always prompt the user for their
+ own password, regardless of the value of target_pw, root_pw or
+ runas_pw.
+ [73a13ccc7933]
+
+2014-01-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac, plugins/sudoers/interfaces.c,
+ plugins/sudoers/match_addr.c:
+ Use inet_aton() instead of inet_addr() as it allows us to
+ distinguish between the address (or mask 255.255.255.255) and an
+ error. In the future we may consider switching to inet_pton() for
+ IPv4 too.
+ [b6b4e4c77e9a]
+
+2014-01-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/missing.h:
+ Fix typo, ULONG_MAX vs. ULLONG_MAX
+ [5d274daa9fb1]
+
+ * plugins/sudoers/sudo_nss.c:
+ Fix typo in the AIX case.
+ [ee531c950fce]
+
+ * plugins/sudoers/sudo_nss.c:
+ Size pointer for sudo_parseln() should be size_t not ssize_t. This
+ was already correct for the nsswitch.conf case.
+ [cfaf895c1db4]
+
+2014-01-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, common/sudo_conf.c, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in, include/sudo_conf.h, src/net_ifs.c:
+ It is now possible to disable network interface probing in sudo.conf
+ by changing the value of the probe_interfaces setting.
+ [e9dc28c7db60]
+
+2014-01-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/match_addr.c:
+ If inet_addr() returns INADDR_NONE, return false instead of
+ iterating through the interfaces looking for a match that will never
+ happen.
+ [1559c301caec]
+
+ * configure, configure.ac, src/Makefile.in:
+ Add explicit dependency on sudoers.la to sudo target when sudoers is
+ compiled statically into the sudo binary.
+ [d08cc66e18bd]
+
+2014-01-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/iolog_path.c, plugins/sudoers/logging.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/timestr.c:
+ Do not assume localtime(), gmtime() and ctime() always return non-
+ NULL.
+ [a1b5b67436de]
+
+2014-01-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, common/Makefile.in, compat/Makefile.in,
+ doc/Makefile.in, include/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in,
+ src/Makefile.in, zlib/Makefile.in:
+ Update copyright years
+ [37d2aaa92544]
+
+ * plugins/sudoers/visudo_json.c:
+ Eliminate dead store found by clang checker.
+ [86874d5340f1]
+
+ * NEWS, configure, configure.ac:
+ Update for sudo 1.8.9p4
+ [f79ab7c6c1c5]
+
+ * common/sudo_debug.c, include/sudo_debug.h, src/preserve_fds.c:
+ When relocating fds, update the debug fd if it is set so we are
+ guaranteed to get debugging output.
+ [b1deaa472aa6]
+
+2014-01-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c:
+ If the event loop exits due to an error and we are not logging I/O,
+ kill the command if still running. Fixes a bug where sudo could exit
+ while the command was still running.
+ [844018ff8a8c]
+
+ * src/preserve_fds.c:
+ When relocating preserved fds, start with the highest ones first to
+ avoid moving fds around more than we have to. Now uses a bitmap to
+ keep track of which fds are being preserved. Fixes a bug where the
+ debugging fd could be relocated to the same fd as the error
+ backchannel temporarily, resulting in debugging output being printed
+ to the backchannel if util@debug was enabled.
+ [55e006dbeaf3]
+
+ * src/preserve_fds.c:
+ When restoring fds traverse list from high -> low, not low -> high
+ to avoid implicitly closing an fd we want to relocate.
+ [6351225f47d7]
+
+ * src/exec.c:
+ If not logging I/O we may get EOF when the command is executed and
+ the other end of the backchannel is closed. Just remove the
+ backchannel event in this case or we will continue to receive the
+ event. Bug #631
+ [a204b69d91f7]
+
+ * src/po/sr.mo, src/po/sr.po:
+ sync with translationproject.org
+ [987087ce4658]
+
+2014-01-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/ttyname.c:
+ Fix strtonum() usage when parsing /proc/self/stat on Linux. Bug #630
+ [3448dffe9701]
+
+ * NEWS, configure, configure.ac:
+ Update for sudo 1.8.9p3
+ [22e5a6f69999]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Do not leak old istack if realloc fails; found by cppcheck. Also
+ modify yyless() to avoid a harmless cppcheck warning every time it
+ is used.
+ [021077017a23]
+
+ * common/term.c:
+ Add suppression line to quiet a bogus (inconclusive) cppcheck
+ warning.
+ [065207271e5d]
+
+ * plugins/group_file/plugin_test.c:
+ Make this compile again
+ [f0ff8df475e8]
+
+ * plugins/sudoers/logwrap.c:
+ Remove dead store; found by cppcheck
+ [a59833af3401]
+
+ * Makefile.in, common/Makefile.in, compat/Makefile.in,
+ doc/Makefile.in, include/Makefile.in,
+ plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in,
+ src/Makefile.in, zlib/Makefile.in:
+ Add cppcheck target to run cppcheck on all source files.
+ [d207c2ef49a2]
+
+2014-01-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, configure, configure.ac:
+ Update for sudo 1.8.9p2
+ [2e7fe6e371a4]
+
+ * config.h.in, configure, ltmain.sh, m4/libtool.m4, m4/ltoptions.m4,
+ m4/ltsugar.m4, m4/ltversion.m4, m4/lt~obsolete.m4:
+ Update to libtool-2.4.2.418
+ [d1dbed89d733]
+
+ * config.guess, config.sub:
+ Update from http://git.savannah.gnu.org/gitweb/?p=config.git
+ [2b5e32d23be5]
+
+2014-01-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sesh.c:
+ Quiet a cppcheck warning about a negative subscript.
+ [ab98b72f5bdf]
+
+ * src/exec_common.c, src/selinux.c, src/sesh.c, src/sudo_exec.h:
+ Make noexec parameter to sudo_execve() bool.
+ [daa75e4c248a]
+
+ * plugins/sudoers/sudoreplay.c:
+ Quiet a few innocuous cppcheck warnings.
+ [90ffa16d27b1]
+
+ * plugins/sudoers/sssd.c:
+ Handle in_res being NULL for sudo_debug_printf() in
+ sudo_sss_filter_result().
+ [8595cc05d2a8]
+
+ * plugins/sudoers/iolog.c:
+ When writing length to timing file, use %u not %d as it is unsigned.
+ [a7f2fcb6919e]
+
+ * plugins/sudoers/visudo_json.c:
+ Close export_fp in the error path too, but do not close stdout.
+ [5c918718ab45]
+
+ * plugins/sudoers/auth/secureware.c:
+ Move right brace outside #ifdef HAVE_DISPCRYPT; found by cppcheck.
+ [f2619d2eb7a8]
+
+ * NEWS:
+ Sudo 1.8.9 also fixes bug #617
+ [cc5c18228719]
+
+2014-01-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ The fix for the hang was already in the 1.8.9 tarballs.
+ [f038ebcc1071]
+
+ * NEWS, configure, configure.ac:
+ Update for sudo 1.8.9p1
+ [732fca0003cf]
+
+ * common/atobool.c, common/event.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/parse.h, src/exec.c, src/preserve_fds.c:
+ Update copyright year.
+ [fdeb5956810e]
+
+ * plugins/sudoers/parse.h:
+ Go back to making the bit fields in struct cmndtag explicitly
+ signed. This fixes a problem on gcc 4.8 (at least) which appears to
+ be treating the value as unsigned by default.
+ [46b9a7bb10ac]
+
+ * common/atobool.c:
+ Use debug_return_int() instead of bare return for debugging support.
+ [c273f822de5f]
+
+2014-01-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/event.c:
+ Fix infinite loop that could be triggered by sudo_ev_loopbreak() and
+ sudo_ev_loopcontinue().
+ [1723561c46b0]
+
+ * NEWS:
+ Update for 1.8.9 final.
+ [d49c14d21410]
+
+2014-01-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ Handle a sequence file with no trailing newline.
+ [aa29306e4f6d]
+
+2014-01-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ Truncate io log and timing files on open when recycling them. Only
+ an issue when the sequence number wraps around.
+ [01b2dfe15ff0]
+
+ * plugins/sudoers/iolog.c:
+ Repair reading of the iolog sequence number that got broken when
+ adding stricter strtoul() checks.
+ [e0f4a11c3437]
+
+ * src/exec.c:
+ If invoked as sudoedit we can't just exec the command directly since
+ the temporary files need to be updated before sudo exits.
+ [508503be1c4f]
+
+ * src/preserve_fds.c:
+ Fix restoration of the close-on-exec flag when moving a relocated fd
+ back into its original position.
+ [5572f1f8b48a]
+
+2014-01-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Add "see below" to reference "Secure editing" section in "Preventing
+ shell escapes".
+ [b2db990a36b3]
+
+2014-01-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Add initial "Secure editing" section.
+ [0d7a192e0e25]
+
+ * doc/LICENSE:
+ Update copyright year.
+ [4a639d9207a9]
+
+2013-12-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po, src/po/eo.mo,
+ src/po/eo.po, src/po/fi.mo, src/po/fi.po:
+ sync with translationproject.org
+ [5c15a411b10d]
+
+ * plugins/sudoers/policy.c:
+ Make user_cwd and user_tty dynamically allocated even for the
+ "unknown" case.
+ [015454bf97f8]
+
+2013-12-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ Use -fstack-protector-strong in preference to -fstack-protector-all
+ or -fstack-protector.
+ [bdd1066eefc4]
+
+ * doc/HISTORY:
+ Dell acquired Quest
+ [3d5b7d27a313]
+
+2013-12-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po, src/po/ru.mo,
+ src/po/ru.po, src/po/vi.mo, src/po/vi.po:
+ sync with translationproject.org
+ [f964671d08ce]
+
+2013-12-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ src/po/cs.mo, src/po/cs.po, src/po/da.mo, src/po/da.po,
+ src/po/it.mo, src/po/it.po, src/po/pl.mo, src/po/pl.po,
+ src/po/pt_BR.mo, src/po/pt_BR.po, src/po/uk.mo, src/po/uk.po,
+ src/po/zh_CN.mo, src/po/zh_CN.po:
+ sync with translationproject.org
+ [5f5becf5fb7a]
+
+ * doc/sudoers.ldap.cat:
+ regen
+ [77745e6bc0d5]
+
+ * NEWS:
+ Update for recent changes.
+ [365b9084268a]
+
+ * plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c:
+ Fix typo; we want setlocale(LC_ALL, "") since we are setting the
+ locale for the first time.
+ [e2b9660e9d48]
+
+2013-12-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c:
+ Use sudoers_initlocale() in main() startup, not sudoers_setlocal()
+ as the latter assumes we are already in the user's locale which may
+ not be the case. For sudoreplay, we can just use setlocale()
+ directly as there is no sudoers locale.
+ [12235e50dea0]
+
+2013-12-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/preserve_fds.c, src/sudo.c, src/sudo.h:
+ Redo preserve_fds support to remap high fds so we can get the most
+ out of closefrom(). The fds are then restored after closefrom().
+ [7d712ec49db7]
+
+ * plugins/sudoers/Makefile.in:
+ Fix install-plugin when sudoers is compiled statically.
+ [36a8bf3b588d]
+
+2013-12-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, common/sudo_debug.c, doc/sudo_plugin.cat,
+ doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ include/sudo_debug.h, include/sudo_plugin.h, src/Makefile.in,
+ src/exec.c, src/exec_pty.c, src/preserve_fds.c, src/sudo.c,
+ src/sudo.h, src/sudo_exec.h:
+ Add support for preventing fds from getting clobbered by
+ closefrom().
+ [269f45964ff0]
+
+2013-12-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ regen
+ [b8f458379b5b]
+
+2013-12-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/alloc.c:
+ Need to include limits.h here too.
+ [b53c6edef597]
+
+2013-12-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.ac, plugins/sudoers/parse.h:
+ No need to use __signed.
+ [05f9648d1953]
+
+ * plugins/sudoers/regress/logging/check_wrap.c:
+ Need limits.h here too.
+ [54aac3bbf66a]
+
+ * compat/closefrom.c:
+ Still need limits.h here.
+ [0abc6b2be208]
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [386b47ced07f]
+
+ * compat/closefrom.c:
+ Go back to using /proc/self/fd instead of /proc/$$/fd as only AIX
+ lacks /proc/self and it has F_CLOSEM.
+ [b5735fbcfdce]
+
+2013-12-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo_json.c:
+ Use a switch to map digest type to name instead of an array of
+ strings.
+ [ab17ceb4dd60]
+
+ * compat/closefrom.c:
+ Use /dev/fd in closefrom() on FreeBSD < 8.0 and Mac OS X.
+ [e70df3b3144b]
+
+ * compat/snprintf.c:
+ Remove _MAX and _MIN compat; we rely on missing.h for that. We
+ already require the compiler handle long long so there's no need to
+ use HAVE_LONG_LONG_INT everywhere.
+ [2bda15071439]
+
+ * common/ttysize.c, include/missing.h:
+ Remove _MAX and _MIN defines that any system from the last 20 years
+ should have. Add ULLONG_MAX in case it is missing.
+ [2db0cee4aaa8]
+
+ * doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in,
+ plugins/sudoers/visudo.c, plugins/sudoers/visudo_json.c:
+ Change visudo -x to take a file name argument, which may be '-' to
+ write the exported sudoers file to stdout.
+ [84cb72c3c391]
+
+ * plugins/sudoers/auth/bsdauth.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/parse.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/visudo.c,
+ plugins/sudoers/visudo_json.c, src/regress/ttyname/check_ttyname.c:
+ Move symbol extern defs into sudoers.h
+ [b631a0b57fae]
+
+ * plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/logging/check_wrap.c:
+ Add missing sudo_util.h
+ [ed0edc2e2d0c]
+
+2013-12-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c:
+ Warn if the time stamp in the I/O log file does not fit in time_t.
+ Warn if the info line is not well-formed instead of silently
+ ignoring it.
+ [37a050de5be5]
+
+2013-12-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/Makefile.in, plugins/sudoers/Makefile.in, src/Makefile.in:
+ Rename libcommon libsudo_util
+ [df3ffd4229e5]
+
+2013-12-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, common/Makefile.in, common/aix.c, common/atobool.c,
+ common/atoid.c, common/atomode.c, common/fmt_string.c,
+ common/gidlist.c, common/progname.c, common/setgroups.c,
+ common/sudo_conf.c, common/term.c, common/ttysize.c,
+ include/missing.h, include/sudo_util.h,
+ plugins/group_file/Makefile.in, plugins/group_file/getgrent.c,
+ plugins/sudoers/Makefile.in, plugins/sudoers/sudoers.h,
+ plugins/sudoers/sudoreplay.c, plugins/system_group/Makefile.in,
+ plugins/system_group/system_group.c, src/Makefile.in, src/sudo.h:
+ Move prototypes for functions provided by libcommon that don't have
+ their own header files into sudo_util.h.
+ [43f423a24416]
+
+2013-12-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/mkdefaults:
+ Now that we have proper number parsing functions we should store
+ T_UINT defaults values as unsigned int, not int.
+ [67d8c2244f1d]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h:
+ Don't use int where we really mean enum def_tuple. When this code
+ was written it was assumed that we may have multiple tuple types.
+ However, that hasn't happened and probably never will.
+ [8491f970f343]
+
+ * plugins/sudoers/po/sudoers.pot, src/po/sudo.pot:
+ Regen after string parsing changes.
+ [fd6bf79c3286]
+
+ * common/atoid.c, common/atomode.c, compat/strtonum.c, configure,
+ configure.ac, include/missing.h, plugins/sudoers/defaults.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/sudoreplay.c, src/parse_args.c, src/ttyname.c:
+ The OpenBSD strtonum() uses very short error strings that can't be
+ translated usefully. Convert them to longer strings on error. Also
+ use the longer strings for atomode() and atoid().
+ [dace028594da]
+
+2013-12-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, common/Makefile.in, common/atoid.c, common/atomode.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.h, src/sudo.c, src/sudo.h:
+ Add atomode() function for parsing a file mode.
+ [44e29629aa5e]
+
+ * common/sudo_conf.c, common/ttysize.c, compat/Makefile.in,
+ compat/closefrom.c, compat/getaddrinfo.c, compat/strtonum.c,
+ configure, configure.ac, include/missing.h,
+ plugins/sudoers/boottime.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/match_addr.c, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/sudoreplay.c, plugins/system_group/system_group.c,
+ src/parse_args.c, src/sudo.c, src/ttyname.c:
+ Use strtonum() instead of atoi(), strtol() or strtoul() where
+ possible.
+ [e4a1fc84b893]
+
+ * MANIFEST, compat/Makefile.in, compat/strtonum.c, config.h.in,
+ configure, configure.ac, include/missing.h, mkdep.pl:
+ Add strtonum.c to compat for simpler number parsing.
+ [a4c69b003da0]
+
+2013-12-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_common.c:
+ Fix a warning on Solaris, we need to use debug_return_const_ptr.
+ [932aa94c0cac]
+
+ * plugins/sudoers/Makefile.in:
+ check_symbols needs to link with SUDO_LIBS in order to get -lpthread
+ on HP-UX for libldap (which uses threads). It would be better to
+ have a separate variable for the pthread library but this is no
+ worse than it used to be.
+ [94591b765371]
+
+2013-12-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ add missing comma
+ [7dcbd1c6dd25]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Make -c option description more accurate.
+ [3f305ae6037e]
+
+2013-12-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS, plugins/sudoers/sudoers.c:
+ When checking whether a user may change the login class, just check
+ pw_uid of the runas user, which was passed in to set_loginclass().
+ [aaf736440441]
+
+2013-12-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo_json.c:
+ Use atoid() when parsing user/group IDs and print them as unsigned
+ int.
+ [40c77459a36a]
+
+2013-12-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c:
+ Correctly parse 64-bit times in I/O log files.
+ [d053ee75adc3]
+
+ * compat/getgrouplist.c, plugins/group_file/getgrent.c,
+ plugins/sudoers/pwutil.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/testsudoers.c:
+ Use atoid() not atoi() when parsing uids/gids.
+ [491146596626]
+
+ * plugins/sudoers/match.c, plugins/sudoers/match_addr.c,
+ plugins/sudoers/parse.h, plugins/sudoers/pwutil.c,
+ plugins/sudoers/pwutil.h, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/sudoers.h:
+ Better match debugging. Sprinkle const in match functions.
+ [4cd8d793f165]
+
+2013-12-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in:
+ Document that plugins can be compiled statically into the sudo
+ binary.
+ [434061cf909f]
+
+2013-12-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sssd.c:
+ sudo_sss_filter_user_netgroup(): fix comment typos, break out of
+ loop early if we match ALL or netgroup.
+ [0691731f4b12]
+
+ * plugins/sudoers/sssd.c:
+ When filtering netgroups, use the passwd struct stashed in the
+ handle, not user_name since we may be listing another users
+ privileges.
+ [f2669cf7b70c]
+
+ * mkpkg:
+ RHEL 6 and above builds sudo with SSSD support
+ [afc3d894851e]
+
+ * plugins/sudoers/sssd.c:
+ Avoid passing NULL domainname to sudo_debug_printf().
+ [b08abe5e6d23]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document sssd debug subsystem.
+ [250c3ab1bcf0]
+
+ * doc/sudo.conf.cat, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in:
+ Document "event" debug subsystem.
+ [85d220b48edc]
+
+ * plugins/sudoers/match.c:
+ Use atoid() instead of atoi() when parsing uids/gids so we get
+ proper range checking.
+ [5c3e2f3f6cb9]
+
+ * plugins/sudoers/sssd.c:
+ Add user netgroup filtering for SSSD. Previously, rules for a
+ netgroup were applied to all even when they did not belong to the
+ specified netgroup. RedHat Bugzilla 880150.
+ [784848b5462c]
+
+ * plugins/sudoers/sssd.c:
+ Fix several issues found by the clang static analyzer; Daniel
+ Kopecek
+ [520261dd7461]
+
+2013-12-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * README.LDAP:
+ Mention how to dump sudoers info from LDAP.
+ [a53c93790a30]
+
+ * src/exec_common.c:
+ On Solaris, disabling the proc_exec privilege appears to interfere
+ with DAC file permissions. Adding DAC override permissions to the
+ inheritable set works around this for commands run as root without
+ giving extra permissions to other users. Bug #626
+ [391ad44026c3]
+
+2013-12-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, common/Makefile.in, common/progname.c, compat/Makefile.in,
+ compat/getprogname.c, configure, configure.ac, include/missing.h,
+ mkdep.pl, plugins/sample/sample_plugin.c, plugins/sudoers/policy.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c, src/parse_args.c,
+ src/regress/ttyname/check_ttyname.c, src/sudo.c:
+ Instead of setprogname(), add initprogname() which gets the program
+ name for getprogname() using /proc or pstat() if possible.
+ [e2d48d81456f]
+
+2013-11-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/ttyname.c:
+ Ignore EOVERFLOW from pstat_getproc(). The HP-UX kernel appears to
+ return this in certain situations but it appears to be harmless at
+ least insofar as retrieving the tty goes.
+ [105bea4e1c20]
+
+ * plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ src/po/cs.mo, src/po/cs.po, src/po/eo.mo, src/po/eo.po,
+ src/po/fi.mo, src/po/fi.po, src/po/it.mo, src/po/it.po,
+ src/po/pl.mo, src/po/pl.po, src/po/pt_BR.mo, src/po/pt_BR.po,
+ src/po/ru.mo, src/po/ru.po, src/po/uk.mo, src/po/uk.po,
+ src/po/vi.mo, src/po/vi.po, src/po/zh_CN.mo, src/po/zh_CN.po:
+ Sync with translationproject.org
+ [3694d7ad4c9d]
+
+2013-11-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo.c:
+ Add missing newline in help message after export option.
+ [1c0bff0c181e]
+
+2013-11-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac, plugins/sudoers/Makefile.in,
+ src/Makefile.in:
+ Do not add LIBDL to SUDO_LIBS or SUDOERS_LIBS in configure, do it in
+ Makefile.in so we can make it last. Fixes a linking problem on
+ Ubuntu precise.
+ [f8d3bddbe742]
+
+2013-11-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, m4/ax_func_getaddrinfo.m4:
+ Do not rely on NULL being defined for getaddrinfo() test. Fixes the
+ check on HP-UX 11.23.
+ [a5dcf0283693]
+
+2013-11-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot, src/po/sudo.pot:
+ Regen for sudo 1.8.9b1
+ [945f27a7aa1c]
+
+ * src/po/de.mo, src/po/de.po, src/po/sr.mo, src/po/sr.po:
+ Sync with translationproject.org
+ [52abae16ccfa]
+
+2013-11-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, MANIFEST, NEWS, common/Makefile.in, common/sudo_dso.c,
+ compat/Makefile.in, compat/dlfcn.h, compat/dlopen.c, config.h.in,
+ configure, configure.ac, include/sudo_dso.h, mkdep.pl,
+ plugins/sudoers/Makefile.in, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/ldap.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/sssd.c, plugins/system_group/Makefile.in,
+ plugins/system_group/system_group.c, src/Makefile.in,
+ src/env_hooks.c, src/load_plugins.c, src/preload.c, src/sudo.c,
+ src/sudo.h:
+ Add wrapper functions for dlopen() et al so that we can support
+ statically compiling in the sudoers plugin but still allow other
+ plugins to be loaded. The new --enable-static-sudoers configure
+ option will cause the sudoers plugin to be compiled statically into
+ the sudo binary. This does not prevent other plugins from being
+ loaded as per sudo.conf.
+ [9425770e9d2b]
+
+2013-11-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo_json.c:
+ Handle non-unix groups correctly. Get rid of runasuser and
+ runasgroup types and use username and usergroup instead. The fact
+ that the user or group is inside a Runas_List doesn't affect its
+ underlying type.
+ [ea1789258c11]
+
+2013-11-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo_json.c:
+ Simplify Defaults list option object. The name and value strings are
+ superfluous.
+ [5852b0184669]
+
+ * compat/dlopen.c:
+ Back out unintended change.
+ [85156e49e96e]
+
+ * MANIFEST, aclocal.m4, configure, configure.ac,
+ m4/ax_func_getaddrinfo.m4:
+ Add dedicated test for getaddrinfo(). Tru64 UNIX contains two
+ versions of getaddrinfo and we must include netdb.h to get the
+ proper definition.
+ [9882e3e1e8e3]
+
+ * compat/dlopen.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c:
+ Define RTLD_GLOBAL for older systems without it. Bug #621
+ [ed38ac84f1da]
+
+2013-11-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/snprintf.c, include/missing.h:
+ Rename snprintf replacement rpl_snprintf since we may now replace
+ the libc version and #define rpl_snprintf snprintf in missing.h so
+ we get our version when needed. This is consistent with how we
+ replace glob and fnmatch.
+ [309aa17d0dfe]
+
+ * common/Makefile.in, common/regress/sudo_conf/conf_test.c,
+ common/regress/sudo_parseln/parseln_test.c,
+ common/regress/tailq/hltq_test.c, src/Makefile.in:
+ libcommon tests need locale_stub.lo to link.
+ [baae40f36de5]
+
+ * MANIFEST, aclocal.m4, compat/snprintf.c, config.h.in, configure,
+ configure.ac, m4/ax_func_snprintf.m4:
+ Add check for C99 compliant (v)snprintf function.
+ [79e02551543c]
+
+ * compat/sig2str.c, configure, configure.ac:
+ Include unistd.h in sig2str.c for Tru64 as it defines SIGRTMIN and
+ SIGRTMAX in terms of sysconf(), which is prototyped in unistd.h. Bug
+ #621; from Daniel Richard G.
+ [2a59ccb8c966]
+
+ * include/gettext.h, plugins/sudoers/locale.c, src/locale_stub.c:
+ Add definition of U_ for --disable-nsl Don't define warning_gettext
+ if --disable-nsl Bug #621; from Daniel Richard G.
+ [c0054eb89c2b]
+
+2013-11-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo_json.c:
+ When merging Defaults entries we need to check the type of the next
+ entry and not just assume it is the same as the previous one.
+ [e97d9b9cf0d5]
+
+ * plugins/sudoers/visudo_json.c:
+ runasgroups not runasgroup in the Cmnd_Spec.
+ [92ea5dc20e4d]
+
+ * plugins/sudoers/visudo_json.c:
+ Fix some syntax errors and change how lists are handled.
+ [027b8dea44b2]
+
+ * common/sudo_debug.c, config.h.in, configure, configure.ac,
+ include/fatal.h, include/sudo_debug.h:
+ Allow sudo to compile without variadic macro support in cpp.
+ Debugging support will be limited (no file info from warnings.) From
+ Daniel Richard G.; Bug #621
+ [51b8b868cd4b]
+
+ * Makefile.in, common/aix.c, common/fatal.c, common/gidlist.c,
+ common/sudo_conf.c, include/fatal.h, include/gettext.h,
+ include/missing.h, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/rfc1938.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/bsm_audit.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/env.c, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/locale.c,
+ plugins/sudoers/logging.c, plugins/sudoers/match.c,
+ plugins/sudoers/policy.c, plugins/sudoers/prompt.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/set_perms.c,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timestamp.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/toke_util.c,
+ plugins/sudoers/visudo.c, plugins/sudoers/visudo_json.c, src/exec.c,
+ src/exec_common.c, src/exec_pty.c, src/load_plugins.c,
+ src/locale_stub.c, src/net_ifs.c, src/parse_args.c, src/selinux.c,
+ src/sesh.c, src/signal.c, src/solaris.c, src/sudo.c,
+ src/sudo_edit.c, src/tgetpass.c, src/utmp.c:
+ Add warning_gettext() wrapper function that changes to the user
+ locale, then calls gettext(). Add U_ macro that calls
+ warning_gettext() instead of gettext(). Rename warning2()/error2()
+ back to warning_nodebug()/error_nodebug().
+ [f3bb207db201]
+
+2013-11-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/fileops.c, compat/getaddrinfo.c, compat/mktemp.c,
+ compat/utimes.c, configure.ac, plugins/sudoers/boottime.c,
+ plugins/sudoers/check.c, plugins/sudoers/getdate.c,
+ plugins/sudoers/getdate.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/logging.h, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/visudo.c, src/exec.c, src/exec_pty.c, src/preload.c,
+ src/sudo.c, src/sudo_edit.c, src/ttyname.c, src/utmp.c:
+ Fix some #if vs. #ifdef and remove an extraneous semicolon. Bug
+ #624; from Daniel Richard G.
+ [b212e4694018]
+
+ * include/sudo_debug.h, plugins/sudoers/defaults.c,
+ plugins/sudoers/ldap.c, src/exec_common.c:
+ Add debug_return_const_str and debug_return_const_ptr for returning
+ a const string or pointer. Using const for the normal versions
+ produces warnings with the Tru64 compiler.
+ [45018a149cb4]
+
+ * common/event_poll.c, compat/getaddrinfo.c, config.h.in, configure,
+ configure.ac, m4/sudo.m4:
+ Fixes for building under Tru64; from Daniel Richard G. Bug #624
+ [fc4a6cbae1ba]
+
+2013-11-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/logging.c:
+ log_{fatal,warning} now logs to the debug file itself.
+ log_{fatal,warning} now calls warningx2() after setting the locale
+ itself instead of using the wrapper macros. This removes the only
+ use of warningx(ngettext(...)).
+ [930129361e0a]
+
+2013-11-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.ac:
+ Add -Wpointer-arith to --enable-warnings
+ [2043ae306d1b]
+
+ * configure, configure.ac:
+ Fix more instances of #include directives where the '#' was not in
+ column 1. From Daniel Richard G. (bug #622)
+ [75f36f39dcab]
+
+ * MANIFEST, doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/visudo.c,
+ plugins/sudoers/visudo_json.c:
+ Add support to visudo to export sudoers in JSON format.
+ [1697b2b4bfd2]
+
+2013-11-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/parse.h:
+ Remove unused digest field from struct cmndspec, the digest really
+ lives in struct sudo_command.
+ [e9a1e2e112d6]
+
+ * config.h.in, configure:
+ Regen with autoconf 2.69
+ [275f69f98f9e]
+
+ * MANIFEST, Makefile.in, config.h.in, configure.ac, configure.in,
+ doc/Makefile.in:
+ Rename configure.in -> configure.ac
+ [0aeafe425373]
+
+ * MANIFEST, aclocal.m4, autogen.sh, config.h.in, configure,
+ configure.in, ltmain.sh, m4/sudo.m4:
+ From Daniel Richard G. (bug #622) Add an autogen.sh script that
+ rebuilds the autoconf world. Move old aclocal.m4 contents to
+ m4/sudo.m4. New (generayed) aclocal.m4 contains the m4_include
+ directives. Some tests had #include directives where the '#' was not
+ in column 1. Updated obsolete macro usage via autoupdate.
+ [5fe8de5a56df]
+
+2013-11-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo_exec.h:
+ Very old systems (pre XPG 4.2) may not support MSG_WAITALL. The
+ likelihood of receiving a partial message is quite low so this is
+ not a big deal.
+ [900a304f9548]
+
+ * configure, configure.in:
+ HP-UX may require _XOPEN_SOURCE_EXTENDED to be defined for
+ MSG_WAITALL to be visible.
+ [f08b1a00a30a]
+
+ * MANIFEST, plugins/sudoers/regress/visudo/test5.out.ok,
+ plugins/sudoers/regress/visudo/test5.sh:
+ Add regress test for bug #623
+ [8e83cfccaf14]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Cope with a comment on the last line of the file with no newline.
+ Bug #623
+ [f826243bc4e6]
+
+ * compat/getaddrinfo.c:
+ Include arpa/inet.h for HP-UX; from Daniel Richard G.
+ [d4d7a4303bae]
+
+ * doc/Makefile.in:
+ Add missing $(mansrcdir) to visudo.mdoc and visudo.man. From Daniel
+ Richard G.
+ [f664c8d2f961]
+
+2013-11-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/fatal.h:
+ In v{warning,fatal}x?() make a new copy of ap for the debug
+ functions. It is not legal to use ap twice without reinitializing
+ it. Noticed by Daniel Richard G.
+ [6ca8bc48ecb3]
+
+ * include/fatal.h:
+ Remove errant warning_restore_locale() call.
+ [4ef7aecefcbb]
+
+ * include/missing.h, plugins/sudoers/logging.c:
+ Move va_copy compat macro to missing.h
+ [c873e4cc4c8a]
+
+ * common/Makefile.in, compat/Makefile.in, mkdep.pl,
+ plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in,
+ src/Makefile.in, zlib/Makefile.in:
+ Uniquify header dependencies so we don't end up with duplicates when
+ a header file includes other headers. The header dependencies are
+ sorted so the generated order is stable.
+ [95747db2f07a]
+
+ * compat/Makefile.in, configure, configure.in, doc/CONTRIBUTORS,
+ mkdep.pl:
+ Add getaddrinfo.lo to LTLIBOBJS for systems that need it. From
+ Daniel Richard G.
+ [e94ee99a52a9]
+
+ * plugins/sudoers/testsudoers.c:
+ Fix pasto
+ [5262735e78e0]
+
+2013-11-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.mdoc.in:
+ Fix typo.
+ [6b11a4eec6b6]
+
+2013-11-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/getdate.c, plugins/sudoers/gram.c:
+ regen
+ [995ca9f21862]
+
+ * plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/toke.c:
+ Fix warnings from -Wold-style-definition
+ [a748c5c7b423]
+
+ * configure, configure.in:
+ Add -Wold-style-definition to --enable-warnings
+ [0484de0deb59]
+
+ * common/event_poll.c:
+ Extra debugging for ready fds.
+ [91fb85cdecbb]
+
+ * common/event_select.c:
+ When deleting an event, check ev->events to determine whether to
+ remove from readfds or writefds instead of blinding removing from
+ both. Also fix highfd adjustment.
+ [7384db65ca9c]
+
+2013-11-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/event_select.c:
+ Only check an fd that is >= 0. Timeout-only events may have a
+ negative fd.
+ [fa0e5cbc3cc2]
+
+2013-11-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/event.c:
+ Don't call sudo_ev_{add,del}_impl() for timeout-only events. This
+ makes it possible to pass sudo_ev_alloc() an fd of -1 for events
+ only use SUDO_EV_TIMEOUT.
+ [6838657a1a2f]
+
+2013-10-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/alloc.c, common/event_select.c, include/sudo_event.h:
+ Make a copy of readfds/writefds before calling select() instead of
+ calculating it each time. Keep track of high fd in the base.
+ [6048b78f2e94]
+
+2013-10-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS:
+ Add Stephen Gelman
+ [0028c7a91a4f]
+
+ * plugins/sudoers/getdate.c, plugins/sudoers/gram.c:
+ Fix sign comparison warning.
+ [914cb36b9ed2]
+
+ * plugins/sudoers/sudoreplay.c:
+ Fix potential NULL dereference in non-interactive mode.
+ [9233428d3f32]
+
+2013-10-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c, src/exec_pty.c:
+ Use MSG_WAITALL when receiving struct command_status over the Unix
+ domain socket since we no longer use datagrams. This should avoid
+ the need to handle incomplete reads, though in theory it is still
+ possible.
+ [28a92888a908]
+
+ * plugins/sudoers/sudoreplay.c:
+ SIGKILL is not catchable
+ [79f82e4cb11d]
+
+ * common/event.c, include/sudo_event.h, plugins/sudoers/sudoreplay.c:
+ Add sudo_ev_get_timeleft() to get the amount of time left before an
+ event times out and use it in sudoreplay.
+ [d5b17ee30fa4]
+
+2013-10-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in,
+ plugins/sudoers/sudoreplay.c:
+ If the user presses <return> or <enter> in sudoreplay, skip to the
+ next event. Useful for skipping past long pauses in the data.
+ [43343f45c94d]
+
+ * common/event.c, common/event_poll.c, common/event_select.c:
+ Fix sudo_ev_scan_impl() return value in event_poll.c. Make sure we
+ clear active flag from unprocessed events if sudo_ev_loopbreak() or
+ sudo_ev_loopcontinue() are used. Remove bogus optimization when the
+ timeout is zero or negative; it could prevent an I/O event from
+ being triggered.
+ [a13603fb3134]
+
+ * plugins/sudoers/sudoreplay.c:
+ Move session replay into its own function.
+ [e323f7729595]
+
+ * common/event.c, common/event_poll.c, common/event_select.c,
+ include/sudo_event.h:
+ Get rid of cur and pending pointers in struct sudo_event_base. We
+ now pop the first event off the active queue instead of using a
+ foreach loop with deferred removal of the event. Add
+ SUDO_EVQ_INSERTED and SUDO_EVQ_TIMEOUTS flags to indicate that the
+ event on the event queue and timeouts queue respectively. No longer
+ need to compare the timeout to {0,0} or compare the event's base
+ pointer to NULL to determine queue membership.
+ [f2b2251fd523]
+
+ * common/event_poll.c:
+ rename sudo_ev_loop_impl() -> sudo_ev_scan_impl()
+ [614faaff04e3]
+
+ * MANIFEST, common/event.c, common/event_poll.c,
+ common/event_select.c, compat/Makefile.in, compat/nanosleep.c,
+ config.h.in, configure, configure.in, include/missing.h,
+ include/sudo_event.h, mkdep.pl, plugins/sudoers/Makefile.in,
+ plugins/sudoers/sudoreplay.c, src/exec.c, src/exec_pty.c:
+ Add support for libevent-style timed events. Adding a timed event is
+ currently O(n). The only consumer of timed events is sudoreplay
+ which only used a singled one so O(n) == O(1) for now. This also
+ allows us to remove the nanosleep compat function as we now use a
+ timeout event instead.
+ [db41c08e92dc]
+
+2013-10-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c, src/exec_pty.c:
+ Now that sudo_ev_base_free() removes all events before freeing we
+ don't need to do this by hand.
+ [b59d43658c5f]
+
+ * common/event.c, common/event_poll.c, common/event_select.c,
+ include/sudo_event.h:
+ Add a list of active events in the base that the back end sets when
+ it calls poll or select. This allows the front end to iterate over
+ the events instead of having that code in both back ends. It will
+ also simplify support for timeout events. Also make sure we can't
+ touch freed memory if a callback frees its own event.
+ [933b99b3f2bc]
+
+ * common/event.c:
+ Remove any existing events before freeing the event base.
+ [2543c6620cf1]
+
+2013-10-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c:
+ mon_handler() should be static
+ [b1a62ef65c96]
+
+2013-10-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ If user specified start_tls and ldaps, display a warning and ignore
+ start_tls. There's no reason to make this a fatal error.
+ [bf446dd1e740]
+
+ * src/exec_pty.c:
+ Add missing else when the connection from the monitor to the parent
+ sudo process is broken (due to the parent dying). Prevents a
+ spurious "unexpected reply type on backchannel" warning.
+ [5c44053cef08]
+
+ * src/exec_pty.c:
+ When flushing output we don't care whether we are the foreground
+ process or not, we still need to flush to /dev/tty. If we are in the
+ background, it is OK to get SIGTTOU.
+ [9716892d1fb5]
+
+ * plugins/sudoers/ldap.c:
+ Should not attempt start_tls on an ldaps connection.
+ [9d01d461c52c]
+
+2013-10-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/regress/parser/check_fill.c:
+ Fix sign compare warning.
+ [6130fa8df758]
+
+ * doc/Makefile.in:
+ Eliminate warning about circular dependency from GNU make.
+ [7ed5df762089]
+
+ * plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c,
+ src/ttyname.c:
+ More sign compare fixes. On Solaris id_t is signed so use uid_t in
+ the set_perms.c ID macro instead.
+ [8166dcc50d0b]
+
+ * common/fileops.c, common/lbuf.c, common/secure_path.c,
+ common/sudo_debug.c, include/secure_path.h,
+ plugins/sudoers/find_path.c, plugins/sudoers/getdate.c,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/interfaces.h,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_path.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/logging.c,
+ plugins/sudoers/match_addr.c, plugins/sudoers/parse.h,
+ plugins/sudoers/policy.c, plugins/sudoers/prompt.c,
+ plugins/sudoers/pwutil_impl.c, plugins/sudoers/set_perms.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, src/load_plugins.c, src/sudo.c,
+ src/ttyname.c:
+ Quiet sign comparision warnings.
+ [e34f45dad10c]
+
+ * configure, configure.in:
+ Add -Wsign-compare to --enable-warnings
+ [d560e274a6ae]
+
+ * plugins/sudoers/ldap.c:
+ Ignore SIGPIPE when connecting to the LDAP server so we can get a
+ proper error message with the IBM LDAP libs. Also return
+ LDAP_SUCCESS instead of 0 from most sudo_ldap_* functions that
+ return an int.
+ [611a4ed9b8ee]
+
+ * plugins/sudoers/regress/parser/check_base64.c,
+ plugins/sudoers/regress/parser/check_digest.c:
+ Quiet compiler warnings.
+ [7d82dcca7126]
+
+2013-10-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ sudo_ldap_parse_uri() should join multiple URIs in the string list
+ together but it was clearing the host entry each time through the
+ loop. Fixes a bug with multiple URI entries in ldap.conf where only
+ the last one was being honored.
+ [83cee19b136d]
+
+ * src/exec_pty.c:
+ Avoid a double free introduced when plugging a memory leak in
+ safe_close(). A new ev_free_by_fd() function is used to remove and
+ free any events sharing the specified fd. This can be used after
+ safe_close() to make sure we don't try to select() on a closed fd.
+ [54f48a281147]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y, src/exec.c:
+ Quiet some llvm check false positives. The common idiom of using
+ TAILQ_FIRST, TAILQ_REMOVE and free in a loop to free each entry in a
+ TAILQ confuses llvm. Use TAILQ_FOREACH_SAFE instead (which is
+ probably faster anyway).
+ [bd1b8c11f416]
+
+ * plugins/sudoers/auth/pam.c:
+ If pam_open_session() fails don't call pam_getenvlist() with a NULL
+ pam handle.
+ [352e0329acba]
+
+ * plugins/sudoers/defaults.c:
+ Fix newly introduced use after frees found by llvm checker.
+ [a81080230f1f]
+
+ * common/event_select.c:
+ Remove an errant list_next() call that should have been removed in
+ the TAILQ conversion.
+ [3bbf8d117ce4]
+
+ * MANIFEST, common/Makefile.in, common/list.c,
+ common/regress/tailq/hltq_test.c, include/list.h, include/queue.h,
+ plugins/sudoers/Makefile.in, plugins/sudoers/alias.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/match.c,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Add "headless" tail queues and use them in place of the semi-
+ circular lists in sudoers. Once the headless tail queue is built up
+ it is converted to a normal TAILQ. This removes the last consumer of
+ list.c and list.h so those can now be removed.
+ [5986ba762a24]
+
+ * common/Makefile.in, common/fatal.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/env.c, plugins/sudoers/interfaces.c,
+ plugins/sudoers/interfaces.h, plugins/sudoers/ldap.c,
+ plugins/sudoers/match_addr.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/visudo.c, src/Makefile.in, src/exec_pty.c,
+ src/hooks.c:
+ Use SLIST and STAILQ macros instead of doing headless singly linked
+ lists manually. As a bonus we now use a tail queue for ldap.c and
+ sudoreplay.c.
+ [c31bc2d99082]
+
+ * MANIFEST, common/Makefile.in, common/event.c, common/event_poll.c,
+ common/event_select.c, common/list.c,
+ common/regress/sudo_conf/conf_test.c, common/sudo_conf.c,
+ doc/LICENSE, include/list.h, include/missing.h, include/queue.h,
+ include/sudo_conf.h, include/sudo_event.h,
+ plugins/sudoers/Makefile.in, plugins/sudoers/ldap.c,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/sssd.c, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudo_nss.h, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/visudo.c,
+ src/Makefile.in, src/exec.c, src/exec_pty.c, src/load_plugins.c,
+ src/sudo.c, src/sudo.h, src/sudo_plugin_int.h:
+ Convert sudo to use BSD TAILQ macros instead of home ground tail
+ queue functions. This includes a private queue.h header derived from
+ FreeBSD. It is simpler to just use our own header rather than try to
+ deal with macros that may or may not be present in various queue.h
+ incarnations.
+ [450bce095d7c]
+
+2013-10-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c:
+ Fix AND operator broken by changes to fix OR.
+ [a4d3485ee943]
+
+2013-10-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c:
+ Fix OR operator.
+ [f5c1c90ee284]
+
+2013-10-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c:
+ Fix memory leak of I/O buffer events in safe_close().
+ [08cd790cfbba]
+
+2013-10-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/sudo_debug.c:
+ Don't allow the debug subsystem to be initialized twice. Otherwise
+ we can exhuast our stack when built in static mode.
+ [fadacb6a4617]
+
+ * common/event_poll.c:
+ Make sure we do not try to usie index -1 in base->pfds[].
+ [beeb922aba3f]
+
+2013-10-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, configure, configure.in:
+ Bump version to 1.8.9
+ [758dbb464796]
+
+2013-10-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c:
+ Convert the monitor process to the event subsystem.
+ [c4fe8e2ba53c]
+
+ * src/exec.c, src/exec_pty.c, src/sudo_exec.h:
+ Convert the main sudo event loop to use the event subsystem. Read
+ events for I/O buffers are added before the loop starts. Write
+ events are added on demand as the buffers are filled.
+ [72a603e997e0]
+
+ * INSTALL, MANIFEST, common/Makefile.in, common/event.c,
+ common/event_poll.c, common/event_select.c, common/list.c,
+ common/sudo_debug.c, config.h.in, configure, configure.in,
+ include/list.h, include/sudo_debug.h, include/sudo_event.h,
+ mkdep.pl, plugins/sudoers/Makefile.in, src/Makefile.in,
+ src/exec_pty.c:
+ Simple event subsystem that uses poll() or select(). Basically a
+ simplied subset of libevent2. Currently only fd events are supported
+ (since that's all we need). The poll() backend is used by default,
+ except on Mac OS X where poll() is broken for devices (including
+ /dev/tty and ptys).
+ [8773142b4117]
+
+ * src/exec.c, src/exec_pty.c:
+ Use SOCK_STREAM for socketpair, not SOCK_DGRAM so we get consistent
+ semantics when the other end closes. This should make the conversion
+ to poll() less problematic.
+ [b6a321722a91]
+
+2013-10-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/sudo_debug.c:
+ Fix removal of trailing newlines in a debug message.
+ [6f5ce5ac64e0]
+
+2013-10-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo.c:
+ When checking for unused Runas_Aliases, count those used as part of
+ a Runas Group too. Fixes a false positive warning.
+ [f13271a4a377]
+
+2013-09-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/missing.h:
+ Include stddef.h for rsize_t and errno_t on systems that support it
+ natively.
+ [bc547d47e9c6]
+
+ * MANIFEST:
+ Fix braino.
+ [67b79747312f]
+
+ * plugins/sudoers/po/da.mo, plugins/sudoers/po/de.mo,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/fi.mo,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/pl.mo,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/uk.mo,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/zh_CN.mo:
+ Rebuild message catalog files.
+ [0a9befb0674e]
+
+ * src/po/da.mo, src/po/eo.mo, src/po/fi.mo, src/po/it.mo,
+ src/po/pl.mo, src/po/pt_BR.mo, src/po/ru.mo, src/po/uk.mo,
+ src/po/vi.mo, src/po/zh_CN.mo:
+ Rebuild message catalog files.
+ [25191089ddf2]
+
+ * MANIFEST, NEWS, doc/CONTRIBUTORS, src/po/cs.mo, src/po/cs.po:
+ Czech translation for sudo from translationproject.org.
+ [8bc0ed069ddb]
+
+2013-09-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/da.po, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/eo.po, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/it.po, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.po, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.po, plugins/sudoers/po/zh_CN.po, src/po/da.po,
+ src/po/eo.po, src/po/fi.po, src/po/it.po, src/po/pl.po,
+ src/po/pt_BR.po, src/po/ru.po, src/po/uk.po, src/po/vi.po,
+ src/po/zh_CN.po:
+ Sync with translationproject.org
+ [c16f9bb4579e]
+
+ * NEWS, plugins/sudoers/getdate.c, plugins/sudoers/getdate.y:
+ Change "next" back to 2. In the context of "next Friday" we really
+ do want the friday of the upcoming (not current) week.
+ Unfortunately, this means that things like "next week" and "next
+ year" will match one more than we really want. Fixing this will
+ require some fairly major changes to the grammar.
+ [7f863c930121]
+
+ * doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in:
+ Mention that relative times don't always do what you might expect.
+ [710a9b0dd36f]
+
+2013-09-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS:
+ Add diacritical for Zdenek Behan.
+ [78d333f88e6c]
+
+2013-09-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/regress/ttyname/check_ttyname.c:
+ Do not fail if ttyname() cannot determine the tty but sudo can.
+ Should fix problems with running "make check" under pbuilder.
+ [e6fc06a6c5cf]
+
+ * plugins/sudoers/Makefile.in:
+ Remove extraneous $$CWD; from Bdale Garbee
+ [4d040ddd7446]
+
+2013-09-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, plugins/sudoers/getdate.c, plugins/sudoers/getdate.y:
+ Make "this" and "next" qualifiers work a bit better. There is still
+ room for improvement as "this week" will use the current time
+ instead of the beginning of the week. That's a separate issue
+ though.
+ [e844c02f754a]
+
+2013-09-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/regress/sudo_conf/conf_test.c,
+ common/regress/sudo_parseln/parseln_test.c:
+ Mark main() public to silence a warning on HP-UX.
+ [ac0b869b9842]
+
+2013-09-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot, plugins/sudoers/timestamp.c:
+ Be specific that we are talking about the Unix epoch; bug #615
+ [25887775371b]
+
+ * plugins/sudoers/auth/bsdauth.c, plugins/sudoers/po/sudoers.pot,
+ src/po/sudo.pot, src/selinux.c:
+ Do not use "setup" as a verb; bug #614
+ [17c4750aac5f]
+
+ * plugins/sudoers/iolog.c:
+ Fix logic goof when checking open() status.
+ [76ece1445d71]
+
+ * plugins/sudoers/po/nl.mo, plugins/sudoers/po/nl.po, src/po/nl.mo,
+ src/po/nl.po, src/po/ru.mo, src/po/ru.po:
+ Sync with translationproject.org
+ [21351498000f]
+
+ * NEWS, plugins/sudoers/sudoreplay.c:
+ Work around a bug in sudo 1.8.7 timing files where the indexes are
+ off by two.
+ [4aa0cd58af58]
+
+ * MANIFEST, plugins/sudoers/iolog.c, plugins/sudoers/iolog.h,
+ plugins/sudoers/sudoreplay.c:
+ Repair writing of the I/O log file indices broken in sudo 1.8.7.
+ [6a5f867884f5]
+
+2013-08-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Try to improve the PAGERS noexec example a bit.
+ [226f11118daa]
+
+2013-08-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ Document comment character in ldap.conf Clarify what is and is not
+ supported in TLS_KEYPW Mention that gsk8capicmd can be used to
+ create a stash file
+ [fb8f06ab4458]
+
+2013-08-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ New bugs fixed for 1.8.8.
+ [c158df7cd9d2]
+
+ * plugins/sudoers/visudo.c:
+ Fix setting of quiet flag when -q / --quiet is specified. Do not
+ print "sudoers: parsed OK" in quiet mode.
+ [df55acd57ce6]
+
+ * plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po, src/po/fi.mo,
+ src/po/fi.po, src/po/it.mo, src/po/it.po:
+ Updated translations from translationproject.org
+ [e9e8abd23a28]
+
+ * plugins/sudoers/check.c:
+ Don't allow root to change its SELinux role without a password. Bug
+ #611
+ [f8b599acb29d]
+
+2013-08-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Mention new Mac OS X symbol interposition.
+ [98293b7c4e0f]
+
+ * plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po, src/po/eo.mo,
+ src/po/eo.po, src/po/fr.mo, src/po/fr.po:
+ Updated translations from translationproject.org
+ [865be7454354]
+
+ * config.h.in, configure, configure.in, src/sudo_noexec.c:
+ Add configure checks for the exec functions we will dummy out. This
+ is only really needed on Mac OS X when symbol interposition is being
+ performed but won't hurt elsewhere.
+ [49c20cf6bab0]
+
+2013-08-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, src/Makefile.in,
+ src/sudo_noexec.c:
+ Fix installation of sudo_noexec on Mac OS X. Use library symbol
+ interposition on Mac OS X 10.4 and higher so we don't need to set
+ DYLD_FORCE_FLAT_NAMESPACE=1.
+ [a82999dff8e6]
+
+2013-08-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ Fix typo in tls_key example for Tivoli
+ [36599f424ac4]
+
+ * src/parse_args.c:
+ Don't escape '$' when running "sudo -i command". Bug #564
+ [17542d52f714]
+
+ * plugins/sudoers/iolog_path.c:
+ Fix typo in comment.
+ [d0510ed5eaba]
+
+ * plugins/sudoers/auth/pam.c:
+ Fix comment.
+ [4e89e0bfd6af]
+
+ * plugins/sudoers/timestr.c, plugins/sudoers/visudo.c:
+ Quiet some gcc -Wformat=2 false positives
+ [28a2014b9822]
+
+2013-08-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/pam.c:
+ Remove now-obsolete arg to env_merge()
+ [ba015cf5d935]
+
+ * plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/pt_BR.mo, plugins/sudoers/po/pt_BR.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ src/po/pl.mo, src/po/pl.po, src/po/pt_BR.mo, src/po/pt_BR.po,
+ src/po/uk.mo, src/po/uk.po, src/po/vi.mo, src/po/vi.po,
+ src/po/zh_CN.mo, src/po/zh_CN.po:
+ Updated translations from translationproject.org
+ [72b6aeaba505]
+
+ * MANIFEST, NEWS, doc/CONTRIBUTORS, src/po/fr.mo, src/po/fr.po:
+ French translation for sudo from translationproject.org.
+ [a72321771860]
+
+ * plugins/sudoers/logging.h:
+ Add __printflike to audit_failure.
+ [1686b3699d41]
+
+ * include/missing.h:
+ Use __nonnull__ attribute in __printflike.
+ [d123613a1fb6]
+
+2013-08-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/env.c, plugins/sudoers/sudoers.h:
+ When merging the PAM environment, allow environment variables set in
+ PAM to override ones set by sudo as long as they do not match the
+ env_keep or env_check lists.
+ [f3c64967fed7]
+
+ * plugins/sudoers/auth/pam.c:
+ Call pam_getenvlist() after we've opened the session to get the
+ session-specific environment variables.
+ [b413fb9e1c77]
+
+ * plugins/sudoers/ldap.c:
+ Fix error display from ldap_ssl_client_init(). There are two error
+ codes. The return value can be decoded via ldap_err2string() but the
+ ssl reason code cannot (you have to look it up in a table online).
+ [0267125ce9f0]
+
+2013-08-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ option not flag
+ [08c31af7b818]
+
+ * compat/getopt_long.c, config.h.in, configure, configure.in:
+ Don't redefine opterr, optind, optopt, optarg in getopt_long.c. Add
+ a check for optreset which is a BSD extension and provide a
+ definition in getopt_long.c if it is not present.
+ [3393e8d83400]
+
+ * plugins/sudoers/po/sudoers.pot, src/po/sudo.pot:
+ regen
+ [f38f65830118]
+
+ * plugins/sudoers/sudoreplay.c, plugins/sudoers/visudo.c:
+ Use lower case for the long option arguments to match the manual.
+ This is inconsistent with GNU but it is better to match the sudo
+ documentation.
+ [8fac2d64f5d2]
+
+ * NEWS:
+ Sudo 1.8.8
+ [105c73752474]
+
+ * src/parse_args.c:
+ Use lower card for the long option arguments to match the manual.
+ This is inconsistent with GNU but it is better to match the sudo
+ documentation.
+ [af243dd39850]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in:
+ Describe how remote command execution can be implemented.
+ [3eba7f93b7f6]
+
+ * doc/sudoers.ldap.cat:
+ Bump version.
+ [0ee7f02f3627]
+
+2013-08-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo.c:
+ Make it a fatal error if the plugin returns invalid or out of range
+ command info.
+ [8a7e56c7584a]
+
+ * plugins/sudoers/policy.c:
+ Use strtol() instead of atoi() and perform error checking of
+ parameters passed from the sudo front-end.
+ [05e05be3c6c4]
+
+ * plugins/sudoers/auth/pam.c:
+ It is not possible for auth to be NULL here.
+ [771500e776e9]
+
+ * plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Initialize user_runhost and user_srunhost to user_host and
+ user_shost in visudo and testsudoers.
+ [c47cca74e1fc]
+
+ * MANIFEST, common/Makefile.in, common/aix.c, common/alloc.c,
+ common/error.c, common/fatal.c, common/gidlist.c, common/lbuf.c,
+ common/list.c, common/sudo_conf.c, common/sudo_debug.c,
+ compat/Makefile.in, compat/getopt_long.c, include/error.h,
+ include/fatal.h, plugins/sudoers/Makefile.in,
+ plugins/sudoers/bsm_audit.c, plugins/sudoers/hexchar.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/locale.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoreplay.c,
+ src/Makefile.in, src/locale_stub.c, src/net_ifs.c,
+ src/regress/ttyname/check_ttyname.c, src/sesh.c, src/sudo.h:
+ Rename error.h -> fatal.h now that there is no error() function.
+ [3a3827f10f04]
+
+ * common/sudo_debug.c, include/sudo_debug.h:
+ Add support to the debug subsystem for zero-length strings. This can
+ happen for things like warning(NULL) or fatal(NULL) where we just
+ want to log the errno string.
+ [3ed739c5cc91]
+
+ * include/error.h:
+ Add __printflike for vfatal, vfatalx, vwarning and vwarningx.
+ [57e65ed595d2]
+
+ * plugins/sudoers/audit.c:
+ Need to include gettext.h for BSM audit.
+ [a87fda2d0123]
+
+ * common/alloc.c, plugins/sudoers/env.c, src/exec_common.c,
+ src/parse_args.c, src/sudo.c:
+ Change some fatalx(NULL) that should be fatal(NULL).
+ [8b1efda9f578]
+
+ * include/error.h, include/missing.h:
+ Use __printf0like for warning() and fatal() since the fmt string may
+ be NULL.
+ [858a890f00ad]
+
+ * compat/pw_dup.c:
+ Quiet a gcc "used uninitialized in this function" false positive.
+ [98f47f89ce60]
+
+ * mkpkg:
+ Enable bsm audit on Mac OS X and Solaris >= 11.
+ [8607488f986c]
+
+ * plugins/sudoers/bsm_audit.c:
+ Fix compilation on Solaris 11.
+ [01aa46298ed7]
+
+ * plugins/sudoers/bsm_audit.c:
+ Add missing missing.h
+ [080de69a55a1]
+
+ * plugins/sudoers/sudoers.c:
+ Move the -C (user_closefrom) check until after set_cmnd() so that
+ closefrom_override can be used in a command-specific Defaults line.
+ Fixes bug #610 from Mengtao Sun.
+ [413565c6ff6b]
+
+2013-08-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c:
+ If not using a pty and the child process gets SIGTTOU or SIGTTIN and
+ sudo is the foreground process, make the child the foreground
+ process and continue it.
+ [5ff433443bc4]
+
+ * src/sudo.c:
+ If sudo is not setuid and was not invoked with a full path, look in
+ the user's PATH for the sudo binary to give a better error message.
+ [a740129a38f0]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in,
+ plugins/sudoers/logging.c, plugins/sudoers/match.c,
+ plugins/sudoers/policy.c, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudoers.h:
+ Add limited support for "sudo -l -h other_host". Since group lookups
+ are done on the local host, rules that use group membership may be
+ incorrect if the group database is not synchronized between hosts.
+ [2c8b222a5f7f]
+
+ * src/parse_args.c:
+ Fix parsing of "-h host" when used in conjunction with the -l flag.
+ [62f3d726d52b]
+
+ * configure, configure.in, doc/fixman.sh, doc/fixmdoc.sh,
+ doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in, doc/sudoreplay.cat,
+ doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in, doc/visudo.cat,
+ doc/visudo.man.in, doc/visudo.mdoc.in, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/visudo.c, src/parse_args.c, src/sudo.c,
+ src/sudo_usage.h.in:
+ Simplify usage messages a bit and make --help output more closely
+ resemble GNU usage wrt long options. Sync usage and man page
+ SYNOPSYS sections and improve long options in the manual pages. Now
+ that we have long options we don't need to give the mnemonic for the
+ single-character options in the description.
+ [17b7e386955a]
+
+2013-08-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/logging.c:
+ Fix setting of mailer argv[0] to basename of mailerpath. No need to
+ strdup() mailerpath as it is not modified.
+ [8843cdd958ee]
+
+ * plugins/sudoers/logging.c:
+ Make sure the mailer exists and is a regular file before trying to
+ exec it.
+ [b73d6214014f]
+
+ * plugins/sudoers/timestamp.c:
+ If tty_tickets are enabled but there is no tty, use a ticket file
+ based on the parent pid.
+ [75408bd61ced]
+
+ * common/sudo_conf.c, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in, include/sudo_conf.h, src/parse_args.c:
+ Allow default plugin dir to be configured in sudo.conf.
+ [478883594cc5]
+
+ * doc/CONTRIBUTORS:
+ UTF8 for Ruusamae, Elan; from Tae Wong
+ [02e0c95b4fa6]
+
+2013-08-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, common/regress/sudo_conf/test5.in,
+ common/regress/sudo_conf/test5.out.ok,
+ common/regress/sudo_conf/test6.in,
+ common/regress/sudo_conf/test6.out.ok, common/sudo_conf.c,
+ doc/sudo.conf.cat, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in,
+ plugins/sudoers/policy.c, plugins/sudoers/pwutil_impl.c, src/sudo.c:
+ Don't allow max_groups to be set to zero, it just complicates things
+ needlessly. Fixes an assertion in visudo when there is a group-
+ based Defaults entry.
+ [d62a8ea32db9]
+
+2013-08-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, common/Makefile.in, common/gidlist.c,
+ plugins/sudoers/policy.c, plugins/sudoers/sudoers.h, src/sudo.c,
+ src/sudo.h:
+ Refactor code to parse list of gids into its own function that is
+ shared by the sudo front-end and the sudoers module. Make uid/gid
+ parse error be fatal, not just a warning.
+ [da3b2b06605c]
+
+ * common/atoid.c:
+ Add function comment block.
+ [09a324de716f]
+
+ * common/atoid.c:
+ Default text domain is now sudo, not sudoers.
+ [1acb1da6f304]
+
+ * common/Makefile.in:
+ Update dependency for atoid.lo
+ [5e367cd44288]
+
+ * common/atoid.c, plugins/sudoers/iolog.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/tsgetgrpw.c, src/sudo.c,
+ src/sudo.h:
+ Add endpointer and separator args to atoid()
+ [2077e4ed8578]
+
+2013-08-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/getgrouplist.c:
+ Use private version of atoid() to avoid a dependency on libcommon.a
+ (since that already depends on libreplace.a).
+ [7c12d63b0560]
+
+ * doc/CONTRIBUTORS:
+ More UTF8 in names; from Tae Wong
+ [512b263f51c8]
+
+ * compat/getgrouplist.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/tsgetgrpw.c, src/sudo.c, src/sudo.h:
+ Use atoid() in more places.
+ [06f4ae57c707]
+
+ * MANIFEST, common/Makefile.in, common/atoid.c,
+ plugins/sudoers/Makefile.in, plugins/sudoers/atoid.c:
+ Move atoid() to common so it can be used in src and compat too.
+ [095d730701e4]
+
+ * compat/closefrom.c:
+ Avoid a crash on Mac OS X 10.8 (at least) when we close
+ libdispatch's fds out from under it before executing the command.
+ Switch to just setting the close on exec flag instead.
+ [349ebf4987df]
+
+ * doc/CONTRIBUTORS:
+ Convert to last, first for easier sorting and use UTF8 (including a
+ BOM).
+ [8c30d221bd75]
+
+ * plugins/sudoers/atoid.c:
+ Add atoid() function to convert a string to an id_t (uid, gid or
+ pid). We have to be careful to choose() either strtol() or strtoul()
+ depending on whether the string appears to be signed or unsigned.
+ Always using strtoul() is unsafe on 64-bit platforms since the uid
+ might be represented as a negative number and (unsigned long)-1 on a
+ 64-bit system is 0xffffffffffffffff not 0xffffffff. Fixes a problem
+ with uids larger than 0x7fffffff on 32-bit platforms.
+ [5d818e399157]
+
+ * MANIFEST, config.h.in, configure, configure.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.h:
+ Add atoid() function to convert a string to an id_t (uid, gid or
+ pid). We have to be careful to choose() either strtol() or strtoul()
+ depending on whether the string appears to be signed or unsigned.
+ Always using strtoul() is unsafe on 64-bit platforms since the uid
+ might be represented as a negative number and (unsigned long)-1 on a
+ 64-bit system is 0xffffffffffffffff not 0xffffffff. Fixes a problem
+ with uids larger than 0x7fffffff on 32-bit platforms.
+ [cd92246a710f]
+
+ * plugins/sudoers/sudoers.c:
+ Avoid "perm stack underflow" error when logging the unknown uid
+ error.
+ [871514c713b7]
+
+ * plugins/sudoers/set_perms.c:
+ In rewind_perms() there is nothing to do if perm_stack_depth == 0.
+ [98de335f47f0]
+
+2013-08-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in:
+ Add pam_setcred sudoers option to allow the user to control whether
+ pam_setcred() is called on the user's behalf.
+ [4260a8e43073]
+
+ * configure, configure.in, doc/sudoers.cat, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c:
+ Add pam_service and pam_login_service sudoers settings to control
+ the service name passed to pam_start.
+ [5ea0e3588f3a]
+
+ * mkpkg:
+ Newer Xcode places the SDKs under Xcode.app
+ [4b54379d5c45]
+
+2013-08-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, common/Makefile.in, common/zero_bytes.c,
+ compat/Makefile.in, compat/memset_s.c, config.h.in, configure,
+ configure.in, doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, include/missing.h, include/sudo_plugin.h,
+ mkdep.pl, plugins/sudoers/Makefile.in,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/secureware.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/logging.c, plugins/sudoers/sha2.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/visudo.c,
+ src/Makefile.in, src/conversation.c, src/sudo.h, src/sudo_edit.c,
+ src/tgetpass.c:
+ Implement memset_s() and use it instead of zero_bytes(). A new
+ constant, SUDO_CONV_REPL_MAX, is defined by the plugin API as the
+ max conversation reply length. This constant can be used as a max
+ value for memset_s() when clearing passwords filled in by the
+ conversation function.
+ [264ec146028e]
+
+2013-08-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/system_group/Makefile.in:
+ Do not try to install plugins when shared modules are disabled
+ (sudoers already had the check).
+ [3d582c042042]
+
+ * plugins/sudoers/Makefile.in:
+ Update dependencies to take into account compat/getopt.h and
+ compat/dlfcn.h.
+ [301fb31cd121]
+
+ * src/Makefile.in:
+ Update dependencies now that sudo_usage.h is always included from
+ the build dir.
+ [c1ff70ec9515]
+
+2013-07-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Add some warnings and debugging to sasl ccname handling.
+ [467f415861f0]
+
+ * plugins/sudoers/ldap.c:
+ Fix write loop invariant in sudo_krb5_copy_cc_file()
+ [6948cf6e9b9f]
+
+2013-07-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Strip off leading FILE: or WRFILE: prefix before trying to copy the
+ user's credential cache.
+ [56c16feab62f]
+
+2013-07-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo.c:
+ Instead of setting RLIMIT_NPROC to unlimited when sudo initializes,
+ just save RLIMIT_NPROC in exec_setup() before the final setuid() and
+ restore it immediately after. We don't need to modify RLIMIT_NPROC
+ for simple euid changes, just for changing the real (and saved) uids
+ before we exec. This also means we no longer need to worry about
+ _SC_CHILD_MAX returning -1. Bug #565
+ [1372f1909039]
+
+2013-07-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c, src/preload.c:
+ Now that the ldap code runs with the real and effective uid set to
+ 0, it is not possible for the gssapi libs to find the user's krb5
+ credential cache file. To work around this, we make a temporary copy
+ of the user's credential cache specified by KRB5CCNAME (opened with
+ the user's effective uid) and point gssapi to it. To set the
+ credential cache file name, we dynamically look up
+ gss_krb5_ccache_name() and use it if available, otherwise fall back
+ to setting KRB5CCNAME.
+ [8b86c134541a]
+
+2013-07-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.man.in, doc/sudoreplay.cat, doc/sudoreplay.man.in,
+ doc/sudoreplay.mdoc.in, doc/visudo.cat, doc/visudo.man.in,
+ doc/visudo.mdoc.in, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/visudo.c:
+ Long option support for visudo and sudoreplay.
+ [91427968be71]
+
+2013-07-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in, src/Makefile.in,
+ src/parse_args.c, src/sudo.c, src/sudo_usage.h.in:
+ Add support for long options and fix inclusion of sudo_usage.h with
+ modern gcc broken in 8597:1fcb7ba13018.
+ [d13134819944]
+
+ * src/Makefile.in:
+ Add rule to rebuild sudo_usage.h when the .in file changes.
+ [59a32899e251]
+
+ * compat/Makefile.in, mkdep.pl, src/Makefile.in:
+ Add make rules for building getopt_long.c
+ [5f57593b3a8b]
+
+ * src/parse_args.c:
+ Make "-h hostname" work. Optional args in GNU getopt() only work
+ when there is no space between the option flag and the argument.
+ [b8258659cabb]
+
+2013-07-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, compat/getopt.h, compat/getopt_long.c, config.h.in,
+ configure, configure.in, doc/LICENSE, src/parse_args.c:
+ Use getopt_long() so we can make the -h flag take an optional
+ argument. Includes a version for those without it.
+ [d1dd66c8a86b]
+
+2013-07-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Document that the -h option can be used specify a host name for
+ future plugins.
+ [8470c74cf326]
+
+ * include/sudo_plugin.h, src/parse_args.c, src/sudo_usage.h.in:
+ Overload -h option to specify an optional hostname for remote
+ access. This is future-proofing; no policy plugins currently support
+ this.
+ [0e01d8c3c623]
+
+ * configure, configure.in:
+ Bump version to 1.8.8
+ [a1155bfaa28f]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in:
+ Document the remote_host setting (-h host)
+ [c737db906f5d]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ fix "the the"
+ [0025464a3942]
+
+ * src/parse_args.c, src/sudo.c, src/sudo.h:
+ Do not error out if arg to -U option cannot be resolved, that is for
+ the plugin to decide. There is no need for runas_user and
+ runas_group to be global, make them local to parse_args() instead.
+ [fb02a62a72ba]
+
+ * MANIFEST, doc/CONTRIBUTORS, plugins/sudoers/po/pt_BR.mo,
+ plugins/sudoers/po/pt_BR.po, src/po/es.mo, src/po/es.po,
+ src/po/pt_BR.mo, src/po/pt_BR.po:
+ Sync with translationproject.org
+ [e8f4772d918a]
+
+2013-07-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/TROUBLESHOOTING:
+ Remove old bits about sudo setuid problems that should have been
+ cleaned up in changeset 7917:fa4894896d8a. Also update the mode of
+ sudo to 04755 to match current packaging.
+ [1e3904cdc2de]
+
+ * plugins/sudoers/auth/pam.c:
+ Go back to ignoring the return value of pam_setcred() since with
+ stacked PAM auth modules a failure from one module may override
+ PAM_SUCCESS from another. If the first module in the stack fails,
+ the others may be run (and succeed) but an error will be returned.
+ This can cause a spurious warning on systems with non-local users
+ (e.g. pam_ldap or pam_sss) where pam_unix is consulted first.
+ [b6022e26135a]
+
+ * src/net_ifs.c:
+ Remove unused variable.
+ [93dde7d82fde]
+
+ * NEWS:
+ Fix typo
+ [5ef79671c2c7]
+
+2013-07-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sssd.c:
+ Fix pasto; sudo_sss_extract_digest() not sudo_ldap_extract_digest().
+ From Dan Harnett.
+ [4a0af6f12765]
+
+2013-06-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Fix formatting typo; from Eric S. Raymond
+ [058b533ba460]
+
+2013-06-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg:
+ Use -gxcoff on aix so dbx can be used to debug sudo.
+ [4950e019ed2d]
+
+2013-06-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in:
+ Fix typo; bug 605
+ [41f7b46a6e51]
+
+2013-06-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/po/da.mo, src/po/eo.mo, src/po/es.mo, src/po/it.mo,
+ src/po/tr.mo:
+ Regen .mo files that were out of date.
+ [9e25a254f9db]
+
+2013-05-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, configure, configure.in:
+ On Solaris 11 and higher, tag binaries for ASLR if supported by the
+ linker.
+ [a2a6cafa3e60]
+
+ * mkpkg:
+ No longer need to disable PIE on Solaris.
+ [cf90019ae67e]
+
+2013-05-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, NEWS, configure, configure.in, doc/TROUBLESHOOTING:
+ Restrict default creation of PIE binaries (-fPIE and -pie) to Linux.
+ OpenBSD also supports PIE but enables it by default so we don't need
+ to do anything. This fixes problems on systems with a version of GNU
+ ld that accepts -pie but where the run-time linker doesn't actually
+ support PIE. Also verify that a trivial PIE binary works unless PIE
+ is explicitly enabled.
+ [3c5f125efeb1]
+
+2013-05-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aclocal.m4, configure, configure.in:
+ Attempt to detect PIE failure on Solaris 10 with GNU as and GNU ld
+ where we can end up crashing due to malloc() failures. Sems OK when
+ Using Sun as and ld.
+ [b8ba412102ab]
+
+ * NEWS:
+ Update with final changes.
+ [78ff6d2ed47a]
+
+2013-05-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Add -fPIE to PIE_LDFLAGS as per gcc manual.
+ [fe900cbb0780]
+
+2013-05-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/Makefile.in, compat/Makefile.in:
+ Add missing $(PIE_LDFLAGS) $(SSP_LDFLAGS) for test programs
+ [f84bc7482b78]
+
+ * MANIFEST, plugins/sudoers/alias.c, plugins/sudoers/match.c,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/visudo/test4.out.ok,
+ plugins/sudoers/regress/visudo/test4.sh, plugins/sudoers/visudo.c:
+ Replace sequence number-based cycle detection in visudo with a
+ "used" flag in struct alias. The caller is required to call
+ alias_put() when it is done with the alias. Inspired by a patch from
+ Daniel Kopecek.
+ [0bdbac1b3b39]
+
+2013-05-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ Eliminate a few relocations related to sudoers_io.
+ [18e9e2cc3367]
+
+ * plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po:
+ Sync with translationproject.org
+ [f38cc128a2ad]
+
+2013-05-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/ttyname.c:
+ Clarify a comment.
+ [7a045ee06e95]
+
+2013-05-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/ttyname.c:
+ Handle d_type == DT_UNKNOWN when resolving the device to a name and
+ sprinkle some more debugging.
+ [8774133747d9]
+
+2013-05-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/TROUBLESHOOTING:
+ Add message about disabling PIE if sudo gets SIGSEGV.
+ [c786af2a6751]
+
+ * plugins/sudoers/check.h, plugins/sudoers/timestamp.c:
+ No longer store the ctime of a devpts tty. The handling of ctime on
+ devpts in Linux has been changed to conform to POSIX. As a result we
+ can no longer assume that the ctime will stay unchanged throughout
+ the life of the session. We store the session ID in the time stamp
+ file so there is a much smaller chance of the time stamp file being
+ reused by a new login. While here, store the uid/gid in the
+ timestamp file too for good measure.
+ [7028b21f7a9b]
+
+ * configure, configure.in:
+ PIE is broken on FreeBSD/arm
+ [f232c60d6229]
+
+ * mkpkg:
+ Add explicit sendmail path for Linux since we may not have sendmail
+ installed in the build chroot.
+ [1ba2f84f4ff0]
+
+2013-05-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/sudo_debug.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/set_perms.c, src/sudo.c, src/tgetpass.c:
+ Quiet a few -Wunused-result compiler warnings.
+ [ef12afb61423]
+
+2013-04-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Mention what SHA-2 formats are supported.
+ [bf298d0fdf8a]
+
+ * doc/CONTRIBUTORS:
+ List code and translations separately.
+ [826547bc1295]
+
+2013-04-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/po/de.mo, plugins/sudoers/po/de.po,
+ plugins/sudoers/po/tr.mo, plugins/sudoers/po/tr.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po:
+ Sync with translationproject.org
+ [9499a6f438b8]
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [cce449e284a6]
+
+ * Makefile.in:
+ Fix c-format for fatal/fatalx
+ [4ad81d3faaeb]
+
+2013-04-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, plugins/sudoers/iolog.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/visudo.c, src/exec_pty.c, src/sudo.h:
+ Change some error/errorx -> fatal/fatalx in comments and xgettext
+ flags.
+ [9d9b64fa2ec9]
+
+ * NEWS:
+ There is now a Turkish translation of sudoers.
+ [701c5af6aa76]
+
+ * MANIFEST, plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/tr.mo, plugins/sudoers/po/tr.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po:
+ Updated translations from translationproject.org including new
+ Turkish translation.
+ [9cedbb50d90f]
+
+2013-04-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document that sudoers will re-use existing I/O log paths unless they
+ are mktemp-style with trailing X's.
+ [4f43bd13d9e7]
+
+ * NEWS, doc/sudoers.cat, doc/sudoers.ldap.cat,
+ doc/sudoers.ldap.man.in, doc/sudoers.ldap.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, plugins/sudoers/ldap.c,
+ plugins/sudoers/policy.c, plugins/sudoers/sudoers.h:
+ Allow ldap_conf and ldap_secret to be specified as plugin arguments
+ in sudo.conf
+ [37c6c425b565]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ sudoers_debug is now deprecated in favor of the sudo debugging
+ framework.
+ [1195be1ec254]
+
+ * plugins/sudoers/ldap.c:
+ Replace DPRINTF with DPRINTF1 and DPRINTF2 macros that use
+ SUDO_DEBUG_DIAG and SUDO_DEBUG_INFO respectively for logging to the
+ debug file with the ldap subsystem. The sudoers_debug setting in
+ ldap.conf is still honored for now but will be removed in a future
+ release.
+ [cfa42b4b913e]
+
+2013-04-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers2ldif:
+ Add support for converting sudoers files with SHA-2 command digests.
+ [dc0d03485946]
+
+ * doc/fixman.sh, doc/fixmdoc.sh, mkdep.pl, mkpkg,
+ plugins/sudoers/sudoers2ldif:
+ Add copyright notice to scripts
+ [5e8bd4e6083f]
+
+ * MANIFEST, plugins/sudoers/regress/sudoers/test14.in,
+ plugins/sudoers/regress/sudoers/test14.out.ok,
+ plugins/sudoers/regress/sudoers/test14.toke.ok:
+ Add regress for SHA-2 digests.
+ [0b258c2a2a95]
+
+ * compat/getgrouplist.c:
+ Solaris maps negative gids to GID_NOBODY.
+ [57050e5c750f]
+
+ * plugins/sudoers/visudo.c:
+ Clear up an llvm checker warning which appears to be a false
+ positive and fix an old XXX while I'm at it.
+ [9ee13133e596]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in, doc/sudoreplay.cat,
+ doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in:
+ Correct last change date
+ [3bc1fa5b0f76]
+
+ * plugins/sudoers/po/sudoers.pot, plugins/sudoers/sudoreplay.c:
+ No need to translate this error message.
+ [4d9941970a26]
+
+ * doc/UPGRADE:
+ Mention .sl vs. .so extension handling on HP-UX Mention group
+ membership changes Fix typos
+ [40ac0efbdb2b]
+
+ * aclocal.m4, common/aix.c, common/alloc.c, common/atobool.c,
+ common/error.c, common/fmt_string.c, common/lbuf.c, common/list.c,
+ common/setgroups.c, common/term.c, common/ttysize.c,
+ compat/Makefile.in, compat/dlopen.c, compat/endian.h,
+ compat/getline.c, compat/getprogname.c, compat/isblank.c,
+ compat/memrchr.c, compat/mksiglist.c, compat/mktemp.c,
+ compat/nanosleep.c, compat/pw_dup.c, compat/sig2str.c,
+ compat/snprintf.c, compat/strlcat.c, compat/strlcpy.c,
+ compat/strsignal.c, compat/utimes.c, doc/Makefile.in,
+ include/Makefile.in, include/alloc.h, include/fileops.h,
+ include/gettext.h, include/lbuf.h, include/missing.h,
+ include/sudo_plugin.h, pathnames.h.in,
+ plugins/group_file/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sample/sample_plugin.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/alias.c, plugins/sudoers/audit.c,
+ plugins/sudoers/auth/afs.c, plugins/sudoers/auth/aix_auth.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/dce.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/passwd.c,
+ plugins/sudoers/auth/rfc1938.c, plugins/sudoers/auth/secureware.c,
+ plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.h, plugins/sudoers/bsm_audit.c,
+ plugins/sudoers/bsm_audit.h, plugins/sudoers/defaults.c,
+ plugins/sudoers/defaults.h, plugins/sudoers/env.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/getspwuid.c,
+ plugins/sudoers/goodpath.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/interfaces.c, plugins/sudoers/interfaces.h,
+ plugins/sudoers/iolog_path.c, plugins/sudoers/linux_audit.c,
+ plugins/sudoers/linux_audit.h, plugins/sudoers/locale.c,
+ plugins/sudoers/logging.h, plugins/sudoers/match.c,
+ plugins/sudoers/match_addr.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h, plugins/sudoers/prompt.c,
+ plugins/sudoers/pwutil.h, plugins/sudoers/redblack.c,
+ plugins/sudoers/redblack.h,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudo_nss.h, plugins/sudoers/sudoers_version.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.h, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/tsgetgrpw.c,
+ plugins/sudoers/visudo.c, plugins/system_group/Makefile.in,
+ plugins/system_group/system_group.c, src/Makefile.in,
+ src/conversation.c, src/exec.c, src/exec_common.c, src/get_pty.c,
+ src/net_ifs.c, src/parse_args.c, src/preload.c, src/selinux.c,
+ src/sesh.c, src/signal.c, src/sudo_edit.c, src/sudo_exec.h,
+ src/sudo_noexec.c, src/sudo_plugin_int.h, src/tgetpass.c,
+ src/utmp.c:
+ Update copyright years.
+ [5c6d72661bad]
+
+ * plugins/sudoers/mon_systrace.h:
+ Systrace support was removed long ago.
+ [10a038a2da77]
+
+2013-04-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/regress/sudoers/test10.toke.out.ok,
+ plugins/sudoers/regress/sudoers/test9.toke.out.ok:
+ Remove some files that were mistakenly added.
+ [833502da26de]
+
+ * common/sudo_debug.c, config.h.in, configure, configure.in,
+ plugins/sudoers/boottime.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/logging.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/timestamp.c:
+ Use time(&now) instead of now = time(NULL) when storing the current
+ time in a time_t (better compiler error checking). Better parsing
+ and printing of 64-bit time_t on 32-bit platforms.
+ [c227dc72c04e]
+
+2013-04-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/ttyname.c:
+ Don't check the tty of the parent process. Now that we get the
+ controlling tty device number from the kernel there is no need. If
+ the process has really disassociated from the tty then reporting
+ "unknown" is appropriate.
+ [62fb66e565db]
+
+2013-04-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/error.c:
+ Use EXIT_FAILURE instead of 1 as the fatal() exit value.
+ [ed94c2c5e88a]
+
+ * src/sesh.c:
+ Change remaining errorx -> fatalx
+ [3f6d70e19303]
+
+2013-04-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/pwutil.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Replace sudo_fakepwnamid() with sudo_mkpwent() and don't return an
+ error if the entry already exists in the cache.
+ [94d45970400a]
+
+ * plugins/sudoers/bsm_audit.c, plugins/sudoers/po/sudoers.pot:
+ Change "foo: failed" to just "foo" since we print the string form of
+ errno. Gets rids of some useless translations.
+ [476f37349dbc]
+
+2013-04-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/match.c:
+ Fix pasto in debug_decl
+ [08650186a239]
+
+ * plugins/sudoers/Makefile.in:
+ regen
+ [acf4c34fba2c]
+
+ * plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h, plugins/sudoers/parse.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/timestamp.c:
+ Rename log_error() -> log_warning() for consistency with
+ warning()/fatal()
+ [474ed5a0e335]
+
+ * plugins/sudoers/auth/API:
+ The NO_EXIT flag was removed a while ago.
+ [e0a4be270226]
+
+ * common/aix.c, common/alloc.c, common/error.c, include/error.h,
+ plugins/sudoers/bsm_audit.c, plugins/sudoers/env.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/hexchar.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/logging.c,
+ plugins/sudoers/policy.c, plugins/sudoers/prompt.c,
+ plugins/sudoers/pwutil.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/visudo.c, src/exec.c, src/exec_common.c,
+ src/exec_pty.c, src/net_ifs.c, src/parse_args.c, src/selinux.c,
+ src/signal.c, src/sudo.c, src/sudo_edit.c, src/tgetpass.c,
+ src/utmp.c:
+ Rename error/errorx -> fatal/fatalx and remove the exit value as it
+ was always 1.
+ [ea66f58c4da5]
+
+ * NEWS:
+ digests are supported in sudoers ldap too
+ [77d6c25f7653]
+
+ * plugins/sudoers/regress/check_symbols/check_symbols.c:
+ Print test failures to stdout like the final count so the outputis
+ not displayed out of order.
+ [f541b78ecb93]
+
+ * plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/eo.po, plugins/sudoers/po/hr.mo,
+ plugins/sudoers/po/hr.po, plugins/sudoers/po/it.po, src/po/da.mo,
+ src/po/da.po, src/po/eo.po, src/po/hr.mo, src/po/hr.po,
+ src/po/it.po, src/po/tr.po:
+ Sync with translationproject.org
+ [cbd70678b99f]
+
+ * Makefile.in:
+ Check for any uncommitted changes in dist target and add force-dist
+ target that omit check-dist.
+ [78dc3f41e37e]
+
+2013-04-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/regress/ttyname/check_ttyname.c:
+ Fix logic bug when checking tty via ttyname().
+ [279aee076194]
+
+ * compat/endian.h:
+ Fix check for _BIG_ENDIAN and _LITTLE_ENDIAN (Solaris) and
+ __BIG_ENDIAN__ and __LITTLE_ENDIAN__ (HP-UX)
+ [fe35e0b04502]
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [0ddebccd3045]
+
+ * NEWS, doc/sample.sudoers, doc/sudoers.cat, doc/sudoers.ldap.cat,
+ doc/sudoers.ldap.man.in, doc/sudoers.ldap.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document digest support.
+ [d794c7b9a7bc]
+
+ * MANIFEST, plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/parser/check_base64.c:
+ Simple bas64 decode unit test.
+ [344b0df0fe50]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/base64.c,
+ plugins/sudoers/match.c, plugins/sudoers/parse.h:
+ Move base64_decode into its own source file.
+ [30497e7f88bc]
+
+ * plugins/sudoers/getdate.c, plugins/sudoers/getdate.y:
+ Only check year against 2038 if time_t is 32-bit.
+ [9c1f2e3fc3ba]
+
+2013-04-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/parse.h,
+ plugins/sudoers/sssd.c:
+ Add digest support for sudoers in ldap and sss.
+ [314937b5e59e]
+
+ * INSTALL, configure, configure.in:
+ Error out in configure if the compiler doesn't support "long long".
+ [d3645c1d50d1]
+
+ * plugins/sudoers/match.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l:
+ Include stdint.h or inttypes.h before sha2.h
+ [20ad1c20313d]
+
+ * common/lbuf.c:
+ Simplify lbuf append functions by moving the realloc code into
+ lbuf_expand(). We now expand as needed each time bytes need to be
+ written to the lbuf. Also handle a NULL pointer being passed in for
+ paranoia's sake.
+ [6283ee562ef4]
+
+ * plugins/sudoers/iolog.c:
+ Zero out struct iolog_details early to avoid a potential (though
+ unlikely) dereference of stack garbage if we hit a fatal error
+ before iolog_deserialize_info() is called.
+ [2eeca8be05fb]
+
+2013-04-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Update copyright year.
+ [b843c6a43238]
+
+ * plugins/sudoers/sudoers_version.h:
+ Bump SUDOERS_GRAMMAR_VERSION for new digest support.
+ [188556fb8156]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y, plugins/sudoers/match.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Sanity check digest in parser so visudo can catch errors. Add base64
+ support
+ [b8586d5cc7ed]
+
+ * MANIFEST, compat/endian.h, config.h.in, configure, configure.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/sha2.c:
+ For big endian architectures just use memcpy() instead of BE macros
+ in a loop.
+ [c71a0f4a8a8e]
+
+2013-04-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, config.h.in, configure, configure.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.h, plugins/sudoers/gram.y,
+ plugins/sudoers/hexchar.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/match.c, plugins/sudoers/parse.h,
+ plugins/sudoers/regress/parser/check_digest.c,
+ plugins/sudoers/regress/parser/check_digest.out.ok,
+ plugins/sudoers/sha2.h, plugins/sudoers/sssd.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c:
+ Initial implementation of checksum support in sudoers. Currently
+ supports SHA-224, SHA-256, SHA-384, SHA-512. TODO: checksum format
+ validation in parser and base64 support. checksum support for ldap
+ sudoers
+ [b8f196346eca]
+
+2013-04-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS, plugins/sudoers/sha2.c, plugins/sudoers/sha2.h:
+ SHA-224, SHA-256, SHA-384 and SHA-512. Derived from the public
+ domain SHA-1 and SHA-2 implementations by Steve Reid and Wei Dai
+ respectively.
+ [7511d07c0a83]
+
+2013-04-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Add sudo 1.8.6p8
+ [0666fd0321ae]
+
+ * plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/po/sudoers.pot:
+ Add missing "not" in error message when mixing standalone and non-
+ standalone authentication methods.
+ [7eba4439db73]
+
+ * plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/secureware.c:
+ Check for crypt() returning NULL. Traditionally, crypt() never
+ returned NULL but newer versions of eglibc have a crypt() that does.
+ Bug #598
+ [887b9df243df]
+
+ * plugins/sudoers/auth/pam.c:
+ Better PAM error messages
+ [fd7eda53cdd7]
+
+ * plugins/sudoers/auth/kerb5.c:
+ Better error messages
+ [98142874a2f4]
+
+ * plugins/sudoers/bsm_audit.c:
+ Use same error message for getauid() failure.
+ [07f0d88cb1df]
+
+ * plugins/sudoers/sssd.c:
+ Start warning with a lower case letter for consistency and to match
+ existing translated strings.
+ [b719ac52c9e3]
+
+2013-04-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg:
+ Disable PIE on Solaris where it is not really supported.
+ [c36c84cdcc7a]
+
+ * src/ttyname.c:
+ AIX may have a 64-bit pr_ttydev that we need to convert to 32-bit
+ before we try to match it against st_rdev.
+ [5dab449fb962]
+
+ * src/ttyname.c:
+ Break out of the loop if sudo_ttyname_scan() returns non-NULL. Fixes
+ a problem finding the tty name when it is not in /dev/pts.
+ [6c205d087fa0]
+
+ * compat/snprintf.c:
+ Support %lld and %llu
+ [feabfa06c954]
+
+ * .hgignore, MANIFEST, src/Makefile.in,
+ src/regress/ttyname/check_ttyname.c:
+ Add ttyname test.
+ [e987038f8c07]
+
+2013-04-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/sl.mo, plugins/sudoers/po/sl.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ src/po/de.mo, src/po/de.po, src/po/fi.mo, src/po/fi.po,
+ src/po/pl.mo, src/po/pl.po, src/po/ru.mo, src/po/ru.po,
+ src/po/sl.mo, src/po/sl.po, src/po/uk.mo, src/po/uk.po,
+ src/po/vi.mo, src/po/vi.po, src/po/zh_CN.mo, src/po/zh_CN.po:
+ Sync with translationproject.org
+ [4d7b73b22079]
+
+ * plugins/sudoers/timestamp.c:
+ Log timestampfile to debug file.
+ [e997281146c0]
+
+ * plugins/sudoers/auth/pam.c, plugins/sudoers/po/sudoers.pot:
+ Don't add the "Password: " string we look up in the PAM text domain
+ to the sudoers.pot file.
+ [771b52244abf]
+
+2013-04-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot:
+ Synce with regcomp() error message change.
+ [fc6d3dfb8eb8]
+
+ * plugins/sudoers/sudoreplay.c:
+ Be consistent with error message when regcomp() fails.
+ [de6c69ba04e4]
+
+2013-04-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/regress/testsudoers/test5.out.ok,
+ plugins/sudoers/regress/testsudoers/test5.sh:
+ Use group -1 instead of 1 as the invalid group since the running
+ user might have group 1 as their default group.
+ [71404a9fa75d]
+
+ * plugins/sudoers/Makefile.in:
+ PWD may be a shell builtin, use CWD instead.
+ [c443105c5091]
+
+2013-04-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c:
+ Split up check_user().
+ [ce7cc0767589]
+
+2013-04-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure.in:
+ Cosmetic fixes in the comments.
+ [640abee43c14]
+
+2013-04-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Use AC_LINK_IFELSE instead of AC_TRY_LINK Fix printing of status
+ message for visibility checks when the test fails.
+ [99665477ee55]
+
+ * config.h.in:
+ regen
+ [00c22606719a]
+
+ * configure, configure.in:
+ We no longer use mbr_check_membership() and setrlimit64() is AIX-
+ specific.
+ [43caf685a1f1]
+
+ * Makefile.in:
+ The first (all) target must be by itself or some makes will choose
+ the run the entire target list.
+ [16cf3def49f5]
+
+ * configure, configure.in:
+ Do exec_prefix expansion when enable_shared even if noexec is not
+ enabled.
+ [7ed28cb32d8d]
+
+ * compat/getgrouplist.c:
+ Use free() not efree() since we don't include alloc.h here
+ [1a008737be24]
+
+ * plugins/sudoers/po/sudoers.pot, src/po/sudo.pot:
+ regen
+ [b939f941346f]
+
+ * plugins/sudoers/regress/testsudoers/test2.sh,
+ plugins/sudoers/regress/testsudoers/test3.sh,
+ plugins/sudoers/regress/testsudoers/test5.sh:
+ Pass in expected gid to testsudoers in addition to the uid that
+ matches the test sudoers files.
+ [6a1710e8cac1]
+
+2013-04-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/missing.h:
+ Tru64 5.x does declare innetgr() and getdomainname().
+ [c75598e69c7e]
+
+ * plugins/sudoers/match.c:
+ Fix compilation when getdomainame() is not present.
+ [e831b017a962]
+
+ * config.h.in, configure.in, include/missing.h:
+ Move SET/CLR/ISSET from config.h.in to missing.h
+ [3a3dd29fd7f0]
+
+ * configure, configure.in:
+ Fix getgrouplist() check.
+ [12a2adf60e98]
+
+ * MANIFEST:
+ No more timestamp.h
+ [5677e26afc0f]
+
+ * plugins/sudoers/check.c:
+ Neded sys/time.h for struct timeval in struct sudo_tty_info.
+ [aceaadd8c400]
+
+ * plugins/sudoers/Makefile.in:
+ regen depends
+ [21675a8b67e5]
+
+ * NEWS:
+ Mention libibmldap on HP-UX
+ [75b4e4b22950]
+
+ * NEWS, plugins/sudoers/match.c:
+ Instead of checking the domain name explicitly for "(none)", just
+ check for illegal characters.
+ [ce35dda811db]
+
+ * plugins/sudoers/visudo.c:
+ Only warn once when we are unable to open the sudoers file.
+ [9e27e3aa5b10]
+
+ * plugins/sudoers/sudoers.c:
+ Fall back to opening /dev/tty to determine whether there is a tty if
+ the system doesn't have kernel support for determing the tty.
+ [2775bcf9a9b5]
+
+ * compat/getprogname.c:
+ Update guard to take __progname into account
+ [60eae3f20232]
+
+ * compat/snprintf.c:
+ Some older systems have inttypes.h but not stdint.h
+ [ed1ef160015f]
+
+ * compat/closefrom.c, compat/dlopen.c, compat/fnmatch.c,
+ compat/getaddrinfo.c, compat/getcwd.c, compat/getgrouplist.c,
+ compat/getline.c, compat/getprogname.c, compat/glob.c,
+ compat/isblank.c, compat/memrchr.c, compat/mktemp.c,
+ compat/nanosleep.c, compat/pw_dup.c, compat/sig2str.c,
+ compat/snprintf.c, compat/strlcat.c, compat/strlcpy.c,
+ compat/strsignal.c, compat/utimes.c:
+ Add guards in compat source files. Not really needed since we only
+ include them in the Makefile if they are needed but should not hurt
+ either.
+ [8cbd3b4595b9]
+
+2013-03-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Don't include gram.h in gram.y, its contents are already included.
+ Move sudoerserror to the end of gram.y so COMMENT is declared when
+ we need to use it.
+ [7d72ebdd7222]
+
+2013-03-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure.in:
+ Remove some pre-ANSI cruft.
+ [6a95704b2116]
+
+ * plugins/sudoers/match.c:
+ Rename NAME_MATCH -> SUDOERS_NAME_MATCH and avoid pulling in glob.h
+ when it is set.
+ [da40c550ffed]
+
+ * NEWS, plugins/sudoers/iolog_path.c:
+ We still want to recognize %{seq} for the SUDOERS_NO_SEQ case but
+ just leave it as-is.
+ [9a22de140d28]
+
+2013-03-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Add missing semicolon in rule.
+ [817d3f1b2a21]
+
+ * plugins/sudoers/sudoers.c:
+ Now that we can determine the terminal even when file descriptors
+ are redirected we can check user_ttypath rather than opening
+ /dev/tty when enforcing requiretty.
+ [56a28bc09041]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Stash umask in struct sudo_user so we don't need to look it up
+ later.
+ [9f85749199dc]
+
+ * plugins/sudoers/sudoers.c:
+ Minor cosmetic change
+ [c373e106ed49]
+
+ * plugins/sudoers/regress/parser/check_addr.c:
+ No longer need to declare interfaces
+ [d7ff7e579557]
+
+ * plugins/sudoers/logging.c:
+ Fix compilation in SUDOERS_NO_SEQ case
+ [9a6db9247534]
+
+ * plugins/sudoers/regress/parser/check_addr.c:
+ No longer need to define sudo_printf
+ [578ad13c3546]
+
+ * plugins/sudoers/check.c, plugins/sudoers/check.h,
+ plugins/sudoers/timestamp.c:
+ Pass auth_pw to the timestamp functions.
+ [f603649177d6]
+
+ * plugins/sudoers/iolog_path.c:
+ Fix SUDOERS_NO_SEQ
+ [17881f9bcd68]
+
+ * plugins/sudoers/locale.c:
+ Don't need all of sudoers.h in here
+ [c518150c6483]
+
+ * plugins/sudoers/sudoers.c:
+ Don't need to include sudoers_version.h here.
+ [8abb31102119]
+
+2013-03-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c:
+ DEFAULT_LECTURE is no longer used.
+ [f565c00a68c1]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.c:
+ Move sudo_conv into policy.c
+ [f699aee7136b]
+
+ * plugins/sudoers/pwutil.c:
+ cosmetic fixes
+ [930e60389ca8]
+
+ * plugins/sudoers/match.c:
+ RHEL (and perhaps other Linux distros) use the string "(none)"
+ instead of an empty string when there is no actual NIS-style domain
+ name. Bug #596
+ [11aec11489ac]
+
+ * plugins/sudoers/match.c:
+ Fix return values when NAME_MATCH is defined.
+ [ce030be9ccef]
+
+2013-03-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/pwutil.c, plugins/sudoers/pwutil.h:
+ Update copyright year.
+ [7e4b8d49addd]
+
+ * plugins/sudoers/pwutil.c, plugins/sudoers/pwutil.h,
+ plugins/sudoers/pwutil_impl.c, plugins/sudoers/sudoers.h:
+ Add sudo_set_grlist(), currently unused by the back end.
+ [b37ac1d0e8fc]
+
+ * plugins/sudoers/pwutil.c:
+ Remove unused macros, fix a debug_decl
+ [6136fb4a0d3b]
+
+ * include/missing.h:
+ Tru64 Unix doesn't prototype innetgr() or getdomainname().
+ [585ac1874dfe]
+
+ * include/missing.h:
+ Whitespace fixes
+ [0bb28cd91d97]
+
+ * common/error.c:
+ Don't need to include setjmp.h here, error.h already includes it.
+ [fd05ab00e186]
+
+2013-03-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/Makefile.in, plugins/sudoers/Makefile.in:
+ regen depends
+ [57991f5e16b4]
+
+ * plugins/sudoers/check.h:
+ Rename guard define.
+ [ccf4dba241d6]
+
+ * plugins/sudoers/check.c, plugins/sudoers/check.h,
+ plugins/sudoers/timestamp.c, plugins/sudoers/timestamp.h:
+ Move contents of timestamp.h into check.h.
+ [c139757a9283]
+
+ * plugins/sudoers/sudoers.h:
+ expand_prompt() is now in prompt.c sudo_printf extern is now in
+ error.h
+ [219bd74ca62b]
+
+ * plugins/sudoers/bsm_audit.h, plugins/sudoers/defaults.h,
+ plugins/sudoers/ins_2001.h, plugins/sudoers/ins_classic.h,
+ plugins/sudoers/ins_csops.h, plugins/sudoers/ins_goons.h,
+ plugins/sudoers/insults.h, plugins/sudoers/interfaces.h,
+ plugins/sudoers/linux_audit.h, plugins/sudoers/logging.h,
+ plugins/sudoers/parse.h, plugins/sudoers/pwutil.h,
+ plugins/sudoers/redblack.h, plugins/sudoers/sudo_nss.h,
+ plugins/sudoers/sudoers.h, plugins/sudoers/timestamp.h,
+ plugins/sudoers/toke.h:
+ Change multiple inclusion guards to be _SUDOERS_FOO_H
+ [faace6d55e78]
+
+2013-03-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/po/nl.mo, plugins/sudoers/po/nl.po,
+ src/po/nl.mo, src/po/nl.po, src/po/tr.mo, src/po/tr.po:
+ New Dutch translation for sudo and sudoers New Turkish translation
+ for sudo From translationproject.org
+ [bc918b7b23a4]
+
+2013-03-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in:
+ Fix a typo in a comment and make sure we don't mistakenly include
+ _PATH_SUDO_ASKPASS and _PATH_SUDO_SESH in config.h.in
+ [694d12ac70ec]
+
+2013-03-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ Don't build check_symbols if we are linking sudoers in statically.
+ [f6602723bab7]
+
+ * configure, configure.in:
+ Use $host_os not $host when we only care about the os name and
+ version.
+ [05e4f4fcba06]
+
+ * aclocal.m4, configure, configure.in:
+ Suppress duplicate -L and -I flags.
+ [228f2f581aed]
+
+ * common/Makefile.in, compat/regress/fnmatch/fnm_test.c:
+ Fix regress tests on non-OpenBSD platforms.
+ [9d91bc859c50]
+
+ * configure, configure.in:
+ If we find sasl/sasl.h there's no need to check for sasl.h too
+ [889efaa86012]
+
+ * aclocal.m4, configure, configure.in:
+ Add -R flags at the very end after configure link tests are done
+ since we can only count on libtool to accept -R, the compiler front
+ end may not. Also unify the libldap and libibmldap tests using
+ AC_SEARCH_LIBS and check for -lCsup on HP-UX which is needed by
+ libibmldap (but is not an explicit dependency).
+ [ab1451894351]
+
+2013-03-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Back out changes that broke detection of skey, opie and ldap
+ libraries.
+ [ffa82b8f8641]
+
+ * plugins/sudoers/regress/testsudoers/test1.sh,
+ plugins/sudoers/regress/testsudoers/test2.sh,
+ plugins/sudoers/regress/testsudoers/test3.sh,
+ plugins/sudoers/regress/testsudoers/test4.sh,
+ plugins/sudoers/regress/testsudoers/test5.sh,
+ plugins/sudoers/regress/visudo/test1.sh,
+ plugins/sudoers/regress/visudo/test2.sh,
+ plugins/sudoers/regress/visudo/test3.sh:
+ Add explicit "exit 0" to prevent the check target from ending
+ prematurely.
+ [cca411b492bd]
+
+ * plugins/sudoers/Makefile.in:
+ Fix exit values in check target so we don't have to ignore errors.
+ [cbc429c409e9]
+
+ * plugins/sudoers/Makefile.in:
+ Fail a test if there is unexpected stderr output.
+ [4fc24d536bec]
+
+ * MANIFEST:
+ Fix path to sudo.conf manuals; remove non-existant test2.err.ok
+ [6b8bcd60dd85]
+
+ * src/load_plugins.c:
+ Fix compilation in dynamic mode.
+ [679856fa0774]
+
+ * configure, configure.in:
+ On HP-UX, libibmldap has a hidden dependency on libCsup
+ [22994709d77c]
+
+ * compat/dlopen.c:
+ Pass BIND_VERBOSE to shl_load()
+ [0060b9cfa9ab]
+
+ * configure, configure.in:
+ Only create static helper libs when --disable-shared is specified.
+ [1fcdb1a437e0]
+
+ * src/load_plugins.c:
+ Ubreak static build.
+ [4ac9f96be285]
+
+ * INSTALL, aclocal.m4, configure, configure.in:
+ Replace --with-rpath and --with-blibpath with --disable-rpath. Now
+ that we use libtool for linking we can just use the -R flag and have
+ libtool translate it to the proper linker flag.
+ [09798fad6888]
+
+2013-03-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c:
+ Bump I/O buffer size 32K
+ [4ef793225309]
+
+2013-03-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in:
+ Document sesh Path setting.
+ [34b0b903b4f8]
+
+ * src/exec.c, src/exec_common.c:
+ Move exec_cmnd to exec.c to fix a compilation issue with sesh.c
+ [06aa1956f38d]
+
+ * common/sudo_conf.c, configure, configure.in, include/sudo_conf.h,
+ src/selinux.c:
+ Make sesh path configurable in sudo.conf
+ [91d331f273b7]
+
+ * configure, configure.in:
+ Use -fno-pie and -nopie if supported when --disable-pie is
+ specified.
+ [777138c04dcc]
+
+2013-03-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Document direct execution of the command if the policy plugin has no
+ close function.
+ [6a14145c6e80]
+
+2013-03-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/pam.c:
+ Only delete creds if we actually established them. Print an error if
+ pam_setcred() fails and we actually authenticated.
+ [1e015314903b]
+
+ * common/Makefile.in, plugins/group_file/Makefile.in:
+ regen
+ [dd8cee2a5e1b]
+
+ * common/alloc.c, include/alloc.h:
+ Convert efree() to a macro that just casts to void * and does
+ free(). If the system free() can't handle free(NULL) this may crash
+ but C89 was a long time ago.
+ [efd0ff9270fb]
+
+ * configure, configure.in:
+ Define _REENTRANT for HP-UX when we add -lpthread to SUDO_LIBS.
+ Fixes a problem with errno sometimes not being set on error on HP-
+ UX.
+ [54b419d58320]
+
+ * common/sudo_debug.c:
+ Fix debug logging from the plugin when there is no error number.
+ This was broken in the big debugging reorg for 1.8.7.
+ [2ea7e145e928]
+
+2013-03-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in, plugins/group_file/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/load_plugins.c:
+ Always install plugins with a .so extension regardless of what
+ extension the system uses for shared libraries. That way the
+ group_plugin sudoers setting can be shared between heterogenous
+ systems.
+ [a7e6ecff6fdf]
+
+ * plugins/sudoers/match.c:
+ Mac OS X has netgroup functions in netdb.h.
+ [243881a974aa]
+
+ * plugins/sudoers/parse.h:
+ Tags in struct cmndtag can be set to IMPLIED as well.
+ [cb6926988cc8]
+
+ * plugins/sudoers/parse.c:
+ Quiet a compiler warning.
+ [14e608c2001d]
+
+ * plugins/sudoers/testsudoers.c:
+ Quiet an llvm checker warning.
+ [2eeb9f3d08f3]
+
+ * plugins/sudoers/parse.c:
+ Quiet gcc -Wuninitialized false positive
+ [643ad987503d]
+
+2013-03-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.cat, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in:
+ Document group_file and system_group plugins.
+ [b56511e79230]
+
+ * NEWS:
+ Sudo 1.8.7
+ [e95183b8fa27]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Try to clarify that sudoedit in sudoers should not include a leading
+ pathname.
+ [7b2beac92a9c]
+
+ * plugins/sudoers/pwutil_impl.c:
+ Make sure groupname_len is at least 32 just to be on the safe side.
+ It is better to allocate a little extra and not need it than to have
+ to reallocate and start over.
+ [6d3e1ba47de9]
+
+ * include/alloc.h, include/missing.h:
+ Add __malloc_like macro to apply __malloc__ attribute to emalloc,
+ ecalloc and estrdup. It cannot be applied to realloc since that may
+ return the same pointer.
+ [8d70cb81d1f1]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Fix potential double free in an error path.
+ [657573feb6a4]
+
+ * src/exec_pty.c:
+ When running the command in a pty, defer the call to exec_setup()
+ until just before we exec the command. This is consistent with the
+ non-pty path. As a side effect, the monitor process runs as root and
+ not the runas user.
+ [e2a7f8c7ee4c]
+
+2013-03-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/closefrom.c:
+ Update copyright year.
+ [9b652af4dfc0]
+
+2013-03-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/closefrom.c:
+ Use pst_highestfd from pstat_getproc() on HP-UX.
+ [09f3fea46a3d]
+
+2013-02-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, common/Makefile.in, doc/Makefile.in,
+ plugins/sudoers/Makefile.in:
+ Clean up generated test files and other minor housekeeping.
+ [f5f4fdd908e1]
+
+ * plugins/sudoers/iolog.c:
+ Add back gettimeofday() call inadvertantly removed in e1abb9810a83
+ [675cce8401ae]
+
+ * config.h.in, configure, configure.in, src/ttyname.c:
+ Use pstat() on HP-UX to determine the tty device.
+ [2884af22a9df]
+
+ * plugins/sudoers/auth/pam.c:
+ Fix PAM compilation: def_pam_session, not just pam_session.
+ [5417d7acc6ea]
+
+ * doc/fixmdoc.sh:
+ Don't remove the -S option description when trimming out selinux.
+ Bug #592
+ [8a94f2cfa0a0]
+
+2013-02-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Update for Sudo 1.8.6p7
+ [0858a73e9c40]
+
+2013-02-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Document when sudo may exec the command directly instead of forking.
+ [da41951edc28]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in:
+ Document that close and version be NULL for plugin API >= 1.3 and
+ that sudo may execute the command directly if there is no close, or
+ pty or timeout needed.
+ [e5f929ddeaf8]
+
+ * plugins/sudoers/auth/sudo_auth.c:
+ Fix debug_decl for sudo_auth_begin_session and
+ sudo_auth_end_session.
+ [58243392c0df]
+
+ * configure, configure.in, doc/sudoers.cat, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c:
+ Add pam_session sudoers option.
+ [d994465db9f1]
+
+ * plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.h:
+ Dummy out close function if there is no end_session for the auth
+ method and the front-end can handle a NULL close function. Avoids
+ the extra sudo process when we don't actually need it.
+ [74886d5b0fb6]
+
+2013-02-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, aclocal.m4:
+ Add m4/ to paths m4_include parameters so we don't need to use
+ autoconf's -I flag.
+ [4fd86e7a84f3]
+
+ * src/exec.c, src/exec_common.c, src/exec_pty.c, src/sudo_exec.h,
+ src/sudo_plugin_int.h:
+ If the policy plugin does not provide a close function, there is no
+ command timeout and no pty is required, skip the event loop and just
+ exec the command directly.
+ [ad532f107170]
+
+ * src/sudo.c:
+ Do not crash if the plugin close and version functions are not
+ defined. If there is no policy close function, simply print a
+ warning that the command was not found.
+ [c789a9dd54e8]
+
+2013-02-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/parse.c:
+ Fix typos in selinux/solaris privs specific code.
+ [9af3999361b4]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, src/parse_args.c:
+ Pass the default plugin directory to the plugin via the settings
+ list. Could be used by a stacking plugin.
+ [688e771fc145]
+
+ * plugins/sudoers/timestamp.c:
+ Completely ignore time stamp file if it is set to the epoch,
+ regardless of what gettimeofday() returns.
+ [df58842af660]
+
+ * doc/CONTRIBUTORS:
+ Add Nikolai Kondrashov
+ [df59791438f9]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sssd.c:
+ Use userpw_matches() for username matching so #uid works for
+ sudoRunAsUser.
+ [a124062334df]
+
+ * plugins/sudoers/sssd.c:
+ Avoid calling realloc3() with a zero size parameter when all
+ retrieved sssd rules fail. Otherwise we'll get a run-time error due
+ to malloc(0) checking.
+ [84dfcb73ebd7]
+
+ * plugins/sudoers/sssd.c:
+ Do not send error mail if a user is not found in SSSD. Local users
+ can run sudo too. From Nikolai Kondrashov
+ [3d2ae99ee468]
+
+2013-02-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, common/regress/sudo_conf/test4.in,
+ common/regress/sudo_conf/test4.out.ok:
+ Test setting disable_coredump to illegal value.
+ [3c71c6c49027]
+
+ * common/sudo_conf.c:
+ Fix atobool() usage.
+ [d40c9f4d06b0]
+
+ * common/regress/sudo_conf/conf_test.c:
+ Remove unused variable.
+ [328b524b365b]
+
+ * plugins/sudoers/sudoers.c:
+ Make "sudo -l non_existent_command" warn that non_existent_command
+ doesn't exist, not the "list" pseudo-command.
+ [9dc0388fc4f3]
+
+ * plugins/sudoers/parse.c:
+ Make sudoers file long list output better match the format used by
+ ldap sudoers. Tags are now converted to options and there is a
+ single command per line.
+ [6e6dc3f20d84]
+
+ * doc/sudo.conf.cat, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in,
+ doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Use the correct the sudoers policy symbol names and undo an editor
+ goof committed when adding max_groups to sudo.conf.
+ [2a6f7ddf5cc3]
+
+ * plugins/sudoers/parse.c, plugins/sudoers/sudo_nss.c:
+ For "sudo -l" start a new line if the runas list changes to make the
+ output easier to read.
+ [7dc3d724c924]
+
+2013-02-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/parse.c, plugins/sudoers/sudo_nss.c:
+ For "sudo -l" and "sudo -ll" only print the runas info for
+ subsequent commands in a list if the runas info has changed. If we
+ have new runas info, print out the tags again so as to be less
+ confusing to the user. For "sudo -ll" set the line continuation
+ indent to 8.
+ [b5ec02fe7fc1]
+
+2013-02-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, Makefile.in, configure, configure.in, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/group_file/Makefile.in, plugins/group_file/getgrent.c,
+ plugins/group_file/group_file.c, plugins/group_file/group_file.exp,
+ plugins/group_file/plugin_test.c, plugins/sample_group/Makefile.in,
+ plugins/sample_group/getgrent.c, plugins/sample_group/plugin_test.c,
+ plugins/sample_group/sample_group.c,
+ plugins/sample_group/sample_group.exp:
+ Rename sample_group plugin to group_file. Install group_file and
+ system_group plugins by default.
+ [951b3e446fae]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/iolog.c,
+ plugins/sudoers/policy.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Add maxseq sudoers option to limit the max number of I/O log files.
+ [e1abb9810a83]
+
+2013-02-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ Log lines and columns in the iolog file.
+ [03adb6230e05]
+
+2013-02-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, common/Makefile.in, common/regress/sudo_conf/conf_test.c,
+ common/regress/sudo_conf/test1.in,
+ common/regress/sudo_conf/test1.out.ok,
+ common/regress/sudo_conf/test2.in,
+ common/regress/sudo_conf/test2.out.ok,
+ common/regress/sudo_conf/test3.in,
+ common/regress/sudo_conf/test3.out.ok, common/sudo_conf.c,
+ include/sudo_conf.h, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c, src/sesh.c,
+ src/sudo.c:
+ Add simple regress tests for sudo.conf parsing.
+ [3c36b61bf61c]
+
+ * src/sudo.c:
+ Always display the I/O plugin version as long as its open functions
+ doesn't return an error. Previously it was only displayed if the
+ plugin open returned 1.
+ [4b0277db3f8c]
+
+ * plugins/sudoers/pwutil_impl.c:
+ Use sysconf(_SC_LOGIN_NAME_MAX) to find max username length instead
+ of poking around in struct utmpx.
+ [2c0cc5c42958]
+
+ * plugins/sudoers/pwutil_impl.c, src/parse_args.c, src/sudo.c:
+ #include "sudo_usage.h" not <sudo_usage.h> so we get the one in the
+ build directory and not the src dir when using a separate build
+ directory.
+ [1fcb7ba13018]
+
+2013-02-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/fileops.c:
+ If a line was longer that 0x80000000 the bit hack to round to the
+ next power of two would roll over to zero.
+ [f4f729cf6f0f]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/sudoers.h, src/sudo.c:
+ Use max_groups in front-end and plugin.
+ [bf1e74166831]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, src/parse_args.c:
+ Pass max_groups to plugin in settings list.
+ [d7d76e8651f4]
+
+ * common/sudo_conf.c, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in, include/sudo_conf.h:
+ Add max_groups setting to sudo.conf (currently unused) and remove
+ unused return value from setters.
+ [f6494f71e1f0]
+
+2013-02-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ Reorganize configure options
+ [23475de8039f]
+
+2013-02-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Add Sudo 1.8.6p7
+ [5192fc511cbe]
+
+2013-02-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL.configure:
+ Sync with autoconf 2.68
+ [985e5c8efa4e]
+
+ * INSTALL, README:
+ Remove obsolete OS notes and move build requirements to INSTALL.
+ [bf0dd53ca164]
+
+2013-02-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in:
+ Sort elements of the settings, user_info and command_info lists.
+ [663062ada5b7]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Remove trailing white space
+ [027916a6c8e7]
+
+ * plugins/sudoers/policy.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/timestamp.c, plugins/sudoers/timestamp.h:
+ Store the session ID in the tty ticket file too. A tty may only be
+ in one session at a time so if the session ID doesn't match we
+ ignore the ticket.
+ [4eb2cb8df48b]
+
+2013-02-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c, src/sudo.c:
+ Move tzset() call from sudoers plugin to sudo front end.
+ [3c058dad8772]
+
+ * doc/sudo.conf.cat, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in,
+ doc/sudoers.cat, doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ Mention line continuation
+ [399873f8c805]
+
+ * MANIFEST, common/Makefile.in, common/fileops.c,
+ common/regress/sudo_parseln/parseln_test.c,
+ common/regress/sudo_parseln/test1.in,
+ common/regress/sudo_parseln/test1.out.ok,
+ common/regress/sudo_parseln/test2.in,
+ common/regress/sudo_parseln/test2.out.ok,
+ common/regress/sudo_parseln/test3.in,
+ common/regress/sudo_parseln/test3.out.ok,
+ common/regress/sudo_parseln/test4.in,
+ common/regress/sudo_parseln/test4.out.ok,
+ common/regress/sudo_parseln/test5.in,
+ common/regress/sudo_parseln/test5.out.ok,
+ common/regress/sudo_parseln/test6.in,
+ common/regress/sudo_parseln/test6.out.ok, common/sudo_conf.c,
+ include/fileops.h, plugins/sudoers/env.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/sudo_nss.c:
+ Add line continuation support to sudo_parseln() and make it use
+ getline() instead of fgets() internally.
+ [d02bf3973fc5]
+
+2013-02-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sample/sample_plugin.c:
+ Fix memory leak in error path; found by llvm checker
+ [d090c26a5b00]
+
+ * plugins/sudoers/sudoreplay.c:
+ Remove useless store detected by llvm checker.
+ [12a4db91651a]
+
+ * configure, configure.in, doc/UPGRADE, mkpkg, src/Makefile.in,
+ src/load_plugins.c, sudo.pp:
+ Sudo now stores its libexec files in a "sudo" subdirectory instead
+ of in libexec itself. For backwards compatibility, if the plugin is
+ not found in the default plugin directory, sudo will check the
+ parent directory default directory ends in "/sudo".
+ [5de67de76489]
+
+ * plugins/sample/sample_plugin.c, plugins/sample_group/sample_group.c,
+ plugins/system_group/system_group.c:
+ Add missing __dso_public to plugin structs so they are exported.
+ [dde703577621]
+
+ * doc/sudo.conf.cat, doc/sudo.conf.man.in, doc/sudo.conf.mdoc.in:
+ Mention that sudoers has its own plugins too.
+ [0a6c6203b512]
+
+2013-02-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/visudo.cat, doc/visudo.man.in, doc/visudo.mdoc.in:
+ Correct last change date.
+ [45894291d792]
+
+ * doc/sudo.cat, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.cat, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in:
+ Remove duplicated sudo.conf info in the sudo, sudoers and
+ sudo_plugin manuals and cross-reference the new sudo.conf manual.
+ [b808ba29cf3a]
+
+ * doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in:
+ Fix typos
+ [0e70964150c6]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in:
+ Fix some typos.
+ [94ae045cfbc6]
+
+ * MANIFEST, doc/Makefile.in, doc/sudo.conf.cat, doc/sudo.conf.man.in,
+ doc/sudo.conf.mdoc.in:
+ Add standalone sudo.conf manual page.
+ [d64d949b700c]
+
+ * doc/sample.sudo.conf:
+ add group_source example
+ [118c1ba1c014]
+
+ * configure, configure.in, doc/sample.sudo.conf, doc/sudo.man.in,
+ doc/sudo.mdoc.in, doc/sudo_plugin.man.in, doc/sudo_plugin.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Use PLUGINDIR in the manuals and fix a typo in the sample sudo.conf.
+ [f5bd6006dc1c]
+
+ * plugins/sudoers/po/it.mo, plugins/sudoers/po/it.po, src/po/it.mo,
+ src/po/it.po:
+ Sync with translationproject.org
+ [a6f2b9aac371]
+
+2013-02-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/vi.mo, plugins/sudoers/po/vi.po, src/po/fi.mo,
+ src/po/fi.po, src/po/gl.mo, src/po/gl.po, src/po/vi.mo,
+ src/po/vi.po:
+ Sync with translationproject.org
+ [ba546666969d]
+
+2013-02-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/da.po, plugins/sudoers/po/eo.mo,
+ plugins/sudoers/po/eo.po, src/po/da.po, src/po/eo.mo, src/po/eo.po,
+ src/po/es.po, src/po/gl.po:
+ Sync with translationproject.org
+ [cdc454e34c03]
+
+2013-01-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Clarify ttyname changes.
+ [cbf2f80fe582]
+
+ * NEWS:
+ Add 1.8.6p6
+ [3aa591e98b3b]
+
+ * src/ttyname.c:
+ Remove ttyname() fall back code on systems where we can query the
+ kernel for the tty device via /proc or sysctl(). If there is no
+ controlling tty, it is better to just treat the tty as unknown
+ rather than to blindly use what is hooked up to std{in,out,err}.
+ [b2bd3005d2e4]
+
+2013-01-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/sudo_conf.c, include/sudo_conf.h, src/sudo.c:
+ Add group_source setting in sudo.conf to allow the admin to specify
+ how a user's groups are looked up. Legal values are static (just the
+ kernel list from getgroups), dynamic (whatever the group database
+ includes) and adaptive (only use group db if kernel group list is
+ full).
+ [87a5b02e22ad]
+
+ * plugins/sudoers/policy.c:
+ Pass back exec_background to front end if it is enabled in sudoers.
+ [8230e1cd0bbd]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Mention that exec_background is for 1.8.7 and higher only.
+ [fdf0d5a3e182]
+
+2013-01-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST:
+ Add missing test files.
+ [1165389aa5e6]
+
+ * plugins/sudoers/regress/visudo/test3.err.ok,
+ plugins/sudoers/regress/visudo/test3.out.ok,
+ plugins/sudoers/regress/visudo/test3.sh:
+ Add regress test for bug 361
+ [54c7fb61b82d]
+
+ * plugins/sudoers/iolog.c:
+ Add __dso_public to extern declaration of declaration to match
+ actual definition.
+ [4695ded501e6]
+
+ * NEWS:
+ Add 1.8.6p5
+ [b07b28c5c4d7]
+
+2013-01-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/regress/visudo/test2.err.ok,
+ plugins/sudoers/regress/visudo/test2.out.ok,
+ plugins/sudoers/regress/visudo/test2.sh:
+ Add test for visudo cycle check core dump; test case from Daniel
+ Kopecek
+ [41074541147a]
+
+ * plugins/sudoers/visudo.c:
+ Fix potential stack overflow due to infinite recursion in alias
+ cycle detection. From Daniel Kopecek.
+ [d7e018a87434]
+
+ * common/sudo_conf.c, include/sudo_conf.h, src/load_plugins.c:
+ Ignore duplicate entries in sudo.conf and report the line number
+ when there is an error. Warn, don't abort if there is more than one
+ policy plugin.
+ [dfcb5a698f0a]
+
+ * plugins/sudoers/tsgetgrpw.c:
+ Use strtoul() not atoi().
+ [58a52cf9b6b8]
+
+2013-01-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/Makefile.in:
+ regen depends for to add compat/nss_dbdefs.h for getgrouplist.lo
+ [9b44e9d26d16]
+
+ * compat/nss_dbdefs.h:
+ Fix typo that breaks the build on HP-UX.
+ [b9ab6ba23485]
+
+ * MANIFEST, compat/getgrouplist.c, compat/nss_dbdefs.h, config.h.in,
+ configure, configure.in:
+ Use nss_search() to implement getgrouplist() where available. Tested
+ on Solaris and HP-UX. We need to include a compatibility header for
+ HP-UX which uses the Solaris nsswitch implementation but doesn't
+ ship nss_dbdefs.h.
+ [d29dbc4dc06d]
+
+2013-01-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c, src/exec_pty.c, src/signal.c, src/sudo.h:
+ Remove extra flag to sudo_sigaction(). We want to trap the signal
+ regardless of whether or not it is ignored by the underlying command
+ since there's no way to know what signal handlers the command will
+ install. Now we just use sudo_sigaction() to set a flag in
+ saved_signals[] to indicate whether a signal needs to be restored
+ before exec.
+ [c042d52c7192]
+
+2013-01-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/getgrouplist.c, config.h.in, configure, configure.in:
+ Use _getgroupsbymember() on Solaris to get the groups list. Fixes
+ performance problems with the getgroupslist() compat on Solaris
+ systems with network-based group databases.
+ [287d3ae2ce8d]
+
+2013-01-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in:
+ Document signal handler behavior in plugin API 1.3
+ [20dc9d1c105f]
+
+ * MANIFEST, include/sudo_plugin.h, src/Makefile.in, src/exec.c,
+ src/exec_pty.c, src/signal.c, src/sudo.c, src/sudo.h:
+ Move signal code into its own source file and add sudo_sigaction()
+ wrapper that has an extra flag to check the saved_signals list to
+ only install the handler if the signal is not already ignored. Bump
+ plugin API version for the new front-end signal behavior.
+ [5d2f27a1b404]
+
+ * plugins/sudoers/sudoers.c, src/exec.c, src/sudo.c, src/sudo.h,
+ src/sudo_exec.h:
+ Catch SIGINT, SIGQUIT and SIGTSTP in the front end before we execute
+ the command. If we get SIGINT or SIGQUIT, call the plugin close()
+ functions as if the command was interrupted. If we get SIGTSTP,
+ uninstall the handler and deliver SIGTSTP to ourselves.
+ [332baf3a81b7]
+
+ * src/exec.c, src/exec_pty.c:
+ Rename handle_signals() to dispatch_signals(). Block other signals
+ in handler() so we don't have to worry about the write() being
+ interrupted.
+ [666e95c9a0f1]
+
+2013-01-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/tgetpass.c:
+ Rename signal handler to avoid name clash with one in exec.c
+ [8913101a29b6]
+
+2013-01-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo.c:
+ Add missing call to save_signals().
+ [47d075d7326b]
+
+2013-01-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, plugins/sudoers/po/sudoers.pot, src/po/sudo.pot:
+ Fill in the comment block at the top of the .pot files and preserve
+ it when regenerating them.
+ [6449497b76db]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.cat, doc/sudoers.man.in,
+ doc/sudoers.mdoc.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/sudoers.c, src/exec_pty.c, src/sudo.c, src/sudo.h:
+ Add exec_background option in plugin command info and a sudoers
+ option to match. When set, commands are started in the background
+ and automatically foregrounded as needed. There are issues with some
+ ill-mannered programs (like Linux su) so this is not the default.
+ [c0b32b0938f2]
+
+ * common/Makefile.in:
+ regen
+ [2b2b220e7aea]
+
+ * src/Makefile.in:
+ Add SESH_OBJS variable for sesh object files.
+ [d3e04ae8fd1f]
+
+ * configure.in, doc/LICENSE, plugins/sudoers/redblack.c:
+ Update copyright year.
+ [61a0f0cedb13]
+
+ * src/exec_pty.c:
+ Always resume the command in the foreground if sudo itself is the
+ foreground process. This helps work around poorly behaved programs
+ that catch SIGTTOU/SIGTTIN but suspend themselves with SIGSTOP. At
+ worst, sudo will go into the background but upon resume the command
+ will be runnable. Otherwise, we can get into a situation where the
+ command will immediately suspend itself.
+ [c368ac3eb2e4]
+
+ * configure, configure.in:
+ Use -fstack-protector-all in preference to -fstack-protector where
+ supported.
+ [f930c95ceb51]
+
+2013-01-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Only test for -fstack-protector and -fvisibility=hidden on GNU
+ compatible compilers.
+ [796f4696d863]
+
+2013-01-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Add Sudo 1.8.6p4
+ [8a928de8e717]
+
+ * common/Makefile.in, compat/Makefile.in, configure, configure.in,
+ plugins/sample/Makefile.in, plugins/sample_group/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/system_group/Makefile.in,
+ src/Makefile.in:
+ Break out stack smashing protector options into SSP_CFLAGS and
+ SSP_LDFLAGS so we can use it everywhere (unlike LT_LDFLAGS).
+ [01be114fc9fb]
+
+2013-01-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS, plugins/sudoers/redblack.c:
+ In rbrepair(), make sure we never try to change the color of the
+ sentinel node, which is the first entry, not the root. From Michael
+ King
+ [3fc4dc4004ec]
+
+2012-12-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c:
+ No need to restore default signal handler for SIGSTOP as it is not
+ catchable. Attempting to do so is harmless but sigaction() will fail
+ and set errno to EINVAL which makes it looks like there is an error.
+ [be7c0b759e9a]
+
+ * src/exec.c:
+ Print SIGCONT_FG and SIGCONT_BG properly in debug output.
+ [93e59e301c8f]
+
+2012-12-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Disable PIE on FreeBSD/ia64, otherwise sudo will segfault.
+ [9ed48f696595]
+
+2012-12-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/missing.h:
+ Add howmany() macro since some systems have this in sys/param.h
+ which we no longer include.
+ [2c5efaa16c45]
+
+2012-12-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/regress/sudoers/test11.toke.out.ok:
+ Remove errant file.
+ [a91699beffc6]
+
+2012-12-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_fill.c:
+ Remove obsolete sudoers_cleanup() stubs.
+ [89153025a2ae]
+
+ * common/alloc.c, common/atobool.c, common/fileops.c,
+ common/fmt_string.c, common/lbuf.c, common/secure_path.c,
+ common/sudo_conf.c, common/sudo_debug.c, common/term.c,
+ compat/closefrom.c, compat/getcwd.c, compat/glob.c,
+ compat/snprintf.c, include/missing.h,
+ plugins/sample/sample_plugin.c, plugins/sample_group/getgrent.c,
+ plugins/sample_group/plugin_test.c,
+ plugins/sample_group/sample_group.c, plugins/sudoers/alias.c,
+ plugins/sudoers/auth/afs.c, plugins/sudoers/auth/aix_auth.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/dce.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/passwd.c,
+ plugins/sudoers/auth/rfc1938.c, plugins/sudoers/auth/secureware.c,
+ plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/boottime.c,
+ plugins/sudoers/check.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/env.c, plugins/sudoers/find_path.c,
+ plugins/sudoers/getspwuid.c, plugins/sudoers/goodpath.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/interfaces.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/logging.c, plugins/sudoers/match.c,
+ plugins/sudoers/match_addr.c, plugins/sudoers/parse.c,
+ plugins/sudoers/policy.c, plugins/sudoers/prompt.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/pwutil_impl.c,
+ plugins/sudoers/redblack.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timestamp.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/toke_util.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/visudo.c,
+ plugins/system_group/system_group.c, src/conversation.c, src/exec.c,
+ src/exec_common.c, src/exec_pty.c, src/get_pty.c,
+ src/load_plugins.c, src/net_ifs.c, src/parse_args.c, src/sudo.c,
+ src/sudo_edit.c, src/tgetpass.c, src/ttyname.c, src/utmp.c:
+ Don't include <sys/param.h>. We only needed it for MAXPATHLEN,
+ MAXHOSTNAMELEN and the MIN/MAX macros. We now use PATH_MAX and
+ HOST_NAME_MAX throughout without falling back on MAXPATHLEN or
+ MAXHOSTNAMELEN and define our own MIN/MAX macros as needed.
+ [f4807d46f504]
+
+ * include/missing.h, plugins/sudoers/match.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c, src/sudo.c:
+ Use MAX_HOST_NAME+1 (limits.h) instead of MAXHOSTNAMELEN
+ (sys/param.h or netdb.h).
+ [2544f5e306dd]
+
+2012-11-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/logging.c:
+ Move debug_decl() in log_failure() to be after the variable
+ declarations for C89.
+ [f48d2035ab44]
+
+2012-11-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/error.c, include/error.h, plugins/sudoers/iolog.c,
+ plugins/sudoers/logging.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Cannot wrap sigsetjmp() or we end up returning to the wrong place.
+ Use a macro instead.
+ [749ee6acdad8]
+
+2012-11-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/policy.c:
+ Fix return in sudoers_policy_open that should be debug_return.
+ [a78b795b6846]
+
+2012-11-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/ttyname.c:
+ Define sudo_ttyname_dev() for the HAVE_STRUCT_PSINFO_PR_TTYDEV case
+ too.
+ [acfa891c229e]
+
+ * src/solaris.c:
+ Quiet a gcc warning and add comment about needing to keep the handle
+ open.
+ [f954f228960f]
+
+2012-11-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ mention --disable-shared
+ [6954d39e2d0f]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in:
+ Add missing command_info argument in I/O plugin open() prototype.
+ Bug #579
+ [72beb07aba0e]
+
+2012-11-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/gram.c:
+ Regen for proper line numbers.
+ [6cf6e132e764]
+
+ * configure, configure.in:
+ Add locale_stub.o to SUDO_OBJS, not locale_stub.lo.
+ [d604dc8ca38a]
+
+ * common/sudo_printf.c:
+ Include missing.h for __printflike.
+ [a33640600faf]
+
+ * plugins/sudoers/iolog.c:
+ Saner loop invariant in io_mkdirs (cosmetic only).
+ [dc30274afe38]
+
+ * MANIFEST, common/Makefile.in, common/error.c, common/sudo_printf.c,
+ configure, configure.in, include/error.h, mkdep.pl,
+ plugins/sudoers/Makefile.in, plugins/sudoers/locale.c,
+ plugins/sudoers/logging.c, plugins/sudoers/plugin_error.c,
+ plugins/sudoers/policy.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ src/Makefile.in, src/error.c, src/exec_pty.c, src/locale_stub.c,
+ src/sesh.c:
+ Move warn/error into common and make static builds work.
+ [4d3f374f4e4c]
+
+ * MANIFEST, common/Makefile.in, common/sudo_debug.c,
+ common/sudo_printf.c, include/error.h, plugins/sudoers/Makefile.in,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/iolog.c, plugins/sudoers/plugin_error.c,
+ plugins/sudoers/policy.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ src/Makefile.in, src/conversation.c, src/sesh.c:
+ Move _sudo_printf from src/conversation.c to common/sudo_printf.c.
+ Add sudo_printf function pointer that is initialized to
+ _sudo_printf() instead of requiring a sudo_conv function pointer
+ everywhere. The plugin will reset sudo_printf to point to the
+ version passed in via the plugin open function. Now plugin_error.c
+ can just call sudo_printf in all cases. The sudoers binaries no
+ longer need their own version of sudo_printf.
+ [9b09d3f63790]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/logging.c,
+ plugins/sudoers/plugin_error.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Add plugin_setjmp() wrapper for siglongjmp(error_jmp, 1) so we don't
+ need error_jmp to be extern. Also add plugin_clearjmp() that clears
+ a flag so error()/errorx() knows when to call exit() vs. longjmp().
+ [5a4617148e70]
+
+ * plugins/sudoers/set_perms.c:
+ Let warning() call gettext() for us.
+ [ab8d502ba4ac]
+
+ * include/error.h, plugins/sudoers/plugin_error.c, src/error.c:
+ Do locale swapping in the warning()/error() macros themselves
+ instead of in the underlying functions.
+ [4cd205540e17]
+
+ * common/alloc.c, common/list.c, include/error.h,
+ plugins/sudoers/env.c, plugins/sudoers/plugin_error.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/visudo.c, src/error.c,
+ src/hooks.c:
+ Rename warning2()/error2() -> warning_nodebug()/error_nodebug().
+ [48346393634d]
+
+ * common/sudo_conf.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/rfc1938.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/linux_audit.c,
+ plugins/sudoers/logging.c, plugins/sudoers/plugin_error.c,
+ plugins/sudoers/policy.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/visudo.c, src/error.c,
+ src/exec.c, src/exec_common.c, src/exec_pty.c, src/load_plugins.c,
+ src/net_ifs.c, src/parse_args.c, src/selinux.c, src/sesh.c,
+ src/solaris.c, src/sudo.c, src/sudo_edit.c, src/tgetpass.c:
+ Call gettext() on parameters for warning()/warningx() instead of
+ having warning() do it for us.
+ [c71088bc9d3e]
+
+ * Makefile.in, plugins/sudoers/alias.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/toke_util.c:
+ Call gettext() in sudoerserror() in the user's locale and pass the
+ untranslated string to it.
+ [cdbfc231b848]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/locale.c,
+ plugins/sudoers/logging.h, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Allow sudoers programs (visudo, sudoreplay, visudo) to use
+ plugin_error.c instead of the error.c from the front-end. This means
+ sudoers_setlocale() needs to be independent of the sudo_user struct
+ and the defaults table. The sudoers locale is now updated via a
+ callback.
+ [e356f5f8cd6a]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/logging.c,
+ plugins/sudoers/plugin_error.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Include setjmp.h in sudoers.h Move error_jmp into plugin_error.c
+ Rename sudoers_plugin_cleanup sudoers_cleanup Make sudoers
+ warning/error functions work when sudo_conv is NULL
+ [7365ee24a779]
+
+ * src/error.c:
+ No need to change locale in front-end warning()/error().
+ [23dc1df7f93b]
+
+ * plugins/sudoers/tsgetgrpw.c:
+ Ignore bad lines in passwd/group file instead if stopping processing
+ when we hit one.
+ [79b790559075]
+
+ * plugins/sudoers/regress/testsudoers/test2.sh,
+ plugins/sudoers/regress/testsudoers/test3.sh,
+ plugins/sudoers/regress/testsudoers/test5.sh:
+ Bash doesn't let you set UID to use MYUID instead.
+ [5be56335f059]
+
+ * plugins/sudoers/visudo.c:
+ Avoid NULL deref for unknown Defaults in strict mode.
+ [545c21c1e7d6]
+
+ * common/sudo_conf.c, common/sudo_debug.c:
+ See DEFAULT_TEXT_DOMAIN
+ [3d723e1d27db]
+
+2012-11-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * .hgignore:
+ Add signame.c and mksigname.
+ [d59bbf423f00]
+
+ * plugins/sudoers/Makefile.in:
+ Fold preinstall into install-plugin and pass the path to the plugin
+ binary to the preinstall command.
+ [2c2205af8bb7]
+
+ * pp:
+ sync with upstream
+ [a4b7336b3256]
+
+ * src/sudo.h:
+ repair spacing
+ [f5c1255ce514]
+
+2012-11-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/sudo_debug.c:
+ Set group on sudo_debug when creating it to gid 0 so systems without
+ BSD group semantics don't get the invoking user's group.
+ [7dda01196554]
+
+ * plugins/sudoers/iolog.c:
+ Rename mkdir_parents() io_mkdirs() and add a flag to specify whether
+ path is a temporary, in which case the final component is created
+ via mkdtemp() instead of mkdir().
+ [79c0c4e7ed58]
+
+ * plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.h:
+ For PERM_ROOT set egid to 0 so log files are not created with the
+ gid of the user.
+ [5b964ea43474]
+
+ * plugins/sudoers/logging.c:
+ Add calls to set_perms(PERM_ROOT) becore logging to a file. We
+ should already be root but since we cache the current permission
+ status it is basically free. That way, if more of sudoers runs as
+ non-root in the future logging will still work correctly.
+ [c591d4973f41]
+
+ * common/sudo_conf.c, config.h.in, configure, configure.in,
+ include/gettext.h, plugins/sudoers/locale.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ src/error.c, src/exec.c, src/sesh.c, src/sudo.c:
+ #unifdef HAVE_SETLOCALE, it is C89 so no need to check for it.
+ [41f6bb4926f4]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in:
+ Mention that sudo.conf is parsed in the C locale.
+ [f711c416e30c]
+
+ * common/sudo_conf.c:
+ Parse sudo.conf in the "C" locale.
+ [776658f651ea]
+
+ * plugins/sudoers/locale.c, plugins/sudoers/logging.h,
+ plugins/sudoers/sudoers.h:
+ Fix compilation on systems w/o setlocale()
+ [6940d1c1c1ce]
+
+ * doc/TROUBLESHOOTING:
+ Sudo now includes a workaround for the Solaris 11 locale issue.
+ [ab93787a552c]
+
+2012-11-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/gettext.h, plugins/sudoers/iolog_path.c,
+ plugins/sudoers/locale.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ src/error.c, src/exec.c, src/sesh.c, src/sudo.c, src/sudo.h:
+ Always include locale.h from gettext.h so we no longer need to
+ include locale.h from the .c files.
+ [93d39182ccfa]
+
+ * MANIFEST, config.h.in, configure, configure.in, mkdep.pl,
+ plugins/sudoers/Makefile.in, src/Makefile.in, src/openbsd.c,
+ src/solaris.c, src/sudo.c, src/sudo.h:
+ Add os-specific initialization functions for solaris (workaround
+ setuid locale problem in Solaris 11) and openbsd (set malloc_options
+ if SUDO_DEVEL). Also move set_project() to solaris.c.
+ [1d6581afbaf4]
+
+2012-11-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/find_path.c, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/policy.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/timestamp.c:
+ Avoid strerror() when possible and just rely on warning/error to
+ handle errno in the proper locale.
+ [bf612caae97c]
+
+ * plugins/sudoers/logging.c:
+ Set sudoers locale in log_allowed()
+ [2dd0ac704cae]
+
+ * plugins/sudoers/check.c:
+ Make the sudo lecture translatable.
+ [3cdfc183d72d]
+
+ * Makefile.in:
+ Add the values of badpass_message, passprompt and mailsub to
+ sudoers.pot so they can be translated.
+ [51cbe8adcb94]
+
+ * plugins/sudoers/logging.c:
+ Expand the FMT_FIRST anf FMT_CONTD macros inline so they get picked
+ up by xgettext.
+ [c5b74115caf0]
+
+2012-11-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c, plugins/sudoers/prompt.c,
+ plugins/sudoers/sudoers.h:
+ Make expand_prompt() args const and free the prompt when we are done
+ with it.
+ [995ef8519fe6]
+
+ * plugins/sudoers/policy.c:
+ Fix cut and pasto
+ [e002921c1d15]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/logging.c:
+ Expand def_mailsub in the sudoers locale, not the user's.
+ [a4775f2fb385]
+
+ * common/sudo_conf.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/rfc1938.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/linux_audit.c,
+ plugins/sudoers/logging.c, plugins/sudoers/plugin_error.c,
+ plugins/sudoers/policy.c, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/visudo.c, src/error.c, src/exec.c,
+ src/exec_common.c, src/exec_pty.c, src/load_plugins.c,
+ src/net_ifs.c, src/parse_args.c, src/selinux.c, src/sesh.c,
+ src/sudo.c, src/sudo_edit.c, src/tgetpass.c:
+ Display warning/error messages in the user's locale.
+ [00a04165c0cf]
+
+ * plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/check.c,
+ plugins/sudoers/env.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/locale.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h, plugins/sudoers/parse.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/timestamp.c:
+ Call gettext inside log_error et al instead of having the caller do
+ it. This way we can display any messages to the user in their own
+ locale but log in the sudoers local.
+ [286e0444f785]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/env.c,
+ plugins/sudoers/locale.c, plugins/sudoers/logging.h,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Add simple locale switching to make it easy to switch from the
+ user's locale to the sudoers locale without making excessive
+ setlocale() calls when we don't need to.
+ [5c61582fdeee]
+
+ * plugins/sudoers/iolog_path.c, plugins/sudoers/logging.c,
+ plugins/sudoers/sudoers.c:
+ Convert setlocale() to sudoers_setlocale() in the sudoers module.
+ This only converts existing uses, there are more places where we
+ need to sprinkle sudoers_setlocale() calls.
+ [8ee0cbf0d0a9]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/logging.c, plugins/sudoers/sudoers.c:
+ audit_failure() now calls gettext itself using the sudoers locale.
+ [d77f1d78799a]
+
+ * common/sudo_debug.c, include/error.h, include/sudo_debug.h,
+ plugins/sudoers/plugin_error.c, src/error.c:
+ Add variants of warn/error and sudo_debug_printf that take a va_list
+ instead of a variable number of args.
+ [00392bdc063c]
+
+ * INSTALL, doc/TROUBLESHOOTING:
+ Document Solaris 11 locale issues and workarounds.
+ [05f7d34af3ae]
+
+ * Makefile.in, configure, configure.in:
+ Solaris gettext() looks in lang.UTF-8, not just lang for UTF-8
+ locales. Make links from localdir/lang -> localdir/lang.UTF-8
+ [5ca9326480e2]
+
+2012-11-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/audit.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h, plugins/sudoers/sudoers.c:
+ Do not inform the user that the command was not permitted by the
+ policy if they do not successfully authenticate. This is a
+ regression introduced in sudo 1.8.6.
+ [c1279df08bfb]
+
+ * plugins/sudoers/Makefile.in:
+ Add preinstall target that runs SUDO_PREINSTALL_CMD. Used to fixup
+ the rpath in HP-UX SOM shared libraries for the LDAP libs.
+ [b07185657b42]
+
+ * src/parse_args.c:
+ The -a option should be #ifdef HAVE_BSD_AUTH_H, not -A.
+ [22c73cbe3ff9]
+
+2012-10-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, configure, configure.in:
+ Allow the user to specify and alternate libtool
+ [c9d6fc9521fd]
+
+2012-10-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS, plugins/sudoers/sudo_nss.c:
+ Allow sudo to be build with sss support without also including ldap
+ support. From Stephane Graber.
+ [b992a80ebea1]
+
+2012-10-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/iolog_path.c,
+ plugins/sudoers/logging.c, plugins/sudoers/plugin_error.c,
+ plugins/sudoers/policy.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c:
+ Refactor policy plugin interface code from sudoers.c into policy.c
+ [393e62910b8a]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c:
+ Refactor command_info setting into its own function.
+ [a952b948324c]
+
+ * plugins/sudoers/interfaces.c, plugins/sudoers/interfaces.h,
+ plugins/sudoers/match_addr.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Make interfaces pointer private to interfaces.c and add
+ get_interfaces() accessor.
+ [b69b9334ed3c]
+
+2012-10-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog_path.c, plugins/sudoers/logging.c,
+ plugins/sudoers/sudoers.h:
+ Make user_cwd const since it is either a string literal or passed in
+ from the front-end.
+ [90751b81e8bc]
+
+ * configure, configure.in:
+ sudo 1.8.7
+ [bf727adb8af0]
+
+ * plugins/sudoers/sudoers.c:
+ Avoid nested strtok() calls.
+ [9d9f22ab52a9]
+
+2012-10-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/check.c,
+ plugins/sudoers/prompt.c, plugins/sudoers/sudoers.h:
+ Move expand_prompt() into its own source file for easier unit
+ testing.
+ [b419b48a436f]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/check.c,
+ plugins/sudoers/check.h, plugins/sudoers/sudoers.h,
+ plugins/sudoers/timestamp.c, plugins/sudoers/timestamp.h:
+ Make check.c independent of the underlying timestamp implementation.
+ [895071bd6065]
+
+ * plugins/sudoers/iolog_path.c:
+ Add SUDOERS_NO_SEQ define to allow ${seq} to be disabled.
+ [8ac38f02dd6d]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Use a list for the possible values of Tag_Spec with a minimal indent
+ to improve readability. In the pod version, these were =head3. Also
+ use .St -p1003.1 instead of just POSIX when talking about glob() and
+ fnmatch().
+ [361a6f7a5c44]
+
+2012-10-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/ttyname.c:
+ sudo_ttyname_dev() is unused if there is no /proc or sysctl().
+ [6598dbf81e16]
+
+ * compat/mksiglist.c, compat/mksigname.c,
+ compat/regress/fnmatch/fnm_test.c, compat/regress/glob/globtest.c,
+ plugins/sample_group/plugin_test.c,
+ plugins/sudoers/regress/check_symbols/check_symbols.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c, src/sesh.c, src/sudo.c:
+ Explicitly mark main() as public in executables to avoid an HP-UX ld
+ warning.
+ [72a40ce218be]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in:
+ Remove grep from SEE ALSO section.
+ [c7cafee1621f]
+
+ * common/alloc.c:
+ If vasprintf() fails, just use the errno it sets instead of assuming
+ ENOMEM.
+ [1be5bfdc0cab]
+
+2012-09-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/TROUBLESHOOTING:
+ Mention HP-UX pam.conf settings.
+ [8b8e745b49fd]
+
+2012-09-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/check.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/timestamp.c,
+ plugins/sudoers/timestamp.h:
+ Split off timestamp functions into their own source file.
+ [d5833332511d]
+
+2012-09-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Mention how !foo is not the same as ALL,!foo
+ [51f8e470757d]
+
+2012-09-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c:
+ Start commands in the background when I/O logging is enabled. We
+ can't do this on Mac OS X due to a kernel bug in tc[gs]etattr(2)
+ which returns EINTR on signal instead of restarting automatically.
+ [83b1d59146f7]
+
+ * src/exec_pty.c:
+ Handle SIGCONT_FG and SIGCONT_BG when converting signal number to
+ string in deliver_signal().
+ [2cefea7a976e]
+
+2012-09-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c:
+ Fix running commands that need the terminal in the background when
+ I/O logging is enabled. E.g. "sudo vi &". When the command is
+ foregrounded, it will now resume properly.
+ [0bc13a253429]
+
+ * plugins/sudoers/match.c:
+ Add rudimentary support for name-based matching as a compile-time
+ option. This unsafe when used in conjunction with the '!' operator.
+ [f93bc8e6db15]
+
+2012-09-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/pwutil.c,
+ plugins/sudoers/pwutil.h, plugins/sudoers/pwutil_impl.c:
+ Split out implementation-specific back end code out of pwutil.c into
+ pwutil_impl.c. This will allow the main pwutil code to be used for
+ lookup methods other than getpw* and getgr*.
+ [999c2dde60e4]
+
+2012-09-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, configure, configure.in:
+ sudo 1.8.6p3
+ [97fef3d9ed65]
+
+2012-09-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/fixman.sh:
+ Don't use embedded newline when matching, use \n. This got expanded
+ at some point. Bug #573
+ [6652f834b8f5]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Rename yyerror() to sudoerserror() to match yacc prefix changes. Not
+ really needed due to the #defines that yacc makes but it is less
+ confusing this way as the lexer calls sudoerserror().
+ [a0577be6527d]
+
+ * common/alloc.c, plugins/sample_group/plugin_test.c,
+ plugins/sudoers/env.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/toke_util.c,
+ src/exec_common.c, src/parse_args.c, src/sudo.c:
+ No need to translate "unable to allocate memory" when we can just
+ use the system translation via strerror().
+ [377499e5827c]
+
+ * plugins/sudoers/sudoreplay.c:
+ Fall back on lstat(2) if d_type in struct dirent is DT_UNKNOWN. Not
+ all file systems support d_type. Bug #572
+ [8b861c62945f]
+
+ * plugins/sudoers/sudoreplay.c:
+ Avoid calling fclose(NULL) in the error path when we cannot open an
+ I/O log file.
+ [9401d5c4bb05]
+
+2012-09-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, configure, configure.in:
+ Sudo 1.8.6p2
+ [6e32496280f2]
+
+ * src/exec.c:
+ When setting the signal handler for SIGTSTP to the default value in
+ non-I/O log mode, store the old handler value for when we restore it
+ after resume.
+ [242628694e42]
+
+ * plugins/sudoers/env.c:
+ Replace the guts of sudo_setenv_nodebug() with our old setenv.c
+ which supports non-standard BSD and glibc semantics. sudo_setenv()
+ now simply calls sudo_setenv2().
+ [57ffb6c9efaa]
+
+2012-09-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.mdoc.in, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document non-Unix group support in LDAP sudoers.
+ [33c89f3aeee6]
+
+ * plugins/sudoers/ldap.c:
+ Enable non-Unix group support for LDAP sudoers. We now check for
+ non-Unix groups and netgroups with the same query in the second
+ pass. Bug #571
+ [eb98fdff54d9]
+
+2012-09-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.h, plugins/sudoers/parse.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.h,
+ plugins/sudoers/toke.l, plugins/sudoers/toke_util.c,
+ plugins/sudoers/visudo.c:
+ Set yacc prefix to "sudoers" to avoid conflicts other yacc parsers.
+ [cb6c0d93215e]
+
+2012-09-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Mention support for SUCCESS=return in /etc/nsswitch.conf
+ [ef1f35aa0863]
+
+ * NEWS, configure, configure.in:
+ sudo 1.8.6p1
+ [73a5e1f004b3]
+
+2012-09-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/env.c:
+ Avoid setting LOGNAME, USER and USERNAME variables twice when
+ set_logname is enabled.
+ [0de4f5fbd1d4]
+
+ * plugins/sudoers/env.c:
+ Fix duplicate detection in sudo_putenv(), do not prune out the
+ variable we just set when overwriting an existing instance. Fixes
+ bug #570
+ [854ee714c831]
+
+ * plugins/sudoers/env.c:
+ Add some debuggging
+ [a25cd3305823]
+
+2012-09-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudo_nss.c:
+ Disable word wrap in list mode when stdout is a pipe to make "sudo
+ -l | grep ..." more useful. Adapted from a diff by Daniel Kopecek.
+ [65ade04511fd]
+
+ * common/lbuf.c:
+ Print a trailing newline in lbuf_print() when there is not enough
+ space to do word wrapping and the lbuf does not end with a newline.
+ [c0200e19cd09]
+
+ * plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoers.c:
+ Add support for [SUCCESS=return] in nsswitch.conf; from Daniel
+ Kopecek
+ [5c480316e3ce]
+
+ * MANIFEST:
+ Add sssd.c
+ [9cadd014ef97]
+
+2012-09-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/da.mo, plugins/sudoers/po/fi.mo,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/sl.mo,
+ plugins/sudoers/po/uk.mo, src/po/fi.mo, src/po/hr.mo, src/po/it.mo,
+ src/po/ru.mo, src/po/sl.mo, src/po/uk.mo, src/po/vi.mo:
+ regen .po files
+ [62423d4d143d]
+
+ * MANIFEST, plugins/sudoers/po/vi.mo:
+ Add Vietnamese sudoers translation from translationproject.org
+ [33666a605525]
+
+ * NEWS:
+ mention PIE
+ [05032e5304c6]
+
+ * MANIFEST, plugins/sudoers/po/vi.po:
+ Add Vietnamese sudoers translation from translationproject.org
+ [015c2204bae2]
+
+2012-08-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, compat/Makefile.in, mkdep.pl:
+ Add missing signame dependency
+ [e493bfb01929]
+
+ * src/exec.c, src/ttyname.c:
+ Silence compiler warnings.
+ [1c5374b66d9b]
+
+ * MANIFEST, compat/Makefile.in, compat/sig2str.c, compat/strsigname.c,
+ config.h.in, configure, configure.in, include/missing.h, mkdep.pl,
+ src/exec.c, src/exec_pty.c:
+ Replace strsigname() with sig2str(), emulating it as needed.
+ [1e348cca1fa6]
+
+ * config.h.in, configure, configure.in, src/utmp.c:
+ Use fseeko() for legacy utmp handling if available.
+ [b4bbd8d2c0e9]
+
+2012-08-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/strsigname.c, config.h.in, configure, configure.in:
+ Detect sys_sigabbrev[] and use it in place of sys_signame[] if
+ present. For some reason glibc does not declare sys_sigabbrev so we
+ must add an extern definition of our own.
+ [b38f3fbd7078]
+
+ * compat/strsignal.c, compat/strsigname.c:
+ Handle NULL entries in sys_siglist and sys_signame.
+ [a388959d9654]
+
+ * compat/mksiglist.c, compat/mksiglist.h, compat/mksigname.c,
+ compat/mksigname.h, compat/strsignal.c, compat/strsigname.c:
+ Convert my_sys_sig{list,name} -> sudo_sys_sig{list,name}
+ [711e41aba59a]
+
+2012-08-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ sync
+ [5a2522488754]
+
+ * src/exec.c:
+ Pass on SIGTSTP to the command if it was sent by a user process (not
+ the kernel or the terminal) when we are not I/O logging and set the
+ default SIGTSTP handler when we re-send the signal to ourself,
+ restoring our handler after we resume.
+ [4259c47e31c0]
+
+ * src/exec.c:
+ Shells typically change their process group when they start up so
+ that they can implement job control. Most well-behaved shells change
+ the pgrp back to its original value before suspending so we must not
+ try to restore in that case, lest we race with the child upon
+ resume, potentially stopping sudo with SIGTTOU while the command
+ continues to run. Some shells, such as pdksh, just suspend the shell
+ by sending SIGSTOP to themselves without restoring the pgrp. In this
+ case we need to change the pgrp back for them. Should fix bug #568
+ [6ac6751ffd17]
+
+2012-08-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, compat/Makefile.in, compat/mksigname.c,
+ compat/mksigname.h, compat/strsignal.c, compat/strsigname.c,
+ config.h.in, configure, configure.in, include/missing.h, mkdep.pl,
+ src/exec.c, src/exec_pty.c:
+ Use strsigname() to print signal names in the debug output. If the
+ system has no strsigname(), use our own.
+ [0735f18906b9]
+
+2012-08-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/regress/testsudoers/test5.inc,
+ plugins/sudoers/regress/testsudoers/test5.sh:
+ Remove generated file and change path for temporary include file.
+ [4e9fa830c6b5]
+
+ * plugins/sudoers/Makefile.in:
+ When running regress tests, list pass/fail rate for each dir
+ (testsudoers and visudo) instead of the total. Also prevent the
+ result files from clobbering each other by keeping them in the
+ relevant directories.
+ [6aac53baff7d]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Don't print an error message in yyerror() if open_sudoers() fails,
+ we've already printed an error message. Also restore the check for
+ sudoers_warnings in yyerror().
+ [aa6036df5fb2]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.h,
+ plugins/sudoers/toke.l:
+ Avoid printing the >>> parse error <<< message for testsudoers when
+ the -t flag is specified.
+ [76f3433c8992]
+
+2012-08-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/parse.c:
+ Fix NULL deref when an entry has no Runas_Entry
+ [4b14983ff6e7]
+
+ * plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ src/po/ja.mo, src/po/ja.po, src/po/pl.mo, src/po/pl.po,
+ src/po/zh_CN.mo, src/po/zh_CN.po:
+ sync with translationproject.org
+ [440e9c9b37de]
+
+ * NEWS:
+ sync
+ [3142ba2dce60]
+
+ * plugins/sudoers/check.c:
+ Correct the check_user() comment header.
+ [73da30308fff]
+
+ * plugins/sudoers/auth/sudo_auth.c:
+ Change a log_fatal() into log_error() when no auth methods are
+ configured. The caller already checks the return value.
+ [05f5c39793a7]
+
+ * plugins/sudoers/logging.c:
+ Add missing debug_return
+ [3a76bb7c2fe7]
+
+2012-08-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.cat, doc/sudoers.ldap.cat,
+ doc/sudoers.ldap.man.in, doc/sudoers.ldap.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Make the capitalization consistent for .Ss and .Sx
+ [5c5735ee4b2f]
+
+ * doc/Makefile.in, doc/fixman.sh, doc/fixmdoc.sh, doc/sudo.cat,
+ doc/sudo.man.in, doc/sudo.mdoc.in:
+ Add COMMAND EXECUTION section that describes how sudo runs the
+ command, the extra sudo processes and signal handling.
+ [dff2d88e984e]
+
+2012-08-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ Happy Easter
+ [4b9d697c6b83]
+
+2012-08-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/Makefile.in:
+ Don't echo the awk command when building siglist.in
+ [21daa72921e6]
+
+ * doc/fixman.sh, doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Cosmetic changes.
+ [19259528e9ad]
+
+ * doc/Makefile.in:
+ The HISTORY, LICENSE and CONTRIBUTORS files are not longer
+ generated.
+ [ea6ac9e981e6]
+
+ * MANIFEST, plugins/sudoers/po/da.po, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/hr.po, plugins/sudoers/po/it.mo,
+ plugins/sudoers/po/it.po, plugins/sudoers/po/sl.po,
+ plugins/sudoers/po/uk.po, src/po/de.mo, src/po/de.po, src/po/fi.po,
+ src/po/hr.po, src/po/it.po, src/po/ru.po, src/po/sl.po,
+ src/po/uk.po, src/po/vi.po:
+ Sync with translationproject.org and add Italian sudoers
+ translation.
+ [9276740aea59]
+
+2012-08-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Expand description of fqdn to talk about systems where the hosts
+ file is searched before DNS.
+ [4ee812ca6116]
+
+2012-08-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/Makefile.in:
+ For cat pages there is nothing to make unless DEVEL is set.
+ [fab4a5b68708]
+
+ * configure, configure.in, doc/Makefile.in:
+ Always use mandoc to format cat pages and remove now-extraneous
+ nroff configure tests.
+ [5747f4ed5762]
+
+ * pp:
+ sync polypkg from git
+ [89ddf6ea3e3f]
+
+ * plugins/sudoers/sudoers.c:
+ Use AI_FQDN instead of AI_CANONNAME if available since "canonical"
+ is not always the same as "fully qualified".
+ [7c1d9c098386]
+
+2012-08-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.mdoc.in:
+ Fix some typos. Describe error messages not related to policy
+ permissions.
+ [f5ebf9030d85]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/visudo.c:
+ Add new check_defaults() function to check (but not update) the
+ Defaults entries. Visudo can now use this instead of update_defaults
+ to check all the defaults regardless instead of just the global
+ Defaults entries.
+ [3fa879ce1b65]
+
+2012-08-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Document sudoers log format.
+ [08998a7061ab]
+
+ * NEWS:
+ Update for sudo 1.8.5p3
+ [6e102a5d4e8d]
+
+ * src/load_plugins.c:
+ Add missing check for I/O plugin API version when checking for the
+ presence of I/O plugin hooks.
+ [ef05c7eeaf81]
+
+ * src/hooks.c:
+ Can't call debug code in the process_hooks_xxx functions() since
+ ctime() may look up the timezone via the TZ environment variable.
+ [2179fb26bd8e]
+
+2012-08-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_common.c, src/sesh.c, src/utmp.c:
+ Include signal.h before sudo_exec.h since it uses sigset_t * in the
+ fork_pty prototype.
+ [94fc0d859600]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in, doc/sudoreplay.cat,
+ doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in, doc/visudo.cat,
+ doc/visudo.man.in, doc/visudo.mdoc.in:
+ Remove OPTIONS section; options now go inside DESCRIPTION
+ [a619fc58a746]
+
+ * plugins/sudoers/po/sudoers.pot, src/po/sudo.pot:
+ regen
+ [44719d80bc06]
+
+ * MANIFEST, NEWS, plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/hr.mo, plugins/sudoers/po/hr.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/sl.mo, plugins/sudoers/po/sl.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ src/po/da.mo, src/po/da.po, src/po/hr.mo, src/po/hr.po,
+ src/po/sl.mo, src/po/sl.po, src/po/vi.mo, src/po/vi.po:
+ Sync with translationproject.org and add new Slovenian translation.
+ [34b4b966bbac]
+
+ * common/alloc.c, plugins/sudoers/check.c, plugins/sudoers/env.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/testsudoers.c:
+ Reduce the number of "internal error, foo overflow" messages that
+ need to be translated.
+ [93ffa2b3d53f]
+
+ * NEWS:
+ Mention HP-UX reboot fix.
+ [1e39b5aa32ac]
+
+ * INSTALL, NEWS, common/sudo_debug.c, configure, configure.in,
+ doc/CONTRIBUTORS, include/sudo_debug.h, mkdep.pl, pathnames.h.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/sssd.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoers.c:
+ Support for using SSSD (http://fedorahosted.org/sssd/) as a sudoers
+ data source. From Daniel Kopecek and Pavel Brezina.
+ [3f85e95d6928]
+
+2012-08-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/sudo_conf.c, src/load_plugins.c:
+ If sudo.conf contains an I/O plugin but no policy plugin, use
+ sudoers for the policy plugin. If a policy plugin is specified
+ without an I/O plugin, only the policy plugin will be loaded.
+ [ea192df2439d]
+
+ * doc/Makefile.in, doc/sudoers.man.in:
+ Do not modify the .Os section when building the .man.in file from
+ .mdoc.in.
+ [a9f9628e147f]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Add a note about wildcards matching multiple words and include an
+ example. Also mention that for sudoedit, a wildcard in command line
+ args does not match a slash.
+ [fcb9fbac14e0]
+
+2012-08-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c, src/sudo_exec.h:
+ Fix a comment, update a variable name in a prototype; all cosmetic.
+ [e89f10cbd6e1]
+
+ * plugins/sudoers/iolog.c:
+ Cast 2nd argument of lseek() to off_t if it is a constant for
+ systems with 64-bit off_t but without a proper lseek() prototype.
+ [d8779da135d0]
+
+ * compat/getline.c, plugins/sudoers/check.c, plugins/sudoers/env.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/visudo.c:
+ Fix some warnings from clang checker-267
+ [1e44ef7860b5]
+
+ * plugins/sample/sample_plugin.c:
+ Fix memory leak found by clang checker-267
+ [f8a43617fdfb]
+
+2012-08-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c, src/exec_pty.c, src/sudo.h, src/sudo_exec.h:
+ If we receive a signal from the command we executed, do not forward
+ it back to the command. This fixes a problem with BSD-derived
+ versions of the reboot command which send SIGTERM to all other
+ processes, including the sudo process. Sudo would then deliver
+ SIGTERM to reboot which would die before calling the reboot() system
+ call, effectively leaving the system in single user mode.
+ [4ffab9ab9e98]
+
+2012-08-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/fixman.sh, doc/fixmdoc.sh:
+ Remove section about Solaris 10 on other systems. Add missing
+ sudoers.man.in bit to fixman.sh.
+ [176559199ba7]
+
+2012-08-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in:
+ Expand section on Solaris privileges.
+ [3a1bfa2f1743]
+
+ * NEWS:
+ Expand a bit on the Solaris priv set changes.
+ [bffb78b4a520]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ The second argument to init_parser() is now bool.
+ [fb727a4fb651]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Fix printing of parse error message to stderr.
+ [dea6b420b84f]
+
+ * plugins/sudoers/check.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/match.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c:
+ If a command matches using an empty Runas_List (i.e. Runas_List is
+ present but empty) and the -u option was not specified, set runas_pw
+ to user_pw instead of using runas_default. This is intended to be
+ used in conjunction with the Solaris Privilege Set support for rules
+ that grant privileges without changing the user.
+ [e84a081f3c11]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.mdoc.in,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y, plugins/sudoers/match.c,
+ plugins/sudoers/parse.c, plugins/sudoers/sudoers_version.h:
+ Add support for parsing an empty Runas_List, which only allows the
+ command to be run as the invoking user. This can be used in
+ conjunction with the Solaris Privilege Set support to grant
+ privileges without changing the user.
+ [dc34373792fc]
+
+2012-08-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/fixman.sh:
+ Fix HP-UX, just use ".TH name section" like the vendor manuals.
+ [559738237c92]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Fix compilation on Solaris
+ [2d310302207c]
+
+ * .hgignore, MANIFEST, doc/Makefile.in, doc/fixman.sh, doc/fixmdoc.sh,
+ doc/sudo.man.sh, doc/sudo.mdoc.sh, doc/sudoers.man.sh,
+ doc/sudoers.mdoc.sh:
+ Generate a sed script file when munging *.mdoc or *.man instead of
+ passing sed expressions on the command line. Older seds do not
+ support \n in a replacement so generate and run a sed script
+ instead.
+ [0bcce3f1ca18]
+
+ * doc/Makefile.in, doc/sudo.man.in, doc/sudo_plugin.man.in,
+ doc/sudoers.ldap.man.in, doc/sudoers.man.in, doc/sudoreplay.man.in,
+ doc/visudo.man.in:
+ Use "Sudo VERSION" as the 4th arg to .TH instead of just "VERSION"
+ [fe0f10b63776]
+
+2012-07-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c:
+ When checking whether a signal is user-generated, compare si_code
+ against SI_USER instead of <= 0 since on HP-UX, terminal-related
+ signals get a code of 0.
+ [4e9021243343]
+
+ * src/sudo.c:
+ SuSE Enterprise Linux uses RLIMIT_NPROC and _SC_CHILD_MAX
+ interchangably. This causes problems when setting RLIMIT_NPROC to
+ RLIM_INFINITY due to a bug in bash where bash tries to honor the
+ value of _SC_CHILD_MAX but treats a value of -1 as an error, and
+ uses a default value of 32 instead.
+
+ Previously, we just checked RLIMIT_NPROC and, if it was unlimited,
+ restored the previous value of RLIMIT_NPROC. However, that makes it
+ impossible to set nproc to unlimited. We now only restore the nproc
+ resource limit if sysconf(_SC_CHILD_MAX) is negative. In most cases,
+ pam_limits will set RLIMIT_NPROC for us.
+ [cb71cc8d0b08]
+
+2012-07-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Active Directory apparently requires that tenths of a second be
+ present in a date so append .0 to the "now" value in the time
+ filter. Also remove space for the global AND from TIMEFILTER_LENGTH
+ since it was not being used consistently. Buffers of
+ TIMEFILTER_LENGTH now need to account for the terminating NUL byte.
+ [d28619ff6e45]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Fix SELinux build
+ [cc0d1f4e851b]
+
+2012-07-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST:
+ Remove pod versinons of HISTORY, CONTRIBUTORS and LICENSE as they
+ were not being kept in sync.
+ [fc3ad1847cb1]
+
+ * doc/HISTORY, doc/Makefile.in, doc/contributors.pod, doc/history.pod,
+ doc/license.pod:
+ Remove pod versinons of HISTORY, CONTRIBUTORS and LICENSE as they
+ were not being kept in sync.
+ [950363dffe3a]
+
+2012-07-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/logging.c:
+ Fix printing of the permission denied message to standard error when
+ a user is not allowed to run a command. This got broken by the
+ recent logging changes.
+ [b7af63da3ca1]
+
+ * plugins/sudoers/sudoers_version.h:
+ Bump grammar version for Solaris privs.
+ [2a2baf024477]
+
+ * doc/schema.ActiveDirectory:
+ Fix errors introduced when sudoNotBefore, sudoNotAfter and sudoOrder
+ were added. From David Hicks.
+ [3fc432a8edb4]
+
+2012-07-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ Remove lex.yy.c when building toke.c
+ [72bb9e62b289]
+
+ * doc/Makefile.in:
+ Fix building docs in a build dir.
+ [7a6f435af022]
+
+ * doc/sudo.man.pl, doc/sudo.pod, doc/sudo_plugin.pod,
+ doc/sudoers.ldap.pod, doc/sudoers.man.pl, doc/sudoers.pod,
+ doc/sudoreplay.pod, doc/visudo.pod:
+ Remove pod versions of the manual; we now use mdoc.
+ [5c967d2dd5db]
+
+ * MANIFEST, doc/Makefile.in, doc/sudo.man.sh, doc/sudo.mdoc.sh,
+ doc/sudoers.man.sh, doc/sudoers.mdoc.sh:
+ Add post-processing scripts to strip out login class, BSD auth,
+ SELinux and privilege set bits when they are not supported.
+ [d0d51f72f597]
+
+ * NEWS, configure.in, doc/CONTRIBUTORS, doc/Makefile.in,
+ doc/contributors.pod, doc/sudoers.cat, doc/sudoers.man.in,
+ doc/sudoers.man.pl, doc/sudoers.mdoc.in, doc/sudoers.pod,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.h, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, src/sudo.c, src/sudo.h:
+ Merge in Solaris privilege support by Darren Moffat and John
+ Zolnowsky
+ [3aa0a64f2f5c]
+
+2012-07-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/contributors.pod:
+ Sync with CONTRIBUTORS file
+ [9a0852306ad9]
+
+ * doc/sudo.man.in, doc/sudo_plugin.man.in, doc/sudoers.ldap.man.in,
+ doc/sudoers.man.in, doc/sudoreplay.man.in:
+ Regen .man.in files with my private mandoc.
+ [dc3c9fc449eb]
+
+ * doc/Makefile.in:
+ add MANDOC variable
+ [35527e66afc5]
+
+2012-07-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.man.in, doc/sudo_plugin.man.in, doc/sudoers.ldap.man.in,
+ doc/sudoers.man.in, doc/sudoreplay.man.in, doc/visudo.man.in:
+ Regen .man.in files with hacked mandoc to avoid issues with historic
+ nroff.
+ [d45cfa7d665f]
+
+2012-07-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.mdoc.in, doc/sudoers.mdoc.in:
+ Fix groff warnings.
+ [111d522ca807]
+
+ * doc/Makefile.in:
+ Fix dependencies for .man.in files.
+ [aefeffe1af2b]
+
+ * .hgignore:
+ Add doc/*.mdoc to ignore file
+ [1e4de6ef2ad8]
+
+ * INSTALL, MANIFEST, NEWS, configure, configure.in, doc/Makefile.in,
+ doc/sudo.cat, doc/sudo.man.in, doc/sudo.mdoc.in,
+ doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.mdoc.in, doc/sudoers.cat, doc/sudoers.ldap.cat,
+ doc/sudoers.ldap.man.in, doc/sudoers.ldap.mdoc.in,
+ doc/sudoers.man.in, doc/sudoers.mdoc.in, doc/sudoreplay.cat,
+ doc/sudoreplay.man.in, doc/sudoreplay.mdoc.in, doc/visudo.cat,
+ doc/visudo.man.in, doc/visudo.mdoc.in:
+ Build .man.in and .cat files from .mdoc.in files. Add new --with-man
+ and --with-mdoc configure options.
+ [c963fd7e8f80]
+
+2012-07-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.mdoc.in, doc/sudo_plugin.mdoc.in, doc/sudoers.ldap.mdoc.in,
+ doc/sudoers.mdoc.in, doc/sudoreplay.mdoc.in, doc/visudo.mdoc.in:
+ Sudo manuals formatted in mdoc, to replace the pod versions.
+ [e6dca4030451]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod,
+ doc/sudoers.cat, doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.pod, doc/sudoers.man.in, doc/sudoers.pod,
+ doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.pod,
+ doc/visudo.cat, doc/visudo.man.in, doc/visudo.pod:
+ More minor costmetic fixes.
+ [a7287a68385a]
+
+2012-07-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod:
+ Minor cosmetic fixes.
+ [9c48bdaf3946]
+
+2012-07-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/logging.c, plugins/sudoers/po/sudoers.pot:
+ Use "a password is required" instead of "password required" when the
+ -n flag is used and we need to read a password.
+ [a3c30fc41648]
+
+2012-07-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Mention logging changes.
+ [8238fd6e02e8]
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [e2cf634ba63b]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod:
+ Document that other mail_* flags have precedence over mail_badpass.
+ [9f4cc9188f40]
+
+ * plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/check.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Move log_denial() calls and logic to log_failure(). Move
+ authentication failure logging to log_auth_failure(). Both of these
+ call audit_failure() for us.
+
+ This subtly changes logging for commands that are denied by sudoers
+ but where the user failed to enter the correct password. Previously,
+ these would be logged as "N incorrect password attempts" but now are
+ logged as "command not allowed". Fixes bug #563
+ [cad35f0b3ad7]
+
+2012-07-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/aix.c:
+ Do not set a resource limit to zero when we are unable to fetch a
+ value from /etc/security/limits.
+ [62bfb0a7895e]
+
+2012-07-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Add "Provides: sudo" to debian sudo-ldap package
+ [beb8afa0beb2]
+
+2012-07-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in, zlib/Makefile.in:
+ Define NO_VIZ for zlib when gcc doesn't support symbol visibility
+ attributes.
+ [9fdcbf526386]
+
+ * configure, configure.in:
+ Use the autoconf cache when checking for symbol export control
+ support.
+ [03c2cce8711f]
+
+ * INSTALL, common/Makefile.in, compat/Makefile.in, configure,
+ configure.in, mkpkg, plugins/sample/Makefile.in,
+ plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/Makefile.in:
+ Add configure check for building PIE executables instead of doing it
+ in mkpkg.
+ [02b5b78ef258]
+
+ * sudo.pp:
+ MacOS pp backend doesn't like modes longer than 4 characters.
+ [01b49022bf01]
+
+2012-07-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Add -Wc,-fstack-protector to LT_LDFLAGS instead of adding
+ -fstack-protector to LDFLAGS so it doesn't get stripped out. Libtool
+ will strip -fstack-protector from the linker flags and we always
+ link with libtool.
+ [0a0a0250ac2b]
+
+2012-06-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo_plugin.cat,
+ doc/sudo_plugin.man.in, doc/sudoers.cat, doc/sudoers.ldap.cat,
+ doc/sudoers.ldap.man.in, doc/sudoers.man.in, doc/sudoreplay.cat,
+ doc/sudoreplay.man.in, doc/visudo.cat, doc/visudo.man.in:
+ Regen for sudo 1.8.6
+ [1657ee28b496]
+
+ * NEWS, doc/sudoers.ldap.pod:
+ Document improved Tivoli Directory Server support.
+ [fb411edf4687]
+
+ * config.h.in, configure, configure.in, plugins/sudoers/ldap.c:
+ Add support for ldaps using Tivoli LDAP libraries. Add ldap.conf
+ option to specify Tivoli key db password. Allow TLS ciphers to be
+ configured for Tivoli.
+ [737e17c91e60]
+
+2012-06-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Tivoli Directory Server 6.3 libs always return a (bogus) error when
+ setting LDAP_OPT_CONNECT_TIMEOUT.
+ [504406637c38]
+
+ * NEWS:
+ Update
+ [687a755604e8]
+
+ * plugins/sudoers/ldap.c:
+ Treat LDAP_OPT_CONNECT_TIMEOUT (Tivoli Directory Server 6.3) the
+ same as LDAP_OPT_CONNECT_TIMEOUT (OpenSSH). Don't make failure to a
+ set an ldap option fatal.
+ [17cf93ae3304]
+
+2012-06-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ Zero pointers in sudo_user struct after freeing, just in case.
+ [8eff1f80b943]
+
+ * plugins/sudoers/sudoers.c:
+ Free user_gids in close function if it has not already been freed.
+ [cbce28877f37]
+
+ * plugins/sudoers/pwutil.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Defer group ID to name resolution until we actually need it.
+ [463e75b81e89]
+
+ * src/sudo.c:
+ It is safe to read in sudo.conf before calling user_info().
+ [3290b6434e3c]
+
+ * plugins/sudoers/env.c, plugins/sudoers/ldap.c:
+ Use MAX_UID_T_LEN + 1 for uid/gid buffers, not MAX_UID_T_LEN to
+ prevent potential truncation. Bug #562.
+ [29d9fc4e0c4e]
+
+2012-06-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ If installing with installp, error out if there is already an
+ instance of the rpm package installed.
+ [ec24c6faba22]
+
+ * mkpkg:
+ Add --disable-nls for AIX
+ [192ac2f7d65e]
+
+2012-06-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Debian sudo-ldap packages should now depend on libldap-2.4-2, not
+ libldap2.
+ [cbcec71e6b58]
+
+2012-06-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Add Homepage and Bugs to debian control file.
+ [0f19d7d14e66]
+
+2012-06-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg:
+ fix typo when setting aix_freeware
+ [2fd6feb50195]
+
+ * common/Makefile.in, compat/Makefile.in, configure, configure.in,
+ doc/Makefile.in, include/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/Makefile.in, zlib/Makefile.in:
+ Don't run regress tests or sudoers sanity check (using the newly-
+ built visudo) when cross compiling. Bug #560
+ [0c4e3f68b2f5]
+
+ * MANIFEST, configure, configure.in, plugins/sample/Makefile.in,
+ plugins/sample/sample_plugin.exp, plugins/sample/sample_plugin.map,
+ plugins/sample/sample_plugin.sym, plugins/sample_group/Makefile.in,
+ plugins/sample_group/sample_group.exp,
+ plugins/sample_group/sample_group.map,
+ plugins/sample_group/sample_group.sym, plugins/sudoers/Makefile.in,
+ plugins/sudoers/sudoers.exp, plugins/sudoers/sudoers.map,
+ plugins/sudoers/sudoers.sym, plugins/system_group/Makefile.in,
+ plugins/system_group/system_group.exp,
+ plugins/system_group/system_group.map,
+ plugins/system_group/system_group.sym:
+ Rename foo.sym -> foo.exp Remove foo.map from the repo and generate
+ it on demand Use a loader option file for HP-UX ld to explicitly
+ export symbols
+ [2402ff5302ab]
+
+ * src/Makefile.in:
+ Remove extraneous backslash
+ [8ca054de138c]
+
+ * plugins/sudoers/regress/check_symbols/check_symbols.c:
+ Don't check for errorx as an exported symbols as it is now a macro.
+ Check for user_in_group() instead.
+ [7b02c8ecd3ea]
+
+2012-06-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Adjust ld map file support to use an anonymous scope to match the
+ updated .map files.
+ [49be44282d9e]
+
+2012-06-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, include/gettext.h:
+ Older versions of Solaris lack ngettext()
+ [028af10dfa5f]
+
+ * configure, configure.in:
+ Move the check for -static-libgcc until after AC_LANG_WERROR has
+ been called and use AX_CHECK_COMPILE_FLAG().
+ [a7b09120e7ff]
+
+ * include/gettext.h:
+ Sudo defines HAVE_SETLOCALE not HAVE_LOCALE_H
+ [3aa2780d4a4e]
+
+ * include/error.h, include/sudo_debug.h:
+ Fix gcc 2.x variant macro support.
+ [8e71c2370997]
+
+ * plugins/sudoers/logging.c, plugins/sudoers/sudoreplay.c:
+ Fix compilation on gcc 2.95 and other compilers that only allow
+ variable declarations at the beginning of a block.
+ [9d80c802bb46]
+
+ * configure, configure.in, plugins/sudoers/Makefile.in:
+ Link check_symbols with SUDO_LIBS to make sure we link with the
+ requisite libraries to successfully dlopen sudoers.so. This is
+ needed on HP-UX where a program dlopen()ing a shared object that
+ uses pthreads must also be linked with pthreads (and HP-UX LDAP uses
+ pthreads).
+ [b8961cd82337]
+
+ * plugins/sudoers/regress/check_symbols/check_symbols.c:
+ Add check for exported local symbols. This will cause a "make check"
+ failure on systems where we don't support symbol hiding.
+ [8aa549389bb1]
+
+ * configure, configure.in:
+ Additional ${foo} -> $(foo) Makefile tweaks.
+ [046bbde18f52]
+
+ * plugins/sample/sample_plugin.map,
+ plugins/sample_group/sample_group.map, plugins/sudoers/sudoers.map,
+ plugins/system_group/system_group.map:
+ No need to provide a name for the scope in the map file since we
+ don't use the it for versioning.
+ [5ed4b997560d]
+
+2012-06-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/check_symbols/check_symbols.c:
+ Add regress test for symbol visibility.
+ [9adddd4e0518]
+
+2012-06-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, configure, configure.in:
+ sudo 1.8.6
+ [57008a7afb77]
+
+ * configure, configure.in, include/missing.h:
+ Add support for controlling symbol visibility using the HP and
+ Solaris C compilers.
+ [46d5b468979e]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/iolog_path.c,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/sudoers.h:
+ Use the expanded io log dir when updating the sequence number.
+ Includes a workaround for older versions of sudo where the sequence
+ number was stored in the unexpanded io log dir.
+ [210797dab9a8]
+
+2012-06-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/parse_args.c:
+ Simplify "sudo -s" argv rewriting.
+ [7be143dae7c5]
+
+ * MANIFEST, configure, configure.in, plugins/sample/Makefile.in,
+ plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/Makefile.in,
+ src/sudo_noexec.map:
+ Don't use a map file for sudo_noexec.so since Solaris ld doesn't
+ allow '*' in the global section. The libtool export flag is now
+ added to LT_LDFLAGS instead of commenting/uncommenting lines.
+ [38fc37a66b04]
+
+2012-06-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, include/missing.h:
+ The visibility attribute was actually added in gcc 3.3.x, not 4.0.
+ Just assume that if -fvisibility=hidden works that the attribute is
+ usable.
+ [d3904d6faf14]
+
+ * plugins/sudoers/check.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_path.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/match.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoers.map,
+ plugins/sudoers/sudoers.sym, plugins/sudoers/testsudoers.c,
+ plugins/system_group/system_group.c:
+ Export group cache from sudoers.so for system_group.so to use.
+ [16695d207fc5]
+
+ * MANIFEST, configure, configure.in, include/missing.h,
+ plugins/sample/Makefile.in, plugins/sample/sample_plugin.map,
+ plugins/sample_group/Makefile.in,
+ plugins/sample_group/sample_group.map, plugins/sudoers/Makefile.in,
+ plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.map, plugins/system_group/Makefile.in,
+ plugins/system_group/system_group.map, src/sudo_noexec.c,
+ src/sudo_noexec.map:
+ Use gcc's visibility attribute to specify when symbols are visible
+ or hidden, if available. If not available, use an ELF version script
+ if it is supported. If all else fails, fall back to using libtool's
+ -export-symbols.
+ [64e889921727]
+
+2012-06-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Add mode for installed locale files but leave the directories with
+ default mode and owner.
+ [142237dbb31f]
+
+2012-06-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg, sudo.pp:
+ Install AIX packages under /opt/freeware with links in /usr/bin and
+ /usr/sbin. This matches the layout of the sudo package from AIX
+ freeware.
+ [0b79d47bbe01]
+
+ * Makefile.in, configure, configure.in, plugins/sample/Makefile.in,
+ plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in, src/Makefile.in, sudo.pp:
+ Install shared objects with mode 0644 except on HP-UX which needs
+ the executable bit set.
+ [ae416af0ba6c]
+
+ * Makefile.in, doc/Makefile.in, include/Makefile.in,
+ plugins/sudoers/Makefile.in, src/Makefile.in:
+ Make installed file modes consistent with the file modes in the sudo
+ package.
+ [307386373289]
+
+2012-06-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.pod:
+ Add "%:" prefix when talking about QAS non-Unix group support.
+ [7cb25f6861f8]
+
+ * pp, sudo.pp:
+ Fix packaging of symbolic links on HP-UX when the link source
+ already exists in the filesystem.
+ [c9bb48031596]
+
+ * mkpkg:
+ Only specify prefix if we are overriding the default value. Fixes
+ the man dir (/usr/local/man vs. /usr/local/share/man).
+ [65351b6c1697]
+
+ * sudo.pp:
+ Fix setting of sudoedit_man variable.
+ [9beed9ae5bba]
+
+ * doc/Makefile.in:
+ Echo the command when linking the sudoedit manual.
+ [6c83b5657b55]
+
+2012-06-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg, sudo.pp:
+ Build .deb packages with selinux support.
+ [3fd9cb1b4526]
+
+2012-06-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Don't list paths for unstripped binaries in the lintial overrides.
+ [4c8e16f1773b]
+
+ * pp:
+ Add support for Installed-Size header in control file, required by
+ newer debian versions.
+ [e97d76234bee]
+
+ * pp:
+ Fix extended description in .deb files.
+ [d35e27ace146]
+
+ * sudo.pp:
+ Add Depends, Replaces and Conflicts headers for .deb packages.
+ [76eb6c4b3278]
+
+2012-06-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudo_nss.c:
+ If there are no privs to print, write the message to the lbuf
+ instead of printing it directly.
+ [ecd56226abb7]
+
+2012-05-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Set -e in %pos and %preun for debian to quiet a lintian warning.
+ [8bb908514df9]
+
+ * doc/Makefile.in, src/Makefile.in, sudo.pp:
+ Install sudoedit and the sudoedit manual as symbolic links, not hard
+ links and package them as such.
+ [f317ff3cf3e7]
+
+ * sudo.pp:
+ Make sudo binary permissions 755 instead of 111 Add lintian
+ overrides file for .deb files.
+ [991cd7d7f0e1]
+
+ * configure, configure.in, doc/Makefile.in, mkpkg:
+ Replace out of date MAN_POSTINSTALL with MANCOMPRESS and
+ MANCOMPRESSEXT which can be used to compress the installed manual
+ pages. Compress the man pages for .deb files to appease lintian.
+ [4e34083b41d2]
+
+ * sudo.pp:
+ Debian fixes:
+ * fix modes to be more in line with what Debian expects
+ * add section
+ * install LICENSE as copyright and ChangeLog as changelog
+ * create stub changelog.debian
+ [7f6c5647f588]
+
+ * pp:
+ Fix find command to properly skip files in the DEBIAN dir when
+ building md5sums.
+ [8918bde941fa]
+
+ * pp, sudo.pp:
+ Use a debian-compliant package maintainer field.
+ [fc51a94170eb]
+
+2012-05-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c:
+ No need to loop over atomic_writev(), it guarantees to write all
+ data or return an error.
+
+ Fix handling of stdout/stderr that contains "\r\n" and handle a
+ "\r\n" pair that spans a buffer.
+ [8aaf02d90c45]
+
+2012-05-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Update for sudo 1.8.5p2
+ [d369d4d40a19]
+
+ * plugins/sudoers/sudoreplay.c:
+ Instead of doing extra write()s when replaying stdout, build up a
+ vector for writev() instead. This results in far fewer system calls.
+ [303d866c025c]
+
+2012-05-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/env_hooks.c, src/sudo.h, src/tgetpass.c:
+ Provide unhooked version of getenv() and use it when looking up
+ DISPLAY and SUDO_ASKPASS in the environment.
+ [04dbdccf4a14]
+
+2012-05-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c:
+ When replaying a log of stdout or stderr, do newline to carriage
+ return + linefeed conversion. We cannot have termios do this for us
+ since we've disabled output postprocessing (POST) when setting raw
+ mode.
+ [61352a7d996f]
+
+2012-05-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ When checking for -fstack-protector, treat warnings as fatal errors.
+ [4124cd12d511]
+
+2012-05-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Fix test for -z relro
+ [548bdb6f5c4a]
+
+ * MANIFEST:
+ Add m4/ax_check_compile_flag.m4 and m4/ax_check_link_flag.m4
+ [ed063264a2a1]
+
+ * INSTALL, aclocal.m4, configure, configure.in,
+ m4/ax_check_compile_flag.m4, m4/ax_check_link_flag.m4:
+ Build with -fstack-protector and link with -zrelo where supported.
+ Added --disable-hardening option to disable hardening options.
+ [0b6c1a1ceb03]
+
+2012-05-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/testsudoers/test1.sh,
+ plugins/sudoers/regress/testsudoers/test2.sh,
+ plugins/sudoers/regress/testsudoers/test3.sh,
+ plugins/sudoers/regress/testsudoers/test4.out.ok,
+ plugins/sudoers/regress/testsudoers/test4.sh,
+ plugins/sudoers/regress/testsudoers/test5.inc,
+ plugins/sudoers/regress/testsudoers/test5.out.ok,
+ plugins/sudoers/regress/testsudoers/test5.sh,
+ plugins/sudoers/testsudoers.c:
+ Add tests for sudoers mode, owner and group checks.
+ [a7607443aba0]
+
+ * plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c:
+ If sudoers_mode is group-readable but the actual sudoers file is
+ not, open the file as uid 0, not uid 1. This fixes a problem when
+ sudoers has a more restrictive mode than what sudo expects to find.
+ In older versions, sudo would silently chmod the file to add the
+ group-readable bit.
+ [c056b6003e6f]
+
+ * INSTALL, common/secure_path.c, config.h.in, configure, configure.in:
+ No longer throw an error if sudoers is a symbolic link. Deprecated
+ the --with-stow option as that is now (effectively) the default.
+ [8ce783e54886]
+
+2012-05-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/testsudoers/test2.inc,
+ plugins/sudoers/regress/testsudoers/test2.out.ok,
+ plugins/sudoers/regress/testsudoers/test2.sh,
+ plugins/sudoers/regress/testsudoers/test3.d/root,
+ plugins/sudoers/regress/testsudoers/test3.out.ok,
+ plugins/sudoers/regress/testsudoers/test3.sh:
+ Add basic tests for #include and #includedir
+ [b303e4218951]
+
+ * plugins/sudoers/testsudoers.c:
+ Add -U sudoers_uid option to testsudoers.
+ [3f8ed13501ba]
+
+2012-05-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, configure, configure.in:
+ Update for 1.8.5p1
+ [c33c49bf5b4b]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Fix #includedir; from Mike Frysinger
+ [d4833d4e39a0]
+
+ * plugins/sudoers/check.c:
+ Don't prompt for a password if the user is in the exempt group, is
+ root, or is running the command as themselves even if the -k option
+ was specified. This makes "sudo -k command" consistent with the
+ behavior one would get if the user ran "sudo -k" immediately before
+ running the command.
+ [632b3961df00]
+
+2012-05-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ Fix capitalization
+ [7258aa977caf]
+
+ * mkpkg:
+ Build PIE executable on Mac OS X 10.5 and above.
+ [2a5c7ef92182]
+
+2012-05-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Update for sudo 1.8.4p5
+ [21164f508b68]
+
+ * plugins/sudoers/match_addr.c:
+ Add missing break between AF_INET and AF_INET6 in
+ addr_matches_if_netmask()
+ [672a4793931a]
+
+ * plugins/sudoers/mon_systrace.c:
+ Move systrace monitor code to the attic
+ [d6faf4754e9c]
+
+2012-05-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c:
+ The pointer to the siginfo_t struct in a signal handler may be NULL.
+ [41a4ee934b53]
+
+2012-05-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/pwutil.c:
+ Fix an alignment problem on NetBSD systems with a 64-bit time_t and
+ strict alignment. Based on a patch from Martin Husemann.
+ [1e5ba3c18f17]
+
+ * include/missing.h:
+ Add offsetof macro for those without it.
+ [e44cb51d2587]
+
+ * MANIFEST:
+ add system_group plugin
+ [6169793b510c]
+
+2012-05-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/dlopen.c:
+ Implement RTLD_NEXT and fix RTLD_DEFAULT for HP-UX.
+ [85bd03bc5d94]
+
+2012-05-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Mention system_group plugin
+ [05393dd4bdb8]
+
+ * Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/system_group/Makefile.in:
+ update depends
+ [6feb0b824fc4]
+
+ * plugins/system_group/system_group.c:
+ Only call gr_delref() when use sudo's password caching functions.
+ [1103442e21fa]
+
+ * plugins/sample_group/Makefile.in, plugins/system_group/Makefile.in:
+ Add missing dependency on libreplace.la
+ [05bfd9d4657f]
+
+ * compat/dlopen.c:
+ Emulate RTLD_DEFAULT and RTLD_SELF w/ shl_findsym() using NULL and
+ PROG_HANDLE.
+ [2382d0693acc]
+
+ * Makefile.in, configure, configure.in,
+ plugins/system_group/Makefile.in,
+ plugins/system_group/system_group.c,
+ plugins/system_group/system_group.sym:
+ Add group plugin that does lookups by name using the system group
+ database.
+ [2ddbb604112f]
+
+ * plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po, src/po/pl.mo,
+ src/po/pl.po:
+ sync with translationproject.org
+ [4ef05df4226d]
+
+2012-05-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ src/po/de.mo, src/po/de.po, src/po/eo.mo, src/po/eo.po,
+ src/po/fi.mo, src/po/fi.po, src/po/ja.mo, src/po/ja.po,
+ src/po/ru.mo, src/po/ru.po, src/po/sr.mo, src/po/sr.po,
+ src/po/uk.mo, src/po/uk.po, src/po/vi.mo, src/po/vi.po,
+ src/po/zh_CN.mo, src/po/zh_CN.po:
+ sync with translationproject.org
+ [115c3f828fc5]
+
+2012-05-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Add mode for docdir and use '-' (default) for localedir mode. Fixes
+ a problem on Linux when building in a directory with the setgid bit
+ set.
+ [582279c8bcb1]
+
+2012-04-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pp:
+ Match CentOS 6.0
+ [1e99ef210f98]
+
+2012-04-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Update with recent changes
+ [c5fc220ba696]
+
+ * pp:
+ Fix version check on AIX
+ [d272e39112f4]
+
+ * plugins/sudoers/po/sudoers.pot, src/po/sudo.pot:
+ regen
+ [72b23509465a]
+
+ * plugins/sudoers/ldap.c:
+ Need to call ldapssl_clientauth_init() for start_tls on Mozilla LDAP
+ SDK.
+ [87b685e70b9a]
+
+ * plugins/sudoers/ldap.c:
+ Fix printing of invalid uri
+ [645aa53acdde]
+
+ * plugins/sudoers/auth/pam.c:
+ Pass PAM_SILENT when deleting creds to remove an annoying warning
+ message on Solaris.
+ [1dd0301ef293]
+
+2012-04-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/utmp.c:
+ Fix the setutxent and endutxent compatibility defines (this time
+ correctly) when only setutent and endutent are available.
+ [d136d2867db9]
+
+ * plugins/sudoers/ldap.c:
+ sudo_ldap_set_options_global() should not take an LDAP handle as an
+ argument since the options affect the global settings.
+ [1dc39b9d20f2]
+
+ * mkpkg:
+ Debian sudo has not been built with --with-exempt=sudo since 1.6.8.
+ [c7716291a856]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod,
+ plugins/sudoers/auth/pam.c, src/exec.c, src/exec_pty.c, src/sudo.c,
+ src/sudo.h:
+ Call the policy's init_session() function before we fork the child.
+ That way, the session is created and destroyed in the same process,
+ which is needed by some modules, such as pam_mount.
+ [ece552ba002e]
+
+ * doc/TROUBLESHOOTING:
+ Add entry for SSL LDAP errors on Mozilla SDKs when the cert dir is
+ not specified.
+ [bd293e100b28]
+
+ * plugins/sudoers/auth/pam.c:
+ Delete creds after closing the PAM session.
+ [5158d726d6a5]
+
+ * plugins/sudoers/ldap.c:
+ Provide a more useful error message if using a Mozilla-style LDAP
+ SDK and you forgot to specify TLS_CERT in ldap.conf.
+ [7cb78feb899c]
+
+ * src/exec_pty.c:
+ Add missing initialization of a sigaction structure when I/O
+ logging. Fixes a potential problem when suspending the command.
+ [f4480f2ba816]
+
+ * plugins/sudoers/ldap.c:
+ Split global and per-connection LDAP options into separate arrays.
+ Set global LDAP options before calling ldap_initialize() or
+ ldap_init(). After we have an LDAP handle, set the per-connection
+ options. Fixes a problem with OpenLDAP using the nss crypto backend;
+ bug #342
+ [265c9d2dc12b]
+
+ * plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ src/po/de.mo, src/po/de.po, src/po/hr.mo, src/po/hr.po,
+ src/po/vi.mo, src/po/vi.po, src/po/zh_CN.mo, src/po/zh_CN.po:
+ sync with translationproject.org
+ [6d7fe44be21e]
+
+2012-04-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo.c, src/sudo.h:
+ Move struct passwd pointer into struct command details.
+ [d6fb1eff2065]
+
+2012-04-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pp:
+ Sync with upstream for Mac OS X (and other) fixes.
+ [c2f4998d01b0]
+
+ * mkpkg:
+ Only built Mac intel universal binary on an intel machine.
+ [0009e0b7e5a8]
+
+ * src/Makefile.in:
+ Do not pass libtool the -static-libtool-libs option when building
+ sudo and sesh. Otherwise, libtool may prefer a static version of an
+ installed library over a dynamic one when linking.
+ [6fbac9adc885]
+
+2012-04-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, NEWS, doc/CONTRIBUTORS, plugins/sudoers/po/hr.mo,
+ plugins/sudoers/po/hr.po, src/po/de.mo, src/po/de.po:
+ Add German translation for sudo Add Croatian translation for sudoers
+ [fa4da1a6530c]
+
+ * plugins/sudoers/iolog.c:
+ typo fix in comment
+ [abd721d1288e]
+
+2012-04-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Update with recent changes
+ [6fa11e8448b9]
+
+ * Makefile.in, plugins/sudoers/po/sudoers.pot, src/po/sudo.pot:
+ Sort xgettext output by file name.
+ [f650841810f0]
+
+ * doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.pod:
+ Clarify what "sudoreplay -l" displays and mention that it is sorted.
+ [84031c117bd6]
+
+ * config.h.in, configure, configure.in, src/ttyname.c:
+ Use AC_HEADER_MAJOR to determine where major/minor are defined.
+ [3c949650a223]
+
+ * config.h.in, configure, configure.in, src/ttyname.c:
+ Include sys/mkdev.h if present instead of sys/sysmacros.h for
+ minor(). This is needed on Solaris (at least) where the makedev
+ macros in sysmacros.h are obsolete and library functions should be
+ used instead.
+ [343928acf81e]
+
+ * mkpkg:
+ When building on Mac OS X, only set SDK_FLAGS if specified osversion
+ doesn't match host.
+ [d84c6efac872]
+
+2012-04-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/ttyname.c:
+ Add back buf and tty variables for _ttyname() case that were
+ inadvertantly removed.
+ [a4a820b22a44]
+
+2012-04-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [5446b12c1250]
+
+ * configure, configure.in:
+ Remove b8 from version number.
+ [5adc4dcec061]
+
+ * src/ttyname.c:
+ remove some XXX
+ [187579a5f593]
+
+ * src/ttyname.c:
+ When looking for a device match, do a breadth-first search instead
+ of depth-first. We already special case /dev/pts/ so chances are
+ good that if it is not a pseudo-tty it is in the base of /dev/. Also
+ avoid a stat(2) when possible if struct dirent has d_type.
+ [0183f8a1b278]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod,
+ src/sudo.c, src/sudo.h:
+ Pass pid, ppid, sid, pgid and tcpgid to plugin in user_info list.
+ [f0574d878491]
+
+ * src/po/eo.mo, src/po/es.mo, src/po/es.po, src/po/fi.mo,
+ src/po/ja.mo, src/po/pl.mo, src/po/ru.mo, src/po/uk.mo,
+ src/po/vi.mo:
+ sync with translationproject.org
+ [4527ea78fbd5]
+
+ * MANIFEST, NEWS, doc/CONTRIBUTORS, src/po/gl.mo, src/po/gl.po,
+ src/po/hr.mo, src/po/hr.po:
+ New Croatian and Galician translations from translationproject.org
+ [ad4bd924b4de]
+
+ * src/ttyname.c:
+ Add depth-first traversal of /dev/ for the /proc case when not
+ /dev/pts/N
+ [499bd3456774]
+
+ * config.h.in, configure, configure.in, plugins/sudoers/sudoreplay.c:
+ If struct dirent has d_type, use it to avoid an extra stat().
+ [741dabbe4bcd]
+
+ * plugins/sudoers/sudoreplay.c:
+ Sort output of "sudoreplay -l"
+ [c0615795bd4b]
+
+2012-04-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c:
+ Fix duplicate free introduced in last rev
+ [efdaabe69d75]
+
+2012-04-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/pam.c:
+ Instead of treating ^C from tgetpass() specially, always return
+ AUTH_INTR if tgetpass() returned NULL. Treat PAM_AUTHINFO_UNAVAIL
+ like PAM_AUTH_ERR which Mac OS X returns this when there is no tty.
+ [a3b17298d4d0]
+
+ * config.h.in, configure, configure.in, src/ttyname.c:
+ Rototill code to determine the tty. For Linux, we now look up the
+ tty device in /proc/pid/stat instead of trying to open
+ /proc/pid/fd/[0-2]. The sudo_ttyname_dev() function maps the given
+ device number to a string. On BSD, we can use devname(). On Solaris,
+ _ttyname_dev() does what we want. TODO: write /dev/ traversal code
+ for the generic sudo_ttyname_dev().
+ [6b22be4d09f0]
+
+2012-04-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/ttyname.c:
+ Define PRNODEV for those w/o it.
+ [f17290e64559]
+
+ * config.h.in, configure, configure.in, src/ttyname.c:
+ Check for SVR4-style struct psinfo.pr_ttydev and use that to
+ determine the tty if std{in,out,err} are not ttys.
+ [76ad33a91f4b]
+
+ * src/ttyname.c:
+ Better support for SVR4-style /proc entries where we can't use
+ ttyname() on the /proc/pid/fd/[0-2] entries. We can, however,
+ attempt to map the device number back to the correct pseudo-tty
+ slave device.
+ [4f9f48cc79eb]
+
+ * src/ttyname.c:
+ When trying to determine the tty name, check parent's stderr in
+ addition to its stdin and stdout.
+ [604644056c7d]
+
+ * src/exec_pty.c:
+ Treat a tty read failure like EOF as it usually means the pty has
+ gone away. Handle write() on the tty returning EIO.
+ [16957f4a706f]
+
+ * src/exec.c, src/exec_pty.c:
+ Linux select() may return ENOMEM if there is a kernel resource
+ shortage. Older Solaris select() may return EIO instead of EBADF
+ when the tty goes away. If we get an unhandled select() failure,
+ kill the child and exit cleanly.
+ [d93940a311ab]
+
+ * src/ttyname.c:
+ Open /proc/pid/fd/[0-2] in non-blocking mode just in case we might
+ block in open.
+ [a9f809d09d52]
+
+2012-04-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/set_perms.c:
+ Fix restoration of AIX permissions.
+ [30c717115988]
+
+ * src/parse_args.c:
+ Allow the -k flag to be used along with the -i and -s flags.
+ [0653b17c97f1]
+
+ * plugins/sudoers/sudoreplay.c:
+ Plug memory leak in parse_logfile() in the error path.
+ [9cce86fa833b]
+
+ * plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ src/po/da.mo, src/po/da.po, src/po/eo.po, src/po/es.po,
+ src/po/fi.po, src/po/it.mo, src/po/it.po, src/po/ja.po,
+ src/po/pl.po, src/po/ru.po, src/po/uk.po, src/po/vi.po,
+ src/po/zh_CN.mo, src/po/zh_CN.po:
+ sync with translationproject.org
+ [14af43d0b170]
+
+2012-04-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/regress/glob/globtest.c, config.h.in, configure,
+ configure.in, plugins/sudoers/match.c:
+ Do not use GLOB_BRACE or GLOB_TILDE flags to glob()--we want the
+ glob() and fnmatch() results to be consistent.
+ [4226750d73c2]
+
+2012-04-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, common/Makefile.in, common/ttysize.c, src/Makefile.in,
+ src/ttysize.c:
+ Move ttysize.c to common so sudoreplay can use it.
+ [b4a0aa514cd4]
+
+ * plugins/sudoers/sudoreplay.c:
+ If I/O log file includes rows + cols, warn if the user's tty is not
+ big enough.
+ [b980ef89efff]
+
+ * plugins/sudoers/sudoreplay.c:
+ Fix printing of TSID in "sudoreplay -l"
+ [4221e3e108b4]
+
+ * common/sudo_debug.c, include/sudo_debug.h,
+ plugins/sudoers/logging.c, plugins/sudoers/visudo.c, src/exec.c,
+ src/exec_pty.c:
+ Log the process id in the debug file output. Since we don't want to
+ keep calling getpid(), stash the value at init time and when we
+ fork().
+ [2782d30c024d]
+
+ * src/exec_pty.c:
+ Ignore SIGTTIN and SIGTTOU in main sudo process when I/O logging. It
+ is better to receive EIO from read()/write() than to be suspended
+ when we don't expect it. Fixes a problem when our terminal is
+ revoked which can happen when, e.g. our sshd is killed
+ unceremoniously. Also, only change the value of "alive" from true to
+ false, never from false to true. It is possible for us to receive
+ notification of the child having stopped after it is already dead.
+ This does not mean it has risen from the grave.
+ [26c9fe8ce0f9]
+
+ * src/exec_pty.c:
+ Distinguish between signals we received from the parent vs. those
+ delivered explicitly to the monitor process in debugging info.
+ [40716cb180e5]
+
+2012-04-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c:
+ In Solaris 11, /dev/pts under the "dev" filesystem, not "devices".
+ Update tty_is_devpts() to match so we can determine when the tty has
+ been reused.
+ [2689665df027]
+
+ * common/sudo_debug.c, include/error.h, include/sudo_debug.h:
+ Always pass __func__, __FILE__ and __LINE__ in sudo_debug_printf()
+ and use a new flag, SUDO_DEBUG_FILENO to specify when to use it.
+ This allows consumers of sudo_debug_printf() to log that data
+ without having to specify it manually.
+ [7c94c4879208]
+
+ * src/exec_pty.c:
+ Make this compile after last change.
+ [ee09034f3266]
+
+ * src/exec_pty.c:
+ Don't try to restore the terminal if we are not the foreground
+ process. Otherwise, we may be stopped by SIGTTOU when we try to
+ update the terminal settings when cleaning up.
+ [c48b24335456]
+
+ * src/exec.c:
+ If select() return EBADF in the main event loop, one of the ttys
+ must have gone away so perform any I/O we can and close the bad fds.
+ [3bc8678c03ce]
+
+ * common/sudo_debug.c, include/error.h, include/sudo_debug.h,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.h,
+ plugins/sudoers/toke.l:
+ Log warning() at SUDO_DEBUG_WARN not SUDO_DEBUG_ERROR. Log the
+ function, file and line number in the debug log for warning() and
+ error().
+ [894cd131f11d]
+
+2012-04-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/sudo_debug.c, include/error.h, include/sudo_debug.h,
+ src/conversation.c:
+ Add SUDO_DEBUG_ERRNO flag to debug functions so we can log errno.
+ Use this flag when wrapping error() and warning() so the debug
+ output includes the error string.
+ [1e2c67adaf1f]
+
+2012-03-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Update for sudo 1.8.5
+ [7d2b62b823fe]
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen
+ [718ad9de92cd]
+
+ * doc/CONTRIBUTORS:
+ sync
+ [f48013aea641]
+
+ * plugins/sudoers/pwutil.c:
+ Use ecalloc()
+ [fabd23c1f271]
+
+ * src/exec_pty.c:
+ Don't need zero_bytes() after ecalloc()
+ [1a9d95cd10ef]
+
+ * config.h.in, configure, configure.in, src/sudo_noexec.c:
+ Add execvpe(), exect(), posix_spawn() and posix_spawnp() wrappers to
+ sudo_noexec.c.
+ [cbaa1d4b0f8a]
+
+ * src/utmp.c:
+ Fix compat setutxent and endutxent macros for systems with
+ setutent() but not setutxent(). From Gustavo Zacarias
+ [d7ce622fc5f2]
+
+2012-03-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ Add ignore_result definition to AH_BOTTOM
+ [8d4096838a98]
+
+ * common/sudo_debug.c, config.h.in, plugins/sample/sample_plugin.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/visudo.c, src/env_hooks.c,
+ src/exec.c, src/exec_pty.c, src/tgetpass.c:
+ Fix compiler warnings on some platforms and provide a better method
+ of defeating gcc's warn_unused_result attribute.
+ [9a8f804fcc75]
+
+ * configure, configure.in:
+ Fix building the builtin zlib from a build dir. When a zlib dir was
+ specified, prepend its include path instead of appending so we get
+ the right zlib headers.
+ [5f61d591b186]
+
+ * doc/LICENSE, zlib/adler32.c, zlib/crc32.c, zlib/crc32.h,
+ zlib/deflate.c, zlib/deflate.h, zlib/gzguts.h, zlib/gzlib.c,
+ zlib/gzread.c, zlib/gzwrite.c, zlib/infback.c, zlib/inffixed.h,
+ zlib/inflate.c, zlib/inftrees.c, zlib/trees.c, zlib/zconf.h.in,
+ zlib/zlib.h, zlib/zutil.c, zlib/zutil.h:
+ Update zlib to version 1.2.6
+ [173c4bc4d4fc]
+
+2012-03-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/missing.h:
+ g/c __unused which is no longer used
+ [7ef3f23edcd6]
+
+ * src/env_hooks.c:
+ Fix compilation if RTLD_NEXT is not defined.
+ [d5605f468b71]
+
+ * src/po/sr.mo, src/po/sr.po:
+ sync with translationproject.org
+ [27d559f7985d]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudoers.cat,
+ doc/sudoers.man.in:
+ regen
+ [f9f63ce478b6]
+
+ * plugins/sudoers/po/sudoers.pot, src/po/sudo.pot:
+ regen
+ [59035d82d15a]
+
+ * Makefile.in:
+ Ignore Project-Id-Version when comparing pot files.
+ [22feb9ede46b]
+
+ * plugins/sudoers/bsm_audit.c:
+ Use error() instead of log_fatal()
+ [54130bda4b50]
+
+ * plugins/sudoers/env.c:
+ Fix signedness of didvar in env_update_didvar()
+ [77048a80b3e4]
+
+ * plugins/sudoers/iolog.c:
+ Quiet a compiler warning on some platforms.
+ [8fdcaece0400]
+
+ * compat/fnmatch.c:
+ cast ctype(3) function/macro arguments from char to unsigned char to
+ avoid potential negative subscripting.
+ [bdcf7eef21ef]
+
+ * common/setgroups.c:
+ Quiet a warning on systems where the gids array in setgroups() is
+ not prototyped as being const, even though it really is.
+ [fdd758c6302d]
+
+ * src/env_hooks.c:
+ Quiet a compiler warning on systems where the argument to putenv(3)
+ is const.
+ [51bae2193b53]
+
+ * plugins/sudoers/sudoreplay.c:
+ Undo an incorrect int -> bool conversion.
+ [b9a4ce320f14]
+
+ * MANIFEST, NEWS, plugins/sudoers/po/sv.mo, plugins/sudoers/po/sv.po,
+ src/po/sv.mo, src/po/sv.po:
+ Add Swedish sudo and sudoers translations from
+ translationproject.org
+ [f7ce1de9073f]
+
+ * plugins/sudoers/env.c:
+ No need to preserve ODMDIR on AIX now that we always read
+ /etc/environment.
+ [4aa04b2f0125]
+
+2012-03-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.pod, plugins/sudoers/env.c:
+ When initializing the environment for env_reset, start out with the
+ contents of /etc/environment on AIX and login.conf on BSD.
+ [5717bdc321e2]
+
+ * doc/TROUBLESHOOTING, src/sudo.c:
+ If we are not running with an effective uid of 0, try to give the
+ user enough information to debug the problem.
+ [fa4894896d8a]
+
+ * plugins/sudoers/getdate.c, plugins/sudoers/gram.c:
+ Quiet a clang-analyzer false positive.
+ [c4c0c1b9c8b0]
+
+ * src/tgetpass.c:
+ If there is nothing to read from the askpass program, set errno to
+ EINTR. This makes the cancel button behave like the user entered ^C
+ at the password prompt when PAM is used.
+ [594302cb9caf]
+
+ * src/sudo.h, src/tgetpass.c:
+ Fetch the value of "askpass" from the sudo conf struct.
+ [4593ee8f1bd3]
+
+ * common/sudo_conf.c:
+ Fix matching of "Path askpass" and "Path noexec"
+ [4df28d62afb9]
+
+2012-03-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo.c:
+ Quiet a clang-analyzer dead store warning.
+ [dd90bf385a3f]
+
+ * plugins/sudoers/sudoers.c:
+ If the "timestampowner" user cannot be resolved, use ROOT_UID
+ instead of exiting with a fatal error.
+ [8d62aae99715]
+
+ * plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/bsm_audit.c,
+ plugins/sudoers/check.c, plugins/sudoers/env.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h, plugins/sudoers/parse.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c:
+ Remove the NO_EXIT flag to log_error() and add a log_fatal()
+ function that exits and is marked no_return. Fixes false positives
+ from static analyzers and is easier for humans to read too.
+ [a0fe785c2a3d]
+
+2012-03-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po, src/po/eo.mo,
+ src/po/eo.po:
+ sync with translationproject.org
+ [df5e8777de13]
+
+2012-03-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/po/da.mo, src/po/da.po:
+ sync with translationproject.org
+ [629d99548b78]
+
+ * plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po:
+ sync with translationproject.org
+ [9d122a2860d6]
+
+2012-03-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/po/it.mo, src/po/it.po:
+ sync with translationproject.org
+ [6397593b15cf]
+
+ * common/sudo_conf.c, plugins/sudoers/alias.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/env.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/interfaces.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/visudo.c, src/exec.c, src/exec_pty.c, src/hooks.c,
+ src/load_plugins.c:
+ Use ecalloc() when allocating structs.
+ [8b5888868db2]
+
+ * common/alloc.c, include/alloc.h:
+ Add ecalloc() and commented out recalloc(). Use inline strnlen()
+ instead of strlen() in estrndup().
+ [7fb9aa46c1e0]
+
+2012-03-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ src/po/fi.mo, src/po/fi.po, src/po/ja.mo, src/po/ja.po,
+ src/po/pl.mo, src/po/pl.po, src/po/ru.mo, src/po/ru.po,
+ src/po/uk.mo, src/po/uk.po, src/po/vi.mo, src/po/vi.po,
+ src/po/zh_CN.mo, src/po/zh_CN.po:
+ sync with translationproject.org
+ [45a032c37334]
+
+2012-03-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/set_perms.c:
+ Remove unused label
+ [2660bb0c1313]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod:
+ Document what changed in each plugin API revision
+ [59b30a6fc4d1]
+
+ * plugins/sudoers/set_perms.c:
+ Remove bogus optimization that could lead to a double free of the
+ group list.
+ [b0bfbd2a83a8]
+
+2012-03-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/TROUBLESHOOTING:
+ Expand AIX /etc/security/privcmds entry.
+ [9f3f072e034e]
+
+ * NEWS:
+ Update for sudo 1.8.5
+ [086049011f25]
+
+ * common/sudo_conf.c, doc/sample.sudo.conf, doc/sudo.cat,
+ doc/sudo.man.in, doc/sudo.pod, doc/sudo_plugin.cat,
+ doc/sudo_plugin.man.in, doc/sudo_plugin.pod, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.pod, include/sudo_conf.h,
+ include/sudo_plugin.h, src/load_plugins.c, src/sudo.c,
+ src/sudo_plugin_int.h:
+ Rename plugin "args" to "options"
+ [f25624951bd2]
+
+ * doc/CONTRIBUTORS:
+ Add Lithuanian and Vietnamese translators
+ [2b4c075b69e3]
+
+ * Makefile.in:
+ Ignore comments when comparing new and old pot files.
+ [f872999347b3]
+
+ * src/Makefile.in:
+ regen
+ [c8193b1b11c7]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in:
+ regen
+ [15e3c17e8a3a]
+
+ * doc/sudo_plugin.pod, include/sudo_plugin.h,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h, plugins/sudoers/env.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h, src/hooks.c,
+ src/sudo.c, src/sudo.h:
+ Pass a pointer to user_env in to the init_session policy plugin
+ function so session setup can modify the user environment as needed.
+ For PAM authentication, merge the PAM environment with the user
+ environment at init_session time. We no longer need to swap in the
+ user_env for environ during session init, nor do we need to disable
+ the env hooks at init_session time.
+ [3f5277b359d8]
+
+ * plugins/sample/sample_plugin.c:
+ Add explicit NULL entries for init_session, register_hooks and
+ deregister_hooks with appropriate comments.
+ [727a57978b40]
+
+ * compat/pw_dup.c:
+ Quiet a gcc "used uninitialized in this function" false positive.
+ [f14b68379ce9]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ We should always call warning() with a format string or a string
+ literal. In this case, the argument (path) is not user-controlled.
+ [e9ef51224024]
+
+2012-03-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/selinux.c:
+ Include sudo_exec.h for the sudo_execve() prototype.
+ [769e58065edc]
+
+ * config.h.in, configure, configure.in:
+ Add check for pam_getenvlist()
+ [36bde3f26c60]
+
+ * common/sudo_conf.c:
+ Set args to NULL in default plugin info struct when there is no
+ Plugin line in sudo.conf.
+ [93ec67708f01]
+
+ * plugins/sudoers/po/sudoers.pot, src/po/sudo.pot:
+ regen
+ [a9287677795c]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo_plugin.cat,
+ doc/sudo_plugin.man.in, doc/sudoers.cat, doc/sudoers.ldap.cat,
+ doc/sudoers.ldap.man.in, doc/sudoers.man.in, doc/sudoreplay.cat,
+ doc/sudoreplay.man.in, doc/visudo.cat, doc/visudo.man.in:
+ regen
+ [a242769d7962]
+
+ * configure, configure.in:
+ Bump version to 1.8.5
+ [e8618f0c2505]
+
+ * doc/sudo_plugin.pod:
+ Document hooks API
+ [e6ad07d27958]
+
+2012-03-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Make sudoersdir relative to PKG_INSTALL_ROOT for Solaris.
+ [fd72340042d3]
+
+ * include/sudo_plugin.h:
+ Use sudo_hook_fn_t in struct sudo_hook.
+ [938f93112d6e]
+
+ * doc/TROUBLESHOOTING:
+ If cross compiling, --host must include the OS in the tuple. E.g.
+ --host powerpc-unknown-linux
+ [b8c010070c1e]
+
+2012-03-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/parse.c:
+ Fix bogus int -> bool conversion; tags can have a value of -1.
+ [e63d6434a303]
+
+ * plugins/sudoers/env.c:
+ Add env_should_keep() and env_should_delete() wrapper functions to
+ simplify things a bit and hide the fact that matches_env_check() is
+ not bool.
+ [7a03d7a12b50]
+
+ * sudo.pp:
+ Fix application of debian-specific sudoers mods when building
+ packages as non-root.
+ [34bf4c52c425]
+
+ * plugins/sudoers/env.c:
+ matches_env_check() returns int, not boolean
+ [0ad915b8d5cb]
+
+ * src/sudo_edit.c:
+ Fix compilation when seteuid() is not available.
+ [8a722f998000]
+
+ * src/ttyname.c:
+ Simply move the free of ki_proc outside the realloc() loop.
+ [217b786da760]
+
+ * src/ttyname.c:
+ Bring back the erealloc() for the ENOMEM loop and just zero the
+ pointer after we free it.
+ [29a016e45127]
+
+ * src/ttyname.c:
+ Don't try to erealloc() a potentially freed pointer; Mateusz Guzik
+ [266e08844065]
+
+2012-03-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/set_perms.c:
+ Use normal error path if unable to set sudoers gid.
+ [01c816918c99]
+
+ * plugins/sudoers/set_perms.c:
+ Make this work again on systems w/o seteuid().
+ [2e67f7421e97]
+
+2012-03-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/set_perms.c:
+ Fix compilation if no seteuid/setreuid/setresuid available.
+ [d0b3c1f88eb4]
+
+ * plugins/sudoers/set_perms.c:
+ Better error messages, and added debugging throughout. Fixed
+ seteuid() version of set_perms()/restore_perms(). Fixed logic bug in
+ AIX version of restore_perms(). Added checks to avoid changing
+ uid/gid when we don't have to. Never set gid/uid state to -1, use
+ the old value instead.
+ [29188d469b5c]
+
+ * src/exec_pty.c, src/ttyname.c:
+ Fix format string warning on Solaris with gcc 3.4.3.
+ [d1eeb6e1dd0f]
+
+ * src/sudo.c:
+ Always declare environ now that we swap it around unilaterally.
+ [aaa3e92e7d0d]
+
+ * src/Makefile.in:
+ Honor LDFLAGS when linking sesh; from Vita Cizek
+ [498b41438f6e]
+
+ * src/sesh.c:
+ Include alloc.h for estrdup() prototype; from Vita Cizek
+ [93203655a320]
+
+2012-03-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ Don't read /etc/environment on Linux when using PAM, PAM should set
+ the environment variables as needed via pam_env.
+ [b1ef62cb2d40]
+
+ * INSTALL:
+ Fix editor goof.
+ [0c3dd3bb8b57]
+
+ * src/hooks.c, src/sudo.c, src/sudo.h:
+ Disable environment hooks after we get user_env back to make sure a
+ plugin can't to modify user_env after we "own" it. This is kind of a
+ hack but we don't want the init_session plugin function to modify
+ user_env.
+ [8e6d119452a5]
+
+ * src/hooks.c, src/sudo.c:
+ Add support for deregistering hooks. If an I/O log plugin fails to
+ initialize, deregister its hooks (if any).
+ [ac00c93900c5]
+
+2012-03-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c, src/sudo.c:
+ Move LOGIN_PATH and LOGIN_SETENV handling to plugin now that we hook
+ setenv.
+ [e75469dd9908]
+
+ * MANIFEST, aclocal.m4, common/sudo_debug.c, compat/Makefile.in,
+ compat/setenv.c, compat/unsetenv.c, config.h.in, configure,
+ configure.in, include/sudo_debug.h, include/sudo_plugin.h, mkdep.pl,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/env.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, src/Makefile.in, src/env_hooks.c,
+ src/hooks.c, src/load_plugins.c, src/sudo.c, src/sudo.h,
+ src/sudo_plugin_int.h:
+ Initial cut at a hooks implementation. The plugin can register hooks
+ for getenv, putenv, setenv and unsetenv. This makes it possible for
+ the plugin to trap changes to the environment made by authentication
+ methods such as PAM or BSD auth so that such changes are reflected
+ in the environment passed back to sudo for execve().
+ [61cffa06f863]
+
+2012-03-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, src/po/vi.mo, src/po/vi.po:
+ Add Vietnamese sudo translation from translationproject.org
+ [96df426790d5]
+
+2012-03-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sample.sudo.conf, doc/sudo.pod, doc/sudo_plugin.pod,
+ doc/sudoers.pod:
+ List sudo_noexec.so not noexec.so in the sample sudo.conf
+ [53844e190ec5]
+
+ * common/sudo_conf.c, doc/sample.sudo.conf, doc/sudo.pod,
+ doc/sudo_plugin.pod, doc/sudoers.pod, include/sudo_conf.h,
+ include/sudo_plugin.h, plugins/sample/sample_plugin.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/toke.l, src/load_plugins.c, src/sudo.c,
+ src/sudo_plugin_int.h:
+ Add support for plugin args at the end of a Plugin line in
+ sudo.conf. Bump the minor number accordingly and update the
+ documentation. A plugin must check the sudo front end's version
+ before using the plugin_args parameter since it is only supported
+ for API version 1.2 and higher.
+ [587f1f819536]
+
+2012-03-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ update depends
+ [6d2da44e11e5]
+
+ * MANIFEST:
+ secure_path.c is in common, not compat
+ [619c4a663dde]
+
+ * configure, configure.in:
+ Add check for variadic macro support in cpp.
+ [756854caf675]
+
+2012-02-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/secure_path.c, common/sudo_conf.c, include/secure_path.h,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Add type param to sudo_secure_path() and add sudo_secure_file() and
+ sudo_secure_dir() wrappers which get by #includedir in sudoers.
+ [2ec2d3d8df04]
+
+2012-02-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/visudo.pod, plugins/sudoers/visudo.c:
+ Check the owner and mode in -c (check) mode unless the -f option is
+ specified. Previously, the owner and mode were checked on the main
+ sudoers file when the -s (strict) option was given, but this was not
+ documented.
+ [b2d6ee1e547a]
+
+ * config.h.in, configure, configure.in, src/ttyname.c:
+ Prefer KERN_PROC2 over KERN_PROC. Fixes compilation on some versions
+ of OpenBSD versions that have KERN_PROC2 but not KERN_PROC.
+ [159f6a50456a]
+
+2012-02-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS:
+ Add Eric Lakin for patch in bug #538
+ [490c29c234c6]
+
+ * src/exec_pty.c:
+ Fix typo in safe_close() made while converting to debug framework
+ that prevented it from actually closing anything.
+ [a66422a62afd]
+
+ * src/exec_pty.c:
+ Add some more debugging.
+ [b5667947dda9]
+
+ * common/Makefile.in, compat/Makefile.in, doc/Makefile.in,
+ include/Makefile.in:
+ We need sysconfdir in compat/Makfile to get the proper sudo.conf
+ path. Add standard prefix and foodir expansion in all Makefiles to
+ avoid this problem in the future.
+ [62b6ce4ecae9]
+
+2012-02-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/po/lt.mo, plugins/sudoers/po/lt.po:
+ New Lithuanian sudoers translation from translationproject.org
+ [10436b649035]
+
+ * plugins/sudoers/po/ja.po:
+ Update from translationproject.org
+ [acb8db5f8ef1]
+
+2012-02-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ When adding gids to the LDAP filter, only add the primary gid once.
+ This is consistent with the space computation/allocation. From Eric
+ Lakin
+ [35d9d99c92c6]
+
+ * doc/TROUBLESHOOTING:
+ Add entry for AIX enhanced RBAC config.
+ [5e10b6f8def7]
+
+ * mkpkg:
+ Target Mac OS X 10.5 when building packages.
+ [06fce9bbebee]
+
+2012-02-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, common/Makefile.in, common/secure_path.c,
+ common/sudo_conf.c, include/secure_path.h,
+ plugins/sudoers/Makefile.in, plugins/sudoers/sudoers.c:
+ Relax the user/group/mode checks on sudoers files. As long as the
+ file is owned by the right user, not world-writable and not writable
+ by a group other than the one specified at configure time (gid 0 by
+ default), the file is considered OK. Note that visudo will still set
+ the mode to the value specified at configure time.
+ [241174babfcc]
+
+2012-02-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/set_perms.c:
+ Add AIX-specific version of permission setting code to make sure
+ that the saved uid gets restored properly.
+ [9a6f5d22c301]
+
+ * config.h.in, configure, configure.in, src/exec_common.c:
+ Check for LD_PRELOAD variants in configure instead of checkign cpp
+ symbols. In disable_execute(), compute the length of the new envp
+ and allocate it once instead of reallocating on demand. Also append
+ old value of LD_PRELOAD (if any) to the new value.
+ [680266346917]
+
+ * plugins/sudoers/def_data.c, plugins/sudoers/def_data.in:
+ Fix the description of noexec.
+ [6a6d142f3c80]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h:
+ The "op" parameter to set_default() must be int, not bool since it
+ is set to '+' or '-' for list add and subtract.
+ [8da5b137bea2]
+
+ * sudo.pp:
+ Make sure sudoers is writable before calling ed script.
+ [95352ab6336b]
+
+2012-02-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS, doc/contributors.pod:
+ Update contributors. Now includes translators and authors of compat
+ code.
+ [4fb5b616b50a]
+
+2012-02-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/po/sudo.pot:
+ regen
+ [2c86e2c328fe]
+
+ * pp, sudo.pp:
+ Build flat packages, not package bundles, on Mac OS X.
+ [57bda3cd5520]
+
+2012-02-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Move macos section to be with the other OS-specific sections.
+ [51423bb2973a]
+
+ * plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po:
+ Sync with translationproject.org
+ [8ce41cbb8da0]
+
+ * configure, configure.in:
+ Don't permanently add -D_FORTIFY_SOURCE=2 to CPPFLAGS
+ [fa979aa6fe7d]
+
+ * sudo.pp:
+ Add Mac OS X support, printing the latest chunk of the NEWS file and
+ the license text in the installer.
+ [ffeab72387c0]
+
+ * sudo.pp:
+ Add explicit file modes that match those used by "make install"
+ [7eb37242c920]
+
+ * pp:
+ Sync with upstream for Mac OS X fixes.
+ [97cba179041e]
+
+ * plugins/sudoers/Makefile.in, src/Makefile.in:
+ Got back to using "install-sh -M" for files installed as non-
+ readable by owner. This fixes "make install" as non-root for package
+ building.
+ [967804ee77d6]
+
+2012-02-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po,
+ plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po:
+ Sync with translationproject.org
+ [0e53db12039a]
+
+ * Makefile.in, doc/Makefile.in, include/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sample_group/Makefile.in,
+ plugins/sudoers/Makefile.in, src/Makefile.in:
+ Use -m not -M for install-sh for everything except setuid. Install
+ locale .mo files mode 0444, not 0644. If timedir parent doesn't
+ exist, use default dir mode, not 0700.
+ [8b6f64c92090]
+
+2012-02-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pp:
+ Re-sync with upstream; no longer need a local patch.
+ [97a2c7be5e59]
+
+ * mkpkg:
+ Add support for building Mac OS X packages.
+ [94d49ac223a4]
+
+ * pp:
+ Sync with upstream
+ [1c97654fc841]
+
+ * src/Makefile.in:
+ No longer need to define _PATH_SUDO_CONF here.
+ [2560905b7482]
+
+ * src/exec_common.c:
+ Fix noexec for Mac OS X.
+ [b7a744bca2c0]
+
+2012-02-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/Makefile.in:
+ Move _PATH_SUDO_CONF override to common to match sudo_debug.c
+ [f0788972a63a]
+
+ * plugins/sudoers/set_perms.c:
+ More complete fix for LDR_PRELOAD on AIX. The addition of
+ set_perm(PERM_ROOT) before calling the nss open functions (needed to
+ avoid a GNU TLS bug) also broke LDR_PRELOAD. Setting the effective
+ and then real uid to 0 for PERM_ROOT works around the issue.
+ [5888eda051af]
+
+ * plugins/sudoers/po/sudoers.pot, src/po/sudo.pot:
+ regen
+ [997fe403e219]
+
+ * src/sudo.c:
+ Set real uid to root before calling sudo_edit() or run_command() so
+ that the monitor process is owned by root and not by the user.
+ Otherwise, on AIX at least, the monitor process shows up in ps as
+ belonging to the user (and can be killed by the user).
+ [d4772d7d2fc5]
+
+ * plugins/sudoers/set_perms.c:
+ For PERM_ROOT when using setreuid(), only set the euid to 0 prior to
+ the call to setuid(0) if the current euid is non-zero. This
+ effectively restores the state of things prior to rev 7bfeb629fccb.
+ Fixes a problem on AIX where LDR_PRELOAD was not being honored for
+ the command being executed.
+ [b9b40325b4dc]
+
+ * MANIFEST, compat/pw_dup.c, config.h.in, configure, configure.in,
+ include/missing.h, src/sudo.c:
+ Make a copy of the struct passwd in exec_setup() to make sure
+ nothing in the policy init modifies it.
+ [b721261c921f]
+
+2012-02-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.pod:
+ update copyright
+ [f9d229d1f65e]
+
+ * common/sudo_debug.c, include/sudo_debug.h:
+ g/c now-unused debug subsystems
+ [8f21726e698f]
+
+ * doc/sudo.pod, doc/sudoers.pod:
+ Enumerate the debug subsystems used by sudo and sudoers.
+ [ac4f84293d14]
+
+2012-02-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, common/sudo_conf.c, doc/sample.sudo.conf, doc/sudo.pod,
+ include/sudo_conf.h, src/sudo.c:
+ Normally, sudo disables core dumps while it is running. This
+ behavior can now be modified at run time with a line in sudo.conf
+ like "Set disable_coredumps false"
+ [ad14e0508b0d]
+
+ * NEWS:
+ Mention Spanish translation
+ [600f3205bd6e]
+
+ * common/sudo_debug.c:
+ Make sure we don't try to fall back to using the conversation
+ function for debugging in the main sudo process if we are unable to
+ open the debug file.
+ [ffa329aa908c]
+
+ * MANIFEST, src/po/es.mo, src/po/es.po:
+ Add sudo Spanish translation from translationproject.org
+ [c1906654e740]
+
+2012-02-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ Better debug subsystem usage
+ [1a31f115743c]
+
+ * src/sudo.c:
+ Remove duplicate function prototypes
+ [ae04b00532eb]
+
+2012-02-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Error out if user specified --with-pam but we can't find the headers
+ or library. Also throw an error if the headers are present but the
+ library is not and vice versa.
+ [d6bf3e3d0aae]
+
+2012-01-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ Fix the sudoers permission check when the expected sudoers mode is
+ owner-writable.
+ [8b0b7e770a22]
+
+2012-01-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Verify that we can link executables built with -D_FORTIFY_SOURCE
+ before using it.
+ [7578215d1a95]
+
+ * src/exec_common.c:
+ Fix potential off-by-one when making a copy of the environment for
+ LD_PRELOAD insertion. Fixes bug #534
+ [cc699cd551b6]
+
+ * configure, configure.in:
+ Add rudimentary check for _FORTIFY_SOURCE support by checking for
+ __sprintf_chk, one of the functions used by gcc to support it.
+ [a992673d2ef8]
+
+ * compat/stdbool.h, config.h.in, configure, configure.in:
+ Use AC_HEADER_STDBOOL instead of checking for stdbool.h ourselves.
+ [8ba1370884b3]
+
+2012-01-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot, src/po/sudo.pot:
+ regen
+ [1e0b38397705]
+
+2012-01-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c, src/sudo.c:
+ The change in 818e82ecbbfc that caused to exit when the monitor dies
+ created a race condition between the monitor exiting and the status
+ being read. All we really want to do is make sure that select()
+ notifies us that there is a status change when the monitor dies
+ unexpectedly so shutdown the socketpair connected to the monitor for
+ writing when it dies. That way we can still read the status that is
+ pending on the socket and select() on Linux will tell us that the fd
+ is ready.
+ [7fb5b30ea48d]
+
+ * MANIFEST, src/Makefile.in, src/exec.c, src/exec_common.c,
+ src/exec_pty.c, src/selinux.c, src/sesh.c, src/sudo.c, src/sudo.h,
+ src/sudo_exec.h:
+ Refactor disable_execute() and my_execve() into exec_common.c for
+ use by sesh.c. This fixes NOEXEC when SELinux is used. Instead of
+ disabling exec in exec_setup(), disable it immediately before
+ executing the command. Adapted from a diff by Arno Schuring.
+ [ec4d8b53db6b]
+
+2012-01-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aclocal.m4, configure, configure.in:
+ Add custom version of AC_CHECK_LIB that uses the extra libs in the
+ cache value name. With this we no longer need to rely on a modified
+ version of autoconf.
+ [1c3b1d482d6c]
+
+2012-01-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Better handling of network functions that need -lsocket -lnsl
+ [cc386342ec2b]
+
+ * src/sudo.c:
+ When setting up the execution environment, set groups before
+ gid/egid like sudo 1.7 did.
+ [928e1c5fa6c1]
+
+ * configure, configure.in:
+ Remove "WARNING: unable to find foo() trying -lsocket -lnsl"
+ [84b23cdf138f]
+
+ * plugins/sudoers/sudoers.c:
+ For "sudo -g" prepend the specified group ID to the beginning of the
+ groups list. This matches BSD convention where the effective gid is
+ the first entry in the group list. This is required on newer FreeBSD
+ where the effective gid is not tracked separately and thus
+ setgroups() changes the egid if this convention is not followed.
+ Fixes bug #532
+ [782d6909108b]
+
+2012-01-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Fix sh warning; use "test" instead of "["
+ [c6ee3407f65e]
+
+ * src/exec.c:
+ When not logging I/O, use a signal handler that only forwards
+ SIGINT, SIGQUIT and SIGHUP when they are user-generated signals.
+ Fixes a race in the non-I/O logging path where the command may
+ receive two keyboard-generated signals; one from the kernel and one
+ from the sudo process.
+ [9638684e786a]
+
+ * src/exec.c:
+ Back out change that put the command in its own pgrp when not
+ logging I/O. It causes problems with pipelines.
+ [4fc9c6e1e770]
+
+2012-01-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/Makefile.in, configure, configure.in:
+ Only run compat regress tests on compat objects we actually build.
+ Fixes "make check" in the compat dir for systems that don't
+ implement character classes in fnmatch() or glob(). Bug #531
+ [a7addc305e83]
+
+2012-01-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po:
+ Update po files from translationproject.org
+ [5ea066af1356]
+
+2012-01-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Include parent directories in case they don't already exist. This
+ fixes a directory permissions problem with the AIX package when the
+ /usr/local directories don't already exist.
+ [a14f783dc827]
+
+ * pp:
+ sync with git version
+ [2f79d0543661]
+
+ * common/Makefile.in, plugins/sudoers/Makefile.in, src/Makefile.in:
+ regen dependencies
+ [24c92ca6c64d]
+
+ * MANIFEST, src/Makefile.in, src/sudo.c, src/sudo.h, src/ttyname.c:
+ Move tty name lookup code to its own file.
+ [58faf072cbf4]
+
+2012-01-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Update with latest sudo 1.8.4 changes.
+ [a4ffe4f42528]
+
+ * config.h.in, configure, configure.in:
+ Remove obsolete template for HAVE_TIMESPEC
+ [75709007c906]
+
+ * src/sudo.c:
+ Add a check for devname() returning a fully-qualified pathname. None
+ of the devname() implementations do this today but you never know
+ when this might change.
+ [16813ace38f9]
+
+2012-01-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo.c:
+ For "visudo -c" also list include files that were checked when
+ everything is OK.
+ [ad6f85b35c9c]
+
+ * src/sudo.c:
+ The device name returned by devname() does not include the /dev/
+ prefix so we need to add it ourselves.
+ [b55285abb7ed]
+
+ * src/sudo.c:
+ Add debug warning if KERN_PROC sysctl fails or devname() can't
+ resolve the tty device to a name.
+ [b5a23916ba3a]
+
+ * common/sudo_debug.c:
+ The result of writev() is never checked so just cast to NULL.
+ [4be4e9b58d5b]
+
+ * plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po:
+ Update Esperanto, Finnish, Polish and Ukrainian translations from
+ translationproject.org.
+ [bb91bc6ad7e9]
+
+2012-01-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, src/sudo.c:
+ Add support for determining tty via sysctl on other BSD variants.
+ [fd15f63f719a]
+
+ * configure, configure.in:
+ Only check for struct kinfo_proc.ki_tdev on systems that support
+ sysctl.
+ [109b3f07a39d]
+
+ * src/sudo.c:
+ For FreeBSD, try the KERN_PROC_PID sysctl() first, falling back on
+ ttyname() of std{in,out,err}.
+ [95969b70bd68]
+
+2012-01-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, src/sudo.c:
+ On newer FreeBSD we can get the parent's tty name via sysctl().
+ [3207290501ee]
+
+ * plugins/sudoers/testsudoers.c:
+ Include locale.h
+ [a602cd0b8c2d]
+
+ * src/sudo.c:
+ Silence a gcc warning.
+ [8c6d0e3cd534]
+
+ * plugins/sudoers/bsm_audit.c:
+ Need to include gettext.h and sudo_debug.h; from John Hein
+ [447912aa7300]
+
+ * plugins/sudoers/iolog.c:
+ Initialize the debug framework from the I/O plugin too.
+ [ce1bf44d96d2]
+
+2012-01-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/testsudoers.c:
+ Enable debugging via sudo.conf.
+ [d85669c749d0]
+
+2012-01-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo.c:
+ Use SUDO_DEBUG_ALIAS for alias checking functions.
+ [fb84af30dc76]
+
+ * configure, configure.in:
+ More complete test for getaddrinfo() that doesn't rely on the
+ network libraries already being added to LIBS.
+ [cbaf2369f4f0]
+
+2012-01-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/aix.c:
+ Add debug support.
+ [def1bdf24485]
+
+ * configure, configure.in:
+ Need -lsocket -lnsl for getaddrinfo(3) on Solaris at least.
+ [a2ea1c2eac61]
+
+ * compat/getaddrinfo.c:
+ Include errno.h and missing.h
+ [7d15e17cc2f2]
+
+ * .hgignore:
+ ignore doc/varsub
+ [417f9fc3231b]
+
+ * configure.in, doc/visudo.pod, plugins/sudoers/Makefile.in,
+ plugins/sudoers/gram.y, plugins/sudoers/match.c,
+ plugins/sudoers/parse.c, plugins/sudoers/testsudoers.c, src/exec.c,
+ src/parse_args.c, src/sudo.c, src/sudo.h:
+ Update copyright year.
+ [5d0ffc7dd567]
+
+ * NEWS:
+ Update for sudo 1.8.4
+ [841e3eff9844]
+
+ * plugins/sudoers/po/sudoers.pot, src/po/sudo.pot:
+ regen pot files
+ [c509cb45b66a]
+
+ * plugins/sudoers/sudoreplay.c:
+ Enable debugging via sudo.conf.
+ [5087aaee8484]
+
+ * plugins/sudoers/visudo.c:
+ Enable debugging via sudo.conf.
+ [04b067c16ed3]
+
+ * plugins/sudoers/visudo.c:
+ Allow "visudo -c" to work when we only have read-only access to the
+ sudoers include files.
+ [d8c6713fe5c1]
+
+ * doc/sudo.pod, doc/visudo.pod:
+ Mention the CONTRIBUTORS file, not HISTORY in AUTHOR section. Add
+ HISTORY section in sudo that points to HISTORY file.
+ [d1f1bcb051c5]
+
+ * doc/sudo.pod, doc/sudo_plugin.pod:
+ Document Debug setting in sudo.conf and debug_flags in plugin.
+ [acfc505aa4a9]
+
+2012-01-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/match.c:
+ Do not include GLOB_MARK in the flags we pass to glob(3). Fixes a
+ bug where a pattern like "/usr/*" include /usr/bin/ in the results,
+ which would be incorrectly be interpreted as if the sudoers file had
+ specified a directory. From Vitezslav Cizek.
+ [0cdb6252188c]
+
+ * INSTALL, config.h.in, configure, configure.in,
+ plugins/sudoers/auth/kerb5.c:
+ Add --enable-kerb5-instance configure option to allow people using
+ Kerberos V authentication to use a custom instance. Adapted from a
+ diff by Michael E Burr.
+ [e83af8bb7aa7]
+
+ * doc/sudo.pod, src/parse_args.c, src/sudo.c, src/sudo.h:
+ Remove -D debug_level option.
+ [cbcd05094347]
+
+ * doc/LICENSE:
+ Update copyright year.
+ [9f43dd7aa852]
+
+2012-01-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/parse.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c:
+ parse_error is now bool, not int
+ [5ea7fb6fda38]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.c:
+ Print a more sensible error if yyparse() returns non-zero but
+ yyerror() was not called.
+ [d44ec88f1183]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/getdate.c,
+ plugins/sudoers/gram.c:
+ Replace y.tab.c with the correct filename in #line directives.
+ [3c84fcb7e959]
+
+2012-01-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo.c:
+ When trying to determine the tty, fall back on /proc/ppid/fd/{0,1,2}
+ if the main process's fds 0-2 are not hooked up to a tty. Adapted
+ from a diff by Zdenek Behan.
+ [b9dfce12af85]
+
+ * src/exec.c:
+ When not logging I/O, put command in its own pgrp and make that the
+ controlling pgrp if the command is in the foreground. Fixes a race
+ in the non-I/O logging path where the command may receive two
+ keyboard-generated signals; one from the kernel and one from the
+ sudo process.
+ [d0e263ce496c]
+
+2011-12-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo_edit.c:
+ Quiet a bogus gcc warning.
+ [2009669e0608]
+
+ * src/parse_args.c, src/sudo.h:
+ Fix warnings related to sudo.conf accessors.
+ [08ddc29ba50b]
+
+ * common/sudo_conf.c, include/sudo_conf.h:
+ Separate sudo.conf parsing from plugin loading and move the parse
+ functions into the common lib so that visudo, etc. can use them.
+ [f1fc659a8079]
+
+ * MANIFEST, common/Makefile.in, src/Makefile.in, src/load_plugins.c,
+ src/parse_args.c, src/sudo.c, src/sudo_plugin_int.h:
+ Separate sudo.conf parsing from plugin loading and move the parse
+ functions into the common lib so that visudo, etc. can use them.
+ [e1f2cf6bd57a]
+
+ * doc/sudoers.pod, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/sudoers.c, src/sudo.c:
+ Remove support for noexec_file in sudoers and the plugin API
+ [3e2fd58879b5]
+
+ * plugins/sudoers/sudoers.c:
+ Don't dump interfaces if there are none.
+ [9081bb4d3e9e]
+
+ * plugins/sudoers/def_data.c, plugins/sudoers/def_data.in:
+ Add missing %s printf escape to the group_plugin, iolog_dir and
+ iolog_file descriptions.
+ [7db03f2b737e]
+
+2011-12-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/def_data.c, plugins/sudoers/def_data.in, src/exec.c:
+ Fix typo in visiblepw description; from Joel Pickett
+ [2fb4b26d5c2c]
+
+2011-12-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, configure, configure.in, mkdep.pl,
+ plugins/sudoers/Makefile.in, plugins/sudoers/env.c,
+ plugins/sudoers/login_class.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, src/sudo.c:
+ When running a login shell with a login_class specified, use
+ LOGIN_SETENV instead of rolling our own login.conf setenv support
+ since FreeBSD's login.conf has more than just setenv capabilities.
+ This requires us to swap the plugin-provided envp for the global
+ environ before calling setusercontext() and then stash the resulting
+ environ pointer back into the command details, which is kind of a
+ hack.
+ [ad4f1190143b]
+
+ * plugins/sudoers/Makefile.in:
+ If srcdir is "." just use the basename of the yacc/lex file when
+ generating the C version. This matches the generated files currently
+ in the repo.
+ [0b11c3df87a8]
+
+ * doc/Makefile.in, plugins/sudoers/Makefile.in:
+ Clean up the DEVEL noise
+ [9de2afe457fd]
+
+ * src/exec.c:
+ Handle different Unix domain socket (actually socketpair) semantics
+ in BSD vs. Linux. In BSD if one end of the socketpair goes away
+ select() returns the fd as readable and the read will fail with
+ ECONNRESET. This doesn't appear to happen on Linux so if we notice
+ that the monitor process has died when I/O logging is enabled,
+ behave like the command has exited. This means we log the wait
+ status of the monitor, not the command, but there is nothing else we
+ can do at that point. This should only be an issue if SIGKILL is
+ sent to the monitor process.
+ [818e82ecbbfc]
+
+ * src/exec_pty.c:
+ Catch common signals in the monitor process so they get passed to
+ the command. Fixes a problem when the entire login session is killed
+ when ssh is disconnected or the terminal window is closed.
+ Previously, the monitor would exit and plugin's close method would
+ not be called.
+ [0e4658263138]
+
+ * INSTALL, configure, configure.in:
+ Mention how to configure pam_hpsec on HP-UX to play nicely with
+ sudo.
+ [a7294cd8ce98]
+
+2011-12-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Escape values in the search expression as per RFC 4515.
+ [c2adbc5db92b]
+
+ * doc/Makefile.in, include/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in,
+ src/Makefile.in:
+ No need for install target to depend explicitly on install-dirs, the
+ install-foo targets all depend on it.
+ [62a36ed98279]
+
+2011-12-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * .hgignore:
+ ignore src/sesh
+ [463d492f6782]
+
+ * MANIFEST, common/Makefile.in, configure, configure.in, mkdep.pl,
+ plugins/sample/Makefile.in, plugins/sample_group/Makefile.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/env.c,
+ plugins/sudoers/login_class.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, src/Makefile.in:
+ Add support for setenv entries in login.conf. We can't use
+ LOGIN_SETENV since the plugin sets up the envp the command is
+ executed with. Also regen the Makefile.in files while here. Fixes
+ bug #527
+ [088d507926e2]
+
+2011-12-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, aclocal.m4, compat/getaddrinfo.c, compat/getaddrinfo.h,
+ config.h.in, configure, configure.in, plugins/sudoers/sudoers.c,
+ src/net_ifs.c:
+ Add getaddrinfo() for those without it, written by Russ Allbery
+ [4cf9ac831222]
+
+ * doc/Makefile.in:
+ Restore PACKAGE_TARNAME, it is used in docdir
+ [9d65e893edb1]
+
+ * MANIFEST, compat/stdbool.h:
+ SunPro C Compiler also has a _Bool builtin. Also add stdbool.h to
+ the MANIFEST
+ [e67700dc5621]
+
+ * common/atobool.c, common/term.c, src/exec.c:
+ Remove duplicate return statements.
+ [48a20d5215fd]
+
+ * plugins/sudoers/auth/bsdauth.c:
+ Remove inaccurate comment
+ [e7f0265cf657]
+
+ * plugins/sudoers/auth/bsdauth.c, plugins/sudoers/sudoers.c:
+ Fetch the login class for the user we authenticate specifically when
+ using BSD authentication. That user may have a different login class
+ than what we will use to run the command. When setting the login
+ class for the command, use the target user's struct passwd, not the
+ invoking user's. Fixes bug 526
+ [21bf0af892f7]
+
+ * compat/Makefile.in, configure, configure.in, doc/Makefile.in,
+ plugins/sudoers/Makefile.in:
+ Replace @DEV@ prefix with DEVEL variable so we can do "make DEVEL=1"
+ [8ee6e0891f27]
+
+ * plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_fill.c:
+ Fix "make check" fallout from the sudo_conv changes in sudo_debug.
+ [b0aaa63c9081]
+
+ * common/fileops.c, common/sudo_debug.c, configure, configure.in,
+ include/fileops.h, plugins/sample/Makefile.in,
+ plugins/sample/sample_plugin.c, plugins/sample_group/Makefile.in,
+ plugins/sample_group/sample_group.c, plugins/sudoers/alias.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/check.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/defaults.h,
+ plugins/sudoers/env.c, plugins/sudoers/find_path.c,
+ plugins/sudoers/goodpath.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_path.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/match.c,
+ plugins/sudoers/match_addr.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h, plugins/sudoers/pwutil.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.h,
+ plugins/sudoers/toke.l, plugins/sudoers/toke_util.c,
+ plugins/sudoers/visudo.c, src/exec.c, src/exec_pty.c,
+ src/load_plugins.c, src/sudo.c, src/sudo.h, src/sudo_exec.h,
+ src/sudo_plugin_int.h, src/utmp.c:
+ Use stdbool.h instead of rolling our own TRUE/FALSE macros.
+ [dcb0bbc42fc9]
+
+2011-12-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/stdbool.h, config.h.in, configure, configure.in:
+ Add stdbool.h for systems without it.
+ [18bd9dda1dcd]
+
+ * aclocal.m4, config.h.in, configure, configure.in:
+ No longer need SUDO_CHECK_TYPE and SUDO_TYPE_* now that the default
+ includes have unistd.h in them. Add check for socklen_t for upcoming
+ getaddrinfo compat.
+ [d705465bef69]
+
+ * common/fileops.c, compat/nanosleep.c, config.h.in, configure,
+ configure.in, plugins/sudoers/interfaces.c,
+ plugins/sudoers/interfaces.h, plugins/sudoers/match_addr.c,
+ plugins/sudoers/sudoreplay.c, src/net_ifs.c:
+ Use HAVE_STRUCT_TIMESPEC and HAVE_STRUCT_IN6_ADDR instead of
+ HAVE_TIMESPEC and HAVE_IN6_ADDR respectively.
+ [fa187c9bd2be]
+
+ * src/sudo_noexec.c:
+ No longer need to include time.h here as missing.h does not use
+ time_t.
+ [fa3a089bf5b1]
+
+2011-11-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo.c:
+ Fix mode on sudoers as needed when the -f option is not specified.
+ [7a1c40b0dc03]
+
+ * MANIFEST, src/po/sr.mo, src/po/sr.po:
+ Add Serbian translation for sudo from translationproject.org
+ [9a0c25e25cba]
+
+ * common/sudo_debug.c, plugins/sudoers/sudoers.c, src/load_plugins.c,
+ src/parse_args.c:
+ No longer pass debug_file to plugin, plugins must now use
+ CONV_DEBUG_MSG
+ [810cda1abb0b]
+
+ * mkpkg:
+ Build PIE executables for newer Debian and Ubuntu
+ [1c5f25f8904a]
+
+ * common/sudo_debug.c:
+ Include time.h for ctime() prototype.
+ [10090cf3bca1]
+
+2011-11-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/sudo_debug.c, include/sudo_debug.h, src/exec.c,
+ src/exec_pty.c:
+ Do not close error pipe or debug fd via closefrom() as we need them
+ to report an exec error should one occur.
+ [732f6587fafa]
+
+ * doc/sudoers.ldap.pod:
+ Document that a sudoUser may now be a group ID.
+ [2fef46b9d3d3]
+
+ * plugins/sudoers/ldap.c:
+ Add support for permitting access by group ID in addition to group
+ name.
+ [b9450fdf1f69]
+
+ * plugins/sudoers/ldap.c:
+ Older Netscape LDAP SDKs don't prototype ldapssl_set_strength()
+ [d62a1e7cff4f]
+
+ * compat/fnmatch.c, compat/fnmatch.h, doc/LICENSE:
+ Replace UCB fnmatch.c with a non-recursive version written by
+ William A. Rowe Jr.
+ [354d3384adb8]
+
+ * plugins/sudoers/auth/pam.c:
+ Fix typo, return_debug vs. debug_return
+ [1b522efcbb0d]
+
+2011-11-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po:
+ Update Japanese sudoers translation from translationproject.org
+ [ec0f2beaad36]
+
+ * doc/sudoers.pod:
+ Make the env_reset descriptions consistent.
+ [41c056f02688]
+
+2011-11-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Do multiple expansion when expanding paths to the noexec file, sesh
+ and the plugin directory. Adapted from a diff by Mike Frysinger
+ [d7e16c876c66]
+
+ * common/Makefile.in:
+ regen
+ [9d729e09c186]
+
+2011-11-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * .hgignore:
+ Add ignore file; from Mike Frysinger
+ [1fa8d52425f8]
+
+ * mkdep.pl:
+ no longer save old Makefile.in to .old
+ [378dd2395545]
+
+ * plugins/sudoers/Makefile.in, src/Makefile.in:
+ regen
+ [769faf517720]
+
+ * config.guess, config.sub, configure, ltmain.sh, m4/libtool.m4,
+ m4/ltoptions.m4, m4/ltversion.m4:
+ Update to libtool 2.4.2
+ [9dac78d84b4f]
+
+2011-11-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers_version.h:
+ Bump grammar version for #include and #includedir relative path
+ support.
+ [82a4f7cd8f71]
+
+2011-11-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.pod, plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Add support for relative paths in #include and #includedir
+ [4d6e3bd0c24f]
+
+ * plugins/sudoers/Makefile.in:
+ Fix install-plugin when shared objects are unsupported or disabled.
+ [cbdd770a7a1b]
+
+ * plugins/sudoers/goodpath.c:
+ Don't write to sbp if it is NULL
+ [fc438f8e8570]
+
+2011-11-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ Remove all sudo/sudoers .mo files on uninstall If LINGUAS is set,
+ only install matching .mo files
+ [c1dc30ab4ebc]
+
+2011-11-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/group_plugin.c, plugins/sudoers/plugin_error.c,
+ plugins/sudoers/sudoers.c, src/conversation.c:
+ Fix non-dynamic (no dlopen) sudo build.
+ [b0bd3fa925a3]
+
+ * configure, configure.in:
+ Don't error out if the user specified --disable-shared
+ [cf035dd1e5cc]
+
+ * common/sudo_debug.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ src/conversation.c:
+ Use SUDO_CONV_DEBUG_MSG in the plugin instead of writing directly to
+ the debug file.
+ [640c62f83251]
+
+ * plugins/sudoers/find_path.c, plugins/sudoers/goodpath.c,
+ plugins/sudoers/sudoers.h:
+ Make sudo_goodpath() return value bolean
+ [fea2d59a6e55]
+
+ * INSTALL, MANIFEST, configure, configure.in, mkdep.pl,
+ plugins/sudoers/Makefile.in, plugins/sudoers/auth/securid.c:
+ Remove obsolete securid auth method.
+ [4e54f860214b]
+
+ * plugins/sudoers/auth/afs.c, plugins/sudoers/auth/aix_auth.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h:
+ Prefix authentication functions with a "sudo_" prefix to avoid
+ namespace problems.
+ [581d74063ea1]
+
+ * INSTALL, MANIFEST, config.h.in, configure, configure.in,
+ doc/TROUBLESHOOTING, mkdep.pl, plugins/sudoers/Makefile.in,
+ plugins/sudoers/auth/kerb4.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h, plugins/sudoers/env.c:
+ Remove the old Kerberos IV support
+ [2e4b4a44209d]
+
+2011-11-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c:
+ Don't print garbage at the end of the custom lecture.
+ [44bb788fafaa]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Add lexer tracing as debug@parser
+ [d850f3f9d414]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/defaults.h, plugins/sudoers/gram.c,
+ plugins/sudoers/match.c, plugins/sudoers/parse.c,
+ plugins/sudoers/regress/parser/check_fill.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/toke_util.c,
+ plugins/sudoers/visudo.c:
+ Revert 003bdb078a15. We need to #include <gram.h> not "gram.h" and
+ <def_data.h> and not "def_data.h" when generating the parser in a
+ build dir.
+ [7da701def753]
+
+2011-11-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkdep.pl, plugins/sudoers/Makefile.in:
+ Better devdir support in mkdep.pl
+ [7dcec57bd155]
+
+ * plugins/sudoers/Makefile.in:
+ Add devdir before srcdir in include path and fix up dependecies
+ accordingly.
+ [6e9958eca485]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/defaults.h, plugins/sudoers/match.c,
+ plugins/sudoers/parse.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/visudo.c:
+ #include "gram.h" not <gram.h> and "def_data.h" and not
+ <def_data.h>.
+ [003bdb078a15]
+
+ * sudo.pp:
+ Mark libexec files as optional. If we build without shared object
+ support, libexec is not used.
+ [4bffcf482219]
+
+ * src/load_plugins.c:
+ Change Debug sudo.conf setting to take a program name as the first
+ argument. In the future, this will allow visudo and sudoreplay to
+ use their own Debug entries.
+ [cfb8f7e4867c]
+
+ * src/sudo.c:
+ fix sudo_debug_printf priority
+ [dcb67e965609]
+
+ * plugins/sudoers/sudoers.c:
+ add missing debug_return_int
+ [d88ec450c592]
+
+2011-11-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/sudo_debug.c, include/error.h, include/sudo_debug.h,
+ plugins/sudoers/logging.c, src/exec.c, src/exec_pty.c:
+ Fold SUDO_DEBUG_PROGERR and SUDO_DEBUG_SYSERR into SUDO_DEBUG_ERROR
+ [dcee8efc294f]
+
+ * doc/UPGRADE:
+ Add missing word in HOME security note.
+ [fd844fdcc1ac]
+
+ * plugins/sudoers/testsudoers.c:
+ Prevent "testsudoers -d username" from trying to malloc(0).
+ [839126e56e8c]
+
+2011-11-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/regress/sudoers/test10.in,
+ plugins/sudoers/regress/sudoers/test10.out.ok,
+ plugins/sudoers/regress/sudoers/test10.toke.ok,
+ plugins/sudoers/regress/sudoers/test10.toke.out.ok,
+ plugins/sudoers/regress/sudoers/test11.in,
+ plugins/sudoers/regress/sudoers/test11.out.ok,
+ plugins/sudoers/regress/sudoers/test11.toke.ok,
+ plugins/sudoers/regress/sudoers/test11.toke.out.ok,
+ plugins/sudoers/regress/sudoers/test12.in,
+ plugins/sudoers/regress/sudoers/test12.out.ok,
+ plugins/sudoers/regress/sudoers/test12.toke.ok,
+ plugins/sudoers/regress/sudoers/test13.in,
+ plugins/sudoers/regress/sudoers/test13.out.ok,
+ plugins/sudoers/regress/sudoers/test13.toke.ok,
+ plugins/sudoers/regress/sudoers/test9.in,
+ plugins/sudoers/regress/sudoers/test9.out.ok,
+ plugins/sudoers/regress/sudoers/test9.toke.ok,
+ plugins/sudoers/regress/sudoers/test9.toke.out.ok:
+ Tests for empty sudoers (should parse OK) and syntax errors within a
+ line (should report correct line number) both with and without the
+ trailing newline.
+ [d57c879c4718]
+
+ * plugins/sudoers/regress/sudoers/test4.out.ok,
+ plugins/sudoers/regress/sudoers/test5.out.ok,
+ plugins/sudoers/regress/sudoers/test7.out.ok,
+ plugins/sudoers/regress/sudoers/test8.out.ok,
+ plugins/sudoers/testsudoers.c:
+ Print line number when there is a parser error.
+ [5444ef6ac6dc]
+
+2011-11-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Keep track of the last token returned. On error, if the last token
+ was COMMENT, decrement sudolineno since the error most likely
+ occurred on the preceding line. Previously we always uses
+ sudolineno-1 which will give the wrong line number for errors within
+ a line.
+ [d661a03a64da]
+
+2011-11-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ update with sudo 1.8.3p1 info
+ [0f79ff31f602]
+
+ * plugins/sudoers/sudoers.c:
+ Fix crash when "sudo -g group -i" is run. Fixes bug 521
+ [a3087ae337c4]
+
+2011-10-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo.c:
+ Make alias_remove_recursive() return TRUE/FALSE as its callers
+ expect and remove two unused arguments. Fixes bug 519.
+ [2ee3b2882844]
+
+ * plugins/sudoers/regress/visudo/test1.out.ok,
+ plugins/sudoers/regress/visudo/test1.sh:
+ Add regress test for bugzilla 519
+ [48000ebedf97]
+
+ * plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_fill.c:
+ Disable warning/error wrapping in regress tests.
+ [373c589ba561]
+
+2011-10-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ Do compile-po as part of sync-po so that the .mo files get rebuild
+ automatically when we sync with translationproject.org
+ [83f3cbfc2f33]
+
+ * plugins/sudoers/Makefile.in:
+ check_addr needs to link with the network libraries on Solaris
+ [322bd70e316e]
+
+ * plugins/sudoers/match.c:
+ When matching a RunasAlias for a runas group, pass the alias in as
+ the group_list, not the user_list. From Daniel Kopecek.
+ [766545edf141]
+
+ * plugins/sudoers/check.c, plugins/sudoers/sudoers.c:
+ We need to init the auth system regardless of whether we need a
+ password since we will be closing the PAM session in the monitor
+ process. Fixes a crash in the monitor on Solaris; bugzilla #518
+ [e82809f86fb3]
+
+2011-10-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c:
+ Get rid of done: label. If the child exits we still need to close
+ the pty, update utmp and restore the SELinux tty context.
+ [cc127bf48405]
+
+2011-10-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/Makefile.in, common/atobool.c, common/fileops.c,
+ common/fmt_string.c, common/lbuf.c, common/list.c,
+ common/setgroups.c, common/term.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/alias.c, plugins/sudoers/audit.c,
+ plugins/sudoers/auth/afs.c, plugins/sudoers/auth/aix_auth.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/dce.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/kerb4.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid.c,
+ plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/boottime.c,
+ plugins/sudoers/bsm_audit.c, plugins/sudoers/check.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/env.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/getspwuid.c,
+ plugins/sudoers/goodpath.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/interfaces.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_path.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/logging.c,
+ plugins/sudoers/logwrap.c, plugins/sudoers/match.c,
+ plugins/sudoers/match_addr.c, plugins/sudoers/parse.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/redblack.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.h,
+ plugins/sudoers/toke.l, plugins/sudoers/toke_util.c,
+ src/Makefile.in, src/conversation.c, src/exec.c, src/exec_pty.c,
+ src/get_pty.c, src/load_plugins.c, src/net_ifs.c, src/parse_args.c,
+ src/selinux.c, src/sudo.c, src/sudo.h, src/sudo_edit.c,
+ src/tgetpass.c, src/ttysize.c, src/utmp.c:
+ Add debug_decl/debug_return (almost) everywhere. Remove old
+ sudo_debug() and convert users to sudo_debug_printf().
+ [8f3bbf907b67]
+
+ * common/alloc.c, include/error.h, plugins/sudoers/plugin_error.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c, src/error.c:
+ Wrap error/errorx and warning/warningx functions with debug
+ statements. Disable wrapping for standalone sudoers programs as well
+ as memory allocation functions (to avoid infinite recursion).
+ [562ed7b5ae8d]
+
+ * README, config.h.in, configure, configure.in:
+ Add checks for __func__ and __FUNCTION__ and mention that we now
+ require a cpp that supports variadic macros.
+ [314cfe4c5d23]
+
+ * MANIFEST, common/Makefile.in, common/sudo_debug.c,
+ include/sudo_debug.h, include/sudo_plugin.h, src/conversation.c,
+ src/load_plugins.c, src/parse_args.c, src/sudo.c,
+ src/sudo_plugin_int.h:
+ New debug framework for sudo and plugins using /etc/sudo.conf that
+ also supports function call tracing.
+ [cded741e9f10]
+
+2011-10-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po:
+ Update Japanese sudoers translation from translationproject.org
+ [c24725775e32]
+
+2011-10-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Override and ignore the --disable-static option. Sudo already runs
+ libtool with -tag=disable-static where applicable and we need non-
+ PIC objects to build the executables.
+ [aff1227b853a]
+
+2011-10-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Add sudoedit fix
+ [74655c7ccad1]
+
+ * plugins/sudoers/po/sudoers.pot:
+ regen pot files
+ [28d89a831ed3]
+
+ * plugins/sudoers/env.c:
+ Ignore set_logname (which is now the default) for sudoedit since we
+ want the LOGNAME, USER and USERNAME environment variables to refer
+ to the calling user since that is who the editor runs as. This
+ allows the editor to find the user's startup files. Fixes bugzilla
+ #515
+ [6c5dddf5ff05]
+
+ * plugins/sudoers/pwutil.c:
+ Instead of trying to grow the buffer in make_grlist_item(), simply
+ increase the total length, free the old buffer and allocate a new
+ one. This is less error prone and saves us from having to adjust all
+ the pointers in the buffer. This code path is only taken when there
+ are groups longer than the length of the user field in struct utmp
+ or utmpx, which should be quite rare.
+ [5587dc8cffaf]
+
+ * src/po/it.mo:
+ Add Italian translation for sudo from translationproject.org
+ [1b3dd886e7e3]
+
+ * MANIFEST, NEWS, plugins/sudoers/po/ja.mo, plugins/sudoers/po/ja.po,
+ src/po/ja.mo, src/po/ja.po:
+ Japanese translation for sudo and sudoers from
+ translationproject.org
+ [c06dd866be6e]
+
+2011-10-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ sudoreplay depends on timestr.lo too; from Mike Frysinger
+ [b9e73214b2f1]
+
+2011-10-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot:
+ Regen sudoers pot file.
+ [019588bafdb3]
+
+ * NEWS:
+ Update with latest sudo 1.8.3 news
+ [6868042a88e9]
+
+ * plugins/sudoers/sudoers.c:
+ It appears that LDAP or NSS may modify the euid so we need to be
+ root for the open(). We restore the old perms at the end of
+ sudoers_policy_open().
+ [2da67a5497ef]
+
+ * plugins/sudoers/set_perms.c:
+ Better warning message on setuid() failure for the setreuid()
+ version of set_perms().
+ [07abcfe7bd9a]
+
+2011-09-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c:
+ Delref auth_pw at the end of check_user() instead of getting a ref
+ twice.
+ [cb665f55e6a5]
+
+ * plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/check.c:
+ Make sudo_auth_{init,cleanup} return TRUE on success and check for
+ sudo_auth_init() return value in check_user().
+ [92631c919356]
+
+ * plugins/sudoers/auth/sudo_auth.c:
+ Do not return without restoring permissions.
+ [59ef40b6696a]
+
+ * plugins/sudoers/po/sudoers.pot, src/po/sudo.pot:
+ regen pot files
+ [9f320a340b7c]
+
+ * plugins/sudoers/auth/API, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/kerb4.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/secureware.c,
+ plugins/sudoers/auth/securid.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/auth/sudo_auth.h,
+ plugins/sudoers/check.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Modify the authentication API such that the init and cleanup
+ functions are always called, regardless of whether or not we are
+ going to verify a password. This is needed for proper PAM session
+ support.
+ [19a53f3fb596]
+
+ * compat/Makefile.in, mkdep.pl, plugins/sudoers/Makefile.in:
+ Add missing dependency for getspwuid.lo and regen other depends.
+ [f7f70eae819a]
+
+ * plugins/sudoers/auth/pam.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h, plugins/sudoers/sudoers.c:
+ Fix a PAM_USER mismatch in session open/close. We update PAM_USER to
+ the target user immediately before setting resource limits, which is
+ after the monitor process has forked (so it has the old value).
+ Also, if the user did not authenticate, there is no pamh in the
+ monitor so we need to init pam here too. This means we end up
+ calling pam_start() twice, which should be fixed, but at least the
+ session is always properly closed now.
+ [fbc063a2a872]
+
+ * src/utmp.c:
+ Add check for old being NULL in utmp_setid(); from Steven McDonald
+ [e87126442f2e]
+
+2011-09-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/pwutil.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ If the invoking user cannot be resolved by uid fake the struct
+ passwd and store it in the cache so we can delref it on exit.
+ [a27e2f8b9f5e]
+
+2011-09-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ Don't error out if the group plugin cannot be loaded, just warn.
+ [0fbfcd381e33]
+
+2011-09-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ Quiet a false positive found by several static analysis tools. These
+ tools don't know that log_error() does not return (it longjmps to
+ error_jmp which returns to the sudo front-end).
+ [33d0469df21b]
+
+2011-09-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/po/da.mo, plugins/sudoers/po/eo.mo,
+ plugins/sudoers/po/fi.mo, plugins/sudoers/po/pl.mo,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/zh_CN.mo, src/po/it.po:
+ Add Italian translation for sudo from translationproject.org Regen
+ .mo files
+ [c3c888a82be6]
+
+2011-09-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/TROUBLESHOOTING:
+ Update to current reality and add bit about ssh auth
+ [184a1e7c2eeb]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Make "verbose" static; fixes a namespace clash with
+ pam_ssh_agent_auth (and it doesn't need to be extern these days).
+ [cc38d2eb2f4c]
+
+ * config.h.in, configure, configure.in, src/get_pty.c:
+ FreeBSD has libutil.h not util.h
+ [dab4c94b6d4f]
+
+ * configure, configure.in:
+ Define _BSD_SOURCE on FreeBSD, OpenBSD and DragonflyBSD
+ [41c362f0a92a]
+
+2011-09-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/da.po, plugins/sudoers/po/eo.po,
+ plugins/sudoers/po/fi.po, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/uk.po, plugins/sudoers/po/zh_CN.po:
+ Update po files from translationproject.org
+ [1e99e147c7fa]
+
+2011-09-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.ldap.pod, plugins/sudoers/ldap.c:
+ Add support for DEREF in ldap.conf.
+ [3c1937a98547]
+
+ * Makefile.in:
+ install target should depend on ChangeLog too, not just install-doc
+ [1a7c83941175]
+
+ * doc/sudoers.pod:
+ Only iolog_file (not iolog_dir) supports mktemp-style suffixes.
+ [0eca47d60a2c]
+
+ * NEWS:
+ Sync with 1.8 branch for sudo 1.8.2 and 1.8.3 changes.
+ [0501415cc5ff]
+
+ * doc/UPGRADE:
+ Document group lookup change and possible side effects.
+ [585743e1ebf7]
+
+ * configure, configure.in:
+ Fix some square brackets in case statements that needed to be
+ doubled up. While here, use $OSMAJOR when it makes sense.
+ [8973343f4696]
+
+ * plugins/sudoers/pwutil.c:
+ Fix a crash in make_grlist_item() on 64-bit machines with strict
+ alignment.
+ [c89508c73c46]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/defaults.h:
+ Remove list_options() function that is no longer used now that "sudo
+ -L" is gone.
+ [fcc6a776c135]
+
+ * configure, configure.in:
+ Error message if user tries --with-CC
+ [ec5b478f813a]
+
+ * configure, configure.in:
+ Check for -libmldap too when looking for ldap libs, which is the
+ Tivoli Directory Server client library.
+ [bb3007a97206]
+
+2011-09-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/parse.c:
+ Honor NOPASSWD tag for denied commands too.
+ [8dd92656db92]
+
+2011-09-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, configure, configure.in:
+ Remove --with-CC option; it doesn't work correctly now that we use
+ libtool. Users can get the same effect by setting the CC environment
+ variable when running configure.
+ [ec22bd1a55e0]
+
+2011-08-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, plugins/sudoers/visudo.c,
+ src/sudo_edit.c:
+ Assume all modern systems support fstat(2).
+ [6a5a8985f6a0]
+
+2011-08-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/regress/glob/globtest.c, config.h.in, configure,
+ configure.in, include/missing.h, plugins/sudoers/sudoers.h,
+ src/sudo.h, src/sudo_noexec.c:
+ Add configure test for missing errno declaration and only declare it
+ ourselves if it is missing.
+ [456e76c809a2]
+
+ * plugins/sudoers/alias.c:
+ Include errno.h before sudo.h to avoid conflicting with the system
+ definition of errno.
+ [d0b97e392512]
+
+2011-08-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/regress/parser/check_addr.c:
+ Only print individual check status when there is a failure.
+ [2ac704c91441]
+
+ * plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/parser/check_addr.c:
+ Add calls to setprogname() for test programs.
+ [a8d9b420e826]
+
+ * configure, configure.in:
+ Add -Wall and -Werror after all tests so they don't cause failures.
+ [2661188ff3fa]
+
+ * plugins/sudoers/Makefile.in:
+ Actually run check_addr in the check target
+ [0b2778bc86bf]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/match.c,
+ plugins/sudoers/match_addr.c,
+ plugins/sudoers/regress/parser/check_addr.c,
+ plugins/sudoers/regress/parser/check_addr.in:
+ Split out address matching into its own file and add regression
+ tests for it.
+ [12b9a2bf8dba]
+
+2011-08-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/match.c:
+ When matching an address with a netmask in sudoers, AND the mask and
+ addr before checking against the local addresses.
+ [9747bb6d7b1c]
+
+2011-08-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/match.c:
+ Fix netmask matching.
+ [a3c8f8cc1464]
+
+ * plugins/sudoers/visudo.c:
+ Don't assume all editors support the +linenumber command line
+ argument, use a whitelist of known good editors.
+ [21d43a91fd10]
+
+2011-08-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/set_perms.c, plugins/sudoers/visudo.c, src/exec.c,
+ src/exec_pty.c, src/sudo.c:
+ Silence compiler warnings on Solaris with gcc 3.4.3
+ [da620bae6fdb]
+
+ * mkpkg:
+ Fix building on RHEL 3
+ [f3227fb2a252]
+
+ * INSTALL, configure, configure.in:
+ Add --enable-werror configure option.
+ [fec2cdb95543]
+
+ * common/setgroups.c:
+ setgroups() proto lives in grp.h on RHEL4, perhaps others.
+ [de91c0de5a98]
+
+ * configure, configure.in:
+ Use PAM by default on AIX 6 and higher.
+ [e16493208e5f]
+
+2011-08-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/po/eo.mo, plugins/sudoers/po/eo.po,
+ src/po/eo.mo, src/po/eo.po:
+ Add new Esperanto translation from translationproject.org
+ [0d9a59e04c64]
+
+2011-08-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog_path.c:
+ Quiet an innocuous valgrind warning.
+ [0582b6027161]
+
+2011-08-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog_path.c,
+ plugins/sudoers/regress/iolog_path/data:
+ Fix expansion of strftime() escapes in log_dir and add a regress
+ test that exhibited the problem.
+ [a5c7c1c4c589]
+
+ * plugins/sudoers/Makefile.in:
+ Fix "make check" return value.
+ [33b58e175230]
+
+2011-08-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot, src/po/sudo.pot:
+ Regen pot files
+ [063841aac19b]
+
+ * Makefile.in:
+ Fix logic inversion in pot file up to date check.
+ [f6a8ca8654df]
+
+2011-08-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Add caching for gettext() checks.
+ [01b7200f6105]
+
+ * configure, configure.in:
+ Better handling of libintl header and library mismatch.
+ [9a49b1d4db69]
+
+2011-08-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ Also check sudoers gid if sudoers is group writable.
+ [23ef96ca0d33]
+
+2011-08-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ If dlopen is present but libtool doesn't find it, error out since it
+ probably means that libtool doesn't support the system.
+ [a9da0a5f7941]
+
+ * mkpkg:
+ configure args on the command line should override builtin defaults.
+ Disable NLS for non-Linux/Solaris unless explicitly enabled.
+ [b2fb05614504]
+
+ * plugins/sudoers/auth/aix_auth.c:
+ Fix loop that calls authenticate(). If there was an error message
+ from authenticate(), display it.
+ [063a0c4f0b9a]
+
+2011-08-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * m4/libtool.m4, m4/ltversion.m4:
+ Update to autoconf 2.68 and libtool 2.4
+ [5a912a6eb67b]
+
+ * config.guess, config.sub, configure, configure.in, ltmain.sh:
+ Update to autoconf 2.68 and libtool 2.4
+ [931ab56aecf6]
+
+ * doc/sudoers.pod:
+ Fix typo; OPT should be OTP
+ [e97bd2e46544]
+
+ * plugins/sudoers/Makefile.in:
+ Rename libsudoers convenience library to libparsesudoers to avoid
+ libtool confusion.
+ [2a89a613f537]
+
+2011-08-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/po/da.mo, plugins/sudoers/po/da.po:
+ Add Danish sudoers translation from translationproject.org
+ [27b96e85eb13]
+
+ * plugins/sudoers/sudoers.c, plugins/sudoers/testsudoers.c:
+ Add dedicated callback function for runas_default sudoers setting
+ that only sets runas_pw if no runas user or group was specified by
+ the user.
+ [b8382d8eea34]
+
+2011-08-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/fi.mo, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po,
+ plugins/sudoers/po/uk.mo, plugins/sudoers/po/uk.po, src/po/ru.mo,
+ src/po/ru.po:
+ Update Finish, Polish, Russian and Ukrainian translations from
+ translationproject.org.
+ [f9339aff664e]
+
+ * plugins/sudoers/defaults.h, plugins/sudoers/sudoers.c,
+ plugins/sudoers/testsudoers.c:
+ Go back to using a callback for runas_default to keep runas_pw in
+ sync. This is needed to make per-entry runas_default settings work
+ with LDAP-based sudoers. Instead of declaring it a callback in
+ def_data.in, sudo and testsudoers poke sudo_defs_table[] which is a
+ bit naughty, but avoids requiring stub functions in visudo and the
+ tests.
+ [9aaefb908415]
+
+2011-08-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ Add check for out of date message catalogs when doing "make dist".
+ [e45a29b612f4]
+
+2011-08-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [d6f9ad26774a]
+
+ * configure.in:
+ Make sure compiler supports static-libgcc before using it.
+ [b01bd9566e50]
+
+2011-08-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/Makefile.in:
+ Link libsudo_noexec.la with LDLDFLAGS for -static-libgcc
+ [c99c7ab3edef]
+
+2011-07-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/po/fi.mo, plugins/sudoers/po/pl.mo,
+ plugins/sudoers/po/pl.po, plugins/sudoers/po/uk.mo,
+ plugins/sudoers/po/zh_CN.mo, src/po/ru.mo, src/po/ru.po,
+ src/po/zh_CN.mo:
+ Add new Russian sudo translation from translationproject.org and
+ rebuild the other translation files.
+ [e20015459056]
+
+2011-07-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/fi.po, plugins/sudoers/po/pl.po:
+ Update Finish and Polish translations from translationproject.org
+ [4e3dbba4a1de]
+
+ * plugins/sudoers/sudoers.c, src/parse_args.c, src/sudo.c:
+ Go back to escaping the command args for "sudo -i" and "sudo -s"
+ before calling the plugin. Otherwise, spaces in the command args are
+ not treated properly. The sudoers plugin will unescape non- spaces
+ to make matching easier.
+ [dfa2c4636f33]
+
+2011-07-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/parse.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l:
+ Fix some potential problems found by the clang static analyzer, none
+ serious.
+ [ff64aa74aae6]
+
+ * plugins/sudoers/po/uk.po, plugins/sudoers/po/zh_CN.po,
+ src/po/zh_CN.po:
+ Updated Ukranian and Chinese (simplified) po files from
+ translationproject.org
+ [ec792becb48e]
+
+2011-07-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/pl.po:
+ Updated Polish translation from translationproject.org
+ [a3af53cb649c]
+
+ * plugins/sudoers/po/sudoers.pot, src/po/sudo.pot:
+ Rebuild pot files
+ [c650524c0f0a]
+
+ * plugins/sudoers/audit.c, plugins/sudoers/sudoers.c:
+ Don't try to audit failure if the runas user does not exist. We
+ don't have the user's command at this point so there is nothing to
+ audit. Add a NULL check in audit_success() and audit_failure() just
+ to be on the safe side.
+ [2a0007c2022f]
+
+ * mkpkg:
+ Add -g to CFLAG for PIE builds.
+ [32a0a9693c9c]
+
+2011-07-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/pwutil.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, src/sudo.c:
+ Remove fallback to per-group lookup when matching groups in sudoers.
+ The sudo front-end will now use getgrouplist() to get the user's
+ list of groups if getgroups() fails or returns zero groups so we
+ always have a list of the user's groups. For systems with
+ mbr_check_membership() which support more that NGROUPS_MAX groups
+ (Mac OS X), skip the call to getgroups() and use getgrouplist() so
+ we get all the groups.
+ [51b3ed8c600b]
+
+2011-07-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/setgroups.c:
+ Fix setgroups() fallback code on EINVAL.
+ [2b6faecd56a4]
+
+ * plugins/sudoers/set_perms.c:
+ Fix two PERM_INITIAL cases that were still using user_gids.
+ [9680bab0acc6]
+
+ * MANIFEST:
+ Add Polish sudo message catalog
+ [8bb40c3ba576]
+
+ * plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ user_group is no longer used, remove it
+ [9acede0fe6c5]
+
+2011-07-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/po/pl.mo, plugins/sudoers/po/pl.po:
+ Add Polish translation from translationproject.org
+ [afac5c638573]
+
+ * MANIFEST, common/Makefile.in, common/setgroups.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.h, src/sudo.c,
+ src/sudo.h, src/sudo_edit.c:
+ Add a wrapper for setgroups() that trims off extra groups and
+ retries if setgroups() fails. Also add some missing addrefs for
+ PERM_USER and PERM_FULL_USER.
+ [224dfd8aae5c]
+
+ * MANIFEST, compat/Makefile.in, compat/getgrouplist.c, config.h.in,
+ configure, configure.in, include/missing.h, mkdep.pl,
+ plugins/sudoers/ldap.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h, src/sudo.c:
+ Instead of keeping separate groups and gids arrays, create struct
+ group_info and use it to store both, along with a count for each.
+ Cache group info on a per-user basis using getgrouplist() to get the
+ groups. We no longer need special to special case the user or list
+ user for user_in_group() and thus no longer need to reset the groups
+ list when listing another user.
+ [0ad849a8b2d5]
+
+ * src/preload.c:
+ Don't rely on NULL since we don't include a header for it.
+ [b40937f1890c]
+
+2011-07-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.pod:
+ Fix typo
+ [c1035360e169]
+
+2011-07-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ Do not shadow global sudo_mode with a local variable in set_cmnd()
+ [0c72969503ad]
+
+2011-07-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ bash 2.x doesd not support the -l flag and exits with an error if it
+ is specified so use --login instead. This causes an error with bash
+ 1.x (which uses -login instead) but this version is hopefully less
+ used than 2.x.
+ [5c4c296e30e6]
+
+ * src/po/pl.mo, src/po/pl.po:
+ Add Polish translation from translationproject.org
+ [48592dd6edcf]
+
+2011-07-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/set_perms.c:
+ Make error strings translatable.
+ [414c5c484768]
+
+ * mkpkg:
+ Only run configure with --with-pam-login for RHEL 5 and above.
+ [6c16e4de4026]
+
+ * sudo.pp:
+ Fix typo in summary
+ [9ac618c9a749]
+
+2011-07-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/logwrap.c:
+ Add missing logwrap.c
+ [c12a413ecc1d]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h,
+ plugins/sudoers/regress/logging/check_wrap.c,
+ plugins/sudoers/regress/logging/check_wrap.in,
+ plugins/sudoers/regress/logging/check_wrap.out.ok:
+ Split out log file word wrap code into its own file and add unit
+ tests. Fixes an off-by one in the word wrap when the log line length
+ matches loglinelen.
+ [52ed277f6690]
+
+2011-07-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg:
+ For SuSE, only use /usr/lib64 as libexec if generating 64-bit
+ binaries.
+ [645ab903cf77]
+
+ * src/load_plugins.c, src/sudo.c:
+ Fix build error when --without-noexec configure option is used.
+ [b994f7b0d8b4]
+
+ * configure, configure.in:
+ Disable noexec for AIX < 5. LDR_PRELOAD is only available in AIX 5.3
+ and above.
+ [c2a6f9b472f3]
+
+2011-07-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Resolve the list of gids passed in from the sudo frontend (the
+ result of getgroups()) to names and store both the group names and
+ ids in the sudo_user struct. When matching groups in the sudoers
+ file, match based on the names in the groups list first and only do
+ a gid-based match when we absolutely have to. By matching on the
+ group name (as it is listed in sudoers) instead of id (which we
+ would have to resolve) we save a lot of group lookups for sudoers
+ files with a lot of groups in them.
+ [8dc19353f148]
+
+2011-06-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ Workaround for "sudo -i command" and newer versions of bash which
+ don't go into login mode when -c is specified unless -l is too.
+ [9393762b80f3]
+
+2011-06-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/logging.c:
+ Rewrite logfile word wrapping code to be more straight-forward and
+ actually wrap at the correct place.
+ [f712a0c90f55]
+
+2011-06-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/CONTRIBUTORS, doc/contributors.pod, plugins/sudoers/sudoers.c:
+ Set use_pty=true in command details when use_pty is set in sudoers.
+ From Ludwig Nussel
+ [8d95a163dfc1]
+
+2011-06-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/zh_CN.mo, plugins/sudoers/po/zh_CN.po,
+ src/po/zh_CN.mo, src/po/zh_CN.po:
+ Sync Chinese (simplified) PO files from translationproject.org
+ [acce8eb7be18]
+
+2011-06-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, plugins/sudoers/po/eu.mo, plugins/sudoers/po/fi.mo,
+ plugins/sudoers/po/uk.mo, src/po/da.mo, src/po/da.po, src/po/eu.mo:
+ Add Danish translation from translationproject.org and add missing
+ Basque mo files.
+ [0c22bb21b9c4]
+
+ * Makefile.in, configure, configure.in:
+ No longer need to specify LINGUAS in configure, "make install-nls"
+ now just installs all the .mo files it finds.
+ [fcd45cf04885]
+
+2011-06-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, doc/CONTRIBUTORS, doc/Makefile.in, doc/contributors.pod:
+ Build CONTRIBUTORS from newly-added contributors.pod
+ [8b192f2720f4]
+
+ * doc/CONTRIBUTORS:
+ Rework the wording in the leading paragraph
+ [312044145cdd]
+
+2011-06-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, doc/CONTRIBUTORS:
+ Add a CONTRIBUTORS file with the names of folks who have contributed
+ code or patches to sudo since I started maintaining it (plus the
+ original authors).
+ [b8bdd8b59528]
+
+2011-06-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/env.c:
+ Preserve SHELL variable for "sudo -s". Otherwise we can end up with
+ a situation where the SHELL variable and the actual shell being run
+ do not match.
+ [b8b3974aee3e]
+
+2011-06-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Only enable Solaris project support when setproject() is present in
+ libproject.
+ [49ad7857ab89]
+
+ * sudo.pp:
+ Explicitly set mode and owner of /etc/sudoers instead of relying on
+ "cp -p" to work in the postinstall script. On AIX 6.1 at least the
+ postinstall script runs before the final file permissions are set.
+ [e41ffc0212b2]
+
+2011-06-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.pod, doc/sudoers.pod:
+ Refer the user to the "Command Environment" section in description
+ of sudo's -i option.
+ [263cc3be7eef]
+
+ * doc/sudo.pod:
+ Fix typo
+ [35dfac450f4d]
+
+2011-06-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkdep.pl:
+ If there is no old dependency for an object file, use the MANIFEST
+ to find its source.
+ [d15e3b9899f9]
+
+ * compat/Makefile.in:
+ Remove dependency for getgrouplist.lo as we don't ship that source
+ file.
+ [312a6d5fe6b0]
+
+2011-06-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/getdate.c, plugins/sudoers/getdate.y:
+ Do not declare yyparse() static as the actual function generated by
+ yacc is extern.
+ [9017b79dcf55]
+
+2011-06-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ Remove locale files in "make uninstall"
+ [201ff261ecbe]
+
+ * configure.in, plugins/sudoers/po/eu.po, plugins/sudoers/po/fi.po,
+ plugins/sudoers/po/uk.po, src/po/eu.po:
+ Add Basque translation and sync Finish and Ukranian translations.
+ [66d2c78c8a13]
+
+ * configure, configure.in:
+ FreeBSD no longer needs the main sudo binary to link with -lpam now
+ that plug-ins are loaded with RTLD_GLOBAL.
+ [96c710df2457]
+
+ * plugins/sudoers/group_plugin.c, src/load_plugins.c:
+ Load plugins with RTLD_GLOBAL instead of RTLD_LOCAL. This fixes
+ problems with pam modules not having access to symbols provided by
+ libpam on some platforms. Affects FreeBSD and SLES 10 at least.
+ [0d016983ec84]
+
+ * Makefile.in:
+ Move xgettext invocation out of update-po target into update-pot
+ [19a73c6d017c]
+
+2011-06-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/po/sudoers.pot, src/po/sudo.pot:
+ Regenerate .pot files for 1.8.2rc2
+ [c3037f591dd8]
+
+ * Makefile.in, common/Makefile.in, compat/Makefile.in,
+ doc/Makefile.in, include/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in,
+ src/Makefile.in, zlib/Makefile.in:
+ Move nls targets to the top level Makefile so the paths in the pot
+ file are saner
+ [65b9285cd8d9]
+
+ * src/po/fi.mo:
+ Add compiled version of sudo Finish translation
+ [8f2405384ea3]
+
+ * MANIFEST, plugins/sudoers/po/fi.mo, plugins/sudoers/po/uk.mo:
+ Update MANIFEST with .po and .mo files Rebuild sudoers fi and uk .mo
+ files
+ [a165e70fa9ec]
+
+ * configure, configure.in, plugins/sudoers/po/fi.po:
+ Add Finish translation from translationproject.org
+ [4466f8a96ceb]
+
+2011-06-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.pod:
+ The group named by exempt_group should not have a % prefix.
+ [df084d6b32c8]
+
+2011-06-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.pod:
+ Fix typo; "Defaults group_plugin" not "Defaults sudo_plugin"
+ [5113699a3f8b]
+
+2011-05-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c, src/exec_pty.c:
+ Fix compressed io log corruption in background mode by using _exit()
+ instead of exit() to avoid flushing buffers twice.
+
+ Improved background mode support. When not allocating a pty, the
+ command is run in its own process group. This prevents write access
+ to the tty. When running in a pty, stdin is not hooked up and we
+ never read from /dev/tty, which results in similar behavior.
+ [87c15149894c]
+
+ * compat/Makefile.in, mkdep.pl, plugins/sudoers/Makefile.in:
+ Clean up regress files Generate proper dependencies for regress objs
+ in compat
+ [88bfc728c1e7]
+
+ * plugins/sudoers/Makefile.in:
+ Add missing dependency for check_fill.o.
+ [0bd6362e3e17]
+
+2011-05-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, configure, configure.in:
+ Add support for --enable-nls[=location]
+ [b90db44a050f]
+
+2011-05-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/linux_audit.c:
+ Include gettext.h
+ [7f909a6e48cb]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/parse.c:
+ Quiet gcc warnings.
+ [b41a6cdca583]
+
+ * configure, configure.in:
+ Don't install .mo files if gettext was not found.
+ [1397b34cc165]
+
+2011-05-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c:
+ Always allocate a pty when running a command in the background but
+ call setsid() after forking to make sure we don't end up with a
+ controlling tty.
+ [b6454ba172e8]
+
+ * plugins/sudoers/iolog.c:
+ Add missing space between command name and the first command line
+ argument.
+ [fe217f0a36d4]
+
+ * plugins/sudoers/sudoreplay.c:
+ Quiet a compiler warning on some platforms.
+ [de9f2849f236]
+
+ * plugins/sudoers/po/README, src/po/README:
+ README file that directs people to translationproject.org
+ [30c0fc323281]
+
+ * plugins/sudoers/po/uk.po, src/po/fi.po:
+ Sync translations with TP
+ [1d7d64559cba]
+
+ * Makefile.in:
+ Add 'sync-po' target to top-level Makefile to rsync the po files
+ from translationproject.org.
+ [20508211aaa3]
+
+ * plugins/sudoers/Makefile.in:
+ install nls files from install target
+ [5fc07b6cab38]
+
+ * Makefile.in, plugins/sudoers/Makefile.in, src/Makefile.in, sudo.pp:
+ Include .mo files in sudo binary packags.
+ [278d4821a916]
+
+ * configure, configure.in, plugins/sudoers/po/zh_CN.mo,
+ plugins/sudoers/po/zh_CN.po, src/po/zh_CN.mo, src/po/zh_CN.po:
+ Add simplified chinese translation
+ [2b33ffc755b9]
+
+2011-05-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in, plugins/sudoers/po/uk.mo,
+ plugins/sudoers/po/uk.po, src/po/uk.mo, src/po/uk.po:
+ Add ukranian translation
+ [2d8102688e93]
+
+ * compat/Makefile.in:
+ refer to siglist.c, not ./siglist.c since not all makes will treat
+ foo and ./foo the same.
+ [6639d293ffba]
+
+ * plugins/sudoers/sudoers.c:
+ Set def_preserve_groups before searching for the command when the -P
+ flag is specified.
+ [0edc7942f875]
+
+ * Makefile.in, compat/Makefile.in, mkdep.pl,
+ plugins/sudoers/Makefile.in:
+ Add dependency for siglist.lo in compat. This is a generated file so
+ "make depend" needs to depend on it.
+ [28d0932f8b50]
+
+ * compat/Makefile.in:
+ More dependency fixes.
+ [aad0d05cd020]
+
+ * compat/Makefile.in:
+ Fix a few dependencies.
+ [eb21aa35a032]
+
+ * plugins/sudoers/Makefile.in, src/Makefile.in:
+ Place compiled mo files in the src dir, not the build dir. When
+ installing compiled mo files, display a status message.
+ [e15634c29cd3]
+
+2011-05-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.ldap.pod, plugins/sudoers/ldap.c:
+ Tivoli Directory Server requires that seconds be present in a
+ timestamp, even though RFC 4517 states that they are optional.
+ [55fe23dd4ef9]
+
+ * plugins/sudoers/sudo_nss.h:
+ Add missing bit of copyright
+ [d2eba3c364ca]
+
+ * doc/visudo.pod:
+ Mention cycle detection warnings
+ [a76bef15ab67]
+
+ * plugins/sudoers/visudo.c:
+ When checking aliases, also check the contents of the alias in case
+ there are problems with an alias that is referenced inside another.
+ Replace the self reference check with real alias cycle detection.
+ [a66c904cf53b]
+
+ * plugins/sudoers/alias.c:
+ Set errno to ELOOP in alias_find() if there is a cycle. Set errno to
+ ENOENT in alias_find() and alias_remove() if the entry could not be
+ found.
+ [b4f0b89e433c]
+
+ * plugins/sudoers/visudo.c:
+ Increment alias_seqno before calls to alias_remove_recursive() to
+ avoid false positives with the alias loop detection. Fixes spurious
+ warnings about unused aliases when they are nested.
+ [a344483b8193]
+
+ * MANIFEST:
+ add mkdep.pl
+ [86b7ed33eab2]
+
+ * plugins/sudoers/Makefile.in:
+ Add dependency on convenience libs to binaries
+ [cd3078b3c997]
+
+ * Makefile.in:
+ mkdep.pl only works when run from the src dir
+ [f35a5e47c944]
+
+ * Makefile.in, common/Makefile.in, compat/Makefile.in, mkdep.pl,
+ plugins/sample/Makefile.in, plugins/sample_group/Makefile.in,
+ plugins/sudoers/Makefile.in, src/Makefile.in, zlib/Makefile.in:
+ Auto-generate Makefile dependencies with a perl script.
+ [a3e4afcd7975]
+
+2011-05-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/match.c:
+ If the user specifies a runas group via sudo's -g option that
+ matches the runas user's group in the passwd database and that group
+ is not denied in the Runas_Spec, allow it. Thus, if user root's gid
+ in /etc/passwd is 0, then "sudo -u root -g root id" is allow even if
+ no groups are present in the Runas_Spec.
+ [e3f9732dc564]
+
+2011-05-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in, src/Makefile.in:
+ Add dependencies on gettext.h
+ [a3a9dc51f78b]
+
+ * plugins/sudoers/Makefile.in, src/Makefile.in:
+ Fix install-nls target with HP-UX sh when gettext is not present.
+ [0c6b9655cd41]
+
+2011-05-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/po/sudoers.pot,
+ src/Makefile.in, src/po/sudo.pot:
+ regenerate .pot files for lbuf changes
+ [918ded125a0b]
+
+ * configure, configure.in:
+ Add missing "checking" message for gettext when using the cache.
+ [9c21187ad1d2]
+
+ * common/lbuf.c, include/lbuf.h, plugins/sudoers/ldap.c,
+ plugins/sudoers/parse.c, plugins/sudoers/sudo_nss.c,
+ src/parse_args.c:
+ Add primitive format string support to the lbuf code to make
+ translations simpler.
+ [ee71c7ef5299]
+
+ * MANIFEST, plugins/sudoers/Makefile.in,
+ plugins/sudoers/po/sudoers.pot, src/Makefile.in, src/po/sudo.pot:
+ Add message catalog template files for sudo and the sudoers module.
+ [f3f8acb1f014]
+
+ * MANIFEST, common/aix.c, common/alloc.c, compat/strsignal.c,
+ config.h.in, configure.in, doc/Makefile.in, include/gettext.h,
+ plugins/sudoers/iolog.c, plugins/sudoers/plugin_error.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/visudo.c, src/error.c,
+ src/net_ifs.c, src/sesh.c, src/sudo.c, src/sudo.h:
+ Add gettext.h convenience header. This is similar to but distinct
+ from the one included with the gettext package.
+ [930a0591f73c]
+
+2011-05-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Add checks for nroff -c and -Tascii flags
+ [19ca990b3149]
+
+ * configure, configure.in:
+ Add check for HP bundled C Compiler (which cannot create shared
+ libs)
+ [517716a7072d]
+
+ * plugins/sudoers/sudoreplay.c:
+ Fix C format warnings.
+ [6514326013fa]
+
+ * include/error.h:
+ Add __printflike
+ [e1749a30a406]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/parse.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/visudo.c, src/parse_args.c:
+ Translate help / usage strings.
+ [ee1cc9b1a8bd]
+
+ * plugins/sudoers/Makefile.in, src/Makefile.in:
+ Set --msgid-bugs-address to the bugzilla url
+ [5a0aa250ca21]
+
+ * Makefile.in, common/Makefile.in, compat/Makefile.in, configure,
+ configure.in, doc/Makefile.in, include/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sample_group/Makefile.in,
+ plugins/sudoers/Makefile.in, src/Makefile.in, zlib/Makefile.in:
+ Add scaffolding to update .po files and install .mo files.
+ [f05f4eed1fe1]
+
+ * doc/license.pod:
+ update copyright year
+ [fa0c62523875]
+
+ * INSTALL, README:
+ No need to include version number at the top of these files.
+ [9f2981325351]
+
+2011-05-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/env.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/visudo.c:
+ Minor warning/error cleanup
+ [9236dc85aeab]
+
+ * config.h.in, configure.in:
+ Emulate ngettext for the non-nls case
+ [13571d63fa36]
+
+ * plugins/sudoers/ldap.c:
+ Do not mark untranslatable strings for translation
+ [735f5d4413fe]
+
+ * plugins/sudoers/check.c:
+ Use ROOT_UID not 0.
+ [09a268db8da4]
+
+ * plugins/sudoers/check.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/logging.c, src/exec.c, src/exec_pty.c,
+ src/load_plugins.c, src/sudo.c, src/sudo_edit.c:
+ Minor warning/error message cleanup
+ [3c7b1a7939b5]
+
+ * plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/logging.c, plugins/sudoers/mon_systrace.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/visudo.c, src/exec.c,
+ src/exec_pty.c, src/net_ifs.c, src/selinux.c:
+ cannot -> "unable to" in warning/error messages
+ [31c3897649e9]
+
+ * plugins/sudoers/check.c, plugins/sudoers/mon_systrace.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/visudo.c, src/exec_pty.c,
+ src/sudo.c, src/utmp.c:
+ can't -> "unable to" in warning/error messages
+ [127b75f15291]
+
+ * configure, configure.in:
+ FreeBSD needs the main sudo executable to link with -lpam when
+ loading dynaic pam modules for some reason.
+ [944522cc9bef]
+
+2011-05-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c, src/exec.c, src/exec_pty.c, src/sudo.c:
+ We don't want to translate debugging messages.
+ [56a1a365815a]
+
+ * configure, configure.in, plugins/sudoers/Makefile.in,
+ plugins/sudoers/iolog.c, plugins/sudoers/plugin_error.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/visudo.c,
+ src/Makefile.in, src/sesh.c, src/sudo.c:
+ Add calls to bindtextdomain() and textdomain() Currently there are
+ two domains, one for the sudo front-end and one for the sudoers
+ plugin and its associated utilities.
+ [0426138f789e]
+
+ * configure, configure.in:
+ Fix caching of libc gettext check.
+ [942142d2c43a]
+
+ * plugins/sudoers/def_data.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/mkdefaults:
+ Mark defaults descriptions for translation
+ [5b27f018e6cf]
+
+ * NEWS:
+ Update for sudo 1.8.1p2
+ [747c4dee2ca7]
+
+2011-05-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Quiet compiler warning when SELinux is enabled.
+ [1fbf77dda240]
+
+ * plugins/sudoers/plugin_error.c, plugins/sudoers/sudoreplay.c,
+ src/error.c, src/net_ifs.c, src/sesh.c:
+ Add missing includes of libintl.h.
+ [bc1d66316082]
+
+ * plugins/sudoers/auth/pam.c:
+ Fix gettext marker.
+ [a5cf4ed66c66]
+
+ * common/aix.c, common/alloc.c, compat/strsignal.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/sudoers.h, src/sudo.h:
+ Include libint.h where needed.
+ [2b0e5a663c7b]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/securid.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/bsm_audit.c, plugins/sudoers/check.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/env.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/interfaces.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_path.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/logging.c,
+ plugins/sudoers/parse.c, plugins/sudoers/plugin_error.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/set_perms.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, plugins/sudoers/visudo.c:
+ Prepare sudoers module messages for translation.
+ [7212ae1909c5]
+
+ * plugins/sudoers/sudoers.c:
+ Only check gid of sudoers file if it is group-readable.
+ [50e3bc0cb242]
+
+ * plugins/sudoers/auth/aix_auth.c:
+ For AIX, keep calling authenticate() until reenter reaches 0.
+ [e240815b74b1]
+
+2011-05-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Cache the status of the initial gettext() check.
+ [32751ebe1704]
+
+ * INSTALL, configure, configure.in:
+ Add --disable-nls flag and improve checks for gettext.
+ [c7e6b17052de]
+
+ * configure, configure.in:
+ When building with gcc on HP-UX, use -march=1.1 to produce portable
+ binaries on a pa-risc2 host. Previously, the +Dportable option was
+ used for the HP-UX C compiler but gcc always produced native
+ binaries.
+ [8f4c749324d7]
+
+2011-05-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/aix.c, common/alloc.c, compat/strsignal.c, src/error.c,
+ src/exec.c, src/exec_pty.c, src/load_plugins.c, src/net_ifs.c,
+ src/parse_args.c, src/selinux.c, src/sesh.c, src/sudo.c,
+ src/sudo_edit.c, src/tgetpass.c, src/utmp.c:
+ Prepare sudo front end messages for translation.
+ [2fc2fabceccb]
+
+2011-05-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, plugins/sudoers/auth/pam.c:
+ Add initial scaffolding to support localization via gettext()
+ [7d47b59fcf95]
+
+ * compat/fnmatch.h, compat/glob.h:
+ Don't let the fnmatch/glob macros expand the function prototype.
+ [a9014aa0288e]
+
+2011-05-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/fnmatch.c, compat/fnmatch.h, compat/glob.c, compat/glob.h:
+ Resolve namespace collisions on HP-UX ia64 and possibly others by
+ adding a rpl_ prefix to our fnmatch and glob replacements and
+ #defining rpl_foo to foo in the header files.
+ [caa9b690a15d]
+
+2011-04-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Split ALL, ROLE and TYPE into their own actions. Since you can only
+ have #ifdefs inside of braces, ROLE and TYPE use a naughty goto in
+ the non-SELinux case. This is safe because the actions are in one
+ big switch() statement.
+ [7473fc2cfa2c]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Fix regexp for matching a CIDR-style IPv4 netmask. From Marc Espie.
+ [9be3480c2865]
+
+2011-04-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/UPGRADE, doc/sudoers.pod:
+ askpass moved from sudoers to sudo.conf in sudo 1.8.0
+ [b2c2956cec4e]
+
+ * doc/sudoers.pod:
+ Remove obsolete warning about runas_default and ordering. Move
+ syslog facility and priority lists into the section where the
+ relevant options are described.
+ [e57b8dc3f779]
+
+2011-04-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/sia.c:
+ Fix SIA support; we no longer have access to the real argc and argv
+ so allocate space for a fake one and use the argv passed to the
+ plugin with "sudo" for argv[0].
+ [1c0552772ad2]
+
+2011-04-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/net_ifs.c:
+ Remove useless realloc when trying to get the buffer size right.
+ [792225380a62]
+
+ * plugins/sudoers/set_perms.c:
+ Be explicit when setting euid to 0 before call to setreuid(0, 0)
+ [7bfeb629fccb]
+
+2011-04-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Need to do checks for krb5_verify_user, krb5_init_secure_context and
+ krb5_get_init_creds_opt_alloc regardless of whether or not
+ krb5-config is present.
+ [9d1b98ece1d3]
+
+2011-04-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/set_perms.c:
+ Work around weird AIX saved uid semantics on setuid() and
+ setreuid(). On AIX, setuid() will only set the saved uid if the euid
+ is already 0.
+ [069fc08150ca]
+
+2011-04-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ update copyright year
+ [1c42d579ba6e]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Treat a missing includedir like an empty one and do not return an
+ error.
+ [92f71d8cbfd4]
+
+2011-04-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pp:
+ Fix ARCH setting in cross-compile Solaris packages.
+ [b0de281cc889]
+
+ * sudo.pp:
+ Fix aix version setting.
+ [98437dbfb085]
+
+ * plugins/sudoers/ldap.c:
+ Remove extraneous parens in LDAP filter when sudoers_search_filter
+ is enabled that causes a search error. From Matthew Thomas.
+ [1d75bf1fc8d9]
+
+2011-04-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/regress/iolog_path/check_iolog_path.c:
+ Correct sizeof() to fix test failure.
+ [fd2f7c0c0572]
+
+ * plugins/sudoers/Makefile.in:
+ "install" target should depend on "install-dirs". Fixes "make -j"
+ problem and closes bz #487. From Chris Coleman.
+ [083902d38edb]
+
+2011-04-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in:
+ Add HAVE_RFC1938_SKEYCHALLENGE
+ [a94cb33758a8]
+
+2011-04-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Mention plugin loading and libgcc changes
+ [e11b30b5026a]
+
+ * src/load_plugins.c, src/sudo.c, src/sudo_plugin_int.h:
+ Load plugins after parsing arguments and potentially printing the
+ version. That way, an error loading or initializing a plugin doesn't
+ break "sudo -h" or "sudo -V".
+ [1b76f2b096a2]
+
+ * Makefile.in:
+ When using a sub-shell to invoke the sub-make, exec make instead of
+ running it inside the shell to avoid an extra process.
+ [fd2c04a71fbf]
+
+ * compat/regress/fnmatch/fnm_test.in, compat/regress/glob/globtest.c:
+ Stop testing unspecified behavior in fnmatch Make glob test more
+ portable
+ [229803093725]
+
+ * compat/Makefile.in:
+ No need to add current dir to include path and having it breaks the
+ test programs that expect to get the system glob.h and fnmatch.h
+ [68085f624be4]
+
+ * INSTALL, configure, configure.in:
+ Fix and document --with-plugindir; partially from Diego Elio Petteno
+ [07edc52ea89e]
+
+ * compat/Makefile.in, compat/regress/fnmatch/fnm_test.c,
+ compat/regress/fnmatch/fnm_test.in, compat/regress/glob/globtest.c,
+ compat/regress/glob/globtest.in:
+ Fix fnmatch and glob tests to not use hard-coded flag values in the
+ input file. Link test programs with libreplace so we get our
+ replacement verions as needed.
+ [c2cca448f660]
+
+ * Makefile.in:
+ If make in a subdir fails, fail the target in the upper level
+ Makefile too. Adapted from a patch from Diego Elio Petteno
+ [76fc9a0d96fd]
+
+ * configure, configure.in, plugins/sudoers/auth/rfc1938.c:
+ Add check for NetBSD-style 4-argument skeychallenge() as Gentoo also
+ has this. Adapted from a patch from Diego Elio Petteno
+ [a97279a59b93]
+
+ * plugins/sudoers/Makefile.in:
+ Make SUDOERS_LDFLAGS reference $(LDFLAGS) instead of using @LDFLAGS@
+ directly.
+ [47b884029b3b]
+
+ * configure, configure.in:
+ Fix warnings when -without-skey, --without-opie, --without-kerb4,
+ --without-kerb5 or --without-SecurID were specified.
+ [71ad150f4d24]
+
+ * MANIFEST:
+ Add plugins/sudoers/sudoers_version.h
+ [7423966de440]
+
+ * configure, configure.in, plugins/sample/Makefile.in,
+ plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in:
+ Back out the --with-libpath addition to SUDOERS_LDFLAGS since that
+ now include LDFLAGS in the sudoers Makefile.in. Add missing settng
+ of @LDFLAGS@ in plugin Makefile.in files.
+ [b835826f889c]
+
+2011-04-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Mention %#gid support in User_List and Runas_List
+ [5a983dff017a]
+
+ * plugins/sudoers/sudoers.c, plugins/sudoers/sudoers_version.h,
+ plugins/sudoers/visudo.c:
+ Keep track of sudoers grammar version and report it in the -V
+ output.
+ [52901a3c0296]
+
+ * plugins/sudoers/sudo_nss.h:
+ Add multiple inclusion guard
+ [50853aed046e]
+
+ * configure, configure.in, plugins/sample/Makefile.in,
+ plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in:
+ The --with-libpath option now adds to SUDOERS_LDFLAGS as well as
+ LDFLAGS. Remove old -static hack for HP-UX < 9. Add LTLDFLAGS and
+ set it to -Wc,-static-libgcc if not using GNU ld so we don't have a
+ dependency on the shared libgcc in sudoers.so.
+ [66ad8bc5e32d]
+
+ * doc/sudoers.pod:
+ Fix typo; from Petr Uzel
+ [f9a7afd80892]
+
+2011-04-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/testsudoers.c:
+ In dump-only mode, use "root" as the default username instead of
+ "nobody" as the latter may not be available on all systems.
+ [0c48e6414337]
+
+2011-03-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/testsudoers.c:
+ Remove NewArgv/NewArgc, they are no longer needed.
+ [16e18f734c7e]
+
+ * plugins/sudoers/testsudoers.c:
+ Fix setting of user_args
+ [aa29e0d0a54a]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Add '!' token to lex tracing
+ [5227ad266235]
+
+ * plugins/sudoers/regress/testsudoers/test1.sh:
+ Use group bin in test, not wheel as most systems have the bin group
+ but the same is no longer true of wheel.
+ [718802b3b45e]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Avoid using pre or post increment in a parameter to a ctype(3)
+ function as it might be a macro that causes the increment to happen
+ more than once.
+ [78e281152c3a]
+
+2011-03-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Strip off the beta or release candidate version when building AIX
+ packages.
+ [28fe31668559]
+
+ * configure, configure.in:
+ We need to include OSDEFS in CFLAGS when doing the utmp/utmpx
+ structure checks for glibc which only has __e_termination visible
+ when _GNU_SOURCE is *not* defined.
+ [59ae1698911f]
+
+ * common/aix.c:
+ getuserattr(user, ...) will fall back to the "default" entry
+ automatically, there's no need to check "default" manually.
+ [3c7a47a61fdb]
+
+2011-03-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/UPGRADE:
+ Document parser changes.
+ [ec415503308d]
+
+ * Makefile.in, common/Makefile.in, compat/Makefile.in,
+ doc/Makefile.in, include/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in,
+ src/Makefile.in, zlib/Makefile.in:
+ If there is an existing sudoers file, only install if it passes a
+ syntax check.
+ [37427c73e8cb]
+
+ * plugins/sudoers/regress/sudoers/test6.out.ok,
+ plugins/sudoers/testsudoers.c:
+ Add runasgroup support to testsudoers
+ [047ea5571f33]
+
+ * plugins/sudoers/Makefile.in:
+ For "make check", keep going even if a test fails.
+ [ce6a0a73c372]
+
+ * plugins/sudoers/testsudoers.c:
+ More useful exit codes:
+ * 0 - parsed OK and command matched.
+ * 1 - parse error
+ * 2 - command not matched
+ * 3 - command denied
+ [1d2ce1361903]
+
+ * doc/sudoers.pod:
+ Document %#gid, and %:#nonunix_gid syntax.
+ [492d4f9696c4]
+
+ * plugins/sudoers/pwutil.c:
+ Add support to user_in_group() for treating group names that begin
+ with a '#' as gids.
+ [20240c94a134]
+
+ * config.h.in, configure, configure.in, src/utmp.c:
+ Add explicit check for struct utmpx.ut_exit.e_termination and struct
+ utmpx.ut_exit.__e_termination. HP-UX uses the latter. Only update
+ ut_exit if we detect one or the other.
+ [b4e8cab777e6]
+
+2011-03-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/toke.c:
+ Add back missing #include of config.h
+ [9ab3897a1b2e]
+
+ * plugins/sudoers/iolog_path.c,
+ plugins/sudoers/regress/iolog_path/data:
+ Avoid a NULL deref on unrecognized escapes. Collapse %% -> % like
+ strftime() does.
+ [93395762cdcd]
+
+ * aclocal.m4:
+ Quote first argument to AC_DEFUN(); from Elan Ruusamae
+ [97f53ad31d77]
+
+2011-03-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST:
+ add new sudoers tests
+ [476af91b3da3]
+
+ * plugins/sudoers/regress/sudoers/test8.in,
+ plugins/sudoers/regress/sudoers/test8.out.ok,
+ plugins/sudoers/regress/sudoers/test8.toke.ok:
+ Add test for a newline in the middle of a string when no line
+ continuation character is used.
+ [de2394bc86ab]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Use bitwise AND instead of modulus to check for length being odd. A
+ newline in the middle of a string is an error unless a line
+ continuation character is used.
+ [bdb1d762a1d5]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Move lexer globals initialization into init_lexer.
+ [1ce62211aadb]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Fix a potential crash when a non-regular file is present in an
+ includedir. Fixes bz #452
+ [1586760c3525]
+
+ * pp:
+ On some Linux systems, "uname -p" contains detailed processor info
+ so check "uname -m" first and then "uname -p" if needed. Recognize
+ PLD Linux.
+ [b8535cb9012e]
+
+2011-03-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/redblack.c:
+ Don't need all sudoers.h here.
+ [8c0929f42dab]
+
+ * src/sudo.c:
+ Print sudo version early, in case policy plugin init fails.
+ [47cddc4358bc]
+
+2011-03-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/regress/sudoers/test4.toke.ok:
+ Update to match change in input.
+ [4a3af8e68790]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Make an empty group or netgroup a syntax error.
+ [66f51ddc2ff6]
+
+ * plugins/sudoers/regress/sudoers/test7.in,
+ plugins/sudoers/regress/sudoers/test7.out.ok,
+ plugins/sudoers/regress/sudoers/test7.toke.ok:
+ An empty group or netgroup should be a syntax error.
+ [bd5bf1e2edce]
+
+ * plugins/sudoers/regress/sudoers/test6.in,
+ plugins/sudoers/regress/sudoers/test6.out.ok,
+ plugins/sudoers/regress/sudoers/test6.toke.ok:
+ Check that uids work in per-user and per-runas Defaults Check that
+ uids and gids work in a Command_Spec
+ [c5e848e6082b]
+
+ * plugins/sudoers/regress/sudoers/test5.in,
+ plugins/sudoers/regress/sudoers/test5.out.ok,
+ plugins/sudoers/regress/sudoers/test5.toke.ok:
+ Test empty string in User_Alias and Command_Spec
+ [3a084d777e03]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Allow a group ID in the User_Spec.
+ [bc2859eb71dc]
+
+2011-03-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Return an error for the empty string when a word is expected. Allow
+ an ID for per-user or per-runas Defaults.
+ [915c259b00ff]
+
+ * plugins/sudoers/testsudoers.c:
+ Fix printing "User_Alias FOO = ALL"
+ [ba58c3d548b3]
+
+2011-03-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/parse_args.c:
+ Better error message about invalid -C argument
+ [c9a8d15bbf5d]
+
+ * NEWS:
+ fix typo
+ [cdcfbafed013]
+
+ * doc/sudoers.pod:
+ Fix placement of equal size ('=') in user specification summary.
+ [5ad7178b230d]
+
+2011-03-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST:
+ update to match sudoers regress
+ [e04db0648717]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Restore ability to define TRACELEXER and have trace output go to
+ stderr.
+ [d9531e4d1b20]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Restore old behavior of setting sawspace = TRUE for command line
+ args when a line continuation character is hit to avoid causing
+ problems for existing sudoers files.
+ [fd930ad25550]
+
+ * plugins/sudoers/regress/sudoers/test4.in,
+ plugins/sudoers/regress/sudoers/test4.out.ok,
+ plugins/sudoers/regress/sudoers/test4.toke.ok:
+ Add test for line continuation and aliases
+ [29ab538ca6bb]
+
+ * plugins/sudoers/Makefile.in:
+ Make test output line up nicely for parse vs. toke
+ [257ef82c1434]
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/sudoers/test1.in,
+ plugins/sudoers/regress/sudoers/test1.out.ok,
+ plugins/sudoers/regress/sudoers/test1.toke.ok,
+ plugins/sudoers/regress/sudoers/test2.in,
+ plugins/sudoers/regress/sudoers/test2.out.ok,
+ plugins/sudoers/regress/sudoers/test2.toke.ok,
+ plugins/sudoers/regress/sudoers/test3.in,
+ plugins/sudoers/regress/sudoers/test3.out.ok,
+ plugins/sudoers/regress/sudoers/test3.toke.ok,
+ plugins/sudoers/regress/testsudoers/test1.ok,
+ plugins/sudoers/regress/testsudoers/test1.out.ok,
+ plugins/sudoers/regress/testsudoers/test1.sh,
+ plugins/sudoers/regress/testsudoers/test2.out,
+ plugins/sudoers/regress/testsudoers/test2.sh,
+ plugins/sudoers/regress/testsudoers/test3.ok,
+ plugins/sudoers/regress/testsudoers/test3.sh,
+ plugins/sudoers/regress/visudo/test1.ok,
+ plugins/sudoers/regress/visudo/test1.sh:
+ Move parser tests to sudoers directory and test the tokenizer output
+ too.
+ [44f529b3cdb6]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ If we match a rule anchored to the beginning of a line after parsing
+ a line continuation character, return an ERROR token. It would be
+ nicer to use REJECT instead but that substantially slows down the
+ lexer.
+ [355478293f8c]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.h,
+ plugins/sudoers/toke.l:
+ Move LEXTRACE macro to toke.h so we can use it in yyerror().
+ [72ee7a06d3ca]
+
+2011-03-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/testsudoers.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l:
+ Make lex tracing settable at run-time in testsudoers via the -t
+ flag. Trace output goes to stderr. Will be used by regress tests to
+ check lexer.
+ [93bd53c413c8]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Allow whitespace after the modifier in a Defaults entry. E.g.
+ "Defaults: username set_home"
+ [9dfcf8dd8a3a]
+
+2011-03-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg:
+ Don't set CC when cross-compiling.
+ [4b95b0c04e1c]
+
+ * NEWS:
+ Credit Matthew Thomas for the sudoers_search_filter changes.
+ [a65998ab09f7]
+
+ * MANIFEST:
+ Add the .sym files to the MANIFEST
+ [f599225cc861]
+
+ * NEWS:
+ Update for sudo 1.8.1 beta
+ [71021e854c49]
+
+ * doc/sudo_plugin.pod, plugins/sudoers/sudoers.c, src/parse_args.c:
+ user_shell -> run_shell to avoid confusion with the user's SHELL
+ variable.
+ [dc0ac6dafc21]
+
+ * src/exec_pty.c:
+ Save the controlling tty process group before suspending in pty
+ mode. Previously, we assumed that the child pgrp == child pid (which
+ is usually, but not always, the case).
+ [10b2883b7875]
+
+ * doc/sudoers.ldap.pod, plugins/sudoers/ldap.c:
+ Add support for sudoers_search_filter setting in ldap.conf. This can
+ be used to restrict the set of records returned by the LDAP query.
+ [b0f1b721d102]
+
+2011-03-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Remove the hack to disable -g in CFLAGS unless --with-devel
+ [89822cf84ef4]
+
+ * doc/sudoers.pod:
+ The '@' character does not normally need to be quoted.
+ [7823f5ed829a]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ We normaly transition from GOTDEFS to STARTDEFS on whitespace, but
+ if that whitespace is followed by a comma, we want to treat it as
+ part of a list and not transition.
+ [1ca6943e1824]
+
+ * plugins/sudoers/regress/testsudoers/test3.ok,
+ plugins/sudoers/regress/testsudoers/test3.sh:
+ Add check for whitespace when a User_List is used for a per-user
+ Defaults entry.
+ [91f75e6dd19a]
+
+ * plugins/sudoers/regress/testsudoers/test2.out,
+ plugins/sudoers/regress/testsudoers/test2.sh:
+ Expand quoted name checks to cover recent fixes.
+ [ce4f76bca146]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Fix parsing of double-quoted names in Defaultd and Aliases which was
+ broken in 601d97ea8792.
+ [424b0d6c1dc4]
+
+ * plugins/sudoers/Makefile.in:
+ toke_util.c lives in $(srcdir) not $(devdir)
+ [94866bebee83]
+
+2011-03-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Change trunk version to 1.8.x to distinguish from real 1.8.0.
+ [a9781e61d064]
+
+ * NEWS, doc/UPGRADE:
+ Document major changes in 1.8.1 and add upgrade notes.
+ [f2cf51b0d9ce]
+
+ * plugins/sudoers/match.c:
+ Be careful not to deref user_stat if it is NULL. This cannot
+ currently happen in sudo but might in other programs using the
+ parser.
+ [06a2334dd674]
+
+ * mkpkg:
+ configure will not add -O2 to CFLAGS if it is already defined to add
+ -O2 to the CFLAGS we pass in when PIE is being used.
+ [1ce6481ece59]
+
+ * doc/sudoers.pod:
+ Warn about the dangers of log_input and mention iolog_file and
+ iolog_dir in the log_input and log_output descriptions.
+ [ae854ffb0768]
+
+ * pp:
+ sync with git version
+ [a993e39ce3cb]
+
+ * doc/sudoers.pod:
+ It seems that h comes after i
+ [0f621109220d]
+
+ * doc/sudoers.pod:
+ Move log_input and log_output to their proper, sorted, location.
+ Document set_utmp and utmp_runas.
+ [273b234b9c34]
+
+ * src/exec.c:
+ Save the controlling tty process group before suspending so we can
+ restore it when we resume. Fixes job control problems on Linux
+ caused by the previous attemp to fix resuming a shell when I/O
+ logging not enabled.
+ [f03a660315ee]
+
+ * common/lbuf.c:
+ Fix printing of the remainder after a newline. Fixes "sudo -l"
+ output corruption that could occur in some cases.
+ [25d83fb501fc]
+
+2011-03-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, src/exec_pty.c,
+ src/sudo_exec.h, src/utmp.c:
+ Add support for ut_exit
+ [b574c13f1bba]
+
+ * doc/sudo_plugin.pod, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/sudoers.c, src/exec.c,
+ src/exec_pty.c, src/sudo.c, src/sudo.h, src/sudo_exec.h, src/utmp.c:
+ Add support for controlling whether utmp is updated and which user
+ is listed in the entry.
+ [44a81632133f]
+
+ * plugins/sudoers/def_data.h, plugins/sudoers/defaults.h,
+ plugins/sudoers/ldap.c, plugins/sudoers/mkdefaults,
+ plugins/sudoers/parse.c:
+ Fix typo; tupple vs. tuple
+ [697744acb710]
+
+ * src/utmp.c:
+ For legacy utmp, strip the /dev/ prefix before trying to determine
+ slot since the ttys file does not include the /dev/ prefix.
+ [7ad5b81ff90c]
+
+ * aclocal.m4, configure, configure.in, pathnames.h.in:
+ Add check for _PATH_UTMP
+ [21e638029bfd]
+
+2011-03-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/regress/iolog_path/check_iolog_path.c:
+ Adapt check_iolog_path to sessid changes
+ [728b5fe2be6f]
+
+ * config.h.in, configure, configure.in, src/Makefile.in,
+ src/exec_pty.c, src/sudo_exec.h, src/utmp.c:
+ Redo utmp handling. If no getutent()/getutxent() is available,
+ assume a ttyslot-based utmp. If getttyent() is available, use that
+ directly instead of ttyslot() so we don't have to do the stdin dup2
+ dance.
+ [18aa455cd140]
+
+2011-03-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, src/Makefile.in, src/exec_pty.c, src/sudo_exec.h,
+ src/utmp.c:
+ Move utmp handling into utmp.c
+ [f6eae6c8e012]
+
+ * common/aix.c, common/alloc.c, common/fileops.c, common/fmt_string.c,
+ common/lbuf.c, common/list.c, compat/isblank.c, compat/memrchr.c,
+ compat/mksiglist.c, compat/nanosleep.c, compat/snprintf.c,
+ compat/strlcat.c, compat/strlcpy.c, compat/strsignal.c,
+ compat/utimes.c, doc/sudo.pod, doc/visudo.pod,
+ include/sudo_plugin.h, plugins/sample/sample_plugin.c,
+ plugins/sample_group/getgrent.c, plugins/sample_group/plugin_test.c,
+ plugins/sudoers/alias.c, plugins/sudoers/auth/afs.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb4.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/passwd.c,
+ plugins/sudoers/auth/rfc1938.c, plugins/sudoers/auth/secureware.c,
+ plugins/sudoers/auth/securid.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/boottime.c,
+ plugins/sudoers/bsm_audit.c, plugins/sudoers/env.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/goodpath.c,
+ plugins/sudoers/logging.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h, plugins/sudoers/redblack.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/timestr.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/visudo.c, src/exec.c,
+ src/exec_pty.c, src/get_pty.c, src/parse_args.c, src/sudo.c,
+ src/sudo.h, src/sudo_edit.c, src/sudo_exec.h, src/sudo_noexec.c,
+ src/sudo_plugin_int.h, src/tgetpass.c:
+ Update copyright years.
+ [16aa39f9060a]
+
+ * doc/sudo_plugin.pod, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, src/parse_args.c:
+ Add "user_shell" boolean as a way to indicate to the plugin that the
+ -s flag was given.
+ [fb1ef0897b32]
+
+ * plugins/sudoers/iolog_path.c, plugins/sudoers/logging.c,
+ plugins/sudoers/sudoers.h:
+ Move sessid out of sudo_user.
+ [ba298ddb57f4]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/iolog_path.c,
+ plugins/sudoers/logging.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Log the TSID even if it is not a simple session ID.
+ [d7cc1b9c513c]
+
+ * doc/sample.sudo.conf, doc/sudo.pod, doc/sudoers.pod:
+ Document noexec in sample.sudo.conf and add back noexec_file section
+ in sudoers with a note that it is deprecated.
+ [4a6e961e494d]
+
+ * plugins/sudoers/set_perms.c:
+ Fix running commands as non-root on systems where setreuid() changes
+ the saved uid based on the effective uid we are changing to.
+ [df0769b71b34]
+
+2011-03-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/defaults.c, src/load_plugins.c, src/sudo.c,
+ src/sudo.h:
+ Move noexec path into sudo.conf now that sudo itself handles noexec.
+ Currently can be configured in sudoers too but is now undocumented
+ and will be removed in a future release.
+ [6fa8befdc110]
+
+ * doc/sudo.pod, doc/sudoers.pod:
+ Document "Path noexec ..." in sudo.conf. No longer document
+ noexec_file in sudoers, it will be removed in a future release.
+ [24eee3a0b3e5]
+
+ * plugins/sudoers/env.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, src/sudo.c, src/sudo.h:
+ Move noexec handling to sudo front-end where it is documented as
+ being.
+ [3ed4f10d7052]
+
+ * config.h.in, configure, configure.in, plugins/sudoers/sudoers.c,
+ src/exec.c, src/exec_pty.c, src/sudo.c, src/sudo.h, src/sudo_edit.c,
+ src/sudo_exec.h:
+ Add support for disabling exec via solaris privileges. Includes
+ preparation for moving noexec support out of sudoers and into front
+ end as documented.
+ [dec843ed553e]
+
+ * plugins/sample/Makefile.in, plugins/sample/sample_plugin.sym,
+ plugins/sample_group/Makefile.in,
+ plugins/sample_group/sample_group.sym, plugins/sudoers/Makefile.in,
+ plugins/sudoers/sudoers.sym:
+ Only export the symbols corresponding to the plugin structs.
+ [8d8d03b0ca54]
+
+ * configure, configure.in, plugins/sample/Makefile.in,
+ plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in:
+ Install plugins manually instead of using libtool. This works around
+ a problem on AIX where libtool will install a .a file containing the
+ .so file instead of the .so file itself.
+ [796971cfbddb]
+
+ * Makefile.in:
+ Move check into its own rule since some versions of make will run
+ both targets as the default rule.
+ [34d759979176]
+
+ * configure, ltmain.sh, m4/libtool.m4, m4/ltoptions.m4,
+ m4/ltversion.m4, m4/lt~obsolete.m4:
+ Update to libtool 2.2.10
+ [34c130de6af7]
+
+2011-03-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c:
+ In handle_signals(), restart the read() on EINTR to make sure we
+ keep up with the signal pipe. Don't return -1 on EAGAIN, it just
+ means we have emptied the pipe.
+ [d5b9c8eb9000]
+
+ * compat/mktemp.c:
+ Reorder functions to quiet a compiler warning.
+ [c9e9a23729f0]
+
+ * mkpkg:
+ Use the Sun Studio C compiler on Solaris if possible
+ [11a86e27891e]
+
+2011-03-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg:
+ Fix default setting of osversion variable.
+ [52e49ca1cedd]
+
+ * doc/sudo_plugin.pod:
+ Make two login_class entris consistent.
+ [18ff1fa94a91]
+
+ * config.h.in, configure, configure.in, src/exec.c, src/exec_pty.c,
+ src/sudo_exec.h:
+ Add support for adding a utmp entry when allocating a new pty.
+ Requires the BSD login(3) or SYSV/POSIX getutent()/getutxent().
+ Currently only creates a new entry if the existing tty has a utmp
+ entry.
+ [32db72b81d80]
+
+ * plugins/sudoers/boottime.c:
+ Avoid pulling in headers we don't need on Linux For getutx?id(),
+ call setutx?ent() first and always call endutx?ent().
+ [5dad21e1ee1b]
+
+ * configure, configure.in:
+ Add some more libs to SUDOERS_LIBS instead of relying on them to be
+ pulled in by SUDO_LIBS.
+ [18a7c21c09a7]
+
+ * plugins/sudoers/sudoers.c:
+ Fix return value of "sudo -l command" when command is not allowed,
+ broken in [c7097ea22111]. The default return value is now TRUE and a
+ bad: label is used when permission is denied. Also fixed missing
+ permissions restoration on certain errors. On error()/errorx(), the
+ password and group files are now closed before returning.
+ [4f2d0e869ae5]
+
+2011-03-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c:
+ Fix passing of login class back to sudo front end.
+ [6f70a784ce48]
+
+ * mkpkg:
+ Add --osversion flag to specify OS instead of running "pp
+ --probeonly"
+ [a8efdccb7bc1]
+
+ * sudo.pp:
+ Fix expr usage w/ GNU expr
+ [48895599ee63]
+
+2011-03-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ Fix exit value for validate and list mode.
+ [c7097ea22111]
+
+ * plugins/sudoers/sudoers.c:
+ Fix non-interactive mode with sudoers plugin.
+ [172f29597bd2]
+
+2011-03-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoreplay.pod:
+ sudoreplay can now find IDs other than %{seq} and display the
+ session.
+ [fc3dd3be67e9]
+
+2011-03-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c:
+ Add support for replaying sessions when iolog_file is set to
+ something other than %{seq}.
+ [ca3131243874]
+
+ * plugins/sudoers/visudo.c:
+ If we are killed by a signal, display the name of the signal that
+ got us.
+ [994bb76a990e]
+
+ * configure, configure.in:
+ Move libs used for authentication from SUDO_LIBS to SUDOERS_LIBS
+ where they belong.
+ [40f94b936fa4]
+
+ * configure.in:
+ Fix bug in skey/opie check that could cause a shell warning.
+ [83c043072be5]
+
+ * plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ No longer need sudo_getepw() stubs.
+ [bbee15c36912]
+
+2011-03-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudo_nss.c:
+ Fix exit value of "sudo -l command" in sudoers module.
+ [a6541867521b]
+
+2011-03-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/regress/glob/globtest.c:
+ Use fgets() not fgetln() for portability.
+ [df1bb67fb168]
+
+ * sudo.pp:
+ Don't use the beta or release candidate version as the rpm release.
+ [d661ef78021a]
+
+2011-02-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ version 1.8.0
+ [f6530d56f6ae] [SUDO_1_8_0]
+
+ * NEWS:
+ update sudo 1.8 section
+ [f2ee2cf95d18]
+
+2011-02-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/regress/testsudoers/test2.sh:
+ fix test description
+ [cd5730fa9f09]
+
+ * plugins/sudoers/regress/testsudoers/test2.out,
+ plugins/sudoers/regress/testsudoers/test2.sh,
+ plugins/sudoers/regress/visudo/test2.out,
+ plugins/sudoers/regress/visudo/test2.sh:
+ convert test2 to use testsudoers
+ [b5ec3f0b69f1]
+
+ * include/sudo_plugin.h, src/sudo_plugin_int.h:
+ Move struct generic_plugin to sudo_plugin_int.h
+ [6f7bc629329c]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/parse.c, plugins/sudoers/parse.h,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Allow sudoers file name, mode, uid and gid to be specified in the
+ settings list. The sudo front end does not currently set these but
+ may in the future.
+ [22f38a0fda2a]
+
+2011-02-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in, doc/sudo.cat, doc/sudo.man.in,
+ doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudoers.cat,
+ doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in, doc/sudoers.man.in,
+ doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/visudo.cat,
+ doc/visudo.man.in:
+ 1.8.0rc1
+ [5d4588b9c057]
+
+ * doc/sudo.pod, doc/sudoreplay.pod, doc/visudo.pod,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/visudo.c,
+ src/parse_args.c, src/sudo.h:
+ add help text to sudo, visudo and sudoreplay for the -h option
+ [52e7378d8476]
+
+2011-02-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/snprintf.c:
+ avoid using "howmany" for a parameter name since it is a select-
+ related macro
+ [a14d565401a1]
+
+ * doc/sudoers.pod:
+ mention group_plugin when describing nonunix_group
+ [e0d1d0034b17]
+
+ * doc/sudo_plugin.pod:
+ Add missing period at end of sentence
+ [6744d7e9056d]
+
+ * Makefile.in, doc/Makefile.in, include/Makefile.in,
+ plugins/sample/Makefile.in, plugins/sample_group/Makefile.in,
+ plugins/sudoers/Makefile.in, src/Makefile.in:
+ add localstatedir; closes bug 471
+ [7aefcab85088]
+
+ * config.h.in, configure, configure.in, plugins/sudoers/sudoreplay.c,
+ src/exec.c, src/exec_pty.c:
+ The howmany macro lives in sys/sysmacros.h on SVR5 systems Closes
+ Bug 470
+ [927ed6740f32]
+
+ * configure.in:
+ add missing AH_TEMPLATE for ENV_RESET
+ [16300010c986]
+
+ * src/exec.c:
+ SVR5 systems return non-zero for success on socketpair(), check for
+ -1 instead. Closes Bug 469
+ [4d276494bf8e]
+
+2011-02-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ 1.8.0b5
+ [d611cd5d73d3]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo_plugin.cat,
+ doc/sudo_plugin.man.in, doc/sudoers.cat, doc/sudoers.ldap.cat,
+ doc/sudoers.ldap.man.in, doc/sudoers.man.in, doc/sudoreplay.cat,
+ doc/sudoreplay.man.in, doc/visudo.cat, doc/visudo.man.in:
+ regen
+ [85e96eeaed82]
+
+ * doc/sudo.pod:
+ Document that a sudo.conf file with no Pligin lines uses the default
+ sudoers plugins.
+ [88bd52da977f]
+
+ * src/load_plugins.c:
+ If sudo.conf contains no Plugin lines, use the default sudoers
+ policy and I/O plugins.
+ [fd8f4cb811ab]
+
+2011-02-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudo_nss.c:
+ Avoid printing empty "Runas and Command-specific defaults for user"
+ line.
+ [2dd330fe4f8b]
+
+ * common/lbuf.c:
+ Truncate the buffer at buf.len before printing in the non-wordwrap
+ case.
+ [901e9833f80d]
+
+ * common/lbuf.c:
+ Remove extra newline when the tty width is very small or unavailable
+ [245c05506c0e]
+
+2011-02-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/alias.c:
+ Remove unneeded variable.
+ [2c086d30b796]
+
+2011-02-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Prefer getutxid over getutid
+ [3f3322e9c93e]
+
+ * plugins/sudoers/boottime.c:
+ Include utmp.h / utmpx.h before missing.h as apparently including it
+ afterwards causes a compilation problem on GNU Hurd.
+ [a528029ae962]
+
+2011-02-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c, plugins/sudoers/toke_util.c:
+ #include "foo.h", not <foo.h> for local includes.
+ [f65ec693998e]
+
+ * src/parse_args.c:
+ remove bogus XXX
+ [9136c17d53ce]
+
+ * compat/mksiglist.c:
+ Fix typo
+ [1a3bb7b455c9]
+
+ * compat/glob.c, plugins/sudoers/ldap.c, plugins/sudoers/logging.c,
+ plugins/sudoers/match.c:
+ return foo not return(foo)
+ [5c9e0647359a]
+
+2011-02-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c:
+ Remove duplicate FD_SET of signal_pipe[0]
+ [3096527d2215]
+
+2011-02-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/mksiglist.c:
+ Use "missing.h" not <missing.h> in generated code.
+ [d8e09cffbe09]
+
+2011-02-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aclocal.m4, configure:
+ fix --with-iologdir=no
+ [a89699cb5f5f]
+
+ * aclocal.m4, configure:
+ fix typo that broke --with-iologdir
+ [91b54eb22403]
+
+2011-02-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in, doc/sudo.cat, doc/sudo.man.in,
+ doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudoers.cat,
+ doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in, doc/sudoers.man.in,
+ doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/visudo.cat,
+ doc/visudo.man.in:
+ Bump version to 1.8.0b4
+ [e2b7f2cdc02e]
+
+ * NEWS:
+ sync
+ [decf5a0a8a33]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod:
+ Attempt to clarify how users and groups interact in Runas_Specs
+ [e6fb3a2dbd77]
+
+ * plugins/sudoers/regress/visudo/test2.out,
+ plugins/sudoers/regress/visudo/test2.sh:
+ Add test for quoted group that contains escaped double quotes
+ [44596c48c629]
+
+ * src/exec.c, src/exec_pty.c:
+ Pass SIGUSR1/SIGUSR2 through to the child.
+ [c3108a827b01]
+
+ * src/exec_pty.c, src/sudo_exec.h:
+ Use special values SIGCONT_FG and SIGCONT_BG instead of SIGUSR1 and
+ SIGUSR2 to indicate whether the child should be continued in the
+ foreground or background.
+ [35ca47cc6785]
+
+ * src/exec.c:
+ Use pid_t not int and check the return value of kill()
+ [36ae7d37d7f9]
+
+2011-02-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c:
+ Remove obsolete comment
+ [baebef4919f6]
+
+ * src/exec.c:
+ In non-pty mode before continuing the child, make it the foreground
+ pgrp if possible. Fixes resuming a shell.
+ [fef5b1d02ddb]
+
+ * src/exec_pty.c:
+ If we get a signal other than SIGCHLD in the monitor, pass it
+ directly to the child.
+ [b3ecb28163a0]
+
+ * src/exec.c, src/exec_pty.c, src/sudo.h:
+ Save signal state before changing handlers and restore before we
+ execute the command.
+ [faf7475dc4bf]
+
+2011-02-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ Use a char array to map a number to a base36 digit.
+ [257576c51f8b]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in, doc/sudoers.ldap.pod:
+ Be clear about what versions of sudo support new LDAP attributes.
+ Fix up some formatting of attribute names. Minor other tweaks.
+ [39f65df71f65]
+
+2011-01-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ match quoted strings the same way whether in a Defaults line or as a
+ user/group/netgroup name. Fixes escaped double quotes in quoted
+ user/group/netgroup names.
+ [601d97ea8792]
+
+ * plugins/sudoers/Makefile.in:
+ 'make check' depends on visudo and testsudoers
+ [127c5a24df8f]
+
+ * plugins/sudoers/sudoers2ldif:
+ Add sudoOrder attribute to each entry Parse LOG_{INPUT,OUTPUT} tags
+ [9029163a58c3]
+
+2011-01-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/UPGRADE:
+ Mention LDAP attribute compatibility status.
+ [2c3595aaec63]
+
+2011-01-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * README.LDAP:
+ Mention phpQLAdmin
+ [9304c9064fbe]
+
+ * INSTALL, NEWS, config.h.in, configure, configure.in,
+ doc/sudoers.man.in, doc/sudoers.pod, plugins/sudoers/defaults.c:
+ Add --disable-env-reset configure option.
+ [8a753aa13a46]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod:
+ Document that sudoers_locale also affects logging and email.
+ [998d6ac11277]
+
+ * NEWS, config.h.in, configure, configure.in,
+ plugins/sudoers/logging.c:
+ Do logging and email sending in the locale specified by the
+ "sudoers_locale" setting ("C" by default). Email send by sudo
+ includes MIME headers when the sudoers locale is not "C".
+ [cb7e55408400]
+
+2011-01-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c:
+ Fix indentation
+ [65ae7e92b9e4]
+
+2011-01-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, src/parse_args.c, src/sudo.c:
+ Perform command escaping for "sudo -s" and "sudo -i" after
+ validating sudoers so the sudoers entries don't need to have all the
+ backslashes.
+ [4e168c103f4b]
+
+2011-01-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/logging.c:
+ Prepend "list " to the command logged when "sudo -l command" is used
+ to make it clear that the command was listed, not run.
+ [f392a6056cd6]
+
+ * plugins/sudoers/parse.c:
+ cosmetic change
+ [7c0951dbc2dd]
+
+ * common/aix.c, common/alloc.c, common/fileops.c, common/fmt_string.c,
+ common/list.c, common/term.c, compat/fnmatch.c, compat/getcwd.c,
+ compat/glob.c, compat/isblank.c, compat/memrchr.c, compat/mktemp.c,
+ compat/nanosleep.c, compat/regress/glob/globtest.c,
+ compat/snprintf.c, compat/strlcat.c, compat/strlcpy.c,
+ compat/strsignal.c, compat/utimes.c, plugins/sample/sample_plugin.c,
+ plugins/sample_group/getgrent.c, plugins/sample_group/plugin_test.c,
+ plugins/sudoers/alias.c, plugins/sudoers/auth/afs.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb4.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/passwd.c,
+ plugins/sudoers/auth/rfc1938.c, plugins/sudoers/auth/secureware.c,
+ plugins/sudoers/auth/securid.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/bsm_audit.c,
+ plugins/sudoers/check.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/goodpath.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/match.c, plugins/sudoers/mon_systrace.c,
+ plugins/sudoers/parse.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/redblack.c, plugins/sudoers/set_perms.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timestr.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/toke_util.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/visudo.c,
+ src/exec_pty.c, src/get_pty.c, src/load_plugins.c, src/parse_args.c,
+ src/sudo_noexec.c, src/tgetpass.c:
+ standardize on "return foo;" rather than "return(foo);" or "return
+ (foo);"
+ [32d76c5aaf8c]
+
+ * plugins/sudoers/sudoers.c:
+ Do not reject sudoers file just because it is root-writable.
+ [0febc579185b]
+
+2011-01-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ sync
+ [1ab03f8278ff]
+
+ * plugins/sudoers/sudo_nss.c:
+ For "sudo -U user -l" if user is not authorized on the host, say so.
+ [289afe6dd15c]
+
+ * plugins/sudoers/ldap.c:
+ In sudo_ldap_lookup(), always do the initial sudoers check as the
+ invoking user. If we are listing another user's privs we will do a
+ separate lookup using list_pw later.
+ [e52bc15de76d]
+
+2011-01-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST:
+ add parser fill tests
+ [4f65140d3515]
+
+ * compat/regress/glob/globtest.c, compat/regress/glob/globtest.in:
+ Don't test features not supported by the bundled glob()
+ [8ec7ace11949]
+
+ * Makefile.in, aclocal.m4, common/Makefile.in, common/term.c,
+ compat/Makefile.in, configure.in, doc/LICENSE, doc/Makefile.in,
+ doc/sudo_plugin.man.in, doc/sudo_plugin.pod,
+ doc/sudoers.ldap.man.in, doc/sudoers.ldap.pod, doc/sudoers.man.in,
+ doc/sudoers.pod, include/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/sudoers/check.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_path.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/match.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c, src/Makefile.in, zlib/Makefile.in:
+ Update copyright year to 2011
+ [ac1b45cb1809]
+
+ * plugins/sudoers/sudo_nss.c:
+ When listing, use separate lbufs for the defaults and the privileges
+ and only print something if the number of privileges is non-zero.
+ Fixes extraneous Defaults output for "sudo -U unauthorized_user -l".
+ [d0854d39f8ef]
+
+ * plugins/sudoers/ldap.c:
+ Stash pointer to user group vector in LDAP handle and only reuse the
+ query if it has not changed. We always allocate a new buffer when we
+ reset the group vector so a simple pointer check is sufficient.
+ [88861d4eba69]
+
+ * plugins/sudoers/sudo_nss.c:
+ Check initgroups() return value.
+ [3bdaf58408a7]
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/parser/check_fill.c:
+ Add tests for the fill functions in toke_util.c
+ [bca587ab4956]
+
+2011-01-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/regress/iolog_path/check_iolog_path.c:
+ fix copyright year
+ [e2038cdaf055]
+
+ * NEWS:
+ sync
+ [56ca5d5eaebe]
+
+2011-01-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/term.c:
+ Clear, don't set, OPOST in c_oflag as was intended in 506ad5ae9b4e.
+ [b91f266624ec]
+
+2011-01-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg, sudo.pp:
+ Add Requires line for audit-libs >= 1.4 for RHEL5+
+ [6c02f976171b]
+
+ * pp:
+ sync with git version
+ [d301c32d5865]
+
+2011-01-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod:
+ fix typo
+ [39353f92976f]
+
+2011-01-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Update for sudo 1.7.4p5
+ [b444da76901f]
+
+ * doc/schema.OpenLDAP, doc/schema.iPlanet:
+ Add sudoNotBefore and sudoNotAfter attributes as optional attributes
+ to the sudoRole object class. From Andreas Mueller
+ [dacfad7e7a95]
+
+2011-01-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS:
+ Mention "sudo -g group" password check fix.
+ [1eb8fb14e53b]
+
+ * plugins/sudoers/sudoers.c:
+ Fix "sudo -g" support in the sudoers module.
+ [07d1b0ce530e]
+
+ * plugins/sudoers/check.c:
+ If the user is running sudo as himself but as a different group we
+ need to prompt for a password.
+ [caf1fcc9a117]
+
+2011-01-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * NEWS, config.h.in, configure, configure.in, doc/sudoers.ldap.cat,
+ doc/sudoers.ldap.man.in, doc/sudoers.ldap.pod,
+ plugins/sudoers/ldap.c:
+ Add support for TIMEOUT in ldap.conf, mapping to the OpenLDAP
+ LDAP_OPT_TIMEOUT. There is no corresponding option for mozilla-
+ derived LDAP SDKs but we can pass the timeout parameter to
+ ldap_search_ext_s() or ldap_search_st() when possible.
+ [5537049991f7]
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in:
+ regen
+ [5b361c3c4324]
+
+ * NEWS, doc/sudoers.ldap.pod, plugins/sudoers/ldap.c:
+ Add NETWORK_TIMEOUT as an alias for BIND_TIMELIMIT for compatibility
+ with OpenLDAP ldap.conf files.
+ [e97843bd16fb]
+
+ * plugins/sudoers/pwutil.c:
+ If user has no supplementary groups, fall back on checking the group
+ file expliticly.
+ [5223ad4eb690]
+
+2011-01-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/toke.h, plugins/sudoers/toke_util.c:
+ constify
+ [6e132a4cca61]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.h,
+ plugins/sudoers/toke.l:
+ Move fill macro to toke.h
+ [623d430798cf]
+
+ * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.h, plugins/sudoers/toke.l,
+ plugins/sudoers/toke_util.c:
+ Split tokenizer utility functions out into toke_util.c
+ [89a97bd51618]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ ANSIfy
+ [ca0eba1dfaa9]
+
+2011-01-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST:
+ sync
+ [a43f94064bb3]
+
+ * plugins/sudoers/Makefile.in:
+ Add visudo tests to check target
+ [8c82fb4ed40f]
+
+ * compat/Makefile.in, compat/regress/fnmatch/fnm_test.c,
+ compat/regress/fnmatch/fnm_test.in, compat/regress/glob/files,
+ compat/regress/glob/globtest.c, compat/regress/glob/globtest.in:
+ Add my regress tests for fnmatch() and glob() from OpenBSD.
+ [6e8c1f211723]
+
+ * plugins/sudoers/regress/testsudoers/test1.sh,
+ plugins/sudoers/regress/visudo/test1.ok,
+ plugins/sudoers/regress/visudo/test1.sh:
+ Add regress test for command tags using visudo -c
+ [18b0ef207c0f]
+
+ * plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/testsudoers/test1.ok,
+ plugins/sudoers/regress/testsudoers/test1.sh:
+ Add support for regress tests using testsudoers
+ [1fa94bd2671b]
+
+ * plugins/sudoers/testsudoers.c:
+ Need to set user_name explicitly due to internal changes made when
+ converting sudoers to a plugin.
+ [1fa54e86a364]
+
+2011-01-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, Makefile.in, common/Makefile.in, compat/Makefile.in,
+ doc/Makefile.in, include/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/sudoers/regress/iolog_path/check_iolog_path.c,
+ plugins/sudoers/regress/iolog_path/data, src/Makefile.in,
+ zlib/Makefile.in:
+ Add regression tests for iolog_path()
+ [afa4b416e559]
+
+ * Makefile.in, common/Makefile.in, compat/Makefile.in,
+ doc/Makefile.in, include/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in,
+ src/Makefile.in, zlib/Makefile.in:
+ Add support for "make Makefile" to regenerate Makefile from
+ Makefile.in
+ [98bd2dda3294]
+
+ * plugins/sudoers/iolog_path.c:
+ Quiest a bogus compiler warning.
+ [5ff932a7ad67]
+
+2011-01-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog_path.c:
+ Protect call to setlocale() with HAVE_SETLOCALE
+ [2c29ee3ccc81]
+
+2011-01-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST:
+ mkstemps.c was renamed mktemp.c
+ [ae299c3b1827]
+
+ * NEWS:
+ Update from 1.7 branch
+ [20817d79717b]
+
+ * Makefile.in:
+ Use "mv -f" when regenerating ChangeLog
+ [c163635206c6]
+
+ * plugins/sudoers/match.c:
+ Fix NULL dereference with "sudo -g group" when the sudoers rule has
+ no runas user or group listed. Fixes RedHat bug Bug 667103.
+ [41a6a1243d9e]
+
+2011-01-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod:
+ Correct the default sudo.conf example
+ [4e791698cad1]
+
+2010-12-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog_path.c:
+ Reset slashp if we allocate a new buffer for strftime()
+ [e491daa4203b]
+
+ * plugins/sudoers/iolog_path.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Add extra out parameter to expand_iolog_path() to allow the caller
+ to split the path into dir and file components if needed.
+ [88346bc5ae39]
+
+2010-12-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ mkdir_iopath() returns size_t now that it uses strlcpy() and not
+ snprintf()
+ [3c4c64d265eb]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/iolog_path.c:
+ Trim leading slashes from iolog_file and trailing slashes from
+ iolog_dir
+ [a803b51f8948]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod,
+ plugins/sudoers/iolog.c, plugins/sudoers/iolog_path.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Pass a single I/O log file name in command_details instead of
+ separate dir + file parameters.
+ [d672a3e46e80]
+
+ * plugins/sudoers/sudoreplay.c:
+ change an error() to errorx()
+ [8013dcfdd69d]
+
+ * plugins/sudoers/iolog.c:
+ Add missing cwd line to I/O log info file that got dropped when
+ iolog_deserialize_info() was added
+ [7cf84f208423]
+
+2010-12-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ Avoid relying on globals filled in by the sudoers policy module for
+ the sudoers I/O log module. The I/O log open function now pulls the
+ bits it needs out of user_info and command_info.
+ [c02f6951b0cc]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ If no iolog file is specified by the policy plugin, use io_nextid()
+ to determine the next file in the sequence.
+ [faa1130b1020]
+
+2010-12-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod:
+ Document iolog_compress in command_info
+ [58895c7d12f5]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c:
+ Add support for the iolog_compress variable in command_info.
+ [36f13a2fd1c1]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c:
+ Add sigsetjmp() calls to all plugin entry points just to be safe.
+ [3fa482355bc4]
+
+ * src/sudo.c, src/sudo.h:
+ Don't need iolog variables in struct command_details, they are for
+ the I/O log plugins to handle.
+ [5111579ffd9d]
+
+2010-12-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod:
+ Document use of mkdtemp() for iolog path teplates
+ [5db6101408a9]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo_plugin.cat,
+ doc/sudo_plugin.man.in, doc/sudoers.cat, doc/sudoers.ldap.cat,
+ doc/sudoers.ldap.man.in, doc/sudoers.man.in, doc/sudoreplay.cat,
+ doc/sudoreplay.man.in, doc/visudo.cat, doc/visudo.man.in:
+ regen
+ [1ee11fd6d4eb]
+
+ * doc/sudo_plugin.pod, doc/sudoers.pod:
+ Document iolog_file and supported escape sequences for sudoers.
+ Clarify that iolog_file can contain directories.
+ [da611dedcbdb]
+
+ * compat/Makefile.in, configure, configure.in:
+ Fix building of mkstemps/mkdtemp replacements.
+ [793a5e303122]
+
+ * compat/mkstemps.c, compat/mktemp.c, config.h.in, configure,
+ configure.in, include/missing.h:
+ Provide mkdtemp() for systems without it.
+ [b0527dfa965c]
+
+ * plugins/sudoers/iolog_path.c:
+ Fix typo
+ [277f6c514cba]
+
+ * plugins/sudoers/iolog.c:
+ Only use mkdtemp() if the path ends in at least 6 Xs since otherwise
+ glibc mkdtemp() returns EINVAL.
+ [2e7323b05579]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/iolog_path.c, plugins/sudoers/plugin_error.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Allow sudoers to specify the iolog file in addition to the iolog
+ dir. Add escape sequence support to iolog file and dir: sequence
+ number, user, group, runas_user, runas_group, hostname and command
+ in addition to any escape sequence recognized by strftime(3).
+ [75cd32ee0435]
+
+ * plugins/sudoers/iolog.c:
+ Add missing sigsetjmp() call in I/O plugin open function. Fixes a
+ crash when the I/O plugin calls error(), errorx() or log_error().
+ [1a6718bd817d]
+
+2010-12-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo_plugin.pod, plugins/sudoers/iolog.c,
+ plugins/sudoers/sudoers.c:
+ Give the policy module fine-grained control over what the I/O plugin
+ logs.
+ [d29784fd2a66]
+
+ * common/term.c:
+ Clear OPOST from c_oflag like we used to. Fixes screen-based editors
+ such as vi.
+ [506ad5ae9b4e]
+
+ * doc/sudoers.pod:
+ Clarify umask option description. From Reuben Thomas.
+ [1294ac84222b]
+
+2010-12-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.ldap.pod, plugins/sudoers/ldap.c:
+ Pick last match in LDAP sudoers too
+ [fbfd8e85703b]
+
+ * doc/sudo_plugin.pod:
+ Document iolog_file, iolog_dir and use_pty
+ [26120a59c20e]
+
+ * plugins/sample/sample_plugin.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/sudoers.c:
+ Adapt plugins to version I/O logging ABI 1.1
+ [880dd64bc1e8]
+
+ * src/exec.c, src/sudo.h:
+ Add use_pty command_info flag for policies to indicate that a pty
+ should be allocated even if no I/O logging is performed.
+ [e7b167f8a6e5]
+
+ * src/sudo.c:
+ Add remaining plugin convenience functions
+ [ffeaf96da031]
+
+ * include/sudo_plugin.h, src/sudo.c, src/sudo.h,
+ src/sudo_plugin_int.h:
+ Change I/O log API to pass in command info to the I/O log open
+ function. Add iolog_file and iolog_dir parameters to command info.
+ This allows the policy plugin to specify the I/O log pathname. Add
+ convenience functions for calling plugin functions that handle ABI
+ backwards compatibility.
+ [9b81dce76ce5]
+
+ * compat/dlopen.c:
+ Remove useless cast
+ [7cecce969739]
+
+2010-12-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Bump version to 1.8.0b3
+ [1dc9f040aae0]
+
+2010-12-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ Remove extraneous newline
+ [71c94551eea5]
+
+2010-12-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.pod, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/iolog.c:
+ Make I/O log dir configurable.
+ [99b576667a38]
+
+ * aclocal.m4, configure, configure.in, doc/sudoers.pod:
+ Rename io_logdir to iolog_dir
+ [0731662acc8d]
+
+2010-12-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pp:
+ Add missing '*' that prevented the generic ELF case from matching.
+ [be77ca26bfb2]
+
+ * pp:
+ If file(1) can't identify the ELF binary type, try readelf(1).
+ [38a18d32a9e3]
+
+2010-11-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/kerb4.c, plugins/sudoers/check.c,
+ plugins/sudoers/env.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/sudoers.c, src/sudo.c:
+ Use %u to print uid/gid, not %lu and adjust casts to match.
+ [03c43b8749cf]
+
+ * doc/sudoers.ldap.pod:
+ Clarify ordering of entries and attributes.
+ [924e2a6bb603]
+
+ * doc/sudoers.ldap.pod:
+ Fix typo and editing goof.
+ [79dc7ccd85a8]
+
+ * doc/schema.ActiveDirectory, doc/schema.OpenLDAP, doc/schema.iPlanet,
+ doc/sudoers.ldap.pod:
+ Merge in ordered LDAP entry support from Andreas Mueller.
+ [ea5885989bad]
+
+ * plugins/sudoers/ldap.c:
+ Make sure we don't dereference a NULL handle.
+ [1a9f9ee15371]
+
+2010-11-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pp:
+ Add support for RHEL 6 file modes that include a trailing dot on
+ files with an SELinux security context
+ [dc09be959547]
+
+2010-11-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo.c:
+ exec_setup() does not need to setuid(0), the Ubuntu issue was in the
+ sudoers module.
+ [d6dd99fc6062]
+
+ * plugins/sudoers/sudoers.c:
+ create_admin_success_flag() should use restore_perms() rather than
+ set_perms() to restore the uid.
+ [eba7a91c1f57]
+
+ * src/sudo.c:
+ In exec_setup() call setuid(0) to make certain the subsequent uid
+ and gid changes will succeed. Fixes a problem on Ubuntu.
+ [c5d32abf0645]
+
+ * src/sudo_edit.c:
+ Error out if we cannot change to root's uid so we catch the failure
+ early.
+ [7a2e7f8f2c80]
+
+2010-11-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.pod:
+ fix typo; from Michael T Hunter
+ [a574a9d0db5b]
+
+ * plugins/sudoers/match.c:
+ In sudoedit mode, assume command line arguments are paths and pass
+ FNM_PATHNAME to fnmatch().
+ [ce0abff8ce9f]
+
+2010-11-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Add workaround for an error in sys/types.h on HP-UX 11.23 when large
+ file support is enabled. Defining _XOPEN_SOURCE_EXTENDED avoids the
+ broken bits of the header file.
+ [e337217f097a]
+
+ * aclocal.m4:
+ Fix SUDO_MAILDIR usage of AC_LANG_PROGRAM
+ [fbbcee28961f]
+
+ * sudo.pp:
+ For Tru64, strip off beta version.
+ [eeccd762df5e]
+
+ * MANIFEST, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/tsgetgrpw.h:
+ Avoid conflicts with system definitions in grp.h and pwd.h
+ [b219ffe1da09]
+
+ * zlib/gzguts.h:
+ Include stdio.h after zlib.h, not before. We need the large file
+ defines to come first.
+ [21d6df39790f]
+
+2010-11-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in:
+ regen
+ [3ff8750d0aac]
+
+ * Makefile.in:
+ Don't clean ChangeLog
+ [ab0d30d289d4]
+
+ * plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Add prototype for cleanup()
+ [75626fd3769a]
+
+2010-11-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/group_plugin.c:
+ Avoid deferencing group_plugin if it is NULL in
+ group_plugin_query(). This should not happen.
+ [4f2933c8da7e]
+
+ * plugins/sudoers/group_plugin.c:
+ group plugin init function return TRUE when successful
+ [198024477030]
+
+2010-11-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Enlarge the array of entry wrappers int blocks of 100 entries to
+ save on allocation time. From Andreas Mueller
+ [375c916bb03b]
+
+ * plugins/sudoers/ldap.c:
+ Add back call to sudo_ldap_timefilter() in sudo_ldap_build_pass2()
+ that was mistakenly dropped.
+ [1555f5bc132d]
+
+2010-11-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/TROUBLESHOOTING:
+ Mention that sudo needs "ar" to build.
+ [65582ace2d09]
+
+ * configure, configure.in:
+ Fail with a more useful error if "ar" is not found.
+ [d1cb83719c17]
+
+2010-11-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Merge in ordered LDAP entry support from Andreas Mueller and add
+ local changes from the 1.7 branch.
+ [bca29e461618]
+
+2010-11-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/schema.ActiveDirectory, doc/schema.OpenLDAP, doc/schema.iPlanet,
+ doc/sudoers.ldap.pod, plugins/sudoers/ldap.c:
+ Add timed entry support from Andreas Mueller.
+ [e18d1df46a8d]
+
+ * plugins/sudoers/group_plugin.c:
+ Don't try to unload if group_plugin is NULL. Don't call dlclose() if
+ group_handle is NULL
+ [de2273da37d5]
+
+ * plugins/sudoers/sudoers.h:
+ It is now plugin_cleanup(), not cleanup()
+ [da62a4e1a78c]
+
+ * plugins/sudoers/logging.c, plugins/sudoers/sudoers.c:
+ Call plugin_cleanup(), not cleanup()
+ [e800ad8b33ad]
+
+2010-11-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Use efree() not free() and remove malloc.h include since we never
+ directly call malloc() or free().
+ [107fffd134bb]
+
+2010-11-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ set PSTAMP for Solaris and move the backend-specific bits to their
+ own %if [xxx] %endif blocks in %set.
+ [a94ebe8920c1]
+
+ * pp:
+ sync with git repo
+ [75ff509696b4]
+
+ * configure, configure.in:
+ Only substitute file zlib files when using the builtin zlib
+ [6c8145b2deb4]
+
+ * common/Makefile.in, compat/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in,
+ src/Makefile.in, zlib/Makefile.in:
+ Give up on using VPATH to find sources as it is implemented
+ inconsistenly in different versions of make.
+ [60517c69aaee]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/getdate.c,
+ plugins/sudoers/gram.c, plugins/sudoers/toke.c:
+ Include config.h before any other includes to make sure we get the
+ right value for _FILE_OFFSET_BITS.
+ [8fb007ca832e]
+
+ * MANIFEST:
+ Add zlib
+ [04a3e23dfaa9]
+
+ * zlib/Makefile.in:
+ Add missing targets
+ [40e45a177168]
+
+ * src/Makefile.in:
+ g/c unused $(GENERATED)
+ [c8758068c1bc]
+
+2010-11-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/group_plugin.c:
+ Zero out group_plugin on unload just to be safe.
+ [0b10f4d101ca]
+
+ * plugins/sudoers/group_plugin.c:
+ Unload group plugin if its init function fails.
+ [6552cdac4b7c]
+
+ * src/sudo.c:
+ Only chdir to cwd if it is different from the current cwd or there
+ is a new root (chroot).
+ [b8203e875e84]
+
+ * configure, configure.in, doc/sudo.cat, doc/sudo.man.in,
+ doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudoers.ldap.cat,
+ doc/sudoers.ldap.man.in, doc/visudo.cat, doc/visudo.man.in:
+ Bump version to 1.8.0b2
+ [6dadeb75a878]
+
+2010-10-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ Better --enable-zlib description
+ [e0da54fa59a6]
+
+ * mkpkg:
+ Use system zlib on Linux Let configure decide on Solaris For all
+ others, use builtin zlib
+ [3d52eddb523c]
+
+ * zlib/zconf.h.in:
+ Add large file support.
+ [bec01215270d]
+
+ * config.h.in:
+ Add large file support.
+ [244e95b034ec]
+
+ * Makefile.in, configure, configure.in, doc/LICENSE, doc/license.pod,
+ zlib/Makefile.in, zlib/adler32.c, zlib/compress.c, zlib/crc32.c,
+ zlib/crc32.h, zlib/deflate.c, zlib/deflate.h, zlib/gzclose.c,
+ zlib/gzguts.h, zlib/gzlib.c, zlib/gzread.c, zlib/gzwrite.c,
+ zlib/infback.c, zlib/inffast.c, zlib/inffast.h, zlib/inffixed.h,
+ zlib/inflate.c, zlib/inflate.h, zlib/inftrees.c, zlib/inftrees.h,
+ zlib/trees.c, zlib/trees.h, zlib/uncompr.c, zlib/zconf.h.in,
+ zlib/zlib.h, zlib/zutil.c, zlib/zutil.h:
+ Add local copy of zlib for systems that lack it.
+ [7542ca465c5a]
+
+2010-10-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c:
+ If perform_io() fails, kill the child before exiting so it doesn't
+ complain about connection reset. We can get an I/O error if, for
+ example, and we get EIO reading from stdin.
+ [e59a05fa729f]
+
+2010-10-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c, src/sudo.c:
+ Fix complilation on systems with set_auth_parameters() Sprinkle
+ volatile to quiet warnings from gcc 2.8.0
+ [a34c2b924ba7]
+
+ * compat/dlfcn.h, compat/dlopen.c:
+ Avoid potential namespace issues with dlopen() emulation.
+ [aedfababd6ca]
+
+ * MANIFEST:
+ sync
+ [6afb97e6d308]
+
+ * plugins/sudoers/interfaces.c:
+ Use INADDR_NONE instead of casting -1 to in_addr_t (which may not
+ exist).
+ [ddfca5af1a36]
+
+ * Makefile.in:
+ Mark ChangeLog as PHONY Don't overwrite ChangeLog if we can't run hg
+ [e9d04bfa4505]
+
+ * configure, configure.in:
+ HP-UX 10.20 libc has an incompatible getline
+ [2e7bc202e78d]
+
+ * plugins/sudoers/visudo.c:
+ Quiet an HP-UX compiler warning.
+ [55b9d587ac8c]
+
+ * configure, configure.in:
+ Check for vi even with --with-editor specified; the sample plugin
+ needs it.
+ [94dfc3643f76]
+
+2010-10-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/dlopen.c:
+ Fix remaining syntax errors.
+ [9d729b5b577e]
+
+ * src/Makefile.in:
+ sudo binary depends on the libtool-generated libs
+ [9e6148406adb]
+
+ * plugins/sudoers/group_plugin.c, src/load_plugins.c:
+ Use HAVE_DLOPEN instead of HAVE_DLFCN_H when determining whether to
+ include the local or system dlfcn.h
+ [68cfe4c1089b]
+
+ * pp:
+ Don't use run_as_superuser=false on HP-UX
+ [532242370b09]
+
+ * src/net_ifs.c:
+ Use memset() instead of zero_bytes() since we don't include
+ sudoers.h
+ [a187c18c2472]
+
+ * plugins/sudoers/interfaces.c:
+ Fix pasto; AF_INET not AF_INET6
+ [2d2e9d7dc6f9]
+
+ * compat/dlopen.c:
+ Actually call shl_load()
+ [ed8153b8a3cd]
+
+ * pp:
+ Update from git repo. Debian: version numbers now compliant with
+ policy section 5.6.12 HP-UX: minimal changes needed to work on HP-UX
+ 10.20
+ [ecf2692bceeb]
+
+ * configure, configure.in:
+ Fix dlopen() detection for systems where dlopen() is in a separate
+ library.
+ [fa6b175582b6]
+
+ * plugins/sudoers/auth/pam.c:
+ If pam_acct_mgmt() returns PAM_AUTH_ERR print a (hopefully) more
+ useful message and return AUTH_FATAL so sudo does not keep trying to
+ validate the user.
+ [1be8857e5291]
+
+ * src/preload.c:
+ sudo_preload_table is an array
+ [b7704e72a9da]
+
+ * compat/dlopen.c:
+ Quiet a compiler warning and fix sudo_preload_table external
+ definition.
+ [8234987664cc]
+
+ * compat/dlfcn.h:
+ Fix multiple inclusion guard in dlfcn.h and fix dlerror() prototype.
+ [8bab6a4053cc]
+
+ * plugins/sudoers/group_plugin.c:
+ Make this compile correctly when no dlopen is available.
+ [57643879bd2b]
+
+2010-10-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c:
+ Having a timestamp file defined is no longer indicative of tty
+ tickets being enabled. Check def_tty_tickets directly.
+ [efcc11ad157f]
+
+ * src/exec_pty.c, src/sudo.h, src/ttysize.c:
+ Fix TCGETWINSZ compat.
+ [da3a8b17cf7a]
+
+2010-10-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec_pty.c, src/ttysize.c:
+ Prefer newer TIOCGWINSZ ioctl to old TIOCGSIZE
+ [926492dd10a6]
+
+2010-10-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c, src/sudo.c:
+ Move set_project() from sudoers module into sudo proper.
+ [beabafac03b4]
+
+ * configure, configure.in:
+ Fix typo and regenerate
+ [4a3caf4234f3]
+
+ * plugins/sudoers/ldap.c:
+ When iterating over returned LDAP entries, keep looking at remaining
+ matches even if we have a positive match. This catches negative
+ matches that may exist in other entries and more closely match the
+ sudoers file behavior.
+ [f47db6e609b0]
+
+ * pp:
+ Add support for multiple package instances on Solaris.
+ [7f2a8b942545]
+
+ * src/exec.c:
+ Add missing signal_pipe[0] to fdsr for the non-pty case.
+ [79d01e11b19c]
+
+ * mkpkg:
+ Add --with-project for Solaris
+ [ffa4c2bb93f7]
+
+ * README:
+ Need ar and ranlib too
+ [5c2f679172ef]
+
+2010-09-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/env.c:
+ Preserve ODMDIR environment variable by default on AIX.
+ [bd47cb1e804f]
+
+2010-09-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, compat/Makefile.in, compat/dlfcn.h, compat/dlopen.c,
+ config.h.in, configure, configure.in, plugins/sample/Makefile.in,
+ plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in,
+ plugins/sudoers/group_plugin.c, plugins/sudoers/plugin_error.c,
+ plugins/sudoers/sudoers.c, src/Makefile.in, src/load_plugins.c,
+ src/preload.c:
+ Add dlopen() emulation for systems without it. For HP-UX 10, emulate
+ using shl_load(). For others, link sudoers plugin statically and use
+ a lookup table to emulate dlsym().
+ [e92edfb3c642]
+
+2010-09-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/fnmatch.c, compat/glob.c, compat/mksiglist.c,
+ compat/nanosleep.c, compat/utimes.c:
+ When including compat headers, use the compat dir as part of the
+ path so we are sure to get the correct header.
+ [6c2a45da6af5]
+
+2010-09-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/linux_audit.c:
+ Ignore ECONNREFUSED from audit_log_user_command() which will occur
+ if auditd is not running.
+ [d314fe4c8d03]
+
+2010-09-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pp:
+ Sync with git version
+ [1c0357744222]
+
+2010-09-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/fileops.c, plugins/sudoers/defaults.c:
+ Cast isblank argument to unsigned char.
+ [c822dbb3ca54]
+
+2010-09-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, config.h.in, configure, configure.in, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.pod, plugins/sudoers/defaults.c:
+ Implement --with-umask-override configure flag.
+ [863e3047df22]
+
+ * plugins/sudoers/env.c:
+ Take MODE_LOGIN_SHELL into account when initially setting reset_home
+ instead of special-casing it later.
+ [5d6b16480fd6]
+
+ * plugins/sudoers/sudoers.c:
+ In login mode, make a copy of the runas user's pw_shell for
+ NewArgv[0] because 1) we modify it and 2) it will runas_pw gets
+ freed before exec.
+ [1d1ccb568dfa]
+
+ * plugins/sudoers/env.c:
+ Reset HOME for "sudo -i" even if HOME was listed in env_keep.
+ [c1c1c65a2d63]
+
+ * src/sudo.c:
+ Use SIG_SETMASK when resetting signal mask instead of SIG_UNBLOCK.
+ [7443454e5f88]
+
+ * src/sudo.c:
+ Reset signal mask at sudo startup time; we need to be able to rely
+ on normal signal delivery to control the child process.
+ [95800163ff94]
+
+2010-09-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * install-sh:
+ Use sed instead of expr to split a flag from its argument. Fixes a
+ problem with expr interpreting its arguments as a flag when they
+ start with a dash.
+ [736065e14301]
+
+ * common/lbuf.c:
+ Do not need sys/time.h after all
+ [91f6f668ccda]
+
+ * common/lbuf.c:
+ Include sys/time.h for utimes() and struct timeval. No longer need
+ ioctl.h or termios.h
+ [2d75273d3213]
+
+ * compat/snprintf.c:
+ Quiet bogus compiler warnings.
+ [fe252e1968f5]
+
+ * include/missing.h:
+ Declare innetgr() for HP-UX which is missing a declaration. Declare
+ domainname() for HP-UX and Solaris which are missing a declaration.
+ [b37c50751138]
+
+ * plugins/sudoers/bsm_audit.c:
+ Use __sun for consistency with the rest of the sources.
+ [6b086b61ccb6]
+
+ * plugins/sudoers/group_plugin.c:
+ Quiet a bogus compiler warning.
+ [ebc069842c4a]
+
+ * plugins/sudoers/pwutil.c:
+ Don't try to delref a NULL group.
+ [f6ff0838be21]
+
+ * common/alloc.c, common/lbuf.c:
+ Include memory.h on systems that need it.
+ [4e676da81c6f]
+
+2010-09-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c:
+ Quiet gcc warnings on glibc systems that use warn_unused_result for
+ write(2).
+ [0532da0b7cf7]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod:
+ sudo_plugin is in section 8; from Ted Percival
+ [b4506a0de87e]
+
+ * plugins/sudoers/Makefile.in:
+ testsudoers depends on libsudoers.la, not sudoreplay
+ [cdb1cc3bf06a]
+
+2010-09-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c:
+ Read as many signals on the signal pipe as we can before returning.
+ [b181671da047]
+
+ * src/exec.c, src/exec_pty.c, src/sudo_exec.h:
+ Instead of using a array to store received signals, open a pipe and
+ have the signal handler write the signal number to one end and
+ select() on the other end. This makes it possible to handle signals
+ similar to I/O without race conditions.
+ [ee84d65c16b6]
+
+2010-09-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/visudo.pod, plugins/sudoers/visudo.c:
+ Make "visudo -c -f -" check the standard input.
+ [195a3d2a9a26]
+
+ * doc/sudoers.pod:
+ set_home and always_set_home have an effect if HOME is present in
+ the env_keep list.
+ [159d0b9dc5c8]
+
+ * plugins/sudoers/env.c:
+ Make -H flag work when HOME is listed in env_keep. Also makes
+ "set_home" and "always_set_home" override override HOME in env_keep.
+ [a3e5b966193f]
+
+2010-09-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/interfaces.c,
+ plugins/sudoers/interfaces.h, plugins/sudoers/match.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c, src/net_ifs.c:
+ Convert sudoers plugin to use interface list passed in settings.
+ [87d9b5f4f586]
+
+ * doc/sudo_plugin.pod, src/Makefile.in, src/net_ifs.c,
+ src/parse_args.c, src/sudo.h:
+ Query local network interfaces in the main sudo driver and pass to
+ the plugin as "network_addrs" in the settings list.
+ [7f35bcfe77a7]
+
+ * plugins/sudoers/bsm_audit.c:
+ Solaris BSM audit return EINVAL when auditing is not enabled,
+ whereas OpenBSM returns ENOSYS.
+ [411b980ec58b]
+
+2010-09-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/fnmatch.c:
+ missing.h should come before most local includes
+ [53921a7b8b5b]
+
+ * plugins/sudoers/sudoreplay.c:
+ missing.h should come before most local includes
+ [e9abb0db1aac]
+
+ * plugins/sudoers/sudoers.h:
+ Make local includes consistent; use double quotes for local includes
+ except for generated ones where we use angle brackets.
+ [09de4faa9547]
+
+ * plugins/sudoers/sudoers.c:
+ Always fill in NewArgv for audit code.
+ [7c3aca60519f]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Add missing LOG_INPUT/LOG_OUTPUT support in the lexer.
+ [007cf6560f92]
+
+ * common/alloc.c, common/atobool.c, common/fileops.c,
+ common/fmt_string.c, common/lbuf.c, common/list.c, common/term.c,
+ common/zero_bytes.c, compat/closefrom.c, compat/fnmatch.c,
+ compat/getcwd.c, compat/getgrouplist.c, compat/getline.c,
+ compat/getprogname.c, compat/glob.c, compat/isblank.c,
+ compat/memrchr.c, compat/mksiglist.c, compat/mkstemps.c,
+ compat/nanosleep.c, compat/setenv.c, compat/snprintf.c,
+ compat/strlcat.c, compat/strlcpy.c, compat/strsignal.c,
+ compat/unsetenv.c, compat/utimes.c, include/compat.h,
+ plugins/sample/sample_plugin.c, plugins/sample_group/getgrent.c,
+ plugins/sample_group/plugin_test.c,
+ plugins/sample_group/sample_group.c, plugins/sudoers/audit.c,
+ plugins/sudoers/auth/afs.c, plugins/sudoers/boottime.c,
+ plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/match.c,
+ plugins/sudoers/plugin_error.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/timestr.c, src/error.c, src/sesh.c, src/sudo.h,
+ src/sudo_noexec.c, src/ttysize.c:
+ Make local includes consistent; use double quotes for local includes
+ except for generated ones where we use angle brackets. Also g/c
+ unused compat.h.
+ [e57070dc8f04]
+
+2010-09-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/match.c:
+ When matching the runas user and runas group (-u and -g command line
+ options), keep track of runas group and runas user matches
+ separately. Only return a positive match if we have a match for both
+ runas user and runas group (if specified).
+ [815219e04cc8]
+
+2010-09-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.ldap.pod, plugins/sudoers/ldap.c:
+ Add support for multiple URI lines by joining the contents and
+ passing the result to ldap_initialize.
+ [a47cae3b72e8]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/parse.c:
+ Do not return -1 on error from the display functions; the caller
+ expects a return value >= 0.
+ [101456a7dd00]
+
+ * plugins/sudoers/sudoers.c:
+ Do not set both MODE_EDIT and MODE_RUN
+ [8faa36694d54]
+
+2010-09-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/missing.h:
+ Move includes to the top of the file.
+ [a51436798e8c]
+
+2010-08-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ Add missing definition of timedir
+ [458a749c2c5e]
+
+ * compat/fnmatch.c, compat/getprogname.c, compat/isblank.c,
+ compat/mksiglist.c, compat/strsignal.c,
+ plugins/sudoers/plugin_error.c, src/error.c, src/sudo_noexec.c:
+ Add #include of sys/types.h for .c files that include missing.h to
+ be sure that size_t and ssize_t are defined.
+ [08e3132dbf4f]
+
+ * plugins/sudoers/Makefile.in:
+ Install sudoers file from the build dir not hte src dir.
+ [ca89e962dbf4]
+
+2010-08-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/set_perms.c:
+ If runas_pw changes, reset the stashed runas aux group vector.
+ Otherwise, if runas_default is set in a per-command Defaults
+ statement, the command runs with root's aux group vector (i.e. the
+ one that was used when locating the command).
+ [24f9107cedd2]
+
+ * plugins/sudoers/Makefile.in:
+ Add target to generate sudoers file Remove generated sudoers file as
+ part of distclean
+ [fb7422e90f03]
+
+2010-08-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/exec.c:
+ When not logging I/O install a handler for SIGCONT and deliver it to
+ the command upon resume. Fixes bugzilla #431
+ [495dce52a5aa]
+
+2010-08-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.h:
+ g/c unused auth_pw extern definition
+ [40eb7477ba17]
+
+ * plugins/sudoers/check.c, plugins/sudoers/sudoers.c:
+ Move get_auth() into check.c where it is actually used.
+ [e31db0ce3a61]
+
+2010-08-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * common/lbuf.c:
+ Convert a remaining puts() and putchar() to use the output function.
+ [d69e363a506b]
+
+ * plugins/sudoers/plugin_error.c:
+ Plug memory leak
+ [68895469ea8d]
+
+2010-08-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/env.c:
+ Set dupcheck to TRUE when setting new HOME value if !env_reset but
+ always_set_home is true. Prevents a duplicate HOME in the
+ environment (old value plus the new one) introduced in f421f8827340.
+ [9ca19183794f]
+
+ * configure, configure.in, plugins/sudoers/sudoers,
+ plugins/sudoers/sudoers.in:
+ Substitute sysconfdir in the installed sudoers file to get the
+ correct path for sudoers.d.
+ [86072b6cd55d]
+
+2010-08-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/get_pty.c:
+ Fix typo that prevented compilation on Irix; Friedrich Haubensak
+ [b48be51b65fc]
+
+2010-08-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, common/Makefile.in, common/aix.c, common/alloc.c,
+ common/atobool.c, common/fileops.c, common/fmt_string.c,
+ common/lbuf.c, common/list.c, common/term.c, common/zero_bytes.c,
+ compat/Makefile.in, compat/closefrom.c, compat/fnmatch.c,
+ compat/getcwd.c, compat/getgrouplist.c, compat/getline.c,
+ compat/getprogname.c, compat/glob.c, compat/isblank.c,
+ compat/memrchr.c, compat/mksiglist.c, compat/mkstemps.c,
+ compat/nanosleep.c, compat/setenv.c, compat/snprintf.c,
+ compat/strlcat.c, compat/strlcpy.c, compat/strsignal.c,
+ compat/unsetenv.c, compat/utimes.c, include/compat.h,
+ include/missing.h, plugins/sample/sample_plugin.c,
+ plugins/sample_group/getgrent.c,
+ plugins/sample_group/sample_group.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/audit.c, plugins/sudoers/boottime.c,
+ plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/linux_audit.c, plugins/sudoers/plugin_error.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/timestr.c, src/Makefile.in, src/error.c, src/sesh.c,
+ src/sudo.h, src/sudo_noexec.c, src/ttysize.c:
+ Merge compat.h and missing.h into missing.h
+ [572909ae9716]
+
+2010-08-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/pam.c:
+ If the user hits ^C while a password is being read, error out before
+ reading any further passwords in the pam conversation function.
+ Otherwise, if multiple PAM auth methods are required, the user will
+ have to hit ^C for each one.
+ [23782631748c]
+
+2010-08-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c:
+ Update comment
+ [a5296cb3a20a]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod:
+ Document sudo_conv_t function and sudo_printf_t return values.
+ [745c0017814c]
+
+ * src/conversation.c:
+ Make _sudo_printf return the number of characters printed on success
+ like printf(3).
+ [8eeefe8d7e77]
+
+2010-08-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ sudoers.h includes sudo_plugin.h for us
+ [cabe68e07807]
+
+ * common/Makefile.in, common/gettime.c, compat/mkstemps.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/visudo.c, src/sudo.h,
+ src/sudo_edit.c:
+ Use gettimeofday() directly instead of via the gettime() wrapper.
+ [7490426c99ae]
+
+ * common/gettime.c, compat/snprintf.c, compat/strcasecmp.c,
+ compat/strerror.c, config.h.in, configure, configure.in,
+ include/compat.h, include/missing.h, plugins/sudoers/logging.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/visudo.c, src/sudo.c:
+ Remove some obsolete configure tests, ancient Unix systems are no
+ longer supported.
+ [2be6218c3a36]
+
+2010-08-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Set pp_kit_version and strip off patch level
+ [aacfda1b676d]
+
+ * sudo.pp:
+ Better handling of versions with a patchlevel. For rpm and deb, use
+ the patchlevel+1 as the release. For AIX, use the patchlevel as the
+ 4th version number. For the rest, just leave the patchlevel in the
+ version string.
+ [638bd35f2346]
+
+2010-08-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/sudo_auth.c:
+ For non-standalone auth methods, stop reading the password if the
+ user enters ^C at the prompt.
+ [82c2911bb264]
+
+ * configure, configure.in, plugins/sudoers/Makefile.in,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/secureware.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/auth/sudo_auth.h,
+ plugins/sudoers/pwutil.c:
+ No need to look up shadow password unless we are doing password-
+ style authentication. This moves the shadow password lookup to the
+ auth functions that need it.
+ [ba9e3eba2b72]
+
+ * plugins/sudoers/sudoers.c:
+ Retain final passwd/group refs until the policy close() function.
+ Note that this doesn't get called in all cases so putting this in a
+ cleanup function is probably better.
+ [bbe214cb4119]
+
+ * plugins/sudoers/check.c:
+ Fix mismerge
+ [395115f89dd6]
+
+ * plugins/sudoers/check.c:
+ When removing/resetting the timestamp file ignore the tty ticket
+ contents.
+ [b709f5667a0b]
+
+ * plugins/sudoers/sudoers.c:
+ delref sudo_user.pw, runas_pw and runas_gr immediately before we
+ return.
+ [4d67d15dfd3b]
+
+2010-08-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/match.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Reference count cached passwd and group structs. The cache holds one
+ reference itself and another is added by sudo_getgr{gid,nam} and
+ sudo_getpw{uid,nam}. The final ref on the runas and user passwd and
+ group structs are persistent for now.
+ [e544685523c3]
+
+ * doc/UPGRADE:
+ fix typo
+ [e32f2d35e6c9]
+
+2010-08-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c:
+ Do not produce a warning for "sudo -k" if the ticket file does not
+ exist.
+ [1598f6061b75]
+
+ * plugins/sudoers/pwutil.c:
+ Instead of caching struct passwd and struct group in the red-black
+ tree, store a struct cache_item which includes both the key and
+ datum. This allows us to user the actual name that was looked up as
+ the key instead of the contents of struct passwd or struct group.
+ This matters because the name in the database may not match what we
+ looked up, due either to case folding or truncation (historically at
+ 8 characters). Also mark the disabled calls to sudo_freepwcache()
+ and sudo_freegrcache() as broken since we use cached data for things
+ like set_perms() and the logging functions. Fixing this would
+ require making a copy of the structs for user and runas or adding a
+ reference count (better).
+ [225d4a22f60e]
+
+ * plugins/sudoers/Makefile.in:
+ Fix path to mkinstalldirs
+ [b4968379b12d]
+
+ * plugins/sudoers/check.c, plugins/sudoers/logging.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/visudo.c,
+ src/exec_pty.c, src/get_pty.c, src/tgetpass.c:
+ Quiet gcc warnings on glibc systems that use warn_unused_result for
+ write(2) and others.
+ [c99f138960e0]
+
+2010-08-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Add %option noinput
+ [72b9cd49b4f1]
+
+ * aclocal.m4, configure, configure.in:
+ Add cross-compile defaults for remaining AC_TRY_RUN usage. Also add
+ back getgroups() check since AC_FUNC_GETGROUPS defaults to "no" when
+ cross-compiling.
+ [e385c176d0ee]
+
+2010-07-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aclocal.m4, compat/snprintf.c, config.h.in, configure, configure.in:
+ Use AC_CHECK_MEMBER in SUDO_SOCK_SA_LEN Use AC_TYPE_LONG_LONG_INT
+ and AC_CHECK_SIZEOF([long int]) instead of rolling our own.
+ [cf3e60d9c440]
+
+2010-07-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pp:
+ Update to latest version
+ [32f93be33961]
+
+2010-07-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Let pp determine pp_aix_version itself.
+ [7cf0245d84ed]
+
+ * INSTALL, config.h.in, configure, configure.in, mkpkg,
+ plugins/sudoers/sudoers.c:
+ Add support for Ubuntu admin flag file and enable it when building
+ Ubuntu packages.
+ [00e27cff2dfb]
+
+ * plugins/sudoers/sudoers, sudo.pp:
+ Add commented out SuSE-like targetpw settings
+ [4605d47b7413]
+
+ * configure, configure.in:
+ Only try to use +DAportable for non-GCC on hppa
+ [75d0f284ccf7]
+
+ * configure, configure.in:
+ Prevent configure from adding the -g flag unless in devel mode
+ [b1fd3f8d45c0]
+
+2010-07-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pp:
+ Go back to sudo-flavor to match existing packages and only use an
+ underscore for those that need it.
+ [d737069d1e1c]
+
+ * sudo.pp:
+ Use sudo_$flavor instead of sudo-$flavor since that causes the least
+ amount of trouble for the various package managers.
+ [71f547af35fc]
+
+ * mkpkg:
+ Fix handling of the ldap flavor Remove destdir unless --debug was
+ specified Make distclean before running configure if there is a
+ Makefile present
+ [6316f08de7d3]
+
+ * sudo.pp:
+ Add back include file.
+ [195627bf68b8]
+
+ * mkpkg:
+ Pass extra args on to configure on HP-UX, if we don't have the HP C
+ compiler, disable zlib to prevent gcc from finding it in
+ /usr/local/lib.
+ [473efa0e2bac]
+
+ * mkpkg:
+ Use the HP ANSI C compiler on HP-UX if possible
+ [fb249b6b175d]
+
+ * plugins/sudoers/sudoreplay.c:
+ Some getline() implementations (FreeBSD 8.0) do not ignore the
+ length pointer when the line pointer is NULL as they should.
+ [2410a1a3543c]
+
+ * plugins/sudoers/sudoreplay.c:
+ Don't need to check for *cp being non-zero, isdigit() will do that.
+ [7df11ea8a487]
+
+ * plugins/sudoers/sudoreplay.c:
+ Add setlocale() so the command line arguments that use floating
+ point work in different locales. Since sudo now logs the timing data
+ in the C locale we must Parse the seconds in the timing file
+ manually instead of using strtod(). Furthermore, sudo 1.7.3 logged
+ the number of seconds with the user's locale so if the decimal point
+ is not '.' try using the locale-specific version.
+ [4d385765f23b]
+
+ * src/exec.c:
+ Do I/O logging in the C locale so the floating point numbers in the
+ timing file are not locale-dependent.
+ [5961cec044ec]
+
+ * plugins/sudoers/sudoreplay.c:
+ Use errorx() not error() for thingsthat don't set errno.
+ [0fe5e692af84]
+
+2010-07-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pp:
+ Better support for 1.2.3 style versions in Tru64 kits
+ [997c549bb777]
+
+ * sudo.pp:
+ Add Tru64 kit support
+ [e273a954f981]
+
+ * pp:
+ Remove apparently unnecessary use of sudo
+ [be8840d85125]
+
+ * Makefile.in, plugins/sudoers/Makefile.in:
+ Create timedir as part of install-dirs target.
+ [c736bc2fb14f]
+
+ * src/exec_pty.c:
+ Handle ENXIO from read/write which can occur when reading/writing a
+ pty that has gone away.
+ [fa2e8059879f]
+
+ * plugins/sudoers/pwutil.c:
+ sudo_pwdup() was not expanding an empty pw_shell to _PATH_BSHELL
+ [3a045475d5ee]
+
+ * mkpkg:
+ platform is a pp flag not a variable
+ [12eba39a47c1]
+
+ * Makefile.in, mkpkg, sudo.pp:
+ Add simple arg parsing for mkpkg so we can set debug, flavor or
+ platform.
+ [ada839fe252d]
+
+ * pp:
+ Make rpm backend work on AIX 5.x
+ [549a76d11393]
+
+2010-07-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers:
+ Add commented out Defaults entry for log_output
+ [7e67d7588900]
+
+2010-07-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/Makefile.in:
+ Remove sudo docdir completely
+ [dce8e82878ef]
+
+ * doc/sample.sudo.conf:
+ Add sample sudo.conf
+ [aafdba3fc411]
+
+ * src/Makefile.in:
+ Pass install-sh -b~ here too.
+ [c3f5eb446c38]
+
+ * plugins/sample/Makefile.in, plugins/sample_group/Makefile.in,
+ plugins/sudoers/Makefile.in, src/Makefile.in:
+ Install binary files with -b~ to make a backup. Fixes "text file
+ busy" error on HP-UX during install.
+ [81f306f54f8c]
+
+ * install-sh:
+ "mv -f" on HP-UX doesn't unlink the destination first so add an
+ explicit rm before moving the temporary into place.
+ [fb719a79582d]
+
+ * configure, configure.in:
+ Some more ${foo} -> $(foo) conversion for consistent Makefiles.
+ [0aa098770074]
+
+ * doc/Makefile.in, plugins/sudoers/Makefile.in:
+ Install sudoers2ldif in the doc dir
+ [33ac3b53d7f5]
+
+2010-07-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pathnames.h.in:
+ Add missing include of maillock.h for Solaris
+ [5a58883be23a]
+
+ * NEWS, configure, configure.in, doc/TROUBLESHOOTING, doc/UPGRADE,
+ doc/sample.syslog.conf, doc/sudoers.cat:
+ Change the default syslog facility from local2 to authpriv (or auth
+ if the operating system doesn't support authpriv).
+ [3b70ba514f49]
+
+ * Makefile.in, sudo.pp:
+ Install sudoers as /etc/sudoers on RPM and debian systems where the
+ package manager will not replace a user-modified configuration file.
+ This fixes upgrades from the vendor sudo packages.
+ [d886b6d60b5b]
+
+ * pp:
+ RPM: use %config(noreplace) instead of %config for volatile This
+ results in the new file being installed with a .rpmnew suffix
+ instead of the file being replaced and the old one renamed with a
+ .rpmsave suffix.
+ [58be2119f8e8]
+
+ * plugins/sudoers/Makefile.in:
+ Add PACKAGE_TARNAME for docdir
+ [930c92b8f8f0]
+
+2010-07-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/mkstemps.c, plugins/sudoers/boottime.c:
+ Include time.h for struct timeval
+ [ddf8b04f0276]
+
+ * src/exec_pty.c:
+ The return value of strsignal() may be const and should be treated
+ as const regardless.
+ [620074ae1e77]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod:
+ Mention that 127.0.0.1 will not match, nor will localhost unless
+ that is the actual host name.
+ [8b574122eb8f]
+
+ * MANIFEST, NEWS, README, WHATSNEW, doc/Makefile.in, doc/UPGRADE:
+ Rename WHATSNEW -> NEWS
+ [d1a2c8c47d89]
+
+ * pp:
+ Updated pp with latest patches
+ [98e16b9b8f62]
+
+ * WHATSNEW:
+ Sync with 1.7.4
+ [65ac4dafeef7]
+
+ * doc/UPGRADE, doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod,
+ plugins/sudoers/sudoers:
+ Add commented out line to add HOME to env_keep and add a warning to
+ the note about the HOME change in UPGRADE.
+ [0d6a775bb6c8]
+
+2010-07-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c:
+ Add LINE_MAX define for those without it.
+ [446d9dbe7859]
+
+ * INSTALL, WHATSNEW, config.h.in, configure, configure.in,
+ doc/UPGRADE, doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod,
+ plugins/sudoers/defaults.c:
+ The tty_tickets option is now on by default.
+ [a01c48206d80]
+
+ * WHATSNEW:
+ Mention that AIX authdb support has been fixed.
+ [87bd7f4eba6a]
+
+ * common/aix.c:
+ setauthdb() only sets the "old" registry if it was set by a previous
+ call to setauthdb(). To restore the original value, passing NULL (or
+ an empty string) to setauthdb() is sufficient.
+ [470da190a254]
+
+2010-07-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * WHATSNEW, doc/UPGRADE, doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod,
+ doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod,
+ plugins/sudoers/env.c:
+ Reset HOME when env_reset is enabled unless it is in env_keep
+ [f421f8827340]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod:
+ The default for set_logname has been "true" for some time now.
+ [f489da5674c3]
+
+ * plugins/sudoers/boottime.c:
+ Add missing include of time.h
+ [624d7014932f]
+
+ * plugins/sudoers/logging.c:
+ Fix check for dup2() return value.
+ [140ea2d50d20]
+
+ * plugins/sudoers/env.c:
+ Add PYTHONUSERBASE to initial_badenv_table
+ [3149aae5b12c]
+
+ * plugins/sudoers/visudo.c:
+ Treat an unknown defaults entry as a parse error.
+ [b3ebad73efb2]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/sudoers.c:
+ Check return value of setdefs() but don't stop setting defaults if
+ we hit an unknown one.
+ [945e752239ab]
+
+ * WHATSNEW, aclocal.m4, config.h.in, configure, configure.in,
+ doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.pod, pathnames.h.in,
+ plugins/sudoers/env.c:
+ If env_reset is enabled, set the MAIL environment variable based on
+ the target user unless MAIL is explicitly preserved in sudoers.
+ [a1b03e2e0e96]
+
+2010-07-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pp:
+ decode debian code names
+ [8741280d9960]
+
+ * WHATSNEW:
+ fix typo
+ [a8a19451110b]
+
+2010-07-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * WHATSNEW:
+ Merge with 1.7.4
+ [9348fa7e15b8]
+
+ * src/sudo.c:
+ Restore RLIMIT_NPROC after the uid switch if it appears that
+ runas_setup() did not do it for us. Fixes a bash script problem on
+ SuSE with RLIMIT_NPROC set to RLIM_INFINITY.
+ [786fb272e5fd]
+
+ * INSTALL:
+ document --with-pam-login
+ [ea93e4c6873c]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod:
+ The tag is NOSETENV, not UNSETENV. From Petr Uzel.
+ [2ac90d8de36e]
+
+2010-07-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg, pp, sudo.pp:
+ Restore the dot removal in the os version reported by polypkg. Adapt
+ mkpkg and sudo.pp to the change.
+ [dcafdd53b88f]
+
+ * sudo.pp:
+ Include flavor in solaris package name
+ [e605f6364c9f]
+
+ * mkpkg:
+ Older shells don't support IFS= so set explictly to space, tab,
+ newline.
+ [7773960bc8a0]
+
+ * mkpkg:
+ Use '=' not '==' in test
+ [c99d42bc48e6]
+
+ * mkpkg:
+ Fix typo that prevented debian from matching
+ [84421078fcb7]
+
+ * mkpkg:
+ Add missing prefix setting for debian
+ [6466f23de4aa]
+
+ * sudo.pp:
+ Use tab indents to reduce the chance of problem with <<- Fix the
+ debian %set section, pp does not set pp_deb_distro Uncomment %sudo
+ line in sudoers for debian Uncomment some env_keep lines for RHEL,
+ SLES and debian to more closely match the vendor sudoers files. Add
+ /etc/pam.d to %files Remove the /etc/sudo-ldap.conf symlink on
+ debian for ldap flavor
+ [c5b49feb1a0c]
+
+ * plugins/sudoers/sudoers:
+ Add commented out env_keep entries, sample Aliases and a %sudo line
+ for debian.
+ [387719e52d0f]
+
+ * configure, configure.in:
+ Move zlib check later on in the script to avoid a strange shell
+ problem on SLES11.
+ [1a3153bb1291]
+
+ * configure.in:
+ Remove check for egrep; configure has its own
+ [a3b9d98cb5d2]
+
+2010-07-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg:
+ Enable zlib for linux distros
+ [8fa51a1405a4]
+
+ * mkpkg:
+ Add ldap flavor to default build
+ [97644f5a555f]
+
+ * mkpkg, sudo.pp:
+ Simplify rpm linux distro settings
+ [b9dcf10cdf20]
+
+ * aclocal.m4, configure, configure.in, doc/UPGRADE, doc/sudoers.cat:
+ Move time stamp files from /var/run/sudo to /var/{db,lib,adm}/sudo.
+ [2c549c1acde9]
+
+ * Makefile.in:
+ Fix ChangeLog creation from build dir
+ [3d0c7904f173]
+
+ * plugins/sudoers/sudoers.c:
+ Handle getcwd() failure.
+ [aef7bef87394]
+
+ * doc/Makefile.in, mkpkg, sudo.pp:
+ Add ldap "flavor" for debian, controlled by the SUDO_FLAVOR
+ environment variable.
+ [be6ed611b7a8]
+
+ * sudo.pp:
+ Create sudo group on debian
+ [6ed6c032042e]
+
+ * mkpkg, sudo.pp:
+ Add debian 4/5/6 and use the dot when doing version matches
+ [6bcb664d1f4f]
+
+ * aclocal.m4, configure:
+ Use a loop when searching for mv, sendmail and sh
+ [d5e9369f8d13]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod:
+ Remove spurious "and"; from debian
+ [a21e6f7c5b99]
+
+ * aclocal.m4, configure, configure.in, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.pod, doc/visudo.cat,
+ doc/visudo.man.in, doc/visudo.pod:
+ Substitute the value of EDITOR into the sudoers and visudo manuals.
+ [cd79e587dd7f]
+
+2010-07-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkpkg, pp, sudo.pp:
+ Initial support for debian 4.0
+ [ac6707915fa8]
+
+ * mkpkg:
+ Some platforms need -fPIE instead of -fpie
+ [fd6be19e5bc2]
+
+ * plugins/sudoers/auth/pam.c:
+ Only set PAM_RHOST for Solaris, where it is needed to avoid a bug.
+ On Linux it causes a DNS lookup via libaudit.
+ [1e10105ade5b]
+
+ * MANIFEST:
+ Update MANIFEST to match packaging changes
+ [ef86ee557b5b]
+
+ * sudo.psf:
+ We now use pp to generate HP-UX packages
+ [f7aa8da7844e]
+
+ * INSTALL.binary, plugins/sudoers/Makefile.binary.in:
+ Remove vestiges of old binary package bits.
+ [afffd005452f]
+
+ * INSTALL, Makefile.in, common/Makefile.in, compat/Makefile.in,
+ doc/Makefile.in, include/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in,
+ src/Makefile.in:
+ install-man -> install-doc
+ [99b5fa05567c]
+
+ * Makefile.in, doc/Makefile.in, include/Makefile.in, mkpkg,
+ plugins/sudoers/Makefile.in, pp, src/Makefile.in, sudo.pp:
+ Use http://rc.quest.com/topics/polypkg/ for packaging
+ [5ca8eb75b223]
+
+ * install-sh:
+ Just ignore the -c option, it is the default Add support for -d
+ option
+ [a8b6b0a131e8]
+
+2010-07-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pathnames.h.in, plugins/sudoers/env.c, plugins/sudoers/logging.c:
+ Use _PATH_STDPATH instead of _PATH_DEFPATH
+ [137fa911908e]
+
+ * plugins/sudoers/Makefile.in, src/Makefile.in:
+ Do not strip binaries.
+ [20166e287176]
+
+ * INSTALL, configure, configure.in:
+ Add --insults=disabled configure option to allow people to build in
+ insult support but have the insults disabled unless explicitly
+ enabled in sudoers.
+ [523b8c552e90]
+
+ * compat/mkstemps.c:
+ Add prototype for gettime()
+ [275eee40473b]
+
+ * config.h.in, configure, configure.in, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/env.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Add support for a sudo-i pam.d file to be used for "sudo -i".
+ Adapted from a RedHat patch.
+ [06d34f16520b]
+
+2010-07-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/missing.h:
+ Fix mkstemps() prototype
+ [2421841e815b]
+
+ * MANIFEST, compat/Makefile.in, compat/mkstemp.c, compat/mkstemps.c,
+ config.h.in, configure, configure.in, include/missing.h,
+ src/sudo_edit.c:
+ Use mkstemps() instead of mkstemp() in sudoedit. This allows
+ sudoedit to preserve the file extension (if any) which may be used
+ by the editor (like emacs) to choose the editing mode.
+ [d33172d2c086]
+
+2010-07-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in, doc/sudoers.ldap.pod,
+ plugins/sudoers/ldap.c:
+ TLS_CACERT is now an alias for TLS_CACERTFILE. OpenLDAP uses
+ TLS_CACERT, not TLS_CACERTFILE in its ldap.conf. Other LDAP client
+ code, such as nss_ldap, uses TLS_CACERTFILE. Also document why you
+ should avoid disabling TLS_CHECKPEER is possible.
+ [196622436212]
+
+2010-07-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod:
+ Make sudo_plugin format a bit more like a man page
+ [048d596e32da]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Add suport for negated user/host/command lists in a Defaults entry.
+ E.g. Defaults:!baduser noexec
+ [d41112cf0342]
+
+ * Makefile.in, common/Makefile.in, compat/Makefile.in,
+ doc/Makefile.in, include/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in,
+ src/Makefile.in:
+ Add uninstall target
+ [fea66ebf136a]
+
+ * common/Makefile.in, compat/Makefile.in:
+ Remove unused AR, SED and RANLIB variables
+ [2ff9928bfdb3]
+
+ * Makefile.in:
+ Do not install sample plugins
+ [5443b87bd1c3]
+
+2010-07-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, aclocal.m4, compat/setenv.c, compat/unsetenv.c, configure,
+ configure.in, plugins/sudoers/env.c:
+ Now that sudoers is a dynamically loaded module we cannot override
+ the libc environment functions because the symbols may already have
+ been resolved via libc. Remove getenv/putenv/setenv/unsetenv
+ replacements from sudoers and add replacements for setenv/unsetenv
+ for systems that lack them.
+ [3f2b43cb8851]
+
+ * configure, configure.in, plugins/sudoers/Makefile.in:
+ Link testsudoers with -ldl when needed
+ [f79606f9fcd7]
+
+ * plugins/sample_group/plugin_test.c:
+ Remove unused time.h and add limits.h for PATH_MAX
+ [3f5d0074d621]
+
+ * doc/sudoers.ldap.pod:
+ Fix typo.
+ [bc855fd57397]
+
+2010-07-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sample_group/plugin_test.c:
+ Do not depend on strlcpy/strlcat
+ [6e7e2b5af051]
+
+ * plugins/sample_group/plugin_test.c:
+ Standalone test driver for sudoers group plugin.
+ [eb1235fc3b8e]
+
+2010-07-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/group_plugin.c, src/load_plugins.c:
+ Use RTLD_LAZY instead of RTLD_NOW; was using RTLD_NOW as a debugging
+ aid.
+ [2a34e616229b]
+
+ * plugins/sample_group/sample_group.c:
+ Fix style nit in function declarations
+ [ab87c7c76bf9]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod:
+ Document group_plugin syntax.
+ [ed1faf72ddcb]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod:
+ Document the sudoers group plugin.
+ [f19a62dc8cfc]
+
+ * INSTALL, MANIFEST, Makefile.in, config.h.in, configure,
+ configure.in, doc/LICENSE, doc/license.pod, include/sudo_plugin.h,
+ plugins/sample_group/Makefile.in, plugins/sample_group/getgrent.c,
+ plugins/sample_group/sample_group.c, plugins/sudoers/Makefile.in,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/group_plugin.c,
+ plugins/sudoers/match.c, plugins/sudoers/nonunix.h,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/vasgroups.c, plugins/sudoers/visudo.c, src/sudo.c:
+ Replace built-in non-unix group support with a sudoers group plugin.
+ Include a sample plugin that can read Unix-format group files.
+ [8fc58ce0b1a8]
+
+ * configure, configure.in, src/load_plugins.c:
+ Add a trailing slash to _PATH_SUDO_PLUGIN_DIR to simplify usage.
+ [5c491dddb8ef]
+
+2010-07-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod, doc/sudoers.cat,
+ doc/sudoers.man.in, doc/sudoers.pod:
+ Move sudoers-specific bits out of sudo(8) and into sudoers(5)
+ [e8a5a5830cfe]
+
+ * aclocal.m4, configure, configure.in:
+ Substitute @io_logdir@ for the sudoers I/O log directory.
+ [21a75ca7b0ab]
+
+2010-06-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, common/Makefile.in, common/aix.c, common/alloc.c,
+ common/atobool.c, common/fileops.c, common/fmt_string.c,
+ common/lbuf.c, common/term.c, compat/fnmatch.c, compat/getcwd.c,
+ compat/getgrouplist.c, compat/getline.c, compat/glob.c,
+ compat/snprintf.c, config.h.in, configure, configure.in,
+ include/fileops.h, plugins/sample/sample_plugin.c,
+ plugins/sudoers/alias.c, plugins/sudoers/auth/afs.c,
+ plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c,
+ plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c,
+ plugins/sudoers/auth/kerb4.c, plugins/sudoers/auth/kerb5.c,
+ plugins/sudoers/auth/pam.c, plugins/sudoers/auth/passwd.c,
+ plugins/sudoers/auth/rfc1938.c, plugins/sudoers/auth/secureware.c,
+ plugins/sudoers/auth/securid.c, plugins/sudoers/auth/securid5.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/boottime.c, plugins/sudoers/check.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/env.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/getdate.c,
+ plugins/sudoers/getdate.y, plugins/sudoers/getspwuid.c,
+ plugins/sudoers/goodpath.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/interfaces.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/logging.c, plugins/sudoers/match.c,
+ plugins/sudoers/parse.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/visudo.c,
+ src/Makefile.in, src/aix.c, src/conversation.c, src/exec.c,
+ src/exec_pty.c, src/get_pty.c, src/load_plugins.c, src/parse_args.c,
+ src/sudo.c, src/sudo.h, src/sudo_edit.c, src/tgetpass.c:
+ Set usrinfo for AIX Set adminstrative domain for the process when
+ looking up user's password or group info and when preparing for
+ execve(). Include strings.h even if string.h exists since they may
+ define different things. Fixes warnings on AIX and others.
+ [cf8b93e872c9]
+
+ * Makefile.in:
+ Add a separate all target for AIX make which was using the entire
+ LHS (not just the first entry) of the first target as the implicit
+ target.
+ [a45b980a01ef]
+
+ * plugins/sudoers/env.c:
+ Do not rely on env.env_len when unsetting a variable, just use the
+ NULL terminator.
+ [ca6eb239c829]
+
+ * plugins/sudoers/env.c:
+ In unsetenv() check for NULL or empty name as per POSIX 1003.1-2008
+ [7046ba7caa4e]
+
+2010-06-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/vasgroups.c:
+ Use warningx() instead of log_error() since the latter is not
+ available to visudo or testsudoers. This does mean that they don't
+ end up in syslog.
+ [152b7c50f426]
+
+ * plugins/sudoers/sudoers.c:
+ Defer call to sudo_nonunix_groupcheck_cleanup() until after we have
+ closed the sudoers sources. From Quest sudo.
+ [c1cd573bab94]
+
+ * plugins/sudoers/pwutil.c:
+ Ignore case when matching user/group names in the cache. From Quest
+ sudo.
+ [2aa4ecc7d7f5]
+
+2010-06-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, src/selinux.c:
+ Add check for setkeycreatecon() when --with-selinux is specified.
+ [affae247b4e0]
+
+ * configure, configure.in:
+ Error out if libaudit.h is missing or ununable when --with-linux-
+ audit was specified
+ [d82e743fac04]
+
+ * doc/HISTORY, doc/history.pod:
+ Add =head3 entries, mostly for the html version
+ [ee93112d0308]
+
+2010-06-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/HISTORY, doc/history.pod:
+ Mention when LDAP was incorporate.
+ [2923dc17f79c]
+
+2010-06-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Define _LINUX_SOURCE_COMPAT on AIX for strsignal() prototype, it is
+ not covered by _ALL_SOURCE.
+ [c92fd69809d0]
+
+2010-06-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ Add a cast to quiet a compiler warning.
+ [a200e07ee1bc]
+
+ * plugins/sudoers/getdate.c, plugins/sudoers/getdate.y:
+ Quiet a compiler warning.
+ [c9acfc927cea]
+
+ * plugins/sudoers/defaults.c, plugins/sudoers/sudoers.c:
+ Call set_fqdn() after sudoers has parsed instead of inline as a
+ callback.
+ [5f4e5d075f2d]
+
+ * WHATSNEW, plugins/sudoers/sudoers.c:
+ Do not call set_fqdn() until sudoers parses (where is gets run as a
+ callback).
+ [09040fca6d40]
+
+ * WHATSNEW:
+ mention the change in tty ticket behavior when there is no tty
+ [575a1fd98f05]
+
+ * plugins/sudoers/check.c:
+ Do not update tty ticket if there is no tty.
+ [63f9c33ce6a7]
+
+ * doc/LICENSE, doc/license.pod:
+ Update copyright year
+ [0722ab5d404b]
+
+ * doc/Makefile.in:
+ Do not rely on BSD make's $>
+ [936a86398bd9]
+
+ * configure, configure.in:
+ Set timedir to /var/db/sudo for darwin to match Apple sudo's
+ location
+ [d5b9b03096f1]
+
+2010-06-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.h:
+ Add stub declarations for struct stat and struct timeval
+ [f6d90551a4fd]
+
+ * MANIFEST:
+ Remove compat/sigaction.c
+ [d0ed6d9a770e]
+
+ * config.h.in, configure, configure.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/sudoreplay.c:
+ Check for zlib.h in addition to libz.
+ [6e191b4a6065]
+
+ * MANIFEST, src/Makefile.in, src/exec.c, src/exec_pty.c, src/sudo.h,
+ src/sudo_exec.h:
+ Move functions and symbols shared between exec.c and exec_pty.c into
+ sudo_exec.h.
+ [14ae63403544]
+
+ * doc/Makefile.in:
+ Comment out rules to build .man.in and .cat files unless --with-
+ devel
+ [3cf7e5606a85]
+
+ * doc/Makefile.in:
+ Comment out rules to build .man.in and .cat files unless --with-
+ devel
+ [d30495b0e29e]
+
+ * src/parse_args.c:
+ Quote any non-alphanumeric characters other than '_' or '-' when
+ passing a command to be run via the shell for the -s and -i options.
+ [d633f74fe2d9]
+
+ * doc/Makefile.in:
+ Add back .man suffix
+ [6e63b60a2739]
+
+ * INSTALL, MANIFEST, WHATSNEW, config.h.in, configure, configure.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/audit.c,
+ plugins/sudoers/bsm_audit.c, plugins/sudoers/linux_audit.c,
+ plugins/sudoers/linux_audit.h, plugins/sudoers/logging.h,
+ src/selinux.c:
+ Add Linux audit support.
+ [5a2f445e0bd4]
+
+2010-06-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ Remove an XXX
+ [a170cbe651d1]
+
+ * doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.pod,
+ plugins/sudoers/sudoreplay.c:
+ Add -f (filter) option to sudoreplay to allow certain streams to be
+ replayed and others ignored.
+ [62e51b432ea1]
+
+ * src/load_plugins.c, src/parse_args.c, src/sudo.c, src/sudo.h,
+ src/tgetpass.c:
+ Fix -A flag when askpass is specified in sudo.conf or if sudo
+ doesn't need to read a password.
+ [2e401e4a00e3]
+
+ * src/exec.c, src/exec_pty.c, src/parse_args.c, src/sudo.c,
+ src/sudo.h, src/sudo_edit.c, src/tgetpass.c:
+ Clean up some XXXs
+ [689f0b002d3d]
+
+ * WHATSNEW, doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.ldap.pod, plugins/sudoers/ldap.c:
+ Add support for multiple sudoers_base entries in ldap.conf. From
+ Joachim Henke
+ [e3e4a3c2bd5b]
+
+ * config.h.in, configure, configure.in, plugins/sudoers/logging.c,
+ src/exec_pty.c:
+ remove setsid check, we require a POSIX system
+ [cc73cb9e22c0]
+
+ * plugins/sudoers/logging.c, src/exec_pty.c, src/selinux.c,
+ src/sudo.c, src/tgetpass.c:
+ Check for dup2() failure.
+ [5d46d66794f5]
+
+ * config.h.in, configure, configure.in:
+ Remove dup2() check, it is not optional.
+ [5f1d56de4384]
+
+2010-06-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * WHATSNEW:
+ sync with sudo 1.7.3
+ [88e5c0bd6d59]
+
+ * INSTALL:
+ SunOS does not ship with an ANSI compiler
+ [f13c85c67069]
+
+ * INSTALL:
+ Update OS specific notes. Delete some really ancient ones and move
+ older ones to the end of the list.
+ [59ce592c4c52]
+
+ * README:
+ Sudo can be downloaded from the web site too Mention "OS dependent
+ notes" section in INSTALL
+ [191871538984]
+
+ * src/exec_pty.c, src/selinux.c:
+ Call selinux_restore_tty() as part of cleanup() so it gets called
+ from error()/errorx()
+ [bb017da6b6da]
+
+ * MANIFEST, doc/PORTING:
+ Remove obsolete porting guide
+ [321e35591344]
+
+ * plugins/sudoers/interfaces.h, plugins/sudoers/match.c:
+ Move union sudo_in_addr_un into interfaces.h
+ [b2c8b19ee094]
+
+ * doc/Makefile.in:
+ Remove useless circular dependencies
+ [5682181b59cf]
+
+ * plugins/sudoers/auth/afs.c, plugins/sudoers/auth/aix_auth.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/dce.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/kerb4.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid.c,
+ plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c:
+ Convert to ANSI C function declarations
+ [a4f76927d034]
+
+ * common/alloc.c, common/fileops.c, common/gettime.c, common/list.c,
+ common/zero_bytes.c, compat/charclass.h, compat/closefrom.c,
+ compat/fnmatch.c, compat/glob.c, compat/isblank.c, compat/memrchr.c,
+ compat/mkstemp.c, compat/nanosleep.c, compat/snprintf.c,
+ compat/strcasecmp.c, compat/strerror.c, compat/strlcat.c,
+ compat/strlcpy.c, compat/timespec.h, compat/utime.h,
+ compat/utimes.c, doc/HISTORY, doc/history.pod, doc/license.pod,
+ include/alloc.h, include/error.h, include/lbuf.h, include/list.h,
+ include/missing.h, pathnames.h.in, plugins/sudoers/alias.c,
+ plugins/sudoers/audit.c, plugins/sudoers/auth/sudo_auth.h,
+ plugins/sudoers/boottime.c, plugins/sudoers/bsm_audit.c,
+ plugins/sudoers/bsm_audit.h, plugins/sudoers/defaults.c,
+ plugins/sudoers/defaults.h, plugins/sudoers/find_path.c,
+ plugins/sudoers/getspwuid.c, plugins/sudoers/goodpath.c,
+ plugins/sudoers/gram.y, plugins/sudoers/interfaces.c,
+ plugins/sudoers/interfaces.h, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h, plugins/sudoers/match.c,
+ plugins/sudoers/parse.h, plugins/sudoers/plugin_error.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/redblack.c,
+ plugins/sudoers/redblack.h, plugins/sudoers/sudo_nss.h,
+ plugins/sudoers/sudoers.h, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/timestr.c,
+ plugins/sudoers/toke.l, plugins/sudoers/visudo.c, src/aix.c,
+ src/conversation.c, src/error.c, src/load_plugins.c,
+ src/parse_args.c, src/sesh.c, src/sudo.h, src/sudo_noexec.c,
+ src/sudo_plugin_int.h, src/sudo_usage.h.in, src/tgetpass.c:
+ Update copyright year
+ [26ac7991f7d8]
+
+ * doc/Makefile.in:
+ Fix commented DEVDOCS when not in devel mode.
+ [e0a97eaf3793]
+
+ * plugins/sudoers/match.c:
+ Quiet a compiler warning.
+ [b2a17ebd5d38]
+
+ * plugins/sudoers/getdate.c, plugins/sudoers/getdate.y:
+ Quiet a compiler warning.
+ [687843bc593d]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/sudoers.h:
+ Make all functions in ldap.c static
+ [b2111e89eeba]
+
+ * doc/schema.ActiveDirectory:
+ Updates from Alain Roy to provide better examples for importing the
+ schema and to fix problems caused by Windows validating attributes
+ which have not yet been added before committing the changes.
+ [69f4c5ccaf89]
+
+2010-06-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in, doc/Makefile.in, doc/sudo.cat,
+ doc/sudo.man.in, doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudoers.cat, doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.man.in, doc/sudoreplay.cat, doc/sudoreplay.man.in,
+ doc/visudo.cat, doc/visudo.man.in:
+ Leave rules to build .man.in and .cat files uncommented but only
+ make them part of the "all" rule in devel mode. Generate .cat files
+ directly from .man.in instead of .man using default values in
+ configure.in
+ [c3054a44f6a5]
+
+ * configure, configure.in:
+ Bump sudo version to 1.8.0b1
+ [8f79c85135e1]
+
+ * configure, configure.in, src/sudo.c, src/sudo_usage.h.in:
+ Print configure args with verbose version information.
+ [1ce690660ed2]
+
+ * TODO, plugins/sudoers/visudo.c:
+ Remove tfd from struct sudoersfile; it is not used. Add prev pointer
+ to struct sudoersfile. Declare list of sudoersfile using TQ_DECLARE.
+ Use tq_append to append sudoers entries to the tail queue.
+ [1743f9a286e4]
+
+2010-06-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * WHATSNEW:
+ Describe tty timestamp improvements
+ [e214e863a313]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ A comment character may not be part of a command line argument
+ unless it is quoted with a backslash. Fixes parsing of: testuser
+ ALL=NOPASSWD: /usr/bin/wl #comment foo bar closes bz #441
+ [ea2e990f85ed]
+
+ * doc/sudoers.pod:
+ Make this read a little bit better when passwd_timeout is 0.
+ [39d362757f31]
+
+ * doc/sudo.man.in, doc/sudo.man.pl, doc/sudo.pod:
+ Attempt to handle a default password prompt timeout of zero more
+ gracefully.
+ [ea47d43acf5b]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ Do not override value of keepopen global, instead restore it to the
+ value we pushed onto the stack when popping.
+ [fe282e5a3402]
+
+ * plugins/sudoers/Makefile.in:
+ Add dependency for utility programs on libreplace and libcommon
+ [2339aba64928]
+
+ * compat/sigaction.c, config.h.in, configure.in, include/compat.h,
+ plugins/sudoers/logging.c, plugins/sudoers/mon_systrace.c,
+ src/exec.c, src/exec_pty.c, src/tgetpass.c:
+ Remove sigaction emulation Use SA_INTERRUPT in sa_flags
+ [7dd61f1bd8d2]
+
+ * MANIFEST, config.h.in, configure, configure.in, include/missing.h:
+ We don't use getgrouplist() at the moment so there's no need to
+ provide a compat version.
+ [1597536fbada]
+
+ * TODO:
+ sync with reality
+ [9e1a874e7885]
+
+ * include/sudo_plugin.h, plugins/sudoers/auth/sudo_auth.c,
+ src/conversation.c, src/sudo.h, src/tgetpass.c:
+ Fix visiblepw sudoers option; the plugin API portion still needs
+ documenting
+ [60b6933ef5e0]
+
+ * src/sudo.c:
+ Print sudo version as well.
+ [987ed459b459]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c:
+ Use sudo_printf for I/O log version Clarify policy plugin version
+ string
+ [5a58b7e8c80b]
+
+ * plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/ldap.c, plugins/sudoers/sudoreplay.c:
+ Silence some compiler warnings
+ [afb1eba90915]
+
+ * src/load_plugins.c, src/tgetpass.c:
+ Store askpass path in a global instead of uses setenv() which many
+ systems lack.
+ [b440bcc0e660]
+
+2010-06-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod, doc/sudo_plugin.cat,
+ doc/sudo_plugin.man.in, doc/sudo_plugin.pod,
+ plugins/sudoers/check.c, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, src/load_plugins.c, src/parse_args.c,
+ src/tgetpass.c:
+ Move askpass path specification from sudoers to sudo.conf.
+ [5507ab867c26]
+
+ * src/exec.c, src/exec_pty.c, src/sudo.c, src/sudo.h:
+ Use a flag bit in struct command_details for selinux instead of a
+ separate field.
+ [c59ca4acded9]
+
+ * src/exec.c, src/exec_pty.c, src/sudo.c, src/sudo.h:
+ Implement background mode. If I/O logging we use pipes instead of a
+ pty.
+ [c07a4b356cbd]
+
+ * compat/mksiglist.c, compat/strsignal.c, include/compat.h,
+ src/exec.c, src/exec_pty.c, src/tgetpass.c:
+ Move compat definition of NSIG to compat.h
+ [ab0385467f25]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod, doc/sudo_plugin.cat,
+ doc/sudo_plugin.man.in, doc/sudo_plugin.pod:
+ Mention plugins in the sudo manual and add some missing path
+ substitution in the sudo_plugin manual.
+ [570f831f47a3]
+
+ * src/Makefile.in:
+ Set _PATH_SUDO_CONF based on $(sysconfdir)
+ [fde51869cf07]
+
+ * common/lbuf.c, common/term.c, config.h.in, configure, configure.in,
+ src/exec.c, src/exec_pty.c, src/ttysize.c:
+ Require POSIX termios to build sudo
+ [9ec6b41f3f95]
+
+ * src/tgetpass.c:
+ Ignore SIGPIPE for "sudo -S"
+ [7ad27fde0c06]
+
+ * src/tgetpass.c:
+ Fix uninitialized variable in TGP_ECHO case and print a newline if
+ the user interrupted password input.
+ [ce19204d8dd4]
+
+ * src/tgetpass.c:
+ Make TGP_ECHO override TGP_MASK and don't try to restore the
+ terminal if we didn't modify it.
+ [a7e11abfe7e4]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod,
+ include/sudo_plugin.h, plugins/sudoers/auth/sudo_auth.c,
+ src/conversation.c, src/sudo.h, src/tgetpass.c:
+ Add SUDO_CONV_PROMPT_MASK define which corresponds to the
+ "pwfeedback" sudoers option. Do not disable echo if TGP_ECHO is set.
+ [e0550590cabe]
+
+ * src/exec_pty.c:
+ Use POSIX tcgetpgrp() instead of BSD TIOCGPGRP ioctl
+ [762448182fe3]
+
+ * src/exec_pty.c:
+ Remove commented out copy of old sudo_execve() function.
+ [9c5e21380472]
+
+2010-06-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/compat.h:
+ No longer need NGROUPS_MAX define
+ [cae4c49d7077]
+
+ * compat/nanosleep.c, config.h.in, configure, configure.in,
+ include/compat.h, plugins/sudoers/check.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/visudo.c, src/sudo_edit.c:
+ Replace timerfoo macros with timevalfoo since the timer macros are
+ known to be busted on some systems.
+ [4f97d79f2d41]
+
+ * src/exec.c, src/exec_pty.c, src/selinux.c, src/sudo.c, src/sudo.h:
+ Add selinux_enabled flag into struct command_details and set it in
+ command_info_to_details(). Return an error from selinux_setup()
+ instead of exiting. Call selinux_setup() from exec_setup().
+ [011bea23a5a0]
+
+ * plugins/sudoers/sudoers.c:
+ Fix setting selinux type on command line.
+ [814b20a0b3be]
+
+ * plugins/sudoers/iolog.c:
+ In sudoers_io_close(), skip NULL io_fds[] elements.
+ [4011ff7d4daf]
+
+ * plugins/sudoers/auth/pam.c:
+ If pam_open_session() fails, pass its status to pam_end.
+ [1d8de4cf8ff3]
+
+ * plugins/sudoers/toke.c, plugins/sudoers/toke.l:
+ If a file in a #includedir has improper permissions or owner just
+ skip it. This prevents packages that incorrectly install a file into
+ /etc/sudoers.d from breaking sudo so easily. Syntax errors in
+ #includedir files still result in a parse error (for now).
+ [ade99a4549a4]
+
+ * src/exec_pty.c:
+ Remove duplicate call to selinux_setup().
+ [82bd52764e21]
+
+ * WHATSNEW, doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/iolog.c:
+ Add use_pty sudoers option to force use of a pty even when not
+ logging I/O.
+ [b280a8972a79]
+
+ * plugins/sudoers/env.c, plugins/sudoers/sudoers.h:
+ Make env_init() void as it never fails.
+ [d3890e55daa7]
+
+ * plugins/sudoers/env.c:
+ No longer use _NSGetEnviron so don't need crt_externs.h
+ [9b4e0e139881]
+
+ * plugins/sudoers/env.c:
+ Remove unused VNULL define
+ [a42cacb263e3]
+
+2010-06-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ Add #define for maximum session id
+ [9e18c17a28c2]
+
+ * MANIFEST, src/Makefile.in, src/exec.c, src/exec_pty.c, src/sudo.h:
+ Split exec.c into exec.c and exec_pty.c
+ [d52376327332]
+
+ * MANIFEST:
+ Sync with source file moves.
+ [4a62c6c9e846]
+
+ * src/Makefile.in, src/get_pty.c, src/pty.c:
+ Rename pty.c -> get_pty.c
+ [5696a12bd29b]
+
+2010-06-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ Only use I/O input log file if def_log_input is set and output file
+ if def_log_output is set.
+ [d866992f1681]
+
+2010-06-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/strsignal.c:
+ Update copyright year
+ [a96f2593fd4e]
+
+ * src/pty.c:
+ uid -> ttyuid
+ [c3454d74ebcb]
+
+ * plugins/sudoers/sudoers.c:
+ For sudoedit, make a local copy of editor string si become part of
+ argv. If no editor environment variable, split def_editor on ':'
+ since it may be a colon-delimited path.
+ [2ee298506a6e]
+
+ * src/sudo_edit.c:
+ Remove unneeded endpwent()/endgrent()
+ [623f6743d101]
+
+ * doc/Makefile.in:
+ Use value of nroff from configure
+ [b2ce649125ab]
+
+ * src/exec.c:
+ Add missing const to I/O log action function
+ [d764a3955e04]
+
+ * plugins/sudoers/check.c:
+ Update copyright year and fix whitespace
+ [e648c35b16be]
+
+ * configure, configure.in:
+ Fix typo
+ [8e0bdfc47da4]
+
+ * plugins/sudoers/iolog.c:
+ Remove redundant tty signal blocking in log function.
+ [f17f575dabd4]
+
+2010-06-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ Place static keyword where it belongs
+ [b01aec7c86b4]
+
+ * plugins/sudoers/logging.c:
+ Always use a printf format string for send_mail()
+ [13b1ada644c9]
+
+ * common/atobool.c, plugins/sudoers/ldap.c:
+ Extend atobool() so we can use it in the LDAP code.
+ [73f8e6807044]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod:
+ Sudo now stashes tty ctime for tty_tickets on Solaris too.
+ [e82df13ad3fd]
+
+ * plugins/sudoers/boottime.c:
+ Fix dummy version of get_boottime()
+ [01d69c06013b]
+
+2010-06-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c:
+ Enable tty_is_devpts() support for Solaris with the "devices"
+ filesystem.
+ [237c6b25fa84]
+
+ * src/exec.c:
+ Unbreak the non-io logging case.
+ [4822b9f709fb]
+
+ * src/conversation.c, src/sudo.c, src/sudo_plugin_int.h:
+ Fix symbol name conflict with sudo_printf.
+ [0d44eab0a8f6]
+
+ * plugins/sudoers/auth/pam.c:
+ Fix OpenPAM detection for newer versions.
+ [1b2abed232d8]
+
+ * plugins/sudoers/vasgroups.c:
+ Sync with Quest sudo git repo
+ [f1d98b3cba02]
+
+ * aclocal.m4, configure, configure.in:
+ HP-UX ld uses +b instead or -R or -rpath Fix typo in libvas check
+ Add missing template for ENV_DEBUG Adapted from Quest sudo
+ [695dbd7b28f4]
+
+ * README.LDAP:
+ Fix typos; from Quest Sudo
+ [4eba9da33b8e]
+
+2010-06-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ Add back -I$(top_srcdir); we need it for including compat/foo.h
+ since we cannot rely on "foo.h" being found relative to the source
+ file when the cwd is different.
+ [bbf24695f325]
+
+ * src/exec.c:
+ Fix a bug where we could treat EAGAIN as a permanent error. Also set
+ cstat if perform_io() returns an error.
+ [200475c4326f]
+
+ * common/alloc.c, plugins/sudoers/boottime.c,
+ plugins/sudoers/sudoers.c:
+ Add casts to quiet compiler warnings.
+ [85eb1c336697]
+
+ * plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c:
+ Fix typo in ternary operator usage.
+ [6492ac1450e2]
+
+2010-05-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, configure, configure.in:
+ Add --enable-warnings and fix typo in SUDO_IO_LOGDIR
+ [92121d693b30]
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod,
+ doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.pod:
+ Update docs to match sudoers I/O logging changes
+ [18d651989e49]
+
+ * INSTALL, WHATSNEW, aclocal.m4, configure, configure.in,
+ pathnames.h.in, plugins/sudoers/def_data.c,
+ plugins/sudoers/def_data.h, plugins/sudoers/def_data.in,
+ plugins/sudoers/defaults.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.h, plugins/sudoers/gram.y,
+ plugins/sudoers/iolog.c, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoreplay.c:
+ Break sudoers transcript feature up into log_input and log_output.
+ [db3c1248d2ad]
+
+ * plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/visudo.c:
+ Use setprogname() as needed.
+ [6beee63a4553]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/sudoreplay.c:
+ Adapt sudoreplay to iolog changes.
+ [581f52c05f0f]
+
+2010-05-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/iolog.c:
+ Log all input and output into separate files and store a number on
+ each timing file line to indicate which file the data is in.
+ [fb460c5273dd]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Make sudoers_io functions static to iolog.c
+ [b2df3cc3eecb]
+
+2010-05-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod, src/parse_args.c,
+ src/sudo_usage.h.in:
+ Completely remove the -L flag from the sudo front end.
+ [3d220030b720]
+
+ * plugins/sudoers/sudoreplay.c:
+ Fix EAGAIN handling when writing to stdout.
+ [4766d77cea49]
+
+ * plugins/sudoers/sudoers.c:
+ Eliminate unused variables
+ [83bd711e79c4]
+
+ * plugins/sudoers/sudoers.c, src/exec.c, src/sudo.c:
+ Re-enable cleanup functions in sudoers plugin and sudo driver for
+ error()/errorx().
+ [43093f937dd8]
+
+ * plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/interfaces.c, plugins/sudoers/iolog.c,
+ plugins/sudoers/parse.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c:
+ Use sudo_printf to display verbose version information.
+ [435cc9f8d4a2]
+
+ * common/Makefile.in, compat/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, src/Makefile.in:
+ Minor Makefile cleanup: fix a typo, change the removal order in the
+ clean targets, and remove a superfluous include path for the sudoers
+ plugin.
+ [6e3b2d6b4437]
+
+ * plugins/sudoers/env.c:
+ Handle duplicate variables in the environment. For unsetenv(), keep
+ looking even after remove the first instance. For sudo_putenv(),
+ check for and remove dupes after we replace an existing value.
+ [c1bbb88d0435]
+
+2010-05-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ Use explicit path to source file instead of $< for files that live
+ in devdir and top_srcdir.
+ [358ab7f6cc64]
+
+ * plugins/sudoers/Makefile.in:
+ Add explicit rules to compile gram.c and toke.c for HP-UX Pevent
+ ending LIBSUDOERS_OBJS with a backslash
+ [481a5c96d47e]
+
+ * plugins/sudoers/Makefile.in, src/Makefile.in:
+ Link libcommon before libreplace since libcommon may use functions
+ only present in libreplace.
+ [1847c496ff5b]
+
+ * common/Makefile.in:
+ Move code common to sudo and the sudoers plugin to a convenience
+ library, libcommon. Removes the need to make links in the sudoers
+ plugin dir and reduces re-compilation of duplicate object files.
+ [4c8986352937]
+
+ * Makefile.in, common/alloc.c, common/atobool.c, common/fileops.c,
+ common/fmt_string.c, common/gettime.c, common/lbuf.c, common/list.c,
+ common/term.c, common/zero_bytes.c, configure, configure.in,
+ plugins/sample/Makefile.in, plugins/sudoers/Makefile.in,
+ src/Makefile.in, src/alloc.c, src/atobool.c, src/fileops.c,
+ src/fmt_string.c, src/gettime.c, src/lbuf.c, src/list.c, src/term.c,
+ src/zero_bytes.c:
+ Move code common to sudo and the sudoers plugin to a convenience
+ library, libcommon. Removes the need to make links in the sudoers
+ plugin dir and reduces re-compilation of duplicate object files.
+ [1d1d98bd55b9]
+
+ * src/exec.c, src/sudo.c, src/sudo.h:
+ Rename script_execve to sudo_execve and rename script_foo in exec.c
+ [a35ec80de96a]
+
+ * MANIFEST, src/Makefile.in, src/exec.c, src/script.c:
+ rename script.c exec.c and fix up the MANIFEST file
+ [36bc3bff9578]
+
+ * src/script.c, src/sudo.c, src/sudo.h:
+ Rename script_setup() to pty_setup() and call from script_execve()
+ directly.
+ [899b0fb2a14d]
+
+ * configure, configure.in:
+ bump version to 1.8.0a2
+ [0b1c1ca9d4e5]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod:
+ Document init_session
+ [b5324785a406]
+
+ * plugins/sudoers/auth/API, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h:
+ Clean up the sudoers auth API a bit and update the docs.
+ [c40fd4cb6e68]
+
+ * include/sudo_plugin.h, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, src/script.c, src/sudo.c:
+ Add init_session function to struct policy_plugin that gets called
+ before the uid/gid/etc changes. A struct passwd pointer is passed
+ in,which may be NULL if the user does not exist in the passwd
+ database.The sudoers module uses init_session to open the pam
+ session as needed.
+ [d71723320ee8]
+
+2010-05-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/pam.c, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/auth/sudo_auth.h, plugins/sudoers/set_perms.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Add open/close session to sudo auth, only used by PAM. This allows
+ us to open (and close) the PAM session from sudoers.
+ [2665e2920d0d]
+
+ * plugins/sudoers/Makefile.in:
+ Add explicit rule to build getdate.o for HP-UX make.
+ [7f049e989956]
+
+ * plugins/sudoers/Makefile.in:
+ Back out most of change 45e406ebdea2. Create dummy .l.c and .y.c
+ rules as an alternate way to prevent HP-UX make (and others) from
+ trying to rebuild the parser in non-dev mode.
+ [f84badad98c5]
+
+ * plugins/sudoers/sudoers.c:
+ Re-enable PATH_MAX check for command
+ [40d8a50da136]
+
+ * Makefile.in:
+ For distclean, clean the main directory last since the subdirs need
+ to be able to run libtool to clean things.
+ [8949a9861634]
+
+ * compat/Makefile.in:
+ Fix generation of mksiglist.h
+ [b7cdc9b36650]
+
+ * src/script.c:
+ Now that we defer sending cstat until the end of script_child() we
+ cannot reuse cstat when reading command status from parent.
+ [25c882643466]
+
+2010-05-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in, doc/sudo.man.in, doc/sudo.man.pl,
+ doc/sudoers.cat, doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in,
+ doc/sudoers.man.in, doc/sudoers.man.pl, doc/sudoreplay.cat,
+ doc/sudoreplay.man.in, doc/visudo.cat, doc/visudo.man.in:
+ Use numeric registers to handle conditionals instead of trying to do
+ it all with text processing.
+ [478079c3fd4b]
+
+ * doc/sudoers.pod:
+ Document per-command SELinux settings
+ [13840d566805]
+
+ * plugins/sudoers/sudoers.c:
+ Repair "sudo -l -U username"
+ [10a0dcdf2ddf]
+
+ * plugins/sudoers/sudoers.c:
+ Set selinux role and type in command details.
+ [8ae6d35a126d]
+
+ * src/script.c, src/selinux.c, src/sudo.h:
+ Rework SELinux support.
+ [83279cc94bf2]
+
+2010-05-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/script.c, src/selinux.c, src/sudo.h:
+ Make SELinux support compile again. Needs more work to be complete.
+ [3d3addebcf82]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ src/parse_args.c, src/script.c, src/selinux.c, src/sudo.c,
+ src/sudo.h:
+ Bring back closefrom settings.
+ [b1c6257d4bbb]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ If running a command or sudoedit in transcript mode, call
+ io_nextid() before log_allowed() so the session id is logged.
+ [c42f3ae40150]
+
+ * configure, configure.in:
+ Use mandoc(1) if nroff(1) is not present.
+ [daad4bbd04af]
+
+ * doc/Makefile.in:
+ Use the --file argument to config.status instead of setting
+ CONFIG_FILES in the environment.
+ [c89411a8bf70]
+
+ * plugins/sudoers/Makefile.in:
+ We cannot conditionally update gram.h or the dependency ordering
+ gets messed up in devel mode.
+ [c938953231d9]
+
+2010-05-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, compat/Makefile.in, configure, configure.in,
+ doc/Makefile.in, include/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, src/Makefile.in:
+ Substitute @SHELL@ into Makefiles
+ [36aa6a095335]
+
+ * config.sub:
+ Fix typo
+ [16d294d26b58]
+
+ * config.guess, config.sub, configure, configure.in:
+ Update to autoconf 2.65
+ [4fa6ea8caea3]
+
+ * Makefile.in:
+ Fix libtool target (space vs. tabs)
+ [755cf3892618]
+
+ * config.h.in, plugins/sudoers/logging.h, plugins/sudoers/visudo.c:
+ Remove use of RETSIGTYPE; all modern systems have signal handlers
+ that return void.
+ [42b4e3aee668]
+
+ * Makefile.in, aclocal.m4, acsite.m4, configure, configure.in,
+ ltmain.sh, m4/libtool.m4, m4/ltoptions.m4, m4/ltsugar.m4,
+ m4/ltversion.m4, m4/lt~obsolete.m4, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, src/Makefile.in:
+ Update to libtool-2.2.6b. I haven't made any local modifications
+ this time, which should be OK since we install sudo_noexec.so by
+ hand now.
+ [6f79ced593bb]
+
+ * compat/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, src/Makefile.in:
+ Use libtool to clean objects
+ [1581057d6472]
+
+ * include/Makefile.in:
+ Install sudo_plugin.h as part of "make install" and make other
+ install targets callable from the top-level Makefile
+ [aaaeb027d774]
+
+ * configure, configure.in:
+ regen with autoupdate to eliminate AC_TRY_LINK
+ [5d5541c230f5]
+
+ * Makefile.in, compat/Makefile.in, configure, configure.in,
+ doc/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, src/Makefile.in:
+ Install sudo_plugin.h as part of "make install" and make other
+ install targets callable from the top-level Makefile
+ [b258b8401b1c]
+
+ * plugins/sample/sample_plugin.c:
+ The sample plugin doesn't support being run with no args so return a
+ usage error in this case.
+ [473b3cf965be]
+
+ * plugins/sudoers/iolog.c:
+ Set close on exec flag for descriptors used for I/O logging so they
+ are not present in the command being run.
+ [2c7e8708df76]
+
+ * plugins/sudoers/tsgetgrpw.c:
+ Set close on exec flag in private versions of setpwent() and
+ setgrent().
+ [64fef78cb833]
+
+ * src/script.c:
+ Close the I/O pipes aftering dup2()ing them to std{in,out,err}.
+ Fixes extra fds being present in the command when it is part of a
+ pipeline.
+ [060451617713]
+
+ * plugins/sudoers/sudoers.c:
+ Set user_tty to "unknown" if there is no tty, like sudo 1.7 does (it
+ is used when logging). Note that user_ttypath will still be NULL if
+ there is no tty.
+ [31b69a6ecda7]
+
+ * src/script.c, src/sudo.h:
+ Cosmetic changes: add comments, remove orphaned prototype and make a
+ global static.
+ [f7851af0143e]
+
+2010-05-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/script.c:
+ Move check for maxfd == -1 to flush_output where it belongs.
+ [b826a95b4491]
+
+ * src/script.c:
+ Break out of select loop if all the fds we want to select on are -1.
+ [f5b387024238]
+
+ * src/sudo.c:
+ Avoid possible malloc(0) if plugin returns an empty groups list.
+ [9765a8fe5ce7]
+
+ * src/sudo.c:
+ Add debugging info when calling plugin close function
+ [95a273c7ff66]
+
+ * src/script.c:
+ Avoid closing stdin/stdout/stderr when we are piping output.
+ [330e76423caf]
+
+ * src/script.c:
+ When execve() of the command fails, it is possible to receive
+ SIGCHLD before we've read the error status from the pipe. Re-order
+ things such that we send the final status at the very end and prefer
+ error status over wait status.
+ [b0dcf825244f]
+
+2010-05-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/sudo_auth.c:
+ Fix compilation for non PAM/BSD auth/AIX auth
+ [e382b39d2e4f]
+
+2010-05-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/script.c:
+ Additional checks to make sure we don't close /dev/tty by mistake.
+ When flushing, sleep in select as long as we have buffers that need
+ to be written out.
+ [8139cbd3dd54]
+
+ * src/script.c:
+ Now that we can use pipes for stdin/stdout/stderr there is no longer
+ a need to error out when there is no tty. We just need to make sure
+ we don't try to use the tty fd if it is -1.
+ [666621635d26]
+
+2010-05-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod,
+ include/sudo_plugin.h, plugins/sample/sample_plugin.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/sudoers.h, src/sudo.c:
+ Add argc and argv to I/O logger open function.
+ [0d7faa007d27]
+
+ * doc/sudo_plugin.man.in, doc/sudo_plugin.pod, include/sudo_plugin.h,
+ plugins/sample/sample_plugin.c, plugins/sudoers/sudoers.c,
+ src/parse_args.c, src/sudo.c, src/sudo_edit.c:
+ Remove check_sudoedit function pointer in struct sudo_policy.
+ Instead, sudo will set sudoedit=true in the settings array. The
+ plugin should check for this and modify argv_out as appropriate in
+ check_policy.
+ [c0328e3276b8]
+
+2010-05-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sample/sample_plugin.c, src/sudo.c, src/sudo.h,
+ src/sudo_edit.c:
+ If plugin sets "sudoedit=true" in the command info, enable sudoedit
+ mode even if not invoked as sudoedit. This allows a plugin to enable
+ sudoedit when the user runs an editor.
+ [96d67b99e42e]
+
+2010-05-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ gram.h must not depend on gram.y if we want to avoid unnecessary
+ rebuilding of targets dependent on gram.h when gram.y changes.
+ [9db4b767fdca]
+
+ * plugins/sample/sample_plugin.c:
+ Refactor common bits of check_policy and check_edit
+ [ac4d366a04cf]
+
+ * plugins/sample/sample_plugin.c:
+ Add sudoedit support
+ [a1a6cc4c0cef]
+
+2010-05-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in:
+ Rely more on VPATH; fixes a dependency issue with the parser.
+ [45e406ebdea2]
+
+ * include/compat.h:
+ Fix typo introduced in last commit
+ [3ccb0f853d11]
+
+ * include/compat.h:
+ Emulate seteuid using setreuid() or setresuid() as needed. There are
+ still a few places that call seteuid() directly.
+ [36e8efa3a99d]
+
+ * src/parse_args.c, src/sudo_edit.c:
+ Attempt to fix building on systems that only have setuid.
+ [8e9ba4083318]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod:
+ Clarify sudoedit a tad.
+ [d39dfaa14ade]
+
+2010-05-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo_edit.c:
+ Fix compilation on HP-UX
+ [f6e47843d139]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod:
+ Document sudoedit
+ [4cbf5196d993]
+
+ * plugins/sudoers/sudoers.c, src/sudo.c, src/sudo.h, src/sudo_edit.c:
+ Change how we handle the sudoedit argv. We now require that there be
+ a "--" in argv to separate the editor and any command line arguments
+ from the files to be edited.
+ [20623d549a3c]
+
+ * include/sudo_plugin.h, plugins/sample/sample_plugin.c,
+ plugins/sudoers/Makefile.in, plugins/sudoers/gettime.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c,
+ src/Makefile.in, src/gettime.c, src/parse_args.c, src/sudo.c,
+ src/sudo.h, src/sudo_edit.c:
+ Work in progress support for sudoedit. The actual interface used by
+ the plugin for sudoedit is likely to change.
+ [c31262a31997]
+
+ * plugins/sudoers/find_path.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/visudo.c:
+ Make find_path() a little more generic by not checking def_foo
+ variables inside it. Instead, pass in ignore_dot as a function
+ argument.
+ [9c23101a094d]
+
+ * plugins/sudoers/env.c:
+ Add version of getenv(3) that uses our own environ pointer.
+ [0e3783e63534]
+
+2010-05-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/script.c:
+ Avoid a potential race condition if SIGCHLD is received immediately
+ before we call select().
+ [99adc5ea7f0a]
+
+ * plugins/sudoers/sudoers.c:
+ Call env_init() before we open the sudoers sources as those may call
+ our setenv() replacement.
+ [5f82601f5ab0]
+
+ * plugins/sudoers/env.c:
+ Initialize env_len in env_init()
+ [7ae02b3029b5]
+
+2010-05-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod:
+ Document time stamp shortcomings under SECURITY NOTES Use "time
+ stamp" instead of timestamp.
+ [2b86120815b2]
+
+ * doc/Makefile.in:
+ Make sed substitution of mansectsu and mansectform global.
+ [94588632dba0]
+
+ * plugins/sudoers/check.c:
+ If the tty lives on a devpts filesystem, stash the ctime in the tty
+ ticket file, as it is not updated when the tty is written to. This
+ helps us determine when a tty has been reused without the user
+ authenticating again with sudo.
+ [0e62a31bceb0]
+
+ * src/tgetpass.c:
+ Fix pasto in mulitple signal fix and use _NSIG not NSIG since that
+ is what our compat checks set.
+ [df50f0a040c9]
+
+ * configure, configure.in:
+ Add check for whether sudo need to link with -ldl to get dlopen().
+ This is a bit of a hack that will get reworked when libtool is
+ updated.
+ [63bdcf579533]
+
+ * plugins/sudoers/check.c:
+ Fix timestamp removal with -k/-K
+ [6b4639fef973]
+
+ * plugins/sudoers/Makefile.in:
+ audit.c is now private to the sudoers plugin
+ [1974f342ae0b]
+
+ * configure, configure.in:
+ Link with -lpthread on HP-UX since a plugin may be linked with
+ -lpthread and dlopen() will fail if the shared object has a
+ dependency on -lpthread but the main program is not linked with it.
+ [d42139391263]
+
+ * config.h.in, configure, configure.in, plugins/sudoers/set_perms.c:
+ Add separate test for getresuid() since HP-UX has setresuid() but no
+ getresuid().
+ [910fe727a374]
+
+ * doc/Makefile.in:
+ Remove errant backslash
+ [dd5464257c69]
+
+ * src/script.c:
+ Fix SIGPIPE handling. Now that we use may use pipes for stdin/stdout
+ we need to pass any SIGPIPE we receive to the running command.
+ [3f6b1991f4fd]
+
+ * src/script.c:
+ Also start the command in the background if stdin is not a tty.
+ [d93bc33a3740]
+
+2010-05-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoreplay.c, src/script.c, src/sudo.h, src/term.c:
+ No need to use pseudo-cbreak mode now that we use pipes when stdout
+ is not a tty. Instead, check whether stdin is a tty and if not,
+ delay setting the tty to raw mode until the command tries to access
+ it itself (and receives SIGTTIN or SIGTTOU).
+ [e68315cf8c6b]
+
+ * src/tgetpass.c:
+ Use an array for signals received instead of a single variable so we
+ don't lose any when there are multiple different signals.
+ [2ac726dac864]
+
+ * src/tgetpass.c:
+ Do signal setup after turning off echo, not before. If we are using
+ a tty but are not the foreground pgrp this will generate SIGTTOU so
+ we want the default action to be taken (suspend process).
+ [bebb6209c795]
+
+2010-05-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/script.c:
+ Flush the iobufs on suspend or child exit using the same logic as
+ the main event loop.
+ [c627feee1035]
+
+ * src/script.c:
+ Free memory after we are done with it.
+ [8db9b611b45a]
+
+2010-05-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/HISTORY:
+ Quest now sponsors Sudo development
+ [6cc490083bc7]
+
+2010-05-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/Makefile.in:
+ Install sudo_plugin man page.
+ [c253729790b2]
+
+ * src/script.c:
+ Go back to reseting io_buffer offset and length (and now also the
+ EOF handling) in the loop we do the FD_SET, not after we drain the
+ buffer after write() since we don't know what order reads and writes
+ will occur in.
+ [5f38bfa8497f]
+
+ * MANIFEST:
+ audit files moved to sudoers plugin directory
+ [b1ead182428e]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod:
+ Document plugin_printf and new logging functions.
+ [fe9430b60ab5]
+
+ * src/script.c:
+ Add support for logging stdin when it is not a tty. There is still a
+ bug where "cat | sudo cat" has problems because both cat and sudo
+ are trying to read from the tty.
+ [04c9c59fcfba]
+
+ * include/sudo_plugin.h, plugins/sample/sample_plugin.c,
+ plugins/sudoers/sudoers.c, src/script.c:
+ Add separate I/O logging functions for tty in/out and
+ stdin/stdout/stderr. NOTE: stdin logging does not currently work and
+ is disabled for now.
+ [a36dfd4ca935]
+
+2010-05-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/sudo_plugin.h, plugins/sample/sample_plugin.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/logging.c, plugins/sudoers/plugin_error.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ src/conversation.c, src/sudo.c, src/sudo_plugin_int.h:
+ Add pointer to a printf like function to plugin open functon. This
+ can be used instead of the conversation function to display info and
+ error messages.
+ [98734eea8ef1]
+
+ * Makefile.in:
+ Stop if make in a subdir fails
+ [228bb3ad2dbc]
+
+ * src/script.c:
+ Only set user's tty to blocking mode when doing the final flush.
+ Flush pipes as well as pty master when the process is done.
+ [20ff67218666]
+
+2010-05-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/ldap.c:
+ Use print_error() when displaying ldap config info in debugging
+ mode.
+ [d142e0cacb22]
+
+ * compat/Makefile.in, compat/strdup.c, compat/strndup.c:
+ No longer need strdup() or strndup() replacements.
+ [df53697174ec]
+
+ * plugins/sudoers/logging.c, plugins/sudoers/plugin_error.c,
+ plugins/sudoers/sudoers.h:
+ Add print_error() function that uses the conversation function to
+ print a variable number of error strings and use it in log_error().
+ [b1fa2861b575]
+
+ * src/script.c, src/sudo.h, src/term.c:
+ Do not need the opost flag to term_copy() now that we use pipes for
+ stdout/stderr when they are not a tty.
+ [f42811f70a19]
+
+ * src/script.c:
+ Use pipes to the sudo process if stdout or stderr is not a tty.
+ Still needs some polishing and a decision as to whether it is
+ desirable to add additonal entry points for logging
+ stdout/stderr/stdin when they are not ttys. That would allow a
+ replay program to keep things separate and to know whether the
+ terminal needs to be in raw mode at replay time.
+ [1a945e0ab2da]
+
+2010-04-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/audit.c,
+ plugins/sudoers/bsm_audit.c, plugins/sudoers/bsm_audit.h,
+ src/audit.c, src/bsm_audit.c, src/bsm_audit.h:
+ Move audit sources into the sudoers plugin dir; the driver does not
+ use them.
+ [50ec36422cd0]
+
+ * compat/getline.c, compat/mksiglist.c, compat/nanosleep.c,
+ compat/strdup.c, compat/strndup.c, plugins/sample/sample_plugin.c,
+ plugins/sudoers/boottime.c, plugins/sudoers/getdate.c,
+ plugins/sudoers/match.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/timestr.c, plugins/sudoers/vasgroups.c, src/alloc.c,
+ src/atobool.c, src/audit.c, src/lbuf.c, src/list.c, src/sesh.c,
+ src/term.c, src/ttysize.c:
+ Use angle brackets when including headers that can only be found
+ when an -I flag is specified. The files in the compat dir could get
+ away with double quotes here but I've converted all the source files
+ to use angle brackets for consistency.
+ [9e30a8fc6d4b]
+
+ * plugins/sudoers/Makefile.in:
+ Add missing -I$(top_srcdir) to CPPFLAGS so includes in the compat
+ dir can be found when building outside the source tree.
+ [1150934b79dd]
+
+ * plugins/sudoers/Makefile.in:
+ Clean up links in distclean
+ [78595028be8b]
+
+ * plugins/sudoers/Makefile.in:
+ Hack around VPATH semantic differences by symlinking files we need
+ from ../../src into the current directory and build those. A better
+ fix would be to either make a .a or .la file with those files in it
+ or simply use a single, flat, Makefile instead of per-subdirs
+ Makefiles.
+ [892c332d3f05]
+
+ * plugins/sudoers/Makefile.in, src/Makefile.in, src/fmt_string.c:
+ fmt_string is used by the sudoers plugin too so do not include
+ sudo.h (which is not really needed here anyway)
+ [231c35e3941f]
+
+ * compat/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, src/Makefile.in:
+ Fix building with non-BSD versions of make such as GNU make.
+ Requires VPATH support, which should be in any non-neolithic make.
+ [dc174f135919]
+
+ * configure, configure.in, plugins/sudoers/Makefile.in,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/sudoers.c,
+ src/Makefile.in:
+ Re-enable bsm audit. Currently auditing is done within the sudoers
+ plugin itself. If possible, this should really be done in the main
+ driver but we don't presently have the needed data to do that. This
+ will be re-evaluated when Linux audit support is added.
+ [1d05a3236bfe]
+
+ * compat/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, src/Makefile.in:
+ Remove extraneous $srcdir and use more .c.lo and .c.o rules instead
+ of explicit rules in the dependency.
+ [88f80efd25f0]
+
+ * plugins/sudoers/visudo.c:
+ Fix mismerge; alias_remove_recursive() now returns int
+ [6257a4849641]
+
+2010-04-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/visudo.c:
+ Fix a crash when checking a sudoers file that has aliases that
+ reference themselves. Based on a diff from David Wood.
+ [545d194484a7]
+
+ * src/script.c:
+ Print signal info after restoring the tty mode, not before.
+ [a68618e67435]
+
+ * src/script.c:
+ Defer call to alarm() until after we fork the child. Pass correct
+ pid to terminate_child() If the command exits due to signal, set
+ alive to false like we do when it exits normally. Add missing check
+ for errpipe[0] != -1 before using it in FD_ISSET
+ [22f0a1549391]
+
+2010-04-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/boottime.c:
+ Use 1/0 instead of TRUE/FALSE so we don't need sudoers.h
+ [0e627170c6e8]
+
+2010-04-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/Makefile.in:
+ Simplify dependencies by using .c.o and .c.lo rules.
+ [6abcaef5d1ac]
+
+ * configure, configure.in, plugins/sudoers/Makefile.in,
+ src/Makefile.in:
+ Substitute in @PROGS@ into src/Makefile to add sesh
+ [cc46d3b6208f]
+
+2010-04-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ Add back calls to log_denial() if sudoers does not allow the
+ command.
+ [9783316207f0]
+
+ * plugins/sudoers/sudoers.c:
+ Pass in correct pwflag for list and validate.
+ [973dd56d4b81]
+
+ * plugins/sudoers/env.c:
+ Add missing check for NULL in validate_env_vars
+ [1d6eb6957824]
+
+ * src/Makefile.in:
+ Add sudo_noexec.la to "all" target, otherwise it only gets built at
+ install time.
+ [644a9694d2ef]
+
+ * plugins/sudoers/sudoers.c:
+ Only set sudo_user.env_vars if the env_add list is empty.
+ [fccdf6f0e0e2]
+
+ * plugins/sudoers/sudoers.c:
+ Set sudo_user.env_vars so that environment variables specified on
+ the command line get logged correctly.
+ [9b51012c491e]
+
+ * plugins/sudoers/env.c, plugins/sudoers/logging.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Re-enable environment files and setting environment variables on the
+ command line.
+ [5662d5645dbd]
+
+2010-04-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c:
+ Fix typo in last commit (ifndef vs ifdef) Make sure we pass ctime()
+ a pointer to time_t as tv_sec in struct timeval may be long.
+ [4de0c46e788e]
+
+ * plugins/sudoers/check.c:
+ Don't stash ctime in on-disk tty ticket info for now; on many
+ (most?) systems the ctime is updated when the tty is written to.
+ Once I have a better idea of what systems do not update ctime on
+ ttys (and have a way to test for this) the ctime stash will be
+ conditionally re-enabled.
+ [a90eeec0f648]
+
+2010-04-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * MANIFEST, Makefile.in:
+ Add back "dist" target, this time using a MANIFEST file
+ [29277c05499f]
+
+ * Makefile.in:
+ Remove Makefile in distclean target
+ [83d695f4f450]
+
+ * Makefile.in, src/Makefile.in:
+ Update clean and cleandir targets
+ [ad7b2afeb9c1]
+
+ * include/fileops.h, plugins/sudoers/sudoers.h, src/fileops.c,
+ src/sudo.h:
+ Move fileops.c defines and prototypes to filesops.h
+ [4545e9b6892d]
+
+ * plugins/sudoers/check.c:
+ Lock the tty timestamp when writing. We shouldn't have to lock when
+ reading since the file is updated via a single write system call.
+ [0c7276f02696]
+
+2010-04-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/alias.c, plugins/sudoers/check.c,
+ plugins/sudoers/defaults.c, plugins/sudoers/find_path.c,
+ plugins/sudoers/getspwuid.c, plugins/sudoers/gettime.c,
+ plugins/sudoers/goodpath.c, plugins/sudoers/interfaces.c,
+ plugins/sudoers/iolog.c, plugins/sudoers/ldap.c,
+ plugins/sudoers/logging.c, plugins/sudoers/match.c,
+ plugins/sudoers/nonunix.h, plugins/sudoers/parse.c,
+ plugins/sudoers/pwutil.c, plugins/sudoers/redblack.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timestr.c, plugins/sudoers/tsgetgrpw.c,
+ plugins/sudoers/vasgroups.c, plugins/sudoers/visudo.c:
+ Convert to ANSI C function declarations
+ [9c45def57cf7]
+
+ * plugins/sudoers/sudoers.h:
+ Remove extraneous bits and classify by source file.
+ [e8ea9f109ebb]
+
+ * include/compat.h:
+ Add timercmp macro for systems without it
+ [d3bf87b1d08e]
+
+ * plugins/sudoers/boottime.c, plugins/sudoers/check.c,
+ plugins/sudoers/sudoers.h:
+ get_boottime() now fills in a timeval struct
+ [3573c3f44e11]
+
+ * plugins/sudoers/check.c:
+ Store info from stat(2)ing the tty in the tty ticket when tty
+ tickets are in use. On most systems, this closes the loophole
+ whereby a user can log out of a tty, log back in and still have the
+ timestamp be valid.
+ [53380f9f5242]
+
+ * config.h.in, configure.in:
+ Add timespec2timeval and use it when getting ctime/mtime
+ [4cb7f7caec2c]
+
+2010-04-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/set_perms.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/testsudoers.c:
+ Convert perm setting to push/pop model; still needs some work Use
+ the stashed runas groups instead of using getgrouplist() Reset perms
+ to the initial value on error
+ [09c072ebde8b]
+
+ * config.h.in, configure.in:
+ fix ctim_get and mtim_get macros
+ [58773dc1e360]
+
+ * config.h.in, configure, configure.in, include/compat.h,
+ plugins/sudoers/check.c, plugins/sudoers/gettime.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/visudo.c, src/fileops.c:
+ Use timeval directly instead of converting to timespec when dealing
+ with file times and time of day.
+ [a0ce1ae00a67]
+
+ * plugins/sudoers/Makefile.in:
+ Don't like sudoreplay with libsudoers.la due to a yacc symbol
+ conflict.
+ [f1a59cc63a15]
+
+2010-04-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Darwin >= 9.x has real setreuid(2)
+ [7ec942a64275]
+
+2010-04-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/env.c, plugins/sudoers/sudoers.h:
+ Ansify env.c
+ [f58551bad10a]
+
+ * plugins/sudoers/env.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Remove remaining references to the environ pointer.
+ [96faa530816a]
+
+2010-04-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, plugins/sudoers/env.c:
+ Don't change the environ directly in the sudoers plugin
+ [6db48ed3f7e0]
+
+2010-04-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ Fix typo
+ [4aa452b07f8f]
+
+ * plugins/sudoers/alias.c:
+ Fix use after free in error message when a duplicate alias exists.
+ [ce1d2812ee34]
+
+2010-04-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod,
+ src/parse_args.c:
+ Add a "noninteractive" boolean to the settings passed in to the
+ plugin's open function that is set when the user specifies the -n
+ flag.
+ [68f8d9d6d4d0]
+
+ * config.h.in, configure, configure.in, plugins/sudoers/env.c:
+ Add workaround for the lack of the environ pointer on Mac OS X in
+ dlopen()ed modules. Use of environ in the sudoers plugin should
+ ultimately be removed but this will do for the moment.
+ [80c61647434f]
+
+ * plugins/sudoers/visudo.c:
+ Set errorfile to the sudoers path if we set parse_error manually.
+ This prevents a NULL dereference in printf() when checking a sudoers
+ file in strict mode when alias errors are present.
+ [45e249ca99f7]
+
+ * plugins/sudoers/sudoers.c:
+ Main sudo no longer print "unable to execute" on exec failure so do
+ it here.
+ [50aaf62b43b5]
+
+2010-04-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/script.c:
+ Use a pipe to pass back errno to the parent if execve() fails. If we
+ get an error in script_child(), kill the command and exit.
+ [dc3bf870f91b]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod,
+ src/parse_args.c, src/sudo.c:
+ Handle plugin's open function returning -2 (usage error).
+ [aadf900c1de8]
+
+ * src/script.c:
+ If execve() fails, leave it to the plugin to print an error string.
+ [e25748f2d5b9]
+
+ * src/script.c:
+ If execve fails in logging mode, pass the errno directly to the
+ grandparent on the backchannel and exit. The immediate parent will
+ get SIGCHLD and try to report that status but its parent will no
+ longer be listening. It would probably be cleaner to pass this over
+ a pipe in script_child().
+ [cb122acc81a8]
+
+ * plugins/sudoers/sudoers.c:
+ Don't override rval with results of check_user() unless it failed.
+ [46fb7e87ac7d]
+
+2010-04-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod:
+ Fix typo
+ [ccd0b693f3da]
+
+ * src/parse_args.c:
+ NULL-terminate env_add
+ [2c534368a0c3]
+
+2010-04-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo.c:
+ Call the I/O log open function before the I/O version function.
+ [e88bf898990b]
+
+ * plugins/sudoers/iolog.c:
+ Remove io_conv and just use sudo_conv
+ [a280052468eb]
+
+ * plugins/sudoers/set_perms.c:
+ Fix set/restore perms for systems w/o setresuid
+ [4160517f6666]
+
+2010-04-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/check.c, plugins/sudoers/logging.c,
+ plugins/sudoers/parse.c, plugins/sudoers/set_perms.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h:
+ Primitive set/restore permissions. Will be replaced by a push/pop
+ model.
+ [aae102290866]
+
+ * src/script.c:
+ Only need to take action on SIGCHLD in parent if no I/O logger. If
+ there is an I/O logger we will receive ECONNRESET or EPIPE when we
+ try to read from the socketpair.
+ [e1e4560401f6]
+
+2010-04-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/memrchr.c, doc/sudoers.cat, doc/sudoers.man.in,
+ doc/sudoers.pod, plugins/sudoers/find_path.c:
+ Merge fb4d571495fa from the 1.7 branch to trunk.
+ [c8fb424ad4d2]
+
+ * find_path.c:
+ Qualify the command even if it is in the current working directory,
+ e.g. "./foo" instead of just returning "foo". This removes an
+ ambiguity between real commands and possible pseudo-commands in
+ command matching.
+ [fb4d571495fa] <1.7>
+
+2010-04-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/script.c:
+ Don't set SA_RESTART when registering SIGALRM handler. Do set
+ SA_RESTART when registering SIGWINCH handler.
+ [173472b76525]
+
+ * doc/Makefile.in:
+ Add dev targets for *.man.in and *.cat that don't specfify the
+ $(srcdir) prefix.
+ [b62f425da2e4]
+
+ * src/script.c:
+ If log_input or log_output returns false, terminate the command.
+ [074f4c0c34a0]
+
+ * src/script.c:
+ Better signal handling. Instead of using a single variable to store
+ the received signal, use an array so we can't lose a signal when
+ multiple are sent. Fix process termination by SIGALRM in non-I/O
+ logger mode. Fix relaying terminal signals to the child in non-I/O
+ logger mode.
+ [7a4723aca99d]
+
+ * src/script.c:
+ Fix a race between when we get the child pid in the parent and when
+ the child process exits. The problem exhibited as a hang after a
+ short-lived process, e.g. "sudo id" when no IO logger was enabled.
+ [80bcc0aca70b]
+
+2010-04-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod:
+ Add a note about the security implications of the fast_glob option.
+ [c37a92ab7c93]
+
+ * sudoers.cat, sudoers.man.in, sudoers.pod:
+ Add a note about the security implications of the fast_glob option.
+ [84f8097553d9] <1.7>
+
+ * memrchr.c:
+ Remove duplicate includes
+ [3e8d90f4c30f] <1.7>
+
+2010-04-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in:
+ Fix up some AC_DEFINE descriptions and regen config.h.in
+ [f4655adc0db3]
+
+2010-04-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/missing.h:
+ No longer check for strdup or strndup for LIBOBJ replacement.
+ [fdc764ee8109]
+
+ * src/script.c:
+ Avoid installing signal handlers that are io-logger specific. Fixes
+ job control when no io logger is enabled.
+ [0853dd0906d4]
+
+ * doc/Makefile.in:
+ Only regen man pages from pod when configured with --with-devel
+ [ab1995f8103d]
+
+2010-04-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile, Makefile.in, configure, configure.in:
+ Top-level Makefile.in. Nothing is currently substituted but this is
+ needed for separate build dirs.
+ [e80873cbd201]
+
+ * compat/Makefile.in, doc/Makefile.in, plugins/sample/Makefile.in,
+ plugins/sudoers/Makefile.in, src/Makefile.in:
+ Fix out-of-tree builds
+ [59a35bef07b8]
+
+ * Merge
+ [386b848047e9]
+
+ * doc/Makefile.in:
+ We always install sudoreplay in 1.8
+ [ce52ba6617c9]
+
+ * plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c:
+ Free str after using it in the version method. Use sudo_conv, not
+ io_conv since we don't have the IO conversation function pointer in
+ the I/O version method anymore now that io_open is delayed.
+ [f2ed132adeb0]
+
+2010-04-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/siglist.in:
+ SIGPOLL is sometimes the same as SIGIO (like on HP-UX)
+ [6d69e1b05faf]
+
+2010-04-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ No need to provide strdup() or strndup(), sudo uses estrdup() and
+ estrndup()
+ [57ec23b72958]
+
+ * compat/Makefile.in, compat/mksiglist.c, compat/mksiglist.h,
+ compat/siglist.in:
+ Add license to mksiglist.c and note that the bits from pdksh are
+ public domain
+ [d8121a2467e8]
+
+ * compat/Makefile.in:
+ Fix LIBOBJDIR vs. srcdir wrt the siglist bits
+ [164160148421]
+
+ * plugins/sudoers/Makefile.in:
+ Add sudoreplay testsudoers and visudo to clean target
+ [138a17e51c0c]
+
+ * compat/Makefile.in, compat/mksiglist.c, compat/mksiglist.h,
+ compat/siglist.in, compat/strsignal.c, configure, configure.in,
+ include/missing.h, src/script.c:
+ Create our own sys_siglist for systems without it for use by
+ strsignal()
+ [2e5da011ebc3]
+
+ * compat/Makefile.in:
+ Remove duplicate $(LIBOBJDIR)
+ [adf9abc9432f]
+
+2010-04-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c, src/sudo.c, src/sudo_edit.c:
+ Main sudo should not block signals; the plugin should do this in
+ check_policy.
+ [3f3736a7c5ed]
+
+2010-03-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/script.c:
+ Fix a sizeof(ptr) vs. sizeof(*ptr)
+ [aa1bcf5afcce]
+
+ * src/script.c:
+ Unlike most operating systems, HP-UX select() is not interrupted by
+ SIGCHLD when the signal is registered with SA_RESTART. If we clear
+ SA_RESTART when calling sigaction() for SIGCHLD we get the expected
+ behavior and the code in the select() loops already handles EINTR
+ correctly.
+ [9eba0115e35a]
+
+ * compat/getprogname.c:
+ progname should be const
+ [130228f062b7]
+
+ * plugins/sudoers/Makefile.in:
+ Move --tag=disable-static to when we link sudoers.la, not when we
+ install.
+ [ceb5e6c3b78b]
+
+ * src/load_plugins.c:
+ Load the sudoers I/O plugin by default too now that it is hooked up.
+ [ea38befd0742]
+
+2010-03-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/pty.c:
+ It looks like AIX doesn't need to push STREAMS modules for ptys.
+ [22da618ba0a1]
+
+2010-03-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/parse_args.c, src/sudo.c:
+ Delay calling the I/O plugin open function until the policy plugin
+ returns success.
+ [f3297c325b48]
+
+2010-03-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/iolog.c,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Add back io logging (transcript) support. Currently, the open
+ function runs too early and it is not possible to use the io module
+ independently of the policy module.
+ [9bd932f66226]
+
+ * plugins/sudoers/set_perms.c:
+ Comment out dead code; will be removed when set_perms is rewritten.
+ [af7a995284f8]
+
+2010-03-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ Fix off by one error when allocating user_groups.
+ [6281fcf9c3bb]
+
+2010-03-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in, plugins/sudoers/Makefile.in:
+ Add REPLAY_LIBS for sudoreplay and add -lrt to it on Solaris.
+ [fbce3e9eda3a]
+
+ * plugins/sudoers/sudoers.c:
+ Fix typo in preserve groups case
+ [1fd72024fb5a]
+
+ * plugins/sudoers/sudoers.c:
+ In command_info it is "runas_groups" not "groups".
+ [5c64dce4f285]
+
+ * src/sudo.c:
+ Fix iteration over runas_groups list.
+ [b3c45a0cd643]
+
+ * configure, configure.in, plugins/sudoers/env.c,
+ plugins/sudoers/match.c, src/script.c:
+ Merge 5177a284b9ff 549f8f7c2463 88f3181692fe from 1.7 branch.
+ [a8108a0776c2]
+
+ * compat/getgrouplist.c:
+ getgrouplist(3) for those without it
+ [4ab4d21e3b16]
+
+ * configure, configure.in:
+ Fix installation of sudoers.ldap in "make install" when --with-ldap
+ was specified without a directory. From Prof. Dr. Andreas Mueller
+ [5177a284b9ff] <1.7>
+
+ * plugins/sudoers/sudoers.c:
+ Set preserve_groups or groups list in command_info
+ [1266119ad654]
+
+ * src/sudo.c:
+ Fix setting of groups list
+ [e75315e40bd4]
+
+ * config.h.in, configure, configure.in, include/compat.h,
+ include/missing.h:
+ Add checks for getgrset and getgrouplist and use replacement
+ getgrouplist if the system doesn't support it.
+ [a62b8ba50863]
+
+ * src/parse_args.c:
+ Pass in preserve_groups when the -P flag is specified as per the
+ design
+ [7420c5d15474]
+
+ * plugins/sudoers/sudoers.c:
+ Check preserve_groups and ignore_ticket args with atobool instead of
+ assuming they are true if present.
+ [71c905702697]
+
+2010-03-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/error.c,
+ plugins/sudoers/plugin_error.c:
+ Rename plugin-specific error.c to plugin_error.c Wire up visudo,
+ sudoreplay and testsudoers in the build
+ [9d581d5fa4d4]
+
+ * src/Makefile.in, src/term.c:
+ term.c does not needto include sudo.h
+ [f6683cdcd2dd]
+
+ * TODO, doc/sudo_plugin.cat, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.pod:
+ Document the -2 return in the check_policy section too
+ [e9cb4c34bbcf]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ src/parse_args.c, src/sudo.c, src/sudo.h:
+ Fix the -s and -i flags and add support for the "implied_shell"
+ option. If the user does not specify a command, sudo will now pass
+ in the path to the user's shell and set impied_shell=true. The
+ plugin can them either check the command normally or return -2 to
+ cause sudo to print a usage message and exit.
+ [bf889c38f229]
+
+2010-03-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, src/load_plugins.c:
+ Bring back SUDOERS_PLUGIN but add .dylib -> .so conversion for
+ Darwin where libraries end in .dylib but modules end in .so
+ [2c56aaa38e21]
+
+ * plugins/sudoers/parse.c:
+ Better prefix determination now that we can't rely on len==0 to tell
+ the beginning on an entry.
+ [622bf18179e9]
+
+ * plugins/sudoers/ldap.c:
+ display_bound_defaults() stub should return 0, not 1 since it is a
+ count, not a boolean.
+ [0327a6c3d55d]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod:
+ Document progname in settings
+ [42031d56a2e3]
+
+ * compat/getprogname.c, include/compat.h,
+ plugins/sample/sample_plugin.c, plugins/sudoers/sudoers.c,
+ src/parse_args.c, src/sudo.c:
+ Rewrite compat/getprogname.c and add setprogname(). The progname is
+ now passed to the plugin via the settings array.
+ [25d8663e6006]
+
+ * configure, configure.in, plugins/sudoers/Makefile.in:
+ Fix --with-ldap
+ [b64b633f426d]
+
+ * plugins/sudoers/sudo_nss.c:
+ Add missing whitespace for Runas and Command-specific defaults
+ [65f4ddf5545e]
+
+ * plugins/sudoers/ldap.c, plugins/sudoers/parse.c,
+ plugins/sudoers/sudo_nss.c:
+ Use embedded newlines in lbuf instead of multiple calls to
+ lbuf_print.
+ [eed3af9cc3e1]
+
+ * src/lbuf.c:
+ Add support for embedded newlines.
+ [e11f79b18deb]
+
+2010-03-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/getprogname.c:
+ If system doesn't support getprogname or __programe and we are
+ building a shared object don't bother with Argc/Argv, just return
+ "sudo"
+ [aebde9062be7]
+
+ * config.h.in, configure, configure.in, src/load_plugins.c:
+ Hard-code sudoers.so instead of using SUDOERS_PLUGIN since libtool
+ appears to always install a shared object with the .so suffix.
+ [f9bbd0c0e9d3]
+
+ * compat/Makefile.in, configure, configure.in,
+ plugins/sample/Makefile.in, plugins/sudoers/Makefile.in,
+ src/Makefile.in:
+ Play more nicely with libtool and let it build libreplace (was
+ libmissing) for us.
+ [a4c6ebb2495c]
+
+ * include/missing.h:
+ Include stdarg.h for va_list rather than requiring all consumers of
+ missing.h to include stdarg.h themselves.
+ [37382df948de]
+
+ * include/lbuf.h, plugins/sudoers/auth/sudo_auth.c,
+ plugins/sudoers/check.c, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h, src/lbuf.c,
+ src/parse_args.c:
+ Pass in output function to lbuf_init() instead of writing to stdout.
+ A side effect is that the usage info can now go to stderr as it
+ should.
+ [6d261261a072]
+
+2010-03-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/lbuf.h, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h, src/lbuf.c,
+ src/parse_args.c, src/sudo.c:
+ Use number of tty columns that is passed in user_info instead of
+ getting it directly in the lbuf code.
+ [8a16635c2638]
+
+ * plugins/sudoers/alias.c, plugins/sudoers/auth/dce.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.h,
+ plugins/sudoers/check.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/defaults.h, plugins/sudoers/env.c,
+ plugins/sudoers/getdate.c, plugins/sudoers/getdate.y,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.y,
+ plugins/sudoers/interfaces.h, plugins/sudoers/logging.c,
+ plugins/sudoers/logging.h, plugins/sudoers/match.c,
+ plugins/sudoers/mon_systrace.h, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h, plugins/sudoers/pwutil.c,
+ plugins/sudoers/redblack.c, plugins/sudoers/redblack.h,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudo_nss.h,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/timestr.c, plugins/sudoers/toke.c,
+ plugins/sudoers/toke.l, plugins/sudoers/tsgetgrpw.c,
+ plugins/sudoers/visudo.c:
+ Kill __P in sudoers
+ [63601e6cb171]
+
+ * config.h.in, configure, configure.in, src/load_plugins.c:
+ Set the sudoers plugin name in configure so we get the extension
+ right.
+ [edad89924cd1]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod:
+ Document lines/cols in user_info
+ [a808872394f3]
+
+ * src/Makefile.in, src/sudo.c, src/sudo.h, src/ttysize.c:
+ Add tty size to user info
+ [23f3d27e77a7]
+
+ * src/script.c:
+ Use TIOCGSIZE/TIOCSSIZE instead of TIOCGWINSZ/TIOCSWINSZ
+ [a2208dd09051]
+
+2010-03-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c:
+ Kill dead code Add missing sigsetjmp in sudo_policy_invalidate Error
+ out if we fail to lookup the user's name that is passed in
+ [e4e3728ed482]
+
+ * plugins/sudoers/error.c:
+ Pass the error value back via siglongjmp.
+ [667b8ad575ce]
+
+ * plugins/sudoers/check.c:
+ Use conversation function for lecture.
+ [1ab4719f509b]
+
+ * plugins/sudoers/check.c:
+ Don't update ticket file if verify_user returns FALSE.
+ [2bbc46a39a2b]
+
+2010-03-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/sudoers.c, src/sudo.c:
+ Wire up invalidate and validate methods for sudoers
+ [c0630c7bca47]
+
+ * plugins/sudoers/check.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h:
+ Add support for -k flag with a command.
+ [edad239b098b]
+
+ * src/parse_args.c:
+ Allow -k to be specified with a command.
+ [43a45add9974]
+
+ * plugins/sudoers/sudoers.c:
+ Wire up policy_list
+ [27cc35699eca]
+
+ * plugins/sudoers/error.c:
+ Add newline at the end of message and space after the colon in
+ warning message
+ [5a591aa8e744]
+
+ * plugins/sudoers/auth/sudo_auth.c:
+ Add missing newline after pass password warning
+ [337dba3870a7]
+
+ * plugins/sudoers/sudoers.c:
+ Set user_groups and user_ngroups based on user_info
+ [61bee85128c8]
+
+ * plugins/sudoers/error.c:
+ Make this compile
+ [7041c441e1c8]
+
+ * Makefile:
+ Build sudoers plugin
+ [5cdf06e66978]
+
+ * plugins/sudoers/gram.c, plugins/sudoers/gram.y:
+ Use warningx in yyerror() so the conversation function gets used
+ when built as part of sudoers.
+ [85f964215eef]
+
+ * plugins/sudoers/error.c, plugins/sudoers/sudoers.c:
+ Make _warning in error.c use the conversation function and remove
+ commented out warning/warningx in sudoers.c.
+ [7c9b09024b63]
+
+ * plugins/sudoers/logging.c:
+ Use siglongjmp() in log_error for fatal errors
+ [b50e26f1c73f]
+
+ * plugins/sample/Makefile.in, plugins/sudoers/Makefile.in:
+ Quiet a libtool warning
+ [b2331fb006bc]
+
+2010-03-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sudoers/auth/pam.c:
+ Rename sudo_conv to conversation to avoid a namespace conflict.
+ [1ad359d36be9]
+
+ * plugins/sudoers/Makefile.in, plugins/sudoers/alias.c,
+ plugins/sudoers/auth/afs.c, plugins/sudoers/auth/aix_auth.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/dce.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/kerb4.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid.c,
+ plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/auth/sudo_auth.h,
+ plugins/sudoers/check.c, plugins/sudoers/defaults.c,
+ plugins/sudoers/env.c, plugins/sudoers/error.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/getspwuid.c,
+ plugins/sudoers/goodpath.c, plugins/sudoers/gram.c,
+ plugins/sudoers/gram.y, plugins/sudoers/interfaces.c,
+ plugins/sudoers/ldap.c, plugins/sudoers/logging.c,
+ plugins/sudoers/match.c, plugins/sudoers/mon_systrace.c,
+ plugins/sudoers/parse.c, plugins/sudoers/pwutil.c,
+ plugins/sudoers/redblack.c, plugins/sudoers/set_perms.c,
+ plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoers.c,
+ plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c,
+ plugins/sudoers/toke.c, plugins/sudoers/tsgetgrpw.c,
+ plugins/sudoers/vasgroups.c, plugins/sudoers/visudo.c:
+ Initial bits of sudoers plugin; still needs work.
+ [af2a2c59a952]
+
+ * config.h.in:
+ Add HAVE_STRDUP and HAVE_STRNDUP
+ [50a3c0dd510f]
+
+ * compat/Makefile.in, configure, configure.in:
+ Build libmissing in two flavors (one PIC one non-PIC) and link with
+ the appropriate one.
+ [b62f411a4c18]
+
+ * Makefile, compat/fnmatch.c, compat/glob.c, compat/nanosleep.c,
+ compat/utimes.c, plugins/sample/Makefile.in, src/Makefile.in:
+ Build libmissing in two flavors (one PIC one non-PIC) and link with
+ the appropriate one.
+ [e1e04972b5fe]
+
+2010-03-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * include/missing.h:
+ Add strdup and strndup and fix strsignal
+ [c159babe2896]
+
+2010-03-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat/strdup.c, compat/strndup.c, configure, configure.in,
+ plugins/sample/Makefile.in, src/Makefile.in:
+ Add strdup and strndup to compat
+ [25c9fd399a4d]
+
+ * plugins/sample/sample_plugin.c:
+ Need to include compat.h before missing.h
+ [c94f7aad380f]
+
+ * compat/strsignal.c:
+ Must check HAVE_DECL_SYS_SIGLIST == 1 (not just if defined) since if
+ it doesn't exist configure will set it to 0.
+ [384580566389]
+
+ * compat/glob.c:
+ Fix botched ANSI C coversion of globexp2()
+ [4a344b8cbe49]
+
+ * configure, configure.in:
+ Remove redundant getgroups check
+ [0b16ec210c81]
+
+ * configure, configure.in, src/lbuf.c, src/script.c, src/term.c:
+ Require either termios or termio, no more sgtty.
+ [9b2fa2f17a1c]
+
+ * compat/strsignal.c, config.h.in, configure, configure.in:
+ Change the sys_siglist check to use AC_CHECK_DECLS and also check
+ for _sys_siglist and__sys_siglist
+ [2e078fed2408]
+
+2010-03-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in, src/Makefile.in:
+ Change SUDO_LDFLAGS to SUDOERS_LDFLAGS and add SUDOERS_OBJS. We now
+ use SUDO_OBJS for the main driver as part of OBJS.
+ [9ae4a80a5ade]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod:
+ Mention in the conversation function section that a newline is not
+ implicit.
+ [04a233b6c491]
+
+ * include/compat.h:
+ Add definition of WCOREDUMP for systems without it. This is known to
+ work on AIX and SunOS 4, but may be incorrect on other systems that
+ lack WCOREDUMP.
+ [c85b3ce6b77d]
+
+2010-03-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sample/sample_plugin.c, src/conversation.c:
+ conversation function no longer puts a newline at the end of info or
+ error messages.
+ [c534cae1ac4a]
+
+ * match.c:
+ When doing a glob match, short circuit if gl.gl_pathc is 0. From
+ Mark Kettenis.
+ [549f8f7c2463] <1.7>
+
+2010-03-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * script.c:
+ Use parent process group id instead of parent process id when
+ checking foreground status and suspending parent. Fixes an issue
+ when running commands under /usr/bin/time and others.
+ [eac86126e335] <1.7>
+
+ * env.c:
+ In setenv(), if the var is empty, return 1 and set errno to EINVAL
+ instead of returning EINVAL directly.
+ [d202091ec15e] <1.7>
+
+2010-03-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/script.c:
+ Use parent process group id instead of parent process id when
+ checking foreground status and suspending parent. Fixes an issue
+ when running commands under /usr/bin/time and others.
+ [564f528c3bb7]
+
+2010-03-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aclocal.m4:
+ transcript option is now --with not --enable
+ [0646fac4cf93]
+
+ * plugins/sample/sample_plugin.c:
+ Add support to -u and -g flags Check fmt_string retval Add timeout
+ for debugging purposes
+ [cfefa4fa60b5]
+
+ * src/script.c, src/sudo.c:
+ Wire up SIGALRM handler Set close on exec flag for child side of the
+ socketpair Fix signal handling when not doing I/O logging
+ [379581ec7272]
+
+ * src/sudo.c:
+ g/c unused SIGCHLD handler
+ [0afa03912dce]
+
+ * src/fmt_string.c, src/parse_args.c, src/sudo.c:
+ Don't use emalloc() in fmt_string(); we want to be able to use it
+ from a plugin.
+ [ade64d368147]
+
+ * include/list.h:
+ tq_remove not list_remove
+ [0e0e1fd5c31c]
+
+ * configure, configure.in:
+ AUTH_OBJS should contain .lo files not .o files.
+ [c64c82c9d5a2]
+
+2010-03-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/parse_args.c:
+ Simplify conversion of command line args to name=value pairs.
+ [75ab127c6a94]
+
+ * plugins/sample/sample_plugin.c:
+ Handle NULL reply from conversation function
+ [6ce09b6cb204]
+
+ * compat/getline.c:
+ Don't depend on emalloc/erealloc
+ [73df09e2109f]
+
+ * plugins/sample/Makefile.in:
+ Use $(OBJS) instead of sample_plugin.lo
+ [2d995db9aa99]
+
+ * plugins/sample/sample_plugin.c:
+ runas_user is in settings not user_info
+ [7ee12068bc57]
+
+ * src/parse_args.c:
+ Fix a mismatch between sudo_settings and settings_pairs that causes
+ some settings to get the wrong values.
+ [b1bc6d81a65f]
+
+2010-03-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/Makefile.in, src/aix.c, src/alloc.c, src/atobool.c, src/error.c,
+ src/fileops.c, src/lbuf.c, src/list.c, src/pty.c, src/sesh.c,
+ src/sudo.c, src/sudo_edit.c, src/term.c, src/zero_bytes.c:
+ Convert to ANSI C
+ [d03b6e4a3b75]
+
+ * src/load_plugins.c:
+ Fix strlcpy() return value check.
+ [7cd66999a374]
+
+ * INSTALL, configure, configure.in:
+ No longer need to substitute in script.o and pty.o; I/O logging
+ support is always built.
+ [45250024c5dc]
+
+2010-02-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/script.c:
+ Add fallback to /bin/sh when execve() fails with ENOEXEC.
+ [7684a15a1352]
+
+ * include/alloc.h, src/alloc.c:
+ Add estrndup()
+ [47621c83bed9]
+
+2010-02-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/script.c, src/sudo.c:
+ Refactor script_execve() a bit so that it can be used in non-script
+ mode. Needs more cleanup.
+ [f09e022d547c]
+
+ * src/sudo.c:
+ Ignore empty entries in command_info list
+ [1eea9a8de21c]
+
+ * include/list.h, src/list.c:
+ Add tq_remove
+ [40908a617cb2]
+
+ * src/conversation.c:
+ Pass timeout to tgetpass()
+ [9e66c918b771]
+
+ * Makefile:
+ Add ChangeLog target
+ [da4a39150838]
+
+ * README, WHATSNEW:
+ Bump version and update things slightly for sudo 1.8.0
+ [4b73cc45e2d4]
+
+ * configure, configure.in:
+ Sudo now requires an ANSI/ISO C compiler
+ [1e51f72e6964]
+
+ * src/alloc.c, src/audit.c, src/error.c, src/lbuf.c,
+ src/sudo_noexec.c:
+ Convert to ANSI C
+ [5cbd315dbde8]
+
+ * include/alloc.h, include/compat.h, include/error.h, include/lbuf.h,
+ include/list.h, include/missing.h:
+ Convert to ANSI C
+ [3f5016ff64f4]
+
+ * compat/charclass.h, compat/closefrom.c, compat/fnmatch.c,
+ compat/fnmatch.h, compat/getcwd.c, compat/getline.c,
+ compat/getprogname.c, compat/glob.c, compat/glob.h,
+ compat/isblank.c, compat/memrchr.c, compat/mkstemp.c,
+ compat/nanosleep.c, compat/sigaction.c, compat/snprintf.c,
+ compat/strcasecmp.c, compat/strerror.c, compat/strlcat.c,
+ compat/strlcpy.c, compat/strsignal.c, compat/utime.h,
+ compat/utimes.c:
+ Convert to ANSI C
+ [0d635c85461c]
+
+2010-02-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/sudo.c, src/tgetpass.c:
+ Make user_details extern so tgetpass can get at the uid and gid. Set
+ uid/gid to user before executing askpass program. Check environment
+ for SUDO_ASKPASS and use that if set. TODO: a way for the policy to
+ set the askpass program itself
+ [d33606396176]
+
+ * src/sudo.c:
+ No longer need sudo_usage.h in sudo.c
+ [063e2946c382]
+
+ * doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod, doc/sudo_plugin.man.in,
+ doc/sudo_plugin.pod, src/Makefile.in, src/parse_args.c,
+ src/sudo_usage.h.in:
+ Document -D level command line flag which maps to the debug_level
+ setting.
+ [61f1e2ab3ac1]
+
+ * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod:
+ Document debug_level in plugin doc. Still need to document the -D
+ flag in sudo itself.
+ [8c62daea3e9b]
+
+2010-02-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * match.c:
+ Check for pseudo-command by looking at the first character of the
+ command in sudoers instead of checking the user-supplied command for
+ a slash.
+ [88f3181692fe] <1.7>
+
+2010-02-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * plugins/sample/sample_plugin.c:
+ include missing,h for vasprintf
+ [92503de49b39]
+
+ * doc/Makefile.in, doc/plugin.pod, doc/sudo_plugin.cat,
+ doc/sudo_plugin.man.in, doc/sudo_plugin.pod:
+ Rename plugin.pod -> sudo_plugin.pod and wire into Makefile
+ [14cfb4775238]
+
+ * plugins/sample/sample_plugin.c:
+ Need to include limits.h
+ [bda7f74343d2]
+
+ * compat/glob.c:
+ No more sudo_getpw*
+ [232e52907634]
+
+ * plugins/sample/Makefile.in, src/Makefile.in:
+ Add missing compat bits
+ [4843dd000e08]
+
+ * compat/closefrom.c, compat/mkstemp.c, plugins/sample/Makefile.in:
+ compat files should not include sudo.h wire up compat in sample
+ plugin
+ [a175b8185e0f]
+
+ * Makefile, configure, configure.in, doc/Makefile.in, src/Makefile.in:
+ Fix up compat dependencies. Fix distclean target in doc/Makefile.in
+ [57e49bc20857]
+
+ * configure, configure.in:
+ Fix typo
+ [333655e3d5fe]
+
+ * plugins/sample/sample_plugin.c:
+ Log input and output to temp files for proof of concept.
+ [ae1dfc34f7d6]
+
+ * Makefile, configure, configure.in, doc/Makefile.in:
+ Add doc Makefile.in and wire it up
+ [6a310443c87d]
+
+ * src/script.c:
+ Handle SIGSTOP in addition to SIGTSTP. Fixes a problem with
+ suspending a shell with the "suspend" builtint.
+ [3d65f182819a]
+
+ * src/script.c:
+ In child, handle parent side of the pipe going away.
+ [a29c14d78cd9]
+
+ * src/script.c:
+ No longer need to check for explicit death of the child (process #2)
+ since if it dies we will get EPIPE from the socketpair. Fix a
+ sizeof() that was causing a spurious error. Convert SCRIPT_DEBUG to
+ sudo_debug.
+ [24c55dd4ff60]
+
+ * src/sudo.c:
+ Make sudo_debug do a single vfprintf() which will result in a single
+ write call on most systems. Avoids problems with interleaved debug
+ printf from different processes. Also remove an extraneous error
+ case since recv() can't return a short read and add some more XXX.
+ [b37a8533ef1e]
+
+2010-02-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * src/script.c:
+ Fix uninitialized variable.
+ [e012a0a30890]
+
+ * src/Makefile.in:
+ Fix sudo install target
+ [1417fa4b4ab9]
+
+ * src/parse_args.c, src/sudo.c, src/sudo.h:
+ Wire up debug_level
+ [144fab289c73]
+
+ * src/Makefile.in:
+ Fix dependencies
+ [5170940af2ce]
+
+ * configure, configure.in:
+ Fix setting of plugin dir
+ [144eda170a72]
+
+ * Makefile:
+ add clean targets
+ [d53f6f6f5c3a]
+
+ * src/atobool.c:
+ Add missing source for sudo front end
+ [42487de9c489]
+
+ * plugins/sample/Makefile.in, plugins/sample/sample_plugin.c:
+ Sample plugin demonstrating the sudo plugin API
+ [f1fd62d7644f]
+
+ * Makefile, configure, configure.in, install-sh, pathnames.h.in,
+ plugins/sudoers/install-sh, src/Makefile.in, src/conversation.c,
+ src/fileops.c, src/fmt_string.c, src/load_plugins.c,
+ src/parse_args.c, src/pty.c, src/script.c, src/sudo.c, src/sudo.h,
+ src/sudo_plugin_int.h, src/sudo_usage.h.in, src/tgetpass.c,
+ sudo_usage.h.in:
+ Modular sudo front-end which loads policy and I/O plugins that do
+ most the actual work. Currently relies on dynamic loading using
+ dlopen(). See doc/plugin.pod for the plugin API.
+ [924f6eb2fbba]
+
+ * doc/plugin.pod, include/sudo_plugin.h:
+ Sudo plugin API
+ [374ccbbd24ae]
+
+ * compat/fnmatch.c, compat/glob.c, compat/nanosleep.c,
+ compat/utimes.c, plugins/sudoers/check.c, plugins/sudoers/gettime.c,
+ plugins/sudoers/match.c, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c,
+ src/fileops.c, src/sudo_edit.c:
+ Replace emul/include.h with compat/include.h to match new source
+ tree layout.
+ [7eccd10449a1]
+
+ * src/lbuf.c:
+ Include missing.h for memrchr() proto
+ [03abd63a8a33]
+
+ * HISTORY, LICENSE, Makefile.binary.in, Makefile.in, PORTING,
+ TROUBLESHOOTING, UPGRADE, aix.c, aixcrypt.exp, alias.c, alloc.c,
+ alloc.h, audit.c, auth/API, auth/afs.c, auth/aix_auth.c,
+ auth/bsdauth.c, auth/dce.c, auth/fwtk.c, auth/kerb4.c, auth/kerb5.c,
+ auth/pam.c, auth/passwd.c, auth/rfc1938.c, auth/secureware.c,
+ auth/securid.c, auth/securid5.c, auth/sia.c, auth/sudo_auth.c,
+ auth/sudo_auth.h, boottime.c, bsm_audit.c, bsm_audit.h, check.c,
+ closefrom.c, compat.h, compat/charclass.h, compat/closefrom.c,
+ compat/fnmatch.c, compat/fnmatch.h, compat/getcwd.c,
+ compat/getline.c, compat/getprogname.c, compat/glob.c,
+ compat/glob.h, compat/isblank.c, compat/memrchr.c, compat/mkstemp.c,
+ compat/nanosleep.c, compat/sigaction.c, compat/snprintf.c,
+ compat/strcasecmp.c, compat/strerror.c, compat/strlcat.c,
+ compat/strlcpy.c, compat/strsignal.c, compat/timespec.h,
+ compat/utime.h, compat/utimes.c, def_data.c, def_data.h,
+ def_data.in, defaults.c, defaults.h, doc/HISTORY, doc/LICENSE,
+ doc/PORTING, doc/TROUBLESHOOTING, doc/UPGRADE, doc/history.pod,
+ doc/license.pod, doc/sample.pam, doc/sample.sudoers,
+ doc/sample.syslog.conf, doc/schema.ActiveDirectory,
+ doc/schema.OpenLDAP, doc/schema.iPlanet, doc/sudo.cat,
+ doc/sudo.man.in, doc/sudo.man.pl, doc/sudo.pod, doc/sudoers.cat,
+ doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in, doc/sudoers.ldap.pod,
+ doc/sudoers.man.in, doc/sudoers.man.pl, doc/sudoers.pod,
+ doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.pod,
+ doc/visudo.cat, doc/visudo.man.in, doc/visudo.pod, emul/charclass.h,
+ emul/fnmatch.h, emul/glob.h, emul/timespec.h, emul/utime.h, env.c,
+ error.c, error.h, fileops.c, find_path.c, fnmatch.c, getcwd.c,
+ getdate.c, getdate.y, getline.c, getprogname.c, getspwuid.c,
+ gettime.c, glob.c, goodpath.c, gram.c, gram.h, gram.y, history.pod,
+ include/alloc.h, include/compat.h, include/error.h, include/lbuf.h,
+ include/list.h, include/missing.h, ins_2001.h, ins_classic.h,
+ ins_csops.h, ins_goons.h, install-sh, insults.h, interfaces.c,
+ interfaces.h, isblank.c, lbuf.c, lbuf.h, ldap.c, license.pod,
+ list.c, list.h, logging.c, logging.h, match.c, memrchr.c, missing.h,
+ mkdefaults, mkstemp.c, mon_systrace.c, mon_systrace.h, nanosleep.c,
+ nonunix.h, parse.c, parse.h, plugins/sudoers/Makefile.binary.in,
+ plugins/sudoers/Makefile.in, plugins/sudoers/aixcrypt.exp,
+ plugins/sudoers/alias.c, plugins/sudoers/auth/API,
+ plugins/sudoers/auth/afs.c, plugins/sudoers/auth/aix_auth.c,
+ plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/dce.c,
+ plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/kerb4.c,
+ plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c,
+ plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c,
+ plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid.c,
+ plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c,
+ plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/auth/sudo_auth.h,
+ plugins/sudoers/boottime.c, plugins/sudoers/check.c,
+ plugins/sudoers/def_data.c, plugins/sudoers/def_data.h,
+ plugins/sudoers/def_data.in, plugins/sudoers/defaults.c,
+ plugins/sudoers/defaults.h, plugins/sudoers/env.c,
+ plugins/sudoers/find_path.c, plugins/sudoers/getdate.c,
+ plugins/sudoers/getdate.y, plugins/sudoers/getspwuid.c,
+ plugins/sudoers/gettime.c, plugins/sudoers/goodpath.c,
+ plugins/sudoers/gram.c, plugins/sudoers/gram.h,
+ plugins/sudoers/gram.y, plugins/sudoers/ins_2001.h,
+ plugins/sudoers/ins_classic.h, plugins/sudoers/ins_csops.h,
+ plugins/sudoers/ins_goons.h, plugins/sudoers/install-sh,
+ plugins/sudoers/insults.h, plugins/sudoers/interfaces.c,
+ plugins/sudoers/interfaces.h, plugins/sudoers/ldap.c,
+ plugins/sudoers/logging.c, plugins/sudoers/logging.h,
+ plugins/sudoers/match.c, plugins/sudoers/mkdefaults,
+ plugins/sudoers/mon_systrace.c, plugins/sudoers/mon_systrace.h,
+ plugins/sudoers/nonunix.h, plugins/sudoers/parse.c,
+ plugins/sudoers/parse.h, plugins/sudoers/pwutil.c,
+ plugins/sudoers/redblack.c, plugins/sudoers/redblack.h,
+ plugins/sudoers/set_perms.c, plugins/sudoers/sudo_nss.c,
+ plugins/sudoers/sudo_nss.h, plugins/sudoers/sudoers,
+ plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h,
+ plugins/sudoers/sudoers2ldif, plugins/sudoers/sudoreplay.c,
+ plugins/sudoers/testsudoers.c, plugins/sudoers/timestr.c,
+ plugins/sudoers/toke.c, plugins/sudoers/toke.l,
+ plugins/sudoers/tsgetgrpw.c, plugins/sudoers/vasgroups.c,
+ plugins/sudoers/visudo.c, pty.c, pwutil.c, redblack.c, redblack.h,
+ sample.pam, sample.sudoers, sample.syslog.conf,
+ schema.ActiveDirectory, schema.OpenLDAP, schema.iPlanet, script.c,
+ selinux.c, sesh.c, set_perms.c, sigaction.c, snprintf.c, src/aix.c,
+ src/alloc.c, src/audit.c, src/bsm_audit.c, src/bsm_audit.h,
+ src/error.c, src/fileops.c, src/lbuf.c, src/list.c, src/pty.c,
+ src/script.c, src/selinux.c, src/sesh.c, src/sudo_edit.c,
+ src/sudo_noexec.c, src/term.c, src/tgetpass.c, src/zero_bytes.c,
+ strcasecmp.c, strerror.c, strlcat.c, strlcpy.c, strsignal.c, sudo.c,
+ sudo.cat, sudo.h, sudo.man.in, sudo.man.pl, sudo.pod, sudo_edit.c,
+ sudo_noexec.c, sudo_nss.c, sudo_nss.h, sudoers, sudoers.cat,
+ sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.ldap.pod,
+ sudoers.man.in, sudoers.man.pl, sudoers.pod, sudoers2ldif,
+ sudoreplay.c, sudoreplay.cat, sudoreplay.man.in, sudoreplay.pod,
+ term.c, testsudoers.c, tgetpass.c, timestr.c, toke.c, toke.l,
+ tsgetgrpw.c, utimes.c, vasgroups.c, visudo.c, visudo.cat,
+ visudo.man.in, visudo.pod, zero_bytes.c:
+ Rework source layout in preparation for modular sudo.
+ [7fc1978c6ad5]
+
+2010-02-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Avoid a duplicate fclose() of the sudoers file.
+ [5dba851088c1]
+
+ * Fix size arg when realloc()ing include stack. From Daniel Kopecek
+ [0a2935061e33]
+
+ * Use setrlimit64(), if available, instead of setrlimit() when setting
+ AIX resource limits since rlim_t is 32bits.
+ [353db89bac61]
+
+ * Fix use after free when sending error messages. From Timo Juhani
+ Lindfors
+ [e50dbd902382]
+
+ * ChangeLog, Makefile.in:
+ Generate the ChangeLog as part of "make dist" instead of having it
+ in the repo.
+ [251b70964673]
+
+2010-02-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * toke.l:
+ Avoid a duplicate fclose() of the sudoers file.
+ [164d39108dde] <1.7>
+
+ * toke.l:
+ Fix size arg when realloc()ing include stack. From Daniel Kopecek
+ [8900bccef219] <1.7>
+
+2010-02-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aix.c, config.h.in, configure, configure.in:
+ Use setrlimit64(), if available, instead of setrlimit() when setting
+ AIX resource limits since rlim_t is 32bits.
+ [2cbb14d98fc1] <1.7>
+
+ * logging.c:
+ Fix use after free when sending error messages. From Timo Juhani
+ Lindfors
+ [caf183fd9d94] <1.7>
+
+2010-01-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ChangeLog, Makefile.in:
+ Generate the ChangeLog as part of "make dist" instead of having it
+ in the repo.
+ [836c31615859] <1.7>
+
+2010-01-18 convert-repo <convert-repo>
+
+ * .hgtags:
+ update tags
+ [9b7aa44ae436]
+
+2010-01-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ Generate correct ChangeLog for 1.7 branch.
+ [586dd90b8878] <1.7>
+
+ * Makefile.binary.in, Makefile.in, aix.c, alias.c, alloc.c, alloc.h,
+ auth/afs.c, auth/aix_auth.c, auth/bsdauth.c, auth/dce.c,
+ auth/fwtk.c, auth/kerb4.c, auth/kerb5.c, auth/pam.c, auth/passwd.c,
+ auth/rfc1938.c, auth/secureware.c, auth/securid.c, auth/securid5.c,
+ auth/sia.c, auth/sudo_auth.c, auth/sudo_auth.h, check.c,
+ closefrom.c, compat.h, configure.in, defaults.c, defaults.h,
+ emul/charclass.h, emul/timespec.h, env.c, error.c, error.h,
+ fileops.c, find_path.c, getcwd.c, getprogname.c, getspwuid.c,
+ gettime.c, goodpath.c, gram.c, gram.y, ins_2001.h, ins_classic.h,
+ ins_csops.h, ins_goons.h, insults.h, interfaces.c, interfaces.h,
+ isblank.c, lbuf.c, lbuf.h, ldap.c, list.c, list.h, logging.c,
+ logging.h, match.c, memrchr.c, missing.h, mkinstalldirs, mkstemp.c,
+ mon_systrace.c, nanosleep.c, parse.c, parse.h, pathnames.h.in,
+ pty.c, pwutil.c, redblack.c, redblack.h, sample.pam, sample.sudoers,
+ sample.syslog.conf, script.c, selinux.c, sesh.c, set_perms.c,
+ sigaction.c, snprintf.c, strcasecmp.c, strerror.c, strlcat.c,
+ strlcpy.c, strsignal.c, sudo.c, sudo.h, sudo.man.in, sudo.pod,
+ sudo_edit.c, sudo_noexec.c, sudo_nss.c, sudo_nss.h, sudo_usage.h.in,
+ sudoers.ldap.man.in, sudoers.ldap.pod, sudoers.man.in, sudoers.pod,
+ sudoers2ldif, sudoreplay.c, sudoreplay.man.in, sudoreplay.pod,
+ term.c, testsudoers.c, tgetpass.c, timestr.c, toke.c, toke.l,
+ utimes.c, visudo.c, visudo.man.in, visudo.pod, zero_bytes.c:
+ Remove CVS $Sudo$ tags.
+ [de683a8b31f5]
+
+2009-12-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo_usage.h.in:
+ make this match sudoers SYNOPSIS
+ [c74ba66944c2]
+
+ * lbuf.c, parse.c:
+ Print a newline between Runas and Command-specific defaults in sudo
+ -l.
+ [b5bdfcc9ce4b]
+
+ * term.c:
+ Use SET and CLR macros in term_raw
+ [50ca42609d6c]
+
+ * sudoreplay.c:
+ Set stdin to non-blocking mode early instead of in check_input. Use
+ term_raw instead of term_cbreak since the data we get has already
+ been expanded via OPOST.
+ [51c47e803d62]
+
+2009-12-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * script.c, term.c:
+ Enable/disable all postprocessing instead of just nl->crnl
+ processing since things like tab expansion matter too. However, if
+ stdout is a tty leave postprocessing on in the pty since we run into
+ problems doing it only on the real stdout with .e.g nvi.
+ [62666e309673]
+
+2009-12-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ If tty_tickets is enabled and there is no tty, prompt for a
+ password. Do not lecture user for "sudo -k command" if user has a
+ timestamp.
+ [5880200c5f6b]
+
+ * INSTALL:
+ Document missing options: --with-efence and --with-bsm-audit
+ [d83afcdf9ff3]
+
+ * sudo.cat, sudo.man.in, sudo.pod, sudoers.cat, sudoers.ldap.cat,
+ sudoers.ldap.man.in, sudoers.ldap.pod, sudoers.man.in, sudoers.pod,
+ sudoreplay.cat, sudoreplay.man.in, sudoreplay.pod, visudo.cat,
+ visudo.man.in, visudo.pod:
+ username -> user name groupname -> group name hostname -> host name
+ [10c85646f45d]
+
+ * INSTALL, README.LDAP, sudoers.pod:
+ filename -> file name like the rest of the docs
+ [1ef8ab5a9018]
+
+2009-12-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ Fix printing of entries with multiple host entries on a single line.
+ [226ceaf91d8d]
+
+2009-12-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ Mention that targetpw affects the timestamp file name.
+ [a26e22e4f72e]
+
+ * def_data.c, def_data.h, def_data.in, defaults.c, script.c,
+ sudoers.pod:
+ Add compress_transcript option.
+ [6e94f8cb9dfb]
+
+2009-12-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ bump to 1.7.3b2
+ [906d7e347d15]
+
+ * pwutil.c, set_perms.c, sudo.c, sudo_nss.c:
+ Better split of membership vs. traditional group check in
+ user_in_group(). Allow user_ngroups to be < 0 if getgroups() fails.
+ [6ebc55d4716b]
+
+2009-12-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pwutil.c:
+ Fix pasto and add default return value.
+ [7973b5e4599c]
+
+ * check.c, match.c, pwutil.c, sudo.h:
+ refactor group member checking into user_in_group()
+ [48ca8c2eddf8]
+
+ * check.c, config.h.in, configure, configure.in, match.c, sudo.c,
+ sudo.h:
+ Add support for mbr_check_membership() as present in darwin.
+ [5501aed02b9f]
+
+2009-12-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * match.c:
+ Rename label to be accurate
+ [3af17dd960f7]
+
+ * Makefile.in, boottime.c, check.c, config.h.in, configure,
+ configure.in, sudo.h:
+ Treat timestamp files from before we booted as old. Idea from and
+ Apple patch.
+ [5c96e484c05a]
+
+2009-12-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c, sudo.pod, sudo_usage.h.in:
+ Allow the -u flag to be used in conjunction with the -v flag as per
+ older versions of sudo.
+ [591e9fc13c1a]
+
+ * logging.c:
+ fix typo in last commit
+ [4fd0c692dcf0]
+
+2009-12-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ Convert fmt_first and fmt_confd into macros.
+ [32e870158b29]
+
+ * sudoers.pod:
+ timeouts can be floats now
+ [89de639a9679]
+
+ * WHATSNEW, def_data.c, def_data.h, def_data.in, defaults.c,
+ defaults.h, mkdefaults:
+ Add support for floating point timeout values (e.g. 2.5 minutes).
+ [210ffa291733]
+
+2009-12-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod:
+ The -L flag will be removed in sudo 1.7.4
+ [ffd026084333]
+
+2009-12-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoreplay.c:
+ Fix a bug due to order of operators.
+ [938d34464283]
+
+2009-11-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * match.c:
+ cmnd_matches() already deals with negation so _cmndlist_matches()
+ does not need to do so itself. Fixes a bug with negated entries in a
+ Cmnd_List.
+ [71c845f6ce73]
+
+2009-11-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Don't exit() from open_sudoers, just return NULL for all errors.
+ [8cfa832f972a]
+
+ * script.c:
+ Can't rely on the shell sending us SIGCONT when transitioning from
+ backgroup to foreground process.
+ [3c6c5b6cb4b3]
+
+ * toke.c, toke.l:
+ Add missing extern def for parse_error
+ [45b7b59d03b7]
+
+2009-11-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * toke.c, toke.l:
+ Avoid a parse error when #includedir doesn't find any files. Closes
+ bug #375
+ [1ce1b850e9e6]
+
+ * Makefile.in:
+ Include sudo.man.pl and sudoers.man.pl in the distribution tarball.
+ [6a22e32da108]
+
+2009-11-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * script.c:
+ Start command out in foreground mode if stdout is a tty. Works
+ around issues with some curses-based programs that don't handle
+ tcsetattr getting interrupted by a signal. Still allows us to avoid
+ hogging the tty if the command is part of a pipeline.
+ [1c32f2b94769]
+
+ * script.c, sudo.c, sudo.h, sudoreplay.c, term.c, tgetpass.c:
+ Use a socketpair to pass signals from parent to child. Child will
+ now pass command status change info back via the socketpair. This
+ allows the parent to distinguish between signals it has been sent
+ directly and signals the command has received. It also means the
+ parent can once again print the signal notifications to the tty so
+ all writes to the pty master occur in the parent. The command is now
+ always started in background mode with tty signals handled by the
+ parent.
+ [c6790b82986d]
+
+2009-11-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Fix a few typos in the descriptions; from Jeff Makey Only do the
+ check for krb5_get_init_creds_opt_free() taking two arguments if we
+ find krb5_get_init_creds_opt_alloc(). Otherwise we will get a false
+ positive when using our own krb5_get_init_creds_opt_free which takes
+ only a single argument.
+ [845a9ff6f93d]
+
+2009-11-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Remove a spurious comma in the kerb5 bits.
+ [3433eab083db]
+
+ * auth/kerb5.c:
+ Call krb5_get_init_creds_opt_init() in our emulated
+ krb5_get_init_creds_opt_alloc() for MIT kerberos.
+ [7ffb40bf43e9]
+
+2009-11-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in:
+ Add HAVE_ZLIB
+ [9297bde61ecc]
+
+ * script.c:
+ Need to ignore SIGTT{IN,OU} in child when running the command in the
+ background. Also some minor cleanup.
+ [dc208d982319]
+
+2009-10-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * script.c:
+ Instead of calling sigsuspend when waiting for SIGUSR[12] from
+ parent, install the signal handlers w/o SA_RESTART and let them
+ interrupt waitpid().
+ [759c7d18203b]
+
+ * script.c:
+ Pass along SIGHUP and SIGTERM from parent to child.
+ [035b0e254568]
+
+ * script.c:
+ Close unused bits of script_fds in processes that don't need them.
+ Restore default SIGCONT handler in child.
+ [e037378ab0c1]
+
+ * script.c:
+ Update foreground/background status in SIGCONT handler in parent
+ process.
+ [3f7f91333264]
+
+2009-10-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * script.c:
+ Defer setting terminal into raw mode until just before we fork() and
+ only do it if sudo is the foreground process. If we get SIGTT{IN,OU}
+ and sudo is already in the foreground be sure to set raw mode before
+ continuing the child.
+ [1102ef40832c]
+
+2009-10-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * script.c:
+ Fix handling of SIGTTOU/SIGTTIN in program being run. We now only
+ give the command the controlling tty if the main sudo process is the
+ foreground process.
+ [cf3a91cb5682]
+
+ * script.c:
+ Don't bother with sudo_waitpid() here for now.
+ [9086de480c2d]
+
+ * script.c:
+ fix non-zlib case
+ [a258bff0f9a6]
+
+2009-10-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * script.c:
+ Remove non-wroking code that crept into rev 1.55
+ [2802dd55cff5]
+
+2009-10-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, configure, configure.in, script.c, sudoreplay.c:
+ First pass at zlib support for transcript data files
+ [5d10260807da]
+
+ * Makefile.in:
+ remove vestiges of ZLDFLAGS
+ [1fa0caf1c0fb]
+
+ * script.c:
+ Add missing variable declaration for when TIOCSCTTY is not defined.
+ Need to include sys/termio.h for TIOCSCTTY on some systems.
+ [ee7f41ac2709]
+
+ * script.c:
+ when resuming command, send SIGCONT to its pgrp not just pid
+ [5cd63c1d565b]
+
+ * selinux.c:
+ remove unused variable
+ [df67df4be228]
+
+ * script.c:
+ include selinux.h for is_selinux_enabled() proto
+ [85ebaa880cc1]
+
+ * script.c:
+ Don't use log_error() in the child process.
+ [def65fe2a433]
+
+ * script.c:
+ Do I/O in parent instead of child since the parent can have both
+ /dev/tty as well as the pty fds open. The child just sets things up
+ and waits for its grandchild and writes the signal description to
+ the pty master if the command was killed by a signal.
+ [95e473208982]
+
+2009-10-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * missing.h, sudo.h:
+ Move two struct forward declarations from sudo.h to missing.h
+ [90ad28294a8c]
+
+ * script.c:
+ Make comment at the top of script_exec() match reality.
+ [c5042d27dbe0]
+
+ * sudo.c:
+ if neither stdin nor stdout is a tty, check stderr
+ [c532ff20c8d8]
+
+ * Makefile.in:
+ Add back dependecy of gram.h on gram.y
+ [c58382b7fcca]
+
+ * script.c:
+ Make transcript mode work as long as we can figure out our tty, even
+ if it is not stdin. We'd like to use /dev/tty but that won't be
+ valid after the setsid().
+ [7b8bba8d99e7]
+
+2009-10-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, pty.c:
+ Add support for IRIX-style dynamic ptys
+ [bedc9bac44c1]
+
+ * Makefile.in, alloc.h, getline.c, sudo.h, sudoreplay.c:
+ Move alloc.c protos into alloc.h
+ [b6a90649617d]
+
+ * missing.h:
+ Move prototypes for missing libc functions to missing.h
+ [dda9ae1ccaf8]
+
+ * Makefile.in, sudo.h, sudoreplay.c:
+ Move prototypes for missing libc functions to missing.h
+ [7483166b577b]
+
+2009-10-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in:
+ Disable transcript support if no tcsetpgrp until we support older
+ BSD-style job control.
+ [27ac1d8163df]
+
+ * configure, configure.in, pty.c, script.c:
+ Break out pty code into pty.c
+ [e85509b25d41]
+
+ * compat.h, config.h.in, configure, configure.in:
+ add killpg macro if no killpg function
+ [3a125f4a51f0]
+
+ * config.h.in, configure, configure.in, script.c:
+ Push ptem and ldterm for STERAMS-based systems when allocating a
+ pty.
+ [36bb39b30ff2]
+
+2009-10-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * script.c:
+ Sprinkle some more O_NOCTTY and call grantpt() before unlockpt()
+ [d94bd5c9bf4e]
+
+ * script.c:
+ Call tcgetpgrp() in the parent, not the child and have the child
+ spin until it is granted. Fixes a race on darwin.
+ [6e8d435339ce]
+
+ * script.c:
+ Only use TIOCNOTTY in the non-setsid case. If no TIOCSCTTY, just
+ reopen slave.
+ [0bdc63c019ca]
+
+2009-10-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * script.c:
+ In script mode, if the command is killed by a signal, print the
+ signal description as well as a core dump notification like the
+ shell does.
+ [9df61738df07]
+
+ * Makefile.in, config.h.in, configure, configure.in, strsignal.c,
+ sudo.h:
+ Add check for strsignal() and a simple implementation if it is not
+ there but sys_siglist is
+ [61421a188ef4]
+
+ * script.c:
+ Add missing WUNTRACED and store the signal that stopped the
+ grandchild in suspended, not signo.
+ [df65042b200e]
+
+ * script.c:
+ g/c unused code
+ [40d8cb5c9203]
+
+ * script.c:
+ Associate the grandchild's pgrp with the tty instead of the child's
+ and just get suspend notifications via SIGCHLD instead of directly.
+ This fixes a hang with programs that try to set terminal attributes
+ and is more consistent with how the shell handles things.
+ [6865abff7e94]
+
+2009-10-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * script.c:
+ Move setpgid() of child into the parent side of the fork() where it
+ belongs.
+ [3defa782777c]
+
+2009-10-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * script.c:
+ fix typo
+ [b6a612b3622c]
+
+ * script.c:
+ Run command in its own pgrp (like the shell does) for easier
+ signalling. No need to relay SIGINT or SIGQUIT to parent, just send
+ to grandchild. Don't want grandchild stopped events in the child
+ (only termination). Flush output after suspending grandchild before
+ signalling parent.
+ [db556bf2176f]
+
+ * script.c:
+ Back out revision 1.34; the problem lies elsewhere.
+ [85f590a03275]
+
+ * script.c:
+ Don't set stdout to blocking mode when flushing remaining output. It
+ can cause us to hang when trying to exit. Need to investigate why.
+ [6f803a3e33ca]
+
+ * script.c:
+ Handle SIGTTOU and remove some debugging.
+ [52d17279053e]
+
+ * term.c:
+ Back out revision 1.10 as the signal that interrupts us may be
+ SIGTTOU or SIGTTIN which the caller must handle.
+ [7e2fa9107975]
+
+ * script.c:
+ Apparently we need to send SIGSTOP to the command as well as ourself
+ when we get SIGTSTP, the kernel doesn't automatically stop the
+ process for us.
+ [1a936e9309c4]
+
+ * script.c:
+ Use an extra process to act as the glue bewteen the sessions
+ associated with the user's controlling tty (what the shell uses) and
+ the tty that sudo is using to do its logging. Basically, this means
+ that if we get, e.g. SIGTSTP from the process sudo is running, we
+ relay the signal to the parent so it's shell can do the job control.
+ [6dd296988060]
+
+ * term.c:
+ Handle getting/setting terminal attributes when the fd is in non-
+ blocking mode.
+ [ae5ae535ea7b]
+
+2009-10-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoreplay.c, sudoreplay.cat, sudoreplay.man.in, sudoreplay.pod:
+ Add support for pausing and changing the speed in interactive mode.
+ [72a2063780a7]
+
+ * script.c:
+ Already define O_NOCTTY in compat.h, don't need it here
+ [b5d80ed3e5ce]
+
+2009-10-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoreplay.c:
+ Add missing protos
+ [c4cb4e7f4d8a]
+
+2009-09-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo_edit.c:
+ Always update the stashed mtime of the temp file instead of using
+ what we have for the original because the time resolution of the
+ filesystem the temporary is on may not match that of the filesystem
+ that holds the original. Should fix bz #371 found by Philippe Levan.
+ [c86ca4bec60c]
+
+ * sudoreplay.c:
+ Use cbreak mode instead of raw mode and add signal handlers to
+ restore the tty on interrupt.
+ [84dd283da41c]
+
+ * script.c, sudo.h, term.c:
+ Retain NL to NLCR conversion on the real tty and skip it on the pty
+ we allocate. That way, if stdout is not a pty there are no extra
+ carriage returns.
+ [32e4f570414e]
+
+ * script.c:
+ Fix log_output(); just pass in a string and a length.
+ [ca980cc0a3fb]
+
+2009-09-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * script.c:
+ do not use errno when complaining out lack of a tty
+ [8f9b8c55ab8e]
+
+2009-09-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, sudoreplay.c, term.c:
+ Instead of messing with line endings, just set terminal to raw mode
+ in sudoreplay.
+ [90943fa87acb]
+
+ * term.c:
+ When copying the terminal attributes to the pty, be sure not to set
+ ONLCR. This prevents extra carriage returns from ending up in the
+ script output file.
+ [e6b5475ac2aa]
+
+ * script.c:
+ Convert a do {} while into a while
+ [e461310d2c77]
+
+ * Makefile.in:
+ Use if then instead of test && when installing binaries that may not
+ exist.
+ [ad4f9490d971]
+
+ * script.c:
+ Add O_NOCTTY when opening a tty device. Explicitly disconnect from
+ old tty before associatng with new one.
+ [0e0ca634b80c]
+
+ * script.c, selinux.c, sudo.c, sudo.h:
+ First cut at refactoring some of the selinux code so it can be used
+ in conjunction with sudo's transcript support.
+ [779b0d8f9d29]
+
+2009-09-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aclocal.m4, configure, configure.in:
+ Fix default case of transcript_enabled being unset.
+ [f8aa96186e6b]
+
+ * script.c, sudoreplay.c:
+ Use _PATH_SUDO_TRANSCRIPT instead of _PATH_SUDO_SESSDIR
+ [2844a7a851fa]
+
+ * INSTALL, Makefile.in, aclocal.m4, configure, configure.in, sudo.c:
+ Hook up --disable-transcript and --enable-transcript=DIR
+ [b3fa7e6b2480]
+
+2009-09-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aclocal.m4, configure, configure.in, pathnames.h.in:
+ _PATH_SUDO_SESSDIR -> _PATH_SUDO_TRANSCRIPT Add --enable-
+ transcript=DIR option to specify the directory
+ [b0bb76d43cda]
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in:
+ regen
+ [c7a8a0a9027c]
+
+ * configure, configure.in, sudoers.man.pl, sudoers.pod:
+ Substitute in default value for secure_path
+ [c8f9ac6dbf93]
+
+ * sudo.pod:
+ Mention that the password must be followed by a newline with the -S
+ option.
+ [2fc589a3ee7e]
+
+2009-09-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * script.c:
+ Go back to dropping out of the select() loop when the process dies;
+ Linux ptys apparently don't behave the same as BSD in regards to
+ select(). No need to flush remaining output to the transcript, only
+ to stdout. Add back code to check the master pty for additional data
+ when we exit the main select loop.
+ [abed9a9cbc6b]
+
+2009-09-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ Add getline.o to COMMON_OBJS
+ [04ef7643cbc2]
+
+ * Makefile.in:
+ sudoreplay depends on libsudo.a
+ [142bd0472631]
+
+ * Makefile.in:
+ More pwutil.o into COMMON_OBJS
+ [4a016b933629]
+
+ * pwutil.c, testsudoers.c, tsgetgrpw.c:
+ Remove my_* redirection in pwutil.c for testsudoers and just use the
+ normal libc get{pw,gr}* names.
+ [9b76d637d86b]
+
+ * sudoreplay.cat, sudoreplay.man.in, sudoreplay.pod:
+ More time and date examples
+ [c6ee0175ec56]
+
+ * Makefile.in, configure, configure.in, nanosleep.c, sudoreplay.c:
+ Move nanosleep() emulation into its own file Check librt.a for
+ nanosleep if we don't find it in libc
+ [4da0cc26aad7]
+
+ * Makefile.in, configure, configure.in:
+ Build libsudo with the common bits and link things against that.
+ [2b53bc0b081a]
+
+ * script.c:
+ Fix final flush.
+ [6da287d833da]
+
+ * script.c:
+ Keep reading from the pty master -> log file until read returns <=
+ 0. Do our best to write everything to stdout when flushing any
+ remaining bits.
+ [2a45d4ae280c]
+
+ * sudoreplay.c:
+ Use unbuffered I/O when writing to stdout and make sure we write the
+ entire buffer.
+ [f39ef9844a47]
+
+2009-09-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoreplay.c:
+ Only use max_wait if it is non-zero
+ [f6c10604d2e8]
+
+ * getdate.c, getdate.y, getline.c:
+ Need compat.h here
+ [5d6722e225a0]
+
+ * sudoreplay.c:
+ Fix nanosleep emulation
+ [34e5e5d72a76]
+
+ * script.c:
+ Fix comment after #endif
+ [bd1347718b25]
+
+ * sudoreplay.c:
+ Add protos for missing libc bits
+ [644f496427a2]
+
+ * configure, configure.in:
+ add missing line continuation char
+ [db13c0d402cd]
+
+ * config.h.in, configure, configure.in, getline.c:
+ Implement getline() in terms of fgetln() if we have it.
+ [3ab786eaadc5]
+
+ * sudoreplay.c:
+ Print year when formatting log line
+ [90be669e3443]
+
+ * sudoreplay.pod:
+ Document cwd, attempt to document time/date formats.
+ [6290fb9b65c6]
+
+ * sudoreplay.c:
+ Fix getline return value check.
+ [d696d6657261]
+
+ * Makefile.in, config.h.in, configure, configure.in, getline.c,
+ sudoreplay.c:
+ Use getline() if the system has it, else use provide our own for
+ sudoreplay.
+ [afca1d6fbe5e]
+
+ * script.c:
+ Refactor code to update output and timing files.
+ [361491332b1a]
+
+2009-09-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoreplay.c:
+ Make sudo_getln() behave more like glibc getline.
+ [40c9f2ea29e6]
+
+ * script.c:
+ When flushing remaining output, also update timing file.
+ [5a9a5a627549]
+
+ * sudoreplay.c:
+ Use get_timestr() and make the -l output look like the regular sudo
+ log.
+ [452ba9d436c9]
+
+ * logging.c, sudo.h, timestr.c:
+ Make get_timestr() take a time_t so we can use it properly in
+ sudoreplay.
+ [82e67cc53c9c]
+
+ * script.c:
+ Create session dir earlier now that we update the seq number early.
+ [797fe8d6dc61]
+
+2009-09-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoreplay.c:
+ Use fromdate and todate as the keywords instead of from and to; the
+ short forms will still be accepted.
+ [d14d9b116df4]
+
+ * sudoreplay.c:
+ Fix reading long liensin sudo_getln()
+ [58dadd74118c]
+
+ * script.c, sudoreplay.c:
+ Log the cwd in the script log file. Add sudo_getln() to read
+ arbitrarily long lines.
+ [faceb802ab8f]
+
+ * Makefile.in, logging.c, sudo.h, timestr.c:
+ Move get_timestr() into its own source file so sudoreplay can use
+ it.
+ [99b054bfa20a]
+
+2009-09-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoreplay.c:
+ Add to and from perdicates (date ranges); needs documentation
+ [1d629174dcf4]
+
+2009-09-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, getdate.c, getdate.y:
+ Fix warning and add generated getdate.c
+ [b877a86b5a03]
+
+ * Makefile.in, getdate.y:
+ Add getdate.y to be used for sudoreplay date parsing.
+ [b8e26fbb7a40]
+
+2009-09-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoreplay.c:
+ Check more than just the first character of a predicate
+ [4fe53728adb1]
+
+ * sudoreplay.cat, sudoreplay.man.in, sudoreplay.pod:
+ Add examples, sort predicates
+ [70f8075cbccc]
+
+ * Makefile.in, sudoreplay.c, sudoreplay.cat, sudoreplay.man.in,
+ sudoreplay.pod:
+ Implement search expressions in sudoreplay similar in concept to
+ what find or tcpdump uses. TODO: date ranges
+ [f7ce4fb4cf3a]
+
+2009-09-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * script.c:
+ Remove vhangup as it was hanging up the wrong tty. Should really
+ vhangup in the child after it as set its tty.
+ [2eed9df73010]
+
+ * sudoers.pod:
+ Fix cut at documenting transcript support.
+ [e6c533a5568a]
+
+ * logging.c:
+ ID= -> TSID= for transcript ID
+ [1bf755a35333]
+
+2009-09-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ Move fast_glob description to where it belongs in sorted order
+ [5901cfb0d25f]
+
+ * def_data.c, def_data.h, def_data.in, gram.c, gram.h, gram.y,
+ parse.c, parse.h, sudo.c:
+ Rename script -> transcript
+ [e06cf823122c]
+
+2009-09-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat.h:
+ Add timeradd and timersub for those without them
+ [929f8aa06c2b]
+
+ * script.c:
+ Sanity check sessid before using it.
+ [aa8ca5211d43]
+
+ * sudo.c:
+ Only set the session id if we are running a command or editing a
+ file.
+ [7205d717c098]
+
+ * script.c:
+ Actually. qsort is fine since most versions fal back to a cheaper
+ sort when the number of elements to sort is small (like in our
+ case).
+ [d11c7cd352fe]
+
+ * config.h.in, configure, configure.in, script.c:
+ Check for dup2 and use dup instead if we don't have it.
+ [98bd89830f8a]
+
+ * script.c, sudo.c, sudo.h:
+ Move the code to dup2 the script fds to low numbered descriptors
+ into script_duplow() and fix the fd sorting.
+ [9453fdc5fba6]
+
+ * script.c, sudo.c, sudo.h:
+ Move script_setup() back to immediately before we drop privs and
+ call the new script_nextid() in its place, which will set
+ sudo_user.sessid for the logging functions.
+ [8434d0c8ff08]
+
+2009-09-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ Install sudoreplay
+ [6acf2cdb4d3f]
+
+ * sudoreplay.c:
+ remove unused variable
+ [2316360bb992]
+
+2009-08-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c, script.c, sudo.c, sudo.h:
+ Log the session ID, if there is one. Currently logs ID=XXXXXX,
+ perhaps should be SESSIONID or SESSID.
+ [53976905b0a6]
+
+ * Makefile.in, configure, configure.in, sudoreplay.cat,
+ sudoreplay.man.in, sudoreplay.pod:
+ Add sudoreplay docs
+ [da4f14f0e64c]
+
+ * sudoreplay.c:
+ add -V (version) flag
+ [b5e743639ee3]
+
+ * sudoreplay.c:
+ Hook up max_wait.
+ [2ec5697a92ba]
+
+ * script.c, sudoreplay.c:
+ Use base36 number for the ID and store script files with paths like
+ /var/log/sudo-session/00/00/00{,.tim,.scr}. This gives us 36^6
+ (2,176,782,336) unique IDs.
+ [6aab019d07aa]
+
+2009-08-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure.in:
+ Add check for regcomp
+ [44c3ebd7ff34]
+
+ * sudoreplay.c:
+ Add support for selecting by pattern and tty when listing.
+ [66189f840c52]
+
+2009-08-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoreplay.c:
+ The beginnings of a list mode.
+ [8d0150b4a52c]
+
+2009-08-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ fix pasto
+ [616b4640b8a8]
+
+ * Makefile.in, config.h.in, configure.in:
+ Add scaffolding for building sudoreplay
+ [a32958505dbe]
+
+ * sudoreplay.c:
+ include error.h first arg to nanotime is const
+ [fe5a7bb31bc5]
+
+ * sudoreplay.c:
+ Initial cut at sudoreplay; replay a sudo session.
+ [f149fba372bd]
+
+2009-08-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * script.c:
+ Fix wait() usage and use correct wait status.
+ [f4745ed7ad05]
+
+ * sudo.c, sudo.h, tgetpass.c:
+ Add protos for term_* to sudo.h
+ [14fe1abd7e7b]
+
+ * script.c:
+ Fix detection of the child process exiting. Since the child is in
+ its own session we should only ever get SIGCHLD for that process but
+ better safe than sorry.
+ [7edfdadd8505]
+
+ * config.h.in:
+ Add UNIX98 pty support.
+ [82f4b53a0e8f]
+
+ * configure, configure.in, script.c:
+ Add UNIX98 pty support.
+ [795b8bb0a3a1]
+
+2009-08-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * term.c:
+ For raw mode, don't bother clearing BRKINT or PARMRK and clear IUCLC
+ if it is defined.
+ [40f8b83baf69]
+
+ * auth/pam.c:
+ Set PAM_RUSER and PAM_RHOST early so they can be used during
+ authentication. Based on a patch from Jamie Beverly.
+ [3d567b453a6a]
+
+ * match.c:
+ Close dir before returning if strlcpy() reports overflow. From
+ Martynas Venckus.
+ [6a82f96473e5]
+
+ * config.h.in, configure, configure.in, script.c:
+ On Linux, the openpty proto libes in pty.h
+ [98643a018d1c]
+
+ * script.c:
+ Call vhangup on exit if the system has it Use setpgrp() if no
+ setsid()
+ [3a9e13149829]
+
+2009-08-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in:
+ Add checks for revoke and vhangup if we don't have openpty
+ [fcb04572e994]
+
+ * script.c:
+ Session logging guts that got forgotten in the previous commit.
+ [c2af08a63ea9]
+
+ * Makefile.in, aclocal.m4, compat.h, config.h.in, configure,
+ configure.in, def_data.c, def_data.h, def_data.in, gram.c, gram.h,
+ gram.y, parse.c, parse.h, pathnames.h.in, sudo.c, sudo.h, term.c,
+ tgetpass.c:
+ First cut at session logging for sudo. Still need to write get_pty()
+ for Unix 98 and old-style BSD ptys. Also needs documentation and
+ general cleanup.
+ [77e3f5e25738]
+
+2009-08-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c, sudo_edit.c:
+ Fix a bug introduced with def_closefrom. The value of def_closefrom
+ already includes the +1.
+ [7291c136300d]
+
+2009-07-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ Generate sudo distributions with pax in ustar mode. No longer need
+ to use a temp file or have the source dir name match the version.
+ [9778177a8272]
+
+2009-07-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * toke.c, toke.l:
+ Fix expansion of %h in #include names. Fixes bugzilla 363
+ [6e346879ba24]
+
+2009-07-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkdefaults:
+ If no arg assume def_data.in
+ [c1dd28c0e675]
+
+ * README, WHATSNEW:
+ Update for 1.7.2
+ [f5ad45f69f05] [SUDO_1_7_2]
+
+ * ChangeLog:
+ sync
+ [6283549396ff]
+
+2009-06-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.cat, sudoers.man.in, sudoers.pod:
+ Add missing single quotes around a colon in Runas_Spec definition.
+ From Elias Benali.
+ [ccc6ee4fca83]
+
+2009-06-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.man.in, sudoers.man.in:
+ regen
+ [546e75304ebf]
+
+ * redblack.c:
+ In rbrepair, re-color the root or the first non-block node we find
+ to be black. Re-coloring the root is probably not needed but won't
+ hurt.
+ [34d01ebe241b]
+
+ * sudo.cat, sudoers.cat:
+ regen
+ [bebf5a39f54f]
+
+2009-06-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * redblack.c:
+ When repairing the tree, don't touch the root node.
+ [9841f0d5d789]
+
+2009-06-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * set_perms.c:
+ Protect call to setegid in runas_setup with #ifdef HAVE_SETEUID.
+ Reported by Josef Schmid.
+ [ed044b1eb879]
+
+2009-06-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ Document that we accept env_pam-style environment files
+ [e3b545456352]
+
+ * env.c:
+ Adapt to accept pam_env-style /etc/environment which allows shell-
+ style lines such as: export EDITOR="/usr/bin/vi"
+ [752eb75bf007]
+
+ * sudoers.pod:
+ Make it clear that env_delete only works when !env_reset. From Loïc
+ Minier
+ [3bd3f8e351ba]
+
+2009-06-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod, sudoers.pod:
+ Add non-unix group bits, adapted from Quest
+ [8ce427de8dea]
+
+ * Makefile.in:
+ build the .cat page in the current working dir, not the src dir
+ [00e87a307674]
+
+ * env.c:
+ Return EINVAL in setenv() if var is NULL or the empty string to
+ match glibc behavior.
+ [23fd7c247142]
+
+2009-06-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Use AS_HELP_STRING for AC_ARG_WITH and AC_ARG_ENABLE
+ [fedd4a3e2a85]
+
+2009-06-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.ldap.cat,
+ sudoers.ldap.man.in, sudoers.man.in, visudo.cat, visudo.man.in:
+ regen
+ [7b9f461a40b3]
+
+2009-06-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ Document --with-libvas and --with-libvas-rpath
+ [a071e6d96c89]
+
+2009-05-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c, sudoers.ldap.pod:
+ For netscape-derived LDAP SDKs the cert and key paths may be a
+ directory or a file. However, version 5.0 of the SDK only seems to
+ support using a directory. If ldapssl_clientauth_init fails and the
+ cert or key paths look like they could be files, strip off the last
+ path element and try again.
+ [ac4e49d83043]
+
+ * Makefile.in:
+ Add non-Unix group .o to COMMON_OBJS and substitute in path to flex.
+ [4547cc1a335f]
+
+2009-05-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in, match.c, sudo.c, vasgroups.c:
+ Update non-Unix group support from Quest, as reworked by me.
+ [1abafce29dc6]
+
+ * toke.c:
+ regen
+ [01bfca9148b7]
+
+ * toke.l:
+ Add support for escaped hex chars in names, e.g. \x20 for space.
+ [3c7be8e58a39]
+
+2009-05-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * LICENSE, Makefile.in, aclocal.m4, alias.c, auth/aix_auth.c,
+ auth/pam.c, auth/sudo_auth.c, auth/sudo_auth.h, check.c, env.c,
+ fileops.c, glob.c, gram.y, interfaces.c, lbuf.c, ldap.c, logging.c,
+ logging.h, match.c, parse.c, parse.h, pathnames.h.in, pwutil.c,
+ set_perms.c, sudo.c, sudo.h, sudo.pod, sudo_nss.c, sudo_nss.h,
+ sudo_usage.h.in, sudoers.ldap.pod, sudoers.pod, testsudoers.c,
+ tgetpass.c, toke.l, visudo.c:
+ Update copyright years.
+ [e615f676c764]
+
+2009-05-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * interfaces.c, lbuf.c:
+ Minor fixes for Minix-3
+ [898c510d23f9]
+
+2009-05-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * set_perms.c:
+ Handle getgroups() returning 0. Also add missing check for
+ HAVE_GETGROUPS.
+ [d73b958f9ffd]
+
+2009-05-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, config.h.in, configure, configure.in, sudo.c,
+ version.h, visudo.c:
+ Replace version.h with PACKAGE_VERSION set via AC_INIT in configure.
+ [5050579a264d]
+
+2009-05-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * set_perms.c:
+ Remove group setting code in setusercontext case, we will do it
+ ourselves later on in runas_setup. Set the gid after
+ initgroups/setgroups is called, since on Mac OS X it seems to change
+ the egid.
+ [09dc21d8b42d]
+
+2009-05-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * LICENSE, Makefile.in, config.h.in, match.c, nonunix.h, sudo.c,
+ vasgroups.c:
+ Initial bits of non-unix group support using Quest Authentication
+ Services
+ [1eecab0ff27e]
+
+ * toke.c, toke.l:
+ Accept %:foo as a non-Unix group
+ [4c4b5dd899a6]
+
+ * toke.c, toke.l:
+ Allow user/group to be double quoted in the case of non-Unix groups
+ which contain spaces.
+ [47a3d568b7e8]
+
+2009-05-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * match.c:
+ Don't allow the user to specify the default runas user if their
+ sudoers entry only allows them to run as a group.
+ [4d726177227c]
+
+2009-05-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Must call audit_success before we change uids.
+ [04a9e6ce6e55]
+
+ * logging.c, set_perms.c, sudo.h, testsudoers.c:
+ Add option for set_perm to not exit on failure and use this in the
+ logging routines.
+ [833dce7b7f42]
+
+ * parse.c:
+ In -l mode, if the user is only allowed to run as a group, display
+ the user's name, not root's before the allowed group.
+ [ef92ff99d265]
+
+ * sudo.c:
+ Fix -g mode, broken by rev 1.503 which had the side effect of
+ setting the runas user to root unilaterally.
+ [50a2f7df4385]
+
+2009-05-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * fileops.c:
+ When unlocking a file with fcntl, use F_SETLK, not F_SETLKW.
+ [30fbe832dcf3]
+
+ * pwutil.c:
+ Only cache by the method we fetched for pwd and grp lookups.
+ Previously we cached both by namd and id but this can cause problems
+ for entries that share the same id. Also add more info in the error
+ message in case the insert fails (which should now be impossible).
+ [ef95a4f0bab5]
+
+2009-04-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ Add a clarification from Nick Sieger
+ [1eadad329561]
+
+2009-04-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ Inline the setting of the environment string.
+ [9515d11c6295]
+
+2009-04-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ setenv(3) in Linux treats a NUL value as the empty string setenv(3)
+ in BSD doesn't return an error if the name has '=' in it, it just
+ treats the '=' as end of string.
+ [941260bf94d2]
+
+2009-04-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * toke.c, toke.l:
+ Not all systems have d_namlen
+ [e377b18d8e2d]
+
+2009-04-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ Fix up some pod2html issues.
+ [823a1f10ab60]
+
+2009-04-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * interfaces.c:
+ Check for NULL ifa_addr and ifa_netmask. Adapted from a diff from
+ Quest Software.
+ [73de36653131]
+
+ * sudoers.pod:
+ Ignore files ending in '~' in sudo.d (emacs backup files)
+ [7871fad702db]
+
+ * toke.c, toke.l:
+ Ignore files ending in '~' in sudo.d (emacs backup files)
+ [53fded2a469f]
+
+2009-04-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.cat, sudoers.man.in, sudoers.pod, toke.c, toke.l:
+ For #includedir, ignore any file containing a dot
+ [a7daa1bce6c2]
+
+ * Makefile.in, version.h:
+ Bump version
+ [ef60f14ffc44]
+
+ * gram.c, gram.y, parse.c, parse.h, sudo.c, sudo.h, sudoers.cat,
+ sudoers.man.in, sudoers.pod, testsudoers.c, toke.c, toke.l,
+ visudo.c:
+ Implement #includedir directive. Files in an includedir are not
+ edited by visudo unless they contain a syntax error.
+ [3923d85a6c79]
+
+ * ChangeLog:
+ sync
+ [8741ed61a78b] [SUDO_1_7_1]
+
+ * WHATSNEW:
+ Forgot umask_override
+ [7c86a21a5504]
+
+ * ChangeLog, TODO:
+ sync
+ [57339ca6bccf]
+
+2009-04-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ Rewind stream if we fdopen sudoers since it may not be at the
+ beginning. Set the keepopen flag on already-open files too so the
+ lexer doesn't close them out from under us.
+ [61292d819aff]
+
+ * visudo.c:
+ Print the proper file name when there is a parse error in an include
+ file.
+ [b0e85d4aedde]
+
+2009-04-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * WHATSNEW:
+ Sync
+ [997e5d485ea3]
+
+2009-04-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Fix a warning when --without-ldap is specified.
+ [d91fd9481b30]
+
+2009-04-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * alias.c, parse.h, visudo.c:
+ Store aliases that we remove during check_aliases in a freelist and
+ free them at the end so we don't leak memory.
+ [805e2272f6a3]
+
+2009-03-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ Check aliases in -c mode too.
+ [9199e188d9f2]
+
+ * alias.c, parse.h, visudo.c:
+ Make alias_remove return the alias struct instead of freeing it
+ directly. Fixes a use after free in alias_remove_recursive, the only
+ consumer.
+ [a04b61804800]
+
+ * alias.c, match.c, parse.c, parse.h, visudo.c:
+ Rename find_alias -> alias_find for consistency.
+ [48b0a82924f3]
+
+2009-03-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ When checking for unused aliases, recurse if the alias points to
+ another alias.
+ [2d4d1a7f3a41]
+
+2009-03-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ Back out rev 1.105 for now. Real ldapux_client.conf support will be
+ done later after some refactoring.
+ [8ad72e69b277]
+
+2009-03-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ Treat ldap_hostport the same as "host" for ldapux.
+ [3281dcc66da8]
+
+ * configure, configure.in:
+ Only check for ldap_sasl_interactive_bind_s if we can find sasl.h.
+ Fixes compilation with ldapux.
+ [ca1ed585ef0e]
+
+2009-03-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * fileops.c:
+ fix char subscript
+ [41e51f080d00]
+
+2009-03-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ remove errant carriage returns
+ [e9e258a31c7b]
+
+ * audit.c, env.c:
+ fix K&R compilation
+ [d182e8920f13]
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.ldap.cat,
+ sudoers.ldap.man.in, sudoers.man.in, visudo.cat, visudo.man.in:
+ regen
+ [791a5cbf04e5]
+
+2009-03-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in:
+ Add missing HAVE_BSM_AUDIT
+ [49ad1bb96f04]
+
+ * WHATSNEW:
+ Add 1.7.1 features
+ [f107f1604c61]
+
+ * INSTALL:
+ Mention --with-netsvc
+ [d1e90d147795]
+
+ * sudoers.ldap.pod:
+ Document netsvc.conf support
+ [e78f8abce6af]
+
+ * configure, configure.in, pathnames.h.in, sudo.c, sudo_nss.c,
+ sudo_nss.h:
+ Add support for AIX netsvc.conf (like nsswitch.conf).
+ [1df56a84dee5]
+
+2009-03-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, env.c:
+ Add --enable-env-debug flag to enable environment sanity checks.
+ [128cdd8832e7]
+
+ * sudoers.ldap.pod, sudoers.pod:
+ Work around some pod2html issue.
+ [e733b9609bd2]
+
+2009-03-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ Only sync environ for putenv, setenv, and unsetenv. We need to make
+ sure that sudo_putenv and sudo_setenv only modify env.envp, not
+ environ.
+ [be3ac732243c]
+
+2009-03-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ Really fix UNSETENV_VOID
+ [08ab7e882507]
+
+ * env.c:
+ Fix unsetenv when UNSETENV_VOID
+ [d3038b3f2f15]
+
+ * aclocal.m4, configure:
+ Fix SUDO_FUNC_PUTENV_CONST
+ [de35569c572b]
+
+ * ldap.c:
+ tivoli-based ldap does not have ldapssl_err2string
+ [c63fd90d5e99]
+
+ * configure:
+ regen
+ [f38f1ee828ad]
+
+2009-03-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, ldap.c:
+ Add support for Tivoli-based LDAP start TLS as seen in AIX.
+ Untested.
+ [8f8771829f85]
+
+ * env.c:
+ Add sanity checks for setenv/unsetenv
+ [adbd1d95856b]
+
+ * Makefile.in:
+ Include bsm_audit.h in the tarball
+ [4a4aa02b2c32]
+
+ * Makefile.in, version.h:
+ bump version for sudo 1.7.1
+ [362c71d21595]
+
+ * aclocal.m4, auth/aix_auth.c, config.h.in, configure, configure.in,
+ env.c, ldap.c, sudo.h:
+ Replace sudo_setenv/sudo_unsetenv with calls to setenv/unsetenv and
+ provide our own setenv/unsetenv/putenv that operates on own env
+ pointer. Make sync_env() inline in setenv/unsetenv/putenv functions.
+ [276edcd23032]
+
+2009-02-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Make "sudoedit -h" work as expected
+ [2bcbbb45d389]
+
+ * auth/pam.c:
+ Make sure def_prompt is always defined. This is a workaround for pam
+ configs that prompt for a password in the session but don't have an
+ auth line. A better fix is to expand the sudo prompt earlier and set
+ def_prompt to that when initializing.
+ [ee073c04aec3]
+
+ * sudo.pod:
+ Mention that the helper for -A may be graphical.
+ [b64a940c4082]
+
+ * TROUBLESHOOTING:
+ Document what happens if there is no tty.
+ [313d58a856a5]
+
+ * sudo.c:
+ cosmetic changes
+ [894f5e3b0c3e]
+
+ * term.c:
+ Fix term_restore
+ [6c6315ff14bc]
+
+ * sudo.c:
+ Fix "sudo -k" with no other args
+ [59e94dc419c6]
+
+2009-02-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c, sudo.c, sudo.pod, sudo_usage.h.in:
+ Allow the -k flag to be specified in conjunction with a command or
+ another option that may require authentication.
+ [5960ff20355d]
+
+2009-02-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Remove unneeded AC_CANONICAL_TARGET; from Diego E. 'Flameeyes'
+ [e86ab69c4a57]
+
+ * Makefile.in:
+ Parallel make fix. From Diego E. 'Flameeyes'
+ [1289d7ee27db]
+
+2009-02-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * def_data.c, def_data.h, def_data.in, sudo.c, sudoers.pod:
+ Implement umask_override
+ [8b87a3f7c5aa]
+
+ * toke.c:
+ regen
+ [79d7ca9ac873]
+
+ * sudoers.pod, toke.l, visudo.c:
+ Implement %h escape in sudoers include filenames.
+ [a7f288dd64f0]
+
+ * audit.c:
+ Need to include compat.h
+ [c0dc07ce2f70]
+
+ * Makefile.in, audit.c, bsm_audit.c, bsm_audit.h, logging.h, sudo.c:
+ Make audit_success and audit_failure generic functions in
+ preparation for integrating linux audit support.
+ [7df020a8fd6f]
+
+ * term.c:
+ remove duplicate include
+ [1dfcd01a7e46]
+
+2009-02-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * bsm_audit.c:
+ Add missing include
+ [fb56e08c37ee]
+
+ * sudo.c:
+ May need to update the runas user after parsing command-based
+ defaults.
+ [246f130d7802]
+
+2009-02-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * glob.c:
+ Add missing pair of braces introduced with character class support.
+ [0e2afa2e03e9]
+
+2009-02-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * def_data.c, def_data.h, def_data.in, sudoers.pod, tgetpass.c:
+ Rename pwstars to pwfeedback
+ [a9f85a57ebac]
+
+2009-02-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * bsm_audit.c, bsm_audit.h:
+ Add const to make MacOS happy.
+ [4274432d6627]
+
+ * Makefile.in, auth/sudo_auth.c, bsm_audit.c, bsm_audit.h, configure,
+ configure.in, sudo.c:
+ Add bsm audit support from Christian S.J. Peron
+ [bef61cd8693d]
+
+ * term.c:
+ This is new code, no DARPA notice.
+ [ec6ad09b9c23]
+
+2009-02-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * def_data.c, def_data.h, def_data.in, match.c, sudoers.pod:
+ Rename simple_glob -> fast_glob
+ [68d9ed803cc1]
+
+ * match.c:
+ g/c unused var
+ [693fa0464eb6]
+
+ * def_data.c, def_data.h, def_data.in, match.c, sudoers.pod:
+ Add simple_glob option to use fnmatch() instead of glob(). This is
+ useful when you need to specify patterns that reference network file
+ systems.
+ [77ba634f6949]
+
+ * tgetpass.c:
+ add term_* proto
+ [520f5149d073]
+
+ * sudoers.pod:
+ mention glob()
+ [ddaab8e03c52]
+
+2009-02-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * tgetpass.c:
+ Delete any pwstars we wrote after the user hits return. That way
+ there is no record on screen as to the user's password length.
+ [fae25cda762b]
+
+2009-02-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * term.c:
+ Move terminal setting bits from tgetpass.c to term.c
+ [03d43325ee99]
+
+ * Makefile.in, def_data.c, def_data.h, def_data.in, sudoers.pod,
+ tgetpass.c:
+ Add pwstars sudoers option that causes sudo to print a star every
+ time the user presses a key.
+ [7aab417e184d]
+
+2009-02-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ Fix up F<> brokenness for visudo.man.in and sudoers.ldap.man.in.
+ [64f70e879816]
+
+2009-01-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ For ldap_search_ext_s() the sizelimit param should be 0, not -1, to
+ indicate no limit. From Mark Janssen.
+ [e2c5732d54f5]
+
+2009-01-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * toke.c, toke.l:
+ Comments that begin with #- should not be parsed as uids.
+ [a72a50f12f41]
+
+2009-01-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Do not try to set the close on exec flag if we didn't actually open
+ sudoers.
+ [ece3ca256904]
+
+2008-12-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ChangeLog:
+ regen
+ [e11f0e4c1bdd] [SUDO_1_7_0]
+
+2008-12-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TODO:
+ sync
+ [5b8954462bb3]
+
+2008-12-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/pam.c:
+ Return PAM_AUTH_ERR instead of PAM_CONV_ERR if user enters ^C at the
+ password prompt.
+ [8563601cb3de]
+
+ * configure, configure.in:
+ Don't try to build sudo_noexec.so on HP-UX with the bundled compiler
+ as it cannot generate shared objects.
+ [6d4262ef9669]
+
+ * emul/charclass.h, glob.c, lbuf.c, tgetpass.c:
+ K&R compilation fixes
+ [77921678d17c]
+
+ * parse.c:
+ Use tq_foreach_fwd when checking pseudo-commands to make it clear
+ that we are not short-circuiting on last match. When pwcheck is
+ 'all', initialize nopass to TRUE and override it with the first non-
+ TRUE entry.
+ [96b209f4778f]
+
+2008-12-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ Do not short circuit pseudo commands when we get a match since,
+ depending on the settings, we may need to examine all commands for
+ tags.
+ [fdbaf89d6f35]
+
+2008-12-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.cat, sudoers.man.in:
+ regen
+ [1ecce7c1b841]
+
+ * sudoers.pod:
+ hostnames may also contain wildcards
+ [82b76695601c]
+
+ * Makefile.in:
+ remove stamp-* files and linux core files in clean target
+ [22003f091467]
+
+2008-12-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/sudo_auth.h, config.h.in, configure, configure.in:
+ Use HAVE_SIA_SES_INIT instead of HAVE_SIA for Digital UNIX
+ [6905bede8410]
+
+2008-11-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ correctly enable SIA on Digital UNIX
+ [a51881d13995]
+
+ * TODO:
+ checkpoint
+ [af0fe8d94d42]
+
+ * ChangeLog:
+ sync
+ [831f623cf99c]
+
+2008-11-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c, sudo.h, tgetpass.c:
+ Even if neither stdin nor stdout are ttys we may still have /dev/tty
+ available to us.
+ [20f306ba883b]
+
+2008-11-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.cat, sudoers.man.in:
+ regen
+ [76d97c4c318f]
+
+ * sudoers.pod:
+ fix typos; Markus Lude
+ [bff8bc1e2066]
+
+ * ChangeLog:
+ sync
+ [f108552531cd]
+
+ * toke.c:
+ regen
+ [de828413c67e]
+
+ * toke.l:
+ Fix matching of a line that only consists of a comment char
+ [09c953d8d5ca]
+
+2008-11-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/pam.c:
+ MacOS pam will retry conversation function if it fails so just treat
+ ^C as an empty password.
+ [d056058930bc]
+
+ * visudo.c:
+ When checking for alias use, also check defaults bindings.
+ [2647f82c7dbd]
+
+ * redblack.c:
+ unused var
+ [b7ff71c17c18]
+
+ * redblack.c:
+ Replace my rbdelete with Emin's version (which actually works ;-)
+ [21b133dd0c72]
+
+2008-11-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * testsudoers.c:
+ malloc debugging
+ [0fb446fa3279]
+
+ * visudo.c:
+ malloc options in devel mode for visudo too
+ [98d06c6afeef]
+
+2008-11-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ fix compilation on non-C99; from Theo
+ [7c304e16c536]
+
+ * visudo.c:
+ fix check_aliases
+ [83f30a3b1765]
+
+ * alias.c:
+ when destroying an alias, free the correct data pointer
+ [6e1a8bd86c01]
+
+ * auth/sudo_auth.h:
+ add proto for aixauth_cleanup; from Dale King
+ [eba94ffc8f63]
+
+2008-11-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat,
+ visudo.man.in:
+ regen
+ [409fa57fff83]
+
+ * sudo.pod, sudoers.pod, visudo.pod:
+ standardize on the term 'option' for command line options (not flag)
+ [228caefc2e36]
+
+2008-11-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ Add note on configuring HP-UX pam
+ [f7674a581baf]
+
+2008-11-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c, sudo.c:
+ Move tty checks into check_user() so we only do them if we actually
+ need a password.
+ [7d997d7106d6]
+
+ * sudo.c:
+ Don't error out if no tty or askpass unless we actually need to
+ authenticate.
+ [9f23b83ed66c]
+
+2008-11-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ChangeLog:
+ regen
+ [23f9aef32da6]
+
+ * pathnames.h.in, sudo.c:
+ s/overriden/overridden/; from Tobias Stoeckmann
+ [9f7459a8fac5]
+
+2008-11-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * WHATSNEW, visudo.c:
+ check sudoers owner and mode in strict mode
+ [a3468c5ac1c4]
+
+ * gram.c, toke.c:
+ regen
+ [7d6b515a5443]
+
+ * sudo.man.in, sudoers.man.in, visudo.man.in:
+ Update copyright years.
+ [52d340cb8cba]
+
+ * LICENSE, alias.c, alloc.c, auth/afs.c, auth/aix_auth.c,
+ auth/bsdauth.c, auth/fwtk.c, auth/kerb4.c, auth/kerb5.c, auth/pam.c,
+ auth/securid.c, auth/securid5.c, auth/sia.c, auth/sudo_auth.h,
+ closefrom.c, compat.h, defaults.c, defaults.h, env.c, fileops.c,
+ gettime.c, gram.y, ins_csops.h, insults.h, interfaces.c,
+ interfaces.h, lbuf.c, license.pod, list.c, logging.c, logging.h,
+ parse.c, parse.h, pwutil.c, redblack.c, redblack.h, snprintf.c,
+ sudo.c, sudo.pod, sudo_edit.c, sudo_nss.h, sudoers.pod,
+ testsudoers.c, toke.l, tsgetgrpw.c, utimes.c, version.h, visudo.c,
+ visudo.pod, zero_bytes.c:
+ Update copyright years.
+ [b4e6bf2beafa]
+
+ * emul/charclass.h, fnmatch.c, glob.c:
+ add my copyright
+ [28681385014a]
+
+2008-11-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * toke.c, toke.l:
+ The loop in fill_cmnd() was going one byte too far past the end,
+ resulting in a NUL being written immediately after the buffer end.
+ [a5a49d603cd7]
+
+ * UPGRADE, WHATSNEW:
+ add sections on tgetpass changes
+ [2e6929b6a102]
+
+ * tgetpass.c:
+ Treat EOF w/o newline as an error.
+ [aa02b1db9240]
+
+2008-11-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ Fix "sudo -v" when NOPASSWD is set.
+ [f4914711ea80]
+
+ * auth/bsdauth.c, auth/fwtk.c, auth/pam.c, auth/sudo_auth.c,
+ auth/sudo_auth.h:
+ No longer treat an empty password at the prompt as special. To quit
+ out of sudo you now need to hit ^C at the password prompt.
+ [980f760ad419]
+
+ * sudoers.cat, sudoers.man.in:
+ regen
+ [6ca21a2cd869]
+
+ * def_data.c, def_data.h, def_data.in, sudo.c, sudoers.pod:
+ Sudo will now refuse to run if no tty is present unless the new
+ visiblepw sudoers flag is set.
+ [0cc56943252e]
+
+2008-11-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aix.c:
+ just use RLIM_INFINITY for RLIM_SAVED_MAX if RLIM_SAVED_MAX not
+ defined
+ [24fc6f712d5c]
+
+ * aix.c:
+ fix fallback value for RLIM_SAVED_MAX
+ [e09e04e1af89]
+
+ * auth/aix_auth.c, auth/sudo_auth.h:
+ Move clearing of AUTHSTATE into aixauth_cleanup.
+ [e14ae7bd259c]
+
+ * auth/aix_auth.c, env.c:
+ Unset AUTHSTATE after calling authenticate() as it may not be
+ correct for the user we are running the command as.
+ [d14f68f1b0ab]
+
+ * isblank.c:
+ Add isblank() function for systems without it. Needed for POSIX
+ character class matching in fnmatch.c and glob.c.
+ [16cba30b283f]
+
+2008-11-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TROUBLESHOOTING:
+ expound on sudo and cd
+ [8e0fa9033637]
+
+2008-11-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ChangeLog:
+ regen
+ [40cf320a10fc]
+
+ * sudoers.cat, sudoers.man.in:
+ regen
+ [7cac761ae2c6]
+
+ * sudoers.pod:
+ mention defauts parse order
+ [4e2ce86d1394]
+
+2008-11-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, aclocal.m4, compat.h, configure:
+ Add isblank() function for systems without it. Needed for POSIX
+ character class matching in fnmatch.c and glob.c.
+ [a1ab55da8424]
+
+ * Makefile.in:
+ add emul/charclass.h to HDRS
+ [7e8a019dcaa4]
+
+2008-11-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TODO:
+ checkpoint
+ [afeb9bc1baed]
+
+ * defaults.c, parse.c, testsudoers.c, visudo.c:
+ Move update_defaults into defaults.c and call it properly from
+ visudo and testsudoers.
+ [f4dbb369461f]
+
+ * defaults.c, interfaces.c, pwutil.c, sudo.c, sudo_edit.c, tgetpass.c,
+ tsgetgrpw.c:
+ use zero_bytes() instead of memset() for consistency
+ [4cee0465f4a8]
+
+ * logging.c, mon_systrace.c, parse.c, sudo.c, sudo_edit.c, tgetpass.c,
+ visudo.c:
+ Zero out sigaction_t before use in case it has non-standard entries.
+ [120092225459]
+
+ * match.c:
+ quiet gcc
+ [098a1df49b23]
+
+ * match.c:
+ Short circuit glob() checks if basename(pattern) !=
+ basename(command). Refactor code that checks for a command in a
+ directory and use it in the glob case if the resolved pattern ends
+ in a '/'.
+ [3c46fd317acb]
+
+2008-11-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * defaults.h, parse.c, sudo.c, testsudoers.c, visudo.c:
+ Defer setting runas defaults until after runaspw/gr is setup.
+ [12e75ee49c0c]
+
+2008-10-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * match.c, sudo.c, testsudoers.c:
+ Use MAXHOSTNAMELEN+1 when allocating host/domain name since some
+ systems do not include space for the NUL in the size. Also manually
+ NUL-terminate buffer from gethostname() since POSIX is wishy-washy
+ on this.
+ [7266ab3296a3]
+
+2008-10-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c, sudoers.pod:
+ When setting the umask, use the union of the user's umask and the
+ default value set in sudoers so that we never lower the user's umask
+ when running a command.
+ [4e804b004e38]
+
+ * sudo.c:
+ Don't try to read from a zero-length sudoers file. Remove the bogus
+ Solaris work-around for EAGAIN. Since we now use fgetc() it should
+ not be a problem.
+ [bb8e5f68d944]
+
+2008-10-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ In update_defaults() check the return value of user*_matches against
+ ALLOW so we don't inadvertantly match on UNSPEC.
+ [4e422fa1527e]
+
+2008-10-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.ldap.cat,
+ sudoers.ldap.man.in, sudoers.man.in, visudo.cat, visudo.man.in:
+ regen man pages; no more hyphenation
+ [15de4fe2fe01]
+
+ * sudo.c:
+ Don't error out on a zero-length sudoers file. With the advent of
+ #include the user could create a situation where sudo is unusable.
+ [6eb461319fa5]
+
+2008-10-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/kerb5.c, config.h.in, configure, configure.in:
+ Newer heimdal has 2-argument krb5_get_init_creds_opt_free() like MIT
+ krb5. Really old heimdal has no krb5_get_init_creds_opt_alloc() at
+ all. Add configure tests to handle all the cases.
+ [4b554a98470d]
+
+2008-10-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod:
+ resort ENVIRONMENT
+ [f4f20f40653e]
+
+ * sudoers.pod:
+ document sudoers_locale
+ [0bffd2dbe806]
+
+ * sudo.pod, sudo_edit.c:
+ add SUDO_EDITOR variable that sudoedit uses in preference to VISUAL
+ or EDITOR
+ [0ef8cb248cee]
+
+ * toke.c, toke.l:
+ In fill_cmnd(), collapse any escaped sudo-specific characters.
+ Allows character classes to be used in pathnames.
+ [5685244c8e44]
+
+2008-10-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lbuf.c:
+ fix typo in non-C89 function declaration
+ [99a7113b3a05]
+
+ * sudoers.pod:
+ Mention POSIX characters classes now that out fnmatch() and glob()
+ support them.
+ [9c916f1230c3]
+
+ * sample.sudoers, sudoers.pod:
+ Replace [A-z] (which won't match in UTF8) with [A-Za-z] which is
+ locale agnostic.
+ [a60a62bec244]
+
+ * parse.h:
+ use __signed char if we are going to assign a negative value since
+ on Power, char is unsigned by default
+ [2877b319df17]
+
+ * config.h.in, configure, configure.in:
+ Add tests for __signed char and signed char.
+ [5eb874fdf1d4]
+
+ * aix.c:
+ Fix AIX limit setting. getuserattr() returns values in disk blocks
+ rather than bytes. The default hard stack size in newer AIX is
+ RLIM_SAVED_MAX. From Dale King.
+ [3db67415ecc3]
+
+2008-09-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * emul/charclass.h, fnmatch.c, glob.c:
+ Add character class support to included glob(3) and fnmatch(3).
+ [6b5b4ad77899]
+
+2008-09-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * emul/fnmatch.h:
+ Remove UCB advertising clause and some compatibility defines.
+ [2ade7bee74e1]
+
+2008-09-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo_edit.c:
+ Check EDITOR/VISUAL to make sure sudoedit is not re-invoking itself
+ or sudo. This allows one to set EDITOR to sudoedit without getting
+ into an infinite loop of sudoedit running itself until the path gets
+ too big.
+ [aa49ab68f82d]
+
+ * def_data.c, def_data.h, def_data.in, defaults.c, sudo.c:
+ Add sudoers_locale Defaults option to override the default sudoers
+ locale of "C".
+ [0639886a35bf]
+
+2008-09-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Set locale to system default except for during sudoers parse.
+ [016dd2736728]
+
+2008-09-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * match.c:
+ Redo change in 1.34 to use pointer arithmetic.
+ [f9e7b63bb450]
+
+2008-09-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * match.c:
+ Fix a dereference (read) of a freed pointer. Reported by Patrick
+ Williams.
+ [69877b633753]
+
+2008-08-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Set locale to "C" to avoid interpretation issues with character
+ ranges in sudoers. May want to make the locale a sudoers option in
+ the future.
+ [098a95de1746]
+
+2008-08-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in:
+ we no longer use setproctitle
+ [c7f20fb747ea]
+
+ * sudo.h:
+ remove #if 1
+ [a368ee6816c6]
+
+ * LICENSE, mkstemp.c:
+ Use my replacement mkstemp() from the mktemp package.
+ [d07c2beb0f9e]
+
+2008-07-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * gram.c:
+ regen with yacc skeleton bug fixed
+ [24784571cbb8]
+
+ * sudoers.pod:
+ Remove duplicate "as root". From Martin Toft.
+ [97241acfee5e]
+
+2008-07-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pwutil.c, sudo.c, sudo.h, testsudoers.c:
+ Flesh out the fake passwd entry used for running commands as a uid
+ not listed in the passwd database. Fixes an issue with some PAM
+ modules.
+ [a6648227f3f2]
+
+2008-07-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Error out in -i mode if the user has no shell. This can happen when
+ running commands as a uid with no password entry.
+ [0c174bef36ff]
+
+2008-06-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * toke.c, toke.l:
+ Better fix for line continuation inside double quotes. Now accepts
+ whitespace between the backslash and the newline like the main
+ lexer.
+ [64efcdf86d31]
+
+2008-06-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * toke.c, toke.l:
+ Fix line continuation in strings. It was only being honored if
+ preceded by whitespace.
+ [96c21271a3e4]
+
+2008-06-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, logging.c:
+ Replace the double fork with a fork + daemonize.
+ [328505441e67]
+
+2008-06-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c, sudo.c:
+ The -i flag should imply env_reset. This got broken in sudo 1.6.9.
+ [3caedfeaec87]
+
+ * logging.c, sudo.c, sudo_edit.c, visudo.c:
+ Change how the mailer is waited for. Instead of having a SIGCHLD
+ handler, use the double fork trick to orphan the child that opens
+ the pipe to sendmail. Fixes a problem running su on some Linux
+ distros.
+ [b59ce60a393d]
+
+2008-06-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Fix configure test for dirfd() on Linux where DIR is opaque.
+ [b8f729cdfecc]
+
+2008-06-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * tgetpass.c:
+ Get rid of the QNX TCSAFLUSH -> TCSADRAIN hack. If QNX still has
+ this problem we'll need to revisit this again.
+ [c17fee8ad530]
+
+2008-06-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ Ignore SIGPIPE instead of blocking it when piping to the mailer. If
+ we only block the signal it may be delivered later when we unblock.
+ Also, there is no need to block SIGCHLD since we no longer do the
+ double fork. The normal SIGCHLD handler is sufficient.
+ [e94a49e992e5]
+
+2008-06-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Add description for NO_PAM_SESSION, from a redhat patch.
+ [b9e4c939ec09]
+
+2008-06-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.cat, sudo.man.in, sudo.pod:
+ Fix typos in -i usage
+ [2d7ce5de0235]
+
+2008-05-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Redo the test for dgettext() in a way that hopefully will work
+ around the libintl_dgettext() undefined problem.
+ [d27beb0cf85e]
+
+2008-05-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * schema.ActiveDirectory:
+ change filename in comment
+ [733da4ee9ac5]
+
+2008-05-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, README.LDAP, sudoers.ldap.cat, sudoers.ldap.man.in,
+ sudoers.ldap.pod:
+ Reference schema.ActiveDirectory
+ [d6aec537800e]
+
+2008-05-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * schema.OpenLDAP, schema.iPlanet:
+ Mark sudoRunAs as deprecated.
+ [00c50df807af]
+
+ * schema.ActiveDirectory:
+ add sudoRunAsUser and sudoRunAsGroup
+ [19bcce6f72fb]
+
+ * schema.ActiveDirectory:
+ Active Directory schema by Chantal Paradis and Eric Paquet
+ [06a09c92c6a5]
+
+2008-05-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ remove an XXX that was fixed
+ [b88038062fa2]
+
+ * ChangeLog:
+ sync
+ [8fc27c17270e]
+
+ * parse.c:
+ Initialize tags to UNSPEC instead of def_* in "sudo -l" mode. This
+ fixes a problem where the tag value printed was influenced by
+ defaults set in the first pass through the parser.
+ [588ccd630367]
+
+2008-05-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, sudo.psf:
+ No point in packaging the TODO file
+ [9590248fffe1]
+
+ * ChangeLog:
+ sync
+ [152acf4c6813]
+
+2008-05-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * WHATSNEW, def_data.c, def_data.h, def_data.in, env.c, sudo.c,
+ sudo.h, sudoers.cat, sudoers.man.in, sudoers.pod:
+ Add env_file Defaults option that is similar to /etc/environment on
+ some systems.
+ [1daf53d51e18]
+
+2008-05-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, README, TODO, WHATSNEW, sudo.cat, sudo.man.in,
+ sudoers.cat, sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.man.in,
+ version.h, visudo.cat, visudo.man.in:
+ change version to 1.7.0
+ [d41d126b9bd8]
+
+ * UPGRADE:
+ initial valgrind pass done
+ [c59c3876d8ca]
+
+2008-04-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ Fix typo/think in sudo_ldap_read_secret() when storing the secret.
+ [830d246c09b0]
+
+2008-04-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ define LDAPS_PORT if the system headers do not
+ [247b12325701]
+
+2008-04-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * gram.c, gram.y:
+ Fix another memory leak in init_parser().
+ [7bba47deba11]
+
+ * configure, configure.in:
+ There was a missing space before the ldap libs in SUDO_LIBS for some
+ configurations.
+ [7524cfc93759]
+
+ * alias.c, gram.c, gram.y, toke.c, toke.l:
+ Clean up some memory leaks pointed out by valgrind.
+ [a965866ece1a]
+
+2008-04-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ fix "sudo -s" broken by mode/flags breakout
+ [acffe984d408]
+
+ * configure, configure.in:
+ remove duplicate check for dgettext
+ [58145529133c]
+
+2008-04-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aix.c:
+ Fall back to default stanza if no user-specific limit is found.
+ [7b8cb29123ee]
+
+2008-04-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * snprintf.c:
+ include stdint.h if present
+ [f0ec38529306]
+
+ * snprintf.c:
+ Use LLONG_MAX, not the old QUAD_MAX
+ [01041ce508fb]
+
+2008-04-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.ldap.pod:
+ fix cut and pasto
+ [34240fdef5ab]
+
+2008-03-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pwutil.c:
+ Add #ifdef PURITY
+ [ce1b571ad526]
+
+2008-03-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/bsdauth.c:
+ remove useless cast
+ [494f8a862e1d]
+
+2008-03-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ChangeLog:
+ sync
+ [f5c97ffaabcc]
+
+ * TODO:
+ sync
+ [96ff1c44c182]
+
+ * sudo.h:
+ Split MODE_* defines into primary and flags.
+ [c02ee3027cb9]
+
+2008-03-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aix.c:
+ It turns out the logic for getting AIX limits is more convoluted
+ than I realized and differs depending on whether the soft and/or
+ hard limits are defined.
+ [cf8d3f85d395]
+
+2008-03-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, configure, configure.in:
+ Back out AIX-specific change to set the sudo_noexec path to the .a
+ file, we do really want to use the .so file. Since libtool doesn't
+ do that correctly, just install the .so file ourselves in the
+ Makefile.
+ [05c6f33177d9]
+
+ * install-sh:
+ If the file given to install is a path, only use the basename of the
+ file when building the destination path.
+ [695ba4e429ce]
+
+2008-03-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ parse_args() cleanup: Sort command line options in the getopt()
+ switch The -U option requires a parameter Normalize a few ISSET
+ calls Split mode into mode and flags and retire the now-obsolete
+ excl variable
+ [0d156835f861]
+
+ * WHATSNEW, check.c, sudo.c, sudo.cat, sudo.h, sudo.man.in, sudo.pod,
+ sudo_usage.h.in:
+ Add -n (non-interactive) flag.
+ [e3e50400d32d]
+
+ * sudo.c:
+ Move version printing, etc. into a separate function.
+ [18c91b476e2c]
+
+ * sudo.c:
+ Don't try to cleanup nsswitch if it has not been initialized.
+ [aeb1ca1b399d]
+
+2008-03-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ Block SIGPIPE in send_mail() so sudo is not killed by a problem
+ executing the mailer.
+ [f130e7924cca]
+
+2008-03-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ AIX shared libs end in .a, not .so.
+ [a5deb07020d8]
+
+2008-03-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ Preserve HOME by default too. Matches documentation and previous
+ behavior.
+ [c16f17f1047c]
+
+2008-03-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Use getopt() to parse the command line. We need to be able to
+ intersperse env variables and options yet still honor "--"" which
+ complicates things slightly.
+ [60f271ce5c16]
+
+2008-03-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ChangeLog:
+ sync
+ [685e67964eda]
+
+ * acsite.m4, configure, ltmain.sh:
+ update to libtool-1.5.26
+ [4c9a8c3d3b40]
+
+ * config.guess, config.sub:
+ update from libtool-1.5.26 distribution
+ [c6641aef2527]
+
+ * aix.c, sudo.h:
+ attempt to fix compilation errors on AIX
+ [edb13e5b2184]
+
+ * Makefile.in:
+ fix typo in last commit
+ [25ba7f7ceae4]
+
+ * Makefile.in:
+ Add WHATSNEW file to the distribution
+ [213f4115de8f]
+
+ * visudo.c:
+ use warningx instead of fprintf(stderr, ...)
+ [a3494b8ccb19]
+
+ * list.c:
+ add DEBUG to list2tq
+ [115d24a3000c]
+
+ * ChangeLog, TODO:
+ sync
+ [60e6f4d1fac0]
+
+ * WHATSNEW:
+ mention mailfrom
+ [e2498f9e18d6]
+
+ * Makefile.in, aix.c, config.h.in, configure, configure.in,
+ set_perms.c, sudo.h:
+ Add aix_setlimits() to set resource limits on AIX using a
+ combination of getuserattr() and setrlimit(). Currently untested.
+ [9b1441fd89ca]
+
+2008-03-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * def_data.c, def_data.h, def_data.in, logging.c, sudoers.cat,
+ sudoers.man.in, sudoers.pod:
+ Add mailfrom Defaults option that sets the value of the From: field
+ in the warning/error mail. If unset the login name of the invoking
+ user is used.
+ [029b9f05d3d9]
+
+ * defaults.c:
+ store a copy of _PATH_SUDO_ASKPASS in def_askpass that is freeable
+ [a90e407d5e00]
+
+ * gram.c, gram.y:
+ When adding a default, only call list2tq() once to do the list to tq
+ conversion. It is not legal to call list2tq multiple times on the
+ same list since list2tq consumes and modifies the list argument.
+ [fbc25d245c4a]
+
+ * sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.ldap.pod:
+ comment out XXXs for now
+ [595a1d43309d]
+
+ * WHATSNEW:
+ mention askpass
+ [b993e0837c22]
+
+2008-03-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Error out if both -A and -S are specified Error out if -A is
+ specified but no askpass is configured
+ [24f1df2638f6]
+
+ * configure, configure.in:
+ we are not going to ship a sudo-specific askpass
+ [61949e7a3943]
+
+2008-03-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.h:
+ fix definition of TGP_ASKPASS
+ [0447c57ba4c3]
+
+ * def_data.c, def_data.in:
+ make askpass boolean-capable
+ [e0885893a325]
+
+ * INSTALL:
+ document --with-askpass
+ [c76e15ba97cf]
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.ldap.cat,
+ sudoers.man.in, visudo.cat:
+ regen
+ [8d16242980b7]
+
+2008-03-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod, sudo_usage.h.in, sudoers.pod:
+ document -A and askpass
+ [02c07505a78c]
+
+ * auth/sudo_auth.c, check.c, configure, configure.in, def_data.c,
+ def_data.h, def_data.in, defaults.c, pathnames.h.in, sudo.c, sudo.h,
+ sudo_usage.h.in, tgetpass.c:
+ Add support for running a helper program to read the password when
+ no tty is present (or when specified with the -A flag). TODO: docs.
+ [05780f5f71fd]
+
+ * def_data.c, def_data.in:
+ add missing printf format to SELinux role and type strings
+ [2b32774715e7]
+
+2008-02-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, configure, configure.in:
+ Disable use of gss_krb5_ccache_name() by default and add
+ --enable-gss-krb5-ccache-name configure option to enable it. It seems
+ that gss_krb5_ccache_name() doesn't work properly with some
+ combinations of Heimdal and OpenLDAP.
+ [f61ebd3b19bd]
+
+2008-02-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * selinux.c:
+ Ignore setexeccon() failing in permissive mode. Also add a call to
+ setkeycreatecon() (though this is probably insufficient). From Dan
+ Walsh.
+ [52564fc1c069]
+
+ * auth/pam.c:
+ Only set std_prompt for the PAM_PROMPT_* cases. The conversation
+ function may be called for non-password reading purposes so we must
+ be careful not to use def_prompt in cases where it may not be set.
+ [29d88ca575ba]
+
+2008-02-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * selinux.c:
+ Don't free the new tty context, we need to keep it around when we
+ restore the tty context after the command completes
+ [5b4bd39b6ea8]
+
+2008-02-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * selinux.c:
+ s/newrole/sudo/
+ [21b8a96ff8df]
+
+ * sudo.man.pl, sudo.pod:
+ Only put login_cap(3) in SEE ALSO section if we have login.conf
+ support
+ [05250ddff2c0]
+
+2008-02-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.ldap.cat,
+ sudoers.ldap.man.in, sudoers.man.in, visudo.cat, visudo.man.in:
+ regen
+ [301e5c5ccdbe]
+
+ * Makefile.in, configure, configure.in:
+ Substitute in comment characters for lines partaining to login.conf,
+ BSD auth and SELinux and only enable them if pertinent.
+ [9a02bd6a6658]
+
+ * sudo.man.pl:
+ Substitute in comment characters for lines partaining to login.conf,
+ BSD auth and SELinux and only enable them if pertinent.
+ [0c56d4750ac3]
+
+ * sudo.pod:
+ Substitute in comment characters for lines partaining to login.conf,
+ BSD auth and SELinux and only enable them if pertinent.
+ [acdbdfd24e1d]
+
+ * sudoers.man.pl:
+ Substitute in comment characters for lines partaining to login.conf,
+ BSD auth and SELinux and only enable them if pertinent.
+ [6c88f30b878a]
+
+ * sudoers.pod:
+ Substitute in comment characters for lines partaining to login.conf,
+ BSD auth and SELinux and only enable them if pertinent.
+ [c1c98fa163ce]
+
+ * Makefile.in, sudo.pod, sudoers.ldap.pod, sudoers.pod, visudo.pod:
+ Remove the =cut on the first line (above the copyright notice) to
+ quiet pod2man. Also remove the hackery in the FILES section and just
+ deal with the fact that there will a newline between each pathname.
+ [2ac1ab191835]
+
+2008-02-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ run sudo.man.pl when generating sudo.man.in
+ [859727369168]
+
+ * configure, configure.in, sudo.man.pl:
+ comment out SELinux manual bits unless --with-selinux was specified
+ [97ff4212b649]
+
+ * sudoers.pod:
+ document role and type defaults for SELinux
+ [870f303366b3]
+
+ * sudo.c, sudo.cat, sudo.man.in, sudo.pod, sudo_usage.h.in:
+ Document "sudo -ll" and make "sudo -l -l" be equivalent.
+ [3ce6dc429ea3]
+
+2008-02-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Treat k*bsd*-gnu like Linux, not BSD. Fixes compilation problems on
+ Debian GNU/kFreeBSD.
+ [c4efa567a328]
+
+2008-02-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/kerb5.c:
+ Avoid Heimdal'isms introduced in the rev 1.32 rewrite of
+ verify_krb_v5_tgt()
+ [f80538e5a6fa]
+
+ * logging.c, logging.h, sudo.c:
+ Remove dependence on VALIDATE_NOT_OK in logging functions. Split
+ log_auth() into log_allowed() and log_denial() Replace mail_auth()
+ with should_mail() and a call to send_mail()
+ [58aac9997557]
+
+2008-02-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ Add debugging so we can tell if the krb5 ccache is accessible
+ [c679322527bb]
+
+ * INSTALL:
+ mention --with-selinux
+ [9efbe0b52194]
+
+2008-02-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [467a834f867c]
+
+ * selinux.c:
+ add Sudo tag
+ [d004ee669bed]
+
+ * sudo.c, sudo.cat, sudo.h, sudo.man.in, sudo.pod, sudo_usage.h.in,
+ sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.ldap.pod,
+ testsudoers.c, toke.c, toke.l:
+ Add support for SELinux RBAC. Sudoers entries may specify a role and
+ type. There are also role and type defaults that may be used. To
+ make sure a transition occurs, when using RBAC commands are executed
+ via the new sesh binary. Based on initial changes from Dan Walsh.
+ [1d4abfe2c004]
+
+ * Makefile.in, config.h.in, configure.in, def_data.c, def_data.h,
+ def_data.in, gram.c, gram.h, gram.y, ldap.c, parse.c, parse.h,
+ pathnames.h.in, selinux.c:
+ Add support for SELinux RBAC. Sudoers entries may specify a role and
+ type. There are also role and type defaults that may be used. To
+ make sure a transition occurs, when using RBAC commands are executed
+ via the new sesh binary. Based on initial changes from Dan Walsh.
+ [6b421948286e]
+
+ * sesh.c:
+ Add support for SELinux RBAC. Sudoers entries may specify a role and
+ type. There are also role and type defaults that may be used. To
+ make sure a transition occurs, when using RBAC commands are executed
+ via the new sesh binary. Based on initial changes from Dan Walsh.
+ [1e3b395ce049]
+
+2008-02-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lbuf.c, ldap.c, parse.c, sudo.c, sudo.h, sudo_nss.c:
+ Add long list (sudo -ll) support for printing verbose LDAP and
+ sudoers file entries. Still need to update manual.
+ [2875be37935c]
+
+2008-02-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c, parse.c, sudo.h, sudo_nss.c, sudo_nss.h:
+ Unify the -l output for file and ldap based sudoers and use lbufs
+ for both. The ldap output does not currently include options that
+ cannot be represented as tags. This will be remedied in a long list
+ output mode to come.
+ [b2e429456596]
+
+2008-01-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * set_perms.c:
+ Use a specific error message for errno == EAGAIN when setuid() et al
+ fails. On Linux systems setuid() will fail with errno set to EAGAIN
+ if changing to the new uid would result in a resource limit
+ violation.
+ [08d0aecd9f03]
+
+ * sudo.c:
+ Unlimit nproc on Linux systems where calling the setuid() family of
+ syscalls causes the nroc resource limit to be checked. The limits
+ will be reset by pam_limits.so when PAM is used. In the non-PAM case
+ the nproc limit will remain unlimited but there doesn't seem to be a
+ way around that other than having sudo parse
+ /etc/security/limits.conf directly.
+ [df024b415a8d]
+
+ * env.c, sudo.c, sudo.pod:
+ Only read /etc/environment on Linux and AIX
+ [90669e2aefdb]
+
+2008-01-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Use SUDO_DEFINE_UNQUOTED instead of AC_DEFINE_UNQUOTED to prevent
+ ldap.conf and ldap.secret paths from going into config.h. Avoid
+ single quotes in variable expansion when using SUDO_DEFINE_UNQUOTED
+ since in some versions of bash they will end up literally in the
+ resulting define.
+ [25390f3ef10a]
+
+2008-01-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * README.LDAP:
+ mention --with-nsswitch=no
+ [c509df927263]
+
+ * configure, configure.in:
+ ldap_ssl.h depends on ldap.h being included first
+ [d96d90e9b21f]
+
+ * config.h.in, configure, configure.in, ldap.c:
+ Include ldap_ssl.h if we can find it. Needed for the
+ ldapssl_set_strength defines on HP-UX at least.
+ [9e530470948a]
+
+ * sudoers.ldap.pod:
+ sync
+ [b9d101f4673a]
+
+ * TODO:
+ sync
+ [2ce951b2ecd0]
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.ldap.cat,
+ sudoers.ldap.man.in, sudoers.man.in, visudo.cat, visudo.man.in:
+ regen
+ [b61d793987e0]
+
+ * Makefile.in:
+ Use 78n line length when formatting cat pages.
+ [761bee9d5759]
+
+ * README.LDAP:
+ Remove redundant info that is now in sudoers.ldap.pod
+ [01828dcce59e]
+
+2008-01-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.ldap.pod:
+ Reorganize the first section a bit. Substitute the proper path for
+ /etc/sudoers.
+ [11ae165e065d]
+
+ * sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.ldap.pod:
+ Substitute values for ldap.conf, ldap.secret and nsswitch.conf Move
+ schema into EXAMPLES
+ [ab6509d1dde7]
+
+ * configure, configure.in:
+ Substitute values for ldap.conf, ldap.secret and nsswitch.conf into
+ sudoers.ldap.man.
+ [6e689972f465]
+
+ * configure, configure.in:
+ substitute for sudoers.ldap.man
+ [5a4a25766dee]
+
+ * Makefile.in:
+ Fix cut & pasto introduced when adding sudoers.ldap man page.
+ [a7b069af8894]
+
+ * sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.ldap.pod:
+ Fill in some of the missing pieces. Still needs some reorganization
+ and editing.
+ [5e7331722166]
+
+2008-01-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, sudoers.ldap.cat, sudoers.ldap.man.in,
+ sudoers.ldap.pod:
+ Beginnings of a sudoers.ldap man page. Currently, much of the
+ information is adapted from README.LDAP.
+ [aad28c8a922d]
+
+2008-01-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pwutil.c:
+ When copying gr_mem we must guarantee that the storage space for
+ gr_mem is properly aligned. The simplest way to do this is to simply
+ store gr_mem directly after struct group. This is not a problem for
+ gr_passwd or gr_name as they are simple strings.
+ [af58fc76f1ed]
+
+ * ldap.c:
+ Fix a typo/thinko in one of the calls to
+ sudo_ldap_check_user_netgroup(). From Marco van Wieringen.
+ [70b2eb8097f5]
+
+2008-01-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, ldap.c:
+ include <mps/ldap_ssl.h> in ldap.c if available
+ [34346206ef16]
+
+2008-01-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * gram.c, gram.y:
+ Make sure we define SIZE_MAX for yacc's skeleton.c
+ [d8a45c7a3c42]
+
+ * tgetpass.c:
+ Use TCSAFLUSH when restoring terminal settings (and echo) to
+ guarantee that any pending output is discarded
+ [549a184479e5]
+
+2008-01-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers:
+ no longer need to specify SETENV when user has sudo ALL
+ [3051b41f8032]
+
+ * testsudoers.c:
+ sync user_args size calculation with sudo.c Add -g group option,
+ renaming old -g to -G Add set_runasgr() and set_runaspw() and use
+ them
+ [0850325180f0]
+
+ * sudo.c, sudo.h:
+ Make set_runaspw static void
+ [5d44d7a340ce]
+
+ * testsudoers.c, visudo.c:
+ g/c set_runaspw stub
+ [79ebb5e2cc38]
+
+ * configure, configure.in:
+ Don't add -llber twice.
+ [4356d302eef4]
+
+2008-01-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ fix typo
+ [249cecc557e9]
+
+2008-01-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * gram.c:
+ regen
+ [2f94ea375b67]
+
+ * configure, configure.in:
+ Fix check that determines whether -llber is required.
+ [6afa99523379]
+
+ * README.LDAP, config.h.in, configure, configure.in, ldap.c:
+ For netscape-based LDAP, use ldapssl_set_strength() to implement the
+ checkpeer ldap.conf option.
+ [16ae24d73795]
+
+ * auth/kerb5.c:
+ Delay krb5_cc_initialize() until we actually need to use the cred
+ cache, which is what krb5_verify_user() does. Better cleanup on
+ failure.
+ [d12e5f1695b8]
+
+2008-01-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/kerb5.c:
+ Rewrite verify_krb_v5_tgt() based on what heimdal's
+ krb5_verify_user() does.
+ [05b5815f86c9]
+
+2008-01-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * gram.c:
+ The U suffix on constants is an ANSI feature
+ [c6dfce3167f1]
+
+ * configure, configure.in:
+ Add check for ber_set_option() in -llber
+ [43d0c0566074]
+
+2008-01-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * README.LDAP:
+ default if no nsswitch.conf is files only
+ [c13001d9c998]
+
+2008-01-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * README.LDAP:
+ don't tell people to mail aaron about LDAP stuff
+ [8165ec1ef0c6]
+
+ * README.LDAP:
+ timelimit and bind_timelimit
+ [44f74cbed167]
+
+ * ChangeLog:
+ sync
+ [aba1a0ab02bd]
+
+ * ldap.c:
+ Move ldap.secret reading into a separate function.
+ [1948acc9f7a4]
+
+ * check.c:
+ user_runas -> runas_pw
+ [334490fc2bae]
+
+2008-01-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TODO:
+ sync
+ [c7b165cc47c6]
+
+ * check.c, sudo.pod, sudoers.pod:
+ Add and document the %p escape in the password prompt. Based on a
+ patch from Patrick Schoenfeld.
+ [3972d4f31ffa]
+
+ * ldap.c:
+ Check strlcpy() return values.
+ [9b42f3ae8ff1]
+
+ * ldap.c:
+ refactor ldap binding code into sudo_ldap_bind_s()
+ [cb0c66a4d955]
+
+ * README.LDAP:
+ Make it clear that host and uri can take multiple parameters. URI is
+ now supported for more than just openldap nsswitch.conf does't
+ accept "compat"
+ [f610dea656d6]
+
+ * sudo.c:
+ comment cleanup and update (c) year
+ [6cd69c810ca5]
+
+ * parse.c, sudo_nss.c:
+ Move display_privs() and display_cmnd() from parse.c to sudo_nss.c.
+ This should make it possible to build an LDAP-only sudo binary.
+ [61c3f27066a0]
+
+ * ldap.c, parse.c, sudo.c, sudo.h, sudo_nss.h:
+ Improve chaining of multiple sudoers sources by passing in the
+ previous return value to the next in the chain
+ [2c0b722b1b2d]
+
+ * gram.y:
+ Free up parser data structures in sudo_file_close().
+ [2251531d4519]
+
+ * gram.c, parse.c:
+ Free up parser data structures in sudo_file_close().
+ [8371f130f401]
+
+ * ldap.c:
+ Parse uri ourself if no ldap_initialize() is present Use
+ ldap_create() instead of deprecated ldap_init() Use
+ ldap_sasl_bind_s() instead of deprecated ldap_simple_bind_s()
+ [85d3825b1953]
+
+ * config.h.in, configure, configure.in:
+ Add check for ldap_sasl_bind_s() Remove -DLDAP_DEPRECATED from
+ CFLAGS
+ [240524512bc5]
+
+2008-01-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in:
+ add check for ldap_create
+ [3089badd73b8]
+
+2008-01-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, ldap.c:
+ Add sudo_ldap_get_first_rdn() to return the first rdn of an entry's
+ dn using the mechanism appropriate for the LDAP SDK in use. Use
+ ldap_unbind_ext_s() instead of deprecated ldap_unbind_s(). Emulate
+ ldap_unbind_ext_s() and ldap_search_ext_s() for SDK's without them.
+ [6deeca3d00cc]
+
+ * lbuf.c:
+ include unistd.h
+ [8419ed0bae7f]
+
+ * config.h.in, configure.in:
+ fix typo in mtim_getnsec
+ [2d5f21230a60]
+
+2008-01-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in:
+ add check for st__tim in struct stat as used by SCO
+ [587060ea2a89]
+
+ * ldap.c:
+ use ldap_search_ext_s instead of deprecated ldap_search_s
+ [5fc44fe3b44c]
+
+ * Makefile.in, TODO, sudo.cat, sudo.man.in:
+ add sudo_nss.h to HDRS
+ [86f01a70ff29]
+
+ * ldap.c:
+ Replace deprecated ldap_explode_dn() with calls to ldap_str2dn() and
+ ldap_rdn2str().
+ [aa217002cfae]
+
+2008-01-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ Use ldap_get_values_len()/ldap_value_free_len() instead of the
+ deprecated ldap_get_values()/ldap_value_free().
+ [e22dceb85e57]
+
+ * ChangeLog:
+ sync
+ [adad27b36107]
+
+ * TODO:
+ sync
+ [c449eb47e0ef]
+
+ * gettime.c, sudo.c:
+ Remove some already fixed XXXs
+ [532788d0e6da]
+
+ * ldap.c:
+ Same return value as non-existent sudoers if LDAP was unable to
+ connect.
+ [5819810e8e4e]
+
+ * sudo.pod:
+ mention /etc/environment
+ [ea8e6102f853]
+
+ * README.LDAP, UPGRADE, WHATSNEW:
+ Update to reflect recent developments.
+ [ed1fb026fe77]
+
+ * sudo.c:
+ Print nsswitch.conf, ldap.conf and ldap.secret paths in -V output.
+ [55b68a58260d]
+
+ * ldap.c:
+ When building up a query don't list groups in the aux group vector
+ that are the same as the passwd file group. On most systems the
+ first gid in the group vector is the same as the passwd entry gid.
+ [4bb51e297e0d]
+
+ * env.c, ldap.c:
+ Define LDAPNOINIT before calling ldap_init(), etc. to disable user
+ ldaprc and system defaults that could affect how LDAP works.
+ [ce5036440db2]
+
+ * INSTALL, configure, configure.in, pathnames.h.in, sudo.c,
+ sudo_nss.c, sudo_nss.h:
+ Rename read_nss -> sudo_read_nss Add --with-nsswitch to allow users
+ to specify nsswitch.conf path or disable it. If --with-nsswitch=no
+ but --with-ldap, order is LDAP, then sudoers. Fix --with-ldap-conf-
+ file and --with-ldap-secret-file
+ [ea5d7704381f]
+
+ * parse.c:
+ Honor def_ignore_local_sudoers
+ [f38e1121fae1]
+
+2007-12-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ no longer need to check def_ignore_local_sudoers here
+ [fce2a72f96fb]
+
+ * parse.c:
+ Refactor group vector resetting into a function and also call it
+ from display_cmnd. Stop after the first sucessful match in
+ display_cmnd. Print a newline between each display_privs method.
+ [981b37b5adff]
+
+ * parse.c:
+ fix double free introduced in rev 1.218
+ [c574b02d8747]
+
+ * ldap.c:
+ belt and suspenders; zero out result after freeing it
+ [7732988d4620]
+
+ * env.c, fileops.c, ldap.c, sudo.h, sudo_nss.c:
+ Refactor line reading into a separate function, sudo_parseln(),
+ which removes comments, leading/trailing whitespace and newlines.
+ May want to rethink the use of sudo_parseln() for /etc/ldap.secret
+ [61d9068f0645]
+
+ * parse.c, sudo.c:
+ Make the inability to read the sudoers file a non-fatal error if
+ there are other sudoers sources available. sudoers_file_lookup now
+ returns "not OK" if sudoers was not present
+ [643babf597a8]
+
+ * ldap.c:
+ make it clear that the global options are from LDAP
+ [9ff950349463]
+
+ * logging.c:
+ allocate proper amount of space for error string
+ [8bebb7d46d19]
+
+ * sudo_nss.c, sudo_nss.h:
+ actual sudo nss code
+ [5bd7d52d7738]
+
+ * ldap.c, parse.c, sudo.c, sudo.h:
+ nss-ify display_privs and display_cmnd.
+ [cccfdd3253f2]
+
+ * defaults.c, parse.c, testsudoers.c, visudo.c:
+ move update_defaults() to parse.c
+ [ace144b958a9]
+
+ * Makefile.in, ldap.c, list.c, parse.c, parse.h, sudo.c, sudo.h:
+ Use nsswitch to hide some sudoers vs. ldap implementation details
+ and reduce the number of #ifdef LDAP TODO: fix display routines and
+ error handling
+ [6225edde89a6]
+
+2007-12-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, README.LDAP, ldap.c, pathnames.h.in, sudo.c, sudo.h:
+ First cut at nsswitch.conf support. Further reorganizaton and
+ related changes are forthcoming.
+ [717f59d0790b]
+
+2007-12-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c, pathnames.h.in, sudo.c, sudo.h:
+ Add support for reading and /etc/environment file. Still needs to be
+ documented and should probably only applies to OSes that have it
+ (AIX and Linux, maybe others).
+ [15d3edae27e4]
+
+ * ldap.c:
+ include limits.h
+ [e19875ef0f82]
+
+2007-12-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * WHATSNEW:
+ reword LDAP SASL
+ [7ec3c4ec31b5]
+
+2007-12-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TODO:
+ sync
+ [87c5a7aea7bf]
+
+ * README.LDAP:
+ Add an example sudoRole, clarify netscape vs. openldap a bit more
+ [6f96c0ca8107]
+
+ * README.LDAP:
+ Be clear on what is OpenLDAP vs. Netscape-derived
+ [a33c8314dec5]
+
+ * config.h.in, configure, configure.in, ldap.c:
+ Use ldapssl_init() for ldaps support instead of trying to do it
+ manually with ldap_init() + ldapssl_install_routines(). Use tls_cert
+ and tls_key for cert7.db and key3.db respectively. Don't print
+ debugging info for options that are not set. Add warning if
+ start_tls specified when not supported.
+ [abb62dc7e4a3]
+
+ * ldap.c:
+ fix compilation on solaris
+ [03d449684e80]
+
+ * Makefile.in:
+ add missing .h and .c files for missing lib objs
+ [8b37825bdfc7]
+
+2007-12-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ fix LDAP_OPT_NETWORK_TIMEOUT setting
+ [226eba89c0ad]
+
+ * ldap.c:
+ fix compilation on Solaris
+ [917d47639eb6]
+
+2007-12-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ fix typo
+ [009d5c81b225]
+
+ * README.LDAP:
+ try to clear up which variables are for OpenLDAP and which are for
+ netscape-derived SDKs
+ [f8d9823ee73c]
+
+ * config.h.in, configure, configure.in, ldap.c:
+ Add support for "ssl on" in both netscape and openldap flavors. Only
+ the OpenLDAP flavor has been tested.
+ [952745829ec5]
+
+ * logging.c, sudo.c, sudo.h:
+ Call cleanup() before exit in log_error() instead of calling
+ sudo_ldap_close() directly. ldap_conn can now be static to sudo.c
+ [da02d1b67a2c]
+
+ * sudo.c:
+ ld -> ldap_conn
+ [01afa6d927cc]
+
+2007-12-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c, sudo.c, sudo.h:
+ Better ldap cleanup.
+ [25b9abe2d617]
+
+ * ldap.c:
+ Distinguish between LDAP conf settings that are connection-specific
+ (which take an ld pointer) and those that are default settings
+ (which do not).
+ [d48dc6c9c3b4]
+
+2007-12-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ Improved warnings on error.
+ [c8dce7b4feb4]
+
+ * ldap.c:
+ Make ldap config table driven and set the config *after* we open the
+ connection.
+ [d9698b5a2681]
+
+2007-12-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ fix LDAP_OPT_X_CONNECT_TIMEOUT compat define
+ [598c6df06660]
+
+ * configure, configure.in:
+ some operating systems need to link with -lkrb5support when using
+ krb5
+ [8896365dde9e]
+
+2007-12-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * WHATSNEW:
+ minor update
+ [acfeeb7f4886]
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in:
+ regen
+ [a3c6699674f9]
+
+2007-12-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ChangeLog, TODO:
+ sync
+ [138e99b925ee]
+
+ * ldap.c, schema.OpenLDAP, schema.iPlanet, sudoers2ldif:
+ add -g support for LDAP
+ [8fc27dbe9287]
+
+2007-12-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * WHATSNEW, sudo.c, sudo.pod, sudo_usage.h.in:
+ The -i and -s flags can now take an optional command.
+ [6afec104ee77]
+
+2007-12-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/pam.c, def_data.c, def_data.h, def_data.in, sudo.c, sudo.pod,
+ sudoers.pod:
+ Add passprompt_override flag to sudoers that will cause the prompt
+ to be overridden in all cases. This flag is also set when the user
+ specifies the -p flag.
+ [e4c5402131a6]
+
+ * sudo.c:
+ Move setting of login class until after sudoers has been parsed. Set
+ NewArgv[0] for -i after runas_pw has been set.
+ [62a48c8c56fa]
+
+ * configure, configure.in:
+ Move the dgettext check.
+ [5fd8a4712d1c]
+
+2007-12-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/pam.c, config.h.in, configure, configure.in:
+ Add basic support for looking up the string "Password: " in the PAM
+ localized text db. This allows us to determine whether the PAM
+ prompt is the default "Password: " one even if it has been
+ localized.
+
+ TODO: concatenate non-std PAM prompts and user-specified sudo
+ prompts.
+ [81c25a415d41]
+
+2007-11-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, config.h.in, configure, configure.in, parse.c,
+ set_perms.c, sudo.c, sudo.h:
+ Use AC_FUNC_GETGROUPS instead of a home-grown attempt that was
+ insufficient.
+ [1cce6ec1a91e]
+
+ * acsite.m4, configure, interfaces.c, memrchr.c:
+ Fix typos; Martynas Venckus
+ [be1233cca11a]
+
+2007-11-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * set_perms.c:
+ Don't assume runas_pw is set; it may not be in the -g case.
+ [aa11bd2193ac]
+
+2007-11-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c, set_perms.c:
+ Set aux group vector for PERM_RUNAS and restore group vector for
+ PERM_ROOT if we previously changed it. Stash the runas group vector
+ so we don't have to call initgroups more than once. Also add no-op
+ check to check_perms.
+ [53837fc755f7]
+
+2007-11-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * WHATSNEW, check.c, def_data.in, defaults.c, gram.c, gram.h, gram.y,
+ ldap.c, logging.c, match.c, mon_systrace.c, parse.c, parse.h,
+ pwutil.c, set_perms.c, sudo.c, sudo.cat, sudo.h, sudo.man.in,
+ sudo.pod, sudo_usage.h.in, sudoers.cat, sudoers.man.in, sudoers.pod,
+ testsudoers.c, visudo.c, visudo.cat, visudo.man.in:
+ Add support for runas groups. This allows the user to run a command
+ with a different effective group. If the -g option is specified
+ without -u the command will be run as the current user (only the
+ group will change). the -g and -u options may be used together.
+ TODO: implement runas group for ldap improve runas group
+ documentation add testsudoers support
+ [9019309df6d0]
+
+ * configure, configure.in:
+ fix setting of mandir
+ [2c60f269399f]
+
+ * sudo.pod, sudoers.pod:
+ document that ALL implies SETENV
+ [bcc8e5b703b9]
+
+ * ldap.c:
+ s/setenv_ok/setenv_implied/g
+ [f005df2c2eea]
+
+ * ldap.c:
+ hostname_matches() returns TRUE on match in sudo 1.7.
+ [c3d4377b6e8b]
+
+ * ldap.c:
+ use strcmp, not strcasecmp when comparing ALL
+ [e486024574a1]
+
+ * ldap.c:
+ Make sudo ALL imply setenv. Note that unlike with file-based sudoers
+ this does affect all the commands in the sudoRole.
+ [bc12f54321d1]
+
+ * gram.c, gram.y, parse.c, parse.h:
+ sudo "ALL" now implies the SETENV tag but, unlike an explicit tag,
+ it is not passed on to other commands in the list.
+ [026e2cb40680]
+
+ * visudo.c:
+ Add missing sudo_setpwent() and sudo_setgrent() calls. Also use
+ sudo_getpwuid() instead of getpwuid().
+ [86f30a8fbd49]
+
+2007-11-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers:
+ Expand on the dangers of not using visudo to edit sudoers.
+ [e434e8057d02]
+
+2007-11-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ Don't quote *?[]! on output since the lexer does not strip off the
+ backslash when reading those in.
+ [561da4a13afa]
+
+2007-11-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * glob.c:
+ expand "u_foo" types to "unsigned foo" to avoid compatibility
+ issues.
+ [b0d7c64d78c3]
+
+2007-11-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ Refactor log line generation in to new_logline().
+ [6a9b9730615d]
+
+2007-10-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TROUBLESHOOTING:
+ fix typo
+ [9e19d4f86e47]
+
+2007-10-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, interfaces.c, interfaces.h,
+ match.c:
+ Add configure check for struct in6_addr instead of relying on
+ AF_INET6 since some systems define AF_INET6 but do not include IPv6
+ support.
+ [e24082c416bd]
+
+2007-10-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Fix block to add -lutil for FreeBSD and NetBSD when logincap is in
+ use.
+ [76a9df4a63be]
+
+2007-10-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ POSIX states that struct timespec be declared in time.h so check
+ there regardless of the value of TIME_WITH_SYS_TIME.
+ [e42c55ec9daf]
+
+2007-10-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * tgetpass.c:
+ Instead of defining a macro to call the appropriate method for
+ turning on/off echo, just define tc[gs]etattr() and the related
+ defines that use the correct terminal ioctls if needed. Also go back
+ to using TCSAFLUSH instead of TCSADRAIN on all but QNX.
+ [5dfb2379d995]
+
+2007-10-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ g/c @ALLOCA@
+ [e6946c2e3820]
+
+ * configure:
+ regen
+ [9bac7159a138]
+
+ * INSTALL, auth/pam.c, config.h.in, configure.in:
+ Add --disable-pam-session configure option to disable calling
+ pam_{open,close}_session. May work around bugs in some PAM
+ implementations.
+ [273d0fdb4a9d]
+
+2007-10-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * tgetpass.c:
+ quiet gcc warnings
+ [325565c5a579]
+
+ * tgetpass.c:
+ Avoid printing the prompt if we are already backgrounded. E.g. if
+ the user runs "sudo foo &" from the shell. In this case, the call to
+ tcsetattr() will cause SIGTTOU to be delivered.
+ [db2139a8d8b8]
+
+2007-09-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * def_data.c, def_data.h, def_data.in:
+ Reorder things such that the definition of env_reset come right
+ before the env variable lists.
+ [e0d8e22a581a]
+
+ * parse.h:
+ Shrink type and seqno in struct alias from int to u_short
+ [9425263dd565]
+
+ * alias.c, match.c, parse.c, parse.h:
+ Add a sequence number in the aliases for loop detection. If we find
+ an alias with the seqno already set to the current (global) value we
+ know we've visited it before so ignore it.
+ [301a0548ffff]
+
+2007-09-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TODO, auth/pam.c, sudo.c, sudo.h:
+ PAM wants the full tty path so add user_ttypath which holds the full
+ path to the tty or is NULL if no tty was present.
+ [c7c1dd4b36c8]
+
+ * auth/pam.c:
+ Set PAM_RHOST to work around a bug in Solaris 7 and lower that
+ results in a segv.
+ [3a8865b3a357]
+
+2007-09-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * gram.c:
+ regen
+ [5647be127950]
+
+ * alias.c, defaults.c, gram.y, list.c, list.h, match.c, parse.c,
+ parse.h, testsudoers.c, visudo.c:
+ rename lh_ -> tq_
+ [8f500c542c4a]
+
+2007-09-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * alloc.c:
+ remove some useless casts
+ [409a448b23f5]
+
+ * alloc.c:
+ pull in inttypes.h for SIZE_MAX; we avoid stdint.h since inttypes.h
+ predates the final C99 spec and the standard specifies that it shall
+ include stdint.h anyway
+ [ae478fdef61a]
+
+2007-09-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, alloca.c, configure.in:
+ Since we ship with a pre-generated parser there is no need to ship a
+ bogus alloca implementation.
+ [3f611a7cc0e5]
+
+ * configure:
+ regen
+ [771eccf5269c]
+
+ * configure.in:
+ remove initial setting of CHECKSIA, we require that it be unset if
+ not used
+ [a2e91adc5aa2]
+
+ * Makefile.in:
+ add list.c to SRCS
+ [7db0e56cf5b9]
+
+ * configure:
+ regen
+ [3716ec30172e]
+
+ * configure.in:
+ only do SIA checks on Digital Unix
+ [6a96e1af2597]
+
+2007-09-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.cat, sudoers.man.in:
+ regen
+ [ac1dc29de72b]
+
+ * ChangeLog, TODO:
+ sync
+ [781effce0a2d]
+
+ * auth/kerb5.c:
+ Remove call to krb5_cc_register() as it is not needed for modern
+ kerb5.
+ [351b8b764f16]
+
+ * configure:
+ regen
+ [ac21dbcc9c2c]
+
+ * aclocal.m4, configure.in:
+ New method for setting the default authentication type and avoiding
+ conflicts in auth types.
+ [5fb15be11f78]
+
+ * match.c, parse.c, testsudoers.c:
+ Each entry in a cmndlist now has an associated runaslist so no need
+ to keep track of the most recent non-NULL one.
+ [582e015786b0]
+
+2007-09-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ back out partial ldaps support mistakenly committed
+ [357703e94b2d]
+
+ * ldap.c:
+ Add support for unix groups and netgroups in sudoRunas
+ [2f04eb91c6d0]
+
+2007-09-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo_edit.c:
+ Fix sudoedit of a non-existent file. From Tilo Stritzky.
+ [a5488a03bddd]
+
+2007-09-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [541177376ee1]
+
+ * INSTALL:
+ update --passprompt escape info
+ [6d57db4cd538]
+
+ * configure.in:
+ remove now-bogus comment and update copyright date
+ [6a4af45fa331]
+
+ * configure.in:
+ Fix up use of with_passwd
+ [7c79d8640f77]
+
+ * acsite.m4, config.guess, config.sub, configure.in, ltmain.sh:
+ Update to autoconf-2.61 andf libtool-1.5.24
+ [045259b0b439]
+
+ * Makefile.in:
+ "cmp -s" not just cmp Add @datarootdir@ to quiet autoconf-2.61
+ [f5b6a7afb817]
+
+2007-09-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * gram.c:
+ regen
+ [b5b78e71d2cb]
+
+ * gram.y:
+ move tags and runaslist propagation to be earlier
+ [94f7805f4489]
+
+ * visudo.c:
+ If -f flag given use the permissions of the original file as a
+ template
+ [9303d22bddb0]
+
+ * gram.y:
+ prevent a double free() when re-initing the parser
+ [5b3907c4de5a]
+
+2007-08-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [49a90b19a17d]
+
+ * aclocal.m4, alias.c, alloc.c, auth/API, auth/afs.c, auth/bsdauth.c,
+ auth/kerb4.c, auth/kerb5.c, auth/pam.c, auth/securid.c,
+ auth/securid5.c, auth/sia.c, auth/sudo_auth.h, config.h.in,
+ configure.in, env.c, ldap.c, list.c, list.h, memrchr.c, parse.c,
+ parse.h, pwutil.c, redblack.c, redblack.h, snprintf.c, sudo.c,
+ sudo.h, testsudoers.c, visudo.c, zero_bytes.c:
+ Remove support for compilers that don't support void *
+ [35e1d01ae197]
+
+ * gram.c:
+ regen
+ [70ce412a458a]
+
+ * Makefile.in, alias.c, defaults.c, gram.y, list.c, list.h, match.c,
+ parse.c, parse.h, testsudoers.c, visudo.c:
+ Move list manipulation macros to list.h and create C versions of the
+ more complex ones in list.c. The names have been down-cased so they
+ appear more like normal functions.
+ [9cea0e281148]
+
+ * Makefile.in:
+ Fix cmp command when regenerating parser. Make gram.o the first
+ dependency for all programs so gram.h will be generated before
+ anything that needs it.
+ [429ea065abf1]
+
+ * gram.y, parse.h:
+ Convert NEW_DEFAULT anf NEW_MEMBER into static functions.
+ [2f3433833589]
+
+ * match.c, parse.c, testsudoers.c:
+ Use LH_FOREACH_REV when checking permission and short-circuit on the
+ first non-UNSPEC hit we get for the command. This means that instead
+ of cycling through the all the parsed sudoers entries we start at
+ the end and work backwards and quit after the first positive or
+ negative match.
+ [881474532f3e]
+
+ * gram.c:
+ regen
+ [9152a19d4188]
+
+ * defaults.c, gram.y, parse.c, parse.h, testsudoers.c, visudo.c:
+ Change list head macros to take a pointer, not a struct.
+ [054f1dcce4cc]
+
+ * gram.c:
+ regen
+ [be154aae6235]
+
+ * gram.y:
+ Propagate the runasspec from one command to the next in a cmndspec.
+ [4957b1cb03a3]
+
+2007-08-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * match.c:
+ Replace has_meta() with a macro that calls strpbrk().
+ [a2e58846a542]
+
+ * regen
+ [5a932a5c9451]
+
+ * alias.c, defaults.c, gram.y, match.c, parse.c, parse.h,
+ testsudoers.c, visudo.c:
+ Use a list head struct when storing the semi-circular lists and
+ convert to tail queues in the process. This will allow us to reverse
+ foreach loops more easily and it makes it clearer which functions
+ expect a list as opposed to a single member.
+
+ Add macros for manipulating lists. Some of these should become
+ functions.
+
+ When freeing up a list, just pop off the last item in the queue
+ instead of going from head to tail. This is simpler since we don't
+ have to stash a pointer to the next member, we always just use the
+ last one in the queue until the queue is empty.
+
+ Rename match functions that take a list to have list in the name.
+ Break cmnd_matches() into cmnd_matches() and cmndlist_matches.
+ [7c37b271607a]
+
+ * parse.c:
+ Fix pasto, append "!" not negated (which is an int) for sudo -l
+ output.
+ [93a444c3997f]
+
+ * Makefile.in:
+ Remove the dependency of gram .h on gram.y, the .c dependency is
+ enough. Only move y.tab.h to gram.h if it is different; avoids
+ needless rebuilding.
+ [67bf4ea2a2e5]
+
+2007-08-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ Defaults lines may be associated with lists of users, hosts,
+ commands and runas users, not just single entries.
+ [795effacb6be]
+
+2007-08-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ Revert the "cmp" portion of the last diff, it doesn't make sense.
+ [26f34bf4e2e3]
+
+ * Makefile.in:
+ Remove *.lo for clean: When generating the parser, only move the
+ generated files into place if they differ from the existing ones.
+ [84673fea371b]
+
+2007-08-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * toke.c, toke.l:
+ Replace IPV6 regexp with a much simpler (readable) one and add an
+ extra check when it matches to make sure we have a valid address.
+ [592e9f690556]
+
+ * match.c:
+ Fix thinko introduced when merging IPV6 support.
+ [da38cd5eb8c7]
+
+2007-08-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * HISTORY, LICENSE:
+ regen
+ [0d7b27b90634]
+
+ * license.pod:
+ add 2007
+ [510e5048ae1a]
+
+ * UPGRADE:
+ mention #uid vs. comment pitfall
+ [4d2861898bcc]
+
+ * acsite.m4:
+ Merge in a patch from the libtool cvs that fixes a problem with the
+ latest autoconf. From Stepan Kasal.
+ [0c279ae7df3e]
+
+ * parse.h:
+ Back out he XOR swap trick, it is slower than a temp variable on
+ modern CPUs.
+ [91c4b024e317]
+
+ * gram.c:
+ regen
+ [cb6d4106fb74]
+
+ * gram.y, parse.h:
+ Convert the tail queue to a semi-circle queue and use the XOR swap
+ trick to swap the prev pointers during append.
+ [8bf4d9fbee58]
+
+2007-08-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.h:
+ remove useless statement
+ [421ec1dd73e6]
+
+ * toke.c, toke.l:
+ Refactor #include parsing into a separate function and return
+ unparsed chars (such as newline or comment) back to the lexer.
+ [64166917aa3d]
+
+2007-08-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * WHATSNEW:
+ mention better uid support
+ [56f510e7f2ec]
+
+ * sudoers.pod:
+ Users may now consist of a uid.
+ [5fd31b2c55ed]
+
+ * gram.c, gram.h, toke.c:
+ regen
+ [599e58af6dc1]
+
+ * parse.c:
+ Use lbuf_append_quoted() for sudo -l output to quote characters that
+ would require quoting in sudoers.
+ [3132d05c990a]
+
+ * lbuf.c, lbuf.h:
+ Add lbuf_append_quoted() which takes a set of characters which
+ should be quoted with a backslash when displayed.
+ [ab09bebb1d65]
+
+ * toke.l:
+ Require that the first character after a comment not be a digit or a
+ dash. This allows us to remove the GOTRUNAS state and treat uid/gids
+ similar to other words. It also means that we can now specify uids
+ in User_Lists and a User_Spec may now contain a uid.
+ [461fe01f8392]
+
+ * gram.y, toke.l:
+ Replace RUNAS token with '(' and ')' tokens to make the runas
+ portion of the grammar more natural.
+ [e0c383b4684d]
+
+ * BUGS:
+ The BUGS file is history
+ [4d9a809585c7]
+
+ * Makefile.in, README:
+ The BUGS file is history
+ [d9500e261172]
+
+2007-08-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * toke.c, toke.l:
+ Allow comments after a RunasAlias as long as the character after the
+ pound sign isn't a digit or a dash.
+ [d7f3bd94eeda]
+
+ * WHATSNEW:
+ Glob support was back-ported to 1.6.9
+ [d1d5cfd46228]
+
+2007-08-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ remove sudo_usage.h in distclean
+ [df05ce9c4127]
+
+ * parse.c:
+ If a Defaults value contains a blank, double-quote the string.
+ [9057a910daad]
+
+ * toke.c, toke.l:
+ Properly deal with Defaults double-quoted strings that span multiple
+ lines using the line continuation char. Previously, the entire
+ thing, including the continuation char, newline, and spaces was
+ stored as-is.
+ [4a4e8eacefe6]
+
+ * sudo.c:
+ Be consistent when using single quotes and backticks.
+ [d010b83a0fa1]
+
+2007-08-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, configure, configure.in, lbuf.c, lbuf.h, parse.c,
+ sudo.c, sudo_usage.h.in:
+ Add new linebuf code to do appends of dynamically allocated strings
+ and word-wrapped output. Currently used for sudo's usage() and sudo
+ -l output. Sudo usage strings are now in sudo_usage.h which is
+ generated at configure time.
+ [4dfd0ee8d961]
+
+2007-08-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c, sudo.c, sudo.h:
+ Fix line wrapping in usage() and use the actual tty width instead of
+ assuming 80.
+ [700eab37c5a6]
+
+2007-08-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * history.pod:
+ some more info
+ [8140112a8ae1]
+
+ * history.pod:
+ Mentioned Chris Jepeway's parser and also the new one that is in
+ sudo 1.7.
+ [2132d00f0597]
+
+2007-08-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod, visudo.pod:
+ For the options list, add flag args where appropriate and increase
+ the indent level so there is room for them.
+ [2b60fb572e12]
+
+2007-08-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ Fix some spacing in "sudo -l" and add a comment about some bogosity
+ in the line wrapping.
+ [b59b056f5ee2]
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat,
+ visudo.man.in:
+ regen
+ [5fb719f18ebc]
+
+ * INSTALL, Makefile.in, WHATSNEW, config.h.in, configure.in,
+ def_data.c, def_data.h, def_data.in, gram.c, gram.h, gram.y,
+ parse.c, parse.h, pathnames.h.in, sudo.c, sudo.h, sudoers.pod,
+ testsudoers.c, toke.c, toke.l:
+ Remove monitor support until there is a versino of systrace that
+ uses a lookaside buffer (or we have a better mechanism to use).
+ [61ff76878e4a]
+
+ * config.h.in, configure, configure.in, sudo.c:
+ use getaddrinfo() instead of gethostbyname() if it is available
+ [cc33c136aa6a]
+
+2007-08-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c, sudo.c:
+ Deal with OSes where sizeof(gid_t) < sizeof(int).
+ [130a89cbdfba]
+
+ * interfaces.c:
+ repair non-getifaddrs() code after ipv6 integration
+ [7ae7a89e2236]
+
+ * sudo.c:
+ If we can open sudoers but fail to read the first byte, close the
+ file stream before trying again.
+ [6f31272fae7b]
+
+2007-08-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * toke.c:
+ regen
+ [4d7afe0aa6fa]
+
+ * gram.y, interfaces.c, interfaces.h, match.c, sudoers.pod, toke.l:
+ Add IPv6 support; adapted from patches by YOSHIFUJI Hideaki
+ [4e6ff2965a42]
+
+ * sudo.pod, sudoers.pod, visudo.pod:
+ Add some missing markup Update copyright
+ [7e6d3c686b5e]
+
+2007-08-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ fix sudo_noexec extension which got broken in the libtool update
+ [3a5b447df861]
+
+2007-08-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ explicitly specify -Tascii to nroff
+ [45c8da4cbefe]
+
+2007-08-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ remove an ANSI-ism that crept in
+ [29086f87b2ca]
+
+2007-08-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod:
+ Adjust list indents Prevent -- from being turned into an em dash Use
+ a list for the environment instead of a literal paragraph
+ [c3abcd8f76f4]
+
+ * visudo.pod:
+ Use a list for the environment instead of an indented literal
+ paragraph.
+ [0ffcfcb7349f]
+
+ * sudoers.pod:
+ Adjust list indentation
+ [615c89e3123a]
+
+ * license.pod:
+ add =head3
+ [8b2e0d38c0bd]
+
+2007-08-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod:
+ mention that when specifying a uid for the -u option the shell may
+ require that the # be escaped
+ [3e3a17bff150]
+
+2007-08-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * match.c:
+ Fix off by one in group matching.
+ [b529602b7fba]
+
+2007-07-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ Fix typo: PYTHONINSPEC should be PYTHONINSPECT. From David Krause.
+ [ffbf8907c6e7]
+
+2007-07-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Add missing define of HAVE_GSS_KRB5_CCACHE_NAME for the
+ -lgssapi_krb5 case.
+ [2b85a89c2252]
+
+ * aclocal.m4, configure, configure.in:
+ Fix link tests such that new gcc doesn't optimize away the test.
+ [83484ec95cba]
+
+2007-07-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod, sudoers.pod, visudo.pod:
+ add missing over/back
+ [251a12c89b91]
+
+ * sudo.pod, sudoers.pod, visudo.pod:
+ Change FILES section to use =item
+ [60b9efc3a0b2]
+
+ * env.c:
+ Add back allocation of the env struct in rebuild_env but save a copy
+ of the old pointer and free it before returning.
+ [1100cd4fa997]
+
+ * env.c:
+ Don't init the private environment in rebuild_env() since it may
+ have already been done implicitly sudo_setenv/sudo_unsetenv.
+
+ Multiply length by sizeof(char *) in memcpy/memmove when copying the
+ environment so we copy the full thing.
+
+ Add missing set of parens so we deref the right pointer in
+ sudo_unsetenv when searching for a matching variable.
+ [9086a8f756b1]
+
+2007-07-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod, sudoers.pod, visudo.pod:
+ Use file markup for paths in the FILES section
+ [940d99f731f2]
+
+ * sudo.pod, sudoers.pod, visudo.pod:
+ Don't capitalize sudo/visudo
+ [f067a455d44b]
+
+ * sudoers.pod:
+ Sort sudoers options; based on a diff from Igor Sobrado.
+ [a9b9befe85ac]
+
+2007-07-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod, sudoers.pod, visudo.pod:
+ Use 8 and 5 instead of @mansectsu@ and @mansectform@ since the
+ latter confuses pod2man. The Makefile rules for the .man.in file
+ will add @mansectsu@ and @mansectform@ back in after pod2man is done
+ anyway.
+ [b50ea0db727c]
+
+2007-07-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * LICENSE, Makefile.in, license.pod:
+ Move license info to pod format
+ [25bdd82e592b]
+
+ * configure, configure.in, sudoers.pod:
+ Substitute value of path_info into sudoers man page.
+ [9ba661a82798]
+
+ * WHATSNEW:
+ remove features that were back-ported to 1.6.9
+ [e76d756cbe65]
+
+ * sudo.c, sudo.pod, visudo.c, visudo.pod:
+ Sort SYNOPSIS and sync usage. From Igor Sobrado.
+ [4970386c9e54]
+
+ * env.c:
+ Only need sudo_setenv/sudo_unsetenv if we are going to use
+ ldap_sasl_interactive_bind_s() but don't have
+ gss_krb5_ccache_name().
+ [f1a73d8b35c5]
+
+ * ChangeLog:
+ rebuild without branch info
+ [5d5a33494677]
+
+ * Makefile.in:
+ Add ChangeLog target
+ [a702034fdd89]
+
+ * auth/pam.c:
+ Run cleanup code if the user hits ^C at the password prompt.
+ [9cf87768e921]
+
+ * auth/pam.c:
+ Some versions of pam_lastlog have a bug that will cause a crash if
+ PAM_TTY is not set so if there is no tty, set PAM_TTY to the empty
+ string.
+ [5b63f6c88866]
+
+2007-07-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ ChageLog not Changelog
+ [1243d8473ceb]
+
+ * ChangeLog:
+ sync
+ [d887df98c6b0]
+
+ * Makefile.in:
+ CHANGE -> Changelog
+ [917738df30dd]
+
+ * TODO:
+ sync
+ [cd382f7d1948]
+
+2007-07-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, ldap.c:
+ Add configure hooks for gss_krb5_ccache_name() and the gssapi
+ headers.
+ [139606209991]
+
+2007-07-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c, sudo.c:
+ rebuild_env() and insert_env_vars() no longer return environment
+ pointer, they set environ directly.
+
+ No longer need to pass around an envp pointer since we just operate
+ on environ now.
+
+ Add dosync argument to insert_env() that indicates whether it should
+ reset environ when realloc()ing env.envp.
+
+ Use an initial size of 128 for the environment.
+ [4735fd5fddb8]
+
+ * env.c:
+ Split sudo_setenv() into an external version and a version only for
+ use by rebuild_env().
+ [fda7d655adb1]
+
+2007-07-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ Add support for using gss_krb5_ccache_name() instead of setting
+ KRB5CCNAME. Also use sudo_unsetenv() in the non-
+ gss_krb5_ccache_name() case if there was no KRB5CCNAME in the
+ original environment. TODO: configure setup for
+ gss_krb5_ccache_name()
+ [fcafa5a49caf]
+
+ * README.LDAP:
+ add krb5_ccname
+ [fceb8f883886]
+
+ * README.LDAP, ldap.c:
+ Add support for sasl_secprops in ldap.conf
+ [1f06f4bf7347]
+
+ * env.c, sudo.h:
+ Add sudo_unsetenv() and refactor private env syncing code into
+ sync_env().
+ [045ecb3fd22b]
+
+ * README.LDAP, ldap.c:
+ The ldap.conf variable is sasl_auth_id not sasl_authid.
+ [a5f98491311b]
+
+2007-07-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c, sudo.c, sudo.h:
+ Add support for krb5_ccname in ldap.conf. If specified, it will
+ override the default value of KRB5CCNAME in the environment for the
+ duration of the call to ldap_sasl_interactive_bind_s().
+ [b08a10c3045b]
+
+ * env.c, sudo.h:
+ Remove format_env() Add sudo_setenv() to replace most format_env() +
+ insert_env() combinations. insert_env() no longer takes a struct
+ environment *
+ [131da52f43f3]
+
+ * ldap.c:
+ Fix use_sasl vs. rootuse_sasl logic.
+ [0c0417b6918c]
+
+ * README.LDAP, config.h.in, configure, configure.in, ldap.c:
+ Add support for SASL auth when connecting to an LDAP server. Adapted
+ from a diff by Tom McLaughlin.
+ [a6285f1356ea]
+
+2007-07-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Only enable AIX or BSD auth if no other exclusive auth method has
+ been chosen. Allows people to e.g., use PAM on AIX without adding
+ --without-aixauth. A better solution is needed to deal with default
+ authentication since if a non-exclusive method is chosen we will
+ still get an error.
+ [83f7afdc0ec3]
+
+2007-07-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * HISTORY, Makefile.in, history.pod:
+ Generate HISTORY from history.pod (which is also used for web pages)
+ [60bcd5164931]
+
+2007-07-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.man.in, sudoers.man.in:
+ regen
+ [63956a366191]
+
+ * sudo.pod:
+ Better explanation of environment handling in the sudo man page.
+ [6c247742f7ee]
+
+ * env.c, sudo.c:
+ Defer setting user-specified env vars until after authentication.
+ [4750b79323ee]
+
+ * env.c:
+ honor def_default_path for PATH set on the command line
+ [6db31d9b6d65]
+
+ * env.c, sudo.c, sudo.pod, sudoers.pod:
+ Allow user to set environment variables on the command line as long
+ as they are allowed by env_keep and env_check. Ie: apply the same
+ restrictions as normal environment variables. TODO: deal with
+ secure_path
+ [26c0da3840cf]
+
+2007-07-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c, sudo_edit.c:
+ Call rebuild_env() in call cases. Pass original envp to sudo_edit().
+ Don't allow -E or env var setting in sudoedit mode. More accurate
+ usage() when called as sudoedit.
+ [a4af20658361]
+
+ * ldap.c:
+ warn -> warning
+ [d87d1192b048]
+
+ * sudo.pod:
+ add -c option to sudoedit synopsis
+ [15b596a7e2db]
+
+ * TODO:
+ udpate to reality
+ [e2f8fde89db1]
+
+ * parse.c:
+ Use ALLOW/DENY instead of TRUE/FALSE when dealing with the return
+ value from {user,host,runas,cmnd}_matches(). Rename *matches
+ variables -> *match. Purely cosmetic.
+ [e54a44c00a88]
+
+ * parse.c:
+ Move setting of FLAG_NO_CHECK into the if(pwflag) block. No change
+ in behavior.
+ [c6272b4f2127]
+
+ * sudoers:
+ add SETENV tag
+ [3a3066bb6788]
+
+2007-07-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ Make pwcheck local to the pwflag block. Use pwcheck even if user
+ didn't match since Defaults options may still apply.
+ [45da9efbbafd]
+
+ * check.c, sudo.c:
+ Do not update timestamp if user not validated by sudoers.
+ [a4a9d4364827]
+
+ * set_perms.c:
+ for PERM_RUNAS, set the egid to the runas user's gid and restore to
+ the user's original in PERM_ROOT
+ [1514bfb32847]
+
+ * logging.c, mon_systrace.c, set_perms.c, sudo.h:
+ PERM_FULL_ROOT is now no different than PERM_ROOT so remove
+ PERM_FULL_ROOT
+ [b9d047a3178c]
+
+ * check.c:
+ don't check timestamp mtime if we are just going to remove it
+ [5d2470bc6cbd]
+
+ * sudoers.pod:
+ Move sudoers defaults parameters into their own section.
+ [54701fbc0ff3]
+
+ * testsudoers.c:
+ Reduce a level of indent by a few placed continue statements.
+ [5d5a9838c8ef]
+
+ * parse.c:
+ Make matching but negated commands/hosts/runas entries override a
+ previous match as expected. Also reduce some levels of indent by a
+ few placed continue statements.
+ [dd59fa4b91a1]
+
+2007-07-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ Print default runas in "sudo -l" if sudoers don't specify one.
+ [07d408c400bd]
+
+ * match.c:
+ Less hacky way of testing whether the domain was set.
+ [a537059776e5]
+
+2007-07-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ Mention pam-devel and openldap-devel for Linux
+ [9e708c54ecc3]
+
+2007-07-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * README.LDAP:
+ or vs. are
+ [abe8c0f3a410]
+
+2007-07-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ fix typo in Solaris project support
+ [2ffeb2d80959]
+
+ * HISTORY:
+ update
+ [df162b36f120]
+
+ * sudo.c:
+ Make -- on the command line match the manual page. The implied shell
+ case has been simplified as a result.
+ [cd217a1f6694]
+
+2007-06-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers2ldif:
+ add simplistic support for sudoRunas; note that if a sudoers entry
+ contains multiple Runas users, all will apply to the sudoRole
+ [65b11421f5c8]
+
+ * sudoers2ldif:
+ honor SETENV and NOSETENV tags
+ [2c0d5ba7a09b]
+
+2007-06-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mon_systrace.c:
+ Redo setting of user_args. We now build up a private copy of argv
+ first and then replace the NULs with spaces.
+ [ccbba72ea112]
+
+ * mon_systrace.c:
+ getcwd() returns NULL on failure, not 0 on success
+ [88cd9e66e530]
+
+ * mon_systrace.c:
+ allow chunksiz to reach 1 before erroring out
+ [619d68f14964]
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat,
+ visudo.man.in:
+ regen
+ [8db512d3caf0]
+
+2007-06-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * def_data.c, def_data.h, def_data.in, env.c, gram.c, gram.h, gram.y,
+ logging.c, parse.c, parse.h, sudo.c, sudo.h, sudo.pod, sudoers.pod,
+ toke.c, toke.l:
+ Add support for setting environment variables on the command line.
+ This is only allowed if the setenv sudoers options is enabled or if
+ the command is prefixed with the SETENV tag.
+ [5744caebd969]
+
+ * README.LDAP:
+ replace Aaron's email address with the sudo-workers list
+ [2ffce5f9afc0]
+
+ * configure:
+ regen
+ [8013dff82c0c]
+
+2007-06-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, README.LDAP:
+ Break schema out into separate files.
+ [1a53966ca1fa]
+
+ * schema.OpenLDAP, schema.iPlanet:
+ Break schema out into separate files.
+ [15e598e4c60b]
+
+2007-06-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/aix_auth.c:
+ free message if set by authenticate()
+ [849c220c1236]
+
+ * match.c:
+ deal with NULL gr_mem
+ [49e4d74f0bbe]
+
+2007-06-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in:
+ regen
+ [fead999ad3e9]
+
+ * configure.in:
+ add template for HAVE_PROJECT_H
+ [e6c42c2eaad1]
+
+ * closefrom.c:
+ include fcntl.h
+ [54d98b382f03]
+
+2007-06-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ mention --with-project
+ [d3ea3baad7c5]
+
+ * config.h.in, configure.in, sudo.c:
+ Add Solaris 10 "project" support. From Michael Brantley.
+ [f14f3c8c6554]
+
+ * sudoers.pod:
+ fix typo
+ [50db81a19787]
+
+ * configure:
+ regen
+ [ea71afd3e564]
+
+ * configure.in:
+ Fix preservation of LDFLAGS in the LDAP case.
+ [40a3a47e8059]
+
+ * memrchr.c:
+ Remove dependecy on NULL
+ [c957ae5e1733]
+
+ * configure:
+ regen
+ [4955ce0c6912]
+
+ * aclocal.m4, configure.in:
+ Can't use the regular autoconf fnmatch() check since we need
+ FNM_CASEFOLD so go back to our custom one.
+ [f10d76237486]
+
+ * env.c:
+ Fix preserving of variables in env_keep.
+ [d040049d6b84]
+
+ * env.c:
+ add XAUTHORIZATION
+ [0d589a5fe015]
+
+ * UPGRADE:
+ expand upon env resetting and mention that it began in 1.6.9 not
+ 1.7.
+ [dba251655c76]
+
+ * sudoers.pod:
+ Update descriptions of env_keep and env_check to match current
+ reality.
+ [dba77357954b]
+
+2007-06-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ Add LINGUAS to initial_checkenv_table. Add COLORS, HOSTNAME,
+ LS_COLORS, MAIL, PS1, PS2, XAUTHORITY to intial_keepenv_table.
+ [eec4632bd190]
+
+ * env.c, logging.c:
+ Treat USERNAME environemnt variable like LOGNAME/USER
+ [09f52dcfd70c]
+
+ * env.c:
+ Don't need to populate keepenv table with the contents of the
+ checkenv table.
+ [527a14afd973]
+
+ * sudo.c:
+ Don't force sudo into the C locale.
+ [8a5bd301ef96]
+
+ * env.c:
+ Make env_check apply when env_reset it true. Environment variables
+ are passed through unless they contain '/' or '%'. There is no need
+ to have a variable in both env_check and env_keep.
+ [840c802721e4]
+
+2007-06-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ Remove an duplicate lock_file() call and add a comment.
+ [5af9dcdf0eb6]
+
+ * UPGRADE:
+ Add sudo 1.6.9 upgrade note.
+ [1585149f2914]
+
+2007-06-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * interfaces.c:
+ Solaris will return EINVAL if the buffer used in SIOCGIFCONF is too
+ small. From Klaus Wagner.
+ [d6899fc44f77]
+
+ * logging.c, sudo.h:
+ Redo the long syslog line splitting based on a patch from Eygene
+ Ryabinkin. Include memrchr() for systems without it.
+ [66a50e8d553a]
+
+ * Makefile.in, config.h.in, configure, configure.in:
+ Redo the long syslog line splitting based on a patch from Eygene
+ Ryabinkin. Include memrchr() for systems without it.
+ [407a46190921]
+
+ * memrchr.c:
+ Redo the long syslog line splitting based on a patch from Eygene
+ Ryabinkin. Include memrchr() for systems without it.
+ [2f6702b7d41b]
+
+ * configure.in:
+ Since we need to be able to convert timespec to timeval for utimes()
+ the last 3 digits in the tv_nsec are not significant. This makes the
+ sudoedit file date comparison work again.
+ [9d0258849fa9]
+
+2007-06-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aclocal.m4, configure, configure.in:
+ Add SUDO_ADD_AUTH macro to deal with adding things to AUTH_OBJS.
+ This deals with exclusive authentication methods in a simple way.
+ [7d70072c0f35]
+
+2007-06-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * LICENSE:
+ mkstemp.c is BSD code too.
+ [29e236d98162]
+
+ * sudo.pod, sudoers.pod, visudo.pod:
+ No commercial support for now.
+ [7c76b3e192dd]
+
+2007-06-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ cleanenv() is no more.
+ [518080514408]
+
+2007-06-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ChangeLog:
+ Display branch info in Changelog
+ [44e3b27427c7]
+
+ * utimes.c:
+ Include config.h early so we have it for TIME_WITH_SYS_TIME
+ [4bf1a00d0703]
+
+ * ChangeLog:
+ Fix Changelog generation and update.
+ [6e960dbcbece]
+
+2007-06-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * closefrom.c:
+ Use /proc/self/fd instead of /proc/$$/fd
+
+ Move old-style fd closing into closefrom_fallback() and call that if
+ /proc/self/fd doesn't exist or the F_CLOSEM fcntl() fails
+ [faa7e4810758]
+
+ * auth/kerb5.c, config.h.in, configure.in:
+ o use krb5_verify_user() if available instead of doing it by hand o
+ use krb5_init_secure_context() if we have it o pass an encryption
+ type of 0 to krb5_kt_read_service_key() instead of
+ ENCTYPE_DES_CBC_MD5 to let kerberos choose.
+ [df7acf72bd7c]
+
+ * env.c:
+ Check TERM and COLORTERM for '%' and '/' characters. From Debian.
+ [f92d05197e40]
+
+ * configure.in:
+ Fix closefrom() substitution in the Makefile
+ [b642b13fcc5c]
+
+ * TROUBLESHOOTING:
+ Mention alternate sudo pronunciation.
+ [7c71dc73409f]
+
+2007-06-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ Remove KRB5_KTNAME from environment. Allow COLORTERM.
+ [70f35a79f780]
+
+ * auth/kerb5.c:
+ If we cannot get a valid service key using the default keytab it is
+ a fatal error. Fixes a bug where sudo could be tricked into allowing
+ access when it should not by a fake KDC. From Thor Lancelot Simon.
+ [a3ae6a47cb23]
+
+2007-05-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aclocal.m4, configure, configure.in:
+ Update long long checks to use AC_CHECK_TYPES and to cache values.
+ [047318eaaeb2]
+
+ * aclocal.m4, configure.in:
+ Use AC_FUNC_FNMATCH instead of a homebrew fnmatch checker. We can't
+ use AC_REPLACE_FNMATCH since that assumes replacing with GNU
+ fnmatch.
+ [80513a1003ea]
+
+2007-05-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Add closefrom() to LIB_OBJS not SUDO_OBJS if it is missing since we
+ need it for visudo now too.
+ [50837c7c2b5e]
+
+2007-04-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ Attempt to clarify the bit talking about network numbers w/o
+ netmasks.
+ [211e68c1d034]
+
+ * sudo.pod:
+ Clarify timestamp dir ownership sentence.
+ [9178f132c7f7]
+
+2007-04-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/pam.c:
+ Linux PAM now defines __LINUX_PAM__, not __LIBPAM_VERSION. From
+ Dmitry V. Levin.
+ [81fce91667bc]
+
+2007-04-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ -i is also one of the mutually exclusive options to list it in the
+ warning message. Noted by Chris Pepper.
+ [7da73fb248e9]
+
+2007-04-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.pod:
+ The sudoers variable is env_editor, not enveditor. From Jean-
+ Francois Saucier.
+ [2a86ec09a6db]
+
+2007-03-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * redblack.c:
+ I tracked down the original author so credit him and include his
+ license info.
+ [3733553a1bba]
+
+2007-02-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.cat, sudo.man.in, sudo.pod, sudoers.cat, sudoers.man.in,
+ sudoers.pod:
+ Fix typos; from Jason McIntyre.
+ [1ee4ce2512f2]
+
+ * logging.c:
+ Restore signal mask before calling reapchild(). Fixes a possible
+ race condition that could prevent sudo from properly waiting for the
+ child.
+ [9ee4192385dc]
+
+2007-01-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pwutil.c:
+ Don't declare pw_free() if we are not going to use it.
+ [adb79a4289ca]
+
+ * env.c:
+ Add NOEXEC support for AIX 5.3 which supports LDR_PRELOAD and
+ LDR_PRELOAD64. The 64-bit version is not currently supported. Remove
+ zero_env() prototype as it no longer exists.
+ [b4fe65027fb6]
+
+2006-12-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ Add "Auto-Submitted: auto-generated" line to sudo mail for rfc 3834.
+ [78002ad90f7b]
+
+2006-09-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/pam.c:
+ If the user enters ^C at the password prompt, abort instead of
+ trying to authenticate with an empty password (which causes an
+ annoying delay).
+ [da3f27b747c7]
+
+2006-08-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * closefrom.c, config.h.in, configure, configure.in:
+ Add fcntl F_CLOSEM support to closefrom(); adapted from a diff by
+ Darren Tucker.
+ [0331b7780759]
+
+ * pwutil.c:
+ pw_free() is only used by sudo_freepwcache() so ifdef it out too.
+ [0014c0d9eeba]
+
+2006-08-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.guess, config.sub:
+ Update to latest versions from cvs.savannah.gnu.org
+ [aa0143101c20]
+
+2006-07-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pwutil.c, sudo_edit.c:
+ Move password/group cache cleaning out of sudo_end{pw,grp}ent() so
+ we can close the passwd/group files early.
+ [559074bd7eb7]
+
+ * config.h.in, configure, configure.in, set_perms.c:
+ Add seteuid() flavor of set_perms() for systems without setreuid()
+ or setresuid() that have a working seteuid(). Tested on Darwin.
+ [508d8da99189]
+
+2006-07-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mon_systrace.c:
+ systrace_read() returns ssize_t
+ [9f97d1d1a59d]
+
+ * configure, configure.in:
+ Fix typo, -lldap vs. -ldap; from Tim Knox.
+ [a8cc43c3bb2a]
+
+2006-07-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * HISTORY:
+ Fix typo; Matt Ackeret
+ [86964ee3dfbd]
+
+2006-07-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Print sudoers path in -V mode for root.
+ [dc43f2d75bd9]
+
+2006-06-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ Do a sub tree search instead of a base search (one level in the tree
+ only) for sudo right objects. This allows system administrators to
+ categorize the rights in a tree to make them easier to manage.
+ [6d2d9abf996e]
+
+2005-12-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod:
+ fix typo
+ [1473413bcbda]
+
+2005-12-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ Convert GET_OPT and GET_OPTI to use just 2 args. Add timelimit and
+ bind_timelimit support; adapted from gentoo.
+ [afc816093026]
+
+2005-11-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ Support comments that start in the middle of a line
+ [c25df6ee3db8]
+
+ * configure, configure.in:
+ Define LDAP_DEPRECATED until we start using ldap_get_values_len()
+ [ee249bfe230a]
+
+2005-11-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * closefrom.c:
+ Silence gcc -Wsign-compare; djm@openbsd.org
+ [28769ce6418d]
+
+ * error.c, sudo.c, sudo.h, testsudoers.c, visudo.c:
+ cleanup() now takes an int as an arg so it can be used as a signal
+ handler too.
+ [2bb0df34d09c]
+
+ * sudo.c:
+ Make a copy of the shell field in the passwd struct for NewArgv to
+ avoid a use after free situation after sudo_endpwent() is called.
+ [5dcc9ffd362e]
+
+2005-11-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in:
+ Add mkstemp() for those poor souls without it.
+ [5fdd02e863e0]
+
+ * Makefile.in:
+ Add mkstemp() for those poor souls without it.
+ [9c1cf2678f24]
+
+ * mkstemp.c:
+ Add mkstemp() for those poor souls without it.
+ [c99401207860]
+
+2005-11-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ Add PERL5DB to list of environment variables to remove.
+ [7375c27ecf75]
+
+2005-11-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mon_systrace.c, mon_systrace.h:
+ Instead of calling the check function twice with a state cookie use
+ separate check/log functions.
+
+ Check more ioctl() calls for failure.
+
+ systrace_{read,write} now return the number of bytes read/written or
+ -1 on error.
+ [3dc8946d90e9]
+
+ * env.c:
+ Add more environment variables to remove; from gentoo linux Add some
+ comments about what bad env variables go to what (more to do)
+ [6918110a6b82]
+
+2005-11-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c, sudo_edit.c:
+ Move sudo_end{gr,pw}ent() until just before the exec since they free
+ up our cached copy of the passwd structs, including sudo_user and
+ sudo_runas. Fixes a use-after-free bug.
+ [54de3778bad0]
+
+ * visudo.c:
+ Close all fd's before executing editor.
+ [4fcc05e1bec8]
+
+ * sudo.c:
+ Enable malloc debugging on OpenBSD when SUDO_DEVEL is set.
+ [ef0e8ffa5c9f]
+
+ * check.c:
+ Fix fd leak when lecture file option is enabled. From Jerry Brown
+ [ce97f9207cd8]
+
+2005-11-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ Add PERLLIB, PERL5LIB and PERL5OPT to the default list of
+ environment variables to remove. From Charles Morris
+ [c96e1367d1c1]
+
+2005-11-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ add JAVA_TOOL_OPTIONS to initial_badenv_table for java 5
+ [72a6a1571226]
+
+2005-10-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ add PS4 and SHELLOPTS to initial_badenv_table for bash
+ [89dfb3f318f3]
+
+2005-08-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ Fix typo; Toby Peterson
+ [b7a3222b23f4]
+
+2005-08-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * tsgetgrpw.c:
+ Make return buffers static so they don't get clobbered
+ [13323a39b9f5]
+
+2005-07-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/securid5.c:
+ Fix securid5 authentication, was not checking for ACM_OK. Also add
+ default cases for the two switch()es. Problem noted by ccon at
+ worldbank
+ [14091e418333]
+
+2005-06-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ Remove ncat() in favor of just counting bytes and pre-allocating
+ what is needed.
+ [25b8712adb61]
+
+2005-06-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ Fix up some comments Add missing fclose() for the rootbinddn case
+ [ae95c8a89711]
+
+ * ldap.c:
+ align struct ldap_config
+ [35d0d64c76f8]
+
+ * ldap.c:
+ use LINE_MAX for max conf file line size
+ [da116cb8853d]
+
+ * pathnames.h.in:
+ add _PATH_LDAP_SECRET
+ [128b04ecfab7]
+
+ * README.LDAP:
+ Mention rootbinddn Give example ou=SUDOers container
+ [852edc69bd1c]
+
+2005-06-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, configure, configure.in, ldap.c:
+ Support rootbinddn in ldap.conf
+ [1615c91522a1]
+
+ * env.c, sudo.pod, sudoers.pod:
+ Preserve DISPLAY environment variable by default.
+ [05f503d5f438]
+
+ * acsite.m4, configure:
+ set need_lib_prefix=no for all cases; this is safe for LD_PRELOAD
+ [18a04dea8d05]
+
+ * acsite.m4, configure:
+ set need_version=no for all cases; this is safe for LD_PRELOAD
+ [b542560e1a73]
+
+ * aclocal.m4:
+ typo
+ [c040df0fcd5a]
+
+ * configure, configure.in:
+ Add dragonfly
+ [f13794618636]
+
+ * auth/pam.c:
+ Fix call to pam_end() when pam_open_session() fails.
+ [0be47cdfdef1]
+
+ * configure:
+ regen
+ [7f5c13b4b800]
+
+ * acsite.m4:
+ rebuild acsite.m4 from libtool 1.9f libtool.m4 ltoptions.m4
+ ltsugar.m4 ltversion.m4
+ [a7ba9fd1a2ab]
+
+ * config.guess, config.sub, ltmain.sh:
+ merge in local changes: config.guess: o better openbsd support
+ config.sub: o hiuxmpp support ltmain.sh o remove requirement that
+ libs must begin with "lib" o don't print a bunch of crap about
+ library installs o don't run ldconfig
+ [f4149f2c720f]
+
+ * config.guess, config.sub, ltmain.sh:
+ libtool 1.9f
+ [82a534e7121f]
+
+ * configure.in:
+ Update with autoupdate and make minor changes for libtool 1.9f
+ [11b5ae5c1428]
+
+2005-06-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ don't call sudo_ldap_display_cmnd if ldap not setup
+ [8bcf6c094ffe]
+
+ * check.c, compat.h:
+ Move declatation of struct timespec to its own include files for
+ systems without it since it needs time_t defined.
+ [2ef2ace8fe85]
+
+ * emul/timespec.h:
+ Move declatation of struct timespec to its own include files for
+ systems without it since it needs time_t defined.
+ [f95137771564]
+
+ * fileops.c:
+ Move declatation of struct timespec to its own include files for
+ systems without it since it needs time_t defined.
+ [dd8573b2ee7d]
+
+ * gettime.c:
+ Move declatation of struct timespec to its own include files for
+ systems without it since it needs time_t defined.
+ [021b4569cc0c]
+
+ * sudo_edit.c, visudo.c:
+ Move declatation of struct timespec to its own include files for
+ systems without it since it needs time_t defined.
+ [b95c333299a0]
+
+ * ldap.c:
+ Don't set safe_cmnd for the "sudo ALL" case.
+ [ad7fa9e07da0]
+
+2005-05-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/pam.c:
+ Call pam_open_session() and pam_close_session() to give pam_limits a
+ chance to run. Idea from Karel Zak.
+ [fed46d471350]
+
+2005-04-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c, sudo.c:
+ Add explicit cast from mode_t -> u_int in printf to silence warnings
+ on Solaris
+ [17bb961fe22d]
+
+ * parse.c:
+ include grp.h to silence a warning on Solaris
+ [14386fbab640]
+
+2005-04-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ Fix printing of += and -= defaults.
+ [a667604c56cd]
+
+2005-04-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mon_systrace.c:
+ Sanity check number of syscall args with argsize. Not really needed
+ but a little paranoia never hurts.
+ [6bb455a2c2d6]
+
+ * mon_systrace.c, mon_systrace.h:
+ Don't do pointer arithmetic on void * Use int, not size_t/ssize_t
+ for systrace lengths (since it uses int)
+ [3cafccffcffd]
+
+2005-04-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mon_systrace.c:
+ Add some memsets for paranoia Fix namespace collsion w/ error Check
+ rval of decode_args() and update_env() Remove improper setting of
+ validated variable
+ [3d385158354d]
+
+2005-04-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c, sudo.c, sudo.h:
+ In -l mode, only check local sudoers file if def_ignore_sudoers is
+ not set and call LDAP versions from display_privs() and
+ display_cmnd() instead of directly from main(). Because of this we
+ need to defer closing the ldap connection until after -l processing
+ has ocurred and we must pass in the ldap pointer to display_privs()
+ and display_cmnd().
+ [1dfc2e8c9f2b]
+
+ * ldap.c:
+ Reorganize LDAP code to better match normal sudoers parsing. Instead
+ of storing strings for later printing in -l mode we do another query
+ since the authenticating user and the user being listed may not be
+ the same (the new -U flag). Also add support for "sudo -l command".
+
+ There is still a fair bit if duplicated code that can probably be
+ refactored.
+ [e9568f19bde5]
+
+2005-04-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ Replace pass variable with do_netgr for better readability.
+ [1bba841b6e79]
+
+ * ldap.c:
+ use DPRINTF macro
+ [02b159b66bb5]
+
+ * ldap.c:
+ estrdup, not strdup
+ [22cdee7973c1]
+
+2005-04-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ Add macro to test if the tag changed to improve readability.
+ [4e11b4819556]
+
+ * parse.c:
+ Avoid printing defaults header if there are no defaults to print...
+ [41a28627df03]
+
+ * glob.c:
+ Fix a warning on systems without strlcpy().
+ [6814e0f0e4f4]
+
+ * pwutil.c:
+ Use macros where possible for sudo_grdup() like sudo_pwdup().
+ [30f201ff35cd]
+
+2005-04-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * utimes.c:
+ It is possible for tv_usec to hold >= 1000000 usecs so add in
+ tv_usec / 1000000.
+ [794ac4d53a65]
+
+2005-03-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/kerb5.c:
+ The component in krb5_principal_get_comp_string() should be 1, not 0
+ for Heimdal. From Alex Plotnick.
+ [fefa351c5044]
+
+2005-03-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * alias.c, alloc.c, check.c, defaults.c, find_path.c, gram.c, gram.y,
+ interfaces.c, ldap.c, logging.c, match.c, mon_systrace.c, pwutil.c,
+ redblack.c, sudo.c, sudo.h, toke.c, toke.l, visudo.c:
+ Add efree() for consistency with emalloc() et al. Allows us to rely
+ on C89 behavior (free(NULL) is valid) even on K&R.
+ [7876bb80d87c]
+
+ * parse.c, sudo.c:
+ Move initgroups() for -U option into display_privs() so group
+ matching in sudoers works correctly.
+ [b074428ad2ca]
+
+2005-03-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ Removed duplicate call to ldap_unbind_s introduced along with
+ sudo_ldap_close.
+ [19acc1c20f7c]
+
+ * parse.c:
+ Add missing space in Defaults printing
+ [95d2935bf6d4]
+
+2005-03-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pwutil.c:
+ Sync sudo_pwdup with OpenBSD changes: use macros for size computaton
+ and string copies.
+ [6b6b241495e5]
+
+2005-03-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pwutil.c:
+ Zero old pw_passwd before replacing with version from shadow file.
+ [3251b349dfe1]
+
+ * configure, configure.in:
+ Only attempt shadow password detection if PAM is not being used Add
+ shadow_* variables to make shadow password detection more generic.
+ [d498a3423ac9]
+
+ * configure.in:
+ Use OSDEFS for os-specific -D_FOO_BAR stuff rather than CPPFLAGS
+ [04d55bbd5e35]
+
+2005-03-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ use a non-breaking space to avoid a double space after e.g.
+ [11cdb54bdf7b]
+
+ * sudo.pod:
+ commna, not colon after e.g.
+ [8d5875ff72e0]
+
+2005-03-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo_noexec.c:
+ Add __ variants of the exec functions. GNU libc at least uses
+ __execve() internally.
+ [d1880473d790]
+
+ * indent.pro:
+ Match reality a bit more.
+ [633e3fa875a7]
+
+ * pwutil.c:
+ Missed piece from rev. 1.6, fix sudo_getpwnam() too.
+ [128f7b21c2ee]
+
+ * pwutil.c:
+ Store shadow password after making a local copy of struct passwd in
+ case normal and shadow routines use the same internal buffer in
+ libc.
+ [f806052a6ffc]
+
+2005-03-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * alloc.c, logging.c:
+ Make varargs usage consistent with the rest of the code.
+ [3d45affc9851]
+
+2005-03-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo_noexec.c:
+ Wrap more of the exec family since on Linux the others do not appear
+ to go through the normal execve() path.
+ [8167769b4e19]
+
+ * visudo.c:
+ make print_unused static like proto says
+ [ecf10e1bae55]
+
+ * glob.c:
+ silence a warning on K&R systems
+ [2e00425f1a5c]
+
+ * alias.c, error.c:
+ make this build in K&R land
+ [156f65f8525a]
+
+ * parse.c:
+ make this build in K&R land
+ [6fc9276889cb]
+
+2005-03-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * toke.c:
+ regen
+ [3b349748cd21]
+
+2005-03-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ return(foo) not return foo optimize _atobool() slightly
+ [11d09d154ed5]
+
+ * ldap.c:
+ Use TRUE/FALSE
+ [53999320d98f]
+
+ * ldap.c:
+ Reformat to match the rest of sudo's code.
+ [1bd0f2afa0e7]
+
+ * sudo.pod:
+ I am the primary author
+ [5d311ecd85c6]
+
+2005-02-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, README, RUNSON:
+ The RUNSON file is toast--it confused too many people and really
+ isn't needed in a configure-oriented world.
+ [96a6ef7bbc08]
+
+ * INSTALL:
+ alternate -> alternative
+ [b65015c5d0a2]
+
+ * tgetpass.c:
+ Use TCSADRAIN instead of TCSAFLUSH since some OSes have issues with
+ TCSAFLUSH.
+ [c66b4763ffdc]
+
+ * toke.l:
+ Allow leading blanks before Defaults and Foo_Alias definitions
+ [2add513d9277]
+
+ * Makefile.in:
+ fix rules to build toke.o and gram.o in devel mode
+ [96cbb414ebd3]
+
+2005-02-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ env_keep overrides set_logname
+ [401877193a15]
+
+ * env.c:
+ Fix disabling set_logname and make env_keep override set_logname.
+ [0906e7a5ed93]
+
+ * compat.h, config.h.in, configure, configure.in:
+ No longer need memmove()
+ [43bdb6efe3f2]
+
+ * env.c, sudo.c:
+ Just clean the environment once. This assumes that any further
+ setenv/putenv will be able to handle the fact that we replaced
+ environ with our own malloc'd copy but all the implementations I've
+ checked do.
+ [11658fe92ba2]
+
+2005-02-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c, sudo.c:
+ In -i mode, base the value of insert_env()'s dupcheck flag on
+ DID_FOO flags. Move checks for $HOME resetting into rebuild_env()
+ [8365b0bd0c71]
+
+2005-02-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c, sudo.c:
+ Move setting of user_path, user_shell, user_prompt and prev_user
+ into init_vars() since user_shell at least is needed there.
+ [37e22dce66e9]
+
+2005-02-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ fix devel builds
+ [9fbb15ef164c]
+
+ * sudo.c:
+ Fix some printf format mismatches on error.
+ [ffc1c3f11740]
+
+ * check.c:
+ Fix some printf format mismatches on error.
+ [7b3b508adf50]
+
+ * configure, gram.c, toke.c:
+ regen
+ [aa76f9d8b02a]
+
+ * Makefile.in, aclocal.m4, alias.c, alloc.c, auth/afs.c,
+ auth/aix_auth.c, auth/bsdauth.c, auth/dce.c, auth/fwtk.c,
+ auth/kerb4.c, auth/kerb5.c, auth/pam.c, auth/passwd.c,
+ auth/rfc1938.c, auth/secureware.c, auth/securid.c, auth/securid5.c,
+ auth/sia.c, auth/sudo_auth.c, auth/sudo_auth.h, check.c,
+ closefrom.c, compat.h, configure.in, defaults.c, defaults.h,
+ emul/utime.h, env.c, error.c, fileops.c, find_path.c, getprogname.c,
+ getspwuid.c, gettime.c, goodpath.c, gram.y, interfaces.c,
+ interfaces.h, ldap.c, logging.c, logging.h, match.c, mon_systrace.c,
+ parse.c, redblack.c, redblack.h, set_perms.c, sigaction.c,
+ snprintf.c, strcasecmp.c, strerror.c, strlcat.c, strlcpy.c, sudo.c,
+ sudo.h, sudo.pod, sudo_edit.c, sudo_noexec.c, sudoers.pod,
+ testsudoers.c, tgetpass.c, toke.l, utimes.c, version.h, visudo.c,
+ visudo.pod, zero_bytes.c:
+ Update copyright years.
+ [0610c3654739]
+
+ * LICENSE:
+ Update copyright years.
+ [f60473bca4b1]
+
+ * Makefile.binary.in:
+ Update copyright years.
+ [d78ffc9f2e2b]
+
+ * BUGS, INSTALL, INSTALL.binary, Makefile.in, README, configure.in:
+ version 1.7
+ [aa977a544ca1]
+
+ * WHATSNEW:
+ What's new in sudo 1.7, based on the 1.7 CHANGES entries.
+ [ecfcf7269c14]
+
+2005-02-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat.h, logging.h, sudo.h:
+ Add __printflike and use it with gcc to warn about printf-like
+ format mismatches
+ [b192ad4a0548]
+
+2005-02-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, ChangeLog:
+ Replaced CHANGES file with ChangeLog generated from cvs logs
+ [d9ace9dab98f]
+
+ * set_perms.c:
+ Use warning/error instead of perror/fatal.
+ [e33259df7738]
+
+ * config.guess:
+ Update OpenBSD section
+ [9d2c23de6801]
+
+ * UPGRADE:
+ Add upgrading noted for 1.7
+ [1fb6b6d6df07]
+
+ * env.c, sudo.c, sudoers.pod:
+ Instead of zeroing out the environment, just prune out entries based
+ on the env_delete and env_check lists. Base building up the new
+ environment on the current environment and the variables we removed
+ initially.
+ [fc192df8fd15]
+
+ * config.h.in, configure, configure.in, sudo.c:
+ Set locale to "C" if locales are supported, just to be safe.
+ [91fbaa98f02e]
+
+ * toke.c, toke.l:
+ Cast argument to ctype functions to unsigned char.
+ [e096b4d65796]
+
+2005-02-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ correct value for DID_USER
+ [b5b05d36ec15]
+
+ * error.c, fnmatch.c, getcwd.c, glob.c, snprintf.c:
+ #include <compat.h> not "compat.h"
+ [7a0ad9a0ccd7]
+
+ * defaults.c:
+ Reset the environment by default.
+ [4ecc6423e0f0]
+
+ * sudo.c:
+ Alloc an extra slot in NewArgv. Removes the need to malloc an new
+ vector if execve() fails.
+ [83dfb6f584a7]
+
+2005-02-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, config.h.in, configure, configure.in, sudo.c:
+ Use execve(2) and wrap the command in sh if we get ENOEXEC.
+ [c0c6af4e2a21]
+
+2005-02-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo_noexec.c:
+ Only include time.h on systems that lack struct timespec which gets
+ defind in compat.h (using time_t).
+ [e373e518b4cb]
+
+ * sudo_noexec.c:
+ Include time.h for time_t in compat.h for systems w/o struct
+ timespec.
+ [a34b5637e458]
+
+ * compat.h, config.h.in, configure, configure.in:
+ use bcopy on systems w/o memmove
+ [f835eafd78c6]
+
+ * compat.h:
+ __attribute__((__unused__)) doesn't work in gcc 2.7.2.1 so limit its
+ use to gcc >= 2.8.
+ [1cb9a4e58566]
+
+ * Makefile.in:
+ Add explicit rule to build sudo_noexec.lo
+ [df1dfcf8dd77]
+
+2005-02-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL.configure, Makefile.in:
+ No longer depend on VPATH; pointed out a bunch of missed
+ dependencies.
+ [601a45d4af6b]
+
+ * TROUBLESHOOTING:
+ Help for PAM when account section is missing
+ [9b8221256756]
+
+ * auth/pam.c:
+ Give user a clue when there is a missing "account" section in the
+ PAM config.
+ [2529625c0495]
+
+ * auth/pam.c:
+ Better error handling.
+ [518c9bda23d8]
+
+ * config.h.in, configure, configure.in:
+ Move _FOO_SOURCE to CPPFLAGS so it takes effect as early as
+ possible. Silences a warning about isblank() on linux.
+ [19c94d7ecdc8]
+
+ * auth/pam.c:
+ Fix typo (missing comma) that caused an incorrect number of args to
+ be passed to log_error().
+ [0099dfec560f]
+
+2005-02-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pwutil.c:
+ Don't try to destroy a tree we didn't create.
+ [d43c4fe03aa4]
+
+2005-01-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * alias.c, alloc.c, auth/afs.c, auth/aix_auth.c, auth/bsdauth.c,
+ auth/dce.c, auth/fwtk.c, auth/kerb4.c, auth/kerb5.c, auth/pam.c,
+ auth/passwd.c, auth/rfc1938.c, auth/secureware.c, auth/securid.c,
+ auth/securid5.c, auth/sia.c, auth/sudo_auth.c, check.c, closefrom.c,
+ compat.h, defaults.c, env.c, error.c, fileops.c, find_path.c,
+ fnmatch.c, getcwd.c, getprogname.c, getspwuid.c, gettime.c,
+ goodpath.c, gram.c, gram.y, interfaces.c, ldap.c, logging.c,
+ match.c, mon_systrace.c, parse.c, pwutil.c, set_perms.c,
+ sigaction.c, snprintf.c, strcasecmp.c, strerror.c, strlcat.c,
+ strlcpy.c, sudo.c, sudo_edit.c, sudo_noexec.c, testsudoers.c,
+ tgetpass.c, toke.c, toke.l, utimes.c, visudo.c, zero_bytes.c:
+ Add __unused to rcsids
+ [ad6b4ac45705]
+
+2005-01-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Fix error message when mixing invalid auth types
+ [68069b3ff5bc]
+
+ * INSTALL:
+ PAM, AIX auth, BSD auth and login_cap are now on by default if the
+ OS supports them.
+ [4e44e9098cf0]
+
+ * auth/sudo_auth.h, config.h.in:
+ s/HAVE_AUTHENTICATE/HAVE_AIXAUTH/g
+ [2d569b43b23e]
+
+ * configure.in:
+ Better checking for conflicting authentication methods Display the
+ authentication methods used at the end of configure Rename --with-
+ authenticate -> --with-aixauth Use --with-aixauth, --with-bsdauth,
+ --with-pam, --with-logincap by default on systems that support them
+ unless disabled. Add OSMAJOR variable that replaces old OSREV; now
+ OSREV has full version number
+ [a21115b6fe9f]
+
+2005-01-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * def_data.c, def_data.in, sudo.c, sudoers.pod:
+ s/-O/-C/
+ [ee73f1b81923]
+
+2005-01-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ Replace: test -n "$FOO" || FOO="bar"
+
+ With: : ${FOO='bar'}
+ [37552d9054fc]
+
+2005-01-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * pwutil.c, testsudoers.c, tsgetgrpw.c:
+ Use function pointers to only call private passwd/group routines
+ when using a nonstandard passwd/group file.
+ [215908681dfb]
+
+2005-01-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ sync
+ [2e55c03f5790]
+
+ * tsgetgrpw.c:
+ Can't use strtok() since it doesn't handle empty fields so add
+ getpwent()/getgrent() functions and call those.
+ [bdaa5b0db70e]
+
+2005-01-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ Fix dummied out toke.c and gram.c dependencies.
+ [4b909c8b2ebe]
+
+ * Makefile.in:
+ Rename PARSESRCS -> GENERATED since it is only used in the clean
+ target Add devdir variable and use it to specify the path to parser
+ sources
+ [f27b3f41ca23]
+
+ * configure:
+ regen
+ [22c6435dbd46]
+
+ * configure.in:
+ Add a devdir variables that defaults to $(srcdir) and is set to . if
+ --devel was specified. Allows for proper dependecies building the
+ parser.
+ [a36d694c6d21]
+
+ * testsudoers.c:
+ Add support for custom passwd/group files.
+ [296549ff4b87]
+
+ * Makefile.in:
+ Build private copy of pwutil.o for testsudoers with MYPW defined so
+ it uses our own passwd/group routines.
+ [bafa54ec78ca]
+
+ * visudo.c:
+ Remove sudo_*{pw,gr}* stubs and add sudo_setspent/sudo_endspent
+ stubs instead. We can now just use the caching sudo_*{pw,gr}*
+ functions in pwutil.c Add comment about wanting to call
+ sudo_endpwent/sudo_endgrent in cleanup()
+ [7e59d6b5510d]
+
+ * tsgetgrpw.c:
+ Remove caching; we will just use what is in pwutil.c Use global
+ buffers for passwd/group structs Rename functions from sudo_* to
+ my_*
+ [8c1e068f574c]
+
+ * logging.c, sudo.c:
+ g/c pwcache_init/pwcache_destroy
+ [60a24909b947]
+
+ * sudo.h:
+ Undo last commit and add sudo_setspent and sudo_endspent instead.
+ [bac80db08296]
+
+ * getspwuid.c, pwutil.c:
+ Move all but the shadow stuff from getspwuid.c to pwutil.c and
+ pwcache_get and pwcache_put as they are no longer needed. Also add
+ preprocessor magic to use private versions of the passwd and group
+ routines if MYPW is defined (for use by testsudoers).
+ [a16b8678a426]
+
+ * tsgetgrpw.c:
+ zero out struct passwd/group before filling it in so if there are
+ fields we don't handle they end up as 0.
+ [274cb6a93301]
+
+ * logging.c, sudo.c, sudo.h, testsudoers.c, visudo.c:
+ Adapt to pwutil.c
+ [43ebd04c8b82]
+
+ * Makefile.in:
+ Add tsgetgrpw.c and pwutil.c Rename the *OBJ variables for better
+ readability.
+ [7f88c6061e2d]
+
+ * tsgetgrpw.c:
+ Passwd and group lookup routines for testsudoers that support
+ alternate passwd and group files.
+ [d7803101d34e]
+
+ * getspwuid.c, pwutil.c:
+ Split off pw/gr cache and dup code into its own file. This allows
+ visudo and testsudoers to use the pw/gr cache too.
+ [ef333d3ffedf]
+
+2005-01-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ Print Defaults info in "sudo -l" output and wrap lines based on the
+ terminal width.
+ [e559eae4250e]
+
+2005-01-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * match.c, testsudoers.c, visudo.c:
+ Only check group vector in usergr_matches() if we are matching the
+ invoking or list user. Always check the group members, even if there
+ was a group vector.
+ [d0c7ceb2a041]
+
+2004-12-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * LICENSE, Makefile.in, fnmatch.3:
+ No longer bundle fnmatch.3
+ [72db4a4ff4e1]
+
+ * CHANGES, TODO:
+ checkpoint
+ [e92781bfd99c]
+
+2004-12-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ sort usage
+ [15e3b876ec2c]
+
+ * sudo.pod:
+ Sort command line options
+ [c1fa56584bc4]
+
+ * def_data.c, def_data.h, def_data.in, defaults.c, logging.c, sudo.c,
+ sudo.pod, sudoers.pod:
+ Add closefrom sudoers option to start closing at a point other than
+ 3. Add closefrom_override sudoers option and -C sudo flag to allow
+ the user to specify a different closefrom starting point.
+ [370652b099d1]
+
+ * pathnames.h.in:
+ Add _PATH_DEVNULL for those without it.
+ [0c4c3e0ceb8b]
+
+ * LICENSE:
+ no more UCB strcasecmp
+ [397a6298e07f]
+
+ * strcasecmp.c:
+ replace BSD licensed one with version derived from pdksh
+ [d7cfda8c57a2]
+
+2004-12-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Fix last commit.
+ [7afb9a180532]
+
+ * sudo.c:
+ Make sure stdin, stdout and stderr are open and dup them to
+ /dev/null if not.
+ [590f387068bd]
+
+2004-12-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c, mon_systrace.c, sudo.c, sudo.h:
+ add sudo_ldap_close
+ [4273a36765a7]
+
+ * fileops.c, gettime.c, sudo.c, sudo_edit.c, utimes.c, visudo.c:
+ Use TIME_WITH_SYS_TIME
+ [c32b59bf15fb]
+
+ * config.h.in, configure, configure.in:
+ Add TIME_WITH_SYS_TIME_H
+ [57cb146f451d]
+
+2004-12-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ Add missing braces to avoid DYLD_FORCE_FLAT_NAMESPACE being set
+ unconditionally on darwin. From Toby Peterson.
+ [d69959681c87]
+
+ * getspwuid.c:
+ Check rbinsert() return value. In the case of faked up entries there
+ is usually a negative response cached that we need to overwrite.
+
+ In pwfree() don't try to zero out a NULL pw_passwd pointer.
+ [00b32d1a48c1]
+
+ * mon_systrace.c:
+ Use the double fork trick to avoid the monitor process being waited
+ for by the main program run through sudo.
+ [e0ce556712ff]
+
+2004-11-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Call initgroups() in -U mode so group matches work normally.
+ [2235bea15283]
+
+ * def_data.h, mkdefaults:
+ Don't print a trailing comma for the last entry in enum def_tupple
+ [c43a96bb31df]
+
+2004-11-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.cat, sudoers.man.in, sudoers.pod:
+ Mention values when lecture, listpw and verifypw are used in boolean
+ context.
+ [a0b5c0abaccf]
+
+ * def_data.c, def_data.in:
+ verifypw when used in a boolean TRUE context should be "all", not
+ "any".
+ [2eb076ddd5e2]
+
+2004-11-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * def_data.in, defaults.c:
+ Allow tuples that can be used as booleans to be used as boolean
+ TRUE. In this case the 2nd possible value of the tuple is used for
+ TRUE.
+ [bd99aa77e88b]
+
+2004-11-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Correct the test for 2-parameter timespecsub
+ [d41c9cb26b97]
+
+ * sudo.h:
+ Add strub struct definitions for passwd, timeval and timespec
+ [c4ce5c43d8c5]
+
+ * config.h.in, configure, configure.in, sudo_edit.c, visudo.c:
+ Add check for 2-argument form of timespecsub (FreeBSD and BSD/OS)
+ and fix a typo in the gettimeofday check.
+ [8ac9893057ce]
+
+2004-11-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * match.c, testsudoers.c:
+ Deal with user_stat being NULL as it is for visudo and testsudoers.
+ [3605a6ff64d0]
+
+ * parse.c, sudo.c, sudo.cat, sudo.h, sudo.man.in, sudo.pod:
+ Add -U option to use in conjunction with -l instead of -u. Add
+ support for "sudo -l command" to test a specific command.
+ [99638789d415]
+
+ * gram.c, gram.y, sudo.c:
+ Set safe_cmnd after sudoers_lookup() if it has not been set.
+ Previously it was set by sudo "ALL" in the parser but at that point
+ the fully-qualified pathname has not yet been found.
+ [ac30d98f8225]
+
+2004-11-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c, testsudoers.c:
+ Correctly handle multiple privileges per userspec and runas
+ inheritence.
+ [a98a965181af]
+
+2004-11-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * defaults.c:
+ Zero out sd_un for each entry in sudo_defs_table in init_defaults.
+ [031d3cd4a848]
+
+2004-11-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * toke.c, toke.l:
+ make per-command defaults work with sudoedit
+ [e56fe33db916]
+
+ * ldap.c, parse.c, sudo.c, sudo.h:
+ Remove the FLAG_NOPASS, FLAG_NOEXEC and FLAG_MONITOR flags. Instead,
+ we just set the approriate defaults variable.
+ [756eeecc1d86]
+
+ * sample.sudoers, sudoers.cat, sudoers.man.in, sudoers.pod:
+ Document per-command Defaults.
+ [92a0f84b91c1]
+
+ * defaults.c, defaults.h, gram.c, gram.h, gram.y, mon_systrace.c,
+ sudo.c, testsudoers.c, toke.c, toke.l, visudo.c:
+ Add support for command-specific Defaults entries. E.g.
+ Defaults!/usr/bin/vi noexec
+ [be3d52bf01cf]
+
+ * defaults.c, match.c, parse.c, parse.h, testsudoers.c:
+ Change an occurence of user_matches() -> runas_matches() missed
+ previously runas_matches(), host_matches() and cmnd_matches() only
+ really need to pass in a list of members. user_matches() still needs
+ to pass in a passwd struct because of "sudo -l"
+ [833b22fc6fa0]
+
+ * parse.c:
+ Check def_authenticate, def_noexec and def_monitor when setting
+ return flags. XXX May be better to just set the defaults directly
+ and get rid of those flags.
+ [b6db22b59d69]
+
+ * alias.c, alloc.c, auth/afs.c, auth/aix_auth.c, auth/bsdauth.c,
+ auth/dce.c, auth/fwtk.c, auth/kerb4.c, auth/kerb5.c, auth/pam.c,
+ auth/passwd.c, auth/rfc1938.c, auth/secureware.c, auth/securid.c,
+ auth/securid5.c, auth/sia.c, auth/sudo_auth.c, check.c, closefrom.c,
+ defaults.c, env.c, error.c, fileops.c, find_path.c, fnmatch.c,
+ getcwd.c, getprogname.c, getspwuid.c, gettime.c, glob.c, goodpath.c,
+ gram.c, gram.y, interfaces.c, ldap.c, logging.c, match.c,
+ mon_systrace.c, parse.c, redblack.c, set_perms.c, snprintf.c,
+ strcasecmp.c, strerror.c, strlcat.c, strlcpy.c, sudo.c, sudo_edit.c,
+ sudo_noexec.c, testsudoers.c, tgetpass.c, toke.c, toke.l, utimes.c,
+ visudo.c, zero_bytes.c:
+ Use: #include <config.h> Not: #include "config.h" That way we get
+ the correct config.h when build dir != src dir
+ [97e5670a442b]
+
+ * Makefile.in:
+ Back out part of rev 1.263; fix -I order
+ [197ea01cad5d]
+
+ * toke.c, toke.l:
+ More robust parsing if #include; could be much better still.
+ [31bc3cd8f045]
+
+ * sudo_edit.c, visudo.c:
+ Make arg splitting in visudo and sudoedit consistent.
+ [7bc74485f246]
+
+ * Makefile.in, alias.c, gram.c, gram.y, parse.h:
+ Split alias routines out into their own file.
+ [d90f633cf9ae]
+
+ * error.h:
+ __attribute__ is already defined in compat.h
+ [676ed3fe9203]
+
+ * visudo.c:
+ quit() should not be __noreturn__ as it is non-void on some
+ platforms.
+ [e528c2b6ba10]
+
+ * auth/fwtk.c, auth/rfc1938.c, auth/securid.c, auth/securid5.c:
+ Add local error/warning functions like err/warn but that call an
+ additional cleanup routine in the error case. This means we no
+ longer need to compile a special version of alloc.o for visudo.
+ [e78e8aae882e]
+
+ * parse.h:
+ Clarify comments about the data structures
+ [ae894e266701]
+
+2004-11-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ Add support for VISUAL and EDITOR containing command line args. If
+ env_editor is not set any args in VISUAL and EDITOR are ignored.
+ Arguments are also now supported in def_editor.
+ [ff7303b8e298]
+
+2004-11-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.h:
+ alias_matches() is no more
+ [b59825e28084]
+
+ * CHANGES, TODO:
+ sync
+ [2b8f5f63c1de]
+
+ * Makefile.in:
+ When regenerating the parser, don't replace gram.h unless it has
+ changed.
+ [819949668018]
+
+ * Makefile.in:
+ remove Makefile.binary for distclean
+ [351eec8d00b2]
+
+ * env.c:
+ Preserve KRB5CCNAME in zero_env() and add a paranoia check to make
+ sure we can't overflow new_env.
+ [3284d17b9c6d]
+
+ * sudo_edit.c:
+ paranoia when stripping trailing slashes from tempdir.
+ [012f1aa2b81f]
+
+ * sudo.c:
+ Set user_ngroups to 0 if getgroups() returns an error.
+ [c46d43e9449a]
+
+2004-11-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, sudo.c:
+ Add configure check for getgroups()
+ [5d8a214e2cef]
+
+ * ldap.c:
+ Use supplementary group vector in struct sudo_user.
+ [3d0c463c034d]
+
+ * match.c:
+ Only do string comparisons on the group members if there is no
+ supplemental group list.
+ [be1c8362f7ef]
+
+ * CHANGES, TODO:
+ sync
+ [db188bc5b975]
+
+ * sudo_edit.c:
+ On Digital UNIX _PATH_VAR_TMP doesn't end with a trailing slash so
+ chop off any trailing slashes we see and add an explicit one.
+ [e1b477dafee1]
+
+ * match.c:
+ remove bogus XXX comment
+ [8aecb8a28d40]
+
+ * match.c:
+ Get rid of alias_matches and correctly fall through to the non-alias
+ cases when there is no alias with the specified name.
+ [2cd555246f09]
+
+ * getspwuid.c:
+ Cache non-existent passwd/group entries too.
+ [8de9a467d271]
+
+ * gram.c:
+ regen
+ [9ece18c58f36]
+
+ * getspwuid.c:
+ fix typo
+ [9a7ae371eac1]
+
+ * check.c, getspwuid.c, glob.c, ldap.c, logging.c, match.c,
+ mon_systrace.h, sudo.c, sudo.h, testsudoers.c, visudo.c:
+ Implement group caching and use the passwd and group caches
+ throughout.
+ [f1d8c5015169]
+
+2004-11-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * match.c:
+ Properly negate the return value of alias_matches() when
+ appropriate.
+ [ce59c4ce77ad]
+
+ * match.c:
+ Make hostname_matches() return TRUE for a match, else FALSE like the
+ caller expects.
+ [1dc03902d3a2]
+
+ * Makefile.in:
+ Add missing dependencies on gram.h
+ [4f94bbb1d50c]
+
+ * match.c:
+ Use runas_matches in alias_matches() now that we have it.
+ [284d22e91178]
+
+ * parse.c, parse.h:
+ Expand aliases in "sudo -l" mode
+ [f67a38b79c44]
+
+ * gram.y, match.c:
+ Use ALIAS for the member type when storing an alias instead of
+ HOSTALIAS/RUNASALIAS/CMNDALIAS/USERALIAS since match.c relies on the
+ more generic type. Expand runas_matches instead of calling
+ user_matches() inside of it since user_matches() looks up
+ USERALIASes, not RUNASALIASes.
+ [52004d75232b]
+
+ * CHANGES, getspwuid.c:
+ Paranoia; zero out pw_passwd before freeing passwd entry.
+ [bd1b22638f00]
+
+ * LICENSE, Makefile.in, alloc.c, check.c, config.h.in, configure,
+ configure.in, defaults.c, emul/err.h, env.c, err.c, error.c,
+ error.h, find_path.c, interfaces.c, logging.c, mon_systrace.c,
+ sudo.c, sudo.h, sudo_edit.c, testsudoers.c, visudo.c:
+ Add local error/warning functions like err/warn but that call an
+ additional cleanup routine in the error case. This means we no
+ longer need to compile a special version of alloc.o for visudo.
+ [25000b676cfe]
+
+ * match.c:
+ Use userpw_matches() to compare usernames, not strcmp(), since the
+ latter checks for "#uid".
+ [fcbe4b859f66]
+
+ * getspwuid.c, mon_systrace.c, mon_systrace.h, sudo.c:
+ Cache passwd db entries in 2 reb-black trees; one indexed by uid,
+ the other by user name. The data returned from the cache should be
+ considered read-only and is destroyed by sudo_endpwent().
+ [ee2418ff3f86]
+
+ * match.c:
+ add cast to uid_t
+ [eb6415302d84]
+
+ * gram.y:
+ missing free in alias_destroy
+ [572ecb680ad8]
+
+ * redblack.c:
+ Can't use rbapply() for rbdestroy since the destructor is passed a
+ data pointer, not a node pointer.
+ [11ce713830c0]
+
+ * getspwuid.c, logging.c, sudo.c, sudo.h:
+ Create and use private versions of setpwent() and endpwent() that
+ set/end the shadow password file too.
+ [616bc76d23bf]
+
+ * gram.c, gram.h, gram.y, match.c, parse.h, testsudoers.c, visudo.c:
+ Store aliases in a red-black tree.
+ [ce017d540416]
+
+ * Makefile.in, redblack.c, redblack.h:
+ red-black tree implementation
+ [cd5586e8f48b]
+
+ * visudo.c:
+ Edit all sudoers file if there were unused or undefined aliases and
+ we are in strict mode.
+ [b6d5f5bb7262]
+
+2004-11-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, def_data.c, def_data.h, def_data.in, defaults.c, env.c,
+ find_path.c, sudoers.cat, sudoers.man.in, sudoers.pod, visudo.c:
+ Bring back the "secure_path" Defaults option now that Defaults take
+ effect before the path is searched.
+ [2e52c0e27606]
+
+2004-11-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c, parse.c:
+ A user can always list their own entries, even with -u. Better error
+ message when failing to list another user's entries.
+ [e2e24deb0071]
+
+ * parse.c, sudo.c, sudo.h:
+ The syntax to list another user's entries is now "-u otheruser -l".
+ Only root or users with sudo "ALL" may list other user's entries.
+ [3c0657e8f5fe]
+
+ * sudo.cat, sudo.man.in, sudo.pod:
+ Update env variable info in SECURITY NOTES
+ [299716071024]
+
+ * env.c:
+ strip CDPATH too
+ [9b97643b26f9]
+
+ * env.c:
+ strip exported bash functions from the environment.
+ [9e5090c8284f]
+
+2004-10-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Only reset sudo_user.pw based on SUDO_USER environment variables for
+ real commands and sudoedit. This avoids a confusing message when a
+ user tries "sudo -l" or "sudo -v" and is denied.
+ [3ea6d0053274]
+
+ * gram.c, gram.y, parse.h:
+ Extend LIST_APPEND to deal with appending lists too
+ [d963e42f622f]
+
+2004-10-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ Convert some bitwise AND to ISSET
+ [130dc40d268e]
+
+ * lex.yy.c, toke.c:
+ toke.c replaces lex.yy.c
+ [048858df79e7]
+
+ * CHANGES, TODO:
+ sync
+ [d19e7abf251c]
+
+ * BUGS:
+ new parser fixes most of the outstanding bugs
+ [0891f66e3758]
+
+ * configure:
+ regen
+ [1a3358cc7283]
+
+ * visudo.c:
+ Rework for the new parser. Now checks for unused aliases in sudoers.
+ [ad462ede3094]
+
+ * testsudoers.c:
+ Rewrite for the new parser. Now supports a -d flag (dump) and adds a
+ -h flag (host). It now defaults to the local hostname unless
+ otherwise specified.
+ [1b69685cc601]
+
+ * sudo.h:
+ Add new prototypes. Remove NOMATCH/UNSPEC (now in parse.h)
+ [2e4fb3abfef0]
+
+ * sudo.c:
+ Update for new parse. We now call find_path() *after* we have
+ updated the global defaults based on sudoers. Also adds support for
+ listing other user's privs if you are root.
+ [cf3db9fc3024]
+
+ * mon_systrace.c:
+ Working LDAP support; also remove a now-unneeded rewind().
+ [649ecf1baf6b]
+
+ * logging.c, logging.h:
+ Add NO_STDERR flag.
+ [6cb935af94e0]
+
+ * ldap.c:
+ Split sudo_ldap_check() into three pieces: sudo_ldap_open(),
+ udo_ldap_update_defaults() and sudo_ldap_check(). This allows us to
+ connecto to LDAP, apply the default options, find the command in the
+ user's path, and then check whether the user is allowed to run it.
+ The important thing here is that the default runas user may be
+ specified as a default option and that needs to be set before we
+ search for the command.
+ [fc0426abc6f1]
+
+ * ldap.c:
+ Add casts to unsigned char for isspace() to quiet a gcc warning.
+ [e5358e3df439]
+
+ * defaults.h:
+ Add prototype for update_defaults()
+ [564dac3db74e]
+
+ * defaults.c:
+ Don't warn about line numbers now that we operate on a set of data
+ structures (or LDAP) and not a file.
+ [bcd9ffb9b67c]
+
+ * config.h.in:
+ No long use lsearch()
+ [9d048c587319]
+
+ * Makefile.in:
+ Update for new and changed file names.
+ [6f424a7c4515]
+
+ * LICENSE:
+ no more BSD lsearch.c
+ [463a96d89026]
+
+ * match.c:
+ foo_matches() routines now live in match.c Added user_matches(),
+ runas_matches(), host_matches(), cmnd_matches() and alias_matches()
+ that operate on the parsed sudoers file.
+ [b14da8a0567e]
+
+ * parse.lex, toke.l:
+ Move parse.lex -> toke.l Rename buffer_frob() -> switch_buffer()
+ WORD no longer needs to exclude '@' kill yywrap()
+ [a922294eb7b7]
+
+ * gram.c, gram.h, gram.y, parse.c, parse.h, parse.yacc, sudo.tab.c,
+ sudo.tab.h:
+ Rewritten parser that converts sudoers into a set of data
+ structures. This eliminates ordering issues and makes it possible to
+ apply sudoers Defaults entries before searching for the command.
+ [30d2ec4d203c]
+
+ * configure.in, emul/search.h, lsearch.c:
+ We won't be using lsearch() any longer.
+ [29c4d54bfac0]
+
+ * ldap.c:
+ sudo should not send mail if someone who runs 'sudo -l' has no
+ entry.
+ [6fc27a69fd9c]
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat,
+ visudo.man.in:
+ regen
+ [8166347917f3]
+
+ * visudo.pod:
+ Update warnings to match new visudo
+ [004c0766798f]
+
+ * sudoers.pod:
+ The new parser doesn't have the old ordering constraints.
+ [ffd43bd08661]
+
+ * sudo.pod:
+ Document that -l now takes an optional username argument
+ [278f9557de8b]
+
+2004-10-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * RUNSON:
+ AIX 5.2.0.0 works
+ [523acd29d858]
+
+ * ldap.c:
+ If LDAP_OPT_SUCCESS is not defined, use LDAP_SUCCESS instead. Fixes
+ a compilation problem with Solaris 9's native LDAP.
+
+ Set FLAG_MONITOR when needed.
+ [35824ade672d]
+
+2004-10-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mon_systrace.c:
+ Call sudo_goodpath() *after* changing the cwd to match the traced
+ process. Fixes relative paths.
+ [12ee111d0ad7]
+
+2004-10-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * testsudoers.c:
+ Kill set_perms() stub--it is no longer needed.
+ [116ed702935d]
+
+2004-10-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.cat, sudoers.man.in, sudoers.pod:
+ stay_setuid now requires set_reuid() or setresuid()
+ [8511f67e25d5]
+
+ * INSTALL, PORTING, TROUBLESHOOTING, config.h.in, configure,
+ configure.in, set_perms.c, sudo.c, sudo.h:
+ Kill use of POSIX saved uids; they aren't worth bothering with.
+ [b3b1f19f18c1]
+
+2004-10-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * glob.c:
+ remove call to issetugid()
+ [63f2e492c08f]
+
+ * sudoers.cat, sudoers.man.in, sudoers.pod:
+ Remove warning about wildcards. Now that we use glob() the bug is
+ fixed.
+ [b15729d32266]
+
+ * parse.c:
+ Use glob(3) instead of fnmatch(3) for matching pathnames and stat
+ each result that matches the basename of the user's command. This
+ makes "cd /usr/bin ; sudo ./blah" work when sudoers allows
+ /usr/bin/blah. Fixes bug #143.
+ [e31eb6310340]
+
+ * config.h.in, configure, configure.in:
+ Define HAVE_EXTENDED_GLOB for extended glob (GLOB_TILDE and
+ GLOB_BRACE)
+ [677ed6661e17]
+
+ * config.h.in, configure, configure.in:
+ Check for a glob() that supports GLOB_BRACE and GLOB_TILDE
+ [aaa2329dd266]
+
+ * LICENSE:
+ reference glob
+ [bedc9a923423]
+
+ * emul/glob.h:
+ 4.4BSD glob(3) with fixes from OpenBSD and some unneeded extensions
+ removed.
+ [0335cf31fb1e]
+
+ * glob.c:
+ 4.4BSD glob(3) with fixes from OpenBSD and some unneeded extensions
+ removed.
+ [81799451473c]
+
+2004-10-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mon_systrace.c:
+ Just return if STRIOCINJECT or STRIOCREPLACE fail. It probably means
+ we are out of space in the stack gap...
+ [5b02b702021e]
+
+ * CHANGES:
+ sync
+ [be3826273e56]
+
+ * mon_systrace.c:
+ Take a stab at ldap sudoers support here.
+ [9d023695b0de]
+
+ * mon_systrace.c, mon_systrace.h:
+ Detach from tracee on SIGHUP, SIGINT and SIGTERM. Now "sudo reboot"
+ doesn't cause reboot to inadvertanly kill itself.
+ [d4aab2365610]
+
+ * mon_systrace.c:
+ put "monitor" in the proctitle, not "systrace"
+ [9a9025767d86]
+
+ * mon_systrace.c:
+ When modifying the environment, don't replace envp when we can get
+ away with just rewriting pointers in the traced process.
+ [c03622f7a2e2]
+
+ * mon_systrace.c, mon_systrace.h:
+ Add environment updating via STRIOCINJECT (if available).
+ [037291016870]
+
+ * sudoers.cat, sudoers.man.in:
+ regen
+ [869acc511046]
+
+2004-10-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lex.yy.c:
+ regen
+ [4e61a9bd3c97]
+
+ * parse.lex:
+ Fix bug introduced in unput() removal; want yyless(0) not yyless(1)
+ [b70d7bd6e147]
+
+ * mon_systrace.c:
+ Include file is now mon_systrace.h
+ [ead4e36d92ae]
+
+ * Makefile.in, configure, configure.in, def_data.c, def_data.h,
+ def_data.in, lex.yy.c, parse.c, parse.h, parse.lex, parse.yacc,
+ sudo.c, sudo.h, sudo.tab.c, sudo.tab.h, sudoers.pod:
+ No longer call it tracing, it is now "monitoring" which should be
+ more a obvious name to non-hackers.
+ [aa811ded0789]
+
+2004-10-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mon_systrace.c, mon_systrace.h:
+ Fix some XXX
+ [a271072dacc6]
+
+ * mon_systrace.c, mon_systrace.h:
+ No need to include syscall.h, use 1024 as the max # of entries (the
+ max that systrace(4) allows).
+
+ Only need to use SYSTR_POLICY_ASSIGN once
+
+ Change check_syscall() -> find_handler() and have it return the
+ handler instead of just running it. We need this since handler now
+ have two parts: one part that generates and answer and another that
+ gets called after the answer is accepted (to do logging).
+
+ Add some missing check_exec for emul execv
+ [a89d243f0525]
+
+ * sample.pam, sample.sudoers, sample.syslog.conf, sudoers:
+ Add $Sudo$ tags.
+ [6f3fedb0daba]
+
+ * config.h.in:
+ Add missing HAVE_LINUX_SYSTRACE_H
+ [ff75ab7bfc53]
+
+ * Makefile.in:
+ add trace_systrace.o dependency
+ [88a408668ab2]
+
+2004-09-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Also look for systrace.h in /usr/include/linux
+ [98b98b436cf3]
+
+ * mon_systrace.c, mon_systrace.h:
+ Move all struct defs and prototypes into trace_systrace.h and mark
+ all but systace_attach() static.
+ [85511253b570]
+
+ * mon_systrace.c, mon_systrace.h:
+ Add support for tracing emulations. At the moment, all emulations
+ are compiled in. It might make sense to #ifdef them in the future,
+ though this impeeds readability.
+ [87bb50abf277]
+
+ * Makefile.in, configure, configure.in:
+ rename systrace.c -> trace_systrace.c
+ [31cfa4407d93]
+
+ * parse.yacc, sudo.tab.c:
+ Allow this to build with a K&R compiler again
+ [32876af5bb98]
+
+ * TODO:
+ sync
+ [46865bd70f7c]
+
+ * compat.h, sudo.c, visudo.c:
+ Use __attribute__((__noreturn__))
+ [65bbad71fe89]
+
+ * visudo.c:
+ Exit() takes a negative value to indicate it was not called via
+ signal.
+ [b93032ed7b60]
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat,
+ visudo.man.in:
+ regen
+ [45bcf4661558]
+
+ * Makefile.in, visudo.c:
+ Define Err() and Errx() that are like err() and errx() but call
+ Exit() instead of exit(). Build private copy of alloc.o for visudo
+ that calls Err() and Errx().
+ [c6d02bf42edd]
+
+2004-09-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lex.yy.c, sudo.tab.c:
+ regen
+ [39de7e7c59da]
+
+ * CHANGES:
+ sync
+ [ba481d9ed1aa]
+
+ * visudo.c:
+ Overhaul visudo for editing multiple files: o visudo has been broken
+ out into functions (more work needed here) o each file is now edited
+ before sudoers is re-parsed o if a #include line is added that file
+ will be edited too
+
+ TODO: o cleanup temp files when exiting via err() or errx() o
+ continue breaking things out into separate functions
+ [80c35cf534eb]
+
+ * parse.lex, sudo.c, sudo.h, testsudoers.c, visudo.c:
+ Add keepopen arg to open_sudoers that open_sudoers can use to
+ indicate to the caller that the fd should not be closed when it is
+ done with it. To be used by visudo to keep locked fds from being
+ closed prematurely (and thus losing the lock).
+ [f330fe632470]
+
+ * parse.yacc, sudo.c:
+ Add errorfile global that contains the name of the file that caused
+ the error.
+ [98079c7a37ed]
+
+ * parse.lex:
+ return COMMENT to yacc grammar for a #include line
+ [2024a8de4fa8]
+
+ * parse.lex:
+ Remove us of unput() in favor of yyless() which is cheaper.
+ [c61291902beb]
+
+ * parse.yacc:
+ Allow an empty sudoers file.
+ [62fb111db2e7]
+
+2004-09-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mon_systrace.c:
+ Rewind sudoers_fp now that sudoers_lookup() doesn't do it for us.
+ [9e15869ef597]
+
+ * lex.yy.c, sudo.tab.c:
+ regen
+ [c29bdd43bfad]
+
+ * visudo.c:
+ Do signal setup before calling edit_sudoers(). Don't shadow the
+ "quiet" global.
+ [74252efd09ff]
+
+ * visudo.c:
+ If a sudoers file includes other files, edit those too. Does not yes
+ deal with creating the new includes files itself.
+ [06af7b9c173f]
+
+ * testsudoers.c:
+ init_parser now takes a path
+ [b5ee186eb192]
+
+ * parse.c, parse.h, parse.lex, parse.yacc:
+ More scaffolding for dealing with multiple sudoers files: o
+ init_parser() now takes a path used to populate the sudoers global o
+ the sudoers global is used to print the correct file in yyerror() o
+ when switching to a new sudoers file, perserve old file name and
+ line number
+ [d9be4970b8bd]
+
+ * Makefile.in, pathnames.h.in:
+ Kill _PATH_SUDOERS_TMP; it is not meaningful now that we can have
+ multiple sudoers files.
+ [6ccc4e921c43]
+
+ * parse.c, sudo.c:
+ Rewind sudoers_fp in open_sudoers() instead of sudoers_lookup() so
+ we start at the right file position when reading include files.
+ [91fcb961e7a4]
+
+ * sudoers.pod:
+ document #include
+ [fbb92a25a726]
+
+ * lex.yy.c:
+ regen
+ [50cd7a4c9dff]
+
+ * parse.lex:
+ Add max depth of 128 for the include stack to avoid loops.
+
+ Since yyerror() doesn't stop parsing, pass return values back to
+ yylex and call yyterminate() on error.
+ [e79dbffb729d]
+
+2004-09-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ document tracing
+ [165a467eadd8]
+
+ * sudo.pod:
+ Mention PREVENTING SHELL ESCAPES section of sudoers man page
+ [3217ccecd834]
+
+ * lex.yy.c, sudo.tab.c:
+ regen
+ [fbd58d1d3a76]
+
+ * parse.lex:
+ Add support for #include in sudoers (visudo support TBD)
+ [a78015ca81af]
+
+ * parse.yacc:
+ make yyerror()'s argument const
+ [7d8e168c019a]
+
+ * testsudoers.c, visudo.c:
+ Add open_sudoers() stubs.
+ [087466787198]
+
+ * sudo.c, sudo.h:
+ Rename check_sudoers() open_sudoers() and make it return a FILE *
+ [142fc511fc65]
+
+2004-09-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * BUGS, INSTALL, INSTALL.binary, Makefile.in, README, configure.in,
+ version.h:
+ Crank version
+ [1adc3f839480]
+
+ * Makefile.in, sudo.psf:
+ Better HP-UX depot construction
+ [2d952b000e63]
+
+2004-09-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mon_systrace.c:
+ o Made children global so check_exec() can lookup a child. o
+ Replaced uid in struct childinfo with struct passwd * (for runas) o
+ new_child() now takes a parent pid so the runas info can be
+ inherited o Added find_child() to lookup a child by its pid o
+ update_child() now fills in a struct passwd o Converted the big
+ if/else mess in set_policy to a switch o Syscalls that change uid
+ are now "ask" so we get SYSTR_MSG_UGID events
+ [29b9ea3f09a3]
+
+ * getspwuid.c:
+ Add flag to sudo_pwdup that indicates whether or not to lookup the
+ shadow password. Will be used to a struct passwd that has the shadow
+ password already filled in.
+ [e19d43dd7238]
+
+ * mon_systrace.c:
+ add missing increment of addr in read_string()
+ [f9eb0f060cb6]
+
+ * mon_systrace.c:
+ Remove bogus call to update_child() and some cosmetic fixes
+ [701ab0b97fef]
+
+ * mon_systrace.c:
+ Don't leak /dev/systrace fd to tracee Make initialized global for
+ simplicity If STRIOCATTACH returns EBUSY we are already being traced
+ Check for user_args == NULL in setproctitle() call Add missing calls
+ to STRIOCANSWER
+ [1956edf9bc3a]
+
+ * sudo.c:
+ g/c sudo_pwdup proto
+ [b7c4d6249ecb]
+
+ * Makefile.in, sudo.psf:
+ Add target for building a depot file
+ [357019efd99b]
+
+ * mon_systrace.c:
+ trim includes
+ [501534428471]
+
+2004-09-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lex.yy.c, sudo.tab.c, sudo.tab.h:
+ regen
+ [52fd250c6986]
+
+ * INSTALL:
+ document --with-systrace
+ [79623927c94e]
+
+ * config.h.in, configure, configure.in:
+ Add check for setproctitle
+ [1730cf1c26ed]
+
+ * mon_systrace.c:
+ pass struct str_msg_ask in to syscall checker so it can set the
+ error code
+ [1703fd2fdef6]
+
+ * mon_systrace.c:
+ systrace(4) support for sudo. On systems with the systrace(4) kernel
+ facility (OpenBSD, NetBSD, Linux w/ patches) sudo can intercept exec
+ calls and check the exec args against the sudoers file. In other
+ words, sudo can now control subcommands and shell escapes.
+ [928c9217c386]
+
+ * sudo.c, sudo.h:
+ Call systrace_attach() if FLAG_TRACE is set.
+ [014ba9402fa5]
+
+ * parse.c, parse.h, parse.lex, parse.yacc, sudo.h:
+ Add trace Defaults option and TRACE/NOTRACE tags and set FLAG_TRACE
+ [a99904db5e56]
+
+ * parse.c, sudo.c:
+ Don't close sudoers_fp, keep it open and set close on exec flag
+ instead.
+ [43a9fec60bee]
+
+ * def_data.c, def_data.h, def_data.in:
+ Add trace option
+ [5b643b86730a]
+
+ * Makefile.in:
+ Add systrace
+ [47a0519c427c]
+
+ * INSTALL:
+ SunOS /bin/sh blows up with configure
+ [005a23cc5615]
+
+ * configure, configure.in:
+ Include sys/param.h before systrace.h
+ [9345bc8efecf]
+
+ * configure:
+ regen
+ [a8f53fcbb254]
+
+ * pathnames.h.in:
+ _PATH_DEV_SYSTRACE
+ [d2ad1e492a00]
+
+ * configure.in:
+ line up options in --help
+ [fa51f2821d09]
+
+ * config.h.in, configure.in:
+ Add --with-systrace
+ [a264d54bc413]
+
+2004-09-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [a4dad0bcc523]
+
+ * aclocal.m4, configure.in:
+ make this work with autoconf-2.59
+ [c4a92b6a684a]
+
+2004-09-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo_edit.c:
+ Simplify logic around open & stat of files and do sanity on edited
+ file even if we lack fstat (still racable but worth doing).
+ [adda65ade70c]
+
+2004-09-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * HISTORY:
+ Add support url
+ [bf6590fbde9f]
+
+ * Makefile.in:
+ versino 1.6.8p1
+ [b84ebfaf1552] [SUDO_1_6_8p1]
+
+ * CHANGES:
+ more changes for 1.6.8p1
+ [e23a9c0393b6]
+
+ * version.h:
+ 1.6.8p1
+ [872f14504b5f]
+
+ * CHANGES, sudo_edit.c:
+ Add sanity check so we don't try to edit something other than a
+ regular file.
+ [350134ec6d4e]
+
+2004-09-15 Aaron Spangler <aaron777@gmail.com>
+
+ * CHANGES:
+ sync
+ [3091ca9eae00]
+
+ * INSTALL:
+ document --with-ldap-conf-file
+ [0e2cd6b896f1]
+
+2004-09-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, ins_csops.h:
+ political correctness strikes again
+ [428e8bc77f55]
+
+ * RUNSON:
+ sync
+ [27f44bd423dc]
+
+2004-09-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.binary.in, Makefile.in:
+ Install sudoedit man link
+ [19a55234fc1f]
+
+ * INSTALL:
+ Update PAM note and mention where HP-UX users can download gcc
+ binaries.
+ [d37cdbbabfd4]
+
+ * Makefile.in:
+ libtool wants to install stuff from .libs so fake one up for binary
+ installations.
+ [a681bc6fcfba]
+
+ * Makefile.binary.in:
+ rm -f old sudoedit link instead of using ln -f set LIBTOOL correctly
+ [3e0c4b3372cc]
+
+ * Makefile.in:
+ Deal with "uname -m" having slashes in it rm -f old sudoedit link
+ instead of using ln -f
+ [cff33fb97e5b]
+
+ * Makefile.binary, Makefile.binary.in:
+ Makefile.binary -> Makefile.binary.in for config.status substitution
+ Add support for installing noexec bits
+ [37d8bb3483c6]
+
+ * Makefile.in:
+ Copy noexec bits into binary dists too No longer use my old arch
+ script for making binary dists
+ [e7058bab9e33]
+
+ * Makefile.binary:
+ Install sudoedit link.
+ [417d1e101711]
+
+2004-09-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * emul/utime.h:
+ avoid __P so there is no need for compat.h to be included
+ [6d8d1f1abf7d]
+
+ * utimes.c:
+ Don't use HAVE_UTIME_H before including config.h.
+ [013b7bb61181]
+
+2004-09-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat.h:
+ Fix Solatis futimes macro
+ [d4eda2ca0d29]
+
+2004-09-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo_edit.c:
+ Rename ots -> omtim for improved readability.
+ [127ca5bb297c]
+
+2004-09-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo_edit.c:
+ Redo changes in revision 1.7. Don't really need to keep the temp
+ file open; re-opening it with the invoking user's euid is
+ sufficient.
+ [55a883165a95]
+
+ * CHANGES:
+ sync
+ [9015b291170d]
+
+ * sudo.cat, sudo.man.in:
+ regen
+ [c0313f6ed783]
+
+ * sudo.pod:
+ back out revision 1.70; it is no long applicable
+ [b641d503aff6]
+
+ * env.c:
+ Let the loader initialize nep
+ [bec192139b02]
+
+ * config.h.in, configure, configure.in:
+ Removed unneed check for fchown Add check for gettimeofday Move
+ autoheader template stuff into separate AH_TEMPLATE lines
+ [bfc0edbd43f2]
+
+ * check.c, compat.h, fileops.c, sudo.h, sudo_edit.c, visudo.c:
+ Use timespec throughout.
+ [1a178a23b69b]
+
+ * Makefile.in:
+ gettime.[co]
+ [6aeb48a7ab7f]
+
+ * gettime.c:
+ function to return the current time in a struct timespec
+ [bf8eb12cb63f]
+
+ * utimes.c:
+ Not a darpa-sponsored file.
+ [121ce5e2036c]
+
+2004-09-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat.h, config.h.in, configure, configure.in:
+ Add a check for struct timespec and provide it for those without.
+ [42124055030d]
+
+ * config.h.in, configure, configure.in, sudo_edit.c:
+ Add checks for st_mtim and st_mtimespec and add macros for pulling
+ the mtime sec and nsec out of struct stat. These are used in
+ sudo_edit() to better tell whether or not the file has changed.
+ [23debfbb3fab]
+
+ * check.c, fileops.c, sudo.h, sudo_edit.c, visudo.c:
+ Add an extra param to touch() for nsec
+ [56f7a4ba8ddb]
+
+ * sudo_edit.c:
+ Call mkstemp() as the in invoking user so we don't have to chown the
+ file later. Only touch() the temp file if we can do it via the file
+ descriptor. Don't check for modification of the temp file if we lack
+ fstat(). Catch errors read()ing the temp file.
+ [665f52c70836]
+
+ * fileops.c:
+ If path is NULL and fd == -1 return -1.
+ [757a518a824c]
+
+ * sudo_edit.c:
+ closefrom() is overkill, the only extra fds are the ones we opened
+ so just close those in the child.
+ [f361c9d2a1f4]
+
+ * Makefile.in, aclocal.m4, check.c, compat.h, config.h.in, configure,
+ configure.in, fileops.c, sudo.h, sudo_edit.c, utime.c, utimes.c,
+ visudo.c:
+ Use utimes() and futimes() instead of utime() in touch(), emulating
+ as needed. Not all systems are able to support setting the times of
+ an fd so touch() takes both an fd and a file name as arguments.
+ [3d9276f29717]
+
+2004-09-07 Aaron Spangler <aaron777@gmail.com>
+
+ * env.c:
+ Rare SEGV
+ [8995f828782d]
+
+2004-09-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat,
+ visudo.man.in:
+ regen
+ [b8e9406711c5]
+
+ * sudo.pod, sudoers.pod, visudo.pod:
+ Add SUPPORT section and re-order some of the sections to match the
+ order we use in OpenBSD.
+ [fa37bd917e2c]
+
+2004-09-06 Aaron Spangler <aaron777@gmail.com>
+
+ * env.c:
+ Openldap ~/.ldaprc fix
+ [1a37afe6850f]
+
+2004-09-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod:
+ Talk about how the editor must write its changes to the original
+ file and not just use rename(2).
+ [c55ed91c5ee9]
+
+ * CHANGES:
+ sync
+ [62af26bd37a2]
+
+ * sudo_edit.c:
+ Keep the temp file open instead of re-opening after the editor has
+ exited.
+ [de41eeb6dcf2]
+
+ * sample.pam:
+ Update for current redhat/fedora core.
+ [8cf083077333]
+
+2004-09-03 Aaron Spangler <aaron777@gmail.com>
+
+ * README.LDAP:
+ tls_ examples
+ [ba783d88a034]
+
+2004-09-02 Aaron Spangler <aaron777@gmail.com>
+
+ * ldap.c:
+ config tls_* options
+ [0b0e0797b3b9]
+
+2004-08-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ No need for -lcrypt when using pam.
+ [41fff3a53e68]
+
+2004-08-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [75820aecce2c]
+
+2004-08-27 Aaron Spangler <aaron777@gmail.com>
+
+ * configure.in, ldap.c, pathnames.h.in:
+ Allow --with-ldap-conf-file option to override LDAP_CONF
+ [c9909bc484a5]
+
+ * ldap.c:
+ cleanup debug message
+ [1f6ca4824d8d]
+
+2004-08-26 Aaron Spangler <aaron777@gmail.com>
+
+ * README.LDAP:
+ more config info
+ [f2e7147fd507]
+
+2004-08-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TODO, find_path.c, goodpath.c, parse.c, sudo.c, sudo.h, visudo.c:
+ Add cmnd_base to struct sudo_user and set it in init_vars(). Add
+ cmnd_stat to struct sudo_user and set it in sudo_goodpath(). No
+ longer use gross statics in command_matches(). Also rename some
+ variables for improved clarity.
+ [7169a6c7bea4]
+
+2004-08-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ document HP's crippled compiler deficiency.
+ [c405ea5a8d4c]
+
+ * INSTALL:
+ Fix some thinkos in --with-editor and --with-env-editor
+ descriptions. Noticed by Norihiko Murase.
+ [dd781de1c985]
+
+ * configure, configure.in:
+ --with-noexec takes an optional PATH argument.
+ [8f6ab77f22cc]
+
+ * INSTALL:
+ document --with-noexec
+ [50cb1fc627ce]
+
+2004-08-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * RUNSON, TODO:
+ sync
+ [f2503bd13373] [SUDO_1_6_8]
+
+ * sudo_edit.c:
+ Better warning message when sudoedit is unable to write to the
+ destination file.
+ [f78c18f2ffa8]
+
+ * sudo.cat, sudo.man.in:
+ regen
+ [7e2bf63d6d9a]
+
+ * sudo.pod:
+ Don't italicize the string "sudoedit"
+ [c691643bd269]
+
+2004-08-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * HISTORY:
+ Mention GratiSoft.
+ [dc53de581b2d]
+
+2004-08-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.tab.c:
+ regen
+ [8ae0484dfc38]
+
+ * parse.yacc:
+ Reset used_runas to FALSE when re-intializing the parser.
+ [b7403f353a02]
+
+2004-08-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.guess:
+ Correct OpenBSD mips support
+ [314fc7afc165]
+
+ * config.guess:
+ Add OpenBSD/mips
+ [ac87d0a773ef]
+
+2004-08-07 Aaron Spangler <aaron777@gmail.com>
+
+ * README.LDAP:
+ More behavior notes
+ [13be1d212b47]
+
+ * README.LDAP:
+ Updates on current behavior
+ [d498a8866d6f]
+
+2004-08-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod:
+ =back does not take an indentlevel (makes no difference to formatted
+ files).
+ [e5f479e24fa8]
+
+ * sudoers.pod:
+ =back does not take an indentlevel (makes no difference to formatted
+ files).
+ [9c8523bb382a]
+
+ * CHANGES:
+ new
+ [2dbd9aba8b33]
+
+ * sudo.c:
+ Consistency. Use same error for bad -u #uid when targetpw is set as
+ we do when a bad -u username is specified.
+ [922961c4a9d6]
+
+ * TODO:
+ Add checksum idea from Steve Mancini
+ [e6ece1b766ba]
+
+ * sudo.cat, sudo.man.in:
+ regen
+ [f93d41fc38b1]
+
+ * sudoers.cat, sudoers.man.in:
+ regen
+ [370d2317829f]
+
+ * sudo.pod, sudoers.pod:
+ Document the restriction on uids specified via -u when targetpw is
+ set.
+ [878fedb455db]
+
+ * sudo.c:
+ Error out when targetpw is enabled and sudo is run with -u #uid but
+ #uid does not exist in the passwd database. We can't do target
+ authentication when the target is not in passwd!
+ [27c5888c86eb]
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in:
+ regen
+ [ceb65711050c]
+
+ * TODO:
+ Some more todo for the next release.
+ [7b7417be7601]
+
+ * INSTALL:
+ Make it clear that PAM should be used for DCE support when possible.
+ [7502029fd385]
+
+ * sudoers.pod:
+ o Document problems with wildcards and relative paths. o Make the
+ order requirements more prominent. o Change a "set" to "reset" for
+ clarity.
+ [bacdd181b33f]
+
+2004-08-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod:
+ Mention --with-secure-path, not SECURE_PATH.
+ [41283ddde5e1]
+
+2004-08-03 Aaron Spangler <aaron777@gmail.com>
+
+ * ldap.c:
+ reflect changes to parse.c
+ [8880fe9b724d]
+
+2004-08-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.tab.c:
+ regen
+ [a57658ca9177]
+
+ * parse.yacc:
+ Don't pass user_cmnd and user_args to command_matches(), just use
+ the globals there. Since we keep state with statics anyway it is
+ misleading to pretend that passing in different cmnd and cmnd_args
+ will work.
+ [a4910bf6032b]
+
+ * parse.c, parse.h, testsudoers.c, visudo.c:
+ Don't pass user_cmnd and user_args to command_matches(), just use
+ the globals there. Since we keep state with statics anyway it is
+ misleading to pretend that passing in different cmnd and cmnd_args
+ will work.
+ [0a2544991fd6]
+
+ * parse.c:
+ Fix a bug introduced in rev. 1.149. When checking for pseudo-
+ commands check for a '/' anywhere in cmnd, not just the first
+ character.
+ [ce98142f03ca]
+
+2004-07-31 Aaron Spangler <aaron777@gmail.com>
+
+ * sudo.man.in, sudo.pod:
+ Clarification thanks to Olivier Blin <oblin@mandrakesoft.com>
+ [a91800e094b1]
+
+ * sudoers.man.in, sudoers.pod:
+ Add ignore_local_sudoers
+ [741ddcbf7083]
+
+ * README.LDAP:
+ Sun One schema definition by Andreas.Bussjaeger@t-systems.com and
+ janth@moldung.no
+ [742c02e07cd9]
+
+2004-07-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ typo
+ [e7cdefbd7a9a]
+
+2004-07-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ sync
+ [734dafc4a85e]
+
+ * parse.c:
+ Parse sudoers file as PERM_RUNAS not PERM_ROOT and remove a useless
+ PERM_SUDOERS. Restore to PERM_ROOT upon exit of the parse.
+ [151b7f593568]
+
+2004-07-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ PAM change
+ [d8fb6d6a22d0]
+
+2004-07-08 Aaron Spangler <aaron777@gmail.com>
+
+ * ldap.c:
+ Better debugging of ALL command
+ [9db3e84029dc]
+
+2004-07-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ When matching for "sudoedit" in sudoers check both the command the
+ user typed *and* the command that is listed in the sudoers entry.
+ [f36ca1f94095]
+
+2004-07-04 Aaron Spangler <aaron777@gmail.com>
+
+ * ldap.c:
+ Added !command feature
+ [ed539574611b]
+
+2004-06-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/pam.c:
+ Use pam_acct_mgmt() to check for disabled accounts; Brian Farrell
+ [2be8e0e8813a]
+
+2004-06-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * LICENSE:
+ License is ISC-style, not BSD-style
+ [ac0589e1dd5d]
+
+ * CHANGES:
+ sync
+ [16058a30f404]
+
+2004-06-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.cat, sudo.man.in:
+ regen
+ [8820eb9c809b]
+
+ * sudo.pod:
+ o Update some out of date bits to reality o Change the shell promt
+ in examples to bourne-shell style o Clarify some details o Add a
+ CAVEAT about "sudo cd /foo"
+ [b0af373214b6]
+
+ * check.c:
+ Don't ask for a password if invoking user == target user.
+ [dd5c96141132]
+
+ * sudo.c:
+ typo in comment
+ [278d20f9b249]
+
+2004-06-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.cat, sudoers.man.in:
+ regen
+ [9036c6f39eff]
+
+ * sudoers.pod:
+ Expand on NOEXEC a little.
+ [9a13756aebe4]
+
+ * TODO:
+ sync
+ [8d2c1af48de8]
+
+ * visudo.cat, visudo.man.in:
+ regen
+ [3921f01607c8]
+
+ * sudo.tab.c:
+ regen
+ [9338c3d68250]
+
+ * CHANGES, parse.yacc, visudo.c:
+ Add a check in visudo for runas_default being set after it has
+ already been used.
+ [803560986a8a]
+
+ * visudo.pod:
+ Add a check in visudo for runas_default being set after it has
+ already been used.
+ [6700358d7ad8]
+
+ * sudo.tab.c:
+ regen
+ [b60636e2cf63]
+
+ * parse.yacc:
+ Add a MATCHED macro for testing whether foo_matches has been set to
+ TRUE or FALSE. This is more readable than checking for >=0 or < 0.
+ Doesn't change the actual code generated.
+ [f376da8ccdc8]
+
+2004-06-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.cat:
+ regen
+ [6cceb6d6c9bd]
+
+ * sudoers.man.in:
+ regen
+ [5acd12b730b3]
+
+ * sudoers:
+ Correct description of where Defaults specs should go.
+ [868db857630d]
+
+ * sudoers.pod:
+ Correct description of where Defaults specs should go.
+ [6b11ff53d7ad]
+
+ * auth/bsdauth.c, auth/kerb5.c:
+ update (c) year
+ [d72eb434c068]
+
+ * auth/pam.c:
+ update (c) year
+ [87149e0eed50]
+
+ * find_path.c:
+ update (c) year
+ [40c227af9227]
+
+ * ldap.c:
+ update (c) year
+ [f264632488a0]
+
+ * logging.h:
+ update (c) year
+ [3cec76d400ce]
+
+ * testsudoers.c, visudo.c:
+ update (c) year
+ [272c8a53604c]
+
+2004-06-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.tab.c:
+ regen
+ [83408d9e9d2e]
+
+ * auth/bsdauth.c, auth/kerb5.c, auth/pam.c, visudo.c:
+ Remove trailing spaces, no actual code changes.
+ [4c3bf2819293]
+
+ * ldap.c, logging.h, parse.c, parse.yacc, sudo.c, testsudoers.c:
+ Remove trailing spaces, no actual code changes.
+ [c7075d1cbed5]
+
+ * tgetpass.c:
+ Remove trailing spaces, no actual code changes.
+ [96f6e0a24c26]
+
+ * compat.h, defaults.c, env.c:
+ Remove trailing spaces, no actual code changes.
+ [893e83c33795]
+
+ * find_path.c:
+ Remove trailing spaces, no actual code changes.
+ [7ed7099f3c71]
+
+ * getcwd.c:
+ Remove trailing spaces, no actual code changes.
+ [776cc0374547]
+
+ * check.c:
+ Remove trailing spaces, no actual code changes.
+ [f77750f8803b]
+
+ * sudo.tab.c:
+ regen
+ [62e0ed883b31]
+
+ * parse.yacc:
+ Fix a >=0 that should be <0 that was improperly converted when
+ UNSPEC was added.
+ [ad1531a55a49]
+
+ * parse.yacc:
+ Add do {} while(0) around pop macro Set cmnd_matches to UNSPEC, not
+ NOMATCH when resetting it.
+ [ae017a12870a]
+
+ * parse.yacc:
+ Fix pastos introduced in SETNMATCH addition.
+ [6ea1c9d80681]
+
+2004-06-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * README.LDAP:
+ Update for configure changes
+ [637a635da287]
+
+ * sudo.tab.c:
+ regen
+ [4753c2788713]
+
+ * parse.yacc:
+ Add NOMATCH and UNSPEC defines (-1 and -2 respectively) and use
+ these in parse.yacc. Also in parse.yacc initialize the *_matches
+ vars to UNSPEC and add two macros, SETMATCH and SETNMATCH for use
+ when setting *_matches to a value that may be
+ NOMATCH/UNSPEC/TRUE/FALSE.
+ [746b519e41a6]
+
+ * sudo.h:
+ Add NOMATCH and UNSPEC defines (-1 and -2 respectively) and use
+ these in parse.yacc. Also in parse.yacc initialize the *_matches
+ vars to UNSPEC and add two macros, SETMATCH and SETNMATCH for use
+ when setting *_matches to a value that may be
+ NOMATCH/UNSPEC/TRUE/FALSE.
+ [2ba622e15a4d]
+
+ * parse.yacc:
+ Initialize runas to -2, not -1 since we need to be able to
+ distinguish between the initialized value and the value of a non-
+ match when passing along the runas value to multiple commands.
+
+ The result of this is that an unmatched runas is now set to -1, not
+ 0. This is required now that parse.c treats a FALSE value for runas
+ as being explicitly denied.
+ [7791ed3621f6]
+
+2004-06-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * getprogname.c:
+ Error out if argc < 1.
+ [c566cce8dc78]
+
+ * sudo.c, visudo.c:
+ Error out if argc < 1.
+ [ce6b2a9eda3c]
+
+ * configure, configure.in:
+ Add tests for what libs we need to link with for ldap and for
+ whether or not lber.h needs to be explicitly included.
+ [b2e9729cc4e7]
+
+2004-06-03 Aaron Spangler <aaron777@gmail.com>
+
+ * ldap.c:
+ Solaris native LDAP build fix
+ [39929e40eb11]
+
+2004-06-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ldap.c:
+ Set edn to NULL is ldap_get_dn() fails to avoid potential use of an
+ unset variable.
+ [6a4c20a66f98]
+
+ * sudo.h:
+ Add prototype for sudo_ldap_list_matches
+ [443b007a8dab]
+
+ * compat.h:
+ Better check for dirfd macro--we now set HAVE_DIRFD for the macro
+ version too. Added check for dd_fd in `DIR' if no dirfd is found;
+ this is now used to confitionally define the dirfd macro in
+ compat.h.
+ [8d50ff1bbf2a]
+
+ * config.h.in:
+ Better check for dirfd macro--we now set HAVE_DIRFD for the macro
+ version too. Added check for dd_fd in `DIR' if no dirfd is found;
+ this is now used to confitionally define the dirfd macro in
+ compat.h.
+ [34eace4faec8]
+
+ * configure, configure.in:
+ Better check for dirfd macro--we now set HAVE_DIRFD for the macro
+ version too. Added check for dd_fd in `DIR' if no dirfd is found;
+ this is now used to confitionally define the dirfd macro in
+ compat.h.
+ [567656978f7e]
+
+ * closefrom.c:
+ Only check /proc/$$/fd if we have the dirfd function/macro.
+ [15e3ccce7553]
+
+ * compat.h, config.h.in, configure, configure.in:
+ Add a check for a dirfd() function (like Linux) and add a dirfd
+ macro in compat.h if there is no dirfd() function or macro.
+ [1e95756edb50]
+
+ * closefrom.c, getcwd.c:
+ dirfd() is now defined in compat.h as needed.
+ [bb1d79271188]
+
+ * CHANGES:
+ Clarify closefrom() note.
+ [f4e4a5508dda]
+
+ * parse.c:
+ When checking for a command in the directory, only copy the base dir
+ once.
+ [7a3276808b87]
+
+ * closefrom.c:
+ If there is a /proc/$$/fd directory, behave like the Solaris
+ closefrom() and only close the descriptors listed therein.
+ [19de23779e84]
+
+ * alloc.c:
+ compat.h guarantees INT_MAX is defined.
+ [1bf0c79d4606]
+
+ * compat.h:
+ Add definitions of OPEN_MAX and INT_MAX for those without it and
+ remove definition of RLIM_INFINITY (now unused).
+ [f827d1ebf96e]
+
+ * CHANGES, alloc.c, check.c, compat.h, find_path.c, getcwd.c, parse.c,
+ sudo.c, sudo.h, visudo.c:
+ Use PATH_MAX, not MAXPATHLEN since the former is standardized.
+ [59788f211c24]
+
+2004-05-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ sync
+ [d32fa124f1ad]
+
+ * RUNSON:
+ Add some entries that were mailed in a while ago
+ [ff8d5bfec54e]
+
+ * closefrom.c:
+ o sysconf returns a long, not an int. o check for negative return
+ value from sysconf/getdtablesize and use OPEN_MAX in this case. o
+ define OPEN_MAX to 256 for those without it (a fair guess...)
+ [ccf81ae6deb2]
+
+2004-05-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * UPGRADE:
+ Mention change in parse order for RunAs entries.
+ [dc73b0bca617]
+
+ * configure:
+ regen
+ [07cce8e0534e]
+
+2004-05-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, README.LDAP, config.h.in, configure.in:
+ o --with-ldap now takes an optional dir as a parameter o added check
+ for ldap_initialize() and start_tls_s()
+ [2b846c7974c6]
+
+ * README.LDAP:
+ Fix some typos, word choice and formatting issues.
+ [00dc8ca84b10]
+
+2004-05-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * tgetpass.c:
+ Use SA_INTERRUPT so SunOS works correctly, avoid stdio and just use
+ read/write as it is simpler.
+ [30f5446ee8b0]
+
+ * configure, configure.in:
+ Remove hack overriding cross-compiler check. It should no longer be
+ needed.
+ [22a6cbd88608]
+
+ * compat.h:
+ Remove select() compat bits since we no longer use select().
+ [d7bbf7cd36f5]
+
+ * CHANGES, tgetpass.c:
+ Use alarm() instead of select() for the timeout for systems that
+ don't fully/properly implement select().
+ [d7cc60f15800]
+
+2004-05-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ synbc
+ [132a39788e07]
+
+ * RUNSON:
+ update
+ [61ef508380c6]
+
+ * set_perms.c:
+ Deal with systems that have no way of setting the effective uid such
+ as nsr-tandem-nsk.
+ [306e00e9b5a4]
+
+ * configure, configure.in:
+ Define NO_SAVED_IDS if we don't find seteuid()
+ [8588f18345cf]
+
+ * config.h.in, configure, configure.in:
+ Add back check for setreuid() since NSK doesn't have it.
+ [43127bd703d1]
+
+ * sudoers.cat, sudoers.man.in:
+ regen
+ [af4f4b20e422]
+
+ * BUGS:
+ sync
+ [3593f17f72ed]
+
+ * CHANGES:
+ sync
+ [29ca3b699c24]
+
+ * parse.c:
+ In sudoers_lookup() return VALIDATE_NOT_OK if the runas user was
+ explicitly denied and the command matched. This fixes a long-
+ standing bug and makes: foo machine = (ALL) /usr/bin/blah foo
+ machine = (!bar) /usr/bin/blah
+
+ equivalent to: foo machine = (ALL, !bar) /usr/bin/blah
+ [2f5ee244985a]
+
+ * sudoers.pod:
+ Clarify mail_noperm
+ [3238b2d41989]
+
+2004-05-20 Aaron Spangler <aaron777@gmail.com>
+
+ * Makefile.in:
+ Missing DESTDIR in make install for sudo_noexec.la
+ [91431e821525]
+
+2004-05-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat,
+ visudo.man.in:
+ regen
+ [cdfde0dcb556]
+
+ * TODO:
+ sync
+ [4799b7d8b62c]
+
+ * sample.sudoers:
+ Remove fastboot/fasthalt (who still remembers these?) and add a
+ minimal sudoedit example.
+ [b1bca73d6250]
+
+ * sudoers.pod:
+ Remove fastboot/fasthalt (who still remembers these?) and add a
+ minimal sudoedit example.
+ [19d299f233cd]
+
+ * CHANGES, INSTALL:
+ filesystem -> file system
+ [85948b608ffe]
+
+ * TROUBLESHOOTING:
+ filesystem -> file system
+ [39fb594e9338]
+
+ * UPGRADE, sudo.c, visudo.c:
+ filesystem -> file system
+ [1e1afaf30469]
+
+ * sudo.pod, sudoers.pod:
+ Fix some minor typos and formatting goofs
+ [e94d243a0b90]
+
+ * lex.yy.c:
+ regen
+ [2eed0ab1f4c4]
+
+ * visudo.pod:
+ remove my email addr
+ [b63262c0389b]
+
+ * sudo.pod, sudoers.pod, visudo.pod:
+ Use @mansectform@ and @mansectsu@ everywhere Make man page
+ references links with L<>
+ [f459f4b9ddb9]
+
+ * parse.lex:
+ Accept quoted globbing characters and pass them verbatim for
+ fnmatch()
+ [8248b86e9380]
+
+ * UPGRADE:
+ Document that /tmp/.odus is gone.
+ [3667b66af5bb]
+
+ * pathnames.h.in:
+ No longer use /tmp/.odus as a possible timestamp dir unless
+ specifically configured to do so. Instead, if no /var/run exists,
+ use /var/adm/sudo or /usr/adm/sudo.
+ [48d94c9f9ad4]
+
+ * CHANGES:
+ No longer use /tmp/.odus as a possible timestamp dir unless
+ specifically configured to do so. Instead, if no /var/run exists,
+ use /var/adm/sudo or /usr/adm/sudo.
+ [6058c4cefcec]
+
+ * aclocal.m4:
+ No longer use /tmp/.odus as a possible timestamp dir unless
+ specifically configured to do so. Instead, if no /var/run exists,
+ use /var/adm/sudo or /usr/adm/sudo.
+ [cf52c4c2803f]
+
+ * configure:
+ No longer use /tmp/.odus as a possible timestamp dir unless
+ specifically configured to do so. Instead, if no /var/run exists,
+ use /var/adm/sudo or /usr/adm/sudo.
+ [058d7b8cf07b]
+
+ * check.c, compat.h:
+ Preliminary changes to support nsr-tandem-nsk. Based on patches from
+ Tom Bates.
+ [390b698b5924]
+
+ * logging.c:
+ Preliminary changes to support nsr-tandem-nsk. Based on patches from
+ Tom Bates.
+ [934bbe6872b6]
+
+ * set_perms.c, sudo.c, tgetpass.c, visudo.c:
+ Preliminary changes to support nsr-tandem-nsk. Based on patches from
+ Tom Bates.
+ [2e5f81834383]
+
+2004-05-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ There was no 1.6.7p6.
+ [8013d2e6b062]
+
+ * BUGS, CHANGES:
+ sync
+ [c38b41f32857]
+
+ * Makefile.in:
+ add missing files to DISTFILES
+ [e6a80ad03039]
+
+ * sudo.cat, sudoers.cat, visudo.cat:
+ regen
+ [027bc9746dd5]
+
+ * sudoers.man.in:
+ regen
+ [f5e85ef686cf]
+
+ * Makefile.in:
+ Fix some line wrap and update (c) year
+ [bad1f46aa1ca]
+
+2004-04-28 Aaron Spangler <aaron777@gmail.com>
+
+ * README.LDAP:
+ Build Note
+ [7a061248249b]
+
+2004-04-07 Aaron Spangler <aaron777@gmail.com>
+
+ * Makefile.in:
+ Fix install-dirs
+ [be0726dd92e7]
+
+2004-04-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.tab.c:
+ regen
+ [3f4f0d1ab8b9]
+
+ * visudo.c:
+ In Exit() when used as a signal handler, emsg is a pointer so
+ sizeof() is wrong so make it a #define instead. Also avoid using a
+ negative exit value. Found by Aaron Campbell
+ [78716a3a3fdc]
+
+2004-03-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ Remove bogus sentence about uids in a User_List. Document usernames
+ vs. uid parsing in a Runas_List.
+ [7ca510b5031c]
+
+ * parse.c, parse.h, parse.yacc, sudo.c, testsudoers.c, visudo.c:
+ If the user specified a uid with the -u flag and the uid exists in
+ the passwd file, set runas_user to the name, not the uid.
+
+ When comparing usernames in sudoers, if a name is really a uid
+ (starts with '#') compare it numerically to pw_uid.
+ [8d6935d04673]
+
+2004-03-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/kerb5.c:
+ krb5_mcc_ops should be const; Johnny C. Lam
+ [aa8c753e426e]
+
+2004-02-28 Aaron Spangler <aaron777@gmail.com>
+
+ * CHANGES, config.h.in, ldap.c:
+ Added start_tls support
+ [7ef864c15b69]
+
+2004-02-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ Clean up libtool stuff for 'make distclean' and add def_data.c,
+ def_data.h to PARSESRCS.
+ [bf9bb6bb06ab]
+
+2004-02-14 Aaron Spangler <aaron777@gmail.com>
+
+ * strlcat.c, strlcpy.c:
+ Un-Fix last license munge
+ [42654b77ac71]
+
+2004-02-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [e4de6b23a4dc]
+
+ * CHANGES, RUNSON, TODO:
+ checkpoint
+ [94e1ace84d5c]
+
+ * lex.yy.c, sudo.tab.c:
+ regen
+ [8ce784505643]
+
+ * auth/passwd.c, auth/rfc1938.c, auth/secureware.c, auth/securid.c,
+ auth/securid5.c, auth/sia.c, auth/sudo_auth.c, auth/sudo_auth.h,
+ emul/search.h, emul/utime.h:
+ More to a less restrictive, ISC-style license.
+ [a31b20e48003]
+
+ * auth/afs.c, auth/aix_auth.c, zero_bytes.c:
+ More to a less restrictive, ISC-style license.
+ [6d234be91c5e]
+
+ * auth/bsdauth.c:
+ More to a less restrictive, ISC-style license.
+ [e21be6594b58]
+
+ * auth/dce.c, auth/fwtk.c, auth/kerb4.c:
+ More to a less restrictive, ISC-style license.
+ [87534c164a52]
+
+ * auth/kerb5.c, auth/pam.c:
+ More to a less restrictive, ISC-style license.
+ [e41f92b41216]
+
+ * sudoers.man.in, sudoers.pod, testsudoers.c, tgetpass.c, visudo.c,
+ visudo.man.in, visudo.pod:
+ More to a less restrictive, ISC-style license.
+ [b02aea324fd6]
+
+ * Makefile.binary:
+ More to a less restrictive, ISC-style license.
+ [1ed561734535]
+
+ * parse.lex, parse.yacc:
+ More to a less restrictive, ISC-style license.
+ [2f5942e847a1]
+
+ * utime.c, version.h:
+ More to a less restrictive, ISC-style license.
+ [e2e038ad8209]
+
+ * LICENSE, Makefile.in, alloc.c, check.c, closefrom.c, compat.h,
+ defaults.c:
+ More to a less restrictive, ISC-style license.
+ [d8d7bfc8a18b]
+
+ * defaults.h:
+ More to a less restrictive, ISC-style license.
+ [008f5d5743f5]
+
+ * env.c:
+ More to a less restrictive, ISC-style license.
+ [d5bd859757de]
+
+ * fileops.c:
+ More to a less restrictive, ISC-style license.
+ [4129a8b38a67]
+
+ * find_path.c, getprogname.c:
+ More to a less restrictive, ISC-style license.
+ [f605d5eab6f1]
+
+ * getspwuid.c, goodpath.c, ins_2001.h, ins_classic.h, ins_csops.h,
+ ins_goons.h, insults.h, interfaces.c, interfaces.h:
+ More to a less restrictive, ISC-style license.
+ [520381c60a54]
+
+ * ldap.c, logging.c, logging.h, parse.c, parse.h, pathnames.h.in,
+ set_perms.c:
+ More to a less restrictive, ISC-style license.
+ [64d772d70ab3]
+
+ * sigaction.c, strerror.c:
+ More to a less restrictive, ISC-style license.
+ [4bccdedca58a]
+
+ * strlcat.c, strlcpy.c, sudo.c, sudo.h, sudo.man.in, sudo.pod,
+ sudo_edit.c:
+ More to a less restrictive, ISC-style license.
+ [71cdcc241e94]
+
+ * sudo_noexec.c:
+ More to a less restrictive, ISC-style license.
+ [a6da7631e0b2]
+
+2004-02-13 Aaron Spangler <aaron777@gmail.com>
+
+ * CHANGES, Makefile.in, README.LDAP, config.h.in, configure.in:
+ Merged in LDAP Support
+ [1038092a161e]
+
+ * def_data.c, def_data.h, def_data.in:
+ Merged in LDAP Support
+ [8fb255280e42]
+
+ * ldap.c, sudo.c, sudo.h:
+ Merged in LDAP Support
+ [547eaa346fcc]
+
+ * sudoers2ldif:
+ Merged in LDAP Support
+ [3994c4d05947]
+
+2004-02-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.h, sudo_noexec.c:
+ Only do "extern int errno" if errno is not a macro.
+ [b2e02a08be8b]
+
+2004-02-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * set_perms.c:
+ setreuid(0, 0) fails on QNX if the euid is not already 0 so set the
+ euid first, then just call setuid(0) to set the real uid too.
+ [f08546e2e0ee]
+
+ * set_perms.c:
+ Use setresuid() and setreuid() for PERM_RUNAS when appropriate
+ instead of seteuid() which may not exist.
+ [ba508581befb]
+
+2004-02-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * LICENSE:
+ 2004
+ [37425513a342]
+
+ * INSTALL, config.h.in, configure, configure.in, ins_classic.h:
+ Add --with-pc-insults configure option
+ [7daa5294c17b]
+
+ * visudo.man.in:
+ Prefer VISUAL over EDITOR like old vipw did.
+ [996252a4ab65]
+
+2004-02-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.man.in, sudoers.man.in:
+ regen
+ [a247f1c52eb9]
+
+ * sudoers.pod:
+ Add a note that noexec is not a cure-all.
+ [9e7fc535367d]
+
+ * sudoers.pod:
+ Mention that disabling "root_sudo" is pretty pointless.
+ [f38a415afba0]
+
+ * configure, configure.in:
+ Substitute for root_sudo in sudoers.pod
+ [ce483cfc86be]
+
+ * sudo.pod:
+ Add sudoedit to the NAME section
+ [51bc453ec2f6]
+
+ * sudoers.pod:
+ Document that fact that setting ignore_dot in sudoers has no effect
+ due to the fact that find_path() is called *before* sudoers is read.
+ [6808df7e417c]
+
+2004-01-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo_edit.c:
+ Do not require _PATH_USRTMP to be set.
+ [546f3270dd10]
+
+ * BUGS, CHANGES, TODO:
+ sync
+ [4205ddeab781]
+
+ * sudo.man.in:
+ regen
+ [e2143690a88a]
+
+ * sudo.pod:
+ Clarify that when sudo is run by root with the SUDO_USER variable
+ set, the sudoers lookup happens for root and not the SUDO_USER user.
+ [47207bec1bdf]
+
+2004-01-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/pam.c, auth/sudo_auth.c, interfaces.c, logging.c, parse.c,
+ set_perms.c, sigaction.c, sudo.c, tgetpass.c:
+ Use the SET, CLR and ISSET macros.
+ [a8b0d7f1e8fd]
+
+ * defaults.c, env.c:
+ Use the SET, CLR and ISSET macros.
+ [2f39431e0a49]
+
+ * fnmatch.c:
+ Use the SET, CLR and ISSET macros.
+ [1afbcba22ba6]
+
+ * interfaces.h:
+ MAIN was replaced with _SUDO_MAIN some time ago.
+ [ea1b38f2ac9d]
+
+ * sudo.c:
+ Don't look at prev_user until after we've parsed sudoers and done
+ the password check. That way, if sudo/sudoedit is run from a root
+ process that was invoked by sudo, we check sudoers for root, not the
+ previous user. This makes sudoedit much more useful and means that
+ for the sudo case, we get correct logging on who actually ran the
+ command.
+ [431dfbf20552]
+
+2004-01-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo_edit.c:
+ Add a comment describing why we need to be notified about our child
+ stopping.
+ [0bec3ce4b49d]
+
+2004-01-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * def_data.c, def_data.in:
+ Update the noexec variable descriptions
+ [9cb7f1aa0e57]
+
+ * sudoers.man.in, sudoers.pod:
+ noexec now replaces more than just execve()
+ [23cbdc0ee95c]
+
+ * sudo_noexec.c:
+ Alas, all the world does not go through execve(2). Many systems
+ still have an execv(2) system call, Linux 2.6 provides fexecve(2)
+ and it is not uncommon for libc to have underscore ('_') versions of
+ the functions to be used internally by the library. Instead of
+ stubbing all these out by hand, define a macro and let it do the
+ work. Extra exec functions pointed out by Reznic Valery.
+ [9fa0cd871b0c]
+
+ * sudo.c, sudo_edit.c:
+ Fix suspending the editor in -e mode. Because we do a fork() first
+ we need to be notified when the child has been stopped and then send
+ that same signal to ourself so the shell can do its job control
+ thing.
+ [773165eb6057]
+
+ * visudo.c:
+ Use WIFEXITED and WEXITSTATUS macros. If there are systems out there
+ that want to run sudo that still don't support these we can try to
+ deal with that later.
+ [6af68e4aff60]
+
+ * lex.yy.c:
+ regen
+ [403435317d5d]
+
+ * sudo.man.in, sudo.pod, sudoers.man.in, sudoers.pod:
+ Document sudo -e / sudoedit
+ [a80f6ea910af]
+
+ * configure, configure.in:
+ fix typo
+ [5020fcdc27f4]
+
+ * config.h.in, configure.in:
+ Add SET/CLR/ISSET
+ [03ff57286e7e]
+
+2004-01-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Allow non-exclusive flags when invoked as sudoedit. Pretty print the
+ long usage() line to not wrap (assumes 80 char display)
+ [3941fa4004bb]
+
+ * Makefile.in, sudo.c:
+ If sudo is invoked as "sudoedit" the -e flag is implied and no other
+ flags are permitted.
+ [929670b01293]
+
+ * sudo.h:
+ Add a new flag, -e, that makes it possible to give users the ability
+ to edit files with the editor of their choice as the invoking user,
+ not the runas user. Temporary files are used for the actual edit and
+ the temp file is copied over the original after the editor is done.
+ [c4051414c1f4]
+
+ * Makefile.in, parse.c, parse.lex, sudo.c, sudo_edit.c:
+ Add a new flag, -e, that makes it possible to give users the ability
+ to edit files with the editor of their choice as the invoking user,
+ not the runas user. Temporary files are used for the actual edit and
+ the temp file is copied over the original after the editor is done.
+ [37ac05c8ac3c]
+
+ * env.c, sudo.c:
+ If real uid == 0 and the SUDO_USER environment variables is set, use
+ that to determine the invoking user's true identity. That way the
+ proper info gets logged by someone who has done "sudo su" but still
+ uses sudo to as root. We can't do this for non-root users since that
+ would open up a security hole, though perhaps it would be acceptable
+ to use getlogin(2) on OSes where this a system call (and doesn't
+ just look in the utmp file).
+ [c2f9198708a1]
+
+ * pathnames.h.in:
+ Add _PATH_TMP, _PATH_VARTMP and _PATH_USRTMP
+ [7d9e5768df93]
+
+ * config.h.in, configure, configure.in:
+ Add check for fchown(2)
+ [a85df18798ed]
+
+2004-01-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Back out portions of the -i commit that set NewArgv[0] in
+ set_runaspw. It is far to late to set NewArgv[0] there and will have
+ no effect anyway as cmnd and safe_cmnd have already been set.
+ [c2d343430c1c]
+
+ * visudo.c, visudo.pod:
+ Prefer VISUAL over EDITOR like old vipw did.
+ [ae32f477cea3]
+
+2004-01-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c, sudo.c:
+ In -i mode always set new environment based on the runas user's
+ passwd entry.
+ [fa653b7887a8]
+
+2004-01-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.man.in, sudo.pod:
+ Document the new -i flag and sync SYNOPSIS section with usage() in
+ sudo.c. Also sort the flags in the OPTIONS section.
+ [6aabc0ffc47e]
+
+ * sudo.c, sudo.h:
+ o Add -i that acts similar to "su -", based on patches from David J.
+ MacKenzie o Sort the flags in the usage message
+ [c0fe7d6beffd]
+
+ * sudoers.man.in, sudoers.pod:
+ Add a missing @runas_default@ substitution.
+ [60516fe2d090]
+
+2004-01-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Change euid to runas user before calling find_path(). Unfortunately,
+ though runas_user can be modified in sudoers we haven't parsed
+ sudoers yet.
+ [f469fdf2e313]
+
+ * sudoers.man.in, sudoers.pod:
+ Add missing defintion of Parameter_List and use single pipes in the
+ Defaults EBNF definition.
+ [f7bed6e909bf]
+
+ * sudo.c:
+ Fix a bug when set_runaspw() is used as a callback. We don't want to
+ reset the contents of runas_pw if the user specified a user via the
+ -u flag.
+
+ Avoid unnecessary passwd lookups in set_authpw(). In most cases we
+ already have the info in runas_pw.
+ [efc35623ba09]
+
+2004-01-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ Add Stan Lee / Uncle Ben quote to the lecture from RedHat
+ [ebd5a76ccd7e]
+
+ * sudo.h:
+ Update sudo_getepw() proto and add one for set_runaspw()
+ [6ed65795c17f]
+
+ * parse.c:
+ If we can't stat the command as root, try as the runas user instead.
+ [ae713fca0e15]
+
+ * testsudoers.c, visudo.c:
+ Add stub set_runaspw() function
+ [42aa37050053]
+
+ * sudo.c:
+ Add set_runaspw() function to fill in runas_pw. This will be used as
+ a callback to update runas_pw when the runas user changes.
+ [e570aa0088d0]
+
+ * env.c, sudo.c:
+ PERM_RUNAS -> PERM_FULL_RUNAS
+ [51eec6f9e89a]
+
+ * set_perms.c, sudo.h:
+ Rename PERM_RUNAS -> PERM_FULL_RUNAS and add a PERM_RUNAS that just
+ changes the euid.
+ [877c6fe4d12c]
+
+ * getspwuid.c:
+ Make sudo_pwdup() act like OpenBSD pw_dup() and allocate memory in
+ one chunk for easy free()ing. Also change it from static to extern.
+ [ab503260a7ec]
+
+ * defaults.c, defaults.h:
+ Add callback support
+ [a61c4ca983fb]
+
+ * def_data.c, def_data.in:
+ Add a callback field and use it for runas_default
+ [d3e9f06872b8]
+
+ * mkdefaults:
+ Add a callback field and use it for runas_default
+ [96b69c27df5e]
+
+2004-01-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/fwtk.c:
+ Add support for chalnecho and display server responses used by fwtk
+ >= 2.0
+ [b1870f7aaf0d]
+
+2004-01-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.man.in, sudoers.pod:
+ ld.so is ld.so.1 on solaris
+ [2bf9a123fa4c]
+
+ * Makefile.in, config.h.in, configure, configure.in, sudo.c, sudo.h:
+ Use closefrom() instead of doing the equivalent inline.
+ [7e3ef6072884]
+
+ * closefrom.c:
+ closefrom(3) for systems w/o it
+ [35caf58bb636]
+
+2004-01-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.man.in:
+ Update from .pod file.
+ [d4c94fc0e0c9]
+
+ * configure, configure.in:
+ Substitute noexec_file for the sudoers man page
+ [203d3376a551]
+
+ * sudo.man.in, sudo.pod:
+ Mention noexec
+ [014375ddbb06]
+
+ * sudoers.man.in, sudoers.pod:
+ Document noexec
+ [49a65d06201f]
+
+ * auth/pam.c, config.h.in, configure.in:
+ Move PAM_CONST macro definition from config.h to pam.c where it
+ belongs. We can't have this in config.h since that gets included too
+ early.
+ [e64748071637]
+
+ * auth/pam.c, config.h.in, configure, configure.in:
+ Some PAM implementations put their headers in /usr/include/pam
+ instead of /usr/include/security.
+ [8cc749e9575c]
+
+ * configure.in:
+ I missed changing the EXEC macro -> EXECV here when I changed this
+ in config.h.in and sudo.c a while ago.
+ [6f5afac7789f]
+
+ * acsite.m4:
+ OpenBSD vax/m88k/hppa don't do shared libs
+ [e4901d958bb7]
+
+ * configure, configure.in:
+ o merge the hpux case entries into a single entry w/ its own sub-
+ case statement. o HP-UX >= 11 support getspnam(), use it in
+ preference to getprpwuid()
+ [0caad428894e]
+
+ * configure, configure.in:
+ eval $shrext so that it expands nicely on MacOS X
+ [40419343eef8]
+
+ * Makefile.in:
+ Don't lie about making a module, it does the wrong thing on mach
+ [7629b28f5688]
+
+ * ltmain.sh:
+ Remove requirement that libs must begin with "lib". They don't when
+ we point directly at the lib using LD_PRELOAD or its equivalent.
+ [d66f3de6ec85]
+
+ * acsite.m4:
+ Disable support for c++, f77 and java. We don't need it, it takes a
+ lot of time, and it hosed our check for shared lib support.
+ [4f5749c52ce4]
+
+ * configure:
+ regen
+ [160865e9d15f]
+
+ * configure.in:
+ Call AC_ENABLE_SHARED and check the status of enable_shared to know
+ when shared libs are available.
+ [42504c1668fc]
+
+ * acsite.m4:
+ Duh, OpenBSD suports shared libs too
+ [8e3cd9417475]
+
+ * config.h.in, configure.in:
+ Only OpenPAM and Linux PAM use const qualifiers.
+ [b2f76476e866]
+
+ * configure, configure.in:
+ o No need to check for sed, libtool config does that for us o move
+ check for --with-noexec until after libtool magic is run so we can
+ use $can_build_shared and $shrext
+ [668c656e89cc]
+
+ * ltmain.sh:
+ Don't print a bunch of crap about library installs since we are not
+ really installing a library.
+ [83fbcad29fe4]
+
+ * env.c:
+ Make format_env() varargs Add noexec support for Darwin, MacOS X,
+ Irix, and Tru64
+ [468885d75d10]
+
+ * acsite.m4, ltconfig, ltmain.sh:
+ Update to libtool 1.5 with local changes: o no ldconfig in the
+ finish step o assume no libprefix or version is needed
+ [4961cffc3797]
+
+ * sudo_noexec.c:
+ Fix compilation under K&R
+ [8b309bf0b1b2]
+
+2004-01-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ checkpoint
+ [3c368badab32]
+
+ * sudo_noexec.c:
+ stub execve() that just returns EACCES; used for noexec
+ functionality
+ [1297acae283a]
+
+ * sudo.tab.c:
+ Regen w/ updated byacc from OpenBSD; fixes a gcc 3.2 issue with
+ generated code.
+ [0a61c735eabe]
+
+ * sudo.tab.h:
+ Regen w/ updated byacc from OpenBSD; fixes a gcc 3.2 issue with
+ generated code.
+ [dcab78c49273]
+
+2004-01-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * def_data.c, def_data.h, def_data.in:
+ Move the environment defaults to the end and shorten a few of the
+ descriptions.
+ [66787b9c612c]
+
+ * configure, configure.in:
+ no shared libs on ultris or convexos
+ [2c5f3c456e32]
+
+ * Makefile.in, configure, configure.in:
+ Build sudo_noexec shared object using libtool; could use some
+ cleanup.
+ [373f483555dd]
+
+ * acsite.m4, ltconfig, ltmain.sh:
+ libtool scaffolding
+ [c903a42e3d90]
+
+ * parse.yacc, sudo.tab.c:
+ Merge the NOPASSWD/PASSWD and NOEXEC/EXEC rules so that order is not
+ important.
+ [c6e8a34639a4]
+
+ * defaults.c, env.c, lex.yy.c, parse.c, parse.h, parse.lex,
+ parse.yacc, pathnames.h.in, sudo.c, sudo.h, sudo.tab.c:
+ update copyright year
+ [a16372ae1711]
+
+ * configure, configure.in, defaults.c, env.c, pathnames.h.in:
+ Add _PATH_SUDO_NOEXEC and corresponding --with-noexec configure
+ option. The default value of noexec_file is set to this.
+ [7d88e1d3c494]
+
+ * def_data.c, def_data.h, def_data.in, env.c, lex.yy.c, parse.c,
+ parse.h, parse.lex, parse.yacc, sudo.c, sudo.h, sudo.tab.c,
+ sudo.tab.h:
+ Add support for preloading a shared object containing a dummy
+ execve() function that just sets error and returns -1. This adds a
+ "noexec_file" option to load the filename as well as a "noexec" flag
+ to enable it unconditionally. There is also a NOEXEC tag that can be
+ attached to specific commands and an EXEC tag to disable it.
+ [c8b6712feb91]
+
+ * mkdefaults:
+ add missing newline to usage statement
+ [e84746618362]
+
+ * config.h.in, sudo.c:
+ Rename EXEC macro -> EXECV
+ [ddaa0c027299]
+
+ * logging.c:
+ Don't truncate usernames to 8 characters in the log message.
+ [f62a20f27075]
+
+ * check.c, sudoers.man.in, sudoers.pod:
+ Update copyright year
+ [ca9964054085]
+
+ * check.c, def_data.c, def_data.h, def_data.in, sudoers.man.in,
+ sudoers.pod:
+ Add a new option, lecture_file, that can be used to point to a
+ custom sudo lecture.
+ [940133231216]
+
+2003-12-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/aix_auth.c, auth/bsdauth.c, auth/fwtk.c, auth/pam.c,
+ auth/sudo_auth.c:
+ Add a zero_bytes() function to do the equivalent of bzero in such a
+ way that will heopfully not be optimized away by sneaky compilers.
+ [161b6d74bfb4]
+
+ * Makefile.in, sudo.h:
+ Add a zero_bytes() function to do the equivalent of bzero in such a
+ way that will heopfully not be optimized away by sneaky compilers.
+ [ff136de3e255]
+
+ * zero_bytes.c:
+ Add a zero_bytes() function to do the equivalent of bzero in such a
+ way that will heopfully not be optimized away by sneaky compilers.
+ [d035abf0af94]
+
+ * err.c:
+ Use #ifdef __STDC__, not #if __STDC__.
+ [6889dd6bc51a]
+
+2003-12-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkdefaults:
+ Always put at least one space between the def_* macro name and its
+ definition.
+ [6b3ad0e6619a]
+
+ * configure, configure.in:
+ Adjust code for --without-lecture to match new values.
+ [062aa788a6b9]
+
+ * visudo.man.in:
+ regen after pasto fix
+ [3deec16906c0]
+
+ * sudoers.man.in, sudoers.pod:
+ Document that "lecture" has changed from a flag to a tuple.
+ [e2c03062b533]
+
+ * check.c, def_data.c, def_data.h, def_data.in, defaults.c,
+ defaults.h, logging.c, mkdefaults, parse.c, sudo.c, sudo.h:
+ Add support for tuples in def_data.in; these are implemented as an
+ enum type. Currently there is only a single tuple enum but in the
+ future we may have one tuple enum per T_TUPLE entry in def_data.in.
+ Currently listpw, verifypw and lecture are tuples. This avoids the
+ need to have two entries (one ival, one str) for pwflags and syslog
+ values.
+
+ lecture is now a tuple with the following values: never, once,
+ always
+
+ We no longer use both an int and string entry for syslog facilities
+ and priorities. Instead, there are logfac2str() and logpri2str()
+ functions that get used when we need to print the string values.
+ [5293f946c836]
+
+ * auth/aix_auth.c, auth/bsdauth.c, auth/fwtk.c, auth/pam.c,
+ auth/rfc1938.c, auth/securid5.c, auth/sia.c, auth/sudo_auth.c,
+ check.c, def_data.h, defaults.c, defaults.h, env.c, find_path.c,
+ logging.c, mkdefaults, parse.c, parse.yacc, set_perms.c, sudo.c,
+ sudo.tab.c, visudo.c:
+ Create def_* macros for each defaults value so we no longer need the
+ def_{flag,ival,str,list,mode} macros (which have been removed). This
+ is a step toward more flexible data types in def_data.in.
+ [009c02934106]
+
+ * TODO:
+ checkpoint
+ [0a99a4bb5d15]
+
+2003-12-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ If we are in -k/-K mode, just spew to stderr. It is not unusual for
+ users to place "sudo -k" in a .logout file which can cause sudo to
+ be run during reboot after the YP/NIS/NIS+/LDAP/etc daemon has died.
+ Previously, this would result in useless mail and logging.
+ [d282e7ed63af]
+
+2003-12-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.pod:
+ fix pasto in VISUAL description
+ [1c6a6148b5f9]
+
+2003-12-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [f44312c63799]
+
+ * CHANGES:
+ checkpoint
+ [0c42e38f78d5]
+
+ * TROUBLESHOOTING:
+ Some OSes (like Solaris) allow export w/ nosuid too
+ [973ce85ffa12]
+
+2003-08-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat.h:
+ We don't use FD_ZERO anymore so just define FD_SET (if not already
+ there).
+ [d1c8c11905cd]
+
+2003-06-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/pam.c:
+ Fix a core dump on Solaris by preserving the pam_handle_t we used
+ during authentication for pam_prep_user(). If we didn't authenticate
+ (ie: ticket still valid), we call pam_init() from pam_prep_user().
+ This is something of a hack; it may be better to change the auth API
+ and add an auth_final() function that acts like pam_prep_user().
+ [f787de49b175]
+
+2003-06-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * set_perms.c:
+ Add explicit declaration of printerr variable in function header
+ (was defaulting to int which is OK but oh so K&R :-). From Theo.
+ [492c2358783f]
+
+2003-06-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure.in:
+ s/HAVE_STOW/USE_STOW/
+ [4b99e1824ece]
+
+ * logging.c:
+ Also exit waitpid() loop when pid == 0. Fixes a problem where the
+ sudo process would spin eating up CPU until sendmail finished when
+ it has to send mail.
+ [ec3d5792b9b4]
+
+2003-05-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * fnmatch.3:
+ Remove advertising clause, UCB has disavowed it
+ [3ff24291bcfa]
+
+ * fnmatch.c:
+ Remove advertising clause, UCB has disavowed it
+ [43a26bbd6628]
+
+2003-05-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ Don't assume that getgrnam() calls don't modify contents of struct
+ passwd returned by getpwnam(). On FreeBSD w/ NIS this can happen.
+ Based on a patch from Kirk Webb.
+ [5574c68f60f3]
+
+2003-05-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ missing ;;
+ [22378f2a9d31]
+
+ * configure.in:
+ darwin has a broken setreuid() in at least some versions
+ [d572aed930d2]
+
+ * env.c:
+ Fix an off by one error when reallocating the environment; Kevin Pye
+ [3d98e7cf097a]
+
+2003-04-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ Fix User_Spec definition; SEKINE Tatsuo
+ [49b0da65e090]
+
+2003-04-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * HISTORY:
+ More info on the early days from Coggs.
+ [9381ca10b06b]
+
+2003-04-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/kerb5.c:
+ remove errant semicolon that prevented compilation under heimdal
+ [d2f2bb73a598]
+
+2003-04-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/afs.c, auth/aix_auth.c, auth/bsdauth.c, auth/dce.c,
+ auth/fwtk.c, auth/kerb4.c, parse.lex, parse.yacc, utime.c,
+ version.h:
+ add DARPA credit on affected files
+ [868d54cbddea]
+
+ * auth/kerb5.c, auth/pam.c:
+ add DARPA credit on affected files
+ [15da3021b49c]
+
+ * auth/passwd.c, auth/rfc1938.c, auth/secureware.c, auth/securid.c,
+ auth/securid5.c, auth/sia.c, auth/sudo_auth.c, fileops.c,
+ find_path.c, getprogname.c, getspwuid.c, goodpath.c, interfaces.c,
+ interfaces.h:
+ add DARPA credit on affected files
+ [da66e28fb3f5]
+
+ * logging.c, parse.c:
+ add DARPA credit on affected files
+ [8f75f822755b]
+
+ * pathnames.h.in:
+ add DARPA credit on affected files
+ [e334cdda422f]
+
+ * set_perms.c:
+ add DARPA credit on affected files
+ [3d79fdabb582]
+
+ * sigaction.c, strerror.c, sudo.c, sudo.h, sudo.man.in, sudo.pod,
+ sudoers.man.in:
+ add DARPA credit on affected files
+ [d8adf1c2ba22]
+
+ * sudoers.pod:
+ add DARPA credit on affected files
+ [83b46318750b]
+
+ * testsudoers.c, tgetpass.c, visudo.c, visudo.man.in, visudo.pod:
+ add DARPA credit on affected files
+ [7020785ee50d]
+
+ * Makefile.in, alloc.c, check.c:
+ add DARPA credit on affected files
+ [cd939e05c810]
+
+ * compat.h:
+ add DARPA credit on affected files
+ [316a735783c4]
+
+ * defaults.c, defaults.h:
+ add DARPA credit on affected files
+ [6a64205fd1eb]
+
+ * env.c:
+ add DARPA credit on affected files
+ [90239f51ef0a]
+
+ * LICENSE:
+ slightly different wording for the darpa credit
+ [e468909c4a21]
+
+2003-04-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * LICENSE:
+ Add DARPA credit
+ [8eb20e2cd63e]
+
+2003-04-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/kerb5.c:
+ Use krb5_princ_component() instead of krb5_princ_realm() for MIT
+ Kerberos like we did before I messed things up ;-)
+
+ Use krb5_principal_get_comp_string() to do the same thing w/
+ Heimdal. I'm not sure if the component should be 0 or 1 in this
+ case.
+
+ #define ENCTYPE_DES_CBC_MD5 ETYPE_DES_CBC_MD5 for Heimdal since
+ older versions lack ENCTYPE_DES_CBC_MD5. This is gross and there
+ should be a configure check for this I guess.
+ [74919a3933fe]
+
+2003-04-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TROUBLESHOOTING, config.h.in, configure, configure.in:
+ builtin -> built-in; Jason McIntyre
+ [70b81ac48943]
+
+ * sample.sudoers:
+ builtin -> built-in; Jason McIntyre
+ [027f2187923e]
+
+ * sudoers.pod:
+ built in -> built-in; Jason McIntyre
+ [da658ef5138d]
+
+2003-04-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ checkpoint for 1.6.7p3
+ [da85f989fadf]
+
+ * HISTORY:
+ Update info on the early years @ SUNY-Buffalo from Cliff Spencer.
+ Amazingly, sudo source from 1985 is available via groups.google.com
+ [39e0fc85b89f]
+
+ * sudo.c:
+ Don't change rl.rlim_max for RLIMIT_CORE. We need only set
+ rl.rlim_cur to 0 to turn off core dumps. This may be needed for the
+ RLIMIT_CORE restoration on some OSes.
+ [7e2c1a7adfd8]
+
+2003-04-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/kerb5.c:
+ Make this compile on Heimdal and MIT Kerberos 5
+ [44c07d615868]
+
+ * config.h.in, configure, configure.in:
+ Check for heimdal even if we found krb5-config and define
+ HAVE_HEIMDAL.
+ [aba0126f0059]
+
+ * auth/kerb5.c:
+ Replace ETYPE_DES_CBC_MD5 with ENCTYPE_DES_CBC_MD5. The former is no
+ longer defined by MIT kerb5 (though it used to be and indeed remains
+ so in Heimdal).
+ [e5a6c64d7cd5]
+
+2003-04-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkinstalldirs:
+ Remove newer stuff that passes multiple (possibly duplicate)
+ directories to "mkdir -p" since that seems to break on Tru64 Unix at
+ least. This basically brings back what shipped with sudo 1.6.6.
+ [f2a1abd872b3]
+
+2003-04-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/kerb5.c:
+ Correct number of args to krb5_principal_get_realm() and fix an
+ unclosed comment that hid the bug.
+ [0b37f8ce7824]
+
+ * configure:
+ regen
+ [1876cb840fe0]
+
+ * BUGS:
+ ++version
+ [ea3573432412]
+
+ * CHANGES, version.h:
+ ++version
+ [f66985a64063]
+
+ * INSTALL:
+ ++version
+ [555aeba5c2bf]
+
+ * INSTALL.binary:
+ ++version
+ [a506204e77d0]
+
+ * Makefile.in:
+ ++version
+ [97ef63cedc38]
+
+ * README:
+ ++version
+ [488e0bbff613]
+
+ * configure.in:
+ ++version
+ [480aff7c048e]
+
+ * configure.in:
+ use krb5-config to determine Kerberos V details if it exists
+ [7b46bbdaf774]
+
+ * alloc.c, auth/fwtk.c, auth/rfc1938.c, auth/securid.c,
+ auth/securid5.c, auth/sia.c, check.c, compat.h, defaults.c, env.c,
+ find_path.c, interfaces.c, logging.c, parse.c, sudo.c, sudo.h,
+ testsudoers.c, visudo.c:
+ Use warn/err and getprogname() throughout. The main exception is
+ openlog(). Since the admin may be filtering logs based on the
+ program name in the log files, hard code this to "sudo".
+ [9f180d015cfa]
+
+ * Makefile.in:
+ Add getprogname.c and err.c
+ [d411c54a07dc]
+
+ * configure:
+ regen
+ [6d585d391acc]
+
+ * config.h.in, configure.in:
+ Add checks for getprognam(), __progname and err.h
+ [bcbccf61d34a]
+
+ * emul/err.h:
+ For systems withour err/warn functions.
+ [1b33118884d9]
+
+ * err.c:
+ For systems withour err/warn functions.
+ [26721f6b041f]
+
+ * getprogname.c:
+ For systems neither getprogname() nor __progname; uses Argv[0].
+ [841cf42af1eb]
+
+2003-04-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ checkpoint for 1.6.7p1
+ [5bfdaf441dce]
+
+ * sudo.c, testsudoers.c:
+ fix strlcpy() rval check (innocuous)
+ [e05ac7e0d1f3]
+
+ * check.c:
+ oflow detection in expand_prompt() was faulty (false positives). The
+ count was based on strlcat() return value which includes the length
+ of the entire string.
+ [086c5a0acb25]
+
+2003-03-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ checkpoint for the sudo 1.6.7 release
+ [87322187ed78]
+
+ * RUNSON, TODO:
+ checkpoint for the sudo 1.6.7 release
+ [096bab4da29a] [SUDO_1_6_7]
+
+2003-03-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ g/c unused variable
+ [c57cd4a17765]
+
+ * configure:
+ regen
+ [e7c1f581dfac]
+
+ * configure.in:
+ use man sections 8 and 5 for csops
+ [87de581bda88]
+
+2003-03-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [cb1433a9c7a1]
+
+ * configure.in:
+ Add -lskey or -lopie directly to SUDO_LIBS instead of having
+ AC_CHECK_LIB() add them to LIBS. Fixes visudo linkage.
+ [ac5667978939]
+
+ * configure:
+ regen
+ [638459118a2a]
+
+ * INSTALL:
+ Add --with-blibpath for AIX. An alternate libpath may be specified
+ or
+ -blibpath support can be disabled. Also change conifgure such that
+ -blibpath is not specified if no -L libpaths were added to
+ SUDO_LDFLAGS.
+ [4b4bbe5bbe1b]
+
+ * aclocal.m4:
+ Add --with-blibpath for AIX. An alternate libpath may be specified
+ or
+ -blibpath support can be disabled. Also change conifgure such that
+ -blibpath is not specified if no -L libpaths were added to
+ SUDO_LDFLAGS.
+ [37022e991575]
+
+ * configure.in:
+ Add --with-blibpath for AIX. An alternate libpath may be specified
+ or
+ -blibpath support can be disabled. Also change conifgure such that
+ -blibpath is not specified if no -L libpaths were added to
+ SUDO_LDFLAGS.
+ [c7d17b480cad]
+
+ * configure.in:
+ add AIX blibpath support
+ [16ba788bf086]
+
+ * INSTALL, configure.in:
+ --with-skey and --with-opie now take an option directory argument
+ This obsoletes a --with-csops hack (/tools/cs/skey)
+
+ Also remove the remaining direct uses of "echo"
+ [5b4986a90c03]
+
+2003-03-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ Detect KTH Kerberos IV and deal with it. Also make -lroken optional
+ for KTH Kerberos IV and V.
+ [119f97b48e18]
+
+ * aclocal.m4:
+ Add SUDO_APPEND_LIBPATH function that add -L/path/to/dir (and
+ -R/path/to/dir if $with_rpath) to the specified variable.
+ [e55e49d076ce]
+
+ * INSTALL, configure.in:
+ Add -R/path/to/libs for Solaris and SVR4. There is a new configure
+ option, --with-rpath to control this behavior.
+ [d4730c5399ab]
+
+ * configure.in:
+ for kerb4 put libdes after libkrb on the link line
+ [5c566100eab6]
+
+ * auth/kerb4.c:
+ typo
+ [6541b72b64a3]
+
+ * configure.in:
+ fix kerberos lib check when a path is specified
+ [ae833a914c6f]
+
+ * logging.c:
+ Fix boolean thinko in SIGCHLD reaper and call reapchild after
+ sending mail instead of doing a conditional sudo_waitpid.
+ [86fa9a35df5a]
+
+2003-03-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [e6275cf528ba]
+
+ * configure.in:
+ replace =DIR with [=DIR] where sensible
+ [c39a59173b38]
+
+ * configure.in:
+ o Use AC_MSG_* instead of "echo" o New Kerberos include/lib
+ detection based on openssh's configure.in
+ [5b7a340912df]
+
+ * INSTALL:
+ --with-kerb4 and --with-kerb5 now take an optional argument.
+ [71ed87fc9c64]
+
+2003-03-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/securid.c:
+ Kill remaining strcpy(), the programmer's guide says username is 32
+ bytes.
+ [bdba70fcd08d]
+
+ * auth/kerb4.c:
+ trat uid_t as unsigned long for printf and use snprintf, not sprintf
+ [8072f5f8966d]
+
+ * auth/rfc1938.c:
+ use snprintf
+ [fc0c70c665fe]
+
+2003-03-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/afs.c, auth/aix_auth.c, auth/bsdauth.c, auth/dce.c,
+ auth/fwtk.c, auth/kerb4.c, auth/kerb5.c, auth/pam.c, auth/passwd.c,
+ auth/rfc1938.c, auth/sudo_auth.c:
+ update copyright year
+ [b0a10ccb1d0e]
+
+ * sudo.man.in, sudoers.man.in, visudo.man.in:
+ update copyright year
+ [8fce0034eb51]
+
+ * LICENSE, Makefile.in, aclocal.m4, alloc.c, check.c, compat.h,
+ configure.in, env.c, find_path.c, interfaces.c, logging.c, parse.c,
+ parse.lex, parse.yacc, set_perms.c, sudo.c, sudo.h, sudo.pod,
+ sudoers.pod, testsudoers.c, version.h, visudo.c, visudo.pod:
+ update copyright year
+ [d541e75fe520]
+
+ * check.c, env.c, sudo.c:
+ Cast [ug]ids to unsigned long and printf with %lu
+ [2ede64d3592b]
+
+ * configure:
+ regen
+ [c7c3245bdf3e]
+
+ * configure.in:
+ correct error messages for --with-sudoers-{mode,uid,gid}
+ [77fc15b1c9db]
+
+ * alloc.c:
+ make the malloc(0) error specific to each function to aid tracking
+ down bugs.
+ [a58c34374b4b]
+
+ * alloc.c:
+ deal with platforms where size_t is signed and there is no SIZE_MAX
+ or SIZE_T_MAX
+ [7192abb4ab4e]
+
+ * auth/kerb5.c:
+ Make this compile w/ Heimdal and fix some gcc warnings.
+ [f52f026f31c2]
+
+ * sudo.c:
+ Use stat_sudoers macro so --with-stow can work
+ [c3674735c139]
+
+ * INSTALL, config.h.in, configure, configure.in:
+ Add support for --with-stow based on patches from Robert Uhl
+ [b274cc1dd52c]
+
+ * env.c:
+ fix indentation
+ [110d9f1721b1]
+
+ * configure.in:
+ back out rev 1.352
+ [1eee91c83f11]
+
+ * lex.yy.c:
+ regen
+ [72fba1c9590b]
+
+ * parse.lex:
+ use strlcpy, not strncpy
+ [4faccbaeccef]
+
+ * set_perms.c:
+ Fix typo; check pw_uid, not pw_gid after setusercontext() failure.
+ [33bf0d18fdc1]
+
+ * logging.c:
+ use pid_t
+ [3e0536993d2c]
+
+2003-03-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * strlcat.c, strlcpy.c:
+ Make gcc shutup about unused rcsid
+ [1669a0c74e9e]
+
+ * interfaces.c:
+ Move the n == 0 check for the non-getifaddrs cas
+ [2460be061b2a]
+
+ * auth/rfc1938.c:
+ skeychallenge() on NetBSD take a size parameter
+ [05acc2012801]
+
+ * configure:
+ regen
+ [24bccf4749e8]
+
+ * configure.in:
+ put -ldl after -lpam, not before; fixes static linking on Linux
+ [7f06b7b2b4d8]
+
+ * interfaces.c:
+ Avoid malloc(0) and fix the loop invariant for the getifaddrs()
+ case.
+ [239a55068646]
+
+ * sudo.cat, sudoers.cat, visudo.cat:
+ regen
+ [4a2eed3981ca]
+
+ * sudo.man.in, sudoers.man.in, visudo.man.in:
+ regen
+ [2c96ea2cf930]
+
+ * Makefile.in:
+ Preserve copyright notice from .pod file in .man.in file
+ [519fbd09aebc]
+
+ * visudo.pod:
+ Add sudoers(5) to SEE ALSO
+ [77ecfe3aedf1]
+
+2003-03-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lex.yy.c:
+ regen
+ [6f5751ce0b74]
+
+ * parse.lex:
+ Don't assume libc can realloc() a NULL string. If malloc/realloc
+ fails, make sure we just return; yyerror() is not terminal.
+ [1b8618623708]
+
+ * lex.yy.c:
+ regen
+ [5d31b46191c6]
+
+ * parse.lex:
+ simplify fill_args a little and use strlcpy for paranoia
+ [0ea35a55542b]
+
+ * sudo.tab.c:
+ regen
+ [5a8d508d708b]
+
+ * check.c, env.c, find_path.c, parse.c, parse.yacc, sudo.c,
+ testsudoers.c:
+ Use strlc{at,py} for paranoia's sake and exit on overflow. In all
+ cases the strings were either pre-allocated to the correct size of
+ length checks were done before the copy but a little paranoia can go
+ a long way.
+ [e73d28f1d14e]
+
+ * sudo.h:
+ Add strlc{at,py} protos
+ [748ffc7fc7f4]
+
+ * env.c, interfaces.c:
+ Use erealloc3()
+ [47f2cb46aba8]
+
+ * configure:
+ regen
+ [e7e2fb79f935]
+
+ * alloc.c:
+ Oflow test of nmemb > SIZE_MAX / size is fine (don't need >=). Use
+ memcpy() instead of strcpy() in estrdup() so this is strcpy()-free.
+ [7e0fa4d6fc1d]
+
+ * sudo.c:
+ snprintf() a uid as %lu, not %ld to match the MAX_UID_T_LEN test in
+ configure.
+ [09ea4d3959e9]
+
+ * aclocal.m4:
+ In MAX_UID_T_LEN test cast uid_t to unsigned long, just unsigned.
+ [31b4fdfdb8bf]
+
+2003-03-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Use snprintf() for paranoia
+ [a2659ceb46de]
+
+ * parse.yacc:
+ Use emalloc2 and erealloc3
+ [90a069842401]
+
+ * Makefile.in:
+ strlc{at,py} for those w/o it
+ [bac82dc916ee]
+
+ * strlcat.c, strlcpy.c:
+ stlc{at,py} for those w/o it.
+ [ce7254f5db09]
+
+ * config.h.in, configure, configure.in:
+ Add stlc{at,py} for those w/o it.
+ [00f08219657a]
+
+ * alloc.c, sudo.h:
+ Add erealloc3(), a realloc() version of emalloc2().
+ [c96eaf08bbed]
+
+ * interfaces.c, sudo.c:
+ Use emalloc2() to allocate N things of a certain size.
+ [1e0aba365555]
+
+ * alloc.c, sudo.h:
+ Add emalloc2() -- like calloc() but w/o the bzero and with
+ error/oflow checking.
+ [292150bc4153]
+
+ * alloc.c:
+ Error out on malloc(0); suggested by theo
+ [995279e81326]
+
+2003-03-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ fix a typo; David Krause
+ [f161213a17ab]
+
+2003-03-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod:
+ fix typo
+ [3ae5ad9a351a]
+
+2003-03-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ Remove DYLD_ from the environment for MacOS X; from bbraun
+ [38caad5a3935]
+
+2003-03-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure.in:
+ not not; Anil Madhavapeddy
+ [d4f4f0bfc66b]
+
+2003-01-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod, sudoers.pod, visudo.pod:
+ typos; jmc@openbsd.org
+ [868c0f09bf9e]
+
+2003-01-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc:
+ Add some missing ';' rule terminators that bison warns about.
+ [535b0b8dcce5]
+
+ * config.sub:
+ fix typo I introduced in last merge
+ [81db4e4f43fe]
+
+ * configure:
+ regenerate with autoconf 2.57
+ [ca0c1e9564f8]
+
+ * config.h.in:
+ Add missing "$HOME"
+ [209186197ad1]
+
+ * configure.in:
+ Add some more square backets to make autoconf 2.57 happy
+ [b5639c14faf7]
+
+ * config.guess:
+ Updates from autoconf-2.57
+ [ea0f8ca622af]
+
+ * config.sub, mkinstalldirs:
+ Updates from autoconf-2.57
+ [36be35eb331b]
+
+2003-01-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lex.yy.c, sudo.tab.c:
+ regen
+ [0b529db7cb6d]
+
+ * sudo.tab.h:
+ regen
+ [13a65a421567]
+
+ * parse.lex, parse.yacc, sudoers.pod:
+ Add support for Defaults>RunasUser
+ [20d726373175]
+
+2003-01-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ fclose() yyin after each yyparse() is done and use fopen() instead
+ of using freopen().
+ [587f8a2df857]
+
+ * parse.lex:
+ Better fix for sudoers files w/o a newline before EOF. It looks like
+ the issue is that yyrestart() does not reset the start condition to
+ INITIAL which is an issue since we parse sudoers multiple times.
+ [920f8326968a]
+
+2003-01-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.lex:
+ Work around what appears to be a flex bug when dealing with files
+ that lack a final newline before EOF. This adds a rule to match EOF
+ in the non-initial states which resets the state to INITIAL and
+ throws an error.
+ [b94943bb1f81]
+
+ * visudo.c:
+ o The parser needs sudoers to end with a newline but some editors
+ (emacs) may not add one. Check for a missing newline at EOF and add
+ one if needed. o Set quiet flag during initial sudoers parse (to get
+ options) o Move yyrestart() call and always use freopen() to open
+ yyin after initial sudoers parse.
+ [12d12f9b07aa]
+
+2002-12-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * set_perms.c:
+ Fix pasto/thinko in setresgid()/setregid() usage. Want to set
+ effective gid, not real gid, when reading sudoers.
+ [c7d18b810fcd]
+
+ * set_perms.c:
+ don't compile set_perms_posix if we have setreuid or setresuid
+ [b9cea7a81a29]
+
+2002-12-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod, sudoers.pod:
+ document new prompt escapes
+ [2f088076b640]
+
+ * check.c:
+ Add %U and %H escapes and redo prompt rewriting. "%%" now gets
+ collapsed to "%" as was originally intended. This also gets rid of
+ lastchar (does lookahead instead of lookback) which should simplify
+ the logic slightly.
+ [4b707b77b3c7]
+
+2002-12-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * tgetpass.c:
+ Write the prompt *after* turning off echo to avoid some password
+ characters being echoed on heavily-loaded machines with fast
+ typists.
+ [d38c57775915]
+
+ * config.sub:
+ Add support for mipseb; wiz@danbala.tuwien.ac.at
+ [cfdac87ed5c8]
+
+ * configure.in:
+ Fix IRIX fallout from name changes in man dir/sect Makefile
+ variables. Patch from erici AT motown DOT cc DOT utexas DOT edu
+ [9a7618755c23]
+
+ * auth/pam.c:
+ Keep a local copy of tgetpass_flags so we don't add in TGP_ECHO to
+ the global copy. Problem noted by Peter Pentchev.
+ [d0a3e189cb06]
+
+2002-11-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.tab.c:
+ regen
+ [23b931359087]
+
+ * parse.yacc:
+ Add missing yyerror() calls; YYERROR does not seem to call this for
+ us.
+ [0be7aeb3ac57]
+
+2002-11-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ fix typo in comment; Pedro Bastos
+ [d7406c460e99]
+
+2002-11-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ document --disable-setresuid
+ [fbd03d03a027]
+
+ * auth/aix_auth.c, auth/bsdauth.c, auth/fwtk.c, auth/pam.c,
+ auth/sudo_auth.c:
+ Sprinkle some volatile qualifiers to prevent over-enthusiastic
+ optimizers from removing memset() calls.
+ [5370ac0e6129]
+
+ * logging.c, parse.yacc:
+ minor sign fixes pointed out by gcc -Wsign-compare
+ [db872438337f]
+
+ * set_perms.c, sudo.c, sudo.h:
+ Revamp set_perms. We now use a version based on setresuid() or
+ setreuid() when possible since that allows us to support the
+ stay_setuid option and we always know exactly what the semantics
+ will be (various Linux kernels have broken POSIX saved uid support).
+ [523bc212396c]
+
+ * config.h.in, configure:
+ regen from configure.in
+ [351877ea2624]
+
+ * configure.in:
+ Add checks for setresuid() and a way to disable using it
+ [a5b21653d169]
+
+ * compat.h:
+ No long need to emulate set*[ug]id() via setres[ug]id() or
+ setre[ug]id(). The new set_perms stuff only uses things it knows are
+ there.
+ [47884bd5d1d9]
+
+ * sudo.c:
+ Before exec, restore state of signal handlers to be the same as when
+ we were initialy invoked instead of just reseting to SIG_DFL. Fixes
+ a problem when using sudo with nohup. Based on a patch from Paul
+ Markham.
+ [f8f5a1484faa]
+
+ * sudo.c:
+ o timestamp_uid should be uid_t, not int o clarify error message
+ when sudo is run by root and no_root_sudo is set
+ [19dda0734264]
+
+2002-09-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * README:
+ update ftp link for bison
+ [98bc191016e3]
+
+2002-07-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * set_perms.c:
+ Error out if setusercontext() fails and the runas user is not root.
+ [089f9ade4686]
+
+2002-05-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/securid5.c:
+ Fix rcsid
+ [07e9e85dcc2f]
+
+ * configure.in:
+ Fix SecurID API test
+ [5ec201f454a5]
+
+2002-05-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ typo in comment
+ [9d385c9ac533]
+
+ * configure.in:
+ securid5 stuff needs pthreads. Just adding -lpthread is suboptimal
+ but I don't see a better way at the moment.
+ [f89e55cbb313]
+
+ * Makefile.in, auth/securid5.c:
+ SecurID API version 5 support from Michael Stroucken
+ [68500ac7e531]
+
+ * configure.in:
+ Add check for SecurID 5.0 API
+ [1ee242e6de6b]
+
+2002-05-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * strerror.c:
+ We actually do still need config.h to get the 'const' definition for
+ K&R C.
+ [d9c982032d85]
+
+2002-05-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen with autoconf 2.5.3
+ [c71fc086eef5]
+
+ * configure.in:
+ Don't set sysconfdir to '/etc' if the user has specified a --prefix.
+ [d90da1efafd9]
+
+ * configure.in:
+ Some fixes for autoconf 2.53 from Robert Uhl o don't AC_SUBST
+ LIBOBJS o force a 4th arg for AC_CHECK_HEADER() to workaround a bug
+ [dd67afefa90d]
+
+ * env.c, sudo.c, sudo.h:
+ No need for dump_badenv() now that dump_defaults() knows how to dump
+ lists.
+ [6bcda468501d]
+
+ * BUGS, INSTALL, INSTALL.binary, Makefile.in, README, configure.in,
+ version.h:
+ ++version
+ [44e3b8f95f0b]
+
+ * sudoers.pod:
+ document timestampowner
+ [37ebd69e9dd1]
+
+ * check.c:
+ Don't call set_perms() when doing timestamp stuff unless
+ timestamp_uid != 0.
+ [63a63d41d18c]
+
+ * auth/sudo_auth.c, check.c, logging.c, parse.c, set_perms.c, sudo.c,
+ sudo.h, testsudoers.c:
+ g/c second arg to set_perms--it is no longer used
+ [7ac4ce50c612]
+
+2002-05-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c, set_perms.c, sudo.c, sudo.h:
+ Add support for non-root timestamp dirs. This allows the timestamp
+ dir to be shared via NFS (though this is not recommended).
+ [faa83dd2b7fb]
+
+ * def_data.c, def_data.h, def_data.in:
+ Add timestampowner, "Owner of the authentication timestamp dir"
+ [d47640d4c86a]
+
+2002-05-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ Don't try to pre-compute the size of the new envp, just allocate
+ space up front and realloc as needed. Changes to the new env pointer
+ must all be made through insert_env() which now keeps track of
+ spaced used and allocates as needed.
+ [39bc934a9f2c]
+
+2002-04-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [0e12c09bb790]
+
+ * configure.in:
+ Fix two typo/pastos; from jrj@purdue.edu
+ [b718a4bf1181]
+
+2002-04-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL.binary, README:
+ ++version
+ [a1e33027278c] [SUDO_1_6_6]
+
+ * configure, sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in,
+ visudo.cat, visudo.man.in:
+ regen
+ [19eb2be283ef]
+
+ * CHANGES, RUNSON, TODO:
+ Sync with 1.6.6
+ [2ff9a9087f63]
+
+ * check.c:
+ The the loop used to expand %h and %u, the lastchar variable was not
+ being initialized. This means that if the last char in the prompt is
+ '%' and the first char is 'h' or 'u' a extra copy of the host or
+ user name would be copied, for which space had not been allocated.
+ [b2e27197857d]
+
+2002-04-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * BUGS, INSTALL, Makefile.in, configure.in, version.h:
+ crank version to 1.6.6
+ [cfd08689e597]
+
+ * auth/afs.c:
+ #undef VOID to get rid of an AFS warning
+ [b40760564dc1]
+
+ * env.c:
+ Use easprintf instead of emalloc + sprintf for some things.
+ [e7bfe2e69a03]
+
+2002-03-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lex.yy.c, sudo.tab.c:
+ regen
+ [35327104383d]
+
+ * parse.c, parse.lex, parse.yacc, testsudoers.c:
+ Remove Chris Jepeway's email address so people don't bug him ;-)
+ [c03410747a69]
+
+2002-03-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Move endpwent() to be after set_perms(PERM_RUNAS, ...) and also call
+ endgrent() at the same time.
+ [28b6097d5d1a]
+
+2002-02-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ Make it clear which configure options take arguments.
+ [38529e7efad0]
+
+2002-01-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat.h:
+ HP-UX 9.x has RLIMIT_* but no RLIM_INFINITY. If there is no
+ RLIM_INFINITY, just pretend it is -1. This works because we only
+ check for RLIM_INFINITY and do not set anything to that value.
+ [53173d34e6eb]
+
+2002-01-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/pam.c:
+ Zero and free allocated memory when there is a conversation error.
+ [e342133db579]
+
+ * auth/bsdauth.c:
+ Use sigaction() not signal()
+ [126c2790561f]
+
+ * INSTALL:
+ Mention that some linux kernels have broken POSIX saved ID support
+ [571ef1a893d3]
+
+ * CHANGES:
+ checkpoint for 1.6.5p2
+ [9e9e456f7f43]
+
+ * configure:
+ regen
+ [d53703a46708]
+
+ * configure.in:
+ Add --disable-setreuid flag
+ [3b9f2679cb55]
+
+ * INSTALL:
+ Document new --disable-setreuid option and change description for
+ --disable-saved-ids to match new error message.
+ [14fd3e5f60a5]
+
+ * set_perms.c:
+ fatal() now takes an argument that determines whether or not to call
+ perror().
+ [d826b25e62ff]
+
+ * PORTING:
+ Update for new error messages from set_perms()
+ [60c545a6bcff]
+
+ * TROUBLESHOOTING:
+ Update for new error messages from set_perms()
+ [78007c3f76a9]
+
+2002-01-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/pam.c:
+ Make this compile w/o warnings
+ [b90843a29af5]
+
+ * auth/pam.c:
+ Mention that we can't use pam_acct_mgmt()
+ [1dfc5a6e0479]
+
+ * auth/aix_auth.c, auth/bsdauth.c, auth/fwtk.c, auth/pam.c:
+ The user's password was not zeroed after use when AIX
+ authentication, BSD authentication, FWTK or PAM was in use.
+ [b18fff30b1e7]
+
+2002-01-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/pam.c:
+ Avoid giving PAM a NULL password response, use the empty string
+ instead. This avoids a log warning when the user hits ^C at the
+ password prompt when PAM is in use.
+ [c3315805e4e4]
+
+ * auth/pam.c:
+ Don't check the return value of pam_setcred(). In Linux-PAM 0.75
+ pam_setcred() returns the last saved return code, not the return
+ code for the setcred module. Because we haven't called
+ pam_authenticate(), this is not set and so pam_setcred() returns
+ PAM_PERM_DENIED.
+ [73db145fa179]
+
+ * Makefile.binary:
+ Don't need a '/' between $(DESTDIR) and a directory.
+ [cd7eb6098b87]
+
+ * Makefile.in:
+ Don't need a '/' between $(DESTDIR) and a directory.
+ [0901ca618176]
+
+2002-01-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [41b12c039282]
+
+ * configure.in:
+ o BSDi also has a bogus setreuid() o Old FreeBSD has a bogus
+ setreuid() o new NetBSD has a real setreuid() o add check for
+ freeifaddrs() if getifaddrs() exists.
+ [a82ee3b01733]
+
+ * config.h.in, interfaces.c:
+ Older BSDi releases lack freeifaddrs() so add a test for that and if
+ it is not present just use free().
+ [6270671ea9d5]
+
+2002-01-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, RUNSON:
+ Checkpoint for 1.6.5p1
+ [26134ecf9b36]
+
+ * auth/passwd.c:
+ Return AUTH_FAILURE in passwd_init() if skeyaccess() denies access
+ to normal passwords, not AUTH_FATAL (which just causes an exit).
+ [785e0f4bc0e2]
+
+ * visudo.c:
+ Don't use memory after it has been freed.
+ [c60492739fdb]
+
+ * auth/passwd.c:
+ skeyaccess() wants a struct passwd * not a char *; Patch from
+ Phillip E. Lobbes
+ [65a1d3806fcd] [SUDO_1_6_5]
+
+ * BUGS:
+ ++version
+ [b2e1825e692e]
+
+ * CHANGES, RUNSON, TODO:
+ checkpoint for sudo 1.6.5
+ [d730945622e7]
+
+2002-01-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [49744c403ac9]
+
+ * INSTALL, INSTALL.binary, Makefile.in, README, configure.in:
+ version 1.6.5
+ [ec30a5f7fc45]
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat,
+ visudo.man.in:
+ sudo version 1.6.5
+ [458a3bed535d]
+
+ * logging.c:
+ o when invoking the mailer as root use a hard-coded environment that
+ doesn't include any info from the user's environment. Basically
+ paranoia.
+
+ o Add support for the NO_ROOT_MAILER compile-time option and run the
+ mailer as the user and not root if NO_ROOT_MAILER is defined.
+ [4df351ec92ce]
+
+ * set_perms.c, sudo.h:
+ Bring back PERM_FULL_USER
+ [edb6039bb284]
+
+ * configure:
+ regen
+ [3eb2943afa03]
+
+ * version.h:
+ version 1.6.5
+ [044fc9a0c72b]
+
+ * INSTALL, config.h.in, configure.in:
+ Add --disable-root-mailer option to run the mailer as the user and
+ not root.
+ [e9f805397963]
+
+ * CHANGES:
+ checkpoint for 1.6.4p2
+ [b58aae5aa98a]
+
+ * PORTING:
+ Mention the "seteuid(0): Operation not permitted" problem here too
+ just for good measure.
+ [90135b37a691]
+
+2002-01-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c, getspwuid.c, sudo.c:
+ The SHELL environment variable was preserved from the user's
+ environment instead of being reset based on the passwd database when
+ the "env_reset" option was used. Now it is reset as it should be.
+ [300066ef3c71]
+
+ * configure:
+ regen
+ [a47d779e6552]
+
+ * INSTALL, TROUBLESHOOTING, config.h.in, configure.in, set_perms.c,
+ sudo.c:
+ Add a configure option to turn off use of POSIX saved IDs
+ [fb18cc8e94d0]
+
+ * configure:
+ regen
+ [d4f2f20025b6]
+
+ * configure.in:
+ add --with-efence option
+ [45c4f33a8e88]
+
+ * sudo.c:
+ Only OR in MODE_RESET_HOME if MODE_RUN is set. Fixes a problem where
+ "sudo -l" would not work if always_set_home was set.
+ [c3a6de6c4800]
+
+ * lex.yy.c:
+ regen
+ [417424452998]
+
+ * parse.lex:
+ Quoted commas were not being treated correctly in command line
+ arguments.
+ [753415541b37]
+
+ * sudo.c:
+ o Move the call to rebuild_env() until after MODE_RESET_HOME is set.
+ Otherwise, the set_home option has no effect.
+
+ o Fix use of freed memory when the "fqdn" flag is set. This was
+ introduced by the fix for the "segv when gethostbynam() fails" bug.
+ Also, we no longer call set_fqdn() if the "fqdn" flag is not set so
+ there is no need to check the "fqdn" flag in set_fqdn() itself.
+ [4b6a4245c04e]
+
+ * env.c:
+ Add 'continue' statements to optimize the switch statement. From
+ Solar.
+ [a82c76975ae5]
+
+2002-01-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.cat, sudoers.man.in:
+ Regen from new sudoers.pod
+ [6ecc07b3d0e1] [SUDO_1_6_4]
+
+ * sudoers.pod:
+ Add caveat about stay_setuid flag
+ [9d228a7bea1b]
+
+ * sudo.c:
+ If set_perms == set_perms_posix and the stay_setuid flag is not set,
+ set all uids to 0 and use set_perms_fallback().
+ [c4e54d1ec86f]
+
+ * set_perms.c, sudo.h:
+ Remove PERM_FULL_USER (which is no longer used) and add
+ PERM_FULL_ROOT (used when exec'ing the mailer).
+ [15406c522ea2]
+
+ * logging.c:
+ Use set_perms(PERM_FULL_ROOT, 0) before exec'ing the mailer since we
+ never want to run the mailer setuid.
+ [2294853e0666]
+
+2002-01-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.cat, sudo.man.in, sudo.pod, visudo.cat, visudo.man.in,
+ visudo.pod:
+ Use sudo.ws instead of courtesan.com in URLs
+ [55204002a308]
+
+ * Makefile.binary, Makefile.in:
+ Fix mansect substitution
+ [b7b5cbc3aa91]
+
+ * Makefile.in:
+ Substitute man sections in Makefile.binary
+ [040deb785e56]
+
+ * Makefile.binary:
+ Sync install targets with Makefile.in and substitute in man
+ sections.
+ [77882a275281]
+
+ * INSTALL, INSTALL.binary:
+ version is 1.6.4
+ [0f87aabbcb70]
+
+ * Makefile.in:
+ Repair bindist target
+ [8d43bfe7e2d1]
+
+ * CHANGES:
+ sync for 1.6.4
+ [13ca3d4a0a72]
+
+2002-01-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * install-sh:
+ Fix case where neither whoami nor id are found
+ [424dd270bc47]
+
+2002-01-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * install-sh:
+ If neither whoami nor id exists, just assume we are root.
+ [2d2644e42c53]
+
+ * alloc.c:
+ Add explicit cast to (VOID *) on malloc/realloc. Seems to be needed
+ on AIX which for some reason isn't pulling in the malloc prototype.
+ [231440d2ee3b]
+
+2002-01-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, aclocal.m4, compat.h, parse.c, sudo.c:
+ (c) 2002
+ [700e3b41a68e]
+
+ * CHANGES:
+ checkpoint
+ [33e604bd8d5b]
+
+ * sudo.c:
+ Defer assigning new environment until right before the exec.
+ [f13c49e75c1c]
+
+ * parse.c:
+ kill extra blank line
+ [12ef22e9dae3]
+
+2002-01-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [a6cd2d788f74]
+
+ * configure.in:
+ Use -O not -O2 for m88k-motorola-sysv* since motorola gcc-derived
+ compiler doesn't recognise -O2.
+ [5234aa543692]
+
+ * HISTORY:
+ Clarify origins of Root Group sudo a bit based on info from
+ billp@rootgroup.com
+ [4deef01c4208]
+
+2002-01-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * LICENSE:
+ 2002
+ [6c8e089dbd1a]
+
+ * CHANGES:
+ checkpoint for 1.6.4rc1
+ [3349eb87a49f]
+
+2002-01-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in:
+ now generated via autoheader
+ [84657d303cb9]
+
+ * configure:
+ regen
+ [207bfa6a13f6]
+
+ * compat.h:
+ Move in some stuff that was previously in config.h.
+ [e576d8b6480f]
+
+ * aclocal.m4, configure.in:
+ Add info for autoheader.
+ [0549cd5da27c]
+
+2002-01-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ o Add DESTDIR support o Use -M, -O, and -G instead of -m, -o, and -g
+ to facilitate non-root installs
+ [619216038f56]
+
+ * install-sh:
+ Add -M option (like -m but only for root) If we can't find "whoami",
+ use "id" w/ some sed.
+ [b39121c8b792]
+
+ * configure:
+ regen
+ [b39b93ff9804]
+
+ * configure.in:
+ allow user to always override mansectsu and mansectform
+ [0fca5e63bd90]
+
+2001-12-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkinstalldirs:
+ update from autoconf 2.52
+ [07bd75a508c3]
+
+ * config.guess, config.sub:
+ Update from autoconf 2.52
+ [857b90fe31b7]
+
+ * configure:
+ regen with autoconf 2.52
+ [08e7d1ea2aeb]
+
+ * configure.in:
+ o Call AC_PROG_CC_STDC to find out how to run the compiler in ANSI
+ mode o Remove compiler-specific checks for HP-UX now that we use
+ AC_PROG_CC_STDC
+ [d433a70b6208]
+
+ * RUNSON:
+ Checkpoint
+ [babf6d2235d1]
+
+ * auth/pam.c:
+ o Add pam_prep_user function to call pam_setcred() for the target
+ user; on Linux this often sets resource limits. o When calling
+ pam_end(), try to convert the auth->result to a PAM_FOO value. This
+ is a hack--we really need to stash the last PAM_FOO value received
+ and use that instead.
+ [6ad6f340dd2a]
+
+ * set_perms.c, sudo.h:
+ o Add pam_prep_user function to call pam_setcred() for the target
+ user; on Linux this often sets resource limits.
+ [67795421ac82]
+
+ * env.c:
+ Fix off by one error in number of bytes allocated via malloc (does
+ not affected any released version of sudo).
+ [5f5915360111]
+
+2001-12-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lex.yy.c:
+ regen
+ [8208c0277775]
+
+ * parse.lex:
+ Allow '@', '(', ')', ':' in arguments to a defaults variable w/o
+ requiring that they be quoted.
+ [ae59bc8f68dd]
+
+ * sudoers.cat, sudoers.man.in, sudoers.pod:
+ Mention that no double quotes are needed when
+ adding/deleting/assigning a single value to a list.
+ [25efc940a1f0]
+
+ * Makefile.in:
+ Don't rely on mkdefaults being executable, call perl explicitly.
+ [6edc97ba5f1d]
+
+ * sudo.tab.c:
+ regen
+ [49130b2e7e4d]
+
+ * parse.yacc:
+ Remove some XXX that are no longer relevant.
+ [d460ac0d3767]
+
+ * defaults.c:
+ o Roll our own loop instead of using strpbrk() for better
+ grokability o When adding to a list we must malloc() and use
+ memcpy(), not strdup() since we must only copy len bytes from str.
+ [649bef08e1f0]
+
+2001-12-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.tab.c:
+ regen
+ [f0bbf2c38c0e]
+
+ * parse.yacc:
+ typo in comment
+ [2563711ff593]
+
+2001-12-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ checkpoint
+ [a6d8a29fb30e]
+
+ * configure:
+ regen
+ [bdfcaaf3bd13]
+
+ * configure.in:
+ avoid the -g flag unless --with-devel was specified
+ [a976707bef30]
+
+ * Makefile.in:
+ mkdefaults, def_data.in and sigaction.c were missing from the
+ tarball
+ [6917ffbaa412]
+
+ * Makefile.in:
+ def_data.c was missing
+ [87c78b11453d]
+
+2001-12-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ Fix setting of $USER and $LOGNAME in the non-reset_env case. Also
+ allow HOME, SHELL, LOGNAME, and USER to be specified in keep_env
+ [fc8698e6a45e]
+
+ * TODO:
+ Another TODO item
+ [6f251d6cd466]
+
+ * sudoers:
+ Add comment for Default section so folks know where it should go.
+ [7edba626f392]
+
+2001-12-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * tgetpass.c:
+ Use TCSETAF, not TCSETA to set terminal in termio case
+ [fbd172f6c5d3]
+
+ * sudoers.cat, sudoers.man.in:
+ regen from sudoers.pod
+ [64edd2de816e]
+
+ * sudoers.pod:
+ o Typo, Runas_User_List should be Runas_List o a User_List can not
+ contain a uid o mention that the Defaults section should come after
+ Alias definitions but before the user specifications
+ [54070ba2092b]
+
+2001-12-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.cat, sudoers.man.in:
+ regen
+ [e62d1d97693c]
+
+ * sudoers.pod:
+ Fix listpw and verifypw sections, they were not being formatted
+ properly.
+ [123868c2f3e9]
+
+ * sudoers.cat, sudoers.man.in:
+ regen
+ [f94841f8b374]
+
+ * sudoers.pod:
+ fix typos
+ [f278f1c1184e]
+
+ * configure:
+ regen
+ [d2270049ba9f]
+
+ * config.h.in, configure.in:
+ use AC_SYS_POSIX_TERMIOS instead of rolling our own
+ [c1a13f1354b9]
+
+ * README:
+ Reference sudo.ws not courtesan.com
+ [ca13be67ebd7]
+
+ * PORTING:
+ Add notes on shadow passwords
+ [aa13863f2314]
+
+ * BUGS:
+ In list mode (sudo -l), characters escaped with a backslash are
+ shown verbatim with the backslash.
+ [1a75a2858be2]
+
+ * sudoers:
+ Add simple examples from OpenBSD (Marc Espie)
+ [3ae9a9ae4125]
+
+ * tgetpass.c:
+ Catch SIGTTIN and SIGTTOU too and treat them like SIGTSTP.
+ [f8817699ee10]
+
+ * CHANGES:
+ minor prettyification
+ [f523587929b9]
+
+ * CHANGES:
+ Updated change log
+ [39d9010ee7a8]
+
+ * testsudoers.c:
+ Fix CIDR handling here too.
+ [c91db8344c32]
+
+ * auth/pam.c:
+ Apparently a NULL response is OK
+ [83bae61078d9]
+
+ * TODO:
+ Checkpoint for upcoming beta release
+ [efb95c09df2a]
+
+ * TROUBLESHOOTING:
+ Many people believe that adding a runas spec should obviate the need
+ for the -u flag. It does not.
+ [c698bad85b0e]
+
+ * RUNSON:
+ checkpoint update for upcoming 1.6.4 beta
+ [009e465a0a45]
+
+ * config.h.in:
+ o Add HAVE_STDLIB_H and HAVE_MEMORY_H o Define HAVE_STRINGS_H even
+ if HAVE_STRING_H is defined -- this is safe now
+ [d27c035f4e14]
+
+ * PORTING:
+ Add signals section
+ [2d24c13cb3c8]
+
+ * configure:
+ regen
+ [2b80a939e2ed]
+
+ * configure.in:
+ Fix check for sigaction_t
+ [6fa41c89ab20]
+
+ * sudo.c:
+ XXX - should call find_path() as runas user, not root. Can't do that
+ until the parser changes though.
+ [f0b4f85651bd]
+
+ * sudo.c:
+ If find_path() fails as root, try again as the invoking user (useful
+ for NFS). Idea from Chip Capelik.
+ [e03fa7872692]
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in:
+ Regenerate after pod file changes
+ [48e4bd75ec21]
+
+ * def_data.c, def_data.h, def_data.in, set_perms.c, sudo.c, sudo.h,
+ sudo.pod, sudoers.pod:
+ Add new sudoers option "preserve_groups". Previously sudo would not
+ call initgroups() if the target user was root. Now it always calls
+ initgroups() unless the -P command line option or the
+ "preserve_groups" sudoers option is set. Idea from TJ Saunders.
+ [4f730359f101]
+
+2001-12-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat.h, config.h.in:
+ Use new HAVE_SIGACTION_T define
+ [dfb25f3cae5b]
+
+ * logging.c:
+ Fix compilation on K&C
+ [7355e3275e34]
+
+ * configure:
+ regen
+ [a710584f92f0]
+
+ * configure.in:
+ Add check for sigaction_t -- IRIX already defines this so don't
+ redefine it.
+ [df9c5737f6da]
+
+ * snprintf.c:
+ fix typo
+ [3d782b8134c8]
+
+ * interfaces.c:
+ need stdlib.h here too
+ [c789d8973ab2]
+
+ * configure:
+ regen
+ [44822856bf46]
+
+ * configure.in:
+ Remove redundant checks for string.h, strings.h and unistd.h
+ [933c94f8bbf4]
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat,
+ visudo.man.in:
+ Regen from pod files
+ [ad18c590f638]
+
+ * BUGS:
+ Update for 1.6.4
+ [26bc88b69d22]
+
+ * configure, lex.yy.c, sudo.tab.c:
+ regen
+ [bef89fd6fa2d]
+
+ * strerror.c:
+ Return EINVAL if errnum > sys_nerr
+ [0512374e6661]
+
+ * auth/sudo_auth.h:
+ o Update copyright year
+ [a877016db6e2]
+
+ * LICENSE, Makefile.binary, Makefile.in, aclocal.m4, compat.h,
+ config.h.in, defaults.h, interfaces.h, pathnames.h.in, sudo.h,
+ sudo.pod:
+ o Update copyright year
+ [e15a1b39039f]
+
+ * configure.in:
+ o Don't define STDC_HEADERS unconditionally for IRIX o Update
+ copyright year
+ [82a8cb819e07]
+
+ * README:
+ update version
+ [d82e523a16b4]
+
+ * auth/afs.c, auth/aix_auth.c, auth/bsdauth.c, auth/dce.c,
+ auth/fwtk.c, auth/kerb4.c, auth/kerb5.c, auth/pam.c, auth/passwd.c,
+ auth/rfc1938.c, auth/secureware.c, auth/securid.c, auth/sia.c,
+ auth/sudo_auth.c, logging.c, parse.c, parse.lex, parse.yacc,
+ set_perms.c, snprintf.c, sudo.c, testsudoers.c, tgetpass.c, utime.c,
+ visudo.c:
+ o Reorder some headers and use STDC_HEADERS define properly o Update
+ copyright year
+ [fe39f76b3795]
+
+ * lsearch.c:
+ o Reorder some headers and use STDC_HEADERS define properly o Update
+ copyright year
+ [764ba3d4fa13]
+
+ * alloc.c, check.c, defaults.c, env.c, fileops.c, find_path.c,
+ fnmatch.c:
+ o Reorder some headers and use STDC_HEADERS define properly o Update
+ copyright year
+ [dab8f192a3ed]
+
+ * getcwd.c:
+ o Reorder some headers and use STDC_HEADERS define properly o Update
+ copyright year
+ [b199d70ac7ab]
+
+ * getspwuid.c, goodpath.c, interfaces.c:
+ o Reorder some headers and use STDC_HEADERS define properly o Update
+ copyright year
+ [fb46d46140d4]
+
+ * configure:
+ regen
+ [156658f25cea]
+
+ * tgetpass.c:
+ flags set in signal handlers should be volatile sig_atomic_t
+ [c22931a5535e]
+
+ * config.h.in, configure.in:
+ Add checks for volatile and sig_atomic_t
+ [b03b3341381d]
+
+ * configure, lex.yy.c:
+ regen
+ [ed9daba88217]
+
+ * def_data.c, def_data.h, def_data.in, defaults.c, env.c, find_path.c,
+ sudo.c, sudoers.pod:
+ Remove "secure_path" Defaults option since it cannot work with the
+ existing parser.
+ [c9e54a0f5971]
+
+ * find_path.c, sudo.c:
+ Unset "secure_path" if user_is_exempt()
+ [fb7544565ae8]
+
+ * env.c, pathnames.h.in:
+ o Remove assumption that PATH and TERM are not listed in env_keep o
+ If no PATH is in the environment use a default value o If TERM is
+ not set in the non-reset case also give it a default value.
+ [c987eb7df268]
+
+ * aclocal.m4, configure.in, defaults.c, pathnames.h.in:
+ _PATH_SENDMAIL -> _PATH_SUDO_SENDMAIL so --without-sendmail works on
+ systems that define in paths.h
+ [51865b0cdebf]
+
+ * auth/passwd.c, auth/sudo_auth.c, auth/sudo_auth.h:
+ Add support for skeyaccess(3) if it is present in libskey.
+ [8add77c7d3e7]
+
+2001-12-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Only need to do 'lc = login_getclass(NULL)' if lc == NULL
+ [5a3d3cbf2c6d]
+
+ * parse.lex:
+ '\\' is a perfectly legal character to have in a command line
+ argument.
+ [c15a466ef00e]
+
+ * sudo.c:
+ o Defer call to set_fqdn() until it is safe to use log_error() o
+ Don't print errno string value if gethostbyname fails, it is not
+ relevant
+ [c0c6bcf08bcb]
+
+ * parse.c:
+ Fix CIDR -> in_addr_t conversion.
+ [2f307ebeb63f]
+
+2001-12-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ Remove an extra "User_List" in the User_Spec definition From
+ ybertrand AT snoopymail.com
+ [97bde59ea280]
+
+ * parse.c:
+ Make 'listpw=never' work for users who are not explicitly mentioned
+ in sudoers.
+ [258f0f30a428]
+
+ * sudoers.pod:
+ Remove gratuitous '=' in EBNF grammar; era AT iki.fi
+ [4b0f03872ee1]
+
+ * sudoers.pod:
+ Document new list Defaults type and convert env_keep and env_delete
+ to lists. Document new env_check option.
+ [a07f1f079fe3]
+
+ * lex.yy.c, sudo.tab.c, sudo.tab.h:
+ regen parser
+ [e39ac6c6581b]
+
+ * parse.lex:
+ Don't let '#' appear in a {WORD} and restrict #foo in a Runas spec
+ to #[0-9-]+.
+ [69c5388908f3]
+
+ * configure:
+ regen
+ [0f1877b88cb3]
+
+ * aclocal.m4:
+ Simpler SUDO_FUNC_ISBLANK that uses AC_TRY_LINK
+ [6545503ae361]
+
+ * config.h.in, configure.in:
+ Add check for skeyaccess(3)
+ [6caf69fe6359]
+
+ * visudo.pod:
+ Document new -c, -f, and -q options
+ [13d0203c21d3]
+
+ * visudo.c:
+ o Add -f option (alternate sudoers file) o Convert to use getopt(3)
+ [4c2b664d617d]
+
+ * configure:
+ regen
+ [6d5bd932e7b5]
+
+ * aclocal.m4, config.h.in, configure.in:
+ Add check for isblank and a replacement macro if it doesn't exist.
+ [b524f5e4f953]
+
+2001-12-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ In check-only mode, don't create sudoers if it does not already
+ exist.
+ [c748a2d5acad]
+
+ * parse.yacc:
+ o Add a new token, DEFVAR, to indicate a Defaults variable name o
+ Add support for "+=" and "-=" list operators o replace some 1 and 0
+ with TRUE and FALSE for greater legibility.
+ [554cb174b37e]
+
+ * parse.lex:
+ o Use exclusive start conditions to remove some ambiguity in the
+ lexer. Also reorder some things for clarity. o Add support for "+="
+ and "-=" list operators. o Use the new DEFVAR token to denote a
+ Defaults variable name.
+ [3a2cf8323e26]
+
+ * sudo.h:
+ Prototype init_envtables()
+ [b74916469dab]
+
+ * env.c:
+ o Convert environment handling to use lists instead of strings. This
+ greatly simplifies routines that need to do "foreach" type
+ operations. o Add new init_envtables() function to set env_check and
+ env_delete defaults based on initial_badenv_table and
+ initial_checkenv_table (formerly sudo_badenv_table).
+ [0a8b404658b6]
+
+ * defaults.c, defaults.h:
+ o Add a new LIST type and functions to manipulate it. o This is for
+ use with environment handling variables. o Call new init_envtables()
+ routine inside init_defaults() to initialize the environment lists.
+ [ae73e64f0902]
+
+ * def_data.c, def_data.h, def_data.in:
+ Convert environment options to use the new LIST type and add a new
+ one, env_check that only deletes if the sanity check fails.
+ [3019503936de]
+
+ * testsudoers.c:
+ Add dummy version of init_envtables()
+ [9d9e3ee609d9]
+
+ * parse.yacc:
+ honor quiet mode
+ [8330fba6167c]
+
+ * visudo.c:
+ Add check-only mode
+ [dab411bc8c35]
+
+ * mkdefaults:
+ Fix generation of entries with NULL descriptions.
+ [ea75b9fed02e]
+
+2001-12-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * tgetpass.c:
+ Use sigaction_t and quiet a gcc warning.
+ [6f67d719c452]
+
+ * sudo.c:
+ Must reset signal handlers before we exec
+ [300418120e1a]
+
+ * auth/aix_auth.c, auth/bsdauth.c, auth/fwtk.c, auth/pam.c,
+ auth/sudo_auth.c:
+ Be carefule now that tgetpass() can return NULL (user hit ^C). PAM
+ version needs testing. Set SIGTSTP to SIG_DFL during password entry
+ so user can suspend us.
+ [00304aa58747]
+
+ * tgetpass.c:
+ Add support for interrupting/suspending tgetpass via keyboard input.
+ If you suspend sudo from the password prompt and resume it will re-
+ prompt you.
+ [4af2b5101d32]
+
+ * sudo.c:
+ Don't block keyboard interrupt signals, just set them to SIG_IGN.
+ [d46d7f67ef6b]
+
+2001-12-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in:
+ add back HAVE_SIGACTION
+ [c9c7702c603e]
+
+ * configure:
+ regen
+ [09fe669d337f]
+
+ * config.h.in, configure.in, logging.c, sudo.c, visudo.c:
+ Kill POSIX_SIGNALS define and old signal support now that we emulate
+ POSIX ones Also be sure to correctly initialize struct sigaction.
+ [4bc2a6dbb2be]
+
+ * strerror.c:
+ Don't need config.h or "#ifndef HAVE_STRERROR" wrapper.
+ [1ad64a19f328]
+
+ * compat.h:
+ Add scaffolding for POSIX signal emulation
+ [945861d4c93b]
+
+ * sigaction.c:
+ o Add missing ';' so this compiles o Can't use NULL since we don't
+ include stdio.h
+ [04d0cac7438f]
+
+ * sigaction.c:
+ Emulate sigaction() using sigvec()
+ [d0b54a989875]
+
+2001-11-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ Document new behavior of negative values of timestamp_timeout Fix a
+ typo
+ [4c0716570d01]
+
+ * sudo.pod:
+ Add security note about command not being logged after 'sudo su' and
+ friends.
+ [43294851a33c]
+
+ * sudo.pod:
+ Mention that -V prints default values when run as root, including
+ the list of environment variables to clear.
+ [d9e5e550a8c3]
+
+ * Makefile.in:
+ Run pod2man with --quotes=none to avoid stupid quoting of C<>
+ entries.
+ [997b23c35dbe]
+
+2001-11-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/sudo_auth.c, def_data.c, def_data.h, def_data.in, sudoers.pod:
+ Add mail_badpass option Also modify mail_always behavior to also
+ send mail when the password is wrong
+ [838d40ccafce]
+
+ * env.c, sudo.c, sudo.h:
+ Dump default bad env table when 'sudo -V' is run by root.
+ [f67f1b8048b0]
+
+ * sudoers.pod:
+ document env_delete
+ [d74f893663a2]
+
+ * env.c:
+ Add support for '*' in env_keep when not resetting the environment
+ (ie: the normal case).
+ [fd4fb62ea8fd]
+
+ * env.c:
+ Add env_delete variable that lets the user replace/add to the
+ bad_env_table. Allow '*' wildcard in env_keep entries.
+ [aa728bc35e29]
+
+2001-11-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkinstalldirs:
+ Force umask to 022 to guarantee sane directory permissions.
+ [9ab3cfe70569]
+
+2001-11-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ add sudo.tab.h and sudo.tab.c to sudo.tab.o dependency
+ [671010465e6f]
+
+ * mkdefaults:
+ fix breakage in last commit
+ [8318f8851e56]
+
+ * Makefile.in:
+ acsite.m4 -> aclocal.m4
+ [30c146873a01]
+
+ * check.c:
+ fix I_TS_TIMEOUT vs. I_TIMESTAMP_TIMEOUT pasto in previous commit
+ [4dc8b39954da]
+
+ * def_data.c:
+ regenerated from def_data.in
+ [915ea16ce1eb]
+
+ * check.c, defaults.c, defaults.h:
+ Add new T_UINT type that most things use instead of T_INT If
+ timestamp_timeout is < 0 then treat the ticket as never expiring (to
+ be expired manually by the user).
+ [3a3a636a2a5d]
+
+ * def_data.in:
+ change most T_INT -> T_UINT
+ [a2228d2457af]
+
+ * mkdefaults:
+ fix warning when no args
+ [ca70a5394af5]
+
+ * visudo.c:
+ Change 2 Exit() -> exit() Avoid stdio in Exit() and call _exit() if
+ we are a signal handler. We no longer print the signal number but
+ the user can just check the exit value for that.
+ [dc424f631fef]
+
+2001-10-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ when setting up pipes in child process check for case where stdin ==
+ pipe fd 0
+ [518112d76184]
+
+2001-10-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ Ignore editor exit value since XPG4 says vi's exit value is the
+ count of editing errors made (failed searches, etc).
+ [b9d952284865]
+
+2001-10-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [cb3aa586f03b]
+
+ * configure.in:
+ sco now is identified by config.guess as *-sco-*
+ [46664bbdea61]
+
+ * configure.in:
+ Check for getspnam() in -lgen if not in -lc for UnixWare.
+ [0f152ad1ba93]
+
+2001-09-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod, visudo.pod:
+ "upper case" -> "uppercase"
+ [f9151f232326]
+
+ * sudoers.pod:
+ fix typos and grammar; pjanzen@foatdi.harvard.edu
+ [2855d73d0237]
+
+2001-08-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ Missing word (specify); krapht@secureops.com
+ [65523eb37a2c]
+
+2001-08-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ If we fail to lookup a login class, apply the default one.
+ [d4869faa6816]
+
+ * logging.c:
+ In log_error() free message, not logline unconditionally, then free
+ logline if it is not the same as message. No function change but
+ this mirrors how they are allocated.
+ [565e5f6cc643]
+
+2001-07-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regenerate
+ [834a48f548a2]
+
+ * configure.in:
+ remove some backslash quotes that are unneeded
+ [50d401d6e2ca]
+
+ * configure.in:
+ o Tweaks to make this work with autoconf-2.50 o Use AC_LIBOBJ
+ instead of changing LIBOBJS directly o Use AC_REPLACE_FUNCS where we
+ can o Use AC_CHECK_FUNCS instead of AC_CHECK_FUNC so we don't have
+ to AC_DEFINE things manually.
+ [f502c5f15f92]
+
+ * config.guess, config.sub:
+ Updated from autoconf-2.50
+ [6140205915ef]
+
+2001-05-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * README:
+ Update mailing list section. We use mailman now, not majordomo.
+ [b9a8ca45e6dc]
+
+2001-05-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * getspwuid.c, logging.c, sudo.c:
+ Use setpwent()/endpwent() + all the shadow variants to make sure we
+ don't inadvertantly leak an fd to the child. Apparently Linux's
+ shadow routines leave the fd open even if you don't call setspent().
+ Reported by mike@gistnet.com; different patch used.
+ [d33792ef6c01]
+
+2001-04-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ s/eg./e.g./
+ [bd32a0acaf93]
+
+ * tgetpass.c:
+ select() may return EAGAIN. If so, continue like we do for EINTR.
+ [5f202c943818]
+
+ * logging.c:
+ Fix a non-exploitable buffer overflow in the word splitting code.
+ This should really be rewritten.
+ [4c724363863a]
+
+ * Makefile.in:
+ FAQ link goes away
+ [1d26dd6c8972]
+
+ * INSTALL:
+ Tell people to look in sample.syslog.conf for examples, not FAQ
+ [affcae3f43ca]
+
+ * TROUBLESHOOTING:
+ Update list of env vars that are cleared
+ [234e56f1435a]
+
+ * sudo.c:
+ remove struct env_table decl since that stuff has all moved to env.c
+ [5dd923148777]
+
+2001-04-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * fileops.c:
+ Fix a pasto in flock-style unlocking and include <sys/file.h> for
+ flock on older systems; twetzel@gwdg.de
+ [d5420d9d2861]
+
+ * configure:
+ regen to get NeXT lockf/flock fix
+ [d3ba6ed70e15]
+
+ * configure.in:
+ force NeXT to use flock since lockf is broken
+ [bd5391dca1bb]
+
+2001-03-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ Use stashed user_gid when checking against exempt gid since sudo
+ sets its gid to a a value that makes sudoers readable. Previously if
+ you used gid 0 as the exempt group everyone would be exempt. From
+ Paul Kranenburg <pk@cs.few.eur.nl>
+ [0b140cc3a817]
+
+2001-03-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [cc455408f32b]
+
+ * aclocal.m4:
+ #include stdio.h in SUDO_CHECK_TYPE since IRIX 6 aparently defines
+ some types (such as ssize_t) therein.
+ [b6aee85ca331]
+
+2001-03-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * defaults.c:
+ Fix negation of paths in a boolean context. Problem found by
+ apt@UH.EDU
+ [8aee217a7cdf]
+
+2001-02-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ pasto
+ [ad32b277bf68]
+
+2001-02-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ SA_RESETHAND means the opposite of what I was thinking--oops To
+ block all signals in old-style signals use ~0, not 0xffffffff
+ [6ecdd793590a]
+
+2001-02-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * defaults.c:
+ coerce difference of pointers to int when used in a string length
+ printf format; deraadt@openbsd.org
+ [a9d10f07180d]
+
+2001-01-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ Block all signals in Exit() to avoid a signal race. There is still a
+ tiny window but I'm not going to worry about it.
+ [6661805c0458]
+
+2001-01-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * env.c:
+ glibc uses the LANGUAGE env var so clear that too; Solar Designer
+ [d4ba95628afb]
+
+ * lex.yy.c:
+ Regenerate with a fix to flex.skl that preserves errno from
+ clobbering by isatty().
+ [607eec736e19]
+
+2000-12-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/aix_auth.c, auth/bsdauth.c, auth/fwtk.c, auth/pam.c,
+ auth/sia.c, auth/sudo_auth.c:
+ Some defaults I_ defines got renamed.
+ [ec19b23caaf3]
+
+ * Makefile.in, check.c, def_data.c, def_data.h, def_data.in,
+ defaults.c, defaults.h, env.c, logging.c, mkdefaults, parse.yacc,
+ set_perms.c, sudo.c, sudo.tab.c:
+ Move defaults info into its own files from which we generate .h and
+ .c files. This makes adding or rearranging variables much simpler.
+ [e91b880b5043]
+
+2000-12-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ fix typo in last commit
+ [10a6ee2bae71]
+
+ * compat.h, config.h.in, configure, configure.in:
+ Add check + emulation for setegid (like seteuid).
+ [29492092bd2f]
+
+ * env.c:
+ Make env_keep override badenv_table as documented Fix traversal of
+ badenv_table (broken in last commit)
+ [37c9f0d22673]
+
+ * set_perms.c, sudo.c, sudo.h:
+ Don't try and build saved uid version of set_perms on systems w/o
+ them. Rename set_perms_saved_uid() -> set_perms_posix() Make
+ set_perms_setreuid simply be set_perms_fallback() and simply include
+ the appropriate function at compile time (setreuid() vs. setuid()).
+ [3107333c062c]
+
+ * sudoers.cat, sudoers.man.in, sudoers.pod:
+ PATH is also preserved when env_reset is in effect
+ [90e45c5711ff]
+
+ * CHANGES, Makefile.in, check.c, compat.h, config.h.in, configure,
+ configure.in, defaults.c, defaults.h, env.c, find_path.c,
+ getspwuid.c, set_perms.c, sudo.c, sudo.cat, sudo.h, sudo.man.in,
+ sudo.pod, sudoers.cat, sudoers.man.in, sudoers.pod, testsudoers.c,
+ visudo.c, visudo.cat, visudo.man.in:
+ New Defaults options: o stay_setuid - sudo will remain setuid if
+ system has saved uids or setreuid(2) o env_reset - reset the
+ environment to a sane default o env_keep - preserve environment
+ variables that would otherwise be cleared
+
+ No longer use getenv/putenv/setenv functions--do environment munging
+ by hand. Potentially dangerous environment variables can be cleared
+ only if they contain '/' pr '%' characters to protect buggy
+ programs. Moved environment routines into env.c (new file)
+ [c2f97651db4c]
+
+ * INSTALL:
+ Clear up --without-passwd description
+ [2f336dab6733]
+
+ * putenv.c, sudo_setenv.c:
+ We now build up a new environment from scratch and assign it to
+ "environ".
+ [6ae6152f2238]
+
+2000-12-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod, visudo.pod:
+ Grammatical fixes from Paul Janzen
+ [e03ead2e56f8]
+
+2000-12-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ If there was a syntax error and the user just wants to quit, unlink
+ sudoers if it is zero length.
+ [74ba7921f520]
+
+ * visudo.c:
+ 'Q' means ignore parse error, not 'q'
+ [e8d0e4491fe6]
+
+ * visudo.c:
+ Open sudoers for writing with mode SUDOERS_MODE From Dimitry Andric
+ <dim@xs4all.nl>
+ [b24990a72491]
+
+2000-12-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * set_perms.c:
+ Add missing #ifdef HAVE_LOGIN_CAP_H; ayamura@ayamura.org
+ [41a8db10e076]
+
+2000-12-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.guess, config.sub:
+ Darwin / Mac OS X support from Wilfredo Sanchez <wsanchez@apple.com>
+ [6052da895d2e]
+
+2000-11-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c, visudo.c:
+ Use exit(127), not exit(-1)
+ [9ff0c3eada34]
+
+ * Makefile.in, defaults.c, defaults.h, set_perms.c, sudo.c:
+ Move set_perms() to its own file and use POSIX saved uid or
+ setreuid() if available.
+
+ Added stay_setuid option for systems that have libraries that
+ perform extra paranoia checks in system libraries for setuid
+ programs (ie: anything with issetugid(2)).
+ [28960f842698]
+
+ * sudo.c:
+ strip more bits from the environment and add a facility for
+ stripping things only if they contain '/' or '%' to address printf
+ format string vulnerabilities in other programs.
+ [b98d6375f299]
+
+2000-11-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [7e74e5c91049]
+
+ * configure.in:
+ For NCR, add -lc89 to LIBS, not SUDO_LIBS and cache the existence of
+ strcasecmp().
+ [a418e9e70442]
+
+ * configure:
+ regen
+ [bbff244a52bc]
+
+ * configure.in:
+ Check for strcasecmp(3) in -lc89 for NCR Unix
+ [361c99576681]
+
+2000-11-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in:
+ Define HAVE_INNETGR #ifdef HAVE__INNETGR
+ [473cdb92b6db]
+
+ * configure:
+ regen
+ [4e6364a195e0]
+
+ * compat.h, config.h.in, configure.in:
+ Add check for _innetgr(3) since NCR systems have that instead of
+ innetgr(3).
+ [25e6852e7494]
+
+2000-10-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/securid.c:
+ check return value of creadcfg() call sd_close() after sd_auth()
+ store username in sd->username so we don't rely on the USER env
+ variable
+ [d106b4f42722]
+
+2000-10-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ document --with-bsdauth
+ [f1518ecc2ee9]
+
+ * configure:
+ regen
+ [dceb35071ea8]
+
+ * configure.in:
+ --with-bsdauth assumes --with-logincap
+ [4200778083fd]
+
+ * auth/bsdauth.c, auth/fwtk.c:
+ When prompting for a response to a challenge, if the user just hits
+ return then reprompt with echo turned on.
+ [a539b6474a97]
+
+2000-10-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Remove debugging code that should not have been committed, oops.
+ [9862607b77a7]
+
+ * auth/bsdauth.c:
+ Use lower-level routines and get the password ourselves. Checks for
+ a challenge and if there is one echo is not turned off.
+ [2d8fcd166baa]
+
+ * auth/pam.c, auth/sudo_auth.h:
+ minor housekeeping, no real code changes
+ [d0074a277fb4]
+
+2000-10-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Fix a coredump in the logging functions if gethostname(2) fails by
+ deferring the call to log_error() until things are better setup.
+
+ Fix return value of set_loginclass() in non-BSD-auth case.
+
+ Hard-code 'sudo' in the usage message so we can fit more options on
+ a line
+ [d9d1b7579818]
+
+ * logging.c:
+ Fix errant ';' (typo) that broken MSG_ONLY
+ [849b2276a470]
+
+2000-10-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.cat, sudo.man.in:
+ regen
+ [bb3c8c6704d1]
+
+ * sudo.pod:
+ Document -a flag
+ [e18316cebaac]
+
+ * Makefile.in, auth/bsdauth.c, auth/sudo_auth.h, config.h.in,
+ configure, configure.in, getspwuid.c, sudo.c:
+ Add support for BSD authentication.
+ [f374cfd9ca0d]
+
+2000-10-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ Fix typo; from sato@complex.eng.hokudai.ac.jp
+ [3085fee9766e]
+
+2000-10-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ Mention negating umask
+ [c9e410294dae]
+
+ * defaults.c:
+ Allow user to specify umask of 0777 (same as !umask)
+ [bb771daa96fe]
+
+2000-10-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod, visudo.pod:
+ Fix a typo and give a URL for the sudo history.
+ [77f73199aedb]
+
+2000-10-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * defaults.c, sudo.pod:
+ fix typos; pepper@reppep.com
+ [5532c7421340]
+
+2000-09-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c, sudo.h, sudo_setenv.c:
+ sudo_setenv() now exits on memory alloc failure instead of returning
+ -1.
+ [71f1cf18f47b]
+
+2000-09-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Strip out NLSPATH and PATH_LOCALE from the environment for FreeBSD
+ and possibly others.
+ [b69d985b0d22]
+
+ * logging.c:
+ Don't use vsyslog(3) since HP-UX (and others?) lack it. This means
+ that "%m" won't be expanded but we don't use that anyway since the
+ logging routines may splat to stderr as well.
+ [8d37a544d0c0]
+
+ * defaults.c, defaults.h, sudo.c, sudoers.cat, sudoers.man.in,
+ sudoers.pod:
+ Add always_set_home variable
+ [dbcaff646e07]
+
+ * configure, configure.in:
+ Have to hard code default values in help since the defaults are set
+ _after_ the help stuff.
+ [7b5d6d72f55c]
+
+2000-08-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lex.yy.c, parse.lex:
+ Allow special characters (including '#') to be embedded in pathnames
+ if quoted by a '\\'. The quoted chars will be dealt with by
+ fnmatch(). Unfortunately, 'sudo -l' still prints the '\\'.
+ [3ed33cf09977]
+
+2000-08-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * install-sh:
+ Better path searching for programs we need.
+ [60517cb1f0d6]
+
+ * TROUBLESHOOTING:
+ Add section on "C compiler cannot create executables" errors.
+ [e4ada6eaee59]
+
+ * Makefile.binary, Makefile.in, version.h:
+ Crank version
+ [93d1bd5b7f5e]
+
+ * aclocal.m4, configure, configure.in, sudo.cat, sudo.man.in,
+ sudo.pod, sudoers.cat, sudoers.man.in, sudoers.pod, visudo.cat,
+ visudo.man.in, visudo.pod:
+ Substitute values from configure into man pages.
+ [619854c356c1]
+
+2000-08-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c, sudo.c:
+ The listpw and verifypw sudoers options would not take effect
+ because the value of the default was checked *before* sudoers was
+ parsed. Instead of passing in the value of PWCHECK_* to
+ sudoers_lookup(), pass in the arg for def_ival() so the check can be
+ deferred until after sudoers is parsed.
+ [4f596e358f72]
+
+2000-08-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * tgetpass.c:
+ When writing prompt, no need to write the NUL as well;
+ hag@linnaean.org
+ [fbcdd7b431ee]
+
+2000-06-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * install-sh:
+ When looking for chown, check in /sbin too
+ [657ba6653f8c]
+
+2000-06-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ Remove extraneous call to init_defaults() and set runas_user to NULL
+ betweem parses so init_defaults will reset it each time, thus
+ avoiding a reference to free()d data.
+ [7421fcd692af]
+
+2000-06-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, interfaces.c, interfaces.h, sudo.c:
+ Add support for using getifaddrs() to get the list of ip addr /
+ netmask pairs. Currently IPv4-only.
+ [a35bc4f7306d]
+
+ * visudo.c:
+ Add a missing check for UserEditor == NULL Add missing '+' before
+ line number when invoking editor to fix a syntax error
+ [f0d4635f6082]
+
+2000-05-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Call clean_env very early in main() for paranoia's sake. Idea from
+ Marc Esipovich.
+ [f8d72ebd0115]
+
+2000-05-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.h:
+ Update proto for evasprintf and easprintf
+ [d147d6e58419]
+
+ * alloc.c:
+ Make easprintf() and evasprintf() return an int.
+ [b2ca5d089667]
+
+ * check.c:
+ If the targetpw flag is set, use target username as part of the
+ timestamp path. If tty tickets are in effect cat the tty and the
+ target username with a ':' as the separator.
+ [de11abc693c2]
+
+2000-05-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/pam.c:
+ Backout part of last change; setting PAM_USER to the invoking user
+ breaks things like targetpw.
+ [427218a7387f]
+
+ * auth/pam.c:
+ set tty and username via pam_set_item
+ [85d1922dbcc9]
+
+ * auth/sudo_auth.c, check.c, getspwuid.c, sudo.c, sudo.h:
+ Fix root, runas, and target authentication for non-passwd file auth
+ methods.
+ [a14535e7b30c]
+
+2000-04-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.cat, sudo.man.in, sudo.pod, sudoers.cat, sudoers.man.in,
+ sudoers.pod, visudo.cat, visudo.man.in, visudo.pod:
+ Use B<-Z> not C<-Z> for command line flags in all places. This is
+ more consistent and works around a bug in Pod::Man.
+ [64b5a05f30c5]
+
+ * sudoers.cat, sudoers.man.in, sudoers.pod:
+ Fix an occurence of 'semicolon' that should be 'colon'
+ [4ea5aacae3fb]
+
+2000-04-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Fix --with-badpri help line
+ [3cc40977c043]
+
+2000-04-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * defaults.c, logging.c, sudo.c:
+ Bracket calls to syslog with an openlog() and closelog() since some
+ authentication methods (like PAM) may do their own logging via
+ syslog. Since we don't use syslog much (usually just once per
+ session) this doesn't really incur a performance penalty. It also
+ Fixes a SEGV with pam_kafs.
+ [fe1cc28529f6]
+
+2000-04-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Fix -H flag. runas_homedir is only valid after set_perms(PERM_RUNAS,
+ mode)
+ [ce9b1c6f68a6]
+
+2000-04-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ Clarify the fact that insults are not enabled just by including them
+ in the binary.
+ [d5a31d48320c]
+
+2000-04-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat,
+ visudo.man.in:
+ Regenerated with perl 5.6.0 pod2man
+ [21751433768b]
+
+ * Makefile.in:
+ Give date string to pod2man since its default is ugly and it ain't
+ got no alibi.
+ [0080b2f6298f]
+
+ * Makefile.in:
+ Do section substitution on the output of pod2man and remove hack
+ needed for old pod2man.
+ [1ef843d5c78b]
+
+ * sudo.pod, sudoers.pod, visudo.pod:
+ Put back real man sections, we will do the substitution later.
+ [f728c1abad7e]
+
+2000-04-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Don't bother checking for the path to vi if user specified --with-
+ editor
+ [bf698487e0d5]
+
+2000-04-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, visudo.c:
+ Visudo now does its own fork/exec instead of calling system(3).
+ [99bbcd88863b]
+
+ * CHANGES, INSTALL, Makefile.in, sudoers.cat, sudoers.man.in,
+ sudoers.pod, visudo.c:
+ Visudo now checks for the existence of an editor and gives a
+ sensible error if it does not exist.
+
+ The path to the editor for visudo is now a colon-separated list of
+ allowable editors. If the user has $EDITOR set and it matches one of
+ the allowed editors that editor will be used. If not, the first
+ editor in the list that actually exists is used.
+ [cc86eb9f5440]
+
+ * sudo.cat, sudo.man.in, sudo.pod:
+ Clear up confusion wrt sudo's return value.
+ [9385b12d8e79]
+
+2000-03-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ Strip sudo and visudo for bindist target
+ [a995ddd79177]
+
+ * sudo.cat, sudo.man.in, sudo.pod, sudoers.cat, sudoers.man.in,
+ sudoers.pod, visudo.cat, visudo.man.in, visudo.pod:
+ Use @mansectsu@ and @mansectform@ in the man page bodies as well.
+ [5eb9e60a726f] [SUDO_1_6_3]
+
+ * visudo.cat, visudo.man.in, visudo.pod:
+ Typo: @sysconf@ -> @sysconfdir@
+ [f07f52fcd099]
+
+ * Makefile.in:
+ 'make dist' should not cause any files to be modified so remove its
+ dependencies.
+ [7f44a2666a9c]
+
+ * CHANGES:
+ Whoops, forgot to add release marker
+ [16c0f16b35b8]
+
+2000-03-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ Final change for 1.6.3 (or so I hope)
+ [473c89da6123]
+
+ * sudo.cat, sudoers.cat, visudo.cat:
+ Use SYSV man sections since BSD systems will have nroff...
+ [0a6bd154324e]
+
+2000-03-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc, sudo.tab.c:
+ When checking to see if the host/user matches in a defaults spec,
+ check against TRUE, not just non-zero since it might be -1.
+ [41f2b7ad3fdd]
+
+ * configure, configure.in:
+ OSF/1 puts file formats in section 4, not 5.
+ [d77c1301afa9]
+
+ * CHANGES, INSTALL, sudo.c:
+ Make login class support work on BSD/OS
+ [e9bbe3c08ade]
+
+ * RUNSON:
+ Update for 1.6.3
+ [c40ce1d76c4d]
+
+ * configure, configure.in:
+ If there is no inet_addr but there *is* an __inet_addr that's ok
+ since inet_addr is probably just a macro then. The better thing to
+ do would be to look for the macro, but this is fine for now.
+ [1b8865ae4d68]
+
+ * configure, configure.in:
+ Don't use shlicc for BSD/OS 4.x
+ [83fbf6dedd2c]
+
+ * Makefile.in, configure, configure.in:
+ *.man lives in cwd, *.cat lives in $(srcdir), add a @mansrcdir@
+ configure variable so we can deal with this. Also, only remove *.man
+ for 'distclean' not 'clean'.
+ [30d56e6de214]
+
+ * sudo.c:
+ set_loginclass() should be static like the proto says
+ [d570a2d55fb8]
+
+2000-03-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * fnmatch.c:
+ Add #ifdef __STDC__ around the rangematch function header to avoid
+ promotion of test to int, thus violating the prototype. Gcc handles
+ this gracefully but more std ANSI compilers will complain.
+ [7d98c3e332b2]
+
+ * emul/fnmatch.h:
+ Pull in newer fnmatch(3) that supports FNM_CASEFOLD
+ [4e1320852f8b]
+
+ * aclocal.m4, configure, fnmatch.3, fnmatch.c:
+ Pull in newer fnmatch(3) that supports FNM_CASEFOLD Check for
+ FNM_CASEFOLD in configure
+ [9ef952bf1896]
+
+ * CHANGES, TODO:
+ update for 1.6.3
+ [e4ba6368a0c5]
+
+ * sudo.tab.c, sudo.tab.h, testsudoers.c, visudo.c:
+ Fully qualified hosts w/ wildcards were not matching the FQHOST
+ token type. There's really no need for a separate token for fully-
+ qualified vs. unqualified anymore so FQHOST is now history and
+ hostname_matches now decides which hostname (short or long) to check
+ based on whether or not the pattern contains a '.'.
+ [fbd2887d9811]
+
+ * lex.yy.c, parse.c, parse.lex, parse.yacc:
+ Fully qualified hosts w/ wildcards were not matching the FQHOST
+ token type. There's really no need for a separate token for fully-
+ qualified vs. unqualified anymore so FQHOST is now history and
+ hostname_matches now decides which hostname (short or long) to check
+ based on whether or not the pattern contains a '.'.
+ [630d9d205397]
+
+ * parse.h:
+ Fully qualified hosts w/ wildcards were not matching the FQHOST
+ token type. There's really no need for a separate token for fully-
+ qualified vs. unqualified anymore so FQHOST is now history and
+ hostname_matches now decides which hostname (short or long) to check
+ based on whether or not the pattern contains a '.'.
+ [dd7bbe223461]
+
+ * parse.c, parse.h, parse.yacc, sudo.tab.c, sudoers.cat,
+ sudoers.man.in, sudoers.pod, testsudoers.c, visudo.c:
+ Add support for wildcards in the hostname.
+ [d8d821ed4238]
+
+ * Makefile.in:
+ Add targets for *.man.in, using config.status to generate *.man from
+ *.man.in
+ [640e50ede485]
+
+ * sudoers.cat, sudoers.man.in, sudoers.pod:
+ Document set_logname option and enbolden refs to sudo and visudo.
+ [9622b3a48707]
+
+ * INSTALL, Makefile.in, aclocal.m4, configure, configure.in, sudo.cat,
+ sudo.man.in, sudo.pod, sudoers.cat, sudoers.man.in, sudoers.pod,
+ visudo.cat, visudo.man.in, visudo.pod:
+ Add FreeBSD login.conf support (untested on BSD/OS) based on a patch
+ from Michael D. Marchionna. configure now does substitution on the
+ man pages, allowing us to fix up the paths and set the section
+ correctly. Based on an idea from Michael D. Marchionna.
+ [463e928a0a2f]
+
+ * auth/passwd.c:
+ Better fix for handling HP-UX aging info.
+ [3950f42d8549]
+
+ * sudo.c:
+ Add support for set_logname run-time default
+ [c6a7cc76b8b4]
+
+ * sudo.man.in, sudoers.man.in, visudo.man.in:
+ configure does substitution on these to produce *.man
+ [b83fc3c1bfc9]
+
+ * sudo.man, sudoers.man, visudo.man:
+ These files now get generated from *.man.in at configure time.
+ [c499061f79e0]
+
+2000-03-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * defaults.c, defaults.h:
+ Add set_logname option so users can turn off setting of LOGNAME/USER
+ environment variables.
+ [6316869180b8]
+
+ * lsearch.c, parse.c, testsudoers.c:
+ kill register
+ [6e104e653748]
+
+2000-03-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/passwd.c:
+ HP-UX adds extra info at the end for password aging so when
+ comparing the result of crypt to pw_passwd we only compare the first
+ len(epass) bytes *unless* the user entered an empty string for a
+ password.
+ [3d24d4e4e889]
+
+ * logging.c:
+ Get rid of grandchild hack, it was causing problems and there is
+ really no need for it. This fixes a bug where we spin eating up CPU
+ when the user runs a long-running process like a shell.
+ [5743b10b1e81]
+
+2000-03-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ User can always specify a login class if he/she is already root.
+ [710d160cef9f]
+
+ * config.h.in, configure, configure.in, defaults.c, defaults.h,
+ sudo.c, sudo.h:
+ FreeBSD login class (login.conf) support.
+ [026b981d6328]
+
+2000-03-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/sudo_auth.c:
+ HAVE_SECUREWARE -> HAVE_GETPRPWNAM; fixes secureware support
+ [9cd4929f1a78]
+
+2000-03-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/passwd.c:
+ Truncate unencrypted password to 8 chars if encrypted password is
+ exactly 13 characters (indicateing standard a DES password). Many
+ versions of crypt() do this for you, but not all (like HP-UX's).
+ [a9d0259cb193]
+
+2000-03-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, RUNSON:
+ Mention that gcc on dynix may have problems
+ [77b97fa5bf1b]
+
+2000-02-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ Link visudo with NET_LIBS since we now call syslog via defaults.c
+ [9e3830b277cc]
+
+ * defaults.c:
+ Use Argv[0] as the first arg to openlog() since visudo uses this
+ too.
+ [e61078f328ec]
+
+2000-02-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Stash coredumpsize resource limit and retsore it before the exec()
+ Otherwise the child ends up with a coredumpsize of 0.
+ [f6a4783835a3]
+
+2000-02-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.cat, sudo.man, sudo.pod:
+ document -S flag
+ [3ebd805b7142]
+
+ * sudo.c:
+ fix usage string
+ [66b2dfa47fe8]
+
+ * CHANGES, RUNSON, TODO, auth/aix_auth.c, auth/fwtk.c, auth/pam.c,
+ auth/sudo_auth.c, sudo.c, sudo.h, tgetpass.c:
+ Added -S flag (read passwd from stdin) and tgetpass_flags global
+ that holds flags to be passed in to tgetpass(). Change echo_off
+ param to tgetpass() into a flags field. There are currently 2
+ possible flags for tgetpass(): TGP_ECHO and TGP_STDIN. In
+ tgetpass(), abstract the echo set/clear via macros and if (flags &
+ TGP_ECHO) but echo is not set on the terminal, but sure to set it.
+ [a4fcbb712cd0]
+
+ * tgetpass.c:
+ Fixed a bug that caused an infinite loop when the password timeout
+ was disabled.
+ [2be1ffc5a39f]
+
+2000-02-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, defaults.c, defaults.h, getspwuid.c, sudo.c, sudo.h,
+ sudoers.cat, sudoers.man, sudoers.pod, visudo.c:
+ Add rootpw, runaspw, and targetpw options.
+ [2d4563e46df7]
+
+ * CHANGES, defaults.c, sudoers.cat, sudoers.man, sudoers.pod,
+ visudo.c:
+ enveditor -> env_editor
+ [ddc5f856e583]
+
+2000-02-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * BUGS, INSTALL, Makefile.in, README, configure, configure.in,
+ sudo.cat, sudo.man, sudoers.cat, sudoers.man, version.h, visudo.cat,
+ visudo.man:
+ crank versino to 1.6.3
+ [a5f7d3e74360]
+
+ * INSTALL, TODO, defaults.c, defaults.h, sudoers.cat, sudoers.man,
+ sudoers.pod, visudo.c:
+ Add 'editor' and 'enveditor' sudoers defaults and make visudo honor
+ them. This means that visudo will now parse the sudoers file
+ *before* it is edited so a bogus sudoers file will cause a warning
+ to go to stderr. Also, visudo checks the variables once--it does not
+ check them after each editor run since that could be confusing.
+ [9f5af18e9212]
+
+2000-02-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * RUNSON:
+ 1.6.2 -> 1.6.2p1
+ [e25b74f1d1af]
+
+ * check.c, sudo.c, sudo.h:
+ Move user_is_exempt prototype into sudo.h
+ [daf26a6ded8a]
+
+2000-02-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ Fix thinko, some && should have been || in the last commit
+ [4b9b2d487ded]
+
+ * configure, configure.in:
+ Don't initialized Makefile variables to be NULL since the user may
+ want to import variables from their environment.
+ [7be019f4422c]
+
+2000-02-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ typo
+ [38f4d8971f0a]
+
+2000-01-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.tab.c:
+ fix a yacc (skeleton.c) warning
+ [a2da228a937b]
+
+2000-01-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, RUNSON, configure, configure.in:
+ Make pam work on HP-UX 11.0;jaearick@colby.edu
+ [b94de0ff6f42]
+
+ * CHANGES:
+ recent changes; prepare for 1.6.2p1
+ [b291635ea141]
+
+ * find_path.c:
+ Don't apply SECURE_PATH if user is example; jmknoble@pobox.com
+ [4306285c4f6e]
+
+2000-01-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.tab.c:
+ Regen with yacc that has a memory leak plugged.
+ [e26383a04eb7]
+
+ * sudoers.cat, sudoers.man, sudoers.pod:
+ Expanded docs on sudoers 'defaults' options based on INSTALL file
+ info.
+ [54c3d62d6c74]
+
+ * INSTALL:
+ Fix some while lies
+ [d15311782150]
+
+2000-01-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ When making a bindist, link FAQ to TROUBLESHOOTING instead of
+ copying.
+ [2d88a6ac88cf]
+
+ * sudoers.cat, sudoers.man, sudoers.pod:
+ Add netgroup caveat
+ [28d119f466e3] [SUDO_1_6_2]
+
+ * RUNSON:
+ Last minute updates
+ [89fb4ed22d52]
+
+ * TROUBLESHOOTING:
+ PAM entry
+ [a9fd59f39457]
+
+ * auth/pam.c:
+ correct a comment
+ [a29627225ba9]
+
+ * CHANGES, RUNSON:
+ update for 1.6.2
+ [b7f1c40ea732]
+
+ * auth/pam.c:
+ Better detection of PAM errors and fix custom prompts with PAM.
+ Based on patches from "Cloyce D. Spradling" <cloyce@headgear.org>
+ [ff69234b94a5]
+
+2000-01-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * snprintf.c:
+ Cast ULONG_MAX to unsigned long long when comparing to an unsigned
+ long long value.
+ [9d918c3a2ecd]
+
+2000-01-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, config.h.in, configure, configure.in, visudo.c:
+ Fix sudoers locking in visudo. We now lock the sudoers file itself,
+ not the temp file (since locking the temp file can foul up editors).
+ The previous locking scheme didn't work because the fd was closed
+ too early.
+ [de2011bb11ed]
+
+ * config.h.in, configure, configure.in:
+ Don't need test for ftruncate() any more.
+ [e5f71c848104]
+
+ * configure, configure.in:
+ Add a test for the -Aa flag w/ HP-UX's cc. Fixes compilation with
+ the unbundled HP-UX cc.
+ [2c373612c644]
+
+2000-01-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.cat, sudoers.man, sudoers.pod:
+ "a a" -> "a"; Aaron Campbell <aaron@cs.dal.ca>
+ [05360d2c314e]
+
+2000-01-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * LICENSE, Makefile.in, defaults.c, defaults.h, parse.c, parse.h,
+ parse.yacc, sudo.c, sudo.h, sudoers.pod, testsudoers.c, tgetpass.c,
+ version.h, visudo.c:
+ update copyright year on changed files
+ [5792a2a28a4c]
+
+ * RUNSON:
+ updates
+ [edf8f19aa403]
+
+ * CHANGES:
+ aix fix
+ [4d4a243b31e2]
+
+ * INSTALL:
+ Crank version to 1.6.2
+ [bcb5cb411624]
+
+ * configure:
+ Crank version to 1.6.2
+ [32a19f33427f]
+
+ * sudo.c:
+ When using rlimit check for RLIM_INFINITY When computing the value
+ of maxfd, use min(getdtablesize(), RLIMIT_NOFILE)
+ [8c16166802e5]
+
+ * CHANGES:
+ recent changes
+ [09fc7112e44d]
+
+ * BUGS, Makefile.in, README, configure.in, sudo.cat, sudo.man,
+ sudoers.cat, sudoers.man, version.h, visudo.cat, visudo.man:
+ Crank version to 1.6.2
+ [055fa61a7c61]
+
+ * INSTALL, defaults.c, defaults.h, sudo.c, sudo.h, sudoers.pod:
+ Add 'shell_noargs' runtime option back in. We have to defer checking
+ until after the sudoers file has been parsed but since there are now
+ other options that operate that way this one can too. Based on a
+ patch from bguillory@email.com.
+ [231db7a007a6]
+
+ * defaults.c, defaults.h, parse.c, sudo.c, sudo.h:
+ Add "listpw" and "verifypw" options.
+ [190683bac878]
+
+ * sudoers.cat, sudoers.man, sudoers.pod:
+ o Fix some typos/omissions o Add section on verifypw and listpw o
+ Define how NOPASSWD interacts with the -v and -l flags
+ [6feb7350eb79]
+
+2000-01-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ For HP-UX cc, add -Aa to CPPFLAGS. For HP-UX always add
+ -D_HPUX_SOURCE to CPPFLAGS.
+ [06cc35d89dc8]
+
+ * defaults.c, defaults.h:
+ In struct sudo_defs_types, move the union to the end and don't
+ initialize the union member since that only works with an ANSI
+ compiler. We set the value of the union by hand in init_defaults()
+ anyway. This allows sudo to compile on a K&R compiler again.
+ [623487e1fcfa]
+
+2000-01-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c, parse.h, parse.yacc, sudo.tab.c, testsudoers.c, visudo.c:
+ netgr_matches needs to check shost as well as host since they may be
+ different.
+ [3f43ace23d3e]
+
+ * tgetpass.c:
+ End on \r as well as \n
+ [cb7c6e6f4202]
+
+2000-01-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Update statbuf.st_mode based on SUDOERS_MODE when we are chaning
+ from 0400 to whatever SUDOERS_MODE is (converting from the old
+ sudoers mode). Assumes that SUDOERS_MODE is less restrictive than
+ 0400 which should always be the case.
+ [34cd83d49d20]
+
+ * parse.c, parse.yacc, sudo.c, sudo.h, sudo.tab.c:
+ Make treatment of -l and -v sane wrt NOPASSWD flags. Now allow -l
+ w/o a passwd if there is *any* entry for the user on the host with a
+ NOPASSWD flag. For -v, only allow w/o a passwd if *all* entries for
+ the user on the host w/ the specified runas user have the NOPASSWD
+ flag set.
+ [4b3b85697653]
+
+ * Makefile.in:
+ add check target
+ [3d24d34a76fd]
+
+1999-12-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ Treat EOF at whatnow prompt like 'x' instead of looping.
+ [5deffc27114c]
+
+1999-12-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ recent changes
+ [5836a9452568] [SUDO_1_6_1]
+
+1999-12-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure, configure.in, sudo.c:
+ Add check for initgroups() since old SYSV lacks this.
+ [657a6005a569]
+
+ * CHANGES, RUNSON, aclocal.m4, config.h.in, configure, configure.in,
+ parse.c, testsudoers.c:
+ o Kill HAVE_FNMATCH_H o Only define HAVE_FNMATCH if <fnmatch.h>
+ exists.
+ [17d081e917d6]
+
+1999-12-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/sudo_auth.c:
+ Don't allow insults to be enabled if the insults[] array is empty.
+ Otherwise there would be division by zero.
+ [b20c14db6029]
+
+ * CHANGES, RUNSON:
+ Don't allow insults to be enabled if the insults[] array is empty.
+ Otherwise there would be division by zero.
+ [974f4780254b]
+
+ * insults.h:
+ Don't allow insults to be enabled if the insults[] array is empty.
+ Otherwise there would be division by zero.
+ [028f130204b0]
+
+ * insults.h:
+ Don't care about USE_INSULTS #define since the insult stuff may be
+ overridden at runtime.
+ [b873df8b299c]
+
+ * auth/sudo_auth.c:
+ Honor insults flag.
+ [756111640fdc]
+
+ * CHANGES, parse.c:
+ Don't ask the user for a password if the user is not allowed to run
+ the command and the authenticate flag (in sudoers) is false.
+ [cea9fdc09c76]
+
+ * CHANGES, RUNSON, lex.yy.c, parse.lex:
+ o Whenever we get a bare newline we change to the INITIAL state. o
+ Enter GOTRUNAS when we see Runas_Alias
+
+ This allows #uid to work in a RunasAlias.
+ [a475513e7c7a]
+
+1999-12-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, parse.yacc, sudo.tab.c:
+ fix parsing of runas lists: o oprunasuser and runaslist now return a
+ value o in a runasspec, if a runaslist does not return TRUE, set
+ runas_matches to FALSE. Normally, a runaslist only returns FALSE for
+ explicitly denied users. o since runaslist does not modify the stack
+ there is no need for a push/pop in runasalias.
+ [82b305b34a8c]
+
+ * check.c, sudo.c:
+ Don't kill the user's tickets until after sudoers has been parsed
+ since tty_tickets and ticket_dir could be set in sudoers.
+ [f43e25367f3a]
+
+ * BUGS, CHANGES, Makefile.binary, Makefile.in, README, RUNSON,
+ configure, configure.in, sudo.cat, sudo.man, sudoers.cat,
+ sudoers.man, tgetpass.c, version.h, visudo.cat, visudo.man:
+ crank version to 1.6
+ [95f8bdcf9bb2]
+
+ * testsudoers.c:
+ add set_fqdn() stub
+ [bbc81af5b41a]
+
+1999-12-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, defaults.c, defaults.h, sudo.c, sudo.h, sudoers.cat,
+ sudoers.man, sudoers.pod, visudo.c:
+ o Kill shell_noargs option, it cannot work since the command needs
+ to be set before sudoers is parsed. o Fix the "set_home" sudoers
+ option (only worked at compile time). o Fix "fqdn" sudoers option.
+ We now set host/shost via set_fqdn which gets called when the "fqdn"
+ option is set in sudoers. o Move the openlog() to store_syslogfac()
+ so this gets overridden correctly from the sudoers file.
+ [3dca861f0f5d]
+
+ * auth/securid.c:
+ SecurID support should compile now.
+ [a544e5c6ea34]
+
+1999-11-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.cat, sudo.man, sudo.pod, sudoers.cat, sudoers.man, visudo.cat,
+ visudo.man, visudo.pod:
+ fix some syntactic goofs
+ [b3451f0d5239]
+
+1999-11-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, sudo.html, sudoers.html, visudo.html:
+ No longer need the .html files as they are generated automatically
+ on the web site.
+ [1b4aa4204584]
+
+ * CHANGES, LICENSE:
+ kill characters that made wml unhappy
+ [b988fbc6da56]
+
+ * HISTORY:
+ typo
+ [a418963f7fce]
+
+1999-11-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * README:
+ majordomo@cs.colorado.edu -> majordomo@courtesan.com
+ [5d151e8ffd3b]
+
+ * Makefile.in, configure:
+ Wrap script execution w/ /bin/sh for the benefit of ctm
+ [3a9c4766b2c3]
+
+1999-11-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Make the -s flag be exclusive too. Also reorder the flags in the
+ exclusive usage message so they are alphabetical.
+ [4c7af200db34]
+
+1999-11-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/pam.c:
+ make pam errors other than PAM_PERM_DENIED fatal
+ [64bcb3fd2baf]
+
+ * auth/API:
+ fix typo
+ [f3134c88b12e]
+
+ * INSTALL:
+ make it clear that /etc/pam.d/sudo is required on linux
+ [213cc3eaad82]
+
+ * auth/pam.c:
+ fix a warning on redhat and spew an error if pam_authenticate()
+ returns an error other than AUTH_SUCCESS or PAM_PERM_DENIED
+ [7e46dd19da89]
+
+ * sudo.cat, sudo.html, sudo.man, sudo.pod:
+ Be very clear that the password required is the user's not root's
+ [a6da127347e5]
+
+1999-11-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ add sample.syslog.conf to DISTFILES and BINFILES
+ [8661c27c007e]
+
+1999-11-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * RUNSON:
+ updates from Brian Jackson + some formatting
+ [6d31c6fa63f8]
+
+1999-11-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL.binary, Makefile.binary, README, RUNSON:
+ o One RUNSon update o Changes for automating real binary releases
+ [dd9585f4406c]
+
+ * Makefile.in:
+ Add bindist target
+ [546ed3fa94bb]
+
+1999-11-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TROUBLESHOOTING:
+ talk about run-time options in addition to compile-time options
+ [1eb813ff0a9a] [SUDO_1_6_0]
+
+ * CHANGES:
+ fix typos
+ [65e92bb70a7b]
+
+ * sudo.c:
+ need sys/time.h if HAVE_SETRLIMIT
+ [ce31655a8a60]
+
+ * PORTING, README, RUNSON, sudo.c, sudo.cat, sudo.html, sudo.man,
+ sudo.pod, visudo.cat, visudo.html, visudo.man, visudo.pod:
+ get rid of references to sudo-bugs. Now mention the web site or the
+ sudo@ alias
+ [a9db861fd8c6]
+
+ * sudoers.html:
+ repair pod2html damage
+ [62ece4277f1f]
+
+ * RUNSON, TODO:
+ Update for 1.6 release
+ [98569c57ba2a]
+
+ * sudoers.cat, sudoers.html, sudoers.man, sudoers.pod:
+ Add warning about using ALL in a command context.
+ [6c77685ab280]
+
+1999-11-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ Call yyrestart() on a parse error to reset the lexer state.
+ [1370a27acdb2]
+
+ * lex.yy.c, parse.lex:
+ Don't need YY_FLUSH_BUFFER after all Move yyrestart() into visudo.c
+ since it might not get called in yywrap if we get a parse error (and
+ we only reread the file on error anyway).
+ [37f4b449e28e]
+
+ * lex.yy.c, parse.lex:
+ Call YY_FLUSH_BUFFER macro in yywrap() to clean up any buffers that
+ might still exist. Call yyrestart() instead of using the deprecated
+ YY_NEW_FILE macro.
+ [7d0d873046c6]
+
+ * lex.yy.c, parse.lex:
+ flex doesn't need %N table size declarations
+ [268b020fd60a]
+
+ * sudoers.cat, sudoers.html, sudoers.man, sudoers.pod:
+ Mention what characters need to be escaped in names.
+ [72ccbb6b0f31]
+
+1999-11-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure:
+ regen
+ [65827abb5c7b]
+
+ * INSTALL:
+ clarify Mac OS X entry
+ [8da1549a71f5]
+
+ * RUNSON:
+ update
+ [0cff8df7459f]
+
+ * configure.in:
+ o Use AC_MSG_ERROR throughout o Check syslog configure options for
+ danity
+ [4cb81e642e5c]
+
+1999-11-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * defaults.c:
+ Fix printing of type T_MODE in dump_defaults()
+ [a868bb6f5515]
+
+ * strcasecmp.c:
+ missing sys/types.h
+ [ca694ca325b6]
+
+ * INSTALL:
+ Break out options that may be overridden at run time into their own
+ section. Add a not about Max OS X and correct some lies.
+ [d8bcfd120593]
+
+1999-11-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, config.h.in, configure, configure.in, sudo.c:
+ o Now use getrlimit to find the highest fd when closing all non-std
+ fd's o Turn off core dumps via setrlimit for the sake of paranoia
+ [dd9f651b6def]
+
+ * RUNSON:
+ updates
+ [f581841fe615]
+
+1999-11-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ updates
+ [553baa1d44c7]
+
+ * tgetpass.c:
+ When read()'ing, do a single character at a time to be sure we don't
+ go oast the newline.
+ [907d33f55bb4]
+
+ * sudo.c:
+ For the sudo_root option, check against user_uid, not getuid() since
+ at this point, ruid == euid == 0.
+ [92d5c51939b4]
+
+ * RUNSON:
+ some updates
+ [e3ed0c1f312b]
+
+ * logging.h:
+ Fix compilation problem when --with-logging=file was specified. This
+ means that syslog is now required to build sudo but that should not
+ be a problem. If it is it can be fixed trivially with a configure
+ check for syslog() or syslog.h.
+ [839a4b069190]
+
+ * tgetpass.c:
+ Make this work again for things like "sudo echo hi | more" where the
+ tty gets put into character at a time mode. We read until we read
+ end of line or we run out of space (similar to fgets(3)).
+ [c8f746df2e63]
+
+1999-10-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.cat, sudoers.html, sudoers.man, sudoers.pod:
+ change ital to bold
+ [f860978e530a]
+
+ * RUNSON:
+ update
+ [9bcfbb405568]
+
+1999-10-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * defaults.c:
+ Error out if syslog parameters are given without a value. For Ultrix
+ or 4.2BSD "syslog" is allowed without a value since there are no
+ facilities in the 4.2BSD syslog.
+ [69e7a686f5f0]
+
+1999-10-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * defaults.c:
+ Ignore the syslog facility for systems w/ old syslog like Ultrix.
+ [5c250adbbb84]
+
+ * TROUBLESHOOTING:
+ people with "." early in their path can have problems running sudo
+ from the build dir ;-)
+ [20a1744a24a4]
+
+1999-10-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.cat, sudo.html, sudo.man, sudo.pod:
+ Remove -r realm option
+ [127caa537f95]
+
+ * auth/kerb5.c, auth/sudo_auth.c, auth/sudo_auth.h, configure,
+ configure.in, sudo.c:
+ New krb5 code from Frank Cusack <fcusack@iconnet.net>.
+ [7177a3893a62]
+
+ * CHANGES:
+ update to reality
+ [766cfbb512d6]
+
+1999-10-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/fwtk.c:
+ include <auth.h> to get function prototypes.
+ [d6c7c12d09fe]
+
+ * sudo.cat, sudo.html, sudo.man, sudo.pod:
+ document -L flag
+ [dc803e1ce0d7]
+
+1999-10-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ in set_perms(), always call setuid(0) before changing the ruid/euid
+ so we always know it will succeed.
+ [8cced1b862bf]
+
+ * defaults.h:
+ #undef T_FOO to avoid conflicts with system defines (like on
+ ULTRIX).
+ [d9f0aac092b0]
+
+ * TODO, sample.sudoers, sudoers.cat, sudoers.html, sudoers.man,
+ sudoers.pod:
+ Docuement "Defaults" lines in /etc/sudoers. Still needs some
+ fleshing out but this is a start.
+ [521a1e629bbc]
+
+1999-10-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * use strtol, not strtoul since not everyone has not strtoul
+ [988462f093cc]
+
+ * defaults.c:
+ use strtol, not strtoul since not everyone has not strtoul
+ [fce835ce62e3]
+
+ * lex.yy.c, parse.lex:
+ last {WORD} rule should only apply in the INITIAL state
+ [9b57570bfa83]
+
+ * lex.yy.c, parse.lex:
+ o Add support for escaped characters in the WORD macro o Modify
+ fill() to squash escape chars
+ [87572d59e4e0]
+
+ * defaults.c, defaults.h:
+ o Add T_PATH flag to allow simple sanity checks for default values
+ that are supposed to be pathnames. o Fix a duplicate free when
+ visudo finds an error.
+ [bdc6855a6c6d]
+
+1999-10-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * defaults.c, defaults.h, logging.c:
+ mail_if_foo -> mail_foo
+ [cbee9415875d]
+
+1999-10-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat.h, defaults.c, defaults.h, sudo.c, tgetpass.c:
+ o Add requiretty option o Move O_NOCTTY to compat.h
+ [65b8bf0e1795]
+
+ * logging.c:
+ The exit() in log_error() was mistakenly removed in a previous
+ version. Put it back...
+ [9473449130a4]
+
+1999-10-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, TODO, auth/aix_auth.c, auth/fwtk.c, auth/pam.c,
+ auth/rfc1938.c, auth/sia.c, auth/sudo_auth.c, check.c, config.h.in,
+ configure, configure.in, defaults.c, defaults.h, find_path.c,
+ getspwuid.c, logging.c, parse.yacc, sudo.c, sudo.tab.c:
+ o Change defaults stuff to put the value right in the struct. o
+ Implement mailer_flags o Store syslog stuff both in int and string
+ form. Setting the string form magically updates the int version. o
+ Add boolean attribute to strings where it makes sense to say !foo
+ [4698953f9a36]
+
+ * tgetpass.c:
+ add O_NOCTTY when opening /dev/tty just in case
+ [4c6d1d1bb300]
+
+1999-10-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/API:
+ cleanup function no longer takes a status arg
+ [0819edbfe7f8]
+
+ * INSTALL:
+ the the
+ [19aadb65ea28]
+
+1999-09-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TODO, config.h.in, configure, configure.in, logging.c:
+ Use strftime() instead of ctime() if it is available.
+ [fb60ea63b514]
+
+1999-09-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * defaults.c:
+ fix copyright date
+ [4a53b54aa72f]
+
+ * RUNSON:
+ update ReliantUNIX entry
+ [de618a4f67d9]
+
+ * defaults.c, defaults.h, logging.c:
+ add log_year option
+ [251a9e20568a]
+
+ * configure, configure.in:
+ add --without-sendmail to help output
+ [93162f199902]
+
+ * configure, configure.in:
+ enforce an otctal arg for --with-suoders-mode
+ [45e1b04ccad3]
+
+1999-09-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * BUGS, INSTALL, Makefile.in, TODO, aclocal.m4, auth/aix_auth.c,
+ auth/fwtk.c, auth/kerb5.c, auth/pam.c, auth/rfc1938.c, auth/sia.c,
+ auth/sudo_auth.c, check.c, config.h.in, configure, configure.in,
+ defaults.c, defaults.h, find_path.c, lex.yy.c, logging.c, parse.h,
+ parse.lex, parse.yacc, sudo.c, sudo.h, sudo.tab.c, sudo.tab.h,
+ testsudoers.c, version.c, visudo.c:
+ Add support for "Defaults" line in sudoers to make configuration
+ variables changable at runtime (and on a global, per-host and per-
+ user basis). Both the names and the internal representation are
+ still subject to change. It was necessary to make sudo_user.runas
+ but a char ** instead of a char * since this value can be changed by
+ a Defaults line. There is a similar (but more complicated) issue
+ with sudo_user.prompt but it is handled differently at the moment.
+
+ Add a "-L" flag to list the name of options with their descriptions.
+ This may only be temporary.
+
+ Move some prototypes to parse.h
+
+ Be much less restrictive on what is allowed for a username.
+ [f71abf7ba80c]
+
+ * sample.syslog.conf:
+ Add more info
+ [e952e6f42d4d]
+
+1999-09-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * LICENSE, fnmatch.3, fnmatch.c, getcwd.c, lsearch.c, snprintf.c,
+ strcasecmp.c:
+ UCB has dropped the advertising clause from their license.
+ [a5602b36a341]
+
+1999-08-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/sudo_auth.h:
+ move dce_verofy proto to correct section
+ [972c815af558]
+
+ * auth/dce.c:
+ remove XXX
+ [820631855be0]
+
+1999-08-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * emul/fnmatch.h:
+ Add fnmatch() prototype
+ [79e84576d92a]
+
+ * fnmatch.c, parse.c, testsudoers.c:
+ Move inclusion of emul/fnmatch.h to be after sudo.h for __P
+ [1182c89fa811]
+
+ * sudo.h:
+ add strcasecmp proto
+ [512d1d8a6a0c]
+
+ * auth/sudo_auth.c:
+ add check for case where there are no auth methods
+ [e4af2b91b43e]
+
+ * configure, configure.in:
+ Define _XOPEN_EXTENDED_SOURCE on AIX and __USE_FIXED_PROTOTYPES__ on
+ SunOS4 w/ gcc
+ [746ce8bcec23]
+
+ * getspwuid.c, lex.yy.c, parse.lex, parse.yacc, sudo.tab.c:
+ include strings.h everywhere we include string.h
+ [6f7d5d437e7b]
+
+ * version.c:
+ nicer output when showing auth methods
+ [0eac4b977f9d]
+
+ * version.c:
+ Add support for SEND_MAIL_WHEN_NO_HOST
+ [9f20a3a3fae6]
+
+ * config.h.in, configure, configure.in:
+ Add _GNU_SOURCE for Linux
+ [c7bd8c511847]
+
+ * lex.yy.c, parse.lex:
+ fix definition of OCTECT
+ [4af30e63244d]
+
+ * configure, configure.in:
+ aix_auth.o not authenticate.o
+ [fe95dfb08df4]
+
+1999-08-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Only block SIGINT, SIGQUIT, SIGTSTP (which can be generated from the
+ keyboard). Since we run with ruid/euid == 0 the user can't really
+ signal us in nasty ways.
+ [a7f6487c0f48]
+
+ * visudo.c:
+ Don't need to worry about catching too many signals since we do
+ locking on the tmp file. If a lockfile is really stale, it will be
+ detected and overwritten.
+ [28983db3e749]
+
+ * INSTALL, Makefile.in:
+ include auth/API in tarball
+ [014991600252]
+
+ * auth/sudo_auth.c:
+ move memset() of plaintext pw outside of verify loop and only do the
+ memset if we are *not* in standalone mode.
+ [66f8e87567e2]
+
+ * auth/sudo_auth.c, auth/sudo_auth.h:
+ DCE is not a standalone method
+ [34963e2d8a1b]
+
+ * sudo.c:
+ fix --enable-noargs-shell
+ [4234062abbb0]
+
+ * snprintf.c:
+ "#ifdef __STDC__" not "#if __STDC__" (I missed one)
+ [c430b80454c6]
+
+ * auth/fwtk.c, auth/sia.c:
+ _cleanup() function returns an int.
+ [d1a1cc071ec1]
+
+ * auth/dce.c:
+ there were still some return(0)'s hanging around, make them
+ AUTH_FAILURE
+ [1002aa1962c3]
+
+ * parse.c:
+ typo in comment
+ [5abc410dbfd2]
+
+ * version.c:
+ add missing semicolon
+ [a262283b52a5]
+
+ * auth/sudo_auth.h:
+ missing backslash
+ [bf89f6bd2900]
+
+1999-08-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, config.h.in, configure, configure.in:
+ Kill _XOPEN_EXTENDED_SOURCE -- causes problems on some OSes
+ [f1a9bca0cf67]
+
+ * Makefile.in:
+ add parse.h to HDRS
+ [a3d054987766]
+
+ * Makefile.in, configure, configure.in:
+ Kill VISUDO_LIBS and VISUDO_LDFLAGS. Add LIBS, NET_LIBS, and
+ LDFLAGS. Common libs go in LIBS, commong ld flags go in LDFLAGS and
+ network libs like -lsocket, -lnsl go in NET_LIBS. This allows
+ testsudoers to build on Solaris and is a bit cleaner in general.
+ [4e6239e97002]
+
+ * UPGRADE:
+ mention ptmp -> sudoers.tmp
+ [ec3baa0fe8a1]
+
+ * config.h.in, configure, configure.in:
+ Define _XOPEN_SOURCE_EXTENDED not _XOPEN_SOURCE
+ [6f93dc7f39f5]
+
+ * RUNSON:
+ add 2 reports
+ [ce0fcc00ee4e]
+
+ * auth/kerb5.c:
+ Minor changes, mostly cosmetic. verify_krb_v5_tgt() changed to
+ return a value more like a system function
+ [0dd56aa21424]
+
+ * auth/dce.c:
+ Add an XXX
+ [58fc8562c212]
+
+ * TODO:
+ more things todo!
+ [5a459d0cf339]
+
+ * sample.sudoers:
+ update based on what is in the man page
+ [1a0477db96fa]
+
+ * parse.yacc, sudo.tab.c:
+ minor change to first line printed in -l mode
+ [69eb57d96952]
+
+ * sudo.cat, sudo.html, sudo.man, sudo.pod:
+ rename "ENVIRONMENT VARIABLES" section to "ENVIRONMENT" to be more
+ standard and add "EXAMPLES" section
+ [7e543335ebe1]
+
+ * visudo.cat, visudo.html, visudo.man, visudo.pod:
+ rename "ENVIRONMENT VARIABLES" section to "ENVIRONMENT" to be more
+ standard
+ [f82d87ed65c2]
+
+ * logging.c, parse.c, sudo.h:
+ add FLAG_NO_CHECK
+ [c7d69176a2d7]
+
+ * lex.yy.c, parse.lex:
+ make an OCTET really be limited to 0-255
+ [6ee568dd6a02]
+
+ * UPGRADE:
+ mention timestamp changes
+ [e44d5302bf60]
+
+ * PORTING:
+ cosmetic cleanup
+ [36fa3a2664dd]
+
+ * sudoers.cat, sudoers.html, sudoers.man, sudoers.pod:
+ new sudoers(8) man page
+ [e674d06283d0]
+
+1999-08-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * version.c:
+ Update comments about syslog name tables
+ [63830a782dcb]
+
+ * CHANGES, LICENSE, Makefile.in, configure, configure.in, parse.yacc,
+ strcasecmp.c, sudo.tab.c:
+ include strcasecmp() for those without it
+ [a0d8e2488bbc]
+
+ * sample.sudoers:
+ Use the : operator some more and fix a typo
+ [18804c70da86]
+
+ * HISTORY:
+ update the history of sudo
+ [9d9b3d5279b3]
+
+ * parse.c, parse.lex, testsudoers.c:
+ CIDR-style netmask support
+ [768644467353]
+
+ * CHANGES:
+ recent changes
+ [a4319e9d07cb]
+
+ * sudo.tab.c, sudo.tab.h:
+ these should be generated with byacc, not bison
+ [f57b9489b752]
+
+ * lex.yy.c:
+ regen
+ [522461f95dfa]
+
+ * parse.h, parse.yacc, sudo.tab.c, sudo.tab.h:
+ In "sudo -l" mode, the type of the stored (expanded) alias was not
+ stored with the contents. This could lead to incorrect output if the
+ sudoers file had different alias types with the same name. Normal
+ parsing (ie: not in '-l' mode) is unaffected.
+ [823fe2bc4b79]
+
+1999-08-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ define _XOPEN_SOURCE to get at crypt() proto on some systems
+ [1b3769b86fb9]
+
+1999-08-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * snprintf.c:
+ fix comment
+ [fc1264df00f7]
+
+ * tgetpass.c:
+ don't need limits.h
+ [f1631829af45]
+
+ * snprintf.c:
+ kill bogus reference to vfprintf
+ [a0b99b25d389]
+
+ * sample.sudoers, sudoers:
+ better examples
+ [b4d87ea64cc8]
+
+ * snprintf.c:
+ Add some const in the K&R defs. This is safe since we define const
+ away if the compiler doesn't grok it.
+ [614d6e83d45e]
+
+ * aclocal.m4, configure:
+ Better test for working long long support. Ultrix compiler supports
+ basic long long but not all operations on them.
+ [5da1508710ed]
+
+ * aclocal.m4, auth/secureware.c, config.h.in, configure, getspwuid.c,
+ snprintf.c, sudo.c:
+ Add check for LONG_IS_QUAD #undef MAXINT before including
+ hpsecurity.h to silence an HP-UX warning Check for U?LONG_LONG_MAX
+ in snprintf.c and use LONG_IS_QUAD
+ [a1f7993367fc]
+
+1999-08-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * LICENSE, aclocal.m4, config.h.in, configure, configure.in,
+ snprintf.c:
+ UCB-derived snprintf + asprintf support. Supports quads if the
+ compiler does. No floating point yet, perhaps later...
+ [0caf05aba945]
+
+1999-08-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/API, auth/sudo_auth.c, auth/sudo_auth.h, check.c, find_path.c,
+ goodpath.c, logging.c, parse.c, sudo.c:
+ Run most of the code as root, not the invoking user. It doesn't
+ really gain us anything to run as the user since an attacker can
+ just have an setuid(0) in their egg. Running as root solves
+ potential problems wrt signalling.
+ [408e530dda01]
+
+ * sudo.tab.c:
+ regen
+ [f8cfb37e37de]
+
+1999-08-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c, sudo.c:
+ Don't wait for child to finish in log_error(), let the signal
+ handler get it if we are still running, else let init reap it for
+ us. The extra time it takes to wait lets the user know that mail is
+ being sent.
+
+ Install SIGCHLD handler in main() and for POSIX signals, block
+ everything
+ *except* SIGCHLD.
+ [d2b6ab0ef3be]
+
+ * INSTALL, config.h.in, configure, configure.in, logging.c, parse.c,
+ parse.yacc, sudo.c, sudo.h:
+ sudoers_lookup() now returns a bitmap instead of an int. This makes
+ it possible to express things like "failed to validate because user
+ not listed for this host". Some thigns that were previously
+ VALIDATE_FOO are now FLAG_FOO. This may change later on.
+
+ Reorganized code in log_auth() and sudo.c to deal with above
+ changes.
+
+ Safer versions of push/pushcp with in the do { ... } while (0) style
+
+ parse.yacc now saves info on the stack to allow parse.c to determine
+ if a user was listed, but not for the host he/she tried to run on.
+
+ Added --with-mail-if-no-host option
+ [63326cb01efc]
+
+1999-08-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc, sudo.h, sudo.tab.c, visudo.c, visudo.cat, visudo.html,
+ visudo.man, visudo.pod:
+ o NewArgv and NewArgc don't need to be externally visible. o If
+ pedantic > 1, it is a parse error. o Add -s (strict) option to
+ visudo which sets pedantic to 2.
+ [5d7d81b55cd5]
+
+ * HISTORY, INSTALL:
+ Just have sudo-bugs contact info in one place
+ [e7f6588ea683]
+
+ * sudo.cat, sudo.html, sudo.man, sudo.pod:
+ Add BUGS section
+ [6607d96ea510]
+
+ * Makefile.in, configure, configure.in:
+ Add testsudoers to default build target if --with-devel Don't clean
+ generated parser files unless "distclean".
+ [5827b769dc57]
+
+ * parse.yacc, sudo.tab.c:
+ In pedantic mode we need to save *all* the aliases, not just those
+ that match, or we get spurious warnings.
+ [24f5b1f0e1de]
+
+ * TROUBLESHOOTING:
+ reference samples.sylog.conf
+ [11841668380a]
+
+1999-08-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sample.syslog.conf:
+ Sample entries for syslog.conf
+ [0f7697d878a1]
+
+ * CHANGES:
+ recent changes
+ [8bca8810c6bd]
+
+ * auth/API, auth/afs.c, auth/aix_auth.c, auth/dce.c, auth/fwtk.c,
+ auth/kerb4.c, auth/kerb5.c, auth/pam.c, auth/passwd.c,
+ auth/rfc1938.c, auth/secureware.c, auth/securid.c, auth/sia.c,
+ auth/sudo_auth.c, auth/sudo_auth.h:
+ In struct sudo_auth, turn need_root and configured into flags and
+ add a flag to specify an auth method is running alone (the only
+ one). Pass auth methods their sudo_auth pointer, not the data
+ pointer. This allows us to get at the flags and tell if we are the
+ only auth method. That, in turn, allows the method to be able to
+ decide what should/should not be a fatal error. Currently only
+ rfc1938 uses it this way, which allows us to kill the OTP_ONLY
+ define and te hackery that went with it. With access to the
+ sudo_auth struct, methods can also get at a string holding their
+ cannonical name (useful in error messages).
+ [b7e320fc6511]
+
+ * INSTALL, Makefile.in, README, config.h.in, configure, configure.in,
+ getspwuid.c, lex.yy.c, parse.lex, parse.yacc, sudo.tab.c,
+ sudo.tab.h:
+ o --with-otp deprecated, use --without-passwd instead o real
+ dependencies in the Makefile o --with-devel option to enable yacc,
+ lex, and -Wall o style -- "foo -> bar" becomes "foo->bar" o ALL goes
+ back to being a token, not a string but don't leak memory o rename
+ hsotspec -> host in parse.yacc
+ [912c45226cb2]
+
+1999-08-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * BUGS, CHANGES:
+ recent changes
+ [801fa6e55687]
+
+ * auth/sudo_auth.c, configure, configure.in, interfaces.c, snprintf.c,
+ sudo.c, sudo.h:
+ o Digital UNIX needs to check for *snprintf() before -ldb is added
+ to LIBS since -ldb includes a bogus snprintf(). o Add forward refs
+ for struct mbuf and struct rtentry for Digital UNIX. o Reorder some
+ functions in snprintf.c to fix -Wall o Add missing includes to fix
+ more -Wall
+ [8d207203e126]
+
+ * INSTALL, auth/sudo_auth.c, check.c, config.h.in, configure,
+ configure.in, parse.yacc, sudo.tab.c, testsudoers.c, version.c,
+ visudo.c:
+ o Add a "pedentic" flag to the parser. This makes sudo warn in cases
+ where an alias may be used before it is defined. Only turned on for
+ visudo and testsudoers. o Add --disable-authentication option that
+ makes sudo not require authentication by default. The PASSWD tag can
+ be used to require authentication for an entry. We no longer
+ overload --without-passwd.
+ [f307e09adf98]
+
+ * lex.yy.c, parse.lex:
+ Break 'WORD' regexp def into HOSTNAME and USERNAME. These days a
+ username can contain just about anything so be very permissive. Also
+ drop the unused \. punctuation.
+ [06a50614ff89]
+
+1999-08-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc, sudo.tab.c:
+ o add a 'val' element to aliasinfo struct and move -> parse.h o
+ find_alias() now returns an aliasinfo * instead of boolean o
+ add_alias() now takes a value parameter to store in the
+ aliasinfo.val o The cmnd, hostspec, runasuser, and user rules now
+ return: 1) positive match 0) negative match (due to '!')
+ -1) no match This means setting $$ explicitly in all cases, which I
+ should have done in the first place. It also means that we always
+ store a value that is != -1 and when we see a '!' we can set
+ *_matches to !rv if rv != -1. The upshot of all of this is that '!'
+ now works the way it should in lists and some of the rules are more
+ uniform and sensible.
+ [ad8e73b5d581]
+
+ * Makefile.in:
+ add parse.h dependency
+ [4ccccd464d30]
+
+ * parse.h:
+ kill unused *_matched macros
+ [02cba6dcb732]
+
+ * parse.yacc:
+ Allow a list of users as the first thing in a user spec, not just a
+ single entry. This makes things more uniform, though it does allow
+ you to write user specs that are hard to read.
+ [3c4c91c508ca]
+
+ * sudo.tab.c:
+ parse.yacc
+ [feca81881bb6]
+
+ * configure:
+ regen
+ [6f247010bb3b]
+
+ * configure.in:
+ fix check for crypt() in libufc
+ [82770736f4b0]
+
+1999-08-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * README:
+ sudo-users list now exists
+ [4716d2bb0bbf]
+
+ * INSTALL, PORTING, README, TODO, TROUBLESHOOTING:
+ Update to reality.
+ [1eda2d57e42a]
+
+ * CHANGES, Makefile.in, TODO, TROUBLESHOOTING, check.c, compat.h,
+ config.h.in, configure, configure.in, fileops.c, logging.c, sudo.h,
+ version.c, visudo.c:
+ o Move lock_file() and touch() into fileops.c so visudo can use them
+ o Visudo now locks the sudoers temp file instead of bailing when the
+ temp file already exists. This fixes the problem of stale temp files
+ but it does *require* that you not try to put the temp file in a
+ world-writable directory. This shoud not be an issue as the temp
+ file should live in the same dir as sudoers. o Visudo now only
+ installs the temp file as sudoers if it changed.
+ [2517cd06c070]
+
+1999-08-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ add fcntl locking
+ [c304adeaf515]
+
+ * config.h.in, configure, configure.in, logging.c:
+ Lock the log file.
+ [d8652704fbdf]
+
+ * Makefile.in, TROUBLESHOOTING, parse.c, pathnames.h.in, sudo.c,
+ visudo.c, visudo.cat, visudo.html, visudo.man, visudo.pod:
+ o /etc/stmp -> /etc/sudoers.tmp since solaris uses stmp as shadow
+ temp file o _PATH_SUDO_SUDOERS -> _PATH_SUDOERS and _PATH_SUDO_STMP
+ -> _PATH_SUDOERS_TMP
+ [68cad8975807]
+
+1999-08-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, check.c, config.h.in, configure, configure.in, version.c:
+ o Kill *_MESSAGE and replace with NO_LECTURE o Add more things to
+ root sudo -V config reporting
+ [cdd2613a9dcf]
+
+ * configure, configure.in:
+ aix_auth.o not authenticate.o
+ [d972e35f6730]
+
+ * config.h.in:
+ Add --with-goodpri and --with-badpri configure options to specify
+ the syslog priority to use.
+ [2595ae50ab86]
+
+ * INSTALL, configure, configure.in, logging.h:
+ Add --with-goodpri and --with-badpri configure options to specify
+ the syslog priority to use.
+ [8276ee9b2b49]
+
+ * compat.h:
+ kill crufty AIX stuff
+ [a4f35ef9854e]
+
+ * Makefile.in:
+ Sigh, some versions of make (like Solaris's) don't deal with $< like
+ I would expect. Both GNU and BSD makes get this right but... So, we
+ just expand $< inline at the cost of some ugliness.
+ [b1b456f8801f]
+
+ * version.c:
+ If the invoking user is root, sudo will now print configure info in
+ -V mode. Currently just prints logging info, to be expanded later.
+ [392f7ed99267]
+
+ * logging.c, logging.h, sudo.c, sudo.h:
+ o new defines for syslog facility and priority o use new
+ print_version() functino for -V mode
+ [78abc5142985]
+
+ * check.c:
+ Don't need version.c
+ [db9a830ad893]
+
+ * aclocal.m4, config.h.in, configure, configure.in:
+ Add check for syslog facilities and priorities tables in syslog.h
+ [b86213e5fc5c]
+
+ * Makefile.in:
+ o authenticate -> aix_auth o add version.c
+ [44b6b9a8d0f5]
+
+ * auth/sudo_auth.c:
+ Missed a prompt -> user_prompt conversion
+ [e4c60b1f210c]
+
+1999-08-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TODO:
+ sudo should lock its logfile
+ [6d2830b28b07]
+
+ * parse.yacc, sudo.tab.c:
+ o Add '!' correctly when expanding Aliases. o Add shortcut macros
+ for append() to make things more readable. o The separator in
+ append() is now a string instead of a char. o In append(), only
+ prepend the separator if the last char is not a '!'. This is a hack
+ but it greatly simplifies '!' handling. o In -l mode, Runas lists
+ and NOPASSWD/PASSWD tags are now inherited across entries in a list
+ (matches current behavior). o Fix formatting in -l mode such that
+ items in a list are separated by a space. Greatlt improves
+ readability. o Space for name field in struct aliasinfo is now
+ allocated dyanically instead of using a (big) buffer. o In
+ add_alias(), only search the list once (lsearch instead of lfind +
+ lsearch)
+ [51f7e07addb9]
+
+ * lex.yy.c, sudo.tab.c, sudo.tab.h:
+ regen
+ [5c19bb05dc21]
+
+ * configure, configure.in:
+ Solais pam doesn't require anye xtra setup
+ [a25ba03d91d1]
+
+ * parse.yacc:
+ o Simpler '!' support now that the lexer deals with multiple !'s for
+ us. o In the case of opFOO, have FOO give a boolean return value and
+ set foo_matches in opFOO, not FOO. o Treat 'ALL' as a string since
+ it gets fill()'d in parse.lex--fixes a small memory leak. In the
+ long run it may be better to just fix parse.lex and make ALL back
+ into a token. However, having it be a string is useful since it can
+ be easily passed back to the parent rule if we so desire.
+ [b3c64b443018]
+
+ * parse.lex:
+ o Remove some unnecessary backslashes o collapse multiple !'s by
+ using !+ and checking if yyleng is even or odd. this allows us to
+ simplify ! handling in parse.yacc
+ [76330e8da8e3]
+
+ * sudo.c:
+ -u flag was being ignored
+ [e30283207585]
+
+1999-08-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ correct fix
+ [a0e2377dec8f]
+
+ * Makefile.in:
+ work around pod2man stupididy
+ [7c755640b67f]
+
+ * Makefile.in:
+ correct dependencies for .cat
+ [5ed7b0653b68]
+
+ * sudo.cat, sudo.man, visudo.cat, visudo.man:
+ regen
+ [b74510dd6a0a]
+
+ * sudo.pod, visudo.pod:
+ Add copyright Update to reality
+ [188e9b046c15]
+
+ * parse.c, sudo.c, sudo.h:
+ rename validate() to the more descriptive sudoers_lookup()
+ [7a1cb652f379]
+
+ * auth/aix_auth.c:
+ use tgetpass
+ [b8ba5daec40a]
+
+1999-07-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ updates
+ [e61460cdf4a0]
+
+ * HISTORY, INSTALL, Makefile.in, README, RUNSON, TROUBLESHOOTING,
+ configure, configure.in, sudo.c:
+ Sudo, not CU Sudo
+ [9061b3573c0c]
+
+ * LICENSE:
+ add 4th term to license similar to term 5 in the apache license
+ [92712e895afb]
+
+ * emul/search.h, emul/utime.h:
+ add 4th term to license similar to term 5 in the apache license
+ [4f93a8b9396e]
+
+ * auth/afs.c, auth/aix_auth.c, auth/dce.c, auth/fwtk.c, auth/kerb4.c,
+ auth/kerb5.c, auth/pam.c, auth/passwd.c, auth/rfc1938.c,
+ auth/secureware.c, auth/securid.c, auth/sia.c, auth/sudo_auth.c,
+ auth/sudo_auth.h, insults.h, interfaces.c, interfaces.h, lex.yy.c,
+ logging.c, logging.h, parse.c, parse.h, parse.lex, parse.yacc,
+ pathnames.h.in, putenv.c, strerror.c, sudo.c, sudo.h, sudo.tab.c,
+ sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, version.h,
+ visudo.c:
+ add 4th term to license similar to term 5 in the apache license
+ [afae9f2bf9ec]
+
+ * Makefile.in, alloc.c, check.c, compat.h, config.h.in, find_path.c,
+ getspwuid.c, goodpath.c:
+ add 4th term to license similar to term 5 in the apache license
+ [969e63dbd38e]
+
+ * ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h:
+ add 4th term to license similar to term 5 in the apache license
+ [c389d3fdafac]
+
+ * LICENSE, aclocal.m4, auth/rfc1938.c, check.c, configure.in,
+ insults.h, logging.c, sudo.c, sudo.h:
+ there was a 1995 release too
+ [5963fd89457a]
+
+1999-07-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ updates
+ [254b794f16ab]
+
+ * check.c:
+ Use dirs instead of files for timestamp. This allows tty and non-
+ tty schemes to coexist reasonably. Note, however, that when you
+ update a tty ticket, the mtime on the user dir gets updated as well.
+ [44bfac32f799]
+
+ * configure, configure.in:
+ Fix getprpwnam() checking on SCO. Need to link with "-lprot -lx"
+ when linking test program, not just -lprot. Also add check for
+ getspnam(). The SCO docs indicate that /etc/shadow can be used but
+ this may be a lie.
+ [2ba21d36cc1e]
+
+1999-07-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/API:
+ first cut at auth API description
+ [3d10df021eb8]
+
+1999-07-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/fwtk.c, auth/kerb4.c, auth/kerb5.c, auth/pam.c, auth/rfc1938.c,
+ auth/secureware.c, auth/securid.c, auth/sudo_auth.c,
+ auth/sudo_auth.h:
+ auth API change. There is now an init method that gets run before
+ the main loop. This allows auth routines to differentiate between
+ initialization that happens once vs. setup that needs to run each
+ time through the loop.
+ [76df1c0d3478]
+
+ * auth/kerb5.c, logging.c:
+ use easprintf() and evasprintf()
+ [fd97d96dc12f]
+
+ * alloc.c, sudo.h:
+ add easprintf() and evasprintf(), error checking versions of
+ asprintf() and vasprintf()
+ [f54385de20b7]
+
+ * TODO:
+ remove 2 items. One done, one won't do.
+ [64513b47bc7a]
+
+ * lex.yy.c, sudo.tab.c:
+ regen
+ [4aa299de2752]
+
+ * configure, sudo.cat, sudo.html, sudo.man, sudoers.html, visudo.cat,
+ visudo.html, visudo.man:
+ regen
+ [553c0d1209be]
+
+ * CHANGES:
+ new changes
+ [d7be00b7e36b]
+
+ * sudo.pod:
+ o Document -K flag and update meaning of -k flag. o BSD-style
+ copyright o Document clearing of BIND resolver environment variables
+ o Clarify bit about shared libs o suggest rc files create /tmp/.odus
+ if your OS gives away files
+ [4a4092be1455]
+
+ * visudo.pod:
+ BSD license
+ [ad0bfd0a4630]
+
+ * version.h:
+ BSD-style copyright
+ [ecc6479325be]
+
+ * tgetpass.c:
+ o BSD copyright o no need to block signals, we now do that in main()
+ o cosmetic changes
+ [61958beda7ab]
+
+ * testsudoers.c, visudo.c:
+ o BSD-style copyright o Use "struct sudo_user" instead of old
+ globals. o some cometic cleanup
+ [88c0c6924082]
+
+ * sudo_setenv.c:
+ BSD-style copyright
+ [df20290129a0]
+
+ * sudo.h:
+ o BSD copyright o logging and parser bits moved to their own .h
+ files o new "struct sudo_user" to encapsulate many of the old
+ globals.
+ [50fc86bf25cb]
+
+ * sudo.c:
+ o no longer contains sudo 1.1/1.2 code o BSD copyright o use new
+ logging routines o simplified flow of control o BIND resolver
+ additions to badenv_table
+ [8c53f15bfcb0]
+
+ * strerror.c:
+ BSD-style copyright
+ [7c906c3a82ac]
+
+ * snprintf.c:
+ Now compiles on more K&R compilers
+ [07ab1d3231c7]
+
+ * putenv.c:
+ BSD-style copyright, cosmetic changes
+ [c42371295881]
+
+ * pathnames.h.in:
+ BSD-style copyright
+ [e5c34ebd4cf1]
+
+ * parse.c, parse.h, parse.lex, parse.yacc:
+ BSD-style copyright. Move parser-specific defines and structs into
+ parse.h + other cosmetic changes
+ [d3088efb6228]
+
+ * logging.h:
+ defines for logging routines
+ [13147941c02d]
+
+ * find_path.c, getspwuid.c, goodpath.c, interfaces.c:
+ BSD-style copyright, cosmetic changes
+ [e8205e91a4fa]
+
+ * ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h,
+ interfaces.h:
+ BSD-style copyright
+ [b9499da7cdce]
+
+ * configure.in:
+ o tgetpass.c is no longer optional o kill DCE_OBJS, add AUTH_OBJS o
+ kill --disable-tgetpass o add --without-passwd o changes to fill in
+ AUTH_OBJS for new auth api o check for strerror(), v?snprintf() and
+ v?asprintf() o replace --with-AuthSRV with --with-fwtk
+ [9a3f39b9c128]
+
+ * config.h.in:
+ BSD-style copyright. Remove USE_GETPASS and HAVE_UTIME_NULL. Add
+ HAVE_FWTK, HAVE_STRERROR, HAVE_SNPRINTF, HAVE_VSNPRINTF,
+ HAVE_ASPRINTF, HAVE_VASPRINTF, WITHOUT_PASSWD and NO_PASSWD
+ [9a09054db53a]
+
+ * compat.h:
+ BSD-style copyright; Add S_IFLNK and MIN/MAX id they are missing.
+ [25509c566975]
+
+ * alloc.c:
+ BSD-style copyright
+ [4967be892363]
+
+ * TROUBLESHOOTING:
+ no more --with-getpass
+ [afd5b670c196]
+
+ * TODO:
+ Take out things I've done...
+ [375420c8270e]
+
+ * README:
+ Refer to LICENSE
+ [c486c8db30f6]
+
+ * PORTING:
+ --with-getpass no longer exists
+ [db48202df1bb]
+
+ * Makefile.in:
+ BSD-style copyright. Update to reflect reality wrt new files and new
+ auth modules.
+ [61a2ca7940fb]
+
+ * INSTALL:
+ Remove --with-AuthSRV and --disable-tgetpass. Add --with-fwtk and
+ --without-passwd.
+ [64e8f9e1c05e]
+
+ * HISTORY:
+ Update history a bit
+ [df60c0a871b8]
+
+ * COPYING, LICENSE:
+ Now distributed under a BSD-style license
+ [d1a184ccabe1]
+
+ * auth/sudo_auth.c:
+ o BSD-style copyright o Add support for NO_PASSWD/WITHOUT_PASSWD
+ options. o skey/opie replaced by rfc1938 code o new struct sudo_user
+ global
+ [891b57060868]
+
+ * auth/pam.c, auth/sia.c:
+ BSD-style copyright and use new log functions
+ [65c44445ea84]
+
+ * auth/kerb5.c:
+ o BSD-style copyright o Use new log functiongs o Use asprintf() and
+ snprintf() where sensible.
+ [1ff0feaacf95]
+
+ * check.c:
+ Rewrote all the old sudo 1.1/1.2 code. Timestamp handling is now
+ done more reasonably--better sanity checks and tty-based stamps are
+ now done as files in a directory with the same name as the invoking
+ user, eg. /var/run/sudo/millert/ttyp1. It is not currently possible
+ to mix tty and non-tty based ticket schemes but this may change in
+ the future (it requires sudo to use a directory instead of a file in
+ the non-tty case). Also, ``sudo -k'' now sets the ticket back to the
+ epoch and ``sudo -K'' really deletes the file. That way you don't
+ get the lecture again just because you killed your ticket in
+ .logout. BSD-style copyright now.
+ [ec3460f85be8]
+
+ * logging.c:
+ o rewritten logging routines. log_error() now takes printf-style
+ varargs and log_auth() for the return value of validate(). o BSD-
+ style copyright
+ [438292025c4e]
+
+ * auth.c, check_sia.c, dce_pwent.c, secureware.c:
+ superceded by new auth API
+ [412060590da7]
+
+ * auth/kerb4.c:
+ BSD-style copyright
+ [cc4e800833c7]
+
+ * auth/fwtk.c:
+ Use snprintf() where it makes sense and add a BSD-style copyright
+ [1b7502388a74]
+
+ * auth/afs.c, auth/aix_auth.c, auth/dce.c, auth/passwd.c,
+ auth/rfc1938.c, auth/secureware.c, auth/securid.c, auth/sudo_auth.h:
+ BSD-style copyright
+ [42583bedae5c]
+
+ * emul/utime.h, utime.c:
+ BSD-style copyright
+ [3985c90aba47]
+
+ * emul/search.h:
+ this has been rewritten so use my BSD-style copyright
+ [176df1b0de6f]
+
+1999-07-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * snprintf.c:
+ include malloc.h if no stdlib.h
+ [7b123f1d1d03]
+
+ * snprintf.c:
+ KTH snprintf()/asprintf() for systems w/o them
+ [3ca9aefb9d01]
+
+ * strerror.c:
+ strerror() for systems w/o it
+ [7f0bd8a1c1b4]
+
+1999-07-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ stylistic changes
+ [6f99aceb7170]
+
+ * parse.c, parse.lex, parse.yacc:
+ Add contribution info in the main comment
+ [e50cec10acd6]
+
+1999-07-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth/pam.c:
+ remove missed ref to PAM_nullpw
+ [a43e59692cdb]
+
+ * auth/sudo_auth.h:
+ pasto
+ [891ff138ab89]
+
+ * auth/kerb5.c:
+ more or less complete now--still untested
+ [21036732faa0]
+
+ * auth/afs.c, auth/pam.c:
+ don't use user_name macro, it will go away
+ [def7cf727349]
+
+ * auth/opie.c, auth/rfc1938.c, auth/skey.c, auth/sudo_auth.h:
+ combine skey/opie code into rfc1938.c
+ [44d88ca93d3e]
+
+ * auth/dce.c, auth/sudo_auth.h:
+ DCE authentication method; basically unchanged from dce_pwent.c
+ [4d468473dd6f]
+
+ * auth/aix_auth.c, auth/sudo_auth.h:
+ AIX authenticate() support. Could probably be much better
+ [000013321a33]
+
+ * auth/sia.c:
+ Fix an uninitialized variable and some cleanup. Now works (tested)
+ [fd6ad88ff055]
+
+ * auth/sia.c, auth/sudo_auth.h:
+ SIA support for digital unix
+ [5335f3e70eab]
+
+ * auth/pam.c:
+ don't use prompt global, it will go away
+ [fadd22dd6ce4]
+
+ * auth/secureware.c:
+ correct copyright years
+ [6aa07c49f51b]
+
+ * auth/afs.c, auth/fwtk.c, auth/kerb4.c, auth/kerb5.c, auth/opie.c,
+ auth/pam.c, auth/passwd.c, auth/secureware.c, auth/securid.c,
+ auth/skey.c, auth/sudo_auth.c, auth/sudo_auth.h:
+ New authentication API and methods
+ [9debe9b59c79]
+
+1999-07-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.tab.c:
+ regen
+ [84578e82c1a6]
+
+ * parse.yacc:
+ only save an entry if user_matches && host_matches, even if the
+ stack is empty (fix for previous commit)
+ [00984b078d8a]
+
+ * sudo.tab.c:
+ regen
+ [66acf160b4b7]
+
+ * parse.yacc:
+ 1) Always save an entry on the stack if it is empty. This fixes the
+ -l and -v flags that were broken by earlier parser changes.
+
+ 2) In a Runas list, don't negate FALSE -> TRUE since that would make
+ !foo match any time the user specified a runas user (via -u) other
+ than foo.
+ [f322eb54b015]
+
+ * testsudoers.c:
+ interfaces and num_interfaces are now auto, not extern
+ [113add5c6518]
+
+1999-07-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth.c:
+ use a static global to keep stae about empty passwords
+ [bc02e30807d8]
+
+ * check_sia.c:
+ make PASSWORD_NOT_CORRECT logging consistent with other modules
+ [21962549d5fd]
+
+1999-07-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * auth.c:
+ PAM prompt code was wrong, looks like we have to kludge it after
+ all.
+ [91f246155ead]
+
+ * auth.c:
+ In the PAM code, when a user hits return at the first password
+ prompt, exit without a warning just like the normal auth code
+ [918f59bacdb7]
+
+ * configure, configure.in:
+ kludge around cross-compiler false positives
+ [5e5fc8356400]
+
+ * auth.c, check.c, check_sia.c, logging.c, sudo.h, tgetpass.c:
+ New (correct) PAM code Tgetpass now takes an echo flag for use with
+ PAM_PROMPT_ECHO_ON Block SIGINT and SIGTSTP during auth remove a
+ useless umask setting Change error from BAD_ALLOCATION ->
+ BAD_AUTH_INIT (for use with sia/PAM) Some cosmetic changes to auth.c
+ for consistency
+ [e71397f09dd8]
+
+ * sudo.c:
+ Some -Wall and kill some trailing spaces
+ [8229b43d5c4e]
+
+ * configure.in:
+ define -D__EXTENSIONS__ for solaris so we get crypt() proto
+ [7533e4436cab]
+
+1999-06-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * RUNSON:
+ add Dynix 4.4.4
+ [b69f773efbce]
+
+ * INSTALL, config.h.in, configure, configure.in:
+ for kerberos V < version, fall back on old kerb4 auth code
+ [d685ed3a1d8e]
+
+ * INSTALL:
+ clarify some things
+ [2f5ba2e8e53a]
+
+ * UPGRADE, sudoers.cat, sudoers.man, sudoers.pod:
+ typos
+ [8925a109c093]
+
+1999-06-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ mention why DONT_LEAK_PATH_INFO is not the default
+ [0346260cb4ec]
+
+1999-06-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * tgetpass.c:
+ Fix open(2) return value checking, was NULL for fopen, should be -1
+ for open
+ [355878bf6d8a]
+
+ * configure:
+ regen
+ [68bf82871862]
+
+ * configure.in:
+ better wording for solaris pam notice
+ [04e88c7a6c42]
+
+ * CHANGES:
+ document recent changes
+ [7c922c5622ef]
+
+ * TROUBLESHOOTING:
+ Update shadow password section
+ [e8448bae7d66]
+
+ * auth.c:
+ move authentication code from check.c to auth.c
+ [e9f6ecae2399]
+
+ * Makefile.in, check.c, sudo.h:
+ move authentication code to auth.c
+ [124cded85f46]
+
+1999-05-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, check.c, check_sia.c, compat.h, find_path.c,
+ getspwuid.c, goodpath.c, interfaces.c, interfaces.h, lex.yy.c,
+ logging.c, parse.c, parse.lex, parse.yacc, secureware.c, sudo.c,
+ sudo.h, sudo.tab.c, sudo_setenv.c, testsudoers.c, tgetpass.c,
+ visudo.c:
+ Move interface-related defines to interfaces.h so we don't have to
+ include <netinet/in.h> everywhere.
+ [e7599d8ea0bf]
+
+1999-05-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, INSTALL, TODO, check.c, compat.h, getspwuid.c, logging.c,
+ parse.yacc, sudo.c, sudo.tab.c, tgetpass.c:
+ o Replace _PASSWD_LEN braindeath with our own SUDO_MAX_PASS. It
+ turns out the old DES crypt does the right thing with passwords
+ longert than 8 characters. o Fix common typo (necesary -> necessary)
+ o Update TODO list
+ [ad75007a6f13]
+
+1999-05-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ set $LOGNAME when we set $USER
+ [391596210fd7]
+
+1999-04-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ add comment about digital unix and interfaces.c warning with gcc
+ [e20f815901cc]
+
+1999-04-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sample.sudoers:
+ use modern paths and give examples for some of the new parser
+ features
+ [e7b2e507c695]
+
+1999-04-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ fix comment
+ [5eb0d005a65f]
+
+ * alloc.c, check.c, check_sia.c, dce_pwent.c, find_path.c,
+ getspwuid.c, goodpath.c, interfaces.c, lex.yy.c, logging.c, parse.c,
+ parse.lex, parse.yacc, putenv.c, secureware.c, sudo.c, sudo.tab.c,
+ sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, visudo.c:
+ Function names should be flush with the start of the line so they
+ can be found trivially in an editor and with grep
+ [3c400abde574]
+
+ * find_path.c, interfaces.c, lex.yy.c, parse.c, parse.lex, parse.yacc,
+ sudo.c, sudo.tab.c, testsudoers.c, tgetpass.c, visudo.c:
+ free(3) is already void, no need to cast it
+ [6981e1ebda0f]
+
+ * logging.c, sudo.c, sudo.h:
+ catch case where cmnd_safe is not set (this should not be possible)
+ [3e1e3038546c]
+
+ * CHANGES, logging.c, parse.c, parse.yacc, sudo.c, sudo.h, sudo.tab.c,
+ testsudoers.c, visudo.c:
+ Stash the "safe" path (ie: the one listed in sudoers) to the command
+ instead of stashing the struct stat. Should be safer.
+ [aa2883fcf57e]
+
+1999-04-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, Makefile.in, UPGRADE:
+ notes on updating from an earlier release
+ [df9fffa4ab2c]
+
+ * CHANGES:
+ updated
+ [574f5065d15a]
+
+1999-04-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc, sudo.tab.c, sudo.tab.h, sudoers.cat, sudoers.html,
+ sudoers.man, sudoers.pod:
+ You can now specifiy a host list instead of just a host or alias.
+ Ie: user = host1,host2,ALIAS,!host3 my_command now works.
+ [e3942bb78021]
+
+ * testsudoers.c:
+ Quiet -Wall
+ [a3edc8b08c3a]
+
+ * parse.yacc, sudo.tab.c:
+ Move the push from the beginning of cmndspec to the end. This means
+ we no longer have to do a push at the end of privilege, just reset
+ some values.
+ [8ea66e5860c6]
+
+ * sudoers.cat, sudoers.html, sudoers.man, sudoers.pod:
+ runas-lists and NOPASSWD/PASSWD modifiers are now sticky and you can
+ use "!" most everywhere
+ [aadae4d1c9d5]
+
+1999-04-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ modernize paths and update su example based on sample.sudoers one
+ [3f6a37e16c83]
+
+ * sample.sudoers:
+ New runas semantics
+ [756ee92865b7]
+
+ * CHANGES, Makefile.in, alloc.c, config.h.in, configure, configure.in,
+ strdup.c, sudo.h:
+ In estrdup(), do the malloc ourselves so we don't need to rely on
+ the system strdup(3) which may or may not exist. There is now no
+ need to provide strdup() for those w/o it. Also, the prototype for
+ estrdup() was wrong, it returns char * and its param is const.
+ [5f1f984da8e3]
+
+ * getcwd.c:
+ $Sudo tag
+ [e4188a35e68c]
+
+ * check.c:
+ buf should be prompt; Michael Robokoff <mrobo@networkcs.com>
+ [2aec87c86cde]
+
+ * CHANGES, TODO, parse.yacc, sudo.tab.c:
+ It is now possible to use the '!' operator in a runas list as well
+ as in a Cmnd_Alias, Host_Alias and User_Alias.
+ [a4fdaabda990]
+
+ * logging.c, sudo.h:
+ Kill GLOBAL_NO_SPW_ENT (not used) and crank GLOBAL_PROBLEM
+ [73d0376785ae]
+
+ * sudo.h:
+ Definitions of *_matched were wrong--user top, not top-2 as
+ subscript.
+ [5f8350a57362]
+
+ * logging.c, parse.c, parse.yacc, sudo.c, sudo.h, sudo.tab.c:
+ Add VALIDATE_NOT_OK_NOPASS for when user is not allowed to run a
+ command but the NOPASSWD flag was set. Make runasspec, runaslist,
+ runasuser, and nopasswd typeless in parse.yacc Add support for '!'
+ in the runas list Fix double printing of '%' and '+' for groups and
+ netgroups respectively Add *_matched macros (no need for local stack
+ variable). Should only be used directly after a pop (since top must
+ be >= 2).
+ [392b1400c4e6]
+
+ * aclocal.m4, configure.in:
+ Add copyright, somewhat silly
+ [55c2cdd82dca]
+
+1999-04-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * BUGS, INSTALL, Makefile.in, README, alloc.c, check.c, check_sia.c,
+ compat.h, config.h.in, configure, configure.in, dce_pwent.c,
+ emul/utime.h, find_path.c, getspwuid.c, goodpath.c, ins_2001.h,
+ ins_classic.h, ins_csops.h, ins_goons.h, insults.h, interfaces.c,
+ lex.yy.c, logging.c, parse.c, parse.lex, parse.yacc, pathnames.h.in,
+ putenv.c, secureware.c, strdup.c, sudo.c, sudo.cat, sudo.h,
+ sudo.man, sudo.tab.c, sudo_setenv.c, sudoers.cat, sudoers.man,
+ testsudoers.c, tgetpass.c, utime.c, version.h, visudo.c, visudo.cat,
+ visudo.man:
+ Crank version to 1.6 and combine copyright statements
+ [0e1c791658ae]
+
+ * sample.sudoers:
+ Use ! not ^ to do negation
+ [1480a0761730]
+
+ * lex.yy.c, sudo.tab.c:
+ regen
+ [89ca5a46684b]
+
+ * parse.lex, parse.yacc:
+ Make runas and NOPASSWD tags persistent across entris in a command
+ list. Add a PASSWD tag to reverse NOPASSWD. When you override a
+ runas or *PASSWD tag the value given becomes the new default for the
+ rest of the command list.
+ [f1bbb4066542]
+
+1999-04-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, RUNSON:
+ update for 1.5.9
+ [a1ae9d4a7d54] [SUDO_1_5_9]
+
+ * visudo.c:
+ Shift return value of system(3) by 8 to get real exit value and if
+ it is not 1 or 0 print the retval along with the error message.
+ [c1ff50d743fb]
+
+1999-03-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ testsudoers needs LIBOBJS too
+ [972571b4e4bf]
+
+ * parse.c, parse.yacc, sudo.tab.c:
+ Fix another parser bug. For a sudoers entry like this: millert
+ ALL=/bin/ls,(daemon) !/bin/ls sudo would not allow millert to run ls
+ as root.
+ [51968e1eb33d]
+
+ * CHANGES:
+ new change
+ [271c6110bb62]
+
+ * parse.yacc, sudo.tab.c:
+ Save entries that match a ! command on the matching stack too
+ [5afb5107116c]
+
+ * sudo.c:
+ Make sudo's usage info better when mutually exclusive args are given
+ and don't rely on argument order to detect this; nick@zeta.org.au
+ [2422753c88fd]
+
+1999-03-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, Makefile.in, RUNSON:
+ updates from CU
+ [b37381e3dafb]
+
+ * Makefile.in:
+ use gzip
+ [94a64e52a166]
+
+ * parse.yacc, sudo.tab.c:
+ Fix off by one error introduced in *alloc changes
+ [95ede581153a]
+
+ * BUGS, CHANGES, INSTALL, Makefile.in, README, alloc.c, check.c,
+ check_sia.c, compat.h, config.h.in, configure, configure.in,
+ dce_pwent.c, emul/utime.h, find_path.c, getspwuid.c, goodpath.c,
+ ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h,
+ interfaces.c, lex.yy.c, logging.c, parse.c, parse.lex, parse.yacc,
+ pathnames.h.in, putenv.c, secureware.c, strdup.c, sudo.c, sudo.cat,
+ sudo.h, sudo.man, sudo.tab.c, sudo_setenv.c, sudoers.cat,
+ sudoers.man, testsudoers.c, tgetpass.c, utime.c, version.h,
+ visudo.c, visudo.cat, visudo.html, visudo.man, visudo.pod:
+ ++version
+ [c6d88f024e37]
+
+ * Makefile.in, check.c, find_path.c, getspwuid.c, goodpath.c,
+ interfaces.c, lex.yy.c, logging.c, parse.c, parse.lex, parse.yacc,
+ putenv.c, secureware.c, strdup.c, sudo.c, sudo.h, sudo.tab.c,
+ sudo_setenv.c, testsudoers.c, utime.c, visudo.c:
+ Use emalloc/erealloc/estrdup
+ [44221d97361a]
+
+ * alloc.c:
+ error checking memory allocation routines
+ [5f8c1e7bbc71]
+
+ * parse.yacc, sudo.tab.c:
+ Still not right, this fixes it for real
+ [ad553b6f5339]
+
+ * parse.yacc, sudo.tab.c:
+ Fix for previous commit
+ [4d6f989f9bf2]
+
+ * CHANGES, INSTALL, parse.yacc:
+ Fix a parser bug that was exposed when mixing different runas specs
+ and ! commands. For example: millert ALL=(daemon)
+ /usr/bin/whoami,!/bin/ls would allow millert to run whoami as root
+ as well as daemon when it should just allow daemon. The problem was
+ that comma-separated commands in a list shared the same entry on the
+ matching stack. Now they get their own entry iff there is a full
+ match. It may be better to just make the runas spec persistent
+ across all commands in a list like the user and host entries of the
+ matching stack. However, since that is a fairly major change it
+ should gets its own minor rev increase.
+ [c4b939cdcc8e]
+
+1999-03-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c, config.h.in:
+ Simplify PAM code and fix a PAM-related warning on Linux
+ [2468399523b6]
+
+1999-03-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ updates
+ [29d4a997769c]
+
+ * sample.sudoers:
+ better su entry
+ [76d8285a72ba]
+
+ * configure:
+ regen
+ [b7450cc6975d]
+
+ * check.c, configure.in:
+ new pam code that works on solaris, should work on linux too;
+ aelberg@home.com
+ [84c16c0ff259]
+
+1999-03-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * RUNSON:
+ more entries
+ [b6bef8660759]
+
+ * config.h.in:
+ only include strings.h if there is no string.h
+ [b66054a32b00]
+
+1999-03-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.guess:
+ Sinix is now being called ReliantUNIX; bjjackso@us.oracle.com
+ [c086d2fe63af]
+
+1999-03-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ shost must be set before log functions are called #ifdef HOST_IN_LOG
+ [d49a7944358f]
+
+1999-03-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, lex.yy.c, parse.lex:
+ Fix a bug wrt quoting characters in command args. Stop processing an
+ arg when you hit a backslash so the quoted-character detection can
+ catch it.
+ [2281438d7f41]
+
+1999-02-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * interfaces.c:
+ include sys/time.h; aparently AIX needs it. ppz@cdu.elektra.ru
+ [31118a9e9916]
+
+1999-02-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ add missing case statement so --without-sendmail works
+ [ca25614f7dd9]
+
+1999-02-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ more
+ [4d70e44f7f93]
+
+1999-02-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ only search for -lsun in irix <= 4.x
+ [e604238317b1]
+
+ * configure, configure.in:
+ back out last configure.in change now that I've hacked autoconf to
+ fix the real problem and add a missing newline
+ [2dabf59a79b5]
+
+ * CHANGES:
+ updated
+ [bb35d526552f]
+
+ * getcwd.c:
+ add def of dirfd() for those without it
+ [95f0173d8441]
+
+ * configure, configure.in:
+ When falling back to checking for socket() when linking with
+ "-lsocket -lnsl" check for main() instead since autoconf has already
+ cached the results of checking for socket() in -lsocket. This is
+ really an autoconf bug as it should use the extra libs as part of
+ the cache variable name.
+ [a845f8b710ad]
+
+ * configure.in:
+ typo
+ [a7d62f62a478]
+
+1999-02-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ fix occurrence of $with_timeout that should be
+ $with_password_timeout; Michael.Neef@neuroinformatik.ruhr-uni-
+ bochum.de
+ [8c4da2cf73d1]
+
+1999-02-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.cat, sudo.html, sudo.man, sudo.pod:
+ fix grammar; espie@openbsd.org
+ [7031d9dfbc3e] [SUDO_1_5_8]
+
+1999-02-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc, sudo.c, testsudoers.c:
+ add cast for strdup in places it does not have it
+ [7ce4478d3b0f]
+
+1999-02-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ define for_BSD_TYPES irix
+ [858337ff4af8]
+
+1999-02-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, sudo.cat, sudo.html, sudo.man, sudo.pod:
+ Make it clear that it is the user's password, not root's, that we
+ want.
+ [ae0f51b35ee4]
+
+ * check.c, sudo.h:
+ If the user enters an empty password and really has no password,
+ accept the empty password they entered. Perviously, they could enter
+ anything
+ *but* an empty password. Also, add GETPASS macro that calls either
+ tgetpass() or getpass() depending on how sudo was configured.
+ Problem noted by jdg@maths.qmw.ac.uk
+ [2fde21ce94c1]
+
+1999-02-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, check.c, check_sia.c, compat.h, config.h.in,
+ dce_pwent.c, emul/utime.h, find_path.c, getspwuid.c, goodpath.c,
+ ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h,
+ interfaces.c, logging.c, parse.c, parse.lex, parse.yacc,
+ pathnames.h.in, putenv.c, secureware.c, strdup.c, sudo.c, sudo.h,
+ sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, version.h,
+ visudo.c:
+ add explicate copyright
+ [d3b4449834a5]
+
+ * CHANGES:
+ mention -lsocket, -lnsl configure changes
+ [9140af4ad8ae]
+
+1999-02-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Don't clobber errno after calling check_sudoers().
+ [59bd581b2654]
+
+1999-02-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ When linking with both -lsocket and -lnsl be sure to do so in that
+ order. Also, when we can't find socket() or inet_addr() and have to
+ try linking with both libs, issue a warning.
+ [0ee547163067]
+
+ * sudo.cat, sudo.man, sudo.pod:
+ clarify bad timestamp and fmt
+ [70e42cf56c75]
+
+1999-01-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, RUNSON:
+ be clear that pam is linux-only and add a RUNSON entry
+ [7fdeab875e0d]
+
+1999-01-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, INSTALL, configure, configure.in:
+ fix and correctly document --with-umask; problem noted by
+ adap@adap.org
+ [11cd0481d63a]
+
+1999-01-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure, configure.in:
+ only use /usr/{man,catman}/local to store man pages if suer didn't
+ override prefix or mandir
+ [781ad2cbe9be]
+
+ * INSTALL, configure, configure.in:
+ fix typo, make --with-SecurID take an arg
+ [026a9b4014fc]
+
+1999-01-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * RUNSON:
+ updates from users
+ [2286982b31e6]
+
+ * CHANGES, INSTALL, check.c, configure, configure.in:
+ FWTK 'authsrv' support from Kevin Kadow <kadow@MSG.NET>
+ [23aa4e5c6b02]
+
+ * configure, configure.in:
+ better fix for the problem of unresolved symbols in -lnsl or
+ -lsocket
+ [82fe70fc287f]
+
+ * configure, configure.in:
+ when checking for functions in -lnsl and -lsocket link with both of
+ them to avoid unresolved symbols on some weirdo systems
+ [1734a591808e]
+
+1999-01-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * BUGS, CHANGES, RUNSON, TODO:
+ old changes that didn't make it into RCS before the RCS->CVS switch
+ [846eb2b8f9aa]
+
+1999-01-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, check.c, check_sia.c, compat.h, config.h.in,
+ configure.in, dce_pwent.c, emul/search.h, emul/utime.h, find_path.c,
+ getspwuid.c, goodpath.c, ins_2001.h, ins_classic.h, ins_csops.h,
+ ins_goons.h, insults.h, interfaces.c, lex.yy.c, logging.c,
+ lsearch.c, parse.c, parse.lex, parse.yacc, pathnames.h.in, putenv.c,
+ secureware.c, strdup.c, sudo.c, sudo.pod, sudo_setenv.c,
+ sudoers.pod, testsudoers.c, tgetpass.c, utime.c, visudo.c,
+ visudo.pod:
+ add sudo tags
+ [962f81eaa5ab]
+
+ * sudo.h:
+ testing Sudo tag
+ [e84cbc521129]
+
+ * version.h:
+ testing Sudo tag
+ [a8c3a3998b88]
+
+ * BUGS, INSTALL, Makefile.in, README, check.c, check_sia.c, compat.h,
+ config.h.in, configure, configure.in, dce_pwent.c, emul/utime.h,
+ find_path.c, getspwuid.c, goodpath.c, ins_2001.h, ins_classic.h,
+ ins_csops.h, ins_goons.h, insults.h, interfaces.c, lex.yy.c,
+ logging.c, parse.c, parse.lex, parse.yacc, pathnames.h.in, putenv.c,
+ secureware.c, strdup.c, sudo.c, sudo.cat, sudo.h, sudo.man,
+ sudo_setenv.c, sudoers.cat, sudoers.man, testsudoers.c, tgetpass.c,
+ utime.c, version.h, visudo.c, visudo.cat, visudo.man:
+ crank version and regen files
+ [23eacf00a1a4]
+
+ * Makefile.in:
+ kill rcs goop in update_version and fix now that version is a const
+ [e6e50bd8d1e1]
+
+ * INSTALL, check.c, config.h.in, configure, configure.in, logging.c,
+ sudo.c, sudo.h, sudo.pod:
+ kerb5 support from fcusack@iconnet.net
+ [8134027986e2]
+
+ * realpath.c, sudo_realpath.c:
+ we no longer use realpath
+ [0f5f64abc646]
+
+ * qualify.c:
+ replaced by find_path.c
+ [9e32a87e09c4]
+
+ * options.h:
+ all options are now configure flags
+ [ee6bd9610102]
+
+ * lex.yy.c:
+ regen
+ [bdbf8a18161f]
+
+ * getwd.c:
+ superceded by getcwd.c
+ [1e54ee0990b4]
+
+ * getpass.c:
+ superceded by tgetpass.c
+ [4e0d1edc30e3]
+
+ * SUPPORTED:
+ superceded by RUNSON
+ [854c5a21cb53]
+
+ * OPTIONS:
+ No longer used now that we have configure options for everything.
+ [9b1ae1c89259]
+
+ * configure:
+ regen based on configure.in
+ [3a4d73936973]
+
+ * sudo.cat, sudo.html, sudo.man, sudoers.cat, sudoers.html,
+ sudoers.man, visudo.cat, visudo.html, visudo.man:
+ regen based on sudo.pod, sudoers.pod, and visudo.pod
+ [c267beb90778]
+
+1998-12-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ fix tty tickets in remove_timestamp (didn't use ':')
+ [fd964a74a32b]
+
+1998-12-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * interfaces.c:
+ close sock when we are done with it
+ [95de0380f8a4]
+
+1998-11-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc:
+ never say "error on line -1"
+ [361db1491121]
+
+1998-11-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ check for -lnsl before -lsocket
+ [8e966d6bbcb5]
+
+ * configure.in:
+ quote '[', ']' used in ranges correctly
+ [fa4f9c6ff651]
+
+1998-11-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in:
+ add missing NO_ROOT_SUDO noted by drno@tsd.edu
+ [c969f25d1667]
+
+1998-11-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * version.h:
+ 1.5.7
+ [7a22de0bc148]
+
+ * INSTALL:
+ more info for 1.5.7
+ [30ad9e784799]
+
+ * README:
+ update for 1.5.7
+ [cd03a0a27cd2]
+
+ * parse.yacc:
+ make increases of cm_list_size and ga_list_size be similar to
+ increases of stacksize (ie: >= not > in initial compare).
+ [6bd450a896c7]
+
+ * parse.yacc:
+ when we get a syntax error, report it for the previous line since
+ that's generally where the error occurred.
+ [c4ac84058f0b]
+
+1998-11-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in, configure.in, interfaces.c:
+ add back check for sys/sockio.h but only use it if SIOCGIFCONF is
+ not defined
+ [d197f31fd1e4] [SUDO_1_5_7]
+
+ * config.h.in:
+ define BSD_COMP for svr4
+ [87ac1147ff79]
+
+ * check.c, check_sia.c, find_path.c, getcwd.c, getspwuid.c,
+ goodpath.c, interfaces.c, logging.c, lsearch.c, parse.c, parse.lex,
+ parse.yacc, putenv.c, secureware.c, strdup.c, sudo.c, sudo_setenv.c,
+ testsudoers.c, tgetpass.c, utime.c, visudo.c:
+ more -Wall
+ [d98e2d32db2a]
+
+ * configure.in:
+ kill check for sockio,h
+ [4399779014c1]
+
+ * config.h.in:
+ no more HAVE_SYS_SOCKIO_H
+ [67484528e347]
+
+ * check.c, check_sia.c, find_path.c, getcwd.c, getspwuid.c,
+ goodpath.c, interfaces.c, logging.c, lsearch.c, parse.c, parse.lex,
+ parse.yacc, putenv.c, secureware.c, strdup.c, sudo.c, sudo_setenv.c,
+ testsudoers.c, tgetpass.c, utime.c, visudo.c:
+ -Wall
+ [2b7e83976788]
+
+1998-11-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ add missing inform_user()
+ [8689528c6d55]
+
+1998-11-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * find_path.c:
+ return NOT_FOUND if given fully qualified path and it does not exist
+ previously it would perror(ENOENT) which bypasses the option to not
+ leak path info
+ [ccbc3d0130ae]
+
+ * configure.in:
+ for kerb5, check for -lkerb4, fall back on -lkrb for kerb, check for
+ -ldes
+ [c77d3b484ece]
+
+1998-11-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ tty tickets are user:tty now
+ [a53a303a614d]
+
+ * check.c:
+ when using tty tickets make it user:tty not user.tty as a username
+ could have a '.' in it
+ [3160b3f5c890]
+
+1998-11-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ add "ignoring foo found in ." for auth successful case
+ [24257169e0bd]
+
+1998-11-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ add missing printf param
+ [8c905124f777]
+
+1998-11-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, config.h.in, configure.in, find_path.c, sudo.c, sudo.h:
+ go back to printing "command not found" unless --disable-path-info
+ specified. Also, tell user when we ignore '.' in their path and it
+ would have been used but for --with-ignore-dot.
+ [066e118c11e4]
+
+ * check.c, sudo.c:
+ Only one space after a colon, not two, in printf's
+ [38452f4c8007]
+
+1998-11-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod:
+ document setting $USER
+ [80557fe6aede]
+
+ * check.c:
+ fix bugs with prompt expansion
+ [44c4fca5f009]
+
+ * sudo.c:
+ set $USER for root too
+ [4b525e1c6269]
+
+1998-11-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * getspwuid.c:
+ typo
+ [5107446f43e0]
+
+ * configure.in:
+ HP-UX's iscomsec is in -lsec, not libc
+ [03c9f700b795]
+
+ * configure.in:
+ remove some entries in the OS case statement that did nothing
+ [ea96e7e0f624]
+
+ * TROUBLESHOOTING:
+ add "cd" section and flush out syslog section
+ [5107f7363b78]
+
+ * Makefile.in:
+ no more sudo-lex.yy.c
+ [ed50826efbbc]
+
+ * check_sia.c:
+ add custom prompt support
+ [6a285cea10b7]
+
+ * testsudoers.c:
+ kill perror("malloc") since we already have a good error messages
+ pw_ent -> pw for brevity
+ [eee31052921e]
+
+ * sudo.c:
+ kill perror("malloc") since we already have a good error messages
+ pw_ent -> pw for brevity set $USER if -u specified
+ [9f3753461f8a]
+
+ * parse.yacc:
+ kill perror("malloc") since we already have a good error messages
+ [849459088ac3]
+
+ * parse.c:
+ kill perror("malloc") since we already have a good error messages
+ pw_ent -> pw for brevity when checking if %group matches, look up
+ user in password file so that %groups works in a RunAs spec.
+ [0489b4ecc59a]
+
+ * logging.c:
+ kill perror("malloc") since we already have a good error messages
+ [3191a18b3526]
+
+ * check.c, getspwuid.c, interfaces.c:
+ kill perror("malloc") since we already have a good error messages
+ pw_ent -> pw for brevity
+ [7193fdb38cf9]
+
+1998-11-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * tgetpass.c:
+ the prompt is expanded before tgetpass is called
+ [0f408f508041]
+
+ * sudo.h:
+ tgetpass now has the same args as getpass again
+ [b6778cd9d79f]
+
+ * getspwuid.c:
+ add iscomsec, issecure support
+ [007be7ec7ae7]
+
+ * check.c:
+ we now expand any %h or %u in the prompt before passing to tgetpass
+ [f3db8c9ee387]
+
+ * configure.in:
+ add check for syslog(3) in -lsocket, -lnsl, -linet
+ [5a96f902ce00]
+
+ * config.h.in:
+ add HAVE_ISCOMSEC and HAVE_ISSECURE
+ [f640b0d4cf05]
+
+ * configure.in:
+ add check for iscomsec in HP-UX
+ [b28b249040f0]
+
+ * configure.in:
+ check for issecure if we have getpwanam on SunOS some options are
+ incompatible with DUNIX SIA check for dispcrypt on DUNIX
+ [a49d05d9c913]
+
+1998-10-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in:
+ add HAVE_DISPCRYPT
+ [7376d543d8d6]
+
+ * secureware.c:
+ add back support for non-dispcrypt based checking for older DUNIX
+ [977b98e936be]
+
+ * INSTALL:
+ sia changes
+ [c5387c06e30f]
+
+ * configure.in:
+ SIA becomes the default on Digital UNIX now havbe --disable-sia to
+ turn it off...
+ [3b647558ea13]
+
+ * check.c:
+ move local includes after system ones
+ [b2abad4c4aef]
+
+1998-10-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c, check_sia.c, sudo.h:
+ add pass_warn() which prints out INCORRECT_PASSWORD or an insult to
+ stderr
+ [547cbf299661]
+
+ * check_sia.c:
+ fix while loop in sia_attempt_auth() that checks the password. Only
+ the first iteration was working.
+ [1886fd1ac831]
+
+1998-10-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aclocal.m4:
+ don't trust UID_MAX or MAXUID
+ [2aeddb1654d8]
+
+ * configure.in:
+ fix two pastos
+ [c18f0a10b75d]
+
+ * configure.in:
+ fix typo
+ [1eb3190ef12d]
+
+ * getspwuid.c, secureware.c:
+ init crypt_type to INT_MAX since it is legal to be negative in DUNX
+ 5.0
+ [cefbde04822d]
+
+ * configure.in:
+ for secureware on dunix, use -lsecurity -ldb -laud -lm but check for
+ -ldb since DUNX < 4.0 lacks it
+ [e6b11d971068]
+
+1998-10-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c, compat.h, config.h.in, configure.in, getspwuid.c,
+ secureware.c, sudo.c, tgetpass.c:
+ getprpwuid is broken in HP-UX 10.20 at least (it sleeps for 2
+ minutes if the shadow files don't exist).
+ [2f297d095004]
+
+1998-10-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ updated --with-editor blurb
+ [77d8a3ea7328]
+
+ * TROUBLESHOOTING:
+ tell how to put sudoers in a different dir
+ [456cd20eb1d0]
+
+ * configure.in:
+ add missing quotes around $with_editor
+ [22881748ab1b]
+
+ * configure.in:
+ typo in --with-editor bits
+ [ab6964580681]
+
+ * INSTALL:
+ I don't expect it to work on Solaris
+ [1c2fceaaf56e]
+
+ * check.c:
+ add back security/pam_misc.h
+ [6ffd30033c1e]
+
+1998-10-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ remove dunix note since configure checks for this now
+ [e9904512b8e8]
+
+ * configure.in:
+ add check for broken dunix prot.h (4.0 < 4.0D is bad)
+ [8a4c1e6aef3b]
+
+ * getspwuid.c, secureware.c, tgetpass.c:
+ new dunix shadow code, use dispcrypt(3)
+ [1b936bc7268c]
+
+ * config.h.in:
+ add HAVE_INITPRIVS
+ [4369f4c4f914]
+
+ * sudo.c:
+ call initprivs() if we have it for getprpwuid later on
+ [11cf5915d826]
+
+ * Makefile.in:
+ clean pathnames.h too
+ [5f1df3262613]
+
+ * configure.in:
+ quote "Sorry, try again." with [] since it has a comma in it set
+ LIBS when we add stuff to SUDO_LIBS set SECUREWARE when we find
+ getprpwuid() so we can check for bigcrypt, set_auth_parameters, and
+ initprivs later.
+ [e226b0a3f250]
+
+ * INSTALL:
+ update Digital UNIX note about acl.h
+ [80132b71d73a]
+
+ * INSTALL:
+ add --with-sia
+ --without-root-sudo -> --disable-root-sudo some reordering
+ [198386358818]
+
+ * secureware.c:
+ add whitespace
+ [4aadaf1a54b0]
+
+ * Makefile.in, check.c, config.h.in, configure.in, logging.c, sudo.h:
+ add SIA support
+ [fa3ddbb9cc51]
+
+ * check_sia.c:
+ Initial revision
+ [2968551d40e4]
+
+1998-10-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ when checking for -lsocket, -lnsl, and -linet, check for the
+ specific functions we need from them.
+ [8d33e64362a3]
+
+ * config.h.in, sudo.h:
+ move Syslog_* defs into sudo.h
+ [03d1774f25c7]
+
+ * Makefile.in, sudo.h:
+ added check_secureware
+ [e46e3cbb9a97]
+
+ * configure.in:
+ finished adding AC_MSG_CHECKING and AC_MSG_RESULT bits
+ [dbefe1856503]
+
+ * insults.h:
+ don't define CLASSIC_INSULTS and CSOPS_INSULTS if no other sets
+ defined. configure now does that for us
+ [e4520ea0581f]
+
+ * configure.in:
+ move some --with options around change a bunch of echo's to
+ AC_MSG_CHECKING, AC_MSG_RESULT pairs
+ [ffdf6869fdd7]
+
+ * configure.in:
+ change $with_foo-bar -> $with_foo_bar kill extra " that caused a
+ syntax error add some echo verbage
+ [3278c49bf74b]
+
+1998-10-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ moved SecureWare stuff into secureware.c
+ [42d3d3ac35dc]
+
+ * secureware.c:
+ Initial revision
+ [aa7f72a249cf]
+
+ * INSTALL:
+ update url to solaris gcc bins
+ [36a3eb668777]
+
+ * INSTALL:
+ change option formatter and flesh out someentries
+ [6fbd1db4a8ad]
+
+ * TROUBLESHOOTING, sudo.pod, visudo.pod:
+ environmental variable -> environment variable
+ [6f14d708e32d]
+
+ * BUGS:
+ everything is now done via configure
+ [c217858f58ab]
+
+ * README:
+ prev rev was 1.5.6
+ [7b4177103c35]
+
+ * Makefile.in:
+ passing SUDOERS_MODE, SUDOERS_UID, SUDOERS_GID correctly
+ [31c6b0a5e0e2]
+
+ * config.h.in:
+ SUDOERS_MODE, SUDOERS_UID, SUDOERS_GID now come from the Makefile
+ [d406a1ef6d25]
+
+ * Makefile.in:
+ merge OSDEFS and OPTIONS into DEFS get sudoers_uid, sudoers_gid,
+ sudoers_mode from configure
+ [1c509500655a]
+
+ * configure.in:
+ SUDOERS_MODE, SUDOERS_UID, and SUDOERS_GID now get substituted into
+ the Makefile, not config.h
+ [d4482f1492fe]
+
+ * INSTALL:
+ document all --with/--enable options
+ [22d81b312d7f]
+
+1998-10-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * insults.h:
+ options.h is no more
+ [560946a33f7f]
+
+ * config.h.in:
+ assimilated options.h
+ [dd8ce74613c1]
+
+ * configure.in:
+ moved options from options.h to configure
+ [d39662f71b4e]
+
+ * check.c, find_path.c, getspwuid.c, goodpath.c, interfaces.c,
+ logging.c, parse.c, parse.lex, parse.yacc, sudo.c, sudo.pod,
+ sudo_setenv.c, visudo.c:
+ no more options.h
+ [43924bf0858d]
+
+ * INSTALL, Makefile.in, PORTING, TROUBLESHOOTING:
+ remove references to options.h
+ [ef3474295395]
+
+ * dce_pwent.c, interfaces.c, sudo.c:
+ kill sys/time.h
+ [4d833f0034e4]
+
+ * tgetpass.c:
+ if select return < -1 still prompt for pw
+ [e0009e5c93a2]
+
+ * options.h:
+ convert LOGGING, LOGFAC, MAXLOGFILELEN, IGNORE_DOT_PATH into
+ configure options
+ [e60a1e546516]
+
+ * parse.c:
+ FAST_MATCH is no longer an optino
+ [c448dbb3464b]
+
+ * check.c:
+ remove_timestamp() if timestamp is preposterous
+ [70d9a86c6ecd]
+
+ * options.h:
+ convert more options to --with/--enable
+ [34646d9b09dc]
+
+ * INSTALL, aclocal.m4:
+ logfile -> logpath
+ [42de502bc637]
+
+ * configure.in:
+ convert more options into --with and --enable
+ [92d0898c9844]
+
+ * tgetpass.c:
+ catch EINTR in select and restart
+ [f045d2f234d7]
+
+ * logging.c:
+ sys/errno -> errno
+ [7f0c5beab6f2]
+
+1998-09-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ UMASK -> SUDO_UMASK.
+ [48f308661514]
+
+ * check.c, logging.c:
+ time.h, not sys/time.h
+ [91de049c79e4]
+
+1998-09-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ MAILER -> _PATH_SENDMAIL
+ [df65d6896639]
+
+ * INSTALL, configure.in:
+ no more --with-C2, now it is --disable-shadow
+ [18bfcab3b9ab]
+
+ * aclocal.m4, check.c, compat.h, config.h.in, configure.in,
+ getspwuid.c, sudo.c, tgetpass.c:
+ new shadow password scheme. Always include shadow support if the
+ platform supports it and the user did not disable it via configure
+ [2135d93bb4a9]
+
+1998-09-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ --with-getpass -> --{enable,disable}-tgetpass
+ [451b33fdd4c7]
+
+ * Makefile.in:
+ pathnames.h -> pathnames.h.in
+ [b109022eca69]
+
+ * check.c:
+ fix version string
+ [761b25c314ea]
+
+ * check.c:
+ move pam_conv to be static to auth function remove pam_misc.h
+ (solaris doesn't have one)
+ [a682e4da987a]
+
+ * aclocal.m4:
+ _CONFIG_PATH_* -> _PATH_* or _PATH_SUDO_* kill SUDO_PROG_PWD
+ [e6005d0599b5]
+
+ * configure.in:
+ munge pathnames.h.in -> pathnames.h kill SUDO_PROG_PWD
+ [24c0ac2155ef]
+
+ * pathnames.h.in:
+ convert to pathnames.h.in
+ [013bddf7f684]
+
+1998-09-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ fix typo in sysv4 matching case /.
+ [2994c4f88cf5]
+
+1998-09-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ pam stuff needs to run as root, not user, for shadow passwords
+ [d94ff75de503]
+
+1998-09-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * BUGS, INSTALL, README, configure.in:
+ updated version
+ [775adc7de7ac]
+
+ * Makefile.in, check.c, compat.h, config.h.in, dce_pwent.c,
+ emul/utime.h, find_path.c, getspwuid.c, goodpath.c, ins_2001.h,
+ ins_classic.h, ins_csops.h, ins_goons.h, insults.h, interfaces.c,
+ logging.c, options.h, parse.c, parse.lex, parse.yacc,
+ pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, sudo_setenv.c,
+ testsudoers.c, tgetpass.c, utime.c, visudo.c:
+ updated version
+ [5ca599fb6b93]
+
+ * check.c:
+ user version.h for long message
+ [47a52ac7e542]
+
+ * check.c:
+ this is version 1.5.6
+ [8451ac79eee2]
+
+1998-09-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ remove errant backslash
+ [0222a8a650ff]
+
+1998-09-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * options.h, parse.yacc, pathnames.h.in:
+ fix version string
+ [fdee73255d64] [SUDO_1_5_6]
+
+ * BUGS, CHANGES, TODO:
+ updtaed for 1.5.6
+ [752443bf7f26]
+
+ * RUNSON:
+ updated for 1.5.6
+ [0f878123fe6a]
+
+1998-09-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * interfaces.c:
+ kill unused localhost_mask var copy if name to ifr_tmp after we zero
+ it
+ [8e89c364cef2]
+
+1998-09-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ Better description of new vs. old sudoers modes fix some typos
+ better description of /usr/ucb/cc gotchas on slowaris
+ [c00b2a6fc1e8]
+
+ * Makefile.in:
+ add sample.pam
+ [ec7f6cc19b00]
+
+ * sudo.c:
+ set NewArgv[0] to user_shell, not basename(user_shell)
+ [1e907cbc9f7b]
+
+1998-09-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * README:
+ mention TROUBLESHOOTING more fix some typos
+ [2c2e6907d4a4]
+
+ * configure.in:
+ move --enable/--disable to be after --with
+ [9b30097f76c1]
+
+ * INSTALL:
+ document --enable/--disable
+ [c522362e38a8]
+
+ * INSTALL:
+ document --with-pam
+ [7e38932c78ac]
+
+1998-09-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ Add message for pam users
+ [d224f277e3cd]
+
+ * sample.pam:
+ Initial revision
+ [3a84d7045f54]
+
+ * config.h.in:
+ fix HAVE_PAM
+ [2f0f303ebd88]
+
+ * check.c, config.h.in, configure.in:
+ pam support, from Gary Calvin <GCalvin@kenwoodusa.com>
+ [ea3e0a72d707]
+
+1998-09-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in:
+ add HOST_IN_LOG and WRAP_LOG
+ [822c36eeb6a8]
+
+ * logging.c:
+ add WRAP_LOG and HOST_IN_LOG
+ [3cf6052bd27e]
+
+ * configure.in:
+ add --enable-log-host and --enable-log-wrap
+ [c968cc12b353]
+
+ * aclocal.m4:
+ use AC_DEFINE_UNQUOTED for --with-logfile and --with-timedir
+ [915fef7e11a1]
+
+1998-09-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat.h:
+ add howmany macro
+ [9107a057a7c8]
+
+ * tgetpass.c:
+ include sys/param.h to get howmany macro
+ [7e908b5e1f32]
+
+1998-09-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * OPTIONS, options.h, parse.yacc, sudo.c, testsudoers.c, visudo.c:
+ add RUNAS_DEFAULT
+ [1e76398ea3fd]
+
+1998-09-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * fnmatch.c:
+ bring in stdio.h for NULL
+ [69c016610cbb]
+
+ * aclocal.m4:
+ allow /bin/{ksh,bach} and /usr/bin/{ksh,bash} as sh
+ [15ab2972f8d0]
+
+ * sudo.c:
+ use HAVE_SET_AUTH_PARAMETERS
+ [8abfdc8c80f7]
+
+ * config.h.in:
+ add HAVE_SET_AUTH_PARAMETERS
+ [673a5ebd5539]
+
+ * configure.in:
+ add *-*-hiuxmpp* add test for set_auth_parameters() if secureware
+ [a401f5a7469a]
+
+ * config.sub:
+ add support for HI-UX/MPP SR220001 02-03 0 SR2201
+ [cb657b7acaae]
+
+ * interfaces.c:
+ initialize previfname
+ [26a1902f56dc]
+
+ * interfaces.c:
+ Don't use SIOCGIFADDR, we don't need it Use SIOCGIFFLAGS if we have
+ it check ifr_flags against IFF_UP and IFF_LOOPBACK instead of
+ kludging it
+ [fa5c890c313b]
+
+ * configure.in:
+ typo
+ [bff579fbe95c]
+
+ * Makefile.in:
+ don't need special build line for sudo.tab.o
+ [10c0a0a912e4]
+
+ * Makefile.in:
+ don't clean sudo.tab.[ch]
+ [c40d5968efbb]
+
+ * sudo.c:
+ Sudo should prompt for a password before telling the user that a
+ command could not be found.
+ [d718c85a0047]
+
+ * BUGS:
+ for 1.5.6
+ [0cc1fe5b9129]
+
+ * INSTALL, README:
+ no longer require yacc
+ [d9096fc5b8b6]
+
+ * Makefile.in:
+ typo
+ [70feb1aefbd5]
+
+ * Makefile.in:
+ y.tab -> sudo.tab include pre-yacc'd parse.yacc
+ [cc802025fd44]
+
+ * parse.lex:
+ include sudo.tab.h, not y.tab.h don't break out of command args if
+ you get a '='
+ [728ad26dbda5]
+
+ * insults.h:
+ fix version ,
+ [242bbce1b2d4]
+
+ * ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h:
+ fix version
+ [2bb9086fea1e]
+
+ * compat.h:
+ fix version
+ [7e634d498ce6]
+
+ * getcwd.c:
+ getcwd(3) from OpenBSD for those without it.
+ [6c68d0df8f6c]
+
+ * sudo.h:
+ HAVE_GETWD -> HAVE_GETCWD
+ [2ad1e64d60c0]
+
+ * configure.in:
+ pretend sunos doesn't have getcwd(3) since it opens a pipe to
+ getpwd!
+ [677992ba5a6a]
+
+ * parse.c:
+ use NAMLEN() macro
+ [8f5685aa3165]
+
+ * fnmatch.c:
+ remove duplicate include of string.h
+ [6024f3051ac3]
+
+ * configure.in:
+ call SUDO_TYPE_DEV_T and SUDO_TYPE_INO_T
+ [3d82a9c22cc2]
+
+ * aclocal.m4:
+ add SUDO_TYPE_DEV_T and SUDO_TYPE_INO_T
+ [53fbc47282f9]
+
+ * config.h.in:
+ add dev_t and ino_t
+ [5929bb0c7e1a]
+
+1998-07-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ fix OTP_ONLY for opie
+ [7edcfa78f2ec]
+
+1998-06-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * testsudoers.c, tgetpass.c:
+ include stdlib.h for malloc proto
+ [c9f4b99a2fe9]
+
+1998-05-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ make update_version saner
+ [d522f93ee04a]
+
+ * config.h.in:
+ add HAVE_WAITPID, HAVE_WAIT3, and sudo_waitpid()
+ [c9a2d21dc608]
+
+ * configure.in:
+ check for waitpid and wait3 or no waitpid
+ [1f18c3224184]
+
+ * logging.c:
+ used waitpid or wait3 if we have 'em
+ [391c3279ee65]
+
+1998-05-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ fix some fprintf args, ariel@oz.engr.sgi.com (Ariel Faigon)
+ [fbf53b18178f]
+
+1998-04-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ don't need to explicately mention -lsocket -lnsl for sequent
+ [1898dc055352]
+
+1998-04-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ dynix should not link with -linet
+ [278a4b9cfe2a]
+
+1998-04-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ mention that HP-UX doesn't ship with yacc
+ [bde5147198c0]
+
+1998-04-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ ignore kerberos if we can't get the local realm
+ [1e311a091a27]
+
+1998-04-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * BUGS, INSTALL, README, configure.in:
+ ++version
+ [499ffc746018]
+
+ * version.h:
+ ++
+ [35ba1ee01bd3]
+
+ * Makefile.in, check.c, config.h.in, dce_pwent.c, emul/utime.h,
+ find_path.c, getcwd.c, getspwuid.c, goodpath.c, interfaces.c,
+ logging.c, parse.c, parse.lex, putenv.c, strdup.c, sudo.c, sudo.h,
+ sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, visudo.c:
+ updated version
+ [b4990a513f31]
+
+ * check.c, sudo.h:
+ fix version
+ [5710795834e8]
+
+ * getcwd.c:
+ don't use popen/pclose. Do it inline.
+ [29e57b0646a4]
+
+ * lsearch.c:
+ add rcsid
+ [b2b55c39858d]
+
+ * sudo.c:
+ typo
+ [d381ac39ed0f]
+
+ * check.c, compat.h, ins_2001.h, ins_classic.h, ins_csops.h,
+ ins_goons.h, insults.h, options.h, parse.yacc, pathnames.h.in,
+ sudo.h:
+ updated version
+ [462d6e1a2d75]
+
+ * check.c, find_path.c, parse.c, sudo.c, testsudoers.c:
+ MAX* + 1 -> MAX*
+ [2c2eeb78d34f]
+
+ * Makefile.in:
+ getwd.c -> getcwd.c
+ [7d718c32fc02]
+
+ * config.h.in:
+ kill HAVE_GETWD
+ [6ad3d702343f]
+
+ * configure.in:
+ getcwd, not getwd
+ [33e5b9841f58]
+
+ * getcwd.c:
+ use MAX* not MAX* + 1 always run pwd as using getwd() defeats the
+ purpose
+ [24e58d340161]
+
+1998-03-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * OPTIONS, options.h:
+ add STUB_LOAD_INTERFACES
+ [d747cb23ca83]
+
+ * Makefile.in, check.c, compat.h, config.h.in, dce_pwent.c,
+ emul/utime.h, find_path.c, getspwuid.c, getwd.c, goodpath.c,
+ ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h,
+ interfaces.c, logging.c, options.h, parse.c, parse.lex, parse.yacc,
+ pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, sudo_setenv.c,
+ testsudoers.c, tgetpass.c, utime.c, visudo.c:
+ updated version
+ [0798229312cc]
+
+ * configure.in:
+ support *-ccur-sysv4 and fix two typos
+ [24a823ad7cc9]
+
+1998-03-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ don't echo about with_logfile and with_timedir
+ [31e4a1e2d9ad]
+
+ * INSTALL:
+ document --with-logfile and --with-timedir
+ [674f811a40e0]
+
+ * aclocal.m4:
+ support --with-logfile and --with-timedir
+ [2fc36b35db12]
+
+ * configure.in:
+ Add --with-logfile and --with-timedir
+ [09045bf07e29]
+
+ * sudo.c:
+ change size computation of NewArgv for UNICOS
+ [b50df07da3a1]
+
+1998-02-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ treate -*-sysv4* like *-*-svr4
+ [471b7ef4dbf2]
+
+1998-02-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ fix spacing for --with-authenticate help
+ [8321cb37c410]
+
+ * Makefile.in, check.c, compat.h, config.h.in, dce_pwent.c,
+ emul/utime.h, find_path.c, getspwuid.c, getwd.c, goodpath.c,
+ ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h,
+ interfaces.c, logging.c, options.h, parse.c, parse.lex, parse.yacc,
+ pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, sudo_setenv.c,
+ testsudoers.c, tgetpass.c, utime.c, visudo.c:
+ updated version
+ [dc1ab97312eb]
+
+ * parse.yacc:
+ fix off by one error in push macro
+ [bece59c8c3a9]
+
+1998-02-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ removed bogus alloca hack
+ [a68dd720462d]
+
+ * check.c:
+ added AIX 4.x authenticate() support
+ [12985eb448a0]
+
+ * parse.yacc:
+ include alloca.h if using bison and not gcc and it exists. fixes an
+ alloca problem on hpux 10.x
+ [e3b5c4f26072]
+
+ * INSTALL:
+ mention --with-authenticate
+ [78a1c96820e7]
+
+ * configure.in:
+ added AIX authenticate() support
+ [c983193ec252]
+
+ * config.h.in:
+ add HAVE_AUTHENTICATE
+ [7b0e5f5db5d9]
+
+ * interfaces.c:
+ dynamically size ifconf buffer
+ [10afb0e9b2f9]
+
+ * configure.in:
+ quote '[' and ']'
+ [8fc38a4defad]
+
+ * Makefile.in, check.c, compat.h, config.h.in, dce_pwent.c,
+ emul/utime.h, find_path.c, getspwuid.c, getwd.c, goodpath.c,
+ ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h,
+ logging.c, options.h, parse.c, parse.lex, parse.yacc,
+ pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, sudo_setenv.c,
+ testsudoers.c, tgetpass.c, utime.c, visudo.c:
+ updated version
+ [5f66de71ec61]
+
+ * visudo.pod:
+ add ERRORS section
+ [3df3edb73cf6]
+
+1998-02-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TROUBLESHOOTING:
+ add busy stmp file explanation
+ [6c555d469b6f]
+
+1998-02-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ the name of the cached var that signals whether or not you are cross
+ compiling changed. It is now ac_cv_prog_cc_cross
+ [123911c0658c]
+
+1998-02-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ mention glibc 2.07 is fixed wrt lsearch()\.
+ [ded758524582]
+
+1998-02-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sample.sudoers, sudoers.pod:
+ better example of su but not root su
+ [b3199610be21]
+
+1998-02-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, check.c, compat.h, config.h.in, dce_pwent.c,
+ emul/utime.h, find_path.c, getspwuid.c, getwd.c, goodpath.c,
+ ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h,
+ interfaces.c, logging.c, options.h, parse.c, parse.lex, parse.yacc,
+ pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, sudo_setenv.c,
+ testsudoers.c, tgetpass.c, utime.c, visudo.c:
+ updated version
+ [46922b84e86b]
+
+ * Makefile.in:
+ correct regexp for updating version
+ [8032728b2a8a]
+
+ * tgetpass.c:
+ remove bogus flush of stderr spew prompt before turning off echo.
+ Seems to fix a weird problem where if sudo complained about a bogus
+ stamp file the user would sometimes not have a chance to enter a
+ password
+ [7aa1493cc141]
+
+ * check.c:
+ fix bogus flush of stderr
+ [6d047871c5e8]
+
+ * sudo.c:
+ close fd's <=2 not <=3 and move that chunk of code up
+ [553e4faac195]
+
+ * configure.in:
+ support hpux1[0-9] not just hpux10
+ [5a34a000ff8a]
+
+1998-01-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ set sudoers_fp to nil after closing
+ [221a8b4bbf34]
+
+1998-01-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.guess, config.sub:
+ updated from autoconf 2.12
+ [6fc86a0fc61b]
+
+ * configure.in:
+ add *-*-svr4 rule
+ [38f0427f7c9d]
+
+1998-01-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * tgetpass.c:
+ fix select usage for high fd's (dynamically allocate readfds)
+ [c2d1f76e0321]
+
+ * check.c:
+ kill extra whitespace
+ [d784b6c9c514]
+
+ * sudo.c:
+ do an initgroups() before running a command, unless the target user
+ is root.
+ [4ca561287480]
+
+1998-01-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TROUBLESHOOTING:
+ tell people to use tabs, not spaces, in syslog.conf
+ [8ae90a205134]
+
+1998-01-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, config.h.in, dce_pwent.c, emul/utime.h, getwd.c,
+ parse.lex, putenv.c, strdup.c, testsudoers.c, utime.c:
+ updated version
+ [4d855ff5de26]
+
+ * check.c, find_path.c, getspwuid.c, goodpath.c, interfaces.c,
+ logging.c, parse.c, sudo.c, sudo_setenv.c, tgetpass.c, visudo.c:
+ updated version
+ [8e007e178b33]
+
+ * compat.h, ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h,
+ insults.h, options.h, parse.yacc, pathnames.h.in, sudo.h:
+ updated version
+ [9ddea5c8814d]
+
+ * Makefile.in:
+ more tweaks to update_version
+ [047698752855]
+
+ * Makefile.in:
+ fixed up update_version rule
+ [47b6fa34b77f]
+
+ * configure.in:
+ ++version
+ [c1ca664e30b7]
+
+ * Makefile.in:
+ removed supe of check.c
+ [8f340a05296a]
+
+ * INSTALL:
+ ++version I missed
+ [a298e6c17491]
+
+ * RUNSON:
+ updated
+ [a14f6057bc15]
+
+ * BUGS, INSTALL, Makefile.in, README, check.c, compat.h, config.h.in,
+ dce_pwent.c, emul/utime.h, find_path.c, getspwuid.c, getwd.c,
+ goodpath.c, ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h,
+ insults.h, interfaces.c, logging.c, options.h, parse.c, parse.lex,
+ parse.yacc, pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h,
+ sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, version.h,
+ visudo.c:
+ updated version
+ [02231b1a3ab3]
+
+ * CHANGES:
+ updated for 1.5.5
+ [634e5fcaf40b]
+
+ * Makefile.in:
+ add rules to update version stuff in files so I don't need to do it
+ by hand
+ [3620ad60485a]
+
+ * sudo.h:
+ sudoers_fp is now extern
+ [88c6e9b9ea84]
+
+ * sudo.c:
+ in check_sudoers, cache the sudoers file handle in sudoers_fp so we
+ don't have to open it again in the parse. This may help with weird
+ solaris problems where EAGAIN sometime occurrs.
+ [d3c26451ed1d]
+
+ * parse.c:
+ sudoers file open is now done only in check_sudoers() so we just do
+ a rewind() instead of an open. May help people on solaris who were
+ getting EAGAIN.
+ [c8b8c7722fa5]
+
+1998-01-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ mention that newer glibc is fixed
+ [20f06f5d3ef3]
+
+1998-01-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ newer irix uses _RLDN32_* envariables for 32-bit binaries so ignore
+ _RLD* instead of _RLD_*
+ [1e22c588d602]
+
+ * parse.c:
+ typo
+ [d0b7cb85f08a]
+
+ * parse.c:
+ fix that bug for real
+ [5a6eeca6d04b]
+
+ * INSTALL:
+ document Linux's libc6 brokenness.
+ [0246c1aa64ee]
+
+ * parse.yacc:
+ -Wall
+ [d0e452fb1e2d]
+
+ * RUNSON:
+ updated
+ [4949a1bbd0a9] [SUDO_1_5_4]
+
+ * TROUBLESHOOTING:
+ remind people to HUP syslogd
+ [590962faa4f0]
+
+ * Makefile.in:
+ add -O flag to tar
+ [622d02de339d]
+
+ * RUNSON:
+ updated
+ [a72930d6e615]
+
+ * TODO:
+ updated
+ [4a51bd458390]
+
+ * sudo.pod:
+ remove author's email addr. people should mail sudo-bugs
+ [9b6bbdb3a6d9]
+
+ * INSTALL:
+ fix version
+ [246274c6c8af]
+
+ * README, check.c, compat.h, config.h.in, configure.in, dce_pwent.c,
+ find_path.c, getspwuid.c, getwd.c, goodpath.c, ins_2001.h,
+ ins_classic.h, ins_csops.h, ins_goons.h, insults.h, interfaces.c,
+ logging.c, options.h, parse.c, parse.lex, parse.yacc,
+ pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, sudo_setenv.c,
+ testsudoers.c, tgetpass.c, utime.c, version.h, visudo.c:
+ ++version
+ [f532ff4ee766]
+
+ * RUNSON:
+ updated
+ [62d5c71358b5]
+
+ * INSTALL, Makefile.in:
+ ++version
+ [1a7c7628edfc]
+
+ * CHANGES:
+ updated fort 1.5.4
+ [7e4873508c99]
+
+ * check.c:
+ exit(1) if user enters no passwd
+ [f382c0e35e4e]
+
+ * BUGS:
+ ++version
+ [fab6a867ab67]
+
+ * parse.c:
+ commands can start with ./* not just /* -- fixes a serious security
+ hole.
+ [244d2fe35ee3]
+
+1997-12-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ Don't set the tty variable to NULL when we lack a tty, leave it as
+ "unknown".
+ [193b26daba03]
+
+1997-11-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sample.sudoers:
+ fix usage of (username) in conjunction with , and !
+ [7ae68607f68f]
+
+ * visudo.c:
+ catch the case where the user is not in the passwd file
+ [31650258deb0]
+
+ * tgetpass.c:
+ use fileno(input) + 1 instead of getdtablesize() as the nfds arg to
+ select(2)
+ [60ab2d9a9ee8]
+
+ * sudo.c:
+ define tty global to an initial value to avoid dumping core in
+ logging functions when passwd file is unavailable.
+ [77056c7bc908]
+
+ * sudo.c:
+ do the set_perms(PERM_USER, sudo_mode) after we have gotten the
+ passwd entry
+ [1fdb8e579a5a]
+
+ * sudo.pod:
+ talk about problem of ALL
+ [1cd1905c9f6f]
+
+1997-10-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * README:
+ new web location
+ [d24dc26f6da5]
+
+ * INSTALL:
+ fdesc bug is fixed in Open/Net BSD
+ [7d4d81b08ac3]
+
+ * HISTORY:
+ updates from Nieusma
+ [3a43769a1b78]
+
+1997-10-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * dce_pwent.c:
+ move compat.h after the system includes
+ [5ea43a5968ac]
+
+1997-08-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ save errno from being clobbered by wait(). From Theo
+ [f2d1c48cd592]
+
+1997-05-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat.h:
+ fix an occurence of setresuid -> setreuid (typo)
+ [394de35c9b1c]
+
+1997-03-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * install-sh:
+ check for path to strip
+ [2b7ef824bd55]
+
+1997-01-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ deal with maxfilelen < 0 case
+ [f0af095178d7]
+
+ * OPTIONS:
+ fixed descriptin
+ [629f60bd4b5f]
+
+1996-12-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ correct error message if mode/owner wrong and not statable by owner
+ but is statable by root.
+ [cb631ce2e85e]
+
+1996-11-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.guess, config.sub:
+ autoconf 2.11
+ [f3cbe59e0756]
+
+1996-11-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, RUNSON, TODO:
+ sudo 1.5.3.
+ [2be3229b8626]
+
+1996-11-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc, sudo.h:
+ command_alias -> generic_alias
+ [c404ca8c510d] [SUDO_1_5_3]
+
+ * sample.sudoers:
+ added Runas_Alias example and fixed syntax errors
+ [c304053f4a8a]
+
+ * OPTIONS, options.h:
+ updated MAILSUBJECT
+ [18d1573fcd2a]
+
+ * logging.c:
+ added %h expansion
+ [a4bff9b284fd]
+
+ * INSTALL, Makefile.in, README, check.c, compat.h, config.h.in,
+ configure.in, dce_pwent.c, find_path.c, getspwuid.c, getwd.c,
+ goodpath.c, ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h,
+ insults.h, interfaces.c, logging.c, options.h, parse.c, parse.lex,
+ parse.yacc, pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h,
+ sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, version.h,
+ visudo.c:
+ ++version
+ [211ff20f956f]
+
+ * BUGS, emul/utime.h:
+ ++version
+ [cde5376579e3]
+
+ * sudoers.pod:
+ document Runas_Alias
+ [b1a58f28fb2c]
+
+ * visudo.pod:
+ q (uid) -> Q
+ [d256649a0e6b]
+
+ * visudo.c:
+ buffer oflow checking q (uit) -> Q if yyparse() fails drop into
+ whatnow
+ [1cb183d15626]
+
+ * parse.yacc:
+ add size params to sprintf
+ [9228f698921f]
+
+ * parse.lex:
+ allow trailing space after '\\' but before '\n'
+ [f51dbbf69fdf]
+
+ * find_path.c:
+ off by one error in path size check
+ [a6d75ccd7632]
+
+ * check.c:
+ sprintf paranoia
+ [3ffb12d198dd]
+
+1996-11-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc:
+ fixed more_aliases
+ [aab12f2a50af]
+
+ * visudo.c:
+ now warns if killed by signal ./
+ [310c186a0fd7]
+
+1996-11-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc:
+ fix Runas_Alias stuff Alias's in runas list now get expanded (but it
+ is gross)
+ [45590b83120f]
+
+ * sudo.c:
+ Can now deal with SUDOERS_UID == 0 and SUDOERS_MODE == 0400
+ [d53e01c14c58]
+
+ * parse.yacc:
+ add Runas_Alias support change FOO to FOO_ALIAS (ie: USER_ALIAS)
+ [7a4a040aae2d]
+
+ * parse.lex:
+ Add Runas_Alias and simplify a rule.
+ [6f794a769a37]
+
+ * parse.yacc:
+ always store User_Alias's since they can be used inside of a runas
+ list. Sigh. Really need a Runas_Alias instead.
+ [3bab058a873e]
+
+1996-10-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ deal with case where there is no sudoers file
+ [fa38b3bb244d]
+
+1996-10-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TROUBLESHOOTING:
+ added one
+ [e61346d06725]
+
+1996-10-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * HISTORY, testsudoers.c:
+ developement -> development
+ [4df55e293941]
+
+ * INSTALL:
+ added a note
+ [3845fb83dbc0]
+
+ * RUNSON:
+ for 1.5.2
+ [5489b7298942]
+
+ * CHANGES:
+ updated
+ [0741834929e6]
+
+1996-10-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * PORTING:
+ removed seteuid() notes
+ [1010a60f281d] [SUDO_1_5_2]
+
+1996-10-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat.h:
+ better seteuid() emulatino
+ [e807623b662c]
+
+ * configure.in:
+ added check for seteuid
+ [8cf9fabc6f4f]
+
+ * config.h.in:
+ added HAVE_SETEUID
+ [596db46aa828]
+
+1996-10-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ first stab at sequent support
+ [b85a7bfcac76]
+
+ * config.h.in:
+ added HAVE_SYS_SELECT_H
+ [93ecdd042463]
+
+ * compat.h:
+ sequent -> _SEQUENT_
+ [63a38b6da98c]
+
+ * compat.h:
+ added seteuid() macro for DYNIX
+ [695bd63c5ea6]
+
+ * tgetpass.c:
+ _AIX -> HAVE_SYS_SELECT_H
+ [b31221211bc2]
+
+1996-10-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * BUGS, INSTALL, Makefile.in, OPTIONS, README, config.h.in, logging.c,
+ parse.c, parse.lex, parse.yacc, putenv.c, strdup.c, sudo_setenv.c,
+ testsudoers.c, tgetpass.c, utime.c, visudo.c:
+ ++version
+ [8052992fd453]
+
+ * check.c, compat.h, dce_pwent.c, emul/utime.h, find_path.c,
+ getspwuid.c, getwd.c, goodpath.c, ins_2001.h, ins_classic.h,
+ ins_csops.h, ins_goons.h, insults.h, interfaces.c, options.h,
+ pathnames.h.in, version.h:
+ ++version
+ [f7ad15e1598a]
+
+ * sudo.pod:
+ added -H and SUDO_PS1
+ [bb965241e30c]
+
+ * configure.in:
+ use SUDO_FUNC_FNMATCH
+ [6a8350d85fb2]
+
+ * aclocal.m4:
+ added SUDO_FUNC_FNMATCH
+ [45b32c91c4ba]
+
+ * sudo.c:
+ added -H flag
+ [11ebc6872fd6]
+
+ * sudo.h:
+ added MODE_RESET_HOME /
+ [67a7f8bcbbd6]
+
+1996-10-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ mention OPIE
+ [5723515d5bbd]
+
+ * options.h:
+ SKEY -> OTP
+ [c1d268130bc4]
+
+ * configure.in:
+ added opie support
+ [123872b41b20]
+
+ * compat.h, config.h.in:
+ added HAVE_OPIE
+ [528c71afc1e5]
+
+ * check.c:
+ added HAVE_OPIE and changed to *_OTP_*
+ [4c62f5db872a]
+
+ * OPTIONS:
+ SKEY -> OTP
+ [bd858e5e9652]
+
+1996-10-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ moved fclose() in skey stuff.
+ [11f7dc8431a6]
+
+1996-10-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * putenv.c:
+ index -> strchr remove unnecesary stuff
+ [af2d05238062]
+
+ * check.c:
+ now call skeychallenge() to get challenge instead of making one up
+ ourselves. this way, we get extra goodies in the prompt.
+ [49b770d98d3a]
+
+1996-09-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ added one
+ [3f5149357e2a] [SUDO_1_5_1]
+
+ * parse.lex:
+ allow logins to start with a number (YUCK!)
+ [7ed7ef324741]
+
+1996-09-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TROUBLESHOOTING:
+ added soalris 2.5 vs 2.4 note
+ [16160a251aae]
+
+ * configure.in:
+ DUNIX doesn't need -lnsl
+ [be924cc322c3]
+
+ * CHANGES:
+ *** empty log message ***
+ [1b2937521981]
+
+ * check.c, compat.h, config.h.in, dce_pwent.c, find_path.c,
+ getspwuid.c, getwd.c, goodpath.c, ins_2001.h, ins_classic.h,
+ ins_csops.h, ins_goons.h, insults.h, interfaces.c, logging.c,
+ options.h, parse.c, parse.lex, parse.yacc, pathnames.h.in, putenv.c,
+ strdup.c, sudo.c, sudo.h, sudo_setenv.c, testsudoers.c, tgetpass.c,
+ utime.c, version.h, visudo.c:
+ courtesan
+ [5f203589bbfe]
+
+ * PORTING, README, RUNSON:
+ courtesan
+ [d72517f4937e]
+
+ * INSTALL, Makefile.in, TROUBLESHOOTING:
+ courtesan
+ [5c007e3c7a71]
+
+ * visudo.pod:
+ *** empty log message ***
+ [37ebe85bd4e1]
+
+ * sudo.pod, visudo.pod:
+ courtesan
+ [37f02e2130ea]
+
+1996-09-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * HISTORY:
+ added courtesan ./
+ [b01435226276]
+
+1996-09-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ added $SUDO_PROMPT support
+ [cb1fa72c093d]
+
+1996-09-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ print long skey challemged to stderr, not stdout
+ [750fc775b3b2]
+
+1996-09-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ updated for 1.5.1
+ [9b615f393057]
+
+ * emul/utime.h:
+ ++version
+ [a94de18deafb]
+
+1996-08-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * RUNSON:
+ updated for 1.5.1
+ [4092f20ab634]
+
+1996-08-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ use shost, not host for tgetpass
+ [6061c49ff9be]
+
+ * sudo.pod:
+ documented %u and %h
+ [6d2922d29897]
+
+ * OPTIONS:
+ documented %u and %h
+ [1a71da13a864]
+
+ * configure.in:
+ fixed typo
+ [1230dec2b062]
+
+ * INSTALL, Makefile.in, README, check.c, compat.h, config.h.in,
+ dce_pwent.c, find_path.c, getspwuid.c, getwd.c, goodpath.c,
+ ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h,
+ interfaces.c, logging.c, options.h, parse.c, parse.lex, parse.yacc,
+ pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, sudo_setenv.c,
+ testsudoers.c, tgetpass.c, utime.c, version.h, visudo.c:
+ ++version
+ [65ce8eabf77a]
+
+ * BUGS:
+ ++version
+ [afecab53aab7]
+
+1996-08-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, configure.in, version.h:
+ ++version
+ [fb3ff940d672]
+
+ * sudo.h:
+ new tgetpass() params
+ [9eccc5b0f8ae]
+
+ * check.c:
+ pass use and host to tgetpass
+ [c56d9d13c401]
+
+ * tgetpass.c:
+ added %u and %h escapes
+ [04ae775d3e5d]
+
+ * OPTIONS, check.c, options.h:
+ added NO_MESSAGE
+ [3927dad19057]
+
+ * configure.in:
+ added cray (unicos) support
+ [1122210c5fb1]
+
+1996-08-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * OPTIONS, options.h, sudo.c:
+ added SHELL_SETS_HOME
+ [0b26909b0929]
+
+1996-08-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ added note about "make install"
+ [7e56ea76d4b4]
+
+ * parse.yacc:
+ changed length/size params from int to size_t
+ [5654e5ceb1b3]
+
+ * OPTIONS:
+ now get CSOPS insults as well by default
+ [297323d0179a]
+
+ * insults.h:
+ use csops insults too by default
+ [07fafc136169]
+
+ * INSTALL, Makefile.in, README, config.h.in, configure.in, version.h:
+ version = 1.5
+ [4b8772b11e3b]
+
+ * sudo.c:
+ added runas_homedir
+ [b0e0d4417a15]
+
+ * TODO:
+ updated for 1.5
+ [66259df825d5]
+
+ * RUNSON:
+ updated for 1.5
+ [e08bc9ebfe95]
+
+ * CHANGES:
+ 1.5 release
+ [8c16942fea41]
+
+ * INSTALL:
+ added "upgrading" notes
+ [210d968964ff]
+
+1996-08-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ now do chmod and chown after edit of temp file and before rename
+ [de174e34faa7] [SUDO_1_5_0]
+
+1996-08-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ ++version added INSTALL.configure
+ [c9e9214f52ae]
+
+ * configure.in, version.h:
+ ++version
+ [5985abed3eb2]
+
+ * TROUBLESHOOTING:
+ *** empty log message ***
+ [d65c540ec52e]
+
+ * parse.yacc:
+ added missing cast
+ [e7247319a7d5]
+
+ * sudo.c:
+ sets $HOME to pw_dir of runas user
+ [d3f7f4d05752]
+
+ * sudo.pod:
+ document $HOME change
+ [854454d458c4]
+
+1996-08-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod:
+ fixed up some wording
+ [b0c8582f2c97]
+
+ * check.c, dce_pwent.c, find_path.c, getspwuid.c, getwd.c, goodpath.c,
+ interfaces.c, logging.c, parse.c, parse.lex, parse.yacc, putenv.c,
+ strdup.c, sudo.c, sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c,
+ visudo.c:
+ ++version
+ [748be723fd8b]
+
+ * compat.h, ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h,
+ insults.h, options.h, pathnames.h.in, sudo.h:
+ ++version
+ [acdf8b1b2a1b]
+
+ * emul/utime.h:
+ ++version
+ [b3f35298ab8d]
+
+ * sudo.h:
+ name nad type changes
+ [db24ab3da141]
+
+ * testsudoers.c:
+ now works with new sudo
+ [379346c42cc2]
+
+ * parse.yacc:
+ fixed some XXX
+ [f5fe4c990052]
+
+ * parse.yacc:
+ some variable name changes + comment headers for functions.
+ [3dc3bd9aa73d]
+
+ * tgetpass.c:
+ added extra paren's to make compilers happy
+ [9e4968a34d56]
+
+ * sudo.c:
+ *** empty log message ***
+ [70c924c1ed69]
+
+ * parse.c:
+ now uses init_parser() if not in sudoers and tries "list" or
+ "validate" scold but don't be nasty.
+ [c0d8fb3f8c9e]
+
+ * TROUBLESHOOTING:
+ now can use upper case login names
+ [c772fffcefe5]
+
+ * visudo.c:
+ now uses init_parser()
+ [b9efae7243fd]
+
+ * INSTALL, README:
+ updated
+ [27dc8283fdc8]
+
+ * PORTING:
+ added info about PASSWORD_TIMEOUT
+ [980e15d892f8]
+
+ * INSTALL.configure:
+ Initial revision
+ [8292e89a08d3]
+
+ * BUGS:
+ fixed a bug ,
+ [c6e46f5624f9]
+
+ * parse.yacc:
+ now dynamically allocates memory for the stacks -- no more
+ overflows!
+ [8615c35b6ad3]
+
+ * sudo.pod:
+ -l now explands command aliases
+ [39f45605935d]
+
+ * parse.yacc:
+ hacks to expand command aliases for `sudo -l'
+ [e4eb752608f9]
+
+ * sudo.c:
+ remove $ENV and $BASH_ENV (dangerous in ksh, posix sh, and bash)
+ [01327ca5084b]
+
+ * sudo.h:
+ added struct command_alias
+ [dd2f32764082]
+
+ * sudo.pod:
+ fixed a bug
+ [e708ff08d2eb]
+
+ * lsearch.c:
+ in compar() key should be first arg
+ [fc14c3fa62ee]
+
+1996-08-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * BUGS:
+ fixed some bugs
+ [639dfe425bd5]
+
+ * parse.yacc:
+ can now deal with upcase HOST and USER names
+ [c6aa7bcfb00d]
+
+ * sudo.c:
+ don't yell too loudly at non-sudoers if they do "sudo -l"
+ [4ef146128d89]
+
+ * sudo.pod:
+ fixed thinko
+ [830f2f0f22e7]
+
+ * parse.c:
+ fix comment
+ [d20ce9e17ddc]
+
+1996-08-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c, parse.yacc:
+ added support for new `sudo -l' stuff
+ [7dceaef3c733]
+
+ * sudo.c:
+ now uses list_matches()
+ [293364821b61]
+
+ * sudo.h:
+ added struct sudo_match
+ [b2684179d179]
+
+ * configure.in:
+ now more -lgnumalloc
+ [4f8ae42617d8]
+
+1996-08-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * install-sh:
+ added more paths for chown and whoami
+ [6e685a19426c]
+
+1996-07-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ typo
+ [3adfa01c04bc]
+
+1996-07-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aclocal.m4:
+ fixed DUNIX check for shadow pw
+ [c25324bcd27b]
+
+ * tgetpass.c:
+ now only turn off echo if it is already on. this fixes a race when
+ you use sudo in a pipelin
+ [28388c2de21c]
+
+ * INSTALL:
+ updated
+ [b45ac9366b7e]
+
+ * configure.in:
+ changed "test -z $foo && do_this" to if; then construct
+ [2183c4426bca]
+
+1996-07-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ added missing defines of SHADOW_TYPE
+ [be89ea68a7f3]
+
+1996-07-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ protect AUTH_CRYPT_OLDCRYPT and AUTH_CRYPT_C1CRYPT since they are
+ only in dunix 4.x
+ [1e7c1c677263]
+
+ * getspwuid.c:
+ added AUTH_CRYPT_C1CRYPT support
+ [88d6b0058b20]
+
+ * parse.c:
+ no longer return VALIDATE_NOT_OK if there was a runas that didn't
+ match. Now we can have runas stuff on more than one line.
+ [52b68920d7b7]
+
+ * getspwuid.c, sudo.c, tgetpass.c:
+ use SHADOW_TYPE instead of HAVE_C2_SECURITY
+ [cf401dfcbc06]
+
+ * configure.in:
+ got rid of HAVE_C2_SECURITY SHADOW_TYPE is always defined to
+ something
+ [c7a233c4dd93]
+
+ * config.h.in:
+ removed HAVE_C2_SECURITY added SPW_BSD
+ [8314405e9754]
+
+ * compat.h:
+ use SHADOW_TYPE instead of HAVE_C2_SECURITY
+ [6f94870df17f]
+
+ * check.c:
+ SHADOW_TYPE is always defined so just against its value
+ [72c69a55d02f]
+
+ * aclocal.m4:
+ added SUDO_CHECK_SHADOW_DUNIX
+ [ef025ae9d496]
+
+1996-07-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ * -> ?* in one example added another instance of (runas) and one of
+ NOPASSWD:
+ [d74fe1dcbe7d]
+
+1996-07-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ added back check for config.cache from other host type
+ [0ba87871f585]
+
+ * parse.lex:
+ removed an instance of \"
+ [1e008d3709f6]
+
+ * sample.sudoers:
+ added an example
+ [dbfcf68ee330]
+
+ * sudoers.pod:
+ updated wrt new wildcard matching
+ [193fa44a475b]
+
+ * configure.in:
+ new check for shadow passwords if we don't know anything
+ [67465df7dc9a]
+
+ * aclocal.m4:
+ new SUDO_CHECK_SHADOW_GENERIC
+ [3563b16a41b8]
+
+ * configure.in:
+ added back check for -lsocket (oops)
+ [a80882ee1cb6]
+
+ * configure.in:
+ better (working) check for shadow passwd type if we know to use C2.
+ [3cdd2a59a641]
+
+ * configure.in:
+ now uses AC_CANONICAL_HOST to figure out os type
+ [80db7fe6e704]
+
+ * Makefile.in:
+ added config.{guess,sub}
+ [c6be7e3ca384]
+
+ * aclocal.m4:
+ removed unused stuff to figure out os type
+ [c9a0f3b57123]
+
+ * config.sub:
+ added openbsd
+ [bfc6bfec3668]
+
+ * config.sub:
+ Initial revision
+ [e6e06ce0d17d]
+
+ * config.guess:
+ Initial revision
+ [99dd06f79199]
+
+ * testsudoers.c:
+ don't call fnmatch() with FNM_PATHNAME flag unless it can only be a
+ pathname. need to check against sudoers_args even if user_args is
+ nil
+ [66e6cf77f5d6]
+
+ * parse.c:
+ don't call fnmatch() with FNM_PATHNAME flag unless it can only be a
+ pathname need to check against sudoers_args even if user_args is nil
+ [74374df17311]
+
+1996-07-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ added support for AUTH_CRYPT_OLDCRYPT w/ DUNIX C2
+ [cbb00261c415]
+
+ * testsudoers.c:
+ now takes command line args and uses cmnd_args
+ [f0c2fd35a527]
+
+ * parse.lex:
+ fill_args was adding an extra leading space
+ [692fc999b2e8]
+
+1996-07-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ fixed dummy command_matches()
+ [93d9543db6e2]
+
+ * parse.yacc:
+ fixed prototype
+ [7b0addfbd429]
+
+ * sudo.h:
+ added cmnd_args
+ [8f47c4ae65ef]
+
+ * parse.yacc:
+ now uses flat args string
+ [016e65877da3]
+
+ * parse.c, parse.lex:
+ now uses flat arg string
+ [5b5f2e3f4c09]
+
+ * visudo.c:
+ added cmnd_args def
+ [876867134775]
+
+ * sudo.c:
+ now sets cmnd_args global
+ [e6fee70cb59b]
+
+ * logging.c:
+ cmnd_args is now exported from sudo.[ch]
+ [7a9cd36e356f]
+
+1996-07-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc:
+ can't rely on cmnd_matches as much as I thought -- added some $$
+ stuff back in to prevent namespace pollution problems.
+ [3c45fedb5af3]
+
+ * parse.yacc:
+ Simplified parse rules wrt runas and NOPASSWD (more consistent).
+ [e6d838c8a4c7]
+
+1996-07-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.lex:
+ NOPASSWD may now have blanks before the ':' '(' only starts a
+ 'runas' if in the initial state to avoid collision with command args
+ [c5c01172f499]
+
+ * configure.in:
+ added checks for specific shadow passwd schemes
+ [b7e3d1f7b84f]
+
+ * aclocal.m4:
+ added routines to check for specific shadow passwd types
+ [e5e1d19960a6]
+
+1996-07-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ added support for ncr boxen
+ [bea9dc5aae7f]
+
+ * aclocal.m4:
+ added support for detecting ncr boxen
+ [8653a158a924]
+
+1996-07-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ added sinix support
+ [5de2b2173ee1]
+
+1996-07-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TROUBLESHOOTING:
+ added info about "config.cache from other other" error.
+ [845b10198e0b]
+
+ * aclocal.m4:
+ now makes sure you don't have a config.cache file from another OS
+ [4fe32571c021]
+
+ * configure.in:
+ now sets $LIBS when needed to configure links with libs when doing
+ tests hpux10 now uses SPW_SECUREWARE for C2 added check for
+ bigcrypt(3) if SPW_SECUREWARE
+ [2df6b8ca538f]
+
+ * getspwuid.c:
+ fixed typo
+ [fe1cb1d792d6]
+
+ * tgetpass.c:
+ now include stuff for SPW_SECUREWARE to get AUTH_MAX_PASSWD_LENGTH
+ [f71138372c07]
+
+ * getspwuid.c:
+ no more SPW_HPUX10
+ [cfdeb18bc16b]
+
+ * config.h.in:
+ no more SPW_HPUX10 added HAVE_BIGCRYPT
+ [00d296479a61]
+
+ * compat.h:
+ now uses AUTH_MAX_PASSWD_LENGTH if SPW_SECUREWARE
+ [6c6d9e680417]
+
+ * check.c:
+ SPW_SECUREWARE now uses bigcrypt
+ [be71fc66690f]
+
+1996-07-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sample.sudoers:
+ fixed 2 syntax errors
+ [45eee19ef4ac]
+
+ * sudoers:
+ root may now run ALL as ALL
+ [1b54c6b9b212]
+
+1996-07-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * interfaces.c:
+ fixed a typo/thinko that broke BSD's with sa_len
+ [603438360126]
+
+1996-07-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c, configure.in:
+ updated AFS support
+ [e572eb8d177a]
+
+ * TROUBLESHOOTING:
+ added entry about /usr/ucb/cc
+ [025b353aa9d3]
+
+ * INSTALL:
+ prep no longer holds gcc binaries
+ [8b0942958049]
+
+ * INSTALL:
+ updated AFS note
+ [7af6efd5abe4]
+
+ * Makefile.in:
+ added @AFS_LIBS@
+ [97b6fe6ad7d6]
+
+ * compat.h:
+ AFS allows long passwords
+ [5fb17122c302]
+
+ * testsudoers.c:
+ fixed -u user support
+ [b1a0c1648639]
+
+ * parse.c:
+ sudo -v now groks VALIDATE_OK_NOPASS
+ [74fc03fffe7e]
+
+ * parse.yacc:
+ fixed no_passwd vs. runas_matched
+ [549a9b791a6a]
+
+ * TROUBLESHOOTING:
+ took out stuff about NFS-mounting since it is no longer an issue
+ [d95ab7fbbc61]
+
+ * INSTALL:
+ added --with-libraries > --with-libpath --with-incpath
+ [d5d15a7a0f4c]
+
+ * parse.yacc:
+ was setting runas_matches to -1 in wrong place
+ [db2b1deb8d33]
+
+ * check.c:
+ removed usersec.h which is not present in new AFS versions
+ [618b016dd17f]
+
+ * tgetpass.c:
+ now deals with timeout <= 0
+ [ba53a1257255]
+
+ * OPTIONS:
+ updated
+ [75093bd8fdca]
+
+ * configure.in:
+ BSD/OS >= 2.0 now uses shlicc instead of just gcc
+ [ff6dbf7825c2]
+
+ * sudo.c:
+ fixed backwards compatibility with sudo 1.4 sudoers mode for root
+ readable/writable filesystems
+ [2694ed627221]
+
+ * Makefile.in:
+ now gives INSTALL -c flag
+ [63db055a2fd1]
+
+ * parse.yacc:
+ slightly simpler initialization of no_passwd and runas_matches
+ [463a1b5fa323]
+
+ * testsudoers.c:
+ added -u username support
+ [38b072fcd6b3]
+
+ * configure.in:
+ improved --with-libraries support
+ [047dbc5f0af2]
+
+1996-07-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ added --with-incpath, --with-libpath, --with-libraries
+ [20f20d6c718c]
+
+ * parse.yacc:
+ now initializes some fields that weren't getting set to -1 pretty
+ gross -- need a rewrite.
+ [021c160390c6]
+
+1996-06-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * alloca.c:
+ removed emacs'isms
+ [9d4ec2efe057]
+
+ * configure.in:
+ no longer add -lPW to *_LIBS since we include alloca.c
+ [a626d1bbea80]
+
+ * config.h.in:
+ added HAVE_ALLOCA_H
+ [15491e2a6cff]
+
+ * Makefile.in:
+ added alloca.c
+ [0400f25e1fe4]
+
+ * alloca.c:
+ Initial revision
+ [06d033aa4882]
+
+ * configure.in:
+ ++version
+ [f52c0fb98f90]
+
+1996-06-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ now set uid to 1 instead of nobody for PERM_SUDOERS since nobody is
+ not always set to a valid uid.
+ [c2669f77704d]
+
+ * OPTIONS:
+ fixed entry for SUDO_MODE
+ [d7272f6035b8]
+
+ * sudo.c:
+ Fixed NFS-mounted sudoers file under solaris both uid *and* gid were
+ being set to -2. Now beat NFS to the punch and set uid to "nobody"
+ ourselves, preserving group 0 to read sudoers.
+ [b1fbc5dd1e34]
+
+ * parse.c:
+ moved set_perms(PERM_ROOT) to be before yyparse()
+ [7619d8080735]
+
+ * logging.c:
+ fixed a typo
+ [318acc48cde0]
+
+ * configure.in:
+ no longer need AC_PROG_INSTALL
+ [de01b1336dc8]
+
+ * Makefile.in:
+ always use install-sh to avoid install(1)'s that use get{pw,gr}nam
+ [ea2351986406]
+
+ * INSTALL:
+ make clean -> make distclean
+ [704a98e8ba10]
+
+1996-06-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc:
+ removed some unnecsary if's
+ [f00db6508132]
+
+ * Makefile.in, version.h:
+ ++version
+ [bdb6740b24c8]
+
+ * parse.c, testsudoers.c:
+ now includes netgroup.h
+ [93f5a06352bc]
+
+ * interfaces.c:
+ removed cats of ioctl to int since they didn't shut up -Wall
+ [83e9f912cd7a]
+
+ * interfaces.c:
+ explicately cast ioctl() to int since it it not always declared
+ [2ff9294e469e]
+
+ * sudo.h:
+ added declarations for yyparse() and yylex()
+ [6071321ab771]
+
+ * parse.yacc:
+ fixed an occurence of '==' -> '='
+ [2c46d2e11d57]
+
+ * config.h.in, configure.in:
+ added check for netgroup.h
+ [73403050f4e3]
+
+ * sudo.c:
+ fixed 2 compiler warnings
+ [680929b0bd97]
+
+ * sudo.c:
+ SHELL_IF_NO_ARGS caused core dump since NewArg[cv] weren't being
+ initialized
+ [18707ecd07c2]
+
+1996-06-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod:
+ fixed a typo
+ [e4b5c12aa130]
+
+1996-06-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc:
+ fixed a formatting thingie
+ [c79327b6f19b]
+
+ * parse.c, parse.yacc:
+ fixed -u support with multiple user lists on a line
+ [e4d1066adca2]
+
+ * configure.in:
+ unixware needs -lgen
+ [b5bf9bca63cc]
+
+ * README:
+ updated ftp location
+ [b25a033f7921]
+
+ * sudoers.pod:
+ add net_addr/netmask support
+ [674e83516d1e]
+
+ * sample.sudoers:
+ added net_addr/mask example
+ [774878e89b28]
+
+ * parse.c, parse.lex:
+ added support for net_addr/netmask
+ [e33de27325d8]
+
+1996-06-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ ^ -> !
+ [1a084950d6ef]
+
+1996-06-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * RUNSON:
+ updated for 1.4.3
+ [c82019025d09]
+
+ * CHANGES:
+ udpated for 1.4.3
+ [ceaa81adb8f0]
+
+ * BUGS, TODO, TROUBLESHOOTING:
+ updated
+ [ff94fae4b853]
+
+ * sample.sudoers:
+ updated with examples of new stuff
+ [99d0b4cb4c9c]
+
+ * INSTALL, README:
+ ++version
+ [b763b80fe836]
+
+ * sudoers.pod:
+ updated wrt -u and NOPASSWD
+ [0b5b722ea0f4]
+
+ * sudo.pod:
+ updated wrt -u and CAVEATS
+ [71d5d53b5d18]
+
+1996-06-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ fixed usage()
+ [114c7d09b550]
+
+ * parse.lex:
+ now use :foo: character classes (makes no diff for generated lexer)
+ [7b0aeb737a02]
+
+1996-06-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ fixed LONG_SKEY_PROMPT stuff
+ [0efe78b4bdda]
+
+1996-06-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ fixed a comment
+ [3d289017104b]
+
+ * lsearch.c:
+ make more like NetBSD one -- now compiles w/o warnings
+ [932206296a54]
+
+ * emul/search.h:
+ fixed decls of lsearch()
+ [c58cf4584c45]
+
+ * config.h.in, configure.in, getspwuid.c:
+ added SPW_HPUX10
+ [d74e5eaa5f17]
+
+ * check.c:
+ hpux 10 uses bigcrypt() if C2
+ [359eb63f4021]
+
+1996-06-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ now always uses fnmatch to match args
+ [a9d91f35256a]
+
+ * tgetpass.c:
+ back to using stdio instead of raw i/o since that caused some
+ problems
+ [e7ce2bc92974]
+
+1996-05-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ now give usage warning if use -l,-v,-k with args
+ [6b48180c4fea]
+
+1996-05-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ NewArgc is now set to 1 for -l, -v, -k
+ [7497cb1416a8]
+
+ * sudo.c:
+ now sets sudoers to correct group if mode is 0400
+ [484c43d99718]
+
+ * install-sh:
+ updated to version used by inn and bind
+ [28683ad8725a]
+
+ * configure.in:
+ now uses -lgnumalloc if it exists
+ [3651ca4415a2]
+
+ * Makefile.in:
+ "make install" now sets uid/gid and mode on sudoers if it exists
+ [1f5216191ae9]
+
+ * sudo.c:
+ rmeoved debugging statements
+ [aeda278e2c26]
+
+ * parse.yacc:
+ added a missing free()
+ [592c9482a159]
+
+ * sudo.c:
+ now uses user_gid instead of getegid (which was wrong anyway) to set
+ SUDO_GID Now sets command line args in SUDO_COMMAND envariabled
+ (logging.c depends on args being in the environment)
+ [9f5328a3b942]
+
+ * logging.c:
+ now uses SUDO_COMMAND envariable to get command args rather than
+ building it up again.
+ [7f8edc5bccb7]
+
+ * parse.c:
+ now uses user_gid
+ [4b9303ae45fe]
+
+ * sudo.c:
+ fixed off by one error in allocation NewArgv
+ [921ea1a4e7c6]
+
+ * parse.c:
+ in sudoers, 'command ""' now means command with no args
+ [a5273648ace2]
+
+ * configure.in:
+ added check for fnmatch(3) and fnmatch.h
+ [258916a7866f]
+
+ * config.h.in:
+ added HAVE_FNMATCH
+ [b9860d361e93]
+
+ * Makefile.in:
+ replaced wildcat.* with fnmatch.*
+ [03ad9ee21a1c]
+
+ * testsudoers.c:
+ now uses fnmatch()
+ [5a7f7de987a9]
+
+1996-05-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ now uses fnmatch() instead of wildmat a trailing star (*) by itself
+ now matches multiple args added support for wildcards in the
+ pathname in sudoers
+ [1f7fb950b868]
+
+1996-05-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * fnmatch.c:
+ now includes compat.h and config.h
+ [090206b95cf8]
+
+ * config.h.in:
+ added HAVE_FNMATCH_H
+ [90eb42150173]
+
+ * configure.in:
+ now checks for alloca() (if needed by bison or dce) and links with
+ -lPW if it contains alloca() and libv and compiler do not.
+ [cfa2b3cef49a]
+
+ * emul/fnmatch.h, fnmatch.3, fnmatch.c:
+ Initial revision
+ [20b1f762a32a]
+
+1996-04-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ now fixes mode on sudoers if set to 0400 to aid in upgrade
+ [d4bdfd521820]
+
+1996-04-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ fixed pod2man usage
+ [5adf2ec77b27]
+
+ * Makefile.in, configure.in, version.h:
+ ++version
+ [b4029de876d0]
+
+ * testsudoers.c, visudo.c:
+ runas_user is now initialized to "root"
+ [8537d97bff39]
+
+ * sudo.h:
+ removed PERM_FULL_ROOT
+ [241f8bbf647f]
+
+ * sudo.c:
+ runas_user defaults to "root" so no more need to PERM_RUNAS
+ [fc0c0dfc72ba]
+
+ * parse.c:
+ will now only running commands as root if there was no runas list
+ (or if root is in the runas list)
+ [40c587666c81]
+
+ * logging.c:
+ now logs "USER=%s"
+ [b733504c87fd]
+
+ * parse.yacc:
+ runas_matches is now set to false if we get a negative match
+ [5495b150b300]
+
+ * parse.lex:
+ make #uid work + some minor cleanup
+ [07851bbce03a]
+
+ * sample.sudoers:
+ added support for NOPASSWD and "runas" from garp@opustel.com /
+ [7a9c67b51fa5]
+
+ * visudo.c:
+ added support for "runas" from garp@opustel.com replaced
+ SUDOERS_OWNER with SUDOERS_UID, SUDOERS_GID added support for
+ SUDOERS_MODE
+ [e714209b9885]
+
+ * testsudoers.c:
+ added support for "runas" from garp@opustel.com
+ [b837f856da10]
+
+ * sudo.h:
+ added support for NO_PASSWD and runas from garp@opustel.com replaced
+ SUDOERS_OWNER with SUDOERS_UID and SUDOERS_GID and added support fro
+ SUDOERS_MODE
+ [cea6f26679b7]
+
+ * sudo.c:
+ added support for NO_PASSWD and runas from garp@opustel.com replaced
+ SUDOERS_OWNER with SUDOERS_UID and SUDOERS_GID and added support fro
+ SUDOERS_MODE
+ [61b5434237c5]
+
+ * parse.yacc:
+ added support for NO_PASSWD and runas from garp@opustel.com
+ [72ebd3056f22]
+
+ * parse.c, parse.lex:
+ added support for NO_PASSWD and runas from garp@opustel.com
+ [fef6dbdd114d]
+
+ * logging.c:
+ added support for SUDOERS_WRONG_MODE and "runas"
+ [e794efc2b443]
+
+ * configure.in:
+ added --with-CC only link with -lshadow on linux (with shadow pw) if
+ libc lacks getspnam()
+ [3ecf4ae21002]
+
+ * OPTIONS, options.h:
+ removed NO_PASSWD since it is not possible to do this in the sudoers
+ file itself. Replaced SUDOERS_OWNER with SUDOERS_UID and
+ SUDOERS_GID. Added SUDOERS_MODE.
+ [2eaa4891ef48]
+
+ * Makefile.in:
+ now uses SUDOERS_UID and SUDOERS_GID
+ [8d615f0fdb2a]
+
+1996-04-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ added --with-CC
+ [a1b8286a81b8]
+
+1996-04-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.lex:
+ added double quote support
+ [a5e4fc7e3a2b]
+
+ * sudoers.pod:
+ documented double quoting
+ [c6ea47969a44]
+
+1996-04-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * mkinstalldirs:
+ Initial revision
+ [dcb86d65ad8f]
+
+ * check.c:
+ fixed some indentation
+ [4d1c5ab8072b]
+
+ * Makefile.in:
+ fixed a typo
+ [0d27eebc7227]
+
+ * Makefile.in:
+ added install-dirs .
+ [f499b99b8be7]
+
+1996-04-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * dce_pwent.c:
+ new version from "Jeff A. Earickson" <jaearick@colby.edu>
+ [422481be5fbd]
+
+1996-04-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ $CSOPS -> $with_csops (whoops, missed one)
+ [b04c6948130e]
+
+ * BUGS:
+ updated
+ [c4d5713e227d]
+
+ * parse.lex:
+ FQHOST now has same constraints as non-FQHOST
+ [e1c3bf2381d1]
+
+ * INSTALL:
+ added note about OS's w/ shadow passwords turned on by default
+ [166257f43be4]
+
+1996-04-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ fixed a typo
+ [e5c3e2e9a359]
+
+ * configure.in:
+ added support for --without-THING sanitized shadow pw situtation by
+ adding support for
+ --without-C2
+ [65dc6bf64cce]
+
+ * tgetpass.c:
+ fixed a typo wrt placement of an end paren
+ [a8780f818231]
+
+ * check.c:
+ was closing an fd that may not have been opened
+ [760271c7bdc9]
+
+1996-03-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * OPTIONS, options.h, sudo.c:
+ added NO_PASSWD
+ [28ff1dc93d7a]
+
+1996-03-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ now always use shadow pw on some arches
+ [069161ccffda]
+
+1996-03-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ added pyramid support
+ [a0eb57a3a531]
+
+ * configure.in:
+ no longer check for C2 if alternate passwd method is used no longer
+ check for some libs twice
+ [2d0c3c902b40]
+
+ * parse.yacc:
+ moved fqdn stuff into parse.lex (FQHOST)
+ [d9c9abd481d8]
+
+ * parse.lex:
+ added FQHOST rules
+ [4a1695acff6d]
+
+ * tgetpass.c:
+ now define TCSASOFT in necesary
+ [3fac2e21c9ab]
+
+ * tgetpass.c:
+ now uses read/write instead of stdio string goop to avoid problems
+ with select(2)
+ [67fd174e518c]
+
+ * OPTIONS, find_path.c, options.h:
+ -DNO_DOT_PATH -> -DIGNORE_DOT_PATH
+ [d05ba5100d28]
+
+1996-03-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ added note about no shadow auto-detect if using alternate auth
+ schemes
+ [b425592232a3]
+
+ * configure.in:
+ don't check for C2 if AFS or DCE (unless they said --with-C2)
+ [61342962171a]
+
+ * testsudoers.c:
+ now groks shost
+ [85dda17303f6]
+
+ * OPTIONS, find_path.c, options.h:
+ added NO_DOT_PATH
+ [c261ca1fb196]
+
+1996-03-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * find_path.c:
+ checkdot now works correctly
+ [3bc4835bb3e9]
+
+1996-03-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ can't have DCE and C2 passwords both...
+ [fb9a8ab7ca66]
+
+1996-03-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc, sudo.c, sudo.h, visudo.c:
+ now uses shost even if not FQDN
+ [87f7498b3a1f]
+
+ * configure.in:
+ now looks for skey in /usr/lib and doesn't require libskey to be in
+ /usr/local/lib just because skey.h is (for my netbsd box :-)
+ [ceb1763e37d2]
+
+ * aclocal.m4, config.h.in, pathnames.h.in:
+ _SUDO_PATH_ -> _CONFIG_PATH_
+ [84d97ad13d75]
+
+ * aclocal.m4, sudo.pod:
+ /var/run/.odus -> /var/run/sudo
+ [922da220b8f5]
+
+ * pathnames.h.in:
+ now uses _SUDO_PATH_TIMEDIR
+ [5ecab0155fdf]
+
+ * OPTIONS:
+ udpated FQDN
+ [361b6f7440c0]
+
+ * aclocal.m4, configure.in:
+ added SUDO_TIMEDIR
+ [368c95c8c950]
+
+ * config.h.in:
+ added _SUDO_PATH_TIMEDIR
+ [3879864d808c]
+
+ * sudo.pod:
+ updated wrt /var/run/sudo
+ [9e14f2a429d3]
+
+ * sudo.c, sudo.h:
+ added support for shost if FQDN
+ [51a3f51a09a1]
+
+ * parse.yacc, visudo.c:
+ now uses shost if FQDN
+ [d19da2e92b42]
+
+ * check.c:
+ Now use skeylookup() instead off skeychallenge()
+ [4c7438bb2ae0]
+
+1996-02-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ mail_argv should not contain ALERTMAIL as it includes "-t"
+ [67ffaaa8f843]
+
+1996-02-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, Makefile.in, README, configure.in, version.h:
+ ++version
+ [e08fd4a809fc]
+
+ * compat.h:
+ added more _PASSWD_LEN stuff -- now uses PASS_MAX too
+ [2f20c3153689]
+
+ * tgetpass.c:
+ now includes limits.h moved _PASSWD_LEN -> compat.h
+ [b1ca3cafdacc]
+
+1996-02-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL, README:
+ ++version
+ [3eacf32803f5]
+
+ * Makefile.in:
+ ++versoin
+ [3b91c317630a]
+
+ * Makefile.in:
+ fixed a typo
+ [3661ac4a7803]
+
+ * configure.in:
+ ++version
+ [60e842973745]
+
+1996-02-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * RUNSON:
+ updated
+ [def2c3c24195]
+
+ * CHANGES:
+ done for 1.4.1 (I hope)
+ [2ab543769a40]
+
+ * sudoers.pod:
+ added info on wildcards
+ [ce3bd41bc063]
+
+ * sample.sudoers:
+ added wildcard example
+ [762feb0577bd]
+
+ * Makefile.in:
+ now uses *.pod to build *.man and *.cat & *.html
+ [3ec14962028b]
+
+ * configure.in:
+ addedSUDO_PROG_BSHELL !ll
+ [3c80b320bf16]
+
+ * visudo.pod:
+ fixed up some formatting
+ [12166c434526]
+
+ * sudoers.pod:
+ redid section describing sample sudoers stuff
+ [b8065cceec71]
+
+ * sudo.pod:
+ fixed some formatting
+ [aa9a681add0f]
+
+ * getspwuid.c:
+ now treats "" as bourne shell
+ [30194a72ad56]
+
+ * Makefile.in:
+ TESTOBJS nwo includes wildmat.o
+ [86cc6500f84d]
+
+ * testsudoers.c:
+ now works with NewArg[cv]
+ [2f72674ce942]
+
+ * sudo.c:
+ removed an XXX (fixed it in getspwuid.c)
+ [e791ee0d1a68]
+
+ * aclocal.m4:
+ added check for bourne shell
+ [a2fd51676b8a]
+
+ * pathnames.h.in:
+ added _PATH_BSHELL
+ [e7c10011d47b]
+
+ * config.h.in:
+ added _SUDO_PATH_BSHELL
+ [6a1182898de9]
+
+1996-02-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ unixware vi returns 256 instead of 0
+ [234ffc7c6786]
+
+ * INSTALL:
+ added Linux note
+ [5f85efcd2b58]
+
+ * logging.c:
+ fixed up some XXX's. file log format now looks a little more like
+ real syslog(3) format.
+ [6df55707bfc3]
+
+ * README, TROUBLESHOOTING:
+ updated wrt lex/flex
+ [eb787d69156b]
+
+ * Makefile.in:
+ commented out rule to build lex.yy.c from parse.lex since we ship
+ with a pre-flex'd parser
+ [7507e2ce4a95]
+
+ * parse.c, parse.yacc, visudo.c:
+ path_matches -> command_matches
+ [0bd469424f86]
+
+ * logging.c:
+ eliminated some strcat()'s
+ [9878a79bc374]
+
+ * configure.in:
+ no longer checks for lex/flex (now assumes flex)
+ [a086ccc73798]
+
+ * configure.in:
+ now checks for $kerb_dir_candidate/krb.h instead of just
+ kerb_dir_candidate
+ [9133bc3c5208]
+
+1996-02-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc:
+ now use a 'hook' expression instead of an iffy one :-)
+ [9560df01b8c0]
+
+1996-02-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ now works with new sudo arg stuff
+ [310a0d43ddad]
+
+ * parse.yacc:
+ fixed dereferencing deadbeef
+ [474ef8a8006b]
+
+ * sudo.c:
+ changed an occurrence of Argv to NewArgv
+ [205b012b7691]
+
+ * parse.lex:
+ took out support for quoted commands since there is no need...
+ [5c5036d353b1]
+
+ * parse.c:
+ fixed a typo in a for() loop
+ [7e8d5283c43b]
+
+ * logging.c:
+ protected against dereferencing rogue pointers
+ [56debd517717]
+
+ * sudo.c:
+ now uses NewArgv amd NewArgc so cmnd_aegs is no longer needed this
+ also allows us to eliminate some kludges in parse_args() and
+ eliminate superfluous code.
+ [5122f66ad150]
+
+ * logging.c:
+ no longer uses cmnd_args, now uses NewArgv instead.
+ [abddd23cf068]
+
+ * sudo.h:
+ added struct sudo_command, NewArgc, and NewArgv removed cmnd_args
+ (no longer used)
+ [78410984fb05]
+
+ * Makefile.in:
+ added wildmat.c to SRCS & SUDOBJS
+ [3800efb41794]
+
+ * parse.yacc:
+ COMMAND is now a struct containing the path and args
+ [5c32822c5b94]
+
+ * parse.lex:
+ replaced append() with fill_cmnd() and fill_args. command args from
+ a sudoers entry are now stored in an arrary for easy matching.
+ [a981d7f4eb0d]
+
+ * parse.c:
+ command line args from sudoers file are now in an array like ones
+ passed in from the command line
+ [1d9e37e84519]
+
+1996-02-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ wildwat stuff now works
+ [49d16488531f]
+
+1996-01-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * version.h:
+ ++version
+ [53e55463ef89]
+
+ * Makefile.in:
+ ++version added wildmat.*
+ [0508297a4711]
+
+1996-01-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.lex:
+ added support for quoted commands (w/ or w/o args)
+ [b9a637155673]
+
+1996-01-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.pod, visudo.pod:
+ cleaned up formatting
+ [4591d4195437]
+
+ * sudo.pod, visudo.pod:
+ Initial revision
+ [7564a8242750]
+
+1996-01-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudoers.pod:
+ looks reasonable, could be mroe readable
+ [a5be2d19d9e0]
+
+ * sudoers.pod:
+ Initial revision
+ [957888be31a6]
+
+1996-01-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * RUNSON:
+ updated
+ [633743aa924b]
+
+ * OPTIONS:
+ updated NO_ROOT_SUDO entry
+ [f1c15b1dec9e]
+
+1996-01-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * RUNSON:
+ *** empty log message ***
+ [5b63de579ff7] [SUDO_1_4_0]
+
+ * sudo.c:
+ fixed SECURE_PATH
+ [6002889f606d]
+
+ * RUNSON:
+ udpa`ted for 1.4
+ [6014a8592815]
+
+ * configure.in:
+ AIX aixcrypt.exp now uses $(srcdir)
+ [b0d57674fef4]
+
+ * TROUBLESHOOTING:
+ added entry for anal ansi compilers
+ [4193cec1c6b1]
+
+1996-01-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ added info on libcrypt_i for SCO
+ [575497d56698]
+
+ * TODO:
+ *** empty log message ***
+ [d0aaf67b9913]
+
+ * sample.sudoers:
+ added comments
+ [a7773f7eda8d]
+
+ * TODO:
+ 1.4 release
+ [1dade29e9fd9]
+
+ * CHANGES:
+ ++version
+ [67241be40780]
+
+ * INSTALL, OPTIONS, README, config.h.in, configure.in:
+ ++version
+ [2e0a37897f68]
+
+ * BUGS:
+ ++version and fixed ISC
+ [78963f01a0e3]
+
+ * check.c, compat.h, dce_pwent.c, find_path.c, getspwuid.c, getwd.c,
+ goodpath.c, ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h,
+ insults.h, logging.c, options.h, pathnames.h.in, putenv.c, strdup.c,
+ sudo.c, sudo.h, sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c,
+ visudo.c:
+ ++version
+ [b6227f29b3d9]
+
+ * interfaces.c:
+ added STUB_LOAD_INTERFACES ++version
+ [d8150a3fd577]
+
+ * Makefile.in, emul/utime.h, parse.c, parse.lex, parse.yacc,
+ version.h:
+ ++version
+ [da9e90e69bdc]
+
+ * PORTING:
+ added info about fd_set in tgetpass added info on interfaces.c
+ [a39902febd17]
+
+1996-01-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * dce_pwent.c:
+ added sudo header
+ [fc0f2c48682e]
+
+ * tgetpass.c:
+ fixed a typo
+ [43d40b72ee8f]
+
+ * Makefile.in:
+ tgetpass.o is now only linked in with sudo (not visudo)
+ [7407c5ff11f8]
+
+1996-01-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * BUGS, INSTALL, Makefile.in, OPTIONS, README, config.h.in,
+ configure.in:
+ ++version
+ [9b82ad805d6b]
+
+ * emul/utime.h:
+ added copyright notice
+ [4380f16cd075]
+
+ * check.c, compat.h, find_path.c, getspwuid.c, getwd.c, goodpath.c,
+ ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h,
+ interfaces.c, logging.c, options.h, parse.c, parse.lex, parse.yacc,
+ pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, sudo_setenv.c,
+ testsudoers.c, tgetpass.c, utime.c, version.h, visudo.c:
+ ++version
+ [32717fdb5d05]
+
+ * tgetpass.c:
+ minor cleanup and now includes sys/bsdtypes for svr4'ish boxen
+ [326864428da2]
+
+ * configure.in:
+ ISC now gets -lcrypt now check for sys/bsdtypes.h
+ [e064799c054b]
+
+ * config.h.in:
+ added check for sys/bsdtypes.h
+ [9adb9533c363]
+
+1996-01-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc:
+ removed debugging stuff (setting freed ptr to NULL)
+ [02fe8eec63a0]
+
+ * TROUBLESHOOTING:
+ added 2 entries
+ [02884e2733e2]
+
+ * Makefile.in:
+ added FAQ
+ [074d8dfcf28d]
+
+ * TROUBLESHOOTING:
+ added section on syslog
+ [e6bc02a22b86]
+
+ * configure.in:
+ added AC_ISC_POSIX for better ISC support
+ [8436b3e12af2]
+
+ * config.h.in:
+ fixed typo
+ [f1b3922babf4]
+
+ * config.h.in:
+ added define for _POSIX_SOURCE
+ [ded6d92b34f9]
+
+1996-01-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ fixed check for lsearch()
+ [75baa5bc28a3]
+
+1995-12-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * interfaces.c:
+ fixed for AIX now deal if num_interfaces == 0 (should not happen)
+ [ae450e859227]
+
+1995-12-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ now only define HAVE_LSEARCH if there is a corresponding search.h
+ [8ce645c5d17f]
+
+ * interfaces.c:
+ works on ISC again
+ [ccac920d424c]
+
+1995-12-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ now define HAVE_LSEARCH if we find lsearch() in libcompat
+ [7343e4313a87]
+
+ * lsearch.c:
+ char * -> const char *
+ [1c0b11c2300a]
+
+ * configure.in:
+ now looks in -lcompat for lsearch()
+ [a1cc1d6fcd09]
+
+ * Makefile.in:
+ remove sudo.core visudo.core for clan target
+ [b523456a85df]
+
+ * aclocal.m4:
+ added UID_MAX support in check for MAX_UID_T_LEN
+ [7ab262b1173f]
+
+ * Makefile.in:
+ fixed another occurence of sudo_getpwuid.*
+ [fb5809c07da2]
+
+ * Makefile.in, getspwuid.c:
+ sudo_getpwuid.c -> getspwuid.c
+ [875f2ef808b4]
+
+ * configure.in:
+ moved the "echo"
+ [ad7b8f966076]
+
+ * BUGS, CHANGES, INSTALL, Makefile.in, OPTIONS, README, check.c,
+ compat.h, config.h.in, configure.in, find_path.c, getspwuid.c,
+ getwd.c, goodpath.c, ins_2001.h, ins_classic.h, ins_csops.h,
+ ins_goons.h, insults.h, interfaces.c, logging.c, options.h, parse.c,
+ parse.lex, parse.yacc, pathnames.h.in, putenv.c, strdup.c, sudo.c,
+ sudo.h, sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c,
+ version.h, visudo.c:
+ ++version
+ [ee57c6410ffa]
+
+ * testsudoers.c:
+ added group support
+ [54d8097df8bd]
+
+ * sample.sudoers:
+ added group entry
+ [50994d31fd49]
+
+ * sudoers.man:
+ documented group support
+ [0a16707f8fed]
+
+ * parse.c, parse.lex, parse.yacc, visudo.c:
+ added group support
+ [427218c879c8]
+
+1995-12-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ tkfile was too short and overflowed the kerberos realm
+ [53823a1ff5af]
+
+1995-12-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ now copy command args directly from Argv
+ [77408278b6fd]
+
+ * sudo.c:
+ replaced code to copy cmnd_args so that is does not use realloc
+ since most realloc()'s really stink
+ [b29a0ff73fb6]
+
+1995-12-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ syslog() fixed in hpux 10.01
+ [2648e6f0cdb0]
+
+1995-12-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ AC_CHECK_LIB() now sets SUDO_LIBS (and VISUDO_LIBS if appropriate)
+ [8f108b8d8711]
+
+ * configure.in:
+ better error if cannot find skey incs or libs
+ [5887662ee9d3]
+
+ * aclocal.m4:
+ now use a temp file for determining max len of uid_t in string form.
+ the old hacky way broke on netbsd
+ [b68f470fa9f8]
+
+ * sudo.c:
+ added set of parens and a space
+ [8a3d4826d022]
+
+1995-12-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * dce_pwent.c:
+ fixes from Jeff Earickson <jaearick@colby.edu> ,
+ [bde0f0b756ec]
+
+ * check.c:
+ modified a comment
+ [e2a97f1afbbe]
+
+ * Makefile.in:
+ fixed up testsudoers target
+ [d39c4e7bb609]
+
+ * configure.in:
+ DCE changes from Jeff Earickson <jaearick@colby.edu> LIBS ->
+ SUDO_LIBS and VISUDO_LIBS LDFLAGS -> SUDO_FDFLAGS and VISUDO_LDFLAGS
+ [da7a1c433828]
+
+ * Makefile.in:
+ LIBS -> SUDO_LIBS , VISUDO_LIBS LDFLAGS -> SUDO_LDFLAGS,
+ VISUDO_LDFLAGS
+ [4b69503e8487]
+
+1995-11-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ fix for C2 on hpux 10 now uses -linet if it exists
+ [8d300112263d]
+
+ * check.c:
+ LONG_SKEY_PROMPT is less of a klusge /
+ [dcc144abaac3]
+
+ * configure.in:
+ fixed typos w/ dce stuff
+ [f7dfd6d4e149]
+
+ * Makefile.in:
+ added dce_pwent.c
+ [79047acdc516]
+
+1995-11-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ amended section on combining authentication mechanisms
+ [dc5138c7c716]
+
+ * PORTING:
+ minor updates for 1.3.6
+ [fe80c13bd994]
+
+ * TROUBLESHOOTING:
+ added 2 more entries
+ [c7201439a0f5]
+
+ * BUGS:
+ updated for 1.3.6
+ [979b414d2a2d]
+
+ * README:
+ overhauled
+ [3af8b60eb594]
+
+ * INSTALL:
+ rewrote for sudo 1.3.6
+ [b16027b9c726]
+
+ * TROUBLESHOOTING:
+ added 3 entries
+ [934c9ee3f153]
+
+1995-11-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * find_path.c, getspwuid.c, sudo.c:
+ added explict casts for strdup since many includes don't prototype
+ it. gag me.
+ [3e19a11f2fcc]
+
+ * sudo.h:
+ removed prototype for sudo_getpwuid() since convex C compiler choked
+ on it.
+ [c3ea74ca67b0]
+
+ * sudo.c:
+ added prototype for sudo_getpwuid()
+ [4a8e3cdc2b98]
+
+ * lsearch.c:
+ now compiles on strict ANSI compilers
+ [3ce5d72d0b08]
+
+ * check.c:
+ added LONG_SKEY_PROMPT support
+ [48a18b8a2332]
+
+ * Makefile.in:
+ added extra $'s for make to eat up, yum.
+ [2995b214e12b]
+
+ * OPTIONS, options.h:
+ added LONG_SKEY_PROMPT
+ [f23ae799b5a4]
+
+1995-11-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ s/key support now works with normal s/key as well as logdaemon
+ [d67573f523bf]
+
+ * OPTIONS, options.h:
+ added SKEY_ONLY
+ [bbf07654e0de]
+
+ * compat.h:
+ set _PASSWD_LEN to 256 for any of KERB4, DCE, SKEY
+ [205895b96a36]
+
+ * INSTALL:
+ added DCE note added more AIX notes
+ [6345403b3522]
+
+ * sudo.c:
+ now include pthread.h for DCE support
+ [6fe02865f679]
+
+ * check.c:
+ dce_pwent() is ok after all .,
+ [d26a8746a55d]
+
+ * logging.c:
+ now uses SYSLOG() macro that equates to either syslog() or
+ syslog_wrapper
+ [42ac4cff8045]
+
+ * dce_pwent.c:
+ minor formatting changes. renamed check() to somthing less generic
+ [71859f217be1]
+
+ * check.c, logging.c, parse.yacc, sudo.c, sudo.h, testsudoers.c,
+ visudo.c:
+ now uses user_pw_ent and simple macros to get at the contents
+ [f4cbf3e7145a]
+
+1995-11-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ simpler dec unix C2 support
+ [86bc8f75250e]
+
+ * getspwuid.c:
+ now sets crypt_type for DEC unix C2
+ [99aeadd18266]
+
+1995-11-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ added csops paths for skey
+ [b8ca672e2117]
+
+ * getspwuid.c:
+ now includes string.h for strdup() prototype
+ [3605259c3620]
+
+ * getspwuid.c:
+ fixed a few typos
+ [46c97e4ea417]
+
+ * check.c:
+ now includes skey.h
+ [11e611ce1b61]
+
+ * getspwuid.c:
+ fixed up comments
+ [223dac56f0c8]
+
+ * check.c:
+ moved a lot of the shadow passwd crap to sudo_getpwuid()
+ [97d8887fb7d3]
+
+ * sudo.c:
+ now uses sudo_pw_ent
+ [d014dadbef48]
+
+ * testsudoers.c:
+ now uses sudo_pw_ent
+ [d92936ed7e34]
+
+ * visudo.c:
+ now sets sudo_pw_ent
+ [ff75cdfcf8b3]
+
+ * getspwuid.c:
+ Initial revision
+ [6deb6df9d7bc]
+
+ * tgetpass.c:
+ moved dce stuff into compat.h
+ [1124284396e7]
+
+ * logging.c, sudo.h:
+ now uses sudo_pw_ent
+ [404ff20a5067]
+
+ * Makefile.in:
+ added sudo_getpwuid.c
+ [6666d0644512]
+
+ * compat.h:
+ added dce support
+ [3c3b36a7ce0e]
+
+ * parse.yacc:
+ now uses sudo_pw_ent
+ [9f5e8d11bd68]
+
+1995-11-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ fixed exempt_group stuff for OS's that don't put base gid in group
+ vector
+ [003f153bd396]
+
+ * check.c:
+ S/Key support now works with sunos4 shadow passwords
+ [1eb64a5efff1]
+
+ * Makefile.in:
+ fixed clean rule
+ [5695a2c62816]
+
+ * config.h.in, configure.in:
+ added DCE support
+ [f53c766c1947]
+
+ * tgetpass.c:
+ DCE & KERB support
+ [904cf436506a]
+
+ * check.c:
+ first stab at dce support
+ [aea5ca07b1e3]
+
+ * dce_pwent.c:
+ now smells like sudo
+ [8b3d609b49cd]
+
+ * dce_pwent.c:
+ Initial revision
+ [b573555f2399]
+
+ * check.c:
+ skey'd sudo now works w/ normal password as well
+ [8d038f9f6e94]
+
+1995-11-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, OPTIONS, check.c, compat.h, config.h.in, find_path.c,
+ getwd.c, goodpath.c, ins_2001.h, ins_classic.h, ins_csops.h,
+ ins_goons.h, insults.h, interfaces.c, logging.c, options.h, parse.c,
+ parse.lex, parse.yacc, pathnames.h.in, putenv.c, strdup.c, sudo.c,
+ sudo.h, sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c,
+ version.h, visudo.c:
+ updated version number
+ [ba7e346d7904]
+
+ * README:
+ updated to reflect version change
+ [1d15cf1d8cc8]
+
+ * configure.in:
+ --with options now line up ++version
+ [08ebf625fbca]
+
+ * sudo.h:
+ removed unecesary S/Key stuff
+ [68188cba90af]
+
+ * configure.in:
+ fixed S/Key support
+ [f6d9cbc36618]
+
+ * Makefile.in:
+ -I stuff now goes in CPPFLAGS
+ [7b8e53c5b046]
+
+ * check.c:
+ fixed SKey support
+ [52c1a5cf4435]
+
+ * README:
+ updated version
+ [bed6498a10bb]
+
+ * OPTIONS:
+ fixed description of EXEMPTGROUP
+ [cfeead55edc2]
+
+ * sudo.c:
+ more people use _RLD_ than just alphas...
+ [6a3c7090a6f6]
+
+ * Makefile.in:
+ replaced $man_prefix with $mandir
+ [dc4b36a550e2]
+
+ * configure.in:
+ fixed a typo
+ [a38a4acddcaf]
+
+ * Makefile.in:
+ now use more GNU'ish dir names
+ [c5498391a520]
+
+ * configure.in:
+ now set *dir correctly (can override from command line)
+ [523ff98fd438]
+
+ * sudo.c:
+ now deal with situations where we getwd() fails
+ [88a9e61dccbb]
+
+1995-11-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ added etc_dir, bin_dir, sbin_dir
+ [75fd08d92842]
+
+ * configure.in:
+ added sbin_dir
+ [3cb318c0d8d1]
+
+ * Makefile.in:
+ now ship a flex-generated lex.yy.c
+ [4d083ed70dce]
+
+ * Makefile.in:
+ now sets _PATH_SUDO_SUDOERS, _PATH_SUDO_STMP, SUDOERS_OWNER
+ [4d51dc9c3780]
+
+ * pathnames.h.in:
+ _PATH_SUDO_SUDOERS & _PATH_SUDO_STMP are now overridden via Makefile
+ [773fd163d52f]
+
+ * options.h:
+ no more error for redefining SUDOERS_OWNER
+ [4ba336644c6a]
+
+ * OPTIONS:
+ expanded SUDOERS_OWNER section
+ [12fae405759e]
+
+1995-11-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ now warn if chown(2) failed
+ [d0d1db6e3a1f]
+
+ * logging.c:
+ better default warning for NO_SUDOERS_FILE
+ [5260b458ac64]
+
+ * sudo.c:
+ added missing set_perms() no more cryptic message if the sudoers
+ file is zero length, now just give a parse error
+ [b81ea724838a]
+
+ * logging.c:
+ better diagnostics if NO_SUDOERS_FILE
+ [877e878663c5]
+
+ * sudo.c:
+ check_sudoers() now catches sudoers files that are not readable (but
+ are stat'able).
+ [fea05663b3de]
+
+1995-11-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ now add -D__STDC__ for convex cc (not gcc)
+ [c80fc53ff51b]
+
+ * configure.in:
+ MAN_PREFIX -> man_prefix now sets prefix and exec_prefix
+ [fe238226a057]
+
+ * Makefile.in:
+ now uses exec_prefix & prefix from configure
+ [f62fca5f56bd]
+
+ * find_path.c, getwd.c, goodpath.c, interfaces.c, logging.c, parse.c,
+ parse.lex, parse.yacc, sudo.c, sudo.h, sudo_setenv.c, tgetpass.c,
+ utime.c, visudo.c:
+ options.h is now <> instead of "" so shadow build trees can have a
+ custom copy of options.h
+ [e6782676099c]
+
+ * check.c:
+ user_is_exempt() is no longer a hack, it now uses getgrnam()
+ [287f8d5356f7]
+
+ * options.h:
+ EXEMPTGROUP is now "sudo"
+ [61487304dbe1]
+
+ * configure.in:
+ MAN_POSTINSTALL now contains a leading space
+ [eaad4ac34012]
+
+ * Makefile.in:
+ removed leading tab if @MAN_POSTINSTALL@ not defined now removes
+ testsudoers in clean:
+ [e01711baceb8]
+
+ * tgetpass.c:
+ includes pwd.h to get _PASSWD_LEN definition
+ [8ec174f263f1]
+
+1995-10-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ unset the KRB_CONF envariable if using kerberos so we don't get
+ spoofed into using a bogus server
+ [2561a0274fca]
+
+1995-09-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc:
+ now explicately initialize match[] tp be FALSE
+ [0e45e5c47766]
+
+1995-09-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ removed unused variable now passes -Wall
+ [3452508bc16d]
+
+ * parse.yacc:
+ yyerror and dumpaliases are now void's now passes -Wall
+ [2769dfb51993]
+
+ * parse.lex:
+ added prototype for yyerror
+ [1f3f0c1b4ab4]
+
+ * check.c, logging.c, parse.c:
+ now passes -Wall
+ [eab57e5e81d2]
+
+ * interfaces.c:
+ rmeoved unused cruft now passes -Wall
+ [7a47e1866f4b]
+
+ * Makefile.in:
+ fixed headers that moved to emul dir
+ [e680c1e5049b]
+
+ * logging.c:
+ fixed deref of nil pointer if no args
+ [973b9bea432f]
+
+1995-09-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * OPTIONS:
+ added a caveat to FQDN section
+ [dcf6e2a5fff4]
+
+1995-09-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ more $srcdir support for install targets
+ [f6eac78436dd]
+
+ * find_path.c, interfaces.c, parse.c, parse.lex, parse.yacc, putenv.c,
+ strdup.c, sudo.c, sudo_setenv.c, testsudoers.c, visudo.c:
+ don't include malloc.h if we include stdlib.h
+ [fca2ff307cd8]
+
+ * parse.yacc:
+ local search.h now lives in emul
+ [51c458904424]
+
+ * check.c, utime.c:
+ local utime.h now lives in emul dir
+ [f92fc9e8c8de]
+
+ * lsearch.c:
+ local search.h now lives in emul
+ [579efc407439]
+
+ * Makefile.in:
+ added support for building in other than the sourcedir
+ [2ab53a43f7d4]
+
+1995-09-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * OPTIONS:
+ annotated CSOPS_INSULTS option
+ [9e57d45a0afa]
+
+ * TROUBLESHOOTING:
+ updated shadow passwords blurb
+ [39b785bc7253]
+
+ * sudo.c:
+ if SHELL_IF_NO_ARGS is set, "sudo -- foo" now runs a shell and
+ passes along foo as the arguments
+ [a91077aa8fc5]
+
+1995-09-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.lex:
+ collapsed pathname and dir sections into one -- its now less
+ expensive
+ [89caa03bec25]
+
+ * parse.lex:
+ fixed spacing quoting [,:\\=] now works correctly append() and
+ fill() now take args to make the above work
+ [09d023d9ef3a]
+
+ * sudo.c:
+ fixed a typo that caused commands with no tty on fd 0 but a tty on
+ fd 1 to erroneously have "none" as their tty
+ [07d2c0e7977c]
+
+1995-09-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ timestampfile is now a global static removed decl of timestampfile
+ in remove_timestamp since we can just use the global one
+ [f0cbdc6aab1c]
+
+ * check.c:
+ created touch() to update timestamps added USE_TTY_TICKETS support
+ (bit of a kludge)
+ [cee1dd0318f8]
+
+ * compat.h:
+ added _S_IFDIR and S_ISDIR
+ [b4a51cc9628e]
+
+ * OPTIONS, options.h:
+ added USE_TTY_TICKETS
+ [b4e22f81f25e]
+
+ * parse.yacc:
+ removed const from casts for lsearch() & lfind() to placate irix 4.x
+ C compiler
+ [5003081f76ea]
+
+1995-09-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ now only strip '/dev/' off of a tty if it starts with '/dev/'
+ [7f62bcd24039]
+
+ * pathnames.h.in:
+ added _PATH_DEV
+ [6375f44d1910]
+
+ * configure.in:
+ AC_HAVE_HEADERS -> AC_CHECK_HEADERS now check for tcgetattr only if
+ have termios.h
+ [9c60391235fd]
+
+ * tgetpass.c:
+ fixed incorrect #ifdef termio uses "unsigned short" not int for
+ c_?flag
+ [d032e6a29845]
+
+ * parse.lex, parse.yacc:
+ fixed a spelling error
+ [cad6a944c7b1]
+
+ * Makefile.in:
+ fixed typo
+ [204a65403e7c]
+
+1995-09-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ fixed a comment
+ [268f760e57ad]
+
+ * parse.yacc:
+ added dotcat() to cat 2 strings w/ a dot effeciently now that we
+ dynamically allocate strings they need to be free()'d
+ [ec2e2152f415]
+
+ * parse.lex:
+ dynamically allocates space for strings
+ [d10ac3533d66]
+
+ * sudo.h:
+ no more MAXCOMMANDLENGTH
+ [e2e1219bff8a]
+
+ * sudo.h:
+ added decl of tty
+ [c8ae81303ee5]
+
+ * logging.c, sudo.c:
+ moved tty stuff into sudo.c
+ [e028abefeb07]
+
+1995-09-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ fixed a logic bug. Was denying a command if user gave command line
+ args but there were none in the sudoers file which is wrong.
+ [7489a99b8e8a]
+
+ * sudo.h:
+ MAXCOMMMANDLEN dropped down to 1K
+ [38ef54ba290b]
+
+ * parse.lex:
+ return foo; -> return(foo);
+ [0e8be1b57001]
+
+ * parse.yacc:
+ fixed netgr_matches() prototype
+ [e69f15910464]
+
+ * parse.lex:
+ added support for escaping "termination" characters
+ [8bd4ef50f35c]
+
+ * parse.c:
+ buf is now of size MAXPATHLEN+1 since it never holds command args
+ [2ce4b763058c]
+
+ * sudo.c:
+ fixed comments
+ [0c74a3d2ebb0]
+
+ * goodpath.c:
+ fixed negation problem (doh!)
+ [782814e3a2d1]
+
+ * parse.yacc:
+ fixed 2nd parameter to lfind()
+ [63d7b1623c08]
+
+ * parse.lex:
+ now do bounds checking in fill() and append()
+ [54381b563251]
+
+ * sudo.c:
+ include netdb.h as we should added a missing void cast added
+ SHELL_IF_NO_ARGS support now use realloc() properly. would fail if
+ realloc actually moved the string instead of shrinking it
+ [897ccdec9c06]
+
+ * sample.sudoers:
+ updated with examples of new features
+ [9b3ed00e8aa6]
+
+ * goodpath.c:
+ now set errno to EACCES if not a regular file or not executable
+ [2d069548a5ea]
+
+ * find_path.c:
+ if given a fully-qualified or relative path we now check it with
+ sudo_goodpath() and error out with the appropriate error message if
+ the file does not exist or is not executable
+ [590f89dd8dec]
+
+ * emul/search.h, lsearch.c:
+ now use correct args for lfind
+ [fccdcdbf020e]
+
+ * logging.c:
+ added a comment
+ [fab9f49708ea]
+
+ * insults.h:
+ added in CSOps insults
+ [ad8eb1862adc]
+
+ * ins_csops.h:
+ Initial revision
+ [de5a475ec018]
+
+ * tgetpass.c:
+ added RCS id
+ [c3ffd550a482]
+
+ * sudo.h:
+ increased MAXCOMMANDLENGTH to 8k HAVE_GETCWD -> HAVE_GETWD
+ [aba25c90d08a]
+
+ * OPTIONS:
+ added CLASSIC_INSULTS, CSOPS_INSULTS, SHELL_IF_NO_ARGS
+ [e27bd62e9ccf]
+
+ * sudo.c:
+ fixed -k load_interfaces() now gets called if FQDN is set
+ -p now works with -s
+ [07ca2a34bae8]
+
+ * parse.c:
+ don't try to stat() "pseudo commands" like "validate"
+ [75527045984b]
+
+ * options.h:
+ added CLASSIC_INSULTS added CSOPS_INSULTS added SHELL_IF_NO_ARGS
+ [07b157a0eafd]
+
+ * configure.in:
+ added SecurID support added other insults to --with-csops
+ [6c992ceb244c]
+
+ * config.h.in:
+ added HAVE_SECURID
+ [e734ff617fe8]
+
+ * Makefile.in:
+ added clobber target added ins_csops.h now gets CFLAGS from
+ configure
+ [d1e29c7cec25]
+
+ * aclocal.m4:
+ relaxed SUDO_FULL_VOID
+ [fb4084f27406]
+
+ * visudo.c:
+ function comment blocks are now in same style as rest of code
+ [04a2931354c5]
+
+ * testsudoers.c:
+ added support for command line args in /etc/sudoers
+ [bfe4e1bcc655]
+
+ * sudoers.man:
+ updated to have command args in the sudoers file
+ [1cd34355e9ea]
+
+ * sudo.man:
+ added -s and -- flags added SHELL to ENVIRONMENT VARIABLES section
+ [930b48023b68]
+
+1995-08-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc:
+ PATH renamed to COMMAND
+ [4e109a6de3cd]
+
+ * parse.lex:
+ it is now a parse error for directories to have args attached to
+ them
+ [2ab10a146b54]
+
+ * logging.c:
+ now say command args if telling user to buzz off
+ [933de26ded8b]
+
+ * sudo.c:
+ -s no longer indicates end of args sped up loading on cmnd_args in
+ load_cmnd()
+ [eac99a4da862]
+
+ * parse.c:
+ removed an unreachable statement
+ [634302623c49]
+
+ * parse.lex:
+ made more efficient by pulling out the terminators when in GOTCMND
+ state and making them their own rule
+ [80798f1e1166]
+
+1995-08-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.h:
+ removed MAXLOGLEN since it is no longer used
+ [102824196b71]
+
+ * parse.lex:
+ now allows command args
+ [d29dfa1e5254]
+
+ * parse.c:
+ now groks command arguments
+ [6c414cb7f105]
+
+ * logging.c:
+ now sets tty correctly when piped input
+ [de46a30c0406]
+
+ * sudo.c:
+ fixed loading of cmnd_args (was including command name too)
+ [15319a425ea6]
+
+ * logging.c:
+ fixed a core dump due to incorrect if construct
+ [582363c7d7fa]
+
+1995-08-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ only add -lsun is irix < 5 don't look for -lnsl or -lsocket if irix
+ [da591fe9b931]
+
+ * aclocal.m4:
+ fixed check for ISC
+ [52e59f2082a7]
+
+ * sudo.c:
+ now sets cmnd_args used by log_error() and that will be used by the
+ parse to check against command args
+ [c6804389723b]
+
+ * sudo.h:
+ added cmnd_args
+ [4d00446b4a8d]
+
+ * logging.c:
+ now dynamically allocate logline since we can guess at its size
+ [4bed8c8446aa]
+
+1995-08-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ cleaned up a bunch of unnecesary #ifdef's eliminated a buffer remove
+ "register" since the compiler knows more than I do now do a
+ "basename" of the tty
+ [3b1bbf0b3da1]
+
+1995-07-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ ++version
+ [5ce552f9a5f1]
+
+ * sudo.h:
+ added shell extern changed MODE_* to be bit masks to allow for
+ several options together
+ [06f9dc4f400c]
+
+ * sudo.c:
+ added -s (shell) option made MODE_* masks so we can do bitwise & and
+ | to see if multiple flags are set.
+ [01f8143010ad]
+
+ * check.c:
+ added securid support
+ [909e078005fe]
+
+1995-07-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ removed a bunch of unnecesary strncpy()'s and replaced with strcat()
+ [644506b57d61]
+
+1995-07-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, version.h:
+ ++version
+ [3cd6f1fbc3d9]
+
+1995-07-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc:
+ fixed free() of an uninitialized pointer (yuck)
+ [8c404ee502ee]
+
+ * testsudoers.c:
+ added netgr_matches
+ [e7c9fa2f774c]
+
+ * parse.c:
+ cleaned up netgr_matches
+ [8108f00b810e]
+
+1995-07-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * RUNSON:
+ updated for 1.3.4
+ [4741704310a1]
+
+1995-07-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ now installs sudoers.man -- really should clean this up though.
+ [455631d45a1d]
+
+ * Makefile.in:
+ added sudoers.cat and sudoers.man
+ [0bdedd6c7363]
+
+ * sudo.man:
+ pulled out stuff on the sudoers file format into a separate man page
+ [de215d999cb9]
+
+ * sudoers.man:
+ Initial revision
+ [f25eafbb7095]
+
+ * HISTORY:
+ fixed up my email address
+ [254fbf80be74]
+
+ * configure.in:
+ added checks for innetgr and getdomainname
+ [24a99cb7e97e]
+
+ * visudo.c:
+ added dummy netgr_matches function
+ [1841ff2c01da]
+
+ * parse.c:
+ added netgr_matches
+ [ec90db6a97b8]
+
+ * parse.lex, parse.yacc:
+ added NETGROUP support
+ [c9dd93e3bc4b]
+
+ * config.h.in:
+ added HAVE_INNETGR & HAVE_GETDOMAINNAME
+ [14abd494d875]
+
+1995-07-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ rewrote clean_env() that has rm_env() builtin
+ [55cb43818a95]
+
+1995-07-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ now cast uid to long in sprintf
+ [b549eea40aeb]
+
+ * OPTIONS:
+ added _INSULTS suffix to HAL & GOONS end
+ [ed620d0aad30]
+
+ * options.h:
+ added _INSULTS suffix to HAL & GOONS
+ [9f72e9b83afd]
+
+ * ins_2001.h, ins_classic.h, ins_goons.h, insults.h:
+ converted to new scheme of insult "unions" end
+ [2f6d2b412132]
+
+ * sudo.c:
+ now uses MAX_UID_T_LEN
+ [c1df79e0f389]
+
+ * configure.in:
+ added SUDO_UID_T_LEN !l
+ [195f0b9f5f84]
+
+ * config.h.in:
+ added MAX_UID_T_LEN
+ [73f42ae4f14d]
+
+ * check.c:
+ now use MAX_UID_T_LEN
+ [df9c063234cb]
+
+ * aclocal.m4:
+ added check for max len of uid_t fixed sco vs. isc check
+ [d558f36d2223]
+
+1995-07-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ corrected version
+ [828dd1571e86]
+
+ * configure.in:
+ added sco support
+ [af1e2f616638]
+
+ * aclocal.m4:
+ hack to check for sco
+ [549ab99a9a43]
+
+ * interfaces.c:
+ removed #include <net/route.h> since it was hosing some OS's
+ [ac78a7c04005]
+
+1995-07-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * find_path.c:
+ fixed prreadlink() prototype
+ [b380fe1f2b11]
+
+ * check.c:
+ added parens in #if's
+ [e96ade691b82]
+
+ * configure.in:
+ added SPW_ prefix
+ [a302683a1483]
+
+ * sudo.h:
+ moved SPW_* to config.h.in
+ [6b3be70e34cf]
+
+ * sudo.c:
+ added a set of parens
+ [8188d735d695]
+
+ * config.h.in:
+ added SPW_*
+ [5ead6371cf60]
+
+ * sudo.h:
+ added SPW_* reordered error codes
+ [dead25b4ed0a]
+
+ * check.c:
+ moved SPW_* to sudo.h
+ [ca51fb04caf4]
+
+1995-07-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ SPW_AUTH -> SPW_SECUREWARE
+ [6b512b2bc5dc]
+
+ * logging.c:
+ GLOBAL_NO_AUTH_ENT -> GLOBAL_NO_SPW_ENT
+ [defdd0944e2f]
+
+ * configure.in:
+ AUTH -> SECUREWARE
+ [d1f8a17001dd]
+
+ * check.c:
+ SPW_AUTH -> SPW_SECUREWARE
+ [af0e8d8b89b2]
+
+ * check.c:
+ now uses SHADOW_TYPE to make shadow pw support more readable and
+ modular. It's a start...
+ [8c2a59667014]
+
+ * configure.in:
+ added autodetection of shadow passwords
+ [85f81fa54b1b]
+
+ * sudo.c:
+ now uses SHADOW_TYPE define
+ [355e5dc09b07]
+
+ * config.h.in:
+ added SHADOW_TYPE which replaces SUNOS4 & __svr4__ defines
+ [c0c06e83e483]
+
+ * aclocal.m4:
+ added SUDO_CHECK_SHADOW
+ [464301301639]
+
+1995-07-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ define SVR4 for ISC define BROKEN_SYSLOG for hpux took out test for
+ memmove() since we dno longer use it...
+ [8aefa87d7d31]
+
+ * CHANGES:
+ updated
+ [ce97b3fd7182]
+
+ * logging.c:
+ added BROKEN_SYSLOG support
+ [a45c3bca36f6]
+
+ * config.h.in:
+ added BROKEN_SYSLOG
+ [6f6abf0a6268]
+
+ * check.c:
+ now only bitch it timestamp > time_now + 2 * timeout to allow for a
+ machine udpating its time from a server
+ [546bc8d35325]
+
+ * sudo.man:
+ added 2 security notes updated Nieusma's email addr
+ [616756c56977]
+
+ * lsearch.c:
+ changed a memmove() to memcpy() since we don't have to worry about
+ overlapping segments.
+ [30baa478526b]
+
+1995-07-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * interfaces.c:
+ cleanup up the loop when interfaces are groped in so that it is
+ readable
+ [1fa39446bd69]
+
+ * Makefile.in, version.h:
+ ++version
+ [b46bd2b1770f]
+
+1995-07-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ annotated 124-126
+ [b82a2b3ec7ce]
+
+1995-07-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ fixed permissions check on /tmp/.odus
+ [cc2431a65468]
+
+1995-07-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ fixed some comments
+ [8896d09b4fda]
+
+ * check.c:
+ now checks owner & mode of timedir also checks for bogus dates on
+ timestamp file
+ [a0fad5df5b0a]
+
+ * OPTIONS:
+ updated TIMEOUT info
+ [033cc22d9e04]
+
+ * logging.c, sudo.h:
+ added BAD_STAMPDIR and BAD_STAMPFILE
+ [31d9ce691101]
+
+ * compat.h:
+ added definition of S_IRWXU
+ [ff2dab091a9b]
+
+ * CHANGES:
+ updated
+ [a40df90284f1]
+
+1995-07-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * interfaces.c:
+ added #ifdef to make it compile on strange arches
+ [4a127f12afce]
+
+1995-07-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aclocal.m4:
+ fixed check for fulkl void impl.
+ [b6f2a4a361d8]
+
+ * check.c:
+ added mssing "static"
+ [520552f2772b]
+
+ * insults.h:
+ replaced #elif with #else #if constructs for ancient C compilers
+ [39ab2d365b57]
+
+ * INSTALL:
+ updated irix c2 & kerb5 info
+ [ae79b99b4905]
+
+ * configure.in:
+ added shadow pw support for irix
+ [632469d9c528]
+
+1995-07-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * BUGS, TODO:
+ updated
+ [2a96bb18ac30]
+
+ * CHANGES:
+ last changes for sudo 1.3.3
+ [c1c0cd1034b8]
+
+ * configure.in:
+ now calls SUDO_SOCK_SA_LEN
+ [14ea78159d45]
+
+ * config.h.in:
+ added HAVE_SA_LEN
+ [cc2a346aa905]
+
+ * aclocal.m4:
+ added SUDO_SOCK_SA_LEN
+ [456a2025644a]
+
+ * interfaces.c:
+ now works with ip implementations that use sa_len in sockaddr
+ [90be6e028077]
+
+ * INSTALL:
+ added note about buggy AIX compiler
+ [c0f6d427e4e4]
+
+ * interfaces.c:
+ now include sys/time.h for AIX
+ [2510858ab38b]
+
+1995-06-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ getcwd -> getwd
+ [66085ebca98e]
+
+ * interfaces.c:
+ now works for ISC and others. yay.
+ [f336d4ffc927]
+
+1995-06-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, version.h:
+ version++
+ [836cffc2078d]
+
+1995-06-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aclocal.m4:
+ fixed test for full void impl
+ [fb004107e7b9]
+
+ * sudo.c:
+ now check to see that st_dev is non-zero before assuming that we are
+ being spoofed
+ [1b0e1c30c506]
+
+1995-06-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aclocal.m4, configure.in:
+ SUDO_FUNC_UTIME_NULL -> AC_FUNC_UTIME_NULL
+ [4953379bfb01]
+
+1995-06-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * aclocal.m4:
+ fixed include file order for SUDO_FUNC_UTIME_POSIX
+ [ff64ab7df44f]
+
+ * logging.c:
+ added cast for ttyname()
+ [444f05f56758]
+
+ * configure.in:
+ fixed typo
+ [de068e748431]
+
+ * check.c:
+ now deal correctly with all known variation of utime() -- yippe
+ [b778a4195a89]
+
+ * configure.in:
+ added SUDO_FUNC_UTIME_POSIX
+ [cf635f2269d6]
+
+ * aclocal.m4:
+ added SUDO_FUNC_UTIME_NULL and SUDO_FUNC_UTIME_POSIX
+ [d79593be4b73]
+
+ * config.h.in:
+ added HAVE_UTIME_POSIX
+ [c67b4ac0dca5]
+
+ * check.c:
+ fixed a typo
+ [b14df5680f59]
+
+ * check.c:
+ no longer assume !HAVE_UTIME_NULL means old BSD utime()
+ [0aeaf4b2f38b]
+
+ * check.c:
+ fixed fascist C compiler warning
+ [c61ddf2f1f93]
+
+ * interfaces.c:
+ now set strioctl.ic_timout in STRSET() now initialize num_interfaces
+ to 0 (just to be anal)
+ [c54cc2ba0052]
+
+1995-06-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.h:
+ increaed MAXLOGLEN by MAXPATHLEN to account for ttyname
+ [74cf585a54fb]
+
+ * logging.c:
+ added tty logging
+ [e27d8dcfbd78]
+
+ * interfaces.c:
+ reworked the ISC code
+ [bcf57ce8ae69]
+
+ * Makefile.in, version.h:
+ updated version
+ [032941c9b94d]
+
+ * check.c:
+ now expect old-style utime(3) if utime() can't take NULL as an arg
+ [018dd4a73030]
+
+ * configure.in:
+ added check for utime.h
+ [0b76e8feb618]
+
+ * config.h.in:
+ added HAVE_UTIME_H
+ [62ee42feda46]
+
+ * Makefile.in:
+ added CPPFLAGS STATIC_FLAGS -> LDFLAGS
+ [fa3201d294e1]
+
+ * configure.in:
+ now search for kerb libs and includes
+ [cc332401e571]
+
+ * check.c:
+ added support for utime(2)'s that can't take a NULL parameter
+ [98797fedf69f]
+
+ * utime.c:
+ moved HAVE_UTIME_NULL stuff to update_timestamp() where t belongs
+ [6ce6d825fb44]
+
+ * configure.in:
+ added utime(s) stuff
+ [a2afb744403e]
+
+ * check.c:
+ now use utime()
+ [48902240a51e]
+
+ * config.h.in:
+ added HAVE_UTIME and HAVE_UTIME_NULL
+ [9a56ab65d4f4]
+
+1995-06-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * utime.c:
+ now use HAVE_UTIME_NULL
+ [e3944de09a92]
+
+ * emul/utime.h, utime.c:
+ Initial revision
+ [a2cbf2ef3427]
+
+ * check.c:
+ need to setuid(0) to make kerb4 stuff work.
+ [c6cfda4039d7]
+
+ * tgetpass.c:
+ no more special case for kerberos
+ [4a5c33145be9]
+
+ * config.h.in:
+ took out setreuid and setresuid stuff added kerb5 stuff (use kerb4
+ emulation)
+ [a607ee43e650]
+
+ * compat.h:
+ no longer need setreuid() emulation now set _PASSWD_LEN to 128 if
+ kerberos
+ [02fb274cc136]
+
+ * check.c:
+ now use private ticket file for kerberos support to avoid trouncing
+ on system one
+ [28d8b6b812c7]
+
+1995-06-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.h:
+ added SPOOF_ATTEMPT & cmnd_st
+ [d3b42a1f4d0d]
+
+ * sudo.c:
+ added anti-spoofing support
+ [ab1e2aa44a57]
+
+ * parse.c:
+ now use global cmnd_st
+ [47018265a1a6]
+
+ * logging.c:
+ added SPOOF_ATTEMPT suypport
+ [7bbe9dd2a021]
+
+ * testsudoers.c, visudo.c:
+ added void casts where appropriate
+ [f191441ba333]
+
+ * parse.yacc:
+ fixed up spacing and added void casts where appropriate
+ [15d886fc809c]
+
+ * sudo.c:
+ fixed problem with "-p prompt" but no args
+ [6fc048261a3e]
+
+1995-06-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.man:
+ added BUGS and annotated -l description
+ [e5c506de2603]
+
+ * sudo.h:
+ validate() now takes a flag
+ [26627becc60a]
+
+ * sudo.c:
+ validate() now takes a flag added -l
+ [a4f7bb97fe54]
+
+ * parse.yacc:
+ added support for -l
+ [e7a9b10b0ad3]
+
+ * parse.c:
+ validate() now takes a flag that says whether or not to check the
+ command
+ [9e1e67f4e281]
+
+1995-06-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ now deals with Argv == 1
+ [0acb637ab635]
+
+ * sudo.man:
+ added -p option
+ [e60382fc0561]
+
+ * sudo.c:
+ added prompt support reworked parse_args()
+ [2f605267ed4a]
+
+ * sudo.h:
+ added prompt
+ [5ab021bdb419]
+
+ * options.h:
+ added PASSPROMPT
+ [614727ff44a2]
+
+ * check.c:
+ now use BUFSIZ as length of kerb password added kpass so pass is
+ always a char * now use prompt global when asking for a password
+ [76be09af784f]
+
+ * tgetpass.c:
+ now use BUFSIZ as _PASSWD_LEN if using kerberos
+ [1e907eed312b]
+
+ * OPTIONS:
+ added PASSPROMPT
+ [ddb2f405ce40]
+
+1995-06-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ only look for -lufc or -lcrypt if crypt() not in libc
+ [9717d315661f]
+
+ * check.c:
+ don't exit on kerb error, just warn if k_errno == KDC_PR_UNKNOWN
+ (unknown user) silently fail
+ [2b48693d4ee9]
+
+ * INSTALL:
+ added kerb4 note
+ [986e393f740c]
+
+ * tgetpass.c:
+ HAVE_KERBEROS -> HAVE_KERB4
+ [e438bfb5e6aa]
+
+ * check.c:
+ removed debugging printf
+ [1cf9f5cbffa5]
+
+ * configure.in:
+ KERBEROS -> KERB4 added checks for setreuid & setresuid
+ [01e9945beb1e]
+
+ * config.h.in:
+ HAVE_KERBEROS -> HAVE_KERB4 added HAVE_SETREUID and HAVE_SETRESUID
+ [0e0bb5b8ac3e]
+
+ * compat.h:
+ added deif of UID_NO_CHANGE & GID_NO_CHANGE added setreuid emulation
+ with setresuid if applic
+ [9dae24c47696]
+
+ * check.c:
+ HAVE_KERBEROS -> HAVE_KERB4 now only do the stupid chown() hack if
+ no setreuid() or a broken one
+ [1fca642bdb8e]
+
+1995-06-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ added kerberos support
+ [da5639b9b8e7]
+
+ * config.h.in:
+ added HAVE_KERBEROS
+ [fcc5be550e65]
+
+ * tgetpass.c:
+ added KERBEROS support (long passwords)
+ [303ba6924dd2]
+
+ * check.c:
+ added kerberos support
+ [e40afe98fc1d]
+
+1995-06-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.h:
+ added MODE_BACKGROUND
+ [9b483c932016]
+
+ * sudo.man:
+ escaped dashes added -b option
+ [62e84f1a7714]
+
+ * sudo.c:
+ added -b option
+ [7e78aaefeb95]
+
+ * check.c:
+ added crypt() for osf/1 3.x enhanced secuiry
+ [e9aa5abdb7d5]
+
+ * configure.in:
+ now check for -lcrypt
+ [5cb9c67e9fa2]
+
+ * interfaces.c:
+ added ENXIO like EADDRNOTAVAIL
+ [74223bb1ba75]
+
+1995-05-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ now emulate getwd(), not getcwd()
+ [3e5439d9a5f4]
+
+ * sudo.c:
+ getcwd() -> getwd()
+ [6392a96a658e]
+
+ * getwd.c:
+ getcwd -> getwd
+ [1b0ab9bae11e]
+
+1995-05-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * ins_2001.h, ins_classic.h, ins_goons.h:
+ Initial revision
+ [86db60d8cf00]
+
+ * insults.h:
+ broke out insults into separate include files
+ [0a01993bd38a]
+
+ * OPTIONS, options.h:
+ added GOONS
+ [e283203c6515]
+
+ * Makefile.in:
+ added ins_2001.h ins_classic.h ins_goons.h
+ [2a39cd6a4cd2]
+
+ * Makefile.in, version.h:
+ ++version
+ [05ebf4f5e41a]
+
+ * visudo.c:
+ moved signal handler setup to setup_signals()
+ [3dd976c04540]
+
+ * sudo.h:
+ added load_interfaces()
+ [af2d473b09e2]
+
+ * sudo.c:
+ moved load_interfaces to interfaces.c
+ [5c8c138e5d4c]
+
+ * parse.yacc:
+ added clearaliases
+ [aeb4ff301daa]
+
+ * OPTIONS, options.h:
+ added FAST_MATCH
+ [f49ea3d1b525]
+
+ * parse.lex:
+ now uses clearaliases variable
+ [a2dda415bf61]
+
+ * interfaces.c:
+ Initial revision
+ [a1990e3f5c69]
+
+ * Makefile.in:
+ added interfaces.[co]
+ [1e8e5984de97]
+
+ * testsudoers.c:
+ now uses ip addrs and netmasks via load_interfaces()
+ [54b8f7a6835e]
+
+ * sudo.c:
+ now remove IFS instead of setting to "sane" value
+ [ce7eec9f115e]
+
+1995-05-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.c:
+ added FAST_MATCH
+ [816d4f5fe81a]
+
+1995-04-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ sudo_goodpath.c-> goodpath.c
+ [a5072c4e1de2]
+
+ * sudo.c:
+ added Andy's new ISC changes
+ [caa6bbee358e]
+
+1995-04-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * OPTIONS:
+ added a sentence to SECURE_PATH info
+ [cad6e1569d15]
+
+ * BUGS:
+ added one
+ [4b35cf699a83]
+
+ * CHANGES:
+ updated
+ [5fded9dc62f0]
+
+ * RUNSON:
+ updated
+ [33cb993cfd39]
+
+1995-04-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * RUNSON:
+ updated for beta3
+ [a05dc6a91995]
+
+ * Makefile.in, version.h:
+ ++version
+ [54aaf3fadc75]
+
+ * aclocal.m4:
+ sendmail is now looked for in /usr/ucblib
+ [231ac1a4662f]
+
+ * sudo.c:
+ fixed indentation
+ [fb137400c8c2]
+
+ * aclocal.m4:
+ fixed a typo
+ [e03f1acc468b]
+
+ * sudo.c:
+ updated ISC mods
+ [070290d4754b]
+
+ * configure.in:
+ added unixware case
+ [e90250bae0d9]
+
+ * check.c:
+ user_is_exempt is no longer hidden
+ [1a341765b8af]
+
+ * RUNSON:
+ updated
+ [a9c4898b26dd]
+
+ * aclocal.m4:
+ isc and riscos changes
+ [98b5d86585d1]
+
+ * OPTIONS:
+ added NOTE about new interaction of EXEMPTGROUP and SECURE_PATH
+ [e1ecc464ce4b]
+
+ * Makefile.in:
+ fixed a typo and added testsudoers stuff
+ [435d60e163dc]
+
+ * testsudoers.c:
+ Initial revision
+ [6ce14a448662]
+
+1995-04-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc:
+ applied fixed patch from Chris
+ [cd6144203d13]
+
+1995-04-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ fixed a typo
+ [34f8a54ba041]
+
+ * parse.yacc:
+ added a set of braces for bison
+ [f0e43b938914]
+
+ * parse.yacc:
+ merged in Chris' changes to dekludge the parser.
+ [82d6e373ab1c]
+
+ * logging.c:
+ send_mail() was calling find_path() which is wrong since find_path()
+ stores cmnd in a static var. Anyhow, it doesn't make much sense
+ since MAILER should always be fully qualified
+ [6eae6a0b8098]
+
+1995-04-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sample.sudoers:
+ added User_Alias stuff
+ [aaba8c8e918d]
+
+ * aclocal.m4:
+ SUDO_NEXT now looks for /usr/lib/NextStep/software_version
+ [52bd81f34b32]
+
+ * RUNSON:
+ added DEC UNIX 3.0 w/ gcc
+ [7daf570775b5]
+
+ * visudo.c:
+ Exit was being used in places where exit should be used
+ [6026a89c07ed]
+
+ * sudoers:
+ added "User alias specification"
+ [a487b6e234f8]
+
+ * parse.yacc:
+ fixed probs caused by making nslots and naliases a size_t
+ [0be919384f3f]
+
+ * RUNSON:
+ added KSR, upped rev to 1.3.1b2
+ [ce04ee6faadf]
+
+ * logging.c, parse.yacc:
+ 1024 -> BUFSIZ
+ [cd6dda45fa11]
+
+ * parse.yacc:
+ void * -> VOID * naliases and nslots are now size_t to appease
+ lsearch on 64-bit machines
+ [bf2f807c0dc1]
+
+1995-04-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TODO:
+ did a bunch of things and added a bunch :-)
+ [42afd957b829]
+
+ * PORTING:
+ updated
+ [972f95c85776]
+
+ * visudo.man:
+ closer to BSD manpage style
+ [07ae88f50325]
+
+ * sudo.man:
+ closer to standard BSD man format
+ [372c28dcc135]
+
+ * compat.h, config.h.in, emul/search.h, insults.h, options.h,
+ pathnames.h.in, sudo.h, version.h:
+ added RCS id
+ [c0ec90b81002]
+
+ * sudo.h:
+ removed crufty #defines that are no longer used
+ [35e2b4b477f0]
+
+ * BUGS:
+ fixed a bug
+ [5bb3e1bee85e]
+
+ * sudo.man:
+ updated based on sudo changes
+ [e65de1cae438]
+
+ * parse.yacc:
+ now allow ALL keyword in User_Aliases now allow ALL keyword as well
+ as a NAME or ALIAS
+ [1fb31404dd0f]
+
+ * CHANGES:
+ updated
+ [b24018ac610b]
+
+ * sudo.c:
+ now sets SUDO_COMMAND and SUDO_GID envariables.
+ [e9d791557fb7]
+
+ * aclocal.m4:
+ fixed bug with full void impl check
+ [35715301023c]
+
+ * parse.yacc:
+ fixed User_Alias supoprt
+ [4c30dfbaaa07]
+
+ * parse.yacc:
+ added stubs for User_Alias support
+ [f4afbd247edf]
+
+ * sudo.c:
+ now sets removes # bogus interfaces from num_interfaces
+ [6f077fac9ab1]
+
+ * parse.lex:
+ added User_Alias support
+ [bc7997e5df85]
+
+1995-04-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ removed extraneous TODO
+ [bc87a3b14d6d]
+
+1995-04-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ ntwk_matches -> addr_matches
+ [475044e288b8]
+
+ * parse.yacc:
+ ntwk_matches -> addr_matches
+ [dd1f4093fd2d]
+
+ * parse.c:
+ ntwk_matches -> addr_matches now use inet_addr() not inet_network()
+ (which expects octet boundaries) fixes for OSF (sizeof(int) !=
+ sizeof(long))
+ [acd2f556940f]
+
+ * sudo.c:
+ took out debugging info
+ [044023063eca]
+
+ * aclocal.m4:
+ OS was being set to unknown before non-uname based host checks. This
+ caused no checks to happen since $OS was not zero-length.
+ [335a7267479d]
+
+ * sudo.c:
+ fixed loading of interfaces struct still has debugging info in
+ though
+ [2d1a18998c1e]
+
+ * parse.c:
+ fixed typo
+ [175674a3a9fa]
+
+1995-04-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ ++version
+ [55d191b5daa3]
+
+ * version.h:
+ ++
+ [d7d1f115696a]
+
+ * visudo.c:
+ removed extraneous extern decl of "top
+ [50355621047d]
+
+ * visudo.c:
+ now zeros "top"
+ [4e683210345b]
+
+ * parse.yacc:
+ removed parser_cleanup (no need for it now)
+ [afa59f222b6c]
+
+ * parse.lex:
+ now calls reset_aliases() directly
+ [3a23cbd60fc0]
+
+1995-04-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * OPTIONS:
+ added a sentence to SECURE_PATH description
+ [c5bf75b85af0]
+
+ * parse.c:
+ fixed my stupid bug where I used NAMLEN on something I wanted to
+ just get the name from. argh.
+ [111f460f6540]
+
+1995-04-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * lsearch.c:
+ fixed argument order of memmove() that i hosed when converting from
+ bcopy(). arghh.
+ [2f5336045c8b]
+
+ * Makefile.in:
+ finally fixed DISTFILES line
+ [a1b419e73a63]
+
+ * Makefile.in:
+ tabs -> spaces
+ [280fb03e5764]
+
+ * Makefile.in:
+ added missing files to DISTFILES
+ [991fc1cd2263]
+
+ * Makefile.in:
+ SUPPORTED -> RUNSON
+ [7580e65b05fb]
+
+1995-04-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TODO:
+ updated
+ [fe764a29c1cc]
+
+ * RUNSON:
+ updated for pl5b1 release
+ [aefc35bd2291]
+
+ * BUGS, TODO:
+ updated
+ [8f0ea249b687]
+
+ * check.c:
+ fixed bug where if you hit return at first sudo prompt it would
+ still log as a failure
+ [24539c854692]
+
+ * CHANGES:
+ updated
+ [251cc7b3ede4]
+
+ * aclocal.m4:
+ better test for bogus void * implementation
+ [efe23180cb88]
+
+ * logging.c:
+ added PASSWORDS_NOT_CORRECT
+ [bd12c73f83f7]
+
+ * check.c:
+ added PASSWORDS_NOT_CORRECT stuff]
+ [90de391a979f]
+
+ * sudo.h:
+ added PASSWORDS_NOT_CORRECT
+ [727fbeb76fc5]
+
+ * tgetpass.c:
+ moved pathnames.h
+ [4f910e5a8df7]
+
+ * sudo.c:
+ removed some unused vars and fixed up uid2str
+ [70e92c7f9076]
+
+ * putenv.c:
+ moved compat.h
+ [b271091586f6]
+
+ * getcwd.c, getwd.c:
+ added pathnames.h
+ [6f25218f133f]
+
+1995-03-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc:
+ fixed a typo I introduced in the last checkin :-(
+ [62c3af75c4fe]
+
+ * parse.lex:
+ can't have #ifdef's where N is defined so just do this the broken
+ way for AIX
+ [c5648a5594e4]
+
+ * parse.yacc:
+ better hack from Chris (but still a hack)
+ [6b6d8aed93f3]
+
+ * parse.lex:
+ stupid hack for broken aix lex
+ [efc3f9e5280e]
+
+ * tgetpass.c:
+ now includes compat.h 
+ [401822173f77]
+
+ * visudo.c:
+ now includes fcntl.h
+ [63865c2f8ac6]
+
+ * compat.h:
+ added FD_SET and FD_ZERO for 4.2BSD
+ [00c5597c0bb0]
+
+ * parse.yacc:
+ dirty hack to fix parser bug. i don't really like this but it works
+ for now...
+ [5b8bbdc81569]
+
+ * sudo.c:
+ uid2str is now static like the prototype says
+ [f2a97b5cb870]
+
+1995-03-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, SUPPORTED, TODO, TROUBLESHOOTING:
+ updated
+ [6f79c3e92716]
+
+ * RUNSON:
+ Initial revision
+ [12a09ef9e884]
+
+ * sudo.c:
+ check_sudoers now returns an error code and sudo calls inform_user
+ and log_error based on the return value.
+ [340eca188d9a]
+
+ * logging.c, sudo.h:
+ added entries for new errors
+ [6050d8542e1f]
+
+ * parse.c:
+ now set uid to that of SUDOERS_OWNER while parsing sudoers file
+ [3683c42bc9b0]
+
+ * Makefile.in:
+ took out testsudoers 
+ [65317d49db48]
+
+ * sudo.c:
+ now explicately checks that it is setuid root
+ [2fe1be60ef6a]
+
+ * sudo.c:
+ If a user has no passwd entry sudo would segv (writing to a garbage
+ pointer). Now allocate space before writing :-)
+ [d08e7eb5e5ef]
+
+ * configure.in:
+ reordered AC_CHECK_FUNCS
+ [4c82e56c6f4f]
+
+ * config.h.in:
+ fixed memset macro
+ [77ede6b714ab]
+
+ * tgetpass.c, visudo.c:
+ bzero -> memset
+ [1a005bb322c8]
+
+ * logging.c:
+ bzero -> memset when a parse error is logged the line number of the
+ error is now logged too
+ [a42d68047723]
+
+ * INSTALL:
+ added Sunos to blurb about c2 security
+ [af750a1d131e]
+
+ * configure.in:
+ added a SUN4 define for C2 security
+ [6ad5b23a3eb0]
+
+ * config.h.in:
+ bcopy -> memmove bzero -> memset
+ [5494460c8464]
+
+ * lsearch.c:
+ bcopy -> memmove char * -> VOID *
+ [a15f5c316e16]
+
+ * check.c:
+ added support for sunos with C2 security
+ [03fea5bb21e6]
+
+ * OPTIONS, options.h:
+ reordered
+ [1686265af3e1]
+
+ * pathnames.h.in:
+ _PATH_SUDO_LOGFILE now set based on configure
+ [5867b58e4a04]
+
+ * configure.in:
+ added SUDO_LOGFILE and SUDO_TYPE_SIZE_T
+ [1984d9fd1b5c]
+
+ * config.h.in:
+ added _SUDO_PATH_LOGFILE
+ [dd3eebe62580]
+
+ * aclocal.m4:
+ added SUDO_LOGFILE to find where to put sudo.log added
+ SUDO_CHECK_TYPE (just AC_CHECK_TYPE but checks unistd.h too) added
+ SUDO_TYPE_SIZE_T (calls SUDO_CHECK_TYPE)
+ [c589a515a99a]
+
+1995-03-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TROUBLESHOOTING:
+ Initial revision
+ [f42f1baba3a8]
+
+ * sudo.c:
+ now do set_perms(PERM_ROOT) before the getpwuid() in load_global()
+ to work around a problem is trusted hpux shadow passwords. yuck.
+ [ae1f13b54687]
+
+ * parse.yacc:
+ backed out a change in malloc/realloc
+ [ab868db0ad69]
+
+ * parse.yacc:
+ now include stdlib.h
+ [957eef0631eb]
+
+ * visudo.c:
+ now do an freopen() of the stmp file so that yyin will always point
+ to the same thing. This is important for flex since we are doing a
+ YY_NEWFILE
+ [44558922fd3e]
+
+ * parse.yacc:
+ replaced yywrap() with parser_cleanup() since yywrap() needs to be
+ in parse.lex to be able to use YY_NEW_FILE. sigh.
+ [12dd09921074]
+
+ * parse.lex:
+ now have a rule that matches anything that doesn't match an
+ explicite rule. well, you know what i mean (. matches anything not
+ yet matched). However, this means that there is input still queued
+ up so we need to do a YY_NEW_FILE; in yywrap. So, yywrap has moved
+ into parse.lex and it calls parser_cleanup() which is most of the
+ old yywrap() sigh.
+ [7f4042bc48d6]
+
+ * SUPPORTED:
+ no longer used
+ [8f220be4da94]
+
+ * getcwd.c, getwd.c:
+ moved compat.h to be the last include file
+ [9f3a65e2d485]
+
+ * parse.yacc:
+ fixed type of aliascmp() args
+ [1c27eb989bdf]
+
+ * find_path.c:
+ NULL -> '\0'
+ [5c8d8cf1692e]
+
+ * parse.yacc:
+ added casts to lfind and lsearch args for irix
+ [61027ddeecf8]
+
+ * Makefile.in:
+ bsdinstall -> install-sh
+ [61de6612c5a5]
+
+ * INSTALL:
+ added info about make realclean
+ [29c6324d727f]
+
+ * Makefile.in:
+ updated VERSION added dependencies for visudo.cat
+ [09077d7229d4]
+
+ * version.h:
+ -> pl5b1
+ [5d21c7ad1a41]
+
+ * sudo.c:
+ took out -l
+ [fc1478d81b38]
+
+ * Makefile.in:
+ now there is a real visudo.man and visudo.cat
+ [58aeac43a6dd]
+
+ * sudo.man:
+ took out visudo stuff
+ [4a6ac4393343]
+
+ * visudo.man:
+ Initial revision
+ [cba348843db8]
+
+ * parse.c, parse.lex, parse.yacc:
+ updated copyright
+ [ffa16b70944a]
+
+ * README:
+ updated for pl5
+ [a26e423e9e5f]
+
+ * sudo.man:
+ updated Nieusma & Hieb email addresses
+ [f0083e71989d]
+
+ * INSTALL:
+ updated to include options.h and OPTIONS
+ [ee59e2b76c94]
+
+ * CHANGES, TODO:
+ updated
+ [51e011ad5220]
+
+ * BUGS:
+ eliminated bug #1 (yay)
+ [e7e88515494e]
+
+ * configure.in:
+ sunos no longer gets linked statically
+ [2e5b3ff3108f]
+
+1995-03-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.lex:
+ prototype now uses __P()
+ [68ecdcab4c70]
+
+ * parse.lex:
+ make fill() non-ansi
+ [d6509972260b]
+
+ * parse.c:
+ made -v (validate) work
+ [13c9d520638c]
+
+ * logging.c:
+ now gives host
+ [f04859cdba5a]
+
+ * find_path.c:
+ don't check for execute/statable if fq or relative path given
+ [4bbe851f3973]
+
+ * parse.c:
+ added a cast
+ [345c308f72f3]
+
+ * visudo.c:
+ now include ctype.h for islower and tolower macros
+ [582c0aa332d5]
+
+ * goodpath.c:
+ moved _S_IFMT & _S_ISREG to compat.h
+ [828e4ca4e7b4]
+
+ * sudo.c:
+ moved a set of parens
+ [5783474ecf37]
+
+ * strdup.c:
+ now include compat.h
+ [75e2036b94af]
+
+ * emul/search.h:
+ void * -> VOID *
+ [cedcfaf04161]
+
+ * parse.yacc:
+ now cast malloc & realloc return vals added search for HAVE_LSEARCH
+ now use strcmp if no strcasecmp available
+ [d6a42bc3d4ae]
+
+ * lsearch.c:
+ void * -> VOID *
+ [886adc44f607]
+
+ * config.h.in:
+ removed HAVE_FLEX added VOID added HAVE_DIRENT_H, HAVE_SYS_NDIR_H,
+ HAVE_SYS_DIR_H, HAVE_NDIR_H added HAVE_LSEARCH
+ [3b50d7fb4349]
+
+ * compat.h:
+ added _S_IFMT, _S_IFREG, and S_ISREG
+ [73d506c7d53c]
+
+ * aclocal.m4:
+ took out SUDO_PROG_INSTALL 1.x to 2.x changes added echo and results
+ to most SUDO_* macros
+ [8442155f5936]
+
+ * Makefile.in:
+ no more -I.
+ [63462f195bd4]
+
+ * configure.in:
+ various 1.x ro 2.x autoconf changes now check for strcasecmp now use
+ AC_INSTALL_PROG instead of custom one added check for fully woorking
+ void implementation
+ [5ac6b6e6230f]
+
+ * Makefile.in:
+ added lsearch & search.h visudo links into $(LIBOBJS)
+ [bc119cda4598]
+
+ * aclocal.m4:
+ partial 1.x to 2.x changes added SUDO_FULL_VOID
+ [1194d01fa5c5]
+
+ * visudo.c:
+ whatnow_help was prototyped to be static be was not declared as such
+ [0f85489dd426]
+
+ * configure.in:
+ autoconf 2.x changes took out HAVE_FLEX (no longer used) added check
+ for dirent/dir/ndir.h
+ [7408f3854948]
+
+ * parse.c:
+ now use groovy gnu autoconf macro AC_HEADER_DIRENT
+ [e465db9f5dfa]
+
+ * getcwd.c, getwd.c:
+ MAXPATHLEN -> MAXPATHLEN+1
+ [714d87424e21]
+
+ * emul/search.h, lsearch.c:
+ Initial revision
+ [55d79482c535]
+
+1995-03-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc:
+ eliminated bison warnings
+ [61ca0a96da22]
+
+ * parse.lex:
+ added missing case
+ [6be0f849747c]
+
+ * visudo.c:
+ now iincludes signal.h
+ [221e0fcc144f]
+
+ * parse.yacc:
+ only clear data structures on a parse error
+ [7b1c0f1a4527]
+
+ * visudo.c:
+ whatnow() now gives help on invalid input
+ [e5a4cd88c587]
+
+ * visudo.c:
+ added a whatnow() function (sort of like mh)
+ [932d9b145f1c]
+
+ * parse.yacc:
+ kill_aliases -> reset_aliases yywrap() now cleans up by calling
+ reset_aliases() and clearing top took reset stuff out of yyerror()
+ since it doesn't beling there (and doesn't work anyway). errorlineno
+ is now initially set to -1 so we can set it to the first error that
+ occurrs (it was getting set to the last)
+ [2f71f95a974c]
+
+ * parse.lex:
+ added a void cast
+ [18ae6042dce4]
+
+ * visudo.c:
+ rewrote from scratch based on 4.3BSD vipw.c
+ [2f6814f18576]
+
+1995-03-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c, sudo.h:
+ removed ocmnd
+ [a31735f41ad4]
+
+ * sudo.h:
+ no more sudo_realpath() and find_path() changed params
+ [8e85c3b39159]
+
+ * sudo.c:
+ find_path() changed since no more realpath()
+ [b25366c7f2ee]
+
+ * parse.yacc:
+ on error, errorlineno is set to the line where the error occurred
+ added kill_aliases() to free the aliases struct now clean up in
+ yyerror() so we can reparse cleanly
+ [2342f578c27a]
+
+ * options.h, parse.c:
+ no more USE_REALPATH
+ [cfc59babeaff]
+
+ * logging.c:
+ changed to use new find_path()
+ [91c7a38e7751]
+
+ * find_path.c:
+ removed all the realpath() stuff
+ [cc21a43a8562]
+
+ * Makefile.in:
+ sudo_realpath.c -> sudo_goodpath.c
+ [03a9b1ddec2f]
+
+ * visudo.c:
+ now works correctly with utk parser
+ [08aa554a0ce8]
+
+ * goodpath.c:
+ Initial revision
+ [1ea607e1ffb2]
+
+ * sudo_realpath.c:
+ eliminated a compiler warning
+ [198bcccc55b6]
+
+ * sudo.c:
+ elinated compiler warning
+ [e2384f9a878b]
+
+ * sudo_realpath.c:
+ added sudo_goodpath()
+ [43878c4cc540]
+
+ * sudo.h:
+ added prototype for sudo_goodpath
+ [23e8627a2265]
+
+ * parse.c:
+ added support for /sys/dir.h
+ [eca897087741]
+
+ * options.h:
+ USE_REALPATH turned off
+ [620ac8b63d85]
+
+ * find_path.c:
+ added calls to sudo_goodpath()
+ [ad170904fbcd]
+
+ * configure.in:
+ added check for dirent.h
+ [7964a8c26855]
+
+ * config.h.in:
+ added HAVE_DIRENT_H
+ [1f785fec7e19]
+
+ * configure.in:
+ added in linux shadow pass stuff 
+ [e585a5785f50]
+
+1995-03-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ added back host, user, cmnd, parse_error
+ [0ec19f3d64f4]
+
+ * visudo.c:
+ added in utk changes plus some minor cosmetic changes
+ [c5c1921c8a58]
+
+ * sudo.c, sudo_realpath.c:
+ added void casts for printf's
+ [9c6ff11c0082]
+
+ * options.h:
+ added a define of USE_REALPATH
+ [db3711c9efc5]
+
+ * configure.in:
+ there is no more visudoers/Makefile
+ [36e1bc1f78d0]
+
+ * Makefile.in:
+ added in utk changes (visudo is now built from the toplevel)
+ [76203d4b345d]
+
+ * find_path.c:
+ added (void) casts to printf's
+ [dd5cb1e060ac]
+
+ * parse.c, parse.lex, parse.yacc, sudo.h, sudo_realpath.c:
+ merged in utk changes
+ [35563307fd8e]
+
+1995-03-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * find_path.c:
+ now check to see that what we are trying to run is a file (or a link
+ to a file, we do a stat(2) so there is no diff)
+ [05889c4bcace]
+
+1995-03-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ updated
+ [3e8047bb26fb]
+
+ * Makefile.in:
+ aclocal.m4 -> acsite.m4 make realclean updated for new autoconf 
+ [0bdbaa7c4c7d]
+
+ * sudo.man:
+ added myself as maintainer
+ [77a9d75aab84]
+
+1995-02-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ changed setegid -> setgid
+ [7f4788d73b6f]
+
+1995-02-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ fixed the test for irix 5.x to skip bad libs
+ [bfef896de013]
+
+ * aclocal.m4:
+ now initialize OS and OSREV
+ [cc302756e440]
+
+1995-01-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ irix5 changes
+ [ac985b23f5f2]
+
+ * configure.in:
+ AC_WITH -> AC_ARG_WITH changes other misc changes for autoconf 2.1
+ compatibility
+ [0cf8c92a06d7]
+
+1995-01-19 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ use YY_NEW_FILE, not yyrestart since OSF flex doesn't do the righ
+ thing wrt yyrestart (grrrr)
+ [18e8eabfbb82]
+
+1995-01-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ added visudoers/compat.h to DISTFILES
+ [db23b574b034]
+
+ * configure.in:
+ fixed an echo
+ [7cbc0462b89d]
+
+ * sudo.c:
+ added ocmnd declaration adjusted for find_path()'s new parameters
+ [d929cd156474]
+
+ * sudo.h:
+ added ocmnd extern adjusted find_path() prototype
+ [e0004daf5d3c]
+
+ * parse.c:
+ cmndcmp() now takes 3 arguments and checks against the qualified as
+ well as the unqualified pathname. more code that should use
+ cmndcmp() but did not, now does
+ [6f70a8c17bee]
+
+ * options.h:
+ added to a comment
+ [7a78680426b2]
+
+ * logging.c:
+ changed to use new find_path() parameter passing
+ [840981d30db4]
+
+ * find_path.c:
+ find_path() now takes 2 copyout parameters (one for the qualified
+ pathname and one for the unqualified pathname). The third parameter
+ may be NULL.
+ [851503b005e9]
+
+ * configure.in:
+ no longer munge pathnames.h
+ [427d8796c5a9]
+
+ * pathnames.h.in:
+ changed _PATH_* to use _SUDO_PATH_* (which are defined in config.h)
+ as a result, pathnames.h does not need to be run through configure
+ and the user can override the configured values easily.
+ [2e378f2ebe88]
+
+ * config.h.in:
+ added _SUDO_PATH_* entries
+ [0857de7cebab]
+
+ * aclocal.m4:
+ _PATH* -> _SUDO_PATH_*
+ [7601193f56cc]
+
+ * Makefile.in:
+ updated DISTFILES and HDRS .o's now depend on config.h
+ [39d8601965cf]
+
+1995-01-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * compat.h:
+ removed extraneous #endif
+ [27d4c5f2ce7e]
+
+ * aclocal.m4:
+ added SUDO_PROG_MV
+ [76dda3bdd816]
+
+ * configure.in:
+ added SUDO_PROG_MV added riscos and isc os types took out
+ -DSHORT_MESSAGE from --with-csops since it is now the default
+ [68c206ad976e]
+
+ * sudo.c:
+ move the include of id.h to compat.h now includes options.h
+ [45a1eaafb3a8]
+
+ * sudo.h:
+ moved compatibility #defines to compat.h
+ [0eee27057698]
+
+ * pathnames.h.in:
+ added _PATH_MV
+ [e830797ab320]
+
+ * config.h.in:
+ move __P to compat.h
+ [188e12e0ba93]
+
+ * getcwd.c, getwd.c, putenv.c:
+ now includes compat.h
+ [c72cb6d73981]
+
+ * compat.h:
+ Initial revision
+ [d4d2f359ae03]
+
+1995-01-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.h:
+ pull user-configurable stuff out and put in options.h
+ [ef929467b070]
+
+1995-01-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.lex, parse.yacc, visudo.c:
+ now includes options.h
+ [e36d7c82add1]
+
+ * check.c, find_path.c, logging.c, parse.c, sudo_realpath.c,
+ sudo_setenv.c:
+ now includes options.h
+ [f186ba03de07]
+
+ * Makefile.in:
+ added visudoers/options.h
+ [e5350c476494]
+
+ * OPTIONS, options.h:
+ Initial revision
+ [9b6b5001e318]
+
+ * Makefile.in:
+ added OPTIONS and options.h
+ [25448341e16a]
+
+ * logging.c:
+ changed #ifdef's to use LOGGING and SLOG_SYSLOG/SLOG_FILE
+ [5dd6385dd1d3]
+
+ * check.c, sudo.h:
+ changed PASSWORD_TIMEOUT to minutes
+ [0ec6aab98738]
+
+1994-12-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ now only do Editor +line_num if line_num != 0
+ [b69f04b5e3c7]
+
+1994-12-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ now use mv if rename(2) fails
+ [83210dca1bab]
+
+ * BUGS:
+ added a visudo bug
+ [d61a806f9aa7]
+
+ * check.c:
+ expanded comment
+ [641f2cba94cb]
+
+1994-11-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ fixed user_is_exempt to return 0 if EXEMPTGROUP is not set
+ [7a11135039a8]
+
+1994-11-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ added mips & isc support
+ [e258dc053119]
+
+ * parse.c:
+ added support for non-root owned sudoers file
+ [fea07e65a0fc]
+
+ * check.c:
+ added exempt group support
+ [928fb4bd9ad5]
+
+ * sudo.h:
+ added set_perms() support added SUDOERS_OWNER so can have non-root
+ own sudoers file added exempt group support added isc support
+ [61c578d31fc1]
+
+ * visudo.c:
+ now copy sudoers to temp file via read/write (not stdio) now chown
+ new sudoers file to SUDOERS_OWNER
+ [a5176c59df70]
+
+1994-11-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ added skey support
+ [35a8d2fabdb7]
+
+ * sudo_realpath.c:
+ be_* -> setperms()
+ [a1631d686e1c]
+
+ * sudo.h:
+ fixed typo added set_perms support added skey support added
+ seteuid()/setegid() emulation for AIX
+ [c0c8d6771406]
+
+ * sudo.c:
+ be_* -> setperms() now check to make sure sudoers file is owned by
+ root nread/write by only root
+ [13ab1e261f1a]
+
+ * logging.c, parse.c:
+ be_* -> setperms()
+ [21499d845c8f]
+
+ * check.c:
+ be_* -> set_perms() added skey support
+ [df51b56871c1]
+
+1994-11-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ ++version
+ [3c1abbe4e43c]
+
+ * version.h:
+ ++
+ [1d2f9b540a95]
+
+1994-10-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ now sets IFS
+ [eabbb41b9f08]
+
+ * insults.h:
+ fixed typo
+ [c7997f19216e]
+
+1994-10-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in:
+ added HAVE_SKEY
+ [da948ec4186b]
+
+1994-10-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ updated
+ [f4b55ab007ea]
+
+ * Makefile.in:
+ ++version
+ [0489068b8c95]
+
+ * version.h:
+ ++
+ [d189faedf423]
+
+ * sudo.c:
+ now bail if ARgv[1] > MAXPATHLEN
+ [0cea8ecc9dc2]
+
+ * configure.in:
+ added function check for tcgetattr(3)
+ [e03289b22c2f]
+
+ * config.h.in:
+ only define HAVE_TERMIOS_H if you have tcgetattr(3)
+ [757eab83d1a2]
+
+ * config.h.in:
+ added check for tcgetattr
+ [c5ae92715930]
+
+1994-09-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ updated
+ [cbc419883108]
+
+1994-09-22 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.lex:
+ now only include unistd.h for linux
+ [e9adeab95ef0]
+
+1994-09-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ added visudo.8 generation
+ [d6a3f0f887f8]
+
+ * configure.in:
+ added -Wl,-bI:./aixcrypt.exp to aix flags
+ [72594a21edcf]
+
+1994-09-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * BUGS:
+ added one
+ [9993a349e096]
+
+ * CHANGES:
+ updated
+ [297b31ec4cdd]
+
+ * README:
+ added mailing list info
+ [10372f94a2b2]
+
+ * parse.yacc:
+ now use sudolineno instead of yylineno fixed bison warnings
+ [25a83e62057b]
+
+ * configure.in:
+ now use -no_library_replacement for osf don't make a static binary
+ for hpux >= 9.0
+ [1fa7b892f1a3]
+
+ * tgetpass.c:
+ added string.h/strings.h inclusion
+ [71faa98fc0a1]
+
+ * config.h.in:
+ added ssize_t def
+ [406284bd1ac0]
+
+ * parse.lex:
+ added inclusion of string.h/strings.h
+ [6985b1df5d09]
+
+ * aclocal.m4:
+ fixed uname | sed (needed to quote the '[')
+ [4cd2d3415c1a]
+
+ * parse.lex:
+ replaced yylineno with sudolineno fixed bison syntax errors
+ [0bd31a5fab26]
+
+ * visudo.c:
+ changed yylineno to sudolineno since yylineno cannot be counted
+ upon.
+ [38c30104d0ae]
+
+ * TODO:
+ updated
+ [5d4746f1a752]
+
+ * parse.c:
+ added code to support command listings
+ [030172e133fd]
+
+ * sudo.c:
+ added code for -l flag
+ [801dbbc82778]
+
+ * sudo.man:
+ fixed typo added info for -l flag
+ [8916ca945d65]
+
+ * configure.in:
+ AC_SSIZE_T -> SUDO_SSIZE_T
+ [c61f7f47013f]
+
+ * aclocal.m4:
+ added SUDO_SSIZE_T
+ [0ccdb77be84d]
+
+ * sudo.h:
+ added MODE_LIST
+ [9b2bd844c76c]
+
+ * configure.in:
+ added AC_SSIZE_T
+ [35cca208f9b5]
+
+ * find_path.c, sudo_realpath.c:
+ readlink() is now declared as returning ssize~_t
+ [0640a08d1407]
+
+ * configure.in:
+ added -laud for OSF c2
+ [b7539c905efc]
+
+1994-09-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, visudo.c:
+ changed sudo-bugs.cs.colorado.edu -> sudo-bugs@cs.colorado.edu
+ [067fd9bcb5e1]
+
+ * config.h.in, parse.lex, parse.yacc, pathnames.h.in:
+ changed sudo-bugs.cs.colorado.edu -> sudo-bugs@cs.colorado.edu
+ [fc46e7c7110a]
+
+ * check.c, find_path.c, getcwd.c, getwd.c, insults.h, logging.c,
+ parse.c, putenv.c, strdup.c, sudo.c, sudo.h, sudo_realpath.c,
+ sudo_setenv.c, tgetpass.c, version.h:
+ changed sudo-bugs.cs.colorado.edu -> sudo-bugs@cs.colorado.ed
+ [d1d4fbc53a98]
+
+1994-09-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in:
+ ++version
+ [b7066d97633f]
+
+ * version.h:
+ ++
+ [65ec69d88110]
+
+ * logging.c:
+ added host to alertmail messages
+ [d973c19ce777]
+
+ * CHANGES, TODO:
+ udpated
+ [5a65eb16faeb]
+
+ * logging.c:
+ fixed logging problem where mail would not say which user it was
+ [35723edcc5d2]
+
+ * configure.in:
+ added -laud for gcc if osf & c2
+ [18f1e0ae5548]
+
+ * check.c:
+ moved set_auth_parameters to sudo.c
+ [d23112fe01db]
+
+ * sudo.c:
+ added set_auth_parameters for osf
+ [eb70f65214ac]
+
+ * configure.in:
+ cleaned up -static stuff
+ [01e9575f0422]
+
+ * Makefile.in:
+ ++version
+ [7ac3bff5c770]
+
+ * version.h:
+ ++
+ [10a4ff478469]
+
+ * sudo.c:
+ changed setenv() to sudo_setenv()
+ [40a78abb9946]
+
+ * check.c:
+ fixed osf problem
+ [3d69b118efb8]
+
+ * configure.in:
+ added OSF C2 stuff
+ [38cff3ad4093]
+
+ * CHANGES:
+ updated
+ [cd341dd0581a]
+
+ * check.c:
+ added osf auth support & removed some extra spaces
+ [a448cdd81514]
+
+ * INSTALL, SUPPORTED:
+ added osf C2 stuff
+ [f70484796146]
+
+1994-08-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TODO:
+ added 2 suggestions
+ [695fbdbd86e6]
+
+ * Makefile.in:
+ removed README.v1.3.1 and added VERSION stuff
+ [f69403eb04c6]
+
+ * version.h:
+ pl1
+ [21580c0f8cb1]
+
+1994-08-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * version.h:
+ 1.3.1final
+ [630114970298]
+
+ * Makefile.in:
+ added HISTORY
+ [901bff251614]
+
+ * sudo.man:
+ mention HISTPRY file
+ [86dbcfd4326e]
+
+ * sudo.c:
+ use sizeof instead of a constant in 1 place
+ [d819604c68ca]
+
+ * parse.yacc:
+ added unistd.h
+ [6f9500f9fe7e]
+
+ * parse.lex:
+ added unistd.h
+ [468b81a276eb]
+
+ * README:
+ udpated
+ [7e275618923a]
+
+ * HISTORY:
+ Initial revision
+ [5db1b0a3939b]
+
+1994-08-17 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * version.h:
+ ++
+ [7dfbb4a810bb] [SUDO_1_3_1]
+
+ * CHANGES:
+ updated
+ [7820ee610bf8]
+
+ * sudo_setenv.c:
+ added unistd.h include
+ [30cf2b654525]
+
+1994-08-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ added sys/time.h for AIX
+ [199fc8caf3a3]
+
+1994-08-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ added check for -lsocket and sys/sockio.h
+ [f9abfbb31031]
+
+ * config.h.in:
+ took out libshadow check and added in sys/sockio.h check
+ [0c4b0393ac80]
+
+ * sudo.c:
+ now include sockio.h instead of ioctl.h if it exists "sudo -" now
+ gets a better error message
+ [53041bea5483]
+
+ * sample.sudoers:
+ now has a dir and subnet entry
+ [56b820f65438]
+
+1994-08-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ removed if_ether.h
+ [b4f64507493e]
+
+ * TODO:
+ added an item
+ [ea2a1bb6922a]
+
+ * sudo.man:
+ added network and ip addresses to man page
+ [01c85016511f]
+
+ * sudo.c:
+ no error if can't get interfaces or netmask since networking may not
+ be in the kernel.
+ [50b8890e2134]
+
+ * parse.c:
+ nwo check for interfaces == NULL
+ [dc1b3eef0db2]
+
+ * parse.c:
+ fixed a bug that caused directory specs in a Cmnd_Alias to fail if
+ the last entry in the spec failed (ie: it was only looking at the
+ last entry). CLeaned things up by adding the cmndcmp() function--all
+ neat & tidy
+ [007e93578e5e]
+
+ * CHANGES:
+ added one
+ [40e8a2cef497]
+
+1994-08-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ now do two passes to skip bogus interfaces (lo0, etc)
+ [465e30aecaf7]
+
+ * parse.lex, parse.yacc, visudo.c:
+ added include of netinet/in.h
+ [11e3816ed362]
+
+ * logging.c, sudo_realpath.c, sudo_setenv.c:
+ added ninclude of netinet/in.h
+ [daccfa40fe1e]
+
+ * check.c, find_path.c, getcwd.c, getwd.c:
+ added include of netinet/in.h
+ [0222f95e06ad]
+
+ * version.h:
+ ++
+ [d6b0cfa35a38]
+
+ * sudo.h:
+ added interfaces global
+ [ba52fa8ad75e]
+
+ * parse.c:
+ now uses new interfaces global
+ [17473ad5ecba]
+
+ * sudo.c:
+ now ip addresses are gleaned fw/o dns
+ [8828bb2007e0]
+
+1994-08-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ added load_ip_addrs() to load the ip_addrs global var
+ [60c825f04238]
+
+ * parse.c:
+ added hostcmp() to compare hostnames, ip addrs, and network addrs
+ [ab0e40e37537]
+
+ * sudo.h:
+ added ip_addrs def added load_ip_addrs prototype
+ [c41c565d0777]
+
+1994-08-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ updated
+ [2a128dbe9bcb]
+
+ * Makefile.in:
+ removed multiple entries in DISTFILES
+ [2490f4f371e6]
+
+ * visudo.c:
+ ansified the !STDC_HEADERS decls
+ [646ba06d17ae]
+
+ * find_path.c, getcwd.c, getwd.c, putenv.c, strdup.c:
+ don't do malloc decl if gnuc
+ [f1bad1925f98]
+
+ * sudo.c:
+ can't use getopt(3) since it munges args to the command to be run as
+ root don't do malloc decl if gnuc
+ [38e78f6da14e]
+
+ * find_path.c, getcwd.c, getwd.c, putenv.c, strdup.c, sudo.c,
+ sudo_realpath.c, sudo_setenv.c:
+ ansi-fied !STDC_HEADER function prottypes
+ [51d8cad89976]
+
+ * getcwd.c, getwd.c:
+ added missing paren
+ [6a1fae70e27e]
+
+ * Makefile.in:
+ added putenv.c to DISTFILES
+ [a5e4523eabbb]
+
+ * sudo_setenv.c:
+ added params to func decls when STDC_HEADERS is not defined now can
+ count on putenv() being there
+ [fd587796189b]
+
+ * sudo_realpath.c:
+ took out errno decl since sudo.h does it for us fixed up a next cc
+ warning added params to func decls when STDC_HEADERS is not defined
+ [70fa5152ace6]
+
+ * sudo.h:
+ took out environ extern added local declaratio of putenv() if local
+ version is needed
+ [a84bae6c020d]
+
+ * find_path.c, getcwd.c, getwd.c, strdup.c, sudo.c:
+ added params to func decls when STDC_HEADERS is not defined
+ [f406f0e47ac0]
+
+ * config.h.in:
+ added memcpy check check to see that ansi vs bsd macros are ntot
+ already defiend before defining (ie: avoid redefinition)
+ [879ae026e19f]
+
+ * configure.in:
+ removed fluff setenv check plus check w/ replace for putenv if also
+ no setenv
+ [e3c03814ad4b]
+
+ * putenv.c:
+ Initial revision
+ [3cff63e2dc1b]
+
+1994-08-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo_setenv.c:
+ Initial revision
+ [4d637631fa6b]
+
+ * sudo.h:
+ rm'd s realp[ath added sudo_realpath and sudo_setenv
+ [07ba001ff57e]
+
+ * sudo.c:
+ now use sudo_setenvc
+ [fd81e04d5ef0]
+
+ * configure.in:
+ added puteenv and setenv, removed realpath
+ [27bfacfb513b]
+
+ * config.h.in:
+ added putenv & setenv
+ [515f14eaf6e4]
+
+ * Makefile.in:
+ added sudo_setenv
+ [217731a717c5]
+
+ * version.h:
+ ++
+ [eadb346d7129]
+
+1994-08-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ added MAN_POSTINSTALL and /usr/share/catman for irix
+ [2a9496c1bdba]
+
+ * Makefile.in:
+ added MAN_POSTINSTALL
+ [89b0d4695529]
+
+ * CHANGES:
+ added
+ [48c021ba8a70]
+
+ * sudo.man:
+ added SUDO_* plus new options
+ [c0759cff5683]
+
+ * CHANGES:
+ added one
+ [7d44a3922d56]
+
+ * configure.in:
+ took out shadow lib
+ [07cf3de18701]
+
+ * TODO:
+ adde done
+ [a27a578e8afe]
+
+ * visudo.c:
+ now use yyrestart() if flex now reset yylineno to 0
+ [77d67ce0b677]
+
+ * Makefile.in:
+ support for installing a cat page instead of a man page if no nroff
+ [44671c0fc0fa]
+
+ * configure.in:
+ now defines HAVE_FLEX fixed up man stuff so that it looks for nroff
+ to determine whether or not to install a cat or man page
+ [0562d069c135]
+
+ * config.h.in:
+ added HAVE_FLEX
+ [c5490bae39d3]
+
+ * sudo.c:
+ not set ret to MODE_RUN initially
+ [88b4983c195b]
+
+ * find_path.c:
+ made command (and therefor cmnd dynamically allocated)
+ [95b82e32b6de]
+
+ * TODO:
+ did #8
+ [fb6f41308cdf]
+
+ * version.h:
+ ++
+ [14112ecab5ae]
+
+ * sudo_realpath.c:
+ changed bufs from MAXPATHLEN to MAXPATHLEN+1
+ [0ad4f34e55c0]
+
+ * sudo.h:
+ added MODE_ removed validate_only and added remove_timestamp()
+ [dd5f99c57728]
+
+ * sudo.c:
+ usage() now takes an int (exit value) added parse_args() to parse
+ command line arguments moved call to find_path() from load_globals
+ to new function load_cmnd() removed validate_only global -- now use
+ the concept of "modes" added -h and -k options
+ [c3887090b28a]
+
+ * parse.c:
+ no longer use global validate_only now checks for command called
+ "validate" removed check for non-fully qualified commands since that
+ is done by find_path
+ [7d56fbd26369]
+
+ * find_path.c:
+ changed MAXPATHLEN r to MAXPATHLEN+1
+ [a86e8664d971]
+
+ * find_path.c:
+ fixed off by one error with MAXPATHLEN and fixed a comment
+ [58adcef8c981]
+
+ * check.c:
+ check_timestamp no longer runs reminder(), it is implied in the
+ return val added remove_timestamp()
+ [42ab5a77066f]
+
+ * CHANGES:
+ updated
+ [8e69b31df024]
+
+1994-08-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * BUGS:
+ fixed on
+ [bc34f1ac4280]
+
+ * sudo_realpath.c:
+ took out old_errno
+ [a168d00a0768]
+
+ * CHANGES:
+ updated
+ [04ba80922df7]
+
+1994-08-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ moved send_mail to after syslog
+ [4d4188087834]
+
+ * sudo.c:
+ now set SUDO_ envariables
+ [e5963f1bd3bb]
+
+1994-08-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * version.h:
+ ++
+ [2a4534845d8c]
+
+ * sudo_realpath.c:
+ now print error if chdir fails
+ [0d75c8973d49]
+
+ * find_path.c:
+ removed an XXX
+ [e2077bcb35aa]
+
+1994-07-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ updated
+ [e30a2b39b41a]
+
+ * configure.in:
+ no more static binaries for aix
+ [77a0beb6bd80]
+
+1994-07-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * INSTALL:
+ fixed typo
+ [ba5e0d391bc4]
+
+ * sudo_realpath.c:
+ took out stuff not needed for sudo now does be_root/be_user itself
+ now uses cwd global
+ [4f6d4641d793]
+
+ * version.h:
+ +=2
+ [97da927b297c]
+
+ * logging.c, sudo.c:
+ be_root/be_user is now down in sudo_realpath()
+ [f331662fa50f]
+
+ * logging.c, sudo.h:
+ now works with 4.2BSD syslog (blech)
+ [98e39d89dd36]
+
+ * find_path.c:
+ now use sudo_realpath()
+ [ab436a8ebd02]
+
+ * config.h.in:
+ took out realpth() stuff since we now use sudo_realpath()
+ [8de5ef9f6044]
+
+ * configure.in:
+ ultrix enhanced sec
+ [815fb7fffcc0]
+
+ * SUPPORTED:
+ added ultrix enhanced sec.
+ [6466766c8062]
+
+ * INSTALL:
+ updated
+ [d681a634297a]
+
+ * check.c:
+ ultrix enhanced security suport
+ [f10c8decbcc2]
+
+ * Makefile.in:
+ added sudo_realpath.c
+ [6b9bcd3be022]
+
+ * CHANGES:
+ updated
+ [2fa8084c1b53]
+
+ * tgetpass.c:
+ increased passwd len to 24 for c2 security
+ [ec64838be62d]
+
+ * BUGS:
+ updated BUGS
+ [ca00d8fec2ce]
+
+1994-07-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ now use user global var
+ [568769719013]
+
+ * configure.in:
+ took out -ls
+ [490a44180d5f]
+
+1994-07-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ added AFS libs
+ [4fb40c8c01ba]
+
+ * sudo.h:
+ user is now a char * added epasswd
+ [27a919fafdfb]
+
+ * sudo.c:
+ added tzset() to load_globals added epasswd (encrypted password)
+ global made user dynamically allocated
+ [b99ef9bdbfce]
+
+ * configure.in:
+ added tzset test
+ [27592dd1214b]
+
+ * config.h.in:
+ added HAVE_TZSET
+ [b13f4213f3d0]
+
+ * check.c:
+ cleaned up encrypted passwd grab somewhat
+ [c8ba9a4db38a]
+
+ * configure.in:
+ fixed AFS typo
+ [2bfcbce237b6]
+
+ * INSTALL:
+ added AFS not
+ [80c67329393c]
+
+ * CHANGES:
+ udpated
+ [2f09ecdd5d31]
+
+ * logging.c:
+ can now log to both syslog & a file
+ [4d5c0932bc01]
+
+ * sudo.h:
+ added BOTH_LOGS
+ [623c539be824]
+
+ * CHANGES:
+ updated
+ [a1c7f5ef3616]
+
+ * configure.in:
+ --with-AFS
+ [28718d8f5daf]
+
+ * config.h.in:
+ added HAVE_AFS
+ [2e32bb4e63e4]
+
+ * check.c:
+ added afs changes
+ [fe4d0ff320a2]
+
+ * sudo.h:
+ removed AFS stuff :-)
+ [a40387e6fa27]
+
+ * tgetpass.c:
+ include sys/select for AIX
+ [f32c5a8f2c84]
+
+ * sudo.h:
+ added AFS
+ [da2ab3dd0348]
+
+ * version.h:
+ ++
+ [452d4dfe25af]
+
+1994-07-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES, SUPPORTED:
+ updated
+ [e7dfe6f23a37]
+
+ * logging.c:
+ can now have MAILER undefined
+ [1d33b98b35e1]
+
+ * INSTALL:
+ new sub-note about MAILER
+ [d35c636a0574]
+
+ * sudo.man:
+ added blurb about password timeout
+ [70c2ee50de20]
+
+ * configure.in:
+ convex c2 changes
+ [367138a6232e]
+
+ * aclocal.m4:
+ took out duplicate define of _CONVEX_SOURCE
+ [647182138450]
+
+ * Makefile.in:
+ added OSDEFS
+ [7fdcd50602d1]
+
+ * config.h.in:
+ added spaces
+ [f2b8a05e48f3]
+
+ * tgetpass.c:
+ added a goto if fgets fails
+ [68a6586d9c45]
+
+ * sudo.h:
+ use __hpux not hpux convex c2 stuff
+ [5c377a8d5f34]
+
+ * sudo.c:
+ use __hpux not hpux
+ [9363bc0f9f9e]
+
+ * logging.c:
+ convex c2 stuff
+ [ea5630975ac4]
+
+ * config.h.in:
+ define ansi-ish cpp os defines if non-ansi are defined for hpux &
+ convex
+ [664f53a5e786]
+
+ * INSTALL:
+ updated to say we support sonvex C2
+ [5f2f8b87013e]
+
+ * check.c:
+ added convex c2 support
+ [9a665d4918fa]
+
+1994-07-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * tgetpass.c:
+ no more ioctl never returns NULL uses fgets() and select() to
+ timeout
+ [b333e6d63e97]
+
+1994-06-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ things were testing -n "$GCC" instead of -z "$GCC"
+ [059a9b15ede2]
+
+ * tgetpass.c:
+ now works + uses fgets()
+ [353d7ebcb7bb]
+
+1994-06-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * tgetpass.c:
+ select doesn't seem to recognize a single '\n' as input waiting so
+ we can;t use it, sigh.
+ [f76e3218b835]
+
+1994-06-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * PORTING:
+ updated tgetpass() blurb
+ [95baac736b49]
+
+ * configure.in:
+ added --with-getpass
+ [42ac0bdf58ed]
+
+ * Makefile.in:
+ added tgetpass stuff
+ [e2b38c635663]
+
+ * tgetpass.c:
+ now uses stdio
+ [36af8ff66e35]
+
+ * version.h:
+ ++
+ [4e81c9db19bd]
+
+1994-06-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * PORTING:
+ updated ,.
+ [54f523770a05]
+
+ * config.h.in:
+ added USE_GETPASS && HAVE_C2_SECURITY
+ [86b355cb2953]
+
+ * configure.in:
+ fixed a test aded --with-C2 and --with-tgetpass
+ [abf6181588ef]
+
+ * check.c:
+ added hpux C2 shit
+ [20d4177ffa88]
+
+ * Makefile.in:
+ took out tgetpass.*
+ [cc82fd9984b4]
+
+ * INSTALL:
+ added C2 blurb
+ [1d2bfc35e4b6]
+
+1994-06-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ no termio(s) for ultrix since it is broken
+ [d3e82e835350]
+
+ * check.c:
+ added a space (yeah, anal)
+ [05e4b31ca68c]
+
+ * realpath.c, sudo_realpath.c:
+ fixed it (duh, rtfm)
+ [f13097cb8cb6]
+
+1994-06-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in:
+ took out bsd signal stuff for irix
+ [e179cdafc97a]
+
+ * visudo.c:
+ comments in #endif
+ [e3a629190f5e]
+
+ * configure.in:
+ don't define BSD signals for irix
+ [3ce57bffb7f0]
+
+ * TODO:
+ did some...
+ [274241cd0f74]
+
+ * CHANGES:
+ updated
+ [8f29fc755faf]
+
+ * realpath.c, sudo_realpath.c:
+ took out unneeded code by changing where a strings was terminated
+ [b5564d62d30e]
+
+1994-06-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * realpath.c, sudo_realpath.c:
+ fix bug where /dirname would return NULL
+ [b85f470daf26]
+
+ * sudo.h:
+ move __P to config.h
+ [7763c0ff3f28]
+
+ * getcwd.c, getwd.c, realpath.c, sudo_realpath.c:
+ added errno definition
+ [4cc9d2d9782a]
+
+ * config.h.in:
+ added __P
+ [ca06f5aa58f3]
+
+ * config.h.in:
+ added HAVE_FCHDIR
+ [206d714641e0]
+
+ * strdup.c:
+ now include stdio
+ [0d8458da0e1d]
+
+ * realpath.c, sudo_realpath.c:
+ now works if no fchdir
+ [e035911b6722]
+
+ * visudo.c:
+ define SA_RESETHAND to null if not defined
+ [afec03e84342]
+
+ * configure.in:
+ added check & replace
+ [c1a65481441c]
+
+ * configure.in:
+ took out -static for nextstep -- it doesn't work
+ [fa1a1a611743]
+
+1994-06-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ moved #endif to where it belongs
+ [07d3a8972097]
+
+ * SUPPORTED:
+ correction
+ [0c1ecba3e5a3]
+
+ * configure.in:
+ now checks for strdup realpath getcwd bzero
+ [f029a1917515]
+
+ * config.h.in:
+ emulate bzero
+ [d792352e44a3]
+
+ * visudo.c:
+ added posic signals
+ [2ed0005f90fc]
+
+ * tgetpass.c:
+ bzero cast
+ [6d91b1a1526f]
+
+ * logging.c:
+ added posix signals
+ [67ede9c22a05]
+
+ * configure.in:
+ removed BROKEN_GETPASS added new srcs toreplace missing functions
+ [cf44274bb1c8]
+
+ * config.h.in:
+ added posix signal stuff
+ [a3c1c98fe8ef]
+
+ * Makefile.in:
+ added new srcs
+ [b6a079afee47]
+
+ * visudo.c:
+ updated useag
+ [589ed091c44f]
+
+ * tgetpass.c:
+ now uses posix signals
+ [30f74964074f]
+
+ * PORTING:
+ updated sto reflect major changes
+ [bcfc309e017b]
+
+ * CHANGES, TODO:
+ updated
+ [23aacbd54278]
+
+ * tgetpass.c:
+ uses sysconf() if available
+ [a27431c90bab]
+
+ * sudo.h:
+ added PASSWORD_TIMEOUT + prototypes for new functions
+ [d7473c2f77c4]
+
+ * realpath.c, sudo_realpath.c:
+ for those w/o this in libc
+ [1e47aa7a9d46]
+
+ * getcwd.c, getwd.c:
+ Initial revision
+ [c90dea57a84f]
+
+ * find_path.c:
+ rewrote to use realpath(3) - nis now all my code
+ [d2c3bb8fb37d]
+
+ * config.h.in:
+ added HAVE_REALPATH
+ [02c10352a8c7]
+
+ * check.c:
+ now use tgetpass
+ [b5c021fc179f]
+
+ * Makefile.in:
+ added LIBOBJS use tgetpass.c
+ [230a7b3eeaa3]
+
+1994-06-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * tgetpass.c:
+ works now :-)
+ [025e7a3875ba]
+
+ * tgetpass.c:
+ Initial revision
+ [3316ab33b230]
+
+ * pathnames.h.in:
+ added /dev/tty
+ [29242585e53f]
+
+1994-06-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * version.h:
+ incremented
+ [f2e54b48280f]
+
+ * sudo.c:
+ always use getcwd
+ [c6068e8a4029]
+
+ * config.h.in:
+ added check for getwd
+ [ab1e102ad673]
+
+ * configure.in:
+ replace strdup & realpath & getcwd if missing
+ [b0eb14f2a1c3]
+
+ * pathnames.h.in:
+ added _PATH_PWD
+ [309d2388f69a]
+
+ * aclocal.m4:
+ added SUDO_PROG_PWD
+ [e16e85deb96c]
+
+ * strdup.c:
+ Initial revision
+ [810efdc15007]
+
+ * realpath.c, sudo_realpath.c:
+ Initial revision
+ [d85eee438e09]
+
+1994-06-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ quoted quare brackets
+ [d0e7ca111d98]
+
+1994-06-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ no need to strdup() a constant
+ [a8c44712df9a]
+
+ * CHANGES:
+ updated
+ [71364129cca0]
+
+ * sudo.man:
+ added validate
+ [0bb198095a26]
+
+ * sudo.c:
+ added -v to usage
+ [31ea71f11dbb]
+
+ * parse.c, sudo.c, sudo.h:
+ added validate_only stuff
+ [9bcd853d3c90]
+
+1994-05-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ now finds sed
+ [6374bb0d3f28]
+
+ * aclocal.m4:
+ $OSREV is now an int
+ [ace0666d66cf]
+
+1994-05-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ added mtxinu to caser
+ [73a776887b16]
+
+ * sudo.h:
+ added EXEC macro
+ [2e8eb28b710a]
+
+ * sudo.c:
+ now use the EXEC nmacro now only do a gethostbyname() if FQDN is set
+ [56afb4f658d5]
+
+ * logging.c:
+ changed mail_argv[] def now use EXEC() macro
+ [ddcabd28edb1]
+
+ * check.c:
+ took out crypt() definition
+ [0e657724cf5f]
+
+ * version.h:
+ upped the version
+ [62c5d66119fc]
+
+ * configure.in:
+ always look for -lnsl
+ [d7b594f0313b]
+
+ * aclocal.m4:
+ added an echo
+ [1caae3491dc5]
+
+ * sudo.h:
+ SHORT_MESSAGE is now the default
+ [cfce35c3119a]
+
+ * config.h.in:
+ fixed typo
+ [6499a564bf75]
+
+ * configure.in:
+ added missing AC_DEFINE(SVR4) for solaris
+ [feef0b17b94f]
+
+ * sudo.man:
+ documented the -v flag
+ [a6429f2bc2cf]
+
+ * SUPPORTED:
+ updated
+ [088886e79540]
+
+ * check.c:
+ proto-ized crypt()
+ [801e4ff5b121]
+
+ * config.h.in:
+ added LIBSHADOW undef
+ [8df588e9ee2b]
+
+ * configure.in:
+ nwo set OS to be lowercase
+ [561ebed833e4]
+
+1994-05-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ now use SUDO_OSTYPE to set $OS
+ [0e60aee23098]
+
+ * aclocal.m4:
+ now use uname to determine os
+ [99705e58d400]
+
+ * visudo.c:
+ added prototypes & moved sig handler around
+ [1f0bc8d23b51]
+
+ * sudo.h:
+ added prototyppes
+ [be3935a2b163]
+
+ * check.c, logging.c, sudo.c:
+ added prototypes
+ [2079b4605ab8]
+
+ * parse.c:
+ added comment
+ [a34d147d8399]
+
+ * config.h.in:
+ nwo use _BSD_SIGNALS not _BSD_COMPAT
+ [63663195f047]
+
+ * aixcrypt.exp:
+ Initial revision
+ [890aed08357e]
+
+ * Makefile.in:
+ added aixcrypt.exp
+ [1005a183105f]
+
+ * parse.lex, parse.yacc:
+ moved config.h to top of includes
+ [9569c49aa5f3]
+
+1994-05-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * find_path.c:
+ now don't bitch if get EACCESS (treat like EPERM)
+ [dbeffb638de4]
+
+ * visudo.c:
+ added -v flag and usage()
+ [4d44ed60ed75]
+
+ * version.h:
+ fixed a typo
+ [cf3f9347ae41]
+
+ * sudo.c:
+ cast Argv to a const for exec added -v flag
+ [d11b6efc0e45]
+
+ * logging.c:
+ mail_argv is now a const
+ [93bb5d90bb6f]
+
+ * configure.in:
+ only set RETSIGTYPE if it is not set already
+ [c97aac260b77]
+
+ * aclocal.m4:
+ now defines & STDC_HEADERS for Irix
+ [9c2b24ad1fc5]
+
+ * Makefile.in:
+ added version.h
+ [9f79e880229a]
+
+ * insults.h, sudo.h:
+ prevent multiple inclusion
+ [d68c8a9243ce]
+
+ * version.h:
+ Initial revision
+ [dbb39c5ef8d9]
+
+ * parse.lex, parse.yacc:
+ now includes config.h
+ [f117e036a56b]
+
+ * aclocal.m4:
+ now talks about sunos 4.x
+ [c9054aa92d4e]
+
+ * visudo.c:
+ calls to Exit now pass an arg
+ [a92104670551]
+
+1994-05-24 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ signal handler now takes an int argument
+ [26f480c41523]
+
+ * CHANGES:
+ updated
+ [8c166a9d796b]
+
+ * sudo.c:
+ ok, the getcwd() is now *really* done as the user
+ [ab86cf85134a]
+
+ * configure.in:
+ changed AIX STATIC_FLAGS
+ [b9c0a3ba5663]
+
+ * aclocal.m4:
+ solaris now defines SVR4
+ [c3e20cac96f5]
+
+ * sudo.h:
+ added cwd and fixed stupid core dump that makes no sense. sigh.
+ [7a9755436dbb]
+
+ * sudo.c:
+ moved getcwd stuff into load_globals
+ [ec2bc90df1f3]
+
+ * parse.c:
+ took out externs that are in suod.h
+ [93c4b3f856d7]
+
+ * logging.c:
+ moved cwd into load_globals
+ [050de754d228]
+
+ * find_path.c:
+ moved cwd stuff
+ [22f3f3b4c34d]
+
+ * Makefile.in:
+ fixed make distclean & realclean
+ [c9964d89bcef]
+
+ * TODO:
+ updated .,
+ [e513581ef0e3]
+
+ * CHANGES:
+ added solaris changes
+ [505d930daf27]
+
+ * aclocal.m4:
+ added solaris changes, need to rework
+ [33f20fb16c49]
+
+ * configure.in:
+ cleaned up for solaris
+ [2fb8cfa05d0f]
+
+ * logging.c:
+ reinstall reapchild signal handler for non-bsd signals
+ [3d1dc545113d]
+
+ * sudo.h:
+ took out getdtablesize() emulation for HP-UX (no longer needed)
+ [1fc83d170f34]
+
+ * sudo.c:
+ support for HAVE_SYSCONF
+ [50ca2a7a224a]
+
+ * visudo.c:
+ added <fcntl.h> for solaris & reorg'd the includes + minor prettying
+ up /
+ [0a570e826dd4]
+
+ * config.h.in:
+ added HAVE_SYSCONF
+ [2b9a9f3a4e94]
+
+1994-05-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ now tells you what os you are running /.
+ [06c6332a895b]
+
+ * aclocal.m4:
+ took out extra ','
+ [e8c75ce59f4a]
+
+1994-05-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * config.h.in:
+ added _BSD_COMPAT
+ [73c5099806c2]
+
+ * aclocal.m4:
+ fixed for irix5
+ [1047d1f6c0eb]
+
+ * CHANGES:
+ updated
+ [1bc4969fee96]
+
+ * sudo.c:
+ uid seinitialized to -2
+ [8d7812b1878b]
+
+1994-04-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ now removes LIBPATH for AIX
+ [075392eb1dd9]
+
+1994-03-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * configure.in:
+ now uses ufc if it finds it
+ [ab6ce30a5958]
+
+1994-03-12 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.h:
+ no longer define yyval & yylval since yacc does it
+ [09d250aea50a]
+
+ * parse.lex:
+ now defines yylval as extenr
+ [8ec2b88952bc]
+
+ * configure.in:
+ BROKEN_GETPASS is now an OPTION
+ [3714f4bb8312]
+
+ * config.h.in:
+ took out BROKEN_GETPASS
+ [9c4f6aa50137]
+
+ * Makefile.in:
+ took out big comment
+ [4c13cff0e556]
+
+ * README:
+ updated
+ [b8b9902b620d]
+
+ * Makefile.in:
+ took out README.beta
+ [ed2cd861e82b]
+
+ * SUPPORTED:
+ Initial revision
+ [2fffc51e6606]
+
+ * INSTALL:
+ now reference SUPPORTED .,
+ [d112c30be1f2]
+
+ * config.h.in:
+ now check for convex OR __convex__
+ [a0e5701a3069]
+
+ * aclocal.m4:
+ now check for convex or __convex__
+ [5dae2bfbe3bc]
+
+ * Makefile.in:
+ added dist target
+ [400a54de57db]
+
+ * aclocal.m4:
+ use __convex__
+ [58a19470ed0b]
+
+ * find_path.c:
+ now use _S_* stat stuff to be ansi-like
+ [28cce560e048]
+
+ * INSTALL:
+ updated for configure directions
+ [a034ccc7c30a]
+
+ * Makefile.in:
+ distclean now removes config.h and pathnames.h
+ [300f2349b4ab]
+
+ * CHANGES:
+ updated
+ [646f7e9430c1]
+
+ * TODO:
+ fixed typoe
+ [70fd6361b2bc]
+
+ * visudo.c:
+ updated version
+ [cf13d87d789f]
+
+ * Makefile.in:
+ updated version
+ [8c5dacc27a7a]
+
+ * config.h.in, pathnames.h.in:
+ added copyright header
+ [747ce3d3d6b7]
+
+ * check.c, find_path.c, insults.h, logging.c, parse.c, parse.lex,
+ parse.yacc, sudo.c, sudo.h:
+ udpated version
+ [4751c39bad18]
+
+ * visudo.c:
+ udpated to use configure + pathnames.h
+ [d45dff76a1cd]
+
+ * aclocal.m4:
+ updated
+ [f05a367a55be]
+
+ * Makefile.in, config.h.in, configure.in:
+ updated
+ [524778598879]
+
+ * sudo.h:
+ now works with configure
+ [83fc40e533f4]
+
+ * check.c, find_path.c, getpass.c, logging.c, parse.c, sudo.c:
+ updated to work with configure + pathnames.h
+ [cb67fa6ab52d]
+
+ * Makefile.in:
+ added LEXLIB
+ [f43cad4ab0a2]
+
+1994-03-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * COPYING:
+ updated gnu general licence to versio 2
+ [2b0b56112ddc]
+
+ * config.h.in, pathnames.h.in:
+ Initial revision
+ [4b586f39ec2d]
+
+ * sudo.h:
+ changed to work with configure
+ [13f3506ddf16]
+
+1994-03-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * Makefile.in, aclocal.m4, configure.in:
+ Initial revision
+ [a8636ae77371]
+
+ * visudo.c:
+ now uses defines used by configure
+ [de438d118993]
+
+1994-03-01 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * find_path.c:
+ sudo won't bitch about EPERM now, for real
+ [ce26d9ef7e3f]
+
+1994-02-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * logging.c:
+ renamed exec_argv to eliminate a libc name clash with ksros
+ [bcb4350d8411]
+
+ * CHANGES:
+ corrected
+ [dae68d422efd]
+
+ * logging.c, sudo.c, sudo.h:
+ execve -> execv
+ [40cc2c4bdb15]
+
+ * TODO:
+ upated
+ [9275a8b8fc45]
+
+ * PORTING:
+ added 2 mroe items
+ [6cbb5c56993c]
+
+ * CHANGES:
+ updated
+ [73f34f8e571a]
+
+ * sudo.h:
+ added UMASK and mode_t declaration
+ [7c2015e1d171]
+
+ * sudo.c:
+ added UMASK
+ [d37be7523680]
+
+ * logging.c:
+ now opens log file with mode 077
+ [0825cc3ee841]
+
+ * check.c:
+ saved current umask ans restores it
+ [659c1aaae8e8]
+
+ * sudo.h:
+ added MAXLOGFILELEN
+ [34331c7dee90]
+
+ * logging.c:
+ split long log lines. FOr syslog, split into multiple entries, for a
+ log file, indent the extra for readability
+ [72c9e4cdba6e]
+
+1994-02-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ added changes
+ [81196833673d]
+
+ * sudo.h:
+ MAXLOGLEN & MAXSYSLOGLEN are now different (as they should be)
+ [1aa69e903840]
+
+1994-02-25 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TODO:
+ added input from Brett M Hogden <hogden@rge.com>
+ [80f01fc88ce9]
+
+1994-02-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ added rmenv() to remove stuff from environ. can now uses execvp() OR
+ execve() becuase of this.
+ [e7fc2535bd67]
+
+ * logging.c:
+ now uses execvp() OR execve()
+ [56391aa1f99d]
+
+ * sudo.h:
+ added USE_EXECVE
+ [f21f38050b95]
+
+ * sudo.h:
+ added environ
+ [6b805e23c6f6]
+
+ * find_path.c:
+ now ignore EPERM
+ [c8fd7117a1d7]
+
+ * sudo.h:
+ moved some func decls out of sudo.h and into sudo.c as statics /.
+ [5f555c267d27]
+
+ * CHANGES:
+ updated
+ [431f478af320]
+
+ * sudo.h:
+ took out Envp
+ [6f722be7793d]
+
+1994-02-14 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * BUGS:
+ Initial revision
+ [4a8ecf0da95c]
+
+1994-02-10 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ added SECURE_PATH
+ [1c72cb222609]
+
+ * sudo.c, sudo.h:
+ added SECURE_PATH
+ [5bf5357a63c5]
+
+ * sudo.h:
+ added SECURE_PATH
+ [3976a74405ac]
+
+ * INSTALL:
+ added sample.sudoers note
+ [1b395d29aaeb]
+
+ * sudoers:
+ Initial revision
+ [485888d07477]
+
+1994-02-09 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * find_path.c:
+ fixed typo
+ [bfc3cc4d41ca]
+
+ * PORTING:
+ took out SAVED_UID garbage
+ [b7c2d3469661] [SUDO_1_3_0]
+
+ * INSTALL:
+ mentioned HAL
+ [253d6695df90]
+
+ * sudo.h:
+ added HAL line
+ [29ec1a4ac6de]
+
+ * insults.h:
+ added HAL insults
+ [7d7c96d77c74]
+
+ * TODO:
+ updated
+ [aa2ed9790586]
+
+ * logging.c:
+ more verbose error if mailer not found
+ [fca47fd00cb6]
+
+ * check.c:
+ now do getpwent as root for soem shadow password systems (bsdi)
+ [e0339e110d46]
+
+1994-02-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.h:
+ took out SAVED_UID garbade
+ [fcb0e81dcdb5]
+
+ * sudo.c:
+ took out SAVED_UID garbage since it don't work
+ [507e9513e9c2]
+
+1994-02-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * README:
+ updated
+ [d2b6b253dae5]
+
+ * insults.h:
+ added a missing space :-)
+ [8940ea991f87]
+
+ * sudo.c, sudo.h:
+ took out multimax cruft
+ [c2606b365181]
+
+ * INSTALL:
+ minor update
+ [05fb6ee73131]
+
+ * PORTING:
+ finished
+ [c4ac47c84dc5]
+
+ * sudo.c:
+ fixed a typo + indentation
+ [7eab40aae8fa]
+
+1994-02-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.h:
+ took outumoved some defines to the config file ,. ,.
+ [defff05beb52]
+
+ * PORTING:
+ Initial revision
+ [c803e9127959]
+
+ * TODO:
+ did #6
+ [c6fa1c946c31]
+
+ * sudo.h:
+ added HAS_SAVED_UID
+ [6a88a39c0a07]
+
+ * sudo.c:
+ put back AIX cruft
+ [a24d2507ddd4]
+
+1994-02-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ aix changes
+ [1663915f754a]
+
+1994-02-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * CHANGES:
+ updated
+ [a8cc73747cae]
+
+ * check.c, logging.c, parse.c, sudo.c, sudo.h:
+ now is only root when abs necesary
+ [3c9d12c5cdfe]
+
+ * check.c:
+ added missing %s\n
+ [609320b72d89]
+
+1994-01-31 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * install-sh:
+ Initial revision
+ [b5bba140a175]
+
+ * TODO:
+ updated
+ [c9d2eba602af]
+
+ * CHANGES:
+ updated
+ [932f1fc3bb14]
+
+ * sudo.c:
+ now removed _RLD_* for alphas
+ [54a36e648158]
+
+ * INSTALL:
+ updated for new config scheme
+ [61c8ae800444]
+
+ * find_path.c:
+ more verbose eror messages
+ [b4fd123db42d]
+
+1994-01-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * TODO:
+ now have solaris
+ [371002fbf266]
+
+ * sudo.h:
+ define __svr4__ for SOLARIS
+ [0b5cf5ed936d]
+
+ * check.c:
+ added svr4 junk for shadow pws for solaris 2.x
+ [91ed58f21618]
+
+ * check.c, sudo.c:
+ took out setuid(0) and setreuid(udi) garbage. Its not needed since
+ we start out setuid with the correct perms.
+ [07689e782b0b]
+
+ * check.c, sudo.c, sudo.h:
+ now use setreuid()
+ [7d64d685d78e]
+
+1994-01-26 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.man:
+ revised AUTHORS secrtion & added ENV_EDITOR stuff to VARIABLES
+ sectoin
+ [b26967b1e19b]
+
+ * visudo.c:
+ now uses ENV_EDITOR if you want to use the EDITOR envar
+ [a4f8fcb9bd1d]
+
+ * sudo.h:
+ now uses ENV_EDITOR if you want to use the EDITOR envar >> .
+ [028cc55c4328]
+
+1993-12-07 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * README:
+ minor update + spell fix
+ [a411717a7249]
+
+ * INSTALL:
+ rewrote most of this
+ [a6750923f9c9]
+
+ * sudo.h:
+ added all options that are in the Makefile
+ [6db3b3b841b3]
+
+ * getpass.c:
+ now use USE_TERMIO #define for sgi & hpux
+ [b91f89ae6be1]
+
+ * TODO:
+ todo: posix sigs
+ [4548a56eb2ef]
+
+1993-12-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c, find_path.c:
+ always include strings.h
+ [1fc20bda92c0]
+
+ * visudo.c:
+ added STATICEDITOR
+ [0596f820716e]
+
+ * sudo.h:
+ sgi has vi in /usr/bin too
+ [94203b62bfd9]
+
+ * sudo.man:
+ added VISUAL
+ [87c2844c4cac]
+
+1993-12-03 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.h:
+ sue /usr/bin/vi on some systems
+ [e3ad9190f35e]
+
+ * sudo.c:
+ fixed warning (include strings.h)
+ [0b896de4d8a0]
+
+ * sudo.man:
+ added John_Rouillard@dl5000.bc.edu's changes (new features)
+ [f41b4205a8cf]
+
+ * CHANGES:
+ changes from John_Rouillard@dl5000.bc.edu
+ [6bdef8e948d5]
+
+ * visudo.c:
+ added EDITOR envar
+ [5c4bf716de21]
+
+ * check.c, find_path.c, parse.c, sudo.c:
+ added patches from John_Rouillard directory spec uses EDITOR
+ [f62a435f8c41]
+
+1993-12-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * getpass.c:
+ added flush for hpux
+ [07cfdd6a7b55]
+
+1993-11-30 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ no longer assume malloc returns a char *
+ [7480bd2756f3]
+
+ * sudo.c:
+ alpha change to remove LD_-like thing fixed SHLIB_PATH stuff -- now
+ gets removed correctly
+ [8587166c6ac8]
+
+ * sudo.h:
+ added STD_HEADERS macro
+ [480f5a9a516c]
+
+ * sudo.c:
+ now uses STD_HEADERS macor for ansi
+ [c5018806fd59]
+
+ * find_path.c:
+ now uses STD_HEADERS macro
+ [ad821e0788ea]
+
+ * check.c:
+ niceties for C compiler bitches -- no real change
+ [0fc0b1a5fb64]
+
+1993-11-29 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ now doesn't fclose a file never opened.
+ [ee888ec9427d]
+
+1993-11-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.man:
+ added visudo line
+ [698d51c66407]
+
+ * sudo.man:
+ added error stuff added me in there...
+ [d202fd34b906]
+
+ * CHANGES:
+ noted insults
+ [998a22c2230c]
+
+ * INSTALL:
+ added blurb about reading stuff
+ [e71db100798f]
+
+ * sudo.h:
+ added insults
+ [c110431cec56]
+
+ * insults.h:
+ corrected somments and removed newlines
+ [493706fd488c]
+
+ * check.c:
+ now uses insults
+ [6d23cf06a0ef]
+
+ * insults.h:
+ Initial revision
+ [83153c26b4a3]
+
+ * INSTALL:
+ added dec syslog note
+ [555437273237]
+
+ * sample.sudoers:
+ added real stuff in there
+ [53442a7fba78]
+
+ * TODO:
+ added a todo
+ [c630472bd4dc]
+
+ * TODO:
+ added one
+ [806464453284]
+
+1993-11-27 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sample.sudoers:
+ Initial revision
+ [7db0a9f1ca8f]
+
+ * sudo.man:
+ updated with changes
+ [d9bf254c6c08]
+
+ * sudo.man:
+ Initial revision
+ [dd6f11174ac6]
+
+ * indent.pro:
+ Initial revision
+ [dbfbb494fad9]
+
+ * CHANGES, COPYING, INSTALL, README, TODO:
+ Initial revision
+ [6d98f489a079]
+
+ * visudo.c:
+ updated version number and took out jeff's old addr since it is no
+ good
+ [ee47c24818cb]
+
+ * check.c, find_path.c, logging.c, parse.c, parse.lex, parse.yacc,
+ sudo.c, sudo.h:
+ updated version number and took out jeff's email (since it is
+ invalid)
+ [54616458a52e]
+
+1993-10-28 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ added fflush()
+ [145c881f4fb4]
+
+1993-10-23 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * find_path.c:
+ now return NULL instead pfof exiting for nopnn-fatal errors
+ [8bc74f8cb1ae]
+
+1993-10-21 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * check.c:
+ new banner
+ [5387ab2af516]
+
+ * parse.lex:
+ now sudo.h gets included first
+ [2acb01c18e18]
+
+1993-10-18 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.lex:
+ now can use flex
+ [164d3839adf0]
+
+ * sudo.h:
+ linux patch
+ [f1b6b1b1a2ca]
+
+ * sudo.c:
+ hpux 9 fix, removes SHLIB_PATH linux patch
+ [67611dc1737f]
+
+ * check.c:
+ linux diff
+ [c24536682397]
+
+1993-10-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * find_path.c:
+ stat now ignores EINVAL
+ [c7761a5dc642]
+
+1993-10-06 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * find_path.c, sudo.c:
+ now declare strdup as extern
+ [6b7d6f8784b5]
+
+1993-10-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * visudo.c:
+ reformatted with indent + by hand
+ [9d43084e4990]
+
+ * check.c, find_path.c, getpass.c, logging.c, parse.c, sudo.c, sudo.h:
+ used indent to "fix" coding style
+ [489ffacbdc70]
+
+ * find_path.c:
+ now checks '.' or '.' or '' in PATH -- but does it LAST should maybe
+ move the code that does this into the loop body. makes it messier
+ tho. hmmm.
+ [c4d22b48da9a]
+
+1993-09-08 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * find_path.c:
+ redid the fix for non-executable files in an easier to read way plus
+ some minor aethetic changes
+ [84fe337f1426]
+
+ * find_path.c:
+ fixed bug with non-executable tings of same name in path introduced
+ by checkig errno after stat(2).
+ [c2a812cfcbc1]
+
+1993-09-05 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ fixed off by one error
+ [fabb7cee0041]
+
+ * find_path.c:
+ now handles decending below '/' correctly
+ [5d2ddfc0b220]
+
+ * sudo.c:
+ now actually builds Envp instead of munging envp
+ [bdc4b08f6898]
+
+1993-09-04 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * parse.yacc:
+ now includes sys/param.h
+ [efbb494ab4de]
+
+ * visudo.c:
+ now includes sys/param.h
+ [ad6c91d59958]
+
+ * sudo.h:
+ fixed ifndef -> ifdef
+ [7aebe822d863]
+
+ * qualify.c:
+ make more like find_path.c
+ [853b2dab2e03]
+
+ * find_path.c:
+ rewritten by millert
+ [c6a043cc11b3]
+
+ * sudo.h:
+ fixed MAXCOMMANDLENGTH now uses USE_CWD and NEED_STRDUP added info
+ about new defines in the comment
+ [39ffefce3aec]
+
+ * logging.c:
+ now uses USE_CWD
+ [fa0f3b118bb3]
+
+ * sudo.h:
+ added delc for clean_envp() and Envp
+ [a12034e300c2]
+
+ * sudo.c:
+ now rips LD_* env vars out of envp and passed sanitized Envp to exec
+ [d201a218e056]
+
+ * logging.c:
+ now uses execve()
+ [f3e01032cd33]
+
+ * find_path.c:
+ ENOTDIR is ok now too (in case part of the path is bogus)
+ [b5cbbb201bb5]
+
+ * qualify.c:
+ now works correctly (ttaltotal rewrite)
+ [0c25d64a5c68]
+
+ * parse.lex:
+ now includes sys/param.h didn't match trailing / -- fix from
+ rouilj@cs.umb.edu
+ [b6363ba110af]
+
+1993-06-11 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ moved around the #ifndef _AIX
+ [7d4330950c20]
+
+ * check.c, logging.c, parse.c:
+ Initial revision
+ [c101e9572d7f]
+
+1993-03-20 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * qualify.c:
+ Initial revision
+ [5a5f21d0e0bf]
+
+1993-03-13 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * find_path.c:
+ now works if you do sudo bin/test
+ [07835120ce43]
+
+ * find_path.c:
+ works
+ [c3da8b5efa20]
+
+1993-03-02 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.h:
+ Initial revision
+ [28a1caa38b72]
+
+ * visudo.c:
+ Initial revision
+ [0e5cd7c3cdbe]
+
+ * parse.lex, parse.yacc:
+ Initial revision
+ [5f2d0cccb06b]
+
+1993-02-16 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * sudo.c:
+ took out errno.h
+ [7466431a2655]
+
+ * sudo.c:
+ now spews error if exec fails and exits with -1
+ [e5c41ea725c1]
+
+ * sudo.c:
+ Initial revision
+ [8aeabe39a0c2]
+
+ * find_path.c:
+ now only execs files with (an) executable bit set.
+ [0a451f9c0e58]
+
+ * find_path.c:
+ Initial revision
+ [02a534891a35]
+
+1993-02-15 Todd C. Miller <Todd.Miller@courtesan.com>
+
+ * getpass.c:
+ added nice comment
+ [ea8b2aaa9389]
+
+ * getpass.c:
+ now works on sgi's
+ [bf2b7c6d0960]
+
+ * getpass.c:
+ Initial revision
+ [9f4de251c1b5]
+
diff --git a/INSTALL.configure b/INSTALL.configure
new file mode 100644
index 0000000..20beeca
--- /dev/null
+++ b/INSTALL.configure
@@ -0,0 +1,368 @@
+Installation Instructions
+*************************
+
+ Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software
+Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved. This file is offered as-is,
+without warranty of any kind.
+
+Basic Installation
+==================
+
+ Briefly, the shell command './configure && make && make install'
+should configure, build, and install this package. The following
+more-detailed instructions are generic; see the 'README' file for
+instructions specific to this package. Some packages provide this
+'INSTALL' file but do not implement all of the features documented
+below. The lack of an optional feature in a given package is not
+necessarily a bug. More recommendations for GNU packages can be found
+in *note Makefile Conventions: (standards)Makefile Conventions.
+
+ The 'configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a 'Makefile' in each directory of the package.
+It may also create one or more '.h' files containing system-dependent
+definitions. Finally, it creates a shell script 'config.status' that
+you can run in the future to recreate the current configuration, and a
+file 'config.log' containing compiler output (useful mainly for
+debugging 'configure').
+
+ It can also use an optional file (typically called 'config.cache' and
+enabled with '--cache-file=config.cache' or simply '-C') that saves the
+results of its tests to speed up reconfiguring. Caching is disabled by
+default to prevent problems with accidental use of stale cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how 'configure' could check whether to do them, and mail
+diffs or instructions to the address given in the 'README' so they can
+be considered for the next release. If you are using the cache, and at
+some point 'config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file 'configure.ac' (or 'configure.in') is used to create
+'configure' by a program called 'autoconf'. You need 'configure.ac' if
+you want to change it or regenerate 'configure' using a newer version of
+'autoconf'.
+
+ The simplest way to compile this package is:
+
+ 1. 'cd' to the directory containing the package's source code and type
+ './configure' to configure the package for your system.
+
+ Running 'configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type 'make' to compile the package.
+
+ 3. Optionally, type 'make check' to run any self-tests that come with
+ the package, generally using the just-built uninstalled binaries.
+
+ 4. Type 'make install' to install the programs and any data files and
+ documentation. When installing into a prefix owned by root, it is
+ recommended that the package be configured and built as a regular
+ user, and only the 'make install' phase executed with root
+ privileges.
+
+ 5. Optionally, type 'make installcheck' to repeat any self-tests, but
+ this time using the binaries in their final installed location.
+ This target does not install anything. Running this target as a
+ regular user, particularly if the prior 'make install' required
+ root privileges, verifies that the installation completed
+ correctly.
+
+ 6. You can remove the program binaries and object files from the
+ source code directory by typing 'make clean'. To also remove the
+ files that 'configure' created (so you can compile the package for
+ a different kind of computer), type 'make distclean'. There is
+ also a 'make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+ 7. Often, you can also type 'make uninstall' to remove the installed
+ files again. In practice, not all packages have tested that
+ uninstallation works correctly, even though it is required by the
+ GNU Coding Standards.
+
+ 8. Some packages, particularly those that use Automake, provide 'make
+ distcheck', which can by used by developers to test that all other
+ targets like 'make install' and 'make uninstall' work correctly.
+ This target is generally not run by end users.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the 'configure' script does not know about. Run './configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give 'configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here is
+an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you can use GNU 'make'. 'cd' to the
+directory where you want the object files and executables to go and run
+the 'configure' script. 'configure' automatically checks for the source
+code in the directory that 'configure' is in and in '..'. This is known
+as a "VPATH" build.
+
+ With a non-GNU 'make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use 'make distclean' before
+reconfiguring for another architecture.
+
+ On macOS 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple '-arch' options to the
+compiler but only a single '-arch' option to the preprocessor. Like
+this:
+
+ ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CPP="gcc -E" CXXCPP="g++ -E"
+
+ This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the 'lipo' tool if you have problems.
+
+Installation Names
+==================
+
+ By default, 'make install' installs the package's commands under
+'/usr/local/bin', include files under '/usr/local/include', etc. You
+can specify an installation prefix other than '/usr/local' by giving
+'configure' the option '--prefix=PREFIX', where PREFIX must be an
+absolute file name.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option '--exec-prefix=PREFIX' to 'configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like '--bindir=DIR' to specify different values for particular
+kinds of files. Run 'configure --help' for a list of the directories
+you can set and what kinds of files go in them. In general, the default
+for these options is expressed in terms of '${prefix}', so that
+specifying just '--prefix' will affect all of the other directory
+specifications that were not explicitly provided.
+
+ The most portable way to affect installation locations is to pass the
+correct locations to 'configure'; however, many packages provide one or
+both of the following shortcuts of passing variable assignments to the
+'make install' command line to change installation locations without
+having to reconfigure or recompile.
+
+ The first method involves providing an override variable for each
+affected directory. For example, 'make install
+prefix=/alternate/directory' will choose an alternate location for all
+directory configuration variables that were expressed in terms of
+'${prefix}'. Any directories that were specified during 'configure',
+but not in terms of '${prefix}', must each be overridden at install time
+for the entire installation to be relocated. The approach of makefile
+variable overrides for each directory variable is required by the GNU
+Coding Standards, and ideally causes no recompilation. However, some
+platforms have known limitations with the semantics of shared libraries
+that end up requiring recompilation when using this method, particularly
+noticeable in packages that use GNU Libtool.
+
+ The second method involves providing the 'DESTDIR' variable. For
+example, 'make install DESTDIR=/alternate/directory' will prepend
+'/alternate/directory' before all installation names. The approach of
+'DESTDIR' overrides is not required by the GNU Coding Standards, and
+does not work on platforms that have drive letters. On the other hand,
+it does better at avoiding recompilation issues, and works well even
+when some directory options were not specified in terms of '${prefix}'
+at 'configure' time.
+
+Optional Features
+=================
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving 'configure' the
+option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'.
+
+ Some packages pay attention to '--enable-FEATURE' options to
+'configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to '--with-PACKAGE' options, where PACKAGE
+is something like 'gnu-as' or 'x' (for the X Window System). The
+'README' should mention any '--enable-' and '--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, 'configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the 'configure' options '--x-includes=DIR' and
+'--x-libraries=DIR' to specify their locations.
+
+ Some packages offer the ability to configure how verbose the
+execution of 'make' will be. For these packages, running './configure
+--enable-silent-rules' sets the default to minimal output, which can be
+overridden with 'make V=1'; while running './configure
+--disable-silent-rules' sets the default to verbose, which can be
+overridden with 'make V=0'.
+
+Particular systems
+==================
+
+ On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC
+is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+ ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+ HP-UX 'make' updates targets which have the same time stamps as their
+prerequisites, which makes it generally unusable when shipped generated
+files such as 'configure' are involved. Use GNU 'make' instead.
+
+ On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its '<wchar.h>' header file. The option '-nodtk' can be used as a
+workaround. If GNU CC is not installed, it is therefore recommended to
+try
+
+ ./configure CC="cc"
+
+and if that doesn't work, try
+
+ ./configure CC="cc -nodtk"
+
+ On Solaris, don't put '/usr/ucb' early in your 'PATH'. This
+directory contains several dysfunctional programs; working variants of
+these programs are available in '/usr/bin'. So, if you need '/usr/ucb'
+in your 'PATH', put it _after_ '/usr/bin'.
+
+ On Haiku, software installed for all users goes in '/boot/common',
+not '/usr/local'. It is recommended to use the following options:
+
+ ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+ There may be some features 'configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, 'configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+'--build=TYPE' option. TYPE can either be a short name for the system
+type, such as 'sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS
+ KERNEL-OS
+
+ See the file 'config.sub' for the possible values of each field. If
+'config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option '--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with '--host=TYPE'.
+
+Sharing Defaults
+================
+
+ If you want to set default values for 'configure' scripts to share,
+you can create a site shell script called 'config.site' that gives
+default values for variables like 'CC', 'cache_file', and 'prefix'.
+'configure' looks for 'PREFIX/share/config.site' if it exists, then
+'PREFIX/etc/config.site' if it exists. Or, you can set the
+'CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all 'configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to 'configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the 'configure' command line, using 'VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified 'gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an
+Autoconf limitation. Until the limitation is lifted, you can use this
+workaround:
+
+ CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+'configure' Invocation
+======================
+
+ 'configure' recognizes the following options to control how it
+operates.
+
+'--help'
+'-h'
+ Print a summary of all of the options to 'configure', and exit.
+
+'--help=short'
+'--help=recursive'
+ Print a summary of the options unique to this package's
+ 'configure', and exit. The 'short' variant lists options used only
+ in the top level, while the 'recursive' variant lists options also
+ present in any nested packages.
+
+'--version'
+'-V'
+ Print the version of Autoconf used to generate the 'configure'
+ script, and exit.
+
+'--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally 'config.cache'. FILE defaults to '/dev/null' to
+ disable caching.
+
+'--config-cache'
+'-C'
+ Alias for '--cache-file=config.cache'.
+
+'--quiet'
+'--silent'
+'-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to '/dev/null' (any error
+ messages will still be shown).
+
+'--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ 'configure' can determine that directory automatically.
+
+'--prefix=DIR'
+ Use DIR as the installation prefix. *note Installation Names:: for
+ more details, including other options available for fine-tuning the
+ installation locations.
+
+'--no-create'
+'-n'
+ Run the configure checks, but stop before creating any output
+ files.
+
+'configure' also accepts some other, not widely useful, options. Run
+'configure --help' for more details.
diff --git a/INSTALL.md b/INSTALL.md
new file mode 100644
index 0000000..add976b
--- /dev/null
+++ b/INSTALL.md
@@ -0,0 +1,1083 @@
+Sudo installation instructions
+==============================
+
+Sudo uses a `configure` script to probe the capabilities and type of the
+system in question. Sudo's `configure` script has a large number of options
+that control its behavior and enable or disable optional functionality.
+Be sure to read this document fully before configuring and building sudo.
+You may also wish to read the file INSTALL.configure which explains more
+about the `configure` script itself.
+
+## System requirements
+
+To build sudo from the source distribution you will need a
+POSIX-compliant operating system (any modern version of BSD, Linux,
+or Unix should work), a C compiler that conforms to ISO C99 or
+higher, and the ar, make, and ranlib utilities.
+
+If you wish to modify the parser then you will need flex version
+2.5.2 or later and either bison or byacc (sudo comes with a parser
+generated with GNU bison). You'll also have to run configure with
+the --with-devel option or pass DEVEL=1 to make. You can get flex
+from https://github.com/westes/flex/. You can get GNU bison from
+https://ftp.gnu.org/pub/gnu/bison/ or any GNU mirror.
+
+Some systems will also require that development library packages be
+installed. The sudo source distribution includes docker configurations
+for common Linux distributions that are used for continuous integration
+in the `docker` directory. See the appropriate OS-specific Dockerfile
+for a list of packages required to build sudo.
+
+## Simple sudo installation
+
+1. If you are upgrading from a previous version of sudo, read
+ [docs/UPGRADE.md](docs/UPGRADE.md) before proceeding.
+
+2. Read the "OS dependent notes" section for any particular
+ "gotchas" relating to your operating system.
+
+3. `cd` to the source or build directory and type `./configure`
+ to generate a Makefile and config.h file suitable for building
+ sudo. Before you actually run configure you should read the
+ "Available configure options" section to see if there are
+ any special options you may want or need.
+
+4. Type `make` to compile sudo. If `configure` did its job properly (and
+ you have a supported configuration) there won't be any problems. If you
+ have a problem, check [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md)
+ for tips on what might have gone wrong. If your problem is not covered,
+ you may file a bug report at https://bugzilla.sudo.ws/ or an issue at
+ https://github.com/sudo-project/sudo/issues/ (not both).
+
+5. Optionally, type `make check` to build and run the sudo unit and
+ regression tests. For more verbose output, use `make check-verbose`.
+
+6. Type `make install` (as root) to install sudo, visudo, the man
+ pages, and a skeleton sudoers file. The install will not overwrite
+ an existing sudoers file. You can also install various pieces of
+ the package via the install-binaries, install-doc, and install-sudoers
+ make targets.
+
+7. Edit the sudoers file with `visudo` as necessary for your
+ site. You will probably want to refer the example sudoers
+ file and sudoers man page included with the sudo package.
+
+8. If you want to use syslogd(8) to do the logging, you'll need to
+ update your `/etc/syslog.conf` file. See the examples/syslog.conf
+ file included in the distribution for an example.
+
+## Available configure options
+
+This section describes flags accepted by the sudo's `configure` script.
+Defaults are listed in brackets after the description.
+
+### Configuration:
+
+ --cache-file=FILE
+ Cache test results in FILE
+
+ --config-cache, -C
+ Alias for --cache-file=config.cache
+
+ --help, -h
+ Print the usage/help info
+
+ --no-create, -n
+ Do not create output files
+
+ --quiet, --silent, -q
+ Do not print "checking..." messages
+
+ --srcdir=DIR
+ Find the sources in DIR [configure dir or ".."]
+
+### Directory and file names:
+
+ --prefix=PREFIX
+ Install architecture-independent files in PREFIX. [/usr/local]
+
+ --exec-prefix=EPREFIX
+ Install architecture-dependent files in EPREFIX.
+ This includes the executables and plugins. [same as PREFIX]
+
+ --bindir=DIR
+ Install cvtsudoers, sudo, sudoedit, and sudoreplay in DIR. [EPREFIX/bin]
+
+ --sbindir=DIR
+ Install sudo_logsrvd, sudo_sendlog, and visudo in DIR. [EPREFIX/sbin]
+
+ --libexecdir=DIR
+ Install plugins and helper programs in DIR/sudo [PREFIX/libexec/sudo]
+
+ --sysconfdir=DIR
+ Look for configuration files such as `sudo.conf` and `sudoers`
+ in DIR. [/etc]
+
+ --includedir=DIR
+ Install sudo_plugin.h include file in DIR [PREFIX/include]
+
+ --datarootdir=DIR
+ Root directory for platform-independent data files [PREFIX/share]
+
+ --localedir=DIR
+ Install sudo and sudoers locale files in DIR [DATAROOTDIR/locale]
+
+ --mandir=DIR
+ Install man pages in DIR [PREFIX/man]
+
+ --docdir=DIR
+ Install other sudo documentation in DIR [DATAROOTDIR/doc/sudo]
+
+ --with-exampledir=DIR
+ Install sudo example files in DIR [DATAROOTDIR/doc/sudo/examples]
+
+ --with-plugindir=DIR
+ The directory that sudo looks in to find the policy and I/O
+ logging plugins. Defaults to the LIBEXEC/sudo.
+
+ --with-rundir=DIR
+ The directory to be used for sudo-specific files that do
+ not survive a system reboot. This is typically where the
+ time stamp directory is located. By default, configure
+ will choose from the following list: /run/sudo /var/run/sudo,
+ /var/db/sudo, /var/lib/sudo, /var/adm/sudo, /usr/adm/sudo.
+
+ This directory should be cleared when the system reboots.
+ On systems that lack /run or /var/run, the default rundir and
+ vardir may be the same. In this case, only the ts directory
+ inside the rundir needs to be cleared at boot time.
+
+ --with-vardir=DIR
+ The directory to be used for sudo-specific files that survive
+ a system reboot. This is typically where the lecture status
+ directory is stored. By default, configure will choose
+ from the following list: /var/db/sudo, /var/lib/sudo,
+ /var/adm/sudo, /usr/adm/sudo.
+
+ This directory should **not** be cleared when the system boots.
+
+ --with-relaydir=DIR
+ The directory to be used for sudo_logsrvd relay temporary files.
+ When sudo_logsrvd is configured as a store-and-forward relay,
+ the journaled data is written to this directory before it is
+ forwarded to a relay server.
+
+ --with-tzdir=DIR
+ The directory to the system's time zone data files. This
+ is only used when sanitizing the TZ environment variable
+ to allow for fully-qualified paths in TZ. By default,
+ configure will look for an existing "zoneinfo" directory
+ in the following locations: /usr/share, /usr/share/lib,
+ /usr/lib, /etc.
+
+ If no zoneinfo directory is found, the TZ variable may not
+ contain a fully-qualified path.
+
+### Compilation options:
+
+ --enable-sanitizer=[flags]
+ Enable the use of sanitizers such as AddressSanitizer and
+ UndefinedBehaviorSanitizer if supported by the compiler.
+ This can help detect common problems such as buffer overflows
+ and use after free bugs as well as behavior not defined by
+ the C standard. For more information see:
+ https://github.com/google/sanitizers/wiki
+
+ If no flags are specified by the user, a default value of
+ "-fsanitize=address,undefined" will be used.
+
+ This option should only be used for testing and not in a
+ production environment. Due to some sanitizers' unchecked
+ use of environment variables, it is trivial to exploit a
+ set-user-ID root executable such as sudo.
+
+ --enable-fuzzer
+ Enable building sudo with the LLVM libFuzzer, see
+ https://www.llvm.org/docs/LibFuzzer.html for details.
+ The resulting binaries, beginning with "fuzz_" can be used
+ to test sudo. To run all the fuzzers for 8192 iterations,
+ "make fuzz" can be used. This option is generally used in
+ conjunction with --enable-sanitizer.
+
+ Fuzzing currently requires the clang C compiler--it is not
+ supported by gcc. For best results, it is suggested to use
+ clang 11 or higher. Some of the fuzzers are known to hang
+ when used with earlier versions.
+
+ This option should only be used for testing and not in a
+ production environment.
+
+ --enable-fuzzer-engine=library
+ The library to use when linking fuzz targets instead of
+ LLVM's libFuzzer. It is intended to be set to the path to
+ an alternate fuzzing library, such as AFL++ or Honggfuzz.
+
+ --enable-fuzzer-linker=command
+ An alternate linker command to use when building fuzz
+ targets, instead of clang. It may be necessary to set this
+ when using the --enable-fuzzer-engine option to link with
+ a fuzzer engine that requires C++ libraries. For oss-fuzz,
+ this option is used to cause fuzz targets to be linked with
+ clang++.
+
+ --disable-hardening
+ Disable the use of compiler/linker exploit mitigation options
+ which are enabled by default. This includes compiling with
+ _FORTIFY_SOURCE defined to 2, building with -fstack-protector,
+ -fstack-clash-protection, -fcf-protection and linking with
+ -zrelro, -znow, and -znoexecstack where supported.
+
+ --disable-largefile
+ Disable support for large (64-bit) files on 32-bit systems
+ where the maximum file size is normally 4GB. By default,
+ configure will enable support for 64-bit file sizes if
+ supported by the operating system.
+
+ --disable-leaks
+ Avoid leaking memory even when we are headed for exit,
+ which helps reduce the noise from static and active analyzers.
+ This option should only be used for testing and not in a
+ production environment.
+
+ --enable-pie
+ Build sudo and related programs as as a position independent
+ executables (PIE). This improves the effectiveness of address
+ space layout randomization (ASLR) on systems that support it.
+ Sudo will create PIE binaries by default on Linux systems.
+
+ --disable-pie
+ Disable the creation of position independent executables (PIE),
+ even if the compiler creates PIE binaries by default. This
+ option may be needed on some Linux systems where PIE binaries
+ are not fully supported.
+
+ --disable-poll
+ Use select() instead of poll() in the event loop. By default,
+ sudo will use poll() on systems that support it. Some systems
+ have a broken poll() implementation and need to use select instead.
+ On macOS, select() is always used since its poll() doesn't
+ support character devices.
+
+ --disable-rpath
+ By default, configure will use -Rpath in addition to -Lpath
+ when passing library paths to the loader. This option will
+ disable the use of -Rpath.
+
+ --disable-shared
+ Disable dynamic shared object support. By default, sudo
+ is built with a plugin API capable of loading arbitrary
+ policy and I/O logging plugins. If the --disable-shared
+ option is specified, this support is disabled and the default
+ sudoers policy and I/O plugins are embedded in the sudo
+ binary itself. This will also disable the intercept and noexec
+ options as they also rely on dynamic shared object support.
+
+ --disable-shared-libutil
+ Disable the use of the dynamic libsudo_util library. By
+ default, sudo, the sudoers plugin and the associated sudo
+ utilities are linked against a shared version of libsudo_util.
+ If the --disable-shared-libutil option is specified, a
+ static version of the libsudo_util library will be used
+ instead. This option may only be used in conjunction with
+ the --enable-static-sudoers option.
+
+ --disable-ssp
+ Disable use of the -fstack-protector compiler option.
+ This does not affect the other hardening options.
+
+ --enable-static-sudoers
+ By default, the sudoers plugin is built and installed as a
+ dynamic shared object. When the --enable-static-sudoers
+ option is specified, the sudoers plugin is compiled directly
+ into the sudo binary. Unlike --disable-shared, this does
+ not prevent other plugins from being used and the intercept
+ and noexec options will continue to function.
+
+ --enable-tmpfiles.d=DIR
+ Set the directory to be used when installing the sudo
+ tmpfiles.d file. This is used to create (or clear) the
+ sudo time stamp directory on operating systems that use
+ systemd. If this option is not specified, configure will
+ use the /usr/lib/tmpfiles.d directory if the file
+ /usr/lib/tmpfiles.d/systemd.conf exists.
+
+ --disable-year2038
+ Disable support for dates after January 2038. By default,
+ configure will enable support for 64-bit time_t values if
+ supported by the operating system.
+
+ --enable-zlib[=location]
+ Enable the use of the zlib compress library when storing
+ I/O log files. If specified, location is the base directory
+ containing the zlib include and lib directories. The special
+ values "system", "builtin", "shared", and "static" can be
+ used to indicate that the system version of zlib should be
+ used or that the version of zlib shipped with sudo should
+ be used instead. If "static" is specified, sudo will
+ statically link the builtin zlib and not install it. If
+ this option is not specified, configure will use the system
+ zlib if it is present, falling back on the sudo version.
+
+ --with-incpath=DIR
+ Adds the specified directory (or directories) to CPPFLAGS
+ so configure and the compiler will look there for include
+ files. Multiple directories may be specified as long as
+ they are space separated.
+ E.g. --with-incpath="/usr/local/include /opt/include"
+
+ --with-libpath=DIR
+ Adds the specified directory (or directories) to LDFLAGS
+ so configure and the compiler will look there for libraries.
+ Multiple directories may be specified as with --with-incpath.
+
+ --with-libraries=LIBRARY
+ Adds the specified library (or libraries) to SUDO_LIBS and
+ and VISUDO_LIBS so sudo will link against them. If the
+ library doesn't start with "-l" or end in ".a" or ".o" a
+ "-l" will be prepended to it. Multiple libraries may be
+ specified as long as they are space separated.
+
+ --with-libtool=PATH
+ By default, sudo will use the included version of libtool
+ to build shared libraries. The --with-libtool option can
+ be used to specify a different version of libtool to use.
+ The special values "system" and "builtin" can be used in
+ place of a path to denote the default system libtool (obtained
+ via the user's PATH) and the default libtool that comes
+ with sudo.
+
+ --with-aix-soname=svr4
+ Starting with version 1.9.13, sudo will build AIX-style
+ shared libraries and dynamic shared objects by default
+ instead of svr4-style.. This means that the default sudo
+ plugins are now .a (archive) files that contain a .so shared
+ object file instead of bare .so files. This was done to
+ improve compatibility with the AIX Freeware ecosystem,
+ specifically, the AIX Freeware build of OpenSSL. To restore
+ the old, pre-1.9.13 behavior, run configure using the
+ --with-aix-soname=svr4 option.
+
+### Optional features:
+
+ --enable-adminconf=[DIR]
+ Search for configuration files in adminconfdir (PREFIX/etc
+ by default) in preference to configuration files in sysconfdir
+ (/etc by default). This can be used on systems where
+ sysconfdir is located on a read-only filesystem. When this
+ option is enabled, the visudo utility will store edited
+ sudoers files in adminconfdir if the original was located
+ in sysconfdir.
+
+ --disable-root-mailer
+ By default sudo will run the mailer as root when tattling
+ on a user so as to prevent that user from killing the mailer.
+ With this option, sudo will run the mailer as the invoking
+ user which some people consider to be safer.
+
+ --enable-nls[=location]
+ Enable natural language support using the gettext() family
+ of functions. If specified, location is the base directory
+ containing the libintl include and lib directories. If
+ this option is not specified, configure will look for the
+ gettext() family of functions in the standard C library
+ first, then check for a standalone libintl (linking with
+ libiconv as needed).
+
+ --disable-nls
+ Disable natural language support. By default, sudo will
+ use the gettext() family of functions, if available, to
+ implement messages in the invoking user's native language.
+ Translations do not exist for all languages.
+
+ --with-ldap[=DIR]
+ Enable LDAP support. If specified, DIR is the base directory
+ containing the LDAP include and lib directories. See
+ [README.LDAP.md](README.LDAP.md) for more information.
+
+ --with-ldap-conf-file=PATH
+ Path to LDAP configuration file. If specified, sudo reads
+ this file instead of `/etc/ldap.conf` to locate the LDAP server.
+
+ --with-ldap-secret-file=PATH
+ Path to LDAP secret password file. If specified, sudo uses
+ this file instead of `/etc/ldap.secret` to read the secret password
+ when rootbinddn is specified in the ldap config file.
+
+ --disable-sasl
+ Disable SASL authentication for LDAP. By default, sudo
+ will compile in support for SASL authentication if the
+ ldap_sasl_interactive_bind_s() function is present in the
+ LDAP libraries.
+
+ --with-apparmor
+ Enable support for the AppArmor Linux Security Module (LSM) on
+ supported systems.
+
+ --with-logincap
+ This adds support for login classes specified in `/etc/login.conf`.
+ It is enabled by default on BSD/OS, Darwin, FreeBSD, OpenBSD, and
+ NetBSD (where available). By default, a login class is not applied
+ unless the "use_loginclass" option is defined in sudoers or the user
+ specifies a class on the command line.
+
+ --with-interfaces=no, --without-interfaces
+ This option keeps sudo from trying to glean the ip address
+ from each attached network interface. It is only useful
+ on a machine where sudo's interface reading support does
+ not work, which may be the case on some SysV-based OS's
+ using STREAMS.
+
+ --enable-intercept[=PATH]
+ Enable support for the "intercept" functionality which
+ allows sudo to perform a policy check when a dynamically-linked
+ program run by sudo attempts to execute another program.
+ This is also used to support the "log_subcmds" sudoers
+ setting. For example, this means that for a shell run
+ through sudo, the individual commands run by the shell are
+ also subject to rules in the sudoers file. See the "Preventing
+ Shell Escapes" section in the sudoers man page for details.
+ If specified, PATH should either be a fully-qualified path
+ name such as /usr/local/libexec/sudo/sudo_intercept.so, or,
+ for AIX and Solaris systems, it may optionally be set to a
+ 32-bit shared library followed by a 64-bit shared library,
+ separated by a colon. If PATH is "no", intercept support
+ will not be compiled in. The default is to compile intercept
+ support if libtool supports building shared objects on your
+ system.
+
+ --with-noexec[=PATH]
+ Enable support for the "noexec" functionality which prevents
+ a dynamically-linked program being run by sudo from executing
+ another program (think shell escapes). See the "Preventing
+ Shell Escapes" section in the sudoers man page for details.
+ If specified, PATH should either be a fully-qualified path
+ name such as /usr/local/libexec/sudo/sudo_noexec.so, or,
+ for AIX and Solaris systems, it may optionally be set to a
+ 32-bit shared library followed by a 64-bit shared library,
+ separated by a colon. If PATH is "no", noexec support
+ will not be compiled in. The default is to compile noexec
+ support if libtool supports building shared objects on your
+ system.
+
+ --with-selinux
+ Enable support for role based access control (RBAC) on systems
+ that support SELinux.
+
+ --with-sssd
+ Enable support for using the System Security Services Daemon
+ (SSSD) as a sudoers data source. For more information on
+ SSD, see https://fedoraproject.org/wiki/Features/SSSD.
+
+ --with-sssd-conf=PATH
+ Specify the path to the SSSD configuration file, if different
+ from the default value of `/etc/sssd/sssd.conf`.
+
+ --with-sssd-lib=PATH
+ Specify the path to the SSSD shared library, which is loaded
+ at run-time.
+
+ --enable-offensive-insults
+ Enable potentially offensive sudo insults from the classic
+ version of sudo.
+
+ --enable-pvs-studio
+ Generate a sample PVS-Studio.cfg file based on the compiler and
+ platform type. The "pvs-studio" Makefile target can then be
+ used if PVS-Studio is installed.
+
+ --enable-python
+ Enable support for sudo plugins written in Python 3.
+ This requires a Python 3 development environment (including
+ Python 3 header files).
+
+ --disable-log-server
+ Disable building the sudo_logsrvd log server.
+
+ --disable-log-client
+ Disable sudoers support for using the sudo_logsrvd log server.
+
+### Operating system-specific options:
+
+ --disable-setreuid
+ Disable use of the setreuid() function for operating systems
+ where it is broken. For instance, 4.4BSD has setreuid() that
+ is not fully functional.
+
+ --disable-setresuid
+ Disable use of the setresuid() function for operating systems
+ where it is broken (none currently known).
+
+ --enable-admin-flag[=PATH]
+ Enable the creation of an Ubuntu-style admin flag file the
+ first time sudo is run. If PATH is not specified, the
+ default value is:
+ ~/.sudo_as_admin_successful
+
+ --enable-devsearch=PATH
+ Set a system-specific search path of directories to look in
+ for device nodes. Sudo uses this when mapping the process's
+ tty device number to a device name. The default value is:
+ /dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev
+
+ --with-bsm-audit
+ Enable support for sudo BSM audit logs on systems that support it.
+ This includes recent versions of FreeBSD, macOS and Solaris.
+
+ --with-linux-audit
+ Enable audit support for Linux systems. Audits attempts
+ to run a command as well as SELinux role changes.
+
+ --with-man
+ Use the "man" macros for manual pages. By default, mdoc versions
+ of the manuals are installed if supported. This can be used to
+ override configure's test for "nroff -mdoc" support.
+
+ --with-mdoc
+ Use the "mdoc" macros for manual pages. By default, mdoc versions
+ of the manuals are installed if supported. This can be used to
+ override configure's test for "nroff -mdoc" support.
+
+ --with-netsvc[=PATH]
+ Path to netsvc.conf or "no" to disable netsvc.conf support.
+ If specified, sudo uses this file instead of /etc/netsvc.conf
+ on AIX systems. If netsvc support is disabled but LDAP is
+ enabled, sudo will check LDAP first, then the sudoers file.
+
+ --with-nsswitch[=PATH]
+ Path to nsswitch.conf or "no" to disable nsswitch support.
+ If specified, sudo uses this file instead of /etc/nsswitch.conf.
+ If nsswitch support is disabled but LDAP is enabled, sudo will
+ check LDAP first, then the sudoers file.
+
+ --with-project
+ Enable support for Solaris project resource limits.
+ This option is only available on Solaris 9 and above.
+
+### Authentication options:
+
+ --with-AFS
+ Enable AFS support with Kerberos authentication. Should work under
+ AFS 3.3. If your AFS doesn't have -laudit you should be able to
+ link without it.
+
+ --with-aixauth
+ Enable support for the AIX general authentication function.
+ This will use the authentication scheme specified for the
+ user on the machine. By default, sudo will use either AIX
+ authentication or PAM depending on the value of the auth_type
+ setting in the `/etc/security/login.cfg` file.
+
+ --with-bsdauth
+ Enable support for BSD authentication. This is the default
+ for BSD/OS and OpenBSD systems that support it.
+ It is not possible to mix BSD authentication with other
+ authentication methods (and there really should be no need
+ to do so). Only the newer BSD authentication API is
+ supported. If you don't have /usr/include/bsd_auth.h then
+ you cannot use this.
+
+ --with-DCE
+ Enable DCE support for systems without PAM. Known to work on
+ HP-UX 9.X, 10.X, and 11.0; other systems may require source
+ code and/or `configure` changes. On systems with PAM support
+ (such as HP-UX 11.0 and higher, Solaris, FreeBSD, and Linux), the
+ DCE PAM module (usually libpam_dce) should be used instead.
+
+ --with-fwtk[=DIR]
+ Enable TIS Firewall Toolkit (FWTK) "authsrv" support. If specified,
+ DIR is the base directory containing the compiled FWTK package
+ (or at least the library and header files).
+
+ --with-kerb5[=DIR]
+ Enable Kerberos V support. If specified, DIR is the base
+ directory containing the Kerberos V include and lib dirs.
+ This uses Kerberos pass phrases for authentication but
+ does not use the Kerberos cookie scheme. Will not work for
+ Kerberos V older than version 1.1.
+
+ --enable-kerb5-instance=string
+ By default, the user name is used as the principal name
+ when authenticating via Kerberos V. If this option is
+ enabled, the specified instance string will be appended to
+ the user name (separated by a slash) when creating the
+ principal name.
+
+ --with-solaris-audit
+ Enable audit support for Solaris 11 and above.
+ For older versions of Solaris, use --with-bsm-audit
+
+ --with-opie[=DIR]
+ Enable NRL OPIE OTP (One Time Password) support. If specified,
+ DIR should contain include and lib directories with opie.h
+ and libopie.a respectively.
+
+ --with-otp-only
+ This option is now just an alias for --without-passwd.
+
+ --with-pam
+ Enable PAM support. This is on by default for Darwin, FreeBSD,
+ Linux, NetBSD, Solaris, and HP-UX (version 11 and higher).
+
+ On RedHat Linux and Fedora you **must** have an `/etc/pam.d/sudo`
+ file installed. You may either use the example pam.conf file included
+ with sudo or use `/etc/pam.d/su` as a reference. The pam.conf file
+ included with sudo may or may not work with other Linux distributions.
+ On Solaris and HP-UX 11 systems you should check (and understand)
+ the contents of `/etc/pam.conf`. Do a `man pam.conf` for more
+ information and consider using the "debug" option, if available,
+ with your PAM libraries in `/etc/pam.conf` to obtain syslog output
+ for debugging purposes.
+
+ --with-pam-login
+ Enable a specific PAM session when sudo is given the -i option.
+ This changes the PAM service name when sudo is run with the -i
+ option from "sudo" to "sudo-i", allowing for a separate pam
+ configuration for sudo's initial login mode.
+
+ --disable-pam-session
+ Disable sudo's PAM session support. This may be needed on
+ older PAM implementations or on operating systems where
+ opening a PAM session changes the utmp or wtmp files. If
+ PAM session support is disabled, resource limits may not
+ be updated for the command being run.
+
+ --with-passwd=no, --without-passwd
+ This option excludes authentication via the passwd (or
+ shadow) file. It should only be used when another, alternative,
+ authentication scheme is in use.
+
+ --with-SecurID[=DIR]
+ Enable SecurID support. If specified, DIR is directory containing
+ libaceclnt.a, acexport.h, and sdacmvls.h.
+
+ --with-skey[=DIR]
+ Enable S/Key OTP (One Time Password) support. If specified,
+ DIR should contain include and lib directories with skey.h
+ and libskey.a respectively.
+
+ --disable-sia
+ Disable SIA support. This is the "Security Integration
+ Architecture" on Digital UNIX. If you disable SIA sudo will
+ use its own authentication routines.
+
+ --disable-shadow
+ Disable shadow password support. Normally, sudo will compile
+ in shadow password support and use a shadow password if it
+ exists.
+
+ --enable-gss-krb5-ccache-name
+ Use the gss_krb5_ccache_name() function to set the Kerberos
+ V credential cache file name. By default, sudo will use
+ the KRB5CCNAME environment variable to set this. While
+ gss_krb5_ccache_name() provides a better API to do this it
+ is not supported by all Kerberos V and SASL combinations.
+
+ --enable-gcrypt[=DIR]
+ Use GNU crypt's SHA-2 message digest functions instead of
+ OpenSSL or the ones bundled with sudo (or in the system's
+ C library). If specified, DIR should contain the GNU crypt
+ include and lib directories. This option only has an effect
+ when OpenSSL 1.0.1 or higher is not present on the system
+ or the --disable-openssl option is also specified.
+
+ --enable-openssl[=DIR]
+ Use OpenSSL's TLS and SHA-2 message digest functions. If
+ it is detected, OpenSSL will be used by default unless the
+ sudo log client and server are disabled via the
+ --disable-log-client and --disable-log-server options. To
+ explicitly disable the use of OpenSSL, the --disable-openssl
+ option can be used. OpenSSL versions prior to 1.0.1 will
+ not be used as they do not support TLS 1.2. If specified,
+ DIR should contain the OpenSSL include and lib directories.
+
+ --enable-openssl-pkgconfig-template=template
+ A printf-style template used to construct the name of the
+ openssl and libcrypto pkg-config files. For example, a
+ template of "e%s30" would cause "eopenssl30" and "libecrypto30"
+ to be used instead. This makes it possible to link with
+ the OpenSSL 3.0 package on OpenBSD. Defaults to "%s".
+
+ --enable-wolfssl[=DIR]
+ Use wolfSSL's TLS and SHA-2 message digest functions. If
+ specified, DIR should contain the OpenSSL include and lib
+ directories.
+
+### Development options:
+
+ --enable-env-debug
+ Enable debugging of the environment setting functions. This
+ enables extra checks to make sure the environment does not
+ become corrupted.
+
+ --enable-postinstall=PATH
+ Enable the use of a postinstall script that is run after
+ the "install" target but before packages as built as part
+ of the "package" target.
+
+ --enable-warnings
+ Enable compiler warnings when building sudo with gcc or clang.
+
+ --enable-werror
+ Enable the -Werror compiler option when building sudo with
+ gcc or clang.
+
+ --with-devel
+ Configure development options. This will enable compiler warnings
+ and set up the Makefile to be able to regenerate the sudoers parser
+ as well as the manual pages.
+
+### Options that set runtime-changeable default values:
+
+ --disable-authentication
+ By default, sudo requires the user to authenticate via a
+ password or similar means. This options causes sudo to
+ **not** require authentication. It is possible to turn
+ authentication back on in sudoers via the PASSWD attribute.
+ Sudoers option: !authenticate
+
+ --disable-env-reset
+ Disable environment resetting. This sets the default value
+ of the "env_reset" Defaults option in sudoers to false.
+ Sudoers option: !env_reset
+
+ --disable-path-info
+ Normally, sudo will tell the user when a command could not be found
+ in their $PATH. Some sites may wish to disable this as it could
+ be used to gather information on the location of executables that
+ the normal user does not have access to. The disadvantage is that
+ if the executable is simply not in the user's path, sudo will tell
+ the user that they are not allowed to run it, which can be confusing.
+ Sudoers option: path_info
+
+ --disable-root-sudo
+ Don't let root run sudo. This can be used to prevent people from
+ "chaining" sudo commands to get a root shell by doing something
+ like `sudo sudo /bin/sh`.
+ Sudoers option: !root_sudo
+
+ --disable-zlib
+ Disable the use of the zlib compress library when storing
+ I/O log files.
+ Sudoers option: !compress_io
+
+ --enable-log-host
+ Log the hostname in the log file.
+ Sudoers option: log_host
+
+ --enable-noargs-shell
+ If sudo is invoked with no arguments it acts as if the "-s" flag had
+ been given. That is, it runs a shell as root (the shell is determined
+ by the SHELL environment variable, falling back on the shell listed
+ in the invoking user's `/etc/passwd` entry).
+ Sudoers option: shell_noargs
+
+ --enable-shell-sets-home
+ If sudo is invoked with the "-s" flag the HOME environment variable
+ will be set to the home directory of the target user (which is root
+ unless the "-u" option is used). This option effectively makes the
+ "-s" flag imply "-H".
+ Sudoers option: set_home
+
+ --enable-timestamp-type=TYPE
+ Set the default time stamp record type. The TYPE may be "global"
+ (a single record per user), "ppid" (a single record for process
+ with the same parent process), or "tty" (a separate record for
+ each login session). The default is "tty".
+ Sudoers option: timestamp_type
+
+ --with-all-insults
+ Include all the insult sets listed below. You must either specify
+ --with-insults or enable insults in the sudoers file for this to
+ have any effect.
+
+ --with-askpass=PATH
+ Set PATH as the "askpass" program to use when no tty is
+ available. Typically, this is a graphical password prompter,
+ similar to the one used by ssh. The program must take a
+ prompt as an argument and print the received password to
+ the standard output. This value may overridden at run-time
+ in the sudo.conf file.
+
+ --with-badpass-message="MESSAGE"
+ Message that is displayed if a user enters an incorrect password.
+ The default is "Sorry, try again." unless insults are turned on.
+ Sudoers option: badpass_message
+
+ --with-badpri=PRIORITY
+ Determines which syslog priority to log unauthenticated
+ commands and errors. The following priorities are supported:
+ alert, crit, debug, emerg, err, info, notice, and warning.
+ Sudoers option: syslog_badpri
+
+ --with-classic-insults
+ Uses insults from sudo "classic." If you just specify --with-insults
+ you will get the classic and CSOps insults. This is on by default if
+ --with-insults is given.
+
+ --with-csops-insults
+ Insults the user with an extra set of insults (some quotes, some
+ original) from a sysadmin group at CU (CSOps). You must specify
+ --with-insults as well for this to have any effect. This is on by
+ default if --with-insults is given.
+
+ --with-editor=PATH
+ Specify the default editor path for use by visudo. This may be a
+ single path name or a colon-separated list of editors. In the latter
+ case, visudo will choose the editor that matches the user's SUDO_EDITOR,
+ VISUAL or EDITOR environment variable, or the first editor in the list
+ that exists. The default is the path to vi on your system.
+ Sudoers option: editor
+
+ --with-env-editor=no, --without-env-editor
+ By default, visudo will consult the SUDO_EDITOR, VISUAL, and EDITOR
+ environment variables before falling back on the default editor list
+ (as specified by --with-editor). visudo is typically run as root so
+ this option may allow a user with visudo privileges to run arbitrary
+ commands as root without logging. Some sites may with to disable this
+ and use a colon-separated list of "safe" editors with the --with-editor
+ option. visudo will then only use the SUDO_EDITOR, VISUAL, or EDITOR
+ variables if they match a value specified via --with-editor.
+ Sudoers option: env_editor
+
+ --with-exempt=GROUP
+ Users in the specified group don't need to enter a password when
+ running sudo. This may be useful for sites that don't want their
+ "core" sysadmins to have to enter a password but where Jr. sysadmins
+ need to. You should probably use NOPASSWD in sudoers instead.
+ Sudoers option: exempt_group
+
+ --with-fqdn
+ Define this if you want to put fully-qualified host names in the sudoers
+ file. Ie: instead of myhost you would use myhost.mydomain.edu. You may
+ still use the short form if you wish (and even mix the two). Beware
+ that turning FQDN on requires sudo to make DNS lookups which may make
+ sudo unusable if your DNS is totally hosed. You must use the host's
+ official name as DNS knows it. That is, you may not use a host alias
+ (CNAME entry) due to performance issues and the fact that there is no
+ way to get all aliases from DNS.
+ Sudoers option: fqdn
+
+ --with-goodpri=PRIORITY
+ Determines which syslog priority to log successfully authenticated
+ commands. The following priorities are supported: alert, crit, debug,
+ emerg, err, info, notice, and warning.
+ Sudoers option: syslog_goodpri
+
+ --with-python-insults
+ Insults the user with lines from "Monty Python's Flying Circus" when an
+ incorrect password is entered. You must either specify --with-insults or
+ enable insults in the sudoers file for this to have any effect.
+
+ --with-goons-insults
+ Insults the user with lines from the "Goon Show" when an incorrect
+ password is entered. You must either specify --with-insults or
+ enable insults in the sudoers file for this to have any effect.
+
+ --with-hal-insults
+ Uses 2001-like insults when an incorrect password is entered.
+ You must either specify --with-insults or enable insults in the
+ sudoers file for this to have any effect.
+
+ --with-ignore-dot
+ If set, sudo will ignore "." or "" (current dir) in $PATH.
+ The $PATH itself is not modified.
+ Sudoers option: ignore_dot
+
+ --with-insults
+ Define this if you want to be insulted for typing an incorrect password
+ just like the original sudo(8). This is off by default.
+ Sudoers option: insults
+
+ --with-insults=disabled
+ Include support for insults but disable them unless explicitly
+ enabled in sudoers.
+ Sudoers option: !insults
+
+ --with-iologdir[=DIR]
+ By default, sudo stores I/O log files in either /var/log/sudo-io,
+ /var/adm/sudo-io, or /usr/log/sudo-io. If this option is specified,
+ I/O logs will be stored in the indicated directory instead.
+ Sudoers option: iolog_dir
+
+ --with-lecture=no, --without-lecture
+ Don't print the lecture the first time a user runs sudo.
+ Sudoers option: !lecture
+
+ --with-logfac=FACILITY
+ Determines which syslog facility to log to. This requires
+ a 4.3BSD or later version of syslog. You can still set
+ this for ancient syslogs but it will have no effect. The
+ following facilities are supported: authpriv (if your OS
+ supports it), auth, daemon, user, local0, local1, local2,
+ local3, local4, local5, local6, and local7.
+ Sudoers option: syslog
+
+ --with-logging=TYPE
+ How you want to do your logging. You may choose "syslog",
+ "file", or "both". Setting this to "syslog" is nice because
+ you can keep all of your sudo logs in one place (see the
+ example syslog.conf file). The default is "syslog".
+ Sudoers options: syslog and logfile
+
+ --with-loglen=NUMBER
+ Number of characters per line for the file log. This is only used if
+ you are to "file" or "both". This value is used to decide when to wrap
+ lines for nicer log files. The default is 80. Setting this to 0
+ will disable the wrapping.
+ Sudoers options: loglinelen
+
+ --with-logpath=PATH
+ Override the default location of the sudo log file and use
+ "path" instead. By default will use /var/log/sudo.log if
+ there is a /var/log dir, falling back to /var/adm/sudo.log
+ or /usr/adm/sudo.log if not.
+ Sudoers option: logfile
+
+ --with-long-otp-prompt
+ When validating with a One Time Password scheme (S/Key or
+ OPIE), a two-line prompt is used to make it easier to cut
+ and paste the challenge to a local window. It's not as
+ pretty as the default but some people find it more convenient.
+ Sudoers option: long_otp_prompt
+
+ --with-mail-if-no-user=no, --without-mail-if-no-user
+ Normally, sudo will mail to the "alertmail" user if the user invoking
+ sudo is not in the sudoers file. This option disables that behavior.
+ Sudoers option: mail_no_user
+
+ --with-mail-if-no-host
+ Send mail to the "alermail" user if the user exists in the sudoers
+ file, but is not allowed to run commands on the current host.
+ Sudoers option: mail_no_host
+
+ --with-mail-if-noperms
+ Send mail to the "alermail" user if the user is allowed to use sudo but
+ the command they are trying is not listed in their sudoers file entry.
+ Sudoers option: mail_no_perms
+
+ --with-mailsubject="SUBJECT"
+ Subject of the mail sent to the "mailto" user. The token "%h"
+ will expand to the hostname of the machine.
+ The default value is "*** SECURITY information for %h ***".
+ Sudoers option: mailsub
+
+ --with-mailto=USER|MAIL_ALIAS
+ User (or mail alias) that mail from sudo is sent to.
+ This should go to a sysadmin at your site. The default value is "root".
+ Sudoers option: mailto
+
+ --with-passprompt="PROMPT"
+ Default prompt to use when asking for a password; can be overridden
+ via the -p option and the SUDO_PROMPT environment variable. Supports
+ the "%H", "%h", "%U", and "%u" escapes as documented in the sudo
+ manual page. The default value is "Password:".
+ Sudoers option: passprompt
+
+ --with-password-timeout=NUMBER
+ Number of minutes before the sudo password prompt times out.
+ The default is 5, set this to 0 for no password timeout.
+ Sudoers option: passwd_timeout
+
+ --with-passwd-tries=NUMBER
+ Number of tries a user gets to enter his/her password before sudo logs
+ the failure and exits. The default is 3.
+ Sudoers option: passwd_tries
+
+ --with-runas-default=USER
+ The default user to run commands as if the -u flag is not specified
+ on the command line. This defaults to "root".
+ Sudoers option: runas_default
+
+ --with-secure-path[=PATH]
+ Path used for every command run from sudo(8). If you don't trust
+ users to have a reasonable PATH environment variable you may want
+ to use this. Another use is if you want to have the "root path"
+ be separate from the "user path." You will need to customize the
+ path for your site. This is not applied to users in the group
+ specified by --with-exemptgroup. If you do not specify a path,
+ "/bin:/usr/ucb:/usr/bin:/usr/sbin:/sbin:/usr/etc:/etc" is used.
+ Sudoers option: secure_path
+
+ --with-sendmail=PATH
+ Override configure's guess as to the location of sendmail.
+ Sudoers option: mailerpath
+
+ --with-sendmail=no, --without-sendmail
+ Do not use sendmail to mail messages to the "mailto" user.
+ Use only if you don't run sendmail or the equivalent.
+ Sudoers options: !mailerpath or !mailto
+
+ --with-sudoers-mode=MODE
+ File mode for the sudoers file (octal). If you wish to
+ NFS-mount the sudoers file this must be group readable.
+ This value may overridden at run-time in the sudo.conf file.
+ The default mode is 0440.
+
+ --with-sudoers-uid=UID
+ User id that "owns" the sudoers file. This is the numeric
+ id, **not** the symbolic name. This value may overridden
+ at run-time in the sudo.conf file. The default is 0.
+
+ --with-sudoers-gid=GID
+ Group id that "owns" the sudoers file. This is the numeric
+ id, **not** the symbolic name. This value may overridden
+ at run-time in the sudo.conf file. The default is 0.
+
+ --with-timeout=NUMBER
+ Number of minutes that can elapse before sudo will ask for a passwd
+ again. The default is 5, set it to 0 to always prompt for a password.
+ Sudoers option: timestamp_timeout
+
+ --with-umask=MASK
+ Umask to use when running the root command. The default is 0022.
+ Sudoers option: umask
+
+ --with-umask=no, --without-umask
+ Preserves the umask of the user invoking sudo.
+ Sudoers option: !umask
+
+ --with-umask-override
+ Use the umask specified in sudoers even if it is less restrictive
+ than the user's. The default is to use the intersection of the
+ user's umask and the umask specified in sudoers.
+ Sudoers option: umask_override
+
+## OS dependent notes
+
+#### HP-UX
+
+The default C compiler shipped with HP-UX is not an ANSI compiler.
+You must use either the HP ANSI C compiler or gcc to build sudo.
+Binary packages of gcc are available from http://hpux.connect.org.uk/.
+
+To prevent PAM from overriding the value of umask on HP-UX 11,
+you will need to add a line like the following to /etc/pam.conf:
+
+ sudo session required libpam_hpsec.so.1 bypass_umask
+
+#### Linux
+
+PAM and LDAP headers are not installed by default on most Linux
+systems. You will need to install the "pam-dev" (rpm) or libpam0g-dev
+(deb) package if `/usr/include/security/pam_appl.h` is not present
+on your system. If you wish to build with LDAP support you will
+also need the "openldap-devel" (rpm) or "libldap2-dev" (deb) package.
+
+#### macOS
+
+The pseudo-tty support in the Darwin kernel has bugs related to
+its handling of the SIGTSTP, SIGTTIN, and SIGTTOU signals. It does
+not restart reads and writes when those signals are delivered. This
+may cause problems for some commands when I/O logging is enabled.
+The issue has been reported to Apple and is bug id #7952709.
+
+#### Solaris
+
+You need to have a C compiler in order to build sudo. Since Solaris
+does not come with one by default this means that you either need
+to either install the Solaris Studio compiler suite, available for
+free from www.oracle.com, or install the GNU C compiler (gcc) which
+is can be installed via the pkg utility on Solaris 11 and higher
+and is distributed on the Solaris Companion CD for older Solaris
+releases. You can also download gcc packages from
+https://www.opencsw.org/packages/CSWgcc4core/.
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..32d6f2d
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,351 @@
+Sudo is distributed under the following license:
+
+ Copyright (c) 1994-1996, 1998-2023
+ Todd C. Miller <Todd.Miller@sudo.ws>
+
+ Permission to use, copy, modify, and distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ Sponsored in part by the Defense Advanced Research Projects
+ Agency (DARPA) and Air Force Research Laboratory, Air Force
+ Materiel Command, USAF, under agreement number F39502-99-1-0512.
+
+The Python plugin bindings bear the following license:
+
+ Copyright (c) 2019-2020 Robert Manner <robert.manner@oneidentity.com>
+
+ Permission to use, copy, modify, and distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+The files hostcheck.c and hostcheck.h bear the following license:
+
+ Copyright (c) 2020 Laszlo Orban <laszlo.orban@oneidentity.com>
+
+ Permission to use, copy, modify, and distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+The file redblack.c bears the following license:
+
+ Copyright (c) 2001 Emin Martinian
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that neither the name of Emin
+ Martinian nor the names of any contributors are be used to endorse or
+ promote products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The file sssd.c bears the following license:
+
+ Copyright (c) 2011 Daniel Kopecek <dkopecek@redhat.com>
+
+ This code is derived from software contributed by Aaron Spangler.
+
+ Permission to use, copy, modify, and distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+The files bsm_audit.c and bsm_audit.h bear the following license:
+
+ Copyright (c) 2009 Christian S.J. Peron
+
+ Permission to use, copy, modify, and distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+The files solaris_audit.c and solaris_audit.h bear the following license:
+
+ Copyright (c) 2014, Oracle and/or its affiliates.
+
+ Permission to use, copy, modify, and distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+The file reallocarray.c bears the following license:
+
+ Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
+
+ Permission to use, copy, modify, and distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+The files getcwd.c, glob.c, glob.h, snprintf.c and sudo_queue.h bear the
+following license:
+
+ Copyright (c) 1989, 1990, 1991, 1993
+ The Regents of the University of California. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+The file fnmatch.c bears the following license:
+
+ Copyright (c) 2011, VMware, Inc.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the VMware, Inc. nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The file getopt_long.c bears the following license:
+
+ Copyright (c) 2000 The NetBSD Foundation, Inc.
+ All rights reserved.
+
+ This code is derived from software contributed to The NetBSD Foundation
+ by Dieter Baron and Thomas Klausner.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+The file inet_pton.c bears the following license:
+
+ Copyright (c) 1996 by Internet Software Consortium.
+
+ Permission to use, copy, modify, and distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ SOFTWARE.
+
+The file arc4random.c bears the following license:
+
+ Copyright (c) 1996, David Mazieres <dm@uun.org>
+ Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
+ Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
+
+ Permission to use, copy, modify, and distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+The file arc4random_uniform.c bears the following license:
+
+ Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+
+ Permission to use, copy, modify, and distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+The file getentropy.c bears the following license:
+
+ Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
+ Copyright (c) 2014 Bob Beck <beck@obtuse.com>
+
+ Permission to use, copy, modify, and distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+The embedded copy of zlib bears the following license:
+
+ Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not
+ be misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source
+ distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+The embedded copy of protobuf-c bears the following license:
+
+ Copyright (c) 2008-2022, Dave Benson and the protobuf-c authors.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/MANIFEST b/MANIFEST
new file mode 100644
index 0000000..a3f8ffb
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,1339 @@
+ChangeLog
+INSTALL.configure
+INSTALL.md
+LICENSE.md
+MANIFEST
+Makefile.in
+NEWS
+README.LDAP.md
+README.md
+aclocal.m4
+autogen.sh
+config.h.in
+configure
+configure.ac
+docker/README
+docker/debian/latest/Dockerfile
+docker/debian/testing/Dockerfile
+docker/fedora/latest/Dockerfile
+docker/fedora/rawhide/Dockerfile
+docker/ubuntu/devel/Dockerfile
+docker/ubuntu/latest/Dockerfile
+docker/ubuntu/rolling/Dockerfile
+docs/CONTRIBUTING.md
+docs/CONTRIBUTORS.md
+docs/HISTORY.md
+docs/Makefile.in
+docs/SECURITY.md
+docs/TROUBLESHOOTING.md
+docs/UPGRADE.md
+docs/cvtsudoers.man.in
+docs/cvtsudoers.mdoc.in
+docs/fixman.sh
+docs/fixmdoc.sed
+docs/schema.ActiveDirectory
+docs/schema.OpenLDAP
+docs/schema.iPlanet
+docs/schema.olcSudo
+docs/sudo.conf.man.in
+docs/sudo.conf.man.in.sed
+docs/sudo.conf.mdoc.in
+docs/sudo.man.in
+docs/sudo.man.in.sed
+docs/sudo.mdoc.in
+docs/sudo_logsrv.proto.man.in
+docs/sudo_logsrv.proto.mdoc.in
+docs/sudo_logsrvd.conf.man.in
+docs/sudo_logsrvd.conf.mdoc.in
+docs/sudo_logsrvd.man.in
+docs/sudo_logsrvd.mdoc.in
+docs/sudo_plugin.man.in
+docs/sudo_plugin.mdoc.in
+docs/sudo_plugin_python.man.in
+docs/sudo_plugin_python.mdoc.in
+docs/sudo_sendlog.man.in
+docs/sudo_sendlog.mdoc.in
+docs/sudoers.ldap.man.in
+docs/sudoers.ldap.mdoc.in
+docs/sudoers.man.in
+docs/sudoers.man.in.sed
+docs/sudoers.mdoc.in
+docs/sudoers_timestamp.man.in
+docs/sudoers_timestamp.mdoc.in
+docs/sudoreplay.man.in
+docs/sudoreplay.mdoc.in
+docs/visudo.man.in
+docs/visudo.mdoc.in
+etc/codespell.exclude
+etc/codespell.ignore
+etc/codespell.skip
+etc/init.d/aix.sh.in
+etc/init.d/hpux.sh.in
+etc/init.d/sudo.conf.in
+etc/macos-background.png
+etc/sudo-logsrvd.pp
+etc/sudo-python.pp
+etc/sudo.pp
+examples/Makefile.in
+examples/cvtsudoers.conf
+examples/pam.conf
+examples/sudo.conf.in
+examples/sudo_logsrvd.conf.in
+examples/sudoers.in
+examples/syslog.conf.in
+include/Makefile.in
+include/compat/charclass.h
+include/compat/endian.h
+include/compat/fnmatch.h
+include/compat/getaddrinfo.h
+include/compat/getopt.h
+include/compat/glob.h
+include/compat/nss_dbdefs.h
+include/compat/sha2.h
+include/compat/stdbool.h
+include/hostcheck.h
+include/intercept.pb-c.h
+include/log_server.pb-c.h
+include/protobuf-c/protobuf-c.h
+include/sudo_compat.h
+include/sudo_conf.h
+include/sudo_debug.h
+include/sudo_digest.h
+include/sudo_dso.h
+include/sudo_event.h
+include/sudo_eventlog.h
+include/sudo_fatal.h
+include/sudo_gettext.h
+include/sudo_iolog.h
+include/sudo_json.h
+include/sudo_lbuf.h
+include/sudo_plugin.h
+include/sudo_queue.h
+include/sudo_rand.h
+include/sudo_ssl_compat.h
+include/sudo_util.h
+lib/eventlog/Makefile.in
+lib/eventlog/eventlog.c
+lib/eventlog/eventlog_conf.c
+lib/eventlog/eventlog_free.c
+lib/eventlog/logwrap.c
+lib/eventlog/parse_json.c
+lib/eventlog/parse_json.h
+lib/eventlog/regress/eventlog_store/store_json_test.c
+lib/eventlog/regress/eventlog_store/store_sudo_test.c
+lib/eventlog/regress/eventlog_store/test1.json.in
+lib/eventlog/regress/eventlog_store/test1.json.out.ok
+lib/eventlog/regress/eventlog_store/test1.sudo.out.ok
+lib/eventlog/regress/eventlog_store/test2.json.in
+lib/eventlog/regress/eventlog_store/test2.json.out.ok
+lib/eventlog/regress/eventlog_store/test2.sudo.out.ok
+lib/eventlog/regress/eventlog_store/test3.json.in
+lib/eventlog/regress/eventlog_store/test3.json.out.ok
+lib/eventlog/regress/eventlog_store/test3.sudo.out.ok
+lib/eventlog/regress/eventlog_store/test4.json.in
+lib/eventlog/regress/eventlog_store/test4.json.out.ok
+lib/eventlog/regress/eventlog_store/test4.sudo.out.ok
+lib/eventlog/regress/logwrap/check_wrap.c
+lib/eventlog/regress/logwrap/check_wrap.in
+lib/eventlog/regress/logwrap/check_wrap.out.ok
+lib/eventlog/regress/parse_json/check_parse_json.c
+lib/eventlog/regress/parse_json/test1.in
+lib/eventlog/regress/parse_json/test2.in
+lib/eventlog/regress/parse_json/test2.out.ok
+lib/eventlog/regress/parse_json/test3.in
+lib/eventlog/regress/parse_json/test3.out.ok
+lib/fuzzstub/Makefile.in
+lib/fuzzstub/fuzzstub.c
+lib/iolog/Makefile.in
+lib/iolog/host_port.c
+lib/iolog/hostcheck.c
+lib/iolog/iolog_clearerr.c
+lib/iolog/iolog_close.c
+lib/iolog/iolog_conf.c
+lib/iolog/iolog_eof.c
+lib/iolog/iolog_filter.c
+lib/iolog/iolog_flush.c
+lib/iolog/iolog_gets.c
+lib/iolog/iolog_json.c
+lib/iolog/iolog_legacy.c
+lib/iolog/iolog_loginfo.c
+lib/iolog/iolog_mkdirs.c
+lib/iolog/iolog_mkdtemp.c
+lib/iolog/iolog_mkpath.c
+lib/iolog/iolog_nextid.c
+lib/iolog/iolog_open.c
+lib/iolog/iolog_openat.c
+lib/iolog/iolog_path.c
+lib/iolog/iolog_read.c
+lib/iolog/iolog_seek.c
+lib/iolog/iolog_swapids.c
+lib/iolog/iolog_timing.c
+lib/iolog/iolog_util.c
+lib/iolog/iolog_write.c
+lib/iolog/regress/corpus/seed/log_json/id.json
+lib/iolog/regress/corpus/seed/log_json/ls.json
+lib/iolog/regress/corpus/seed/log_json/mailq.json
+lib/iolog/regress/corpus/seed/log_json/make.json
+lib/iolog/regress/corpus/seed/log_json/pkg_add.json
+lib/iolog/regress/corpus/seed/log_json/pkg_delete.json
+lib/iolog/regress/corpus/seed/log_json/printenv.json
+lib/iolog/regress/corpus/seed/log_legacy/id.log
+lib/iolog/regress/corpus/seed/log_legacy/less.log
+lib/iolog/regress/corpus/seed/log_legacy/ls.log
+lib/iolog/regress/corpus/seed/log_legacy/mailq.log
+lib/iolog/regress/corpus/seed/log_legacy/make.log
+lib/iolog/regress/corpus/seed/log_legacy/pkg_add.log
+lib/iolog/regress/corpus/seed/log_legacy/pkg_delete.log
+lib/iolog/regress/corpus/seed/log_legacy/printenv.log
+lib/iolog/regress/corpus/seed/log_legacy/smtpctl.log
+lib/iolog/regress/corpus/seed/log_legacy/vi.log
+lib/iolog/regress/corpus/seed/timing/timing.1
+lib/iolog/regress/corpus/seed/timing/timing.2
+lib/iolog/regress/corpus/seed/timing/timing.3
+lib/iolog/regress/corpus/seed/timing/timing.4
+lib/iolog/regress/corpus/seed/timing/timing.5
+lib/iolog/regress/corpus/seed/timing/timing.6
+lib/iolog/regress/corpus/seed/timing/timing.7
+lib/iolog/regress/corpus/seed/timing/timing.8
+lib/iolog/regress/corpus/seed/timing/timing.9
+lib/iolog/regress/fuzz/fuzz_iolog_json.c
+lib/iolog/regress/fuzz/fuzz_iolog_json.dict
+lib/iolog/regress/fuzz/fuzz_iolog_legacy.c
+lib/iolog/regress/fuzz/fuzz_iolog_legacy.dict
+lib/iolog/regress/fuzz/fuzz_iolog_timing.c
+lib/iolog/regress/fuzz/fuzz_iolog_timing.dict
+lib/iolog/regress/host_port/host_port_test.c
+lib/iolog/regress/iolog_filter/check_iolog_filter.c
+lib/iolog/regress/iolog_filter/test1/log
+lib/iolog/regress/iolog_filter/test1/timing
+lib/iolog/regress/iolog_filter/test1/ttyin
+lib/iolog/regress/iolog_filter/test1/ttyin.filtered
+lib/iolog/regress/iolog_filter/test1/ttyout
+lib/iolog/regress/iolog_filter/test2/log
+lib/iolog/regress/iolog_filter/test2/timing
+lib/iolog/regress/iolog_filter/test2/ttyin
+lib/iolog/regress/iolog_filter/test2/ttyin.filtered
+lib/iolog/regress/iolog_filter/test2/ttyout
+lib/iolog/regress/iolog_filter/test3/log
+lib/iolog/regress/iolog_filter/test3/timing
+lib/iolog/regress/iolog_filter/test3/ttyin
+lib/iolog/regress/iolog_filter/test3/ttyin.filtered
+lib/iolog/regress/iolog_filter/test3/ttyout
+lib/iolog/regress/iolog_mkpath/check_iolog_mkpath.c
+lib/iolog/regress/iolog_path/check_iolog_path.c
+lib/iolog/regress/iolog_path/data
+lib/iolog/regress/iolog_timing/check_iolog_timing.c
+lib/logsrv/Makefile.in
+lib/logsrv/log_server.pb-c.c
+lib/logsrv/log_server.proto
+lib/protobuf-c/Makefile.in
+lib/protobuf-c/protobuf-c.c
+lib/ssl_compat/Makefile.in
+lib/ssl_compat/ssl_compat.c
+lib/util/Makefile.in
+lib/util/aix.c
+lib/util/arc4random.c
+lib/util/arc4random_buf.c
+lib/util/arc4random_uniform.c
+lib/util/basename.c
+lib/util/cfmakeraw.c
+lib/util/chacha_private.h
+lib/util/closefrom.c
+lib/util/digest.c
+lib/util/digest_gcrypt.c
+lib/util/digest_openssl.c
+lib/util/dup3.c
+lib/util/event.c
+lib/util/event_poll.c
+lib/util/event_select.c
+lib/util/explicit_bzero.c
+lib/util/fatal.c
+lib/util/fchmodat.c
+lib/util/fchownat.c
+lib/util/fnmatch.c
+lib/util/freezero.c
+lib/util/fstatat.c
+lib/util/getaddrinfo.c
+lib/util/getdelim.c
+lib/util/getentropy.c
+lib/util/getgrouplist.c
+lib/util/gethostname.c
+lib/util/getopt_long.c
+lib/util/gettime.c
+lib/util/getusershell.c
+lib/util/gidlist.c
+lib/util/glob.c
+lib/util/gmtime_r.c
+lib/util/hexchar.c
+lib/util/inet_ntop.c
+lib/util/inet_pton.c
+lib/util/isblank.c
+lib/util/json.c
+lib/util/key_val.c
+lib/util/lbuf.c
+lib/util/localtime_r.c
+lib/util/locking.c
+lib/util/logfac.c
+lib/util/logpri.c
+lib/util/memrchr.c
+lib/util/mkdir_parents.c
+lib/util/mkdirat.c
+lib/util/mksiglist.c
+lib/util/mksigname.c
+lib/util/mktemp.c
+lib/util/mmap_alloc.c
+lib/util/multiarch.c
+lib/util/nanosleep.c
+lib/util/openat.c
+lib/util/parseln.c
+lib/util/pipe2.c
+lib/util/pread.c
+lib/util/progname.c
+lib/util/pw_dup.c
+lib/util/pwrite.c
+lib/util/rcstr.c
+lib/util/reallocarray.c
+lib/util/realpath.c
+lib/util/regex.c
+lib/util/regress/closefrom/closefrom_test.c
+lib/util/regress/corpus/seed/sudo_conf/sudo.conf.1
+lib/util/regress/corpus/seed/sudo_conf/sudo.conf.2
+lib/util/regress/corpus/seed/sudo_conf/sudo.conf.3
+lib/util/regress/digest/digest_test.c
+lib/util/regress/fnmatch/fnm_test.c
+lib/util/regress/fnmatch/fnm_test.in
+lib/util/regress/fuzz/fuzz_sudo_conf.c
+lib/util/regress/fuzz/fuzz_sudo_conf.dict
+lib/util/regress/getdelim/getdelim_test.c
+lib/util/regress/getgrouplist/getgids.c
+lib/util/regress/getgrouplist/getgrouplist_test.c
+lib/util/regress/glob/files
+lib/util/regress/glob/globtest.c
+lib/util/regress/glob/globtest.in
+lib/util/regress/harness.in
+lib/util/regress/hexchar/hexchar_test.c
+lib/util/regress/json/json_test.c
+lib/util/regress/mktemp/mktemp_test.c
+lib/util/regress/multiarch/multiarch_test.c
+lib/util/regress/open_parent_dir/open_parent_dir_test.c
+lib/util/regress/parse_gids/parse_gids_test.c
+lib/util/regress/progname/progname_test.c
+lib/util/regress/regex/regex_test.c
+lib/util/regress/strsig/strsig_test.c
+lib/util/regress/strsplit/strsplit_test.c
+lib/util/regress/strtofoo/strtobool_test.c
+lib/util/regress/strtofoo/strtoid_test.c
+lib/util/regress/strtofoo/strtomode_test.c
+lib/util/regress/strtofoo/strtonum_test.c
+lib/util/regress/sudo_conf/conf_test.c
+lib/util/regress/sudo_conf/test1.in
+lib/util/regress/sudo_conf/test1.out.ok
+lib/util/regress/sudo_conf/test2.in
+lib/util/regress/sudo_conf/test2.out.ok
+lib/util/regress/sudo_conf/test3.in
+lib/util/regress/sudo_conf/test3.out.ok
+lib/util/regress/sudo_conf/test4.err.ok
+lib/util/regress/sudo_conf/test4.in
+lib/util/regress/sudo_conf/test4.out.ok
+lib/util/regress/sudo_conf/test5.err.ok
+lib/util/regress/sudo_conf/test5.in
+lib/util/regress/sudo_conf/test5.out.ok
+lib/util/regress/sudo_conf/test6.in
+lib/util/regress/sudo_conf/test6.out.ok
+lib/util/regress/sudo_conf/test7.in
+lib/util/regress/sudo_conf/test7.out.ok
+lib/util/regress/sudo_parseln/parseln_test.c
+lib/util/regress/sudo_parseln/test1.in
+lib/util/regress/sudo_parseln/test1.out.ok
+lib/util/regress/sudo_parseln/test2.in
+lib/util/regress/sudo_parseln/test2.out.ok
+lib/util/regress/sudo_parseln/test3.in
+lib/util/regress/sudo_parseln/test3.out.ok
+lib/util/regress/sudo_parseln/test4.in
+lib/util/regress/sudo_parseln/test4.out.ok
+lib/util/regress/sudo_parseln/test5.in
+lib/util/regress/sudo_parseln/test5.out.ok
+lib/util/regress/sudo_parseln/test6.in
+lib/util/regress/sudo_parseln/test6.out.ok
+lib/util/regress/tailq/hltq_test.c
+lib/util/regress/uuid/uuid_test.c
+lib/util/roundup.c
+lib/util/secure_path.c
+lib/util/setgroups.c
+lib/util/sha2.c
+lib/util/sig2str.c
+lib/util/siglist.in
+lib/util/snprintf.c
+lib/util/str2sig.c
+lib/util/strlcat.c
+lib/util/strlcpy.c
+lib/util/strndup.c
+lib/util/strnlen.c
+lib/util/strsignal.c
+lib/util/strsplit.c
+lib/util/strtobool.c
+lib/util/strtoid.c
+lib/util/strtomode.c
+lib/util/strtonum.c
+lib/util/sudo_conf.c
+lib/util/sudo_debug.c
+lib/util/sudo_dso.c
+lib/util/sys_siglist.h
+lib/util/sys_signame.h
+lib/util/term.c
+lib/util/timegm.c
+lib/util/ttyname_dev.c
+lib/util/ttysize.c
+lib/util/unlinkat.c
+lib/util/util.exp.in
+lib/util/utimens.c
+lib/util/uuid.c
+lib/zlib/Makefile.in
+lib/zlib/adler32.c
+lib/zlib/compress.c
+lib/zlib/crc32.c
+lib/zlib/crc32.h
+lib/zlib/deflate.c
+lib/zlib/deflate.h
+lib/zlib/gzclose.c
+lib/zlib/gzguts.h
+lib/zlib/gzlib.c
+lib/zlib/gzread.c
+lib/zlib/gzwrite.c
+lib/zlib/infback.c
+lib/zlib/inffast.c
+lib/zlib/inffast.h
+lib/zlib/inffixed.h
+lib/zlib/inflate.c
+lib/zlib/inflate.h
+lib/zlib/inftrees.c
+lib/zlib/inftrees.h
+lib/zlib/trees.c
+lib/zlib/trees.h
+lib/zlib/uncompr.c
+lib/zlib/zconf.h.in
+lib/zlib/zlib.exp
+lib/zlib/zlib.h
+lib/zlib/zutil.c
+lib/zlib/zutil.h
+logsrvd/Makefile.in
+logsrvd/iolog_writer.c
+logsrvd/logsrv_util.c
+logsrvd/logsrv_util.h
+logsrvd/logsrvd.c
+logsrvd/logsrvd.h
+logsrvd/logsrvd_conf.c
+logsrvd/logsrvd_journal.c
+logsrvd/logsrvd_local.c
+logsrvd/logsrvd_queue.c
+logsrvd/logsrvd_relay.c
+logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.1
+logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.2
+logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.3
+logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.4
+logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.5
+logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.6
+logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.7
+logsrvd/regress/fuzz/fuzz_logsrvd_conf.c
+logsrvd/regress/fuzz/fuzz_logsrvd_conf.dict
+logsrvd/regress/logsrvd_conf/cacert.pem
+logsrvd/regress/logsrvd_conf/logsrvd_cert.pem
+logsrvd/regress/logsrvd_conf/logsrvd_conf_test.c
+logsrvd/regress/logsrvd_conf/logsrvd_dhparams.pem
+logsrvd/regress/logsrvd_conf/logsrvd_key.pem
+logsrvd/regress/logsrvd_conf/sudo_logsrvd.conf.1.in
+logsrvd/regress/logsrvd_conf/sudo_logsrvd.conf.2.in
+logsrvd/regress/logsrvd_conf/tls/sudo_logsrvd.conf.1.in
+logsrvd/regress/logsrvd_conf/tls/sudo_logsrvd.conf.2.in
+logsrvd/sendlog.c
+logsrvd/sendlog.h
+logsrvd/tls_client.c
+logsrvd/tls_common.h
+logsrvd/tls_init.c
+m4/ax_append_flag.m4
+m4/ax_check_compile_flag.m4
+m4/ax_check_link_flag.m4
+m4/ax_func_getaddrinfo.m4
+m4/ax_func_snprintf.m4
+m4/ax_gcc_builtin.m4
+m4/ax_prog_cc_for_build.m4
+m4/gettext.m4
+m4/hardening.m4
+m4/ldap.m4
+m4/libtool.m4
+m4/ltoptions.m4
+m4/ltsugar.m4
+m4/ltversion.m4
+m4/lt~obsolete.m4
+m4/openssl.m4
+m4/pie.m4
+m4/python.m4
+m4/runlog.m4
+m4/sanitizer.m4
+m4/sudo.m4
+m4/visibility.m4
+pathnames.h.in
+plugins/audit_json/Makefile.in
+plugins/audit_json/audit_json.c
+plugins/audit_json/audit_json.exp
+plugins/group_file/Makefile.in
+plugins/group_file/getgrent.c
+plugins/group_file/group_file.c
+plugins/group_file/group_file.exp
+plugins/group_file/plugin_test.c
+plugins/python/Makefile.in
+plugins/python/example_approval_plugin.py
+plugins/python/example_audit_plugin.py
+plugins/python/example_conversation.py
+plugins/python/example_debugging.py
+plugins/python/example_group_plugin.py
+plugins/python/example_io_plugin.py
+plugins/python/example_policy_plugin.py
+plugins/python/lsan_suppr.txt
+plugins/python/pyhelpers.c
+plugins/python/pyhelpers.h
+plugins/python/pyhelpers_cpychecker.h
+plugins/python/python_baseplugin.c
+plugins/python/python_convmessage.c
+plugins/python/python_loghandler.c
+plugins/python/python_plugin.exp
+plugins/python/python_plugin_approval.c
+plugins/python/python_plugin_approval_multi.inc
+plugins/python/python_plugin_audit.c
+plugins/python/python_plugin_audit_multi.inc
+plugins/python/python_plugin_common.c
+plugins/python/python_plugin_common.h
+plugins/python/python_plugin_group.c
+plugins/python/python_plugin_io.c
+plugins/python/python_plugin_io_multi.inc
+plugins/python/python_plugin_policy.c
+plugins/python/regress/check_python_examples.c
+plugins/python/regress/iohelpers.c
+plugins/python/regress/iohelpers.h
+plugins/python/regress/plugin_approval_test.py
+plugins/python/regress/plugin_conflict.py
+plugins/python/regress/plugin_errorstr.py
+plugins/python/regress/testdata/check_example_audit_plugin_receives_accept.stdout
+plugins/python/regress/testdata/check_example_audit_plugin_receives_error.stdout
+plugins/python/regress/testdata/check_example_audit_plugin_receives_reject.stdout
+plugins/python/regress/testdata/check_example_audit_plugin_version_display.stdout
+plugins/python/regress/testdata/check_example_audit_plugin_workflow_multiple.stderr
+plugins/python/regress/testdata/check_example_audit_plugin_workflow_multiple.stdout
+plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.conversation
+plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.stderr
+plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.stdout
+plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.stored
+plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.conversation
+plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.stderr
+plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.stdout
+plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.stored
+plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.conv
+plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.conversation
+plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.stderr
+plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.stdout
+plugins/python/regress/testdata/check_example_debugging_c_calls@diag.log
+plugins/python/regress/testdata/check_example_debugging_c_calls@info.log
+plugins/python/regress/testdata/check_example_debugging_load@diag.log
+plugins/python/regress/testdata/check_example_debugging_plugin@err.log
+plugins/python/regress/testdata/check_example_debugging_plugin@info.log
+plugins/python/regress/testdata/check_example_debugging_py_calls@diag.log
+plugins/python/regress/testdata/check_example_debugging_py_calls@info.log
+plugins/python/regress/testdata/check_example_debugging_sudo_cb@info.log
+plugins/python/regress/testdata/check_example_group_plugin_is_able_to_debug.log
+plugins/python/regress/testdata/check_example_io_plugin_command_log.stderr
+plugins/python/regress/testdata/check_example_io_plugin_command_log.stdout
+plugins/python/regress/testdata/check_example_io_plugin_command_log.stored
+plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stderr
+plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stdout
+plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple1.stored
+plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple2.stored
+plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stderr
+plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stdout
+plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stored
+plugins/python/regress/testdata/check_example_io_plugin_fails_with_python_backtrace.stderr
+plugins/python/regress/testdata/check_example_io_plugin_fails_with_python_backtrace.stdout
+plugins/python/regress/testdata/check_example_io_plugin_version_display.stderr
+plugins/python/regress/testdata/check_example_io_plugin_version_display.stdout
+plugins/python/regress/testdata/check_example_io_plugin_version_display.stored
+plugins/python/regress/testdata/check_example_io_plugin_version_display_full.stdout
+plugins/python/regress/testdata/check_example_policy_plugin_accepted_execution.stderr
+plugins/python/regress/testdata/check_example_policy_plugin_accepted_execution.stdout
+plugins/python/regress/testdata/check_example_policy_plugin_denied_execution.stderr
+plugins/python/regress/testdata/check_example_policy_plugin_denied_execution.stdout
+plugins/python/regress/testdata/check_example_policy_plugin_failed_execution.stderr
+plugins/python/regress/testdata/check_example_policy_plugin_failed_execution.stdout
+plugins/python/regress/testdata/check_example_policy_plugin_list.stderr
+plugins/python/regress/testdata/check_example_policy_plugin_list.stdout
+plugins/python/regress/testdata/check_example_policy_plugin_validate_invalidate.log
+plugins/python/regress/testdata/check_example_policy_plugin_version_display.stderr
+plugins/python/regress/testdata/check_example_policy_plugin_version_display.stdout
+plugins/python/regress/testdata/check_example_policy_plugin_version_display_full.stdout
+plugins/python/regress/testdata/check_loading_fails_missing_classname.stderr
+plugins/python/regress/testdata/check_loading_fails_missing_classname.stdout
+plugins/python/regress/testdata/check_loading_fails_missing_path.stderr
+plugins/python/regress/testdata/check_loading_fails_missing_path.stdout
+plugins/python/regress/testdata/check_loading_fails_not_owned_by_root.stderr
+plugins/python/regress/testdata/check_loading_fails_not_owned_by_root.stdout
+plugins/python/regress/testdata/check_loading_fails_wrong_classname.stderr
+plugins/python/regress/testdata/check_loading_fails_wrong_classname.stdout
+plugins/python/regress/testdata/check_loading_fails_wrong_path.stderr
+plugins/python/regress/testdata/check_loading_fails_wrong_path.stdout
+plugins/python/regress/testdata/check_loading_succeeds_with_missing_classname.stdout
+plugins/python/regress/testdata/check_multiple_approval_plugin_and_arguments.stderr
+plugins/python/regress/testdata/check_multiple_approval_plugin_and_arguments.stdout
+plugins/python/regress/testdata/check_python_plugins_do_not_affect_each_other.stdout
+plugins/python/regress/testhelpers.c
+plugins/python/regress/testhelpers.h
+plugins/python/sudo_python_debug.c
+plugins/python/sudo_python_debug.h
+plugins/python/sudo_python_module.c
+plugins/python/sudo_python_module.h
+plugins/sample/Makefile.in
+plugins/sample/README
+plugins/sample/sample_plugin.c
+plugins/sample/sample_plugin.exp
+plugins/sample_approval/Makefile.in
+plugins/sample_approval/sample_approval.c
+plugins/sample_approval/sample_approval.exp
+plugins/sudoers/Makefile.in
+plugins/sudoers/alias.c
+plugins/sudoers/audit.c
+plugins/sudoers/auth/API
+plugins/sudoers/auth/afs.c
+plugins/sudoers/auth/aix_auth.c
+plugins/sudoers/auth/bsdauth.c
+plugins/sudoers/auth/dce.c
+plugins/sudoers/auth/fwtk.c
+plugins/sudoers/auth/kerb5.c
+plugins/sudoers/auth/pam.c
+plugins/sudoers/auth/passwd.c
+plugins/sudoers/auth/rfc1938.c
+plugins/sudoers/auth/secureware.c
+plugins/sudoers/auth/securid5.c
+plugins/sudoers/auth/sia.c
+plugins/sudoers/auth/sudo_auth.c
+plugins/sudoers/auth/sudo_auth.h
+plugins/sudoers/b64_decode.c
+plugins/sudoers/b64_encode.c
+plugins/sudoers/boottime.c
+plugins/sudoers/bsm_audit.c
+plugins/sudoers/bsm_audit.h
+plugins/sudoers/canon_path.c
+plugins/sudoers/check.c
+plugins/sudoers/check_aliases.c
+plugins/sudoers/check_util.c
+plugins/sudoers/cvtsudoers.c
+plugins/sudoers/cvtsudoers.h
+plugins/sudoers/cvtsudoers_csv.c
+plugins/sudoers/cvtsudoers_json.c
+plugins/sudoers/cvtsudoers_ldif.c
+plugins/sudoers/cvtsudoers_merge.c
+plugins/sudoers/cvtsudoers_pwutil.c
+plugins/sudoers/def_data.c
+plugins/sudoers/def_data.h
+plugins/sudoers/def_data.in
+plugins/sudoers/defaults.c
+plugins/sudoers/defaults.h
+plugins/sudoers/digestname.c
+plugins/sudoers/display.c
+plugins/sudoers/editor.c
+plugins/sudoers/env.c
+plugins/sudoers/env_pattern.c
+plugins/sudoers/exptilde.c
+plugins/sudoers/file.c
+plugins/sudoers/filedigest.c
+plugins/sudoers/find_path.c
+plugins/sudoers/fmtsudoers.c
+plugins/sudoers/fmtsudoers_cvt.c
+plugins/sudoers/gc.c
+plugins/sudoers/gentime.c
+plugins/sudoers/getdate.c
+plugins/sudoers/getdate.y
+plugins/sudoers/getspwuid.c
+plugins/sudoers/goodpath.c
+plugins/sudoers/gram.c
+plugins/sudoers/gram.h
+plugins/sudoers/gram.y
+plugins/sudoers/group_plugin.c
+plugins/sudoers/ins_2001.h
+plugins/sudoers/ins_classic.h
+plugins/sudoers/ins_csops.h
+plugins/sudoers/ins_goons.h
+plugins/sudoers/ins_python.h
+plugins/sudoers/insults.h
+plugins/sudoers/interfaces.c
+plugins/sudoers/interfaces.h
+plugins/sudoers/iolog.c
+plugins/sudoers/iolog_path_escapes.c
+plugins/sudoers/ldap.c
+plugins/sudoers/ldap_conf.c
+plugins/sudoers/ldap_innetgr.c
+plugins/sudoers/ldap_util.c
+plugins/sudoers/linux_audit.c
+plugins/sudoers/linux_audit.h
+plugins/sudoers/locale.c
+plugins/sudoers/log_client.c
+plugins/sudoers/log_client.h
+plugins/sudoers/logging.c
+plugins/sudoers/logging.h
+plugins/sudoers/lookup.c
+plugins/sudoers/match.c
+plugins/sudoers/match_addr.c
+plugins/sudoers/match_command.c
+plugins/sudoers/match_digest.c
+plugins/sudoers/mkdefaults
+plugins/sudoers/parse.h
+plugins/sudoers/parse_ldif.c
+plugins/sudoers/parser_warnx.c
+plugins/sudoers/pivot.c
+plugins/sudoers/pivot.h
+plugins/sudoers/po/README
+plugins/sudoers/po/ast.mo
+plugins/sudoers/po/ast.po
+plugins/sudoers/po/ca.mo
+plugins/sudoers/po/ca.po
+plugins/sudoers/po/cs.mo
+plugins/sudoers/po/cs.po
+plugins/sudoers/po/da.mo
+plugins/sudoers/po/da.po
+plugins/sudoers/po/de.mo
+plugins/sudoers/po/de.po
+plugins/sudoers/po/el.mo
+plugins/sudoers/po/el.po
+plugins/sudoers/po/eo.mo
+plugins/sudoers/po/eo.po
+plugins/sudoers/po/es.mo
+plugins/sudoers/po/es.po
+plugins/sudoers/po/eu.mo
+plugins/sudoers/po/eu.po
+plugins/sudoers/po/fi.mo
+plugins/sudoers/po/fi.po
+plugins/sudoers/po/fr.mo
+plugins/sudoers/po/fr.po
+plugins/sudoers/po/fur.mo
+plugins/sudoers/po/fur.po
+plugins/sudoers/po/hr.mo
+plugins/sudoers/po/hr.po
+plugins/sudoers/po/hu.mo
+plugins/sudoers/po/hu.po
+plugins/sudoers/po/it.mo
+plugins/sudoers/po/it.po
+plugins/sudoers/po/ja.mo
+plugins/sudoers/po/ja.po
+plugins/sudoers/po/ka.mo
+plugins/sudoers/po/ka.po
+plugins/sudoers/po/ko.mo
+plugins/sudoers/po/ko.po
+plugins/sudoers/po/lt.mo
+plugins/sudoers/po/lt.po
+plugins/sudoers/po/nb.mo
+plugins/sudoers/po/nb.po
+plugins/sudoers/po/nl.mo
+plugins/sudoers/po/nl.po
+plugins/sudoers/po/pl.mo
+plugins/sudoers/po/pl.po
+plugins/sudoers/po/pt.mo
+plugins/sudoers/po/pt.po
+plugins/sudoers/po/pt_BR.mo
+plugins/sudoers/po/pt_BR.po
+plugins/sudoers/po/ro.mo
+plugins/sudoers/po/ro.po
+plugins/sudoers/po/ru.mo
+plugins/sudoers/po/ru.po
+plugins/sudoers/po/sk.mo
+plugins/sudoers/po/sk.po
+plugins/sudoers/po/sl.mo
+plugins/sudoers/po/sl.po
+plugins/sudoers/po/sr.mo
+plugins/sudoers/po/sr.po
+plugins/sudoers/po/sudoers.pot
+plugins/sudoers/po/sv.mo
+plugins/sudoers/po/sv.po
+plugins/sudoers/po/tr.mo
+plugins/sudoers/po/tr.po
+plugins/sudoers/po/uk.mo
+plugins/sudoers/po/uk.po
+plugins/sudoers/po/vi.mo
+plugins/sudoers/po/vi.po
+plugins/sudoers/po/zh_CN.mo
+plugins/sudoers/po/zh_CN.po
+plugins/sudoers/po/zh_TW.mo
+plugins/sudoers/po/zh_TW.po
+plugins/sudoers/policy.c
+plugins/sudoers/prompt.c
+plugins/sudoers/pwutil.c
+plugins/sudoers/pwutil.h
+plugins/sudoers/pwutil_impl.c
+plugins/sudoers/redblack.c
+plugins/sudoers/redblack.h
+plugins/sudoers/regress/check_symbols/check_symbols.c
+plugins/sudoers/regress/corpus/seed/ldif/invalid_b64.ldif
+plugins/sudoers/regress/corpus/seed/ldif/pr196.ldif
+plugins/sudoers/regress/corpus/seed/ldif/sample.ldif
+plugins/sudoers/regress/corpus/seed/ldif/valid_b64.ldif
+plugins/sudoers/regress/corpus/seed/policy/policy.1
+plugins/sudoers/regress/corpus/seed/policy/policy.2
+plugins/sudoers/regress/corpus/seed/policy/policy.3
+plugins/sudoers/regress/corpus/seed/policy/policy.4
+plugins/sudoers/regress/corpus/seed/policy/policy.5
+plugins/sudoers/regress/cvtsudoers/sudoers
+plugins/sudoers/regress/cvtsudoers/sudoers.defs
+plugins/sudoers/regress/cvtsudoers/sudoers1
+plugins/sudoers/regress/cvtsudoers/sudoers2
+plugins/sudoers/regress/cvtsudoers/sudoers3
+plugins/sudoers/regress/cvtsudoers/sudoers4
+plugins/sudoers/regress/cvtsudoers/test1.out.ok
+plugins/sudoers/regress/cvtsudoers/test1.sh
+plugins/sudoers/regress/cvtsudoers/test10.out.ok
+plugins/sudoers/regress/cvtsudoers/test10.sh
+plugins/sudoers/regress/cvtsudoers/test11.out.ok
+plugins/sudoers/regress/cvtsudoers/test11.sh
+plugins/sudoers/regress/cvtsudoers/test12.out.ok
+plugins/sudoers/regress/cvtsudoers/test12.sh
+plugins/sudoers/regress/cvtsudoers/test13.out.ok
+plugins/sudoers/regress/cvtsudoers/test13.sh
+plugins/sudoers/regress/cvtsudoers/test14.out.ok
+plugins/sudoers/regress/cvtsudoers/test14.sh
+plugins/sudoers/regress/cvtsudoers/test15.out.ok
+plugins/sudoers/regress/cvtsudoers/test15.sh
+plugins/sudoers/regress/cvtsudoers/test16.out.ok
+plugins/sudoers/regress/cvtsudoers/test16.sh
+plugins/sudoers/regress/cvtsudoers/test17.out.ok
+plugins/sudoers/regress/cvtsudoers/test17.sh
+plugins/sudoers/regress/cvtsudoers/test18.out.ok
+plugins/sudoers/regress/cvtsudoers/test18.sh
+plugins/sudoers/regress/cvtsudoers/test19.out.ok
+plugins/sudoers/regress/cvtsudoers/test19.sh
+plugins/sudoers/regress/cvtsudoers/test2.out.ok
+plugins/sudoers/regress/cvtsudoers/test2.sh
+plugins/sudoers/regress/cvtsudoers/test20.conf
+plugins/sudoers/regress/cvtsudoers/test20.out.ok
+plugins/sudoers/regress/cvtsudoers/test20.sh
+plugins/sudoers/regress/cvtsudoers/test21.conf
+plugins/sudoers/regress/cvtsudoers/test21.out.ok
+plugins/sudoers/regress/cvtsudoers/test21.sh
+plugins/sudoers/regress/cvtsudoers/test22.out.ok
+plugins/sudoers/regress/cvtsudoers/test22.sh
+plugins/sudoers/regress/cvtsudoers/test23.out.ok
+plugins/sudoers/regress/cvtsudoers/test23.sh
+plugins/sudoers/regress/cvtsudoers/test24.out.ok
+plugins/sudoers/regress/cvtsudoers/test24.sh
+plugins/sudoers/regress/cvtsudoers/test25.out.ok
+plugins/sudoers/regress/cvtsudoers/test25.sh
+plugins/sudoers/regress/cvtsudoers/test26.err.ok
+plugins/sudoers/regress/cvtsudoers/test26.out.ok
+plugins/sudoers/regress/cvtsudoers/test26.sh
+plugins/sudoers/regress/cvtsudoers/test27.out.ok
+plugins/sudoers/regress/cvtsudoers/test27.sh
+plugins/sudoers/regress/cvtsudoers/test28.out.ok
+plugins/sudoers/regress/cvtsudoers/test28.sh
+plugins/sudoers/regress/cvtsudoers/test29.out.ok
+plugins/sudoers/regress/cvtsudoers/test29.sh
+plugins/sudoers/regress/cvtsudoers/test3.out.ok
+plugins/sudoers/regress/cvtsudoers/test3.sh
+plugins/sudoers/regress/cvtsudoers/test30.out.ok
+plugins/sudoers/regress/cvtsudoers/test30.sh
+plugins/sudoers/regress/cvtsudoers/test31.conf
+plugins/sudoers/regress/cvtsudoers/test31.out.ok
+plugins/sudoers/regress/cvtsudoers/test31.sh
+plugins/sudoers/regress/cvtsudoers/test32.err.ok
+plugins/sudoers/regress/cvtsudoers/test32.out.ok
+plugins/sudoers/regress/cvtsudoers/test32.sh
+plugins/sudoers/regress/cvtsudoers/test33.out.ok
+plugins/sudoers/regress/cvtsudoers/test33.sh
+plugins/sudoers/regress/cvtsudoers/test34.out.ok
+plugins/sudoers/regress/cvtsudoers/test34.sh
+plugins/sudoers/regress/cvtsudoers/test35.out.ok
+plugins/sudoers/regress/cvtsudoers/test35.sh
+plugins/sudoers/regress/cvtsudoers/test36.out.ok
+plugins/sudoers/regress/cvtsudoers/test36.sh
+plugins/sudoers/regress/cvtsudoers/test37.out.ok
+plugins/sudoers/regress/cvtsudoers/test37.sh
+plugins/sudoers/regress/cvtsudoers/test38.out.ok
+plugins/sudoers/regress/cvtsudoers/test38.sh
+plugins/sudoers/regress/cvtsudoers/test39.out.ok
+plugins/sudoers/regress/cvtsudoers/test39.sh
+plugins/sudoers/regress/cvtsudoers/test4.out.ok
+plugins/sudoers/regress/cvtsudoers/test4.sh
+plugins/sudoers/regress/cvtsudoers/test40.out.ok
+plugins/sudoers/regress/cvtsudoers/test40.sh
+plugins/sudoers/regress/cvtsudoers/test5.out.ok
+plugins/sudoers/regress/cvtsudoers/test5.sh
+plugins/sudoers/regress/cvtsudoers/test6.out.ok
+plugins/sudoers/regress/cvtsudoers/test6.sh
+plugins/sudoers/regress/cvtsudoers/test7.out.ok
+plugins/sudoers/regress/cvtsudoers/test7.sh
+plugins/sudoers/regress/cvtsudoers/test8.out.ok
+plugins/sudoers/regress/cvtsudoers/test8.sh
+plugins/sudoers/regress/cvtsudoers/test9.out.ok
+plugins/sudoers/regress/cvtsudoers/test9.sh
+plugins/sudoers/regress/editor/check_editor.c
+plugins/sudoers/regress/env_match/check_env_pattern.c
+plugins/sudoers/regress/env_match/data
+plugins/sudoers/regress/exptilde/check_exptilde.c
+plugins/sudoers/regress/fuzz/fuzz_policy.c
+plugins/sudoers/regress/fuzz/fuzz_policy.dict
+plugins/sudoers/regress/fuzz/fuzz_stubs.c
+plugins/sudoers/regress/fuzz/fuzz_sudoers.c
+plugins/sudoers/regress/fuzz/fuzz_sudoers.dict
+plugins/sudoers/regress/fuzz/fuzz_sudoers.out.ok
+plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c
+plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.dict
+plugins/sudoers/regress/harness.in
+plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c
+plugins/sudoers/regress/parser/check_addr.c
+plugins/sudoers/regress/parser/check_addr.in
+plugins/sudoers/regress/parser/check_base64.c
+plugins/sudoers/regress/parser/check_digest.c
+plugins/sudoers/regress/parser/check_digest.out.ok
+plugins/sudoers/regress/parser/check_fill.c
+plugins/sudoers/regress/parser/check_gentime.c
+plugins/sudoers/regress/serialize_list/check_serialize_list.c
+plugins/sudoers/regress/starttime/check_starttime.c
+plugins/sudoers/regress/sudoers/test1.in
+plugins/sudoers/regress/sudoers/test1.json.ok
+plugins/sudoers/regress/sudoers/test1.ldif.ok
+plugins/sudoers/regress/sudoers/test1.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test1.out.ok
+plugins/sudoers/regress/sudoers/test1.toke.ok
+plugins/sudoers/regress/sudoers/test10.in
+plugins/sudoers/regress/sudoers/test10.json.ok
+plugins/sudoers/regress/sudoers/test10.ldif.ok
+plugins/sudoers/regress/sudoers/test10.out.ok
+plugins/sudoers/regress/sudoers/test10.toke.ok
+plugins/sudoers/regress/sudoers/test11.in
+plugins/sudoers/regress/sudoers/test11.json.ok
+plugins/sudoers/regress/sudoers/test11.ldif.ok
+plugins/sudoers/regress/sudoers/test11.out.ok
+plugins/sudoers/regress/sudoers/test11.toke.ok
+plugins/sudoers/regress/sudoers/test12.in
+plugins/sudoers/regress/sudoers/test12.json.ok
+plugins/sudoers/regress/sudoers/test12.ldif.ok
+plugins/sudoers/regress/sudoers/test12.out.ok
+plugins/sudoers/regress/sudoers/test12.toke.ok
+plugins/sudoers/regress/sudoers/test13.in
+plugins/sudoers/regress/sudoers/test13.json.ok
+plugins/sudoers/regress/sudoers/test13.ldif.ok
+plugins/sudoers/regress/sudoers/test13.out.ok
+plugins/sudoers/regress/sudoers/test13.toke.ok
+plugins/sudoers/regress/sudoers/test14.in
+plugins/sudoers/regress/sudoers/test14.json.ok
+plugins/sudoers/regress/sudoers/test14.ldif.ok
+plugins/sudoers/regress/sudoers/test14.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test14.out.ok
+plugins/sudoers/regress/sudoers/test14.toke.ok
+plugins/sudoers/regress/sudoers/test15.in
+plugins/sudoers/regress/sudoers/test15.json.ok
+plugins/sudoers/regress/sudoers/test15.ldif.ok
+plugins/sudoers/regress/sudoers/test15.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test15.out.ok
+plugins/sudoers/regress/sudoers/test15.toke.ok
+plugins/sudoers/regress/sudoers/test16.in
+plugins/sudoers/regress/sudoers/test16.json.ok
+plugins/sudoers/regress/sudoers/test16.ldif.ok
+plugins/sudoers/regress/sudoers/test16.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test16.out.ok
+plugins/sudoers/regress/sudoers/test16.toke.ok
+plugins/sudoers/regress/sudoers/test17.in
+plugins/sudoers/regress/sudoers/test17.json.ok
+plugins/sudoers/regress/sudoers/test17.ldif.ok
+plugins/sudoers/regress/sudoers/test17.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test17.out.ok
+plugins/sudoers/regress/sudoers/test17.toke.ok
+plugins/sudoers/regress/sudoers/test18.in
+plugins/sudoers/regress/sudoers/test18.json.ok
+plugins/sudoers/regress/sudoers/test18.ldif.ok
+plugins/sudoers/regress/sudoers/test18.out.ok
+plugins/sudoers/regress/sudoers/test18.toke.ok
+plugins/sudoers/regress/sudoers/test19.in
+plugins/sudoers/regress/sudoers/test19.json.ok
+plugins/sudoers/regress/sudoers/test19.ldif.ok
+plugins/sudoers/regress/sudoers/test19.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test19.out.ok
+plugins/sudoers/regress/sudoers/test19.toke.ok
+plugins/sudoers/regress/sudoers/test2.in
+plugins/sudoers/regress/sudoers/test2.json.ok
+plugins/sudoers/regress/sudoers/test2.ldif.ok
+plugins/sudoers/regress/sudoers/test2.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test2.out.ok
+plugins/sudoers/regress/sudoers/test2.toke.ok
+plugins/sudoers/regress/sudoers/test20.in
+plugins/sudoers/regress/sudoers/test20.json.ok
+plugins/sudoers/regress/sudoers/test20.ldif.ok
+plugins/sudoers/regress/sudoers/test20.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test20.out.ok
+plugins/sudoers/regress/sudoers/test20.toke.ok
+plugins/sudoers/regress/sudoers/test21.in
+plugins/sudoers/regress/sudoers/test21.json.ok
+plugins/sudoers/regress/sudoers/test21.ldif.ok
+plugins/sudoers/regress/sudoers/test21.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test21.out.ok
+plugins/sudoers/regress/sudoers/test21.toke.ok
+plugins/sudoers/regress/sudoers/test22.in
+plugins/sudoers/regress/sudoers/test22.json.ok
+plugins/sudoers/regress/sudoers/test22.ldif.ok
+plugins/sudoers/regress/sudoers/test22.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test22.out.ok
+plugins/sudoers/regress/sudoers/test22.toke.ok
+plugins/sudoers/regress/sudoers/test23.in
+plugins/sudoers/regress/sudoers/test23.json.ok
+plugins/sudoers/regress/sudoers/test23.ldif.ok
+plugins/sudoers/regress/sudoers/test23.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test23.out.ok
+plugins/sudoers/regress/sudoers/test23.toke.ok
+plugins/sudoers/regress/sudoers/test24.in
+plugins/sudoers/regress/sudoers/test24.json.ok
+plugins/sudoers/regress/sudoers/test24.ldif.ok
+plugins/sudoers/regress/sudoers/test24.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test24.out.ok
+plugins/sudoers/regress/sudoers/test24.toke.ok
+plugins/sudoers/regress/sudoers/test25.in
+plugins/sudoers/regress/sudoers/test25.json.ok
+plugins/sudoers/regress/sudoers/test25.ldif.ok
+plugins/sudoers/regress/sudoers/test25.out.ok
+plugins/sudoers/regress/sudoers/test25.toke.ok
+plugins/sudoers/regress/sudoers/test26.in
+plugins/sudoers/regress/sudoers/test26.json.ok
+plugins/sudoers/regress/sudoers/test26.ldif.ok
+plugins/sudoers/regress/sudoers/test26.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test26.out.ok
+plugins/sudoers/regress/sudoers/test26.toke.ok
+plugins/sudoers/regress/sudoers/test27.in
+plugins/sudoers/regress/sudoers/test27.json.ok
+plugins/sudoers/regress/sudoers/test27.ldif.ok
+plugins/sudoers/regress/sudoers/test27.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test27.out.ok
+plugins/sudoers/regress/sudoers/test27.toke.ok
+plugins/sudoers/regress/sudoers/test28.in
+plugins/sudoers/regress/sudoers/test28.json.ok
+plugins/sudoers/regress/sudoers/test28.ldif.ok
+plugins/sudoers/regress/sudoers/test28.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test28.out.ok
+plugins/sudoers/regress/sudoers/test28.toke.ok
+plugins/sudoers/regress/sudoers/test29.in
+plugins/sudoers/regress/sudoers/test29.json.ok
+plugins/sudoers/regress/sudoers/test29.ldif.ok
+plugins/sudoers/regress/sudoers/test29.out.ok
+plugins/sudoers/regress/sudoers/test29.toke.ok
+plugins/sudoers/regress/sudoers/test3.in
+plugins/sudoers/regress/sudoers/test3.json.ok
+plugins/sudoers/regress/sudoers/test3.ldif.ok
+plugins/sudoers/regress/sudoers/test3.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test3.out.ok
+plugins/sudoers/regress/sudoers/test3.toke.ok
+plugins/sudoers/regress/sudoers/test30.in
+plugins/sudoers/regress/sudoers/test30.json.ok
+plugins/sudoers/regress/sudoers/test30.ldif.ok
+plugins/sudoers/regress/sudoers/test30.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test30.out.ok
+plugins/sudoers/regress/sudoers/test30.sudo.ok
+plugins/sudoers/regress/sudoers/test30.toke.ok
+plugins/sudoers/regress/sudoers/test4.in
+plugins/sudoers/regress/sudoers/test4.json.ok
+plugins/sudoers/regress/sudoers/test4.ldif.ok
+plugins/sudoers/regress/sudoers/test4.out.ok
+plugins/sudoers/regress/sudoers/test4.toke.ok
+plugins/sudoers/regress/sudoers/test5.in
+plugins/sudoers/regress/sudoers/test5.json.ok
+plugins/sudoers/regress/sudoers/test5.ldif.ok
+plugins/sudoers/regress/sudoers/test5.out.ok
+plugins/sudoers/regress/sudoers/test5.toke.ok
+plugins/sudoers/regress/sudoers/test6.in
+plugins/sudoers/regress/sudoers/test6.json.ok
+plugins/sudoers/regress/sudoers/test6.ldif.ok
+plugins/sudoers/regress/sudoers/test6.ldif2sudo.ok
+plugins/sudoers/regress/sudoers/test6.out.ok
+plugins/sudoers/regress/sudoers/test6.toke.ok
+plugins/sudoers/regress/sudoers/test7.in
+plugins/sudoers/regress/sudoers/test7.json.ok
+plugins/sudoers/regress/sudoers/test7.ldif.ok
+plugins/sudoers/regress/sudoers/test7.out.ok
+plugins/sudoers/regress/sudoers/test7.toke.ok
+plugins/sudoers/regress/sudoers/test8.in
+plugins/sudoers/regress/sudoers/test8.json.ok
+plugins/sudoers/regress/sudoers/test8.ldif.ok
+plugins/sudoers/regress/sudoers/test8.out.ok
+plugins/sudoers/regress/sudoers/test8.toke.ok
+plugins/sudoers/regress/sudoers/test9.in
+plugins/sudoers/regress/sudoers/test9.json.ok
+plugins/sudoers/regress/sudoers/test9.ldif.ok
+plugins/sudoers/regress/sudoers/test9.out.ok
+plugins/sudoers/regress/sudoers/test9.toke.ok
+plugins/sudoers/regress/testsudoers/group
+plugins/sudoers/regress/testsudoers/passwd
+plugins/sudoers/regress/testsudoers/test1.out.ok
+plugins/sudoers/regress/testsudoers/test1.sh
+plugins/sudoers/regress/testsudoers/test10.out.ok
+plugins/sudoers/regress/testsudoers/test10.sh
+plugins/sudoers/regress/testsudoers/test11.out.ok
+plugins/sudoers/regress/testsudoers/test11.sh
+plugins/sudoers/regress/testsudoers/test12.out.ok
+plugins/sudoers/regress/testsudoers/test12.sh
+plugins/sudoers/regress/testsudoers/test13.out.ok
+plugins/sudoers/regress/testsudoers/test13.sh
+plugins/sudoers/regress/testsudoers/test14.out.ok
+plugins/sudoers/regress/testsudoers/test14.sh
+plugins/sudoers/regress/testsudoers/test15.out.ok
+plugins/sudoers/regress/testsudoers/test15.sh
+plugins/sudoers/regress/testsudoers/test16.out.ok
+plugins/sudoers/regress/testsudoers/test16.sh
+plugins/sudoers/regress/testsudoers/test17.out.ok
+plugins/sudoers/regress/testsudoers/test17.sh
+plugins/sudoers/regress/testsudoers/test18.out.ok
+plugins/sudoers/regress/testsudoers/test18.sh
+plugins/sudoers/regress/testsudoers/test19.out.ok
+plugins/sudoers/regress/testsudoers/test19.sh
+plugins/sudoers/regress/testsudoers/test2.inc
+plugins/sudoers/regress/testsudoers/test2.out.ok
+plugins/sudoers/regress/testsudoers/test2.sh
+plugins/sudoers/regress/testsudoers/test20.out.ok
+plugins/sudoers/regress/testsudoers/test20.sh
+plugins/sudoers/regress/testsudoers/test21.out.ok
+plugins/sudoers/regress/testsudoers/test21.sh
+plugins/sudoers/regress/testsudoers/test22.out.ok
+plugins/sudoers/regress/testsudoers/test22.sh
+plugins/sudoers/regress/testsudoers/test23.out.ok
+plugins/sudoers/regress/testsudoers/test23.sh
+plugins/sudoers/regress/testsudoers/test24.out.ok
+plugins/sudoers/regress/testsudoers/test24.sh
+plugins/sudoers/regress/testsudoers/test25.out.ok
+plugins/sudoers/regress/testsudoers/test25.sh
+plugins/sudoers/regress/testsudoers/test26.out.ok
+plugins/sudoers/regress/testsudoers/test26.sh
+plugins/sudoers/regress/testsudoers/test27.out.ok
+plugins/sudoers/regress/testsudoers/test27.sh
+plugins/sudoers/regress/testsudoers/test28.out.ok
+plugins/sudoers/regress/testsudoers/test28.sh
+plugins/sudoers/regress/testsudoers/test29.out.ok
+plugins/sudoers/regress/testsudoers/test29.sh
+plugins/sudoers/regress/testsudoers/test3.out.ok
+plugins/sudoers/regress/testsudoers/test3.sh
+plugins/sudoers/regress/testsudoers/test30.out.ok
+plugins/sudoers/regress/testsudoers/test30.sh
+plugins/sudoers/regress/testsudoers/test31.out.ok
+plugins/sudoers/regress/testsudoers/test31.sh
+plugins/sudoers/regress/testsudoers/test4.out.ok
+plugins/sudoers/regress/testsudoers/test4.sh
+plugins/sudoers/regress/testsudoers/test5.out.ok
+plugins/sudoers/regress/testsudoers/test5.sh
+plugins/sudoers/regress/testsudoers/test6.out.ok
+plugins/sudoers/regress/testsudoers/test6.sh
+plugins/sudoers/regress/testsudoers/test7.out.ok
+plugins/sudoers/regress/testsudoers/test7.sh
+plugins/sudoers/regress/testsudoers/test8.out.ok
+plugins/sudoers/regress/testsudoers/test8.sh
+plugins/sudoers/regress/testsudoers/test9.out.ok
+plugins/sudoers/regress/testsudoers/test9.sh
+plugins/sudoers/regress/unescape/check_unesc.c
+plugins/sudoers/regress/visudo/test1.out.ok
+plugins/sudoers/regress/visudo/test1.sh
+plugins/sudoers/regress/visudo/test10.out.ok
+plugins/sudoers/regress/visudo/test10.sh
+plugins/sudoers/regress/visudo/test2.err.ok
+plugins/sudoers/regress/visudo/test2.out.ok
+plugins/sudoers/regress/visudo/test2.sh
+plugins/sudoers/regress/visudo/test3.err.ok
+plugins/sudoers/regress/visudo/test3.out.ok
+plugins/sudoers/regress/visudo/test3.sh
+plugins/sudoers/regress/visudo/test4.out.ok
+plugins/sudoers/regress/visudo/test4.sh
+plugins/sudoers/regress/visudo/test5.out.ok
+plugins/sudoers/regress/visudo/test5.sh
+plugins/sudoers/regress/visudo/test6.out.ok
+plugins/sudoers/regress/visudo/test6.sh
+plugins/sudoers/regress/visudo/test7.out.ok
+plugins/sudoers/regress/visudo/test7.sh
+plugins/sudoers/regress/visudo/test8.err.ok
+plugins/sudoers/regress/visudo/test8.out.ok
+plugins/sudoers/regress/visudo/test8.sh
+plugins/sudoers/regress/visudo/test9.out.ok
+plugins/sudoers/regress/visudo/test9.sh
+plugins/sudoers/resolve_cmnd.c
+plugins/sudoers/serialize_list.c
+plugins/sudoers/set_perms.c
+plugins/sudoers/sethost.c
+plugins/sudoers/solaris_audit.c
+plugins/sudoers/solaris_audit.h
+plugins/sudoers/sssd.c
+plugins/sudoers/starttime.c
+plugins/sudoers/strlcpy_unesc.c
+plugins/sudoers/strlist.c
+plugins/sudoers/strlist.h
+plugins/sudoers/strvec_join.c
+plugins/sudoers/stubs.c
+plugins/sudoers/sudo_ldap.h
+plugins/sudoers/sudo_ldap_conf.h
+plugins/sudoers/sudo_nss.c
+plugins/sudoers/sudo_nss.h
+plugins/sudoers/sudo_printf.c
+plugins/sudoers/sudoers.c
+plugins/sudoers/sudoers.exp
+plugins/sudoers/sudoers.h
+plugins/sudoers/sudoers.in
+plugins/sudoers/sudoers_cb.c
+plugins/sudoers/sudoers_ctx_free.c
+plugins/sudoers/sudoers_debug.c
+plugins/sudoers/sudoers_debug.h
+plugins/sudoers/sudoers_hooks.c
+plugins/sudoers/sudoers_version.h
+plugins/sudoers/sudoreplay.c
+plugins/sudoers/testsudoers.c
+plugins/sudoers/testsudoers_pwutil.c
+plugins/sudoers/testsudoers_pwutil.h
+plugins/sudoers/timeout.c
+plugins/sudoers/timestamp.c
+plugins/sudoers/timestamp.h
+plugins/sudoers/timestr.c
+plugins/sudoers/toke.c
+plugins/sudoers/toke.h
+plugins/sudoers/toke.l
+plugins/sudoers/toke_util.c
+plugins/sudoers/tsdump.c
+plugins/sudoers/tsgetgrpw.c
+plugins/sudoers/tsgetgrpw.h
+plugins/sudoers/unesc_str.c
+plugins/sudoers/visudo.c
+plugins/sudoers/visudo_cb.c
+plugins/system_group/Makefile.in
+plugins/system_group/system_group.c
+plugins/system_group/system_group.exp
+po/README
+po/ast.mo
+po/ast.po
+po/ca.mo
+po/ca.po
+po/cs.mo
+po/cs.po
+po/da.mo
+po/da.po
+po/de.mo
+po/de.po
+po/eo.mo
+po/eo.po
+po/es.mo
+po/es.po
+po/eu.mo
+po/eu.po
+po/fa.mo
+po/fa.po
+po/fi.mo
+po/fi.po
+po/fr.mo
+po/fr.po
+po/fur.mo
+po/fur.po
+po/gl.mo
+po/gl.po
+po/hr.mo
+po/hr.po
+po/hu.mo
+po/hu.po
+po/id.mo
+po/id.po
+po/it.mo
+po/it.po
+po/ja.mo
+po/ja.po
+po/ka.mo
+po/ka.po
+po/ko.mo
+po/ko.po
+po/nb.mo
+po/nb.po
+po/nl.mo
+po/nl.po
+po/nn.mo
+po/nn.po
+po/pl.mo
+po/pl.po
+po/pt.mo
+po/pt.po
+po/pt_BR.mo
+po/pt_BR.po
+po/ro.mo
+po/ro.po
+po/ru.mo
+po/ru.po
+po/sk.mo
+po/sk.po
+po/sl.mo
+po/sl.po
+po/sq.mo
+po/sq.po
+po/sr.mo
+po/sr.po
+po/sudo.pot
+po/sv.mo
+po/sv.po
+po/tr.mo
+po/tr.po
+po/uk.mo
+po/uk.po
+po/vi.mo
+po/vi.po
+po/zh_CN.mo
+po/zh_CN.po
+po/zh_TW.mo
+po/zh_TW.po
+scripts/config.guess
+scripts/config.sub
+scripts/generate_test_coverage.sh
+scripts/install-sh
+scripts/log2cl.pl
+scripts/ltmain.sh
+scripts/mkdep.pl
+scripts/mkinstalldirs
+scripts/mkpkg
+scripts/pp
+scripts/unanon
+src/Makefile.in
+src/apparmor.c
+src/conversation.c
+src/copy_file.c
+src/edit_open.c
+src/env_hooks.c
+src/exec.c
+src/exec_common.c
+src/exec_intercept.c
+src/exec_intercept.h
+src/exec_iolog.c
+src/exec_monitor.c
+src/exec_nopty.c
+src/exec_preload.c
+src/exec_ptrace.c
+src/exec_ptrace.h
+src/exec_pty.c
+src/get_pty.c
+src/hooks.c
+src/intercept.exp.in
+src/intercept.pb-c.c
+src/intercept.proto
+src/limits.c
+src/load_plugins.c
+src/net_ifs.c
+src/openbsd.c
+src/parse_args.c
+src/preload.c
+src/preserve_fds.c
+src/regress/intercept/test_ptrace.c
+src/regress/net_ifs/check_net_ifs.c
+src/regress/noexec/check_noexec.c
+src/regress/ttyname/check_ttyname.c
+src/selinux.c
+src/sesh.c
+src/signal.c
+src/solaris.c
+src/sudo.c
+src/sudo.h
+src/sudo_edit.c
+src/sudo_edit.h
+src/sudo_exec.h
+src/sudo_intercept.c
+src/sudo_intercept_common.c
+src/sudo_noexec.c
+src/sudo_plugin_int.h
+src/sudo_usage.h.in
+src/suspend_parent.c
+src/tgetpass.c
+src/ttyname.c
+src/utmp.c
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..3caa667
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,462 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2010-2015, 2017-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+devdir = @devdir@
+scriptdir = $(top_srcdir)/scripts
+
+# Installation paths for package building
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+sysconfdir = @sysconfdir@
+adminconfdir = @adminconfdir@
+libexecdir = @libexecdir@
+includedir = @includedir@
+datarootdir = @datarootdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+exampledir = @exampledir@
+docdir = @docdir@
+mandir = @mandir@
+rundir = @rundir@
+vardir = @vardir@
+
+# User and group ids the installed files should be "owned" by
+install_uid = 0
+install_gid = 0
+
+# sudoers owner and mode for package building
+sudoers_uid = @SUDOERS_UID@
+sudoers_gid = @SUDOERS_GID@
+sudoers_mode = @SUDOERS_MODE@
+shlib_mode = @SHLIB_MODE@
+
+# Version of python detected by configure (major.minor)
+python_version = @PYTHON_VERSION@
+
+SUBDIRS = lib/util @ZLIB_SRC@ lib/eventlog lib/fuzzstub lib/iolog \
+ lib/protobuf-c @SSL_COMPAT_SRC@ @LOGSRV_SRC@ @LOGSRVD_SRC@ \
+ plugins/audit_json plugins/group_file plugins/sudoers \
+ plugins/system_group @PYTHON_PLUGIN_SRC@ src include \
+ docs examples
+
+SAMPLES = plugins/sample plugins/sample_approval
+
+VERSION = @PACKAGE_VERSION@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+
+SHELL = @SHELL@
+
+EGREP = @EGREP@
+SED = @SED@
+
+INSTALL = $(SHELL) $(scriptdir)/install-sh -c
+INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
+
+ECHO_N = @ECHO_N@
+ECHO_C = @ECHO_C@
+
+# Message catalog support
+NLS = @SUDO_NLS@
+POTFILES = po/sudo.pot plugins/sudoers/po/sudoers.pot
+LOCALEDIR_SUFFIX = @LOCALEDIR_SUFFIX@
+MSGFMT = msgfmt
+MSGMERGE = msgmerge
+XGETTEXT = xgettext
+XGETTEXT_OPTS = -F -k_ -kN_ -kU_ --copyright-holder="Todd C. Miller" \
+ "--msgid-bugs-address=https://bugzilla.sudo.ws" \
+ --package-name=@PACKAGE_NAME@ --package-version=$(VERSION) \
+ --flag warning:1:c-format --flag warningx:1:c-format \
+ --flag fatal:1:c-format --flag fatalx:1:c-format \
+ --flag easprintf:3:c-format --flag sudo_lbuf_append:2:c-format \
+ --flag sudo_lbuf_append_quoted:3:c-format --foreign-user
+
+# Default cppcheck options when run from the top-level Makefile
+CPPCHECK_OPTS = -q --enable=warning,performance,portability --suppress=constStatement --suppress=compareBoolExpressionWithInt --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
+
+# Default splint options when run from the top-level Makefile
+SPLINT_OPTS = -D__restrict= -checks
+
+# Default PVS-studio options when run from the top-level Makefile
+PVS_CFG = $(top_builddir)/PVS-Studio.cfg
+PVS_IGNORE = 'V707,V011,V002,V536,V568'
+PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
+
+all: config.status
+ for d in $(SUBDIRS) $(SAMPLES); do \
+ (cd $$d && exec $(MAKE) $@) && continue; \
+ exit $$?; \
+ done
+
+check check-verbose check-fuzzer fuzz pre-install: config.status
+ for d in $(SUBDIRS) $(SAMPLES); do \
+ (cd $$d && exec $(MAKE) $@) && continue; \
+ exit $$?; \
+ done
+
+uncrustify.files: Makefile
+ $(EGREP) '\.[ch]$$' $(top_srcdir)/MANIFEST | $(EGREP) -v '(/zlib/|/(arc4random|arc4random_uniform|chacha_private|charclass|fnmatch|getaddrinfo|getcwd|getdate|getentropy|getopt|getopt_long|glob|gram|inet_ntop|inet_pton|log_server.pb-c|mktemp|pw_dup|reallocarray|mktemp_test|protobuf-c|snprintf|stdbool|strlcat|strlcpy|sudo_queue|toke)\.[ch]$$)' > uncrustify.files
+
+reformat: uncrustify.files
+ ( cd $(top_srcdir) && uncrustify -c etc/uncrustify.cfg --replace --no-backup -F $(top_builddir)/uncrustify.files )
+
+check-format: uncrustify.files
+ ( cd $(top_srcdir) && uncrustify -c etc/uncrustify.cfg --check -F $(top_builddir)/uncrustify.files )
+
+spell:
+ ( cd $(top_srcdir) && codespell -I etc/codespell.ignore -x etc/codespell.exclude `$(EGREP) -v -f etc/codespell.skip MANIFEST` )
+
+cppcheck: config.status
+ rval=0; \
+ for d in $(SUBDIRS) $(SAMPLES); do \
+ echo checking $$d; \
+ (cd $$d && exec $(MAKE) CPPCHECK_OPTS="$(CPPCHECK_OPTS)" $@) || rval=`expr $$rval + $$?`; \
+ done; \
+ exit $$rval
+
+splint: config.status
+ rval=0; \
+ for d in $(SUBDIRS) $(SAMPLES); do \
+ echo splinting $$d; \
+ (cd $$d && exec $(MAKE) SPLINT_OPTS="$(SPLINT_OPTS)" $@) || rval=`expr $$rval + $$?`; \
+ done; \
+ exit $$rval
+
+cov-build:
+ make clean
+ cov-build --dir cov-int make $(MFLAGS) all
+
+cov-upload:
+ tar zcf cov-int.tgz cov-int
+ curl --form token=$$COVERITY_SUDO_TOKEN \
+ --form email=todd.miller@sudo.ws \
+ --form file=@cov-int.tgz \
+ --form version="$(VERSION)" \
+ https://scan.coverity.com/builds?project=sudo
+
+cov-analyze: cov-upload
+
+pvs-studio: config.status
+ files=; \
+ rval=0; \
+ for d in $(SUBDIRS) $(SAMPLES); do \
+ (cd $$d && exec $(MAKE) PVS_IGNORE="$(PVS_IGNORE)" pvs-log-files) || rval=`expr $$rval + $$?`; \
+ for f in $$d/*.plog; do \
+ if test "$$f" != "$$d/*.plog"; then \
+ files="$$files $$f"; \
+ fi; \
+ done; \
+ done; \
+ if test $$rval -ne 0; then \
+ exit $$rval; \
+ fi; \
+ plog-converter $(PVS_LOG_OPTS) $$files
+
+install-dirs install-binaries install-fuzzer install-includes install-plugin: config.status pre-install
+ for d in $(SUBDIRS); do \
+ (cd $$d && exec $(MAKE) "INSTALL_OWNER=$(INSTALL_OWNER)" $@) && continue; \
+ exit $$?; \
+ done
+
+install-doc: config.status ChangeLog
+ for d in $(SUBDIRS); do \
+ (cd $$d && exec $(MAKE) "INSTALL_OWNER=$(INSTALL_OWNER)" $@) && continue; \
+ exit $$?; \
+ done
+
+install: config.status ChangeLog pre-install install-nls
+ for d in $(SUBDIRS); do \
+ (cd $$d && exec $(MAKE) "INSTALL_OWNER=$(INSTALL_OWNER)" $@) && continue; \
+ exit $$?; \
+ done
+
+postinstall:
+ @POSTINSTALL@
+
+uninstall: uninstall-nls
+ for d in $(SUBDIRS); do \
+ (cd $$d && exec $(MAKE) $@) && continue; \
+ exit $$?; \
+ done
+
+uninstall-nls:
+ for pot in $(POTFILES); do \
+ domain=`basename $$pot .pot`; \
+ rm -f $(DESTDIR)$(localedir)/*/LC_MESSAGES/$$domain.mo; \
+ done
+
+siglist.c signame.c:
+ cd lib/util && exec $(MAKE) $@
+
+tsgetusershell.c:
+ cd plugins/sudoers && exec $(MAKE) $@
+
+depend: siglist.c signame.c tsgetusershell.c
+ $(scriptdir)/mkdep.pl \
+ --srcdir=$(abs_top_srcdir) --builddir=$(abs_top_builddir) \
+ lib/util/Makefile.in lib/zlib/Makefile.in \
+ lib/fuzzstub/Makefile.in lib/eventlog/Makefile.in \
+ lib/iolog/Makefile.in lib/logsrv/Makefile.in logsrvd/Makefile.in \
+ lib/protobuf-c/Makefile.in plugins/group_file/Makefile.in \
+ plugins/sample/Makefile.in plugins/sudoers/Makefile.in \
+ plugins/system_group/Makefile.in plugins/python/Makefile.in \
+ src/Makefile.in && \
+ $(top_builddir)/config.status --file $(top_builddir)/lib/util/Makefile \
+ --file $(top_builddir)/lib/zlib/Makefile \
+ --file $(top_builddir)/lib/eventlog/Makefile \
+ --file $(top_builddir)/lib/fuzzstub/Makefile \
+ --file $(top_builddir)/lib/iolog/Makefile \
+ --file $(top_builddir)/lib/logsrv/Makefile \
+ --file $(top_builddir)/lib/protobuf-c/Makefile \
+ --file $(top_builddir)/logsrvd/Makefile \
+ --file $(top_builddir)/plugins/sample/Makefile \
+ --file $(top_builddir)/plugins/group_file/Makefile \
+ --file $(top_builddir)/plugins/sudoers/Makefile \
+ --file $(top_builddir)/plugins/system_group/Makefile \
+ --file $(top_builddir)/plugins/python/Makefile \
+ --file $(top_builddir)/src/Makefile
+
+# Only try to build ChangeLog from a repo checkout, not a release tarball.
+# The CODEOWNERS file is not present in the release tarball.
+ChangeLog:
+ if test -f $(srcdir)/docs/CODEOWNERS; then \
+ if test -d $(srcdir)/.hg && hg -R $(srcdir) identify -ibt >stamp-$@.tmp 2>&1; then \
+ cmp stamp-$@.tmp stamp-$@ >/dev/null 2>&1 || { \
+ mv -f stamp-$@.tmp stamp-$@; \
+ if hg log -R $(srcdir) --template=changelog -r "sort(branch(.) or follow(), -date)" > $@.tmp; then \
+ mv -f $@.tmp $(srcdir)/$@; \
+ fi; \
+ }; \
+ elif test -d $(srcdir)/.git && git --git-dir $(srcdir)/.git describe --tags >stamp-$@.tmp 2>&1; then \
+ cmp stamp-$@.tmp stamp-$@ >/dev/null 2>&1 || { \
+ mv -f stamp-$@.tmp stamp-$@; \
+ if $(scriptdir)/log2cl.pl -R $(srcdir)/.git > $@.tmp; then \
+ mv -f $@.tmp $(srcdir)/$@; \
+ fi; \
+ }; \
+ fi; \
+ rm -f $@.tmp stamp-$@.tmp; \
+ fi
+ if test ! -f $(srcdir)/$@; then \
+ echo "ChangeLog data not available" > $(srcdir)/$@; \
+ fi
+
+config.status:
+ @if [ ! -s config.status ]; then \
+ echo "Please run configure first"; \
+ exit 1; \
+ fi
+
+libtool: $(LIBTOOL_DEPS)
+ $(SHELL) ./config.status --recheck
+
+Makefile: $(srcdir)/Makefile.in
+ ./config.status --file Makefile
+
+sync-po: rsync-po compile-po
+
+rsync-po:
+ rsync -Lrtvz translationproject.org::tp/latest/sudo/ po/
+ rsync -Lrtvz translationproject.org::tp/latest/sudoers/ plugins/sudoers/po/
+
+update-pot:
+ @if $(XGETTEXT) --help >/dev/null 2>&1; then \
+ cd $(top_srcdir); \
+ for pot in $(POTFILES); do \
+ echo "Updating $$pot"; \
+ domain=`basename $$pot .pot`; \
+ case "$$domain" in \
+ sudo) tmpfiles=; cfiles="src/*.c lib/util/*.c";; \
+ sudoers) \
+ echo "gettext \"syntax error\"" > confstr.sh; \
+ $(SED) -n 's/^.*--with-passprompt=\(.*\)$$/gettext \"\1\"/p' $(scriptdir)/mkpkg | sort -u >> confstr.sh; \
+ $(SED) -n -e 's/^badpass_message="/gettext "/p' \
+ -e 's/^passprompt="/gettext "/p' \
+ -e 's/^mailsub="/gettext "/p' configure.ac \
+ >> confstr.sh; \
+ tmpfiles=confstr.sh; \
+ cfiles="lib/eventlog/*.c lib/iolog/*.c logsrvd/*.c plugins/sudoers/*.c plugins/sudoers/auth/*.c";; \
+ *) echo unknown domain $$domain; continue;; \
+ esac; \
+ $(XGETTEXT) $(XGETTEXT_OPTS) -d$$domain $$cfiles $$tmpfiles -o $$pot.tmp; \
+ test -n "$$tmpfiles" && rm -f $$tmpfiles; \
+ if diff -I'^.POT-Creation-Date' -I'^.Project-Id-Version' -I'^#' $$pot.tmp $$pot >/dev/null; then \
+ rm -f $$pot.tmp; \
+ else \
+ printf '/^#$$/+1,$$d\nw\nq\n' | ed - $$pot; \
+ $(SED) '1,/^#$$/d' $$pot.tmp >> $$pot; \
+ rm -f $$pot.tmp; \
+ fi; \
+ done; \
+ else \
+ echo "Unable to update .pot files: $(XGETTEXT) not found" 1>&2; \
+ fi
+
+update-po: update-pot
+ @if $(MSGFMT) --help >/dev/null 2>&1; then \
+ cd $(top_srcdir); \
+ for pot in $(POTFILES); do \
+ podir=`dirname $$pot`; \
+ for po in $$podir/*.po; do \
+ echo $(ECHO_N) "Updating $$po$(ECHO_C)"; \
+ $(MSGMERGE) --update $$po $$pot; \
+ $(MSGFMT) --output /dev/null --check-format $$po || exit 1; \
+ done; \
+ done; \
+ else \
+ echo "Unable to update .po files: $(MSGFMT) not found" 1>&2; \
+ fi
+
+compile-po:
+ @if $(MSGFMT) --help >/dev/null 2>&1; then \
+ cd $(top_srcdir); \
+ rm -f Makefile.$$$$; \
+ POFILES=""; \
+ for pot in $(POTFILES); do \
+ podir=`dirname $$pot`; \
+ for po in $$podir/*.po; do \
+ POFILES="$$POFILES $$po"; \
+ done; \
+ done; \
+ echo "all: `echo $$POFILES | $(SED) 's/\.po/.mo/g'`" >> Makefile.$$$$; \
+ echo "" >> Makefile.$$$$; \
+ for po in $$POFILES; do \
+ mo=`echo $$po | $(SED) 's/po$$/mo/'`; \
+ echo "$$mo: $$po" >> Makefile.$$$$; \
+ echo " $(MSGFMT) --statistics -c -o $$mo $$po" >> Makefile.$$$$; \
+ done; \
+ $(MAKE) -f Makefile.$$$$; \
+ rm -f Makefile.$$$$; \
+ else \
+ echo "Unable to compile message catalogs: $(MSGFMT) not found" 1>&2; \
+ fi
+
+install-nls:
+ @if test "$(NLS)" = "enabled"; then \
+ for pot in $(POTFILES); do \
+ podir=`dirname $(top_srcdir)/$$pot`; \
+ domain=`basename $$pot .pot`; \
+ SUDO_LINGUAS=$${LINGUAS-"`echo $$podir/*.mo | $(SED) 's:'$$podir'/\([^ ]*\).mo:\1:g'`"}; \
+ echo $(ECHO_N) "Installing $$domain message catalogs:$(ECHO_C)"; \
+ for lang in $$SUDO_LINGUAS; do \
+ test -s $$podir/$$lang.mo || continue; \
+ echo $(ECHO_N) " $$lang$(ECHO_C)"; \
+ $(SHELL) $(scriptdir)/mkinstalldirs $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES; \
+ if test -n "$(LOCALEDIR_SUFFIX)"; then \
+ if test ! -d $(DESTDIR)$(localedir)/$$lang$(LOCALEDIR_SUFFIX); then \
+ ln -s $$lang $(DESTDIR)$(localedir)/$$lang$(LOCALEDIR_SUFFIX); \
+ fi; \
+ fi; \
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 $$podir/$$lang.mo $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$$domain.mo; \
+ done; \
+ echo ""; \
+ done; \
+ fi
+
+mkdefaults:
+ cd plugins/sudoers && exec $(MAKE) DEVEL=1 ./def_data.c ./def_data.h
+
+check-dist: update-pot compile-po mkdefaults
+ @if test -d $(srcdir)/.hg && cd $(srcdir); then \
+ if test `hg stat -am | wc -l` -ne 0; then \
+ echo "Uncommitted changes" 1>&2; \
+ hg stat -am 1>&2; \
+ exit 1; \
+ fi; \
+ fi
+
+dist: check-dist force-dist
+
+force-dist: ChangeLog $(srcdir)/MANIFEST
+ cd $(top_srcdir) && $(SED) 's/[ ].*//' MANIFEST | \
+ pax -w -x ustar -f ../$(PACKAGE_TARNAME)-$(VERSION).tar \
+ -s '/^/$(PACKAGE_TARNAME)-$(VERSION)\//' && \
+ gzip -9f ../$(PACKAGE_TARNAME)-$(VERSION).tar && \
+ ls -l ../$(PACKAGE_TARNAME)-$(VERSION).tar.gz
+
+package: @PPFILES@
+ DESTDIR=$(abs_top_builddir)/destdir; rm -rf $$DESTDIR; \
+ $(MAKE) install INSTALL_OWNER= DESTDIR=$$DESTDIR && \
+ $(MAKE) postinstall INSTALL_OWNER= DESTDIR=$$DESTDIR && \
+ for p in @PPFILES@; do \
+ $(SHELL) $(scriptdir)/pp $(PPFLAGS) --destdir=$$DESTDIR $$p \
+ srcdir=$(top_srcdir) \
+ prefix=$(prefix) \
+ bindir=$(bindir) \
+ sbindir=$(sbindir) \
+ libexecdir=$(libexecdir) \
+ includedir=$(includedir) \
+ vardir=$(vardir) \
+ rundir=$(rundir) \
+ mandir=$(mandir) \
+ localedir=$(localedir) \
+ docdir=$(docdir) \
+ exampledir=$(exampledir) \
+ sysconfdir=$(sysconfdir) \
+ sudoers_uid=$(sudoers_uid) \
+ sudoers_gid=$(sudoers_gid) \
+ sudoers_mode=$(sudoers_mode) \
+ shlib_mode=$(shlib_mode) \
+ python_version=$(python_version) \
+ version=$(VERSION) $(PPVARS); \
+ done
+
+clean: config.status
+ for d in $(SUBDIRS) $(SAMPLES); do \
+ (cd $$d && exec $(MAKE) $@); \
+ done
+ -rm -rf cov-int cov-int.tgz uncrustify.files
+
+mostlyclean: clean
+
+distclean: config.status
+ for d in $(SUBDIRS) $(SAMPLES); do \
+ (cd $$d && exec $(MAKE) $@); \
+ done
+ -rm -rf autom4te.cache ChangeLog config.cache config.h config.log \
+ config.status etc/init.d/*.sh etc/init.d/sudo.conf libtool \
+ Makefile pathnames.h stamp-*
+
+cleandir: distclean
+
+clobber: distclean
+
+realclean: distclean
+
+me:
+
+a:
+
+sandwich:
+ @if test -n "$$SUDO_USER"; then \
+ echo "Okay."; \
+ else \
+ echo "What? Make it yourself!"; \
+ fi
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean ChangeLog \
+ me a sandwich check-format reformat
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..535964e
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,4494 @@
+What's new in Sudo 1.9.15p5
+
+ * Fixed evaluation of the "lecture", "listpw", "verifypw", and
+ "fdexec" sudoers Defaults settings when used without an explicit
+ value. Previously, if specified without a value they were
+ evaluated as boolean "false", even when the negation operator
+ ('!') was not present.
+
+ * Fixed a bug introduced in sudo 1.9.14 that prevented LDAP
+ netgroup queries using the NETGROUP_BASE setting from being
+ performed.
+
+ * Sudo will now transparently rename a user's lecture file from
+ the older name-based path to the newer user-ID-based path.
+ GitHub issue #342.
+
+ * Fixed a bug introduced in sudo 1.9.15 that could cause a memory
+ allocation failure if sysconf(_SC_LOGIN_NAME_MAX) fails. Bug #1066.
+
+What's new in Sudo 1.9.15p4
+
+ * Fixed a bug introduced in sudo 1.9.15 that could prevent a user's
+ privileges from being listed by "sudo -l" if the sudoers entry
+ in /etc/nsswitch.conf contains "[SUCCESS=return]". This did not
+ affect the ability to run commands via sudo. Bug #1063.
+
+What's new in Sudo 1.9.15p3
+
+ * Always disable core dumps when sudo sends itself a fatal signal.
+ Fixes a problem where sudo could potentially dump core dump when
+ it re-sends the fatal signal to itself. This is only an issue
+ if the command received a signal that would normally result in
+ a core dump but the command did not actually dump core.
+
+ * Fixed a bug matching a command with a relative path name when
+ the sudoers rule uses shell globbing rules for the path name.
+ Bug #1062.
+
+ * Permit visudo to be run even if the local host name is not set.
+ GitHub issue #332.
+
+ * Fixed an editing error introduced in sudo 1.9.15 that could
+ prevent sudoreplay from replaying sessions correctly.
+ GitHub issue #334.
+
+ * Fixed a bug introduced in sudo 1.9.15 where "sudo -l > /dev/null"
+ could hang on Linux systems. GitHub issue #335.
+
+ * Fixed a bug introduced in sudo 1.9.15 where Solaris privileges
+ specified in sudoers were not applied to the command being run.
+
+What's new in Sudo 1.9.15p2
+
+ * Fixed a bug on BSD systems where sudo would not restore the
+ terminal settings on exit if the terminal had parity enabled.
+ GitHub issue #326.
+
+What's new in Sudo 1.9.15p1
+
+ * Fixed a bug introduced in sudo 1.9.15 that prevented LDAP-based
+ sudoers from being able to read the ldap.conf file.
+ GitHub issue #325.
+
+What's new in Sudo 1.9.15
+
+ * Fixed an undefined symbol problem on older versions of macOS
+ when "intercept" or "log_subcmds" are enabled in sudoers.
+ GitHub issue #276.
+
+ * Fixed "make check" failure related to getpwent(3) wrapping
+ on NetBSD.
+
+ * Fixed the warning message for "sudo -l command" when the command
+ is not permitted. There was a missing space between "list" and
+ the actual command due to changes in sudo 1.9.14.
+
+ * Fixed a bug where output could go to the wrong terminal if
+ "use_pty" is enabled (the default) and the standard input, output
+ or error is redirected to a different terminal. Bug #1056.
+
+ * The visudo utility will no longer create an empty file when the
+ specified sudoers file does not exist and the user exits the
+ editor without making any changes. GitHub issue #294.
+
+ * The AIX and Solaris sudo packages on www.sudo.ws now support
+ "log_subcmds" and "intercept" with both 32-bit and 64-bit
+ binaries. Previously, they only worked when running binaries
+ with the same word size as the sudo binary. GitHub issue #289.
+
+ * The sudoers source is now logged in the JSON event log. This
+ makes it possible to tell which rule resulted in a match.
+
+ * Running "sudo -ll command" now produces verbose output that
+ includes matching rule as well as the path to the sudoers file
+ the matching rule came from. For LDAP sudoers, the name of the
+ matching sudoRole is printed instead.
+
+ * The embedded copy of zlib has been updated to version 1.3.
+
+ * The sudoers plugin has been modified to make it more resilient
+ to ROWHAMMER attacks on authentication and policy matching.
+ This addresses CVE-2023-42465.
+
+ * The sudoers plugin now constructs the user time stamp file path
+ name using the user-ID instead of the user name. This avoids a
+ potential problem with user names that contain a path separator
+ ('/') being interpreted as part of the path name. A similar
+ issue in sudo-rs has been assigned CVE-2023-42456.
+
+ * A path separator ('/') in a user, group or host name is now
+ replaced with an underbar character ('_') when expanding escapes
+ in @include and @includedir directives as well as the "iolog_file"
+ and "iolog_dir" sudoers Default settings.
+
+ * The "intercept_verify" sudoers option is now only applied when
+ the "intercept" option is set in sudoers. Previously, it was
+ also applied when "log_subcmds" was enabled. Sudo 1.9.14
+ contained an incorrect fix for this. Bug #1058.
+
+ * Changes to terminal settings are now performed atomically, where
+ possible. If the command is being run in a pseudo-terminal and
+ the user's terminal is already in raw mode, sudo will not change
+ the user's terminal settings. This prevents concurrent sudo
+ processes from restoring the terminal settings to the wrong values.
+ GitHub issue #312.
+
+ * Reverted a change from sudo 1.9.4 that resulted in PAM session
+ modules being called with the environment of the command to be
+ run instead of the environment of the invoking user.
+ GitHub issue #318.
+
+ * New Indonesian translation from translationproject.org.
+
+ * The sudo_logsrvd server will now raise its open file descriptor
+ limit to the maximum allowed value when it starts up. Each
+ connection can require up to nine open file descriptors so the
+ default soft limit may be too low.
+
+ * Better log message when rejecting a command if the "intercept"
+ option is enabled and the "intercept_allow_setid" option is
+ disabled. Previously, "command not allowed" would be logged and
+ the user had no way of knowing what the actual problem was.
+
+ * Sudo will now log the invoking user's environment as "submitenv"
+ in the JSON logs. The command's environment ("runenv") is no
+ longer logged for commands rejected by the sudoers file or an
+ approval plugin.
+
+What's new in Sudo 1.9.14p3
+
+ * Fixed a crash with Python 3.12 when the sudo Python plugin is
+ unloaded. This only affects "make check" for the Python plugin.
+
+ * Adapted the sudo Python plugin test output to match Python 3.12.
+
+What's new in Sudo 1.9.14p2
+
+ * Fixed a crash on Linux systems introduced in version 1.9.14 when
+ running a command with a NULL argv[0] if "log_subcmds" or
+ "intercept" is enabled in sudoers.
+
+ * Fixed a problem with "stair-stepped" output when piping or
+ redirecting the output of a sudo command that takes user input.
+
+ * Fixed a bug introduced in sudo 1.9.14 that affects matching
+ sudoers rules containing a Runas_Spec with an empty Runas user.
+ These rules should only match when sudo's -g option is used but
+ were matching even without the -g option. GitHub issue #290.
+
+What's new in Sudo 1.9.14p1
+
+ * Fixed an invalid free bug in sudo_logsrvd that was introduced
+ in version 1.9.14 which could cause sudo_logsrvd to crash.
+
+ * The sudoers plugin no longer tries to send the terminal name
+ to the log server when no terminal is present. This bug was
+ introduced in version 1.9.14.
+
+What's new in Sudo 1.9.14
+
+ * Fixed a bug where if the "intercept" or "log_subcmds" sudoers
+ option was enabled and a sub-command was run where the first
+ entry of the argument vector didn't match the command being run.
+ This resulted in commands like "sudo su -" being killed due to
+ the mismatch. Bug #1050.
+
+ * The sudoers plugin now canonicalizes command path names before
+ matching (where possible). This fixes a bug where sudo could
+ execute the wrong path if there are multiple symbolic links with
+ the same target and the same base name in sudoers that a user is
+ allowed to run. GitHub issue #228.
+
+ * Improved command matching when a chroot is specified in sudoers.
+ The sudoers plugin will now change the root directory id needed
+ before performing command matching. Previously, the root directory
+ was simply prepended to the path that was being processed.
+
+ * When NETGROUP_BASE is set in the ldap.conf file, sudo will now
+ perform its own netgroup lookups of the host name instead of
+ using the system innetgr(3) function. This guarantees that user
+ and host netgroup lookups are performed using the same LDAP
+ server (or servers).
+
+ * Fixed a bug introduced in sudo 1.9.13 that resulted in a missing
+ " ; " separator between environment variables and the command
+ in log entries.
+
+ * The visudo utility now displays a warning when it ignores a file
+ in an include dir such as /etc/sudoers.d.
+
+ * When running a command in a pseudo-terminal, sudo will initialize
+ the terminal settings even if it is the background process.
+ Previously, sudo only initialized the pseudo-terminal when running
+ in the foreground. This fixes an issue where a program that
+ checks the window size would read the wrong value when sudo was
+ running in the background.
+
+ * Fixed a bug where only the first two digits of the TSID field
+ being was logged. Bug #1046.
+
+ * The "use_pty" sudoers option is now enabled by default. To
+ restore the historic behavior where a command is run in the
+ user's terminal, add "Defaults !use_pty" to the sudoers file.
+ GitHub issue #258.
+
+ * Sudo's "-b" option now works when the command is run in a
+ pseudo-terminal.
+
+ * When disabling core dumps, sudo now only modifies the soft limit
+ and leaves the hard limit as-is. This avoids problems on Linux
+ when sudo does not have CAP_SYS_RESOURCE, which may be the case
+ when run inside a container. GitHub issue #42.
+
+ * Sudo configuration file paths have been converted to colon-separated
+ lists of paths. This makes it possible to have configuration
+ files on a read-only file system while still allowing for local
+ modifications in a different (writable) directory. The new
+ --enable-adminconf configure option can be used to specify a
+ directory that is searched for configuration files in preference
+ to the sysconfdir (which is usually /etc).
+
+ * The NETGROUP_QUERY ldap.conf parameter can now be disabled for
+ LDAP servers that do not support querying the nisNetgroup object
+ by its nisNetgroupTriple attribute, while still allowing sudo to
+ query the LDAP server directly to determine netgroup membership.
+
+ * Fixed a long-standing bug where a sudoers rule without an explicit
+ runas list allowed the user to run a command as root and any
+ group instead of just one of the groups that root is a member
+ of. For example, a rule such as "myuser ALL = ALL" would permit
+ "sudo -u root -g othergroup" even if root did not belong to
+ "othergroup".
+
+ * Fixed a bug where a sudoers rule with an explicit runas list
+ allowed a user to run sudo commands as themselves. For example,
+ a rule such as "myuser ALL = (root) ALL", "myuser" should only
+ allow commands to be run as root (optionally using one of root's
+ groups). However, the rule also allowed the user to run
+ "sudo -u myuser -g myuser command".
+
+ * Fixed a bug that prevented the user from specifying a group on
+ the command line via "sudo -g" if the rule's Runas_Spec contained
+ a Runas_Alias.
+
+ * Sudo now requires a C compiler that conforms to ISO C99 or higher
+ to build.
+
+What's new in Sudo 1.9.13p3
+
+ * Fixed a bug introduced in sudo 1.9.13 that caused a syntax error
+ when "list" was used as a user or host name. GitHub issue #246.
+
+ * Fixed a bug that could cause sudo to hang when running a command
+ in a pseudo-terminal when there is still input buffered after a
+ command has exited.
+
+ * Fixed "sudo -U otheruser -l command". This is a regression in
+ sudo 1.9.13. GitHub issue #248.
+
+ * Fixed "sudo -l command args" when matching a command in sudoers
+ with command line arguments. This is a regression in sudo 1.9.13.
+ GitHub issue #249.
+
+What's new in Sudo 1.9.13p2
+
+ * Fixed the --enable-static-sudoers option, broken in sudo 1.9.13.
+ GitHub issue #245.
+
+ * Fixed a potential double-free bug when matching a sudoers rule
+ that contains a per-command chroot directive (CHROOT=dir). This
+ bug was introduced in sudo 1.9.8.
+
+What's new in Sudo 1.9.13p1
+
+ * Fixed a typo in the configure script that resulted in a line
+ like "]: command not found" in the output. GitHub issue #238.
+
+ * Corrected the order of the C23 [[noreturn]] attribute in function
+ prototypes. This fixes a build error with GCC 13. GitHub issue
+ #239.
+
+ * The "check" make target misbehaved when there was more than
+ one version of the UTF-8 C locale in the output of "locale -a".
+ GitHub issue #241.
+
+ * Removed a dependency on the AC_SYS_YEAR2038 macro in configure.ac.
+ This was added in autoconf 2.72 but sudo's configure.ac only
+ required autoconf 2.70.
+
+ * Relaxed the autoconf version requirement to version 2.69.
+
+What's new in Sudo 1.9.13
+
+ * Fixed a bug running relative commands via sudo when "log_subcmds"
+ is enabled. GitHub issue #194.
+
+ * Fixed a signal handling bug when running sudo commands in a shell
+ script. Signals were not being forwarded to the command when
+ the sudo process was not run in its own process group.
+
+ * Fixed a bug in cvtsudoers' LDIF parsing when the file ends without
+ a newline and a backslash is the last character of the file.
+
+ * Fixed a potential use-after-free bug with cvtsudoers filtering.
+ GitHub issue #198.
+
+ * Added a reminder to the default lecture that the password will
+ not echo. This line is only displayed when the pwfeedback option
+ is disabled. GitHub issue #195.
+
+ * Fixed potential memory leaks in error paths. GitHub issues #199,
+ #202.
+
+ * Fixed potential NULL dereferences on memory allocation failure.
+ GitHub issues #204, #211.
+
+ * Sudo now uses C23-style attributes in function prototypes instead
+ of gcc-style attributes if supported.
+
+ * Added a new "list" pseudo-command in sudoers to allow a user to
+ list another user's privileges. Previously, only root or a user
+ with the ability to run any command as either root or the target
+ user on the current host could use the -U option. This also
+ includes a fix to the log entry when a user lacks permission to
+ run "sudo -U otheruser -l command". Previously, the logs would
+ indicate that the user tried to run the actual command, now the
+ log entry includes the list operation.
+
+ * JSON logging now escapes control characters if they happen to
+ appear in the command or environment.
+
+ * New Albanian translation from translationproject.org.
+
+ * Regular expressions in sudoers or logsrvd.conf may no longer
+ contain consecutive repetition operators. This is implementation-
+ specific behavior according to POSIX, but some implementations
+ will allocate excessive amounts of memory. This mainly affects
+ the fuzzers.
+
+ * Sudo now builds AIX-style shared libraries and dynamic shared
+ objects by default instead of svr4-style. This means that the
+ default sudo plugins are now .a (archive) files that contain a
+ .so shared object file instead of bare .so files. This was done
+ to improve compatibility with the AIX Freeware ecosystem,
+ specifically, the AIX Freeware build of OpenSSL. Sudo will still
+ load svr4-style .so plugins and if a .so file is requested,
+ either via sudo.conf or the sudoers file, and only the .a file
+ is present, sudo will convert the path from plugin.so to
+ plugin.a(plugin.so) when loading it. This ensures compatibility
+ with existing configurations. To restore the old, pre-1.9.13
+ behavior, run configure using the --with-aix-soname=svr4 option.
+
+ * Sudo no longer checks the ownership and mode of the plugins that
+ it loads. Plugins are configured via either the sudo.conf or
+ sudoers file which are trusted configuration files. These checks
+ suffered from time-of-check vs. time-of-use race conditions and
+ complicate loading plugins that are not simple paths. Ownership
+ and mode checks are still performed when loading the sudo.conf
+ and sudoers files, which do not suffer from race conditions.
+ The sudo.conf "developer_mode" setting is no longer used.
+
+ * Control characters in sudo log messages and "sudoreplay -l"
+ output are now escaped in octal format. Space characters in the
+ command path are also escaped. Command line arguments that
+ contain spaces are surrounded by single quotes and any literal
+ single quote or backslash characters are escaped with a backslash.
+ This makes it possible to distinguish multiple command line
+ arguments from a single argument that contains spaces.
+
+ * Improved support for DragonFly BSD which uses a different struct
+ procinfo than either FreeBSD or 4.4BSD.
+
+ * Fixed a compilation error on Linux arm systems running older
+ kernels that may not define EM_ARM in linux/elf-em.h.
+ GitHub issue #232.
+
+ * Fixed a compilation error when LDFLAGS contains -Wl,--no-undefined.
+ Sudo will now link using -Wl,--no-undefined by default if possible.
+ GitHub issue #234.
+
+ * Fixed a bug executing a command with a very long argument vector
+ when "log_subcmds" or "intercept" is enabled on a system where
+ "intercept_type" is set to "trace". GitHub issue #194.
+
+ * When sudo is configured to run a command in a pseudo-terminal
+ but the standard input is not connected to a terminal, the command
+ will now be run as a background process. This works around a
+ problem running sudo commands in the background from a shell
+ script where changing the terminal to raw mode could interfere
+ with the interactive shell that ran the script.
+ GitHub issue #237.
+
+ * A missing include file in sudoers is no longer a fatal error
+ unless the error_recovery plugin argument has been set to false.
+
+What's new in Sudo 1.9.12p2
+
+ * Fixed a compilation error on Linux/aarch64. GitHub issue #197.
+
+ * Fixed a potential crash introduced in the fix for GitHub issue #134.
+ If a user's sudoers entry did not have any RunAs user's set,
+ running "sudo -U otheruser -l" would dereference a NULL pointer.
+
+ * Fixed a bug introduced in sudo 1.9.12 that could prevent sudo
+ from creating a I/O files when the "iolog_file" sudoers setting
+ contains six or more Xs.
+
+ * Fixed a compilation issue on AIX with the native compiler.
+ GitHub issue #231.
+
+ * Fixed CVE-2023-22809, a flaw in sudo's -e option (aka sudoedit)
+ that could allow a malicious user with sudoedit privileges to
+ edit arbitrary files.
+
+What's new in Sudo 1.9.12p1
+
+ * Sudo's configure script now does a better job of detecting when
+ the -fstack-clash-protection compiler option does not work.
+ GitHub issue #191.
+
+ * Fixed CVE-2022-43995, a potential out-of-bounds write for passwords
+ smaller than 8 characters when passwd authentication is enabled.
+ This does not affect configurations that use other authentication
+ methods such as PAM, AIX authentication or BSD authentication.
+
+ * Fixed a build error with some configurations compiling host_port.c.
+
+What's new in Sudo 1.9.12
+
+ * Fixed a bug in the ptrace-based intercept mode where the current
+ working directory could include garbage at the end.
+
+ * Fixed a compilation error on systems that lack the stdint.h
+ header. Bug #1035
+
+ * Fixed a bug when logging the command's exit status in intercept
+ mode. The wrong command could be logged with the exit status.
+
+ * For ptrace-based intercept mode, sudo will now attempt to
+ verify that the command path name, arguments and environment
+ have not changed from the time when they were authorized by the
+ security policy. The new "intercept_verify" sudoers setting can
+ be used to control this behavior.
+
+ * Fixed running commands with a relative path (e.g. ./foo) in
+ intercept mode. Previously, this would fail if sudo's current
+ working directory was different from that of the command.
+
+ * Sudo now supports passing the execve(2) system call the NULL
+ pointer for the `argv` and/or `envp` arguments when in intercept
+ mode. Linux treats a NULL pointer like an empty array.
+
+ * The sudoers LDAP schema now allows sudoUser, sudoRunasUser and
+ sudoRunasGroup to include UTF-8 characters, not just 7-bit ASCII.
+
+ * Fixed a problem with "sudo -i" on SELinux when the target user's
+ home directory is not searchable by sudo. GitHub issue #160.
+
+ * Neovim has been added to the list of visudo editors that support
+ passing the line number on the command line.
+
+ * Fixed a bug in sudo's SHA384 and SHA512 message digest padding.
+
+ * Added a new "-N" (--no-update) command line option to sudo which
+ can be used to prevent sudo from updating the user's cached
+ credentials. It is now possible to determine whether or not a
+ user's cached credentials are currently valid by running:
+
+ $ sudo -Nnv
+
+ and checking the exit value. One use case for this is to indicate
+ in a shell prompt that sudo is "active" for the user.
+
+ * PAM approval modules are no longer invoked when running sub-commands
+ in intercept mode unless the "intercept_authenticate" option is set.
+ There is a substantial performance penalty for calling into PAM
+ for each command run. PAM approval modules are still called for
+ the initial command.
+
+ * Intercept mode on Linux now uses process_vm_readv(2) and
+ process_vm_writev(2) if available.
+
+ * The XDG_CURRENT_DESKTOP environment variable is now preserved
+ by default. This makes it possible for graphical applications
+ to choose the correct theme when run via sudo.
+
+ * On 64-bit systems, if sudo fails to load a sudoers group plugin,
+ it will use system-specific heuristics to try to locate a 64-bit
+ version of the plugin.
+
+ * The cvtsudoers manual now documents the JSON and CSV output
+ formats. GitHub issue #172.
+
+ * Fixed a bug where sub-commands were not being logged to a remote
+ log server when log_subcmds was enabled. GitHub issue #174.
+
+ * The new log_stdin, log_stdout, log_stderr, log_ttyin, and log_ttyout
+ sudoers settings can be used to support more fine-grained I/O logging.
+ The sudo front-end no longer allocates a pseudo-terminal when running
+ a command if the I/O logging plugin requests logging of stdin, stdout,
+ or stderr but not terminal input/output.
+
+ * Quieted a libgcrypt run-time initialization warning.
+ This fixes Debian bug #1019428 and Ubuntu bug #1397663.
+
+ * Fixed a bug in visudo that caused literal backslashes to be removed
+ from the EDITOR environment variable. GitHub issue #179.
+
+ * The sudo Python plugin now implements the "find_spec" method instead
+ of the the deprecated "find_module". This fixes a test failure when
+ a newer version of setuptools that doesn't include "find_module" is
+ found on the system.
+
+ * Fixed a bug introduced in sudo 1.9.9 where sudo_logsrvd created
+ the process ID file, usually /var/run/sudo/sudo_logsrvd.pid, as
+ a directory instead of a plain file. The same bug could result
+ in I/O log directories that end in six or more X's being created
+ literally in addition to the name being used as a template for
+ the mkdtemp(3) function.
+
+ * Fixed a long-standing bug where a sudoers rule with a command
+ line argument of "", which indicates the command may be run with
+ no arguments, would also match a literal "" on the command line.
+ GitHub issue #182.
+
+ * Added the -I option to visudo which only edits the main sudoers
+ file. Include files are not edited unless a syntax error is found.
+
+ * Fixed "sudo -l -U otheruser" output when the runas list is empty.
+ Previously, sudo would list the invoking user instead of the
+ list user. GitHub issue #183.
+
+ * Fixed the display of command tags and options in "sudo -l" output
+ when the RunAs user or group changes. A new line is started for
+ RunAs changes which means we need to display the command tags
+ and options again. GitHub issue #184.
+
+ * The sesh helper program now uses getopt_long(3) to parse the
+ command line options.
+
+ * The embedded copy of zlib has been updated to version 1.2.13.
+
+ * Fixed a bug that prevented event log data from being sent to the
+ log server when I/O logging was not enabled. This only affected
+ systems without PAM or configurations where the pam_session and
+ pam_setcred options were disabled in the sudoers file.
+
+ * Fixed a bug where "sudo -l" output included a carriage return
+ after the newline. This is only needed when displaying to a
+ terminal in raw mode. Bug #1042.
+
+What's new in Sudo 1.9.11p3
+
+ * Fixed "connection reset" errors on AIX when running shell scripts
+ with the "intercept" or "log_subcmds" sudoers options enabled.
+ Bug #1034.
+
+ * Fixed very slow execution of shell scripts when the "intercept"
+ or "log_subcmds" sudoers options are set on systems that enable
+ Nagle's algorithm on the loopback device, such as AIX.
+ Bug #1034.
+
+What's new in Sudo 1.9.11p2
+
+ * Fixed a compilation error on Linux/x86_64 with the x32 ABI.
+
+ * Fixed a regression introduced in 1.9.11p1 that caused a warning
+ when logging to sudo_logsrvd if the command returned no output.
+
+What's new in Sudo 1.9.11p1
+
+ * Correctly handle EAGAIN in the I/O read/right events. This fixes
+ a hang seen on some systems when piping a large amount of data
+ through sudo, such as via rsync. Bug #963.
+
+ * Changes to avoid implementation or unspecified behavior when
+ bit shifting signed values in the protobuf library.
+
+ * Fixed a compilation error on Linux/aarch64.
+
+ * Fixed the configure check for seccomp(2) support on Linux.
+
+ * Corrected the EBNF specification for tags in the sudoers manual
+ page. GitHub issue #153.
+
+What's new in Sudo 1.9.11
+
+ * Fixed a crash in the Python module with Python 3.9.10 on some
+ systems. Additionally, "make check" now passes for Python 3.9.10.
+
+ * Error messages sent via email now include more details, including
+ the file name and the line number and column of the error.
+ Multiple errors are sent in a single message. Previously, only
+ the first error was included.
+
+ * Fixed logging of parse errors in JSON format. Previously,
+ the JSON logger would not write entries unless the command and
+ runuser were set. These may not be known at the time a parse
+ error is encountered.
+
+ * Fixed a potential crash parsing sudoers lines larger than twice
+ the value of LINE_MAX on systems that lack the getdelim() function.
+
+ * The tests run by "make check" now unset the LANGUAGE environment
+ variable. Otherwise, localization strings will not match if
+ LANGUAGE is set to a non-English locale. Bug #1025.
+
+ * The "starttime" test now passed when run under Debian faketime.
+ Bug #1026.
+
+ * The Kerberos authentication module now honors the custom password
+ prompt if one has been specified.
+
+ * The embedded copy of zlib has been updated to version 1.2.12.
+
+ * Updated the version of libtool used by sudo to version 2.4.7.
+
+ * Sudo now defines _TIME_BITS to 64 on systems that define __TIMESIZE
+ in the header files (currently only GNU libc). This is required
+ to allow the use of 64-bit time values on some 32-bit systems.
+
+ * Sudo's "intercept" and "log_subcmds" options no longer force the
+ command to run in its own pseudo-terminal. It is now also
+ possible to intercept the system(3) function.
+
+ * Fixed a bug in sudo_logsrvd when run in store-first relay mode
+ where the commit point messages sent by the server were incorrect
+ if the command was suspended or received a window size change
+ event.
+
+ * Fixed a potential crash in sudo_logsrvd when the "tls_dhparams"
+ configuration setting was used.
+
+ * The "intercept" and "log_subcmds" functionality can now use
+ ptrace(2) on Linux systems that support seccomp(2) filtering.
+ This has the advantage of working for both static and dynamic
+ binaries and can work with sudo's SELinux RBAC mode. The following
+ architectures are currently supported: i386, x86_64, aarch64,
+ arm, mips (log_subcmds only), powerpc, riscv, and s390x. The
+ default is to use ptrace(2) where possible; the new "intercept_type"
+ sudoers setting can be used to explicitly set the type.
+
+ * New Georgian translation from translationproject.org.
+
+ * Fixed creating packages on CentOS Stream.
+
+ * Fixed a bug in the intercept and log_subcmds support where
+ the execve(2) wrapper was using the current environment instead
+ of the passed environment pointer. Bug #1030.
+
+ * Added AppArmor integration for Linux. A sudoers rule can now
+ specify an APPARMOR_PROFILE option to run a command confined by
+ the named AppArmor profile.
+
+ * Fixed parsing of the "server_log" setting in sudo_logsrvd.conf.
+ Non-paths were being treated as paths and an actual path was
+ treated as an error.
+
+What's new in Sudo 1.9.10
+
+ * Added new "log_passwords" and "passprompt_regex" sudoers options.
+ If "log_passwords" is disabled, sudo will attempt to prevent passwords
+ from being logged. If sudo detects any of the regular expressions in
+ the "passprompt_regex" list in the terminal output, sudo will log '*'
+ characters instead of the terminal input until a newline or carriage
+ return is found in the input or an output character is received.
+
+ * Added new "log_passwords" and "passprompt_regex" settings to
+ sudo_logsrvd that operate like the sudoers options when logging
+ terminal input.
+
+ * Fixed several few bugs in the cvtsudoers utility when merging
+ multiple sudoers sources.
+
+ * Fixed a bug in sudo_logsrvd when parsing the sudo_logsrvd.conf
+ file, where the "retry_interval" in the [relay] section was not
+ being recognized.
+
+ * Restored the pre-1.9.9 behavior of not performing authentication
+ when sudo's -n option is specified. A new "noninteractive_auth"
+ sudoers option has been added to enable PAM authentication in
+ non-interactive mode. GitHub issue #131.
+
+ * On systems with /proc, if the /proc/self/stat (Linux) or
+ /proc/pid/psinfo (other systems) file is missing or invalid,
+ sudo will now check file descriptors 0-2 to determine the user's
+ terminal. Bug #1020.
+
+ * Fixed a compilation problem on Debian kFreeBSD. Bug #1021.
+
+ * Fixed a crash in sudo_logsrvd when running in relay mode if
+ an alert message is received.
+
+ * Fixed an issue that resulting in "problem with defaults entries"
+ email to be sent if a user ran sudo when the sudoers entry in
+ the nsswitch.conf file includes "sss" but no sudo provider is
+ configured in /etc/sssd/sssd.conf. Bug #1022.
+
+ * Updated the warning displayed when the invoking user is not
+ allowed to run sudo. If sudo has been configured to send mail
+ on failed attempts (see the mail_* flags in sudoers), it will
+ now print "This incident has been reported to the administrator."
+ If the "mailto" or "mailerpath" sudoers settings are disabled,
+ the message will not be printed and no mail will be sent.
+ GitHub issue #48.
+
+ * Fixed a bug where the user-specified command timeout was not
+ being honored if the sudoers rule did not also specify a timeout.
+
+ * Added support for using POSIX extended regular expressions in
+ sudoers rules. A command and/or arguments in sudoers are treated
+ as a regular expression if they start with a '^' character and
+ end with a '$'. The command and arguments are matched separately,
+ either one (or both) may be a regular expression.
+ Bug #578, GitHub issue #15.
+
+ * A user may now only run "sudo -U otheruser -l" if they have a
+ "sudo ALL" privilege where the RunAs user contains either "root"
+ or "otheruser". Previously, having "sudo ALL" was sufficient,
+ regardless of the RunAs user. GitHub issue #134.
+
+ * The sudo lecture is now displayed immediately before the password
+ prompt. As a result, sudo will no longer display the lecture
+ unless the user needs to enter a password. Authentication methods
+ that don't interact with the user via a terminal do not trigger
+ the lecture.
+
+ * Sudo now uses its own closefrom() emulation on Linux systems.
+ The glibc version may not work in a chroot jail where /proc is
+ not available. If close_range(2) is present, it will be used
+ in preference to /proc/self/fd.
+
+What's new in Sudo 1.9.9
+
+ * Sudo can now be built with OpenSSL 3.0 without generating warnings
+ about deprecated OpenSSL APIs.
+
+ * A digest can now be specified along with the "ALL" command in
+ the LDAP and SSSD back-ends. Sudo 1.9.0 introduced support for
+ this in the sudoers file but did not include corresponding changes
+ for the other back-ends.
+
+ * visudo now only warns about an undefined alias or a cycle in an
+ alias once for each alias.
+
+ * The sudoRole cn was truncated by a single character in warning messages.
+ GitHub issue #115.
+
+ * The cvtsudoers utility has new --group-file and --passwd-file options
+ to use a custom passwd or group file when the --match-local option is
+ also used.
+
+ * The cvtsudoers utility can now filter or match based on a command.
+
+ * The cvtsudoers utility can now produce output in csv (comma-separated
+ value) format. This can be used to help generate entitlement reports.
+
+ * Fixed a bug in sudo_logsrvd that could result in the connection being
+ dropped for very long command lines.
+
+ * Fixed a bug where sudo_logsrvd would not accept a restore point
+ of zero.
+
+ * Fixed a bug in visudo where the value of the "editor" setting was not
+ used if it did not match the user's EDITOR environment variable.
+ This was only a problem if the "env_editor" setting was not enabled.
+ Bug #1000.
+
+ * Sudo now builds with the -fcf-protection compiler option and the
+ "-z now" linker option if supported.
+
+ * The output of "sudoreplay -l" now more closely matches the
+ traditional sudo log format.
+
+ * The sudo_sendlog utility will now use the full contents of the log.json
+ file, if present. This makes it possible to send sudo-format I/O logs
+ that use the newer log.json format to sudo_logsrvd without losing any
+ information.
+
+ * Fixed compilation of the arc4random_buf() replacement on systems with
+ arc4random() but no arc4random_buf(). Bug #1008.
+
+ * Sudo now uses its own getentropy() by default on Linux. The GNU libc
+ version of getentropy() will fail on older kernels that don't support
+ the getrandom() system call.
+
+ * It is now possible to build sudo with WolfSSL's OpenSSL compatibility
+ layer by using the --enable-wolfssl configure option.
+
+ * Fixed a bug related to Daylight Saving Time when parsing timestamps
+ in Generalized Time format. This affected the NOTBEFORE and
+ NOTAFTER options in sudoers. Bug #1006
+
+ * Added the -O and -P options to visudo, which can be used to check
+ or set the owner and permissions. This can be used in conjunction
+ with the -c option to check that the sudoers file ownership and
+ permissions are correct. Bug #1007.
+
+ * It is now possible to set resource limits in the sudoers file itself.
+ The special values "default" and "user" refer to the default system
+ limit and invoking user limit respectively. The core dump size limit
+ is now set to 0 by default unless overridden by the sudoers file.
+
+ * The cvtsudoers utility can now merge multiple sudoers sources into
+ a single, combined sudoers file. If there are conflicting entries,
+ cvtsudoers will attempt to resolve them but manual intervention
+ may be required. The merging of sudoers rules is currently fairly
+ simplistic but will be improved in a future release.
+
+ * Sudo was parsing but not applying the "deref" and "tls_reqcert"
+ ldap.conf settings. This meant the options were effectively
+ ignored which broke dereferencing of aliases in LDAP. Bug #1013.
+
+ * Clarified in the sudo man page that the security policy may
+ override the user's PATH environment variable. Bug #1014.
+
+ * When sudo is run in non-interactive mode (with the -n option), it
+ will now attempt PAM authentication and only exit with an error
+ if user interaction is required. This allows PAM modules that
+ don't interact with the user to succeed. Previously, sudo
+ would not attempt authentication if the -n option was specified.
+ Bug #956 and GitHub issue #83.
+
+ * Fixed a regression introduced in version 1.9.1 when sudo is
+ built with the --with-fqdn configure option. The local host
+ name was being resolved before the sudoers file was processed,
+ making it impossible to disable DNS lookups by negating the
+ "fqdn" sudoers option. Bug #1016.
+
+ * Added support for negated sudoUser attributes in the LDAP and
+ SSSD sudoers back ends. A matching sudoUser that is negated
+ will cause the sudoRole containing it to be ignored.
+
+ * Fixed a bug where the stack resource limit could be set to a
+ value smaller than that of the invoking user and not be reset
+ before the command was run. Bug #1017.
+
+What's new in Sudo 1.9.8p2
+
+ * Fixed a potential out-of-bounds read with "sudo -i" when the
+ target user's shell is bash. This is a regression introduced
+ in sudo 1.9.8. Bug #998.
+
+ * sudo_logsrvd now only sends a log ID for first command of a session.
+ There is no need to send the log ID for each sub-command.
+
+ * Fixed a few minor memory leaks in intercept mode.
+
+ * Fixed a problem with sudo_logsrvd in relay mode if "store_first"
+ was enabled when handling sub-commands. A new zero-length journal
+ file was created for each sub-command instead of simply using
+ the existing journal file.
+
+ * Fixed a bug where sudoedit would fail if one of the directories
+ in the path to be edited had the immutable flag set (BSD, Linux
+ or macOS). GitHub issue #122.
+
+What's new in Sudo 1.9.8p1
+
+ * Fixed support for passing a prompt (sudo -p) or a login class
+ (sudo -c) on the command line. This is a regression introduced
+ in sudo 1.9.8. Bug #993.
+
+ * Fixed a crash with "sudo ALL" rules in the LDAP and SSSD back-ends.
+ This is a regression introduced in sudo 1.9.8. Bug #994.
+
+ * Fixed a compilation error when the --enable-static-sudoers configure
+ option was specified. This is a regression introduced in sudo
+ 1.9.8 caused by a symbol clash with the intercept and log server
+ protobuf functions.
+
+What's new in Sudo 1.9.8
+
+ * It is now possible to transparently intercepting sub-commands
+ executed by the original command run via sudo. Intercept support
+ is implemented using LD_PRELOAD (or the equivalent supported by
+ the system) and so has some limitations. The two main limitations
+ are that only dynamic executables are supported and only the
+ execl, execle, execlp, execv, execve, execvp, and execvpe library
+ functions are currently intercepted. Its main use case is to
+ support restricting privileged shells run via sudo.
+
+ To support this, there is a new "intercept" Defaults setting and
+ an INTERCEPT command tag that can be used in sudoers. For example:
+
+ Cmnd_Alias SHELLS=/bin/bash, /bin/sh, /bin/csh, /bin/ksh, /bin/zsh
+ Defaults!SHELLS intercept
+
+ would cause sudo to run the listed shells in intercept mode.
+ This can also be set on a per-rule basis. For example:
+
+ Cmnd_Alias SHELLS=/bin/bash, /bin/sh, /bin/csh, /bin/ksh, /bin/zsh
+ chuck ALL = INTERCEPT: SHELLS
+
+ would only apply intercept mode to user "chuck" when running one
+ of the listed shells.
+
+ In intercept mode, sudo will not prompt for a password before
+ running a sub-command and will not allow a set-user-ID or
+ set-group-ID program to be run by default. The new
+ intercept_authenticate and intercept_allow_setid sudoers settings
+ can be used to change this behavior.
+
+ * The new "log_subcmds" sudoers setting can be used to log additional
+ commands run in a privileged shell. It uses the same mechanism as
+ the intercept support described above and has the same limitations.
+
+ * The new "log_exit_status" sudoers setting can be used to log
+ the exit status commands run via sudo. This is also a corresponding
+ "log_exit" setting in the sudo_logsrvd.conf eventlog stanza.
+
+ * Support for logging sudo_logsrvd errors via syslog or to a file.
+ Previously, most sudo_logsrvd errors were only visible in the
+ debug log.
+
+ * Better diagnostics when there is a TLS certificate validation error.
+
+ * Using the "+=" or "-=" operators in a Defaults setting that takes
+ a string, not a list, now produces a warning from sudo and a
+ syntax error from inside visudo.
+
+ * Fixed a bug where the "iolog_mode" setting in sudoers and sudo_logsrvd
+ had no effect when creating I/O log parent directories if the I/O log
+ file name ended with the string "XXXXXX".
+
+ * Fixed a bug in the sudoers custom prompt code where the size
+ parameter that was passed to the strlcpy() function was incorrect.
+ No overflow was possible since the correct amount of memory was
+ already pre-allocated.
+
+ * The mksigname and mksiglist helper programs are now built with
+ the host compiler, not the target compiler, when cross-compiling.
+ Bug #989.
+
+ * Fixed compilation error when the --enable-static-sudoers configure
+ option was specified. This was due to a typo introduced in sudo
+ 1.9.7. GitHub PR #113.
+
+What's new in Sudo 1.9.7p2
+
+ * When formatting JSON output, octal numbers are now stored as
+ strings, not numbers. The JSON spec does not actually support
+ octal numbers with a '0' prefix.
+
+ * Fixed a compilation issue on Solaris 9.
+
+ * Sudo now can handle the getgroups() function returning a different
+ number of groups for subsequent invocations. GitHub PR #106.
+
+ * When loading a Python plugin, python_plugin.so now verifies
+ that the module loaded matches the one we tried to load. This
+ allows sudo to display a more useful error message when trying
+ to load a plugin with a name that conflicts with a Python module
+ installed in the system location.
+
+ * Sudo no longer sets the the open files resource limit to "unlimited"
+ while it runs. This avoids a problem where sudo's closefrom()
+ emulation would need to close a very large number of descriptors
+ on systems without a way to determine which ones are actually open.
+
+ * Sudo now includes a configure check for va_copy or __va_copy and
+ only defines its own version if the configure test fails.
+
+ * Fixed a bug in sudo's utmp file handling which prevented old
+ entries from being reused. As a result, the utmp (or utmpx)
+ file was appended to unnecessarily. GitHub PR #108.
+
+ * Fixed a bug introduced in sudo 1.9.7 that prevented sudo_logsrvd
+ from accepting TLS connections when OpenSSL is used. Bug #988.
+
+What's new in Sudo 1.9.7p1
+
+ * Fixed an SELinux sudoedit bug when the edited temporary file
+ could not be opened. The sesh helper would still be run even
+ when there are no temporary files available to install.
+
+ * Fixed a compilation problem on FreeBSD.
+
+ * The sudo_noexec.so file is now built as a module on all systems
+ other than macOS. This makes it possible to use other libtool
+ implementations such as slibtool. On macOS shared libraries and
+ modules are not interchangeable and the version of libtool shipped
+ with sudo must be used.
+
+ * Fixed a few bugs in the getgrouplist() emulation on Solaris when
+ reading from the local group file.
+
+ * Fixed a bug in sudo_logsrvd that prevented periodic relay server
+ connection retries from occurring in "store_first" mode.
+
+ * Disabled the nss_search()-based getgrouplist() emulation on HP-UX
+ due to a crash when the group source is set to "compat" in
+ /etc/nsswitch.conf. This is probably due to a mismatch between
+ include/compat/nss_dbdefs.h and what HP-UX uses internally. On
+ HP-UX we now just cycle through groups the slow way using
+ getgrent(). Bug #978.
+
+What's new in Sudo 1.9.7
+
+ * The "fuzz" Makefile target now runs all the fuzzers for 8192
+ passes (can be overridden via the FUZZ_RUNS variable). This makes
+ it easier to run the fuzzers in-tree. To run a fuzzer indefinitely,
+ set FUZZ_RUNS=-1, e.g. "make FUZZ_RUNS=-1 fuzz".
+
+ * Fixed fuzzing on FreeBSD where the ld.lld linker returns an
+ error by default when a symbol is multiply-defined.
+
+ * Added support for determining local IPv6 addresses on systems
+ that lack the getifaddrs() function. This now works on AIX,
+ HP-UX and Solaris (at least). Bug #969.
+
+ * Fixed a bug introduced in sudo 1.9.6 that caused "sudo -V" to
+ report a usage error. Also, when invoked as sudoedit, sudo now
+ allows a more restricted set of options that matches the usage
+ statement and documentation. GitHub issue #95.
+
+ * Fixed a crash in sudo_sendlog when the specified certificate
+ or key does not exist or is invalid. Bug #970
+
+ * Fixed a compilation error when sudo is configured with the
+ --disable-log-client option.
+
+ * Sudo's limited support for SUCCESS=return entries in nsswitch.conf
+ is now documented. Bug #971.
+
+ * Sudo now requires autoconf 2.70 or higher to regenerate the
+ configure script. Bug #972.
+
+ * sudo_logsrvd now has a relay mode which can be used to create
+ a hierarchy of log servers. By default, when a relay server is
+ defined, messages from the client are forwarded immediately to
+ the relay. However, if the "store_first" setting is enabled,
+ the log will be stored locally until the command completes and
+ then relayed. Bug #965.
+
+ * Sudo now links with OpenSSL by default if it is available unless
+ the --disable-openssl configure option is used or both the
+ --disable-log-client and --disable-log-server configure options
+ are specified.
+
+ * Fixed configure's Python version detection when the version minor
+ number is more than a single digit, for example Python 3.10.
+
+ * The sudo Python module tests now pass for Python 3.10.
+
+ * Sudo will now avoid changing the datasize resource limit
+ as long as the existing value is at least 1GB. This works around
+ a problem on 64-bit HP-UX where it is not possible to exactly
+ restore the original datasize limit. Bug #973.
+
+ * Fixed a race condition that could result in a hang when sudo is
+ executed by a process where the SIGCHLD handler is set to SIG_IGN.
+ This fixes the bug described by GitHub PR #98.
+
+ * Fixed an out-of-bounds read in sudoedit and visudo when the
+ EDITOR, VISUAL or SUDO_EDITOR environment variables end in an
+ unescaped backslash. Also fixed the handling of quote characters
+ that are escaped by a backslash. GitHub issue #99.
+
+ * Fixed a bug that prevented the "log_server_verify" sudoers option
+ from taking effect.
+
+ * The sudo_sendlog utility has a new -s option to cause it to stop
+ sending I/O records after a user-specified elapsed time. This
+ can be used to test the I/O log restart functionality of sudo_logsrvd.
+
+ * Fixed a crash introduced in sudo 1.9.4 in sudo_logsrvd when
+ attempting to restart an interrupted I/O log transfer.
+
+ * The TLS connection timeout in the sudoers log client was previously
+ hard-coded to 10 seconds. It now uses the value of log_server_timeout.
+
+ * The configure script now outputs a summary of the user-configurable
+ options at the end, separate from output of configure script tests.
+ Bug #820.
+
+ * Corrected the description of which groups may be specified via the
+ -g option in the Runas_Spec section. Bug #975.
+
+What's new in Sudo 1.9.6p1
+
+ * Fixed a regression introduced in sudo 1.9.6 that resulted in an
+ error message instead of a usage message when sudo is run with
+ no arguments.
+
+What's new in Sudo 1.9.6
+
+ * Fixed a sudo_sendlog compilation problem with the AIX xlC compiler.
+
+ * Fixed a regression introduced in sudo 1.9.4 where the
+ --disable-root-mailer configure option had no effect.
+
+ * Added a --disable-leaks configure option that avoids some
+ memory leaks on exit that would otherwise occur. This is intended
+ to be used with development tools that measure memory leaks. It
+ is not safe to use in production at this time.
+
+ * Plugged some memory leaks identified by oss-fuzz and ASAN.
+
+ * Fixed the handling of sudoOptions for an LDAP sudoRole that
+ contains multiple sudoCommands. Previously, some of the options
+ would only be applied to the first sudoCommand.
+
+ * Fixed a potential out of bounds read in the parsing of NOTBEFORE
+ and NOTAFTER sudoers command options (and their LDAP equivalents).
+
+ * The parser used for reading I/O log JSON files is now more
+ resilient when processing invalid JSON.
+
+ * Fixed typos that prevented "make uninstall" from working.
+ GitHub issue #87.
+
+ * Fixed a regression introduced in sudo 1.9.4 where the last line
+ in a sudoers file might not have a terminating NUL character
+ added if no newline was present.
+
+ * Integrated oss-fuzz and LLVM's libFuzzer with sudo. The new
+ --enable-fuzzer configure option can be combined with the
+ --enable-sanitizer option to build sudo with fuzzing support.
+ Multiple fuzz targets are available for fuzzing different parts
+ of sudo. Fuzzers are built and tested via "make fuzz" or as part
+ of "make check" (even when sudo is not built with fuzzing support).
+ Fuzzing support currently requires the LLVM clang compiler (not gcc).
+
+ * Fixed the --enable-static-sudoers configure option.
+ GitHub issue #92.
+
+ * Fixed a potential out of bounds read sudo when is run by a user
+ with more groups than the value of "max_groups" in sudo.conf.
+
+ * Added an "admin_flag" sudoers option to make the use of the
+ ~/.sudo_as_admin_successful file configurable on systems where
+ sudo is build with the --enable-admin-flag configure option.
+ This mostly affects Ubuntu and its derivatives. GitHub issue #56.
+
+ * The "max_groups" setting in sudo.conf is now limited to 1024.
+ This setting is obsolete and should no longer be needed.
+
+ * Fixed a bug in the tilde expansion of "CHROOT=dir" and "CWD=dir"
+ sudoers command options. A path "~/foo" was expanded to
+ "/home/userfoo" instead of "/home/user/foo". This also affects
+ the runchroot and runcwd Defaults settings.
+
+ * Fixed a bug on systems without a native getdelim(3) function
+ where very long lines could cause parsing of the sudoers file
+ to end prematurely. Bug #960.
+
+ * Fixed a potential integer overflow when converting the
+ timestamp_timeout and passwd_timeout sudoers settings to a
+ timespec struct.
+
+ * The default for the "group_source" setting in sudo.conf is now
+ "dynamic" on macOS. Recent versions of macOS do not reliably
+ return all of a user's non-local groups via getgroups(2), even
+ when _DARWIN_UNLIMITED_GETGROUPS is defined. Bug #946.
+
+ * Fixed a potential use-after-free in the PAM conversation function.
+ Bug #967.
+
+ * Fixed potential redefinition of sys/stat.h macros in sudo_compat.h.
+ Bug #968.
+
+What's new in Sudo 1.9.5p2
+
+ * Fixed sudo's setprogname(3) emulation on systems that don't
+ provide it.
+
+ * Fixed a problem with the sudoers log server client where a partial
+ write to the server could result the sudo process consuming large
+ amounts of CPU time due to a cycle in the buffer queue. Bug #954.
+
+ * Added a missing dependency on libsudo_util in libsudo_eventlog.
+ Fixes a link error when building sudo statically.
+
+ * The user's KRB5CCNAME environment variable is now preserved when
+ performing PAM authentication. This fixes GSSAPI authentication
+ when the user has a non-default ccache.
+
+ * When invoked as sudoedit, the same set of command line options
+ are now accepted as for "sudo -e". The -H and -P options are
+ now rejected for sudoedit and "sudo -e" which matches the sudo
+ 1.7 behavior. This is part of the fix for CVE-2021-3156.
+
+ * Fixed a potential buffer overflow when unescaping backslashes
+ in the command's arguments. Normally, sudo escapes special
+ characters when running a command via a shell (sudo -s or sudo
+ -i). However, it was also possible to run sudoedit with the -s
+ or -i flags in which case no escaping had actually been done,
+ making a buffer overflow possible. This fixes CVE-2021-3156.
+
+What's new in Sudo 1.9.5p1
+
+ * Fixed a regression introduced in sudo 1.9.5 where the editor run
+ by sudoedit was set-user-ID root unless SELinux RBAC was in use.
+ The editor is now run with the user's real and effective user-IDs.
+
+What's new in Sudo 1.9.5
+
+ * Fixed a crash introduced in 1.9.4 when running "sudo -i" as an
+ unknown user. This is related to but distinct from Bug #948.
+
+ * If the "lecture_file" setting is enabled in sudoers, it must now
+ refer to a regular file or a symbolic link to a regular file.
+
+ * Fixed a potential use-after-free bug in sudo_logsrvd when the
+ server shuts down if there are existing connections from clients
+ that are only logging events and not session I/O data.
+
+ * Fixed a buffer size mismatch when serializing the list of IP
+ addresses for configured network interfaces. This bug is not
+ actually exploitable since the allocated buffer is large enough
+ to hold the list of addresses.
+
+ * If sudo is executed with a name other than "sudo" or "sudoedit",
+ it will now fall back to "sudo" as the program name. This affects
+ warning, help and usage messages as well as the matching of Debug
+ lines in the /etc/sudo.conf file. Previously, it was possible
+ for the invoking user to manipulate the program name by setting
+ argv[0] to an arbitrary value when executing sudo.
+
+ * Sudo now checks for failure when setting the close-on-exec flag
+ on open file descriptors. This should never fail but, if it
+ were to, there is the possibility of a file descriptor leak to
+ a child process (such as the command sudo runs).
+
+ * Fixed CVE-2021-23239, a potential information leak in sudoedit
+ that could be used to test for the existence of directories not
+ normally accessible to the user in certain circumstances. When
+ creating a new file, sudoedit checks to make sure the parent
+ directory of the new file exists before running the editor.
+ However, a race condition exists if the invoking user can replace
+ (or create) the parent directory. If a symbolic link is created
+ in place of the parent directory, sudoedit will run the editor
+ as long as the target of the link exists. If the target of the
+ link does not exist, an error message will be displayed. The
+ race condition can be used to test for the existence of an
+ arbitrary directory. However, it _cannot_ be used to write to
+ an arbitrary location.
+
+ * Fixed CVE-2021-23240, a flaw in the temporary file handling of
+ sudoedit's SELinux RBAC support. On systems where SELinux is
+ enabled, a user with sudoedit permissions may be able to set the
+ owner of an arbitrary file to the user-ID of the target user.
+ On Linux kernels that support "protected symlinks", setting
+ /proc/sys/fs/protected_symlinks to 1 will prevent the bug from
+ being exploited. For more information see
+ https://www.sudo.ws/alerts/sudoedit_selinux.html.
+
+ * Added writability checks for sudoedit when SELinux RBAC is in use.
+ This makes sudoedit behavior consistent regardless of whether
+ or not SELinux RBAC is in use. Previously, the "sudoedit_checkdir"
+ setting had no effect for RBAC entries.
+
+ * A new sudoers option "selinux" can be used to disable sudo's
+ SELinux RBAC support.
+
+ * Quieted warnings from PVS Studio, clang analyzer, and cppcheck.
+ Added suppression annotations for PVS Studio false positives.
+
+What's new in Sudo 1.9.4p2
+
+ * Fixed a bug introduced in sudo 1.9.4p1 which could lead to a crash
+ if the sudoers file contains a runas user-specific Defaults entry.
+ Bug #951.
+
+What's new in Sudo 1.9.4p1
+
+ * Sudo on macOS now supports users with more than 16 groups without
+ needing to set "group_source" to "dynamic" in /etc/sudo.conf.
+ Previously, only the first 15 were used when matching group-based
+ rules in sudoers. Bug #946.
+
+ * Fixed a regression introduced in version 1.9.4 where sudo would
+ not build when configured using the --without-sendmail option.
+ Bug #947.
+
+ * Fixed a problem where if I/O logging was disabled and sudo was
+ unable to connect to sudo_logsrvd, the command would still be
+ allowed to run even when the "ignore_logfile_errors" sudoers
+ option was enabled.
+
+ * Fixed a crash introduced in version 1.9.4 when attempting to run
+ a command as a non-existent user. Bug #948.
+
+ * The installed sudo.conf file now has the default sudoers Plugin
+ lines commented out. This fixes a potential conflict when there
+ is both a system-installed version of sudo and a user-installed
+ version. GitHub issue #75.
+
+ * Fixed a regression introduced in sudo 1.9.4 where sudo would run
+ the command as a child process even when a pseudo-terminal was
+ not in use and the "pam_session" and "pam_setcred" options were
+ disabled. GitHub issue #76.
+
+ * Fixed a regression introduced in sudo 1.8.9 where the "closefrom"
+ sudoers option could not be set to a value of 3. Bug #950.
+
+What's new in Sudo 1.9.4
+
+ * The sudoers parser will now detect when an upper-case reserved
+ word is used when declaring an alias. Now instead of "syntax
+ error, unexpected CHROOT, expecting ALIAS" the message will be
+ "syntax error, reserved word CHROOT used as an alias name".
+ Bug #941.
+
+ * Better handling of sudoers files without a final newline.
+ The parser now adds a newline at end-of-file automatically which
+ removes the need for special cases in the parser.
+
+ * Fixed a regression introduced in sudo 1.9.1 in the sssd back-end
+ where an uninitialized pointer could be freed on an error path.
+ GitHub issue #67.
+
+ * The core logging code is now shared between sudo_logsrvd and
+ the sudoers plugin.
+
+ * JSON log entries sent to syslog now use "minimal" JSON which
+ skips all non-essential white space.
+
+ * The sudoers plugin can now produce JSON-formatted logs. The
+ "log_format" sudoers option can be used to select sudo or json
+ format logs. The default is sudo format logs.
+
+ * The sudoers plugin and visudo now display the column number in
+ syntax error messages in addition to the line number. Bug #841.
+
+ * If I/O logging is not enabled but "log_servers" is set, the
+ sudoers plugin will now log accept events to sudo_logsrvd.
+ Previously, the accept event was only sent when I/O logging was
+ enabled. The sudoers plugin now sends reject and alert events too.
+
+ * The sudo logsrv protocol has been extended to allow an AlertMessage
+ to contain an optional array of InfoMessage, as AcceptMessage
+ and RejectMessage already do.
+
+ * Fixed a bug in sudo_logsrvd where receipt of SIGHUP would result
+ in duplicate entries in the debug log when debugging was enabled.
+
+ * The visudo utility now supports EDITOR environment variables
+ that use single or double quotes in the command arguments.
+ Bug #942.
+
+ * The PAM session modules now run when sudo is set-user-ID root,
+ which allows a module to determine the original user-ID.
+ Bug #944.
+
+ * Fixed a regression introduced in sudo 1.8.24 in the LDAP back-end
+ where sudoNotBefore and sudoNotAfter were applied even when the
+ SUDOERS_TIMED setting was not present in ldap.conf. Bug #945.
+
+ * Sudo packages for macOS 11 now contain universal binaries that
+ support both Intel and Apple Silicon CPUs.
+
+ * For sudo_logsrvd, an empty value for the "pid_file" setting in
+ sudo_logsrvd.conf will now disable the process ID file.
+
+What's new in Sudo 1.9.3p1
+
+ * Fixed a regression introduced in sudo 1.9.3 where the configure
+ script would not detect the crypt(3) function if it was present
+ in the C library, not an additional library.
+
+ * Fixed a regression introduced in sudo 1.8.23 with shadow passwd
+ file authentication on OpenBSD. BSD authentication was not
+ affected.
+
+ * Sudo now logs when a user-specified command-line option is
+ rejected by a sudoers rule. Previously, these conditions were
+ written to the audit log, but the default sudo log file. Affected
+ command line arguments include -C (--close-from), -D (--chdir),
+ -R (--chroot), -g (--group) and -u (--user).
+
+What's new in Sudo 1.9.3
+
+ * sudoedit will now prompt the user before overwriting an existing
+ file with one that is zero-length after editing. Bug #922.
+
+ * Fixed building the Python plugin on systems with a compiler that
+ doesn't support symbol hiding.
+
+ * Sudo now uses a linker script to hide symbols even when the
+ compiler supports symbol hiding. This should make it easier to
+ detect omissions in the symbol exports file, regardless of the
+ platform.
+
+ * Fixed the libssl dependency in Debian packages for older releases
+ that use libssl1.0.0.
+
+ * Sudo and visudo now provide more detailed messages when a syntax
+ error is detected in sudoers. The offending line and token are
+ now displayed. If the parser was generated by GNU bison,
+ additional information about what token was expected is also
+ displayed. Bug #841.
+
+ * Sudoers rules must now end in either a newline or the end-of-file.
+ Previously, it was possible to have multiple rules on a single
+ line, separated by white space. The use of an end-of-line
+ terminator makes it possible to display accurate error messages.
+
+ * Sudo no longer refuses to run if a syntax error in the sudoers
+ file is encountered. The entry with the syntax error will be
+ discarded and sudo will continue to parse the file. This makes
+ recovery from a syntax error less painful on systems where sudo
+ is the primary method of superuser access. The historic behavior
+ can be restored by add "error_recovery=false" to the sudoers
+ plugin's optional arguments in sudo.conf. Bug #618.
+
+ * Fixed the sample_approval plugin's symbol exports file for systems
+ where the compiler doesn't support symbol hiding.
+
+ * Fixed a regression introduced in sudo 1.9.1 where arguments to
+ the "sudoers_policy" plugin in sudo.conf were not being applied.
+ The sudoers file is now parsed by the "sudoers_audit" plugin,
+ which is loaded implicitly when "sudoers_policy" is listed in
+ sudo.conf. Starting with sudo 1.9.3, if there are plugin arguments
+ for "sudoers_policy" but "sudoers_audit" is not listed, those
+ arguments will be applied to "sudoers_audit" instead.
+
+ * The user's resource limits are now passed to sudo plugins in
+ the user_info[] list. A plugin cannot determine the limits
+ itself because sudo changes the limits while it runs to prevent
+ resource starvation.
+
+ * It is now possible to set the working directory or change the
+ root directory on a per-command basis using the CWD and CHROOT
+ options. CWD and CHROOT are now reserved words in sudoers--they
+ can no longer be used as alias names. There are also new Defaults
+ settings, runchroot and runcwd, that can be used to set the
+ working directory or root directory on a more global basis.
+
+ * New -D (--chdir) and -R (--chroot) command line options can be
+ used to set the working directory or root directory if the sudoers
+ file allows it. This functionality is not enabled by default
+ and must be explicitly enabled in the sudoers file.
+
+ * Fixed a regression introduced in sudo 1.9.1 where the sudoers_audit
+ symbol could not be resolved when sudo is configured with the
+ --enable-static-sudoers option. Bug #936 and GitHub issue #61.
+
+What's new in Sudo 1.9.2
+
+ * Fixed package builds on RedHat Enterprise Linux 8.
+
+ * The configure script now uses pkg-config to find the openssl
+ cflags and libs where possible.
+
+ * The contents of the log.json I/O log file is now documented in
+ the sudoers manual.
+
+ * The sudoers plugin now properly exports the sudoers_audit symbol
+ on systems where the compiler lacks symbol visibility controls.
+ This caused a regression in 1.9.1 where a successful sudo command
+ was not logged due to the missing audit plugin. Bug #931.
+
+ * Fixed a regression introduced in 1.9.1 that can result in crash
+ when there is a syntax error in the sudoers file. Bug #934.
+
+What's new in Sudo 1.9.1
+
+ * Fixed an AIX-specific problem when I/O logging was enabled.
+ The terminal device was not being properly set to raw mode.
+ Bug #927.
+
+ * Corrected handling of sudo_logsrvd connections without associated
+ I/O log data. This fixes support for RejectMessage as well as
+ AcceptMessage when the expect_iobufs flag is not set.
+
+ * Added an "iolog_path" entry to the JSON-format event log produced
+ by sudo_logsrvd. Previously, it was only possible to determine
+ the I/O log file an event belonged to using sudo-format logs.
+
+ * Fixed the bundle IDs for sudo-logsrvd and sudo-python macOS packages.
+
+ * I/O log files produced by the sudoers plugin now clear the write
+ bits on the I/O log timing file when the log is complete. This
+ is consistent with how sudo_logsrvd indicates that a log is
+ complete.
+
+ * The sudoreplay utility has a new "-F" (follow) command line
+ option to allow replaying a session that is still in progress,
+ similar to "tail -f".
+
+ * The @include and @includedir directives can be used in sudoers
+ instead of #include and #includedir. In addition, include paths
+ may now have embedded white space by either using a double-quoted
+ string or escaping the space characters with a backslash.
+
+ * Fixed some Solaris 11.4 compilation errors.
+
+ * When running a command in a pty, sudo will no longer try to
+ suspend itself if the user's tty has been revoked (for instance
+ when the parent ssh daemon is killed). This fixes a bug where
+ sudo would continuously suspend the command (which would succeed),
+ then suspend itself (which would fail due to the missing tty)
+ and then resume the command.
+
+ * If sudo's event loop fails due to the tty being revoked, remove
+ the user's tty events and restart the event loop (once). This
+ fixes a problem when running "sudo reboot" in a pty on some
+ systems. When the event loop exited unexpectedly, sudo would
+ kill the command running in the pty, which in the case of "reboot",
+ could lead to the system being in a half-rebooted state.
+
+ * Fixed a regression introduced in sudo 1.8.23 in the LDAP and
+ SSSD back-ends where a missing sudoHost attribute was treated
+ as an "ALL" wildcard value. A sudoRole with no sudoHost attribute
+ is now ignored as it was prior to version 1.8.23.
+
+ * The audit plugin API has been changed slightly. The sudo front-end
+ now audits an accept event itself after all approval plugins are
+ run and the I/O logging plugins (if any) are opened. This makes
+ it possible for an audit plugin to only log a single overall
+ accept event if desired.
+
+ * The sudoers plugin can now be loaded as an audit plugin. Logging
+ of successful commands is now performed in the audit plugin's
+ accept function. As a result, commands are now only logged if
+ allowed by sudoers and all approval plugins. Commands rejected
+ by an approval plugin are now also logged by the sudoers plugin.
+
+ * Romanian translation for sudo and sudoers from translationproject.org.
+
+ * Fixed a regression introduced in sudo 1.9.0 where sudoedit did
+ not remove its temporary files after installing them. Bug #929.
+
+ * Fixed a regression introduced in sudo 1.9.0 where the iolog_file
+ setting in sudoers and sudo_logsrvd.conf caused an error if the
+ file name ended in six or more X's.
+
+What's new in Sudo 1.9.0
+
+ * Fixed a test failure in the strsig_test regress test on FreeBSD.
+
+ * The maximum length of a conversation reply has been increased
+ from 255 to 1023 characters. This allows for longer user passwords.
+ Bug #860.
+
+ * Sudo now includes a logging daemon, sudo_logsrvd, which can be
+ used to implement centralized logging of I/O logs. TLS connections
+ are supported when sudo is configured with the --enable-openssl
+ option. For more information, see the sudo_logsrvd, logsrvd.conf
+ and sudo_logsrv.proto manuals as well as the log_servers setting
+ in the sudoers manual.
+
+ The --disable-log-server and --disable-log-client configure
+ options can be used to disable building the I/O log server and/or
+ remote I/O log support in the sudoers plugin.
+
+ * The new sudo_sendlog utility can be used to test sudo_logsrvd
+ or send existing sudo I/O logs to a centralized server.
+
+ * It is now possible to write sudo plugins in Python 3 when sudo
+ is configured with the --enable-python option. See the
+ sudo_plugin_python manual for details.
+
+ Sudo 1.9.0 comes with several Python example plugins that get
+ installed sudo's examples directory.
+
+ The sudo blog article "What's new in sudo 1.9: Python"
+ (https://blog.sudo.ws/posts/2020/01/whats-new-in-sudo-1.9-python/)
+ includes a simple tutorial on writing python plugins.
+
+ * Sudo now supports an "audit" plugin type. An audit plugin
+ receives accept, reject, exit and error messages and can be used
+ to implement custom logging that is independent of the underlying
+ security policy. Multiple audit plugins may be specified in
+ the sudo.conf file. A sample audit plugin is included that
+ writes logs in JSON format.
+
+ * Sudo now supports an "approval" plugin type. An approval plugin
+ is run only after the main security policy (such as sudoers) accepts
+ a command to be run. The approval policy may perform additional
+ checks, potentially interacting with the user. Multiple approval
+ plugins may be specified in the sudo.conf file. Only if all
+ approval plugins succeed will the command be allowed.
+
+ * Sudo's -S command line option now causes the sudo conversation
+ function to write to the standard output or standard error instead
+ of the terminal device.
+
+ * Fixed a bug where if a #include or #includedir directive was the
+ last line in sudoers and there was no final newline character, it
+ was silently ignored. Bug #917.
+
+ * It is now possible to use "Cmd_Alias" instead of "Cmnd_Alias" for
+ people who find the former more natural.
+
+ * The new "pam_ruser" and "pam_rhost" sudoers settings can be used
+ to enable or disable setting the PAM remote user and/or host
+ values during PAM session setup.
+
+ * More than one SHA-2 digest may now be specified for a single
+ command. Multiple digests must be separated by a comma.
+
+ * It is now possible to specify a SHA-2 digest in conjunction with
+ the "ALL" reserved word in a command specification. This allows
+ one to give permission to run any command that matches the
+ specified digest, regardless of its path.
+
+ * Sudo and sudo_logsrvd now create an extended I/O log info file
+ in JSON format that contains additional information about the
+ command that was run, such as the host name. The sudoreplay
+ utility uses this file in preference to the legacy log file.
+
+ * The sudoreplay utility can now match on a host name in list mode.
+ The list output also now includes the host name if one is present
+ in the log file.
+
+ * For "sudo -i", if the target user's home directory does not
+ exist, sudo will now warn about the problem but run the command
+ in the current working directory. Previously, this was a fatal
+ error. Debian bug #598519.
+
+ * The command line arguments in the SUDO_COMMAND environment
+ variable are now truncated at 4096 characters. This avoids an
+ "Argument list too long" error when executing a command with a
+ large number of arguments. Bug #923 (Debian bug #596631).
+
+ * Sudo now properly ends the PAM transaction when the user
+ authenticates successfully but sudoers denies the command.
+ Debian bug #669687.
+
+ * The sudoers grammar in the manual now indicates that "sudoedit"
+ requires one or more arguments. Debian bug #571621.
+
+ * When copying the edited files to the original path, sudoedit now
+ allocates any additional space needed before writing. Previously,
+ it could truncate the destination file if the file system was
+ full. Bug #922.
+
+ * Fixed an issue where PAM session modules could be called with
+ the wrong user name when multiple users in the passwd database
+ share the the same user-ID. Debian bug #734752.
+
+ * Sudo command line options that take a value may only be specified
+ once. This is to help guard against problems caused by poorly
+ written scripts that invoke sudo with user-controlled input.
+ Bug #924.
+
+What's new in Sudo 1.8.31p1
+
+ * Sudo once again ignores a failure to restore the RLIMIT_CORE
+ resource limit, as it did prior to version 1.8.29. Linux
+ containers don't allow RLIMIT_CORE to be set back to RLIM_INFINITY
+ if we set the limit to zero, even for root, which resulted in a
+ warning from sudo.
+
+What's new in Sudo 1.8.31
+
+ * Fixed CVE-2019-18634, a buffer overflow when the "pwfeedback"
+ sudoers option is enabled on systems with uni-directional pipes.
+
+ * The "sudoedit_checkdir" option now treats a user-owned directory
+ as writable, even if it does not have the write bit set at the
+ time of check. Symbolic links will no longer be followed by
+ sudoedit in any user-owned directory. Bug #912
+
+ * Fixed sudoedit on macOS 10.15 and above where the root file system
+ is mounted read-only. Bug #913.
+
+ * Fixed a crash introduced in sudo 1.8.30 when suspending sudo
+ at the password prompt. Bug #914.
+
+ * Fixed compilation on systems where the mmap MAP_ANON flag
+ is not available. Bug #915.
+
+What's new in Sudo 1.8.30
+
+ * Fixed a warning on macOS introduced in sudo 1.8.29 when sudo
+ attempts to set the open file limit to unlimited. Bug #904.
+
+ * Sudo now closes file descriptors before changing uids. This
+ prevents a non-root process from interfering with sudo's ability
+ to close file descriptors on systems that support the prlimit(2)
+ system call.
+
+ * Sudo now treats an attempt to run "sudo sudoedit" as simply
+ "sudoedit". If the sudoers file contains a fully-qualified path
+ to sudoedit, sudo will now treat it simply as "sudoedit" (with
+ no path). Visudo will will now treat a fully-qualified path
+ to sudoedit as an error. Bug #871.
+
+ * Fixed a bug introduced in sudo 1.8.28 where sudo would warn about
+ a missing /etc/environment file on AIX and Linux when PAM is not
+ enabled. Bug #907
+
+ * Fixed a bug on Linux introduced in sudo 1.8.29 that prevented
+ the askpass program from running due to an unlimited stack size
+ resource limit. Bug #908.
+
+ * If a group provider plugin has optional arguments, the argument list
+ passed to the plugin is now NULL terminated as per the documentation.
+
+ * The user's time stamp file is now only updated if both authentication
+ and approval phases succeed. This is consistent with the behavior
+ of sudo prior to version 1.8.23. Bug #910
+
+ * The new allow_unknown_runas_id sudoers setting can be used to
+ enable or disable the use of unknown user or group IDs. Previously,
+ sudo would always allow unknown user or group IDs if the sudoers
+ entry permitted it, including via the "ALL" alias. As of sudo
+ 1.8.30, the admin must explicitly enable support for unknown IDs.
+
+ * The new runas_check_shell sudoers setting can be used to require
+ that the runas user have a shell listed in the /etc/shells file.
+ On many systems, users such as "bin", do not have a valid shell
+ and this flag can be used to prevent commands from being run as
+ those users.
+
+ * Fixed a problem restoring the SELinux tty context during reboot
+ if mctransd is killed before sudo finishes. GitHub issue #17.
+
+ * Fixed an intermittent warning on NetBSD when sudo restores the
+ initial stack size limit.
+
+What's new in Sudo 1.8.29
+
+ * The cvtsudoers command will now reject non-LDIF input when converting
+ from LDIF format to sudoers or JSON formats.
+
+ * The new log_allowed and log_denied sudoers settings make it possible
+ to disable logging and auditing of allowed and/or denied commands.
+
+ * The umask is now handled differently on systems with PAM or login.conf.
+ If the umask is explicitly set in sudoers, that value is used regardless
+ of what PAM or login.conf may specify. However, if the umask is not
+ explicitly set in sudoers, PAM or login.conf may now override the default
+ sudoers umask. Bug #900.
+
+ * For "make install", the sudoers file is no longer checked for syntax
+ errors when DESTDIR is set. The default sudoers file includes the
+ contents of /etc/sudoers.d which may not be readable as non-root.
+ Bug #902.
+
+ * Sudo now sets most resource limits to their maximum value to avoid
+ problems caused by insufficient resources, such as an inability to
+ allocate memory or open files and pipes.
+
+ * Fixed a regression introduced in sudo 1.8.28 where sudo would refuse
+ to run if the parent process was not associated with a session.
+ This was due to sudo passing a session ID of -1 to the plugin.
+
+What's new in Sudo 1.8.28p1
+
+ * The fix for Bug #869 caused "sudo -v" to prompt for a password
+ when "verifypw" is set to "all" (the default) and all of the
+ user's sudoers entries are marked with NOPASSWD. Bug #901.
+
+What's new in Sudo 1.8.28
+
+ * Sudo will now only set PAM_TTY to the empty string when no
+ terminal is present on Solaris and Linux. This workaround is
+ only needed on those systems which may have PAM modules that
+ misbehave when PAM_TTY is not set.
+
+ * The mailerflags sudoers option now has a default value even if
+ sendmail support was disabled at configure time. Fixes a crash
+ when the mailerpath sudoers option is set but mailerflags is not.
+ Bug #878.
+
+ * Sudo will now filter out last login messages on HP-UX unless it
+ a shell is being run via "sudo -s" or "sudo -i". Otherwise,
+ when trusted mode is enabled, these messages will be displayed
+ for each command.
+
+ * On AIX, when the user's password has expired and PAM is not in use,
+ sudo will now allow the user to change their password.
+ Bug #883.
+
+ * Sudo has a new -B command line option that will ring the terminal
+ bell when prompting for a password.
+
+ * Sudo no longer refuses to prompt for a password when it cannot
+ determine the user's terminal as long as it can open /dev/tty.
+ This allows sudo to function on systems where /proc is unavailable,
+ such as when running in a chroot environment.
+
+ * The "env_editor" sudoers flag is now on by default. This makes
+ source builds more consistent with the packages generated by
+ sudo's mkpkg script.
+
+ * Sudo no longer ships with pre-formatted copies of the manual pages.
+ These were included for systems like IRIX that don't ship with an
+ nroff utility. There are now multiple Open Source nroff replacements
+ so this should no longer be an issue.
+
+ * Fixed a bad interaction with configure's --prefix and
+ --disable-shared options. Bug #886.
+
+ * More verbose error message when a password is required and no terminal
+ is present. Bug #828.
+
+ * Command tags, such as NOPASSWD, are honored when a user tries to run a
+ command that is allowed by sudoers but which does not actually
+ exist on the file system. Bug #888.
+
+ * Asturian translation for sudoers from translationproject.org.
+
+ * I/O log timing files now store signal suspend and resume information
+ in the form of a signal name instead of a number.
+
+ * Fixed a bug introduced in 1.8.24 that prevented sudo from honoring
+ the value of "ipa_hostname" from sssd.conf, if specified, when
+ matching the host name.
+
+ * Fixed a bug introduced in 1.8.21 that prevented the core dump
+ resource limit set in the pam_limits module from taking effect.
+ Bug #894.
+
+ * Fixed parsing of double-quoted Defaults group and netgroup bindings.
+
+ * The user ID is now used when matching sudoUser attributes in LDAP.
+ Previously, the user name, group name and group IDs were used
+ when matching but not the user ID.
+
+ * Sudo now writes PAM messages to the user's terminal, if available,
+ instead of the standard output or standard error. This prevents
+ PAM output from being intermixed with that of the command when
+ output is sent to a file or pipe. Bug #895.
+
+ * Sudoedit now honors the umask and umask_override settings in sudoers.
+ Previously, the user's umask was used as-is.
+
+ * Fixed a bug where the terminal's file context was not restored
+ when using SELinux RBAC. Bug #898.
+
+ * Fixed CVE-2019-14287, a bug where a sudo user may be able to
+ run a command as root when the Runas specification explicitly
+ disallows root access as long as the ALL keyword is listed first.
+
+What's new in Sudo 1.8.27
+
+ * On HP-UX, sudo will now update the utmps file when running a command
+ in a pseudo-tty. Previously, only the utmp and utmpx files were
+ updated.
+
+ * Nanosecond precision file time stamps are now supported in HP-UX.
+
+ * Fixes and clarifications to the sudo plugin documentation.
+
+ * The sudo manuals no longer require extensive post-processing to
+ hide system-specific features. Conditionals in the roff source
+ are now used instead. This fixes corruption of the sudo manual
+ on systems without BSD login classes. Bug #861.
+
+ * If an I/O logging plugin is configured but the plugin does not
+ actually log any I/O, sudo will no longer force the command to
+ be run in a pseudo-tty.
+
+ * The fix for bug #843 in sudo 1.8.24 was incomplete. If the
+ user's password was expired or needed to be updated, but no sudo
+ password was required, the PAM handle was freed too early,
+ resulting in a failure when processing PAM session modules.
+
+ * In visudo, it is now possible to specify the path to sudoers
+ without using the -f option. Bug #864.
+
+ * Fixed a bug introduced in sudo 1.8.22 where the utmp (or utmpx)
+ file would not be updated when a command was run in a pseudo-tty.
+ Bug #865.
+
+ * Sudo now sets the silent flag when opening the PAM session except
+ when running a shell via "sudo -s" or "sudo -i". This prevents
+ the pam_lastlog module from printing the last login information
+ for each sudo command. Bug #867.
+
+ * Fixed the default AIX hard resource limit for the maximum number
+ of files a user may have open. If no hard limit for "nofiles"
+ is explicitly set in /etc/security/limits, the default should
+ be "unlimited". Previously, the default hard limit was 8196.
+
+What's new in Sudo 1.8.26
+
+ * Fixed a bug in cvtsudoers when converting to JSON format when
+ alias expansion is enabled. Bug #853.
+
+ * Sudo no long sets the USERNAME environment variable when running
+ commands. This is a non-standard environment variable that was
+ set on some older Linux systems.
+
+ * Sudo now treats the LOGNAME and USER environment variables (as
+ well as the LOGIN variable on AIX) as a single unit. If one is
+ preserved or removed from the environment using env_keep, env_check
+ or env_delete, so is the other.
+
+ * Added support for OpenLDAP's TLS_REQCERT setting in ldap.conf.
+
+ * Sudo now logs when the command was suspended and resumed in the
+ I/O logs. This information is used by sudoreplay to skip the
+ time suspended when replaying the session unless the new -S flag
+ is used.
+
+ * Fixed documentation problems found by the igor utility. Bug #854.
+
+ * Sudo now prints a warning message when there is an error or end
+ of file while reading the password instead of exiting silently.
+
+ * Fixed a bug in the sudoers LDAP back-end parsing the command_timeout,
+ role, type, privs and limitprivs sudoOptions. This also affected
+ cvtsudoers conversion from LDIF to sudoers or JSON.
+
+ * Fixed a bug that prevented timeout settings in sudoers from
+ functioning unless a timeout was also specified on the command
+ line.
+
+ * Asturian translation for sudo from translationproject.org.
+
+ * When generating LDIF output, cvtsudoers can now be configured
+ to pad the sudoOrder increment such that the start order is used
+ as a prefix. Bug #856.
+
+ * Fixed a bug introduced in sudo 1.8.25 that prevented sudo from
+ properly setting the user's groups on AIX. Bug #857.
+
+ * If the user specifies a group via sudo's -g option that matches
+ any of the target user's groups, it is now allowed even if no
+ groups are present in the Runas_Spec. Previously, it was only
+ allowed if it matched the target user's primary group.
+
+ * The sudoers LDAP back-end now supports negated sudoRunAsUser and
+ sudoRunAsGroup entries.
+
+ * Sudo now provides a proper error message when the "fqdn" sudoers
+ option is set and it is unable to resolve the local host name.
+ Bug #859.
+
+ * Portuguese translation for sudo and sudoers from translationproject.org.
+
+ * Sudo now includes sudoers LDAP schema for the on-line configuration
+ supported by OpenLDAP.
+
+What's new in Sudo 1.8.25p1
+
+ * Fixed a bug introduced in sudo 1.8.25 that caused a crash on
+ systems that have the poll() function but not the ppoll() function.
+ Bug #851.
+
+What's new in Sudo 1.8.25
+
+ * Fixed a bug introduced in sudo 1.8.20 that broke formatting of
+ I/O log timing file entries on systems without a C99-compatible
+ snprintf() function. Our replacement snprintf() doesn't support
+ floating point so we can't use the "%f" format directive.
+
+ * I/O log timing file entries now use a monotonic timer and include
+ nanosecond precision. A monotonic timer that does not increment
+ while the system is sleeping is used where available.
+
+ * Fixed a bug introduced in sudo 1.8.24 where sudoNotAfter in the LDAP
+ back-end was not being properly parsed. Bug #845.
+
+ * When sudo runs a command in a pseudo-terminal, the follower
+ device is now closed in the main process immediately after
+ starting the monitor process. This removes the need for an
+ AIX-specific workaround that was added in sudo 1.8.24.
+
+ * Added support for monotonic timers on HP-UX.
+
+ * Fixed a bug displaying timeout values the "sudo -V" output.
+ The value displayed was 3600 times the actual value. Bug #846.
+
+ * Fixed a build issue on AIX 7.1 BOS levels that include memset_s()
+ and define rsize_t in string.h. Bug #847.
+
+ * The testsudoers utility now supports querying an LDIF-format
+ policy.
+
+ * Sudo now sets the LOGIN environment variable to the same value as
+ LOGNAME on AIX systems. Bug #848.
+
+ * Fixed a regression introduced in sudo 1.8.24 where the LDAP and
+ SSSD back-ends evaluated the rules in reverse sudoOrder. Bug #849.
+
+What's new in Sudo 1.8.24
+
+ * The LDAP and SSS back-ends now use the same rule evaluation code
+ as the sudoers file back-end. This builds on the work in sudo
+ 1.8.23 where the formatting functions for "sudo -l" output were
+ shared. The handling of negated commands in SSS and LDAP is
+ unchanged.
+
+ * Fixed a regression introduced in 1.8.23 where "sudo -i" could
+ not be used in conjunction with --preserve-env=VARIABLE. Bug #835.
+
+ * cvtsudoers can now parse base64-encoded attributes in LDIF files.
+
+ * Random insults are now more random.
+
+ * Fixed the noexec wordexp(3) test on FreeBSD.
+
+ * Added SUDO_CONV_PREFER_TTY flag for conversation function to
+ tell sudo to try writing to /dev/tty first. Can be used in
+ conjunction with SUDO_CONV_INFO_MSG and SUDO_CONV_ERROR_MSG.
+
+ * Sudo now supports an arbitrary number of groups per user on
+ Solaris. Previously, only the first 64 groups were found.
+ This should remove the need to set "max_groups" in sudo.conf.
+
+ * Fixed typos in the OpenLDAP sudo schema. Bugs #839 and #840.
+
+ * Fixed a race condition when building with parallel make.
+ Bug #842.
+
+ * Fixed a duplicate free when netgroup_base in ldap.conf is set
+ to an invalid value.
+
+ * Fixed a bug introduced in sudo 1.8.23 on AIX that could prevent
+ local users and groups from being resolved properly on systems
+ that have users stored in NIS, LDAP or AD.
+
+ * Added a workaround for an AIX bug exposed by a change in sudo
+ 1.8.23 that prevents the terminal mode from being restored when
+ I/O logging is enabled.
+
+ * On systems using PAM, sudo now ignores the PAM_NEW_AUTHTOK_REQD
+ and PAM_AUTHTOK_EXPIRED errors from PAM account management if
+ authentication is disabled for the user. This fixes a regression
+ introduced in sudo 1.8.23. Bug #843.
+
+ * Fixed an ambiguity in the sudoers manual in the description and
+ definition of User, Runas, Host, and Cmnd Aliases. Bug #834.
+
+ * Fixed a bug that resulted in only the first window size change
+ event being logged.
+
+ * Fixed a bug on HP-UX systems introduced in sudo 1.8.22 that
+ caused sudo to prompt for a password every time when tty-based
+ time stamp files were in use.
+
+ * Fixed a compilation problem on systems that define O_PATH or
+ O_SEARCH in fnctl.h but do not define O_DIRECTORY. Bug #844.
+
+What's new in Sudo 1.8.23
+
+ * PAM account management modules and BSD auth approval modules are
+ now run even when no password is required.
+
+ * For kernel-based time stamps, if no terminal is present, fall
+ back to parent-pid style time stamps.
+
+ * The new cvtsudoers utility replaces both the "sudoers2ldif" script
+ and the "visudo -x" functionality. It can read a file in either
+ sudoers or LDIF format and produce JSON, LDIF or sudoers output.
+ It is also possible to filter the generated output file by user,
+ group or host name.
+
+ * The file, ldap and sss sudoers back-ends now share a common set
+ of formatting functions for "sudo -l" output, which is also used
+ by the cvtsudoers utility.
+
+ * The /run directory is now used in preference to /var/run if it
+ exists. Bug #822.
+
+ * More accurate descriptions of the --with-rundir and --with-vardir
+ configure options. Bug #823.
+
+ * The setpassent() and setgroupent() functions are now used on systems
+ that support them to keep the passwd and group database open.
+ Sudo performs a lot of passwd and group lookups so it can be
+ beneficial to avoid opening and closing the files each time.
+
+ * The new case_insensitive_user and case_insensitive_group sudoers
+ options can be used to control whether sudo does case-sensitive
+ matching of users and groups in sudoers. Case insensitive
+ matching is now the default.
+
+ * Fixed a bug on some systems where sudo could hang on command
+ exit when I/O logging was enabled. Bug #826.
+
+ * Fixed the build-time process start time test on Linux when the
+ test is run from within a container. Bug #829.
+
+ * When determining which temporary directory to use, sudoedit now
+ checks the directory for writability before using it. Previously,
+ sudoedit only performed an existence check. Bug #827.
+
+ * Sudo now includes an optional set of Monty Python-inspired insults.
+
+ * Fixed the execution of scripts with an associated digest (checksum)
+ in sudoers on FreeBSD systems. FreeBSD does not have a proper
+ /dev/fd directory mounted by default and its fexecve(2) is not
+ fully POSIX compliant when executing scripts. Bug #831.
+
+ * Chinese (Taiwan) translation for sudo from translationproject.org.
+
+What's new in Sudo 1.8.22
+
+ * Commands run in the background from a script run via sudo will
+ no longer receive SIGHUP when the parent exits and I/O logging
+ is enabled. Bug #502
+
+ * A particularly offensive insult is now disabled by default.
+ Bug #804
+
+ * The description of "sudo -i" now correctly documents that
+ the "env_keep" and "env_check" sudoers options are applied to
+ the environment. Bug #806
+
+ * Fixed a crash when the system's host name is not set.
+ Bug #807
+
+ * The sudoers2ldif script now handles #include and #includedir
+ directives.
+
+ * Fixed a bug where sudo would silently exit when the command was
+ not allowed by sudoers and the "passwd_tries" sudoers option
+ was set to a value less than one.
+
+ * Fixed a bug with the "listpw" and "verifypw" sudoers options and
+ multiple sudoers sources. If the option is set to "all", a
+ password should be required unless none of a user's sudoers
+ entries from any source require authentication.
+
+ * Fixed a bug with the "listpw" and "verifypw" sudoers options in
+ the LDAP and SSSD back-ends. If the option is set to "any", and
+ the entry contained multiple rules, only the first matching rule
+ was checked. If an entry contained more than one matching rule
+ and the first rule required authentication but a subsequent rule
+ did not, sudo would prompt for a password when it should not have.
+
+ * When running a command as the invoking user (not root), sudo
+ would execute the command with the same group vector it was
+ started with. Sudo now executes the command with a new group
+ vector based on the group database which is consistent with
+ how su(1) operates.
+
+ * Fixed a double free in the SSSD back-end that could occur when
+ ipa_hostname is present in sssd.conf and is set to an unqualified
+ host name.
+
+ * When I/O logging is enabled, sudo will now write to the terminal
+ even when it is a background process. Previously, sudo would
+ only write to the tty when it was the foreground process when
+ I/O logging was enabled. If the TOSTOP terminal flag is set,
+ sudo will suspend the command (and then itself) with the SIGTTOU
+ signal.
+
+ * A new "authfail_message" sudoers option that overrides the
+ default "N incorrect password attempt(s)".
+
+ * An empty sudoRunAsUser attribute in the LDAP and SSSD back-ends
+ will now match the invoking user. This is more consistent with
+ how an empty runas user in the sudoers file is treated.
+
+ * Documented that in check mode, visudo does not check the owner/mode
+ on files specified with the -f flag. Bug #809.
+
+ * It is now an error to specify the runas user as an empty string
+ on the command line. Previously, an empty runas user was treated
+ the same as an unspecified runas user. Bug #817.
+
+ * When "timestamp_type" option is set to "tty" and a terminal is
+ present, the time stamp record will now include the start time
+ of the session leader. When the "timestamp_type" option is set
+ to "ppid" or when no terminal is available, the start time of
+ the parent process is used instead. This significantly reduces
+ the likelihood of a time stamp record being re-used when a user
+ logs out and back in again. Bug #818.
+
+ * The sudoers time stamp file format is now documented in the new
+ sudoers_timestamp manual.
+
+ * The "timestamp_type" option now takes a "kernel" value on OpenBSD
+ systems. This causes the tty-based time stamp to be stored in
+ the kernel instead of on the file system. If no tty is present,
+ the time stamp is considered to be invalid.
+
+ * Visudo will now use the SUDO_EDITOR environment variable (if
+ present) in addition to VISUAL and EDITOR.
+
+What's new in Sudo 1.8.21p2
+
+ * Fixed a bug introduced in version 1.8.21 which prevented sudo
+ from using the PAM-supplied prompt. Bug #799
+
+ * Fixed a bug introduced in version 1.8.21 which could result in
+ sudo hanging when running commands that exit quickly. Bug #800
+
+ * Fixed a bug introduced in version 1.8.21 which prevented the
+ command from being run when the password was read via an external
+ program using the askpass interface. Bug #801
+
+What's new in Sudo 1.8.21p1
+
+ * On systems that support both PAM and SIGINFO, the main sudo
+ process will no longer forward SIGINFO to the command if the
+ signal was generated from the keyboard. The command will have
+ already received SIGINFO since it is part of the same process
+ group so there's no need for sudo to forward it. This is
+ consistent with the handling of SIGINT, SIGQUIT and SIGTSTP.
+ Bug #796
+
+ * If SUDOERS_SEARCH_FILTER in ldap.conf does not specify a value,
+ the LDAP search expression used when looking up netgroups and
+ non-Unix groups had a syntax error if a group plugin was not
+ specified.
+
+ * "sudo -U otheruser -l" will now have an exit value of 0 even
+ if "otheruser" has no sudo privileges. The exit value when a
+ user attempts to lists their own privileges or when a command
+ is specified is unchanged.
+
+ * Fixed a regression introduced in sudo 1.8.21 where sudoreplay
+ playback would hang for I/O logs that contain terminal input.
+
+ * Sudo 1.8.18 contained an incomplete fix for the matching of
+ entries in the LDAP and SSSD back-ends when a sudoRunAsGroup is
+ specified but no sudoRunAsUser is present in the sudoRole.
+
+What's new in Sudo 1.8.21
+
+ * The path that sudo uses to search for terminal devices can now
+ be configured via the new "devsearch" Path setting in sudo.conf.
+
+ * It is now possible to preserve bash shell functions in the
+ environment when the "env_reset" sudoers setting is disabled by
+ removing the "*=()*" pattern from the env_delete list.
+
+ * A change made in sudo 1.8.15 inadvertently caused sudoedit to
+ send itself SIGHUP instead of exiting when the editor returns
+ an error or the file was not modified.
+
+ * Sudoedit now uses an exit code of zero if the file was not
+ actually modified. Previously, sudoedit treated a lack of
+ modifications as an error.
+
+ * When running a command in a pseudo-tty (pty), sudo now copies a
+ subset of the terminal flags to the new pty. Previously, all
+ flags were copied, even those not appropriate for a pty.
+
+ * Fixed a problem with debug logging in the sudoers I/O logging
+ plugin.
+
+ * Window size change events are now logged to the policy plugin.
+ On xterm and compatible terminals, sudoreplay is now capable of
+ resizing the terminal to match the size of the terminal the
+ command was run on. The new -R option can be used to disable
+ terminal resizing.
+
+ * Fixed a bug in visudo where a newly added file was not checked
+ for syntax errors. Bug #791.
+
+ * Fixed a bug in visudo where if a syntax error in an include
+ directory (like /etc/sudoers.d) was detected, the edited version
+ was left as a temporary file instead of being installed.
+
+ * On PAM systems, sudo will now treat "username's Password:" as
+ a standard password prompt. As a result, the SUDO_PROMPT
+ environment variable will now override "username's Password:"
+ as well as the more common "Password:". Previously, the
+ "passprompt_override" Defaults setting would need to be set for
+ SUDO_PROMPT to override a prompt of "username's Password:".
+
+ * A new "syslog_pid" sudoers setting has been added to include
+ sudo's process ID along with the process name when logging via
+ syslog. Bug #792.
+
+ * Fixed a bug introduced in sudo 1.8.18 where a command would
+ not be terminated when the I/O logging plugin returned an error
+ to the sudo front-end.
+
+ * A new "timestamp_type" sudoers setting has been added that replaces
+ the "tty_tickets" option. In addition to tty and global time stamp
+ records, it is now possible to use the parent process ID to restrict
+ the time stamp to commands run by the same process, usually the shell.
+ Bug #793.
+
+ * The --preserve-env command line option has been extended to accept
+ a comma-separated list of environment variables to preserve.
+ Bug #279.
+
+ * Friulian translation for sudo from translationproject.org.
+
+What's new in Sudo 1.8.20p2
+
+ * Fixed a bug parsing /proc/pid/stat on Linux when the process
+ name contains newlines. This is not exploitable due to the /dev
+ traversal changes in sudo 1.8.20p1.
+
+What's new in Sudo 1.8.20p1
+
+ * Fixed "make check" when using OpenSSL or GNU crypt.
+ Bug #787.
+
+ * Fixed CVE-2017-1000367, a bug parsing /proc/pid/stat on Linux
+ when the process name contains spaces. Since the user has control
+ over the command name, this could potentially be used by a user
+ with sudo access to overwrite an arbitrary file on systems with
+ SELinux enabled. Also stop performing a breadth-first traversal
+ of /dev when looking for the device; only a hard-coded list of
+ directories are checked,
+
+What's new in Sudo 1.8.20
+
+ * Added support for SASL_MECH in ldap.conf. Bug #764
+
+ * Added support for digest matching when the command is a glob-style
+ pattern or a directory. Previously, only explicit path matches
+ supported digest checks.
+
+ * New "fdexec" Defaults option to control whether a command
+ is executed by path or by open file descriptor.
+
+ * The embedded copy of zlib has been upgraded to version 1.2.11.
+
+ * Fixed a bug that prevented sudoers include files with a relative
+ path starting with the letter 'i' from being opened. Bug #776.
+
+ * Added support for command timeouts in sudoers. The command will
+ be terminated if the timeout expires.
+
+ * The SELinux role and type are now displayed in the "sudo -l"
+ output for the LDAP and SSSD back-ends, just as they are in the
+ sudoers back-end.
+
+ * A new command line option, -T, can be used to specify a command
+ timeout as long as the user-specified timeout is not longer than
+ the timeout specified in sudoers. This option may only be
+ used when the "user_command_timeouts" flag is enabled in sudoers.
+
+ * Added NOTBEFORE and NOTAFTER command options to the sudoers
+ back-end similar to what is already available in the LDAP back-end.
+
+ * Sudo can now optionally use the SHA2 functions in OpenSSL or GNU
+ crypt instead of the SHA2 implementation bundled with sudo.
+
+ * Fixed a compilation error on systems without the stdbool.h header
+ file. Bug #778.
+
+ * Fixed a compilation error in the standalone Kerberos V authentication
+ module. Bug #777.
+
+ * Added the iolog_flush flag to sudoers which causes I/O log data
+ to be written immediately to disk instead of being buffered.
+
+ * I/O log files are now created with group ID 0 by default unless
+ the "iolog_user" or "iolog_group" options are set in sudoers.
+
+ * It is now possible to store I/O log files on an NFS-mounted
+ file system where uid 0 is remapped to an unprivileged user.
+ The "iolog_user" option must be set to a non-root user and the
+ top-level I/O log directory must exist and be owned by that user.
+
+ * Added the restricted_env_file setting to sudoers which is similar
+ to env_file but its contents are subject to the same restrictions
+ as variables in the invoking user's environment.
+
+ * Fixed a use after free bug in the SSSD back-end when the fqdn
+ sudoOption is enabled and no hostname value is present in
+ /etc/sssd/sssd.conf.
+
+ * Fixed a typo that resulted in a compilation error on systems
+ where the killpg() function is not found by configure.
+
+ * Fixed a compilation error with the included version of zlib
+ when sudo was built outside the source tree.
+
+ * Fixed the exit value of sudo when the command is terminated by
+ a signal other than SIGINT. This was broken in sudo 1.8.15 by
+ the fix for Bug #722. Bug #784.
+
+ * Fixed a regression introduced in sudo 1.8.18 where the "lecture"
+ option could not be used in a positive boolean context, only
+ a negative one.
+
+ * Fixed an issue where sudo would consume stdin if it was not
+ connected to a tty even if log_input is not enabled in sudoers.
+ Bug #786.
+
+ * Clarify in the sudoers manual that the #includedir directive
+ diverts control to the files in the specified directory and,
+ when parsing of those files is complete, returns control to the
+ original file. Bug #775.
+
+What's new in Sudo 1.8.19p2
+
+ * Fixed a crash in visudo introduced in sudo 1.8.9 when an IP address
+ or network is used in a host-based Defaults entry. Bug #766
+
+ * Added a missing check for the ignore_iolog_errors flag when
+ the sudoers plugin generates the I/O log file path name.
+
+ * Fixed a typo in sudo's vsyslog() replacement that resulted in
+ garbage being logged to syslog.
+
+What's new in Sudo 1.8.19p1
+
+ * Fixed a bug introduced in sudo 1.8.19 that resulted in the wrong
+ syslog priority and facility being used.
+
+What's new in Sudo 1.8.19
+
+ * New "syslog_maxlen" Defaults option to control the maximum size of
+ syslog messages generated by sudo.
+
+ * Sudo has been run against PVS-Studio and any issues that were
+ not false positives have been addressed.
+
+ * I/O log files are now created with the same group ID as the
+ parent directory and not the invoking user's group ID.
+
+ * I/O log permissions and ownership are now configurable via the
+ "iolog_mode", "iolog_user" and "iolog_group" sudoers Defaults
+ variables.
+
+ * Fixed configuration of the sudoers I/O log plugin debug subsystem.
+ Previously, I/O log information was not being written to the
+ sudoers debug log.
+
+ * Fixed a bug in visudo that broke editing of files in an include
+ dir that have a syntax error. Normally, visudo does not edit
+ those files, but if a syntax error is detected in one, the user
+ should get a chance to fix it.
+
+ * Warnings about unknown or unparsable sudoers Defaults entries now
+ include the file and line number of the problem.
+
+ * Visudo will now use the file and line number information about an
+ unknown or unparsable Defaults entry to go directly to the file
+ with the problem.
+
+ * Fixed a bug in the sudoers LDAP back-end where a negated sudoHost
+ entry would prevent other sudoHost entries following it from matching.
+
+ * Warnings from visudo about a cycle in an Alias entry now include the
+ file and line number of the problem.
+
+ * In strict mode, visudo will now use the file and line number
+ information about a cycle in an Alias entry to go directly to the
+ file with the problem.
+
+ * The sudo_noexec.so file is now linked with -ldl on systems that
+ require it for the wordexp() wrapper.
+
+ * Fixed linking of sudo_noexec.so on macOS systems where it must be
+ a dynamic library and not a module.
+
+ * Sudo's "make check" now includes a test for sudo_noexec.so
+ working.
+
+ * The sudo front-end now passes the user's umask to the plugin.
+ Previously the plugin had to determine this itself.
+
+ * Sudoreplay can now display the stdin and ttyin streams when they
+ are explicitly added to the filter list.
+
+ * Fixed a bug introduced in sudo 1.8.17 where the "all" setting
+ for verifypw and listpw was not being honored. Bug #762.
+
+ * The syslog priority (syslog_goodpri and syslog_badpri) can now
+ be negated or set to "none" to disable logging of successful or
+ unsuccessful sudo attempts via syslog.
+
+What's new in Sudo 1.8.18p1
+
+ * When sudo_noexec.so is used, the WRDE_NOCMD flag is now added
+ if the wordexp() function is called. This prevents commands
+ from being run via wordexp() without disabling it entirely.
+
+ * On Linux systems, sudo_noexec.so now uses a seccomp filter to
+ disable execute access if the kernel supports seccomp. This is
+ more robust than the traditional method of using stub functions
+ that return an error.
+
+What's new in Sudo 1.8.18
+
+ * The sudoers locale is now set before parsing the sudoers file.
+ If sudoers_locale is set in sudoers, it is applied before
+ evaluating other Defaults entries. Previously, sudoers_locale
+ was used when evaluating sudoers but not during the initial parse.
+ Bug #748.
+
+ * A missing or otherwise invalid #includedir is now ignored instead
+ of causing a parse error.
+
+ * During "make install", backup files are only used on HP-UX where
+ it is not possible to unlink a shared object that is in use.
+ This works around a bug in ldconfig on Linux which could create
+ links to the backup shared library file instead of the current
+ one.
+
+ * Fixed a bug introduced in 1.8.17 where sudoers entries with long
+ commands lines could be truncated, preventing a match. Bug #752.
+
+ * The fqdn, runas_default and sudoers_locale Defaults settings are
+ now applied before any other Defaults settings since they can
+ change how other Defaults settings are parsed.
+
+ * On systems without the O_NOFOLLOW open(2) flag, when the NOFOLLOW
+ flag is set, sudoedit now checks whether the file is a symbolic link
+ before opening it as well as after the open. Bug #753.
+
+ * Sudo will now only resolve a user's group IDs to group names
+ when sudoers includes group-based permissions. Group lookups
+ can be expensive on some systems where the group database is
+ not local.
+
+ * If the file system holding the sudo log file is full, allow
+ the command to run unless the new ignore_logfile_errors Defaults
+ option is disabled. Bug #751.
+
+ * The ignore_audit_errors and ignore_iolog_errors Defaults options
+ have been added to control sudo's behavior when it is unable to
+ write to the audit and I/O logs.
+
+ * Fixed a bug introduced in 1.8.17 where the SIGPIPE signal handler
+ was not being restored when sudo directly executes the command.
+
+ * Fixed a bug where "sudo -l command" would indicate that a command
+ was runnable even when denied by sudoers when using the LDAP or
+ SSSD back-ends.
+
+ * The match_group_by_gid Defaults option has been added to allow
+ sites where group name resolution is slow and where sudoers only
+ contains a small number of groups to match groups by group ID
+ instead of by group name.
+
+ * Fixed a bug on Linux where a 32-bit sudo binary could fail with
+ an "unable to allocate memory" error when run on a 64-bit system.
+ Bug #755
+
+ * When parsing ldap.conf, sudo will now only treat a '#' character
+ as the start of a comment when it is at the beginning of the
+ line.
+
+ * Fixed a potential crash when auditing is enabled and the audit
+ function fails with an error. Bug #756
+
+ * Norwegian Nynorsk translation for sudo from translationproject.org.
+
+ * Fixed a typo that broke short host name matching when the fqdn
+ flag is enabled in sudoers. Bug #757
+
+ * Negated sudoHost attributes are now supported by the LDAP and
+ SSSD back-ends.
+
+ * Fixed matching entries in the LDAP and SSSD back-ends when a
+ RunAsGroup is specified but no RunAsUser is present.
+
+ * Fixed "sudo -l" output in the LDAP and SSSD back-ends when a
+ RunAsGroup is specified but no RunAsUser is present.
+
+What's new in Sudo 1.8.17p1
+
+ * Fixed a bug introduced in 1.8.17 where the user's groups were
+ not set on systems that don't use PAM. Bug #749.
+
+What's new in Sudo 1.8.17
+
+ * On AIX, if /etc/security/login.cfg has auth_type set to PAM_AUTH
+ but pam_start(3) fails, fall back to AIX authentication.
+ Bug #740.
+
+ * Sudo now takes all sudoers sources into account when determining
+ whether or not "sudo -l" or "sudo -v" should prompt for a password.
+ In other words, if both file and ldap sudoers sources are in
+ specified in /etc/nsswitch.conf, "sudo -v" will now require that
+ all entries in both sources be have NOPASSWD (file) or !authenticate
+ (ldap) in the entries.
+
+ * Sudo now ignores SIGPIPE until the command is executed. Previously,
+ SIGPIPE was only ignored in a few select places. Bug #739.
+
+ * Fixed a bug introduced in sudo 1.8.14 where (non-syslog) log
+ file entries were missing the newline when loglinelen is set to
+ a non-positive number. Bug #742.
+
+ * Unix groups are now set before the plugin session initialization
+ code is run. This makes it possible to use dynamic groups with
+ the Linux-PAM pam_group module.
+
+ * Fixed a bug where a debugging statement could dereference a NULL
+ pointer when looking up a group that doesn't exist. Bug #743.
+
+ * Sudo has been run through the Coverity code scanner. A number of
+ minor bugs have been fixed as a result. None were security issues.
+
+ * SELinux support, which was broken in 1.8.16, has been repaired.
+
+ * Fixed a bug when logging I/O where all output buffers might not
+ get flushed at exit.
+
+ * Forward slashes are no longer escaped in the JSON output of
+ "visudo -x". This was never required by the standard and not
+ escaping them improves readability of the output.
+
+ * Sudo no longer treats PAM_SESSION_ERR as a fatal error when
+ opening the PAM session. Other errors from pam_open_session()
+ are still treated as fatal. This avoids the "policy plugin
+ failed session initialization" error message seen on some systems.
+
+ * Korean translation for sudo and sudoers from translationproject.org.
+
+ * Fixed a bug on AIX where the stack size hard resource limit was
+ being set to 2GB instead of 4GB on 64-bit systems.
+
+ * The SSSD back-end now properly supports "sudo -U otheruser -l".
+
+ * The SSSD back-end now uses the value of "ipa_hostname"
+ from sssd.conf, if specified, when matching the host name.
+
+ * Fixed a hang on some systems when the command is being run in
+ a pty and it failed to execute.
+
+ * When performing a wildcard match in sudoers, check for an exact
+ string match if the user command was fully-qualified (or resolved
+ via the PATH). This fixes an issue executing scripts on Linux
+ when there are multiple wildcard matches with the same base name.
+ Bug #746.
+
+What's new in Sudo 1.8.16
+
+ * Fixed a compilation error on Solaris 10 with Stun Studio 12.
+ Bug #727.
+
+ * When preserving variables from the invoking user's environment, if
+ there are duplicates sudo now only keeps the first instance.
+
+ * Fixed a bug that could cause warning mail to be sent in list
+ mode (sudo -l) for users without sudo privileges when the
+ LDAP and sssd back-ends are used.
+
+ * Fixed a bug that prevented the "mail_no_user" option from working
+ properly with the LDAP back-end.
+
+ * In the LDAP and sssd back-ends, white space is now ignored between
+ an operator (!, +, +=, -=) when parsing a sudoOption.
+
+ * It is now possible to disable Path settings in sudo.conf
+ by omitting the path name.
+
+ * The sudoedit_checkdir Defaults option is now enabled by default
+ and has been extended. When editing files with sudoedit, each
+ directory in the path to be edited is now checked. If a directory
+ is writable by the invoking user, symbolic links will not be
+ followed. If the parent directory of the file to be edited is
+ writable, sudoedit will refuse to edit it.
+ Bug #707.
+
+ * The netgroup_tuple Defaults option has been added to enable matching
+ of the entire netgroup tuple, not just the host or user portion.
+ Bug #717.
+
+ * When matching commands based on the SHA2 digest, sudo will now
+ use fexecve(2) to execute the command if it is available. This
+ fixes a time of check versus time of use race condition when the
+ directory holding the command is writable by the invoking user.
+
+ * On AIX systems, sudo now caches the auth registry string along
+ with password and group information. This fixes a potential
+ problem when a user or group of the same name exists in multiple
+ auth registries. For example, local and LDAP.
+
+ * Fixed a crash in the SSSD back-end when the invoking user is not
+ found. Bug #732.
+
+ * Added the --enable-asan configure flag to enable address sanitizer
+ support. A few minor memory leaks have been plugged to quiet
+ the ASAN leak detector.
+
+ * The value of _PATH_SUDO_CONF may once again be overridden via
+ the Makefile. Bug #735.
+
+ * The sudoers2ldif script now handles multiple roles with same name.
+
+ * Fixed a compilation error on systems that have the posix_spawn()
+ and posix_spawnp() functions but an unusable spawn.h header.
+ Bug #730.
+
+ * Fixed support for negating character classes in sudo's version
+ of the fnmatch() function.
+
+ * Fixed a bug in the LDAP and SSSD back-ends that could allow an
+ unauthorized user to list another user's privileges. Bug #738.
+
+ * The PAM conversation function now works around an ambiguity in the
+ PAM spec with respect to multiple messages. Bug #726.
+
+What's new in Sudo 1.8.15
+
+ * Fixed a bug that prevented sudo from building outside the source tree
+ on some platforms. Bug #708.
+
+ * Fixed the location of the sssd library in the RHEL/Centos packages.
+ Bug #710.
+
+ * Fixed a build problem on systems that don't implicitly include
+ sys/types.h from other header files. Bug #711.
+
+ * Fixed a problem on Linux using containers where sudo would ignore
+ signals sent by a process in a different container.
+
+ * Sudo now refuses to run a command if the PAM session module
+ returns an error.
+
+ * When editing files with sudoedit, symbolic links will no longer
+ be followed by default. The old behavior can be restored by
+ enabling the sudoedit_follow option in sudoers or on a per-command
+ basis with the FOLLOW and NOFOLLOW tags. Bug #707.
+
+ * Fixed a bug introduced in version 1.8.14 that caused the last
+ valid editor in the sudoers "editor" list to be used by visudo
+ and sudoedit instead of the first. Bug #714.
+
+ * Fixed a bug in visudo that prevented the addition of a final
+ newline to edited files without one.
+
+ * Fixed a bug decoding certain base64 digests in sudoers when the
+ intermediate format included a '=' character.
+
+ * Individual records are now locked in the time stamp file instead
+ of the entire file. This allows sudo to avoid prompting for a
+ password multiple times on the same terminal when used in a
+ pipeline. In other words, "sudo cat foo | sudo grep bar" now
+ only prompts for the password once. Previously, both sudo
+ processes would prompt for a password, often making it impossible
+ to enter.
+
+ * Fixed a bug where sudo would fail to run commands as a non-root
+ user on systems that lack both setresuid() and setreuid().
+ Bug #713.
+
+ * Fixed a bug introduced in sudo 1.8.14 that prevented visudo from
+ re-editing the correct file when a syntax error was detected.
+
+ * Fixed a bug where sudo would not relay a SIGHUP signal to the
+ command when the terminal is closed and the command is not run
+ in its own pseudo-tty. Bug #719
+
+ * If some, but not all, of the LOGNAME, USER or USERNAME environment
+ variables have been preserved from the invoking user's environment,
+ sudo will now use the preserved value to set the remaining variables
+ instead of using the runas user. This ensures that if, for example,
+ only LOGNAME is present in the env_keep list, that sudo will not
+ set USER and USERNAME to the runas user.
+
+* When the command sudo is running dies due to a signal, sudo will
+ now send itself that same signal with the default signal handler
+ installed instead of exiting. The bash shell appears to ignore
+ some signals, e.g. SIGINT, unless the command being run is killed
+ by that signal. This makes the behavior of commands run under
+ sudo the same as without sudo when bash is the shell. Bug #722
+
+ * Slovak translation for sudo from translationproject.org.
+
+ * Hungarian and Slovak translations for sudoers from translationproject.org.
+
+ * Previously, when env_reset was enabled (the default) and the -s
+ option was not used, the SHELL environment variable was set to the
+ shell of the invoking user. Now, when env_reset is enabled and
+ the -s option is not used, SHELL is set based on the target user.
+
+ * Fixed challenge/response style BSD authentication.
+
+ * Added the sudoedit_checkdir Defaults option to prevent sudoedit
+ from editing files located in a directory that is writable by
+ the invoking user.
+
+ * Added the always_query_group_plugin Defaults option to control
+ whether groups not found in the system group database are passed
+ to the group plugin. Previously, unknown system groups were
+ always passed to the group plugin.
+
+ * When creating a new file, sudoedit will now check that the file's
+ parent directory exists before running the editor.
+
+ * Fixed the compiler stack protector test in configure for compilers
+ that support -fstack-protector but don't actually have the ssp
+ library available.
+
+What's new in Sudo 1.8.14p3
+
+ * Fixed a bug introduced in sudo 1.8.14p2 that prevented sudo
+ from working when no tty was present.
+
+ * Fixed tty detection on newer AIX systems where dev_t is 64-bit.
+
+What's new in Sudo 1.8.14p2
+
+ * Fixed a bug introduced in sudo 1.8.14 that prevented the lecture
+ file from being created. Bug #704.
+
+What's new in Sudo 1.8.14p1
+
+ * Fixed a bug introduced in sudo 1.8.14 that prevented the sssd
+ back-end from working. Bug #703.
+
+What's new in Sudo 1.8.14
+
+ * Log messages on Mac OS X now respect sudoers_locale when sudo
+ is build with NLS support.
+
+ * The sudo manual pages now pass "mandoc -Tlint" with no warnings.
+
+ * Fixed a compilation problem on systems with the sig2str() function
+ that do not define SIG2STR_MAX in signal.h.
+
+ * Worked around a compiler bug that resulted in unexpected behavior
+ when returning an int from a function declared to return bool
+ without an explicit cast.
+
+ * Worked around a bug in Mac OS X 10.10 BSD auditing where the
+ au_preselect() fails for AUE_sudo events but succeeds for
+ AUE_DARWIN_sudo.
+
+ * Fixed a hang on Linux systems with glibc when sudo is linked with
+ jemalloc.
+
+ * When the user runs a command as a user ID that is not present in
+ the password database via the -u flag, the command is now run
+ with the group ID of the invoking user instead of group ID 0.
+
+ * Fixed a compilation problem on systems that don't pull in
+ definitions of uid_t and gid_t without sys/types.h or unistd.h.
+
+ * Fixed a compilation problem on newer AIX systems which use a
+ struct st_timespec for time stamps in struct stat that differs
+ from struct timespec. Bug #702.
+
+ * The example directory is now configurable via --with-exampledir
+ and defaults to DATAROOTDIR/examples/sudo on BSD systems.
+
+ * The /usr/lib/tmpfiles.d/sudo.conf file is now installed as part
+ of "make install" when systemd is in use.
+
+ * Fixed a linker problem on some systems with libintl. Bug #690.
+
+ * Fixed compilation with compilers that don't support __func__
+ or __FUNCTION__.
+
+ * Sudo no longer needs to uses weak symbols to support localization
+ in the warning functions. A registration function is used instead.
+
+ * Fixed a setresuid() failure in sudoers on Linux kernels where
+ uid changes take the nproc resource limit into account.
+
+ * Fixed LDAP netgroup queries on AIX.
+
+ * Sudo will now display the custom prompt on Linux systems with PAM
+ even if the "Password: " prompt is not localized by the PAM module.
+ Bug #701.
+
+ * Double-quoted values in an LDAP sudoOption are now supported
+ for consistency with file-based sudoers.
+
+ * Fixed a bug that prevented the btime entry in /proc/stat from
+ being parsed on Linux.
+
+What's new in Sudo 1.8.13
+
+ * The examples directory is now a subdirectory of the doc dir to
+ conform to Debian guidelines. Bug #682.
+
+ * Fixed a compilation error for siglist.c and signame.c on some
+ systems. Bug #686
+
+ * Weak symbols are now used for sudo_warn_gettext() and
+ sudo_warn_strerror() in libsudo_util to avoid link errors when
+ -Wl,--no-undefined is used in LDFLAGS. The --disable-weak-symbols
+ configure option can be used to disable the user of weak symbols.
+
+ * Fixed a bug in sudo's mkstemps() replacement function that
+ prevented the file extension from being preserved in sudoedit.
+
+ * A new mail_all_cmnds sudoers flag will send mail when a user runs
+ a command (or tries to). The behavior of the mail_always flag has
+ been restored to always send mail when sudo is run.
+
+ * New "MAIL" and "NOMAIL" command tags have been added to toggle
+ mail sending behavior on a per-command (or Cmnd_Alias) basis.
+
+ * Fixed matching of empty passwords when sudo is configured to
+ use passwd (or shadow) file authentication on systems where the
+ crypt() function returns NULL for invalid salts.
+
+ * On AIX, sudo now uses the value of the auth_type setting in
+ /etc/security/login.cfg to determine whether to use LAM or PAM
+ for user authentication.
+
+ * The "all" setting for listpw and verifypw now works correctly
+ with LDAP and sssd sudoers.
+
+ * The sudo timestamp directory is now created at boot time on
+ platforms that use systemd.
+
+ * Sudo will now restore the value of the SIGPIPE handler before
+ executing the command.
+
+ * Sudo now uses "struct timespec" instead of "struct timeval" for
+ time keeping when possible. If supported, sudoedit and visudo
+ now use nanosecond granularity time stamps.
+
+ * Fixed a symbol name collision with systems that have their own
+ SHA2 implementation. This fixes a problem where PAM could use
+ the wrong SHA2 implementation on Solaris 10 systems configured
+ to use SHA512 for passwords.
+
+ * The editor invoked by sudoedit once again uses an unmodified
+ copy of the user's environment as per the documentation. This
+ was inadvertently changed in sudo 1.8.0. Bug #688.
+
+What's new in Sudo 1.8.12
+
+ * The embedded copy of zlib has been upgraded to version 1.2.8 and
+ is now installed as a shared library where supported.
+
+ * Debug settings for the sudo front end and sudoers plugin are now
+ configured separately.
+
+ * Multiple sudo.conf Debug entries may now be specified per program
+ (or plugin).
+
+ * The plugin API has been extended such that the path to the plugin
+ that was loaded is now included in the settings array. This
+ path can be used to register with the debugging subsystem. The
+ debug_flags setting is now prefixed with a file name and may be
+ specified multiple times if there is more than one matching Debug
+ setting in sudo.conf.
+
+ * The sudoers regression tests now run with the locale set to C
+ since some of the tests compare output that includes locale-specific
+ messages. Bug #672
+
+ * Fixed a bug where sudo would not run commands on Linux when
+ compiled with audit support if audit is disabled. Bug #671
+
+ * Added __BASH_FUNC<* to the environment blacklist to match
+ Apple's syntax for newer-style bash functions.
+
+ * The default password prompt now includes a trailing space after
+ "Password:" for consistency with su(1) on most systems.
+ Bug #663
+
+ * Fixed a problem on DragonFly BSD where SIGCHLD could be ignored,
+ preventing sudo from exiting. Bug #676
+
+ * Visudo will now use the optional sudoers_file, sudoers_mode,
+ sudoers_uid and sudoers_gid arguments if specified on the
+ sudoers.so Plugin line in the sudo.conf file.
+
+ * Fixed a problem introduced in sudo 1.8.8 that prevented the full
+ host name from being used when the "fqdn" sudoers option is used.
+ Bug #678
+
+ * French and Russian translations for sudoers from translationproject.org.
+
+ * Sudo now installs a handler for SIGCHLD signal handler immediately
+ before stating the process that will execute the command (or
+ start the monitor). The handler used to be installed earlier
+ but this causes problems with poorly behaved PAM modules that
+ install their own SIGCHLD signal handler and neglect to restore
+ sudo's original handler. Bug #657
+
+ * Removed a limit on the length of command line arguments expanded
+ by a wild card using sudo's version of the fnmatch() function.
+ This limit was introduced when sudo's version of fnmatch()
+ was replaced in sudo 1.8.4.
+
+ * LDAP-based sudoers can now query an LDAP server for a user's
+ netgroups directly. This is often much faster than fetching
+ every sudoRole object containing a sudoUser that begins with a
+ `+' prefix and checking whether the user is a member of any of
+ the returned netgroups.
+
+ * The mail_always sudoers option no longer sends mail for "sudo -l"
+ or "sudo -v" unless the user is unable to authenticate themselves.
+
+ * Fixed a crash when sudo is run with an empty argument vector.
+
+ * Fixed two potential crashes when sudo is run with very low
+ resource limits.
+
+ * The TZ environment variable is now checked for safety instead
+ of simply being copied to the environment of the command.
+
+What's new in Sudo 1.8.11p2
+
+ * Fixed a bug where dynamic shared objects loaded from a plugin
+ could use the hooked version of getenv() but not the hooked
+ versions of putenv(), setenv() or unsetenv(). This can cause
+ problems for PAM modules that use those functions.
+
+What's new in Sudo 1.8.11p1
+
+ * Fixed a compilation problem on some systems when the
+ --disable-shared-libutil configure option was specified.
+
+ * The user can no longer interrupt the sleep after an incorrect
+ password on PAM systems using pam_unix.
+ Bug #666
+
+ * Fixed a compilation problem on Linux systems that do not use PAM.
+ Bug #667
+
+ * "make install" will now work with the stock GNU autotools
+ install-sh script. Bug #669
+
+ * Fixed a crash with "sudo -i" when the current working directory
+ does not exist. Bug #670
+
+ * Fixed a potential crash in the debug subsystem when logging a message
+ larger that 1024 bytes.
+
+ * Fixed a "make check" failure for ttyname when stdin is closed and
+ stdout and stderr are redirected to a different tty. Bug #643
+
+ * Added BASH_FUNC_* to the environment blacklist to match newer-style
+ bash functions.
+
+What's new in Sudo 1.8.11
+
+ * The sudoers plugin no longer uses setjmp/longjmp to recover
+ from fatal errors. All errors are now propagated to the caller
+ via return codes.
+
+ * When running a command in the background, sudo will now forward
+ SIGINFO to the command (if supported).
+
+ * Sudo will now use the system versions of the sha2 functions from
+ libc or libmd if available.
+
+ * Visudo now works correctly on GNU Hurd. Bug #647
+
+ * Fixed suspend and resume of curses programs on some system when
+ the command is not being run in a pseudo-terminal. Bug #649
+
+ * Fixed a crash with LDAP-based sudoers on some systems when
+ Kerberos was enabled.
+
+ * Sudo now includes optional Solaris audit support.
+
+ * Catalan translation for sudoers from translationproject.org.
+
+ * Norwegian Bokmaal translation for sudo from translationproject.org.
+
+ * Greek translation for sudoers from translationproject.org
+
+ * The sudo source tree has been reorganized to more closely resemble
+ that of other gettext-enabled packages.
+
+ * Sudo and its associated programs now link against a shared version
+ of libsudo_util. The --disable-shared-libutil configure option
+ may be used to force static linking if the --enable-static-sudoers
+ option is also specified.
+
+ * The passwords in ldap.conf and ldap.secret may now be encoded
+ in base64.
+
+ * Audit updates. SELinux role changes are now audited. For
+ sudoedit, we now audit the actual editor being run, instead of
+ just the sudoedit command.
+
+ * Fixed bugs in the man page post-processing that could cause
+ portions of the manuals to be removed.
+
+ * Fixed a crash in the system_group plugin. Bug #653.
+
+ * Fixed sudoedit on platforms without a system version of the
+ getprogname() function. Bug #654.
+
+ * Fixed compilation problems with some pre-C99 compilers.
+
+ * Fixed sudo's -C option which was broken in version 1.8.9.
+
+ * It is now possible to match an environment variable's value as
+ well as its name using env_keep and env_check. This can be used
+ to preserve bash functions which would otherwise be removed from
+ the environment.
+
+ * New files created via sudoedit as a non-root user now have the
+ proper group id. Bug #656
+
+ * Sudoedit now works correctly in conjunction with sudo's SELinux
+ RBAC support. Temporary files are now created with the proper
+ security context.
+
+ * The sudo I/O logging plugin API has been updated. If a logging
+ function returns an error, the command will be terminated and
+ all of the plugin's logging functions will be disabled. If a
+ logging function rejects the command's output it will no longer
+ be displayed to the user's terminal.
+
+ * Fixed a compilation error on systems that lack openpty(), _getpty()
+ and grantpt(). Bug #660
+
+ * Fixed a hang when a sudoers source is listed more than once in
+ a single sudoers nsswitch.conf entry.
+
+ * On AIX, shell scripts without a #! magic number are now passed to
+ /usr/bin/sh, not /usr/bin/bsh. This is consistent with what the
+ execvp() function on AIX does and matches historic sudo behavior.
+ Bug #661
+
+ * Fixed a cross-compilation problem building mksiglist and mksigname.
+ Bug #662
+
+What's new in Sudo 1.8.10p3?
+
+ * Fixed expansion of %p in the prompt for "sudo -l" when rootpw,
+ runaspw or targetpw is set. Bug #639
+
+ * Fixed matching of UIDs and GIDs which was broken in version 1.8.9.
+ Bug #640
+
+ * PAM credential initialization has been re-enabled. It was
+ unintentionally disabled by default in version 1.8.8. The way
+ credentials are initialized has also been fixed. Bug #642.
+
+ * Fixed a descriptor leak on Linux when determining boot time. Sudo
+ normally closes extra descriptors before running a command so
+ the impact is limited. Bug #645
+
+ * Fixed flushing of the last buffer of data when I/O logging is
+ enabled. This bug, introduced in version 1.8.9, could cause
+ incomplete command output on some systems. Bug #646
+
+What's new in Sudo 1.8.10p2?
+
+ * Fixed a hang introduced in sudo 1.8.10 when timestamp_timeout
+ is set to zero.
+
+What's new in Sudo 1.8.10p1?
+
+ * Fixed a bug introduced in sudo 1.8.10 that prevented the disabling
+ of tty-based tickets.
+
+ * Fixed a bug with negated commands in "sudo -l command" that
+ could cause the command to be listed even when it was explicitly
+ denied. This only affected list mode when a command was specified.
+ Bug #636
+
+What's new in Sudo 1.8.10?
+
+ * It is now possible to disable network interface probing in
+ sudo.conf by changing the value of the probe_interfaces
+ setting.
+
+ * When listing a user's privileges (sudo -l), the sudoers plugin
+ will now prompt for the user's password even if the targetpw,
+ rootpw or runaspw options are set.
+
+ * The sudoers plugin uses a new format for its time stamp files.
+ Each user now has a single file which may contain multiple records
+ when per-tty time stamps are in use (the default). The time
+ stamps use a monotonic timer where available and are once again
+ located in a directory under /var/run. The lecture status is
+ now stored separately from the time stamps in a different directory.
+ Bug #616
+
+ * sudo's -K option will now remove all of the user's time stamps,
+ not just the time stamp for the current terminal. The -k option
+ can be used to only disable time stamps for the current terminal.
+
+ * If sudo was started in the background and needed to prompt for
+ a password, it was not possible to suspend it at the password
+ prompt. This now works properly.
+
+ * LDAP-based sudoers now uses a default search filter of
+ (objectClass=sudoRole) for more efficient queries. The netgroup
+ query has been modified to avoid falling below the minimum length
+ for OpenLDAP substring indices.
+
+ * The new "use_netgroups" sudoers option can be used to explicitly
+ enable or disable netgroups support. For LDAP-based sudoers,
+ netgroup support requires an expensive substring match on the
+ server. If netgroups are not needed, this option can be disabled
+ to reduce the load on the LDAP server.
+
+ * Sudo is once again able to open the sudoers file when the group
+ on sudoers doesn't match the expected value, so long as the file
+ is not group writable.
+
+ * Sudo now installs an init.d script to clear the time stamp
+ directory at boot time on AIX and HP-UX systems. These systems
+ either lack /var/run or do not clear it on boot.
+
+ * The JSON format used by "visudo -x" now properly supports the
+ negation operator. In addition, the Options object is now the
+ same for both Defaults and Cmnd_Specs.
+
+ * Czech and Serbian translations for sudoers from translationproject.org.
+
+ * Catalan translation for sudo from translationproject.org.
+
+What's new in Sudo 1.8.9p5?
+
+ * Fixed a compilation error on AIX when LDAP support is enabled.
+
+ * Fixed parsing of the "umask" defaults setting in sudoers. Bug #632.
+
+ * Fixed a failed assertion when the "closefrom_override" defaults
+ setting is enabled in sudoers and sudo's -C flag is used. Bug #633.
+
+What's new in Sudo 1.8.9p4?
+
+ * Fixed a bug where sudo could consume large amounts of CPU while
+ the command was running when I/O logging is not enabled. Bug #631
+
+ * Fixed a bug where sudo would exit with an error when the debug
+ level is set to util@debug or all@debug and I/O logging is not
+ enabled. The command would continue running after sudo exited.
+
+What's new in Sudo 1.8.9p3?
+
+ * Fixed a bug introduced in sudo 1.8.9 that prevented the tty name
+ from being resolved properly on Linux systems. Bug #630.
+
+What's new in Sudo 1.8.9p2?
+
+ * Updated config.guess, config.sub and libtool to support the ppc64le
+ architecture (IBM PowerPC Little Endian).
+
+What's new in Sudo 1.8.9p1?
+
+ * Fixed a problem with gcc 4.8's handling of bit fields that could
+ lead to the noexec flag being enabled even when it was not
+ explicitly set.
+
+What's new in Sudo 1.8.9?
+
+ * Reworked sudo's main event loop to use a simple event subsystem
+ using poll(2) or select(2) as the back end.
+
+ * It is now possible to statically compile the sudoers plugin into
+ the sudo binary without disabling shared library support. The
+ sudo.conf file may still be used to configure other plugins.
+
+ * Sudo can now be compiled again with a C preprocessor that does
+ not support variadic macros.
+
+ * Visudo can now export a sudoers file in JSON format using the
+ new -x flag.
+
+ * The locale is now set correctly again for visudo and sudoreplay.
+
+ * The plugin API has been extended to allow the plugin to exclude
+ specific file descriptors from the "closefrom" range.
+
+ * There is now a workaround for a Solaris-specific problem where
+ NOEXEC was overriding traditional root DAC behavior.
+
+ * Add user netgroup filtering for SSSD. Previously, rules for
+ a netgroup were applied to all even when they did not belong
+ to the specified netgroup.
+
+ * On systems with BSD login classes, if the user specified a group
+ (not a user) to run the command as, it was possible to specify
+ a different login class even when the command was not run as the
+ super user.
+
+ * The closefrom() emulation on Mac OS X now uses /dev/fd if possible.
+
+ * Fixed a bug where sudoedit would not update the original file
+ from the temporary when PAM or I/O logging is not enabled.
+
+ * When recycling I/O logs, the log files are now truncated properly.
+
+ * Fixes bugs #617, #621, #622, #623, #624, #625, #626
+
+What's new in Sudo 1.8.8?
+
+ * Removed a warning on PAM systems with stacked auth modules
+ where the first module on the stack does not succeed.
+
+ * Sudo, sudoreplay and visudo now support GNU-style long options.
+
+ * The -h (--host) option may now be used to specify a host name.
+ This is currently only used by the sudoers plugin in conjunction
+ with the -l (--list) option.
+
+ * Program usage messages and manual SYNOPSIS sections have been
+ simplified.
+
+ * Sudo's LDAP SASL support now works properly with Kerberos.
+ Previously, the SASL library was unable to locate the user's
+ credential cache.
+
+ * It is now possible to set the nproc resource limit to unlimited
+ via pam_limits on Linux (bug #565).
+
+ * New "pam_service" and "pam_login_service" sudoers options
+ that can be used to specify the PAM service name to use.
+
+ * New "pam_session" and "pam_setcred" sudoers options that
+ can be used to disable PAM session and credential support.
+
+ * The sudoers plugin now properly supports UIDs and GIDs
+ that are larger than 0x7fffffff on 32-bit platforms.
+
+ * Fixed a visudo bug introduced in sudo 1.8.7 where per-group
+ Defaults entries would cause an internal error.
+
+ * If the "tty_tickets" sudoers option is enabled (the default),
+ but there is no tty present, sudo will now use a ticket file
+ based on the parent process ID. This makes it possible to support
+ the normal timeout behavior for the session.
+
+ * Fixed a problem running commands that change their process
+ group and then attempt to change the terminal settings when not
+ running the command in a pseudo-terminal. Previously, the process
+ would receive SIGTTOU since it was effectively a background
+ process. Sudo will now grant the child the controlling tty and
+ continue it when this happens.
+
+ * The "closefrom_override" sudoers option may now be used in
+ a command-specified Defaults entry (bug #610).
+
+ * Sudo's BSM audit support now works on Solaris 11.
+
+ * Brazilian Portuguese translation for sudo and sudoers from
+ translationproject.org.
+
+ * Czech translation for sudo from translationproject.org.
+
+ * French translation for sudo from translationproject.org.
+
+ * Sudo's noexec support on Mac OS X 10.4 and above now uses dynamic
+ symbol interposition instead of setting DYLD_FORCE_FLAT_NAMESPACE=1
+ which causes issues with some programs.
+
+ * Fixed visudo's -q (--quiet) flag, broken in sudo 1.8.6.
+
+ * Root may no longer change its SELinux role without entering
+ a password.
+
+ * Fixed a bug introduced in Sudo 1.8.7 where the indexes written
+ to the I/O log timing file are two greater than they should be.
+ Sudoreplay now contains a work-around to parse those files.
+
+ * In sudoreplay's list mode, the "this" qualifier in "fromdate"
+ or "todate" expressions now behaves more sensibly. Previously,
+ it would often match a date that was "one more" than expected.
+ For example, "this week" now matches the current week instead
+ of the following week.
+
+What's new in Sudo 1.8.7?
+
+ * The non-Unix group plugin is now supported when sudoers data
+ is stored in LDAP.
+
+ * Sudo now uses a workaround for a locale bug on Solaris 11.0
+ that prevents setuid programs like sudo from fully using locales.
+
+ * User messages are now always displayed in the user's locale,
+ even when the same message is being logged or mailed in a
+ different locale.
+
+ * Log files created by sudo now explicitly have the group set
+ to group ID 0 rather than relying on BSD group semantics (which
+ may not be the default).
+
+ * A new "exec_background" sudoers option can be used to initially
+ run the command without read access to the terminal when running
+ a command in a pseudo-tty. If the command tries to read from
+ the terminal it will be stopped by the kernel (via SIGTTIN or
+ SIGTTOU) and sudo will immediately restart it as the foreground
+ process (if possible). This allows sudo to only pass terminal
+ input to the program if the program actually is expecting it.
+ Unfortunately, a few poorly-behaved programs (like "su" on most
+ Linux systems) do not handle SIGTTIN and SIGTTOU properly.
+
+ * Sudo now uses an efficient group query to get all the groups
+ for a user instead of iterating over every record in the group
+ database on HP-UX and Solaris.
+
+ * Sudo now produces better error messages when there is an error
+ in the sudo.conf file.
+
+ * Two new settings have been added to sudo.conf to give the admin
+ better control of how group database queries are performed. The
+ "group_source" specifies how the group list for a user will be
+ determined. Legal values are "static" (use the kernel groups
+ list), "dynamic" (perform a group database query) and "adaptive"
+ (only perform a group database query if the kernel list is full).
+ The "max_groups" setting specifies the maximum number of groups
+ a user may belong to when performing a group database query.
+
+ * The sudo.conf file now supports line continuation by using a
+ backslash as the last character on the line.
+
+ * There is now a standalone sudo.conf manual page.
+
+ * Sudo now stores its libexec files in a "sudo" sub-directory instead
+ of in libexec itself. For backward compatibility, if the plugin
+ is not found in the default plugin directory, sudo will check
+ the parent directory if the default directory ends in "/sudo".
+
+ * The sudoers I/O logging plugin now logs the terminal size.
+
+ * A new sudoers option "maxseq" can be used to limit the number of
+ I/O log entries that are stored.
+
+ * The "system_group" and "group_file" sudoers group provider plugins
+ are now installed by default.
+
+ * The list output (sudo -l) output from the sudoers plugin is now
+ less ambiguous when an entry includes different runas users.
+ The long list output (sudo -ll) for file-based sudoers is now
+ more consistent with the format of LDAP-based sudoers.
+
+ * A UID may now be used in the sudoRunAsUser attributes for LDAP
+ sudoers.
+
+ * Minor plugin API change: the close and version functions are now
+ optional. If the policy plugin does not provide a close function
+ and the command is not being run in a new pseudo-tty, sudo may
+ now execute the command directly instead of in a child process.
+
+ * A new sudoers option "pam_session" can be used to disable sudo's
+ PAM session support.
+
+ * On HP-UX systems, sudo will now use the pstat() function to
+ determine the tty instead of ttyname().
+
+ * Turkish translation for sudo and sudoers from translationproject.org.
+
+ * Dutch translation for sudo and sudoers from translationproject.org.
+
+ * Tivoli Directory Server client libraries may now be used with
+ HP-UX where libibmldap has a hidden dependency on libCsup.
+
+ * The sudoers plugin will now ignore invalid domain names when
+ checking netgroup membership. Most Linux systems use the string
+ "(none)" for the NIS-style domain name instead of an empty string.
+
+ * New support for specifying a SHA-2 digest along with the command
+ in sudoers. Supported hash types are sha224, sha256, sha384 and
+ sha512. See the description of Digest_Spec in the sudoers manual
+ or the description of sudoCommand in the sudoers.ldap manual for
+ details.
+
+ * The paths to ldap.conf and ldap.secret may now be specified as
+ arguments to the sudoers plugin in the sudo.conf file.
+
+ * Fixed potential false positives in visudo's alias cycle detection.
+
+ * Fixed a problem where the time stamp file was being treated
+ as out of date on Linux systems where the change time on the
+ pseudo-tty device node can change after it is allocated.
+
+ * Sudo now only builds Position Independent Executables (PIE)
+ by default on Linux systems and verifies that a trivial test
+ program builds and runs.
+
+ * On Solaris 11.1 and higher, sudo binaries will now have the
+ ASLR tag enabled if supported by the linker.
+
+What's new in Sudo 1.8.6p8?
+
+ * Terminal detection now works properly on 64-bit AIX kernels.
+ This was broken by the removal of the ttyname() fallback in Sudo
+ 1.8.6p6. Sudo is now able to map an AIX 64-bit device number
+ to the corresponding device file in /dev.
+
+ * Sudo now checks for crypt() returning NULL when performing
+ passwd-based authentication.
+
+What's new in Sudo 1.8.6p7?
+
+ * A time stamp file with the date set to the epoch by "sudo -k"
+ is now completely ignored regardless of what the local clock is
+ set to. Previously, if the local clock was set to a value between
+ the epoch and the time stamp timeout value, a time stamp reset
+ by "sudo -k" would be considered current.
+
+ * The tty-specific time stamp file now includes the session ID
+ of the sudo process that created it. If a process with the same
+ tty but a different session ID runs sudo, the user will now be
+ prompted for a password (assuming authentication is required for
+ the command).
+
+What's new in Sudo 1.8.6p6?
+
+ * On systems where the controlling tty can be determined via /proc
+ or sysctl(), sudo will no longer fall back to using ttyname()
+ if the process has no controlling tty. This prevents sudo from
+ using a non-controlling tty for logging and time stamp purposes.
+
+What's new in Sudo 1.8.6p5?
+
+ * Fixed a potential crash in visudo's alias cycle detection.
+
+ * Improved performance on Solaris when retrieving the group list
+ for the target user. On systems with a large number of groups
+ where the group database is not local (NIS, LDAP, AD), fetching
+ the group list could take a minute or more.
+
+What's new in Sudo 1.8.6p4?
+
+ * The -fstack-protector is now used when linking visudo, sudoreplay
+ and testsudoers.
+
+ * Avoid building PIE binaries on FreeBSD/ia64 as they don't run
+ properly.
+
+ * Fixed a crash in visudo strict mode when an unknown Defaults
+ setting is encountered.
+
+ * Do not inform the user that the command was not permitted by the
+ policy if they do not successfully authenticate. This is a
+ regression introduced in sudo 1.8.6.
+
+ * Allow sudo to be build with sss support without also including
+ ldap support.
+
+ * Fixed running commands that need the terminal in the background
+ when I/O logging is enabled. E.g. "sudo vi &". When the command
+ is foregrounded, it will now resume properly.
+
+What's new in Sudo 1.8.6p3?
+
+ * Fixed post-processing of the man pages on systems with legacy
+ versions of sed.
+
+ * Fixed "sudoreplay -l" on Linux systems with file systems that
+ set DT_UNKNOWN in the d_type field of struct dirent.
+
+What's new in Sudo 1.8.6p2?
+
+ * Fixed suspending a command after it has already been resumed
+ once when I/O logging (or use_pty) is not enabled.
+ This was a regression introduced in version 1.8.6.
+
+What's new in Sudo 1.8.6p1?
+
+ * Fixed the setting of LOGNAME, USER and USERNAME variables in the
+ command's environment when env_reset is enabled (the default).
+ This was a regression introduced in version 1.8.6.
+
+ * Sudo now honors SUCCESS=return in /etc/nsswitch.conf.
+
+What's new in Sudo 1.8.6?
+
+ * Sudo is now built with the -fstack-protector flag if the the
+ compiler supports it. Also, the -zrelro linker flag is used if
+ supported. The --disable-hardening configure option can be used
+ to build sudo without stack smashing protection.
+
+ * Sudo is now built as a Position Independent Executable (PIE)
+ if supported by the compiler and linker.
+
+ * If the user is a member of the "exempt" group in sudoers, they
+ will no longer be prompted for a password even if the -k flag
+ is specified with the command. This makes "sudo -k command"
+ consistent with the behavior one would get if the user ran "sudo
+ -k" immediately before running the command.
+
+ * The sudoers file may now be a symbolic link. Previously, sudo
+ would refuse to read sudoers unless it was a regular file.
+
+ * The sudoreplay command can now properly replay sessions where
+ no tty was present.
+
+ * The sudoers plugin now takes advantage of symbol visibility
+ controls when supported by the compiler or linker. As a result,
+ only a small number of symbols are exported which significantly
+ reduces the chances of a conflict with other shared objects.
+
+ * Improved support for the Tivoli Directory Server LDAP client
+ libraries. This includes support for using LDAP over SSL (ldaps)
+ as well as support for the BIND_TIMELIMIT, TLS_KEY and TLS_CIPHERS
+ ldap.conf options. A new ldap.conf option, TLS_KEYPW can be
+ used to specify a password to decrypt the key database.
+
+ * When constructing a time filter for use with LDAP sudoNotBefore
+ and sudoNotAfter attributes, the current time now includes tenths
+ of a second. This fixes a problem with timed entries on Active
+ Directory.
+
+ * If a user fails to authenticate and the command would be rejected
+ by sudoers, it is now logged with "command not allowed" instead
+ of "N incorrect password attempts". Likewise, the "mail_no_perms"
+ sudoers option now takes precedence over "mail_badpass".
+
+ * The sudo manuals are now formatted using the mdoc macros. Versions
+ using the legacy man macros are provided for systems that lack mdoc.
+
+ * New support for Solaris privilege sets. This makes it possible
+ to specify fine-grained privileges in the sudoers file on Solaris
+ 10 and above. A Runas_Spec that contains no Runas_Lists can be
+ used to give a user the ability to run a command as themselves
+ but with an expanded privilege set.
+
+ * Fixed a problem with the reboot and shutdown commands on some
+ systems (such as HP-UX and BSD). On these systems, reboot sends
+ all processes (except itself) SIGTERM. When sudo received
+ SIGTERM, it would relay it to the reboot process, thus killing
+ reboot before it had a chance to actually reboot the system.
+
+ * Support for using the System Security Services Daemon (SSSD) as
+ a source of sudoers data.
+
+ * Slovenian translation for sudo and sudoers from translationproject.org.
+
+ * Visudo will now warn about unknown Defaults entries that are
+ per-host, per-user, per-runas or per-command.
+
+ * Fixed a race condition that could cause sudo to receive SIGTTOU
+ (and stop) when resuming a shell that was run via sudo when I/O
+ logging (and use_pty) is not enabled.
+
+ * Sending SIGTSTP directly to the sudo process will now suspend the
+ running command when I/O logging (and use_pty) is not enabled.
+
+What's new in Sudo 1.8.5p3?
+
+ * Fixed the loading of I/O plugins that conform to a plugin API
+ version older than 1.2.
+
+What's new in Sudo 1.8.5p2?
+
+ * Fixed use of the SUDO_ASKPASS environment variable which was
+ broken in Sudo 1.8.5.
+
+ * Fixed a problem reading the sudoers file when the file mode is
+ more restrictive than the expected mode. For example, when the
+ expected sudoers file mode is 0440 but the actual mode is 0400.
+
+What's new in Sudo 1.8.5p1?
+
+ * Fixed a bug that prevented files in an include directory from
+ being evaluated.
+
+What's new in Sudo 1.8.5?
+
+ * When "noexec" is enabled, sudo_noexec.so will now be prepended
+ to any existing LD_PRELOAD variable instead of replacing it.
+
+ * The sudo_noexec.so shared library now wraps the execvpe(),
+ exect(), posix_spawn() and posix_spawnp() functions.
+
+ * The user/group/mode checks on sudoers files have been relaxed.
+ As long as the file is owned by the sudoers UID, not world-writable
+ and not writable by a group other than the sudoers GID, the file
+ is considered OK. Note that visudo will still set the mode to
+ the value specified at configure time.
+
+ * It is now possible to specify the sudoers path, UID, GID and
+ file mode as options to the plugin in the sudo.conf file.
+
+ * Croatian, Galician, German, Lithuanian, Swedish and Vietnamese
+ translations from translationproject.org.
+
+ * /etc/environment is no longer read directly on Linux systems
+ when PAM is used. Sudo now merges the PAM environment into the
+ user's environment which is typically set by the pam_env module.
+
+ * The initial environment created when env_reset is in effect now
+ includes the contents of /etc/environment on AIX systems and the
+ "setenv" and "path" entries from /etc/login.conf on BSD systems.
+
+ * The plugin API has been extended in three ways. First, options
+ specified in sudo.conf after the plugin pathname are passed to
+ the plugin's open function. Second, sudo has limited support
+ for hooks that can be used by plugins. Currently, the hooks are
+ limited to environment handling functions. Third, the init_session
+ policy plugin function is passed a pointer to the user environment
+ which can be updated during session setup. The plugin API version
+ has been incremented to version 1.2. See the sudo_plugin manual
+ for more information.
+
+ * The policy plugin's init_session function is now called by the
+ parent sudo process, not the child process that executes the
+ command. This allows the PAM session to be open and closed in
+ the same process, which some PAM modules require.
+
+ * Fixed parsing of "Path askpass" and "Path noexec" in sudo.conf,
+ which was broken in version 1.8.4.
+
+ * On systems with an SVR4-style /proc file system, the /proc/pid/psinfo
+ file is now uses to determine the controlling terminal, if possible.
+ This allows tty-based tickets to work properly even when, e.g.
+ standard input, output and error are redirected to /dev/null.
+
+ * The output of "sudoreplay -l" is now sorted by file name (or
+ sequence number). Previously, entries were displayed in the
+ order in which they were found on the file system.
+
+ * Sudo now behaves properly when I/O logging is enabled and the
+ controlling terminal is revoked (e.g. the running sshd is killed).
+ Previously, sudo may have exited without calling the I/O plugin's
+ close function which can lead to an incomplete I/O log.
+
+ * Sudo can now detect when a user has logged out and back in again
+ on Solaris 11, just like it can on Solaris 10.
+
+ * The built-in zlib included with Sudo has been upgraded to version
+ 1.2.6.
+
+ * Setting the SSL parameter to start_tls in ldap.conf now works
+ properly when using Mozilla-based SDKs that support the
+ ldap_start_tls_s() function.
+
+ * The TLS_CHECKPEER parameter in ldap.conf now works when the
+ Mozilla NSS crypto back-end is used with OpenLDAP.
+
+ * A new group provider plugin, system_group, is included which
+ performs group look ups by name using the system groups database.
+ This can be used to restore the pre-1.7.3 sudo group lookup
+ behavior.
+
+What's new in Sudo 1.8.4p5?
+
+ * Fixed a bug when matching against an IP address with an associated
+ netmask in the sudoers file. In certain circumstances, this
+ could allow users to run commands on hosts they are not authorized
+ for.
+
+What's new in Sudo 1.8.4p4?
+
+ * Fixed a bug introduced in Sudo 1.8.4 which prevented "sudo -v"
+ from working.
+
+What's new in Sudo 1.8.4p3?
+
+ * Fixed a crash on FreeBSD when no tty is present.
+
+ * Fixed a bug introduced in Sudo 1.8.4 that allowed users to
+ specify environment variables to set on the command line without
+ having sudo "ALL" permissions or the "SETENV" tag.
+
+ * When visudo is run with the -c (check) option, the sudoers
+ file(s) owner and mode are now also checked unless the -f option
+ was specified.
+
+What's new in Sudo 1.8.4p2?
+
+ * Fixed a bug introduced in Sudo 1.8.4 where insufficient space
+ was allocated for group IDs in the LDAP filter.
+
+ * Fixed a bug introduced in Sudo 1.8.4 where the path to sudo.conf
+ was "/sudo.conf" instead of "/etc/sudo.conf".
+
+ * Fixed a bug introduced in Sudo 1.8.4 which could cause a hang
+ when I/O logging is enabled and input is from a pipe or file.
+
+What's new in Sudo 1.8.4p1?
+
+ * Fixed a bug introduced in sudo 1.8.4 that broke adding to or
+ deleting from the env_keep, env_check and env_delete lists in
+ sudoers on some platforms.
+
+What's new in Sudo 1.8.4?
+
+ * The -D flag in sudo has been replaced with a more general debugging
+ framework that is configured in sudo.conf.
+
+ * Fixed a false positive in visudo strict mode when aliases are
+ in use.
+
+ * Fixed a crash with "sudo -i" when a runas group was specified
+ without a runas user.
+
+ * The line on which a syntax error is reported in the sudoers file
+ is now more accurate. Previously it was often off by a line.
+
+ * Fixed a bug where stack garbage could be printed at the end of
+ the lecture when the "lecture_file" option was enabled.
+
+ * "make install" now honors the LINGUAS environment variable.
+
+ * The #include and #includedir directives in sudoers now support
+ relative paths. If the path is not fully qualified it is expected
+ to be located in the same directory of the sudoers file that is
+ including it.
+
+ * Serbian and Spanish translations for sudo from translationproject.org.
+
+ * LDAP-based sudoers may now access by group ID in addition to
+ group name.
+
+ * visudo will now fix the mode on the sudoers file even if no changes
+ are made unless the -f option is specified.
+
+ * The "use_loginclass" sudoers option works properly again.
+
+ * On systems that use login.conf, "sudo -i" now sets environment
+ variables based on login.conf.
+
+ * For LDAP-based sudoers, values in the search expression are now
+ escaped as per RFC 4515.
+
+ * The plugin close function is now properly called when a login
+ session is killed (as opposed to the actual command being killed).
+ This can happen when an ssh session is disconnected or the
+ terminal window is closed.
+
+ * The deprecated "noexec_file" sudoers option is no longer supported.
+
+ * Fixed a race condition when I/O logging is not enabled that could
+ result in tty-generated signals (e.g. control-C) being received
+ by the command twice.
+
+ * If none of the standard input, output or error are connected to
+ a tty device, sudo will now check its parent's standard input,
+ output or error for the tty name on systems with /proc and BSD
+ systems that support the KERN_PROC_PID sysctl. This allows
+ tty-based tickets to work properly even when, e.g. standard
+ input, output and error are redirected to /dev/null.
+
+ * Added the --enable-kerb5-instance configure option to allow
+ people using Kerberos V authentication to specify a custom
+ instance so the principal name can be, e.g. "username/sudo"
+ similar to how ksu uses "username/root".
+
+ * Fixed a bug where a pattern like "/usr/*" included /usr/bin/ in
+ the results, which would be incorrectly be interpreted as if the
+ sudoers file had specified a directory.
+
+ * "visudo -c" will now list any include files that were checked
+ in addition to the main sudoers file when everything parses OK.
+
+ * Users that only have read-only access to the sudoers file may
+ now run "visudo -c". Previously, write permissions were required
+ even though no writing is down in check-only mode.
+
+ * It is now possible to prevent the disabling of core dumps from
+ within sudo itself by adding a line to the sudo.conf file like
+ "Set disable_coredump false".
+
+What's new in Sudo 1.8.3p2?
+
+ * Fixed a format string vulnerability when the sudo binary (or a
+ symbolic link to the sudo binary) contains printf format escapes
+ and the -D (debugging) flag is used.
+
+What's new in Sudo 1.8.3p1?
+
+ * Fixed a crash in the monitor process on Solaris when NOPASSWD
+ was specified or when authentication was disabled.
+
+ * Fixed matching of a Runas_Alias in the group section of a
+ Runas_Spec.
+
+What's new in Sudo 1.8.3?
+
+ * Fixed expansion of strftime() escape sequences in the "log_dir"
+ sudoers setting.
+
+ * Esperanto, Italian and Japanese translations from translationproject.org.
+
+ * Sudo will now use PAM by default on AIX 6 and higher.
+
+ * Added --enable-werror configure option for gcc's -Werror flag.
+
+ * Visudo no longer assumes all editors support the +linenumber
+ command line argument. It now uses a allowlist of editors known
+ to support the option.
+
+ * Fixed matching of network addresses when a netmask is specified
+ but the address is not the first one in the CIDR block.
+
+ * The configure script now check whether or not errno.h declares
+ the errno variable. Previously, sudo would always declare errno
+ itself for older systems that don't declare it in errno.h.
+
+ * The NOPASSWD tag is now honored for denied commands too, which
+ matches historic sudo behavior (prior to sudo 1.7.0).
+
+ * Sudo now honors the "DEREF" setting in ldap.conf which controls
+ how alias dereferencing is done during an LDAP search.
+
+ * A symbol conflict with the pam_ssh_agent_auth PAM module that
+ would cause a crash been resolved.
+
+ * The inability to load a group provider plugin is no longer
+ a fatal error.
+
+ * A potential crash in the utmp handling code has been fixed.
+
+ * Two PAM session issues have been resolved. In previous versions
+ of sudo, the PAM session was opened as one user and closed as
+ another. Additionally, if no authentication was performed, the
+ PAM session would never be closed.
+
+ * Sudo will now work correctly with LDAP-based sudoers using TLS
+ or SSL on Debian systems.
+
+ * The LOGNAME, USER and USERNAME environment variables are preserved
+ correctly again in sudoedit mode.
+
+What's new in Sudo 1.8.2?
+
+ * Sudo, visudo, sudoreplay and the sudoers plug-in now have natural
+ language support (NLS). This can be disabled by passing configure
+ the --disable-nls option. Sudo will use gettext(), if available,
+ to display translated messages. All translations are coordinated
+ via The Translation Project, https://translationproject.org/.
+
+ * Plug-ins are now loaded with the RTLD_GLOBAL flag instead of
+ RTLD_LOCAL. This fixes missing symbol problems in PAM modules
+ on certain platforms, such as FreeBSD and SuSE Linux Enterprise.
+
+ * I/O logging is now supported for commands run in background mode
+ (using sudo's -b flag).
+
+ * Group ownership of the sudoers file is now only enforced when
+ the file mode on sudoers allows group readability or writability.
+
+ * Visudo now checks the contents of an alias and warns about cycles
+ when the alias is expanded.
+
+ * If the user specifies a group via sudo's -g option that matches
+ the target user's group in the password database, it is now
+ allowed even if no groups are present in the Runas_Spec.
+
+ * The sudo Makefiles now have more complete dependencies which are
+ automatically generated instead of being maintained manually.
+
+ * The "use_pty" sudoers option is now correctly passed back to the
+ sudo front end. This was missing in previous versions of sudo
+ 1.8 which prevented "use_pty" from being honored.
+
+ * "sudo -i command" now works correctly with the bash version
+ 2.0 and higher. Previously, the .bash_profile would not be
+ sourced prior to running the command unless bash was built with
+ NON_INTERACTIVE_LOGIN_SHELLS defined.
+
+ * When matching groups in the sudoers file, sudo will now match
+ based on the name of the group instead of the group ID. This can
+ substantially reduce the number of group lookups for sudoers
+ files that contain a large number of groups.
+
+ * Multi-factor authentication is now supported on AIX.
+
+ * Added support for non-RFC 4517 compliant LDAP servers that require
+ that seconds be present in a timestamp, such as Tivoli Directory Server.
+
+ * If the group vector is to be preserved, the PATH search for the
+ command is now done with the user's original group vector.
+
+ * For LDAP-based sudoers, the "runas_default" sudoOption now works
+ properly in a sudoRole that contains a sudoCommand.
+
+ * Spaces in command line arguments for "sudo -s" and "sudo -i" are
+ now escaped with a backslash when checking the security policy.
+
+What's new in Sudo 1.8.1p2?
+
+ * Two-character CIDR-style IPv4 netmasks are now matched correctly
+ in the sudoers file.
+
+ * A build error with MIT Kerberos V has been resolved.
+
+ * A crash on HP-UX in the sudoers plugin when wildcards are
+ present in the sudoers file has been resolved.
+
+ * Sudo now works correctly on Tru64 Unix again.
+
+What's new in Sudo 1.8.1p1?
+
+ * Fixed a problem on AIX where sudo was unable to set the final
+ UID if the PAM module modified the effective UID.
+
+ * A non-existent includedir is now treated the same as an empty
+ directory and not reported as an error.
+
+ * Removed extraneous parens in LDAP filter when sudoers_search_filter
+ is enabled that can cause an LDAP search error.
+
+ * Fixed a "make -j" problem for "make install".
+
+What's new in Sudo 1.8.1?
+
+ * A new LDAP setting, sudoers_search_filter, has been added to
+ ldap.conf. This setting can be used to restrict the set of
+ records returned by the LDAP query. Based on changes from Matthew
+ Thomas.
+
+ * White space is now permitted within a User_List when used in
+ conjunction with a per-user Defaults definition.
+
+ * A group ID (%#GID) may now be specified in a User_List or Runas_List.
+ Likewise, for non-Unix groups the syntax is %:#GID.
+
+ * Support for double-quoted words in the sudoers file has been fixed.
+ The change in 1.7.5 for escaping the double quote character
+ caused the double quoting to only be available at the beginning
+ of an entry.
+
+ * The fix for resuming a suspended shell in 1.7.5 caused problems
+ with resuming non-shells on Linux. Sudo will now save the process
+ group ID of the program it is running on suspend and restore it
+ when resuming, which fixes both problems.
+
+ * A bug that could result in corrupted output in "sudo -l" has been
+ fixed.
+
+ * Sudo will now create an entry in the utmp (or utmpx) file when
+ allocating a pseudo-tty (e.g. when logging I/O). The "set_utmp"
+ and "utmp_runas" sudoers file options can be used to control this.
+ Other policy plugins may use the "set_utmp" and "utmp_user"
+ entries in the command_info list.
+
+ * The sudoers policy now stores the TSID field in the logs
+ even when the "iolog_file" sudoers option is defined to a value
+ other than %{sessid}. Previously, the TSID field was only
+ included in the log file when the "iolog_file" option was set
+ to its default value.
+
+ * The sudoreplay utility now supports arbitrary session IDs.
+ Previously, it would only work with the base-36 session IDs
+ that the sudoers plugin uses by default.
+
+ * Sudo now passes "run_shell=true" to the policy plugin in the
+ settings list when sudo's -s command line option is specified.
+ The sudoers policy plugin uses this to implement the "set_home"
+ sudoers option which was missing from sudo 1.8.0.
+
+ * The "noexec" functionality has been moved out of the sudoers
+ policy plugin and into the sudo front-end, which matches the
+ behavior documented in the plugin writer's guide. As a result,
+ the path to the noexec file is now specified in the sudo.conf
+ file instead of the sudoers file.
+
+ * On Solaris 10, the PRIV_PROC_EXEC privilege is now used to
+ implement the "noexec" feature. Previously, this was implemented
+ via the LD_PRELOAD environment variable.
+
+ * The exit values for "sudo -l", "sudo -v" and "sudo -l command"
+ have been fixed in the sudoers policy plugin.
+
+ * The sudoers policy plugin now passes the login class, if any,
+ back to the sudo front-end.
+
+ * The sudoers policy plugin was not being linked with requisite
+ libraries in certain configurations.
+
+ * Sudo now parses command line arguments before loading any plugins.
+ This allows "sudo -V" or "sudo -h" to work even if there is a problem
+ with sudo.conf
+
+ * Plugins are now linked with the static version of libgcc to allow
+ the plugin to run on a system where no shared libgcc is installed,
+ or where it is installed in a different location.
+
+What's new in Sudo 1.8.0?
+
+ * Sudo has been refactored to use a modular framework that can
+ support third-party policy and I/O logging plugins. The default
+ plugin is "sudoers" which provides the traditional sudo functionality.
+ See the sudo_plugin manual for details on the plugin API and the
+ sample in the plugins directory for a simple example.
+
+What's new in Sudo 1.7.5?
+
+ * When using visudo in check mode, a file named "-" may be used to
+ check sudoers data on the standard input.
+
+ * Sudo now only fetches shadow password entries when using the
+ password database directly for authentication.
+
+ * Password and group entries are now cached using the same key
+ that was used to look them up. This fixes a problem when looking
+ up entries by name if the name in the retrieved entry does not
+ match the name used to look it up. This may happen on some systems
+ that do case insensitive lookups or that truncate long names.
+
+ * GCC will no longer display warnings on glibc systems that use
+ the warn_unused_result attribute for write(2) and other system calls.
+
+ * If a PAM account management module denies access, sudo now prints
+ a more useful error message and stops trying to validate the user.
+
+ * Fixed a potential hang on idle systems when the sudo-run process
+ exits immediately.
+
+ * Sudo now includes a copy of zlib that will be used on systems
+ that do not have zlib installed.
+
+ * The --with-umask-override configure flag has been added to enable
+ the "umask_override" sudoers Defaults option at build time.
+
+ * Sudo now unblocks all signals on startup to avoid problems caused
+ by the parent process changing the default signal mask.
+
+ * LDAP Sudoers entries may now specify a time period for which
+ the entry is valid. This requires an updated sudoers schema
+ that includes the sudoNotBefore and sudoNotAfter attributes.
+ Support for timed entries must be explicitly enabled in the
+ ldap.conf file. Based on changes from Andreas Mueller.
+
+ * LDAP Sudoers entries may now specify a sudoOrder attribute that
+ determines the order in which matching entries are applied. The
+ last matching entry is used, just like file-based sudoers. This
+ requires an updated sudoers schema that includes the sudoOrder
+ attribute. Based on changes from Andreas Mueller.
+
+ * When run as sudoedit, or when given the -e flag, sudo now treats
+ command line arguments as pathnames. This means that slashes
+ in the sudoers file entry must explicitly match slashes in
+ the command line arguments. As a result, and entry such as:
+ user ALL = sudoedit /etc/*
+ will allow editing of /etc/motd but not /etc/security/default.
+
+ * NETWORK_TIMEOUT is now an alias for BIND_TIMELIMIT in ldap.conf for
+ compatibility with OpenLDAP configuration files.
+
+ * The LDAP API TIMEOUT parameter is now honored in ldap.conf.
+
+ * The I/O log directory may now be specified in the sudoers file.
+
+ * Sudo will no longer refuse to run if the sudoers file is writable
+ by root.
+
+ * Sudo now performs command line escaping for "sudo -s" and "sudo -i"
+ after validating the command so the sudoers entries do not need
+ to include the backslashes.
+
+ * Logging and email sending are now done in the locale specified
+ by the "sudoers_locale" setting ("C" by default). Email send by
+ sudo now includes MIME headers when "sudoers_locale" is not "C".
+
+ * The configure script has a new option, --disable-env-reset, to
+ allow one to change the default for the sudoers Default setting
+ "env_reset" at compile time.
+
+ * When logging "sudo -l command", sudo will now prepend "list "
+ to the command in the log line to distinguish between an
+ actual command invocation in the logs.
+
+ * Double-quoted group and user names may now include escaped double
+ quotes as part of the name. Previously this was a parse error.
+
+ * Sudo once again restores the state of the signal handlers it
+ modifies before executing the command. This allows sudo to be
+ used with the nohup command.
+
+ * Resuming a suspended shell now works properly when I/O logging
+ is not enabled (the I/O logging case was already correct).
+
+What's new in Sudo 1.7.4p6?
+
+ * A bug has been fixed in the I/O logging support that could cause
+ visual artifacts in full-screen programs such as text editors.
+
+What's new in Sudo 1.7.4p5?
+
+ * A bug has been fixed that would allow a command to be run without the
+ user entering a password when sudo's -g flag is used without the -u flag.
+
+ * If user has no supplementary groups, sudo will now fall back on checking
+ the group file explicitly, which restores historic sudo behavior.
+
+ * A crash has been fixed when sudo's -g flag is used without the -u flag
+ and the sudoers file contains an entry with no runas user or group listed.
+
+ * A crash has been fixed when the Solaris project support is enabled
+ and sudo's -g flag is used without the -u flag.
+
+ * Sudo no longer exits with an error when support for auditing is
+ compiled in but auditing is not enabled.
+
+ * Fixed a bug introduced in sudo 1.7.3 where the ticket file was not
+ being honored when the "targetpw" sudoers Defaults option was enabled.
+
+ * The LOG_INPUT and LOG_OUTPUT tags in sudoers are now parsed correctly.
+
+ * A crash has been fixed in "sudo -l" when sudo is built with auditing
+ support and the user is not allowed to run any commands on the host.
+
+What's new in Sudo 1.7.4p4?
+
+ * A potential security issue has been fixed with respect to the handling
+ of sudo's -g command line option when -u is also specified. The flaw
+ may allow an attacker to run commands as a user that is not authorized
+ by the sudoers file.
+
+ * A bug has been fixed where "sudo -l" output was incomplete if multiple
+ sudoers sources were defined in nsswitch.conf and there was an error
+ querying one of the sources.
+
+ * The log_input, log_output, and use_pty sudoers options now work correctly
+ on AIX. Previously, sudo would hang if they were enabled.
+
+ * The "make install" target now works correctly when sudo is built in a
+ directory other than the source directory.
+
+ * The "runas_default" sudoers setting now works properly in a per-command
+ Defaults line.
+
+ * Suspending and resuming the bash shell when PAM is in use now works
+ correctly. The SIGCONT signal was not propagated to the child process.
+
+What's new in Sudo 1.7.4p3?
+
+ * A bug has been fixed where duplicate HOME environment variables could be
+ present when the env_reset setting was disabled and the always_set_home
+ setting was enabled in sudoers.
+
+ * The value of sysconfdir is now substituted into the path to the sudoers.d
+ directory in the installed sudoers file.
+
+ * Compilation problems on IRIX and other platforms have been fixed.
+
+ * If multiple PAM "auth" actions are specified and the user enters ^C at
+ the password prompt, sudo will no longer prompt for a password for any
+ subsequent "auth" actions. Previously it was necessary to enter ^C for
+ each "auth" action.
+
+What's new in Sudo 1.7.4p2?
+
+ * A bug where sudo could spin in a busy loop waiting for the child process
+ has been fixed.
+
+What's new in Sudo 1.7.4p1?
+
+ * A bug introduced in sudo 1.7.3 that prevented the -k and -K options from
+ functioning when the tty_tickets sudoers option is enabled has been fixed.
+
+ * Sudo no longer prints a warning when the -k or -K options are specified
+ and the ticket file does not exist.
+
+ * It is now easier to cross-compile sudo.
+
+What's new in Sudo 1.7.4?
+
+ * Sudoedit will now preserve the file extension in the name of the
+ temporary file being edited. The extension is used by some
+ editors (such as emacs) to choose the editing mode.
+
+ * Time stamp files have moved from /var/run/sudo to either /var/db/sudo,
+ /var/lib/sudo or /var/adm/sudo. The directories are checked for
+ existence in that order. This prevents users from receiving the
+ sudo lecture every time the system reboots. Time stamp files older
+ than the boot time are ignored on systems where it is possible to
+ determine this.
+
+ * The tty_tickets sudoers option is now enabled by default.
+
+ * Ancillary documentation (README files, LICENSE, etc) is now installed
+ in a sudo documentation directory.
+
+ * Sudo now recognizes "tls_cacert" as an alias for "tls_cacertfile"
+ in ldap.conf.
+
+ * Defaults settings that are tied to a user, host or command may
+ now include the negation operator. For example:
+ Defaults:!millert lecture
+ will match any user but millert.
+
+ * The default PATH environment variable, used when no PATH variable
+ exists, now includes /usr/sbin and /sbin.
+
+ * Sudo now uses polypkg (https://github.com/OneIdentity/Polypkg)
+ for cross-platform packing.
+
+ * On Linux, sudo will now restore the nproc resource limit before
+ executing a command, unless the limit appears to have been modified
+ by pam_limits. This avoids a problem with bash scripts that open
+ more than 32 descriptors on SuSE Linux, where sysconf(_SC_CHILD_MAX)
+ will return -1 when RLIMIT_NPROC is set to RLIMIT_UNLIMITED (-1).
+
+ * The HOME and MAIL environment variables are now reset based on the
+ target user's password database entry when the env_reset sudoers option
+ is enabled (which is the case in the default configuration). Users
+ wishing to preserve the original values should use a sudoers entry like:
+ Defaults env_keep += HOME
+ to preserve the old value of HOME and
+ Defaults env_keep += MAIL
+ to preserve the old value of MAIL.
+
+ * Fixed a problem in the restoration of the AIX authdb registry setting.
+
+ * Sudo will now fork(2) and wait until the command has completed before
+ calling pam_close_session().
+
+ * The default syslog facility is now "authpriv" if the operating system
+ supports it, else "auth".
+
+What's new in Sudo 1.7.3?
+
+ * Support for logging I/O for the command being run.
+ For more information, see the documentation for the "log_input"
+ and "log_output" Defaults options in the sudoers manual. Also
+ see the sudoreplay manual for how to replay I/O log sessions.
+
+ * The use_pty sudoers option can be used to force a command to be
+ run in a pseudo-pty, even when I/O logging is not enabled.
+
+ * On some systems, sudo can now detect when a user has logged out
+ and back in again when tty-based time stamps are in use. Supported
+ systems include Solaris systems with the devices file system,
+ Mac OS X, and Linux systems with the devpts filesystem (pseudo-ttys
+ only).
+
+ * On AIX systems, the registry setting in /etc/security/user is
+ now taken into account when looking up users and groups. Sudo
+ now applies the correct the user and group ids when running a
+ command as a user whose account details come from a different
+ source (e.g. LDAP or DCE vs. local files).
+
+ * Support for multiple 'sudoers_base' and 'uri' entries in ldap.conf.
+ When multiple entries are listed, sudo will try each one in the
+ order in which they are specified.
+
+ * Sudo's SELinux support should now function correctly when running
+ commands as a non-root user and when one of stdin, stdout or stderr
+ is not a terminal.
+
+ * Sudo will now use the Linux audit system with configure with
+ the --with-linux-audit flag.
+
+ * Sudo now uses mbr_check_membership() on systems that support it
+ to determine group membership. Currently, only Darwin (Mac OS X)
+ supports this.
+
+ * When the tty_tickets sudoers option is enabled but there is no
+ terminal device, sudo will no longer use or create a tty-based
+ ticket file. Previously, sudo would use a tty name of "unknown".
+ As a consequence, if a user has no terminal device, sudo will
+ now always prompt for a password.
+
+ * The passwd_timeout and timestamp_timeout options may now be
+ specified as floating point numbers for more granular timeout
+ values.
+
+ * Negating the fqdn option in sudoers now works correctly when sudo
+ is configured with the --with-fqdn option. In previous versions
+ of sudo the fqdn was set before sudoers was parsed.
+
+What's new in Sudo 1.7.2?
+
+ * A new #includedir directive is available in sudoers. This can be
+ used to implement an /etc/sudo.d directory. Files in an includedir
+ are not edited by visudo unless they contain a syntax error.
+
+ * The -g option did not work properly when only setting the group
+ (and not the user). Also, in -l mode the wrong user was displayed
+ for sudoers entries where only the group was allowed to be set.
+
+ * Fixed a problem with the alias checking in visudo which
+ could prevent visudo from exiting.
+
+ * Sudo will now correctly parse the shell-style /etc/environment
+ file format used by pam_env on Linux.
+
+ * When doing password and group database lookups, sudo will only
+ cache an entry by name or by id, depending on how the entry was
+ looked up. Previously, sudo would cache by both name and id
+ from a single lookup, but this breaks sites that have multiple
+ password or group database names that map to the same UID or
+ GID.
+
+ * User and group names in sudoers may now be enclosed in double
+ quotes to avoid having to escape special characters.
+
+ * BSM audit fixes when changing to a non-root UID.
+
+ * Experimental non-Unix group support. Currently only works with
+ Quest Authorization Services and allows Active Directory groups
+ fixes for Minix-3.
+
+ * For Netscape/Mozilla-derived LDAP SDKs the certificate and key
+ paths may be specified as a directory or a file. However, version
+ 5.0 of the SDK only appears to support using a directory (despite
+ documentation to the contrary). If SSL client initialization
+ fails and the certificate or key paths look like they could be
+ default file name, strip off the last path element and try again.
+
+ * A setenv() compatibility fix for Linux systems, where a NULL
+ value is treated the same as an empty string and the variable
+ name is checked against the NULL pointer.
+
+What's new in Sudo 1.7.1?
+
+ * A new Defaults option "pwfeedback" will cause sudo to provide visual
+ feedback when the user is entering a password.
+
+ * A new Defaults option "fast_glob" will cause sudo to use the fnmatch()
+ function for file name globbing instead of glob(). When this option
+ is enabled, sudo will not check the file system when expanding wildcards.
+ This is faster but a side effect is that relative paths with wildcard
+ will no longer work.
+
+ * New BSM audit support for systems that support it such as FreeBSD
+ and Mac OS X.
+
+ * The file name specified with the #include directive may now include
+ a %h escape which is expanded to the short form of hostname.
+
+ * The -k flag may now be specified along with a command, causing the
+ user's timestamp file to be ignored.
+
+ * New support for Tivoli-based LDAP START_TLS, present in AIX.
+
+ * New support for /etc/netsvc.conf on AIX.
+
+ * The unused alias checks in visudo now handle the case of an alias
+ referring to another alias.
+
+What's new in Sudo 1.7.0?
+
+ * Rewritten parser that converts sudoers into a set of data structures.
+ This eliminates a number of ordering issues and makes it possible to
+ apply sudoers Defaults entries before searching for the command.
+ It also adds support for per-command Defaults specifications.
+
+ * Sudoers now supports a #include facility to allow the inclusion of other
+ sudoers-format files.
+
+ * Sudo's -l (list) flag has been enhanced:
+ o applicable Defaults options are now listed
+ o a command argument can be specified for testing whether a user
+ may run a specific command.
+ o a new -U flag can be used in conjunction with "sudo -l" to allow
+ root (or a user with "sudo ALL") list another user's privileges.
+
+ * A new -g flag has been added to allow the user to specify a
+ primary group to run the command as. The sudoers syntax has been
+ extended to include a group section in the Runas specification.
+
+ * A UID may now be used anywhere a username is valid.
+
+ * The "secure_path" run-time Defaults option has been restored.
+
+ * Password and group data is now cached for fast lookups.
+
+ * The file descriptor at which sudo starts closing all open files is now
+ configurable via sudoers and, optionally, the command line.
+
+ * Visudo will now warn about aliases that are defined but not used.
+
+ * The -i and -s command line flags now take an optional command
+ to be run via the shell. Previously, the argument was passed
+ to the shell as a script to run.
+
+ * Improved LDAP support. SASL authentication may now be used in
+ conjunction when connecting to an LDAP server. The krb5_ccname
+ parameter in ldap.conf may be used to enable Kerberos.
+
+ * Support for /etc/nsswitch.conf. LDAP users may now use nsswitch.conf
+ to specify the sudoers order. E.g.:
+ sudoers: ldap files
+ to check LDAP, then /etc/sudoers. The default is "files", even
+ when LDAP support is compiled in. This differs from sudo 1.6
+ where LDAP was always consulted first.
+
+ * Support for /etc/environment on AIX and Linux. If sudo is run
+ with the -i flag, the contents of /etc/environment are used to
+ populate the new environment that is passed to the command being
+ run.
+
+ * If no terminal is available or if the new -A flag is specified,
+ sudo will use a helper program to read the password if one is
+ configured. Typically, this is a graphical password prompter
+ such as ssh-askpass.
+
+ * A new Defaults option, "mailfrom" that sets the value of the
+ "From:" field in the warning/error mail. If unspecified, the
+ login name of the invoking user is used.
+
+ * A new Defaults option, "env_file" that refers to a file containing
+ environment variables to be set in the command being run.
+
+ * A new flag, -n, may be used to indicate that sudo should not
+ prompt the user for a password and, instead, exit with an error
+ if authentication is required.
+
+ * If sudo needs to prompt for a password and it is unable to disable
+ echo (and no askpass program is defined), it will refuse to run
+ unless the "visiblepw" Defaults option has been specified.
+
+ * Prior to version 1.7.0, hitting enter/return at the Password: prompt
+ would exit sudo. In sudo 1.7.0 and beyond, this is treated as
+ an empty password. To exit sudo, the user must press ^C or ^D
+ at the prompt.
+
+ * visudo will now check the sudoers file owner and mode in -c (check)
+ mode when the -s (strict) flag is specified.
+
+ * A new Defaults option "umask_override" will cause sudo to set the
+ umask specified in sudoers even if it is more permissive than the
+ invoking user's umask.
diff --git a/README.LDAP.md b/README.LDAP.md
new file mode 100644
index 0000000..7d3e97f
--- /dev/null
+++ b/README.LDAP.md
@@ -0,0 +1,209 @@
+This file explains how to build the optional LDAP functionality of SUDO to
+store /etc/sudoers information. This feature is distinct from LDAP passwords.
+
+For general sudo LDAP configuration details, see the sudoers.ldap manual that
+comes with the sudo distribution. A pre-formatted version of the manual may
+be found in the sudoers.ldap.cat file.
+
+The sudo binary compiled with LDAP support should be totally backward
+compatible and be syntactically and source code equivalent to its
+non LDAP-enabled build.
+
+## LDAP philosophy
+
+As times change and servers become cheap, an enterprise can easily have 500+
+UNIX servers. Using LDAP to synchronize Users, Groups, Hosts, Mounts, and
+others across an enterprise can greatly reduce the administrative overhead.
+
+In the past, sudo has used a single local configuration file, /etc/sudoers.
+While the same sudoers file can be shared among machines, no built-in
+mechanism exists to distribute it. Some have attempted to workaround this
+by synchronizing changes via CVS/RSYNC/RDIST/RCP/SCP and even NFS.
+
+By using LDAP for sudoers we gain a centrally administered, globally
+available configuration source for sudo.
+
+For information on OpenLDAP, see https://www.openldap.org/.
+
+## Definitions
+
+Many times the word 'Directory' is used in the document to refer to the LDAP
+server, structure, and contents.
+
+Many times 'options' are used in this document to refer to sudoer 'defaults'.
+They are one and the same.
+
+## Build instructions
+
+The simplest way to build sudo with LDAP support is to include the
+`--with-ldap` option.
+
+ $ ./configure --with-ldap
+
+If your ldap libraries and headers are in a non-standard place, you will need
+to specify them at configure time. E.g.
+
+ $ ./configure --with-ldap=/usr/local/ldapsdk
+
+Sudo is developed using OpenLDAP but Netscape-based LDAP libraries
+(such as those present in Solaris) and IBM LDAP are also known to work.
+
+If special configuration was required to build an LDAP-enabled sudo,
+let the sudo workers mailing list <sudo-workers@sudo.ws> know so
+we can improve sudo.
+
+## Schema Changes
+
+You must add the appropriate schema to your LDAP server before it
+can store sudoers content.
+
+For OpenLDAP, there are two options, depending on how slapd is configured.
+
+The first option is to copy the file schema.OpenLDAP to the schema
+directory (e.g. /etc/openldap/schema). You must then edit your
+slapd.conf and add an include line the new schema, for example:
+
+ # Sudo LDAP schema
+ include /etc/openldap/schema/sudo.schema
+
+In order for sudoRole LDAP queries to be efficient, the server must index
+the attribute 'sudoUser', for example:
+
+ # Indices to maintain
+ index sudoUser eq
+
+After making the changes to slapd.conf, restart slapd.
+
+The second option is only for OpenLDAP 2.3 and higher where slapd.conf
+has been configured to use on-line configuration. If your slapd.conf
+file includes the line:
+
+ database config
+
+it should be possible to use the schema.olcSudo file.
+
+You can apply schema.olcSudo using the ldapadd utility or another
+suitable LDAP browser. For example:
+
+ # ldapadd -f schema.olcSudo -H ldap://ldapserver -W -x \
+ -D cn=Manager,dc=example,dc=com
+
+There is no need to restart slapd when updating on-line configuration.
+
+For Netscape-derived LDAP servers such as SunONE, iPlanet, or Fedora Directory,
+copy the schema.iPlanet file to the schema directory with the name 99sudo.ldif.
+
+On Solaris, schemas are stored in /var/Sun/mps/slapd-\`hostname\`/config/schema/.
+For Fedora Directory Server, they are stored in /etc/dirsrv/schema/.
+
+After copying the schema file to the appropriate directory, restart
+the LDAP server.
+
+Finally, using an LDAP browser/editor, enable indexing by editing the
+client profile to provide a Service Search Descriptor (SSD) for sudoers,
+replacing example.com with your domain:
+
+ serviceSearchDescriptor: sudoers: ou=sudoers,dc=example,dc=com
+
+If using an Active Directory server, copy schema.ActiveDirectory
+to your Windows domain controller and run the following command:
+
+ ldifde -i -f schema.ActiveDirectory -c dc=X dc=example,dc=com
+
+## Importing /etc/sudoers into LDAP
+
+Importing sudoers is a two-step process.
+
+1. Ask your LDAP Administrator where to create the ou=SUDOers container.
+ For instance, if using OpenLDAP:
+```
+ dn: ou=SUDOers,dc=example,dc=com
+ objectClass: top
+ objectClass: organizationalUnit
+ ou: SUDOers
+```
+
+(An example location is shown below). Then use the cvtsudoers utility to
+convert your sudoers file into LDIF format.
+```
+ # SUDOERS_BASE=ou=SUDOers,dc=example,dc=com
+ # export SUDOERS_BASE
+ # cvtsudoers -f ldif -o /tmp/sudoers.ldif /etc/sudoers
+```
+
+2. Import into your directory server. The following example is for
+ OpenLDAP. If you are using another directory, provide the LDIF
+ file to your LDAP Administrator.
+```
+ # ldapadd -f /tmp/sudoers.ldif -H ldap://ldapserver \
+ -D cn=Manager,dc=example,dc=com -W -x
+```
+
+3. Verify the sudoers LDAP data:
+```
+ # ldapsearch -b "$SUDOERS_BASE" -D cn=Manager,dc=example,dc=com -W -x
+```
+
+## Managing LDAP entries
+
+Doing a one-time bulk load of your ldap entries is fine. However what if you
+need to make minor changes on a daily basis? It doesn't make sense to delete
+and re-add objects. (You can, but this is tedious).
+
+I recommend using any of the following LDAP browsers to administer your SUDOers.
+
+ * GQ - The gentleman's LDAP client - Open Source - I use this a lot on Linux
+ and since it is Schema aware, I don't need to create a sudoRole template.
+
+ https://sourceforge.net/projects/gqclient/
+
+ * phpQLAdmin - Open Source - phpQLAdmin is an administration tool,
+ originally for QmailLDAP, that supports editing sudoRole objects
+ in version 2.3.2 and higher.
+
+ http://phpqladmin.com/
+
+ * LDAP Browser/Editor - by Jarek Gawor - I use this a lot on Windows
+ and Solaris. It runs anywhere in a Java Virtual Machine including
+ web pages. You have to make a template from an existing sudoRole entry.
+
+ http://pi.hv.pl/Gawor%20ldapbrowser/
+
+ * Apache Directory Studio - Open Source - an Eclipse-based LDAP
+ development platform. Includes an LDAP browser, and LDIF editor,
+ a schema editor and more.
+
+ https://directory.apache.org/studio
+
+ There are dozens of others, some Open Source, some free, some not.
+
+## Configure your /etc/ldap.conf and /etc/nsswitch.conf
+
+The /etc/ldap.conf file is meant to be shared between sudo, pam_ldap, nss_ldap
+and other ldap applications and modules. IBM Secureway unfortunately uses
+the same file name but has a different syntax. If you need to change where
+this file is stored, re-run configure with the `--with-ldap-conf-file=PATH`
+option.
+
+See the "Configuring ldap.conf" section in the sudoers.ldap manual
+for a list of supported ldap.conf parameters and an example ldap.conf
+
+Make sure you sudoers_base matches the location you specified when you
+imported the sudoers ldif data.
+
+After configuring /etc/ldap.conf, you must add a line in the
+/etc/nsswitch.conf file to tell sudo to look in LDAP for sudoers.
+See the "Configuring nsswitch.conf" section in the sudoers.ldap
+manual for details. Sudo will use /etc/nsswitch.conf even if the
+underlying operating system does not support it. To disable nsswitch
+support, run configure with the `--with-nsswitch=no` option. This
+will cause sudo to consult LDAP first and /etc/sudoers second,
+unless the ignore_sudoers_file flag is set in the global LDAP options.
+
+## Debugging your LDAP configuration
+
+Enable debugging if you believe sudo is not parsing LDAP the way you think it
+should. Setting the 'sudoers_debug' parameter to a value of 1 shows moderate
+debugging. A value of 2 shows the results of the matches themselves. Make
+sure to set the value back to zero so that other users don't get confused by
+the debugging messages.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2eabc05
--- /dev/null
+++ b/README.md
@@ -0,0 +1,105 @@
+## The sudo philosophy
+
+Sudo is a program designed to allow a sysadmin to give limited root privileges
+to users and log root activity. The basic philosophy is to give as few
+privileges as possible but still allow people to get their work done.
+
+## Where to find sudo
+
+Before building sudo, make sure you have the current version. The
+latest sudo may always be gotten via anonymous ftp from ftp.sudo.ws
+in the directory /pub/sudo/ or from the sudo web site, https://www.sudo.ws/
+
+The distribution is sudo-M.m.tar.gz where _M_ is the major version
+number and _m_ is the minor version number. Beta versions of sudo may
+also be available. If you join the _sudo-workers_ mailing list you
+will get the beta announcements (see the Mailing lists section below).
+
+## What's new
+
+See the NEWS file for a list of major changes in this release. For
+a complete list of changes, see the [ChangeLog](ChangeLog).
+For a summary of major changes to the current stable release, see
+https://www.sudo.ws/releases/stable/.
+
+If you are upgrading from an earlier version of Sudo, read
+[docs/UPGRADE.md](docs/UPGRADE.md) for information on changes in
+behavior that may affect you.
+
+For a history of sudo see [docs/HISTORY.md](docs/HISTORY.md).
+You can find a list of contributors to sudo in
+[docs/CONTRIBUTORS.md](docs/CONTRIBUTORS.md).
+
+## Building the release
+
+Read the installation guide, [INSTALL.md](INSTALL.md), before trying
+to build sudo. Pay special attention to the "OS dependent notes" section.
+
+## How to contribute
+
+See [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) for information on
+how you can help contribute to sudo.
+
+## Copyright
+
+Sudo is distributed under an ISC-style license.
+Refer to [LICENSE.md](LICENSE.md) for details.
+
+## Mailing lists
+
+#### sudo-announce
+
+This list receives announcements whenever a new version of sudo is
+released. https://www.sudo.ws/mailman/listinfo/sudo-announce
+
+#### sudo-blog
+
+This list receives a message when a new sudo blog article is
+available. https://www.sudo.ws/mailman/listinfo/sudo-blog
+
+#### sudo-commits
+
+This list receives a message for each commit made to the sudo source
+repository. https://www.sudo.ws/mailman/listinfo/sudo-commits
+
+#### sudo-users
+
+This list is for questions and general discussion about sudo.
+https://www.sudo.ws/mailman/listinfo/sudo-users
+
+#### sudo-workers
+
+This list is for people working on and porting sudo.
+https://www.sudo.ws/mailman/listinfo/sudo-workers
+
+To subscribe to a list, visit its url (listed above) and enter your
+email address to subscribe. Digest versions are available but these are
+fairly low traffic lists so the digest versions are not a significant win.
+
+Mailing list archives are also available. See the mailing list web sites
+for the appropriate links.
+
+## Sudo web page
+
+There is a sudo web page at https://www.sudo.ws/ that contains
+documentation, downloads, a bug tracker, the source repo, the sudo
+blog, information about beta versions and other useful info.
+
+## Filing bug reports/issues
+
+If you believe you have found a bug, you can either file a bug
+report in the sudo bug database, https://bugzilla.sudo.ws/, or open
+a [GitHub issue](https://github.com/sudo-project/sudo/issues),
+whichever you find easier. If you would prefer to use email,
+messages may be sent to the [sudo-workers@sudo.ws mailing
+list](https://www.sudo.ws/mailman/listinfo/sudo-workers) (public)
+or to sudo@sudo.ws (private).
+
+For sudo's security policy and how to report security issues, see
+[docs/SECURITY.md](docs/SECURITY.md).
+
+Please check [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md)
+*before* submitting a bug report. When reporting bugs, be sure to
+include the version of sudo you are using, the operating system
+and/or distro that is affected, and, if possible, step-by-step
+instructions to reproduce the problem.
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..718cfec
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,36 @@
+# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
+
+# Copyright (C) 1996-2021 Free Software Foundation, Inc.
+
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+m4_include([m4/ax_append_flag.m4])
+m4_include([m4/ax_check_compile_flag.m4])
+m4_include([m4/ax_check_link_flag.m4])
+m4_include([m4/ax_func_getaddrinfo.m4])
+m4_include([m4/ax_func_snprintf.m4])
+m4_include([m4/ax_gcc_builtin.m4])
+m4_include([m4/ax_prog_cc_for_build.m4])
+m4_include([m4/gettext.m4])
+m4_include([m4/hardening.m4])
+m4_include([m4/ldap.m4])
+m4_include([m4/libtool.m4])
+m4_include([m4/ltoptions.m4])
+m4_include([m4/ltsugar.m4])
+m4_include([m4/ltversion.m4])
+m4_include([m4/lt~obsolete.m4])
+m4_include([m4/openssl.m4])
+m4_include([m4/pie.m4])
+m4_include([m4/python.m4])
+m4_include([m4/runlog.m4])
+m4_include([m4/sanitizer.m4])
+m4_include([m4/sudo.m4])
+m4_include([m4/visibility.m4])
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..a922f60
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# OpenBSD may have multiple versions of autoconf and automake installed
+# If the user hasn't chosen one themselves, we do here.
+if [ "`/usr/bin/uname 2>&1`" = "OpenBSD" ]; then
+ if [ X"$AUTOMAKE_VERSION" = X"" ]; then
+ AUTOMAKE_VERSION=1.16; export AUTOMAKE_VERSION
+ fi
+ if [ X"$AUTOCONF_VERSION" = X"" ]; then
+ AUTOCONF_VERSION=2.71; export AUTOCONF_VERSION
+ fi
+fi
+
+set -ex
+
+autoreconf -f -i -v -Wall -I m4
+
+rm -rf autom4te.cache
+
+exit 0
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 0000000..7361c02
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,1709 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+#ifndef SUDO_CONFIG_H
+#define SUDO_CONFIG_H
+
+/* Configure script arguments used to build sudo. */
+#undef CONFIGURE_ARGS
+
+/* Define to 1 if you want the insults from the "classic" version sudo. */
+#undef CLASSIC_INSULTS
+
+/* Define to 1 if you want insults culled from the twisted minds of CSOps. */
+#undef CSOPS_INSULTS
+
+/* Define to 1 if you want sudo to display "command not allowed" instead of
+ "command not found" when a command cannot be found. */
+#undef DONT_LEAK_PATH_INFO
+
+/* A colon-separated list of pathnames to be used as the editor for visudo. */
+#undef EDITOR
+
+/* Define to 1 to enable sudo's plugin interface. */
+#undef ENABLE_SUDO_PLUGIN_API
+
+/* Define to 1 to enable environment function debugging. */
+#undef ENV_DEBUG
+
+/* Define to 1 if you want visudo to honor the EDITOR and VISUAL env
+ variables. */
+#undef ENV_EDITOR
+
+/* Define to 1 to enable environment resetting by default. */
+#undef ENV_RESET
+
+/* If defined, users in this group need not enter a passwd (ie "sudo"). */
+#undef EXEMPTGROUP
+
+/* Define to 1 if you want to require fully qualified hosts in sudoers. */
+#undef FQDN
+
+/* Define to the type of elements in the array argument to 'getgroups'.
+ Usually this is either 'int' or 'gid_t'. */
+#undef GETGROUPS_T
+
+/* Define to 1 if you want insults from the "Goon Show". */
+#undef GOONS_INSULTS
+
+/* Define to 1 if you want 2001-like insults. */
+#undef HAL_INSULTS
+
+/* Define to 1 if you use AFS. */
+#undef HAVE_AFS
+
+/* Define to 1 if you use AIX general authentication. */
+#undef HAVE_AIXAUTH
+
+/* Define to 1 to enable AppArmor support. */
+#undef HAVE_APPARMOR
+
+/* Define to 1 if you have the 'arc4random' function. */
+#undef HAVE_ARC4RANDOM
+
+/* Define to 1 if you have the 'arc4random_buf' function. */
+#undef HAVE_ARC4RANDOM_BUF
+
+/* Define to 1 if you have the 'arc4random_uniform' function. */
+#undef HAVE_ARC4RANDOM_UNIFORM
+
+/* Define to 1 if you have the 'ASN1_STRING_get0_data' function. */
+#undef HAVE_ASN1_STRING_GET0_DATA
+
+/* Define to 1 if you have the 'asprintf' function. */
+#undef HAVE_ASPRINTF
+
+/* Define to 1 if the system has the type 'authdb_t'. */
+#undef HAVE_AUTHDB_T
+
+/* Define to 1 if you have the 'authenticate' function. */
+#undef HAVE_AUTHENTICATE
+
+/* Define to 1 if you have the 'auth_challenge' function. */
+#undef HAVE_AUTH_CHALLENGE
+
+/* Define to 1 if the 'au_close' functions takes 4 arguments like Solaris 11.
+ */
+#undef HAVE_AU_CLOSE_SOLARIS11
+
+/* Define to 1 if you have the 'bigcrypt' function. */
+#undef HAVE_BIGCRYPT
+
+/* Define to 1 if you use BSD authentication. */
+#undef HAVE_BSD_AUTH_H
+
+/* Define to 1 to enable BSM audit support. */
+#undef HAVE_BSM_AUDIT
+
+/* Define to 1 if you have the 'bzero' function. */
+#undef HAVE_BZERO
+
+/* Define to 1 if you have the 'cfmakeraw' function. */
+#undef HAVE_CFMAKERAW
+
+/* Define to 1 if you have the 'clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
+/* Define to 1 if you have the 'closefrom' function. */
+#undef HAVE_CLOSEFROM
+
+/* Define to 1 if you have the 'close_range' function. */
+#undef HAVE_CLOSE_RANGE
+
+/* Define to 1 if you have the <crt_externs.h> header file. */
+#undef HAVE_CRT_EXTERNS_H
+
+/* Define to 1 if you have the 'crypt' function. */
+#undef HAVE_CRYPT
+
+/* Define to 1 if you use OSF DCE. */
+#undef HAVE_DCE
+
+/* Define to 1 if your 'DIR' contains dd_fd. */
+#undef HAVE_DD_FD
+
+/* Define to 1 if you have the declaration of 'errno', and to 0 if you don't.
+ */
+#undef HAVE_DECL_ERRNO
+
+/* Define to 1 if you have the declaration of 'getdelim', and to 0 if you
+ don't. */
+#undef HAVE_DECL_GETDELIM
+
+/* Define to 1 if you have the declaration of 'getdomainname', and to 0 if you
+ don't. */
+#undef HAVE_DECL_GETDOMAINNAME
+
+/* Define to 1 if you have the declaration of 'getgrouplist_2', and to 0 if
+ you don't. */
+#undef HAVE_DECL_GETGROUPLIST_2
+
+/* Define to 1 if you have the declaration of 'getresuid', and to 0 if you
+ don't. */
+#undef HAVE_DECL_GETRESUID
+
+/* Define to 1 if you have the declaration of 'getusershell', and to 0 if you
+ don't. */
+#undef HAVE_DECL_GETUSERSHELL
+
+/* Define to 1 if you have the declaration of 'h_errno', and to 0 if you
+ don't. */
+#undef HAVE_DECL_H_ERRNO
+
+/* Define to 1 if you have the declaration of 'innetgr', and to 0 if you
+ don't. */
+#undef HAVE_DECL_INNETGR
+
+/* Define to 1 if you have the declaration of 'LLONG_MAX', and to 0 if you
+ don't. */
+#undef HAVE_DECL_LLONG_MAX
+
+/* Define to 1 if you have the declaration of 'LLONG_MIN', and to 0 if you
+ don't. */
+#undef HAVE_DECL_LLONG_MIN
+
+/* Define to 1 if you have the declaration of 'NSIG', and to 0 if you don't.
+ */
+#undef HAVE_DECL_NSIG
+
+/* Define to 1 if you have the declaration of 'PATH_MAX', and to 0 if you
+ don't. */
+#undef HAVE_DECL_PATH_MAX
+
+/* Define to 1 if you have the declaration of 'pread64', and to 0 if you
+ don't. */
+#undef HAVE_DECL_PREAD64
+
+/* Define to 1 if you have the declaration of 'pwrite64', and to 0 if you
+ don't. */
+#undef HAVE_DECL_PWRITE64
+
+/* Define to 1 if you have the declaration of 'QUAD_MAX', and to 0 if you
+ don't. */
+#undef HAVE_DECL_QUAD_MAX
+
+/* Define to 1 if you have the declaration of 'QUAD_MIN', and to 0 if you
+ don't. */
+#undef HAVE_DECL_QUAD_MIN
+
+/* Define to 1 if you have the declaration of 'SECCOMP_MODE_FILTER', and to 0
+ if you don't. */
+#undef HAVE_DECL_SECCOMP_MODE_FILTER
+
+/* Define to 1 if you have the declaration of 'setauthdb', and to 0 if you
+ don't. */
+#undef HAVE_DECL_SETAUTHDB
+
+/* Define to 1 if you have the declaration of 'setresuid', and to 0 if you
+ don't. */
+#undef HAVE_DECL_SETRESUID
+
+/* Define to 1 if you have the declaration of 'SIG2STR_MAX', and to 0 if you
+ don't. */
+#undef HAVE_DECL_SIG2STR_MAX
+
+/* Define to 1 if you have the declaration of 'SIZE_MAX', and to 0 if you
+ don't. */
+#undef HAVE_DECL_SIZE_MAX
+
+/* Define to 1 if you have the declaration of 'SIZE_T_MAX', and to 0 if you
+ don't. */
+#undef HAVE_DECL_SIZE_T_MAX
+
+/* Define to 1 if you have the declaration of 'SSIZE_MAX', and to 0 if you
+ don't. */
+#undef HAVE_DECL_SSIZE_MAX
+
+/* Define to 1 if you have the declaration of 'sys_sigabbrev', and to 0 if you
+ don't. */
+#undef HAVE_DECL_SYS_SIGABBREV
+
+/* Define to 1 if you have the declaration of 'sys_siglist', and to 0 if you
+ don't. */
+#undef HAVE_DECL_SYS_SIGLIST
+
+/* Define to 1 if you have the declaration of 'sys_signame', and to 0 if you
+ don't. */
+#undef HAVE_DECL_SYS_SIGNAME
+
+/* Define to 1 if you have the declaration of 'ULLONG_MAX', and to 0 if you
+ don't. */
+#undef HAVE_DECL_ULLONG_MAX
+
+/* Define to 1 if you have the declaration of 'UQUAD_MAX', and to 0 if you
+ don't. */
+#undef HAVE_DECL_UQUAD_MAX
+
+/* Define to 1 if you have the declaration of 'usrinfo', and to 0 if you
+ don't. */
+#undef HAVE_DECL_USRINFO
+
+/* Define to 1 if you have the declaration of '_innetgr', and to 0 if you
+ don't. */
+#undef HAVE_DECL__INNETGR
+
+/* Define to 1 if you have the declaration of '_NSIG', and to 0 if you don't.
+ */
+#undef HAVE_DECL__NSIG
+
+/* Define to 1 if you have the declaration of '_POSIX_PATH_MAX', and to 0 if
+ you don't. */
+#undef HAVE_DECL__POSIX_PATH_MAX
+
+/* Define to 1 if you have the declaration of '_sys_siglist', and to 0 if you
+ don't. */
+#undef HAVE_DECL__SYS_SIGLIST
+
+/* Define to 1 if you have the declaration of '_sys_signame', and to 0 if you
+ don't. */
+#undef HAVE_DECL__SYS_SIGNAME
+
+/* Define to 1 if you have the declaration of '__NSIG', and to 0 if you don't.
+ */
+#undef HAVE_DECL___NSIG
+
+/* Define to 1 if you have the 'devname' function. */
+#undef HAVE_DEVNAME
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines 'DIR'.
+ */
+#undef HAVE_DIRENT_H
+
+/* Define to 1 if you have the 'dirfd' function or macro. */
+#undef HAVE_DIRFD
+
+/* Define to 1 if you have the 'dispcrypt' function. */
+#undef HAVE_DISPCRYPT
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the 'dlopen' function. */
+#undef HAVE_DLOPEN
+
+/* Define to 1 if you have the 'dl_iterate_phdr' function. */
+#undef HAVE_DL_ITERATE_PHDR
+
+/* Define to 1 if the compiler supports the __visibility__ attribute. */
+#undef HAVE_DSO_VISIBILITY
+
+/* Define to 1 if you have the 'dup3' function. */
+#undef HAVE_DUP3
+
+/* Define to 1 if you have the <endian.h> header file. */
+#undef HAVE_ENDIAN_H
+
+/* Define to 1 if you have the 'exect' function. */
+#undef HAVE_EXECT
+
+/* Define to 1 if you have the 'execvP' function. */
+#undef HAVE_EXECVP
+
+/* Define to 1 if you have the 'execvpe' function. */
+#undef HAVE_EXECVPE
+
+/* Define to 1 if you have the 'explicit_bzero' function. */
+#undef HAVE_EXPLICIT_BZERO
+
+/* Define to 1 if you have the 'explicit_memset' function. */
+#undef HAVE_EXPLICIT_MEMSET
+
+/* Define to 1 if you have the 'faccessat' function. */
+#undef HAVE_FACCESSAT
+
+/* Define to 1 if the compiler supports the fallthrough attribute. */
+#undef HAVE_FALLTHROUGH_ATTRIBUTE
+
+/* Define to 1 if you have the 'fchmodat' function. */
+#undef HAVE_FCHMODAT
+
+/* Define to 1 if you have the 'fchownat' function. */
+#undef HAVE_FCHOWNAT
+
+/* Define to 1 if your system has the F_CLOSEM fcntl. */
+#undef HAVE_FCNTL_CLOSEM
+
+/* Define to 1 if you have the 'fexecve' function. */
+#undef HAVE_FEXECVE
+
+/* Define to 1 if you have the 'fmemopen' function. */
+#undef HAVE_FMEMOPEN
+
+/* Define to 1 if you have the 'fnmatch' function. */
+#undef HAVE_FNMATCH
+
+/* Define to 1 if you have the 'freeifaddrs' function. */
+#undef HAVE_FREEIFADDRS
+
+/* Define to 1 if you have the 'freezero' function. */
+#undef HAVE_FREEZERO
+
+/* Define to 1 if fseeko (and ftello) are declared in stdio.h. */
+#undef HAVE_FSEEKO
+
+/* Define to 1 if you have the 'fstatat' function. */
+#undef HAVE_FSTATAT
+
+/* Define to 1 if you have the 'futime' function. */
+#undef HAVE_FUTIME
+
+/* Define to 1 if you have the 'futimens' function. */
+#undef HAVE_FUTIMENS
+
+/* Define to 1 if you have the 'futimes' function. */
+#undef HAVE_FUTIMES
+
+/* Define to 1 if you have the 'futimesat' function. */
+#undef HAVE_FUTIMESAT
+
+/* Define to 1 if you use the FWTK authsrv daemon. */
+#undef HAVE_FWTK
+
+/* Define to 1 if you are using gcrypt's sha2 functions. */
+#undef HAVE_GCRYPT
+
+/* Define to 1 if you have the 'getaddrinfo' function. */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if you have the 'getauxval' function. */
+#undef HAVE_GETAUXVAL
+
+/* Define to 1 if you have the 'getdelim' function. */
+#undef HAVE_GETDELIM
+
+/* Define to 1 if you have the 'getdomainname' function. */
+#undef HAVE_GETDOMAINNAME
+
+/* Define to 1 if you have the 'getentropy' function. */
+#undef HAVE_GETENTROPY
+
+/* Define to 1 if you have the 'getgrouplist' function. */
+#undef HAVE_GETGROUPLIST
+
+/* Define to 1 if you have the 'getgrouplist_2' function. */
+#undef HAVE_GETGROUPLIST_2
+
+/* Define to 1 if your system has a working 'getgroups' function. */
+#undef HAVE_GETGROUPS
+
+/* Define to 1 if you have the 'getgrset' function. */
+#undef HAVE_GETGRSET
+
+/* Define to 1 if you have the 'gethrtime' function. */
+#undef HAVE_GETHRTIME
+
+/* Define to 1 if you have the 'getifaddrs' function. */
+#undef HAVE_GETIFADDRS
+
+/* Define to 1 if you have the 'getopt_long' function. */
+#undef HAVE_GETOPT_LONG
+
+/* Define to 1 if you have the 'getprogname' function. */
+#undef HAVE_GETPROGNAME
+
+/* Define to 1 if you have the 'getprpwnam' function. (SecureWare-style shadow
+ passwords). */
+#undef HAVE_GETPRPWNAM
+
+/* Define to 1 if you have the 'getpwnam_shadow' function. */
+#undef HAVE_GETPWNAM_SHADOW
+
+/* Define to 1 if you have the 'getresuid' function. */
+#undef HAVE_GETRESUID
+
+/* Define to 1 if you have the 'getspnam' function (SVR4-style shadow
+ passwords). */
+#undef HAVE_GETSPNAM
+
+/* Define to 1 if you have the 'getttyent' function. */
+#undef HAVE_GETTTYENT
+
+/* Define to 1 if you have the 'getuserattr' function. */
+#undef HAVE_GETUSERATTR
+
+/* Define to 1 if you have the 'getusershell' function. */
+#undef HAVE_GETUSERSHELL
+
+/* Define to 1 if you have the 'getutid' function. */
+#undef HAVE_GETUTID
+
+/* Define to 1 if you have the 'getutsid' function. */
+#undef HAVE_GETUTSID
+
+/* Define to 1 if you have the 'getutxid' function. */
+#undef HAVE_GETUTXID
+
+/* Define to 1 if you have the 'glob' function. */
+#undef HAVE_GLOB
+
+/* Define to 1 if you have the 'gmtime_r' function. */
+#undef HAVE_GMTIME_R
+
+/* Define to 1 if you have the 'grantpt' function. */
+#undef HAVE_GRANTPT
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_H
+
+/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_KRB5_H
+
+/* Define to 1 if you have the <gssapi.h> header file. */
+#undef HAVE_GSSAPI_H
+
+/* Define to 1 if you have the 'gss_krb5_ccache_name' function. */
+#undef HAVE_GSS_KRB5_CCACHE_NAME
+
+/* Define to 1 if your Kerberos is Heimdal. */
+#undef HAVE_HEIMDAL
+
+/* Define to 1 if you have the 'inet_ntop' function. */
+#undef HAVE_INET_NTOP
+
+/* Define to 1 if you have the 'inet_pton' function. */
+#undef HAVE_INET_PTON
+
+/* Define to 1 if you have the 'initprivs' function. */
+#undef HAVE_INITPRIVS
+
+/* Define to 1 if you have the 'innetgr' function. */
+#undef HAVE_INNETGR
+
+/* Define to 1 if the system has the type 'intmax_t'. */
+#undef HAVE_INTMAX_T
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define if you have isblank(3). */
+#undef HAVE_ISBLANK
+
+/* Define to 1 if you have the 'iscomsec' function. (HP-UX >= 10.x check for
+ shadow enabled). */
+#undef HAVE_ISCOMSEC
+
+/* Define to 1 if you use Kerberos V. */
+#undef HAVE_KERB5
+
+/* Define to 1 if you have the 'killpg' function. */
+#undef HAVE_KILLPG
+
+/* Define to 1 if your system has a NetBSD-style kinfo_proc2 struct. */
+#undef HAVE_KINFO_PROC2_NETBSD
+
+/* Define to 1 if your system has a 4.4BSD-style kinfo_proc struct. */
+#undef HAVE_KINFO_PROC_44BSD
+
+/* Define to 1 if your system has a Dragonfly-style kinfo_proc struct. */
+#undef HAVE_KINFO_PROC_DFLY
+
+/* Define to 1 if your system has a FreeBSD-style kinfo_proc struct. */
+#undef HAVE_KINFO_PROC_FREEBSD
+
+/* Define to 1 if your system has an OpenBSD-style kinfo_proc struct. */
+#undef HAVE_KINFO_PROC_OPENBSD
+
+/* Define to 1 if you have the 'krb5_get_init_creds_opt_alloc' function. */
+#undef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
+
+/* Define to 1 if your 'krb5_get_init_creds_opt_free' function takes two
+ arguments. */
+#undef HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_TWO_ARGS
+
+/* Define to 1 if you have the 'krb5_init_secure_context' function. */
+#undef HAVE_KRB5_INIT_SECURE_CONTEXT
+
+/* Define to 1 if you have the 'krb5_verify_user' function. */
+#undef HAVE_KRB5_VERIFY_USER
+
+/* Define to 1 if your LDAP needs <lber.h>. (OpenLDAP does not). */
+#undef HAVE_LBER_H
+
+/* Define to 1 if you use LDAP for sudoers. */
+#undef HAVE_LDAP
+
+/* Define to 1 if you have the <ldapssl.h> header file. */
+#undef HAVE_LDAPSSL_H
+
+/* Define to 1 if you have the 'ldapssl_init' function. */
+#undef HAVE_LDAPSSL_INIT
+
+/* Define to 1 if you have the 'ldapssl_set_strength' function. */
+#undef HAVE_LDAPSSL_SET_STRENGTH
+
+/* Define to 1 if you have the 'ldap_create' function. */
+#undef HAVE_LDAP_CREATE
+
+/* Define to 1 if you have the 'ldap_initialize' function. */
+#undef HAVE_LDAP_INITIALIZE
+
+/* Define to 1 if you have the 'ldap_sasl_bind_s' function. */
+#undef HAVE_LDAP_SASL_BIND_S
+
+/* Define to 1 if you have the 'ldap_sasl_interactive_bind_s' function. */
+#undef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
+
+/* Define to 1 if you have the 'ldap_search_ext_s' function. */
+#undef HAVE_LDAP_SEARCH_EXT_S
+
+/* Define to 1 if you have the 'ldap_search_st' function. */
+#undef HAVE_LDAP_SEARCH_ST
+
+/* Define to 1 if you have the 'ldap_ssl_client_init' function. */
+#undef HAVE_LDAP_SSL_CLIENT_INIT
+
+/* Define to 1 if you have the <ldap_ssl.h> header file. */
+#undef HAVE_LDAP_SSL_H
+
+/* Define to 1 if you have the 'ldap_ssl_init' function. */
+#undef HAVE_LDAP_SSL_INIT
+
+/* Define to 1 if you have the 'ldap_start_tls_s' function. */
+#undef HAVE_LDAP_START_TLS_S
+
+/* Define to 1 if you have the 'ldap_start_tls_s_np' function. */
+#undef HAVE_LDAP_START_TLS_S_NP
+
+/* Define to 1 if you have the 'ldap_str2dn' function. */
+#undef HAVE_LDAP_STR2DN
+
+/* Define to 1 if you have the 'ldap_unbind_ext_s' function. */
+#undef HAVE_LDAP_UNBIND_EXT_S
+
+/* Define to 1 if you have the <libintl.h> header file. */
+#undef HAVE_LIBINTL_H
+
+/* Define to 1 if you have the <libproc.h> header file. */
+#undef HAVE_LIBPROC_H
+
+/* Define to 1 if you have the <libutil.h> header file. */
+#undef HAVE_LIBUTIL_H
+
+/* Define to 1 to enable Linux audit support. */
+#undef HAVE_LINUX_AUDIT
+
+/* Define to 1 if you have the <linux/close_range.h> header file. */
+#undef HAVE_LINUX_CLOSE_RANGE_H
+
+/* Define to 1 if you have the <linux/random.h> header file. */
+#undef HAVE_LINUX_RANDOM_H
+
+/* Define to 1 if you have the 'localtime_r' function. */
+#undef HAVE_LOCALTIME_R
+
+/* Define to 1 if you have the 'lockf' function. */
+#undef HAVE_LOCKF
+
+/* Define to 1 if you have the <login_cap.h> header file. */
+#undef HAVE_LOGIN_CAP_H
+
+/* Define to 1 if the system has the type 'long long int'. */
+#undef HAVE_LONG_LONG_INT
+
+/* Define to 1 if you have the <machine/endian.h> header file. */
+#undef HAVE_MACHINE_ENDIAN_H
+
+/* Define to 1 if you have the 'mach_continuous_time' function. */
+#undef HAVE_MACH_CONTINUOUS_TIME
+
+/* Define to 1 if you have the <maillock.h> header file. */
+#undef HAVE_MAILLOCK_H
+
+/* Define to 1 if you have the 'memrchr' function. */
+#undef HAVE_MEMRCHR
+
+/* Define to 1 if you have the 'memset_explicit' function. */
+#undef HAVE_MEMSET_EXPLICIT
+
+/* Define to 1 if you have the 'memset_s' function. */
+#undef HAVE_MEMSET_S
+
+/* Define to 1 if you have the <minix/config.h> header file. */
+#undef HAVE_MINIX_CONFIG_H
+
+/* Define to 1 if you have the 'mkdirat' function. */
+#undef HAVE_MKDIRAT
+
+/* Define to 1 if you have the 'mkdtempat' function. */
+#undef HAVE_MKDTEMPAT
+
+/* Define to 1 if you have the 'mkdtempat_np' function. */
+#undef HAVE_MKDTEMPAT_NP
+
+/* Define to 1 if you have the 'mkostempsat' function. */
+#undef HAVE_MKOSTEMPSAT
+
+/* Define to 1 if you have the 'mkostempsat_np' function. */
+#undef HAVE_MKOSTEMPSAT_NP
+
+/* Define to 1 if you have the <mps/ldap_ssl.h> header file. */
+#undef HAVE_MPS_LDAP_SSL_H
+
+/* Define to 1 if you have the 'nanosleep' function. */
+#undef HAVE_NANOSLEEP
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines 'DIR'. */
+#undef HAVE_NDIR_H
+
+/* Define to 1 if you have the <netgroup.h> header file. */
+#undef HAVE_NETGROUP_H
+
+/* Define to 1 if you have the 'ngettext' function. */
+#undef HAVE_NGETTEXT
+
+/* Define to 1 if you have the 'nl_langinfo' function. */
+#undef HAVE_NL_LANGINFO
+
+/* Define to 1 if you have the <nss_dbdefs.h> header file. */
+#undef HAVE_NSS_DBDEFS_H
+
+/* Define to 1 if you have the 'nss_search' function. */
+#undef HAVE_NSS_SEARCH
+
+/* Define to 1 if you have the 'openat' function. */
+#undef HAVE_OPENAT
+
+/* Define to 1 if you have the 'openpty' function. */
+#undef HAVE_OPENPTY
+
+/* Define to 1 if you are using OpenSSL's TLS and sha2 functions. */
+#undef HAVE_OPENSSL
+
+/* Define to 1 if you use NRL OPIE. */
+#undef HAVE_OPIE
+
+/* Define to 1 if you have the 'optreset' symbol. */
+#undef HAVE_OPTRESET
+
+/* Define to 1 if you use PAM authentication. */
+#undef HAVE_PAM
+
+/* Define to 1 if you have the 'pam_getenvlist' function. */
+#undef HAVE_PAM_GETENVLIST
+
+/* Define to 1 if you use a specific PAM session for sudo -i. */
+#undef HAVE_PAM_LOGIN
+
+/* Define to 1 if you have the <pam/pam_appl.h> header file. */
+#undef HAVE_PAM_PAM_APPL_H
+
+/* Define to 1 if you have the <paths.h> header file. */
+#undef HAVE_PATHS_H
+
+/* Define to 1 if you have the 'pipe2' function. */
+#undef HAVE_PIPE2
+
+/* Define to 1 if you have the 'poll' function. */
+#undef HAVE_POLL
+
+/* Define to 1 if you have the 'posix_openpt' function. */
+#undef HAVE_POSIX_OPENPT
+
+/* Define to 1 if you have the 'posix_spawn' function. */
+#undef HAVE_POSIX_SPAWN
+
+/* Define to 1 if you have the 'posix_spawnp' function. */
+#undef HAVE_POSIX_SPAWNP
+
+/* Define to 1 if you have the 'ppoll' function. */
+#undef HAVE_PPOLL
+
+/* Define to 1 if you have the 'pread' function. */
+#undef HAVE_PREAD
+
+/* Define to 1 if you have the 'pread64' function. */
+#undef HAVE_PREAD64
+
+/* Define to 1 if you have the 'priv_set' function. */
+#undef HAVE_PRIV_SET
+
+/* Define to 1 if you have the 'process_vm_readv' function. */
+#undef HAVE_PROCESS_VM_READV
+
+/* Define to 1 if you have the <procfs.h> header file. */
+#undef HAVE_PROCFS_H
+
+/* Define to 1 if you have the 'proc_pidinfo' function. */
+#undef HAVE_PROC_PIDINFO
+
+/* Define to 1 if you have the <project.h> header file. */
+#undef HAVE_PROJECT_H
+
+/* Define to 1 if you have the 'pselect' function. */
+#undef HAVE_PSELECT
+
+/* Define to 1 if you have the 'pstat_getproc' function. */
+#undef HAVE_PSTAT_GETPROC
+
+/* Define to 1 if you have the 'pthread_atfork' function. */
+#undef HAVE_PTHREAD_ATFORK
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#undef HAVE_PTHREAD_H
+
+/* Define to 1 if you have the <pty.h> header file. */
+#undef HAVE_PTY_H
+
+/* Define to 1 if you have the 'pwrite' function. */
+#undef HAVE_PWRITE
+
+/* Define to 1 if you have the 'pwrite64' function. */
+#undef HAVE_PWRITE64
+
+/* Define to 1 if you have the 'pw_dup' function. */
+#undef HAVE_PW_DUP
+
+/* Define to 1 if you have the 'reallocarray' function. */
+#undef HAVE_REALLOCARRAY
+
+/* Define to 1 if you have the 'realpath' function. */
+#undef HAVE_REALPATH
+
+/* Define to 1 if you have the 'renameat' function. */
+#undef HAVE_RENAMEAT
+
+/* Define to 1 if you have the 'revoke' function. */
+#undef HAVE_REVOKE
+
+/* Define to 1 if the skeychallenge() function is RFC1938-compliant and takes
+ 4 arguments. */
+#undef HAVE_RFC1938_SKEYCHALLENGE
+
+/* Define to 1 if you have the <sasl.h> header file. */
+#undef HAVE_SASL_H
+
+/* Define to 1 if you have the <sasl/sasl.h> header file. */
+#undef HAVE_SASL_SASL_H
+
+/* Define to 1 if you use SecurID for authentication. */
+#undef HAVE_SECURID
+
+/* Define to 1 if you have the <security/pam_appl.h> header file. */
+#undef HAVE_SECURITY_PAM_APPL_H
+
+/* Define to 1 to enable SELinux RBAC support. */
+#undef HAVE_SELINUX
+
+/* Define to 1 if you have the 'setauthdb' function. */
+#undef HAVE_SETAUTHDB
+
+/* Define to 1 if you have the 'seteuid' function. */
+#undef HAVE_SETEUID
+
+/* Define to 1 if you have the 'setgroupent' function. */
+#undef HAVE_SETGROUPENT
+
+/* Define to 1 if you have the 'setkeycreatecon' function. */
+#undef HAVE_SETKEYCREATECON
+
+/* Define to 1 if you have the 'setpassent' function. */
+#undef HAVE_SETPASSENT
+
+/* Define to 1 if you have the 'setprogname' function. */
+#undef HAVE_SETPROGNAME
+
+/* Define to 1 if you have the 'setresuid' function. */
+#undef HAVE_SETRESUID
+
+/* Define to 1 if you have the 'setreuid' function. */
+#undef HAVE_SETREUID
+
+/* Define to 1 if you have the 'setrlimit64' function. */
+#undef HAVE_SETRLIMIT64
+
+/* Define to 1 if you have the 'set_auth_parameters' function. */
+#undef HAVE_SET_AUTH_PARAMETERS
+
+/* Define to 1 if you have the 'SHA224Update' function. */
+#undef HAVE_SHA224UPDATE
+
+/* Define to 1 if you have the 'shl_load' function. */
+#undef HAVE_SHL_LOAD
+
+/* Define to 1 if you have the 'sia_ses_init' function. */
+#undef HAVE_SIA_SES_INIT
+
+/* Define to 1 if you have the 'sig2str' function. */
+#undef HAVE_SIG2STR
+
+/* Define to 1 if you have the 'sigabbrev_np' function. */
+#undef HAVE_SIGABBREV_NP
+
+/* Define to 1 if the system has the type 'sig_atomic_t'. */
+#undef HAVE_SIG_ATOMIC_T
+
+/* Define to 1 if you use S/Key. */
+#undef HAVE_SKEY
+
+/* Define to 1 if your S/Key library has skeyaccess(). */
+#undef HAVE_SKEYACCESS
+
+/* Define to 1 if you have the 'snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if the system has the type 'socklen_t'. */
+#undef HAVE_SOCKLEN_T
+
+/* Define to 1 to enable Solaris audit support. */
+#undef HAVE_SOLARIS_AUDIT
+
+/* Define to 1 if you have the <spawn.h> header file. */
+#undef HAVE_SPAWN_H
+
+/* Define to 1 if you have the 'SSL_CTX_get0_certificate' function. */
+#undef HAVE_SSL_CTX_GET0_CERTIFICATE
+
+/* Define to 1 if you have the 'SSL_CTX_set0_tmp_dh_pkey' function. */
+#undef HAVE_SSL_CTX_SET0_TMP_DH_PKEY
+
+/* Define to 1 if you have the 'SSL_CTX_set_ciphersuites' function or macro.
+ */
+#undef HAVE_SSL_CTX_SET_CIPHERSUITES
+
+/* Define to 1 if you have the 'SSL_CTX_set_min_proto_version' function or
+ macro. */
+#undef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
+
+/* Define to 1 if you have the 'SSL_read_ex' function. */
+#undef HAVE_SSL_READ_EX
+
+/* Define to 1 to enable SSSD support. */
+#undef HAVE_SSSD
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the 'str2sig' function. */
+#undef HAVE_STR2SIG
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the 'strlcat' function. */
+#undef HAVE_STRLCAT
+
+/* Define to 1 if you have the 'strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define to 1 if you have the 'strndup' function. */
+#undef HAVE_STRNDUP
+
+/* Define to 1 if you have the 'strnlen' function. */
+#undef HAVE_STRNLEN
+
+/* Define to 1 if you have the 'strsignal' function. */
+#undef HAVE_STRSIGNAL
+
+/* Define to 1 if you have the 'strtoull' function. */
+#undef HAVE_STRTOULL
+
+/* Define to 1 if 'd_namlen' is a member of 'struct dirent'. */
+#undef HAVE_STRUCT_DIRENT_D_NAMLEN
+
+/* Define to 1 if 'd_type' is a member of 'struct dirent'. */
+#undef HAVE_STRUCT_DIRENT_D_TYPE
+
+/* Define to 1 if the system has the type 'struct in6_addr'. */
+#undef HAVE_STRUCT_IN6_ADDR
+
+/* Define to 1 if 'pr_ttydev' is a member of 'struct psinfo'. */
+#undef HAVE_STRUCT_PSINFO_PR_TTYDEV
+
+/* Define if your struct sockaddr_in has a sin_len field. */
+#undef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+
+/* Define if your struct sockaddr has an sa_len field. */
+#undef HAVE_STRUCT_SOCKADDR_SA_LEN
+
+/* Define to 1 if 'tm_gmtoff' is a member of 'struct tm'. */
+#undef HAVE_STRUCT_TM_TM_GMTOFF
+
+/* Define to 1 if 'ut_exit' is a member of 'struct utmp'. */
+#undef HAVE_STRUCT_UTMP_UT_EXIT
+
+/* Define to 1 if 'ut_exit.e_termination' is a member of 'struct utmp'. */
+#undef HAVE_STRUCT_UTMP_UT_EXIT_E_TERMINATION
+
+/* Define to 1 if 'ut_exit.__e_termination' is a member of 'struct utmp'. */
+#undef HAVE_STRUCT_UTMP_UT_EXIT___E_TERMINATION
+
+/* Define to 1 if 'ut_id' is a member of 'struct utmp'. */
+#undef HAVE_STRUCT_UTMP_UT_ID
+
+/* Define to 1 if 'ut_pid' is a member of 'struct utmp'. */
+#undef HAVE_STRUCT_UTMP_UT_PID
+
+/* Define to 1 if 'ut_tv' is a member of 'struct utmp'. */
+#undef HAVE_STRUCT_UTMP_UT_TV
+
+/* Define to 1 if 'ut_type' is a member of 'struct utmp'. */
+#undef HAVE_STRUCT_UTMP_UT_TYPE
+
+/* Define to 1 if 'ut_user' is a member of 'struct utmp'. */
+#undef HAVE_STRUCT_UTMP_UT_USER
+
+/* Define to 1 if your struct stat has an st_mtim member. */
+#undef HAVE_ST_MTIM
+
+/* Define to 1 if your struct stat has an st_mtimespec member. */
+#undef HAVE_ST_MTIMESPEC
+
+/* Define to 1 if your struct stat has an st_nmtime member. */
+#undef HAVE_ST_NMTIME
+
+/* Define to 1 if your struct stat uses an st__tim union. */
+#undef HAVE_ST__TIM
+
+/* Define to 1 if you have the 'sysctl' function. */
+#undef HAVE_SYSCTL
+
+/* Define to 1 if you have the 'sysinfo' function. */
+#undef HAVE_SYSINFO
+
+/* Define to 1 if you have the <sys/bsdtypes.h> header file. */
+#undef HAVE_SYS_BSDTYPES_H
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines 'DIR'.
+ */
+#undef HAVE_SYS_DIR_H
+
+/* Define to 1 if you have the <sys/endian.h> header file. */
+#undef HAVE_SYS_ENDIAN_H
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines 'DIR'.
+ */
+#undef HAVE_SYS_NDIR_H
+
+/* Define to 1 if you have the <sys/procfs.h> header file. */
+#undef HAVE_SYS_PROCFS_H
+
+/* Define to 1 if you have the <sys/random.h> header file. */
+#undef HAVE_SYS_RANDOM_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if your libc has the 'sys_sigabbrev' symbol. */
+#undef HAVE_SYS_SIGABBREV
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#undef HAVE_SYS_SOCKIO_H
+
+/* Define to 1 if you have the <sys/statvfs.h> header file. */
+#undef HAVE_SYS_STATVFS_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/stropts.h> header file. */
+#undef HAVE_SYS_STROPTS_H
+
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+#undef HAVE_SYS_SYSCALL_H
+
+/* Define to 1 if you have the <sys/sysctl.h> header file. */
+#undef HAVE_SYS_SYSCTL_H
+
+/* Define to 1 if you have the <sys/sysmacros.h> header file. */
+#undef HAVE_SYS_SYSMACROS_H
+
+/* Define to 1 if you have the <sys/systeminfo.h> header file. */
+#undef HAVE_SYS_SYSTEMINFO_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the 'timegm' function. */
+#undef HAVE_TIMEGM
+
+/* Define to 1 if you have the 'TLS_method' function. */
+#undef HAVE_TLS_METHOD
+
+/* Define to 1 if you have the 'ttyslot' function. */
+#undef HAVE_TTYSLOT
+
+/* Define to 1 if the system has the type 'uintmax_t'. */
+#undef HAVE_UINTMAX_T
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the 'unlinkat' function. */
+#undef HAVE_UNLINKAT
+
+/* Define to 1 if you have the 'unsetenv' function. */
+#undef HAVE_UNSETENV
+
+/* Define to 1 if the system has the type 'unsigned long long int'. */
+#undef HAVE_UNSIGNED_LONG_LONG_INT
+
+/* Define to 1 if you have the <util.h> header file. */
+#undef HAVE_UTIL_H
+
+/* Define to 1 if you have the 'utimensat' function. */
+#undef HAVE_UTIMENSAT
+
+/* Define to 1 if you have the 'utimes' function. */
+#undef HAVE_UTIMES
+
+/* Define to 1 if you have the <utmps.h> header file. */
+#undef HAVE_UTMPS_H
+
+/* Define to 1 if you have the <utmpx.h> header file. */
+#undef HAVE_UTMPX_H
+
+/* Define to 1 if you have the 'vasprintf' function. */
+#undef HAVE_VASPRINTF
+
+/* Define to 1 if you have the 'va_copy' function. */
+#undef HAVE_VA_COPY
+
+/* Define to 1 if you have the 'vsnprintf' function. */
+#undef HAVE_VSNPRINTF
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#undef HAVE_WCHAR_H
+
+/* Define to 1 if you are using wolfSSL's TLS and sha2 functions. */
+#undef HAVE_WOLFSSL
+
+/* Define to 1 if you have the 'wordexp' function. */
+#undef HAVE_WORDEXP
+
+/* Define to 1 if you have the <wordexp.h> header file. */
+#undef HAVE_WORDEXP_H
+
+/* Define to 1 if you have the 'X509_STORE_CTX_get0_cert' function. */
+#undef HAVE_X509_STORE_CTX_GET0_CERT
+
+/* Define to 1 if you have the <zlib.h> header file. */
+#undef HAVE_ZLIB_H
+
+/* Define to 1 if the system has the type '_Bool'. */
+#undef HAVE__BOOL
+
+/* Define to 1 if you have the '_getpty' function. */
+#undef HAVE__GETPTY
+
+/* Define to 1 if you have the '_innetgr' function. */
+#undef HAVE__INNETGR
+
+/* Define to 1 if you have the '_NSGetEnviron' function. */
+#undef HAVE__NSGETENVIRON
+
+/* Define to 1 if you have the '_nss_initf_group' function. */
+#undef HAVE__NSS_INITF_GROUP
+
+/* Define to 1 if you have the '_nss_XbyY_buf_alloc' function. */
+#undef HAVE__NSS_XBYY_BUF_ALLOC
+
+/* Define to 1 if you have the '_ttyname_dev' function. */
+#undef HAVE__TTYNAME_DEV
+
+/* Define to 1 if you have the '__builtin_clz' built-in function */
+#undef HAVE___BUILTIN_CLZ
+
+/* Define to 1 if you have the '__builtin_clzl' built-in function */
+#undef HAVE___BUILTIN_CLZL
+
+/* Define to 1 if the compiler supports the C99 __func__ variable. */
+#undef HAVE___FUNC__
+
+/* Define to 1 if you have dyld with __interpose attribute support. */
+#undef HAVE___INTERPOSE
+
+/* Define to 1 if you have the '__nss_initf_group' function. */
+#undef HAVE___NSS_INITF_GROUP
+
+/* Define to 1 if you have the '__nss_XbyY_buf_alloc' function. */
+#undef HAVE___NSS_XBYY_BUF_ALLOC
+
+/* Define to 1 if your crt0.o defines the __progname symbol for you. */
+#undef HAVE___PROGNAME
+
+/* Define to 1 if you have the '__va_copy' function. */
+#undef HAVE___VA_COPY
+
+/* Define to 1 if you want the hostname to be entered into the log file. */
+#undef HOST_IN_LOG
+
+/* Define to 1 if you want to ignore '.' and empty PATH elements. */
+#undef IGNORE_DOT_PATH
+
+/* The message given when a bad password is entered. */
+#undef INCORRECT_PASSWORD
+
+/* Define to (int) if the 'ioctl' function request takes an int request
+ argument. */
+#undef IOCTL_REQ_CAST
+
+/* The syslog facility sudo will use. */
+#undef LOGFAC
+
+/* Define to SLOG_SYSLOG, SLOG_FILE, or SLOG_BOTH. */
+#undef LOGGING
+
+/* Define to 1 if you want a two line OTP (S/Key or OPIE) prompt. */
+#undef LONG_OTP_PROMPT
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#undef LT_OBJDIR
+
+/* The subject of the mail sent by sudo to the MAILTO user/address. */
+#undef MAILSUBJECT
+
+/* The user or email address that sudo mail is sent to. */
+#undef MAILTO
+
+/* Define to 1 if 'major', 'minor', and 'makedev' are declared in <mkdev.h>.
+ */
+#undef MAJOR_IN_MKDEV
+
+/* Define to 1 if 'major', 'minor', and 'makedev' are declared in
+ <sysmacros.h>. */
+#undef MAJOR_IN_SYSMACROS
+
+/* The max number of chars per log file line (for line wrapping). */
+#undef MAXLOGFILELEN
+
+/* Define to 1 if resolv.h must be included to get the 'inet_ntop' or
+ 'inet_pton' function prototypes. */
+#undef NEED_RESOLV_H
+
+/* Define to 1 if you don't want sudo to prompt for a password by default. */
+#undef NO_AUTHENTICATION
+
+/* Define to 1 if you want sudo to free up memory before exiting. */
+#undef NO_LEAKS
+
+/* Define to 1 if you don't want users to get the lecture the first time they
+ use sudo. */
+#undef NO_LECTURE
+
+/* Define to 1 if you don't want to use sudo's PAM session support. */
+#undef NO_PAM_SESSION
+
+/* Define to avoid running the mailer as root. */
+#undef NO_ROOT_MAILER
+
+/* Define to 1 if root should not be allowed to use sudo. */
+#undef NO_ROOT_SUDO
+
+/* Define if your C preprocessor does not support variadic macros. */
+#undef NO_VARIADIC_MACROS
+
+/* Define to 1 to include offensive insults from the classic version of sudo.
+ */
+#undef OFFENSIVE_INSULTS
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if your system uses a Solaris-derived PAM and not Linux-PAM or
+ OpenPAM. */
+#undef PAM_SUN_CODEBASE
+
+/* The default password prompt. */
+#undef PASSPROMPT
+
+/* The passwd prompt timeout (in minutes). */
+#undef PASSWORD_TIMEOUT
+
+/* Enable replacement (v)snprintf if system (v)snprintf is broken. */
+#undef PREFER_PORTABLE_SNPRINTF
+
+/* The syslog priority sudo will use for unsuccessful attempts/errors. */
+#undef PRI_FAILURE
+
+/* The syslog priority sudo will use for successful attempts. */
+#undef PRI_SUCCESS
+
+/* Define to const if the 'putenv' function takes a const argument. */
+#undef PUTENV_CONST
+
+/* Define to 1 if you want insults from "Monty Python's Flying Circus". */
+#undef PYTHON_INSULTS
+
+/* The default value of preloaded objects (if any). */
+#undef RTLD_PRELOAD_DEFAULT
+
+/* The delimiter to use when defining multiple preloaded objects. */
+#undef RTLD_PRELOAD_DELIM
+
+/* An extra environment variable that is required to enable preloading (if
+ any). */
+#undef RTLD_PRELOAD_ENABLE_VAR
+
+/* The environment variable that controls preloading of dynamic objects. */
+#undef RTLD_PRELOAD_VAR
+
+/* The environment variable that controls preloading of 32-bit dynamic
+ objects. */
+#undef RTLD_PRELOAD_VAR_32
+
+/* The environment variable that controls preloading of 64-bit dynamic
+ objects. */
+#undef RTLD_PRELOAD_VAR_64
+
+/* The user sudo should run commands as by default. */
+#undef RUNAS_DEFAULT
+
+/* A colon-separated list of directories to override the user's PATH with. */
+#undef SECURE_PATH
+
+/* Define to 1 to send mail when the user is not allowed to run a command. */
+#undef SEND_MAIL_WHEN_NOT_OK
+
+/* Define to 1 to send mail when the user is not allowed to run sudo on this
+ host. */
+#undef SEND_MAIL_WHEN_NO_HOST
+
+/* Define to 1 to send mail when the user is not in the sudoers file. */
+#undef SEND_MAIL_WHEN_NO_USER
+
+/* Define to 1 if the sha2 functions use 'const void *' instead of 'const
+ unsigned char'. */
+#undef SHA2_VOID_PTR
+
+/* Define to 1 if you want sudo to start a shell if given no arguments. */
+#undef SHELL_IF_NO_ARGS
+
+/* Define to 1 if you want sudo to set $HOME in shell mode. */
+#undef SHELL_SETS_HOME
+
+/* The size of 'id_t', as computed by sizeof. */
+#undef SIZEOF_ID_T
+
+/* The size of 'long', as computed by sizeof. */
+#undef SIZEOF_LONG
+
+/* The size of 'long long', as computed by sizeof. */
+#undef SIZEOF_LONG_LONG
+
+/* The size of 'time_t', as computed by sizeof. */
+#undef SIZEOF_TIME_T
+
+/* The size of 'uid_t', as computed by sizeof. */
+#undef SIZEOF_UID_T
+
+/* Define to 1 to compile the sudoers plugin statically into the sudo binary.
+ */
+#undef STATIC_SUDOERS_PLUGIN
+
+/* Define to 1 if all of the C89 standard headers exist (not just the ones
+ required in a freestanding environment). This macro is provided for
+ backward compatibility; new code need not use it. */
+#undef STDC_HEADERS
+
+/* Define to 1 if the code in interfaces.c does not compile for you. */
+#undef STUB_LOAD_INTERFACES
+
+/* Define to 1 to compile support for sudo_logsrvd in the sudoers plugin. */
+#undef SUDOERS_LOG_CLIENT
+
+/* An instance string to append to the username (separated by a slash) for
+ Kerberos V authentication. */
+#undef SUDO_KRB5_INSTANCE
+
+/* The umask that the sudo-run prog should use. */
+#undef SUDO_UMASK
+
+/* The number of minutes before sudo asks for a password again. */
+#undef TIMEOUT
+
+/* Define to global, ppid or tty to set the default timestamp record type. */
+#undef TIMESTAMP_TYPE
+
+/* The number of tries a user gets to enter their password. */
+#undef TRIES_FOR_PASSWORD
+
+/* Define to 1 to use the umask specified in sudoers even when it is less
+ restrictive than the invoking user's. */
+#undef UMASK_OVERRIDE
+
+/* Define to 1 if the 'unsetenv' function returns void instead of 'int'. */
+#undef UNSETENV_VOID
+
+/* Define to 1 if you want to insult the user for entering an incorrect
+ password. */
+#undef USE_INSULTS
+
+/* Define to 1 if you use GNU stow packaging. */
+#undef USE_STOW
+
+/* Enable extensions on AIX, Interix, z/OS. */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable general extensions on macOS. */
+#ifndef _DARWIN_C_SOURCE
+# undef _DARWIN_C_SOURCE
+#endif
+/* Enable general extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable X/Open compliant socket functions that do not require linking
+ with -lxnet on HP-UX 11.11. */
+#ifndef _HPUX_ALT_XOPEN_SOCKET_API
+# undef _HPUX_ALT_XOPEN_SOCKET_API
+#endif
+/* Identify the host operating system as Minix.
+ This macro does not affect the system headers' behavior.
+ A future release of Autoconf may stop defining this macro. */
+#ifndef _MINIX
+# undef _MINIX
+#endif
+/* Enable general extensions on NetBSD.
+ Enable NetBSD compatibility extensions on Minix. */
+#ifndef _NETBSD_SOURCE
+# undef _NETBSD_SOURCE
+#endif
+/* Enable OpenBSD compatibility extensions on NetBSD.
+ Oddly enough, this does nothing on OpenBSD. */
+#ifndef _OPENBSD_SOURCE
+# undef _OPENBSD_SOURCE
+#endif
+/* Define to 1 if needed for POSIX-compatible behavior. */
+#ifndef _POSIX_SOURCE
+# undef _POSIX_SOURCE
+#endif
+/* Define to 2 if needed for POSIX-compatible behavior. */
+#ifndef _POSIX_1_SOURCE
+# undef _POSIX_1_SOURCE
+#endif
+/* Enable POSIX-compatible threading on Solaris. */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */
+#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
+# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
+#endif
+/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */
+#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
+# undef __STDC_WANT_IEC_60559_BFP_EXT__
+#endif
+/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */
+#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
+# undef __STDC_WANT_IEC_60559_DFP_EXT__
+#endif
+/* Enable extensions specified by C23 Annex F. */
+#ifndef __STDC_WANT_IEC_60559_EXT__
+# undef __STDC_WANT_IEC_60559_EXT__
+#endif
+/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
+#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
+# undef __STDC_WANT_IEC_60559_FUNCS_EXT__
+#endif
+/* Enable extensions specified by C23 Annex H and ISO/IEC TS 18661-3:2015. */
+#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
+# undef __STDC_WANT_IEC_60559_TYPES_EXT__
+#endif
+/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */
+#ifndef __STDC_WANT_LIB_EXT2__
+# undef __STDC_WANT_LIB_EXT2__
+#endif
+/* Enable extensions specified by ISO/IEC 24747:2009. */
+#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
+# undef __STDC_WANT_MATH_SPEC_FUNCS__
+#endif
+/* Enable extensions on HP NonStop. */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable X/Open extensions. Define to 500 only if necessary
+ to make mbstate_t available. */
+#ifndef _XOPEN_SOURCE
+# undef _XOPEN_SOURCE
+#endif
+
+
+/* Define to avoid using the passwd/shadow file for authentication. */
+#undef WITHOUT_PASSWD
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define to 1 if necessary to make fseeko visible. */
+#undef _LARGEFILE_SOURCE
+
+/* Define to 1 on platforms where this makes off_t a 64-bit type. */
+#undef _LARGE_FILES
+
+/* Number of bits in time_t, on hosts where this is settable. */
+#undef _TIME_BITS
+
+/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+#undef _UINT32_T
+
+/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+#undef _UINT64_T
+
+/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+#undef _UINT8_T
+
+/* Define to 1 on platforms where this makes time_t a 64-bit type. */
+#undef __MINGW_USE_VC2005_COMPAT
+
+/* Define to __FUNCTION__ if your compiler supports __FUNCTION__ but not
+ __func__ */
+#undef __func__
+
+/* Define to empty if 'const' does not conform to ANSI C. */
+#undef const
+
+/* Define as 'int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define to '__inline__' or '__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to the type of a signed integer type of width exactly 16 bits if
+ such a type exists and the standard includes do not define it. */
+#undef int16_t
+
+/* Define to the type of a signed integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+#undef int32_t
+
+/* Define to the type of a signed integer type of width exactly 64 bits if
+ such a type exists and the standard includes do not define it. */
+#undef int64_t
+
+/* Define to the type of a signed integer type of width exactly 8 bits if such
+ a type exists and the standard includes do not define it. */
+#undef int8_t
+
+/* Define to the widest signed integer type if <stdint.h> and <inttypes.h> do
+ not define. */
+#undef intmax_t
+
+/* Define to an OS-specific initialization function or 'os_init_common'. */
+#undef os_init
+
+/* Define to the equivalent of the C99 'restrict' keyword, or to
+ nothing if this is not supported. Do not define if restrict is
+ supported only directly. */
+#undef restrict
+/* Work around a bug in older versions of Sun C++, which did not
+ #define __restrict__ or support _Restrict or __restrict__
+ even though the corresponding Sun C compiler ended up with
+ "#define restrict _Restrict" or "#define restrict __restrict__"
+ in the previous line. This workaround can be removed once
+ we assume Oracle Developer Studio 12.5 (2016) or later. */
+#if defined __SUNPRO_CC && !defined __RESTRICT && !defined __restrict__
+# define _Restrict
+# define __restrict__
+#endif
+
+/* Define as 'int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+/* Define to the type of an unsigned integer type of width exactly 16 bits if
+ such a type exists and the standard includes do not define it. */
+#undef uint16_t
+
+/* Define to the type of an unsigned integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+#undef uint32_t
+
+/* Define to the type of an unsigned integer type of width exactly 64 bits if
+ such a type exists and the standard includes do not define it. */
+#undef uint64_t
+
+/* Define to the type of an unsigned integer type of width exactly 8 bits if
+ such a type exists and the standard includes do not define it. */
+#undef uint8_t
+
+/* Define to the widest unsigned integer type if <stdint.h> and <inttypes.h>
+ do not define. */
+#undef uintmax_t
+
+/* Define to empty if the keyword 'volatile' does not work. Warning: valid
+ code using 'volatile' can become incorrect without. Disable with care. */
+#undef volatile
+
+#ifndef HAVE_SIG_ATOMIC_T
+typedef int sig_atomic_t;
+#endif
+
+#ifndef HAVE_SOCKLEN_T
+typedef unsigned int socklen_t;
+#endif
+
+#ifndef __GNUC_PREREQ__
+# ifdef __GNUC__
+# define __GNUC_PREREQ__(ma, mi) \
+ ((__GNUC__ > (ma)) || (__GNUC__ == (ma) && __GNUC_MINOR__ >= (mi)))
+# else
+# define __GNUC_PREREQ__(ma, mi) 0
+# endif
+#endif
+
+/* Define away __attribute__ for non-gcc or old gcc. */
+#if !defined(__attribute__) && !__GNUC_PREREQ__(2, 5)
+# define __attribute__(x)
+#endif
+
+/* For functions that call exit() directly. */
+#ifdef __has_c_attribute
+# if __has_c_attribute(__noreturn__)
+# define sudo_noreturn [[__noreturn__]]
+# endif
+#endif
+#ifndef sudo_noreturn
+# if __GNUC_PREREQ__(2, 5)
+# define sudo_noreturn __attribute__((__noreturn__))
+# else
+# define sudo_noreturn
+# endif
+#endif
+
+/* For malloc-like functions that return uninitialized or zeroed memory. */
+#if __GNUC_PREREQ__(2, 96)
+# define sudo_malloclike __attribute__((__malloc__))
+#else
+# define sudo_malloclike
+#endif
+
+/* Compile-time checking for function arguments that must not be NULL. */
+#if __GNUC_PREREQ__(3, 3)
+# define sudo_attr_nonnull(_a) __attribute__((__nonnull__ (_a)))
+#else
+# define sudo_attr_nonnull(_a)
+#endif
+
+/* For catching format string mismatches. */
+#if __GNUC_PREREQ__(2, 7)
+# define sudo_printflike(_f, _v) __attribute__((__format__ (__printf__, _f, _v))) sudo_attr_nonnull(_f)
+# define sudo_printf0like(_f, _v) __attribute__((__format__ (__printf__, _f, _v)))
+# define sudo_attr_fmt_arg(_f) __attribute__((__format_arg__ (_f)))
+#else
+# define sudo_printflike(_f, _v)
+# define sudo_printf0like(_f, _v)
+# define sudo_attr_fmt_arg(_f)
+#endif
+
+/* C23 defines a fallthrough attribute, gcc 7.0 and clang 10 have their own. */
+#ifdef __has_c_attribute
+# if __has_c_attribute(__fallthrough__)
+# define FALLTHROUGH [[__fallthrough__]]
+# endif
+#endif
+#ifndef FALLTHROUGH
+# if defined(HAVE_FALLTHROUGH_ATTRIBUTE)
+# define FALLTHROUGH __attribute__((__fallthrough__))
+# else
+# define FALLTHROUGH do { } while (0)
+# endif
+#endif
+
+/* Symbol visibility controls. */
+#ifdef HAVE_DSO_VISIBILITY
+# if defined(__GNUC__)
+# define sudo_dso_public __attribute__((__visibility__("default")))
+# elif defined(__SUNPRO_C)
+# define sudo_dso_public __global
+# else
+# define sudo_dso_public __declspec(dllexport)
+# endif
+#else
+# define sudo_dso_public
+#endif
+
+/* BSD compatibility on some SVR4 systems. */
+#ifdef __svr4__
+# define BSD_COMP
+#endif
+
+/* Enable BSD extensions on systems that have them. */
+#ifndef _BSD_SOURCE
+# undef _BSD_SOURCE
+#endif
+
+/* Enable OpenBSD extensions on NetBSD. */
+#ifndef _OPENBSD_SOURCE
+# undef _OPENBSD_SOURCE
+#endif
+
+/* Enable BSD types on IRIX. */
+#ifndef _BSD_TYPES
+# undef _BSD_TYPES
+#endif
+
+/* Enable Linux-compatible extensions on AIX. */
+#ifndef _LINUX_SOURCE_COMPAT
+# undef _LINUX_SOURCE_COMPAT
+#endif
+
+/* Enable unlimited getgroups(2) support on macOS. */
+#ifndef _DARWIN_UNLIMITED_GETGROUPS
+# undef _DARWIN_UNLIMITED_GETGROUPS
+#endif
+
+/* Enable prototypes in GCC fixed includes on older systems. */
+#ifndef __USE_FIXED_PROTOTYPES__
+# undef __USE_FIXED_PROTOTYPES__
+#endif
+
+/* Enable XPG4v2 extensions to POSIX, needed for MSG_WAITALL on older HP-UX. */
+#ifndef _XOPEN_SOURCE_EXTENDED
+# undef _XOPEN_SOURCE_EXTENDED
+#endif
+
+/* Enable reentrant versions of the standard C API (obsolete). */
+#ifndef _REENTRANT
+# undef _REENTRANT
+#endif
+
+/* Enable "safer" versions of the standard C API (ISO C11). */
+#ifndef __STDC_WANT_LIB_EXT1__
+# undef __STDC_WANT_LIB_EXT1__
+#endif
+
+/* Prevent static analyzers from genering bogus memory leak warnings. */
+#if defined(__COVERITY__) && !defined(NO_LEAKS)
+# define NO_LEAKS
+#endif
+
+#endif /* SUDO_CONFIG_H */
diff --git a/configure b/configure
new file mode 100755
index 0000000..d01f428
--- /dev/null
+++ b/configure
@@ -0,0 +1,38690 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.72c for sudo 1.9.15p5.
+#
+# Report bugs to <https://bugzilla.sudo.ws/>.
+#
+#
+# Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation,
+# Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else case e in #(
+ e) case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac ;;
+esac
+fi
+
+
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
+as_nl='
+'
+export as_nl
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
+
+# The user is always right.
+if ${PATH_SEPARATOR+false} :; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as 'sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed 'exec'.
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else case e in #(
+ e) case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" )
+then :
+
+else case e in #(
+ e) exitcode=1; echo positional parameters were not saved. ;;
+esac
+fi
+test x\$exitcode = x0 || exit 1
+blah=\$(echo \$(echo blah))
+test x\"\$blah\" = xblah || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+
+ test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
+ ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+ ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+ PATH=/empty FPATH=/empty; export PATH FPATH
+ test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
+ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null
+then :
+ as_have_required=yes
+else case e in #(
+ e) as_have_required=no ;;
+esac
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
+then :
+
+else case e in #(
+ e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
+then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else case e in #(
+ e) if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi ;;
+esac
+fi
+
+
+ if test "x$CONFIG_SHELL" != x
+then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed 'exec'.
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno
+then :
+ printf "%s\n" "$0: This script requires a shell more modern than all"
+ printf "%s\n" "$0: the shells that I found on your system."
+ if test ${ZSH_VERSION+y} ; then
+ printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and
+$0: https://bugzilla.sudo.ws/ about your system, including
+$0: any error possibly output before this message. Then
+$0: install a modern shell, or manually run the script
+$0: under such a shell if you do have one."
+ fi
+ exit 1
+fi ;;
+esac
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else case e in #(
+ e) as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ } ;;
+esac
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else case e in #(
+ e) as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ } ;;
+esac
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ printf "%s\n" "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ t clear
+ :clear
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.
+ # In both cases, we have to default to 'cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated
+
+# Sed expression to map a string onto a valid variable name.
+as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+as_tr_sh="eval sed '$as_sed_sh'" # deprecated
+
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='sudo'
+PACKAGE_TARNAME='sudo'
+PACKAGE_VERSION='1.9.15p5'
+PACKAGE_STRING='sudo 1.9.15p5'
+PACKAGE_BUGREPORT='https://bugzilla.sudo.ws/'
+PACKAGE_URL=''
+
+ac_unique_file="src/sudo.c"
+ac_config_libobj_dir=lib/util
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stddef.h>
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
+#endif
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_header_c_list=
+ac_func_c_list=
+ac_c_werror_flag=
+enable_year2038=yes
+ac_subst_vars='LTLIBOBJS
+KRB5CONFIG
+LIBOBJS
+PYTHON_CONFIG
+PYTHON_LIBS
+PYTHON_INCLUDE
+pkgpyexecdir
+pyexecdir
+pkgpythondir
+pythondir
+PYTHON_PLATFORM
+PYTHON_EXEC_PREFIX
+PYTHON_PREFIX
+PYTHON_VERSION
+PYTHON
+FLEX
+YFLAGS
+YACC
+TRPROG
+UNAMEPROG
+SHA1SUM
+LT_SYS_LIBRARY_PATH
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+MANIFEST_TOOL
+AWK
+STRIP
+ac_ct_AR
+DLLTOOL
+OBJDUMP
+FILECMD
+LN_S
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+EGREP
+GREP
+SED
+LIBTOOL
+host_os
+host_vendor
+host_cpu
+host
+LDFLAGS_FOR_BUILD
+CPPFLAGS_FOR_BUILD
+CFLAGS_FOR_BUILD
+BUILD_OBJEXT
+BUILD_EXEEXT
+CPP_FOR_BUILD
+ac_ct_CC_FOR_BUILD
+CC_FOR_BUILD
+build_os
+build_vendor
+build_cpu
+build
+RANLIB
+AR
+CPP
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+python_plugin
+sudoers_plugin
+plugindir
+pam_login_service
+pam_session
+editor
+secure_path
+netsvc_conf
+nsswitch_conf
+sssd_lib
+ldap_secret
+ldap_conf
+path_info
+root_sudo
+insults
+timestamp_type
+passwd_tries
+env_reset
+env_editor
+runas_default
+fqdn
+badpass_message
+mailsub
+mailto
+mail_no_perms
+mail_no_host
+mail_no_user
+ignore_dot
+loglen
+badpri
+goodpri
+logfac
+lecture
+long_otp_prompt
+passprompt
+umask_override
+sudo_umask
+password_timeout
+timeout
+vardir
+rundir
+relay_dir
+logpath
+log_dir
+iolog_dir
+sudoers_path
+sudo_logsrvd_conf
+sudo_conf
+cvtsudoers_conf
+INTERCEPT_EXP
+FUZZ_LD
+FUZZ_ENGINE
+PPFILES
+LIBLOGSRV
+LOGSRVD_CONF
+LOGSRVD_SRC
+LOGSRV_SRC
+LOGSRV
+SSL_COMPAT_SRC
+PYTHON_PLUGIN_SRC
+PYTHON_PLUGIN
+SIGNAME
+devsearch
+DIGEST
+adminconfdir
+exampledir
+TMPFILES_D
+COMPAT_EXP
+RC_LINK
+INIT_DIR
+INIT_SCRIPT
+HARDENING_CFLAGS
+HARDENING_LDFLAGS
+PIE_CFLAGS
+PIE_LDFLAGS
+ASAN_CFLAGS
+ASAN_LDFLAGS
+CROSS_COMPILING
+SUDOERS_TEST_PROGS
+COMPAT_TEST_PROGS
+LOCALEDIR_SUFFIX
+SUDO_NLS
+LIBPTHREAD
+LIBTLS
+LIBCRYPTO
+LIBINTL
+LIBRT
+LIBDL
+LIBTOOL_DEPS
+ZLIB_SRC
+ZLIB
+LOGINCAP_USAGE
+LDAP
+SELINUX_USAGE
+BSDAUTH_USAGE
+DONT_LEAK_PATH_INFO
+PRELOAD_MODULE
+INSTALL_NOEXEC
+INSTALL_INTERCEPT
+INSTALL_BACKUP
+sesh_file
+noexec_file
+NOEXECDIR
+NOEXECFILE
+intercept_file
+INTERCEPTDIR
+INTERCEPTFILE
+mansectmisc
+mansectform
+mansectsu
+devdir
+AAMAN
+SEMAN
+PSMAN
+LCMAN
+BAMAN
+EXAMPLES
+DEVEL
+SUDOERS_GID
+SUDOERS_UID
+SUDOERS_MODE
+SHLIB_MODE
+SHLIB_ENABLE
+POSTINSTALL
+MANCOMPRESSEXT
+MANCOMPRESS
+MANDIRTYPE
+MANTYPE
+AUTH_OBJS
+GETGROUPS_LIB
+REPLAY_LIBS
+AFS_LIBS
+NET_LIBS
+STATIC_SUDOERS
+SUDOERS_LIBS
+SUDO_LIBS
+SUDO_OBJS
+SUDOERS_OBJS
+SUDOERS_LT_STATIC
+COMMON_OBJS
+LT_DEP_LIBS
+LT_STATIC
+LT_LDEXPORTS
+LT_LDDEP
+LT_LDFLAGS
+ZLIB_LDFLAGS
+LIBUTIL_LDFLAGS
+SUDOERS_LDFLAGS
+SUDO_LDFLAGS
+PROGS
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+runstatedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL
+BSHELLPROG
+MVPROG
+VIPROG
+SENDMAILPROG'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_otp_only
+with_alertmail
+with_pc_insults
+with_devel
+with_CC
+with_rpath
+with_blibpath
+with_bsm_audit
+with_linux_audit
+with_solaris_audit
+with_sssd
+with_sssd_conf
+with_sssd_lib
+with_incpath
+with_libpath
+with_libraries
+with_csops
+with_passwd
+with_skey
+with_opie
+with_long_otp_prompt
+with_SecurID
+with_fwtk
+with_kerb5
+with_aixauth
+with_pam
+with_AFS
+with_DCE
+with_logincap
+with_bsdauth
+with_project
+with_lecture
+with_logging
+with_logfac
+with_goodpri
+with_badpri
+with_logpath
+with_loglen
+with_ignore_dot
+with_mail_if_no_user
+with_mail_if_no_host
+with_mail_if_noperms
+with_mailto
+with_mailsubject
+with_passprompt
+with_badpass_message
+with_fqdn
+with_timedir
+with_rundir
+with_vardir
+with_iologdir
+with_relaydir
+with_tzdir
+with_sendmail
+with_sudoers_mode
+with_sudoers_uid
+with_sudoers_gid
+with_umask
+with_umask_override
+with_runas_default
+with_exempt
+with_editor
+with_env_editor
+with_passwd_tries
+with_timeout
+with_password_timeout
+with_tty_tickets
+with_insults
+with_all_insults
+with_classic_insults
+with_csops_insults
+with_hal_insults
+with_goons_insults
+with_python_insults
+with_nsswitch
+with_ldap
+with_ldap_conf_file
+with_ldap_secret_file
+with_secure_path
+with_interfaces
+with_askpass
+with_exampledir
+with_plugindir
+with_man
+with_mdoc
+enable_authentication
+enable_root_mailer
+enable_setreuid
+enable_setresuid
+enable_shadow
+enable_root_sudo
+enable_log_host
+enable_noargs_shell
+enable_shell_sets_home
+enable_path_info
+enable_env_debug
+enable_postinstall
+enable_zlib
+enable_env_reset
+enable_warnings
+enable_werror
+enable_ssp
+enable_hardening
+enable_pie
+enable_sanitizer
+enable_fuzzer
+enable_fuzzer_engine
+enable_fuzzer_linker
+enable_leaks
+enable_poll
+enable_admin_flag
+enable_nls
+enable_rpath
+enable_static_sudoers
+enable_shared_libutil
+enable_tmpfiles_d
+enable_devsearch
+with_selinux
+with_apparmor
+enable_sasl
+enable_timestamp_type
+enable_offensive_insults
+enable_package_build
+enable_gss_krb5_ccache_name
+enable_pvs_studio
+enable_log_server
+enable_log_client
+enable_openssl
+enable_openssl_pkgconfig_template
+enable_wolfssl
+enable_gcrypt
+enable_python
+enable_adminconf
+enable_shared
+enable_static
+with_pic
+enable_fast_install
+with_aix_soname
+with_gnu_ld
+with_sysroot
+enable_libtool_lock
+with_libtool
+enable_intercept
+with_noexec
+with_netsvc
+enable_sia
+enable_largefile
+with_pam_login
+enable_pam_session
+enable_kerb5_instance
+enable_year2038
+'
+ ac_precious_vars='SENDMAILPROG
+VIPROG
+MVPROG
+BSHELLPROG
+build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+LT_SYS_LIBRARY_PATH
+YACC
+YFLAGS
+PYTHON
+PYTHON_INCLUDE
+PYTHON_LIBS
+PYTHON_CONFIG'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: '$ac_useropt'"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: '$ac_useropt'"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: '$ac_useropt'"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: '$ac_useropt'"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: '$ac_option'
+Try '$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: '$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir runstatedir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: '$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but 'cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+'configure' configures sudo 1.9.15p5 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print 'checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for '--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or '..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, 'make install' will install all the files in
+'$ac_default_prefix/bin', '$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than '$ac_default_prefix' using '--prefix',
+for instance '--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/sudo]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of sudo 1.9.15p5:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --disable-authentication
+ Do not require authentication by default
+ --disable-root-mailer Don't run the mailer as root, run as the user
+ --disable-setreuid Don't try to use the setreuid() function
+ --disable-setresuid Don't try to use the setresuid() function
+ --disable-shadow Never use shadow passwords
+ --disable-root-sudo Don't allow root to run sudo
+ --enable-log-host Log the hostname in the log file
+ --enable-noargs-shell If sudo is given no arguments run a shell
+ --enable-shell-sets-home
+ Set $HOME to target user in shell mode
+ --disable-path-info Print 'command not allowed' not 'command not found'
+ --enable-env-debug Whether to enable environment debugging.
+ --enable-postinstall Script to run after the install phase
+ --enable-zlib[=PATH] Whether to enable or disable zlib
+ --enable-env-reset Whether to enable environment resetting by default.
+ --enable-warnings Whether to enable compiler warnings
+ --enable-werror Whether to enable the -Werror compiler option
+ --disable-ssp Do not compile using the -fstack-protector option.
+ --disable-hardening Do not use compiler/linker exploit mitigation
+ options
+ --enable-pie Build sudo as a position independent executable.
+ --enable-sanitizer Build sudo with sanitizer support.
+ --enable-fuzzer Build sudo with LLVM libFuzzer support.
+ --enable-fuzzer-engine Link fuzz targets with the specified fuzzer engine
+ instead of the default.
+ --enable-fuzzer-linker Use the specified linker when building fuzz targets
+ instead of the default C compiler.
+ --disable-leaks Prevent some harmless memory leaks.
+ --disable-poll Use select() instead of poll().
+ --enable-admin-flag[=PATH]
+ Whether to create a Ubuntu-style admin flag file
+ --disable-nls Disable natural language support using gettext
+ --disable-rpath Disable passing of -Rpath to the linker
+ --enable-static-sudoers Build the sudoers policy module as part of the sudo
+ binary instead as a plugin
+ --disable-shared-libutil
+ Disable use of the libsudo_util shared library.
+ --enable-tmpfiles.d=DIR Set the path to the systemd tmpfiles.d directory.
+ --enable-devsearch=PATH The colon-delimited path to search for device nodes
+ when determining the tty name.
+ --enable-sasl Enable/disable LDAP SASL support
+ --timestamp-type=TYPE Set the default time stamp record type to global,
+ ppid or tty.
+ --enable-offensive-insults
+ Enable potentially offensive sudo insults.
+ --enable-package-build Enable options for package building.
+ --enable-gss-krb5-ccache-name
+ Use GSS-API to set the Kerberos V cred cache name
+ --enable-pvs-studio Create a PVS-Studio.cfg file.
+ --disable-log-server Disable building the sudo_logsrvd log server.
+ --disable-log-client Disable sudoers support for using the sudo_logsrvd
+ log server.
+ --enable-openssl Use OpenSSL's TLS and sha2 functions
+ --enable-openssl-pkgconfig-template
+ A printf format string used to construct the OpenSSL
+ pkg-config name
+ --enable-wolfssl Use wolfSSL's TLS and sha2 functions
+ --enable-gcrypt Use GNU crypt's sha2 functions
+ --enable-python Compile python plugin support
+ --enable-adminconf[=DIR]
+ Use configuration files from adminconfdir in
+ preference to sysconfdir
+ --enable-shared[=PKGS] build shared libraries [default=yes]
+ --enable-static[=PKGS] build static libraries [default=yes]
+ --enable-fast-install[=PKGS]
+ optimize for fast installation [default=yes]
+ --disable-libtool-lock avoid locking (might break parallel builds)
+ --enable-intercept fully qualified pathname of sudo_intercept.so
+ --disable-sia Disable SIA on Digital UNIX
+ --disable-largefile omit support for large files
+ --disable-pam-session Disable PAM session support
+ --enable-kerb5-instance instance string to append to the username (separated
+ by a slash)
+ --disable-year2038 don't support timestamps after 2038
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-otp-only deprecated
+ --with-alertmail deprecated
+ --with-pc-insults deprecated
+ --with-devel add development options
+ --with-CC C compiler to use
+ --with-rpath deprecated, use --disable-rpath
+ --with-blibpath[=PATH] deprecated
+ --with-bsm-audit enable BSM audit support
+ --with-linux-audit enable Linux audit support
+ --with-solaris-audit enable Solaris audit support
+ --with-sssd enable SSSD support
+ --with-sssd-conf path to the SSSD config file
+ --with-sssd-lib path to the SSSD library
+ --with-incpath additional places to look for include files
+ --with-libpath additional places to look for libraries
+ --with-libraries additional libraries to link with
+ --with-csops add CSOps standard options
+ --without-passwd don't use passwd/shadow file for authentication
+ --with-skey[=DIR] enable S/Key support
+ --with-opie[=DIR] enable OPIE support
+ --with-long-otp-prompt use a two line OTP (skey/opie) prompt
+ --with-SecurID[=DIR] enable SecurID support
+ --with-fwtk[=DIR] enable FWTK AuthSRV support
+ --with-kerb5[=DIR] enable Kerberos V support
+ --with-aixauth enable AIX general authentication support
+ --with-pam enable PAM support
+ --with-AFS enable AFS support
+ --with-DCE enable DCE support
+ --with-logincap enable BSD login class support
+ --with-bsdauth enable BSD authentication support
+ --with-project enable Solaris project support
+ --without-lecture don't print lecture for first-time sudoer
+ --with-logging log via syslog, file, or both
+ --with-logfac syslog facility to log with (default is "auth")
+ --with-goodpri syslog priority for commands (def is "notice")
+ --with-badpri syslog priority for failures (def is "alert")
+ --with-logpath path to the sudo log file
+ --with-loglen maximum length of a log file line (default is 80)
+ --with-ignore-dot ignore '.' in the PATH
+ --without-mail-if-no-user
+ do not send mail if user not in sudoers
+ --with-mail-if-no-host send mail if user in sudoers but not for this host
+ --with-mail-if-noperms send mail if user not allowed to run command
+ --with-mailto who should get sudo mail (default is "root")
+ --with-mailsubject subject of sudo mail
+ --with-passprompt default password prompt
+ --with-badpass-message message the user sees when the password is wrong
+ --with-fqdn expect fully qualified hosts in sudoers
+ --with-timedir=DIR deprecated
+ --with-rundir=DIR directory for sudo-specific files that do not
+ survive a system reboot, e.g. '/var/run/sudo'
+ --with-vardir=DIR directory for sudo-specific files that survive a
+ system reboot, e.g. '/var/db/sudo' or
+ '/var/lib/sudo'
+ --with-iologdir=DIR directory to store sudo I/O log files in
+ --with-relaydir=DIR directory to store sudo_logsrvd relay temporary
+ files in
+ --with-tzdir=DIR path to the time zone data directory
+ --with-sendmail set path to sendmail
+ --without-sendmail do not send mail at all
+ --with-sudoers-mode mode of sudoers file (defaults to 0440)
+ --with-sudoers-uid uid that owns sudoers file (defaults to 0)
+ --with-sudoers-gid gid that owns sudoers file (defaults to 0)
+ --with-umask umask with which the prog should run (default is
+ 022)
+ --without-umask Preserves the umask of the user invoking sudo.
+ --with-umask-override Use the umask specified in sudoers even if it is
+ less restrictive than the user's.
+ --with-runas-default User to run commands as (default is "root")
+ --with-exempt=group no passwd needed for users in this group
+ --with-editor=path Default editor for visudo (defaults to vi)
+ --with-env-editor Use the environment variable EDITOR for visudo
+ --with-passwd-tries number of tries to enter password (default is 3)
+ --with-timeout minutes before sudo asks for passwd again (def is 5
+ minutes)
+ --with-password-timeout passwd prompt timeout in minutes (default is 5
+ minutes)
+ --with-tty-tickets use a different ticket file for each tty
+ --with-insults insult the user for entering an incorrect password
+ --with-all-insults include all the sudo insult sets
+ --with-classic-insults include the insults from the "classic" sudo
+ --with-csops-insults include CSOps insults
+ --with-hal-insults include 2001-like insults
+ --with-goons-insults include the insults from the "Goon Show"
+ --with-python-insults include the insults from "Monty Python's Flying
+ Circus"
+ --with-nsswitch[=PATH] path to nsswitch.conf
+ --with-ldap[=DIR] enable LDAP support
+ --with-ldap-conf-file path to LDAP configuration file
+ --with-ldap-secret-file path to LDAP secret password file
+ --with-secure-path override the user's path with a built-in one
+ --without-interfaces don't try to read the ip addr of network interfaces
+ --with-askpass=PATH Fully qualified pathname of askpass helper
+ --with-exampledir=DIR path to install sudo examples in
+ --with-plugindir=DIR set directory to load plugins from
+ --with-man manual pages use man macros
+ --with-mdoc manual pages use mdoc macros
+ --with-selinux enable SELinux support
+ --with-apparmor enable AppArmor support
+ --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use
+ both]
+ --with-aix-soname=aix|svr4|both
+ shared library versioning (aka "SONAME") variant to
+ provide on AIX, [default=aix].
+ --with-gnu-ld assume the C compiler uses GNU ld [default=no]
+ --with-sysroot[=DIR] Search for dependent libraries within DIR (or the
+ compiler's sysroot if not specified).
+ --with-libtool=PATH specify path to libtool
+ --with-noexec[=PATH] fully qualified pathname of sudo_noexec.so
+ --with-netsvc[=PATH] path to netsvc.conf
+ --with-pam-login enable specific PAM session for sudo -i
+
+Some influential environment variables:
+ SENDMAILPROG
+ The fully-qualified path to the sendmail program to use.
+ VIPROG The fully-qualified path to the vi program to use.
+ MVPROG The fully-qualified path to the mv program to use.
+ BSHELLPROG The fully-qualified path to the Bourne shell to use.
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+ LT_SYS_LIBRARY_PATH
+ User-defined run-time library search path.
+ YACC The 'Yet Another Compiler Compiler' implementation to use.
+ Defaults to the first program found out of: 'bison -y', 'byacc',
+ 'yacc'.
+ YFLAGS The list of arguments that will be passed by default to $YACC.
+ This script will default YFLAGS to the empty string to avoid a
+ default value of '-d' given by some make applications.
+ PYTHON the Python interpreter
+ PYTHON_INCLUDE
+ Include flags for python, bypassing python-config
+ PYTHON_LIBS Linker flags for python, bypassing python-config
+ PYTHON_CONFIG
+ Path to python-config
+
+Use these variables to override the choices made by 'configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <https://bugzilla.sudo.ws/>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for configure.gnu first; this name is used for a wrapper for
+ # Metaconfig's "Configure" on case-insensitive file systems.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+sudo configure 1.9.15p5
+generated by GNU Autoconf 2.72c
+
+Copyright (C) 2023 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest.beam
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext
+then :
+ ac_retval=0
+else case e in #(
+ e) printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1 ;;
+esac
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ eval "$3=yes"
+else case e in #(
+ e) eval "$3=no" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }
+then :
+ ac_retval=0
+else case e in #(
+ e) printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1 ;;
+esac
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }
+then :
+ ac_retval=0
+else case e in #(
+ e) printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1 ;;
+esac
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (void); below. */
+
+#include <limits.h>
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 (void);
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main (void)
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ eval "$3=yes"
+else case e in #(
+ e) eval "$3=no" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext ;;
+esac
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) eval "$3=no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main (void)
+{
+if (sizeof ($2))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main (void)
+{
+if (sizeof (($2)))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else case e in #(
+ e) eval "$3=yes" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
+# ac_fn_check_decl LINENO SYMBOL VAR INCLUDES EXTRA-OPTIONS FLAG-VAR
+# ------------------------------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly. Pass EXTRA-OPTIONS to the compiler, using FLAG-VAR.
+ac_fn_check_decl ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ as_decl_name=`echo $2|sed 's/ *(.*//'`
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+printf %s "checking whether $as_decl_name is declared... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+ eval ac_save_FLAGS=\$$6
+ as_fn_append $6 " $5"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main (void)
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+ (void) $as_decl_use;
+#else
+ (void) $as_decl_name;
+#endif
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ eval "$3=yes"
+else case e in #(
+ e) eval "$3=no" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ eval $6=\$ac_save_FLAGS
+ ;;
+esac
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_check_decl
+
+# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
+# ----------------------------------------------------
+# Tries to find if the field MEMBER exists in type AGGR, after including
+# INCLUDES, setting cache variable VAR accordingly.
+ac_fn_c_check_member ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+printf %s "checking for $2.$3... " >&6; }
+if eval test \${$4+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main (void)
+{
+static $2 ac_aggr;
+if (ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ eval "$4=yes"
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main (void)
+{
+static $2 ac_aggr;
+if (sizeof ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ eval "$4=yes"
+else case e in #(
+ e) eval "$4=no" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+eval ac_res=\$$4
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_member
+
+# ac_fn_c_find_intX_t LINENO BITS VAR
+# -----------------------------------
+# Finds a signed integer type with width BITS, setting cache variable VAR
+# accordingly.
+ac_fn_c_find_intX_t ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5
+printf %s "checking for int$2_t... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) eval "$3=no"
+ # Order is important - never check a type that is potentially smaller
+ # than half of the expected target width.
+ for ac_type in int$2_t 'int' 'long int' \
+ 'long long int' 'short int' 'signed char'; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+ enum { N = $2 / 2 - 1 };
+int
+main (void)
+{
+static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+ enum { N = $2 / 2 - 1 };
+int
+main (void)
+{
+static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1)
+ < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else case e in #(
+ e) case $ac_type in #(
+ int$2_t) :
+ eval "$3=yes" ;; #(
+ *) :
+ eval "$3=\$ac_type" ;;
+esac ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ if eval test \"x\$"$3"\" = x"no"
+then :
+
+else case e in #(
+ e) break ;;
+esac
+fi
+ done ;;
+esac
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_find_intX_t
+
+# ac_fn_c_find_uintX_t LINENO BITS VAR
+# ------------------------------------
+# Finds an unsigned integer type with width BITS, setting cache variable VAR
+# accordingly.
+ac_fn_c_find_uintX_t ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5
+printf %s "checking for uint$2_t... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) eval "$3=no"
+ # Order is important - never check a type that is potentially smaller
+ # than half of the expected target width.
+ for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \
+ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main (void)
+{
+static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ case $ac_type in #(
+ uint$2_t) :
+ eval "$3=yes" ;; #(
+ *) :
+ eval "$3=\$ac_type" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ if eval test \"x\$"$3"\" = x"no"
+then :
+
+else case e in #(
+ e) break ;;
+esac
+fi
+ done ;;
+esac
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_find_uintX_t
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
+# executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+then :
+ ac_retval=0
+else case e in #(
+ e) printf "%s\n" "$as_me: program exited with status $ac_status" >&5
+ printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status ;;
+esac
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
+# --------------------------------------------
+# Tries to find the compile-time value of EXPR in a program that includes
+# INCLUDES, setting VAR accordingly. Returns whether the value could be
+# computed
+ac_fn_c_compute_int ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main (void)
+{
+static int test_array [1 - 2 * !(($2) >= 0)];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main (void)
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_hi=$ac_mid; break
+else case e in #(
+ e) as_fn_arith $ac_mid + 1 && ac_lo=$as_val
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ done
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main (void)
+{
+static int test_array [1 - 2 * !(($2) < 0)];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main (void)
+{
+static int test_array [1 - 2 * !(($2) >= $ac_mid)];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_lo=$ac_mid; break
+else case e in #(
+ e) as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ done
+else case e in #(
+ e) ac_lo= ac_hi= ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main (void)
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_hi=$ac_mid
+else case e in #(
+ e) as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+done
+case $ac_lo in #((
+?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
+'') ac_retval=1 ;;
+esac
+ else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+static long int longval (void) { return $2; }
+static unsigned long int ulongval (void) { return $2; }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main (void)
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ return 1;
+ if (($2) < 0)
+ {
+ long int i = longval ();
+ if (i != ($2))
+ return 1;
+ fprintf (f, "%ld", i);
+ }
+ else
+ {
+ unsigned long int i = ulongval ();
+ if (i != ($2))
+ return 1;
+ fprintf (f, "%lu", i);
+ }
+ /* Do not output a trailing newline, as this causes \r\n confusion
+ on some platforms. */
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"
+then :
+ echo >>conftest.val; read $3 <conftest.val; ac_retval=0
+else case e in #(
+ e) ac_retval=1 ;;
+esac
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f conftest.val
+
+ fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_compute_int
+ac_configure_args_raw=
+for ac_arg
+do
+ case $ac_arg in
+ *\'*)
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append ac_configure_args_raw " '$ac_arg'"
+done
+
+case $ac_configure_args_raw in
+ *$as_nl*)
+ ac_safe_unquote= ;;
+ *)
+ ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab.
+ ac_unsafe_a="$ac_unsafe_z#~"
+ ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
+ ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
+esac
+
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by sudo $as_me 1.9.15p5, which was
+generated by GNU Autoconf 2.72c. Invocation command line was
+
+ $ $0$ac_configure_args_raw
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ printf "%s\n" "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Sanitize IFS.
+ IFS=" "" $as_nl"
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ printf "%s\n" "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ printf "%s\n" "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ printf "%s\n" "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ printf "%s\n" "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ printf "%s\n" "$as_me: caught signal $ac_signal"
+ printf "%s\n" "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+printf "%s\n" "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+ ac_site_files="$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+ ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
+else
+ ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+fi
+
+for ac_site_file in $ac_site_files
+do
+ case $ac_site_file in #(
+ */*) :
+ ;; #(
+ *) :
+ ac_site_file=./$ac_site_file ;;
+esac
+ if test -f "$ac_site_file" && test -r "$ac_site_file"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See 'config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
+# Test code for whether the C compiler supports C89 (global declarations)
+ac_c_conftest_c89_globals='
+/* Does the compiler advertise C89 conformance?
+ Do not test the value of __STDC__, because some compilers set it to 0
+ while being otherwise adequately conformant. */
+#if !defined __STDC__
+# error "Compiler does not advertise C89 conformance"
+#endif
+
+#include <stddef.h>
+#include <stdarg.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */
+struct buf { int x; };
+struct buf * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (char **p, int i)
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* C89 style stringification. */
+#define noexpand_stringify(a) #a
+const char *stringified = noexpand_stringify(arbitrary+token=sequence);
+
+/* C89 style token pasting. Exercises some of the corner cases that
+ e.g. old MSVC gets wrong, but not very hard. */
+#define noexpand_concat(a,b) a##b
+#define expand_concat(a,b) noexpand_concat(a,b)
+extern int vA;
+extern int vbee;
+#define aye A
+#define bee B
+int *pvA = &expand_concat(v,aye);
+int *pvbee = &noexpand_concat(v,bee);
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not \xHH hex character constants.
+ These do not provoke an error unfortunately, instead are silently treated
+ as an "x". The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously \x00 != x always comes out true, for an
+ array size at least. It is necessary to write \x00 == 0 to get something
+ that is true only with -std. */
+int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) '\''x'\''
+int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
+ int, int);'
+
+# Test code for whether the C compiler supports C89 (body of main).
+ac_c_conftest_c89_main='
+ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
+'
+
+# Test code for whether the C compiler supports C99 (global declarations)
+ac_c_conftest_c99_globals='
+// Does the compiler advertise C99 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
+# error "Compiler does not advertise C99 conformance"
+#endif
+
+#include <stdbool.h>
+extern int puts (const char *);
+extern int printf (const char *, ...);
+extern int dprintf (int, const char *, ...);
+extern void *malloc (size_t);
+extern void free (void *);
+
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+// dprintf is used instead of fprintf to avoid needing to declare
+// FILE and stderr.
+#define debug(...) dprintf (2, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ #error "your preprocessor is broken"
+#endif
+#if BIG_OK
+#else
+ #error "your preprocessor is broken"
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy.
+static bool
+test_varargs (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
+
+ const char *str = "";
+ int number = 0;
+ float fnumber = 0;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case '\''s'\'': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case '\''d'\'': // int
+ number = va_arg (args_copy, int);
+ break;
+ case '\''f'\'': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
+
+ return *str && number && fnumber;
+}
+'
+
+# Test code for whether the C compiler supports C99 (body of main).
+ac_c_conftest_c99_main='
+ // Check bool.
+ _Bool success = false;
+ success |= (argc != 0);
+
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
+ test_varargs_macros ();
+
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
+ // Work around memory leak warnings.
+ free (ia);
+
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[0] = argv[0][0];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
+ || dynamic_array[ni.number - 1] != 543);
+'
+
+# Test code for whether the C compiler supports C11 (global declarations)
+ac_c_conftest_c11_globals='
+// Does the compiler advertise C11 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
+# error "Compiler does not advertise C11 conformance"
+#endif
+
+// Check _Alignas.
+char _Alignas (double) aligned_as_double;
+char _Alignas (0) no_special_alignment;
+extern char aligned_as_int;
+char _Alignas (0) _Alignas (int) aligned_as_int;
+
+// Check _Alignof.
+enum
+{
+ int_alignment = _Alignof (int),
+ int_array_alignment = _Alignof (int[100]),
+ char_alignment = _Alignof (char)
+};
+_Static_assert (0 < -_Alignof (int), "_Alignof is signed");
+
+// Check _Noreturn.
+int _Noreturn does_not_return (void) { for (;;) continue; }
+
+// Check _Static_assert.
+struct test_static_assert
+{
+ int x;
+ _Static_assert (sizeof (int) <= sizeof (long int),
+ "_Static_assert does not work in struct");
+ long int y;
+};
+
+// Check UTF-8 literals.
+#define u8 syntax error!
+char const utf8_literal[] = u8"happens to be ASCII" "another string";
+
+// Check duplicate typedefs.
+typedef long *long_ptr;
+typedef long int *long_ptr;
+typedef long_ptr long_ptr;
+
+// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
+struct anonymous
+{
+ union {
+ struct { int i; int j; };
+ struct { int k; long int l; } w;
+ };
+ int m;
+} v1;
+'
+
+# Test code for whether the C compiler supports C11 (body of main).
+ac_c_conftest_c11_main='
+ _Static_assert ((offsetof (struct anonymous, i)
+ == offsetof (struct anonymous, w.k)),
+ "Anonymous union alignment botch");
+ v1.i = 2;
+ v1.w.k = 5;
+ ok |= v1.i != 5;
+'
+
+# Test code for whether the C compiler supports C11 (complete).
+ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+${ac_c_conftest_c11_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ ${ac_c_conftest_c11_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C99 (complete).
+ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C89 (complete).
+ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ return ok;
+}
+"
+
+as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
+as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
+as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
+as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
+as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
+as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
+as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
+as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
+as_fn_append ac_header_c_list " wchar.h wchar_h HAVE_WCHAR_H"
+as_fn_append ac_header_c_list " minix/config.h minix_config_h HAVE_MINIX_CONFIG_H"
+as_fn_append ac_header_c_list " netgroup.h netgroup_h HAVE_NETGROUP_H"
+as_fn_append ac_header_c_list " paths.h paths_h HAVE_PATHS_H"
+as_fn_append ac_header_c_list " spawn.h spawn_h HAVE_SPAWN_H"
+as_fn_append ac_header_c_list " wordexp.h wordexp_h HAVE_WORDEXP_H"
+as_fn_append ac_header_c_list " sys/sockio.h sys_sockio_h HAVE_SYS_SOCKIO_H"
+as_fn_append ac_header_c_list " sys/bsdtypes.h sys_bsdtypes_h HAVE_SYS_BSDTYPES_H"
+as_fn_append ac_header_c_list " sys/select.h sys_select_h HAVE_SYS_SELECT_H"
+as_fn_append ac_header_c_list " sys/stropts.h sys_stropts_h HAVE_SYS_STROPTS_H"
+as_fn_append ac_header_c_list " sys/sysmacros.h sys_sysmacros_h HAVE_SYS_SYSMACROS_H"
+as_fn_append ac_header_c_list " sys/statvfs.h sys_statvfs_h HAVE_SYS_STATVFS_H"
+as_fn_append ac_func_c_list " faccessat HAVE_FACCESSAT"
+as_fn_append ac_func_c_list " fexecve HAVE_FEXECVE"
+as_fn_append ac_func_c_list " fmemopen HAVE_FMEMOPEN"
+as_fn_append ac_func_c_list " killpg HAVE_KILLPG"
+as_fn_append ac_func_c_list " nl_langinfo HAVE_NL_LANGINFO"
+as_fn_append ac_func_c_list " renameat HAVE_RENAMEAT"
+as_fn_append ac_func_c_list " strtoull HAVE_STRTOULL"
+as_fn_append ac_func_c_list " wordexp HAVE_WORDEXP"
+as_fn_append ac_func_c_list " seteuid HAVE_SETEUID"
+
+# Auxiliary files required by this configure script.
+ac_aux_files="ltmain.sh config.guess config.sub"
+
+# Locations in which to look for auxiliary files.
+ac_aux_dir_candidates="${srcdir}/scripts"
+
+# Search for a directory containing all of the required auxiliary files,
+# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
+# If we don't find one directory that contains all the files we need,
+# we report the set of missing files from the *first* directory in
+# $ac_aux_dir_candidates and give up.
+ac_missing_aux_files=""
+ac_first_candidate=:
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in $ac_aux_dir_candidates
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ as_found=:
+
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5
+ ac_aux_dir_found=yes
+ ac_install_sh=
+ for ac_aux in $ac_aux_files
+ do
+ # As a special case, if "install-sh" is required, that requirement
+ # can be satisfied by any of "install-sh", "install.sh", or "shtool",
+ # and $ac_install_sh is set appropriately for whichever one is found.
+ if test x"$ac_aux" = x"install-sh"
+ then
+ if test -f "${as_dir}install-sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5
+ ac_install_sh="${as_dir}install-sh -c"
+ elif test -f "${as_dir}install.sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5
+ ac_install_sh="${as_dir}install.sh -c"
+ elif test -f "${as_dir}shtool"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5
+ ac_install_sh="${as_dir}shtool install -c"
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} install-sh"
+ else
+ break
+ fi
+ fi
+ else
+ if test -f "${as_dir}${ac_aux}"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
+ else
+ break
+ fi
+ fi
+ fi
+ done
+ if test "$ac_aux_dir_found" = yes; then
+ ac_aux_dir="$as_dir"
+ break
+ fi
+ ac_first_candidate=false
+
+ as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else case e in #(
+ e) as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 ;;
+esac
+fi
+
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+if test -f "${ac_aux_dir}config.guess"; then
+ ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
+fi
+if test -f "${ac_aux_dir}config.sub"; then
+ ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
+fi
+if test -f "$ac_aux_dir/configure"; then
+ ac_configure="$SHELL ${ac_aux_dir}configure"
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&5
+printf "%s\n" "$as_me: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was not set in the previous run" >&5
+printf "%s\n" "$as_me: error: '$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' has changed since the previous run:" >&5
+printf "%s\n" "$as_me: error: '$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&5
+printf "%s\n" "$as_me: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: '$ac_old_val'" >&5
+printf "%s\n" "$as_me: former value: '$ac_old_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: '$ac_new_val'" >&5
+printf "%s\n" "$as_me: current value: '$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run '${MAKE-make} distclean' and/or 'rm $cache_file'
+ and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_config_headers="$ac_config_headers config.h pathnames.h"
+
+
+
+PROGS=sudo
+LT_LDDEP="\$(shlib_exp)"
+LT_LDEXPORTS="-export-symbols \$(shlib_exp)"
+BAMAN=0
+LCMAN=0
+PSMAN=0
+SEMAN=0
+AAMAN=0
+devdir='$(srcdir)'
+PRELOAD_MODULE='-module'
+LDAP='#'
+SUDO_NLS=disabled
+exampledir='$(docdir)/examples'
+adminconfdir='$(prefix)/etc'
+PYTHON_PLUGIN='#'
+LOGSRV_SRC='lib/logsrv'
+LOGSRVD_SRC='logsrvd'
+LOGSRVD_CONF='sudo_logsrvd.conf'
+LIBLOGSRV='$(top_builddir)/lib/logsrv/liblogsrv.la $(top_builddir)/lib/protobuf-c/libprotobuf-c.la'
+PPFILES='$(srcdir)/etc/sudo.pp'
+FUZZ_LD='$(CC)'
+cvtsudoers_conf='$(sysconfdir)/cvtsudoers.conf'
+sudo_conf='$(sysconfdir)/sudo.conf'
+sudo_logsrvd_conf='$(sysconfdir)/sudo_logsrvd.conf'
+sudoers_path='$(sysconfdir)/sudoers'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+# Begin initial values for man page substitution
+#
+iolog_dir=/var/log/sudo-io
+log_dir=/var/log
+logpath=/var/log/sudo.log
+relay_dir=/var/log/sudo_logsrvd
+rundir=/var/run/sudo
+vardir=/var/adm/sudo
+timeout=5
+password_timeout=5
+sudo_umask=0022
+umask_override=off
+passprompt="Password: "
+long_otp_prompt=off
+lecture=once
+logfac=auth
+goodpri=notice
+badpri=alert
+loglen=80
+ignore_dot=off
+mail_no_user=on
+mail_no_host=off
+mail_no_perms=off
+mailto=root
+mailsub="*** SECURITY information for %h ***"
+badpass_message="Sorry, try again."
+fqdn=off
+runas_default=root
+env_editor=on
+env_reset=on
+editor=vi
+passwd_tries=3
+timestamp_type=tty
+insults=off
+root_sudo=on
+path_info=on
+ldap_conf=/etc/ldap.conf
+ldap_secret=/etc/ldap.secret
+netsvc_conf=/etc/netsvc.conf
+intercept_file="$libexecdir/sudo/sudo_intercept.so"
+noexec_file="$libexecdir/sudo/sudo_noexec.so"
+sesh_file="$libexecdir/sudo/sesh"
+nsswitch_conf=/etc/nsswitch.conf
+secure_path="not set"
+pam_session=on
+pam_login_service=sudo
+plugindir="$libexecdir/sudo"
+sudoers_plugin="sudoers.so"
+python_plugin="python_plugin.so"
+DIGEST=digest.lo
+devsearch="/dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev"
+#
+# End initial values for man page substitution
+#
+: ${MANDIRTYPE='man'}
+: ${SHLIB_MODE='0644'}
+: ${SUDOERS_MODE='0440'}
+: ${SUDOERS_UID='0'}
+: ${SUDOERS_GID='0'}
+CONFIGURE_ARGS="$@"
+AUTH_REG=
+AUTH_EXCL=
+AUTH_EXCL_DEF=
+AUTH_DEF=passwd
+CHECKSHADOW=true
+shadow_funcs=
+shadow_libs=
+OS_INIT=os_init_common
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
+ fi
+fi
+fi ;;
+esac
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+set dummy ${ac_tool_prefix}clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "clang", so it can be a program name with args.
+set dummy clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+fi
+
+
+test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See 'config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion -version; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+printf %s "checking whether the C compiler works... " >&6; }
+ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to 'no'.
+# So ignore a value of 'no', otherwise this would lead to 'EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an '-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else case e in #(
+ e) ac_file='' ;;
+esac
+fi
+if test -z "$ac_file"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See 'config.log' for more details" "$LINENO" 5; }
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; } ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+printf %s "checking for C compiler default output file name... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+printf "%s\n" "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+printf %s "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
+ # If both 'conftest.exe' and 'conftest' are 'present' (well, observable)
+# catch 'conftest.exe'. For instance with Cygwin, 'ls conftest' will
+# work properly (i.e., refer to 'conftest.exe'), while it won't with
+# 'rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else case e in #(
+ e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See 'config.log' for more details" "$LINENO" 5; } ;;
+esac
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+printf "%s\n" "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main (void)
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+printf %s "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error 77 "cannot run C compiled programs.
+If you meant to cross compile, use '--host'.
+See 'config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+printf "%s\n" "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext \
+ conftest.o conftest.obj conftest.out
+ac_clean_files=$ac_clean_files_save
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+printf %s "checking for suffix of object files... " >&6; }
+if test ${ac_cv_objext+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else case e in #(
+ e) printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See 'config.log' for more details" "$LINENO" 5; } ;;
+esac
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+printf "%s\n" "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+printf %s "checking whether the compiler supports GNU C... " >&6; }
+if test ${ac_cv_c_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_compiler_gnu=yes
+else case e in #(
+ e) ac_compiler_gnu=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+y}
+ac_save_CFLAGS=$CFLAGS
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+printf %s "checking whether $CC accepts -g... " >&6; }
+if test ${ac_cv_prog_cc_g+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_g=yes
+else case e in #(
+ e) CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else case e in #(
+ e) ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
+if test $ac_test_CFLAGS; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+ac_prog_cc_stdc=no
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
+printf %s "checking for $CC option to enable C11 features... " >&6; }
+if test ${ac_cv_prog_cc_c11+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_cv_prog_cc_c11=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c11_program
+_ACEOF
+for ac_arg in '' -std=gnu11
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC ;;
+esac
+fi
+
+if test "x$ac_cv_prog_cc_c11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else case e in #(
+ e) if test "x$ac_cv_prog_cc_c11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
+ CC="$CC $ac_cv_prog_cc_c11" ;;
+esac
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
+ ac_prog_cc_stdc=c11 ;;
+esac
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
+printf %s "checking for $CC option to enable C99 features... " >&6; }
+if test ${ac_cv_prog_cc_c99+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c99_program
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC ;;
+esac
+fi
+
+if test "x$ac_cv_prog_cc_c99" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else case e in #(
+ e) if test "x$ac_cv_prog_cc_c99" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
+ CC="$CC $ac_cv_prog_cc_c99" ;;
+esac
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+ ac_prog_cc_stdc=c99 ;;
+esac
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
+printf %s "checking for $CC option to enable C89 features... " >&6; }
+if test ${ac_cv_prog_cc_c89+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c89_program
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC ;;
+esac
+fi
+
+if test "x$ac_cv_prog_cc_c89" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else case e in #(
+ e) if test "x$ac_cv_prog_cc_c89" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
+ CC="$CC $ac_cv_prog_cc_c89" ;;
+esac
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+ ac_prog_cc_stdc=c89 ;;
+esac
+fi
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_header= ac_cache=
+for ac_item in $ac_header_c_list
+do
+ if test $ac_cache; then
+ ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
+ if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
+ printf "%s\n" "#define $ac_item 1" >> confdefs.h
+ fi
+ ac_header= ac_cache=
+ elif test $ac_header; then
+ ac_cache=$ac_item
+ else
+ ac_header=$ac_item
+ fi
+done
+
+
+
+
+
+
+
+
+if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
+then :
+
+printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+
+
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5
+printf %s "checking whether it is safe to define __EXTENSIONS__... " >&6; }
+if test ${ac_cv_safe_to_define___extensions__+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+# define __EXTENSIONS__ 1
+ $ac_includes_default
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_safe_to_define___extensions__=yes
+else case e in #(
+ e) ac_cv_safe_to_define___extensions__=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5
+printf "%s\n" "$ac_cv_safe_to_define___extensions__" >&6; }
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether _XOPEN_SOURCE should be defined" >&5
+printf %s "checking whether _XOPEN_SOURCE should be defined... " >&6; }
+if test ${ac_cv_should_define__xopen_source+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_cv_should_define__xopen_source=no
+ if test $ac_cv_header_wchar_h = yes
+then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <wchar.h>
+ mbstate_t x;
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #define _XOPEN_SOURCE 500
+ #include <wchar.h>
+ mbstate_t x;
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_should_define__xopen_source=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_should_define__xopen_source" >&5
+printf "%s\n" "$ac_cv_should_define__xopen_source" >&6; }
+
+ printf "%s\n" "#define _ALL_SOURCE 1" >>confdefs.h
+
+ printf "%s\n" "#define _DARWIN_C_SOURCE 1" >>confdefs.h
+
+ printf "%s\n" "#define _GNU_SOURCE 1" >>confdefs.h
+
+ printf "%s\n" "#define _HPUX_ALT_XOPEN_SOCKET_API 1" >>confdefs.h
+
+ printf "%s\n" "#define _NETBSD_SOURCE 1" >>confdefs.h
+
+ printf "%s\n" "#define _OPENBSD_SOURCE 1" >>confdefs.h
+
+ printf "%s\n" "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+ printf "%s\n" "#define __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 1" >>confdefs.h
+
+ printf "%s\n" "#define __STDC_WANT_IEC_60559_BFP_EXT__ 1" >>confdefs.h
+
+ printf "%s\n" "#define __STDC_WANT_IEC_60559_DFP_EXT__ 1" >>confdefs.h
+
+ printf "%s\n" "#define __STDC_WANT_IEC_60559_EXT__ 1" >>confdefs.h
+
+ printf "%s\n" "#define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1" >>confdefs.h
+
+ printf "%s\n" "#define __STDC_WANT_IEC_60559_TYPES_EXT__ 1" >>confdefs.h
+
+ printf "%s\n" "#define __STDC_WANT_LIB_EXT2__ 1" >>confdefs.h
+
+ printf "%s\n" "#define __STDC_WANT_MATH_SPEC_FUNCS__ 1" >>confdefs.h
+
+ printf "%s\n" "#define _TANDEM_SOURCE 1" >>confdefs.h
+
+ if test $ac_cv_header_minix_config_h = yes
+then :
+ MINIX=yes
+ printf "%s\n" "#define _MINIX 1" >>confdefs.h
+
+ printf "%s\n" "#define _POSIX_SOURCE 1" >>confdefs.h
+
+ printf "%s\n" "#define _POSIX_1_SOURCE 2" >>confdefs.h
+
+else case e in #(
+ e) MINIX= ;;
+esac
+fi
+ if test $ac_cv_safe_to_define___extensions__ = yes
+then :
+ printf "%s\n" "#define __EXTENSIONS__ 1" >>confdefs.h
+
+fi
+ if test $ac_cv_should_define__xopen_source = yes
+then :
+ printf "%s\n" "#define _XOPEN_SOURCE 500" >>confdefs.h
+
+fi
+
+
+#
+# Prior to sudo 1.8.7, sudo stored libexec files in $libexecdir.
+# Starting with sudo 1.8.7, $libexecdir/sudo is used so strip
+# off an extraneous "/sudo" from libexecdir.
+#
+case "$libexecdir" in
+ */sudo)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: libexecdir should not include the \"sudo\" subdirectory" >&5
+printf "%s\n" "$as_me: WARNING: libexecdir should not include the \"sudo\" subdirectory" >&2;}
+ libexecdir=`expr "$libexecdir" : '\\(.*\\)/sudo$'`
+ ;;
+esac
+
+
+
+# Check whether --with-otp-only was given.
+if test ${with_otp_only+y}
+then :
+ withval=$with_otp_only; case $with_otp_only in
+ yes) with_passwd="no"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: --with-otp-only option deprecated, treating as --without-passwd" >&5
+printf "%s\n" "$as_me: --with-otp-only option deprecated, treating as --without-passwd" >&6;}
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-alertmail was given.
+if test ${with_alertmail+y}
+then :
+ withval=$with_alertmail; case $with_alertmail in
+ *) with_mailto="$with_alertmail"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: --with-alertmail option deprecated, treating as --mailto" >&5
+printf "%s\n" "$as_me: --with-alertmail option deprecated, treating as --mailto" >&6;}
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-pc-insults was given.
+if test ${with_pc_insults+y}
+then :
+ withval=$with_pc_insults; case $with_pc_insults in
+ yes) enable_offensive_insults=no
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: --with-pc-insults option deprecated, it is now the default" >&5
+printf "%s\n" "$as_me: --with-pc-insults option deprecated, it is now the default" >&6;}
+ ;;
+ no) enable_offensive_insults=yes
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: --without-pc-insults option deprecated, use --enable-offensive-insults" >&5
+printf "%s\n" "$as_me: --without-pc-insults option deprecated, use --enable-offensive-insults" >&6;}
+ ;;
+esac
+fi
+
+
+
+
+# Check whether --with-devel was given.
+if test ${with_devel+y}
+then :
+ withval=$with_devel; case $with_devel in
+ yes) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: setting up for development: -Wall, flex, yacc" >&5
+printf "%s\n" "$as_me: setting up for development: -Wall, flex, yacc" >&6;}
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -DSUDO_DEVEL "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -DSUDO_DEVEL"; } >&5
+ (: CPPFLAGS already contains -DSUDO_DEVEL) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -DSUDO_DEVEL"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-DSUDO_DEVEL
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ DEVEL="true"
+ devdir=.
+ ;;
+ no) ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --with-devel: $with_devel" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --with-devel: $with_devel" >&2;}
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-CC was given.
+if test ${with_CC+y}
+then :
+ withval=$with_CC; case $with_CC in
+ *) as_fn_error $? "the --with-CC option is no longer supported, please pass CC=$with_CC to configure instead." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-rpath was given.
+if test ${with_rpath+y}
+then :
+ withval=$with_rpath; { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: --with-rpath deprecated, rpath is now the default" >&5
+printf "%s\n" "$as_me: WARNING: --with-rpath deprecated, rpath is now the default" >&2;}
+fi
+
+
+
+# Check whether --with-blibpath was given.
+if test ${with_blibpath+y}
+then :
+ withval=$with_blibpath; { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: --with-blibpath deprecated, use --with-libpath" >&5
+printf "%s\n" "$as_me: WARNING: --with-blibpath deprecated, use --with-libpath" >&2;}
+fi
+
+
+
+# Check whether --with-bsm-audit was given.
+if test ${with_bsm_audit+y}
+then :
+ withval=$with_bsm_audit; case $with_bsm_audit in
+ yes) printf "%s\n" "#define HAVE_BSM_AUDIT 1" >>confdefs.h
+
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lbsm"
+ SUDOERS_OBJS="${SUDOERS_OBJS} bsm_audit.lo"
+ ;;
+ no) ;;
+ *) as_fn_error $? "--with-bsm-audit does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-linux-audit was given.
+if test ${with_linux_audit+y}
+then :
+ withval=$with_linux_audit; case $with_linux_audit in
+ yes) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <libaudit.h>
+int
+main (void)
+{
+int i = AUDIT_USER_CMD; (void)i;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+ printf "%s\n" "#define HAVE_LINUX_AUDIT 1" >>confdefs.h
+
+ SUDO_LIBS="${SUDO_LIBS} -laudit"
+ SUDOERS_LIBS="${SUDO_LIBS} -laudit"
+ SUDOERS_OBJS="${SUDOERS_OBJS} linux_audit.lo"
+
+else case e in #(
+ e)
+ as_fn_error $? "unable to find AUDIT_USER_CMD in libaudit.h for --with-linux-audit" "$LINENO" 5
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ;;
+ no) ;;
+ *) as_fn_error $? "--with-linux-audit does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-solaris-audit was given.
+if test ${with_solaris_audit+y}
+then :
+ withval=$with_solaris_audit; case $with_solaris_audit in
+ yes) printf "%s\n" "#define HAVE_SOLARIS_AUDIT 1" >>confdefs.h
+
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lbsm"
+ SUDOERS_OBJS="${SUDOERS_OBJS} solaris_audit.lo"
+ ;;
+ no) ;;
+ *) as_fn_error $? "--with-solaris-audit does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-sssd was given.
+if test ${with_sssd+y}
+then :
+ withval=$with_sssd; case $with_sssd in
+ yes) SUDOERS_OBJS="${SUDOERS_OBJS} sssd.lo"
+ case "$SUDOERS_OBJS" in
+ *ldap_util.lo*) ;;
+ *) SUDOERS_OBJS="${SUDOERS_OBJS} ldap_util.lo";;
+ esac
+ printf "%s\n" "#define HAVE_SSSD 1" >>confdefs.h
+
+ ;;
+ no) ;;
+ *) as_fn_error $? "--with-sssd does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-sssd-conf was given.
+if test ${with_sssd_conf+y}
+then :
+ withval=$with_sssd_conf;
+fi
+
+sssd_conf="/etc/sssd/sssd.conf"
+test -n "$with_sssd_conf" && sssd_conf="$with_sssd_conf"
+cat >>confdefs.h <<EOF
+#define _PATH_SSSD_CONF "$sssd_conf"
+EOF
+
+
+
+# Check whether --with-sssd-lib was given.
+if test ${with_sssd_lib+y}
+then :
+ withval=$with_sssd_lib;
+fi
+
+sssd_lib="\"LIBDIR\""
+test -n "$with_sssd_lib" && sssd_lib="$with_sssd_lib"
+cat >>confdefs.h <<EOF
+#define _PATH_SSSD_LIB "$sssd_lib"
+EOF
+
+
+
+# Check whether --with-incpath was given.
+if test ${with_incpath+y}
+then :
+ withval=$with_incpath; case $with_incpath in
+ yes) as_fn_error $? "must give --with-incpath an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-incpath not supported." "$LINENO" 5
+ ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: adding ${with_incpath} to CPPFLAGS" >&5
+printf "%s\n" "$as_me: adding ${with_incpath} to CPPFLAGS" >&6;}
+ for i in ${with_incpath}; do
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -I${i} "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -I\${i}"; } >&5
+ (: CPPFLAGS already contains -I${i}) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -I${i}"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-I${i}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ done
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-libpath was given.
+if test ${with_libpath+y}
+then :
+ withval=$with_libpath; case $with_libpath in
+ yes) as_fn_error $? "must give --with-libpath an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-libpath not supported." "$LINENO" 5
+ ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: adding ${with_libpath} to LDFLAGS" >&5
+printf "%s\n" "$as_me: adding ${with_libpath} to LDFLAGS" >&6;}
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-libraries was given.
+if test ${with_libraries+y}
+then :
+ withval=$with_libraries; case $with_libraries in
+ yes) as_fn_error $? "must give --with-libraries an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-libraries not supported." "$LINENO" 5
+ ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: adding ${with_libraries} to LIBS" >&5
+printf "%s\n" "$as_me: adding ${with_libraries} to LIBS" >&6;}
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-csops was given.
+if test ${with_csops+y}
+then :
+ withval=$with_csops; case $with_csops in
+ yes) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: adding CSOps standard options" >&5
+printf "%s\n" "$as_me: adding CSOps standard options" >&6;}
+ CHECKSIA=false
+ with_ignore_dot=yes
+ insults=on
+ with_classic_insults=yes
+ with_csops_insults=yes
+ with_env_editor=yes
+ : ${mansectsu='8'}
+ : ${mansectform='5'}
+ : ${mansectmisc='7'}
+ ;;
+ no) ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --with-csops: $with_csops" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --with-csops: $with_csops" >&2;}
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-passwd was given.
+if test ${with_passwd+y}
+then :
+ withval=$with_passwd; case $with_passwd in
+ yes|no) AUTH_DEF=""
+ test "$with_passwd" = "yes" && AUTH_REG="$AUTH_REG passwd"
+ ;;
+ *) as_fn_error $? "sorry, --with-passwd does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-skey was given.
+if test ${with_skey+y}
+then :
+ withval=$with_skey; case $with_skey in
+ no) ;;
+ *) printf "%s\n" "#define HAVE_SKEY 1" >>confdefs.h
+
+ AUTH_REG="$AUTH_REG S/Key"
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-opie was given.
+if test ${with_opie+y}
+then :
+ withval=$with_opie; case $with_opie in
+ no) ;;
+ *) printf "%s\n" "#define HAVE_OPIE 1" >>confdefs.h
+
+ AUTH_REG="$AUTH_REG NRL_OPIE"
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-long-otp-prompt was given.
+if test ${with_long_otp_prompt+y}
+then :
+ withval=$with_long_otp_prompt; case $with_long_otp_prompt in
+ yes) printf "%s\n" "#define LONG_OTP_PROMPT 1" >>confdefs.h
+
+ long_otp_prompt=on
+ ;;
+ no) long_otp_prompt=off
+ ;;
+ *) as_fn_error $? "--with-long-otp-prompt does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-SecurID was given.
+if test ${with_SecurID+y}
+then :
+ withval=$with_SecurID; case $with_SecurID in
+ no) ;;
+ *) printf "%s\n" "#define HAVE_SECURID 1" >>confdefs.h
+
+ AUTH_EXCL="$AUTH_EXCL SecurID"
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-fwtk was given.
+if test ${with_fwtk+y}
+then :
+ withval=$with_fwtk; case $with_fwtk in
+ no) ;;
+ *) printf "%s\n" "#define HAVE_FWTK 1" >>confdefs.h
+
+ AUTH_EXCL="$AUTH_EXCL FWTK"
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-kerb5 was given.
+if test ${with_kerb5+y}
+then :
+ withval=$with_kerb5; case $with_kerb5 in
+ no) ;;
+ *) AUTH_REG="$AUTH_REG kerb5"
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-aixauth was given.
+if test ${with_aixauth+y}
+then :
+ withval=$with_aixauth; case $with_aixauth in
+ yes) AUTH_EXCL="$AUTH_EXCL AIX_AUTH";;
+ no) ;;
+ *) as_fn_error $? "--with-aixauth does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-pam was given.
+if test ${with_pam+y}
+then :
+ withval=$with_pam; case $with_pam in
+ yes) AUTH_EXCL="$AUTH_EXCL PAM";;
+ no) ;;
+ *) as_fn_error $? "--with-pam does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-AFS was given.
+if test ${with_AFS+y}
+then :
+ withval=$with_AFS; case $with_AFS in
+ yes) printf "%s\n" "#define HAVE_AFS 1" >>confdefs.h
+
+ AUTH_REG="$AUTH_REG AFS"
+ ;;
+ no) ;;
+ *) as_fn_error $? "--with-AFS does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-DCE was given.
+if test ${with_DCE+y}
+then :
+ withval=$with_DCE; case $with_DCE in
+ yes) printf "%s\n" "#define HAVE_DCE 1" >>confdefs.h
+
+ AUTH_REG="$AUTH_REG DCE"
+ ;;
+ no) ;;
+ *) as_fn_error $? "--with-DCE does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-logincap was given.
+if test ${with_logincap+y}
+then :
+ withval=$with_logincap; case $with_logincap in
+ yes|no) ;;
+ *) as_fn_error $? "--with-logincap does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-bsdauth was given.
+if test ${with_bsdauth+y}
+then :
+ withval=$with_bsdauth; case $with_bsdauth in
+ yes) AUTH_EXCL="$AUTH_EXCL BSD_AUTH";;
+ no) ;;
+ *) as_fn_error $? "--with-bsdauth does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-project was given.
+if test ${with_project+y}
+then :
+ withval=$with_project; case $with_project in
+ yes|no) ;;
+ no) ;;
+ *) as_fn_error $? "--with-project does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-lecture was given.
+if test ${with_lecture+y}
+then :
+ withval=$with_lecture; case $with_lecture in
+ yes|short|always) lecture=once
+ ;;
+ no|none|never) lecture=never
+ printf "%s\n" "#define NO_LECTURE 1" >>confdefs.h
+
+ ;;
+ *) as_fn_error $? "unknown argument to --with-lecture: $with_lecture" "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-logging was given.
+if test ${with_logging+y}
+then :
+ withval=$with_logging; case $with_logging in
+ yes) as_fn_error $? "must give --with-logging an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-logging not supported." "$LINENO" 5
+ ;;
+ syslog) printf "%s\n" "#define LOGGING SLOG_SYSLOG" >>confdefs.h
+
+ ;;
+ file) printf "%s\n" "#define LOGGING SLOG_FILE" >>confdefs.h
+
+ ;;
+ both) printf "%s\n" "#define LOGGING SLOG_BOTH" >>confdefs.h
+
+ ;;
+ *) as_fn_error $? "unknown argument to --with-logging: $with_logging" "$LINENO" 5
+ ;;
+esac
+else case e in #(
+ e)
+ with_logging=syslog
+ printf "%s\n" "#define LOGGING SLOG_SYSLOG" >>confdefs.h
+
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-logfac was given.
+if test ${with_logfac+y}
+then :
+ withval=$with_logfac; case $with_logfac in
+ yes) as_fn_error $? "must give --with-logfac an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-logfac not supported." "$LINENO" 5
+ ;;
+ authpriv|auth|daemon|user|local0|local1|local2|local3|local4|local5|local6|local7) logfac=$with_logfac
+ ;;
+ *) as_fn_error $? "$with_logfac is not a supported syslog facility." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-goodpri was given.
+if test ${with_goodpri+y}
+then :
+ withval=$with_goodpri; case $with_goodpri in
+ yes) as_fn_error $? "must give --with-goodpri an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-goodpri not supported." "$LINENO" 5
+ ;;
+ alert|crit|debug|emerg|err|info|notice|warning)
+ goodpri=$with_goodpri
+ ;;
+ *) as_fn_error $? "$with_goodpri is not a supported syslog priority." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+printf "%s\n" "#define PRI_SUCCESS \"$goodpri\"" >>confdefs.h
+
+
+
+# Check whether --with-badpri was given.
+if test ${with_badpri+y}
+then :
+ withval=$with_badpri; case $with_badpri in
+ yes) as_fn_error $? "must give --with-badpri an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-badpri not supported." "$LINENO" 5
+ ;;
+ alert|crit|debug|emerg|err|info|notice|warning)
+ badpri=$with_badpri
+ ;;
+ *) as_fn_error $? "$with_badpri is not a supported syslog priority." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+printf "%s\n" "#define PRI_FAILURE \"$badpri\"" >>confdefs.h
+
+
+
+# Check whether --with-logpath was given.
+if test ${with_logpath+y}
+then :
+ withval=$with_logpath; case $with_logpath in
+ yes) as_fn_error $? "must give --with-logpath an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-logpath not supported." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-loglen was given.
+if test ${with_loglen+y}
+then :
+ withval=$with_loglen; case $with_loglen in
+ yes) as_fn_error $? "must give --with-loglen an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-loglen not supported." "$LINENO" 5
+ ;;
+ [0-9]*) loglen=$with_loglen
+ ;;
+ *) as_fn_error $? "you must enter a number, not $with_loglen" "$LINENO" 5
+ ;;
+esac
+fi
+
+
+printf "%s\n" "#define MAXLOGFILELEN $loglen" >>confdefs.h
+
+
+
+# Check whether --with-ignore-dot was given.
+if test ${with_ignore_dot+y}
+then :
+ withval=$with_ignore_dot; case $with_ignore_dot in
+ yes) ignore_dot=on
+ printf "%s\n" "#define IGNORE_DOT_PATH 1" >>confdefs.h
+
+ ;;
+ no) ignore_dot=off
+ ;;
+ *) as_fn_error $? "--with-ignore-dot does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-mail-if-no-user was given.
+if test ${with_mail_if_no_user+y}
+then :
+ withval=$with_mail_if_no_user; case $with_mail_if_no_user in
+ yes) mail_no_user=on
+ ;;
+ no) mail_no_user=off
+ ;;
+ *) as_fn_error $? "--with-mail-if-no-user does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+if test "$mail_no_user" = "on"
+then :
+ printf "%s\n" "#define SEND_MAIL_WHEN_NO_USER 1" >>confdefs.h
+
+fi
+
+
+# Check whether --with-mail-if-no-host was given.
+if test ${with_mail_if_no_host+y}
+then :
+ withval=$with_mail_if_no_host; case $with_mail_if_no_host in
+ yes) mail_no_host=on
+ printf "%s\n" "#define SEND_MAIL_WHEN_NO_HOST 1" >>confdefs.h
+
+ ;;
+ no) mail_no_host=off
+ ;;
+ *) as_fn_error $? "--with-mail-if-no-host does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-mail-if-noperms was given.
+if test ${with_mail_if_noperms+y}
+then :
+ withval=$with_mail_if_noperms; case $with_mail_if_noperms in
+ yes) mail_noperms=on
+ printf "%s\n" "#define SEND_MAIL_WHEN_NOT_OK 1" >>confdefs.h
+
+ ;;
+ no) mail_noperms=off
+ ;;
+ *) as_fn_error $? "--with-mail-if-noperms does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-mailto was given.
+if test ${with_mailto+y}
+then :
+ withval=$with_mailto; case $with_mailto in
+ yes) as_fn_error $? "must give --with-mailto an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-mailto not supported." "$LINENO" 5
+ ;;
+ *) mailto=$with_mailto
+ ;;
+esac
+fi
+
+
+printf "%s\n" "#define MAILTO \"$mailto\"" >>confdefs.h
+
+
+
+# Check whether --with-mailsubject was given.
+if test ${with_mailsubject+y}
+then :
+ withval=$with_mailsubject; case $with_mailsubject in
+ yes) as_fn_error $? "must give --with-mailsubject an argument." "$LINENO" 5
+ ;;
+ no) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: sorry, --without-mailsubject not supported." >&5
+printf "%s\n" "$as_me: WARNING: sorry, --without-mailsubject not supported." >&2;}
+ ;;
+ *) mailsub="$with_mailsubject"
+ ;;
+esac
+fi
+
+
+printf "%s\n" "#define MAILSUBJECT \"$mailsub\"" >>confdefs.h
+
+
+
+# Check whether --with-passprompt was given.
+if test ${with_passprompt+y}
+then :
+ withval=$with_passprompt; case $with_passprompt in
+ yes) as_fn_error $? "must give --with-passprompt an argument." "$LINENO" 5
+ ;;
+ no) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: sorry, --without-passprompt not supported." >&5
+printf "%s\n" "$as_me: WARNING: sorry, --without-passprompt not supported." >&2;}
+ ;;
+ *) passprompt="$with_passprompt"
+esac
+fi
+
+
+printf "%s\n" "#define PASSPROMPT \"$passprompt\"" >>confdefs.h
+
+
+
+# Check whether --with-badpass-message was given.
+if test ${with_badpass_message+y}
+then :
+ withval=$with_badpass_message; case $with_badpass_message in
+ yes) as_fn_error $? "must give --with-badpass-message an argument." "$LINENO" 5
+ ;;
+ no) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: sorry, --without-badpass-message not supported." >&5
+printf "%s\n" "$as_me: WARNING: sorry, --without-badpass-message not supported." >&2;}
+ ;;
+ *) badpass_message="$with_badpass_message"
+ ;;
+esac
+fi
+
+
+printf "%s\n" "#define INCORRECT_PASSWORD \"$badpass_message\"" >>confdefs.h
+
+
+
+# Check whether --with-fqdn was given.
+if test ${with_fqdn+y}
+then :
+ withval=$with_fqdn; case $with_fqdn in
+ yes) fqdn=on
+ printf "%s\n" "#define FQDN 1" >>confdefs.h
+
+ ;;
+ no) fqdn=off
+ ;;
+ *) as_fn_error $? "--with-fqdn does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-timedir was given.
+if test ${with_timedir+y}
+then :
+ withval=$with_timedir; case $with_timedir in
+ *) as_fn_error $? "--without-timedir no longer supported, see --with-rundir." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-rundir was given.
+if test ${with_rundir+y}
+then :
+ withval=$with_rundir; case $with_rundir in
+ yes) as_fn_error $? "must give --with-rundir an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-rundir not supported." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-vardir was given.
+if test ${with_vardir+y}
+then :
+ withval=$with_vardir; case $with_vardir in
+ yes) as_fn_error $? "must give --with-vardir an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-vardir not supported." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-iologdir was given.
+if test ${with_iologdir+y}
+then :
+ withval=$with_iologdir; case $with_iologdir in
+ yes) ;;
+ no) as_fn_error $? "--without-iologdir not supported." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-relaydir was given.
+if test ${with_relaydir+y}
+then :
+ withval=$with_relaydir; case $with_relaydir in
+ yes) ;;
+ no) as_fn_error $? "--without-relaydir not supported." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-tzdir was given.
+if test ${with_tzdir+y}
+then :
+ withval=$with_tzdir; case $with_tzdir in
+ yes) as_fn_error $? "must give --with-tzdir an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-sendmail was given.
+if test ${with_sendmail+y}
+then :
+ withval=$with_sendmail; case $with_sendmail in
+ yes) with_sendmail=""
+ ;;
+ no) ;;
+ *) cat >>confdefs.h <<EOF
+#define _PATH_SUDO_SENDMAIL "$with_sendmail"
+EOF
+
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-sudoers-mode was given.
+if test ${with_sudoers_mode+y}
+then :
+ withval=$with_sudoers_mode; case $with_sudoers_mode in
+ yes) as_fn_error $? "must give --with-sudoers-mode an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-sudoers-mode not supported." "$LINENO" 5
+ ;;
+ [1-9]*) SUDOERS_MODE=0${with_sudoers_mode}
+ ;;
+ 0*) SUDOERS_MODE=$with_sudoers_mode
+ ;;
+ *) as_fn_error $? "you must use an octal mode, not a name." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-sudoers-uid was given.
+if test ${with_sudoers_uid+y}
+then :
+ withval=$with_sudoers_uid; case $with_sudoers_uid in
+ yes) as_fn_error $? "must give --with-sudoers-uid an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-sudoers-uid not supported." "$LINENO" 5
+ ;;
+ [0-9]*) SUDOERS_UID=$with_sudoers_uid
+ ;;
+ *) as_fn_error $? "you must use an unsigned numeric uid, not a name." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-sudoers-gid was given.
+if test ${with_sudoers_gid+y}
+then :
+ withval=$with_sudoers_gid; case $with_sudoers_gid in
+ yes) as_fn_error $? "must give --with-sudoers-gid an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-sudoers-gid not supported." "$LINENO" 5
+ ;;
+ [0-9]*) SUDOERS_GID=$with_sudoers_gid
+ ;;
+ *) as_fn_error $? "you must use an unsigned numeric gid, not a name." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-umask was given.
+if test ${with_umask+y}
+then :
+ withval=$with_umask; case $with_umask in
+ yes) as_fn_error $? "must give --with-umask an argument." "$LINENO" 5
+ ;;
+ no) sudo_umask=0777
+ ;;
+ [0-9]*) sudo_umask=$with_umask
+ ;;
+ *) as_fn_error $? "you must enter a numeric mask." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+printf "%s\n" "#define SUDO_UMASK $sudo_umask" >>confdefs.h
+
+
+
+# Check whether --with-umask-override was given.
+if test ${with_umask_override+y}
+then :
+ withval=$with_umask_override; case $with_umask_override in
+ yes) printf "%s\n" "#define UMASK_OVERRIDE 1" >>confdefs.h
+
+ umask_override=on
+ ;;
+ no) umask_override=off
+ ;;
+ *) as_fn_error $? "--with-umask-override does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-runas-default was given.
+if test ${with_runas_default+y}
+then :
+ withval=$with_runas_default; case $with_runas_default in
+ yes) as_fn_error $? "must give --with-runas-default an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-runas-default not supported." "$LINENO" 5
+ ;;
+ *) runas_default="$with_runas_default"
+ ;;
+esac
+fi
+
+
+printf "%s\n" "#define RUNAS_DEFAULT \"$runas_default\"" >>confdefs.h
+
+
+
+# Check whether --with-exempt was given.
+if test ${with_exempt+y}
+then :
+ withval=$with_exempt; case $with_exempt in
+ yes) as_fn_error $? "must give --with-exempt an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-exempt not supported." "$LINENO" 5
+ ;;
+ *)
+printf "%s\n" "#define EXEMPTGROUP \"$with_exempt\"" >>confdefs.h
+
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-editor was given.
+if test ${with_editor+y}
+then :
+ withval=$with_editor; case $with_editor in
+ yes) as_fn_error $? "must give --with-editor an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-editor not supported." "$LINENO" 5
+ ;;
+ *)
+printf "%s\n" "#define EDITOR \"$with_editor\"" >>confdefs.h
+
+ editor="$with_editor"
+ ;;
+esac
+else case e in #(
+ e) printf "%s\n" "#define EDITOR _PATH_VI" >>confdefs.h
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-env-editor was given.
+if test ${with_env_editor+y}
+then :
+ withval=$with_env_editor; case $with_env_editor in
+ yes) env_editor=on
+ ;;
+ no) env_editor=off
+ ;;
+ *) as_fn_error $? "--with-env-editor does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+if test "$env_editor" = "on"
+then :
+ printf "%s\n" "#define ENV_EDITOR 1" >>confdefs.h
+
+fi
+
+
+# Check whether --with-passwd-tries was given.
+if test ${with_passwd_tries+y}
+then :
+ withval=$with_passwd_tries; case $with_passwd_tries in
+ yes) ;;
+ no) as_fn_error $? "--without-editor not supported." "$LINENO" 5
+ ;;
+ [1-9]*) passwd_tries=$with_passwd_tries
+ ;;
+ *) as_fn_error $? "you must enter the number of tries, > 0" "$LINENO" 5
+ ;;
+esac
+fi
+
+
+printf "%s\n" "#define TRIES_FOR_PASSWORD $passwd_tries" >>confdefs.h
+
+
+
+# Check whether --with-timeout was given.
+if test ${with_timeout+y}
+then :
+ withval=$with_timeout; case $with_timeout in
+ yes) ;;
+ no) timeout=0
+ ;;
+ [0-9]*) timeout=$with_timeout
+ ;;
+ *) as_fn_error $? "you must enter the number of minutes." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+printf "%s\n" "#define TIMEOUT $timeout" >>confdefs.h
+
+
+
+# Check whether --with-password-timeout was given.
+if test ${with_password_timeout+y}
+then :
+ withval=$with_password_timeout; case $with_password_timeout in
+ yes) ;;
+ no) password_timeout=0
+ ;;
+ [0-9]*) password_timeout=$with_password_timeout
+ ;;
+ *) as_fn_error $? "you must enter the number of minutes." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+printf "%s\n" "#define PASSWORD_TIMEOUT $password_timeout" >>confdefs.h
+
+
+
+# Check whether --with-tty-tickets was given.
+if test ${with_tty_tickets+y}
+then :
+ withval=$with_tty_tickets; case $with_tty_tickets in
+ yes) timestamp_type=tty
+ ;;
+ no) timestamp_type=global
+ ;;
+ *) as_fn_error $? "--with-tty-tickets does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-insults was given.
+if test ${with_insults+y}
+then :
+ withval=$with_insults; case $with_insults in
+ yes) insults=on
+ printf "%s\n" "#define USE_INSULTS 1" >>confdefs.h
+
+ with_classic_insults=yes
+ with_csops_insults=yes
+ ;;
+ disabled) insults=off
+ with_classic_insults=yes
+ with_csops_insults=yes
+ ;;
+ no) insults=off
+ ;;
+ *) as_fn_error $? "--with-insults does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-all-insults was given.
+if test ${with_all_insults+y}
+then :
+ withval=$with_all_insults; case $with_all_insults in
+ yes) with_classic_insults=yes
+ with_csops_insults=yes
+ with_hal_insults=yes
+ with_goons_insults=yes
+ with_python_insults=yes
+ ;;
+ no) ;;
+ *) as_fn_error $? "--with-all-insults does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-classic-insults was given.
+if test ${with_classic_insults+y}
+then :
+ withval=$with_classic_insults; case $with_classic_insults in
+ yes) printf "%s\n" "#define CLASSIC_INSULTS 1" >>confdefs.h
+
+ ;;
+ no) ;;
+ *) as_fn_error $? "--with-classic-insults does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-csops-insults was given.
+if test ${with_csops_insults+y}
+then :
+ withval=$with_csops_insults; case $with_csops_insults in
+ yes) printf "%s\n" "#define CSOPS_INSULTS 1" >>confdefs.h
+
+ ;;
+ no) ;;
+ *) as_fn_error $? "--with-csops-insults does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-hal-insults was given.
+if test ${with_hal_insults+y}
+then :
+ withval=$with_hal_insults; case $with_hal_insults in
+ yes) printf "%s\n" "#define HAL_INSULTS 1" >>confdefs.h
+
+ ;;
+ no) ;;
+ *) as_fn_error $? "--with-hal-insults does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-goons-insults was given.
+if test ${with_goons_insults+y}
+then :
+ withval=$with_goons_insults; case $with_goons_insults in
+ yes) printf "%s\n" "#define GOONS_INSULTS 1" >>confdefs.h
+
+ ;;
+ no) ;;
+ *) as_fn_error $? "--with-goons-insults does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-python-insults was given.
+if test ${with_python_insults+y}
+then :
+ withval=$with_python_insults; case $with_python_insults in
+ yes) printf "%s\n" "#define PYTHON_INSULTS 1" >>confdefs.h
+
+ ;;
+ no) ;;
+ *) as_fn_error $? "--with-python-insults does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-nsswitch was given.
+if test ${with_nsswitch+y}
+then :
+ withval=$with_nsswitch; case $with_nsswitch in
+ no) ;;
+ yes) with_nsswitch="/etc/nsswitch.conf"
+ ;;
+ *) ;;
+esac
+fi
+
+
+
+# Check whether --with-ldap was given.
+if test ${with_ldap+y}
+then :
+ withval=$with_ldap; case $with_ldap in
+ no) ;;
+ *) printf "%s\n" "#define HAVE_LDAP 1" >>confdefs.h
+
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-ldap-conf-file was given.
+if test ${with_ldap_conf_file+y}
+then :
+ withval=$with_ldap_conf_file;
+fi
+
+test -n "$with_ldap_conf_file" && ldap_conf="$with_ldap_conf_file"
+cat >>confdefs.h <<EOF
+#define _PATH_LDAP_CONF "$ldap_conf"
+EOF
+
+
+
+# Check whether --with-ldap-secret-file was given.
+if test ${with_ldap_secret_file+y}
+then :
+ withval=$with_ldap_secret_file;
+fi
+
+test -n "$with_ldap_secret_file" && ldap_secret="$with_ldap_secret_file"
+cat >>confdefs.h <<EOF
+#define _PATH_LDAP_SECRET "$ldap_secret"
+EOF
+
+
+
+# Check whether --with-secure-path was given.
+if test ${with_secure_path+y}
+then :
+ withval=$with_secure_path; case $with_secure_path in
+ yes) with_secure_path="/bin:/usr/ucb:/usr/bin:/usr/sbin:/sbin:/usr/etc:/etc"
+ printf "%s\n" "#define SECURE_PATH \"$with_secure_path\"" >>confdefs.h
+
+ secure_path="set to $with_secure_path"
+ ;;
+ no) ;;
+ *) printf "%s\n" "#define SECURE_PATH \"$with_secure_path\"" >>confdefs.h
+
+ secure_path="set to $with_secure_path"
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-interfaces was given.
+if test ${with_interfaces+y}
+then :
+ withval=$with_interfaces; case $with_interfaces in
+ yes) ;;
+ no) printf "%s\n" "#define STUB_LOAD_INTERFACES 1" >>confdefs.h
+
+ ;;
+ *) as_fn_error $? "--with-interfaces does not take an argument." "$LINENO" 5
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-askpass was given.
+if test ${with_askpass+y}
+then :
+ withval=$with_askpass; case $with_askpass in
+ yes) as_fn_error $? "--with-askpass takes a path as an argument." "$LINENO" 5
+ ;;
+ no) ;;
+ *) ;;
+esac
+else case e in #(
+ e)
+ with_askpass=no
+ ;;
+esac
+fi
+
+if test X"$with_askpass" != X"no"
+then :
+
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDO_ASKPASS "$with_askpass"
+EOF
+
+
+else case e in #(
+ e)
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDO_ASKPASS NULL
+EOF
+
+ ;;
+esac
+fi
+
+
+# Check whether --with-exampledir was given.
+if test ${with_exampledir+y}
+then :
+ withval=$with_exampledir; case $with_exampledir in
+ yes) as_fn_error $? "must give --with-exampledir an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-exampledir not supported." "$LINENO" 5
+ ;;
+ *) exampledir="$with_exampledir"
+esac
+fi
+
+
+
+# Check whether --with-plugindir was given.
+if test ${with_plugindir+y}
+then :
+ withval=$with_plugindir; case $with_plugindir in
+ yes) as_fn_error $? "must give --with-plugindir an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--without-plugindir not supported." "$LINENO" 5
+ ;;
+ *) plugindir="$with_plugindir"
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-man was given.
+if test ${with_man+y}
+then :
+ withval=$with_man; case $with_man in
+ yes) MANTYPE=man
+ ;;
+ no) as_fn_error $? "--without-man not supported." "$LINENO" 5
+ ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --with-man: $with_man." >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --with-man: $with_man." >&2;}
+ ;;
+esac
+fi
+
+
+
+# Check whether --with-mdoc was given.
+if test ${with_mdoc+y}
+then :
+ withval=$with_mdoc; case $with_mdoc in
+ yes) MANTYPE=mdoc
+ ;;
+ no) as_fn_error $? "--without-mdoc not supported." "$LINENO" 5
+ ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --with-mdoc: $with_mdoc." >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --with-mdoc: $with_mdoc." >&2;}
+ ;;
+esac
+fi
+
+
+
+# Check whether --enable-authentication was given.
+if test ${enable_authentication+y}
+then :
+ enableval=$enable_authentication; case "$enableval" in
+ yes) ;;
+ no) printf "%s\n" "#define NO_AUTHENTICATION 1" >>confdefs.h
+
+ ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-authentication: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-authentication: $enableval" >&2;}
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-root-mailer was given.
+if test ${enable_root_mailer+y}
+then :
+ enableval=$enable_root_mailer; case "$enableval" in
+ yes) ;;
+ no) printf "%s\n" "#define NO_ROOT_MAILER 1" >>confdefs.h
+
+ ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-root-mailer: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-root-mailer: $enableval" >&2;}
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-setreuid was given.
+if test ${enable_setreuid+y}
+then :
+ enableval=$enable_setreuid; case "$enableval" in
+ no) SKIP_SETREUID=yes
+ ;;
+ *) ;;
+ esac
+
+fi
+
+
+# Check whether --enable-setresuid was given.
+if test ${enable_setresuid+y}
+then :
+ enableval=$enable_setresuid; case "$enableval" in
+ no) SKIP_SETRESUID=yes
+ ;;
+ *) ;;
+ esac
+
+fi
+
+
+# Check whether --enable-shadow was given.
+if test ${enable_shadow+y}
+then :
+ enableval=$enable_shadow; case "$enableval" in
+ yes) ;;
+ no) CHECKSHADOW="false"
+ ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-shadow: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-shadow: $enableval" >&2;}
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-root-sudo was given.
+if test ${enable_root_sudo+y}
+then :
+ enableval=$enable_root_sudo; case "$enableval" in
+ yes) ;;
+ no) printf "%s\n" "#define NO_ROOT_SUDO 1" >>confdefs.h
+
+ root_sudo=off
+ ;;
+ *) as_fn_error $? "--enable-root-sudo does not take an argument." "$LINENO" 5
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-log-host was given.
+if test ${enable_log_host+y}
+then :
+ enableval=$enable_log_host; case "$enableval" in
+ yes) printf "%s\n" "#define HOST_IN_LOG 1" >>confdefs.h
+
+ ;;
+ no) ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-log-host: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-log-host: $enableval" >&2;}
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-noargs-shell was given.
+if test ${enable_noargs_shell+y}
+then :
+ enableval=$enable_noargs_shell; case "$enableval" in
+ yes) printf "%s\n" "#define SHELL_IF_NO_ARGS 1" >>confdefs.h
+
+ ;;
+ no) ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-noargs-shell: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-noargs-shell: $enableval" >&2;}
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-shell-sets-home was given.
+if test ${enable_shell_sets_home+y}
+then :
+ enableval=$enable_shell_sets_home; case "$enableval" in
+ yes) printf "%s\n" "#define SHELL_SETS_HOME 1" >>confdefs.h
+
+ ;;
+ no) ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-shell-sets-home: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-shell-sets-home: $enableval" >&2;}
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-path_info was given.
+if test ${enable_path_info+y}
+then :
+ enableval=$enable_path_info; case "$enableval" in
+ yes) ;;
+ no) printf "%s\n" "#define DONT_LEAK_PATH_INFO 1" >>confdefs.h
+
+ path_info=off
+ ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-path-info: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-path-info: $enableval" >&2;}
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-env_debug was given.
+if test ${enable_env_debug+y}
+then :
+ enableval=$enable_env_debug; case "$enableval" in
+ yes) printf "%s\n" "#define ENV_DEBUG 1" >>confdefs.h
+
+ ;;
+ no) ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-env-debug: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-env-debug: $enableval" >&2;}
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-postinstall was given.
+if test ${enable_postinstall+y}
+then :
+ enableval=$enable_postinstall; case "$enableval" in
+ yes) as_fn_error $? "must give --enable-postinstall an argument." "$LINENO" 5
+ ;;
+ no) as_fn_error $? "--enable-postinstall not supported." "$LINENO" 5
+ ;;
+ *) POSTINSTALL="$enableval"
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-zlib was given.
+if test ${enable_zlib+y}
+then :
+ enableval=$enable_zlib;
+else case e in #(
+ e) enable_zlib=yes ;;
+esac
+fi
+
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -DZLIB_CONST "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -DZLIB_CONST"; } >&5
+ (: CPPFLAGS already contains -DZLIB_CONST) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -DZLIB_CONST"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-DZLIB_CONST
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+# Check whether --enable-env_reset was given.
+if test ${enable_env_reset+y}
+then :
+ enableval=$enable_env_reset; case "$enableval" in
+ yes) env_reset=on
+ ;;
+ no) env_reset=off
+ ;;
+ *) env_reset=on
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-env-reset: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-env-reset: $enableval" >&2;}
+ ;;
+ esac
+
+fi
+
+if test "$env_reset" = "on"
+then :
+
+ printf "%s\n" "#define ENV_RESET 1" >>confdefs.h
+
+
+else case e in #(
+ e)
+ printf "%s\n" "#define ENV_RESET 0" >>confdefs.h
+
+ ;;
+esac
+fi
+
+# Check whether --enable-warnings was given.
+if test ${enable_warnings+y}
+then :
+ enableval=$enable_warnings; case "$enableval" in
+ yes) ;;
+ no) ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-warnings: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-warnings: $enableval" >&2;}
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-werror was given.
+if test ${enable_werror+y}
+then :
+ enableval=$enable_werror; case "$enableval" in
+ yes) ;;
+ no) ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-werror: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-werror: $enableval" >&2;}
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-ssp was given.
+if test ${enable_ssp+y}
+then :
+ enableval=$enable_ssp;
+else case e in #(
+ e) enable_ssp=yes ;;
+esac
+fi
+
+
+# Check whether --enable-hardening was given.
+if test ${enable_hardening+y}
+then :
+ enableval=$enable_hardening;
+else case e in #(
+ e) enable_hardening=yes ;;
+esac
+fi
+
+
+# Check whether --enable-pie was given.
+if test ${enable_pie+y}
+then :
+ enableval=$enable_pie;
+fi
+
+
+# Check whether --enable-sanitizer was given.
+if test ${enable_sanitizer+y}
+then :
+ enableval=$enable_sanitizer;
+ if test X"$enable_sanitizer" = X"yes"
+then :
+
+ enable_sanitizer="-fsanitize=address,undefined"
+
+fi
+
+else case e in #(
+ e) enable_sanitizer=no ;;
+esac
+fi
+
+
+# Check whether --enable-fuzzer was given.
+if test ${enable_fuzzer+y}
+then :
+ enableval=$enable_fuzzer;
+else case e in #(
+ e) enable_fuzzer=no ;;
+esac
+fi
+
+
+# Check whether --enable-fuzzer-engine was given.
+if test ${enable_fuzzer_engine+y}
+then :
+ enableval=$enable_fuzzer_engine; case "$enableval" in
+ yes) as_fn_error $? "must give --enable-fuzzer-engine an argument." "$LINENO" 5
+ ;;
+ no) ;;
+ *) FUZZ_ENGINE="$enableval"
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-fuzzer-linker was given.
+if test ${enable_fuzzer_linker+y}
+then :
+ enableval=$enable_fuzzer_linker; case "$enableval" in
+ yes) as_fn_error $? "must give --enable-fuzzer-linker an argument." "$LINENO" 5
+ ;;
+ no) ;;
+ *) FUZZ_LD="$enableval"
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-leaks was given.
+if test ${enable_leaks+y}
+then :
+ enableval=$enable_leaks; case "$enableval" in
+ yes) ;;
+ no) printf "%s\n" "#define NO_LEAKS 1" >>confdefs.h
+
+ ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --disable-leaks: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --disable-leaks: $enableval" >&2;}
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-poll was given.
+if test ${enable_poll+y}
+then :
+ enableval=$enable_poll;
+fi
+
+
+# Check whether --enable-admin-flag was given.
+if test ${enable_admin_flag+y}
+then :
+ enableval=$enable_admin_flag; case "$enableval" in
+ yes) cat >>confdefs.h <<EOF
+#define _PATH_SUDO_ADMIN_FLAG "~/.sudo_as_admin_successful"
+EOF
+
+ ;;
+ no) ;;
+ *) cat >>confdefs.h <<EOF
+#define _PATH_SUDO_ADMIN_FLAG "$enableval"
+EOF
+
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-nls was given.
+if test ${enable_nls+y}
+then :
+ enableval=$enable_nls;
+else case e in #(
+ e) enable_nls=yes ;;
+esac
+fi
+
+
+# Check whether --enable-rpath was given.
+if test ${enable_rpath+y}
+then :
+ enableval=$enable_rpath;
+else case e in #(
+ e) enable_rpath=yes ;;
+esac
+fi
+
+
+# Check whether --enable-static-sudoers was given.
+if test ${enable_static_sudoers+y}
+then :
+ enableval=$enable_static_sudoers;
+else case e in #(
+ e) enable_static_sudoers=no ;;
+esac
+fi
+
+
+# Check whether --enable-shared_libutil was given.
+if test ${enable_shared_libutil+y}
+then :
+ enableval=$enable_shared_libutil;
+else case e in #(
+ e) enable_shared_libutil=yes ;;
+esac
+fi
+
+
+# Check whether --enable-tmpfiles.d was given.
+if test ${enable_tmpfiles_d+y}
+then :
+ enableval=$enable_tmpfiles_d; case $enableval in
+ yes) TMPFILES_D=/usr/lib/tmpfiles.d
+ ;;
+ no) TMPFILES_D=
+ ;;
+ *) TMPFILES_D="$enableval"
+esac
+else case e in #(
+ e)
+ test -f /usr/lib/tmpfiles.d/systemd.conf && TMPFILES_D=/usr/lib/tmpfiles.d
+ ;;
+esac
+fi
+
+
+# Check whether --enable-devsearch was given.
+if test ${enable_devsearch+y}
+then :
+ enableval=$enable_devsearch; case $enableval in
+ yes) # use default value
+ ;;
+ no) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring attempt to disable the device search path" >&5
+printf "%s\n" "$as_me: WARNING: ignoring attempt to disable the device search path" >&2;}
+ ;;
+ *) devsearch="$enableval"
+ ;;
+esac
+fi
+
+ds="`echo \"$devsearch\"|sed 's@/dev/*\([^:]*:*\)@_PATH_DEV \"\1\" @g'`"
+cat >>confdefs.h <<EOF
+#define _PATH_SUDO_DEVSEARCH $ds
+EOF
+
+
+
+# Check whether --with-selinux was given.
+if test ${with_selinux+y}
+then :
+ withval=$with_selinux; case $with_selinux in
+ yes) SELINUX_USAGE="[-r role] [-t type] "
+ printf "%s\n" "#define HAVE_SELINUX 1" >>confdefs.h
+
+ SUDO_LIBS="${SUDO_LIBS} -lselinux"
+ SUDO_OBJS="${SUDO_OBJS} selinux.o"
+ PROGS="${PROGS} sesh"
+ SEMAN=1
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for setkeycreatecon in -lselinux" >&5
+printf %s "checking for setkeycreatecon in -lselinux... " >&6; }
+if test ${ac_cv_lib_selinux_setkeycreatecon+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lselinux $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char setkeycreatecon (void);
+int
+main (void)
+{
+return setkeycreatecon ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_selinux_setkeycreatecon=yes
+else case e in #(
+ e) ac_cv_lib_selinux_setkeycreatecon=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_selinux_setkeycreatecon" >&5
+printf "%s\n" "$ac_cv_lib_selinux_setkeycreatecon" >&6; }
+if test "x$ac_cv_lib_selinux_setkeycreatecon" = xyes
+then :
+ printf "%s\n" "#define HAVE_SETKEYCREATECON 1" >>confdefs.h
+
+fi
+
+ ;;
+ no) ;;
+ *) as_fn_error $? "--with-selinux does not take an argument." "$LINENO" 5
+ ;;
+esac
+else case e in #(
+ e) with_selinux=no ;;
+esac
+fi
+
+
+
+# Check whether --with-apparmor was given.
+if test ${with_apparmor+y}
+then :
+ withval=$with_apparmor; case $with_apparmor in
+ yes) printf "%s\n" "#define HAVE_APPARMOR 1" >>confdefs.h
+
+ AAMAN=1
+ SUDO_LIBS="${SUDO_LIBS} -lapparmor"
+ SUDO_OBJS="${SUDO_OBJS} apparmor.o"
+ ;;
+ no) ;;
+ *) as_fn_error $? "--with-apparmor does not take an argument." "$LINENO" 5
+
+esac
+else case e in #(
+ e) with_apparmor=no ;;
+esac
+fi
+
+
+# Check whether --enable-sasl was given.
+if test ${enable_sasl+y}
+then :
+ enableval=$enable_sasl; case "$enableval" in
+ yes|no) ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-sasl: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-sasl: $enableval" >&2;}
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-timestamp-type was given.
+if test ${enable_timestamp_type+y}
+then :
+ enableval=$enable_timestamp_type; case "$enableval" in
+ global|ppid|tty)
+ timestamp_type=$enableval
+ ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-timestamp-type: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-timestamp-type: $enableval" >&2;}
+ ;;
+ esac
+
+fi
+
+printf "%s\n" "#define TIMESTAMP_TYPE $timestamp_type" >>confdefs.h
+
+
+# Check whether --enable-offensive_insults was given.
+if test ${enable_offensive_insults+y}
+then :
+ enableval=$enable_offensive_insults;
+else case e in #(
+ e) enable_offensive_insults=no ;;
+esac
+fi
+
+if test "$enable_offensive_insults" = "yes"
+then :
+ printf "%s\n" "#define OFFENSIVE_INSULTS 1" >>confdefs.h
+
+fi
+
+# Check whether --enable-package_build was given.
+if test ${enable_package_build+y}
+then :
+ enableval=$enable_package_build;
+else case e in #(
+ e) enable_package_build=no ;;
+esac
+fi
+
+
+# Check whether --enable-gss_krb5_ccache_name was given.
+if test ${enable_gss_krb5_ccache_name+y}
+then :
+ enableval=$enable_gss_krb5_ccache_name; check_gss_krb5_ccache_name=$enableval
+else case e in #(
+ e) check_gss_krb5_ccache_name=no ;;
+esac
+fi
+
+
+# Check whether --enable-pvs-studio was given.
+if test ${enable_pvs_studio+y}
+then :
+ enableval=$enable_pvs_studio;
+fi
+
+
+# Check whether --enable-log-server was given.
+if test ${enable_log_server+y}
+then :
+ enableval=$enable_log_server; case "$enableval" in
+ yes)
+ ;;
+ no)
+ LOGSRV=#
+ LOGSRVD_SRC=
+ LOGSRVD_CONF=
+ ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-log-server: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-log-server: $enableval" >&2;}
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-log-client was given.
+if test ${enable_log_client+y}
+then :
+ enableval=$enable_log_client; case "$enableval" in
+ yes)
+ printf "%s\n" "#define SUDOERS_LOG_CLIENT 1" >>confdefs.h
+
+ ;;
+ no)
+ ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-log-client: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-log-client: $enableval" >&2;}
+ ;;
+ esac
+
+else case e in #(
+ e) printf "%s\n" "#define SUDOERS_LOG_CLIENT 1" >>confdefs.h
+ ;;
+esac
+fi
+
+
+if test X"${enable_log_client}${enable_log_server}" = X"nono"
+then :
+
+ # No need for liblogsrv.la
+ LOGSRV_SRC=
+ LIBLOGSRV=
+
+fi
+if test X"$LOGSRVD_SRC" != X""
+then :
+
+ PPFILES="$PPFILES "'$(srcdir)/etc/sudo-logsrvd.pp'
+
+fi
+
+# Check whether --enable-openssl was given.
+if test ${enable_openssl+y}
+then :
+ enableval=$enable_openssl;
+else case e in #(
+ e)
+ # Enable OpenSSL by default unless logsrvd and client are disabled
+ if test X"${enable_log_client}${enable_log_server}" != X"nono"
+then :
+
+ enable_openssl=maybe
+
+fi
+ ;;
+esac
+fi
+
+# Check whether --enable-openssl-pkgconfig-template was given.
+if test ${enable_openssl_pkgconfig_template+y}
+then :
+ enableval=$enable_openssl_pkgconfig_template;
+else case e in #(
+ e) enable_openssl_pkgconfig_template="%s" ;;
+esac
+fi
+
+
+# Check whether --enable-wolfssl was given.
+if test ${enable_wolfssl+y}
+then :
+ enableval=$enable_wolfssl;
+ enable_openssl=no
+
+fi
+
+
+# Check whether --enable-gcrypt was given.
+if test ${enable_gcrypt+y}
+then :
+ enableval=$enable_gcrypt;
+ if test "${enable_openssl-no}${enable_wolfssl-no}" != "nono"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring --enable-gcrypt when OpenSSL or wolfSSL is enabled." >&5
+printf "%s\n" "$as_me: WARNING: ignoring --enable-gcrypt when OpenSSL or wolfSSL is enabled." >&2;}
+ enable_gcrypt=no
+
+fi
+
+fi
+
+
+# Check whether --enable-python was given.
+if test ${enable_python+y}
+then :
+ enableval=$enable_python; case "$enableval" in
+ yes|no)
+ ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-python: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-python: $enableval" >&2;}
+ ;;
+ esac
+
+fi
+
+
+# Check whether --enable-adminconf was given.
+if test ${enable_adminconf+y}
+then :
+ enableval=$enable_adminconf; case "$enableval" in
+ yes|no)
+ ;;
+ *) adminconfdir="$enableval"
+ enable_adminconf=yes
+ ;;
+ esac
+
+else case e in #(
+ e) enable_adminconf=no ;;
+esac
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+printf %s "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test ${ac_cv_prog_CPP+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) # Double quotes because $CC needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+
+else case e in #(
+ e) # Broken: fails on valid input.
+continue ;;
+esac
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+ # Broken: success on invalid input.
+continue
+else case e in #(
+ e) # Passes both tests.
+ac_preproc_ok=:
+break ;;
+esac
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok
+then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+ ;;
+esac
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+printf "%s\n" "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+
+else case e in #(
+ e) # Broken: fails on valid input.
+continue ;;
+esac
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+ # Broken: success on invalid input.
+continue
+else case e in #(
+ e) # Passes both tests.
+ac_preproc_ok=:
+break ;;
+esac
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok
+then :
+
+else case e in #(
+ e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See 'config.log' for more details" "$LINENO" 5; } ;;
+esac
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_AR+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+printf "%s\n" "$AR" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_AR+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="ar"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+printf "%s\n" "$ac_ct_AR" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_AR" = x; then
+ AR="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_RANLIB+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+printf "%s\n" "$RANLIB" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_RANLIB+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+printf "%s\n" "$ac_ct_RANLIB" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test X"$AR" = X"false"
+then :
+
+ as_fn_error $? "the \"ar\" utility is required to build sudo" "$LINENO" 5
+
+fi
+
+
+
+ # Make sure we can run config.sub.
+$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+printf %s "checking build system type... " >&6; }
+if test ${ac_cv_build+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
+test "x$ac_build_alias" = x &&
+ as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+printf "%s\n" "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+
+
+cross_compiling_build=no
+
+ac_build_tool_prefix=
+if test -n "$build"
+then :
+ ac_build_tool_prefix="$build-"
+elif test -n "$build_alias"
+then :
+ ac_build_tool_prefix="$build_alias-"
+fi
+
+ac_ext=c
+ac_cpp='$CPP_FOR_BUILD $CPPFLAGS_FOR_BUILD'
+ac_compile='$CC_FOR_BUILD -c $CFLAGS_FOR_BUILD $CPPFLAGS_FOR_BUILD conftest.$ac_ext >&5'
+ac_link='$CC_FOR_BUILD -o conftest$ac_build_exeext $CFLAGS_FOR_BUILD $CPPFLAGS_FOR_BUILD $LDFLAGS_FOR_BUILD conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_build_c_compiler_gnu
+
+
+was_set_c_compiler_gnu=${ac_cv_c_compiler_gnu+y}
+if test ${was_set_c_compiler_gnu}
+then :
+ saved_c_compiler_gnu=$ac_cv_c_compiler_gnu
+ { ac_cv_c_compiler_gnu=; unset ac_cv_c_compiler_gnu;}
+fi
+
+ac_ext=c
+ac_cpp='$CPP_FOR_BUILD $CPPFLAGS_FOR_BUILD'
+ac_compile='$CC_FOR_BUILD -c $CFLAGS_FOR_BUILD $CPPFLAGS_FOR_BUILD conftest.$ac_ext >&5'
+ac_link='$CC_FOR_BUILD -o conftest$ac_build_exeext $CFLAGS_FOR_BUILD $CPPFLAGS_FOR_BUILD $LDFLAGS_FOR_BUILD conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_build_c_compiler_gnu
+if test -n "$ac_build_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_build_tool_prefix}gcc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC_FOR_BUILD+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$CC_FOR_BUILD"; then
+ ac_cv_prog_CC_FOR_BUILD="$CC_FOR_BUILD" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC_FOR_BUILD="${ac_build_tool_prefix}gcc"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+CC_FOR_BUILD=$ac_cv_prog_CC_FOR_BUILD
+if test -n "$CC_FOR_BUILD"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC_FOR_BUILD" >&5
+printf "%s\n" "$CC_FOR_BUILD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC_FOR_BUILD"; then
+ ac_ct_CC_FOR_BUILD=$CC_FOR_BUILD
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC_FOR_BUILD+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_CC_FOR_BUILD"; then
+ ac_cv_prog_ac_ct_CC_FOR_BUILD="$ac_ct_CC_FOR_BUILD" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC_FOR_BUILD="gcc"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_CC_FOR_BUILD=$ac_cv_prog_ac_ct_CC_FOR_BUILD
+if test -n "$ac_ct_CC_FOR_BUILD"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC_FOR_BUILD" >&5
+printf "%s\n" "$ac_ct_CC_FOR_BUILD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC_FOR_BUILD" = x; then
+ CC_FOR_BUILD=""
+ else
+ case $cross_compiling_build:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with build triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with build triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC_FOR_BUILD=$ac_ct_CC_FOR_BUILD
+ fi
+else
+ CC_FOR_BUILD="$ac_cv_prog_CC_FOR_BUILD"
+fi
+
+if test -z "$CC_FOR_BUILD"; then
+ if test -n "$ac_build_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_build_tool_prefix}cc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC_FOR_BUILD+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$CC_FOR_BUILD"; then
+ ac_cv_prog_CC_FOR_BUILD="$CC_FOR_BUILD" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC_FOR_BUILD="${ac_build_tool_prefix}cc"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+CC_FOR_BUILD=$ac_cv_prog_CC_FOR_BUILD
+if test -n "$CC_FOR_BUILD"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC_FOR_BUILD" >&5
+printf "%s\n" "$CC_FOR_BUILD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC_FOR_BUILD"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC_FOR_BUILD+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$CC_FOR_BUILD"; then
+ ac_cv_prog_CC_FOR_BUILD="$CC_FOR_BUILD" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC_FOR_BUILD="cc"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC_FOR_BUILD
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC_FOR_BUILD to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC_FOR_BUILD="$as_dir$ac_word${1+' '}$@"
+ fi
+fi
+fi ;;
+esac
+fi
+CC_FOR_BUILD=$ac_cv_prog_CC_FOR_BUILD
+if test -n "$CC_FOR_BUILD"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC_FOR_BUILD" >&5
+printf "%s\n" "$CC_FOR_BUILD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC_FOR_BUILD"; then
+ if test -n "$ac_build_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_build_tool_prefix$ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC_FOR_BUILD+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$CC_FOR_BUILD"; then
+ ac_cv_prog_CC_FOR_BUILD="$CC_FOR_BUILD" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC_FOR_BUILD="$ac_build_tool_prefix$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+CC_FOR_BUILD=$ac_cv_prog_CC_FOR_BUILD
+if test -n "$CC_FOR_BUILD"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC_FOR_BUILD" >&5
+printf "%s\n" "$CC_FOR_BUILD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$CC_FOR_BUILD" && break
+ done
+fi
+if test -z "$CC_FOR_BUILD"; then
+ ac_ct_CC_FOR_BUILD=$CC_FOR_BUILD
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC_FOR_BUILD+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_CC_FOR_BUILD"; then
+ ac_cv_prog_ac_ct_CC_FOR_BUILD="$ac_ct_CC_FOR_BUILD" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC_FOR_BUILD="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_CC_FOR_BUILD=$ac_cv_prog_ac_ct_CC_FOR_BUILD
+if test -n "$ac_ct_CC_FOR_BUILD"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC_FOR_BUILD" >&5
+printf "%s\n" "$ac_ct_CC_FOR_BUILD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC_FOR_BUILD" && break
+done
+
+ if test "x$ac_ct_CC_FOR_BUILD" = x; then
+ CC_FOR_BUILD=""
+ else
+ case $cross_compiling_build:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with build triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with build triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC_FOR_BUILD=$ac_ct_CC_FOR_BUILD
+ fi
+fi
+
+fi
+if test -z "$CC_FOR_BUILD"; then
+ if test -n "$ac_build_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+set dummy ${ac_build_tool_prefix}clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC_FOR_BUILD+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$CC_FOR_BUILD"; then
+ ac_cv_prog_CC_FOR_BUILD="$CC_FOR_BUILD" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC_FOR_BUILD="${ac_build_tool_prefix}clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+CC_FOR_BUILD=$ac_cv_prog_CC_FOR_BUILD
+if test -n "$CC_FOR_BUILD"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC_FOR_BUILD" >&5
+printf "%s\n" "$CC_FOR_BUILD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC_FOR_BUILD"; then
+ ac_ct_CC_FOR_BUILD=$CC_FOR_BUILD
+ # Extract the first word of "clang", so it can be a program name with args.
+set dummy clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC_FOR_BUILD+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_CC_FOR_BUILD"; then
+ ac_cv_prog_ac_ct_CC_FOR_BUILD="$ac_ct_CC_FOR_BUILD" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC_FOR_BUILD="clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_CC_FOR_BUILD=$ac_cv_prog_ac_ct_CC_FOR_BUILD
+if test -n "$ac_ct_CC_FOR_BUILD"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC_FOR_BUILD" >&5
+printf "%s\n" "$ac_ct_CC_FOR_BUILD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC_FOR_BUILD" = x; then
+ CC_FOR_BUILD=""
+ else
+ case $cross_compiling_build:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with build triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with build triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC_FOR_BUILD=$ac_ct_CC_FOR_BUILD
+ fi
+else
+ CC_FOR_BUILD="$ac_cv_prog_CC_FOR_BUILD"
+fi
+
+fi
+
+
+test -z "$CC_FOR_BUILD" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See 'config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion -version; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+printf %s "checking whether the compiler supports GNU C... " >&6; }
+if test ${ac_cv_c_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_compiler_gnu=yes
+else case e in #(
+ e) ac_compiler_gnu=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_build_objext conftest.beam conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+if test $ac_compiler_gnu = yes; then
+ GCC_FOR_BUILD=yes
+else
+ GCC_FOR_BUILD=
+fi
+ac_test_CFLAGS=${CFLAGS_FOR_BUILD+y}
+ac_save_CFLAGS=$CFLAGS_FOR_BUILD
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC_FOR_BUILD accepts -g" >&5
+printf %s "checking whether $CC_FOR_BUILD accepts -g... " >&6; }
+if test ${ac_cv_build_prog_cc_g+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_build_prog_cc_g=no
+ CFLAGS_FOR_BUILD="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_build_prog_cc_g=yes
+else case e in #(
+ e) CFLAGS_FOR_BUILD=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else case e in #(
+ e) ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS_FOR_BUILD="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_build_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_build_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_build_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_build_objext conftest.beam conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build_prog_cc_g" >&5
+printf "%s\n" "$ac_cv_build_prog_cc_g" >&6; }
+if test $ac_test_CFLAGS; then
+ CFLAGS_FOR_BUILD=$ac_save_CFLAGS
+elif test $ac_cv_build_prog_cc_g = yes; then
+ if test "$GCC_FOR_BUILD" = yes; then
+ CFLAGS_FOR_BUILD="-g -O2"
+ else
+ CFLAGS_FOR_BUILD="-g"
+ fi
+else
+ if test "$GCC_FOR_BUILD" = yes; then
+ CFLAGS_FOR_BUILD="-O2"
+ else
+ CFLAGS_FOR_BUILD=
+ fi
+fi
+ac_prog_cc_stdc=no
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC_FOR_BUILD option to enable C11 features" >&5
+printf %s "checking for $CC_FOR_BUILD option to enable C11 features... " >&6; }
+if test ${ac_cv_build_prog_cc_c11+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_cv_build_prog_cc_c11=no
+ac_save_CC=$CC_FOR_BUILD
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c11_program
+_ACEOF
+for ac_arg in '' -std=gnu11
+do
+ CC_FOR_BUILD="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_build_prog_cc_c11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_build_objext conftest.beam
+ test "x$ac_cv_build_prog_cc_c11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC_FOR_BUILD=$ac_save_CC ;;
+esac
+fi
+
+if test "x$ac_cv_build_prog_cc_c11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else case e in #(
+ e) if test "x$ac_cv_build_prog_cc_c11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build_prog_cc_c11" >&5
+printf "%s\n" "$ac_cv_build_prog_cc_c11" >&6; }
+ CC_FOR_BUILD="$CC_FOR_BUILD $ac_cv_build_prog_cc_c11" ;;
+esac
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_build_prog_cc_c11
+ ac_prog_cc_stdc=c11 ;;
+esac
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC_FOR_BUILD option to enable C99 features" >&5
+printf %s "checking for $CC_FOR_BUILD option to enable C99 features... " >&6; }
+if test ${ac_cv_build_prog_cc_c99+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_cv_build_prog_cc_c99=no
+ac_save_CC=$CC_FOR_BUILD
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c99_program
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+do
+ CC_FOR_BUILD="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_build_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_build_objext conftest.beam
+ test "x$ac_cv_build_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC_FOR_BUILD=$ac_save_CC ;;
+esac
+fi
+
+if test "x$ac_cv_build_prog_cc_c99" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else case e in #(
+ e) if test "x$ac_cv_build_prog_cc_c99" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build_prog_cc_c99" >&5
+printf "%s\n" "$ac_cv_build_prog_cc_c99" >&6; }
+ CC_FOR_BUILD="$CC_FOR_BUILD $ac_cv_build_prog_cc_c99" ;;
+esac
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_build_prog_cc_c99
+ ac_prog_cc_stdc=c99 ;;
+esac
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC_FOR_BUILD option to enable C89 features" >&5
+printf %s "checking for $CC_FOR_BUILD option to enable C89 features... " >&6; }
+if test ${ac_cv_build_prog_cc_c89+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_cv_build_prog_cc_c89=no
+ac_save_CC=$CC_FOR_BUILD
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c89_program
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC_FOR_BUILD="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_build_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_build_objext conftest.beam
+ test "x$ac_cv_build_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC_FOR_BUILD=$ac_save_CC ;;
+esac
+fi
+
+if test "x$ac_cv_build_prog_cc_c89" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else case e in #(
+ e) if test "x$ac_cv_build_prog_cc_c89" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build_prog_cc_c89" >&5
+printf "%s\n" "$ac_cv_build_prog_cc_c89" >&6; }
+ CC_FOR_BUILD="$CC_FOR_BUILD $ac_cv_build_prog_cc_c89" ;;
+esac
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_build_prog_cc_c89
+ ac_prog_cc_stdc=c89 ;;
+esac
+fi
+fi
+
+ac_ext=c
+ac_cpp='$CPP_FOR_BUILD $CPPFLAGS_FOR_BUILD'
+ac_compile='$CC_FOR_BUILD -c $CFLAGS_FOR_BUILD $CPPFLAGS_FOR_BUILD conftest.$ac_ext >&5'
+ac_link='$CC_FOR_BUILD -o conftest$ac_build_exeext $CFLAGS_FOR_BUILD $CPPFLAGS_FOR_BUILD $LDFLAGS_FOR_BUILD conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_build_c_compiler_gnu
+
+
+if test ${was_set_c_compiler_gnu}
+then :
+ ac_cv_c_compiler_gnu=$saved_c_compiler_gnu
+fi
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+printf %s "checking whether the C compiler works... " >&6; }
+ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to 'no'.
+# So ignore a value of 'no', otherwise this would lead to 'EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test ${ac_cv_build_exeext+y} && test "$ac_cv_build_exeext" != no;
+ then :; else
+ ac_cv_build_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an '-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_build_exeext" = no && ac_cv_build_exeext=
+
+else case e in #(
+ e) ac_file='' ;;
+esac
+fi
+if test -z "$ac_file"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See 'config.log' for more details" "$LINENO" 5; }
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; } ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+printf %s "checking for C compiler default output file name... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+printf "%s\n" "$ac_file" >&6; }
+ac_build_exeext=$ac_cv_build_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_build_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+printf %s "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
+ # If both 'conftest.exe' and 'conftest' are 'present' (well, observable)
+# catch 'conftest.exe'. For instance with Cygwin, 'ls conftest' will
+# work properly (i.e., refer to 'conftest.exe'), while it won't with
+# 'rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_build_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else case e in #(
+ e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See 'config.log' for more details" "$LINENO" 5; } ;;
+esac
+fi
+rm -f conftest conftest$ac_cv_build_exeext
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build_exeext" >&5
+printf "%s\n" "$ac_cv_build_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_build_exeext
+ac_build_exeext=$BUILD_EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main (void)
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+printf %s "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling_build" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_build_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling_build=no
+ else
+ if test "$cross_compiling_build" = maybe; then
+ cross_compiling_build=yes
+ else
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error 77 "cannot run C compiled programs.
+If you meant to cross compile, use '--build'.
+See 'config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling_build" >&5
+printf "%s\n" "$cross_compiling_build" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_build_exeext \
+ conftest.o conftest.obj conftest.out
+ac_clean_files=$ac_clean_files_save
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+printf %s "checking for suffix of object files... " >&6; }
+if test ${ac_cv_build_objext+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_build_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else case e in #(
+ e) printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See 'config.log' for more details" "$LINENO" 5; } ;;
+esac
+fi
+rm -f conftest.$ac_cv_build_objext conftest.$ac_ext ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build_objext" >&5
+printf "%s\n" "$ac_cv_build_objext" >&6; }
+OBJEXT=$ac_cv_build_objext
+ac_build_objext=$BUILD_OBJEXT
+
+ac_ext=c
+ac_cpp='$CPP_FOR_BUILD $CPPFLAGS_FOR_BUILD'
+ac_compile='$CC_FOR_BUILD -c $CFLAGS_FOR_BUILD $CPPFLAGS_FOR_BUILD conftest.$ac_ext >&5'
+ac_link='$CC_FOR_BUILD -o conftest$ac_build_exeext $CFLAGS_FOR_BUILD $CPPFLAGS_FOR_BUILD $LDFLAGS_FOR_BUILD conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_build_c_compiler_gnu
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+printf %s "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP_FOR_BUILD" && test -d "$CPP_FOR_BUILD"; then
+ CPP_FOR_BUILD=
+fi
+if test -z "$CPP_FOR_BUILD"; then
+ if test ${ac_cv_build_prog_CPP+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) # Double quotes because $CC needs to be expanded
+ for CPP_FOR_BUILD in "$CC_FOR_BUILD -E" "$CC_FOR_BUILD -E -traditional-cpp" cpp /lib/cpp
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+
+else case e in #(
+ e) # Broken: fails on valid input.
+continue ;;
+esac
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+ # Broken: success on invalid input.
+continue
+else case e in #(
+ e) # Passes both tests.
+ac_preproc_ok=:
+break ;;
+esac
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok
+then :
+ break
+fi
+
+ done
+ ac_cv_build_prog_CPP=$CPP_FOR_BUILD
+ ;;
+esac
+fi
+ CPP_FOR_BUILD=$ac_cv_build_prog_CPP
+else
+ ac_cv_build_prog_CPP=$CPP_FOR_BUILD
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP_FOR_BUILD" >&5
+printf "%s\n" "$CPP_FOR_BUILD" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+
+else case e in #(
+ e) # Broken: fails on valid input.
+continue ;;
+esac
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+ # Broken: success on invalid input.
+continue
+else case e in #(
+ e) # Passes both tests.
+ac_preproc_ok=:
+break ;;
+esac
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of 'break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok
+then :
+
+else case e in #(
+ e) { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP_FOR_BUILD\" fails sanity check
+See 'config.log' for more details" "$LINENO" 5; } ;;
+esac
+fi
+
+ac_ext=c
+ac_cpp='$CPP_FOR_BUILD $CPPFLAGS_FOR_BUILD'
+ac_compile='$CC_FOR_BUILD -c $CFLAGS_FOR_BUILD $CPPFLAGS_FOR_BUILD conftest.$ac_ext >&5'
+ac_link='$CC_FOR_BUILD -o conftest$ac_build_exeext $CFLAGS_FOR_BUILD $CPPFLAGS_FOR_BUILD $LDFLAGS_FOR_BUILD conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_build_c_compiler_gnu
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+if test "x$ac_cv_prog_cc_c89" = "xno"
+then :
+
+ as_fn_error $? "Sudo version $PACKAGE_VERSION requires an ANSI C compiler to build." "$LINENO" 5
+
+fi
+
+if test "$enable_static" = "no"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring --disable-static, sudo does not install static libs" >&5
+printf "%s\n" "$as_me: WARNING: ignoring --disable-static, sudo does not install static libs" >&2;}
+ enable_static=yes
+
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+printf %s "checking host system type... " >&6; }
+if test ${ac_cv_host+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
+fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+printf "%s\n" "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+
+
+ if test X"$enable_pvs_studio" = X"yes"; then
+ # Determine preprocessor type
+ case "$CC" in
+ *clang*) preprocessor=clang;;
+ *gcc*) preprocessor=gcc;;
+ *) case `$CC --version 2>&1` in
+ *clang*) preprocessor=clang;;
+ *gcc*) preprocessor=gcc;;
+ *) as_fn_error $? "Compiler must be gcc or clang for PVS-Studio." "$LINENO" 5;;
+ esac
+ ;;
+ esac
+
+ # Determine platform (currently linux or macos)
+ case "$host" in
+ x86_64-*-linux*) pvs_platform=linux64;;
+ *86-*-linux*) pvs_platform=linux32;;
+ *-*-darwin*) pvs_platform=macos;;
+ *) as_fn_error $? "PVS-Studio does not support $host." "$LINENO" 5;;
+ esac
+
+ # Create a basic PVS-Studio.cfg file
+ cat > PVS-Studio.cfg <<-EOF
+ preprocessor = $preprocessor
+ platform = $pvs_platform
+ analysis-mode = 4
+ language = C
+ EOF
+
+ # Check for a license file in the default location
+ if test -f "$HOME/.config/PVS-Studio/PVS-Studio.lic"; then
+ echo "lic-file = $HOME/.config/PVS-Studio/PVS-Studio.lic" >> PVS-Studio.cfg
+ fi
+ fi
+
+
+case "$host_os" in
+hpux11.1[1-9]|hpux11.[2-9][0-9]|hpux1[2-9].*)
+ # Prefer dlopen() over shl_load()
+ : ${ac_cv_func_shl_load='no'}
+ : ${ac_cv_lib_dld_shl_load='no'}
+ ;;
+esac
+
+
+
+case `pwd` in
+ *\ * | *\ *)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+printf "%s\n" "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
+esac
+
+
+
+macro_version='2.4.7'
+macro_revision='2.4.7'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ltmain=$ac_aux_dir/ltmain.sh
+
+# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
+printf %s "checking how to print strings... " >&6; }
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='printf %s\n'
+else
+ # Use this function as a fallback that always works.
+ func_fallback_echo ()
+ {
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+ }
+ ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+ $ECHO ""
+}
+
+case $ECHO in
+ printf*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: printf" >&5
+printf "%s\n" "printf" >&6; } ;;
+ print*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
+printf "%s\n" "print -r" >&6; } ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cat" >&5
+printf "%s\n" "cat" >&6; } ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+printf %s "checking for a sed that does not truncate output... " >&6; }
+if test ${ac_cv_path_SED+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+ for ac_i in 1 2 3 4 5 6 7; do
+ ac_script="$ac_script$as_nl$ac_script"
+ done
+ echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+ { ac_script=; unset ac_script;}
+ if test -z "$SED"; then
+ ac_path_SED_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in sed gsed
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_SED="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_SED" || continue
+# Check for GNU ac_path_SED and select it if it is found.
+ # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in #(
+*GNU*)
+ ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+#(
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" '' >> "conftest.nl"
+ "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_SED_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_SED="$ac_path_SED"
+ ac_path_SED_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_SED_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_SED"; then
+ as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
+ fi
+else
+ ac_cv_path_SED=$SED
+fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+printf "%s\n" "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+ rm -f conftest.sed
+
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+
+
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+printf %s "checking for grep that handles long lines and -e... " >&6; }
+if test ${ac_cv_path_GREP+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in grep ggrep
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in #(
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+#(
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+printf "%s\n" "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+printf %s "checking for egrep... " >&6; }
+if test ${ac_cv_path_EGREP+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in egrep
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in #(
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+#(
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+printf "%s\n" "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+ EGREP_TRADITIONAL=$EGREP
+ ac_cv_path_EGREP_TRADITIONAL=$EGREP
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
+printf %s "checking for fgrep... " >&6; }
+if test ${ac_cv_path_FGREP+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
+ then ac_cv_path_FGREP="$GREP -F"
+ else
+ if test -z "$FGREP"; then
+ ac_path_FGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in fgrep
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_FGREP="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_FGREP" || continue
+# Check for GNU ac_path_FGREP and select it if it is found.
+ # Check for GNU $ac_path_FGREP
+case `"$ac_path_FGREP" --version 2>&1` in #(
+*GNU*)
+ ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
+#(
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" 'FGREP' >> "conftest.nl"
+ "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_FGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_FGREP="$ac_path_FGREP"
+ ac_path_FGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_FGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_FGREP"; then
+ as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_FGREP=$FGREP
+fi
+
+ fi ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
+printf "%s\n" "$ac_cv_path_FGREP" >&6; }
+ FGREP="$ac_cv_path_FGREP"
+
+
+test -z "$GREP" && GREP=grep
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-gnu-ld was given.
+if test ${with_gnu_ld+y}
+then :
+ withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes
+else case e in #(
+ e) with_gnu_ld=no ;;
+esac
+fi
+
+ac_prog=ld
+if test yes = "$GCC"; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+printf %s "checking for ld used by $CC... " >&6; }
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return, which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+ while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD=$ac_prog
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test yes = "$with_gnu_ld"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+printf %s "checking for GNU ld... " >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+printf %s "checking for non-GNU ld... " >&6; }
+fi
+if test ${lt_cv_path_LD+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -z "$LD"; then
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD=$ac_dir/$ac_prog
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test no != "$with_gnu_ld" && break
+ ;;
+ *)
+ test yes != "$with_gnu_ld" && break
+ ;;
+ esac
+ fi
+ done
+ IFS=$lt_save_ifs
+else
+ lt_cv_path_LD=$LD # Let the user override the test with a path.
+fi ;;
+esac
+fi
+
+LD=$lt_cv_path_LD
+if test -n "$LD"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+printf "%s\n" "$LD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+printf %s "checking if the linker ($LD) is GNU ld... " >&6; }
+if test ${lt_cv_prog_gnu_ld+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
+printf "%s\n" "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
+printf %s "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
+if test ${lt_cv_path_NM+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM=$NM
+else
+ lt_nm_to_check=${ac_tool_prefix}nm
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm=$ac_dir/$lt_tmp_nm
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the 'sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
+ case $build_os in
+ mingw*) lt_bad_file=conftest.nm/nofile ;;
+ *) lt_bad_file=/dev/null ;;
+ esac
+ case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
+ *$lt_bad_file* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break 2
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break 2
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS=$lt_save_ifs
+ done
+ : ${lt_cv_path_NM=no}
+fi ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
+printf "%s\n" "$lt_cv_path_NM" >&6; }
+if test no != "$lt_cv_path_NM"; then
+ NM=$lt_cv_path_NM
+else
+ # Didn't find any BSD compatible name lister, look for dumpbin.
+ if test -n "$DUMPBIN"; then :
+ # Let the user override the test.
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in dumpbin "link -dump"
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_DUMPBIN+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$DUMPBIN"; then
+ ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+DUMPBIN=$ac_cv_prog_DUMPBIN
+if test -n "$DUMPBIN"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
+printf "%s\n" "$DUMPBIN" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$DUMPBIN" && break
+ done
+fi
+if test -z "$DUMPBIN"; then
+ ac_ct_DUMPBIN=$DUMPBIN
+ for ac_prog in dumpbin "link -dump"
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_DUMPBIN+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_DUMPBIN"; then
+ ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
+if test -n "$ac_ct_DUMPBIN"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
+printf "%s\n" "$ac_ct_DUMPBIN" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_DUMPBIN" && break
+done
+
+ if test "x$ac_ct_DUMPBIN" = x; then
+ DUMPBIN=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ DUMPBIN=$ac_ct_DUMPBIN
+ fi
+fi
+
+ case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
+ *COFF*)
+ DUMPBIN="$DUMPBIN -symbols -headers"
+ ;;
+ *)
+ DUMPBIN=:
+ ;;
+ esac
+ fi
+
+ if test : != "$DUMPBIN"; then
+ NM=$DUMPBIN
+ fi
+fi
+test -z "$NM" && NM=nm
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
+printf %s "checking the name lister ($NM) interface... " >&6; }
+if test ${lt_cv_nm_interface+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_nm_interface="BSD nm"
+ echo "int some_variable = 0;" > conftest.$ac_ext
+ (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
+ (eval "$ac_compile" 2>conftest.err)
+ cat conftest.err >&5
+ (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+ cat conftest.err >&5
+ (eval echo "\"\$as_me:$LINENO: output\"" >&5)
+ cat conftest.out >&5
+ if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+ lt_cv_nm_interface="MS dumpbin"
+ fi
+ rm -f conftest* ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
+printf "%s\n" "$lt_cv_nm_interface" >&6; }
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+printf %s "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+printf "%s\n" "no, using $LN_S" >&6; }
+fi
+
+# find the maximum length of command line arguments
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
+printf %s "checking the maximum length of command line arguments... " >&6; }
+if test ${lt_cv_sys_max_cmd_len+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) i=0
+ teststring=ABCD
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw* | cegcc*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ mint*)
+ # On MiNT this can take a long time and run out of memory.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ os2*)
+ # The test takes a long time on OS/2.
+ lt_cv_sys_max_cmd_len=8192
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[ ]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+ if test -n "$lt_cv_sys_max_cmd_len" && \
+ test undefined != "$lt_cv_sys_max_cmd_len"; then
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ else
+ # Make teststring a little bigger before we do anything with it.
+ # a 1K string should be a reasonable start.
+ for i in 1 2 3 4 5 6 7 8; do
+ teststring=$teststring$teststring
+ done
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ while { test X`env echo "$teststring$teststring" 2>/dev/null` \
+ = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+ test 17 != "$i" # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ # Only check the string length outside the loop.
+ lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on
+ # massive amounts of additional arguments before passing them to the
+ # linker. It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ fi
+ ;;
+ esac
+ ;;
+esac
+fi
+
+if test -n "$lt_cv_sys_max_cmd_len"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
+printf "%s\n" "$lt_cv_sys_max_cmd_len" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5
+printf "%s\n" "none" >&6; }
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+
+
+
+
+
+: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ lt_unset=unset
+else
+ lt_unset=false
+fi
+
+
+
+
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+ lt_SP2NL='tr \040 \012'
+ lt_NL2SP='tr \015\012 \040\040'
+ ;;
+ *) # EBCDIC based system
+ lt_SP2NL='tr \100 \n'
+ lt_NL2SP='tr \r\n \100\100'
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5
+printf %s "checking how to convert $build file names to $host format... " >&6; }
+if test ${lt_cv_to_host_file_cmd+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) case $host in
+ *-*-mingw* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+ ;;
+ *-*-cygwin* )
+ lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+ ;;
+ * ) # otherwise, assume *nix
+ lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+ ;;
+ esac
+ ;;
+ *-*-cygwin* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+ ;;
+ *-*-cygwin* )
+ lt_cv_to_host_file_cmd=func_convert_file_noop
+ ;;
+ * ) # otherwise, assume *nix
+ lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+ ;;
+ esac
+ ;;
+ * ) # unhandled hosts (and "normal" native builds)
+ lt_cv_to_host_file_cmd=func_convert_file_noop
+ ;;
+esac
+ ;;
+esac
+fi
+
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5
+printf "%s\n" "$lt_cv_to_host_file_cmd" >&6; }
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5
+printf %s "checking how to convert $build file names to toolchain format... " >&6; }
+if test ${lt_cv_to_tool_file_cmd+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) #assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+ *-*-mingw* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+ ;;
+ esac
+ ;;
+esac
+ ;;
+esac
+fi
+
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5
+printf "%s\n" "$lt_cv_to_tool_file_cmd" >&6; }
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
+printf %s "checking for $LD option to reload object files... " >&6; }
+if test ${lt_cv_ld_reload_flag+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_ld_reload_flag='-r' ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
+printf "%s\n" "$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ if test yes != "$GCC"; then
+ reload_cmds=false
+ fi
+ ;;
+ darwin*)
+ if test yes = "$GCC"; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}file", so it can be a program name with args.
+set dummy ${ac_tool_prefix}file; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_FILECMD+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$FILECMD"; then
+ ac_cv_prog_FILECMD="$FILECMD" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_FILECMD="${ac_tool_prefix}file"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+FILECMD=$ac_cv_prog_FILECMD
+if test -n "$FILECMD"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FILECMD" >&5
+printf "%s\n" "$FILECMD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_FILECMD"; then
+ ac_ct_FILECMD=$FILECMD
+ # Extract the first word of "file", so it can be a program name with args.
+set dummy file; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_FILECMD+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_FILECMD"; then
+ ac_cv_prog_ac_ct_FILECMD="$ac_ct_FILECMD" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_FILECMD="file"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_FILECMD=$ac_cv_prog_ac_ct_FILECMD
+if test -n "$ac_ct_FILECMD"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_FILECMD" >&5
+printf "%s\n" "$ac_ct_FILECMD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_FILECMD" = x; then
+ FILECMD=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ FILECMD=$ac_ct_FILECMD
+ fi
+else
+ FILECMD="$ac_cv_prog_FILECMD"
+fi
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_OBJDUMP+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$OBJDUMP"; then
+ ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+printf "%s\n" "$OBJDUMP" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+ ac_ct_OBJDUMP=$OBJDUMP
+ # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_OBJDUMP+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_OBJDUMP"; then
+ ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_OBJDUMP="objdump"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+printf "%s\n" "$ac_ct_OBJDUMP" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_OBJDUMP" = x; then
+ OBJDUMP="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OBJDUMP=$ac_ct_OBJDUMP
+ fi
+else
+ OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
+printf %s "checking how to recognize dependent libraries... " >&6; }
+if test ${lt_cv_deplibs_check_method+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# 'unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# that responds to the $file_magic_cmd with a given extended regex.
+# If you have 'file' or equivalent on your system and you're not sure
+# whether 'pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[4-9]*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[45]*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='$FILECMD -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump',
+ # unless we find 'file', for example because we are cross-compiling.
+ if ( file / ) >/dev/null 2>&1; then
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ else
+ # Keep this pattern in sync with the one in func_win32_libid.
+ lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ fi
+ ;;
+
+cegcc*)
+ # use the weaker test based on 'objdump'. See mingw*.
+ lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | dragonfly* | midnightbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=$FILECMD
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+haiku*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+interix[3-9]*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=$FILECMD
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+*nto* | *qnx*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+openbsd* | bitrig*)
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+rdos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+tpf*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+os2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
+printf "%s\n" "$lt_cv_deplibs_check_method" >&6; }
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+ case $host_os in
+ mingw* | pw32*)
+ if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+ want_nocaseglob=yes
+ else
+ file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"`
+ fi
+ ;;
+ esac
+fi
+
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_DLLTOOL+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$DLLTOOL"; then
+ ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+DLLTOOL=$ac_cv_prog_DLLTOOL
+if test -n "$DLLTOOL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
+printf "%s\n" "$DLLTOOL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DLLTOOL"; then
+ ac_ct_DLLTOOL=$DLLTOOL
+ # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_DLLTOOL+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_DLLTOOL"; then
+ ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_DLLTOOL="dlltool"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
+if test -n "$ac_ct_DLLTOOL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
+printf "%s\n" "$ac_ct_DLLTOOL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_DLLTOOL" = x; then
+ DLLTOOL="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ DLLTOOL=$ac_ct_DLLTOOL
+ fi
+else
+ DLLTOOL="$ac_cv_prog_DLLTOOL"
+fi
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5
+printf %s "checking how to associate runtime and link libraries... " >&6; }
+if test ${lt_cv_sharedlib_from_linklib_cmd+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+ # two different shell functions defined in ltmain.sh;
+ # decide which one to use based on capabilities of $DLLTOOL
+ case `$DLLTOOL --help 2>&1` in
+ *--identify-strict*)
+ lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+ ;;
+ *)
+ lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+ ;;
+ esac
+ ;;
+*)
+ # fallback: assume linklib IS sharedlib
+ lt_cv_sharedlib_from_linklib_cmd=$ECHO
+ ;;
+esac
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5
+printf "%s\n" "$lt_cv_sharedlib_from_linklib_cmd" >&6; }
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in ar
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_AR+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+printf "%s\n" "$AR" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$AR" && break
+ done
+fi
+if test -z "$AR"; then
+ ac_ct_AR=$AR
+ for ac_prog in ar
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_AR+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+printf "%s\n" "$ac_ct_AR" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_AR" && break
+done
+
+ if test "x$ac_ct_AR" = x; then
+ AR="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+fi
+
+: ${AR=ar}
+
+
+
+
+
+
+# Use ARFLAGS variable as AR's operation code to sync the variable naming with
+# Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
+# higher priority because thats what people were doing historically (setting
+# ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS
+# variable obsoleted/removed.
+
+test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
+lt_ar_flags=$AR_FLAGS
+
+
+
+
+
+
+# Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override
+# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5
+printf %s "checking for archiver @FILE support... " >&6; }
+if test ${lt_cv_ar_at_file+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_ar_at_file=no
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ echo conftest.$ac_objext > conftest.lst
+ lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+ (eval $lt_ar_try) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if test 0 -eq "$ac_status"; then
+ # Ensure the archiver fails upon bogus file names.
+ rm -f conftest.$ac_objext libconftest.a
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+ (eval $lt_ar_try) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if test 0 -ne "$ac_status"; then
+ lt_cv_ar_at_file=@
+ fi
+ fi
+ rm -f conftest.* libconftest.a
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5
+printf "%s\n" "$lt_cv_ar_at_file" >&6; }
+
+if test no = "$lt_cv_ar_at_file"; then
+ archiver_list_spec=
+else
+ archiver_list_spec=$lt_cv_ar_at_file
+fi
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_STRIP+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+printf "%s\n" "$STRIP" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_STRIP+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+printf "%s\n" "$ac_ct_STRIP" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+test -z "$STRIP" && STRIP=:
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_RANLIB+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+printf "%s\n" "$RANLIB" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_RANLIB+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+printf "%s\n" "$ac_ct_RANLIB" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+test -z "$RANLIB" && RANLIB=:
+
+
+
+
+
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ bitrig* | openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
+fi
+
+case $host_os in
+ darwin*)
+ lock_old_archive_extraction=yes ;;
+ *)
+ lock_old_archive_extraction=no ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_AWK+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AWK="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+printf "%s\n" "$AWK" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
+printf %s "checking command to parse $NM output from $compiler object... " >&6; }
+if test ${lt_cv_sys_global_symbol_pipe+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[BCDT]'
+ ;;
+cygwin* | mingw* | pw32* | cegcc*)
+ symcode='[ABCDGISTW]'
+ ;;
+hpux*)
+ if test ia64 = "$host_cpu"; then
+ symcode='[ABCDEGRST]'
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[BCDEGRST]'
+ ;;
+osf*)
+ symcode='[BCDEGQRST]'
+ ;;
+solaris*)
+ symcode='[BDRT]'
+ ;;
+sco3.2v5*)
+ symcode='[DT]'
+ ;;
+sysv4.2uw2*)
+ symcode='[DT]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[ABDT]'
+ ;;
+sysv4)
+ symcode='[DFNSTU]'
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[ABCDGIRSTW]' ;;
+esac
+
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Gets list of data symbols to import.
+ lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'"
+ # Adjust the below global symbol transforms to fixup imported variables.
+ lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
+ lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'"
+ lt_c_name_lib_hook="\
+ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\
+ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'"
+else
+ # Disable hooks by default.
+ lt_cv_sys_global_symbol_to_import=
+ lt_cdecl_hook=
+ lt_c_name_hook=
+ lt_c_name_lib_hook=
+fi
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
+$lt_cdecl_hook\
+" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
+$lt_c_name_hook\
+" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'"
+
+# Transform an extracted symbol line into symbol name with lib prefix and
+# symbol address.
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
+$lt_c_name_lib_hook\
+" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Fake it for dumpbin and say T for any non-static function,
+ # D for any global variable and I for any imported variable.
+ # Also find C++ and __fastcall symbols from MSVC++ or ICC,
+ # which start with @ or ?.
+ lt_cv_sys_global_symbol_pipe="$AWK '"\
+" {last_section=section; section=\$ 3};"\
+" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
+" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
+" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
+" \$ 0!~/External *\|/{next};"\
+" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+" {if(hide[section]) next};"\
+" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
+" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
+" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
+" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
+" ' prfx=^$ac_symprfx"
+ else
+ lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+ fi
+ lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5
+ (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+ if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */
+#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
+/* DATA imports from DLLs on WIN32 can't be const, because runtime
+ relocations are performed -- see ld's documentation on pseudo-relocs. */
+# define LT_DLSYM_CONST
+#elif defined __osf__
+/* This system does not cope well with relocations in const data. */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+ cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols. */
+LT_DLSYM_CONST struct {
+ const char *name;
+ void *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[] =
+{
+ { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+ $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+ cat <<\_LT_EOF >> conftest.$ac_ext
+ {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_globsym_save_LIBS=$LIBS
+ lt_globsym_save_CFLAGS=$CFLAGS
+ LIBS=conftstm.$ac_objext
+ CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s conftest$ac_exeext; then
+ pipe_works=yes
+ fi
+ LIBS=$lt_globsym_save_LIBS
+ CFLAGS=$lt_globsym_save_CFLAGS
+ else
+ echo "cannot find nm_test_func in $nlist" >&5
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&5
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+ fi
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ fi
+ rm -rf conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test yes = "$pipe_works"; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+ ;;
+esac
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+printf "%s\n" "failed" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+printf "%s\n" "ok" >&6; }
+fi
+
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then
+ nm_file_list_spec='@'
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5
+printf %s "checking for sysroot... " >&6; }
+
+# Check whether --with-sysroot was given.
+if test ${with_sysroot+y}
+then :
+ withval=$with_sysroot;
+else case e in #(
+ e) with_sysroot=no ;;
+esac
+fi
+
+
+lt_sysroot=
+case $with_sysroot in #(
+ yes)
+ if test yes = "$GCC"; then
+ lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+ fi
+ ;; #(
+ /*)
+ lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
+ ;; #(
+ no|'')
+ ;; #(
+ *)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5
+printf "%s\n" "$with_sysroot" >&6; }
+ as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5
+ ;;
+esac
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5
+printf "%s\n" "${lt_sysroot:-no}" >&6; }
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5
+printf %s "checking for a working dd... " >&6; }
+if test ${ac_cv_path_lt_DD+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+: ${lt_DD:=$DD}
+if test -z "$lt_DD"; then
+ ac_path_lt_DD_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in dd
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_lt_DD="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_lt_DD" || continue
+if "$ac_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+ cmp -s conftest.i conftest.out \
+ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
+fi
+ $ac_path_lt_DD_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_lt_DD"; then
+ :
+ fi
+else
+ ac_cv_path_lt_DD=$lt_DD
+fi
+
+rm -f conftest.i conftest2.i conftest.out ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5
+printf "%s\n" "$ac_cv_path_lt_DD" >&6; }
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5
+printf %s "checking how to truncate binary pipes... " >&6; }
+if test ${lt_cv_truncate_bin+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+lt_cv_truncate_bin=
+if "$ac_cv_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+ cmp -s conftest.i conftest.out \
+ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
+fi
+rm -f conftest.i conftest2.i conftest.out
+test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5
+printf "%s\n" "$lt_cv_truncate_bin" >&6; }
+
+
+
+
+
+
+
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+ for cc_temp in $*""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+ done
+ func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+
+# Check whether --enable-libtool-lock was given.
+if test ${enable_libtool_lock+y}
+then :
+ enableval=$enable_libtool_lock;
+fi
+
+test no = "$enable_libtool_lock" || enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out what ABI is being produced by ac_compile, and set mode
+ # options accordingly.
+ echo 'int i;' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ case `$FILECMD conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE=32
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE=64
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ if test yes = "$lt_cv_prog_gnu_ld"; then
+ case `$FILECMD conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `$FILECMD conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+mips64*-*linux*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ emul=elf
+ case `$FILECMD conftest.$ac_objext` in
+ *32-bit*)
+ emul="${emul}32"
+ ;;
+ *64-bit*)
+ emul="${emul}64"
+ ;;
+ esac
+ case `$FILECMD conftest.$ac_objext` in
+ *MSB*)
+ emul="${emul}btsmip"
+ ;;
+ *LSB*)
+ emul="${emul}ltsmip"
+ ;;
+ esac
+ case `$FILECMD conftest.$ac_objext` in
+ *N32*)
+ emul="${emul}n32"
+ ;;
+ esac
+ LD="${LD-ld} -m $emul"
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly. Note that the listed cases only cover the
+ # situations where additional linker options are needed (such as when
+ # doing 32-bit compilation for a host where ld defaults to 64-bit, or
+ # vice versa); the common cases where no linker options are needed do
+ # not appear in the list.
+ echo 'int i;' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ case `$FILECMD conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_i386_fbsd"
+ ;;
+ x86_64-*linux*)
+ case `$FILECMD conftest.o` in
+ *x86-64*)
+ LD="${LD-ld} -m elf32_x86_64"
+ ;;
+ *)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ esac
+ ;;
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_x86_64_fbsd"
+ ;;
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*|s390*-*tpf*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS -belf"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
+printf %s "checking whether the C compiler needs -belf... " >&6; }
+if test ${lt_cv_cc_needs_belf+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ lt_cv_cc_needs_belf=yes
+else case e in #(
+ e) lt_cv_cc_needs_belf=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
+printf "%s\n" "$lt_cv_cc_needs_belf" >&6; }
+ if test yes != "$lt_cv_cc_needs_belf"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS=$SAVE_CFLAGS
+ fi
+ ;;
+*-*solaris*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo 'int i;' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ case `$FILECMD conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*)
+ case $host in
+ i?86-*-solaris*|x86_64-*-solaris*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ sparc*-*-solaris*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ # GNU ld 2.21 introduced _sol2 emulations. Use them if available.
+ if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+ LD=${LD-ld}_sol2
+ fi
+ ;;
+ *)
+ if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+ LD="${LD-ld} -64"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+esac
+
+need_locks=$enable_libtool_lock
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args.
+set dummy ${ac_tool_prefix}mt; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_MANIFEST_TOOL+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$MANIFEST_TOOL"; then
+ ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL
+if test -n "$MANIFEST_TOOL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5
+printf "%s\n" "$MANIFEST_TOOL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_MANIFEST_TOOL"; then
+ ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL
+ # Extract the first word of "mt", so it can be a program name with args.
+set dummy mt; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_MANIFEST_TOOL+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_MANIFEST_TOOL"; then
+ ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_MANIFEST_TOOL="mt"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL
+if test -n "$ac_ct_MANIFEST_TOOL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5
+printf "%s\n" "$ac_ct_MANIFEST_TOOL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_MANIFEST_TOOL" = x; then
+ MANIFEST_TOOL=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL
+ fi
+else
+ MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL"
+fi
+
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5
+printf %s "checking if $MANIFEST_TOOL is a manifest tool... " >&6; }
+if test ${lt_cv_path_mainfest_tool+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_path_mainfest_tool=no
+ echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5
+ $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+ cat conftest.err >&5
+ if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+ lt_cv_path_mainfest_tool=yes
+ fi
+ rm -f conftest* ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5
+printf "%s\n" "$lt_cv_path_mainfest_tool" >&6; }
+if test yes != "$lt_cv_path_mainfest_tool"; then
+ MANIFEST_TOOL=:
+fi
+
+
+
+
+
+
+ case $host_os in
+ rhapsody* | darwin*)
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_DSYMUTIL+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$DSYMUTIL"; then
+ ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+DSYMUTIL=$ac_cv_prog_DSYMUTIL
+if test -n "$DSYMUTIL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
+printf "%s\n" "$DSYMUTIL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DSYMUTIL"; then
+ ac_ct_DSYMUTIL=$DSYMUTIL
+ # Extract the first word of "dsymutil", so it can be a program name with args.
+set dummy dsymutil; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_DSYMUTIL+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_DSYMUTIL"; then
+ ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
+if test -n "$ac_ct_DSYMUTIL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
+printf "%s\n" "$ac_ct_DSYMUTIL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_DSYMUTIL" = x; then
+ DSYMUTIL=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ DSYMUTIL=$ac_ct_DSYMUTIL
+ fi
+else
+ DSYMUTIL="$ac_cv_prog_DSYMUTIL"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_NMEDIT+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$NMEDIT"; then
+ ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+NMEDIT=$ac_cv_prog_NMEDIT
+if test -n "$NMEDIT"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
+printf "%s\n" "$NMEDIT" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_NMEDIT"; then
+ ac_ct_NMEDIT=$NMEDIT
+ # Extract the first word of "nmedit", so it can be a program name with args.
+set dummy nmedit; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_NMEDIT+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_NMEDIT"; then
+ ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_NMEDIT="nmedit"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
+if test -n "$ac_ct_NMEDIT"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
+printf "%s\n" "$ac_ct_NMEDIT" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_NMEDIT" = x; then
+ NMEDIT=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ NMEDIT=$ac_ct_NMEDIT
+ fi
+else
+ NMEDIT="$ac_cv_prog_NMEDIT"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}lipo; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_LIPO+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$LIPO"; then
+ ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+LIPO=$ac_cv_prog_LIPO
+if test -n "$LIPO"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
+printf "%s\n" "$LIPO" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_LIPO"; then
+ ac_ct_LIPO=$LIPO
+ # Extract the first word of "lipo", so it can be a program name with args.
+set dummy lipo; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_LIPO+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_LIPO"; then
+ ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_LIPO="lipo"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
+if test -n "$ac_ct_LIPO"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
+printf "%s\n" "$ac_ct_LIPO" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_LIPO" = x; then
+ LIPO=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ LIPO=$ac_ct_LIPO
+ fi
+else
+ LIPO="$ac_cv_prog_LIPO"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_OTOOL+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$OTOOL"; then
+ ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+OTOOL=$ac_cv_prog_OTOOL
+if test -n "$OTOOL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+printf "%s\n" "$OTOOL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL"; then
+ ac_ct_OTOOL=$OTOOL
+ # Extract the first word of "otool", so it can be a program name with args.
+set dummy otool; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_OTOOL+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_OTOOL"; then
+ ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_OTOOL="otool"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
+if test -n "$ac_ct_OTOOL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
+printf "%s\n" "$ac_ct_OTOOL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_OTOOL" = x; then
+ OTOOL=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OTOOL=$ac_ct_OTOOL
+ fi
+else
+ OTOOL="$ac_cv_prog_OTOOL"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool64; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_OTOOL64+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$OTOOL64"; then
+ ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+OTOOL64=$ac_cv_prog_OTOOL64
+if test -n "$OTOOL64"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
+printf "%s\n" "$OTOOL64" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL64"; then
+ ac_ct_OTOOL64=$OTOOL64
+ # Extract the first word of "otool64", so it can be a program name with args.
+set dummy otool64; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_OTOOL64+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$ac_ct_OTOOL64"; then
+ ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_OTOOL64="otool64"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
+if test -n "$ac_ct_OTOOL64"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
+printf "%s\n" "$ac_ct_OTOOL64" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_OTOOL64" = x; then
+ OTOOL64=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OTOOL64=$ac_ct_OTOOL64
+ fi
+else
+ OTOOL64="$ac_cv_prog_OTOOL64"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
+printf %s "checking for -single_module linker flag... " >&6; }
+if test ${lt_cv_apple_cc_single_mod+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_apple_cc_single_mod=no
+ if test -z "$LT_MULTI_MODULE"; then
+ # By default we will add the -single_module flag. You can override
+ # by either setting the environment variable LT_MULTI_MODULE
+ # non-empty at configure time, or by adding -multi_module to the
+ # link flags.
+ rm -rf libconftest.dylib*
+ echo "int foo(void){return 1;}" > conftest.c
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&5
+ $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+ _lt_result=$?
+ # If there is a non-empty error log, and "single_module"
+ # appears in it, assume the flag caused a linker warning
+ if test -s conftest.err && $GREP single_module conftest.err; then
+ cat conftest.err >&5
+ # Otherwise, if the output was created with a 0 exit code from
+ # the compiler, it worked.
+ elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
+ lt_cv_apple_cc_single_mod=yes
+ else
+ cat conftest.err >&5
+ fi
+ rm -rf libconftest.dylib*
+ rm -f conftest.*
+ fi ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
+printf "%s\n" "$lt_cv_apple_cc_single_mod" >&6; }
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
+printf %s "checking for -exported_symbols_list linker flag... " >&6; }
+if test ${lt_cv_ld_exported_symbols_list+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_ld_exported_symbols_list=no
+ save_LDFLAGS=$LDFLAGS
+ echo "_main" > conftest.sym
+ LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ lt_cv_ld_exported_symbols_list=yes
+else case e in #(
+ e) lt_cv_ld_exported_symbols_list=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$save_LDFLAGS
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
+printf "%s\n" "$lt_cv_ld_exported_symbols_list" >&6; }
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
+printf %s "checking for -force_load linker flag... " >&6; }
+if test ${lt_cv_ld_force_load+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_ld_force_load=no
+ cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+ echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
+ $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
+ echo "$AR $AR_FLAGS libconftest.a conftest.o" >&5
+ $AR $AR_FLAGS libconftest.a conftest.o 2>&5
+ echo "$RANLIB libconftest.a" >&5
+ $RANLIB libconftest.a 2>&5
+ cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
+ $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+ _lt_result=$?
+ if test -s conftest.err && $GREP force_load conftest.err; then
+ cat conftest.err >&5
+ elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
+ lt_cv_ld_force_load=yes
+ else
+ cat conftest.err >&5
+ fi
+ rm -f conftest.err libconftest.a conftest conftest.c
+ rm -rf conftest.dSYM
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
+printf "%s\n" "$lt_cv_ld_force_load" >&6; }
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
+ darwin1.*)
+ _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+ darwin*)
+ case $MACOSX_DEPLOYMENT_TARGET,$host in
+ 10.[012],*|,*powerpc*-darwin[5-8]*)
+ _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+ *)
+ _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+ esac
+ ;;
+ esac
+ if test yes = "$lt_cv_apple_cc_single_mod"; then
+ _lt_dar_single_mod='$single_module'
+ fi
+ if test yes = "$lt_cv_ld_exported_symbols_list"; then
+ _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
+ else
+ _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
+ fi
+ if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
+ _lt_dsymutil='~$DSYMUTIL $lib || :'
+ else
+ _lt_dsymutil=
+ fi
+ ;;
+ esac
+
+# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+# string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+# string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+# "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+# VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+ case x$2 in
+ x)
+ ;;
+ *:)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
+ ;;
+ x:*)
+ eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ *::*)
+ eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+ eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
+ ;;
+ *)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ esac
+}
+
+ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_dlfcn_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_DLFCN_H 1" >>confdefs.h
+
+fi
+
+
+
+
+
+# Set options
+enable_dlopen=yes
+
+
+
+
+ enable_win32_dll=no
+
+
+ # Check whether --enable-shared was given.
+if test ${enable_shared+y}
+then :
+ enableval=$enable_shared; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac
+else case e in #(
+ e) enable_shared=yes ;;
+esac
+fi
+
+
+
+
+
+
+
+
+
+ # Check whether --enable-static was given.
+if test ${enable_static+y}
+then :
+ enableval=$enable_static; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac
+else case e in #(
+ e) enable_static=yes ;;
+esac
+fi
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-pic was given.
+if test ${with_pic+y}
+then :
+ withval=$with_pic; lt_p=${PACKAGE-default}
+ case $withval in
+ yes|no) pic_mode=$withval ;;
+ *)
+ pic_mode=default
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for lt_pkg in $withval; do
+ IFS=$lt_save_ifs
+ if test "X$lt_pkg" = "X$lt_p"; then
+ pic_mode=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac
+else case e in #(
+ e) pic_mode=default ;;
+esac
+fi
+
+
+
+
+
+
+
+
+ # Check whether --enable-fast-install was given.
+if test ${enable_fast_install+y}
+then :
+ enableval=$enable_fast_install; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac
+else case e in #(
+ e) enable_fast_install=yes ;;
+esac
+fi
+
+
+
+
+
+
+
+
+ shared_archive_member_spec=
+case $host,$enable_shared in
+power*-*-aix[5-9]*,yes)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5
+printf %s "checking which variant of shared library versioning to provide... " >&6; }
+
+# Check whether --with-aix-soname was given.
+if test ${with_aix_soname+y}
+then :
+ withval=$with_aix_soname; case $withval in
+ aix|svr4|both)
+ ;;
+ *)
+ as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5
+ ;;
+ esac
+ lt_cv_with_aix_soname=$with_aix_soname
+else case e in #(
+ e) if test ${lt_cv_with_aix_soname+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_with_aix_soname=aix ;;
+esac
+fi
+
+ with_aix_soname=$lt_cv_with_aix_soname ;;
+esac
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5
+printf "%s\n" "$with_aix_soname" >&6; }
+ if test aix != "$with_aix_soname"; then
+ # For the AIX way of multilib, we name the shared archive member
+ # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
+ # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
+ # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
+ # the AIX toolchain works better with OBJECT_MODE set (default 32).
+ if test 64 = "${OBJECT_MODE-32}"; then
+ shared_archive_member_spec=shr_64
+ else
+ shared_archive_member_spec=shr
+ fi
+ fi
+ ;;
+*)
+ with_aix_soname=aix
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS=$ltmain
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test -z "$LN_S" && LN_S="ln -s"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
+printf %s "checking for objdir... " >&6; }
+if test ${lt_cv_objdir+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
+printf "%s\n" "$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+printf "%s\n" "#define LT_OBJDIR \"$lt_cv_objdir/\"" >>confdefs.h
+
+
+
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test set != "${COLLECT_NAMES+set}"; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a '.a' archive for static linking (except MSVC and
+# ICC, which need '.lib').
+libext=a
+
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+old_CC=$CC
+old_CFLAGS=$CFLAGS
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+func_cc_basename $compiler
+cc_basename=$func_cc_basename_result
+
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
+printf %s "checking for ${ac_tool_prefix}file... " >&6; }
+if test ${lt_cv_path_MAGIC_CMD+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD=$MAGIC_CMD
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/${ac_tool_prefix}file"; then
+ lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS=$lt_save_ifs
+ MAGIC_CMD=$lt_save_MAGIC_CMD
+ ;;
+esac ;;
+esac
+fi
+
+MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+if test -n "$MAGIC_CMD"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+printf "%s\n" "$MAGIC_CMD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+
+
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for file" >&5
+printf %s "checking for file... " >&6; }
+if test ${lt_cv_path_MAGIC_CMD+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD=$MAGIC_CMD
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/file"; then
+ lt_cv_path_MAGIC_CMD=$ac_dir/"file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS=$lt_save_ifs
+ MAGIC_CMD=$lt_save_MAGIC_CMD
+ ;;
+esac ;;
+esac
+fi
+
+MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+if test -n "$MAGIC_CMD"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+printf "%s\n" "$MAGIC_CMD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ else
+ MAGIC_CMD=:
+ fi
+fi
+
+ fi
+ ;;
+esac
+
+# Use C for the default configuration in the libtool script
+
+lt_save_CC=$CC
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+
+lt_prog_compiler_no_builtin_flag=
+
+if test yes = "$GCC"; then
+ case $cc_basename in
+ nvcc*)
+ lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
+ *)
+ lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
+ esac
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+printf %s "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
+if test ${lt_cv_prog_compiler_rtti_exceptions+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_prog_compiler_rtti_exceptions=no
+ ac_outfile=conftest.$ac_objext
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_rtti_exceptions=yes
+ fi
+ fi
+ $RM conftest*
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+printf "%s\n" "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then
+ lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+ :
+fi
+
+fi
+
+
+
+
+
+
+ lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+
+ if test yes = "$GCC"; then
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_static='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the '-m68020' flag to GCC prevents building anything better,
+ # like '-m68040'.
+ lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ case $host_os in
+ os2*)
+ lt_prog_compiler_static='$wl-static'
+ ;;
+ esac
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic='-fno-common'
+ ;;
+
+ haiku*)
+ # PIC is the default for Haiku.
+ # The "-static" flag exists, but is broken.
+ lt_prog_compiler_static=
+ ;;
+
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+ ;;
+
+ interix[3-9]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared=no
+ enable_shared=no
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ lt_prog_compiler_pic='-fPIC -shared'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic=-Kconform_pic
+ fi
+ ;;
+
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+
+ case $cc_basename in
+ nvcc*) # Cuda Compiler Driver 2.2
+ lt_prog_compiler_wl='-Xlinker '
+ if test -n "$lt_prog_compiler_pic"; then
+ lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic"
+ fi
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl='-Wl,'
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ else
+ lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic='-fno-common'
+ case $cc_basename in
+ nagfor*)
+ # NAG Fortran compiler
+ lt_prog_compiler_wl='-Wl,-Wl,,'
+ lt_prog_compiler_pic='-PIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ esac
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ case $host_os in
+ os2*)
+ lt_prog_compiler_static='$wl-static'
+ ;;
+ esac
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static='$wl-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ case $cc_basename in
+ # old Intel for x86_64, which still supported -KPIC.
+ ecc*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ # icc used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ icc* | ifort*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ # Lahey Fortran 8.1.
+ lf95*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='--shared'
+ lt_prog_compiler_static='--static'
+ ;;
+ nagfor*)
+ # NAG Fortran compiler
+ lt_prog_compiler_wl='-Wl,-Wl,,'
+ lt_prog_compiler_pic='-PIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ tcc*)
+ # Fabrice Bellard et al's Tiny C Compiler
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fpic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+ xl* | bgxl* | bgf* | mpixl*)
+ # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-qpic'
+ lt_prog_compiler_static='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | $SED 5q` in
+ *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*)
+ # Sun Fortran 8.3 passes all unrecognized flags to the linker
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ lt_prog_compiler_wl=''
+ ;;
+ *Sun\ F* | *Sun*Fortran*)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ lt_prog_compiler_wl='-Qoption ld '
+ ;;
+ *Sun\ C*)
+ # Sun C 5.9
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ lt_prog_compiler_wl='-Wl,'
+ ;;
+ *Intel*\ [CF]*Compiler*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ *Portland\ Group*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fpic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ lt_prog_compiler_pic='-fPIC -shared'
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ rdos*)
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+ lt_prog_compiler_wl='-Qoption ld ';;
+ *)
+ lt_prog_compiler_wl='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl='-Qoption ld '
+ lt_prog_compiler_pic='-PIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic='-Kconform_pic'
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ unicos*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_can_build_shared=no
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic='-pic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared=no
+ ;;
+ esac
+ fi
+
+case $host_os in
+ # For platforms that do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic=
+ ;;
+ *)
+ lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+ ;;
+esac
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+printf %s "checking for $compiler option to produce PIC... " >&6; }
+if test ${lt_cv_prog_compiler_pic+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_prog_compiler_pic=$lt_prog_compiler_pic ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5
+printf "%s\n" "$lt_cv_prog_compiler_pic" >&6; }
+lt_prog_compiler_pic=$lt_cv_prog_compiler_pic
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+printf %s "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
+if test ${lt_cv_prog_compiler_pic_works+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_prog_compiler_pic_works=no
+ ac_outfile=conftest.$ac_objext
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_pic_works=yes
+ fi
+ fi
+ $RM conftest*
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
+printf "%s\n" "$lt_cv_prog_compiler_pic_works" >&6; }
+
+if test yes = "$lt_cv_prog_compiler_pic_works"; then
+ case $lt_prog_compiler_pic in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+ esac
+else
+ lt_prog_compiler_pic=
+ lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+printf %s "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if test ${lt_cv_prog_compiler_static_works+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_prog_compiler_static_works=no
+ save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_static_works=yes
+ fi
+ else
+ lt_cv_prog_compiler_static_works=yes
+ fi
+ fi
+ $RM -r conftest*
+ LDFLAGS=$save_LDFLAGS
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
+printf "%s\n" "$lt_cv_prog_compiler_static_works" >&6; }
+
+if test yes = "$lt_cv_prog_compiler_static_works"; then
+ :
+else
+ lt_prog_compiler_static=
+fi
+
+
+
+
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test ${lt_cv_prog_compiler_c_o+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_prog_compiler_c_o=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test ${lt_cv_prog_compiler_c_o+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_prog_compiler_c_o=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+hard_links=nottested
+if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then
+ # do not overwrite the value of need_locks provided by the user
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+printf %s "checking if we can lock with hard links... " >&6; }
+ hard_links=yes
+ $RM conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+printf "%s\n" "$hard_links" >&6; }
+ if test no = "$hard_links"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5
+printf "%s\n" "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+
+
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+ runpath_var=
+ allow_undefined_flag=
+ always_export_symbols=no
+ archive_cmds=
+ archive_expsym_cmds=
+ compiler_needs_object=no
+ enable_shared_with_static_runtimes=no
+ export_dynamic_flag_spec=
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ hardcode_automatic=no
+ hardcode_direct=no
+ hardcode_direct_absolute=no
+ hardcode_libdir_flag_spec=
+ hardcode_libdir_separator=
+ hardcode_minus_L=no
+ hardcode_shlibpath_var=unsupported
+ fix_hardcoded_libdir_flag_spec=
+ fix_hardcoded_libdir_flag_spec_ld=
+ inherit_rpath=no
+ link_all_deplibs=unknown
+ module_cmds=
+ module_expsym_cmds=
+ old_archive_from_new_cmds=
+ old_archive_from_expsyms_cmds=
+ thread_safe_flag_spec=
+ whole_archive_flag_spec=
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ' (' and ')$', so one must not match beginning or
+ # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
+ # as well as any symbol that contains 'd'.
+ exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ # Exclude shared library initialization/finalization symbols.
+ extract_expsyms_cmds=
+
+ case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++ or Intel C++ Compiler.
+ if test yes != "$GCC"; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
+ with_gnu_ld=yes
+ ;;
+ openbsd* | bitrig*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs=yes
+
+ # On some targets, GNU ld is compatible enough with the native linker
+ # that we're better off using the native interface for both.
+ lt_use_gnu_ld_interface=no
+ if test yes = "$with_gnu_ld"; then
+ case $host_os in
+ aix*)
+ # The AIX port of GNU ld has always aspired to compatibility
+ # with the native linker. However, as the warning in the GNU ld
+ # block says, versions before 2.19.5* couldn't really create working
+ # shared libraries, regardless of the interface used.
+ case `$LD -v 2>&1` in
+ *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+ *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
+ *\ \(GNU\ Binutils\)\ [3-9]*) ;;
+ *)
+ lt_use_gnu_ld_interface=yes
+ ;;
+ esac
+ ;;
+ *)
+ lt_use_gnu_ld_interface=yes
+ ;;
+ esac
+ fi
+
+ if test yes = "$lt_use_gnu_ld_interface"; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='$wl'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ export_dynamic_flag_spec='$wl--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+ else
+ whole_archive_flag_spec=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in
+ *GNU\ gold*) supports_anon_versioning=yes ;;
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix[3-9]*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test ia64 != "$host_cpu"; then
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds=''
+ ;;
+ m68k)
+ archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ ;;
+ esac
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ export_dynamic_flag_spec='$wl--export-all-symbols'
+ allow_undefined_flag=unsupported
+ always_export_symbols=no
+ enable_shared_with_static_runtimes=yes
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
+ exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file, use it as
+ # is; otherwise, prepend EXPORTS...
+ archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ haiku*)
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ link_all_deplibs=yes
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ shrext_cmds=.dll
+ archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ enable_shared_with_static_runtimes=yes
+ file_list_spec='@'
+ ;;
+
+ interix[3-9]*)
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+ export_dynamic_flag_spec='$wl-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+ tmp_diet=no
+ if test linux-dietlibc = "$host_os"; then
+ case $cc_basename in
+ diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
+ esac
+ fi
+ if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+ && test no = "$tmp_diet"
+ then
+ tmp_addflag=' $pic_flag'
+ tmp_sharedflag='-shared'
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95* | pgfortran*)
+ # Portland Group f77 and f90 compilers
+ whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ lf95*) # Lahey Fortran 8.1
+ whole_archive_flag_spec=
+ tmp_sharedflag='--shared' ;;
+ nagfor*) # NAGFOR 5.3
+ tmp_sharedflag='-Wl,-shared' ;;
+ xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+ tmp_sharedflag='-qmkshrobj'
+ tmp_addflag= ;;
+ nvcc*) # Cuda Compiler Driver 2.2
+ whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ compiler_needs_object=yes
+ ;;
+ esac
+ case `$CC -V 2>&1 | $SED 5q` in
+ *Sun\ C*) # Sun C 5.9
+ whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ compiler_needs_object=yes
+ tmp_sharedflag='-G' ;;
+ *Sun\ F*) # Sun Fortran 8.3
+ tmp_sharedflag='-G' ;;
+ esac
+ archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+
+ if test yes = "$supports_anon_versioning"; then
+ archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
+ fi
+
+ case $cc_basename in
+ tcc*)
+ export_dynamic_flag_spec='-rdynamic'
+ ;;
+ xlf* | bgf* | bgxlf* | mpixlf*)
+ # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+ whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+ if test yes = "$supports_anon_versioning"; then
+ archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ esac
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+
+ if test no = "$ld_shlibs"; then
+ runpath_var=
+ hardcode_libdir_flag_spec=
+ export_dynamic_flag_spec=
+ whole_archive_flag_spec=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+ archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+
+ aix[4-9]*)
+ if test ia64 = "$host_cpu"; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to GNU nm, but means don't demangle to AIX nm.
+ # Without the "-l" option, or with the "-B" option, AIX nm treats
+ # weak defined symbols like other global defined symbols, whereas
+ # GNU nm marks them as "W".
+ # While the 'weak' keyword is ignored in the Export File, we need
+ # it in the Import File for the 'aix-soname' feature, so we have
+ # to replace the "-B" option with "-P" for AIX nm.
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # have runtime linking enabled, and use it for executables.
+ # For shared libraries, we enable/disable runtime linking
+ # depending on the kind of the shared library created -
+ # when "with_aix_soname,aix_use_runtimelinking" is:
+ # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
+ # "aix,yes" lib.so shared, rtl:yes, for executables
+ # lib.a static archive
+ # "both,no" lib.so.V(shr.o) shared, rtl:yes
+ # lib.a(lib.so.V) shared, rtl:no, for executables
+ # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a(lib.so.V) shared, rtl:no
+ # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a static archive
+ case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+ for ld_flag in $LDFLAGS; do
+ if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # With aix-soname=svr4, we create the lib.so.V shared archives only,
+ # so we don't have lib.a shared libs to link our executables.
+ # We have to force runtime linking in this case.
+ aix_use_runtimelinking=yes
+ LDFLAGS="$LDFLAGS -Wl,-brtl"
+ fi
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds=''
+ hardcode_direct=yes
+ hardcode_direct_absolute=yes
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+ file_list_spec='$wl-f,'
+ case $with_aix_soname,$aix_use_runtimelinking in
+ aix,*) ;; # traditional, no import file
+ svr4,* | *,yes) # use import file
+ # The Import File defines what to hardcode.
+ hardcode_direct=no
+ hardcode_direct_absolute=no
+ ;;
+ esac
+
+ if test yes = "$GCC"; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`$CC -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag="$shared_flag "'$wl-G'
+ fi
+ # Need to ensure runtime linking is disabled for the traditional
+ # shared library, or the linker may eventually find shared libraries
+ # /with/ Import File - we do not want to mix them.
+ shared_flag_aix='-shared'
+ shared_flag_svr4='-shared $wl-G'
+ else
+ # not using gcc
+ if test ia64 = "$host_cpu"; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag='$wl-G'
+ else
+ shared_flag='$wl-bM:SRE'
+ fi
+ shared_flag_aix='$wl-bM:SRE'
+ shared_flag_svr4='$wl-G'
+ fi
+ fi
+
+ export_dynamic_flag_spec='$wl-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols=yes
+ if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag='-berok'
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ if test set = "${lt_cv_aix_libpath+set}"; then
+ aix_libpath=$lt_cv_aix_libpath
+else
+ if test ${lt_cv_aix_libpath_+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+
+ lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\([^ ]*\) *$/\1/
+ p
+ }
+ }'
+ lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ # Check for a 64-bit object if we didn't find anything.
+ if test -z "$lt_cv_aix_libpath_"; then
+ lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ if test -z "$lt_cv_aix_libpath_"; then
+ lt_cv_aix_libpath_=/usr/lib:/lib
+ fi
+ ;;
+esac
+fi
+
+ aix_libpath=$lt_cv_aix_libpath_
+fi
+
+ hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+ else
+ if test ia64 = "$host_cpu"; then
+ hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag="-z nodefs"
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ if test set = "${lt_cv_aix_libpath+set}"; then
+ aix_libpath=$lt_cv_aix_libpath
+else
+ if test ${lt_cv_aix_libpath_+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+
+ lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\([^ ]*\) *$/\1/
+ p
+ }
+ }'
+ lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ # Check for a 64-bit object if we didn't find anything.
+ if test -z "$lt_cv_aix_libpath_"; then
+ lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ if test -z "$lt_cv_aix_libpath_"; then
+ lt_cv_aix_libpath_=/usr/lib:/lib
+ fi
+ ;;
+esac
+fi
+
+ aix_libpath=$lt_cv_aix_libpath_
+fi
+
+ hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag=' $wl-bernotok'
+ allow_undefined_flag=' $wl-berok'
+ if test yes = "$with_gnu_ld"; then
+ # We only use this code for GNU lds that support --whole-archive.
+ whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive'
+ else
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec='$convenience'
+ fi
+ archive_cmds_need_lc=yes
+ archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+ # -brtl affects multiple linker settings, -berok does not and is overridden later
+ compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`'
+ if test svr4 != "$with_aix_soname"; then
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+ fi
+ if test aix != "$with_aix_soname"; then
+ archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+ else
+ # used by -dlpreopen to get the symbols
+ archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
+ fi
+ archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds=''
+ ;;
+ m68k)
+ archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ ;;
+ esac
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++ or Intel C++ Compiler.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ case $cc_basename in
+ cl* | icl*)
+ # Native MSVC or ICC
+ hardcode_libdir_flag_spec=' '
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+ file_list_spec='@'
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=.dll
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+ archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then
+ cp "$export_symbols" "$output_objdir/$soname.def";
+ echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+ else
+ $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+ fi~
+ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+ linknames='
+ # The linker will not automatically build a static lib if we build a DLL.
+ # _LT_TAGVAR(old_archive_from_new_cmds, )='true'
+ enable_shared_with_static_runtimes=yes
+ exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+ # Don't use ranlib
+ old_postinstall_cmds='chmod 644 $oldlib'
+ postlink_cmds='lt_outputfile="@OUTPUT@"~
+ lt_tool_outputfile="@TOOL_OUTPUT@"~
+ case $lt_outputfile in
+ *.exe|*.EXE) ;;
+ *)
+ lt_outputfile=$lt_outputfile.exe
+ lt_tool_outputfile=$lt_tool_outputfile.exe
+ ;;
+ esac~
+ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+ $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+ $RM "$lt_outputfile.manifest";
+ fi'
+ ;;
+ *)
+ # Assume MSVC and ICC wrapper
+ hardcode_libdir_flag_spec=' '
+ allow_undefined_flag=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=.dll
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_from_new_cmds='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+ enable_shared_with_static_runtimes=yes
+ ;;
+ esac
+ ;;
+
+ darwin* | rhapsody*)
+
+
+ archive_cmds_need_lc=no
+ hardcode_direct=no
+ hardcode_automatic=yes
+ hardcode_shlibpath_var=unsupported
+ if test yes = "$lt_cv_ld_force_load"; then
+ whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+
+ else
+ whole_archive_flag_spec=''
+ fi
+ link_all_deplibs=yes
+ allow_undefined_flag=$_lt_dar_allow_undefined
+ case $cc_basename in
+ ifort*|nagfor*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test yes = "$_lt_dar_can_shared"; then
+ output_verbose_link_cmd=func_echo_all
+ archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
+ module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
+ archive_expsym_cmds="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
+ module_expsym_cmds="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
+
+ else
+ ld_shlibs=no
+ fi
+
+ ;;
+
+ dgux*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2.*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | dragonfly* | midnightbsd*)
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ hpux9*)
+ if test yes = "$GCC"; then
+ archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec='$wl+b $wl$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ export_dynamic_flag_spec='$wl-E'
+ ;;
+
+ hpux10*)
+ if test yes,no = "$GCC,$with_gnu_ld"; then
+ archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags $fix_hardcoded_libdir_flag'
+ module_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $fix_hardcoded_libdir_flag'
+ else
+ archive_cmds='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags $fix_hardcoded_libdir_flag_ld'
+ module_cmds='$LD -b -o $lib $libobjs $deplibs $linker_flags $fix_hardcoded_libdir_flag_ld'
+ fi
+ if test no = "$with_gnu_ld"; then
+ hardcode_libdir_flag_spec='$wl+b $wl$libdir $fix_hardcoded_libdir_flag'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ hardcode_direct_absolute=yes
+ export_dynamic_flag_spec='$wl-E'
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ # gcc-3.0.1 (collect2) breaks on -Wl,+cdp.
+ # HP-cc ignores -Wl,+cdp, and we test the linker for +cdp support.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if +cdp linker flag works" >&5
+printf %s "checking if +cdp linker flag works... " >&6; }
+if test ${lt_cv_ldflag_cdp_works+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_ldflag_cdp_works=no
+ save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,+cdp -Wl,/usr/lib/libc.1:/nonexistent -Wl,+cdp -Wl,/lib/libc.1:/nonexistent"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ lt_cv_ldflag_cdp_works=yes
+else case e in #(
+ e) lt_cv_ldflag_cdp_works=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS="$save_LDFLAGS"
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ldflag_cdp_works" >&5
+printf "%s\n" "$lt_cv_ldflag_cdp_works" >&6; }
+ if test "$lt_cv_ldflag_cdp_works" = yes; then
+ fix_hardcoded_libdir_flag_spec='${wl}+cdp ${wl}${linkdir}/${dlname}:${libdir}/${dlname}'
+ fix_hardcoded_libdir_flag_spec_ld='+cdp ${linkdir}/${dlname}:${libdir}/${dlname}'
+ fi
+ fi
+ ;;
+
+ hpux11*)
+ if test yes,no = "$GCC,$with_gnu_ld"; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ module_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ module_cmds='$CC -shared $pic_flag $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags $fix_hardcoded_libdir_flag'
+ module_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $fix_hardcoded_libdir_flag'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ module_cmds='$CC -b -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ module_cmds='$CC -b $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+
+ # Older versions of the 11.00 compiler do not understand -b yet
+ # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
+printf %s "checking if $CC understands -b... " >&6; }
+if test ${lt_cv_prog_compiler__b+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_prog_compiler__b=no
+ save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -b"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler__b=yes
+ fi
+ else
+ lt_cv_prog_compiler__b=yes
+ fi
+ fi
+ $RM -r conftest*
+ LDFLAGS=$save_LDFLAGS
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
+printf "%s\n" "$lt_cv_prog_compiler__b" >&6; }
+
+if test yes = "$lt_cv_prog_compiler__b"; then
+
+ archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags $fix_hardcoded_libdir_flag'
+ module_cmds='$CC -b -o $lib $libobjs $deplibs $compiler_flags $fix_hardcoded_libdir_flag'
+
+else
+
+ archive_cmds='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags $fix_hardcoded_libdir_flag_ld'
+ module_cmds='$LD -b -o $lib $libobjs $deplibs $linker_flags $fix_hardcoded_libdir_flag_ld'
+
+fi
+
+ ;;
+ esac
+ fi
+ if test no = "$with_gnu_ld"; then
+ hardcode_libdir_flag_spec='$wl+b $wl$libdir $fix_hardcoded_libdir_flag'
+ hardcode_libdir_separator=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ ;;
+ *)
+ hardcode_direct=yes
+ hardcode_direct_absolute=yes
+ export_dynamic_flag_spec='$wl-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ # gcc-3.0.1 (collect2) breaks on -Wl,+cdp.
+ # HP-cc ignores -Wl,+cdp, and we test the linker for +cdp support.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if +cdp linker flag works" >&5
+printf %s "checking if +cdp linker flag works... " >&6; }
+if test ${lt_cv_ldflag_cdp_works+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_ldflag_cdp_works=no
+ save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,+cdp -Wl,/usr/lib/libc.1:/nonexistent -Wl,+cdp -Wl,/lib/libc.1:/nonexistent"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ lt_cv_ldflag_cdp_works=yes
+else case e in #(
+ e) lt_cv_ldflag_cdp_works=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS="$save_LDFLAGS"
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ldflag_cdp_works" >&5
+printf "%s\n" "$lt_cv_ldflag_cdp_works" >&6; }
+ if test "$lt_cv_ldflag_cdp_works" = yes; then
+ fix_hardcoded_libdir_flag_spec='${wl}+cdp ${wl}${linkdir}/${dlname}:${libdir}/${dlname}'
+ fix_hardcoded_libdir_flag_spec_ld='+cdp ${linkdir}/${dlname}:${libdir}/${dlname}'
+ fi
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test yes = "$GCC"; then
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ # Try to use the -exported_symbol ld option, if it does not
+ # work, assume that -exports_file does not work either and
+ # implicitly export all symbols.
+ # This should be the same for all languages, so no per-tag cache variable.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5
+printf %s "checking whether the $host_os linker accepts -exported_symbol... " >&6; }
+if test ${lt_cv_irix_exported_symbol+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int foo (void) { return 0; }
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ lt_cv_irix_exported_symbol=yes
+else case e in #(
+ e) lt_cv_irix_exported_symbol=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$save_LDFLAGS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5
+printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; }
+ if test yes = "$lt_cv_irix_exported_symbol"; then
+ archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
+ fi
+ else
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
+ fi
+ archive_cmds_need_lc='no'
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ hardcode_libdir_separator=:
+ inherit_rpath=yes
+ link_all_deplibs=yes
+ ;;
+
+ linux*)
+ case $cc_basename in
+ tcc*)
+ # Fabrice Bellard et al's Tiny C Compiler
+ ld_shlibs=yes
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ newsos6)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ hardcode_libdir_separator=:
+ hardcode_shlibpath_var=no
+ ;;
+
+ *nto* | *qnx*)
+ ;;
+
+ openbsd* | bitrig*)
+ if test -f /usr/libexec/ld.so; then
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ hardcode_direct_absolute=yes
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+ export_dynamic_flag_spec='$wl-E'
+ else
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+ fi
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ shrext_cmds=.dll
+ archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ enable_shared_with_static_runtimes=yes
+ file_list_spec='@'
+ ;;
+
+ osf3*)
+ if test yes = "$GCC"; then
+ allow_undefined_flag=' $wl-expect_unresolved $wl\*'
+ archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ fi
+ archive_cmds_need_lc='no'
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test yes = "$GCC"; then
+ allow_undefined_flag=' $wl-expect_unresolved $wl\*'
+ archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+ archive_cmds_need_lc='no'
+ hardcode_libdir_separator=:
+ ;;
+
+ solaris*)
+ no_undefined_flag=' -z defs'
+ if test yes = "$GCC"; then
+ wlarc='$wl'
+ archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ else
+ case `$CC -V 2>&1` in
+ *"Compilers 5.0"*)
+ wlarc=''
+ archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+ ;;
+ *)
+ wlarc='$wl'
+ archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ ;;
+ esac
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_shlibpath_var=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands '-z linker_flag'. GCC discards it without '$wl',
+ # but is careful enough not to reorder.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ if test yes = "$GCC"; then
+ whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
+ else
+ whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+ fi
+ ;;
+ esac
+ link_all_deplibs=yes
+ ;;
+
+ sunos4*)
+ if test sequent = "$host_vendor"; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds='$CC -r -o $output$reload_objs'
+ hardcode_direct=no
+ ;;
+ motorola)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ export_dynamic_flag_spec='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+ no_undefined_flag='$wl-z,text'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ runpath_var='LD_RUN_PATH'
+
+ if test yes = "$GCC"; then
+ archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We CANNOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag='$wl-z,text'
+ allow_undefined_flag='$wl-z,nodefs'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='$wl-R,$libdir'
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+ export_dynamic_flag_spec='$wl-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test yes = "$GCC"; then
+ archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+
+ if test sni = "$host_vendor"; then
+ case $host in
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ export_dynamic_flag_spec='$wl-Blargedynsym'
+ ;;
+ esac
+ fi
+ fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
+printf "%s\n" "$ld_shlibs" >&6; }
+test no = "$ld_shlibs" && can_build_shared=no
+
+with_gnu_ld=$with_gnu_ld
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc=yes
+
+ if test yes,yes = "$GCC,$enable_shared"; then
+ case $archive_cmds in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+printf %s "checking whether -lc should be explicitly linked in... " >&6; }
+if test ${lt_cv_archive_cmds_need_lc+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) $RM conftest*
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl
+ pic_flag=$lt_prog_compiler_pic
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag
+ allow_undefined_flag=
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+ (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ then
+ lt_cv_archive_cmds_need_lc=no
+ else
+ lt_cv_archive_cmds_need_lc=yes
+ fi
+ allow_undefined_flag=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $RM conftest*
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
+printf "%s\n" "$lt_cv_archive_cmds_need_lc" >&6; }
+ archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+printf %s "checking dynamic linker characteristics... " >&6; }
+
+if test yes = "$GCC"; then
+ case $host_os in
+ darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
+ *) lt_awk_arg='/^libraries:/' ;;
+ esac
+ case $host_os in
+ mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;;
+ *) lt_sed_strip_eq='s|=/|/|g' ;;
+ esac
+ lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+ case $lt_search_path_spec in
+ *\;*)
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+ ;;
+ *)
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+ ;;
+ esac
+ # Ok, now we have the path, separated by spaces, we can step through it
+ # and add multilib dir if necessary...
+ lt_tmp_lt_search_path_spec=
+ lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+ # ...but if some path component already ends with the multilib dir we assume
+ # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
+ case "$lt_multi_os_dir; $lt_search_path_spec " in
+ "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
+ lt_multi_os_dir=
+ ;;
+ esac
+ for lt_sys_path in $lt_search_path_spec; do
+ if test -d "$lt_sys_path$lt_multi_os_dir"; then
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
+ elif test -n "$lt_multi_os_dir"; then
+ test -d "$lt_sys_path" && \
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+ fi
+ done
+ lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS = " "; FS = "/|\n";} {
+ lt_foo = "";
+ lt_count = 0;
+ for (lt_i = NF; lt_i > 0; lt_i--) {
+ if ($lt_i != "" && $lt_i != ".") {
+ if ($lt_i == "..") {
+ lt_count++;
+ } else {
+ if (lt_count == 0) {
+ lt_foo = "/" $lt_i lt_foo;
+ } else {
+ lt_count--;
+ }
+ }
+ }
+ }
+ if (lt_foo != "") { lt_freq[lt_foo]++; }
+ if (lt_freq[lt_foo] == 1) { print lt_foo; }
+}'`
+ # AWK program above erroneously prepends '/' to C:/dos/paths
+ # for these hosts.
+ case $host_os in
+ mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+ $SED 's|/\([A-Za-z]:\)|\1|g'` ;;
+ esac
+ sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=.so
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+
+
+case $host_os in
+aix3*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+
+aix[4-9]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 supports IA64
+ library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line '#! .'. This would cause the generated library to
+ # depend on '.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # Using Import Files as archive members, it is possible to support
+ # filename-based versioning of shared library archives on AIX. While
+ # this would work for both with and without runtime linking, it will
+ # prevent static linking of such archives. So we do filename-based
+ # shared library versioning with .so extension only, which is used
+ # when both runtime linking and shared linking is enabled.
+ # Unfortunately, runtime linking may impact performance, so we do
+ # not want this to be the default eventually. Also, we use the
+ # versioned .so libs for executables only if there is the -brtl
+ # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
+ # To allow for filename-based versioning support, we need to create
+ # libNAME.so.V as an archive file, containing:
+ # *) an Import File, referring to the versioned filename of the
+ # archive as well as the shared archive member, telling the
+ # bitwidth (32 or 64) of that shared object, and providing the
+ # list of exported symbols of that shared object, eventually
+ # decorated with the 'weak' keyword
+ # *) the shared object with the F_LOADONLY flag set, to really avoid
+ # it being seen by the linker.
+ # At run time we better use the real file rather than another symlink,
+ # but for link time we create the symlink libNAME.so -> libNAME.so.V
+
+ case $with_aix_soname,$aix_use_runtimelinking in
+ # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ aix,yes) # traditional libtool
+ dynamic_linker='AIX unversionable lib.so'
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ ;;
+ aix,no) # traditional AIX only
+ dynamic_linker='AIX lib.a(lib.so.V)'
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='$libname$release.a $libname.a'
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+ svr4,*) # full svr4 only
+ dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)"
+ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+ # We do not specify a path in Import Files, so LIBPATH fires.
+ shlibpath_overrides_runpath=yes
+ ;;
+ *,yes) # both, prefer svr4
+ dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)"
+ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+ # unpreferred sharedlib libNAME.a needs extra handling
+ postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
+ postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
+ # We do not specify a path in Import Files, so LIBPATH fires.
+ shlibpath_overrides_runpath=yes
+ ;;
+ *,no) # both, prefer aix
+ dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)"
+ library_names_spec='$libname$release.a $libname.a'
+ soname_spec='$libname$release$shared_ext$major'
+ # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
+ postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
+ postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
+ ;;
+ esac
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ case $host_cpu in
+ powerpc)
+ # Since July 2007 AmigaOS4 officially supports .so libraries.
+ # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ ;;
+ m68k)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+ esac
+ ;;
+
+beos*)
+ library_names_spec='$libname$shared_ext'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+ version_type=windows
+ shrext_cmds=.dll
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$cc_basename in
+ yes,*)
+ # gcc
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
+ ;;
+ mingw* | cegcc*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ ;;
+
+ *,cl* | *,icl*)
+ # Native MSVC or ICC
+ libname_spec='$name'
+ soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+ library_names_spec='$libname.dll.lib'
+
+ case $build_os in
+ mingw*)
+ sys_lib_search_path_spec=
+ lt_save_ifs=$IFS
+ IFS=';'
+ for lt_path in $LIB
+ do
+ IFS=$lt_save_ifs
+ # Let DOS variable expansion print the short 8.3 style file name.
+ lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+ sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+ done
+ IFS=$lt_save_ifs
+ # Convert to MSYS style.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
+ ;;
+ cygwin*)
+ # Convert to unix form, then to dos form, then back to unix form
+ # but this time dos style (no spaces!) so that the unix form looks
+ # like /cygdrive/c/PROGRA~1:/cygdr...
+ sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+ sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+ sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ ;;
+ *)
+ sys_lib_search_path_spec=$LIB
+ if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ # FIXME: find the short name or the path components, as spaces are
+ # common. (e.g. "Program Files" -> "PROGRA~1")
+ ;;
+ esac
+
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+ dynamic_linker='Win32 link.exe'
+ ;;
+
+ *)
+ # Assume MSVC and ICC wrapper
+ library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib'
+ dynamic_linker='Win32 ld.exe'
+ ;;
+ esac
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
+ soname_spec='$libname$release$major$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd* | dragonfly* | midnightbsd*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[23].*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2.*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ *) # from 4.6 on, and DragonFly
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+haiku*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ dynamic_linker="$host_os runtime_loader"
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ if test 32 = "$HPUX_IA64_MODE"; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ sys_lib_dlsearch_path_spec=/usr/lib/hpux32
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ sys_lib_dlsearch_path_spec=/usr/lib/hpux64
+ fi
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+ postinstall_cmds='chmod 555 $lib'
+ # or fails outright, so override atomically:
+ install_override_mode=555
+ ;;
+
+interix[3-9]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test yes = "$lt_cv_prog_gnu_ld"; then
+ version_type=linux # correct to gnu/linux during the next big refactor
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='$libname$release$shared_ext$major'
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
+ sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+linux*android*)
+ version_type=none # Android doesn't support versioned libraries.
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext'
+ soname_spec='$libname$release$shared_ext'
+ finish_cmds=
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ dynamic_linker='Android linker'
+ # Don't embed -rpath directories since the linker doesn't support them.
+ hardcode_libdir_flag_spec='-L$libdir'
+ ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+
+ # Some binutils ld are patched to set DT_RUNPATH
+ if test ${lt_cv_shlibpath_overrides_runpath+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) lt_cv_shlibpath_overrides_runpath=no
+ save_LDFLAGS=$LDFLAGS
+ save_libdir=$libdir
+ eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
+ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null
+then :
+ lt_cv_shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$save_LDFLAGS
+ libdir=$save_libdir
+ ;;
+esac
+fi
+
+ shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Ideally, we could use ldconfig to report *all* directores which are
+ # searched for libraries, however this is still not possible. Aside from not
+ # being certain /sbin/ldconfig is available, command
+ # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
+ # even though it is searched at run-time. Try to do the best guess by
+ # appending ld.so.conf contents (and includes) to the search path.
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+*nto* | *qnx*)
+ version_type=qnx
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='ldqnx.so'
+ ;;
+
+openbsd* | bitrig*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec=/usr/lib
+ need_lib_prefix=no
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ need_version=no
+ else
+ need_version=yes
+ fi
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+os2*)
+ libname_spec='$name'
+ version_type=windows
+ shrext_cmds=.dll
+ need_version=no
+ need_lib_prefix=no
+ # OS/2 can only load a DLL with a base name of 8 characters or less.
+ soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
+ v=$($ECHO $release$versuffix | tr -d .-);
+ n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
+ $ECHO $n$v`$shared_ext'
+ library_names_spec='${libname}_dll.$libext'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=BEGINLIBPATH
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='$libname$release$shared_ext$major'
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+
+rdos*)
+ dynamic_linker=no
+ ;;
+
+solaris*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test yes = "$with_gnu_ld"; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec; then
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
+ soname_spec='$libname$shared_ext.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=sco
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ if test yes = "$with_gnu_ld"; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+tpf*)
+ # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+uts4*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+printf "%s\n" "$dynamic_linker" >&6; }
+test no = "$dynamic_linker" && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test yes = "$GCC"; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
+ sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
+fi
+
+if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
+ sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
+fi
+
+# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
+configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
+
+# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
+func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
+
+# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
+configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+printf %s "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" ||
+ test -n "$runpath_var" ||
+ test yes = "$hardcode_automatic"; then
+
+ # We can hardcode non-existent directories.
+ if test no != "$hardcode_direct" &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" &&
+ test -z "$fix_hardcoded_libdir_flag_spec" &&
+ test no != "$hardcode_minus_L"; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action=unsupported
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
+printf "%s\n" "$hardcode_action" >&6; }
+
+if test relink = "$hardcode_action" ||
+ test yes = "$inherit_rpath"; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test yes = "$shlibpath_overrides_runpath" ||
+ test no = "$enable_shared"; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+
+
+
+
+ if test yes != "$enable_dlopen"; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen=load_add_on
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32* | cegcc*)
+ lt_cv_dlopen=LoadLibrary
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen=dlopen
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+printf %s "checking for dlopen in -ldl... " >&6; }
+if test ${ac_cv_lib_dl_dlopen+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen (void);
+int
+main (void)
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_dl_dlopen=yes
+else case e in #(
+ e) ac_cv_lib_dl_dlopen=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes
+then :
+ lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
+else case e in #(
+ e)
+ lt_cv_dlopen=dyld
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+esac
+fi
+
+ ;;
+
+ tpf*)
+ # Don't try to run any link tests for TPF. We know it's impossible
+ # because TPF is a cross-compiler, and we know how we open DSOs.
+ lt_cv_dlopen=dlopen
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=no
+ ;;
+
+ *)
+ ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = xyes
+then :
+ lt_cv_dlopen=shl_load
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+printf %s "checking for shl_load in -ldld... " >&6; }
+if test ${ac_cv_lib_dld_shl_load+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load (void);
+int
+main (void)
+{
+return shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_dld_shl_load=yes
+else case e in #(
+ e) ac_cv_lib_dld_shl_load=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+printf "%s\n" "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = xyes
+then :
+ lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld
+else case e in #(
+ e) ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
+if test "x$ac_cv_func_dlopen" = xyes
+then :
+ lt_cv_dlopen=dlopen
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+printf %s "checking for dlopen in -ldl... " >&6; }
+if test ${ac_cv_lib_dl_dlopen+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen (void);
+int
+main (void)
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_dl_dlopen=yes
+else case e in #(
+ e) ac_cv_lib_dl_dlopen=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes
+then :
+ lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
+printf %s "checking for dlopen in -lsvld... " >&6; }
+if test ${ac_cv_lib_svld_dlopen+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen (void);
+int
+main (void)
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_svld_dlopen=yes
+else case e in #(
+ e) ac_cv_lib_svld_dlopen=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
+printf "%s\n" "$ac_cv_lib_svld_dlopen" >&6; }
+if test "x$ac_cv_lib_svld_dlopen" = xyes
+then :
+ lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
+printf %s "checking for dld_link in -ldld... " >&6; }
+if test ${ac_cv_lib_dld_dld_link+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link (void);
+int
+main (void)
+{
+return dld_link ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_dld_dld_link=yes
+else case e in #(
+ e) ac_cv_lib_dld_dld_link=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
+printf "%s\n" "$ac_cv_lib_dld_dld_link" >&6; }
+if test "x$ac_cv_lib_dld_dld_link" = xyes
+then :
+ lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld
+fi
+
+ ;;
+esac
+fi
+
+ ;;
+esac
+fi
+
+ ;;
+esac
+fi
+
+ ;;
+esac
+fi
+
+ ;;
+esac
+fi
+
+ ;;
+ esac
+
+ if test no = "$lt_cv_dlopen"; then
+ enable_dlopen=no
+ else
+ enable_dlopen=yes
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS=$CPPFLAGS
+ test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS=$LDFLAGS
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS=$LIBS
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
+printf %s "checking whether a program can dlopen itself... " >&6; }
+if test ${lt_cv_dlopen_self+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test yes = "$cross_compiling"; then :
+ lt_cv_dlopen_self=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+/* When -fvisibility=hidden is used, assume the code has been annotated
+ correspondingly for the symbols needed. */
+#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else
+ {
+ if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ else puts (dlerror ());
+ }
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ return status;
+}
+_LT_EOF
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self=no
+ fi
+fi
+rm -fr conftest*
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
+printf "%s\n" "$lt_cv_dlopen_self" >&6; }
+
+ if test yes = "$lt_cv_dlopen_self"; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
+printf %s "checking whether a statically linked program can dlopen itself... " >&6; }
+if test ${lt_cv_dlopen_self_static+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test yes = "$cross_compiling"; then :
+ lt_cv_dlopen_self_static=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+/* When -fvisibility=hidden is used, assume the code has been annotated
+ correspondingly for the symbols needed. */
+#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else
+ {
+ if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ else puts (dlerror ());
+ }
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ return status;
+}
+_LT_EOF
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self_static=no
+ fi
+fi
+rm -fr conftest*
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
+printf "%s\n" "$lt_cv_dlopen_self_static" >&6; }
+ fi
+
+ CPPFLAGS=$save_CPPFLAGS
+ LDFLAGS=$save_LDFLAGS
+ LIBS=$save_LIBS
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+striplib=
+old_striplib=
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
+printf %s "checking whether stripping libraries is possible... " >&6; }
+if test -z "$STRIP"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+else
+ if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+ old_striplib="$STRIP --strip-debug"
+ striplib="$STRIP --strip-unneeded"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ else
+ case $host_os in
+ darwin*)
+ # FIXME - insert some real tests, host_os isn't really good enough
+ striplib="$STRIP -x"
+ old_striplib="$STRIP -S"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ ;;
+ freebsd*)
+ if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
+ old_striplib="$STRIP --strip-debug"
+ striplib="$STRIP --strip-unneeded"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ fi
+ ;;
+ *)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ ;;
+ esac
+ fi
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+ # Report what library types will actually be built
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
+printf %s "checking if libtool supports shared libraries... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
+printf "%s\n" "$can_build_shared" >&6; }
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
+printf %s "checking whether to build shared libraries... " >&6; }
+ test no = "$can_build_shared" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test yes = "$enable_shared" && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+ aix[4-9]*)
+ if test ia64 != "$host_cpu"; then
+ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+ yes,aix,yes) ;; # shared object as lib.so file only
+ yes,svr4,*) ;; # shared object as lib.so archive member only
+ yes,*) enable_static=no ;; # shared object in lib.a archive as well
+ esac
+ fi
+ ;;
+ esac
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
+printf "%s\n" "$enable_shared" >&6; }
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
+printf %s "checking whether to build static libraries... " >&6; }
+ # Make sure either enable_shared or enable_static is yes.
+ test yes = "$enable_shared" || enable_static=yes
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
+printf "%s\n" "$enable_static" >&6; }
+
+
+
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC=$lt_save_CC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ac_config_commands="$ac_config_commands libtool"
+
+
+
+
+# Only expand once:
+
+
+
+case "$host_os" in
+aix*)
+ if test X"$aix_use_runtimelinking" != X"yes"
+then :
+
+ # Using traditional AIX dynamic shared objects in an archive file.
+ noexec_file="$libexecdir/sudo/sudo_noexec.a(sudo_noexec.so)"
+ intercept_file="$libexecdir/sudo/sudo_intercept.a(sudo_intercept.so)"
+ sudoers_plugin="sudoers.a(sudoers.so)"
+ python_plugin="python_plugin.a(python_plugin.so)"
+
+fi
+ ;;
+esac
+cat >>confdefs.h <<EOF
+#define _PATH_SUDOERS_PLUGIN "$sudoers_plugin"
+EOF
+
+
+
+# Check whether --with-libtool was given.
+if test ${with_libtool+y}
+then :
+ withval=$with_libtool; case $with_libtool in
+ yes|builtin) ;;
+ no) as_fn_error $? "--without-libtool not supported." "$LINENO" 5
+ ;;
+ system) LIBTOOL=libtool
+ ;;
+ *) LIBTOOL="$with_libtool"
+ ;;
+esac
+fi
+
+
+if test "$enable_shared" = "no"
+then :
+
+ enable_intercept=no
+ with_noexec=no
+ enable_dlopen=no
+ lt_cv_dlopen=none
+ lt_cv_dlopen_libs=
+ ac_cv_func_dlopen=no
+ LT_LDFLAGS=-static
+
+fi
+LIBDL="$lt_cv_dlopen_libs"
+SHLIB_ENABLE="$enable_dlopen"
+
+# Check whether --enable-intercept was given.
+if test ${enable_intercept+y}
+then :
+ enableval=$enable_intercept; case "$enableval" in
+ yes) ;;
+ no) ;;
+ *) intercept_file="$enableval"
+ ;;
+ esac
+
+else case e in #(
+ e) enable_intercept="$intercept_file" ;;
+esac
+fi
+
+INTERCEPTFILE="sudo_intercept.so"
+INTERCEPTDIR="`echo $intercept_file|sed -e 's:^${\([^}]*\)}:$(\1):' -e 's:^\([^:]*\)/[^/].*$:\1:'`"
+
+
+# Check whether --with-noexec was given.
+if test ${with_noexec+y}
+then :
+ withval=$with_noexec; case $with_noexec in
+ yes) ;;
+ no) ;;
+ *) noexec_file="$with_noexec"
+ ;;
+esac
+else case e in #(
+ e) with_noexec="$noexec_file" ;;
+esac
+fi
+
+NOEXECFILE="sudo_noexec.so"
+NOEXECDIR="`echo $noexec_file|sed -e 's:^${\([^}]*\)}:$(\1):' -e 's:^\([^:]*\)/[^/].*$:\1:'`"
+
+# Extract the first word of "sha1sum", so it can be a program name with args.
+set dummy sha1sum; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_SHA1SUM+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) case $SHA1SUM in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_SHA1SUM="$SHA1SUM" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_SHA1SUM="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_SHA1SUM" && ac_cv_path_SHA1SUM="openssl dgst -sha1"
+ ;;
+esac ;;
+esac
+fi
+SHA1SUM=$ac_cv_path_SHA1SUM
+if test -n "$SHA1SUM"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SHA1SUM" >&5
+printf "%s\n" "$SHA1SUM" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+# Extract the first word of "uname", so it can be a program name with args.
+set dummy uname; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_UNAMEPROG+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) case $UNAMEPROG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_UNAMEPROG="$UNAMEPROG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_UNAMEPROG="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_UNAMEPROG" && ac_cv_path_UNAMEPROG="uname"
+ ;;
+esac ;;
+esac
+fi
+UNAMEPROG=$ac_cv_path_UNAMEPROG
+if test -n "$UNAMEPROG"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $UNAMEPROG" >&5
+printf "%s\n" "$UNAMEPROG" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+# Extract the first word of "tr", so it can be a program name with args.
+set dummy tr; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_TRPROG+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) case $TRPROG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_TRPROG="$TRPROG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_TRPROG="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_TRPROG" && ac_cv_path_TRPROG="tr"
+ ;;
+esac ;;
+esac
+fi
+TRPROG=$ac_cv_path_TRPROG
+if test -n "$TRPROG"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TRPROG" >&5
+printf "%s\n" "$TRPROG" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mandoc or nroff" >&5
+printf %s "checking for mandoc or nroff... " >&6; }
+if test ${ac_cv_path_NROFF+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ if test -z "$NROFF"; then
+ ac_path_NROFF_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in mandoc nroff
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_NROFF="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_NROFF" || continue
+ac_cv_path_NROFF="$ac_path_NROFF"
+ $ac_path_NROFF_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_NROFF"; then
+ ac_cv_path_NROFF=no
+ fi
+else
+ ac_cv_path_NROFF=$NROFF
+fi
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_NROFF" >&5
+printf "%s\n" "$ac_cv_path_NROFF" >&6; }
+case "$ac_cv_path_NROFF" in
+*mandoc|no)
+ # Prefer mdoc format for mandoc (or when no formatter is present).
+ : ${MANTYPE='mdoc'}
+ ;;
+*)
+ # Check whether nroff supports -mdoc, this may produce incorrect
+ # results when cross-compiling.
+ test -n "$MANTYPE" && sudo_cv_var_mantype="$MANTYPE"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking which macro set to use for manual pages" >&5
+printf %s "checking which macro set to use for manual pages... " >&6; }
+if test ${sudo_cv_var_mantype+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ sudo_cv_var_mantype="man"
+ echo ".Sh NAME" > conftest
+ echo ".Nm sudo" >> conftest
+ echo ".Nd sudo" >> conftest
+ echo ".Sh DESCRIPTION" >> conftest
+ echo "sudo" >> conftest
+ if $ac_cv_path_NROFF -mdoc conftest >/dev/null 2>&1; then
+ sudo_cv_var_mantype="mdoc"
+ fi
+ rm -f conftest
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_var_mantype" >&5
+printf "%s\n" "$sudo_cv_var_mantype" >&6; }
+ MANTYPE="$sudo_cv_var_mantype"
+ ;;
+esac
+
+if test -n "$sudo_cv_prev_host"
+then :
+
+ if test "$sudo_cv_prev_host" != "$host"
+then :
+
+ as_fn_error $? "config.cache was created on a different host; remove it and re-run configure." "$LINENO" 5
+
+fi
+
+fi
+sudo_cv_prev_host="$host"
+
+cat >>confdefs.h <<EOF
+#define CONFIGURE_ARGS "$CONFIGURE_ARGS"
+EOF
+
+
+if test -n "$host_os"
+then :
+
+ OSREV=`echo $host_os | sed 's/^[^0-9\.]*\([0-9\.]*\).*$/\1/'`
+ OSMAJOR=`echo $OSREV | sed 's/\..*$//'`
+
+else case e in #(
+ e)
+ OSREV=0
+ OSMAJOR=0
+ ;;
+esac
+fi
+
+case "$host" in
+ *-*-solaris2*)
+ printf "%s\n" "#define PAM_SUN_CODEBASE 1" >>confdefs.h
+
+
+ # illumos has a broken fmemopen(3)
+ if test X"`uname -o 2>/dev/null`" = X"illumos"; then
+ : ${ac_cv_func_fmemopen='no'}
+ fi
+
+ # Solaris-specific initialization
+ OS_INIT=os_init_solaris
+ SUDO_OBJS="${SUDO_OBJS} solaris.o"
+
+ # AFS support needs -lucb
+ if test "$with_AFS" = "yes"
+then :
+
+ AFS_LIBS="-lc -lucb"
+
+fi
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+
+ for ac_func in priv_set
+do :
+ ac_fn_c_check_func "$LINENO" "priv_set" "ac_cv_func_priv_set"
+if test "x$ac_cv_func_priv_set" = xyes
+then :
+ printf "%s\n" "#define HAVE_PRIV_SET 1" >>confdefs.h
+ PSMAN=1
+fi
+
+done
+ ;;
+ *-*-aix*)
+ printf "%s\n" "#define PAM_SUN_CODEBASE 1" >>confdefs.h
+
+
+ # To get all prototypes (so we pass -Wall)
+ printf "%s\n" "#define _LINUX_SOURCE_COMPAT 1" >>confdefs.h
+
+
+ # For AIX we build in support for both LAM and PAM
+ # and choose which to use based on auth_type in
+ # /etc/security/login.cfg
+ if test X"${with_pam}${with_aixauth}" = X""
+then :
+
+ AUTH_EXCL_DEF="AIX_AUTH PAM"
+
+fi
+
+ # AIX analog of nsswitch.conf, enabled by default
+
+# Check whether --with-netsvc was given.
+if test ${with_netsvc+y}
+then :
+ withval=$with_netsvc; case $with_netsvc in
+ no) ;;
+ yes) with_netsvc="/etc/netsvc.conf"
+ ;;
+ *) ;;
+ esac
+fi
+
+ if test -z "$with_nsswitch" -a -z "$with_netsvc"
+then :
+
+ with_netsvc="/etc/netsvc.conf"
+
+fi
+
+ # cfmakeraw is broken on AIX (and is not documented)
+ : ${ac_cv_func_cfmakeraw='no'}
+
+ # strnlen/strndup may be broken on AIX < 6 depending
+ # on the libc version, use our own.
+ if test $OSMAJOR -lt 6
+then :
+
+ : ${ac_cv_func_strnlen='no'}
+
+fi
+
+ # fmemopen(3) has a bug wrt feof() on some AIX versions.
+ # https://www.ibm.com/support/pages/apar/IJ11845
+ : ${ac_cv_func_fmemopen='no'}
+
+ # getdelim() may or may not be present on AIX <= 6.1.
+ # bos610 is missing getdelim but bos61J has it.
+ if test "$enable_package_build" = "yes"
+then :
+
+ if test $OSMAJOR -le 6
+then :
+
+ : ${ac_cv_func_getdelim='no'}
+
+fi
+
+fi
+
+ # memset_s() may or may ont be present on AIX <= 7.1.
+ # bos710 is missing memset_s but bos71L has it.
+ if test "$enable_package_build" = "yes"
+then :
+
+ if test $OSMAJOR -le 7
+then :
+
+ : ${ac_cv_func_memset_s='no'}
+
+fi
+
+fi
+
+ # Remove timedir on boot, AIX does not have /var/run
+ INIT_SCRIPT=aix.sh
+ INIT_DIR=/etc/rc.d/init.d
+ RC_LINK=/etc/rc.d/rc2.d/S90sudo
+
+ # AIX-specific functions
+ ac_fn_c_check_func "$LINENO" "getuserattr" "ac_cv_func_getuserattr"
+if test "x$ac_cv_func_getuserattr" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETUSERATTR 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "setrlimit64" "ac_cv_func_setrlimit64"
+if test "x$ac_cv_func_setrlimit64" = xyes
+then :
+ printf "%s\n" "#define HAVE_SETRLIMIT64 1" >>confdefs.h
+
+fi
+
+
+ for ac_func in setauthdb
+do :
+ ac_fn_c_check_func "$LINENO" "setauthdb" "ac_cv_func_setauthdb"
+if test "x$ac_cv_func_setauthdb" = xyes
+then :
+ printf "%s\n" "#define HAVE_SETAUTHDB 1" >>confdefs.h
+ ac_fn_c_check_type "$LINENO" "authdb_t" "ac_cv_type_authdb_t" "#include <usersec.h>
+"
+if test "x$ac_cv_type_authdb_t" = xyes
+then :
+
+printf "%s\n" "#define HAVE_AUTHDB_T 1" >>confdefs.h
+
+
+fi
+
+fi
+
+done
+
+ COMMON_OBJS="${COMMON_OBJS} aix.lo"
+
+ for _sym in aix_prep_user_v1 aix_restoreauthdb_v1 aix_setauthdb_v1 aix_setauthdb_v2 aix_getauthregistry_v1; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+
+ # These prototypes may be missing
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5
+printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; }
+if test ${ac_cv_c_undeclared_builtin_options+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_save_CFLAGS=$CFLAGS
+ ac_cv_c_undeclared_builtin_options='cannot detect'
+ for ac_arg in '' -fno-builtin; do
+ CFLAGS="$ac_save_CFLAGS $ac_arg"
+ # This test program should *not* compile successfully.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+(void) strchr;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else case e in #(
+ e) # This test program should compile successfully.
+ # No library function is consistently available on
+ # freestanding implementations, so test against a dummy
+ # declaration. Include always-available headers on the
+ # off chance that they somehow elicit warnings.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <float.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stddef.h>
+extern void ac_decl (int, char *);
+
+int
+main (void)
+{
+(void) ac_decl (0, (char *) 0);
+ (void) ac_decl;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ if test x"$ac_arg" = x
+then :
+ ac_cv_c_undeclared_builtin_options='none needed'
+else case e in #(
+ e) ac_cv_c_undeclared_builtin_options=$ac_arg ;;
+esac
+fi
+ break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ done
+ CFLAGS=$ac_save_CFLAGS
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_undeclared_builtin_options" >&5
+printf "%s\n" "$ac_cv_c_undeclared_builtin_options" >&6; }
+ case $ac_cv_c_undeclared_builtin_options in #(
+ 'cannot detect') :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "cannot make $CC report undeclared builtins
+See 'config.log' for more details" "$LINENO" 5; } ;; #(
+ 'none needed') :
+ ac_c_undeclared_builtin_options='' ;; #(
+ *) :
+ ac_c_undeclared_builtin_options=$ac_cv_c_undeclared_builtin_options ;;
+esac
+
+ac_fn_check_decl "$LINENO" "usrinfo" "ac_cv_have_decl_usrinfo" "
+#include <sys/types.h>
+#include <uinfo.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_usrinfo" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_USRINFO $ac_have_decl" >>confdefs.h
+
+ ac_fn_check_decl "$LINENO" "setauthdb" "ac_cv_have_decl_setauthdb" "
+#include <sys/types.h>
+#include <usersec.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_setauthdb" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_SETAUTHDB $ac_have_decl" >>confdefs.h
+
+ ;;
+ *-*-hiuxmpp*)
+ # HI-UX/MPP is based on OSF/1
+
+ # ignore envariables wrt dynamic lib path
+
+if test ${SUDO_LDFLAGS+y}
+then :
+
+ case " $SUDO_LDFLAGS " in #(
+ *" -Wl,-no_library_replacement "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDO_LDFLAGS already contains -Wl,-no_library_replacement"; } >&5
+ (: SUDO_LDFLAGS already contains -Wl,-no_library_replacement) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDO_LDFLAGS " -Wl,-no_library_replacement"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDO_LDFLAGS=\"\$SUDO_LDFLAGS\""; } >&5
+ (: SUDO_LDFLAGS="$SUDO_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDO_LDFLAGS=-Wl,-no_library_replacement
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDO_LDFLAGS=\"\$SUDO_LDFLAGS\""; } >&5
+ (: SUDO_LDFLAGS="$SUDO_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+ shadow_funcs="getprpwnam dispcrypt"
+ shadow_libs="-lsecurity"
+
+ : ${mansectsu='8'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ *-*-hpux*)
+ printf "%s\n" "#define PAM_SUN_CODEBASE 1" >>confdefs.h
+
+
+ # AFS support needs -lBSD
+ if test "$with_AFS" = "yes"
+then :
+ AFS_LIBS="-lc -lBSD"
+ ]
+fi
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+
+ # HP-UX does not clear /var/run so we need to do it
+ INIT_SCRIPT=hpux.sh
+ INIT_DIR=/sbin/init.d
+ RC_LINK=/sbin/rc2.d/S900sudo
+
+ # HP-UX shared libs must be executable.
+ # Load time is much greater if writable so use 0555.
+ SHLIB_MODE=0555
+
+ # HP-UX won't unlink a shared lib that is open
+ INSTALL_BACKUP='~'
+
+ # The HP bundled compiler cannot generate shared libs
+ if test -z "$GCC"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for HP bundled C compiler" >&5
+printf %s "checking for HP bundled C compiler... " >&6; }
+if test ${sudo_cv_var_hpccbundled+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if $CC -V 2>&1 | grep '^(Bundled)' >/dev/null 2>&1; then
+ sudo_cv_var_hpccbundled=yes
+ else
+ sudo_cv_var_hpccbundled=no
+ fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_var_hpccbundled" >&5
+printf "%s\n" "$sudo_cv_var_hpccbundled" >&6; }
+ if test "$sudo_cv_var_hpccbundled" = "yes"
+then :
+
+ as_fn_error $? "The HP bundled C compiler is unable to build Sudo, you must use gcc or the HP ANSI C compiler instead." "$LINENO" 5
+
+fi
+
+fi
+
+ # Build PA-RISC1.1 objects for better portability
+ case "$host_cpu" in
+ hppa[2-9]*)
+ _CFLAGS="$CFLAGS"
+ if test -n "$GCC"
+then :
+
+ portable_flag="-march=1.1"
+
+else case e in #(
+ e)
+ portable_flag="+DAportable"
+ ;;
+esac
+fi
+ CFLAGS="$CFLAGS $portable_flag"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands $portable_flag" >&5
+printf %s "checking whether $CC understands $portable_flag... " >&6; }
+if test ${sudo_cv_var_daportable+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ sudo_cv_var_daportable=yes
+else case e in #(
+ e) sudo_cv_var_daportable=no
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_var_daportable" >&5
+printf "%s\n" "$sudo_cv_var_daportable" >&6; }
+ if test X"$sudo_cv_var_daportable" != X"yes"
+then :
+
+ CFLAGS="$_CFLAGS"
+
+fi
+ ;;
+ esac
+
+ case "$host_os" in
+ hpux10.*)
+ shadow_funcs="getprpwnam iscomsec"
+ shadow_libs="-lsec"
+ # HP-UX 10.x doesn't support LD_PRELOAD
+ with_noexec=no
+ ;;
+ *)
+ shadow_funcs="getspnam iscomsec"
+ shadow_libs="-lsec"
+ test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+ ;;
+ esac
+ ac_fn_c_check_header_compile "$LINENO" "utmps.h" "ac_cv_header_utmps_h" "$ac_includes_default"
+if test "x$ac_cv_header_utmps_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_UTMPS_H 1" >>confdefs.h
+
+fi
+
+ ac_fn_c_check_func "$LINENO" "pstat_getproc" "ac_cv_func_pstat_getproc"
+if test "x$ac_cv_func_pstat_getproc" = xyes
+then :
+ printf "%s\n" "#define HAVE_PSTAT_GETPROC 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "gethrtime" "ac_cv_func_gethrtime"
+if test "x$ac_cv_func_gethrtime" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETHRTIME 1" >>confdefs.h
+
+fi
+
+ ;;
+ *-dec-osf*)
+ # ignore envariables wrt dynamic lib path
+
+if test ${SUDO_LDFLAGS+y}
+then :
+
+ case " $SUDO_LDFLAGS " in #(
+ *" -Wl,-no_library_replacement "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDO_LDFLAGS already contains -Wl,-no_library_replacement"; } >&5
+ (: SUDO_LDFLAGS already contains -Wl,-no_library_replacement) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDO_LDFLAGS " -Wl,-no_library_replacement"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDO_LDFLAGS=\"\$SUDO_LDFLAGS\""; } >&5
+ (: SUDO_LDFLAGS="$SUDO_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDO_LDFLAGS=-Wl,-no_library_replacement
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDO_LDFLAGS=\"\$SUDO_LDFLAGS\""; } >&5
+ (: SUDO_LDFLAGS="$SUDO_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+ : ${CHECKSIA='true'}
+ # Check whether --enable-sia was given.
+if test ${enable_sia+y}
+then :
+ enableval=$enable_sia; case "$enableval" in
+ yes) CHECKSIA=true
+ ;;
+ no) CHECKSIA=false
+ ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-sia: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-sia: $enableval" >&2;}
+ ;;
+ esac
+
+fi
+
+
+ shadow_funcs="getprpwnam dispcrypt"
+ # OSF/1 4.x and higher need -ldb too
+ if test $OSMAJOR -lt 4
+then :
+
+ shadow_libs="-lsecurity -laud -lm"
+
+else case e in #(
+ e)
+ shadow_libs="-lsecurity -ldb -laud -lm"
+ ;;
+esac
+fi
+
+ # use SIA by default, if we have it
+ test "$CHECKSIA" = "true" && AUTH_EXCL_DEF="SIA"
+
+ #
+ # Some versions of Digital Unix ship with a broken
+ # copy of prot.h, which we need for shadow passwords.
+ # XXX - make should remove this as part of distclean
+ #
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for broken prot.h" >&5
+printf %s "checking for broken prot.h... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/security.h>
+#include <prot.h>
+
+int
+main (void)
+{
+return(0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes, fixing locally" >&5
+printf "%s\n" "yes, fixing locally" >&6; }
+ sed 's:<acl.h>:<sys/acl.h>:g' < /usr/include/prot.h > prot.h
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+
+ : ${mansectsu='8'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ *-*-irix*)
+ printf "%s\n" "#define _BSD_TYPES 1" >>confdefs.h
+
+ if test "$prefix" = "/usr/local" -a "$mandir" = '${datarootdir}/man'
+then :
+
+ if test -d "/usr/share/man/local"
+then :
+
+ mandir="/usr/share/man/local"
+
+else case e in #(
+ e)
+ mandir="/usr/man/local"
+ ;;
+esac
+fi
+
+fi
+ # IRIX <= 4 needs -lsun
+ if test "$OSMAJOR" -le 4
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getpwnam in -lsun" >&5
+printf %s "checking for getpwnam in -lsun... " >&6; }
+if test ${ac_cv_lib_sun_getpwnam+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsun $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getpwnam (void);
+int
+main (void)
+{
+return getpwnam ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_sun_getpwnam=yes
+else case e in #(
+ e) ac_cv_lib_sun_getpwnam=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sun_getpwnam" >&5
+printf "%s\n" "$ac_cv_lib_sun_getpwnam" >&6; }
+if test "x$ac_cv_lib_sun_getpwnam" = xyes
+then :
+ LIBS="${LIBS} -lsun"
+fi
+
+
+fi
+
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ *-*-linux*|*-*-k*bsd*-gnu)
+ shadow_funcs="getspnam"
+ test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+ # Check for SECCOMP_MODE_FILTER in linux/seccomp.h
+ ac_fn_check_decl "$LINENO" "SECCOMP_MODE_FILTER" "ac_cv_have_decl_SECCOMP_MODE_FILTER" "
+#include <sys/types.h>
+#include <sys/prctl.h>
+#include <asm/unistd.h>
+#include <linux/seccomp.h>
+#include <linux/filter.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SECCOMP_MODE_FILTER" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_SECCOMP_MODE_FILTER $ac_have_decl" >>confdefs.h
+
+ # We call getrandom via syscall(3) in case it is not in libc
+ ac_fn_c_check_header_compile "$LINENO" "linux/random.h" "ac_cv_header_linux_random_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_random_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_LINUX_RANDOM_H 1" >>confdefs.h
+
+fi
+ac_fn_c_check_header_compile "$LINENO" "sys/syscall.h" "ac_cv_header_sys_syscall_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_syscall_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_SYSCALL_H 1" >>confdefs.h
+
+fi
+
+
+ # Only use our replacement functions when not fuzzing,
+ # they may skew the coverage reports.
+ if test X"$enable_fuzzer" = X"no"
+then :
+
+ # glibc's getentropy() emulation may fail on older kernels.
+ # We use our own getentropy() by default on Linux.
+ : ${ac_cv_func_getentropy='no'}
+
+ # glibc's arc4random() may fail in chroot on older kernels.
+ # We use our own arc4random() by default on Linux.
+ : ${ac_cv_func_arc4random='no'}
+
+ # glibc's closefrom() emulation may fail in chroot.
+ # We use our own closefrom() by default on Linux.
+ : ${ac_cv_func_closefrom='no'}
+
+fi
+
+ # Linux 3.2 supports reading/writing a another process
+ # without using ptrace(2).
+ ac_fn_c_check_func "$LINENO" "process_vm_readv" "ac_cv_func_process_vm_readv"
+if test "x$ac_cv_func_process_vm_readv" = xyes
+then :
+ printf "%s\n" "#define HAVE_PROCESS_VM_READV 1" >>confdefs.h
+
+fi
+
+ ;;
+ *-*-gnu*)
+ # lockf() is broken on the Hurd
+ ac_cv_func_lockf=no
+ ;;
+ *-*-sco*|*-sco-*)
+ shadow_funcs="getprpwnam"
+ shadow_libs="-lprot -lx"
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ m88k-motorola-sysv*)
+ # motorolla's cc (a variant of gcc) does -O but not -O2
+ CFLAGS=`echo $CFLAGS | sed 's/-O2/-O/g'`
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ *-sequent-sysv*)
+ shadow_funcs="getspnam"
+ shadow_libs="-lsec"
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ *-ncr-sysv4*|*-ncr-sysvr4*)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for strcasecmp in -lc89" >&5
+printf %s "checking for strcasecmp in -lc89... " >&6; }
+if test ${ac_cv_lib_c89_strcasecmp+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc89 $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char strcasecmp (void);
+int
+main (void)
+{
+return strcasecmp ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_c89_strcasecmp=yes
+else case e in #(
+ e) ac_cv_lib_c89_strcasecmp=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c89_strcasecmp" >&5
+printf "%s\n" "$ac_cv_lib_c89_strcasecmp" >&6; }
+if test "x$ac_cv_lib_c89_strcasecmp" = xyes
+then :
+ LIBS="${LIBS} -lc89"
+fi
+
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ *-ccur-sysv4*|*-ccur-sysvr4*)
+ LIBS="${LIBS} -lgen"
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ *-*-bsdi*)
+ SKIP_SETREUID=yes
+ # Check for newer BSD auth API
+ if test -z "$with_bsdauth"
+then :
+
+
+ for ac_func in auth_challenge
+do :
+ ac_fn_c_check_func "$LINENO" "auth_challenge" "ac_cv_func_auth_challenge"
+if test "x$ac_cv_func_auth_challenge" = xyes
+then :
+ printf "%s\n" "#define HAVE_AUTH_CHALLENGE 1" >>confdefs.h
+ AUTH_EXCL_DEF="BSD_AUTH"
+fi
+
+done
+
+fi
+ ;;
+ *-*-freebsd*)
+ printf "%s\n" "#define _BSD_SOURCE 1" >>confdefs.h
+
+
+ # FreeBSD has a real setreuid(2) starting with 2.1 and
+ # backported to 2.0.5. We just take 2.1 and above...
+ case "$OSREV" in
+ 0.*|1.*|2.0*)
+ SKIP_SETREUID=yes
+ ;;
+ esac
+ if test "${with_skey-'no'}" = "yes"
+then :
+
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lmd"
+
+fi
+ CHECKSHADOW="false"
+ test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+ : ${with_logincap='maybe'}
+
+ # Examples go in share/examples/sudo
+ if test X"$with_exampledir" = X""
+then :
+
+ exampledir='$(datarootdir)/examples/$(PACKAGE_TARNAME)'
+
+fi
+ ;;
+ *-*-*openbsd*)
+ printf "%s\n" "#define _BSD_SOURCE 1" >>confdefs.h
+
+
+ # OpenBSD-specific initialization
+ OS_INIT=os_init_openbsd
+ SUDO_OBJS="${SUDO_OBJS} openbsd.o"
+
+ # OpenBSD has a real setreuid(2) starting with 3.3 but
+ # we will use setresuid(2) instead.
+ SKIP_SETREUID=yes
+
+ # OpenBSD >= 3.0 supports BSD auth
+ if test -z "$with_bsdauth"
+then :
+
+ if test "$OSMAJOR" -ge 3
+then :
+
+ AUTH_EXCL_DEF="BSD_AUTH"
+
+fi
+
+fi
+ : ${with_logincap='maybe'}
+
+ # Newer OpenBSD only fills in pw_password for getpwnam_shadow()
+ shadow_funcs="getpwnam_shadow"
+
+ # Examples go in share/examples/sudo
+ if test X"$with_exampledir" = X""
+then :
+
+ exampledir='$(datarootdir)/examples/$(PACKAGE_TARNAME)'
+
+fi
+ ;;
+ *-*-*netbsd*)
+ # NetBSD has a real setreuid(2) starting with 1.3.2
+ case "$OSREV" in
+ 0.9*|1.[012]*|1.3|1.3.1)
+ SKIP_SETREUID=yes
+ ;;
+ esac
+ CHECKSHADOW="false"
+ test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+ : ${with_logincap='maybe'}
+
+ # For reallocarray()
+ printf "%s\n" "#define _OPENBSD_SOURCE 1" >>confdefs.h
+
+
+ # Examples go in share/examples/sudo
+ if test X"$with_exampledir" = X""
+then :
+
+ exampledir='$(datarootdir)/examples/$(PACKAGE_TARNAME)'
+
+fi
+ ;;
+ *-*-dragonfly*)
+ printf "%s\n" "#define _BSD_SOURCE 1" >>confdefs.h
+
+
+ if test "${with_skey-'no'}" = "yes"
+then :
+
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lmd"
+
+fi
+ CHECKSHADOW="false"
+ test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+ : ${with_logincap='yes'}
+
+ # Examples go in share/examples/sudo
+ if test X"$with_exampledir" = X""
+then :
+
+ exampledir='$(datarootdir)/examples/$(PACKAGE_TARNAME)'
+
+fi
+ ;;
+ *-*-*bsd*)
+ CHECKSHADOW="false"
+ # Examples go in share/examples/sudo
+ if test X"$with_exampledir" = X""
+then :
+
+ exampledir='$(datarootdir)/examples/$(PACKAGE_TARNAME)'
+
+fi
+ ;;
+ *-*-darwin*)
+ # Darwin has a real setreuid(2) starting with 9.0
+ if test $OSMAJOR -lt 9
+then :
+
+ SKIP_SETREUID=yes
+
+fi
+ CHECKSHADOW="false"
+ test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+ : ${with_logincap='yes'}
+ # Darwin has a broken poll(), Apple radar 3710161
+ : ${enable_poll='no'}
+
+ # Build sudo_noexec.so as a shared library, not a module.
+ # On Darwin, modules and shared libraries are incompatible.
+ PRELOAD_MODULE=
+
+ # Mach monotonic timer that runs while sleeping
+ ac_fn_c_check_func "$LINENO" "mach_continuous_time" "ac_cv_func_mach_continuous_time"
+if test "x$ac_cv_func_mach_continuous_time" = xyes
+then :
+ printf "%s\n" "#define HAVE_MACH_CONTINUOUS_TIME 1" >>confdefs.h
+
+fi
+
+
+ # Undocumented API that dynamically allocates the groups.
+
+ for ac_func in getgrouplist_2
+do :
+ ac_fn_c_check_func "$LINENO" "getgrouplist_2" "ac_cv_func_getgrouplist_2"
+if test "x$ac_cv_func_getgrouplist_2" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETGROUPLIST_2 1" >>confdefs.h
+ ac_fn_check_decl "$LINENO" "getgrouplist_2" "ac_cv_have_decl_getgrouplist_2" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_getgrouplist_2" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_GETGROUPLIST_2 $ac_have_decl" >>confdefs.h
+
+fi
+
+done
+
+ # We use proc_pidinfo() to emulate closefrom() on macOS.
+ for ac_header in libproc.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "libproc.h" "ac_cv_header_libproc_h" "$ac_includes_default"
+if test "x$ac_cv_header_libproc_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBPROC_H 1" >>confdefs.h
+ ac_fn_c_check_func "$LINENO" "proc_pidinfo" "ac_cv_func_proc_pidinfo"
+if test "x$ac_cv_func_proc_pidinfo" = xyes
+then :
+ printf "%s\n" "#define HAVE_PROC_PIDINFO 1" >>confdefs.h
+
+fi
+
+fi
+
+done
+
+ # We cannot directly access environ from a shared object
+ for ac_header in crt_externs.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "crt_externs.h" "ac_cv_header_crt_externs_h" "$ac_includes_default"
+if test "x$ac_cv_header_crt_externs_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_CRT_EXTERNS_H 1" >>confdefs.h
+ ac_fn_c_check_func "$LINENO" "_NSGetEnviron" "ac_cv_func__NSGetEnviron"
+if test "x$ac_cv_func__NSGetEnviron" = xyes
+then :
+ printf "%s\n" "#define HAVE__NSGETENVIRON 1" >>confdefs.h
+
+fi
+
+fi
+
+done
+
+ # We need to force a flat namespace to make libc
+ # symbol hooking work like it does on ELF.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,-force_flat_namespace" >&5
+printf %s "checking whether the linker accepts -Wl,-force_flat_namespace... " >&6; }
+if test ${ax_cv_check_ldflags___Wl__force_flat_namespace+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-force_flat_namespace"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_check_ldflags___Wl__force_flat_namespace=yes
+else case e in #(
+ e) ax_cv_check_ldflags___Wl__force_flat_namespace=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl__force_flat_namespace" >&5
+printf "%s\n" "$ax_cv_check_ldflags___Wl__force_flat_namespace" >&6; }
+if test x"$ax_cv_check_ldflags___Wl__force_flat_namespace" = xyes
+then :
+
+if test ${SUDO_LDFLAGS+y}
+then :
+
+ case " $SUDO_LDFLAGS " in #(
+ *" -Wl,-force_flat_namespace "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDO_LDFLAGS already contains -Wl,-force_flat_namespace"; } >&5
+ (: SUDO_LDFLAGS already contains -Wl,-force_flat_namespace) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDO_LDFLAGS " -Wl,-force_flat_namespace"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDO_LDFLAGS=\"\$SUDO_LDFLAGS\""; } >&5
+ (: SUDO_LDFLAGS="$SUDO_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDO_LDFLAGS=-Wl,-force_flat_namespace
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDO_LDFLAGS=\"\$SUDO_LDFLAGS\""; } >&5
+ (: SUDO_LDFLAGS="$SUDO_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+
+ # Examples go in share/examples/sudo
+ if test X"$with_exampledir" = X""
+then :
+
+ exampledir='$(datarootdir)/examples/$(PACKAGE_TARNAME)'
+
+fi
+ ;;
+ *-*-nextstep*)
+ # lockf() is broken on the NeXT
+ ac_cv_func_lockf=no
+ ;;
+ *-*-*sysv4*)
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ *-*-*sco3.2*) # SCO OpenServer 5
+ : ${mansectsu='1'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ shadow_funcs="getprpwnam"
+ shadow_libs="-lprot"
+ ;;
+# UnixWare 7.x, OpenUNIX 8
+ *-*-*sysv5*)
+ : ${mansectsu='1'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ case "$host" in
+ *-*-sysv5SCO_SV*) # SCO OpenServer 6.x
+ shadow_funcs="getprpwnam"
+ shadow_libs="-lprot"
+ ;;
+ *) shadow_funcs="getspnam"
+ test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+ ;;
+ esac
+ ;;
+ *-*-sysv*)
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+esac
+
+AUTH_REG=${AUTH_REG# }
+AUTH_EXCL=${AUTH_EXCL# }
+if test -n "$AUTH_EXCL" -a -n "$AUTH_REG"
+then :
+
+ as_fn_error $? "Cannot mix mutually exclusive ($AUTH_EXCL) and regular ($AUTH_REG) authentication methods" "$LINENO" 5
+
+fi
+if test X"${with_skey}${with_opie}" = X"yesyes"
+then :
+
+ as_fn_error $? "cannot use both S/Key and OPIE" "$LINENO" 5
+
+fi
+
+: ${mansectsu='8'}
+: ${mansectform='5'}
+: ${mansectmisc='7'}
+
+if test -n "$with_libpath"
+then :
+
+ for i in ${with_libpath}; do
+
+
+if test ${LDFLAGS+y}
+then :
+
+ case " $LDFLAGS " in #(
+ *" -L$i "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS already contains -L\$i"; } >&5
+ (: LDFLAGS already contains -L$i) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LDFLAGS " -L$i"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS\""; } >&5
+ (: LDFLAGS="$LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LDFLAGS=-L$i
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS\""; } >&5
+ (: LDFLAGS="$LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${LDFLAGS_R+y}
+then :
+
+ case " $LDFLAGS_R " in #(
+ *" -R$i "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS_R already contains -R\$i"; } >&5
+ (: LDFLAGS_R already contains -R$i) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LDFLAGS_R " -R$i"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS_R=\"\$LDFLAGS_R\""; } >&5
+ (: LDFLAGS_R="$LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LDFLAGS_R=-R$i
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS_R=\"\$LDFLAGS_R\""; } >&5
+ (: LDFLAGS_R="$LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+ done
+
+fi
+if test -n "$with_libraries"
+then :
+
+ for i in ${with_libraries}; do
+ case $i in
+ -l*) ;;
+ *.a) ;;
+ *.o) ;;
+ *) i="-l${i}";;
+ esac
+ LIBS="${LIBS} ${i}"
+ done
+
+fi
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
+printf %s "checking for an ANSI C-conforming const... " >&6; }
+if test ${ac_cv_c_const+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this sort of thing. */
+ typedef int charset[2];
+ const charset cs = { 0, 0 };
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *pcpcc;
+ char **ppc;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* IBM XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ pcpcc = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++pcpcc;
+ ppc = (char**) pcpcc;
+ pcpcc = (char const *const *) ppc;
+ { /* SCO 3.2v4 cc rejects this sort of thing. */
+ char tx;
+ char *t = &tx;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ if (s) return 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* IBM XL C 1.02.0.0 rejects this sort of thing, saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; } bx;
+ struct s *b = &bx; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ if (!foo) return 0;
+ }
+ return !cs[0] && !zero.x;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_c_const=yes
+else case e in #(
+ e) ac_cv_c_const=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5
+printf "%s\n" "$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+printf "%s\n" "#define const /**/" >>confdefs.h
+
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5
+printf %s "checking for C/C++ restrict keyword... " >&6; }
+if test ${ac_cv_c_restrict+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_cv_c_restrict=no
+ # Put '__restrict__' first, to avoid problems with glibc and non-GCC; see:
+ # https://lists.gnu.org/archive/html/bug-autoconf/2016-02/msg00006.html
+ # Put 'restrict' last, because C++ lacks it.
+ for ac_kw in __restrict__ __restrict _Restrict restrict; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+typedef int *int_ptr;
+ int foo (int_ptr $ac_kw ip) { return ip[0]; }
+ int bar (int [$ac_kw]); /* Catch GCC bug 14050. */
+ int bar (int ip[$ac_kw]) { return ip[0]; }
+
+int
+main (void)
+{
+int s[1];
+ int *$ac_kw t = s;
+ t[0] = 0;
+ return foo (t) + bar (t);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_c_restrict=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ test "$ac_cv_c_restrict" != no && break
+ done
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_restrict" >&5
+printf "%s\n" "$ac_cv_c_restrict" >&6; }
+
+ case $ac_cv_c_restrict in
+ restrict) ;;
+ no) printf "%s\n" "#define restrict /**/" >>confdefs.h
+ ;;
+ *) printf "%s\n" "#define restrict $ac_cv_c_restrict" >>confdefs.h
+ ;;
+ esac
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+printf %s "checking for inline... " >&6; }
+if test ${ac_cv_c_inline+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo (void) {return 0; }
+$ac_kw foo_t foo (void) {return 0; }
+#endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_c_inline=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ test "$ac_cv_c_inline" != no && break
+done
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
+printf "%s\n" "$ac_cv_c_inline" >&6; }
+
+case $ac_cv_c_inline in
+ inline | yes) ;;
+ *)
+ case $ac_cv_c_inline in
+ no) ac_val=;;
+ *) ac_val=$ac_cv_c_inline;;
+ esac
+ cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+ ;;
+esac
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working volatile" >&5
+printf %s "checking for working volatile... " >&6; }
+if test ${ac_cv_c_volatile+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+volatile int x;
+int * volatile y = (int *) 0;
+return !x && !y;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_c_volatile=yes
+else case e in #(
+ e) ac_cv_c_volatile=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_volatile" >&5
+printf "%s\n" "$ac_cv_c_volatile" >&6; }
+if test $ac_cv_c_volatile = no; then
+
+printf "%s\n" "#define volatile /**/" >>confdefs.h
+
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for variadic macro support in cpp" >&5
+printf %s "checking for variadic macro support in cpp... " >&6; }
+if test ${sudo_cv_cpp_variadic_macros+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ sudo_cv_cpp_variadic_macros=yes
+ if test X"$ac_cv_build_prog_cc_c99" = X"no"; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+#if defined(__GNUC__) && __GNUC__ == 2
+# define sudo_fprintf(fp, fmt...) fprintf((fp), (fmt))
+#else
+# define sudo_fprintf(fp, ...) fprintf((fp), __VA_ARGS__)
+#endif
+int
+main (void)
+{
+sudo_fprintf(stderr, "a %s", "test");
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else case e in #(
+ e) sudo_cv_cpp_variadic_macros=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_cpp_variadic_macros" >&5
+printf "%s\n" "$sudo_cv_cpp_variadic_macros" >&6; }
+ if test X"$sudo_cv_cpp_variadic_macros" = X"no"; then
+
+printf "%s\n" "#define NO_VARIADIC_MACROS 1" >>confdefs.h
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: your C preprocessor doesn't support variadic macros, debugging support will be limited" >&5
+printf "%s\n" "$as_me: WARNING: your C preprocessor doesn't support variadic macros, debugging support will be limited" >&2;}
+
+ for _sym in sudo_debug_printf_nvm_v1; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ fi
+
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_AWK+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AWK="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+printf "%s\n" "$AWK" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+for ac_prog in 'bison -y' byacc
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_YACC+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$YACC"; then
+ ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_YACC="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi ;;
+esac
+fi
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5
+printf "%s\n" "$YACC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+# Extract the first word of "flex", so it can be a program name with args.
+set dummy flex; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_FLEX+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) case $FLEX in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_FLEX="$FLEX" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_FLEX="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_FLEX" && ac_cv_path_FLEX="flex"
+ ;;
+esac ;;
+esac
+fi
+FLEX=$ac_cv_path_FLEX
+if test -n "$FLEX"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FLEX" >&5
+printf "%s\n" "$FLEX" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+
+ # Extract the first word of "mv", so it can be a program name with args.
+set dummy mv; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_MVPROG+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) case $MVPROG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_MVPROG="$MVPROG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /usr/bin$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/ucb$PATH_SEPARATOR/usr/local/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_MVPROG="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac ;;
+esac
+fi
+MVPROG=$ac_cv_path_MVPROG
+if test -n "$MVPROG"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MVPROG" >&5
+printf "%s\n" "$MVPROG" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "${ac_cv_path_MVPROG}" && cat >>confdefs.h <<EOF
+#define _PATH_MV "${ac_cv_path_MVPROG}"
+EOF
+
+
+
+ # Extract the first word of "sh", so it can be a program name with args.
+set dummy sh; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_BSHELLPROG+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) case $BSHELLPROG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_BSHELLPROG="$BSHELLPROG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_BSHELLPROG="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_BSHELLPROG" && ac_cv_path_BSHELLPROG="/usr/bin$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/sbin"
+ ;;
+esac ;;
+esac
+fi
+BSHELLPROG=$ac_cv_path_BSHELLPROG
+if test -n "$BSHELLPROG"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $BSHELLPROG" >&5
+printf "%s\n" "$BSHELLPROG" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "${ac_cv_path_BSHELLPROG}" && cat >>confdefs.h <<EOF
+#define _PATH_BSHELL "${ac_cv_path_BSHELLPROG}"
+EOF
+
+
+if test -z "$with_sendmail"
+then :
+
+
+ # Extract the first word of "sendmail", so it can be a program name with args.
+set dummy sendmail; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_SENDMAILPROG+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) case $SENDMAILPROG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_SENDMAILPROG="$SENDMAILPROG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /usr/sbin$PATH_SEPARATOR/usr/lib$PATH_SEPARATOR/usr/etc$PATH_SEPARATOR/usr/ucblib$PATH_SEPARATOR/usr/local/lib$PATH_SEPARATOR/usr/local/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_SENDMAILPROG="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac ;;
+esac
+fi
+SENDMAILPROG=$ac_cv_path_SENDMAILPROG
+if test -n "$SENDMAILPROG"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SENDMAILPROG" >&5
+printf "%s\n" "$SENDMAILPROG" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "${ac_cv_path_SENDMAILPROG}" && cat >>confdefs.h <<EOF
+#define _PATH_SUDO_SENDMAIL "${ac_cv_path_SENDMAILPROG}"
+EOF
+
+
+ with_sendmail="$ac_cv_path_SENDMAILPROG"
+
+fi
+
+ # Extract the first word of "vi", so it can be a program name with args.
+set dummy vi; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_VIPROG+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) case $VIPROG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_VIPROG="$VIPROG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /usr/bin$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/ucb$PATH_SEPARATOR/usr/bsd$PATH_SEPARATOR/usr/local/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_VIPROG="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac ;;
+esac
+fi
+VIPROG=$ac_cv_path_VIPROG
+if test -n "$VIPROG"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $VIPROG" >&5
+printf "%s\n" "$VIPROG" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "${ac_cv_path_VIPROG}" && cat >>confdefs.h <<EOF
+#define _PATH_VI "${ac_cv_path_VIPROG}"
+EOF
+
+
+if test -z "$with_editor"
+then :
+
+ editor="$ac_cv_path_VIPROG"
+
+fi
+if test X"$with_logfac" = X""
+then :
+
+ ac_fn_check_decl "$LINENO" "LOG_AUTHPRIV" "ac_cv_have_decl_LOG_AUTHPRIV" "#include <syslog.h>
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_LOG_AUTHPRIV" = xyes
+then :
+ logfac=authpriv
+fi
+
+fi
+
+printf "%s\n" "#define LOGFAC \"$logfac\"" >>confdefs.h
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+ as_ac_Header=`printf "%s\n" "ac_cv_header_dirent_$ac_hdr" | sed "$as_sed_sh"`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5
+printf %s "checking for $ac_hdr that defines DIR... " >&6; }
+if eval test \${$as_ac_Header+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <$ac_hdr>
+
+int
+main (void)
+{
+if ((DIR *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ eval "$as_ac_Header=yes"
+else case e in #(
+ e) eval "$as_ac_Header=no" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+eval ac_res=\$$as_ac_Header
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_hdr" | sed "$as_sed_cpp"` 1
+_ACEOF
+
+ac_header_dirent=$ac_hdr; break
+fi
+
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5
+printf %s "checking for library containing opendir... " >&6; }
+if test ${ac_cv_search_opendir+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char opendir (void);
+int
+main (void)
+{
+return opendir ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' dir
+do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_search_opendir=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext
+ if test ${ac_cv_search_opendir+y}
+then :
+ break
+fi
+done
+if test ${ac_cv_search_opendir+y}
+then :
+
+else case e in #(
+ e) ac_cv_search_opendir=no ;;
+esac
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5
+printf "%s\n" "$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no
+then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5
+printf %s "checking for library containing opendir... " >&6; }
+if test ${ac_cv_search_opendir+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char opendir (void);
+int
+main (void)
+{
+return opendir ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' x
+do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_search_opendir=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext
+ if test ${ac_cv_search_opendir+y}
+then :
+ break
+fi
+done
+if test ${ac_cv_search_opendir+y}
+then :
+
+else case e in #(
+ e) ac_cv_search_opendir=no ;;
+esac
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5
+printf "%s\n" "$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no
+then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+fi
+
+ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default"
+if test "x$ac_cv_type__Bool" = xyes
+then :
+
+printf "%s\n" "#define HAVE__BOOL 1" >>confdefs.h
+
+
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99 or later" >&5
+printf %s "checking for stdbool.h that conforms to C99 or later... " >&6; }
+if test ${ac_cv_header_stdbool_h+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdbool.h>
+
+ /* "true" and "false" should be usable in #if expressions and
+ integer constant expressions, and "bool" should be a valid
+ type name.
+
+ Although C99 requires bool, true, and false to be macros,
+ C23 and C++11 overrule that, so do not test for that.
+ Although C99 requires __bool_true_false_are_defined and
+ _Bool, C23 says they are obsolescent, so do not require
+ them. */
+
+ #if !true
+ #error "'true' is not true"
+ #endif
+ #if true != 1
+ #error "'true' is not equal to 1"
+ #endif
+ char b[true == 1 ? 1 : -1];
+ char c[true];
+
+ #if false
+ #error "'false' is not false"
+ #endif
+ #if false != 0
+ #error "'false' is not equal to 0"
+ #endif
+ char d[false == 0 ? 1 : -1];
+
+ enum { e = false, f = true, g = false * true, h = true * 256 };
+
+ char i[(bool) 0.5 == true ? 1 : -1];
+ char j[(bool) 0.0 == false ? 1 : -1];
+ char k[sizeof (bool) > 0 ? 1 : -1];
+
+ struct sb { bool s: 1; bool t; } s;
+ char l[sizeof s.t > 0 ? 1 : -1];
+
+ /* The following fails for
+ HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */
+ bool m[h];
+ char n[sizeof m == h * sizeof m[0] ? 1 : -1];
+ char o[-1 - (bool) 0 < 0 ? 1 : -1];
+ /* Catch a bug in an HP-UX C compiler. See
+ https://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
+ https://lists.gnu.org/r/bug-coreutils/2005-11/msg00161.html
+ */
+ bool p = true;
+ bool *pp = &p;
+
+int
+main (void)
+{
+
+ bool ps = &s;
+ *pp |= p;
+ *pp |= ! p;
+
+ /* Refer to every declared value, so they cannot be
+ discarded as unused. */
+ return (!b + !c + !d + !e + !f + !g + !h + !i + !j + !k
+ + !l + !m + !n + !o + !p + !pp + !ps);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_header_stdbool_h=yes
+else case e in #(
+ e) ac_cv_header_stdbool_h=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5
+printf "%s\n" "$ac_cv_header_stdbool_h" >&6; }
+
+if test $ac_cv_header_stdbool_h = yes; then
+
+printf "%s\n" "#define HAVE_STDBOOL_H 1" >>confdefs.h
+
+fi
+
+
+ac_fn_c_check_header_compile "$LINENO" "sys/mkdev.h" "ac_cv_header_sys_mkdev_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_mkdev_h" = xyes
+then :
+
+printf "%s\n" "#define MAJOR_IN_MKDEV 1" >>confdefs.h
+
+fi
+
+if test $ac_cv_header_sys_mkdev_h = no; then
+ ac_fn_c_check_header_compile "$LINENO" "sys/sysmacros.h" "ac_cv_header_sys_sysmacros_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_sysmacros_h" = xyes
+then :
+
+printf "%s\n" "#define MAJOR_IN_SYSMACROS 1" >>confdefs.h
+
+fi
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+if test X"$ac_cv_header_utmps_h" != X"yes"
+then :
+
+ ac_fn_c_check_header_compile "$LINENO" "utmpx.h" "ac_cv_header_utmpx_h" "$ac_includes_default"
+if test "x$ac_cv_header_utmpx_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_UTMPX_H 1" >>confdefs.h
+
+fi
+
+
+fi
+ for ac_header in endian.h sys/endian.h machine/endian.h
+do :
+ as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | sed "$as_sed_sh"`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_header" | sed "$as_sed_cpp"` 1
+_ACEOF
+ break
+fi
+
+done
+ for ac_header in procfs.h sys/procfs.h
+do :
+ as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | sed "$as_sed_sh"`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_header" | sed "$as_sed_cpp"` 1
+_ACEOF
+ ac_fn_c_check_member "$LINENO" "struct psinfo" "pr_ttydev" "ac_cv_member_struct_psinfo_pr_ttydev" "$ac_includes_default
+#ifdef HAVE_PROCFS_H
+#include <procfs.h>
+#endif
+#ifdef HAVE_SYS_PROCFS_H
+#include <sys/procfs.h>
+#endif
+
+"
+if test "x$ac_cv_member_struct_psinfo_pr_ttydev" = xyes
+then :
+
+printf "%s\n" "#define HAVE_STRUCT_PSINFO_PR_TTYDEV 1" >>confdefs.h
+
+ac_fn_c_check_func "$LINENO" "_ttyname_dev" "ac_cv_func__ttyname_dev"
+if test "x$ac_cv_func__ttyname_dev" = xyes
+then :
+ printf "%s\n" "#define HAVE__TTYNAME_DEV 1" >>confdefs.h
+
+fi
+
+fi
+
+break
+fi
+
+done
+#
+# Check for large file and 64-bit time support.
+#
+# Check whether --enable-largefile was given.
+if test ${enable_largefile+y}
+then :
+ enableval=$enable_largefile;
+fi
+if test "$enable_largefile,$enable_year2038" != no,no
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable large file support" >&5
+printf %s "checking for $CC option to enable large file support... " >&6; }
+if test ${ac_cv_sys_largefile_opts+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_save_CC="$CC"
+ ac_opt_found=no
+ for ac_opt in "none needed" "-D_FILE_OFFSET_BITS=64" "-D_LARGE_FILES=1" "-n32"; do
+ if test x"$ac_opt" != x"none needed"
+then :
+ CC="$ac_save_CC $ac_opt"
+fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_sys_largefile_opts="$ac_opt"
+ ac_opt_found=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ test $ac_opt_found = no || break
+ done
+ CC="$ac_save_CC"
+
+ test $ac_opt_found = yes || ac_cv_sys_largefile_opts="support not detected" ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_opts" >&5
+printf "%s\n" "$ac_cv_sys_largefile_opts" >&6; }
+
+ac_have_largefile=yes
+case $ac_cv_sys_largefile_opts in #(
+ "none needed") :
+ ;; #(
+ "supported through gnulib") :
+ ;; #(
+ "support not detected") :
+ ac_have_largefile=no ;; #(
+ "-D_FILE_OFFSET_BITS=64") :
+
+printf "%s\n" "#define _FILE_OFFSET_BITS 64" >>confdefs.h
+ ;; #(
+ "-D_LARGE_FILES=1") :
+
+printf "%s\n" "#define _LARGE_FILES 1" >>confdefs.h
+ ;; #(
+ "-n32") :
+ CC="$CC -n32" ;; #(
+ *) :
+ as_fn_error $? "internal error: bad value for \$ac_cv_sys_largefile_opts" "$LINENO" 5 ;;
+esac
+
+if test "$enable_year2038" != no
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option for timestamps after 2038" >&5
+printf %s "checking for $CC option for timestamps after 2038... " >&6; }
+if test ${ac_cv_sys_year2038_opts+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_save_CPPFLAGS="$CPPFLAGS"
+ ac_opt_found=no
+ for ac_opt in "none needed" "-D_TIME_BITS=64" "-D__MINGW_USE_VC2005_COMPAT" "-U_USE_32_BIT_TIME_T -D__MINGW_USE_VC2005_COMPAT"; do
+ if test x"$ac_opt" != x"none needed"
+then :
+ CPPFLAGS="$ac_save_CPPFLAGS $ac_opt"
+fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <time.h>
+ /* Check that time_t can represent 2**32 - 1 correctly. */
+ #define LARGE_TIME_T \\
+ ((time_t) (((time_t) 1 << 30) - 1 + 3 * ((time_t) 1 << 30)))
+ int verify_time_t_range[(LARGE_TIME_T / 65537 == 65535
+ && LARGE_TIME_T % 65537 == 0)
+ ? 1 : -1];
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_sys_year2038_opts="$ac_opt"
+ ac_opt_found=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ test $ac_opt_found = no || break
+ done
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ test $ac_opt_found = yes || ac_cv_sys_year2038_opts="support not detected" ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_year2038_opts" >&5
+printf "%s\n" "$ac_cv_sys_year2038_opts" >&6; }
+
+ac_have_year2038=yes
+case $ac_cv_sys_year2038_opts in #(
+ "none needed") :
+ ;; #(
+ "support not detected") :
+ ac_have_year2038=no ;; #(
+ "-D_TIME_BITS=64") :
+
+printf "%s\n" "#define _TIME_BITS 64" >>confdefs.h
+ ;; #(
+ "-D__MINGW_USE_VC2005_COMPAT") :
+
+printf "%s\n" "#define __MINGW_USE_VC2005_COMPAT 1" >>confdefs.h
+ ;; #(
+ "-U_USE_32_BIT_TIME_T"*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "the 'time_t' type is currently forced to be 32-bit. It
+will stop working after mid-January 2038. Remove
+_USE_32BIT_TIME_T from the compiler flags.
+See 'config.log' for more details" "$LINENO" 5; } ;; #(
+ *) :
+ as_fn_error $? "internal error: bad value for \$ac_cv_sys_year2038_opts" "$LINENO" 5 ;;
+esac
+
+fi
+
+fi
+if test "$enable_year2038,$ac_have_year2038,$cross_compiling" = yes,no,no
+then :
+ # If we're not cross compiling and 'touch' works with a large
+ # timestamp, then we can presume the system supports wider time_t
+ # *somehow* and we just weren't able to detect it. One common
+ # case that we deliberately *don't* probe for is a system that
+ # supports both 32- and 64-bit ABIs but only the 64-bit ABI offers
+ # wide time_t. (It would be inappropriate for us to override an
+ # intentional use of -m32.) Error out, demanding use of
+ # --disable-year2038 if this is intentional.
+ if TZ=UTC0 touch -t 210602070628.15 conftest.time 2>/dev/null
+then :
+ case `TZ=UTC0 LC_ALL=C ls -l conftest.time 2>/dev/null` in #(
+ *'Feb 7 2106'* | *'Feb 7 17:10'*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error $? "this system appears to support timestamps after
+mid-January 2038, but no mechanism for enabling wide
+'time_t' was detected. Did you mean to build a 64-bit
+binary? (E.g., 'CC=\"${CC} -m64\"'.) To proceed with
+32-bit time_t, configure with '--disable-year2038'.
+See 'config.log' for more details" "$LINENO" 5; } ;; #(
+ *) :
+ ;;
+esac
+fi
+fi
+
+#
+# Don't allow undefined symbols, even in shared libraries, if possible.
+# This will detect missing symbols at build-time instead of run-time
+# but is incompatible with the sanitizers/fuzzers.
+# We must set this *before* the library tests.
+#
+if test -n "$GCC" -a X"${enable_sanitizer}${enable_fuzzer}" = X"nono"
+then :
+
+ case $host_os in #(
+ darwin*) :
+
+ # On macOS 13, using "-undefined dynamic_lookup" produces a
+ # warning. Use the -no-undefined libtool option to avoid this.
+
+if test ${LT_LDFLAGS+y}
+then :
+
+ case " $LT_LDFLAGS " in #(
+ *" -no-undefined "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LT_LDFLAGS already contains -no-undefined"; } >&5
+ (: LT_LDFLAGS already contains -no-undefined) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LT_LDFLAGS " -no-undefined"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LT_LDFLAGS=\"\$LT_LDFLAGS\""; } >&5
+ (: LT_LDFLAGS="$LT_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LT_LDFLAGS=-no-undefined
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LT_LDFLAGS=\"\$LT_LDFLAGS\""; } >&5
+ (: LT_LDFLAGS="$LT_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ ;; #(
+ *) :
+
+ # On FreeBSD and Dragonfly, environ is filled in by the dynamic loader
+ # so -Wl,--no-undefined causes a link error when environ is used.
+ # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=263265
+ # We use errno because OpenBSD shared libraries don't explicitly
+ # link with libc, which can result in undefined reference errors.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the linker accepts -Wl,--no-undefined" >&5
+printf %s "checking the linker accepts -Wl,--no-undefined... " >&6; }
+if test ${sudo_cv_var_ld___no_undefined+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ sudo_cv_var_ld___no_undefined=no
+ _CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $lt_prog_compiler_pic"
+ _LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_prog_compiler_pic -shared -Wl,--no-undefined"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <errno.h>
+ extern char **environ;
+int
+main (void)
+{
+int ret = ((long)environ & 0xff) + errno; return ret;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ sudo_cv_var_ld___no_undefined=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ CFLAGS="$_CFLAGS"
+ LDFLAGS="$_LDFLAGS"
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_var_ld___no_undefined" >&5
+printf "%s\n" "$sudo_cv_var_ld___no_undefined" >&6; }
+ if test "$sudo_cv_var_ld___no_undefined" = "yes"
+then :
+
+
+if test ${LDFLAGS+y}
+then :
+
+ case " $LDFLAGS " in #(
+ *" -Wl,--no-undefined "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS already contains -Wl,--no-undefined"; } >&5
+ (: LDFLAGS already contains -Wl,--no-undefined) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LDFLAGS " -Wl,--no-undefined"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS\""; } >&5
+ (: LDFLAGS="$LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LDFLAGS=-Wl,--no-undefined
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS\""; } >&5
+ (: LDFLAGS="$LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+fi
+ ;;
+esac
+
+fi
+
+#
+# HP-UX may need to define _XOPEN_SOURCE_EXTENDED to expose MSG_WAITALL.
+# Also, HP-UX 11.23 has a broken sys/types.h when large files support
+# is enabled and _XOPEN_SOURCE_EXTENDED is not also defined.
+# The following test will define _XOPEN_SOURCE_EXTENDED in either case.
+#
+case "$host_os" in
+ hpux*)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether sys/socket.h needs _XOPEN_SOURCE_EXTENDED for MSG_WAITALL" >&5
+printf %s "checking whether sys/socket.h needs _XOPEN_SOURCE_EXTENDED for MSG_WAITALL... " >&6; }
+if test ${sudo_cv_xopen_source_extended+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+# include <sys/socket.h>
+int
+main (void)
+{
+int a = MSG_WAITALL; return a;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ sudo_cv_xopen_source_extended=no
+else case e in #(
+ e)
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _XOPEN_SOURCE_EXTENDED
+ $ac_includes_default
+# include <sys/socket.h>
+# include <net/if.h>
+int
+main (void)
+{
+int a = MSG_WAITALL; return a;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ sudo_cv_xopen_source_extended=yes
+else case e in #(
+ e) sudo_cv_xopen_source_extended=error ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_xopen_source_extended" >&5
+printf "%s\n" "$sudo_cv_xopen_source_extended" >&6; }
+ if test "$sudo_cv_xopen_source_extended" = "yes"
+then :
+
+ printf "%s\n" "#define _XOPEN_SOURCE_EXTENDED 1" >>confdefs.h
+
+
+fi
+ ;;
+esac
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for the user mail spool directory" >&5
+printf %s "checking for the user mail spool directory... " >&6; }
+if test ${sudo_cv_mail_dir+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ sudo_cv_mail_dir=no
+ if test X"$ac_cv_header_paths_h" = X"yes"; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+#include <paths.h>
+int
+main (void)
+{
+char *p = _PATH_MAILDIR;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ sudo_cv_mail_dir="paths.h"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ fi
+ if test $sudo_cv_mail_dir = no; then
+ # Solaris has maillock.h which defines MAILDIR
+ for ac_header in maillock.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "maillock.h" "ac_cv_header_maillock_h" "$ac_includes_default"
+if test "x$ac_cv_header_maillock_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_MAILLOCK_H 1" >>confdefs.h
+
+ sudo_cv_mail_dir=maillock.h
+
+else case e in #(
+ e)
+ sudo_cv_mail_dir=/var/mail
+ for d in /var/mail /var/spool/mail /usr/spool/mail; do
+ if test -d "$d"; then
+ sudo_cv_mail_dir="$d"
+ break
+ fi
+ done
+ ;;
+esac
+fi
+
+done
+ fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_mail_dir" >&5
+printf "%s\n" "$sudo_cv_mail_dir" >&6; }
+ case "$sudo_cv_mail_dir" in
+ paths.h)
+ # _PATH_MAILDIR already present in paths.h.
+ ;;
+ maillock.h)
+ # Use MAILDIR from maillock.h
+ cat >>confdefs.h <<\EOF
+#define _PATH_MAILDIR MAILDIR
+EOF
+
+ printf "%s\n" "#define HAVE_MAILLOCK_H 1" >>confdefs.h
+
+ ;;
+ *)
+ cat >>confdefs.h <<EOF
+#define _PATH_MAILDIR "$sudo_cv_mail_dir"
+EOF
+
+ ;;
+ esac
+
+if test ${with_logincap-'no'} != "no"
+then :
+
+ for ac_header in login_cap.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "login_cap.h" "ac_cv_header_login_cap_h" "$ac_includes_default"
+if test "x$ac_cv_header_login_cap_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_LOGIN_CAP_H 1" >>confdefs.h
+
+ LOGINCAP_USAGE='[-c class] '
+ LCMAN=1
+ with_logincap=yes
+
+fi
+
+done
+ if test "${with_logincap}" = "yes"
+then :
+
+ # setusercontext() is in libutil on NetBSD, FreeBSD, Dragonfly BSD.
+ _LIBS="$LIBS"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing setusercontext" >&5
+printf %s "checking for library containing setusercontext... " >&6; }
+if test ${ac_cv_search_setusercontext+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char setusercontext (void);
+int
+main (void)
+{
+return setusercontext ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' util
+do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_search_setusercontext=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext
+ if test ${ac_cv_search_setusercontext+y}
+then :
+ break
+fi
+done
+if test ${ac_cv_search_setusercontext+y}
+then :
+
+else case e in #(
+ e) ac_cv_search_setusercontext=no ;;
+esac
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_setusercontext" >&5
+printf "%s\n" "$ac_cv_search_setusercontext" >&6; }
+ac_res=$ac_cv_search_setusercontext
+if test "$ac_res" != no
+then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+ LIBS="$_LIBS"
+ if test "${ac_cv_search_setusercontext}" != "none required"
+then :
+
+ SUDO_LIBS="${SUDO_LIBS} -lutil"
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lutil"
+
+fi
+
+fi
+
+fi
+if test ${with_project-'no'} != "no"
+then :
+
+ ac_fn_c_check_header_compile "$LINENO" "project.h" "ac_cv_header_project_h" "$ac_includes_default"
+if test "x$ac_cv_header_project_h" = xyes
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for setproject in -lproject" >&5
+printf %s "checking for setproject in -lproject... " >&6; }
+if test ${ac_cv_lib_project_setproject+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lproject $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char setproject (void);
+int
+main (void)
+{
+return setproject ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_project_setproject=yes
+else case e in #(
+ e) ac_cv_lib_project_setproject=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_project_setproject" >&5
+printf "%s\n" "$ac_cv_lib_project_setproject" >&6; }
+if test "x$ac_cv_lib_project_setproject" = xyes
+then :
+
+ printf "%s\n" "#define HAVE_PROJECT_H 1" >>confdefs.h
+
+ SUDO_LIBS="${SUDO_LIBS} -lproject"
+
+fi
+
+
+else case e in #(
+ e) with_project=no ;;
+esac
+fi
+
+
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for unsigned long long int" >&5
+printf %s "checking for unsigned long long int... " >&6; }
+if test ${ac_cv_type_unsigned_long_long_int+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_cv_type_unsigned_long_long_int=yes
+ case $ac_prog_cc_stdc in
+ no | c89) ;;
+ *)
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ /* For now, do not test the preprocessor; as of 2007 there are too many
+ implementations with broken preprocessors. Perhaps this can
+ be revisited in 2012. In the meantime, code should not expect
+ #if to work with literals wider than 32 bits. */
+ /* Test literals. */
+ long long int ll = 9223372036854775807ll;
+ long long int nll = -9223372036854775807LL;
+ unsigned long long int ull = 18446744073709551615ULL;
+ /* Test constant expressions. */
+ typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll)
+ ? 1 : -1)];
+ typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1
+ ? 1 : -1)];
+ int i = 63;
+int
+main (void)
+{
+/* Test availability of runtime routines for shift and division. */
+ long long int llmax = 9223372036854775807ll;
+ unsigned long long int ullmax = 18446744073709551615ull;
+ return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i)
+ | (llmax / ll) | (llmax % ll)
+ | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i)
+ | (ullmax / ull) | (ullmax % ull));
+ ;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+
+else case e in #(
+ e) ac_cv_type_unsigned_long_long_int=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext;;
+ esac ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_unsigned_long_long_int" >&5
+printf "%s\n" "$ac_cv_type_unsigned_long_long_int" >&6; }
+ if test $ac_cv_type_unsigned_long_long_int = yes; then
+
+printf "%s\n" "#define HAVE_UNSIGNED_LONG_LONG_INT 1" >>confdefs.h
+
+ fi
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for long long int" >&5
+printf %s "checking for long long int... " >&6; }
+if test ${ac_cv_type_long_long_int+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_cv_type_long_long_int=yes
+ case $ac_prog_cc_stdc in
+ no | c89) ;;
+ *)
+ ac_cv_type_long_long_int=$ac_cv_type_unsigned_long_long_int
+ if test $ac_cv_type_long_long_int = yes; then
+ if test "$cross_compiling" = yes
+then :
+ :
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+ #ifndef LLONG_MAX
+ # define HALF \\
+ (1LL << (sizeof (long long int) * CHAR_BIT - 2))
+ # define LLONG_MAX (HALF - 1 + HALF)
+ #endif
+int
+main (void)
+{
+long long int n = 1;
+ int i;
+ for (i = 0; ; i++)
+ {
+ long long int m = n << i;
+ if (m >> i != n)
+ return 1;
+ if (LLONG_MAX / 2 < m)
+ break;
+ }
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"
+then :
+
+else case e in #(
+ e) ac_cv_type_long_long_int=no ;;
+esac
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+
+ fi;;
+ esac ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_long_int" >&5
+printf "%s\n" "$ac_cv_type_long_long_int" >&6; }
+ if test $ac_cv_type_long_long_int = yes; then
+
+printf "%s\n" "#define HAVE_LONG_LONG_INT 1" >>confdefs.h
+
+ fi
+
+if test X"${ac_cv_header_stdint_h}${ac_cv_header_inttypes_h}" = X"nono"
+then :
+
+ ac_fn_c_find_intX_t "$LINENO" "8" "ac_cv_c_int8_t"
+case $ac_cv_c_int8_t in #(
+ no|yes) ;; #(
+ *)
+
+printf "%s\n" "#define int8_t $ac_cv_c_int8_t" >>confdefs.h
+;;
+esac
+
+ ac_fn_c_find_uintX_t "$LINENO" "8" "ac_cv_c_uint8_t"
+case $ac_cv_c_uint8_t in #(
+ no|yes) ;; #(
+ *)
+
+printf "%s\n" "#define _UINT8_T 1" >>confdefs.h
+
+
+printf "%s\n" "#define uint8_t $ac_cv_c_uint8_t" >>confdefs.h
+;;
+ esac
+
+ ac_fn_c_find_intX_t "$LINENO" "16" "ac_cv_c_int16_t"
+case $ac_cv_c_int16_t in #(
+ no|yes) ;; #(
+ *)
+
+printf "%s\n" "#define int16_t $ac_cv_c_int16_t" >>confdefs.h
+;;
+esac
+
+ ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t"
+case $ac_cv_c_uint16_t in #(
+ no|yes) ;; #(
+ *)
+
+
+printf "%s\n" "#define uint16_t $ac_cv_c_uint16_t" >>confdefs.h
+;;
+ esac
+
+ ac_fn_c_find_intX_t "$LINENO" "32" "ac_cv_c_int32_t"
+case $ac_cv_c_int32_t in #(
+ no|yes) ;; #(
+ *)
+
+printf "%s\n" "#define int32_t $ac_cv_c_int32_t" >>confdefs.h
+;;
+esac
+
+ ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t"
+case $ac_cv_c_uint32_t in #(
+ no|yes) ;; #(
+ *)
+
+printf "%s\n" "#define _UINT32_T 1" >>confdefs.h
+
+
+printf "%s\n" "#define uint32_t $ac_cv_c_uint32_t" >>confdefs.h
+;;
+ esac
+
+ ac_fn_c_find_intX_t "$LINENO" "64" "ac_cv_c_int64_t"
+case $ac_cv_c_int64_t in #(
+ no|yes) ;; #(
+ *)
+
+printf "%s\n" "#define int64_t $ac_cv_c_int64_t" >>confdefs.h
+;;
+esac
+
+ ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t"
+case $ac_cv_c_uint64_t in #(
+ no|yes) ;; #(
+ *)
+
+printf "%s\n" "#define _UINT64_T 1" >>confdefs.h
+
+
+printf "%s\n" "#define uint64_t $ac_cv_c_uint64_t" >>confdefs.h
+;;
+ esac
+
+
+
+ ac_fn_c_check_type "$LINENO" "intmax_t" "ac_cv_type_intmax_t" "$ac_includes_default"
+if test "x$ac_cv_type_intmax_t" = xyes
+then :
+
+printf "%s\n" "#define HAVE_INTMAX_T 1" >>confdefs.h
+
+else case e in #(
+ e) test $ac_cv_type_long_long_int = yes \
+ && ac_type='long long int' \
+ || ac_type='long int'
+
+printf "%s\n" "#define intmax_t $ac_type" >>confdefs.h
+ ;;
+esac
+fi
+
+
+
+
+ ac_fn_c_check_type "$LINENO" "uintmax_t" "ac_cv_type_uintmax_t" "$ac_includes_default"
+if test "x$ac_cv_type_uintmax_t" = xyes
+then :
+
+printf "%s\n" "#define HAVE_UINTMAX_T 1" >>confdefs.h
+
+else case e in #(
+ e) test $ac_cv_type_unsigned_long_long_int = yes \
+ && ac_type='unsigned long long int' \
+ || ac_type='unsigned long int'
+
+printf "%s\n" "#define uintmax_t $ac_type" >>confdefs.h
+ ;;
+esac
+fi
+
+
+
+fi
+ac_fn_c_check_type "$LINENO" "sig_atomic_t" "ac_cv_type_sig_atomic_t" "
+$ac_includes_default
+#include <signal.h>
+"
+if test "x$ac_cv_type_sig_atomic_t" = xyes
+then :
+
+printf "%s\n" "#define HAVE_SIG_ATOMIC_T 1" >>confdefs.h
+
+
+fi
+
+ac_fn_c_check_type "$LINENO" "struct in6_addr" "ac_cv_type_struct_in6_addr" "#include <sys/types.h>
+#include <netinet/in.h>
+"
+if test "x$ac_cv_type_struct_in6_addr" = xyes
+then :
+
+printf "%s\n" "#define HAVE_STRUCT_IN6_ADDR 1" >>confdefs.h
+
+
+fi
+
+ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "
+$ac_includes_default
+#include <sys/socket.h>
+"
+if test "x$ac_cv_type_socklen_t" = xyes
+then :
+
+printf "%s\n" "#define HAVE_SOCKLEN_T 1" >>confdefs.h
+
+
+fi
+
+
+ ac_fn_c_check_member "$LINENO" "struct sockaddr" "sa_len" "ac_cv_member_struct_sockaddr_sa_len" "
+# include <sys/types.h>
+# include <sys/socket.h>
+
+"
+if test "x$ac_cv_member_struct_sockaddr_sa_len" = xyes
+then :
+
+printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_SA_LEN 1" >>confdefs.h
+
+fi
+
+
+
+ ac_fn_c_check_member "$LINENO" "struct sockaddr_in" "sin_len" "ac_cv_member_struct_sockaddr_in_sin_len" "
+# include <sys/types.h>
+# include <sys/socket.h>
+
+"
+if test "x$ac_cv_member_struct_sockaddr_in_sin_len" = xyes
+then :
+
+printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 1" >>confdefs.h
+
+fi
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like 'int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
+printf %s "checking size of long... " >&6; }
+if test ${ac_cv_sizeof_long+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"
+then :
+
+else case e in #(
+ e) if test "$ac_cv_type_long" = yes; then
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (long)
+See 'config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_long=0
+ fi ;;
+esac
+fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
+printf "%s\n" "$ac_cv_sizeof_long" >&6; }
+
+
+
+printf "%s\n" "#define SIZEOF_LONG $ac_cv_sizeof_long" >>confdefs.h
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like 'int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5
+printf %s "checking size of long long... " >&6; }
+if test ${ac_cv_sizeof_long_long+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"
+then :
+
+else case e in #(
+ e) if test "$ac_cv_type_long_long" = yes; then
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (long long)
+See 'config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_long_long=0
+ fi ;;
+esac
+fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5
+printf "%s\n" "$ac_cv_sizeof_long_long" >&6; }
+
+
+
+printf "%s\n" "#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long" >>confdefs.h
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like 'int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of id_t" >&5
+printf %s "checking size of id_t... " >&6; }
+if test ${ac_cv_sizeof_id_t+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (id_t))" "ac_cv_sizeof_id_t" "$ac_includes_default"
+then :
+
+else case e in #(
+ e) if test "$ac_cv_type_id_t" = yes; then
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (id_t)
+See 'config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_id_t=0
+ fi ;;
+esac
+fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_id_t" >&5
+printf "%s\n" "$ac_cv_sizeof_id_t" >&6; }
+
+
+
+printf "%s\n" "#define SIZEOF_ID_T $ac_cv_sizeof_id_t" >>confdefs.h
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like 'int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of time_t" >&5
+printf %s "checking size of time_t... " >&6; }
+if test ${ac_cv_sizeof_time_t+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (time_t))" "ac_cv_sizeof_time_t" "$ac_includes_default"
+then :
+
+else case e in #(
+ e) if test "$ac_cv_type_time_t" = yes; then
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (time_t)
+See 'config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_time_t=0
+ fi ;;
+esac
+fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_time_t" >&5
+printf "%s\n" "$ac_cv_sizeof_time_t" >&6; }
+
+
+
+printf "%s\n" "#define SIZEOF_TIME_T $ac_cv_sizeof_time_t" >>confdefs.h
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like 'int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of uid_t" >&5
+printf %s "checking size of uid_t... " >&6; }
+if test ${ac_cv_sizeof_uid_t+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (uid_t))" "ac_cv_sizeof_uid_t" "$ac_includes_default"
+then :
+
+else case e in #(
+ e) if test "$ac_cv_type_uid_t" = yes; then
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (uid_t)
+See 'config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_uid_t=0
+ fi ;;
+esac
+fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_uid_t" >&5
+printf "%s\n" "$ac_cv_sizeof_uid_t" >&6; }
+
+
+
+printf "%s\n" "#define SIZEOF_UID_T $ac_cv_sizeof_uid_t" >>confdefs.h
+
+
+# sudo current assumes uid_t can be cast to unsigned int without problems
+if test $ac_cv_sizeof_uid_t -gt 4
+then :
+ as_fn_error $? "sudo does not support systems where uid_t is larger than 32-bit" "$LINENO" 5
+fi
+if test X"$ac_cv_header_utmps_h" = X"yes"
+then :
+
+
+ ac_fn_c_check_member "$LINENO" "struct utmps" "ut_id" "ac_cv_member_struct_utmps_ut_id" "
+# include <sys/types.h>
+# include <utmps.h>
+
+"
+if test "x$ac_cv_member_struct_utmps_ut_id" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_ID 1" >>confdefs.h
+
+
+fi
+
+ ac_fn_c_check_member "$LINENO" "struct utmps" "ut_pid" "ac_cv_member_struct_utmps_ut_pid" "
+# include <sys/types.h>
+# include <utmps.h>
+
+"
+if test "x$ac_cv_member_struct_utmps_ut_pid" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_PID 1" >>confdefs.h
+
+
+fi
+
+ ac_fn_c_check_member "$LINENO" "struct utmps" "ut_tv" "ac_cv_member_struct_utmps_ut_tv" "
+# include <sys/types.h>
+# include <utmps.h>
+
+"
+if test "x$ac_cv_member_struct_utmps_ut_tv" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_TV 1" >>confdefs.h
+
+
+fi
+
+ ac_fn_c_check_member "$LINENO" "struct utmps" "ut_type" "ac_cv_member_struct_utmps_ut_type" "
+# include <sys/types.h>
+# include <utmps.h>
+
+"
+if test "x$ac_cv_member_struct_utmps_ut_type" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_TYPE 1" >>confdefs.h
+
+
+fi
+
+ if test "utmps" = "utmp"; then
+ ac_fn_c_check_member "$LINENO" "struct utmp" "ut_user" "ac_cv_member_struct_utmp_ut_user" "
+# include <sys/types.h>
+# include <utmps.h>
+
+"
+if test "x$ac_cv_member_struct_utmp_ut_user" = xyes
+then :
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_USER 1" >>confdefs.h
+
+
+fi
+
+ fi
+ ac_fn_c_check_member "$LINENO" "struct utmps" "ut_exit.__e_termination" "ac_cv_member_struct_utmps_ut_exit___e_termination" "
+# include <sys/types.h>
+# include <utmps.h>
+
+"
+if test "x$ac_cv_member_struct_utmps_ut_exit___e_termination" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_EXIT 1" >>confdefs.h
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_EXIT___E_TERMINATION 1" >>confdefs.h
+
+
+else case e in #(
+ e)
+ ac_fn_c_check_member "$LINENO" "struct utmps" "ut_exit.e_termination" "ac_cv_member_struct_utmps_ut_exit_e_termination" "
+# include <sys/types.h>
+# include <utmps.h>
+
+"
+if test "x$ac_cv_member_struct_utmps_ut_exit_e_termination" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_EXIT 1" >>confdefs.h
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_EXIT_E_TERMINATION 1" >>confdefs.h
+
+
+fi
+
+ ;;
+esac
+fi
+
+
+
+elif test X"$ac_cv_header_utmpx_h" = X"yes"
+then :
+
+
+ ac_fn_c_check_member "$LINENO" "struct utmpx" "ut_id" "ac_cv_member_struct_utmpx_ut_id" "
+# include <sys/types.h>
+# include <utmpx.h>
+
+"
+if test "x$ac_cv_member_struct_utmpx_ut_id" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_ID 1" >>confdefs.h
+
+
+fi
+
+ ac_fn_c_check_member "$LINENO" "struct utmpx" "ut_pid" "ac_cv_member_struct_utmpx_ut_pid" "
+# include <sys/types.h>
+# include <utmpx.h>
+
+"
+if test "x$ac_cv_member_struct_utmpx_ut_pid" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_PID 1" >>confdefs.h
+
+
+fi
+
+ ac_fn_c_check_member "$LINENO" "struct utmpx" "ut_tv" "ac_cv_member_struct_utmpx_ut_tv" "
+# include <sys/types.h>
+# include <utmpx.h>
+
+"
+if test "x$ac_cv_member_struct_utmpx_ut_tv" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_TV 1" >>confdefs.h
+
+
+fi
+
+ ac_fn_c_check_member "$LINENO" "struct utmpx" "ut_type" "ac_cv_member_struct_utmpx_ut_type" "
+# include <sys/types.h>
+# include <utmpx.h>
+
+"
+if test "x$ac_cv_member_struct_utmpx_ut_type" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_TYPE 1" >>confdefs.h
+
+
+fi
+
+ if test "utmpx" = "utmp"; then
+ ac_fn_c_check_member "$LINENO" "struct utmp" "ut_user" "ac_cv_member_struct_utmp_ut_user" "
+# include <sys/types.h>
+# include <utmpx.h>
+
+"
+if test "x$ac_cv_member_struct_utmp_ut_user" = xyes
+then :
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_USER 1" >>confdefs.h
+
+
+fi
+
+ fi
+ ac_fn_c_check_member "$LINENO" "struct utmpx" "ut_exit.__e_termination" "ac_cv_member_struct_utmpx_ut_exit___e_termination" "
+# include <sys/types.h>
+# include <utmpx.h>
+
+"
+if test "x$ac_cv_member_struct_utmpx_ut_exit___e_termination" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_EXIT 1" >>confdefs.h
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_EXIT___E_TERMINATION 1" >>confdefs.h
+
+
+else case e in #(
+ e)
+ ac_fn_c_check_member "$LINENO" "struct utmpx" "ut_exit.e_termination" "ac_cv_member_struct_utmpx_ut_exit_e_termination" "
+# include <sys/types.h>
+# include <utmpx.h>
+
+"
+if test "x$ac_cv_member_struct_utmpx_ut_exit_e_termination" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_EXIT 1" >>confdefs.h
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_EXIT_E_TERMINATION 1" >>confdefs.h
+
+
+fi
+
+ ;;
+esac
+fi
+
+
+
+else case e in #(
+ e)
+
+ ac_fn_c_check_member "$LINENO" "struct utmp" "ut_id" "ac_cv_member_struct_utmp_ut_id" "
+# include <sys/types.h>
+# include <utmp.h>
+
+"
+if test "x$ac_cv_member_struct_utmp_ut_id" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_ID 1" >>confdefs.h
+
+
+fi
+
+ ac_fn_c_check_member "$LINENO" "struct utmp" "ut_pid" "ac_cv_member_struct_utmp_ut_pid" "
+# include <sys/types.h>
+# include <utmp.h>
+
+"
+if test "x$ac_cv_member_struct_utmp_ut_pid" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_PID 1" >>confdefs.h
+
+
+fi
+
+ ac_fn_c_check_member "$LINENO" "struct utmp" "ut_tv" "ac_cv_member_struct_utmp_ut_tv" "
+# include <sys/types.h>
+# include <utmp.h>
+
+"
+if test "x$ac_cv_member_struct_utmp_ut_tv" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_TV 1" >>confdefs.h
+
+
+fi
+
+ ac_fn_c_check_member "$LINENO" "struct utmp" "ut_type" "ac_cv_member_struct_utmp_ut_type" "
+# include <sys/types.h>
+# include <utmp.h>
+
+"
+if test "x$ac_cv_member_struct_utmp_ut_type" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_TYPE 1" >>confdefs.h
+
+
+fi
+
+ if test "utmp" = "utmp"; then
+ ac_fn_c_check_member "$LINENO" "struct utmp" "ut_user" "ac_cv_member_struct_utmp_ut_user" "
+# include <sys/types.h>
+# include <utmp.h>
+
+"
+if test "x$ac_cv_member_struct_utmp_ut_user" = xyes
+then :
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_USER 1" >>confdefs.h
+
+
+fi
+
+ fi
+ ac_fn_c_check_member "$LINENO" "struct utmp" "ut_exit.__e_termination" "ac_cv_member_struct_utmp_ut_exit___e_termination" "
+# include <sys/types.h>
+# include <utmp.h>
+
+"
+if test "x$ac_cv_member_struct_utmp_ut_exit___e_termination" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_EXIT 1" >>confdefs.h
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_EXIT___E_TERMINATION 1" >>confdefs.h
+
+
+else case e in #(
+ e)
+ ac_fn_c_check_member "$LINENO" "struct utmp" "ut_exit.e_termination" "ac_cv_member_struct_utmp_ut_exit_e_termination" "
+# include <sys/types.h>
+# include <utmp.h>
+
+"
+if test "x$ac_cv_member_struct_utmp_ut_exit_e_termination" = xyes
+then :
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_EXIT 1" >>confdefs.h
+
+
+printf "%s\n" "#define HAVE_STRUCT_UTMP_UT_EXIT_E_TERMINATION 1" >>confdefs.h
+
+
+fi
+
+ ;;
+esac
+fi
+
+
+ ;;
+esac
+fi
+
+RTLD_PRELOAD_VAR="LD_PRELOAD"
+if test $ac_cv_sizeof_long -eq 4; then
+ RTLD_PRELOAD_VAR_32="LD_PRELOAD"
+else
+ RTLD_PRELOAD_VAR_64="LD_PRELOAD"
+fi
+RTLD_PRELOAD_ENABLE_VAR=
+RTLD_PRELOAD_DELIM=":"
+RTLD_PRELOAD_DEFAULT=
+
+case "$host" in
+ *-*-solaris2*)
+ # LD_PRELOAD is space-delimited
+ RTLD_PRELOAD_DELIM=" "
+ RTLD_PRELOAD_VAR_32="LD_PRELOAD_32"
+ RTLD_PRELOAD_VAR_64="LD_PRELOAD_64"
+ ;;
+ *-*-aix*)
+ # LDR_PRELOAD and LDR_PRELOAD64 are only supported on
+ # AIX 5.3 and above.
+ case "$OSREV" in
+ [1-4].*|5.[1-2]*)
+ with_noexec=no
+ ;;
+ *)
+ # AIX uses LDR_PRELOAD for 32-bit executables
+ # and LDR_PRELOAD64 for 64-bit executable.
+ RTLD_PRELOAD_VAR_32="LDR_PRELOAD"
+ RTLD_PRELOAD_VAR_64="LDR_PRELOAD64"
+ if test $ac_cv_sizeof_long -eq 4; then
+ RTLD_PRELOAD_VAR="LDR_PRELOAD"
+ else
+ RTLD_PRELOAD_VAR="LDR_PRELOAD64"
+ fi
+ ;;
+ esac
+ ;;
+ *-dec-osf*|*-*-hiuxmpp*|*-*-irix*)
+ # ":DEFAULT" must be appended to _RLD_LIST
+ RTLD_PRELOAD_VAR="_RLD_LIST"
+ RTLD_PRELOAD_DEFAULT="DEFAULT"
+ ;;
+ *-*-darwin*)
+ # Darwin 8 and above can interpose library symbols cleanly
+ if test $OSMAJOR -ge 8
+then :
+
+ printf "%s\n" "#define HAVE___INTERPOSE 1" >>confdefs.h
+
+ dlyld_interpose=yes
+
+else case e in #(
+ e)
+ RTLD_PRELOAD_ENABLE_VAR="DYLD_FORCE_FLAT_NAMESPACE"
+ ;;
+esac
+fi
+ RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
+
+ # Build sudo_noexec.so as a shared library, not a module.
+ # On Darwin, modules and shared libraries are incompatible.
+ PRELOAD_MODULE=
+ ;;
+ *-*-nextstep*)
+ RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
+ RTLD_PRELOAD_ENABLE_VAR="DYLD_FORCE_FLAT_NAMESPACE"
+ ;;
+esac
+
+if test X"$enable_intercept" = X"no"
+then :
+
+ intercept_file=disabled
+
+fi
+if test X"$with_noexec" = X"no"
+then :
+
+ noexec_file=disabled
+
+fi
+if test X"${intercept_file} ${noexec_file}" != X"disabled disabled"
+then :
+
+ cat >>confdefs.h <<EOF
+#define RTLD_PRELOAD_VAR "$RTLD_PRELOAD_VAR"
+EOF
+
+ if test -n "$RTLD_PRELOAD_VAR_32"; then
+ cat >>confdefs.h <<EOF
+#define RTLD_PRELOAD_VAR_32 "$RTLD_PRELOAD_VAR_32"
+EOF
+
+ fi
+ if test -n "$RTLD_PRELOAD_VAR_64"; then
+ cat >>confdefs.h <<EOF
+#define RTLD_PRELOAD_VAR_64 "$RTLD_PRELOAD_VAR_64"
+EOF
+
+ fi
+ cat >>confdefs.h <<EOF
+#define RTLD_PRELOAD_DELIM '$RTLD_PRELOAD_DELIM'
+EOF
+
+ if test -n "$RTLD_PRELOAD_DEFAULT"
+then :
+
+ cat >>confdefs.h <<EOF
+#define RTLD_PRELOAD_DEFAULT "$RTLD_PRELOAD_DEFAULT"
+EOF
+
+
+fi
+ if test -n "$RTLD_PRELOAD_ENABLE_VAR"
+then :
+
+ cat >>confdefs.h <<EOF
+#define RTLD_PRELOAD_ENABLE_VAR "$RTLD_PRELOAD_ENABLE_VAR"
+EOF
+
+
+fi
+
+fi
+
+if test ${enable_python-'no'} = "yes"
+then :
+
+
+
+
+
+
+
+ if test -n "$PYTHON"; then
+ # If the user set $PYTHON, use it and don't search something else.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $PYTHON version is >= 3" >&5
+printf %s "checking whether $PYTHON version is >= 3... " >&6; }
+ prog="import sys
+# split strings by '.' and convert to numeric. Append some zeros
+# because we need at least 4 digits for the hex conversion.
+# map returns an iterator in Python 3.0 and a list in 2.x
+minver = list(map(int, '3'.split('.'))) + [0, 0, 0]
+minverhex = 0
+# xrange is not present in Python 3.0 and range returns an iterator
+for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i]
+sys.exit(sys.hexversion < minverhex)"
+ if { echo "$as_me:$LINENO: $PYTHON -c "$prog"" >&5
+ ($PYTHON -c "$prog") >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ as_fn_error $? "Python interpreter is too old" "$LINENO" 5 ;;
+esac
+fi
+ am_display_PYTHON=$PYTHON
+ else
+ # Otherwise, try each interpreter until we find one that satisfies
+ # VERSION.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a Python interpreter with version >= 3" >&5
+printf %s "checking for a Python interpreter with version >= 3... " >&6; }
+if test ${am_cv_pathless_PYTHON+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ for am_cv_pathless_PYTHON in python python2 python3 python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 none; do
+ test "$am_cv_pathless_PYTHON" = none && break
+ prog="import sys
+# split strings by '.' and convert to numeric. Append some zeros
+# because we need at least 4 digits for the hex conversion.
+# map returns an iterator in Python 3.0 and a list in 2.x
+minver = list(map(int, '3'.split('.'))) + [0, 0, 0]
+minverhex = 0
+# xrange is not present in Python 3.0 and range returns an iterator
+for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i]
+sys.exit(sys.hexversion < minverhex)"
+ if { echo "$as_me:$LINENO: $am_cv_pathless_PYTHON -c "$prog"" >&5
+ ($am_cv_pathless_PYTHON -c "$prog") >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+then :
+ break
+fi
+ done ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_pathless_PYTHON" >&5
+printf "%s\n" "$am_cv_pathless_PYTHON" >&6; }
+ # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON.
+ if test "$am_cv_pathless_PYTHON" = none; then
+ PYTHON=:
+ else
+ # Extract the first word of "$am_cv_pathless_PYTHON", so it can be a program name with args.
+set dummy $am_cv_pathless_PYTHON; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_PYTHON+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) case $PYTHON in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_PYTHON="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac ;;
+esac
+fi
+PYTHON=$ac_cv_path_PYTHON
+if test -n "$PYTHON"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5
+printf "%s\n" "$PYTHON" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ fi
+ am_display_PYTHON=$am_cv_pathless_PYTHON
+ fi
+
+
+ if test "$PYTHON" = :; then
+ as_fn_error $? "no suitable Python interpreter found" "$LINENO" 5
+ else
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON version" >&5
+printf %s "checking for $am_display_PYTHON version... " >&6; }
+if test ${am_cv_python_version+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) am_cv_python_version=`$PYTHON -c "import sys; print('%u.%u' % sys.version_info[:2])"` ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_version" >&5
+printf "%s\n" "$am_cv_python_version" >&6; }
+ PYTHON_VERSION=$am_cv_python_version
+
+
+
+ PYTHON_PREFIX='${prefix}'
+
+ PYTHON_EXEC_PREFIX='${exec_prefix}'
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON platform" >&5
+printf %s "checking for $am_display_PYTHON platform... " >&6; }
+if test ${am_cv_python_platform+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"` ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_platform" >&5
+printf "%s\n" "$am_cv_python_platform" >&6; }
+ PYTHON_PLATFORM=$am_cv_python_platform
+
+
+ # Just factor out some code duplication.
+ am_python_setup_sysconfig="\
+import sys
+# Prefer sysconfig over distutils.sysconfig, for better compatibility
+# with python 3.x. See automake bug#10227.
+try:
+ import sysconfig
+except ImportError:
+ can_use_sysconfig = 0
+else:
+ can_use_sysconfig = 1
+# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs:
+# <https://github.com/pypa/virtualenv/issues/118>
+try:
+ from platform import python_implementation
+ if python_implementation() == 'CPython' and sys.version[:3] == '2.7':
+ can_use_sysconfig = 0
+except ImportError:
+ pass"
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory" >&5
+printf %s "checking for $am_display_PYTHON script directory... " >&6; }
+if test ${am_cv_python_pythondir+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test "x$prefix" = xNONE
+ then
+ am_py_prefix=$ac_default_prefix
+ else
+ am_py_prefix=$prefix
+ fi
+ am_cv_python_pythondir=`$PYTHON -c "
+$am_python_setup_sysconfig
+if can_use_sysconfig:
+ sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
+else:
+ from distutils import sysconfig
+ sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
+sys.stdout.write(sitedir)"`
+ case $am_cv_python_pythondir in
+ $am_py_prefix*)
+ am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'`
+ am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"`
+ ;;
+ *)
+ case $am_py_prefix in
+ /usr|/System*) ;;
+ *)
+ am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pythondir" >&5
+printf "%s\n" "$am_cv_python_pythondir" >&6; }
+ pythondir=$am_cv_python_pythondir
+
+
+
+ pkgpythondir=\${pythondir}/$PACKAGE
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory" >&5
+printf %s "checking for $am_display_PYTHON extension module directory... " >&6; }
+if test ${am_cv_python_pyexecdir+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test "x$exec_prefix" = xNONE
+ then
+ am_py_exec_prefix=$am_py_prefix
+ else
+ am_py_exec_prefix=$exec_prefix
+ fi
+ am_cv_python_pyexecdir=`$PYTHON -c "
+$am_python_setup_sysconfig
+if can_use_sysconfig:
+ sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'})
+else:
+ from distutils import sysconfig
+ sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix')
+sys.stdout.write(sitedir)"`
+ case $am_cv_python_pyexecdir in
+ $am_py_exec_prefix*)
+ am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'`
+ am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"`
+ ;;
+ *)
+ case $am_py_exec_prefix in
+ /usr|/System*) ;;
+ *)
+ am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pyexecdir" >&5
+printf "%s\n" "$am_cv_python_pyexecdir" >&6; }
+ pyexecdir=$am_cv_python_pyexecdir
+
+
+
+ pkgpyexecdir=\${pyexecdir}/$PACKAGE
+
+
+
+ fi
+
+
+
+
+
+
+
+ if test -z "$PYTHON_INCLUDE" || test -z "$PYTHON_LIBS"
+then :
+
+ if test -z "$PYTHON_CONFIG"
+then :
+
+ for ac_prog in python$PYTHON_VERSION-config python-config
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_PYTHON_CONFIG+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) case $PYTHON_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PYTHON_CONFIG="$PYTHON_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in `dirname $PYTHON`
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_PYTHON_CONFIG="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac ;;
+esac
+fi
+PYTHON_CONFIG=$ac_cv_path_PYTHON_CONFIG
+if test -n "$PYTHON_CONFIG"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PYTHON_CONFIG" >&5
+printf "%s\n" "$PYTHON_CONFIG" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$PYTHON_CONFIG" && break
+done
+test -n "$PYTHON_CONFIG" || PYTHON_CONFIG="no"
+
+ if test "$PYTHON_CONFIG" = no
+then :
+ as_fn_error $? "cannot find python-config for $PYTHON." "$LINENO" 5
+fi
+
+fi
+
+fi
+
+ if test -z "$PYTHON_INCLUDE"
+then :
+
+ # Pull out python include path, ignore other flags
+ PYTHON_INCLUDE=`$PYTHON_CONFIG --cflags | tr " " "\n" | grep "^-I" | sort -u | tr "\n" " "`
+
+fi
+
+ if test -z "$PYTHON_LIBS"
+then :
+
+ # Newer versions of python3-config need --embed to include libpython
+ if $PYTHON_CONFIG 2>&1 | grep embed >/dev/null; then
+ PY_EMBED=--embed
+ else
+ PY_EMBED=
+ fi
+ PYTHON_LIBS=`$PYTHON_CONFIG --ldflags $PY_EMBED`
+ PYTHON_LIBS=`$PYTHON_CONFIG --ldflags $PY_EMBED | tr " " "\n" | grep "^-[lL]" | tr "\n" " "`
+
+fi
+
+ PPFILES="$PPFILES "'$(srcdir)/etc/sudo-python.pp'
+ PYTHON_PLUGIN_SRC=plugins/python
+ PYTHON_PLUGIN=
+ ac_config_files="$ac_config_files $PYTHON_PLUGIN_SRC/Makefile"
+
+
+fi
+
+ac_fn_c_check_type "$LINENO" "uid_t" "ac_cv_type_uid_t" "$ac_includes_default"
+if test "x$ac_cv_type_uid_t" = xyes
+then :
+
+else case e in #(
+ e)
+printf "%s\n" "#define uid_t int" >>confdefs.h
+ ;;
+esac
+fi
+
+ac_fn_c_check_type "$LINENO" "gid_t" "ac_cv_type_gid_t" "$ac_includes_default"
+if test "x$ac_cv_type_gid_t" = xyes
+then :
+
+else case e in #(
+ e)
+printf "%s\n" "#define gid_t int" >>confdefs.h
+ ;;
+esac
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking type of array argument to getgroups" >&5
+printf %s "checking type of array argument to getgroups... " >&6; }
+if test ${ac_cv_type_getgroups+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) # If AC_TYPE_UID_T says there isn't any gid_t typedef, then we can skip
+# everything below.
+if test $ac_cv_type_gid_t = no
+then :
+ ac_cv_type_getgroups=int
+else case e in #(
+ e) # Test programs below rely on strict type checking of extern declarations:
+ # 'extern int getgroups(int, int *); extern int getgroups(int, pid_t *);'
+ # is valid in C89 if and only if pid_t is a typedef for int. Unlike
+ # anything involving either an assignment or a function call, compilers
+ # tend to make this kind of type mismatch a hard error, not just an
+ # "incompatible pointer types" warning.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+extern int getgroups(int, gid_t *);
+int
+main (void)
+{
+return !(getgroups(0, 0) >= 0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_getgroups_gidarray=yes
+else case e in #(
+ e) ac_getgroups_gidarray=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+extern int getgroups(int, int *);
+int
+main (void)
+{
+return !(getgroups(0, 0) >= 0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_getgroups_intarray=yes
+else case e in #(
+ e) ac_getgroups_intarray=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+
+ case int:$ac_getgroups_intarray,gid:$ac_getgroups_gidarray in #(
+ int:yes,gid:no) :
+ ac_cv_type_getgroups=int ;; #(
+ int:no,gid:yes) :
+ ac_cv_type_getgroups=gid_t ;; #(
+ int:yes,gid:yes) :
+
+ # Both programs compiled - this means *either* that getgroups
+ # was declared with no prototype, in which case we should use int,
+ # or that it was declared prototyped but gid_t is a typedef for int,
+ # in which case we should use gid_t. Distinguish the two cases
+ # by testing if the compiler catches a blatantly incorrect function
+ # signature for getgroups.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+extern int getgroups(int, float);
+int
+main (void)
+{
+return !(getgroups(0, 0) >= 0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+ # Compiler did not catch incorrect argument list;
+ # getgroups is unprototyped.
+ ac_cv_type_getgroups=int
+
+else case e in #(
+ e)
+ # Compiler caught incorrect argument list;
+ # gid_t is a typedef for int.
+ ac_cv_type_getgroups=gid_t
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ;; #(
+ *) :
+
+ # Both programs failed to compile - this probably means getgroups
+ # wasn't declared at all. Use 'int', as this is probably a very
+ # old system where the type _would have been_ int.
+ ac_cv_type_getgroups=int
+ ;;
+esac
+ ;;
+esac
+fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_getgroups" >&5
+printf "%s\n" "$ac_cv_type_getgroups" >&6; }
+printf "%s\n" "#define GETGROUPS_T $ac_cv_type_getgroups" >>confdefs.h
+
+
+
+# On older systems getgroups might be in -lbsd.
+# This is reported to be necessary on an ITOS 3000WS running SEIUX 3.1.
+ac_save_LIBS=$LIBS
+LIBS=
+GETGROUPS_LIB=
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing getgroups" >&5
+printf %s "checking for library containing getgroups... " >&6; }
+if test ${ac_cv_search_getgroups+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getgroups (void);
+int
+main (void)
+{
+return getgroups ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' bsd
+do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_search_getgroups=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext
+ if test ${ac_cv_search_getgroups+y}
+then :
+ break
+fi
+done
+if test ${ac_cv_search_getgroups+y}
+then :
+
+else case e in #(
+ e) ac_cv_search_getgroups=no ;;
+esac
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getgroups" >&5
+printf "%s\n" "$ac_cv_search_getgroups" >&6; }
+ac_res=$ac_cv_search_getgroups
+if test "$ac_res" != no
+then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+ test "$ac_res" = "none required" || GETGROUPS_LIB="$ac_res"
+ ac_cv_func_getgroups=yes
+else case e in #(
+ e) ac_cv_func_getgroups=no ;;
+esac
+fi
+
+LIBS=$ac_save_LIBS
+
+
+# Known severe bugs in getgroups on particular systems.
+# - On Ultrix 4.3 and NextSTEP 3.2, getgroups (0, 0) is reported to
+# fail, rather than returning the number of supplementary groups as
+# it ought to. We do not know the exact range of releases affected
+# in either case.
+# We currently reject all versions of the systems with known bugs, and
+# no other systems. Please send corrections to bug-autoconf@gnu.org.
+if test $ac_cv_func_getgroups = yes; then
+ # This AC_CACHE_CHECK exists so that one may override an incorrect
+ # guess by setting ac_cv_func_getgroups_works in a config.site file.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working getgroups" >&5
+printf %s "checking for working getgroups... " >&6; }
+if test ${ac_cv_func_getgroups_works+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) case $host_os in #(
+ ultrix* | nextstep*) :
+ ac_cv_func_getgroups_works=no # getgroups(0,0) fails
+ ;; #(
+ *) :
+ ac_cv_func_getgroups_works=yes ;;
+esac ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getgroups_works" >&5
+printf "%s\n" "$ac_cv_func_getgroups_works" >&6; }
+else
+ ac_cv_func_getgroups_works=no
+fi
+if test $ac_cv_func_getgroups_works = yes; then
+
+printf "%s\n" "#define HAVE_GETGROUPS 1" >>confdefs.h
+
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for declarations of fseeko and ftello" >&5
+printf %s "checking for declarations of fseeko and ftello... " >&6; }
+if test ${ac_cv_func_fseeko_ftello+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#if defined __hpux && !defined _LARGEFILE_SOURCE
+# include <limits.h>
+# if LONG_MAX >> 31 == 0
+# error "32-bit HP-UX 11/ia64 needs _LARGEFILE_SOURCE for fseeko in C++"
+# endif
+#endif
+#include <sys/types.h> /* for off_t */
+#include <stdio.h>
+
+int
+main (void)
+{
+
+ int (*fp1) (FILE *, off_t, int) = fseeko;
+ off_t (*fp2) (FILE *) = ftello;
+ return fseeko (stdin, 0, 0)
+ && fp1 (stdin, 0, 0)
+ && ftello (stdin) >= 0
+ && fp2 (stdin) >= 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_func_fseeko_ftello=yes
+else case e in #(
+ e) ac_save_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS -D_LARGEFILE_SOURCE=1"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#if defined __hpux && !defined _LARGEFILE_SOURCE
+# include <limits.h>
+# if LONG_MAX >> 31 == 0
+# error "32-bit HP-UX 11/ia64 needs _LARGEFILE_SOURCE for fseeko in C++"
+# endif
+#endif
+#include <sys/types.h> /* for off_t */
+#include <stdio.h>
+
+int
+main (void)
+{
+
+ int (*fp1) (FILE *, off_t, int) = fseeko;
+ off_t (*fp2) (FILE *) = ftello;
+ return fseeko (stdin, 0, 0)
+ && fp1 (stdin, 0, 0)
+ && ftello (stdin) >= 0
+ && fp2 (stdin) >= 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_func_fseeko_ftello="need _LARGEFILE_SOURCE"
+else case e in #(
+ e) ac_cv_func_fseeko_ftello=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fseeko_ftello" >&5
+printf "%s\n" "$ac_cv_func_fseeko_ftello" >&6; }
+if test "$ac_cv_func_fseeko_ftello" != no
+then :
+
+printf "%s\n" "#define HAVE_FSEEKO 1" >>confdefs.h
+
+fi
+if test "$ac_cv_func_fseeko_ftello" = "need _LARGEFILE_SOURCE"
+then :
+
+printf "%s\n" "#define _LARGEFILE_SOURCE 1" >>confdefs.h
+
+fi
+
+ac_func=
+for ac_item in $ac_func_c_list
+do
+ if test $ac_func; then
+ ac_fn_c_check_func "$LINENO" $ac_func ac_cv_func_$ac_func
+ if eval test \"x\$ac_cv_func_$ac_func\" = xyes; then
+ echo "#define $ac_item 1" >> confdefs.h
+ fi
+ ac_func=
+ else
+ ac_func=$ac_item
+ fi
+done
+
+
+
+
+
+
+
+
+
+ for ac_func in execvpe
+do :
+ ac_fn_c_check_func "$LINENO" "execvpe" "ac_cv_func_execvpe"
+if test "x$ac_cv_func_execvpe" = xyes
+then :
+ printf "%s\n" "#define HAVE_EXECVPE 1" >>confdefs.h
+
+ for _sym in execvpe; do
+ INTERCEPT_EXP="${INTERCEPT_EXP}${_sym}
+"
+ done
+
+fi
+
+done
+
+ for ac_func in pread
+do :
+ ac_fn_c_check_func "$LINENO" "pread" "ac_cv_func_pread"
+if test "x$ac_cv_func_pread" = xyes
+then :
+ printf "%s\n" "#define HAVE_PREAD 1" >>confdefs.h
+
+ # pread/pwrite on 32-bit HP-UX 11.x may not support large files
+ case "$host_os" in
+ hpux*)
+
+ for ac_func in pread64 pwrite64
+do :
+ as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | sed "$as_sed_sh"`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_func" | sed "$as_sed_cpp"` 1
+_ACEOF
+
+ ac_fn_check_decl "$LINENO" "pread64" "ac_cv_have_decl_pread64" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_pread64" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_PREAD64 $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "pwrite64" "ac_cv_have_decl_pwrite64" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_pwrite64" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_PWRITE64 $ac_have_decl" >>confdefs.h
+
+
+fi
+
+done
+ ;;
+ esac
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" pread.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS pread.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_pread; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in pwrite
+do :
+ ac_fn_c_check_func "$LINENO" "pwrite" "ac_cv_func_pwrite"
+if test "x$ac_cv_func_pwrite" = xyes
+then :
+ printf "%s\n" "#define HAVE_PWRITE 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" pwrite.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS pwrite.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_pwrite; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in cfmakeraw
+do :
+ ac_fn_c_check_func "$LINENO" "cfmakeraw" "ac_cv_func_cfmakeraw"
+if test "x$ac_cv_func_cfmakeraw" = xyes
+then :
+ printf "%s\n" "#define HAVE_CFMAKERAW 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" cfmakeraw.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS cfmakeraw.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_cfmakeraw; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in localtime_r
+do :
+ ac_fn_c_check_func "$LINENO" "localtime_r" "ac_cv_func_localtime_r"
+if test "x$ac_cv_func_localtime_r" = xyes
+then :
+ printf "%s\n" "#define HAVE_LOCALTIME_R 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" localtime_r.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS localtime_r.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_localtime_r; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in gmtime_r
+do :
+ ac_fn_c_check_func "$LINENO" "gmtime_r" "ac_cv_func_gmtime_r"
+if test "x$ac_cv_func_gmtime_r" = xyes
+then :
+ printf "%s\n" "#define HAVE_GMTIME_R 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" gmtime_r.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS gmtime_r.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_gmtime_r; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in timegm
+do :
+ ac_fn_c_check_func "$LINENO" "timegm" "ac_cv_func_timegm"
+if test "x$ac_cv_func_timegm" = xyes
+then :
+ printf "%s\n" "#define HAVE_TIMEGM 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" timegm.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS timegm.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_timegm; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in getgrouplist
+do :
+ ac_fn_c_check_func "$LINENO" "getgrouplist" "ac_cv_func_getgrouplist"
+if test "x$ac_cv_func_getgrouplist" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETGROUPLIST 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case "$host_os" in
+ aix*)
+ ac_fn_c_check_func "$LINENO" "getgrset" "ac_cv_func_getgrset"
+if test "x$ac_cv_func_getgrset" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETGRSET 1" >>confdefs.h
+
+fi
+
+ ;;
+ *)
+ ac_fn_c_check_func "$LINENO" "nss_search" "ac_cv_func_nss_search"
+if test "x$ac_cv_func_nss_search" = xyes
+then :
+
+ ac_fn_c_check_func "$LINENO" "_nss_XbyY_buf_alloc" "ac_cv_func__nss_XbyY_buf_alloc"
+if test "x$ac_cv_func__nss_XbyY_buf_alloc" = xyes
+then :
+
+ # Solaris
+ ac_fn_c_check_func "$LINENO" "_nss_initf_group" "ac_cv_func__nss_initf_group"
+if test "x$ac_cv_func__nss_initf_group" = xyes
+then :
+
+ ac_fn_c_check_header_compile "$LINENO" "nss_dbdefs.h" "ac_cv_header_nss_dbdefs_h" "$ac_includes_default"
+if test "x$ac_cv_header_nss_dbdefs_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_NSS_DBDEFS_H 1" >>confdefs.h
+
+fi
+
+ printf "%s\n" "#define HAVE_NSS_SEARCH 1" >>confdefs.h
+
+ printf "%s\n" "#define HAVE__NSS_XBYY_BUF_ALLOC 1" >>confdefs.h
+
+ printf "%s\n" "#define HAVE__NSS_INITF_GROUP 1" >>confdefs.h
+
+
+else case e in #(
+ e)
+ for ac_header in nss_dbdefs.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "nss_dbdefs.h" "ac_cv_header_nss_dbdefs_h" "$ac_includes_default"
+if test "x$ac_cv_header_nss_dbdefs_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_NSS_DBDEFS_H 1" >>confdefs.h
+
+ # Older Solaris does not export _nss_initf_group
+ # but we can use our own.
+ printf "%s\n" "#define HAVE_NSS_SEARCH 1" >>confdefs.h
+
+ printf "%s\n" "#define HAVE__NSS_XBYY_BUF_ALLOC 1" >>confdefs.h
+
+
+fi
+
+done
+ ;;
+esac
+fi
+
+
+else case e in #(
+ e)
+ :
+ ;;
+esac
+fi
+
+
+fi
+
+ ;;
+ esac
+
+ for _sym in sudo_getgrouplist; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in getdelim
+do :
+ ac_fn_c_check_func "$LINENO" "getdelim" "ac_cv_func_getdelim"
+if test "x$ac_cv_func_getdelim" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETDELIM 1" >>confdefs.h
+
+ # Out of date gcc fixed includes may result in missing getdelim() prototype
+ ac_fn_check_decl "$LINENO" "getdelim" "ac_cv_have_decl_getdelim" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_getdelim" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_GETDELIM $ac_have_decl" >>confdefs.h
+
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" getdelim.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS getdelim.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_getdelim; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }getdelim_test"
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in getusershell
+do :
+ ac_fn_c_check_func "$LINENO" "getusershell" "ac_cv_func_getusershell"
+if test "x$ac_cv_func_getusershell" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETUSERSHELL 1" >>confdefs.h
+
+ # Older Solaris has getusershell() et al but does not declare it.
+ ac_fn_check_decl "$LINENO" "getusershell" "ac_cv_have_decl_getusershell" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_getusershell" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_GETUSERSHELL $ac_have_decl" >>confdefs.h
+
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" getusershell.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS getusershell.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_getusershell; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in reallocarray
+do :
+ ac_fn_c_check_func "$LINENO" "reallocarray" "ac_cv_func_reallocarray"
+if test "x$ac_cv_func_reallocarray" = xyes
+then :
+ printf "%s\n" "#define HAVE_REALLOCARRAY 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" reallocarray.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS reallocarray.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_reallocarray; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in arc4random
+do :
+ ac_fn_c_check_func "$LINENO" "arc4random" "ac_cv_func_arc4random"
+if test "x$ac_cv_func_arc4random" = xyes
+then :
+ printf "%s\n" "#define HAVE_ARC4RANDOM 1" >>confdefs.h
+
+
+ for ac_func in arc4random_uniform
+do :
+ ac_fn_c_check_func "$LINENO" "arc4random_uniform" "ac_cv_func_arc4random_uniform"
+if test "x$ac_cv_func_arc4random_uniform" = xyes
+then :
+ printf "%s\n" "#define HAVE_ARC4RANDOM_UNIFORM 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" arc4random_uniform.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS arc4random_uniform.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_arc4random_uniform; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in arc4random_buf
+do :
+ ac_fn_c_check_func "$LINENO" "arc4random_buf" "ac_cv_func_arc4random_buf"
+if test "x$ac_cv_func_arc4random_buf" = xyes
+then :
+ printf "%s\n" "#define HAVE_ARC4RANDOM_BUF 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" arc4random_buf.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS arc4random_buf.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_arc4random_buf; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" arc4random.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS arc4random.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_arc4random; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+
+ for _sym in sudo_arc4random_buf; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ case " $LIBOBJS " in
+ *" arc4random_uniform.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS arc4random_uniform.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_arc4random_uniform; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ # arc4random.c needs getentropy()
+
+ for ac_func in getentropy
+do :
+ ac_fn_c_check_func "$LINENO" "getentropy" "ac_cv_func_getentropy"
+if test "x$ac_cv_func_getentropy" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETENTROPY 1" >>confdefs.h
+
+ ac_fn_c_check_header_compile "$LINENO" "sys/random.h" "ac_cv_header_sys_random_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_random_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_RANDOM_H 1" >>confdefs.h
+
+fi
+
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" getentropy.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS getentropy.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_getentropy; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ac_fn_c_check_func "$LINENO" "getauxval" "ac_cv_func_getauxval"
+if test "x$ac_cv_func_getauxval" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETAUXVAL 1" >>confdefs.h
+
+fi
+
+ ;;
+esac
+fi
+
+done
+ # arc4random.c wants pthread_atfork
+ for ac_header in pthread.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_PTHREAD_H 1" >>confdefs.h
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5
+printf %s "checking for main in -lpthread... " >&6; }
+if test ${ac_cv_lib_pthread_main+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+int
+main (void)
+{
+return main ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_pthread_main=yes
+else case e in #(
+ e) ac_cv_lib_pthread_main=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5
+printf "%s\n" "$ac_cv_lib_pthread_main" >&6; }
+if test "x$ac_cv_lib_pthread_main" = xyes
+then :
+ LIBPTHREAD="-lpthread"
+fi
+
+ ac_fn_c_check_func "$LINENO" "pthread_atfork" "ac_cv_func_pthread_atfork"
+if test "x$ac_cv_func_pthread_atfork" = xyes
+then :
+ printf "%s\n" "#define HAVE_PTHREAD_ATFORK 1" >>confdefs.h
+
+fi
+
+
+fi
+
+done
+ ;;
+esac
+fi
+
+done
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __builtin_clz" >&5
+printf %s "checking for __builtin_clz... " >&6; }
+if test ${ax_cv_have___builtin_clz+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ __builtin_clz(0)
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_have___builtin_clz=yes
+else case e in #(
+ e) ax_cv_have___builtin_clz=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_have___builtin_clz" >&5
+printf "%s\n" "$ax_cv_have___builtin_clz" >&6; }
+
+ if test yes = $ax_cv_have___builtin_clz
+then :
+
+printf "%s\n" "#define HAVE___BUILTIN_CLZ 1" >>confdefs.h
+
+fi
+
+
+
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __builtin_clzl" >&5
+printf %s "checking for __builtin_clzl... " >&6; }
+if test ${ax_cv_have___builtin_clzl+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ __builtin_clzl(0)
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_have___builtin_clzl=yes
+else case e in #(
+ e) ax_cv_have___builtin_clzl=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_have___builtin_clzl" >&5
+printf "%s\n" "$ax_cv_have___builtin_clzl" >&6; }
+
+ if test yes = $ax_cv_have___builtin_clzl
+then :
+
+printf "%s\n" "#define HAVE___BUILTIN_CLZL 1" >>confdefs.h
+
+fi
+
+
+
+
+utmp_style=LEGACY
+
+ for ac_func in getutsid getutxid getutid
+do :
+ as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | sed "$as_sed_sh"`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_func" | sed "$as_sed_cpp"` 1
+_ACEOF
+ utmp_style=POSIX; break
+fi
+
+done
+if test "$utmp_style" = "LEGACY"
+then :
+
+
+ for ac_func in getttyent ttyslot
+do :
+ as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | sed "$as_sed_sh"`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_func" | sed "$as_sed_cpp"` 1
+_ACEOF
+ break
+fi
+
+done
+
+fi
+
+
+ for ac_func in sysctl
+do :
+ ac_fn_c_check_func "$LINENO" "sysctl" "ac_cv_func_sysctl"
+if test "x$ac_cv_func_sysctl" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYSCTL 1" >>confdefs.h
+
+ ac_fn_c_check_func "$LINENO" "devname" "ac_cv_func_devname"
+if test "x$ac_cv_func_devname" = xyes
+then :
+ printf "%s\n" "#define HAVE_DEVNAME 1" >>confdefs.h
+
+fi
+
+ # Check for the various flavors of kinfo_proc
+ found=false
+ ac_fn_c_check_member "$LINENO" "struct kinfo_proc" "ki_structsize" "ac_cv_member_struct_kinfo_proc_ki_structsize" "
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+"
+if test "x$ac_cv_member_struct_kinfo_proc_ki_structsize" = xyes
+then :
+
+ printf "%s\n" "#define HAVE_KINFO_PROC_FREEBSD 1" >>confdefs.h
+
+ found=true
+
+fi
+
+ if test "$found" = "false"
+then :
+
+ ac_fn_c_check_member "$LINENO" "struct kinfo_proc" "kp_paddr" "ac_cv_member_struct_kinfo_proc_kp_paddr" "
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+"
+if test "x$ac_cv_member_struct_kinfo_proc_kp_paddr" = xyes
+then :
+
+ printf "%s\n" "#define HAVE_KINFO_PROC_DFLY 1" >>confdefs.h
+
+ found=true
+
+fi
+
+
+fi
+ if test "$found" = "false"
+then :
+
+ ac_fn_c_check_member "$LINENO" "struct kinfo_proc2" "p_paddr" "ac_cv_member_struct_kinfo_proc2_p_paddr" "
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+"
+if test "x$ac_cv_member_struct_kinfo_proc2_p_paddr" = xyes
+then :
+
+ printf "%s\n" "#define HAVE_KINFO_PROC2_NETBSD 1" >>confdefs.h
+
+ found=true
+
+fi
+
+
+fi
+ if test "$found" = "false"
+then :
+
+ ac_fn_c_check_member "$LINENO" "struct kinfo_proc" "p_paddr" "ac_cv_member_struct_kinfo_proc_p_paddr" "
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+"
+if test "x$ac_cv_member_struct_kinfo_proc_p_paddr" = xyes
+then :
+
+ printf "%s\n" "#define HAVE_KINFO_PROC_OPENBSD 1" >>confdefs.h
+
+ found=true
+
+fi
+
+
+fi
+ if test "$found" = "false"
+then :
+
+ ac_fn_c_check_member "$LINENO" "struct kinfo_proc" "kp_proc" "ac_cv_member_struct_kinfo_proc_kp_proc" "
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+"
+if test "x$ac_cv_member_struct_kinfo_proc_kp_proc" = xyes
+then :
+
+ printf "%s\n" "#define HAVE_KINFO_PROC_44BSD 1" >>confdefs.h
+
+ found=true
+
+fi
+
+
+fi
+
+fi
+
+done
+
+
+ for ac_func in openpty
+do :
+ ac_fn_c_check_func "$LINENO" "openpty" "ac_cv_func_openpty"
+if test "x$ac_cv_func_openpty" = xyes
+then :
+ printf "%s\n" "#define HAVE_OPENPTY 1" >>confdefs.h
+ for ac_header in libutil.h util.h pty.h
+do :
+ as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | sed "$as_sed_sh"`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_header" | sed "$as_sed_cpp"` 1
+_ACEOF
+ break
+fi
+
+done
+else case e in #(
+ e)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for openpty in -lutil" >&5
+printf %s "checking for openpty in -lutil... " >&6; }
+if test ${ac_cv_lib_util_openpty+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lutil $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char openpty (void);
+int
+main (void)
+{
+return openpty ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_util_openpty=yes
+else case e in #(
+ e) ac_cv_lib_util_openpty=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_util_openpty" >&5
+printf "%s\n" "$ac_cv_lib_util_openpty" >&6; }
+if test "x$ac_cv_lib_util_openpty" = xyes
+then :
+
+ for ac_header in libutil.h util.h pty.h
+do :
+ as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | sed "$as_sed_sh"`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_header" | sed "$as_sed_cpp"` 1
+_ACEOF
+ break
+fi
+
+done
+ case "$SUDO_LIBS" in
+ *-lutil*) ;;
+ *) SUDO_LIBS="${SUDO_LIBS} -lutil";;
+ esac
+ printf "%s\n" "#define HAVE_OPENPTY 1" >>confdefs.h
+
+
+else case e in #(
+ e)
+
+ for ac_func in _getpty
+do :
+ ac_fn_c_check_func "$LINENO" "_getpty" "ac_cv_func__getpty"
+if test "x$ac_cv_func__getpty" = xyes
+then :
+ printf "%s\n" "#define HAVE__GETPTY 1" >>confdefs.h
+
+else case e in #(
+ e)
+
+ for ac_func in grantpt
+do :
+ ac_fn_c_check_func "$LINENO" "grantpt" "ac_cv_func_grantpt"
+if test "x$ac_cv_func_grantpt" = xyes
+then :
+ printf "%s\n" "#define HAVE_GRANTPT 1" >>confdefs.h
+
+ ac_fn_c_check_func "$LINENO" "posix_openpt" "ac_cv_func_posix_openpt"
+if test "x$ac_cv_func_posix_openpt" = xyes
+then :
+ printf "%s\n" "#define HAVE_POSIX_OPENPT 1" >>confdefs.h
+
+fi
+
+
+else case e in #(
+ e)
+ ac_fn_c_check_func "$LINENO" "revoke" "ac_cv_func_revoke"
+if test "x$ac_cv_func_revoke" = xyes
+then :
+ printf "%s\n" "#define HAVE_REVOKE 1" >>confdefs.h
+
+fi
+
+ ;;
+esac
+fi
+
+done
+ ;;
+esac
+fi
+
+done
+ ;;
+esac
+fi
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in unsetenv
+do :
+ ac_fn_c_check_func "$LINENO" "unsetenv" "ac_cv_func_unsetenv"
+if test "x$ac_cv_func_unsetenv" = xyes
+then :
+ printf "%s\n" "#define HAVE_UNSETENV 1" >>confdefs.h
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether unsetenv returns void" >&5
+printf %s "checking whether unsetenv returns void... " >&6; }
+if test ${sudo_cv_func_unsetenv_void+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main (void)
+{
+
+ return unsetenv("FOO");
+
+ ;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ sudo_cv_func_unsetenv_void=no
+else case e in #(
+ e) sudo_cv_func_unsetenv_void=yes ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_func_unsetenv_void" >&5
+printf "%s\n" "$sudo_cv_func_unsetenv_void" >&6; }
+ if test $sudo_cv_func_unsetenv_void = yes; then
+
+printf "%s\n" "#define UNSETENV_VOID 1" >>confdefs.h
+
+ fi
+
+fi
+
+done
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether putenv takes a const argument" >&5
+printf %s "checking whether putenv takes a const argument... " >&6; }
+if test ${sudo_cv_func_putenv_const+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+ int putenv(const char *string) {return 0;}
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ sudo_cv_func_putenv_const=yes
+else case e in #(
+ e) sudo_cv_func_putenv_const=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_func_putenv_const" >&5
+printf "%s\n" "$sudo_cv_func_putenv_const" >&6; }
+ if test $sudo_cv_func_putenv_const = yes; then
+
+printf "%s\n" "#define PUTENV_CONST const" >>confdefs.h
+
+ else
+ printf "%s\n" "#define PUTENV_CONST /**/" >>confdefs.h
+
+ fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ioctl() takes an int request argument" >&5
+printf %s "checking whether ioctl() takes an int request argument... " >&6; }
+if test ${sudo_cv_func_ioctl_req_int+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+ int ioctl(int fd, int req, ...) {return 0;}
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ sudo_cv_func_ioctl_req_int=yes
+else case e in #(
+ e) sudo_cv_func_ioctl_req_int=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_func_ioctl_req_int" >&5
+printf "%s\n" "$sudo_cv_func_ioctl_req_int" >&6; }
+ if test $sudo_cv_func_ioctl_req_int = yes; then
+
+printf "%s\n" "#define IOCTL_REQ_CAST (int)" >>confdefs.h
+
+ else
+ printf "%s\n" "#define IOCTL_REQ_CAST /**/" >>confdefs.h
+
+ fi
+
+if test -z "$SKIP_SETRESUID"
+then :
+
+
+ for ac_func in setresuid
+do :
+ ac_fn_c_check_func "$LINENO" "setresuid" "ac_cv_func_setresuid"
+if test "x$ac_cv_func_setresuid" = xyes
+then :
+ printf "%s\n" "#define HAVE_SETRESUID 1" >>confdefs.h
+
+ SKIP_SETREUID=yes
+ ac_fn_check_decl "$LINENO" "setresuid" "ac_cv_have_decl_setresuid" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_setresuid" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_SETRESUID $ac_have_decl" >>confdefs.h
+
+
+ for ac_func in getresuid
+do :
+ ac_fn_c_check_func "$LINENO" "getresuid" "ac_cv_func_getresuid"
+if test "x$ac_cv_func_getresuid" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETRESUID 1" >>confdefs.h
+ ac_fn_check_decl "$LINENO" "getresuid" "ac_cv_have_decl_getresuid" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_getresuid" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_GETRESUID $ac_have_decl" >>confdefs.h
+
+fi
+
+done
+
+fi
+
+done
+
+fi
+if test -z "$SKIP_SETRESUID"
+then :
+
+ ac_fn_c_check_func "$LINENO" "setreuid" "ac_cv_func_setreuid"
+if test "x$ac_cv_func_setreuid" = xyes
+then :
+ printf "%s\n" "#define HAVE_SETREUID 1" >>confdefs.h
+
+fi
+
+
+fi
+
+
+if test X"$with_interfaces" != X"no"
+then :
+
+
+ for ac_func in getifaddrs
+do :
+ ac_fn_c_check_func "$LINENO" "getifaddrs" "ac_cv_func_getifaddrs"
+if test "x$ac_cv_func_getifaddrs" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETIFADDRS 1" >>confdefs.h
+ ac_fn_c_check_func "$LINENO" "freeifaddrs" "ac_cv_func_freeifaddrs"
+if test "x$ac_cv_func_freeifaddrs" = xyes
+then :
+ printf "%s\n" "#define HAVE_FREEIFADDRS 1" >>confdefs.h
+
+fi
+
+fi
+
+done
+
+fi
+
+ for ac_func in lockf
+do :
+ ac_fn_c_check_func "$LINENO" "lockf" "ac_cv_func_lockf"
+if test "x$ac_cv_func_lockf" = xyes
+then :
+ printf "%s\n" "#define HAVE_LOCKF 1" >>confdefs.h
+ break
+fi
+
+done
+
+ for ac_func in innetgr
+do :
+ ac_fn_c_check_func "$LINENO" "innetgr" "ac_cv_func_innetgr"
+if test "x$ac_cv_func_innetgr" = xyes
+then :
+ printf "%s\n" "#define HAVE_INNETGR 1" >>confdefs.h
+
+ ac_fn_check_decl "$LINENO" "innetgr" "ac_cv_have_decl_innetgr" "
+$ac_includes_default
+#ifdef HAVE_NETGROUP_H
+# include <netgroup.h>
+#else
+# include <netdb.h>
+#endif /* HAVE_NETGROUP_H */
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_innetgr" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_INNETGR $ac_have_decl" >>confdefs.h
+
+else case e in #(
+ e)
+
+ for ac_func in _innetgr
+do :
+ ac_fn_c_check_func "$LINENO" "_innetgr" "ac_cv_func__innetgr"
+if test "x$ac_cv_func__innetgr" = xyes
+then :
+ printf "%s\n" "#define HAVE__INNETGR 1" >>confdefs.h
+
+ ac_fn_check_decl "$LINENO" "_innetgr" "ac_cv_have_decl__innetgr" "
+$ac_includes_default
+#ifdef HAVE_NETGROUP_H
+# include <netgroup.h>
+#else
+# include <netdb.h>
+#endif /* HAVE_NETGROUP_H */
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl__innetgr" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL__INNETGR $ac_have_decl" >>confdefs.h
+
+
+fi
+
+done
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in getdomainname
+do :
+ ac_fn_c_check_func "$LINENO" "getdomainname" "ac_cv_func_getdomainname"
+if test "x$ac_cv_func_getdomainname" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETDOMAINNAME 1" >>confdefs.h
+
+ ac_fn_check_decl "$LINENO" "getdomainname" "ac_cv_have_decl_getdomainname" "
+$ac_includes_default
+#include <netdb.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_getdomainname" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_GETDOMAINNAME $ac_have_decl" >>confdefs.h
+
+
+else case e in #(
+ e)
+
+ for ac_func in sysinfo
+do :
+ ac_fn_c_check_func "$LINENO" "sysinfo" "ac_cv_func_sysinfo"
+if test "x$ac_cv_func_sysinfo" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYSINFO 1" >>confdefs.h
+ ac_fn_c_check_header_compile "$LINENO" "sys/systeminfo.h" "ac_cv_header_sys_systeminfo_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_systeminfo_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_SYSTEMINFO_H 1" >>confdefs.h
+
+fi
+
+fi
+
+done
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in utimensat
+do :
+ ac_fn_c_check_func "$LINENO" "utimensat" "ac_cv_func_utimensat"
+if test "x$ac_cv_func_utimensat" = xyes
+then :
+ printf "%s\n" "#define HAVE_UTIMENSAT 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" utimens.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS utimens.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_utimensat; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ac_fn_c_check_func "$LINENO" "utimes" "ac_cv_func_utimes"
+if test "x$ac_cv_func_utimes" = xyes
+then :
+ printf "%s\n" "#define HAVE_UTIMES 1" >>confdefs.h
+
+fi
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in futimens
+do :
+ ac_fn_c_check_func "$LINENO" "futimens" "ac_cv_func_futimens"
+if test "x$ac_cv_func_futimens" = xyes
+then :
+ printf "%s\n" "#define HAVE_FUTIMENS 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" utimens.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS utimens.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_futimens; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+
+ for ac_func in futimes futimesat futime
+do :
+ as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | sed "$as_sed_sh"`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_func" | sed "$as_sed_cpp"` 1
+_ACEOF
+ break
+fi
+
+done
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in explicit_bzero
+do :
+ ac_fn_c_check_func "$LINENO" "explicit_bzero" "ac_cv_func_explicit_bzero"
+if test "x$ac_cv_func_explicit_bzero" = xyes
+then :
+ printf "%s\n" "#define HAVE_EXPLICIT_BZERO 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" explicit_bzero.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS explicit_bzero.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_explicit_bzero; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+
+ for ac_func in explicit_memset memset_explicit memset_s bzero
+do :
+ as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | sed "$as_sed_sh"`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_func" | sed "$as_sed_cpp"` 1
+_ACEOF
+ break
+fi
+
+done
+ ;;
+esac
+fi
+
+done
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working fnmatch with FNM_CASEFOLD" >&5
+printf %s "checking for working fnmatch with FNM_CASEFOLD... " >&6; }
+if test ${sudo_cv_func_fnmatch+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ if test "$cross_compiling" = yes
+then :
+ sudo_cv_func_fnmatch=no
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <fnmatch.h>
+int main() { return(fnmatch("/*/bin/echo *", "/usr/bin/echo just a test", FNM_CASEFOLD)); }
+_ACEOF
+if ac_fn_c_try_run "$LINENO"
+then :
+ sudo_cv_func_fnmatch=yes
+else case e in #(
+ e) sudo_cv_func_fnmatch=no ;;
+esac
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_func_fnmatch" >&5
+printf "%s\n" "$sudo_cv_func_fnmatch" >&6; }
+ if test $sudo_cv_func_fnmatch = yes
+then :
+ printf "%s\n" "#define HAVE_FNMATCH 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" fnmatch.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS fnmatch.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_fnmatch; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }fnm_test"
+ ;;
+esac
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for isblank" >&5
+printf %s "checking for isblank... " >&6; }
+if test ${sudo_cv_func_isblank+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+int
+main (void)
+{
+return (isblank('a'));
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ sudo_cv_func_isblank=yes
+else case e in #(
+ e) sudo_cv_func_isblank=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_func_isblank" >&5
+printf "%s\n" "$sudo_cv_func_isblank" >&6; }
+
+ if test "$sudo_cv_func_isblank" = "yes"; then
+
+printf "%s\n" "#define HAVE_ISBLANK 1" >>confdefs.h
+
+ else
+ case " $LIBOBJS " in
+ *" isblank.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS isblank.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in isblank; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ fi
+
+
+ for ac_func in glob
+do :
+ ac_fn_c_check_func "$LINENO" "glob" "ac_cv_func_glob"
+if test "x$ac_cv_func_glob" = xyes
+then :
+ printf "%s\n" "#define HAVE_GLOB 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" glob.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS glob.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_glob sudo_globfree; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in memrchr
+do :
+ ac_fn_c_check_func "$LINENO" "memrchr" "ac_cv_func_memrchr"
+if test "x$ac_cv_func_memrchr" = xyes
+then :
+ printf "%s\n" "#define HAVE_MEMRCHR 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" memrchr.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS memrchr.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_memrchr; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in freezero
+do :
+ ac_fn_c_check_func "$LINENO" "freezero" "ac_cv_func_freezero"
+if test "x$ac_cv_func_freezero" = xyes
+then :
+ printf "%s\n" "#define HAVE_FREEZERO 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" freezero.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS freezero.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_freezero; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in nanosleep
+do :
+ ac_fn_c_check_func "$LINENO" "nanosleep" "ac_cv_func_nanosleep"
+if test "x$ac_cv_func_nanosleep" = xyes
+then :
+ printf "%s\n" "#define HAVE_NANOSLEEP 1" >>confdefs.h
+
+else case e in #(
+ e)
+ # On Solaris, nanosleep is in librt
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for nanosleep in -lrt" >&5
+printf %s "checking for nanosleep in -lrt... " >&6; }
+if test ${ac_cv_lib_rt_nanosleep+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrt $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char nanosleep (void);
+int
+main (void)
+{
+return nanosleep ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_rt_nanosleep=yes
+else case e in #(
+ e) ac_cv_lib_rt_nanosleep=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_nanosleep" >&5
+printf "%s\n" "$ac_cv_lib_rt_nanosleep" >&6; }
+if test "x$ac_cv_lib_rt_nanosleep" = xyes
+then :
+
+ printf "%s\n" "#define HAVE_NANOSLEEP 1" >>confdefs.h
+
+ LIBRT="-lrt"
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" nanosleep.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS nanosleep.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_nanosleep; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in fchownat
+do :
+ ac_fn_c_check_func "$LINENO" "fchownat" "ac_cv_func_fchownat"
+if test "x$ac_cv_func_fchownat" = xyes
+then :
+ printf "%s\n" "#define HAVE_FCHOWNAT 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" fchownat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS fchownat.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_fchownat; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in mkdirat
+do :
+ ac_fn_c_check_func "$LINENO" "mkdirat" "ac_cv_func_mkdirat"
+if test "x$ac_cv_func_mkdirat" = xyes
+then :
+ printf "%s\n" "#define HAVE_MKDIRAT 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" mkdirat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS mkdirat.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_mkdirat; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in openat
+do :
+ ac_fn_c_check_func "$LINENO" "openat" "ac_cv_func_openat"
+if test "x$ac_cv_func_openat" = xyes
+then :
+ printf "%s\n" "#define HAVE_OPENAT 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" openat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS openat.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_openat; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in unlinkat
+do :
+ ac_fn_c_check_func "$LINENO" "unlinkat" "ac_cv_func_unlinkat"
+if test "x$ac_cv_func_unlinkat" = xyes
+then :
+ printf "%s\n" "#define HAVE_UNLINKAT 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" unlinkat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS unlinkat.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_unlinkat; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in fchmodat
+do :
+ ac_fn_c_check_func "$LINENO" "fchmodat" "ac_cv_func_fchmodat"
+if test "x$ac_cv_func_fchmodat" = xyes
+then :
+ printf "%s\n" "#define HAVE_FCHMODAT 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" fchmodat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS fchmodat.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_fchmodat; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in fstatat
+do :
+ ac_fn_c_check_func "$LINENO" "fstatat" "ac_cv_func_fstatat"
+if test "x$ac_cv_func_fstatat" = xyes
+then :
+ printf "%s\n" "#define HAVE_FSTATAT 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" fstatat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS fstatat.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_fstatat; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in dup3
+do :
+ ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3"
+if test "x$ac_cv_func_dup3" = xyes
+then :
+ printf "%s\n" "#define HAVE_DUP3 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" dup3.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS dup3.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_dup3; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in pipe2
+do :
+ ac_fn_c_check_func "$LINENO" "pipe2" "ac_cv_func_pipe2"
+if test "x$ac_cv_func_pipe2" = xyes
+then :
+ printf "%s\n" "#define HAVE_PIPE2 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" pipe2.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS pipe2.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_pipe2; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in pw_dup
+do :
+ ac_fn_c_check_func "$LINENO" "pw_dup" "ac_cv_func_pw_dup"
+if test "x$ac_cv_func_pw_dup" = xyes
+then :
+ printf "%s\n" "#define HAVE_PW_DUP 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" pw_dup.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS pw_dup.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_pw_dup; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in realpath
+do :
+ ac_fn_c_check_func "$LINENO" "realpath" "ac_cv_func_realpath"
+if test "x$ac_cv_func_realpath" = xyes
+then :
+ printf "%s\n" "#define HAVE_REALPATH 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" realpath.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS realpath.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_realpath; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in strlcpy
+do :
+ ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy"
+if test "x$ac_cv_func_strlcpy" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRLCPY 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" strlcpy.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strlcpy.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_strlcpy; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in strlcat
+do :
+ ac_fn_c_check_func "$LINENO" "strlcat" "ac_cv_func_strlcat"
+if test "x$ac_cv_func_strlcat" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRLCAT 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" strlcat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strlcat.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_strlcat; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+ac_fn_c_check_func "$LINENO" "strnlen" "ac_cv_func_strnlen"
+if test "x$ac_cv_func_strnlen" = xyes
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working strnlen" >&5
+printf %s "checking for working strnlen... " >&6; }
+if test ${ac_cv_func_strnlen_working+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test "$cross_compiling" = yes
+then :
+ # Guess no on AIX systems, yes otherwise.
+ case "$host_os" in
+ aix*) ac_cv_func_strnlen_working=no;;
+ *) ac_cv_func_strnlen_working=yes;;
+ esac
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main (void)
+{
+
+#define S "foobar"
+#define S_LEN (sizeof S - 1)
+
+ /* At least one implementation is buggy: that of AIX 4.3 would
+ give strnlen (S, 1) == 3. */
+
+ int i;
+ for (i = 0; i < S_LEN + 1; ++i)
+ {
+ int expected = i <= S_LEN ? i : S_LEN;
+ if (strnlen (S, i) != expected)
+ return 1;
+ }
+ return 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"
+then :
+ ac_cv_func_strnlen_working=yes
+else case e in #(
+ e) ac_cv_func_strnlen_working=no ;;
+esac
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_strnlen_working" >&5
+printf "%s\n" "$ac_cv_func_strnlen_working" >&6; }
+test $ac_cv_func_strnlen_working = no && case " $LIBOBJS " in
+ *" strnlen.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strnlen.$ac_objext"
+ ;;
+esac
+
+
+else case e in #(
+ e) case " $LIBOBJS " in
+ *" strnlen.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strnlen.$ac_objext"
+ ;;
+esac
+ ;;
+esac
+fi
+
+if test X"$ac_cv_func_strnlen_working" = X"yes"
+then :
+
+ printf "%s\n" "#define HAVE_STRNLEN 1" >>confdefs.h
+
+
+ for ac_func in strndup
+do :
+ ac_fn_c_check_func "$LINENO" "strndup" "ac_cv_func_strndup"
+if test "x$ac_cv_func_strndup" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRNDUP 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" strndup.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strndup.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_strndup; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+else case e in #(
+ e)
+ # Broken or missing strnlen, use our own.
+
+ for _sym in sudo_strnlen; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ # Avoid libc strndup() since it is usually implemented using strnlen()
+ case " $LIBOBJS " in
+ *" strndup.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strndup.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_strndup; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+ for ac_func in clock_gettime
+do :
+ ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime"
+if test "x$ac_cv_func_clock_gettime" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h
+
+else case e in #(
+ e)
+ # On Solaris, clock_gettime is in librt
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+printf %s "checking for clock_gettime in -lrt... " >&6; }
+if test ${ac_cv_lib_rt_clock_gettime+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrt $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime (void);
+int
+main (void)
+{
+return clock_gettime ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_rt_clock_gettime=yes
+else case e in #(
+ e) ac_cv_lib_rt_clock_gettime=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+printf "%s\n" "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = xyes
+then :
+
+ printf "%s\n" "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h
+
+ LIBRT="-lrt"
+
+fi
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in getopt_long
+do :
+ ac_fn_c_check_func "$LINENO" "getopt_long" "ac_cv_func_getopt_long"
+if test "x$ac_cv_func_getopt_long" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETOPT_LONG 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" getopt_long.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS getopt_long.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_getopt_long sudo_getopt_long_only; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for optreset" >&5
+printf %s "checking for optreset... " >&6; }
+if test ${sudo_cv_optreset+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+extern int optreset; optreset = 1; return optreset;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ sudo_cv_optreset=yes
+else case e in #(
+ e) sudo_cv_optreset=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_optreset" >&5
+printf "%s\n" "$sudo_cv_optreset" >&6; }
+ if test "$sudo_cv_optreset" = "yes"
+then :
+
+ printf "%s\n" "#define HAVE_OPTRESET 1" >>confdefs.h
+
+
+fi
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in closefrom
+do :
+ ac_fn_c_check_func "$LINENO" "closefrom" "ac_cv_func_closefrom"
+if test "x$ac_cv_func_closefrom" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOSEFROM 1" >>confdefs.h
+
+else case e in #(
+ e) case " $LIBOBJS " in
+ *" closefrom.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS closefrom.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_closefrom; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ac_fn_check_decl "$LINENO" "F_CLOSEM" "ac_cv_have_decl_F_CLOSEM" "
+# include <limits.h>
+# include <fcntl.h>
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_F_CLOSEM" = xyes
+then :
+ printf "%s\n" "#define HAVE_FCNTL_CLOSEM 1" >>confdefs.h
+
+else case e in #(
+ e)
+ # Linux has a special header for close_range(2).
+
+ for ac_func in close_range
+do :
+ ac_fn_c_check_func "$LINENO" "close_range" "ac_cv_func_close_range"
+if test "x$ac_cv_func_close_range" = xyes
+then :
+ printf "%s\n" "#define HAVE_CLOSE_RANGE 1" >>confdefs.h
+
+ case "$host_os" in
+ linux*) ac_fn_c_check_header_compile "$LINENO" "linux/close_range.h" "ac_cv_header_linux_close_range_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_close_range_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_LINUX_CLOSE_RANGE_H 1" >>confdefs.h
+
+fi
+;;
+ esac
+
+fi
+
+done
+ ;;
+esac
+fi
+ COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }closefrom_test"
+ ;;
+esac
+fi
+
+done
+sudo_mktemp=no
+case "$host_os" in
+ darwin*)
+ # macOS has these but uses a _np (non-portable) suffix
+
+ for ac_func in mkdtempat_np mkostempsat_np
+do :
+ as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | sed "$as_sed_sh"`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_func" | sed "$as_sed_cpp"` 1
+_ACEOF
+
+else case e in #(
+ e) sudo_mktemp=yes; break ;;
+esac
+fi
+
+done
+ ;;
+ *)
+
+ for ac_func in mkdtempat mkostempsat
+do :
+ as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | sed "$as_sed_sh"`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_func" | sed "$as_sed_cpp"` 1
+_ACEOF
+
+else case e in #(
+ e) sudo_mktemp=yes; break ;;
+esac
+fi
+
+done
+ ;;
+esac
+# If any of the mktemp family are missing we use our own.
+if test X"$sudo_mktemp" = X"yes"
+then :
+
+ case " $LIBOBJS " in
+ *" mktemp.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS mktemp.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_mkdtemp sudo_mkdtempat sudo_mkostempsat sudo_mkstemp sudo_mkstemps; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }mktemp_test"
+
+fi
+ac_fn_c_check_func "$LINENO" "snprintf" "ac_cv_func_snprintf"
+if test "x$ac_cv_func_snprintf" = xyes
+then :
+ printf "%s\n" "#define HAVE_SNPRINTF 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "vsnprintf" "ac_cv_func_vsnprintf"
+if test "x$ac_cv_func_vsnprintf" = xyes
+then :
+ printf "%s\n" "#define HAVE_VSNPRINTF 1" >>confdefs.h
+
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working snprintf" >&5
+printf %s "checking for working snprintf... " >&6; }
+if test ${ac_cv_have_working_snprintf+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test "$cross_compiling" = yes
+then :
+ ac_cv_have_working_snprintf=cross
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+#include <string.h>
+
+int main(void)
+{
+ char bufs[5] = { 'x', 'x', 'x', '\0', '\0' };
+ char bufd[5] = { 'x', 'x', 'x', '\0', '\0' };
+ int i;
+ i = snprintf (bufs, 2, "%s", "111");
+ if (strcmp (bufs, "1")) return (1);
+ if (i != 3) return (1);
+ i = snprintf (bufd, 2, "%d", 111);
+ if (strcmp (bufd, "1")) return (1);
+ if (i != 3) return (1);
+ return(0);
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"
+then :
+ ac_cv_have_working_snprintf=yes
+else case e in #(
+ e) ac_cv_have_working_snprintf=no ;;
+esac
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+ ;;
+esac
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_working_snprintf" >&5
+printf "%s\n" "$ac_cv_have_working_snprintf" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working vsnprintf" >&5
+printf %s "checking for working vsnprintf... " >&6; }
+if test ${ac_cv_have_working_vsnprintf+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test "$cross_compiling" = yes
+then :
+ ac_cv_have_working_vsnprintf=cross
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+int my_vsnprintf (char *buf, const char *tmpl, ...)
+{
+ int i;
+ va_list args;
+ va_start (args, tmpl);
+ i = vsnprintf (buf, 2, tmpl, args);
+ va_end (args);
+ return i;
+}
+
+int main(void)
+{
+ char bufs[5] = { 'x', 'x', 'x', '\0', '\0' };
+ char bufd[5] = { 'x', 'x', 'x', '\0', '\0' };
+ int i;
+ i = my_vsnprintf (bufs, "%s", "111");
+ if (strcmp (bufs, "1")) return (1);
+ if (i != 3) return (1);
+ i = my_vsnprintf (bufd, "%d", 111);
+ if (strcmp (bufd, "1")) return (1);
+ if (i != 3) return (1);
+ return(0);
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"
+then :
+ ac_cv_have_working_vsnprintf=yes
+else case e in #(
+ e) ac_cv_have_working_vsnprintf=no ;;
+esac
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+ ;;
+esac
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_working_vsnprintf" >&5
+printf "%s\n" "$ac_cv_have_working_vsnprintf" >&6; }
+if test x$ac_cv_have_working_snprintf$ac_cv_have_working_vsnprintf != "xyesyes"; then
+ case " $LIBOBJS " in
+ *" snprintf.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS snprintf.$ac_objext"
+ ;;
+esac
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Replacing missing/broken (v)snprintf() with sudo's version." >&5
+printf "%s\n" "$as_me: WARNING: Replacing missing/broken (v)snprintf() with sudo's version." >&2;}
+
+printf "%s\n" "#define PREFER_PORTABLE_SNPRINTF 1" >>confdefs.h
+
+fi
+if test X"$ac_cv_have_working_snprintf$ac_cv_have_working_vsnprintf" = X"yesyes"
+then :
+
+ # System has a C99-compliant v?snprintf(), check for v?asprintf()
+
+ for ac_func in asprintf
+do :
+ ac_fn_c_check_func "$LINENO" "asprintf" "ac_cv_func_asprintf"
+if test "x$ac_cv_func_asprintf" = xyes
+then :
+ printf "%s\n" "#define HAVE_ASPRINTF 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" snprintf.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS snprintf.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_asprintf; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in vasprintf
+do :
+ ac_fn_c_check_func "$LINENO" "vasprintf" "ac_cv_func_vasprintf"
+if test "x$ac_cv_func_vasprintf" = xyes
+then :
+ printf "%s\n" "#define HAVE_VASPRINTF 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" snprintf.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS snprintf.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_vasprintf; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+else case e in #(
+ e)
+ # Missing or non-compliant v?snprintf(), assume missing/bad v?asprintf()
+
+ for _sym in sudo_snprintf sudo_vsnprintf sudo_asprintf sudo_vasprintf; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+ac_fn_c_check_member "$LINENO" "struct tm" "tm_gmtoff" "ac_cv_member_struct_tm_tm_gmtoff" "
+$ac_includes_default
+#include <errno.h>
+
+"
+if test "x$ac_cv_member_struct_tm_tm_gmtoff" = xyes
+then :
+
+printf "%s\n" "#define HAVE_STRUCT_TM_TM_GMTOFF 1" >>confdefs.h
+
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim" "ac_cv_member_struct_stat_st_mtim" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_mtim" = xyes
+then :
+ printf "%s\n" "#define HAVE_ST_MTIM 1" >>confdefs.h
+
+ ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim.st__tim" "ac_cv_member_struct_stat_st_mtim_st__tim" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_mtim_st__tim" = xyes
+then :
+ printf "%s\n" "#define HAVE_ST__TIM 1" >>confdefs.h
+
+fi
+
+else case e in #(
+ e) ac_fn_c_check_member "$LINENO" "struct stat" "st_mtimespec" "ac_cv_member_struct_stat_st_mtimespec" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_mtimespec" = xyes
+then :
+ printf "%s\n" "#define HAVE_ST_MTIMESPEC 1" >>confdefs.h
+
+else case e in #(
+ e) ac_fn_c_check_member "$LINENO" "struct stat" "st_nmtime" "ac_cv_member_struct_stat_st_nmtime" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_nmtime" = xyes
+then :
+ printf "%s\n" "#define HAVE_ST_NMTIME 1" >>confdefs.h
+
+fi
+ ;;
+esac
+fi
+
+
+ ;;
+esac
+fi
+
+ac_fn_c_check_func "$LINENO" "setpassent" "ac_cv_func_setpassent"
+if test "x$ac_cv_func_setpassent" = xyes
+then :
+ printf "%s\n" "#define HAVE_SETPASSENT 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "setgroupent" "ac_cv_func_setgroupent"
+if test "x$ac_cv_func_setgroupent" = xyes
+then :
+ printf "%s\n" "#define HAVE_SETGROUPENT 1" >>confdefs.h
+
+fi
+
+if test X"$with_noexec" != X"no"
+then :
+
+ # Check for non-standard exec functions
+ ac_fn_c_check_func "$LINENO" "exect" "ac_cv_func_exect"
+if test "x$ac_cv_func_exect" = xyes
+then :
+ printf "%s\n" "#define HAVE_EXECT 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "execvP" "ac_cv_func_execvP"
+if test "x$ac_cv_func_execvP" = xyes
+then :
+ printf "%s\n" "#define HAVE_EXECVP 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "execvpe" "ac_cv_func_execvpe"
+if test "x$ac_cv_func_execvpe" = xyes
+then :
+ printf "%s\n" "#define HAVE_EXECVPE 1" >>confdefs.h
+
+fi
+
+ # Check for posix_spawn, and posix_spawnp
+ if test X"$ac_cv_header_spawn_h" = X"yes"
+then :
+
+ ac_fn_c_check_func "$LINENO" "posix_spawn" "ac_cv_func_posix_spawn"
+if test "x$ac_cv_func_posix_spawn" = xyes
+then :
+ printf "%s\n" "#define HAVE_POSIX_SPAWN 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "posix_spawnp" "ac_cv_func_posix_spawnp"
+if test "x$ac_cv_func_posix_spawnp" = xyes
+then :
+ printf "%s\n" "#define HAVE_POSIX_SPAWNP 1" >>confdefs.h
+
+fi
+
+
+fi
+
+fi
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <$ac_header_dirent>
+int
+main (void)
+{
+DIR *d; (void)dirfd(d);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ printf "%s\n" "#define HAVE_DIRFD 1" >>confdefs.h
+
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <$ac_header_dirent>
+int
+main (void)
+{
+DIR d; memset(&d, 0, sizeof(d)); return(d.dd_fd);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ printf "%s\n" "#define HAVE_DD_FD 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ac_fn_c_check_member "$LINENO" "struct dirent" "d_type" "ac_cv_member_struct_dirent_d_type" "
+$ac_includes_default
+#include <$ac_header_dirent>
+
+"
+if test "x$ac_cv_member_struct_dirent_d_type" = xyes
+then :
+
+printf "%s\n" "#define HAVE_STRUCT_DIRENT_D_TYPE 1" >>confdefs.h
+
+
+fi
+ac_fn_c_check_member "$LINENO" "struct dirent" "d_namlen" "ac_cv_member_struct_dirent_d_namlen" "
+$ac_includes_default
+#include <$ac_header_dirent>
+
+"
+if test "x$ac_cv_member_struct_dirent_d_namlen" = xyes
+then :
+
+printf "%s\n" "#define HAVE_STRUCT_DIRENT_D_NAMLEN 1" >>confdefs.h
+
+
+fi
+
+
+
+
+ openssl_missing=no
+ if test "${enable_openssl-no}" != no; then
+ # Use pkg-config to find the openssl cflags and libs if possible.
+ if test "$enable_openssl" != "yes" -a "$enable_openssl" != "maybe"; then
+ PKG_CONFIG_LIBDIR=
+ for d in ${enable_openssl}/*/pkgconfig; do
+ if test -d "$d"; then
+ PKG_CONFIG_LIBDIR="$PKG_CONFIG_LIBDIR:$d"
+ fi
+ done
+ if test -n "$PKG_CONFIG_LIBDIR"; then
+ PKG_CONFIG_LIBDIR=${PKG_CONFIG_LIBDIR#:}
+ export PKG_CONFIG_LIBDIR
+ fi
+ elif test "$cross_compiling" = "yes" -a -z "$PKG_CONFIG"; then
+ # Cannot use pkg-config when cross-compiling
+ PKG_CONFIG=false
+ fi
+ : ${PKG_CONFIG='pkg-config'}
+ pkg_openssl=`printf $enable_openssl_pkgconfig_template "openssl"`
+ pkg_libcrypto=lib`printf $enable_openssl_pkgconfig_template "crypto"`
+ if $PKG_CONFIG --exists "$pkg_openssl >= 1.0.1" >/dev/null 2>&1; then
+ printf "%s\n" "#define HAVE_OPENSSL 1" >>confdefs.h
+
+ if test "$enable_openssl" = "maybe"; then
+ enable_openssl=yes
+ fi
+
+ # Check whether --static is needed (don't assume name of ssl lib)
+ # There may be dependent libraries or -pthread.
+ O_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS `$PKG_CONFIG --libs-only-L $pkg_openssl`"
+ libssl="`$PKG_CONFIG --libs-only-l $pkg_openssl | sed 's/^ *-l//'`"
+ libssl_extra="`echo $libssl | sed 's/^[^ ]* *//'`"
+ libssl="`echo $libssl | sed 's/ .*//'`"
+ as_ac_Lib=`printf "%s\n" "ac_cv_lib_$libssl""_SSL_new$libssl_extra" | sed "$as_sed_sh"`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SSL_new in -l$libssl" >&5
+printf %s "checking for SSL_new in -l$libssl... " >&6; }
+if eval test \${$as_ac_Lib+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-l$libssl $libssl_extra $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char SSL_new (void);
+int
+main (void)
+{
+return SSL_new ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ eval "$as_ac_Lib=yes"
+else case e in #(
+ e) eval "$as_ac_Lib=no" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+eval ac_res=\$$as_ac_Lib
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"
+then :
+ STATIC=""
+else case e in #(
+ e) STATIC="--static" ;;
+esac
+fi
+
+ LDFLAGS="$O_LDFLAGS"
+
+ # Use pkg-config to determine OpenSSL libs and cflags
+ for f in `$PKG_CONFIG $STATIC --libs $pkg_openssl`; do
+ case "$f" in
+ -L*)
+ f="${f#-L}"
+
+
+if test ${LIBTLS+y}
+then :
+
+ case " $LIBTLS " in #(
+ *" -L$f "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS already contains -L\$f"; } >&5
+ (: LIBTLS already contains -L$f) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LIBTLS " -L$f"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS=\"\$LIBTLS\""; } >&5
+ (: LIBTLS="$LIBTLS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LIBTLS=-L$f
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS=\"\$LIBTLS\""; } >&5
+ (: LIBTLS="$LIBTLS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${LIBTLS_R+y}
+then :
+
+ case " $LIBTLS_R " in #(
+ *" -R$f "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS_R already contains -R\$f"; } >&5
+ (: LIBTLS_R already contains -R$f) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LIBTLS_R " -R$f"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS_R=\"\$LIBTLS_R\""; } >&5
+ (: LIBTLS_R="$LIBTLS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LIBTLS_R=-R$f
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS_R=\"\$LIBTLS_R\""; } >&5
+ (: LIBTLS_R="$LIBTLS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+ ;;
+ *)
+ # Do not use AX_APPEND_FLAG as it will break static builds by removing
+ # duplicates such as -lz or -latomic which are needed by -lssl and -lcrypto
+ LIBTLS="$LIBTLS $f"
+ ;;
+ esac
+ done
+ if $PKG_CONFIG --exists $pkg_libcrypto >/dev/null 2>&1; then
+ # Use OpenSSL's sha2 functions if possible (don't assume name of crypto)
+ O_LDFLAGS="$LDFLAGS"
+ libcrypto=
+ libcrypto_extra=
+ for f in `$PKG_CONFIG $STATIC --libs $pkg_libcrypto`; do
+ case "$f" in
+ -l*)
+ if test -z "$libcrypto"; then
+ libcrypto="${f#-l}"
+ else
+ libcrypto_extra="$libcrypto_extra $f"
+ fi
+ ;;
+ *)
+
+if test ${LDFLAGS+y}
+then :
+
+ case " $LDFLAGS " in #(
+ *" $f "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS already contains \$f"; } >&5
+ (: LDFLAGS already contains $f) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LDFLAGS " $f"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS\""; } >&5
+ (: LDFLAGS="$LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LDFLAGS=$f
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS\""; } >&5
+ (: LDFLAGS="$LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ ;;
+ esac
+ done
+ as_ac_Lib=`printf "%s\n" "ac_cv_lib_$libcrypto""_EVP_MD_CTX_new$libcrypto_extra" | sed "$as_sed_sh"`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for EVP_MD_CTX_new in -l$libcrypto" >&5
+printf %s "checking for EVP_MD_CTX_new in -l$libcrypto... " >&6; }
+if eval test \${$as_ac_Lib+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-l$libcrypto $libcrypto_extra $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char EVP_MD_CTX_new (void);
+int
+main (void)
+{
+return EVP_MD_CTX_new ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ eval "$as_ac_Lib=yes"
+else case e in #(
+ e) eval "$as_ac_Lib=no" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+eval ac_res=\$$as_ac_Lib
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"
+then :
+ DIGEST=digest_openssl.lo
+fi
+
+ LDFLAGS="$O_LDFLAGS"
+
+ # Use pkg-config to determine libcrypto libs and cflags
+ for f in `$PKG_CONFIG $STATIC --libs $pkg_libcrypto`; do
+ case "$f" in
+ -L*)
+ f="${f#-L}"
+
+
+if test ${LIBCRYPTO+y}
+then :
+
+ case " $LIBCRYPTO " in #(
+ *" -L$f "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO already contains -L\$f"; } >&5
+ (: LIBCRYPTO already contains -L$f) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LIBCRYPTO " -L$f"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO=\"\$LIBCRYPTO\""; } >&5
+ (: LIBCRYPTO="$LIBCRYPTO") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LIBCRYPTO=-L$f
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO=\"\$LIBCRYPTO\""; } >&5
+ (: LIBCRYPTO="$LIBCRYPTO") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${LIBCRYPTO_R+y}
+then :
+
+ case " $LIBCRYPTO_R " in #(
+ *" -R$f "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO_R already contains -R\$f"; } >&5
+ (: LIBCRYPTO_R already contains -R$f) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LIBCRYPTO_R " -R$f"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO_R=\"\$LIBCRYPTO_R\""; } >&5
+ (: LIBCRYPTO_R="$LIBCRYPTO_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LIBCRYPTO_R=-R$f
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO_R=\"\$LIBCRYPTO_R\""; } >&5
+ (: LIBCRYPTO_R="$LIBCRYPTO_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+ ;;
+ *)
+
+if test ${LIBCRYPTO+y}
+then :
+
+ case " $LIBCRYPTO " in #(
+ *" $f "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO already contains \$f"; } >&5
+ (: LIBCRYPTO already contains $f) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LIBCRYPTO " $f"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO=\"\$LIBCRYPTO\""; } >&5
+ (: LIBCRYPTO="$LIBCRYPTO") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LIBCRYPTO=$f
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO=\"\$LIBCRYPTO\""; } >&5
+ (: LIBCRYPTO="$LIBCRYPTO") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ ;;
+ esac
+ done
+ else
+ # No separate pkg config for libcrypto
+ LIBCRYPTO="$LIBTLS"
+ LIBCRYPTO_R="$LIBTLS_R"
+ fi
+ for f in `$PKG_CONFIG --cflags-only-I $pkg_openssl`; do
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" $f "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains \$f"; } >&5
+ (: CPPFLAGS already contains $f) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " $f"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=$f
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ done
+ else
+ # No pkg-config file present, try to do it manually
+ O_LDFLAGS="$LDFLAGS"
+ if test "$enable_openssl" != "yes" -a "$enable_openssl" != "maybe"; then
+
+
+if test ${LDFLAGS+y}
+then :
+
+ case " $LDFLAGS " in #(
+ *" -L${enable_openssl}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS already contains -L\${enable_openssl}/lib"; } >&5
+ (: LDFLAGS already contains -L${enable_openssl}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LDFLAGS " -L${enable_openssl}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS\""; } >&5
+ (: LDFLAGS="$LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LDFLAGS=-L${enable_openssl}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS\""; } >&5
+ (: LDFLAGS="$LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${LDFLAGS_R+y}
+then :
+
+ case " $LDFLAGS_R " in #(
+ *" -R${enable_openssl}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS_R already contains -R\${enable_openssl}/lib"; } >&5
+ (: LDFLAGS_R already contains -R${enable_openssl}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LDFLAGS_R " -R${enable_openssl}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS_R=\"\$LDFLAGS_R\""; } >&5
+ (: LDFLAGS_R="$LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LDFLAGS_R=-R${enable_openssl}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS_R=\"\$LDFLAGS_R\""; } >&5
+ (: LDFLAGS_R="$LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+ fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SSL_new in -lssl" >&5
+printf %s "checking for SSL_new in -lssl... " >&6; }
+if test ${ac_cv_lib_ssl_SSL_new_lcrypto+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lssl -lcrypto $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char SSL_new (void);
+int
+main (void)
+{
+return SSL_new ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_ssl_SSL_new_lcrypto=yes
+else case e in #(
+ e) ac_cv_lib_ssl_SSL_new_lcrypto=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_new_lcrypto" >&5
+printf "%s\n" "$ac_cv_lib_ssl_SSL_new_lcrypto" >&6; }
+if test "x$ac_cv_lib_ssl_SSL_new_lcrypto" = xyes
+then :
+
+ # Check OPENSSL_VERSION_NUMBER in headers
+ O_CPPFLAGS="$CPPFLAGS"
+ if test "$enable_openssl" != "yes" -a "$enable_openssl" != "maybe"; then
+ # Note: we only reset CPPFLAGS on failure
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -I${enable_openssl}/include "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -I\${enable_openssl}/include"; } >&5
+ (: CPPFLAGS already contains -I${enable_openssl}/include) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -I${enable_openssl}/include"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-I${enable_openssl}/include
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <openssl/opensslv.h>
+#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x1000100fL
+#error "OpenSSL too old"
+#endif
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+
+ # OpenSSL >= 1.0.1 detected, use it.
+ printf "%s\n" "#define HAVE_OPENSSL 1" >>confdefs.h
+
+ if test "$enable_openssl" != "yes" -a "$enable_openssl" != "maybe"; then
+
+
+if test ${LIBCRYPTO+y}
+then :
+
+ case " $LIBCRYPTO " in #(
+ *" -L${enable_openssl}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO already contains -L\${enable_openssl}/lib"; } >&5
+ (: LIBCRYPTO already contains -L${enable_openssl}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LIBCRYPTO " -L${enable_openssl}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO=\"\$LIBCRYPTO\""; } >&5
+ (: LIBCRYPTO="$LIBCRYPTO") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LIBCRYPTO=-L${enable_openssl}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO=\"\$LIBCRYPTO\""; } >&5
+ (: LIBCRYPTO="$LIBCRYPTO") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${LIBCRYPTO_R+y}
+then :
+
+ case " $LIBCRYPTO_R " in #(
+ *" -R${enable_openssl}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO_R already contains -R\${enable_openssl}/lib"; } >&5
+ (: LIBCRYPTO_R already contains -R${enable_openssl}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LIBCRYPTO_R " -R${enable_openssl}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO_R=\"\$LIBCRYPTO_R\""; } >&5
+ (: LIBCRYPTO_R="$LIBCRYPTO_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LIBCRYPTO_R=-R${enable_openssl}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO_R=\"\$LIBCRYPTO_R\""; } >&5
+ (: LIBCRYPTO_R="$LIBCRYPTO_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+
+
+if test ${LIBTLS+y}
+then :
+
+ case " $LIBTLS " in #(
+ *" -L${enable_openssl}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS already contains -L\${enable_openssl}/lib"; } >&5
+ (: LIBTLS already contains -L${enable_openssl}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LIBTLS " -L${enable_openssl}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS=\"\$LIBTLS\""; } >&5
+ (: LIBTLS="$LIBTLS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LIBTLS=-L${enable_openssl}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS=\"\$LIBTLS\""; } >&5
+ (: LIBTLS="$LIBTLS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${LIBTLS_R+y}
+then :
+
+ case " $LIBTLS_R " in #(
+ *" -R${enable_openssl}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS_R already contains -R\${enable_openssl}/lib"; } >&5
+ (: LIBTLS_R already contains -R${enable_openssl}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LIBTLS_R " -R${enable_openssl}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS_R=\"\$LIBTLS_R\""; } >&5
+ (: LIBTLS_R="$LIBTLS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LIBTLS_R=-R${enable_openssl}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS_R=\"\$LIBTLS_R\""; } >&5
+ (: LIBTLS_R="$LIBTLS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+ else
+ enable_openssl=yes
+ fi
+ LIBCRYPTO="${LIBCRYPTO} -lcrypto"
+ LIBTLS="${LIBTLS} -lssl -lcrypto"
+
+ # Use OpenSSL's sha2 functions if possible
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for EVP_MD_CTX_new in -lcrypto" >&5
+printf %s "checking for EVP_MD_CTX_new in -lcrypto... " >&6; }
+if test ${ac_cv_lib_crypto_EVP_MD_CTX_new+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypto $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char EVP_MD_CTX_new (void);
+int
+main (void)
+{
+return EVP_MD_CTX_new ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_crypto_EVP_MD_CTX_new=yes
+else case e in #(
+ e) ac_cv_lib_crypto_EVP_MD_CTX_new=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_EVP_MD_CTX_new" >&5
+printf "%s\n" "$ac_cv_lib_crypto_EVP_MD_CTX_new" >&6; }
+if test "x$ac_cv_lib_crypto_EVP_MD_CTX_new" = xyes
+then :
+
+ DIGEST=digest_openssl.lo
+
+fi
+
+
+else case e in #(
+ e)
+ # OpenSSL < 1.0.1 detected, ignore it.
+ if test "$enable_openssl" = "maybe"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: OpenSSL too old (1.0.1 or higher required), Sudo logsrv connections will not be encrypted." >&5
+printf "%s\n" "$as_me: WARNING: OpenSSL too old (1.0.1 or higher required), Sudo logsrv connections will not be encrypted." >&2;}
+ openssl_missing=yes
+ enable_openssl=no
+ else
+ as_fn_error $? "OpenSSL too old (1.0.1 or higher required)." "$LINENO" 5
+ fi
+ CPPFLAGS="$O_CPPFLAGS"
+ ;;
+esac
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+else case e in #(
+ e)
+ if test "$enable_openssl" = "maybe"; then
+ openssl_missing=yes
+ enable_openssl=no
+ else
+ as_fn_error $? "OpenSSL development libraries not found." "$LINENO" 5
+ fi
+ ;;
+esac
+fi
+
+ LDFLAGS="$O_LDFLAGS"
+ fi
+ if test "$enable_openssl" != "yes" -a "$enable_openssl" != "maybe"; then
+ unset PKG_CONFIG_LIBDIR
+ fi
+ fi
+ #
+ # Note that enable_openssl may be reset above.
+ #
+ if test "${enable_openssl-no}" != no; then
+ OLIBS="$LIBS"
+ LIBS="$LIBS $LIBTLS"
+ ac_fn_c_check_func "$LINENO" "X509_STORE_CTX_get0_cert" "ac_cv_func_X509_STORE_CTX_get0_cert"
+if test "x$ac_cv_func_X509_STORE_CTX_get0_cert" = xyes
+then :
+ printf "%s\n" "#define HAVE_X509_STORE_CTX_GET0_CERT 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "ASN1_STRING_get0_data" "ac_cv_func_ASN1_STRING_get0_data"
+if test "x$ac_cv_func_ASN1_STRING_get0_data" = xyes
+then :
+ printf "%s\n" "#define HAVE_ASN1_STRING_GET0_DATA 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "SSL_CTX_get0_certificate" "ac_cv_func_SSL_CTX_get0_certificate"
+if test "x$ac_cv_func_SSL_CTX_get0_certificate" = xyes
+then :
+ printf "%s\n" "#define HAVE_SSL_CTX_GET0_CERTIFICATE 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "SSL_CTX_set0_tmp_dh_pkey" "ac_cv_func_SSL_CTX_set0_tmp_dh_pkey"
+if test "x$ac_cv_func_SSL_CTX_set0_tmp_dh_pkey" = xyes
+then :
+ printf "%s\n" "#define HAVE_SSL_CTX_SET0_TMP_DH_PKEY 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "TLS_method" "ac_cv_func_TLS_method"
+if test "x$ac_cv_func_TLS_method" = xyes
+then :
+ printf "%s\n" "#define HAVE_TLS_METHOD 1" >>confdefs.h
+
+fi
+
+ # SSL_CTX_set_min_proto_version may be a macro
+ ac_fn_check_decl "$LINENO" "SSL_CTX_set_min_proto_version" "ac_cv_have_decl_SSL_CTX_set_min_proto_version" "
+ $ac_includes_default
+ #include <openssl/ssl.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SSL_CTX_set_min_proto_version" = xyes
+then :
+ printf "%s\n" "#define HAVE_SSL_CTX_SET_MIN_PROTO_VERSION 1" >>confdefs.h
+
+fi
+
+ for ac_func in SSL_read_ex
+do :
+ ac_fn_c_check_func "$LINENO" "SSL_read_ex" "ac_cv_func_SSL_read_ex"
+if test "x$ac_cv_func_SSL_read_ex" = xyes
+then :
+ printf "%s\n" "#define HAVE_SSL_READ_EX 1" >>confdefs.h
+
+else case e in #(
+ e)
+ SSL_COMPAT_SRC=lib/ssl_compat
+ ;;
+esac
+fi
+
+done
+ # LibreSSL TLS 1.3 support may not be enabled, check for declaration too.
+ ac_fn_c_check_func "$LINENO" "SSL_CTX_set_ciphersuites" "ac_cv_func_SSL_CTX_set_ciphersuites"
+if test "x$ac_cv_func_SSL_CTX_set_ciphersuites" = xyes
+then :
+
+ ac_fn_check_decl "$LINENO" "SSL_CTX_set_ciphersuites" "ac_cv_have_decl_SSL_CTX_set_ciphersuites" "
+ $ac_includes_default
+ #include <openssl/ssl.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SSL_CTX_set_ciphersuites" = xyes
+then :
+ printf "%s\n" "#define HAVE_SSL_CTX_SET_CIPHERSUITES 1" >>confdefs.h
+
+fi
+
+fi
+
+ LIBS="$OLIBS"
+ elif test "${enable_wolfssl-no}" != no; then
+ # Check for OpenSSL compatibility functions in wolfSSL.
+ # Use pkg-config to find the wolfssl cflags and libs if possible.
+ if test "$enable_wolfssl" != "yes"; then
+ PKG_CONFIG_LIBDIR="${enable_wolfssl}/lib/pkgconfig:${enable_wolfssl}/lib64/pkgconfig:${enable_wolfssl}/share/pkgconfig"
+ export PKG_CONFIG_LIBDIR
+ elif test "$cross_compiling" = "yes" -a -z "$PKG_CONFIG"; then
+ # Cannot use pkg-config when cross-compiling
+ PKG_CONFIG=false
+ fi
+ : ${PKG_CONFIG='pkg-config'}
+ if $PKG_CONFIG --exists wolfssl >/dev/null 2>&1; then
+ printf "%s\n" "#define HAVE_OPENSSL 1" >>confdefs.h
+
+ printf "%s\n" "#define HAVE_WOLFSSL 1" >>confdefs.h
+
+
+ O_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS `$PKG_CONFIG --cflags-only-I wolfssl`"
+ O_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS `$PKG_CONFIG --libs-only-L wolfssl`"
+
+ # Check whether --static is needed
+ libssl="`$PKG_CONFIG --libs-only-l wolfssl | sed 's/^ *-l//'`"
+ libssl_extra=`echo $libssl | sed 's/^[^ ]* *//'`
+ libssl=`echo $libssl | sed 's/ .*//'`
+ as_ac_Lib=`printf "%s\n" "ac_cv_lib_$libssl""_wolfSSL_new$libssl_extra" | sed "$as_sed_sh"`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wolfSSL_new in -l$libssl" >&5
+printf %s "checking for wolfSSL_new in -l$libssl... " >&6; }
+if eval test \${$as_ac_Lib+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-l$libssl $libssl_extra $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char wolfSSL_new (void);
+int
+main (void)
+{
+return wolfSSL_new ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ eval "$as_ac_Lib=yes"
+else case e in #(
+ e) eval "$as_ac_Lib=no" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+eval ac_res=\$$as_ac_Lib
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"
+then :
+ STATIC=""
+else case e in #(
+ e) STATIC="--static" ;;
+esac
+fi
+
+
+ # Use wolfSSL's sha2 functions if possible
+ ac_fn_check_decl "$LINENO" "EVP_MD_CTX_new" "ac_cv_have_decl_EVP_MD_CTX_new" "
+ $ac_includes_default
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/evp.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_EVP_MD_CTX_new" = xyes
+then :
+ DIGEST=digest_openssl.lo
+fi
+ CPPFLAGS="$O_CPPFLAGS"
+ LDFLAGS="$O_LDFLAGS"
+
+ # Use pkg-config to determine wolfSSL libs and cflags
+ for f in `$PKG_CONFIG $STATIC --libs wolfssl`; do
+ case "$f" in
+ -L*)
+ f="${f#-L}"
+
+
+if test ${LIBTLS+y}
+then :
+
+ case " $LIBTLS " in #(
+ *" -L$f "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS already contains -L\$f"; } >&5
+ (: LIBTLS already contains -L$f) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LIBTLS " -L$f"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS=\"\$LIBTLS\""; } >&5
+ (: LIBTLS="$LIBTLS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LIBTLS=-L$f
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS=\"\$LIBTLS\""; } >&5
+ (: LIBTLS="$LIBTLS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${LIBTLS_R+y}
+then :
+
+ case " $LIBTLS_R " in #(
+ *" -R$f "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS_R already contains -R\$f"; } >&5
+ (: LIBTLS_R already contains -R$f) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LIBTLS_R " -R$f"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS_R=\"\$LIBTLS_R\""; } >&5
+ (: LIBTLS_R="$LIBTLS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LIBTLS_R=-R$f
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS_R=\"\$LIBTLS_R\""; } >&5
+ (: LIBTLS_R="$LIBTLS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+ ;;
+ *)
+
+if test ${LIBTLS+y}
+then :
+
+ case " $LIBTLS " in #(
+ *" $f "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS already contains \$f"; } >&5
+ (: LIBTLS already contains $f) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LIBTLS " $f"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS=\"\$LIBTLS\""; } >&5
+ (: LIBTLS="$LIBTLS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LIBTLS=$f
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS=\"\$LIBTLS\""; } >&5
+ (: LIBTLS="$LIBTLS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ ;;
+ esac
+ done
+ # No separate pkg config for libcrypto
+ LIBCRYPTO="$LIBTLS"
+ LIBCRYPTO_R="$LIBTLS_R"
+ for f in `$PKG_CONFIG --cflags-only-I wolfssl`; do
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" $f "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains \$f"; } >&5
+ (: CPPFLAGS already contains $f) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " $f"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=$f
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ # So we find the openssl compat headers under wolfssl
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" $f/wolfssl "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains \$f/wolfssl"; } >&5
+ (: CPPFLAGS already contains $f/wolfssl) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " $f/wolfssl"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=$f/wolfssl
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ done
+ if test "$CPPFLAGS" = "$O_CPPFLAGS"; then
+ # So we find the openssl compat headers under wolfssl (XXX)
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -I/usr/include/wolfssl "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -I/usr/include/wolfssl"; } >&5
+ (: CPPFLAGS already contains -I/usr/include/wolfssl) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -I/usr/include/wolfssl"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-I/usr/include/wolfssl
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+ else
+ printf "%s\n" "#define HAVE_OPENSSL 1" >>confdefs.h
+
+ printf "%s\n" "#define HAVE_WOLFSSL 1" >>confdefs.h
+
+
+ # No pkg-config file present, try to do it manually
+ if test "$enable_wolfssl" != "yes"; then
+
+
+if test ${LIBCRYPTO+y}
+then :
+
+ case " $LIBCRYPTO " in #(
+ *" -L${enable_wolfssl}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO already contains -L\${enable_wolfssl}/lib"; } >&5
+ (: LIBCRYPTO already contains -L${enable_wolfssl}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LIBCRYPTO " -L${enable_wolfssl}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO=\"\$LIBCRYPTO\""; } >&5
+ (: LIBCRYPTO="$LIBCRYPTO") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LIBCRYPTO=-L${enable_wolfssl}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO=\"\$LIBCRYPTO\""; } >&5
+ (: LIBCRYPTO="$LIBCRYPTO") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${LIBCRYPTO_R+y}
+then :
+
+ case " $LIBCRYPTO_R " in #(
+ *" -R${enable_wolfssl}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO_R already contains -R\${enable_wolfssl}/lib"; } >&5
+ (: LIBCRYPTO_R already contains -R${enable_wolfssl}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LIBCRYPTO_R " -R${enable_wolfssl}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO_R=\"\$LIBCRYPTO_R\""; } >&5
+ (: LIBCRYPTO_R="$LIBCRYPTO_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LIBCRYPTO_R=-R${enable_wolfssl}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBCRYPTO_R=\"\$LIBCRYPTO_R\""; } >&5
+ (: LIBCRYPTO_R="$LIBCRYPTO_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+
+
+if test ${LIBTLS+y}
+then :
+
+ case " $LIBTLS " in #(
+ *" -L${enable_wolfssl}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS already contains -L\${enable_wolfssl}/lib"; } >&5
+ (: LIBTLS already contains -L${enable_wolfssl}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LIBTLS " -L${enable_wolfssl}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS=\"\$LIBTLS\""; } >&5
+ (: LIBTLS="$LIBTLS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LIBTLS=-L${enable_wolfssl}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS=\"\$LIBTLS\""; } >&5
+ (: LIBTLS="$LIBTLS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${LIBTLS_R+y}
+then :
+
+ case " $LIBTLS_R " in #(
+ *" -R${enable_wolfssl}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS_R already contains -R\${enable_wolfssl}/lib"; } >&5
+ (: LIBTLS_R already contains -R${enable_wolfssl}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LIBTLS_R " -R${enable_wolfssl}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS_R=\"\$LIBTLS_R\""; } >&5
+ (: LIBTLS_R="$LIBTLS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LIBTLS_R=-R${enable_wolfssl}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBTLS_R=\"\$LIBTLS_R\""; } >&5
+ (: LIBTLS_R="$LIBTLS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -I${enable_wolfssl}/include "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -I\${enable_wolfssl}/include"; } >&5
+ (: CPPFLAGS already contains -I${enable_wolfssl}/include) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -I${enable_wolfssl}/include"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-I${enable_wolfssl}/include
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ # So we find the openssl compat headers under wolfssl
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -I${enable_wolfssl}/include/wolfssl "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -I\${enable_wolfssl}/include/wolfssl"; } >&5
+ (: CPPFLAGS already contains -I${enable_wolfssl}/include/wolfssl) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -I${enable_wolfssl}/include/wolfssl"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-I${enable_wolfssl}/include/wolfssl
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ else
+ # So we find the openssl compat headers under wolfssl (XXX)
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -I/usr/include/wolfssl "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -I/usr/include/wolfssl"; } >&5
+ (: CPPFLAGS already contains -I/usr/include/wolfssl) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -I/usr/include/wolfssl"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-I/usr/include/wolfssl
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+ LIBTLS="${LIBTLS} -lwolfssl"
+ LIBCRYPTO="${LIBCRYPTO} -lwolfssl"
+
+ # Use wolfSSL's sha2 functions if possible
+ ac_fn_check_decl "$LINENO" "EVP_MD_CTX_new" "ac_cv_have_decl_EVP_MD_CTX_new" "
+ $ac_includes_default
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/evp.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_EVP_MD_CTX_new" = xyes
+then :
+ DIGEST=digest_openssl.lo
+fi
+ fi
+ ac_fn_check_decl "$LINENO" "X509_STORE_CTX_get0_cert" "ac_cv_have_decl_X509_STORE_CTX_get0_cert" "
+ $ac_includes_default
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/x509.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_X509_STORE_CTX_get0_cert" = xyes
+then :
+ printf "%s\n" "#define HAVE_X509_STORE_CTX_GET0_CERT 1" >>confdefs.h
+
+fi
+ ac_fn_check_decl "$LINENO" "ASN1_STRING_get0_data" "ac_cv_have_decl_ASN1_STRING_get0_data" "
+ $ac_includes_default
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/asn1.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_ASN1_STRING_get0_data" = xyes
+then :
+ printf "%s\n" "#define HAVE_ASN1_STRING_GET0_DATA 1" >>confdefs.h
+
+fi
+ ac_fn_check_decl "$LINENO" "SSL_CTX_get0_certificate" "ac_cv_have_decl_SSL_CTX_get0_certificate" "
+ $ac_includes_default
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/ssl.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SSL_CTX_get0_certificate" = xyes
+then :
+ printf "%s\n" "#define HAVE_SSL_CTX_GET0_CERTIFICATE 1" >>confdefs.h
+
+fi
+ ac_fn_check_decl "$LINENO" "SSL_CTX_set0_tmp_dh_pkey" "ac_cv_have_decl_SSL_CTX_set0_tmp_dh_pkey" "
+ $ac_includes_default
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/ssl.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SSL_CTX_set0_tmp_dh_pkey" = xyes
+then :
+ printf "%s\n" "#define HAVE_SSL_CTX_SET0_TMP_DH_PKEY 1" >>confdefs.h
+
+fi
+ ac_fn_check_decl "$LINENO" "TLS_method" "ac_cv_have_decl_TLS_method" "
+ $ac_includes_default
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/ssl.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_TLS_method" = xyes
+then :
+ printf "%s\n" "#define HAVE_TLS_METHOD 1" >>confdefs.h
+
+fi
+ ac_fn_check_decl "$LINENO" "SSL_CTX_set_min_proto_version" "ac_cv_have_decl_SSL_CTX_set_min_proto_version" "
+ $ac_includes_default
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/ssl.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SSL_CTX_set_min_proto_version" = xyes
+then :
+ printf "%s\n" "#define HAVE_SSL_CTX_SET_MIN_PROTO_VERSION 1" >>confdefs.h
+
+fi
+ ac_fn_check_decl "$LINENO" "SSL_CTX_set_ciphersuites" "ac_cv_have_decl_SSL_CTX_set_ciphersuites" "
+ $ac_includes_default
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/ssl.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SSL_CTX_set_ciphersuites" = xyes
+then :
+ printf "%s\n" "#define HAVE_SSL_CTX_SET_CIPHERSUITES 1" >>confdefs.h
+
+fi
+ ac_fn_check_decl "$LINENO" "SSL_read_ex" "ac_cv_have_decl_SSL_read_ex" "
+ $ac_includes_default
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/ssl.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SSL_read_ex" = xyes
+then :
+ printf "%s\n" "#define HAVE_SSL_READ_EX 1" >>confdefs.h
+
+else case e in #(
+ e)
+ SSL_COMPAT_SRC=lib/ssl_compat
+ ;;
+esac
+fi
+ fi
+ if test -n "$SSL_COMPAT_SRC"; then
+ LIBTLS='$(top_builddir)/lib/ssl_compat/libssl_compat.la '"${LIBTLS}"
+ fi
+
+
+if test "$DIGEST" = "digest.lo"
+then :
+
+ if test "${enable_gcrypt-no}" != no
+then :
+
+ # Use gcrypt's sha2 functions
+ printf "%s\n" "#define HAVE_GCRYPT 1" >>confdefs.h
+
+ DIGEST=digest_gcrypt.lo
+ LIBCRYPTO="-lgcrypt"
+ if test "$enable_gcrypt" != "yes"
+then :
+
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -I${enable_gcrypt}/include "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -I\${enable_gcrypt}/include"; } >&5
+ (: CPPFLAGS already contains -I${enable_gcrypt}/include) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -I${enable_gcrypt}/include"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-I${enable_gcrypt}/include
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+
+if test ${LDFLAGS+y}
+then :
+
+ case " $LDFLAGS " in #(
+ *" -L${enable_gcrypt}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS already contains -L\${enable_gcrypt}/lib"; } >&5
+ (: LDFLAGS already contains -L${enable_gcrypt}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LDFLAGS " -L${enable_gcrypt}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS\""; } >&5
+ (: LDFLAGS="$LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LDFLAGS=-L${enable_gcrypt}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS\""; } >&5
+ (: LDFLAGS="$LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${LDFLAGS_R+y}
+then :
+
+ case " $LDFLAGS_R " in #(
+ *" -R${enable_gcrypt}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS_R already contains -R\${enable_gcrypt}/lib"; } >&5
+ (: LDFLAGS_R already contains -R${enable_gcrypt}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LDFLAGS_R " -R${enable_gcrypt}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS_R=\"\$LDFLAGS_R\""; } >&5
+ (: LDFLAGS_R="$LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LDFLAGS_R=-R${enable_gcrypt}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS_R=\"\$LDFLAGS_R\""; } >&5
+ (: LDFLAGS_R="$LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+
+fi
+
+else case e in #(
+ e)
+ # Use sudo's sha2 functions if not in libmd or libc.
+ FOUND_SHA2=no
+ ac_fn_c_check_header_compile "$LINENO" "sha2.h" "ac_cv_header_sha2_h" "$ac_includes_default"
+if test "x$ac_cv_header_sha2_h" = xyes
+then :
+
+ FOUND_SHA2=yes
+
+ for ac_func in SHA224Update
+do :
+ ac_fn_c_check_func "$LINENO" "SHA224Update" "ac_cv_func_SHA224Update"
+if test "x$ac_cv_func_SHA224Update" = xyes
+then :
+ printf "%s\n" "#define HAVE_SHA224UPDATE 1" >>confdefs.h
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the data argument of SHA224Update() is void *" >&5
+printf %s "checking whether the data argument of SHA224Update() is void *... " >&6; }
+if test ${sudo_cv_func_sha2_void_ptr+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+#include <sha2.h>
+void SHA224Update(SHA2_CTX *context, const void *data, size_t len) {return;}
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ sudo_cv_func_sha2_void_ptr=yes
+else case e in #(
+ e) sudo_cv_func_sha2_void_ptr=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_func_sha2_void_ptr" >&5
+printf "%s\n" "$sudo_cv_func_sha2_void_ptr" >&6; }
+ if test $sudo_cv_func_sha2_void_ptr = yes; then
+
+printf "%s\n" "#define SHA2_VOID_PTR 1" >>confdefs.h
+
+ fi
+
+else case e in #(
+ e)
+ # On some systems, SHA224Update is in libmd
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SHA224Update in -lmd" >&5
+printf %s "checking for SHA224Update in -lmd... " >&6; }
+if test ${ac_cv_lib_md_SHA224Update+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lmd $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char SHA224Update (void);
+int
+main (void)
+{
+return SHA224Update ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_md_SHA224Update=yes
+else case e in #(
+ e) ac_cv_lib_md_SHA224Update=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_md_SHA224Update" >&5
+printf "%s\n" "$ac_cv_lib_md_SHA224Update" >&6; }
+if test "x$ac_cv_lib_md_SHA224Update" = xyes
+then :
+
+ printf "%s\n" "#define HAVE_SHA224UPDATE 1" >>confdefs.h
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the data argument of SHA224Update() is void *" >&5
+printf %s "checking whether the data argument of SHA224Update() is void *... " >&6; }
+if test ${sudo_cv_func_sha2_void_ptr+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+#include <sha2.h>
+void SHA224Update(SHA2_CTX *context, const void *data, size_t len) {return;}
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ sudo_cv_func_sha2_void_ptr=yes
+else case e in #(
+ e) sudo_cv_func_sha2_void_ptr=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_func_sha2_void_ptr" >&5
+printf "%s\n" "$sudo_cv_func_sha2_void_ptr" >&6; }
+ if test $sudo_cv_func_sha2_void_ptr = yes; then
+
+printf "%s\n" "#define SHA2_VOID_PTR 1" >>confdefs.h
+
+ fi
+
+ LIBCRYPTO="-lmd"
+
+else case e in #(
+ e)
+ # Does not have SHA224Update
+ FOUND_SHA2=no
+ ;;
+esac
+fi
+
+ ;;
+esac
+fi
+
+done
+
+fi
+
+ if test X"$FOUND_SHA2" = X"no"
+then :
+
+ case " $LIBOBJS " in
+ *" sha2.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS sha2.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_SHA224Final sudo_SHA224Init sudo_SHA224Pad sudo_SHA224Transform sudo_SHA224Update sudo_SHA256Final sudo_SHA256Init sudo_SHA256Pad sudo_SHA256Transform sudo_SHA256Update sudo_SHA384Final sudo_SHA384Init sudo_SHA384Pad sudo_SHA384Transform sudo_SHA384Update sudo_SHA512Final sudo_SHA512Init sudo_SHA512Pad sudo_SHA512Transform sudo_SHA512Update; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+
+fi
+ ;;
+esac
+fi
+
+fi
+
+
+ _LIBS="$LIBS"
+ LIBS="${LIBS} ${NET_LIBS}"
+ found=true
+ ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket"
+if test "x$ac_cv_func_socket" = xyes
+then :
+
+else case e in #(
+ e)
+ # Look for socket in network libraries appending to NET_LIBS as needed.
+ # May need to link with -lnsl and -lsocket due to unresolved symbols
+ found=false
+ for libs in "-lsocket" "-linet" "-lsocket -lnsl" "-lresolv"; do
+ _libs=
+ for lib in $libs; do
+ case "$NET_LIBS" in
+ *"$lib"*) ;;
+ *) _libs="$_libs $lib";;
+ esac
+ done
+ libs="${_libs# }"
+ test -z "$libs" && continue
+ lib="`echo \"$libs\"|sed -e 's/^-l//' -e 's/ .*$//'`"
+ extralibs="`echo \"$libs\"|sed 's/^-l[^ ]*//'`"
+
+ _sudo_check_lib_extras=`echo "$extralibs"|sed -e 's/ *//g' -e 's/-l/_/g'`
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for socket in -l$lib${5+ }$extralibs" >&5
+printf %s "checking for socket in -l$lib${5+ }$extralibs... " >&6; }
+ if { as_var=sudo_cv_lib_$lib''_socket$_sudo_check_lib_extras; eval test \${$as_var+y}; }
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ SUDO_CHECK_LIB_OLIBS="$LIBS"
+ LIBS="$LIBS -l$lib${5+ }$extralibs"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char socket (void);
+int
+main (void)
+{
+return socket ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ eval sudo_cv_lib_$lib''_socket$_sudo_check_lib_extras=yes
+else case e in #(
+ e) eval sudo_cv_lib_$lib''_socket$_sudo_check_lib_extras=no
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS="$SUDO_CHECK_LIB_OLIBS"
+ ;;
+esac
+fi
+
+ if eval test \$sudo_cv_lib_$lib''_socket$_sudo_check_lib_extras = "yes"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+ found=true
+ NET_LIBS="${NET_LIBS}${NET_LIBS+ }$libs"
+ INET_PTON_LIBS="$libs"
+ case "$libs" in
+ *-lresolv*)
+ printf "%s\n" "#define NEED_RESOLV_H 1" >>confdefs.h
+
+ ;;
+ esac
+ break
+
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+ fi
+
+ done
+ ;;
+esac
+fi
+
+ LIBS="$_LIBS"
+ if test $found = true
+then :
+
+fi
+
+
+ONET_LIBS="$NET_LIBS"
+
+ _LIBS="$LIBS"
+ LIBS="${LIBS} ${NET_LIBS}"
+ found=true
+ ac_fn_c_check_func "$LINENO" "inet_pton" "ac_cv_func_inet_pton"
+if test "x$ac_cv_func_inet_pton" = xyes
+then :
+
+ printf "%s\n" "#define HAVE_INET_PTON 1" >>confdefs.h
+
+ INET_PTON_LIBS=
+ for lib in $NET_LIBS; do
+ case "$ONET_LIBS" in
+ *"$lib"*) ;;
+ *) INET_PTON_LIBS="${INET_PTON_LIBS}${INET_PTON_LIBS+ }$lib";;
+ esac
+ done
+
+else case e in #(
+ e)
+ # Look for inet_pton in network libraries appending to NET_LIBS as needed.
+ # May need to link with -lnsl and -lsocket due to unresolved symbols
+ found=false
+ for libs in "-lsocket" "-linet" "-lsocket -lnsl" "-lresolv"; do
+ _libs=
+ for lib in $libs; do
+ case "$NET_LIBS" in
+ *"$lib"*) ;;
+ *) _libs="$_libs $lib";;
+ esac
+ done
+ libs="${_libs# }"
+ test -z "$libs" && continue
+ lib="`echo \"$libs\"|sed -e 's/^-l//' -e 's/ .*$//'`"
+ extralibs="`echo \"$libs\"|sed 's/^-l[^ ]*//'`"
+
+ _sudo_check_lib_extras=`echo "$extralibs"|sed -e 's/ *//g' -e 's/-l/_/g'`
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inet_pton in -l$lib${5+ }$extralibs" >&5
+printf %s "checking for inet_pton in -l$lib${5+ }$extralibs... " >&6; }
+ if { as_var=sudo_cv_lib_$lib''_inet_pton$_sudo_check_lib_extras; eval test \${$as_var+y}; }
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ SUDO_CHECK_LIB_OLIBS="$LIBS"
+ LIBS="$LIBS -l$lib${5+ }$extralibs"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char inet_pton (void);
+int
+main (void)
+{
+return inet_pton ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ eval sudo_cv_lib_$lib''_inet_pton$_sudo_check_lib_extras=yes
+else case e in #(
+ e) eval sudo_cv_lib_$lib''_inet_pton$_sudo_check_lib_extras=no
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS="$SUDO_CHECK_LIB_OLIBS"
+ ;;
+esac
+fi
+
+ if eval test \$sudo_cv_lib_$lib''_inet_pton$_sudo_check_lib_extras = "yes"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+ found=true
+ NET_LIBS="${NET_LIBS}${NET_LIBS+ }$libs"
+ INET_PTON_LIBS="$libs"
+ case "$libs" in
+ *-lresolv*)
+ printf "%s\n" "#define NEED_RESOLV_H 1" >>confdefs.h
+
+ ;;
+ esac
+ break
+
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+ fi
+
+ done
+ ;;
+esac
+fi
+
+ LIBS="$_LIBS"
+ if test $found = true
+then :
+
+ printf "%s\n" "#define HAVE_INET_PTON 1" >>confdefs.h
+
+ INET_PTON_LIBS=
+ for lib in $NET_LIBS; do
+ case "$ONET_LIBS" in
+ *"$lib"*) ;;
+ *) INET_PTON_LIBS="${INET_PTON_LIBS}${INET_PTON_LIBS+ }$lib";;
+ esac
+ done
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" inet_pton.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS inet_pton.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_inet_pton; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+
+
+ _LIBS="$LIBS"
+ LIBS="${LIBS} ${NET_LIBS}"
+ found=true
+ ac_fn_c_check_func "$LINENO" "inet_ntop" "ac_cv_func_inet_ntop"
+if test "x$ac_cv_func_inet_ntop" = xyes
+then :
+
+ printf "%s\n" "#define HAVE_INET_NTOP 1" >>confdefs.h
+
+
+else case e in #(
+ e)
+ # Look for inet_ntop in network libraries appending to NET_LIBS as needed.
+ # May need to link with -lnsl and -lsocket due to unresolved symbols
+ found=false
+ for libs in "-lsocket" "-linet" "-lsocket -lnsl" "-lresolv"; do
+ _libs=
+ for lib in $libs; do
+ case "$NET_LIBS" in
+ *"$lib"*) ;;
+ *) _libs="$_libs $lib";;
+ esac
+ done
+ libs="${_libs# }"
+ test -z "$libs" && continue
+ lib="`echo \"$libs\"|sed -e 's/^-l//' -e 's/ .*$//'`"
+ extralibs="`echo \"$libs\"|sed 's/^-l[^ ]*//'`"
+
+ _sudo_check_lib_extras=`echo "$extralibs"|sed -e 's/ *//g' -e 's/-l/_/g'`
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inet_ntop in -l$lib${5+ }$extralibs" >&5
+printf %s "checking for inet_ntop in -l$lib${5+ }$extralibs... " >&6; }
+ if { as_var=sudo_cv_lib_$lib''_inet_ntop$_sudo_check_lib_extras; eval test \${$as_var+y}; }
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ SUDO_CHECK_LIB_OLIBS="$LIBS"
+ LIBS="$LIBS -l$lib${5+ }$extralibs"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char inet_ntop (void);
+int
+main (void)
+{
+return inet_ntop ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ eval sudo_cv_lib_$lib''_inet_ntop$_sudo_check_lib_extras=yes
+else case e in #(
+ e) eval sudo_cv_lib_$lib''_inet_ntop$_sudo_check_lib_extras=no
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS="$SUDO_CHECK_LIB_OLIBS"
+ ;;
+esac
+fi
+
+ if eval test \$sudo_cv_lib_$lib''_inet_ntop$_sudo_check_lib_extras = "yes"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+ found=true
+ NET_LIBS="${NET_LIBS}${NET_LIBS+ }$libs"
+ INET_PTON_LIBS="$libs"
+ case "$libs" in
+ *-lresolv*)
+ printf "%s\n" "#define NEED_RESOLV_H 1" >>confdefs.h
+
+ ;;
+ esac
+ break
+
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+ fi
+
+ done
+ ;;
+esac
+fi
+
+ LIBS="$_LIBS"
+ if test $found = true
+then :
+
+ printf "%s\n" "#define HAVE_INET_NTOP 1" >>confdefs.h
+
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" inet_ntop.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS inet_ntop.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_inet_ntop; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+
+
+ _LIBS="$LIBS"
+ LIBS="${LIBS} ${NET_LIBS}"
+ found=true
+ ac_fn_c_check_func "$LINENO" "syslog" "ac_cv_func_syslog"
+if test "x$ac_cv_func_syslog" = xyes
+then :
+
+else case e in #(
+ e)
+ # Look for syslog in network libraries appending to NET_LIBS as needed.
+ # May need to link with -lnsl and -lsocket due to unresolved symbols
+ found=false
+ for libs in "-lsocket" "-linet" "-lsocket -lnsl" "-lresolv"; do
+ _libs=
+ for lib in $libs; do
+ case "$NET_LIBS" in
+ *"$lib"*) ;;
+ *) _libs="$_libs $lib";;
+ esac
+ done
+ libs="${_libs# }"
+ test -z "$libs" && continue
+ lib="`echo \"$libs\"|sed -e 's/^-l//' -e 's/ .*$//'`"
+ extralibs="`echo \"$libs\"|sed 's/^-l[^ ]*//'`"
+
+ _sudo_check_lib_extras=`echo "$extralibs"|sed -e 's/ *//g' -e 's/-l/_/g'`
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for syslog in -l$lib${5+ }$extralibs" >&5
+printf %s "checking for syslog in -l$lib${5+ }$extralibs... " >&6; }
+ if { as_var=sudo_cv_lib_$lib''_syslog$_sudo_check_lib_extras; eval test \${$as_var+y}; }
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ SUDO_CHECK_LIB_OLIBS="$LIBS"
+ LIBS="$LIBS -l$lib${5+ }$extralibs"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char syslog (void);
+int
+main (void)
+{
+return syslog ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ eval sudo_cv_lib_$lib''_syslog$_sudo_check_lib_extras=yes
+else case e in #(
+ e) eval sudo_cv_lib_$lib''_syslog$_sudo_check_lib_extras=no
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS="$SUDO_CHECK_LIB_OLIBS"
+ ;;
+esac
+fi
+
+ if eval test \$sudo_cv_lib_$lib''_syslog$_sudo_check_lib_extras = "yes"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+ found=true
+ NET_LIBS="${NET_LIBS}${NET_LIBS+ }$libs"
+ INET_PTON_LIBS="$libs"
+ case "$libs" in
+ *-lresolv*)
+ printf "%s\n" "#define NEED_RESOLV_H 1" >>confdefs.h
+
+ ;;
+ esac
+ break
+
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+ fi
+
+ done
+ ;;
+esac
+fi
+
+ LIBS="$_LIBS"
+ if test $found = true
+then :
+
+fi
+
+
+OLIBS="$LIBS"
+GETADDRINFO_LIBS=
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo" >&5
+printf %s "checking for getaddrinfo... " >&6; }
+if test ${ax_cv_func_getaddrinfo+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+int main() { return getaddrinfo(0, 0, 0, 0); }
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_func_getaddrinfo=yes
+else case e in #(
+ e) ax_cv_func_getaddrinfo=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext ;;
+esac
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_func_getaddrinfo" >&5
+printf "%s\n" "$ax_cv_func_getaddrinfo" >&6; }
+if test X"$ax_cv_func_getaddrinfo" = X"yes"; then
+
+printf "%s\n" "#define HAVE_GETADDRINFO 1" >>confdefs.h
+
+else
+ # Not found in libc, check libsocket and libinet
+ _found=no
+ for _libs in "-lsocket" "-linet" "-lsocket -lnsl"; do
+ _cv="ax_cv_lib_getaddrinfo`echo \"$_libs\"|sed -e 's/-l/_/g' -e 's/ *//g'`"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo in $_libs" >&5
+printf %s "checking for getaddrinfo in $_libs... " >&6; }
+ if eval test \${$_cv+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ _nlibs=
+ for _l in $_libs; do
+ case "$LIBS" in
+ *"$_l"*) ;;
+ *) _nlibs="$_nlibs $_l";;
+ esac
+ done
+ _libs="${_nlibs# }"
+ if test -z "$_libs"; then
+ # No new libs to check
+ eval $_cv=no
+ else
+ AX_FUNC_GETADDRINFO_OLIBS="$LIBS"
+ LIBS="$LIBS $_libs"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ int main() { return getaddrinfo(0, 0, 0, 0); }
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ eval $_cv=yes
+else case e in #(
+ e) eval $_cv=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS="$AX_FUNC_GETADDRINFO_OLIBS"
+ fi
+ ;;
+esac
+fi
+
+ if eval test \$$_cv = "yes"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ printf "%s\n" "#define HAVE_GETADDRINFO 1" >>confdefs.h
+
+ test -n "$_libs" && LIBS="$LIBS $_libs"
+ break
+ fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ done
+ if eval test \$$_cv != "yes"; then
+ case " $LIBOBJS " in
+ *" getaddrinfo.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS getaddrinfo.$ac_objext"
+ ;;
+esac
+
+ fi
+fi
+
+case " $LIBOBJS " in
+ *" getaddrinfo.$ac_objext "* )
+
+ for _sym in sudo_getaddrinfo sudo_freeaddrinfo sudo_gai_strerror; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ # We need libsudo_util to pull in dependent libraries for
+ # inet_pton(), gethostbyname(), and getservbyname()
+ if test -n "${INET_PTON_LIBS}"
+then :
+
+ LT_DEP_LIBS="${LT_DEP_LIBS}${LT_DEP_LIBS+ }${INET_PTON_LIBS}"
+ LIBS="${LIBS}${LIBS+ }${INET_PTON_LIBS}"
+
+fi
+
+ _LIBS="$LIBS"
+ LIBS="${LIBS} ${NET_LIBS}"
+ found=true
+ ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname"
+if test "x$ac_cv_func_gethostbyname" = xyes
+then :
+
+else case e in #(
+ e)
+ # Look for gethostbyname in network libraries appending to NET_LIBS as needed.
+ # May need to link with -lnsl and -lsocket due to unresolved symbols
+ found=false
+ for libs in "-lsocket" "-linet" "-lsocket -lnsl" "-lresolv"; do
+ _libs=
+ for lib in $libs; do
+ case "$NET_LIBS" in
+ *"$lib"*) ;;
+ *) _libs="$_libs $lib";;
+ esac
+ done
+ libs="${_libs# }"
+ test -z "$libs" && continue
+ lib="`echo \"$libs\"|sed -e 's/^-l//' -e 's/ .*$//'`"
+ extralibs="`echo \"$libs\"|sed 's/^-l[^ ]*//'`"
+
+ _sudo_check_lib_extras=`echo "$extralibs"|sed -e 's/ *//g' -e 's/-l/_/g'`
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -l$lib${5+ }$extralibs" >&5
+printf %s "checking for gethostbyname in -l$lib${5+ }$extralibs... " >&6; }
+ if { as_var=sudo_cv_lib_$lib''_gethostbyname$_sudo_check_lib_extras; eval test \${$as_var+y}; }
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ SUDO_CHECK_LIB_OLIBS="$LIBS"
+ LIBS="$LIBS -l$lib${5+ }$extralibs"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname (void);
+int
+main (void)
+{
+return gethostbyname ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ eval sudo_cv_lib_$lib''_gethostbyname$_sudo_check_lib_extras=yes
+else case e in #(
+ e) eval sudo_cv_lib_$lib''_gethostbyname$_sudo_check_lib_extras=no
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS="$SUDO_CHECK_LIB_OLIBS"
+ ;;
+esac
+fi
+
+ if eval test \$sudo_cv_lib_$lib''_gethostbyname$_sudo_check_lib_extras = "yes"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+ found=true
+ NET_LIBS="${NET_LIBS}${NET_LIBS+ }$libs"
+ INET_PTON_LIBS="$libs"
+ case "$libs" in
+ *-lresolv*)
+ printf "%s\n" "#define NEED_RESOLV_H 1" >>confdefs.h
+
+ ;;
+ esac
+ break
+
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+ fi
+
+ done
+ ;;
+esac
+fi
+
+ LIBS="$_LIBS"
+ if test $found = true
+then :
+
+fi
+
+ ;;
+ *)
+ for lib in $LIBS; do
+ case "$OLIBS" in
+ *"$lib"*) ;;
+ *) GETADDRINFO_LIBS="${GETADDRINFO_LIBS}${GETADDRINFO_LIBS+ }$lib";;
+ esac
+ done
+ if test -n "${GETADDRINFO_LIBS}"
+then :
+
+ # We need libsudo_util to pull in dependent libraries for
+ # gai_strerror()
+ LT_DEP_LIBS="${LT_DEP_LIBS}${LT_DEP_LIBS+ }${GETADDRINFO_LIBS}"
+ LIBS="${LIBS}${LIBS+ }${GETADDRINFO_LIBS}"
+
+ # Add to NET_LIBS if necessary
+ for lib in $GETADDRINFO_LIBS; do
+ case "$NET_LIBS" in
+ *"$lib"*) ;;
+ *) NET_LIBS="${NET_LIBS}${NET_LIBS+ }$lib";;
+ esac
+ done
+
+fi
+ ;;
+esac
+LIBS="$OLIBS"
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for va_copy" >&5
+printf %s "checking for va_copy... " >&6; }
+if test ${sudo_cv_func_va_copy+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+ va_list ap1, ap2;
+int
+main (void)
+{
+va_copy(ap1, ap2);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ sudo_cv_func_va_copy=yes
+else case e in #(
+ e) sudo_cv_func_va_copy=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_func_va_copy" >&5
+printf "%s\n" "$sudo_cv_func_va_copy" >&6; }
+if test "$sudo_cv_func_va_copy" = "yes"
+then :
+
+ printf "%s\n" "#define HAVE_VA_COPY 1" >>confdefs.h
+
+
+else case e in #(
+ e)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __va_copy" >&5
+printf %s "checking for __va_copy... " >&6; }
+if test ${sudo_cv_func___va_copy+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+ va_list ap1, ap2;
+int
+main (void)
+{
+__va_copy(ap1, ap2);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ sudo_cv_func___va_copy=yes
+else case e in #(
+ e) sudo_cv_func___va_copy=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_func___va_copy" >&5
+printf "%s\n" "$sudo_cv_func___va_copy" >&6; }
+ if test "$sudo_cv_func___va_copy" = "yes"
+then :
+
+ printf "%s\n" "#define HAVE___VA_COPY 1" >>confdefs.h
+
+
+fi
+ ;;
+esac
+fi
+
+
+ for ac_func in getprogname
+do :
+ ac_fn_c_check_func "$LINENO" "getprogname" "ac_cv_func_getprogname"
+if test "x$ac_cv_func_getprogname" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETPROGNAME 1" >>confdefs.h
+
+
+ for ac_func in setprogname
+do :
+ ac_fn_c_check_func "$LINENO" "setprogname" "ac_cv_func_setprogname"
+if test "x$ac_cv_func_setprogname" = xyes
+then :
+ printf "%s\n" "#define HAVE_SETPROGNAME 1" >>confdefs.h
+
+else case e in #(
+ e)
+ for _sym in sudo_setprogname; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+ ;;
+esac
+fi
+
+done
+
+else case e in #(
+ e)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __progname" >&5
+printf %s "checking for __progname... " >&6; }
+if test ${sudo_cv___progname+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+extern char *__progname; if (__progname[0] == '\0') return 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ sudo_cv___progname=yes
+else case e in #(
+ e) sudo_cv___progname=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv___progname" >&5
+printf "%s\n" "$sudo_cv___progname" >&6; }
+ if test "$sudo_cv___progname" = "yes"
+then :
+
+ printf "%s\n" "#define HAVE___PROGNAME 1" >>confdefs.h
+
+
+fi
+
+ for _sym in sudo_getprogname; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+
+ for _sym in sudo_setprogname; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __func__" >&5
+printf %s "checking for __func__... " >&6; }
+if test ${sudo_cv___func__+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ if test X"$ac_cv_build_prog_cc_c99" = X"no"
+then :
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+if (__func__[0] == '\0') return 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ sudo_cv___func__=yes
+else case e in #(
+ e) sudo_cv___func__=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+
+else case e in #(
+ e)
+ # C99 and higher support __func__
+ sudo_cv___func__=yes
+ ;;
+esac
+fi
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv___func__" >&5
+printf "%s\n" "$sudo_cv___func__" >&6; }
+if test "$sudo_cv___func__" = "yes"
+then :
+
+ printf "%s\n" "#define HAVE___FUNC__ 1" >>confdefs.h
+
+
+elif test -n "$GCC"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __FUNCTION__" >&5
+printf %s "checking for __FUNCTION__... " >&6; }
+if test ${sudo_cv___FUNCTION__+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+if(__FUNCTION__[0] == '\0') return 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ sudo_cv___FUNCTION__=yes
+else case e in #(
+ e) sudo_cv___FUNCTION__=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv___FUNCTION__" >&5
+printf "%s\n" "$sudo_cv___FUNCTION__" >&6; }
+ if test "$sudo_cv___FUNCTION__" = "yes"
+then :
+
+ printf "%s\n" "#define HAVE___FUNC__ 1" >>confdefs.h
+
+
+printf "%s\n" "#define __func__ __FUNCTION__" >>confdefs.h
+
+
+fi
+
+fi
+
+
+ # gettext() and friends may be located in libc (Linux and Solaris)
+ # or in libintl. However, it is possible to have libintl installed
+ # even when gettext() is present in libc. In the case of GNU libintl,
+ # gettext() will be defined to gettext_libintl in libintl.h.
+ # Since gcc prefers /usr/local/include to /usr/include, we need to
+ # make sure we use the gettext() that matches the include file.
+ if test "$enable_nls" != "no"; then
+ if test "$enable_nls" != "yes"; then
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -I${enable_nls}/include "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -I\${enable_nls}/include"; } >&5
+ (: CPPFLAGS already contains -I${enable_nls}/include) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -I${enable_nls}/include"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-I${enable_nls}/include
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+
+if test ${LDFLAGS+y}
+then :
+
+ case " $LDFLAGS " in #(
+ *" -L$enable_nls/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS already contains -L\$enable_nls/lib"; } >&5
+ (: LDFLAGS already contains -L$enable_nls/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LDFLAGS " -L$enable_nls/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS\""; } >&5
+ (: LDFLAGS="$LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LDFLAGS=-L$enable_nls/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS\""; } >&5
+ (: LDFLAGS="$LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${LDFLAGS_R+y}
+then :
+
+ case " $LDFLAGS_R " in #(
+ *" -R$enable_nls/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS_R already contains -R\$enable_nls/lib"; } >&5
+ (: LDFLAGS_R already contains -R$enable_nls/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LDFLAGS_R " -R$enable_nls/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS_R=\"\$LDFLAGS_R\""; } >&5
+ (: LDFLAGS_R="$LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LDFLAGS_R=-R$enable_nls/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS_R=\"\$LDFLAGS_R\""; } >&5
+ (: LDFLAGS_R="$LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+ fi
+ OLIBS="$LIBS"
+ for l in "libc" "-lintl" "-lintl -liconv"; do
+ if test "$l" = "libc"; then
+ # If user specified a dir for libintl ignore libc
+ if test "$enable_nls" != "yes"; then
+ continue
+ fi
+ gettext_name=sudo_cv_gettext
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gettext" >&5
+printf %s "checking for gettext... " >&6; }
+ else
+ LIBS="$OLIBS $l"
+ gettext_name=sudo_cv_gettext"`echo $l|sed -e 's/ //g' -e 's/-/_/g'`"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gettext in $l" >&5
+printf %s "checking for gettext in $l... " >&6; }
+ fi
+ if eval test \${$gettext_name+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <libintl.h>
+int
+main (void)
+{
+(void)gettext((char *)0);
+ ;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ eval $gettext_name=yes
+else case e in #(
+ e) eval $gettext_name=no
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ ;;
+esac
+fi
+
+ eval gettext_result="\$$gettext_name"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $gettext_result" >&5
+printf "%s\n" "$gettext_result" >&6; }
+ if test "$gettext_result" = "yes"; then
+ ac_fn_c_check_func "$LINENO" "ngettext" "ac_cv_func_ngettext"
+if test "x$ac_cv_func_ngettext" = xyes
+then :
+ printf "%s\n" "#define HAVE_NGETTEXT 1" >>confdefs.h
+
+fi
+
+ break
+ fi
+ done
+ LIBS="$OLIBS"
+
+ if test "$sudo_cv_gettext" = "yes"; then
+ SUDO_NLS=enabled
+ # For Solaris we need links from lang to lang.UTF-8 in localedir
+ case "$host_os" in
+ solaris2*) LOCALEDIR_SUFFIX=".UTF-8";;
+ esac
+ elif test "$sudo_cv_gettext_lintl" = "yes"; then
+ SUDO_NLS=enabled
+ LIBINTL="-lintl"
+ elif test "$sudo_cv_gettext_lintl_liconv" = "yes"; then
+ SUDO_NLS=enabled
+ LIBINTL="-lintl -liconv"
+ fi
+ if test X"$SUDO_NLS" = X"enabled"; then
+ printf "%s\n" "#define HAVE_LIBINTL_H 1" >>confdefs.h
+
+
+ for _sym in sudo_warn_gettext_v1; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ fi
+ fi
+
+
+case "$enable_zlib" in
+ yes)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gzclearerr in -lz" >&5
+printf %s "checking for gzclearerr in -lz... " >&6; }
+if test ${ac_cv_lib_z_gzclearerr+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lz $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gzclearerr (void);
+int
+main (void)
+{
+return gzclearerr ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_z_gzclearerr=yes
+else case e in #(
+ e) ac_cv_lib_z_gzclearerr=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_gzclearerr" >&5
+printf "%s\n" "$ac_cv_lib_z_gzclearerr" >&6; }
+if test "x$ac_cv_lib_z_gzclearerr" = xyes
+then :
+
+ for ac_header in zlib.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_zlib_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_ZLIB_H 1" >>confdefs.h
+ ZLIB="-lz"
+else case e in #(
+ e) enable_zlib=builtin ;;
+esac
+fi
+
+done
+
+fi
+
+ ;;
+ no)
+ ;;
+ system)
+ printf "%s\n" "#define HAVE_ZLIB_H 1" >>confdefs.h
+
+ ZLIB="-lz"
+ ;;
+ static|shared|builtin)
+ # handled below
+ ;;
+ *)
+ printf "%s\n" "#define HAVE_ZLIB_H 1" >>confdefs.h
+
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -I${enable_zlib}/include "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -I\${enable_zlib}/include"; } >&5
+ (: CPPFLAGS already contains -I${enable_zlib}/include) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -I${enable_zlib}/include"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-I${enable_zlib}/include
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+
+if test ${ZLIB+y}
+then :
+
+ case " $ZLIB " in #(
+ *" -L$enable_zlib/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ZLIB already contains -L\$enable_zlib/lib"; } >&5
+ (: ZLIB already contains -L$enable_zlib/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append ZLIB " -L$enable_zlib/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ZLIB=\"\$ZLIB\""; } >&5
+ (: ZLIB="$ZLIB") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ ZLIB=-L$enable_zlib/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ZLIB=\"\$ZLIB\""; } >&5
+ (: ZLIB="$ZLIB") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${ZLIB_R+y}
+then :
+
+ case " $ZLIB_R " in #(
+ *" -R$enable_zlib/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ZLIB_R already contains -R\$enable_zlib/lib"; } >&5
+ (: ZLIB_R already contains -R$enable_zlib/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append ZLIB_R " -R$enable_zlib/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ZLIB_R=\"\$ZLIB_R\""; } >&5
+ (: ZLIB_R="$ZLIB_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ ZLIB_R=-R$enable_zlib/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ZLIB_R=\"\$ZLIB_R\""; } >&5
+ (: ZLIB_R="$ZLIB_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+ ZLIB="${ZLIB} -lz"
+ ;;
+esac
+case "$enable_zlib" in
+ builtin|static|dynamic)
+ printf "%s\n" "#define HAVE_ZLIB_H 1" >>confdefs.h
+
+ # XXX - can't use AX_APPEND_FLAG due to use of $(top_foo) and quoting
+ CPPFLAGS='-I$(top_builddir)/lib/zlib -I$(top_srcdir)/lib/zlib '"${CPPFLAGS}"
+ ZLIB="${ZLIB}"' $(top_builddir)/lib/zlib/libsudo_z.la'
+ ZLIB_SRC=lib/zlib
+ ac_config_headers="$ac_config_headers lib/zlib/zconf.h"
+
+ ac_config_files="$ac_config_files lib/zlib/Makefile"
+
+ if test X"$enable_shared" = X"no" -o "$enable_zlib" = "static"
+then :
+
+ if test "$enable_zlib" = "shared"
+then :
+
+ as_fn_error $? "unable to build shared libraries on this system" "$LINENO" 5
+
+fi
+ # Build as convenience library
+ ZLIB_LDFLAGS=-no-install
+
+fi
+ ;;
+esac
+
+ac_fn_check_decl "$LINENO" "NSIG" "ac_cv_have_decl_NSIG" "
+$ac_includes_default
+#include <signal.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_NSIG" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_NSIG $ac_have_decl" >>confdefs.h
+if test $ac_have_decl = 1
+then :
+
+else case e in #(
+ e)
+ ac_fn_check_decl "$LINENO" "_NSIG" "ac_cv_have_decl__NSIG" "
+$ac_includes_default
+#include <signal.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl__NSIG" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL__NSIG $ac_have_decl" >>confdefs.h
+if test $ac_have_decl = 1
+then :
+
+else case e in #(
+ e)
+ ac_fn_check_decl "$LINENO" "__NSIG" "ac_cv_have_decl___NSIG" "
+$ac_includes_default
+#include <signal.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl___NSIG" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL___NSIG $ac_have_decl" >>confdefs.h
+
+ ;;
+esac
+fi
+
+ ;;
+esac
+fi
+
+
+ac_fn_check_decl "$LINENO" "errno" "ac_cv_have_decl_errno" "
+$ac_includes_default
+#include <errno.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_errno" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_ERRNO $ac_have_decl" >>confdefs.h
+
+
+ac_fn_check_decl "$LINENO" "h_errno" "ac_cv_have_decl_h_errno" "
+$ac_includes_default
+#include <netdb.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_h_errno" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_H_ERRNO $ac_have_decl" >>confdefs.h
+
+
+ac_fn_check_decl "$LINENO" "LLONG_MAX" "ac_cv_have_decl_LLONG_MAX" "
+#include <sys/types.h>
+#include <limits.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_LLONG_MAX" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_LLONG_MAX $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "LLONG_MIN" "ac_cv_have_decl_LLONG_MIN" "
+#include <sys/types.h>
+#include <limits.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_LLONG_MIN" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_LLONG_MIN $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "ULLONG_MAX" "ac_cv_have_decl_ULLONG_MAX" "
+#include <sys/types.h>
+#include <limits.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_ULLONG_MAX" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_ULLONG_MAX $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "PATH_MAX" "ac_cv_have_decl_PATH_MAX" "
+#include <sys/types.h>
+#include <limits.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_PATH_MAX" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_PATH_MAX $ac_have_decl" >>confdefs.h
+ac_fn_check_decl "$LINENO" "SSIZE_MAX" "ac_cv_have_decl_SSIZE_MAX" "
+#include <sys/types.h>
+#include <limits.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SSIZE_MAX" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_SSIZE_MAX $ac_have_decl" >>confdefs.h
+
+ac_fn_check_decl "$LINENO" "SIZE_MAX" "ac_cv_have_decl_SIZE_MAX" "
+#include <sys/types.h>
+#include <limits.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SIZE_MAX" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_SIZE_MAX $ac_have_decl" >>confdefs.h
+
+if test "$ac_cv_have_decl_LLONG_MAX" != "yes"
+then :
+
+ ac_fn_check_decl "$LINENO" "QUAD_MAX" "ac_cv_have_decl_QUAD_MAX" "
+#include <sys/types.h>
+#include <limits.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_QUAD_MAX" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_QUAD_MAX $ac_have_decl" >>confdefs.h
+
+
+fi
+if test "$ac_cv_have_decl_LLONG_MIN" != "yes"
+then :
+
+ ac_fn_check_decl "$LINENO" "QUAD_MIN" "ac_cv_have_decl_QUAD_MIN" "
+#include <sys/types.h>
+#include <limits.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_QUAD_MIN" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_QUAD_MIN $ac_have_decl" >>confdefs.h
+
+
+fi
+if test "$ac_cv_have_decl_ULLONG_MAX" != "yes"
+then :
+
+ ac_fn_check_decl "$LINENO" "UQUAD_MAX" "ac_cv_have_decl_UQUAD_MAX" "
+#include <sys/types.h>
+#include <limits.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_UQUAD_MAX" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_UQUAD_MAX $ac_have_decl" >>confdefs.h
+
+
+fi
+if test "$ac_cv_have_decl_SIZE_MAX" != "yes"
+then :
+
+ ac_fn_check_decl "$LINENO" "SIZE_T_MAX" "ac_cv_have_decl_SIZE_T_MAX" "
+#include <sys/types.h>
+#include <limits.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SIZE_T_MAX" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_SIZE_T_MAX $ac_have_decl" >>confdefs.h
+
+
+fi
+if test "$ac_cv_have_decl_PATH_MAX" != "yes"
+then :
+
+ ac_fn_check_decl "$LINENO" "_POSIX_PATH_MAX" "ac_cv_have_decl__POSIX_PATH_MAX" "
+#include <sys/types.h>
+#include <limits.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl__POSIX_PATH_MAX" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL__POSIX_PATH_MAX $ac_have_decl" >>confdefs.h
+
+
+fi
+
+
+ for ac_func in strsignal
+do :
+ ac_fn_c_check_func "$LINENO" "strsignal" "ac_cv_func_strsignal"
+if test "x$ac_cv_func_strsignal" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRSIGNAL 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" strsignal.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strsignal.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_strsignal; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ HAVE_SIGLIST="false"
+ ac_fn_check_decl "$LINENO" "sys_siglist" "ac_cv_have_decl_sys_siglist" "
+$ac_includes_default
+#include <signal.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_sys_siglist" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_SYS_SIGLIST $ac_have_decl" >>confdefs.h
+if test $ac_have_decl = 1
+then :
+ HAVE_SIGLIST="true"
+else case e in #(
+ e)
+ ac_fn_check_decl "$LINENO" "_sys_siglist" "ac_cv_have_decl__sys_siglist" "
+$ac_includes_default
+#include <signal.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl__sys_siglist" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL__SYS_SIGLIST $ac_have_decl" >>confdefs.h
+if test $ac_have_decl = 1
+then :
+ HAVE_SIGLIST="true"
+fi
+
+ ;;
+esac
+fi
+
+ if test "$HAVE_SIGLIST" != "true"
+then :
+
+ case " $LIBOBJS " in
+ *" siglist.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS siglist.$ac_objext"
+ ;;
+esac
+
+
+fi
+ ;;
+esac
+fi
+
+done
+
+
+ for ac_func in sig2str
+do :
+ ac_fn_c_check_func "$LINENO" "sig2str" "ac_cv_func_sig2str"
+if test "x$ac_cv_func_sig2str" = xyes
+then :
+ printf "%s\n" "#define HAVE_SIG2STR 1" >>confdefs.h
+
+ ac_fn_check_decl "$LINENO" "SIG2STR_MAX" "ac_cv_have_decl_SIG2STR_MAX" "
+# include <signal.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_SIG2STR_MAX" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_SIG2STR_MAX $ac_have_decl" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" sig2str.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS sig2str.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_sig2str; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+ for ac_func in str2sig
+do :
+ ac_fn_c_check_func "$LINENO" "str2sig" "ac_cv_func_str2sig"
+if test "x$ac_cv_func_str2sig" = xyes
+then :
+ printf "%s\n" "#define HAVE_STR2SIG 1" >>confdefs.h
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" str2sig.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS str2sig.$ac_objext"
+ ;;
+esac
+
+
+ for _sym in sudo_str2sig; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+
+ ;;
+esac
+fi
+
+done
+
+if test x"${ac_cv_func_sig2str}${ac_cv_func_str2sig}" != x"yesyes"
+then :
+
+ ac_fn_c_check_func "$LINENO" "sigabbrev_np" "ac_cv_func_sigabbrev_np"
+if test "x$ac_cv_func_sigabbrev_np" = xyes
+then :
+ printf "%s\n" "#define HAVE_SIGABBREV_NP 1" >>confdefs.h
+
+fi
+
+ if test x"${ac_cv_func_sigabbrev_np}" != x"yes"
+then :
+
+ COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }strsig_test"
+ HAVE_SIGNAME="false"
+ ac_fn_check_decl "$LINENO" "sys_signame" "ac_cv_have_decl_sys_signame" "
+$ac_includes_default
+#include <signal.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_sys_signame" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_SYS_SIGNAME $ac_have_decl" >>confdefs.h
+if test $ac_have_decl = 1
+then :
+ HAVE_SIGNAME="true"
+else case e in #(
+ e)
+ ac_fn_check_decl "$LINENO" "_sys_signame" "ac_cv_have_decl__sys_signame" "
+$ac_includes_default
+#include <signal.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl__sys_signame" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL__SYS_SIGNAME $ac_have_decl" >>confdefs.h
+if test $ac_have_decl = 1
+then :
+ HAVE_SIGNAME="true"
+else case e in #(
+ e)
+ ac_fn_check_decl "$LINENO" "sys_sigabbrev" "ac_cv_have_decl_sys_sigabbrev" "
+$ac_includes_default
+#include <signal.h>
+
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_sys_sigabbrev" = xyes
+then :
+ ac_have_decl=1
+else case e in #(
+ e) ac_have_decl=0 ;;
+esac
+fi
+printf "%s\n" "#define HAVE_DECL_SYS_SIGABBREV $ac_have_decl" >>confdefs.h
+if test $ac_have_decl = 1
+then :
+ HAVE_SIGNAME="true"
+fi
+
+ ;;
+esac
+fi
+
+ ;;
+esac
+fi
+
+ if test "$HAVE_SIGNAME" != "true"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for undeclared sys_sigabbrev" >&5
+printf %s "checking for undeclared sys_sigabbrev... " >&6; }
+if test ${sudo_cv_var_sys_sigabbrev+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+extern char **sys_sigabbrev;
+int
+main (void)
+{
+return sys_sigabbrev[1];
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ sudo_cv_var_sys_sigabbrev=yes
+else case e in #(
+ e) sudo_cv_var_sys_sigabbrev=no
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_var_sys_sigabbrev" >&5
+printf "%s\n" "$sudo_cv_var_sys_sigabbrev" >&6; }
+ if test "$sudo_cv_var_sys_sigabbrev" = yes
+then :
+
+ printf "%s\n" "#define HAVE_SYS_SIGABBREV 1" >>confdefs.h
+
+
+else case e in #(
+ e)
+ case " $LIBOBJS " in
+ *" signame.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS signame.$ac_objext"
+ ;;
+esac
+
+ SIGNAME=signame.lo
+ ;;
+esac
+fi
+
+fi
+
+fi
+
+fi
+
+OLIBS="$LIBS"
+LIBS="$LIBS $lt_cv_dlopen_libs"
+ac_fn_c_check_func "$LINENO" "dl_iterate_phdr" "ac_cv_func_dl_iterate_phdr"
+if test "x$ac_cv_func_dl_iterate_phdr" = xyes
+then :
+ printf "%s\n" "#define HAVE_DL_ITERATE_PHDR 1" >>confdefs.h
+
+fi
+
+LIBS="$OLIBS"
+
+if test ${with_netsvc-"no"} != "no"
+then :
+
+ cat >>confdefs.h <<EOF
+#define _PATH_NETSVC_CONF "${with_netsvc-/etc/netsvc.conf}"
+EOF
+
+ netsvc_conf=${with_netsvc-/etc/netsvc.conf}
+
+elif test ${with_nsswitch-"yes"} != "no"
+then :
+
+ cat >>confdefs.h <<EOF
+#define _PATH_NSSWITCH_CONF "${with_nsswitch-/etc/nsswitch.conf}"
+EOF
+
+ nsswitch_conf=${with_nsswitch-/etc/nsswitch.conf}
+
+fi
+
+
+if test -z "${AUTH_EXCL}${AUTH_REG}" -a -n "$AUTH_EXCL_DEF"
+then :
+
+ for auth in $AUTH_EXCL_DEF; do
+ case $auth in
+ AIX_AUTH) with_aixauth=maybe;;
+ BSD_AUTH) with_bsdauth=maybe;;
+ PAM) with_pam=maybe;;
+ SIA) CHECKSIA=true;;
+ esac
+ done
+
+fi
+
+if test ${with_pam-"no"} != "no"
+then :
+
+ #
+ # Check for pam_start() in libpam first, then for pam_appl.h.
+ #
+ found_pam_lib=no
+ as_ac_Lib=`printf "%s\n" "ac_cv_lib_pam_pam_start$lt_cv_dlopen_libs" | sed "$as_sed_sh"`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pam_start in -lpam" >&5
+printf %s "checking for pam_start in -lpam... " >&6; }
+if eval test \${$as_ac_Lib+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpam $lt_cv_dlopen_libs $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pam_start (void);
+int
+main (void)
+{
+return pam_start ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ eval "$as_ac_Lib=yes"
+else case e in #(
+ e) eval "$as_ac_Lib=no" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+eval ac_res=\$$as_ac_Lib
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"
+then :
+ found_pam_lib=yes
+fi
+
+ #
+ # Some PAM implementations (macOS for example) put the PAM headers
+ # in /usr/include/pam instead of /usr/include/security...
+ #
+ found_pam_hdrs=no
+ for ac_header in security/pam_appl.h pam/pam_appl.h
+do :
+ as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | sed "$as_sed_sh"`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_header" | sed "$as_sed_cpp"` 1
+_ACEOF
+ found_pam_hdrs=yes; break
+fi
+
+done
+ if test "$found_pam_lib" = "yes" -a "$found_pam_hdrs" = "yes"
+then :
+
+ # Found both PAM libs and headers
+ with_pam=yes
+
+elif test "$with_pam" = "yes"
+then :
+
+ if test "$found_pam_lib" = "no"
+then :
+
+ as_fn_error $? "--with-pam specified but unable to locate PAM development library." "$LINENO" 5
+
+fi
+ if test "$found_pam_hdrs" = "no"
+then :
+
+ as_fn_error $? "--with-pam specified but unable to locate PAM development headers." "$LINENO" 5
+
+fi
+
+elif test "$found_pam_lib" != "$found_pam_hdrs"
+then :
+
+ if test "$found_pam_lib" = "no"
+then :
+
+ as_fn_error $? "found PAM headers but no PAM development library; specify --without-pam to build without PAM" "$LINENO" 5
+
+fi
+ if test "$found_pam_hdrs" = "no"
+then :
+
+ as_fn_error $? "found PAM library but no PAM development headers; specify --without-pam to build without PAM" "$LINENO" 5
+
+fi
+
+fi
+
+ if test "$with_pam" = "yes"
+then :
+
+ # Older PAM implementations lack pam_getenvlist
+ OLIBS="$LIBS"
+ LIBS="$LIBS -lpam $lt_cv_dlopen_libs"
+ ac_fn_c_check_func "$LINENO" "pam_getenvlist" "ac_cv_func_pam_getenvlist"
+if test "x$ac_cv_func_pam_getenvlist" = xyes
+then :
+ printf "%s\n" "#define HAVE_PAM_GETENVLIST 1" >>confdefs.h
+
+fi
+
+ LIBS="$OLIBS"
+
+ # We already link with -ldl if needed (see LIBDL below)
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lpam"
+ printf "%s\n" "#define HAVE_PAM 1" >>confdefs.h
+
+ AUTH_OBJS="$AUTH_OBJS pam.lo";
+ AUTH_EXCL=PAM
+
+
+# Check whether --with-pam-login was given.
+if test ${with_pam_login+y}
+then :
+ withval=$with_pam_login; case $with_pam_login in
+ yes) printf "%s\n" "#define HAVE_PAM_LOGIN 1" >>confdefs.h
+
+ pam_login_service="sudo-i"
+ ;;
+ no) ;;
+ *) as_fn_error $? "--with-pam-login does not take an argument." "$LINENO" 5
+ ;;
+ esac
+fi
+
+
+ # Check whether --enable-pam_session was given.
+if test ${enable_pam_session+y}
+then :
+ enableval=$enable_pam_session; case "$enableval" in
+ yes) ;;
+ no) printf "%s\n" "#define NO_PAM_SESSION 1" >>confdefs.h
+
+ pam_session=off
+ ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: ignoring unknown argument to --enable-pam-session: $enableval" >&5
+printf "%s\n" "$as_me: WARNING: ignoring unknown argument to --enable-pam-session: $enableval" >&2;}
+ ;;
+ esac
+fi
+
+
+fi
+
+fi
+
+if test ${with_aixauth-'no'} != "no"
+then :
+
+
+ for ac_func in authenticate
+do :
+ ac_fn_c_check_func "$LINENO" "authenticate" "ac_cv_func_authenticate"
+if test "x$ac_cv_func_authenticate" = xyes
+then :
+ printf "%s\n" "#define HAVE_AUTHENTICATE 1" >>confdefs.h
+ with_aixauth=yes
+fi
+
+done
+ if test "${with_aixauth}" = "yes"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: using AIX general authentication" >&5
+printf "%s\n" "$as_me: using AIX general authentication" >&6;}
+ printf "%s\n" "#define HAVE_AIXAUTH 1" >>confdefs.h
+
+ AUTH_OBJS="$AUTH_OBJS aix_auth.lo";
+ SUDOERS_LIBS="${SUDOERS_LIBS} -ls"
+ AUTH_EXCL=AIX_AUTH
+
+fi
+
+fi
+
+if test ${with_bsdauth-'no'} != "no"
+then :
+
+ ac_fn_c_check_header_compile "$LINENO" "bsd_auth.h" "ac_cv_header_bsd_auth_h" "$ac_includes_default"
+if test "x$ac_cv_header_bsd_auth_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_BSD_AUTH_H 1" >>confdefs.h
+
+ AUTH_OBJS="$AUTH_OBJS bsdauth.lo"
+ BSDAUTH_USAGE='[-a type] '
+ AUTH_EXCL=BSD_AUTH; BAMAN=1
+else case e in #(
+ e) as_fn_error $? "BSD authentication was specified but bsd_auth.h could not be found" "$LINENO" 5 ;;
+esac
+fi
+
+
+fi
+
+if test ${CHECKSIA-'false'} = "true"
+then :
+
+
+ for ac_func in sia_ses_init
+do :
+ ac_fn_c_check_func "$LINENO" "sia_ses_init" "ac_cv_func_sia_ses_init"
+if test "x$ac_cv_func_sia_ses_init" = xyes
+then :
+ printf "%s\n" "#define HAVE_SIA_SES_INIT 1" >>confdefs.h
+ found=true
+else case e in #(
+ e) found=false ;;
+esac
+fi
+
+done
+ if test "$found" = "true"
+then :
+
+ AUTH_EXCL=SIA
+ AUTH_OBJS="$AUTH_OBJS sia.lo"
+
+fi
+
+fi
+
+if test ${with_fwtk-'no'} != "no"
+then :
+
+ if test "$with_fwtk" != "yes"
+then :
+
+
+
+if test ${SUDOERS_LDFLAGS+y}
+then :
+
+ case " $SUDOERS_LDFLAGS " in #(
+ *" -L${with_fwtk} "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS already contains -L\${with_fwtk}"; } >&5
+ (: SUDOERS_LDFLAGS already contains -L${with_fwtk}) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS " -L${with_fwtk}"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS=-L${with_fwtk}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${SUDOERS_LDFLAGS_R+y}
+then :
+
+ case " $SUDOERS_LDFLAGS_R " in #(
+ *" -R${with_fwtk} "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R already contains -R\${with_fwtk}"; } >&5
+ (: SUDOERS_LDFLAGS_R already contains -R${with_fwtk}) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS_R " -R${with_fwtk}"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS_R=-R${with_fwtk}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -I${with_fwtk} "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -I\${with_fwtk}"; } >&5
+ (: CPPFLAGS already contains -I${with_fwtk}) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -I${with_fwtk}"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-I${with_fwtk}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ with_fwtk=yes
+
+fi
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lauth -lfwall"
+ AUTH_OBJS="$AUTH_OBJS fwtk.lo"
+
+fi
+
+if test ${with_SecurID-'no'} != "no"
+then :
+
+ if test "$with_SecurID" != "yes"
+then :
+
+elif test -d /usr/ace/examples
+then :
+
+ with_SecurID=/usr/ace/examples
+
+else case e in #(
+ e)
+ with_SecurID=/usr/ace
+ ;;
+esac
+fi
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -I${with_SecurID} "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -I\${with_SecurID}"; } >&5
+ (: CPPFLAGS already contains -I${with_SecurID}) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -I${with_SecurID}"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-I${with_SecurID}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+
+if test ${SUDOERS_LDFLAGS+y}
+then :
+
+ case " $SUDOERS_LDFLAGS " in #(
+ *" -L${with_SecurID} "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS already contains -L\${with_SecurID}"; } >&5
+ (: SUDOERS_LDFLAGS already contains -L${with_SecurID}) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS " -L${with_SecurID}"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS=-L${with_SecurID}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${SUDOERS_LDFLAGS_R+y}
+then :
+
+ case " $SUDOERS_LDFLAGS_R " in #(
+ *" -R${with_SecurID} "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R already contains -R\${with_SecurID}"; } >&5
+ (: SUDOERS_LDFLAGS_R already contains -R${with_SecurID}) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS_R " -R${with_SecurID}"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS_R=-R${with_SecurID}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+ SUDOERS_LIBS="${SUDOERS_LIBS} -laceclnt -lpthread"
+ AUTH_OBJS="$AUTH_OBJS securid5.lo";
+
+fi
+
+
+if test -z "${AUTH_EXCL}" -a -n "$AUTH_DEF"
+then :
+
+ for auth in $AUTH_DEF; do
+ case $auth in
+ passwd) : ${with_passwd='maybe'};;
+ esac
+ done
+
+fi
+
+if test ${with_kerb5-'no'} != "no"
+then :
+
+ # Extract the first word of "krb5-config", so it can be a program name with args.
+set dummy krb5-config; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_KRB5CONFIG+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) if test -n "$KRB5CONFIG"; then
+ ac_cv_prog_KRB5CONFIG="$KRB5CONFIG" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_KRB5CONFIG="yes"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_KRB5CONFIG" && ac_cv_prog_KRB5CONFIG=""""
+fi ;;
+esac
+fi
+KRB5CONFIG=$ac_cv_prog_KRB5CONFIG
+if test -n "$KRB5CONFIG"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $KRB5CONFIG" >&5
+printf "%s\n" "$KRB5CONFIG" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ if test -n "$KRB5CONFIG"
+then :
+
+ printf "%s\n" "#define HAVE_KERB5 1" >>confdefs.h
+
+ AUTH_OBJS="$AUTH_OBJS kerb5.lo"
+ for f in `krb5-config --cflags`; do
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" $f "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains \$f"; } >&5
+ (: CPPFLAGS already contains $f) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " $f"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=$f
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ done
+ SUDOERS_LIBS="$SUDOERS_LIBS `krb5-config --libs`"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5
+printf %s "checking whether we are using Heimdal... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <krb5.h>
+int
+main (void)
+{
+const char *tmp = heimdal_version;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ printf "%s\n" "#define HAVE_HEIMDAL 1" >>confdefs.h
+
+
+else case e in #(
+ e)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+
+else case e in #(
+ e)
+ printf "%s\n" "#define HAVE_KERB5 1" >>confdefs.h
+
+ if test "$with_kerb5" = "yes"
+then :
+
+ found=no
+ O_CPPFLAGS="$CPPFLAGS"
+ for dir in "" "kerberosV/" "krb5/" "kerberos5/" "kerberosv5/"; do
+ CPPFLAGS="$O_CPPFLAGS -I/usr/include/${dir}"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <krb5.h>
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+ found=yes; break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+ done
+ if test X"$found" = X"no"
+then :
+
+ CPPFLAGS="$O_CPPFLAGS"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unable to locate Kerberos V include files, you will have to edit the Makefile and add -I/path/to/krb/includes to CPPFLAGS" >&5
+printf "%s\n" "$as_me: WARNING: unable to locate Kerberos V include files, you will have to edit the Makefile and add -I/path/to/krb/includes to CPPFLAGS" >&2;}
+
+fi
+
+else case e in #(
+ e)
+
+
+if test ${SUDOERS_LDFLAGS+y}
+then :
+
+ case " $SUDOERS_LDFLAGS " in #(
+ *" -L${with_kerb5}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS already contains -L\${with_kerb5}/lib"; } >&5
+ (: SUDOERS_LDFLAGS already contains -L${with_kerb5}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS " -L${with_kerb5}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS=-L${with_kerb5}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${SUDOERS_LDFLAGS_R+y}
+then :
+
+ case " $SUDOERS_LDFLAGS_R " in #(
+ *" -R${with_kerb5}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R already contains -R\${with_kerb5}/lib"; } >&5
+ (: SUDOERS_LDFLAGS_R already contains -R${with_kerb5}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS_R " -R${with_kerb5}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS_R=-R${with_kerb5}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -I${with_kerb5}/include "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -I\${with_kerb5}/include"; } >&5
+ (: CPPFLAGS already contains -I${with_kerb5}/include) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -I${with_kerb5}/include"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-I${with_kerb5}/include
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ ;;
+esac
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5
+printf %s "checking whether we are using Heimdal... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <krb5.h>
+int
+main (void)
+{
+const char *tmp = heimdal_version;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ printf "%s\n" "#define HAVE_HEIMDAL 1" >>confdefs.h
+
+ # XXX - need to check whether -lcrypo is needed!
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lkrb5 -lcrypto -ldes -lcom_err -lasn1"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lroken" >&5
+printf %s "checking for main in -lroken... " >&6; }
+if test ${ac_cv_lib_roken_main+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lroken $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+int
+main (void)
+{
+return main ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_roken_main=yes
+else case e in #(
+ e) ac_cv_lib_roken_main=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_roken_main" >&5
+printf "%s\n" "$ac_cv_lib_roken_main" >&6; }
+if test "x$ac_cv_lib_roken_main" = xyes
+then :
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lroken"
+fi
+
+
+else case e in #(
+ e)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lkrb5 -lk5crypto -lcom_err"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lkrb5support" >&5
+printf %s "checking for main in -lkrb5support... " >&6; }
+if test ${ac_cv_lib_krb5support_main+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lkrb5support $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+int
+main (void)
+{
+return main ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_krb5support_main=yes
+else case e in #(
+ e) ac_cv_lib_krb5support_main=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_krb5support_main" >&5
+printf "%s\n" "$ac_cv_lib_krb5support_main" >&6; }
+if test "x$ac_cv_lib_krb5support_main" = xyes
+then :
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lkrb5support"
+fi
+
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ AUTH_OBJS="$AUTH_OBJS kerb5.lo"
+ ;;
+esac
+fi
+ _LIBS="$LIBS"
+ LIBS="${LIBS} ${SUDOERS_LIBS}"
+ ac_fn_c_check_func "$LINENO" "krb5_verify_user" "ac_cv_func_krb5_verify_user"
+if test "x$ac_cv_func_krb5_verify_user" = xyes
+then :
+ printf "%s\n" "#define HAVE_KRB5_VERIFY_USER 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "krb5_init_secure_context" "ac_cv_func_krb5_init_secure_context"
+if test "x$ac_cv_func_krb5_init_secure_context" = xyes
+then :
+ printf "%s\n" "#define HAVE_KRB5_INIT_SECURE_CONTEXT 1" >>confdefs.h
+
+fi
+
+
+ for ac_func in krb5_get_init_creds_opt_alloc
+do :
+ ac_fn_c_check_func "$LINENO" "krb5_get_init_creds_opt_alloc" "ac_cv_func_krb5_get_init_creds_opt_alloc"
+if test "x$ac_cv_func_krb5_get_init_creds_opt_alloc" = xyes
+then :
+ printf "%s\n" "#define HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC 1" >>confdefs.h
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether krb5_get_init_creds_opt_free takes a context" >&5
+printf %s "checking whether krb5_get_init_creds_opt_free takes a context... " >&6; }
+if test ${sudo_cv_krb5_get_init_creds_opt_free_two_args+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <krb5.h>
+int
+main (void)
+{
+krb5_get_init_creds_opt_free(NULL, NULL);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ sudo_cv_krb5_get_init_creds_opt_free_two_args=yes
+else case e in #(
+ e) sudo_cv_krb5_get_init_creds_opt_free_two_args=no
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_krb5_get_init_creds_opt_free_two_args" >&5
+printf "%s\n" "$sudo_cv_krb5_get_init_creds_opt_free_two_args" >&6; }
+
+fi
+
+done
+ if test X"$sudo_cv_krb5_get_init_creds_opt_free_two_args" = X"yes"
+then :
+
+ printf "%s\n" "#define HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_TWO_ARGS 1" >>confdefs.h
+
+
+fi
+ LIBS="$_LIBS"
+ # Check whether --enable-kerb5-instance was given.
+if test ${enable_kerb5_instance+y}
+then :
+ enableval=$enable_kerb5_instance; case "$enableval" in
+ yes) as_fn_error $? "must give --enable-kerb5-instance an argument." "$LINENO" 5
+ ;;
+ no) ;;
+ *) cat >>confdefs.h <<EOF
+#define SUDO_KRB5_INSTANCE "$enableval"
+EOF
+
+ ;;
+ esac
+fi
+
+
+fi
+
+if test ${with_AFS-'no'} = "yes"
+then :
+
+ # looks like the "standard" place for AFS libs is /usr/afsws/lib
+ AFSLIBDIRS="/usr/lib/afs /usr/afsws/lib /usr/afsws/lib/afs"
+ for i in $AFSLIBDIRS; do
+ if test -d ${i}
+then :
+
+
+
+if test ${SUDOERS_LDFLAGS+y}
+then :
+
+ case " $SUDOERS_LDFLAGS " in #(
+ *" -L$i "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS already contains -L\$i"; } >&5
+ (: SUDOERS_LDFLAGS already contains -L$i) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS " -L$i"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS=-L$i
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${SUDOERS_LDFLAGS_R+y}
+then :
+
+ case " $SUDOERS_LDFLAGS_R " in #(
+ *" -R$i "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R already contains -R\$i"; } >&5
+ (: SUDOERS_LDFLAGS_R already contains -R$i) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS_R " -R$i"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS_R=-R$i
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+ FOUND_AFSLIBDIR=true
+
+fi
+ done
+ if test -z "$FOUND_AFSLIBDIR"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unable to locate AFS libraries, you will have to edit the Makefile and add -L/path/to/afs/libs to SUDOERS_LDFLAGS or rerun configure with the --with-libpath options." >&5
+printf "%s\n" "$as_me: WARNING: unable to locate AFS libraries, you will have to edit the Makefile and add -L/path/to/afs/libs to SUDOERS_LDFLAGS or rerun configure with the --with-libpath options." >&2;}
+
+fi
+
+ # Order is important here. Note that we build AFS_LIBS from right to left
+ # since AFS_LIBS may be initialized with BSD compat libs that must go last
+ AFS_LIBS="-laudit ${AFS_LIBS}"
+ for i in $AFSLIBDIRS; do
+ if test -f ${i}/util.a
+then :
+
+ AFS_LIBS="${i}/util.a ${AFS_LIBS}"
+ FOUND_UTIL_A=true
+ break;
+
+fi
+ done
+ if test -z "$FOUND_UTIL_A"
+then :
+
+ AFS_LIBS="-lutil ${AFS_LIBS}"
+
+fi
+ AFS_LIBS="-lkauth -lprot -lubik -lauth -lrxkad -lsys -ldes -lrx -llwp -lcom_err ${AFS_LIBS}"
+
+ # AFS includes may live in /usr/include on some machines...
+ for i in /usr/afsws/include; do
+ if test -d ${i}
+then :
+
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -I${i} "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -I\${i}"; } >&5
+ (: CPPFLAGS already contains -I${i}) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -I${i}"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-I${i}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ FOUND_AFSINCDIR=true
+
+fi
+ done
+
+ if test -z "$FOUND_AFSLIBDIR"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unable to locate AFS include dir, you may have to edit the Makefile and add -I/path/to/afs/includes to CPPFLAGS or rerun configure with the --with-incpath options." >&5
+printf "%s\n" "$as_me: WARNING: unable to locate AFS include dir, you may have to edit the Makefile and add -I/path/to/afs/includes to CPPFLAGS or rerun configure with the --with-incpath options." >&2;}
+
+fi
+
+ AUTH_OBJS="$AUTH_OBJS afs.lo"
+
+fi
+
+if test ${with_DCE-'no'} = "yes"
+then :
+
+ DCE_OBJS="${DCE_OBJS} dce_pwent.o"
+ SUDOERS_LIBS="${SUDOERS_LIBS} -ldce"
+ AUTH_OBJS="$AUTH_OBJS dce.lo"
+
+fi
+
+if test "${with_skey-'no'}" = "yes"
+then :
+
+ O_LDFLAGS="$LDFLAGS"
+ if test "$with_skey" != "yes"
+then :
+
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -I${with_skey}/include "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -I\${with_skey}/include"; } >&5
+ (: CPPFLAGS already contains -I${with_skey}/include) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -I${with_skey}/include"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-I${with_skey}/include
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ LDFLAGS="$LDFLAGS -L${with_skey}/lib"
+
+
+if test ${SUDOERS_LDFLAGS+y}
+then :
+
+ case " $SUDOERS_LDFLAGS " in #(
+ *" -L${with_skey}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS already contains -L\${with_skey}/lib"; } >&5
+ (: SUDOERS_LDFLAGS already contains -L${with_skey}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS " -L${with_skey}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS=-L${with_skey}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${SUDOERS_LDFLAGS_R+y}
+then :
+
+ case " $SUDOERS_LDFLAGS_R " in #(
+ *" -R${with_skey}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R already contains -R\${with_skey}/lib"; } >&5
+ (: SUDOERS_LDFLAGS_R already contains -R${with_skey}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS_R " -R${with_skey}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS_R=-R${with_skey}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+ ac_fn_c_check_header_compile "$LINENO" "skey.h" "ac_cv_header_skey_h" "#include <stdio.h>
+"
+if test "x$ac_cv_header_skey_h" = xyes
+then :
+ found=yes
+else case e in #(
+ e) found=no ;;
+esac
+fi
+
+
+else case e in #(
+ e)
+ found=no
+ O_CPPFLAGS="$CPPFLAGS"
+ for dir in "" "/usr/local" "/usr/contrib"; do
+ test -n "$dir" && CPPFLAGS="$O_CPPFLAGS -I${dir}/include"
+ ac_fn_c_check_header_compile "$LINENO" "skey.h" "ac_cv_header_skey_h" "#include <stdio.h>
+"
+if test "x$ac_cv_header_skey_h" = xyes
+then :
+ found=yes; break
+fi
+
+ done
+ if test "$found" = "no" -o -z "$dir"
+then :
+
+ CPPFLAGS="$O_CPPFLAGS"
+
+else case e in #(
+ e)
+ LDFLAGS="$LDFLAGS -L${dir}/lib"
+
+
+if test ${SUDOERS_LDFLAGS+y}
+then :
+
+ case " $SUDOERS_LDFLAGS " in #(
+ *" -L${dir}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS already contains -L\${dir}/lib"; } >&5
+ (: SUDOERS_LDFLAGS already contains -L${dir}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS " -L${dir}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS=-L${dir}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${SUDOERS_LDFLAGS_R+y}
+then :
+
+ case " $SUDOERS_LDFLAGS_R " in #(
+ *" -R${dir}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R already contains -R\${dir}/lib"; } >&5
+ (: SUDOERS_LDFLAGS_R already contains -R${dir}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS_R " -R${dir}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS_R=-R${dir}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+ ;;
+esac
+fi
+ if test "$found" = "no"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unable to locate skey.h, you will have to edit the Makefile and add -I/path/to/skey/includes to CPPFLAGS" >&5
+printf "%s\n" "$as_me: WARNING: unable to locate skey.h, you will have to edit the Makefile and add -I/path/to/skey/includes to CPPFLAGS" >&2;}
+
+fi
+ ;;
+esac
+fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lskey" >&5
+printf %s "checking for main in -lskey... " >&6; }
+if test ${ac_cv_lib_skey_main+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lskey $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+int
+main (void)
+{
+return main ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_skey_main=yes
+else case e in #(
+ e) ac_cv_lib_skey_main=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_skey_main" >&5
+printf "%s\n" "$ac_cv_lib_skey_main" >&6; }
+if test "x$ac_cv_lib_skey_main" = xyes
+then :
+ found=yes
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unable to locate libskey.a, you will have to edit the Makefile and add -L/path/to/skey/lib to SUDOERS_LDFLAGS" >&5
+printf "%s\n" "$as_me: WARNING: unable to locate libskey.a, you will have to edit the Makefile and add -L/path/to/skey/lib to SUDOERS_LDFLAGS" >&2;} ;;
+esac
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for skeyaccess in -lskey" >&5
+printf %s "checking for skeyaccess in -lskey... " >&6; }
+if test ${ac_cv_lib_skey_skeyaccess+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lskey $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char skeyaccess (void);
+int
+main (void)
+{
+return skeyaccess ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_skey_skeyaccess=yes
+else case e in #(
+ e) ac_cv_lib_skey_skeyaccess=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_skey_skeyaccess" >&5
+printf "%s\n" "$ac_cv_lib_skey_skeyaccess" >&6; }
+if test "x$ac_cv_lib_skey_skeyaccess" = xyes
+then :
+ printf "%s\n" "#define HAVE_SKEYACCESS 1" >>confdefs.h
+
+fi
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for RFC1938-compliant skeychallenge" >&5
+printf %s "checking for RFC1938-compliant skeychallenge... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+# include <stdio.h>
+# include <skey.h>
+int
+main (void)
+{
+skeychallenge(NULL, NULL, NULL, 0);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+ printf "%s\n" "#define HAVE_RFC1938_SKEYCHALLENGE 1" >>confdefs.h
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+else case e in #(
+ e)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+
+ LDFLAGS="$O_LDFLAGS"
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lskey"
+ AUTH_OBJS="$AUTH_OBJS rfc1938.lo"
+
+fi
+
+if test "${with_opie-'no'}" = "yes"
+then :
+
+ O_LDFLAGS="$LDFLAGS"
+ if test "$with_opie" != "yes"
+then :
+
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -I${with_opie}/include "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -I\${with_opie}/include"; } >&5
+ (: CPPFLAGS already contains -I${with_opie}/include) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -I${with_opie}/include"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-I${with_opie}/include
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ LDFLAGS="$LDFLAGS -L${with_opie}/lib"
+
+
+if test ${SUDOERS_LDFLAGS+y}
+then :
+
+ case " $SUDOERS_LDFLAGS " in #(
+ *" -L${with_opie}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS already contains -L\${with_opie}/lib"; } >&5
+ (: SUDOERS_LDFLAGS already contains -L${with_opie}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS " -L${with_opie}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS=-L${with_opie}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${SUDOERS_LDFLAGS_R+y}
+then :
+
+ case " $SUDOERS_LDFLAGS_R " in #(
+ *" -R${with_opie}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R already contains -R\${with_opie}/lib"; } >&5
+ (: SUDOERS_LDFLAGS_R already contains -R${with_opie}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS_R " -R${with_opie}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS_R=-R${with_opie}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <opie.h>
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+ found=yes
+else case e in #(
+ e) found=no ;;
+esac
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+else case e in #(
+ e)
+ found=no
+ O_CPPFLAGS="$CPPFLAGS"
+ for dir in "" "/usr/local" "/usr/contrib"; do
+ test -n "$dir" && CPPFLAGS="$O_CPPFLAGS -I${dir}/include"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <opie.h>
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+ found=yes; break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+ done
+ if test "$found" = "no" -o -z "$dir"
+then :
+
+ CPPFLAGS="$O_CPPFLAGS"
+
+else case e in #(
+ e)
+ LDFLAGS="$LDFLAGS -L${dir}/lib"
+
+
+if test ${SUDOERS_LDFLAGS+y}
+then :
+
+ case " $SUDOERS_LDFLAGS " in #(
+ *" -L${dir}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS already contains -L\${dir}/lib"; } >&5
+ (: SUDOERS_LDFLAGS already contains -L${dir}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS " -L${dir}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS=-L${dir}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${SUDOERS_LDFLAGS_R+y}
+then :
+
+ case " $SUDOERS_LDFLAGS_R " in #(
+ *" -R${dir}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R already contains -R\${dir}/lib"; } >&5
+ (: SUDOERS_LDFLAGS_R already contains -R${dir}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS_R " -R${dir}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS_R=-R${dir}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+ ;;
+esac
+fi
+ if test "$found" = "no"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unable to locate opie.h, you will have to edit the Makefile and add -I/path/to/opie/includes to CPPFLAGS" >&5
+printf "%s\n" "$as_me: WARNING: unable to locate opie.h, you will have to edit the Makefile and add -I/path/to/opie/includes to CPPFLAGS" >&2;}
+
+fi
+ ;;
+esac
+fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lopie" >&5
+printf %s "checking for main in -lopie... " >&6; }
+if test ${ac_cv_lib_opie_main+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lopie $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+int
+main (void)
+{
+return main ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_opie_main=yes
+else case e in #(
+ e) ac_cv_lib_opie_main=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_opie_main" >&5
+printf "%s\n" "$ac_cv_lib_opie_main" >&6; }
+if test "x$ac_cv_lib_opie_main" = xyes
+then :
+ found=yes
+else case e in #(
+ e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unable to locate libopie.a, you will have to edit the Makefile and add -L/path/to/opie/lib to SUDOERS_LDFLAGS" >&5
+printf "%s\n" "$as_me: WARNING: unable to locate libopie.a, you will have to edit the Makefile and add -L/path/to/opie/lib to SUDOERS_LDFLAGS" >&2;} ;;
+esac
+fi
+
+ LDFLAGS="$O_LDFLAGS"
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lopie"
+ AUTH_OBJS="$AUTH_OBJS rfc1938.lo"
+
+fi
+
+if test ${with_passwd-'no'} != "no"
+then :
+
+ _LIBS="$LIBS"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing crypt" >&5
+printf %s "checking for library containing crypt... " >&6; }
+if test ${ac_cv_search_crypt+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char crypt (void);
+int
+main (void)
+{
+return crypt ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' crypt crypt_d ufc
+do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_search_crypt=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext
+ if test ${ac_cv_search_crypt+y}
+then :
+ break
+fi
+done
+if test ${ac_cv_search_crypt+y}
+then :
+
+else case e in #(
+ e) ac_cv_search_crypt=no ;;
+esac
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_crypt" >&5
+printf "%s\n" "$ac_cv_search_crypt" >&6; }
+ac_res=$ac_cv_search_crypt
+if test "$ac_res" != no
+then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+ test "${ac_cv_search_crypt}" != "none required" && shadow_libs="${shadow_libs} ${ac_cv_search_crypt}"
+
+fi
+
+ if test "${ac_cv_search_crypt}" != "no"
+then :
+
+ printf "%s\n" "#define HAVE_CRYPT 1" >>confdefs.h
+
+
+fi
+ LIBS="$_LIBS"
+
+ if test "$CHECKSHADOW" = "true" -a -n "$shadow_funcs"
+then :
+
+ _LIBS="$LIBS"
+ LIBS="$LIBS $shadow_libs"
+ found=no
+ for func in $shadow_funcs; do
+ as_ac_var=`printf "%s\n" "ac_cv_func_$func" | sed "$as_sed_sh"`
+ac_fn_c_check_func "$LINENO" "$func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"
+then :
+
+ case "$func" in
+ dispcrypt)
+ printf "%s\n" "#define HAVE_DISPCRYPT 1" >>confdefs.h
+
+ ;;
+ getprpwnam)
+ printf "%s\n" "#define HAVE_GETPRPWNAM 1" >>confdefs.h
+
+ SECUREWARE=1
+ ;;
+ getpwnam_shadow)
+ printf "%s\n" "#define HAVE_GETPWNAM_SHADOW 1" >>confdefs.h
+
+ ;;
+ getspnam)
+ printf "%s\n" "#define HAVE_GETSPNAM 1" >>confdefs.h
+
+ ;;
+ iscomsec)
+ printf "%s\n" "#define HAVE_ISCOMSEC 1" >>confdefs.h
+
+ ;;
+ *)
+ as_fn_error $? "unhandled shadow password function $func" "$LINENO" 5
+ ;;
+ esac
+ found=yes
+
+fi
+
+ done
+ if test "$found" = "no"
+then :
+
+ shadow_libs=
+
+fi
+ CHECKSHADOW=false
+ LIBS="$_LIBS"
+
+fi
+ if test "$CHECKSHADOW" = "true"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing getspnam" >&5
+printf %s "checking for library containing getspnam... " >&6; }
+if test ${ac_cv_search_getspnam+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getspnam (void);
+int
+main (void)
+{
+return getspnam ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' gen shadow
+do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_search_getspnam=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext
+ if test ${ac_cv_search_getspnam+y}
+then :
+ break
+fi
+done
+if test ${ac_cv_search_getspnam+y}
+then :
+
+else case e in #(
+ e) ac_cv_search_getspnam=no ;;
+esac
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getspnam" >&5
+printf "%s\n" "$ac_cv_search_getspnam" >&6; }
+ac_res=$ac_cv_search_getspnam
+if test "$ac_res" != no
+then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+ printf "%s\n" "#define HAVE_GETSPNAM 1" >>confdefs.h
+
+ test "${ac_cv_search_getspnam}" != "none required" && shadow_libs="${shadow_libs} ${ac_cv_search_getspnam}"
+ CHECKSHADOW=false
+
+fi
+
+
+fi
+ if test "$CHECKSHADOW" = "true"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing getprpwnam" >&5
+printf %s "checking for library containing getprpwnam... " >&6; }
+if test ${ac_cv_search_getprpwnam+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getprpwnam (void);
+int
+main (void)
+{
+return getprpwnam ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' sec security prot
+do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_search_getprpwnam=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext
+ if test ${ac_cv_search_getprpwnam+y}
+then :
+ break
+fi
+done
+if test ${ac_cv_search_getprpwnam+y}
+then :
+
+else case e in #(
+ e) ac_cv_search_getprpwnam=no ;;
+esac
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getprpwnam" >&5
+printf "%s\n" "$ac_cv_search_getprpwnam" >&6; }
+ac_res=$ac_cv_search_getprpwnam
+if test "$ac_res" != no
+then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+ printf "%s\n" "#define HAVE_GETPRPWNAM 1" >>confdefs.h
+
+ test "${ac_cv_search_getprpwnam}" != "none required" && shadow_libs="${shadow_libs} ${ac_cv_search_getprpwnam}"
+ SECUREWARE=1
+ CHECKSHADOW=false
+
+fi
+
+
+fi
+ if test -n "$shadow_libs"
+then :
+
+ # sudoers needs to link with shadow libs for password auth
+ SUDOERS_LIBS="$SUDOERS_LIBS $shadow_libs"
+
+fi
+ if test -n "$SECUREWARE"
+then :
+
+ _LIBS="$LIBS"
+ LIBS="$LIBS $shadow_libs"
+ ac_fn_c_check_func "$LINENO" "bigcrypt" "ac_cv_func_bigcrypt"
+if test "x$ac_cv_func_bigcrypt" = xyes
+then :
+ printf "%s\n" "#define HAVE_BIGCRYPT 1" >>confdefs.h
+
+fi
+
+ AUTH_OBJS="$AUTH_OBJS secureware.lo"
+ # set_auth_parameters() and initprivs() are called from sudo.c
+
+ for ac_func in set_auth_parameters initprivs
+do :
+ as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | sed "$as_sed_sh"`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_func" | sed "$as_sed_cpp"` 1
+_ACEOF
+ test -n "$shadow_libs" && SUDO_LIBS="$SUDO_LIBS $shadow_libs"
+fi
+
+done
+ LIBS="$_LIBS"
+
+fi
+
+fi
+
+if test X"$with_bsm_audit" = X"yes"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether au_close() takes 4 arguments" >&5
+printf %s "checking whether au_close() takes 4 arguments... " >&6; }
+if test ${sudo_cv_func_au_close_solaris11+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+#include <bsm/audit.h>
+#include <bsm/libbsm.h>
+#include <bsm/audit_uevents.h>
+
+int au_close(int d, int keep, au_event_t event, au_emod_t emod) {return 0;}
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ sudo_cv_func_au_close_solaris11=yes
+else case e in #(
+ e) sudo_cv_func_au_close_solaris11=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_func_au_close_solaris11" >&5
+printf "%s\n" "$sudo_cv_func_au_close_solaris11" >&6; }
+ if test $sudo_cv_func_au_close_solaris11 = yes; then
+
+printf "%s\n" "#define HAVE_AU_CLOSE_SOLARIS11 1" >>confdefs.h
+
+ fi
+
+
+fi
+
+if test X"$enable_poll" = X""
+then :
+
+
+ for ac_func in ppoll poll
+do :
+ as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | sed "$as_sed_sh"`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_func" | sed "$as_sed_cpp"` 1
+_ACEOF
+ enable_poll=yes; break
+else case e in #(
+ e) enable_poll=no ;;
+esac
+fi
+
+done
+
+elif test X"$enable_poll" = X"yes"
+then :
+
+
+ for ac_func in ppoll
+do :
+ ac_fn_c_check_func "$LINENO" "ppoll" "ac_cv_func_ppoll"
+if test "x$ac_cv_func_ppoll" = xyes
+then :
+ printf "%s\n" "#define HAVE_PPOLL 1" >>confdefs.h
+
+else case e in #(
+ e) printf "%s\n" "#define HAVE_POLL 1" >>confdefs.h
+ ;;
+esac
+fi
+
+done
+
+fi
+if test "$enable_poll" = "yes"
+then :
+
+ COMMON_OBJS="${COMMON_OBJS} event_poll.lo"
+
+else case e in #(
+ e)
+ ac_fn_c_check_func "$LINENO" "pselect" "ac_cv_func_pselect"
+if test "x$ac_cv_func_pselect" = xyes
+then :
+ printf "%s\n" "#define HAVE_PSELECT 1" >>confdefs.h
+
+fi
+
+ COMMON_OBJS="${COMMON_OBJS} event_select.lo"
+ ;;
+esac
+fi
+
+
+ if test ${with_ldap-'no'} != "no"; then
+ O_LDFLAGS="$LDFLAGS"
+ if test "$with_ldap" != "yes"; then
+
+
+if test ${SUDOERS_LDFLAGS+y}
+then :
+
+ case " $SUDOERS_LDFLAGS " in #(
+ *" -L${with_ldap}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS already contains -L\${with_ldap}/lib"; } >&5
+ (: SUDOERS_LDFLAGS already contains -L${with_ldap}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS " -L${with_ldap}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS=-L${with_ldap}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${SUDOERS_LDFLAGS_R+y}
+then :
+
+ case " $SUDOERS_LDFLAGS_R " in #(
+ *" -R${with_ldap}/lib "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R already contains -R\${with_ldap}/lib"; } >&5
+ (: SUDOERS_LDFLAGS_R already contains -R${with_ldap}/lib) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS_R " -R${with_ldap}/lib"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS_R=-R${with_ldap}/lib
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+ LDFLAGS="$LDFLAGS -L${with_ldap}/lib"
+ if test -d "${with_ldap}/lib64"; then
+
+
+if test ${SUDOERS_LDFLAGS+y}
+then :
+
+ case " $SUDOERS_LDFLAGS " in #(
+ *" -L${with_ldap}/lib64 "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS already contains -L\${with_ldap}/lib64"; } >&5
+ (: SUDOERS_LDFLAGS already contains -L${with_ldap}/lib64) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS " -L${with_ldap}/lib64"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS=-L${with_ldap}/lib64
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test X"$enable_rpath" = X"yes"; then
+
+if test ${SUDOERS_LDFLAGS_R+y}
+then :
+
+ case " $SUDOERS_LDFLAGS_R " in #(
+ *" -R${with_ldap}/lib64 "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R already contains -R\${with_ldap}/lib64"; } >&5
+ (: SUDOERS_LDFLAGS_R already contains -R${with_ldap}/lib64) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS_R " -R${with_ldap}/lib64"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS_R=-R${with_ldap}/lib64
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS_R=\"\$SUDOERS_LDFLAGS_R\""; } >&5
+ (: SUDOERS_LDFLAGS_R="$SUDOERS_LDFLAGS_R") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ fi
+
+ LDFLAGS="$LDFLAGS -L${with_ldap}/lib64"
+ fi
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -I${with_ldap}/include "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -I\${with_ldap}/include"; } >&5
+ (: CPPFLAGS already contains -I${with_ldap}/include) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -I${with_ldap}/include"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-I${with_ldap}/include
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ with_ldap=yes
+ fi
+ SUDOERS_OBJS="${SUDOERS_OBJS} ldap.lo ldap_conf.lo ldap_innetgr.lo"
+ case "$SUDOERS_OBJS" in
+ *ldap_util.lo*) ;;
+ *) SUDOERS_OBJS="${SUDOERS_OBJS} ldap_util.lo";;
+ esac
+ LDAP=""
+
+ _LIBS="$LIBS"
+ LDAP_LIBS=""
+ IBMLDAP_EXTRA=""
+ found=no
+ # On HP-UX, libibmldap has a hidden dependency on libCsup
+ case "$host_os" in
+ hpux*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lCsup" >&5
+printf %s "checking for main in -lCsup... " >&6; }
+if test ${ac_cv_lib_Csup_main+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lCsup $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+int
+main (void)
+{
+return main ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_Csup_main=yes
+else case e in #(
+ e) ac_cv_lib_Csup_main=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Csup_main" >&5
+printf "%s\n" "$ac_cv_lib_Csup_main" >&6; }
+if test "x$ac_cv_lib_Csup_main" = xyes
+then :
+ IBMLDAP_EXTRA=" -lCsup"
+fi
+;;
+ esac
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing ldap_init" >&5
+printf %s "checking for library containing ldap_init... " >&6; }
+if test ${ac_cv_search_ldap_init+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ldap_init (void);
+int
+main (void)
+{
+return ldap_init ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' "ibmldap${IBMLDAP_EXTRA}" "ibmldap -lidsldif${IBMLDAP_EXTRA}" "ldap" "ldap -llber" "ldap -llber -lssl -lcrypto" "ibmldap${IBMLDAP_EXTRA}"
+do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_search_ldap_init=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext
+ if test ${ac_cv_search_ldap_init+y}
+then :
+ break
+fi
+done
+if test ${ac_cv_search_ldap_init+y}
+then :
+
+else case e in #(
+ e) ac_cv_search_ldap_init=no ;;
+esac
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ldap_init" >&5
+printf "%s\n" "$ac_cv_search_ldap_init" >&6; }
+ac_res=$ac_cv_search_ldap_init
+if test "$ac_res" != no
+then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+ test "${ac_cv_search_ldap_init}" != "none required" && LDAP_LIBS="${ac_cv_search_ldap_init}"
+ found=yes
+
+fi
+
+ # If nothing linked, try -lldap and hope for the best
+ if test "$found" = "no"; then
+ LDAP_LIBS="-lldap"
+ fi
+ LIBS="${_LIBS} ${LDAP_LIBS}"
+
+ ac_fn_check_decl "$LINENO" "LBER_OPT_DEBUG_LEVEL" "ac_cv_have_decl_LBER_OPT_DEBUG_LEVEL" "$ac_includes_default
+#include <lber.h>
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_LBER_OPT_DEBUG_LEVEL" = xyes
+then :
+
+ case "$LDAP_LIBS" in
+ *-llber*)
+ # Already linking with -llber
+ ;;
+ *) # Link with -llber for ber_set_option() if it exists
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ber_set_option in -llber" >&5
+printf %s "checking for ber_set_option in -llber... " >&6; }
+if test ${ac_cv_lib_lber_ber_set_option+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-llber $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ber_set_option (void);
+int
+main (void)
+{
+return ber_set_option ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_lber_ber_set_option=yes
+else case e in #(
+ e) ac_cv_lib_lber_ber_set_option=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lber_ber_set_option" >&5
+printf "%s\n" "$ac_cv_lib_lber_ber_set_option" >&6; }
+if test "x$ac_cv_lib_lber_ber_set_option" = xyes
+then :
+ found=yes
+else case e in #(
+ e) found=no ;;
+esac
+fi
+
+ if test X"$found" = X"yes"; then
+ LDAP_LIBS="$LDAP_LIBS -llber"
+ fi
+ ;;
+ esac
+
+fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether lber.h is needed when including ldap.h" >&5
+printf %s "checking whether lber.h is needed when including ldap.h... " >&6; }
+if test ${sudo_cv_header_lber_h+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <ldap.h>
+int
+main (void)
+{
+return ldap_msgfree(NULL)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+
+ # No need to explicitly include lber.h when including ldap.h.
+ sudo_cv_header_lber_h=no
+
+else case e in #(
+ e)
+ sudo_cv_header_lber_h=yes
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_header_lber_h" >&5
+printf "%s\n" "$sudo_cv_header_lber_h" >&6; }
+ if test X"$sudo_cv_header_lber_h" = X"yes"; then
+ printf "%s\n" "#define HAVE_LBER_H 1" >>confdefs.h
+
+ fi
+
+ if test ${enable_sasl-'yes'} = "yes"; then
+ found_sasl_h=no
+ for ac_header in sasl/sasl.h sasl.h
+do :
+ as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | sed "$as_sed_sh"`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_header" | sed "$as_sed_cpp"` 1
+_ACEOF
+
+ found_sasl_h=yes
+ ac_fn_c_check_func "$LINENO" "ldap_sasl_interactive_bind_s" "ac_cv_func_ldap_sasl_interactive_bind_s"
+if test "x$ac_cv_func_ldap_sasl_interactive_bind_s" = xyes
+then :
+ printf "%s\n" "#define HAVE_LDAP_SASL_INTERACTIVE_BIND_S 1" >>confdefs.h
+
+fi
+
+ break
+
+fi
+
+done
+ if test X${enable_sasl} = X"yes"; then
+ if test X"$found_sasl_h" != X"yes"; then
+ as_fn_error $? "--enable-sasl specified but unable to locate SASL development headers." "$LINENO" 5
+ fi
+ if test X"$ac_cv_func_ldap_sasl_interactive_bind_s" != X"yes"; then :
+ as_fn_error $? "--enable-sasl specified but SASL support is missing in your LDAP library" "$LINENO" 5
+ fi
+ fi
+ fi
+ for ac_header in ldapssl.h ldap_ssl.h mps/ldap_ssl.h
+do :
+ as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | sed "$as_sed_sh"`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include <ldap.h>
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_header" | sed "$as_sed_cpp"` 1
+_ACEOF
+ break
+fi
+
+done
+ ac_fn_c_check_func "$LINENO" "ldap_initialize" "ac_cv_func_ldap_initialize"
+if test "x$ac_cv_func_ldap_initialize" = xyes
+then :
+ printf "%s\n" "#define HAVE_LDAP_INITIALIZE 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "ldap_start_tls_s" "ac_cv_func_ldap_start_tls_s"
+if test "x$ac_cv_func_ldap_start_tls_s" = xyes
+then :
+ printf "%s\n" "#define HAVE_LDAP_START_TLS_S 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "ldapssl_init" "ac_cv_func_ldapssl_init"
+if test "x$ac_cv_func_ldapssl_init" = xyes
+then :
+ printf "%s\n" "#define HAVE_LDAPSSL_INIT 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "ldapssl_set_strength" "ac_cv_func_ldapssl_set_strength"
+if test "x$ac_cv_func_ldapssl_set_strength" = xyes
+then :
+ printf "%s\n" "#define HAVE_LDAPSSL_SET_STRENGTH 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "ldap_unbind_ext_s" "ac_cv_func_ldap_unbind_ext_s"
+if test "x$ac_cv_func_ldap_unbind_ext_s" = xyes
+then :
+ printf "%s\n" "#define HAVE_LDAP_UNBIND_EXT_S 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "ldap_str2dn" "ac_cv_func_ldap_str2dn"
+if test "x$ac_cv_func_ldap_str2dn" = xyes
+then :
+ printf "%s\n" "#define HAVE_LDAP_STR2DN 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "ldap_create" "ac_cv_func_ldap_create"
+if test "x$ac_cv_func_ldap_create" = xyes
+then :
+ printf "%s\n" "#define HAVE_LDAP_CREATE 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "ldap_sasl_bind_s" "ac_cv_func_ldap_sasl_bind_s"
+if test "x$ac_cv_func_ldap_sasl_bind_s" = xyes
+then :
+ printf "%s\n" "#define HAVE_LDAP_SASL_BIND_S 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "ldap_ssl_init" "ac_cv_func_ldap_ssl_init"
+if test "x$ac_cv_func_ldap_ssl_init" = xyes
+then :
+ printf "%s\n" "#define HAVE_LDAP_SSL_INIT 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "ldap_ssl_client_init" "ac_cv_func_ldap_ssl_client_init"
+if test "x$ac_cv_func_ldap_ssl_client_init" = xyes
+then :
+ printf "%s\n" "#define HAVE_LDAP_SSL_CLIENT_INIT 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "ldap_start_tls_s_np" "ac_cv_func_ldap_start_tls_s_np"
+if test "x$ac_cv_func_ldap_start_tls_s_np" = xyes
+then :
+ printf "%s\n" "#define HAVE_LDAP_START_TLS_S_NP 1" >>confdefs.h
+
+fi
+
+
+ for ac_func in ldap_search_ext_s ldap_search_st
+do :
+ as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | sed "$as_sed_sh"`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_func" | sed "$as_sed_cpp"` 1
+_ACEOF
+ break
+fi
+
+done
+
+ if test X"$check_gss_krb5_ccache_name" = X"yes"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gss_krb5_ccache_name in -lgssapi" >&5
+printf %s "checking for gss_krb5_ccache_name in -lgssapi... " >&6; }
+if test ${ac_cv_lib_gssapi_gss_krb5_ccache_name+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgssapi $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gss_krb5_ccache_name (void);
+int
+main (void)
+{
+return gss_krb5_ccache_name ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_gssapi_gss_krb5_ccache_name=yes
+else case e in #(
+ e) ac_cv_lib_gssapi_gss_krb5_ccache_name=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gssapi_gss_krb5_ccache_name" >&5
+printf "%s\n" "$ac_cv_lib_gssapi_gss_krb5_ccache_name" >&6; }
+if test "x$ac_cv_lib_gssapi_gss_krb5_ccache_name" = xyes
+then :
+
+ printf "%s\n" "#define HAVE_GSS_KRB5_CCACHE_NAME 1" >>confdefs.h
+
+ LDAP_LIBS="${LDAP_LIBS} -lgssapi"
+
+else case e in #(
+ e)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gss_krb5_ccache_name in -lgssapi_krb5" >&5
+printf %s "checking for gss_krb5_ccache_name in -lgssapi_krb5... " >&6; }
+if test ${ac_cv_lib_gssapi_krb5_gss_krb5_ccache_name+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgssapi_krb5 $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply.
+ The 'extern "C"' is for builds by C++ compilers;
+ although this is not generally supported in C code supporting it here
+ has little cost and some practical benefit (sr 110532). */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gss_krb5_ccache_name (void);
+int
+main (void)
+{
+return gss_krb5_ccache_name ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_gssapi_krb5_gss_krb5_ccache_name=yes
+else case e in #(
+ e) ac_cv_lib_gssapi_krb5_gss_krb5_ccache_name=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gssapi_krb5_gss_krb5_ccache_name" >&5
+printf "%s\n" "$ac_cv_lib_gssapi_krb5_gss_krb5_ccache_name" >&6; }
+if test "x$ac_cv_lib_gssapi_krb5_gss_krb5_ccache_name" = xyes
+then :
+
+ printf "%s\n" "#define HAVE_GSS_KRB5_CCACHE_NAME 1" >>confdefs.h
+
+ LDAP_LIBS="${LDAP_LIBS} -lgssapi_krb5"
+
+fi
+
+ ;;
+esac
+fi
+
+
+ # gssapi headers may be separate or part of Kerberos V
+ found=no
+ O_CPPFLAGS="$CPPFLAGS"
+ for dir in "" "kerberosV" "krb5" "kerberos5" "kerberosv5"; do
+ test X"$dir" != X"" && CPPFLAGS="$O_CPPFLAGS -I/usr/include/${dir}"
+ # Use AC_PREPROC_IFELSE to check existence to avoid caching
+ # since we test with multiple values of CPPFLAGS
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <gssapi/gssapi.h>
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+
+ ac_fn_c_check_header_compile "$LINENO" "gssapi/gssapi.h" "ac_cv_header_gssapi_gssapi_h" "$ac_includes_default"
+if test "x$ac_cv_header_gssapi_gssapi_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_GSSAPI_GSSAPI_H 1" >>confdefs.h
+
+fi
+
+ break
+
+else case e in #(
+ e)
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <gssapi.h>
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+
+ ac_fn_c_check_header_compile "$LINENO" "gssapi.h" "ac_cv_header_gssapi_h" "$ac_includes_default"
+if test "x$ac_cv_header_gssapi_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_GSSAPI_H 1" >>confdefs.h
+
+fi
+
+ break
+
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+ ;;
+esac
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+ done
+ if test X"$ac_cv_header_gssapi_gssapi_h" != X"no"; then
+ ac_fn_c_check_header_compile "$LINENO" "gssapi/gssapi_krb5.h" "ac_cv_header_gssapi_gssapi_krb5_h" "$ac_includes_default"
+if test "x$ac_cv_header_gssapi_gssapi_krb5_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_GSSAPI_GSSAPI_KRB5_H 1" >>confdefs.h
+
+fi
+
+ elif test X"$ac_cv_header_gssapi_h" = X"no"; then
+ CPPFLAGS="$O_CPPFLAGS"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unable to locate gssapi.h, you will have to edit the Makefile and add -I/path/to/gssapi/includes to CPPFLAGS" >&5
+printf "%s\n" "$as_me: WARNING: unable to locate gssapi.h, you will have to edit the Makefile and add -I/path/to/gssapi/includes to CPPFLAGS" >&2;}
+ fi
+ fi
+
+ SUDOERS_LIBS="${SUDOERS_LIBS} ${LDAP_LIBS}"
+ LIBS="$_LIBS"
+ LDFLAGS="$O_LDFLAGS"
+ fi
+
+
+#
+# How to do dynamic object loading.
+# We support dlopen() and sh_load(), else fall back to static loading.
+#
+case "$lt_cv_dlopen" in
+ dlopen)
+ printf "%s\n" "#define HAVE_DLOPEN 1" >>confdefs.h
+
+ if test "$enable_static_sudoers" = "yes"
+then :
+
+ printf "%s\n" "#define STATIC_SUDOERS_PLUGIN 1" >>confdefs.h
+
+ SUDO_OBJS="${SUDO_OBJS} preload.o"
+ STATIC_SUDOERS="\$(top_builddir)/plugins/sudoers/sudoers.la"
+
+if test ${SUDOERS_LDFLAGS+y}
+then :
+
+ case " $SUDOERS_LDFLAGS " in #(
+ *" -no-install "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS already contains -no-install"; } >&5
+ (: SUDOERS_LDFLAGS already contains -no-install) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS " -no-install"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS=-no-install
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ SUDOERS_LT_STATIC="--tag=disable-shared"
+ LT_STATIC=""
+
+else case e in #(
+ e)
+ SUDOERS_LT_STATIC="--tag=disable-static"
+ LT_STATIC="--tag=disable-static"
+ ;;
+esac
+fi
+ ;;
+ shl_load)
+ printf "%s\n" "#define HAVE_SHL_LOAD 1" >>confdefs.h
+
+ if test "$enable_static_sudoers" = "yes"
+then :
+
+ printf "%s\n" "#define STATIC_SUDOERS_PLUGIN 1" >>confdefs.h
+
+ SUDO_OBJS="${SUDO_OBJS} preload.o"
+ STATIC_SUDOERS="\$(top_builddir)/plugins/sudoers/sudoers.la"
+
+if test ${SUDOERS_LDFLAGS+y}
+then :
+
+ case " $SUDOERS_LDFLAGS " in #(
+ *" -no-install "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS already contains -no-install"; } >&5
+ (: SUDOERS_LDFLAGS already contains -no-install) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append SUDOERS_LDFLAGS " -no-install"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ SUDOERS_LDFLAGS=-no-install
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : SUDOERS_LDFLAGS=\"\$SUDOERS_LDFLAGS\""; } >&5
+ (: SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ SUDOERS_LT_STATIC="--tag=disable-shared"
+ LT_STATIC=""
+
+else case e in #(
+ e)
+ SUDOERS_LT_STATIC="--tag=disable-static"
+ LT_STATIC="--tag=disable-static"
+ ;;
+esac
+fi
+ ;;
+ *)
+ if test X"${ac_cv_func_dlopen}" = X"yes"
+then :
+
+ as_fn_error $? "dlopen present but libtool doesn't appear to support your platform." "$LINENO" 5
+
+fi
+ # Preload sudoers module symbols
+ printf "%s\n" "#define STATIC_SUDOERS_PLUGIN 1" >>confdefs.h
+
+ SUDO_OBJS="${SUDO_OBJS} preload.o"
+ STATIC_SUDOERS="\$(top_builddir)/plugins/sudoers/sudoers.la"
+ LT_STATIC=""
+ ;;
+esac
+
+#
+# The check_symbols test can only succeed with a dynamic sudoers plugin.
+#
+if test X"$STATIC_SUDOERS" = X""; then
+ SUDOERS_TEST_PROGS="${SUDOERS_TEST_PROGS}${SUDOERS_TEST_PROGS+ }check_symbols"
+fi
+
+#
+# We can only disable linking with the shared libsudo_util if
+# sudoers is linked statically too.
+#
+if test "$enable_shared_libutil" = "no"
+then :
+
+ if test X"$STATIC_SUDOERS" = X""
+then :
+
+ as_fn_error $? "--disable-shared-libutil may only be specified with --enable-static-sudoers or when dynamic linking is disabled." "$LINENO" 5
+
+else case e in #(
+ e)
+ # Do not install libsudo_util.
+
+if test ${LIBUTIL_LDFLAGS+y}
+then :
+
+ case " $LIBUTIL_LDFLAGS " in #(
+ *" -no-install "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBUTIL_LDFLAGS already contains -no-install"; } >&5
+ (: LIBUTIL_LDFLAGS already contains -no-install) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LIBUTIL_LDFLAGS " -no-install"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBUTIL_LDFLAGS=\"\$LIBUTIL_LDFLAGS\""; } >&5
+ (: LIBUTIL_LDFLAGS="$LIBUTIL_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LIBUTIL_LDFLAGS=-no-install
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LIBUTIL_LDFLAGS=\"\$LIBUTIL_LDFLAGS\""; } >&5
+ (: LIBUTIL_LDFLAGS="$LIBUTIL_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ ;;
+esac
+fi
+
+fi
+
+# On HP-UX, you cannot dlopen() a shared object that uses pthreads unless
+# the main program is linked against -lpthread. We have no knowledge of
+# what libraries a plugin may depend on (e.g. HP-UX LDAP which uses pthreads)
+# so always link against -lpthread on HP-UX if it is available.
+# This check should go after all other libraries tests.
+case "$host_os" in
+ hpux*)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5
+printf %s "checking for main in -lpthread... " >&6; }
+if test ${ac_cv_lib_pthread_main+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+int
+main (void)
+{
+return main ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_pthread_main=yes
+else case e in #(
+ e) ac_cv_lib_pthread_main=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5
+printf "%s\n" "$ac_cv_lib_pthread_main" >&6; }
+if test "x$ac_cv_lib_pthread_main" = xyes
+then :
+ SUDO_LIBS="${SUDO_LIBS} -lpthread"
+fi
+
+ printf "%s\n" "#define _REENTRANT 1" >>confdefs.h
+
+ ;;
+esac
+
+if test "$utmp_style" = "LEGACY"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for utmp file path" >&5
+printf %s "checking for utmp file path... " >&6; }
+if test ${sudo_cv_path_UTMP+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ sudo_cv_path_UTMP=no
+ for p in "/var/run/utmp" "/var/adm/utmp" "/etc/utmp"; do
+ if test -r "$p"; then
+ sudo_cv_path_UTMP="$p"
+ break
+ fi
+ done
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_path_UTMP" >&5
+printf "%s\n" "$sudo_cv_path_UTMP" >&6; }
+ if test X"$sudo_cv_path_UTMP" != X"no"; then
+ cat >>confdefs.h <<EOF
+#define _PATH_UTMP "$sudo_cv_path_UTMP"
+EOF
+
+ fi
+
+fi
+
+ if test "${with_logdir-yes}" != "yes"; then
+ log_dir="$with_logdir"
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for log dir location" >&5
+printf %s "checking for log dir location... " >&6; }
+if test ${sudo_cv_log_dir+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ # Default value of log_dir set in configure.ac
+ sudo_cv_log_dir="$log_dir"
+ for d in /var/log /var/adm /usr/adm; do
+ if test -d "$d"; then
+ sudo_cv_log_dir="$d"
+ break
+ fi
+ done
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_log_dir" >&5
+printf "%s\n" "$sudo_cv_log_dir" >&6; }
+ log_dir="$sudo_cv_log_dir"
+ fi
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDO_LOGDIR "$log_dir"
+EOF
+
+
+
+ if test -n "$with_logpath"; then
+ logpath="$with_logpath"
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for log file location" >&5
+printf %s "checking for log file location... " >&6; }
+if test ${sudo_cv_log_path+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ # Default value of logpath set in configure.ac
+ sudo_cv_log_path="$logpath"
+ for d in /var/log /var/adm /usr/adm; do
+ if test -d "$d"; then
+ sudo_cv_log_path="$d/sudo.log"
+ break
+ fi
+ done
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_log_path" >&5
+printf "%s\n" "$sudo_cv_log_path" >&6; }
+ logpath="$sudo_cv_log_path"
+ fi
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDO_LOGFILE "$logpath"
+EOF
+
+
+
+ if test "${with_relaydir-yes}" != "yes"; then
+ relay_dir="$with_relaydir"
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sudo_logsrvd relay dir location" >&5
+printf %s "checking for sudo_logsrvd relay dir location... " >&6; }
+if test ${sudo_cv_relay_dir+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ # Default value of relay_dir set in configure.ac
+ sudo_cv_relay_dir="$relay_dir"
+ for d in /var/log /var/adm /usr/adm; do
+ if test -d "$d"; then
+ sudo_cv_relay_dir="$d/sudo_logsrvd"
+ break
+ fi
+ done
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_relay_dir" >&5
+printf "%s\n" "$sudo_cv_relay_dir" >&6; }
+ relay_dir="$sudo_cv_relay_dir"
+ fi
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDO_RELAY_DIR "$relay_dir"
+EOF
+
+
+
+ if test -n "$with_rundir"; then
+ rundir="$with_rundir"
+ elif test -n "$runstatedir" && test "$runstatedir" != '${localstatedir}/run'; then
+ rundir="$runstatedir/sudo"
+ else
+ # No --with-rundir or --runstatedir specified
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sudo run dir location" >&5
+printf %s "checking for sudo run dir location... " >&6; }
+if test ${sudo_cv_run_dir+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ sudo_cv_run_dir=no
+ for d in /run /var/run /var/db /var/lib /var/adm /usr/adm; do
+ if test -d "$d"; then
+ sudo_cv_run_dir="$d/sudo"
+ break
+ fi
+ done
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_run_dir" >&5
+printf "%s\n" "$sudo_cv_run_dir" >&6; }
+ rundir="$sudo_cv_run_dir"
+ fi
+ if test X"$rundir" != X"no"; then
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDO_TIMEDIR "$rundir/ts"
+EOF
+
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDO_LOGSRVD_PID "$rundir/sudo_logsrvd.pid"
+EOF
+
+ fi
+
+
+ if test -n "$with_vardir"; then
+ vardir="$with_vardir"
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sudo var dir location" >&5
+printf %s "checking for sudo var dir location... " >&6; }
+if test ${sudo_cv_var_dir+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ sudo_cv_var_dir=no
+ for d in /var/db /var/lib /var/adm /usr/adm; do
+ if test -d "$d"; then
+ sudo_cv_var_dir="$d/sudo"
+ break
+ fi
+ done
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_var_dir" >&5
+printf "%s\n" "$sudo_cv_var_dir" >&6; }
+ vardir="$sudo_cv_var_dir"
+ fi
+ if test X"$vardir" != X"no"; then
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDO_LECTURE_DIR "$vardir/lectured"
+EOF
+
+ fi
+
+
+ if test "${with_iologdir-yes}" != "yes"; then
+ iolog_dir="$with_iologdir"
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for I/O log dir location" >&5
+printf %s "checking for I/O log dir location... " >&6; }
+if test ${sudo_cv_iolog_dir+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ # Default value of iolog_dir set in configure.ac
+ sudo_cv_iolog_dir="$iolog_dir"
+ for d in /var/log /var/adm /usr/adm; do
+ if test -d "$d"; then
+ sudo_cv_iolog_dir="$d/sudo-io"
+ break
+ fi
+ done
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_iolog_dir" >&5
+printf "%s\n" "$sudo_cv_iolog_dir" >&6; }
+ iolog_dir="$sudo_cv_iolog_dir"
+ fi
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDO_IO_LOGDIR "$iolog_dir"
+EOF
+
+
+
+ if test -n "$with_tzdir"; then
+ tzdir="$with_tzdir"
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking time zone data directory" >&5
+printf %s "checking time zone data directory... " >&6; }
+if test ${sudo_cv_tz_dir+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ sudo_cv_tz_dir=no
+ for d in /usr/share /usr/share/lib /usr/lib /etc; do
+ if test -d "$d/zoneinfo"; then
+ sudo_cv_tz_dir="$d/zoneinfo"
+ break
+ fi
+ done
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_tz_dir" >&5
+printf "%s\n" "$sudo_cv_tz_dir" >&6; }
+ tzdir="$sudo_cv_tz_dir"
+ fi
+ if test X"$tzdir" != X"no"; then
+ cat >>confdefs.h <<EOF
+#define _PATH_ZONEINFO "$tzdir"
+EOF
+
+ fi
+
+
+
+ac_c_werror_flag=yes
+
+ac_fn_c_check_header_compile "$LINENO" "sys/sysctl.h" "ac_cv_header_sys_sysctl_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_sysctl_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_SYSCTL_H 1" >>confdefs.h
+
+fi
+
+
+if test -n "$GCC" -a "$lt_cv_prog_gnu_ld" != "yes"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -static-libgcc" >&5
+printf %s "checking whether C compiler accepts -static-libgcc... " >&6; }
+if test ${ax_cv_check_cflags___static_libgcc+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -static-libgcc"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ax_cv_check_cflags___static_libgcc=yes
+else case e in #(
+ e) ax_cv_check_cflags___static_libgcc=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___static_libgcc" >&5
+printf "%s\n" "$ax_cv_check_cflags___static_libgcc" >&6; }
+if test "x$ax_cv_check_cflags___static_libgcc" = xyes
+then :
+
+if test ${LT_LDFLAGS+y}
+then :
+
+ case " $LT_LDFLAGS " in #(
+ *" -Wc,-static-libgcc "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LT_LDFLAGS already contains -Wc,-static-libgcc"; } >&5
+ (: LT_LDFLAGS already contains -Wc,-static-libgcc) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LT_LDFLAGS " -Wc,-static-libgcc"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LT_LDFLAGS=\"\$LT_LDFLAGS\""; } >&5
+ (: LT_LDFLAGS="$LT_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LT_LDFLAGS=-Wc,-static-libgcc
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LT_LDFLAGS=\"\$LT_LDFLAGS\""; } >&5
+ (: LT_LDFLAGS="$LT_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+
+fi
+
+case "$host_os" in
+ netbsd*)
+ ;;
+ *)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,--enable-new-dtags" >&5
+printf %s "checking whether the linker accepts -Wl,--enable-new-dtags... " >&6; }
+if test ${ax_cv_check_ldflags___Wl___enable_new_dtags+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,--enable-new-dtags"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_check_ldflags___Wl___enable_new_dtags=yes
+else case e in #(
+ e) ax_cv_check_ldflags___Wl___enable_new_dtags=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl___enable_new_dtags" >&5
+printf "%s\n" "$ax_cv_check_ldflags___Wl___enable_new_dtags" >&6; }
+if test x"$ax_cv_check_ldflags___Wl___enable_new_dtags" = xyes
+then :
+
+if test ${LDFLAGS+y}
+then :
+
+ case " $LDFLAGS " in #(
+ *" -Wl,--enable-new-dtags "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS already contains -Wl,--enable-new-dtags"; } >&5
+ (: LDFLAGS already contains -Wl,--enable-new-dtags) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append LDFLAGS " -Wl,--enable-new-dtags"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS\""; } >&5
+ (: LDFLAGS="$LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ LDFLAGS=-Wl,--enable-new-dtags
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : LDFLAGS=\"\$LDFLAGS\""; } >&5
+ (: LDFLAGS="$LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ ;;
+esac
+
+
+ if test -n "$GCC"; then
+ if test X"$enable_pie" = X""; then
+ case "$host_os" in
+ linux*)
+ # Attempt to build with PIE support
+ enable_pie="maybe"
+ ;;
+ esac
+ fi
+ if test X"$enable_pie" != X""; then
+ if test "$enable_pie" = "no"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fno-pie" >&5
+printf %s "checking whether C compiler accepts -fno-pie... " >&6; }
+if test ${ax_cv_check_cflags___fno_pie+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -fno-pie"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ax_cv_check_cflags___fno_pie=yes
+else case e in #(
+ e) ax_cv_check_cflags___fno_pie=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fno_pie" >&5
+printf "%s\n" "$ax_cv_check_cflags___fno_pie" >&6; }
+if test "x$ax_cv_check_cflags___fno_pie" = xyes
+then :
+
+ _CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fno-pie"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -nopie" >&5
+printf %s "checking whether the linker accepts -nopie... " >&6; }
+if test ${ax_cv_check_ldflags___nopie+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -nopie"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_check_ldflags___nopie=yes
+else case e in #(
+ e) ax_cv_check_ldflags___nopie=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___nopie" >&5
+printf "%s\n" "$ax_cv_check_ldflags___nopie" >&6; }
+if test x"$ax_cv_check_ldflags___nopie" = xyes
+then :
+
+ PIE_CFLAGS="-fno-pie"
+ PIE_LDFLAGS="-nopie"
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ CFLAGS="$_CFLAGS"
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fPIE" >&5
+printf %s "checking whether C compiler accepts -fPIE... " >&6; }
+if test ${ax_cv_check_cflags___fPIE+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -fPIE"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ax_cv_check_cflags___fPIE=yes
+else case e in #(
+ e) ax_cv_check_cflags___fPIE=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fPIE" >&5
+printf "%s\n" "$ax_cv_check_cflags___fPIE" >&6; }
+if test "x$ax_cv_check_cflags___fPIE" = xyes
+then :
+
+ _CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fPIE"
+ _LDFLAGS="$LDFLAGS"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -pie" >&5
+printf %s "checking whether the linker accepts -pie... " >&6; }
+if test ${ax_cv_check_ldflags___pie+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -pie"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_check_ldflags___pie=yes
+else case e in #(
+ e) ax_cv_check_ldflags___pie=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___pie" >&5
+printf "%s\n" "$ax_cv_check_ldflags___pie" >&6; }
+if test x"$ax_cv_check_ldflags___pie" = xyes
+then :
+
+ if test "$enable_pie" = "maybe"; then
+ LDFLAGS="$LDFLAGS -pie"
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working PIE support" >&5
+printf %s "checking for working PIE support... " >&6; }
+if test ${sudo_cv_working_pie+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ if test "$cross_compiling" = yes
+then :
+ sudo_cv_working_pie=no
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int main() { char *p = malloc(1024); if (p == NULL) return 1; memset(p, 0, 1024); return 0; }
+_ACEOF
+if ac_fn_c_try_run "$LINENO"
+then :
+ sudo_cv_working_pie=yes
+else case e in #(
+ e) sudo_cv_working_pie=no ;;
+esac
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_working_pie" >&5
+printf "%s\n" "$sudo_cv_working_pie" >&6; }
+ if test $sudo_cv_working_pie = yes
+then :
+ enable_pie=yes
+fi
+
+ fi
+ if test "$enable_pie" = "yes"; then
+ PIE_CFLAGS="-fPIE"
+ PIE_LDFLAGS="-Wc,-fPIE -pie"
+ fi
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ CFLAGS="$_CFLAGS"
+ LDFLAGS="$_LDFLAGS"
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ fi
+ fi
+ fi
+ if test X"$enable_pie" != X"no" -a X"$with_gnu_ld" = X"no"; then
+ # Solaris 11.1 and higher ld supports PIE executables, ASLR,
+ # non-executable stack and non-executable heap.
+ case "$host_os" in
+ solaris2.1[1-9]|solaris2.[2-9][0-9])
+ # This assumes lt_prog_compiler_pic is a single flag,
+ # which is the case on Solaris.
+ if test -n "$lt_prog_compiler_pic"; then
+ _CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $lt_prog_compiler_pic"
+ _LDFLAGS="$LDFLAGS"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,-ztype=pie" >&5
+printf %s "checking whether the linker accepts -Wl,-ztype=pie... " >&6; }
+if test ${ax_cv_check_ldflags___Wl__ztype_pie+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-ztype=pie"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_check_ldflags___Wl__ztype_pie=yes
+else case e in #(
+ e) ax_cv_check_ldflags___Wl__ztype_pie=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl__ztype_pie" >&5
+printf "%s\n" "$ax_cv_check_ldflags___Wl__ztype_pie" >&6; }
+if test x"$ax_cv_check_ldflags___Wl__ztype_pie" = xyes
+then :
+
+ # Try building PIE if not disabled.
+ if test X"$enable_pie" = X""; then
+ LDFLAGS="$LDFLAGS -Wl,-ztype=pie"
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working PIE support" >&5
+printf %s "checking for working PIE support... " >&6; }
+if test ${sudo_cv_working_pie+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ if test "$cross_compiling" = yes
+then :
+ sudo_cv_working_pie=no
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int main() { char *p = malloc(1024); if (p == NULL) return 1; memset(p, 0, 1024); return 0; }
+_ACEOF
+if ac_fn_c_try_run "$LINENO"
+then :
+ sudo_cv_working_pie=yes
+else case e in #(
+ e) sudo_cv_working_pie=no ;;
+esac
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+esac
+fi
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_working_pie" >&5
+printf "%s\n" "$sudo_cv_working_pie" >&6; }
+ if test $sudo_cv_working_pie = yes
+then :
+ enable_pie=yes
+fi
+
+ fi
+ if test "$enable_pie" = "yes"; then
+ PIE_CFLAGS="$lt_prog_compiler_pic"
+ PIE_LDFLAGS="-Wc,$lt_prog_compiler_pic -Wl,-ztype=pie"
+ fi
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ CFLAGS="$_CFLAGS"
+ LDFLAGS="$_LDFLAGS"
+ fi
+ # These flags are only valid when linking an executable
+ # so we cannot add them to HARDENING_LDFLAGS.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,-zaslr" >&5
+printf %s "checking whether the linker accepts -Wl,-zaslr... " >&6; }
+if test ${ax_cv_check_ldflags___Wl__zaslr+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-zaslr"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_check_ldflags___Wl__zaslr=yes
+else case e in #(
+ e) ax_cv_check_ldflags___Wl__zaslr=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl__zaslr" >&5
+printf "%s\n" "$ax_cv_check_ldflags___Wl__zaslr" >&6; }
+if test x"$ax_cv_check_ldflags___Wl__zaslr" = xyes
+then :
+
+
+if test ${PIE_LDFLAGS+y}
+then :
+
+ case " $PIE_LDFLAGS " in #(
+ *" -Wl,-zaslr "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : PIE_LDFLAGS already contains -Wl,-zaslr"; } >&5
+ (: PIE_LDFLAGS already contains -Wl,-zaslr) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append PIE_LDFLAGS " -Wl,-zaslr"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : PIE_LDFLAGS=\"\$PIE_LDFLAGS\""; } >&5
+ (: PIE_LDFLAGS="$PIE_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ PIE_LDFLAGS=-Wl,-zaslr
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : PIE_LDFLAGS=\"\$PIE_LDFLAGS\""; } >&5
+ (: PIE_LDFLAGS="$PIE_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,-znxheap" >&5
+printf %s "checking whether the linker accepts -Wl,-znxheap... " >&6; }
+if test ${ax_cv_check_ldflags___Wl__znxheap+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-znxheap"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_check_ldflags___Wl__znxheap=yes
+else case e in #(
+ e) ax_cv_check_ldflags___Wl__znxheap=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl__znxheap" >&5
+printf "%s\n" "$ax_cv_check_ldflags___Wl__znxheap" >&6; }
+if test x"$ax_cv_check_ldflags___Wl__znxheap" = xyes
+then :
+
+
+if test ${PIE_LDFLAGS+y}
+then :
+
+ case " $PIE_LDFLAGS " in #(
+ *" -Wl,-znxheap "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : PIE_LDFLAGS already contains -Wl,-znxheap"; } >&5
+ (: PIE_LDFLAGS already contains -Wl,-znxheap) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append PIE_LDFLAGS " -Wl,-znxheap"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : PIE_LDFLAGS=\"\$PIE_LDFLAGS\""; } >&5
+ (: PIE_LDFLAGS="$PIE_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ PIE_LDFLAGS=-Wl,-znxheap
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : PIE_LDFLAGS=\"\$PIE_LDFLAGS\""; } >&5
+ (: PIE_LDFLAGS="$PIE_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,-znxstack" >&5
+printf %s "checking whether the linker accepts -Wl,-znxstack... " >&6; }
+if test ${ax_cv_check_ldflags___Wl__znxstack+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-znxstack"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_check_ldflags___Wl__znxstack=yes
+else case e in #(
+ e) ax_cv_check_ldflags___Wl__znxstack=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl__znxstack" >&5
+printf "%s\n" "$ax_cv_check_ldflags___Wl__znxstack" >&6; }
+if test x"$ax_cv_check_ldflags___Wl__znxstack" = xyes
+then :
+
+
+if test ${PIE_LDFLAGS+y}
+then :
+
+ case " $PIE_LDFLAGS " in #(
+ *" -Wl,-znxstack "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : PIE_LDFLAGS already contains -Wl,-znxstack"; } >&5
+ (: PIE_LDFLAGS already contains -Wl,-znxstack) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append PIE_LDFLAGS " -Wl,-znxstack"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : PIE_LDFLAGS=\"\$PIE_LDFLAGS\""; } >&5
+ (: PIE_LDFLAGS="$PIE_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ PIE_LDFLAGS=-Wl,-znxstack
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : PIE_LDFLAGS=\"\$PIE_LDFLAGS\""; } >&5
+ (: PIE_LDFLAGS="$PIE_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ ;;
+ esac
+ fi
+
+
+ if test -n "$GCC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fvisibility=hidden" >&5
+printf %s "checking whether C compiler accepts -fvisibility=hidden... " >&6; }
+if test ${ax_cv_check_cflags___fvisibility_hidden+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -fvisibility=hidden"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ax_cv_check_cflags___fvisibility_hidden=yes
+else case e in #(
+ e) ax_cv_check_cflags___fvisibility_hidden=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fvisibility_hidden" >&5
+printf "%s\n" "$ax_cv_check_cflags___fvisibility_hidden" >&6; }
+if test "x$ax_cv_check_cflags___fvisibility_hidden" = xyes
+then :
+
+ printf "%s\n" "#define HAVE_DSO_VISIBILITY 1" >>confdefs.h
+
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -fvisibility=hidden "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -fvisibility=hidden"; } >&5
+ (: CFLAGS already contains -fvisibility=hidden) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -fvisibility=hidden"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-fvisibility=hidden
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ LT_LDEXPORTS=
+ LT_LDDEP=
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ else
+ case "$host_os" in
+ hpux*)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Bhidden_def" >&5
+printf %s "checking whether C compiler accepts -Bhidden_def... " >&6; }
+if test ${ax_cv_check_cflags___Bhidden_def+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -Bhidden_def"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ax_cv_check_cflags___Bhidden_def=yes
+else case e in #(
+ e) ax_cv_check_cflags___Bhidden_def=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Bhidden_def" >&5
+printf "%s\n" "$ax_cv_check_cflags___Bhidden_def" >&6; }
+if test "x$ax_cv_check_cflags___Bhidden_def" = xyes
+then :
+
+ # HP-UX cc may not allow __declspec(dllexport) to be
+ # used in conjunction with #pragma HP_DEFINED_EXTERNAL
+ # when redefining standard libc functions.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether __declspec(dllexport) can be used when overriding libc functions" >&5
+printf %s "checking whether __declspec(dllexport) can be used when overriding libc functions... " >&6; }
+if test ${sudo_cv_var_hpux_declspec_libc_function+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ _CFLAGS="$CFLAGS"
+ CFLAGS="${CFLAGS} -Bhidden_def"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+ __declspec(dllexport) char * getenv(const char *n) { return NULL; }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+ sudo_cv_var_hpux_declspec_libc_function=yes
+
+else case e in #(
+ e)
+ sudo_cv_var_hpux_declspec_libc_function=no
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS="$_CFLAGS"
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_var_hpux_declspec_libc_function" >&5
+printf "%s\n" "$sudo_cv_var_hpux_declspec_libc_function" >&6; }
+ if test "$sudo_cv_var_hpux_declspec_libc_function" = "yes"; then
+ printf "%s\n" "#define HAVE_DSO_VISIBILITY 1" >>confdefs.h
+
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -Bhidden_def "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Bhidden_def"; } >&5
+ (: CFLAGS already contains -Bhidden_def) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -Bhidden_def"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-Bhidden_def
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ LT_LDEXPORTS=
+ LT_LDDEP=
+ fi
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ ;;
+ solaris2*)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -xldscope=hidden" >&5
+printf %s "checking whether C compiler accepts -xldscope=hidden... " >&6; }
+if test ${ax_cv_check_cflags___xldscope_hidden+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -xldscope=hidden"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ax_cv_check_cflags___xldscope_hidden=yes
+else case e in #(
+ e) ax_cv_check_cflags___xldscope_hidden=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___xldscope_hidden" >&5
+printf "%s\n" "$ax_cv_check_cflags___xldscope_hidden" >&6; }
+if test "x$ax_cv_check_cflags___xldscope_hidden" = xyes
+then :
+
+ printf "%s\n" "#define HAVE_DSO_VISIBILITY 1" >>confdefs.h
+
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -xldscope=hidden "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -xldscope=hidden"; } >&5
+ (: CFLAGS already contains -xldscope=hidden) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -xldscope=hidden"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-xldscope=hidden
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ LT_LDEXPORTS=
+ LT_LDDEP=
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ ;;
+ esac
+ fi
+
+ if test "$lt_cv_prog_gnu_ld" = "yes"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ld supports anonymous map files" >&5
+printf %s "checking whether ld supports anonymous map files... " >&6; }
+if test ${sudo_cv_var_gnu_ld_anon_map+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ sudo_cv_var_gnu_ld_anon_map=no
+ cat > conftest.map <<-EOF
+ {
+ global: foo;
+ local: *;
+ };
+ EOF
+ _CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $lt_prog_compiler_pic"
+ _LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_prog_compiler_pic -shared -Wl,--version-script,./conftest.map"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int foo;
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ sudo_cv_var_gnu_ld_anon_map=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ CFLAGS="$_CFLAGS"
+ LDFLAGS="$_LDFLAGS"
+ rm -f conftest.map
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_var_gnu_ld_anon_map" >&5
+printf "%s\n" "$sudo_cv_var_gnu_ld_anon_map" >&6; }
+ if test "$sudo_cv_var_gnu_ld_anon_map" = "yes"; then
+ LT_LDDEP="\$(shlib_map)"; LT_LDEXPORTS="-Wl,--version-script,\$(shlib_map)"
+ fi
+ else
+ case "$host_os" in
+ solaris2*)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ld supports anonymous map files" >&5
+printf %s "checking whether ld supports anonymous map files... " >&6; }
+if test ${sudo_cv_var_solaris_ld_anon_map+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ sudo_cv_var_solaris_ld_anon_map=no
+ cat > conftest.map <<-EOF
+ {
+ global: foo;
+ local: *;
+ };
+ EOF
+ _CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $lt_prog_compiler_pic"
+ _LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS -shared -Wl,-M,./conftest.map"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int foo;
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ sudo_cv_var_solaris_ld_anon_map=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ CFLAGS="$_CFLAGS"
+ LDFLAGS="$_LDFLAGS"
+ rm -f conftest.map
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_var_solaris_ld_anon_map" >&5
+printf "%s\n" "$sudo_cv_var_solaris_ld_anon_map" >&6; }
+ if test "$sudo_cv_var_solaris_ld_anon_map" = "yes"; then
+ LT_LDDEP="\$(shlib_map)"; LT_LDEXPORTS="-Wl,-M,\$(shlib_map)"
+ fi
+ ;;
+ hpux*)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ld supports controlling exported symbols" >&5
+printf %s "checking whether ld supports controlling exported symbols... " >&6; }
+if test ${sudo_cv_var_hpux_ld_symbol_export+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ sudo_cv_var_hpux_ld_symbol_export=no
+ echo "+e foo" > conftest.opt
+ _CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $lt_prog_compiler_pic"
+ _LDFLAGS="$LDFLAGS"
+ if test -n "$GCC"; then
+ LDFLAGS="$LDFLAGS -shared -Wl,-c,./conftest.opt"
+ else
+ LDFLAGS="$LDFLAGS -b -Wl,-c,./conftest.opt"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int foo;
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ sudo_cv_var_hpux_ld_symbol_export=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ CFLAGS="$_CFLAGS"
+ LDFLAGS="$_LDFLAGS"
+ rm -f conftest.opt
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_var_hpux_ld_symbol_export" >&5
+printf "%s\n" "$sudo_cv_var_hpux_ld_symbol_export" >&6; }
+ if test "$sudo_cv_var_hpux_ld_symbol_export" = "yes"; then
+ LT_LDDEP="\$(shlib_opt)"; LT_LDEXPORTS="-Wl,-c,\$(shlib_opt)"
+ fi
+ ;;
+ esac
+ fi
+
+
+ if test X"${enable_sanitizer}{enable_fuzzer}" != X"nono"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,--allow-multiple-definition" >&5
+printf %s "checking whether the linker accepts -Wl,--allow-multiple-definition... " >&6; }
+if test ${ax_cv_check_ldflags___Wl___allow_multiple_definition+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,--allow-multiple-definition"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_check_ldflags___Wl___allow_multiple_definition=yes
+else case e in #(
+ e) ax_cv_check_ldflags___Wl___allow_multiple_definition=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl___allow_multiple_definition" >&5
+printf "%s\n" "$ax_cv_check_ldflags___Wl___allow_multiple_definition" >&6; }
+if test x"$ax_cv_check_ldflags___Wl___allow_multiple_definition" = xyes
+then :
+
+if test ${ASAN_LDFLAGS+y}
+then :
+
+ case " $ASAN_LDFLAGS " in #(
+ *" -Wl,--allow-multiple-definition "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_LDFLAGS already contains -Wl,--allow-multiple-definition"; } >&5
+ (: ASAN_LDFLAGS already contains -Wl,--allow-multiple-definition) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append ASAN_LDFLAGS " -Wl,--allow-multiple-definition"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_LDFLAGS=\"\$ASAN_LDFLAGS\""; } >&5
+ (: ASAN_LDFLAGS="$ASAN_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ ASAN_LDFLAGS=-Wl,--allow-multiple-definition
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_LDFLAGS=\"\$ASAN_LDFLAGS\""; } >&5
+ (: ASAN_LDFLAGS="$ASAN_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ fi
+
+ if test X"$enable_sanitizer" != X"no"; then
+ as_CACHEVAR=`printf "%s\n" "ax_cv_check_cflags__$enable_sanitizer" | sed "$as_sed_sh"`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $enable_sanitizer" >&5
+printf %s "checking whether C compiler accepts $enable_sanitizer... " >&6; }
+if eval test \${$as_CACHEVAR+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS $enable_sanitizer"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ eval "$as_CACHEVAR=yes"
+else case e in #(
+ e) eval "$as_CACHEVAR=no" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags ;;
+esac
+fi
+eval ac_res=\$$as_CACHEVAR
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"
+then :
+
+
+if test ${ASAN_CFLAGS+y}
+then :
+
+ case " $ASAN_CFLAGS " in #(
+ *" $enable_sanitizer "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_CFLAGS already contains \$enable_sanitizer"; } >&5
+ (: ASAN_CFLAGS already contains $enable_sanitizer) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append ASAN_CFLAGS " $enable_sanitizer"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_CFLAGS=\"\$ASAN_CFLAGS\""; } >&5
+ (: ASAN_CFLAGS="$ASAN_CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ ASAN_CFLAGS=$enable_sanitizer
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_CFLAGS=\"\$ASAN_CFLAGS\""; } >&5
+ (: ASAN_CFLAGS="$ASAN_CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+if test ${ASAN_LDFLAGS+y}
+then :
+
+ case " $ASAN_LDFLAGS " in #(
+ *" -XCClinker "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_LDFLAGS already contains -XCClinker"; } >&5
+ (: ASAN_LDFLAGS already contains -XCClinker) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append ASAN_LDFLAGS " -XCClinker"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_LDFLAGS=\"\$ASAN_LDFLAGS\""; } >&5
+ (: ASAN_LDFLAGS="$ASAN_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ ASAN_LDFLAGS=-XCClinker
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_LDFLAGS=\"\$ASAN_LDFLAGS\""; } >&5
+ (: ASAN_LDFLAGS="$ASAN_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+if test ${ASAN_LDFLAGS+y}
+then :
+
+ case " $ASAN_LDFLAGS " in #(
+ *" $enable_sanitizer "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_LDFLAGS already contains \$enable_sanitizer"; } >&5
+ (: ASAN_LDFLAGS already contains $enable_sanitizer) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append ASAN_LDFLAGS " $enable_sanitizer"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_LDFLAGS=\"\$ASAN_LDFLAGS\""; } >&5
+ (: ASAN_LDFLAGS="$ASAN_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ ASAN_LDFLAGS=$enable_sanitizer
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_LDFLAGS=\"\$ASAN_LDFLAGS\""; } >&5
+ (: ASAN_LDFLAGS="$ASAN_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fno-omit-frame-pointer" >&5
+printf %s "checking whether C compiler accepts -fno-omit-frame-pointer... " >&6; }
+if test ${ax_cv_check_cflags___fno_omit_frame_pointer+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -fno-omit-frame-pointer"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ax_cv_check_cflags___fno_omit_frame_pointer=yes
+else case e in #(
+ e) ax_cv_check_cflags___fno_omit_frame_pointer=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fno_omit_frame_pointer" >&5
+printf "%s\n" "$ax_cv_check_cflags___fno_omit_frame_pointer" >&6; }
+if test "x$ax_cv_check_cflags___fno_omit_frame_pointer" = xyes
+then :
+
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -fno-omit-frame-pointer "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -fno-omit-frame-pointer"; } >&5
+ (: CFLAGS already contains -fno-omit-frame-pointer) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -fno-omit-frame-pointer"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-fno-omit-frame-pointer
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ printf "%s\n" "#define NO_LEAKS 1" >>confdefs.h
+
+ case `$CC --version 2>&1` in
+ *gcc*)
+ libasan=`$CC -print-file-name=libasan.so 2>/dev/null`
+ if test -n "$libasan" -a X"$libasan" != X"libasan.so"; then
+ # libasan.so may be a linker script
+ libasan="`awk 'BEGIN {lib=ARGV[1]} /^INPUT/ {lib=$3} END {print lib}' \"$libasan\"`"
+ cat >>confdefs.h <<EOF
+#define _PATH_ASAN_LIB "$libasan"
+EOF
+
+ fi
+ ;;
+ esac
+
+else case e in #(
+ e)
+ as_fn_error $? "$CC does not support the $enable_sanitizer flag" "$LINENO" 5
+ ;;
+esac
+fi
+
+ fi
+
+ if test X"$enable_fuzzer" = X"yes"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fsanitize=fuzzer-no-link" >&5
+printf %s "checking whether C compiler accepts -fsanitize=fuzzer-no-link... " >&6; }
+if test ${ax_cv_check_cflags___fsanitize_fuzzer_no_link+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -fsanitize=fuzzer-no-link"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ax_cv_check_cflags___fsanitize_fuzzer_no_link=yes
+else case e in #(
+ e) ax_cv_check_cflags___fsanitize_fuzzer_no_link=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fsanitize_fuzzer_no_link" >&5
+printf "%s\n" "$ax_cv_check_cflags___fsanitize_fuzzer_no_link" >&6; }
+if test "x$ax_cv_check_cflags___fsanitize_fuzzer_no_link" = xyes
+then :
+
+
+if test ${ASAN_CFLAGS+y}
+then :
+
+ case " $ASAN_CFLAGS " in #(
+ *" -fsanitize=fuzzer-no-link "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_CFLAGS already contains -fsanitize=fuzzer-no-link"; } >&5
+ (: ASAN_CFLAGS already contains -fsanitize=fuzzer-no-link) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append ASAN_CFLAGS " -fsanitize=fuzzer-no-link"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_CFLAGS=\"\$ASAN_CFLAGS\""; } >&5
+ (: ASAN_CFLAGS="$ASAN_CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ ASAN_CFLAGS=-fsanitize=fuzzer-no-link
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_CFLAGS=\"\$ASAN_CFLAGS\""; } >&5
+ (: ASAN_CFLAGS="$ASAN_CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+if test ${ASAN_LDFLAGS+y}
+then :
+
+ case " $ASAN_LDFLAGS " in #(
+ *" -XCClinker "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_LDFLAGS already contains -XCClinker"; } >&5
+ (: ASAN_LDFLAGS already contains -XCClinker) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append ASAN_LDFLAGS " -XCClinker"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_LDFLAGS=\"\$ASAN_LDFLAGS\""; } >&5
+ (: ASAN_LDFLAGS="$ASAN_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ ASAN_LDFLAGS=-XCClinker
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_LDFLAGS=\"\$ASAN_LDFLAGS\""; } >&5
+ (: ASAN_LDFLAGS="$ASAN_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+if test ${ASAN_LDFLAGS+y}
+then :
+
+ case " $ASAN_LDFLAGS " in #(
+ *" -fsanitize=fuzzer-no-link "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_LDFLAGS already contains -fsanitize=fuzzer-no-link"; } >&5
+ (: ASAN_LDFLAGS already contains -fsanitize=fuzzer-no-link) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append ASAN_LDFLAGS " -fsanitize=fuzzer-no-link"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_LDFLAGS=\"\$ASAN_LDFLAGS\""; } >&5
+ (: ASAN_LDFLAGS="$ASAN_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ ASAN_LDFLAGS=-fsanitize=fuzzer-no-link
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : ASAN_LDFLAGS=\"\$ASAN_LDFLAGS\""; } >&5
+ (: ASAN_LDFLAGS="$ASAN_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ if test -z "$FUZZ_ENGINE"; then
+ FUZZ_ENGINE="-fsanitize=fuzzer"
+ fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fno-omit-frame-pointer" >&5
+printf %s "checking whether C compiler accepts -fno-omit-frame-pointer... " >&6; }
+if test ${ax_cv_check_cflags___fno_omit_frame_pointer+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -fno-omit-frame-pointer"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ax_cv_check_cflags___fno_omit_frame_pointer=yes
+else case e in #(
+ e) ax_cv_check_cflags___fno_omit_frame_pointer=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fno_omit_frame_pointer" >&5
+printf "%s\n" "$ax_cv_check_cflags___fno_omit_frame_pointer" >&6; }
+if test "x$ax_cv_check_cflags___fno_omit_frame_pointer" = xyes
+then :
+
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -fno-omit-frame-pointer "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -fno-omit-frame-pointer"; } >&5
+ (: CFLAGS already contains -fno-omit-frame-pointer) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -fno-omit-frame-pointer"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-fno-omit-frame-pointer
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ # Use CFLAGS, not CPPFLAGS to match oss-fuzz behavior
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION"; } >&5
+ (: CFLAGS already contains -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ printf "%s\n" "#define NO_LEAKS 1" >>confdefs.h
+
+
+else case e in #(
+ e)
+ as_fn_error $? "$CC does not support the -fsanitize=fuzzer-no-link flag" "$LINENO" 5
+ ;;
+esac
+fi
+
+ else
+ # Not using compiler fuzzing support, link with stub library.
+ FUZZ_ENGINE='$(top_builddir)/lib/fuzzstub/libsudo_fuzzstub.la'
+ fi
+
+
+ if test "$enable_hardening" != "no"; then
+ #
+ # Attempt to use _FORTIFY_SOURCE with sprintf. If the headers support
+ # it but libc does not, __sprintf_chk should be an undefined symbol.
+ #
+ O_CPPFLAGS="$CPPFLAGS"
+
+if test ${CPPFLAGS+y}
+then :
+
+ case " $CPPFLAGS " in #(
+ *" -D_FORTIFY_SOURCE=2 "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS already contains -D_FORTIFY_SOURCE=2"; } >&5
+ (: CPPFLAGS already contains -D_FORTIFY_SOURCE=2) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CPPFLAGS " -D_FORTIFY_SOURCE=2"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CPPFLAGS=-D_FORTIFY_SOURCE=2
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CPPFLAGS=\"\$CPPFLAGS\""; } >&5
+ (: CPPFLAGS="$CPPFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether _FORTIFY_SOURCE may be specified" >&5
+printf %s "checking whether _FORTIFY_SOURCE may be specified... " >&6; }
+if test ${sudo_cv_use_fortify_source+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <stdio.h>
+int
+main (void)
+{
+char buf[4]; sprintf(buf, "%s", "foo"); return buf[0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ sudo_cv_use_fortify_source=yes
+else case e in #(
+ e) sudo_cv_use_fortify_source=no
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_use_fortify_source" >&5
+printf "%s\n" "$sudo_cv_use_fortify_source" >&6; }
+ if test "$sudo_cv_use_fortify_source" != yes; then
+ CPPFLAGS="$O_CPPFLAGS"
+ fi
+
+ if test -n "$GCC" -a "$enable_ssp" != "no"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for compiler stack protector support" >&5
+printf %s "checking for compiler stack protector support... " >&6; }
+if test ${sudo_cv_var_stack_protector+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ # Avoid CFLAGS since the compiler might optimize away our
+ # test. We don't want CPPFLAGS or LIBS to interfere with
+ # the test but keep LDFLAGS as it may have an rpath needed
+ # to find the ssp lib.
+ _CPPFLAGS="$CPPFLAGS"
+ _CFLAGS="$CFLAGS"
+ _LDFLAGS="$LDFLAGS"
+ _LIBS="$LIBS"
+ CPPFLAGS=
+ LIBS=
+
+ sudo_cv_var_stack_protector="-fstack-protector-strong"
+ CFLAGS="$sudo_cv_var_stack_protector"
+ LDFLAGS="$_LDFLAGS $sudo_cv_var_stack_protector"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ $ac_includes_default
+int
+main (void)
+{
+char buf[1024]; buf[1023] = '\0';
+ ;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+
+else case e in #(
+ e)
+ sudo_cv_var_stack_protector="-fstack-protector-all"
+ CFLAGS="$sudo_cv_var_stack_protector"
+ LDFLAGS="$_LDFLAGS $sudo_cv_var_stack_protector"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ $ac_includes_default
+int
+main (void)
+{
+char buf[1024]; buf[1023] = '\0';
+ ;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+
+else case e in #(
+ e)
+ sudo_cv_var_stack_protector="-fstack-protector"
+ CFLAGS="$sudo_cv_var_stack_protector"
+ LDFLAGS="$_LDFLAGS $sudo_cv_var_stack_protector"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ $ac_includes_default
+int
+main (void)
+{
+char buf[1024]; buf[1023] = '\0';
+ ;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+
+else case e in #(
+ e)
+ sudo_cv_var_stack_protector=no
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ CPPFLAGS="$_CPPFLAGS"
+ CFLAGS="$_CFLAGS"
+ LDFLAGS="$_LDFLAGS"
+ LIBS="$_LIBS"
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_var_stack_protector" >&5
+printf "%s\n" "$sudo_cv_var_stack_protector" >&6; }
+ if test X"$sudo_cv_var_stack_protector" != X"no"; then
+ HARDENING_CFLAGS="$sudo_cv_var_stack_protector"
+ HARDENING_LDFLAGS="-Wc,$sudo_cv_var_stack_protector"
+ fi
+ fi
+
+ # The gcc front-end may accept -fstack-clash-protection even if the
+ # machine-specific code does not support it. We use a test program
+ # with a large stack allocation to try to cause the compiler to
+ # insert the stack clash protection code, or fail if not supported.
+ if test -n "$GCC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler supports -fstack-clash-protection" >&5
+printf %s "checking whether C compiler supports -fstack-clash-protection... " >&6; }
+if test ${sudo_cv_check_cflags___fstack_clash_protection+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ _CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fstack-clash-protection"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ int main(int argc, char *argv[]) { char buf[16384], *src = argv[0], *dst = buf; while ((*dst++ = *src++) != '\0') { continue; } return buf[argc]; }
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ sudo_cv_check_cflags___fstack_clash_protection=yes
+else case e in #(
+ e) sudo_cv_check_cflags___fstack_clash_protection=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS="$_CFLAGS"
+
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_check_cflags___fstack_clash_protection" >&5
+printf "%s\n" "$sudo_cv_check_cflags___fstack_clash_protection" >&6; }
+ if test X"$sudo_cv_check_cflags___fstack_clash_protection" = X"yes"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -fstack-clash-protection" >&5
+printf %s "checking whether the linker accepts -fstack-clash-protection... " >&6; }
+if test ${ax_cv_check_ldflags___fstack_clash_protection+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -fstack-clash-protection"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_check_ldflags___fstack_clash_protection=yes
+else case e in #(
+ e) ax_cv_check_ldflags___fstack_clash_protection=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___fstack_clash_protection" >&5
+printf "%s\n" "$ax_cv_check_ldflags___fstack_clash_protection" >&6; }
+if test x"$ax_cv_check_ldflags___fstack_clash_protection" = xyes
+then :
+
+
+if test ${HARDENING_CFLAGS+y}
+then :
+
+ case " $HARDENING_CFLAGS " in #(
+ *" -fstack-clash-protection "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_CFLAGS already contains -fstack-clash-protection"; } >&5
+ (: HARDENING_CFLAGS already contains -fstack-clash-protection) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append HARDENING_CFLAGS " -fstack-clash-protection"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_CFLAGS=\"\$HARDENING_CFLAGS\""; } >&5
+ (: HARDENING_CFLAGS="$HARDENING_CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ HARDENING_CFLAGS=-fstack-clash-protection
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_CFLAGS=\"\$HARDENING_CFLAGS\""; } >&5
+ (: HARDENING_CFLAGS="$HARDENING_CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+if test ${HARDENING_LDFLAGS+y}
+then :
+
+ case " $HARDENING_LDFLAGS " in #(
+ *" -Wc,-fstack-clash-protection "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_LDFLAGS already contains -Wc,-fstack-clash-protection"; } >&5
+ (: HARDENING_LDFLAGS already contains -Wc,-fstack-clash-protection) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append HARDENING_LDFLAGS " -Wc,-fstack-clash-protection"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_LDFLAGS=\"\$HARDENING_LDFLAGS\""; } >&5
+ (: HARDENING_LDFLAGS="$HARDENING_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ HARDENING_LDFLAGS=-Wc,-fstack-clash-protection
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_LDFLAGS=\"\$HARDENING_LDFLAGS\""; } >&5
+ (: HARDENING_LDFLAGS="$HARDENING_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ fi
+
+ # Check for control-flow transfer instrumentation (Intel CET).
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fcf-protection" >&5
+printf %s "checking whether C compiler accepts -fcf-protection... " >&6; }
+if test ${ax_cv_check_cflags___fcf_protection+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -fcf-protection"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ax_cv_check_cflags___fcf_protection=yes
+else case e in #(
+ e) ax_cv_check_cflags___fcf_protection=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fcf_protection" >&5
+printf "%s\n" "$ax_cv_check_cflags___fcf_protection" >&6; }
+if test "x$ax_cv_check_cflags___fcf_protection" = xyes
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -fcf-protection" >&5
+printf %s "checking whether the linker accepts -fcf-protection... " >&6; }
+if test ${ax_cv_check_ldflags___fcf_protection+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -fcf-protection"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_check_ldflags___fcf_protection=yes
+else case e in #(
+ e) ax_cv_check_ldflags___fcf_protection=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___fcf_protection" >&5
+printf "%s\n" "$ax_cv_check_ldflags___fcf_protection" >&6; }
+if test x"$ax_cv_check_ldflags___fcf_protection" = xyes
+then :
+
+
+if test ${HARDENING_CFLAGS+y}
+then :
+
+ case " $HARDENING_CFLAGS " in #(
+ *" -fcf-protection "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_CFLAGS already contains -fcf-protection"; } >&5
+ (: HARDENING_CFLAGS already contains -fcf-protection) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append HARDENING_CFLAGS " -fcf-protection"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_CFLAGS=\"\$HARDENING_CFLAGS\""; } >&5
+ (: HARDENING_CFLAGS="$HARDENING_CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ HARDENING_CFLAGS=-fcf-protection
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_CFLAGS=\"\$HARDENING_CFLAGS\""; } >&5
+ (: HARDENING_CFLAGS="$HARDENING_CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+if test ${HARDENING_LDFLAGS+y}
+then :
+
+ case " $HARDENING_LDFLAGS " in #(
+ *" -Wc,-fcf-protection "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_LDFLAGS already contains -Wc,-fcf-protection"; } >&5
+ (: HARDENING_LDFLAGS already contains -Wc,-fcf-protection) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append HARDENING_LDFLAGS " -Wc,-fcf-protection"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_LDFLAGS=\"\$HARDENING_LDFLAGS\""; } >&5
+ (: HARDENING_LDFLAGS="$HARDENING_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ HARDENING_LDFLAGS=-Wc,-fcf-protection
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_LDFLAGS=\"\$HARDENING_LDFLAGS\""; } >&5
+ (: HARDENING_LDFLAGS="$HARDENING_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ fi
+
+ # Linker-specific hardening flags.
+ if test X"$with_gnu_ld" = X"yes"; then
+ # GNU ld, and similar (gold, lld, etc).
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,-z,relro" >&5
+printf %s "checking whether the linker accepts -Wl,-z,relro... " >&6; }
+if test ${ax_cv_check_ldflags___Wl__z_relro+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-z,relro"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_check_ldflags___Wl__z_relro=yes
+else case e in #(
+ e) ax_cv_check_ldflags___Wl__z_relro=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl__z_relro" >&5
+printf "%s\n" "$ax_cv_check_ldflags___Wl__z_relro" >&6; }
+if test x"$ax_cv_check_ldflags___Wl__z_relro" = xyes
+then :
+
+if test ${HARDENING_LDFLAGS+y}
+then :
+
+ case " $HARDENING_LDFLAGS " in #(
+ *" -Wl,-z,relro "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_LDFLAGS already contains -Wl,-z,relro"; } >&5
+ (: HARDENING_LDFLAGS already contains -Wl,-z,relro) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append HARDENING_LDFLAGS " -Wl,-z,relro"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_LDFLAGS=\"\$HARDENING_LDFLAGS\""; } >&5
+ (: HARDENING_LDFLAGS="$HARDENING_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ HARDENING_LDFLAGS=-Wl,-z,relro
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_LDFLAGS=\"\$HARDENING_LDFLAGS\""; } >&5
+ (: HARDENING_LDFLAGS="$HARDENING_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,-z,now" >&5
+printf %s "checking whether the linker accepts -Wl,-z,now... " >&6; }
+if test ${ax_cv_check_ldflags___Wl__z_now+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-z,now"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_check_ldflags___Wl__z_now=yes
+else case e in #(
+ e) ax_cv_check_ldflags___Wl__z_now=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl__z_now" >&5
+printf "%s\n" "$ax_cv_check_ldflags___Wl__z_now" >&6; }
+if test x"$ax_cv_check_ldflags___Wl__z_now" = xyes
+then :
+
+if test ${HARDENING_LDFLAGS+y}
+then :
+
+ case " $HARDENING_LDFLAGS " in #(
+ *" -Wl,-z,now "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_LDFLAGS already contains -Wl,-z,now"; } >&5
+ (: HARDENING_LDFLAGS already contains -Wl,-z,now) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append HARDENING_LDFLAGS " -Wl,-z,now"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_LDFLAGS=\"\$HARDENING_LDFLAGS\""; } >&5
+ (: HARDENING_LDFLAGS="$HARDENING_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ HARDENING_LDFLAGS=-Wl,-z,now
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_LDFLAGS=\"\$HARDENING_LDFLAGS\""; } >&5
+ (: HARDENING_LDFLAGS="$HARDENING_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,-z,noexecstack" >&5
+printf %s "checking whether the linker accepts -Wl,-z,noexecstack... " >&6; }
+if test ${ax_cv_check_ldflags___Wl__z_noexecstack+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-z,noexecstack"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_check_ldflags___Wl__z_noexecstack=yes
+else case e in #(
+ e) ax_cv_check_ldflags___Wl__z_noexecstack=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl__z_noexecstack" >&5
+printf "%s\n" "$ax_cv_check_ldflags___Wl__z_noexecstack" >&6; }
+if test x"$ax_cv_check_ldflags___Wl__z_noexecstack" = xyes
+then :
+
+if test ${HARDENING_LDFLAGS+y}
+then :
+
+ case " $HARDENING_LDFLAGS " in #(
+ *" -Wl,-z,noexecstack "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_LDFLAGS already contains -Wl,-z,noexecstack"; } >&5
+ (: HARDENING_LDFLAGS already contains -Wl,-z,noexecstack) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append HARDENING_LDFLAGS " -Wl,-z,noexecstack"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_LDFLAGS=\"\$HARDENING_LDFLAGS\""; } >&5
+ (: HARDENING_LDFLAGS="$HARDENING_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ HARDENING_LDFLAGS=-Wl,-z,noexecstack
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : HARDENING_LDFLAGS=\"\$HARDENING_LDFLAGS\""; } >&5
+ (: HARDENING_LDFLAGS="$HARDENING_LDFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ fi
+ fi
+
+case "$with_passwd" in
+yes|maybe)
+ AUTH_OBJS="$AUTH_OBJS getspwuid.lo passwd.lo"
+ if test "${ac_cv_search_crypt}" = "no"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: no crypt function found, assuming plaintext passwords" >&5
+printf "%s\n" "$as_me: WARNING: no crypt function found, assuming plaintext passwords" >&2;}
+
+fi
+ ;;
+*)
+ printf "%s\n" "#define WITHOUT_PASSWD 1" >>confdefs.h
+
+ if test -z "$AUTH_OBJS"
+then :
+
+ as_fn_error $? "no authentication methods defined." "$LINENO" 5
+
+fi
+ ;;
+esac
+AUTH_OBJS=${AUTH_OBJS# }
+
+if test -n "$LIBS"
+then :
+
+ L="$LIBS"
+ LIBS=
+ for l in ${L}; do
+ dupe=0
+ for sl in ${SUDO_LIBS} ${SUDOERS_LIBS} ${NET_LIBS}; do
+ test $l = $sl && dupe=1
+ done
+ test $dupe = 0 && LIBS="${LIBS} $l"
+ done
+
+fi
+
+
+printf "%s\n" "#define os_init $OS_INIT" >>confdefs.h
+
+
+if test -n "$GCC"
+then :
+
+ #
+ # The fallthrough attribute is supported by gcc 7.0 and clang 10.
+ # This test relies on AC_LANG_WERROR.
+ #
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC supports the fallthrough attribute" >&5
+printf %s "checking whether $CC supports the fallthrough attribute... " >&6; }
+if test ${sudo_cv_var_fallthrough_attribute+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ int main(int argc, char *argv[])
+ {
+ int num = argc + 1;
+ switch (num) {
+ case 1:
+ num = 0;
+ __attribute__((__fallthrough__));
+ case 0:
+ num++;
+ }
+ return num;
+ }
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+ sudo_cv_var_fallthrough_attribute=yes
+
+else case e in #(
+ e)
+ sudo_cv_var_fallthrough_attribute=no
+ ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_var_fallthrough_attribute" >&5
+printf "%s\n" "$sudo_cv_var_fallthrough_attribute" >&6; }
+ if test X"$sudo_cv_var_fallthrough_attribute" = X"yes"
+then :
+
+ printf "%s\n" "#define HAVE_FALLTHROUGH_ATTRIBUTE 1" >>confdefs.h
+
+
+fi
+ if test X"$enable_warnings" = X"yes" -o X"$with_devel" = X"yes"
+then :
+
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -Wall "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Wall"; } >&5
+ (: CFLAGS already contains -Wall) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -Wall"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-Wall
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -Wmissing-prototypes "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Wmissing-prototypes"; } >&5
+ (: CFLAGS already contains -Wmissing-prototypes) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -Wmissing-prototypes"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-Wmissing-prototypes
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -Wno-unknown-pragmas "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Wno-unknown-pragmas"; } >&5
+ (: CFLAGS already contains -Wno-unknown-pragmas) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -Wno-unknown-pragmas"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-Wno-unknown-pragmas
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -Wpointer-arith "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Wpointer-arith"; } >&5
+ (: CFLAGS already contains -Wpointer-arith) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -Wpointer-arith"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-Wpointer-arith
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -Wshadow "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Wshadow"; } >&5
+ (: CFLAGS already contains -Wshadow) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -Wshadow"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-Wshadow
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -Wsign-compare "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Wsign-compare"; } >&5
+ (: CFLAGS already contains -Wsign-compare) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -Wsign-compare"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-Wsign-compare
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -Wwrite-strings "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Wwrite-strings"; } >&5
+ (: CFLAGS already contains -Wwrite-strings) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -Wwrite-strings"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-Wwrite-strings
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wvla" >&5
+printf %s "checking whether C compiler accepts -Wvla... " >&6; }
+if test ${ax_cv_check_cflags___Wvla+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -Wvla"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ax_cv_check_cflags___Wvla=yes
+else case e in #(
+ e) ax_cv_check_cflags___Wvla=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wvla" >&5
+printf "%s\n" "$ax_cv_check_cflags___Wvla" >&6; }
+if test "x$ax_cv_check_cflags___Wvla" = xyes
+then :
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -Wvla "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Wvla"; } >&5
+ (: CFLAGS already contains -Wvla) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -Wvla"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-Wvla
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Walloca" >&5
+printf %s "checking whether C compiler accepts -Walloca... " >&6; }
+if test ${ax_cv_check_cflags___Walloca+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -Walloca"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ax_cv_check_cflags___Walloca=yes
+else case e in #(
+ e) ax_cv_check_cflags___Walloca=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Walloca" >&5
+printf "%s\n" "$ax_cv_check_cflags___Walloca" >&6; }
+if test "x$ax_cv_check_cflags___Walloca" = xyes
+then :
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -Walloca "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Walloca"; } >&5
+ (: CFLAGS already contains -Walloca) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -Walloca"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-Walloca
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wtrampolines" >&5
+printf %s "checking whether C compiler accepts -Wtrampolines... " >&6; }
+if test ${ax_cv_check_cflags___Wtrampolines+y}
+then :
+ printf %s "(cached) " >&6
+else case e in #(
+ e)
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -Wtrampolines"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ax_cv_check_cflags___Wtrampolines=yes
+else case e in #(
+ e) ax_cv_check_cflags___Wtrampolines=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Wtrampolines" >&5
+printf "%s\n" "$ax_cv_check_cflags___Wtrampolines" >&6; }
+if test "x$ax_cv_check_cflags___Wtrampolines" = xyes
+then :
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -Wtrampolines "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Wtrampolines"; } >&5
+ (: CFLAGS already contains -Wtrampolines) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -Wtrampolines"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-Wtrampolines
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+else case e in #(
+ e) : ;;
+esac
+fi
+
+ if test X"$sudo_cv_var_fallthrough_attribute" = X"yes"
+then :
+
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -Wimplicit-fallthrough "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Wimplicit-fallthrough"; } >&5
+ (: CFLAGS already contains -Wimplicit-fallthrough) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -Wimplicit-fallthrough"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-Wimplicit-fallthrough
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+fi
+
+fi
+ if test X"$enable_werror" = X"yes"
+then :
+
+
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -Werror "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Werror"; } >&5
+ (: CFLAGS already contains -Werror) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -Werror"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-Werror
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+
+
+fi
+ case "$host_os" in
+ # Avoid unwanted warnings on macOS
+ darwin*)
+if test ${CFLAGS+y}
+then :
+
+ case " $CFLAGS " in #(
+ *" -Wno-deprecated-declarations "*) :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains -Wno-deprecated-declarations"; } >&5
+ (: CFLAGS already contains -Wno-deprecated-declarations) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } ;; #(
+ *) :
+
+ as_fn_append CFLAGS " -Wno-deprecated-declarations"
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+
+else case e in #(
+ e)
+ CFLAGS=-Wno-deprecated-declarations
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS\""; } >&5
+ (: CFLAGS="$CFLAGS") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ ;;
+esac
+fi
+;;
+ esac
+
+fi
+
+CROSS_COMPILING="$cross_compiling"
+
+test "$exec_prefix" = "NONE" && exec_prefix='$(prefix)'
+
+oexec_prefix="$exec_prefix"
+if test "$exec_prefix" = '$(prefix)'; then
+ if test "$prefix" = "NONE"; then
+ exec_prefix="$ac_default_prefix"
+ else
+ exec_prefix="$prefix"
+ fi
+fi
+
+# Update exec_prefix in intercept_file
+_intercept_file=
+while test X"$intercept_file" != X"$_intercept_file"; do
+ _intercept_file="$intercept_file"
+ eval "intercept_file=\"$_intercept_file\""
+done
+
+# Update exec_prefix in noexec_file
+_noexec_file=
+while test X"$noexec_file" != X"$_noexec_file"; do
+ _noexec_file="$noexec_file"
+ eval "noexec_file=\"$_noexec_file\""
+done
+
+# Update exec_prefix in sesh_file
+_sesh_file=
+while test X"$sesh_file" != X"$_sesh_file"; do
+ _sesh_file="$sesh_file"
+ eval "sesh_file=\"$_sesh_file\""
+done
+
+# Update exec_prefix in plugindir
+_plugindir=
+while test X"$plugindir" != X"$_plugindir"; do
+ _plugindir="$plugindir"
+ eval "plugindir=\"$_plugindir\""
+done
+exec_prefix="$oexec_prefix"
+
+if test X"$enable_intercept" != X"no"
+then :
+
+ SUDO_OBJS="${SUDO_OBJS} intercept.pb-c.o"
+ PROGS="${PROGS} sudo_intercept.la"
+ INSTALL_INTERCEPT="install-intercept"
+
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDO_INTERCEPT "$intercept_file"
+EOF
+
+
+fi
+if test X"$with_noexec" != X"no"
+then :
+
+ PROGS="${PROGS} sudo_noexec.la"
+ INSTALL_NOEXEC="install-noexec"
+
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDO_NOEXEC "$noexec_file"
+EOF
+
+
+fi
+if test X"$with_selinux" != X"no"
+then :
+
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDO_SESH "$sesh_file"
+EOF
+
+
+else case e in #(
+ e)
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDO_SESH NULL
+EOF
+
+ ;;
+esac
+fi
+if test X"$enable_shared" != X"no"
+then :
+
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDO_PLUGIN_DIR "$plugindir/"
+EOF
+
+
+printf "%s\n" "#define ENABLE_SUDO_PLUGIN_API 1" >>confdefs.h
+
+
+else case e in #(
+ e)
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDO_PLUGIN_DIR NULL
+EOF
+
+ ;;
+esac
+fi
+
+if test X"$LDFLAGS_R" != X""; then
+ LDFLAGS="$LDFLAGS $LDFLAGS_R"
+fi
+if test X"$SUDOERS_LDFLAGS_R" != X""; then
+ SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS $SUDOERS_LDFLAGS_R"
+fi
+if test X"$ZLIB_R" != X""; then
+ ZLIB="$ZLIB_R $ZLIB"
+fi
+if test X"$LIBCRYPTO_R" != X""; then
+ LIBCRYPTO="$LIBCRYPTO_R $LIBCRYPTO"
+fi
+if test X"$LIBTLS_R" != X""; then
+ LIBTLS="$LIBTLS_R $LIBTLS"
+fi
+
+CFLAGS=${CFLAGS# }
+CPPFLAGS=${CPPFLAGS# }
+LDFLAGS=${LDFLAGS# }
+SUDO_LDFLAGS=${SUDO_LDFLAGS# }
+SUDOERS_LDFLAGS=${SUDOERS_LDFLAGS# }
+LIBS=${LIBS# }
+SUDO_LIBS=${SUDO_LIBS# }
+SUDOERS_LIBS=${SUDOERS_LIBS# }
+
+if test X"$prefix" = X"NONE"; then
+ test X"$mandir" = X'${datarootdir}/man' && mandir='$(prefix)/man'
+else
+ test X"$mandir" = X'${datarootdir}/man' && mandir='$(datarootdir)/man'
+fi
+test X"$bindir" = X'${exec_prefix}/bin' && bindir='$(exec_prefix)/bin'
+test X"$sbindir" = X'${exec_prefix}/sbin' && sbindir='$(exec_prefix)/sbin'
+test X"$libexecdir" = X'${exec_prefix}/libexec' && libexecdir='$(exec_prefix)/libexec'
+test X"$includedir" = X'${prefix}/include' && includedir='$(prefix)/include'
+test X"$datarootdir" = X'${prefix}/share' && datarootdir='$(prefix)/share'
+test X"$docdir" = X'${datarootdir}/doc/${PACKAGE_TARNAME}' && docdir='$(datarootdir)/doc/$(PACKAGE_TARNAME)'
+test X"$localedir" = X'${datarootdir}/locale' && localedir='$(datarootdir)/locale'
+test X"$localstatedir" = X'${prefix}/var' && localstatedir='$(prefix)/var'
+test X"$runstatedir" = X'${localstatedir}/run' && runstatedir='$(localstatedir)/run'
+test X"$adminconfdir" = X'${prefix}/etc' && adminconfdir='$(prefix)/etc'
+test X"$sysconfdir" = X'${prefix}/etc' && sysconfdir='/etc'
+
+# The configuration file search path is to check adminconfdir first and
+# fall back to sysconfdir. This can support systems with read-only
+# sysconfdir (/etc) that contains a set of default configuration files.
+
+ _sysconfdir="$sysconfdir"
+ while :; do
+ _sysconfdir="`echo \"$_sysconfdir\" | sed -e 's/(/{/g' -e 's/)/}/g'`"
+ case "$_sysconfdir" in
+ *\${[A-Za-z]*}*)
+ eval _sysconfdir="$_sysconfdir"
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+case "$_sysconfdir" in
+ NONE/*)
+ _sysconfdir="${ac_default_prefix}${_sysconfdir#NONE}"
+ ;;
+esac
+
+
+ _adminconfdir="$adminconfdir"
+ while :; do
+ _adminconfdir="`echo \"$_adminconfdir\" | sed -e 's/(/{/g' -e 's/)/}/g'`"
+ case "$_adminconfdir" in
+ *\${[A-Za-z]*}*)
+ eval _adminconfdir="$_adminconfdir"
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+case "$_adminconfdir" in
+ NONE/*)
+ _adminconfdir="${ac_default_prefix}${_adminconfdir#NONE}"
+ ;;
+esac
+
+if test $enable_adminconf = yes
+then :
+
+ # Only use adminconfdir if different from sysconfdir
+ if test X"$_sysconfdir" != X"$_adminconfdir"
+then :
+
+ cvtsudoers_conf='$(adminconfdir)/cvtsudoers.conf:'$cvtsudoers_conf
+ sudo_conf='$(adminconfdir)/sudo.conf:'$sudo_conf
+ sudo_logsrvd_conf='$(adminconfdir)/sudo_logsrvd.conf:'$sudo_logsrvd_conf
+ sudoers_path='$(adminconfdir)/sudoers:'$sudoers_path
+
+fi
+
+fi
+
+# Expand config file paths for use in pathnames.h (after config dir override)
+
+ as_save_IFS=$IFS
+ IFS=:
+ _sudo_define_path_res=
+ for as_dir in $cvtsudoers_conf; do
+
+ _sudo_define_path_exp="$as_dir"
+ while :; do
+ _sudo_define_path_exp="`echo \"$_sudo_define_path_exp\" | sed -e 's/(/{/g' -e 's/)/}/g'`"
+ case "$_sudo_define_path_exp" in
+ *\${[A-Za-z]*}*)
+ eval _sudo_define_path_exp="$_sudo_define_path_exp"
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+case "$_sudo_define_path_exp" in
+ NONE/*)
+ _sudo_define_path_exp="${ac_default_prefix}${_sudo_define_path_exp#NONE}"
+ ;;
+esac
+
+ if test -z "${_sudo_define_path_res}"; then
+ _sudo_define_path_res="${_sudo_define_path_exp}"
+ else
+ _sudo_define_path_res="${_sudo_define_path_res}:${_sudo_define_path_exp}"
+ fi
+ done
+ IFS=$as_save_IFS
+ cat >>confdefs.h <<EOF
+#define _PATH_CVTSUDOERS_CONF "${_sudo_define_path_res}"
+EOF
+
+
+
+ as_save_IFS=$IFS
+ IFS=:
+ _sudo_define_path_res=
+ for as_dir in $sudo_conf; do
+
+ _sudo_define_path_exp="$as_dir"
+ while :; do
+ _sudo_define_path_exp="`echo \"$_sudo_define_path_exp\" | sed -e 's/(/{/g' -e 's/)/}/g'`"
+ case "$_sudo_define_path_exp" in
+ *\${[A-Za-z]*}*)
+ eval _sudo_define_path_exp="$_sudo_define_path_exp"
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+case "$_sudo_define_path_exp" in
+ NONE/*)
+ _sudo_define_path_exp="${ac_default_prefix}${_sudo_define_path_exp#NONE}"
+ ;;
+esac
+
+ if test -z "${_sudo_define_path_res}"; then
+ _sudo_define_path_res="${_sudo_define_path_exp}"
+ else
+ _sudo_define_path_res="${_sudo_define_path_res}:${_sudo_define_path_exp}"
+ fi
+ done
+ IFS=$as_save_IFS
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDO_CONF "${_sudo_define_path_res}"
+EOF
+
+
+
+ as_save_IFS=$IFS
+ IFS=:
+ _sudo_define_path_res=
+ for as_dir in $sudo_logsrvd_conf; do
+
+ _sudo_define_path_exp="$as_dir"
+ while :; do
+ _sudo_define_path_exp="`echo \"$_sudo_define_path_exp\" | sed -e 's/(/{/g' -e 's/)/}/g'`"
+ case "$_sudo_define_path_exp" in
+ *\${[A-Za-z]*}*)
+ eval _sudo_define_path_exp="$_sudo_define_path_exp"
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+case "$_sudo_define_path_exp" in
+ NONE/*)
+ _sudo_define_path_exp="${ac_default_prefix}${_sudo_define_path_exp#NONE}"
+ ;;
+esac
+
+ if test -z "${_sudo_define_path_res}"; then
+ _sudo_define_path_res="${_sudo_define_path_exp}"
+ else
+ _sudo_define_path_res="${_sudo_define_path_res}:${_sudo_define_path_exp}"
+ fi
+ done
+ IFS=$as_save_IFS
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDO_LOGSRVD_CONF "${_sudo_define_path_res}"
+EOF
+
+
+
+ as_save_IFS=$IFS
+ IFS=:
+ _sudo_define_path_res=
+ for as_dir in $sudoers_path; do
+
+ _sudo_define_path_exp="$as_dir"
+ while :; do
+ _sudo_define_path_exp="`echo \"$_sudo_define_path_exp\" | sed -e 's/(/{/g' -e 's/)/}/g'`"
+ case "$_sudo_define_path_exp" in
+ *\${[A-Za-z]*}*)
+ eval _sudo_define_path_exp="$_sudo_define_path_exp"
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+case "$_sudo_define_path_exp" in
+ NONE/*)
+ _sudo_define_path_exp="${ac_default_prefix}${_sudo_define_path_exp#NONE}"
+ ;;
+esac
+
+ if test -z "${_sudo_define_path_res}"; then
+ _sudo_define_path_res="${_sudo_define_path_exp}"
+ else
+ _sudo_define_path_res="${_sudo_define_path_res}:${_sudo_define_path_exp}"
+ fi
+ done
+ IFS=$as_save_IFS
+ cat >>confdefs.h <<EOF
+#define _PATH_SUDOERS "${_sudo_define_path_res}"
+EOF
+
+
+
+# Convert exampledir to something that can be used in the man pages
+
+ EXAMPLES="$exampledir"
+ while :; do
+ EXAMPLES="`echo \"$EXAMPLES\" | sed -e 's/(/{/g' -e 's/)/}/g'`"
+ case "$EXAMPLES" in
+ *\${[A-Za-z]*}*)
+ eval EXAMPLES="$EXAMPLES"
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+case "$EXAMPLES" in
+ NONE/*)
+ EXAMPLES="${ac_default_prefix}${EXAMPLES#NONE}"
+ ;;
+esac
+
+
+if test X"$INIT_SCRIPT" != X""
+then :
+
+ ac_config_files="$ac_config_files etc/init.d/$INIT_SCRIPT"
+
+
+elif test X"$TMPFILES_D" != X""
+then :
+
+ ac_config_files="$ac_config_files etc/init.d/sudo.conf"
+
+
+fi
+
+ac_config_files="$ac_config_files Makefile docs/Makefile examples/Makefile examples/sudoers examples/sudo.conf examples/sudo_logsrvd.conf examples/syslog.conf include/Makefile lib/eventlog/Makefile lib/fuzzstub/Makefile lib/iolog/Makefile lib/logsrv/Makefile lib/protobuf-c/Makefile lib/ssl_compat/Makefile lib/util/Makefile lib/util/regress/harness lib/util/util.exp logsrvd/Makefile src/intercept.exp src/sudo_usage.h src/Makefile plugins/audit_json/Makefile plugins/sample/Makefile plugins/group_file/Makefile plugins/sample_approval/Makefile plugins/system_group/Makefile plugins/sudoers/Makefile plugins/sudoers/regress/harness plugins/sudoers/sudoers"
+
+ac_config_commands="$ac_config_commands harness"
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# 'ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* 'ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # 'set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # 'set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+# Check whether --enable-year2038 was given.
+if test ${enable_year2038+y}
+then :
+ enableval=$enable_year2038;
+fi
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else case e in #(
+ e) case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac ;;
+esac
+fi
+
+
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
+as_nl='
+'
+export as_nl
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
+
+# The user is always right.
+if ${PATH_SEPARATOR+false} :; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as 'sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ printf "%s\n" "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else case e in #(
+ e) as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ } ;;
+esac
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else case e in #(
+ e) as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ } ;;
+esac
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable.
+ # In both cases, we have to default to 'cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated
+
+# Sed expression to map a string onto a valid variable name.
+as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+as_tr_sh="eval sed '$as_sed_sh'" # deprecated
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by sudo $as_me 1.9.15p5, which was
+generated by GNU Autoconf 2.72c. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+'$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <https://bugzilla.sudo.ws/>."
+
+_ACEOF
+ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
+ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config='$ac_cs_config_escaped'
+ac_cs_version="\\
+sudo config.status 1.9.15p5
+configured by $0, generated by GNU Autoconf 2.72c,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2023 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ printf "%s\n" "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ printf "%s\n" "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: '$1'
+Try '$0 --help' for more information.";;
+ --help | --hel | -h )
+ printf "%s\n" "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: '$1'
+Try '$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ printf "%s\n" "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
+enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
+shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`'
+SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
+ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
+PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`'
+host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
+host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
+host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
+build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
+build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
+build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
+SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
+Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
+GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
+EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
+FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
+LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
+NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
+LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
+exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
+FILECMD='`$ECHO "$FILECMD" | $SED "$delay_single_quote_subst"`'
+OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
+file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`'
+want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`'
+DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`'
+sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`'
+AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
+lt_ar_flags='`$ECHO "$lt_ar_flags" | $SED "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
+archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`'
+STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
+lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
+CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
+compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
+GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
+lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`'
+nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`'
+lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`'
+lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`'
+objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
+need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
+MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
+LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
+libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
+fix_hardcoded_libdir_flag_spec='`$ECHO "$fix_hardcoded_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
+fix_hardcoded_libdir_flag_spec_ld='`$ECHO "$fix_hardcoded_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
+postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
+need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
+version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
+install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
+configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`'
+configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
+striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
+
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in SHELL \
+ECHO \
+PATH_SEPARATOR \
+SED \
+GREP \
+EGREP \
+FGREP \
+LD \
+NM \
+LN_S \
+lt_SP2NL \
+lt_NL2SP \
+reload_flag \
+FILECMD \
+OBJDUMP \
+deplibs_check_method \
+file_magic_cmd \
+file_magic_glob \
+want_nocaseglob \
+DLLTOOL \
+sharedlib_from_linklib_cmd \
+AR \
+archiver_list_spec \
+STRIP \
+RANLIB \
+CC \
+CFLAGS \
+compiler \
+lt_cv_sys_global_symbol_pipe \
+lt_cv_sys_global_symbol_to_cdecl \
+lt_cv_sys_global_symbol_to_import \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+lt_cv_nm_interface \
+nm_file_list_spec \
+lt_cv_truncate_bin \
+lt_prog_compiler_no_builtin_flag \
+lt_prog_compiler_pic \
+lt_prog_compiler_wl \
+lt_prog_compiler_static \
+lt_cv_prog_compiler_c_o \
+need_locks \
+MANIFEST_TOOL \
+DSYMUTIL \
+NMEDIT \
+LIPO \
+OTOOL \
+OTOOL64 \
+shrext_cmds \
+export_dynamic_flag_spec \
+whole_archive_flag_spec \
+compiler_needs_object \
+with_gnu_ld \
+allow_undefined_flag \
+no_undefined_flag \
+hardcode_libdir_flag_spec \
+hardcode_libdir_separator \
+fix_hardcoded_libdir_flag_spec \
+fix_hardcoded_libdir_flag_spec_ld \
+exclude_expsyms \
+include_expsyms \
+file_list_spec \
+variables_saved_for_relink \
+libname_spec \
+library_names_spec \
+soname_spec \
+install_override_mode \
+finish_eval \
+old_striplib \
+striplib; do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[\\\\\\\`\\"\\\$]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds \
+old_postinstall_cmds \
+old_postuninstall_cmds \
+old_archive_cmds \
+extract_expsyms_cmds \
+old_archive_from_new_cmds \
+old_archive_from_expsyms_cmds \
+archive_cmds \
+archive_expsym_cmds \
+module_cmds \
+module_expsym_cmds \
+export_symbols_cmds \
+prelink_cmds \
+postlink_cmds \
+postinstall_cmds \
+postuninstall_cmds \
+finish_cmds \
+sys_lib_search_path_spec \
+configure_time_dlsearch_path \
+configure_time_lt_sys_library_path; do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[\\\\\\\`\\"\\\$]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+ac_aux_dir='$ac_aux_dir'
+
+# See if we are running on zsh, and set the options that allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+fi
+
+
+ PACKAGE='$PACKAGE'
+ VERSION='$VERSION'
+ RM='$RM'
+ ofile='$ofile'
+
+
+
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "pathnames.h") CONFIG_HEADERS="$CONFIG_HEADERS pathnames.h" ;;
+ "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+ "$PYTHON_PLUGIN_SRC/Makefile") CONFIG_FILES="$CONFIG_FILES $PYTHON_PLUGIN_SRC/Makefile" ;;
+ "lib/zlib/zconf.h") CONFIG_HEADERS="$CONFIG_HEADERS lib/zlib/zconf.h" ;;
+ "lib/zlib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/zlib/Makefile" ;;
+ "etc/init.d/$INIT_SCRIPT") CONFIG_FILES="$CONFIG_FILES etc/init.d/$INIT_SCRIPT" ;;
+ "etc/init.d/sudo.conf") CONFIG_FILES="$CONFIG_FILES etc/init.d/sudo.conf" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;;
+ "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;;
+ "examples/sudoers") CONFIG_FILES="$CONFIG_FILES examples/sudoers" ;;
+ "examples/sudo.conf") CONFIG_FILES="$CONFIG_FILES examples/sudo.conf" ;;
+ "examples/sudo_logsrvd.conf") CONFIG_FILES="$CONFIG_FILES examples/sudo_logsrvd.conf" ;;
+ "examples/syslog.conf") CONFIG_FILES="$CONFIG_FILES examples/syslog.conf" ;;
+ "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
+ "lib/eventlog/Makefile") CONFIG_FILES="$CONFIG_FILES lib/eventlog/Makefile" ;;
+ "lib/fuzzstub/Makefile") CONFIG_FILES="$CONFIG_FILES lib/fuzzstub/Makefile" ;;
+ "lib/iolog/Makefile") CONFIG_FILES="$CONFIG_FILES lib/iolog/Makefile" ;;
+ "lib/logsrv/Makefile") CONFIG_FILES="$CONFIG_FILES lib/logsrv/Makefile" ;;
+ "lib/protobuf-c/Makefile") CONFIG_FILES="$CONFIG_FILES lib/protobuf-c/Makefile" ;;
+ "lib/ssl_compat/Makefile") CONFIG_FILES="$CONFIG_FILES lib/ssl_compat/Makefile" ;;
+ "lib/util/Makefile") CONFIG_FILES="$CONFIG_FILES lib/util/Makefile" ;;
+ "lib/util/regress/harness") CONFIG_FILES="$CONFIG_FILES lib/util/regress/harness" ;;
+ "lib/util/util.exp") CONFIG_FILES="$CONFIG_FILES lib/util/util.exp" ;;
+ "logsrvd/Makefile") CONFIG_FILES="$CONFIG_FILES logsrvd/Makefile" ;;
+ "src/intercept.exp") CONFIG_FILES="$CONFIG_FILES src/intercept.exp" ;;
+ "src/sudo_usage.h") CONFIG_FILES="$CONFIG_FILES src/sudo_usage.h" ;;
+ "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
+ "plugins/audit_json/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/audit_json/Makefile" ;;
+ "plugins/sample/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/sample/Makefile" ;;
+ "plugins/group_file/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/group_file/Makefile" ;;
+ "plugins/sample_approval/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/sample_approval/Makefile" ;;
+ "plugins/system_group/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/system_group/Makefile" ;;
+ "plugins/sudoers/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/sudoers/Makefile" ;;
+ "plugins/sudoers/regress/harness") CONFIG_FILES="$CONFIG_FILES plugins/sudoers/regress/harness" ;;
+ "plugins/sudoers/sudoers") CONFIG_FILES="$CONFIG_FILES plugins/sudoers/sudoers" ;;
+ "harness") CONFIG_COMMANDS="$CONFIG_COMMANDS harness" ;;
+
+ *) as_fn_error $? "invalid argument: '$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
+ test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers
+ test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to '$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with './config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with './config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script 'defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag '$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain ':'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: '$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is 'configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+printf "%s\n" "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`printf "%s\n" "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when '$srcdir' = '.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable 'datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable 'datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ printf "%s\n" "/* $configure_input */" >&1 \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+printf "%s\n" "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ printf "%s\n" "/* $configure_input */" >&1 \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+ ;;
+
+ :C) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+printf "%s\n" "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "libtool":C)
+
+ # See if we are running on zsh, and set the options that allow our
+ # commands through without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+ fi
+
+ cfgfile=${ofile}T
+ trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+ $RM "$cfgfile"
+
+ cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+# Generated automatically by $as_me ($PACKAGE) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit, 1996
+
+# Copyright (C) 2014 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions. There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program or library that is built
+# using GNU Libtool, you may include this file under the same
+# distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags=''
+
+# Configured defaults for sys_lib_dlsearch_path munging.
+: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# Shared archive member basename,for filename based shared library versioning on AIX.
+shared_archive_member_spec=$shared_archive_member_spec
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that protects backslashes.
+ECHO=$lt_ECHO
+
+# The PATH separator for the build system.
+PATH_SEPARATOR=$lt_PATH_SEPARATOR
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# convert \$build file names to \$host format.
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+
+# convert \$build files to toolchain format.
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+
+# A file(cmd) program that detects file types.
+FILECMD=$lt_FILECMD
+
+# An object symbol dumper.
+OBJDUMP=$lt_OBJDUMP
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method = "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# How to find potential files when deplibs_check_method = "file_magic".
+file_magic_glob=$lt_file_magic_glob
+
+# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
+want_nocaseglob=$lt_want_nocaseglob
+
+# DLL creation program.
+DLLTOOL=$lt_DLLTOOL
+
+# Command to associate shared and link libraries.
+sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
+
+# The archiver.
+AR=$lt_AR
+
+# Flags to create an archive (by configure).
+lt_ar_flags=$lt_ar_flags
+
+# Flags to create an archive.
+AR_FLAGS=\${ARFLAGS-"\$lt_ar_flags"}
+
+# How to feed a file listing to the archiver.
+archiver_list_spec=$lt_archiver_list_spec
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Whether to use a lock for old archive extraction.
+lock_old_archive_extraction=$lock_old_archive_extraction
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm into a list of symbols to manually relocate.
+global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# The name lister interface.
+nm_interface=$lt_lt_cv_nm_interface
+
+# Specify filename containing input files for \$NM.
+nm_file_list_spec=$lt_nm_file_list_spec
+
+# The root where to search for dependent libraries,and where our libraries should be installed.
+lt_sysroot=$lt_sysroot
+
+# Command to truncate a binary pipe.
+lt_truncate_bin=$lt_lt_cv_truncate_bin
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Manifest tool.
+MANIFEST_TOOL=$lt_MANIFEST_TOOL
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Permission mode override for installation of shared libraries.
+install_override_mode=$lt_install_override_mode
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Detected run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path
+
+# Explicit LT_SYS_LIBRARY_PATH set during ./configure time.
+configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \$shlibpath_var if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Flag to modify a path being hardcoded into the resulting binary.
+fix_hardcoded_libdir_flag_spec=$lt_fix_hardcoded_libdir_flag_spec
+
+# If ld is used when linking,flag to modify a path being hardcoded into the resulting binary.
+fix_hardcoded_libdir_flag_spec_ld=$lt_fix_hardcoded_libdir_flag_spec_ld
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Commands necessary for finishing linking programs.
+postlink_cmds=$lt_postlink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+ cat <<'_LT_EOF' >> "$cfgfile"
+
+# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
+
+# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+# string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+# string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+# "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+# VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+ case x$2 in
+ x)
+ ;;
+ *:)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
+ ;;
+ x:*)
+ eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ *::*)
+ eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+ eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
+ ;;
+ *)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ esac
+}
+
+
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+ for cc_temp in $*""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+ done
+ func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+
+
+# ### END FUNCTIONS SHARED WITH CONFIGURE
+
+_LT_EOF
+
+ case $host_os in
+ aix3*)
+ cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test set != "${COLLECT_NAMES+set}"; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+_LT_EOF
+ ;;
+ esac
+
+
+
+ltmain=$ac_aux_dir/ltmain.sh
+
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ $SED '$q' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" ||
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+
+ ;;
+ "harness":C) chmod +x lib/util/regress/harness plugins/sudoers/regress/harness ;;
+
+ esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
+if test ${LIBTLS+y}; then
+ have_tls=yes
+fi
+echo "" >&6
+echo "Configured Sudo version $PACKAGE_VERSION" >&6
+echo " Compiler settings:" >&6
+echo " compiler : $CC" >&6
+echo " compiler options : $CFLAGS" >&6
+echo " preprocessor options : $CPPFLAGS" >&6
+echo " front-end libraries : $SUDO_LIBS" >&6
+echo " front-end linker options : $SUDO_LDFLAGS" >&6
+echo " network libraries : $NET_LIBS" >&6
+echo " Crypto library : $LIBCRYPTO" >&6
+echo " TLS libraries : $LIBTLS" >&6
+echo " extra libraries : $LIBS" >&6
+echo " extra linker options : $LDFLAGS" >&6
+echo " sudoers libraries : $SUDOERS_LIBS" >&6
+echo " sudoers linker options : $SUDOERS_LDFLAGS" >&6
+if test "${enable_sanitizer-no}" != "no"; then
+ echo " sanitizer options : ${enable_sanitizer}" >&6
+fi
+if test X"$FUZZ_LD" != X"\$(CC)"; then
+ echo " fuzzing linker : ${FUZZ_LD}" >&6
+fi
+if test X"$FUZZ_ENGINE" != X"\$(top_builddir)/lib/fuzzstub/libsudo_fuzzstub.la"; then
+ echo " fuzzing engine : ${FUZZ_ENGINE}" >&6
+fi
+echo " Plugin options:" >&6
+echo " plugin support : ${SHLIB_ENABLE}" >&6
+echo " Sudoers plugin static : ${enable_static_sudoers-no}" >&6
+echo " Python plugin : ${enable_python-no}" >&6
+if test "${enable_python-no}" != "no"; then
+ echo " Python CFLAGS : ${PYTHON_INCLUDE}" >&6
+ echo " Python LDFLAGS : ${PYTHON_LIBS}" >&6
+fi
+echo " Optional features:" >&6
+echo " log client : ${enable_log_client-yes}" >&6
+echo " log server : ${enable_log_server-yes}" >&6
+echo " log client/server TLS : ${have_tls-no}" >&6
+case "$host_os" in
+ linux*) echo " SELinux RBAC : ${with_selinux-yes}" >&6;;
+esac
+echo " Optional sudoers back-ends:" >&6
+echo " LDAP : ${with_ldap-no}" >&6
+if test "${with_ldap-no}" != "no"; then
+ echo " ldap configuration : ${ldap_conf}" >&6
+ echo " ldap secret : ${ldap_secret}" >&6
+ echo " SASL authentication : ${enable_sasl-no}" >&6
+fi
+echo " SSSD : ${with_sssd-no}" >&6
+if test "${with_sssd-no}" != "no"; then
+ echo " SSSD config path : ${sssd_conf}" >&6
+ if test "${sssd_lib}" = \""LIBDIR\""; then
+ echo " SSSD lib dir : ${libdir}" >&6
+ else
+ echo " SSSD lib dir : ${sssd_lib}" >&6
+ fi
+fi
+echo " Authentication options:" >&6
+echo " require authentication : ${enable_authentication-yes}" >&6
+auth_methods=`echo "$AUTH_OBJS" | sed -e 's/\.lo//g' -e 's/getspwuid *//'`
+echo " authentication methods : ${auth_methods}" >&6
+if test "${with_pam-no}" = "yes"; then
+ echo " pam session support : ${pam_session}" >&6
+ echo " pam login service : ${pam_login_service}" >&6
+fi
+if test "${with_kerb5-no}" != "no"; then
+ echo " kerb5 instance string : ${with_kerb5-none}" >&6
+fi
+if test "${with_opie-no}-${with_skey-no}" != "no-no"; then
+ echo " long OTP prompt : ${long_otp_prompt-no}" >&6
+fi
+echo " group exempt from passwords : ${with_exempt-none}" >&6
+echo " password prompt : ${passprompt}" >&6
+echo " password prompt timeout : ${password_timeout} minutes" >&6
+echo " password tries : ${passwd_tries}" >&6
+echo " bad password message : ${badpass_message}" >&6
+if test "$insults" = "on"; then
+ i=""
+ test "$enable_offensive_insults" = "yes" && i="offensive ${i}"
+ test "$with_python_insults" = "yes" && i="python ${i}"
+ test "$with_goons_insults" = "yes" && i="goons ${i}"
+ test "$with_hal_insults" = "yes" && i="hal ${i}"
+ test "$with_csops_insults" = "yes" && i="csops ${i}"
+ test "$with_classic_insults" = "yes" && i="classic ${i}"
+else
+ i=no
+fi
+echo " insults : $i" >&6
+echo " display lecture : ${lecture}" >&6
+echo " timestamp (credential) type : ${timestamp_type}" >&6
+echo " timestamp (credential) timeout: ${timeout} minutes" >&6
+echo " Logging options:" >&6
+echo " logging default : ${with_logging}" >&6
+echo " syslog facility : ${logfac}" >&6
+echo " syslog priority allowed : ${goodpri}" >&6
+echo " syslog priority denied : ${badpri}" >&6
+echo " log file path : ${logpath}" >&6
+echo " log file includes hostname : ${enable_log_host-no}" >&6
+echo " log file line length : ${loglen}" >&6
+echo " compress I/O logs : ${enable_zlib}" >&6
+case "$host_os" in
+ linux*) echo " Linux audit : ${with_linux_audit-no}" >&6;;
+ solaris2.11*) echo " Solaris audit : ${with_solaris_audit-no}" >&6;;
+ *) echo " BSM audit : ${with_bsm_audit-no}" >&6;;
+esac
+echo " run mailer as root : ${enable_root_mailer-yes}" >&6
+echo " warning/error mail recipient : ${mailto}" >&6
+echo " warning/error mail subject : ${mailsub}" >&6
+echo " mail if user not in sudoers : ${mail_no_user}" >&6
+echo " mail if user not on host : ${mail_no_host}" >&6
+echo " mail if command not allowed : ${mail_no_perms}" >&6
+echo " Pathnames:" >&6
+echo " prefix : $prefix" >&6
+echo " sysconfdir : $_sysconfdir" >&6
+if test "${enable_adminconf-no}" != "no"; then
+ echo " adminconfdir : $_adminconfdir" >&6
+fi
+echo " log directory : ${log_dir}" >&6
+echo " run directory : ${rundir}" >&6
+echo " var directory : ${vardir}" >&6
+echo " I/O log directory : ${iolog_dir}" >&6
+echo " sudo_logsrvd relay directory : ${relay_dir}" >&6
+if test X"$with_exampledir" != X""; then
+ echo " exampledir : $exampledir" >&6
+fi
+echo " plugin directory : ${plugindir}" >&6
+echo " sudoers plugin : ${sudoers_plugin}" >&6
+if test "${enable_python-no}" != "no"; then
+ echo " python plugin : ${python_plugin}" >&6
+fi
+echo " sudoers file : ${sudoers_path}" >&6
+echo " cvtsudoers.conf file : ${cvtsudoers_conf}" >&6
+echo " sudo.conf file : ${sudo_conf}" >&6
+echo " sudo_logsrvd.conf file : ${sudo_logsrvd_conf}" >&6
+echo " path to sendmail : ${with_sendmail}" >&6
+echo " time zone directory : ${tzdir}" >&6
+if test -n "$TMPFILES_D"; then
+ echo " systemd tempfiles dir : ${TMPFILES_D}" >&6
+fi
+if test ${with_netsvc-"no"} != "no"; then
+ echo " netsvc file : ${netsvc_conf}" >&6
+elif test ${with_nsswitch-"yes"} != "no"; then
+ echo " nsswitch file : ${nsswitch_conf}" >&6
+fi
+echo " intercept file : ${intercept_file}" >&6
+echo " noexec file : ${noexec_file}" >&6
+echo " secure path : ${with_secure_path-no}" >&6
+echo " askpass helper file : ${with_askpass-no}" >&6
+echo " device search path : ${devsearch}" >&6
+echo " Other options:" >&6
+if test "${with_devel-no}" != "no"; then
+ echo " development build : ${with_devel}" >&6
+fi
+case "$host_os" in
+ solaris2*) echo " Solaris project support : ${with_project-no}" >&6;;
+esac
+if test "${with_logincap+set}" = "set"; then
+ echo " /etc/login.conf support : ${with_logincap}" >&6
+fi
+echo " fully-qualified domain names : ${fqdn}" >&6
+echo " default umask : ${sudo_umask}" >&6
+echo " umask override : ${umask_override}" >&6
+echo " default runas user : ${runas_default}" >&6
+echo " probe network interfaces : ${with_interfaces-yes}" >&6
+echo " allow root to run sudo : ${root_sudo}" >&6
+echo " reset environment for commands: ${env_reset}" >&6
+echo " run shell if no args : ${enable_noargs_shell-no}" >&6
+echo " ignore '.' or '' in \$PATH : ${ignore_dot}" >&6
+echo " disable path info : ${enable_path_info-no}" >&6
+echo " sudoers file mode : ${SUDOERS_MODE}" >&6
+echo " sudoers file owner : ${SUDOERS_UID}:${SUDOERS_GID}" >&6
+echo " default visudo editor : ${editor}" >&6
+echo " visudo supports \$EDITOR : ${env_editor}" >&6
+if test "${enable_env_debug+set}" = "set"; then
+ echo " environment debugging : ${enable_env_debug-no}" >&6
+fi
+echo "" >&6
+
+if test "$openssl_missing" = "yes"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: OpenSSL dev libraries not found, Sudo logsrv connections will not be encrypted." >&5
+printf "%s\n" "$as_me: WARNING: OpenSSL dev libraries not found, Sudo logsrv connections will not be encrypted." >&2;}
+
+fi
+if test "$with_pam" = "yes"
+then :
+
+ case $host_os in
+ hpux*)
+ if test -f /usr/lib/security/libpam_hpsec.so.1
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: you may wish to add the following line to /etc/pam.conf" >&5
+printf "%s\n" "$as_me: you may wish to add the following line to /etc/pam.conf" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: sudo session required libpam_hpsec.so.1 bypass_umask bypass_last_login" >&5
+printf "%s\n" "$as_me: sudo session required libpam_hpsec.so.1 bypass_umask bypass_last_login" >&6;}
+
+fi
+ ;;
+ linux*)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: you will need to customize examples/pam.conf and install it as /etc/pam.d/sudo" >&5
+printf "%s\n" "$as_me: you will need to customize examples/pam.conf and install it as /etc/pam.d/sudo" >&6;}
+ ;;
+ esac
+
+fi
+case "$rundir" in
+ /run/*|/var/run/*)
+ clear_rundir=0
+ ;;
+ *)
+ clear_rundir=1
+ ;;
+esac
+if test $clear_rundir -eq 1
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: the $rundir/ts directory must be cleared at boot time." >&5
+printf "%s\n" "$as_me: warning: the $rundir/ts directory must be cleared at boot time." >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: You may need to create a startup item to do this." >&5
+printf "%s\n" "$as_me: You may need to create a startup item to do this." >&6;}
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..1d3998d
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,4937 @@
+dnl
+dnl Use the top-level autogen.sh script to generate configure and config.h.in
+dnl
+dnl SPDX-License-Identifier: ISC
+dnl
+dnl Copyright (c) 1994-1996, 1998-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+dnl
+dnl Permission to use, copy, modify, and distribute this software for any
+dnl purpose with or without fee is hereby granted, provided that the above
+dnl copyright notice and this permission notice appear in all copies.
+dnl
+dnl THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+dnl WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+dnl MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+dnl ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+dnl WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+dnl ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+dnl OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+dnl
+AC_PREREQ([2.69])
+AC_INIT([sudo], [1.9.15p5], [https://bugzilla.sudo.ws/], [sudo])
+AC_CONFIG_HEADERS([config.h pathnames.h])
+AC_CONFIG_SRCDIR([src/sudo.c])
+AC_CONFIG_AUX_DIR([scripts])
+dnl
+dnl Variables that get substituted in the Makefile and man pages
+dnl
+AC_SUBST([PROGS], [sudo])dnl
+AC_SUBST([SUDO_LDFLAGS])dnl
+AC_SUBST([SUDOERS_LDFLAGS])dnl
+AC_SUBST([LIBUTIL_LDFLAGS])dnl
+AC_SUBST([ZLIB_LDFLAGS])dnl
+AC_SUBST([LT_LDFLAGS])dnl
+AC_SUBST([LT_LDDEP], ["\$(shlib_exp)"])dnl
+AC_SUBST([LT_LDEXPORTS], ["-export-symbols \$(shlib_exp)"])dnl
+AC_SUBST([LT_STATIC])dnl
+AC_SUBST([LT_DEP_LIBS])dnl
+AC_SUBST([COMMON_OBJS])dnl
+AC_SUBST([SUDOERS_LT_STATIC])dnl
+AC_SUBST([SUDOERS_OBJS])dnl
+AC_SUBST([SUDO_OBJS])dnl
+AC_SUBST([SUDO_LIBS])dnl
+AC_SUBST([SUDOERS_LIBS])dnl
+AC_SUBST([STATIC_SUDOERS])dnl
+AC_SUBST([NET_LIBS])dnl
+AC_SUBST([AFS_LIBS])dnl
+AC_SUBST([REPLAY_LIBS])dnl
+AC_SUBST([GETGROUPS_LIB])dnl
+AC_SUBST([AUTH_OBJS])dnl
+AC_SUBST([MANTYPE])dnl
+AC_SUBST([MANDIRTYPE])dnl
+AC_SUBST([MANCOMPRESS])dnl
+AC_SUBST([MANCOMPRESSEXT])dnl
+AC_SUBST([POSTINSTALL])dnl
+AC_SUBST([SHLIB_ENABLE])dnl
+AC_SUBST([SHLIB_MODE])dnl
+AC_SUBST([SUDOERS_MODE])dnl
+AC_SUBST([SUDOERS_UID])dnl
+AC_SUBST([SUDOERS_GID])dnl
+AC_SUBST([DEVEL])dnl
+AC_SUBST([EXAMPLES])dnl
+AC_SUBST([BAMAN], [0])dnl
+AC_SUBST([LCMAN], [0])dnl
+AC_SUBST([PSMAN], [0])dnl
+AC_SUBST([SEMAN], [0])dnl
+AC_SUBST([AAMAN], [0])dnl
+AC_SUBST([devdir], ['$(srcdir)'])dnl
+AC_SUBST([mansectsu])dnl
+AC_SUBST([mansectform])dnl
+AC_SUBST([mansectmisc])dnl
+AC_SUBST([INTERCEPTFILE])dnl
+AC_SUBST([INTERCEPTDIR])dnl
+AC_SUBST([intercept_file])dnl
+AC_SUBST([NOEXECFILE])dnl
+AC_SUBST([NOEXECDIR])dnl
+AC_SUBST([noexec_file])dnl
+AC_SUBST([sesh_file])dnl
+AC_SUBST([INSTALL_BACKUP])dnl
+AC_SUBST([INSTALL_INTERCEPT])dnl
+AC_SUBST([INSTALL_NOEXEC])dnl
+AC_SUBST([PRELOAD_MODULE], ['-module'])dnl
+AC_SUBST([DONT_LEAK_PATH_INFO])dnl
+AC_SUBST([BSDAUTH_USAGE])dnl
+AC_SUBST([SELINUX_USAGE])dnl
+AC_SUBST([LDAP], ['#'])dnl
+AC_SUBST([LOGINCAP_USAGE])dnl
+AC_SUBST([ZLIB])dnl
+AC_SUBST([ZLIB_SRC])dnl
+AC_SUBST([LIBTOOL_DEPS])dnl
+AC_SUBST([LIBDL])dnl
+AC_SUBST([LIBRT])dnl
+AC_SUBST([LIBINTL])dnl
+AC_SUBST([LIBCRYPTO])dnl
+AC_SUBST([LIBTLS])dnl
+AC_SUBST([LIBPTHREAD])dnl
+AC_SUBST([SUDO_NLS], [disabled])dnl
+AC_SUBST([LOCALEDIR_SUFFIX])dnl
+AC_SUBST([COMPAT_TEST_PROGS])dnl
+AC_SUBST([SUDOERS_TEST_PROGS])dnl
+AC_SUBST([CROSS_COMPILING])dnl
+AC_SUBST([ASAN_LDFLAGS])dnl
+AC_SUBST([ASAN_CFLAGS])dnl
+AC_SUBST([PIE_LDFLAGS])dnl
+AC_SUBST([PIE_CFLAGS])dnl
+AC_SUBST([HARDENING_LDFLAGS])dnl
+AC_SUBST([HARDENING_CFLAGS])dnl
+AC_SUBST([INIT_SCRIPT])dnl
+AC_SUBST([INIT_DIR])dnl
+AC_SUBST([RC_LINK])dnl
+AC_SUBST([COMPAT_EXP])dnl
+AC_SUBST([TMPFILES_D])dnl
+AC_SUBST([exampledir], ['$(docdir)/examples'])dnl
+AC_SUBST([adminconfdir], ['$(prefix)/etc'])dnl
+AC_SUBST([DIGEST])dnl
+AC_SUBST([devsearch])dnl
+AC_SUBST([SIGNAME])dnl
+AC_SUBST([PYTHON_PLUGIN], ['#'])dnl
+AC_SUBST([PYTHON_PLUGIN_SRC])dnl
+AC_SUBST([SSL_COMPAT_SRC])dnl
+AC_SUBST([LOGSRV])dnl
+AC_SUBST([LOGSRV_SRC], ['lib/logsrv'])dnl
+AC_SUBST([LOGSRVD_SRC], ['logsrvd'])dnl
+AC_SUBST([LOGSRVD_CONF], ['sudo_logsrvd.conf'])dnl
+AC_SUBST([LIBLOGSRV], ['$(top_builddir)/lib/logsrv/liblogsrv.la $(top_builddir)/lib/protobuf-c/libprotobuf-c.la'])dnl
+AC_SUBST([PPFILES], ['$(srcdir)/etc/sudo.pp'])dnl
+AC_SUBST([FUZZ_ENGINE])dnl
+AC_SUBST([FUZZ_LD], ['$(CC)'])dnl
+AC_SUBST([INTERCEPT_EXP])dnl
+dnl
+dnl Config file paths
+dnl Either a single file or a colon-separated list of paths.
+dnl
+AC_SUBST([cvtsudoers_conf], ['$(sysconfdir)/cvtsudoers.conf'])dnl
+AC_SUBST([sudo_conf], ['$(sysconfdir)/sudo.conf'])dnl
+AC_SUBST([sudo_logsrvd_conf], ['$(sysconfdir)/sudo_logsrvd.conf'])dnl
+AC_SUBST([sudoers_path], ['$(sysconfdir)/sudoers'])dnl
+dnl
+dnl Variables that get substituted in docs (not overridden by environment)
+dnl
+AC_SUBST([iolog_dir])dnl real initial value from SUDO_IO_LOGDIR
+AC_SUBST([log_dir])dnl real initial value from SUDO_LOGDIR
+AC_SUBST([logpath])dnl real initial value from SUDO_LOGFILE
+AC_SUBST([relay_dir])dnl real initial value from SUDO_RELAY_DIR
+AC_SUBST([rundir])dnl real initial value from SUDO_RUNDIR
+AC_SUBST([vardir])dnl real initial value from SUDO_VARDIR
+AC_SUBST([timeout])
+AC_SUBST([password_timeout])
+AC_SUBST([sudo_umask])
+AC_SUBST([umask_override])
+AC_SUBST([passprompt])
+AC_SUBST([long_otp_prompt])
+AC_SUBST([lecture])
+AC_SUBST([logfac])
+AC_SUBST([goodpri])
+AC_SUBST([badpri])
+AC_SUBST([loglen])
+AC_SUBST([ignore_dot])
+AC_SUBST([mail_no_user])
+AC_SUBST([mail_no_host])
+AC_SUBST([mail_no_perms])
+AC_SUBST([mailto])
+AC_SUBST([mailsub])
+AC_SUBST([badpass_message])
+AC_SUBST([fqdn])
+AC_SUBST([runas_default])
+AC_SUBST([env_editor])
+AC_SUBST([env_reset])
+AC_SUBST([passwd_tries])
+AC_SUBST([timestamp_type])
+AC_SUBST([insults])
+AC_SUBST([root_sudo])
+AC_SUBST([path_info])
+AC_SUBST([ldap_conf])
+AC_SUBST([ldap_secret])
+AC_SUBST([sssd_lib])
+AC_SUBST([nsswitch_conf])
+AC_SUBST([netsvc_conf])
+AC_SUBST([secure_path])
+AC_SUBST([editor])
+AC_SUBST([pam_session])
+AC_SUBST([pam_login_service])
+AC_SUBST([plugindir])
+AC_SUBST([sudoers_plugin])
+AC_SUBST([python_plugin])
+#
+# Begin initial values for man page substitution
+#
+iolog_dir=/var/log/sudo-io
+log_dir=/var/log
+logpath=/var/log/sudo.log
+relay_dir=/var/log/sudo_logsrvd
+rundir=/var/run/sudo
+vardir=/var/adm/sudo
+timeout=5
+password_timeout=5
+sudo_umask=0022
+umask_override=off
+passprompt="Password: "
+long_otp_prompt=off
+lecture=once
+logfac=auth
+goodpri=notice
+badpri=alert
+loglen=80
+ignore_dot=off
+mail_no_user=on
+mail_no_host=off
+mail_no_perms=off
+mailto=root
+mailsub="*** SECURITY information for %h ***"
+badpass_message="Sorry, try again."
+fqdn=off
+runas_default=root
+env_editor=on
+env_reset=on
+editor=vi
+passwd_tries=3
+timestamp_type=tty
+insults=off
+root_sudo=on
+path_info=on
+ldap_conf=/etc/ldap.conf
+ldap_secret=/etc/ldap.secret
+netsvc_conf=/etc/netsvc.conf
+intercept_file="$libexecdir/sudo/sudo_intercept.so"
+noexec_file="$libexecdir/sudo/sudo_noexec.so"
+sesh_file="$libexecdir/sudo/sesh"
+nsswitch_conf=/etc/nsswitch.conf
+secure_path="not set"
+pam_session=on
+pam_login_service=sudo
+plugindir="$libexecdir/sudo"
+sudoers_plugin="sudoers.so"
+python_plugin="python_plugin.so"
+DIGEST=digest.lo
+devsearch="/dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev"
+#
+# End initial values for man page substitution
+#
+dnl
+dnl Initial values for Makefile variables listed above
+dnl May be overridden by environment variables..
+dnl
+: ${MANDIRTYPE='man'}
+: ${SHLIB_MODE='0644'}
+: ${SUDOERS_MODE='0440'}
+: ${SUDOERS_UID='0'}
+: ${SUDOERS_GID='0'}
+dnl
+dnl Other variables
+dnl
+CONFIGURE_ARGS="$@"
+AUTH_REG=
+AUTH_EXCL=
+AUTH_EXCL_DEF=
+AUTH_DEF=passwd
+CHECKSHADOW=true
+shadow_funcs=
+shadow_libs=
+OS_INIT=os_init_common
+
+dnl
+dnl libc replacement functions live in libsudo_util.a
+dnl
+AC_CONFIG_LIBOBJ_DIR(lib/util)
+
+dnl
+dnl We must call AC_USE_SYSTEM_EXTENSIONS before the compiler is run.
+dnl
+AC_USE_SYSTEM_EXTENSIONS
+
+#
+# Prior to sudo 1.8.7, sudo stored libexec files in $libexecdir.
+# Starting with sudo 1.8.7, $libexecdir/sudo is used so strip
+# off an extraneous "/sudo" from libexecdir.
+#
+case "$libexecdir" in
+ */sudo)
+ AC_MSG_WARN([libexecdir should not include the "sudo" subdirectory])
+ libexecdir=`expr "$libexecdir" : '\\(.*\\)/sudo$'`
+ ;;
+esac
+
+dnl
+dnl Deprecated --with options (these all warn or generate an error)
+dnl
+
+AC_ARG_WITH(otp-only, [AS_HELP_STRING([--with-otp-only], [deprecated])],
+[case $with_otp_only in
+ yes) with_passwd="no"
+ AC_MSG_NOTICE([--with-otp-only option deprecated, treating as --without-passwd])
+ ;;
+esac])
+
+AC_ARG_WITH(alertmail, [AS_HELP_STRING([--with-alertmail], [deprecated])],
+[case $with_alertmail in
+ *) with_mailto="$with_alertmail"
+ AC_MSG_NOTICE([--with-alertmail option deprecated, treating as --mailto])
+ ;;
+esac])
+
+AC_ARG_WITH(pc-insults, [AS_HELP_STRING([--with-pc-insults], [deprecated])],
+[case $with_pc_insults in
+ yes) enable_offensive_insults=no
+ AC_MSG_NOTICE([--with-pc-insults option deprecated, it is now the default])
+ ;;
+ no) enable_offensive_insults=yes
+ AC_MSG_NOTICE([--without-pc-insults option deprecated, use --enable-offensive-insults])
+ ;;
+esac])
+
+dnl
+dnl Options for --with
+dnl
+
+AC_ARG_WITH(devel, [AS_HELP_STRING([--with-devel], [add development options])],
+[case $with_devel in
+ yes) AC_MSG_NOTICE([setting up for development: -Wall, flex, yacc])
+ AX_APPEND_FLAG([-DSUDO_DEVEL], [CPPFLAGS])
+ DEVEL="true"
+ devdir=.
+ ;;
+ no) ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --with-devel: $with_devel])
+ ;;
+esac])
+
+AC_ARG_WITH(CC, [AS_HELP_STRING([--with-CC], [C compiler to use])],
+[case $with_CC in
+ *) AC_MSG_ERROR([the --with-CC option is no longer supported, please pass CC=$with_CC to configure instead.])
+ ;;
+esac])
+
+AC_ARG_WITH(rpath, [AS_HELP_STRING([--with-rpath], [deprecated, use --disable-rpath])],
+[AC_MSG_WARN([--with-rpath deprecated, rpath is now the default])])
+
+AC_ARG_WITH(blibpath, [AS_HELP_STRING([--with-blibpath[[=PATH]]], [deprecated])],
+[AC_MSG_WARN([--with-blibpath deprecated, use --with-libpath])])
+
+dnl
+dnl Handle BSM auditing support.
+dnl
+AC_ARG_WITH(bsm-audit, [AS_HELP_STRING([--with-bsm-audit], [enable BSM audit support])],
+[case $with_bsm_audit in
+ yes) AC_DEFINE(HAVE_BSM_AUDIT)
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lbsm"
+ SUDOERS_OBJS="${SUDOERS_OBJS} bsm_audit.lo"
+ ;;
+ no) ;;
+ *) AC_MSG_ERROR([--with-bsm-audit does not take an argument.])
+ ;;
+esac])
+
+dnl
+dnl Handle Linux auditing support.
+dnl
+AC_ARG_WITH(linux-audit, [AS_HELP_STRING([--with-linux-audit], [enable Linux audit support])],
+[case $with_linux_audit in
+ yes) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <libaudit.h>]], [[int i = AUDIT_USER_CMD; (void)i;]])], [
+ AC_DEFINE(HAVE_LINUX_AUDIT)
+ SUDO_LIBS="${SUDO_LIBS} -laudit"
+ SUDOERS_LIBS="${SUDO_LIBS} -laudit"
+ SUDOERS_OBJS="${SUDOERS_OBJS} linux_audit.lo"
+ ], [
+ AC_MSG_ERROR([unable to find AUDIT_USER_CMD in libaudit.h for --with-linux-audit])
+ ])
+ ;;
+ no) ;;
+ *) AC_MSG_ERROR([--with-linux-audit does not take an argument.])
+ ;;
+esac])
+
+dnl
+dnl Handle Solaris auditing support.
+dnl
+AC_ARG_WITH(solaris-audit, [AS_HELP_STRING([--with-solaris-audit], [enable Solaris audit support])],
+[case $with_solaris_audit in
+ yes) AC_DEFINE(HAVE_SOLARIS_AUDIT)
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lbsm"
+ SUDOERS_OBJS="${SUDOERS_OBJS} solaris_audit.lo"
+ ;;
+ no) ;;
+ *) AC_MSG_ERROR([--with-solaris-audit does not take an argument.])
+ ;;
+esac])
+
+dnl
+dnl Handle SSSD support.
+dnl
+AC_ARG_WITH(sssd, [AS_HELP_STRING([--with-sssd], [enable SSSD support])],
+[case $with_sssd in
+ yes) SUDOERS_OBJS="${SUDOERS_OBJS} sssd.lo"
+ case "$SUDOERS_OBJS" in
+ *ldap_util.lo*) ;;
+ *) SUDOERS_OBJS="${SUDOERS_OBJS} ldap_util.lo";;
+ esac
+ AC_DEFINE(HAVE_SSSD)
+ ;;
+ no) ;;
+ *) AC_MSG_ERROR([--with-sssd does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(sssd-conf, [AS_HELP_STRING([--with-sssd-conf], [path to the SSSD config file])])
+sssd_conf="/etc/sssd/sssd.conf"
+test -n "$with_sssd_conf" && sssd_conf="$with_sssd_conf"
+SUDO_DEFINE_UNQUOTED(_PATH_SSSD_CONF, "$sssd_conf", [Path to the SSSD config file])
+
+AC_ARG_WITH(sssd-lib, [AS_HELP_STRING([--with-sssd-lib], [path to the SSSD library])])
+sssd_lib="\"LIBDIR\""
+test -n "$with_sssd_lib" && sssd_lib="$with_sssd_lib"
+SUDO_DEFINE_UNQUOTED(_PATH_SSSD_LIB, "$sssd_lib", [Path to the SSSD library])
+
+AC_ARG_WITH(incpath, [AS_HELP_STRING([--with-incpath], [additional places to look for include files])],
+[case $with_incpath in
+ yes) AC_MSG_ERROR([must give --with-incpath an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-incpath not supported.])
+ ;;
+ *) AC_MSG_NOTICE([adding ${with_incpath} to CPPFLAGS])
+ for i in ${with_incpath}; do
+ AX_APPEND_FLAG([-I${i}], [CPPFLAGS])
+ done
+ ;;
+esac])
+
+AC_ARG_WITH(libpath, [AS_HELP_STRING([--with-libpath], [additional places to look for libraries])],
+[case $with_libpath in
+ yes) AC_MSG_ERROR([must give --with-libpath an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-libpath not supported.])
+ ;;
+ *) AC_MSG_NOTICE([adding ${with_libpath} to LDFLAGS])
+ ;;
+esac])
+
+AC_ARG_WITH(libraries, [AS_HELP_STRING([--with-libraries], [additional libraries to link with])],
+[case $with_libraries in
+ yes) AC_MSG_ERROR([must give --with-libraries an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-libraries not supported.])
+ ;;
+ *) AC_MSG_NOTICE([adding ${with_libraries} to LIBS])
+ ;;
+esac])
+
+AC_ARG_WITH(csops, [AS_HELP_STRING([--with-csops], [add CSOps standard options])],
+[case $with_csops in
+ yes) AC_MSG_NOTICE([adding CSOps standard options])
+ CHECKSIA=false
+ with_ignore_dot=yes
+ insults=on
+ with_classic_insults=yes
+ with_csops_insults=yes
+ with_env_editor=yes
+ : ${mansectsu='8'}
+ : ${mansectform='5'}
+ : ${mansectmisc='7'}
+ ;;
+ no) ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --with-csops: $with_csops])
+ ;;
+esac])
+
+AC_ARG_WITH(passwd, [AS_HELP_STRING([--without-passwd], [don't use passwd/shadow file for authentication])],
+[case $with_passwd in
+ yes|no) AUTH_DEF=""
+ test "$with_passwd" = "yes" && AUTH_REG="$AUTH_REG passwd"
+ ;;
+ *) AC_MSG_ERROR([sorry, --with-passwd does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(skey, [AS_HELP_STRING([--with-skey[[=DIR]]], [enable S/Key support ])],
+[case $with_skey in
+ no) ;;
+ *) AC_DEFINE(HAVE_SKEY)
+ AUTH_REG="$AUTH_REG S/Key"
+ ;;
+esac])
+
+AC_ARG_WITH(opie, [AS_HELP_STRING([--with-opie[[=DIR]]], [enable OPIE support ])],
+[case $with_opie in
+ no) ;;
+ *) AC_DEFINE(HAVE_OPIE)
+ AUTH_REG="$AUTH_REG NRL_OPIE"
+ ;;
+esac])
+
+AC_ARG_WITH(long-otp-prompt, [AS_HELP_STRING([--with-long-otp-prompt], [use a two line OTP (skey/opie) prompt])],
+[case $with_long_otp_prompt in
+ yes) AC_DEFINE(LONG_OTP_PROMPT)
+ long_otp_prompt=on
+ ;;
+ no) long_otp_prompt=off
+ ;;
+ *) AC_MSG_ERROR([--with-long-otp-prompt does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(SecurID, [AS_HELP_STRING([--with-SecurID[[=DIR]]], [enable SecurID support])],
+[case $with_SecurID in
+ no) ;;
+ *) AC_DEFINE(HAVE_SECURID)
+ AUTH_EXCL="$AUTH_EXCL SecurID"
+ ;;
+esac])
+
+AC_ARG_WITH(fwtk, [AS_HELP_STRING([--with-fwtk[[=DIR]]], [enable FWTK AuthSRV support])],
+[case $with_fwtk in
+ no) ;;
+ *) AC_DEFINE(HAVE_FWTK)
+ AUTH_EXCL="$AUTH_EXCL FWTK"
+ ;;
+esac])
+
+AC_ARG_WITH(kerb5, [AS_HELP_STRING([--with-kerb5[[=DIR]]], [enable Kerberos V support])],
+[case $with_kerb5 in
+ no) ;;
+ *) AUTH_REG="$AUTH_REG kerb5"
+ ;;
+esac])
+
+AC_ARG_WITH(aixauth, [AS_HELP_STRING([--with-aixauth], [enable AIX general authentication support])],
+[case $with_aixauth in
+ yes) AUTH_EXCL="$AUTH_EXCL AIX_AUTH";;
+ no) ;;
+ *) AC_MSG_ERROR([--with-aixauth does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(pam, [AS_HELP_STRING([--with-pam], [enable PAM support])],
+[case $with_pam in
+ yes) AUTH_EXCL="$AUTH_EXCL PAM";;
+ no) ;;
+ *) AC_MSG_ERROR([--with-pam does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(AFS, [AS_HELP_STRING([--with-AFS], [enable AFS support])],
+[case $with_AFS in
+ yes) AC_DEFINE(HAVE_AFS)
+ AUTH_REG="$AUTH_REG AFS"
+ ;;
+ no) ;;
+ *) AC_MSG_ERROR([--with-AFS does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(DCE, [AS_HELP_STRING([--with-DCE], [enable DCE support])],
+[case $with_DCE in
+ yes) AC_DEFINE(HAVE_DCE)
+ AUTH_REG="$AUTH_REG DCE"
+ ;;
+ no) ;;
+ *) AC_MSG_ERROR([--with-DCE does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(logincap, [AS_HELP_STRING([--with-logincap], [enable BSD login class support])],
+[case $with_logincap in
+ yes|no) ;;
+ *) AC_MSG_ERROR([--with-logincap does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(bsdauth, [AS_HELP_STRING([--with-bsdauth], [enable BSD authentication support])],
+[case $with_bsdauth in
+ yes) AUTH_EXCL="$AUTH_EXCL BSD_AUTH";;
+ no) ;;
+ *) AC_MSG_ERROR([--with-bsdauth does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(project, [AS_HELP_STRING([--with-project], [enable Solaris project support])],
+[case $with_project in
+ yes|no) ;;
+ no) ;;
+ *) AC_MSG_ERROR([--with-project does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(lecture, [AS_HELP_STRING([--without-lecture], [don't print lecture for first-time sudoer])],
+[case $with_lecture in
+ yes|short|always) lecture=once
+ ;;
+ no|none|never) lecture=never
+ AC_DEFINE(NO_LECTURE)
+ ;;
+ *) AC_MSG_ERROR([unknown argument to --with-lecture: $with_lecture])
+ ;;
+esac])
+
+AC_ARG_WITH(logging, [AS_HELP_STRING([--with-logging], [log via syslog, file, or both])],
+[case $with_logging in
+ yes) AC_MSG_ERROR([must give --with-logging an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-logging not supported.])
+ ;;
+ syslog) AC_DEFINE(LOGGING, SLOG_SYSLOG)
+ ;;
+ file) AC_DEFINE(LOGGING, SLOG_FILE)
+ ;;
+ both) AC_DEFINE(LOGGING, SLOG_BOTH)
+ ;;
+ *) AC_MSG_ERROR([unknown argument to --with-logging: $with_logging])
+ ;;
+esac], [
+ with_logging=syslog
+ AC_DEFINE(LOGGING, SLOG_SYSLOG)
+])
+
+AC_ARG_WITH(logfac, [AS_HELP_STRING([--with-logfac], [syslog facility to log with (default is "auth")])],
+[case $with_logfac in
+ yes) AC_MSG_ERROR([must give --with-logfac an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-logfac not supported.])
+ ;;
+ authpriv|auth|daemon|user|local0|local1|local2|local3|local4|local5|local6|local7) logfac=$with_logfac
+ ;;
+ *) AC_MSG_ERROR([$with_logfac is not a supported syslog facility.])
+ ;;
+esac])
+
+AC_ARG_WITH(goodpri, [AS_HELP_STRING([--with-goodpri], [syslog priority for commands (def is "notice")])],
+[case $with_goodpri in
+ yes) AC_MSG_ERROR([must give --with-goodpri an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-goodpri not supported.])
+ ;;
+ alert|crit|debug|emerg|err|info|notice|warning)
+ goodpri=$with_goodpri
+ ;;
+ *) AC_MSG_ERROR([$with_goodpri is not a supported syslog priority.])
+ ;;
+esac])
+AC_DEFINE_UNQUOTED(PRI_SUCCESS, "$goodpri", [The syslog priority sudo will use for successful attempts.])
+
+AC_ARG_WITH(badpri, [AS_HELP_STRING([--with-badpri], [syslog priority for failures (def is "alert")])],
+[case $with_badpri in
+ yes) AC_MSG_ERROR([must give --with-badpri an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-badpri not supported.])
+ ;;
+ alert|crit|debug|emerg|err|info|notice|warning)
+ badpri=$with_badpri
+ ;;
+ *) AC_MSG_ERROR([$with_badpri is not a supported syslog priority.])
+ ;;
+esac])
+AC_DEFINE_UNQUOTED(PRI_FAILURE, "$badpri", [The syslog priority sudo will use for unsuccessful attempts/errors.])
+
+AC_ARG_WITH(logpath, [AS_HELP_STRING([--with-logpath], [path to the sudo log file])],
+[case $with_logpath in
+ yes) AC_MSG_ERROR([must give --with-logpath an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-logpath not supported.])
+ ;;
+esac])
+
+AC_ARG_WITH(loglen, [AS_HELP_STRING([--with-loglen], [maximum length of a log file line (default is 80)])],
+[case $with_loglen in
+ yes) AC_MSG_ERROR([must give --with-loglen an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-loglen not supported.])
+ ;;
+ [[0-9]]*) loglen=$with_loglen
+ ;;
+ *) AC_MSG_ERROR([you must enter a number, not $with_loglen])
+ ;;
+esac])
+AC_DEFINE_UNQUOTED(MAXLOGFILELEN, $loglen, [The max number of chars per log file line (for line wrapping).])
+
+AC_ARG_WITH(ignore-dot, [AS_HELP_STRING([--with-ignore-dot], [ignore '.' in the PATH])],
+[case $with_ignore_dot in
+ yes) ignore_dot=on
+ AC_DEFINE(IGNORE_DOT_PATH)
+ ;;
+ no) ignore_dot=off
+ ;;
+ *) AC_MSG_ERROR([--with-ignore-dot does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(mail-if-no-user, [AS_HELP_STRING([--without-mail-if-no-user], [do not send mail if user not in sudoers])],
+[case $with_mail_if_no_user in
+ yes) mail_no_user=on
+ ;;
+ no) mail_no_user=off
+ ;;
+ *) AC_MSG_ERROR([--with-mail-if-no-user does not take an argument.])
+ ;;
+esac])
+AS_IF([test "$mail_no_user" = "on"], [AC_DEFINE(SEND_MAIL_WHEN_NO_USER)])
+
+AC_ARG_WITH(mail-if-no-host, [AS_HELP_STRING([--with-mail-if-no-host], [send mail if user in sudoers but not for this host])],
+[case $with_mail_if_no_host in
+ yes) mail_no_host=on
+ AC_DEFINE(SEND_MAIL_WHEN_NO_HOST)
+ ;;
+ no) mail_no_host=off
+ ;;
+ *) AC_MSG_ERROR([--with-mail-if-no-host does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(mail-if-noperms, [AS_HELP_STRING([--with-mail-if-noperms], [send mail if user not allowed to run command])],
+[case $with_mail_if_noperms in
+ yes) mail_noperms=on
+ AC_DEFINE(SEND_MAIL_WHEN_NOT_OK)
+ ;;
+ no) mail_noperms=off
+ ;;
+ *) AC_MSG_ERROR([--with-mail-if-noperms does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(mailto, [AS_HELP_STRING([--with-mailto], [who should get sudo mail (default is "root")])],
+[case $with_mailto in
+ yes) AC_MSG_ERROR([must give --with-mailto an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-mailto not supported.])
+ ;;
+ *) mailto=$with_mailto
+ ;;
+esac])
+AC_DEFINE_UNQUOTED(MAILTO, "$mailto", [The user or email address that sudo mail is sent to.])
+
+AC_ARG_WITH(mailsubject, [AS_HELP_STRING([--with-mailsubject], [subject of sudo mail])],
+[case $with_mailsubject in
+ yes) AC_MSG_ERROR([must give --with-mailsubject an argument.])
+ ;;
+ no) AC_MSG_WARN([sorry, --without-mailsubject not supported.])
+ ;;
+ *) mailsub="$with_mailsubject"
+ ;;
+esac])
+AC_DEFINE_UNQUOTED(MAILSUBJECT, "$mailsub", [The subject of the mail sent by sudo to the MAILTO user/address.])
+
+AC_ARG_WITH(passprompt, [AS_HELP_STRING([--with-passprompt], [default password prompt])],
+[case $with_passprompt in
+ yes) AC_MSG_ERROR([must give --with-passprompt an argument.])
+ ;;
+ no) AC_MSG_WARN([sorry, --without-passprompt not supported.])
+ ;;
+ *) passprompt="$with_passprompt"
+esac])
+AC_DEFINE_UNQUOTED(PASSPROMPT, "$passprompt", [The default password prompt.])
+
+AC_ARG_WITH(badpass-message, [AS_HELP_STRING([--with-badpass-message], [message the user sees when the password is wrong])],
+[case $with_badpass_message in
+ yes) AC_MSG_ERROR([must give --with-badpass-message an argument.])
+ ;;
+ no) AC_MSG_WARN([sorry, --without-badpass-message not supported.])
+ ;;
+ *) badpass_message="$with_badpass_message"
+ ;;
+esac])
+AC_DEFINE_UNQUOTED(INCORRECT_PASSWORD, "$badpass_message", [The message given when a bad password is entered.])
+
+AC_ARG_WITH(fqdn, [AS_HELP_STRING([--with-fqdn], [expect fully qualified hosts in sudoers])],
+[case $with_fqdn in
+ yes) fqdn=on
+ AC_DEFINE(FQDN)
+ ;;
+ no) fqdn=off
+ ;;
+ *) AC_MSG_ERROR([--with-fqdn does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(timedir, [AS_HELP_STRING([--with-timedir=DIR], [deprecated])],
+[case $with_timedir in
+ *) AC_MSG_ERROR([--without-timedir no longer supported, see --with-rundir.])
+ ;;
+esac])
+
+AC_ARG_WITH(rundir, [AS_HELP_STRING([--with-rundir=DIR], [directory for sudo-specific files that do not survive a system reboot, e.g. '/var/run/sudo'])],
+[case $with_rundir in
+ yes) AC_MSG_ERROR([must give --with-rundir an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-rundir not supported.])
+ ;;
+esac])
+
+AC_ARG_WITH(vardir, [AS_HELP_STRING([--with-vardir=DIR], [directory for sudo-specific files that survive a system reboot, e.g. '/var/db/sudo' or '/var/lib/sudo'])],
+[case $with_vardir in
+ yes) AC_MSG_ERROR([must give --with-vardir an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-vardir not supported.])
+ ;;
+esac])
+
+AC_ARG_WITH(iologdir, [AS_HELP_STRING([--with-iologdir=DIR], [directory to store sudo I/O log files in])],
+[case $with_iologdir in
+ yes) ;;
+ no) AC_MSG_ERROR([--without-iologdir not supported.])
+ ;;
+esac])
+
+AC_ARG_WITH(relaydir, [AS_HELP_STRING([--with-relaydir=DIR], [directory to store sudo_logsrvd relay temporary files in])],
+[case $with_relaydir in
+ yes) ;;
+ no) AC_MSG_ERROR([--without-relaydir not supported.])
+ ;;
+esac])
+
+AC_ARG_WITH(tzdir, [AS_HELP_STRING([--with-tzdir=DIR], [path to the time zone data directory])],
+[case $with_tzdir in
+ yes) AC_MSG_ERROR([must give --with-tzdir an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(sendmail, [AS_HELP_STRING([--with-sendmail], [set path to sendmail])
+AS_HELP_STRING([--without-sendmail], [do not send mail at all])],
+[case $with_sendmail in
+ yes) with_sendmail=""
+ ;;
+ no) ;;
+ *) SUDO_DEFINE_UNQUOTED(_PATH_SUDO_SENDMAIL, "$with_sendmail")
+ ;;
+esac])
+
+AC_ARG_WITH(sudoers-mode, [AS_HELP_STRING([--with-sudoers-mode], [mode of sudoers file (defaults to 0440)])],
+[case $with_sudoers_mode in
+ yes) AC_MSG_ERROR([must give --with-sudoers-mode an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-sudoers-mode not supported.])
+ ;;
+ [[1-9]]*) SUDOERS_MODE=0${with_sudoers_mode}
+ ;;
+ 0*) SUDOERS_MODE=$with_sudoers_mode
+ ;;
+ *) AC_MSG_ERROR([you must use an octal mode, not a name.])
+ ;;
+esac])
+
+AC_ARG_WITH(sudoers-uid, [AS_HELP_STRING([--with-sudoers-uid], [uid that owns sudoers file (defaults to 0)])],
+[case $with_sudoers_uid in
+ yes) AC_MSG_ERROR([must give --with-sudoers-uid an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-sudoers-uid not supported.])
+ ;;
+ [[0-9]]*) SUDOERS_UID=$with_sudoers_uid
+ ;;
+ *) AC_MSG_ERROR([you must use an unsigned numeric uid, not a name.])
+ ;;
+esac])
+
+AC_ARG_WITH(sudoers-gid, [AS_HELP_STRING([--with-sudoers-gid], [gid that owns sudoers file (defaults to 0)])],
+[case $with_sudoers_gid in
+ yes) AC_MSG_ERROR([must give --with-sudoers-gid an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-sudoers-gid not supported.])
+ ;;
+ [[0-9]]*) SUDOERS_GID=$with_sudoers_gid
+ ;;
+ *) AC_MSG_ERROR([you must use an unsigned numeric gid, not a name.])
+ ;;
+esac])
+
+AC_ARG_WITH(umask, [AS_HELP_STRING([--with-umask], [umask with which the prog should run (default is 022)])
+AS_HELP_STRING([--without-umask], [Preserves the umask of the user invoking sudo.])],
+[case $with_umask in
+ yes) AC_MSG_ERROR([must give --with-umask an argument.])
+ ;;
+ no) sudo_umask=0777
+ ;;
+ [[0-9]]*) sudo_umask=$with_umask
+ ;;
+ *) AC_MSG_ERROR([you must enter a numeric mask.])
+ ;;
+esac])
+AC_DEFINE_UNQUOTED(SUDO_UMASK, $sudo_umask, [The umask that the sudo-run prog should use.])
+
+AC_ARG_WITH(umask-override, [AS_HELP_STRING([--with-umask-override], [Use the umask specified in sudoers even if it is less restrictive than the user's.])],
+[case $with_umask_override in
+ yes) AC_DEFINE(UMASK_OVERRIDE)
+ umask_override=on
+ ;;
+ no) umask_override=off
+ ;;
+ *) AC_MSG_ERROR([--with-umask-override does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(runas-default, [AS_HELP_STRING([--with-runas-default], [User to run commands as (default is "root")])],
+[case $with_runas_default in
+ yes) AC_MSG_ERROR([must give --with-runas-default an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-runas-default not supported.])
+ ;;
+ *) runas_default="$with_runas_default"
+ ;;
+esac])
+AC_DEFINE_UNQUOTED(RUNAS_DEFAULT, "$runas_default", [The user sudo should run commands as by default.])
+
+AC_ARG_WITH(exempt, [AS_HELP_STRING([--with-exempt=group], [no passwd needed for users in this group])],
+[case $with_exempt in
+ yes) AC_MSG_ERROR([must give --with-exempt an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-exempt not supported.])
+ ;;
+ *) AC_DEFINE_UNQUOTED(EXEMPTGROUP, "$with_exempt", [If defined, users in this group need not enter a passwd (ie "sudo").])
+ ;;
+esac])
+
+AC_ARG_WITH(editor, [AS_HELP_STRING([--with-editor=path], [Default editor for visudo (defaults to vi)])],
+[case $with_editor in
+ yes) AC_MSG_ERROR([must give --with-editor an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-editor not supported.])
+ ;;
+ *) AC_DEFINE_UNQUOTED(EDITOR, "$with_editor", [A colon-separated list of pathnames to be used as the editor for visudo.])
+ editor="$with_editor"
+ ;;
+esac], [AC_DEFINE(EDITOR, _PATH_VI)])
+
+AC_ARG_WITH(env-editor, [AS_HELP_STRING([--with-env-editor], [Use the environment variable EDITOR for visudo])],
+[case $with_env_editor in
+ yes) env_editor=on
+ ;;
+ no) env_editor=off
+ ;;
+ *) AC_MSG_ERROR([--with-env-editor does not take an argument.])
+ ;;
+esac])
+AS_IF([test "$env_editor" = "on"], [AC_DEFINE(ENV_EDITOR)])
+
+AC_ARG_WITH(passwd-tries, [AS_HELP_STRING([--with-passwd-tries], [number of tries to enter password (default is 3)])],
+[case $with_passwd_tries in
+ yes) ;;
+ no) AC_MSG_ERROR([--without-editor not supported.])
+ ;;
+ [[1-9]]*) passwd_tries=$with_passwd_tries
+ ;;
+ *) AC_MSG_ERROR([you must enter the number of tries, > 0])
+ ;;
+esac])
+AC_DEFINE_UNQUOTED(TRIES_FOR_PASSWORD, $passwd_tries, [The number of tries a user gets to enter their password.])
+
+AC_ARG_WITH(timeout, [AS_HELP_STRING([--with-timeout], [minutes before sudo asks for passwd again (def is 5 minutes)])],
+[case $with_timeout in
+ yes) ;;
+ no) timeout=0
+ ;;
+ [[0-9]]*) timeout=$with_timeout
+ ;;
+ *) AC_MSG_ERROR([you must enter the number of minutes.])
+ ;;
+esac])
+AC_DEFINE_UNQUOTED(TIMEOUT, $timeout, [The number of minutes before sudo asks for a password again.])
+
+AC_ARG_WITH(password-timeout, [AS_HELP_STRING([--with-password-timeout], [passwd prompt timeout in minutes (default is 5 minutes)])],
+[case $with_password_timeout in
+ yes) ;;
+ no) password_timeout=0
+ ;;
+ [[0-9]]*) password_timeout=$with_password_timeout
+ ;;
+ *) AC_MSG_ERROR([you must enter the number of minutes.])
+ ;;
+esac])
+AC_DEFINE_UNQUOTED(PASSWORD_TIMEOUT, $password_timeout, [The passwd prompt timeout (in minutes).])
+
+AC_ARG_WITH(tty-tickets, [AS_HELP_STRING([--with-tty-tickets], [use a different ticket file for each tty])],
+[case $with_tty_tickets in
+ yes) timestamp_type=tty
+ ;;
+ no) timestamp_type=global
+ ;;
+ *) AC_MSG_ERROR([--with-tty-tickets does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(insults, [AS_HELP_STRING([--with-insults], [insult the user for entering an incorrect password])],
+[case $with_insults in
+ yes) insults=on
+ AC_DEFINE(USE_INSULTS)
+ with_classic_insults=yes
+ with_csops_insults=yes
+ ;;
+ disabled) insults=off
+ with_classic_insults=yes
+ with_csops_insults=yes
+ ;;
+ no) insults=off
+ ;;
+ *) AC_MSG_ERROR([--with-insults does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(all-insults, [AS_HELP_STRING([--with-all-insults], [include all the sudo insult sets])],
+[case $with_all_insults in
+ yes) with_classic_insults=yes
+ with_csops_insults=yes
+ with_hal_insults=yes
+ with_goons_insults=yes
+ with_python_insults=yes
+ ;;
+ no) ;;
+ *) AC_MSG_ERROR([--with-all-insults does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(classic-insults, [AS_HELP_STRING([--with-classic-insults], [include the insults from the "classic" sudo])],
+[case $with_classic_insults in
+ yes) AC_DEFINE(CLASSIC_INSULTS)
+ ;;
+ no) ;;
+ *) AC_MSG_ERROR([--with-classic-insults does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(csops-insults, [AS_HELP_STRING([--with-csops-insults], [include CSOps insults])],
+[case $with_csops_insults in
+ yes) AC_DEFINE(CSOPS_INSULTS)
+ ;;
+ no) ;;
+ *) AC_MSG_ERROR([--with-csops-insults does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(hal-insults, [AS_HELP_STRING([--with-hal-insults], [include 2001-like insults])],
+[case $with_hal_insults in
+ yes) AC_DEFINE(HAL_INSULTS)
+ ;;
+ no) ;;
+ *) AC_MSG_ERROR([--with-hal-insults does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(goons-insults, [AS_HELP_STRING([--with-goons-insults], [include the insults from the "Goon Show"])],
+[case $with_goons_insults in
+ yes) AC_DEFINE(GOONS_INSULTS)
+ ;;
+ no) ;;
+ *) AC_MSG_ERROR([--with-goons-insults does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(python-insults, [AS_HELP_STRING([--with-python-insults], [include the insults from "Monty Python's Flying Circus"])],
+[case $with_python_insults in
+ yes) AC_DEFINE(PYTHON_INSULTS)
+ ;;
+ no) ;;
+ *) AC_MSG_ERROR([--with-python-insults does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(nsswitch, [AS_HELP_STRING([--with-nsswitch[[=PATH]]], [path to nsswitch.conf])],
+[case $with_nsswitch in
+ no) ;;
+ yes) with_nsswitch="/etc/nsswitch.conf"
+ ;;
+ *) ;;
+esac])
+
+AC_ARG_WITH(ldap, [AS_HELP_STRING([--with-ldap[[=DIR]]], [enable LDAP support])],
+[case $with_ldap in
+ no) ;;
+ *) AC_DEFINE(HAVE_LDAP)
+ ;;
+esac])
+
+AC_ARG_WITH(ldap-conf-file, [AS_HELP_STRING([--with-ldap-conf-file], [path to LDAP configuration file])])
+test -n "$with_ldap_conf_file" && ldap_conf="$with_ldap_conf_file"
+SUDO_DEFINE_UNQUOTED(_PATH_LDAP_CONF, "$ldap_conf", [Path to the ldap.conf file])
+
+AC_ARG_WITH(ldap-secret-file, [AS_HELP_STRING([--with-ldap-secret-file], [path to LDAP secret password file])])
+test -n "$with_ldap_secret_file" && ldap_secret="$with_ldap_secret_file"
+SUDO_DEFINE_UNQUOTED(_PATH_LDAP_SECRET, "$ldap_secret", [Path to the ldap.secret file])
+
+AC_ARG_WITH(secure-path, [AS_HELP_STRING([--with-secure-path], [override the user's path with a built-in one])],
+[case $with_secure_path in
+ yes) with_secure_path="/bin:/usr/ucb:/usr/bin:/usr/sbin:/sbin:/usr/etc:/etc"
+ AC_DEFINE_UNQUOTED(SECURE_PATH, "$with_secure_path")
+ secure_path="set to $with_secure_path"
+ ;;
+ no) ;;
+ *) AC_DEFINE_UNQUOTED(SECURE_PATH, "$with_secure_path")
+ secure_path="set to $with_secure_path"
+ ;;
+esac])
+
+AC_ARG_WITH(interfaces, [AS_HELP_STRING([--without-interfaces], [don't try to read the ip addr of network interfaces])],
+[case $with_interfaces in
+ yes) ;;
+ no) AC_DEFINE(STUB_LOAD_INTERFACES)
+ ;;
+ *) AC_MSG_ERROR([--with-interfaces does not take an argument.])
+ ;;
+esac])
+
+AC_ARG_WITH(askpass, [AS_HELP_STRING([--with-askpass=PATH], [Fully qualified pathname of askpass helper])],
+[case $with_askpass in
+ yes) AC_MSG_ERROR([--with-askpass takes a path as an argument.])
+ ;;
+ no) ;;
+ *) ;;
+esac], [
+ with_askpass=no
+])
+AS_IF([test X"$with_askpass" != X"no"], [
+ SUDO_DEFINE_UNQUOTED(_PATH_SUDO_ASKPASS, "$with_askpass")
+], [
+ SUDO_DEFINE_UNQUOTED(_PATH_SUDO_ASKPASS, NULL)
+])
+
+AC_ARG_WITH(exampledir, [AS_HELP_STRING([--with-exampledir=DIR], [path to install sudo examples in])],
+[case $with_exampledir in
+ yes) AC_MSG_ERROR([must give --with-exampledir an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-exampledir not supported.])
+ ;;
+ *) exampledir="$with_exampledir"
+esac])
+
+AC_ARG_WITH(plugindir, [AS_HELP_STRING([--with-plugindir=DIR], [set directory to load plugins from])],
+[case $with_plugindir in
+ yes) AC_MSG_ERROR([must give --with-plugindir an argument.])
+ ;;
+ no) AC_MSG_ERROR([--without-plugindir not supported.])
+ ;;
+ *) plugindir="$with_plugindir"
+ ;;
+esac])
+
+AC_ARG_WITH(man, [AS_HELP_STRING([--with-man], [manual pages use man macros])],
+[case $with_man in
+ yes) MANTYPE=man
+ ;;
+ no) AC_MSG_ERROR([--without-man not supported.])
+ ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --with-man: $with_man.])
+ ;;
+esac])
+
+AC_ARG_WITH(mdoc, [AS_HELP_STRING([--with-mdoc], [manual pages use mdoc macros])],
+[case $with_mdoc in
+ yes) MANTYPE=mdoc
+ ;;
+ no) AC_MSG_ERROR([--without-mdoc not supported.])
+ ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --with-mdoc: $with_mdoc.])
+ ;;
+esac])
+
+dnl
+dnl Options for --enable
+dnl
+
+AC_ARG_ENABLE(authentication,
+[AS_HELP_STRING([--disable-authentication], [Do not require authentication by default])],
+[ case "$enableval" in
+ yes) ;;
+ no) AC_DEFINE(NO_AUTHENTICATION)
+ ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --enable-authentication: $enableval])
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(root-mailer,
+[AS_HELP_STRING([--disable-root-mailer], [Don't run the mailer as root, run as the user])],
+[ case "$enableval" in
+ yes) ;;
+ no) AC_DEFINE(NO_ROOT_MAILER)
+ ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --enable-root-mailer: $enableval])
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(setreuid,
+[AS_HELP_STRING([--disable-setreuid], [Don't try to use the setreuid() function])],
+[ case "$enableval" in
+ no) SKIP_SETREUID=yes
+ ;;
+ *) ;;
+ esac
+])
+
+AC_ARG_ENABLE(setresuid,
+[AS_HELP_STRING([--disable-setresuid], [Don't try to use the setresuid() function])],
+[ case "$enableval" in
+ no) SKIP_SETRESUID=yes
+ ;;
+ *) ;;
+ esac
+])
+
+AC_ARG_ENABLE(shadow,
+[AS_HELP_STRING([--disable-shadow], [Never use shadow passwords])],
+[ case "$enableval" in
+ yes) ;;
+ no) CHECKSHADOW="false"
+ ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --enable-shadow: $enableval])
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(root-sudo,
+[AS_HELP_STRING([--disable-root-sudo], [Don't allow root to run sudo])],
+[ case "$enableval" in
+ yes) ;;
+ no) AC_DEFINE(NO_ROOT_SUDO)
+ root_sudo=off
+ ;;
+ *) AC_MSG_ERROR([--enable-root-sudo does not take an argument.])
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(log-host,
+[AS_HELP_STRING([--enable-log-host], [Log the hostname in the log file])],
+[ case "$enableval" in
+ yes) AC_DEFINE(HOST_IN_LOG)
+ ;;
+ no) ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --enable-log-host: $enableval])
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(noargs-shell,
+[AS_HELP_STRING([--enable-noargs-shell], [If sudo is given no arguments run a shell])],
+[ case "$enableval" in
+ yes) AC_DEFINE(SHELL_IF_NO_ARGS)
+ ;;
+ no) ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --enable-noargs-shell: $enableval])
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(shell-sets-home,
+[AS_HELP_STRING([--enable-shell-sets-home], [Set $HOME to target user in shell mode])],
+[ case "$enableval" in
+ yes) AC_DEFINE(SHELL_SETS_HOME)
+ ;;
+ no) ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --enable-shell-sets-home: $enableval])
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(path_info,
+[AS_HELP_STRING([--disable-path-info], [Print 'command not allowed' not 'command not found'])],
+[ case "$enableval" in
+ yes) ;;
+ no) AC_DEFINE(DONT_LEAK_PATH_INFO)
+ path_info=off
+ ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --enable-path-info: $enableval])
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(env_debug,
+[AS_HELP_STRING([--enable-env-debug], [Whether to enable environment debugging.])],
+[ case "$enableval" in
+ yes) AC_DEFINE(ENV_DEBUG)
+ ;;
+ no) ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --enable-env-debug: $enableval])
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(postinstall,
+[AS_HELP_STRING([--enable-postinstall], [Script to run after the install phase])],
+[ case "$enableval" in
+ yes) AC_MSG_ERROR([must give --enable-postinstall an argument.])
+ ;;
+ no) AC_MSG_ERROR([--enable-postinstall not supported.])
+ ;;
+ *) POSTINSTALL="$enableval"
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(zlib,
+[AS_HELP_STRING([--enable-zlib[[=PATH]]], [Whether to enable or disable zlib])],
+[], [enable_zlib=yes])
+AX_APPEND_FLAG([-DZLIB_CONST], [CPPFLAGS])
+
+AC_ARG_ENABLE(env_reset,
+[AS_HELP_STRING([--enable-env-reset], [Whether to enable environment resetting by default.])],
+[ case "$enableval" in
+ yes) env_reset=on
+ ;;
+ no) env_reset=off
+ ;;
+ *) env_reset=on
+ AC_MSG_WARN([ignoring unknown argument to --enable-env-reset: $enableval])
+ ;;
+ esac
+])
+AS_IF([test "$env_reset" = "on"], [
+ AC_DEFINE(ENV_RESET, 1)
+], [
+ AC_DEFINE(ENV_RESET, 0)
+])
+
+AC_ARG_ENABLE(warnings,
+[AS_HELP_STRING([--enable-warnings], [Whether to enable compiler warnings])],
+[ case "$enableval" in
+ yes) ;;
+ no) ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --enable-warnings: $enableval])
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(werror,
+[AS_HELP_STRING([--enable-werror], [Whether to enable the -Werror compiler option])],
+[ case "$enableval" in
+ yes) ;;
+ no) ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --enable-werror: $enableval])
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(ssp,
+[AS_HELP_STRING([--disable-ssp], [Do not compile using the -fstack-protector option.])],
+[], [enable_ssp=yes])
+
+AC_ARG_ENABLE(hardening,
+[AS_HELP_STRING([--disable-hardening], [Do not use compiler/linker exploit mitigation options])],
+[], [enable_hardening=yes])
+
+AC_ARG_ENABLE(pie,
+[AS_HELP_STRING([--enable-pie], [Build sudo as a position independent executable.])])
+
+AC_ARG_ENABLE(sanitizer,
+[AS_HELP_STRING([--enable-sanitizer], [Build sudo with sanitizer support.])], [
+ AS_IF([test X"$enable_sanitizer" = X"yes"], [
+ enable_sanitizer="-fsanitize=address,undefined"
+ ])
+], [enable_sanitizer=no])
+
+AC_ARG_ENABLE(fuzzer,
+[AS_HELP_STRING([--enable-fuzzer], [Build sudo with LLVM libFuzzer support.])],
+[], [enable_fuzzer=no])
+
+AC_ARG_ENABLE(fuzzer-engine,
+[AS_HELP_STRING([--enable-fuzzer-engine], [Link fuzz targets with the specified fuzzer engine instead of the default.])],
+[ case "$enableval" in
+ yes) AC_MSG_ERROR([must give --enable-fuzzer-engine an argument.])
+ ;;
+ no) ;;
+ *) FUZZ_ENGINE="$enableval"
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(fuzzer-linker,
+[AS_HELP_STRING([--enable-fuzzer-linker], [Use the specified linker when building fuzz targets instead of the default C compiler.])],
+[ case "$enableval" in
+ yes) AC_MSG_ERROR([must give --enable-fuzzer-linker an argument.])
+ ;;
+ no) ;;
+ *) FUZZ_LD="$enableval"
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(leaks,
+[AS_HELP_STRING([--disable-leaks], [Prevent some harmless memory leaks.])],
+[ case "$enableval" in
+ yes) ;;
+ no) AC_DEFINE(NO_LEAKS)
+ ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --disable-leaks: $enableval])
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(poll,
+[AS_HELP_STRING([--disable-poll], [Use select() instead of poll().])])
+
+AC_ARG_ENABLE(admin-flag,
+[AS_HELP_STRING([--enable-admin-flag[[=PATH]]], [Whether to create a Ubuntu-style admin flag file])],
+[ case "$enableval" in
+ yes) SUDO_DEFINE_UNQUOTED(_PATH_SUDO_ADMIN_FLAG, "~/.sudo_as_admin_successful")
+ ;;
+ no) ;;
+ *) SUDO_DEFINE_UNQUOTED(_PATH_SUDO_ADMIN_FLAG, "$enableval")
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(nls,
+[AS_HELP_STRING([--disable-nls], [Disable natural language support using gettext])],
+[], [enable_nls=yes])
+
+AC_ARG_ENABLE(rpath,
+[AS_HELP_STRING([--disable-rpath], [Disable passing of -Rpath to the linker])],
+[], [enable_rpath=yes])
+
+AC_ARG_ENABLE(static-sudoers,
+[AS_HELP_STRING([--enable-static-sudoers], [Build the sudoers policy module as part of the sudo binary instead as a plugin])],
+[], [enable_static_sudoers=no])
+
+AC_ARG_ENABLE(shared_libutil,
+[AS_HELP_STRING([--disable-shared-libutil], [Disable use of the libsudo_util shared library.])],
+[], [enable_shared_libutil=yes])
+
+AC_ARG_ENABLE(tmpfiles.d,
+[AS_HELP_STRING([--enable-tmpfiles.d=DIR], [Set the path to the systemd tmpfiles.d directory.])],
+[case $enableval in
+ yes) TMPFILES_D=/usr/lib/tmpfiles.d
+ ;;
+ no) TMPFILES_D=
+ ;;
+ *) TMPFILES_D="$enableval"
+esac], [
+ test -f /usr/lib/tmpfiles.d/systemd.conf && TMPFILES_D=/usr/lib/tmpfiles.d
+])
+
+AC_ARG_ENABLE(devsearch,
+[AS_HELP_STRING([--enable-devsearch=PATH], [The colon-delimited path to search for device nodes when determining the tty name.])],
+[case $enableval in
+ yes) # use default value
+ ;;
+ no) AC_MSG_WARN([ignoring attempt to disable the device search path])
+ ;;
+ *) devsearch="$enableval"
+ ;;
+esac])
+ds="`echo \"$devsearch\"|sed 's@/dev/*\([[^:]]*:*\)@_PATH_DEV \"\1\" @g'`"
+SUDO_DEFINE_UNQUOTED(_PATH_SUDO_DEVSEARCH, $ds)
+
+AC_ARG_WITH(selinux, [AS_HELP_STRING([--with-selinux], [enable SELinux support])],
+[case $with_selinux in
+ yes) SELINUX_USAGE="[[-r role]] [[-t type]] "
+ AC_DEFINE(HAVE_SELINUX)
+ SUDO_LIBS="${SUDO_LIBS} -lselinux"
+ SUDO_OBJS="${SUDO_OBJS} selinux.o"
+ PROGS="${PROGS} sesh"
+ SEMAN=1
+ AC_CHECK_LIB([selinux], [setkeycreatecon],
+ [AC_DEFINE(HAVE_SETKEYCREATECON)])
+ ;;
+ no) ;;
+ *) AC_MSG_ERROR([--with-selinux does not take an argument.])
+ ;;
+esac], [with_selinux=no])
+
+AC_ARG_WITH(apparmor, [AS_HELP_STRING([--with-apparmor], [enable AppArmor support])],
+[case $with_apparmor in
+ yes) AC_DEFINE(HAVE_APPARMOR)
+ AAMAN=1
+ SUDO_LIBS="${SUDO_LIBS} -lapparmor"
+ SUDO_OBJS="${SUDO_OBJS} apparmor.o"
+ ;;
+ no) ;;
+ *) AC_MSG_ERROR([--with-apparmor does not take an argument.])
+
+esac], [with_apparmor=no])
+
+AC_ARG_ENABLE(sasl,
+[AS_HELP_STRING([--enable-sasl], [Enable/disable LDAP SASL support])],
+[ case "$enableval" in
+ yes|no) ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --enable-sasl: $enableval])
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(timestamp-type,
+[AS_HELP_STRING([--timestamp-type=TYPE], [Set the default time stamp record type to global, ppid or tty.])],
+[ case "$enableval" in
+ global|ppid|tty)
+ timestamp_type=$enableval
+ ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --enable-timestamp-type: $enableval])
+ ;;
+ esac
+])
+AC_DEFINE_UNQUOTED(TIMESTAMP_TYPE, $timestamp_type)
+
+AC_ARG_ENABLE(offensive_insults,
+[AS_HELP_STRING([--enable-offensive-insults], [Enable potentially offensive sudo insults.])],
+[], [enable_offensive_insults=no])
+AS_IF([test "$enable_offensive_insults" = "yes"], [AC_DEFINE(OFFENSIVE_INSULTS)])
+
+AC_ARG_ENABLE(package_build,
+[AS_HELP_STRING([--enable-package-build], [Enable options for package building.])],
+[], [enable_package_build=no])
+
+dnl
+dnl gss_krb5_ccache_name() may not work on Heimdal so we don't use it by default
+dnl
+AC_ARG_ENABLE(gss_krb5_ccache_name,
+[AS_HELP_STRING([--enable-gss-krb5-ccache-name], [Use GSS-API to set the Kerberos V cred cache name])],
+[check_gss_krb5_ccache_name=$enableval], [check_gss_krb5_ccache_name=no])
+
+AC_ARG_ENABLE(pvs-studio,
+[AS_HELP_STRING([--enable-pvs-studio], [Create a PVS-Studio.cfg file.])])
+
+AC_ARG_ENABLE(log-server,
+[AS_HELP_STRING([--disable-log-server], [Disable building the sudo_logsrvd log server.])],
+[ case "$enableval" in
+ yes)
+ ;;
+ no)
+ LOGSRV=#
+ LOGSRVD_SRC=
+ LOGSRVD_CONF=
+ ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --enable-log-server: $enableval])
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(log-client,
+[AS_HELP_STRING([--disable-log-client], [Disable sudoers support for using the sudo_logsrvd log server.])],
+[ case "$enableval" in
+ yes)
+ AC_DEFINE([SUDOERS_LOG_CLIENT])
+ ;;
+ no)
+ ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --enable-log-client: $enableval])
+ ;;
+ esac
+], [AC_DEFINE([SUDOERS_LOG_CLIENT])])
+
+AS_IF([test X"${enable_log_client}${enable_log_server}" = X"nono"], [
+ # No need for liblogsrv.la
+ LOGSRV_SRC=
+ LIBLOGSRV=
+])
+AS_IF([test X"$LOGSRVD_SRC" != X""], [
+ PPFILES="$PPFILES "'$(srcdir)/etc/sudo-logsrvd.pp'
+])
+
+dnl
+dnl Do OpenSSL / wolfSSL / gcrypt after logsrv options
+dnl
+AC_ARG_ENABLE(openssl,
+[AS_HELP_STRING([--enable-openssl], [Use OpenSSL's TLS and sha2 functions])],
+[], [
+ # Enable OpenSSL by default unless logsrvd and client are disabled
+ AS_IF([test X"${enable_log_client}${enable_log_server}" != X"nono"], [
+ enable_openssl=maybe
+ ])
+])
+AC_ARG_ENABLE(openssl-pkgconfig-template,
+[AS_HELP_STRING([--enable-openssl-pkgconfig-template], [A printf format string used to construct the OpenSSL pkg-config name])],
+[], [enable_openssl_pkgconfig_template="%s"])
+
+AC_ARG_ENABLE(wolfssl,
+[AS_HELP_STRING([--enable-wolfssl], [Use wolfSSL's TLS and sha2 functions])], [
+ enable_openssl=no
+])
+
+AC_ARG_ENABLE(gcrypt,
+[AS_HELP_STRING([--enable-gcrypt], [Use GNU crypt's sha2 functions])], [
+ AS_IF([test "${enable_openssl-no}${enable_wolfssl-no}" != "nono"], [
+ AC_MSG_WARN([ignoring --enable-gcrypt when OpenSSL or wolfSSL is enabled.])
+ enable_gcrypt=no
+ ])
+])
+
+AC_ARG_ENABLE(python,
+[AS_HELP_STRING([--enable-python], [Compile python plugin support])],
+[ case "$enableval" in
+ yes|no)
+ ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --enable-python: $enableval])
+ ;;
+ esac
+])
+
+AC_ARG_ENABLE(adminconf,
+[AS_HELP_STRING([--enable-adminconf[[=DIR]]], [Use configuration files from adminconfdir in preference to sysconfdir])],
+[ case "$enableval" in
+ yes|no)
+ ;;
+ *) adminconfdir="$enableval"
+ enable_adminconf=yes
+ ;;
+ esac
+], [enable_adminconf=no])
+
+dnl
+dnl C compiler checks
+dnl
+AC_PROG_CPP
+AC_CHECK_TOOL(AR, ar, false)
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AS_IF([test X"$AR" = X"false"], [
+ AC_MSG_ERROR([the "ar" utility is required to build sudo])
+])
+AX_PROG_CC_FOR_BUILD
+
+AS_IF([test "x$ac_cv_prog_cc_c89" = "xno"], [
+ AC_MSG_ERROR([Sudo version $PACKAGE_VERSION requires an ANSI C compiler to build.])
+])
+
+dnl
+dnl If the user specified --disable-static, override them or we'll
+dnl be unable to build the executables in the sudoers plugin dir.
+dnl
+AS_IF([test "$enable_static" = "no"], [
+ AC_MSG_WARN([ignoring --disable-static, sudo does not install static libs])
+ enable_static=yes
+])
+
+dnl
+dnl Set host variables and m4 macro dir
+dnl
+AC_CANONICAL_HOST
+AC_CONFIG_MACRO_DIR([m4])
+
+dnl
+dnl Relies on CC host being set
+dnl
+SUDO_PVS_STUDIO_CFG
+
+dnl
+dnl On HP-UX 11.11 and higher we prefer dlopen() over shl_load().
+dnl Libtool defaults to shl_load() so we need to prime the cache
+dnl to override that default.
+dnl
+case "$host_os" in
+hpux11.1[[1-9]]|hpux11.[[2-9]][[0-9]]|hpux1[[2-9]].*)
+ # Prefer dlopen() over shl_load()
+ : ${ac_cv_func_shl_load='no'}
+ : ${ac_cv_lib_dld_shl_load='no'}
+ ;;
+esac
+
+dnl
+dnl Libtool init, we require libtool 2.2.6b or higher
+dnl
+LT_PREREQ([2.2.6b])
+LT_INIT([dlopen])
+
+dnl
+dnl AIX supports two distinct flavors of shared libraries.
+dnl Traditional AIX shared libs are .a files with a .so inside.
+dnl AIX SVR4-style shared libs are plain .so files. The --with-aix-soname
+dnl option can be used to select the type. We need to set the default
+dnl values to match. This must come after the LT_INIT() call.
+dnl
+case "$host_os" in
+aix*)
+ AS_IF([test X"$aix_use_runtimelinking" != X"yes"], [
+ # Using traditional AIX dynamic shared objects in an archive file.
+ noexec_file="$libexecdir/sudo/sudo_noexec.a(sudo_noexec.so)"
+ intercept_file="$libexecdir/sudo/sudo_intercept.a(sudo_intercept.so)"
+ sudoers_plugin="sudoers.a(sudoers.so)"
+ python_plugin="python_plugin.a(python_plugin.so)"
+ ])
+ ;;
+esac
+SUDO_DEFINE_UNQUOTED([_PATH_SUDOERS_PLUGIN], ["$sudoers_plugin"])
+
+dnl
+dnl Allow the user to specify an alternate libtool.
+dnl XXX - should be able to skip LT_INIT if we are using a different libtool
+dnl
+AC_ARG_WITH(libtool, [AS_HELP_STRING([--with-libtool=PATH], [specify path to libtool])],
+[case $with_libtool in
+ yes|builtin) ;;
+ no) AC_MSG_ERROR([--without-libtool not supported.])
+ ;;
+ system) LIBTOOL=libtool
+ ;;
+ *) LIBTOOL="$with_libtool"
+ ;;
+esac])
+
+dnl
+dnl Defer enable_intercept and with_noexec until after libtool magic runs
+dnl
+AS_IF([test "$enable_shared" = "no"], [
+ enable_intercept=no
+ with_noexec=no
+ enable_dlopen=no
+ lt_cv_dlopen=none
+ lt_cv_dlopen_libs=
+ ac_cv_func_dlopen=no
+ LT_LDFLAGS=-static
+])
+LIBDL="$lt_cv_dlopen_libs"
+SHLIB_ENABLE="$enable_dlopen"
+
+AC_ARG_ENABLE(intercept,
+[AS_HELP_STRING([--enable-intercept], [fully qualified pathname of sudo_intercept.so])],
+[ case "$enableval" in
+ yes) ;;
+ no) ;;
+ *) intercept_file="$enableval"
+ ;;
+ esac
+], [enable_intercept="$intercept_file"])
+INTERCEPTFILE="sudo_intercept.so"
+INTERCEPTDIR="`echo $intercept_file|sed -e 's:^${\([[^}]]*\)}:$(\1):' -e 's:^\([[^:]]*\)/[[^/]].*$:\1:'`"
+
+AC_ARG_WITH(noexec, [AS_HELP_STRING([--with-noexec[[=PATH]]], [fully qualified pathname of sudo_noexec.so])],
+[case $with_noexec in
+ yes) ;;
+ no) ;;
+ *) noexec_file="$with_noexec"
+ ;;
+esac], [with_noexec="$noexec_file"])
+NOEXECFILE="sudo_noexec.so"
+NOEXECDIR="`echo $noexec_file|sed -e 's:^${\([[^}]]*\)}:$(\1):' -e 's:^\([[^:]]*\)/[[^/]].*$:\1:'`"
+
+dnl
+dnl Find programs we use
+dnl
+AC_PATH_PROG(SHA1SUM, [sha1sum], [openssl dgst -sha1])
+AC_PATH_PROG(UNAMEPROG, [uname], [uname])
+AC_PATH_PROG(TRPROG, [tr], [tr])
+AC_CACHE_CHECK([for mandoc or nroff], [ac_cv_path_NROFF], [
+ AC_PATH_PROGS_FEATURE_CHECK([NROFF], [mandoc nroff], [ac_cv_path_NROFF="$ac_path_NROFF"], [ac_cv_path_NROFF=no])
+])
+case "$ac_cv_path_NROFF" in
+*mandoc|no)
+ # Prefer mdoc format for mandoc (or when no formatter is present).
+ : ${MANTYPE='mdoc'}
+ ;;
+*)
+ # Check whether nroff supports -mdoc, this may produce incorrect
+ # results when cross-compiling.
+ test -n "$MANTYPE" && sudo_cv_var_mantype="$MANTYPE"
+ AC_CACHE_CHECK([which macro set to use for manual pages],
+ [sudo_cv_var_mantype],
+ [
+ sudo_cv_var_mantype="man"
+ echo ".Sh NAME" > conftest
+ echo ".Nm sudo" >> conftest
+ echo ".Nd sudo" >> conftest
+ echo ".Sh DESCRIPTION" >> conftest
+ echo "sudo" >> conftest
+ if $ac_cv_path_NROFF -mdoc conftest >/dev/null 2>&1; then
+ sudo_cv_var_mantype="mdoc"
+ fi
+ rm -f conftest
+ ]
+ )
+ MANTYPE="$sudo_cv_var_mantype"
+ ;;
+esac
+
+dnl
+dnl If a config.cache exists make sure it matches the current host.
+dnl
+AS_IF([test -n "$sudo_cv_prev_host"], [
+ AS_IF([test "$sudo_cv_prev_host" != "$host"], [
+ AC_MSG_ERROR([config.cache was created on a different host; remove it and re-run configure.])
+ ])
+])
+sudo_cv_prev_host="$host"
+
+dnl
+dnl Store configure arguments for "sudo -V"
+dnl
+SUDO_DEFINE_UNQUOTED([CONFIGURE_ARGS], "$CONFIGURE_ARGS")
+
+dnl
+dnl We want to be able to differentiate between different rev's
+dnl
+AS_IF([test -n "$host_os"], [
+ OSREV=`echo $host_os | sed 's/^[[^0-9\.]]*\([[0-9\.]]*\).*$/\1/'`
+ OSMAJOR=`echo $OSREV | sed 's/\..*$//'`
+], [
+ OSREV=0
+ OSMAJOR=0
+])
+
+case "$host" in
+ *-*-solaris2*)
+ AC_DEFINE([PAM_SUN_CODEBASE])
+
+ # illumos has a broken fmemopen(3)
+ if test X"`uname -o 2>/dev/null`" = X"illumos"; then
+ : ${ac_cv_func_fmemopen='no'}
+ fi
+
+ # Solaris-specific initialization
+ OS_INIT=os_init_solaris
+ SUDO_OBJS="${SUDO_OBJS} solaris.o"
+
+ # AFS support needs -lucb
+ AS_IF([test "$with_AFS" = "yes"], [
+ AFS_LIBS="-lc -lucb"
+ ])
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+ AC_CHECK_FUNCS([priv_set], [PSMAN=1])
+ ;;
+ *-*-aix*)
+ AC_DEFINE([PAM_SUN_CODEBASE])
+
+ # To get all prototypes (so we pass -Wall)
+ AC_DEFINE([_LINUX_SOURCE_COMPAT])
+
+ # For AIX we build in support for both LAM and PAM
+ # and choose which to use based on auth_type in
+ # /etc/security/login.cfg
+ AS_IF([test X"${with_pam}${with_aixauth}" = X""], [
+ AUTH_EXCL_DEF="AIX_AUTH PAM"
+ ])
+
+ # AIX analog of nsswitch.conf, enabled by default
+ AC_ARG_WITH(netsvc, [AS_HELP_STRING([--with-netsvc[[=PATH]]], [path to netsvc.conf])],
+ [case $with_netsvc in
+ no) ;;
+ yes) with_netsvc="/etc/netsvc.conf"
+ ;;
+ *) ;;
+ esac])
+ AS_IF([test -z "$with_nsswitch" -a -z "$with_netsvc"], [
+ with_netsvc="/etc/netsvc.conf"
+ ])
+
+ # cfmakeraw is broken on AIX (and is not documented)
+ : ${ac_cv_func_cfmakeraw='no'}
+
+ # strnlen/strndup may be broken on AIX < 6 depending
+ # on the libc version, use our own.
+ AS_IF([test $OSMAJOR -lt 6], [
+ : ${ac_cv_func_strnlen='no'}
+ ])
+
+ # fmemopen(3) has a bug wrt feof() on some AIX versions.
+ # https://www.ibm.com/support/pages/apar/IJ11845
+ : ${ac_cv_func_fmemopen='no'}
+
+ # getdelim() may or may not be present on AIX <= 6.1.
+ # bos610 is missing getdelim but bos61J has it.
+ AS_IF([test "$enable_package_build" = "yes"], [
+ AS_IF([test $OSMAJOR -le 6], [
+ : ${ac_cv_func_getdelim='no'}
+ ])
+ ])
+
+ # memset_s() may or may ont be present on AIX <= 7.1.
+ # bos710 is missing memset_s but bos71L has it.
+ AS_IF([test "$enable_package_build" = "yes"], [
+ AS_IF([test $OSMAJOR -le 7], [
+ : ${ac_cv_func_memset_s='no'}
+ ])
+ ])
+
+ # Remove timedir on boot, AIX does not have /var/run
+ INIT_SCRIPT=aix.sh
+ INIT_DIR=/etc/rc.d/init.d
+ RC_LINK=/etc/rc.d/rc2.d/S90sudo
+
+ # AIX-specific functions
+ AC_CHECK_FUNCS([getuserattr setrlimit64])
+ AC_CHECK_FUNCS([setauthdb],
+ [AC_CHECK_TYPES([authdb_t], [], [], [#include <usersec.h>])])
+
+ COMMON_OBJS="${COMMON_OBJS} aix.lo"
+ SUDO_APPEND_COMPAT_EXP(aix_prep_user_v1 aix_restoreauthdb_v1 aix_setauthdb_v1 aix_setauthdb_v2 aix_getauthregistry_v1)
+
+ # These prototypes may be missing
+ AC_CHECK_DECLS([usrinfo], [], [], [
+#include <sys/types.h>
+#include <uinfo.h>
+ ])
+ AC_CHECK_DECLS([setauthdb], [], [], [
+#include <sys/types.h>
+#include <usersec.h>
+ ])
+ ;;
+ *-*-hiuxmpp*)
+ # HI-UX/MPP is based on OSF/1
+
+ # ignore envariables wrt dynamic lib path
+ AX_APPEND_FLAG([-Wl,-no_library_replacement], [SUDO_LDFLAGS])
+
+ shadow_funcs="getprpwnam dispcrypt"
+ shadow_libs="-lsecurity"
+
+ : ${mansectsu='8'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ *-*-hpux*)
+ AC_DEFINE([PAM_SUN_CODEBASE])
+
+ # AFS support needs -lBSD
+ AS_IF([test "$with_AFS" = "yes"],
+ AFS_LIBS="-lc -lBSD"
+ ])
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+
+ # HP-UX does not clear /var/run so we need to do it
+ INIT_SCRIPT=hpux.sh
+ INIT_DIR=/sbin/init.d
+ RC_LINK=/sbin/rc2.d/S900sudo
+
+ # HP-UX shared libs must be executable.
+ # Load time is much greater if writable so use 0555.
+ SHLIB_MODE=0555
+
+ # HP-UX won't unlink a shared lib that is open
+ INSTALL_BACKUP='~'
+
+ # The HP bundled compiler cannot generate shared libs
+ AS_IF([test -z "$GCC"], [
+ AC_CACHE_CHECK([for HP bundled C compiler],
+ [sudo_cv_var_hpccbundled],
+ [if $CC -V 2>&1 | grep '^(Bundled)' >/dev/null 2>&1; then
+ sudo_cv_var_hpccbundled=yes
+ else
+ sudo_cv_var_hpccbundled=no
+ fi]
+ )
+ AS_IF([test "$sudo_cv_var_hpccbundled" = "yes"], [
+ AC_MSG_ERROR([The HP bundled C compiler is unable to build Sudo, you must use gcc or the HP ANSI C compiler instead.])
+ ])
+ ])
+
+ # Build PA-RISC1.1 objects for better portability
+ case "$host_cpu" in
+ hppa[[2-9]]*)
+ _CFLAGS="$CFLAGS"
+ AS_IF([test -n "$GCC"], [
+ portable_flag="-march=1.1"
+ ], [
+ portable_flag="+DAportable"
+ ])
+ CFLAGS="$CFLAGS $portable_flag"
+ AC_CACHE_CHECK([whether $CC understands $portable_flag],
+ [sudo_cv_var_daportable],
+ [AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[]], [[]])],
+ [sudo_cv_var_daportable=yes],
+ [sudo_cv_var_daportable=no]
+ )
+ ]
+ )
+ AS_IF([test X"$sudo_cv_var_daportable" != X"yes"], [
+ CFLAGS="$_CFLAGS"
+ ])
+ ;;
+ esac
+
+ case "$host_os" in
+ hpux10.*)
+ shadow_funcs="getprpwnam iscomsec"
+ shadow_libs="-lsec"
+ # HP-UX 10.x doesn't support LD_PRELOAD
+ with_noexec=no
+ ;;
+ *)
+ shadow_funcs="getspnam iscomsec"
+ shadow_libs="-lsec"
+ test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+ ;;
+ esac
+ AC_CHECK_HEADERS([utmps.h])
+ AC_CHECK_FUNCS([pstat_getproc gethrtime])
+ ;;
+ *-dec-osf*)
+ # ignore envariables wrt dynamic lib path
+ AX_APPEND_FLAG([-Wl,-no_library_replacement], [SUDO_LDFLAGS])
+
+ : ${CHECKSIA='true'}
+ AC_ARG_ENABLE(sia,
+ [AS_HELP_STRING([--disable-sia], [Disable SIA on Digital UNIX])],
+ [ case "$enableval" in
+ yes) CHECKSIA=true
+ ;;
+ no) CHECKSIA=false
+ ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --enable-sia: $enableval])
+ ;;
+ esac
+ ])
+
+ shadow_funcs="getprpwnam dispcrypt"
+ # OSF/1 4.x and higher need -ldb too
+ AS_IF([test $OSMAJOR -lt 4], [
+ shadow_libs="-lsecurity -laud -lm"
+ ], [
+ shadow_libs="-lsecurity -ldb -laud -lm"
+ ])
+
+ # use SIA by default, if we have it
+ test "$CHECKSIA" = "true" && AUTH_EXCL_DEF="SIA"
+
+ #
+ # Some versions of Digital Unix ship with a broken
+ # copy of prot.h, which we need for shadow passwords.
+ # XXX - make should remove this as part of distclean
+ #
+ AC_MSG_CHECKING([for broken prot.h])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/security.h>
+#include <prot.h>
+ ]], [[return(0);]])], [AC_MSG_RESULT(no)], [AC_MSG_RESULT([yes, fixing locally])
+ sed 's:<acl.h>:<sys/acl.h>:g' < /usr/include/prot.h > prot.h
+ ])
+
+ : ${mansectsu='8'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ *-*-irix*)
+ AC_DEFINE([_BSD_TYPES])
+ AS_IF([test "$prefix" = "/usr/local" -a "$mandir" = '${datarootdir}/man'], [
+ AS_IF([test -d "/usr/share/man/local"], [
+ mandir="/usr/share/man/local"
+ ], [
+ mandir="/usr/man/local"
+ ])
+ ])
+ # IRIX <= 4 needs -lsun
+ AS_IF([test "$OSMAJOR" -le 4], [
+ AC_CHECK_LIB([sun], [getpwnam], [LIBS="${LIBS} -lsun"])
+ ])
+
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ *-*-linux*|*-*-k*bsd*-gnu)
+ shadow_funcs="getspnam"
+ test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+ # Check for SECCOMP_MODE_FILTER in linux/seccomp.h
+ AC_CHECK_DECLS([SECCOMP_MODE_FILTER], [], [], [
+#include <sys/types.h>
+#include <sys/prctl.h>
+#include <asm/unistd.h>
+#include <linux/seccomp.h>
+#include <linux/filter.h>
+ ])
+ # We call getrandom via syscall(3) in case it is not in libc
+ AC_CHECK_HEADERS([linux/random.h sys/syscall.h])
+
+ # Only use our replacement functions when not fuzzing,
+ # they may skew the coverage reports.
+ AS_IF([test X"$enable_fuzzer" = X"no"], [
+ # glibc's getentropy() emulation may fail on older kernels.
+ # We use our own getentropy() by default on Linux.
+ : ${ac_cv_func_getentropy='no'}
+
+ # glibc's arc4random() may fail in chroot on older kernels.
+ # We use our own arc4random() by default on Linux.
+ : ${ac_cv_func_arc4random='no'}
+
+ # glibc's closefrom() emulation may fail in chroot.
+ # We use our own closefrom() by default on Linux.
+ : ${ac_cv_func_closefrom='no'}
+ ])
+
+ # Linux 3.2 supports reading/writing a another process
+ # without using ptrace(2).
+ AC_CHECK_FUNCS([process_vm_readv])
+ ;;
+ *-*-gnu*)
+ # lockf() is broken on the Hurd
+ ac_cv_func_lockf=no
+ ;;
+ *-*-sco*|*-sco-*)
+ shadow_funcs="getprpwnam"
+ shadow_libs="-lprot -lx"
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ m88k-motorola-sysv*)
+ # motorolla's cc (a variant of gcc) does -O but not -O2
+ CFLAGS=`echo $CFLAGS | sed 's/-O2/-O/g'`
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ *-sequent-sysv*)
+ shadow_funcs="getspnam"
+ shadow_libs="-lsec"
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ *-ncr-sysv4*|*-ncr-sysvr4*)
+ AC_CHECK_LIB([c89], [strcasecmp], [LIBS="${LIBS} -lc89"])
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ *-ccur-sysv4*|*-ccur-sysvr4*)
+ LIBS="${LIBS} -lgen"
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ *-*-bsdi*)
+ SKIP_SETREUID=yes
+ # Check for newer BSD auth API
+ AS_IF([test -z "$with_bsdauth"], [
+ AC_CHECK_FUNCS([auth_challenge], [AUTH_EXCL_DEF="BSD_AUTH"])
+ ])
+ ;;
+ *-*-freebsd*)
+ AC_DEFINE([_BSD_SOURCE])
+
+ # FreeBSD has a real setreuid(2) starting with 2.1 and
+ # backported to 2.0.5. We just take 2.1 and above...
+ case "$OSREV" in
+ 0.*|1.*|2.0*)
+ SKIP_SETREUID=yes
+ ;;
+ esac
+ AS_IF([test "${with_skey-'no'}" = "yes"], [
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lmd"
+ ])
+ CHECKSHADOW="false"
+ test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+ : ${with_logincap='maybe'}
+
+ # Examples go in share/examples/sudo
+ AS_IF([test X"$with_exampledir" = X""], [
+ exampledir='$(datarootdir)/examples/$(PACKAGE_TARNAME)'
+ ])
+ ;;
+ *-*-*openbsd*)
+ AC_DEFINE([_BSD_SOURCE])
+
+ # OpenBSD-specific initialization
+ OS_INIT=os_init_openbsd
+ SUDO_OBJS="${SUDO_OBJS} openbsd.o"
+
+ # OpenBSD has a real setreuid(2) starting with 3.3 but
+ # we will use setresuid(2) instead.
+ SKIP_SETREUID=yes
+
+ # OpenBSD >= 3.0 supports BSD auth
+ AS_IF([test -z "$with_bsdauth"], [
+ AS_IF([test "$OSMAJOR" -ge 3], [
+ AUTH_EXCL_DEF="BSD_AUTH"
+ ])
+ ])
+ : ${with_logincap='maybe'}
+
+ # Newer OpenBSD only fills in pw_password for getpwnam_shadow()
+ shadow_funcs="getpwnam_shadow"
+
+ # Examples go in share/examples/sudo
+ AS_IF([test X"$with_exampledir" = X""], [
+ exampledir='$(datarootdir)/examples/$(PACKAGE_TARNAME)'
+ ])
+ ;;
+ *-*-*netbsd*)
+ # NetBSD has a real setreuid(2) starting with 1.3.2
+ case "$OSREV" in
+ 0.9*|1.[[012]]*|1.3|1.3.1)
+ SKIP_SETREUID=yes
+ ;;
+ esac
+ CHECKSHADOW="false"
+ test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+ : ${with_logincap='maybe'}
+
+ # For reallocarray()
+ AC_DEFINE([_OPENBSD_SOURCE])
+
+ # Examples go in share/examples/sudo
+ AS_IF([test X"$with_exampledir" = X""], [
+ exampledir='$(datarootdir)/examples/$(PACKAGE_TARNAME)'
+ ])
+ ;;
+ *-*-dragonfly*)
+ AC_DEFINE([_BSD_SOURCE])
+
+ AS_IF([test "${with_skey-'no'}" = "yes"], [
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lmd"
+ ])
+ CHECKSHADOW="false"
+ test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+ : ${with_logincap='yes'}
+
+ # Examples go in share/examples/sudo
+ AS_IF([test X"$with_exampledir" = X""], [
+ exampledir='$(datarootdir)/examples/$(PACKAGE_TARNAME)'
+ ])
+ ;;
+ *-*-*bsd*)
+ CHECKSHADOW="false"
+ # Examples go in share/examples/sudo
+ AS_IF([test X"$with_exampledir" = X""], [
+ exampledir='$(datarootdir)/examples/$(PACKAGE_TARNAME)'
+ ])
+ ;;
+ *-*-darwin*)
+ # Darwin has a real setreuid(2) starting with 9.0
+ AS_IF([test $OSMAJOR -lt 9], [
+ SKIP_SETREUID=yes
+ ])
+ CHECKSHADOW="false"
+ test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+ : ${with_logincap='yes'}
+ # Darwin has a broken poll(), Apple radar 3710161
+ : ${enable_poll='no'}
+
+ # Build sudo_noexec.so as a shared library, not a module.
+ # On Darwin, modules and shared libraries are incompatible.
+ PRELOAD_MODULE=
+
+ # Mach monotonic timer that runs while sleeping
+ AC_CHECK_FUNCS([mach_continuous_time])
+
+ # Undocumented API that dynamically allocates the groups.
+ AC_CHECK_FUNCS([getgrouplist_2], [AC_CHECK_DECLS([getgrouplist_2])])
+
+ # We use proc_pidinfo() to emulate closefrom() on macOS.
+ AC_CHECK_HEADERS([libproc.h], [AC_CHECK_FUNCS([proc_pidinfo])])
+
+ # We cannot directly access environ from a shared object
+ AC_CHECK_HEADERS([crt_externs.h], [AC_CHECK_FUNCS([_NSGetEnviron])])
+
+ # We need to force a flat namespace to make libc
+ # symbol hooking work like it does on ELF.
+ AX_CHECK_LINK_FLAG([-Wl,-force_flat_namespace], [AX_APPEND_FLAG([-Wl,-force_flat_namespace], [SUDO_LDFLAGS])])
+
+ # Examples go in share/examples/sudo
+ AS_IF([test X"$with_exampledir" = X""], [
+ exampledir='$(datarootdir)/examples/$(PACKAGE_TARNAME)'
+ ])
+ ;;
+ *-*-nextstep*)
+ # lockf() is broken on the NeXT
+ ac_cv_func_lockf=no
+ ;;
+ *-*-*sysv4*)
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+ *-*-*sco3.2*) # SCO OpenServer 5
+ : ${mansectsu='1'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ shadow_funcs="getprpwnam"
+ shadow_libs="-lprot"
+ ;;
+# UnixWare 7.x, OpenUNIX 8
+ *-*-*sysv5*)
+ : ${mansectsu='1'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ case "$host" in
+ *-*-sysv5SCO_SV*) # SCO OpenServer 6.x
+ shadow_funcs="getprpwnam"
+ shadow_libs="-lprot"
+ ;;
+ *) shadow_funcs="getspnam"
+ test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
+ ;;
+ esac
+ ;;
+ *-*-sysv*)
+ : ${mansectsu='1m'}
+ : ${mansectform='4'}
+ : ${mansectmisc='5'}
+ ;;
+esac
+
+dnl
+dnl Check for mixing mutually exclusive and regular auth methods
+dnl
+AUTH_REG=${AUTH_REG# }
+AUTH_EXCL=${AUTH_EXCL# }
+AS_IF([test -n "$AUTH_EXCL" -a -n "$AUTH_REG"], [
+ AC_MSG_ERROR([Cannot mix mutually exclusive ($AUTH_EXCL) and regular ($AUTH_REG) authentication methods])
+])
+dnl
+dnl Only one of S/Key and OPIE may be specified
+dnl
+AS_IF([test X"${with_skey}${with_opie}" = X"yesyes"], [
+ AC_MSG_ERROR([cannot use both S/Key and OPIE])
+])
+
+dnl
+dnl Use BSD-style man sections by default
+dnl
+: ${mansectsu='8'}
+: ${mansectform='5'}
+: ${mansectmisc='7'}
+
+dnl
+dnl Add in any libpaths or libraries specified via configure
+dnl
+AS_IF([test -n "$with_libpath"], [
+ for i in ${with_libpath}; do
+ SUDO_APPEND_LIBPATH(LDFLAGS, [$i])
+ done
+])
+AS_IF([test -n "$with_libraries"], [
+ for i in ${with_libraries}; do
+ case $i in
+ -l*) ;;
+ *.a) ;;
+ *.o) ;;
+ *) i="-l${i}";;
+ esac
+ LIBS="${LIBS} ${i}"
+ done
+])
+
+dnl
+dnl C compiler checks (to be done after os checks)
+dnl AC_PROG_CC_STDC is deprecated in autoconf 2.70 and above.
+dnl
+m4_bmatch(m4_defn([AC_AUTOCONF_VERSION]), [^2\.69], [AC_PROG_CC_STDC])
+AC_C_CONST
+AC_C_RESTRICT
+AC_C_INLINE
+AC_C_VOLATILE
+SUDO_CPP_VARIADIC_MACROS
+
+dnl
+dnl Program checks
+dnl
+AC_PROG_AWK
+AC_PROG_YACC
+AC_PATH_PROG([FLEX], [flex], [flex])
+SUDO_PROG_MV
+SUDO_PROG_BSHELL
+AS_IF([test -z "$with_sendmail"], [
+ SUDO_PROG_SENDMAIL
+ with_sendmail="$ac_cv_path_SENDMAILPROG"
+])
+SUDO_PROG_VI
+dnl
+dnl Use fully-qualified path to vi in the manual
+dnl
+AS_IF([test -z "$with_editor"], [
+ editor="$ac_cv_path_VIPROG"
+])
+dnl
+dnl Check for authpriv support in syslog
+dnl
+AS_IF([test X"$with_logfac" = X""], [
+ AC_CHECK_DECL([LOG_AUTHPRIV], [logfac=authpriv], [], [#include <syslog.h>])
+])
+AC_DEFINE_UNQUOTED(LOGFAC, "$logfac", [The syslog facility sudo will use.])
+dnl
+dnl Header file checks
+dnl
+AC_HEADER_DIRENT
+AC_HEADER_STDBOOL
+AC_HEADER_MAJOR
+AC_CHECK_HEADERS_ONCE([netgroup.h paths.h spawn.h wordexp.h sys/sockio.h sys/bsdtypes.h sys/select.h sys/stropts.h sys/sysmacros.h sys/statvfs.h])
+AS_IF([test X"$ac_cv_header_utmps_h" != X"yes"], [
+ AC_CHECK_HEADERS([utmpx.h])
+])
+AC_CHECK_HEADERS([endian.h] [sys/endian.h] [machine/endian.h], [break])
+AC_CHECK_HEADERS([procfs.h] [sys/procfs.h], [AC_CHECK_MEMBERS(struct psinfo.pr_ttydev, [AC_CHECK_FUNCS([_ttyname_dev])], [], [AC_INCLUDES_DEFAULT
+#ifdef HAVE_PROCFS_H
+#include <procfs.h>
+#endif
+#ifdef HAVE_SYS_PROCFS_H
+#include <sys/procfs.h>
+#endif
+])]
+break)
+#
+# Check for large file and 64-bit time support.
+#
+AC_SYS_LARGEFILE
+m4_ifdef([AC_SYS_YEAR2038], [AC_SYS_YEAR2038], [
+ # GNU libc only allows setting _TIME_BITS when FILE_OFFSET_BITS is also set. # GNU libc defines __TIMESIZE on systems where _TIME_BITS can be set.
+ AS_IF([test X"$ac_cv_sys_file_offset_bits" = X"yes"], [
+ AC_CHECK_DECL(__TIMESIZE, [
+ AC_DEFINE([_TIME_BITS], [64], [Number of bits in a timestamp, on hosts where this is settable.])
+ ], [], [
+AC_INCLUDES_DEFAULT
+#include <time.h>
+ ])
+ ])
+])
+
+#
+# Don't allow undefined symbols, even in shared libraries, if possible.
+# This will detect missing symbols at build-time instead of run-time
+# but is incompatible with the sanitizers/fuzzers.
+# We must set this *before* the library tests.
+#
+AS_IF([test -n "$GCC" -a X"${enable_sanitizer}${enable_fuzzer}" = X"nono"], [
+ AS_CASE([$host_os], [darwin*], [
+ # On macOS 13, using "-undefined dynamic_lookup" produces a
+ # warning. Use the -no-undefined libtool option to avoid this.
+ AX_APPEND_FLAG([-no-undefined], [LT_LDFLAGS])
+ ], [
+ # On FreeBSD and Dragonfly, environ is filled in by the dynamic loader
+ # so -Wl,--no-undefined causes a link error when environ is used.
+ # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=263265
+ # We use errno because OpenBSD shared libraries don't explicitly
+ # link with libc, which can result in undefined reference errors.
+ AC_CACHE_CHECK([the linker accepts -Wl,--no-undefined],
+ [sudo_cv_var_ld___no_undefined],
+ [
+ sudo_cv_var_ld___no_undefined=no
+ _CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $lt_prog_compiler_pic"
+ _LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_prog_compiler_pic -shared -Wl,--no-undefined"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <errno.h>
+ extern char **environ;]], [[int ret = ((long)environ & 0xff) + errno; return ret;]])],
+ [sudo_cv_var_ld___no_undefined=yes])
+ CFLAGS="$_CFLAGS"
+ LDFLAGS="$_LDFLAGS"
+ ]
+ )
+ AS_IF([test "$sudo_cv_var_ld___no_undefined" = "yes"], [
+ AX_APPEND_FLAG([-Wl,--no-undefined], [LDFLAGS])
+ ])
+ ])
+])
+
+#
+# HP-UX may need to define _XOPEN_SOURCE_EXTENDED to expose MSG_WAITALL.
+# Also, HP-UX 11.23 has a broken sys/types.h when large files support
+# is enabled and _XOPEN_SOURCE_EXTENDED is not also defined.
+# The following test will define _XOPEN_SOURCE_EXTENDED in either case.
+#
+case "$host_os" in
+ hpux*)
+ AC_CACHE_CHECK([whether sys/socket.h needs _XOPEN_SOURCE_EXTENDED for MSG_WAITALL], [sudo_cv_xopen_source_extended],
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
+[# include <sys/socket.h>]], [[int a = MSG_WAITALL; return a;]])],
+ [sudo_cv_xopen_source_extended=no], [
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#define _XOPEN_SOURCE_EXTENDED
+ AC_INCLUDES_DEFAULT
+[# include <sys/socket.h>
+# include <net/if.h>]], [[int a = MSG_WAITALL; return a;]])],
+ [sudo_cv_xopen_source_extended=yes],
+ [sudo_cv_xopen_source_extended=error])
+ ])])
+ AS_IF([test "$sudo_cv_xopen_source_extended" = "yes"], [
+ AC_DEFINE([_XOPEN_SOURCE_EXTENDED])
+ ])
+ ;;
+esac
+SUDO_MAILDIR
+AS_IF([test ${with_logincap-'no'} != "no"], [
+ AC_CHECK_HEADERS([login_cap.h], [
+ LOGINCAP_USAGE='[[-c class]] '
+ LCMAN=1
+ with_logincap=yes
+ ])
+ AS_IF([test "${with_logincap}" = "yes"], [
+ # setusercontext() is in libutil on NetBSD, FreeBSD, Dragonfly BSD.
+ _LIBS="$LIBS"
+ AC_SEARCH_LIBS([setusercontext], [util])
+ LIBS="$_LIBS"
+ AS_IF([test "${ac_cv_search_setusercontext}" != "none required"], [
+ SUDO_LIBS="${SUDO_LIBS} -lutil"
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lutil"
+ ])
+ ])
+])
+AS_IF([test ${with_project-'no'} != "no"], [
+ AC_CHECK_HEADER(project.h, [
+ AC_CHECK_LIB([project], [setproject], [
+ AC_DEFINE(HAVE_PROJECT_H)
+ SUDO_LIBS="${SUDO_LIBS} -lproject"
+ ])
+ ], [with_project=no])
+])
+dnl
+dnl typedef checks
+dnl
+AS_IF([test X"${ac_cv_header_stdint_h}${ac_cv_header_inttypes_h}" = X"nono"], [
+ AC_TYPE_INT8_T
+ AC_TYPE_UINT8_T
+ AC_TYPE_INT16_T
+ AC_TYPE_UINT16_T
+ AC_TYPE_INT32_T
+ AC_TYPE_UINT32_T
+ AC_TYPE_INT64_T
+ AC_TYPE_UINT64_T
+ AC_TYPE_INTMAX_T
+ AC_TYPE_UINTMAX_T
+])
+AC_CHECK_TYPES([sig_atomic_t], [], [], [
+AC_INCLUDES_DEFAULT
+#include <signal.h>])
+AC_CHECK_TYPES([struct in6_addr], [], [], [#include <sys/types.h>
+#include <netinet/in.h>])
+AC_CHECK_TYPES(socklen_t, [], [], [
+AC_INCLUDES_DEFAULT
+#include <sys/socket.h>])
+SUDO_SOCK_SA_LEN
+SUDO_SOCK_SIN_LEN
+AC_CHECK_SIZEOF([long])
+AC_CHECK_SIZEOF([long long])
+AC_CHECK_SIZEOF([id_t])
+AC_CHECK_SIZEOF([time_t])
+AC_CHECK_SIZEOF([uid_t])
+# sudo current assumes uid_t can be cast to unsigned int without problems
+AS_IF([test $ac_cv_sizeof_uid_t -gt 4], [AC_MSG_ERROR([sudo does not support systems where uid_t is larger than 32-bit])])
+AS_IF([test X"$ac_cv_header_utmps_h" = X"yes"], [
+ SUDO_CHECK_UTMP_MEMBERS([utmps])
+], [test X"$ac_cv_header_utmpx_h" = X"yes"], [
+ SUDO_CHECK_UTMP_MEMBERS([utmpx])
+], [
+ SUDO_CHECK_UTMP_MEMBERS([utmp])
+])
+
+dnl
+dnl Default values for LD_PRELOAD and related settings.
+dnl
+RTLD_PRELOAD_VAR="LD_PRELOAD"
+if test $ac_cv_sizeof_long -eq 4; then
+ RTLD_PRELOAD_VAR_32="LD_PRELOAD"
+else
+ RTLD_PRELOAD_VAR_64="LD_PRELOAD"
+fi
+RTLD_PRELOAD_ENABLE_VAR=
+RTLD_PRELOAD_DELIM=":"
+RTLD_PRELOAD_DEFAULT=
+
+dnl
+dnl System-specific LD_PRELOAD equivalents.
+dnl The below tests rely on ac_cv_sizeof_long being defined.
+dnl
+case "$host" in
+ *-*-solaris2*)
+ # LD_PRELOAD is space-delimited
+ RTLD_PRELOAD_DELIM=" "
+ RTLD_PRELOAD_VAR_32="LD_PRELOAD_32"
+ RTLD_PRELOAD_VAR_64="LD_PRELOAD_64"
+ ;;
+ *-*-aix*)
+ # LDR_PRELOAD and LDR_PRELOAD64 are only supported on
+ # AIX 5.3 and above.
+ case "$OSREV" in
+ [[1-4]].*|5.[[1-2]]*)
+ with_noexec=no
+ ;;
+ *)
+ # AIX uses LDR_PRELOAD for 32-bit executables
+ # and LDR_PRELOAD64 for 64-bit executable.
+ RTLD_PRELOAD_VAR_32="LDR_PRELOAD"
+ RTLD_PRELOAD_VAR_64="LDR_PRELOAD64"
+ if test $ac_cv_sizeof_long -eq 4; then
+ RTLD_PRELOAD_VAR="LDR_PRELOAD"
+ else
+ RTLD_PRELOAD_VAR="LDR_PRELOAD64"
+ fi
+ ;;
+ esac
+ ;;
+ *-dec-osf*|*-*-hiuxmpp*|*-*-irix*)
+ # ":DEFAULT" must be appended to _RLD_LIST
+ RTLD_PRELOAD_VAR="_RLD_LIST"
+ RTLD_PRELOAD_DEFAULT="DEFAULT"
+ ;;
+ *-*-darwin*)
+ # Darwin 8 and above can interpose library symbols cleanly
+ AS_IF([test $OSMAJOR -ge 8], [
+ AC_DEFINE(HAVE___INTERPOSE)
+ dlyld_interpose=yes
+ ], [
+ RTLD_PRELOAD_ENABLE_VAR="DYLD_FORCE_FLAT_NAMESPACE"
+ ])
+ RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
+
+ # Build sudo_noexec.so as a shared library, not a module.
+ # On Darwin, modules and shared libraries are incompatible.
+ PRELOAD_MODULE=
+ ;;
+ *-*-nextstep*)
+ RTLD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
+ RTLD_PRELOAD_ENABLE_VAR="DYLD_FORCE_FLAT_NAMESPACE"
+ ;;
+esac
+
+dnl
+dnl Library preloading to support NOEXEC
+dnl
+AS_IF([test X"$enable_intercept" = X"no"], [
+ intercept_file=disabled
+])
+AS_IF([test X"$with_noexec" = X"no"], [
+ noexec_file=disabled
+])
+AS_IF([test X"${intercept_file} ${noexec_file}" != X"disabled disabled"], [
+ SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_VAR, "$RTLD_PRELOAD_VAR")
+ if test -n "$RTLD_PRELOAD_VAR_32"; then
+ SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_VAR_32, "$RTLD_PRELOAD_VAR_32")
+ fi
+ if test -n "$RTLD_PRELOAD_VAR_64"; then
+ SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_VAR_64, "$RTLD_PRELOAD_VAR_64")
+ fi
+ SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_DELIM, '$RTLD_PRELOAD_DELIM')
+ AS_IF([test -n "$RTLD_PRELOAD_DEFAULT"], [
+ SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_DEFAULT, "$RTLD_PRELOAD_DEFAULT")
+ ])
+ AS_IF([test -n "$RTLD_PRELOAD_ENABLE_VAR"], [
+ SUDO_DEFINE_UNQUOTED(RTLD_PRELOAD_ENABLE_VAR, "$RTLD_PRELOAD_ENABLE_VAR")
+ ])
+])
+
+dnl
+dnl Python plugin support
+dnl
+AS_IF([test ${enable_python-'no'} = "yes"], [
+ AM_PATH_PYTHON([3])
+
+ AC_ARG_VAR([PYTHON_INCLUDE], [Include flags for python, bypassing python-config])
+ AC_ARG_VAR([PYTHON_LIBS], [Linker flags for python, bypassing python-config])
+ AC_ARG_VAR([PYTHON_CONFIG], [Path to python-config])
+
+ AS_IF([test -z "$PYTHON_INCLUDE" || test -z "$PYTHON_LIBS"], [
+ AS_IF([test -z "$PYTHON_CONFIG"], [
+ AC_PATH_PROGS([PYTHON_CONFIG],
+ [python$PYTHON_VERSION-config python-config],
+ [no],
+ [`dirname $PYTHON`])
+ AS_IF([test "$PYTHON_CONFIG" = no], [AC_MSG_ERROR([cannot find python-config for $PYTHON.])])
+ ])
+ ])
+
+ AS_IF([test -z "$PYTHON_INCLUDE"], [
+ # Pull out python include path, ignore other flags
+ PYTHON_INCLUDE=`$PYTHON_CONFIG --cflags | tr " " "\n" | grep "^-I" | sort -u | tr "\n" " "`
+ ])
+
+ AS_IF([test -z "$PYTHON_LIBS"], [
+ # Newer versions of python3-config need --embed to include libpython
+ if $PYTHON_CONFIG 2>&1 | grep embed >/dev/null; then
+ PY_EMBED=--embed
+ else
+ PY_EMBED=
+ fi
+ PYTHON_LIBS=`$PYTHON_CONFIG --ldflags $PY_EMBED`
+ PYTHON_LIBS=`$PYTHON_CONFIG --ldflags $PY_EMBED | tr " " "\n" | grep "^-[[lL]]" | tr "\n" " "`
+ ])
+
+ PPFILES="$PPFILES "'$(srcdir)/etc/sudo-python.pp'
+ PYTHON_PLUGIN_SRC=plugins/python
+ PYTHON_PLUGIN=
+ AC_CONFIG_FILES([$PYTHON_PLUGIN_SRC/Makefile])
+])
+
+dnl
+dnl Function checks
+dnl
+AC_FUNC_GETGROUPS
+AC_FUNC_FSEEKO
+AC_CHECK_FUNCS_ONCE([faccessat fexecve fmemopen killpg nl_langinfo renameat strtoull wordexp])
+AC_CHECK_FUNCS([execvpe], [SUDO_APPEND_INTERCEPT_EXP(execvpe)])
+AC_CHECK_FUNCS([pread], [
+ # pread/pwrite on 32-bit HP-UX 11.x may not support large files
+ case "$host_os" in
+ hpux*)
+ AC_CHECK_FUNCS([pread64 pwrite64], [
+ AC_CHECK_DECLS([pread64, pwrite64])
+ ])
+ ;;
+ esac
+], [
+ AC_LIBOBJ(pread)
+ SUDO_APPEND_COMPAT_EXP(sudo_pread)
+])
+AC_CHECK_FUNCS([pwrite], [], [
+ AC_LIBOBJ(pwrite)
+ SUDO_APPEND_COMPAT_EXP(sudo_pwrite)
+])
+AC_CHECK_FUNCS([cfmakeraw], [], [
+ AC_LIBOBJ(cfmakeraw)
+ SUDO_APPEND_COMPAT_EXP(sudo_cfmakeraw)
+])
+AC_CHECK_FUNCS([localtime_r], [], [
+ AC_LIBOBJ(localtime_r)
+ SUDO_APPEND_COMPAT_EXP(sudo_localtime_r)
+])
+AC_CHECK_FUNCS([gmtime_r], [], [
+ AC_LIBOBJ(gmtime_r)
+ SUDO_APPEND_COMPAT_EXP(sudo_gmtime_r)
+])
+AC_CHECK_FUNCS([timegm], [], [
+ AC_LIBOBJ(timegm)
+ SUDO_APPEND_COMPAT_EXP(sudo_timegm)
+])
+AC_CHECK_FUNCS([getgrouplist], [], [
+ case "$host_os" in
+ aix*)
+ AC_CHECK_FUNCS([getgrset])
+ ;;
+ *)
+ AC_CHECK_FUNC([nss_search], [
+ AC_CHECK_FUNC([_nss_XbyY_buf_alloc], [
+ # Solaris
+ AC_CHECK_FUNC([_nss_initf_group], [
+ AC_CHECK_HEADERS([nss_dbdefs.h])
+ AC_DEFINE([HAVE_NSS_SEARCH])
+ AC_DEFINE([HAVE__NSS_XBYY_BUF_ALLOC])
+ AC_DEFINE([HAVE__NSS_INITF_GROUP])
+ ], [
+ AC_CHECK_HEADERS([nss_dbdefs.h], [
+ # Older Solaris does not export _nss_initf_group
+ # but we can use our own.
+ AC_DEFINE([HAVE_NSS_SEARCH])
+ AC_DEFINE([HAVE__NSS_XBYY_BUF_ALLOC])
+ ])
+ ])
+ ], [
+ dnl HP-UX support disabled until "group: compat" fixed
+ dnl # HP-UX
+ dnl AC_CHECK_FUNC([__nss_XbyY_buf_alloc], [
+ dnl AC_CHECK_FUNC([__nss_initf_group], [
+ dnl AC_CHECK_HEADERS([nss_dbdefs.h])
+ dnl AC_DEFINE([HAVE_NSS_SEARCH])
+ dnl AC_DEFINE([HAVE___NSS_XBYY_BUF_ALLOC])
+ dnl AC_DEFINE([HAVE___NSS_INITF_GROUP])
+ dnl ])
+ dnl])
+ :
+ ])
+ ])
+ ;;
+ esac
+ SUDO_APPEND_COMPAT_EXP(sudo_getgrouplist)
+])
+AC_CHECK_FUNCS([getdelim], [
+ # Out of date gcc fixed includes may result in missing getdelim() prototype
+ AC_CHECK_DECLS([getdelim])
+], [
+ AC_LIBOBJ(getdelim)
+ SUDO_APPEND_COMPAT_EXP(sudo_getdelim)
+ COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }getdelim_test"
+])
+AC_CHECK_FUNCS([getusershell], [
+ # Older Solaris has getusershell() et al but does not declare it.
+ AC_CHECK_DECLS([getusershell])
+], [
+ AC_LIBOBJ(getusershell)
+ SUDO_APPEND_COMPAT_EXP(sudo_getusershell)
+])
+AC_CHECK_FUNCS([reallocarray], [], [
+ AC_LIBOBJ(reallocarray)
+ SUDO_APPEND_COMPAT_EXP(sudo_reallocarray)
+])
+AC_CHECK_FUNCS([arc4random], [
+ AC_CHECK_FUNCS([arc4random_uniform], [], [
+ AC_LIBOBJ(arc4random_uniform)
+ SUDO_APPEND_COMPAT_EXP(sudo_arc4random_uniform)
+ ])
+ AC_CHECK_FUNCS([arc4random_buf], [], [
+ AC_LIBOBJ(arc4random_buf)
+ SUDO_APPEND_COMPAT_EXP(sudo_arc4random_buf)
+ ])
+], [
+ AC_LIBOBJ(arc4random)
+ SUDO_APPEND_COMPAT_EXP(sudo_arc4random)
+ SUDO_APPEND_COMPAT_EXP(sudo_arc4random_buf)
+ AC_LIBOBJ(arc4random_uniform)
+ SUDO_APPEND_COMPAT_EXP(sudo_arc4random_uniform)
+ # arc4random.c needs getentropy()
+ AC_CHECK_FUNCS([getentropy], [
+ AC_CHECK_HEADERS([sys/random.h])
+ ], [
+ AC_LIBOBJ(getentropy)
+ SUDO_APPEND_COMPAT_EXP(sudo_getentropy)
+ AC_CHECK_FUNCS([getauxval])
+ ])
+ # arc4random.c wants pthread_atfork
+ AC_CHECK_HEADERS([pthread.h], [
+ AC_CHECK_LIB([pthread], [main], [LIBPTHREAD="-lpthread"])
+ AC_CHECK_FUNCS([pthread_atfork])
+ ])
+])
+AX_GCC_BUILTIN(__builtin_clz)
+AX_GCC_BUILTIN(__builtin_clzl)
+
+utmp_style=LEGACY
+AC_CHECK_FUNCS([getutsid getutxid getutid], [utmp_style=POSIX; break])
+AS_IF([test "$utmp_style" = "LEGACY"], [
+ AC_CHECK_FUNCS([getttyent ttyslot], [break])
+])
+
+AC_CHECK_FUNCS([sysctl], [
+ AC_CHECK_FUNCS([devname])
+ # Check for the various flavors of kinfo_proc
+ found=false
+ AC_CHECK_MEMBER([struct kinfo_proc.ki_structsize], [
+ AC_DEFINE(HAVE_KINFO_PROC_FREEBSD)
+ found=true
+ ], [], [
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+ ])
+ AS_IF([test "$found" = "false"], [
+ AC_CHECK_MEMBER([struct kinfo_proc.kp_paddr], [
+ AC_DEFINE(HAVE_KINFO_PROC_DFLY)
+ found=true
+ ], [], [
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+ ])
+ ])
+ AS_IF([test "$found" = "false"], [
+ AC_CHECK_MEMBER([struct kinfo_proc2.p_paddr], [
+ AC_DEFINE(HAVE_KINFO_PROC2_NETBSD)
+ found=true
+ ], [], [
+#include <sys/param.h>
+#include <sys/sysctl.h>
+ ])
+ ])
+ AS_IF([test "$found" = "false"], [
+ AC_CHECK_MEMBER([struct kinfo_proc.p_paddr], [
+ AC_DEFINE(HAVE_KINFO_PROC_OPENBSD)
+ found=true
+ ], [], [
+#include <sys/param.h>
+#include <sys/sysctl.h>
+ ])
+ ])
+ AS_IF([test "$found" = "false"], [
+ AC_CHECK_MEMBER([struct kinfo_proc.kp_proc], [
+ AC_DEFINE(HAVE_KINFO_PROC_44BSD)
+ found=true
+ ], [], [
+#include <sys/param.h>
+#include <sys/sysctl.h>
+ ])
+ ])
+])
+
+AC_CHECK_FUNCS([openpty], [AC_CHECK_HEADERS([libutil.h util.h pty.h], [break])], [
+ AC_CHECK_LIB([util], [openpty], [
+ AC_CHECK_HEADERS([libutil.h util.h pty.h], [break])
+ case "$SUDO_LIBS" in
+ *-lutil*) ;;
+ *) SUDO_LIBS="${SUDO_LIBS} -lutil";;
+ esac
+ AC_DEFINE(HAVE_OPENPTY)
+ ], [
+ AC_CHECK_FUNCS([_getpty], [], [
+ AC_CHECK_FUNCS([grantpt], [
+ AC_CHECK_FUNCS([posix_openpt])
+ ], [
+ AC_CHECK_FUNCS([revoke])
+ ])
+ ])
+ ])
+])
+AC_CHECK_FUNCS([unsetenv], [SUDO_FUNC_UNSETENV_VOID], [])
+SUDO_FUNC_PUTENV_CONST
+SUDO_FUNC_IOCTL_REQ_INT
+AS_IF([test -z "$SKIP_SETRESUID"], [
+ AC_CHECK_FUNCS([setresuid], [
+ SKIP_SETREUID=yes
+ AC_CHECK_DECLS([setresuid])
+ AC_CHECK_FUNCS([getresuid], [AC_CHECK_DECLS([getresuid])])
+ ])
+])
+AS_IF([test -z "$SKIP_SETRESUID"], [
+ AC_CHECK_FUNCS([setreuid])
+])
+AC_CHECK_FUNCS_ONCE([seteuid])
+AS_IF([test X"$with_interfaces" != X"no"], [
+ AC_CHECK_FUNCS([getifaddrs], [AC_CHECK_FUNCS([freeifaddrs])])
+])
+AC_CHECK_FUNCS([lockf], [break])
+AC_CHECK_FUNCS([innetgr], [
+ AC_CHECK_DECLS([innetgr], [], [], [
+AC_INCLUDES_DEFAULT
+#ifdef HAVE_NETGROUP_H
+# include <netgroup.h>
+#else
+# include <netdb.h>
+#endif /* HAVE_NETGROUP_H */
+])], [
+ AC_CHECK_FUNCS([_innetgr], [
+ AC_CHECK_DECLS([_innetgr], [], [], [
+AC_INCLUDES_DEFAULT
+#ifdef HAVE_NETGROUP_H
+# include <netgroup.h>
+#else
+# include <netdb.h>
+#endif /* HAVE_NETGROUP_H */
+ ])
+ ])
+])
+AC_CHECK_FUNCS([getdomainname], [
+ AC_CHECK_DECLS([getdomainname], [], [], [
+AC_INCLUDES_DEFAULT
+#include <netdb.h>
+ ])
+], [
+ AC_CHECK_FUNCS([sysinfo], [AC_CHECK_HEADERS([sys/systeminfo.h])])
+])
+AC_CHECK_FUNCS([utimensat], [], [
+ AC_LIBOBJ(utimens)
+ SUDO_APPEND_COMPAT_EXP(sudo_utimensat)
+ AC_CHECK_FUNCS([utimes])
+])
+AC_CHECK_FUNCS([futimens], [], [
+ AC_LIBOBJ(utimens)
+ SUDO_APPEND_COMPAT_EXP(sudo_futimens)
+ AC_CHECK_FUNCS([futimes futimesat futime], [break])
+])
+AC_CHECK_FUNCS([explicit_bzero], [], [
+ AC_LIBOBJ(explicit_bzero)
+ SUDO_APPEND_COMPAT_EXP(sudo_explicit_bzero)
+ AC_CHECK_FUNCS([explicit_memset memset_explicit memset_s bzero], [break])
+])
+SUDO_FUNC_FNMATCH([AC_DEFINE(HAVE_FNMATCH)], [
+ AC_LIBOBJ(fnmatch)
+ SUDO_APPEND_COMPAT_EXP(sudo_fnmatch)
+ COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }fnm_test"
+])
+SUDO_FUNC_ISBLANK
+AC_CHECK_FUNCS([glob], [], [
+ AC_LIBOBJ(glob)
+ SUDO_APPEND_COMPAT_EXP(sudo_glob sudo_globfree)
+])
+AC_CHECK_FUNCS([memrchr], [], [
+ AC_LIBOBJ(memrchr)
+ SUDO_APPEND_COMPAT_EXP(sudo_memrchr)
+])
+AC_CHECK_FUNCS([freezero], [], [
+ AC_LIBOBJ(freezero)
+ SUDO_APPEND_COMPAT_EXP(sudo_freezero)
+])
+AC_CHECK_FUNCS(nanosleep, [], [
+ # On Solaris, nanosleep is in librt
+ AC_CHECK_LIB([rt], [nanosleep], [
+ AC_DEFINE(HAVE_NANOSLEEP)
+ LIBRT="-lrt"
+ ], [
+ AC_LIBOBJ(nanosleep)
+ SUDO_APPEND_COMPAT_EXP(sudo_nanosleep)
+ ])
+])
+AC_CHECK_FUNCS([fchownat], [], [
+ AC_LIBOBJ(fchownat)
+ SUDO_APPEND_COMPAT_EXP(sudo_fchownat)
+])
+AC_CHECK_FUNCS([mkdirat], [], [
+ AC_LIBOBJ(mkdirat)
+ SUDO_APPEND_COMPAT_EXP(sudo_mkdirat)
+])
+AC_CHECK_FUNCS([openat], [], [
+ AC_LIBOBJ(openat)
+ SUDO_APPEND_COMPAT_EXP(sudo_openat)
+])
+AC_CHECK_FUNCS([unlinkat], [], [
+ AC_LIBOBJ(unlinkat)
+ SUDO_APPEND_COMPAT_EXP(sudo_unlinkat)
+])
+AC_CHECK_FUNCS([fchmodat], [], [
+ AC_LIBOBJ(fchmodat)
+ SUDO_APPEND_COMPAT_EXP(sudo_fchmodat)
+])
+AC_CHECK_FUNCS([fstatat], [], [
+ AC_LIBOBJ(fstatat)
+ SUDO_APPEND_COMPAT_EXP(sudo_fstatat)
+])
+AC_CHECK_FUNCS([dup3], [], [
+ AC_LIBOBJ(dup3)
+ SUDO_APPEND_COMPAT_EXP(sudo_dup3)
+])
+AC_CHECK_FUNCS([pipe2], [], [
+ AC_LIBOBJ(pipe2)
+ SUDO_APPEND_COMPAT_EXP(sudo_pipe2)
+])
+AC_CHECK_FUNCS([pw_dup], [], [
+ AC_LIBOBJ(pw_dup)
+ SUDO_APPEND_COMPAT_EXP(sudo_pw_dup)
+])
+AC_CHECK_FUNCS([realpath], [], [
+ AC_LIBOBJ(realpath)
+ SUDO_APPEND_COMPAT_EXP(sudo_realpath)
+])
+AC_CHECK_FUNCS([strlcpy], [], [
+ AC_LIBOBJ(strlcpy)
+ SUDO_APPEND_COMPAT_EXP(sudo_strlcpy)
+])
+AC_CHECK_FUNCS([strlcat], [], [
+ AC_LIBOBJ(strlcat)
+ SUDO_APPEND_COMPAT_EXP(sudo_strlcat)
+])
+AC_CHECK_FUNC([strnlen], [AC_FUNC_STRNLEN], [AC_LIBOBJ(strnlen)])
+AS_IF([test X"$ac_cv_func_strnlen_working" = X"yes"], [
+ AC_DEFINE(HAVE_STRNLEN)
+ AC_CHECK_FUNCS([strndup], [], [
+ AC_LIBOBJ(strndup)
+ SUDO_APPEND_COMPAT_EXP(sudo_strndup)
+ ])
+], [
+ # Broken or missing strnlen, use our own.
+ SUDO_APPEND_COMPAT_EXP(sudo_strnlen)
+ # Avoid libc strndup() since it is usually implemented using strnlen()
+ AC_LIBOBJ(strndup)
+ SUDO_APPEND_COMPAT_EXP(sudo_strndup)
+])
+AC_CHECK_FUNCS([clock_gettime], [], [
+ # On Solaris, clock_gettime is in librt
+ AC_CHECK_LIB([rt], [clock_gettime], [
+ AC_DEFINE(HAVE_CLOCK_GETTIME)
+ LIBRT="-lrt"
+ ])
+])
+AC_CHECK_FUNCS([getopt_long], [], [
+ AC_LIBOBJ(getopt_long)
+ SUDO_APPEND_COMPAT_EXP(sudo_getopt_long sudo_getopt_long_only)
+ AC_CACHE_CHECK([for optreset], sudo_cv_optreset, [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[extern int optreset; optreset = 1; return optreset;]])], [sudo_cv_optreset=yes], [sudo_cv_optreset=no])])
+ AS_IF([test "$sudo_cv_optreset" = "yes"], [
+ AC_DEFINE(HAVE_OPTRESET)
+ ])
+])
+AC_CHECK_FUNCS([closefrom], [], [AC_LIBOBJ(closefrom)
+ SUDO_APPEND_COMPAT_EXP(sudo_closefrom)
+ AC_CHECK_DECL(F_CLOSEM, AC_DEFINE(HAVE_FCNTL_CLOSEM), [
+ # Linux has a special header for close_range(2).
+ AC_CHECK_FUNCS([close_range], [
+ case "$host_os" in
+ linux*) AC_CHECK_HEADERS([linux/close_range.h]);;
+ esac
+ ])
+ ], [
+# include <limits.h>
+# include <fcntl.h> ])
+ COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }closefrom_test"
+])
+sudo_mktemp=no
+case "$host_os" in
+ darwin*)
+ # macOS has these but uses a _np (non-portable) suffix
+ AC_CHECK_FUNCS([mkdtempat_np mkostempsat_np], [], [sudo_mktemp=yes; break])
+ ;;
+ *)
+ AC_CHECK_FUNCS([mkdtempat mkostempsat], [], [sudo_mktemp=yes; break])
+ ;;
+esac
+# If any of the mktemp family are missing we use our own.
+AS_IF([test X"$sudo_mktemp" = X"yes"], [
+ AC_LIBOBJ(mktemp)
+ SUDO_APPEND_COMPAT_EXP(sudo_mkdtemp sudo_mkdtempat sudo_mkostempsat sudo_mkstemp sudo_mkstemps)
+ COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }mktemp_test"
+])
+AX_FUNC_SNPRINTF
+AS_IF([test X"$ac_cv_have_working_snprintf$ac_cv_have_working_vsnprintf" = X"yesyes"], [
+ # System has a C99-compliant v?snprintf(), check for v?asprintf()
+ AC_CHECK_FUNCS([asprintf], [], [
+ AC_LIBOBJ(snprintf)
+ SUDO_APPEND_COMPAT_EXP(sudo_asprintf)
+ ])
+ AC_CHECK_FUNCS([vasprintf], [], [
+ AC_LIBOBJ(snprintf)
+ SUDO_APPEND_COMPAT_EXP(sudo_vasprintf)
+ ])
+], [
+ # Missing or non-compliant v?snprintf(), assume missing/bad v?asprintf()
+ SUDO_APPEND_COMPAT_EXP(sudo_snprintf sudo_vsnprintf sudo_asprintf sudo_vasprintf)
+])
+AC_CHECK_MEMBERS([struct tm.tm_gmtoff], [], [], [
+AC_INCLUDES_DEFAULT
+#include <errno.h>
+])
+AC_CHECK_MEMBER([struct stat.st_mtim],
+ [AC_DEFINE(HAVE_ST_MTIM)]
+ [AC_CHECK_MEMBER([struct stat.st_mtim.st__tim], AC_DEFINE(HAVE_ST__TIM))],
+ [AC_CHECK_MEMBER([struct stat.st_mtimespec],
+ [AC_DEFINE([HAVE_ST_MTIMESPEC])],
+ [AC_CHECK_MEMBER([struct stat.st_nmtime], AC_DEFINE(HAVE_ST_NMTIME))])
+ ]
+)
+dnl
+dnl 4.4BSD-based systems can force the password or group file to be held open
+dnl
+AC_CHECK_FUNCS([setpassent setgroupent])
+dnl
+dnl Function checks for sudo_noexec
+dnl
+AS_IF([test X"$with_noexec" != X"no"], [
+ # Check for non-standard exec functions
+ AC_CHECK_FUNCS([exect execvP execvpe])
+ # Check for posix_spawn, and posix_spawnp
+ AS_IF([test X"$ac_cv_header_spawn_h" = X"yes"], [
+ AC_CHECK_FUNCS([posix_spawn posix_spawnp])
+ ])
+])
+
+dnl
+dnl Check for the dirfd function/macro. If not found, look for dd_fd in DIR.
+dnl
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
+#include <$ac_header_dirent>]], [[DIR *d; (void)dirfd(d);]])], [AC_DEFINE(HAVE_DIRFD)], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
+#include <$ac_header_dirent>]], [[DIR d; memset(&d, 0, sizeof(d)); return(d.dd_fd);]])], [AC_DEFINE(HAVE_DD_FD)], [])])
+AC_CHECK_MEMBERS([struct dirent.d_type, struct dirent.d_namlen], [], [], [
+AC_INCLUDES_DEFAULT
+#include <$ac_header_dirent>
+])
+
+dnl
+dnl Check for OpenSSL or wolfSSL
+dnl
+SUDO_CHECK_OPENSSL
+
+dnl
+dnl Check for sha2 functions if not using openssl or wolfssl
+dnl
+AS_IF([test "$DIGEST" = "digest.lo"], [
+ AS_IF([test "${enable_gcrypt-no}" != no], [
+ # Use gcrypt's sha2 functions
+ AC_DEFINE(HAVE_GCRYPT)
+ DIGEST=digest_gcrypt.lo
+ LIBCRYPTO="-lgcrypt"
+ AS_IF([test "$enable_gcrypt" != "yes"], [
+ AX_APPEND_FLAG([-I${enable_gcrypt}/include], [CPPFLAGS])
+ SUDO_APPEND_LIBPATH(LDFLAGS, [${enable_gcrypt}/lib])
+ ])
+ ], [
+ # Use sudo's sha2 functions if not in libmd or libc.
+ FOUND_SHA2=no
+ AC_CHECK_HEADER([sha2.h], [
+ FOUND_SHA2=yes
+ AC_CHECK_FUNCS([SHA224Update], [SUDO_FUNC_SHA2_VOID_PTR], [
+ # On some systems, SHA224Update is in libmd
+ AC_CHECK_LIB([md], [SHA224Update], [
+ AC_DEFINE(HAVE_SHA224UPDATE)
+ SUDO_FUNC_SHA2_VOID_PTR
+ LIBCRYPTO="-lmd"
+ ], [
+ # Does not have SHA224Update
+ FOUND_SHA2=no
+ ])
+ ])
+ ])
+ AS_IF([test X"$FOUND_SHA2" = X"no"], [
+ AC_LIBOBJ(sha2)
+ SUDO_APPEND_COMPAT_EXP(sudo_SHA224Final sudo_SHA224Init sudo_SHA224Pad sudo_SHA224Transform sudo_SHA224Update sudo_SHA256Final sudo_SHA256Init sudo_SHA256Pad sudo_SHA256Transform sudo_SHA256Update sudo_SHA384Final sudo_SHA384Init sudo_SHA384Pad sudo_SHA384Transform sudo_SHA384Update sudo_SHA512Final sudo_SHA512Init sudo_SHA512Pad sudo_SHA512Transform sudo_SHA512Update)
+ ])
+ ])
+])
+
+dnl
+dnl Network functions may live in libsocket, libinet, libnsl, or libresolv.
+dnl Order is important here.
+dnl
+SUDO_CHECK_NET_FUNC([socket])
+
+dnl
+dnl We need to keep track of inet_pton()'s dependent libraries for
+dnl our getaddrinfo() replacement.
+dnl
+ONET_LIBS="$NET_LIBS"
+SUDO_CHECK_NET_FUNC([inet_pton], [
+ AC_DEFINE(HAVE_INET_PTON)
+ INET_PTON_LIBS=
+ for lib in $NET_LIBS; do
+ case "$ONET_LIBS" in
+ *"$lib"*) ;;
+ *) INET_PTON_LIBS="${INET_PTON_LIBS}${INET_PTON_LIBS+ }$lib";;
+ esac
+ done
+], [
+ AC_LIBOBJ(inet_pton)
+ SUDO_APPEND_COMPAT_EXP(sudo_inet_pton)
+])
+
+dnl
+dnl The check for inet_ntop() must follow inet_pton() for INET_PTON_LIBS.
+dnl
+SUDO_CHECK_NET_FUNC([inet_ntop], [
+ AC_DEFINE(HAVE_INET_NTOP)
+], [
+ AC_LIBOBJ(inet_ntop)
+ SUDO_APPEND_COMPAT_EXP(sudo_inet_ntop)
+])
+
+dnl
+dnl The check for syslog() must be last so we can detect INET_PTON_LIBS.
+dnl
+SUDO_CHECK_NET_FUNC([syslog])
+
+dnl
+dnl Check for getaddrinfo and add any required libs to NET_LIBS.
+dnl If it was added to LIBOBJS we need to export the symbols.
+dnl
+OLIBS="$LIBS"
+GETADDRINFO_LIBS=
+AX_FUNC_GETADDRINFO
+case " $LIBOBJS " in
+ *" getaddrinfo.$ac_objext "* )
+ SUDO_APPEND_COMPAT_EXP(sudo_getaddrinfo sudo_freeaddrinfo sudo_gai_strerror)
+ # We need libsudo_util to pull in dependent libraries for
+ # inet_pton(), gethostbyname(), and getservbyname()
+ AS_IF([test -n "${INET_PTON_LIBS}"], [
+ LT_DEP_LIBS="${LT_DEP_LIBS}${LT_DEP_LIBS+ }${INET_PTON_LIBS}"
+ LIBS="${LIBS}${LIBS+ }${INET_PTON_LIBS}"
+ ])
+ SUDO_CHECK_NET_FUNC([gethostbyname])
+ ;;
+ *)
+ for lib in $LIBS; do
+ case "$OLIBS" in
+ *"$lib"*) ;;
+ *) GETADDRINFO_LIBS="${GETADDRINFO_LIBS}${GETADDRINFO_LIBS+ }$lib";;
+ esac
+ done
+ AS_IF([test -n "${GETADDRINFO_LIBS}"], [
+ # We need libsudo_util to pull in dependent libraries for
+ # gai_strerror()
+ LT_DEP_LIBS="${LT_DEP_LIBS}${LT_DEP_LIBS+ }${GETADDRINFO_LIBS}"
+ LIBS="${LIBS}${LIBS+ }${GETADDRINFO_LIBS}"
+
+ # Add to NET_LIBS if necessary
+ for lib in $GETADDRINFO_LIBS; do
+ case "$NET_LIBS" in
+ *"$lib"*) ;;
+ *) NET_LIBS="${NET_LIBS}${NET_LIBS+ }$lib";;
+ esac
+ done
+ ])
+ ;;
+esac
+LIBS="$OLIBS"
+
+dnl
+dnl Check for va_copy or __va_copy in stdarg.h
+dnl
+AC_CACHE_CHECK([for va_copy], sudo_cv_func_va_copy, [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdarg.h>
+ va_list ap1, ap2;]], [[va_copy(ap1, ap2);]])],
+ [sudo_cv_func_va_copy=yes], [sudo_cv_func_va_copy=no])
+])
+AS_IF([test "$sudo_cv_func_va_copy" = "yes"], [
+ AC_DEFINE(HAVE_VA_COPY)
+], [
+ AC_CACHE_CHECK([for __va_copy], sudo_cv_func___va_copy, [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdarg.h>
+ va_list ap1, ap2;]], [[__va_copy(ap1, ap2);]])],
+ [sudo_cv_func___va_copy=yes], [sudo_cv_func___va_copy=no])
+ ])
+ AS_IF([test "$sudo_cv_func___va_copy" = "yes"], [
+ AC_DEFINE(HAVE___VA_COPY)
+ ])
+])
+
+dnl
+dnl Check for getprogname()/setprogname() or __progname
+dnl
+AC_CHECK_FUNCS([getprogname], [
+ AC_CHECK_FUNCS([setprogname], [], [SUDO_APPEND_COMPAT_EXP(sudo_setprogname)])
+], [
+ AC_CACHE_CHECK([for __progname], sudo_cv___progname, [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[extern char *__progname; if (__progname[0] == '\0') return 1;]])], [sudo_cv___progname=yes], [sudo_cv___progname=no])])
+ AS_IF([test "$sudo_cv___progname" = "yes"], [
+ AC_DEFINE(HAVE___PROGNAME)
+ ])
+ SUDO_APPEND_COMPAT_EXP(sudo_getprogname)
+ SUDO_APPEND_COMPAT_EXP(sudo_setprogname)
+])
+
+dnl
+dnl Check for __func__ or __FUNCTION__
+dnl
+AC_CACHE_CHECK([for __func__], sudo_cv___func__, [
+ AS_IF([test X"$ac_cv_prog_cc_c99" = X"no"], [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[if (__func__[0] == '\0') return 1;]])], [sudo_cv___func__=yes], [sudo_cv___func__=no])
+ ], [
+ # C99 and higher support __func__
+ sudo_cv___func__=yes
+ ])
+])
+AS_IF([test "$sudo_cv___func__" = "yes"], [
+ AC_DEFINE(HAVE___FUNC__)
+], [test -n "$GCC"], [
+ AC_CACHE_CHECK([for __FUNCTION__], sudo_cv___FUNCTION__, [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[if(__FUNCTION__[0] == '\0') return 1;]])], [sudo_cv___FUNCTION__=yes], [sudo_cv___FUNCTION__=no])])
+ AS_IF([test "$sudo_cv___FUNCTION__" = "yes"], [
+ AC_DEFINE(HAVE___FUNC__)
+ AC_DEFINE(__func__, __FUNCTION__, [Define to __FUNCTION__ if your compiler supports __FUNCTION__ but not __func__])
+ ])
+])
+
+SUDO_CHECK_GETTEXT
+
+dnl
+dnl Deferred zlib option processing.
+dnl By default we use the system zlib if it is present.
+dnl If a directory was specified for zlib (or we are use sudo's version),
+dnl prepend the include dir to make sure we get the right zlib header.
+dnl
+case "$enable_zlib" in
+ yes)
+ AC_CHECK_LIB([z], [gzclearerr], [
+ AC_CHECK_HEADERS([zlib.h], [ZLIB="-lz"], [enable_zlib=builtin])
+ ])
+ ;;
+ no)
+ ;;
+ system)
+ AC_DEFINE(HAVE_ZLIB_H)
+ ZLIB="-lz"
+ ;;
+ static|shared|builtin)
+ # handled below
+ ;;
+ *)
+ AC_DEFINE(HAVE_ZLIB_H)
+ AX_APPEND_FLAG([-I${enable_zlib}/include], [CPPFLAGS])
+ SUDO_APPEND_LIBPATH(ZLIB, [$enable_zlib/lib])
+ ZLIB="${ZLIB} -lz"
+ ;;
+esac
+case "$enable_zlib" in
+ builtin|static|dynamic)
+ AC_DEFINE(HAVE_ZLIB_H)
+ # XXX - can't use AX_APPEND_FLAG due to use of $(top_foo) and quoting
+ CPPFLAGS='-I$(top_builddir)/lib/zlib -I$(top_srcdir)/lib/zlib '"${CPPFLAGS}"
+ ZLIB="${ZLIB}"' $(top_builddir)/lib/zlib/libsudo_z.la'
+ ZLIB_SRC=lib/zlib
+ AC_CONFIG_HEADERS([lib/zlib/zconf.h])
+ AC_CONFIG_FILES([lib/zlib/Makefile])
+ AS_IF([test X"$enable_shared" = X"no" -o "$enable_zlib" = "static"], [
+ AS_IF([test "$enable_zlib" = "shared"], [
+ AC_MSG_ERROR([unable to build shared libraries on this system])
+ ])
+ # Build as convenience library
+ ZLIB_LDFLAGS=-no-install
+ ])
+ ;;
+esac
+
+dnl
+dnl Check for NSIG, _NSIG or __NSIG declarations in signal.h
+dnl
+AC_CHECK_DECLS([NSIG], [], [
+ AC_CHECK_DECLS([_NSIG], [], [
+ AC_CHECK_DECLS([__NSIG], [], [], [
+AC_INCLUDES_DEFAULT
+#include <signal.h>
+ ])
+ ], [
+AC_INCLUDES_DEFAULT
+#include <signal.h>
+ ])
+], [
+AC_INCLUDES_DEFAULT
+#include <signal.h>
+])
+
+dnl
+dnl Check for errno declaration in errno.h
+dnl
+AC_CHECK_DECLS([errno], [], [], [
+AC_INCLUDES_DEFAULT
+#include <errno.h>
+])
+
+dnl
+dnl Check for h_errno declaration in netdb.h
+dnl
+AC_CHECK_DECLS([h_errno], [], [], [
+AC_INCLUDES_DEFAULT
+#include <netdb.h>
+])
+
+dnl
+dnl Check for incomplete limits.h and missing SIZE_MAX.
+dnl
+AC_CHECK_DECLS([LLONG_MAX, LLONG_MIN, ULLONG_MAX, PATH_MAX, SSIZE_MAX], [], [], [
+#include <sys/types.h>
+#include <limits.h>
+])
+AC_CHECK_DECLS([SIZE_MAX], [], [], [
+#include <sys/types.h>
+#include <limits.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+])
+dnl
+dnl Try to find equivalents for missing types
+dnl
+AS_IF([test "$ac_cv_have_decl_LLONG_MAX" != "yes"], [
+ AC_CHECK_DECLS([QUAD_MAX], [], [], [[
+#include <sys/types.h>
+#include <limits.h>
+ ]])
+])
+AS_IF([test "$ac_cv_have_decl_LLONG_MIN" != "yes"], [
+ AC_CHECK_DECLS([QUAD_MIN], [], [], [[
+#include <sys/types.h>
+#include <limits.h>
+ ]])
+])
+AS_IF([test "$ac_cv_have_decl_ULLONG_MAX" != "yes"], [
+ AC_CHECK_DECLS([UQUAD_MAX], [], [], [[
+#include <sys/types.h>
+#include <limits.h>
+ ]])
+])
+AS_IF([test "$ac_cv_have_decl_SIZE_MAX" != "yes"], [
+ AC_CHECK_DECLS([SIZE_T_MAX], [], [], [[
+#include <sys/types.h>
+#include <limits.h>
+ ]])
+])
+AS_IF([test "$ac_cv_have_decl_PATH_MAX" != "yes"], [
+ AC_CHECK_DECLS([_POSIX_PATH_MAX], [], [], [[
+#include <sys/types.h>
+#include <limits.h>
+ ]])
+])
+
+dnl
+dnl Check for strsignal() or sys_siglist
+dnl
+AC_CHECK_FUNCS([strsignal], [], [
+ AC_LIBOBJ(strsignal)
+ SUDO_APPEND_COMPAT_EXP(sudo_strsignal)
+ HAVE_SIGLIST="false"
+ AC_CHECK_DECLS([sys_siglist], [HAVE_SIGLIST="true"], [
+ AC_CHECK_DECLS([_sys_siglist], [HAVE_SIGLIST="true"], [], [
+AC_INCLUDES_DEFAULT
+#include <signal.h>
+ ])
+ ], [
+AC_INCLUDES_DEFAULT
+#include <signal.h>
+ ])
+ AS_IF([test "$HAVE_SIGLIST" != "true"], [
+ AC_LIBOBJ(siglist)
+ ])
+])
+
+dnl
+dnl Check for sig2str() and str2sig(), sys_signame or sys_sigabbrev
+dnl
+AC_CHECK_FUNCS([sig2str], [
+ AC_CHECK_DECLS(SIG2STR_MAX, [], [], [
+# include <signal.h>
+])], [
+ AC_LIBOBJ(sig2str)
+ SUDO_APPEND_COMPAT_EXP(sudo_sig2str)
+])
+AC_CHECK_FUNCS([str2sig], [], [
+ AC_LIBOBJ(str2sig)
+ SUDO_APPEND_COMPAT_EXP(sudo_str2sig)
+])
+
+dnl
+dnl Check for sys_signame or sys_sigabbrev if missing sig2str() or str2sig().
+dnl Also enable unit tests for sig2str() and str2sig().
+dnl
+AS_IF([test x"${ac_cv_func_sig2str}${ac_cv_func_str2sig}" != x"yesyes"], [
+ AC_CHECK_FUNCS([sigabbrev_np])
+ AS_IF([test x"${ac_cv_func_sigabbrev_np}" != x"yes"], [
+ COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }strsig_test"
+ HAVE_SIGNAME="false"
+ AC_CHECK_DECLS([sys_signame], [HAVE_SIGNAME="true"], [
+ AC_CHECK_DECLS([_sys_signame], [HAVE_SIGNAME="true"], [
+ AC_CHECK_DECLS([sys_sigabbrev], [HAVE_SIGNAME="true"], [], [
+AC_INCLUDES_DEFAULT
+#include <signal.h>
+ ])
+ ], [
+AC_INCLUDES_DEFAULT
+#include <signal.h>
+ ])
+ ], [
+AC_INCLUDES_DEFAULT
+#include <signal.h>
+ ])
+ AS_IF([test "$HAVE_SIGNAME" != "true"], [
+ AC_CACHE_CHECK([for undeclared sys_sigabbrev],
+ [sudo_cv_var_sys_sigabbrev],
+ [AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[extern char **sys_sigabbrev;]], [[return sys_sigabbrev[1];]])],
+ [sudo_cv_var_sys_sigabbrev=yes],
+ [sudo_cv_var_sys_sigabbrev=no]
+ )
+ ]
+ )
+ AS_IF([test "$sudo_cv_var_sys_sigabbrev" = yes], [
+ AC_DEFINE(HAVE_SYS_SIGABBREV)
+ ], [
+ AC_LIBOBJ(signame)
+ SIGNAME=signame.lo
+ ])
+ ])
+ ])
+])
+
+dnl
+dnl Check for dl_iterate_phdr, may require -ldl
+dnl
+OLIBS="$LIBS"
+LIBS="$LIBS $lt_cv_dlopen_libs"
+AC_CHECK_FUNCS([dl_iterate_phdr])
+LIBS="$OLIBS"
+
+dnl
+dnl nsswitch.conf and its equivalents
+dnl
+AS_IF([test ${with_netsvc-"no"} != "no"], [
+ SUDO_DEFINE_UNQUOTED(_PATH_NETSVC_CONF, "${with_netsvc-/etc/netsvc.conf}")
+ netsvc_conf=${with_netsvc-/etc/netsvc.conf}
+], [test ${with_nsswitch-"yes"} != "no"], [
+ SUDO_DEFINE_UNQUOTED(_PATH_NSSWITCH_CONF, "${with_nsswitch-/etc/nsswitch.conf}")
+ nsswitch_conf=${with_nsswitch-/etc/nsswitch.conf}
+])
+
+dnl
+dnl Mutually exclusive auth checks come first, followed by
+dnl non-exclusive ones. Note: passwd must be last of all!
+dnl
+
+dnl
+dnl Convert default authentication methods to with_* if
+dnl no explicit authentication scheme was specified.
+dnl
+AS_IF([test -z "${AUTH_EXCL}${AUTH_REG}" -a -n "$AUTH_EXCL_DEF"], [
+ for auth in $AUTH_EXCL_DEF; do
+ case $auth in
+ AIX_AUTH) with_aixauth=maybe;;
+ BSD_AUTH) with_bsdauth=maybe;;
+ PAM) with_pam=maybe;;
+ SIA) CHECKSIA=true;;
+ esac
+ done
+])
+
+dnl
+dnl PAM support. Systems that use PAM by default set with_pam=default
+dnl and we do the actual tests here.
+dnl
+AS_IF([test ${with_pam-"no"} != "no"], [
+ #
+ # Check for pam_start() in libpam first, then for pam_appl.h.
+ #
+ found_pam_lib=no
+ AC_CHECK_LIB([pam], [pam_start], [found_pam_lib=yes], [], [$lt_cv_dlopen_libs])
+ #
+ # Some PAM implementations (macOS for example) put the PAM headers
+ # in /usr/include/pam instead of /usr/include/security...
+ #
+ found_pam_hdrs=no
+ AC_CHECK_HEADERS([security/pam_appl.h] [pam/pam_appl.h], [found_pam_hdrs=yes; break])
+ AS_IF([test "$found_pam_lib" = "yes" -a "$found_pam_hdrs" = "yes"], [
+ # Found both PAM libs and headers
+ with_pam=yes
+ ], [test "$with_pam" = "yes"], [
+ AS_IF([test "$found_pam_lib" = "no"], [
+ AC_MSG_ERROR([--with-pam specified but unable to locate PAM development library.])
+ ])
+ AS_IF([test "$found_pam_hdrs" = "no"], [
+ AC_MSG_ERROR([--with-pam specified but unable to locate PAM development headers.])
+ ])
+ ], [test "$found_pam_lib" != "$found_pam_hdrs"], [
+ AS_IF([test "$found_pam_lib" = "no"], [
+ AC_MSG_ERROR([found PAM headers but no PAM development library; specify --without-pam to build without PAM])
+ ])
+ AS_IF([test "$found_pam_hdrs" = "no"], [
+ AC_MSG_ERROR([found PAM library but no PAM development headers; specify --without-pam to build without PAM])
+ ])
+ ])
+
+ AS_IF([test "$with_pam" = "yes"], [
+ # Older PAM implementations lack pam_getenvlist
+ OLIBS="$LIBS"
+ LIBS="$LIBS -lpam $lt_cv_dlopen_libs"
+ AC_CHECK_FUNCS([pam_getenvlist])
+ LIBS="$OLIBS"
+
+ # We already link with -ldl if needed (see LIBDL below)
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lpam"
+ AC_DEFINE(HAVE_PAM)
+ AUTH_OBJS="$AUTH_OBJS pam.lo";
+ AUTH_EXCL=PAM
+
+ AC_ARG_WITH(pam-login, [AS_HELP_STRING([--with-pam-login], [enable specific PAM session for sudo -i])],
+ [case $with_pam_login in
+ yes) AC_DEFINE([HAVE_PAM_LOGIN])
+ pam_login_service="sudo-i"
+ ;;
+ no) ;;
+ *) AC_MSG_ERROR([--with-pam-login does not take an argument.])
+ ;;
+ esac])
+
+ AC_ARG_ENABLE(pam_session,
+ [AS_HELP_STRING([--disable-pam-session], [Disable PAM session support])],
+ [ case "$enableval" in
+ yes) ;;
+ no) AC_DEFINE(NO_PAM_SESSION)
+ pam_session=off
+ ;;
+ *) AC_MSG_WARN([ignoring unknown argument to --enable-pam-session: $enableval])
+ ;;
+ esac])
+ ])
+])
+
+dnl
+dnl AIX general authentication
+dnl We may build in support for both AIX LAM and PAM and select
+dnl which one to use at run-time.
+dnl
+AS_IF([test ${with_aixauth-'no'} != "no"], [
+ AC_CHECK_FUNCS([authenticate], [with_aixauth=yes])
+ AS_IF([test "${with_aixauth}" = "yes"], [
+ AC_MSG_NOTICE([using AIX general authentication])
+ AC_DEFINE(HAVE_AIXAUTH)
+ AUTH_OBJS="$AUTH_OBJS aix_auth.lo";
+ SUDOERS_LIBS="${SUDOERS_LIBS} -ls"
+ AUTH_EXCL=AIX_AUTH
+ ])
+])
+
+dnl
+dnl BSD authentication
+dnl If set to "maybe" only enable if no other exclusive method in use.
+dnl
+AS_IF([test ${with_bsdauth-'no'} != "no"], [
+ AC_CHECK_HEADER(bsd_auth.h, AC_DEFINE(HAVE_BSD_AUTH_H)
+ [AUTH_OBJS="$AUTH_OBJS bsdauth.lo"]
+ [BSDAUTH_USAGE='[[-a type]] ']
+ [AUTH_EXCL=BSD_AUTH; BAMAN=1],
+ [AC_MSG_ERROR([BSD authentication was specified but bsd_auth.h could not be found])])
+])
+
+dnl
+dnl SIA authentication for Tru64 Unix
+dnl
+AS_IF([test ${CHECKSIA-'false'} = "true"], [
+ AC_CHECK_FUNCS([sia_ses_init], [found=true], [found=false])
+ AS_IF([test "$found" = "true"], [
+ AUTH_EXCL=SIA
+ AUTH_OBJS="$AUTH_OBJS sia.lo"
+ ])
+])
+
+dnl
+dnl extra FWTK libs + includes
+dnl
+AS_IF([test ${with_fwtk-'no'} != "no"], [
+ AS_IF([test "$with_fwtk" != "yes"], [
+ SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${with_fwtk}])
+ AX_APPEND_FLAG([-I${with_fwtk}], [CPPFLAGS])
+ with_fwtk=yes
+ ])
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lauth -lfwall"
+ AUTH_OBJS="$AUTH_OBJS fwtk.lo"
+])
+
+dnl
+dnl extra SecurID lib + includes
+dnl
+AS_IF([test ${with_SecurID-'no'} != "no"], [
+ AS_IF([test "$with_SecurID" != "yes"], [], [test -d /usr/ace/examples], [
+ with_SecurID=/usr/ace/examples
+ ], [
+ with_SecurID=/usr/ace
+ ])
+ AX_APPEND_FLAG([-I${with_SecurID}], [CPPFLAGS])
+ SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${with_SecurID}])
+ SUDOERS_LIBS="${SUDOERS_LIBS} -laceclnt -lpthread"
+ AUTH_OBJS="$AUTH_OBJS securid5.lo";
+])
+
+dnl
+dnl Non-mutually exclusive auth checks come next.
+dnl Note: passwd must be last of all!
+dnl
+
+dnl
+dnl Convert default authentication methods to with_* if
+dnl no explicit authentication scheme was specified.
+dnl
+AS_IF([test -z "${AUTH_EXCL}" -a -n "$AUTH_DEF"], [
+ for auth in $AUTH_DEF; do
+ case $auth in
+ passwd) : ${with_passwd='maybe'};;
+ esac
+ done
+])
+
+dnl
+dnl Kerberos V
+dnl There is an easy way and a hard way...
+dnl
+AS_IF([test ${with_kerb5-'no'} != "no"], [
+ AC_CHECK_PROG(KRB5CONFIG, krb5-config, yes, "")
+ AS_IF([test -n "$KRB5CONFIG"], [
+ AC_DEFINE(HAVE_KERB5)
+ AUTH_OBJS="$AUTH_OBJS kerb5.lo"
+ for f in `krb5-config --cflags`; do
+ AX_APPEND_FLAG([$f], [CPPFLAGS])
+ done
+ SUDOERS_LIBS="$SUDOERS_LIBS `krb5-config --libs`"
+ dnl
+ dnl Try to determine whether we have Heimdal or MIT Kerberos
+ dnl
+ AC_MSG_CHECKING(whether we are using Heimdal)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <krb5.h>]], [[const char *tmp = heimdal_version;]])], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_HEIMDAL)
+ ], [
+ AC_MSG_RESULT(no)
+ ]
+ )
+ ], [
+ AC_DEFINE(HAVE_KERB5)
+ dnl
+ dnl Use the specified directory, if any, else search for correct inc dir
+ dnl
+ AS_IF([test "$with_kerb5" = "yes"], [
+ found=no
+ O_CPPFLAGS="$CPPFLAGS"
+ for dir in "" "kerberosV/" "krb5/" "kerberos5/" "kerberosv5/"; do
+ CPPFLAGS="$O_CPPFLAGS -I/usr/include/${dir}"
+ AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[#include <krb5.h>]])], [found=yes; break])
+ done
+ AS_IF([test X"$found" = X"no"], [
+ CPPFLAGS="$O_CPPFLAGS"
+ AC_MSG_WARN([unable to locate Kerberos V include files, you will have to edit the Makefile and add -I/path/to/krb/includes to CPPFLAGS])
+ ])
+ ], [
+ dnl XXX - try to include krb5.h here too
+ SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${with_kerb5}/lib])
+ AX_APPEND_FLAG([-I${with_kerb5}/include], [CPPFLAGS])
+ ])
+
+ dnl
+ dnl Try to determine whether we have Heimdal or MIT Kerberos
+ dnl
+ AC_MSG_CHECKING(whether we are using Heimdal)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <krb5.h>]], [[const char *tmp = heimdal_version;]])], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_HEIMDAL)
+ # XXX - need to check whether -lcrypo is needed!
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lkrb5 -lcrypto -ldes -lcom_err -lasn1"
+ AC_CHECK_LIB([roken], [main], [SUDOERS_LIBS="${SUDOERS_LIBS} -lroken"])
+ ], [
+ AC_MSG_RESULT(no)
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lkrb5 -lk5crypto -lcom_err"
+ AC_CHECK_LIB([krb5support], [main], [SUDOERS_LIBS="${SUDOERS_LIBS} -lkrb5support"])
+ ])
+ AUTH_OBJS="$AUTH_OBJS kerb5.lo"
+ ])
+ _LIBS="$LIBS"
+ LIBS="${LIBS} ${SUDOERS_LIBS}"
+ AC_CHECK_FUNCS([krb5_verify_user krb5_init_secure_context])
+ AC_CHECK_FUNCS([krb5_get_init_creds_opt_alloc], [
+ AC_CACHE_CHECK([whether krb5_get_init_creds_opt_free takes a context],
+ sudo_cv_krb5_get_init_creds_opt_free_two_args, [
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <krb5.h>]],
+ [[krb5_get_init_creds_opt_free(NULL, NULL);]]
+ )],
+ [sudo_cv_krb5_get_init_creds_opt_free_two_args=yes],
+ [sudo_cv_krb5_get_init_creds_opt_free_two_args=no]
+ )
+ ]
+ )
+ ])
+ AS_IF([test X"$sudo_cv_krb5_get_init_creds_opt_free_two_args" = X"yes"], [
+ AC_DEFINE(HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_TWO_ARGS)
+ ])
+ LIBS="$_LIBS"
+ AC_ARG_ENABLE(kerb5-instance,
+ [AS_HELP_STRING([--enable-kerb5-instance], [instance string to append to the username (separated by a slash)])],
+ [ case "$enableval" in
+ yes) AC_MSG_ERROR([must give --enable-kerb5-instance an argument.])
+ ;;
+ no) ;;
+ *) SUDO_DEFINE_UNQUOTED(SUDO_KRB5_INSTANCE, "$enableval")
+ ;;
+ esac])
+])
+
+dnl
+dnl extra AFS libs and includes
+dnl
+AS_IF([test ${with_AFS-'no'} = "yes"], [
+ # looks like the "standard" place for AFS libs is /usr/afsws/lib
+ AFSLIBDIRS="/usr/lib/afs /usr/afsws/lib /usr/afsws/lib/afs"
+ for i in $AFSLIBDIRS; do
+ AS_IF([test -d ${i}], [
+ SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [$i])
+ FOUND_AFSLIBDIR=true
+ ])
+ done
+ AS_IF([test -z "$FOUND_AFSLIBDIR"], [
+ AC_MSG_WARN([unable to locate AFS libraries, you will have to edit the Makefile and add -L/path/to/afs/libs to SUDOERS_LDFLAGS or rerun configure with the --with-libpath options.])
+ ])
+
+ # Order is important here. Note that we build AFS_LIBS from right to left
+ # since AFS_LIBS may be initialized with BSD compat libs that must go last
+ AFS_LIBS="-laudit ${AFS_LIBS}"
+ for i in $AFSLIBDIRS; do
+ AS_IF([test -f ${i}/util.a], [
+ AFS_LIBS="${i}/util.a ${AFS_LIBS}"
+ FOUND_UTIL_A=true
+ break;
+ ])
+ done
+ AS_IF([test -z "$FOUND_UTIL_A"], [
+ AFS_LIBS="-lutil ${AFS_LIBS}"
+ ])
+ AFS_LIBS="-lkauth -lprot -lubik -lauth -lrxkad -lsys -ldes -lrx -llwp -lcom_err ${AFS_LIBS}"
+
+ # AFS includes may live in /usr/include on some machines...
+ for i in /usr/afsws/include; do
+ AS_IF([test -d ${i}], [
+ AX_APPEND_FLAG([-I${i}], [CPPFLAGS])
+ FOUND_AFSINCDIR=true
+ ])
+ done
+
+ AS_IF([test -z "$FOUND_AFSLIBDIR"], [
+ AC_MSG_WARN([unable to locate AFS include dir, you may have to edit the Makefile and add -I/path/to/afs/includes to CPPFLAGS or rerun configure with the --with-incpath options.])
+ ])
+
+ AUTH_OBJS="$AUTH_OBJS afs.lo"
+])
+
+dnl
+dnl extra DCE obj + lib
+dnl Order of libs in HP-UX 10.x is important, -ldce must be last.
+dnl
+AS_IF([test ${with_DCE-'no'} = "yes"], [
+ DCE_OBJS="${DCE_OBJS} dce_pwent.o"
+ SUDOERS_LIBS="${SUDOERS_LIBS} -ldce"
+ AUTH_OBJS="$AUTH_OBJS dce.lo"
+])
+
+dnl
+dnl extra S/Key lib and includes
+dnl
+AS_IF([test "${with_skey-'no'}" = "yes"], [
+ O_LDFLAGS="$LDFLAGS"
+ AS_IF([test "$with_skey" != "yes"], [
+ AX_APPEND_FLAG([-I${with_skey}/include], [CPPFLAGS])
+ LDFLAGS="$LDFLAGS -L${with_skey}/lib"
+ SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${with_skey}/lib])
+ AC_CHECK_HEADER([skey.h], [found=yes], [found=no], [#include <stdio.h>])
+ ], [
+ found=no
+ O_CPPFLAGS="$CPPFLAGS"
+ for dir in "" "/usr/local" "/usr/contrib"; do
+ test -n "$dir" && CPPFLAGS="$O_CPPFLAGS -I${dir}/include"
+ AC_CHECK_HEADER([skey.h], [found=yes; break], [], [#include <stdio.h>])
+ done
+ AS_IF([test "$found" = "no" -o -z "$dir"], [
+ CPPFLAGS="$O_CPPFLAGS"
+ ], [
+ LDFLAGS="$LDFLAGS -L${dir}/lib"
+ SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${dir}/lib])
+ ])
+ AS_IF([test "$found" = "no"], [
+ AC_MSG_WARN([unable to locate skey.h, you will have to edit the Makefile and add -I/path/to/skey/includes to CPPFLAGS])
+ ])
+ ])
+ AC_CHECK_LIB([skey], [main], [found=yes], [AC_MSG_WARN([unable to locate libskey.a, you will have to edit the Makefile and add -L/path/to/skey/lib to SUDOERS_LDFLAGS])])
+ AC_CHECK_LIB([skey], [skeyaccess], [AC_DEFINE(HAVE_SKEYACCESS)])
+
+ AC_MSG_CHECKING([for RFC1938-compliant skeychallenge])
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[
+# include <stdio.h>
+# include <skey.h>]],
+ [[skeychallenge(NULL, NULL, NULL, 0);]]
+ )], [
+ AC_DEFINE(HAVE_RFC1938_SKEYCHALLENGE)
+ AC_MSG_RESULT([yes])
+ ], [
+ AC_MSG_RESULT([no])
+ ]
+ )
+
+ LDFLAGS="$O_LDFLAGS"
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lskey"
+ AUTH_OBJS="$AUTH_OBJS rfc1938.lo"
+])
+
+dnl
+dnl extra OPIE lib and includes
+dnl
+AS_IF([test "${with_opie-'no'}" = "yes"], [
+ O_LDFLAGS="$LDFLAGS"
+ AS_IF([test "$with_opie" != "yes"], [
+ AX_APPEND_FLAG([-I${with_opie}/include], [CPPFLAGS])
+ LDFLAGS="$LDFLAGS -L${with_opie}/lib"
+ SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${with_opie}/lib])
+ AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[#include <opie.h>]])], [found=yes], [found=no])
+ ], [
+ found=no
+ O_CPPFLAGS="$CPPFLAGS"
+ for dir in "" "/usr/local" "/usr/contrib"; do
+ test -n "$dir" && CPPFLAGS="$O_CPPFLAGS -I${dir}/include"
+ AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[#include <opie.h>]])], [found=yes; break])
+ done
+ AS_IF([test "$found" = "no" -o -z "$dir"], [
+ CPPFLAGS="$O_CPPFLAGS"
+ ], [
+ LDFLAGS="$LDFLAGS -L${dir}/lib"
+ SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${dir}/lib])
+ ])
+ AS_IF([test "$found" = "no"], [
+ AC_MSG_WARN([unable to locate opie.h, you will have to edit the Makefile and add -I/path/to/opie/includes to CPPFLAGS])
+ ])
+ ])
+ AC_CHECK_LIB([opie], [main], [found=yes], [AC_MSG_WARN([unable to locate libopie.a, you will have to edit the Makefile and add -L/path/to/opie/lib to SUDOERS_LDFLAGS])])
+ LDFLAGS="$O_LDFLAGS"
+ SUDOERS_LIBS="${SUDOERS_LIBS} -lopie"
+ AUTH_OBJS="$AUTH_OBJS rfc1938.lo"
+])
+
+dnl
+dnl Check for shadow password routines if we have not already done so.
+dnl If there is a specific list of functions to check we do that first.
+dnl Otherwise, we check for SVR4-style and then SecureWare-style.
+dnl
+AS_IF([test ${with_passwd-'no'} != "no"], [
+ dnl
+ dnl if crypt(3) not in libc, look elsewhere
+ dnl
+ _LIBS="$LIBS"
+ AC_SEARCH_LIBS([crypt], [crypt crypt_d ufc], [
+ test "${ac_cv_search_crypt}" != "none required" && shadow_libs="${shadow_libs} ${ac_cv_search_crypt}"
+ ])
+ AS_IF([test "${ac_cv_search_crypt}" != "no"], [
+ AC_DEFINE(HAVE_CRYPT)
+ ])
+ LIBS="$_LIBS"
+
+ AS_IF([test "$CHECKSHADOW" = "true" -a -n "$shadow_funcs"], [
+ _LIBS="$LIBS"
+ LIBS="$LIBS $shadow_libs"
+ found=no
+ for func in $shadow_funcs; do
+ AC_CHECK_FUNC([$func], [
+ dnl Enumerate shadow functions instead of using:
+ dnl AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_$func]))
+ dnl for autoheader's sake and to catch template omissions.
+ case "$func" in
+ dispcrypt)
+ AC_DEFINE(HAVE_DISPCRYPT)
+ ;;
+ getprpwnam)
+ AC_DEFINE(HAVE_GETPRPWNAM)
+ SECUREWARE=1
+ ;;
+ getpwnam_shadow)
+ AC_DEFINE(HAVE_GETPWNAM_SHADOW)
+ ;;
+ getspnam)
+ AC_DEFINE(HAVE_GETSPNAM)
+ ;;
+ iscomsec)
+ AC_DEFINE(HAVE_ISCOMSEC)
+ ;;
+ *)
+ AC_MSG_ERROR([unhandled shadow password function $func])
+ ;;
+ esac
+ found=yes
+ ])
+ done
+ AS_IF([test "$found" = "no"], [
+ shadow_libs=
+ ])
+ CHECKSHADOW=false
+ LIBS="$_LIBS"
+ ])
+ AS_IF([test "$CHECKSHADOW" = "true"], [
+ AC_SEARCH_LIBS([getspnam], [gen shadow], [
+ AC_DEFINE(HAVE_GETSPNAM)
+ test "${ac_cv_search_getspnam}" != "none required" && shadow_libs="${shadow_libs} ${ac_cv_search_getspnam}"
+ CHECKSHADOW=false
+ ])
+ ])
+ AS_IF([test "$CHECKSHADOW" = "true"], [
+ AC_SEARCH_LIBS([getprpwnam], [sec security prot], [
+ AC_DEFINE(HAVE_GETPRPWNAM)
+ test "${ac_cv_search_getprpwnam}" != "none required" && shadow_libs="${shadow_libs} ${ac_cv_search_getprpwnam}"
+ SECUREWARE=1
+ CHECKSHADOW=false
+ ])
+ ])
+ AS_IF([test -n "$shadow_libs"], [
+ # sudoers needs to link with shadow libs for password auth
+ SUDOERS_LIBS="$SUDOERS_LIBS $shadow_libs"
+ ])
+ AS_IF([test -n "$SECUREWARE"], [
+ _LIBS="$LIBS"
+ LIBS="$LIBS $shadow_libs"
+ AC_CHECK_FUNCS([bigcrypt])
+ AUTH_OBJS="$AUTH_OBJS secureware.lo"
+ # set_auth_parameters() and initprivs() are called from sudo.c
+ AC_CHECK_FUNCS([set_auth_parameters initprivs], [test -n "$shadow_libs" && SUDO_LIBS="$SUDO_LIBS $shadow_libs"])
+ LIBS="$_LIBS"
+ ])
+])
+
+dnl
+dnl Solaris 11 added a 4th argument to the au_close() function
+dnl
+AS_IF([test X"$with_bsm_audit" = X"yes"], [
+ SUDO_FUNC_AU_CLOSE_SOLARIS11
+])
+
+dnl
+dnl Choose event subsystem backend: poll or select
+dnl
+AS_IF([test X"$enable_poll" = X""], [
+ AC_CHECK_FUNCS([ppoll poll], [enable_poll=yes; break], [enable_poll=no])
+], [test X"$enable_poll" = X"yes"], [
+ AC_CHECK_FUNCS([ppoll], [], AC_DEFINE(HAVE_POLL))
+])
+AS_IF([test "$enable_poll" = "yes"], [
+ COMMON_OBJS="${COMMON_OBJS} event_poll.lo"
+], [
+ AC_CHECK_FUNCS([pselect])
+ COMMON_OBJS="${COMMON_OBJS} event_select.lo"
+])
+
+dnl
+dnl If LDAP support is enabled, add sudo ldap objects to SUDOERS_OBJS
+dnl and add LDAP libraries to SUDOERS_LDFLAGS SUDOERS_LIBS.
+dnl
+SUDO_CHECK_LDAP
+
+#
+# How to do dynamic object loading.
+# We support dlopen() and sh_load(), else fall back to static loading.
+#
+case "$lt_cv_dlopen" in
+ dlopen)
+ AC_DEFINE(HAVE_DLOPEN)
+ AS_IF([test "$enable_static_sudoers" = "yes"], [
+ AC_DEFINE(STATIC_SUDOERS_PLUGIN)
+ SUDO_OBJS="${SUDO_OBJS} preload.o"
+ STATIC_SUDOERS="\$(top_builddir)/plugins/sudoers/sudoers.la"
+ AX_APPEND_FLAG([-no-install], [SUDOERS_LDFLAGS])
+ SUDOERS_LT_STATIC="--tag=disable-shared"
+ LT_STATIC=""
+ ], [
+ SUDOERS_LT_STATIC="--tag=disable-static"
+ LT_STATIC="--tag=disable-static"
+ ])
+ ;;
+ shl_load)
+ AC_DEFINE(HAVE_SHL_LOAD)
+ AS_IF([test "$enable_static_sudoers" = "yes"], [
+ AC_DEFINE(STATIC_SUDOERS_PLUGIN)
+ SUDO_OBJS="${SUDO_OBJS} preload.o"
+ STATIC_SUDOERS="\$(top_builddir)/plugins/sudoers/sudoers.la"
+ AX_APPEND_FLAG([-no-install], [SUDOERS_LDFLAGS])
+ SUDOERS_LT_STATIC="--tag=disable-shared"
+ LT_STATIC=""
+ ], [
+ SUDOERS_LT_STATIC="--tag=disable-static"
+ LT_STATIC="--tag=disable-static"
+ ])
+ ;;
+ *)
+ AS_IF([test X"${ac_cv_func_dlopen}" = X"yes"], [
+ AC_MSG_ERROR([dlopen present but libtool doesn't appear to support your platform.])
+ ])
+ # Preload sudoers module symbols
+ AC_DEFINE(STATIC_SUDOERS_PLUGIN)
+ SUDO_OBJS="${SUDO_OBJS} preload.o"
+ STATIC_SUDOERS="\$(top_builddir)/plugins/sudoers/sudoers.la"
+ LT_STATIC=""
+ ;;
+esac
+
+#
+# The check_symbols test can only succeed with a dynamic sudoers plugin.
+#
+if test X"$STATIC_SUDOERS" = X""; then
+ SUDOERS_TEST_PROGS="${SUDOERS_TEST_PROGS}${SUDOERS_TEST_PROGS+ }check_symbols"
+fi
+
+#
+# We can only disable linking with the shared libsudo_util if
+# sudoers is linked statically too.
+#
+AS_IF([test "$enable_shared_libutil" = "no"], [
+ AS_IF([test X"$STATIC_SUDOERS" = X""], [
+ AC_MSG_ERROR([--disable-shared-libutil may only be specified with --enable-static-sudoers or when dynamic linking is disabled.])
+ ], [
+ # Do not install libsudo_util.
+ AX_APPEND_FLAG([-no-install], [LIBUTIL_LDFLAGS])
+ ])
+])
+
+# On HP-UX, you cannot dlopen() a shared object that uses pthreads unless
+# the main program is linked against -lpthread. We have no knowledge of
+# what libraries a plugin may depend on (e.g. HP-UX LDAP which uses pthreads)
+# so always link against -lpthread on HP-UX if it is available.
+# This check should go after all other libraries tests.
+case "$host_os" in
+ hpux*)
+ AC_CHECK_LIB([pthread], [main], [SUDO_LIBS="${SUDO_LIBS} -lpthread"])
+ AC_DEFINE(_REENTRANT)
+ ;;
+esac
+
+dnl
+dnl Check for log file, timestamp and iolog locations
+dnl
+AS_IF([test "$utmp_style" = "LEGACY"], [SUDO_PATH_UTMP])
+SUDO_LOGDIR
+SUDO_LOGFILE
+SUDO_RELAY_DIR
+SUDO_RUNDIR
+SUDO_VARDIR
+SUDO_IO_LOGDIR
+SUDO_TZDIR
+
+dnl
+dnl Turn warnings into errors.
+dnl All compiler/loader tests after this point will fail if
+dnl a warning is displayed (normally, warnings are not fatal).
+dnl
+AC_LANG_WERROR
+
+dnl
+dnl Don't use sys/sysctl.h if it is marked deprecated (Linux).
+dnl This test relies on AC_LANG_WERROR
+dnl
+AC_CHECK_HEADERS([sys/sysctl.h])
+
+dnl
+dnl If compiler supports the -static-libgcc flag use it unless we have
+dnl GNU ld (which can avoid linking in libgcc when it is not needed).
+dnl This test relies on AC_LANG_WERROR
+dnl
+AS_IF([test -n "$GCC" -a "$lt_cv_prog_gnu_ld" != "yes"], [
+ AX_CHECK_COMPILE_FLAG([-static-libgcc], [AX_APPEND_FLAG([-Wc,-static-libgcc], [LT_LDFLAGS])])
+])
+
+dnl
+dnl We want to use DT_RUNPATH in preference to DT_RPATH in ELF binaries.
+dnl Otherwise, LD_LIBRARY_PATH does not work when running the tests.
+dnl We don't do this on NetBSD where RPATH already supports LD_LIBRARY_PATH.
+dnl
+case "$host_os" in
+ netbsd*)
+ ;;
+ *)
+ AX_CHECK_LINK_FLAG([-Wl,--enable-new-dtags], [AX_APPEND_FLAG([-Wl,--enable-new-dtags], [LDFLAGS])])
+ ;;
+esac
+
+SUDO_CHECK_PIE_SUPPORT
+SUDO_SYMBOL_VISIBILITY
+SUDO_CHECK_SANITIZER
+SUDO_CHECK_HARDENING
+
+dnl
+dnl Use passwd auth module?
+dnl
+case "$with_passwd" in
+yes|maybe)
+ AUTH_OBJS="$AUTH_OBJS getspwuid.lo passwd.lo"
+ AS_IF([test "${ac_cv_search_crypt}" = "no"], [
+ AC_MSG_WARN([no crypt function found, assuming plaintext passwords])
+ ])
+ ;;
+*)
+ AC_DEFINE(WITHOUT_PASSWD)
+ AS_IF([test -z "$AUTH_OBJS"], [
+ AC_MSG_ERROR([no authentication methods defined.])
+ ])
+ ;;
+esac
+AUTH_OBJS=${AUTH_OBJS# }
+
+dnl
+dnl LIBS may contain duplicates from SUDO_LIBS, SUDOERS_LIBS, or NET_LIBS
+dnl
+AS_IF([test -n "$LIBS"], [
+ L="$LIBS"
+ LIBS=
+ for l in ${L}; do
+ dupe=0
+ for sl in ${SUDO_LIBS} ${SUDOERS_LIBS} ${NET_LIBS}; do
+ test $l = $sl && dupe=1
+ done
+ test $dupe = 0 && LIBS="${LIBS} $l"
+ done
+])
+
+dnl
+dnl OS-specific initialization
+dnl
+AC_DEFINE_UNQUOTED(os_init, $OS_INIT, [Define to an OS-specific initialization function or 'os_init_common'.])
+
+dnl
+dnl We add -Wall and -Werror after all tests so they don't cause failures
+dnl
+AS_IF([test -n "$GCC"], [
+ #
+ # The fallthrough attribute is supported by gcc 7.0 and clang 10.
+ # This test relies on AC_LANG_WERROR.
+ #
+ AC_CACHE_CHECK([whether $CC supports the fallthrough attribute],
+ [sudo_cv_var_fallthrough_attribute],
+ [AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+ int main(int argc, char *argv[])
+ {
+ int num = argc + 1;
+ switch (num) {
+ case 1:
+ num = 0;
+ __attribute__((__fallthrough__));
+ case 0:
+ num++;
+ }
+ return num;
+ }
+ ]])],
+ [
+ sudo_cv_var_fallthrough_attribute=yes
+ ],
+ [
+ sudo_cv_var_fallthrough_attribute=no]
+ )]
+ )
+ AS_IF([test X"$sudo_cv_var_fallthrough_attribute" = X"yes"], [
+ AC_DEFINE(HAVE_FALLTHROUGH_ATTRIBUTE)
+ ])
+ AS_IF([test X"$enable_warnings" = X"yes" -o X"$with_devel" = X"yes"], [
+ dnl
+ dnl Default warnings for development use.
+ dnl
+ AX_APPEND_FLAG([-Wall], [CFLAGS])
+ AX_APPEND_FLAG([-Wmissing-prototypes], [CFLAGS])
+ AX_APPEND_FLAG([-Wno-unknown-pragmas], [CFLAGS])
+ AX_APPEND_FLAG([-Wpointer-arith], [CFLAGS])
+ AX_APPEND_FLAG([-Wshadow], [CFLAGS])
+ AX_APPEND_FLAG([-Wsign-compare], [CFLAGS])
+ AX_APPEND_FLAG([-Wwrite-strings], [CFLAGS])
+ AX_CHECK_COMPILE_FLAG([-Wvla], [AX_APPEND_FLAG([-Wvla], [CFLAGS])])
+ AX_CHECK_COMPILE_FLAG([-Walloca], [AX_APPEND_FLAG([-Walloca], [CFLAGS])])
+ AX_CHECK_COMPILE_FLAG([-Wtrampolines], [AX_APPEND_FLAG([-Wtrampolines], [CFLAGS])])
+ AS_IF([test X"$sudo_cv_var_fallthrough_attribute" = X"yes"], [
+ AX_APPEND_FLAG([-Wimplicit-fallthrough], [CFLAGS])
+ ])
+ ])
+ AS_IF([test X"$enable_werror" = X"yes"], [
+ AX_APPEND_FLAG([-Werror], [CFLAGS])
+ ])
+ case "$host_os" in
+ # Avoid unwanted warnings on macOS
+ darwin*) AX_APPEND_FLAG([-Wno-deprecated-declarations], [CFLAGS]);;
+ esac
+])
+
+dnl
+dnl Skip regress tests and sudoers validation checks if cross compiling.
+dnl
+CROSS_COMPILING="$cross_compiling"
+
+dnl
+dnl Set exec_prefix
+dnl
+test "$exec_prefix" = "NONE" && exec_prefix='$(prefix)'
+
+dnl
+dnl Expand exec_prefix in variables used by the manual pages
+dnl
+oexec_prefix="$exec_prefix"
+if test "$exec_prefix" = '$(prefix)'; then
+ if test "$prefix" = "NONE"; then
+ exec_prefix="$ac_default_prefix"
+ else
+ exec_prefix="$prefix"
+ fi
+fi
+
+# Update exec_prefix in intercept_file
+_intercept_file=
+while test X"$intercept_file" != X"$_intercept_file"; do
+ _intercept_file="$intercept_file"
+ eval "intercept_file=\"$_intercept_file\""
+done
+
+# Update exec_prefix in noexec_file
+_noexec_file=
+while test X"$noexec_file" != X"$_noexec_file"; do
+ _noexec_file="$noexec_file"
+ eval "noexec_file=\"$_noexec_file\""
+done
+
+# Update exec_prefix in sesh_file
+_sesh_file=
+while test X"$sesh_file" != X"$_sesh_file"; do
+ _sesh_file="$sesh_file"
+ eval "sesh_file=\"$_sesh_file\""
+done
+
+# Update exec_prefix in plugindir
+_plugindir=
+while test X"$plugindir" != X"$_plugindir"; do
+ _plugindir="$plugindir"
+ eval "plugindir=\"$_plugindir\""
+done
+exec_prefix="$oexec_prefix"
+
+dnl
+dnl Defer setting _PATH_SUDO_NOEXEC, etc until after exec_prefix is set
+dnl
+AS_IF([test X"$enable_intercept" != X"no"], [
+ SUDO_OBJS="${SUDO_OBJS} intercept.pb-c.o"
+ PROGS="${PROGS} sudo_intercept.la"
+ INSTALL_INTERCEPT="install-intercept"
+
+ SUDO_DEFINE_UNQUOTED(_PATH_SUDO_INTERCEPT, "$intercept_file", [The fully qualified pathname of sudo_intercept.so])
+])
+AS_IF([test X"$with_noexec" != X"no"], [
+ PROGS="${PROGS} sudo_noexec.la"
+ INSTALL_NOEXEC="install-noexec"
+
+ SUDO_DEFINE_UNQUOTED(_PATH_SUDO_NOEXEC, "$noexec_file", [The fully qualified pathname of sudo_noexec.so])
+])
+AS_IF([test X"$with_selinux" != X"no"], [
+ SUDO_DEFINE_UNQUOTED(_PATH_SUDO_SESH, "$sesh_file")
+], [
+ SUDO_DEFINE_UNQUOTED(_PATH_SUDO_SESH, NULL)
+])
+AS_IF([test X"$enable_shared" != X"no"], [
+ SUDO_DEFINE_UNQUOTED(_PATH_SUDO_PLUGIN_DIR, "$plugindir/")
+ AC_DEFINE(ENABLE_SUDO_PLUGIN_API, 1, [Define to 1 to enable sudo's plugin interface.])
+], [
+ SUDO_DEFINE_UNQUOTED(_PATH_SUDO_PLUGIN_DIR, NULL)
+])
+
+dnl
+dnl Add -R options to LDFLAGS, etc.
+dnl
+if test X"$LDFLAGS_R" != X""; then
+ LDFLAGS="$LDFLAGS $LDFLAGS_R"
+fi
+if test X"$SUDOERS_LDFLAGS_R" != X""; then
+ SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS $SUDOERS_LDFLAGS_R"
+fi
+if test X"$ZLIB_R" != X""; then
+ ZLIB="$ZLIB_R $ZLIB"
+fi
+if test X"$LIBCRYPTO_R" != X""; then
+ LIBCRYPTO="$LIBCRYPTO_R $LIBCRYPTO"
+fi
+if test X"$LIBTLS_R" != X""; then
+ LIBTLS="$LIBTLS_R $LIBTLS"
+fi
+
+dnl
+dnl Trim leading spaces
+dnl
+CFLAGS=${CFLAGS# }
+CPPFLAGS=${CPPFLAGS# }
+LDFLAGS=${LDFLAGS# }
+SUDO_LDFLAGS=${SUDO_LDFLAGS# }
+SUDOERS_LDFLAGS=${SUDOERS_LDFLAGS# }
+LIBS=${LIBS# }
+SUDO_LIBS=${SUDO_LIBS# }
+SUDOERS_LIBS=${SUDOERS_LIBS# }
+
+dnl
+dnl Override default configure dirs for the Makefile
+dnl
+if test X"$prefix" = X"NONE"; then
+ test X"$mandir" = X'${datarootdir}/man' && mandir='$(prefix)/man'
+else
+ test X"$mandir" = X'${datarootdir}/man' && mandir='$(datarootdir)/man'
+fi
+test X"$bindir" = X'${exec_prefix}/bin' && bindir='$(exec_prefix)/bin'
+test X"$sbindir" = X'${exec_prefix}/sbin' && sbindir='$(exec_prefix)/sbin'
+test X"$libexecdir" = X'${exec_prefix}/libexec' && libexecdir='$(exec_prefix)/libexec'
+test X"$includedir" = X'${prefix}/include' && includedir='$(prefix)/include'
+test X"$datarootdir" = X'${prefix}/share' && datarootdir='$(prefix)/share'
+test X"$docdir" = X'${datarootdir}/doc/${PACKAGE_TARNAME}' && docdir='$(datarootdir)/doc/$(PACKAGE_TARNAME)'
+test X"$localedir" = X'${datarootdir}/locale' && localedir='$(datarootdir)/locale'
+test X"$localstatedir" = X'${prefix}/var' && localstatedir='$(prefix)/var'
+test X"$runstatedir" = X'${localstatedir}/run' && runstatedir='$(localstatedir)/run'
+test X"$adminconfdir" = X'${prefix}/etc' && adminconfdir='$(prefix)/etc'
+test X"$sysconfdir" = X'${prefix}/etc' && sysconfdir='/etc'
+
+# The configuration file search path is to check adminconfdir first and
+# fall back to sysconfdir. This can support systems with read-only
+# sysconfdir (/etc) that contains a set of default configuration files.
+SUDO_EXPAND_PATH([$sysconfdir], [_sysconfdir])
+SUDO_EXPAND_PATH([$adminconfdir], [_adminconfdir])
+AS_IF([test $enable_adminconf = yes], [
+ # Only use adminconfdir if different from sysconfdir
+ AS_IF([test X"$_sysconfdir" != X"$_adminconfdir"], [
+ cvtsudoers_conf='$(adminconfdir)/cvtsudoers.conf:'$cvtsudoers_conf
+ sudo_conf='$(adminconfdir)/sudo.conf:'$sudo_conf
+ sudo_logsrvd_conf='$(adminconfdir)/sudo_logsrvd.conf:'$sudo_logsrvd_conf
+ sudoers_path='$(adminconfdir)/sudoers:'$sudoers_path
+ ])
+])
+
+# Expand config file paths for use in pathnames.h (after config dir override)
+SUDO_DEFINE_PATH([$cvtsudoers_conf], [_PATH_CVTSUDOERS_CONF])
+SUDO_DEFINE_PATH([$sudo_conf], [_PATH_SUDO_CONF])
+SUDO_DEFINE_PATH([$sudo_logsrvd_conf], [_PATH_SUDO_LOGSRVD_CONF])
+SUDO_DEFINE_PATH([$sudoers_path], [_PATH_SUDOERS])
+
+# Convert exampledir to something that can be used in the man pages
+SUDO_EXPAND_PATH([$exampledir], [EXAMPLES])
+
+dnl
+dnl Substitute into the Makefile and man pages
+dnl
+AS_IF([test X"$INIT_SCRIPT" != X""], [
+ AC_CONFIG_FILES([etc/init.d/$INIT_SCRIPT])
+], [test X"$TMPFILES_D" != X""], [
+ AC_CONFIG_FILES([etc/init.d/sudo.conf])
+])
+
+AC_CONFIG_FILES([Makefile docs/Makefile examples/Makefile examples/sudoers examples/sudo.conf examples/sudo_logsrvd.conf examples/syslog.conf include/Makefile lib/eventlog/Makefile lib/fuzzstub/Makefile lib/iolog/Makefile lib/logsrv/Makefile lib/protobuf-c/Makefile lib/ssl_compat/Makefile lib/util/Makefile lib/util/regress/harness lib/util/util.exp logsrvd/Makefile src/intercept.exp src/sudo_usage.h src/Makefile plugins/audit_json/Makefile plugins/sample/Makefile plugins/group_file/Makefile plugins/sample_approval/Makefile plugins/system_group/Makefile plugins/sudoers/Makefile plugins/sudoers/regress/harness plugins/sudoers/sudoers])
+AC_CONFIG_COMMANDS([harness], [chmod +x lib/util/regress/harness plugins/sudoers/regress/harness])
+
+AC_OUTPUT
+
+dnl
+dnl Summarize configuration
+dnl
+if test ${LIBTLS+y}; then
+ have_tls=yes
+fi
+echo "" >&AS_MESSAGE_FD
+echo "Configured Sudo version $PACKAGE_VERSION" >&AS_MESSAGE_FD
+echo " Compiler settings:" >&AS_MESSAGE_FD
+echo " compiler : $CC" >&AS_MESSAGE_FD
+echo " compiler options : $CFLAGS" >&AS_MESSAGE_FD
+echo " preprocessor options : $CPPFLAGS" >&AS_MESSAGE_FD
+echo " front-end libraries : $SUDO_LIBS" >&AS_MESSAGE_FD
+echo " front-end linker options : $SUDO_LDFLAGS" >&AS_MESSAGE_FD
+echo " network libraries : $NET_LIBS" >&AS_MESSAGE_FD
+echo " Crypto library : $LIBCRYPTO" >&AS_MESSAGE_FD
+echo " TLS libraries : $LIBTLS" >&AS_MESSAGE_FD
+echo " extra libraries : $LIBS" >&AS_MESSAGE_FD
+echo " extra linker options : $LDFLAGS" >&AS_MESSAGE_FD
+echo " sudoers libraries : $SUDOERS_LIBS" >&AS_MESSAGE_FD
+echo " sudoers linker options : $SUDOERS_LDFLAGS" >&AS_MESSAGE_FD
+if test "${enable_sanitizer-no}" != "no"; then
+ echo " sanitizer options : ${enable_sanitizer}" >&AS_MESSAGE_FD
+fi
+if test X"$FUZZ_LD" != X"\$(CC)"; then
+ echo " fuzzing linker : ${FUZZ_LD}" >&AS_MESSAGE_FD
+fi
+if test X"$FUZZ_ENGINE" != X"\$(top_builddir)/lib/fuzzstub/libsudo_fuzzstub.la"; then
+ echo " fuzzing engine : ${FUZZ_ENGINE}" >&AS_MESSAGE_FD
+fi
+echo " Plugin options:" >&AS_MESSAGE_FD
+echo " plugin support : ${SHLIB_ENABLE}" >&AS_MESSAGE_FD
+echo " Sudoers plugin static : ${enable_static_sudoers-no}" >&AS_MESSAGE_FD
+echo " Python plugin : ${enable_python-no}" >&AS_MESSAGE_FD
+if test "${enable_python-no}" != "no"; then
+ echo " Python CFLAGS : ${PYTHON_INCLUDE}" >&AS_MESSAGE_FD
+ echo " Python LDFLAGS : ${PYTHON_LIBS}" >&AS_MESSAGE_FD
+fi
+echo " Optional features:" >&AS_MESSAGE_FD
+echo " log client : ${enable_log_client-yes}" >&AS_MESSAGE_FD
+echo " log server : ${enable_log_server-yes}" >&AS_MESSAGE_FD
+echo " log client/server TLS : ${have_tls-no}" >&AS_MESSAGE_FD
+case "$host_os" in
+ linux*) echo " SELinux RBAC : ${with_selinux-yes}" >&AS_MESSAGE_FD;;
+esac
+echo " Optional sudoers back-ends:" >&AS_MESSAGE_FD
+echo " LDAP : ${with_ldap-no}" >&AS_MESSAGE_FD
+if test "${with_ldap-no}" != "no"; then
+ echo " ldap configuration : ${ldap_conf}" >&AS_MESSAGE_FD
+ echo " ldap secret : ${ldap_secret}" >&AS_MESSAGE_FD
+ echo " SASL authentication : ${enable_sasl-no}" >&AS_MESSAGE_FD
+fi
+echo " SSSD : ${with_sssd-no}" >&AS_MESSAGE_FD
+if test "${with_sssd-no}" != "no"; then
+ echo " SSSD config path : ${sssd_conf}" >&AS_MESSAGE_FD
+ if test "${sssd_lib}" = \""LIBDIR\""; then
+ echo " SSSD lib dir : ${libdir}" >&AS_MESSAGE_FD
+ else
+ echo " SSSD lib dir : ${sssd_lib}" >&AS_MESSAGE_FD
+ fi
+fi
+echo " Authentication options:" >&AS_MESSAGE_FD
+echo " require authentication : ${enable_authentication-yes}" >&AS_MESSAGE_FD
+auth_methods=`echo "$AUTH_OBJS" | sed -e 's/\.lo//g' -e 's/getspwuid *//'`
+echo " authentication methods : ${auth_methods}" >&AS_MESSAGE_FD
+if test "${with_pam-no}" = "yes"; then
+ echo " pam session support : ${pam_session}" >&AS_MESSAGE_FD
+ echo " pam login service : ${pam_login_service}" >&AS_MESSAGE_FD
+fi
+if test "${with_kerb5-no}" != "no"; then
+ echo " kerb5 instance string : ${with_kerb5-none}" >&AS_MESSAGE_FD
+fi
+if test "${with_opie-no}-${with_skey-no}" != "no-no"; then
+ echo " long OTP prompt : ${long_otp_prompt-no}" >&AS_MESSAGE_FD
+fi
+echo " group exempt from passwords : ${with_exempt-none}" >&AS_MESSAGE_FD
+echo " password prompt : ${passprompt}" >&AS_MESSAGE_FD
+echo " password prompt timeout : ${password_timeout} minutes" >&AS_MESSAGE_FD
+echo " password tries : ${passwd_tries}" >&AS_MESSAGE_FD
+echo " bad password message : ${badpass_message}" >&AS_MESSAGE_FD
+if test "$insults" = "on"; then
+ i=""
+ test "$enable_offensive_insults" = "yes" && i="offensive ${i}"
+ test "$with_python_insults" = "yes" && i="python ${i}"
+ test "$with_goons_insults" = "yes" && i="goons ${i}"
+ test "$with_hal_insults" = "yes" && i="hal ${i}"
+ test "$with_csops_insults" = "yes" && i="csops ${i}"
+ test "$with_classic_insults" = "yes" && i="classic ${i}"
+else
+ i=no
+fi
+echo " insults : $i" >&AS_MESSAGE_FD
+echo " display lecture : ${lecture}" >&AS_MESSAGE_FD
+echo " timestamp (credential) type : ${timestamp_type}" >&AS_MESSAGE_FD
+echo " timestamp (credential) timeout: ${timeout} minutes" >&AS_MESSAGE_FD
+echo " Logging options:" >&AS_MESSAGE_FD
+echo " logging default : ${with_logging}" >&AS_MESSAGE_FD
+echo " syslog facility : ${logfac}" >&AS_MESSAGE_FD
+echo " syslog priority allowed : ${goodpri}" >&AS_MESSAGE_FD
+echo " syslog priority denied : ${badpri}" >&AS_MESSAGE_FD
+echo " log file path : ${logpath}" >&AS_MESSAGE_FD
+echo " log file includes hostname : ${enable_log_host-no}" >&AS_MESSAGE_FD
+echo " log file line length : ${loglen}" >&AS_MESSAGE_FD
+echo " compress I/O logs : ${enable_zlib}" >&AS_MESSAGE_FD
+case "$host_os" in
+ linux*) echo " Linux audit : ${with_linux_audit-no}" >&AS_MESSAGE_FD;;
+ solaris2.11*) echo " Solaris audit : ${with_solaris_audit-no}" >&AS_MESSAGE_FD;;
+ *) echo " BSM audit : ${with_bsm_audit-no}" >&AS_MESSAGE_FD;;
+esac
+echo " run mailer as root : ${enable_root_mailer-yes}" >&AS_MESSAGE_FD
+echo " warning/error mail recipient : ${mailto}" >&AS_MESSAGE_FD
+echo " warning/error mail subject : ${mailsub}" >&AS_MESSAGE_FD
+echo " mail if user not in sudoers : ${mail_no_user}" >&AS_MESSAGE_FD
+echo " mail if user not on host : ${mail_no_host}" >&AS_MESSAGE_FD
+echo " mail if command not allowed : ${mail_no_perms}" >&AS_MESSAGE_FD
+echo " Pathnames:" >&AS_MESSAGE_FD
+echo " prefix : $prefix" >&AS_MESSAGE_FD
+echo " sysconfdir : $_sysconfdir" >&AS_MESSAGE_FD
+if test "${enable_adminconf-no}" != "no"; then
+ echo " adminconfdir : $_adminconfdir" >&AS_MESSAGE_FD
+fi
+echo " log directory : ${log_dir}" >&AS_MESSAGE_FD
+echo " run directory : ${rundir}" >&AS_MESSAGE_FD
+echo " var directory : ${vardir}" >&AS_MESSAGE_FD
+echo " I/O log directory : ${iolog_dir}" >&AS_MESSAGE_FD
+echo " sudo_logsrvd relay directory : ${relay_dir}" >&AS_MESSAGE_FD
+if test X"$with_exampledir" != X""; then
+ echo " exampledir : $exampledir" >&AS_MESSAGE_FD
+fi
+echo " plugin directory : ${plugindir}" >&AS_MESSAGE_FD
+echo " sudoers plugin : ${sudoers_plugin}" >&AS_MESSAGE_FD
+if test "${enable_python-no}" != "no"; then
+ echo " python plugin : ${python_plugin}" >&AS_MESSAGE_FD
+fi
+echo " sudoers file : ${sudoers_path}" >&AS_MESSAGE_FD
+echo " cvtsudoers.conf file : ${cvtsudoers_conf}" >&AS_MESSAGE_FD
+echo " sudo.conf file : ${sudo_conf}" >&AS_MESSAGE_FD
+echo " sudo_logsrvd.conf file : ${sudo_logsrvd_conf}" >&AS_MESSAGE_FD
+echo " path to sendmail : ${with_sendmail}" >&AS_MESSAGE_FD
+echo " time zone directory : ${tzdir}" >&AS_MESSAGE_FD
+if test -n "$TMPFILES_D"; then
+ echo " systemd tempfiles dir : ${TMPFILES_D}" >&AS_MESSAGE_FD
+fi
+if test ${with_netsvc-"no"} != "no"; then
+ echo " netsvc file : ${netsvc_conf}" >&AS_MESSAGE_FD
+elif test ${with_nsswitch-"yes"} != "no"; then
+ echo " nsswitch file : ${nsswitch_conf}" >&AS_MESSAGE_FD
+fi
+echo " intercept file : ${intercept_file}" >&AS_MESSAGE_FD
+echo " noexec file : ${noexec_file}" >&AS_MESSAGE_FD
+echo " secure path : ${with_secure_path-no}" >&AS_MESSAGE_FD
+echo " askpass helper file : ${with_askpass-no}" >&AS_MESSAGE_FD
+echo " device search path : ${devsearch}" >&AS_MESSAGE_FD
+echo " Other options:" >&AS_MESSAGE_FD
+if test "${with_devel-no}" != "no"; then
+ echo " development build : ${with_devel}" >&AS_MESSAGE_FD
+fi
+case "$host_os" in
+ solaris2*) echo " Solaris project support : ${with_project-no}" >&AS_MESSAGE_FD;;
+esac
+if test "${with_logincap+set}" = "set"; then
+ echo " /etc/login.conf support : ${with_logincap}" >&AS_MESSAGE_FD
+fi
+echo " fully-qualified domain names : ${fqdn}" >&AS_MESSAGE_FD
+echo " default umask : ${sudo_umask}" >&AS_MESSAGE_FD
+echo " umask override : ${umask_override}" >&AS_MESSAGE_FD
+echo " default runas user : ${runas_default}" >&AS_MESSAGE_FD
+echo " probe network interfaces : ${with_interfaces-yes}" >&AS_MESSAGE_FD
+echo " allow root to run sudo : ${root_sudo}" >&AS_MESSAGE_FD
+echo " reset environment for commands: ${env_reset}" >&AS_MESSAGE_FD
+echo " run shell if no args : ${enable_noargs_shell-no}" >&AS_MESSAGE_FD
+echo " ignore '.' or '' in \$PATH : ${ignore_dot}" >&AS_MESSAGE_FD
+echo " disable path info : ${enable_path_info-no}" >&AS_MESSAGE_FD
+echo " sudoers file mode : ${SUDOERS_MODE}" >&AS_MESSAGE_FD
+echo " sudoers file owner : ${SUDOERS_UID}:${SUDOERS_GID}" >&AS_MESSAGE_FD
+echo " default visudo editor : ${editor}" >&AS_MESSAGE_FD
+echo " visudo supports \$EDITOR : ${env_editor}" >&AS_MESSAGE_FD
+if test "${enable_env_debug+set}" = "set"; then
+ echo " environment debugging : ${enable_env_debug-no}" >&AS_MESSAGE_FD
+fi
+echo "" >&AS_MESSAGE_FD
+
+dnl
+dnl Display any warnings/info the user needs to know about at the end.
+dnl
+AS_IF([test "$openssl_missing" = "yes"], [
+ AC_MSG_WARN([OpenSSL dev libraries not found, Sudo logsrv connections will not be encrypted.])
+])
+AS_IF([test "$with_pam" = "yes"], [
+ case $host_os in
+ hpux*)
+ AS_IF([test -f /usr/lib/security/libpam_hpsec.so.1], [
+ AC_MSG_NOTICE([you may wish to add the following line to /etc/pam.conf])
+ AC_MSG_NOTICE([sudo session required libpam_hpsec.so.1 bypass_umask bypass_last_login])
+ ])
+ ;;
+ linux*)
+ AC_MSG_NOTICE([you will need to customize examples/pam.conf and install it as /etc/pam.d/sudo])
+ ;;
+ esac
+])
+dnl
+dnl Warn user if they may need to clear rundir manually.
+dnl
+case "$rundir" in
+ /run/*|/var/run/*)
+ clear_rundir=0
+ ;;
+ *)
+ clear_rundir=1
+ ;;
+esac
+AS_IF([test $clear_rundir -eq 1], [
+ AC_MSG_NOTICE([warning: the $rundir/ts directory must be cleared at boot time.])
+ AC_MSG_NOTICE([ You may need to create a startup item to do this.])
+])
+
+dnl
+dnl Autoheader templates
+dnl
+AH_TEMPLATE(CLASSIC_INSULTS, [Define to 1 if you want the insults from the "classic" version sudo.])
+AH_TEMPLATE(CSOPS_INSULTS, [Define to 1 if you want insults culled from the twisted minds of CSOps.])
+AH_TEMPLATE(DONT_LEAK_PATH_INFO, [Define to 1 if you want sudo to display "command not allowed" instead of "command not found" when a command cannot be found.])
+AH_TEMPLATE(ENV_DEBUG, [Define to 1 to enable environment function debugging.])
+AH_TEMPLATE(ENV_EDITOR, [Define to 1 if you want visudo to honor the EDITOR and VISUAL env variables.])
+AH_TEMPLATE(FQDN, [Define to 1 if you want to require fully qualified hosts in sudoers.])
+AH_TEMPLATE(ENV_RESET, [Define to 1 to enable environment resetting by default.])
+AH_TEMPLATE(PYTHON_INSULTS, [Define to 1 if you want insults from "Monty Python's Flying Circus".])
+AH_TEMPLATE(GOONS_INSULTS, [Define to 1 if you want insults from the "Goon Show".])
+AH_TEMPLATE(HAL_INSULTS, [Define to 1 if you want 2001-like insults.])
+AH_TEMPLATE(HAVE_AFS, [Define to 1 if you use AFS.])
+AH_TEMPLATE(HAVE_AIXAUTH, [Define to 1 if you use AIX general authentication.])
+AH_TEMPLATE(HAVE_BSD_AUTH_H, [Define to 1 if you use BSD authentication.])
+AH_TEMPLATE(HAVE_BSM_AUDIT, [Define to 1 to enable BSM audit support.])
+AH_TEMPLATE(HAVE_CRYPT, [Define to 1 if you have the 'crypt' function.])
+AH_TEMPLATE(HAVE_DCE, [Define to 1 if you use OSF DCE.])
+AH_TEMPLATE(HAVE_DD_FD, [Define to 1 if your 'DIR' contains dd_fd.])
+AH_TEMPLATE(HAVE_DIRFD, [Define to 1 if you have the 'dirfd' function or macro.])
+AH_TEMPLATE(HAVE_DISPCRYPT, [Define to 1 if you have the 'dispcrypt' function.])
+AH_TEMPLATE(HAVE_DLOPEN, [Define to 1 if you have the 'dlopen' function.])
+AH_TEMPLATE(HAVE_FCNTL_CLOSEM, [Define to 1 if your system has the F_CLOSEM fcntl.])
+AH_TEMPLATE(HAVE_FNMATCH, [Define to 1 if you have the 'fnmatch' function.])
+AH_TEMPLATE(HAVE_FWTK, [Define to 1 if you use the FWTK authsrv daemon.])
+AH_TEMPLATE(HAVE_GETPRPWNAM, [Define to 1 if you have the 'getprpwnam' function. (SecureWare-style shadow passwords).])
+AH_TEMPLATE(HAVE_GETPWNAM_SHADOW, [Define to 1 if you have the 'getpwnam_shadow' function.])
+AH_TEMPLATE(HAVE_GETSPNAM, [Define to 1 if you have the 'getspnam' function (SVR4-style shadow passwords).])
+AH_TEMPLATE(HAVE_GSS_KRB5_CCACHE_NAME, [Define to 1 if you have the 'gss_krb5_ccache_name' function.])
+AH_TEMPLATE(HAVE_HEIMDAL, [Define to 1 if your Kerberos is Heimdal.])
+AH_TEMPLATE(HAVE_INET_NTOP, [Define to 1 if you have the 'inet_ntop' function.])
+AH_TEMPLATE(HAVE_INET_PTON, [Define to 1 if you have the 'inet_pton' function.])
+AH_TEMPLATE(HAVE_ISCOMSEC, [Define to 1 if you have the 'iscomsec' function. (HP-UX >= 10.x check for shadow enabled).])
+AH_TEMPLATE(HAVE_KERB5, [Define to 1 if you use Kerberos V.])
+AH_TEMPLATE(HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC, [Define to 1 if you have the 'krb5_get_init_creds_opt_alloc' function.])
+AH_TEMPLATE(HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_TWO_ARGS, [Define to 1 if your 'krb5_get_init_creds_opt_free' function takes two arguments.])
+AH_TEMPLATE(HAVE_KRB5_INIT_SECURE_CONTEXT, [Define to 1 if you have the 'krb5_init_secure_context' function.])
+AH_TEMPLATE(HAVE_KRB5_VERIFY_USER, [Define to 1 if you have the 'krb5_verify_user' function.])
+AH_TEMPLATE(HAVE_LBER_H, [Define to 1 if your LDAP needs <lber.h>. (OpenLDAP does not).])
+AH_TEMPLATE(HAVE_LDAP, [Define to 1 if you use LDAP for sudoers.])
+AH_TEMPLATE(HAVE_LIBINTL_H, [Define to 1 if you have the <libintl.h> header file.])
+AH_TEMPLATE(HAVE_LINUX_AUDIT, [Define to 1 to enable Linux audit support.])
+AH_TEMPLATE(HAVE_SSSD, [Define to 1 to enable SSSD support.])
+AH_TEMPLATE(HAVE_OPIE, [Define to 1 if you use NRL OPIE.])
+AH_TEMPLATE(HAVE_OPTRESET, [Define to 1 if you have the 'optreset' symbol.])
+AH_TEMPLATE(HAVE_PAM, [Define to 1 if you use PAM authentication.])
+AH_TEMPLATE(HAVE_PAM_LOGIN, [Define to 1 if you use a specific PAM session for sudo -i.])
+AH_TEMPLATE(HAVE_PROJECT_H, [Define to 1 if you have the <project.h> header file.])
+AH_TEMPLATE(HAVE_SECURID, [Define to 1 if you use SecurID for authentication.])
+AH_TEMPLATE(HAVE_SELINUX, [Define to 1 to enable SELinux RBAC support.])
+AH_TEMPLATE(HAVE_SETKEYCREATECON, [Define to 1 if you have the 'setkeycreatecon' function.])
+AH_TEMPLATE(HAVE_APPARMOR, [Define to 1 to enable AppArmor support.])
+AH_TEMPLATE(HAVE_SHL_LOAD, [Define to 1 if you have the 'shl_load' function.])
+AH_TEMPLATE(HAVE_SKEY, [Define to 1 if you use S/Key.])
+AH_TEMPLATE(HAVE_SKEYACCESS, [Define to 1 if your S/Key library has skeyaccess().])
+AH_TEMPLATE(HAVE_RFC1938_SKEYCHALLENGE, [Define to 1 if the skeychallenge() function is RFC1938-compliant and takes 4 arguments.])
+AH_TEMPLATE(HAVE_SOLARIS_AUDIT, [Define to 1 to enable Solaris audit support.])
+AH_TEMPLATE(HAVE_ST__TIM, [Define to 1 if your struct stat uses an st__tim union.])
+AH_TEMPLATE(HAVE_ST_MTIM, [Define to 1 if your struct stat has an st_mtim member.])
+AH_TEMPLATE(HAVE_ST_MTIMESPEC, [Define to 1 if your struct stat has an st_mtimespec member.])
+AH_TEMPLATE(HAVE_ST_NMTIME, [Define to 1 if your struct stat has an st_nmtime member.])
+AH_TEMPLATE(HAVE___PROGNAME, [Define to 1 if your crt0.o defines the __progname symbol for you.])
+AH_TEMPLATE(HOST_IN_LOG, [Define to 1 if you want the hostname to be entered into the log file.])
+AH_TEMPLATE(IGNORE_DOT_PATH, [Define to 1 if you want to ignore '.' and empty PATH elements.])
+AH_TEMPLATE(LOGGING, [Define to SLOG_SYSLOG, SLOG_FILE, or SLOG_BOTH.])
+AH_TEMPLATE(LONG_OTP_PROMPT, [Define to 1 if you want a two line OTP (S/Key or OPIE) prompt.])
+AH_TEMPLATE(NO_AUTHENTICATION, [Define to 1 if you don't want sudo to prompt for a password by default.])
+AH_TEMPLATE(NO_LEAKS, [Define to 1 if you want sudo to free up memory before exiting.])
+AH_TEMPLATE(NO_LECTURE, [Define to 1 if you don't want users to get the lecture the first time they use sudo.])
+AH_TEMPLATE(NO_PAM_SESSION, [Define to 1 if you don't want to use sudo's PAM session support.])
+AH_TEMPLATE(NO_ROOT_MAILER, [Define to avoid running the mailer as root.])
+AH_TEMPLATE(NO_ROOT_SUDO, [Define to 1 if root should not be allowed to use sudo.])
+AH_TEMPLATE(TIMESTAMP_TYPE, [Define to global, ppid or tty to set the default timestamp record type.])
+AH_TEMPLATE(OFFENSIVE_INSULTS, [Define to 1 to include offensive insults from the classic version of sudo.])
+AH_TEMPLATE(SECURE_PATH, [A colon-separated list of directories to override the user's PATH with.])
+AH_TEMPLATE(SEND_MAIL_WHEN_NOT_OK, [Define to 1 to send mail when the user is not allowed to run a command.])
+AH_TEMPLATE(SEND_MAIL_WHEN_NO_HOST, [Define to 1 to send mail when the user is not allowed to run sudo on this host.])
+AH_TEMPLATE(SEND_MAIL_WHEN_NO_USER, [Define to 1 to send mail when the user is not in the sudoers file.])
+AH_TEMPLATE(SHELL_IF_NO_ARGS, [Define to 1 if you want sudo to start a shell if given no arguments.])
+AH_TEMPLATE(SHELL_SETS_HOME, [Define to 1 if you want sudo to set $HOME in shell mode.])
+AH_TEMPLATE(STATIC_SUDOERS_PLUGIN, [Define to 1 to compile the sudoers plugin statically into the sudo binary.])
+AH_TEMPLATE(STUB_LOAD_INTERFACES, [Define to 1 if the code in interfaces.c does not compile for you.])
+AH_TEMPLATE(UMASK_OVERRIDE, [Define to 1 to use the umask specified in sudoers even when it is less restrictive than the invoking user's.])
+AH_TEMPLATE(USE_INSULTS, [Define to 1 if you want to insult the user for entering an incorrect password.])
+AH_TEMPLATE(USE_STOW, [Define to 1 if you use GNU stow packaging.])
+AH_TEMPLATE(WITHOUT_PASSWD, [Define to avoid using the passwd/shadow file for authentication.])
+AH_TEMPLATE(HAVE___FUNC__, [Define to 1 if the compiler supports the C99 __func__ variable.])
+AH_TEMPLATE(HAVE___INTERPOSE, [Define to 1 if you have dyld with __interpose attribute support.])
+AH_TEMPLATE(SUDO_KRB5_INSTANCE, [An instance string to append to the username (separated by a slash) for Kerberos V authentication.])
+AH_TEMPLATE(RTLD_PRELOAD_VAR, [The environment variable that controls preloading of dynamic objects.])
+AH_TEMPLATE(RTLD_PRELOAD_VAR_32, [The environment variable that controls preloading of 32-bit dynamic objects.])
+AH_TEMPLATE(RTLD_PRELOAD_VAR_64, [The environment variable that controls preloading of 64-bit dynamic objects.])
+AH_TEMPLATE(RTLD_PRELOAD_ENABLE_VAR, [An extra environment variable that is required to enable preloading (if any).])
+AH_TEMPLATE(RTLD_PRELOAD_DELIM, [The delimiter to use when defining multiple preloaded objects.])
+AH_TEMPLATE(RTLD_PRELOAD_DEFAULT, [The default value of preloaded objects (if any).])
+AH_TEMPLATE(HAVE_DSO_VISIBILITY, [Define to 1 if the compiler supports the __visibility__ attribute.])
+AH_TEMPLATE(HAVE_SYS_SIGABBREV, [Define to 1 if your libc has the 'sys_sigabbrev' symbol.])
+AH_TEMPLATE(HAVE_NSS_SEARCH, [Define to 1 if you have the 'nss_search' function.])
+AH_TEMPLATE(HAVE__NSS_INITF_GROUP, [Define to 1 if you have the '_nss_initf_group' function.])
+AH_TEMPLATE(HAVE___NSS_INITF_GROUP, [Define to 1 if you have the '__nss_initf_group' function.])
+AH_TEMPLATE(HAVE__NSS_XBYY_BUF_ALLOC, [Define to 1 if you have the '_nss_XbyY_buf_alloc' function.])
+AH_TEMPLATE(HAVE___NSS_XBYY_BUF_ALLOC, [Define to 1 if you have the '__nss_XbyY_buf_alloc' function.])
+AH_TEMPLATE(NEED_RESOLV_H, [Define to 1 if resolv.h must be included to get the 'inet_ntop' or 'inet_pton' function prototypes.])
+AH_TEMPLATE(HAVE_STRNLEN, [Define to 1 if you have the 'strnlen' function.])
+AH_TEMPLATE(PAM_SUN_CODEBASE, [Define to 1 if your system uses a Solaris-derived PAM and not Linux-PAM or OpenPAM.])
+AH_TEMPLATE(HAVE_KINFO_PROC_44BSD, [Define to 1 if your system has a 4.4BSD-style kinfo_proc struct.])
+AH_TEMPLATE(HAVE_KINFO_PROC_FREEBSD, [Define to 1 if your system has a FreeBSD-style kinfo_proc struct.])
+AH_TEMPLATE(HAVE_KINFO_PROC_DFLY, [Define to 1 if your system has a Dragonfly-style kinfo_proc struct.])
+AH_TEMPLATE(HAVE_KINFO_PROC2_NETBSD, [Define to 1 if your system has a NetBSD-style kinfo_proc2 struct.])
+AH_TEMPLATE(HAVE_KINFO_PROC_OPENBSD, [Define to 1 if your system has an OpenBSD-style kinfo_proc struct.])
+AH_TEMPLATE(HAVE_OPENSSL, [Define to 1 if you are using OpenSSL's TLS and sha2 functions.])
+AH_TEMPLATE(HAVE_WOLFSSL, [Define to 1 if you are using wolfSSL's TLS and sha2 functions.])
+AH_TEMPLATE(HAVE_GCRYPT, [Define to 1 if you are using gcrypt's sha2 functions.])
+AH_TEMPLATE(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION, [Define to 1 if you have the 'SSL_CTX_set_min_proto_version' function or macro.])
+AH_TEMPLATE(HAVE_SSL_CTX_SET_CIPHERSUITES, [Define to 1 if you have the 'SSL_CTX_set_ciphersuites' function or macro.])
+AH_TEMPLATE(SUDOERS_LOG_CLIENT, [Define to 1 to compile support for sudo_logsrvd in the sudoers plugin.])
+AH_TEMPLATE(HAVE_FALLTHROUGH_ATTRIBUTE, [Define to 1 if the compiler supports the fallthrough attribute.])
+AH_TEMPLATE(HAVE_VA_COPY, [Define to 1 if you have the 'va_copy' function.])
+AH_TEMPLATE(HAVE___VA_COPY, [Define to 1 if you have the '__va_copy' function.])
+
+dnl
+dnl Bits to copy verbatim into config.h.in
+dnl
+AH_TOP([#ifndef SUDO_CONFIG_H
+#define SUDO_CONFIG_H
+
+/* Configure script arguments used to build sudo. */
+#undef CONFIGURE_ARGS])
+
+AH_BOTTOM([#ifndef HAVE_SIG_ATOMIC_T
+typedef int sig_atomic_t;
+#endif
+
+#ifndef HAVE_SOCKLEN_T
+typedef unsigned int socklen_t;
+#endif
+
+#ifndef __GNUC_PREREQ__
+# ifdef __GNUC__
+# define __GNUC_PREREQ__(ma, mi) \
+ ((__GNUC__ > (ma)) || (__GNUC__ == (ma) && __GNUC_MINOR__ >= (mi)))
+# else
+# define __GNUC_PREREQ__(ma, mi) 0
+# endif
+#endif
+
+/* Define away __attribute__ for non-gcc or old gcc. */
+#if !defined(__attribute__) && !__GNUC_PREREQ__(2, 5)
+# define __attribute__(x)
+#endif
+
+/* For functions that call exit() directly. */
+#ifdef __has_c_attribute
+# if __has_c_attribute(__noreturn__)
+# define sudo_noreturn [[__noreturn__]]
+# endif
+#endif
+#ifndef sudo_noreturn
+# if __GNUC_PREREQ__(2, 5)
+# define sudo_noreturn __attribute__((__noreturn__))
+# else
+# define sudo_noreturn
+# endif
+#endif
+
+/* For malloc-like functions that return uninitialized or zeroed memory. */
+#if __GNUC_PREREQ__(2, 96)
+# define sudo_malloclike __attribute__((__malloc__))
+#else
+# define sudo_malloclike
+#endif
+
+/* Compile-time checking for function arguments that must not be NULL. */
+#if __GNUC_PREREQ__(3, 3)
+# define sudo_attr_nonnull(_a) __attribute__((__nonnull__ (_a)))
+#else
+# define sudo_attr_nonnull(_a)
+#endif
+
+/* For catching format string mismatches. */
+#if __GNUC_PREREQ__(2, 7)
+# define sudo_printflike(_f, _v) __attribute__((__format__ (__printf__, _f, _v))) sudo_attr_nonnull(_f)
+# define sudo_printf0like(_f, _v) __attribute__((__format__ (__printf__, _f, _v)))
+# define sudo_attr_fmt_arg(_f) __attribute__((__format_arg__ (_f)))
+#else
+# define sudo_printflike(_f, _v)
+# define sudo_printf0like(_f, _v)
+# define sudo_attr_fmt_arg(_f)
+#endif
+
+/* C23 defines a fallthrough attribute, gcc 7.0 and clang 10 have their own. */
+#ifdef __has_c_attribute
+# if __has_c_attribute(__fallthrough__)
+# define FALLTHROUGH [[__fallthrough__]]
+# endif
+#endif
+#ifndef FALLTHROUGH
+# if defined(HAVE_FALLTHROUGH_ATTRIBUTE)
+# define FALLTHROUGH __attribute__((__fallthrough__))
+# else
+# define FALLTHROUGH do { } while (0)
+# endif
+#endif
+
+/* Symbol visibility controls. */
+#ifdef HAVE_DSO_VISIBILITY
+# if defined(__GNUC__)
+# define sudo_dso_public __attribute__((__visibility__("default")))
+# elif defined(__SUNPRO_C)
+# define sudo_dso_public __global
+# else
+# define sudo_dso_public __declspec(dllexport)
+# endif
+#else
+# define sudo_dso_public
+#endif
+
+/* BSD compatibility on some SVR4 systems. */
+#ifdef __svr4__
+# define BSD_COMP
+#endif
+
+/* Enable BSD extensions on systems that have them. */
+#ifndef _BSD_SOURCE
+# undef _BSD_SOURCE
+#endif
+
+/* Enable OpenBSD extensions on NetBSD. */
+#ifndef _OPENBSD_SOURCE
+# undef _OPENBSD_SOURCE
+#endif
+
+/* Enable BSD types on IRIX. */
+#ifndef _BSD_TYPES
+# undef _BSD_TYPES
+#endif
+
+/* Enable Linux-compatible extensions on AIX. */
+#ifndef _LINUX_SOURCE_COMPAT
+# undef _LINUX_SOURCE_COMPAT
+#endif
+
+/* Enable unlimited getgroups(2) support on macOS. */
+#ifndef _DARWIN_UNLIMITED_GETGROUPS
+# undef _DARWIN_UNLIMITED_GETGROUPS
+#endif
+
+/* Enable prototypes in GCC fixed includes on older systems. */
+#ifndef __USE_FIXED_PROTOTYPES__
+# undef __USE_FIXED_PROTOTYPES__
+#endif
+
+/* Enable XPG4v2 extensions to POSIX, needed for MSG_WAITALL on older HP-UX. */
+#ifndef _XOPEN_SOURCE_EXTENDED
+# undef _XOPEN_SOURCE_EXTENDED
+#endif
+
+/* Enable reentrant versions of the standard C API (obsolete). */
+#ifndef _REENTRANT
+# undef _REENTRANT
+#endif
+
+/* Enable "safer" versions of the standard C API (ISO C11). */
+#ifndef __STDC_WANT_LIB_EXT1__
+# undef __STDC_WANT_LIB_EXT1__
+#endif
+
+/* Prevent static analyzers from genering bogus memory leak warnings. */
+#if defined(__COVERITY__) && !defined(NO_LEAKS)
+# define NO_LEAKS
+#endif
+
+#endif /* SUDO_CONFIG_H */])
diff --git a/docker/README b/docker/README
new file mode 100644
index 0000000..679446b
--- /dev/null
+++ b/docker/README
@@ -0,0 +1,45 @@
+Container images are stored in https://hub.docker.com/repositories as
+user sudoproject. Build images are named based on the distro and use
+the tag to differentiate between different versions and architectures.
+There should always be a "latest" tag (or manifest).
+
+When creating a new Dockerfile, use one of the Debian or Fedora files
+as a template. The examples below use podman rather than docker but it
+should be possible to them interchangeably.
+
+To build Debian containers for both amd64 and i386 (others only have amd64):
+
+ podman build --arch amd64 --pull -t sudoproject/debian:latest.amd64 \
+ docker/debian/latest
+ podman build --arch 386 --pull -t sudoproject/debian:latest.i386 \
+ docker/debian/latest
+
+Then push it to dockerhub (may need to run "podman login" first):
+ podman push sudoproject/debian:latest.amd64
+ podman push sudoproject/debian:latest.i386
+
+Multi-arch containers are supported by creating a manifest, e.g.:
+ podman manifest create sudoproject/debian:latest
+ podman manifest add sudoproject/debian:latest \
+ sudoproject/debian:latest.amd64
+ podman manifest add sudoproject/debian:latest \
+ sudoproject/debian:latest.i386
+
+Finally push the manifest to dockerhub:
+ podman push sudoproject/debian:latest
+
+When building bleeding edge images it is possible that the seccomp
+filter will be out of date with respect to system calls. It may
+be necessary to pass podman the --security-opt=seccomp=unconfined
+option in this case.
+
+Note that memory sanitizer uses ptrace which is not allowed for
+non-root containers by default. This will cause a failure when
+running the tests if sudo is configured with --enable-sanitizer.
+The simplest solution is to run the container with the SYS_PTRACE
+capability. E.g.
+ podman run -it --cap-add SYS_PTRACE ...
+
+Alternately, disable leak sanitizer by setting
+ ASAN_OPTIONS=detect_leaks=0
+in the environment of the container doing "make check".
diff --git a/docker/debian/latest/Dockerfile b/docker/debian/latest/Dockerfile
new file mode 100644
index 0000000..6621cec
--- /dev/null
+++ b/docker/debian/latest/Dockerfile
@@ -0,0 +1,10 @@
+FROM docker.io/library/debian:latest
+
+RUN DEBIAN_FRONTEND=noninteractive TZ=America/Denver apt-get update && \
+ DEBIAN_FRONTEND=noninteractive TZ=America/Denver apt-get install -y \
+ build-essential curl dpkg-dev ed fakeroot file git libapparmor-dev \
+ libaudit-dev libkrb5-dev libldap2-dev libpam0g-dev libpython3-dev \
+ libsasl2-dev libselinux1-dev libsepol-dev libssl-dev libwolfssl-dev \
+ lsb-release ncurses-term openssh-client pkg-config procps python3-dev \
+ ssh zlib1g-dev
+RUN useradd -ms /bin/bash build
diff --git a/docker/debian/testing/Dockerfile b/docker/debian/testing/Dockerfile
new file mode 100644
index 0000000..83f0e4a
--- /dev/null
+++ b/docker/debian/testing/Dockerfile
@@ -0,0 +1,10 @@
+FROM docker.io/library/debian:testing
+
+RUN DEBIAN_FRONTEND=noninteractive TZ=America/Denver apt-get update && \
+ DEBIAN_FRONTEND=noninteractive TZ=America/Denver apt-get install -y \
+ build-essential curl dpkg-dev ed fakeroot file git libapparmor-dev \
+ libaudit-dev libkrb5-dev libldap2-dev libpam0g-dev libpython3-dev \
+ libsasl2-dev libselinux1-dev libsepol-dev libssl-dev libwolfssl-dev \
+ lsb-release ncurses-term openssh-client pkg-config procps python3-dev \
+ ssh zlib1g-dev
+RUN useradd -ms /bin/bash build
diff --git a/docker/fedora/latest/Dockerfile b/docker/fedora/latest/Dockerfile
new file mode 100644
index 0000000..dec471a
--- /dev/null
+++ b/docker/fedora/latest/Dockerfile
@@ -0,0 +1,8 @@
+FROM docker.io/library/fedora:latest
+ENV TZ=America/Denver
+
+RUN dnf -y install audit-libs-devel cyrus-sasl-devel glibc-devel krb5-devel \
+ libasan libubsan libselinux-devel libsepol-devel make openldap-devel \
+ openssl-devel pam-devel python3-devel rpm-build zlib-devel binutils \
+ ed gcc gdb git openssh pkg-config procps which
+RUN useradd -ms /bin/bash build
diff --git a/docker/fedora/rawhide/Dockerfile b/docker/fedora/rawhide/Dockerfile
new file mode 100644
index 0000000..21b400d
--- /dev/null
+++ b/docker/fedora/rawhide/Dockerfile
@@ -0,0 +1,8 @@
+FROM docker.io/library/fedora:rawhide
+ENV TZ=America/Denver
+
+RUN dnf -y install audit-libs-devel cyrus-sasl-devel glibc-devel krb5-devel \
+ libasan libubsan libselinux-devel libsepol-devel make openldap-devel \
+ openssl-devel pam-devel python3-devel rpm-build zlib-devel binutils \
+ ed gcc gdb git openssh pkg-config procps which
+RUN useradd -ms /bin/bash build
diff --git a/docker/ubuntu/devel/Dockerfile b/docker/ubuntu/devel/Dockerfile
new file mode 100644
index 0000000..f5d305a
--- /dev/null
+++ b/docker/ubuntu/devel/Dockerfile
@@ -0,0 +1,10 @@
+FROM docker.io/library/ubuntu:devel
+
+RUN DEBIAN_FRONTEND=noninteractive TZ=America/Denver apt-get update && \
+ DEBIAN_FRONTEND=noninteractive TZ=America/Denver apt-get install -y \
+ build-essential curl dpkg-dev ed fakeroot file git libapparmor-dev \
+ libaudit-dev libkrb5-dev libldap2-dev libpam0g-dev libpython3-dev \
+ libsasl2-dev libselinux1-dev libsepol-dev libssl-dev libwolfssl-dev \
+ lsb-release ncurses-term openssh-client pkg-config procps python3-dev \
+ ssh zlib1g-dev
+RUN useradd -ms /bin/bash build
diff --git a/docker/ubuntu/latest/Dockerfile b/docker/ubuntu/latest/Dockerfile
new file mode 100644
index 0000000..582baae
--- /dev/null
+++ b/docker/ubuntu/latest/Dockerfile
@@ -0,0 +1,10 @@
+FROM docker.io/library/ubuntu:latest
+
+RUN DEBIAN_FRONTEND=noninteractive TZ=America/Denver apt-get update && \
+ DEBIAN_FRONTEND=noninteractive TZ=America/Denver apt-get install -y \
+ build-essential curl dpkg-dev ed fakeroot file git libapparmor-dev \
+ libaudit-dev libkrb5-dev libldap2-dev libpam0g-dev libpython3-dev \
+ libsasl2-dev libselinux1-dev libsepol-dev libssl-dev libwolfssl-dev \
+ lsb-release ncurses-term openssh-client pkg-config procps python3-dev \
+ ssh zlib1g-dev
+RUN useradd -ms /bin/bash build
diff --git a/docker/ubuntu/rolling/Dockerfile b/docker/ubuntu/rolling/Dockerfile
new file mode 100644
index 0000000..bf31a96
--- /dev/null
+++ b/docker/ubuntu/rolling/Dockerfile
@@ -0,0 +1,10 @@
+FROM docker.io/library/ubuntu:rolling
+
+RUN DEBIAN_FRONTEND=noninteractive TZ=America/Denver apt-get update && \
+ DEBIAN_FRONTEND=noninteractive TZ=America/Denver apt-get install -y \
+ build-essential curl dpkg-dev ed fakeroot file git libapparmor-dev \
+ libaudit-dev libkrb5-dev libldap2-dev libpam0g-dev libpython3-dev \
+ libsasl2-dev libselinux1-dev libsepol-dev libssl-dev libwolfssl-dev \
+ lsb-release ncurses-term openssh-client pkg-config procps python3-dev \
+ ssh zlib1g-dev
+RUN useradd -ms /bin/bash build
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
new file mode 100644
index 0000000..415ca41
--- /dev/null
+++ b/docs/CONTRIBUTING.md
@@ -0,0 +1,88 @@
+Contributing to Sudo
+====================
+
+Thank you for your interest in contributing to Sudo! There are a
+number of way you can help make Sudo better.
+
+## Getting started
+
+To get an overview of Sudo, see the [README.md](../README.md) file.
+There are multiple ways to contribute, some of which don't require
+writing a single line of code.
+
+## Filing bug reports/issues
+
+If you believe you have found a bug, you can either file a bug
+report in the sudo bug database, https://bugzilla.sudo.ws/, or open
+a [GitHub issue](https://github.com/sudo-project/sudo/issues),
+whichever you find easier. If you would prefer to use email,
+messages may be sent to the [sudo-workers@sudo.ws mailing
+list](https://www.sudo.ws/mailman/listinfo/sudo-workers) (public)
+or to sudo@sudo.ws (private).
+
+For sudo's security policy and how to report security issues, see
+[SECURITY.md](SECURITY.md).
+
+Please check [TROUBLESHOOTING.md](TROUBLESHOOTING.md) *before*
+submitting a bug report. When reporting bugs, be sure to include
+the version of sudo you are using, the operating system and/or
+distro that is affected, and, if possible, step-by-step instructions
+to reproduce the problem.
+
+## Making changes to Sudo
+
+If you are interested in making changes to Sudo there are two main
+work flows:
+
+ * clone the [sudo repo](https://github.com/sudo-project/sudo), make
+ your changes, and submit a Pull Request (PR).
+
+ * send a diff with your changes to the [sudo-workers@sudo.ws mailing
+ list](https://www.sudo.ws/mailman/listinfo/sudo-workers) to start
+ a discussion.
+
+In addition to the [GitHub repo](https://github.com/sudo-project/sudo),
+there is also a [mercurial repo](https://www.sudo.ws/repos/sudo).
+
+## sudo-workers mailing list
+
+If you would like to discuss your changes before submitting a
+PR, you may do so on the [sudo-workers@sudo.ws mailing
+list](https://www.sudo.ws/mailman/listinfo/sudo-workers).
+Otherwise, discussion can simply occur as part of the PR work flow.
+
+## Fuzzing
+
+Sudo uses the [oss-fuzz project](https://github.com/google/oss-fuzz.git)
+to perform fuzzing. Each commit to the _main_ branch will trigger
+a short fuzzing run via the [CIFuzz
+action](https://github.com/sudo-project/sudo/actions/workflows/main.yml).
+The history of that action shows successful and failed fuzzing runs.
+
+Longer fuzzing runs occur using the ClusterFuzz infrastructure. These
+fuzzing runs are longer than those used by CIFuzz. A [public list of
+failures](https://bugs.chromium.org/p/oss-fuzz/issues/list?q=sudoers)
+is available.
+
+For more information, see https://www.sudo.ws/security/fuzzing/.
+
+## Translations
+
+Sudo uses [GNU gettext](https://www.gnu.org/software/gettext/) for
+its National Language Support (NLS). Strings in sudo and related
+programs are collected in `.pot` files that can be translated into
+multiple languages.
+
+Translations for sudo are coordinated by the [Translation
+Project](https://translationproject.org). If you would like to
+contribute to Sudo's translations, please join a translation team
+at the Translation Project instead of contributing a `.po` file
+directly. This will avoid duplicated work if there is already a
+translation in progress. If you would like to become a member of
+a translation team, please follow the [instructions for
+translators](https://translationproject.org/html/translators.html).
+
+There are currently two translation domains: [one for the sudo
+front-end](https://translationproject.org/domain/sudo.html) and a
+[separate one for the sudoers module and related
+utilities](https://translationproject.org/domain/sudoers.html).
diff --git a/docs/CONTRIBUTORS.md b/docs/CONTRIBUTORS.md
new file mode 100644
index 0000000..f9d5f07
--- /dev/null
+++ b/docs/CONTRIBUTORS.md
@@ -0,0 +1,252 @@
+The following list of people, sorted by last name, have contributed
+code or patches to this implementation of sudo since I began
+maintaining it in 1993. This list is known to be incomplete--if
+you believe you should be listed, send a note to sudo@sudo.ws.
+
+ Ackeret, Matt
+ Adler, Mark
+ Allbery, Russ
+ Anderson, Jamie
+ Andrew, Nick
+ Andric, Dimitry
+ Barron, Danny
+ Bates, Tom
+ Behan, Zdeněk
+ Bellis, Ray
+ Benali, Elias
+ Beverly, Jamie
+ Boardman, Spider
+ Bos, Sander
+ Bostley, P.J.
+ Bowes, Keith
+ Boyce, Keith Garry
+ Brantley, Michael
+ Braun, Rob
+ Březina, Pavel
+ Brooks, Piete
+ Brown, Jerry
+ Burr, Michael E
+ Burton, Ross
+ Bussjaeger, Andreas
+ Calvin, Gary
+ Campbell, Aaron
+ Chazelas, Stephane
+ Cheloha, Scott
+ Čížek, Vítězslav
+ Coleman, Chris
+ Corzine, Deven T.
+ Cusack, Frank
+ Dai, Wei
+ Dill, David
+ Earickson, Jeff
+ Eckhardt, Drew
+ Edgington, Ben
+ Esipovich, Marc
+ Espie, Marc
+ Faigon, Ariel
+ Farrell, Brian
+ Fobes, Steve
+ Frysinger, Mike
+ G., Daniel Richard
+ Gailly, Jean-loup
+ Gelman, Stephen
+ Gerraty, Simon J.
+ Graber, Stephane
+ Guillory, B.
+ Hayman, Randy M.
+ Henke, Joachim
+ Hideaki, Yoshifuji
+ Hieb, Dave
+ Holloway, Nick
+ Hoover, Adam
+ Hunter, Michael T.
+ Hutchings, Ben
+ Irrgang, Eric
+ Jackson, Brian
+ Jackson, John R.
+ Jackson, Richard L., Jr.
+ Janssen, Mark
+ Jindrák, Jaroslav
+ Jepeway, Chris
+ Jorge, Joel Peláe
+ Jover, Guillem
+ Juhani, Timo
+ Kikuchi, Ayamura
+ Kadow, Kevin
+ Kasal, Stepan
+ Kienenberger, Mike
+ King, Dale
+ King, Michael
+ Klyachkin, Andrey
+ Knoble, Jim
+ Knox, Tim
+ Komarnitsky, Alek O.
+ Kondrashov, Nikolai
+ Kopeček, Daniel
+ Kranenburg, Paul
+ Krause, David
+ Lakin, Eric
+ Larsen, Case
+ Levin, Dmitry V.
+ Libby, Kendall
+ Lobbes, Phillip E.
+ McIntyre, Jason
+ MacKenzie, David J.
+ McLaughlin, Tom
+ Makey, Jeff
+ Mallayya, Sangamesh
+ Manner, Róbert
+ Marchionna, Michael D.
+ Markham, Paul
+ Martinian, Emin
+ Meskes, Michael
+ Michael, David
+ Miller, Todd C.
+ Minier, Loïc
+ Moffat, Darren
+ Moldung, Jan Thomas
+ Morris, Charles
+ Mueller, Andreas
+ Müller, Dworkin
+ Nieusma, Jeff
+ Nikitser, Peter A.
+ Nussel, Ludwig
+ Orbán, László
+ Ouellet, Jean-Philippe
+ Paquet, Eric
+ Paradis, Chantal
+ Pasteleurs, Frederic
+ Percival, Ted
+ Perera, Andres
+ Peron, Christian S.J.
+ Peschel, Aaron
+ Peslyak, Alexander
+ Peterson, Toby
+ Pettenò, Diego Elio
+ Pickett, Joel
+ Plotnick, Alex
+ de Raadt, Theo
+ Rasch, Gudleik
+ Reid, Steve
+ Richards, Matt
+ Rossum, Guido van
+ Rouillard, John P.
+ Rowe, William A., Jr.
+ Roy, Alain
+ Ruusamäe, Elan
+ Ryabinkin, Eygene
+ Sato, Yuichi
+ Sánchez, Wilfredo
+ Sanders, Miguel
+ Sasaki, Kan
+ Saucier, Jean-Francois
+ Schoenfeld, Patrick
+ Schuring, Arno
+ Schwarze, Ingo
+ Scott, Dougal
+ Shand, Will
+ Sieger, Nick
+ Simon, Thor Lancelot
+ Skoll, Dianne
+ Slemko, Marc
+ Smith, Andy
+ Sobrado, Igor
+ Soulen, Steven
+ Spangler, Aaron
+ Spradling, Cloyce D.
+ Spradling, Michael
+ Stier, Matthew
+ Stoeckmann, Tobias
+ Street, Russell
+ Stritzky, Tilo
+ Stroucken, Michael
+ Tarrall, Robert
+ Thomas, Matthew
+ Todd, Giles
+ Toft, Martin
+ Torek, Chris
+ Tucker, Darren
+ Uhl, Robert
+ Uzel, Petr
+ Valery, Reznic
+ Van Dinter, Theo
+ Venckus, Martynas
+ de Vries, Maarten
+ Wagner, Klaus
+ Walsh, Dan
+ Warburton, John
+ Webb, Kirk
+ Wetzel, Timm
+ Wieringen, Marco van
+ Wilk, Jakub
+ Winiger, Gary
+ Wood, David
+ Zacarias, Gustavo
+ Zolnowsky, John
+
+The following people have worked to translate sudo into
+other languages as part of the Translation Project, see
+https://translationproject.org for more details.
+
+ Albuquerque, Pedro
+ Blättermann, Mario
+ Bogusz, Jakub
+ Buo-ren, Lin
+ Casagrande, Milo
+ Castro, Felipe
+ Cho, Seong-ho
+ Chornoivan, Yuri
+ Diéguez, Francisco
+ Doghonadze, Temuri
+ Fontenelle, Rafael
+ García-Fontes, Walter
+ Gezer, Volkan
+ Hamasaki, Takeshi
+ Hamming, Peter
+ Hansen, Joe
+ Hantrais, Frédéric
+ Hein, Jochen
+ Hufthammer, Karl Ove
+ Jerovšek, Damir
+ Karvonen, Jorma
+ Kazik, Dušan
+ Kelemen, Gábor
+ Keçeci, Mehmet
+ Košir, Klemen
+ Kozlov, Yuri
+ Kramer, Jakob
+ Krznar, Tomislav
+ Marchal, Frédéric
+ Margevičius, Algimantas
+ Maryanov, Pavel
+ Florentina Mușat
+ Nurmi, Lauri
+ Nikolić, Miroslav
+ Nylander, Daniel
+ Pan, Yi-Jyun
+ Písař, Petr
+ Puente, Enol
+ Putanec, Božidar
+ Quân, Trần Ngọc
+ Rasmussen, Sebastian
+ Regueiro, Leandro
+ Sarıer, Özgür
+ Selimaj, Agron
+ Sendón, Abel
+ Șerbănescu, Daniel
+ Shahedany, Eshagh
+ Sikrom, Åka
+ Spingos, Dimitris
+ Taniguchi, Yasuaki
+ Tomat, Fábio
+ Triwidada, Andika
+ Úr, Balázs
+ Uranga, Mikel Olasagasti
+ Vorotnikov, Artem
+ Wang, Wylmer
+ Yang, Boyuan
+
+The following people designed the artwork used on the sudo website:
+
+ Shield logo: Badger, Trent
+ Sandwich logo (inspired by xkcd): Stillman, Mark
diff --git a/docs/HISTORY.md b/docs/HISTORY.md
new file mode 100644
index 0000000..f728f62
--- /dev/null
+++ b/docs/HISTORY.md
@@ -0,0 +1,77 @@
+A Brief History of Sudo
+=======================
+
+## The Early Years
+
+Sudo was first conceived and implemented by Bob Coggeshall and Cliff Spencer
+around 1980 at the Department of Computer Science at SUNY/Buffalo. It ran on
+a VAX-11/750 running 4.1BSD. An updated version, credited to Phil Betchel,
+Cliff Spencer, Gretchen Phillips, John LoVerso, and Don Gworek, was posted to
+the net.sources Usenet newsgroup in December of 1985.
+
+## Sudo at CU-Boulder
+
+In the Summer of 1986, Garth Snyder released an enhanced version of sudo.
+For the next 5 years, sudo was fed and watered by a handful of folks at
+CU-Boulder, including Bob Coggeshall, Bob Manchek, and Trent Hein.
+
+## Root Group Sudo
+
+In 1991, Dave Hieb and Jeff Nieusma wrote a new version of sudo with an
+enhanced sudoers format under contract to a consulting firm called "The Root
+Group". This version was later released under the GNU public license.
+
+## CU Sudo
+
+In 1994, after maintaining sudo informally within CU-Boulder for some time,
+Todd C. Miller made a public release of "CU sudo" (version 1.3) with bug
+fixes and support for more operating systems. The "CU" was added to
+differentiate it from the "official" version from "The Root Group".
+
+In 1995, a new parser for the sudoers file was contributed by Chris Jepeway.
+The new parser was a proper grammar (unlike the old one) and could work with
+both sudo and visudo (previously they had slightly different parsers).
+
+In 1996, Todd, who had been maintaining sudo for several years in his spare
+time, moved distribution of sudo from a CU-Boulder ftp site to his domain,
+courtesan.com.
+
+## Just Plain Sudo
+
+In 1999, the "CU" prefix was dropped from the name since there had been no
+formal release of sudo from "The Root Group" since 1991 (the original
+authors now work elsewhere). As of version 1.6, Sudo no longer contains any
+of the original "Root Group" code and is available under an ISC-style
+license.
+
+In 2001, the sudo web site, ftp site, and mailing lists were moved from
+courtesan.com to the sudo.ws domain (sudo.org was already taken).
+
+## LDAP Integration
+
+In 2003, Nationwide Mutual Insurance Company contributed code written by
+Aaron Spangler to store the sudoers data in LDAP. These changes were
+incorporated into Sudo 1.6.8.
+
+## New Parser
+
+In 2005, Todd rewrote the sudoers parser to better support the features that
+had been added in the past ten years. This new parser removes some
+limitations of the previous one, removes ordering constraints and adds
+support for including multiple sudoers files.
+
+## Quest Sponsorship
+
+In 2010, Quest Software began sponsoring Sudo development by hiring
+Todd to work on Sudo as part of his full-time job. This enabled
+the addition of I/O logging, the plugin API, the log server,
+additional regression and fuzz tests, support for binary packages
+and more regular releases.
+
+## Present Day
+
+Sudo, in its current form, is maintained by:
+
+ Todd C. Miller <Todd.Miller@sudo.ws>
+
+Todd continues to enhance sudo and fix bugs.
diff --git a/docs/Makefile.in b/docs/Makefile.in
new file mode 100644
index 0000000..d8614d6
--- /dev/null
+++ b/docs/Makefile.in
@@ -0,0 +1,434 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2010-2015, 2017-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+docdir = @docdir@
+scriptdir = $(top_srcdir)/scripts
+
+# Tools to use
+SED = @SED@
+IGOR = igor
+MANDOC = mandoc
+MANCOMPRESS = @MANCOMPRESS@
+MANCOMPRESSEXT = @MANCOMPRESSEXT@
+TR = @TRPROG@
+
+# Our install program supports extra flags...
+INSTALL = $(SHELL) $(scriptdir)/install-sh -c
+INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
+
+# Where to install things...
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+sysconfdir = @sysconfdir@
+adminconfdir = @adminconfdir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+
+# Directory in which to install the man page
+mantype = @MANTYPE@
+mansectsu = @mansectsu@
+mansectform = @mansectform@
+mandirexe = $(mandir)/@MANDIRTYPE@1
+mandirsu = $(mandir)/@MANDIRTYPE@$(mansectsu)
+mandirform = $(mandir)/@MANDIRTYPE@$(mansectform)
+
+# User and group ids the installed files should be "owned" by
+install_uid = 0
+install_gid = 0
+
+# Set to non-empty for development mode
+DEVEL = @DEVEL@
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+DOCS = ./cvtsudoers.$(mantype) ./sudo.$(mantype) ./sudo.conf.$(mantype) \
+ ./sudo_logsrvd.$(mantype) ./sudo_logsrv.proto.$(mantype) \
+ ./sudo_logsrvd.conf.$(mantype) ./sudo_plugin.$(mantype) \
+ ./sudo_plugin_python.$(mantype) ./sudo_sendlog.$(mantype) \
+ ./sudoers.$(mantype) ./sudoers.ldap.$(mantype) \
+ ./sudoers_timestamp.$(mantype) \
+ ./sudoreplay.$(mantype) ./visudo.$(mantype)
+
+DEVDOCS = $(srcdir)/cvtsudoers.man.in $(srcdir)/sudo.conf.man.in \
+ $(srcdir)/sudo.man.in $(srcdir)/sudo_logsrvd.man.in \
+ $(srcdir)/sudo_logsrv.proto.man.in \
+ $(srcdir)/sudo_logsrvd.conf.man.in \
+ $(srcdir)/sudo_plugin.man.in $(srcdir)/sudo_plugin_python.man.in \
+ $(srcdir)/sudo_sendlog.man.in $(srcdir)/sudoers.ldap.man.in \
+ $(srcdir)/sudoers.man.in $(srcdir)/sudoers_timestamp.man.in \
+ $(srcdir)/sudoreplay.man.in $(srcdir)/visudo.man.in
+
+OTHER_DOCS = $(top_srcdir)/ChangeLog $(top_srcdir)/NEWS \
+ $(top_srcdir)/README.md $(srcdir)/CONTRIBUTING.md \
+ $(top_srcdir)/LICENSE.md $(srcdir)/CONTRIBUTORS.md \
+ $(srcdir)/HISTORY.md $(srcdir)/SECURITY.md \
+ $(srcdir)/TROUBLESHOOTING.md $(srcdir)/UPGRADE.md
+
+OTHER_DOCS_LDAP = $(top_srcdir)/README.LDAP.md $(srcdir)/schema.*
+
+VERSION = @PACKAGE_VERSION@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+
+all: $(DEVDOCS) $(DOCS)
+
+igor: all
+ @if [ "$(mantype)" != "mdoc" ]; then \
+ echo "make igor only supported for mdoc manuals" 1>&2; \
+ exit 1; \
+ else \
+ rval=0; \
+ for m in $(DOCS); do \
+ echo $(IGOR) -D $$m; \
+ $(IGOR) -D $$m || rval=`expr $$rval + $$?`; \
+ done; \
+ exit $$rval; \
+ fi
+
+lint: all
+ @if [ "$(mantype)" != "mdoc" ]; then \
+ echo "make lint only supported for mdoc manuals" 1>&2; \
+ exit 1; \
+ else \
+ rval=0; \
+ for m in $(DOCS); do \
+ echo $(MANDOC) -Tlint -Wwarning $$m; \
+ $(MANDOC) -Tlint -Wwarning $$m || rval=`expr $$rval + $$?`; \
+ done; \
+ exit $$rval; \
+ fi
+
+depend:
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file docs/Makefile
+
+.SUFFIXES: .man
+
+$(srcdir)/sudo.man.in: $(srcdir)/sudo.mdoc.in $(srcdir)/sudo.man.in.sed
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e 's/^\(\.nr [A-Z][A-Z]\) .[A-Z][A-Z]MAN./\1 1/' -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudo.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDO" \)"8"\(.*\)/\1"'$$mansectsu'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" -f $(srcdir)/sudo.man.in.sed > $@; \
+ fi
+
+fixman.sed: $(srcdir)/fixman.sh
+ $(SHELL) $(srcdir)/fixman.sh $@
+
+./sudo.man: $(top_builddir)/config.status $(srcdir)/sudo.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudo.man.in | $(SED) -f fixman.sed > $@
+
+./sudo.mdoc: $(top_builddir)/config.status $(srcdir)/sudo.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=docs/$@
+
+$(srcdir)/visudo.man.in: $(srcdir)/visudo.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/visudo.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "VISUDO" \)"8"\(.*\)/\1"'$$mansectsu'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./visudo.man: $(top_builddir)/config.status $(srcdir)/visudo.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/visudo.man.in | $(SED) -f fixman.sed > $@
+
+./visudo.mdoc: $(top_builddir)/config.status $(srcdir)/visudo.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=docs/$@
+
+$(srcdir)/sudo.conf.man.in: $(srcdir)/sudo.conf.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e 's/^\(\.nr [A-Z][A-Z]\) .[A-Z][A-Z]MAN./\1 1/' -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudo.conf.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDO.CONF" \)"5"\(.*\)/\1"'$$mansectform'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" -f $(srcdir)/sudo.conf.man.in.sed > $@; \
+ fi
+
+./sudo.conf.man: $(top_builddir)/config.status $(srcdir)/sudo.conf.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudo.conf.man.in | $(SED) -f fixman.sed > $@
+
+./sudo.conf.mdoc: $(top_builddir)/config.status $(srcdir)/sudo.conf.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=docs/$@
+
+$(srcdir)/sudoers.man.in: $(srcdir)/sudoers.mdoc.in $(srcdir)/sudoers.man.in.sed
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e 's/^\(\.nr [A-Z][A-Z]\) .[A-Z][A-Z]MAN./\1 1/' -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudoers.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDOERS" \)"5"\(.*\)/\1"'$$mansectform'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" -f $(srcdir)/sudoers.man.in.sed> $@; \
+ fi
+
+./sudoers.man: $(top_builddir)/config.status $(srcdir)/sudoers.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudoers.man.in | $(SED) -f fixman.sed > $@
+
+./sudoers.mdoc: $(top_builddir)/config.status $(srcdir)/sudoers.mdoc.in $(srcdir)/fixmdoc.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudoers.mdoc.in | $(SED) -f $(srcdir)/fixmdoc.sed > $@
+
+$(srcdir)/sudoers.ldap.man.in: $(srcdir)/sudoers.ldap.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudoers.ldap.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDOERS.LDAP" \)"5"\(.*\)/\1"'$$mansectform'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./sudoers.ldap.man: $(top_builddir)/config.status $(srcdir)/sudoers.ldap.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudoers.ldap.man.in | $(SED) -f fixman.sed > $@
+
+./sudoers.ldap.mdoc: $(top_builddir)/config.status $(srcdir)/sudoers.ldap.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=docs/$@
+
+$(srcdir)/sudoers_timestamp.man.in: $(srcdir)/sudoers_timestamp.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudoers_timestamp.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDOERS_TIMESTAMP" \)"5"\(.*\)/\1"'$$mansectform'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./sudoers_timestamp.man: $(top_builddir)/config.status $(srcdir)/sudoers_timestamp.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudoers_timestamp.man.in | $(SED) -f fixman.sed > $@
+
+./sudoers_timestamp.mdoc: $(top_builddir)/config.status $(srcdir)/sudoers_timestamp.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=docs/$@
+
+$(srcdir)/cvtsudoers.man.in: $(srcdir)/cvtsudoers.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/cvtsudoers.mdoc.in | $(MANDOC) -Tman | $(SED) -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./cvtsudoers.man: $(top_builddir)/config.status $(srcdir)/cvtsudoers.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/cvtsudoers.man.in | $(SED) -f fixman.sed > $@
+
+./cvtsudoers.mdoc: $(top_builddir)/config.status $(srcdir)/cvtsudoers.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=docs/$@
+
+$(srcdir)/sudoreplay.man.in: $(srcdir)/sudoreplay.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudoreplay.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDOREPLAY" \)"8"\(.*\)/\1"'$$mansectsu'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./sudoreplay.man: $(top_builddir)/config.status $(srcdir)/sudoreplay.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudoreplay.man.in | $(SED) -f fixman.sed > $@
+
+./sudoreplay.mdoc: $(top_builddir)/config.status $(srcdir)/sudoreplay.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=docs/$@
+
+$(srcdir)/sudo_logsrvd.man.in: $(srcdir)/sudo_logsrvd.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudo_logsrvd.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDO_LOGSRVD" \)"8"\(.*\)/\1"'$$mansectsu'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./sudo_logsrvd.man: $(top_builddir)/config.status $(srcdir)/sudo_logsrvd.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudo_logsrvd.man.in | $(SED) -f fixman.sed > $@
+
+./sudo_logsrvd.mdoc: $(top_builddir)/config.status $(srcdir)/sudo_logsrvd.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=docs/$@
+
+$(srcdir)/sudo_logsrv.proto.man.in: $(srcdir)/sudo_logsrv.proto.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudo_logsrv.proto.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDO_LOGSRV.PROTO" \)"5"\(.*\)/\1"'$$mansectform'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(5)/($$mansectform)/g" > $@; \
+ fi
+
+./sudo_logsrv.proto.man: $(top_builddir)/config.status $(srcdir)/sudo_logsrv.proto.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudo_logsrv.proto.man.in | $(SED) -f fixman.sed > $@
+
+./sudo_logsrv.proto.mdoc: $(top_builddir)/config.status $(srcdir)/sudo_logsrv.proto.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=docs/$@
+
+$(srcdir)/sudo_logsrvd.conf.man.in: $(srcdir)/sudo_logsrvd.conf.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudo_logsrvd.conf.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDO_LOGSRVD.CONF" \)"5"\(.*\)/\1"'$$mansectform'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(5)/($$mansectform)/g" > $@; \
+ fi
+
+./sudo_logsrvd.conf.man: $(top_builddir)/config.status $(srcdir)/sudo_logsrvd.conf.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudo_logsrvd.conf.man.in | $(SED) -f fixman.sed > $@
+
+./sudo_logsrvd.conf.mdoc: $(top_builddir)/config.status $(srcdir)/sudo_logsrvd.conf.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=docs/$@
+
+$(srcdir)/sudo_plugin.man.in: $(srcdir)/sudo_plugin.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudo_plugin.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDO_PLUGIN" \)"8"\(.*\)/\1"'$$mansectsu'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./sudo_plugin.man: $(top_builddir)/config.status $(srcdir)/sudo_plugin.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudo_plugin.man.in | $(SED) -f fixman.sed > $@
+
+./sudo_plugin.mdoc: $(top_builddir)/config.status $(srcdir)/sudo_plugin.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=docs/$@
+
+$(srcdir)/sudo_plugin_python.man.in: $(srcdir)/sudo_plugin_python.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudo_plugin_python.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDO_PLUGIN_PYTHON" \)"8"\(.*\)/\1"'$$mansectsu'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./sudo_plugin_python.man: $(top_builddir)/config.status $(srcdir)/sudo_plugin_python.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudo_plugin_python.man.in | $(SED) -f fixman.sed > $@
+
+./sudo_plugin_python.mdoc: $(top_builddir)/config.status $(srcdir)/sudo_plugin_python.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=docs/$@
+
+$(srcdir)/sudo_sendlog.man.in: $(srcdir)/sudo_sendlog.mdoc.in
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "Generating $@"; \
+ mansectsu=`echo @MANSECTSU@|$(TR) A-Z a-z`; \
+ mansectform=`echo @MANSECTFORM@|$(TR) A-Z a-z`; \
+ $(SED) -e "s/$$mansectsu/8/g" -e "s/$$mansectform/5/g" $(srcdir)/sudo_sendlog.mdoc.in | $(MANDOC) -Tman | $(SED) -e 's/^\(\.TH "SUDO_SENDLOG" \)"8"\(.*\)/\1"'$$mansectsu'"\2/' -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" > $@; \
+ fi
+
+./sudo_sendlog.man: $(top_builddir)/config.status $(srcdir)/sudo_sendlog.man.in fixman.sed
+ (cd $(top_builddir) && $(SHELL) config.status --file=-) < $(srcdir)/sudo_sendlog.man.in | $(SED) -f fixman.sed > $@
+
+./sudo_sendlog.mdoc: $(top_builddir)/config.status $(srcdir)/sudo_sendlog.mdoc.in
+ cd $(top_builddir) && $(SHELL) config.status --file=docs/$@
+
+pre-install:
+
+install: install-doc
+
+install-dirs:
+ $(SHELL) $(scriptdir)/mkinstalldirs $(DESTDIR)$(docdir) \
+ $(DESTDIR)$(mandirexe) $(DESTDIR)$(mandirform) $(DESTDIR)$(mandirsu)
+
+install-binaries:
+
+install-includes:
+
+install-doc: install-dirs
+ for f in $(OTHER_DOCS); do $(INSTALL) $(INSTALL_OWNER) -m 0644 $$f $(DESTDIR)$(docdir); done
+ @LDAP@for f in $(OTHER_DOCS_LDAP); do $(INSTALL) $(INSTALL_OWNER) -m 0644 $$f $(DESTDIR)$(docdir); done
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./cvtsudoers.$(mantype) $(DESTDIR)$(mandirexe)/cvtsudoers.1
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudo.$(mantype) $(DESTDIR)$(mandirsu)/sudo.$(mansectsu)
+ @LOGSRV@$(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudo_logsrvd.$(mantype) $(DESTDIR)$(mandirsu)/sudo_logsrvd.$(mansectsu)
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudo_plugin.$(mantype) $(DESTDIR)$(mandirform)/sudo_plugin.$(mansectform)
+ @PYTHON_PLUGIN@$(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudo_plugin_python.$(mantype) $(DESTDIR)$(mandirform)/sudo_plugin_python.$(mansectform)
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudo_sendlog.$(mantype) $(DESTDIR)$(mandirsu)/sudo_sendlog.$(mansectsu)
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudoreplay.$(mantype) $(DESTDIR)$(mandirsu)/sudoreplay.$(mansectsu)
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./visudo.$(mantype) $(DESTDIR)$(mandirsu)/visudo.$(mansectsu)
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudo.conf.$(mantype) $(DESTDIR)$(mandirform)/sudo.conf.$(mansectform)
+ @LOGSRV@$(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudo_logsrv.proto.$(mantype) $(DESTDIR)$(mandirform)/sudo_logsrv.proto.$(mansectform)
+ @LOGSRV@$(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudo_logsrvd.conf.$(mantype) $(DESTDIR)$(mandirform)/sudo_logsrvd.conf.$(mansectform)
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudoers.$(mantype) $(DESTDIR)$(mandirform)/sudoers.$(mansectform)
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudoers_timestamp.$(mantype) $(DESTDIR)$(mandirform)/sudoers_timestamp.$(mansectform)
+ @LDAP@$(INSTALL) $(INSTALL_OWNER) -m 0644 ./sudoers.ldap.$(mantype) $(DESTDIR)$(mandirform)/sudoers.ldap.$(mansectform)
+ @if test -n "$(MANCOMPRESS)"; then \
+ for f in $(mandirexe)/cvtsudoers.1 $(mandirsu)/sudo.$(mansectsu) $(mandirsu)/sudo_logsrvd.$(mansectsu) $(mandirform)/sudo_plugin.$(mansectform) $(mandirform)/sudo_plugin_python.$(mansectform) $(mandirsu)/sudo_sendlog.$(mansectsu) $(mandirsu)/sudoreplay.$(mansectsu) $(mandirsu)/visudo.$(mansectsu) $(mandirform)/sudo.conf.$(mansectform) $(mandirform)/sudo_logsrv.proto.$(mansectform) $(mandirform)/sudo_logsrvd.conf.$(mansectform) $(mandirform)/sudoers.$(mansectform) $(mandirform)/sudoers_timestamp.$(mansectform) $(mandirform)/sudoers.ldap.$(mansectform); do \
+ if test -f $(DESTDIR)$$f; then \
+ echo $(MANCOMPRESS) -f $(DESTDIR)$$f; \
+ $(MANCOMPRESS) -f $(DESTDIR)$$f; \
+ fi; \
+ done; \
+ rm -f $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu)$(MANCOMPRESSEXT); \
+ echo ln -s sudo.$(mansectsu)$(MANCOMPRESSEXT) $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu)$(MANCOMPRESSEXT); \
+ ln -s sudo.$(mansectsu)$(MANCOMPRESSEXT) $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu)$(MANCOMPRESSEXT); \
+ else \
+ rm -f $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu); \
+ echo ln -s sudo.$(mansectsu) $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu); \
+ ln -s sudo.$(mansectsu) $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu); \
+ fi
+
+install-plugin:
+
+install-fuzzer:
+
+uninstall:
+ -rm -rf $(DESTDIR)$(docdir)
+ -rm -f $(DESTDIR)$(mandirexe)/cvtsudoers.1 \
+ $(DESTDIR)$(mandirsu)/sudo.$(mansectsu) \
+ $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu) \
+ $(DESTDIR)$(mandirsu)/sudo_logsrvd.$(mansectsu) \
+ $(DESTDIR)$(mandirsu)/sudo_sendlog.$(mansectsu) \
+ $(DESTDIR)$(mandirsu)/sudoreplay.$(mansectsu) \
+ $(DESTDIR)$(mandirsu)/visudo.$(mansectsu) \
+ $(DESTDIR)$(mandirform)/sudo.conf.$(mansectform) \
+ $(DESTDIR)$(mandirform)/sudo_logsrv.proto.$(mansectform) \
+ $(DESTDIR)$(mandirform)/sudo_logsrvd.conf.$(mansectform) \
+ $(DESTDIR)$(mandirform)/sudo_plugin.$(mansectform) \
+ $(DESTDIR)$(mandirform)/sudo_plugin_python.$(mansectform) \
+ $(DESTDIR)$(mandirform)/sudoers.$(mansectform) \
+ $(DESTDIR)$(mandirform)/sudoers_timestamp.$(mansectform) \
+ $(DESTDIR)$(mandirform)/sudoers.ldap.$(mansectform)
+
+splint:
+
+cppcheck:
+
+pvs-log-files:
+
+pvs-studio:
+
+fuzz:
+
+check-fuzzer:
+
+check: check-fuzzer
+
+check-verbose: check
+
+clean:
+ -rm -f fixman.sed
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile config.log *.man *.mdoc
+
+clobber: distclean
+
+realclean: distclean
+
+cleandir: distclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean
diff --git a/docs/SECURITY.md b/docs/SECURITY.md
new file mode 100644
index 0000000..1bb2680
--- /dev/null
+++ b/docs/SECURITY.md
@@ -0,0 +1,43 @@
+Sudo Security Policy
+====================
+
+The Sudo Project takes security seriously. If you believe you have found a security vulnerability in Sudo, you can report it to us as described below.
+
+## Reporting Security Issues
+
+**Do not report security vulnerabilities through public GitHub issues or Bugzilla.**
+
+Instead, report them via email to <Todd.Miller@sudo.ws>. You may encrypt your message with PGP if you would like. The current PGP key has the fingerprint 59D1 E9CC BA2B 3767 04FD D35B A9F4 C021 CEA4 70FB and may be downloaded from [the sudo.ws web site](https://www.sudo.ws/dist/PGPKEYS) or the [OpenPGP Key Server](https://keys.openpgp.org/search?q=0xa9f4c021cea470fb).
+
+We try to respond to security issues in a timely manner but understand that Sudo is a volunteer project.
+
+Include as much of the following information as possible to help us better understand the nature and scope of the potential issue:
+
+ * Type of issue (e.g. buffer overflow, privilege escalation, etc.)
+ * Full paths of source file(s) related to the issue
+ * The location of the affected source code (tag/branch/commit or direct URL)
+ * Any special configuration required to reproduce the issue
+ * The operating system and/or distro affected
+ * Step-by-step instructions to reproduce the issue
+ * Proof-of-concept or exploit code (if possible)
+ * Impact of the issue, including how an attacker might exploit the issue
+
+This information will help us triage your report more quickly.
+
+As a volunteer-led project, we are not able to offer bug bounties.
+However, we'd be happy to send you Sudo stickers as a way of saying
+thank you!
+
+## Preferred Languages
+
+We prefer all communications to be in English.
+
+## Disclosure Policy
+
+The Sudo Project follows the principle of [Coordinated Vulnerability Disclosure](https://vuls.cert.org/confluence/display/CVD/Executive+Summary). Disclosure is usually coordinated using the [distros mailing list](https://oss-security.openwall.org/wiki/mailing-lists/distros).
+
+## Security Advisories
+
+The Sudo web site contains an archive of [sudo security advisories](https://www.sudo.ws/security/advisories/).
+Additionally, information about vulnerabilities in sudo is sent to the
+[oss-security mailing list](https://oss-security.openwall.org/wiki/mailing-lists/oss-security) once the information becomes public.
diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md
new file mode 100644
index 0000000..2d3b721
--- /dev/null
+++ b/docs/TROUBLESHOOTING.md
@@ -0,0 +1,359 @@
+Troubleshooting tips and FAQ for Sudo
+=====================================
+
+#### When I run configure, it says "C compiler cannot create executables".
+
+> This usually means you either don't have a working compiler. This
+> could be due to the lack of a license or that some component of the
+> compiler suite could not be found. Check config.log for clues as
+> to why this is happening. On many systems, compiler components live
+> in /usr/ccs/bin which may not be in your PATH environment variable.
+
+#### When I run configure, it says "sudo requires the 'ar' utility to build".
+
+> As part of the build process, sudo creates a temporary library
+> containing objects that are shared amongst the different sudo
+> executables. On Unix systems, the 'ar' utility is used to do this.
+> This error indicates that 'ar' is missing on your system. On Solaris
+> systems, you may need to install the SUNWbtool package. On other
+> systems 'ar' may be included in the GNU binutils package.
+
+#### Sudo compiles and installs successfully but when I try to run it I get:
+
+ The "no new privileges" flag is set, which prevents sudo from
+ running as root. If sudo is running in a container, you may
+ need to adjust the container configuration to disable the flag.
+
+> Sudo was run by a process that has the Linux "no new privileges"
+> flag set. This causes the set-user-ID bit to be ignored when running
+> an executable, which will prevent sudo from functioning. The most
+> likely cause for this is running sudo within a container that sets
+> this flag. Check the documentation to see if it is possible to
+> configure the container such that the flag is not set.
+
+#### Sudo compiles and installs successfully but when I try to run it I get:
+
+ /usr/local/bin/sudo must be owned by uid 0 and have the setuid bit set
+
+> Sudo must be set-user-ID root to do its work. Either `/usr/local/bin/sudo`
+> is not owned by user-ID 0 or the set-user-ID bit is not set. This should
+> have been done for you by `make install` but you can fix it manually by
+> running the following as root:
+
+ chown root /usr/local/bin/sudo; chmod 4755 /usr/local/bin/sudo
+
+#### Sudo compiles and installs successfully but when I try to run it I get:
+
+ effective uid is not 0, is /usr/local/bin/sudo on a file system with the
+ 'nosuid' option set or an NFS file system without root privileges?
+
+> The owner and permissions on the sudo binary appear to be OK but when
+> sudo ran, the set-user-ID bit did not have an effect. There are two
+> common causes for this. The first is that the file system the sudo
+> binary is located on is mounted with the 'nosuid' mount option, which
+> disables set-user-ID binaries. The output of the 'mount' command should
+> tell you if the file system is mounted with the 'nosuid' option. The
+> other possible cause is that sudo is installed on an NFS-mounted file
+> system that is exported without root privileges. By default, NFS file
+> systems are exported with user-ID 0 mapped to a non-privileged ID (usually
+> -2). You should be able to determine whether sudo is located on an
+> NFS-mounted filesystem by running "df \`which sudo\`".
+
+#### Sudo never gives me a chance to enter a password using PAM
+
+It just says "Sorry, try again." three times and exits.
+
+> You didn't setup PAM to work with sudo. On RedHat or Fedora Linux
+> this generally means installing the sample pam.conf file as
+> /etc/pam.d/sudo. See the example pam.conf file for hints on what
+> to use for other Linux systems.
+
+#### Sudo says my account has expired but I know it has not
+
+> If you get the following error from sudo:
+
+ Account expired or PAM config lacks an 'account' section for sudo,
+ contact your system administrator`
+
+> double-check the `/etc/shadow` file to verify that the target user
+> (for example, root) does not have the password expiration field set.
+> A common way to disable access to an account is to set the expiration
+> date to 1, such as via `usermod -e 1`. If the account is marked as
+> expired, sudo will not allow you to access it.
+>
+> If, however, the account has not expired, it is possible that the PAM
+> configuration lacks an 'account' specification. On Linux this usually
+> means you are missing a line in /etc/pam.d/sudo similar to:
+
+ account required pam_unix.so
+
+#### Sudo is configured use syslog but nothing gets logged
+
+> Make sure you have an entry in your syslog.conf file to save
+> the sudo messages (see the example syslog.conf file). The default
+> log facility is authpriv (changeable via configure or in sudoers).
+> Don't forget to send a SIGHUP to your syslogd so that it re-reads
+> its conf file. Also, remember that syslogd does *not* create
+> log files, you need to create the file before syslogd will log
+> to it (e.g.: touch /var/log/sudo).
+
+> The facility (e.g. 'auth.debug') must be separated from
+> the destination (e.g. '/var/log/auth' or '@loghost') by tabs,
+> *not* spaces. This is a common error.
+
+#### Sudo won't accept my password, even when entered correctly
+
+> If you are not using pam and your system uses shadow passwords,
+> it is possible that sudo didn't properly detect that shadow
+> passwords are in use. Take a look at the generated config.h
+> file and verify that the C function used for shadow password
+> look ups was detected. For instance, for SVR4-style shadow
+> passwords, `HAVE_GETSPNAM` should be defined (you can search for
+> the string 'shadow passwords' in config.h with your editor).
+> There is no define needed for 4.4BSD-based shadow passwords
+> which just use the standard getpw* routines.
+
+#### Can sudo use the ssh agent instead of asking for the user's password?
+
+> Not directly, but you can use a PAM module like pam_ssh_agent_auth
+> or pam_ssh for this purpose.
+
+#### I want to place the sudoers file in a directory other than /etc
+
+> Use the `--sysconfdir` option to configure. For example:
+
+ configure --sysconfdir=/dir/you/want/sudoers/in
+
+> Alternately, you can set the path in the sudo.conf file as an
+> argument to the sudoers.so plugin. For example:
+
+ Plugin sudoers_policy sudoers.so sudoers_file=/path/to/sudoers
+
+#### Can I put the sudoers file in NIS/NIS+?
+
+> There is no support for making an NIS/NIS+ map/table out of the sudoers
+> file at this time. You can distribute the sudoers file via rsync or rdist.
+> It is also possible to NFS-mount the sudoers file. If you use LDAP at your
+> site you may be interested in sudo's LDAP sudoers support, see
+> [README.LDAP.md](../README.LDAP.md) and the sudoers.ldap manual.
+
+#### I don't run sendmail, does this mean that I cannot use sudo?
+
+> No, you just need to disable mailing with a line like:
+
+ Defaults !mailerpath
+
+> in your sudoers file or run configure with the `--without-sendmail`
+> option.
+
+#### How can I make visudo use a different editor?
+
+> You can specify the editor to use in visudo in the sudoers file.
+> See the 'editor' and 'env_editor' entries in the sudoers manual.
+> The defaults can also be set at configure time using the
+> `--with-editor` and `--with-env-editor` configure options.
+
+#### Why does sudo modify the command's environment?
+
+> By default, sudo runs commands with a new, minimal environment.
+> The 'env_keep' setting in sudoers can be used to control which
+> environment variables are preserved from the invoking user's
+> environment via the 'env_keep' setting in sudoers.
+>
+> While it is possible to disable the 'env_reset' setting, which
+> will preserve all environment variables that don't match a black
+> list, doing so is strongly discouraged. See the "Command
+> environment" section of the sudoers manual for more information.
+
+#### Why does sudo reset the HOME environment variable?
+
+> Many programs use the HOME environment variable to locate
+> configuration and data files. Often, these configuration files
+> are treated as trusted input that affects how the program operates.
+> By controlling the configuration files, a user may be able to
+> cause the program to execute other commands without sudo's
+> restrictions or logging.
+>
+> Some programs perform extra checks when the real and effective
+> user-IDs differ, but because sudo runs commands with all user-IDs
+> set to the target user, these checks are insufficient.
+>
+> While it is possible to preserve the value of the HOME environment
+> variable by adding it to the 'env_keep' list in the sudoers file,
+> doing so is strongly discouraged. Users wishing to edit files
+> with sudo should run sudoedit (or sudo -e) to get their accustomed
+> editor configuration instead of invoking the editor directly.
+
+#### How can I prevent sudo from asking for a password?
+
+> To specify this on a per-user (and per-command) basis, use the
+> 'NOPASSWD' tag right before the command list in sudoers. See
+> the sudoers man page and examples/sudoers for details. To disable
+> passwords completely, add '!authenticate' to the Defaults line
+> in /etc/sudoers. You can also turn off authentication on a
+> per-user or per-host basis using a user or host-specific Defaults
+> entry in sudoers. To hard-code the global default, you can
+> configure with the `--without-passwd` option.
+
+#### The configure scripts says `no acceptable cc found in $PATH`
+
+> /usr/ucb/cc was the only C compiler that configure could find.
+> You need to tell configure the path to the 'real' C compiler
+> via the `--with-CC option`. On Solaris, the path is probably
+> something like /opt/SUNWspro/SC4.0/bin/cc. If you have gcc
+> that will also work.
+
+#### The configure scripts says "config.cache exists from another platform!"
+
+> configure caches the results of its tests in a file called
+> config.cache to make re-running configure speedy. However,
+> if you are building sudo for a different platform the results
+> in config.cache will be wrong so you need to remove the config.cache file.
+> You can do this via `rm config.cache`, or `make realclean` to also
+> remove any object files and configure temp files that are present.
+
+#### When I run 'visudo' it says "sudoers file busy, try again later."
+
+> Someone else is currently editing the sudoers file with visudo.
+
+#### When I try to use 'cd' with sudo it says "cd: command not found"
+
+> 'cd' is a shell built-in command, you can't run it as a command
+> since a child process (sudo) cannot affect the current working
+> directory of the parent (your shell).
+
+#### When I try to use 'cd' with sudo nothing happens.
+
+> Even though 'cd' is a shell built-in command, some operating systems
+> include a /usr/bin/cd command for completeness. A standalone
+> "cd' command is totally useless since a child process (cd) cannot
+> affect the current working directory of the parent (your shell).
+> Thus, `sudo cd /foo` will start a child process, change the
+> directory and immediately exit without doing anything useful.
+
+#### How can I run a command via sudo as a user other than root?
+
+> The default user sudo tries to run things as is always root, even if
+> the invoking user can only run commands as a single, specific user.
+> This may change in the future but at the present time you have to
+> work around this using the 'runas_default' option in sudoers.
+> For example, given the following sudoers rule:
+
+ bob ALL=(oracle) ALL
+
+> You can cause sudo to run all commands as 'oracle' for user 'bob'
+> with a sudoers entry like:
+
+ Defaults:bob runas_default=oracle
+
+#### When I try to run sudo via ssh, I get an error:
+
+ sudo: a terminal is required to read the password; either use the -S
+ option to read from standard input or configure an askpass helper
+
+> If sudo needs to authenticate a user, it requires access to the user's
+> terminal to disable echo so the password is not displayed to the screen.
+> The above message indicates that no terminal was present.
+
+> When running a command via ssh, a terminal is not allocated by default
+> which can cause this message. The '-t' option to ssh will force it to
+> allocate a tty. Alternately, you may be able to use the ssh-askpass
+> utility to prompt for the password if X11 forwarding is enabled and an
+> askpass helper is configured in the sudo.conf file. If you do not mind
+> your password being echoed to the screen, you may use sudo's -S option
+> to read the password from the standard input. Alternately, you may set
+> the 'visiblepw' sudoers option which will allow the password to be entered
+> even when echo cannot be disabled, though this is not recommended.
+
+#### When I try to use SSL-enabled LDAP with sudo I get an error:
+
+ unable to initialize SSL cert and key db: security library: bad database.
+ you must set TLS_CERT in /etc/ldap.conf to use SSL
+
+> On systems that use a Mozilla-derived LDAP SDK there must be a
+> certificate database in place to use SSL-encrypted LDAP connections.
+> This file is usually /var/ldap/cert8.db or /etc/ldap/cert8.db.
+> The actual number after 'cert' will vary, depending on the version
+> of the LDAP SDK that is being used. If you do not have a certificate
+> database you can either copy one from a mozilla-derived browser, such
+> as firefox, or create one using the `certutil` command. You can run
+> `certutil` as follows and press the <return> (or <enter>) key at the
+> password prompt:
+
+ # certutil -N -d /var/ldap
+
+> Enter a password which will be used to encrypt your keys.
+> The password should be at least 8 characters long,
+> and should contain at least one non-alphabetic character.
+
+ Enter new password: <return>
+ Re-enter password: <return>
+
+#### After upgrading my system, sudo_logsrvd gives the error:
+
+ X509_verify_cert: CA cert does not include key usage extension
+
+> This can happen if you are using self-signed certificates that do not
+> include the key usage extension. This error can occur if the certificates
+> were generated using OpenSSL 1.x but sudo_logsrvd now uses OpenSSL 3.x,
+> for example after a system upgrade. The x509 certificate validation in
+> OpenSSL 3.x now requires that the key usage extension be present.
+> One way to address this is to disable certificate verification in
+> sudo_logsrvd by setting the _tls_verify_ key in the `[server]` section
+> to _false_. Alternately, you can simply remove your old CA and the
+> associated certificates and create a new one using an updated
+> `/etc/ssl/openssl.cnf` file. See the sudo_logsrvd manual for more
+> information on creating self-signed certificates.
+
+#### On HP-UX, the umask setting in sudoers has no effect.
+
+> If your /etc/pam.conf file has the libpam_hpsec.so.1 session module
+> enabled, you may need to a add line like the following to pam.conf:
+> sudo session required libpam_hpsec.so.1 bypass_umask
+
+#### When I run `sudo -i shell_alias` I get "command not found"
+
+> Commands run via `sudo -i` are executed by the shell in
+> non-interactive mode. The bash shell will only parse aliases in
+> interactive mode unless the 'expand_aliases' shell option is
+> set. If you add `shopt -s expand_aliases` to your .bash_profile
+> (or .profile if using that instead) the aliases should now be
+> available to `sudo -i`.
+
+#### When I run sudo on AIX I get the following error:
+
+ setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID): Operation not permitted.
+
+> AIX's Enhanced RBAC is preventing sudo from running. To fix
+> this, add the following entry to /etc/security/privcmds (adjust
+> the path to sudo as needed) and run the setkst command as root:
+
+ /usr/local/bin/sudo:
+ accessauths = ALLOW_ALL
+ innateprivs = PV_DAC_GID,PV_DAC_R,PV_DAC_UID,PV_DAC_X,PV_FS_CHOWN,PV_PROC_PRIO,PV_NET_PORT,PV_NET_CNTL,PV_SU_UID
+ secflags = FSF_EPS
+
+#### Sudo builds without error but when I run it I get a Segmentation fault.
+
+> If you are on a Linux system, the first thing to try is to run
+> configure with the `--disable-pie` option, then `make clean` and
+> `make`. If that fixes the problem then your operating system
+> does not properly support position independent executables.
+> Send a message to sudo@sudo.ws with system details such as the
+> Linux distro, kernel version, and CPU architecture.
+
+#### When I run configure I get the following error:
+
+ dlopen present but libtool doesn't appear to support your platform.
+
+> Libtool doesn't know how to support dynamic linking on the operating
+> system you are building for. If you are cross-compiling, you need to
+> specify the operating system, not just the CPU type. For example,
+> `--host powerpc-unknown-linux`
+> instead of just:
+> `--host powerpc`
+
+#### How do you pronounce 'sudo'?
+
+> The official pronunciation is soo-doo (for su 'do'). However, an
+> alternate pronunciation, a homophone of 'pseudo', is also common.
diff --git a/docs/UPGRADE.md b/docs/UPGRADE.md
new file mode 100644
index 0000000..1e2cb5f
--- /dev/null
+++ b/docs/UPGRADE.md
@@ -0,0 +1,636 @@
+Notes on upgrading from an older release
+========================================
+
+ * Upgrading from a version prior to 1.9.15:
+
+ The sudoers plugin now uses a time stamp path name that is based
+ on the user-ID instead of the user name. For example, a time
+ stamp file that was /var/run/sudo/ts/root in sudo 1.9.14 will
+ now be /var/run/sudo/ts/0. The lecture flag file name is now
+ also based on the user-ID, which will result in users receiving
+ the sudo lecture again on upgrade to sudo 1.9.15.
+
+ * Upgrading from a version prior to 1.9.14:
+
+ Sudo now runs commands in a new pseudo-terminal by default. This
+ can prevent a malicious program run via sudo from accessing the
+ user's terminal device after the command completes.
+
+ When sudo runs a command in a new pseudo-terminal, an additional
+ process is created to monitor the command's status and pass
+ terminal control signals between the two terminals. See the
+ "Process model" subsection in the sudo manual and the description
+ of the "use_pty" option in the sudoers manual for more information.
+
+ A side effect of running the command in a new pseudo-terminal
+ is that sudo must pass input from the user's terminal to the
+ pseudo-terminal, even if the command being run does not require
+ the input. The "exec_background" option in sudoers can be used
+ to prevent this, but some screen-oriented commands may not operate
+ properly when run as a background process.
+
+ To restore the historic behavior where a command is run in the
+ user's terminal, add the following line to the sudoers file:
+
+ Defaults !use_pty
+
+ * Upgrading from a version prior to 1.9.13:
+
+ Sudo now builds AIX-style shared libraries and dynamic shared
+ objects by default instead of svr4-style. This means that the
+ default sudo plugins are now .a (archive) files that contain a
+ .so shared object file instead of bare .so files. This was done
+ to improve compatibility with the AIX Freeware ecosystem,
+ specifically, the AIX Freeware build of OpenSSL. When loading
+ a .a file as a plugin the name of the included .so file must
+ also be specified, for example /usr/libexec/sudo/sudoers.a(sudoers.so).
+
+ Sudo is still capable of loading svr4-style .so plugins and if
+ a .so file is requested, either via sudo.conf or the sudoers
+ file, and only the .a file is present, sudo will convert the
+ path from plugin.so to plugin.a(plugin.so). This ensures
+ compatibility with existing configurations. To restore the old,
+ pre-1.9.13 behavior, run configure using the --with-aix-soname=svr4
+ option.
+
+ * Upgrading from a version prior to 1.9.10:
+
+ Sudo now interprets a command line argument in sudoers that
+ begins with a '^' character as a regular expression. To start
+ a command argument with a literal '^' character, it must be
+ escaped with a backslash ('\'). This may result in a syntax
+ error after upgrading for existing sudoers rules where the command
+ line arguments begin with a '^'.
+
+ A user may now only run "sudo -U otheruser -l" if they have a
+ "sudo ALL" privilege where the RunAs user contains either "root"
+ or "otheruser". Previously, having "sudo ALL" was sufficient,
+ regardless of the RunAs user.
+
+ * Upgrading from a version prior to 1.9.9:
+
+ Sudo now runs commands with the core limit resource limit set
+ to 0 by default. While most operating systems restrict core
+ dumps of set-user-ID programs like sudo, this protection is
+ lost when sudo executes a command. By disabling core dumps by
+ default, it is possible to avoid potential security problems
+ such as those seen with the Linux logrotate utility, which could
+ interpret a core dump as a valid configuration file.
+
+ To restore the historic core dump file size behavior, add the
+ following line to the sudoers file:
+
+ Defaults rlimit_core=default
+
+ * Upgrading from a version prior to 1.9.7:
+
+ Sudo now links with OpenSSL 1.0.1 or higher by default if it
+ is present on the system unless it is explicitly disabled (via
+ `--disable-openssl`), or unless the sudo log client and server
+ code is disabled (via `--disable-log-client` and `--disable-log-server`).
+ As a result, the sudo log server (and the client built into the
+ sudoers plugin) now support TLS connections by default.
+
+ * Upgrading from a version prior to 1.9.3:
+
+ Due to the addition of the CHROOT and CWD options, it is no
+ longer possible to declare an alias with one of those names.
+ If a sudoers file has an alias with one of those names, sudo
+ and visudo will report a syntax error with a message like
+ "syntax error: unexpected CHROOT, expecting ALIAS".
+
+ Starting with version 1.9.3, sudoers rules must end in either
+ a newline or the end-of-file. This makes it possible to provide
+ better error messages. Previously, it was possible to include
+ multiple rules on a single line, separated by white space.
+
+ Starting with version 1.9.3, sudo will attempt to recover from
+ a syntax error in the sudoers file by discarding the portion
+ of the line that contains the error until the end of the line.
+ To restore the historic behavior of refusing to run when a
+ syntax error is encountered, add `error_recovery=false` as a
+ plugin option in sudo.conf for the "sudoers_audit" plugin, (or
+ "sudoers_policy" if there is no "sudoers_audit" plugin configured).
+
+ * Upgrading from a version prior to 1.9.1:
+
+ Starting with version 1.9.1, sudoers plugin arguments in sudo.conf
+ should be specified for the "sudoers_audit" plugin, not
+ "sudoers_policy". This is because the sudoers file is now
+ opened and parsed by the "sudoers_audit" plugin. Previously,
+ this was done by the "sudoers_policy" plugin. The use of an
+ audit plugin makes it possible for the sudoers module to detect
+ when a command has been rejected by an approval plugin and only
+ log commands that are allowed by both policy and approval
+ plugins.
+
+ * Upgrading from a version prior to 1.8.30:
+
+ Starting with version 1.8.30, sudo will no longer allow commands
+ to be run as a user or group ID that is not in the password or
+ group databases by default. Previously, sudo would always allow
+ unknown user or group IDs if the sudoers entry permitted it,
+ including via the _ALL_ alias. The old behavior can be restored
+ by setting the new "allow_unknown_runas_id" Defaults setting
+ in the sudoers file.
+
+ * Upgrading from a version prior to 1.8.29:
+
+ Starting with version 1.8.29, if the umask is explicitly set
+ in sudoers, that value is used regardless of the umask specified
+ by PAM or login.conf. However, if the umask is not explicitly
+ set in sudoers, PAM, or login.conf may now override the default
+ sudoers umask. Previously, the sudoers umask always overrode
+ the umask set by PAM, which was not the documented behavior.
+
+ * Upgrading from a version prior to 1.8.28:
+
+ Starting with version 1.8.28, sudo stores the signal that caused
+ a command to be suspended or resumed as a string in the I/O log
+ timing file. The version of sudoreplay included with sudo
+ 1.8.28 can process either type of I/O log file but older versions
+ of sudoreplay are unable to replay the newer logs.
+
+ Starting with version 1.8.28, sudoedit honors the umask and
+ umask_override settings in sudoers. Previously, the user's
+ umask was used as-is.
+
+ * Upgrading from a version prior to 1.8.26:
+
+ Starting with version 1.8.26, sudo no long sets the USERNAME
+ environment variable when running commands. This is a non-standard
+ environment variable that was set on some older Linux systems.
+ Sudo still sets the LOGNAME, USER, and, on AIX systems, LOGIN
+ environment variables.
+
+ Handling of the LOGNAME, USER (and on AIX, LOGIN) environment
+ variables has changed slightly in version 1.8.26. Sudo now
+ treats those variables as a single unit. This means that if
+ one variable is preserved or removed from the environment using
+ env_keep, env_check, or env_delete, the others are too.
+
+ * Upgrading from a version prior to 1.8.23:
+
+ In sudo 1.8.23 the "sudoers2ldif" script and the `visudo -x`
+ functionality has been superseded by the "cvtsudoers" utility.
+ The cvtsudoers utility is intended to be a drop-in replacement
+ for "sudoers2ldif". Because it uses the same parser as sudo
+ and visudo, cvtsudoers can perform a more accurate conversion
+ than sudoers2ldif could.
+
+ To convert a sudoers file to JSON, the format option must be
+ specified. For example, instead of:
+
+ visudo -f sudoers_file -x output_file
+
+ one would use:
+
+ cvtsudoers -f json -o output_file sudoers_file
+
+ Unlike "visudo -x", "cvtsudoers" reads from the standard input
+ by default. Also, the base DN may be specified on the command
+ line, if desired, using the -b option.
+
+ * Upgrading from a version prior to 1.8.20:
+
+ Due to the addition of the TIMEOUT, NOTBEFORE, and NOTAFTTER
+ options, it is no longer possible to declare an alias with one
+ of those names. If a sudoers file has an alias with one of
+ those names, sudo, and visudo will report a syntax error with a
+ message like "syntax error: unexpected TIMEOUT, expecting ALIAS".
+
+ Prior to version 1.8.20, when log_input, log_output, or use_pty
+ were enabled, if any of the standard input, output, or error
+ were not connected to a terminal, sudo would use a pipe. The
+ pipe allows sudo to interpose itself between the old standard
+ input, output, or error and log the contents. Beginning with
+ version 1.8.20, a pipe is only used when I/O logging is enabled.
+ If use_pty is set without log_input or log_output, no pipe will
+ be used. Additionally, if log_input is set without log_output,
+ a pipe is only used for the standard input. Likewise, if
+ log_output is set without log_input, a pipe is only used for
+ the standard output and standard error. This results in a
+ noticeable change in behavior if the use_pty flag is set and no
+ terminal is present when running commands such as scripts that
+ execute other commands asynchronously (in the background).
+ Previously, sudo would exit immediately, causing background
+ commands to terminate with a broken pipe if they attempt to
+ write to the standard output or standard error. As of version
+ 1.8.20, a pipe will not be used in this case so the command
+ will no longer be terminated.
+
+ * Upgrading from a version prior to 1.8.16:
+
+ When editing files with sudoedit, files in a directory that is
+ writable by the invoking user may no longer be edited by default.
+ Also, sudoedit will refuse to follow a symbolic link in the
+ path to be edited if that directory containing the link is
+ writable by the user. This behavior can be disabled by negating
+ the sudoedit_checkdir sudoers option, which is now enabled by
+ default.
+
+ * Upgrading from a version prior to 1.8.15:
+
+ Prior to version 1.8.15, when env_reset was enabled (the default)
+ and the -s option was not used, the SHELL environment variable
+ was set to the shell of the invoking user. In 1.8.15 and above,
+ when env_reset is enabled and the -s option is not used, SHELL
+ is set based on the target user.
+
+ When editing files with sudoedit, symbolic links will no longer
+ be followed by default. The old behavior can be restored by
+ enabling the sudoedit_follow option in sudoers or on a per-command
+ basis with the FOLLOW and NOFOLLOW tags.
+
+ Prior to version 1.8.15, groups listed in sudoers that were not
+ found in the system group database were passed to the group
+ plugin, if any. Starting with 1.8.15, only groups of the form
+ %:group are resolved via the group plugin by default. The old
+ behavior can be restored by using the always_query_group_plugin
+ sudoers option.
+
+ Locking of the time stamp file has changed in sudo 1.8.15.
+ Previously, the user's entire time stamp file was locked while
+ retrieving and updating a time stamp record. Now, only a single
+ record, specific to the tty or parent process ID, is locked.
+ This lock is held while the user enters their password. If
+ sudo is suspended at the password prompt (or run in the
+ background), the lock is dropped until sudo is resumed, at which
+ point it will be reacquired. This allows sudo to be used in a
+ pipeline even when a password is required--only one instance
+ of sudo will prompt for a password.
+
+ * Upgrading from a version prior to 1.8.14:
+
+ On HP-UX, sudo will no longer check for "plugin.sl" if "plugin.so"
+ is specified but does not exist. This was a temporary hack for
+ backward compatibility with Sudo 1.8.6 and below when the
+ plugin path name was not listed in sudo.conf. A plugin path
+ name that explicitly ends in ".sl" will still work as expected.
+
+ * Upgrading from a version prior to 1.8.12:
+
+ On Solaris, sudo is now able to determine the NIS domain name.
+ As a result, if you had previously been using netgroups that
+ do not include the domain, you will need to either set the
+ domain in the entry or leave the domain part of the tuple blank.
+
+ For example, the following will no longer work:
+
+ my-hosts (foo,-,-) (bar,-,-) (baz,-,-)
+
+ and should be changed to:
+
+ my-hosts (foo,-,) (bar,-,) (baz,-,)
+
+ * Upgrading from a version prior to 1.8.10:
+
+ The time stamp file format has changed in sudo 1.8.10. There
+ is now a single time stamp file for each user, even when tty-based
+ time stamps are used. Each time stamp file may contain multiple
+ records to support tty-based time stamps as well as multiple
+ authentication users. On systems that support it, monotonic
+ time is stored instead of wall clock time. As a result, it is
+ important that the time stamp files not persist when the system
+ reboots. For this reason, the default location for the time
+ stamp files has changed back to a directory located in `/var/run`.
+ Systems that do not have `/var/run` (e.g. AIX) or that do not clear
+ it on boot (e.g. HP-UX) will need to clear the time stamp
+ directory via a start up script. Such a script is installed by
+ default on AIX and HP-UX systems.
+
+ Because there is now a single time stamp file per user, the -K
+ option will remove all of the user's time stamps, not just the
+ time stamp for the current terminal.
+
+ Lecture status is now stored separately from the time stamps in a
+ separate directory: `/var/db/sudo/lectured`, `/var/lib/sudo/lectured`
+ or `/var/adm/sudo/lectured` depending on what is present on the system.
+
+ LDAP-based sudoers now uses a default search filter of
+ (objectClass=sudoRole) for more efficient queries. It is
+ possible to disable the default search filter by specifying
+ SUDOERS_SEARCH_FILTER in ldap.conf but omitting a value.
+
+ * Upgrading from a version prior to 1.8.7:
+
+ Sudo now stores its libexec files in a "sudo" sub-directory
+ instead of in libexec itself. For backward compatibility, if
+ the plugin is not found in the default plugin directory, sudo
+ will check the parent directory default directory ends in `/sudo`.
+
+ The default sudo plugins now all use the .so extension, regardless
+ of the extension used by system shared libraries. For backward
+ compatibility, sudo on HP-UX will also search for a plugin with
+ an .sl extension if the .so version is not found.
+
+ Handling of users belonging to a large number of groups has
+ changed. Previously, sudo would only use the group list from
+ the kernel unless the system_group plugin was enabled in sudoers.
+ Now, sudo will query the groups database if the user belongs
+ to the maximum number of groups supported by the kernel. See
+ the group_source and max_groups settings in the sudo.conf manual
+ for details.
+
+ * Upgrading from a version prior to 1.8.2:
+
+ When matching Unix groups in the sudoers file, sudo will now
+ match based on the name of the group as it appears in sudoers
+ instead of the group-ID. This can substantially reduce the
+ number of group lookups for sudoers files that contain a large
+ number of groups. There are a few side effects of this change.
+
+ 1) Unix groups with different names but the same group-ID are
+ can no longer be used interchangeably. Sudo will look up all
+ of a user's groups by group-ID and use the resulting group
+ names when matching sudoers entries. If there are multiple
+ groups with the same ID, the group name returned by the
+ system getgrgid() library function is the name that will be
+ used when matching sudoers entries.
+
+ 2) Unix group names specified in the sudoers file that are
+ longer than the system maximum will no longer match. For
+ instance, if there is a Unix group "fireflie" on a system
+ where group names are limited to eight characters, "%fireflies"
+ in sudoers will no longer match "fireflie". Previously, a
+ lookup by name of the group "fireflies" would have matched
+ the "fireflie" group on most systems.
+
+ The legacy group matching behavior may be restored by enabling
+ the match_group_by_gid Defaults option in sudoers available
+ in sudo 1.8.18 and higher.
+
+ * Upgrading from a version prior to 1.8.1:
+
+ Changes in the sudoers parser could result in parse errors for
+ existing sudoers file. These changes cause certain erroneous
+ entries to be flagged as errors where before they allowed.
+ Changes include:
+
+ Combining multiple Defaults entries with a backslash. E.g.
+
+ Defaults set_path \
+ Defaults syslog
+
+ which should be:
+
+ Defaults set_path
+ Defaults syslog
+
+ Also, double-quoted strings with a missing end-quote are now
+ detected and result in an error. Previously, text starting a
+ double quote and ending with a newline was ignored. E.g.
+
+ Defaults set_path"foo
+
+ In previous versions of sudo, the _"foo_ portion would have
+ been ignored.
+
+ To avoid problems, sudo 1.8.1's `make install` will not install
+ a new sudo binary if the existing sudoers file has errors.
+
+ In Sudo 1.8.1 the _noexec_ functionality has moved out of the
+ sudoers policy plugin and into the sudo front-end. As a result,
+ the path to the noexec file is now specified in the sudo.conf
+ file instead of the sudoers file. If you have a sudoers file
+ that uses the "noexec_file" option, you will need to move the
+ definition to the sudo.conf file instead.
+
+ Old style in `/etc/sudoers`:
+
+ Defaults noexec_file=/usr/local/libexec/sudo_noexec.so
+
+ New style in `/etc/sudo.conf`:
+
+ Path noexec /usr/local/libexec/sudo_noexec.so
+
+ * Upgrading from a version prior to 1.8.0:
+
+ Starting with version 1.8.0, sudo uses a modular framework to
+ support policy and I/O logging plugins. The default policy
+ plugin is "sudoers" which provides the traditional sudoers
+ evaluation and I/O logging. Plugins are typically located in
+ `/usr/libexec` or `/usr/local/libexec`, though this is system-dependent.
+ The sudoers plugin is named "sudoers.so" on most systems.
+
+ The sudo.conf file, usually stored in `/etc`, is used to configure
+ plugins. This file is optional--if no plugins are specified
+ in sudo.conf, the "sudoers" plugin is used. See the example
+ sudo.conf file in the docs directory or refer to the updated
+ sudo manual to see how to configure sudo.conf.
+
+ The "askpass" setting has moved from the sudoers file to the
+ sudo.conf file. If you have a sudoers file that uses the
+ "askpass" option, you will need to move the definition to the
+ sudo.conf file.
+
+ Old style in `/etc/sudoers`:
+
+ Defaults askpass=/usr/X11R6/bin/ssh-askpass
+
+ New style in `/etc/sudo.conf`:
+
+ Path askpass /usr/X11R6/bin/ssh-askpass
+
+ * Upgrading from a version prior to 1.7.5:
+
+ Sudo 1.7.5 includes an updated LDAP schema with support for
+ the sudoNotBefore, sudoNotAfter, and sudoOrder attributes.
+
+ The sudoNotBefore and sudoNotAfter attribute support is only
+ used when the SUDOERS_TIMED setting is enabled in ldap.conf.
+ If enabled, those attributes are used directly when constructing
+ an LDAP filter. As a result, your LDAP server must have the
+ updated schema if you want to use sudoNotBefore and sudoNotAfter.
+
+ The sudoOrder support does not affect the LDAP filter sudo
+ constructs and so there is no need to explicitly enable it in
+ ldap.conf. If the sudoOrder attribute is not present in an
+ entry, a value of 0 is used. If no entries contain sudoOrder
+ attributes, the results are in whatever order the LDAP server
+ returns them, as in past versions of sudo.
+
+ Older versions of sudo will simply ignore the new attributes
+ if they are present in an entry. There are no compatibility
+ problems using the updated schema with older versions of sudo.
+
+ * Upgrading from a version prior to 1.7.4:
+
+ Starting with sudo 1.7.4, the time stamp files have moved from
+ `/var/run/sudo` to either `/var/db/sudo`, `/var/lib/sudo`, or
+ `/var/adm/sudo`. The directories are checked for existence in
+ that order. This prevents users from receiving the sudo lecture
+ every time the system reboots. Time stamp files older than the
+ boot time are ignored on systems where it is possible to determine
+ this.
+
+ Additionally, the tty_tickets sudoers option is now enabled by
+ default. To restore the old behavior (single time stamp per user),
+ add a line like:
+
+ Defaults !tty_tickets
+
+ to sudoers or use the `--without-tty-tickets` configure option.
+
+ The HOME and MAIL environment variables are now reset based on the
+ target user's password database entry when the env_reset sudoers option
+ is enabled (which is the case in the default configuration). Users
+ wishing to preserve the original values should use a sudoers entry like:
+
+ Defaults env_keep += HOME
+
+ to preserve the old value of HOME and
+
+ Defaults env_keep += MAIL
+
+ to preserve the old value of MAIL.
+
+ Preserving HOME has security implications since many programs
+ use it when searching for configuration files. Adding HOME to
+ env_keep may enable a user to run unrestricted commands via sudo.
+
+ The default syslog facility has changed from "local2" to "authpriv"
+ (or "auth" if the operating system doesn't have "authpriv").
+ The `--with-logfac` configure option can be used to change this
+ or it can be changed in the sudoers file.
+
+ * Upgrading from a version prior to 1.7.0:
+
+ Starting with sudo 1.7.0, comments in the sudoers file must not
+ have a digit or minus sign immediately after the comment character
+ ('#'). Otherwise, the comment may be interpreted as a user or
+ group-ID.
+
+ When sudo is build with LDAP support the `/etc/nsswitch.conf` file is
+ now used to determine the sudoers sea ch order. sudo will default to
+ only using `/etc/sudoers` unless `/etc/nsswitch.conf` says otherwise.
+ This can be changed with an nsswitch.conf line, e.g.:
+
+ sudoers: ldap files
+
+ Would case LDAP to be searched first, then the sudoers file.
+ To restore the pre-1.7.0 behavior, run configure with the
+ `--with-nsswitch=no` flag.
+
+ Sudo now ignores user .ldaprc files as well as system LDAP defaults.
+ All LDAP configuration is now in `/etc/ldap.conf` (or whichever file
+ was specified by configure's `--with-ldap-conf-file` option).
+ If you are using TLS, you may now need to specify:
+
+ tls_checkpeer no
+
+ in sudo's ldap.conf unless ldap.conf references a valid certificate
+ authority file(s).
+
+ * Upgrading from a version prior to 1.6.9:
+
+ Starting with sudo 1.6.9, if an OS supports a modular authentication
+ method such as PAM, it will be used by default by configure.
+
+ Environment variable handling has changed significantly in sudo
+ 1.6.9. Prior to version 1.6.9, sudo would preserve the user's
+ environment, pruning out potentially dangerous variables.
+ Beginning with sudo 1.6.9, the environment is reset to a default
+ set of values with only a small number of "safe" variables
+ preserved. To preserve specific environment variables, add
+ them to the "env_keep" list in sudoers. E.g.
+
+ Defaults env_keep += "EDITOR"
+
+ The old behavior can be restored by negating the "env_reset"
+ option in sudoers. E.g.
+
+ Defaults !env_reset
+
+ There have also been changes to how the "env_keep" and
+ "env_check" options behave.
+
+ Prior to sudo 1.6.9, the TERM and PATH environment variables
+ would always be preserved even if the env_keep option was
+ redefined. That is no longer the case. Consequently, if
+ env_keep is set with "=" and not simply appended to (i.e. using
+ "+="), PATH and TERM must be explicitly included in the list
+ of environment variables to keep. The LOGNAME, SHELL, USER,
+ and USERNAME environment variables are still always set.
+
+ Additionally, the env_check setting previously had no effect
+ when env_reset was set (which is now on by default). Starting
+ with sudo 1.6.9, environment variables listed in env_check are
+ also preserved in the env_reset case, provided that they do not
+ contain a '/' or '%' character. It is not necessary to also
+ list a variable in env_keep--having it in env_check is sufficient.
+
+ The default lists of variables to be preserved and/or checked
+ are displayed when sudo is run by root with the -V flag.
+
+ * Upgrading from a version prior to 1.6.8:
+
+ Prior to sudo 1.6.8, if `/var/run` did not exist, sudo would put
+ the time stamp files in `/tmp/.odus`. As of sudo 1.6.8, the
+ time stamp files will be placed in `/var/adm/sudo` or `/usr/adm/sudo`
+ if there is no `/var/run directory`. This directory will be
+ created if it does not already exist.
+
+ Previously, a sudoers entry that explicitly prohibited running
+ a command as a certain user did not override a previous entry
+ allowing the same command. This has been fixed in sudo 1.6.8
+ such that the last match is now used (as it is documented).
+ Hopefully no one was depending on the previous (buggy) behavior.
+
+ * Upgrading from a version prior to 1.6:
+
+ As of sudo 1.6, parsing of runas entries and the NOPASSWD tag
+ has changed. Prior to 1.6, a runas specifier applied only to
+ a single command directly following it. Likewise, the NOPASSWD
+ tag only allowed the command directly following it to be run
+ without a password. Starting with sudo 1.6, both the runas
+ specifier and the NOPASSWD tag are "sticky" for an entire
+ command list. So, given the following line in sudo < 1.6
+
+ millert ALL=(daemon) NOPASSWD:/usr/bin/whoami,/bin/ls
+
+ millert would be able to run `/usr/bin/whoami` as user daemon
+ without a password and `/bin/ls` as root with a password.
+
+ As of sudo 1.6, the same line now means that millert is able
+ to run run both `/usr/bin/whoami` and `/bin/ls` as user daemon
+ without a password. To expand on this, take the following
+ example:
+
+ millert ALL=(daemon) NOPASSWD:/usr/bin/whoami, (root) /bin/ls, \
+ /sbin/dump
+
+ millert can run `/usr/bin/whoami` as daemon and `/bin/ls` and
+ `/sbin/dump` as root. No password need be given for either
+ command. In other words, the "(root)" sets the default runas
+ user to root for the rest of the list. If we wanted to require
+ a password for `/bin/ls` and `/sbin/dump` the line could be written
+ as:
+
+ millert ALL=(daemon) NOPASSWD:/usr/bin/whoami, \
+ (root) PASSWD:/bin/ls, /sbin/dump
+
+ Additionally, sudo now uses a per-user time stamp directory
+ instead of a time stamp file. This allows tty time stamps to
+ simply be files within the user's time stamp dir. For the
+ default, non-tty case, the time stamp on the directory itself
+ is used.
+
+ Also, the temporary file used by visudo is now `/etc/sudoers.tmp`
+ since some versions of vipw on systems with shadow passwords use
+ `/etc/stmp` for the temporary shadow file.
+
+ * Upgrading from a version prior to 1.5:
+
+ By default, sudo expects the sudoers file to be mode 0440 and
+ to be owned by user and group 0. This differs from version 1.4
+ and below which expected the sudoers file to be mode 0400 and
+ to be owned by root. Doing a `make install` will set the sudoers
+ file to the new mode and group. If sudo encounters a sudoers
+ file with the old permissions it will attempt to update it to
+ the new scheme. You cannot, however, use a sudoers file with
+ the new permissions with an old sudo binary. It is suggested
+ that if have a means of distributing sudo you distribute the
+ new binaries first, then the new sudoers file (or you can leave
+ sudoers as is and sudo will fix the permissions itself as long
+ as sudoers is on a local file system).
diff --git a/docs/cvtsudoers.man.in b/docs/cvtsudoers.man.in
new file mode 100644
index 0000000..401996e
--- /dev/null
+++ b/docs/cvtsudoers.man.in
@@ -0,0 +1,1391 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2018, 2021-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.TH "CVTSUDOERS" "1" "January 16, 2023" "Sudo @PACKAGE_VERSION@" "General Commands Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBcvtsudoers\fR
+\- convert between sudoers file formats
+.SH "SYNOPSIS"
+.HP 11n
+\fBcvtsudoers\fR
+[\fB\-ehMpV\fR]
+[\fB\-b\fR\ \fIdn\fR]
+[\fB\-c\fR\ \fIconf_file\fR]
+[\fB\-d\fR\ \fIdeftypes\fR]
+[\fB\-f\fR\ \fIoutput_format\fR]
+[\fB\-i\fR\ \fIinput_format\fR]
+[\fB\-I\fR\ \fIincrement\fR]
+[\fB\-l\fR\ \fIlog_file\fR]
+[\fB\-m\fR\ \fIfilter\fR]
+[\fB\-o\fR\ \fIoutput_file\fR]
+[\fB\-O\fR\ \fIstart_point\fR]
+[\fB\-P\fR\ \fIpadding\fR]
+[\fB\-s\fR\ \fIsections\fR]
+[\fIinput_file\ ...\fR]
+.SH "DESCRIPTION"
+The
+\fBcvtsudoers\fR
+utility accepts one or more security policies in either
+\fIsudoers\fR
+or LDIF format as input, and generates a single
+policy of the specified format as output.
+The default input format is
+\fIsudoers.\fR
+The default output format is LDIF.
+It is only possible to convert a policy file that is syntactically correct.
+.PP
+If no
+\fIinput_file\fR
+is specified, or if it is
+\(oq-\(cq,
+the policy is read from the standard input.
+Input files may be optionally prefixed with a host name followed by a colon
+(\(oq:\&\(cq)
+to make the policy rules specific to a host when merging multiple files.
+By default, the result is written to the standard output.
+.PP
+The options are as follows:
+.TP 8n
+\fB\-b\fR \fIdn\fR, \fB\--base\fR=\fIdn\fR
+The base DN (distinguished name) that will be used when performing
+LDAP queries.
+Typically this is of the form
+\(lqou=SUDOers,dc=my-domain,dc=com\(rq
+for the domain my-domain.com.
+If this option is not specified, the value of the
+\fRSUDOERS_BASE\fR
+environment variable will be used instead.
+Only necessary when converting to LDIF format.
+.TP 8n
+\fB\-c\fR \fIconf_file\fR, \fB\--config\fR=\fIconf_file\fR
+Specify the path to the configuration file.
+Defaults to
+\fI@sysconfdir@/cvtsudoers.conf\fR.
+.TP 8n
+\fB\-d\fR \fIdeftypes\fR, \fB\--defaults\fR=\fIdeftypes\fR
+Only convert
+\fIDefaults\fR
+entries of the specified types.
+One or more
+\fIDefaults\fR
+types may be specified, separated by a comma
+(\(oq\&,\(cq).
+The supported types are:
+.PP
+.RS 8n
+.PD 0
+.TP 9n
+all
+All Defaults entries.
+.PD
+.TP 9n
+global
+Global Defaults entries that are applied regardless of
+user, runas, host, or command.
+.TP 9n
+user
+Per-user Defaults entries.
+.TP 9n
+runas
+Per-runas user Defaults entries.
+.TP 9n
+host
+Per-host Defaults entries.
+.TP 9n
+command
+Per-command Defaults entries.
+.PP
+See the
+\fBDefaults\fR
+section in
+sudoers(@mansectform@)
+for more information.
+.sp
+If the
+\fB\-d\fR
+option is not specified, all
+\fIDefaults\fR
+entries will be converted.
+.RE
+.TP 8n
+\fB\-e\fR, \fB\--expand-aliases\fR
+Expand aliases in
+\fIinput_file\fR.
+Aliases are preserved by default when the output
+\fIformat\fR
+is JSON or sudoers.
+.TP 8n
+\fB\-f\fR \fIoutput_format\fR, \fB\--output-format\fR=\fIoutput_format\fR
+Specify the output format (case-insensitive).
+The following formats are supported:
+.PP
+.RS 8n
+.PD 0
+.TP 9n
+CSV
+CSV (comma-separated value) files are often used by spreadsheets
+and report generators.
+See
+\fICSV output format\fR
+for more details.
+.PD
+.TP 9n
+JSON
+JSON (JavaScript Object Notation) files are usually easier for
+third-party applications to consume than the traditional
+\fIsudoers\fR
+format.
+The various values have explicit types which removes much of the
+ambiguity of the
+\fIsudoers\fR
+format.
+See
+\fIJSON output format\fR
+for more details.
+.TP 9n
+LDIF
+LDIF (LDAP Data Interchange Format) files can be imported into an LDAP
+server for use with
+sudoers.ldap(@mansectform@).
+.sp
+Conversion to LDIF has the following limitations:
+.PP
+.RS 9n
+.PD 0
+.TP 3n
+\fB\(bu\fR
+Command, host, runas, and user-specific Defaults lines cannot be
+translated as they don't have an equivalent in the sudoers LDAP schema.
+.PD
+.TP 3n
+\fB\(bu\fR
+Command, host, runas, and user aliases are not supported by the
+sudoers LDAP schema so they are expanded during the conversion.
+.PD 0
+.PP
+.RE
+.PD
+.TP 9n
+sudoers
+Traditional sudoers format.
+A new sudoers file will be reconstructed from the parsed input file.
+Comments are not preserved and data from any include files will be
+output inline.
+.PD 0
+.PP
+.RE
+.PD
+.TP 8n
+\fB\--group-file\fR=\fIfile\fR
+When the
+\fB\-M\fR
+option is also specified, perform group queries using
+\fIfile\fR
+instead of the system group database.
+.TP 8n
+\fB\-h\fR, \fB\--help\fR
+Display a short help message to the standard output and exit.
+.TP 8n
+\fB\-i\fR \fIinput_format\fR, \fB\--input-format\fR=\fIinput_format\fR
+Specify the input format.
+The following formats are supported:
+.PP
+.RS 8n
+.PD 0
+.TP 9n
+LDIF
+LDIF (LDAP Data Interchange Format) files can be exported from an LDAP
+server to convert security policies used by
+sudoers.ldap(@mansectform@).
+If a base DN (distinguished name) is specified, only sudoRole objects
+that match the base DN will be processed.
+Not all sudoOptions specified in a sudoRole can be translated from
+LDIF to sudoers format.
+.PD
+.TP 9n
+sudoers
+Traditional sudoers format.
+This is the default input format.
+.PD 0
+.PP
+.RE
+.PD
+.TP 8n
+\fB\-I\fR \fIincrement\fR, \fB\--increment\fR=\fIincrement\fR
+When generating LDIF output, increment each sudoOrder attribute by
+the specified number.
+Defaults to an increment of 1.
+.TP 8n
+\fB\-l\fR \fIlog_file\fR, \fB\--logfile\fR=\fIlog_file\fR
+Log conversion warnings to
+\fIlog_file\fR
+instead of to the standard error.
+This is particularly useful when merging multiple
+\fIsudoers\fR
+files, which can generate a large number of warnings.
+.TP 8n
+\fB\-m\fR \fIfilter\fR, \fB\--match\fR=\fIfilter\fR
+Only output rules that match the specified
+\fIfilter\fR.
+A
+\fIfilter\fR
+expression is made up of one or more
+\fBkey =\fR \fIvalue\fR
+pairs, separated by a comma
+(\(oq\&,\(cq).
+The
+\fBkey\fR
+may be
+\(lqcmnd\(rq
+(or \(lqcmd\(rq),
+\(lqhost\(rq,
+\(lqgroup\(rq,
+or
+\(lquser\(rq.
+For example,
+\fBuser\fR = \fIoperator\fR
+or
+\fBhost\fR = \fIwww\fR.
+An upper-case
+\fICmnd_Alias\fR,
+\fIHost_alias\fR,
+or
+\fIUser_Alias\fR
+may be specified as the
+\(lqcmnd\(rq,
+\(lqhost\(rq,
+or
+\(lquser\(rq.
+.sp
+A matching
+\fIsudoers\fR
+rule may also include users, groups, and hosts that are not part of the
+\fIfilter\fR.
+This can happen when a rule includes multiple users, groups, or hosts.
+To prune out any non-matching user, group, or host from the rules, the
+\fB\-p\fR
+option may be used.
+.sp
+By default, the password and group databases are not consulted when matching
+against the filter so the users and groups do not need to be present
+on the local system (see the
+\fB\-M\fR
+option).
+Only aliases that are referenced by the filtered policy rules will
+be displayed.
+.TP 8n
+\fB\-M\fR, \fB\--match-local\fR
+When the
+\fB\-m\fR
+option is also specified, use password and group database information
+when matching users and groups in the filter.
+Only users and groups in the filter that exist on the local system will match,
+and a user's groups will automatically be added to the filter.
+If the
+\fB\-M\fR
+is
+\fInot\fR
+specified, users and groups in the filter do not need to exist on the
+local system, but all groups used for matching must be explicitly listed
+in the filter.
+.TP 8n
+\fB\-o\fR \fIoutput_file\fR, \fB\--output\fR=\fIoutput_file\fR
+Write the converted output to
+\fIoutput_file\fR.
+If no
+\fIoutput_file\fR
+is specified, or if it is
+\(oq-\(cq,
+the converted
+\fIsudoers\fR
+policy will be written to the standard output.
+.TP 8n
+\fB\-O\fR \fIstart_point\fR, \fB\--order-start\fR=\fIstart_point\fR
+When generating LDIF output, use the number specified by
+\fIstart_point\fR
+in the sudoOrder attribute of the first sudoRole object.
+Subsequent sudoRole object use a sudoOrder value generated by adding an
+\fIincrement\fR,
+see the
+\fB\-I\fR
+option for details.
+Defaults to a starting point of 1.
+A starting point of 0 will disable the generation of sudoOrder
+attributes in the resulting LDIF file.
+.TP 8n
+\fB\--passwd-file\fR=\fIfile\fR
+When the
+\fB\-M\fR
+option is also specified, perform passwd queries using
+\fIfile\fR
+instead of the system passwd database.
+.TP 8n
+\fB\-p\fR, \fB\--prune-matches\fR
+When the
+\fB\-m\fR
+option is also specified,
+\fBcvtsudoers\fR
+will prune out non-matching users, groups, and hosts from
+matching entries.
+.TP 8n
+\fB\-P\fR \fIpadding\fR, \fB\--padding\fR=\fIpadding\fR
+When generating LDIF output, construct the initial sudoOrder value by
+concatenating
+\fIorder_start\fR
+and
+\fIincrement\fR,
+padding the
+\fIincrement\fR
+with zeros until it consists of
+\fIpadding\fR
+digits.
+For example, if
+\fIorder_start\fR
+is 1027,
+\fIpadding\fR
+is 3, and
+\fIincrement\fR
+is 1, the value of sudoOrder for the first entry will be 1027000,
+followed by 1027001, 1027002, etc.
+If the number of sudoRole entries is larger than the padding would allow,
+\fBcvtsudoers\fR
+will exit with an error.
+By default, no padding is performed.
+.TP 8n
+\fB\-s\fR \fIsections\fR, \fB\--suppress\fR=\fIsections\fR
+Suppress the output of specific
+\fIsections\fR
+of the security policy.
+One or more section names may be specified, separated by a comma
+(\(oq\&,\(cq).
+The supported section name are:
+\fBdefaults\fR,
+\fBaliases\fR
+and
+\fBprivileges\fR
+(which may be shortened to
+\fBprivs\fR).
+.TP 8n
+\fB\-V\fR, \fB\--version\fR
+Print the
+\fBcvtsudoers\fR
+and
+\fIsudoers\fR
+grammar versions and exit.
+.SS "Merging multiple files"
+When multiple input files are specified,
+\fBcvtsudoers\fR
+will attempt to merge them into a single policy file.
+It is assumed that user and group names are consistent among
+the policy files to be merged.
+For example, user
+\(lqbob\(rq
+on one host is the same as user
+\(lqbob\(rq
+on another host.
+.PP
+When merging policy files, it is possible to prefix the input file name
+with a host name, separated by a colon
+(\(oq:\&\(cq).
+When the files are merged, the host name will be used to restrict
+the policy rules to that specific host where possible.
+.PP
+The merging process is performed as follows:
+.TP 3n
+\fB\(bu\fR
+Each input file is parsed into internal sudoers data structures.
+.TP 3n
+\fB\(bu\fR
+Aliases are merged and renamed as necessary to avoid conflicts.
+In the event of a conflict, the first alias found is left as-is and
+subsequent aliases of the same name are renamed with a numeric suffix
+separated with a underscore
+(\(oq_\(cq).
+For example, if there are two different aliases named
+\fRSERVERS\fR,
+the first will be left as-is and the second will be renamed
+\fRSERVERS_1\fR.
+References to the renamed alias are also updated in the policy file.
+Duplicate aliases (those with identical contents) are pruned.
+.TP 3n
+\fB\(bu\fR
+Defaults settings are merged and duplicates are removed.
+If there are conflicts in the Defaults settings, a warning is emitted for
+each conflict.
+If a host name is specified with the input file,
+\fBcvtsudoers\fR
+will change the global Defaults settings in that file to be host-specific.
+A warning is emitted for command, user, or runas-specific Defaults settings
+which cannot be made host-specific.
+.TP 3n
+\fB\(bu\fR
+Per-user rules are merged and duplicates are removed.
+If a host name is specified with the input file,
+\fBcvtsudoers\fR
+will change rules that specify a host name of
+\fBALL\fR
+to the host name associated with the policy file being merged.
+The merging of rules is currently fairly simplistic but will be
+improved in a later release.
+.PP
+It is possible to merge policy files with differing formats.
+.SS "The cvtsudoers.conf file"
+Options in the form
+\(lqkeyword = value\(rq
+may also be specified in a configuration file,
+\fI@sysconfdir@/cvtsudoers.conf\fR
+by default.
+The following keywords are recognized:
+.TP 6n
+\fBdefaults =\fR \fIdeftypes\fR
+See the description of the
+\fB\-d\fR
+command line option.
+.TP 6n
+\fBexpand_aliases =\fR \fIyes\fR | \fIno\fR
+See the description of the
+\fB\-e\fR
+command line option.
+.TP 6n
+\fBgroup_file =\fR \fIfile\fR
+See the description of the
+\fB\--group-file\fR
+command line option.
+.TP 6n
+\fBinput_format =\fR \fIldif\fR | \fIsudoers\fR
+See the description of the
+\fB\-i\fR
+command line option.
+.TP 6n
+\fBmatch =\fR \fIfilter\fR
+See the description of the
+\fB\-m\fR
+command line option.
+.TP 6n
+\fBmatch_local =\fR \fIyes\fR | \fIno\fR
+See the description of the
+\fB\-M\fR
+command line option.
+.TP 6n
+\fBorder_increment =\fR \fIincrement\fR
+See the description of the
+\fB\-I\fR
+command line option.
+.TP 6n
+\fBorder_start =\fR \fIstart_point\fR
+See the description of the
+\fB\-O\fR
+command line option.
+.TP 6n
+\fBoutput_format =\fR \fIcsv\fR | \fIjson\fR | \fIldif\fR | \fIsudoers\fR
+See the description of the
+\fB\-f\fR
+command line option.
+.TP 6n
+\fBpadding =\fR \fIpadding\fR
+See the description of the
+\fB\-P\fR
+command line option.
+.TP 6n
+\fBpasswd_file =\fR \fIfile\fR
+See the description of the
+\fB\--passwd-file\fR
+command line option.
+.TP 6n
+\fBprune_matches =\fR \fIyes\fR | \fIno\fR
+See the description of the
+\fB\-p\fR
+command line option.
+.TP 6n
+\fBsudoers_base =\fR \fIdn\fR
+See the description of the
+\fB\-b\fR
+command line option.
+.TP 6n
+\fBsuppress =\fR \fIsections\fR
+See the description of the
+\fB\-s\fR
+command line option.
+.PP
+Options on the command line will override values from the
+configuration file.
+.SS "JSON output format"
+The
+\fIsudoers\fR
+JSON format may contain any of the following top-level objects:
+.TP 6n
+Defaults
+An array of objects, each containing an
+\fIOptions\fR
+array and an optional
+\fIBinding\fR
+array.
+.sp
+The
+\fIOptions\fR
+array consists of one or more objects, each containing a
+\(lqname:value\(rq
+pair that corresponds to a
+\fIsudoers\fR
+\fIDefaults\fR
+setting.
+\fIOptions\fR
+that operate on a list will also include an
+\fIoperation\fR
+entry in the object, with a value of
+\(lqlist_assign\(rq
+for
+\(oq=\(cq,
+\(lqlist_add\(rq
+for
+\(oq+=\(cq,
+or
+\(lqlist_remove\(rq
+for
+\(oq-=\(cq.
+.sp
+The optional
+\fIBinding\fR
+array consists of one or more objects, each containing a
+\(lqname:value\(rq
+pair and an optional
+\fInegated\fR
+entry, which will negate any comparison performed with the object.
+If a
+\fIBinding\fR
+is present, the setting will only take effect if one of the specified
+\fIcommand\fR,
+\fIhostname\fR,
+\fInetgroup\fR,
+\fInetworkaddr\fR,
+\fInonunixgid\fR,
+\fInonunixgroup\fR,
+\fIusergid\fR,
+\fIusergroup\fR,
+\fIuserid\fR,
+\fIusername\fR,
+or alias entries match.
+.sp
+For example, the following
+\fIsudoers\fR
+entry:
+.nf
+.sp
+.RS 6n
+Defaults@somehost set_home, env_keep += DISPLAY
+.RE
+.fi
+.RS 6n
+.sp
+converts to:
+.nf
+.sp
+.RS 6n
+"Defaults": [
+ {
+ "Binding": [
+ { "hostname": "somehost" }
+ ],
+ "Options": [
+ { "set_home": true },
+ {
+ "operation": "list_add",
+ "env_keep": [
+ "DISPLAY"
+ ]
+ }
+ ]
+ }
+]
+.RE
+.fi
+.RE
+.TP 6n
+User_Aliases
+A JSON object containing one or more
+\fIsudoers\fR
+\fIUser_Alias\fR
+entries where each named alias has as its value an array
+containing one or more objects.
+Each object contains a
+\(lqname:value\(rq
+pair and an optional
+\fInegated\fR
+entry, which will negate any comparison performed with the object.
+The name may be one of
+\fInetgroup\fR,
+\fInonunixgid\fR,
+\fInonunixgroup\fR,
+\fIuseralias\fR,
+\fIusergid\fR,
+\fIusergroup\fR,
+\fIuserid\fR,
+or
+\fIusername\fR.
+.sp
+For example, the following
+\fIsudoers\fR
+entry:
+.nf
+.sp
+.RS 6n
+User_Alias SYSADMIN = will, %wheel, +admin
+.RE
+.fi
+.RS 6n
+.sp
+converts to:
+.nf
+.sp
+.RS 6n
+"User_Aliases": {
+ "SYSADMIN": [
+ { "username": "will" },
+ { "usergroup": "wheel" },
+ { "netgroup": "admin" }
+ ]
+}
+.RE
+.fi
+.RE
+.TP 6n
+Runas_Aliases
+A JSON object containing one or more
+\fIsudoers\fR
+\fIRunas_Alias\fR
+entries, where each named alias has as its value an array
+containing one or more objects.
+Each object contains a
+\(lqname:value\(rq
+pair and an optional
+\fInegated\fR
+entry, which will negate any comparison performed with the object.
+The name may be one of
+\fInetgroup\fR,
+\fInonunixgid\fR,
+\fInonunixgroup\fR,
+\fIrunasalias\fR,
+\fIusergid\fR,
+\fIusergroup\fR,
+\fIuserid\fR,
+or
+\fIusername\fR.
+.sp
+For example, the following
+\fIsudoers\fR
+entry:
+.nf
+.sp
+.RS 6n
+Runas_Alias DB = oracle, sybase : OP = root, operator
+.RE
+.fi
+.RS 6n
+.sp
+converts to:
+.nf
+.sp
+.RS 6n
+"Runas_Aliases": {
+ "DB": [
+ { "username": "oracle" },
+ { "username": "sybase" }
+ ],
+ "OP": [
+ { "username": "root" },
+ { "username": "operator" }
+ ]
+}
+.RE
+.fi
+.RE
+.TP 6n
+Host_Aliases
+A JSON object containing one or more
+\fIsudoers\fR
+\fIHost_Alias\fR
+entries where each named alias has as its value an array
+containing one or more objects.
+Each object contains a
+\(lqname:value\(rq
+pair and an optional
+\fInegated\fR
+entry, which will negate any comparison performed with the object.
+The name may be one of
+\fIhostalias\fR,
+\fIhostname\fR,
+\fInetgroup\fR,
+or
+\fInetworkaddr\fR.
+.sp
+For example, the following
+\fIsudoers\fR
+entries:
+.nf
+.sp
+.RS 6n
+Host_Alias DORMNET = 128.138.243.0, 128.138.204.0/24
+Host_Alias SERVERS = boulder, refuge
+.RE
+.fi
+.RS 6n
+.sp
+convert to:
+.nf
+.sp
+.RS 6n
+"Host_Aliases": {
+ "DORMNET": [
+ { "networkaddr": "128.138.243.0" },
+ { "networkaddr": "128.138.204.0/24" }
+ ],
+ "SERVERS": [
+ { "hostname": "boulder" },
+ { "hostname": "refuge" }
+ ]
+}
+.RE
+.fi
+.RE
+.TP 6n
+Cmnd_Aliases
+A JSON object containing one or more
+\fIsudoers\fR
+\fICmnd_Alias\fR
+entries where each named alias has as its value an array
+containing one or more objects.
+Each object contains a
+\(lqname:value\(rq
+pair and an optional
+\fInegated\fR
+entry, which will negate any comparison performed with the object.
+The name may be either another
+\fIcmndalias\fR
+or a
+\fIcommand\fR.
+For example, the following
+\fIsudoers\fR
+entries:
+.nf
+.sp
+.RS 6n
+Cmnd_Alias SHELLS = /bin/bash, /bin/csh, /bin/sh, /bin/zsh
+Cmnd_Alias VIPW = /usr/bin/chpass, /usr/bin/chfn, /usr/bin/chsh, \e
+ /usr/bin/passwd, /usr/sbin/vigr, /usr/sbin/vipw
+.RE
+.fi
+.RS 6n
+.sp
+convert to:
+.nf
+.sp
+.RS 6n
+"Cmnd_Aliases": {
+ "SHELLS": [
+ { "command": "/bin/bash" },
+ { "command": "/bin/csh" },
+ { "command": "/bin/sh" },
+ { "command": "/bin/zsh" }
+ ],
+ "VIPW": [
+ { "command": "/usr/bin/chpass" },
+ { "command": "/usr/bin/chfn" },
+ { "command": "/usr/bin/chsh" },
+ { "command": "/usr/bin/passwd" },
+ { "command": "/usr/sbin/vigr" },
+ { "command": "/usr/sbin/vipw" }
+ ]
+}
+.RE
+.fi
+.RE
+.TP 6n
+User_Specs
+A JSON array containing one or more objects, each representing a
+\fIsudoers\fR
+User_Spec.
+Each object in the
+\fIUser_Specs\fR
+array should contain a
+\fIUser_List\fR
+array, a
+\fIHost_List\fR
+array and a
+\fICmnd_Specs\fR
+array.
+.sp
+A
+\fIUser_List\fR
+consists of one or more objects.
+Each object contains a
+\(lqname:value\(rq
+pair and an optional
+\fInegated\fR
+entry, which will negate any comparison performed with the object.
+The name may be one of
+\fInetgroup\fR,
+\fInonunixgid\fR,
+\fInonunixgroup\fR,
+\fIuseralias\fR,
+\fIusergid\fR,
+\fIusergroup\fR,
+\fIuserid\fR,
+or
+\fIusername\fR.
+If
+\fIusername\fR
+is set to the special value
+\fBALL\fR,
+it will match any user.
+.sp
+A
+\fIHost_List\fR
+consists of one or more objects.
+Each object contains a
+\(lqname:value\(rq
+pair and an optional
+\fInegated\fR
+entry, which will negate any comparison performed with the object.
+The name may be one of
+\fIhostalias\fR,
+\fIhostname\fR,
+\fInetgroup\fR,
+or
+\fInetworkaddr\fR.
+If
+\fIhostname\fR
+is set to the special value
+\fBALL\fR,
+it will match any host.
+.sp
+The
+\fICmnd_Specs\fR
+array consists of one or more JSON objects describing a command that
+may be run.
+Each
+\fICmnd_Specs\fR
+is made up of a
+\fICommands\fR
+array, an optional
+\fIrunasusers\fR
+array, an optional
+\fIrunasgroups\fR
+array, and an optional
+\fIOptions array.\fR
+.sp
+The
+\fICommands\fR
+array consists of one or more objects containing
+\(lqname:value\(rq
+pair elements.
+The following names and values are supported:
+.PP
+.RS 6n
+.PD 0
+.TP 9n
+command
+A string containing the command to run.
+The special value
+\fBALL\fR
+it will match any command.
+.PD
+.TP 9n
+negated
+A boolean value that, if true, will negate any comparison performed
+with the object.
+.TP 9n
+sha224
+A string containing the SHA224 digest of the
+\fIcommand\fR.
+.TP 9n
+sha256
+A string containing the SHA256 digest of the
+\fIcommand\fR.
+.TP 9n
+sha384
+A string containing the SHA384 digest of the
+\fIcommand\fR.
+.TP 9n
+sha512
+A string containing the SHA512 digest of the
+\fIcommand\fR.
+.PP
+The
+\fIrunasusers\fR
+array consists of objects describing users the command may be run as.
+Each object contains a
+\(lqname:value\(rq
+pair and an optional
+\fInegated\fR
+entry, which will negate any comparison performed with the object.
+The name may be one of
+\fInetgroup\fR,
+\fInonunixgid\fR,
+\fInonunixgroup\fR,
+\fIrunasalias\fR,
+\fIusergid\fR,
+\fIusergroup\fR,
+\fIuserid\fR,
+or
+\fIusername\fR.
+If
+\fIusername\fR
+is set to the special value
+\fBALL\fR,
+it will match any user.
+If
+\fIusername\fR
+is set to the empty string
+\(lq\(rq,
+it will match the invoking user.
+.sp
+The
+\fIrunasgroups\fR
+array consists of objects describing groups the command may be run as.
+Each object contains a
+\(lqname:value\(rq
+pair and an optional
+\fInegated\fR
+entry, which will negate any comparison performed with the object.
+The name may be one of
+\fIrunasalias\fR,
+\fIusergid\fR,
+or
+\fIusergroup\fR.
+If
+\fIusergroup\fR
+is set to the special value
+\fBALL\fR,
+it will match any group.
+.sp
+The
+\fIOptions\fR
+array is of the same format as the one in the
+\fIDefaults\fR
+object.
+Any
+\fITag_Spec\fR
+entries in
+\fIsudoers\fR
+are converted to
+\fIOptions\fR.
+A user with
+\(lqsudo ALL\(rq
+privileges will automatically have the
+\fIsetenv\fR
+option enabled to match the implicit behavior provided by
+\fIsudoers\fR.
+.sp
+For example, the following
+\fIsudoers\fR
+entry:
+.nf
+.sp
+.RS 6n
+millert ALL = (ALL : ALL) NOPASSWD: ALL, !/usr/bin/id
+.RE
+.fi
+.sp
+converts to:
+.nf
+.sp
+.RS 6n
+"User_Specs": [
+ {
+ "User_List": [
+ { "username": "millert" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "ALL" }
+ ],
+ "runasgroups": [
+ { "usergroup": "ALL" }
+ ],
+ "Options": [
+ { "authenticate": false },
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" },
+ {
+ "command": "/usr/bin/id",
+ "negated": true
+ }
+ ]
+ }
+ ]
+ }
+]
+.RE
+.fi
+.RE
+.SS "CSV output format"
+CSV (comma-separated value) files are often used by spreadsheets
+and report generators.
+For CSV output,
+\fBcvtsudoers\fR
+double quotes strings that contain commas.
+For each literal double quote character present inside the string,
+two double quotes are output.
+This method of quoting commas is compatible with most spreadsheet programs.
+.PP
+There are three possible sections in
+\fBcvtsudoers\fR's
+CSV output, each separated by a blank line:
+.TP 6n
+defaults
+This section includes any
+\fIDefaults\fR
+settings in
+\fIsudoers\fR.
+The
+\fIdefaults\fR
+section begins with the following heading:
+.nf
+.sp
+.RS 12n
+defaults_type,binding,name,operator,value
+.RE
+.fi
+.RS 6n
+.sp
+The fields are as follows:
+.TP 6n
+defaults_type
+The type of
+\fIDefaults\fR
+setting; one of
+\fIdefaults\fR,
+\fIdefaults_command\fR,
+\fIdefaults_host\fR,
+\fIdefaults_runas\fR,
+or
+\fIdefaults_user\fR.
+.TP 6n
+binding
+For
+\fIdefaults_command\fR,
+\fIdefaults_host\fR,
+\fIdefaults_runas\fR,
+and
+\fIdefaults_user\fR
+this is the value that must match for the setting to be applied.
+.TP 6n
+name
+The name of the
+\fIDefaults\fR
+setting.
+.TP 6n
+operator
+The operator determines how the value is applied to the setting.
+It may be either
+\(oq=\(cq
+(assignment),
+\(oq+=\(cq
+(append),
+or
+\(oq-=\(cq
+(remove).
+.TP 6n
+value
+.br
+The setting's value, usually a string or, for
+settings used in a boolean context,
+\fItrue\fR
+or
+\fIfalse\fR.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+aliases
+This section includes any
+\fICmnd_Alias\fR
+\fIHost_Alias\fR,
+\fIRunas_Alias\fR,
+or
+\fIUser_Alias\fR,
+entries from
+\fIsudoers\fR.
+The
+\fIaliases\fR
+section begins with the following heading:
+.nf
+.sp
+.RS 12n
+alias_type,alias_name,members
+.RE
+.fi
+.RS 6n
+.sp
+The fields are as follows:
+.TP 6n
+alias_type
+The type of alias; one of
+\fICmnd_Alias\fR,
+\fIHost_Alias\fR,
+\fIRunas_Alias\fR,
+or
+\fIUser_Alias\fR.
+.TP 6n
+alias_name
+The name of the alias; a string starting with an upper-case letter that
+consists of upper-case letters, digits, or underscores.
+.TP 6n
+members
+A comma-separated list of members belonging to the alias.
+Due to the use of commas,
+\fImembers\fR
+is surrounded by double quotes if it contains more than one member.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+rules
+.br
+This section includes the
+\fIsudoers\fR
+rules that grant privileges.
+The
+\fIrules\fR
+section begins with the following heading:
+.nf
+.sp
+.RS 12n
+rule,user,host,runusers,rungroups,options,command
+.RE
+.fi
+.RS 6n
+.sp
+The fields are as follows:
+.TP 6n
+rule
+This field indicates a
+\fIsudoers\fR
+\fIrule\fR
+entry.
+.TP 6n
+user
+The user the rule applies to.
+This may also be a Unix group (preceded by a
+\(oq%\(cq
+character), a non-Unix group (preceded by
+\(oq%:\(cq)
+or a netgroup (preceded by a
+\(oq+\(cq
+character)
+or a
+\fIUser_Alias\fR.
+If set to the special value
+\fBALL\fR,
+it will match any user.
+.TP 6n
+host
+The host the rule applies to.
+This may also be a netgroup (preceded by a
+\(oq+\(cq
+character)
+or a
+\fIHost_Alias\fR.
+If set to the special value
+\fBALL\fR,
+it will match any host.
+.TP 6n
+runusers
+An optional comma-separated list of users (or
+\fIRunas_Alias\fRes)
+the command may be run as.
+If it contains more than one member, the value is surrounded by
+double quotes.
+If set to the special value
+\fBALL\fR,
+it will match any user.
+If empty, the root user is assumed.
+.TP 6n
+rungroups
+An optional comma-separated list of groups (or
+\fIRunas_Alias\fRes)
+the command may be run as.
+If it contains more than one member, the value is surrounded by
+double quotes.
+If set to the special value
+\fBALL\fR,
+it will match any group.
+If empty, the
+\fIrunuser\fR's
+group is used.
+.TP 6n
+options
+An optional list of
+\fIDefaults\fR
+settings to apply to the command.
+Any
+\fITag_Spec\fR
+entries in
+\fIsudoers\fR
+are converted to
+\fIoptions\fR.
+.TP 6n
+commands
+A list of commands, with optional arguments, that the user is allowed to run.
+If set to the special value
+\fBALL\fR,
+it will match any command.
+.PP
+For example, the following
+\fIsudoers\fR
+entry:
+.nf
+.sp
+.RS 6n
+millert ALL = (ALL : ALL) NOPASSWD: ALL, !/usr/bin/id
+.RE
+.fi
+.sp
+converts to:
+.nf
+.sp
+.RS 6n
+rule,millert,ALL,ALL,ALL,"!authenticate","ALL,!/usr/bin/id"
+.RE
+.fi
+.RE
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/cvtsudoers.conf\fR
+default configuration for cvtsudoers
+.SH "EXAMPLES"
+Convert
+\fI/etc/sudoers\fR
+to LDIF (LDAP Data Interchange Format) where the
+\fIldap.conf\fR
+file uses a
+\fIsudoers_base\fR
+of my-domain,dc=com, storing the result in
+\fIsudoers.ldif\fR:
+.nf
+.sp
+.RS 4n
+$ cvtsudoers -b ou=SUDOers,dc=my-domain,dc=com -o sudoers.ldif \e
+ /etc/sudoers
+.RE
+.fi
+.PP
+Convert
+\fI/etc/sudoers\fR
+to JSON format, storing the result in
+\fIsudoers.json\fR:
+.nf
+.sp
+.RS 4n
+$ cvtsudoers -f json -o sudoers.json /etc/sudoers
+.RE
+.fi
+.PP
+Parse
+\fI/etc/sudoers\fR
+and display only rules that match user
+\fIambrose\fR
+on host
+\fIhastur\fR:
+.nf
+.sp
+.RS 4n
+$ cvtsudoers -f sudoers -m user=ambrose,host=hastur /etc/sudoers
+.RE
+.fi
+.PP
+Same as above, but expand aliases and prune out any non-matching
+users and hosts from the expanded entries.
+.nf
+.sp
+.RS 4n
+$ cvtsudoers -ep -f sudoers -m user=ambrose,host=hastur /etc/sudoers
+.RE
+.fi
+.PP
+Convert
+\fIsudoers.ldif\fR
+from LDIF to traditional
+\fIsudoers\fR
+format:
+.nf
+.sp
+.RS 4n
+$ cvtsudoers -i ldif -f sudoers -o sudoers.new sudoers.ldif
+.RE
+.fi
+.PP
+Merge a global
+\fIsudoers\fR
+file with two host-specific policy files from the hosts
+\(lqxyzzy\(rq
+and
+\(lqplugh\(rq:
+.nf
+.sp
+.RS 4n
+$ cvtsudoers -f sudoers -o sudoers.merged sudoers \e
+ xyzzy:sudoers.xyzzy plugh:sudoers.plugh
+.RE
+.fi
+.SH "SEE ALSO"
+sudoers(@mansectform@),
+sudoers.ldap(@mansectform@),
+sudo(@mansectsu@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS.md file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you believe you have found a bug in
+\fBcvtsudoers\fR,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBcvtsudoers\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/cvtsudoers.mdoc.in b/docs/cvtsudoers.mdoc.in
new file mode 100644
index 0000000..5618376
--- /dev/null
+++ b/docs/cvtsudoers.mdoc.in
@@ -0,0 +1,1207 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2018, 2021-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd January 16, 2023
+.Dt CVTSUDOERS 1
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm cvtsudoers
+.Nd convert between sudoers file formats
+.Sh SYNOPSIS
+.Nm cvtsudoers
+.Op Fl ehMpV
+.Op Fl b Ar dn
+.Op Fl c Ar conf_file
+.Op Fl d Ar deftypes
+.Op Fl f Ar output_format
+.Op Fl i Ar input_format
+.Op Fl I Ar increment
+.Op Fl l Ar log_file
+.Op Fl m Ar filter
+.Op Fl o Ar output_file
+.Op Fl O Ar start_point
+.Op Fl P Ar padding
+.Op Fl s Ar sections
+.Op Ar input_file ...
+.Sh DESCRIPTION
+The
+.Nm
+utility accepts one or more security policies in either
+.Em sudoers
+or LDIF format as input, and generates a single
+policy of the specified format as output.
+The default input format is
+.Em sudoers.
+The default output format is LDIF.
+It is only possible to convert a policy file that is syntactically correct.
+.Pp
+If no
+.Ar input_file
+is specified, or if it is
+.Ql - ,
+the policy is read from the standard input.
+Input files may be optionally prefixed with a host name followed by a colon
+.Pq Ql :\&
+to make the policy rules specific to a host when merging multiple files.
+By default, the result is written to the standard output.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl b Ar dn , Fl -base Ns = Ns Ar dn
+The base DN (distinguished name) that will be used when performing
+LDAP queries.
+Typically this is of the form
+.Dq ou=SUDOers,dc=my-domain,dc=com
+for the domain my-domain.com.
+If this option is not specified, the value of the
+.Ev SUDOERS_BASE
+environment variable will be used instead.
+Only necessary when converting to LDIF format.
+.It Fl c Ar conf_file , Fl -config Ns = Ns Ar conf_file
+Specify the path to the configuration file.
+Defaults to
+.Pa @sysconfdir@/cvtsudoers.conf .
+.It Fl d Ar deftypes , Fl -defaults Ns = Ns Ar deftypes
+Only convert
+.Em Defaults
+entries of the specified types.
+One or more
+.Em Defaults
+types may be specified, separated by a comma
+.Pq Ql \&, .
+The supported types are:
+.Bl -tag -width "command"
+.It all
+All Defaults entries.
+.It global
+Global Defaults entries that are applied regardless of
+user, runas, host, or command.
+.It user
+Per-user Defaults entries.
+.It runas
+Per-runas user Defaults entries.
+.It host
+Per-host Defaults entries.
+.It command
+Per-command Defaults entries.
+.El
+.Pp
+See the
+.Sy Defaults
+section in
+.Xr sudoers @mansectform@
+for more information.
+.Pp
+If the
+.Fl d
+option is not specified, all
+.Em Defaults
+entries will be converted.
+.It Fl e , Fl -expand-aliases
+Expand aliases in
+.Ar input_file .
+Aliases are preserved by default when the output
+.Ar format
+is JSON or sudoers.
+.It Fl f Ar output_format , Fl -output-format Ns = Ns Ar output_format
+Specify the output format (case-insensitive).
+The following formats are supported:
+.Bl -tag -width "sudoers"
+.It CSV
+CSV (comma-separated value) files are often used by spreadsheets
+and report generators.
+See
+.Sx CSV output format
+for more details.
+.It JSON
+JSON (JavaScript Object Notation) files are usually easier for
+third-party applications to consume than the traditional
+.Em sudoers
+format.
+The various values have explicit types which removes much of the
+ambiguity of the
+.Em sudoers
+format.
+See
+.Sx JSON output format
+for more details.
+.It LDIF
+LDIF (LDAP Data Interchange Format) files can be imported into an LDAP
+server for use with
+.Xr sudoers.ldap @mansectform@ .
+.Pp
+Conversion to LDIF has the following limitations:
+.Bl -bullet -width 1n
+.It
+Command, host, runas, and user-specific Defaults lines cannot be
+translated as they don't have an equivalent in the sudoers LDAP schema.
+.It
+Command, host, runas, and user aliases are not supported by the
+sudoers LDAP schema so they are expanded during the conversion.
+.El
+.It sudoers
+Traditional sudoers format.
+A new sudoers file will be reconstructed from the parsed input file.
+Comments are not preserved and data from any include files will be
+output inline.
+.El
+.It Fl -group-file Ns = Ns Ar file
+When the
+.Fl M
+option is also specified, perform group queries using
+.Ar file
+instead of the system group database.
+.It Fl h , Fl -help
+Display a short help message to the standard output and exit.
+.It Fl i Ar input_format , Fl -input-format Ns = Ns Ar input_format
+Specify the input format.
+The following formats are supported:
+.Bl -tag -width "sudoers"
+.It LDIF
+LDIF (LDAP Data Interchange Format) files can be exported from an LDAP
+server to convert security policies used by
+.Xr sudoers.ldap @mansectform@ .
+If a base DN (distinguished name) is specified, only sudoRole objects
+that match the base DN will be processed.
+Not all sudoOptions specified in a sudoRole can be translated from
+LDIF to sudoers format.
+.It sudoers
+Traditional sudoers format.
+This is the default input format.
+.El
+.It Fl I Ar increment , Fl -increment Ns = Ns Ar increment
+When generating LDIF output, increment each sudoOrder attribute by
+the specified number.
+Defaults to an increment of 1.
+.It Fl l Ar log_file , Fl -logfile Ns = Ns Ar log_file
+Log conversion warnings to
+.Ar log_file
+instead of to the standard error.
+This is particularly useful when merging multiple
+.Em sudoers
+files, which can generate a large number of warnings.
+.It Fl m Ar filter , Fl -match Ns = Ns Ar filter
+Only output rules that match the specified
+.Ar filter .
+A
+.Ar filter
+expression is made up of one or more
+.Sy key = Ar value
+pairs, separated by a comma
+.Pq Ql \&, .
+The
+.Sy key
+may be
+.Dq cmnd
+.Pq or Dq cmd ,
+.Dq host ,
+.Dq group ,
+or
+.Dq user .
+For example,
+.Sy user No = Ar operator
+or
+.Sy host No = Ar www .
+An upper-case
+.Em Cmnd_Alias ,
+.Em Host_alias ,
+or
+.Em User_Alias
+may be specified as the
+.Dq cmnd ,
+.Dq host ,
+or
+.Dq user .
+.Pp
+A matching
+.Em sudoers
+rule may also include users, groups, and hosts that are not part of the
+.Ar filter .
+This can happen when a rule includes multiple users, groups, or hosts.
+To prune out any non-matching user, group, or host from the rules, the
+.Fl p
+option may be used.
+.Pp
+By default, the password and group databases are not consulted when matching
+against the filter so the users and groups do not need to be present
+on the local system (see the
+.Fl M
+option).
+Only aliases that are referenced by the filtered policy rules will
+be displayed.
+.It Fl M , Fl -match-local
+When the
+.Fl m
+option is also specified, use password and group database information
+when matching users and groups in the filter.
+Only users and groups in the filter that exist on the local system will match,
+and a user's groups will automatically be added to the filter.
+If the
+.Fl M
+is
+.Em not
+specified, users and groups in the filter do not need to exist on the
+local system, but all groups used for matching must be explicitly listed
+in the filter.
+.It Fl o Ar output_file , Fl -output Ns = Ns Ar output_file
+Write the converted output to
+.Ar output_file .
+If no
+.Ar output_file
+is specified, or if it is
+.Ql - ,
+the converted
+.Em sudoers
+policy will be written to the standard output.
+.It Fl O Ar start_point , Fl -order-start Ns = Ns Ar start_point
+When generating LDIF output, use the number specified by
+.Ar start_point
+in the sudoOrder attribute of the first sudoRole object.
+Subsequent sudoRole object use a sudoOrder value generated by adding an
+.Ar increment ,
+see the
+.Fl I
+option for details.
+Defaults to a starting point of 1.
+A starting point of 0 will disable the generation of sudoOrder
+attributes in the resulting LDIF file.
+.It Fl -passwd-file Ns = Ns Ar file
+When the
+.Fl M
+option is also specified, perform passwd queries using
+.Ar file
+instead of the system passwd database.
+.It Fl p , Fl -prune-matches
+When the
+.Fl m
+option is also specified,
+.Nm
+will prune out non-matching users, groups, and hosts from
+matching entries.
+.It Fl P Ar padding , Fl -padding Ns = Ns Ar padding
+When generating LDIF output, construct the initial sudoOrder value by
+concatenating
+.Ar order_start
+and
+.Ar increment ,
+padding the
+.Ar increment
+with zeros until it consists of
+.Ar padding
+digits.
+For example, if
+.Ar order_start
+is 1027,
+.Ar padding
+is 3, and
+.Ar increment
+is 1, the value of sudoOrder for the first entry will be 1027000,
+followed by 1027001, 1027002, etc.
+If the number of sudoRole entries is larger than the padding would allow,
+.Nm
+will exit with an error.
+By default, no padding is performed.
+.It Fl s Ar sections , Fl -suppress Ns = Ns Ar sections
+Suppress the output of specific
+.Ar sections
+of the security policy.
+One or more section names may be specified, separated by a comma
+.Pq Ql \&, .
+The supported section name are:
+.Sy defaults ,
+.Sy aliases
+and
+.Sy privileges
+(which may be shortened to
+.Sy privs ) .
+.It Fl V , -version
+Print the
+.Nm
+and
+.Em sudoers
+grammar versions and exit.
+.El
+.Ss Merging multiple files
+When multiple input files are specified,
+.Nm
+will attempt to merge them into a single policy file.
+It is assumed that user and group names are consistent among
+the policy files to be merged.
+For example, user
+.Dq bob
+on one host is the same as user
+.Dq bob
+on another host.
+.Pp
+When merging policy files, it is possible to prefix the input file name
+with a host name, separated by a colon
+.Pq Ql :\& .
+When the files are merged, the host name will be used to restrict
+the policy rules to that specific host where possible.
+.Pp
+The merging process is performed as follows:
+.Bl -bullet -width 1n
+.It
+Each input file is parsed into internal sudoers data structures.
+.It
+Aliases are merged and renamed as necessary to avoid conflicts.
+In the event of a conflict, the first alias found is left as-is and
+subsequent aliases of the same name are renamed with a numeric suffix
+separated with a underscore
+.Pq Ql _ .
+For example, if there are two different aliases named
+.Dv SERVERS ,
+the first will be left as-is and the second will be renamed
+.Dv SERVERS_1 .
+References to the renamed alias are also updated in the policy file.
+Duplicate aliases (those with identical contents) are pruned.
+.It
+Defaults settings are merged and duplicates are removed.
+If there are conflicts in the Defaults settings, a warning is emitted for
+each conflict.
+If a host name is specified with the input file,
+.Nm
+will change the global Defaults settings in that file to be host-specific.
+A warning is emitted for command, user, or runas-specific Defaults settings
+which cannot be made host-specific.
+.It
+Per-user rules are merged and duplicates are removed.
+If a host name is specified with the input file,
+.Nm
+will change rules that specify a host name of
+.Sy ALL
+to the host name associated with the policy file being merged.
+The merging of rules is currently fairly simplistic but will be
+improved in a later release.
+.El
+.Pp
+It is possible to merge policy files with differing formats.
+.Ss The cvtsudoers.conf file
+Options in the form
+.Dq keyword = value
+may also be specified in a configuration file,
+.Pa @sysconfdir@/cvtsudoers.conf
+by default.
+The following keywords are recognized:
+.Bl -tag -width 4n
+.It Sy defaults = Ar deftypes
+See the description of the
+.Fl d
+command line option.
+.It Sy expand_aliases = Ar yes | no
+See the description of the
+.Fl e
+command line option.
+.It Sy group_file = Ar file
+See the description of the
+.Fl -group-file
+command line option.
+.It Sy input_format = Ar ldif | sudoers
+See the description of the
+.Fl i
+command line option.
+.It Sy match = Ar filter
+See the description of the
+.Fl m
+command line option.
+.It Sy match_local = Ar yes | no
+See the description of the
+.Fl M
+command line option.
+.It Sy order_increment = Ar increment
+See the description of the
+.Fl I
+command line option.
+.It Sy order_start = Ar start_point
+See the description of the
+.Fl O
+command line option.
+.It Sy output_format = Ar csv | json | ldif | sudoers
+See the description of the
+.Fl f
+command line option.
+.It Sy padding = Ar padding
+See the description of the
+.Fl P
+command line option.
+.It Sy passwd_file = Ar file
+See the description of the
+.Fl -passwd-file
+command line option.
+.It Sy prune_matches = Ar yes | no
+See the description of the
+.Fl p
+command line option.
+.It Sy sudoers_base = Ar dn
+See the description of the
+.Fl b
+command line option.
+.It Sy suppress = Ar sections
+See the description of the
+.Fl s
+command line option.
+.El
+.Pp
+Options on the command line will override values from the
+configuration file.
+.Ss JSON output format
+The
+.Em sudoers
+JSON format may contain any of the following top-level objects:
+.Bl -tag -width 4n
+.It Defaults
+An array of objects, each containing an
+.Em Options
+array and an optional
+.Em Binding
+array.
+.Pp
+The
+.Em Options
+array consists of one or more objects, each containing a
+.Dq name:value
+pair that corresponds to a
+.Em sudoers
+.Em Defaults
+setting.
+.Em Options
+that operate on a list will also include an
+.Em operation
+entry in the object, with a value of
+.Dq list_assign
+for
+.Ql = ,
+.Dq list_add
+for
+.Ql += ,
+or
+.Dq list_remove
+for
+.Ql -= .
+.Pp
+The optional
+.Em Binding
+array consists of one or more objects, each containing a
+.Dq name:value
+pair and an optional
+.Em negated
+entry, which will negate any comparison performed with the object.
+If a
+.Em Binding
+is present, the setting will only take effect if one of the specified
+.Em command ,
+.Em hostname ,
+.Em netgroup ,
+.Em networkaddr ,
+.Em nonunixgid ,
+.Em nonunixgroup ,
+.Em usergid ,
+.Em usergroup ,
+.Em userid ,
+.Em username ,
+or alias entries match.
+.Pp
+For example, the following
+.Em sudoers
+entry:
+.Bd -literal
+Defaults@somehost set_home, env_keep += DISPLAY
+.Ed
+.Pp
+converts to:
+.Bd -literal
+"Defaults": [
+ {
+ "Binding": [
+ { "hostname": "somehost" }
+ ],
+ "Options": [
+ { "set_home": true },
+ {
+ "operation": "list_add",
+ "env_keep": [
+ "DISPLAY"
+ ]
+ }
+ ]
+ }
+]
+.Ed
+.It User_Aliases
+A JSON object containing one or more
+.Em sudoers
+.Em User_Alias
+entries where each named alias has as its value an array
+containing one or more objects.
+Each object contains a
+.Dq name:value
+pair and an optional
+.Em negated
+entry, which will negate any comparison performed with the object.
+The name may be one of
+.Em netgroup ,
+.Em nonunixgid ,
+.Em nonunixgroup ,
+.Em useralias ,
+.Em usergid ,
+.Em usergroup ,
+.Em userid ,
+or
+.Em username .
+.Pp
+For example, the following
+.Em sudoers
+entry:
+.Bd -literal
+User_Alias SYSADMIN = will, %wheel, +admin
+.Ed
+.Pp
+converts to:
+.Bd -literal
+"User_Aliases": {
+ "SYSADMIN": [
+ { "username": "will" },
+ { "usergroup": "wheel" },
+ { "netgroup": "admin" }
+ ]
+}
+.Ed
+.It Runas_Aliases
+A JSON object containing one or more
+.Em sudoers
+.Em Runas_Alias
+entries, where each named alias has as its value an array
+containing one or more objects.
+Each object contains a
+.Dq name:value
+pair and an optional
+.Em negated
+entry, which will negate any comparison performed with the object.
+The name may be one of
+.Em netgroup ,
+.Em nonunixgid ,
+.Em nonunixgroup ,
+.Em runasalias ,
+.Em usergid ,
+.Em usergroup ,
+.Em userid ,
+or
+.Em username .
+.Pp
+For example, the following
+.Em sudoers
+entry:
+.Bd -literal
+Runas_Alias DB = oracle, sybase : OP = root, operator
+.Ed
+.Pp
+converts to:
+.Bd -literal
+"Runas_Aliases": {
+ "DB": [
+ { "username": "oracle" },
+ { "username": "sybase" }
+ ],
+ "OP": [
+ { "username": "root" },
+ { "username": "operator" }
+ ]
+}
+.Ed
+.It Host_Aliases
+A JSON object containing one or more
+.Em sudoers
+.Em Host_Alias
+entries where each named alias has as its value an array
+containing one or more objects.
+Each object contains a
+.Dq name:value
+pair and an optional
+.Em negated
+entry, which will negate any comparison performed with the object.
+The name may be one of
+.Em hostalias ,
+.Em hostname ,
+.Em netgroup ,
+or
+.Em networkaddr .
+.Pp
+For example, the following
+.Em sudoers
+entries:
+.Bd -literal
+Host_Alias DORMNET = 128.138.243.0, 128.138.204.0/24
+Host_Alias SERVERS = boulder, refuge
+.Ed
+.Pp
+convert to:
+.Bd -literal
+"Host_Aliases": {
+ "DORMNET": [
+ { "networkaddr": "128.138.243.0" },
+ { "networkaddr": "128.138.204.0/24" }
+ ],
+ "SERVERS": [
+ { "hostname": "boulder" },
+ { "hostname": "refuge" }
+ ]
+}
+.Ed
+.It Cmnd_Aliases
+A JSON object containing one or more
+.Em sudoers
+.Em Cmnd_Alias
+entries where each named alias has as its value an array
+containing one or more objects.
+Each object contains a
+.Dq name:value
+pair and an optional
+.Em negated
+entry, which will negate any comparison performed with the object.
+The name may be either another
+.Em cmndalias
+or a
+.Em command .
+For example, the following
+.Em sudoers
+entries:
+.Bd -literal
+Cmnd_Alias SHELLS = /bin/bash, /bin/csh, /bin/sh, /bin/zsh
+Cmnd_Alias VIPW = /usr/bin/chpass, /usr/bin/chfn, /usr/bin/chsh, \e
+ /usr/bin/passwd, /usr/sbin/vigr, /usr/sbin/vipw
+.Ed
+.Pp
+convert to:
+.Bd -literal
+"Cmnd_Aliases": {
+ "SHELLS": [
+ { "command": "/bin/bash" },
+ { "command": "/bin/csh" },
+ { "command": "/bin/sh" },
+ { "command": "/bin/zsh" }
+ ],
+ "VIPW": [
+ { "command": "/usr/bin/chpass" },
+ { "command": "/usr/bin/chfn" },
+ { "command": "/usr/bin/chsh" },
+ { "command": "/usr/bin/passwd" },
+ { "command": "/usr/sbin/vigr" },
+ { "command": "/usr/sbin/vipw" }
+ ]
+}
+.Ed
+.It User_Specs
+A JSON array containing one or more objects, each representing a
+.Em sudoers
+User_Spec.
+Each object in the
+.Em User_Specs
+array should contain a
+.Em User_List
+array, a
+.Em Host_List
+array and a
+.Em Cmnd_Specs
+array.
+.Pp
+A
+.Em User_List
+consists of one or more objects.
+Each object contains a
+.Dq name:value
+pair and an optional
+.Em negated
+entry, which will negate any comparison performed with the object.
+The name may be one of
+.Em netgroup ,
+.Em nonunixgid ,
+.Em nonunixgroup ,
+.Em useralias ,
+.Em usergid ,
+.Em usergroup ,
+.Em userid ,
+or
+.Em username .
+If
+.Em username
+is set to the special value
+.Sy ALL ,
+it will match any user.
+.Pp
+A
+.Em Host_List
+consists of one or more objects.
+Each object contains a
+.Dq name:value
+pair and an optional
+.Em negated
+entry, which will negate any comparison performed with the object.
+The name may be one of
+.Em hostalias ,
+.Em hostname ,
+.Em netgroup ,
+or
+.Em networkaddr .
+If
+.Em hostname
+is set to the special value
+.Sy ALL ,
+it will match any host.
+.Pp
+The
+.Em Cmnd_Specs
+array consists of one or more JSON objects describing a command that
+may be run.
+Each
+.Em Cmnd_Specs
+is made up of a
+.Em Commands
+array, an optional
+.Em runasusers
+array, an optional
+.Em runasgroups
+array, and an optional
+.Em Options array.
+.Pp
+The
+.Em Commands
+array consists of one or more objects containing
+.Dq name:value
+pair elements.
+The following names and values are supported:
+.Bl -tag -width "command"
+.It command
+A string containing the command to run.
+The special value
+.Sy ALL
+it will match any command.
+.It negated
+A boolean value that, if true, will negate any comparison performed
+with the object.
+.It sha224
+A string containing the SHA224 digest of the
+.Em command .
+.It sha256
+A string containing the SHA256 digest of the
+.Em command .
+.It sha384
+A string containing the SHA384 digest of the
+.Em command .
+.It sha512
+A string containing the SHA512 digest of the
+.Em command .
+.El
+.Pp
+The
+.Em runasusers
+array consists of objects describing users the command may be run as.
+Each object contains a
+.Dq name:value
+pair and an optional
+.Em negated
+entry, which will negate any comparison performed with the object.
+The name may be one of
+.Em netgroup ,
+.Em nonunixgid ,
+.Em nonunixgroup ,
+.Em runasalias ,
+.Em usergid ,
+.Em usergroup ,
+.Em userid ,
+or
+.Em username .
+If
+.Em username
+is set to the special value
+.Sy ALL ,
+it will match any user.
+If
+.Em username
+is set to the empty string
+.Dq "" ,
+it will match the invoking user.
+.Pp
+The
+.Em runasgroups
+array consists of objects describing groups the command may be run as.
+Each object contains a
+.Dq name:value
+pair and an optional
+.Em negated
+entry, which will negate any comparison performed with the object.
+The name may be one of
+.Em runasalias ,
+.Em usergid ,
+or
+.Em usergroup .
+If
+.Em usergroup
+is set to the special value
+.Sy ALL ,
+it will match any group.
+.Pp
+The
+.Em Options
+array is of the same format as the one in the
+.Em Defaults
+object.
+Any
+.Em Tag_Spec
+entries in
+.Em sudoers
+are converted to
+.Em Options .
+A user with
+.Dq sudo ALL
+privileges will automatically have the
+.Em setenv
+option enabled to match the implicit behavior provided by
+.Em sudoers .
+.Pp
+For example, the following
+.Em sudoers
+entry:
+.Bd -literal
+millert ALL = (ALL : ALL) NOPASSWD: ALL, !/usr/bin/id
+.Ed
+.Pp
+converts to:
+.Bd -literal
+"User_Specs": [
+ {
+ "User_List": [
+ { "username": "millert" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "ALL" }
+ ],
+ "runasgroups": [
+ { "usergroup": "ALL" }
+ ],
+ "Options": [
+ { "authenticate": false },
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" },
+ {
+ "command": "/usr/bin/id",
+ "negated": true
+ }
+ ]
+ }
+ ]
+ }
+]
+.Ed
+.El
+.Ss CSV output format
+CSV (comma-separated value) files are often used by spreadsheets
+and report generators.
+For CSV output,
+.Nm
+double quotes strings that contain commas.
+For each literal double quote character present inside the string,
+two double quotes are output.
+This method of quoting commas is compatible with most spreadsheet programs.
+.Pp
+There are three possible sections in
+.Nm cvtsudoers Ns 's
+CSV output, each separated by a blank line:
+.Bl -tag -width 4n
+.It defaults
+This section includes any
+.Em Defaults
+settings in
+.Em sudoers .
+The
+.Em defaults
+section begins with the following heading:
+.Bd -literal -offset indent
+defaults_type,binding,name,operator,value
+.Ed
+.Pp
+The fields are as follows:
+.Bl -tag -width 4n
+.It defaults_type
+The type of
+.Em Defaults
+setting; one of
+.Em defaults ,
+.Em defaults_command ,
+.Em defaults_host ,
+.Em defaults_runas ,
+or
+.Em defaults_user .
+.It binding
+For
+.Em defaults_command ,
+.Em defaults_host ,
+.Em defaults_runas ,
+and
+.Em defaults_user
+this is the value that must match for the setting to be applied.
+.It name
+The name of the
+.Em Defaults
+setting.
+.It operator
+The operator determines how the value is applied to the setting.
+It may be either
+.Ql =
+(assignment),
+.Ql +=
+(append),
+or
+.Ql -=
+(remove).
+.It value
+The setting's value, usually a string or, for
+settings used in a boolean context,
+.Em true
+or
+.Em false .
+.El
+.It aliases
+This section includes any
+.Em Cmnd_Alias
+.Em Host_Alias ,
+.Em Runas_Alias ,
+or
+.Em User_Alias ,
+entries from
+.Em sudoers .
+The
+.Em aliases
+section begins with the following heading:
+.Bd -literal -offset indent
+alias_type,alias_name,members
+.Ed
+.Pp
+The fields are as follows:
+.Bl -tag -width 4n
+.It alias_type
+The type of alias; one of
+.Em Cmnd_Alias ,
+.Em Host_Alias ,
+.Em Runas_Alias ,
+or
+.Em User_Alias .
+.It alias_name
+The name of the alias; a string starting with an upper-case letter that
+consists of upper-case letters, digits, or underscores.
+.It members
+A comma-separated list of members belonging to the alias.
+Due to the use of commas,
+.Em members
+is surrounded by double quotes if it contains more than one member.
+.El
+.It rules
+This section includes the
+.Em sudoers
+rules that grant privileges.
+The
+.Em rules
+section begins with the following heading:
+.Bd -literal -offset indent
+rule,user,host,runusers,rungroups,options,command
+.Ed
+.Pp
+The fields are as follows:
+.Bl -tag -width 4n
+.It rule
+This field indicates a
+.Em sudoers
+.Em rule
+entry.
+.It user
+The user the rule applies to.
+This may also be a Unix group (preceded by a
+.Ql %
+character), a non-Unix group (preceded by
+.Ql %: )
+or a netgroup (preceded by a
+.Ql +
+character)
+or a
+.Em User_Alias .
+If set to the special value
+.Sy ALL ,
+it will match any user.
+.It host
+The host the rule applies to.
+This may also be a netgroup (preceded by a
+.Ql +
+character)
+or a
+.Em Host_Alias .
+If set to the special value
+.Sy ALL ,
+it will match any host.
+.It runusers
+An optional comma-separated list of users (or
+.Em Runas_Alias Ns No es )
+the command may be run as.
+If it contains more than one member, the value is surrounded by
+double quotes.
+If set to the special value
+.Sy ALL ,
+it will match any user.
+If empty, the root user is assumed.
+.It rungroups
+An optional comma-separated list of groups (or
+.Em Runas_Alias Ns No es )
+the command may be run as.
+If it contains more than one member, the value is surrounded by
+double quotes.
+If set to the special value
+.Sy ALL ,
+it will match any group.
+If empty, the
+.Em runuser Ns 's
+group is used.
+.It options
+An optional list of
+.Em Defaults
+settings to apply to the command.
+Any
+.Em Tag_Spec
+entries in
+.Em sudoers
+are converted to
+.Em options .
+.It commands
+A list of commands, with optional arguments, that the user is allowed to run.
+If set to the special value
+.Sy ALL ,
+it will match any command.
+.El
+.Pp
+For example, the following
+.Em sudoers
+entry:
+.Bd -literal
+millert ALL = (ALL : ALL) NOPASSWD: ALL, !/usr/bin/id
+.Ed
+.Pp
+converts to:
+.Bd -literal
+rule,millert,ALL,ALL,ALL,"!authenticate","ALL,!/usr/bin/id"
+.Ed
+.El
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/cvtsudoers.conf
+default configuration for cvtsudoers
+.El
+.Sh EXAMPLES
+Convert
+.Pa /etc/sudoers
+to LDIF (LDAP Data Interchange Format) where the
+.Pa ldap.conf
+file uses a
+.Em sudoers_base
+of my-domain,dc=com, storing the result in
+.Pa sudoers.ldif :
+.Bd -literal -offset 4n
+$ cvtsudoers -b ou=SUDOers,dc=my-domain,dc=com -o sudoers.ldif \e
+ /etc/sudoers
+.Ed
+.Pp
+Convert
+.Pa /etc/sudoers
+to JSON format, storing the result in
+.Pa sudoers.json :
+.Bd -literal -offset 4n
+$ cvtsudoers -f json -o sudoers.json /etc/sudoers
+.Ed
+.Pp
+Parse
+.Pa /etc/sudoers
+and display only rules that match user
+.Em ambrose
+on host
+.Em hastur :
+.Bd -literal -offset 4n
+$ cvtsudoers -f sudoers -m user=ambrose,host=hastur /etc/sudoers
+.Ed
+.Pp
+Same as above, but expand aliases and prune out any non-matching
+users and hosts from the expanded entries.
+.Bd -literal -offset 4n
+$ cvtsudoers -ep -f sudoers -m user=ambrose,host=hastur /etc/sudoers
+.Ed
+.Pp
+Convert
+.Pa sudoers.ldif
+from LDIF to traditional
+.Em sudoers
+format:
+.Bd -literal -offset 4n
+$ cvtsudoers -i ldif -f sudoers -o sudoers.new sudoers.ldif
+.Ed
+.Pp
+Merge a global
+.Em sudoers
+file with two host-specific policy files from the hosts
+.Dq xyzzy
+and
+.Dq plugh :
+.Bd -literal -offset 4n
+$ cvtsudoers -f sudoers -o sudoers.merged sudoers \e
+ xyzzy:sudoers.xyzzy plugh:sudoers.plugh
+.Ed
+.Sh SEE ALSO
+.Xr sudoers @mansectform@ ,
+.Xr sudoers.ldap @mansectform@ ,
+.Xr sudo @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS.md file in the
+.Nm sudo
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you believe you have found a bug in
+.Nm ,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+.Nm sudo
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/fixman.sh b/docs/fixman.sh
new file mode 100755
index 0000000..c22b58c
--- /dev/null
+++ b/docs/fixman.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2012-2014, 2017 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+OUTFILE="$1"
+rm -f "$OUTFILE"
+> "$OUTFILE"
+
+# HP-UX friendly header/footer for all man pages
+if [ X"`uname 2>&1`" = X"HP-UX" ]; then
+ cat >>"$OUTFILE" <<-'EOF'
+ s/^\.TH \("[^"]*"\) \("[^"]*"\) "\([^"]*\)" "\([^"]*\)" \("[^"]*"\)/.TH \1 \2\
+ .ds )H \4\
+ .ds ]W \3/
+EOF
+fi
+
+# Replace "0 minutes" with "unlimited"
+cat >>"$OUTFILE" <<-'EOF'
+ /^\\fR0\\fR$/ {
+ N
+ s/^\\fR0\\fR\nminutes\.$/unlimited./
+ }
+EOF
diff --git a/docs/fixmdoc.sed b/docs/fixmdoc.sed
new file mode 100644
index 0000000..3d57216
--- /dev/null
+++ b/docs/fixmdoc.sed
@@ -0,0 +1,5 @@
+# Replace "0 minutes" with "unlimited"
+/^\.Li 0$/ {
+ N
+ s/^\.Li 0\nminutes\.$/unlimited./
+}
diff --git a/docs/schema.ActiveDirectory b/docs/schema.ActiveDirectory
new file mode 100644
index 0000000..f488eef
--- /dev/null
+++ b/docs/schema.ActiveDirectory
@@ -0,0 +1,255 @@
+#
+# Active Directory Schema for sudo configuration (sudoers)
+#
+# To extend your Active Directory schema, run one of the following command
+# on your Windows DC (default port - Active Directory):
+#
+# ldifde -i -f schema.ActiveDirectory -c "CN=Schema,CN=Configuration,DC=X" #schemaNamingContext
+#
+# or on your Windows DC if using another port (with Active Directory LightWeight Directory Services / ADAM-Active Directory Application Mode)
+# Port 50000 by example (or any other port specified when defining the ADLDS/ADAM instance
+#
+# ldifde -i -f schema.ActiveDirectory -t 50000 -c "CN=Schema,CN=Configuration,DC=X" #schemaNamingContext
+#
+# or
+#
+# ldifde -i -f schema.ActiveDirectory -s server:port -c "CN=Schema,CN=Configuration,DC=X" #schemaNamingContext
+#
+# Can add username domain and password
+#
+# -b username domain password
+#
+# Can create Log file in current or any directory
+#
+# -j .
+#
+
+dn: CN=sudoUser,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoUser
+distinguishedName: CN=sudoUser,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.1
+attributeSyntax: 2.5.5.5
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoUser
+adminDescription: User(s) who may run sudo
+oMSyntax: 22
+searchFlags: 1
+lDAPDisplayName: sudoUser
+name: sudoUser
+schemaIDGUID:: JrGcaKpnoU+0s+HgeFjAbg==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoHost,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoHost
+distinguishedName: CN=sudoHost,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.2
+attributeSyntax: 2.5.5.5
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoHost
+adminDescription: Host(s) who may run sudo
+oMSyntax: 22
+lDAPDisplayName: sudoHost
+name: sudoHost
+schemaIDGUID:: d0TTjg+Y6U28g/Y+ns2k4w==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoCommand,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoCommand
+distinguishedName: CN=sudoCommand,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.3
+attributeSyntax: 2.5.5.5
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoCommand
+adminDescription: Command(s) to be executed by sudo
+oMSyntax: 22
+lDAPDisplayName: sudoCommand
+name: sudoCommand
+schemaIDGUID:: D6QR4P5UyUen3RGYJCHCPg==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoRunAs,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoRunAs
+distinguishedName: CN=sudoRunAs,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.4
+attributeSyntax: 2.5.5.5
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoRunAs
+adminDescription: User(s) impersonated by sudo (deprecated)
+oMSyntax: 22
+lDAPDisplayName: sudoRunAs
+name: sudoRunAs
+schemaIDGUID:: CP98mCQTyUKKxGrQeM80hQ==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoOption,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoOption
+distinguishedName: CN=sudoOption,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.5
+attributeSyntax: 2.5.5.5
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoOption
+adminDescription: Option(s) followed by sudo
+oMSyntax: 22
+lDAPDisplayName: sudoOption
+name: sudoOption
+schemaIDGUID:: ojaPzBBlAEmsvrHxQctLnA==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoRunAsUser,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoRunAsUser
+distinguishedName: CN=sudoRunAsUser,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.6
+attributeSyntax: 2.5.5.5
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoRunAsUser
+adminDescription: User(s) impersonated by sudo
+oMSyntax: 22
+lDAPDisplayName: sudoRunAsUser
+name: sudoRunAsUser
+schemaIDGUID:: 9C52yPYd3RG3jMR2VtiVkw==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoRunAsGroup,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoRunAsGroup
+distinguishedName: CN=sudoRunAsGroup,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.7
+attributeSyntax: 2.5.5.5
+isSingleValued: FALSE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoRunAsGroup
+adminDescription: Groups(s) impersonated by sudo
+oMSyntax: 22
+lDAPDisplayName: sudoRunAsGroup
+name: sudoRunAsGroup
+schemaIDGUID:: xJhSt/Yd3RGJPTB1VtiVkw==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoNotBefore,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoNotBefore
+distinguishedName: CN=sudoNotBefore,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.8
+attributeSyntax: 2.5.5.11
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoNotBefore
+adminDescription: Start of time interval for which the entry is valid
+oMSyntax: 24
+lDAPDisplayName: sudoNotBefore
+name: sudoNotBefore
+schemaIDGUID:: dm1HnRfY4RGf4gopYYhwmw==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoNotAfter,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoNotAfter
+distinguishedName: CN=sudoNotAfter,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.9
+attributeSyntax: 2.5.5.11
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoNotAfter
+adminDescription: End of time interval for which the entry is valid
+oMSyntax: 24
+lDAPDisplayName: sudoNotAfter
+name: sudoNotAfter
+schemaIDGUID:: OAr/pBfY4RG9dBIpYYhwmw==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn: CN=sudoOrder,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: attributeSchema
+cn: sudoOrder
+distinguishedName: CN=sudoOrder,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+attributeID: 1.3.6.1.4.1.15953.9.1.10
+attributeSyntax: 2.5.5.9
+isSingleValued: TRUE
+showInAdvancedViewOnly: TRUE
+adminDisplayName: sudoOrder
+adminDescription: an integer to order the sudoRole entries
+oMSyntax: 2
+lDAPDisplayName: sudoOrder
+name: sudoOrder
+schemaIDGUID:: 0J8yrRfY4RGIYBUpYYhwmw==
+objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X
+
+dn:
+changetype: modify
+add: schemaUpdateNow
+schemaUpdateNow: 1
+-
+
+dn: CN=sudoRole,CN=Schema,CN=Configuration,DC=X
+changetype: add
+objectClass: top
+objectClass: classSchema
+cn: sudoRole
+distinguishedName: CN=sudoRole,CN=Schema,CN=Configuration,DC=X
+instanceType: 4
+possSuperiors: container
+possSuperiors: top
+subClassOf: top
+governsID: 1.3.6.1.4.1.15953.9.2.1
+mayContain: sudoCommand
+mayContain: sudoHost
+mayContain: sudoOption
+mayContain: sudoRunAs
+mayContain: sudoRunAsUser
+mayContain: sudoRunAsGroup
+mayContain: sudoUser
+mayContain: sudoNotBefore
+mayContain: sudoNotAfter
+mayContain: sudoOrder
+rDNAttID: cn
+showInAdvancedViewOnly: FALSE
+adminDisplayName: sudoRole
+adminDescription: Sudoer Entries
+objectClassCategory: 1
+lDAPDisplayName: sudoRole
+name: sudoRole
+schemaIDGUID:: SQn432lnZ0+ukbdh3+gN3w==
+systemOnly: FALSE
+objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=X
+defaultObjectCategory: CN=sudoRole,CN=Schema,CN=Configuration,DC=X
diff --git a/docs/schema.OpenLDAP b/docs/schema.OpenLDAP
new file mode 100644
index 0000000..451c525
--- /dev/null
+++ b/docs/schema.OpenLDAP
@@ -0,0 +1,78 @@
+#
+# OpenLDAP schema file for Sudo
+# Save as /etc/openldap/schema/sudo.schema and restart slapd.
+# For a version that uses online configuration, see schema.olcSudo.
+#
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.1
+ NAME 'sudoUser'
+ DESC 'User(s) who may run sudo'
+ EQUALITY caseExactMatch
+ SUBSTR caseExactSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.2
+ NAME 'sudoHost'
+ DESC 'Host(s) who may run sudo'
+ EQUALITY caseExactIA5Match
+ SUBSTR caseExactIA5SubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.3
+ NAME 'sudoCommand'
+ DESC 'Command(s) to be executed by sudo'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.4
+ NAME 'sudoRunAs'
+ DESC 'User(s) impersonated by sudo (deprecated)'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.5
+ NAME 'sudoOption'
+ DESC 'Options(s) followed by sudo'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.6
+ NAME 'sudoRunAsUser'
+ DESC 'User(s) impersonated by sudo'
+ EQUALITY caseExactMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.7
+ NAME 'sudoRunAsGroup'
+ DESC 'Group(s) impersonated by sudo'
+ EQUALITY caseExactMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.8
+ NAME 'sudoNotBefore'
+ DESC 'Start of time interval for which the entry is valid'
+ EQUALITY generalizedTimeMatch
+ ORDERING generalizedTimeOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.9
+ NAME 'sudoNotAfter'
+ DESC 'End of time interval for which the entry is valid'
+ EQUALITY generalizedTimeMatch
+ ORDERING generalizedTimeOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.10
+ NAME 'sudoOrder'
+ DESC 'an integer to order the sudoRole entries'
+ EQUALITY integerMatch
+ ORDERING integerOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
+ DESC 'Sudoer Entries'
+ MUST ( cn )
+ MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $
+ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotBefore $
+ sudoNotAfter $ description )
+ )
diff --git a/docs/schema.iPlanet b/docs/schema.iPlanet
new file mode 100644
index 0000000..56ad02b
--- /dev/null
+++ b/docs/schema.iPlanet
@@ -0,0 +1,12 @@
+dn: cn=schema
+attributeTypes: ( 1.3.6.1.4.1.15953.9.1.1 NAME 'sudoUser' DESC 'User(s) who may run sudo' EQUALITY caseExactMatch SUBSTR caseExactSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'SUDO' )
+attributeTypes: ( 1.3.6.1.4.1.15953.9.1.2 NAME 'sudoHost' DESC 'Host(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' )
+attributeTypes: ( 1.3.6.1.4.1.15953.9.1.3 NAME 'sudoCommand' DESC 'Command(s) to be executed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' )
+attributeTypes: ( 1.3.6.1.4.1.15953.9.1.4 NAME 'sudoRunAs' DESC 'User(s) impersonated by sudo (deprecated)' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' )
+attributeTypes: ( 1.3.6.1.4.1.15953.9.1.5 NAME 'sudoOption' DESC 'Options(s) followed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' )
+attributeTypes: ( 1.3.6.1.4.1.15953.9.1.6 NAME 'sudoRunAsUser' DESC 'User(s) impersonated by sudo' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'SUDO' )
+attributeTypes: ( 1.3.6.1.4.1.15953.9.1.7 NAME 'sudoRunAsGroup' DESC 'Group(s) impersonated by sudo' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'SUDO' )
+attributeTypes: ( 1.3.6.1.4.1.15953.9.1.8 NAME 'sudoNotBefore' DESC 'Start of time interval for which the entry is valid' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
+attributeTypes: ( 1.3.6.1.4.1.15953.9.1.9 NAME 'sudoNotAfter' DESC 'End of time interval for which the entry is valid' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
+attributeTypes: ( 1.3.6.1.4.1.15953.9.1.10 NAME 'sudoOrder' DESC 'an integer to order the sudoRole entries' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+objectClasses: ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL DESC 'Sudoer Entries' MUST ( cn ) MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotBefore $ sudoNotAfter $ description ) X-ORIGIN 'SUDO' )
diff --git a/docs/schema.olcSudo b/docs/schema.olcSudo
new file mode 100644
index 0000000..8948ca4
--- /dev/null
+++ b/docs/schema.olcSudo
@@ -0,0 +1,79 @@
+dn: cn=sudoschema,cn=schema,cn=config
+objectClass: olcSchemaConfig
+cn: sudoschema
+#
+# OpenLDAP schema file for Sudo in on-line configuration (OLC) format.
+# Import using ldapadd or another suitable LDAP browser.
+# Converted to OLC format by Frederic Pasteleurs <frederic@askarel.be>
+#
+olcattributetypes: ( 1.3.6.1.4.1.15953.9.1.1
+ NAME 'sudoUser'
+ DESC 'User(s) who may run sudo'
+ EQUALITY caseExactMatch
+ SUBSTR caseExactSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+#
+olcattributetypes: ( 1.3.6.1.4.1.15953.9.1.2
+ NAME 'sudoHost'
+ DESC 'Host(s) who may run sudo'
+ EQUALITY caseExactIA5Match
+ SUBSTR caseExactIA5SubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+#
+olcattributetypes: ( 1.3.6.1.4.1.15953.9.1.3
+ NAME 'sudoCommand'
+ DESC 'Command(s) to be executed by sudo'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+#
+olcattributetypes: ( 1.3.6.1.4.1.15953.9.1.4
+ NAME 'sudoRunAs'
+ DESC 'User(s) impersonated by sudo (deprecated)'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+#
+olcattributetypes: ( 1.3.6.1.4.1.15953.9.1.5
+ NAME 'sudoOption'
+ DESC 'Options(s) followed by sudo'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+#
+olcattributetypes: ( 1.3.6.1.4.1.15953.9.1.6
+ NAME 'sudoRunAsUser'
+ DESC 'User(s) impersonated by sudo'
+ EQUALITY caseExactMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+#
+olcattributetypes: ( 1.3.6.1.4.1.15953.9.1.7
+ NAME 'sudoRunAsGroup'
+ DESC 'Group(s) impersonated by sudo'
+ EQUALITY caseExactMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+#
+olcattributetypes: ( 1.3.6.1.4.1.15953.9.1.8
+ NAME 'sudoNotBefore'
+ DESC 'Start of time interval for which the entry is valid'
+ EQUALITY generalizedTimeMatch
+ ORDERING generalizedTimeOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
+#
+olcattributetypes: ( 1.3.6.1.4.1.15953.9.1.9
+ NAME 'sudoNotAfter'
+ DESC 'End of time interval for which the entry is valid'
+ EQUALITY generalizedTimeMatch
+ ORDERING generalizedTimeOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
+#
+olcattributeTypes: ( 1.3.6.1.4.1.15953.9.1.10
+ NAME 'sudoOrder'
+ DESC 'an integer to order the sudoRole entries'
+ EQUALITY integerMatch
+ ORDERING integerOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+#
+olcobjectclasses: ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
+ DESC 'Sudoer Entries'
+ MUST ( cn )
+ MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotBefore $ sudoNotAfter $
+ description )
+ )
diff --git a/docs/sudo.conf.man.in b/docs/sudo.conf.man.in
new file mode 100644
index 0000000..5c4354e
--- /dev/null
+++ b/docs/sudo.conf.man.in
@@ -0,0 +1,929 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2010-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.nr SL @SEMAN@
+.TH "SUDO.CONF" "@mansectform@" "November 6, 2023" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudo.conf\fR
+\- configuration for sudo front-end
+.SH "DESCRIPTION"
+The
+\fBsudo.conf\fR
+file is used to configure the
+\fBsudo\fR
+front-end.
+It is used to configure sudo plugins, plugin-agnostic path names,
+debug flags, and other settings.
+.PP
+The
+\fBsudo.conf\fR
+file supports the following directives, described in detail below.
+.TP 8n
+Plugin
+an approval, audit, I/O logging, or security policy plugin
+.TP 8n
+Path
+a plugin-agnostic path
+.TP 8n
+Set
+a front-end setting, such as
+\fIdisable_coredump\fR
+or
+\fIgroup_source\fR
+.TP 8n
+Debug
+debug flags to aid in debugging
+\fBsudo\fR,
+\fBsudoreplay\fR,
+\fBvisudo\fR,
+and the
+\fBsudoers\fR
+plugin.
+.PP
+The pound sign
+(\(oq#\(cq)
+is used to indicate a comment.
+Both the comment character and any text after it, up to the end of
+the line, are ignored.
+.PP
+Long lines can be continued with a backslash
+(\(oq\e\(cq)
+as the last character on the line.
+Leading white space is removed from the beginning of lines
+even when a continuation character is used.
+.PP
+Non-comment lines that don't begin with
+\fIPlugin\fR,
+\fIPath\fR,
+\fIDebug\fR,
+or
+\fISet\fR
+are silently ignored.
+.PP
+The
+\fBsudo.conf\fR
+file is always parsed in the
+\(oqC\(cq
+locale.
+.SS "Plugin configuration"
+\fBsudo\fR
+supports a plugin architecture for security policies and input/output
+logging.
+Third parties can develop and distribute their own policy and I/O
+logging plugins to work seamlessly with the
+\fBsudo\fR
+front-end.
+Plugins are dynamically loaded based on the contents of
+\fBsudo.conf\fR.
+.PP
+A
+\fIPlugin\fR
+line consists of the
+\fIPlugin\fR
+keyword, followed by the
+\fIsymbol_name\fR
+and the
+\fIpath\fR
+to the dynamic shared object that contains the plugin.
+The
+\fIsymbol_name\fR
+is the name of the
+\fIstruct approval_plugin\fR,
+\fIstruct audit_plugin\fR,
+\fIstruct io_plugin\fR,
+or
+\fIstruct policy_plugin\fR
+defined by the plugin.
+If a plugin implements multiple plugin types, there must be a
+\fIPlugin\fR
+line for each unique symbol name.
+The
+\fIpath\fR
+may be fully qualified or relative.
+If not fully qualified, it is relative to the directory
+specified by the
+\fIplugin_dir\fR
+\fIPath\fR
+setting, which defaults to
+\fI@plugindir@\fR.
+In other words:
+.nf
+.sp
+.RS 4n
+Plugin sudoers_policy @sudoers_plugin@
+.RE
+.fi
+.PP
+is equivalent to:
+.nf
+.sp
+.RS 4n
+Plugin sudoers_policy @plugindir@/@sudoers_plugin@
+.RE
+.fi
+.PP
+If the plugin was compiled statically into the
+\fBsudo\fR
+binary instead of being installed as a dynamic shared object, the
+\fIpath\fR
+should be specified without a leading directory,
+as it does not actually exist in the file system.
+For example:
+.nf
+.sp
+.RS 4n
+Plugin sudoers_policy @sudoers_plugin@
+.RE
+.fi
+.PP
+On AIX systems, the plugin may be either a shared object
+ending in
+\(oq.so\(cq
+or an archive file containing a shared object ending in
+\(oq.a\(cq
+with the name of the shared object in parentheses at the end.
+.PP
+Starting with
+\fBsudo\fR
+1.8.5, any additional parameters after the
+\fIpath\fR
+are passed as arguments to the plugin's
+\fIopen\fR
+function.
+For example, to override the compile-time default sudoers file mode:
+.nf
+.sp
+.RS 4n
+Plugin sudoers_policy @sudoers_plugin@ sudoers_mode=0440
+.RE
+.fi
+.PP
+See the
+sudoers(@mansectform@)
+manual for a list of supported arguments.
+.PP
+The same dynamic shared object may contain multiple plugins,
+each with a different symbol name.
+The file must be owned by user-ID 0 and only writable by its owner.
+Because of ambiguities that arise from composite policies, only a single
+policy plugin may be specified.
+This limitation does not apply to I/O plugins.
+.PP
+If no
+\fBsudo.conf\fR
+file is present, or if it contains no
+\fIPlugin\fR
+lines, the
+\fBsudoers\fR
+plugin will be used as the default security policy, for I/O logging
+(if enabled by the policy), and for auditing.
+This is equivalent to the following:
+.nf
+.sp
+.RS 4n
+Plugin sudoers_policy @sudoers_plugin@
+Plugin sudoers_io @sudoers_plugin@
+Plugin sudoers_audit @sudoers_plugin@
+.RE
+.fi
+.PP
+Starting with
+\fBsudo\fR
+version 1.9.1, some of the logging functionality of the
+\fBsudoers\fR
+plugin has been moved from the policy plugin to an audit plugin.
+To maintain compatibility with
+\fBsudo.conf\fR
+files from older
+\fBsudo\fR
+versions, if
+\fBsudoers\fR
+is configured as the security policy, it will be used as an audit
+plugin as well.
+This guarantees that the logging behavior will be consistent with that of
+\fBsudo\fR
+versions 1.9.0 and below.
+.PP
+For more information on the
+\fBsudo\fR
+plugin architecture, see the
+sudo_plugin(@mansectform@)
+manual.
+.SS "Path settings"
+A
+\fIPath\fR
+line consists of the
+\fIPath\fR
+keyword, followed by the name of the path to set and its value.
+For example:
+.nf
+.sp
+.RS 4n
+Path intercept @intercept_file@
+Path noexec @noexec_file@
+Path askpass /usr/X11R6/bin/ssh-askpass
+.RE
+.fi
+.PP
+If no path name is specified, features relying on the specified
+setting will be disabled.
+Disabling
+\fIPath\fR
+settings is only supported in
+\fBsudo\fR
+version 1.8.16 and higher.
+.PP
+The following plugin-agnostic paths may be set in the
+\fI@sysconfdir@/sudo.conf\fR
+file:
+.TP 6n
+askpass
+The fully qualified path to a helper program used to read the user's
+password when no terminal is available.
+This may be the case when
+\fBsudo\fR
+is executed from a graphical (as opposed to text-based) application.
+The program specified by
+\fIaskpass\fR
+should display the argument passed to it as the prompt and write
+the user's password to the standard output.
+The value of
+\fIaskpass\fR
+may be overridden by the
+\fRSUDO_ASKPASS\fR
+environment variable.
+.TP 6n
+devsearch
+An ordered, colon-separated search path of directories to look in for
+device nodes.
+This is used when mapping the process's tty device number to a device name
+on systems that do not provide such a mechanism.
+Sudo will
+\fInot\fR
+recurse into sub-directories.
+If terminal devices may be located in a sub-directory of
+\fI/dev\fR,
+that path must be explicitly listed in
+\fIdevsearch\fR.
+The default value is
+\fI/dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev\fR
+.sp
+This option is ignored on systems that support either the
+\fBdevname\fR()
+or
+\fB_ttyname_dev\fR()
+functions, for example
+BSD,
+macOS and Solaris.
+.TP 6n
+intercept
+The path to a shared library containing a wrappers for the
+execve(2),
+execl(3),
+execle(3),
+execlp(3),
+execv(3),
+execvp(3),
+execvpe(3),
+and
+system(3)
+library functions that intercepts attempts to run further commands and
+performs a policy check before allowing them to be executed.
+This is used to implement the
+\fIintercept\fR
+and
+\fIlog_subcmds\fR
+functionality on systems that support
+\fRLD_PRELOAD\fR
+or the equivalent.
+.sp
+The
+\fIintercept\fR
+path may be set to either a single fully-qualified path, or, for systems
+that support separate
+\fRLD_PRELOAD\fR
+environment variables for 32-bit and 64-bit executables, it may optionally
+be set to two fully-qualified paths separated by a colon
+(\(oq:\&\(cq).
+The first path should be the 32-bit version and the second the
+64-bit version.
+This two-path form is currently only supported on AIX and Solaris
+systems.
+The default value is
+\fI@intercept_file@\fR.
+.TP 6n
+noexec
+The path to a shared library containing wrappers for the
+execve(2),
+execl(3),
+execle(3),
+execlp(3),
+exect(3),
+execv(3),
+execveat(3),
+execvP(3),
+execvp(3),
+execvpe(3),
+fexecve(3),
+popen(3),
+posix_spawn(3),
+posix_spawnp(3),
+system(3),
+and
+wordexp(3)
+library functions that prevent the execution of further commands.
+This is used to implement the
+\fInoexec\fR
+functionality on systems that support
+\fRLD_PRELOAD\fR
+or the equivalent.
+.sp
+The
+\fInoexec\fR
+path may be set to either a single fully-qualified path, or, for systems
+that support separate
+\fRLD_PRELOAD\fR
+environment variables for 32-bit and 64-bit executables, it may optionally
+be set to two fully-qualified paths separated by a colon
+(\(oq:\&\(cq).
+The first path should be the 32-bit version and the second the
+64-bit version.
+This two-path form is currently only supported on AIX and Solaris
+systems.
+The default value is
+\fI@noexec_file@\fR.
+.TP 6n
+plugin_dir
+The default directory to use when searching for plugins
+that are specified without a fully qualified path name.
+The default value is
+\fI@plugindir@\fR.
+.TP 6n
+sesh
+The fully-qualified path to the
+\fBsesh\fR
+binary.
+This setting is only used when
+\fBsudo\fR
+is built with SELinux support.
+The default value is
+\fI@sesh_file@\fR.
+.\}
+.SS "Other settings"
+The
+\fBsudo.conf\fR
+file also supports the following front-end settings:
+.TP 6n
+disable_coredump
+Core dumps of
+\fBsudo\fR
+itself are disabled by default to prevent the disclosure of potentially
+sensitive information.
+To aid in debugging
+\fBsudo\fR
+crashes, you may wish to re-enable core dumps by setting
+\(lqdisable_coredump\(rq
+to false in
+\fBsudo.conf\fR
+as follows:
+.nf
+.sp
+.RS 10n
+Set disable_coredump false
+.RE
+.fi
+.RS 6n
+.sp
+All modern operating systems place restrictions on core dumps
+from set-user-ID processes like
+\fBsudo\fR
+so this option can be enabled without compromising security.
+To actually get a
+\fBsudo\fR
+core file you will likely need to enable core dumps for set-user-ID processes.
+On
+BSD
+and Linux systems this is accomplished in the
+sysctl(@mansectsu@)
+command.
+On Solaris, the
+coreadm(1m)
+command is used to configure core dump behavior.
+.sp
+This setting is only available in
+\fBsudo\fR
+version 1.8.4 and higher.
+.RE
+.TP 6n
+group_source
+\fBsudo\fR
+passes the invoking user's group list to the policy and I/O plugins.
+On most systems, there is an upper limit to the number of groups that
+a user may belong to simultaneously (typically 16 for compatibility
+with NFS).
+On systems with the
+getconf(1)
+utility, running:
+.RS 12n
+getconf NGROUPS_MAX
+.RE
+.RS 6n
+will return the maximum number of groups.
+.sp
+However, it is still possible to be a member of a larger number of
+groups--they simply won't be included in the group list returned
+by the kernel for the user.
+Starting with
+\fBsudo\fR
+version 1.8.7, if the user's kernel group list has the maximum number
+of entries,
+\fBsudo\fR
+will consult the group database directly to determine the group list.
+This makes it possible for the security policy to perform matching by group
+name even when the user is a member of more than the maximum number of groups.
+.sp
+The
+\fIgroup_source\fR
+setting allows the administrator to change this default behavior.
+Supported values for
+\fIgroup_source\fR
+are:
+.TP 6n
+static
+Use the static group list that the kernel returns.
+Retrieving the group list this way is very fast but it is subject
+to an upper limit as described above.
+It is
+\(lqstatic\(rq
+in that it does not reflect changes to the group database made
+after the user logs in.
+This was the default behavior prior to
+\fBsudo\fR
+1.8.7.
+.TP 6n
+dynamic
+Always query the group database directly.
+It is
+\(lqdynamic\(rq
+in that changes made to the group database after the user logs in
+will be reflected in the group list.
+On some systems, querying the group database for all of a user's
+groups can be time consuming when querying a network-based group
+database.
+Most operating systems provide an efficient method of performing
+such queries.
+Currently,
+\fBsudo\fR
+supports efficient group queries on AIX,
+BSD,
+Linux, macOS, and Solaris.
+This is the default behavior on macOS in
+\fBsudo\fR
+1.9.6 and higher.
+.TP 6n
+adaptive
+Only query the group database if the static group list returned
+by the kernel has the maximum number of entries.
+This is the default behavior on systems other than macOS in
+\fBsudo\fR
+1.8.7 and higher.
+.PP
+For example, to cause
+\fBsudo\fR
+to only use the kernel's static list of groups for the user:
+.nf
+.sp
+.RS 10n
+Set group_source static
+.RE
+.fi
+.sp
+This setting is only available in
+\fBsudo\fR
+version 1.8.7 and higher.
+.RE
+.TP 6n
+max_groups
+The maximum number of user groups to retrieve from the group database.
+Values less than one or larger than 1024 will be ignored.
+This setting is only used when querying the group database directly.
+It is intended to be used on systems where it is not possible to detect
+when the array to be populated with group entries is not sufficiently large.
+By default,
+\fBsudo\fR
+will allocate four times the system's maximum number of groups (see above)
+and retry with double that number if the group database query fails.
+.sp
+This setting is only available in
+\fBsudo\fR
+version 1.8.7 and higher.
+It should not be required in
+\fBsudo\fR
+versions 1.8.24 and higher and may be removed in a later release.
+.TP 6n
+probe_interfaces
+By default,
+\fBsudo\fR
+will probe the system's network interfaces and pass the IP address
+of each enabled interface to the policy plugin.
+This makes it possible for the plugin to match rules based on the IP address
+without having to query DNS.
+On Linux systems with a large number of virtual interfaces, this may
+take a non-negligible amount of time.
+If IP-based matching is not required, network interface probing
+can be disabled as follows:
+.nf
+.sp
+.RS 10n
+Set probe_interfaces false
+.RE
+.fi
+.RS 6n
+.sp
+This setting is only available in
+\fBsudo\fR
+version 1.8.10 and higher.
+.RE
+.SS "Debug settings"
+\fBsudo\fR
+versions 1.8.4 and higher support a flexible debugging framework
+that can log what
+\fBsudo\fR
+is doing internally if there is a problem.
+.PP
+A
+\fIDebug\fR
+line consists of the
+\fIDebug\fR
+keyword, followed by the name of the program, plugin, or shared object
+to debug, the debug file name, and a comma-separated list of debug flags.
+The debug flag syntax used by
+\fBsudo\fR,
+the
+\fBsudoers\fR
+plugin along with its associated programs and shared objects is
+\fIsubsystem\fR@\fIpriority\fR
+but a third-party plugin is free to use a different format so long
+as it does not include a comma
+(\(oq\&,\(cq).
+.PP
+On AIX systems, a
+\fIDebug\fR
+line will match a plugin specified as either the name of an
+SVR4-style shared object file ending in
+\(oq.so\(cq,
+an archive file ending in
+\(oq.a\(cq,
+or an archive file ending in
+\(oq.a\(cq
+with the name of the shared object in parentheses.
+.PP
+Examples:
+.nf
+.sp
+.RS 4n
+Debug sudo @log_dir@/sudo_debug all@warn,plugin@info
+.RE
+.fi
+.PP
+would log all debugging statements at the
+\fIwarn\fR
+level and higher in addition to those at the
+\fIinfo\fR
+level for the plugin subsystem.
+.nf
+.sp
+.RS 4n
+Debug sudo_intercept.so @log_dir@/intercept_debug all@debug
+.RE
+.fi
+.PP
+would log all debugging statements, regardless of level, for the
+\fIsudo_intercept.so\fR
+shared library that implements
+\fBsudo\fR's
+intercept functionality on some systems.
+.nf
+.sp
+.RS 4n
+Debug @sudoers_plugin@ @log_dir@/sudoers_debug all@debug
+.RE
+.fi
+.PP
+would log all debugging statements, regardless of level, for the
+\fBsudoers\fR
+plugin.
+See
+sudoers(@mansectform@)
+for the full list of subsystems supported by the
+\fBsudoers\fR
+plugin.
+.PP
+As of
+\fBsudo\fR
+1.8.12, multiple
+\fIDebug\fR
+entries may be specified per program.
+Older versions of
+\fBsudo\fR
+only support a single
+\fIDebug\fR
+entry per program.
+Plugin-specific
+\fIDebug\fR
+entries are also supported starting with
+\fBsudo\fR
+1.8.12 and are matched by either the base name of the plugin that was loaded
+(for example
+\fI@sudoers_plugin@\fR)
+or by the plugin's fully-qualified path name.
+Previously, the
+\fBsudoers\fR
+plugin shared the same
+\fIDebug\fR
+entry as the
+\fBsudo\fR
+front-end and could not be configured separately.
+.PP
+The following priorities are supported, in order of decreasing severity:
+\fIcrit\fR, \fIerr\fR, \fIwarn\fR, \fInotice\fR, \fIdiag\fR, \fIinfo\fR, \fItrace\fR,
+and
+\fIdebug\fR.
+Each priority, when specified, also includes all priorities higher
+than it.
+For example, a priority of
+\fInotice\fR
+would include debug messages logged at
+\fInotice\fR
+and higher.
+.PP
+The priorities
+\fItrace\fR
+and
+\fIdebug\fR
+also include function call tracing which logs when a function is
+entered and when it returns.
+For example, the following trace is for the
+\fBget_user_groups\fR()
+function located in src/sudo.c:
+.nf
+.sp
+.RS 4n
+sudo[123] -> get_user_groups @ src/sudo.c:385
+sudo[123] <- get_user_groups @ src/sudo.c:429 := groups=10,0,5
+.RE
+.fi
+.PP
+When the function is entered, indicated by a right arrow
+\(oq->\(cq,
+the program, process ID, function, source file, and line number
+are logged.
+When the function returns, indicated by a left arrow
+\(oq<-\(cq,
+the same information is logged along with the return value.
+In this case, the return value is a string.
+.PP
+The following subsystems are used by the
+\fBsudo\fR
+front-end:
+.TP 12n
+\fIall\fR
+matches every subsystem
+.TP 12n
+\fIargs\fR
+command line argument processing
+.TP 12n
+\fIconv\fR
+user conversation
+.TP 12n
+\fIedit\fR
+sudoedit
+.TP 12n
+\fIevent\fR
+event subsystem
+.TP 12n
+\fIexec\fR
+command execution
+.TP 12n
+\fImain\fR
+\fBsudo\fR
+main function
+.TP 12n
+\fInetif\fR
+network interface handling
+.TP 12n
+\fIpcomm\fR
+communication with the plugin
+.TP 12n
+\fIplugin\fR
+plugin configuration
+.TP 12n
+\fIpty\fR
+pseudo-terminal related code
+.TP 12n
+\fIselinux\fR
+SELinux-specific handling
+.TP 12n
+\fIutil\fR
+utility functions
+.TP 12n
+\fIutmp\fR
+utmp handling
+.PP
+The
+sudoers(@mansectform@)
+plugin includes support for additional subsystems.
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/sudo.conf\fR
+\fBsudo\fR
+front-end configuration
+.SH "EXAMPLES"
+.nf
+.RS 0n
+#
+# Default @sysconfdir@/sudo.conf file
+#
+# Sudo plugins:
+# Plugin plugin_name plugin_path plugin_options ...
+#
+# The plugin_path is relative to @plugindir@ unless
+# fully qualified.
+# The plugin_name corresponds to a global symbol in the plugin
+# that contains the plugin interface structure.
+# The plugin_options are optional.
+#
+# The sudoers plugin is used by default if no Plugin lines are present.
+#Plugin sudoers_policy @sudoers_plugin@
+#Plugin sudoers_io @sudoers_plugin@
+#Plugin sudoers_audit @sudoers_plugin@
+
+#
+# Sudo askpass:
+# Path askpass /path/to/askpass
+#
+# An askpass helper program may be specified to provide a graphical
+# password prompt for "sudo -A" support. Sudo does not ship with its
+# own askpass program but can use the OpenSSH askpass.
+#
+# Use the OpenSSH askpass
+#Path askpass /usr/X11R6/bin/ssh-askpass
+#
+# Use the Gnome OpenSSH askpass
+#Path askpass /usr/libexec/openssh/gnome-ssh-askpass
+
+#
+# Sudo device search path:
+# Path devsearch /dev/path1:/dev/path2:/dev
+#
+# A colon-separated list of paths to check when searching for a user's
+# terminal device.
+#
+#Path devsearch /dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev
+
+#
+# Sudo command interception:
+# Path intercept /path/to/sudo_intercept.so
+#
+# Path to a shared library containing replacements for the execv()
+# and execve() library functions that perform a policy check to verify
+# the command is allowed and simply return an error if not. This is
+# used to implement the "intercept" functionality on systems that
+# support LD_PRELOAD or its equivalent.
+#
+# The compiled-in value is usually sufficient and should only be changed
+# if you rename or move the sudo_intercept.so file.
+#
+#Path intercept @intercept_file@
+
+#
+# Sudo noexec:
+# Path noexec /path/to/sudo_noexec.so
+#
+# Path to a shared library containing replacements for the execv()
+# family of library functions that just return an error. This is
+# used to implement the "noexec" functionality on systems that support
+# LD_PRELOAD or its equivalent.
+#
+# The compiled-in value is usually sufficient and should only be changed
+# if you rename or move the sudo_noexec.so file.
+#
+#Path noexec @noexec_file@
+
+#
+# Sudo plugin directory:
+# Path plugin_dir /path/to/plugins
+#
+# The default directory to use when searching for plugins that are
+# specified without a fully qualified path name.
+#
+#Path plugin_dir @plugindir@
+
+#
+# Core dumps:
+# Set disable_coredump true|false
+#
+# By default, sudo disables core dumps while it is executing (they
+# are re-enabled for the command that is run).
+# To aid in debugging sudo problems, you may wish to enable core
+# dumps by setting "disable_coredump" to false.
+#
+#Set disable_coredump false
+
+#
+# User groups:
+# Set group_source static|dynamic|adaptive
+#
+# Sudo passes the user's group list to the policy plugin.
+# If the user is a member of the maximum number of groups (usually 16),
+# sudo will query the group database directly to be sure to include
+# the full list of groups.
+#
+# On some systems, this can be expensive so the behavior is configurable.
+# The "group_source" setting has three possible values:
+# static - use the user's list of groups returned by the kernel.
+# dynamic - query the group database to find the list of groups.
+# adaptive - if user is in less than the maximum number of groups.
+# use the kernel list, else query the group database.
+#
+#Set group_source static
+
+#
+# Sudo interface probing:
+# Set probe_interfaces true|false
+#
+# By default, sudo will probe the system's network interfaces and
+# pass the IP address of each enabled interface to the policy plugin.
+# On systems with a large number of virtual interfaces this may take
+# a noticeable amount of time.
+#
+#Set probe_interfaces false
+
+#
+# Sudo debug files:
+# Debug program /path/to/debug_log subsystem@priority[,subsyste@priority]
+#
+# Sudo and related programs support logging debug information to a file.
+# The program is typically sudo, sudoers.so, sudoreplay, or visudo.
+#
+# Subsystems vary based on the program; "all" matches all subsystems.
+# Priority may be crit, err, warn, notice, diag, info, trace, or debug.
+# Multiple subsystem@priority may be specified, separated by a comma.
+#
+#Debug sudo @log_dir@/sudo_debug all@debug
+#Debug @sudoers_plugin@ @log_dir@/sudoers_debug all@debug
+.RE
+.fi
+.SH "SEE ALSO"
+sudo_plugin(@mansectform@),
+sudoers(@mansectform@),
+sudo(@mansectsu@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS.md file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you believe you have found a bug in
+\fBsudo\fR,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudo.conf.man.in.sed b/docs/sudo.conf.man.in.sed
new file mode 100644
index 0000000..2534bc8
--- /dev/null
+++ b/docs/sudo.conf.man.in.sed
@@ -0,0 +1,15 @@
+s/^\(.TH .*\)/.nr SL @SEMAN@\
+\1/
+
+/^\.TP 10n$/ {
+ N
+ /^.TP 10n\nsesh$/ {
+ i\
+.if \\n(SL \\{\\
+ }
+}
+
+/^\\fI@sesh_file@\\fR\.$/ {
+ a\
+.\\}
+}
diff --git a/docs/sudo.conf.mdoc.in b/docs/sudo.conf.mdoc.in
new file mode 100644
index 0000000..3359b0d
--- /dev/null
+++ b/docs/sudo.conf.mdoc.in
@@ -0,0 +1,859 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2010-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.nr SL @SEMAN@
+.Dd November 6, 2023
+.Dt SUDO.CONF @mansectform@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudo.conf
+.Nd configuration for sudo front-end
+.Sh DESCRIPTION
+The
+.Nm sudo.conf
+file is used to configure the
+.Nm sudo
+front-end.
+It is used to configure sudo plugins, plugin-agnostic path names,
+debug flags, and other settings.
+.Pp
+The
+.Nm
+file supports the following directives, described in detail below.
+.Bl -tag -width "Plugin"
+.It Plugin
+an approval, audit, I/O logging, or security policy plugin
+.It Path
+a plugin-agnostic path
+.It Set
+a front-end setting, such as
+.Em disable_coredump
+or
+.Em group_source
+.It Debug
+debug flags to aid in debugging
+.Nm sudo ,
+.Nm sudoreplay ,
+.Nm visudo ,
+and the
+.Nm sudoers
+plugin.
+.El
+.Pp
+The pound sign
+.Pq Ql #
+is used to indicate a comment.
+Both the comment character and any text after it, up to the end of
+the line, are ignored.
+.Pp
+Long lines can be continued with a backslash
+.Pq Ql \e
+as the last character on the line.
+Leading white space is removed from the beginning of lines
+even when a continuation character is used.
+.Pp
+Non-comment lines that don't begin with
+.Em Plugin ,
+.Em Path ,
+.Em Debug ,
+or
+.Em Set
+are silently ignored.
+.Pp
+The
+.Nm
+file is always parsed in the
+.Ql C
+locale.
+.Ss Plugin configuration
+.Nm sudo
+supports a plugin architecture for security policies and input/output
+logging.
+Third parties can develop and distribute their own policy and I/O
+logging plugins to work seamlessly with the
+.Nm sudo
+front-end.
+Plugins are dynamically loaded based on the contents of
+.Nm .
+.Pp
+A
+.Em Plugin
+line consists of the
+.Em Plugin
+keyword, followed by the
+.Em symbol_name
+and the
+.Em path
+to the dynamic shared object that contains the plugin.
+The
+.Em symbol_name
+is the name of the
+.Vt struct approval_plugin ,
+.Vt struct audit_plugin ,
+.Vt struct io_plugin ,
+or
+.Vt struct policy_plugin
+defined by the plugin.
+If a plugin implements multiple plugin types, there must be a
+.Em Plugin
+line for each unique symbol name.
+The
+.Em path
+may be fully qualified or relative.
+If not fully qualified, it is relative to the directory
+specified by the
+.Em plugin_dir
+.Em Path
+setting, which defaults to
+.Pa @plugindir@ .
+In other words:
+.Bd -literal -offset 4n
+Plugin sudoers_policy @sudoers_plugin@
+.Ed
+.Pp
+is equivalent to:
+.Bd -literal -offset 4n
+Plugin sudoers_policy @plugindir@/@sudoers_plugin@
+.Ed
+.Pp
+If the plugin was compiled statically into the
+.Nm sudo
+binary instead of being installed as a dynamic shared object, the
+.Em path
+should be specified without a leading directory,
+as it does not actually exist in the file system.
+For example:
+.Bd -literal -offset 4n
+Plugin sudoers_policy @sudoers_plugin@
+.Ed
+.Pp
+On AIX systems, the plugin may be either a shared object
+ending in
+.Ql .so
+or an archive file containing a shared object ending in
+.Ql .a
+with the name of the shared object in parentheses at the end.
+.Pp
+Starting with
+.Nm sudo
+1.8.5, any additional parameters after the
+.Em path
+are passed as arguments to the plugin's
+.Em open
+function.
+For example, to override the compile-time default sudoers file mode:
+.Bd -literal -offset 4n
+Plugin sudoers_policy @sudoers_plugin@ sudoers_mode=0440
+.Ed
+.Pp
+See the
+.Xr sudoers @mansectform@
+manual for a list of supported arguments.
+.Pp
+The same dynamic shared object may contain multiple plugins,
+each with a different symbol name.
+The file must be owned by user-ID 0 and only writable by its owner.
+Because of ambiguities that arise from composite policies, only a single
+policy plugin may be specified.
+This limitation does not apply to I/O plugins.
+.Pp
+If no
+.Nm
+file is present, or if it contains no
+.Em Plugin
+lines, the
+.Nm sudoers
+plugin will be used as the default security policy, for I/O logging
+(if enabled by the policy), and for auditing.
+This is equivalent to the following:
+.Bd -literal -offset 4n
+Plugin sudoers_policy @sudoers_plugin@
+Plugin sudoers_io @sudoers_plugin@
+Plugin sudoers_audit @sudoers_plugin@
+.Ed
+.Pp
+Starting with
+.Nm sudo
+version 1.9.1, some of the logging functionality of the
+.Nm sudoers
+plugin has been moved from the policy plugin to an audit plugin.
+To maintain compatibility with
+.Nm
+files from older
+.Nm sudo
+versions, if
+.Nm sudoers
+is configured as the security policy, it will be used as an audit
+plugin as well.
+This guarantees that the logging behavior will be consistent with that of
+.Nm sudo
+versions 1.9.0 and below.
+.Pp
+For more information on the
+.Nm sudo
+plugin architecture, see the
+.Xr sudo_plugin @mansectform@
+manual.
+.Ss Path settings
+A
+.Em Path
+line consists of the
+.Em Path
+keyword, followed by the name of the path to set and its value.
+For example:
+.Bd -literal -offset 4n
+Path intercept @intercept_file@
+Path noexec @noexec_file@
+Path askpass /usr/X11R6/bin/ssh-askpass
+.Ed
+.Pp
+If no path name is specified, features relying on the specified
+setting will be disabled.
+Disabling
+.Em Path
+settings is only supported in
+.Nm sudo
+version 1.8.16 and higher.
+.Pp
+The following plugin-agnostic paths may be set in the
+.Pa @sysconfdir@/sudo.conf
+file:
+.Bl -tag -width 4n
+.It askpass
+The fully qualified path to a helper program used to read the user's
+password when no terminal is available.
+This may be the case when
+.Nm sudo
+is executed from a graphical (as opposed to text-based) application.
+The program specified by
+.Em askpass
+should display the argument passed to it as the prompt and write
+the user's password to the standard output.
+The value of
+.Em askpass
+may be overridden by the
+.Ev SUDO_ASKPASS
+environment variable.
+.It devsearch
+An ordered, colon-separated search path of directories to look in for
+device nodes.
+This is used when mapping the process's tty device number to a device name
+on systems that do not provide such a mechanism.
+Sudo will
+.Em not
+recurse into sub-directories.
+If terminal devices may be located in a sub-directory of
+.Pa /dev ,
+that path must be explicitly listed in
+.Em devsearch .
+The default value is
+.Pa /dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev
+.Pp
+This option is ignored on systems that support either the
+.Fn devname
+or
+.Fn _ttyname_dev
+functions, for example
+.Bx ,
+macOS and Solaris.
+.It intercept
+The path to a shared library containing a wrappers for the
+.Xr execve 2 ,
+.Xr execl 3 ,
+.Xr execle 3 ,
+.Xr execlp 3 ,
+.Xr execv 3 ,
+.Xr execvp 3 ,
+.Xr execvpe 3 ,
+and
+.Xr system 3
+library functions that intercepts attempts to run further commands and
+performs a policy check before allowing them to be executed.
+This is used to implement the
+.Em intercept
+and
+.Em log_subcmds
+functionality on systems that support
+.Ev LD_PRELOAD
+or the equivalent.
+.Pp
+The
+.Em intercept
+path may be set to either a single fully-qualified path, or, for systems
+that support separate
+.Dv LD_PRELOAD
+environment variables for 32-bit and 64-bit executables, it may optionally
+be set to two fully-qualified paths separated by a colon
+.Pq Ql :\& .
+The first path should be the 32-bit version and the second the
+64-bit version.
+This two-path form is currently only supported on AIX and Solaris
+systems.
+The default value is
+.Pa @intercept_file@ .
+.It noexec
+The path to a shared library containing wrappers for the
+.Xr execve 2 ,
+.Xr execl 3 ,
+.Xr execle 3 ,
+.Xr execlp 3 ,
+.Xr exect 3 ,
+.Xr execv 3 ,
+.Xr execveat 3 ,
+.Xr execvP 3 ,
+.Xr execvp 3 ,
+.Xr execvpe 3 ,
+.Xr fexecve 3 ,
+.Xr popen 3 ,
+.Xr posix_spawn 3 ,
+.Xr posix_spawnp 3 ,
+.Xr system 3 ,
+and
+.Xr wordexp 3
+library functions that prevent the execution of further commands.
+This is used to implement the
+.Em noexec
+functionality on systems that support
+.Ev LD_PRELOAD
+or the equivalent.
+.Pp
+The
+.Em noexec
+path may be set to either a single fully-qualified path, or, for systems
+that support separate
+.Dv LD_PRELOAD
+environment variables for 32-bit and 64-bit executables, it may optionally
+be set to two fully-qualified paths separated by a colon
+.Pq Ql :\& .
+The first path should be the 32-bit version and the second the
+64-bit version.
+This two-path form is currently only supported on AIX and Solaris
+systems.
+The default value is
+.Pa @noexec_file@ .
+.It plugin_dir
+The default directory to use when searching for plugins
+that are specified without a fully qualified path name.
+The default value is
+.Pa @plugindir@ .
+.if \n(SL \{\
+.It sesh
+The fully-qualified path to the
+.Nm sesh
+binary.
+This setting is only used when
+.Nm sudo
+is built with SELinux support.
+The default value is
+.Pa @sesh_file@ .
+.\}
+.El
+.Ss Other settings
+The
+.Nm
+file also supports the following front-end settings:
+.Bl -tag -width 4n
+.It disable_coredump
+Core dumps of
+.Nm sudo
+itself are disabled by default to prevent the disclosure of potentially
+sensitive information.
+To aid in debugging
+.Nm sudo
+crashes, you may wish to re-enable core dumps by setting
+.Dq disable_coredump
+to false in
+.Nm
+as follows:
+.Bd -literal -offset 4n
+Set disable_coredump false
+.Ed
+.Pp
+All modern operating systems place restrictions on core dumps
+from set-user-ID processes like
+.Nm sudo
+so this option can be enabled without compromising security.
+To actually get a
+.Nm sudo
+core file you will likely need to enable core dumps for set-user-ID processes.
+On
+.Bx
+and Linux systems this is accomplished in the
+.Xr sysctl 8
+command.
+On Solaris, the
+.Xr coreadm 1m
+command is used to configure core dump behavior.
+.Pp
+This setting is only available in
+.Nm sudo
+version 1.8.4 and higher.
+.It group_source
+.Nm sudo
+passes the invoking user's group list to the policy and I/O plugins.
+On most systems, there is an upper limit to the number of groups that
+a user may belong to simultaneously (typically 16 for compatibility
+with NFS).
+On systems with the
+.Xr getconf 1
+utility, running:
+.Dl getconf NGROUPS_MAX
+will return the maximum number of groups.
+.Pp
+However, it is still possible to be a member of a larger number of
+groups--they simply won't be included in the group list returned
+by the kernel for the user.
+Starting with
+.Nm sudo
+version 1.8.7, if the user's kernel group list has the maximum number
+of entries,
+.Nm sudo
+will consult the group database directly to determine the group list.
+This makes it possible for the security policy to perform matching by group
+name even when the user is a member of more than the maximum number of groups.
+.Pp
+The
+.Em group_source
+setting allows the administrator to change this default behavior.
+Supported values for
+.Em group_source
+are:
+.Bl -tag -width 4n
+.It static
+Use the static group list that the kernel returns.
+Retrieving the group list this way is very fast but it is subject
+to an upper limit as described above.
+It is
+.Dq static
+in that it does not reflect changes to the group database made
+after the user logs in.
+This was the default behavior prior to
+.Nm sudo
+1.8.7.
+.It dynamic
+Always query the group database directly.
+It is
+.Dq dynamic
+in that changes made to the group database after the user logs in
+will be reflected in the group list.
+On some systems, querying the group database for all of a user's
+groups can be time consuming when querying a network-based group
+database.
+Most operating systems provide an efficient method of performing
+such queries.
+Currently,
+.Nm sudo
+supports efficient group queries on AIX,
+.Bx ,
+Linux, macOS, and Solaris.
+This is the default behavior on macOS in
+.Nm sudo
+1.9.6 and higher.
+.It adaptive
+Only query the group database if the static group list returned
+by the kernel has the maximum number of entries.
+This is the default behavior on systems other than macOS in
+.Nm sudo
+1.8.7 and higher.
+.El
+.Pp
+For example, to cause
+.Nm sudo
+to only use the kernel's static list of groups for the user:
+.Bd -literal -offset 4n
+Set group_source static
+.Ed
+.Pp
+This setting is only available in
+.Nm sudo
+version 1.8.7 and higher.
+.It max_groups
+The maximum number of user groups to retrieve from the group database.
+Values less than one or larger than 1024 will be ignored.
+This setting is only used when querying the group database directly.
+It is intended to be used on systems where it is not possible to detect
+when the array to be populated with group entries is not sufficiently large.
+By default,
+.Nm sudo
+will allocate four times the system's maximum number of groups (see above)
+and retry with double that number if the group database query fails.
+.Pp
+This setting is only available in
+.Nm sudo
+version 1.8.7 and higher.
+It should not be required in
+.Nm sudo
+versions 1.8.24 and higher and may be removed in a later release.
+.It probe_interfaces
+By default,
+.Nm sudo
+will probe the system's network interfaces and pass the IP address
+of each enabled interface to the policy plugin.
+This makes it possible for the plugin to match rules based on the IP address
+without having to query DNS.
+On Linux systems with a large number of virtual interfaces, this may
+take a non-negligible amount of time.
+If IP-based matching is not required, network interface probing
+can be disabled as follows:
+.Bd -literal -offset 4n
+Set probe_interfaces false
+.Ed
+.Pp
+This setting is only available in
+.Nm sudo
+version 1.8.10 and higher.
+.El
+.Ss Debug settings
+.Nm sudo
+versions 1.8.4 and higher support a flexible debugging framework
+that can log what
+.Nm sudo
+is doing internally if there is a problem.
+.Pp
+A
+.Em Debug
+line consists of the
+.Em Debug
+keyword, followed by the name of the program, plugin, or shared object
+to debug, the debug file name, and a comma-separated list of debug flags.
+The debug flag syntax used by
+.Nm sudo ,
+the
+.Nm sudoers
+plugin along with its associated programs and shared objects is
+.Em subsystem Ns @ Ns Em priority
+but a third-party plugin is free to use a different format so long
+as it does not include a comma
+.Pq Ql \&, .
+.Pp
+On AIX systems, a
+.Em Debug
+line will match a plugin specified as either the name of an
+SVR4-style shared object file ending in
+.Ql .so ,
+an archive file ending in
+.Ql .a ,
+or an archive file ending in
+.Ql .a
+with the name of the shared object in parentheses.
+.Pp
+Examples:
+.Bd -literal -offset 4n
+Debug sudo @log_dir@/sudo_debug all@warn,plugin@info
+.Ed
+.Pp
+would log all debugging statements at the
+.Em warn
+level and higher in addition to those at the
+.Em info
+level for the plugin subsystem.
+.Bd -literal -offset 4n
+Debug sudo_intercept.so @log_dir@/intercept_debug all@debug
+.Ed
+.Pp
+would log all debugging statements, regardless of level, for the
+.Pa sudo_intercept.so
+shared library that implements
+.Nm sudo Ns 's
+intercept functionality on some systems.
+.Bd -literal -offset 4n
+Debug @sudoers_plugin@ @log_dir@/sudoers_debug all@debug
+.Ed
+.Pp
+would log all debugging statements, regardless of level, for the
+.Nm sudoers
+plugin.
+See
+.Xr sudoers @mansectform@
+for the full list of subsystems supported by the
+.Nm sudoers
+plugin.
+.Pp
+As of
+.Nm sudo
+1.8.12, multiple
+.Em Debug
+entries may be specified per program.
+Older versions of
+.Nm sudo
+only support a single
+.Em Debug
+entry per program.
+Plugin-specific
+.Em Debug
+entries are also supported starting with
+.Nm sudo
+1.8.12 and are matched by either the base name of the plugin that was loaded
+(for example
+.Pa @sudoers_plugin@ )
+or by the plugin's fully-qualified path name.
+Previously, the
+.Nm sudoers
+plugin shared the same
+.Em Debug
+entry as the
+.Nm sudo
+front-end and could not be configured separately.
+.Pp
+The following priorities are supported, in order of decreasing severity:
+.Em crit , err , warn , notice , diag , info , trace ,
+and
+.Em debug .
+Each priority, when specified, also includes all priorities higher
+than it.
+For example, a priority of
+.Em notice
+would include debug messages logged at
+.Em notice
+and higher.
+.Pp
+The priorities
+.Em trace
+and
+.Em debug
+also include function call tracing which logs when a function is
+entered and when it returns.
+For example, the following trace is for the
+.Fn get_user_groups
+function located in src/sudo.c:
+.Bd -literal -offset 4n
+sudo[123] -> get_user_groups @ src/sudo.c:385
+sudo[123] <- get_user_groups @ src/sudo.c:429 := groups=10,0,5
+.Ed
+.Pp
+When the function is entered, indicated by a right arrow
+.Ql -> ,
+the program, process ID, function, source file, and line number
+are logged.
+When the function returns, indicated by a left arrow
+.Ql <- ,
+the same information is logged along with the return value.
+In this case, the return value is a string.
+.Pp
+The following subsystems are used by the
+.Nm sudo
+front-end:
+.Bl -tag -width Fl
+.It Em all
+matches every subsystem
+.It Em args
+command line argument processing
+.It Em conv
+user conversation
+.It Em edit
+sudoedit
+.It Em event
+event subsystem
+.It Em exec
+command execution
+.It Em main
+.Nm sudo
+main function
+.It Em netif
+network interface handling
+.It Em pcomm
+communication with the plugin
+.It Em plugin
+plugin configuration
+.It Em pty
+pseudo-terminal related code
+.It Em selinux
+SELinux-specific handling
+.It Em util
+utility functions
+.It Em utmp
+utmp handling
+.El
+.Pp
+The
+.Xr sudoers @mansectform@
+plugin includes support for additional subsystems.
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/sudo.conf
+.Nm sudo
+front-end configuration
+.El
+.Sh EXAMPLES
+.Bd -literal
+#
+# Default @sysconfdir@/sudo.conf file
+#
+# Sudo plugins:
+# Plugin plugin_name plugin_path plugin_options ...
+#
+# The plugin_path is relative to @plugindir@ unless
+# fully qualified.
+# The plugin_name corresponds to a global symbol in the plugin
+# that contains the plugin interface structure.
+# The plugin_options are optional.
+#
+# The sudoers plugin is used by default if no Plugin lines are present.
+#Plugin sudoers_policy @sudoers_plugin@
+#Plugin sudoers_io @sudoers_plugin@
+#Plugin sudoers_audit @sudoers_plugin@
+
+#
+# Sudo askpass:
+# Path askpass /path/to/askpass
+#
+# An askpass helper program may be specified to provide a graphical
+# password prompt for "sudo -A" support. Sudo does not ship with its
+# own askpass program but can use the OpenSSH askpass.
+#
+# Use the OpenSSH askpass
+#Path askpass /usr/X11R6/bin/ssh-askpass
+#
+# Use the Gnome OpenSSH askpass
+#Path askpass /usr/libexec/openssh/gnome-ssh-askpass
+
+#
+# Sudo device search path:
+# Path devsearch /dev/path1:/dev/path2:/dev
+#
+# A colon-separated list of paths to check when searching for a user's
+# terminal device.
+#
+#Path devsearch /dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev
+
+#
+# Sudo command interception:
+# Path intercept /path/to/sudo_intercept.so
+#
+# Path to a shared library containing replacements for the execv()
+# and execve() library functions that perform a policy check to verify
+# the command is allowed and simply return an error if not. This is
+# used to implement the "intercept" functionality on systems that
+# support LD_PRELOAD or its equivalent.
+#
+# The compiled-in value is usually sufficient and should only be changed
+# if you rename or move the sudo_intercept.so file.
+#
+#Path intercept @intercept_file@
+
+#
+# Sudo noexec:
+# Path noexec /path/to/sudo_noexec.so
+#
+# Path to a shared library containing replacements for the execv()
+# family of library functions that just return an error. This is
+# used to implement the "noexec" functionality on systems that support
+# LD_PRELOAD or its equivalent.
+#
+# The compiled-in value is usually sufficient and should only be changed
+# if you rename or move the sudo_noexec.so file.
+#
+#Path noexec @noexec_file@
+
+#
+# Sudo plugin directory:
+# Path plugin_dir /path/to/plugins
+#
+# The default directory to use when searching for plugins that are
+# specified without a fully qualified path name.
+#
+#Path plugin_dir @plugindir@
+
+#
+# Core dumps:
+# Set disable_coredump true|false
+#
+# By default, sudo disables core dumps while it is executing (they
+# are re-enabled for the command that is run).
+# To aid in debugging sudo problems, you may wish to enable core
+# dumps by setting "disable_coredump" to false.
+#
+#Set disable_coredump false
+
+#
+# User groups:
+# Set group_source static|dynamic|adaptive
+#
+# Sudo passes the user's group list to the policy plugin.
+# If the user is a member of the maximum number of groups (usually 16),
+# sudo will query the group database directly to be sure to include
+# the full list of groups.
+#
+# On some systems, this can be expensive so the behavior is configurable.
+# The "group_source" setting has three possible values:
+# static - use the user's list of groups returned by the kernel.
+# dynamic - query the group database to find the list of groups.
+# adaptive - if user is in less than the maximum number of groups.
+# use the kernel list, else query the group database.
+#
+#Set group_source static
+
+#
+# Sudo interface probing:
+# Set probe_interfaces true|false
+#
+# By default, sudo will probe the system's network interfaces and
+# pass the IP address of each enabled interface to the policy plugin.
+# On systems with a large number of virtual interfaces this may take
+# a noticeable amount of time.
+#
+#Set probe_interfaces false
+
+#
+# Sudo debug files:
+# Debug program /path/to/debug_log subsystem@priority[,subsyste@priority]
+#
+# Sudo and related programs support logging debug information to a file.
+# The program is typically sudo, sudoers.so, sudoreplay, or visudo.
+#
+# Subsystems vary based on the program; "all" matches all subsystems.
+# Priority may be crit, err, warn, notice, diag, info, trace, or debug.
+# Multiple subsystem@priority may be specified, separated by a comma.
+#
+#Debug sudo @log_dir@/sudo_debug all@debug
+#Debug @sudoers_plugin@ @log_dir@/sudoers_debug all@debug
+.Ed
+.Sh SEE ALSO
+.Xr sudo_plugin @mansectform@ ,
+.Xr sudoers @mansectform@ ,
+.Xr sudo @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS.md file in the
+.Nm sudo
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you believe you have found a bug in
+.Nm sudo ,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm sudo
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+.Nm sudo
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudo.man.in b/docs/sudo.man.in
new file mode 100644
index 0000000..eab53e2
--- /dev/null
+++ b/docs/sudo.man.in
@@ -0,0 +1,1739 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 1994-1996, 1998-2005, 2007-2023
+.\" Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" Sponsored in part by the Defense Advanced Research Projects
+.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
+.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
+.\"
+.nr SL @SEMAN@
+.nr BA @BAMAN@
+.nr LC @LCMAN@
+.nr PS @PSMAN@
+.TH "SUDO" "@mansectsu@" "August 9, 2023" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudo\fR,
+\fBsudoedit\fR
+\- execute a command as another user
+.SH "SYNOPSIS"
+.HP 5n
+\fBsudo\fR
+\fB\-h\fR\ |\ \fB\-K\fR\ |\ \fB\-k\fR\ |\ \fB\-V\fR
+.br
+.PD 0
+.HP 5n
+\fBsudo\fR
+\fB\-v\fR
+[\fB\-ABkNnS\fR]
+.if \n(BA [\fB\-a\fR\ \fItype\fR]
+[\fB\-g\fR\ \fIgroup\fR]
+[\fB\-h\fR\ \fIhost\fR]
+[\fB\-p\fR\ \fIprompt\fR]
+[\fB\-u\fR\ \fIuser\fR]
+.br
+.HP 5n
+\fBsudo\fR
+\fB\-l\fR
+[\fB\-ABkNnS\fR]
+.if \n(BA [\fB\-a\fR\ \fItype\fR]
+[\fB\-g\fR\ \fIgroup\fR]
+[\fB\-h\fR\ \fIhost\fR]
+[\fB\-p\fR\ \fIprompt\fR]
+[\fB\-U\fR\ \fIuser\fR]
+[\fB\-u\fR\ \fIuser\fR]
+[\fIcommand\fR\ [\fIarg\ ...\fR]]
+.br
+.HP 5n
+\fBsudo\fR
+[\fB\-ABbEHnPS\fR]
+.if \n(BA [\fB\-a\fR\ \fItype\fR]
+[\fB\-C\fR\ \fInum\fR]
+.if \n(LC [\fB\-c\fR\ \fIclass\fR]
+[\fB\-D\fR\ \fIdirectory\fR]
+[\fB\-g\fR\ \fIgroup\fR]
+[\fB\-h\fR\ \fIhost\fR]
+[\fB\-p\fR\ \fIprompt\fR]
+[\fB\-R\fR\ \fIdirectory\fR]
+.if \n(SL [\fB\-r\fR\ \fIrole\fR]
+.if \n(SL [\fB\-t\fR\ \fItype\fR]
+[\fB\-T\fR\ \fItimeout\fR]
+[\fB\-u\fR\ \fIuser\fR]
+[\fIVAR\fR=\fIvalue\fR]
+[\fB\-i\fR\ |\ \fB\-s\fR]
+[\fIcommand\fR\ [\fIarg\ ...\fR]]
+.br
+.HP 9n
+\fBsudoedit\fR
+[\fB\-ABkNnS\fR]
+.if \n(BA [\fB\-a\fR\ \fItype\fR]
+[\fB\-C\fR\ \fInum\fR]
+.if \n(LC [\fB\-c\fR\ \fIclass\fR]
+[\fB\-D\fR\ \fIdirectory\fR]
+[\fB\-g\fR\ \fIgroup\fR]
+[\fB\-h\fR\ \fIhost\fR]
+[\fB\-p\fR\ \fIprompt\fR]
+[\fB\-R\fR\ \fIdirectory\fR]
+.if \n(SL [\fB\-r\fR\ \fIrole\fR]
+.if \n(SL [\fB\-t\fR\ \fItype\fR]
+[\fB\-T\fR\ \fItimeout\fR]
+[\fB\-u\fR\ \fIuser\fR]
+\fIfile\ ...\fR
+.PD
+.SH "DESCRIPTION"
+\fBsudo\fR
+allows a permitted user to execute a
+\fIcommand\fR
+as the superuser or another user, as specified by the security
+policy.
+The invoking user's real
+(\fInot\fR effective)
+user-ID is used to determine the user name with which
+to query the security policy.
+.PP
+\fBsudo\fR
+supports a plugin architecture for security policies, auditing,
+and input/output logging.
+Third parties can develop and distribute their own plugins to work
+seamlessly with the
+\fBsudo\fR
+front-end.
+The default security policy is
+\fIsudoers\fR,
+which is configured via the file
+\fI@sysconfdir@/sudoers\fR,
+or via LDAP.
+See the
+\fIPlugins\fR
+section for more information.
+.PP
+The security policy determines what privileges, if any, a user has
+to run
+\fBsudo\fR.
+The policy may require that users authenticate themselves with a
+password or another authentication mechanism.
+If authentication is required,
+\fBsudo\fR
+will exit if the user's password is not entered within a configurable
+time limit.
+This limit is policy-specific; the default password prompt timeout
+for the
+\fIsudoers\fR
+security policy is @password_timeout@ minutes.
+.PP
+Security policies may support credential caching to allow the user
+to run
+\fBsudo\fR
+again for a period of time without requiring authentication.
+By default, the
+\fIsudoers\fR
+policy caches credentials on a per-terminal basis for @timeout@ minutes.
+See the
+\fItimestamp_type\fR
+and
+\fItimestamp_timeout\fR
+options in
+sudoers(@mansectform@)
+for more information.
+By running
+\fBsudo\fR
+with the
+\fB\-v\fR
+option, a user can update the cached credentials without running a
+\fIcommand\fR.
+.PP
+On systems where
+\fBsudo\fR
+is the primary method of gaining superuser privileges, it is imperative
+to avoid syntax errors in the security policy configuration files.
+For the default security policy,
+sudoers(@mansectform@),
+changes to the configuration files should be made using the
+visudo(@mansectsu@)
+utility which will ensure that no syntax errors are introduced.
+.PP
+When invoked as
+\fBsudoedit\fR,
+the
+\fB\-e\fR
+option (described below), is implied.
+.PP
+Security policies and audit plugins may log successful and failed attempts
+to run
+\fBsudo\fR.
+If an I/O plugin is configured, the running
+\fIcommand\fR's
+input and output may be logged as well.
+.PP
+The options are as follows:
+.TP 8n
+\fB\-A\fR, \fB\--askpass\fR
+Normally, if
+\fBsudo\fR
+requires a password, it will read it from the user's terminal.
+If the
+\fB\-A\fR (\fIaskpass\fR)
+option is specified, a (possibly graphical) helper program is
+executed to read the user's password and output the password to the
+standard output.
+If the
+\fRSUDO_ASKPASS\fR
+environment variable is set, it specifies the path to the helper
+program.
+Otherwise, if
+sudo.conf(@mansectform@)
+contains a line specifying the askpass program, that value will be
+used.
+For example:
+.nf
+.sp
+.RS 12n
+# Path to askpass helper program
+Path askpass /usr/X11R6/bin/ssh-askpass
+.RE
+.fi
+.RS 8n
+.sp
+If no askpass program is available,
+\fBsudo\fR
+will exit with an error.
+.RE
+.TP 8n
+\fB\-a\fR \fItype\fR, \fB\--auth-type\fR=\fItype\fR
+Use the specified
+BSD
+authentication
+\fItype\fR
+when validating the user, if allowed by
+\fI/etc/login.conf\fR.
+The system administrator may specify a list of sudo-specific
+authentication methods by adding an
+\(lqauth-sudo\(rq
+entry in
+\fI/etc/login.conf\fR.
+This option is only available on systems that support
+BSD
+authentication.
+.TP 8n
+\fB\-B\fR, \fB\--bell\fR
+Ring the bell as part of the password prompt when a terminal is present.
+This option has no effect if an askpass program is used.
+.TP 8n
+\fB\-b\fR, \fB\--background\fR
+Run the given
+\fIcommand\fR
+in the background.
+It is not possible to use shell job control to manipulate background
+processes started by
+\fBsudo\fR.
+Most interactive
+\fIcommand\fRs
+will fail to work properly in background mode.
+.TP 8n
+\fB\-C\fR \fInum\fR, \fB\--close-from\fR=\fInum\fR
+Close all file descriptors greater than or equal to
+\fInum\fR
+before executing a
+\fIcommand\fR.
+Values less than three are not permitted.
+By default,
+\fBsudo\fR
+will close all open file descriptors other than standard input,
+standard output, and standard error when executing a
+\fIcommand\fR.
+The security policy may restrict the user's ability to use this option.
+The
+\fIsudoers\fR
+policy only permits use of the
+\fB\-C\fR
+option when the administrator has enabled the
+\fIclosefrom_override\fR
+option.
+.TP 8n
+\fB\-c\fR \fIclass\fR, \fB\--login-class\fR=\fIclass\fR
+Run the
+\fIcommand\fR
+with resource limits and scheduling priority of the specified login
+\fIclass\fR.
+The
+\fIclass\fR
+argument can be either a class name as defined in
+\fI/etc/login.conf\fR,
+or a single
+\(oq\-\(cq
+character.
+If
+\fIclass\fR
+is
+\fB-\fR,
+the default login class of the target user will be used.
+Otherwise, the
+\fIcommand\fR
+must be run as the superuser (user-ID 0), or
+\fBsudo\fR
+must be run from a shell that is already running as the superuser.
+If the
+\fIcommand\fR
+is being run as a login shell, additional
+\fI/etc/login.conf\fR
+settings, such as the umask and environment variables, will
+be applied, if present.
+This option is only available on systems with
+BSD
+login classes.
+.TP 8n
+\fB\-D\fR \fIdirectory\fR, \fB\--chdir\fR=\fIdirectory\fR
+Run the
+\fIcommand\fR
+in the specified
+\fIdirectory\fR
+instead of the current working directory.
+The security policy may return an error if the user does not have
+permission to specify the working directory.
+.TP 8n
+\fB\-E\fR, \fB\--preserve-env\fR
+Indicates to the security policy that the user wishes to
+preserve their existing environment variables.
+The security policy may return an error if the user does not have
+permission to preserve the environment.
+.TP 8n
+\fB\--preserve-env=list\fR
+Indicates to the security policy that the user wishes to add the
+comma-separated list of environment variables to those preserved
+from the user's environment.
+The security policy may return an error if the user does not have
+permission to preserve the environment.
+This option may be specified multiple times.
+.TP 8n
+\fB\-e\fR, \fB\--edit\fR
+Edit one or more
+\fIfile\fRs
+instead of running a
+\fIcommand\fR.
+In lieu of a path name, the string "sudoedit" is used when consulting
+the security policy.
+If the user is authorized by the policy, the following steps are
+taken:
+.RS 12n
+.TP 5n
+1.\&
+Temporary copies are made of the files to be edited with the owner
+set to the invoking user.
+.TP 5n
+2.\&
+The editor specified by the policy is run to edit the temporary
+files.
+The
+\fIsudoers\fR
+policy uses the
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+and
+\fREDITOR\fR
+environment variables (in that order).
+If none of
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+or
+\fREDITOR\fR
+are set, the first program listed in the
+\fIeditor\fR
+sudoers(@mansectform@)
+option is used.
+.TP 5n
+3.\&
+If they have been modified, the temporary files are copied back to
+their original location and the temporary versions are removed.
+.RE
+.RS 8n
+.sp
+To help prevent the editing of unauthorized files, the following
+restrictions are enforced unless explicitly allowed by the security policy:
+.RS 9n
+.TP 3n
+\fB\(bu\fR
+Symbolic links may not be edited (version 1.8.15 and higher).
+.TP 3n
+\fB\(bu\fR
+Symbolic links along the path to be edited are not followed when the
+parent directory is writable by the invoking user unless that user
+is root (version 1.8.16 and higher).
+.TP 3n
+\fB\(bu\fR
+Files located in a directory that is writable by the invoking user may
+not be edited unless that user is root (version 1.8.16 and higher).
+.RE
+.sp
+Users are never allowed to edit device special files.
+.sp
+If the specified file does not exist, it will be created.
+Unlike most
+\fIcommand\fRs
+run by
+\fIsudo\fR,
+the editor is run with the invoking user's environment unmodified.
+If the temporary file becomes empty after editing, the user will
+be prompted before it is installed.
+If, for some reason,
+\fBsudo\fR
+is unable to update a file with its edited version, the user will
+receive a warning and the edited copy will remain in a temporary
+file.
+.RE
+.TP 8n
+\fB\-g\fR \fIgroup\fR, \fB\--group\fR=\fIgroup\fR
+Run the
+\fIcommand\fR
+with the primary group set to
+\fIgroup\fR
+instead of the primary group specified by the target
+user's password database entry.
+The
+\fIgroup\fR
+may be either a group name or a numeric group-ID
+(GID)
+prefixed with the
+\(oq#\(cq
+character (e.g.,
+\(oq#0\(cq
+for GID 0).
+When running a
+\fIcommand\fR
+as a GID, many shells require that the
+\(oq#\(cq
+be escaped with a backslash
+(\(oq\e\(cq).
+If no
+\fB\-u\fR
+option is specified, the
+\fIcommand\fR
+will be run as the invoking user.
+In either case, the primary group will be set to
+\fIgroup\fR.
+The
+\fIsudoers\fR
+policy permits any of the target user's groups to be specified via
+the
+\fB\-g\fR
+option as long as the
+\fB\-P\fR
+option is not in use.
+.TP 8n
+\fB\-H\fR, \fB\--set-home\fR
+Request that the security policy set the
+\fRHOME\fR
+environment variable to the home directory specified by the target
+user's password database entry.
+Depending on the policy, this may be the default behavior.
+.TP 8n
+\fB\-h\fR, \fB\--help\fR
+Display a short help message to the standard output and exit.
+.TP 8n
+\fB\-h\fR \fIhost\fR, \fB\--host\fR=\fIhost\fR
+Run the
+\fIcommand\fR
+on the specified
+\fIhost\fR
+if the security policy plugin supports remote
+\fIcommand\fRs.
+The
+\fIsudoers\fR
+plugin does not currently support running remote
+\fIcommand\fRs.
+This may also be used in conjunction with the
+\fB\-l\fR
+option to list a user's privileges for the remote host.
+.TP 8n
+\fB\-i\fR, \fB\--login\fR
+Run the shell specified by the target user's password database entry
+as a login shell.
+This means that login-specific resource files such as
+\fI.profile\fR,
+\fI.bash_profile\fR,
+or
+\fI.login\fR
+will be read by the shell.
+If a
+\fIcommand\fR
+is specified, it is passed to the shell as a simple
+\fIcommand\fR
+using the
+\fB\-c\fR
+option.
+The
+\fIcommand\fR
+and any
+\fIarg\fRs
+are concatenated, separated by spaces, after escaping each character
+(including white space)
+with a backslash
+(\(oq\e\(cq)
+except for alphanumerics, underscores,
+hyphens, and dollar signs.
+If no
+\fIcommand\fR
+is specified, an interactive shell is executed.
+\fBsudo\fR
+attempts to change to that user's home directory before running the
+shell.
+The
+\fIcommand\fR
+is run with an environment similar to the one a user would receive at log in.
+Most shells behave differently when a
+\fIcommand\fR
+is specified as compared to an interactive session; consult the shell's manual
+for details.
+The
+\fICommand environment\fR
+section in the
+sudoers(@mansectform@)
+manual documents how the
+\fB\-i\fR
+option affects the environment in which a
+\fIcommand\fR
+is run when the
+\fIsudoers\fR
+policy is in use.
+.TP 8n
+\fB\-K\fR, \fB\--remove-timestamp\fR
+Similar to the
+\fB\-k\fR
+option, except that it removes every cached credential for the user,
+regardless of the terminal or parent process ID.
+The next time
+\fBsudo\fR
+is run, a password must be entered if the
+security policy requires authentication.
+It is not possible to use the
+\fB\-K\fR
+option in conjunction with a
+\fIcommand\fR
+or other option.
+This option does not require a password.
+Not all security policies support credential caching.
+.TP 8n
+\fB\-k\fR, \fB\--reset-timestamp\fR
+When used without a
+\fIcommand\fR,
+invalidates the user's cached credentials for the current session.
+The next time
+\fBsudo\fR
+is run in the session, a password must be entered if the
+security policy requires authentication.
+By default, the
+\fBsudoers\fR
+policy uses a separate record in the credential cache for each
+terminal (or parent process ID if no terminal is present).
+This prevents the
+\fB\-k\fR
+option from interfering with
+\fBsudo\fR
+commands run in a different terminal session.
+See the
+\fItimestamp_type\fR
+option in
+sudoers(@mansectform@)
+for more information.
+This option does not require a password, and was added to allow a
+user to revoke
+\fBsudo\fR
+permissions from a
+\fI.logout\fR
+file.
+.sp
+When used in conjunction with a
+\fIcommand\fR
+or an option that may require a password, this option will cause
+\fBsudo\fR
+to ignore the user's cached credentials.
+As a result,
+\fBsudo\fR
+will prompt for a password (if one is required by the security
+policy) and will not update the user's cached credentials.
+.sp
+Not all security policies support credential caching.
+.TP 8n
+\fB\-l\fR, \fB\--list\fR
+If no
+\fIcommand\fR
+is specified, list the privileges for the invoking user (or the
+\fIuser\fR
+specified by the
+\fB\-U\fR
+option) on the current host.
+A longer list format is used if this option is specified multiple times
+and the security policy supports a verbose output format.
+.sp
+If a
+\fIcommand\fR
+is specified and is permitted by the security policy for the invoking
+user (or the,
+\fIuser\fR
+specified by the
+\fB\-U\fR
+option) on the current host,
+the fully-qualified path to the
+\fIcommand\fR
+is displayed along with any
+\fIarg\fRs.
+If
+\fB\-l\fR
+is specified more than once (and the security policy supports it),
+the matching rule is displayed in a verbose format along with the
+\fIcommand\fR.
+If a
+\fIcommand\fR
+is specified but not allowed by the policy,
+\fBsudo\fR
+will exit with a status value of 1.
+.TP 8n
+\fB\-N\fR, \fB\--no-update\fR
+Do not update the user's cached credentials, even if the user successfully
+authenticates.
+Unlike the
+\fB\-k\fR
+flag, existing cached credentials are used if they are valid.
+To detect when the user's cached credentials are valid (or when no
+authentication is required), the following can be used:
+.nf
+.sp
+.RS 12n
+sudo -Nnv
+.RE
+.fi
+.RS 8n
+.sp
+Not all security policies support credential caching.
+.RE
+.TP 8n
+\fB\-n\fR, \fB\--non-interactive\fR
+Avoid prompting the user for input of any kind.
+If a password is required for the
+\fIcommand\fR
+to run,
+\fBsudo\fR
+will display an error message and exit.
+.TP 8n
+\fB\-P\fR, \fB\--preserve-groups\fR
+Preserve the invoking user's group vector unaltered.
+By default, the
+\fIsudoers\fR
+policy will initialize the group vector to the list of groups the
+target user is a member of.
+The real and effective group-IDs, however, are still set to match
+the target user.
+.TP 8n
+\fB\-p\fR \fIprompt\fR, \fB\--prompt\fR=\fIprompt\fR
+Use a custom password prompt with optional escape sequences.
+The following percent
+(\(oq%\(cq)
+escape sequences are supported by the
+\fIsudoers\fR
+policy:
+.PP
+.RS 8n
+.PD 0
+.TP 4n
+%H
+expanded to the host name including the domain name (only if the
+machine's host name is fully qualified or the
+\fIfqdn\fR
+option is set in
+sudoers(@mansectform@))
+.PD
+.TP 4n
+%h
+expanded to the local host name without the domain name
+.TP 4n
+%p
+expanded to the name of the user whose password is being requested
+(respects the
+\fIrootpw\fR,
+\fItargetpw\fR,
+and
+\fIrunaspw\fR
+flags in
+sudoers(@mansectform@))
+.TP 4n
+\&%U
+expanded to the login name of the user the
+\fIcommand\fR
+will be run as (defaults to root unless the
+\fB\-u\fR
+option is also specified)
+.TP 4n
+%u
+expanded to the invoking user's login name
+.TP 4n
+%%
+two consecutive
+\(oq%\(cq
+characters are collapsed into a single
+\(oq%\(cq
+character
+.PP
+The custom prompt will override the default prompt specified by either
+the security policy or the
+\fRSUDO_PROMPT\fR
+environment variable.
+On systems that use PAM, the custom prompt will also override the prompt
+specified by a PAM module unless the
+\fIpassprompt_override\fR
+flag is disabled in
+\fIsudoers\fR.
+.RE
+.TP 8n
+\fB\-R\fR \fIdirectory\fR, \fB\--chroot\fR=\fIdirectory\fR
+Change to the specified root
+\fIdirectory\fR
+(see
+chroot(@mansectsu@))
+before running the
+\fIcommand\fR.
+The security policy may return an error if the user does not have
+permission to specify the root directory.
+.TP 8n
+\fB\-r\fR \fIrole\fR, \fB\--role\fR=\fIrole\fR
+Run the
+\fIcommand\fR
+with an SELinux security context that includes the specified
+\fIrole\fR.
+.TP 8n
+\fB\-S\fR, \fB\--stdin\fR
+Write the prompt to the standard error and read the password from the
+standard input instead of using the terminal device.
+.TP 8n
+\fB\-s\fR, \fB\--shell\fR
+Run the shell specified by the
+\fRSHELL\fR
+environment variable if it is set or the shell specified by the
+invoking user's password database entry.
+If a
+\fIcommand\fR
+is specified, it is passed to the shell as a simple command using the
+\fB\-c\fR
+option.
+The
+\fIcommand\fR
+and any
+\fIarg\fRs
+are concatenated, separated by spaces, after escaping each character
+(including white space)
+with a backslash
+(\(oq\e\(cq)
+except for alphanumerics, underscores,
+hyphens, and dollar signs.
+If no
+\fIcommand\fR
+is specified, an interactive shell is executed.
+Most shells behave differently when a
+\fIcommand\fR
+is specified as compared to an interactive session; consult the shell's manual
+for details.
+.TP 8n
+\fB\-t\fR \fItype\fR, \fB\--type\fR=\fItype\fR
+Run the
+\fIcommand\fR
+with an SELinux security context that includes the specified
+\fItype\fR.
+If no
+\fItype\fR
+is specified, the default type is derived from the role.
+.TP 8n
+\fB\-U\fR \fIuser\fR, \fB\--other-user\fR=\fIuser\fR
+Used in conjunction with the
+\fB\-l\fR
+option to list the privileges for
+\fIuser\fR
+instead of for the invoking user.
+The security policy may restrict listing other users' privileges.
+When using the
+\fIsudoers\fR
+policy, the
+\fB\-U\fR
+option is restricted to the root user and users with either the
+\(lqlist\(rq
+priviege for the specified
+\fIuser\fR
+or the ability to run any
+\fIcommand\fR
+as root or
+\fIuser\fR
+on the current host.
+.TP 8n
+\fB\-T\fR \fItimeout\fR, \fB\--command-timeout\fR=\fItimeout\fR
+Used to set a timeout for the
+\fIcommand\fR.
+If the timeout expires before the
+\fIcommand\fR
+has exited, the
+\fIcommand\fR
+will be terminated.
+The security policy may restrict the user's ability to set timeouts.
+The
+\fIsudoers\fR
+policy requires that user-specified timeouts be explicitly enabled.
+.TP 8n
+\fB\-u\fR \fIuser\fR, \fB\--user\fR=\fIuser\fR
+Run the
+\fIcommand\fR
+as a user other than the default target user (usually
+\fBroot\fR).
+The
+\fIuser\fR
+may be either a user name or a numeric user-ID
+(UID)
+prefixed with the
+\(oq#\(cq
+character (e.g.,
+\(oq#0\(cq
+for UID 0).
+When running
+\fIcommand\fRs as
+a UID, many shells require that the
+\(oq#\(cq
+be escaped with a backslash
+(\(oq\e\(cq).
+Some security policies may restrict UIDs
+to those listed in the password database.
+The
+\fIsudoers\fR
+policy allows UIDs that are not in the password database as long as the
+\fItargetpw\fR
+option is not set.
+Other security policies may not support this.
+.TP 8n
+\fB\-V\fR, \fB\--version\fR
+Print the
+\fBsudo\fR
+version string as well as the version string of any configured plugins.
+If the invoking user is already root, the
+\fB\-V\fR
+option will display the options passed to configure when
+\fBsudo\fR
+was built; plugins may display additional information such as
+default options.
+.TP 8n
+\fB\-v\fR, \fB\--validate\fR
+Update the user's cached credentials, authenticating the user
+if necessary.
+For the
+\fIsudoers\fR
+plugin, this extends the
+\fBsudo\fR
+timeout for another @timeout@ minutes by default, but does not run a
+\fIcommand\fR.
+Not all security policies support cached credentials.
+.TP 8n
+\fB\--\fR
+The
+\fB\--\fR
+is used to delimit the end of the
+\fBsudo\fR
+options.
+Subsequent options are passed to the
+\fIcommand\fR.
+.PP
+Options that take a value may only be specified once unless
+otherwise indicated in the description.
+This is to help guard against problems caused by poorly written
+scripts that invoke
+\fBsudo\fR
+with user-controlled input.
+.PP
+Environment variables to be set for the
+\fIcommand\fR
+may also be passed as options to
+\fBsudo\fR
+in the form
+\fIVAR\fR=\fIvalue\fR,
+for example
+\fRLD_LIBRARY_PATH\fR=\fI/usr/local/pkg/lib\fR.
+Environment variables may be subject to restrictions
+imposed by the security policy plugin.
+The
+\fIsudoers\fR
+policy subjects environment variables passed as options to the same
+restrictions as existing environment variables with one important
+difference.
+If the
+\fIsetenv\fR
+option is set in
+\fIsudoers\fR,
+the
+\fIcommand\fR
+to be run has the
+\fRSETENV\fR
+tag set or the
+\fIcommand\fR
+matched is
+\fBALL\fR,
+the user may set variables that would otherwise be forbidden.
+See
+sudoers(@mansectform@)
+for more information.
+.SH "COMMAND EXECUTION"
+When
+\fBsudo\fR
+executes a
+\fIcommand\fR,
+the security policy specifies the execution environment for the
+\fIcommand\fR.
+Typically, the real and effective user and group and IDs are set to
+match those of the target user, as specified in the password database,
+and the group vector is initialized based on the group database
+(unless the
+\fB\-P\fR
+option was specified).
+.PP
+The following parameters may be specified by security policy:
+.TP 3n
+\fB\(bu\fR
+real and effective user-ID
+.TP 3n
+\fB\(bu\fR
+real and effective group-ID
+.TP 3n
+\fB\(bu\fR
+supplementary group-IDs
+.TP 3n
+\fB\(bu\fR
+the environment list
+.TP 3n
+\fB\(bu\fR
+current working directory
+.TP 3n
+\fB\(bu\fR
+file creation mode mask (umask)
+.if \n(SL \{\
+.TP 3n
+\fB\(bu\fR
+SELinux role and type
+.\}
+.if \n(PS \{\
+.TP 3n
+\fB\(bu\fR
+Solaris project
+.\}
+.if \n(PS \{\
+.TP 3n
+\fB\(bu\fR
+Solaris privileges
+.\}
+.if \n(LC \{\
+.TP 3n
+\fB\(bu\fR
+BSD
+login class
+.\}
+.TP 3n
+\fB\(bu\fR
+scheduling priority (aka nice value)
+.SS "Process model"
+There are two distinct ways
+\fBsudo\fR
+can run a
+\fIcommand\fR.
+.PP
+If an I/O logging plugin is configured to log terminal I/O, or if
+the security policy explicitly requests it, a new pseudo-terminal
+(\(lqpty\(rq)
+is allocated and
+fork(2)
+is used to create a second
+\fBsudo\fR
+process, referred to as the
+\fImonitor\fR.
+The
+\fImonitor\fR
+creates a new terminal session with itself as the leader and the pty as its
+controlling terminal, calls
+fork(2)
+again, sets up the execution environment as described above, and then uses the
+execve(2)
+system call to run the
+\fIcommand\fR
+in the child process.
+The
+\fImonitor\fR
+exists to relay job control signals between the user's
+terminal and the pty the
+\fIcommand\fR
+is being run in.
+This makes it possible to suspend and resume the
+\fIcommand\fR
+normally.
+Without the
+\fImonitor\fR,
+the
+\fIcommand\fR
+would be in what POSIX terms an
+\(lqorphaned process group\(rq
+and it would not receive any job control signals from the kernel.
+When the
+\fIcommand\fR
+exits or is terminated by a signal, the
+\fImonitor\fR
+passes the
+\fIcommand\fR's
+exit status to the main
+\fBsudo\fR
+process and exits.
+After receiving the
+\fIcommand\fR's
+exit status, the main
+\fBsudo\fR
+process passes the
+\fIcommand\fR's
+exit status to the security policy's close function, as well as the
+close function of any configured audit plugin, and exits.
+This mode is the default for sudo versions 1.9.14 and above when using
+the sudoers policy.
+.PP
+If no pty is used,
+\fBsudo\fR
+calls
+fork(2),
+sets up the execution environment as described above, and uses the
+execve(2)
+system call to run the
+\fIcommand\fR
+in the child process.
+The main
+\fBsudo\fR
+process waits until the
+\fIcommand\fR
+has completed, then passes the
+\fIcommand\fR's
+exit status to the security policy's close function, as well as the
+close function of any configured audit plugins, and exits.
+As a special case, if the policy plugin does not define a close
+function,
+\fBsudo\fR
+will execute the
+\fIcommand\fR
+directly instead of calling
+fork(2)
+first.
+The
+\fIsudoers\fR
+policy plugin will only define a close function when I/O logging
+is enabled, a pty is required, an SELinux role is specified, the
+\fIcommand\fR
+has an associated timeout, or the
+\fIpam_session\fR
+or
+\fIpam_setcred\fR
+options are enabled.
+Both
+\fIpam_session\fR
+and
+\fIpam_setcred\fR
+are enabled by default on systems using PAM.
+This mode is the default for sudo versions prior to 1.9.14 when using
+the sudoers policy.
+.PP
+On systems that use PAM, the security policy's close function
+is responsible for closing the PAM session.
+It may also log the
+\fIcommand\fR's
+exit status.
+.SS "Signal handling"
+When the
+\fIcommand\fR
+is run as a child of the
+\fBsudo\fR
+process,
+\fBsudo\fR
+will relay signals it receives to the
+\fIcommand\fR.
+The
+\fRSIGINT\fR
+and
+\fRSIGQUIT\fR
+signals are only relayed when the
+\fIcommand\fR
+is being run in a new pty or when the signal was sent by a user
+process, not the kernel.
+This prevents the
+\fIcommand\fR
+from receiving
+\fRSIGINT\fR
+twice each time the user enters control-C.
+Some signals, such as
+\fRSIGSTOP\fR
+and
+\fRSIGKILL\fR,
+cannot be caught and thus will not be relayed to the
+\fIcommand\fR.
+As a general rule,
+\fRSIGTSTP\fR
+should be used instead of
+\fRSIGSTOP\fR
+when you wish to suspend a
+\fIcommand\fR
+being run by
+\fBsudo\fR.
+.PP
+As a special case,
+\fBsudo\fR
+will not relay signals that were sent by the
+\fIcommand\fR
+it is running.
+This prevents the
+\fIcommand\fR
+from accidentally killing itself.
+On some systems, the
+reboot(@mansectsu@)
+utility sends
+\fRSIGTERM\fR
+to all non-system processes other than itself before rebooting
+the system.
+This prevents
+\fBsudo\fR
+from relaying the
+\fRSIGTERM\fR
+signal it received back to
+reboot(@mansectsu@),
+which might then exit before the system was actually rebooted,
+leaving it in a half-dead state similar to single user mode.
+Note, however, that this check only applies to the
+\fIcommand\fR
+run by
+\fBsudo\fR
+and not any other processes that the
+\fIcommand\fR
+may create.
+As a result, running a script that calls
+reboot(@mansectsu@)
+or
+shutdown(@mansectsu@)
+via
+\fBsudo\fR
+may cause the system to end up in this undefined state unless the
+reboot(@mansectsu@)
+or
+shutdown(@mansectsu@)
+are run using the
+\fBexec\fR()
+family of functions instead of
+\fBsystem\fR()
+(which interposes a shell between the
+\fIcommand\fR
+and the calling process).
+.SS "Plugins"
+Plugins may be specified via
+\fIPlugin\fR
+directives in the
+sudo.conf(@mansectform@)
+file.
+They may be loaded as dynamic shared objects (on systems that support them),
+or compiled directly into the
+\fBsudo\fR
+binary.
+If no
+sudo.conf(@mansectform@)
+file is present, or if it doesn't contain any
+\fIPlugin\fR
+lines,
+\fBsudo\fR
+will use
+sudoers(@mansectform@)
+for the policy, auditing, and I/O logging plugins.
+See the
+sudo.conf(@mansectform@)
+manual for details of the
+\fI@sysconfdir@/sudo.conf\fR
+file and the
+sudo_plugin(@mansectform@)
+manual for more information about the
+\fBsudo\fR
+plugin architecture.
+.SH "EXIT VALUE"
+Upon successful execution of a
+\fIcommand\fR,
+the exit status from
+\fBsudo\fR
+will be the exit status of the program that was executed.
+If the
+\fIcommand\fR
+terminated due to receipt of a signal,
+\fBsudo\fR
+will send itself the same signal that terminated the
+\fIcommand\fR.
+.PP
+If the
+\fB\-l\fR
+option was specified without a
+\fIcommand\fR,
+\fBsudo\fR
+will exit with a value of 0 if the user is allowed to run
+\fBsudo\fR
+and they authenticated successfully (as required by the security policy).
+If a
+\fIcommand\fR
+is specified with the
+\fB\-l\fR
+option, the exit value will only be 0 if the
+\fIcommand\fR
+is permitted by the security policy, otherwise it will be 1.
+.PP
+If there is an authentication failure, a configuration/permission
+problem, or if the given
+\fIcommand\fR
+cannot be executed,
+\fBsudo\fR
+exits with a value of 1.
+In the latter case, the error string is printed to the standard error.
+If
+\fBsudo\fR
+cannot
+stat(2)
+one or more entries in the user's
+\fRPATH\fR,
+an error is printed to the standard error.
+(If the directory does not exist or if it is not really a directory,
+the entry is ignored and no error is printed.)
+This should not happen under normal circumstances.
+The most common reason for
+stat(2)
+to return
+\(lqpermission denied\(rq
+is if you are running an automounter and one of the directories in
+your
+\fRPATH\fR
+is on a machine that is currently unreachable.
+.SH "SECURITY NOTES"
+\fBsudo\fR
+tries to be safe when executing external
+\fIcommand\fRs.
+.PP
+To prevent command spoofing,
+\fBsudo\fR
+checks "." and "" (both denoting current directory) last when
+searching for a
+\fIcommand\fR
+in the user's
+\fRPATH\fR
+(if one or both are in the
+\fRPATH\fR).
+Depending on the security policy, the user's
+\fRPATH\fR
+environment variable may be modified, replaced,
+or passed unchanged to the program that
+\fBsudo\fR
+executes.
+.PP
+Users should
+\fInever\fR
+be granted
+\fBsudo\fR
+privileges to execute files that are writable by the user or
+that reside in a directory that is writable by the user.
+If the user can modify or replace the
+\fIcommand\fR
+there is no way to limit what additional
+\fIcommand\fRs
+they can run.
+.PP
+By default,
+\fBsudo\fR
+will only log the
+\fIcommand\fR
+it explicitly runs.
+If a user runs a
+\fIcommand\fR
+such as
+\(oqsudo su\(cq
+or
+\(oqsudo sh\(cq,
+subsequent
+\fIcommand\fRs
+run from that shell are not subject to
+\fBsudo\fR's
+security policy.
+The same is true for
+\fIcommand\fRs
+that offer shell escapes (including most editors).
+If I/O logging is enabled, subsequent
+\fIcommand\fRs
+will have their input and/or output logged, but there will not be
+traditional logs for those
+\fIcommand\fRs.
+Because of this, care must be taken when giving users access to
+\fIcommand\fRs
+via
+\fBsudo\fR
+to verify that the
+\fIcommand\fR
+does not inadvertently give the user an effective root shell.
+For information on ways to address this, see the
+\fIPreventing shell escapes\fR
+section in
+sudoers(@mansectform@).
+.PP
+To prevent the disclosure of potentially sensitive information,
+\fBsudo\fR
+disables core dumps by default while it is executing (they are
+re-enabled for the
+\fIcommand\fR
+that is run).
+This historical practice dates from a time when most operating
+systems allowed set-user-ID processes to dump core by default.
+To aid in debugging
+\fBsudo\fR
+crashes, you may wish to re-enable core dumps by setting
+\(lqdisable_coredump\(rq
+to false in the
+sudo.conf(@mansectform@)
+file as follows:
+.nf
+.sp
+.RS 4n
+Set disable_coredump false
+.RE
+.fi
+.PP
+See the
+sudo.conf(@mansectform@)
+manual for more information.
+.SH "ENVIRONMENT"
+\fBsudo\fR
+utilizes the following environment variables.
+The security policy has control over the actual content of the
+\fIcommand\fR's
+environment.
+.TP 17n
+\fREDITOR\fR
+Default editor to use in
+\fB\-e\fR
+(sudoedit) mode if neither
+\fRSUDO_EDITOR\fR
+nor
+\fRVISUAL\fR
+is set.
+.TP 17n
+\fRMAIL\fR
+Set to the mail spool of the target user when the
+\fB\-i\fR
+option is specified, or when
+\fIenv_reset\fR
+is enabled in
+\fIsudoers\fR
+(unless
+\fRMAIL\fR
+is present in the
+\fIenv_keep\fR
+list).
+.TP 17n
+\fRHOME\fR
+Set to the home directory of the target user when the
+\fB\-i\fR
+or
+\fB\-H\fR
+options are specified, when the
+\fB\-s\fR
+option is specified and
+\fIset_home\fR
+is set in
+\fIsudoers\fR,
+when
+\fIalways_set_home\fR
+is enabled in
+\fIsudoers\fR,
+or when
+\fIenv_reset\fR
+is enabled in
+\fIsudoers\fR
+and
+\fRHOME\fR
+is not present in the
+\fIenv_keep\fR
+list.
+.TP 17n
+\fRLOGNAME\fR
+Set to the login name of the target user when the
+\fB\-i\fR
+option is specified, when the
+\fIset_logname\fR
+option is enabled in
+\fIsudoers\fR,
+or when the
+\fIenv_reset\fR
+option is enabled in
+\fIsudoers\fR
+(unless
+\fRLOGNAME\fR
+is present in the
+\fIenv_keep\fR
+list).
+.TP 17n
+\fRPATH\fR
+May be overridden by the security policy.
+.TP 17n
+\fRSHELL\fR
+Used to determine shell to run with
+\fB\-s\fR
+option.
+.TP 17n
+\fRSUDO_ASKPASS\fR
+Specifies the path to a helper program used to read the password
+if no terminal is available or if the
+\fB\-A\fR
+option is specified.
+.TP 17n
+\fRSUDO_COMMAND\fR
+Set to the
+\fIcommand\fR
+run by sudo, including any
+\fIarg\fRs.
+The
+\fIarg\fRs
+are truncated at 4096 characters to prevent a potential execution error.
+.TP 17n
+\fRSUDO_EDITOR\fR
+Default editor to use in
+\fB\-e\fR
+(sudoedit) mode.
+.TP 17n
+\fRSUDO_GID\fR
+Set to the group-ID of the user who invoked sudo.
+.TP 17n
+\fRSUDO_PROMPT\fR
+Used as the default password prompt unless the
+\fB\-p\fR
+option was specified.
+.TP 17n
+\fRSUDO_PS1\fR
+If set,
+\fRPS1\fR
+will be set to its value for the program being run.
+.TP 17n
+\fRSUDO_UID\fR
+Set to the user-ID of the user who invoked sudo.
+.TP 17n
+\fRSUDO_USER\fR
+Set to the login name of the user who invoked sudo.
+.TP 17n
+\fRUSER\fR
+Set to the same value as
+\fRLOGNAME\fR,
+described above.
+.TP 17n
+\fRVISUAL\fR
+Default editor to use in
+\fB\-e\fR
+(sudoedit) mode if
+\fRSUDO_EDITOR\fR
+is not set.
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/sudo.conf\fR
+\fBsudo\fR
+front-end configuration
+.SH "EXAMPLES"
+The following examples assume a properly configured security policy.
+.PP
+To get a file listing of an unreadable directory:
+.nf
+.sp
+.RS 4n
+$ sudo ls /usr/local/protected
+.RE
+.fi
+.PP
+To list the home directory of user yaz on a machine where the file
+system holding ~yaz is not exported as root:
+.nf
+.sp
+.RS 4n
+$ sudo -u yaz ls ~yaz
+.RE
+.fi
+.PP
+To edit the
+\fIindex.html\fR
+file as user www:
+.nf
+.sp
+.RS 4n
+$ sudoedit -u www ~www/htdocs/index.html
+.RE
+.fi
+.PP
+To view system logs only accessible to root and users in the adm
+group:
+.nf
+.sp
+.RS 4n
+$ sudo -g adm more @log_dir@/syslog
+.RE
+.fi
+.PP
+To run an editor as jim with a different primary group:
+.nf
+.sp
+.RS 4n
+$ sudoedit -u jim -g audio ~jim/sound.txt
+.RE
+.fi
+.PP
+To shut down a machine:
+.nf
+.sp
+.RS 4n
+$ sudo shutdown -r +15 "quick reboot"
+.RE
+.fi
+.PP
+To make a usage listing of the directories in the /home partition.
+The
+\fIcommands\fR
+are run in a sub-shell to allow the
+\(oqcd\(cq
+command and file redirection to work.
+.nf
+.sp
+.RS 4n
+$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"
+.RE
+.fi
+.SH "DIAGNOSTICS"
+Error messages produced by
+\fBsudo\fR
+include:
+.TP 6n
+\fRediting files in a writable directory is not permitted\fR
+By default,
+\fBsudoedit\fR
+does not permit editing a file when any of the parent directories are writable
+by the invoking user.
+This avoids a race condition that could allow the user to overwrite
+an arbitrary file.
+See the
+\fIsudoedit_checkdir\fR
+option in
+sudoers(@mansectform@)
+for more information.
+.TP 6n
+\fRediting symbolic links is not permitted\fR
+By default,
+\fBsudoedit\fR
+does not follow symbolic links when opening files.
+See the
+\fIsudoedit_follow\fR
+option in
+sudoers(@mansectform@)
+for more information.
+.TP 6n
+\fReffective uid is not 0, is sudo installed setuid root?\fR
+\fBsudo\fR
+was not run with root privileges.
+The
+\fBsudo\fR
+binary must be owned by the root user and have the set-user-ID bit set.
+Also, it must not be located on a file system mounted with the
+\(oqnosuid\(cq
+option or on an NFS file system that maps uid 0 to an unprivileged uid.
+.TP 6n
+\fReffective uid is not 0, is sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?\fR
+\fBsudo\fR
+was not run with root privileges.
+The
+\fBsudo\fR
+binary has the proper owner and permissions but it still did not run
+with root privileges.
+The most common reason for this is that the file system the
+\fBsudo\fR
+binary is located on is mounted with the
+\(oqnosuid\(cq
+option or it is an NFS file system that maps uid 0 to an unprivileged uid.
+.TP 6n
+\fRfatal error, unable to load plugins\fR
+An error occurred while loading or initializing the plugins specified in
+sudo.conf(@mansectform@).
+.TP 6n
+\fRinvalid environment variable name\fR
+One or more environment variable names specified via the
+\fB\-E\fR
+option contained an equal sign
+(\(oq=\(cq).
+The arguments to the
+\fB\-E\fR
+option should be environment variable names without an associated value.
+.TP 6n
+\fRno password was provided\fR
+When
+\fBsudo\fR
+tried to read the password, it did not receive any characters.
+This may happen if no terminal is available (or the
+\fB\-S\fR
+option is specified) and the standard input has been redirected from
+\fI/dev/null\fR.
+.TP 6n
+\fRa terminal is required to read the password\fR
+\fBsudo\fR
+needs to read the password but there is no mechanism available for it
+to do so.
+A terminal is not present to read the password from,
+\fBsudo\fR
+has not been configured to read from the standard input,
+the
+\fB\-S\fR
+option was not used, and no askpass helper has been specified either via the
+sudo.conf(@mansectform@)
+file or the
+\fRSUDO_ASKPASS\fR
+environment variable.
+.TP 6n
+\fRno writable temporary directory found\fR
+\fBsudoedit\fR
+was unable to find a usable temporary directory in which to store its
+intermediate files.
+.TP 6n
+\fRThe\fR \(lqno new privileges\(rq flag is set, which prevents sudo from running as root.
+\fBsudo\fR
+was run by a process that has the Linux
+\(lqno new privileges\(rq
+flag is set.
+This causes the set-user-ID bit to be ignored when running an executable,
+which will prevent
+\fBsudo\fR
+from functioning.
+The most likely cause for this is running
+\fBsudo\fR
+within a container that sets this flag.
+Check the documentation to see if it is possible to configure the
+container such that the flag is not set.
+.TP 6n
+\fRsudo must be owned by uid 0 and have the setuid bit set\fR
+\fBsudo\fR
+was not run with root privileges.
+The
+\fBsudo\fR
+binary does not have the correct owner or permissions.
+It must be owned by the root user and have the set-user-ID bit set.
+.TP 6n
+\fRsudoedit is not supported on this platform\fR
+It is only possible to run
+\fBsudoedit\fR
+on systems that support setting the effective user-ID.
+.TP 6n
+\fRtimed out reading password\fR
+The user did not enter a password before the password timeout
+(5 minutes by default) expired.
+.TP 6n
+\fRyou do not exist in the passwd database\fR
+Your user-ID does not appear in the system passwd database.
+.TP 6n
+\fRyou may not specify environment variables in edit mode\fR
+It is only possible to specify environment variables when running a
+\fIcommand\fR.
+When editing a file, the editor is run with the user's environment unmodified.
+.SH "SEE ALSO"
+su(1),
+stat(2),
+login_cap(3),
+passwd(@mansectform@),
+sudo.conf(@mansectform@),
+sudo_plugin(@mansectform@),
+sudoers(@mansectform@),
+sudoers_timestamp(@mansectform@),
+sudoreplay(@mansectsu@),
+visudo(@mansectsu@)
+.SH "HISTORY"
+See the HISTORY.md file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/about/history/) for a brief
+history of sudo.
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS.md file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "CAVEATS"
+There is no easy way to prevent a user from gaining a root shell
+if that user is allowed to run arbitrary
+\fIcommands\fR
+via
+\fBsudo\fR.
+Also, many programs (such as editors) allow the user to run
+\fIcommand\fRs
+via shell escapes, thus avoiding
+\fBsudo\fR's
+checks.
+However, on most systems it is possible to prevent shell escapes with the
+sudoers(@mansectform@)
+plugin's
+\fInoexec\fR
+functionality.
+.PP
+It is not meaningful to run the
+\(oqcd\(cq
+\fIcommand\fR
+directly via sudo, e.g.,
+.nf
+.sp
+.RS 4n
+$ sudo cd /usr/local/protected
+.RE
+.fi
+.PP
+since when the
+\fIcommand\fR
+exits the parent process (your shell) will still be the same.
+The
+\fB\-D\fR
+option can be used to run a
+\fIcommand\fR
+in a specific
+\fIdirectory\fR.
+.PP
+Running shell scripts via
+\fBsudo\fR
+can expose the same kernel bugs that make set-user-ID shell scripts
+unsafe on some operating systems (if your OS has a /dev/fd/ directory,
+set-user-ID shell scripts are generally safe).
+.SH "BUGS"
+If you believe you have found a bug in
+\fBsudo\fR,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudo.man.in.sed b/docs/sudo.man.in.sed
new file mode 100644
index 0000000..432dd74
--- /dev/null
+++ b/docs/sudo.man.in.sed
@@ -0,0 +1,76 @@
+s/^\(.TH .*\)/.nr SL @SEMAN@\
+.nr BA @BAMAN@\
+.nr LC @LCMAN@\
+.nr PS @PSMAN@\
+\1/
+
+s/^\(\[\\fB\\-a\\fR.*\\fItype\\fR\]\) *$/.if \\n(BA \1/
+s/^\(\[\\fB\\-c\\fR.*\\fIclass\\fR\]\) *$/.if \\n(LC \1/
+s/^\(\[\\fB\\-r\\fR.*\\fIrole\\fR\]\) *$/.if \\n(SL \1/
+s/^\(\[\\fB\\-t\\fR.*\\fItype\\fR\]\) *$/.if \\n(SL \1/
+
+/^\.TP 12n$/ {
+ N
+ /^\.TP 12n\n\\fB\\-a\\fR.*\\fItype\\fR$/,/^\.TP 12n/ {
+ /^\.TP 12n/ {
+ /^\.TP 12n\n\\fB\\-a\\fR.*\\fItype\\fR$/i\
+.if \\n(BA \\{\\
+ /^\.TP 12n\n\\fB\\-a\\fR.*\\fItype\\fR$/!i\
+.\\}
+ }
+ }
+ /^\.TP 12n\n\\fB\\-c\\fR.*\\fIclass\\fR$/,/^\.TP 12n/ {
+ /^\.TP 12n/ {
+ /^\.TP 12n\n\\fB\\-c\\fR.*\\fIclass\\fR$/i\
+.if \\n(LC \\{\\
+ /^\.TP 12n\n\\fB\\-c\\fR.*\\fIclass\\fR$/!i\
+.\\}
+ }
+ }
+ /^\.TP 12n\n\\fB\\-r\\fR.*\\fIrole\\fR$/,/^\.TP 12n/ {
+ /^\.TP 12n/ {
+ /^\.TP 12n\n\\fB\\-r\\fR.*\\fIrole\\fR$/i\
+.if \\n(SL \\{\\
+ /^\.TP 12n\n\\fB\\-r\\fR.*\\fIrole\\fR$/!i\
+.\\}
+ }
+ }
+ /^\.TP 12n\n\\fB\\-t\\fR.*\\fItype\\fR$/,/^\.TP 12n/ {
+ /^\.TP 12n/ {
+ /^\.TP 12n\n\\fB\\-t\\fR.*\\fItype\\fR$/i\
+.if \\n(SL \\{\\
+ /^\.TP 12n\n\\fB\\-t\\fR.*\\fItype\\fR$/!i\
+.\\}
+ }
+ }
+}
+
+/^\.TP 3n$/ {
+ N
+ N
+ /^.TP 3n\n\\fB\\(bu\\fR\nSELinux role and type$/ {
+ i\
+.if \\n(SL \\{\\
+ a\
+.\\}
+ }
+ /^.TP 3n\n\\fB\\(bu\\fR\nSolaris project$/ {
+ i\
+.if \\n(PS \\{\\
+ a\
+.\\}
+ }
+ /^.TP 3n\n\\fB\\(bu\\fR\nSolaris privileges$/ {
+ i\
+.if \\n(PS \\{\\
+ a\
+.\\}
+ }
+ /^.TP 3n\n\\fB\\(bu\\fR\nBSD$/ {
+ N
+ i\
+.if \\n(LC \\{\\
+ a\
+.\\}
+ }
+}
diff --git a/docs/sudo.mdoc.in b/docs/sudo.mdoc.in
new file mode 100644
index 0000000..9374f6c
--- /dev/null
+++ b/docs/sudo.mdoc.in
@@ -0,0 +1,1628 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 1994-1996, 1998-2005, 2007-2023
+.\" Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" Sponsored in part by the Defense Advanced Research Projects
+.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
+.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
+.\"
+.nr SL @SEMAN@
+.nr BA @BAMAN@
+.nr LC @LCMAN@
+.nr PS @PSMAN@
+.Dd August 9, 2023
+.Dt SUDO @mansectsu@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudo ,
+.Nm sudoedit
+.Nd execute a command as another user
+.Sh SYNOPSIS
+.Nm sudo
+.Fl h | K | k | V
+.Nm sudo
+.Fl v
+.Op Fl ABkNnS
+.if \n(BA \{\
+.Op Fl a Ar type
+.\}
+.Op Fl g Ar group
+.Op Fl h Ar host
+.Op Fl p Ar prompt
+.Op Fl u Ar user
+.Nm sudo
+.Fl l
+.Op Fl ABkNnS
+.if \n(BA \{\
+.Op Fl a Ar type
+.\}
+.Op Fl g Ar group
+.Op Fl h Ar host
+.Op Fl p Ar prompt
+.Op Fl U Ar user
+.Op Fl u Ar user
+.Op Ar command Op Ar arg ...
+.Nm sudo
+.Op Fl ABbEHnPS
+.if \n(BA \{\
+.Op Fl a Ar type
+.\}
+.Op Fl C Ar num
+.if \n(LC \{\
+.Op Fl c Ar class
+.\}
+.Op Fl D Ar directory
+.Op Fl g Ar group
+.Op Fl h Ar host
+.Op Fl p Ar prompt
+.Op Fl R Ar directory
+.if \n(SL \{\
+.Op Fl r Ar role
+.Op Fl t Ar type
+.\}
+.Op Fl T Ar timeout
+.Op Fl u Ar user
+.Op Ar VAR Ns = Ns Ar value
+.Op Fl i | s
+.Op Ar command Op Ar arg ...
+.Nm sudoedit
+.Op Fl ABkNnS
+.if \n(BA \{\
+.Op Fl a Ar type
+.\}
+.Op Fl C Ar num
+.if \n(LC \{\
+.Op Fl c Ar class
+.\}
+.Op Fl D Ar directory
+.Op Fl g Ar group
+.Op Fl h Ar host
+.Op Fl p Ar prompt
+.Op Fl R Ar directory
+.if \n(SL \{\
+.Op Fl r Ar role
+.Op Fl t Ar type
+.\}
+.Op Fl T Ar timeout
+.Op Fl u Ar user
+.Ar
+.Sh DESCRIPTION
+.Nm
+allows a permitted user to execute a
+.Ar command
+as the superuser or another user, as specified by the security
+policy.
+The invoking user's real
+.Pq Em not No effective
+user-ID is used to determine the user name with which
+to query the security policy.
+.Pp
+.Nm
+supports a plugin architecture for security policies, auditing,
+and input/output logging.
+Third parties can develop and distribute their own plugins to work
+seamlessly with the
+.Nm
+front-end.
+The default security policy is
+.Em sudoers ,
+which is configured via the file
+.Pa @sysconfdir@/sudoers ,
+or via LDAP.
+See the
+.Sx Plugins
+section for more information.
+.Pp
+The security policy determines what privileges, if any, a user has
+to run
+.Nm .
+The policy may require that users authenticate themselves with a
+password or another authentication mechanism.
+If authentication is required,
+.Nm
+will exit if the user's password is not entered within a configurable
+time limit.
+This limit is policy-specific; the default password prompt timeout
+for the
+.Em sudoers
+security policy is @password_timeout@ minutes.
+.Pp
+Security policies may support credential caching to allow the user
+to run
+.Nm
+again for a period of time without requiring authentication.
+By default, the
+.Em sudoers
+policy caches credentials on a per-terminal basis for @timeout@ minutes.
+See the
+.Em timestamp_type
+and
+.Em timestamp_timeout
+options in
+.Xr sudoers @mansectform@
+for more information.
+By running
+.Nm
+with the
+.Fl v
+option, a user can update the cached credentials without running a
+.Ar command .
+.Pp
+On systems where
+.Nm
+is the primary method of gaining superuser privileges, it is imperative
+to avoid syntax errors in the security policy configuration files.
+For the default security policy,
+.Xr sudoers @mansectform@ ,
+changes to the configuration files should be made using the
+.Xr visudo @mansectsu@
+utility which will ensure that no syntax errors are introduced.
+.Pp
+When invoked as
+.Nm sudoedit ,
+the
+.Fl e
+option (described below), is implied.
+.Pp
+Security policies and audit plugins may log successful and failed attempts
+to run
+.Nm .
+If an I/O plugin is configured, the running
+.Ar command Ns 's
+input and output may be logged as well.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl A , -askpass
+Normally, if
+.Nm
+requires a password, it will read it from the user's terminal.
+If the
+.Fl A Pq Em askpass
+option is specified, a (possibly graphical) helper program is
+executed to read the user's password and output the password to the
+standard output.
+If the
+.Ev SUDO_ASKPASS
+environment variable is set, it specifies the path to the helper
+program.
+Otherwise, if
+.Xr sudo.conf @mansectform@
+contains a line specifying the askpass program, that value will be
+used.
+For example:
+.Bd -literal -offset 4n
+# Path to askpass helper program
+Path askpass /usr/X11R6/bin/ssh-askpass
+.Ed
+.Pp
+If no askpass program is available,
+.Nm
+will exit with an error.
+.if \n(BA \{\
+.It Fl a Ar type , Fl -auth-type Ns = Ns Ar type
+Use the specified
+.Bx
+authentication
+.Ar type
+when validating the user, if allowed by
+.Pa /etc/login.conf .
+The system administrator may specify a list of sudo-specific
+authentication methods by adding an
+.Dq auth-sudo
+entry in
+.Pa /etc/login.conf .
+This option is only available on systems that support
+.Bx
+authentication.
+.\}
+.It Fl B , -bell
+Ring the bell as part of the password prompt when a terminal is present.
+This option has no effect if an askpass program is used.
+.It Fl b , -background
+Run the given
+.Ar command
+in the background.
+It is not possible to use shell job control to manipulate background
+processes started by
+.Nm .
+Most interactive
+.Ar command Ns s
+will fail to work properly in background mode.
+.It Fl C Ar num , Fl -close-from Ns = Ns Ar num
+Close all file descriptors greater than or equal to
+.Ar num
+before executing a
+.Ar command .
+Values less than three are not permitted.
+By default,
+.Nm
+will close all open file descriptors other than standard input,
+standard output, and standard error when executing a
+.Ar command .
+The security policy may restrict the user's ability to use this option.
+The
+.Em sudoers
+policy only permits use of the
+.Fl C
+option when the administrator has enabled the
+.Em closefrom_override
+option.
+.if \n(LC \{\
+.It Fl c Ar class , Fl -login-class Ns = Ns Ar class
+Run the
+.Ar command
+with resource limits and scheduling priority of the specified login
+.Ar class .
+The
+.Ar class
+argument can be either a class name as defined in
+.Pa /etc/login.conf ,
+or a single
+.Ql \-
+character.
+If
+.Ar class
+is
+.Cm - ,
+the default login class of the target user will be used.
+Otherwise, the
+.Ar command
+must be run as the superuser (user-ID 0), or
+.Nm
+must be run from a shell that is already running as the superuser.
+If the
+.Ar command
+is being run as a login shell, additional
+.Pa /etc/login.conf
+settings, such as the umask and environment variables, will
+be applied, if present.
+This option is only available on systems with
+.Bx
+login classes.
+.\}
+.It Fl D Ar directory , Fl -chdir Ns = Ns Ar directory
+Run the
+.Ar command
+in the specified
+.Ar directory
+instead of the current working directory.
+The security policy may return an error if the user does not have
+permission to specify the working directory.
+.It Fl E , -preserve-env
+Indicates to the security policy that the user wishes to
+preserve their existing environment variables.
+The security policy may return an error if the user does not have
+permission to preserve the environment.
+.It Fl -preserve-env=list
+Indicates to the security policy that the user wishes to add the
+comma-separated list of environment variables to those preserved
+from the user's environment.
+The security policy may return an error if the user does not have
+permission to preserve the environment.
+This option may be specified multiple times.
+.It Fl e , -edit
+Edit one or more
+.Ar file Ns s
+instead of running a
+.Ar command .
+In lieu of a path name, the string "sudoedit" is used when consulting
+the security policy.
+If the user is authorized by the policy, the following steps are
+taken:
+.Bl -enum -offset 4
+.It
+Temporary copies are made of the files to be edited with the owner
+set to the invoking user.
+.It
+The editor specified by the policy is run to edit the temporary
+files.
+The
+.Em sudoers
+policy uses the
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+and
+.Ev EDITOR
+environment variables (in that order).
+If none of
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+or
+.Ev EDITOR
+are set, the first program listed in the
+.Em editor
+.Xr sudoers @mansectform@
+option is used.
+.It
+If they have been modified, the temporary files are copied back to
+their original location and the temporary versions are removed.
+.El
+.Pp
+To help prevent the editing of unauthorized files, the following
+restrictions are enforced unless explicitly allowed by the security policy:
+.Bl -bullet -offset 1n -width 1n
+.It
+Symbolic links may not be edited (version 1.8.15 and higher).
+.It
+Symbolic links along the path to be edited are not followed when the
+parent directory is writable by the invoking user unless that user
+is root (version 1.8.16 and higher).
+.It
+Files located in a directory that is writable by the invoking user may
+not be edited unless that user is root (version 1.8.16 and higher).
+.El
+.Pp
+Users are never allowed to edit device special files.
+.Pp
+If the specified file does not exist, it will be created.
+Unlike most
+.Ar command Ns s
+run by
+.Em sudo ,
+the editor is run with the invoking user's environment unmodified.
+If the temporary file becomes empty after editing, the user will
+be prompted before it is installed.
+If, for some reason,
+.Nm
+is unable to update a file with its edited version, the user will
+receive a warning and the edited copy will remain in a temporary
+file.
+.It Fl g Ar group , Fl -group Ns = Ns Ar group
+Run the
+.Ar command
+with the primary group set to
+.Ar group
+instead of the primary group specified by the target
+user's password database entry.
+The
+.Ar group
+may be either a group name or a numeric group-ID
+.Pq GID
+prefixed with the
+.Ql #
+character (e.g.,
+.Ql #0
+for GID 0).
+When running a
+.Ar command
+as a GID, many shells require that the
+.Ql #
+be escaped with a backslash
+.Pq Ql \e .
+If no
+.Fl u
+option is specified, the
+.Ar command
+will be run as the invoking user.
+In either case, the primary group will be set to
+.Ar group .
+The
+.Em sudoers
+policy permits any of the target user's groups to be specified via
+the
+.Fl g
+option as long as the
+.Fl P
+option is not in use.
+.It Fl H , -set-home
+Request that the security policy set the
+.Ev HOME
+environment variable to the home directory specified by the target
+user's password database entry.
+Depending on the policy, this may be the default behavior.
+.It Fl h , -help
+Display a short help message to the standard output and exit.
+.It Fl h Ar host , Fl -host Ns = Ns Ar host
+Run the
+.Ar command
+on the specified
+.Ar host
+if the security policy plugin supports remote
+.Ar command Ns s.
+The
+.Em sudoers
+plugin does not currently support running remote
+.Ar command Ns s.
+This may also be used in conjunction with the
+.Fl l
+option to list a user's privileges for the remote host.
+.It Fl i , -login
+Run the shell specified by the target user's password database entry
+as a login shell.
+This means that login-specific resource files such as
+.Pa .profile ,
+.Pa .bash_profile ,
+or
+.Pa .login
+will be read by the shell.
+If a
+.Ar command
+is specified, it is passed to the shell as a simple
+.Ar command
+using the
+.Fl c
+option.
+The
+.Ar command
+and any
+.Ar arg Ns s
+are concatenated, separated by spaces, after escaping each character
+.Pq including white space
+with a backslash
+.Pq Ql \e
+except for alphanumerics, underscores,
+hyphens, and dollar signs.
+If no
+.Ar command
+is specified, an interactive shell is executed.
+.Nm
+attempts to change to that user's home directory before running the
+shell.
+The
+.Ar command
+is run with an environment similar to the one a user would receive at log in.
+Most shells behave differently when a
+.Ar command
+is specified as compared to an interactive session; consult the shell's manual
+for details.
+The
+.Em Command environment
+section in the
+.Xr sudoers @mansectform@
+manual documents how the
+.Fl i
+option affects the environment in which a
+.Ar command
+is run when the
+.Em sudoers
+policy is in use.
+.It Fl K , -remove-timestamp
+Similar to the
+.Fl k
+option, except that it removes every cached credential for the user,
+regardless of the terminal or parent process ID.
+The next time
+.Nm
+is run, a password must be entered if the
+security policy requires authentication.
+It is not possible to use the
+.Fl K
+option in conjunction with a
+.Ar command
+or other option.
+This option does not require a password.
+Not all security policies support credential caching.
+.It Fl k , -reset-timestamp
+When used without a
+.Ar command ,
+invalidates the user's cached credentials for the current session.
+The next time
+.Nm
+is run in the session, a password must be entered if the
+security policy requires authentication.
+By default, the
+.Nm sudoers
+policy uses a separate record in the credential cache for each
+terminal (or parent process ID if no terminal is present).
+This prevents the
+.Fl k
+option from interfering with
+.Nm
+commands run in a different terminal session.
+See the
+.Em timestamp_type
+option in
+.Xr sudoers @mansectform@
+for more information.
+This option does not require a password, and was added to allow a
+user to revoke
+.Nm
+permissions from a
+.Pa .logout
+file.
+.Pp
+When used in conjunction with a
+.Ar command
+or an option that may require a password, this option will cause
+.Nm
+to ignore the user's cached credentials.
+As a result,
+.Nm
+will prompt for a password (if one is required by the security
+policy) and will not update the user's cached credentials.
+.Pp
+Not all security policies support credential caching.
+.It Fl l , Fl -list
+If no
+.Ar command
+is specified, list the privileges for the invoking user (or the
+.Ar user
+specified by the
+.Fl U
+option) on the current host.
+A longer list format is used if this option is specified multiple times
+and the security policy supports a verbose output format.
+.Pp
+If a
+.Ar command
+is specified and is permitted by the security policy for the invoking
+user (or the,
+.Ar user
+specified by the
+.Fl U
+option) on the current host,
+the fully-qualified path to the
+.Ar command
+is displayed along with any
+.Ar arg Ns s.
+If
+.Fl l
+is specified more than once (and the security policy supports it),
+the matching rule is displayed in a verbose format along with the
+.Ar command .
+If a
+.Ar command
+is specified but not allowed by the policy,
+.Nm
+will exit with a status value of 1.
+.It Fl N , -no-update
+Do not update the user's cached credentials, even if the user successfully
+authenticates.
+Unlike the
+.Fl k
+flag, existing cached credentials are used if they are valid.
+To detect when the user's cached credentials are valid (or when no
+authentication is required), the following can be used:
+.Bd -literal -offset 4n
+sudo -Nnv
+.Ed
+.Pp
+Not all security policies support credential caching.
+.It Fl n , -non-interactive
+Avoid prompting the user for input of any kind.
+If a password is required for the
+.Ar command
+to run,
+.Nm
+will display an error message and exit.
+.It Fl P , -preserve-groups
+Preserve the invoking user's group vector unaltered.
+By default, the
+.Em sudoers
+policy will initialize the group vector to the list of groups the
+target user is a member of.
+The real and effective group-IDs, however, are still set to match
+the target user.
+.It Fl p Ar prompt , Fl -prompt Ns = Ns Ar prompt
+Use a custom password prompt with optional escape sequences.
+The following percent
+.Pq Ql %
+escape sequences are supported by the
+.Em sudoers
+policy:
+.Bl -tag -width 2n
+.It %H
+expanded to the host name including the domain name (only if the
+machine's host name is fully qualified or the
+.Em fqdn
+option is set in
+.Xr sudoers @mansectform@ )
+.It %h
+expanded to the local host name without the domain name
+.It %p
+expanded to the name of the user whose password is being requested
+(respects the
+.Em rootpw ,
+.Em targetpw ,
+and
+.Em runaspw
+flags in
+.Xr sudoers @mansectform@ )
+.It \&%U
+expanded to the login name of the user the
+.Ar command
+will be run as (defaults to root unless the
+.Fl u
+option is also specified)
+.It %u
+expanded to the invoking user's login name
+.It %%
+two consecutive
+.Ql %
+characters are collapsed into a single
+.Ql %
+character
+.El
+.Pp
+The custom prompt will override the default prompt specified by either
+the security policy or the
+.Ev SUDO_PROMPT
+environment variable.
+On systems that use PAM, the custom prompt will also override the prompt
+specified by a PAM module unless the
+.Em passprompt_override
+flag is disabled in
+.Em sudoers .
+.It Fl R Ar directory , Fl -chroot Ns = Ns Ar directory
+Change to the specified root
+.Ar directory
+(see
+.Xr chroot @mansectsu@ )
+before running the
+.Ar command .
+The security policy may return an error if the user does not have
+permission to specify the root directory.
+.if \n(SL \{\
+.It Fl r Ar role , Fl -role Ns = Ns Ar role
+Run the
+.Ar command
+with an SELinux security context that includes the specified
+.Ar role .
+.\}
+.It Fl S , -stdin
+Write the prompt to the standard error and read the password from the
+standard input instead of using the terminal device.
+.It Fl s , -shell
+Run the shell specified by the
+.Ev SHELL
+environment variable if it is set or the shell specified by the
+invoking user's password database entry.
+If a
+.Ar command
+is specified, it is passed to the shell as a simple command using the
+.Fl c
+option.
+The
+.Ar command
+and any
+.Ar arg Ns s
+are concatenated, separated by spaces, after escaping each character
+.Pq including white space
+with a backslash
+.Pq Ql \e
+except for alphanumerics, underscores,
+hyphens, and dollar signs.
+If no
+.Ar command
+is specified, an interactive shell is executed.
+Most shells behave differently when a
+.Ar command
+is specified as compared to an interactive session; consult the shell's manual
+for details.
+.if \n(SL \{\
+.It Fl t Ar type , Fl -type Ns = Ns Ar type
+Run the
+.Ar command
+with an SELinux security context that includes the specified
+.Ar type .
+If no
+.Ar type
+is specified, the default type is derived from the role.
+.\}
+.It Fl U Ar user , Fl -other-user Ns = Ns Ar user
+Used in conjunction with the
+.Fl l
+option to list the privileges for
+.Ar user
+instead of for the invoking user.
+The security policy may restrict listing other users' privileges.
+When using the
+.Em sudoers
+policy, the
+.Fl U
+option is restricted to the root user and users with either the
+.Dq list
+priviege for the specified
+.Ar user
+or the ability to run any
+.Ar command
+as root or
+.Ar user
+on the current host.
+.It Fl T Ar timeout , Fl -command-timeout Ns = Ns Ar timeout
+Used to set a timeout for the
+.Ar command .
+If the timeout expires before the
+.Ar command
+has exited, the
+.Ar command
+will be terminated.
+The security policy may restrict the user's ability to set timeouts.
+The
+.Em sudoers
+policy requires that user-specified timeouts be explicitly enabled.
+.It Fl u Ar user , Fl -user Ns = Ns Ar user
+Run the
+.Ar command
+as a user other than the default target user (usually
+.Sy root ) .
+The
+.Ar user
+may be either a user name or a numeric user-ID
+.Pq UID
+prefixed with the
+.Ql #
+character (e.g.,
+.Ql #0
+for UID 0).
+When running
+.Ar command Ns s as
+a UID, many shells require that the
+.Ql #
+be escaped with a backslash
+.Pq Ql \e .
+Some security policies may restrict UIDs
+to those listed in the password database.
+The
+.Em sudoers
+policy allows UIDs that are not in the password database as long as the
+.Em targetpw
+option is not set.
+Other security policies may not support this.
+.It Fl V , -version
+Print the
+.Nm
+version string as well as the version string of any configured plugins.
+If the invoking user is already root, the
+.Fl V
+option will display the options passed to configure when
+.Nm
+was built; plugins may display additional information such as
+default options.
+.It Fl v , -validate
+Update the user's cached credentials, authenticating the user
+if necessary.
+For the
+.Em sudoers
+plugin, this extends the
+.Nm
+timeout for another @timeout@ minutes by default, but does not run a
+.Ar command .
+Not all security policies support cached credentials.
+.It Fl -
+The
+.Fl -
+is used to delimit the end of the
+.Nm
+options.
+Subsequent options are passed to the
+.Ar command .
+.El
+.Pp
+Options that take a value may only be specified once unless
+otherwise indicated in the description.
+This is to help guard against problems caused by poorly written
+scripts that invoke
+.Nm sudo
+with user-controlled input.
+.Pp
+Environment variables to be set for the
+.Ar command
+may also be passed as options to
+.Nm
+in the form
+.Ar VAR Ns = Ns Ar value ,
+for example
+.Ev LD_LIBRARY_PATH Ns = Ns Pa /usr/local/pkg/lib .
+Environment variables may be subject to restrictions
+imposed by the security policy plugin.
+The
+.Em sudoers
+policy subjects environment variables passed as options to the same
+restrictions as existing environment variables with one important
+difference.
+If the
+.Em setenv
+option is set in
+.Em sudoers ,
+the
+.Ar command
+to be run has the
+.Dv SETENV
+tag set or the
+.Ar command
+matched is
+.Sy ALL ,
+the user may set variables that would otherwise be forbidden.
+See
+.Xr sudoers @mansectform@
+for more information.
+.Sh COMMAND EXECUTION
+When
+.Nm
+executes a
+.Ar command ,
+the security policy specifies the execution environment for the
+.Ar command .
+Typically, the real and effective user and group and IDs are set to
+match those of the target user, as specified in the password database,
+and the group vector is initialized based on the group database
+(unless the
+.Fl P
+option was specified).
+.Pp
+The following parameters may be specified by security policy:
+.Bl -bullet -width 1n
+.It
+real and effective user-ID
+.It
+real and effective group-ID
+.It
+supplementary group-IDs
+.It
+the environment list
+.It
+current working directory
+.It
+file creation mode mask (umask)
+.if \n(SL \{\
+.It
+SELinux role and type
+.\}
+.if \n(PS \{\
+.It
+Solaris project
+.It
+Solaris privileges
+.\}
+.if \n(LC \{\
+.It
+.Bx
+login class
+.\}
+.It
+scheduling priority (aka nice value)
+.El
+.Ss Process model
+There are two distinct ways
+.Nm
+can run a
+.Ar command .
+.Pp
+If an I/O logging plugin is configured to log terminal I/O, or if
+the security policy explicitly requests it, a new pseudo-terminal
+.Pq Dq pty
+is allocated and
+.Xr fork 2
+is used to create a second
+.Nm
+process, referred to as the
+.Em monitor .
+The
+.Em monitor
+creates a new terminal session with itself as the leader and the pty as its
+controlling terminal, calls
+.Xr fork 2
+again, sets up the execution environment as described above, and then uses the
+.Xr execve 2
+system call to run the
+.Ar command
+in the child process.
+The
+.Em monitor
+exists to relay job control signals between the user's
+terminal and the pty the
+.Ar command
+is being run in.
+This makes it possible to suspend and resume the
+.Ar command
+normally.
+Without the
+.Em monitor ,
+the
+.Ar command
+would be in what POSIX terms an
+.Dq orphaned process group
+and it would not receive any job control signals from the kernel.
+When the
+.Ar command
+exits or is terminated by a signal, the
+.Em monitor
+passes the
+.Ar command Ns 's
+exit status to the main
+.Nm
+process and exits.
+After receiving the
+.Ar command Ns 's
+exit status, the main
+.Nm
+process passes the
+.Ar command Ns 's
+exit status to the security policy's close function, as well as the
+close function of any configured audit plugin, and exits.
+This mode is the default for sudo versions 1.9.14 and above when using
+the sudoers policy.
+.Pp
+If no pty is used,
+.Nm
+calls
+.Xr fork 2 ,
+sets up the execution environment as described above, and uses the
+.Xr execve 2
+system call to run the
+.Ar command
+in the child process.
+The main
+.Nm
+process waits until the
+.Ar command
+has completed, then passes the
+.Ar command Ns 's
+exit status to the security policy's close function, as well as the
+close function of any configured audit plugins, and exits.
+As a special case, if the policy plugin does not define a close
+function,
+.Nm
+will execute the
+.Ar command
+directly instead of calling
+.Xr fork 2
+first.
+The
+.Em sudoers
+policy plugin will only define a close function when I/O logging
+is enabled, a pty is required, an SELinux role is specified, the
+.Ar command
+has an associated timeout, or the
+.Em pam_session
+or
+.Em pam_setcred
+options are enabled.
+Both
+.Em pam_session
+and
+.Em pam_setcred
+are enabled by default on systems using PAM.
+This mode is the default for sudo versions prior to 1.9.14 when using
+the sudoers policy.
+.Pp
+On systems that use PAM, the security policy's close function
+is responsible for closing the PAM session.
+It may also log the
+.Ar command Ns 's
+exit status.
+.Ss Signal handling
+When the
+.Ar command
+is run as a child of the
+.Nm
+process,
+.Nm
+will relay signals it receives to the
+.Ar command .
+The
+.Dv SIGINT
+and
+.Dv SIGQUIT
+signals are only relayed when the
+.Ar command
+is being run in a new pty or when the signal was sent by a user
+process, not the kernel.
+This prevents the
+.Ar command
+from receiving
+.Dv SIGINT
+twice each time the user enters control-C.
+Some signals, such as
+.Dv SIGSTOP
+and
+.Dv SIGKILL ,
+cannot be caught and thus will not be relayed to the
+.Ar command .
+As a general rule,
+.Dv SIGTSTP
+should be used instead of
+.Dv SIGSTOP
+when you wish to suspend a
+.Ar command
+being run by
+.Nm .
+.Pp
+As a special case,
+.Nm
+will not relay signals that were sent by the
+.Ar command
+it is running.
+This prevents the
+.Ar command
+from accidentally killing itself.
+On some systems, the
+.Xr reboot @mansectsu@
+utility sends
+.Dv SIGTERM
+to all non-system processes other than itself before rebooting
+the system.
+This prevents
+.Nm
+from relaying the
+.Dv SIGTERM
+signal it received back to
+.Xr reboot @mansectsu@ ,
+which might then exit before the system was actually rebooted,
+leaving it in a half-dead state similar to single user mode.
+Note, however, that this check only applies to the
+.Ar command
+run by
+.Nm
+and not any other processes that the
+.Ar command
+may create.
+As a result, running a script that calls
+.Xr reboot @mansectsu@
+or
+.Xr shutdown @mansectsu@
+via
+.Nm
+may cause the system to end up in this undefined state unless the
+.Xr reboot @mansectsu@
+or
+.Xr shutdown @mansectsu@
+are run using the
+.Fn exec
+family of functions instead of
+.Fn system
+(which interposes a shell between the
+.Ar command
+and the calling process).
+.Ss Plugins
+Plugins may be specified via
+.Em Plugin
+directives in the
+.Xr sudo.conf @mansectform@
+file.
+They may be loaded as dynamic shared objects (on systems that support them),
+or compiled directly into the
+.Nm
+binary.
+If no
+.Xr sudo.conf @mansectform@
+file is present, or if it doesn't contain any
+.Em Plugin
+lines,
+.Nm
+will use
+.Xr sudoers @mansectform@
+for the policy, auditing, and I/O logging plugins.
+See the
+.Xr sudo.conf @mansectform@
+manual for details of the
+.Pa @sysconfdir@/sudo.conf
+file and the
+.Xr sudo_plugin @mansectform@
+manual for more information about the
+.Nm
+plugin architecture.
+.Sh EXIT VALUE
+Upon successful execution of a
+.Ar command ,
+the exit status from
+.Nm
+will be the exit status of the program that was executed.
+If the
+.Ar command
+terminated due to receipt of a signal,
+.Nm
+will send itself the same signal that terminated the
+.Ar command .
+.Pp
+If the
+.Fl l
+option was specified without a
+.Ar command ,
+.Nm
+will exit with a value of 0 if the user is allowed to run
+.Nm
+and they authenticated successfully (as required by the security policy).
+If a
+.Ar command
+is specified with the
+.Fl l
+option, the exit value will only be 0 if the
+.Ar command
+is permitted by the security policy, otherwise it will be 1.
+.Pp
+If there is an authentication failure, a configuration/permission
+problem, or if the given
+.Ar command
+cannot be executed,
+.Nm
+exits with a value of 1.
+In the latter case, the error string is printed to the standard error.
+If
+.Nm
+cannot
+.Xr stat 2
+one or more entries in the user's
+.Ev PATH ,
+an error is printed to the standard error.
+(If the directory does not exist or if it is not really a directory,
+the entry is ignored and no error is printed.)
+This should not happen under normal circumstances.
+The most common reason for
+.Xr stat 2
+to return
+.Dq permission denied
+is if you are running an automounter and one of the directories in
+your
+.Ev PATH
+is on a machine that is currently unreachable.
+.Sh SECURITY NOTES
+.Nm
+tries to be safe when executing external
+.Ar command Ns s.
+.Pp
+To prevent command spoofing,
+.Nm
+checks "." and "" (both denoting current directory) last when
+searching for a
+.Ar command
+in the user's
+.Ev PATH
+(if one or both are in the
+.Ev PATH ) .
+Depending on the security policy, the user's
+.Ev PATH
+environment variable may be modified, replaced,
+or passed unchanged to the program that
+.Nm
+executes.
+.Pp
+Users should
+.Em never
+be granted
+.Nm
+privileges to execute files that are writable by the user or
+that reside in a directory that is writable by the user.
+If the user can modify or replace the
+.Ar command
+there is no way to limit what additional
+.Ar command Ns s
+they can run.
+.Pp
+By default,
+.Nm
+will only log the
+.Ar command
+it explicitly runs.
+If a user runs a
+.Ar command
+such as
+.Ql sudo su
+or
+.Ql sudo sh ,
+subsequent
+.Ar command Ns s
+run from that shell are not subject to
+.Nm sudo Ns 's
+security policy.
+The same is true for
+.Ar command Ns s
+that offer shell escapes (including most editors).
+If I/O logging is enabled, subsequent
+.Ar command Ns s
+will have their input and/or output logged, but there will not be
+traditional logs for those
+.Ar command Ns s.
+Because of this, care must be taken when giving users access to
+.Ar command Ns s
+via
+.Nm
+to verify that the
+.Ar command
+does not inadvertently give the user an effective root shell.
+For information on ways to address this, see the
+.Em Preventing shell escapes
+section in
+.Xr sudoers @mansectform@ .
+.Pp
+To prevent the disclosure of potentially sensitive information,
+.Nm
+disables core dumps by default while it is executing (they are
+re-enabled for the
+.Ar command
+that is run).
+This historical practice dates from a time when most operating
+systems allowed set-user-ID processes to dump core by default.
+To aid in debugging
+.Nm
+crashes, you may wish to re-enable core dumps by setting
+.Dq disable_coredump
+to false in the
+.Xr sudo.conf @mansectform@
+file as follows:
+.Bd -literal -offset 4n
+Set disable_coredump false
+.Ed
+.Pp
+See the
+.Xr sudo.conf @mansectform@
+manual for more information.
+.Sh ENVIRONMENT
+.Nm
+utilizes the following environment variables.
+The security policy has control over the actual content of the
+.Ar command Ns 's
+environment.
+.Bl -tag -width 15n
+.It Ev EDITOR
+Default editor to use in
+.Fl e
+(sudoedit) mode if neither
+.Ev SUDO_EDITOR
+nor
+.Ev VISUAL
+is set.
+.It Ev MAIL
+Set to the mail spool of the target user when the
+.Fl i
+option is specified, or when
+.Em env_reset
+is enabled in
+.Em sudoers
+(unless
+.Ev MAIL
+is present in the
+.Em env_keep
+list).
+.It Ev HOME
+Set to the home directory of the target user when the
+.Fl i
+or
+.Fl H
+options are specified, when the
+.Fl s
+option is specified and
+.Em set_home
+is set in
+.Em sudoers ,
+when
+.Em always_set_home
+is enabled in
+.Em sudoers ,
+or when
+.Em env_reset
+is enabled in
+.Em sudoers
+and
+.Ev HOME
+is not present in the
+.Em env_keep
+list.
+.It Ev LOGNAME
+Set to the login name of the target user when the
+.Fl i
+option is specified, when the
+.Em set_logname
+option is enabled in
+.Em sudoers ,
+or when the
+.Em env_reset
+option is enabled in
+.Em sudoers
+(unless
+.Ev LOGNAME
+is present in the
+.Em env_keep
+list).
+.It Ev PATH
+May be overridden by the security policy.
+.It Ev SHELL
+Used to determine shell to run with
+.Fl s
+option.
+.It Ev SUDO_ASKPASS
+Specifies the path to a helper program used to read the password
+if no terminal is available or if the
+.Fl A
+option is specified.
+.It Ev SUDO_COMMAND
+Set to the
+.Ar command
+run by sudo, including any
+.Ar arg Ns s.
+The
+.Ar arg Ns s
+are truncated at 4096 characters to prevent a potential execution error.
+.It Ev SUDO_EDITOR
+Default editor to use in
+.Fl e
+(sudoedit) mode.
+.It Ev SUDO_GID
+Set to the group-ID of the user who invoked sudo.
+.It Ev SUDO_PROMPT
+Used as the default password prompt unless the
+.Fl p
+option was specified.
+.It Ev SUDO_PS1
+If set,
+.Ev PS1
+will be set to its value for the program being run.
+.It Ev SUDO_UID
+Set to the user-ID of the user who invoked sudo.
+.It Ev SUDO_USER
+Set to the login name of the user who invoked sudo.
+.It Ev USER
+Set to the same value as
+.Ev LOGNAME ,
+described above.
+.It Ev VISUAL
+Default editor to use in
+.Fl e
+(sudoedit) mode if
+.Ev SUDO_EDITOR
+is not set.
+.El
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/sudo.conf
+.Nm
+front-end configuration
+.El
+.Sh EXAMPLES
+The following examples assume a properly configured security policy.
+.Pp
+To get a file listing of an unreadable directory:
+.Bd -literal -offset 4n
+$ sudo ls /usr/local/protected
+.Ed
+.Pp
+To list the home directory of user yaz on a machine where the file
+system holding ~yaz is not exported as root:
+.Bd -literal -offset 4n
+$ sudo -u yaz ls ~yaz
+.Ed
+.Pp
+To edit the
+.Pa index.html
+file as user www:
+.Bd -literal -offset 4n
+$ sudoedit -u www ~www/htdocs/index.html
+.Ed
+.Pp
+To view system logs only accessible to root and users in the adm
+group:
+.Bd -literal -offset 4n
+$ sudo -g adm more @log_dir@/syslog
+.Ed
+.Pp
+To run an editor as jim with a different primary group:
+.Bd -literal -offset 4n
+$ sudoedit -u jim -g audio ~jim/sound.txt
+.Ed
+.Pp
+To shut down a machine:
+.Bd -literal -offset 4n
+$ sudo shutdown -r +15 "quick reboot"
+.Ed
+.Pp
+To make a usage listing of the directories in the /home partition.
+The
+.Ar commands
+are run in a sub-shell to allow the
+.Ql cd
+command and file redirection to work.
+.Bd -literal -offset 4n
+$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"
+.Ed
+.Sh DIAGNOSTICS
+Error messages produced by
+.Nm
+include:
+.Bl -tag -width 4n
+.It Li editing files in a writable directory is not permitted
+By default,
+.Nm sudoedit
+does not permit editing a file when any of the parent directories are writable
+by the invoking user.
+This avoids a race condition that could allow the user to overwrite
+an arbitrary file.
+See the
+.Em sudoedit_checkdir
+option in
+.Xr sudoers @mansectform@
+for more information.
+.It Li editing symbolic links is not permitted
+By default,
+.Nm sudoedit
+does not follow symbolic links when opening files.
+See the
+.Em sudoedit_follow
+option in
+.Xr sudoers @mansectform@
+for more information.
+.It Li effective uid is not 0, is sudo installed setuid root?
+.Nm
+was not run with root privileges.
+The
+.Nm
+binary must be owned by the root user and have the set-user-ID bit set.
+Also, it must not be located on a file system mounted with the
+.Sq nosuid
+option or on an NFS file system that maps uid 0 to an unprivileged uid.
+.It Li effective uid is not 0, is sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?
+.Nm
+was not run with root privileges.
+The
+.Nm
+binary has the proper owner and permissions but it still did not run
+with root privileges.
+The most common reason for this is that the file system the
+.Nm
+binary is located on is mounted with the
+.Sq nosuid
+option or it is an NFS file system that maps uid 0 to an unprivileged uid.
+.It Li fatal error, unable to load plugins
+An error occurred while loading or initializing the plugins specified in
+.Xr sudo.conf @mansectform@ .
+.It Li invalid environment variable name
+One or more environment variable names specified via the
+.Fl E
+option contained an equal sign
+.Pq Ql = .
+The arguments to the
+.Fl E
+option should be environment variable names without an associated value.
+.It Li no password was provided
+When
+.Nm
+tried to read the password, it did not receive any characters.
+This may happen if no terminal is available (or the
+.Fl S
+option is specified) and the standard input has been redirected from
+.Pa /dev/null .
+.It Li a terminal is required to read the password
+.Nm
+needs to read the password but there is no mechanism available for it
+to do so.
+A terminal is not present to read the password from,
+.Nm
+has not been configured to read from the standard input,
+the
+.Fl S
+option was not used, and no askpass helper has been specified either via the
+.Xr sudo.conf @mansectform@
+file or the
+.Ev SUDO_ASKPASS
+environment variable.
+.It Li no writable temporary directory found
+.Nm sudoedit
+was unable to find a usable temporary directory in which to store its
+intermediate files.
+.It Li The Do "no new privileges" Dc "flag is set, which prevents sudo from running as root."
+.Nm
+was run by a process that has the Linux
+.Dq no new privileges
+flag is set.
+This causes the set-user-ID bit to be ignored when running an executable,
+which will prevent
+.Nm
+from functioning.
+The most likely cause for this is running
+.Nm
+within a container that sets this flag.
+Check the documentation to see if it is possible to configure the
+container such that the flag is not set.
+.It Li sudo must be owned by uid 0 and have the setuid bit set
+.Nm
+was not run with root privileges.
+The
+.Nm
+binary does not have the correct owner or permissions.
+It must be owned by the root user and have the set-user-ID bit set.
+.It Li sudoedit is not supported on this platform
+It is only possible to run
+.Nm sudoedit
+on systems that support setting the effective user-ID.
+.It Li timed out reading password
+The user did not enter a password before the password timeout
+(5 minutes by default) expired.
+.It Li you do not exist in the passwd database
+Your user-ID does not appear in the system passwd database.
+.It Li you may not specify environment variables in edit mode
+It is only possible to specify environment variables when running a
+.Ar command .
+When editing a file, the editor is run with the user's environment unmodified.
+.El
+.Sh SEE ALSO
+.Xr su 1 ,
+.Xr stat 2 ,
+.Xr login_cap 3 ,
+.Xr passwd @mansectform@ ,
+.Xr sudo.conf @mansectform@ ,
+.Xr sudo_plugin @mansectform@ ,
+.Xr sudoers @mansectform@ ,
+.Xr sudoers_timestamp @mansectform@ ,
+.Xr sudoreplay @mansectsu@ ,
+.Xr visudo @mansectsu@
+.Sh HISTORY
+See the HISTORY.md file in the
+.Nm
+distribution (https://www.sudo.ws/about/history/) for a brief
+history of sudo.
+.Sh AUTHORS
+Many people have worked on
+.Nm
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS.md file in the
+.Nm
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+.Nm .
+.Sh CAVEATS
+There is no easy way to prevent a user from gaining a root shell
+if that user is allowed to run arbitrary
+.Ar commands
+via
+.Nm .
+Also, many programs (such as editors) allow the user to run
+.Ar command Ns s
+via shell escapes, thus avoiding
+.Nm sudo Ns 's
+checks.
+However, on most systems it is possible to prevent shell escapes with the
+.Xr sudoers @mansectform@
+plugin's
+.Em noexec
+functionality.
+.Pp
+It is not meaningful to run the
+.Ql cd
+.Ar command
+directly via sudo, e.g.,
+.Bd -literal -offset 4n
+$ sudo cd /usr/local/protected
+.Ed
+.Pp
+since when the
+.Ar command
+exits the parent process (your shell) will still be the same.
+The
+.Fl D
+option can be used to run a
+.Ar command
+in a specific
+.Ar directory .
+.Pp
+Running shell scripts via
+.Nm
+can expose the same kernel bugs that make set-user-ID shell scripts
+unsafe on some operating systems (if your OS has a /dev/fd/ directory,
+set-user-ID shell scripts are generally safe).
+.Sh BUGS
+If you believe you have found a bug in
+.Nm ,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+.Nm
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudo_logsrv.proto.man.in b/docs/sudo_logsrv.proto.man.in
new file mode 100644
index 0000000..fadb8b6
--- /dev/null
+++ b/docs/sudo_logsrv.proto.man.in
@@ -0,0 +1,911 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.TH "SUDO_LOGSRV.PROTO" "@mansectform@" "September 13, 2022" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudo_logsrv.proto\fR
+\- Sudo log server protocol
+.SH "DESCRIPTION"
+Starting with version 1.9.0,
+\fBsudo\fR
+supports sending event and I/O logs to a log server.
+The protocol used is written in Google's Protocol Buffers domain
+specific language.
+The
+\fIEXAMPLES\fR
+section includes a complete description of the protocol in Protocol
+Buffers format.
+.PP
+Because there is no way to determine message boundaries when using
+Protocol Buffers, the wire size of each message is sent immediately
+preceding the message itself as a 32-bit unsigned integer in network
+byte order.
+This is referred to as
+\(lqlength-prefix framing\(rq
+and is how Google suggests handling the lack of message delimiters.
+.PP
+The protocol is made up of two basic messages,
+\fIClientMessage\fR
+and
+\fIServerMessage\fR,
+described below.
+The server must accept messages up to two megabytes in size.
+The server may return an error if the client tries to send a message
+larger than two megabytes.
+.SH "Client Messages"
+A
+\fIClientMessage\fR
+is a container used to encapsulate all the possible message types
+a client may send to the server.
+.nf
+.sp
+.RS 0n
+message ClientMessage {
+ oneof type {
+ AcceptMessage accept_msg = 1;
+ RejectMessage reject_msg = 2;
+ ExitMessage exit_msg = 3;
+ RestartMessage restart_msg = 4;
+ AlertMessage alert_msg = 5;
+ IoBuffer ttyin_buf = 6;
+ IoBuffer ttyout_buf = 7;
+ IoBuffer stdin_buf = 8;
+ IoBuffer stdout_buf = 9;
+ IoBuffer stderr_buf = 10;
+ ChangeWindowSize winsize_event = 11;
+ CommandSuspend suspend_event = 12;
+ ClientHello hello_msg = 13;
+ }
+}
+.RE
+.fi
+.PP
+The different
+\fIClientMessage\fR
+sub-messages the client may sent to the server are described below.
+.SS "TimeSpec"
+.nf
+.RS 0n
+message TimeSpec {
+ int64 tv_sec = 1;
+ int32 tv_nsec = 2;
+}
+.RE
+.fi
+.PP
+A
+\fITimeSpec\fR
+is the equivalent of a POSIX
+\fIstruct timespec\fR,
+containing seconds and nanoseconds members.
+The
+\fItv_sec\fR
+member is a 64-bit integer to support dates after the year 2038.
+.SS "InfoMessage"
+.nf
+.RS 0n
+message InfoMessage {
+ message StringList {
+ repeated string strings = 1;
+ }
+ message NumberList {
+ repeated int64 numbers = 1;
+ }
+ string key = 1;
+ oneof value {
+ int64 numval = 2;
+ string strval = 3;
+ StringList strlistval = 4;
+ NumberList numlistval = 5;
+ }
+}
+.RE
+.fi
+.PP
+An
+\fIInfoMessage\fR
+is used to represent information about the invoking user as well as the
+execution environment the command runs in the form of key-value pairs.
+The key is always a string but the value may be a 64-bit integer,
+a string, an array of strings, or an array of 64-bit integers.
+The event log data is composed of
+\fIInfoMessage\fR
+entries.
+See the
+\fIEVENT LOG VARIABLES\fR
+section for more information.
+.SS "ClientHello hello_msg"
+.nf
+.RS 0n
+message ClientHello {
+ string client_id = 1;
+}
+.RE
+.fi
+.PP
+A
+\fIClientHello\fR
+message consists of client information that may be sent to the
+server when the client first connects.
+.TP 8n
+client_id
+A free-form client description.
+This usually includes the name and version of the client implementation.
+.SS "AcceptMessage accept_msg"
+.nf
+.RS 0n
+message AcceptMessage {
+ TimeSpec submit_time = 1;
+ repeated InfoMessage info_msgs = 2;
+ bool expect_iobufs = 3;
+}
+.RE
+.fi
+.PP
+An
+\fIAcceptMessage\fR
+is sent by the client when a command is allowed by the security policy.
+It contains the following members:
+.TP 8n
+submit_time
+The wall clock time when the command was submitted to the security policy.
+.TP 8n
+info_msgs
+An array of
+\fIInfoMessage\fR
+describing the user who submitted the command as well as the execution
+environment of the command.
+This information is used to generate an event log entry and may also be
+used by server to determine where and how the I/O log is stored.
+.TP 8n
+expect_iobufs
+Set to true if the server should expect
+\fIIoBuffer\fR
+messages to follow (for I/O logging) or false if the server should only
+store the event log.
+.PP
+If an
+\fIAcceptMessage\fR
+is sent, the client must not send a
+\fIRejectMessage\fR
+or
+\fIRestartMessage\fR.
+.SS "RejectMessage reject_msg"
+.nf
+.RS 0n
+message RejectMessage {
+ TimeSpec submit_time = 1;
+ string reason = 2;
+ repeated InfoMessage info_msgs = 3;
+}
+.RE
+.fi
+.PP
+A
+\fIRejectMessage\fR
+is sent by the client when a command is denied by the security policy.
+It contains the following members:
+.TP 8n
+submit_time
+The wall clock time when the command was submitted to the security policy.
+.TP 8n
+reason
+The reason the security policy gave for denying the command.
+.TP 8n
+info_msgs
+An array of
+\fIInfoMessage\fR
+describing the user who submitted the command as well as the execution
+environment of the command.
+This information is used to generate an event log entry.
+.PP
+If a
+\fIRejectMessage\fR
+is sent, the client must not send an
+\fIAcceptMessage\fR
+or
+\fIRestartMessage\fR.
+.SS "ExitMessage exit_msg"
+.nf
+.RS 0n
+message ExitMessage {
+ TimeSpec run_time = 1;
+ int32 exit_value = 2;
+ bool dumped_core = 3;
+ string signal = 4;
+ string error = 5;
+}
+.PP
+.RE
+.fi
+An
+\fIExitMessage\fR
+is sent by the client after the command has exited or has been
+terminated by a signal.
+It contains the following members:
+.TP 8n
+run_time
+The total amount of elapsed time since the command started,
+calculated using a monotonic clock where possible.
+This is not the wall clock time.
+.TP 8n
+exit_value
+The command's exit value in the range 0-255.
+.TP 8n
+dumped_core
+True if the command was terminated by a signal and dumped core.
+.TP 8n
+signal
+If the command was terminated by a signal, this is set to the
+name of the signal without the leading
+\(lqSIG\(rq.
+For example,
+\fRINT\fR,
+\fRTERM\fR,
+\fRKILL\fR,
+\fRSEGV\fR.
+.TP 8n
+error
+A message from the client indicating that the command was terminated
+unexpectedly due to an error.
+.PP
+When performing I/O logging, the client should wait for a
+\fIcommit_point\fR
+corresponding to the final
+\fIIoBuffer\fR
+before closing the connection unless the final
+\fIcommit_point\fR
+has already been received.
+.SS "RestartMessage restart_msg"
+.nf
+.RS 0n
+message RestartMessage {
+ string log_id = 1;
+ TimeSpec resume_point = 2;
+}
+.RE
+.fi
+.PP
+A
+\fIRestartMessage\fR
+is sent by the client to resume sending an existing I/O log that
+was previously interrupted.
+It contains the following members:
+.TP 8n
+log_id
+The the server-side name for an I/O log that was previously
+sent to the client by the server.
+This may be a path name on the server or some other kind of server-side
+identifier.
+.TP 8n
+resume_point
+The point in time after which to resume the I/O log.
+This is in the form of a
+\fITimeSpec\fR
+representing the amount of time since the command started, not
+the wall clock time.
+The
+\fIresume_point\fR
+should correspond to a
+\fIcommit_point\fR
+previously sent to the client by the server.
+If the server receives a
+\fIRestartMessage\fR
+containing a
+\fIresume_point\fR
+it has not previously seen, an error will be returned to the client
+and the connection will be dropped.
+.PP
+If a
+\fIRestartMessage\fR
+is sent, the client must not send an
+\fIAcceptMessage\fR
+or
+\fIRejectMessage\fR.
+.SS "AlertMessage alert_msg"
+.nf
+.RS 0n
+message AlertMessage {
+ TimeSpec alert_time = 1;
+ string reason = 2;
+ repeated InfoMessage info_msgs = 3;
+}
+.RE
+.fi
+.PP
+An
+\fIAlertMessage\fR
+is sent by the client to indicate a problem detected by the security
+policy while the command is running that should be stored in the event log.
+It contains the following members:
+.TP 8n
+alert_time
+The wall clock time when the alert occurred.
+.TP 8n
+reason
+The reason for the alert.
+.TP 8n
+info_msgs
+An optional array of
+\fIInfoMessage\fR
+describing the user who submitted the command as well as the execution
+environment of the command.
+This information is used to generate an event log entry.
+.SS "IoBuffer ttyin_buf | ttyout_buf | stdin_buf | stdout_buf | stderr_buf"
+.nf
+.RS 0n
+message IoBuffer {
+ TimeSpec delay = 1;
+ bytes data = 2;
+}
+.RE
+.fi
+.PP
+An
+\fIIoBuffer\fR
+is used to represent data from terminal input, terminal
+output, standard input, standard output, or standard error.
+It contains the following members:
+.TP 8n
+delay
+The elapsed time since the last record in the form of a
+\fITimeSpec\fR.
+The
+\fIdelay\fR
+should be calculated using a monotonic clock where possible.
+.TP 8n
+data
+The binary I/O log data from terminal input, terminal output,
+standard input, standard output, or standard error.
+.SS "ChangeWindowSize winsize_event"
+.nf
+.RS 0n
+message ChangeWindowSize {
+ TimeSpec delay = 1;
+ int32 rows = 2;
+ int32 cols = 3;
+}
+.RE
+.fi
+.PP
+A
+\fIChangeWindowSize\fR
+message is sent by the client when the terminal running the command
+changes size.
+It contains the following members:
+.TP 8n
+delay
+The elapsed time since the last record in the form of a
+\fITimeSpec\fR.
+The
+\fIdelay\fR
+should be calculated using a monotonic clock where possible.
+.TP 8n
+rows
+The new number of terminal rows.
+.TP 8n
+cols
+The new number of terminal columns.
+.SS "CommandSuspend suspend_event"
+.nf
+.RS 0n
+message CommandSuspend {
+ TimeSpec delay = 1;
+ string signal = 2;
+}
+.RE
+.fi
+.PP
+A
+\fICommandSuspend\fR
+message is sent by the client when the command is either suspended
+or resumed.
+It contains the following members:
+.TP 8n
+delay
+The elapsed time since the last record in the form of a
+\fITimeSpec\fR.
+The
+\fIdelay\fR
+should be calculated using a monotonic clock where possible.
+.TP 8n
+signal
+The signal name without the leading
+\(lqSIG\(rq.
+For example,
+\fRSTOP\fR,
+\fRTSTP\fR,
+\fRCONT\fR.
+.SH "Server Messages"
+A
+\fIServerMessage\fR
+is a container used to encapsulate all the possible message types
+the server may send to a client.
+.nf
+.sp
+.RS 0n
+message ServerMessage {
+ oneof type {
+ ServerHello hello = 1;
+ TimeSpec commit_point = 2;
+ string log_id = 3;
+ string error = 4;
+ string abort = 5;
+ }
+}
+.RE
+.fi
+.PP
+The different
+\fIServerMessage\fR
+sub-messages the server may sent to the client are described below.
+.SS "ServerHello hello"
+.nf
+.RS 0n
+message ServerHello {
+ string server_id = 1;
+ string redirect = 2;
+ repeated string servers = 3;
+ bool subcommands = 4;
+}
+.RE
+.fi
+.PP
+The
+\fIServerHello\fR
+message consists of server information sent when the client first connects.
+It contains the following members:
+.TP 8n
+server_id
+A free-form server description.
+Usually this includes the name and version of the implementation
+running on the log server.
+This member is always present.
+.TP 8n
+redirect
+A host and port separated by a colon
+(\(oq\(cq):
+that the client should connect to instead.
+The host may be a host name, an IPv4 address, or an IPv6 address
+in square brackets.
+This may be used for server load balancing.
+The server will disconnect after sending the
+\fIServerHello\fR
+when it includes a
+\fBredirect\fR.
+.TP 8n
+servers
+.br
+A list of other known log servers.
+This can be used to implement log server redundancy and allows the
+client to discover all other log servers simply by connecting to
+one known server.
+This member may be omitted when there is only a single log server.
+.TP 8n
+subcommands
+If set, the server supports logging additional commands during a session.
+The client may send an
+\fIAcceptMessage\fR
+or
+\fIRejectMessage\fR
+when
+\fBsudo\fR
+is running in
+\fIintercept\fR
+mode.
+In this mode, commands spawned from the initial command authorized by
+\fBsudo\fR
+are subject to policy restrictions and/or are logged.
+If
+\fIsubcommands\fR
+is false, the client must not attempt to log additional commands.
+.SS "TimeSpec commit_point"
+A periodic time stamp sent by the server to indicate when I/O log
+buffers have been committed to storage.
+This message is not sent after every
+\fIIoBuffer\fR
+but rather at a server-configurable interval.
+When the server receives an
+\fIExitMessage\fR,
+it will respond with a
+\fIcommit_point\fR
+corresponding to the last received
+\fIIoBuffer\fR
+before closing the connection.
+.SS "string log_id"
+The server-side ID of the I/O log being stored, sent in response
+to an
+\fIAcceptMessage\fR
+where
+\fIexpect_iobufs\fR
+is true.
+.SS "string error"
+A fatal server-side error.
+The server will close the connection after sending the
+\fIerror\fR
+message.
+.SS "string abort"
+An
+\fIabort\fR
+message from the server indicates that the client should kill the
+command and terminate the session.
+It may be used to implement simple server-side policy.
+The server will close the connection after sending the
+\fIabort\fR
+message.
+.SH "Protocol flow of control"
+The expected protocol flow is as follows:
+.TP 5n
+1.\&
+Client connects to the first available server.
+If the client is configured to use TLS, a TLS handshake will be
+attempted.
+.TP 5n
+2.\&
+Client sends
+\fIClientHello\fR.
+This is currently optional but allows the server to detect a
+non-TLS connection on the TLS port.
+.TP 5n
+3.\&
+Server sends
+\fIServerHello\fR.
+.TP 5n
+4.\&
+Client responds with either
+\fIAcceptMessage\fR,
+\fIRejectMessage\fR,
+or
+\fIRestartMessage\fR.
+.TP 5n
+5.\&
+If client sent a
+\fIAcceptMessage\fR
+with
+\fIexpect_iobufs\fR
+set, server creates a new I/O log and responds with a
+\fIlog_id\fR.
+.TP 5n
+6.\&
+Client sends zero or more
+\fIIoBuffer\fR
+messages.
+.TP 5n
+7.\&
+Server periodically responds to
+\fIIoBuffer\fR
+messages with a
+\fIcommit_point\fR.
+.TP 5n
+8.\&
+Client sends an
+\fIExitMessage\fR
+when the command exits or is killed.
+.TP 5n
+9.\&
+Server sends the final
+\fIcommit_point\fR
+if one is pending.
+.TP 5n
+10.\&
+Server closes the connection.
+After receiving the final
+\fIcommit_point\fR,
+the client shuts down its side of the TLS connection if TLS
+is in use, and closes the connection.
+.TP 5n
+11.\&
+Server shuts down its side of the TLS connection if TLS is in use,
+and closes the connection.
+.PP
+At any point, the server may send an
+\fIerror\fR
+or
+\fIabort\fR
+message to the client at which point the server will close the
+connection.
+If an
+\fIabort\fR
+message is received, the client should terminate the running command.
+.SH "EVENT LOG VARIABLES"
+\fIAcceptMessage\fR,
+\fIAlertMessage\fR
+and
+\fIRejectMessage\fR
+classes contain an array of
+\fIInfoMessage\fR
+that should contain information about the user who submitted the command
+as well as information about the execution environment of the command
+if it was accepted.
+.PP
+Some variables have a
+\fIclient\fR,
+\fIrun\fR,
+or
+\fIsubmit\fR
+prefix.
+These prefixes are used to eliminate ambiguity for variables that
+could apply to the client program, the user submitting the command,
+or the command being run.
+Variables with a
+\fIclient\fR
+prefix pertain to the program performing the connection to the log
+server, for example
+\fBsudo\fR.
+Variables with a
+\fIrun\fR
+prefix pertain to the command that the user requested be run.
+Variables with a
+\fIsubmit\fR
+prefix pertain to the user submitting the request
+(the user running \fBsudo\fR).
+.PP
+The following
+\fIInfoMessage\fR
+entries are required:
+.TS
+l l l.
+.PP
+\fBKey\fR \fBType\fR \fBDescription\fR
+.PP
+command string command that was submitted
+.PP
+runuser string name of user the command was run as
+.PP
+submithost string name of host the command was submitted on
+.PP
+submituser string name of user submitting the command
+.TE
+.PP
+The following
+\fIInfoMessage\fR
+entries are recognized, but not required:
+.TS
+l l l.
+.PP
+\fBKey\fR \fBType\fR \fBDescription\fR
+.PP
+clientargv StringList client's original argument vector
+.PP
+clientpid int64 client's process ID
+.PP
+clientppid int64 client's parent process ID
+.PP
+clientsid int64 client's terminal session ID
+.PP
+columns int64 number of columns in the terminal
+.PP
+lines int64 number of lines in the terminal
+.PP
+runargv StringList argument vector of command to run
+.PP
+runchroot string root directory of command to run
+.PP
+runcwd string running command's working directory
+.PP
+runenv StringList the running command's environment
+.PP
+rungid int64 primary group-ID of the command
+.PP
+rungids NumberList supplementary group-IDs for the command
+.PP
+rungroup string primary group name of the command
+.PP
+rungroups StringList supplementary group names for the command
+.PP
+runuid int64 run user's user-ID
+.PP
+submitcwd string submit user's current working directory
+.PP
+submitenv StringList the submit user's environment
+.PP
+submitgid int64 submit user's primary group-ID
+.PP
+submitgids NumberList submit user's supplementary group-IDs
+.PP
+submitgroup string submitting user's primary group name
+.PP
+submitgroups StringList submit user's supplementary group names
+.PP
+submituid int64 submit user's user-ID
+.PP
+ttyname string the terminal the command was submitted from
+.TE
+.PP
+The server must accept other variables not listed above but may
+ignore them.
+.SH "EXAMPLES"
+The Protocol Buffers description of the log server protocol, using
+\(lqproto3\(rq
+syntax, is included in full below.
+.nf
+.sp
+.RS 0n
+syntax = "proto3";
+
+/*
+ * Client message to the server. Messages on the wire are
+ * prefixed with a 32-bit size in network byte order.
+ */
+message ClientMessage {
+ oneof type {
+ AcceptMessage accept_msg = 1;
+ RejectMessage reject_msg = 2;
+ ExitMessage exit_msg = 3;
+ RestartMessage restart_msg = 4;
+ AlertMessage alert_msg = 5;
+ IoBuffer ttyin_buf = 6;
+ IoBuffer ttyout_buf = 7;
+ IoBuffer stdin_buf = 8;
+ IoBuffer stdout_buf = 9;
+ IoBuffer stderr_buf = 10;
+ ChangeWindowSize winsize_event = 11;
+ CommandSuspend suspend_event = 12;
+ }
+}
+
+/* Equivalent of POSIX struct timespec */
+message TimeSpec {
+ int64 tv_sec = 1; /* seconds */
+ int32 tv_nsec = 2; /* nanoseconds */
+}
+
+/* I/O buffer with keystroke data */
+message IoBuffer {
+ TimeSpec delay = 1; /* elapsed time since last record */
+ bytes data = 2; /* keystroke data */
+}
+
+/*
+ * Key/value pairs, like Privilege Manager struct info.
+ * The value may be a number, a string, or a list of strings.
+ */
+message InfoMessage {
+ message StringList {
+ repeated string strings = 1;
+ }
+ message NumberList {
+ repeated int64 numbers = 1;
+ }
+ string key = 1;
+ oneof value {
+ int64 numval = 2;
+ string strval = 3;
+ StringList strlistval = 4;
+ NumberList numlistval = 5;
+ }
+}
+
+/*
+ * Event log data for command accepted by the policy.
+ */
+message AcceptMessage {
+ TimeSpec submit_time = 1; /* when command was submitted */
+ repeated InfoMessage info_msgs = 2; /* key,value event log data */
+ bool expect_iobufs = 3; /* true if I/O logging enabled */
+}
+
+/*
+ * Event log data for command rejected by the policy.
+ */
+message RejectMessage {
+ TimeSpec submit_time = 1; /* when command was submitted */
+ string reason = 2; /* reason command was rejected */
+ repeated InfoMessage info_msgs = 3; /* key,value event log data */
+}
+
+/* Message sent by client when command exits. */
+/* Might revisit runtime and use end_time instead */
+message ExitMessage {
+ TimeSpec run_time = 1; /* total elapsed run time */
+ int32 exit_value = 2; /* 0-255 */
+ bool dumped_core = 3; /* true if command dumped core */
+ string signal = 4; /* signal name if killed by signal */
+ string error = 5; /* if killed due to other error */
+}
+
+/* Alert message, policy module-specific. */
+message AlertMessage {
+ TimeSpec alert_time = 1; /* time alert message occurred */
+ string reason = 2; /* policy alert error string */
+ repeated InfoMessage info_msgs = 3; /* key,value event log data */
+}
+
+/* Used to restart an existing I/O log on the server. */
+message RestartMessage {
+ string log_id = 1; /* ID of log being restarted */
+ TimeSpec resume_point = 2; /* resume point (elapsed time) */
+}
+
+/* Window size change event. */
+message ChangeWindowSize {
+ TimeSpec delay = 1; /* elapsed time since last record */
+ int32 rows = 2; /* new number of rows */
+ int32 cols = 3; /* new number of columns */
+}
+
+/* Command suspend/resume event. */
+message CommandSuspend {
+ TimeSpec delay = 1; /* elapsed time since last record */
+ string signal = 2; /* signal that caused suspend/resume */
+}
+
+/*
+ * Server messages to the client. Messages on the wire are
+ * prefixed with a 32-bit size in network byte order.
+ */
+message ServerMessage {
+ oneof type {
+ ServerHello hello = 1; /* server hello message */
+ TimeSpec commit_point = 2; /* cumulative time of records stored */
+ string log_id = 3; /* ID of server-side I/O log */
+ string error = 4; /* error message from server */
+ string abort = 5; /* abort message, kill command */
+ }
+}
+
+/* Hello message from server when client connects. */
+message ServerHello {
+ string server_id = 1; /* free-form server description */
+ string redirect = 2; /* optional redirect if busy */
+ repeated string servers = 3; /* optional list of known servers */
+}
+.RE
+.fi
+.SH "SEE ALSO"
+sudo_logsrvd.conf(@mansectform@),
+sudoers(@mansectform@),
+sudo(8),
+sudo_logsrvd(8)
+.PP
+\fIProtocol Buffers\fR,
+https://developers.google.com/protocol-buffers/.
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS.md file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you believe you have found a bug in
+\fBsudo\fR,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudo_logsrv.proto.mdoc.in b/docs/sudo_logsrv.proto.mdoc.in
new file mode 100644
index 0000000..daa4a55
--- /dev/null
+++ b/docs/sudo_logsrv.proto.mdoc.in
@@ -0,0 +1,828 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd September 13, 2022
+.Dt SUDO_LOGSRV.PROTO @mansectform@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudo_logsrv.proto
+.Nd Sudo log server protocol
+.Sh DESCRIPTION
+Starting with version 1.9.0,
+.Nm sudo
+supports sending event and I/O logs to a log server.
+The protocol used is written in Google's Protocol Buffers domain
+specific language.
+The
+.Sx EXAMPLES
+section includes a complete description of the protocol in Protocol
+Buffers format.
+.Pp
+Because there is no way to determine message boundaries when using
+Protocol Buffers, the wire size of each message is sent immediately
+preceding the message itself as a 32-bit unsigned integer in network
+byte order.
+This is referred to as
+.Dq length-prefix framing
+and is how Google suggests handling the lack of message delimiters.
+.Pp
+The protocol is made up of two basic messages,
+.Em ClientMessage
+and
+.Em ServerMessage ,
+described below.
+The server must accept messages up to two megabytes in size.
+The server may return an error if the client tries to send a message
+larger than two megabytes.
+.Sh Client Messages
+A
+.Em ClientMessage
+is a container used to encapsulate all the possible message types
+a client may send to the server.
+.Bd -literal
+message ClientMessage {
+ oneof type {
+ AcceptMessage accept_msg = 1;
+ RejectMessage reject_msg = 2;
+ ExitMessage exit_msg = 3;
+ RestartMessage restart_msg = 4;
+ AlertMessage alert_msg = 5;
+ IoBuffer ttyin_buf = 6;
+ IoBuffer ttyout_buf = 7;
+ IoBuffer stdin_buf = 8;
+ IoBuffer stdout_buf = 9;
+ IoBuffer stderr_buf = 10;
+ ChangeWindowSize winsize_event = 11;
+ CommandSuspend suspend_event = 12;
+ ClientHello hello_msg = 13;
+ }
+}
+.Ed
+.Pp
+The different
+.Em ClientMessage
+sub-messages the client may sent to the server are described below.
+.Ss TimeSpec
+.Bd -literal
+message TimeSpec {
+ int64 tv_sec = 1;
+ int32 tv_nsec = 2;
+}
+.Ed
+.Pp
+A
+.Em TimeSpec
+is the equivalent of a POSIX
+.Vt struct timespec ,
+containing seconds and nanoseconds members.
+The
+.Em tv_sec
+member is a 64-bit integer to support dates after the year 2038.
+.Ss InfoMessage
+.Bd -literal
+message InfoMessage {
+ message StringList {
+ repeated string strings = 1;
+ }
+ message NumberList {
+ repeated int64 numbers = 1;
+ }
+ string key = 1;
+ oneof value {
+ int64 numval = 2;
+ string strval = 3;
+ StringList strlistval = 4;
+ NumberList numlistval = 5;
+ }
+}
+.Ed
+.Pp
+An
+.Em InfoMessage
+is used to represent information about the invoking user as well as the
+execution environment the command runs in the form of key-value pairs.
+The key is always a string but the value may be a 64-bit integer,
+a string, an array of strings, or an array of 64-bit integers.
+The event log data is composed of
+.Em InfoMessage
+entries.
+See the
+.Sx EVENT LOG VARIABLES
+section for more information.
+.Ss ClientHello hello_msg
+.Bd -literal
+message ClientHello {
+ string client_id = 1;
+}
+.Ed
+.Pp
+A
+.Em ClientHello
+message consists of client information that may be sent to the
+server when the client first connects.
+.Bl -tag -width Ds
+.It client_id
+A free-form client description.
+This usually includes the name and version of the client implementation.
+.El
+.Ss AcceptMessage accept_msg
+.Bd -literal
+message AcceptMessage {
+ TimeSpec submit_time = 1;
+ repeated InfoMessage info_msgs = 2;
+ bool expect_iobufs = 3;
+}
+.Ed
+.Pp
+An
+.Em AcceptMessage
+is sent by the client when a command is allowed by the security policy.
+It contains the following members:
+.Bl -tag -width Ds
+.It submit_time
+The wall clock time when the command was submitted to the security policy.
+.It info_msgs
+An array of
+.Em InfoMessage
+describing the user who submitted the command as well as the execution
+environment of the command.
+This information is used to generate an event log entry and may also be
+used by server to determine where and how the I/O log is stored.
+.It expect_iobufs
+Set to true if the server should expect
+.Em IoBuffer
+messages to follow (for I/O logging) or false if the server should only
+store the event log.
+.El
+.Pp
+If an
+.Em AcceptMessage
+is sent, the client must not send a
+.Em RejectMessage
+or
+.Em RestartMessage .
+.Ss RejectMessage reject_msg
+.Bd -literal
+message RejectMessage {
+ TimeSpec submit_time = 1;
+ string reason = 2;
+ repeated InfoMessage info_msgs = 3;
+}
+.Ed
+.Pp
+A
+.Em RejectMessage
+is sent by the client when a command is denied by the security policy.
+It contains the following members:
+.Bl -tag -width Ds
+.It submit_time
+The wall clock time when the command was submitted to the security policy.
+.It reason
+The reason the security policy gave for denying the command.
+.It info_msgs
+An array of
+.Em InfoMessage
+describing the user who submitted the command as well as the execution
+environment of the command.
+This information is used to generate an event log entry.
+.El
+.Pp
+If a
+.Em RejectMessage
+is sent, the client must not send an
+.Em AcceptMessage
+or
+.Em RestartMessage .
+.Ss ExitMessage exit_msg
+.Bd -literal
+message ExitMessage {
+ TimeSpec run_time = 1;
+ int32 exit_value = 2;
+ bool dumped_core = 3;
+ string signal = 4;
+ string error = 5;
+}
+.Pp
+.Ed
+An
+.Em ExitMessage
+is sent by the client after the command has exited or has been
+terminated by a signal.
+It contains the following members:
+.Bl -tag -width Ds
+.It run_time
+The total amount of elapsed time since the command started,
+calculated using a monotonic clock where possible.
+This is not the wall clock time.
+.It exit_value
+The command's exit value in the range 0-255.
+.It dumped_core
+True if the command was terminated by a signal and dumped core.
+.It signal
+If the command was terminated by a signal, this is set to the
+name of the signal without the leading
+.Dq SIG .
+For example,
+.Dv INT ,
+.Dv TERM ,
+.Dv KILL ,
+.Dv SEGV .
+.It error
+A message from the client indicating that the command was terminated
+unexpectedly due to an error.
+.El
+.Pp
+When performing I/O logging, the client should wait for a
+.Em commit_point
+corresponding to the final
+.Em IoBuffer
+before closing the connection unless the final
+.Em commit_point
+has already been received.
+.Ss RestartMessage restart_msg
+.Bd -literal
+message RestartMessage {
+ string log_id = 1;
+ TimeSpec resume_point = 2;
+}
+.Ed
+.Pp
+A
+.Em RestartMessage
+is sent by the client to resume sending an existing I/O log that
+was previously interrupted.
+It contains the following members:
+.Bl -tag -width Ds
+.It log_id
+The the server-side name for an I/O log that was previously
+sent to the client by the server.
+This may be a path name on the server or some other kind of server-side
+identifier.
+.It resume_point
+The point in time after which to resume the I/O log.
+This is in the form of a
+.Em TimeSpec
+representing the amount of time since the command started, not
+the wall clock time.
+The
+.Em resume_point
+should correspond to a
+.Em commit_point
+previously sent to the client by the server.
+If the server receives a
+.Em RestartMessage
+containing a
+.Em resume_point
+it has not previously seen, an error will be returned to the client
+and the connection will be dropped.
+.El
+.Pp
+If a
+.Em RestartMessage
+is sent, the client must not send an
+.Em AcceptMessage
+or
+.Em RejectMessage .
+.Ss AlertMessage alert_msg
+.Bd -literal
+message AlertMessage {
+ TimeSpec alert_time = 1;
+ string reason = 2;
+ repeated InfoMessage info_msgs = 3;
+}
+.Ed
+.Pp
+An
+.Em AlertMessage
+is sent by the client to indicate a problem detected by the security
+policy while the command is running that should be stored in the event log.
+It contains the following members:
+.Bl -tag -width Ds
+.It alert_time
+The wall clock time when the alert occurred.
+.It reason
+The reason for the alert.
+.It info_msgs
+An optional array of
+.Em InfoMessage
+describing the user who submitted the command as well as the execution
+environment of the command.
+This information is used to generate an event log entry.
+.El
+.Ss IoBuffer ttyin_buf | ttyout_buf | stdin_buf | stdout_buf | stderr_buf
+.Bd -literal
+message IoBuffer {
+ TimeSpec delay = 1;
+ bytes data = 2;
+}
+.Ed
+.Pp
+An
+.Em IoBuffer
+is used to represent data from terminal input, terminal
+output, standard input, standard output, or standard error.
+It contains the following members:
+.Bl -tag -width Ds
+.It delay
+The elapsed time since the last record in the form of a
+.Em TimeSpec .
+The
+.Em delay
+should be calculated using a monotonic clock where possible.
+.It data
+The binary I/O log data from terminal input, terminal output,
+standard input, standard output, or standard error.
+.El
+.Ss ChangeWindowSize winsize_event
+.Bd -literal
+message ChangeWindowSize {
+ TimeSpec delay = 1;
+ int32 rows = 2;
+ int32 cols = 3;
+}
+.Ed
+.Pp
+A
+.Em ChangeWindowSize
+message is sent by the client when the terminal running the command
+changes size.
+It contains the following members:
+.Bl -tag -width Ds
+.It delay
+The elapsed time since the last record in the form of a
+.Em TimeSpec .
+The
+.Em delay
+should be calculated using a monotonic clock where possible.
+.It rows
+The new number of terminal rows.
+.It cols
+The new number of terminal columns.
+.El
+.Ss CommandSuspend suspend_event
+.Bd -literal
+message CommandSuspend {
+ TimeSpec delay = 1;
+ string signal = 2;
+}
+.Ed
+.Pp
+A
+.Em CommandSuspend
+message is sent by the client when the command is either suspended
+or resumed.
+It contains the following members:
+.Bl -tag -width Ds
+.It delay
+The elapsed time since the last record in the form of a
+.Em TimeSpec .
+The
+.Em delay
+should be calculated using a monotonic clock where possible.
+.It signal
+The signal name without the leading
+.Dq SIG .
+For example,
+.Dv STOP ,
+.Dv TSTP ,
+.Dv CONT .
+.El
+.Sh Server Messages
+A
+.Em ServerMessage
+is a container used to encapsulate all the possible message types
+the server may send to a client.
+.Bd -literal
+message ServerMessage {
+ oneof type {
+ ServerHello hello = 1;
+ TimeSpec commit_point = 2;
+ string log_id = 3;
+ string error = 4;
+ string abort = 5;
+ }
+}
+.Ed
+.Pp
+The different
+.Em ServerMessage
+sub-messages the server may sent to the client are described below.
+.Ss ServerHello hello
+.Bd -literal
+message ServerHello {
+ string server_id = 1;
+ string redirect = 2;
+ repeated string servers = 3;
+ bool subcommands = 4;
+}
+.Ed
+.Pp
+The
+.Em ServerHello
+message consists of server information sent when the client first connects.
+It contains the following members:
+.Bl -tag -width Ds
+.It server_id
+A free-form server description.
+Usually this includes the name and version of the implementation
+running on the log server.
+This member is always present.
+.It redirect
+A host and port separated by a colon
+.Pq Ql :
+that the client should connect to instead.
+The host may be a host name, an IPv4 address, or an IPv6 address
+in square brackets.
+This may be used for server load balancing.
+The server will disconnect after sending the
+.Em ServerHello
+when it includes a
+.Sy redirect .
+.It servers
+A list of other known log servers.
+This can be used to implement log server redundancy and allows the
+client to discover all other log servers simply by connecting to
+one known server.
+This member may be omitted when there is only a single log server.
+.It subcommands
+If set, the server supports logging additional commands during a session.
+The client may send an
+.Em AcceptMessage
+or
+.Em RejectMessage
+when
+.Nm sudo
+is running in
+.Em intercept
+mode.
+In this mode, commands spawned from the initial command authorized by
+.Nm sudo
+are subject to policy restrictions and/or are logged.
+If
+.Em subcommands
+is false, the client must not attempt to log additional commands.
+.El
+.Ss TimeSpec commit_point
+A periodic time stamp sent by the server to indicate when I/O log
+buffers have been committed to storage.
+This message is not sent after every
+.Em IoBuffer
+but rather at a server-configurable interval.
+When the server receives an
+.Em ExitMessage ,
+it will respond with a
+.Em commit_point
+corresponding to the last received
+.Em IoBuffer
+before closing the connection.
+.Ss string log_id
+The server-side ID of the I/O log being stored, sent in response
+to an
+.Em AcceptMessage
+where
+.Em expect_iobufs
+is true.
+.Ss string error
+A fatal server-side error.
+The server will close the connection after sending the
+.Em error
+message.
+.Ss string abort
+An
+.Em abort
+message from the server indicates that the client should kill the
+command and terminate the session.
+It may be used to implement simple server-side policy.
+The server will close the connection after sending the
+.Em abort
+message.
+.Sh Protocol flow of control
+The expected protocol flow is as follows:
+.Bl -enum
+.It
+Client connects to the first available server.
+If the client is configured to use TLS, a TLS handshake will be
+attempted.
+.It
+Client sends
+.Em ClientHello .
+This is currently optional but allows the server to detect a
+non-TLS connection on the TLS port.
+.It
+Server sends
+.Em ServerHello .
+.It
+Client responds with either
+.Em AcceptMessage ,
+.Em RejectMessage ,
+or
+.Em RestartMessage .
+.It
+If client sent a
+.Em AcceptMessage
+with
+.Em expect_iobufs
+set, server creates a new I/O log and responds with a
+.Em log_id .
+.It
+Client sends zero or more
+.Em IoBuffer
+messages.
+.It
+Server periodically responds to
+.Em IoBuffer
+messages with a
+.Em commit_point .
+.It
+Client sends an
+.Em ExitMessage
+when the command exits or is killed.
+.It
+Server sends the final
+.Em commit_point
+if one is pending.
+.It
+Server closes the connection.
+After receiving the final
+.Em commit_point ,
+the client shuts down its side of the TLS connection if TLS
+is in use, and closes the connection.
+.It
+Server shuts down its side of the TLS connection if TLS is in use,
+and closes the connection.
+.El
+.Pp
+At any point, the server may send an
+.Em error
+or
+.Em abort
+message to the client at which point the server will close the
+connection.
+If an
+.Em abort
+message is received, the client should terminate the running command.
+.Sh EVENT LOG VARIABLES
+.Em AcceptMessage ,
+.Em AlertMessage
+and
+.Em RejectMessage
+classes contain an array of
+.Em InfoMessage
+that should contain information about the user who submitted the command
+as well as information about the execution environment of the command
+if it was accepted.
+.Pp
+Some variables have a
+.Em client ,
+.Em run ,
+or
+.Em submit
+prefix.
+These prefixes are used to eliminate ambiguity for variables that
+could apply to the client program, the user submitting the command,
+or the command being run.
+Variables with a
+.Em client
+prefix pertain to the program performing the connection to the log
+server, for example
+.Nm sudo .
+Variables with a
+.Em run
+prefix pertain to the command that the user requested be run.
+Variables with a
+.Em submit
+prefix pertain to the user submitting the request
+.Pq the user running Nm sudo .
+.Pp
+The following
+.Em InfoMessage
+entries are required:
+.Bl -column "submitgroup" "stringlist" "name of host the command was submitted on"
+.It Sy Key Ta Sy Type Ta Sy Description
+.It command Ta string Ta command that was submitted
+.It runuser Ta string Ta name of user the command was run as
+.It submithost Ta string Ta name of host the command was submitted on
+.It submituser Ta string Ta name of user submitting the command
+.El
+.Pp
+The following
+.Em InfoMessage
+entries are recognized, but not required:
+.Bl -column "submitgroup" "stringlist" "name of host the command was submitted on"
+.It Sy Key Ta Sy Type Ta Sy Description
+.It clientargv Ta StringList Ta client's original argument vector
+.It clientpid Ta int64 Ta client's process ID
+.It clientppid Ta int64 Ta client's parent process ID
+.It clientsid Ta int64 Ta client's terminal session ID
+.It columns Ta int64 Ta number of columns in the terminal
+.It lines Ta int64 Ta number of lines in the terminal
+.It runargv Ta StringList Ta argument vector of command to run
+.It runchroot Ta string Ta root directory of command to run
+.It runcwd Ta string Ta running command's working directory
+.It runenv Ta StringList Ta the running command's environment
+.It rungid Ta int64 Ta primary group-ID of the command
+.It rungids Ta NumberList Ta supplementary group-IDs for the command
+.It rungroup Ta string Ta primary group name of the command
+.It rungroups Ta StringList Ta supplementary group names for the command
+.It runuid Ta int64 Ta run user's user-ID
+.It submitcwd Ta string Ta submit user's current working directory
+.It submitenv Ta StringList Ta the submit user's environment
+.It submitgid Ta int64 Ta submit user's primary group-ID
+.It submitgids Ta NumberList Ta submit user's supplementary group-IDs
+.It submitgroup Ta string Ta submitting user's primary group name
+.It submitgroups Ta StringList Ta submit user's supplementary group names
+.It submituid Ta int64 Ta submit user's user-ID
+.It ttyname Ta string Ta the terminal the command was submitted from
+.El
+.Pp
+The server must accept other variables not listed above but may
+ignore them.
+.Sh EXAMPLES
+The Protocol Buffers description of the log server protocol, using
+.Dq proto3
+syntax, is included in full below.
+.Bd -literal
+syntax = "proto3";
+
+/*
+ * Client message to the server. Messages on the wire are
+ * prefixed with a 32-bit size in network byte order.
+ */
+message ClientMessage {
+ oneof type {
+ AcceptMessage accept_msg = 1;
+ RejectMessage reject_msg = 2;
+ ExitMessage exit_msg = 3;
+ RestartMessage restart_msg = 4;
+ AlertMessage alert_msg = 5;
+ IoBuffer ttyin_buf = 6;
+ IoBuffer ttyout_buf = 7;
+ IoBuffer stdin_buf = 8;
+ IoBuffer stdout_buf = 9;
+ IoBuffer stderr_buf = 10;
+ ChangeWindowSize winsize_event = 11;
+ CommandSuspend suspend_event = 12;
+ }
+}
+
+/* Equivalent of POSIX struct timespec */
+message TimeSpec {
+ int64 tv_sec = 1; /* seconds */
+ int32 tv_nsec = 2; /* nanoseconds */
+}
+
+/* I/O buffer with keystroke data */
+message IoBuffer {
+ TimeSpec delay = 1; /* elapsed time since last record */
+ bytes data = 2; /* keystroke data */
+}
+
+/*
+ * Key/value pairs, like Privilege Manager struct info.
+ * The value may be a number, a string, or a list of strings.
+ */
+message InfoMessage {
+ message StringList {
+ repeated string strings = 1;
+ }
+ message NumberList {
+ repeated int64 numbers = 1;
+ }
+ string key = 1;
+ oneof value {
+ int64 numval = 2;
+ string strval = 3;
+ StringList strlistval = 4;
+ NumberList numlistval = 5;
+ }
+}
+
+/*
+ * Event log data for command accepted by the policy.
+ */
+message AcceptMessage {
+ TimeSpec submit_time = 1; /* when command was submitted */
+ repeated InfoMessage info_msgs = 2; /* key,value event log data */
+ bool expect_iobufs = 3; /* true if I/O logging enabled */
+}
+
+/*
+ * Event log data for command rejected by the policy.
+ */
+message RejectMessage {
+ TimeSpec submit_time = 1; /* when command was submitted */
+ string reason = 2; /* reason command was rejected */
+ repeated InfoMessage info_msgs = 3; /* key,value event log data */
+}
+
+/* Message sent by client when command exits. */
+/* Might revisit runtime and use end_time instead */
+message ExitMessage {
+ TimeSpec run_time = 1; /* total elapsed run time */
+ int32 exit_value = 2; /* 0-255 */
+ bool dumped_core = 3; /* true if command dumped core */
+ string signal = 4; /* signal name if killed by signal */
+ string error = 5; /* if killed due to other error */
+}
+
+/* Alert message, policy module-specific. */
+message AlertMessage {
+ TimeSpec alert_time = 1; /* time alert message occurred */
+ string reason = 2; /* policy alert error string */
+ repeated InfoMessage info_msgs = 3; /* key,value event log data */
+}
+
+/* Used to restart an existing I/O log on the server. */
+message RestartMessage {
+ string log_id = 1; /* ID of log being restarted */
+ TimeSpec resume_point = 2; /* resume point (elapsed time) */
+}
+
+/* Window size change event. */
+message ChangeWindowSize {
+ TimeSpec delay = 1; /* elapsed time since last record */
+ int32 rows = 2; /* new number of rows */
+ int32 cols = 3; /* new number of columns */
+}
+
+/* Command suspend/resume event. */
+message CommandSuspend {
+ TimeSpec delay = 1; /* elapsed time since last record */
+ string signal = 2; /* signal that caused suspend/resume */
+}
+
+/*
+ * Server messages to the client. Messages on the wire are
+ * prefixed with a 32-bit size in network byte order.
+ */
+message ServerMessage {
+ oneof type {
+ ServerHello hello = 1; /* server hello message */
+ TimeSpec commit_point = 2; /* cumulative time of records stored */
+ string log_id = 3; /* ID of server-side I/O log */
+ string error = 4; /* error message from server */
+ string abort = 5; /* abort message, kill command */
+ }
+}
+
+/* Hello message from server when client connects. */
+message ServerHello {
+ string server_id = 1; /* free-form server description */
+ string redirect = 2; /* optional redirect if busy */
+ repeated string servers = 3; /* optional list of known servers */
+}
+.Ed
+.Sh SEE ALSO
+.Xr sudo_logsrvd.conf @mansectform@ ,
+.Xr sudoers @mansectform@ ,
+.Xr sudo @mansectsu@ ,
+.Xr sudo_logsrvd @mansectsu@
+.Rs
+.%T Protocol Buffers
+.%U https://developers.google.com/protocol-buffers/
+.Re
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS.md file in the
+.Nm sudo
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you believe you have found a bug in
+.Nm sudo ,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm sudo
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+.Nm sudo
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudo_logsrvd.conf.man.in b/docs/sudo_logsrvd.conf.man.in
new file mode 100644
index 0000000..2b5826a
--- /dev/null
+++ b/docs/sudo_logsrvd.conf.man.in
@@ -0,0 +1,1114 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.TH "SUDO_LOGSRVD.CONF" "@mansectform@" "January 16, 2023" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudo_logsrvd.conf\fR
+\- configuration for sudo_logsrvd
+.SH "DESCRIPTION"
+The
+\fBsudo_logsrvd.conf\fR
+file is used to configure the
+\fBsudo_logsrvd\fR
+log server.
+It uses an INI-style format made up of sections in square brackets and
+\(lqkey = value\(rq
+pairs specific to each section below the section name.
+Depending on the key, values may be integers, booleans, or strings.
+Section and key names are not case sensitive, but values are.
+.PP
+The pound sign
+(\(oq#\(cq)
+is used to indicate a comment.
+Both the comment character and any text after it, up to the end of
+the line, are ignored.
+Lines beginning with a semi-colon
+(\(oq\&;\(cq)
+are also ignored.
+.PP
+Long lines can be continued with a backslash
+(\(oq\e\(cq)
+as the last character on the line.
+Leading white space is removed from the beginning of lines
+even when the continuation character is used.
+.PP
+The
+\fIEXAMPLES\fR
+section contains a copy of the default
+\fBsudo_logsrvd.conf\fR
+file.
+.PP
+The following configuration sections are recognized:
+.PP
+.RS 1n
+.PD 0
+.TP 3n
+\fB\(bu\fR
+server
+.TP 3n
+\fB\(bu\fR
+relay
+.TP 3n
+\fB\(bu\fR
+iolog
+.TP 3n
+\fB\(bu\fR
+eventlog
+.TP 3n
+\fB\(bu\fR
+syslog
+.TP 3n
+\fB\(bu\fR
+logfile
+.RE
+.PD
+.PP
+Each section is described in detail below.
+.SS "server"
+The
+\fIserver\fR
+section configures the address and port the server will listen on.
+The following keys are recognized:
+.TP 6n
+listen_address = host[:port][(tls)]
+The host name or IP address, optional port to listen on and
+an optional Transport Layer Security (TLS) flag in parentheses.
+.sp
+The host may be a host name, an IPv4 address, an IPv6 address
+in square brackets or the wild card entry
+\(oq*\(cq.
+A host setting of
+\(oq*\(cq
+will cause
+\fBsudo_logsrvd\fR
+to listen on all configured network interfaces.
+.sp
+If the optional tls flag is present,
+\fBsudo_logsrvd\fR
+will secure the connection with TLS version 1.2 or 1.3.
+Versions of TLS prior to 1.2 are not supported.
+See
+sudo_logsrvd(8)
+for details on generating TLS keys and certificates.
+.sp
+If a port is specified, it may either be a port number or a known
+service name as defined by the system service name database.
+If no port is specified, port 30343 will be used for plaintext
+connections and port 30344 will be used for TLS connections.
+.sp
+The default value is:
+.nf
+.RS 12n
+listen_address = *:30343
+listen_address = *:30344(tls)
+.RE
+.fi
+.RS 6n
+which will listen on all configured network interfaces for both
+plaintext and TLS connections.
+Multiple
+\fIlisten_address\fR
+lines may be specified to listen on more than one port or interface.
+.RE
+.TP 6n
+server_log = string
+Where to log server warning and error messages.
+Supported values are
+\fInone\fR,
+\fIstderr\fR,
+\fIsyslog\fR,
+or a path name beginning with the
+\(oq/\(cq
+character.
+A value of
+\fIstderr\fR
+is only effective when used in conjunction with the
+\fB\-n\fR
+option.
+The default value is
+\fIsyslog\fR.
+.TP 6n
+pid_file = path
+The path to the file containing the process ID of the running
+\fBsudo_logsrvd\fR.
+If set to an empty value, or if
+\fBsudo_logsrvd\fR
+is run with the
+\fB\-n\fR
+option, no
+\fIpid_file\fR
+will be created.
+If
+\fIpid_file\fR
+refers to a symbolic link, it will be ignored.
+The default value is
+\fI@rundir@/sudo_logsrvd.pid\fR.
+.TP 6n
+tcp_keepalive = boolean
+If true,
+\fBsudo_logsrvd\fR
+will enable the TCP keepalive socket option on the client connection.
+This enables the periodic transmission of keepalive messages to the client.
+If the client does not respond to a message in time, the connection will
+be closed.
+Defaults to
+\fItrue\fR.
+.TP 6n
+timeout = number
+The amount of time, in seconds,
+\fBsudo_logsrvd\fR
+will wait for the client to respond.
+A value of 0 will disable the timeout.
+The default value is
+\fI30\fR.
+.TP 6n
+tls_cacert = path
+The path to a certificate authority bundle file, in PEM format,
+to use instead of the system's default certificate authority database
+when authenticating clients.
+The default is to use
+\fI/etc/ssl/sudo/cacert.pem\fR
+if it exists, otherwise the system's default certificate authority
+database is used.
+.TP 6n
+tls_cert = path
+The path to the server's certificate file, in PEM format.
+The default value is
+\fI/etc/ssl/sudo/certs/logsrvd_cert.pem\fR.
+.TP 6n
+tls_checkpeer = bool
+If true, client certificates will be validated by
+\fBsudo_logsrvd\fR;
+clients without a valid certificate will be unable to connect.
+If false, no validation of client certificates will be performed.
+It true and client certificates are created using a private certificate
+authority, the
+\fItls_cacert\fR
+setting must be set to a CA bundle that contains the CA certificate
+used to generate the client certificate.
+The default value is
+\fIfalse\fR.
+.TP 6n
+tls_ciphers_v12 = string
+A list of ciphers to use for connections secured by TLS version 1.2 only,
+separated by a colon
+\(oq:\&\(cq.
+See the
+\fICIPHER LIST FORMAT\fR
+section in
+openssl-ciphers(1)
+for full details.
+The default value is
+\(lqHIGH:!aNULL\(rq
+which consists of encryption cipher suites with key lengths larger than
+128 bits, and some cipher suites with 128-bit keys.
+Cipher suites that offer no authentication are excluded.
+.TP 6n
+tls_ciphers_v13 = string
+A list of ciphers to use for connections secured by TLS version 1.3 only,
+separated by a colon
+\(oq:\&\(cq.
+Supported cipher suites depend on the version of OpenSSL used,
+but should include the following:
+.sp
+.RS 12n
+.PD 0
+.TP 6n
+TLS_AES_128_GCM_SHA256
+.TP 6n
+TLS_AES_256_GCM_SHA384
+.TP 6n
+TLS_CHACHA20_POLY1305_SHA256
+.TP 6n
+TLS_AES_128_CCM_SHA256
+.TP 6n
+TLS_AES_128_CCM_8_SHA256
+.RE
+.RS 6n
+.sp
+The default cipher suite is
+\(lqTLS_AES_256_GCM_SHA384\(rq.
+.RE
+.PD
+.TP 6n
+tls_dhparams = path
+The path to a file containing custom Diffie-Hellman parameters in PEM format.
+This file can be created with the following command:
+.nf
+.sp
+.RS 6n
+openssl dhparam -out /etc/sudo_logsrvd_dhparams.pem 2048
+.RE
+.fi
+.RS 6n
+.sp
+By default,
+\fBsudo_logsrvd\fR
+will use the OpenSSL defaults for Diffie-Hellman key generation.
+.RE
+.TP 6n
+tls_key = path
+The path to the server's private key file, in PEM format.
+The default value is
+\fI/etc/ssl/sudo/private/logsrvd_key.pem\fR.
+.TP 6n
+tls_verify = bool
+If true,
+\fBsudo_logsrvd\fR
+will validate its own certificate at startup time or when the
+configuration is changed.
+If false, no verification is performed of the server certificate.
+When using self-signed certificates without a certificate authority,
+this setting should be set to false.
+The default value is
+\fItrue\fR.
+.SS "relay"
+The
+\fIrelay\fR
+section configures the optional logsrv relay host and port the server will
+connect to.
+The TLS configuration keys are optional, by default the corresponding
+keys in the
+\fIserver\fR
+section will be used.
+They are only present in this section to make it possible for the relay
+connection to use a different set of TLS parameters from the client-facing
+server.
+The following keys are recognized:
+.TP 6n
+connect_timeout = number
+The amount of time, in seconds,
+\fBsudo_logsrvd\fR
+will wait for the connection to a
+\fIrelay_host\fR
+(see below) to complete.
+Once the connection is complete, the
+\fItimeout\fR
+setting controls the amount of time
+\fBsudo_logsrvd\fR
+will wait for the relay to respond.
+A value of 0 will disable the timeout.
+The default value is
+\fI30\fR.
+.TP 6n
+relay_dir = path
+The directory in which log messages are temporarily stored before they
+are sent to the relay host.
+Messages are stored in the wire format specified by
+sudo_logsrv.proto(@mansectform@)
+The default value is
+\fI@relay_dir@\fR.
+.TP 6n
+relay_host = host[:port][(tls)]
+The relay host name or IP address, optional port to connect to and
+an optional Transport Layer Security (TLS) flag in parentheses.
+The syntax is identical to
+\fIlisten_address\fR
+in the
+\fIserver\fR
+section with one exception: the wild card
+\(oq*\(cq
+syntax is not supported.
+.sp
+When this setting is enabled, messages from the client will be forwarded
+to one of the specified relay hosts instead of being stored locally.
+The
+\fIhost\fR
+could be running an instance of
+\fBsudo_logsrvd\fR
+or another server that supports the
+sudo_logsrv.proto(@mansectform@)
+protocol.
+.sp
+If multiple
+\fIrelay_host\fR
+lines are specified, the first available relay host will be used.
+.TP 6n
+retry_interval = number
+The number of seconds to wait after a connection error before making
+a new attempt to forward a message to a relay host.
+The default value is
+\fI30\fR.
+.TP 6n
+store_first = boolean
+If true,
+\fBsudo_logsrvd\fR
+will store logs locally before relaying them.
+Once the log is complete, a connection to the relay host is opened
+and the log is relayed.
+If the network connection is interrupted before the log can be fully
+transferred, it will be retransmitted later.
+The default is to relay logs in real-time.
+.TP 6n
+tcp_keepalive = boolean
+If true,
+\fBsudo_logsrvd\fR
+will enable the TCP keepalive socket option on the relay connection.
+This enables the periodic transmission of keepalive messages to the relay
+server.
+If the relay does not respond to a message in time, the connection will
+be closed.
+.TP 6n
+timeout = number
+The amount of time, in seconds,
+\fBsudo_logsrvd\fR
+will wait for the relay server to respond after a connection has succeeded.
+A value of 0 will disable the timeout.
+The default value is
+\fI30\fR.
+.TP 6n
+tls_cacert = path
+The path to a certificate authority bundle file, in PEM format,
+to use instead of the system's default certificate authority database
+when authenticating clients.
+The default is to use the value specified in the
+\fIserver\fR
+section, or the system's default certificate authority database if
+no value is set.
+.TP 6n
+tls_cert = path
+The path to the server's certificate file, in PEM format.
+The default is to use the value specified in the
+\fIserver\fR
+section.
+.TP 6n
+tls_checkpeer = bool
+If true, the relay host's certificate will be validated by
+\fBsudo_logsrvd\fR;
+connections to a relay without a valid certificate will fail.
+If false, no validation of relay certificates will be performed.
+It true and relay certificates are created using a private certificate
+authority, the
+\fItls_cacert\fR
+setting must be set to a CA bundle that contains the CA certificate
+used to generate the relay certificate.
+The default is to use the value specified in the
+\fIserver\fR
+section.
+.TP 6n
+tls_ciphers_v12 = string
+A list of ciphers to use for connections secured by TLS version 1.2 only,
+separated by a colon
+\(oq:\&\(cq.
+See the
+\fICIPHER LIST FORMAT\fR
+section in
+openssl-ciphers(1)
+for full details.
+The default is to use the value specified in the
+\fIserver\fR
+section.
+.TP 6n
+tls_ciphers_v13 = string
+A list of ciphers to use for connections secured by TLS version 1.3 only,
+separated by a colon
+\(oq:\&\(cq.
+Supported cipher suites depend on the version of OpenSSL used,
+see the
+\fIserver\fR
+section for more information.
+The default is to use the value specified in the
+\fIserver\fR
+section.
+.TP 6n
+tls_dhparams = path
+The path to a file containing custom Diffie-Hellman parameters in PEM format.
+The default is to use the value specified in the
+\fIserver\fR
+section.
+.TP 6n
+tls_key = path
+The path to the server's private key file, in PEM format.
+The default is to use the value specified in the
+\fIserver\fR
+section.
+.TP 6n
+tls_verify = bool
+If true, the server's certificate used for relaying will be verified at startup.
+If false, no verification is performed of the server certificate.
+When using self-signed certificates without a certificate authority,
+this setting should be set to false.
+The default is to use the value specified in the
+\fIserver\fR
+section.
+.SS "iolog"
+The
+\fIiolog\fR
+section configures I/O log parameters.
+These settings are identical to the I/O configuration in
+sudoers(@mansectform@).
+The following keys are recognized:
+.TP 6n
+iolog_compress = boolean
+If set, I/O logs will be compressed using
+\fBzlib\fR.
+Enabling compression can make it harder to view the logs in real-time as
+the program is executing due to buffering.
+The default value is
+\fIfalse\fR.
+.TP 6n
+iolog_dir = path
+The top-level directory to use when constructing the path
+name for the I/O log directory.
+The session sequence number, if any, is stored in the directory.
+The default value is
+\fI@iolog_dir@\fR.
+.sp
+The following percent
+(\(oq%\(cq)
+escape sequences are supported:
+.PP
+.RS 6n
+.PD 0
+.TP 6n
+%{seq}
+expanded to a monotonically increasing base-36 sequence number, such as 0100A5,
+where every two digits are used to form a new directory, e.g.,
+\fI01/00/A5\fR
+.PD
+.TP 6n
+%{user}
+expanded to the invoking user's login name
+.TP 6n
+%{group}
+expanded to the name of the invoking user's real group-ID
+.TP 6n
+%{runas_user}
+expanded to the login name of the user the command will
+be run as (e.g., root)
+.TP 6n
+%{runas_group}
+expanded to the group name of the user the command will
+be run as (e.g., wheel)
+.TP 6n
+%{hostname}
+expanded to the local host name without the domain name
+.TP 6n
+%{command}
+expanded to the base name of the command being run
+.PP
+In addition, any escape sequences supported by the system's
+strftime(3)
+function will be expanded.
+.sp
+To include a literal
+\(oq%\(cq
+character, the string
+\(oq%%\(cq
+should be used.
+.RE
+.TP 6n
+iolog_file = path
+The path name, relative to
+\fIiolog_dir\fR,
+in which to store I/O logs.
+It is possible for
+\fIiolog_file\fR
+to contain directory components.
+The default value is
+\(lq%{seq}\(rq.
+.sp
+See the
+\fIiolog_dir\fR
+setting above for a list of supported percent
+(\(oq%\(cq)
+escape sequences.
+.sp
+In addition to the escape sequences, path names that end in six or
+more
+\fIX\fRs
+will have the
+\fIX\fRs
+replaced with a unique combination of digits and letters, similar to the
+mktemp(3)
+function.
+.sp
+If the path created by concatenating
+\fIiolog_dir\fR
+and
+\fIiolog_file\fR
+already exists, the existing I/O log file will be truncated and
+overwritten unless
+\fIiolog_file\fR
+ends in six or
+more
+\fIX\fRs.
+.TP 6n
+iolog_flush = boolean
+If set, I/O log data is flushed to disk after each write instead of
+buffering it.
+This makes it possible to view the logs in real-time as the program is
+executing but may significantly reduce the effectiveness
+of I/O log compression.
+I/O logs are always flushed before sending a commit point to the client
+regardless of this setting.
+The default value is
+\fItrue\fR.
+.TP 6n
+iolog_group = name
+The group name to look up when setting the group-ID on new I/O log
+files and directories.
+If
+\fIiolog_group\fR
+is not set,
+the primary group-ID of the user specified by
+\fIiolog_user is used.\fR
+If neither
+\fIiolog_group\fR
+nor
+\fIiolog_user\fR
+are set, I/O log files and directories are created with group-ID 0.
+.TP 6n
+iolog_mode = mode
+The file mode to use when creating I/O log files.
+Mode bits for read and write permissions for owner, group, or other
+are honored, everything else is ignored.
+The file permissions will always include the owner read and
+write bits, even if they are not present in the specified mode.
+When creating I/O log directories, search (execute) bits are added
+to match the read and write bits specified by
+\fIiolog_mode\fR.
+The default value is
+\fI0600\fR.
+.TP 6n
+iolog_user = name
+The user name to look up when setting the owner of new
+I/O log files and directories.
+If
+\fIiolog_group\fR
+is set, it will be used instead of the user's primary group-ID.
+By default, I/O log files and directories are created with user and
+group-ID 0.
+.TP 6n
+log_passwords = bool
+Most programs that require a user's password will disable echo before
+reading the password to avoid displaying the plaintext password on
+the screen.
+However, if terminal input is being logged,
+the password will still be present in the I/O log.
+If
+\fIlog_passwords\fR
+is set to
+\fIfalse\fR,
+\fBsudo_logsrvd\fR
+will attempt to prevent passwords from being logged.
+It does this by using the regular expressions in
+\fIpassprompt_regex\fR
+to match a password prompt in the terminal output buffer.
+When a match is found, input characters in the I/O log will be replaced with
+\(oq*\(cq
+until either a line feed or carriage return is found in the terminal input
+or a new terminal output buffer is received.
+If, however, a program displays characters as the user types them
+(such as
+\fBsudo\fR
+when the
+\fIpwfeedback\fR
+option is set), only the
+first character of the password will be replaced in the I/O log.
+The default value is
+\fItrue\fR.
+.TP 6n
+maxseq = number
+The maximum sequence number that will be substituted for the
+\(lq%{seq}\(rq
+escape in the I/O log file (see the
+\fIiolog_dir\fR
+description above for more information).
+While the value substituted for
+\(lq%{seq}\(rq
+is in base 36,
+\fImaxseq\fR
+itself should be expressed in decimal.
+Values larger than 2176782336 (which corresponds to the
+base 36 sequence number
+\(lqZZZZZZ\(rq)
+will be silently truncated to 2176782336.
+The default value is
+\fI2176782336\fR.
+.TP 6n
+passprompt_regex = string
+One or more POSIX extended regular expressions used to
+match password prompts in the terminal output when
+\fIlog_passwords\fR
+is disabled.
+As an extension, if the regular expression begins with
+\(lq(?i)\(rq,
+it will be matched in a case-insensitive manner.
+Multiple
+\fIpassprompt_regex\fR
+settings may be specified.
+Each regular expression is limited to 1024 characters.
+The default value is
+\(lq[Pp]assword[: ]*\(rq.
+.SS "eventlog"
+The
+\fIeventlog\fR
+section configures how (and if) security policy events are logged.
+.TP 6n
+log_type = string
+Where to log accept, reject, and alert events reported by the policy.
+Supported values are
+\fIsyslog\fR,
+\fIlogfile\fR,
+and
+\fInone\fR.
+The default value is
+\fIsyslog\fR.
+.TP 6n
+log_exit = boolean
+If true,
+\fBsudo_logsrvd\fR
+will log an event when a command exits or is terminated by a signal.
+Defaults to
+\fIfalse\fR.
+.TP 6n
+log_format = string
+The event log format.
+Supported log formats are
+\(lqsudo\(rq
+for traditional sudo-style logs and
+\(lqjson\(rq
+for JSON-format logs.
+The JSON log entries contain the full contents of the accept, reject, exit
+and alert messages.
+The default value is
+\fIsudo\fR.
+.SS "syslog"
+The
+\fIsyslog\fR
+section configures how events are logged via
+syslog(3).
+.TP 6n
+facility = string
+Syslog facility if syslog is being used for logging.
+Defaults to
+\fI@logfac@\fR.
+.sp
+The following syslog facilities are supported:
+\fBauthpriv\fR
+(if your
+OS supports it),
+\fBauth\fR,
+\fBdaemon\fR,
+\fBuser\fR,
+\fBlocal0\fR,
+\fBlocal1\fR,
+\fBlocal2\fR,
+\fBlocal3\fR,
+\fBlocal4\fR,
+\fBlocal5\fR,
+\fBlocal6\fR,
+and
+\fBlocal7\fR.
+.TP 6n
+accept_priority = string
+Syslog priority to use when the user is allowed to run a command and
+authentication is successful.
+Defaults to
+\fI@goodpri@\fR.
+.sp
+The following syslog priorities are supported:
+\fBalert\fR,
+\fBcrit\fR,
+\fBdebug\fR,
+\fBemerg\fR,
+\fBerr\fR,
+\fBinfo\fR,
+\fBnotice\fR,
+\fBwarning\fR,
+and
+\fBnone\fR.
+Setting it to a value of
+\fBnone\fR
+will disable logging of successful commands.
+.TP 6n
+reject_priority = string
+Syslog priority to use when the user is not allowed to run a command or
+when authentication is unsuccessful.
+Defaults to
+\fI@badpri@\fR.
+.sp
+See
+\fIaccept_priority\fR
+for the list of supported syslog priorities.
+.TP 6n
+alert_priority = string
+Syslog priority to use for event log alert messages received from the client.
+Defaults to
+\fI@badpri@\fR.
+.sp
+See
+\fIaccept_priority\fR
+for the list of supported syslog priorities.
+.TP 6n
+maxlen = number
+On many systems,
+syslog(3)
+has a relatively small log buffer.
+IETF RFC 5424 states that syslog servers must support messages of
+at least 480 bytes and should support messages up to 2048 bytes.
+By default,
+\fBsudo_logsrvd\fR
+creates log messages up to 960 bytes which corresponds to the
+historic
+BSD
+syslog implementation which used a 1024 byte buffer
+to store the message, date, hostname, and program name.
+.sp
+To prevent syslog messages from being truncated,
+\fBsudo_logsrvd\fR
+will split up sudo-style log messages that are larger than
+\fImaxlen\fR
+bytes.
+When a message is split, additional parts will include the string
+\(lq(command continued)\(rq
+after the user name and before the continued command line arguments.
+JSON-format log entries are never split and are not affected by
+\fImaxlen\fR.
+.TP 6n
+server_facility = string
+Syslog facility if syslog is being used for server warning messages.
+See above for a list of supported facilities.
+Defaults to
+\fIdaemon\fR
+.SS "logfile"
+The
+\fIlogfile\fR
+section consists of settings related to logging to a plain file
+(not syslog).
+.TP 6n
+path = string
+The path to the file-based event log.
+This path must be fully-qualified and start with a
+\(oq/\(cq
+character.
+The default value is
+\fI@logpath@\fR.
+.TP 6n
+time_format = string
+The string used when formatting the date and time for file-based event logs.
+Formatting is performed via the system's
+strftime(3)
+function so any escape sequences supported by that function will be expanded.
+The default value is
+\(lq%h %e %T\(rq
+which produces dates like
+\(lqOct 3 07:15:24\(rq
+in the
+\(oqC\(cq
+locale.
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/sudo_logsrvd.conf\fR
+Sudo log server configuration file
+.SH "EXAMPLES"
+.nf
+.RS 0n
+#
+# sudo logsrv daemon configuration
+#
+
+[server]
+# The host name or IP address and port to listen on with an optional TLS
+# flag. If no port is specified, port 30343 will be used for plaintext
+# connections and port 30344 will be used to TLS connections.
+# The following forms are accepted:
+# listen_address = hostname(tls)
+# listen_address = hostname:port(tls)
+# listen_address = IPv4_address(tls)
+# listen_address = IPv4_address:port(tls)
+# listen_address = [IPv6_address](tls)
+# listen_address = [IPv6_address]:port(tls)
+#
+# The (tls) suffix should be omitted for plaintext connections.
+#
+# Multiple listen_address settings may be specified.
+# The default is to listen on all addresses.
+#listen_address = *:30343
+#listen_address = *:30344(tls)
+
+# The file containing the ID of the running sudo_logsrvd process.
+#pid_file = @rundir@/sudo_logsrvd.pid
+
+# Where to log server warnings: none, stderr, syslog, or a path name.
+#server_log = syslog
+
+# If true, enable the SO_KEEPALIVE socket option on client connections.
+# Defaults to true.
+#tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the client to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+#timeout = 30
+
+# If true, the server will validate its own certificate at startup.
+# Defaults to true.
+#tls_verify = true
+
+# If true, client certificates will be validated by the server;
+# clients without a valid certificate will be unable to connect.
+# By default, client certs are not checked.
+#tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+#tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# Required for TLS connections.
+#tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# Required for TLS connections.
+#tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# This setting is only effective if the negotiated protocol is TLS version
+# 1.2. The default cipher list is HIGH:!aNULL.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default cipher list is TLS_AES_256_GCM_SHA384.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# If not set, the server will use the OpenSSL defaults.
+#tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[relay]
+# The host name or IP address and port to send logs to in relay mode.
+# The syntax is identical to listen_address with the exception of
+# the wild card ('*') syntax. When this setting is enabled, logs will
+# be relayed to the specified host instead of being stored locally.
+# This setting is not enabled by default.
+#relay_host = relayhost.dom.ain
+#relay_host = relayhost.dom.ain(tls)
+
+# The amount of time, in seconds, the server will wait for a connection
+# to the relay server to complete. A value of 0 will disable the timeout.
+# The default value is 30.
+#connect_timeout = 30
+
+# The directory to store messages in before they are sent to the relay.
+# Messages are stored in wire format.
+# The default value is @relay_dir@.
+#relay_dir = @relay_dir@
+
+# The number of seconds to wait after a connection error before
+# making a new attempt to forward a message to a relay host.
+# The default value is 30.
+#retry_interval = 30
+
+# Whether to store the log before relaying it. If true, enable store
+# and forward mode. If false, the client connection is immediately
+# relayed. Defaults to false.
+#store_first = true
+
+# If true, enable the SO_KEEPALIVE socket option on relay connections.
+# Defaults to true.
+#tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the relay to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+#timeout = 30
+
+# If true, the server's relay certificate will be verified at startup.
+# The default is to use the value in the [server] section.
+#tls_verify = true
+
+# Whether to verify the relay's certificate for TLS connections.
+# The default is to use the value in the [server] section.
+#tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+# The default is to use the value in the [server] section.
+#tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# The default is to use the certificate in the [server] section.
+#tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# The default is to use the key in the [server] section.
+#tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# this setting is only effective if the negotiated protocol is TLS version
+# 1.2. The default is to use the value in the [server] section.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default is to use the value in the [server] section.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# The default is to use the value in the [server] section.
+#tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[iolog]
+# The top-level directory to use when constructing the path name for the
+# I/O log directory. The session sequence number, if any, is stored here.
+#iolog_dir = @iolog_dir@
+
+# The path name, relative to iolog_dir, in which to store I/O logs.
+# It is possible for iolog_file to contain directory components.
+#iolog_file = %{seq}
+
+# If set, I/O logs will be compressed using zlib. Enabling compression can
+# make it harder to view the logs in real-time as the program is executing.
+#iolog_compress = false
+
+# If set, I/O log data is flushed to disk after each write instead of
+# buffering it. This makes it possible to view the logs in real-time
+# as the program is executing but reduces the effectiveness of compression.
+#iolog_flush = true
+
+# The group to use when creating new I/O log files and directories.
+# If iolog_group is not set, the primary group-ID of the user specified
+# by iolog_user is used. If neither iolog_group nor iolog_user
+# are set, I/O log files and directories are created with group-ID 0.
+#iolog_group = wheel
+
+# The user to use when setting the user-ID and group-ID of new I/O
+# log files and directories. If iolog_group is set, it will be used
+# instead of the user's primary group-ID. By default, I/O log files
+# and directories are created with user and group-ID 0.
+#iolog_user = root
+
+# The file mode to use when creating I/O log files. The file permissions
+# will always include the owner read and write bits, even if they are
+# not present in the specified mode. When creating I/O log directories,
+# search (execute) bits are added to match the read and write bits
+# specified by iolog_mode.
+#iolog_mode = 0600
+
+# If disabled, sudo_logsrvd will attempt to avoid logging plaintext
+# password in the terminal input using passprompt_regex.
+#log_passwords = true
+
+# The maximum sequence number that will be substituted for the "%{seq}"
+# escape in the I/O log file. While the value substituted for "%{seq}"
+# is in base 36, maxseq itself should be expressed in decimal. Values
+# larger than 2176782336 (which corresponds to the base 36 sequence
+# number "ZZZZZZ") will be silently truncated to 2176782336.
+#maxseq = 2176782336
+
+# One or more POSIX extended regular expressions used to match
+# password prompts in the terminal output when log_passwords is
+# disabled. Multiple passprompt_regex settings may be specified.
+#passprompt_regex = [Pp]assword[: ]*
+#passprompt_regex = [Pp]assword for [a-z0-9]+: *
+
+[eventlog]
+# Where to log accept, reject, exit, and alert events.
+# Accepted values are syslog, logfile, or none.
+# Defaults to syslog
+#log_type = syslog
+
+# Whether to log an event when a command exits or is terminated by a signal.
+# Defaults to false
+#log_exit = true
+
+# Event log format.
+# Currently only sudo-style event logs are supported.
+#log_format = sudo
+
+[syslog]
+# The maximum length of a syslog payload.
+# On many systems, syslog(3) has a relatively small log buffer.
+# IETF RFC 5424 states that syslog servers must support messages
+# of at least 480 bytes and should support messages up to 2048 bytes.
+# Messages larger than this value will be split into multiple messages.
+#maxlen = 960
+
+# The syslog facility to use for event log messages.
+# The following syslog facilities are supported: authpriv (if your OS
+# supports it), auth, daemon, user, local0, local1, local2, local3,
+# local4, local5, local6, and local7.
+#facility = @logfac@
+
+# Syslog priority to use for event log accept messages, when the command
+# is allowed by the security policy. The following syslog priorities are
+# supported: alert, crit, debug, emerg, err, info, notice, warning, none.
+#accept_priority = @goodpri@
+
+# Syslog priority to use for event log reject messages, when the command
+# is not allowed by the security policy.
+#reject_priority = @badpri@
+
+# Syslog priority to use for event log alert messages reported by the
+# client.
+#alert_priority = @badpri@
+
+# The syslog facility to use for server warning messages.
+# Defaults to daemon.
+#server_facility = daemon
+
+[logfile]
+# The path to the file-based event log.
+# This path must be fully-qualified and start with a '/' character.
+#path = @logpath@
+
+# The format string used when formatting the date and time for
+# file-based event logs. Formatting is performed via strftime(3) so
+# any format string supported by that function is allowed.
+#time_format = %h %e %T
+.RE
+.fi
+.SH "SEE ALSO"
+strftime(3),
+sudo.conf(@mansectform@),
+sudoers(@mansectform@),
+sudo(8),
+sudo_logsrvd(8)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS.md file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you believe you have found a bug in
+\fBsudo\fR,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudo_logsrvd.conf.mdoc.in b/docs/sudo_logsrvd.conf.mdoc.in
new file mode 100644
index 0000000..8fee88c
--- /dev/null
+++ b/docs/sudo_logsrvd.conf.mdoc.in
@@ -0,0 +1,1038 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd January 16, 2023
+.Dt SUDO_LOGSRVD.CONF @mansectform@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudo_logsrvd.conf
+.Nd configuration for sudo_logsrvd
+.Sh DESCRIPTION
+The
+.Nm sudo_logsrvd.conf
+file is used to configure the
+.Nm sudo_logsrvd
+log server.
+It uses an INI-style format made up of sections in square brackets and
+.Dq key = value
+pairs specific to each section below the section name.
+Depending on the key, values may be integers, booleans, or strings.
+Section and key names are not case sensitive, but values are.
+.Pp
+The pound sign
+.Pq Ql #
+is used to indicate a comment.
+Both the comment character and any text after it, up to the end of
+the line, are ignored.
+Lines beginning with a semi-colon
+.Pq Ql \&;
+are also ignored.
+.Pp
+Long lines can be continued with a backslash
+.Pq Ql \e
+as the last character on the line.
+Leading white space is removed from the beginning of lines
+even when the continuation character is used.
+.Pp
+The
+.Sx EXAMPLES
+section contains a copy of the default
+.Nm
+file.
+.Pp
+The following configuration sections are recognized:
+.Pp
+.Bl -bullet -compact -offset 1n -width 1n
+.It
+server
+.It
+relay
+.It
+iolog
+.It
+eventlog
+.It
+syslog
+.It
+logfile
+.El
+.Pp
+Each section is described in detail below.
+.Ss server
+The
+.Em server
+section configures the address and port the server will listen on.
+The following keys are recognized:
+.Bl -tag -width 4n
+.It listen_address = host Ns Oo : Ns port Oc Ns Op (tls)
+The host name or IP address, optional port to listen on and
+an optional Transport Layer Security (TLS) flag in parentheses.
+.Pp
+The host may be a host name, an IPv4 address, an IPv6 address
+in square brackets or the wild card entry
+.Ql * .
+A host setting of
+.Ql *
+will cause
+.Nm sudo_logsrvd
+to listen on all configured network interfaces.
+.Pp
+If the optional tls flag is present,
+.Nm sudo_logsrvd
+will secure the connection with TLS version 1.2 or 1.3.
+Versions of TLS prior to 1.2 are not supported.
+See
+.Xr sudo_logsrvd @mansectsu@
+for details on generating TLS keys and certificates.
+.Pp
+If a port is specified, it may either be a port number or a known
+service name as defined by the system service name database.
+If no port is specified, port 30343 will be used for plaintext
+connections and port 30344 will be used for TLS connections.
+.Pp
+The default value is:
+.Bd -literal -compact -offset indent
+listen_address = *:30343
+listen_address = *:30344(tls)
+.Ed
+which will listen on all configured network interfaces for both
+plaintext and TLS connections.
+Multiple
+.Em listen_address
+lines may be specified to listen on more than one port or interface.
+.It server_log = string
+Where to log server warning and error messages.
+Supported values are
+.Em none ,
+.Em stderr ,
+.Em syslog ,
+or a path name beginning with the
+.Ql /
+character.
+A value of
+.Em stderr
+is only effective when used in conjunction with the
+.Fl n
+option.
+The default value is
+.Em syslog .
+.It pid_file = path
+The path to the file containing the process ID of the running
+.Nm sudo_logsrvd .
+If set to an empty value, or if
+.Nm sudo_logsrvd
+is run with the
+.Fl n
+option, no
+.Em pid_file
+will be created.
+If
+.Em pid_file
+refers to a symbolic link, it will be ignored.
+The default value is
+.Pa @rundir@/sudo_logsrvd.pid .
+.It tcp_keepalive = boolean
+If true,
+.Nm sudo_logsrvd
+will enable the TCP keepalive socket option on the client connection.
+This enables the periodic transmission of keepalive messages to the client.
+If the client does not respond to a message in time, the connection will
+be closed.
+Defaults to
+.Em true .
+.It timeout = number
+The amount of time, in seconds,
+.Nm sudo_logsrvd
+will wait for the client to respond.
+A value of 0 will disable the timeout.
+The default value is
+.Em 30 .
+.It tls_cacert = path
+The path to a certificate authority bundle file, in PEM format,
+to use instead of the system's default certificate authority database
+when authenticating clients.
+The default is to use
+.Pa /etc/ssl/sudo/cacert.pem
+if it exists, otherwise the system's default certificate authority
+database is used.
+.It tls_cert = path
+The path to the server's certificate file, in PEM format.
+The default value is
+.Pa /etc/ssl/sudo/certs/logsrvd_cert.pem .
+.It tls_checkpeer = bool
+If true, client certificates will be validated by
+.Nm sudo_logsrvd ;
+clients without a valid certificate will be unable to connect.
+If false, no validation of client certificates will be performed.
+It true and client certificates are created using a private certificate
+authority, the
+.Em tls_cacert
+setting must be set to a CA bundle that contains the CA certificate
+used to generate the client certificate.
+The default value is
+.Em false .
+.It tls_ciphers_v12 = string
+A list of ciphers to use for connections secured by TLS version 1.2 only,
+separated by a colon
+.Ql :\& .
+See the
+.Sx CIPHER LIST FORMAT
+section in
+.Xr openssl-ciphers 1
+for full details.
+The default value is
+.Dq HIGH:!aNULL
+which consists of encryption cipher suites with key lengths larger than
+128 bits, and some cipher suites with 128-bit keys.
+Cipher suites that offer no authentication are excluded.
+.It tls_ciphers_v13 = string
+A list of ciphers to use for connections secured by TLS version 1.3 only,
+separated by a colon
+.Ql :\& .
+Supported cipher suites depend on the version of OpenSSL used,
+but should include the following:
+.Pp
+.Bl -tag -compact -width 4n -offset indent
+.It TLS_AES_128_GCM_SHA256
+.It TLS_AES_256_GCM_SHA384
+.It TLS_CHACHA20_POLY1305_SHA256
+.It TLS_AES_128_CCM_SHA256
+.It TLS_AES_128_CCM_8_SHA256
+.El
+.Pp
+The default cipher suite is
+.Dq TLS_AES_256_GCM_SHA384 .
+.It tls_dhparams = path
+The path to a file containing custom Diffie-Hellman parameters in PEM format.
+This file can be created with the following command:
+.Bd -literal
+openssl dhparam -out /etc/sudo_logsrvd_dhparams.pem 2048
+.Ed
+.Pp
+By default,
+.Nm sudo_logsrvd
+will use the OpenSSL defaults for Diffie-Hellman key generation.
+.It tls_key = path
+The path to the server's private key file, in PEM format.
+The default value is
+.Pa /etc/ssl/sudo/private/logsrvd_key.pem .
+.It tls_verify = bool
+If true,
+.Nm sudo_logsrvd
+will validate its own certificate at startup time or when the
+configuration is changed.
+If false, no verification is performed of the server certificate.
+When using self-signed certificates without a certificate authority,
+this setting should be set to false.
+The default value is
+.Em true .
+.El
+.Ss relay
+The
+.Em relay
+section configures the optional logsrv relay host and port the server will
+connect to.
+The TLS configuration keys are optional, by default the corresponding
+keys in the
+.Sx server
+section will be used.
+They are only present in this section to make it possible for the relay
+connection to use a different set of TLS parameters from the client-facing
+server.
+The following keys are recognized:
+.Bl -tag -width 4n
+.It connect_timeout = number
+The amount of time, in seconds,
+.Nm sudo_logsrvd
+will wait for the connection to a
+.Em relay_host
+(see below) to complete.
+Once the connection is complete, the
+.Em timeout
+setting controls the amount of time
+.Nm sudo_logsrvd
+will wait for the relay to respond.
+A value of 0 will disable the timeout.
+The default value is
+.Em 30 .
+.It relay_dir = path
+The directory in which log messages are temporarily stored before they
+are sent to the relay host.
+Messages are stored in the wire format specified by
+.Xr sudo_logsrv.proto @mansectform@
+The default value is
+.Pa @relay_dir@ .
+.It relay_host = host Ns Oo : Ns port Oc Ns Op (tls)
+The relay host name or IP address, optional port to connect to and
+an optional Transport Layer Security (TLS) flag in parentheses.
+The syntax is identical to
+.Em listen_address
+in the
+.Sx server
+section with one exception: the wild card
+.Ql *
+syntax is not supported.
+.Pp
+When this setting is enabled, messages from the client will be forwarded
+to one of the specified relay hosts instead of being stored locally.
+The
+.Ar host
+could be running an instance of
+.Nm sudo_logsrvd
+or another server that supports the
+.Xr sudo_logsrv.proto @mansectform@
+protocol.
+.Pp
+If multiple
+.Em relay_host
+lines are specified, the first available relay host will be used.
+.It retry_interval = number
+The number of seconds to wait after a connection error before making
+a new attempt to forward a message to a relay host.
+The default value is
+.Em 30 .
+.It store_first = boolean
+If true,
+.Nm sudo_logsrvd
+will store logs locally before relaying them.
+Once the log is complete, a connection to the relay host is opened
+and the log is relayed.
+If the network connection is interrupted before the log can be fully
+transferred, it will be retransmitted later.
+The default is to relay logs in real-time.
+.It tcp_keepalive = boolean
+If true,
+.Nm sudo_logsrvd
+will enable the TCP keepalive socket option on the relay connection.
+This enables the periodic transmission of keepalive messages to the relay
+server.
+If the relay does not respond to a message in time, the connection will
+be closed.
+.It timeout = number
+The amount of time, in seconds,
+.Nm sudo_logsrvd
+will wait for the relay server to respond after a connection has succeeded.
+A value of 0 will disable the timeout.
+The default value is
+.Em 30 .
+.It tls_cacert = path
+The path to a certificate authority bundle file, in PEM format,
+to use instead of the system's default certificate authority database
+when authenticating clients.
+The default is to use the value specified in the
+.Sx server
+section, or the system's default certificate authority database if
+no value is set.
+.It tls_cert = path
+The path to the server's certificate file, in PEM format.
+The default is to use the value specified in the
+.Sx server
+section.
+.It tls_checkpeer = bool
+If true, the relay host's certificate will be validated by
+.Nm sudo_logsrvd ;
+connections to a relay without a valid certificate will fail.
+If false, no validation of relay certificates will be performed.
+It true and relay certificates are created using a private certificate
+authority, the
+.Em tls_cacert
+setting must be set to a CA bundle that contains the CA certificate
+used to generate the relay certificate.
+The default is to use the value specified in the
+.Sx server
+section.
+.It tls_ciphers_v12 = string
+A list of ciphers to use for connections secured by TLS version 1.2 only,
+separated by a colon
+.Ql :\& .
+See the
+.Sx CIPHER LIST FORMAT
+section in
+.Xr openssl-ciphers 1
+for full details.
+The default is to use the value specified in the
+.Sx server
+section.
+.It tls_ciphers_v13 = string
+A list of ciphers to use for connections secured by TLS version 1.3 only,
+separated by a colon
+.Ql :\& .
+Supported cipher suites depend on the version of OpenSSL used,
+see the
+.Sx server
+section for more information.
+The default is to use the value specified in the
+.Sx server
+section.
+.It tls_dhparams = path
+The path to a file containing custom Diffie-Hellman parameters in PEM format.
+The default is to use the value specified in the
+.Sx server
+section.
+.It tls_key = path
+The path to the server's private key file, in PEM format.
+The default is to use the value specified in the
+.Sx server
+section.
+.It tls_verify = bool
+If true, the server's certificate used for relaying will be verified at startup.
+If false, no verification is performed of the server certificate.
+When using self-signed certificates without a certificate authority,
+this setting should be set to false.
+The default is to use the value specified in the
+.Sx server
+section.
+.El
+.Ss iolog
+The
+.Em iolog
+section configures I/O log parameters.
+These settings are identical to the I/O configuration in
+.Xr sudoers @mansectform@ .
+The following keys are recognized:
+.Bl -tag -width 4n
+.It iolog_compress = boolean
+If set, I/O logs will be compressed using
+.Sy zlib .
+Enabling compression can make it harder to view the logs in real-time as
+the program is executing due to buffering.
+The default value is
+.Em false .
+.It iolog_dir = path
+The top-level directory to use when constructing the path
+name for the I/O log directory.
+The session sequence number, if any, is stored in the directory.
+The default value is
+.Pa @iolog_dir@ .
+.Pp
+The following percent
+.Pq Ql %
+escape sequences are supported:
+.Bl -tag -width 4n
+.It %{seq}
+expanded to a monotonically increasing base-36 sequence number, such as 0100A5,
+where every two digits are used to form a new directory, e.g.,
+.Pa 01/00/A5
+.It %{user}
+expanded to the invoking user's login name
+.It %{group}
+expanded to the name of the invoking user's real group-ID
+.It %{runas_user}
+expanded to the login name of the user the command will
+be run as (e.g., root)
+.It %{runas_group}
+expanded to the group name of the user the command will
+be run as (e.g., wheel)
+.It %{hostname}
+expanded to the local host name without the domain name
+.It %{command}
+expanded to the base name of the command being run
+.El
+.Pp
+In addition, any escape sequences supported by the system's
+.Xr strftime 3
+function will be expanded.
+.Pp
+To include a literal
+.Ql %
+character, the string
+.Ql %%
+should be used.
+.It iolog_file = path
+The path name, relative to
+.Em iolog_dir ,
+in which to store I/O logs.
+It is possible for
+.Em iolog_file
+to contain directory components.
+The default value is
+.Dq %{seq} .
+.Pp
+See the
+.Em iolog_dir
+setting above for a list of supported percent
+.Pq Ql %
+escape sequences.
+.Pp
+In addition to the escape sequences, path names that end in six or
+more
+.Em X Ns s
+will have the
+.Em X Ns s
+replaced with a unique combination of digits and letters, similar to the
+.Xr mktemp 3
+function.
+.Pp
+If the path created by concatenating
+.Em iolog_dir
+and
+.Em iolog_file
+already exists, the existing I/O log file will be truncated and
+overwritten unless
+.Em iolog_file
+ends in six or
+more
+.Em X Ns s .
+.It iolog_flush = boolean
+If set, I/O log data is flushed to disk after each write instead of
+buffering it.
+This makes it possible to view the logs in real-time as the program is
+executing but may significantly reduce the effectiveness
+of I/O log compression.
+I/O logs are always flushed before sending a commit point to the client
+regardless of this setting.
+The default value is
+.Em true .
+.It iolog_group = name
+The group name to look up when setting the group-ID on new I/O log
+files and directories.
+If
+.Em iolog_group
+is not set,
+the primary group-ID of the user specified by
+.Em iolog_user is used.
+If neither
+.Em iolog_group
+nor
+.Em iolog_user
+are set, I/O log files and directories are created with group-ID 0.
+.It iolog_mode = mode
+The file mode to use when creating I/O log files.
+Mode bits for read and write permissions for owner, group, or other
+are honored, everything else is ignored.
+The file permissions will always include the owner read and
+write bits, even if they are not present in the specified mode.
+When creating I/O log directories, search (execute) bits are added
+to match the read and write bits specified by
+.Em iolog_mode .
+The default value is
+.Em 0600 .
+.It iolog_user = name
+The user name to look up when setting the owner of new
+I/O log files and directories.
+If
+.Em iolog_group
+is set, it will be used instead of the user's primary group-ID.
+By default, I/O log files and directories are created with user and
+group-ID 0.
+.It log_passwords = bool
+Most programs that require a user's password will disable echo before
+reading the password to avoid displaying the plaintext password on
+the screen.
+However, if terminal input is being logged,
+the password will still be present in the I/O log.
+If
+.Em log_passwords
+is set to
+.Em false ,
+.Nm sudo_logsrvd
+will attempt to prevent passwords from being logged.
+It does this by using the regular expressions in
+.Em passprompt_regex
+to match a password prompt in the terminal output buffer.
+When a match is found, input characters in the I/O log will be replaced with
+.Ql *
+until either a line feed or carriage return is found in the terminal input
+or a new terminal output buffer is received.
+If, however, a program displays characters as the user types them
+(such as
+.Nm sudo
+when the
+.Em pwfeedback
+option is set), only the
+first character of the password will be replaced in the I/O log.
+The default value is
+.Em true .
+.It maxseq = number
+The maximum sequence number that will be substituted for the
+.Dq %{seq}
+escape in the I/O log file (see the
+.Em iolog_dir
+description above for more information).
+While the value substituted for
+.Dq %{seq}
+is in base 36,
+.Em maxseq
+itself should be expressed in decimal.
+Values larger than 2176782336 (which corresponds to the
+base 36 sequence number
+.Dq ZZZZZZ )
+will be silently truncated to 2176782336.
+The default value is
+.Em 2176782336 .
+.It passprompt_regex = string
+One or more POSIX extended regular expressions used to
+match password prompts in the terminal output when
+.Em log_passwords
+is disabled.
+As an extension, if the regular expression begins with
+.Dq (?i) ,
+it will be matched in a case-insensitive manner.
+Multiple
+.Em passprompt_regex
+settings may be specified.
+Each regular expression is limited to 1024 characters.
+The default value is
+.Dq [Pp]assword[: ]* .
+.El
+.Ss eventlog
+The
+.Em eventlog
+section configures how (and if) security policy events are logged.
+.Bl -tag -width 4n
+.It log_type = string
+Where to log accept, reject, and alert events reported by the policy.
+Supported values are
+.Em syslog ,
+.Em logfile ,
+and
+.Em none .
+The default value is
+.Em syslog .
+.It log_exit = boolean
+If true,
+.Nm sudo_logsrvd
+will log an event when a command exits or is terminated by a signal.
+Defaults to
+.Em false .
+.It log_format = string
+The event log format.
+Supported log formats are
+.Dq sudo
+for traditional sudo-style logs and
+.Dq json
+for JSON-format logs.
+The JSON log entries contain the full contents of the accept, reject, exit
+and alert messages.
+The default value is
+.Em sudo .
+.El
+.Ss syslog
+The
+.Em syslog
+section configures how events are logged via
+.Xr syslog 3 .
+.Bl -tag -width 4n
+.It facility = string
+Syslog facility if syslog is being used for logging.
+Defaults to
+.Em @logfac@ .
+.Pp
+The following syslog facilities are supported:
+.Sy authpriv
+(if your
+OS supports it),
+.Sy auth ,
+.Sy daemon ,
+.Sy user ,
+.Sy local0 ,
+.Sy local1 ,
+.Sy local2 ,
+.Sy local3 ,
+.Sy local4 ,
+.Sy local5 ,
+.Sy local6 ,
+and
+.Sy local7 .
+.It accept_priority = string
+Syslog priority to use when the user is allowed to run a command and
+authentication is successful.
+Defaults to
+.Em @goodpri@ .
+.Pp
+The following syslog priorities are supported:
+.Sy alert ,
+.Sy crit ,
+.Sy debug ,
+.Sy emerg ,
+.Sy err ,
+.Sy info ,
+.Sy notice ,
+.Sy warning ,
+and
+.Sy none .
+Setting it to a value of
+.Sy none
+will disable logging of successful commands.
+.It reject_priority = string
+Syslog priority to use when the user is not allowed to run a command or
+when authentication is unsuccessful.
+Defaults to
+.Em @badpri@ .
+.Pp
+See
+.Em accept_priority
+for the list of supported syslog priorities.
+.It alert_priority = string
+Syslog priority to use for event log alert messages received from the client.
+Defaults to
+.Em @badpri@ .
+.Pp
+See
+.Em accept_priority
+for the list of supported syslog priorities.
+.It maxlen = number
+On many systems,
+.Xr syslog 3
+has a relatively small log buffer.
+IETF RFC 5424 states that syslog servers must support messages of
+at least 480 bytes and should support messages up to 2048 bytes.
+By default,
+.Nm sudo_logsrvd
+creates log messages up to 960 bytes which corresponds to the
+historic
+.Bx
+syslog implementation which used a 1024 byte buffer
+to store the message, date, hostname, and program name.
+.Pp
+To prevent syslog messages from being truncated,
+.Nm sudo_logsrvd
+will split up sudo-style log messages that are larger than
+.Em maxlen
+bytes.
+When a message is split, additional parts will include the string
+.Dq Pq command continued
+after the user name and before the continued command line arguments.
+JSON-format log entries are never split and are not affected by
+.Em maxlen .
+.It server_facility = string
+Syslog facility if syslog is being used for server warning messages.
+See above for a list of supported facilities.
+Defaults to
+.Em daemon
+.El
+.Ss logfile
+The
+.Em logfile
+section consists of settings related to logging to a plain file
+(not syslog).
+.Bl -tag -width 4n
+.It path = string
+The path to the file-based event log.
+This path must be fully-qualified and start with a
+.Sq /
+character.
+The default value is
+.Pa @logpath@ .
+.It time_format = string
+The string used when formatting the date and time for file-based event logs.
+Formatting is performed via the system's
+.Xr strftime 3
+function so any escape sequences supported by that function will be expanded.
+The default value is
+.Dq "%h %e %T"
+which produces dates like
+.Dq Oct 3 07:15:24
+in the
+.Ql C
+locale.
+.El
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/sudo_logsrvd.conf
+Sudo log server configuration file
+.El
+.Sh EXAMPLES
+.Bd -literal
+#
+# sudo logsrv daemon configuration
+#
+
+[server]
+# The host name or IP address and port to listen on with an optional TLS
+# flag. If no port is specified, port 30343 will be used for plaintext
+# connections and port 30344 will be used to TLS connections.
+# The following forms are accepted:
+# listen_address = hostname(tls)
+# listen_address = hostname:port(tls)
+# listen_address = IPv4_address(tls)
+# listen_address = IPv4_address:port(tls)
+# listen_address = [IPv6_address](tls)
+# listen_address = [IPv6_address]:port(tls)
+#
+# The (tls) suffix should be omitted for plaintext connections.
+#
+# Multiple listen_address settings may be specified.
+# The default is to listen on all addresses.
+#listen_address = *:30343
+#listen_address = *:30344(tls)
+
+# The file containing the ID of the running sudo_logsrvd process.
+#pid_file = @rundir@/sudo_logsrvd.pid
+
+# Where to log server warnings: none, stderr, syslog, or a path name.
+#server_log = syslog
+
+# If true, enable the SO_KEEPALIVE socket option on client connections.
+# Defaults to true.
+#tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the client to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+#timeout = 30
+
+# If true, the server will validate its own certificate at startup.
+# Defaults to true.
+#tls_verify = true
+
+# If true, client certificates will be validated by the server;
+# clients without a valid certificate will be unable to connect.
+# By default, client certs are not checked.
+#tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+#tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# Required for TLS connections.
+#tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# Required for TLS connections.
+#tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# This setting is only effective if the negotiated protocol is TLS version
+# 1.2. The default cipher list is HIGH:!aNULL.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default cipher list is TLS_AES_256_GCM_SHA384.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# If not set, the server will use the OpenSSL defaults.
+#tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[relay]
+# The host name or IP address and port to send logs to in relay mode.
+# The syntax is identical to listen_address with the exception of
+# the wild card ('*') syntax. When this setting is enabled, logs will
+# be relayed to the specified host instead of being stored locally.
+# This setting is not enabled by default.
+#relay_host = relayhost.dom.ain
+#relay_host = relayhost.dom.ain(tls)
+
+# The amount of time, in seconds, the server will wait for a connection
+# to the relay server to complete. A value of 0 will disable the timeout.
+# The default value is 30.
+#connect_timeout = 30
+
+# The directory to store messages in before they are sent to the relay.
+# Messages are stored in wire format.
+# The default value is @relay_dir@.
+#relay_dir = @relay_dir@
+
+# The number of seconds to wait after a connection error before
+# making a new attempt to forward a message to a relay host.
+# The default value is 30.
+#retry_interval = 30
+
+# Whether to store the log before relaying it. If true, enable store
+# and forward mode. If false, the client connection is immediately
+# relayed. Defaults to false.
+#store_first = true
+
+# If true, enable the SO_KEEPALIVE socket option on relay connections.
+# Defaults to true.
+#tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the relay to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+#timeout = 30
+
+# If true, the server's relay certificate will be verified at startup.
+# The default is to use the value in the [server] section.
+#tls_verify = true
+
+# Whether to verify the relay's certificate for TLS connections.
+# The default is to use the value in the [server] section.
+#tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+# The default is to use the value in the [server] section.
+#tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# The default is to use the certificate in the [server] section.
+#tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# The default is to use the key in the [server] section.
+#tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# this setting is only effective if the negotiated protocol is TLS version
+# 1.2. The default is to use the value in the [server] section.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default is to use the value in the [server] section.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# The default is to use the value in the [server] section.
+#tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[iolog]
+# The top-level directory to use when constructing the path name for the
+# I/O log directory. The session sequence number, if any, is stored here.
+#iolog_dir = @iolog_dir@
+
+# The path name, relative to iolog_dir, in which to store I/O logs.
+# It is possible for iolog_file to contain directory components.
+#iolog_file = %{seq}
+
+# If set, I/O logs will be compressed using zlib. Enabling compression can
+# make it harder to view the logs in real-time as the program is executing.
+#iolog_compress = false
+
+# If set, I/O log data is flushed to disk after each write instead of
+# buffering it. This makes it possible to view the logs in real-time
+# as the program is executing but reduces the effectiveness of compression.
+#iolog_flush = true
+
+# The group to use when creating new I/O log files and directories.
+# If iolog_group is not set, the primary group-ID of the user specified
+# by iolog_user is used. If neither iolog_group nor iolog_user
+# are set, I/O log files and directories are created with group-ID 0.
+#iolog_group = wheel
+
+# The user to use when setting the user-ID and group-ID of new I/O
+# log files and directories. If iolog_group is set, it will be used
+# instead of the user's primary group-ID. By default, I/O log files
+# and directories are created with user and group-ID 0.
+#iolog_user = root
+
+# The file mode to use when creating I/O log files. The file permissions
+# will always include the owner read and write bits, even if they are
+# not present in the specified mode. When creating I/O log directories,
+# search (execute) bits are added to match the read and write bits
+# specified by iolog_mode.
+#iolog_mode = 0600
+
+# If disabled, sudo_logsrvd will attempt to avoid logging plaintext
+# password in the terminal input using passprompt_regex.
+#log_passwords = true
+
+# The maximum sequence number that will be substituted for the "%{seq}"
+# escape in the I/O log file. While the value substituted for "%{seq}"
+# is in base 36, maxseq itself should be expressed in decimal. Values
+# larger than 2176782336 (which corresponds to the base 36 sequence
+# number "ZZZZZZ") will be silently truncated to 2176782336.
+#maxseq = 2176782336
+
+# One or more POSIX extended regular expressions used to match
+# password prompts in the terminal output when log_passwords is
+# disabled. Multiple passprompt_regex settings may be specified.
+#passprompt_regex = [Pp]assword[: ]*
+#passprompt_regex = [Pp]assword for [a-z0-9]+: *
+
+[eventlog]
+# Where to log accept, reject, exit, and alert events.
+# Accepted values are syslog, logfile, or none.
+# Defaults to syslog
+#log_type = syslog
+
+# Whether to log an event when a command exits or is terminated by a signal.
+# Defaults to false
+#log_exit = true
+
+# Event log format.
+# Currently only sudo-style event logs are supported.
+#log_format = sudo
+
+[syslog]
+# The maximum length of a syslog payload.
+# On many systems, syslog(3) has a relatively small log buffer.
+# IETF RFC 5424 states that syslog servers must support messages
+# of at least 480 bytes and should support messages up to 2048 bytes.
+# Messages larger than this value will be split into multiple messages.
+#maxlen = 960
+
+# The syslog facility to use for event log messages.
+# The following syslog facilities are supported: authpriv (if your OS
+# supports it), auth, daemon, user, local0, local1, local2, local3,
+# local4, local5, local6, and local7.
+#facility = @logfac@
+
+# Syslog priority to use for event log accept messages, when the command
+# is allowed by the security policy. The following syslog priorities are
+# supported: alert, crit, debug, emerg, err, info, notice, warning, none.
+#accept_priority = @goodpri@
+
+# Syslog priority to use for event log reject messages, when the command
+# is not allowed by the security policy.
+#reject_priority = @badpri@
+
+# Syslog priority to use for event log alert messages reported by the
+# client.
+#alert_priority = @badpri@
+
+# The syslog facility to use for server warning messages.
+# Defaults to daemon.
+#server_facility = daemon
+
+[logfile]
+# The path to the file-based event log.
+# This path must be fully-qualified and start with a '/' character.
+#path = @logpath@
+
+# The format string used when formatting the date and time for
+# file-based event logs. Formatting is performed via strftime(3) so
+# any format string supported by that function is allowed.
+#time_format = %h %e %T
+.Ed
+.Sh SEE ALSO
+.Xr strftime 3 ,
+.Xr sudo.conf @mansectform@ ,
+.Xr sudoers @mansectform@ ,
+.Xr sudo @mansectsu@ ,
+.Xr sudo_logsrvd @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS.md file in the
+.Nm sudo
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you believe you have found a bug in
+.Nm sudo ,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm sudo
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+.Nm sudo
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudo_logsrvd.man.in b/docs/sudo_logsrvd.man.in
new file mode 100644
index 0000000..eb93636
--- /dev/null
+++ b/docs/sudo_logsrvd.man.in
@@ -0,0 +1,479 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.TH "SUDO_LOGSRVD" "@mansectsu@" "January 16, 2023" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudo_logsrvd\fR
+\- sudo event and I/O log server
+.SH "SYNOPSIS"
+.HP 13n
+\fBsudo_logsrvd\fR
+[\fB\-hnV\fR]
+[\fB\-f\fR\ \fIfile\fR]
+[\fB\-R\fR\ \fIpercentage\fR]
+.SH "DESCRIPTION"
+\fBsudo_logsrvd\fR
+is a high-performance log server that accepts event and I/O logs from
+\fBsudo\fR.
+It can be used to implement centralized logging of
+\fBsudo\fR
+logs.
+The server has two modes of operation: local and relay.
+By default,
+\fBsudo_logsrvd\fR
+stores the logs locally but it can also be configured to
+relay them to another server that supports the
+sudo_logsrv.proto(@mansectform@)
+protocol.
+.PP
+When not relaying, event log entries may be logged either via
+syslog(3)
+or to a local file.
+I/O Logs stored locally by
+\fBsudo_logsrvd\fR
+can be replayed via the
+sudoreplay(@mansectsu@)
+utility in the same way as logs generated directly by the
+\fBsudoers\fR
+plugin.
+.PP
+The server also supports restarting interrupted log transfers.
+To distinguish completed I/O logs from incomplete ones, the
+I/O log timing file is set to be read-only when the log is complete.
+.PP
+Configuration parameters for
+\fBsudo_logsrvd\fR
+may be specified in the
+sudo_logsrvd.conf(@mansectform@)
+file or the file specified via the
+\fB\-f\fR
+option.
+.PP
+\fBsudo_logsrvd\fR
+rereads its configuration file when it receives SIGHUP and writes server
+state to the debug file (if one is configured) when it receives SIGUSR1.
+.PP
+The options are as follows:
+.TP 8n
+\fB\-f\fR \fIfile\fR, \fB\--file\fR=\fIfile\fR
+Read configuration from
+\fIfile\fR
+instead of the default,
+\fI@sysconfdir@/sudo_logsrvd.conf\fR.
+.TP 8n
+\fB\-h\fR, \fB\--help\fR
+Display a short help message to the standard output and exit.
+.TP 8n
+\fB\-n\fR, \fB\--no-fork\fR
+Run
+\fBsudo_logsrvd\fR
+in the foreground instead of detaching from the terminal and becoming
+a daemon.
+.TP 8n
+\fB\-R\fR \fIpercentage\fR, \fB\--random-drop\fR=\fIpercentage\fR
+For each message, there is a
+\fIpercentage\fR
+chance that the server will drop the connection.
+This is only intended for debugging the ability of a
+client to restart a connection.
+.TP 8n
+\fB\-V\fR, \fB\--version\fR
+Print the
+\fBsudo_logsrvd\fR
+version and exit.
+.SS "Securing server connections"
+The I/O log data sent to
+\fBsudo_logsrvd\fR
+may contain sensitive information such as passwords and should be
+secured using Transport Layer Security (TLS).
+Doing so requires having a signed certificate on the server and, if
+\fItls_checkpeer\fR
+is enabled in
+sudo_logsrvd.conf(@mansectform@),
+a signed certificate on the client as well.
+.PP
+The certificates can either be signed by a well-known Certificate
+Authority (CA), or a private CA can be used.
+Instructions for creating a private CA are included below in the
+\fIEXAMPLES\fR
+section.
+.SS "Debugging sudo_logsrvd"
+\fBsudo_logsrvd\fR
+supports a flexible debugging framework that is configured via
+\fIDebug\fR
+lines in the
+sudo.conf(@mansectform@)
+file.
+.PP
+For more information on configuring
+sudo.conf(@mansectform@),
+refer to its manual.
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/sudo.conf\fR
+Sudo front-end configuration
+.TP 26n
+\fI@sysconfdir@/sudo_logsrvd.conf\fR
+Sudo log server configuration file
+.TP 26n
+\fI@relay_dir@/incoming\fR
+Directory where new journals are stored when the
+\fIstore_first relay\fR
+setting is enabled.
+.TP 26n
+\fI@relay_dir@/outgoing\fR
+Directory where completed journals are stored when the
+\fIstore_first relay\fR
+setting is enabled.
+.TP 26n
+\fI@iolog_dir@\fR
+Default I/O log file location
+.TP 26n
+\fI@rundir@/sudo_logsrvd.pid\fR
+.br
+Process ID file for
+\fBsudo_logsrvd\fR
+.SH "EXAMPLES"
+.SS "Creating self-signed certificates"
+Unless you are using certificates signed by a well-known Certificate
+Authority (or a local enterprise CA), you will need to create your
+own CA that can sign the certificates used by
+\fBsudo_logsrvd\fR,
+\fBsudo_sendlog\fR,
+and the
+\fBsudoers\fR
+plugin.
+The following steps use the
+openssl(1)
+command to create keys and certificates.
+.SS "Initial setup"
+First, we need to create a directory structure to store the
+files for the CA.
+We'll create a new directory hierarchy in
+\fI/etc/ssl/sudo\fR
+for this purpose.
+.nf
+.sp
+.RS 4n
+# mkdir /etc/ssl/sudo
+# cd /etc/ssl/sudo
+# mkdir certs csr newcerts private
+# chmod 700 private
+# touch index.txt
+# echo 1000 > serial
+.RE
+.fi
+.PP
+The serial and index.txt files are used to keep track of signed certificates.
+.PP
+Next, we need to make a copy of the openssl.conf file and customize
+it for our new CA.
+The path to openssl.cnf is system-dependent but
+\fI/etc/ssl/openssl.cnf\fR
+is the most common location.
+You will need to adjust the example below if it has a different location on
+your system.
+.nf
+.sp
+.RS 4n
+# cp /etc/ssl/openssl.cnf .
+.RE
+.fi
+.PP
+Now edit the
+\fIopenssl.cnf\fR
+file in the current directory and make sure it contains
+\(lqca\(rq,
+\(lqCA_default\(rq,
+\(lqv3_ca\(rq,
+and
+\(lqusr_cert\(rq
+sections.
+Those sections should include at least the following settings:
+.nf
+.sp
+.RS 4n
+[ ca ]
+default_ca = CA_default
+
+[ CA_default ]
+dir = /etc/ssl/sudo
+certs = $dir/certs
+database = $dir/index.txt
+certificate = $dir/cacert.pem
+serial = $dir/serial
+
+[ v3_ca ]
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer
+basicConstraints = critical,CA:true
+keyUsage = cRLSign, keyCertSign
+
+[ usr_cert ]
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, \e
+ keyEncipherment
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid,issuer
+.RE
+.fi
+.PP
+If your
+\fIopenssl.conf\fR
+file already has a
+\(lqCA_default\(rq
+section, you may only need to modify the
+\(lqdir\(rq
+setting and enable the
+\(lqkeyUsage\(rq
+settings if they are commented out.
+.SS "Creating the CA key and certificate"
+In order to create and sign our own certificates, we need to create
+a private key and a certificate for the root of the CA.
+First, create the private key and protect it with a pass phrase:
+.nf
+.sp
+.RS 4n
+# openssl genrsa -aes256 -out private/cakey.pem 4096
+# chmod 400 private/cakey.pem
+.RE
+.fi
+.PP
+Next, generate the root certificate, using appropriate values for
+the site-specific fields:
+.nf
+.sp
+.RS 4n
+# openssl req -config openssl.cnf -key private/cakey.pem \e
+ -new -x509 -days 7300 -sha256 -extensions v3_ca \e
+ -out cacert.pem
+
+Enter pass phrase for private/cakey.pem:
+You are about to be asked to enter information that will be
+incorporated into your certificate request.
+What you are about to enter is what is called a Distinguished Name
+or a DN.
+There are quite a few fields but you can leave some blank.
+For some fields there will be a default value,
+If you enter '.', the field will be left blank.
+-----
+Country Name (2 letter code) [AU]:US
+State or Province Name (full name) [Some-State]:Colorado
+Locality Name (eg, city) []:
+Organization Name (eg, company) [Internet Widgits Pty Ltd]:sudo
+Organizational Unit Name (eg, section) []:sudo Certificate Authority
+Common Name (e.g., server FQDN or YOUR name) []:sudo Root CA
+Email Address []:
+
+# chmod 444 cacert.pem
+.RE
+.fi
+.PP
+Finally, verify the root certificate:
+.nf
+.sp
+.RS 4n
+# openssl x509 -noout -text -in cacert.pem
+.RE
+.fi
+.SS "Creating and signing certificates"
+The server and client certificates will be signed by the previously
+created root CA.
+Usually, the root CA is not used to sign server/client certificates
+directly.
+Instead, intermediate certificates are created and signed with the
+root CA and the intermediate certs are used to sign CSRs (Certificate
+Signing Request).
+In this example we'll skip this part for simplicity's sake and sign the
+CSRs with the root CA.
+.PP
+First, generate the private key without a pass phrase.
+.nf
+.sp
+.RS 4n
+# openssl genrsa -out private/logsrvd_key.pem 2048
+# chmod 400 private/logsrvd_key.pem
+.RE
+.fi
+.PP
+Next, create a certificate signing request (CSR) for the server's certificate.
+The organization name must match the name given in the root certificate.
+The common name should be either the server's IP address or a fully
+qualified domain name.
+.nf
+.sp
+.RS 4n
+# openssl req -config openssl.cnf -key private/logsrvd_key.pem -new \e
+ -sha256 -out csr/logsrvd_csr.pem
+
+Enter pass phrase for private/logsrvd_key.pem:
+You are about to be asked to enter information that will be
+incorporated into your certificate request.
+What you are about to enter is what is called a Distinguished Name
+or a DN.
+There are quite a few fields but you can leave some blank.
+For some fields there will be a default value,
+If you enter '.', the field will be left blank.
+-----
+Country Name (2 letter code) [AU]:US
+State or Province Name (full name) [Some-State]:Colorado
+Locality Name (eg, city) []:
+Organization Name (eg, company) [Internet Widgits Pty Ltd]:sudo
+Organizational Unit Name (eg, section) []:sudo log server
+Common Name (e.g., server FQDN or YOUR name) []:logserver.example.com
+Email Address []:
+
+Please enter the following 'extra' attributes
+to be sent with your certificate request
+A challenge password []:
+An optional company name []:
+.RE
+.fi
+.PP
+Now sign the CSR that was just created:
+.nf
+.sp
+.RS 4n
+# openssl ca -config openssl.cnf -days 375 -notext -md sha256 \e
+ -in csr/logsrvd_csr.pem -out certs/logsrvd_cert.pem
+
+Using configuration from openssl.cnf
+Enter pass phrase for ./private/cakey.pem:
+Check that the request matches the signature
+Signature ok
+Certificate Details:
+ Serial Number: 4096 (0x1000)
+ Validity
+ Not Before: Nov 11 14:05:05 2019 GMT
+ Not After : Nov 20 14:05:05 2020 GMT
+ Subject:
+ countryName = US
+ stateOrProvinceName = Colorado
+ organizationName = sudo
+ organizationalUnitName = sudo log server
+ commonName = logserve.example.com
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 4C:50:F9:D0:BE:1A:4C:B2:AC:90:76:56:C7:9E:16:AE:E6:9E:E5:B5
+ X509v3 Authority Key Identifier:
+ keyid:D7:91:24:16:B1:03:06:65:1A:7A:6E:CF:51:E9:5C:CB:7A:95:3E:0C
+
+Certificate is to be certified until Nov 20 14:05:05 2020 GMT (375 days)
+Sign the certificate? [y/n]:y
+
+1 out of 1 certificate requests certified, commit? [y/n]y
+Write out database with 1 new entries
+Data Base Updated
+.RE
+.fi
+.PP
+Finally, verify the new certificate:
+.nf
+.sp
+.RS 4n
+# openssl verify -CAfile cacert.pem certs/logsrvd_cert.pem
+certs/logsrvd_cert.pem: OK
+.RE
+.fi
+.PP
+The
+\fI/etc/ssl/sudo/certs\fR
+directory now contains a signed and verified certificate for use with
+\fBsudo_logsrvd\fR.
+.PP
+To generate a client certificate, repeat the process above using
+a different file name.
+.SS "Configuring sudo_logsrvd to use TLS"
+To use TLS for client/server communication, both
+\fBsudo_logsrvd\fR
+and the
+\fBsudoers\fR
+plugin need to be configured to use TLS.
+Configuring
+\fBsudo_logsrvd\fR
+for TLS requires the following settings, assuming the same path
+names used earlier:
+.nf
+.sp
+.RS 4n
+# Listen on port 30344 for TLS connections to any address.
+listen_address = *:30344(tls)
+
+# Path to the certificate authority bundle file in PEM format.
+tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+.RE
+.fi
+.PP
+The root CA cert
+(\fIcacert.pem\fR)
+must be installed on the system running
+\fBsudo_logsrvd\fR.
+If peer authentication is enabled on the client, a copy of
+\fIcacert.pem\fR
+must be present on the client system too.
+.SH "SEE ALSO"
+sudo.conf(@mansectform@),
+sudo_logsrvd.conf(@mansectform@),
+sudoers(@mansectform@),
+sudo(@mansectsu@),
+sudo_sendlog(@mansectsu@),
+sudoreplay(@mansectsu@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS.md file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you believe you have found a bug in
+\fBsudo_logsrvd\fR,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo_logsrvd\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudo_logsrvd.mdoc.in b/docs/sudo_logsrvd.mdoc.in
new file mode 100644
index 0000000..bde5ff6
--- /dev/null
+++ b/docs/sudo_logsrvd.mdoc.in
@@ -0,0 +1,435 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd January 16, 2023
+.Dt SUDO_LOGSRVD @mansectsu@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudo_logsrvd
+.Nd sudo event and I/O log server
+.Sh SYNOPSIS
+.Nm sudo_logsrvd
+.Op Fl hnV
+.Op Fl f Ar file
+.Op Fl R Ar percentage
+.Sh DESCRIPTION
+.Nm
+is a high-performance log server that accepts event and I/O logs from
+.Nm sudo .
+It can be used to implement centralized logging of
+.Nm sudo
+logs.
+The server has two modes of operation: local and relay.
+By default,
+.Nm
+stores the logs locally but it can also be configured to
+relay them to another server that supports the
+.Xr sudo_logsrv.proto @mansectform@
+protocol.
+.Pp
+When not relaying, event log entries may be logged either via
+.Xr syslog 3
+or to a local file.
+I/O Logs stored locally by
+.Nm
+can be replayed via the
+.Xr sudoreplay @mansectsu@
+utility in the same way as logs generated directly by the
+.Nm sudoers
+plugin.
+.Pp
+The server also supports restarting interrupted log transfers.
+To distinguish completed I/O logs from incomplete ones, the
+I/O log timing file is set to be read-only when the log is complete.
+.Pp
+Configuration parameters for
+.Nm
+may be specified in the
+.Xr sudo_logsrvd.conf @mansectform@
+file or the file specified via the
+.Fl f
+option.
+.Pp
+.Nm
+rereads its configuration file when it receives SIGHUP and writes server
+state to the debug file (if one is configured) when it receives SIGUSR1.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl f Ar file , Fl -file Ns = Ns Ar file
+Read configuration from
+.Ar file
+instead of the default,
+.Pa @sysconfdir@/sudo_logsrvd.conf .
+.It Fl h , -help
+Display a short help message to the standard output and exit.
+.It Fl n , -no-fork
+Run
+.Nm
+in the foreground instead of detaching from the terminal and becoming
+a daemon.
+.It Fl R Ar percentage , Fl -random-drop Ns = Ns Ar percentage
+For each message, there is a
+.Ar percentage
+chance that the server will drop the connection.
+This is only intended for debugging the ability of a
+client to restart a connection.
+.It Fl V , -version
+Print the
+.Nm
+version and exit.
+.El
+.Ss Securing server connections
+The I/O log data sent to
+.Nm
+may contain sensitive information such as passwords and should be
+secured using Transport Layer Security (TLS).
+Doing so requires having a signed certificate on the server and, if
+.Em tls_checkpeer
+is enabled in
+.Xr sudo_logsrvd.conf @mansectform@ ,
+a signed certificate on the client as well.
+.Pp
+The certificates can either be signed by a well-known Certificate
+Authority (CA), or a private CA can be used.
+Instructions for creating a private CA are included below in the
+.Sx EXAMPLES
+section.
+.Ss Debugging sudo_logsrvd
+.Nm
+supports a flexible debugging framework that is configured via
+.Em Debug
+lines in the
+.Xr sudo.conf @mansectform@
+file.
+.Pp
+For more information on configuring
+.Xr sudo.conf @mansectform@ ,
+refer to its manual.
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/sudo.conf
+Sudo front-end configuration
+.It Pa @sysconfdir@/sudo_logsrvd.conf
+Sudo log server configuration file
+.It Pa @relay_dir@/incoming
+Directory where new journals are stored when the
+.Em store_first relay
+setting is enabled.
+.It Pa @relay_dir@/outgoing
+Directory where completed journals are stored when the
+.Em store_first relay
+setting is enabled.
+.It Pa @iolog_dir@
+Default I/O log file location
+.It Pa @rundir@/sudo_logsrvd.pid
+Process ID file for
+.Nm
+.El
+.Sh EXAMPLES
+.Ss Creating self-signed certificates
+Unless you are using certificates signed by a well-known Certificate
+Authority (or a local enterprise CA), you will need to create your
+own CA that can sign the certificates used by
+.Nm ,
+.Nm sudo_sendlog ,
+and the
+.Nm sudoers
+plugin.
+The following steps use the
+.Xr openssl 1
+command to create keys and certificates.
+.Ss Initial setup
+First, we need to create a directory structure to store the
+files for the CA.
+We'll create a new directory hierarchy in
+.Pa /etc/ssl/sudo
+for this purpose.
+.Bd -literal -offset 4n
+# mkdir /etc/ssl/sudo
+# cd /etc/ssl/sudo
+# mkdir certs csr newcerts private
+# chmod 700 private
+# touch index.txt
+# echo 1000 > serial
+.Ed
+.Pp
+The serial and index.txt files are used to keep track of signed certificates.
+.Pp
+Next, we need to make a copy of the openssl.conf file and customize
+it for our new CA.
+The path to openssl.cnf is system-dependent but
+.Pa /etc/ssl/openssl.cnf
+is the most common location.
+You will need to adjust the example below if it has a different location on
+your system.
+.Bd -literal -offset 4n
+# cp /etc/ssl/openssl.cnf .
+.Ed
+.Pp
+Now edit the
+.Pa openssl.cnf
+file in the current directory and make sure it contains
+.Dq ca ,
+.Dq CA_default ,
+.Dq v3_ca ,
+and
+.Dq usr_cert
+sections.
+Those sections should include at least the following settings:
+.Bd -literal -offset 4n
+[ ca ]
+default_ca = CA_default
+
+[ CA_default ]
+dir = /etc/ssl/sudo
+certs = $dir/certs
+database = $dir/index.txt
+certificate = $dir/cacert.pem
+serial = $dir/serial
+
+[ v3_ca ]
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer
+basicConstraints = critical,CA:true
+keyUsage = cRLSign, keyCertSign
+
+[ usr_cert ]
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, \e
+ keyEncipherment
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid,issuer
+.Ed
+.Pp
+If your
+.Pa openssl.conf
+file already has a
+.Dq CA_default
+section, you may only need to modify the
+.Dq dir
+setting and enable the
+.Dq keyUsage
+settings if they are commented out.
+.Ss Creating the CA key and certificate
+In order to create and sign our own certificates, we need to create
+a private key and a certificate for the root of the CA.
+First, create the private key and protect it with a pass phrase:
+.Bd -literal -offset 4n
+# openssl genrsa -aes256 -out private/cakey.pem 4096
+# chmod 400 private/cakey.pem
+.Ed
+.Pp
+Next, generate the root certificate, using appropriate values for
+the site-specific fields:
+.Bd -literal -offset 4n
+# openssl req -config openssl.cnf -key private/cakey.pem \e
+ -new -x509 -days 7300 -sha256 -extensions v3_ca \e
+ -out cacert.pem
+
+Enter pass phrase for private/cakey.pem:
+You are about to be asked to enter information that will be
+incorporated into your certificate request.
+What you are about to enter is what is called a Distinguished Name
+or a DN.
+There are quite a few fields but you can leave some blank.
+For some fields there will be a default value,
+If you enter '.', the field will be left blank.
+-----
+Country Name (2 letter code) [AU]:US
+State or Province Name (full name) [Some-State]:Colorado
+Locality Name (eg, city) []:
+Organization Name (eg, company) [Internet Widgits Pty Ltd]:sudo
+Organizational Unit Name (eg, section) []:sudo Certificate Authority
+Common Name (e.g., server FQDN or YOUR name) []:sudo Root CA
+Email Address []:
+
+# chmod 444 cacert.pem
+.Ed
+.Pp
+Finally, verify the root certificate:
+.Bd -literal -offset 4n
+# openssl x509 -noout -text -in cacert.pem
+.Ed
+.Ss Creating and signing certificates
+The server and client certificates will be signed by the previously
+created root CA.
+Usually, the root CA is not used to sign server/client certificates
+directly.
+Instead, intermediate certificates are created and signed with the
+root CA and the intermediate certs are used to sign CSRs (Certificate
+Signing Request).
+In this example we'll skip this part for simplicity's sake and sign the
+CSRs with the root CA.
+.Pp
+First, generate the private key without a pass phrase.
+.Bd -literal -offset 4n
+# openssl genrsa -out private/logsrvd_key.pem 2048
+# chmod 400 private/logsrvd_key.pem
+.Ed
+.Pp
+Next, create a certificate signing request (CSR) for the server's certificate.
+The organization name must match the name given in the root certificate.
+The common name should be either the server's IP address or a fully
+qualified domain name.
+.Bd -literal -offset 4n
+# openssl req -config openssl.cnf -key private/logsrvd_key.pem -new \e
+ -sha256 -out csr/logsrvd_csr.pem
+
+Enter pass phrase for private/logsrvd_key.pem:
+You are about to be asked to enter information that will be
+incorporated into your certificate request.
+What you are about to enter is what is called a Distinguished Name
+or a DN.
+There are quite a few fields but you can leave some blank.
+For some fields there will be a default value,
+If you enter '.', the field will be left blank.
+-----
+Country Name (2 letter code) [AU]:US
+State or Province Name (full name) [Some-State]:Colorado
+Locality Name (eg, city) []:
+Organization Name (eg, company) [Internet Widgits Pty Ltd]:sudo
+Organizational Unit Name (eg, section) []:sudo log server
+Common Name (e.g., server FQDN or YOUR name) []:logserver.example.com
+Email Address []:
+
+Please enter the following 'extra' attributes
+to be sent with your certificate request
+A challenge password []:
+An optional company name []:
+.Ed
+.Pp
+Now sign the CSR that was just created:
+.Bd -literal -offset 4n
+# openssl ca -config openssl.cnf -days 375 -notext -md sha256 \e
+ -in csr/logsrvd_csr.pem -out certs/logsrvd_cert.pem
+
+Using configuration from openssl.cnf
+Enter pass phrase for ./private/cakey.pem:
+Check that the request matches the signature
+Signature ok
+Certificate Details:
+ Serial Number: 4096 (0x1000)
+ Validity
+ Not Before: Nov 11 14:05:05 2019 GMT
+ Not After : Nov 20 14:05:05 2020 GMT
+ Subject:
+ countryName = US
+ stateOrProvinceName = Colorado
+ organizationName = sudo
+ organizationalUnitName = sudo log server
+ commonName = logserve.example.com
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ X509v3 Key Usage:
+ Digital Signature, Non Repudiation, Key Encipherment
+ X509v3 Subject Key Identifier:
+ 4C:50:F9:D0:BE:1A:4C:B2:AC:90:76:56:C7:9E:16:AE:E6:9E:E5:B5
+ X509v3 Authority Key Identifier:
+ keyid:D7:91:24:16:B1:03:06:65:1A:7A:6E:CF:51:E9:5C:CB:7A:95:3E:0C
+
+Certificate is to be certified until Nov 20 14:05:05 2020 GMT (375 days)
+Sign the certificate? [y/n]:y
+
+1 out of 1 certificate requests certified, commit? [y/n]y
+Write out database with 1 new entries
+Data Base Updated
+.Ed
+.Pp
+Finally, verify the new certificate:
+.Bd -literal -offset 4n
+# openssl verify -CAfile cacert.pem certs/logsrvd_cert.pem
+certs/logsrvd_cert.pem: OK
+.Ed
+.Pp
+The
+.Pa /etc/ssl/sudo/certs
+directory now contains a signed and verified certificate for use with
+.Nm sudo_logsrvd .
+.Pp
+To generate a client certificate, repeat the process above using
+a different file name.
+.Ss Configuring sudo_logsrvd to use TLS
+To use TLS for client/server communication, both
+.Nm
+and the
+.Nm sudoers
+plugin need to be configured to use TLS.
+Configuring
+.Nm
+for TLS requires the following settings, assuming the same path
+names used earlier:
+.Bd -literal -offset 4n
+# Listen on port 30344 for TLS connections to any address.
+listen_address = *:30344(tls)
+
+# Path to the certificate authority bundle file in PEM format.
+tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+.Ed
+.Pp
+The root CA cert
+.Pq Pa cacert.pem
+must be installed on the system running
+.Nm .
+If peer authentication is enabled on the client, a copy of
+.Pa cacert.pem
+must be present on the client system too.
+.Sh SEE ALSO
+.Xr sudo.conf @mansectform@ ,
+.Xr sudo_logsrvd.conf @mansectform@ ,
+.Xr sudoers @mansectform@ ,
+.Xr sudo @mansectsu@ ,
+.Xr sudo_sendlog @mansectsu@ ,
+.Xr sudoreplay @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS.md file in the
+.Nm sudo
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you believe you have found a bug in
+.Nm ,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+.Nm sudo
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudo_plugin.man.in b/docs/sudo_plugin.man.in
new file mode 100644
index 0000000..c36fe00
--- /dev/null
+++ b/docs/sudo_plugin.man.in
@@ -0,0 +1,5512 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2009-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.TH "SUDO_PLUGIN" "5" "July 10, 2023" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudo_plugin\fR
+\- Sudo Plugin API
+.SH "DESCRIPTION"
+Starting with version 1.8,
+\fBsudo\fR
+supports a plugin API
+for policy and session logging.
+Plugins may be compiled as dynamic shared objects (the default on
+systems that support them) or compiled statically into the
+\fBsudo\fR
+binary itself.
+By default, the
+\fBsudoers\fR
+plugin provides audit, security policy and I/O logging capabilities.
+Via the plugin API,
+\fBsudo\fR
+can be configured to use alternate plugins provided by third parties.
+The plugins to be used are specified in the
+sudo.conf(@mansectform@)
+file.
+.PP
+The API is versioned with a major and minor number.
+The minor version number is incremented when additions are made.
+The major number is incremented when incompatible changes are made.
+A plugin should be check the version passed to it and make sure that the
+major version matches.
+.PP
+The plugin API is defined by the
+<\fIsudo_plugin.h\fR>
+header file.
+.SS "Policy plugin API"
+A policy plugin must declare and populate a
+\fIstruct policy_plugin\fR
+in the global scope.
+This structure contains pointers to the functions that implement the
+\fBsudo\fR
+policy checks.
+The name of the symbol should be specified in
+sudo.conf(@mansectform@)
+along with a path to the plugin so that
+\fBsudo\fR
+can load it.
+.nf
+.sp
+.RS 0n
+struct policy_plugin {
+#define SUDO_POLICY_PLUGIN 1
+ unsigned int type; /* always SUDO_POLICY_PLUGIN */
+ unsigned int version; /* always SUDO_API_VERSION */
+ int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], char * const user_env[],
+ char * const plugin_options[], const char **errstr);
+ void (*close)(int exit_status, int error);
+ int (*show_version)(int verbose);
+ int (*check_policy)(int argc, char * const argv[],
+ char *env_add[], char **command_info[],
+ char **argv_out[], char **user_env_out[], const char **errstr);
+ int (*list)(int argc, char * const argv[], int verbose,
+ const char *user, const char **errstr);
+ int (*validate)(const char **errstr);
+ void (*invalidate)(int rmcred);
+ int (*init_session)(struct passwd *pwd, char **user_env[],
+ const char **errstr);
+ void (*register_hooks)(int version,
+ int (*register_hook)(struct sudo_hook *hook));
+ void (*deregister_hooks)(int version,
+ int (*deregister_hook)(struct sudo_hook *hook));
+ struct sudo_plugin_event * (*event_alloc)(void);
+};
+.RE
+.fi
+.PP
+A
+\fIstruct policy_plugin\fR
+has the following fields:
+.TP 6n
+\fItype\fR
+The
+\fItype\fR
+field should always be set to SUDO_POLICY_PLUGIN.
+.TP 6n
+\fIversion\fR
+The
+\fIversion\fR
+field should be set to
+\fRSUDO_API_VERSION\fR.
+.sp
+This allows
+\fBsudo\fR
+to determine the API version the plugin was
+built against.
+.TP 6n
+\fIopen\fR
+.nf
+.RS 6n
+int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], char * const user_env[],
+ char * const plugin_options[], const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+\fBsudo\fR
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBsudo_plugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional error information to the user.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIversion\fR
+The version passed in by
+\fBsudo\fR
+allows the plugin to determine the
+major and minor version number of the plugin API supported by
+\fBsudo\fR.
+.TP 6n
+\fIconversation\fR
+A pointer to the
+\fBconversation\fR()
+function that can be used by the plugin to interact with the user (see
+\fIConversation API\fR
+for details).
+Returns 0 on success and \-1 on failure.
+.TP 6n
+\fIsudo_plugin_printf\fR
+A pointer to a
+\fBprintf\fR()-style
+function that may be used to display informational or error messages (see
+\fIConversation API\fR
+for details).
+Returns the number of characters printed on success and \-1 on failure.
+.TP 6n
+\fIsettings\fR
+A vector of user-supplied
+\fBsudo\fR
+settings in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+These settings correspond to options the user specified when running
+\fBsudo\fR.
+As such, they will only be present when the corresponding option has
+been specified on the command line.
+.sp
+When parsing
+\fIsettings\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one itself but the
+\fIvalue\fR
+might.
+.sp
+The following values may be set by
+\fBsudo\fR:
+.PP
+.RS 6n
+.PD 0
+.TP 6n
+bsdauth_type=string
+Authentication type, if specified by the
+\fB\-a\fR
+option, to use on
+systems where
+BSD
+authentication is supported.
+.PD
+.TP 6n
+closefrom=number
+If specified, the user has requested via the
+\fB\-C\fR
+option that
+\fBsudo\fR
+close all files descriptors with a value of
+\fInumber\fR
+or higher.
+The plugin may optionally pass this, or another value, back in the
+\fIcommand_info\fR
+list.
+.TP 6n
+cmnd_chroot=string
+The root directory (see
+chroot(2))
+to run the command in, as specified by the user via the
+\fB\-R\fR
+option.
+The plugin may ignore or restrict the user's ability to specify a new
+root directory.
+Only available starting with API version 1.16.
+.TP 6n
+cmnd_cwd=string
+The working directory to run the command in, as specified by the user via the
+\fB\-D\fR
+option.
+The plugin may ignore or restrict the user's ability to specify a new
+working directory.
+Only available starting with API version 1.16.
+.TP 6n
+debug_flags=string
+A debug file path name followed by a space and a comma-separated
+list of debug flags that correspond to the plugin's
+\fIDebug\fR
+entry in
+sudo.conf(@mansectform@),
+if there is one.
+The flags are passed to the plugin exactly as they appear in
+sudo.conf(@mansectform@).
+The syntax used by
+\fBsudo\fR
+and the
+\fBsudoers\fR
+plugin is
+\fIsubsystem\fR@\fIpriority\fR
+but a plugin is free to use a different
+format so long as it does not include a comma
+(\(oq,\&\(cq).
+Prior to
+\fBsudo\fR
+1.8.12, there was no way to specify plugin-specific
+\fIdebug_flags\fR
+so the value was always the same as that used by the
+\fBsudo\fR
+front-end and did not include a path name, only the flags themselves.
+As of version 1.7 of the plugin interface,
+\fBsudo\fR
+will only pass
+\fIdebug_flags\fR
+if
+sudo.conf(@mansectform@)
+contains a plugin-specific
+\fIDebug\fR
+entry.
+.TP 6n
+ignore_ticket=bool
+Set to true if the user specified the
+\fB\-k\fR
+option along with a
+command, indicating that the user wishes to ignore any cached
+authentication credentials.
+\fIimplied_shell\fR
+to true.
+This allows
+\fBsudo\fR
+with no arguments
+to be used similarly to
+su(1).
+If the plugin does not to support this usage, it may return a value of \-2
+from the
+\fBcheck_policy\fR()
+function, which will cause
+\fBsudo\fR
+to print a usage message and exit.
+.TP 6n
+implied_shell=bool
+If the user does not specify a program on the command line,
+\fBsudo\fR
+will pass the plugin the path to the user's shell and set
+\fIimplied_shell\fR.
+.TP 6n
+intercept_ptrace=bool
+Indicates whether or not the system supports intercept
+mode using
+ptrace(2).
+This is currently only true for Linux systems that support
+seccomp(2)
+filtering and the
+\(lqtrap\(rq
+action.
+Other systems will use a dynamic shared object to implement
+intercept.
+Only available starting with API version 1.19.
+.TP 6n
+intercept_setid=bool
+Indicates whether or not the system supports running set-user-ID
+and set-group-ID binaries in intercept mode.
+This is currently only true for Linux systems that support
+seccomp(2)
+filtering and the
+\(lqtrap\(rq
+action.
+On systems that use a dynamic shared object to implement
+intercept, the dynamic linker (ld.so or the equivalent)
+will disable preloading of shared objects when executing a
+set-user-ID or set-group-ID binary.
+This will disable intercept mode for that program and any other
+programs that it executes.
+The policy plugin may refuse to execute a set-user-ID or set-group-ID
+binary in intercept mode to avoid this.
+Only available starting with API version 1.19.
+.TP 6n
+login_class=string
+BSD
+login class to use when setting resource limits and nice value,
+if specified by the
+\fB\-c\fR
+option.
+.TP 6n
+login_shell=bool
+Set to true if the user specified the
+\fB\-i\fR
+option, indicating that
+the user wishes to run a login shell.
+.TP 6n
+max_groups=int
+The maximum number of groups a user may belong to.
+This will only be present if there is a corresponding setting in
+sudo.conf(@mansectform@).
+.TP 6n
+network_addrs=list
+A space-separated list of IP network addresses and netmasks in the
+form
+\(lqaddr/netmask\(rq,
+e.g.,
+\(lq192.168.1.2/255.255.255.0\(rq.
+The address and netmask pairs may be either IPv4 or IPv6, depending on
+what the operating system supports.
+If the address contains a colon
+(\(oq:\&\(cq),
+it is an IPv6 address, else it is IPv4.
+.TP 6n
+noninteractive=bool
+Set to true if the user specified the
+\fB\-n\fR
+option, indicating that
+\fBsudo\fR
+should operate in non-interactive mode.
+The plugin may reject a command run in non-interactive mode if user
+interaction is required.
+.TP 6n
+plugin_dir=string
+The default plugin directory used by the
+\fBsudo\fR
+front-end.
+This is the default directory set at compile time and may not
+correspond to the directory the running plugin was loaded from.
+It may be used by a plugin to locate support files.
+.TP 6n
+plugin_path=string
+The path name of plugin loaded by the
+\fBsudo\fR
+front-end.
+The path name will be a fully-qualified unless the plugin was
+statically compiled into
+\fBsudo\fR.
+.TP 6n
+preserve_environment=bool
+Set to true if the user specified the
+\fB\-E\fR
+option, indicating that
+the user wishes to preserve the environment.
+.TP 6n
+preserve_groups=bool
+Set to true if the user specified the
+\fB\-P\fR
+option, indicating that
+the user wishes to preserve the group vector instead of setting it
+based on the runas user.
+.TP 6n
+progname=string
+The command name that sudo was run as, typically
+\(lqsudo\(rq
+or
+\(lqsudoedit\(rq.
+.TP 6n
+prompt=string
+The prompt to use when requesting a password, if specified via
+the
+\fB\-p\fR
+option.
+.TP 6n
+remote_host=string
+The name of the remote host to run the command on, if specified via
+the
+\fB\-h\fR
+option.
+Support for running the command on a remote host is meant to be implemented
+via a helper program that is executed in place of the user-specified command.
+The
+\fBsudo\fR
+front-end is only capable of executing commands on the local host.
+Only available starting with API version 1.4.
+.TP 6n
+run_shell=bool
+Set to true if the user specified the
+\fB\-s\fR
+option, indicating that the user wishes to run a shell.
+.TP 6n
+runas_group=string
+The group name or group-ID to run the command as, if specified via
+the
+\fB\-g\fR
+option.
+.TP 6n
+runas_user=string
+The user name or user-ID to run the command as, if specified via the
+\fB\-u\fR
+option.
+.TP 6n
+selinux_role=string
+SELinux role to use when executing the command, if specified by
+the
+\fB\-r\fR
+option.
+.TP 6n
+selinux_type=string
+SELinux type to use when executing the command, if specified by
+the
+\fB\-t\fR
+option.
+.TP 6n
+set_home=bool
+Set to true if the user specified the
+\fB\-H\fR
+option.
+If true, set the
+\fRHOME\fR
+environment variable to the target user's home directory.
+.TP 6n
+sudoedit=bool
+Set to true when the
+\fB\-e\fR
+option is specified or if invoked as
+\fBsudoedit\fR.
+The plugin shall substitute an editor into
+\fIargv\fR
+in the
+\fBcheck_policy\fR()
+function or return \-2 with a usage error
+if the plugin does not support
+\fIsudoedit\fR.
+For more information, see the
+\fBcheck_policy\fR()
+section.
+.TP 6n
+timeout=string
+Command timeout specified by the user via the
+\fB\-T\fR
+option.
+Not all plugins support command timeouts and the ability of the
+user to set a timeout may be restricted by policy.
+The format of the timeout string is plugin-specific.
+.TP 6n
+update_ticket=bool
+Set to false if the user specified the
+\fB\-N\fR
+option, indicating that the user wishes to avoid updating any cached
+authentication credentials.
+Only available starting with API version 1.20.
+.PP
+Additional settings may be added in the future so the plugin should
+silently ignore settings that it does not recognize.
+.RE
+.TP 6n
+\fIuser_info\fR
+A vector of information about the user running the command in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIuser_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+The following values may be set by
+\fBsudo\fR:
+.PP
+.RS 6n
+.PD 0
+.TP 6n
+cols=int
+The number of columns the user's terminal supports.
+If there is no terminal device available, a default value of 80 is used.
+.PD
+.TP 6n
+cwd=string
+The user's current working directory.
+.TP 6n
+egid=gid_t
+The effective group-ID of the user invoking
+\fBsudo\fR.
+.TP 6n
+euid=uid_t
+The effective user-ID of the user invoking
+\fBsudo\fR.
+.TP 6n
+gid=gid_t
+The real group-ID of the user invoking
+\fBsudo\fR.
+.TP 6n
+groups=list
+The user's supplementary group list formatted as a string of
+comma-separated group-IDs.
+.TP 6n
+host=string
+The local machine's hostname as returned by the
+gethostname(2)
+system call.
+.TP 6n
+lines=int
+The number of lines the user's terminal supports.
+If there is
+no terminal device available, a default value of 24 is used.
+.TP 6n
+pgid=int
+The ID of the process group that the running
+\fBsudo\fR
+process is a member of.
+Only available starting with API version 1.2.
+.TP 6n
+pid=int
+The process ID of the running
+\fBsudo\fR
+process.
+Only available starting with API version 1.2.
+.TP 6n
+ppid=int
+The parent process ID of the running
+\fBsudo\fR
+process.
+Only available starting with API version 1.2.
+.TP 6n
+rlimit_as=soft,hard
+The maximum size to which the process's address space may grow (in bytes),
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_core=soft,hard
+The largest size core dump file that may be created (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_cpu=soft,hard
+The maximum amount of CPU time that the process may use (in seconds).
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_data=soft,hard
+The maximum size of the data segment for the process (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_fsize=soft,hard
+The largest size file that the process may create (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_locks=soft,hard
+The maximum number of locks that the process may establish,
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_memlock=soft,hard
+The maximum size that the process may lock in memory (in bytes),
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_nofile=soft,hard
+The maximum number of files that the process may have open.
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_nproc=soft,hard
+The maximum number of processes that the user may run simultaneously.
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_rss=soft,hard
+The maximum size to which the process's resident set size may grow (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+rlimit_stack=soft,hard
+The maximum size to which the process's stack may grow (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.TP 6n
+sid=int
+The session ID of the running
+\fBsudo\fR
+process or 0 if
+\fBsudo\fR
+is not part of a POSIX job control session.
+Only available starting with API version 1.2.
+.TP 6n
+tcpgid=int
+The ID of the foreground process group associated with the terminal
+device associated with the
+\fBsudo\fR
+process or 0 if there is no terminal present.
+Only available starting with API version 1.2.
+.TP 6n
+tty=string
+The path to the user's terminal device.
+If the user has no terminal device associated with the session,
+the value will be empty, as in
+\(oqtty=\(cq.
+.TP 6n
+uid=uid_t
+The real user-ID of the user invoking
+\fBsudo\fR.
+.TP 6n
+umask=octal
+The invoking user's file creation mask.
+Only available starting with API version 1.10.
+.TP 6n
+user=string
+The name of the user invoking
+\fBsudo\fR.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIuser_env\fR
+The user's environment in the form of a
+\fRNULL\fR-terminated vector of
+\(lqname=value\(rq
+strings.
+.sp
+When parsing
+\fIuser_env\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.TP 6n
+\fIplugin_options\fR
+Any (non-comment) strings immediately after the plugin path are
+passed as arguments to the plugin.
+These arguments are split on a white space boundary and are passed to
+the plugin in the form of a
+\fRNULL\fR-terminated
+array of strings.
+If no arguments were
+specified,
+\fIplugin_options\fR
+will be the
+\fRNULL\fR
+pointer.
+.sp
+The
+\fIplugin_options\fR
+parameter is only available starting with
+API version 1.2.
+A plugin
+\fBmust\fR
+check the API version specified
+by the
+\fBsudo\fR
+front-end before using
+\fIplugin_options\fR.
+Failure to do so may result in a crash.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBopen\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+The
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front-end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIclose\fR
+.br
+.nf
+.RS 6n
+void (*close)(int exit_status, int error);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBclose\fR()
+function is called when
+\fBsudo\fR
+is finished, shortly before it exits.
+Starting with API version 1.15,
+\fBclose\fR()
+is called regardless of whether or not a command was actually executed.
+This makes it possible for plugins to perform cleanup even when a
+command was not run.
+It is not possible to tell whether a command was run based solely
+on the arguments passed to the
+\fBclose\fR()
+function.
+To determine if a command was actually run,
+the plugin must keep track of whether or not the
+\fBcheck_policy\fR()
+function returned successfully.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIexit_status\fR
+The command's exit status, as returned by the
+wait(2)
+system call, or zero if no command was run.
+The value of
+\fIexit_status\fR
+is undefined if
+\fIerror\fR
+is non-zero.
+.TP 6n
+\fIerror\fR
+.br
+If the command could not be executed, this is set to the value of
+\fIerrno\fR
+set by the
+execve(2)
+system call.
+The plugin is responsible for displaying error information via the
+\fBconversation\fR()
+or
+\fBsudo_plugin_printf\fR()
+function.
+If the command was successfully executed, the value of
+\fIerror\fR
+is zero.
+.PP
+If no
+\fBclose\fR()
+function is defined, no I/O logging plugins are loaded,
+and neither the
+\fItimeout\fR
+nor
+\fIuse_pty\fR
+options are set in the
+\fIcommand_info\fR
+list, the
+\fBsudo\fR
+front-end may execute the command directly instead of running
+it as a child process.
+.RE
+.TP 6n
+\fIshow_version\fR
+.nf
+.RS 6n
+int (*show_version)(int verbose);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBshow_version\fR()
+function is called by
+\fBsudo\fR
+when the user specifies the
+\fB\-V\fR
+option.
+The plugin may display its version information to the user via the
+\fBconversation\fR()
+or
+\fBsudo_plugin_printf\fR()
+function using
+\fRSUDO_CONV_INFO_MSG\fR.
+If the user requests detailed version information, the
+\fIverbose\fR
+flag will be non-zero.
+.sp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error, although the return value is currently
+ignored.
+.RE
+.TP 6n
+\fIcheck_policy\fR
+.nf
+.RS 6n
+int (*check_policy)(int argc, char * const argv[], char *env_add[],
+ char **command_info[], char **argv_out[], char **user_env_out[],
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBcheck_policy\fR()
+function is called by
+\fBsudo\fR
+to determine
+whether the user is allowed to run the specified commands.
+.sp
+If the
+\fIsudoedit\fR
+option was enabled in the
+\fIsettings\fR
+array passed to the
+\fBopen\fR()
+function, the user has requested
+\fIsudoedit\fR
+mode.
+\fIsudoedit\fR
+is a mechanism for editing one or more files
+where an editor is run with the user's credentials instead of with
+elevated privileges.
+\fBsudo\fR
+achieves this by creating user-writable
+temporary copies of the files to be edited and then overwriting the
+originals with the temporary copies after editing is complete.
+If the plugin supports
+\fIsudoedit\fR,
+it must set
+\fIsudoedit=true\fR
+in the
+\fIcommand_info\fR
+list.
+The plugin is responsible for choosing the editor to be used,
+potentially from a variable in the user's environment, such as
+\fREDITOR\fR,
+and should be stored in
+\fIargv_out\fR
+(environment variables may include command line options).
+The files to be edited should be copied from
+\fIargv\fR
+to
+\fIargv_out\fR,
+separated from the
+editor and its arguments by a
+\(oq--\(cq
+element.
+The
+\(oq--\(cq
+will be removed by
+\fBsudo\fR
+before the editor is executed.
+The plugin may also set
+\fIsudoedit_nfiles\fR
+to the number of files to be edited in the
+\fIcommand_info\fR
+list; this will only be used by the
+\fBsudo\fR
+front-end starting with API version 1.21.
+.sp
+The
+\fBcheck_policy\fR()
+function returns 1 if the command is allowed,
+0 if not allowed, \-1 for a general error, or \-2 for a usage error
+or if
+\fIsudoedit\fR
+was specified but is unsupported by the plugin.
+In the latter case,
+\fBsudo\fR
+will print a usage message before it
+exits.
+If an error occurs, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBsudo_plugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional error information to the user.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIargc\fR
+The number of elements in
+\fIargv\fR,
+not counting the final
+\fRNULL\fR
+pointer.
+.TP 6n
+\fIargv\fR
+The argument vector describing the command the user wishes to run,
+in the same form as what would be passed to the
+execve(2)
+system call.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.TP 6n
+\fIenv_add\fR
+Additional environment variables specified by the user on the command
+line in the form of a
+\fRNULL\fR-terminated
+vector of
+\(lqname=value\(rq
+strings.
+The plugin may reject the command if one or more variables
+are not allowed to be set, or it may silently ignore such variables.
+.sp
+When parsing
+\fIenv_add\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one itself but the
+\fIvalue\fR
+might.
+.TP 6n
+\fIcommand_info\fR
+Information about the command being run in the form of
+\(lqname=value\(rq
+strings.
+These values are used by
+\fBsudo\fR
+to set the execution environment when running a command.
+The plugin is responsible for creating and populating the vector,
+which must be terminated with a
+\fRNULL\fR
+pointer.
+The following values are recognized by
+\fBsudo\fR:
+.PP
+.RS 6n
+.PD 0
+.TP 6n
+apparmor_profile=string
+AppArmor profile to transition to when executing the command.
+Only available starting with API version 1.19.
+.PD
+.TP 6n
+chroot=string
+The root directory to use when running the command.
+.TP 6n
+closefrom=number
+If specified,
+\fBsudo\fR
+will close all files descriptors with a value
+of
+\fInumber\fR
+or higher.
+.TP 6n
+command=string
+Fully qualified path to the command to be executed.
+.TP 6n
+cwd=string
+The current working directory to change to when executing the command.
+If
+\fBsudo\fR
+is unable to change to the new working directory, the command will
+not be run unless
+\fIcwd_optional\fR
+is also set (see below).
+.TP 6n
+cwd_optional=bool
+If set,
+\fBsudo\fR
+will treat an inability to change to the new working directory as a
+non-fatal error.
+This setting has no effect unless
+\fIcwd\fR
+is also set.
+.TP 6n
+exec_background=bool
+By default,
+\fBsudo\fR
+runs a command as the foreground process as long as
+\fBsudo\fR
+itself is running in the foreground.
+When
+\fIexec_background\fR
+is enabled and the command is being run in a pseudo-terminal
+(due to I/O logging or the
+\fIuse_pty\fR
+setting), the command will be run as a background process.
+Attempts to read from the controlling terminal (or to change terminal
+settings) will result in the command being suspended with the
+\fRSIGTTIN\fR
+signal (or
+\fRSIGTTOU\fR
+in the case of terminal settings).
+If this happens when
+\fBsudo\fR
+is a foreground process, the command will be granted the controlling terminal
+and resumed in the foreground with no user intervention required.
+The advantage of initially running the command in the background is that
+\fBsudo\fR
+need not read from the terminal unless the command explicitly requests it.
+Otherwise, any terminal input must be passed to the command, whether it
+has required it or not (the kernel buffers terminals so it is not possible
+to tell whether the command really wants the input).
+This is different from historic
+\fBsudo\fR
+behavior or when the command is not being run in a pseudo-terminal.
+.sp
+For this to work seamlessly, the operating system must support the
+automatic restarting of system calls.
+Unfortunately, not all operating systems do this by default,
+and even those that do may have bugs.
+For example, macOS fails to restart the
+\fBtcgetattr\fR()
+and
+\fBtcsetattr\fR()
+system calls (this is a bug in macOS).
+Furthermore, because this behavior depends on the command stopping with the
+\fRSIGTTIN\fR
+or
+\fRSIGTTOU\fR
+signals, programs that catch these signals and suspend themselves
+with a different signal (usually
+\fRSIGTOP\fR)
+will not be automatically foregrounded.
+Some versions of the linux
+su(1)
+command behave this way.
+Because of this, a plugin should not set
+\fIexec_background\fR
+unless it is explicitly enabled by the administrator and there should
+be a way to enabled or disable it on a per-command basis.
+.sp
+This setting has no effect unless I/O logging is enabled or
+\fIuse_pty\fR
+is enabled.
+.TP 6n
+execfd=number
+If specified,
+\fBsudo\fR
+will use the
+fexecve(2)
+system call to execute the command instead of
+execve(2).
+The specified
+\fInumber\fR
+must refer to an open file descriptor.
+.TP 6n
+intercept=bool
+If set,
+\fBsudo\fR
+will intercept attempts to execute a subsequent command and perform
+a policy check via the policy plugin's
+\fBcheck_policy\fR()
+function to determine whether or not the command is permitted.
+This can be used to prevent shell escapes on supported platforms
+but it has a number of limitations.
+See
+\fBPreventing shell escapes\fR
+in
+sudoers(@mansectform@)
+for details.
+Only available starting with API version 1.18.
+.TP 6n
+intercept_verify=bool
+If set,
+\fBsudo\fR
+will attempt to verify that a command run in intercept mode has the
+expected path name, command line arguments and environment.
+This setting has no effect unless
+\fIuse_ptrace\fR
+is also enabled.
+Only available starting with API version 1.20.
+.TP 6n
+iolog_compress=bool
+Set to true if the I/O logging plugins, if any, should compress the
+log data.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+iolog_group=string
+The group that will own newly created I/O log files and directories.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+iolog_mode=octal
+The file permission mode to use when creating I/O log files and directories.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+iolog_user=string
+The user that will own newly created I/O log files and directories.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+iolog_path=string
+Fully qualified path to the file or directory in which I/O log is
+to be stored.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+If no I/O logging plugin is loaded, this setting has no effect.
+.TP 6n
+iolog_stdin=bool
+Set to true if the I/O logging plugins, if any, should log the
+standard input if it is not connected to a terminal device.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+iolog_stdout=bool
+Set to true if the I/O logging plugins, if any, should log the
+standard output if it is not connected to a terminal device.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+iolog_stderr=bool
+Set to true if the I/O logging plugins, if any, should log the
+standard error if it is not connected to a terminal device.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+iolog_ttyin=bool
+Set to true if the I/O logging plugins, if any, should log all
+terminal input.
+This only includes input typed by the user and not from a pipe or
+redirected from a file.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+iolog_ttyout=bool
+Set to true if the I/O logging plugins, if any, should log all
+terminal output.
+This only includes output to the screen, not output to a pipe or file.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.TP 6n
+login_class=string
+BSD
+login class to use when setting resource limits and nice value (optional).
+This option is only set on systems that support login classes.
+.TP 6n
+nice=int
+Nice value (priority) to use when executing the command.
+The nice value, if specified, overrides the priority associated with the
+\fIlogin_class\fR
+on
+BSD
+systems.
+.TP 6n
+log_subcmds=bool
+If set,
+\fBsudo\fR
+will call the audit plugin's
+\fBaccept\fR()
+function to log when the command runs a subsequent command, if supported
+by the system.
+If
+\fIintercept\fR
+is also specified,
+\fIlog_subcmds\fR
+will be ignored.
+See
+\fBPreventing shell escapes\fR
+in
+sudoers(@mansectform@)
+for more information.
+Only available starting with API version 1.18.
+.TP 6n
+noexec=bool
+If set, prevent the command from executing other programs.
+.TP 6n
+preserve_fds=list
+A comma-separated list of file descriptors that should be
+preserved, regardless of the value of the
+\fIclosefrom\fR
+setting.
+Only available starting with API version 1.5.
+.TP 6n
+preserve_groups=bool
+If set,
+\fBsudo\fR
+will preserve the user's group vector instead of
+initializing the group vector based on
+\fIrunas_user\fR.
+.TP 6n
+rlimit_as=soft,hard
+The maximum size to which the process's address space may grow (in bytes),
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+A value of
+\(lquser\(rq
+will cause the invoking user's resource limit to be preserved.
+A value of
+\(lqdefault\(rq
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.TP 6n
+rlimit_core=soft,hard
+The largest size core dump file that may be created (in bytes).
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+A value of
+\(lquser\(rq
+will cause the invoking user's resource limit to be preserved.
+A value of
+\(lqdefault\(rq
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.TP 6n
+rlimit_cpu=soft,hard
+The maximum amount of CPU time that the process may use (in seconds).
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+A value of
+\(lquser\(rq
+will cause the invoking user's resource limit to be preserved.
+A value of
+\(lqdefault\(rq
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.TP 6n
+rlimit_data=soft,hard
+The maximum size of the data segment for the process (in bytes).
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+A value of
+\(lquser\(rq
+will cause the invoking user's resource limit to be preserved.
+A value of
+\(lqdefault\(rq
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.TP 6n
+rlimit_fsize=soft,hard
+The largest size file that the process may create (in bytes).
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+A value of
+\(lquser\(rq
+will cause the invoking user's resource limit to be preserved.
+A value of
+\(lqdefault\(rq
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.TP 6n
+rlimit_locks=soft,hard
+The maximum number of locks that the process may establish,
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+A value of
+\(lquser\(rq
+will cause the invoking user's resource limit to be preserved.
+A value of
+\(lqdefault\(rq
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.TP 6n
+rlimit_memlock=soft,hard
+The maximum size that the process may lock in memory (in bytes),
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+A value of
+\(lquser\(rq
+will cause the invoking user's resource limit to be preserved.
+A value of
+\(lqdefault\(rq
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.TP 6n
+rlimit_nofile=soft,hard
+The maximum number of files that the process may have open.
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+A value of
+\(lquser\(rq
+will cause the invoking user's resource limit to be preserved.
+A value of
+\(lqdefault\(rq
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.TP 6n
+rlimit_nproc=soft,hard
+The maximum number of processes that the user may run simultaneously.
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+A value of
+\(lquser\(rq
+will cause the invoking user's resource limit to be preserved.
+A value of
+\(lqdefault\(rq
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.TP 6n
+rlimit_rss=soft,hard
+The maximum size to which the process's resident set size may grow (in bytes).
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+A value of
+\(lquser\(rq
+will cause the invoking user's resource limit to be preserved.
+A value of
+\(lqdefault\(rq
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.TP 6n
+rlimit_stack=soft,hard
+The maximum size to which the process's stack may grow (in bytes).
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+\(lqinfinity\(rq
+indicates that there is no limit.
+A value of
+\(lquser\(rq
+will cause the invoking user's resource limit to be preserved.
+A value of
+\(lqdefault\(rq
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.TP 6n
+runas_egid=gid
+Effective group-ID to run the command as.
+If not specified, the value of
+\fIrunas_gid\fR
+is used.
+.TP 6n
+runas_euid=uid
+Effective user-ID to run the command as.
+If not specified, the value of
+\fIrunas_uid\fR
+is used.
+.TP 6n
+runas_gid=gid
+Group-ID to run the command as.
+.TP 6n
+runas_group=string
+The name of the group the command will run as, if it is different
+from the
+\fIrunas_user\fR's
+default group.
+This value is provided for auditing purposes only, the
+\fBsudo\fR
+front-end uses
+\fIrunas_egid\fR
+and
+\fIrunas_gid\fR
+when executing the command.
+.TP 6n
+runas_groups=list
+The supplementary group vector to use for the command in the form
+of a comma-separated list of group-IDs.
+If
+\fIpreserve_groups\fR
+is set, this option is ignored.
+.TP 6n
+runas_uid=uid
+User-ID to run the command as.
+.TP 6n
+runas_user=string
+The name of the user the command will run as, which should correspond to
+\fIrunas_euid\fR
+(or
+\fIrunas_uid\fR
+if
+\fIrunas_euid\fR
+is not set).
+This value is provided for auditing purposes only, the
+\fBsudo\fR
+front-end uses
+\fIrunas_euid\fR
+and
+\fIrunas_uid\fR
+when executing the command.
+.TP 6n
+selinux_role=string
+SELinux role to use when executing the command.
+.TP 6n
+selinux_type=string
+SELinux type to use when executing the command.
+.TP 6n
+set_utmp=bool
+Create a utmp (or utmpx) entry when a pseudo-terminal is allocated.
+By default, the new entry will be a copy of the user's existing utmp
+entry (if any), with the tty, time, type, and pid fields updated.
+.TP 6n
+sudoedit=bool
+Set to true when in
+\fIsudoedit\fR
+mode.
+The plugin may enable
+\fIsudoedit\fR
+mode even if
+\fBsudo\fR
+was not invoked as
+\fBsudoedit\fR.
+This allows the plugin to perform command substitution and transparently
+enable
+\fIsudoedit\fR
+when the user attempts to run an editor.
+.TP 6n
+sudoedit_checkdir=bool
+Set to false to disable directory writability checks in
+\fBsudoedit\fR.
+By default,
+\fBsudoedit\fR
+1.8.16 and higher will check all directory components of the path to be
+edited for writability by the invoking user.
+Symbolic links will not be followed in writable directories and
+\fBsudoedit\fR
+will refuse to edit a file located in a writable directory.
+These restrictions are not enforced when
+\fBsudoedit\fR
+is run by root.
+The
+\fIsudoedit_checkdir\fR
+option can be set to false to disable this check.
+Only available starting with API version 1.8.
+.TP 6n
+sudoedit_follow=bool
+Set to true to allow
+\fBsudoedit\fR
+to edit files that are symbolic links.
+By default,
+\fBsudoedit\fR
+1.8.15 and higher will refuse to open a symbolic link.
+The
+\fIsudoedit_follow\fR
+option can be used to restore the older behavior and allow
+\fBsudoedit\fR
+to open symbolic links.
+Only available starting with API version 1.8.
+.TP 6n
+sudoedit_nfiles=number
+The number of files to be edited by the user.
+If present, this is will be used by the
+\fBsudo\fR
+front-end to determine which elements of the
+\fIargv_out\fR
+vector are files to be edited.
+The
+\(oq--\(cq
+element must immediately precede the first file to be editied.
+If
+\fIsudoedit_nfiles\fR
+is not specified, the
+\fBsudo\fR
+front-end will use the position of the
+\(oq--\(cq
+element to determine where the file list begins.
+Only available starting with API version 1.21.
+.TP 6n
+timeout=int
+Command timeout.
+If non-zero then when the timeout expires the command will be killed.
+.TP 6n
+umask=octal
+The file creation mask to use when executing the command.
+This value may be overridden by PAM or login.conf on some systems
+unless the
+\fIumask_override\fR
+option is also set.
+.TP 6n
+umask_override=bool
+Force the value specified by the
+\fIumask\fR
+option to override any umask set by PAM or login.conf.
+.TP 6n
+use_ptrace=bool
+If set,
+\fBsudo\fR
+will use
+ptrace(2)
+to implement intercept mode if supported by the system.
+This setting has no effect unless
+\fIintercept\fR
+is also set.
+Only available starting with API version 1.19.
+.TP 6n
+use_pty=bool
+Allocate a pseudo-terminal to run the command in, regardless of whether
+or not I/O logging is in use.
+By default,
+\fBsudo\fR
+will only run
+the command in a pseudo-terminal when an I/O log plugin is loaded.
+.TP 6n
+utmp_user=string
+User name to use when constructing a new utmp (or utmpx) entry when
+\fIset_utmp\fR
+is enabled.
+This option can be used to set the user field in the utmp entry to
+the user the command runs as rather than the invoking user.
+If not set,
+\fBsudo\fR
+will base the new entry on
+the invoking user's existing entry.
+.PP
+Unsupported values will be ignored.
+.RE
+.TP 6n
+\fIargv_out\fR
+The
+\fRNULL\fR-terminated
+argument vector to pass to the
+execve(2)
+system call when executing the command.
+The plugin is responsible for allocating and populating the vector.
+.TP 6n
+\fIuser_env_out\fR
+The
+\fRNULL\fR-terminated
+environment vector to use when executing the command.
+The plugin is responsible for allocating and populating the vector.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBcheck_policy\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+The
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front-end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIlist\fR
+.nf
+.RS 6n
+int (*list)(int argc, char * const argv[], int verbose,
+ const char *user, const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+List available privileges for the invoking user.
+Returns 1 on success, 0 on failure, and \-1 on error.
+On error, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBsudo_plugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional error information to
+the user.
+.sp
+Privileges should be output via the
+\fBconversation\fR()
+or
+\fBsudo_plugin_printf\fR()
+function using
+\fRSUDO_CONV_INFO_MSG\fR.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIargc\fR
+The number of elements in
+\fIargv\fR,
+not counting the final
+\fRNULL\fR
+pointer.
+.TP 6n
+\fIargv\fR
+If
+non-\fRNULL\fR,
+an argument vector describing a command the user
+wishes to check against the policy in the same form as what would
+be passed to the
+execve(2)
+system call.
+If the command is permitted by the policy, the fully-qualified path
+to the command should be displayed along with any command line arguments.
+.TP 6n
+\fIverbose\fR
+Flag indicating whether to list in verbose mode or not.
+.TP 6n
+\fIuser\fR
+The name of a different user to list privileges for if the policy
+allows it.
+If
+\fRNULL\fR,
+the plugin should list the privileges of the invoking user.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBlist\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+The
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front-end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIvalidate\fR
+.nf
+.RS 6n
+int (*validate)(const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBvalidate\fR()
+function is called when
+\fBsudo\fR
+is run with the
+\fB\-v\fR
+option.
+For policy plugins such as
+\fBsudoers\fR
+that cache
+authentication credentials, this function will validate and cache
+the credentials.
+.sp
+The
+\fBvalidate\fR()
+function should be
+\fRNULL\fR
+if the plugin does not support credential caching.
+.sp
+Returns 1 on success, 0 on failure, and \-1 on error.
+On error, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBsudo_plugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional
+error information to the user.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIerrstr\fR
+If the
+\fBvalidate\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+The
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front-end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIinvalidate\fR
+.nf
+.RS 6n
+void (*invalidate)(int rmcred);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBinvalidate\fR()
+function is called when
+\fBsudo\fR
+is run with the
+\fB\-k\fR
+or
+\fB\-K\fR
+option.
+For policy plugins such as
+\fBsudoers\fR
+that
+cache authentication credentials, this function will invalidate the
+credentials.
+If the
+\fIrmcred\fR
+flag is non-zero, the plugin may remove
+the credentials instead of simply invalidating them.
+.sp
+The
+\fBinvalidate\fR()
+function should be
+\fRNULL\fR
+if the plugin does not support credential caching.
+.RE
+.TP 6n
+\fIinit_session\fR
+.nf
+.RS 6n
+int (*init_session)(struct passwd *pwd, char **user_env[],
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBinit_session\fR()
+function is called before
+\fBsudo\fR
+sets up the
+execution environment for the command.
+It is run in the parent
+\fBsudo\fR
+process before any user-ID or group-ID changes.
+This can be used to perform session setup that is not supported by
+\fIcommand_info\fR,
+such as opening the PAM session.
+The
+\fBclose\fR()
+function can be
+used to tear down the session that was opened by
+\fBinit_session\fR().
+.sp
+Returns 1 on success, 0 on failure, and \-1 on error.
+On error, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBsudo_plugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional
+error information to the user.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIpwd\fR
+If the user-ID the command will run as was found in the password database,
+\fIpwd\fR
+will describe that user, otherwise it will be
+\fRNULL\fR.
+.TP 6n
+\fIuser_env_out\fR
+The
+\fRNULL\fR-terminated
+environment vector to use when executing the command.
+This is the same string passed back to the front-end via the Policy Plugin's
+\fIuser_env_out\fR
+parameter.
+If the
+\fBinit_session\fR()
+function needs to modify the user environment, it should update the
+pointer stored in
+\fIuser_env_out\fR.
+The expected use case is to merge the contents of the PAM environment
+(if any) with the contents of
+\fIuser_env_out\fR.
+The
+\fIuser_env_out\fR
+parameter is only available
+starting with API version 1.2.
+A plugin
+\fBmust\fR
+check the API
+version specified by the
+\fBsudo\fR
+front-end before using
+\fIuser_env_out\fR.
+Failure to do so may result in a crash.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBinit_session\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+The
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front-end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIregister_hooks\fR
+.nf
+.RS 6n
+void (*register_hooks)(int version,
+ int (*register_hook)(struct sudo_hook *hook));
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBregister_hooks\fR()
+function is called by the sudo front-end to
+register any hooks the plugin needs.
+If the plugin does not support hooks,
+\fIregister_hooks\fR
+should be set to the
+\fRNULL\fR
+pointer.
+.sp
+The
+\fIversion\fR
+argument describes the version of the hooks API
+supported by the
+\fBsudo\fR
+front-end.
+.sp
+The
+\fBregister_hook\fR()
+function should be used to register any supported
+hooks the plugin needs.
+It returns 0 on success, 1 if the hook type is not supported, and \-1
+if the major version in
+\fIstruct sudo_hook\fR
+does not match the front-end's major hook API version.
+.sp
+See the
+\fIHook function API\fR
+section below for more information about hooks.
+.sp
+The
+\fBregister_hooks\fR()
+function is only available starting
+with API version 1.2.
+If the
+\fBsudo\fR
+front-end doesn't support API
+version 1.2 or higher,
+\fBregister_hooks\fR()
+will not be called.
+.RE
+.TP 6n
+\fIderegister_hooks\fR
+.nf
+.RS 6n
+void (*deregister_hooks)(int version,
+ int (*deregister_hook)(struct sudo_hook *hook));
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBderegister_hooks\fR()
+function is called by the sudo front-end
+to deregister any hooks the plugin has registered.
+If the plugin does not support hooks,
+\fIderegister_hooks\fR
+should be set to the
+\fRNULL\fR
+pointer.
+.sp
+The
+\fIversion\fR
+argument describes the version of the hooks API
+supported by the
+\fBsudo\fR
+front-end.
+.sp
+The
+\fBderegister_hook\fR()
+function should be used to deregister any
+hooks that were put in place by the
+\fBregister_hook\fR()
+function.
+If the plugin tries to deregister a hook that the front-end does not support,
+\fBderegister_hook\fR()
+will return an error.
+.sp
+See the
+\fIHook function API\fR
+section below for more information about hooks.
+.sp
+The
+\fBderegister_hooks\fR()
+function is only available starting
+with API version 1.2.
+If the
+\fBsudo\fR
+front-end doesn't support API
+version 1.2 or higher,
+\fBderegister_hooks\fR()
+will not be called.
+.RE
+.TP 6n
+\fIevent_alloc\fR
+.nf
+.RS 6n
+struct sudo_plugin_event * (*event_alloc)(void);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBevent_alloc\fR()
+function is used to allocate a
+\fIstruct sudo_plugin_event\fR
+which provides access to the main
+\fBsudo\fR
+event loop.
+Unlike the other fields, the
+\fIevent_alloc\fR
+pointer is filled in by the
+\fBsudo\fR
+front-end, not by the plugin.
+.sp
+See the
+\fIEvent API\fR
+section below for more information
+about events.
+.sp
+The
+\fBevent_alloc\fR()
+function is only available starting
+with API version 1.15.
+If the
+\fBsudo\fR
+front-end doesn't support API
+version 1.15 or higher,
+\fIevent_alloc\fR
+will not be set.
+.RE
+.PP
+\fIPolicy Plugin Version Macros\fR
+.nf
+.sp
+.RS 0n
+/* Plugin API version major/minor. */
+#define SUDO_API_VERSION_MAJOR 1
+#define SUDO_API_VERSION_MINOR 13
+#define SUDO_API_MKVERSION(x, y) ((x << 16) | y)
+#define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR,\e
+ SUDO_API_VERSION_MINOR)
+
+/* Getters and setters for API version */
+#define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16)
+#define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
+#define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \e
+ *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e
+} while(0)
+#define SUDO_API_VERSION_SET_MINOR(vp, n) do { \e
+ *(vp) = (*(vp) & 0xffff0000) | (n); \e
+} while(0)
+.RE
+.fi
+.SS "I/O plugin API"
+.nf
+.RS 0n
+struct io_plugin {
+#define SUDO_IO_PLUGIN 2
+ unsigned int type; /* always SUDO_IO_PLUGIN */
+ unsigned int version; /* always SUDO_API_VERSION */
+ int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], char * const command_info[],
+ int argc, char * const argv[], char * const user_env[],
+ char * const plugin_options[], const char **errstr);
+ void (*close)(int exit_status, int error); /* wait status or error */
+ int (*show_version)(int verbose);
+ int (*log_ttyin)(const char *buf, unsigned int len,
+ const char **errstr);
+ int (*log_ttyout)(const char *buf, unsigned int len,
+ const char **errstr);
+ int (*log_stdin)(const char *buf, unsigned int len,
+ const char **errstr);
+ int (*log_stdout)(const char *buf, unsigned int len,
+ const char **errstr);
+ int (*log_stderr)(const char *buf, unsigned int len,
+ const char **errstr);
+ void (*register_hooks)(int version,
+ int (*register_hook)(struct sudo_hook *hook));
+ void (*deregister_hooks)(int version,
+ int (*deregister_hook)(struct sudo_hook *hook));
+ int (*change_winsize)(unsigned int lines, unsigned int cols,
+ const char **errstr);
+ int (*log_suspend)(int signo, const char **errstr);
+ struct sudo_plugin_event * (*event_alloc)(void);
+};
+.RE
+.fi
+.PP
+When an I/O plugin is loaded,
+\fBsudo\fR
+runs the command in a pseudo-terminal.
+This makes it possible to log the input and output from the user's
+session.
+If any of the standard input, standard output, or standard error do not
+correspond to a tty,
+\fBsudo\fR
+will open a pipe to capture the I/O for logging before passing it on.
+.PP
+The
+\fBlog_ttyin\fR()
+function receives the raw user input from the terminal
+device (this will include input even when echo is disabled,
+such as when a password is read).
+The
+\fBlog_ttyout\fR()
+function receives output from the pseudo-terminal that is
+suitable for replaying the user's session at a later time.
+The
+\fBlog_stdin\fR(),
+\fBlog_stdout\fR(),
+and
+\fBlog_stderr\fR()
+functions are only called if the standard input, standard output,
+or standard error respectively correspond to something other than
+a tty.
+.PP
+Any of the logging functions may be set to the
+\fRNULL\fR
+pointer if no logging is to be performed.
+If the open function returns 0, no I/O will be sent to the plugin.
+.PP
+If a logging function returns an error
+(\-1),
+the running command will be terminated and all of the plugin's logging
+functions will be disabled.
+Other I/O logging plugins will still receive any remaining
+input or output that has not yet been processed.
+.PP
+If an input logging function rejects the data by returning 0, the
+command will be terminated and the data will not be passed to the
+command, though it will still be sent to any other I/O logging plugins.
+If an output logging function rejects the data by returning 0, the
+command will be terminated and the data will not be written to the
+terminal, though it will still be sent to any other I/O logging plugins.
+.PP
+A
+\fIstruct audit_plugin\fR
+has the following fields:
+.TP 6n
+\fItype\fR
+The
+\fItype\fR
+field should always be set to
+\fRSUDO_IO_PLUGIN\fR.
+.TP 6n
+\fIversion\fR
+The
+\fIversion\fR
+field should be set to
+\fRSUDO_API_VERSION\fR.
+.sp
+This allows
+\fBsudo\fR
+to determine the API version the plugin was
+built against.
+.TP 6n
+\fIopen\fR
+.nf
+.RS 6n
+int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], char * const command_info[],
+ int argc, char * const argv[], char * const user_env[],
+ char * const plugin_options[]);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBopen\fR()
+function is run before the
+\fBlog_ttyin\fR(),
+\fBlog_ttyout\fR(),
+\fBlog_stdin\fR(),
+\fBlog_stdout\fR(),
+\fBlog_stderr\fR(),
+\fBlog_suspend\fR(),
+\fBchange_winsize\fR(),
+or
+\fBshow_version\fR()
+functions are called.
+It is only called if the version is being requested or if the
+policy plugin's
+\fBcheck_policy\fR()
+function has returned successfully.
+It returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+\fBsudo\fR
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBsudo_plugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional error information to the user.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIversion\fR
+The version passed in by
+\fBsudo\fR
+allows the plugin to determine the
+major and minor version number of the plugin API supported by
+\fBsudo\fR.
+.TP 6n
+\fIconversation\fR
+A pointer to the
+\fBconversation\fR()
+function that may be used by the
+\fBFa\fR(\fIshow_version\fR)
+function to display version information (see
+\fBshow_version\fR()
+below).
+The
+\fBconversation\fR()
+function may also be used to display additional error message to the user.
+The
+\fBconversation\fR()
+function returns 0 on success and \-1 on failure.
+.TP 6n
+\fIsudo_plugin_printf\fR
+A pointer to a
+\fBprintf\fR()-style
+function that may be used by the
+\fBshow_version\fR()
+function to display version information (see
+show_version below).
+The
+\fBsudo_plugin_printf\fR()
+function may also be used to display additional error message to the user.
+The
+\fBsudo_plugin_printf\fR()
+function returns number of characters printed on success and \-1 on failure.
+.TP 6n
+\fIsettings\fR
+A vector of user-supplied
+\fBsudo\fR
+settings in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+These settings correspond to options the user specified when running
+\fBsudo\fR.
+As such, they will only be present when the corresponding option has
+been specified on the command line.
+.sp
+When parsing
+\fIsettings\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible settings.
+.TP 6n
+\fIuser_info\fR
+A vector of information about the user running the command in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIuser_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible strings.
+.TP 6n
+\fIcommand_info\fR
+A vector of information describing the command being run in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIcommand_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible strings.
+.TP 6n
+\fIargc\fR
+The number of elements in
+\fIargv\fR,
+not counting the final
+\fRNULL\fR
+pointer.
+It can be zero, such as when
+\fBsudo\fR
+is called with the
+\fB\-V\fR
+option.
+.TP 6n
+\fIargv\fR
+If
+non-\fRNULL\fR,
+an argument vector describing a command the user
+wishes to run in the same form as what would be passed to the
+execve(2)
+system call.
+.TP 6n
+\fIuser_env\fR
+The user's environment in the form of a
+\fRNULL\fR-terminated
+vector of
+\(lqname=value\(rq
+strings.
+.sp
+When parsing
+\fIuser_env\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.TP 6n
+\fIplugin_options\fR
+Any (non-comment) strings immediately after the plugin path are
+treated as arguments to the plugin.
+These arguments are split on a white space boundary and are passed to
+the plugin in the form of a
+\fRNULL\fR-terminated
+array of strings.
+If no arguments were specified,
+\fIplugin_options\fR
+will be the
+\fRNULL\fR
+pointer.
+.sp
+The
+\fIplugin_options\fR
+parameter is only available starting with
+API version 1.2.
+A plugin
+\fBmust\fR
+check the API version specified
+by the
+\fBsudo\fR
+front-end before using
+\fIplugin_options\fR.
+Failure to do so may result in a crash.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBopen\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+The
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front-end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIclose\fR
+.br
+.nf
+.RS 6n
+void (*close)(int exit_status, int error);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBclose\fR()
+function is called when
+\fBsudo\fR
+is finished, shortly before it exits.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIexit_status\fR
+The command's exit status, as returned by the
+wait(2)
+system call, or zero if no command was run.
+The value of
+\fIexit_status\fR
+is undefined if
+\fIerror\fR
+is non-zero.
+.TP 6n
+\fIerror\fR
+.br
+If the command could not be executed, this is set to the value of
+\fIerrno\fR
+set by the
+execve(2)
+system call.
+If the command was successfully executed, the value of
+\fIerror\fR
+is zero.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIshow_version\fR
+.nf
+.RS 6n
+int (*show_version)(int verbose);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBshow_version\fR()
+function is called by
+\fBsudo\fR
+when the user specifies the
+\fB\-V\fR
+option.
+The plugin may display its version information to the user via the
+\fBconversation\fR()
+or
+\fBsudo_plugin_printf\fR()
+function using
+\fRSUDO_CONV_INFO_MSG\fR.
+If the user requests detailed version information, the
+\fIverbose\fR
+flag will be non-zero.
+.sp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error, although the return value is currently
+ignored.
+.RE
+.TP 6n
+\fIlog_ttyin\fR
+.nf
+.RS 6n
+int (*log_ttyin)(const char *buf, unsigned int len,
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBlog_ttyin\fR()
+function is called whenever data can be read from
+the user but before it is passed to the running command.
+This allows the plugin to reject data if it chooses to (for instance
+if the input contains banned content).
+Returns 1 if the data should be passed to the command, 0 if the data
+is rejected (which will terminate the running command), or \-1 if an
+error occurred.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIbuf\fR
+The buffer containing user input.
+.TP 6n
+\fIlen\fR
+The length of
+\fIbuf\fR
+in bytes.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBlog_ttyin\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+The
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front-end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIlog_ttyout\fR
+.nf
+.RS 6n
+int (*log_ttyout)(const char *buf, unsigned int len,
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBlog_ttyout\fR()
+function is called whenever data can be read from
+the command but before it is written to the user's terminal.
+This allows the plugin to reject data if it chooses to (for instance
+if the output contains banned content).
+Returns 1 if the data should be passed to the user, 0 if the data is rejected
+(which will terminate the running command), or \-1 if an error occurred.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIbuf\fR
+The buffer containing command output.
+.TP 6n
+\fIlen\fR
+The length of
+\fIbuf\fR
+in bytes.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBlog_ttyout\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+The
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front-end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIlog_stdin\fR
+.nf
+.RS 6n
+int (*log_stdin)(const char *buf, unsigned int len,
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBlog_stdin\fR()
+function is only used if the standard input does
+not correspond to a tty device.
+It is called whenever data can be read from the standard input but
+before it is passed to the running command.
+This allows the plugin to reject data if it chooses to
+(for instance if the input contains banned content).
+Returns 1 if the data should be passed to the command, 0 if the
+data is rejected (which will terminate the running command), or \-1
+if an error occurred.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIbuf\fR
+The buffer containing user input.
+.TP 6n
+\fIlen\fR
+The length of
+\fIbuf\fR
+in bytes.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBlog_stdin\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+The
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front-end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIlog_stdout\fR
+.nf
+.RS 6n
+int (*log_stdout)(const char *buf, unsigned int len,
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBlog_stdout\fR()
+function is only used if the standard output does not correspond
+to a tty device.
+It is called whenever data can be read from the command but before
+it is written to the standard output.
+This allows the plugin to reject data if it chooses to
+(for instance if the output contains banned content).
+Returns 1 if the data should be passed to the user, 0 if the data
+is rejected (which will terminate the running command), or \-1 if
+an error occurred.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIbuf\fR
+The buffer containing command output.
+.TP 6n
+\fIlen\fR
+The length of
+\fIbuf\fR
+in bytes.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBlog_stdout\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+The
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front-end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIlog_stderr\fR
+.nf
+.RS 6n
+int (*log_stderr)(const char *buf, unsigned int len,
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBlog_stderr\fR()
+function is only used if the standard error does
+not correspond to a tty device.
+It is called whenever data can be read from the command but before it
+is written to the standard error.
+This allows the plugin to reject data if it chooses to
+(for instance if the output contains banned content).
+Returns 1 if the data should be passed to the user, 0 if the data
+is rejected (which will terminate the running command), or \-1 if
+an error occurred.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIbuf\fR
+The buffer containing command output.
+.TP 6n
+\fIlen\fR
+The length of
+\fIbuf\fR
+in bytes.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBlog_stderr\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+The
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front-end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIregister_hooks\fR
+See the
+\fIPolicy plugin API\fR
+section for a description of
+\fBregister_hooks\fR().
+.TP 6n
+\fIderegister_hooks\fR
+See the
+\fIPolicy plugin API\fR
+section for a description of
+\fBderegister_hooks\fR().
+.TP 6n
+\fIchange_winsize\fR
+.nf
+.RS 6n
+int (*change_winsize)(unsigned int lines, unsigned int cols,
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBchange_winsize\fR()
+function is called whenever the window size of the terminal changes from
+the initial values specified in the
+\fIuser_info\fR
+list.
+Returns \-1 if an error occurred, in which case no further calls to
+\fBchange_winsize\fR()
+will be made,
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIlines\fR
+.br
+The number of lines (rows) in the re-sized terminal.
+.TP 6n
+\fIcols\fR
+The number of columns in the re-sized terminal.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBchange_winsize\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+The
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front-end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIlog_suspend\fR
+.nf
+.RS 6n
+int (*log_suspend)(int signo, const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBlog_suspend\fR()
+function is called whenever a command is suspended or resumed.
+Logging this information makes it possible to skip the period of time when
+the command was suspended during playback of a session.
+Returns \-1 if an error occurred, in which case no further calls to
+\fBlog_suspend\fR()
+will be made,
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIsigno\fR
+.br
+The signal that caused the command to be suspended, or
+\fRSIGCONT\fR
+if the command was resumed.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBlog_suspend\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.sp
+The
+\fIerrstr\fR
+parameter is only available starting with
+API version 1.15.
+A plugin
+\fBmust\fR
+check the API version specified by the
+\fBsudo\fR
+front-end before using
+\fIerrstr\fR.
+Failure to do so may result in a crash.
+.TP 6n
+\fIevent_alloc\fR
+.nf
+.RS 6n
+struct sudo_plugin_event * (*event_alloc)(void);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBevent_alloc\fR()
+function is used to allocate a
+\fIstruct sudo_plugin_event\fR
+which provides access to the main
+\fBsudo\fR
+event loop.
+Unlike the other fields, the
+\fBevent_alloc\fR()
+pointer is filled in by the
+\fBsudo\fR
+front-end, not by the plugin.
+.sp
+See the
+\fIEvent API\fR
+section below for more information
+about events.
+.sp
+The
+\fBevent_alloc\fR()
+function is only available starting
+with API version 1.15.
+If the
+\fBsudo\fR
+front-end doesn't support API
+version 1.15 or higher,
+\fBevent_alloc\fR()
+will not be set.
+.RE
+.PP
+\fII/O Plugin Version Macros\fR
+.sp
+Same as for the
+\fIPolicy plugin API\fR.
+.RE
+.SS "Audit plugin API"
+.nf
+.RS 0n
+/* Audit plugin close function status types. */
+#define SUDO_PLUGIN_NO_STATUS 0
+#define SUDO_PLUGIN_WAIT_STATUS 1
+#define SUDO_PLUGIN_EXEC_ERROR 2
+#define SUDO_PLUGIN_SUDO_ERROR 3
+
+#define SUDO_AUDIT_PLUGIN 3
+struct audit_plugin {
+ unsigned int type; /* always SUDO_AUDIT_PLUGIN */
+ unsigned int version; /* always SUDO_API_VERSION */
+ int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr);
+ void (*close)(int status_type, int status);
+ int (*accept)(const char *plugin_name,
+ unsigned int plugin_type, char * const command_info[],
+ char * const run_argv[], char * const run_envp[],
+ const char **errstr);
+ int (*reject)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+ int (*error)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+ int (*show_version)(int verbose);
+ void (*register_hooks)(int version,
+ int (*register_hook)(struct sudo_hook *hook));
+ void (*deregister_hooks)(int version,
+ int (*deregister_hook)(struct sudo_hook *hook));
+ struct sudo_plugin_event * (*event_alloc)(void);
+}
+.RE
+.fi
+.PP
+An audit plugin can be used to log successful and unsuccessful attempts
+to run
+\fBsudo\fR
+independent of the policy or any I/O plugins.
+Multiple audit plugins may be specified in
+sudo.conf(@mansectform@).
+.PP
+A
+\fIstruct audit_plugin\fR
+has the following fields:
+.TP 6n
+\fItype\fR
+The
+\fItype\fR
+field should always be set to
+\fRSUDO_AUDIT_PLUGIN\fR.
+.TP 6n
+\fIversion\fR
+The
+\fIversion\fR
+field should be set to
+\fRSUDO_API_VERSION\fR.
+.sp
+This allows
+\fBsudo\fR
+to determine the API version the plugin was
+built against.
+.TP 6n
+\fIopen\fR
+.nf
+.RS 6n
+int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The audit
+\fBopen\fR()
+function is run before any other
+\fBsudo\fR
+plugin API functions.
+This makes it possible to audit failures in the other plugins.
+It returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+\fBsudo\fR
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional error information to the user.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIversion\fR
+The version passed in by
+\fBsudo\fR
+allows the plugin to determine the
+major and minor version number of the plugin API supported by
+\fBsudo\fR.
+.TP 6n
+\fIconversation\fR
+A pointer to the
+\fBconversation\fR()
+function that may be used by the
+\fBshow_version\fR()
+function to display version information (see
+\fBshow_version\fR()
+below).
+The
+\fBconversation\fR()
+function may also be used to display additional error message to the user.
+The
+\fBconversation\fR()
+function returns 0 on success, and \-1 on failure.
+.TP 6n
+\fIplugin_printf\fR
+A pointer to a
+\fBprintf\fR()-style
+function that may be used by the
+\fBshow_version\fR()
+function to display version information (see
+show_version below).
+The
+\fBplugin_printf\fR()
+function may also be used to display additional error message to the user.
+The
+\fBplugin_printf\fR()
+function returns number of characters printed on success and \-1 on failure.
+.TP 6n
+\fIsettings\fR
+A vector of user-supplied
+\fBsudo\fR
+settings in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+These settings correspond to options the user specified when running
+\fBsudo\fR.
+As such, they will only be present when the corresponding option has
+been specified on the command line.
+.sp
+When parsing
+\fIsettings\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible settings.
+.TP 6n
+\fIuser_info\fR
+A vector of information about the user running the command in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIuser_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible strings.
+.TP 6n
+\fIsubmit_optind\fR
+The index into
+\fIsubmit_argv\fR
+that corresponds to the first entry that is not a command line option.
+If
+\fIsubmit_argv\fR
+only consists of options, which may be the case with the
+\fB\-l\fR
+or
+\fB\-v\fR
+options,
+\fIsubmit_argv\fR[\fIsubmit_optind\fR]
+will evaluate to the NULL pointer.
+.TP 6n
+\fIsubmit_argv\fR
+The argument vector
+\fBsudo\fR
+was invoked with, including all command line options.
+The
+\fIsubmit_optind\fR
+argument can be used to determine the end of the command line options.
+.TP 6n
+\fIsubmit_envp\fR
+The invoking user's environment in the form of a
+\fRNULL\fR-terminated
+vector of
+\(lqname=value\(rq
+strings.
+.sp
+When parsing
+\fIsubmit_envp\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.TP 6n
+\fIplugin_options\fR
+Any (non-comment) strings immediately after the plugin path are
+treated as arguments to the plugin.
+These arguments are split on a white space boundary and are passed to
+the plugin in the form of a
+\fRNULL\fR-terminated
+array of strings.
+If no arguments were specified,
+\fIplugin_options\fR
+will be the
+\fRNULL\fR
+pointer.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBopen\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIclose\fR
+.br
+.nf
+.RS 6n
+void (*close)(int status_type, int status);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBclose\fR()
+function is called when
+\fBsudo\fR
+is finished, shortly before it exits.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIstatus_type\fR
+The type of status being passed.
+One of
+\fRSUDO_PLUGIN_NO_STATUS\fR,
+\fRSUDO_PLUGIN_WAIT_STATUS\fR,
+\fRSUDO_PLUGIN_EXEC_ERROR\fR
+or
+\fRSUDO_PLUGIN_SUDO_ERROR\fR.
+.TP 6n
+\fIstatus\fR
+Depending on the value of
+\fIstatus_type\fR,
+this value is either
+ignored, the command's exit status as returned by the
+wait(2)
+system call, the value of
+\fIerrno\fR
+set by the
+execve(2)
+system call, or the value of
+\fIerrno\fR
+resulting from an error in the
+\fBsudo\fR
+front-end.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIaccept\fR
+.nf
+.RS 6n
+int (*accept)(const char *plugin_name, unsigned int plugin_type,
+ char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBaccept\fR()
+function is called when a command or action is accepted by a policy
+or approval plugin.
+The function arguments are as follows:
+.TP 6n
+\fIplugin_name\fR
+The name of the plugin that accepted the command or
+\(lqsudo\(rq
+for the
+\fBsudo\fR
+front-end.
+.TP 6n
+\fIplugin_type\fR
+The type of plugin that accepted the command, currently either
+\fRSUDO_POLICY_PLUGIN\fR,
+\fRSUDO_POLICY_APPROVAL\fR,
+or
+\fRSUDO_FRONT_END\fR.
+The
+\fBaccept\fR()
+function is called multiple times--once for each policy or approval
+plugin that succeeds and once for the sudo front-end.
+When called on behalf of the sudo front-end,
+\fIcommand_info\fR
+may include information from an I/O logging plugin as well.
+.sp
+Typically, an audit plugin is interested in either the accept status from
+the
+\fBsudo\fR
+front-end or from the various policy and approval plugins, but not both.
+It is possible for the policy plugin to accept a command that is
+later rejected by an approval plugin, in which case the audit
+plugin's
+\fBaccept\fR()
+and
+\fBreject\fR()
+functions will
+\fIboth\fR
+be called.
+.TP 6n
+\fIcommand_info\fR
+An optional
+vector of information describing the command being run in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIcommand_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible strings.
+.TP 6n
+\fIrun_argv\fR
+A
+\fRNULL\fR-terminated
+argument vector describing a command that will be run in the
+same form as what would be passed to the
+execve(2)
+system call.
+.TP 6n
+\fIrun_envp\fR
+The environment the command will be run with in the form of a
+\fRNULL\fR-terminated
+vector of
+\(lqname=value\(rq
+strings.
+.sp
+When parsing
+\fIrun_envp\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBaccept\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIreject\fR
+.nf
+.RS 6n
+int (*reject)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBreject\fR()
+function is called when a command or action is rejected by a plugin.
+The function arguments are as follows:
+.TP 6n
+\fIplugin_name\fR
+The name of the plugin that rejected the command.
+.TP 6n
+\fIplugin_type\fR
+The type of plugin that rejected the command, currently either
+\fRSUDO_POLICY_PLUGIN\fR,
+\fRSUDO_APPROVAL_PLUGIN\fR,
+or
+\fRSUDO_IO_PLUGIN\fR.
+.sp
+Unlike the
+\fBaccept\fR()
+function, the
+\fBreject\fR()
+function is not called on behalf of the
+\fBsudo\fR
+front-end.
+.TP 6n
+\fIaudit_msg\fR
+An optional string describing the reason the command was rejected
+by the plugin.
+If the plugin did not provide a reason,
+\fIaudit_msg\fR
+will be the
+\fRNULL\fR
+pointer.
+.TP 6n
+\fIcommand_info\fR
+An optional
+vector of information describing the command being run in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIcommand_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible strings.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBreject\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIerror\fR
+.br
+.nf
+.RS 6n
+int (*error)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBerror\fR()
+function is called when a plugin or the
+\fBsudo\fR
+front-end returns an error.
+The function arguments are as follows:
+.TP 6n
+\fIplugin_name\fR
+The name of the plugin that generated the error or
+\(lqsudo\(rq
+for the
+\fBsudo\fR
+front-end.
+.TP 6n
+\fIplugin_type\fR
+The type of plugin that generated the error, or
+\fRSUDO_FRONT_END\fR
+for the
+\fBsudo\fR
+front-end.
+.TP 6n
+\fIaudit_msg\fR
+An optional string describing the plugin error.
+If the plugin did not provide a description,
+\fIaudit_msg\fR
+will be the
+\fRNULL\fR
+pointer.
+.TP 6n
+\fIcommand_info\fR
+An optional
+vector of information describing the command being run in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIcommand_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible strings.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBerror\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIshow_version\fR
+.nf
+.RS 6n
+int (*show_version)(int verbose);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBshow_version\fR()
+function is called by
+\fBsudo\fR
+when the user specifies the
+\fB\-V\fR
+option.
+The plugin may display its version information to the user via the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function using
+\fRSUDO_CONV_INFO_MSG\fR.
+If the user requests detailed version information, the verbose flag will be set.
+.sp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error, although the return value is currently
+ignored.
+.RE
+.TP 6n
+\fIregister_hooks\fR
+See the
+\fIPolicy plugin API\fR
+section for a description of
+\fBregister_hooks\fR().
+.TP 6n
+\fIderegister_hooks\fR
+See the
+\fIPolicy plugin API\fR
+section for a description of
+\fBderegister_hooks\fR().
+.TP 6n
+\fIevent_alloc\fR
+.nf
+.RS 6n
+struct sudo_plugin_event * (*event_alloc)(void);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBevent_alloc\fR()
+function is used to allocate a
+\fIstruct sudo_plugin_event\fR
+which provides access to the main
+\fBsudo\fR
+event loop.
+Unlike the other fields, the
+\fIevent_alloc\fR
+pointer is filled in by the
+\fBsudo\fR
+front-end, not by the plugin.
+.sp
+See the
+\fIEvent API\fR
+section below for more information
+about events.
+.sp
+The
+\fBevent_alloc\fR()
+function is only available starting
+with API version 1.17.
+If the
+\fBsudo\fR
+front-end doesn't support API
+version 1.17 or higher,
+\fBevent_alloc\fR()
+will not be set.
+.RE
+.SS "Approval plugin API"
+.nf
+.RS 0n
+struct approval_plugin {
+#define SUDO_APPROVAL_PLUGIN 4
+ unsigned int type; /* always SUDO_APPROVAL_PLUGIN */
+ unsigned int version; /* always SUDO_API_VERSION */
+ int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr);
+ void (*close)(void);
+ int (*check)(char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr);
+ int (*show_version)(int verbose);
+};
+.RE
+.fi
+.PP
+An approval plugin can be used to apply extra constraints after a
+command has been accepted by the policy plugin.
+Unlike the other plugin types, it does not remain open until the command
+completes.
+The plugin is opened before a call to
+\fBcheck\fR()
+or
+\fBshow_version\fR()
+and closed shortly thereafter (audit plugin functions must be called
+before the plugin is closed).
+Multiple approval plugins may be specified in
+sudo.conf(@mansectform@).
+.PP
+A
+\fIstruct approval_plugin\fR
+has the following fields:
+.TP 6n
+\fItype\fR
+The
+\fItype\fR
+field should always be set to
+\fRSUDO_APPROVAL_PLUGIN\fR.
+.TP 6n
+\fIversion\fR
+The
+\fIversion\fR
+field should be set to
+\fRSUDO_API_VERSION\fR.
+.sp
+This allows
+\fBsudo\fR
+to determine the API version the plugin was
+built against.
+.TP 6n
+\fIopen\fR
+.nf
+.RS 6n
+int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The approval
+\fBopen\fR()
+function is run immediately before a call to the plugin's
+\fBcheck\fR()
+or
+\fBshow_version\fR()
+functions.
+It is only called if the version is being requested or if the
+policy plugin's
+\fBcheck_policy\fR()
+function has returned successfully.
+It returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+\fBsudo\fR
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional error information to the user.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIversion\fR
+The version passed in by
+\fBsudo\fR
+allows the plugin to determine the
+major and minor version number of the plugin API supported by
+\fBsudo\fR.
+.TP 6n
+\fIconversation\fR
+A pointer to the
+\fBconversation\fR()
+function that can be used by the plugin to interact with the user (see
+\fIConversation API\fR
+for details).
+Returns 0 on success and \-1 on failure.
+.TP 6n
+\fIplugin_printf\fR
+A pointer to a
+\fBprintf\fR()-style
+function that may be used to display informational or error messages (see
+\fIConversation API\fR
+for details).
+Returns the number of characters printed on success and \-1 on failure.
+.TP 6n
+\fIsettings\fR
+A vector of user-supplied
+\fBsudo\fR
+settings in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+These settings correspond to options the user specified when running
+\fBsudo\fR.
+As such, they will only be present when the corresponding option has
+been specified on the command line.
+.sp
+When parsing
+\fIsettings\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible settings.
+.TP 6n
+\fIuser_info\fR
+A vector of information about the user running the command in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIuser_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible strings.
+.TP 6n
+\fIsubmit_optind\fR
+The index into
+\fIsubmit_argv\fR
+that corresponds to the first entry that is not a command line option.
+If
+\fIsubmit_argv\fR
+only consists of options, which may be the case with the
+\fB\-l\fR
+or
+\fB\-v\fR
+options,
+\fIsubmit_argv\fR[\fIsubmit_optind\fR]
+will evaluate to the NULL pointer.
+.TP 6n
+\fIsubmit_argv\fR
+The argument vector
+\fBsudo\fR
+was invoked with, including all command line options.
+The
+\fIsubmit_optind\fR
+argument can be used to determine the end of the command line options.
+.TP 6n
+\fIsubmit_envp\fR
+The invoking user's environment in the form of a
+\fRNULL\fR-terminated
+vector of
+\(lqname=value\(rq
+strings.
+.sp
+When parsing
+\fIsubmit_envp\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.TP 6n
+\fIplugin_options\fR
+Any (non-comment) strings immediately after the plugin path are
+treated as arguments to the plugin.
+These arguments are split on a white space boundary and are passed to
+the plugin in the form of a
+\fRNULL\fR-terminated
+array of strings.
+If no arguments were specified,
+\fIplugin_options\fR
+will be the
+\fRNULL\fR
+pointer.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBopen\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIclose\fR
+.br
+.nf
+.RS 6n
+void (*close)(void);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBclose\fR()
+function is called after the approval plugin's
+\fBcheck\fR()
+or
+\fBshow_version\fR()
+functions have been called.
+It takes no arguments.
+The
+\fBclose\fR()
+function is typically used to perform plugin-specific cleanup,
+such as the freeing of memory objects allocated by the plugin.
+If the plugin does not need to perform any cleanup,
+\fBclose\fR()
+may be set to the
+\fRNULL\fR
+pointer.
+.RE
+.TP 6n
+\fIcheck\fR
+.br
+.nf
+.RS 6n
+int (*check)(char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr);
+.RE
+.fi
+.RS 6n
+.sp
+The approval
+\fBcheck\fR()
+function is run after the policy plugin
+\fBcheck_policy\fR()
+function and before any I/O logging plugins.
+If multiple approval plugins are loaded, they must all succeed for
+the command to be allowed.
+It returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+\fBsudo\fR
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional error information to the user.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIcommand_info\fR
+A vector of information describing the command being run in the form of
+\(lqname=value\(rq
+strings.
+The vector is terminated by a
+\fRNULL\fR
+pointer.
+.sp
+When parsing
+\fIcommand_info\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.sp
+See the
+\fIPolicy plugin API\fR
+section for a list of all possible strings.
+.TP 6n
+\fIrun_argv\fR
+A
+\fRNULL\fR-terminated
+argument vector describing a command that will be run in the
+same form as what would be passed to the
+execve(2)
+system call.
+.TP 6n
+\fIrun_envp\fR
+The environment the command will be run with in the form of a
+\fRNULL\fR-terminated
+vector of
+\(lqname=value\(rq
+strings.
+.sp
+When parsing
+\fIrun_envp\fR,
+the plugin should split on the
+\fBfirst\fR
+equal sign
+(\(oq=\(cq)
+since the
+\fIname\fR
+field will never include one
+itself but the
+\fIvalue\fR
+might.
+.TP 6n
+\fIerrstr\fR
+If the
+\fBopen\fR()
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+\fIerrstr\fR.
+The
+\fBsudo\fR
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+\fIerrstr\fR
+must remain valid until the plugin's
+\fBclose\fR()
+function is called.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIshow_version\fR
+.nf
+.RS 6n
+int (*show_version)(int verbose);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBshow_version\fR()
+function is called by
+\fBsudo\fR
+when the user specifies the
+\fB\-V\fR
+option.
+The plugin may display its version information to the user via the
+\fBconversation\fR()
+or
+\fBplugin_printf\fR()
+function using
+\fRSUDO_CONV_INFO_MSG\fR.
+If the user requests detailed version information, the verbose flag will be set.
+.sp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error, although the return value is currently
+ignored.
+.RE
+.SS "Signal handlers"
+The
+\fBsudo\fR
+front-end installs default signal handlers to trap common signals
+while the plugin functions are run.
+The following signals are trapped by default before the command is
+executed:
+.TP 3n
+\fB\(bu\fR
+\fRSIGALRM\fR
+.PD 0
+.TP 3n
+\fB\(bu\fR
+\fRSIGHUP\fR
+.TP 3n
+\fB\(bu\fR
+\fRSIGINT\fR
+.TP 3n
+\fB\(bu\fR
+\fRSIGPIPE\fR
+.TP 3n
+\fB\(bu\fR
+\fRSIGQUIT\fR
+.TP 3n
+\fB\(bu\fR
+\fRSIGTERM\fR
+.TP 3n
+\fB\(bu\fR
+\fRSIGTSTP\fR
+.TP 3n
+\fB\(bu\fR
+\fRSIGUSR1\fR
+.TP 3n
+\fB\(bu\fR
+\fRSIGUSR2\fR
+.PD
+.PP
+If a fatal signal is received before the command is executed,
+\fBsudo\fR
+will call the plugin's
+\fBclose\fR()
+function with an exit status of 128 plus the value of the signal
+that was received.
+This allows for consistent logging of commands killed by a signal
+for plugins that log such information in their
+\fBclose\fR()
+function.
+An exception to this is
+\fRSIGPIPE\fR,
+which is ignored until the command is executed.
+.PP
+A plugin may temporarily install its own signal handlers but must
+restore the original handler before the plugin function returns.
+.SS "Hook function API"
+Beginning with plugin API version 1.2, it is possible to install
+hooks for certain functions called by the
+\fBsudo\fR
+front-end.
+.PP
+Currently, the only supported hooks relate to the handling of
+environment variables.
+Hooks can be used to intercept attempts to get, set, or remove
+environment variables so that these changes can be reflected in
+the version of the environment that is used to execute a command.
+A future version of the API will support hooking internal
+\fBsudo\fR
+front-end functions as well.
+.PP
+\fIHook structure\fR
+.PP
+Hooks in
+\fBsudo\fR
+are described by the following structure:
+.nf
+.sp
+.RS 0n
+typedef int (*sudo_hook_fn_t)();
+
+struct sudo_hook {
+ unsigned int hook_version;
+ unsigned int hook_type;
+ sudo_hook_fn_t hook_fn;
+ void *closure;
+};
+.RE
+.fi
+.PP
+A
+\fIstruct sudo_hook\fR
+has the following fields:
+.TP 6n
+\fIhook_version\fR
+The
+\fIhook_version\fR
+field should be set to
+\fRSUDO_HOOK_VERSION\fR.
+.TP 6n
+\fIhook_type\fR
+The
+\fIhook_type\fR
+field may be one of the following supported hook types:
+.PP
+.RS 6n
+.PD 0
+.TP 6n
+\fRSUDO_HOOK_SETENV\fR
+The C library
+setenv(3)
+function.
+Any registered hooks will run before the C library implementation.
+The
+\fIhook_fn\fR
+field should
+be a function that matches the following typedef:
+.nf
+.sp
+.RS 6n
+typedef int (*sudo_hook_fn_setenv_t)(const char *name,
+ const char *value, int overwrite, void *closure);
+.RE
+.fi
+.RS 6n
+.sp
+If the registered hook does not match the typedef the results are
+unspecified.
+.RE
+.PD
+.TP 6n
+\fRSUDO_HOOK_UNSETENV\fR
+The C library
+unsetenv(3)
+function.
+Any registered hooks will run before the C library implementation.
+The
+\fIhook_fn\fR
+field should
+be a function that matches the following typedef:
+.nf
+.sp
+.RS 6n
+typedef int (*sudo_hook_fn_unsetenv_t)(const char *name,
+ void *closure);
+.RE
+.fi
+.TP 6n
+\fRSUDO_HOOK_GETENV\fR
+The C library
+getenv(3)
+function.
+Any registered hooks will run before the C library implementation.
+The
+\fIhook_fn\fR
+field should
+be a function that matches the following typedef:
+.nf
+.sp
+.RS 6n
+typedef int (*sudo_hook_fn_getenv_t)(const char *name,
+ char **value, void *closure);
+.RE
+.fi
+.RS 6n
+.sp
+If the registered hook does not match the typedef the results are
+unspecified.
+.RE
+.TP 6n
+\fRSUDO_HOOK_PUTENV\fR
+The C library
+putenv(3)
+function.
+Any registered hooks will run before the C library implementation.
+The
+\fIhook_fn\fR
+field should
+be a function that matches the following typedef:
+.nf
+.sp
+.RS 6n
+typedef int (*sudo_hook_fn_putenv_t)(char *string,
+ void *closure);
+.RE
+.fi
+.RS 6n
+.sp
+If the registered hook does not match the typedef the results are
+unspecified.
+.RE
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIhook_fn\fR
+.nf
+.RS 6n
+sudo_hook_fn_t hook_fn;
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fIhook_fn\fR
+field should be set to the plugin's hook implementation.
+The actual function arguments will vary depending on the
+\fIhook_type\fR
+(see
+\fIhook_type\fR
+above).
+In all cases, the
+\fIclosure\fR
+field of
+\fIstruct sudo_hook\fR
+is passed as the last function parameter.
+This can be used to pass arbitrary data to the plugin's hook implementation.
+.sp
+The function return value may be one of the following:
+.TP 6n
+\fRSUDO_HOOK_RET_ERROR\fR
+The hook function encountered an error.
+.TP 6n
+\fRSUDO_HOOK_RET_NEXT\fR
+The hook completed without error, go on to the next hook (including
+the system implementation if applicable).
+For example, a
+getenv(3)
+hook might return
+\fRSUDO_HOOK_RET_NEXT\fR
+if the specified variable was not found in the private copy of the environment.
+.TP 6n
+\fRSUDO_HOOK_RET_STOP\fR
+The hook completed without error, stop processing hooks for this invocation.
+This can be used to replace the system implementation.
+For example, a
+\fIsetenv\fR
+hook that operates on a private copy of
+the environment but leaves
+\fIenviron\fR
+unchanged.
+.PD 0
+.PP
+.RE
+.PD
+.PP
+Care must be taken when hooking C library functions,
+it is very easy to create an infinite loop.
+For example, a
+getenv(3)
+hook that calls the
+snprintf(3)
+function may create a loop if the
+snprintf(3)
+implementation calls
+getenv(3)
+to check the locale.
+To prevent this, you may wish to use a static variable in the hook
+function to guard against nested calls.
+For example:
+.nf
+.sp
+.RS 6n
+static int in_progress = 0; /* avoid recursion */
+if (in_progress)
+ return SUDO_HOOK_RET_NEXT;
+in_progress = 1;
+\&...
+in_progress = 0;
+return SUDO_HOOK_RET_STOP;
+.RE
+.fi
+.PP
+\fIHook API Version Macros\fR
+.nf
+.sp
+.RS 0n
+/* Hook API version major/minor */
+#define SUDO_HOOK_VERSION_MAJOR 1
+#define SUDO_HOOK_VERSION_MINOR 0
+#define SUDO_HOOK_VERSION SUDO_API_MKVERSION(SUDO_HOOK_VERSION_MAJOR,\e
+ SUDO_HOOK_VERSION_MINOR)
+.RE
+.fi
+.PP
+For getters and setters see the
+\fIPolicy plugin API\fR.
+.SS "Event API"
+When
+\fBsudo\fR
+runs a command, it uses an event loop to service signals and I/O.
+Events may be triggered based on time, a file or socket descriptor
+becoming ready, or due to receipt of a signal.
+Starting with API version 1.15, it is possible for a plugin to
+participate in this event loop by calling the
+\fBevent_alloc\fR()
+function.
+.PP
+\fIEvent structure\fR
+.PP
+Events are described by the following structure:
+.nf
+.RS 0n
+typedef void (*sudo_plugin_ev_callback_t)(int fd, int what, void *closure);
+
+struct sudo_plugin_event {
+ int (*set)(struct sudo_plugin_event *pev, int fd, int events,
+ sudo_plugin_ev_callback_t callback, void *closure);
+ int (*add)(struct sudo_plugin_event *pev, struct timespec *timeout);
+ int (*del)(struct sudo_plugin_event *pev);
+ int (*pending)(struct sudo_plugin_event *pev, int events,
+ struct timespec *ts);
+ int (*fd)(struct sudo_plugin_event *pev);
+ void (*setbase)(struct sudo_plugin_event *pev, void *base);
+ void (*loopbreak)(struct sudo_plugin_event *pev);
+ void (*free)(struct sudo_plugin_event *pev);
+};
+.RE
+.fi
+.PP
+A
+\fIstruct sudo_plugin_event\fR
+contains the following function pointers:
+.TP 6n
+\fIset\fR
+.nf
+.RS 6n
+int (*set)(struct sudo_plugin_event *pev, int fd, int events,
+ sudo_plugin_ev_callback_t callback, void *closure);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBset\fR()
+function takes the following arguments:
+.TP 6n
+\fIstruct sudo_plugin_event *\fR\fIpev\fR
+A pointer to the
+\fIstruct sudo_plugin_event\fR
+itself.
+.TP 6n
+\fIfd\fR
+The file or socket descriptor for I/O-based events or the signal
+number for signal events.
+For time-based events,
+\fIfd\fR
+must be \-1.
+.TP 6n
+\fIevents\fR
+The following values determine what will trigger the event callback:
+.PP
+.RS 6n
+.PD 0
+.TP 6n
+\fRSUDO_PLUGIN_EV_TIMEOUT\fR
+callback is run after the specified timeout expires
+.PD
+.TP 6n
+\fRSUDO_PLUGIN_EV_READ\fR
+callback is run when the file descriptor is readable
+.TP 6n
+\fRSUDO_PLUGIN_EV_WRITE\fR
+callback is run when the file descriptor is writable
+.TP 6n
+\fRSUDO_PLUGIN_EV_PERSIST\fR
+event is persistent and remains enabled until explicitly deleted
+.TP 6n
+\fRSUDO_PLUGIN_EV_SIGNAL\fR
+callback is run when the specified signal is received
+.PP
+The
+\fRSUDO_PLUGIN_EV_PERSIST\fR
+flag may be ORed with any of the event types.
+It is also possible to OR
+\fRSUDO_PLUGIN_EV_READ\fR
+and
+\fRSUDO_PLUGIN_EV_WRITE\fR
+together to run the callback when a descriptor is ready to be
+either read from or written to.
+All other event values are mutually exclusive.
+.RE
+.TP 6n
+\fIsudo_plugin_ev_callback_t\fR \fIcallback\fR
+.nf
+.RS 6n
+typedef void (*sudo_plugin_ev_callback_t)(int fd, int what,
+ void *closure);
+.RE
+.fi
+.RS 6n
+.sp
+The function to call when an event is triggered.
+The
+\fBcallback\fR()
+function is run with the following arguments:
+.TP 6n
+\fIfd\fR
+The file or socket descriptor for I/O-based events or the signal
+number for signal events.
+.TP 6n
+\fIwhat\fR
+The event type that triggered that callback.
+For events that have multiple event types (for example
+\fRSUDO_PLUGIN_EV_READ\fR
+and
+\fRSUDO_PLUGIN_EV_WRITE\fR)
+or have an associated timeout,
+\fIwhat\fR
+can be used to determine why the callback was run.
+.TP 6n
+\fIclosure\fR
+The generic pointer that was specified in the
+\fBset\fR()
+function.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIclosure\fR
+A generic pointer that will be passed to the callback function.
+.PP
+The
+\fBset\fR()
+function returns 1 on success, and \-1 if a error occurred.
+.RE
+.TP 6n
+\fIadd\fR
+.nf
+.RS 6n
+int (*add)(struct sudo_plugin_event *pev, struct timespec *timeout);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBadd\fR()
+function adds the event
+\fIpev\fR
+to
+\fBsudo\fR's
+event loop.
+The event must have previously been initialized via the
+\fBset\fR()
+function.
+If the
+\fItimeout\fR
+argument is not NULL, it should specify a (relative) timeout after
+which the event will be triggered if the main event criteria has
+not been met.
+This is often used to implement an I/O timeout where the event
+will fire if a descriptor is not ready within a certain time
+period.
+If the event is already present in the event loop, its
+\fItimeout\fR
+will be adjusted to match the new value, if any.
+.sp
+The
+\fBadd\fR()
+function returns 1 on success, and \-1 if a error occurred.
+.RE
+.TP 6n
+\fIdel\fR
+.nf
+.RS 6n
+int (*del)(struct sudo_plugin_event *pev);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBdel\fR()
+function deletes the event
+\fIpev\fR
+from
+\fBsudo\fR's
+event loop.
+Deleted events can be added back via the
+\fBadd\fR()
+function.
+.sp
+The
+\fBdel\fR()
+function returns 1 on success, and \-1 if a error occurred.
+.RE
+.TP 6n
+\fIpending\fR
+.nf
+.RS 6n
+int (*pending)(struct sudo_plugin_event *pev, int events,
+ struct timespec *ts);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBpending\fR()
+function can be used to determine whether one or more events is pending.
+The
+\fIevents\fR
+argument specifies which events to check for.
+See the
+\fBset\fR()
+function for a list of valid event types.
+If
+\fRSUDO_PLUGIN_EV_TIMEOUT\fR
+is specified in
+\fIevents\fR,
+the event has an associated timeout and the
+\fIts\fR
+pointer is non-NULL, it will be filled in with the remaining time.
+.RE
+.TP 6n
+\fIfd\fR
+.nf
+.RS 6n
+int (*fd)(struct sudo_plugin_event *pev);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBfd\fR()
+function returns the descriptor or signal number associated with
+the event
+\fIpev\fR.
+.RE
+.TP 6n
+\fIsetbase\fR
+.nf
+.RS 6n
+void (*setbase)(struct sudo_plugin_event *pev, void *base);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBsetbase\fR()
+function sets the underlying event
+\fIbase\fR
+for
+\fIpev\fR
+to the specified value.
+This can be used to move an event created via
+\fBevent_alloc\fR()
+to a new event loop allocated by sudo's event subsystem.
+If
+\fIbase\fR
+is
+\fRNULL\fR,
+\fIpev\fR's
+event base is reset to the default value, which corresponds to
+\fBsudo\fR's
+main event loop.
+Using this function requires linking the plugin with the sudo_util
+library.
+It is unlikely to be used outside of the
+\fBsudoers\fR
+plugin.
+.RE
+.TP 6n
+\fIloopbreak\fR
+.nf
+.RS 6n
+void (*loopbreak)(struct sudo_plugin_event *pev);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBloopbreak\fR()
+function causes
+\fBsudo\fR's
+event loop to exit immediately and the running command to be terminated.
+.RE
+.TP 6n
+\fIfree\fR
+.nf
+.RS 6n
+void (*free)(struct sudo_plugin_event *pev);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBfree\fR()
+function deletes the event
+\fIpev\fR
+from the event loop and frees the memory associated with it.
+.RE
+.SS "Remote command execution"
+The
+\fBsudo\fR
+front-end does not support running remote commands.
+However, starting with
+\fBsudo\fR
+1.8.8, the
+\fB\-h\fR
+option may be used to specify a remote host that is passed
+to the policy plugin.
+A plugin may also accept a
+\fIrunas_user\fR
+in the form of
+\(lquser@hostname\(rq
+which will work with older versions of
+\fBsudo\fR.
+It is anticipated that remote commands will be supported by executing a
+\(lqhelper\(rq
+program.
+The policy plugin should setup the execution environment such that the
+\fBsudo\fR
+front-end will run the helper which, in turn, will connect to the
+remote host and run the command.
+.PP
+For example, the policy plugin could utilize
+\fBssh\fR
+to perform remote command execution.
+The helper program would be responsible for running
+\fBssh\fR
+with the proper options to use a private key or certificate
+that the remote host will accept and run a program
+on the remote host that would setup the execution environment
+accordingly.
+.PP
+Remote
+\fBsudoedit\fR
+functionality must be handled by the policy plugin, not
+\fBsudo\fR
+itself as the front-end has no knowledge that a remote command is
+being executed.
+This may be addressed in a future revision of the plugin API.
+.SS "Conversation API"
+If the plugin needs to interact with the user, it may do so via the
+\fBconversation\fR()
+function.
+A plugin should not attempt to read directly from the standard input
+or the user's terminal (neither of which are guaranteed to exist).
+The caller must include a trailing newline in
+\fImsg\fR
+if one is to be printed.
+.PP
+A
+\fBprintf\fR()-style
+function is also available that can be used to display informational
+or error messages to the user, which is usually more convenient for
+simple messages where no use input is required.
+.PP
+\fIConversation function structures\fR
+.PP
+The conversation function takes as arguments pointers to the following
+structures:
+.nf
+.sp
+.RS 0n
+struct sudo_conv_message {
+#define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */
+#define SUDO_CONV_PROMPT_ECHO_ON 0x0002 /* echo user input */
+#define SUDO_CONV_ERROR_MSG 0x0003 /* error message */
+#define SUDO_CONV_INFO_MSG 0x0004 /* informational message */
+#define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */
+#define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */
+#define SUDO_CONV_PREFER_TTY 0x2000 /* flag: use tty if possible */
+ int msg_type;
+ int timeout;
+ const char *msg;
+};
+
+#define SUDO_CONV_REPL_MAX 1023
+
+struct sudo_conv_reply {
+ char *reply;
+};
+
+typedef int (*sudo_conv_callback_fn_t)(int signo, void *closure);
+struct sudo_conv_callback {
+ unsigned int version;
+ void *closure;
+ sudo_conv_callback_fn_t on_suspend;
+ sudo_conv_callback_fn_t on_resume;
+};
+.RE
+.fi
+.PP
+Pointers to the
+\fBconversation\fR()
+and
+\fBprintf\fR()-style
+functions are passed
+in to the plugin's
+\fBopen\fR()
+function when the plugin is initialized.
+The following type definitions can be used in the declaration of the
+\fBopen\fR()
+function:
+.nf
+.sp
+.RS 0n
+typedef int (*sudo_conv_t)(int num_msgs,
+ const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback);
+
+typedef int (*sudo_printf_t)(int msg_type, const char * restrict fmt, ...);
+.RE
+.fi
+.PP
+To use the
+\fBconversation\fR()
+function, the plugin must pass an array of
+\fIstruct sudo_conv_message\fR
+and
+\fIstruct sudo_conv_reply\fR.
+There must be a
+\fIstruct sudo_conv_message\fR
+and
+\fIstruct sudo_conv_reply\fR
+for each message in the conversation, that is, both arrays must
+have the same number of elements.
+Each
+\fIstruct sudo_conv_reply\fR
+must have its
+\fIreply\fR
+member initialized to
+\fRNULL\fR.
+The
+\fIstruct sudo_conv_callback\fR
+pointer, if not
+\fRNULL\fR,
+should contain function pointers to be called when the
+\fBsudo\fR
+process is suspended and/or resumed during conversation input.
+The
+\fIon_suspend\fR
+and
+\fIon_resume\fR
+functions are called with the signal that caused
+\fBsudo\fR
+to be suspended and the
+\fIclosure\fR
+pointer from the
+\fIstruct sudo_conv_callback\fR.
+These functions should return 0 on success and \-1 on error.
+On error, the conversation will end and the conversation function
+will return a value of \-1.
+The intended use is to allow the plugin to release resources, such as locks,
+that should not be held indefinitely while suspended and then reacquire them
+when the process is resumed.
+The functions are not actually invoked from within a signal handler.
+.PP
+The
+\fImsg_type\fR
+must be set to one of the following values:
+.TP 6n
+\fRSUDO_CONV_PROMPT_ECHO_OFF\fR
+Prompt the user for input with echo disabled;
+this is generally used for passwords.
+The reply will be stored in the
+\fIreplies\fR
+array, and it will never be
+\fRNULL\fR.
+.TP 6n
+\fRSUDO_CONV_PROMPT_ECHO_ON\fR
+Prompt the user for input with echo enabled.
+The reply will be stored in the
+\fIreplies\fR
+array, and it will never be
+\fRNULL\fR.
+.TP 6n
+\fRSUDO_CONV_ERROR_MSG\fR
+Display an error message.
+The message is written to the standard error unless the
+\fRSUDO_CONV_PREFER_TTY\fR
+flag is set, in which case it is written to the user's terminal if possible.
+.TP 6n
+\fRSUDO_CONV_INFO_MSG\fR
+Display a message.
+The message is written to the standard output unless the
+\fRSUDO_CONV_PREFER_TTY\fR
+flag is set, in which case it is written to the user's terminal if possible.
+.TP 6n
+\fRSUDO_CONV_PROMPT_MASK\fR
+Prompt the user for input but echo an asterisk character for each
+character read.
+The reply will be stored in the
+\fIreplies\fR
+array, and it will never be
+\fRNULL\fR.
+This can be used to provide visual feedback to the user while reading
+sensitive information that should not be displayed.
+.PP
+In addition to the above values, the following flag bits may also be set:
+.TP 6n
+\fRSUDO_CONV_PROMPT_ECHO_OK\fR
+Allow input to be read when echo cannot be disabled
+when the message type is
+\fRSUDO_CONV_PROMPT_ECHO_OFF\fR
+or
+\fRSUDO_CONV_PROMPT_MASK\fR.
+By default,
+\fBsudo\fR
+will refuse to read input if the echo cannot be disabled for those
+message types.
+.TP 6n
+\fRSUDO_CONV_PREFER_TTY\fR
+When displaying a message via
+\fRSUDO_CONV_ERROR_MSG\fR
+or
+\fRSUDO_CONV_INFO_MSG\fR,
+try to write the message to the user's terminal.
+If the terminal is unavailable, the standard error or standard output
+will be used, depending upon whether
+\fRSUDO_CONV_ERROR_MSG\fR
+or
+\fRSUDO_CONV_INFO_MSG\fR
+was used.
+The user's terminal is always used when possible for input,
+this flag is only used for output.
+.PP
+The
+\fItimeout\fR
+in seconds until the prompt will wait for no more input.
+A zero value implies an infinite timeout.
+.PP
+The plugin is responsible for freeing the reply buffer located in each
+\fIstruct sudo_conv_reply\fR,
+if it is not
+\fRNULL\fR.
+\fRSUDO_CONV_REPL_MAX\fR
+represents the maximum length of the reply buffer (not including
+the trailing NUL character).
+In practical terms, this is the longest password
+\fBsudo\fR
+will support.
+.PP
+The
+\fBprintf\fR()-style
+function uses the same underlying mechanism as the
+\fBconversation\fR()
+function but only supports
+\fRSUDO_CONV_INFO_MSG\fR
+and
+\fRSUDO_CONV_ERROR_MSG\fR
+for the
+\fImsg_type\fR
+parameter.
+It can be more convenient than using the
+\fBconversation\fR()
+function if no user reply is needed and supports standard
+\fBprintf\fR()
+escape sequences.
+.PP
+See the sample plugin for an example of the
+\fBconversation\fR()
+function usage.
+.SS "Plugin invocation order"
+As of
+\fBsudo\fR
+1.9.0, the plugin
+\fBopen\fR()
+and
+\fBclose\fR()
+functions are called in the
+following order:
+.TP 5n
+1.\&
+audit open
+.TP 5n
+2.\&
+policy open
+.TP 5n
+3.\&
+approval open
+.TP 5n
+4.\&
+approval close
+.TP 5n
+5.\&
+I/O log open
+.TP 5n
+6.\&
+command runs
+.TP 5n
+7.\&
+command exits
+.TP 5n
+8.\&
+I/O log close
+.TP 5n
+9.\&
+policy close
+.TP 5n
+10.\&
+audit close
+.TP 5n
+11.\&
+sudo exits
+.PP
+Prior to
+\fBsudo\fR
+1.9.0, the I/O log
+\fBclose\fR()
+function was called
+\fIafter\fR
+the policy
+\fBclose\fR()
+function.
+.SS "Sudoers group plugin API"
+The
+\fBsudoers\fR
+plugin supports its own plugin interface to allow non-Unix
+group lookups.
+This can be used to query a group source other than the standard Unix
+group database.
+Two sample group plugins are bundled with
+\fBsudo\fR,
+\fIgroup_file\fR,
+and
+\fIsystem_group\fR,
+are detailed in
+sudoers(@mansectform@).
+Third party group plugins include a QAS AD plugin available from Quest Software.
+.PP
+A group plugin must declare and populate a
+\fIstruct sudoers_group_plugin\fR
+in the global scope.
+This structure contains pointers to the functions that implement plugin
+initialization, cleanup, and group lookup.
+.nf
+.sp
+.RS 0n
+struct sudoers_group_plugin {
+ unsigned int version;
+ int (*init)(int version, sudo_printf_t sudo_plugin_printf,
+ char *const argv[]);
+ void (*cleanup)(void);
+ int (*query)(const char *user, const char *group,
+ const struct passwd *pwd);
+};
+.RE
+.fi
+.PP
+A
+\fIstruct sudoers_group_plugin\fR
+has the following fields:
+.TP 6n
+\fIversion\fR
+The
+\fIversion\fR
+field should be set to GROUP_API_VERSION.
+.sp
+This allows
+\fBsudoers\fR
+to determine the API version the group plugin
+was built against.
+.TP 6n
+\fIinit\fR
+.nf
+.RS 6n
+int (*init)(int version, sudo_printf_t sudo_plugin_printf,
+ char *const argv[]);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBinit\fR()
+function is called after
+\fIsudoers\fR
+has been parsed but
+before any policy checks.
+It returns 1 on success, 0 on failure (or if the plugin is not configured),
+and \-1 if a error occurred.
+If an error occurs, the plugin may call the
+\fBplugin_printf\fR()
+function with
+\fRSUDO_CONF_ERROR_MSG\fR
+to present additional error information to the user.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIversion\fR
+The version passed in by
+\fBsudoers\fR
+allows the plugin to determine the
+major and minor version number of the group plugin API supported by
+\fBsudoers\fR.
+.TP 6n
+\fIplugin_printf\fR
+A pointer to a
+\fBprintf\fR()-style
+function that may be used to display informational or error message to the user.
+Returns the number of characters printed on success and \-1 on failure.
+.TP 6n
+\fIargv\fR
+A
+\fRNULL\fR-terminated
+array of arguments generated from the
+\fIgroup_plugin\fR
+option in
+\fIsudoers\fR.
+If no arguments were given,
+\fIargv\fR
+will be
+\fRNULL\fR.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIcleanup\fR
+.nf
+.RS 6n
+void (*cleanup)();
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBcleanup\fR()
+function is called when
+\fBsudoers\fR
+has finished its
+group checks.
+The plugin should free any memory it has allocated and close open file handles.
+.RE
+.TP 6n
+\fIquery\fR
+.br
+.nf
+.RS 6n
+int (*query)(const char *user, const char *group,
+ const struct passwd *pwd);
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBquery\fR()
+function is used to ask the group plugin whether
+\fIuser\fR
+is a member of
+\fIgroup\fR.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIuser\fR
+The name of the user being looked up in the external group database.
+.TP 6n
+\fIgroup\fR
+.br
+The name of the group being queried.
+.TP 6n
+\fIpwd\fR
+The password database entry for
+\fIuser\fR,
+if any.
+If
+\fIuser\fR
+is not
+present in the password database,
+\fIpwd\fR
+will be
+\fRNULL\fR.
+.PD 0
+.PP
+.RE
+.PD
+.PP
+\fIGroup API Version Macros\fR
+.nf
+.sp
+.RS 0n
+/* Sudoers group plugin version major/minor */
+#define GROUP_API_VERSION_MAJOR 1
+#define GROUP_API_VERSION_MINOR 0
+#define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \e
+ GROUP_API_VERSION_MINOR)
+.RE
+.fi
+For getters and setters see the
+\fIPolicy plugin API\fR.
+.SH "PLUGIN API CHANGELOG"
+The following revisions have been made to the Sudo Plugin API.
+.TP 6n
+Version 1.0
+Initial API version.
+.TP 6n
+Version 1.1 (sudo 1.8.0)
+The I/O logging plugin's
+\fBopen\fR()
+function was modified to take the
+\fIcommand_info\fR
+list as an argument.
+.TP 6n
+Version 1.2 (sudo 1.8.5)
+The Policy and I/O logging plugins'
+\fBopen\fR()
+functions are now passed
+a list of plugin parameters if any are specified in
+sudo.conf(@mansectform@).
+.sp
+A simple hooks API has been introduced to allow plugins to hook in to the
+system's environment handling functions.
+.sp
+The
+\fBinit_session\fR()
+Policy plugin function is now passed a pointer
+to the user environment which can be updated as needed.
+This can be used to merge in environment variables stored in the PAM
+handle before a command is run.
+.TP 6n
+Version 1.3 (sudo 1.8.7)
+Support for the
+\fIexec_background\fR
+entry has been added to the
+\fIcommand_info\fR
+list.
+.sp
+The
+\fImax_groups\fR
+and
+\fIplugin_dir\fR
+entries were added to the
+\fIsettings\fR
+list.
+.sp
+The
+\fBversion\fR()
+and
+\fBclose\fR()
+functions are now optional.
+Previously, a missing
+\fBversion\fR()
+or
+\fBclose\fR()
+function would result in a crash.
+If no policy plugin
+\fBclose\fR()
+function is defined, a default
+\fBclose\fR()
+function will be provided by the
+\fBsudo\fR
+front-end that displays a warning if the command could not be
+executed.
+.sp
+The
+\fBsudo\fR
+front-end now installs default signal handlers to trap common signals
+while the plugin functions are run.
+.TP 6n
+Version 1.4 (sudo 1.8.8)
+The
+\fIremote_host\fR
+entry was added to the
+\fIsettings\fR
+list.
+.TP 6n
+Version 1.5 (sudo 1.8.9)
+The
+\fIpreserve_fds\fR
+entry was added to the
+\fIcommand_info\fR
+list.
+.TP 6n
+Version 1.6 (sudo 1.8.11)
+The behavior when an I/O logging plugin returns an error
+(\-1)
+has changed.
+Previously, the
+\fBsudo\fR
+front-end took no action when the
+\fBlog_ttyin\fR(),
+\fBlog_ttyout\fR(),
+\fBlog_stdin\fR(),
+\fBlog_stdout\fR(),
+or
+\fBlog_stderr\fR()
+function returned an error.
+.sp
+The behavior when an I/O logging plugin returns 0 has changed.
+Previously, output from the command would be displayed to the
+terminal even if an output logging function returned 0.
+.TP 6n
+Version 1.7 (sudo 1.8.12)
+The
+\fIplugin_path\fR
+entry was added to the
+\fIsettings\fR
+list.
+.sp
+The
+\fIdebug_flags\fR
+entry now starts with a debug file path name and may occur multiple
+times if there are multiple plugin-specific Debug lines in the
+sudo.conf(@mansectform@) file.
+.TP 6n
+Version 1.8 (sudo 1.8.15)
+The
+\fIsudoedit_checkdir\fR
+and
+\fIsudoedit_follow\fR
+entries were added to the
+\fIcommand_info\fR
+list.
+The default value of
+\fIsudoedit_checkdir\fR
+was changed to true in sudo 1.8.16.
+.sp
+The sudo
+\fBconversation\fR()
+function now takes a pointer to a
+\fIstruct sudo_conv_callback\fR
+as its fourth argument.
+The
+\fIsudo_conv_t\fR
+definition has been updated to match.
+The plugin must specify that it supports plugin API version 1.8 or higher
+to receive a conversation function pointer that supports this argument.
+.TP 6n
+Version 1.9 (sudo 1.8.16)
+The
+\fIexecfd\fR
+entry was added to the
+\fIcommand_info\fR
+list.
+.TP 6n
+Version 1.10 (sudo 1.8.19)
+The
+\fIumask\fR
+entry was added to the
+\fIuser_info\fR
+list.
+The
+\fIiolog_group\fR,
+\fIiolog_mode\fR,
+and
+\fIiolog_user\fR
+entries were added to the
+\fIcommand_info\fR
+list.
+.TP 6n
+Version 1.11 (sudo 1.8.20)
+The
+\fItimeout\fR
+entry was added to the
+\fIsettings\fR
+list.
+.TP 6n
+Version 1.12 (sudo 1.8.21)
+The
+\fBchange_winsize\fR()
+function was added to
+\fIstruct io_plugin\fR.
+.TP 6n
+Version 1.13 (sudo 1.8.26)
+The
+\fBlog_suspend\fR()
+function was added to
+\fIstruct io_plugin\fR.
+.TP 6n
+Version 1.14 (sudo 1.8.29)
+The
+\fIumask_override\fR
+entry was added to the
+\fIcommand_info\fR
+list.
+.TP 6n
+Version 1.15 (sudo 1.9.0)
+The
+\fIcwd_optional\fR
+entry was added to the
+\fIcommand_info\fR
+list.
+.sp
+The
+\fBevent_alloc\fR()
+function was added to
+\fIstruct policy_plugin\fR
+and
+\fIstruct io_plugin\fR.
+.sp
+The
+\fIerrstr\fR
+argument was added to the policy and I/O plugin functions
+which the plugin function can use to return an error string.
+This string may be used by the audit plugin to report failure or
+error conditions set by the other plugins.
+.sp
+The
+\fBclose\fR()
+function is now is called regardless of whether or not a command
+was actually executed.
+This makes it possible for plugins to perform cleanup even when a
+command was not run.
+.sp
+\fRSUDO_CONV_REPL_MAX\fR
+has increased from 255 to 1023 bytes.
+.sp
+Support for audit and approval plugins was added.
+.TP 6n
+Version 1.16 (sudo 1.9.3)
+Initial resource limit values were added to the
+\fIuser_info\fR
+list.
+.sp
+The
+\fIcmnd_chroot\fR
+and
+\fIcmnd_cwd\fR
+entries were added to the
+\fIsettings\fR
+list.
+.TP 6n
+Version 1.17 (sudo 1.9.4)
+The
+\fBevent_alloc\fR()
+function was added to
+\fIstruct audit_plugin\fR
+and
+\fIstruct approval_plugin\fR.
+.TP 6n
+Version 1.18 (sudo 1.9.9)
+The policy may now set resource limit values in the
+\fIcommand_info\fR
+list.
+The
+\fIintercept\fR
+and
+\fIlog_subcmds\fR
+entries were added to the
+\fIcommand_info\fR
+list.
+.TP 6n
+Version 1.19 (sudo 1.9.11)
+The
+\fIintercept_ptrace\fR
+and
+\fIintercept_setid\fR
+entries were added to the
+\fIsettings\fR
+list.
+The
+\fIapparmor_profile\fR
+and
+\fIuse_ptrace\fR
+entries were added to the
+\fIcommand_info\fR
+list.
+.TP 6n
+Version 1.20 (sudo 1.9.12)
+The
+\fIupdate_ticket\fR
+entry was added to the
+\fIsettings\fR
+list.
+The
+\fIintercept_verify\fR
+entry was added to the
+\fIcommand_info\fR
+list.
+.TP 6n
+Version 1.21 (sudo 1.9.13)
+The
+\fIsudoedit_nfiles\fR
+entry was added to the
+\fIcommand_info\fR
+list.
+.SH "SEE ALSO"
+sudo.conf(@mansectform@),
+sudoers(@mansectform@),
+sudo(@mansectsu@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS.md file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you believe you have found a bug in
+\fBsudo\fR,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudo_plugin.mdoc.in b/docs/sudo_plugin.mdoc.in
new file mode 100644
index 0000000..b604dbe
--- /dev/null
+++ b/docs/sudo_plugin.mdoc.in
@@ -0,0 +1,4895 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2009-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd July 10, 2023
+.Dt SUDO_PLUGIN @mansectform@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudo_plugin
+.Nd Sudo Plugin API
+.Sh DESCRIPTION
+Starting with version 1.8,
+.Nm sudo
+supports a plugin API
+for policy and session logging.
+Plugins may be compiled as dynamic shared objects (the default on
+systems that support them) or compiled statically into the
+.Nm sudo
+binary itself.
+By default, the
+.Nm sudoers
+plugin provides audit, security policy and I/O logging capabilities.
+Via the plugin API,
+.Nm sudo
+can be configured to use alternate plugins provided by third parties.
+The plugins to be used are specified in the
+.Xr sudo.conf @mansectform@
+file.
+.Pp
+The API is versioned with a major and minor number.
+The minor version number is incremented when additions are made.
+The major number is incremented when incompatible changes are made.
+A plugin should be check the version passed to it and make sure that the
+major version matches.
+.Pp
+The plugin API is defined by the
+.In sudo_plugin.h
+header file.
+.Ss Policy plugin API
+A policy plugin must declare and populate a
+.Vt struct policy_plugin
+in the global scope.
+This structure contains pointers to the functions that implement the
+.Nm sudo
+policy checks.
+The name of the symbol should be specified in
+.Xr sudo.conf @mansectform@
+along with a path to the plugin so that
+.Nm sudo
+can load it.
+.Bd -literal
+struct policy_plugin {
+#define SUDO_POLICY_PLUGIN 1
+ unsigned int type; /* always SUDO_POLICY_PLUGIN */
+ unsigned int version; /* always SUDO_API_VERSION */
+ int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], char * const user_env[],
+ char * const plugin_options[], const char **errstr);
+ void (*close)(int exit_status, int error);
+ int (*show_version)(int verbose);
+ int (*check_policy)(int argc, char * const argv[],
+ char *env_add[], char **command_info[],
+ char **argv_out[], char **user_env_out[], const char **errstr);
+ int (*list)(int argc, char * const argv[], int verbose,
+ const char *user, const char **errstr);
+ int (*validate)(const char **errstr);
+ void (*invalidate)(int rmcred);
+ int (*init_session)(struct passwd *pwd, char **user_env[],
+ const char **errstr);
+ void (*register_hooks)(int version,
+ int (*register_hook)(struct sudo_hook *hook));
+ void (*deregister_hooks)(int version,
+ int (*deregister_hook)(struct sudo_hook *hook));
+ struct sudo_plugin_event * (*event_alloc)(void);
+};
+.Ed
+.Pp
+A
+.Vt struct policy_plugin
+has the following fields:
+.Bl -tag -width 4n
+.It Fa type
+The
+.Fa type
+field should always be set to SUDO_POLICY_PLUGIN.
+.It Fa version
+The
+.Fa version
+field should be set to
+.Dv SUDO_API_VERSION .
+.Pp
+This allows
+.Nm sudo
+to determine the API version the plugin was
+built against.
+.It Fa open
+.Bd -literal -compact
+int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], char * const user_env[],
+ char * const plugin_options[], const char **errstr);
+.Ed
+.Pp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+.Nm sudo
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+.Fn conversation
+or
+.Fn sudo_plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional error information to the user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa version
+The version passed in by
+.Nm sudo
+allows the plugin to determine the
+major and minor version number of the plugin API supported by
+.Nm sudo .
+.It Fa conversation
+A pointer to the
+.Fn conversation
+function that can be used by the plugin to interact with the user (see
+.Sx Conversation API
+for details).
+Returns 0 on success and \-1 on failure.
+.It Fa sudo_plugin_printf
+A pointer to a
+.Fn printf Ns -style
+function that may be used to display informational or error messages (see
+.Sx Conversation API
+for details).
+Returns the number of characters printed on success and \-1 on failure.
+.It Fa settings
+A vector of user-supplied
+.Nm sudo
+settings in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+These settings correspond to options the user specified when running
+.Nm sudo .
+As such, they will only be present when the corresponding option has
+been specified on the command line.
+.Pp
+When parsing
+.Fa settings ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one itself but the
+.Em value
+might.
+.Pp
+The following values may be set by
+.Nm sudo :
+.Bl -tag -width 4n
+.It bsdauth_type=string
+Authentication type, if specified by the
+.Fl a
+option, to use on
+systems where
+.Bx
+authentication is supported.
+.It closefrom=number
+If specified, the user has requested via the
+.Fl C
+option that
+.Nm sudo
+close all files descriptors with a value of
+.Em number
+or higher.
+The plugin may optionally pass this, or another value, back in the
+.Fa command_info
+list.
+.It cmnd_chroot=string
+The root directory (see
+.Xr chroot 2 )
+to run the command in, as specified by the user via the
+.Fl R
+option.
+The plugin may ignore or restrict the user's ability to specify a new
+root directory.
+Only available starting with API version 1.16.
+.It cmnd_cwd=string
+The working directory to run the command in, as specified by the user via the
+.Fl D
+option.
+The plugin may ignore or restrict the user's ability to specify a new
+working directory.
+Only available starting with API version 1.16.
+.It debug_flags=string
+A debug file path name followed by a space and a comma-separated
+list of debug flags that correspond to the plugin's
+.Em Debug
+entry in
+.Xr sudo.conf @mansectform@ ,
+if there is one.
+The flags are passed to the plugin exactly as they appear in
+.Xr sudo.conf @mansectform@ .
+The syntax used by
+.Nm sudo
+and the
+.Nm sudoers
+plugin is
+.Em subsystem Ns @ Ns Em priority
+but a plugin is free to use a different
+format so long as it does not include a comma
+.Pq Ql ,\& .
+Prior to
+.Nm sudo
+1.8.12, there was no way to specify plugin-specific
+.Em debug_flags
+so the value was always the same as that used by the
+.Nm sudo
+front-end and did not include a path name, only the flags themselves.
+As of version 1.7 of the plugin interface,
+.Nm sudo
+will only pass
+.Em debug_flags
+if
+.Xr sudo.conf @mansectform@
+contains a plugin-specific
+.Em Debug
+entry.
+.It ignore_ticket=bool
+Set to true if the user specified the
+.Fl k
+option along with a
+command, indicating that the user wishes to ignore any cached
+authentication credentials.
+.Em implied_shell
+to true.
+This allows
+.Nm sudo
+with no arguments
+to be used similarly to
+.Xr su 1 .
+If the plugin does not to support this usage, it may return a value of \-2
+from the
+.Fn check_policy
+function, which will cause
+.Nm sudo
+to print a usage message and exit.
+.It implied_shell=bool
+If the user does not specify a program on the command line,
+.Nm sudo
+will pass the plugin the path to the user's shell and set
+.Em implied_shell .
+.It intercept_ptrace=bool
+Indicates whether or not the system supports intercept
+mode using
+.Xr ptrace 2 .
+This is currently only true for Linux systems that support
+.Xr seccomp 2
+filtering and the
+.Dq trap
+action.
+Other systems will use a dynamic shared object to implement
+intercept.
+Only available starting with API version 1.19.
+.It intercept_setid=bool
+Indicates whether or not the system supports running set-user-ID
+and set-group-ID binaries in intercept mode.
+This is currently only true for Linux systems that support
+.Xr seccomp 2
+filtering and the
+.Dq trap
+action.
+On systems that use a dynamic shared object to implement
+intercept, the dynamic linker (ld.so or the equivalent)
+will disable preloading of shared objects when executing a
+set-user-ID or set-group-ID binary.
+This will disable intercept mode for that program and any other
+programs that it executes.
+The policy plugin may refuse to execute a set-user-ID or set-group-ID
+binary in intercept mode to avoid this.
+Only available starting with API version 1.19.
+.It login_class=string
+.Bx
+login class to use when setting resource limits and nice value,
+if specified by the
+.Fl c
+option.
+.It login_shell=bool
+Set to true if the user specified the
+.Fl i
+option, indicating that
+the user wishes to run a login shell.
+.It max_groups=int
+The maximum number of groups a user may belong to.
+This will only be present if there is a corresponding setting in
+.Xr sudo.conf @mansectform@ .
+.It network_addrs=list
+A space-separated list of IP network addresses and netmasks in the
+form
+.Dq addr/netmask ,
+e.g.,
+.Dq 192.168.1.2/255.255.255.0 .
+The address and netmask pairs may be either IPv4 or IPv6, depending on
+what the operating system supports.
+If the address contains a colon
+.Pq Ql :\& ,
+it is an IPv6 address, else it is IPv4.
+.It noninteractive=bool
+Set to true if the user specified the
+.Fl n
+option, indicating that
+.Nm sudo
+should operate in non-interactive mode.
+The plugin may reject a command run in non-interactive mode if user
+interaction is required.
+.It plugin_dir=string
+The default plugin directory used by the
+.Nm sudo
+front-end.
+This is the default directory set at compile time and may not
+correspond to the directory the running plugin was loaded from.
+It may be used by a plugin to locate support files.
+.It plugin_path=string
+The path name of plugin loaded by the
+.Nm sudo
+front-end.
+The path name will be a fully-qualified unless the plugin was
+statically compiled into
+.Nm sudo .
+.It preserve_environment=bool
+Set to true if the user specified the
+.Fl E
+option, indicating that
+the user wishes to preserve the environment.
+.It preserve_groups=bool
+Set to true if the user specified the
+.Fl P
+option, indicating that
+the user wishes to preserve the group vector instead of setting it
+based on the runas user.
+.It progname=string
+The command name that sudo was run as, typically
+.Dq sudo
+or
+.Dq sudoedit .
+.It prompt=string
+The prompt to use when requesting a password, if specified via
+the
+.Fl p
+option.
+.It remote_host=string
+The name of the remote host to run the command on, if specified via
+the
+.Fl h
+option.
+Support for running the command on a remote host is meant to be implemented
+via a helper program that is executed in place of the user-specified command.
+The
+.Nm sudo
+front-end is only capable of executing commands on the local host.
+Only available starting with API version 1.4.
+.It run_shell=bool
+Set to true if the user specified the
+.Fl s
+option, indicating that the user wishes to run a shell.
+.It runas_group=string
+The group name or group-ID to run the command as, if specified via
+the
+.Fl g
+option.
+.It runas_user=string
+The user name or user-ID to run the command as, if specified via the
+.Fl u
+option.
+.It selinux_role=string
+SELinux role to use when executing the command, if specified by
+the
+.Fl r
+option.
+.It selinux_type=string
+SELinux type to use when executing the command, if specified by
+the
+.Fl t
+option.
+.It set_home=bool
+Set to true if the user specified the
+.Fl H
+option.
+If true, set the
+.Ev HOME
+environment variable to the target user's home directory.
+.It sudoedit=bool
+Set to true when the
+.Fl e
+option is specified or if invoked as
+.Nm sudoedit .
+The plugin shall substitute an editor into
+.Fa argv
+in the
+.Fn check_policy
+function or return \-2 with a usage error
+if the plugin does not support
+.Em sudoedit .
+For more information, see the
+.Fn check_policy
+section.
+.It timeout=string
+Command timeout specified by the user via the
+.Fl T
+option.
+Not all plugins support command timeouts and the ability of the
+user to set a timeout may be restricted by policy.
+The format of the timeout string is plugin-specific.
+.It update_ticket=bool
+Set to false if the user specified the
+.Fl N
+option, indicating that the user wishes to avoid updating any cached
+authentication credentials.
+Only available starting with API version 1.20.
+.El
+.Pp
+Additional settings may be added in the future so the plugin should
+silently ignore settings that it does not recognize.
+.It Fa user_info
+A vector of information about the user running the command in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Fa user_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+The following values may be set by
+.Nm sudo :
+.Bl -tag -width 4n
+.It cols=int
+The number of columns the user's terminal supports.
+If there is no terminal device available, a default value of 80 is used.
+.It cwd=string
+The user's current working directory.
+.It egid=gid_t
+The effective group-ID of the user invoking
+.Nm sudo .
+.It euid=uid_t
+The effective user-ID of the user invoking
+.Nm sudo .
+.It gid=gid_t
+The real group-ID of the user invoking
+.Nm sudo .
+.It groups=list
+The user's supplementary group list formatted as a string of
+comma-separated group-IDs.
+.It host=string
+The local machine's hostname as returned by the
+.Xr gethostname 2
+system call.
+.It lines=int
+The number of lines the user's terminal supports.
+If there is
+no terminal device available, a default value of 24 is used.
+.It pgid=int
+The ID of the process group that the running
+.Nm sudo
+process is a member of.
+Only available starting with API version 1.2.
+.It pid=int
+The process ID of the running
+.Nm sudo
+process.
+Only available starting with API version 1.2.
+.It ppid=int
+The parent process ID of the running
+.Nm sudo
+process.
+Only available starting with API version 1.2.
+.It rlimit_as=soft,hard
+The maximum size to which the process's address space may grow (in bytes),
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_core=soft,hard
+The largest size core dump file that may be created (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_cpu=soft,hard
+The maximum amount of CPU time that the process may use (in seconds).
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_data=soft,hard
+The maximum size of the data segment for the process (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_fsize=soft,hard
+The largest size file that the process may create (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_locks=soft,hard
+The maximum number of locks that the process may establish,
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_memlock=soft,hard
+The maximum size that the process may lock in memory (in bytes),
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_nofile=soft,hard
+The maximum number of files that the process may have open.
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_nproc=soft,hard
+The maximum number of processes that the user may run simultaneously.
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_rss=soft,hard
+The maximum size to which the process's resident set size may grow (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It rlimit_stack=soft,hard
+The maximum size to which the process's stack may grow (in bytes).
+The soft and hard limits are separated by a comma.
+A value of
+.Dq infinity
+indicates that there is no limit.
+Only available starting with API version 1.16.
+.It sid=int
+The session ID of the running
+.Nm sudo
+process or 0 if
+.Nm sudo
+is not part of a POSIX job control session.
+Only available starting with API version 1.2.
+.It tcpgid=int
+The ID of the foreground process group associated with the terminal
+device associated with the
+.Nm sudo
+process or 0 if there is no terminal present.
+Only available starting with API version 1.2.
+.It tty=string
+The path to the user's terminal device.
+If the user has no terminal device associated with the session,
+the value will be empty, as in
+.Ql tty= .
+.It uid=uid_t
+The real user-ID of the user invoking
+.Nm sudo .
+.It umask=octal
+The invoking user's file creation mask.
+Only available starting with API version 1.10.
+.It user=string
+The name of the user invoking
+.Nm sudo .
+.El
+.It Fa user_env
+The user's environment in the form of a
+.Dv NULL Ns -terminated vector of
+.Dq name=value
+strings.
+.Pp
+When parsing
+.Fa user_env ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.It Fa plugin_options
+Any (non-comment) strings immediately after the plugin path are
+passed as arguments to the plugin.
+These arguments are split on a white space boundary and are passed to
+the plugin in the form of a
+.Dv NULL Ns -terminated
+array of strings.
+If no arguments were
+specified,
+.Fa plugin_options
+will be the
+.Dv NULL
+pointer.
+.Pp
+The
+.Fa plugin_options
+parameter is only available starting with
+API version 1.2.
+A plugin
+.Sy must
+check the API version specified
+by the
+.Nm sudo
+front-end before using
+.Fa plugin_options .
+Failure to do so may result in a crash.
+.It Fa errstr
+If the
+.Fn open
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+The
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front-end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It Fa close
+.Bd -literal -compact
+void (*close)(int exit_status, int error);
+.Ed
+.Pp
+The
+.Fn close
+function is called when
+.Nm sudo
+is finished, shortly before it exits.
+Starting with API version 1.15,
+.Fn close
+is called regardless of whether or not a command was actually executed.
+This makes it possible for plugins to perform cleanup even when a
+command was not run.
+It is not possible to tell whether a command was run based solely
+on the arguments passed to the
+.Fn close
+function.
+To determine if a command was actually run,
+the plugin must keep track of whether or not the
+.Fn check_policy
+function returned successfully.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa exit_status
+The command's exit status, as returned by the
+.Xr wait 2
+system call, or zero if no command was run.
+The value of
+.Fa exit_status
+is undefined if
+.Fa error
+is non-zero.
+.It Fa error
+If the command could not be executed, this is set to the value of
+.Va errno
+set by the
+.Xr execve 2
+system call.
+The plugin is responsible for displaying error information via the
+.Fn conversation
+or
+.Fn sudo_plugin_printf
+function.
+If the command was successfully executed, the value of
+.Fa error
+is zero.
+.El
+.Pp
+If no
+.Fn close
+function is defined, no I/O logging plugins are loaded,
+and neither the
+.Em timeout
+nor
+.Em use_pty
+options are set in the
+.Fa command_info
+list, the
+.Nm sudo
+front-end may execute the command directly instead of running
+it as a child process.
+.It Fa show_version
+.Bd -literal -compact
+int (*show_version)(int verbose);
+.Ed
+.Pp
+The
+.Fn show_version
+function is called by
+.Nm sudo
+when the user specifies the
+.Fl V
+option.
+The plugin may display its version information to the user via the
+.Fn conversation
+or
+.Fn sudo_plugin_printf
+function using
+.Dv SUDO_CONV_INFO_MSG .
+If the user requests detailed version information, the
+.Fa verbose
+flag will be non-zero.
+.Pp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error, although the return value is currently
+ignored.
+.It Fa check_policy
+.Bd -literal -compact
+int (*check_policy)(int argc, char * const argv[], char *env_add[],
+ char **command_info[], char **argv_out[], char **user_env_out[],
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn check_policy
+function is called by
+.Nm sudo
+to determine
+whether the user is allowed to run the specified commands.
+.Pp
+If the
+.Em sudoedit
+option was enabled in the
+.Fa settings
+array passed to the
+.Fn open
+function, the user has requested
+.Em sudoedit
+mode.
+.Em sudoedit
+is a mechanism for editing one or more files
+where an editor is run with the user's credentials instead of with
+elevated privileges.
+.Nm sudo
+achieves this by creating user-writable
+temporary copies of the files to be edited and then overwriting the
+originals with the temporary copies after editing is complete.
+If the plugin supports
+.Em sudoedit ,
+it must set
+.Em sudoedit=true
+in the
+.Fa command_info
+list.
+The plugin is responsible for choosing the editor to be used,
+potentially from a variable in the user's environment, such as
+.Ev EDITOR ,
+and should be stored in
+.Fa argv_out
+(environment variables may include command line options).
+The files to be edited should be copied from
+.Fa argv
+to
+.Fa argv_out ,
+separated from the
+editor and its arguments by a
+.Ql --
+element.
+The
+.Ql --
+will be removed by
+.Nm sudo
+before the editor is executed.
+The plugin may also set
+.Em sudoedit_nfiles
+to the number of files to be edited in the
+.Fa command_info
+list; this will only be used by the
+.Nm sudo
+front-end starting with API version 1.21.
+.Pp
+The
+.Fn check_policy
+function returns 1 if the command is allowed,
+0 if not allowed, \-1 for a general error, or \-2 for a usage error
+or if
+.Em sudoedit
+was specified but is unsupported by the plugin.
+In the latter case,
+.Nm sudo
+will print a usage message before it
+exits.
+If an error occurs, the plugin may optionally call the
+.Fn conversation
+or
+.Fn sudo_plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional error information to the user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa argc
+The number of elements in
+.Fa argv ,
+not counting the final
+.Dv NULL
+pointer.
+.It Fa argv
+The argument vector describing the command the user wishes to run,
+in the same form as what would be passed to the
+.Xr execve 2
+system call.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.It Fa env_add
+Additional environment variables specified by the user on the command
+line in the form of a
+.Dv NULL Ns -terminated
+vector of
+.Dq name=value
+strings.
+The plugin may reject the command if one or more variables
+are not allowed to be set, or it may silently ignore such variables.
+.Pp
+When parsing
+.Fa env_add ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one itself but the
+.Em value
+might.
+.It Fa command_info
+Information about the command being run in the form of
+.Dq name=value
+strings.
+These values are used by
+.Nm sudo
+to set the execution environment when running a command.
+The plugin is responsible for creating and populating the vector,
+which must be terminated with a
+.Dv NULL
+pointer.
+The following values are recognized by
+.Nm sudo :
+.Bl -tag -width 4n
+.It apparmor_profile=string
+AppArmor profile to transition to when executing the command.
+Only available starting with API version 1.19.
+.It chroot=string
+The root directory to use when running the command.
+.It closefrom=number
+If specified,
+.Nm sudo
+will close all files descriptors with a value
+of
+.Em number
+or higher.
+.It command=string
+Fully qualified path to the command to be executed.
+.It cwd=string
+The current working directory to change to when executing the command.
+If
+.Nm sudo
+is unable to change to the new working directory, the command will
+not be run unless
+.Em cwd_optional
+is also set (see below).
+.It cwd_optional=bool
+If set,
+.Nm sudo
+will treat an inability to change to the new working directory as a
+non-fatal error.
+This setting has no effect unless
+.Em cwd
+is also set.
+.It exec_background=bool
+By default,
+.Nm sudo
+runs a command as the foreground process as long as
+.Nm sudo
+itself is running in the foreground.
+When
+.Em exec_background
+is enabled and the command is being run in a pseudo-terminal
+(due to I/O logging or the
+.Em use_pty
+setting), the command will be run as a background process.
+Attempts to read from the controlling terminal (or to change terminal
+settings) will result in the command being suspended with the
+.Dv SIGTTIN
+signal (or
+.Dv SIGTTOU
+in the case of terminal settings).
+If this happens when
+.Nm sudo
+is a foreground process, the command will be granted the controlling terminal
+and resumed in the foreground with no user intervention required.
+The advantage of initially running the command in the background is that
+.Nm sudo
+need not read from the terminal unless the command explicitly requests it.
+Otherwise, any terminal input must be passed to the command, whether it
+has required it or not (the kernel buffers terminals so it is not possible
+to tell whether the command really wants the input).
+This is different from historic
+.Nm sudo
+behavior or when the command is not being run in a pseudo-terminal.
+.Pp
+For this to work seamlessly, the operating system must support the
+automatic restarting of system calls.
+Unfortunately, not all operating systems do this by default,
+and even those that do may have bugs.
+For example, macOS fails to restart the
+.Fn tcgetattr
+and
+.Fn tcsetattr
+system calls (this is a bug in macOS).
+Furthermore, because this behavior depends on the command stopping with the
+.Dv SIGTTIN
+or
+.Dv SIGTTOU
+signals, programs that catch these signals and suspend themselves
+with a different signal (usually
+.Dv SIGTOP )
+will not be automatically foregrounded.
+Some versions of the linux
+.Xr su 1
+command behave this way.
+Because of this, a plugin should not set
+.Em exec_background
+unless it is explicitly enabled by the administrator and there should
+be a way to enabled or disable it on a per-command basis.
+.Pp
+This setting has no effect unless I/O logging is enabled or
+.Em use_pty
+is enabled.
+.It execfd=number
+If specified,
+.Nm sudo
+will use the
+.Xr fexecve 2
+system call to execute the command instead of
+.Xr execve 2 .
+The specified
+.Em number
+must refer to an open file descriptor.
+.It intercept=bool
+If set,
+.Nm sudo
+will intercept attempts to execute a subsequent command and perform
+a policy check via the policy plugin's
+.Fn check_policy
+function to determine whether or not the command is permitted.
+This can be used to prevent shell escapes on supported platforms
+but it has a number of limitations.
+See
+.Sy Preventing shell escapes
+in
+.Xr sudoers @mansectform@
+for details.
+Only available starting with API version 1.18.
+.It intercept_verify=bool
+If set,
+.Nm sudo
+will attempt to verify that a command run in intercept mode has the
+expected path name, command line arguments and environment.
+This setting has no effect unless
+.Em use_ptrace
+is also enabled.
+Only available starting with API version 1.20.
+.It iolog_compress=bool
+Set to true if the I/O logging plugins, if any, should compress the
+log data.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It iolog_group=string
+The group that will own newly created I/O log files and directories.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It iolog_mode=octal
+The file permission mode to use when creating I/O log files and directories.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It iolog_user=string
+The user that will own newly created I/O log files and directories.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It iolog_path=string
+Fully qualified path to the file or directory in which I/O log is
+to be stored.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+If no I/O logging plugin is loaded, this setting has no effect.
+.It iolog_stdin=bool
+Set to true if the I/O logging plugins, if any, should log the
+standard input if it is not connected to a terminal device.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It iolog_stdout=bool
+Set to true if the I/O logging plugins, if any, should log the
+standard output if it is not connected to a terminal device.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It iolog_stderr=bool
+Set to true if the I/O logging plugins, if any, should log the
+standard error if it is not connected to a terminal device.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It iolog_ttyin=bool
+Set to true if the I/O logging plugins, if any, should log all
+terminal input.
+This only includes input typed by the user and not from a pipe or
+redirected from a file.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It iolog_ttyout=bool
+Set to true if the I/O logging plugins, if any, should log all
+terminal output.
+This only includes output to the screen, not output to a pipe or file.
+This is a hint to the I/O logging plugin which may choose to ignore it.
+.It login_class=string
+.Bx
+login class to use when setting resource limits and nice value (optional).
+This option is only set on systems that support login classes.
+.It nice=int
+Nice value (priority) to use when executing the command.
+The nice value, if specified, overrides the priority associated with the
+.Em login_class
+on
+.Bx
+systems.
+.It log_subcmds=bool
+If set,
+.Nm sudo
+will call the audit plugin's
+.Fn accept
+function to log when the command runs a subsequent command, if supported
+by the system.
+If
+.Em intercept
+is also specified,
+.Em log_subcmds
+will be ignored.
+See
+.Sy Preventing shell escapes
+in
+.Xr sudoers @mansectform@
+for more information.
+Only available starting with API version 1.18.
+.It noexec=bool
+If set, prevent the command from executing other programs.
+.It preserve_fds=list
+A comma-separated list of file descriptors that should be
+preserved, regardless of the value of the
+.Em closefrom
+setting.
+Only available starting with API version 1.5.
+.It preserve_groups=bool
+If set,
+.Nm sudo
+will preserve the user's group vector instead of
+initializing the group vector based on
+.Em runas_user .
+.It rlimit_as=soft,hard
+The maximum size to which the process's address space may grow (in bytes),
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+.Dq infinity
+indicates that there is no limit.
+A value of
+.Dq user
+will cause the invoking user's resource limit to be preserved.
+A value of
+.Dq default
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.It rlimit_core=soft,hard
+The largest size core dump file that may be created (in bytes).
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+.Dq infinity
+indicates that there is no limit.
+A value of
+.Dq user
+will cause the invoking user's resource limit to be preserved.
+A value of
+.Dq default
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.It rlimit_cpu=soft,hard
+The maximum amount of CPU time that the process may use (in seconds).
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+.Dq infinity
+indicates that there is no limit.
+A value of
+.Dq user
+will cause the invoking user's resource limit to be preserved.
+A value of
+.Dq default
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.It rlimit_data=soft,hard
+The maximum size of the data segment for the process (in bytes).
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+.Dq infinity
+indicates that there is no limit.
+A value of
+.Dq user
+will cause the invoking user's resource limit to be preserved.
+A value of
+.Dq default
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.It rlimit_fsize=soft,hard
+The largest size file that the process may create (in bytes).
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+.Dq infinity
+indicates that there is no limit.
+A value of
+.Dq user
+will cause the invoking user's resource limit to be preserved.
+A value of
+.Dq default
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.It rlimit_locks=soft,hard
+The maximum number of locks that the process may establish,
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+.Dq infinity
+indicates that there is no limit.
+A value of
+.Dq user
+will cause the invoking user's resource limit to be preserved.
+A value of
+.Dq default
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.It rlimit_memlock=soft,hard
+The maximum size that the process may lock in memory (in bytes),
+if supported by the operating system.
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+.Dq infinity
+indicates that there is no limit.
+A value of
+.Dq user
+will cause the invoking user's resource limit to be preserved.
+A value of
+.Dq default
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.It rlimit_nofile=soft,hard
+The maximum number of files that the process may have open.
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+.Dq infinity
+indicates that there is no limit.
+A value of
+.Dq user
+will cause the invoking user's resource limit to be preserved.
+A value of
+.Dq default
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.It rlimit_nproc=soft,hard
+The maximum number of processes that the user may run simultaneously.
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+.Dq infinity
+indicates that there is no limit.
+A value of
+.Dq user
+will cause the invoking user's resource limit to be preserved.
+A value of
+.Dq default
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.It rlimit_rss=soft,hard
+The maximum size to which the process's resident set size may grow (in bytes).
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+.Dq infinity
+indicates that there is no limit.
+A value of
+.Dq user
+will cause the invoking user's resource limit to be preserved.
+A value of
+.Dq default
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.It rlimit_stack=soft,hard
+The maximum size to which the process's stack may grow (in bytes).
+The soft and hard limits are separated by a comma.
+If only a single value is specified, both the hard and soft limits are set.
+A value of
+.Dq infinity
+indicates that there is no limit.
+A value of
+.Dq user
+will cause the invoking user's resource limit to be preserved.
+A value of
+.Dq default
+will cause the target user's default resource limit to be used
+on systems that allow per-user resource limits to be configured.
+Only available starting with API version 1.18.
+.It runas_egid=gid
+Effective group-ID to run the command as.
+If not specified, the value of
+.Em runas_gid
+is used.
+.It runas_euid=uid
+Effective user-ID to run the command as.
+If not specified, the value of
+.Em runas_uid
+is used.
+.It runas_gid=gid
+Group-ID to run the command as.
+.It runas_group=string
+The name of the group the command will run as, if it is different
+from the
+.Em runas_user Ns 's
+default group.
+This value is provided for auditing purposes only, the
+.Nm sudo
+front-end uses
+.Em runas_egid
+and
+.Em runas_gid
+when executing the command.
+.It runas_groups=list
+The supplementary group vector to use for the command in the form
+of a comma-separated list of group-IDs.
+If
+.Em preserve_groups
+is set, this option is ignored.
+.It runas_uid=uid
+User-ID to run the command as.
+.It runas_user=string
+The name of the user the command will run as, which should correspond to
+.Em runas_euid
+(or
+.Em runas_uid
+if
+.Em runas_euid
+is not set).
+This value is provided for auditing purposes only, the
+.Nm sudo
+front-end uses
+.Em runas_euid
+and
+.Em runas_uid
+when executing the command.
+.It selinux_role=string
+SELinux role to use when executing the command.
+.It selinux_type=string
+SELinux type to use when executing the command.
+.It set_utmp=bool
+Create a utmp (or utmpx) entry when a pseudo-terminal is allocated.
+By default, the new entry will be a copy of the user's existing utmp
+entry (if any), with the tty, time, type, and pid fields updated.
+.It sudoedit=bool
+Set to true when in
+.Em sudoedit
+mode.
+The plugin may enable
+.Em sudoedit
+mode even if
+.Nm sudo
+was not invoked as
+.Nm sudoedit .
+This allows the plugin to perform command substitution and transparently
+enable
+.Em sudoedit
+when the user attempts to run an editor.
+.It sudoedit_checkdir=bool
+Set to false to disable directory writability checks in
+.Nm sudoedit .
+By default,
+.Nm sudoedit
+1.8.16 and higher will check all directory components of the path to be
+edited for writability by the invoking user.
+Symbolic links will not be followed in writable directories and
+.Nm sudoedit
+will refuse to edit a file located in a writable directory.
+These restrictions are not enforced when
+.Nm sudoedit
+is run by root.
+The
+.Em sudoedit_checkdir
+option can be set to false to disable this check.
+Only available starting with API version 1.8.
+.It sudoedit_follow=bool
+Set to true to allow
+.Nm sudoedit
+to edit files that are symbolic links.
+By default,
+.Nm sudoedit
+1.8.15 and higher will refuse to open a symbolic link.
+The
+.Em sudoedit_follow
+option can be used to restore the older behavior and allow
+.Nm sudoedit
+to open symbolic links.
+Only available starting with API version 1.8.
+.It sudoedit_nfiles=number
+The number of files to be edited by the user.
+If present, this is will be used by the
+.Nm sudo
+front-end to determine which elements of the
+.Fa argv_out
+vector are files to be edited.
+The
+.Ql --
+element must immediately precede the first file to be editied.
+If
+.Em sudoedit_nfiles
+is not specified, the
+.Nm sudo
+front-end will use the position of the
+.Ql --
+element to determine where the file list begins.
+Only available starting with API version 1.21.
+.It timeout=int
+Command timeout.
+If non-zero then when the timeout expires the command will be killed.
+.It umask=octal
+The file creation mask to use when executing the command.
+This value may be overridden by PAM or login.conf on some systems
+unless the
+.Em umask_override
+option is also set.
+.It umask_override=bool
+Force the value specified by the
+.Em umask
+option to override any umask set by PAM or login.conf.
+.It use_ptrace=bool
+If set,
+.Nm sudo
+will use
+.Xr ptrace 2
+to implement intercept mode if supported by the system.
+This setting has no effect unless
+.Em intercept
+is also set.
+Only available starting with API version 1.19.
+.It use_pty=bool
+Allocate a pseudo-terminal to run the command in, regardless of whether
+or not I/O logging is in use.
+By default,
+.Nm sudo
+will only run
+the command in a pseudo-terminal when an I/O log plugin is loaded.
+.It utmp_user=string
+User name to use when constructing a new utmp (or utmpx) entry when
+.Em set_utmp
+is enabled.
+This option can be used to set the user field in the utmp entry to
+the user the command runs as rather than the invoking user.
+If not set,
+.Nm sudo
+will base the new entry on
+the invoking user's existing entry.
+.El
+.Pp
+Unsupported values will be ignored.
+.It Fa argv_out
+The
+.Dv NULL Ns -terminated
+argument vector to pass to the
+.Xr execve 2
+system call when executing the command.
+The plugin is responsible for allocating and populating the vector.
+.It Fa user_env_out
+The
+.Dv NULL Ns -terminated
+environment vector to use when executing the command.
+The plugin is responsible for allocating and populating the vector.
+.It Fa errstr
+If the
+.Fn check_policy
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+The
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front-end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It Fa list
+.Bd -literal -compact
+int (*list)(int argc, char * const argv[], int verbose,
+ const char *user, const char **errstr);
+.Ed
+.Pp
+List available privileges for the invoking user.
+Returns 1 on success, 0 on failure, and \-1 on error.
+On error, the plugin may optionally call the
+.Fn conversation
+or
+.Fn sudo_plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional error information to
+the user.
+.Pp
+Privileges should be output via the
+.Fn conversation
+or
+.Fn sudo_plugin_printf
+function using
+.Dv SUDO_CONV_INFO_MSG .
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa argc
+The number of elements in
+.Fa argv ,
+not counting the final
+.Dv NULL
+pointer.
+.It Fa argv
+If
+.No non- Ns Dv NULL ,
+an argument vector describing a command the user
+wishes to check against the policy in the same form as what would
+be passed to the
+.Xr execve 2
+system call.
+If the command is permitted by the policy, the fully-qualified path
+to the command should be displayed along with any command line arguments.
+.It Fa verbose
+Flag indicating whether to list in verbose mode or not.
+.It Fa user
+The name of a different user to list privileges for if the policy
+allows it.
+If
+.Dv NULL ,
+the plugin should list the privileges of the invoking user.
+.It Fa errstr
+If the
+.Fn list
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+The
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front-end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It Fa validate
+.Bd -literal -compact
+int (*validate)(const char **errstr);
+.Ed
+.Pp
+The
+.Fn validate
+function is called when
+.Nm sudo
+is run with the
+.Fl v
+option.
+For policy plugins such as
+.Nm sudoers
+that cache
+authentication credentials, this function will validate and cache
+the credentials.
+.Pp
+The
+.Fn validate
+function should be
+.Dv NULL
+if the plugin does not support credential caching.
+.Pp
+Returns 1 on success, 0 on failure, and \-1 on error.
+On error, the plugin may optionally call the
+.Fn conversation
+or
+.Fn sudo_plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional
+error information to the user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Va errstr
+If the
+.Fn validate
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+The
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front-end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It Fa invalidate
+.Bd -literal -compact
+void (*invalidate)(int rmcred);
+.Ed
+.Pp
+The
+.Fn invalidate
+function is called when
+.Nm sudo
+is run with the
+.Fl k
+or
+.Fl K
+option.
+For policy plugins such as
+.Nm sudoers
+that
+cache authentication credentials, this function will invalidate the
+credentials.
+If the
+.Fa rmcred
+flag is non-zero, the plugin may remove
+the credentials instead of simply invalidating them.
+.Pp
+The
+.Fn invalidate
+function should be
+.Dv NULL
+if the plugin does not support credential caching.
+.It Fa init_session
+.Bd -literal -compact
+int (*init_session)(struct passwd *pwd, char **user_env[],
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn init_session
+function is called before
+.Nm sudo
+sets up the
+execution environment for the command.
+It is run in the parent
+.Nm sudo
+process before any user-ID or group-ID changes.
+This can be used to perform session setup that is not supported by
+.Fa command_info ,
+such as opening the PAM session.
+The
+.Fn close
+function can be
+used to tear down the session that was opened by
+.Fn init_session .
+.Pp
+Returns 1 on success, 0 on failure, and \-1 on error.
+On error, the plugin may optionally call the
+.Fn conversation
+or
+.Fn sudo_plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional
+error information to the user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa pwd
+If the user-ID the command will run as was found in the password database,
+.Fa pwd
+will describe that user, otherwise it will be
+.Dv NULL .
+.It Fa user_env_out
+The
+.Dv NULL Ns -terminated
+environment vector to use when executing the command.
+This is the same string passed back to the front-end via the Policy Plugin's
+.Fa user_env_out
+parameter.
+If the
+.Fn init_session
+function needs to modify the user environment, it should update the
+pointer stored in
+.Fa user_env_out .
+The expected use case is to merge the contents of the PAM environment
+(if any) with the contents of
+.Fa user_env_out .
+The
+.Fa user_env_out
+parameter is only available
+starting with API version 1.2.
+A plugin
+.Sy must
+check the API
+version specified by the
+.Nm sudo
+front-end before using
+.Fa user_env_out .
+Failure to do so may result in a crash.
+.It Fa errstr
+If the
+.Fn init_session
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+The
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front-end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It Fa register_hooks
+.Bd -literal -compact
+void (*register_hooks)(int version,
+ int (*register_hook)(struct sudo_hook *hook));
+.Ed
+.Pp
+The
+.Fn register_hooks
+function is called by the sudo front-end to
+register any hooks the plugin needs.
+If the plugin does not support hooks,
+.Fa register_hooks
+should be set to the
+.Dv NULL
+pointer.
+.Pp
+The
+.Fa version
+argument describes the version of the hooks API
+supported by the
+.Nm sudo
+front-end.
+.Pp
+The
+.Fn register_hook
+function should be used to register any supported
+hooks the plugin needs.
+It returns 0 on success, 1 if the hook type is not supported, and \-1
+if the major version in
+.Vt struct sudo_hook
+does not match the front-end's major hook API version.
+.Pp
+See the
+.Sx Hook function API
+section below for more information about hooks.
+.Pp
+The
+.Fn register_hooks
+function is only available starting
+with API version 1.2.
+If the
+.Nm sudo
+front-end doesn't support API
+version 1.2 or higher,
+.Fn register_hooks
+will not be called.
+.It Fa deregister_hooks
+.Bd -literal -compact
+void (*deregister_hooks)(int version,
+ int (*deregister_hook)(struct sudo_hook *hook));
+.Ed
+.Pp
+The
+.Fn deregister_hooks
+function is called by the sudo front-end
+to deregister any hooks the plugin has registered.
+If the plugin does not support hooks,
+.Fa deregister_hooks
+should be set to the
+.Dv NULL
+pointer.
+.Pp
+The
+.Fa version
+argument describes the version of the hooks API
+supported by the
+.Nm sudo
+front-end.
+.Pp
+The
+.Fn deregister_hook
+function should be used to deregister any
+hooks that were put in place by the
+.Fn register_hook
+function.
+If the plugin tries to deregister a hook that the front-end does not support,
+.Fn deregister_hook
+will return an error.
+.Pp
+See the
+.Sx Hook function API
+section below for more information about hooks.
+.Pp
+The
+.Fn deregister_hooks
+function is only available starting
+with API version 1.2.
+If the
+.Nm sudo
+front-end doesn't support API
+version 1.2 or higher,
+.Fn deregister_hooks
+will not be called.
+.It Fa event_alloc
+.Bd -literal -compact
+struct sudo_plugin_event * (*event_alloc)(void);
+.Ed
+.Pp
+The
+.Fn event_alloc
+function is used to allocate a
+.Vt struct sudo_plugin_event
+which provides access to the main
+.Nm sudo
+event loop.
+Unlike the other fields, the
+.Fa event_alloc
+pointer is filled in by the
+.Nm sudo
+front-end, not by the plugin.
+.Pp
+See the
+.Sx Event API
+section below for more information
+about events.
+.Pp
+The
+.Fn event_alloc
+function is only available starting
+with API version 1.15.
+If the
+.Nm sudo
+front-end doesn't support API
+version 1.15 or higher,
+.Fa event_alloc
+will not be set.
+.El
+.Pp
+.Em Policy Plugin Version Macros
+.Bd -literal
+/* Plugin API version major/minor. */
+#define SUDO_API_VERSION_MAJOR 1
+#define SUDO_API_VERSION_MINOR 13
+#define SUDO_API_MKVERSION(x, y) ((x << 16) | y)
+#define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR,\e
+ SUDO_API_VERSION_MINOR)
+
+/* Getters and setters for API version */
+#define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16)
+#define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff)
+#define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \e
+ *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e
+} while(0)
+#define SUDO_API_VERSION_SET_MINOR(vp, n) do { \e
+ *(vp) = (*(vp) & 0xffff0000) | (n); \e
+} while(0)
+.Ed
+.Ss I/O plugin API
+.Bd -literal
+struct io_plugin {
+#define SUDO_IO_PLUGIN 2
+ unsigned int type; /* always SUDO_IO_PLUGIN */
+ unsigned int version; /* always SUDO_API_VERSION */
+ int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], char * const command_info[],
+ int argc, char * const argv[], char * const user_env[],
+ char * const plugin_options[], const char **errstr);
+ void (*close)(int exit_status, int error); /* wait status or error */
+ int (*show_version)(int verbose);
+ int (*log_ttyin)(const char *buf, unsigned int len,
+ const char **errstr);
+ int (*log_ttyout)(const char *buf, unsigned int len,
+ const char **errstr);
+ int (*log_stdin)(const char *buf, unsigned int len,
+ const char **errstr);
+ int (*log_stdout)(const char *buf, unsigned int len,
+ const char **errstr);
+ int (*log_stderr)(const char *buf, unsigned int len,
+ const char **errstr);
+ void (*register_hooks)(int version,
+ int (*register_hook)(struct sudo_hook *hook));
+ void (*deregister_hooks)(int version,
+ int (*deregister_hook)(struct sudo_hook *hook));
+ int (*change_winsize)(unsigned int lines, unsigned int cols,
+ const char **errstr);
+ int (*log_suspend)(int signo, const char **errstr);
+ struct sudo_plugin_event * (*event_alloc)(void);
+};
+.Ed
+.Pp
+When an I/O plugin is loaded,
+.Nm sudo
+runs the command in a pseudo-terminal.
+This makes it possible to log the input and output from the user's
+session.
+If any of the standard input, standard output, or standard error do not
+correspond to a tty,
+.Nm sudo
+will open a pipe to capture the I/O for logging before passing it on.
+.Pp
+The
+.Fn log_ttyin
+function receives the raw user input from the terminal
+device (this will include input even when echo is disabled,
+such as when a password is read).
+The
+.Fn log_ttyout
+function receives output from the pseudo-terminal that is
+suitable for replaying the user's session at a later time.
+The
+.Fn log_stdin ,
+.Fn log_stdout ,
+and
+.Fn log_stderr
+functions are only called if the standard input, standard output,
+or standard error respectively correspond to something other than
+a tty.
+.Pp
+Any of the logging functions may be set to the
+.Dv NULL
+pointer if no logging is to be performed.
+If the open function returns 0, no I/O will be sent to the plugin.
+.Pp
+If a logging function returns an error
+.Pq \-1 ,
+the running command will be terminated and all of the plugin's logging
+functions will be disabled.
+Other I/O logging plugins will still receive any remaining
+input or output that has not yet been processed.
+.Pp
+If an input logging function rejects the data by returning 0, the
+command will be terminated and the data will not be passed to the
+command, though it will still be sent to any other I/O logging plugins.
+If an output logging function rejects the data by returning 0, the
+command will be terminated and the data will not be written to the
+terminal, though it will still be sent to any other I/O logging plugins.
+.Pp
+A
+.Vt struct audit_plugin
+has the following fields:
+.Bl -tag -width 4n
+.It Fa type
+The
+.Fa type
+field should always be set to
+.Dv SUDO_IO_PLUGIN .
+.It Fa version
+The
+.Fa version
+field should be set to
+.Dv SUDO_API_VERSION .
+.Pp
+This allows
+.Nm sudo
+to determine the API version the plugin was
+built against.
+.It Fa open
+.Bd -literal -compact
+int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], char * const command_info[],
+ int argc, char * const argv[], char * const user_env[],
+ char * const plugin_options[]);
+.Ed
+.Pp
+The
+.Fn open
+function is run before the
+.Fn log_ttyin ,
+.Fn log_ttyout ,
+.Fn log_stdin ,
+.Fn log_stdout ,
+.Fn log_stderr ,
+.Fn log_suspend ,
+.Fn change_winsize ,
+or
+.Fn show_version
+functions are called.
+It is only called if the version is being requested or if the
+policy plugin's
+.Fn check_policy
+function has returned successfully.
+It returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+.Nm sudo
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+.Fn conversation
+or
+.Fn sudo_plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional error information to the user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa version
+The version passed in by
+.Nm sudo
+allows the plugin to determine the
+major and minor version number of the plugin API supported by
+.Nm sudo .
+.It Fa conversation
+A pointer to the
+.Fn conversation
+function that may be used by the
+.Fn Fa show_version
+function to display version information (see
+.Fn show_version
+below).
+The
+.Fn conversation
+function may also be used to display additional error message to the user.
+The
+.Fn conversation
+function returns 0 on success and \-1 on failure.
+.It Fa sudo_plugin_printf
+A pointer to a
+.Fn printf Ns -style
+function that may be used by the
+.Fn show_version
+function to display version information (see
+show_version below).
+The
+.Fn sudo_plugin_printf
+function may also be used to display additional error message to the user.
+The
+.Fn sudo_plugin_printf
+function returns number of characters printed on success and \-1 on failure.
+.It Fa settings
+A vector of user-supplied
+.Nm sudo
+settings in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+These settings correspond to options the user specified when running
+.Nm sudo .
+As such, they will only be present when the corresponding option has
+been specified on the command line.
+.Pp
+When parsing
+.Fa settings ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible settings.
+.It Fa user_info
+A vector of information about the user running the command in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Fa user_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible strings.
+.It Fa command_info
+A vector of information describing the command being run in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Fa command_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible strings.
+.It Fa argc
+The number of elements in
+.Fa argv ,
+not counting the final
+.Dv NULL
+pointer.
+It can be zero, such as when
+.Nm sudo
+is called with the
+.Fl V
+option.
+.It Fa argv
+If
+.No non- Ns Dv NULL ,
+an argument vector describing a command the user
+wishes to run in the same form as what would be passed to the
+.Xr execve 2
+system call.
+.It Fa user_env
+The user's environment in the form of a
+.Dv NULL Ns -terminated
+vector of
+.Dq name=value
+strings.
+.Pp
+When parsing
+.Fa user_env ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.It Fa plugin_options
+Any (non-comment) strings immediately after the plugin path are
+treated as arguments to the plugin.
+These arguments are split on a white space boundary and are passed to
+the plugin in the form of a
+.Dv NULL Ns -terminated
+array of strings.
+If no arguments were specified,
+.Fa plugin_options
+will be the
+.Dv NULL
+pointer.
+.Pp
+The
+.Fa plugin_options
+parameter is only available starting with
+API version 1.2.
+A plugin
+.Sy must
+check the API version specified
+by the
+.Nm sudo
+front-end before using
+.Fa plugin_options .
+Failure to do so may result in a crash.
+.It Fa errstr
+If the
+.Fn open
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+The
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front-end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It Fa close
+.Bd -literal -compact
+void (*close)(int exit_status, int error);
+.Ed
+.Pp
+The
+.Fn close
+function is called when
+.Nm sudo
+is finished, shortly before it exits.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa exit_status
+The command's exit status, as returned by the
+.Xr wait 2
+system call, or zero if no command was run.
+The value of
+.Fa exit_status
+is undefined if
+.Fa error
+is non-zero.
+.It Fa error
+If the command could not be executed, this is set to the value of
+.Va errno
+set by the
+.Xr execve 2
+system call.
+If the command was successfully executed, the value of
+.Fa error
+is zero.
+.El
+.It Fa show_version
+.Bd -literal -compact
+int (*show_version)(int verbose);
+.Ed
+.Pp
+The
+.Fn show_version
+function is called by
+.Nm sudo
+when the user specifies the
+.Fl V
+option.
+The plugin may display its version information to the user via the
+.Fn conversation
+or
+.Fn sudo_plugin_printf
+function using
+.Dv SUDO_CONV_INFO_MSG .
+If the user requests detailed version information, the
+.Fa verbose
+flag will be non-zero.
+.Pp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error, although the return value is currently
+ignored.
+.It Fa log_ttyin
+.Bd -literal -compact
+int (*log_ttyin)(const char *buf, unsigned int len,
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn log_ttyin
+function is called whenever data can be read from
+the user but before it is passed to the running command.
+This allows the plugin to reject data if it chooses to (for instance
+if the input contains banned content).
+Returns 1 if the data should be passed to the command, 0 if the data
+is rejected (which will terminate the running command), or \-1 if an
+error occurred.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa buf
+The buffer containing user input.
+.It Fa len
+The length of
+.Fa buf
+in bytes.
+.It Fa errstr
+If the
+.Fn log_ttyin
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+The
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front-end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It Fa log_ttyout
+.Bd -literal -compact
+int (*log_ttyout)(const char *buf, unsigned int len,
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn log_ttyout
+function is called whenever data can be read from
+the command but before it is written to the user's terminal.
+This allows the plugin to reject data if it chooses to (for instance
+if the output contains banned content).
+Returns 1 if the data should be passed to the user, 0 if the data is rejected
+(which will terminate the running command), or \-1 if an error occurred.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa buf
+The buffer containing command output.
+.It Fa len
+The length of
+.Fa buf
+in bytes.
+.It Fa errstr
+If the
+.Fn log_ttyout
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+The
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front-end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It Fa log_stdin
+.Bd -literal -compact
+int (*log_stdin)(const char *buf, unsigned int len,
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn log_stdin
+function is only used if the standard input does
+not correspond to a tty device.
+It is called whenever data can be read from the standard input but
+before it is passed to the running command.
+This allows the plugin to reject data if it chooses to
+(for instance if the input contains banned content).
+Returns 1 if the data should be passed to the command, 0 if the
+data is rejected (which will terminate the running command), or \-1
+if an error occurred.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa buf
+The buffer containing user input.
+.It Fa len
+The length of
+.Fa buf
+in bytes.
+.It Fa errstr
+If the
+.Fn log_stdin
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+The
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front-end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It Fa log_stdout
+.Bd -literal -compact
+int (*log_stdout)(const char *buf, unsigned int len,
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn log_stdout
+function is only used if the standard output does not correspond
+to a tty device.
+It is called whenever data can be read from the command but before
+it is written to the standard output.
+This allows the plugin to reject data if it chooses to
+(for instance if the output contains banned content).
+Returns 1 if the data should be passed to the user, 0 if the data
+is rejected (which will terminate the running command), or \-1 if
+an error occurred.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa buf
+The buffer containing command output.
+.It Fa len
+The length of
+.Fa buf
+in bytes.
+.It Fa errstr
+If the
+.Fn log_stdout
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+The
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front-end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It Fa log_stderr
+.Bd -literal -compact
+int (*log_stderr)(const char *buf, unsigned int len,
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn log_stderr
+function is only used if the standard error does
+not correspond to a tty device.
+It is called whenever data can be read from the command but before it
+is written to the standard error.
+This allows the plugin to reject data if it chooses to
+(for instance if the output contains banned content).
+Returns 1 if the data should be passed to the user, 0 if the data
+is rejected (which will terminate the running command), or \-1 if
+an error occurred.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa buf
+The buffer containing command output.
+.It Fa len
+The length of
+.Fa buf
+in bytes.
+.It Fa errstr
+If the
+.Fn log_stderr
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+The
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front-end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It Fa register_hooks
+See the
+.Sx Policy plugin API
+section for a description of
+.Fn register_hooks .
+.It Fa deregister_hooks
+See the
+.Sx Policy plugin API
+section for a description of
+.Fn deregister_hooks .
+.It Fa change_winsize
+.Bd -literal -compact
+int (*change_winsize)(unsigned int lines, unsigned int cols,
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn change_winsize
+function is called whenever the window size of the terminal changes from
+the initial values specified in the
+.Fa user_info
+list.
+Returns \-1 if an error occurred, in which case no further calls to
+.Fn change_winsize
+will be made,
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa lines
+The number of lines (rows) in the re-sized terminal.
+.It Fa cols
+The number of columns in the re-sized terminal.
+.It Fa errstr
+If the
+.Fn change_winsize
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+The
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front-end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.El
+.It Fa log_suspend
+.Bd -literal -compact
+int (*log_suspend)(int signo, const char **errstr);
+.Ed
+.Pp
+The
+.Fn log_suspend
+function is called whenever a command is suspended or resumed.
+Logging this information makes it possible to skip the period of time when
+the command was suspended during playback of a session.
+Returns \-1 if an error occurred, in which case no further calls to
+.Fn log_suspend
+will be made,
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa signo
+The signal that caused the command to be suspended, or
+.Dv SIGCONT
+if the command was resumed.
+.It Fa errstr
+If the
+.Fn log_suspend
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.Pp
+The
+.Fa errstr
+parameter is only available starting with
+API version 1.15.
+A plugin
+.Sy must
+check the API version specified by the
+.Nm sudo
+front-end before using
+.Fa errstr .
+Failure to do so may result in a crash.
+.It Fa event_alloc
+.Bd -literal -compact
+struct sudo_plugin_event * (*event_alloc)(void);
+.Ed
+.Pp
+The
+.Fn event_alloc
+function is used to allocate a
+.Vt struct sudo_plugin_event
+which provides access to the main
+.Nm sudo
+event loop.
+Unlike the other fields, the
+.Fn event_alloc
+pointer is filled in by the
+.Nm sudo
+front-end, not by the plugin.
+.Pp
+See the
+.Sx Event API
+section below for more information
+about events.
+.Pp
+The
+.Fn event_alloc
+function is only available starting
+with API version 1.15.
+If the
+.Nm sudo
+front-end doesn't support API
+version 1.15 or higher,
+.Fn event_alloc
+will not be set.
+.El
+.Pp
+.Em I/O Plugin Version Macros
+.Pp
+Same as for the
+.Sx Policy plugin API .
+.El
+.Ss Audit plugin API
+.Bd -literal
+/* Audit plugin close function status types. */
+#define SUDO_PLUGIN_NO_STATUS 0
+#define SUDO_PLUGIN_WAIT_STATUS 1
+#define SUDO_PLUGIN_EXEC_ERROR 2
+#define SUDO_PLUGIN_SUDO_ERROR 3
+
+#define SUDO_AUDIT_PLUGIN 3
+struct audit_plugin {
+ unsigned int type; /* always SUDO_AUDIT_PLUGIN */
+ unsigned int version; /* always SUDO_API_VERSION */
+ int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr);
+ void (*close)(int status_type, int status);
+ int (*accept)(const char *plugin_name,
+ unsigned int plugin_type, char * const command_info[],
+ char * const run_argv[], char * const run_envp[],
+ const char **errstr);
+ int (*reject)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+ int (*error)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+ int (*show_version)(int verbose);
+ void (*register_hooks)(int version,
+ int (*register_hook)(struct sudo_hook *hook));
+ void (*deregister_hooks)(int version,
+ int (*deregister_hook)(struct sudo_hook *hook));
+ struct sudo_plugin_event * (*event_alloc)(void);
+}
+.Ed
+.Pp
+An audit plugin can be used to log successful and unsuccessful attempts
+to run
+.Nm sudo
+independent of the policy or any I/O plugins.
+Multiple audit plugins may be specified in
+.Xr sudo.conf @mansectform@ .
+.Pp
+A
+.Vt struct audit_plugin
+has the following fields:
+.Bl -tag -width 4n
+.It Fa type
+The
+.Fa type
+field should always be set to
+.Dv SUDO_AUDIT_PLUGIN .
+.It Fa version
+The
+.Fa version
+field should be set to
+.Dv SUDO_API_VERSION .
+.Pp
+This allows
+.Nm sudo
+to determine the API version the plugin was
+built against.
+.It Fa open
+.Bd -literal -compact
+int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr);
+.Ed
+.Pp
+The audit
+.Fn open
+function is run before any other
+.Nm sudo
+plugin API functions.
+This makes it possible to audit failures in the other plugins.
+It returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+.Nm sudo
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+.Fn conversation
+or
+.Fn plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional error information to the user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa version
+The version passed in by
+.Nm sudo
+allows the plugin to determine the
+major and minor version number of the plugin API supported by
+.Nm sudo .
+.It Fa conversation
+A pointer to the
+.Fn conversation
+function that may be used by the
+.Fn show_version
+function to display version information (see
+.Fn show_version
+below).
+The
+.Fn conversation
+function may also be used to display additional error message to the user.
+The
+.Fn conversation
+function returns 0 on success, and \-1 on failure.
+.It Fa plugin_printf
+A pointer to a
+.Fn printf Ns -style
+function that may be used by the
+.Fn show_version
+function to display version information (see
+show_version below).
+The
+.Fn plugin_printf
+function may also be used to display additional error message to the user.
+The
+.Fn plugin_printf
+function returns number of characters printed on success and \-1 on failure.
+.It Fa settings
+A vector of user-supplied
+.Nm sudo
+settings in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+These settings correspond to options the user specified when running
+.Nm sudo .
+As such, they will only be present when the corresponding option has
+been specified on the command line.
+.Pp
+When parsing
+.Fa settings ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible settings.
+.It Fa user_info
+A vector of information about the user running the command in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Fa user_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible strings.
+.It Fa submit_optind
+The index into
+.Fa submit_argv
+that corresponds to the first entry that is not a command line option.
+If
+.Fa submit_argv
+only consists of options, which may be the case with the
+.Fl l
+or
+.Fl v
+options,
+.Fa submit_argv Ns [ Fa submit_optind ]
+will evaluate to the NULL pointer.
+.It Fa submit_argv
+The argument vector
+.Nm sudo
+was invoked with, including all command line options.
+The
+.Fa submit_optind
+argument can be used to determine the end of the command line options.
+.It Fa submit_envp
+The invoking user's environment in the form of a
+.Dv NULL Ns -terminated
+vector of
+.Dq name=value
+strings.
+.Pp
+When parsing
+.Fa submit_envp ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.It Fa plugin_options
+Any (non-comment) strings immediately after the plugin path are
+treated as arguments to the plugin.
+These arguments are split on a white space boundary and are passed to
+the plugin in the form of a
+.Dv NULL Ns -terminated
+array of strings.
+If no arguments were specified,
+.Fa plugin_options
+will be the
+.Dv NULL
+pointer.
+.It Fa errstr
+If the
+.Fn open
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.El
+.It Fa close
+.Bd -literal -compact
+void (*close)(int status_type, int status);
+.Ed
+.Pp
+The
+.Fn close
+function is called when
+.Nm sudo
+is finished, shortly before it exits.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa status_type
+The type of status being passed.
+One of
+.Dv SUDO_PLUGIN_NO_STATUS ,
+.Dv SUDO_PLUGIN_WAIT_STATUS ,
+.Dv SUDO_PLUGIN_EXEC_ERROR
+or
+.Dv SUDO_PLUGIN_SUDO_ERROR .
+.It Fa status
+Depending on the value of
+.Fa status_type ,
+this value is either
+ignored, the command's exit status as returned by the
+.Xr wait 2
+system call, the value of
+.Va errno
+set by the
+.Xr execve 2
+system call, or the value of
+.Va errno
+resulting from an error in the
+.Nm sudo
+front-end.
+.El
+.It Fa accept
+.Bd -literal -compact
+int (*accept)(const char *plugin_name, unsigned int plugin_type,
+ char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr);
+.Ed
+.Pp
+The
+.Fn accept
+function is called when a command or action is accepted by a policy
+or approval plugin.
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa plugin_name
+The name of the plugin that accepted the command or
+.Dq sudo
+for the
+.Nm sudo
+front-end.
+.It Fa plugin_type
+The type of plugin that accepted the command, currently either
+.Dv SUDO_POLICY_PLUGIN ,
+.Dv SUDO_POLICY_APPROVAL ,
+or
+.Dv SUDO_FRONT_END .
+The
+.Fn accept
+function is called multiple times--once for each policy or approval
+plugin that succeeds and once for the sudo front-end.
+When called on behalf of the sudo front-end,
+.Fa command_info
+may include information from an I/O logging plugin as well.
+.Pp
+Typically, an audit plugin is interested in either the accept status from
+the
+.Nm sudo
+front-end or from the various policy and approval plugins, but not both.
+It is possible for the policy plugin to accept a command that is
+later rejected by an approval plugin, in which case the audit
+plugin's
+.Fn accept
+and
+.Fn reject
+functions will
+.Em both
+be called.
+.It Fa command_info
+An optional
+vector of information describing the command being run in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Fa command_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible strings.
+.It Fa run_argv
+A
+.Dv NULL Ns -terminated
+argument vector describing a command that will be run in the
+same form as what would be passed to the
+.Xr execve 2
+system call.
+.It Fa run_envp
+The environment the command will be run with in the form of a
+.Dv NULL Ns -terminated
+vector of
+.Dq name=value
+strings.
+.Pp
+When parsing
+.Fa run_envp ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.It Fa errstr
+If the
+.Fn accept
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.El
+.It Fa reject
+.Bd -literal -compact
+int (*reject)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn reject
+function is called when a command or action is rejected by a plugin.
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa plugin_name
+The name of the plugin that rejected the command.
+.It Fa plugin_type
+The type of plugin that rejected the command, currently either
+.Dv SUDO_POLICY_PLUGIN ,
+.Dv SUDO_APPROVAL_PLUGIN ,
+or
+.Dv SUDO_IO_PLUGIN .
+.Pp
+Unlike the
+.Fn accept
+function, the
+.Fn reject
+function is not called on behalf of the
+.Nm sudo
+front-end.
+.It Fa audit_msg
+An optional string describing the reason the command was rejected
+by the plugin.
+If the plugin did not provide a reason,
+.Fa audit_msg
+will be the
+.Dv NULL
+pointer.
+.It Fa command_info
+An optional
+vector of information describing the command being run in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Fa command_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible strings.
+.It Fa errstr
+If the
+.Fn reject
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.El
+.It Fa error
+.Bd -literal -compact
+int (*error)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+.Ed
+.Pp
+The
+.Fn error
+function is called when a plugin or the
+.Nm sudo
+front-end returns an error.
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa plugin_name
+The name of the plugin that generated the error or
+.Dq sudo
+for the
+.Nm sudo
+front-end.
+.It Fa plugin_type
+The type of plugin that generated the error, or
+.Dv SUDO_FRONT_END
+for the
+.Nm sudo
+front-end.
+.It Fa audit_msg
+An optional string describing the plugin error.
+If the plugin did not provide a description,
+.Fa audit_msg
+will be the
+.Dv NULL
+pointer.
+.It Fa command_info
+An optional
+vector of information describing the command being run in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Fa command_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible strings.
+.It Fa errstr
+If the
+.Fn error
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.El
+.It Fa show_version
+.Bd -literal -compact
+int (*show_version)(int verbose);
+.Ed
+.Pp
+The
+.Fn show_version
+function is called by
+.Nm sudo
+when the user specifies the
+.Fl V
+option.
+The plugin may display its version information to the user via the
+.Fn conversation
+or
+.Fn plugin_printf
+function using
+.Dv SUDO_CONV_INFO_MSG .
+If the user requests detailed version information, the verbose flag will be set.
+.Pp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error, although the return value is currently
+ignored.
+.It Fa register_hooks
+See the
+.Sx Policy plugin API
+section for a description of
+.Fn register_hooks .
+.It Fa deregister_hooks
+See the
+.Sx Policy plugin API
+section for a description of
+.Fn deregister_hooks .
+.It Fa event_alloc
+.Bd -literal -compact
+struct sudo_plugin_event * (*event_alloc)(void);
+.Ed
+.Pp
+The
+.Fn event_alloc
+function is used to allocate a
+.Vt struct sudo_plugin_event
+which provides access to the main
+.Nm sudo
+event loop.
+Unlike the other fields, the
+.Fa event_alloc
+pointer is filled in by the
+.Nm sudo
+front-end, not by the plugin.
+.Pp
+See the
+.Sx Event API
+section below for more information
+about events.
+.Pp
+The
+.Fn event_alloc
+function is only available starting
+with API version 1.17.
+If the
+.Nm sudo
+front-end doesn't support API
+version 1.17 or higher,
+.Fn event_alloc
+will not be set.
+.El
+.Ss Approval plugin API
+.Bd -literal
+struct approval_plugin {
+#define SUDO_APPROVAL_PLUGIN 4
+ unsigned int type; /* always SUDO_APPROVAL_PLUGIN */
+ unsigned int version; /* always SUDO_API_VERSION */
+ int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr);
+ void (*close)(void);
+ int (*check)(char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr);
+ int (*show_version)(int verbose);
+};
+.Ed
+.Pp
+An approval plugin can be used to apply extra constraints after a
+command has been accepted by the policy plugin.
+Unlike the other plugin types, it does not remain open until the command
+completes.
+The plugin is opened before a call to
+.Fn check
+or
+.Fn show_version
+and closed shortly thereafter (audit plugin functions must be called
+before the plugin is closed).
+Multiple approval plugins may be specified in
+.Xr sudo.conf @mansectform@ .
+.Pp
+A
+.Vt struct approval_plugin
+has the following fields:
+.Bl -tag -width 4n
+.It Fa type
+The
+.Fa type
+field should always be set to
+.Dv SUDO_APPROVAL_PLUGIN .
+.It Fa version
+The
+.Fa version
+field should be set to
+.Dv SUDO_API_VERSION .
+.Pp
+This allows
+.Nm sudo
+to determine the API version the plugin was
+built against.
+.It Fa open
+.Bd -literal -compact
+int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr);
+.Ed
+.Pp
+The approval
+.Fn open
+function is run immediately before a call to the plugin's
+.Fn check
+or
+.Fn show_version
+functions.
+It is only called if the version is being requested or if the
+policy plugin's
+.Fn check_policy
+function has returned successfully.
+It returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+.Nm sudo
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+.Fn conversation
+or
+.Fn plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional error information to the user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa version
+The version passed in by
+.Nm sudo
+allows the plugin to determine the
+major and minor version number of the plugin API supported by
+.Nm sudo .
+.It Fa conversation
+A pointer to the
+.Fn conversation
+function that can be used by the plugin to interact with the user (see
+.Sx Conversation API
+for details).
+Returns 0 on success and \-1 on failure.
+.It Fa plugin_printf
+A pointer to a
+.Fn printf Ns -style
+function that may be used to display informational or error messages (see
+.Sx Conversation API
+for details).
+Returns the number of characters printed on success and \-1 on failure.
+.It Fa settings
+A vector of user-supplied
+.Nm sudo
+settings in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+These settings correspond to options the user specified when running
+.Nm sudo .
+As such, they will only be present when the corresponding option has
+been specified on the command line.
+.Pp
+When parsing
+.Fa settings ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible settings.
+.It Fa user_info
+A vector of information about the user running the command in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Fa user_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible strings.
+.It Fa submit_optind
+The index into
+.Fa submit_argv
+that corresponds to the first entry that is not a command line option.
+If
+.Fa submit_argv
+only consists of options, which may be the case with the
+.Fl l
+or
+.Fl v
+options,
+.Fa submit_argv Ns [ Fa submit_optind ]
+will evaluate to the NULL pointer.
+.It Fa submit_argv
+The argument vector
+.Nm sudo
+was invoked with, including all command line options.
+The
+.Fa submit_optind
+argument can be used to determine the end of the command line options.
+.It Fa submit_envp
+The invoking user's environment in the form of a
+.Dv NULL Ns -terminated
+vector of
+.Dq name=value
+strings.
+.Pp
+When parsing
+.Fa submit_envp ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.It Fa plugin_options
+Any (non-comment) strings immediately after the plugin path are
+treated as arguments to the plugin.
+These arguments are split on a white space boundary and are passed to
+the plugin in the form of a
+.Dv NULL Ns -terminated
+array of strings.
+If no arguments were specified,
+.Fa plugin_options
+will be the
+.Dv NULL
+pointer.
+.It Fa errstr
+If the
+.Fn open
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.El
+.It Fa close
+.Bd -literal -compact
+void (*close)(void);
+.Ed
+.Pp
+The
+.Fn close
+function is called after the approval plugin's
+.Fn check
+or
+.Fn show_version
+functions have been called.
+It takes no arguments.
+The
+.Fn close
+function is typically used to perform plugin-specific cleanup,
+such as the freeing of memory objects allocated by the plugin.
+If the plugin does not need to perform any cleanup,
+.Fn close
+may be set to the
+.Dv NULL
+pointer.
+.It Fa check
+.Bd -literal -compact
+int (*check)(char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr);
+.Ed
+.Pp
+The approval
+.Fn check
+function is run after the policy plugin
+.Fn check_policy
+function and before any I/O logging plugins.
+If multiple approval plugins are loaded, they must all succeed for
+the command to be allowed.
+It returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error.
+In the latter case,
+.Nm sudo
+will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the
+.Fn conversation
+or
+.Fn plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional error information to the user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa command_info
+A vector of information describing the command being run in the form of
+.Dq name=value
+strings.
+The vector is terminated by a
+.Dv NULL
+pointer.
+.Pp
+When parsing
+.Fa command_info ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.Pp
+See the
+.Sx Policy plugin API
+section for a list of all possible strings.
+.It Fa run_argv
+A
+.Dv NULL Ns -terminated
+argument vector describing a command that will be run in the
+same form as what would be passed to the
+.Xr execve 2
+system call.
+.It Fa run_envp
+The environment the command will be run with in the form of a
+.Dv NULL Ns -terminated
+vector of
+.Dq name=value
+strings.
+.Pp
+When parsing
+.Fa run_envp ,
+the plugin should split on the
+.Sy first
+equal sign
+.Pq Ql =
+since the
+.Em name
+field will never include one
+itself but the
+.Em value
+might.
+.It Fa errstr
+If the
+.Fn open
+function returns a value other than 1, the plugin may
+store a message describing the failure or error in
+.Fa errstr .
+The
+.Nm sudo
+front-end will then pass this value to any registered audit plugins.
+The string stored in
+.Fa errstr
+must remain valid until the plugin's
+.Fn close
+function is called.
+.El
+.It Fa show_version
+.Bd -literal -compact
+int (*show_version)(int verbose);
+.Ed
+.Pp
+The
+.Fn show_version
+function is called by
+.Nm sudo
+when the user specifies the
+.Fl V
+option.
+The plugin may display its version information to the user via the
+.Fn conversation
+or
+.Fn plugin_printf
+function using
+.Dv SUDO_CONV_INFO_MSG .
+If the user requests detailed version information, the verbose flag will be set.
+.Pp
+Returns 1 on success, 0 on failure, \-1 if a general error occurred,
+or \-2 if there was a usage error, although the return value is currently
+ignored.
+.El
+.Ss Signal handlers
+The
+.Nm sudo
+front-end installs default signal handlers to trap common signals
+while the plugin functions are run.
+The following signals are trapped by default before the command is
+executed:
+.Pp
+.Bl -bullet -compact -width 1n
+.It
+.Dv SIGALRM
+.It
+.Dv SIGHUP
+.It
+.Dv SIGINT
+.It
+.Dv SIGPIPE
+.It
+.Dv SIGQUIT
+.It
+.Dv SIGTERM
+.It
+.Dv SIGTSTP
+.It
+.Dv SIGUSR1
+.It
+.Dv SIGUSR2
+.El
+.Pp
+If a fatal signal is received before the command is executed,
+.Nm sudo
+will call the plugin's
+.Fn close
+function with an exit status of 128 plus the value of the signal
+that was received.
+This allows for consistent logging of commands killed by a signal
+for plugins that log such information in their
+.Fn close
+function.
+An exception to this is
+.Dv SIGPIPE ,
+which is ignored until the command is executed.
+.Pp
+A plugin may temporarily install its own signal handlers but must
+restore the original handler before the plugin function returns.
+.Ss Hook function API
+Beginning with plugin API version 1.2, it is possible to install
+hooks for certain functions called by the
+.Nm sudo
+front-end.
+.Pp
+Currently, the only supported hooks relate to the handling of
+environment variables.
+Hooks can be used to intercept attempts to get, set, or remove
+environment variables so that these changes can be reflected in
+the version of the environment that is used to execute a command.
+A future version of the API will support hooking internal
+.Nm sudo
+front-end functions as well.
+.Pp
+.Em Hook structure
+.Pp
+Hooks in
+.Nm sudo
+are described by the following structure:
+.Bd -literal
+typedef int (*sudo_hook_fn_t)();
+
+struct sudo_hook {
+ unsigned int hook_version;
+ unsigned int hook_type;
+ sudo_hook_fn_t hook_fn;
+ void *closure;
+};
+.Ed
+.Pp
+A
+.Vt struct sudo_hook
+has the following fields:
+.Bl -tag -width 4n
+.It Fa hook_version
+The
+.Fa hook_version
+field should be set to
+.Dv SUDO_HOOK_VERSION .
+.It Fa hook_type
+The
+.Fa hook_type
+field may be one of the following supported hook types:
+.Bl -tag -width 4n
+.It Dv SUDO_HOOK_SETENV
+The C library
+.Xr setenv 3
+function.
+Any registered hooks will run before the C library implementation.
+The
+.Fa hook_fn
+field should
+be a function that matches the following typedef:
+.Bd -literal
+typedef int (*sudo_hook_fn_setenv_t)(const char *name,
+ const char *value, int overwrite, void *closure);
+.Ed
+.Pp
+If the registered hook does not match the typedef the results are
+unspecified.
+.It Dv SUDO_HOOK_UNSETENV
+The C library
+.Xr unsetenv 3
+function.
+Any registered hooks will run before the C library implementation.
+The
+.Fa hook_fn
+field should
+be a function that matches the following typedef:
+.Bd -literal
+typedef int (*sudo_hook_fn_unsetenv_t)(const char *name,
+ void *closure);
+.Ed
+.It Dv SUDO_HOOK_GETENV
+The C library
+.Xr getenv 3
+function.
+Any registered hooks will run before the C library implementation.
+The
+.Fa hook_fn
+field should
+be a function that matches the following typedef:
+.Bd -literal
+typedef int (*sudo_hook_fn_getenv_t)(const char *name,
+ char **value, void *closure);
+.Ed
+.Pp
+If the registered hook does not match the typedef the results are
+unspecified.
+.It Dv SUDO_HOOK_PUTENV
+The C library
+.Xr putenv 3
+function.
+Any registered hooks will run before the C library implementation.
+The
+.Fa hook_fn
+field should
+be a function that matches the following typedef:
+.Bd -literal
+typedef int (*sudo_hook_fn_putenv_t)(char *string,
+ void *closure);
+.Ed
+.Pp
+If the registered hook does not match the typedef the results are
+unspecified.
+.El
+.It Fa hook_fn
+.Bd -literal -compact
+sudo_hook_fn_t hook_fn;
+.Ed
+.Pp
+The
+.Fa hook_fn
+field should be set to the plugin's hook implementation.
+The actual function arguments will vary depending on the
+.Fa hook_type
+(see
+.Fa hook_type
+above).
+In all cases, the
+.Fa closure
+field of
+.Vt struct sudo_hook
+is passed as the last function parameter.
+This can be used to pass arbitrary data to the plugin's hook implementation.
+.Pp
+The function return value may be one of the following:
+.Bl -tag -width 4n
+.It Dv SUDO_HOOK_RET_ERROR
+The hook function encountered an error.
+.It Dv SUDO_HOOK_RET_NEXT
+The hook completed without error, go on to the next hook (including
+the system implementation if applicable).
+For example, a
+.Xr getenv 3
+hook might return
+.Dv SUDO_HOOK_RET_NEXT
+if the specified variable was not found in the private copy of the environment.
+.It Dv SUDO_HOOK_RET_STOP
+The hook completed without error, stop processing hooks for this invocation.
+This can be used to replace the system implementation.
+For example, a
+.Fa setenv
+hook that operates on a private copy of
+the environment but leaves
+.Va environ
+unchanged.
+.El
+.El
+.Pp
+Care must be taken when hooking C library functions,
+it is very easy to create an infinite loop.
+For example, a
+.Xr getenv 3
+hook that calls the
+.Xr snprintf 3
+function may create a loop if the
+.Xr snprintf 3
+implementation calls
+.Xr getenv 3
+to check the locale.
+To prevent this, you may wish to use a static variable in the hook
+function to guard against nested calls.
+For example:
+.Bd -literal -offset indent
+static int in_progress = 0; /* avoid recursion */
+if (in_progress)
+ return SUDO_HOOK_RET_NEXT;
+in_progress = 1;
+\&...
+in_progress = 0;
+return SUDO_HOOK_RET_STOP;
+.Ed
+.Pp
+.Em Hook API Version Macros
+.Bd -literal
+/* Hook API version major/minor */
+#define SUDO_HOOK_VERSION_MAJOR 1
+#define SUDO_HOOK_VERSION_MINOR 0
+#define SUDO_HOOK_VERSION SUDO_API_MKVERSION(SUDO_HOOK_VERSION_MAJOR,\e
+ SUDO_HOOK_VERSION_MINOR)
+.Ed
+.Pp
+For getters and setters see the
+.Sx Policy plugin API .
+.Ss Event API
+When
+.Nm sudo
+runs a command, it uses an event loop to service signals and I/O.
+Events may be triggered based on time, a file or socket descriptor
+becoming ready, or due to receipt of a signal.
+Starting with API version 1.15, it is possible for a plugin to
+participate in this event loop by calling the
+.Fn event_alloc
+function.
+.Pp
+.Em Event structure
+.Pp
+Events are described by the following structure:
+.Pp
+.Bd -literal -compact
+typedef void (*sudo_plugin_ev_callback_t)(int fd, int what, void *closure);
+
+struct sudo_plugin_event {
+ int (*set)(struct sudo_plugin_event *pev, int fd, int events,
+ sudo_plugin_ev_callback_t callback, void *closure);
+ int (*add)(struct sudo_plugin_event *pev, struct timespec *timeout);
+ int (*del)(struct sudo_plugin_event *pev);
+ int (*pending)(struct sudo_plugin_event *pev, int events,
+ struct timespec *ts);
+ int (*fd)(struct sudo_plugin_event *pev);
+ void (*setbase)(struct sudo_plugin_event *pev, void *base);
+ void (*loopbreak)(struct sudo_plugin_event *pev);
+ void (*free)(struct sudo_plugin_event *pev);
+};
+.Ed
+.Pp
+A
+.Vt struct sudo_plugin_event
+contains the following function pointers:
+.Bl -tag -width 4n
+.It Fa set
+.Bd -literal -compact
+int (*set)(struct sudo_plugin_event *pev, int fd, int events,
+ sudo_plugin_ev_callback_t callback, void *closure);
+.Ed
+.Pp
+The
+.Fn set
+function takes the following arguments:
+.Bl -tag -width 4n
+.It Vt struct sudo_plugin_event * Ns Fa pev
+A pointer to the
+.Vt struct sudo_plugin_event
+itself.
+.It Fa fd
+The file or socket descriptor for I/O-based events or the signal
+number for signal events.
+For time-based events,
+.Fa fd
+must be \-1.
+.It Fa events
+The following values determine what will trigger the event callback:
+.Bl -tag -width 4n
+.It Dv SUDO_PLUGIN_EV_TIMEOUT
+callback is run after the specified timeout expires
+.It Dv SUDO_PLUGIN_EV_READ
+callback is run when the file descriptor is readable
+.It Dv SUDO_PLUGIN_EV_WRITE
+callback is run when the file descriptor is writable
+.It Dv SUDO_PLUGIN_EV_PERSIST
+event is persistent and remains enabled until explicitly deleted
+.It Dv SUDO_PLUGIN_EV_SIGNAL
+callback is run when the specified signal is received
+.El
+.Pp
+The
+.Dv SUDO_PLUGIN_EV_PERSIST
+flag may be ORed with any of the event types.
+It is also possible to OR
+.Dv SUDO_PLUGIN_EV_READ
+and
+.Dv SUDO_PLUGIN_EV_WRITE
+together to run the callback when a descriptor is ready to be
+either read from or written to.
+All other event values are mutually exclusive.
+.It Vt sudo_plugin_ev_callback_t Fa callback
+.Bd -literal -compact
+typedef void (*sudo_plugin_ev_callback_t)(int fd, int what,
+ void *closure);
+.Ed
+.Pp
+The function to call when an event is triggered.
+The
+.Fn callback
+function is run with the following arguments:
+.Bl -tag -width 4n
+.It Fa fd
+The file or socket descriptor for I/O-based events or the signal
+number for signal events.
+.It Fa what
+The event type that triggered that callback.
+For events that have multiple event types (for example
+.Dv SUDO_PLUGIN_EV_READ
+and
+.Dv SUDO_PLUGIN_EV_WRITE )
+or have an associated timeout,
+.Fa what
+can be used to determine why the callback was run.
+.It Fa closure
+The generic pointer that was specified in the
+.Fn set
+function.
+.El
+.It Fa closure
+A generic pointer that will be passed to the callback function.
+.El
+.Pp
+The
+.Fn set
+function returns 1 on success, and \-1 if a error occurred.
+.It Fa add
+.Bd -literal -compact
+int (*add)(struct sudo_plugin_event *pev, struct timespec *timeout);
+.Ed
+.Pp
+The
+.Fn add
+function adds the event
+.Fa pev
+to
+.Nm sudo Ns No 's
+event loop.
+The event must have previously been initialized via the
+.Fn set
+function.
+If the
+.Fa timeout
+argument is not NULL, it should specify a (relative) timeout after
+which the event will be triggered if the main event criteria has
+not been met.
+This is often used to implement an I/O timeout where the event
+will fire if a descriptor is not ready within a certain time
+period.
+If the event is already present in the event loop, its
+.Fa timeout
+will be adjusted to match the new value, if any.
+.Pp
+The
+.Fn add
+function returns 1 on success, and \-1 if a error occurred.
+.It Fa del
+.Bd -literal -compact
+int (*del)(struct sudo_plugin_event *pev);
+.Ed
+.Pp
+The
+.Fn del
+function deletes the event
+.Fa pev
+from
+.Nm sudo Ns No 's
+event loop.
+Deleted events can be added back via the
+.Fn add
+function.
+.Pp
+The
+.Fn del
+function returns 1 on success, and \-1 if a error occurred.
+.It Fa pending
+.Bd -literal -compact
+int (*pending)(struct sudo_plugin_event *pev, int events,
+ struct timespec *ts);
+.Ed
+.Pp
+The
+.Fn pending
+function can be used to determine whether one or more events is pending.
+The
+.Fa events
+argument specifies which events to check for.
+See the
+.Fn set
+function for a list of valid event types.
+If
+.Dv SUDO_PLUGIN_EV_TIMEOUT
+is specified in
+.Fa events ,
+the event has an associated timeout and the
+.Fa ts
+pointer is non-NULL, it will be filled in with the remaining time.
+.It Fa fd
+.Bd -literal -compact
+int (*fd)(struct sudo_plugin_event *pev);
+.Ed
+.Pp
+The
+.Fn fd
+function returns the descriptor or signal number associated with
+the event
+.Fa pev .
+.It Fa setbase
+.Bd -literal -compact
+void (*setbase)(struct sudo_plugin_event *pev, void *base);
+.Ed
+.Pp
+The
+.Fn setbase
+function sets the underlying event
+.Fa base
+for
+.Fa pev
+to the specified value.
+This can be used to move an event created via
+.Fn event_alloc
+to a new event loop allocated by sudo's event subsystem.
+If
+.Fa base
+is
+.Dv NULL ,
+.Fa pev Ns 's
+event base is reset to the default value, which corresponds to
+.Nm sudo Ns 's
+main event loop.
+Using this function requires linking the plugin with the sudo_util
+library.
+It is unlikely to be used outside of the
+.Nm sudoers
+plugin.
+.It Fa loopbreak
+.Bd -literal -compact
+void (*loopbreak)(struct sudo_plugin_event *pev);
+.Ed
+.Pp
+The
+.Fn loopbreak
+function causes
+.Nm sudo Ns No 's
+event loop to exit immediately and the running command to be terminated.
+.It Fa free
+.Bd -literal -compact
+void (*free)(struct sudo_plugin_event *pev);
+.Ed
+.Pp
+The
+.Fn free
+function deletes the event
+.Fa pev
+from the event loop and frees the memory associated with it.
+.El
+.Ss Remote command execution
+The
+.Nm sudo
+front-end does not support running remote commands.
+However, starting with
+.Nm sudo
+1.8.8, the
+.Fl h
+option may be used to specify a remote host that is passed
+to the policy plugin.
+A plugin may also accept a
+.Em runas_user
+in the form of
+.Dq user@hostname
+which will work with older versions of
+.Nm sudo .
+It is anticipated that remote commands will be supported by executing a
+.Dq helper
+program.
+The policy plugin should setup the execution environment such that the
+.Nm sudo
+front-end will run the helper which, in turn, will connect to the
+remote host and run the command.
+.Pp
+For example, the policy plugin could utilize
+.Nm ssh
+to perform remote command execution.
+The helper program would be responsible for running
+.Nm ssh
+with the proper options to use a private key or certificate
+that the remote host will accept and run a program
+on the remote host that would setup the execution environment
+accordingly.
+.Pp
+Remote
+.Nm sudoedit
+functionality must be handled by the policy plugin, not
+.Nm sudo
+itself as the front-end has no knowledge that a remote command is
+being executed.
+This may be addressed in a future revision of the plugin API.
+.Ss Conversation API
+If the plugin needs to interact with the user, it may do so via the
+.Fn conversation
+function.
+A plugin should not attempt to read directly from the standard input
+or the user's terminal (neither of which are guaranteed to exist).
+The caller must include a trailing newline in
+.Fa msg
+if one is to be printed.
+.Pp
+A
+.Fn printf Ns -style
+function is also available that can be used to display informational
+or error messages to the user, which is usually more convenient for
+simple messages where no use input is required.
+.Pp
+.Em Conversation function structures
+.Pp
+The conversation function takes as arguments pointers to the following
+structures:
+.Bd -literal
+struct sudo_conv_message {
+#define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */
+#define SUDO_CONV_PROMPT_ECHO_ON 0x0002 /* echo user input */
+#define SUDO_CONV_ERROR_MSG 0x0003 /* error message */
+#define SUDO_CONV_INFO_MSG 0x0004 /* informational message */
+#define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */
+#define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */
+#define SUDO_CONV_PREFER_TTY 0x2000 /* flag: use tty if possible */
+ int msg_type;
+ int timeout;
+ const char *msg;
+};
+
+#define SUDO_CONV_REPL_MAX 1023
+
+struct sudo_conv_reply {
+ char *reply;
+};
+
+typedef int (*sudo_conv_callback_fn_t)(int signo, void *closure);
+struct sudo_conv_callback {
+ unsigned int version;
+ void *closure;
+ sudo_conv_callback_fn_t on_suspend;
+ sudo_conv_callback_fn_t on_resume;
+};
+.Ed
+.Pp
+Pointers to the
+.Fn conversation
+and
+.Fn printf Ns -style
+functions are passed
+in to the plugin's
+.Fn open
+function when the plugin is initialized.
+The following type definitions can be used in the declaration of the
+.Fn open
+function:
+.Bd -literal
+typedef int (*sudo_conv_t)(int num_msgs,
+ const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback);
+
+typedef int (*sudo_printf_t)(int msg_type, const char * restrict fmt, ...);
+.Ed
+.Pp
+To use the
+.Fn conversation
+function, the plugin must pass an array of
+.Vt struct sudo_conv_message
+and
+.Vt struct sudo_conv_reply .
+There must be a
+.Vt struct sudo_conv_message
+and
+.Vt struct sudo_conv_reply
+for each message in the conversation, that is, both arrays must
+have the same number of elements.
+Each
+.Vt struct sudo_conv_reply
+must have its
+.Fa reply
+member initialized to
+.Dv NULL .
+The
+.Vt struct sudo_conv_callback
+pointer, if not
+.Dv NULL ,
+should contain function pointers to be called when the
+.Nm sudo
+process is suspended and/or resumed during conversation input.
+The
+.Fa on_suspend
+and
+.Fa on_resume
+functions are called with the signal that caused
+.Nm sudo
+to be suspended and the
+.Fa closure
+pointer from the
+.Vt struct sudo_conv_callback .
+These functions should return 0 on success and \-1 on error.
+On error, the conversation will end and the conversation function
+will return a value of \-1.
+The intended use is to allow the plugin to release resources, such as locks,
+that should not be held indefinitely while suspended and then reacquire them
+when the process is resumed.
+The functions are not actually invoked from within a signal handler.
+.Pp
+The
+.Fa msg_type
+must be set to one of the following values:
+.Bl -tag -width 4n
+.It Dv SUDO_CONV_PROMPT_ECHO_OFF
+Prompt the user for input with echo disabled;
+this is generally used for passwords.
+The reply will be stored in the
+.Fa replies
+array, and it will never be
+.Dv NULL .
+.It Dv SUDO_CONV_PROMPT_ECHO_ON
+Prompt the user for input with echo enabled.
+The reply will be stored in the
+.Fa replies
+array, and it will never be
+.Dv NULL .
+.It Dv SUDO_CONV_ERROR_MSG
+Display an error message.
+The message is written to the standard error unless the
+.Dv SUDO_CONV_PREFER_TTY
+flag is set, in which case it is written to the user's terminal if possible.
+.It Dv SUDO_CONV_INFO_MSG
+Display a message.
+The message is written to the standard output unless the
+.Dv SUDO_CONV_PREFER_TTY
+flag is set, in which case it is written to the user's terminal if possible.
+.It Dv SUDO_CONV_PROMPT_MASK
+Prompt the user for input but echo an asterisk character for each
+character read.
+The reply will be stored in the
+.Fa replies
+array, and it will never be
+.Dv NULL .
+This can be used to provide visual feedback to the user while reading
+sensitive information that should not be displayed.
+.El
+.Pp
+In addition to the above values, the following flag bits may also be set:
+.Bl -tag -width 4n
+.It Dv SUDO_CONV_PROMPT_ECHO_OK
+Allow input to be read when echo cannot be disabled
+when the message type is
+.Dv SUDO_CONV_PROMPT_ECHO_OFF
+or
+.Dv SUDO_CONV_PROMPT_MASK .
+By default,
+.Nm sudo
+will refuse to read input if the echo cannot be disabled for those
+message types.
+.It Dv SUDO_CONV_PREFER_TTY
+When displaying a message via
+.Dv SUDO_CONV_ERROR_MSG
+or
+.Dv SUDO_CONV_INFO_MSG ,
+try to write the message to the user's terminal.
+If the terminal is unavailable, the standard error or standard output
+will be used, depending upon whether
+.Dv SUDO_CONV_ERROR_MSG
+or
+.Dv SUDO_CONV_INFO_MSG
+was used.
+The user's terminal is always used when possible for input,
+this flag is only used for output.
+.El
+.Pp
+The
+.Fa timeout
+in seconds until the prompt will wait for no more input.
+A zero value implies an infinite timeout.
+.Pp
+The plugin is responsible for freeing the reply buffer located in each
+.Vt struct sudo_conv_reply ,
+if it is not
+.Dv NULL .
+.Dv SUDO_CONV_REPL_MAX
+represents the maximum length of the reply buffer (not including
+the trailing NUL character).
+In practical terms, this is the longest password
+.Nm sudo
+will support.
+.Pp
+The
+.Fn printf Ns -style
+function uses the same underlying mechanism as the
+.Fn conversation
+function but only supports
+.Dv SUDO_CONV_INFO_MSG
+and
+.Dv SUDO_CONV_ERROR_MSG
+for the
+.Fa msg_type
+parameter.
+It can be more convenient than using the
+.Fn conversation
+function if no user reply is needed and supports standard
+.Fn printf
+escape sequences.
+.Pp
+See the sample plugin for an example of the
+.Fn conversation
+function usage.
+.Ss Plugin invocation order
+As of
+.Nm sudo
+1.9.0, the plugin
+.Fn open
+and
+.Fn close
+functions are called in the
+following order:
+.Bl -enum
+.It
+audit open
+.It
+policy open
+.It
+approval open
+.It
+approval close
+.It
+I/O log open
+.It
+command runs
+.It
+command exits
+.It
+I/O log close
+.It
+policy close
+.It
+audit close
+.It
+sudo exits
+.El
+.Pp
+Prior to
+.Nm sudo
+1.9.0, the I/O log
+.Fn close
+function was called
+.Em after
+the policy
+.Fn close
+function.
+.Ss Sudoers group plugin API
+The
+.Nm sudoers
+plugin supports its own plugin interface to allow non-Unix
+group lookups.
+This can be used to query a group source other than the standard Unix
+group database.
+Two sample group plugins are bundled with
+.Nm sudo ,
+.Em group_file ,
+and
+.Em system_group ,
+are detailed in
+.Xr sudoers @mansectform@ .
+Third party group plugins include a QAS AD plugin available from Quest Software.
+.Pp
+A group plugin must declare and populate a
+.Vt struct sudoers_group_plugin
+in the global scope.
+This structure contains pointers to the functions that implement plugin
+initialization, cleanup, and group lookup.
+.Bd -literal
+struct sudoers_group_plugin {
+ unsigned int version;
+ int (*init)(int version, sudo_printf_t sudo_plugin_printf,
+ char *const argv[]);
+ void (*cleanup)(void);
+ int (*query)(const char *user, const char *group,
+ const struct passwd *pwd);
+};
+.Ed
+.Pp
+A
+.Vt struct sudoers_group_plugin
+has the following fields:
+.Bl -tag -width 4n
+.It Fa version
+The
+.Fa version
+field should be set to GROUP_API_VERSION.
+.Pp
+This allows
+.Nm sudoers
+to determine the API version the group plugin
+was built against.
+.It Fa init
+.Bd -literal -compact
+int (*init)(int version, sudo_printf_t sudo_plugin_printf,
+ char *const argv[]);
+.Ed
+.Pp
+The
+.Fn init
+function is called after
+.Em sudoers
+has been parsed but
+before any policy checks.
+It returns 1 on success, 0 on failure (or if the plugin is not configured),
+and \-1 if a error occurred.
+If an error occurs, the plugin may call the
+.Fn plugin_printf
+function with
+.Dv SUDO_CONF_ERROR_MSG
+to present additional error information to the user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa version
+The version passed in by
+.Nm sudoers
+allows the plugin to determine the
+major and minor version number of the group plugin API supported by
+.Nm sudoers .
+.It Fa plugin_printf
+A pointer to a
+.Fn printf Ns -style
+function that may be used to display informational or error message to the user.
+Returns the number of characters printed on success and \-1 on failure.
+.It Fa argv
+A
+.Dv NULL Ns -terminated
+array of arguments generated from the
+.Em group_plugin
+option in
+.Em sudoers .
+If no arguments were given,
+.Fa argv
+will be
+.Dv NULL .
+.El
+.It Fa cleanup
+.Bd -literal -compact
+void (*cleanup)();
+.Ed
+.Pp
+The
+.Fn cleanup
+function is called when
+.Nm sudoers
+has finished its
+group checks.
+The plugin should free any memory it has allocated and close open file handles.
+.It Fa query
+.Bd -literal -compact
+int (*query)(const char *user, const char *group,
+ const struct passwd *pwd);
+.Ed
+.Pp
+The
+.Fn query
+function is used to ask the group plugin whether
+.Fa user
+is a member of
+.Fa group .
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa user
+The name of the user being looked up in the external group database.
+.It Fa group
+The name of the group being queried.
+.It Fa pwd
+The password database entry for
+.Fa user ,
+if any.
+If
+.Fa user
+is not
+present in the password database,
+.Fa pwd
+will be
+.Dv NULL .
+.El
+.El
+.Pp
+.Em Group API Version Macros
+.Bd -literal
+/* Sudoers group plugin version major/minor */
+#define GROUP_API_VERSION_MAJOR 1
+#define GROUP_API_VERSION_MINOR 0
+#define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \e
+ GROUP_API_VERSION_MINOR)
+.Ed
+For getters and setters see the
+.Sx Policy plugin API .
+.Sh PLUGIN API CHANGELOG
+The following revisions have been made to the Sudo Plugin API.
+.Bl -tag -width 4n
+.It Version 1.0
+Initial API version.
+.It Version 1.1 (sudo 1.8.0)
+The I/O logging plugin's
+.Fn open
+function was modified to take the
+.Fa command_info
+list as an argument.
+.It Version 1.2 (sudo 1.8.5)
+The Policy and I/O logging plugins'
+.Fn open
+functions are now passed
+a list of plugin parameters if any are specified in
+.Xr sudo.conf @mansectform@ .
+.Pp
+A simple hooks API has been introduced to allow plugins to hook in to the
+system's environment handling functions.
+.Pp
+The
+.Fn init_session
+Policy plugin function is now passed a pointer
+to the user environment which can be updated as needed.
+This can be used to merge in environment variables stored in the PAM
+handle before a command is run.
+.It Version 1.3 (sudo 1.8.7)
+Support for the
+.Em exec_background
+entry has been added to the
+.Fa command_info
+list.
+.Pp
+The
+.Em max_groups
+and
+.Em plugin_dir
+entries were added to the
+.Fa settings
+list.
+.Pp
+The
+.Fn version
+and
+.Fn close
+functions are now optional.
+Previously, a missing
+.Fn version
+or
+.Fn close
+function would result in a crash.
+If no policy plugin
+.Fn close
+function is defined, a default
+.Fn close
+function will be provided by the
+.Nm sudo
+front-end that displays a warning if the command could not be
+executed.
+.Pp
+The
+.Nm sudo
+front-end now installs default signal handlers to trap common signals
+while the plugin functions are run.
+.It Version 1.4 (sudo 1.8.8)
+The
+.Em remote_host
+entry was added to the
+.Fa settings
+list.
+.It Version 1.5 (sudo 1.8.9)
+The
+.Em preserve_fds
+entry was added to the
+.Fa command_info
+list.
+.It Version 1.6 (sudo 1.8.11)
+The behavior when an I/O logging plugin returns an error
+.Pq \-1
+has changed.
+Previously, the
+.Nm sudo
+front-end took no action when the
+.Fn log_ttyin ,
+.Fn log_ttyout ,
+.Fn log_stdin ,
+.Fn log_stdout ,
+or
+.Fn log_stderr
+function returned an error.
+.Pp
+The behavior when an I/O logging plugin returns 0 has changed.
+Previously, output from the command would be displayed to the
+terminal even if an output logging function returned 0.
+.It Version 1.7 (sudo 1.8.12)
+The
+.Em plugin_path
+entry was added to the
+.Fa settings
+list.
+.Pp
+The
+.Em debug_flags
+entry now starts with a debug file path name and may occur multiple
+times if there are multiple plugin-specific Debug lines in the
+.Xr sudo.conf @mansectform@ file.
+.It Version 1.8 (sudo 1.8.15)
+The
+.Em sudoedit_checkdir
+and
+.Em sudoedit_follow
+entries were added to the
+.Fa command_info
+list.
+The default value of
+.Em sudoedit_checkdir
+was changed to true in sudo 1.8.16.
+.Pp
+The sudo
+.Fn conversation
+function now takes a pointer to a
+.Vt struct sudo_conv_callback
+as its fourth argument.
+The
+.Vt sudo_conv_t
+definition has been updated to match.
+The plugin must specify that it supports plugin API version 1.8 or higher
+to receive a conversation function pointer that supports this argument.
+.It Version 1.9 (sudo 1.8.16)
+The
+.Em execfd
+entry was added to the
+.Fa command_info
+list.
+.It Version 1.10 (sudo 1.8.19)
+The
+.Em umask
+entry was added to the
+.Fa user_info
+list.
+The
+.Em iolog_group ,
+.Em iolog_mode ,
+and
+.Em iolog_user
+entries were added to the
+.Fa command_info
+list.
+.It Version 1.11 (sudo 1.8.20)
+The
+.Em timeout
+entry was added to the
+.Fa settings
+list.
+.It Version 1.12 (sudo 1.8.21)
+The
+.Fn change_winsize
+function was added to
+.Vt struct io_plugin .
+.It Version 1.13 (sudo 1.8.26)
+The
+.Fn log_suspend
+function was added to
+.Vt struct io_plugin .
+.It Version 1.14 (sudo 1.8.29)
+The
+.Em umask_override
+entry was added to the
+.Fa command_info
+list.
+.It Version 1.15 (sudo 1.9.0)
+The
+.Em cwd_optional
+entry was added to the
+.Fa command_info
+list.
+.Pp
+The
+.Fn event_alloc
+function was added to
+.Vt struct policy_plugin
+and
+.Vt struct io_plugin .
+.Pp
+The
+.Fa errstr
+argument was added to the policy and I/O plugin functions
+which the plugin function can use to return an error string.
+This string may be used by the audit plugin to report failure or
+error conditions set by the other plugins.
+.Pp
+The
+.Fn close
+function is now is called regardless of whether or not a command
+was actually executed.
+This makes it possible for plugins to perform cleanup even when a
+command was not run.
+.Pp
+.Dv SUDO_CONV_REPL_MAX
+has increased from 255 to 1023 bytes.
+.Pp
+Support for audit and approval plugins was added.
+.It Version 1.16 (sudo 1.9.3)
+Initial resource limit values were added to the
+.Fa user_info
+list.
+.Pp
+The
+.Em cmnd_chroot
+and
+.Em cmnd_cwd
+entries were added to the
+.Fa settings
+list.
+.It Version 1.17 (sudo 1.9.4)
+The
+.Fn event_alloc
+function was added to
+.Vt struct audit_plugin
+and
+.Vt struct approval_plugin .
+.It Version 1.18 (sudo 1.9.9)
+The policy may now set resource limit values in the
+.Fa command_info
+list.
+The
+.Em intercept
+and
+.Em log_subcmds
+entries were added to the
+.Fa command_info
+list.
+.It Version 1.19 (sudo 1.9.11)
+The
+.Em intercept_ptrace
+and
+.Em intercept_setid
+entries were added to the
+.Fa settings
+list.
+The
+.Em apparmor_profile
+and
+.Em use_ptrace
+entries were added to the
+.Fa command_info
+list.
+.It Version 1.20 (sudo 1.9.12)
+The
+.Em update_ticket
+entry was added to the
+.Fa settings
+list.
+The
+.Em intercept_verify
+entry was added to the
+.Fa command_info
+list.
+.It Version 1.21 (sudo 1.9.13)
+The
+.Em sudoedit_nfiles
+entry was added to the
+.Fa command_info
+list.
+.El
+.Sh SEE ALSO
+.Xr sudo.conf @mansectform@ ,
+.Xr sudoers @mansectform@ ,
+.Xr sudo @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS.md file in the
+.Nm sudo
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you believe you have found a bug in
+.Nm sudo ,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm sudo
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+.Nm sudo
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudo_plugin_python.man.in b/docs/sudo_plugin_python.man.in
new file mode 100644
index 0000000..e77e96c
--- /dev/null
+++ b/docs/sudo_plugin_python.man.in
@@ -0,0 +1,1905 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2021 Robert Manner <robert.manner@oneidentity.com>
+.\" Copyright (c) 2019-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.TH "SUDO_PLUGIN_PYTHON" "5" "January 16, 2023" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudo_plugin_python\fR
+\- Sudo Plugin API (Python)
+.SH "DESCRIPTION"
+Starting with version 1.9,
+\fBsudo\fR
+plugins can be written in python.
+The API closely follows the C
+\fBsudo\fR
+plugin API described by
+sudo_plugin(@mansectform@).
+.PP
+The supported plugins types are:
+.PP
+.RS 1n
+.PD 0
+.TP 3n
+\fB\(bu\fR
+Policy plugin
+.TP 3n
+\fB\(bu\fR
+I/O plugin
+.TP 3n
+\fB\(bu\fR
+Audit plugin
+.TP 3n
+\fB\(bu\fR
+Approval plugin
+.TP 3n
+\fB\(bu\fR
+Group provider plugin
+.RE
+.PD
+.PP
+Python plugin support needs to be explicitly enabled at build time
+with the configure option
+\(lq--enable-python\(rq.
+Python version 3.0 or higher is required.
+.SS "Sudo Python Plugin Base"
+A plugin written in Python should be a class in a python file that
+inherits from
+\fIsudo.Plugin\fR.
+The
+\fIsudo.Plugin\fR
+base class has no real purpose other than to identify this class as a plugin.
+.PP
+The only implemented method is a constructor, which stores the
+keyword arguments it receives as fields (member variables) in the object.
+This is intended as a convenience to allow you to avoid writing the
+constructor yourself.
+.PP
+For example:
+.nf
+.sp
+.RS 4n
+import sudo
+
+class MySudoPlugin(sudo.Plugin):
+ # example constructor (optional)
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ # example destructor (optional)
+ def __del__(self):
+ pass
+.RE
+.fi
+.PP
+Both the constructor and destructor are optional and can be omitted.
+.PP
+The customized Plugin class should define a few plugin-specific methods.
+When the plugin loads,
+\fBsudo\fR
+will create an instance of this class and call the methods.
+The actual methods required depend on the type of the plugin,
+but most return an
+\fIint\fR
+result code, as documented in
+sudo_plugin(@mansectform@),
+that indicates whether or not the method was successful.
+The Python sudo module defines the following constants to improve readability:
+.RS 4n
+.TS
+l l.
+.PP
+\fBDefine\fR \fBValue\fR
+.PP
+\fRsudo.RC.OK\fR 1
+.PP
+\fRsudo.RC.ACCEPT\fR 1
+.PP
+\fRsudo.RC.REJECT\fR 0
+.PP
+\fRsudo.RC.ERROR\fR \-1
+.PP
+\fRsudo.RC.USAGE_ERROR\fR \-2
+.TE
+.RE
+.PP
+If a function returns
+\fRNone\fR
+(for example, if it does not call return),
+it will be considered to have returned
+\fRsudo.RC.OK\fR.
+If an exception is raised (other than sudo.PluginException), the
+backtrace will be shown to the user and the plugin function will return
+\fRsudo.RC.ERROR\fR.
+If that is not acceptable, you must catch the exception and handle it yourself.
+.PP
+Instead of just returning
+\fRsudo.RC.ERROR\fR
+or
+\fRsudo.RC.REJECT\fR
+result code the plugin can also provide a message describing the problem.
+This can be done by raising one of the special exceptions:
+.nf
+.sp
+.RS 4n
+raise sudo.PluginError("Message")
+raise sudo.PluginReject("Message")
+.RE
+.fi
+.PP
+This added message will be used by the audit plugins.
+Both exceptions inherit from
+\fRsudo.PluginException\fR
+.SS "Python Plugin Loader"
+Running the Python interpreter and bridging between C and Python is
+handled by the
+\fBsudo\fR
+plugin
+\fI@python_plugin@\fR.
+This shared object can be loaded like any other dynamic
+\fBsudo\fR
+plugin and should receive the path and the class name of the Python
+plugin it is loading as arguments.
+.PP
+Example usage in
+sudo.conf(@mansectform@):
+.nf
+.sp
+.RS 4n
+Plugin python_policy @python_plugin@ ModulePath=<path> ClassName=<class>
+Plugin python_io @python_plugin@ ModulePath=<path> ClassName=<class>
+Plugin python_audit @python_plugin@ ModulePath=<path> ClassName=<class>
+Plugin python_approval @python_plugin@ ModulePath=<path> ClassName=<class>
+.RE
+.fi
+.PP
+Example group provider plugin usage in the
+\fIsudoers\fR
+file:
+.nf
+.sp
+.RS 4n
+Defaults group_plugin="@python_plugin@ ModulePath=<path> ClassName=<class>"
+.RE
+.fi
+.PP
+The plugin arguments are as follows:
+.TP 6n
+ModulePath
+The path of a python file which contains the class of the sudo Python plugin.
+It must be either an absolute path or a path relative to the sudo Python plugin
+directory,
+\fI@plugindir@/python\fR.
+The parent directory of
+\fIModulePath\fR
+will be appended to Python's module search path (there is currently no
+way to force Python to load a module from a fully-qualified path).
+It is good practice to use a prefix for the module file that is unlikely
+to conflict with other installed Python modules, for example,
+\fIsudo_policy.py\fR.
+Otherwise, if the there is an installed Python module with the same
+file name as the sudo Python plugin file (without the directory),
+the wrong file will be loaded.
+.TP 6n
+ClassName
+(Optional.) The name of the class implementing the sudo Python plugin.
+If not supplied, the one and only sudo.Plugin that is present in the module
+will be used.
+If there are multiple such plugins in the module (or none), it
+will result in an error.
+.SS "Policy plugin API"
+Policy plugins must be registered in
+sudo.conf(@mansectform@).
+For example:
+.nf
+.sp
+.RS 4n
+Plugin python_policy @python_plugin@ ModulePath=<path> ClassName=<class>
+.RE
+.fi
+.PP
+Currently, only a single policy plugin may be specified in
+sudo.conf(@mansectform@).
+.PP
+A policy plugin may have the following member functions:
+.TP 6n
+\fIconstructor\fR
+.nf
+.RS 6n
+__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
+ version: str, user_info: Tuple[str, ...],
+ plugin_options: Tuple[str, ...])
+.RE
+.fi
+.RS 6n
+.sp
+Implementing this function is optional.
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.sp
+The constructor matches the
+\fBopen\fR()
+function in the C
+\fBsudo\fR
+plugin API.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIuser_env\fR
+The user's environment as a tuple of strings in
+\(lqkey=value\(rq
+format.
+.TP 6n
+\fIsettings\fR
+A tuple of user-supplied
+\fIsudo\fR
+settings in the form of
+\(lqkey=value\(rq
+strings.
+.TP 6n
+\fIversion\fR
+The version of the Python Policy Plugin API.
+.TP 6n
+\fIuser_info\fR
+A tuple of information about the user running the command in the form of
+\(lqkey=value\(rq
+strings.
+.TP 6n
+\fIplugin_options\fR
+The plugin options passed as arguments in the
+sudo.conf(@mansectform@)
+plugin registration.
+This is a tuple of strings, usually (but not necessarily) in
+\(lqkey=value\(rq
+format.
+.PP
+The
+\fBsudo.options_as_dict\fR()
+convenience function can be used to convert
+\(lqkey=value\(rq
+pairs to a dictionary.
+For a list of recognized keys and their supported values,
+see the policy plugin
+\fBopen\fR()
+documentation in
+sudo_plugin(@mansectform@).
+.RE
+.TP 6n
+\fIcheck_policy\fR
+.nf
+.RS 6n
+check_policy(self, argv: Tuple[str, ...], env_add: Tuple[str, ...])
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBcheck_policy\fR()
+function is called by
+\fBsudo\fR
+to determine whether the user is allowed to run the specified command.
+Implementing this function is mandatory for a policy plugin.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIargv\fR
+A tuple describing the command the user wishes to run.
+.TP 6n
+\fIenv_add\fR
+Additional environment variables specified by the user on the command line in
+the form of a tuple of
+\(lqkey=value\(rq
+pairs.
+The
+\fBsudo.options_as_dict\fR()
+convenience function can be used to convert them to a dictionary.
+.PP
+This function should return a result code or a tuple in the following format:
+.nf
+.sp
+.RS 10n
+return (rc, command_info_out, argv_out, user_env_out)
+.RE
+.fi
+.sp
+The tuple values are as follows:
+.TP 6n
+\fIrc\fR
+The result of the policy check, one of the
+\fRsudo.RC.*\fR
+constants.
+\fRsudo.RC.ACCEPT\fR
+if the command is allowed,
+\fRsudo.RC.REJECT\fR
+if not allowed,
+\fRsudo.RC.ERROR\fR
+for a general error, or
+\fRsudo.RC.USAGE_ERROR\fR
+for a usage error.
+.TP 6n
+\fIcommand_info_out\fR
+Optional (only required when the command is accepted).
+Information about the command being run in the form of
+\(lqkey=value\(rq
+strings.
+.sp
+To accept a command, at the very minimum the plugin must set in the
+\fIcommand\fR,
+\fIrunas_uid\fR,
+and
+\fIrunas_gid\fR
+keys.
+.sp
+For a list of recognized keys and supported values,
+see the
+\fBcheck_policy\fR()
+documentation in
+sudo_plugin(@mansectform@).
+.TP 6n
+\fIargv_out\fR
+Optional (only required when the command is accepted).
+The arguments to pass to the
+execve(2)
+system call when executing the command.
+.TP 6n
+\fIuser_env_out\fR
+Optional (only required when the command is accepted).
+The environment to use when executing the command in the form of a
+tuple of strings in
+\(lqkey=value\(rq
+format.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIinit_session\fR
+.nf
+.RS 6n
+init_session(self, user_pwd: Tuple, user_env: Tuple[str, ...])
+.RE
+.fi
+.RS 6n
+.sp
+Perform session setup (optional).
+The
+\fBinit_session\fR()
+function is called before
+\fBsudo\fR
+sets up the
+execution environment for the command before any user-ID or group-ID changes.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIuser_pwd\fR
+A tuple describing the user's passwd entry.
+Convertible to
+\fIpwd.struct_passwd or\fR
+\fRNone\fR
+if the user is not present in the password database.
+.sp
+Example conversion:
+.nf
+.RS 12n
+user_pwd = pwd.struct_passwd(user_pwd) if user_pwd else None
+.RE
+.fi
+.TP 6n
+\fIuser_env\fR
+The environment the command will run in.
+This is a tuple of strings in
+\(lqkey=value\(rq
+format.
+.PP
+This function should return a result code or a tuple in the following format:
+.nf
+.sp
+.RS 10n
+return (rc, user_env_out)
+.RE
+.fi
+.sp
+The tuple values are as follows:
+.TP 6n
+\fIrc\fR
+The result of the session init, one of the
+\fRsudo.RC.*\fR
+constants.
+\fRsudo.RC.OK\fR
+on success, 0 on failure, or
+\fRsudo.RC.ERROR\fR
+if an error occurred.
+.TP 6n
+\fIuser_env_out\fR
+Optional.
+If the
+\fBinit_session\fR()
+function needs to modify the user environment, it can return the new
+environment in
+\fIuser_env_out\fR.
+If this is omitted, no changes will be made to
+\fIuser_env\fR.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIlist\fR
+.nf
+.RS 6n
+list(self, argv: Tuple[str, ...], is_verbose: int, user: str)
+.RE
+.fi
+.RS 6n
+.sp
+List available privileges for the invoking user.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIargv\fR
+If not set to
+\fRNone\fR,
+an argument vector describing a command the user wishes to check
+against the policy.
+.TP 6n
+\fIis_verbose\fR
+Flag indicating whether to list in verbose mode or not.
+.TP 6n
+\fIuser\fR
+The name of a different user to list privileges for if the policy allows it.
+If
+\fRNone\fR,
+the plugin should list the privileges of the invoking user.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIvalidate\fR
+.nf
+.RS 6n
+validate(self)
+.RE
+.fi
+.RS 6n
+.sp
+For policy plugins that cache authentication credentials, this function is used to validate and cache the credentials (optional).
+.RE
+.TP 6n
+\fIinvalidate\fR
+.nf
+.RS 6n
+invalidate(self, remove: int)
+.RE
+.fi
+.RS 6n
+.sp
+For policy plugins that cache authentication credentials, this function is used to invalidate the credentials (optional).
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIremove\fR
+If this flag is set, the plugin may remove the credentials instead of simply
+invalidating them.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIshow_version\fR
+.nf
+.RS 6n
+show_version(self, is_verbose: int)
+.RE
+.fi
+.RS 6n
+.sp
+Display the plugin version information to the user.
+The
+\fBsudo.log_info\fR()
+function should be used.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIis_verbose\fR
+A flag to indicate displaying more verbose information.
+Currently this is 1 if
+\(oqsudo -V\(cq
+is run as the root user.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIclose\fR
+.br
+.nf
+.RS 6n
+close(self, exit_status: int, error: int)
+.RE
+.fi
+.RS 6n
+.sp
+Called when a command finishes executing.
+.sp
+Works the same as the
+\fBclose\fR()
+function in the C
+\fBsudo\fR
+plugin API, except that it only gets called if
+\fBsudo\fR
+attempts to execute the command.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIexit_status\fR
+The exit status of the command if was executed, otherwise \-1.
+.TP 6n
+\fIerror\fR
+.br
+If the command could not be executed, this is set to the value of
+errno set by the
+execve(2)
+system call, otherwise 0.
+.PD 0
+.PP
+.RE
+.PD
+.SS "Policy plugin example"
+Sudo ships with an example Python policy plugin.
+To try it, register it by adding the following lines to
+\fI@sysconfdir@/sudo.conf\fR:
+.nf
+.sp
+.RS 0n
+Plugin python_policy @python_plugin@ \e
+ ModulePath=@EXAMPLES@/example_policy_plugin.py \e
+ ClassName=SudoPolicyPlugin
+.RE
+.fi
+.PP
+Only one policy plugin can be enabled at a time so you must disable
+any other policy plugin listed in
+\fI@sysconfdir@/sudo.conf\fR,
+such as
+sudoers(@mansectform@).
+.SS "I/O plugin API"
+I/O plugins must be registered in
+sudo.conf(@mansectform@).
+For example:
+.nf
+.sp
+.RS 4n
+Plugin python_io @python_plugin@ ModulePath=<path> ClassName=<class>
+.RE
+.fi
+.PP
+Sudo supports loading multiple I/O plugins.
+Currently only 8 python I/O plugins can be loaded at once.
+.PP
+An I/O plugin may have the following member functions:
+.TP 6n
+\fIconstructor\fR
+.nf
+.RS 6n
+__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
+ version: str, user_info: Tuple[str, ...],
+ plugin_options: Tuple[str, ...])
+.RE
+.fi
+.RS 6n
+.sp
+Implementing this function is optional.
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.sp
+The constructor matches the
+\fBopen\fR()
+function in the C
+\fBsudo\fR
+plugin API.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIuser_env\fR
+The user's environment as a tuple of strings in
+\(lqkey=value\(rq
+format.
+.TP 6n
+\fIsettings\fR
+A tuple of user-supplied
+\fIsudo\fR
+settings in the form of
+\(lqkey=value\(rq
+strings.
+.TP 6n
+\fIversion\fR
+The version of the Python I/O Plugin API.
+.TP 6n
+\fIuser_info\fR
+A tuple of information about the user running the command in the form of
+\(lqkey=value\(rq
+strings.
+.TP 6n
+\fIplugin_options\fR
+The plugin options passed as arguments in the
+sudo.conf(@mansectform@)
+plugin registration.
+This is a tuple of strings, usually (but not necessarily) in
+\(lqkey=value\(rq
+format.
+.PP
+The
+\fBsudo.options_as_dict\fR()
+convenience function can be used to convert
+\(lqkey=value\(rq
+pairs to a dictionary.
+For a list of recognized keys and their supported values,
+see the I/O plugin
+\fBopen\fR()
+documentation in
+sudo_plugin(@mansectform@).
+.RE
+.TP 6n
+\fIopen\fR
+.nf
+.RS 6n
+open(self, argv: Tuple[str, ...],
+ command_info: Tuple[str, ...]) -> int
+.RE
+.fi
+.RS 6n
+.sp
+Receives the command the user wishes to run.
+.sp
+Works the same as the
+\fBopen\fR()
+function in the C
+\fBsudo\fR
+plugin API except that:
+.sp
+.RS 7n
+.PD 0
+.TP 3n
+\fB\(bu\fR
+It only gets called when there is a command to be executed
+(and not for a version query for example).
+.TP 3n
+\fB\(bu\fR
+Other arguments of the C API
+\fBopen\fR()
+function are received through the constructor.
+.RE
+.sp
+The function arguments are as follows:
+.PD
+.TP 6n
+\fIargv\fR
+A tuple of the arguments describing the command the user wishes to run.
+.TP 6n
+\fIcommand_info\fR
+Information about the command being run in the form of
+\(lqkey=value\(rq
+strings.
+.PP
+The
+\fBsudo.options_as_dict\fR()
+convenience function can be used to convert
+\(lqkey=value\(rq
+pairs to a dictionary.
+For a list of recognized keys and their supported values,
+see the I/O plugin
+\fBopen\fR()
+documentation in
+sudo_plugin(@mansectform@).
+.sp
+The
+\fBopen\fR()
+function should return a result code, one of the
+\fRsudo.RC.*\fR
+constants.
+If the function returns
+\fRsudo.RC.REJECT\fR,
+no I/O will be sent to the plugin.
+.RE
+.TP 6n
+\fIlog_ttyin\fR, \fIlog_ttyout\fR, \fIlog_stdin\fR, \fIlog_stdout\fR, \fIlog_stderr\fR
+.nf
+.RS 6n
+log_ttyin(self, buf: str) -> int
+log_ttyout(self, buf: str) -> int
+log_stdin(self, buf: str) -> int
+log_stdout(self, buf: str) -> int
+log_stderr(self, buf: str) -> int
+.RE
+.fi
+.RS 6n
+.sp
+Receive the user input or output of the terminal device and
+application standard input, standard output, or standard error.
+See the matching calls in
+sudo_plugin(@mansectform@).
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIbuf\fR
+The input (or output) buffer in the form of a string.
+.PP
+The function should return a result code, one of the
+\fRsudo.RC.*\fR
+constants.
+.sp
+If
+\fRsudo.RC.ERROR\fR
+is returned, the running command will be terminated and all of the
+plugin's logging functions will be disabled.
+Other I/O logging plugins will still receive any remaining
+input or output that has not yet been processed.
+.sp
+If an input logging function rejects the data by returning
+\fRsudo.RC.REJECT\fR,
+the command will be terminated and the data will not be passed to the
+command, though it will still be sent to any other I/O logging plugins.
+If an output logging function rejects the data by returning
+\fRsudo.RC.REJECT\fR,
+the command will be terminated and the data will not be written to the
+terminal, though it will still be sent to any other I/O logging plugins.
+.RE
+.TP 6n
+\fIchange_winsize\fR
+.nf
+.RS 6n
+change_winsize(self, line: int, cols: int) -> int
+.RE
+.fi
+.RS 6n
+.sp
+Called whenever the window size of the terminal changes.
+The function arguments are as follows:
+.TP 6n
+\fIline\fR
+The number of lines of the terminal.
+.TP 6n
+\fIcols\fR
+The number of columns of the terminal.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIlog_suspend\fR
+.nf
+.RS 6n
+log_suspend(self, signo: int) -> int
+.RE
+.fi
+.RS 6n
+Called whenever a command is suspended or resumed.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIsigno\fR
+.br
+The number of the signal that caused the command to be suspended or
+\fRSIGCONT\fR
+if the command was resumed.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIshow_version\fR
+.nf
+.RS 6n
+show_version(self, is_verbose: int)
+.RE
+.fi
+.RS 6n
+Display the plugin version information to the user.
+The
+\fBsudo.log_info\fR()
+function should be used.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIis_verbose\fR
+A flag to indicate displaying more verbose information.
+Currently this is 1 if
+\(oqsudo -V\(cq
+is run as the root user.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIclose\fR
+.br
+.nf
+.RS 6n
+close(self, exit_status: int, error: int) -> None
+.RE
+.fi
+.RS 6n
+Called when a command finishes execution.
+.sp
+Works the same as the
+\fBclose\fR()
+function in the C
+\fBsudo\fR
+plugin API, except that it only gets called if
+\fBsudo\fR
+attempts to execute the command.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIexit_status\fR
+The exit status of the command if was executed, otherwise \-1.
+.TP 6n
+\fIerror\fR
+.br
+If the command could not be executed, this is set to the value of
+errno set by the
+execve(2)
+system call, otherwise 0.
+.PD 0
+.PP
+.RE
+.PD
+.SS "I/O plugin example"
+Sudo ships with a Python I/O plugin example.
+To try it, register it by adding the following lines to
+\fI@sysconfdir@/sudo.conf\fR:
+.nf
+.sp
+.RS 4n
+Plugin python_io @python_plugin@ \e
+ ModulePath=@EXAMPLES@/example_io_plugin.py \e
+ ClassName=SudoIOPlugin
+.RE
+.fi
+.SS "Audit plugin API"
+Audit plugins must be registered in
+sudo.conf(@mansectform@).
+For example:
+.nf
+.sp
+.RS 4n
+Plugin python_audit @python_plugin@ ModulePath=<path> ClassName=<class>
+.RE
+.fi
+.PP
+Sudo supports loading multiple audit plugins.
+Currently only 8 python audit plugins can be loaded at once.
+.PP
+An audit plugin may have the following member functions (all of which are optional):
+.TP 6n
+\fIconstructor\fR
+.nf
+.RS 6n
+__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
+ version: str, user_info: Tuple[str, ...], plugin_options: Tuple[str, ...])
+.RE
+.fi
+.RS 6n
+.sp
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.sp
+The constructor matches the
+\fBopen\fR()
+function in the C
+\fBsudo\fR
+plugin API.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIuser_env\fR
+The user's environment as a tuple of strings in
+\(lqkey=value\(rq
+format.
+.TP 6n
+\fIsettings\fR
+A tuple of user-supplied
+\fIsudo\fR
+settings in the form of
+\(lqkey=value\(rq
+strings.
+.TP 6n
+\fIversion\fR
+The version of the Python Audit Plugin API.
+.TP 6n
+\fIuser_info\fR
+A tuple of information about the user running the command in the form of
+\(lqkey=value\(rq
+strings.
+.TP 6n
+\fIplugin_options\fR
+The plugin options passed as arguments in the
+sudo.conf(@mansectform@)
+plugin registration.
+This is a tuple of strings, usually (but not necessarily) in
+\(lqkey=value\(rq
+format.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIopen\fR
+.nf
+.RS 6n
+open(self, submit_optind: int,
+ submit_argv: Tuple[str, ...]) -> int
+.RE
+.fi
+.RS 6n
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIsubmit_optind\fR
+The index into
+\fIsubmit_argv\fR
+that corresponds to the first entry that is not a command line option.
+.TP 6n
+\fIsubmit_argv\fR
+The argument vector sudo was invoked with, including all command line options.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIclose\fR
+.br
+.nf
+.RS 6n
+close(self, status_type: int, status: int) -> None
+.RE
+.fi
+.RS 6n
+.sp
+Called when sudo is finished, shortly before it exits.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIstatus_type\fR
+The type of status being passed.
+One of the
+\fRsudo.EXIT_REASON.*\fR
+constants.
+.TP 6n
+\fIstatus\fR
+Depending on the value of
+\fIstatus_type\fR,
+this value is either
+ignored, the command's exit status as returned by the
+wait(2)
+system call, the value of
+\fIerrno\fR
+set by the
+execve(2)
+system call, or the value of
+\fIerrno\fR
+resulting from an error in the
+\fBsudo\fR
+front-end.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIshow_version\fR
+.nf
+.RS 6n
+show_version(self, is_verbose: int) -> int
+.RE
+.fi
+.RS 6n
+.sp
+Display the plugin version information to the user.
+The
+\fBsudo.log_info\fR()
+function should be used.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIis_verbose\fR
+A flag to indicate displaying more verbose information.
+Currently this is 1 if
+\(oqsudo -V\(cq
+is run as the root user.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIaccept\fR
+.nf
+.RS 6n
+accept(self, plugin_name: str, plugin_type: int, command_info: Tuple[str, ...],
+ run_argv: Tuple[str, ...], run_envp: Tuple[str, ...]) -> int
+.RE
+.fi
+.RS 6n
+.sp
+This function is called when a command or action is accepted by a policy
+or approval plugin.
+The function arguments are as follows:
+.TP 6n
+plugin_name
+The name of the plugin that accepted the command or
+\(lqsudo\(rq
+for the
+\fBsudo\fR
+front-end.
+.TP 6n
+plugin_type
+The type of plugin that accepted the command, currently either
+\fRsudo.PLUGIN_TYPE.POLICY\fR,
+\fRsudo.PLUGIN_TYPE.APPROVAL\fR,
+or
+\fRsudo.PLUGIN_TYPE.SUDO\fR.
+The
+\fBaccept\fR()
+function is called multiple times--once for each policy or approval
+plugin that succeeds and once for the sudo front-end.
+When called on behalf of the sudo front-end,
+\fIcommand_info\fR
+may include information from an I/O logging plugin as well.
+.sp
+Typically, an audit plugin is interested in either the accept status from
+the
+\fBsudo\fR
+front-end or from the various policy and approval plugins, but not both.
+It is possible for the policy plugin to accept a command that is
+later rejected by an approval plugin, in which case the audit
+plugin's
+\fBaccept\fR()
+and
+\fBreject\fR()
+functions will
+\fIboth\fR
+be called.
+.TP 6n
+command_info
+A vector of information describing the command being run.
+See the
+sudo_plugin(@mansectform@)
+manual for possible values.
+.TP 6n
+run_argv
+Argument vector describing a command that will be run.
+.TP 6n
+run_envp
+The environment the command will be run with.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIreject\fR
+.nf
+.RS 6n
+reject(self, plugin_name: str, plugin_type: int, audit_msg: str,
+ command_info: Tuple[str, ...]) -> int
+.RE
+.fi
+.RS 6n
+.sp
+This function is called when a command or action is rejected by the policy
+plugin.
+The function arguments are as follows:
+.TP 6n
+plugin_name
+The name of the plugin that rejected the command.
+.TP 6n
+plugin_type
+The type of plugin that rejected the command, currently either
+\fRsudo.PLUGIN_TYPE.POLICY\fR,
+\fRsudo.PLUGIN_TYPE.APPROVAL\fR,
+or
+\fRsudo.PLUGIN_TYPE.IO\fR.
+.sp
+Unlike the
+\fBaccept\fR()
+function, the
+\fBreject\fR()
+function is not called on behalf of the
+\fBsudo\fR
+front-end.
+.TP 6n
+audit_msg
+An optional string describing the reason the command was rejected by the plugin.
+If the plugin did not provide a reason, audit_msg will be
+\fRNone\fR.
+.TP 6n
+command_info
+A vector of information describing the rejected command.
+See the
+sudo_plugin(@mansectform@)
+manual for possible values.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIerror\fR
+.br
+.nf
+.RS 6n
+error(self, plugin_name: str, plugin_type: int, audit_msg: str,
+ command_info: Tuple[str, ...]) -> int
+.RE
+.fi
+.RS 6n
+.sp
+This function is called when a plugin or the
+\fBsudo\fR
+front-end returns an error.
+The function arguments are as follows:
+.TP 6n
+plugin_name
+The name of the plugin that generated the error or
+\(lqsudo\(rq
+for the
+\fBsudo\fR
+front-end.
+.TP 6n
+plugin_type
+The type of plugin that generated the error, or
+\fRSUDO_FRONT_END\fR
+for the
+\fBsudo\fR
+front-end.
+.TP 6n
+audit_msg
+An optional string describing the plugin error.
+If the plugin did not provide a description, it will be
+\fRNone\fR.
+.TP 6n
+command_info
+A vector of information describing the command.
+See the
+sudo_plugin(@mansectform@)
+manual for possible values.
+.PD 0
+.PP
+.RE
+.PD
+.SS "Audit plugin example"
+Sudo ships with a Python Audit plugin example.
+To try it, register it by adding the following lines to
+\fI@sysconfdir@/sudo.conf\fR:
+.nf
+.sp
+.RS 4n
+Plugin python_audit @python_plugin@ \e
+ ModulePath=@EXAMPLES@/example_audit_plugin.py \e
+ ClassName=SudoAuditPlugin
+.RE
+.fi
+.PP
+It will log the plugin accept / reject / error results to the output.
+.SS "Approval plugin API"
+Approval plugins must be registered in
+sudo.conf(@mansectform@).
+For example:
+.nf
+.sp
+.RS 4n
+Plugin python_approval @python_plugin@ ModulePath=<path> ClassName=<class>
+.RE
+.fi
+.PP
+Sudo supports loading multiple approval plugins.
+Currently only 8 python approval plugins can be loaded at once.
+.PP
+An approval plugin may have the following member functions:
+.TP 6n
+\fIconstructor\fR
+.nf
+.RS 6n
+__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
+ version: str, user_info: Tuple[str, ...], plugin_options: Tuple[str, ...],
+ submit_optind: int, submit_argv: Tuple[str, ...])
+.RE
+.fi
+.RS 6n
+.sp
+Optional.
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.sp
+The constructor matches the
+\fBopen\fR()
+function in the C
+\fBsudo\fR
+plugin API.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIuser_env\fR
+The user's environment as a tuple of strings in
+\(lqkey=value\(rq
+format.
+.TP 6n
+\fIsettings\fR
+A tuple of user-supplied
+\fIsudo\fR
+settings in the form of
+\(lqkey=value\(rq
+strings.
+.TP 6n
+\fIversion\fR
+The version of the Python Approval Plugin API.
+.TP 6n
+\fIuser_info\fR
+A tuple of information about the user running the command in the form of
+\(lqkey=value\(rq
+strings.
+.TP 6n
+\fIplugin_options\fR
+The plugin options passed as arguments in the
+sudo.conf(@mansectform@)
+plugin registration.
+This is a tuple of strings, usually (but not necessarily) in
+\(lqkey=value\(rq
+format.
+.TP 6n
+\fIsubmit_optind\fR
+The index into
+\fIsubmit_argv\fR
+that corresponds to the first entry that is not a command line option.
+.TP 6n
+\fIsubmit_argv\fR
+The argument vector sudo was invoked with, including all command line options.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIshow_version\fR
+.nf
+.RS 6n
+show_version(self, is_verbose: int) -> int
+.RE
+.fi
+.RS 6n
+.sp
+Display the version.
+(Same as for all the other plugins.)
+.RE
+.TP 6n
+\fIcheck\fR
+.br
+.nf
+.RS 6n
+check(self, command_info: Tuple[str, ...], run_argv: Tuple[str, ...],
+ run_env: Tuple[str, ...]) -> int
+.RE
+.fi
+.RS 6n
+.sp
+This function is called after policy plugin's check_policy has succeeded.
+It can reject execution of the command by returning sudo.RC.REJECT or
+raising the special exception:
+.nf
+.sp
+.RS 10n
+raise sudo.PluginReject("some message")
+.RE
+.fi
+.sp
+with the message describing the problem.
+In the latter case, the audit plugins will get the description.
+.sp
+The function arguments are as follows:
+.TP 6n
+command_info
+A vector of information describing the command that will run.
+See the
+sudo_plugin(@mansectform@)
+manual for possible values.
+.TP 6n
+run_argv
+Argument vector describing a command that will be run.
+.TP 6n
+run_env
+The environment the command will be run with.
+.PD 0
+.PP
+.RE
+.PD
+.SS "Approval plugin example"
+Sudo ships with a Python Approval plugin example.
+To try it, register it by adding the following lines to
+\fI@sysconfdir@/sudo.conf\fR:
+.nf
+.sp
+.RS 4n
+Plugin python_approval @python_plugin@ \e
+ ModulePath=@EXAMPLES@/example_approval_plugin.py \e
+ ClassName=BusinessHoursApprovalPlugin
+.RE
+.fi
+.PP
+It will only allow execution of commands in the "business hours" (from Monday
+to Friday between 8:00 and 17:59:59).
+.SS "Sudoers group provider plugin API"
+A group provider plugin is registered in the
+sudoers(@mansectform@)
+file.
+For example:
+.nf
+.sp
+.RS 4n
+Defaults group_plugin="@python_plugin@ ModulePath=<path> ClassName=<class>"
+.RE
+.fi
+.PP
+Currently, only a single group plugin can be registered in
+\fIsudoers\fR.
+.PP
+A group provider plugin may have the following member functions:
+.TP 6n
+\fIconstructor\fR
+.nf
+.RS 6n
+__init__(self, args: Tuple[str, ...], version: str)
+.RE
+.fi
+.RS 6n
+.sp
+Implementing this function is optional.
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIargs\fR
+The plugin options passed as arguments in the
+\fIsudoers\fR
+file plugin registration.
+All the arguments are free form strings (not necessarily in
+\(lqkey=value\(rq
+format).
+.TP 6n
+\fIversion\fR
+The version of the Python Group Plugin API.
+.PD 0
+.PP
+.RE
+.PD
+.TP 6n
+\fIquery\fR
+.br
+.nf
+.RS 6n
+query(self, user: str, group: str, user_pwd: Tuple)
+.RE
+.fi
+.RS 6n
+.sp
+The
+\fBquery\fR()
+function is used to ask the group plugin whether
+\fIuser\fR
+is a member of
+\fIgroup\fR.
+This method is required.
+.RE
+.PP
+The function arguments are as follows:
+.TP 6n
+\fIuser\fR
+The name of the user being looked up in the external group database.
+.TP 6n
+\fIgroup\fR
+.br
+The name of the group being queried.
+.TP 6n
+\fIuser_pwd\fR
+The password database entry for the user, if any.
+If
+\fIuser\fR
+is not present in the password database,
+\fIuser_pwd\fR
+will be
+\fRNULL\fR.
+.SS "Group plugin example"
+Sudo ships with a Python group plugin example.
+To try it, register it in the
+\fIsudoers\fR
+file by adding the following lines:
+.nf
+.sp
+.RS 4n
+Defaults group_plugin="@python_plugin@ \e
+ ModulePath=@EXAMPLES@/example_group_plugin.py \e
+ ClassName=SudoGroupPlugin"
+.RE
+.fi
+.PP
+The example plugin will tell
+\fBsudo\fR
+that the user
+\fItest\fR
+is part of the non-Unix group
+\fImygroup\fR.
+If you add a rule that uses this group, it will affect the
+\fItest\fR
+user.
+For example:
+.nf
+.sp
+.RS 4n
+%:mygroup ALL=(ALL) NOPASSWD: ALL
+.RE
+.fi
+.PP
+Will allow user
+\fItest\fR
+to run
+\fBsudo\fR
+without a password.
+.SS "Hook function API"
+The hook function API is currently not supported for plugins
+written in Python.
+.SS "Conversation API"
+A Python plugin can interact with the user using the
+\fBsudo.conv\fR()
+function which displays one or more messages described by the
+\fRsudo.ConvMessage\fR
+class.
+This is the Python equivalent of the
+\fBconversation\fR()
+function in the C
+\fBsudo\fR
+plugin API.
+A plugin should not attempt to read directly from the standard input or
+the user's tty (neither of which are guaranteed to exist).
+.PP
+The
+\fRsudo.ConvMessage\fR
+class specifies how the user interaction should occur:
+.nf
+.sp
+.RS 4n
+sudo.ConvMessage(msg_type: int, msg: str, timeout: int)
+.RE
+.fi
+.PP
+\fRsudo.ConvMessage\fR
+member variables:
+.TP 6n
+\fImsg_type\fR
+Specifies the type of the conversation.
+See the
+\fRsudo.CONV.*\fR
+constants below.
+.TP 6n
+\fImsg\fR
+The message to display to the user.
+The caller must include a trailing newline in
+\fImsg\fR
+if one is to be displayed.
+.TP 6n
+\fItimeout\fR
+Optional.
+The maximum amount of time for the conversation in seconds.
+If the timeout is exceeded, the
+\fBsudo.conv\fR()
+function will raise a
+\fRsudo.ConversationInterrupted\fR
+exception.
+The default is to wait forever (no timeout).
+.PP
+To specify the message type, the following constants are available:
+.PP
+.RS 1n
+.PD 0
+.TP 3n
+\fB\(bu\fR
+\fRsudo.CONV.PROMPT_ECHO_OFF\fR
+.TP 3n
+\fB\(bu\fR
+\fRsudo.CONV.PROMPT_ECHO_ON\fR
+.TP 3n
+\fB\(bu\fR
+\fRsudo.CONV.ERROR_MSG\fR
+.TP 3n
+\fB\(bu\fR
+\fRsudo.CONV.INFO_MSG\fR
+.TP 3n
+\fB\(bu\fR
+\fRsudo.CONV.PROMPT_MASK\fR
+.TP 3n
+\fB\(bu\fR
+\fRsudo.CONV.PROMPT_ECHO_OK\fR
+.TP 3n
+\fB\(bu\fR
+\fRsudo.CONV.PREFER_TTY\fR
+.RE
+.PD
+.PP
+See the
+sudo_plugin(@mansectform@)
+manual for a description of the message types.
+.PP
+The
+\fBsudo.conv\fR()
+function performs the actual user interaction:
+.nf
+.sp
+.RS 4n
+sudo.conv(message(s), on_suspend=suspend_function,
+ on_resume=resume_function)
+.RE
+.fi
+.PP
+The function arguments are as follows:
+.TP 6n
+\fImessage(s)\fR
+One of more messages (of type
+\fRsudo.ConvMessage\fR),
+each describing a conversation.
+At least one message is required.
+.TP 6n
+\fIon_suspend\fR
+An optional callback function which gets called if the conversation
+is suspended, for example by the user pressing control-Z.
+The specified function must take a single argument which will be filled
+with the number of the signal that caused the process to be suspended.
+.TP 6n
+\fIon_resume\fR
+An optional callback function which gets called when the previously
+suspended conversation is resumed.
+The specified function must take a single argument which will be filled
+with the number of the signal that caused the process to be suspended.
+.PP
+The
+\fBsudo.conv\fR()
+function can raise the following exceptions:
+.TP 6n
+\fRsudo.SudoException\fR
+If the conversation fails, for example when the conversation function is not
+available.
+.TP 6n
+\fRsudo.ConversationInterrupted\fR
+If the conversation function returns an error, e.g., the timeout passed
+or the user interrupted the conversation by pressing control-C.
+.SS "Conversation example"
+Sudo ships with an example plugin demonstrating the Python conversation API.
+To try it, register it by adding the following lines to
+\fI@sysconfdir@/sudo.conf\fR:
+.nf
+.sp
+.RS 4n
+Plugin python_io @python_plugin@ \e
+ ModulePath=@EXAMPLES@/example_conversation.py \e
+ ClassName=ReasonLoggerIOPlugin
+.RE
+.fi
+.SS "Information / error display API"
+.nf
+.RS 0n
+sudo.log_info(string(s), sep=" ", end="\en")
+sudo.log_error(string(s), sep=" ", end="\en")
+.RE
+.fi
+.PP
+To display information to the user, the
+\fBsudo.log_info\fR()
+function can be used.
+To display error messages, use
+\fBsudo.log_error\fR().
+The syntax is similar to the Python
+\fBprint\fR()
+function.
+.PP
+The function arguments are as follows:
+.TP 6n
+\fIstring(s)\fR
+One or more strings to display.
+.TP 6n
+\fIsep\fR
+An optional string which will be used as the separator between the
+specified strings.
+The default is a space character,
+(\(oq\ \(cq).
+.TP 6n
+\fIend\fR
+An optional string which will be displayed at the end of the message.
+The default is a new line character
+(\(oq\en\(cq).
+.SS "Debug API"
+Debug messages are not visible to the user and are only logged debugging
+is explicitly enabled in
+sudo.conf(@mansectform@).
+Python plugins can use the
+\fBsudo.debug\fR()
+function to make use of
+\fBsudo\fR's
+debug system.
+.PP
+\fIEnabling debugging in sudo.conf\fR
+.PP
+To enable debug messages, add a
+\fIDebug\fR
+line to
+sudo.conf(@mansectform@)
+with the program set to
+\fI@python_plugin@\fR.
+For example, to store debug output in
+\fI@log_dir@/sudo_python_debug\fR,
+use a line like the following:
+.nf
+.sp
+.RS 4n
+Debug @python_plugin@ @log_dir@/sudo_python_debug \e
+ plugin@trace,c_calls@trace
+.RE
+.fi
+.PP
+The debug options are in the form of multiple
+\(lqsubsystem@level\(rq
+strings, separated by commas
+(\(oq\&,\(cq).
+For example to just see the debug output of
+\fBsudo.debug\fR()
+calls, use:
+.nf
+.sp
+.RS 4n
+Debug @python_plugin@ @log_dir@/sudo_python_debug plugin@trace
+.RE
+.fi
+.PP
+See
+sudo_conf(@mansectform@)
+for more details.
+.PP
+The most interesting subsystems for Python plugin development are:
+.TP 6n
+\fIplugin\fR
+Logs each
+\fBsudo.debug\fR()
+API call.
+.TP 6n
+\fIpy_calls\fR
+Logs whenever a C function calls into the python module.
+For example, calling the
+\fB__init__\fR()
+function.
+.TP 6n
+\fIc_calls\fR
+Logs whenever python calls into a C
+\fBsudo\fR
+API function.
+.TP 6n
+\fIinternal\fR
+Logs internal functions of the python language wrapper plugin.
+.TP 6n
+\fIsudo_cb\fR
+Logs when
+\fBsudo\fR
+calls into the python plugin API.
+.TP 6n
+\fIload\fR
+Logs python plugin loading / unloading events.
+.PP
+You can also specify
+\(lqall\(rq
+as the subsystem name to log debug messages for all subsystems.
+.PP
+The
+\fBsudo.debug\fR()
+function is defined as:
+.nf
+.sp
+.RS 4n
+sudo.debug(level, message(s))
+.RE
+.fi
+.PP
+The function arguments are as follows:
+.TP 6n
+\fIlevel\fR
+.br
+an integer, use one of the log level constants below
+.TP 6n
+\fImessage(s)\fR
+one or more messages to log
+.PP
+\fIAvailable log levels:\fR
+.TS
+l l l.
+.PP
+\fBsudo.conf name\fR \fBPython constant\fR \fBdescription\fR
+.PP
+crit \fRsudo.DEBUG.CRIT\fR only critical messages
+.PP
+err \fRsudo.DEBUG.ERROR\fR
+.PP
+warn \fRsudo.DEBUG.WARN\fR
+.PP
+notice \fRsudo.DEBUG.NOTICE\fR
+.PP
+diag \fRsudo.DEBUG.DIAG\fR
+.PP
+info \fRsudo.DEBUG.INFO\fR
+.PP
+trace \fRsudo.DEBUG.TRACE\fR
+.PP
+debug \fRsudo.DEBUG.DEBUG\fR very extreme verbose debugging
+.TE
+.PP
+\fIUsing the logging module\fR
+.PP
+Alternatively, a plugin can use the built in logging module of Python as well.
+Sudo adds its log handler to the root logger, so by default all output of a
+logger will get forwarded to sudo log system, as it would call sudo.debug.
+.PP
+The log handler of sudo will map each Python log level of a message to
+the appropriate sudo debug level.
+The sudo debug system will only receive messages that are not filtered
+out by the Python loggers.
+For example, the log level of the python logger will be an additional
+filter for the log messages, and is usually very different from
+what level is set in sudo.conf for the sudo debug system.
+.SS "Debug example"
+Sudo ships with an example debug plugin.
+To try it, register it by adding the following lines to
+\fI@sysconfdir@/sudo.conf\fR:
+.nf
+.sp
+.RS 4n
+Plugin python_io @python_plugin@ \e
+ ModulePath=@EXAMPLES@/example_debugging.py \e
+ ClassName=DebugDemoPlugin
+
+Debug @python_plugin@ \e
+ @log_dir@/sudo_python_debug plugin@trace,c_calls@trace
+.RE
+.fi
+.SS "Option conversion API"
+The Python plugin API includes two convenience functions to
+convert options in
+\(lqkey=value\(rq
+format to a dictionary and vice versa.
+.TP 6n
+options_as_dict
+.nf
+.RS 6n
+options_as_dict(options)
+.RE
+.fi
+.RS 6n
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIoptions\fR
+An iterable (tuple, list, etc.) of strings, each in
+\(lqkey=value\(rq
+format.
+This is how the plugin API passes options and settings to a Python plugin.
+.PP
+The function returns the resulting dictionary.
+Each string of the passed in
+\fIoptions\fR
+will be split at the first equal sign
+(\(oq\&=\(cq)
+into a
+\fIkey\fR
+and
+\fIvalue\fR.
+Dictionary keys will never contain this symbol (but values may).
+.RE
+.TP 6n
+options_from_dict
+.nf
+.RS 6n
+options_from_dict(options_dict)
+.RE
+.fi
+.RS 6n
+.sp
+The function arguments are as follows:
+.TP 6n
+\fIoptions_dict\fR
+A dictionary where both the key and the value are strings.
+The key should not contain an equal sign
+(\(oq\&=\(cq),
+otherwise the resulting string will have a different meaning.
+However, this is not currently enforced.
+.PP
+The function returns a tuple containing the strings in
+\(lqkey=value\(rq
+form for each key and value in the
+\fIoptions_dict\fR
+dictionary passed in.
+This is how the plugin API accepts options and settings.
+.RE
+.SH "PLUGIN API CHANGELOG (Python)"
+None yet
+.SH "LIMITATIONS"
+A maximum of 8 python I/O plugins can be loaded at once.
+If
+\fI@sysconfdir@/sudo.conf\fR
+contains more, those will be rejected with a warning message.
+.PP
+The Event API and the hook function API is currently not accessible
+for Python plugins.
+.SH "SEE ALSO"
+sudo.conf(@mansectform@),
+sudo_plugin(@mansectform@),
+sudoers(@mansectform@),
+sudo(@mansectsu@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS.md file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+Python plugin support is currently considered experimental.
+.PP
+If you believe you have found a bug in
+\fBsudo\fR,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.SH "SECURITY CONSIDERATIONS"
+All Python plugin handling is implemented inside the
+\fI@python_plugin@\fR
+dynamic plugin.
+Therefore, if no Python plugin is registered in
+sudo.conf(@mansectform@)
+or the
+\fIsudoers\fR
+file,
+\fBsudo\fR
+will not load the Python interpreter or the Python libraries.
+.PP
+As
+\fBsudo\fR
+runs plugins as
+\fBroot\fR,
+care must be taken when writing Python plugins to avoid creating
+security vulnerabilities, just as one would when writing plugins
+in C.
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudo_plugin_python.mdoc.in b/docs/sudo_plugin_python.mdoc.in
new file mode 100644
index 0000000..f6edd47
--- /dev/null
+++ b/docs/sudo_plugin_python.mdoc.in
@@ -0,0 +1,1556 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2021 Robert Manner <robert.manner@oneidentity.com>
+.\" Copyright (c) 2019-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd January 16, 2023
+.Dt SUDO_PLUGIN_PYTHON @mansectform@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudo_plugin_python
+.Nd Sudo Plugin API (Python)
+.Sh DESCRIPTION
+Starting with version 1.9,
+.Nm sudo
+plugins can be written in python.
+The API closely follows the C
+.Nm sudo
+plugin API described by
+.Xr sudo_plugin @mansectform@ .
+.Pp
+The supported plugins types are:
+.Pp
+.Bl -bullet -compact -offset 1n -width 1n
+.It
+Policy plugin
+.It
+I/O plugin
+.It
+Audit plugin
+.It
+Approval plugin
+.It
+Group provider plugin
+.El
+.Pp
+Python plugin support needs to be explicitly enabled at build time
+with the configure option
+.Dq --enable-python .
+Python version 3.0 or higher is required.
+.Ss Sudo Python Plugin Base
+A plugin written in Python should be a class in a python file that
+inherits from
+.Em sudo.Plugin .
+The
+.Em sudo.Plugin
+base class has no real purpose other than to identify this class as a plugin.
+.Pp
+The only implemented method is a constructor, which stores the
+keyword arguments it receives as fields (member variables) in the object.
+This is intended as a convenience to allow you to avoid writing the
+constructor yourself.
+.Pp
+For example:
+.Bd -literal -offset 4n
+import sudo
+
+class MySudoPlugin(sudo.Plugin):
+ # example constructor (optional)
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ # example destructor (optional)
+ def __del__(self):
+ pass
+.Ed
+.Pp
+Both the constructor and destructor are optional and can be omitted.
+.Pp
+The customized Plugin class should define a few plugin-specific methods.
+When the plugin loads,
+.Nm sudo
+will create an instance of this class and call the methods.
+The actual methods required depend on the type of the plugin,
+but most return an
+.Vt int
+result code, as documented in
+.Xr sudo_plugin @mansectform@ ,
+that indicates whether or not the method was successful.
+The Python sudo module defines the following constants to improve readability:
+.Bl -column "sudo.RC.USAGE_ERROR" "XXX" -offset 4n
+.It Sy Define Ta Sy Value
+.It Dv sudo.RC.OK Ta 1
+.It Dv sudo.RC.ACCEPT Ta 1
+.It Dv sudo.RC.REJECT Ta 0
+.It Dv sudo.RC.ERROR Ta \-1
+.It Dv sudo.RC.USAGE_ERROR Ta \-2
+.El
+.Pp
+If a function returns
+.Dv None
+(for example, if it does not call return),
+it will be considered to have returned
+.Dv sudo.RC.OK .
+If an exception is raised (other than sudo.PluginException), the
+backtrace will be shown to the user and the plugin function will return
+.Dv sudo.RC.ERROR .
+If that is not acceptable, you must catch the exception and handle it yourself.
+.Pp
+Instead of just returning
+.Dv sudo.RC.ERROR
+or
+.Dv sudo.RC.REJECT
+result code the plugin can also provide a message describing the problem.
+This can be done by raising one of the special exceptions:
+.Bd -literal -offset 4n
+raise sudo.PluginError("Message")
+raise sudo.PluginReject("Message")
+.Ed
+.Pp
+This added message will be used by the audit plugins.
+Both exceptions inherit from
+.Dv sudo.PluginException
+.Ss Python Plugin Loader
+Running the Python interpreter and bridging between C and Python is
+handled by the
+.Nm sudo
+plugin
+.Pa @python_plugin@ .
+This shared object can be loaded like any other dynamic
+.Nm sudo
+plugin and should receive the path and the class name of the Python
+plugin it is loading as arguments.
+.Pp
+Example usage in
+.Xr sudo.conf @mansectform@ :
+.Bd -literal -offset 4n
+Plugin python_policy @python_plugin@ ModulePath=<path> ClassName=<class>
+Plugin python_io @python_plugin@ ModulePath=<path> ClassName=<class>
+Plugin python_audit @python_plugin@ ModulePath=<path> ClassName=<class>
+Plugin python_approval @python_plugin@ ModulePath=<path> ClassName=<class>
+.Ed
+.Pp
+Example group provider plugin usage in the
+.Em sudoers
+file:
+.Bd -literal -offset 4n
+Defaults group_plugin="@python_plugin@ ModulePath=<path> ClassName=<class>"
+.Ed
+.Pp
+The plugin arguments are as follows:
+.Bl -tag -width 4n
+.It ModulePath
+The path of a python file which contains the class of the sudo Python plugin.
+It must be either an absolute path or a path relative to the sudo Python plugin
+directory,
+.Pa @plugindir@/python .
+The parent directory of
+.Em ModulePath
+will be appended to Python's module search path (there is currently no
+way to force Python to load a module from a fully-qualified path).
+It is good practice to use a prefix for the module file that is unlikely
+to conflict with other installed Python modules, for example,
+.Pa sudo_policy.py .
+Otherwise, if the there is an installed Python module with the same
+file name as the sudo Python plugin file (without the directory),
+the wrong file will be loaded.
+.It ClassName
+(Optional.) The name of the class implementing the sudo Python plugin.
+If not supplied, the one and only sudo.Plugin that is present in the module
+will be used.
+If there are multiple such plugins in the module (or none), it
+will result in an error.
+.El
+.Ss Policy plugin API
+Policy plugins must be registered in
+.Xr sudo.conf @mansectform@ .
+For example:
+.Bd -literal -offset 4n
+Plugin python_policy @python_plugin@ ModulePath=<path> ClassName=<class>
+.Ed
+.Pp
+Currently, only a single policy plugin may be specified in
+.Xr sudo.conf @mansectform@ .
+.Pp
+A policy plugin may have the following member functions:
+.Bl -tag -width 4n
+.It Fa constructor
+.Bd -literal -compact
+__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
+ version: str, user_info: Tuple[str, ...],
+ plugin_options: Tuple[str, ...])
+.Ed
+.Pp
+Implementing this function is optional.
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.Pp
+The constructor matches the
+.Fn open
+function in the C
+.Nm sudo
+plugin API.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa user_env
+The user's environment as a tuple of strings in
+.Dq key=value
+format.
+.It Fa settings
+A tuple of user-supplied
+.Em sudo
+settings in the form of
+.Dq key=value
+strings.
+.It Fa version
+The version of the Python Policy Plugin API.
+.It Fa user_info
+A tuple of information about the user running the command in the form of
+.Dq key=value
+strings.
+.It Fa plugin_options
+The plugin options passed as arguments in the
+.Xr sudo.conf @mansectform@
+plugin registration.
+This is a tuple of strings, usually (but not necessarily) in
+.Dq key=value
+format.
+.El
+.Pp
+The
+.Fn sudo.options_as_dict
+convenience function can be used to convert
+.Dq key=value
+pairs to a dictionary.
+For a list of recognized keys and their supported values,
+see the policy plugin
+.Fn open
+documentation in
+.Xr sudo_plugin @mansectform@ .
+.It Fa check_policy
+.Bd -literal -compact
+check_policy(self, argv: Tuple[str, ...], env_add: Tuple[str, ...])
+.Ed
+.Pp
+The
+.Fn check_policy
+function is called by
+.Nm sudo
+to determine whether the user is allowed to run the specified command.
+Implementing this function is mandatory for a policy plugin.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa argv
+A tuple describing the command the user wishes to run.
+.It Fa env_add
+Additional environment variables specified by the user on the command line in
+the form of a tuple of
+.Dq key=value
+pairs.
+The
+.Fn sudo.options_as_dict
+convenience function can be used to convert them to a dictionary.
+.El
+.Pp
+This function should return a result code or a tuple in the following format:
+.Bd -literal -offset 4n
+return (rc, command_info_out, argv_out, user_env_out)
+.Ed
+.Pp
+The tuple values are as follows:
+.Bl -tag -width 4n
+.It Fa rc
+The result of the policy check, one of the
+.Dv sudo.RC.*
+constants.
+.Dv sudo.RC.ACCEPT
+if the command is allowed,
+.Dv sudo.RC.REJECT
+if not allowed,
+.Dv sudo.RC.ERROR
+for a general error, or
+.Dv sudo.RC.USAGE_ERROR
+for a usage error.
+.It Fa command_info_out
+Optional (only required when the command is accepted).
+Information about the command being run in the form of
+.Dq key=value
+strings.
+.Pp
+To accept a command, at the very minimum the plugin must set in the
+.Em command ,
+.Em runas_uid ,
+and
+.Em runas_gid
+keys.
+.Pp
+For a list of recognized keys and supported values,
+see the
+.Fn check_policy
+documentation in
+.Xr sudo_plugin @mansectform@ .
+.It Fa argv_out
+Optional (only required when the command is accepted).
+The arguments to pass to the
+.Xr execve 2
+system call when executing the command.
+.It Fa user_env_out
+Optional (only required when the command is accepted).
+The environment to use when executing the command in the form of a
+tuple of strings in
+.Dq key=value
+format.
+.El
+.It Fa init_session
+.Bd -literal -compact
+init_session(self, user_pwd: Tuple, user_env: Tuple[str, ...])
+.Ed
+.Pp
+Perform session setup (optional).
+The
+.Fn init_session
+function is called before
+.Nm sudo
+sets up the
+execution environment for the command before any user-ID or group-ID changes.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa user_pwd
+A tuple describing the user's passwd entry.
+Convertible to
+.Vt pwd.struct_passwd or
+.Dv None
+if the user is not present in the password database.
+.Pp
+Example conversion:
+.Bd -literal -compact -offset indent
+user_pwd = pwd.struct_passwd(user_pwd) if user_pwd else None
+.Ed
+.It Fa user_env
+The environment the command will run in.
+This is a tuple of strings in
+.Dq key=value
+format.
+.El
+.Pp
+This function should return a result code or a tuple in the following format:
+.Bd -literal -offset 4n
+return (rc, user_env_out)
+.Ed
+.Pp
+The tuple values are as follows:
+.Bl -tag -width 4n
+.It Fa rc
+The result of the session init, one of the
+.Dv sudo.RC.*
+constants.
+.Dv sudo.RC.OK
+on success, 0 on failure, or
+.Dv sudo.RC.ERROR
+if an error occurred.
+.It Fa user_env_out
+Optional.
+If the
+.Fn init_session
+function needs to modify the user environment, it can return the new
+environment in
+.Fa user_env_out .
+If this is omitted, no changes will be made to
+.Fa user_env .
+.El
+.It Fa list
+.Bd -literal -compact
+list(self, argv: Tuple[str, ...], is_verbose: int, user: str)
+.Ed
+.Pp
+List available privileges for the invoking user.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa argv
+If not set to
+.Dv None ,
+an argument vector describing a command the user wishes to check
+against the policy.
+.It Fa is_verbose
+Flag indicating whether to list in verbose mode or not.
+.It Fa user
+The name of a different user to list privileges for if the policy allows it.
+If
+.Dv None ,
+the plugin should list the privileges of the invoking user.
+.El
+.It Fa validate
+.Bd -literal -compact
+validate(self)
+.Ed
+.Pp
+For policy plugins that cache authentication credentials, this function is used to validate and cache the credentials (optional).
+.It Fa invalidate
+.Bd -literal -compact
+invalidate(self, remove: int)
+.Ed
+.Pp
+For policy plugins that cache authentication credentials, this function is used to invalidate the credentials (optional).
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa remove
+If this flag is set, the plugin may remove the credentials instead of simply
+invalidating them.
+.El
+.It Fa show_version
+.Bd -literal -compact
+show_version(self, is_verbose: int)
+.Ed
+.Pp
+Display the plugin version information to the user.
+The
+.Fn sudo.log_info
+function should be used.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa is_verbose
+A flag to indicate displaying more verbose information.
+Currently this is 1 if
+.Ql sudo -V
+is run as the root user.
+.El
+.It Fa close
+.Bd -literal -compact
+close(self, exit_status: int, error: int)
+.Ed
+.Pp
+Called when a command finishes executing.
+.Pp
+Works the same as the
+.Fn close
+function in the C
+.Nm sudo
+plugin API, except that it only gets called if
+.Nm sudo
+attempts to execute the command.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa exit_status
+The exit status of the command if was executed, otherwise \-1.
+.It Fa error
+If the command could not be executed, this is set to the value of
+errno set by the
+.Xr execve 2
+system call, otherwise 0.
+.El
+.El
+.Ss Policy plugin example
+Sudo ships with an example Python policy plugin.
+To try it, register it by adding the following lines to
+.Pa @sysconfdir@/sudo.conf :
+.Bd -literal
+Plugin python_policy @python_plugin@ \e
+ ModulePath=@EXAMPLES@/example_policy_plugin.py \e
+ ClassName=SudoPolicyPlugin
+.Ed
+.Pp
+Only one policy plugin can be enabled at a time so you must disable
+any other policy plugin listed in
+.Pa @sysconfdir@/sudo.conf ,
+such as
+.Xr sudoers @mansectform@ .
+.Ss I/O plugin API
+I/O plugins must be registered in
+.Xr sudo.conf @mansectform@ .
+For example:
+.Bd -literal -offset 4n
+Plugin python_io @python_plugin@ ModulePath=<path> ClassName=<class>
+.Ed
+.Pp
+Sudo supports loading multiple I/O plugins.
+Currently only 8 python I/O plugins can be loaded at once.
+.Pp
+An I/O plugin may have the following member functions:
+.Bl -tag -width 4n
+.It Fa constructor
+.Bd -literal -compact
+__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
+ version: str, user_info: Tuple[str, ...],
+ plugin_options: Tuple[str, ...])
+.Ed
+.Pp
+Implementing this function is optional.
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.Pp
+The constructor matches the
+.Fn open
+function in the C
+.Nm sudo
+plugin API.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa user_env
+The user's environment as a tuple of strings in
+.Dq key=value
+format.
+.It Fa settings
+A tuple of user-supplied
+.Em sudo
+settings in the form of
+.Dq key=value
+strings.
+.It Fa version
+The version of the Python I/O Plugin API.
+.It Fa user_info
+A tuple of information about the user running the command in the form of
+.Dq key=value
+strings.
+.It Fa plugin_options
+The plugin options passed as arguments in the
+.Xr sudo.conf @mansectform@
+plugin registration.
+This is a tuple of strings, usually (but not necessarily) in
+.Dq key=value
+format.
+.El
+.Pp
+The
+.Fn sudo.options_as_dict
+convenience function can be used to convert
+.Dq key=value
+pairs to a dictionary.
+For a list of recognized keys and their supported values,
+see the I/O plugin
+.Fn open
+documentation in
+.Xr sudo_plugin @mansectform@ .
+.It Fa open
+.Bd -literal -compact
+open(self, argv: Tuple[str, ...],
+ command_info: Tuple[str, ...]) -> int
+.Ed
+.Pp
+Receives the command the user wishes to run.
+.Pp
+Works the same as the
+.Fn open
+function in the C
+.Nm sudo
+plugin API except that:
+.Pp
+.Bl -bullet -compact -offset 1n -width 1n
+.It
+It only gets called when there is a command to be executed
+(and not for a version query for example).
+.It
+Other arguments of the C API
+.Fn open
+function are received through the constructor.
+.El
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa argv
+A tuple of the arguments describing the command the user wishes to run.
+.It Fa command_info
+Information about the command being run in the form of
+.Dq key=value
+strings.
+.El
+.Pp
+The
+.Fn sudo.options_as_dict
+convenience function can be used to convert
+.Dq key=value
+pairs to a dictionary.
+For a list of recognized keys and their supported values,
+see the I/O plugin
+.Fn open
+documentation in
+.Xr sudo_plugin @mansectform@ .
+.Pp
+The
+.Fn open
+function should return a result code, one of the
+.Dv sudo.RC.*
+constants.
+If the function returns
+.Dv sudo.RC.REJECT ,
+no I/O will be sent to the plugin.
+.It Fa log_ttyin , log_ttyout , log_stdin , log_stdout , log_stderr
+.Bd -literal -compact
+log_ttyin(self, buf: str) -> int
+log_ttyout(self, buf: str) -> int
+log_stdin(self, buf: str) -> int
+log_stdout(self, buf: str) -> int
+log_stderr(self, buf: str) -> int
+.Ed
+.Pp
+Receive the user input or output of the terminal device and
+application standard input, standard output, or standard error.
+See the matching calls in
+.Xr sudo_plugin @mansectform@ .
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa buf
+The input (or output) buffer in the form of a string.
+.El
+.Pp
+The function should return a result code, one of the
+.Dv sudo.RC.*
+constants.
+.Pp
+If
+.Dv sudo.RC.ERROR
+is returned, the running command will be terminated and all of the
+plugin's logging functions will be disabled.
+Other I/O logging plugins will still receive any remaining
+input or output that has not yet been processed.
+.Pp
+If an input logging function rejects the data by returning
+.Dv sudo.RC.REJECT ,
+the command will be terminated and the data will not be passed to the
+command, though it will still be sent to any other I/O logging plugins.
+If an output logging function rejects the data by returning
+.Dv sudo.RC.REJECT ,
+the command will be terminated and the data will not be written to the
+terminal, though it will still be sent to any other I/O logging plugins.
+.It Fa change_winsize
+.Bd -literal -compact
+change_winsize(self, line: int, cols: int) -> int
+.Ed
+.Pp
+Called whenever the window size of the terminal changes.
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa line
+The number of lines of the terminal.
+.It Fa cols
+The number of columns of the terminal.
+.El
+.It Fa log_suspend
+.Bd -literal -compact
+log_suspend(self, signo: int) -> int
+.Ed
+Called whenever a command is suspended or resumed.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa signo
+The number of the signal that caused the command to be suspended or
+.Dv SIGCONT
+if the command was resumed.
+.El
+.It Fa show_version
+.Bd -literal -compact
+show_version(self, is_verbose: int)
+.Ed
+Display the plugin version information to the user.
+The
+.Fn sudo.log_info
+function should be used.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa is_verbose
+A flag to indicate displaying more verbose information.
+Currently this is 1 if
+.Ql sudo -V
+is run as the root user.
+.El
+.It Fa close
+.Bd -literal -compact
+close(self, exit_status: int, error: int) -> None
+.Ed
+Called when a command finishes execution.
+.Pp
+Works the same as the
+.Fn close
+function in the C
+.Nm sudo
+plugin API, except that it only gets called if
+.Nm sudo
+attempts to execute the command.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa exit_status
+The exit status of the command if was executed, otherwise \-1.
+.It Fa error
+If the command could not be executed, this is set to the value of
+errno set by the
+.Xr execve 2
+system call, otherwise 0.
+.El
+.El
+.Ss I/O plugin example
+Sudo ships with a Python I/O plugin example.
+To try it, register it by adding the following lines to
+.Pa @sysconfdir@/sudo.conf :
+.Bd -literal -offset 4n
+Plugin python_io @python_plugin@ \e
+ ModulePath=@EXAMPLES@/example_io_plugin.py \e
+ ClassName=SudoIOPlugin
+.Ed
+.Ss Audit plugin API
+Audit plugins must be registered in
+.Xr sudo.conf @mansectform@ .
+For example:
+.Bd -literal -offset 4n
+Plugin python_audit @python_plugin@ ModulePath=<path> ClassName=<class>
+.Ed
+.Pp
+Sudo supports loading multiple audit plugins.
+Currently only 8 python audit plugins can be loaded at once.
+.Pp
+An audit plugin may have the following member functions (all of which are optional):
+.Bl -tag -width 4n
+.It Fa constructor
+.Bd -literal -compact
+__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
+ version: str, user_info: Tuple[str, ...], plugin_options: Tuple[str, ...])
+.Ed
+.Pp
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.Pp
+The constructor matches the
+.Fn open
+function in the C
+.Nm sudo
+plugin API.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa user_env
+The user's environment as a tuple of strings in
+.Dq key=value
+format.
+.It Fa settings
+A tuple of user-supplied
+.Em sudo
+settings in the form of
+.Dq key=value
+strings.
+.It Fa version
+The version of the Python Audit Plugin API.
+.It Fa user_info
+A tuple of information about the user running the command in the form of
+.Dq key=value
+strings.
+.It Fa plugin_options
+The plugin options passed as arguments in the
+.Xr sudo.conf @mansectform@
+plugin registration.
+This is a tuple of strings, usually (but not necessarily) in
+.Dq key=value
+format.
+.El
+.It Fa open
+.Bd -literal -compact
+open(self, submit_optind: int,
+ submit_argv: Tuple[str, ...]) -> int
+.Ed
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa submit_optind
+The index into
+.Fa submit_argv
+that corresponds to the first entry that is not a command line option.
+.It Fa submit_argv
+The argument vector sudo was invoked with, including all command line options.
+.El
+.It Fa close
+.Bd -literal -compact
+close(self, status_type: int, status: int) -> None
+.Ed
+.Pp
+Called when sudo is finished, shortly before it exits.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa status_type
+The type of status being passed.
+One of the
+.Dv sudo.EXIT_REASON.*
+constants.
+.It Fa status
+Depending on the value of
+.Fa status_type ,
+this value is either
+ignored, the command's exit status as returned by the
+.Xr wait 2
+system call, the value of
+.Va errno
+set by the
+.Xr execve 2
+system call, or the value of
+.Va errno
+resulting from an error in the
+.Nm sudo
+front-end.
+.El
+.It Fa show_version
+.Bd -literal -compact
+show_version(self, is_verbose: int) -> int
+.Ed
+.Pp
+Display the plugin version information to the user.
+The
+.Fn sudo.log_info
+function should be used.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa is_verbose
+A flag to indicate displaying more verbose information.
+Currently this is 1 if
+.Ql sudo -V
+is run as the root user.
+.El
+.It Fa accept
+.Bd -literal -compact
+accept(self, plugin_name: str, plugin_type: int, command_info: Tuple[str, ...],
+ run_argv: Tuple[str, ...], run_envp: Tuple[str, ...]) -> int
+.Ed
+.Pp
+This function is called when a command or action is accepted by a policy
+or approval plugin.
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It plugin_name
+The name of the plugin that accepted the command or
+.Dq sudo
+for the
+.Nm sudo
+front-end.
+.It plugin_type
+The type of plugin that accepted the command, currently either
+.Dv sudo.PLUGIN_TYPE.POLICY ,
+.Dv sudo.PLUGIN_TYPE.APPROVAL ,
+or
+.Dv sudo.PLUGIN_TYPE.SUDO .
+The
+.Fn accept
+function is called multiple times--once for each policy or approval
+plugin that succeeds and once for the sudo front-end.
+When called on behalf of the sudo front-end,
+.Fa command_info
+may include information from an I/O logging plugin as well.
+.Pp
+Typically, an audit plugin is interested in either the accept status from
+the
+.Nm sudo
+front-end or from the various policy and approval plugins, but not both.
+It is possible for the policy plugin to accept a command that is
+later rejected by an approval plugin, in which case the audit
+plugin's
+.Fn accept
+and
+.Fn reject
+functions will
+.Em both
+be called.
+.It command_info
+A vector of information describing the command being run.
+See the
+.Xr sudo_plugin @mansectform@
+manual for possible values.
+.It run_argv
+Argument vector describing a command that will be run.
+.It run_envp
+The environment the command will be run with.
+.El
+.It Fa reject
+.Bd -literal -compact
+reject(self, plugin_name: str, plugin_type: int, audit_msg: str,
+ command_info: Tuple[str, ...]) -> int
+.Ed
+.Pp
+This function is called when a command or action is rejected by the policy
+plugin.
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It plugin_name
+The name of the plugin that rejected the command.
+.It plugin_type
+The type of plugin that rejected the command, currently either
+.Dv sudo.PLUGIN_TYPE.POLICY ,
+.Dv sudo.PLUGIN_TYPE.APPROVAL ,
+or
+.Dv sudo.PLUGIN_TYPE.IO .
+.Pp
+Unlike the
+.Fn accept
+function, the
+.Fn reject
+function is not called on behalf of the
+.Nm sudo
+front-end.
+.It audit_msg
+An optional string describing the reason the command was rejected by the plugin.
+If the plugin did not provide a reason, audit_msg will be
+.Dv None .
+.It command_info
+A vector of information describing the rejected command.
+See the
+.Xr sudo_plugin @mansectform@
+manual for possible values.
+.El
+.It Fa error
+.Bd -literal -compact
+error(self, plugin_name: str, plugin_type: int, audit_msg: str,
+ command_info: Tuple[str, ...]) -> int
+.Ed
+.Pp
+This function is called when a plugin or the
+.Nm sudo
+front-end returns an error.
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It plugin_name
+The name of the plugin that generated the error or
+.Dq sudo
+for the
+.Nm sudo
+front-end.
+.It plugin_type
+The type of plugin that generated the error, or
+.Dv SUDO_FRONT_END
+for the
+.Nm sudo
+front-end.
+.It audit_msg
+An optional string describing the plugin error.
+If the plugin did not provide a description, it will be
+.Dv None .
+.It command_info
+A vector of information describing the command.
+See the
+.Xr sudo_plugin @mansectform@
+manual for possible values.
+.El
+.El
+.Ss Audit plugin example
+Sudo ships with a Python Audit plugin example.
+To try it, register it by adding the following lines to
+.Pa @sysconfdir@/sudo.conf :
+.Bd -literal -offset 4n
+Plugin python_audit @python_plugin@ \e
+ ModulePath=@EXAMPLES@/example_audit_plugin.py \e
+ ClassName=SudoAuditPlugin
+.Ed
+.Pp
+It will log the plugin accept / reject / error results to the output.
+.Ss Approval plugin API
+Approval plugins must be registered in
+.Xr sudo.conf @mansectform@ .
+For example:
+.Bd -literal -offset 4n
+Plugin python_approval @python_plugin@ ModulePath=<path> ClassName=<class>
+.Ed
+.Pp
+Sudo supports loading multiple approval plugins.
+Currently only 8 python approval plugins can be loaded at once.
+.Pp
+An approval plugin may have the following member functions:
+.Bl -tag -width 4n
+.It Fa constructor
+.Bd -literal -compact
+__init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
+ version: str, user_info: Tuple[str, ...], plugin_options: Tuple[str, ...],
+ submit_optind: int, submit_argv: Tuple[str, ...])
+.Ed
+.Pp
+Optional.
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.Pp
+The constructor matches the
+.Fn open
+function in the C
+.Nm sudo
+plugin API.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa user_env
+The user's environment as a tuple of strings in
+.Dq key=value
+format.
+.It Fa settings
+A tuple of user-supplied
+.Em sudo
+settings in the form of
+.Dq key=value
+strings.
+.It Fa version
+The version of the Python Approval Plugin API.
+.It Fa user_info
+A tuple of information about the user running the command in the form of
+.Dq key=value
+strings.
+.It Fa plugin_options
+The plugin options passed as arguments in the
+.Xr sudo.conf @mansectform@
+plugin registration.
+This is a tuple of strings, usually (but not necessarily) in
+.Dq key=value
+format.
+.It Fa submit_optind
+The index into
+.Fa submit_argv
+that corresponds to the first entry that is not a command line option.
+.It Fa submit_argv
+The argument vector sudo was invoked with, including all command line options.
+.El
+.It Fa show_version
+.Bd -literal -compact
+show_version(self, is_verbose: int) -> int
+.Ed
+.Pp
+Display the version.
+(Same as for all the other plugins.)
+.It Fa check
+.Bd -literal -compact
+check(self, command_info: Tuple[str, ...], run_argv: Tuple[str, ...],
+ run_env: Tuple[str, ...]) -> int
+.Ed
+.Pp
+This function is called after policy plugin's check_policy has succeeded.
+It can reject execution of the command by returning sudo.RC.REJECT or
+raising the special exception:
+.Bd -literal -offset 4n
+raise sudo.PluginReject("some message")
+.Ed
+.Pp
+with the message describing the problem.
+In the latter case, the audit plugins will get the description.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It command_info
+A vector of information describing the command that will run.
+See the
+.Xr sudo_plugin @mansectform@
+manual for possible values.
+.It run_argv
+Argument vector describing a command that will be run.
+.It run_env
+The environment the command will be run with.
+.El
+.El
+.Ss Approval plugin example
+Sudo ships with a Python Approval plugin example.
+To try it, register it by adding the following lines to
+.Pa @sysconfdir@/sudo.conf :
+.Bd -literal -offset 4n
+Plugin python_approval @python_plugin@ \e
+ ModulePath=@EXAMPLES@/example_approval_plugin.py \e
+ ClassName=BusinessHoursApprovalPlugin
+.Ed
+.Pp
+It will only allow execution of commands in the "business hours" (from Monday
+to Friday between 8:00 and 17:59:59).
+.Ss Sudoers group provider plugin API
+A group provider plugin is registered in the
+.Xr sudoers @mansectform@
+file.
+For example:
+.Bd -literal -offset 4n
+Defaults group_plugin="@python_plugin@ ModulePath=<path> ClassName=<class>"
+.Ed
+.Pp
+Currently, only a single group plugin can be registered in
+.Em sudoers .
+.Pp
+A group provider plugin may have the following member functions:
+.Bl -tag -width 4n
+.It Fa constructor
+.Bd -literal -compact
+__init__(self, args: Tuple[str, ...], version: str)
+.Ed
+.Pp
+Implementing this function is optional.
+The default constructor will set the keyword arguments it receives
+as member variables in the object.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa args
+The plugin options passed as arguments in the
+.Em sudoers
+file plugin registration.
+All the arguments are free form strings (not necessarily in
+.Dq key=value
+format).
+.It Fa version
+The version of the Python Group Plugin API.
+.El
+.It Fa query
+.Bd -literal -compact
+query(self, user: str, group: str, user_pwd: Tuple)
+.Ed
+.Pp
+The
+.Fn query
+function is used to ask the group plugin whether
+.Fa user
+is a member of
+.Fa group .
+This method is required.
+.El
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa user
+The name of the user being looked up in the external group database.
+.It Fa group
+The name of the group being queried.
+.It Fa user_pwd
+The password database entry for the user, if any.
+If
+.Fa user
+is not present in the password database,
+.Fa user_pwd
+will be
+.Dv NULL .
+.El
+.Ss Group plugin example
+Sudo ships with a Python group plugin example.
+To try it, register it in the
+.Em sudoers
+file by adding the following lines:
+.Bd -literal -offset 4n
+Defaults group_plugin="@python_plugin@ \e
+ ModulePath=@EXAMPLES@/example_group_plugin.py \e
+ ClassName=SudoGroupPlugin"
+.Ed
+.Pp
+The example plugin will tell
+.Nm sudo
+that the user
+.Em test
+is part of the non-Unix group
+.Em mygroup .
+If you add a rule that uses this group, it will affect the
+.Em test
+user.
+For example:
+.Bd -literal -offset 4n
+%:mygroup ALL=(ALL) NOPASSWD: ALL
+.Ed
+.Pp
+Will allow user
+.Em test
+to run
+.Nm sudo
+without a password.
+.Ss Hook function API
+The hook function API is currently not supported for plugins
+written in Python.
+.Ss Conversation API
+A Python plugin can interact with the user using the
+.Fn sudo.conv
+function which displays one or more messages described by the
+.Dv sudo.ConvMessage
+class.
+This is the Python equivalent of the
+.Fn conversation
+function in the C
+.Nm sudo
+plugin API.
+A plugin should not attempt to read directly from the standard input or
+the user's tty (neither of which are guaranteed to exist).
+.Pp
+The
+.Dv sudo.ConvMessage
+class specifies how the user interaction should occur:
+.Bd -literal -offset 4n
+sudo.ConvMessage(msg_type: int, msg: str, timeout: int)
+.Ed
+.Pp
+.Dv sudo.ConvMessage
+member variables:
+.Bl -tag -width 4n
+.It Fa msg_type
+Specifies the type of the conversation.
+See the
+.Dv sudo.CONV.*
+constants below.
+.It Fa msg
+The message to display to the user.
+The caller must include a trailing newline in
+.Fa msg
+if one is to be displayed.
+.It Fa timeout
+Optional.
+The maximum amount of time for the conversation in seconds.
+If the timeout is exceeded, the
+.Fn sudo.conv
+function will raise a
+.Dv sudo.ConversationInterrupted
+exception.
+The default is to wait forever (no timeout).
+.El
+.Pp
+To specify the message type, the following constants are available:
+.Pp
+.Bl -bullet -compact -offset 1n -width 1n
+.It
+.Dv sudo.CONV.PROMPT_ECHO_OFF
+.It
+.Dv sudo.CONV.PROMPT_ECHO_ON
+.It
+.Dv sudo.CONV.ERROR_MSG
+.It
+.Dv sudo.CONV.INFO_MSG
+.It
+.Dv sudo.CONV.PROMPT_MASK
+.It
+.Dv sudo.CONV.PROMPT_ECHO_OK
+.It
+.Dv sudo.CONV.PREFER_TTY
+.El
+.Pp
+See the
+.Xr sudo_plugin @mansectform@
+manual for a description of the message types.
+.Pp
+The
+.Fn sudo.conv
+function performs the actual user interaction:
+.Bd -literal -offset 4n
+sudo.conv(message(s), on_suspend=suspend_function,
+ on_resume=resume_function)
+.Ed
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa message(s)
+One of more messages (of type
+.Dv sudo.ConvMessage ) ,
+each describing a conversation.
+At least one message is required.
+.It Fa on_suspend
+An optional callback function which gets called if the conversation
+is suspended, for example by the user pressing control-Z.
+The specified function must take a single argument which will be filled
+with the number of the signal that caused the process to be suspended.
+.It Fa on_resume
+An optional callback function which gets called when the previously
+suspended conversation is resumed.
+The specified function must take a single argument which will be filled
+with the number of the signal that caused the process to be suspended.
+.El
+.Pp
+The
+.Fn sudo.conv
+function can raise the following exceptions:
+.Bl -tag -width 4n
+.It Dv sudo.SudoException
+If the conversation fails, for example when the conversation function is not
+available.
+.It Dv sudo.ConversationInterrupted
+If the conversation function returns an error, e.g., the timeout passed
+or the user interrupted the conversation by pressing control-C.
+.El
+.Ss Conversation example
+Sudo ships with an example plugin demonstrating the Python conversation API.
+To try it, register it by adding the following lines to
+.Pa @sysconfdir@/sudo.conf :
+.Bd -literal -offset 4n
+Plugin python_io @python_plugin@ \e
+ ModulePath=@EXAMPLES@/example_conversation.py \e
+ ClassName=ReasonLoggerIOPlugin
+.Ed
+.Ss Information / error display API
+.Bd -literal
+sudo.log_info(string(s), sep=" ", end="\en")
+sudo.log_error(string(s), sep=" ", end="\en")
+.Ed
+.Pp
+To display information to the user, the
+.Fn sudo.log_info
+function can be used.
+To display error messages, use
+.Fn sudo.log_error .
+The syntax is similar to the Python
+.Fn print
+function.
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa string(s)
+One or more strings to display.
+.It Fa sep
+An optional string which will be used as the separator between the
+specified strings.
+The default is a space character,
+.Pq Sq \ .
+.It Fa end
+An optional string which will be displayed at the end of the message.
+The default is a new line character
+.Pq Sq \en .
+.El
+.Ss Debug API
+Debug messages are not visible to the user and are only logged debugging
+is explicitly enabled in
+.Xr sudo.conf @mansectform@ .
+Python plugins can use the
+.Fn sudo.debug
+function to make use of
+.Nm sudo Ns No 's
+debug system.
+.Pp
+.Em Enabling debugging in sudo.conf
+.Pp
+To enable debug messages, add a
+.Em Debug
+line to
+.Xr sudo.conf @mansectform@
+with the program set to
+.Pa @python_plugin@ .
+For example, to store debug output in
+.Pa @log_dir@/sudo_python_debug ,
+use a line like the following:
+.Bd -literal -offset 4n
+Debug @python_plugin@ @log_dir@/sudo_python_debug \e
+ plugin@trace,c_calls@trace
+.Ed
+.Pp
+The debug options are in the form of multiple
+.Dq subsystem@level
+strings, separated by commas
+.Pq Sq \&, .
+For example to just see the debug output of
+.Fn sudo.debug
+calls, use:
+.Bd -literal -offset 4n
+Debug @python_plugin@ @log_dir@/sudo_python_debug plugin@trace
+.Ed
+.Pp
+See
+.Xr sudo_conf @mansectform@
+for more details.
+.Pp
+The most interesting subsystems for Python plugin development are:
+.Bl -tag -width 4n
+.It Em plugin
+Logs each
+.Fn sudo.debug
+API call.
+.It Em py_calls
+Logs whenever a C function calls into the python module.
+For example, calling the
+.Fn __init__
+function.
+.It Em c_calls
+Logs whenever python calls into a C
+.Nm sudo
+API function.
+.It Em internal
+Logs internal functions of the python language wrapper plugin.
+.It Em sudo_cb
+Logs when
+.Nm sudo
+calls into the python plugin API.
+.It Em load
+Logs python plugin loading / unloading events.
+.El
+.Pp
+You can also specify
+.Dq all
+as the subsystem name to log debug messages for all subsystems.
+.Pp
+The
+.Fn sudo.debug
+function is defined as:
+.Bd -literal -offset 4n
+sudo.debug(level, message(s))
+.Ed
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa level
+an integer, use one of the log level constants below
+.It Fa message(s)
+one or more messages to log
+.El
+.Pp
+.Em Available log levels:
+.Bl -column "name in sudo.conf" "Python constant" "only critical messages"
+.It Sy sudo.conf name Ta Sy Python constant Ta Sy description
+.It crit Ta Dv sudo.DEBUG.CRIT Ta only critical messages
+.It err Ta Dv sudo.DEBUG.ERROR Ta
+.It warn Ta Dv sudo.DEBUG.WARN Ta
+.It notice Ta Dv sudo.DEBUG.NOTICE Ta
+.It diag Ta Dv sudo.DEBUG.DIAG Ta
+.It info Ta Dv sudo.DEBUG.INFO Ta
+.It trace Ta Dv sudo.DEBUG.TRACE Ta
+.It debug Ta Dv sudo.DEBUG.DEBUG Ta very extreme verbose debugging
+.El
+.Pp
+.Em Using the logging module
+.Pp
+Alternatively, a plugin can use the built in logging module of Python as well.
+Sudo adds its log handler to the root logger, so by default all output of a
+logger will get forwarded to sudo log system, as it would call sudo.debug.
+.Pp
+The log handler of sudo will map each Python log level of a message to
+the appropriate sudo debug level.
+The sudo debug system will only receive messages that are not filtered
+out by the Python loggers.
+For example, the log level of the python logger will be an additional
+filter for the log messages, and is usually very different from
+what level is set in sudo.conf for the sudo debug system.
+.Ss Debug example
+Sudo ships with an example debug plugin.
+To try it, register it by adding the following lines to
+.Pa @sysconfdir@/sudo.conf :
+.Bd -literal -offset 4n
+Plugin python_io @python_plugin@ \e
+ ModulePath=@EXAMPLES@/example_debugging.py \e
+ ClassName=DebugDemoPlugin
+
+Debug @python_plugin@ \e
+ @log_dir@/sudo_python_debug plugin@trace,c_calls@trace
+.Ed
+.Ss Option conversion API
+The Python plugin API includes two convenience functions to
+convert options in
+.Dq key=value
+format to a dictionary and vice versa.
+.Bl -tag -width 4n
+.It options_as_dict
+.Bd -literal -compact
+options_as_dict(options)
+.Ed
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa options
+An iterable (tuple, list, etc.) of strings, each in
+.Dq key=value
+format.
+This is how the plugin API passes options and settings to a Python plugin.
+.El
+.Pp
+The function returns the resulting dictionary.
+Each string of the passed in
+.Fa options
+will be split at the first equal sign
+.Pq Sq \&=
+into a
+.Em key
+and
+.Em value .
+Dictionary keys will never contain this symbol (but values may).
+.It options_from_dict
+.Bd -literal -compact
+options_from_dict(options_dict)
+.Ed
+.Pp
+The function arguments are as follows:
+.Bl -tag -width 4n
+.It Fa options_dict
+A dictionary where both the key and the value are strings.
+The key should not contain an equal sign
+.Pq Sq \&= ,
+otherwise the resulting string will have a different meaning.
+However, this is not currently enforced.
+.El
+.Pp
+The function returns a tuple containing the strings in
+.Dq key=value
+form for each key and value in the
+.Fa options_dict
+dictionary passed in.
+This is how the plugin API accepts options and settings.
+.El
+.Sh PLUGIN API CHANGELOG (Python)
+None yet
+.Sh LIMITATIONS
+A maximum of 8 python I/O plugins can be loaded at once.
+If
+.Pa @sysconfdir@/sudo.conf
+contains more, those will be rejected with a warning message.
+.Pp
+The Event API and the hook function API is currently not accessible
+for Python plugins.
+.Sh SEE ALSO
+.Xr sudo.conf @mansectform@ ,
+.Xr sudo_plugin @mansectform@ ,
+.Xr sudoers @mansectform@ ,
+.Xr sudo @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS.md file in the
+.Nm sudo
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+Python plugin support is currently considered experimental.
+.Pp
+If you believe you have found a bug in
+.Nm sudo ,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.Sh SECURITY CONSIDERATIONS
+All Python plugin handling is implemented inside the
+.Pa @python_plugin@
+dynamic plugin.
+Therefore, if no Python plugin is registered in
+.Xr sudo.conf @mansectform@
+or the
+.Em sudoers
+file,
+.Nm sudo
+will not load the Python interpreter or the Python libraries.
+.Pp
+As
+.Nm sudo
+runs plugins as
+.Sy root ,
+care must be taken when writing Python plugins to avoid creating
+security vulnerabilities, just as one would when writing plugins
+in C.
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm sudo
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+.Nm sudo
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudo_sendlog.man.in b/docs/sudo_sendlog.man.in
new file mode 100644
index 0000000..1bccdc4
--- /dev/null
+++ b/docs/sudo_sendlog.man.in
@@ -0,0 +1,204 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.TH "SUDO_SENDLOG" "@mansectsu@" "January 16, 2023" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudo_sendlog\fR
+\- send sudo I/O log to log server
+.SH "SYNOPSIS"
+.HP 13n
+\fBsudo_sendlog\fR
+[\fB\-AnV\fR]
+[\fB\-b\fR\ \fIca_bundle\fR]
+[\fB\-c\fR\ \fIcert_file\fR]
+[\fB\-h\fR\ \fIhost\fR]
+[\fB\-i\fR\ \fIiolog-id\fR]
+[\fB\-k\fR\ \fIkey_file\fR]
+[\fB\-p\fR\ \fIport\fR]
+[\fB\-r\fR\ \fIrestart-point\fR]
+[\fB\-R\fR\ \fIreject-reason\fR]
+[\fB\-s\fR\ \fIstop-point\fR]
+[\fB\-t\fR\ \fInumber\fR]
+\fIpath\fR
+.SH "DESCRIPTION"
+\fBsudo_sendlog\fR
+can be used to send the existing
+\fBsudoers\fR
+I/O log
+\fIpath\fR
+to a remote log server such as
+sudo_logsrvd(@mansectsu@)
+for central storage.
+.PP
+The options are as follows:
+.TP 8n
+\fB\-A\fR, \fB\--accept-only\fR
+Only send the accept event, not the I/O associated with the log.
+This can be used to test the logging of accept events without
+any associated I/O.
+.TP 8n
+\fB\-b\fR, \fB\--ca-bundle\fR
+The path to a certificate authority bundle file, in PEM format,
+to use instead of the system's default certificate authority database
+when authenticating the log server.
+The default is to use the system's default certificate authority database.
+.TP 8n
+\fB\-c\fR, \fB\--cert\fR
+The path to the client's certificate file in PEM format.
+This setting is required when the connection to the remote log server
+is secured with TLS.
+.TP 8n
+\fB\--help\fR
+.br
+Display a short help message to the standard output and exit.
+.TP 8n
+\fB\-h\fR, \fB\--host\fR
+Connect to the specified
+\fIhost\fR
+instead of localhost.
+.TP 8n
+\fB\-i\fR, \fB\--iolog-id\fR
+Use the specified
+\fIiolog-id\fR
+when restarting a log transfer.
+The
+\fIiolog-id\fR
+is reported by the server when it creates the remote I/O log.
+This option may only be used in conjunction with the
+\fB\-r\fR
+option.
+.TP 8n
+\fB\-k\fR, \fB\--key\fR
+The path to the client's private key file in PEM format.
+This setting is required when the connection to the remote log server
+is secured with TLS.
+.TP 8n
+\fB\-n\fR, \fB\--no-verify\fR
+If specified, the server's certificate will not be verified during
+the TLS handshake.
+By default,
+\fBsudo_sendlog\fR
+verifies that the server's certificate is valid and that it contains either
+the server's host name or its IP address.
+This setting is only supported when the connection to the remote log server
+is secured with TLS.
+.TP 8n
+\fB\-p\fR, \fB\--port\fR
+Use the specified network
+\fIport\fR
+when connecting to the log server instead of the
+default, port 30344.
+.TP 8n
+\fB\-r\fR, \fB\--restart\fR
+Restart an interrupted connection to the log server.
+The specified
+\fIrestart-point\fR
+is used to tell the server the point in time at which to continue the log.
+The
+\fIrestart-point\fR
+is specified in the form
+\(lqseconds,nanoseconds\(rq
+and is usually the last commit point received from the server.
+The
+\fB\-i\fR
+option must also be specified when restarting a transfer.
+.TP 8n
+\fB\-R\fR, \fB\--reject\fR
+Send a reject event for the command using the specified
+\fIreject-reason\fR,
+even though it was actually accepted locally.
+This can be used to test the logging of reject events; no I/O
+will be sent.
+.TP 8n
+\fB\-s\fR, \fB\--stop-after\fR
+Stop sending log records and close the connection when
+\fIstop-point\fR
+is reached.
+This can be used for testing purposes to send a partial I/O log to the server.
+Partial logs can be restarted using the
+\fB\-r\fR
+option.
+The
+\fIstop-point\fR
+is an elapsed time specified in the form
+\(lqseconds,nanoseconds\(rq.
+.TP 8n
+\fB\-t\fR, \fB\--test\fR
+Open
+\fInumber\fR
+simultaneous connections to the log server and send the specified
+I/O log file on each one.
+This option is useful for performance testing.
+.TP 8n
+\fB\-V\fR, \fB\--version\fR
+Print the
+\fBsudo_sendlog\fR
+version and exit.
+.SS "Debugging sendlog"
+\fBsudo_sendlog\fR
+supports a flexible debugging framework that is configured via
+\fIDebug\fR
+lines in the
+sudo.conf(@mansectform@)
+file.
+.PP
+For more information on configuring
+sudo.conf(@mansectform@),
+refer to its manual.
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/sudo.conf\fR
+Sudo front-end configuration
+.SH "SEE ALSO"
+sudo.conf(@mansectform@),
+sudo(@mansectsu@),
+sudo_logsrvd(@mansectsu@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS.md file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you believe you have found a bug in
+\fBsudo_sendlog\fR,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo_sendlog\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudo_sendlog.mdoc.in b/docs/sudo_sendlog.mdoc.in
new file mode 100644
index 0000000..1314ce4
--- /dev/null
+++ b/docs/sudo_sendlog.mdoc.in
@@ -0,0 +1,189 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2019-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd January 16, 2023
+.Dt SUDO_SENDLOG @mansectsu@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudo_sendlog
+.Nd send sudo I/O log to log server
+.Sh SYNOPSIS
+.Nm sudo_sendlog
+.Op Fl AnV
+.Op Fl b Ar ca_bundle
+.Op Fl c Ar cert_file
+.Op Fl h Ar host
+.Op Fl i Ar iolog-id
+.Op Fl k Ar key_file
+.Op Fl p Ar port
+.Op Fl r Ar restart-point
+.Op Fl R Ar reject-reason
+.Op Fl s Ar stop-point
+.Op Fl t Ar number
+.Ar path
+.Sh DESCRIPTION
+.Nm
+can be used to send the existing
+.Nm sudoers
+I/O log
+.Ar path
+to a remote log server such as
+.Xr sudo_logsrvd @mansectsu@
+for central storage.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl A , -accept-only
+Only send the accept event, not the I/O associated with the log.
+This can be used to test the logging of accept events without
+any associated I/O.
+.It Fl b , -ca-bundle
+The path to a certificate authority bundle file, in PEM format,
+to use instead of the system's default certificate authority database
+when authenticating the log server.
+The default is to use the system's default certificate authority database.
+.It Fl c , -cert
+The path to the client's certificate file in PEM format.
+This setting is required when the connection to the remote log server
+is secured with TLS.
+.It Fl -help
+Display a short help message to the standard output and exit.
+.It Fl h , -host
+Connect to the specified
+.Ar host
+instead of localhost.
+.It Fl i , -iolog-id
+Use the specified
+.Ar iolog-id
+when restarting a log transfer.
+The
+.Ar iolog-id
+is reported by the server when it creates the remote I/O log.
+This option may only be used in conjunction with the
+.Fl r
+option.
+.It Fl k , -key
+The path to the client's private key file in PEM format.
+This setting is required when the connection to the remote log server
+is secured with TLS.
+.It Fl n , -no-verify
+If specified, the server's certificate will not be verified during
+the TLS handshake.
+By default,
+.Nm
+verifies that the server's certificate is valid and that it contains either
+the server's host name or its IP address.
+This setting is only supported when the connection to the remote log server
+is secured with TLS.
+.It Fl p , -port
+Use the specified network
+.Ar port
+when connecting to the log server instead of the
+default, port 30344.
+.It Fl r , -restart
+Restart an interrupted connection to the log server.
+The specified
+.Ar restart-point
+is used to tell the server the point in time at which to continue the log.
+The
+.Ar restart-point
+is specified in the form
+.Dq seconds,nanoseconds
+and is usually the last commit point received from the server.
+The
+.Fl i
+option must also be specified when restarting a transfer.
+.It Fl R , -reject
+Send a reject event for the command using the specified
+.Ar reject-reason ,
+even though it was actually accepted locally.
+This can be used to test the logging of reject events; no I/O
+will be sent.
+.It Fl s , -stop-after
+Stop sending log records and close the connection when
+.Ar stop-point
+is reached.
+This can be used for testing purposes to send a partial I/O log to the server.
+Partial logs can be restarted using the
+.Fl r
+option.
+The
+.Ar stop-point
+is an elapsed time specified in the form
+.Dq seconds,nanoseconds .
+.It Fl t , -test
+Open
+.Ar number
+simultaneous connections to the log server and send the specified
+I/O log file on each one.
+This option is useful for performance testing.
+.It Fl V , -version
+Print the
+.Nm
+version and exit.
+.El
+.Ss Debugging sendlog
+.Nm
+supports a flexible debugging framework that is configured via
+.Em Debug
+lines in the
+.Xr sudo.conf @mansectform@
+file.
+.Pp
+For more information on configuring
+.Xr sudo.conf @mansectform@ ,
+refer to its manual.
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/sudo.conf
+Sudo front-end configuration
+.El
+.Sh SEE ALSO
+.Xr sudo.conf @mansectform@ ,
+.Xr sudo @mansectsu@ ,
+.Xr sudo_logsrvd @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS.md file in the
+.Nm sudo
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you believe you have found a bug in
+.Nm ,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+.Nm sudo
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudoers.ldap.man.in b/docs/sudoers.ldap.man.in
new file mode 100644
index 0000000..ed88296
--- /dev/null
+++ b/docs/sudoers.ldap.man.in
@@ -0,0 +1,1801 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2003-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.TH "SUDOERS.LDAP" "@mansectform@" "June 7, 2023" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudoers.ldap\fR
+\- sudo LDAP configuration
+.SH "DESCRIPTION"
+In addition to the standard
+\fIsudoers\fR
+file,
+\fBsudo\fR
+may be configured
+via LDAP.
+This can be especially useful for synchronizing
+\fIsudoers\fR
+in a large, distributed environment.
+.PP
+Using LDAP for
+\fIsudoers\fR
+has several benefits:
+.TP 3n
+\fB\(bu\fR
+\fBsudo\fR
+no longer needs to read
+\fIsudoers\fR
+in its entirety.
+When LDAP is used, there are only two or three LDAP queries per invocation.
+This makes it especially fast and particularly usable in LDAP environments.
+.TP 3n
+\fB\(bu\fR
+It is possible to specify per-entry options that override the global
+default options.
+\fI@sysconfdir@/sudoers\fR
+only supports default options and limited options associated with
+user/host/commands/aliases.
+The syntax is complicated and can be difficult for users to understand.
+Placing the options directly in the entry is more natural.
+.TP 3n
+\fB\(bu\fR
+The
+\fBvisudo\fR
+program is no longer needed.
+\fBvisudo\fR
+provides locking and syntax checking of the
+\fI@sysconfdir@/sudoers\fR
+file.
+Since LDAP updates are atomic, locking is no longer necessary.
+Because syntax is checked when the data is inserted into LDAP, there
+is no need for a specialized tool to check syntax.
+.SS "SUDOers LDAP container"
+The
+\fIsudoers\fR
+configuration is contained in the
+\(oqou=SUDOers\(cq
+LDAP container.
+.PP
+Sudo first looks for the
+\(oqcn=defaults\(cq
+entry in the SUDOers container.
+If found, the multi-valued
+\fIsudoOption\fR
+attribute is parsed in the same manner as a global
+\fIDefaults\fR
+line in
+\fI@sysconfdir@/sudoers\fR.
+In the following example, the
+\fRSSH_AUTH_SOCK\fR
+variable will be preserved in the environment for all users.
+.nf
+.sp
+.RS 4n
+dn: cn=defaults,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: env_keep+=SSH_AUTH_SOCK
+.RE
+.fi
+.PP
+The equivalent of a sudoer in LDAP is a
+\fIsudoRole\fR.
+It consists of the following attributes:
+.TP 6n
+\fBsudoUser\fR
+A user name, user-ID (prefixed with
+\(oq#\(cq),
+Unix group name or ID (prefixed with
+\(oq%\(cq
+or
+\(oq%#\(cq
+respectively), user netgroup (prefixed with
+\(oq+\(cq),
+or non-Unix group name or ID (prefixed with
+\(oq%:\(cq
+or
+\(oq%:#\(cq
+respectively).
+User netgroups are matched using the user and domain members only;
+the host member is not used when matching.
+Non-Unix group support is only available when an appropriate
+\fIgroup_plugin\fR
+is defined in the global
+\fIdefaults\fR
+\fIsudoRole\fR
+object.
+If a
+\fIsudoUser\fR
+entry is preceded by an exclamation point,
+\(oq\&!\(cq,
+and the entry matches, the
+\fIsudoRole\fR
+in which it resides will be ignored.
+Negated
+\fIsudoUser\fR
+entries are only supported by version 1.9.9 or higher.
+.TP 6n
+\fBsudoHost\fR
+A host name, IP address, IP network, or host netgroup (prefixed with a
+\(oq+\(cq).
+The special value
+\fBALL\fR
+will match any host.
+Host netgroups are matched using the host (both qualified and unqualified)
+and domain members only; the user member is not used when matching.
+If a
+\fIsudoHost\fR
+entry is preceded by an exclamation point,
+\(oq\&!\(cq,
+and the entry matches, the
+\fIsudoRole\fR
+in which it resides will be ignored.
+Negated
+\fIsudoHost\fR
+entries are only supported by version 1.8.18 or higher.
+.TP 6n
+\fBsudoCommand\fR
+A fully-qualified Unix command name with optional command line arguments,
+potentially including globbing characters (aka wild cards).
+If a command name is preceded by an exclamation point,
+\(oq\&!\(cq,
+the user will be prohibited from running that command.
+.sp
+The built-in command
+\(lqsudoedit\(rq
+is used to permit a user to run
+\fBsudo\fR
+with the
+\fB\-e\fR
+option (or as
+\fBsudoedit\fR).
+It may take command line arguments just as a normal command does.
+Unlike other commands,
+\(lqsudoedit\(rq
+is a built into
+\fBsudo\fR
+itself and must be specified in without a leading path.
+.sp
+The special value
+\fBALL\fR
+will match any command.
+.sp
+If a command name is prefixed with a SHA-2 digest, it will
+only be allowed if the digest matches.
+This may be useful in situations where the user invoking
+\fBsudo\fR
+has write access to the command or its parent directory.
+The following digest formats are supported: sha224, sha256, sha384, and sha512.
+The digest name must be followed by a colon
+(\(oq:\&\(cq)
+and then the actual digest, in either hex or base64 format.
+For example, given the following value for sudoCommand:
+.nf
+.sp
+.RS 10n
+sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ /bin/ls
+.RE
+.fi
+.RS 6n
+.sp
+The user may only run
+\fI/bin/ls\fR
+if its sha224 digest matches the specified value.
+Command digests are only supported by version 1.8.7 or higher.
+.RE
+.TP 6n
+\fBsudoOption\fR
+Identical in function to the global options described above, but
+specific to the
+\fIsudoRole\fR
+in which it resides.
+.TP 6n
+\fBsudoRunAsUser\fR
+A user name or user-ID (prefixed with
+\(oq#\(cq)
+that commands may be run as or a Unix group (prefixed with a
+\(oq%\(cq)
+or user netgroup (prefixed with a
+\(oq+\(cq)
+that contains a list of users that commands may be run as.
+The special value
+\fBALL\fR
+will match any user.
+If a
+\fIsudoRunAsUser\fR
+entry is preceded by an exclamation point,
+\(oq\&!\(cq,
+and the entry matches, the
+\fIsudoRole\fR
+in which it resides will be ignored.
+If
+\fIsudoRunAsUser\fR
+is specified but empty, it will match the invoking user.
+If neither
+\fIsudoRunAsUser\fR
+nor
+\fIsudoRunAsGroup\fR
+are present, the value of the
+\fIrunas_default\fR
+\fIsudoOption\fR
+is used (defaults to @runas_default@).
+.sp
+The
+\fIsudoRunAsUser\fR
+attribute is only available in
+\fBsudo\fR
+versions
+1.7.0 and higher.
+Older versions of
+\fBsudo\fR
+use the
+\fIsudoRunAs\fR
+attribute instead.
+Negated
+\fIsudoRunAsUser\fR
+entries are only supported by version 1.8.26 or higher.
+.TP 6n
+\fBsudoRunAsGroup\fR
+A Unix group or group-ID (prefixed with
+\(oq#\(cq)
+that commands may be run as.
+The special value
+\fBALL\fR
+will match any group.
+If a
+\fIsudoRunAsGroup\fR
+entry is preceded by an exclamation point,
+\(oq\&!\(cq,
+and the entry matches, the
+\fIsudoRole\fR
+in which it resides will be ignored.
+.sp
+The
+\fIsudoRunAsGroup\fR
+attribute is only available in
+\fBsudo\fR
+versions
+1.7.0 and higher.
+Negated
+\fIsudoRunAsGroup\fR
+entries are only supported by version 1.8.26 or higher.
+.TP 6n
+\fBsudoNotBefore\fR
+A timestamp in the form
+\(oqyyyymmddHHMMSSZ\(cq
+that can be used to provide a start date/time for when the
+\fIsudoRole\fR
+will be valid.
+If multiple
+\fIsudoNotBefore\fR
+entries are present, the earliest is used.
+Timestamps must be in Coordinated Universal Time (UTC),
+not the local timezone.
+The minute and seconds portions are optional, but some LDAP servers
+require that they be present (contrary to the RFC).
+.sp
+The
+\fIsudoNotBefore\fR
+attribute is only available in
+\fBsudo\fR
+versions 1.7.5 and higher and must be explicitly enabled via the
+\fBSUDOERS_TIMED\fR
+option in
+\fI@ldap_conf@\fR.
+.TP 6n
+\fBsudoNotAfter\fR
+A timestamp in the form
+\(oqyyyymmddHHMMSSZ\(cq
+that indicates an expiration date/time, after which the
+\fIsudoRole\fR
+will no longer be valid.
+If multiple
+\fIsudoNotAfter\fR
+entries are present, the last one is used.
+Timestamps must be in Coordinated Universal Time (UTC),
+not the local timezone.
+The minute and seconds portions are optional, but some LDAP servers
+require that they be present (contrary to the RFC).
+.sp
+The
+\fIsudoNotAfter\fR
+attribute is only available in
+\fBsudo\fR
+versions
+1.7.5 and higher and must be explicitly enabled via the
+\fBSUDOERS_TIMED\fR
+option in
+\fI@ldap_conf@\fR.
+.TP 6n
+\fBsudoOrder\fR
+The
+\fIsudoRole\fR
+entries retrieved from the LDAP directory have no inherent order.
+The
+\fIsudoOrder\fR
+attribute is an integer (or floating point value for LDAP servers
+that support it) that is used to sort the matching entries.
+This allows LDAP-based sudoers entries to more closely mimic the behavior
+of the sudoers file, where the order of the entries influences the result.
+If multiple entries match, the entry with the highest
+\fIsudoOrder\fR
+attribute is chosen.
+This corresponds to the
+\(lqlast match\(rq
+behavior of the sudoers file.
+If the
+\fIsudoOrder\fR
+attribute is not present, a value of 0 is assumed.
+.sp
+The
+\fIsudoOrder\fR
+attribute is only available in
+\fBsudo\fR
+versions 1.7.5 and higher.
+.PP
+Each attribute listed above should contain a single value, but there
+may be multiple instances of each attribute type.
+A
+\fIsudoRole\fR
+must contain at least one
+\fIsudoUser\fR,
+\fIsudoHost\fR,
+and
+\fIsudoCommand\fR.
+.PP
+The following example allows users in group wheel to run any command
+on any host via
+\fBsudo\fR:
+.nf
+.sp
+.RS 4n
+dn: cn=%wheel,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: %wheel
+sudoUser: %wheel
+sudoHost: ALL
+sudoCommand: ALL
+.RE
+.fi
+.SS "Anatomy of LDAP sudoers lookup"
+When looking up a sudoer using LDAP there are only two or three
+LDAP queries per invocation.
+The first query is to parse the global options.
+The second is to match against the user's name and the groups that
+the user belongs to.
+(The special
+\fBALL\fR
+tag is matched in this query too.)
+If no match is returned for the user's name and groups, a third
+query returns all entries containing user netgroups and other
+non-Unix groups and checks to see if the user belongs to any of them.
+.PP
+If timed entries are enabled with the
+\fBSUDOERS_TIMED\fR
+parameter, the LDAP queries include a sub-filter that limits retrieval
+to entries that satisfy the time constraints, if any.
+.PP
+If the
+\fBNETGROUP_BASE\fR
+parameter is present and
+\fBNETGROUP_QUERY\fR
+has not been disabled (see
+\fIConfiguring ldap.conf\fR
+below), queries are performed to determine the list of netgroups
+the user belongs to before the sudoers query.
+This makes it possible to include netgroups in the sudoers query
+string in the same manner as Unix groups.
+The third query mentioned above is not performed unless a group provider
+plugin is also configured.
+The actual LDAP queries performed by
+\fBsudo\fR
+are as follows:
+.TP 5n
+1.\&
+Match all
+\fInisNetgroup\fR
+records with a
+\fInisNetgroupTriple\fR
+containing the user, host, and NIS domain.
+The query will match
+\fInisNetgroupTriple\fR
+entries with either the short or long form of the host name or
+no host name specified in the tuple.
+If the NIS domain is set, the query will match only match entries
+that include the domain or for which there is no domain present.
+If the NIS domain is
+\fInot\fR
+set, a wildcard is used to match any domain name but be aware that the
+NIS schema used by some LDAP servers may not support wild cards for
+\fInisNetgroupTriple\fR.
+.TP 5n
+2.\&
+Repeated queries are performed to find any nested
+\fInisNetgroup\fR
+records with a
+\fImemberNisNetgroup\fR
+entry that refers to an already-matched record.
+.PP
+For sites with a large number of netgroups, using
+\fBNETGROUP_BASE\fR
+can significantly speed up
+\fBsudo\fR's
+execution time as long as the LDAP server supports querying the
+\fInisNetgroup\fR
+object by its
+\fInisNetgroupTriple\fR
+attribute.
+.SS "Differences between LDAP and non-LDAP sudoers"
+One of the major differences between LDAP and file-based
+\fIsudoers\fR
+is that in LDAP,
+\fBsudo\fR-specific
+Aliases are not supported.
+.PP
+For the most part, there is little need for
+\fBsudo\fR-specific
+Aliases.
+Unix groups, non-Unix groups (via the
+\fIgroup_plugin\fR),
+or user netgroups can be used in place of User_Aliases and Runas_Aliases.
+Host netgroups can be used in place of Host_Aliases.
+Since groups and netgroups can also be stored in LDAP there is no real need for
+\fBsudo\fR-specific
+aliases.
+.PP
+There are also some subtle differences in the way sudoers is handled
+once in LDAP.
+Probably the biggest is that according to the RFC, LDAP ordering
+is arbitrary and you cannot expect that Attributes and Entries are
+returned in any specific order.
+.PP
+The order in which different entries are applied can be controlled
+using the
+\fIsudoOrder\fR
+attribute, but there is no way to guarantee the order of attributes
+within a specific entry.
+If there are conflicting command rules in an entry, the negative
+takes precedence.
+This is called paranoid behavior (not necessarily the most specific
+match).
+.PP
+Here is an example:
+.nf
+.sp
+.RS 4n
+# /etc/sudoers:
+# Allow all commands except shell
+johnny ALL=(root) ALL,!/bin/sh
+# Always allows all commands because ALL is matched last
+puddles ALL=(root) !/bin/sh,ALL
+
+# LDAP equivalent of johnny
+# Allows all commands except shell
+dn: cn=role1,ou=Sudoers,dc=my-domain,dc=com
+objectClass: sudoRole
+objectClass: top
+cn: role1
+sudoUser: johnny
+sudoHost: ALL
+sudoCommand: ALL
+sudoCommand: !/bin/sh
+
+# LDAP equivalent of puddles
+# Notice that even though ALL comes last, it still behaves like
+# role1 since the LDAP code assumes the more paranoid configuration
+dn: cn=role2,ou=Sudoers,dc=my-domain,dc=com
+objectClass: sudoRole
+objectClass: top
+cn: role2
+sudoUser: puddles
+sudoHost: ALL
+sudoCommand: !/bin/sh
+sudoCommand: ALL
+.RE
+.fi
+.SS "Converting between file-based and LDAP sudoers"
+The
+cvtsudoers(1)
+utility can be used to convert between file-based and LDAP
+\fIsudoers\fR.
+However, there are features in the file-based sudoers that have
+no equivalent in LDAP-based sudoers (and vice versa).
+These cannot be converted automatically.
+.PP
+For example, a Cmnd_Alias in a
+\fIsudoers\fR
+file may be converted to a
+\fIsudoRole\fR
+that contains multiple commands.
+Multiple users and/or groups may be assigned to the
+\fIsudoRole\fR.
+.PP
+Also, host, user, runas, and command-based
+\fIDefaults\fR
+entries are not supported.
+However, a
+\fIsudoRole\fR
+may contain one or more
+\fIsudoOption\fR
+attributes which can often serve the same purpose.
+.PP
+Consider the following
+\fIsudoers\fR
+lines:
+.nf
+.sp
+.RS 4n
+Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less
+Defaults!PAGERS noexec
+alice, bob ALL = ALL
+.RE
+.fi
+.PP
+In this example, alice and bob are allowed to run all commands, but
+the commands listed in PAGERS will have the noexec flag set,
+preventing shell escapes.
+.PP
+When converting this to LDAP, two sudoRole objects can be used:
+.nf
+.sp
+.RS 4n
+dn: cn=PAGERS,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: PAGERS
+sudoUser: alice
+sudoUser: bob
+sudoHost: ALL
+sudoCommand: /usr/bin/more
+sudoCommand: /usr/bin/pg
+sudoCommand: /usr/bin/less
+sudoOption: noexec
+sudoOrder: 900
+
+dn: cn=ADMINS,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: ADMINS
+sudoUser: alice
+sudoUser: bob
+sudoHost: ALL
+sudoCommand: ALL
+sudoOrder: 100
+.RE
+.fi
+.PP
+In the LDAP version, the sudoOrder attribute is used to guarantee
+that the PAGERS sudoRole with
+\fInoexec\fR
+has precedence.
+Unlike the
+\fIsudoers\fR
+version, the LDAP version requires that all users for whom the restriction
+should apply be assigned to the PAGERS sudoRole.
+Using a Unix group or netgroup in PAGERS rather than listing each
+user would make this easier to maintain.
+.PP
+Per-user
+\fIDefaults\fR
+entries can be emulated by using one or more sudoOption attributes
+in a sudoRole.
+Consider the following
+\fIsudoers\fR
+lines:
+.nf
+.sp
+.RS 4n
+User_Alias ADMINS = john, sally
+Defaults:ADMINS !authenticate
+ADMINS ALL = (ALL:ALL) ALL
+.RE
+.fi
+.PP
+In this example, john and sally are allowed to run any command
+as any user or group.
+.PP
+When converting this to LDAP, we can use a Unix group instead
+of the User_Alias.
+.nf
+.sp
+.RS 4n
+dn: cn=admins,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: admins
+sudoUser: %admin
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOption: !authenticate
+.RE
+.fi
+.PP
+This assumes that users john and sally are members of the
+\(lqadmins\(rq
+Unix group.
+.SS "Sudoers schema"
+In order to use
+\fBsudo\fR's
+LDAP support, the
+\fBsudo\fR
+schema must be
+installed on your LDAP server.
+In addition, be sure to index the
+\fIsudoUser\fR
+attribute.
+.PP
+The
+\fBsudo\fR
+distribution includes versions of the
+\fBsudoers\fR
+schema for multiple LDAP servers:
+.TP 6n
+\fIschema.OpenLDAP\fR
+OpenLDAP slapd and
+OpenBSD
+ldapd
+.TP 6n
+\fIschema.olcSudo\fR
+OpenLDAP slapd 2.3 and higher when on-line configuration is enabled
+.TP 6n
+\fIschema.iPlanet\fR
+Netscape-derived servers such as the iPlanet, Oracle,
+and 389 Directory Servers
+.TP 6n
+\fIschema.ActiveDirectory\fR
+Microsoft Active Directory
+.PP
+The schema in OpenLDAP format is also included in the
+\fIEXAMPLES\fR
+section.
+.SS "Configuring ldap.conf"
+Sudo reads the
+\fI@ldap_conf@\fR
+file for LDAP-specific configuration.
+Typically, this file is shared between different LDAP-aware clients.
+As such, most of the settings are not
+\fBsudo\fR-specific.
+The
+\fI@ldap_conf@\fR
+file is parsed by
+\fBsudo\fR
+itself and may support options that differ from those described in the
+system's
+ldap.conf(@mansectform@)
+manual.
+The path to
+\fIldap.conf\fR
+may be overridden via the
+\fIldap_conf\fR
+plugin argument in
+sudo.conf(@mansectform@).
+.PP
+On systems using the OpenLDAP libraries, default values specified in
+\fI/etc/openldap/ldap.conf\fR
+or the user's
+\fI.ldaprc\fR
+files are not used.
+.PP
+\fBsudo\fR
+supports a variety of LDAP library implementations, including
+OpenLDAP, Netscape-derived (also used by Solaris and HP-UX), and
+IBM LDAP (aka Tivoli).
+Some options are specific to certain LDAP implementations or have
+implementation-specific behavior.
+These differences are noted below where applicable.
+.PP
+Only those options explicitly listed in
+\fI@ldap_conf@\fR
+as being supported by
+\fBsudo\fR
+are honored.
+Configuration options are listed below in upper case but are parsed
+in a case-independent manner.
+.PP
+Lines beginning with a pound sign
+(\(oq#\(cq)
+are ignored.
+Leading white space is removed from the beginning of lines.
+.TP 6n
+\fBBIND_TIMELIMIT\fR \fIseconds\fR
+The
+\fBBIND_TIMELIMIT\fR
+parameter specifies the amount of time, in seconds, to wait while trying
+to connect to an LDAP server.
+If multiple
+\fBURI\fRs
+or
+\fBHOST\fRs
+are specified, this is the amount of time to wait before trying
+the next one in the list.
+.TP 6n
+\fBBINDDN\fR \fIDN\fR
+The
+\fBBINDDN\fR
+parameter specifies the identity, in the form of a Distinguished Name (DN),
+to use when performing LDAP operations.
+If not specified, LDAP operations are performed with an anonymous identity.
+By default, most LDAP servers will allow anonymous access.
+.TP 6n
+\fBBINDPW\fR \fIsecret\fR
+The
+\fBBINDPW\fR
+parameter specifies the password to use when performing LDAP operations.
+This is typically used in conjunction with the
+\fBBINDDN\fR
+parameter.
+The
+\fIsecret\fR
+may be a plaintext password or a base64-encoded string with a
+\(lqbase64:\(rq
+prefix.
+For example:
+.nf
+.sp
+.RS 10n
+BINDPW base64:dGVzdA==
+.RE
+.fi
+.RS 6n
+.sp
+If a plaintext password is used, it should be a simple string without quotes.
+Plain text passwords may not include the comment character
+(\(oq#\(cq)
+and the escaping of special characters with a backslash
+(\(oq\e\(cq)
+is not supported.
+.RE
+.TP 6n
+\fBDEREF\fR \fInever/searching/finding/always\fR
+How alias dereferencing is to be performed when searching.
+See the
+ldap.conf(@mansectform@)
+manual for a full description of this option.
+.TP 6n
+\fBHOST\fR \fIname[:port] ...\fR
+If no
+\fBURI\fR
+is specified (see below), the
+\fBHOST\fR
+parameter specifies a white space-delimited list of LDAP servers to connect to.
+Each host may include an optional
+\fIport\fR
+separated by a colon
+(\(oq:\&\(cq).
+The
+\fBHOST\fR
+parameter is deprecated in favor of the
+\fBURI\fR
+specification and is included for backward compatibility only.
+.TP 6n
+\fBKRB5_CCNAME\fR \fIfile name\fR
+The path to the Kerberos 5 credential cache to use when authenticating
+with the remote server.
+.sp
+This option is only relevant when using SASL authentication (see below).
+.TP 6n
+\fBLDAP_VERSION\fR \fInumber\fR
+The version of the LDAP protocol to use when connecting to the server.
+The default value is protocol version 3.
+.TP 6n
+\fBNETGROUP_BASE\fR \fIbase\fR
+The base DN to use when performing LDAP netgroup queries.
+Typically this is of the form
+\(oqou=netgroup,dc=my-domain,dc=com\(cq
+for the domain my-domain.com.
+Multiple
+\fBNETGROUP_BASE\fR
+lines may be specified, in which case they are queried in the order specified.
+.sp
+When this option is enabled,
+\fBsudo\fR
+will query the LDAP server directly when matching netgroups present in a
+\fIsudoRole\fR
+instead of relying on the C library's
+\fBinnetgr\fR()
+function.
+.sp
+Additionally, if the
+\fBNETGROUP_QUERY\fR
+parameter (which is enabled by default) has not been disabled, the
+user's netgroups will be queried directly via LDAP for use in the
+main sudoers query.
+This is usually faster than fetching every
+\fIsudoRole\fR
+object containing a
+\fIsudoUser\fR
+that begins with a
+\(oq+\(cq
+prefix and checking whether the user is a member of each one.
+The NIS schema used by some LDAP servers needs a modification to
+support querying the
+\fInisNetgroup\fR
+object by its
+\fInisNetgroupTriple\fR
+attribute.
+For example, OpenLDAP's
+\fBslapd\fR
+requires the following change to the
+\fInisNetgroupTriple\fR
+attribute:
+.nf
+.sp
+.RS 10n
+attributetype ( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple'
+ DESC 'Netgroup triple'
+ EQUALITY caseIgnoreIA5Match
+ SUBSTR caseIgnoreIA5SubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+.RE
+.fi
+.RS 6n
+.sp
+Before enabling
+\fBNETGROUP_BASE\fR,
+you should verify that your LDAP server supports matching
+\fInisNetgroupTriple\fR.
+For example, using
+\fBldapsearch\fR:
+.nf
+.sp
+.RS 10n
+$ ldapsearch -b $NETGROUP_BASE \e
+ '(&(objectClass=nisNetgroup)(nisNetgroupTriple=\e28*,USER,\e29))'
+.RE
+.fi
+.sp
+where your
+\fInisNetgroup\fR
+data includes an object with the following
+\fInisNetgroupTriple\fR:
+.sp
+.RS 12n
+nisNetgroupTriple: (,USER,)
+.RE
+.RE
+.TP 6n
+\fBNETGROUP_QUERY\fR \fIon/true/yes/off/false/no\fR
+The
+\fBNETGROUP_QUERY\fR
+parameter indicates whether or not the LDAP server supports querying
+\fInisNetgroup\fR
+objects by matching on
+\fInisNetgroupTriple\fR
+attributes.
+By default,
+\fBsudoers\fR
+expects to be able to perform queries that match on
+\fInisNetgroupTriple\fR
+attributes when
+\fBNETGROUP_BASE\fR
+is set, but not all LDAP servers support this.
+.sp
+If
+\fBNETGROUP_QUERY\fR
+is disabled,
+\fBsudoers\fR
+will not attempt to determine the list of netgroups the user belongs
+to, but will still use
+\fBNETGROUP_BASE\fR
+directly when matching netgroups.
+This can be used to support netgroups on systems that lack the
+\fBinnetgr\fR()
+C library function.
+See the description of the
+\fBNETGROUP_BASE\fR
+parameter for more information.
+.TP 6n
+\fBNETGROUP_SEARCH_FILTER\fR \fIldap_filter\fR
+An LDAP filter which is used to restrict the set of records returned
+when performing an LDAP netgroup query.
+Typically, this is of the form
+\(oqattribute=value\(cq
+or
+\(oq(&(attribute=value)(attribute2=value2))\(cq.
+The default search filter is:
+\(oqobjectClass=nisNetgroup\(cq.
+If
+\fIldap_filter\fR
+is omitted, no search filter will be used.
+.sp
+This option is only used when querying netgroups directly via LDAP.
+.TP 6n
+\fBNETWORK_TIMEOUT\fR \fIseconds\fR
+An alias for
+\fBBIND_TIMELIMIT\fR
+provided for OpenLDAP compatibility.
+.TP 6n
+\fBPORT\fR \fIport_number\fR
+If no
+\fBURI\fR
+is specified, the
+\fBPORT\fR
+parameter specifies the default port to connect to on the LDAP server if a
+\fBHOST\fR
+parameter does not specify the port itself.
+If no
+\fBPORT\fR
+parameter is used, the default is port 389 for LDAP and port 636 for LDAP
+over TLS (SSL).
+The
+\fBPORT\fR
+parameter is deprecated in favor of the
+\fBURI\fR
+specification and is included for backward compatibility only.
+.TP 6n
+\fBROOTBINDDN\fR \fIDN\fR
+The
+\fBROOTBINDDN\fR
+parameter specifies the identity, in the form of a Distinguished Name (DN),
+to use when performing privileged LDAP operations, such as
+\fIsudoers\fR
+queries.
+The password corresponding to the identity should be stored in the
+or the path specified by the
+\fIldap_secret\fR
+plugin argument in
+sudo.conf(@mansectform@),
+which defaults to
+\fI@ldap_secret@\fR.
+If no
+\fBROOTBINDDN\fR
+is specified, the
+\fBBINDDN\fR
+identity is used (if any).
+.TP 6n
+\fBROOTUSE_SASL\fR \fIon/true/yes/off/false/no\fR
+Enable
+\fBROOTUSE_SASL\fR
+to enable SASL authentication when connecting
+to an LDAP server from a privileged process, such as
+\fBsudo\fR.
+.TP 6n
+\fBSASL_AUTH_ID\fR \fIidentity\fR
+The SASL user name to use when connecting to the LDAP server.
+By default,
+\fBsudo\fR
+will use an anonymous connection.
+.sp
+This option is only relevant when using SASL authentication.
+.TP 6n
+\fBSASL_MECH\fR \fImechanisms\fR
+A white space-delimited list of SASL authentication mechanisms to use.
+By default,
+\fBsudo\fR
+will use
+\fRGSSAPI\fR
+authentication.
+.TP 6n
+\fBSASL_SECPROPS\fR \fInone/properties\fR
+SASL security properties or
+\fInone\fR
+for no properties.
+See the SASL programmer's manual for details.
+.sp
+This option is only relevant when using SASL authentication.
+.TP 6n
+\fBSSL\fR \fIon/true/yes/off/false/no\fR
+If the
+\fBSSL\fR
+parameter is set to
+\fIon\fR,
+\fItrue\fR,
+or
+\fIyes\fR
+TLS (SSL) encryption is always used when communicating with the LDAP server.
+Typically, this involves connecting to the server on port 636 (ldaps).
+.TP 6n
+\fBSSL\fR \fIstart_tls\fR
+If the
+\fBSSL\fR
+parameter is set to
+\fIstart_tls\fR,
+the LDAP server connection is initiated normally and TLS encryption is
+begun before the bind credentials are sent.
+This has the advantage of not requiring a dedicated port for encrypted
+communications.
+This parameter is only supported by LDAP servers that honor the
+\fIstart_tls\fR
+extension, such as the OpenLDAP and IBM Tivoli Directory servers.
+.TP 6n
+\fBSUDOERS_BASE\fR \fIbase\fR
+The base DN to use when performing
+\fBsudo\fR
+LDAP queries.
+Typically this is of the form
+\(oqou=SUDOers,dc=my-domain,dc=com\(cq
+for the domain my-domain.com.
+Multiple
+\fBSUDOERS_BASE\fR
+lines may be specified, in which case they are queried in the order specified.
+.TP 6n
+\fBSUDOERS_DEBUG\fR \fIdebug_level\fR
+This sets the debug level for
+\fBsudo\fR
+LDAP queries.
+Debugging information is printed to the standard error.
+A value of 1 results in a moderate amount of debugging information.
+A value of 2 shows the results of the matches themselves.
+This parameter should not be set in a production environment as the
+extra information is likely to confuse users.
+.sp
+The
+\fBSUDOERS_DEBUG\fR
+parameter is deprecated and will be removed in a future release.
+The same information is now logged via the
+\fBsudo\fR
+debugging framework using the
+\(lqldap\(rq
+subsystem at priorities
+\fIdiag\fR
+and
+\fIinfo\fR
+for
+\fIdebug_level\fR
+values 1 and 2 respectively.
+See the
+sudo.conf(@mansectform@)
+manual for details on how to configure
+\fBsudo\fR
+debugging.
+.TP 6n
+\fBSUDOERS_SEARCH_FILTER\fR \fIldap_filter\fR
+An LDAP filter which is used to restrict the set of records returned
+when performing a
+\fBsudo\fR
+LDAP query.
+Typically, this is of the
+form
+\(oqattribute=value\(cq
+or
+\(oq(&(attribute=value)(attribute2=value2))\(cq.
+The default search filter is:
+\(oqobjectClass=sudoRole\(cq.
+If
+\fIldap_filter\fR
+is omitted, no search filter will be used.
+.TP 6n
+\fBSUDOERS_TIMED\fR \fIon/true/yes/off/false/no\fR
+Whether or not to evaluate the
+\fIsudoNotBefore\fR
+and
+\fIsudoNotAfter\fR
+attributes that implement time-dependent sudoers entries.
+.TP 6n
+\fBTIMELIMIT\fR \fIseconds\fR
+The
+\fBTIMELIMIT\fR
+parameter specifies the amount of time, in seconds, to wait for a
+response to an LDAP query.
+.TP 6n
+\fBTIMEOUT\fR \fIseconds\fR
+The
+\fBTIMEOUT\fR
+parameter specifies the amount of time, in seconds, to wait for a
+response from the various LDAP APIs.
+.TP 6n
+\fBTLS_CACERT\fR \fIfile name\fR
+An alias for
+\fBTLS_CACERTFILE\fR
+for OpenLDAP compatibility.
+.TP 6n
+\fBTLS_CACERTFILE\fR \fIfile name\fR
+The path to a certificate authority bundle which contains the certificates
+for all the Certificate Authorities the client knows to be valid, e.g.,
+\fI/etc/ssl/ca-bundle.pem\fR.
+.sp
+This option is only supported by the OpenLDAP libraries.
+Netscape-derived LDAP libraries use the same certificate
+database for CA and client certificates (see
+\fBTLS_CERT\fR).
+.TP 6n
+\fBTLS_CACERTDIR\fR \fIdirectory\fR
+Similar to
+\fBTLS_CACERTFILE\fR
+but instead of a file, it is a directory containing individual
+Certificate Authority certificates, e.g.,
+\fI/etc/ssl/certs\fR.
+The directory specified by
+\fBTLS_CACERTDIR\fR
+is checked after
+\fBTLS_CACERTFILE\fR.
+.sp
+This option is only supported by the OpenLDAP libraries.
+.TP 6n
+\fBTLS_CERT\fR \fIfile name\fR
+The path to a file containing the client certificate which can
+be used to authenticate the client to the LDAP server.
+The certificate type depends on the LDAP libraries used.
+.PP
+.RS 6n
+.PD 0
+.TP 6n
+OpenLDAP:
+\(oqtls_cert /etc/ssl/client_cert.pem\(cq
+.PD
+.TP 6n
+Netscape-derived:
+\(oqtls_cert /var/ldap/cert7.db\(cq
+.TP 6n
+IBM LDAP:
+Unused, the key database specified by
+\fBTLS_KEY\fR
+contains both keys and certificates.
+.PP
+When using Netscape-derived libraries, this file may also contain
+Certificate Authority certificates.
+.RE
+.TP 6n
+\fBTLS_CHECKPEER\fR \fIon/true/yes/off/false/no\fR
+If enabled,
+\fBTLS_CHECKPEER\fR
+will cause the LDAP server's TLS certificated to be verified.
+If the server's TLS certificate cannot be verified (usually because it
+is signed by an unknown certificate authority),
+\fBsudo\fR
+will be unable to connect to it.
+If
+\fBTLS_CHECKPEER\fR
+is disabled, no check is made.
+Disabling this check creates an opportunity for man-in-the-middle
+attacks since the server's identity will not be authenticated.
+If possible, the CA's certificate should be installed locally so it can
+be verified.
+.sp
+This option is not supported by the IBM LDAP libraries.
+.TP 6n
+\fBTLS_KEY\fR \fIfile name\fR
+The path to a file containing the private key which matches the
+certificate specified by
+\fBTLS_CERT\fR.
+The private key must not be password-protected.
+The key type depends on the LDAP libraries used.
+.PP
+.RS 6n
+.PD 0
+.TP 6n
+OpenLDAP:
+\(oqtls_key /etc/ssl/client_key.pem\(cq
+.PD
+.TP 6n
+Netscape-derived:
+\(oqtls_key /var/ldap/key3.db\(cq
+.TP 6n
+IBM LDAP:
+\(oqtls_key /usr/ldap/ldapkey.kdb\(cq
+.PP
+When using IBM LDAP libraries, this file may also contain
+Certificate Authority and client certificates and may be encrypted.
+.RE
+.TP 6n
+\fBTLS_CIPHERS\fR \fIcipher list\fR
+The
+\fBTLS_CIPHERS\fR
+parameter allows the administer to restrict which encryption algorithms
+may be used for TLS (SSL) connections.
+See the OpenLDAP or IBM Tivoli Directory Server manual for a list of valid
+ciphers.
+.sp
+This option is not supported by Netscape-derived libraries.
+.TP 6n
+\fBTLS_KEYPW\fR \fIsecret\fR
+The
+\fBTLS_KEYPW\fR
+contains the password used to decrypt the key database on clients
+using the IBM LDAP library.
+The
+\fIsecret\fR
+may be a plaintext password or a base64-encoded string with a
+\(lqbase64:\(rq
+prefix.
+For example:
+.nf
+.sp
+.RS 10n
+TLS_KEYPW base64:dGVzdA==
+.RE
+.fi
+.RS 6n
+.sp
+If a plaintext password is used, it should be a simple string without quotes.
+Plain text passwords may not include the comment character
+(\(oq#\(cq)
+and the escaping of special characters with a backslash
+(\(oq\e\(cq)
+is not supported.
+If this option is used,
+\fI@ldap_conf@\fR
+must not be world-readable to avoid exposing the password.
+Alternately, a
+\fIstash file\fR
+can be used to store the password in encrypted form (see below).
+.sp
+If no
+\fBTLS_KEYPW\fR
+is specified, a
+\fIstash file\fR
+will be used if it exists.
+The
+\fIstash file\fR
+must have the same path as the file specified by
+\fBTLS_KEY\fR,
+but use a
+\(oq.sth\(cq
+file extension instead of
+\(oq.kdb\(cq,
+for example
+\(oqldapkey.sth\(cq.
+The default
+\(oqldapkey.kdb\(cq
+that ships with the IBM Tivoli Directory Server is encrypted with the password
+\(oqssl_password\(cq.
+The
+\fIgsk8capicmd\fR
+utility can be used to manage the key database and create a
+\fIstash file\fR.
+.sp
+This option is only supported by the IBM LDAP libraries.
+.RE
+.TP 6n
+\fBTLS_REQCERT\fR \fIlevel\fR
+The
+\fBTLS_REQCERT\fR
+parameter controls how the LDAP server's TLS certificated will be
+verified (if at all).
+If the server's TLS certificate cannot be verified (usually because it
+is signed by an unknown certificate authority),
+\fBsudo\fR
+will be unable to connect to it.
+The following
+\fIlevel\fR
+values are supported:
+.RS 10n
+.TP 6n
+never
+.br
+The server certificate will not be requested or checked.
+.TP 6n
+allow
+.br
+The server certificate will be requested.
+A missing or invalid certificate is ignored and not considered an error.
+.TP 6n
+try
+The server certificate will be requested.
+A missing certificate is ignored but an invalid certificate will
+result in a connection error.
+.TP 6n
+demand | \fIhard\fR
+The server certificate will be requested.
+A missing or invalid certificate will result in a connection error.
+This is the default behavior.
+.RE
+.RS 6n
+.sp
+This option is only supported by the OpenLDAP libraries.
+Other LDAP libraries only support the
+\fBTLS_CHECKPEER\fR
+parameter.
+.RE
+.TP 6n
+\fBTLS_RANDFILE\fR \fIfile name\fR
+The
+\fBTLS_RANDFILE\fR
+parameter specifies the path to an entropy source for systems that lack
+a random device.
+It is generally used in conjunction with
+\fIprngd\fR
+or
+\fIegd\fR.
+.sp
+This option is only supported by the OpenLDAP libraries.
+.TP 6n
+\fBURI\fR \fIldap[s]://[hostname[:port]] ...\fR
+Specifies a white space-delimited list of one or more URIs describing
+the LDAP server(s) to connect to.
+The
+\fIprotocol\fR
+may be either
+\fIldap\fR
+\fIldaps\fR,
+the latter being for servers that support TLS (SSL) encryption.
+If no
+\fIport\fR
+is specified, the default is port 389 for
+\(oqldap://\(cq
+or port 636 for
+\(oqldaps://\(cq.
+If no
+\fIhostname\fR
+is specified,
+\fBsudo\fR
+will connect to
+\fIlocalhost\fR.
+Multiple
+\fBURI\fR
+lines are treated identically to a
+\fBURI\fR
+line containing multiple entries.
+Only systems using the OpenSSL libraries support the mixing of
+\(oqldap://\(cq
+and
+\(oqldaps://\(cq
+URIs.
+Both the Netscape-derived and IBM LDAP libraries used on most commercial
+versions of Unix are only capable of supporting one or the other.
+.TP 6n
+\fBUSE_SASL\fR \fIon/true/yes/off/false/no\fR
+Enable
+\fBUSE_SASL\fR
+for LDAP servers that support SASL authentication.
+.TP 6n
+\fBROOTSASL_AUTH_ID\fR \fIidentity\fR
+The SASL user name to use when
+\fBROOTUSE_SASL\fR
+is enabled.
+.PP
+See the
+\fIldap.conf\fR
+entry in the
+\fIEXAMPLES\fR
+section.
+.SS "Configuring nsswitch.conf"
+Unless it is disabled at build time,
+\fBsudo\fR
+consults the Name Service Switch file,
+\fI@nsswitch_conf@\fR,
+to specify the
+\fIsudoers\fR
+search order.
+Sudo looks for a line beginning with
+\fIsudoers\fR:
+and uses this to determine the search order.
+By default,
+\fBsudo\fR
+does not stop searching after the first match and later matches take
+precedence over earlier ones (unless
+\(oq[SUCCESS=return]\(cq
+is used, see below).
+The following sources are recognized:
+.PP
+.RS 4n
+.PD 0
+.TP 7n
+files
+read sudoers from
+\fI@sysconfdir@/sudoers\fR
+.TP 7n
+ldap
+read sudoers from LDAP
+.RE
+.PD
+.PP
+In addition, a subset of
+\fInsswitch.conf\fR-style
+action statements is supported, specifically
+\(oq[SUCCESS=return]\(cq
+and
+\(oq[NOTFOUND=return]\(cq.
+These will unconditionally terminate the search if the user was either
+found
+\(oq[SUCCESS=return]\(cq
+or not found
+\(oq[NOTFOUND=return]\(cq
+in the immediately preceding source.
+Other action statements tokens are not supported, nor is test
+negation with
+\(oq\&!\(cq.
+.PP
+To consult LDAP first followed by the local sudoers file (if it
+exists), use:
+.nf
+.sp
+.RS 4n
+sudoers: ldap files
+.RE
+.fi
+.PP
+To consult LDAP only when no match is found in the local sudoers
+file (if it exists), use:
+.nf
+.sp
+.RS 4n
+sudoers: files [SUCCESS=return] ldap
+.RE
+.fi
+.PP
+The local
+\fIsudoers\fR
+file can be ignored completely by using:
+.nf
+.sp
+.RS 4n
+sudoers: ldap
+.RE
+.fi
+.PP
+If the
+\fI@nsswitch_conf@\fR
+file is not present or there is no sudoers line, the following
+default is assumed:
+.nf
+.sp
+.RS 4n
+sudoers: files
+.RE
+.fi
+.PP
+The
+\fI@nsswitch_conf@\fR
+file is supported even when the underlying operating system does not
+support it, except on AIX (see below).
+.SS "Configuring netsvc.conf"
+On AIX systems, the
+\fI@netsvc_conf@\fR
+file is consulted instead of
+\fI@nsswitch_conf@\fR.
+\fBsudo\fR
+simply treats
+\fInetsvc.conf\fR
+as a variant of
+\fInsswitch.conf\fR;
+information in the previous section unrelated to the file format
+itself still applies.
+.PP
+To consult LDAP first followed by the local sudoers file (if it
+exists), use:
+.nf
+.sp
+.RS 4n
+sudoers = ldap, files
+.RE
+.fi
+.PP
+The local
+\fIsudoers\fR
+file can be ignored completely by using:
+.nf
+.sp
+.RS 4n
+sudoers = ldap
+.RE
+.fi
+.PP
+To treat LDAP as authoritative and only use the local sudoers file
+if the user is not present in LDAP, use:
+.nf
+.sp
+.RS 4n
+sudoers = ldap = auth, files
+.RE
+.fi
+.PP
+In the above example, the
+\fIauth\fR
+qualifier only affects user lookups; both LDAP and
+\fIsudoers\fR
+will be queried for
+\fIDefaults\fR
+entries.
+.PP
+If the
+\fI@netsvc_conf@\fR
+file is not present or there is no sudoers line, the following
+default is assumed:
+.nf
+.sp
+.RS 4n
+sudoers = files
+.RE
+.fi
+.SS "Integration with sssd"
+On systems with the
+\fISystem Security Services Daemon\fR
+(SSSD) and where
+\fBsudo\fR
+has been built with SSSD support,
+it is possible to use SSSD to cache LDAP
+\fIsudoers\fR
+rules.
+To use SSSD as the
+\fIsudoers\fR
+source, you should use
+\fIsss\fR
+instead of
+\fIldap\fR
+for the sudoers entry in
+\fI@nsswitch_conf@\fR.
+The
+\fI@ldap_conf@\fR
+file is not used by the SSSD
+\fBsudo\fR
+back end.
+See
+sssd-sudo(@mansectform@)
+for more information on configuring
+\fBsudo\fR
+to work with SSSD.
+.SH "FILES"
+.TP 26n
+\fI@ldap_conf@\fR
+LDAP configuration file
+.TP 26n
+\fI@nsswitch_conf@\fR
+determines sudoers source order
+.TP 26n
+\fI@netsvc_conf@\fR
+determines sudoers source order on AIX
+.SH "EXAMPLES"
+.SS "Example ldap.conf"
+.nf
+.RS 2n
+# Either specify one or more URIs or one or more host:port pairs.
+# If neither is specified sudo will default to localhost, port 389.
+#
+#host ldapserver
+#host ldapserver1 ldapserver2:390
+#
+# Default port if host is specified without one, defaults to 389.
+#port 389
+#
+# URI will override the host and port settings.
+uri ldap://ldapserver
+#uri ldaps://secureldapserver
+#uri ldaps://secureldapserver ldap://ldapserver
+#
+# The amount of time, in seconds, to wait while trying to connect to
+# an LDAP server.
+bind_timelimit 30
+#
+# The amount of time, in seconds, to wait while performing an LDAP query.
+timelimit 30
+#
+# Must be set or sudo will ignore LDAP; may be specified multiple times.
+sudoers_base ou=SUDOers,dc=my-domain,dc=com
+#
+# verbose sudoers matching from ldap
+#sudoers_debug 2
+#
+# Enable support for time-based entries in sudoers.
+#sudoers_timed yes
+#
+# optional proxy credentials
+#binddn <who to search as>
+#bindpw <password>
+#rootbinddn <who to search as, uses /etc/ldap.secret for bindpw>
+#
+# LDAP protocol version, defaults to 3
+#ldap_version 3
+#
+# Define if you want to use an encrypted LDAP connection.
+# Typically, you must also set the port to 636 (ldaps).
+#ssl on
+#
+# Define if you want to use port 389 and switch to
+# encryption before the bind credentials are sent.
+# Only supported by LDAP servers that support the start_tls
+# extension such as OpenLDAP.
+#ssl start_tls
+#
+# Additional TLS options follow that allow tweaking of the
+# SSL/TLS connection.
+#
+#tls_checkpeer yes # verify server SSL certificate
+#tls_checkpeer no # ignore server SSL certificate
+#
+# If you enable tls_checkpeer, specify either tls_cacertfile
+# or tls_cacertdir. Only supported when using OpenLDAP.
+#
+#tls_cacertfile /etc/certs/trusted_signers.pem
+#tls_cacertdir /etc/certs
+#
+# For systems that don't have /dev/random
+# use this along with PRNGD or EGD.pl to seed the
+# random number pool to generate cryptographic session keys.
+# Only supported when using OpenLDAP.
+#
+#tls_randfile /etc/egd-pool
+#
+# You may restrict which ciphers are used. Consult your SSL
+# documentation for which options go here.
+# Only supported when using OpenLDAP.
+#
+#tls_ciphers <cipher-list>
+#
+# Sudo can provide a client certificate when communicating to
+# the LDAP server.
+# Tips:
+# * Enable both lines at the same time.
+# * Do not password protect the key file.
+# * Ensure the keyfile is only readable by root.
+#
+# For OpenLDAP:
+#tls_cert /etc/certs/client_cert.pem
+#tls_key /etc/certs/client_key.pem
+#
+# For Netscape-derived LDAP, tls_cert and tls_key may specify either
+# a directory, in which case the files in the directory must have the
+# default names (e.g., cert8.db and key4.db), or the path to the cert
+# and key files themselves. However, a bug in version 5.0 of the LDAP
+# SDK will prevent specific file names from working. For this reason
+# it is suggested that tls_cert and tls_key be set to a directory,
+# not a file name.
+#
+# The certificate database specified by tls_cert may contain CA certs
+# and/or the client's cert. If the client's cert is included, tls_key
+# should be specified as well.
+# For backward compatibility, "sslpath" may be used in place of tls_cert.
+#tls_cert /var/ldap
+#tls_key /var/ldap
+#
+# If using SASL authentication for LDAP (OpenSSL)
+# use_sasl yes
+# sasl_auth_id <SASL user name>
+# rootuse_sasl yes
+# rootsasl_auth_id <SASL user name for root access>
+# sasl_secprops none
+# krb5_ccname /etc/.ldapcache
+.RE
+.fi
+.SS "Sudoers schema for OpenLDAP"
+The following schema, in OpenLDAP format, is included with
+\fBsudo\fR
+source and binary distributions as
+\fIschema.OpenLDAP\fR.
+Simply copy
+it to the schema directory (e.g.,
+\fI/etc/openldap/schema\fR),
+add the proper
+\fIinclude\fR
+line in
+\fIslapd.conf\fR
+and restart
+\fBslapd\fR.
+Sites using the optional on-line configuration supported by OpenLDAP 2.3
+and higher should apply the
+\fIschema.olcSudo\fR
+file instead.
+.nf
+.sp
+.RS 2n
+attributetype ( 1.3.6.1.4.1.15953.9.1.1
+ NAME 'sudoUser'
+ DESC 'User(s) who may run sudo'
+ EQUALITY caseExactMatch
+ SUBSTR caseExactSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.2
+ NAME 'sudoHost'
+ DESC 'Host(s) who may run sudo'
+ EQUALITY caseExactIA5Match
+ SUBSTR caseExactIA5SubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.3
+ NAME 'sudoCommand'
+ DESC 'Command(s) to be executed by sudo'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.4
+ NAME 'sudoRunAs'
+ DESC 'User(s) impersonated by sudo'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.5
+ NAME 'sudoOption'
+ DESC 'Options(s) followed by sudo'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.6
+ NAME 'sudoRunAsUser'
+ DESC 'User(s) impersonated by sudo'
+ EQUALITY caseExactMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.7
+ NAME 'sudoRunAsGroup'
+ DESC 'Group(s) impersonated by sudo'
+ EQUALITY caseExactMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.8
+ NAME 'sudoNotBefore'
+ DESC 'Start of time interval for which the entry is valid'
+ EQUALITY generalizedTimeMatch
+ ORDERING generalizedTimeOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.9
+ NAME 'sudoNotAfter'
+ DESC 'End of time interval for which the entry is valid'
+ EQUALITY generalizedTimeMatch
+ ORDERING generalizedTimeOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.10
+ NAME 'sudoOrder'
+ DESC 'an integer to order the sudoRole entries'
+ EQUALITY integerMatch
+ ORDERING integerOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
+ DESC 'Sudoer Entries'
+ MUST ( cn )
+ MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $
+ sudoRunAsGroup $ sudoOption $ sudoNotBefore $ sudoNotAfter $
+ sudoOrder $ description )
+ )
+.RE
+.fi
+.SH "SEE ALSO"
+cvtsudoers(1),
+ldap.conf(@mansectform@),
+sssd-sudo(@mansectform@),
+sudo.conf(@mansectform@),
+sudoers(@mansectform@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS.md file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "CAVEATS"
+There are differences in the way that LDAP-based
+\fIsudoers\fR
+is parsed compared to file-based
+\fIsudoers\fR.
+See the
+\fIDifferences between LDAP and non-LDAP sudoers\fR
+section for more information.
+.SH "BUGS"
+If you believe you have found a bug in
+\fBsudo\fR,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudoers.ldap.mdoc.in b/docs/sudoers.ldap.mdoc.in
new file mode 100644
index 0000000..c1a63ea
--- /dev/null
+++ b/docs/sudoers.ldap.mdoc.in
@@ -0,0 +1,1653 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2003-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd June 7, 2023
+.Dt SUDOERS.LDAP @mansectform@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudoers.ldap
+.Nd sudo LDAP configuration
+.Sh DESCRIPTION
+In addition to the standard
+.Em sudoers
+file,
+.Nm sudo
+may be configured
+via LDAP.
+This can be especially useful for synchronizing
+.Em sudoers
+in a large, distributed environment.
+.Pp
+Using LDAP for
+.Em sudoers
+has several benefits:
+.Bl -bullet -width 1n
+.It
+.Nm sudo
+no longer needs to read
+.Em sudoers
+in its entirety.
+When LDAP is used, there are only two or three LDAP queries per invocation.
+This makes it especially fast and particularly usable in LDAP environments.
+.It
+It is possible to specify per-entry options that override the global
+default options.
+.Pa @sysconfdir@/sudoers
+only supports default options and limited options associated with
+user/host/commands/aliases.
+The syntax is complicated and can be difficult for users to understand.
+Placing the options directly in the entry is more natural.
+.It
+The
+.Nm visudo
+program is no longer needed.
+.Nm visudo
+provides locking and syntax checking of the
+.Pa @sysconfdir@/sudoers
+file.
+Since LDAP updates are atomic, locking is no longer necessary.
+Because syntax is checked when the data is inserted into LDAP, there
+is no need for a specialized tool to check syntax.
+.El
+.Ss SUDOers LDAP container
+The
+.Em sudoers
+configuration is contained in the
+.Ql ou=SUDOers
+LDAP container.
+.Pp
+Sudo first looks for the
+.Ql cn=defaults
+entry in the SUDOers container.
+If found, the multi-valued
+.Em sudoOption
+attribute is parsed in the same manner as a global
+.Em Defaults
+line in
+.Pa @sysconfdir@/sudoers .
+In the following example, the
+.Ev SSH_AUTH_SOCK
+variable will be preserved in the environment for all users.
+.Bd -literal -offset 4n
+dn: cn=defaults,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: env_keep+=SSH_AUTH_SOCK
+.Ed
+.Pp
+The equivalent of a sudoer in LDAP is a
+.Em sudoRole .
+It consists of the following attributes:
+.Bl -tag -width 4n
+.It Sy sudoUser
+A user name, user-ID (prefixed with
+.Ql # ) ,
+Unix group name or ID (prefixed with
+.Ql %
+or
+.Ql %#
+respectively), user netgroup (prefixed with
+.Ql + ) ,
+or non-Unix group name or ID (prefixed with
+.Ql %:
+or
+.Ql %:#
+respectively).
+User netgroups are matched using the user and domain members only;
+the host member is not used when matching.
+Non-Unix group support is only available when an appropriate
+.Em group_plugin
+is defined in the global
+.Em defaults
+.Em sudoRole
+object.
+If a
+.Em sudoUser
+entry is preceded by an exclamation point,
+.Ql \&! ,
+and the entry matches, the
+.Em sudoRole
+in which it resides will be ignored.
+Negated
+.Em sudoUser
+entries are only supported by version 1.9.9 or higher.
+.It Sy sudoHost
+A host name, IP address, IP network, or host netgroup (prefixed with a
+.Ql + ) .
+The special value
+.Sy ALL
+will match any host.
+Host netgroups are matched using the host (both qualified and unqualified)
+and domain members only; the user member is not used when matching.
+If a
+.Em sudoHost
+entry is preceded by an exclamation point,
+.Ql \&! ,
+and the entry matches, the
+.Em sudoRole
+in which it resides will be ignored.
+Negated
+.Em sudoHost
+entries are only supported by version 1.8.18 or higher.
+.It Sy sudoCommand
+A fully-qualified Unix command name with optional command line arguments,
+potentially including globbing characters (aka wild cards).
+If a command name is preceded by an exclamation point,
+.Ql \&! ,
+the user will be prohibited from running that command.
+.Pp
+The built-in command
+.Dq sudoedit
+is used to permit a user to run
+.Nm sudo
+with the
+.Fl e
+option (or as
+.Nm sudoedit ) .
+It may take command line arguments just as a normal command does.
+Unlike other commands,
+.Dq sudoedit
+is a built into
+.Nm sudo
+itself and must be specified in without a leading path.
+.Pp
+The special value
+.Sy ALL
+will match any command.
+.Pp
+If a command name is prefixed with a SHA-2 digest, it will
+only be allowed if the digest matches.
+This may be useful in situations where the user invoking
+.Nm sudo
+has write access to the command or its parent directory.
+The following digest formats are supported: sha224, sha256, sha384, and sha512.
+The digest name must be followed by a colon
+.Pq Ql :\&
+and then the actual digest, in either hex or base64 format.
+For example, given the following value for sudoCommand:
+.Bd -literal -offset 4n
+sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ /bin/ls
+.Ed
+.Pp
+The user may only run
+.Pa /bin/ls
+if its sha224 digest matches the specified value.
+Command digests are only supported by version 1.8.7 or higher.
+.It Sy sudoOption
+Identical in function to the global options described above, but
+specific to the
+.Em sudoRole
+in which it resides.
+.It Sy sudoRunAsUser
+A user name or user-ID (prefixed with
+.Ql # )
+that commands may be run as or a Unix group (prefixed with a
+.Ql % )
+or user netgroup (prefixed with a
+.Ql + )
+that contains a list of users that commands may be run as.
+The special value
+.Sy ALL
+will match any user.
+If a
+.Em sudoRunAsUser
+entry is preceded by an exclamation point,
+.Ql \&! ,
+and the entry matches, the
+.Em sudoRole
+in which it resides will be ignored.
+If
+.Em sudoRunAsUser
+is specified but empty, it will match the invoking user.
+If neither
+.Em sudoRunAsUser
+nor
+.Em sudoRunAsGroup
+are present, the value of the
+.Em runas_default
+.Em sudoOption
+is used (defaults to @runas_default@).
+.Pp
+The
+.Em sudoRunAsUser
+attribute is only available in
+.Nm sudo
+versions
+1.7.0 and higher.
+Older versions of
+.Nm sudo
+use the
+.Em sudoRunAs
+attribute instead.
+Negated
+.Em sudoRunAsUser
+entries are only supported by version 1.8.26 or higher.
+.It Sy sudoRunAsGroup
+A Unix group or group-ID (prefixed with
+.Ql # )
+that commands may be run as.
+The special value
+.Sy ALL
+will match any group.
+If a
+.Em sudoRunAsGroup
+entry is preceded by an exclamation point,
+.Ql \&! ,
+and the entry matches, the
+.Em sudoRole
+in which it resides will be ignored.
+.Pp
+The
+.Em sudoRunAsGroup
+attribute is only available in
+.Nm sudo
+versions
+1.7.0 and higher.
+Negated
+.Em sudoRunAsGroup
+entries are only supported by version 1.8.26 or higher.
+.It Sy sudoNotBefore
+A timestamp in the form
+.Ql yyyymmddHHMMSSZ
+that can be used to provide a start date/time for when the
+.Em sudoRole
+will be valid.
+If multiple
+.Em sudoNotBefore
+entries are present, the earliest is used.
+Timestamps must be in Coordinated Universal Time (UTC),
+not the local timezone.
+The minute and seconds portions are optional, but some LDAP servers
+require that they be present (contrary to the RFC).
+.Pp
+The
+.Em sudoNotBefore
+attribute is only available in
+.Nm sudo
+versions 1.7.5 and higher and must be explicitly enabled via the
+.Sy SUDOERS_TIMED
+option in
+.Pa @ldap_conf@ .
+.It Sy sudoNotAfter
+A timestamp in the form
+.Ql yyyymmddHHMMSSZ
+that indicates an expiration date/time, after which the
+.Em sudoRole
+will no longer be valid.
+If multiple
+.Em sudoNotAfter
+entries are present, the last one is used.
+Timestamps must be in Coordinated Universal Time (UTC),
+not the local timezone.
+The minute and seconds portions are optional, but some LDAP servers
+require that they be present (contrary to the RFC).
+.Pp
+The
+.Em sudoNotAfter
+attribute is only available in
+.Nm sudo
+versions
+1.7.5 and higher and must be explicitly enabled via the
+.Sy SUDOERS_TIMED
+option in
+.Pa @ldap_conf@ .
+.It Sy sudoOrder
+The
+.Em sudoRole
+entries retrieved from the LDAP directory have no inherent order.
+The
+.Em sudoOrder
+attribute is an integer (or floating point value for LDAP servers
+that support it) that is used to sort the matching entries.
+This allows LDAP-based sudoers entries to more closely mimic the behavior
+of the sudoers file, where the order of the entries influences the result.
+If multiple entries match, the entry with the highest
+.Em sudoOrder
+attribute is chosen.
+This corresponds to the
+.Dq last match
+behavior of the sudoers file.
+If the
+.Em sudoOrder
+attribute is not present, a value of 0 is assumed.
+.Pp
+The
+.Em sudoOrder
+attribute is only available in
+.Nm sudo
+versions 1.7.5 and higher.
+.El
+.Pp
+Each attribute listed above should contain a single value, but there
+may be multiple instances of each attribute type.
+A
+.Em sudoRole
+must contain at least one
+.Em sudoUser ,
+.Em sudoHost ,
+and
+.Em sudoCommand .
+.Pp
+The following example allows users in group wheel to run any command
+on any host via
+.Nm sudo :
+.Bd -literal -offset 4n
+dn: cn=%wheel,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: %wheel
+sudoUser: %wheel
+sudoHost: ALL
+sudoCommand: ALL
+.Ed
+.Ss Anatomy of LDAP sudoers lookup
+When looking up a sudoer using LDAP there are only two or three
+LDAP queries per invocation.
+The first query is to parse the global options.
+The second is to match against the user's name and the groups that
+the user belongs to.
+(The special
+.Sy ALL
+tag is matched in this query too.)
+If no match is returned for the user's name and groups, a third
+query returns all entries containing user netgroups and other
+non-Unix groups and checks to see if the user belongs to any of them.
+.Pp
+If timed entries are enabled with the
+.Sy SUDOERS_TIMED
+parameter, the LDAP queries include a sub-filter that limits retrieval
+to entries that satisfy the time constraints, if any.
+.Pp
+If the
+.Sy NETGROUP_BASE
+parameter is present and
+.Sy NETGROUP_QUERY
+has not been disabled (see
+.Sx Configuring ldap.conf
+below), queries are performed to determine the list of netgroups
+the user belongs to before the sudoers query.
+This makes it possible to include netgroups in the sudoers query
+string in the same manner as Unix groups.
+The third query mentioned above is not performed unless a group provider
+plugin is also configured.
+The actual LDAP queries performed by
+.Nm sudo
+are as follows:
+.Bl -enum
+.It
+Match all
+.Em nisNetgroup
+records with a
+.Em nisNetgroupTriple
+containing the user, host, and NIS domain.
+The query will match
+.Em nisNetgroupTriple
+entries with either the short or long form of the host name or
+no host name specified in the tuple.
+If the NIS domain is set, the query will match only match entries
+that include the domain or for which there is no domain present.
+If the NIS domain is
+.Em not
+set, a wildcard is used to match any domain name but be aware that the
+NIS schema used by some LDAP servers may not support wild cards for
+.Em nisNetgroupTriple .
+.It
+Repeated queries are performed to find any nested
+.Em nisNetgroup
+records with a
+.Em memberNisNetgroup
+entry that refers to an already-matched record.
+.El
+.Pp
+For sites with a large number of netgroups, using
+.Sy NETGROUP_BASE
+can significantly speed up
+.Nm sudo Ns 's
+execution time as long as the LDAP server supports querying the
+.Em nisNetgroup
+object by its
+.Em nisNetgroupTriple
+attribute.
+.Ss Differences between LDAP and non-LDAP sudoers
+One of the major differences between LDAP and file-based
+.Em sudoers
+is that in LDAP,
+.Nm sudo Ns -specific
+Aliases are not supported.
+.Pp
+For the most part, there is little need for
+.Nm sudo Ns -specific
+Aliases.
+Unix groups, non-Unix groups (via the
+.Em group_plugin ) ,
+or user netgroups can be used in place of User_Aliases and Runas_Aliases.
+Host netgroups can be used in place of Host_Aliases.
+Since groups and netgroups can also be stored in LDAP there is no real need for
+.Nm sudo Ns -specific
+aliases.
+.Pp
+There are also some subtle differences in the way sudoers is handled
+once in LDAP.
+Probably the biggest is that according to the RFC, LDAP ordering
+is arbitrary and you cannot expect that Attributes and Entries are
+returned in any specific order.
+.Pp
+The order in which different entries are applied can be controlled
+using the
+.Em sudoOrder
+attribute, but there is no way to guarantee the order of attributes
+within a specific entry.
+If there are conflicting command rules in an entry, the negative
+takes precedence.
+This is called paranoid behavior (not necessarily the most specific
+match).
+.Pp
+Here is an example:
+.Bd -literal -offset 4n
+# /etc/sudoers:
+# Allow all commands except shell
+johnny ALL=(root) ALL,!/bin/sh
+# Always allows all commands because ALL is matched last
+puddles ALL=(root) !/bin/sh,ALL
+
+# LDAP equivalent of johnny
+# Allows all commands except shell
+dn: cn=role1,ou=Sudoers,dc=my-domain,dc=com
+objectClass: sudoRole
+objectClass: top
+cn: role1
+sudoUser: johnny
+sudoHost: ALL
+sudoCommand: ALL
+sudoCommand: !/bin/sh
+
+# LDAP equivalent of puddles
+# Notice that even though ALL comes last, it still behaves like
+# role1 since the LDAP code assumes the more paranoid configuration
+dn: cn=role2,ou=Sudoers,dc=my-domain,dc=com
+objectClass: sudoRole
+objectClass: top
+cn: role2
+sudoUser: puddles
+sudoHost: ALL
+sudoCommand: !/bin/sh
+sudoCommand: ALL
+.Ed
+.Ss Converting between file-based and LDAP sudoers
+The
+.Xr cvtsudoers 1
+utility can be used to convert between file-based and LDAP
+.Em sudoers .
+However, there are features in the file-based sudoers that have
+no equivalent in LDAP-based sudoers (and vice versa).
+These cannot be converted automatically.
+.Pp
+For example, a Cmnd_Alias in a
+.Em sudoers
+file may be converted to a
+.Em sudoRole
+that contains multiple commands.
+Multiple users and/or groups may be assigned to the
+.Em sudoRole .
+.Pp
+Also, host, user, runas, and command-based
+.Em Defaults
+entries are not supported.
+However, a
+.Em sudoRole
+may contain one or more
+.Em sudoOption
+attributes which can often serve the same purpose.
+.Pp
+Consider the following
+.Em sudoers
+lines:
+.Bd -literal -offset 4n
+Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less
+Defaults!PAGERS noexec
+alice, bob ALL = ALL
+.Ed
+.Pp
+In this example, alice and bob are allowed to run all commands, but
+the commands listed in PAGERS will have the noexec flag set,
+preventing shell escapes.
+.Pp
+When converting this to LDAP, two sudoRole objects can be used:
+.Bd -literal -offset 4n
+dn: cn=PAGERS,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: PAGERS
+sudoUser: alice
+sudoUser: bob
+sudoHost: ALL
+sudoCommand: /usr/bin/more
+sudoCommand: /usr/bin/pg
+sudoCommand: /usr/bin/less
+sudoOption: noexec
+sudoOrder: 900
+
+dn: cn=ADMINS,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: ADMINS
+sudoUser: alice
+sudoUser: bob
+sudoHost: ALL
+sudoCommand: ALL
+sudoOrder: 100
+.Ed
+.Pp
+In the LDAP version, the sudoOrder attribute is used to guarantee
+that the PAGERS sudoRole with
+.Em noexec
+has precedence.
+Unlike the
+.Em sudoers
+version, the LDAP version requires that all users for whom the restriction
+should apply be assigned to the PAGERS sudoRole.
+Using a Unix group or netgroup in PAGERS rather than listing each
+user would make this easier to maintain.
+.Pp
+Per-user
+.Em Defaults
+entries can be emulated by using one or more sudoOption attributes
+in a sudoRole.
+Consider the following
+.Em sudoers
+lines:
+.Bd -literal -offset 4n
+User_Alias ADMINS = john, sally
+Defaults:ADMINS !authenticate
+ADMINS ALL = (ALL:ALL) ALL
+.Ed
+.Pp
+In this example, john and sally are allowed to run any command
+as any user or group.
+.Pp
+When converting this to LDAP, we can use a Unix group instead
+of the User_Alias.
+.Bd -literal -offset 4n
+dn: cn=admins,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: admins
+sudoUser: %admin
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOption: !authenticate
+.Ed
+.Pp
+This assumes that users john and sally are members of the
+.Dq admins
+Unix group.
+.Ss Sudoers schema
+In order to use
+.Nm sudo Ns 's
+LDAP support, the
+.Nm sudo
+schema must be
+installed on your LDAP server.
+In addition, be sure to index the
+.Em sudoUser
+attribute.
+.Pp
+The
+.Nm sudo
+distribution includes versions of the
+.Nm sudoers
+schema for multiple LDAP servers:
+.Bl -tag -width 4n
+.It Pa schema.OpenLDAP
+OpenLDAP slapd and
+.Ox
+ldapd
+.It Pa schema.olcSudo
+OpenLDAP slapd 2.3 and higher when on-line configuration is enabled
+.It Pa schema.iPlanet
+Netscape-derived servers such as the iPlanet, Oracle,
+and 389 Directory Servers
+.It Pa schema.ActiveDirectory
+Microsoft Active Directory
+.El
+.Pp
+The schema in OpenLDAP format is also included in the
+.Sx EXAMPLES
+section.
+.Ss Configuring ldap.conf
+Sudo reads the
+.Pa @ldap_conf@
+file for LDAP-specific configuration.
+Typically, this file is shared between different LDAP-aware clients.
+As such, most of the settings are not
+.Nm sudo Ns -specific.
+The
+.Pa @ldap_conf@
+file is parsed by
+.Nm sudo
+itself and may support options that differ from those described in the
+system's
+.Xr ldap.conf @mansectform@
+manual.
+The path to
+.Pa ldap.conf
+may be overridden via the
+.Em ldap_conf
+plugin argument in
+.Xr sudo.conf @mansectform@ .
+.Pp
+On systems using the OpenLDAP libraries, default values specified in
+.Pa /etc/openldap/ldap.conf
+or the user's
+.Pa .ldaprc
+files are not used.
+.Pp
+.Nm sudo
+supports a variety of LDAP library implementations, including
+OpenLDAP, Netscape-derived (also used by Solaris and HP-UX), and
+IBM LDAP (aka Tivoli).
+Some options are specific to certain LDAP implementations or have
+implementation-specific behavior.
+These differences are noted below where applicable.
+.Pp
+Only those options explicitly listed in
+.Pa @ldap_conf@
+as being supported by
+.Nm sudo
+are honored.
+Configuration options are listed below in upper case but are parsed
+in a case-independent manner.
+.Pp
+Lines beginning with a pound sign
+.Pq Ql #
+are ignored.
+Leading white space is removed from the beginning of lines.
+.Bl -tag -width 4n
+.It Sy BIND_TIMELIMIT Ar seconds
+The
+.Sy BIND_TIMELIMIT
+parameter specifies the amount of time, in seconds, to wait while trying
+to connect to an LDAP server.
+If multiple
+.Sy URI Ns s
+or
+.Sy HOST Ns s
+are specified, this is the amount of time to wait before trying
+the next one in the list.
+.It Sy BINDDN Ar DN
+The
+.Sy BINDDN
+parameter specifies the identity, in the form of a Distinguished Name (DN),
+to use when performing LDAP operations.
+If not specified, LDAP operations are performed with an anonymous identity.
+By default, most LDAP servers will allow anonymous access.
+.It Sy BINDPW Ar secret
+The
+.Sy BINDPW
+parameter specifies the password to use when performing LDAP operations.
+This is typically used in conjunction with the
+.Sy BINDDN
+parameter.
+The
+.Ar secret
+may be a plaintext password or a base64-encoded string with a
+.Dq base64:
+prefix.
+For example:
+.Bd -literal -offset 4n
+BINDPW base64:dGVzdA==
+.Ed
+.Pp
+If a plaintext password is used, it should be a simple string without quotes.
+Plain text passwords may not include the comment character
+.Pq Ql #
+and the escaping of special characters with a backslash
+.Pq Ql \e
+is not supported.
+.It Sy DEREF Ar never/searching/finding/always
+How alias dereferencing is to be performed when searching.
+See the
+.Xr ldap.conf @mansectform@
+manual for a full description of this option.
+.It Sy HOST Ar name[:port] ...
+If no
+.Sy URI
+is specified (see below), the
+.Sy HOST
+parameter specifies a white space-delimited list of LDAP servers to connect to.
+Each host may include an optional
+.Em port
+separated by a colon
+.Pq Ql :\& .
+The
+.Sy HOST
+parameter is deprecated in favor of the
+.Sy URI
+specification and is included for backward compatibility only.
+.It Sy KRB5_CCNAME Ar file name
+The path to the Kerberos 5 credential cache to use when authenticating
+with the remote server.
+.Pp
+This option is only relevant when using SASL authentication (see below).
+.It Sy LDAP_VERSION Ar number
+The version of the LDAP protocol to use when connecting to the server.
+The default value is protocol version 3.
+.It Sy NETGROUP_BASE Ar base
+The base DN to use when performing LDAP netgroup queries.
+Typically this is of the form
+.Ql ou=netgroup,dc=my-domain,dc=com
+for the domain my-domain.com.
+Multiple
+.Sy NETGROUP_BASE
+lines may be specified, in which case they are queried in the order specified.
+.Pp
+When this option is enabled,
+.Nm sudo
+will query the LDAP server directly when matching netgroups present in a
+.Em sudoRole
+instead of relying on the C library's
+.Fn innetgr
+function.
+.Pp
+Additionally, if the
+.Sy NETGROUP_QUERY
+parameter (which is enabled by default) has not been disabled, the
+user's netgroups will be queried directly via LDAP for use in the
+main sudoers query.
+This is usually faster than fetching every
+.Em sudoRole
+object containing a
+.Em sudoUser
+that begins with a
+.Ql +
+prefix and checking whether the user is a member of each one.
+The NIS schema used by some LDAP servers needs a modification to
+support querying the
+.Em nisNetgroup
+object by its
+.Em nisNetgroupTriple
+attribute.
+For example, OpenLDAP's
+.Sy slapd
+requires the following change to the
+.Em nisNetgroupTriple
+attribute:
+.Bd -literal -offset 4n
+attributetype ( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple'
+ DESC 'Netgroup triple'
+ EQUALITY caseIgnoreIA5Match
+ SUBSTR caseIgnoreIA5SubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+.Ed
+.Pp
+Before enabling
+.Sy NETGROUP_BASE ,
+you should verify that your LDAP server supports matching
+.Em nisNetgroupTriple .
+For example, using
+.Sy ldapsearch :
+.Bd -literal -offset 4n
+$ ldapsearch -b $NETGROUP_BASE \e
+ '(&(objectClass=nisNetgroup)(nisNetgroupTriple=\e28*,USER,\e29))'
+.Ed
+.Pp
+where your
+.Em nisNetgroup
+data includes an object with the following
+.Em nisNetgroupTriple :
+.Pp
+.Dl nisNetgroupTriple: (,USER,)
+.It Sy NETGROUP_QUERY Ar on/true/yes/off/false/no
+The
+.Sy NETGROUP_QUERY
+parameter indicates whether or not the LDAP server supports querying
+.Em nisNetgroup
+objects by matching on
+.Em nisNetgroupTriple
+attributes.
+By default,
+.Nm sudoers
+expects to be able to perform queries that match on
+.Em nisNetgroupTriple
+attributes when
+.Sy NETGROUP_BASE
+is set, but not all LDAP servers support this.
+.Pp
+If
+.Sy NETGROUP_QUERY
+is disabled,
+.Nm sudoers
+will not attempt to determine the list of netgroups the user belongs
+to, but will still use
+.Sy NETGROUP_BASE
+directly when matching netgroups.
+This can be used to support netgroups on systems that lack the
+.Fn innetgr
+C library function.
+See the description of the
+.Sy NETGROUP_BASE
+parameter for more information.
+.It Sy NETGROUP_SEARCH_FILTER Ar ldap_filter
+An LDAP filter which is used to restrict the set of records returned
+when performing an LDAP netgroup query.
+Typically, this is of the form
+.Ql attribute=value
+or
+.Ql (&(attribute=value)(attribute2=value2)) .
+The default search filter is:
+.Ql objectClass=nisNetgroup .
+If
+.Ar ldap_filter
+is omitted, no search filter will be used.
+.Pp
+This option is only used when querying netgroups directly via LDAP.
+.It Sy NETWORK_TIMEOUT Ar seconds
+An alias for
+.Sy BIND_TIMELIMIT
+provided for OpenLDAP compatibility.
+.It Sy PORT Ar port_number
+If no
+.Sy URI
+is specified, the
+.Sy PORT
+parameter specifies the default port to connect to on the LDAP server if a
+.Sy HOST
+parameter does not specify the port itself.
+If no
+.Sy PORT
+parameter is used, the default is port 389 for LDAP and port 636 for LDAP
+over TLS (SSL).
+The
+.Sy PORT
+parameter is deprecated in favor of the
+.Sy URI
+specification and is included for backward compatibility only.
+.It Sy ROOTBINDDN Ar DN
+The
+.Sy ROOTBINDDN
+parameter specifies the identity, in the form of a Distinguished Name (DN),
+to use when performing privileged LDAP operations, such as
+.Em sudoers
+queries.
+The password corresponding to the identity should be stored in the
+or the path specified by the
+.Em ldap_secret
+plugin argument in
+.Xr sudo.conf @mansectform@ ,
+which defaults to
+.Pa @ldap_secret@ .
+If no
+.Sy ROOTBINDDN
+is specified, the
+.Sy BINDDN
+identity is used (if any).
+.It Sy ROOTUSE_SASL Ar on/true/yes/off/false/no
+Enable
+.Sy ROOTUSE_SASL
+to enable SASL authentication when connecting
+to an LDAP server from a privileged process, such as
+.Nm sudo .
+.It Sy SASL_AUTH_ID Ar identity
+The SASL user name to use when connecting to the LDAP server.
+By default,
+.Nm sudo
+will use an anonymous connection.
+.Pp
+This option is only relevant when using SASL authentication.
+.It Sy SASL_MECH Ar mechanisms
+A white space-delimited list of SASL authentication mechanisms to use.
+By default,
+.Nm sudo
+will use
+.Dv GSSAPI
+authentication.
+.It Sy SASL_SECPROPS Ar none/properties
+SASL security properties or
+.Em none
+for no properties.
+See the SASL programmer's manual for details.
+.Pp
+This option is only relevant when using SASL authentication.
+.It Sy SSL Ar on/true/yes/off/false/no
+If the
+.Sy SSL
+parameter is set to
+.Em on ,
+.Em true ,
+or
+.Em yes
+TLS (SSL) encryption is always used when communicating with the LDAP server.
+Typically, this involves connecting to the server on port 636 (ldaps).
+.It Sy SSL Ar start_tls
+If the
+.Sy SSL
+parameter is set to
+.Em start_tls ,
+the LDAP server connection is initiated normally and TLS encryption is
+begun before the bind credentials are sent.
+This has the advantage of not requiring a dedicated port for encrypted
+communications.
+This parameter is only supported by LDAP servers that honor the
+.Em start_tls
+extension, such as the OpenLDAP and IBM Tivoli Directory servers.
+.It Sy SUDOERS_BASE Ar base
+The base DN to use when performing
+.Nm sudo
+LDAP queries.
+Typically this is of the form
+.Ql ou=SUDOers,dc=my-domain,dc=com
+for the domain my-domain.com.
+Multiple
+.Sy SUDOERS_BASE
+lines may be specified, in which case they are queried in the order specified.
+.It Sy SUDOERS_DEBUG Ar debug_level
+This sets the debug level for
+.Nm sudo
+LDAP queries.
+Debugging information is printed to the standard error.
+A value of 1 results in a moderate amount of debugging information.
+A value of 2 shows the results of the matches themselves.
+This parameter should not be set in a production environment as the
+extra information is likely to confuse users.
+.Pp
+The
+.Sy SUDOERS_DEBUG
+parameter is deprecated and will be removed in a future release.
+The same information is now logged via the
+.Nm sudo
+debugging framework using the
+.Dq ldap
+subsystem at priorities
+.Em diag
+and
+.Em info
+for
+.Em debug_level
+values 1 and 2 respectively.
+See the
+.Xr sudo.conf @mansectform@
+manual for details on how to configure
+.Nm sudo
+debugging.
+.It Sy SUDOERS_SEARCH_FILTER Ar ldap_filter
+An LDAP filter which is used to restrict the set of records returned
+when performing a
+.Nm sudo
+LDAP query.
+Typically, this is of the
+form
+.Ql attribute=value
+or
+.Ql (&(attribute=value)(attribute2=value2)) .
+The default search filter is:
+.Ql objectClass=sudoRole .
+If
+.Ar ldap_filter
+is omitted, no search filter will be used.
+.It Sy SUDOERS_TIMED Ar on/true/yes/off/false/no
+Whether or not to evaluate the
+.Em sudoNotBefore
+and
+.Em sudoNotAfter
+attributes that implement time-dependent sudoers entries.
+.It Sy TIMELIMIT Ar seconds
+The
+.Sy TIMELIMIT
+parameter specifies the amount of time, in seconds, to wait for a
+response to an LDAP query.
+.It Sy TIMEOUT Ar seconds
+The
+.Sy TIMEOUT
+parameter specifies the amount of time, in seconds, to wait for a
+response from the various LDAP APIs.
+.It Sy TLS_CACERT Ar file name
+An alias for
+.Sy TLS_CACERTFILE
+for OpenLDAP compatibility.
+.It Sy TLS_CACERTFILE Ar file name
+The path to a certificate authority bundle which contains the certificates
+for all the Certificate Authorities the client knows to be valid, e.g.,
+.Pa /etc/ssl/ca-bundle.pem .
+.Pp
+This option is only supported by the OpenLDAP libraries.
+Netscape-derived LDAP libraries use the same certificate
+database for CA and client certificates (see
+.Sy TLS_CERT ) .
+.It Sy TLS_CACERTDIR Ar directory
+Similar to
+.Sy TLS_CACERTFILE
+but instead of a file, it is a directory containing individual
+Certificate Authority certificates, e.g.,
+.Pa /etc/ssl/certs .
+The directory specified by
+.Sy TLS_CACERTDIR
+is checked after
+.Sy TLS_CACERTFILE .
+.Pp
+This option is only supported by the OpenLDAP libraries.
+.It Sy TLS_CERT Ar file name
+The path to a file containing the client certificate which can
+be used to authenticate the client to the LDAP server.
+The certificate type depends on the LDAP libraries used.
+.Bl -tag -width 4n
+.It OpenLDAP:
+.Ql tls_cert /etc/ssl/client_cert.pem
+.It Netscape-derived:
+.Ql tls_cert /var/ldap/cert7.db
+.It IBM LDAP:
+Unused, the key database specified by
+.Sy TLS_KEY
+contains both keys and certificates.
+.El
+.Pp
+When using Netscape-derived libraries, this file may also contain
+Certificate Authority certificates.
+.It Sy TLS_CHECKPEER Ar on/true/yes/off/false/no
+If enabled,
+.Sy TLS_CHECKPEER
+will cause the LDAP server's TLS certificated to be verified.
+If the server's TLS certificate cannot be verified (usually because it
+is signed by an unknown certificate authority),
+.Nm sudo
+will be unable to connect to it.
+If
+.Sy TLS_CHECKPEER
+is disabled, no check is made.
+Disabling this check creates an opportunity for man-in-the-middle
+attacks since the server's identity will not be authenticated.
+If possible, the CA's certificate should be installed locally so it can
+be verified.
+.Pp
+This option is not supported by the IBM LDAP libraries.
+.It Sy TLS_KEY Ar file name
+The path to a file containing the private key which matches the
+certificate specified by
+.Sy TLS_CERT .
+The private key must not be password-protected.
+The key type depends on the LDAP libraries used.
+.Bl -tag -width 4n
+.It OpenLDAP:
+.Ql tls_key /etc/ssl/client_key.pem
+.It Netscape-derived:
+.Ql tls_key /var/ldap/key3.db
+.It IBM LDAP:
+.Ql tls_key /usr/ldap/ldapkey.kdb
+.El
+.Pp
+When using IBM LDAP libraries, this file may also contain
+Certificate Authority and client certificates and may be encrypted.
+.It Sy TLS_CIPHERS Ar cipher list
+The
+.Sy TLS_CIPHERS
+parameter allows the administer to restrict which encryption algorithms
+may be used for TLS (SSL) connections.
+See the OpenLDAP or IBM Tivoli Directory Server manual for a list of valid
+ciphers.
+.Pp
+This option is not supported by Netscape-derived libraries.
+.It Sy TLS_KEYPW Ar secret
+The
+.Sy TLS_KEYPW
+contains the password used to decrypt the key database on clients
+using the IBM LDAP library.
+The
+.Ar secret
+may be a plaintext password or a base64-encoded string with a
+.Dq base64:
+prefix.
+For example:
+.Bd -literal -offset 4n
+TLS_KEYPW base64:dGVzdA==
+.Ed
+.Pp
+If a plaintext password is used, it should be a simple string without quotes.
+Plain text passwords may not include the comment character
+.Pq Ql #
+and the escaping of special characters with a backslash
+.Pq Ql \e
+is not supported.
+If this option is used,
+.Pa @ldap_conf@
+must not be world-readable to avoid exposing the password.
+Alternately, a
+.Em stash file
+can be used to store the password in encrypted form (see below).
+.Pp
+If no
+.Sy TLS_KEYPW
+is specified, a
+.Em stash file
+will be used if it exists.
+The
+.Em stash file
+must have the same path as the file specified by
+.Sy TLS_KEY ,
+but use a
+.Ql .sth
+file extension instead of
+.Ql .kdb ,
+for example
+.Ql ldapkey.sth .
+The default
+.Ql ldapkey.kdb
+that ships with the IBM Tivoli Directory Server is encrypted with the password
+.Ql ssl_password .
+The
+.Em gsk8capicmd
+utility can be used to manage the key database and create a
+.Em stash file .
+.Pp
+This option is only supported by the IBM LDAP libraries.
+.It Sy TLS_REQCERT Ar level
+The
+.Sy TLS_REQCERT
+parameter controls how the LDAP server's TLS certificated will be
+verified (if at all).
+If the server's TLS certificate cannot be verified (usually because it
+is signed by an unknown certificate authority),
+.Nm sudo
+will be unable to connect to it.
+The following
+.Ar level
+values are supported:
+.Bl -tag -width 4n -offset 4n
+.It never
+The server certificate will not be requested or checked.
+.It allow
+The server certificate will be requested.
+A missing or invalid certificate is ignored and not considered an error.
+.It try
+The server certificate will be requested.
+A missing certificate is ignored but an invalid certificate will
+result in a connection error.
+.It demand | Ar hard
+The server certificate will be requested.
+A missing or invalid certificate will result in a connection error.
+This is the default behavior.
+.El
+.Pp
+This option is only supported by the OpenLDAP libraries.
+Other LDAP libraries only support the
+.Sy TLS_CHECKPEER
+parameter.
+.It Sy TLS_RANDFILE Ar file name
+The
+.Sy TLS_RANDFILE
+parameter specifies the path to an entropy source for systems that lack
+a random device.
+It is generally used in conjunction with
+.Em prngd
+or
+.Em egd .
+.Pp
+This option is only supported by the OpenLDAP libraries.
+.It Sy URI Ar ldap[s]://[hostname[:port]] ...
+Specifies a white space-delimited list of one or more URIs describing
+the LDAP server(s) to connect to.
+The
+.Em protocol
+may be either
+.Em ldap
+.Em ldaps ,
+the latter being for servers that support TLS (SSL) encryption.
+If no
+.Em port
+is specified, the default is port 389 for
+.Ql ldap://
+or port 636 for
+.Ql ldaps:// .
+If no
+.Em hostname
+is specified,
+.Nm sudo
+will connect to
+.Em localhost .
+Multiple
+.Sy URI
+lines are treated identically to a
+.Sy URI
+line containing multiple entries.
+Only systems using the OpenSSL libraries support the mixing of
+.Ql ldap://
+and
+.Ql ldaps://
+URIs.
+Both the Netscape-derived and IBM LDAP libraries used on most commercial
+versions of Unix are only capable of supporting one or the other.
+.It Sy USE_SASL Ar on/true/yes/off/false/no
+Enable
+.Sy USE_SASL
+for LDAP servers that support SASL authentication.
+.It Sy ROOTSASL_AUTH_ID Ar identity
+The SASL user name to use when
+.Sy ROOTUSE_SASL
+is enabled.
+.El
+.Pp
+See the
+.Pa ldap.conf
+entry in the
+.Sx EXAMPLES
+section.
+.Ss Configuring nsswitch.conf
+Unless it is disabled at build time,
+.Nm sudo
+consults the Name Service Switch file,
+.Pa @nsswitch_conf@ ,
+to specify the
+.Em sudoers
+search order.
+Sudo looks for a line beginning with
+.Em sudoers :
+and uses this to determine the search order.
+By default,
+.Nm sudo
+does not stop searching after the first match and later matches take
+precedence over earlier ones (unless
+.Ql [SUCCESS=return]
+is used, see below).
+The following sources are recognized:
+.Pp
+.Bl -tag -width "files" -offset 4n -compact
+.It files
+read sudoers from
+.Pa @sysconfdir@/sudoers
+.It ldap
+read sudoers from LDAP
+.El
+.Pp
+In addition, a subset of
+.Pa nsswitch.conf Ns -style
+action statements is supported, specifically
+.Ql [SUCCESS=return]
+and
+.Ql [NOTFOUND=return] .
+These will unconditionally terminate the search if the user was either
+found
+.Ql [SUCCESS=return]
+or not found
+.Ql [NOTFOUND=return]
+in the immediately preceding source.
+Other action statements tokens are not supported, nor is test
+negation with
+.Ql \&! .
+.Pp
+To consult LDAP first followed by the local sudoers file (if it
+exists), use:
+.Bd -literal -offset 4n
+sudoers: ldap files
+.Ed
+.Pp
+To consult LDAP only when no match is found in the local sudoers
+file (if it exists), use:
+.Bd -literal -offset 4n
+sudoers: files [SUCCESS=return] ldap
+.Ed
+.Pp
+The local
+.Em sudoers
+file can be ignored completely by using:
+.Bd -literal -offset 4n
+sudoers: ldap
+.Ed
+.Pp
+If the
+.Pa @nsswitch_conf@
+file is not present or there is no sudoers line, the following
+default is assumed:
+.Bd -literal -offset 4n
+sudoers: files
+.Ed
+.Pp
+The
+.Pa @nsswitch_conf@
+file is supported even when the underlying operating system does not
+support it, except on AIX (see below).
+.Ss Configuring netsvc.conf
+On AIX systems, the
+.Pa @netsvc_conf@
+file is consulted instead of
+.Pa @nsswitch_conf@ .
+.Nm sudo
+simply treats
+.Pa netsvc.conf
+as a variant of
+.Pa nsswitch.conf ;
+information in the previous section unrelated to the file format
+itself still applies.
+.Pp
+To consult LDAP first followed by the local sudoers file (if it
+exists), use:
+.Bd -literal -offset 4n
+sudoers = ldap, files
+.Ed
+.Pp
+The local
+.Em sudoers
+file can be ignored completely by using:
+.Bd -literal -offset 4n
+sudoers = ldap
+.Ed
+.Pp
+To treat LDAP as authoritative and only use the local sudoers file
+if the user is not present in LDAP, use:
+.Bd -literal -offset 4n
+sudoers = ldap = auth, files
+.Ed
+.Pp
+In the above example, the
+.Em auth
+qualifier only affects user lookups; both LDAP and
+.Em sudoers
+will be queried for
+.Em Defaults
+entries.
+.Pp
+If the
+.Pa @netsvc_conf@
+file is not present or there is no sudoers line, the following
+default is assumed:
+.Bd -literal -offset 4n
+sudoers = files
+.Ed
+.Ss Integration with sssd
+On systems with the
+.Em System Security Services Daemon
+(SSSD) and where
+.Nm sudo
+has been built with SSSD support,
+it is possible to use SSSD to cache LDAP
+.Em sudoers
+rules.
+To use SSSD as the
+.Em sudoers
+source, you should use
+.Em sss
+instead of
+.Em ldap
+for the sudoers entry in
+.Pa @nsswitch_conf@ .
+The
+.Pa @ldap_conf@
+file is not used by the SSSD
+.Nm sudo
+back end.
+See
+.Xr sssd-sudo @mansectform@
+for more information on configuring
+.Nm sudo
+to work with SSSD.
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @ldap_conf@
+LDAP configuration file
+.It Pa @nsswitch_conf@
+determines sudoers source order
+.It Pa @netsvc_conf@
+determines sudoers source order on AIX
+.El
+.Sh EXAMPLES
+.Ss Example ldap.conf
+.Bd -literal -offset 2n
+# Either specify one or more URIs or one or more host:port pairs.
+# If neither is specified sudo will default to localhost, port 389.
+#
+#host ldapserver
+#host ldapserver1 ldapserver2:390
+#
+# Default port if host is specified without one, defaults to 389.
+#port 389
+#
+# URI will override the host and port settings.
+uri ldap://ldapserver
+#uri ldaps://secureldapserver
+#uri ldaps://secureldapserver ldap://ldapserver
+#
+# The amount of time, in seconds, to wait while trying to connect to
+# an LDAP server.
+bind_timelimit 30
+#
+# The amount of time, in seconds, to wait while performing an LDAP query.
+timelimit 30
+#
+# Must be set or sudo will ignore LDAP; may be specified multiple times.
+sudoers_base ou=SUDOers,dc=my-domain,dc=com
+#
+# verbose sudoers matching from ldap
+#sudoers_debug 2
+#
+# Enable support for time-based entries in sudoers.
+#sudoers_timed yes
+#
+# optional proxy credentials
+#binddn <who to search as>
+#bindpw <password>
+#rootbinddn <who to search as, uses /etc/ldap.secret for bindpw>
+#
+# LDAP protocol version, defaults to 3
+#ldap_version 3
+#
+# Define if you want to use an encrypted LDAP connection.
+# Typically, you must also set the port to 636 (ldaps).
+#ssl on
+#
+# Define if you want to use port 389 and switch to
+# encryption before the bind credentials are sent.
+# Only supported by LDAP servers that support the start_tls
+# extension such as OpenLDAP.
+#ssl start_tls
+#
+# Additional TLS options follow that allow tweaking of the
+# SSL/TLS connection.
+#
+#tls_checkpeer yes # verify server SSL certificate
+#tls_checkpeer no # ignore server SSL certificate
+#
+# If you enable tls_checkpeer, specify either tls_cacertfile
+# or tls_cacertdir. Only supported when using OpenLDAP.
+#
+#tls_cacertfile /etc/certs/trusted_signers.pem
+#tls_cacertdir /etc/certs
+#
+# For systems that don't have /dev/random
+# use this along with PRNGD or EGD.pl to seed the
+# random number pool to generate cryptographic session keys.
+# Only supported when using OpenLDAP.
+#
+#tls_randfile /etc/egd-pool
+#
+# You may restrict which ciphers are used. Consult your SSL
+# documentation for which options go here.
+# Only supported when using OpenLDAP.
+#
+#tls_ciphers <cipher-list>
+#
+# Sudo can provide a client certificate when communicating to
+# the LDAP server.
+# Tips:
+# * Enable both lines at the same time.
+# * Do not password protect the key file.
+# * Ensure the keyfile is only readable by root.
+#
+# For OpenLDAP:
+#tls_cert /etc/certs/client_cert.pem
+#tls_key /etc/certs/client_key.pem
+#
+# For Netscape-derived LDAP, tls_cert and tls_key may specify either
+# a directory, in which case the files in the directory must have the
+# default names (e.g., cert8.db and key4.db), or the path to the cert
+# and key files themselves. However, a bug in version 5.0 of the LDAP
+# SDK will prevent specific file names from working. For this reason
+# it is suggested that tls_cert and tls_key be set to a directory,
+# not a file name.
+#
+# The certificate database specified by tls_cert may contain CA certs
+# and/or the client's cert. If the client's cert is included, tls_key
+# should be specified as well.
+# For backward compatibility, "sslpath" may be used in place of tls_cert.
+#tls_cert /var/ldap
+#tls_key /var/ldap
+#
+# If using SASL authentication for LDAP (OpenSSL)
+# use_sasl yes
+# sasl_auth_id <SASL user name>
+# rootuse_sasl yes
+# rootsasl_auth_id <SASL user name for root access>
+# sasl_secprops none
+# krb5_ccname /etc/.ldapcache
+.Ed
+.Ss Sudoers schema for OpenLDAP
+The following schema, in OpenLDAP format, is included with
+.Nm sudo
+source and binary distributions as
+.Pa schema.OpenLDAP .
+Simply copy
+it to the schema directory (e.g.,
+.Pa /etc/openldap/schema ) ,
+add the proper
+.Em include
+line in
+.Pa slapd.conf
+and restart
+.Nm slapd .
+Sites using the optional on-line configuration supported by OpenLDAP 2.3
+and higher should apply the
+.Pa schema.olcSudo
+file instead.
+.Bd -literal -offset 2n
+attributetype ( 1.3.6.1.4.1.15953.9.1.1
+ NAME 'sudoUser'
+ DESC 'User(s) who may run sudo'
+ EQUALITY caseExactMatch
+ SUBSTR caseExactSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.2
+ NAME 'sudoHost'
+ DESC 'Host(s) who may run sudo'
+ EQUALITY caseExactIA5Match
+ SUBSTR caseExactIA5SubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.3
+ NAME 'sudoCommand'
+ DESC 'Command(s) to be executed by sudo'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.4
+ NAME 'sudoRunAs'
+ DESC 'User(s) impersonated by sudo'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.5
+ NAME 'sudoOption'
+ DESC 'Options(s) followed by sudo'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.6
+ NAME 'sudoRunAsUser'
+ DESC 'User(s) impersonated by sudo'
+ EQUALITY caseExactMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.7
+ NAME 'sudoRunAsGroup'
+ DESC 'Group(s) impersonated by sudo'
+ EQUALITY caseExactMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.8
+ NAME 'sudoNotBefore'
+ DESC 'Start of time interval for which the entry is valid'
+ EQUALITY generalizedTimeMatch
+ ORDERING generalizedTimeOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.9
+ NAME 'sudoNotAfter'
+ DESC 'End of time interval for which the entry is valid'
+ EQUALITY generalizedTimeMatch
+ ORDERING generalizedTimeOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
+
+attributetype ( 1.3.6.1.4.1.15953.9.1.10
+ NAME 'sudoOrder'
+ DESC 'an integer to order the sudoRole entries'
+ EQUALITY integerMatch
+ ORDERING integerOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL
+ DESC 'Sudoer Entries'
+ MUST ( cn )
+ MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $
+ sudoRunAsGroup $ sudoOption $ sudoNotBefore $ sudoNotAfter $
+ sudoOrder $ description )
+ )
+.Ed
+.Sh SEE ALSO
+.Xr cvtsudoers 1 ,
+.Xr ldap.conf @mansectform@ ,
+.Xr sssd-sudo @mansectform@ ,
+.Xr sudo.conf @mansectform@ ,
+.Xr sudoers @mansectform@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS.md file in the
+.Nm sudo
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh CAVEATS
+There are differences in the way that LDAP-based
+.Em sudoers
+is parsed compared to file-based
+.Em sudoers .
+See the
+.Sx Differences between LDAP and non-LDAP sudoers
+section for more information.
+.Sh BUGS
+If you believe you have found a bug in
+.Nm sudo ,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm sudo
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+.Nm sudo
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudoers.man.in b/docs/sudoers.man.in
new file mode 100644
index 0000000..e8e6830
--- /dev/null
+++ b/docs/sudoers.man.in
@@ -0,0 +1,8031 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 1994-1996, 1998-2005, 2007-2023
+.\" Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" Sponsored in part by the Defense Advanced Research Projects
+.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
+.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
+.\"
+.nr SL @SEMAN@
+.nr BA @BAMAN@
+.nr LC @LCMAN@
+.nr PS @PSMAN@
+.TH "SUDOERS" "@mansectform@" "December 19, 2023" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudoers\fR
+\- default sudo security policy plugin
+.SH "DESCRIPTION"
+The
+\fBsudoers\fR
+policy plugin determines a user's
+\fBsudo\fR
+privileges.
+It is the default
+\fBsudo\fR
+policy plugin.
+The policy is driven by
+the
+\fI@sysconfdir@/sudoers\fR
+file or, optionally, in LDAP.
+The policy format is described in detail in the
+\fISUDOERS FILE FORMAT\fR
+section.
+For information on storing
+\fBsudoers\fR
+policy information
+in LDAP, see
+sudoers.ldap(@mansectform@).
+.SS "Configuring sudo.conf for sudoers"
+\fBsudo\fR
+consults the
+sudo.conf(@mansectform@)
+file to determine which plugins to load.
+If no
+sudo.conf(@mansectform@)
+file is present, or if it contains no
+\fIPlugin\fR
+lines,
+\fBsudoers\fR
+will be used for auditing, policy decisions and I/O logging.
+To explicitly configure
+sudo.conf(@mansectform@)
+to use the
+\fBsudoers\fR
+plugin, the following configuration can be used.
+.nf
+.sp
+.RS 4n
+Plugin sudoers_audit @sudoers_plugin@
+Plugin sudoers_policy @sudoers_plugin@
+Plugin sudoers_io @sudoers_plugin@
+.RE
+.fi
+.PP
+Starting with
+\fBsudo\fR
+1.8.5, it is possible to specify optional arguments to the
+\fBsudoers\fR
+plugin in the
+sudo.conf(@mansectform@)
+file.
+Plugin arguments, if any, should be listed after the path to the plugin
+(i.e., after
+\fI@sudoers_plugin@\fR).
+The arguments are only effective for the plugin that opens (and parses) the
+\fIsudoers\fR
+file.
+.PP
+For
+\fBsudo\fR
+version 1.9.1 and higher, this is the
+\fIsudoers_audit\fR
+plugin.
+For older versions, it is the
+\fIsudoers_policy\fR
+plugin.
+Multiple arguments may be specified, separated by white space.
+For example:
+.nf
+.sp
+.RS 4n
+Plugin sudoers_audit @sudoers_plugin@ sudoers_mode=0400 error_recovery=false
+.RE
+.fi
+.PP
+The following plugin arguments are supported:
+.TP 6n
+error_recovery=bool
+The
+\fIerror_recovery\fR
+argument can be used to control whether
+\fBsudoers\fR
+should attempt to recover from syntax errors in the
+\fIsudoers\fR
+file.
+If set to
+\fItrue\fR
+(the default),
+\fBsudoers\fR
+will try to recover from a syntax error by discarding the portion
+of the line that contains the error until the end of the line.
+A value of
+\fIfalse\fR
+will disable error recovery.
+Prior to version 1.9.3, no error recovery was performed.
+.TP 6n
+ignore_perms=bool
+The
+\fIignore_perms\fR
+argument can be used to disable security checks when loading the
+\fIsudoers\fR
+file.
+If enabled, the
+\fIsudoers\fR
+file will be loaded regardless of the owner or file mode.
+This argument is intended to be used for testing purposes and
+should not be enabled on production systems.
+.TP 6n
+ldap_conf=pathname
+The
+\fIldap_conf\fR
+argument can be used to override the default path to the
+\fIldap.conf\fR
+file.
+.TP 6n
+ldap_secret=pathname
+The
+\fIldap_secret\fR
+argument can be used to override the default path to the
+\fIldap.secret\fR
+file.
+.TP 6n
+sudoers_file=pathname
+The
+\fIsudoers_file\fR
+argument can be used to override the default path to the
+\fIsudoers\fR
+file.
+.TP 6n
+sudoers_uid=user-ID
+The
+\fIsudoers_uid\fR
+argument can be used to override the default owner of the sudoers file.
+It should be specified as a numeric user-ID.
+.TP 6n
+sudoers_gid=group-ID
+The
+\fIsudoers_gid\fR
+argument can be used to override the default group of the sudoers file.
+It must be specified as a numeric group-ID (not a group name).
+.TP 6n
+sudoers_mode=mode
+The
+\fIsudoers_mode\fR
+argument can be used to override the default file mode for the sudoers file.
+It should be specified as an octal value.
+.PP
+For more information on configuring
+sudo.conf(@mansectform@),
+refer to its manual.
+.SS "User Authentication"
+The
+\fBsudoers\fR
+security policy requires that most users authenticate
+themselves before they can use
+\fBsudo\fR.
+A password is not required
+if the invoking user is
+\fBroot\fR,
+if the target user is the same as the invoking user, or if the
+policy has disabled authentication for the user or command.
+Unlike
+su(1),
+when
+\fBsudoers\fR
+requires
+authentication, it validates the invoking user's credentials, not
+the target user's (or
+\fB@runas_default@\fR's)
+credentials.
+This can be changed via
+the
+\fIrootpw\fR,
+\fItargetpw\fR
+and
+\fIrunaspw\fR
+flags, described later.
+.PP
+If a user who is not listed in the policy tries to run a command
+via
+\fBsudo\fR,
+mail is sent to the proper authorities.
+The address
+used for such mail is configurable via the
+\fImailto\fR
+Defaults entry
+(described later) and defaults to
+\fI@mailto@\fR.
+.PP
+No mail will be sent if an unauthorized user tries to run
+\fBsudo\fR
+with the
+\fB\-l\fR
+or
+\fB\-v\fR
+option unless there is an authentication error and
+either the
+\fImail_always\fR
+or
+\fImail_badpass\fR
+flags are enabled.
+This allows users to
+determine for themselves whether or not they are allowed to use
+\fBsudo\fR.
+By default, all attempts to run
+\fBsudo\fR
+(successful or not)
+are logged, regardless of whether or not mail is sent.
+.PP
+If
+\fBsudo\fR
+is run by
+\fBroot\fR
+and the
+\fRSUDO_USER\fR
+environment variable
+is set, the
+\fBsudoers\fR
+policy will use this value to determine who
+the actual user is.
+This can be used by a user to log commands
+through sudo even when a
+\fBroot\fR
+shell has been invoked.
+It also
+allows the
+\fB\-e\fR
+option to remain useful even when invoked via a
+sudo-run script or program.
+Note, however, that the
+\fIsudoers\fR
+file lookup is still done for
+\fBroot\fR,
+not the user specified by
+\fRSUDO_USER\fR.
+.PP
+\fBsudoers\fR
+uses per-user time stamp files for credential caching.
+Once a user has been authenticated, a record is written
+containing the user-ID that was used to authenticate, the
+terminal session ID, the start time of the session leader
+(or parent process) and a time stamp
+(using a monotonic clock if one is available).
+The user may then use
+\fBsudo\fR
+without a password for a short period of time (@timeout@ minutes
+unless overridden by the
+\fItimestamp_timeout\fR
+option).
+By default,
+\fBsudoers\fR
+uses a separate record for each terminal, which means that
+a user's login sessions are authenticated separately.
+The
+\fItimestamp_type\fR
+option can be used to select the type of time stamp record
+\fBsudoers\fR
+will use.
+.SS "Logging"
+By default,
+\fBsudoers\fR
+logs both successful and unsuccessful attempts (as well
+as errors).
+The
+\fIlog_allowed\fR
+and
+\fIlog_denied\fR
+flags can be used to control this behavior.
+Messages can be logged to
+syslog(3),
+a log file, or both.
+The default is to log to
+syslog(3)
+but this is configurable via the
+\fIsyslog\fR
+and
+\fIlogfile\fR
+settings.
+See
+\fIEVENT LOGGING\fR
+for a description of the log file format.
+.PP
+\fBsudoers\fR
+is also capable of running a command in a pseudo-terminal and logging
+input and/or output.
+The standard input, standard output, and standard error can be logged
+even when not associated with a terminal.
+For more information about I/O logging, see the
+\fII/O LOGGING\fR
+section.
+.PP
+Starting with version 1.9, the
+\fIlog_servers\fR
+setting may be used to send event and I/O log data to a remote server running
+\fBsudo_logsrvd\fR
+or another service that implements the protocol described by
+sudo_logsrv.proto(@mansectform@).
+.SS "Command environment"
+Since environment variables can influence program behavior,
+\fBsudoers\fR
+provides a means to restrict which variables from the user's
+environment are inherited by the command to be run.
+There are two
+distinct ways
+\fBsudoers\fR
+can deal with environment variables.
+.PP
+By default, the
+\fIenv_reset\fR
+flag is enabled.
+This causes commands
+to be executed with a new, minimal environment.
+On AIX (and Linux
+systems without PAM), the environment is initialized with the
+contents of the
+\fI/etc/environment\fR
+file.
+.if \n(LC \{\
+On
+BSD
+systems, if the
+\fIuse_loginclass\fR
+flag is enabled, the environment is initialized
+based on the
+\fIpath\fR
+and
+\fIsetenv\fR
+settings in
+\fI/etc/login.conf\fR.
+.\}
+The
+\fRHOME\fR,
+\fRMAIL\fR,
+\fRSHELL\fR,
+\fRLOGNAME\fR
+and
+\fRUSER\fR
+environment variables are initialized based on the target user
+and the
+\fRSUDO_*\fR
+variables are set based on the invoking user.
+Additional variables, such as
+\fRDISPLAY\fR,
+\fRPATH\fR
+and
+\fRTERM\fR,
+are preserved from the invoking user's environment if permitted by the
+\fIenv_check\fR,
+or
+\fIenv_keep\fR
+options.
+A few environment variables are treated specially.
+If the
+\fRPATH\fR
+and
+\fRTERM\fR
+variables are not preserved from the user's environment, they will be set
+to default values.
+The
+\fRLOGNAME\fR
+and
+\fRUSER\fR
+are handled as a single entity.
+If one of them is preserved (or removed) from the user's environment,
+the other will be as well.
+If
+\fRLOGNAME\fR
+and
+\fRUSER\fR
+are to be preserved but only one of them is present in the user's environment,
+the other will be set to the same value.
+This avoids an inconsistent environment where one of the variables
+describing the user name is set to the invoking user and one is
+set to the target user.
+Environment variables with a value beginning with
+\(oq()\(cq
+are removed unless both the name and value parts are matched by
+\fIenv_keep\fR
+or
+\fIenv_check\fR,
+as they may be interpreted as functions by the
+\fBbash\fR
+shell.
+Prior to version 1.8.11, such variables were always removed.
+.PP
+If, however, the
+\fIenv_reset\fR
+flag is disabled, any variables not
+explicitly denied by the
+\fIenv_check\fR
+and
+\fIenv_delete\fR
+options are allowed and their values are
+inherited from the invoking process.
+Prior to version 1.8.21, environment variables with a value beginning with
+\(oq()\(cq
+were always removed.
+Beginning with version 1.8.21, a pattern in
+\fIenv_delete\fR
+is used to match
+\fBbash\fR
+shell functions instead.
+Since it is not possible
+to block all potentially dangerous environment variables, use
+of the default
+\fIenv_reset\fR
+behavior is encouraged.
+.PP
+Environment variables specified by
+\fIenv_check\fR,
+\fIenv_delete\fR,
+or
+\fIenv_keep\fR
+may include one or more
+\(oq*\(cq
+characters which will match zero or more characters.
+No other wildcard characters are supported.
+.PP
+By default, environment variables are matched by name.
+However, if the pattern includes an equal sign
+(\(oq=\&\(cq),
+both the variables name and value must match.
+For example, a
+\fBbash\fR
+shell function could be matched as follows:
+.nf
+.sp
+.RS 4n
+env_keep += "BASH_FUNC_my_func%%=()*"
+.RE
+.fi
+.PP
+Without the
+\(oq=()*\(cq
+suffix, this would not match, as
+\fBbash\fR
+shell functions are not preserved by default.
+.PP
+The complete list of environment variables that are preserved or removed,
+as modified by global Defaults parameters in
+\fIsudoers\fR,
+is displayed when
+\fBsudo\fR
+is run by
+\fBroot\fR
+with the
+\fB\-V\fR
+option.
+The list of environment variables to remove
+varies based on the operating system
+\fBsudo\fR
+is running on.
+.PP
+Other settings may influence the command environment:
+.TP 3n
+\fB\(bu\fR
+\fBsudoers\fR
+options such as
+\fIalways_set_home\fR,
+\fIsecure_path\fR,
+\fIset_logname\fR,
+\fIset_home\fR,
+and
+\fIsetenv\fR.
+.TP 3n
+\fB\(bu\fR
+Command tags, such as
+\fRSETENV\fR
+and
+\fRNOSETENV\fR.
+Note that
+\fRSETENV\fR
+is implied if the command matched is
+\fBALL\fR.
+.TP 3n
+\fB\(bu\fR
+\fBsudo\fR
+options, such as
+\fB\-E\fR
+and
+\fB\-i\fR.
+.PP
+On systems that support PAM where the
+\fBpam_env\fR
+module is enabled for
+\fBsudo\fR,
+variables in the PAM environment may be merged in to the environment.
+If a variable in the PAM environment is already present in the
+user's environment, the value will only be overridden if the variable
+was not preserved by
+\fBsudoers\fR.
+When
+\fIenv_reset\fR
+is enabled, variables preserved from the invoking user's environment
+by the
+\fIenv_keep\fR
+list take precedence over those in the PAM environment.
+When
+\fIenv_reset\fR
+is disabled, variables present the invoking user's environment
+take precedence over those in the PAM environment unless they
+match a pattern in the
+\fIenv_delete\fR
+list.
+.PP
+The dynamic linker on most operating systems will remove variables
+that can control dynamic linking from the environment of set-user-ID
+executables, including
+\fBsudo\fR.
+Depending on the operating
+system this may include
+\fR_RLD*\fR,
+\fRDYLD_*\fR,
+\fRLD_*\fR,
+\fRLDR_*\fR,
+\fRLIBPATH\fR,
+\fRSHLIB_PATH\fR,
+and others.
+These type of variables are
+removed from the environment before
+\fBsudo\fR
+even begins execution
+and, as such, it is not possible for
+\fBsudo\fR
+to preserve them.
+.PP
+As a special case, if the
+\fB\-i\fR
+option (initial login) is
+specified,
+\fBsudoers\fR
+will initialize the environment regardless
+of the value of
+\fIenv_reset\fR.
+The
+\fRDISPLAY\fR,
+\fRPATH\fR
+and
+\fRTERM\fR
+variables remain unchanged;
+\fRHOME\fR,
+\fRMAIL\fR,
+\fRSHELL\fR,
+\fRUSER\fR,
+and
+\fRLOGNAME\fR
+are set based on the target user.
+On AIX (and Linux
+systems without PAM), the contents of
+\fI/etc/environment\fR
+are also
+included.
+.if \n(LC \{\
+On
+BSD
+systems, if the
+\fIuse_loginclass\fR
+flag is
+enabled, the
+\fIpath\fR
+and
+\fIsetenv\fR
+variables in
+\fI/etc/login.conf\fR
+are also applied.
+.\}
+All other environment variables are removed unless permitted by
+\fIenv_keep\fR
+or
+\fIenv_check\fR,
+described above.
+.PP
+Finally, the
+\fIrestricted_env_file\fR
+and
+\fIenv_file\fR
+files are applied, if present.
+The variables in
+\fIrestricted_env_file\fR
+are applied first and are subject to the same restrictions as the
+invoking user's environment, as detailed above.
+The variables in
+\fIenv_file\fR
+are applied last and are not subject to these restrictions.
+In both cases, variables present in the files will only be set to
+their specified values if they would not conflict with an existing
+environment variable.
+.SH "SUDOERS FILE FORMAT"
+The
+\fIsudoers\fR
+file is composed of two types of entries: aliases
+(basically variables) and user specifications (which specify who
+may run what).
+.PP
+When multiple entries match for a user, they are applied in order.
+Where there are multiple matches, the last match is used (which is
+not necessarily the most specific match).
+.PP
+The
+\fIsudoers\fR
+file grammar will be described below in Extended Backus-Naur
+Form (EBNF).
+Don't despair if you are unfamiliar with EBNF; it is fairly simple,
+and the definitions below are annotated.
+.SS "Resource limits"
+By default,
+\fBsudoers\fR
+uses the operating system's native method of setting resource limits
+for the target user.
+On Linux systems, resource limits are usually set by the
+\fIpam_limits.so\fR
+PAM module.
+On some BSD systems, the
+\fI/etc/login.conf\fR
+file specifies resource limits for the user.
+On AIX systems, resource limits are configured in the
+\fI/etc/security/limits\fR
+file.
+If there is no system mechanism to set per-user resource limits,
+the command will run with the same limits as the invoking user.
+The one exception to this is the core dump file size, which is set by
+\fBsudoers\fR
+to 0 by default.
+Disabling core dumps by default makes it possible to avoid potential
+security problems where the core file is treated as trusted input.
+.PP
+Resource limits may also be set in the
+\fIsudoers\fR
+file itself, in which case they override those set by the system.
+See the
+\fIrlimit_as,\fR
+\fIrlimit_core,\fR
+\fIrlimit_cpu,\fR
+\fIrlimit_data,\fR
+\fIrlimit_fsize,\fR
+\fIrlimit_locks,\fR
+\fIrlimit_memlock,\fR
+\fIrlimit_nofile,\fR
+\fIrlimit_nproc,\fR
+\fIrlimit_rss,\fR
+\fIrlimit_stack\fR
+options described below.
+Resource limits in
+\fBsudoers\fR
+may be specified in one of the following formats:
+.TP 8n
+\(lqvalue\(rq
+Both the soft and hard resource limits are set to the same value.
+The special value
+\(lqinfinity\(rq
+can be used to indicate that the value is unlimited.
+.TP 8n
+\(lqsoft,hard\(rq
+Two comma-separated values.
+The soft limit is set to the first value and the hard limit is set
+to the second.
+Both values must either be enclosed in a set of double quotes,
+or the comma must be escaped with a backslash
+(\(oq\e\(cq).
+The special value
+\(lqinfinity\(rq
+may be used in place of either value.
+.TP 8n
+\(lqdefault\(rq
+The default resource limit for the user will be used.
+This may be a user-specific value (see above) or the value of the
+resource limit when
+\fBsudo\fR
+was invoked for systems that don't support per-user limits.
+.TP 8n
+\(lquser\(rq
+The invoking user's resource limits will be preserved when running
+the command.
+.PP
+For example, to restore the historic core dump file size behavior,
+a line like the following may be used.
+.sp
+.RS 6n
+Defaults rlimit_core=default
+.RE
+.PP
+Resource limits in
+\fBsudoers\fR
+are only supported by version 1.8.7 or higher.
+.SS "Quick guide to EBNF"
+EBNF is a concise and exact way of describing the grammar of a language.
+Each EBNF definition is made up of
+\fIproduction rules\fR.
+For example:
+.nf
+.sp
+.RS 4n
+symbol ::= definition | alternate1 | alternate2 ...
+.RE
+.fi
+.PP
+Each
+\fIproduction rule\fR
+references others and thus makes up a
+grammar for the language.
+EBNF also contains the following
+operators, which many readers will recognize from regular
+expressions.
+Do not, however, confuse them with
+\(lqwildcard\(rq
+characters, which have different meanings.
+.TP 6n
+\&?
+Means that the preceding symbol (or group of symbols) is optional.
+That is, it may appear once or not at all.
+.TP 6n
+*
+Means that the preceding symbol (or group of symbols) may appear
+zero or more times.
+.TP 6n
++
+Means that the preceding symbol (or group of symbols) may appear
+one or more times.
+.PP
+Parentheses may be used to group symbols together.
+For clarity,
+we will use single quotes
+('')
+to designate what is a verbatim character string (as opposed to a symbol name).
+.SS "Aliases"
+There are four kinds of aliases:
+\fIUser_Alias\fR,
+\fIRunas_Alias\fR,
+\fIHost_Alias\fR
+and
+\fICmnd_Alias\fR.
+Beginning with
+\fBsudo\fR
+1.9.0,
+\fICmd_Alias\fR
+may be used in place of
+\fICmnd_Alias\fR
+if desired.
+.nf
+.sp
+.RS 0n
+Alias ::= 'User_Alias' User_Alias_Spec (':' User_Alias_Spec)* |
+ 'Runas_Alias' Runas_Alias_Spec (':' Runas_Alias_Spec)* |
+ 'Host_Alias' Host_Alias_Spec (':' Host_Alias_Spec)* |
+ 'Cmnd_Alias' Cmnd_Alias_Spec (':' Cmnd_Alias_Spec)* |
+ 'Cmd_Alias' Cmnd_Alias_Spec (':' Cmnd_Alias_Spec)*
+
+User_Alias ::= NAME
+
+User_Alias_Spec ::= User_Alias '=' User_List
+
+Runas_Alias ::= NAME
+
+Runas_Alias_Spec ::= Runas_Alias '=' Runas_List
+
+Host_Alias ::= NAME
+
+Host_Alias_Spec ::= Host_Alias '=' Host_List
+
+Cmnd_Alias ::= NAME
+
+Cmnd_Alias_Spec ::= Cmnd_Alias '=' Cmnd_List
+
+NAME ::= [A-Z]([A-Z][0-9]_)*
+.RE
+.fi
+.PP
+Each
+\fIalias\fR
+definition is of the form
+.nf
+.sp
+.RS 0n
+Alias_Type NAME = item1, item2, ...
+.RE
+.fi
+.PP
+where
+\fIAlias_Type\fR
+is one of
+\fIUser_Alias\fR,
+\fIRunas_Alias\fR,
+\fIHost_Alias\fR,
+or
+\fICmnd_Alias\fR.
+A
+\fRNAME\fR
+is a string of uppercase letters, numbers,
+and underscore characters
+(\(oq_\(cq).
+A
+\fRNAME\fR
+\fBmust\fR
+start with an
+uppercase letter.
+It is possible to put several alias definitions
+of the same type on a single line, joined by a colon
+(\(oq:\&\(cq).
+For example:
+.nf
+.sp
+.RS 0n
+Alias_Type NAME = item1, item2, item3 : NAME = item4, item5
+.RE
+.fi
+.PP
+It is a syntax error to redefine an existing
+\fIalias\fR.
+It is possible to use the same name for
+\fIaliases\fR
+of different types, but this is not recommended.
+.PP
+The definitions of what constitutes a valid
+\fIalias\fR
+member follow.
+.nf
+.sp
+.RS 0n
+User_List ::= User |
+ User ',' User_List
+
+User ::= '!'* user name |
+ '!'* #user-ID |
+ '!'* %group |
+ '!'* %#group-ID |
+ '!'* +netgroup |
+ '!'* %:nonunix_group |
+ '!'* %:#nonunix_gid |
+ '!'* User_Alias
+.RE
+.fi
+.PP
+A
+\fIUser_List\fR
+is made up of one or more user names, user-IDs
+(prefixed with
+\(oq#\(cq),
+system group names and IDs (prefixed with
+\(oq%\(cq
+and
+\(oq%#\(cq
+respectively), netgroups (prefixed with
+\(oq+\(cq),
+non-Unix group names and IDs (prefixed with
+\(oq%:\(cq
+and
+\(oq%:#\(cq
+respectively), and
+\fIUser_Alias\fRes.
+Each list item may be prefixed with zero or more
+\(oq\&!\(cq
+operators.
+An odd number of
+\(oq\&!\(cq
+operators negate the value of
+the item; an even number just cancel each other out.
+User netgroups are matched using the user and domain members only;
+the host member is not used when matching.
+.PP
+A
+\fIuser name\fR,
+\fIuser-ID\fR,
+\fIgroup\fR,
+\fIgroup-ID\fR,
+\fInetgroup\fR,
+\fInonunix_group\fR
+or
+\fInonunix_gid\fR
+may be enclosed in double quotes to avoid the
+need for escaping special characters.
+Alternately, special characters
+may be specified in escaped hex mode, e.g., \ex20 for space.
+When
+using double quotes, any prefix characters must be included inside
+the quotes.
+.PP
+The actual
+\fInonunix_group\fR
+and
+\fInonunix_gid\fR
+syntax depends on
+the underlying group provider plugin.
+For instance, the QAS AD plugin supports the following formats:
+.TP 3n
+\fB\(bu\fR
+Group in the same domain: "%:Group Name"
+.TP 3n
+\fB\(bu\fR
+Group in any domain: "%:Group Name@FULLY.QUALIFIED.DOMAIN"
+.TP 3n
+\fB\(bu\fR
+Group SID: "%:S-1-2-34-5678901234-5678901234-5678901234-567"
+.PP
+See
+\fIGROUP PROVIDER PLUGINS\fR
+for more information.
+.PP
+Quotes around group names are optional.
+Unquoted strings must use a backslash
+(\(oq\e\(cq)
+to escape spaces and special characters.
+See
+\fIOther special characters and reserved words\fR
+for a list of
+characters that need to be escaped.
+.nf
+.sp
+.RS 0n
+Runas_List ::= Runas_Member |
+ Runas_Member ',' Runas_List
+
+Runas_Member ::= '!'* user name |
+ '!'* #user-ID |
+ '!'* %group |
+ '!'* %#group-ID |
+ '!'* %:nonunix_group |
+ '!'* %:#nonunix_gid |
+ '!'* +netgroup |
+ '!'* Runas_Alias |
+ '!'* ALL
+.RE
+.fi
+.PP
+A
+\fIRunas_List\fR
+is similar to a
+\fIUser_List\fR
+except that instead
+of
+\fIUser_Alias\fRes
+it can contain
+\fIRunas_Alias\fRes.
+User names and groups are matched as strings.
+In other words, two users (groups) with the same user (group) ID
+are considered to be distinct.
+If you wish to match all user names with the same user-ID (e.g.,
+\fBroot\fR
+and
+\fBtoor\fR),
+you can use a user-ID instead of a name (#0 in the example given).
+The user-ID or group-ID specified in a
+\fIRunas_Member\fR
+need not be listed in the password or group database.
+.nf
+.sp
+.RS 0n
+Host_List ::= Host |
+ Host ',' Host_List
+
+Host ::= '!'* host name |
+ '!'* ip_addr |
+ '!'* network(/netmask)? |
+ '!'* +netgroup |
+ '!'* Host_Alias |
+ '!'* ALL
+.RE
+.fi
+.PP
+A
+\fIHost_List\fR
+is made up of one or more host names, IP addresses,
+network numbers, netgroups (prefixed with
+\(oq+\(cq),
+and other aliases.
+Again, the value of an item may be negated with the
+\(oq\&!\(cq
+operator.
+Host netgroups are matched using the host (both qualified and unqualified)
+and domain members only; the user member is not used when matching.
+If you specify a network number without a netmask,
+\fBsudo\fR
+will query each of the local host's network interfaces and,
+if the network number corresponds to one of the hosts's network
+interfaces, will use the netmask of that interface.
+The netmask may be specified either in standard IP address notation
+(e.g., 255.255.255.0 or ffff:ffff:ffff:ffff::),
+or CIDR notation (number of bits, e.g., 24 or 64).
+A host name may include shell-style wildcards (see the
+\fIWildcards\fR
+section below),
+but unless the
+\fIhostname\fR
+command on your machine returns the fully
+qualified host name, you'll need to use the
+\fIfqdn\fR
+flag for wildcards to be useful.
+\fBsudo\fR
+only inspects actual network interfaces; this means that IP address
+127.0.0.1 (localhost) will never match.
+Also, the host name
+\(lqlocalhost\(rq
+will only match if that is the actual host name, which is usually
+only the case for non-networked systems.
+.nf
+.sp
+.RS 0n
+digest ::= [A-Fa-f0-9]+ |
+ [A-Za-z0-9\e+/=]+
+
+Digest_Spec ::= "sha224" ':' digest |
+ "sha256" ':' digest |
+ "sha384" ':' digest |
+ "sha512" ':' digest
+
+Digest_List ::= Digest_Spec |
+ Digest_Spec ',' Digest_List
+
+Cmnd_List ::= Cmnd |
+ Cmnd ',' Cmnd_List
+
+command name ::= regex |
+ file name
+
+command ::= command name |
+ command name args |
+ command name regex |
+ command name '""' |
+ ALL
+
+Edit_Spec ::= "sudoedit" file name+ |
+ "sudoedit" regex |
+ "sudoedit"
+
+List_Spec ::= "list"
+
+Cmnd ::= Digest_List? '!'* command |
+ '!'* directory |
+ '!'* Edit_Spec |
+ '!'* List_Spec |
+ '!'* Cmnd_Alias
+.RE
+.fi
+.PP
+A
+\fICmnd_List\fR
+is a list of one or more commands, directories, or aliases.
+A command is a fully qualified file name, which may include
+shell-style wildcards (see the
+\fIWildcards\fR
+section below),
+or a regular expression that starts with
+\(oq^\(cq
+and ends with
+\(oq$\(cq
+(see the
+\fIRegular expressions\fR
+section below).
+A directory is a
+fully qualified path name ending in a
+\(oq/\(cq.
+When you specify a directory in a
+\fICmnd_List\fR,
+the user will be able to run any file within that directory
+(but not in any sub-directories therein).
+If no command line arguments are specified, the user may run the
+command with any arguments they choose.
+Command line arguments can include wildcards or be a regular
+expression that starts with
+\(oq^\(cq
+and ends with
+\(oq$\(cq.
+If the command line arguments consist of
+\(oq\&""\(cq,
+the command may only be run with
+\fIno\fR
+arguments.
+.PP
+If a
+\fICmnd\fR
+has associated command line arguments, the arguments
+in the
+\fICmnd\fR
+must match those given by the user on the command line.
+If the arguments in a
+\fICmnd\fR
+begin with the
+\(oq^\(cq
+character, they will be interpreted as a regular expression
+and matched accordingly.
+Otherwise, shell-style wildcards are used when matching.
+Unless a regular expression is specified, the following characters must
+be escaped with a
+\(oq\e\(cq
+if they are used in command arguments:
+\(oq,\&\(cq,
+\(oq:\&\(cq,
+\(oq=\&\(cq,
+\(oq\e\(cq.
+To prevent arguments in a
+\fICmnd\fR
+that begin with a
+\(oq^\(cq
+character from being interpreted as a regular expression, the
+\(oq^\(cq
+must be escaped with a
+\(oq\e\(cq.
+.PP
+There are two commands built into
+\fBsudo\fR
+itself:
+\(lqlist\(rq
+and
+\(lqsudoedit\(rq.
+Unlike other commands, these two must be specified in the
+\fIsudoers\fR
+file
+\fIwithout\fR
+a leading path.
+.PP
+The
+\(lqlist\(rq
+built-in can be used to permit a user to list another user's privileges with
+\fBsudo\fR's
+\fB\-U\fR
+option.
+For example,
+\(lqsudo -l -U otheruser\(rq.
+A user with the
+\(lqlist\(rq
+privilege is able to list another user's privileges even if they
+don't have permission to run commands as that user.
+By default, only root or a user with the ability to run any command as
+either root or the specified
+\fIuser\fR
+on the current host may use the
+\fB\-U\fR
+option.
+No command line arguments may be specified with the
+\(lqlist\(rq
+built-in.
+.PP
+The
+\(lqsudoedit\(rq
+built-in is used to permit a user to run
+\fBsudo\fR
+with the
+\fB\-e\fR
+option (or as
+\fBsudoedit\fR).
+It may take command line arguments just as a normal command does.
+Unlike other commands,
+\(lqsudoedit\(rq
+is built into
+\fBsudo\fR
+itself and must be specified in the
+\fIsudoers\fR
+file
+\fIwithout\fR
+a leading path.
+If a leading path is present, for example
+\fI/usr/bin/sudoedit\fR,
+the path name will be silently converted to
+\(lqsudoedit\(rq.
+A fully-qualified path for
+\fBsudoedit\fR
+is treated as an error by
+\fBvisudo\fR.
+.PP
+A
+\fIcommand\fR
+may be preceded by a
+\fIDigest_List\fR,
+a comma-separated list of one or more
+\fIDigest_Spec\fR
+entries.
+If a
+\fIDigest_List\fR
+is present, the command will only match successfully if it can be verified
+using one of the SHA-2 digests in the list.
+Starting with version 1.9.0, the
+\fBALL\fR
+reserved word can be used in conjunction with a
+\fIDigest_List\fR.
+The following digest formats are supported: sha224, sha256, sha384, and sha512.
+The string may be specified in either hex or base64 format
+(base64 is more compact).
+There are several utilities capable of generating SHA-2 digests in hex
+format such as openssl, shasum, sha224sum, sha256sum, sha384sum, sha512sum.
+.PP
+For example, using openssl:
+.nf
+.sp
+.RS 0n
+$ openssl dgst -sha224 /bin/ls
+SHA224(/bin/ls)= 118187da8364d490b4a7debbf483004e8f3e053ec954309de2c41a25
+.RE
+.fi
+.PP
+It is also possible to use openssl to generate base64 output:
+.nf
+.sp
+.RS 0n
+$ openssl dgst -binary -sha224 /bin/ls | openssl base64
+EYGH2oNk1JC0p9679IMATo8+BT7JVDCd4sQaJQ==
+.RE
+.fi
+.PP
+Warning, if the user has write access to the command itself (directly or via a
+\fBsudo\fR
+command), it may be possible for the user to replace the command after the
+digest check has been performed but before the command is executed.
+A similar race condition exists on systems that lack the
+fexecve(2)
+system call when the directory in which the command is located
+is writable by the user.
+See the description of the
+\fIfdexec\fR
+setting for more information on how
+\fBsudo\fR
+executes commands that have an associated digest.
+.PP
+Command digests are only supported by version 1.8.7 or higher.
+.SS "Defaults"
+Certain configuration options may be changed from their default
+values at run-time via one or more
+\fIDefault_Entry\fR
+lines.
+These may affect all users on any host
+(\(oqDefaults\(cq),
+all users on a specific host
+(\(oqDefaults@host\(cq),
+a specific user
+(\(oqDefaults:user\(cq),
+a specific command
+(\(oqDefaults!cmnd\(cq),
+or commands being run as a specific user
+(\(oqDefaults>runasuser\(cq).
+.PP
+White space is not permitted between
+\(oqDefaults\(cq
+and the
+\(oq@\(cq,
+\(oq\&:\(cq,
+\(oq\&!\(cq,
+or
+\(oq>\(cq
+characters.
+While a comma-separated list may be used in place of a single value after the
+\(oq@\(cq,
+\(oq\&:\(cq,
+\(oq\&!\(cq,
+or
+\(oq>\(cq
+character, using an alias instead of a list is often improve readability.
+Per-command entries may not include command line arguments.
+If you need to specify arguments, define a
+\fICmnd_Alias\fR
+and reference that instead.
+.nf
+.sp
+.RS 0n
+Default_Type ::= 'Defaults' |
+ 'Defaults@' Host_List |
+ 'Defaults:' User_List |
+ 'Defaults!' Cmnd_List |
+ 'Defaults>' Runas_List
+
+Default_Entry ::= Default_Type Parameter_List
+
+Parameter_List ::= Parameter |
+ Parameter ',' Parameter_List
+
+Parameter ::= Parameter '=' Value |
+ Parameter '+=' Value |
+ Parameter '-=' Value |
+ '!'* Parameter
+.RE
+.fi
+.PP
+Parameters may be
+\fBflags\fR,
+\fBinteger\fR
+values,
+\fBstrings\fR,
+or
+\fBlists\fR.
+Flags are implicitly boolean and can be turned off via the
+\(oq\&!\(cq
+operator.
+Some integer, string and list parameters may also be
+used in a boolean context to disable them.
+Values may be enclosed
+in double quotes
+(\&"")
+when they contain multiple words.
+Special characters may be escaped with a backslash
+(\(oq\e\(cq).
+.PP
+To include a literal backslash character in a command line argument
+you must escape the backslash twice.
+For example, to match
+\(oq\en\(cq
+as part of a command line argument, you must use
+\(oq\e\e\e\en\(cq
+in the
+\fIsudoers\fR
+file.
+This is due to there being two levels of escaping, one in the
+\fIsudoers\fR
+parser itself and another when command line arguments are matched by the
+fnmatch(3)
+or
+regexec(3)
+function.
+.PP
+Lists have two additional assignment operators,
+\(oq+=\(cq
+and
+\(oq-=\(cq.
+These operators are used to add to and delete from a list respectively.
+It is not an error to use the
+\(oq-=\(cq
+operator to remove an element
+that does not exist in a list.
+.PP
+Defaults entries are parsed in the following order: global, host,
+user, and runas Defaults first, then command defaults.
+If there are multiple Defaults settings of the same type, the last
+matching setting is used.
+The following Defaults settings are parsed before all others since
+they may affect subsequent entries:
+\fIfqdn\fR,
+\fIgroup_plugin\fR,
+\fIrunas_default\fR,
+\fIsudoers_locale\fR.
+.PP
+See
+\fISUDOERS OPTIONS\fR
+for a list of supported Defaults parameters.
+.SS "User specification"
+.nf
+.RS 0n
+User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \e
+ (':' Host_List '=' Cmnd_Spec_List)*
+
+Cmnd_Spec_List ::= Cmnd_Spec |
+ Cmnd_Spec ',' Cmnd_Spec_List
+
+Cmnd_Spec ::= Runas_Spec? Option_Spec* (Tag_Spec ':')* Cmnd
+
+Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')'
+
+.ie \n(SL \{\
+.ie \n(PS Option_Spec ::= (SELinux_Spec | Solaris_Priv_Spec | Date_Spec | Timeout_Spec)
+.el Option_Spec ::= (SELinux_Spec | Date_Spec | Timeout_Spec)
+.\}
+.el \{\
+.ie \n(PS Option_Spec ::= (Solaris_Priv_Spec | Date_Spec | Timeout_Spec)
+.el Option_Spec ::= (Date_Spec | Timeout_Spec)
+.\}
+
+.if \n(SL \{\
+SELinux_Spec ::= ('ROLE=role' | 'TYPE=type')
+
+.\}
+AppArmor_Spec ::= 'APPARMOR_PROFILE=profile'
+
+.if \n(PS \{\
+Solaris_Priv_Spec ::= ('PRIVS=privset' | 'LIMITPRIVS=privset')
+
+.\}
+Date_Spec ::= ('NOTBEFORE=timestamp' | 'NOTAFTER=timestamp')
+
+Timeout_Spec ::= 'TIMEOUT=timeout'
+
+Chdir_Spec ::= 'CWD=directory'
+
+Chroot_Spec ::= 'CHROOT=directory'
+
+Tag_Spec ::= ('EXEC' | 'NOEXEC' | 'FOLLOW' | 'NOFOLLOW' |
+ 'LOG_INPUT' | 'NOLOG_INPUT' | 'LOG_OUTPUT' |
+ 'NOLOG_OUTPUT' | 'MAIL' | 'NOMAIL' | 'INTERCEPT' |
+ 'NOINTERCEPT' | 'PASSWD' | 'NOPASSWD' | 'SETENV' |
+ 'NOSETENV')
+.RE
+.fi
+.PP
+A
+\fBuser specification\fR
+determines which commands a user may run
+(and as what user) on specified hosts.
+By default, commands are run as
+\fB@runas_default@\fR
+(unless
+\fIrunas_default\fR
+has been set to a different value)
+but this can also be changed on a per-command basis.
+.PP
+The basic structure of a user specification is
+\(lqwho where = (as_whom) what\(rq.
+Let's break that down into its constituent parts:
+.SS "Runas_Spec"
+A
+\fIRunas_Spec\fR
+determines the user and/or the group that a command
+may be run as.
+A fully-specified
+\fIRunas_Spec\fR
+consists of two
+\fIRunas_List\fRs
+(as defined above) separated by a colon
+(\(oq\&:\(cq)
+and enclosed in a set of parentheses.
+The first
+\fIRunas_List\fR
+indicates which users the command may be run as via the
+\fB\-u\fR
+option.
+The second defines a list of groups that may be specified via the
+\fB\-g\fR
+option (in addition to any of the target user's groups).
+If both
+\fIRunas_List\fRs
+are specified, the command may be run with any combination of users
+and groups listed in their respective
+\fIRunas_List\fRs.
+If only the first is specified, the command may be run as any user
+in the list and, optionally, with any group the target user belongs to.
+If the first
+\fIRunas_List\fR
+is empty but the
+second is specified, the command may be run as the invoking user
+with the group set to any listed in the
+\fIRunas_List\fR.
+If both
+\fIRunas_List\fRs
+are empty, the command may only be run as the invoking user and the
+group, if specified, must be one that the invoking user is a member of.
+If no
+\fIRunas_Spec\fR
+is specified, the command may only be run as the
+\fIrunas_default\fR
+user
+(\fB@runas_default@\fR
+by default) and the group,
+if specified, must be one that the
+\fIrunas_default\fR
+user is a member of.
+.PP
+A
+\fIRunas_Spec\fR
+sets the default for the commands that follow it.
+What this means is that for the entry:
+.nf
+.sp
+.RS 0n
+dgb boulder = (operator) /bin/ls, /bin/kill, /usr/bin/lprm
+.RE
+.fi
+.PP
+The user
+\fBdgb\fR
+may run
+\fI/bin/ls\fR,
+\fI/bin/kill\fR,
+and
+\fI/usr/bin/lprm\fR
+on the host
+boulder\(embut
+only as
+\fBoperator\fR.
+For example:
+.nf
+.sp
+.RS 0n
+$ sudo -u operator /bin/ls
+.RE
+.fi
+.PP
+It is also possible to override a
+\fIRunas_Spec\fR
+later on in an entry.
+If we modify the entry like so:
+.nf
+.sp
+.RS 0n
+dgb boulder = (operator) /bin/ls, (root) /bin/kill, /usr/bin/lprm
+.RE
+.fi
+.PP
+Then user
+\fBdgb\fR
+is now allowed to run
+\fI/bin/ls\fR
+as
+\fBoperator\fR,
+but
+\fI/bin/kill\fR
+and
+\fI/usr/bin/lprm\fR
+as
+\fBroot\fR.
+.PP
+We can extend this to allow
+\fBdgb\fR
+to run
+\fI/bin/ls\fR
+with either
+the user or group set to
+\fBoperator\fR:
+.nf
+.sp
+.RS 0n
+dgb boulder = (operator : operator) /bin/ls, (root) /bin/kill,\e
+ /usr/bin/lprm
+.RE
+.fi
+.PP
+While the group portion of the
+\fIRunas_Spec\fR
+permits the
+user to run as command with that group, it does not force the user
+to do so.
+If no group is specified on the command line, the command
+will run with the group listed in the target user's password database
+entry.
+The following would all be permitted by the sudoers entry above:
+.nf
+.sp
+.RS 0n
+$ sudo -u operator /bin/ls
+$ sudo -u operator -g operator /bin/ls
+$ sudo -g operator /bin/ls
+.RE
+.fi
+.PP
+In the following example, user
+\fBtcm\fR
+may run commands that access
+a modem device file with the dialer group.
+.nf
+.sp
+.RS 0n
+tcm boulder = (:dialer) /usr/bin/tip, /usr/bin/cu,\e
+ /usr/local/bin/minicom
+.RE
+.fi
+.PP
+In this example only the group will be set, the command still runs as user
+\fBtcm\fR.
+For example:
+.nf
+.sp
+.RS 0n
+$ sudo -g dialer /usr/bin/cu
+.RE
+.fi
+.PP
+Multiple users and groups may be present in a
+\fIRunas_Spec\fR,
+in which case the user may select any combination of users and groups via the
+\fB\-u\fR
+and
+\fB\-g\fR
+options.
+In this example:
+.nf
+.sp
+.RS 0n
+alan ALL = (root, bin : operator, system) ALL
+.RE
+.fi
+.PP
+user
+\fBalan\fR
+may run any command as either user
+\fBroot\fR
+or
+\fBbin\fR,
+optionally setting the group to operator or system.
+.SS "Option_Spec"
+A
+\fICmnd\fR
+may have zero or more options associated with it.
+Options may consist of
+.if \n(SL \{\
+SELinux roles and/or types,
+.\}
+AppArmor profiles,
+.if \n(PS \{\
+Solaris privileges sets,
+.\}
+start and/or end dates and command timeouts.
+Once an option is set for a
+\fICmnd\fR,
+subsequent
+\fICmnd\fRs
+in the
+\fICmnd_Spec_List\fR,
+inherit that option unless it is overridden by another option.
+Option names are reserved words in
+\fIsudoers\fR.
+This means that none of the valid option names (see below) can be used
+when declaring an alias.
+.if \n(SL \{\
+.SS "SELinux_Spec"
+On systems with SELinux support,
+\fIsudoers\fR
+file entries may optionally have an SELinux role and/or type associated
+with a command.
+This can be used to implement a form of role-based access control (RBAC).
+If a role or
+type is specified with the command it will override any default values
+specified in
+\fIsudoers\fR.
+A role or type specified on the command line,
+however, will supersede the values in
+\fIsudoers\fR.
+.\}
+.SS "AppArmor_Spec"
+On systems supporting AppArmor,
+\fIsudoers\fR
+file entries may optionally specify an AppArmor profile that should be
+used to confine a command.
+If an AppArmor profile is specified with the command, it will override
+any default values specified in
+\fIsudoers\fR.
+Appropriate profile transition rules must be defined to support the
+profile change specified for a user.
+.PP
+AppArmor profiles can be specified in any way that complies with the
+rules of
+aa_change_profile(2).
+For instance, in the following
+\fIsudoers\fR
+entry
+.nf
+.sp
+.RS 0n
+alice ALL = (root) APPARMOR_PROFILE=my-profile ALL
+.RE
+.fi
+.PP
+the user
+\fBalice\fR
+may run any command as
+\fBroot\fR
+under confinement by the profile
+\(oqmy-profile\(cq.
+You can also stack profiles, or allow a user to run commands unconfined by
+any profile.
+For example:
+.nf
+.sp
+.RS 0n
+bob ALL = (root) APPARMOR_PROFILE=foo//&bar /usr/bin/vi
+cathy ALL = (root) APPARMOR_PROFILE=unconfined /bin/ls
+.RE
+.fi
+.PP
+These
+\fIsudoers\fR
+entries allow user
+\fBbob\fR
+to run
+\fI/usr/bin/vi\fR
+as
+\fBroot\fR
+under the stacked profiles
+\(oqfoo\(cq
+and
+\(oqbar\(cq,
+and user
+\fBcathy\fR
+to run
+\fI/bin/ls\fR
+without any confinement at all.
+.if \n(PS \{\
+.SS "Solaris_Priv_Spec"
+On Solaris systems,
+\fIsudoers\fR
+file entries may optionally specify Solaris privilege set and/or limit
+privilege set associated with a command.
+If privileges or limit privileges are specified with the command
+it will override any default values specified in
+\fIsudoers\fR.
+.PP
+A privilege set is a comma-separated list of privilege names.
+The
+ppriv(1)
+command can be used to list all privileges known to the system.
+For example:
+.nf
+.sp
+.RS 0n
+$ ppriv -l
+.RE
+.fi
+.PP
+In addition, there are several
+\(lqspecial\(rq
+privilege strings:
+.TP 7n
+none
+the empty set
+.TP 7n
+all
+the set of all privileges
+.TP 7n
+zone
+the set of all privileges available in the current zone
+.TP 7n
+basic
+the default set of privileges normal users are granted at login time
+.PP
+Privileges can be excluded from a set by prefixing the privilege
+name with either an
+\(oq\&!\(cq
+or
+\(oq\-\(cq
+character.
+.\}
+.SS "Date_Spec"
+\fBsudoers\fR
+rules can be specified with a start and end date via the
+\fRNOTBEFORE\fR
+and
+\fRNOTAFTER\fR
+settings.
+The time stamp must be specified in
+\(lqGeneralized Time\(rq
+as defined by RFC 4517.
+The format is effectively
+\(oqyyyymmddHHMMSSZ\(cq
+where the minutes and seconds are optional.
+The
+\(oqZ\(cq
+suffix indicates that the time stamp is in Coordinated Universal Time (UTC).
+It is also possible to specify a timezone offset from UTC in hours
+and minutes instead of a
+\(oqZ\(cq.
+For example,
+\(oq-0500\(cq
+would correspond to Eastern Standard time in the US.
+As an extension, if no
+\(oqZ\(cq
+or timezone offset is specified, local time will be used.
+.PP
+The following are all valid time stamps:
+.nf
+.sp
+.RS 4n
+20170214083000Z
+2017021408Z
+20160315220000-0500
+20151201235900
+.RE
+.fi
+.SS "Timeout_Spec"
+A command may have a timeout associated with it.
+If the timeout expires before the command has exited, the
+command will be terminated.
+The timeout may be specified in combinations of days, hours,
+minutes, and seconds with a single-letter case-insensitive suffix
+that indicates the unit of time.
+For example, a timeout of 7 days, 8 hours, 30 minutes, and
+10 seconds would be written as
+\(oq7d8h30m10s\(cq.
+If a number is specified without a unit, seconds are assumed.
+Any of the days, minutes, hours, or seconds may be omitted.
+The order must be from largest to smallest unit and a unit
+may not be specified more than once.
+.PP
+The following are all
+\fIvalid\fR
+timeout values:
+\(oq7d8h30m10s\(cq,
+\(oq14d\(cq,
+\(oq8h30m\(cq,
+\(oq600s\(cq,
+\(oq3600\(cq.
+The following are
+\fIinvalid\fR
+timeout values:
+\(oq12m2w1d\(cq,
+\(oq30s10m4h\(cq,
+\(oq1d2d3h\(cq.
+.PP
+This setting is only supported by version 1.8.20 or higher.
+.SS "Chdir_Spec"
+The working directory that the command will be run in can be specified
+using the
+\fRCWD\fR
+setting.
+The
+\fIdirectory\fR
+must be a fully-qualified path name beginning with a
+\(oq/\(cq
+or
+\(oq~\(cq
+character, or the special value
+\(lq*\(rq.
+A value of
+\(lq*\(rq
+indicates that the user may specify the working directory by running
+\fBsudo\fR
+with the
+\fB\-D\fR
+option.
+By default, commands are run from the invoking user's current working
+directory, unless the
+\fB\-i\fR
+option is given.
+Path names of the form
+\fI~user/path/name\fR
+are interpreted as being relative to the named user's home directory.
+If the user name is omitted, the path will be relative to the runas
+user's home directory.
+.PP
+This setting is only supported by version 1.9.3 or higher.
+.SS "Chroot_Spec"
+The root directory that the command will be run in can be specified
+using the
+\fRCHROOT\fR
+setting.
+The
+\fIdirectory\fR
+must be a fully-qualified path name beginning with a
+\(oq/\(cq
+or
+\(oq~\(cq
+character, or the special value
+\(lq*\(rq.
+A value of
+\(lq*\(rq
+indicates that the user may specify the root directory by running
+\fBsudo\fR
+with the
+\fB\-R\fR
+option.
+This setting can be used to run the command in a
+chroot(2)
+\(lqsandbox\(rq
+similar to the
+chroot(@mansectsu@)
+utility.
+Path names of the form
+\fI~user/path/name\fR
+are interpreted as being relative to the named user's home directory.
+If the user name is omitted, the path will be relative to the runas
+user's home directory.
+.PP
+This setting is only supported by version 1.9.3 or higher.
+.SS "Tag_Spec"
+A command may have zero or more tags associated with it.
+The following tag values are supported:
+\fREXEC\fR,
+\fRNOEXEC\fR,
+\fRFOLLOW\fR,
+\fRNOFOLLOW\fR,
+\fRLOG_INPUT\fR,
+\fRNOLOG_INPUT\fR,
+\fRLOG_OUTPUT\fR,
+\fRNOLOG_OUTPUT\fR,
+\fRMAIL\fR,
+\fRNOMAIL\fR,
+\fRINTERCEPT\fR,
+\fRNOINTERCEPT\fR,
+\fRPASSWD\fR,
+\fRNOPASSWD\fR,
+\fRSETENV\fR,
+and
+\fRNOSETENV\fR.
+Once a tag is set on a
+\fICmnd\fR,
+subsequent
+\fICmnd\fRs
+in the
+\fICmnd_Spec_List\fR,
+inherit the tag unless it is overridden by the opposite tag (in other words,
+\fRPASSWD\fR
+overrides
+\fRNOPASSWD\fR
+and
+\fRNOEXEC\fR
+overrides
+\fREXEC\fR).
+.TP 2n
+\fREXEC\fR and \fRNOEXEC\fR
+.sp
+If
+\fBsudo\fR
+has been compiled with
+\fInoexec\fR
+support and the underlying operating system supports it, the
+\fRNOEXEC\fR
+tag can be used to prevent a dynamically-linked executable from
+running further commands itself.
+.sp
+In the following example, user
+\fBaaron\fR
+may run
+\fI/usr/bin/more\fR
+and
+\fI/usr/bin/vi\fR
+on the host shanty, but shell escapes will be disabled.
+.nf
+.sp
+.RS 2n
+aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi
+.RE
+.fi
+.RS 2n
+.sp
+See the
+\fIPreventing shell escapes\fR
+section below for more details on how
+\fRNOEXEC\fR
+works and whether or not it will work on your system.
+.RE
+.TP 2n
+\fRFOLLOW\fR and \fRNOFOLLOW\fR
+.sp
+Starting with version 1.8.15,
+\fBsudoedit\fR
+will not open a file that is a symbolic link unless the
+\fIsudoedit_follow\fR
+flag is enabled.
+The
+\fRFOLLOW\fR
+and
+\fRNOFOLLOW\fR
+tags override the value of
+\fIsudoedit_follow\fR
+and can be used to permit (or deny) the editing of symbolic links
+on a per-command basis.
+These tags are only effective for the
+\fIsudoedit\fR
+command and are ignored for all other commands.
+.TP 2n
+\fRLOG_INPUT\fR and \fRNOLOG_INPUT\fR
+.sp
+These tags override the value of the
+\fIlog_input\fR
+flag on a per-command basis.
+For more information, see
+\fII/O LOGGING\fR.
+.TP 2n
+\fRLOG_OUTPUT\fR and \fRNOLOG_OUTPUT\fR
+.sp
+These tags override the value of the
+\fIlog_output\fR
+flag on a per-command basis.
+For more information, see
+\fII/O LOGGING\fR.
+.TP 2n
+\fRMAIL\fR and \fRNOMAIL\fR
+.sp
+These tags provide fine-grained control over whether
+mail will be sent when a user runs a command by
+overriding the value of the
+\fImail_all_cmnds\fR
+flag on a per-command basis.
+They have no effect when
+\fBsudo\fR
+is run with the
+\fB\-l\fR
+or
+\fB\-v\fR
+options.
+A
+\fRNOMAIL\fR
+tag will also override the
+\fImail_always\fR
+and
+\fImail_no_perms\fR
+options.
+For more information, see the descriptions of
+\fImail_all_cmnds\fR,
+\fImail_always\fR,
+and
+\fImail_no_perms\fR
+in the
+\fISUDOERS OPTIONS\fR
+section below.
+.TP 2n
+\fRPASSWD\fR and \fRNOPASSWD\fR
+.sp
+By default,
+\fBsudo\fR
+requires that a user authenticate
+before running a command.
+This behavior can be modified via the
+\fRNOPASSWD\fR
+tag.
+Like a
+\fIRunas_Spec\fR,
+the
+\fRNOPASSWD\fR
+tag sets
+a default for the commands that follow it in the
+\fICmnd_Spec_List\fR.
+Conversely, the
+\fRPASSWD\fR
+tag can be used to reverse things.
+For example:
+.nf
+.sp
+.RS 2n
+ray rushmore = NOPASSWD: /bin/kill, /bin/ls, /usr/bin/lprm
+.RE
+.fi
+.RS 2n
+.sp
+would allow the user
+\fBray\fR
+to run
+\fI/bin/kill\fR,
+\fI/bin/ls\fR,
+and
+\fI/usr/bin/lprm\fR
+as
+\fB@runas_default@\fR
+on the machine
+\(lqrushmore\(rq
+without authenticating himself.
+If we only want
+\fBray\fR
+to be able to
+run
+\fI/bin/kill\fR
+without a password the entry would be:
+.nf
+.sp
+.RS 2n
+ray rushmore = NOPASSWD: /bin/kill, PASSWD: /bin/ls, /usr/bin/lprm
+.RE
+.fi
+.sp
+Note, however, that the
+\fRPASSWD\fR
+tag has no effect on users who are in the group specified by the
+\fIexempt_group\fR
+setting.
+.sp
+By default, if the
+\fRNOPASSWD\fR
+tag is applied to any of a user's entries for the current host,
+the user will be able to run
+\(oqsudo -l\(cq
+without a password.
+Additionally, a user may only run
+\(oqsudo -v\(cq
+without a password if all of the user's entries for the current
+host have the
+\fRNOPASSWD\fR
+tag.
+This behavior may be overridden via the
+\fIverifypw\fR
+and
+\fIlistpw\fR
+options.
+.RE
+.TP 2n
+\fRSETENV\fR and \fRNOSETENV\fR
+.sp
+These tags override the value of the
+\fIsetenv\fR
+flag on a per-command basis.
+If
+\fRSETENV\fR
+has been set for a command, the user may disable the
+\fIenv_reset\fR
+flag from the command line via the
+\fB\-E\fR
+option.
+Additionally, environment variables set on the command
+line are not subject to the restrictions imposed by
+\fIenv_check\fR,
+\fIenv_delete\fR,
+or
+\fIenv_keep\fR.
+As such, only trusted users should be allowed to set variables in this manner.
+If the command matched is
+\fBALL\fR,
+the
+\fRSETENV\fR
+tag is implied for that command; this default may be overridden by use of the
+\fRNOSETENV\fR
+tag.
+.TP 2n
+\fRINTERCEPT\fR and \fRNOINTERCEPT\fR
+.sp
+If
+\fBsudo\fR
+has been compiled with
+\fIintercept\fR
+support and the underlying operating system supports it, the
+\fRINTERCEPT\fR
+tag can be used to cause programs spawned by a command to be validated against
+\fIsudoers\fR
+and logged just like they would be if run through
+\fBsudo\fR
+directly.
+This is useful in conjunction with commands that allow shell escapes
+such as editors, shells, and paginators.
+There is additional overhead due to the policy check that may add
+latency when running commands such as shell scripts that execute a
+large number of sub-commands.
+For interactive commands, such as a shell or editor,
+the overhead is not usually noticeable.
+.sp
+In the following example, user
+\fBchuck\fR
+may run any command on the machine
+\(lqresearch\(rq
+in intercept mode.
+.nf
+.sp
+.RS 2n
+chuck research = INTERCEPT: ALL
+.RE
+.fi
+.RS 2n
+.sp
+See the
+\fIPreventing shell escapes\fR
+section below for more details on how
+\fRINTERCEPT\fR
+works and whether or not it will work on your system.
+.RE
+.SS "Wildcards"
+\fBsudo\fR
+allows shell-style
+\fIwildcards\fR
+(aka meta or glob characters)
+to be used in host names, path names, and command line arguments in the
+\fIsudoers\fR
+file.
+Wildcard matching is done via the
+glob(3)
+and
+fnmatch(3)
+functions as specified by
+IEEE Std 1003.1 (\(lqPOSIX.1\(rq).
+.TP 8n
+*
+Matches any set of zero or more characters (including white space).
+.TP 8n
+\&?
+Matches any single character (including white space).
+.TP 8n
+[...]
+Matches any character in the specified range.
+.TP 8n
+[!...]
+Matches any character
+\fInot\fR
+in the specified range.
+.TP 8n
+\ex
+For any character
+\(oqx\(cq,
+evaluates to
+\(oqx\(cq.
+This is used to escape special characters such as:
+\(oq*\(cq,
+\(oq\&?\(cq,
+\(oq[\&\(cq,
+and
+\(oq]\&\(cq.
+.PP
+\fBThese are not regular expressions.\fR
+Unlike a regular expression there is no way to match one or more
+characters within a range.
+.PP
+Character classes may be used if your system's
+glob(3)
+and
+fnmatch(3)
+functions support them.
+However, because the
+\(oq:\&\(cq
+character has special meaning in
+\fIsudoers\fR,
+it must be
+escaped.
+For example:
+.nf
+.sp
+.RS 4n
+/bin/ls [[\e:\&alpha\e:\&]]*
+.RE
+.fi
+.PP
+Would match any file name beginning with a letter.
+.PP
+A forward slash
+(\(oq/\(cq)
+will
+\fInot\fR
+be matched by
+wildcards used in the file name portion of the command.
+This is to make a path like:
+.nf
+.sp
+.RS 4n
+/usr/bin/*
+.RE
+.fi
+.PP
+match
+\fI/usr/bin/who\fR
+but not
+\fI/usr/bin/X11/xterm\fR.
+.PP
+When matching the command line arguments, however, a slash
+\fIdoes\fR
+get matched by wildcards since command line arguments may contain
+arbitrary strings and not just path names.
+.PP
+\fBWildcards in command line arguments should be used with care.\fR
+.br
+Wildcards can match any character, including white space.
+In most cases, it is safer to use a regular expression to match
+command line arguments.
+For more information, see
+\fIWildcards in command arguments\fR
+below.
+.SS "Exceptions to wildcard rules"
+The following exceptions apply to the above rules:
+.TP 10n
+\&""
+If the empty string
+\(oq\&""\(cq
+is the only command line argument in the
+\fIsudoers\fR
+file entry it means that command is not allowed to be run with
+\fIany\fR
+arguments.
+.TP 10n
+sudoedit
+Command line arguments to the
+\fIsudoedit\fR
+built-in command should always be path names, so a forward slash
+(\(oq/\(cq)
+will not be matched by a wildcard.
+.SS "Regular expressions"
+Starting with version 1.9.10, it is possible to use
+regular expressions for path names and command line arguments.
+Regular expressions are more expressive than shell-style
+\fIwildcards\fR
+and are usually safer because they provide a greater degree of
+control when matching.
+The type of regular expressions supported by
+\fBsudoers\fR
+are POSIX extended regular expressions, similar to those used by the
+egrep(1)
+utility.
+They are usually documented in the
+regex(@mansectmisc@)
+or
+re_format(@mansectmisc@)
+manual, depending on the system.
+As an extension, if the regular expression begins with
+\(lq(?i)\(rq,
+it will be matched in a case-insensitive manner.
+.PP
+In
+\fIsudoers\fR,
+regular expressions must start with a
+\(oq^\(cq
+character and end with a
+\(oq$\(cq.
+This makes it explicit what is, or is not, a regular expression.
+Either the path name, the command line arguments or both may
+be regular expressions.
+Because the path name and arguments are matched separately, it is
+even possible to use wildcards for the path name and regular
+expressions for the arguments.
+It is not possible to use a single regular expression to match
+both the command and its arguments.
+Regular expressions in
+\fIsudoers\fR
+are limited to 1024 characters.
+.PP
+There is no need to escape
+\fIsudoers\fR
+special characters in a regular expression other than the pound sign
+(\(oq#\(cq).
+.PP
+In the following example, user
+\fBjohn\fR
+can run the
+passwd(1)
+command as
+\fB@runas_default@\fR
+on any host but is not allowed to change
+\fBroot\fR's
+password.
+This kind of rule is impossible to express safely using wildcards.
+.nf
+.sp
+.RS 4n
+john ALL = /usr/bin/passwd ^[a-zA-Z0-9_]+$,\e
+ !/usr/bin/passwd root
+.RE
+.fi
+.PP
+It is also possible to use a regular expression in conjunction with
+\fBsudoedit\fR
+rules.
+The following rule would give user bob the ability to edit the
+\fI/etc/motd\fR,
+\fI/etc/issue\fR,
+and
+\fI/etc/hosts\fR
+files only.
+.nf
+.sp
+.RS 4n
+bob ALL = sudoedit ^/etc/(motd|issue|hosts)$
+.RE
+.fi
+.PP
+Regular expressions may also be used to match the command itself.
+In this example, a regular expression is used to allow user
+\fBsid\fR
+to run the
+\fI/usr/sbin/groupadd\fR,
+\fI/usr/sbin/groupmod\fR,
+\fI/usr/sbin/groupdel\fR,
+\fI/usr/sbin/useradd\fR,
+\fI/usr/sbin/usermod\fR,
+and
+\fI/usr/sbin/userdel\fR
+commands as
+\fB@runas_default@\fR.
+.nf
+.sp
+.RS 4n
+sid ALL = ^/usr/sbin/(group|user)(add|mod|del)$
+.RE
+.fi
+.PP
+One disadvantage of using a regular expression to match the command
+name is that it is not possible to match relative paths such as
+\fI./useradd\fR
+or
+\fI../sbin/useradd\fR.
+This has security implications when a regular expression is used
+for the command name in conjunction with the negation operator,
+\(oq!\&\(cq,
+as such rules can be trivially bypassed.
+Because of this, using a negated regular expression for the command name is
+\fBstrongly discouraged\fR.
+This does not apply to negated commands that only use a regular
+expression to match the command arguments.
+See
+\fIRegular expressions in command names\fR
+below for more information.
+.SS "Including other files from within sudoers"
+It is possible to include other
+\fIsudoers\fR
+files from within the
+\fIsudoers\fR
+file currently being parsed using the
+\fI@include\fR
+and
+\fI@includedir\fR
+directives.
+For compatibility with sudo versions prior to 1.9.1,
+\fI#include\fR
+and
+\fI#includedir\fR
+are also accepted.
+.PP
+An include file can be used, for example, to keep a site-wide
+\fIsudoers\fR
+file in addition to a local, per-machine file.
+For the sake of this example the site-wide
+\fIsudoers\fR
+file will be
+\fI/etc/sudoers\fR
+and the per-machine one will be
+\fI/etc/sudoers.local\fR.
+To include
+\fI/etc/sudoers.local\fR
+from within
+\fI/etc/sudoers\fR
+one would use the following line in
+\fI/etc/sudoers\fR:
+.nf
+.sp
+.RS 4n
+@include /etc/sudoers.local
+.RE
+.fi
+.PP
+When
+\fBsudo\fR
+reaches this line it will suspend processing of the current file
+(\fI/etc/sudoers\fR)
+and switch to
+\fI/etc/sudoers.local\fR.
+Upon reaching the end of
+\fI/etc/sudoers.local\fR,
+the rest of
+\fI/etc/sudoers\fR
+will be processed.
+Files that are included may themselves include other files.
+A hard limit of 128 nested include files is enforced to prevent include
+file loops.
+.PP
+Starting with version 1.9.1, the path to the include file may contain
+white space if it is escaped with a backslash
+(\(oq\e\(cq).
+Alternately, the entire path may be enclosed in double quotes
+(\&""),
+in which case no escaping is necessary.
+To include a literal backslash in the path,
+\(oq\e\e\(cq
+should be used.
+.PP
+If the path to the include file is not fully-qualified (does not
+begin with a
+\(oq/\(cq),
+it must be located in the same directory as the sudoers file it was
+included from.
+For example, if
+\fI/etc/sudoers\fR
+contains the line:
+.nf
+.sp
+.RS 4n
+@include sudoers.local
+.RE
+.fi
+.PP
+the file that will be included is
+\fI/etc/sudoers.local\fR.
+.PP
+The file name may also include the
+\(oq%h\(cq
+escape, signifying the short form of the host name.
+In other words, if the machine's host name is
+\(lqxerxes\(rq,
+then
+.nf
+.sp
+.RS 4n
+@include /etc/sudoers.%h
+.RE
+.fi
+.PP
+will cause
+\fBsudo\fR
+to include the file
+\fI/etc/sudoers.xerxes\fR.
+Any path name separator characters
+(\(oq/\(cq)
+present in the host name will be replaced with an underbar
+(\(oq_\(cq)
+during expansion.
+.PP
+The
+\fI@includedir\fR
+directive can be used to create a
+\fIsudoers.d\fR
+directory that the system package manager can drop
+\fIsudoers\fR
+file rules into as part of package installation.
+For example, given:
+.nf
+.sp
+.RS 4n
+@includedir /etc/sudoers.d
+.RE
+.fi
+.PP
+\fBsudo\fR
+will suspend processing of the current file and read each file in
+\fI/etc/sudoers.d\fR,
+skipping file names that end in
+\(oq~\(cq
+or contain a
+\(oq.\&\(cq
+character to avoid causing problems with package manager or editor
+temporary/backup files.
+.PP
+Files are parsed in sorted lexical order.
+That is,
+\fI/etc/sudoers.d/01_first\fR
+will be parsed before
+\fI/etc/sudoers.d/10_second\fR.
+Be aware that because the sorting is lexical, not numeric,
+\fI/etc/sudoers.d/1_whoops\fR
+would be loaded
+\fIafter\fR
+\fI/etc/sudoers.d/10_second\fR.
+Using a consistent number of leading zeroes in the file names can be used
+to avoid such problems.
+After parsing the files in the directory, control returns to the
+file that contained the
+\fI@includedir\fR
+directive.
+.PP
+Unlike files included via
+\fI@include\fR,
+\fBvisudo\fR
+will not edit the files in a
+\fI@includedir\fR
+directory unless one of them contains a syntax error.
+It is still possible to run
+\fBvisudo\fR
+with the
+\fB\-f\fR
+flag to edit the files directly, but this will not catch the
+redefinition of an
+\fIalias\fR
+that is also present in a different file.
+.SS "Other special characters and reserved words"
+The pound sign
+(\(oq#\(cq)
+is used to indicate a comment (unless it is part of a #include
+directive or unless it occurs in the context of a user name and is
+followed by one or more digits, in which case it is treated as a
+user-ID).
+Both the comment character and any text after it, up to the end of
+the line, are ignored.
+.PP
+The reserved word
+\fBALL\fR
+is a built-in
+\fIalias\fR
+that always causes a match to succeed.
+It can be used wherever one might otherwise use a
+\fICmnd_Alias\fR,
+\fIUser_Alias\fR,
+\fIRunas_Alias\fR,
+or
+\fIHost_Alias\fR.
+Attempting to define an
+\fIalias\fR
+named
+\fBALL\fR
+will result in a syntax error.
+Using
+\fBALL\fR
+can be dangerous since in a command context, it allows the user to run
+\fIany\fR
+command on the system.
+.PP
+The following option names permitted in an
+\fIOption_Spec\fR
+are also considered reserved words:
+\fRCHROOT\fR,
+.if \n(PS \{\
+\fRPRIVS\fR,
+.\}
+.if \n(PS \{\
+\fRLIMITPRIVS\fR,
+.\}
+.if \n(SL \{\
+\fRROLE\fR,
+.\}
+.if \n(SL \{\
+\fRTYPE\fR,
+.\}
+\fRTIMEOUT\fR,
+\fRCWD\fR,
+\fRNOTBEFORE\fR
+and
+\fRNOTAFTER\fR.
+Attempting to define an
+\fIalias\fR
+with the same name as one of the options will result in a syntax error.
+.PP
+An exclamation point
+(\(oq\&!\(cq)
+can be used as a logical
+\fInot\fR
+operator in a list or
+\fIalias\fR
+as well as in front of a
+\fICmnd\fR.
+This allows one to exclude certain values.
+For the
+\(oq\&!\(cq
+operator to be effective, there must be something for it to exclude.
+For example, to match all users except for
+\fBroot\fR
+one would use:
+.nf
+.sp
+.RS 4n
+ALL, !root
+.RE
+.fi
+.PP
+If the
+\fBALL\fR,
+is omitted, as in:
+.nf
+.sp
+.RS 4n
+!root
+.RE
+.fi
+.PP
+it would explicitly deny
+\fBroot\fR
+but not match any other users.
+This is different from a true
+\(lqnegation\(rq
+operator.
+.PP
+Note, however, that using a
+\(oq\&!\(cq
+in conjunction with the built-in
+\fBALL\fR
+alias to allow a user to run
+\(lqall but a few\(rq
+commands rarely works as intended (see
+\fISECURITY NOTES\fR
+below).
+.PP
+Long lines can be continued with a backslash
+(\(oq\e\(cq)
+as the last character on the line.
+.PP
+White space between elements in a list as well as special syntactic
+characters in a
+\fIUser Specification\fR
+(\(oq=\&\(cq,
+\(oq:\&\(cq,
+\(oq(\&\(cq,
+\(oq)\&\(cq)
+is optional.
+.PP
+The following characters must be escaped with a backslash
+(\(oq\e\(cq)
+when used as part of a word (e.g., a user name or host name):
+\(oq\&!\(cq,
+\(oq=\&\(cq,
+\(oq:\&\(cq,
+\(oq,\&\(cq,
+\(oq(\&\(cq,
+\(oq)\&\(cq,
+\(oq\e\(cq.
+.SH "SUDOERS OPTIONS"
+\fBsudo\fR's
+behavior can be modified by
+\fIDefault_Entry\fR
+lines, as explained earlier.
+A list of all supported Defaults parameters, grouped by type, are listed below.
+.PP
+\fBBoolean Flags\fR:
+.TP 18n
+always_query_group_plugin
+If a
+\fIgroup_plugin\fR
+is configured, use it to resolve groups of the form
+\(oq%group\(cq
+as long as there is not also a system group of the same name.
+Normally, only groups of the form
+\(oq%:group\(cq
+are passed to the
+\fIgroup_plugin\fR.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+always_set_home
+If enabled,
+\fBsudo\fR
+will set the
+\fRHOME\fR
+environment variable to the home directory of the target user
+(which is the
+\fIrunas_default\fR
+user unless the
+\fB\-u\fR
+option is used).
+This flag is largely obsolete and has no effect unless the
+\fIenv_reset\fR
+flag has been disabled or
+\fRHOME\fR
+is present in the
+\fIenv_keep\fR
+list, both of which are strongly discouraged.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+authenticate
+If set, users must authenticate themselves via a password (or other
+means of authentication) before they may run commands.
+This default may be overridden via the
+\fRPASSWD\fR
+and
+\fRNOPASSWD\fR
+tags.
+This flag is
+\fIon\fR
+by default.
+.TP 18n
+case_insensitive_group
+If enabled, group names in
+\fIsudoers\fR
+will be matched in a case insensitive manner.
+This may be necessary when users are stored in LDAP or AD.
+This flag is
+\fIon\fR
+by default.
+.TP 18n
+case_insensitive_user
+If enabled, user names in
+\fIsudoers\fR
+will be matched in a case insensitive manner.
+This may be necessary when groups are stored in LDAP or AD.
+This flag is
+\fIon\fR
+by default.
+.TP 18n
+closefrom_override
+If set, the user may use the
+\fB\-C\fR
+option which overrides the default starting point at which
+\fBsudo\fR
+begins closing open file descriptors.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+compress_io
+If set, and
+\fBsudo\fR
+is configured to log a command's input or output,
+the I/O logs will be compressed using
+\fBzlib\fR.
+This flag is
+\fIon\fR
+by default when
+\fBsudo\fR
+is compiled with
+\fBzlib\fR
+support.
+.TP 18n
+exec_background
+By default,
+\fBsudo\fR
+runs a command as the foreground process as long as
+\fBsudo\fR
+itself is running in the foreground.
+When the
+\fIexec_background\fR
+flag is enabled and the command is being run in a pseudo-terminal
+(due to I/O logging or the
+\fIuse_pty\fR
+flag), the command will be run as a background process.
+Attempts to read from the controlling terminal (or to change terminal
+settings) will result in the command being suspended with the
+\fRSIGTTIN\fR
+signal (or
+\fRSIGTTOU\fR
+in the case of terminal settings).
+If this happens when
+\fBsudo\fR
+is a foreground process, the command will be granted the controlling terminal
+and resumed in the foreground with no user intervention required.
+The advantage of initially running the command in the background is that
+\fBsudo\fR
+need not read from the terminal unless the command explicitly requests it.
+Otherwise, any terminal input must be passed to the command, whether it
+has required it or not (the kernel buffers terminals so it is not possible
+to tell whether the command really wants the input).
+This is different from historic
+\fIsudo\fR
+behavior or when the command is not being run in a pseudo-terminal.
+.sp
+For this to work seamlessly, the operating system must support the
+automatic restarting of system calls.
+Unfortunately, not all operating systems do this by default,
+and even those that do may have bugs.
+For example, macOS fails to restart the
+tcgetattr(3)
+and
+tcsetattr(3)
+functions (this is a bug in macOS).
+Furthermore, because this behavior depends on the command stopping with the
+\fRSIGTTIN\fR
+or
+\fRSIGTTOU\fR
+signals, programs that catch these signals and suspend themselves
+with a different signal (usually
+\fRSIGTOP\fR)
+will not be automatically foregrounded.
+Some versions of the linux
+su(1)
+command behave this way.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.8.7 or higher.
+It has no effect unless I/O logging is enabled or the
+\fIuse_pty\fR
+flag is enabled.
+.TP 18n
+env_editor
+If set,
+\fBvisudo\fR
+will use the value of the
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+or
+\fREDITOR\fR
+environment variables before falling back on the default editor list.
+\fBvisudo\fR
+is typically run as
+\fBroot\fR
+so this flag may allow a user with
+\fBvisudo\fR
+privileges to run arbitrary commands as
+\fBroot\fR
+without logging.
+An alternative is to place a colon-separated list of
+\(lqsafe\(rq
+editors int the
+\fIeditor\fR
+setting.
+\fBvisudo\fR
+will then only use
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+or
+\fREDITOR\fR
+if they match a value specified in
+\fIeditor\fR.
+If the
+\fIenv_reset\fR
+flag is enabled, the
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+and/or
+\fREDITOR\fR
+environment variables must be present in the
+\fIenv_keep\fR
+list for the
+\fIenv_editor\fR
+flag to function when
+\fBvisudo\fR
+is invoked via
+\fBsudo\fR.
+This flag is
+\fI@env_editor@\fR
+by default.
+.TP 18n
+env_reset
+If set,
+\fBsudo\fR
+will run the command in a minimal environment containing the
+\fRTERM\fR,
+\fRPATH\fR,
+\fRHOME\fR,
+\fRMAIL\fR,
+\fRSHELL\fR,
+\fRLOGNAME\fR,
+\fRUSER\fR
+and
+\fRSUDO_*\fR
+variables.
+Any variables in the caller's environment or in the file specified
+by the
+\fIrestricted_env_file\fR
+setting that match the
+\fIenv_keep\fR
+and
+\fIenv_check\fR
+lists are then added, followed by any variables present in the file
+specified by the
+\fIenv_file\fR
+setting (if any).
+The contents of the
+\fIenv_keep\fR
+and
+\fIenv_check\fR
+lists, as modified by global Defaults parameters in
+\fIsudoers\fR,
+are displayed when
+\fBsudo\fR
+is run by
+\fBroot\fR
+with the
+\fB\-V\fR
+option.
+If the
+\fIsecure_path\fR
+setting is enabled, its value will be used for the
+\fRPATH\fR
+environment variable.
+This flag is
+\fI@env_reset@\fR
+by default.
+.TP 18n
+fast_glob
+Normally,
+\fBsudo\fR
+uses the
+glob(3)
+function to do shell-style globbing when matching path names.
+However, since it accesses the file system,
+glob(3)
+can take a long time to complete for some patterns, especially
+when the pattern references a network file system that is mounted
+on demand (auto mounted).
+The
+\fIfast_glob\fR
+flag causes
+\fBsudo\fR
+to use the
+fnmatch(3)
+function, which does not access the file system to do its matching.
+The disadvantage of
+\fIfast_glob\fR
+is that it is unable to match relative paths such as
+\fI./ls\fR
+or
+\fI../bin/ls\fR.
+This has security implications when path names that include globbing
+characters are used with the negation operator,
+\(oq!\&\(cq,
+as such rules can be trivially bypassed.
+As such, this flag should not be used when the
+\fIsudoers\fR
+file contains rules that contain negated path names which include globbing
+characters.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+log_passwords
+Most programs that require a user's password will disable echo before
+reading the password to avoid displaying the plaintext password on
+the screen.
+However, if terminal input is being logged (see
+\fII/O LOGGING\fR),
+the password will still be present in the I/O log.
+If the
+\fIlog_passwords\fR
+option is disabled,
+\fBsudoers\fR
+will attempt to prevent passwords from being logged.
+It does this by using the regular expressions in
+\fIpassprompt_regex\fR
+to match a password prompt in the terminal output buffer.
+When a match is found, input characters in the I/O log will be replaced with
+\(oq*\(cq
+until either a line feed or carriage return is found in the terminal input
+or a new terminal output buffer is received.
+If, however, a program displays characters as the user types
+(such as
+\fBsudo\fR
+when
+\fIpwfeedback\fR
+is set), only the
+first character of the password will be replaced in the I/O log.
+This option has no effect unless
+\fIlog_input\fR
+or
+\fIlog_ttyin\fR
+are also set.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting is only supported by version 1.9.10 or higher.
+.TP 18n
+fqdn
+Set this flag if you want to put fully qualified host names in the
+\fIsudoers\fR
+file when the local host name (as returned by the
+\(oqhostname\(cq
+command) does not contain the domain name.
+In other words, instead of myhost you would use myhost.mydomain.edu.
+You may still use the short form if you wish (and even mix the two).
+This flag is only effective when the
+\(lqcanonical\(rq
+host name, as returned by the
+getaddrinfo(3)
+or
+gethostbyname(3)
+function, is a fully-qualified domain name.
+This is usually the case when the system is configured to use DNS
+for host name resolution.
+.sp
+If the system is configured to use the
+\fI/etc/hosts\fR
+file in preference to DNS, the
+\(lqcanonical\(rq
+host name may not be fully-qualified.
+The order that sources are queried for host name resolution
+is usually specified in the
+\fI@nsswitch_conf@\fR,
+\fI@netsvc_conf@\fR,
+\fI/etc/host.conf\fR,
+or, in some cases,
+\fI/etc/resolv.conf\fR
+file.
+In the
+\fI/etc/hosts\fR
+file, the first host name of the entry is considered to be the
+\(lqcanonical\(rq
+name; subsequent names are aliases that are not used by
+\fBsudoers\fR.
+For example, the following hosts file line for the machine
+\(lqxyzzy\(rq
+has the fully-qualified domain name as the
+\(lqcanonical\(rq
+host name, and the short version as an alias.
+.sp
+.RS 24n
+192.168.1.1 xyzzy.sudo.ws xyzzy
+.RE
+.RS 18n
+.sp
+If the machine's hosts file entry is not formatted properly, the
+\fIfqdn\fR
+flag will not be effective if it is queried before DNS.
+.sp
+Beware that when using DNS for host name resolution, turning on
+\fIfqdn\fR
+requires
+\fBsudoers\fR
+to make DNS lookups which renders
+\fBsudo\fR
+unusable if DNS stops working (for example if the machine is disconnected
+from the network).
+Just like with the hosts file, you must use the
+\(lqcanonical\(rq
+name as DNS knows it.
+That is, you may not use a host alias (CNAME entry) due to performance
+issues and the fact that there is no way to get all aliases from DNS.
+.sp
+This flag is
+\fI@fqdn@\fR
+by default.
+.RE
+.TP 18n
+ignore_audit_errors
+Allow commands to be run even if
+\fBsudoers\fR
+cannot write to the audit log.
+If enabled, an audit log write failure is not treated as a fatal error.
+If disabled, a command may only be run after the audit event is successfully
+written.
+This flag is only effective on systems for which
+\fBsudoers\fR
+supports audit logging, including
+FreeBSD,
+Linux, macOS, and Solaris.
+This flag is
+\fIon\fR
+by default.
+.TP 18n
+ignore_dot
+If set,
+\fBsudo\fR
+will ignore "." or "" (both denoting the current directory) in the
+\fRPATH\fR
+environment variable; the
+\fRPATH\fR
+itself is not modified.
+This flag is
+\fI@ignore_dot@\fR
+by default.
+.TP 18n
+ignore_iolog_errors
+Allow commands to be run even if
+\fBsudoers\fR
+cannot write to the I/O log (local or remote).
+If enabled, an I/O log write failure is not treated as a fatal error.
+If disabled, the command will be terminated if the I/O log cannot be written to.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+ignore_logfile_errors
+Allow commands to be run even if
+\fBsudoers\fR
+cannot write to the log file.
+If enabled, a log file write failure is not treated as a fatal error.
+If disabled, a command may only be run after the log file entry is successfully
+written.
+This flag only has an effect when
+\fBsudoers\fR
+is configured to use file-based logging via the
+\fIlogfile\fR
+setting.
+This flag is
+\fIon\fR
+by default.
+.TP 18n
+ignore_local_sudoers
+If set via LDAP, parsing of
+\fI@sysconfdir@/sudoers\fR
+will be skipped.
+This is intended for sites that wish to prevent the usage of local
+sudoers files so that only LDAP is used.
+This thwarts the efforts of rogue operators who would attempt to add roles to
+\fI@sysconfdir@/sudoers\fR.
+When this flag is enabled,
+\fI@sysconfdir@/sudoers\fR
+does not even need to exist.
+Since this flag tells
+\fBsudo\fR
+how to behave when no specific LDAP entries have been matched, this
+sudoOption is only meaningful for the
+\(oqcn=defaults\(cq
+section.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+ignore_unknown_defaults
+If set,
+\fBsudo\fR
+will not produce a warning if it encounters an unknown Defaults entry
+in the
+\fIsudoers\fR
+file or an unknown sudoOption in LDAP.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+insults
+If set,
+\fBsudo\fR
+will insult users when they enter an incorrect password.
+This flag is
+\fI@insults@\fR
+by default.
+.TP 18n
+log_allowed
+If set,
+\fBsudoers\fR
+will log commands allowed by the policy to the system audit log
+(where supported) as well as to syslog and/or a log file.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting is only supported by version 1.8.29 or higher.
+.TP 18n
+log_denied
+If set,
+\fBsudoers\fR
+will log commands denied by the policy to the system audit log
+(where supported) as well as to syslog and/or a log file.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting is only supported by version 1.8.29 or higher.
+.TP 18n
+log_exit_status
+If set,
+\fBsudoers\fR
+will log the exit value of commands that are run to syslog and/or a log file.
+If a command was terminated by a signal, the signal name is logged as well.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.9.8 or higher.
+.TP 18n
+log_host
+If set, the host name will be included in log entries written to
+the file configured by the
+\fIlogfile\fR
+setting.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+log_input
+If set,
+\fBsudo\fR
+will run the command in a pseudo-terminal (if
+\fBsudo\fR
+was run from a terminal) and log all user input.
+If the standard input is not connected to the user's terminal, due
+to I/O redirection or because the command is part of a pipeline,
+that input is also logged.
+For more information about I/O logging, see the
+\fII/O LOGGING\fR
+section.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+log_output
+If set,
+\fBsudo\fR
+will run the command in a pseudo-terminal (if
+\fBsudo\fR
+was run from a terminal) and log all output that is sent to the
+user's terminal, the standard output or the standard error.
+If the standard output or standard error is not connected to the
+user's terminal, due to I/O redirection or because the command is
+part of a pipeline, that output is also logged.
+For more information about I/O logging, see the
+\fII/O LOGGING\fR
+section.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+log_server_keepalive
+If set,
+\fBsudo\fR
+will enable the TCP keepalive socket option on the connection to the log server.
+This enables the periodic transmission of keepalive messages to the server.
+If the server does not respond to a message, the connection will
+be closed and the running command will be terminated unless the
+\fIignore_iolog_errors\fR
+flag (I/O logging enabled) or the
+\fIignore_log_errors\fR
+flag (I/O logging disabled) is set.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.TP 18n
+log_server_verify
+.br
+If set, the server certificate received during the TLS handshake
+must be valid and it must contain either the server name (from
+\fIlog_servers\fR)
+or its IP address.
+If either of these conditions is not met, the TLS handshake will fail.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.TP 18n
+log_stderr
+If set,
+\fBsudo\fR
+will log the standard error if it is not connected to the user's terminal.
+This can be used to log output to a pipe or redirected to a file.
+This flag is
+\fIoff\fR
+by default but is enabled when either the
+\fIlog_output\fR
+flag or the
+\fRLOG_OUTPUT\fR
+command tag is set.
+.TP 18n
+log_stdin
+If set,
+\fBsudo\fR
+will log the standard input if it is not connected to the user's terminal.
+This can be used to log input from a pipe or redirected from a file.
+This flag is
+\fIoff\fR
+by default but is enabled when either the
+\fIlog_input\fR
+flag or the
+\fRLOG_INPUT\fR
+command tag is set.
+.TP 18n
+log_stdout
+If set,
+\fBsudo\fR
+will log the standard output if it is not connected to the user's terminal.
+This can be used to log output to a pipe or redirected to a file.
+This flag is
+\fIoff\fR
+by default but is enabled when either the
+\fIlog_output\fR
+flag or the
+\fRLOG_OUTPUT\fR
+command tag is set.
+.TP 18n
+log_subcmds
+If set,
+\fBsudoers\fR
+will log when a command spawns a child process and executes a program
+using the
+execve(2),
+execl(3),
+execle(3),
+execlp(3),
+execv(3),
+execvp(3),
+execvpe(3),
+or
+system(3)
+library functions.
+For example, if a shell is run by
+\fBsudo\fR,
+the individual commands run via the shell will be logged.
+This flag is
+\fIoff\fR
+by default.
+.sp
+The
+\fIlog_subcmds\fR
+flag uses the same underlying mechanism as the
+\fIintercept\fR
+setting.
+Some commands may not work properly when
+\fIlog_subcmds\fR
+is enabled, due to the way it intercepts sub-commands.
+See
+\fIPreventing shell escapes\fR
+for more information on what systems support this option and its limitations.
+This setting is only supported by version 1.9.8 or higher
+and is incompatible with SELinux RBAC support unless the system supports
+seccomp(2)
+filter mode.
+.TP 18n
+log_ttyin
+If set,
+\fBsudo\fR
+will run the command in a pseudo-terminal and log user keystrokes
+sent to the user's terminal, if one is present.
+This flag is
+\fIoff\fR
+by default but is enabled when either the
+\fIlog_input\fR
+flag or the
+\fRLOG_INPUT\fR
+command tag is set.
+If no terminal is present, for example when running a remote command using
+ssh(1),
+this flag will have no effect.
+.TP 18n
+log_ttyout
+If set,
+\fBsudo\fR
+will run the command in a pseudo-terminal and log all output displayed
+on the user's terminal, if one is present.
+This flag is
+\fIoff\fR
+by default but is enabled when either the
+\fIlog_output\fR
+flag or the
+\fRLOG_OUTPUT\fR
+command tag is set.
+If no terminal is present, for example when running a remote command using
+ssh(1),
+this flag will have no effect.
+.TP 18n
+log_year
+If set, the four-digit year will be logged in the (non-syslog)
+\fBsudo\fR
+log file.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+long_otp_prompt
+When validating with a One Time Password (OTP) scheme such as
+\fBS/Key\fR
+or
+\fBOPIE\fR,
+a two-line prompt is used to make it easier
+to cut and paste the challenge to a local window.
+It's not as pretty as the default but some people find it more convenient.
+This flag is
+\fI@long_otp_prompt@\fR
+by default.
+.TP 18n
+mail_all_cmnds
+Send mail to the
+\fImailto\fR
+user every time a user attempts to run a command via
+\fBsudo\fR
+(this includes
+\fBsudoedit\fR).
+No mail will be sent if the user runs
+\fBsudo\fR
+with the
+\fB\-l\fR
+or
+\fB\-v\fR
+option unless there is an authentication error and the
+\fImail_badpass\fR
+flag is also set.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+mail_always
+Send mail to the
+\fImailto\fR
+user every time a user runs
+\fBsudo\fR.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+mail_badpass
+Send mail to the
+\fImailto\fR
+user if the user running
+\fBsudo\fR
+does not enter the correct password.
+If the command the user is attempting to run is not permitted by
+\fBsudoers\fR
+and one of the
+\fImail_all_cmnds\fR,
+\fImail_always\fR,
+\fImail_no_host\fR,
+\fImail_no_perms\fR
+or
+\fImail_no_user\fR
+flags are set, this flag will have no effect.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+mail_no_host
+If set, mail will be sent to the
+\fImailto\fR
+user if the invoking user exists in the
+\fIsudoers\fR
+file, but is not allowed to run commands on the current host.
+This flag is
+\fI@mail_no_host@\fR
+by default.
+.TP 18n
+mail_no_perms
+If set, mail will be sent to the
+\fImailto\fR
+user if the invoking user is allowed to use
+\fBsudo\fR
+but the command they are trying is not listed in their
+\fIsudoers\fR
+file entry or is explicitly denied.
+This flag is
+\fI@mail_no_perms@\fR
+by default.
+.TP 18n
+mail_no_user
+If set, mail will be sent to the
+\fImailto\fR
+user if the invoking user is not in the
+\fIsudoers\fR
+file.
+This flag is
+\fI@mail_no_user@\fR
+by default.
+.TP 18n
+match_group_by_gid
+By default,
+\fBsudoers\fR
+will look up each group the user is a member of by group-ID to
+determine the group name (this is only done once).
+The resulting list of the user's group names is used when matching
+groups listed in the
+\fIsudoers\fR
+file.
+This works well on systems where the number of groups listed in the
+\fIsudoers\fR
+file is larger than the number of groups a typical user belongs to.
+On systems where group lookups are slow, where users may belong
+to a large number of groups, or where the number of groups listed
+in the
+\fIsudoers\fR
+file is relatively small, it may be prohibitively expensive and
+running commands via
+\fBsudo\fR
+may take longer than normal.
+On such systems it may be faster to use the
+\fImatch_group_by_gid\fR
+flag to avoid resolving the user's group-IDs to group names.
+In this case,
+\fBsudoers\fR
+must look up any group name listed in the
+\fIsudoers\fR
+file and use the group-ID instead of the group name when determining
+whether the user is a member of the group.
+.sp
+If
+\fImatch_group_by_gid\fR
+is enabled, group database lookups performed by
+\fBsudoers\fR
+will be keyed by group name as opposed to group-ID.
+On systems where there are multiple sources for the group database,
+it is possible to have conflicting group names or group-IDs in the local
+\fI/etc/group\fR
+file and the remote group database.
+On such systems, enabling or disabling
+\fImatch_group_by_gid\fR
+can be used to choose whether group database queries are performed
+by name (enabled) or ID (disabled), which may aid in working around
+group entry conflicts.
+.sp
+The
+\fImatch_group_by_gid\fR
+flag has no effect when
+\fIsudoers\fR
+data is stored in LDAP.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.8.18 or higher.
+.TP 18n
+intercept
+If set, all commands run via
+\fBsudo\fR
+will behave as if the
+\fRINTERCEPT\fR
+tag has been set, unless overridden by an
+\fRNOINTERCEPT\fR
+tag.
+Some commands may not work properly when
+\fIintercept\fR
+is enabled, due to the way it intercept sub-commands.
+See the description of
+\fRINTERCEPT and NOINTERCEPT\fR
+above as well as the
+\fIPreventing shell escapes\fR
+section at the end of this manual.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.9.8 or higher
+and is incompatible with SELinux RBAC support unless the system supports
+seccomp(2)
+filter mode.
+.TP 18n
+intercept_allow_setid
+On most systems, the dynamic loader will ignore
+\fRLD_PRELOAD\fR
+(or the equivalent) when running set-user-ID and set-group-ID
+programs, effectively disabling intercept mode.
+To prevent this from happening,
+\fBsudoers\fR
+will not permit a set-user-ID or set-group-ID program to be run in
+intercept mode unless
+\fIintercept_allow_setid\fR
+is enable.
+This flag has no effect unless the
+\fIintercept\fR
+flag is enabled or the
+\fRINTERCEPT\fR
+tag has been set for the command.
+This flag is
+\fIon\fR
+by default when the
+\fIintercept_type\fR
+option is set to
+\fItrace\fR,
+otherwise it default to
+\fIoff\fR.
+.sp
+This setting is only supported by version 1.9.8 or higher.
+.TP 18n
+intercept_authenticate
+If set, commands run by an intercepted process must be authenticated
+when the user's time stamp is not current.
+For example, if a shell is run with
+\fIintercept\fR
+enabled, as soon as the invoking user's time stamp is out of date,
+subsequent commands will need to be authenticated.
+This flag has no effect unless the
+\fIintercept\fR
+flag is enabled or the
+\fRINTERCEPT\fR
+tag has been set for the command.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.9.8 or higher.
+.TP 18n
+intercept_verify
+If set,
+\fBsudo\fR
+will attempt to verify that a command run in intercept mode has
+the expected path name, command line arguments and environment.
+.sp
+The process will be stopped after
+execve(2)
+has completed but before the new command has had a chance to run.
+To verify the command,
+\fBsudo\fR
+will read the command's path from
+\fI/proc/PID/exe\fR,
+the command line arguments and environment from the process's memory,
+and compare them against the arguments that were passed to
+execve(2).
+In the event of a mismatch, the command will be sent a
+\fRSIGKILL\fR
+signal and terminated.
+.sp
+This can help prevent a time of check versus time of use issue with
+intercept mode where the
+execve(2)
+arguments could be altered after the
+\fBsudoers\fR
+policy check.
+The checks can only be performed if the
+proc(@mansectform@)
+file system is available.
+This flag has no effect unless the
+\fIintercept\fR
+flag is enabled or the
+\fRINTERCEPT\fR
+tag has been set for the command and the
+\fIintercept_type\fR
+option is set to
+\fItrace\fR.
+.sp
+This setting is incompatible with programs that change their root directory via
+chroot(2).
+If a program changes its root directory, path names will no longer match
+those seen by the
+\fBsudo\fR
+parent process and sub-commands will be terminated before they have a chance
+to run.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting is only supported by version 1.9.12 or higher.
+.TP 18n
+netgroup_tuple
+If set, netgroup lookups will be performed using the full netgroup
+tuple: host name, user name, and domain (if one is set).
+Historically,
+\fBsudo\fR
+only matched the user name and domain for netgroups used in a
+\fIUser_List\fR
+and only matched the host name and domain for netgroups used in a
+\fIHost_List\fR.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+noexec
+If set, all commands run via
+\fBsudo\fR
+will behave as if the
+\fRNOEXEC\fR
+tag has been set, unless overridden by an
+\fREXEC\fR
+tag.
+See the description of
+\fREXEC and NOEXEC\fR
+above as well as the
+\fIPreventing shell escapes\fR
+section at the end of this manual.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+noninteractive_auth
+If set, authentication will be attempted even in non-interactive mode
+(when
+\fBsudo\fR's
+\fB\-n\fR
+option is specified).
+This allows authentication methods that don't require user interaction
+to succeed.
+Authentication methods that require input from the user's terminal
+will still fail.
+If disabled, authentication will not be attempted in non-interactive mode.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.9.10 or higher.
+.TP 18n
+pam_acct_mgmt
+On systems that use PAM for authentication,
+\fBsudo\fR
+will perform PAM account validation for the invoking user by default.
+The actual checks performed depend on which PAM modules are configured.
+If enabled, account validation will be performed regardless of whether
+or not a password is required.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting is only supported by version 1.8.28 or higher.
+.TP 18n
+pam_rhost
+On systems that use PAM for authentication,
+\fBsudo\fR
+will set the PAM remote host value to the name of the local host
+when the
+\fIpam_rhost\fR
+flag is enabled.
+On Linux systems, enabling
+\fIpam_rhost\fR
+may result in DNS lookups of the local host name when PAM is initialized.
+On Solaris versions prior to Solaris 8,
+\fIpam_rhost\fR
+must be enabled if
+\fIpam_ruser\fR
+is also enabled to avoid a crash in the Solaris PAM implementation.
+.sp
+This flag is
+\fIoff\fR
+by default on systems other than Solaris.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.TP 18n
+pam_ruser
+On systems that use PAM for authentication,
+\fBsudo\fR
+will set the PAM remote user value to the name of the user that invoked sudo
+when the
+\fIpam_ruser\fR
+flag is enabled.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.TP 18n
+pam_session
+On systems that use PAM for authentication,
+\fBsudo\fR
+will create a new PAM session for the command to be run in.
+Unless
+\fBsudo\fR
+is given the
+\fB\-i\fR
+or
+\fB\-s\fR
+options, PAM session modules are run with the
+\(lqsilent\(rq
+flag enabled.
+This prevents last login information from being displayed for every
+command on some systems.
+Disabling
+\fIpam_session\fR
+may be needed on older PAM implementations or on operating systems where
+opening a PAM session changes the utmp or wtmp files.
+If PAM session support is disabled, resource limits may not be updated
+for the command being run.
+If
+\fIpam_session\fR,
+\fIpam_setcred\fR,
+and
+\fIuse_pty\fR
+are disabled,
+\fIlog_servers\fR
+has not been set and I/O logging has not been configured,
+\fBsudo\fR
+will execute the command directly instead of running it as a child
+process.
+This flag is
+\fI@pam_session@\fR
+by default.
+.sp
+This setting is only supported by version 1.8.7 or higher.
+.TP 18n
+pam_setcred
+On systems that use PAM for authentication,
+\fBsudo\fR
+will attempt to establish credentials for the target user by default,
+if supported by the underlying authentication system.
+One example of a credential is a Kerberos ticket.
+If
+\fIpam_session\fR,
+\fIpam_setcred\fR,
+and
+\fIuse_pty\fR
+are disabled,
+\fIlog_servers\fR
+has not been set and I/O logging has not been configured,
+\fBsudo\fR
+will execute the command directly instead of running it as a child
+process.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting is only supported by version 1.8.8 or higher.
+.TP 18n
+passprompt_override
+If set, the prompt specified by
+\fIpassprompt\fR
+or the
+\fRSUDO_PROMPT\fR
+environment variable will always be used and will replace the
+prompt provided by a PAM module or other authentication method.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+path_info
+Normally,
+\fBsudo\fR
+will tell the user when a command could not be
+found in their
+\fRPATH\fR
+environment variable.
+Some sites may wish to disable this as it could be used to gather
+information on the location of executables that the normal user does
+not have access to.
+The disadvantage is that if the executable is simply not in the user's
+\fRPATH\fR,
+\fBsudo\fR
+will tell the user that they are not allowed to run it, which can be confusing.
+This flag is
+\fI@path_info@\fR
+by default.
+.TP 18n
+preserve_groups
+By default,
+\fBsudo\fR
+will initialize the group vector to the list of groups the target user is in.
+When
+\fIpreserve_groups\fR
+is set, the user's existing group vector is left unaltered.
+The real and effective group-IDs, however, are still set to match the
+target user.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+pwfeedback
+By default,
+\fBsudo\fR
+reads the password like most other Unix programs,
+by turning off echo until the user hits the return (or enter) key.
+Some users become confused by this as it appears to them that
+\fBsudo\fR
+has hung at this point.
+When
+\fIpwfeedback\fR
+is set,
+\fBsudo\fR
+will provide visual feedback when the user presses a key.
+This does have a security impact as an onlooker may be able to
+determine the length of the password being entered.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+requiretty
+If set,
+\fBsudo\fR
+will only run when the user is logged in to a real tty.
+When this flag is set,
+\fBsudo\fR
+can only be run from a login session and not via other means such as
+cron(@mansectsu@)
+or cgi-bin scripts.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+root_sudo
+If set,
+\fBroot\fR
+is allowed to run
+\fBsudo\fR
+too.
+Disabling this prevents users from
+\(lqchaining\(rq
+\fBsudo\fR
+commands to get a
+\fBroot\fR
+shell by doing something like
+\(oqsudo sudo /bin/sh\(cq.
+Note, however, that turning off
+\fIroot_sudo\fR
+will also prevent
+\fBroot\fR
+from running
+\fBsudoedit\fR.
+Disabling
+\fIroot_sudo\fR
+provides no real additional security; it exists purely for historical reasons.
+This flag is
+\fI@root_sudo@\fR
+by default.
+.TP 18n
+rootpw
+If set,
+\fBsudo\fR
+will prompt for the
+\fBroot\fR
+password instead of the password of the invoking user
+when running a command or editing a file.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+runas_allow_unknown_id
+If enabled, allow matching of runas user and group IDs that are
+not present in the password or group databases.
+In addition to explicitly matching unknown user or group IDs in a
+\fIRunas_List\fR,
+this option also allows the
+\fBALL\fR
+alias to match unknown IDs.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.8.30 or higher.
+Older versions of
+\fBsudo\fR
+always allowed matching of unknown user and group IDs.
+.TP 18n
+runas_check_shell
+.br
+If enabled,
+\fBsudo\fR
+will only run commands as a user whose shell appears in the
+\fI/etc/shells\fR
+file, even if the invoking user's
+\fIRunas_List\fR
+would otherwise permit it.
+If no
+\fI/etc/shells\fR
+file is present, a system-dependent list of built-in default shells is used.
+On many operating systems, system users such as
+\(lqbin\(rq,
+do not have a valid shell and this flag can be used to prevent
+commands from being run as those users.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.8.30 or higher.
+.TP 18n
+runaspw
+If set,
+\fBsudo\fR
+will prompt for the password of the user defined by the
+\fIrunas_default\fR
+option (defaults to
+\fB@runas_default@\fR)
+instead of the password of the invoking user
+when running a command or editing a file.
+This flag is
+\fIoff\fR
+by default.
+.if \n(SL \{\
+.TP 18n
+selinux
+If enabled, the user may specify an SELinux role and/or type to use
+when running the command, as permitted by the SELinux policy.
+If SELinux is disabled on the system, this flag has no effect.
+This flag is
+\fIon\fR
+by default.
+.\}
+.TP 18n
+set_home
+If enabled and
+\fBsudo\fR
+is invoked with the
+\fB\-s\fR
+option, the
+\fRHOME\fR
+environment variable will be set to the home directory of the target
+user (which is the
+\fIrunas_default\fR
+user unless the
+\fB\-u\fR
+option is used).
+This flag is largely obsolete and has no effect unless the
+\fIenv_reset\fR
+flag has been disabled or
+\fRHOME\fR
+is present in the
+\fIenv_keep\fR
+list, both of which are strongly discouraged.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+set_logname
+Normally,
+\fBsudo\fR
+will set the
+\fRLOGNAME\fR
+and
+\fRUSER\fR
+environment variables to the name of the target user (the user specified by
+\fIrunas_default\fR
+unless the
+\fB\-u\fR
+option is given).
+However, since some programs (including the RCS revision control system) use
+\fRLOGNAME\fR
+to determine the real identity of the user, it may be desirable to
+change this behavior.
+This can be done by negating the set_logname option.
+The
+\fIset_logname\fR
+option will have no effect
+if the
+\fIenv_reset\fR
+option has not been disabled and the
+\fIenv_keep\fR
+list contains
+\fRLOGNAME\fR
+or
+\fRUSER\fR.
+This flag is
+\fIon\fR
+by default.
+.TP 18n
+set_utmp
+When enabled,
+\fBsudo\fR
+will create an entry in the utmp (or utmpx) file when a pseudo-terminal
+is allocated.
+A pseudo-terminal is allocated by
+\fBsudo\fR
+when it is running in a terminal and one or more of the
+\fIlog_input\fR,
+\fIlog_output\fR,
+\fIlog_stdin\fR,
+\fIlog_stdout\fR,
+\fIlog_stderr\fR,
+\fIlog_ttyin\fR,
+\fIlog_ttyout\fR,
+or
+\fIuse_pty\fR
+flags is enabled.
+By default, the new entry will be a copy of the user's existing utmp
+entry (if any), with the tty, time, type, and pid fields updated.
+This flag is
+\fIon\fR
+by default.
+.TP 18n
+setenv
+Allow the user to disable the
+\fIenv_reset\fR
+option from the command line via the
+\fB\-E\fR
+option.
+Additionally, environment variables set via the command line are
+not subject to the restrictions imposed by
+\fIenv_check\fR,
+\fIenv_delete\fR,
+or
+\fIenv_keep\fR.
+As such, only trusted users should be allowed to set variables in this manner.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+shell_noargs
+If set and
+\fBsudo\fR
+is invoked with no arguments it acts as if the
+\fB\-s\fR
+option had been given.
+That is, it runs a shell as
+\fBroot\fR
+(the shell is determined by the
+\fRSHELL\fR
+environment variable if it is set, falling back on the shell listed
+in the invoking user's /etc/passwd entry if not).
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+stay_setuid
+Normally, when
+\fBsudo\fR
+executes a command the real and effective user-IDs are set to the target
+user
+(\fB@runas_default@\fR
+by default).
+This option changes that behavior such that the real user-ID is left
+as the invoking user's user-ID.
+In other words, this makes
+\fBsudo\fR
+act as a set-user-ID wrapper.
+This can be useful on systems that disable some potentially
+dangerous functionality when a program is run set-user-ID.
+This option is only effective on systems that support either the
+setreuid(2)
+or
+setresuid(2)
+system call.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+sudoedit_checkdir
+.br
+If set,
+\fBsudoedit\fR
+will check all directory components of the path to be edited for writability
+by the invoking user.
+Symbolic links will not be followed in writable directories and
+\fBsudoedit\fR
+will refuse to edit a file located in a writable directory.
+These restrictions are not enforced when
+\fBsudoedit\fR
+is run by
+\fBroot\fR.
+On some systems, if all directory components of the path to be edited
+are not readable by the target user,
+\fBsudoedit\fR
+will be unable to edit the file.
+This flag is
+\fIon\fR
+by default.
+.sp
+This setting was first introduced in version 1.8.15 but initially
+suffered from a race condition.
+The check for symbolic links in writable intermediate directories
+was added in version 1.8.16.
+.TP 18n
+sudoedit_follow
+By default,
+\fBsudoedit\fR
+will not follow symbolic links when opening files.
+The
+\fIsudoedit_follow\fR
+option can be enabled to allow
+\fBsudoedit\fR
+to open symbolic links.
+It may be overridden on a per-command basis by the
+\fRFOLLOW\fR
+and
+\fRNOFOLLOW\fR
+tags.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.8.15 or higher.
+.TP 18n
+syslog_pid
+When logging via
+syslog(3),
+include the process ID in the log entry.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.8.21 or higher.
+.TP 18n
+targetpw
+If set,
+\fBsudo\fR
+will prompt for the password of the user specified
+by the
+\fB\-u\fR
+option (defaults to the value of
+\fIrunas_default\fR)
+instead of the password of the invoking user
+when running a command or editing a file.
+This flag precludes the use of a user-ID not listed in the passwd
+database as an argument to the
+\fB\-u\fR
+option.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+tty_tickets
+If set, users must authenticate on a per-tty basis.
+With this flag enabled,
+\fBsudo\fR
+will use a separate record in the time stamp file for each terminal.
+If disabled, a single record is used for all login sessions.
+.sp
+This option has been superseded by the
+\fItimestamp_type\fR
+option.
+.TP 18n
+umask_override
+If set,
+\fBsudo\fR
+will set the umask as specified in the
+\fIsudoers\fR
+file without modification.
+This makes it possible to specify a umask in the
+\fIsudoers\fR
+file that is more permissive than the user's own umask and matches
+historical behavior.
+If
+\fIumask_override\fR
+is not set,
+\fBsudo\fR
+will set the umask to be the union of the user's umask and what is specified in
+\fIsudoers\fR.
+This flag is
+\fI@umask_override@\fR
+by default.
+.if \n(BA \{\
+.TP 18n
+use_loginclass
+If set,
+\fBsudo\fR
+will apply the defaults specified for the target user's login class
+if one exists.
+Only available if
+\fBsudo\fR
+is configured with the
+\fR--with-logincap\fR
+option.
+This flag is
+\fIoff\fR
+by default.
+.\}
+.TP 18n
+use_netgroups
+If set, netgroups (prefixed with
+\(oq+\(cq),
+may be used in place of a user or host.
+For LDAP-based sudoers, netgroup support requires an expensive
+sub-string match on the server unless the
+\fBNETGROUP_BASE\fR
+directive is present in the
+\fI@ldap_conf@\fR
+file.
+If netgroups are not needed, this option can be disabled to reduce the
+load on the LDAP server.
+This flag is
+\fIon\fR
+by default.
+.TP 18n
+use_pty
+If set, and
+\fBsudo\fR
+is running in a terminal, the command will be run in a new pseudo-terminal.
+If the
+\fBsudo\fR
+process is not attached to a terminal,
+\fIuse_pty\fR
+has no effect.
+.sp
+A malicious program run under
+\fBsudo\fR
+may be capable of injecting commands into the user's
+terminal or running a background process that retains access to the
+user's terminal device even after the main program has finished
+executing.
+By running the command in a separate pseudo-terminal, this attack is
+no longer possible.
+This flag is
+\fIon\fR
+by default for
+\fBsudo\fR
+1.9.14 and above.
+.TP 18n
+user_command_timeouts
+If set, the user may specify a timeout on the command line.
+If the timeout expires before the command has exited, the
+command will be terminated.
+If a timeout is specified both in the
+\fIsudoers\fR
+file and on the command line, the smaller of the two timeouts will be used.
+See the
+\fITimeout_Spec\fR
+section for a description of the timeout syntax.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.8.20 or higher.
+.TP 18n
+utmp_runas
+If set,
+\fBsudo\fR
+will store the name of the runas user when updating the utmp (or utmpx) file.
+By default,
+\fBsudo\fR
+stores the name of the invoking user.
+This flag is
+\fIoff\fR
+by default.
+.TP 18n
+visiblepw
+By default,
+\fBsudo\fR
+will refuse to run if the user must enter a password but it is not
+possible to disable echo on the terminal.
+If the
+\fIvisiblepw\fR
+flag is set,
+\fBsudo\fR
+will prompt for a password even when it would be visible on the screen.
+This makes it possible to run things like
+\(oqssh somehost sudo ls\(cq
+since by default,
+ssh(1)
+does
+not allocate a tty when running a command.
+This flag is
+\fIoff\fR
+by default.
+.PP
+\fBIntegers\fR:
+.TP 18n
+closefrom
+Before it executes a command,
+\fBsudo\fR
+will close all open file descriptors other than standard input,
+standard output, and standard error (file descriptors 0-2).
+The
+\fIclosefrom\fR
+option can be used to specify a different file descriptor at which
+to start closing.
+The default is 3.
+.TP 18n
+command_timeout
+The maximum amount of time a command is allowed to run before
+it is terminated.
+See the
+\fITimeout_Spec\fR
+section for a description of the timeout syntax.
+.sp
+This setting is only supported by version 1.8.20 or higher.
+.TP 18n
+log_server_timeout
+The maximum amount of time to wait when connecting to a log server
+or waiting for a server response.
+See the
+\fITimeout_Spec\fR
+section for a description of the timeout syntax.
+The default value is 30 seconds.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.TP 18n
+maxseq
+The maximum sequence number that will be substituted for the
+\(oq%{seq}\(cq
+escape in the I/O log file (see the
+\fIiolog_dir\fR
+description below for more information).
+While the value substituted for
+\(oq%{seq}\(cq
+is in base 36,
+\fImaxseq\fR
+itself should be expressed in decimal.
+Values larger than 2176782336 (which corresponds to the
+base 36 sequence number
+\(lqZZZZZZ\(rq)
+will be silently truncated to 2176782336.
+The default value is 2176782336.
+.sp
+Once the local sequence number reaches the value of
+\fImaxseq\fR,
+it will
+\(lqroll over\(rq
+to zero, after which
+\fBsudoers\fR
+will truncate and re-use any existing I/O log path names.
+.sp
+This setting is only supported by version 1.8.7 or higher.
+.TP 18n
+passwd_tries
+The number of tries a user gets to enter his/her password before
+\fBsudo\fR
+logs the failure and exits.
+The default is @passwd_tries@.
+.TP 18n
+syslog_maxlen
+On many systems,
+syslog(3)
+has a relatively small log buffer.
+IETF RFC 5424 states that syslog servers must support messages of
+at least 480 bytes and should support messages up to 2048 bytes.
+By default,
+\fBsudoers\fR
+creates log messages up to 980 bytes which corresponds to the
+historic
+BSD
+syslog implementation which used a 1024 byte buffer
+to store the message, date, hostname, and program name.
+To prevent syslog messages from being truncated,
+\fBsudoers\fR
+will split up log messages that are larger than
+\fIsyslog_maxlen\fR
+bytes.
+When a message is split, additional parts will include the string
+\(lq(command continued)\(rq
+after the user name and before the continued command line arguments.
+.sp
+This setting is only supported by version 1.8.19 or higher.
+.PP
+\fBIntegers that can be used in a boolean context\fR:
+.TP 18n
+loglinelen
+Number of characters per line for the file log.
+This value is used to decide when to wrap lines for nicer log files.
+This has no effect on the syslog log file, only the file log.
+The default is @loglen@ (use 0 or negate the option to disable word wrap).
+.TP 18n
+passwd_timeout
+Number of minutes before the
+\fBsudo\fR
+password prompt times out, or 0 for no timeout.
+The timeout may include a fractional component
+if minute granularity is insufficient, for example 2.5.
+The default is @password_timeout@.
+.TP 18n
+timestamp_timeout
+.br
+Number of minutes that can elapse before
+\fBsudo\fR
+will ask for a password again.
+The timeout may include a fractional component if
+minute granularity is insufficient, for example 2.5.
+The default is @timeout@.
+Set this to 0 to always prompt for a password.
+If set to a value less than 0 the user's time stamp will not expire
+until the system is rebooted.
+This can be used to allow users to create or delete their own time stamps via
+\(oqsudo -v\(cq
+and
+\(oqsudo -k\(cq
+respectively.
+.TP 18n
+umask
+File mode creation mask to use when running the command.
+Negate this option or set it to 0777 to prevent
+\fBsudoers\fR
+from changing the umask.
+Unless the
+\fIumask_override\fR
+flag is set, the actual umask will be the union of the
+user's umask and the value of the
+\fIumask\fR
+setting, which defaults to @sudo_umask@.
+This guarantees that
+\fBsudo\fR
+never lowers the umask when running a command.
+.sp
+If
+\fIumask\fR
+is explicitly set in
+\fIsudoers\fR,
+it will override any umask setting in PAM or login.conf.
+If
+\fIumask\fR
+is not set in
+\fIsudoers\fR,
+the umask specified by PAM or login.conf will take precedence.
+The umask setting in PAM is not used for
+\fBsudoedit\fR,
+which does not create a new PAM session.
+.PP
+\fBStrings\fR:
+.TP 18n
+apparmor_profile
+The default AppArmor profile to transition into when executing the
+command.
+The default
+\fIapparmor_profile\fR
+can be overridden for individual
+\fIsudoers\fR
+entries by specifying the
+\fRAPPARMOR_PROFILE\fR
+option.
+This option is only available when sudo is built with AppArmor
+support.
+.TP 18n
+authfail_message
+Message that is displayed after a user fails to authenticate.
+The message may include the
+\(oq%d\(cq
+escape which will expand to the number of failed password attempts.
+If set, it overrides the default message,
+\(lq%d incorrect password attempt(s)\(rq.
+.TP 18n
+badpass_message
+Message that is displayed if a user enters an incorrect password.
+The default is
+\(lq@badpass_message@\(rq
+unless insults are enabled.
+.TP 18n
+editor
+A colon
+(\(oq:\&\(cq)
+separated list of editor path names used by
+\fBsudoedit\fR
+and
+\fBvisudo\fR.
+For
+\fBsudoedit\fR,
+this list is used to find an editor when none of the
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+or
+\fREDITOR\fR
+environment variables are set to an editor that exists and is executable.
+For
+\fBvisudo\fR,
+it is used as a white list of allowed editors;
+\fBvisudo\fR
+will choose the editor that matches the user's
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+or
+\fREDITOR\fR
+environment variable if possible, or the first editor in the
+list that exists and is executable if not.
+Unless invoked as
+\fBsudoedit\fR,
+\fBsudo\fR
+does not preserve the
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR
+or
+\fREDITOR\fR
+environment variables unless they are present in the
+\fIenv_keep\fR
+list or the
+\fIenv_reset\fR
+option is disabled.
+The default is
+\fI@editor@\fR.
+.TP 18n
+intercept_type
+The underlying mechanism used by the
+\fIintercept\fR
+and
+\fIlog_subcmds\fR
+options.
+It has the following possible values:
+.PP
+.RS 18n
+.PD 0
+.TP 8n
+dso
+Preload a dynamic shared object (shared library) that intercepts the
+execve(2),
+execl(3),
+execle(3),
+execlp(3),
+execv(3),
+execvp(3),
+execvpe(3),
+and
+system(3)
+library functions.
+A value of
+\fIdso\fR
+is incompatible with
+\fBsudo\fR's
+SELinux RBAC support.
+.PD
+.TP 8n
+trace
+Use
+ptrace(2)
+to intercept the
+execve(2)
+system call.
+This is only supported on Linux systems where
+seccomp(2)
+filtering is enabled.
+If the
+\fI/proc/sys/kernel/seccomp/actions_avail\fR
+file is missing or does not contain a
+\(lqtrap\(rq
+element, setting
+\fIintercept_type\fR
+to
+\fItrace\fR
+will have no effect and
+\fIdso\fR
+will be used instead.
+.PP
+The default is to use
+\fItrace\fR
+if it is supported by the system and
+\fIdso\fR
+if it is not.
+.RE
+.TP 18n
+iolog_dir
+The top-level directory to use when constructing the path name for
+the input/output log directory.
+Only used if the
+\fIlog_input\fR
+or
+\fIlog_output\fR
+options are enabled or when the
+\fRLOG_INPUT\fR
+or
+\fRLOG_OUTPUT\fR
+tags are present for a command.
+The session sequence number, if any, is stored in the directory.
+The default is
+\fI@iolog_dir@\fR.
+.sp
+The following percent
+(\(oq%\(cq)
+escape sequences are supported:
+.PP
+.RS 18n
+.PD 0
+.TP 6n
+%{seq}
+expanded to a monotonically increasing base-36 sequence number, such as 0100A5,
+where every two digits are used to form a new directory, e.g.,
+\fI01/00/A5\fR
+.PD
+.TP 6n
+%{user}
+expanded to the invoking user's login name
+.TP 6n
+%{group}
+expanded to the name of the invoking user's real group-ID
+.TP 6n
+%{runas_user}
+expanded to the login name of the user the command will
+be run as (e.g.,
+\fBroot\fR)
+.TP 6n
+%{runas_group}
+expanded to the group name of the user the command will
+be run as (e.g.,
+\fBwheel\fR)
+.TP 6n
+%{hostname}
+expanded to the local host name without the domain name
+.TP 6n
+%{command}
+expanded to the base name of the command being run
+.PP
+In addition, any escape sequences supported by the system's
+strftime(3)
+function will be expanded.
+.sp
+To include a literal
+\(oq%\(cq
+character, the string
+\(oq%%\(cq
+should be used.
+.sp
+Any path name separator characters
+(\(oq/\(cq)
+present in the user, group or host name will be replaced with an underbar
+(\(oq_\(cq)
+during expansion.
+.RE
+.TP 18n
+iolog_file
+The path name, relative to
+\fIiolog_dir\fR,
+in which to store input/output logs when the
+\fIlog_input\fR
+or
+\fIlog_output\fR
+options are enabled or when the
+\fRLOG_INPUT\fR
+or
+\fRLOG_OUTPUT\fR
+tags are present for a command.
+\fIiolog_file\fR
+may contain directory components.
+The default is
+\(oq%{seq}\(cq.
+.sp
+See the
+\fIiolog_dir\fR
+option above for a list of supported percent
+(\(oq%\(cq)
+escape sequences.
+.sp
+In addition to the escape sequences, path names that end in six or
+more
+\fIX\fRs
+will have the
+\fIX\fRs
+replaced with a unique combination of digits and letters, similar to the
+mktemp(3)
+function.
+.sp
+If the path created by concatenating
+\fIiolog_dir\fR
+and
+\fIiolog_file\fR
+already exists, the existing I/O log file will be truncated and
+overwritten unless
+\fIiolog_file\fR
+ends in six or
+more
+\fIX\fRs.
+.TP 18n
+iolog_flush
+If set,
+\fBsudo\fR
+will flush I/O log data to disk after each write instead of buffering it.
+This makes it possible to view the logs in real-time as the program
+is executing but may significantly reduce the effectiveness of I/O
+log compression.
+This flag is
+\fIoff\fR
+by default.
+.sp
+This setting is only supported by version 1.8.20 or higher.
+.TP 18n
+iolog_group
+The group name to look up when setting the group-ID on new I/O log
+files and directories.
+If
+\fIiolog_group\fR
+is not set,
+the primary group-ID of the user specified by
+\fIiolog_user\fR
+is used.
+If neither
+\fIiolog_group\fR
+nor
+\fIiolog_user\fR
+are set, I/O log files and directories are created with group-ID 0.
+.sp
+This setting is only supported by version 1.8.19 or higher.
+.TP 18n
+iolog_mode
+The file mode to use when creating I/O log files.
+Mode bits for read and write permissions for owner, group, or other
+are honored, everything else is ignored.
+The file permissions will always include the owner read and
+write bits, even if they are not present in the specified mode.
+When creating I/O log directories, search (execute) bits are added
+to match the read and write bits specified by
+\fIiolog_mode\fR.
+Defaults to 0600 (read and write by user only).
+.sp
+This setting is only supported by version 1.8.19 or higher.
+.TP 18n
+iolog_user
+The user name to look up when setting the user and group-IDs on new
+I/O log files and directories.
+If
+\fIiolog_group\fR
+is set, it will be used instead of the user's primary group-ID.
+By default, I/O log files and directories are created with user and
+group-ID 0.
+.sp
+This setting can be useful when the I/O logs are stored on a Network
+File System (NFS) share.
+Having a dedicated user own the I/O log files means that
+\fBsudoers\fR
+does not write to the log files as user-ID 0, which is usually
+not permitted by NFS.
+.sp
+This setting is only supported by version 1.8.19 or higher.
+.TP 18n
+lecture_status_dir
+The directory in which
+\fBsudo\fR
+stores per-user lecture status files.
+Once a user has received the lecture, a zero-length file is
+created in this directory so that
+\fBsudo\fR
+will not lecture the user again.
+This directory should
+\fInot\fR
+be cleared when the system reboots.
+The default is
+\fI@vardir@/lectured\fR.
+.if \n(PS \{\
+.TP 18n
+limitprivs
+The default Solaris limit privileges to use when constructing a new
+privilege set for a command.
+This bounds all privileges of the executing process.
+The default limit privileges may be overridden on a per-command basis in
+\fIsudoers\fR.
+This option is only available if
+\fBsudoers\fR
+is built on Solaris 10 or higher.
+.\}
+.TP 18n
+log_server_cabundle
+The path to a certificate authority bundle file, in PEM format,
+to use instead of the system's default certificate authority database
+when authenticating the log server.
+The default is to use the system's default certificate authority database.
+This setting has no effect unless
+\fIlog_servers\fR
+is set and the remote log server is secured with TLS.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.TP 18n
+log_server_peer_cert
+The path to the
+\fBsudo\fR
+client's certificate file, in PEM format.
+This setting is required when the remote log server is secured
+with TLS and client certificate validation is enabled.
+For
+\fBsudo_logsrvd\fR,
+client certificate validation is controlled by the
+\fItls_checkpeer\fR
+option, which defaults to
+\fIfalse\fR.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.TP 18n
+log_server_peer_key
+The path to the
+\fBsudo\fR
+client's private key file, in PEM format.
+This setting is required when the remote log server is secured
+with TLS and client certificate validation is enabled.
+For
+\fBsudo_logsrvd\fR,
+client certificate validation is controlled by the
+\fItls_checkpeer\fR
+flag, which defaults to
+\fIfalse\fR.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.TP 18n
+mailsub
+Subject of the mail sent to the
+\fImailto\fR
+user.
+The escape
+\(oq%h\(cq
+will expand to the host name of the machine.
+Default is
+\(lq@mailsub@\(rq.
+.TP 18n
+noexec_file
+As of
+\fBsudo\fR
+version 1.8.1 this option is no longer supported.
+The path to the noexec file should now be set in the
+sudo.conf(@mansectform@)
+file.
+.TP 18n
+pam_askpass_service
+On systems that use PAM for authentication, this is the service
+name used when the
+\fB\-A\fR
+option is specified.
+The default value is either
+\(oqsudo\(cq
+or
+\(oq@pam_login_service@\(cq,
+depending on whether or not the
+\fB\-i\fR
+option is also specified.
+See the description of
+\fIpam_service\fR
+for more information.
+.sp
+This setting is only supported by version 1.9.9 or higher.
+.TP 18n
+pam_login_service
+.br
+On systems that use PAM for authentication, this is the service
+name used when the
+\fB\-i\fR
+option is specified.
+The default value is
+\(oq@pam_login_service@\(cq.
+See the description of
+\fIpam_service\fR
+for more information.
+.sp
+This setting is only supported by version 1.8.8 or higher.
+.TP 18n
+pam_service
+On systems that use PAM for authentication, the service name
+specifies the PAM policy to apply.
+This usually corresponds to an entry in the
+\fIpam.conf\fR
+file or a file in the
+\fI/etc/pam.d\fR
+directory.
+The default value is
+\(oqsudo\(cq.
+.sp
+This setting is only supported by version 1.8.8 or higher.
+.TP 18n
+passprompt
+The default prompt to use when asking for a password; can be overridden via the
+\fB\-p\fR
+option or the
+\fRSUDO_PROMPT\fR
+environment variable.
+The following percent
+(\(oq%\(cq)
+escape sequences are supported:
+.PP
+.RS 18n
+.PD 0
+.TP 6n
+%H
+expanded to the local host name including the domain name
+(only if the machine's host name is fully qualified or the
+\fIfqdn\fR
+option is set)
+.PD
+.TP 6n
+%h
+expanded to the local host name without the domain name
+.TP 6n
+%p
+expanded to the user whose password is being asked for (respects the
+\fIrootpw\fR,
+\fItargetpw\fR
+and
+\fIrunaspw\fR
+flags in
+\fIsudoers\fR)
+.TP 6n
+\&%U
+expanded to the login name of the user the command will
+be run as (defaults to
+\fB@runas_default@\fR)
+.TP 6n
+%u
+expanded to the invoking user's login name
+.TP 6n
+%%
+two consecutive
+\(oq%\(cq
+characters are collapsed into a single
+\(oq%\(cq
+character
+.PP
+On systems that use PAM for authentication,
+\fIpassprompt\fR
+will only be used if the prompt provided by the PAM module matches the string
+\(lqPassword: \(rq
+or
+\(lqusername's Password: \(rq.
+This ensures that the
+\fIpassprompt\fR
+setting does not interfere with challenge-response style authentication.
+The
+\fIpassprompt_override\fR
+flag can be used to change this behavior.
+.sp
+The default value is
+\(oq@passprompt@\(cq.
+.RE
+.if \n(PS \{\
+.TP 18n
+privs
+The default Solaris privileges to use when constructing a new
+privilege set for a command.
+This is passed to the executing process via the inherited privilege set,
+but is bounded by the limit privileges.
+If the
+\fIprivs\fR
+option is specified but the
+\fIlimitprivs\fR
+option is not, the limit privileges of the executing process is set to
+\fIprivs\fR.
+The default privileges may be overridden on a per-command basis in
+\fIsudoers\fR.
+This option is only available if
+\fBsudoers\fR
+is built on Solaris 10 or higher.
+.\}
+.if \n(SL \{\
+.TP 18n
+role
+The default SELinux role to use when constructing a new security
+context to run the command.
+The default role may be overridden on a per-command basis in the
+\fIsudoers\fR
+file or via command line options.
+This option is only available when
+\fBsudo\fR
+is built with SELinux support.
+.\}
+.TP 18n
+runas_default
+The default user to run commands as if the
+\fB\-u\fR
+option is not specified on the command line.
+This defaults to
+\fB@runas_default@\fR.
+.TP 18n
+sudoers_locale
+Locale to use when parsing the sudoers file, logging commands, and
+sending email.
+Changing the locale may affect how sudoers is interpreted.
+Defaults to
+\(oqC\(cq.
+.TP 18n
+timestamp_type
+\fBsudoers\fR
+uses per-user time stamp files for credential caching.
+The
+\fItimestamp_type\fR
+option can be used to specify the type of time stamp record used.
+It has the following possible values:
+.PP
+.RS 18n
+.PD 0
+.TP 8n
+global
+A single time stamp record is used for all of a user's login sessions,
+regardless of the terminal or parent process ID.
+An additional record is used to serialize password prompts when
+\fBsudo\fR
+is used multiple times in a pipeline, but this does not affect authentication.
+.PD
+.TP 8n
+ppid
+A single time stamp record is used for all processes with the same parent
+process ID (usually the shell).
+Commands run from the same shell (or other common parent process)
+will not require a password for
+\fItimestamp_timeout\fR
+minutes (@timeout@ by default).
+Commands run via
+\fBsudo\fR
+with a different parent process ID, for example from a shell script,
+will be authenticated separately.
+.TP 8n
+tty
+One time stamp record is used for each terminal,
+which means that a user's login sessions are authenticated separately.
+If no terminal is present, the behavior is the same as
+\fIppid\fR.
+Commands run from the same terminal will not require a password for
+\fItimestamp_timeout\fR
+minutes (@timeout@ by default).
+.TP 8n
+kernel
+The time stamp is stored in the kernel as an attribute of the terminal
+device.
+If no terminal is present, the behavior is the same as
+\fIppid\fR.
+Negative
+\fItimestamp_timeout\fR
+values are not supported and positive values are limited to a maximum
+of 60 minutes.
+This is currently only supported on
+OpenBSD.
+.PP
+The default value is
+\fI@timestamp_type@\fR.
+.sp
+This setting is only supported by version 1.8.21 or higher.
+.RE
+.TP 18n
+timestampdir
+The directory in which
+\fBsudo\fR
+stores its time stamp files.
+This directory should be cleared when the system reboots.
+The default is
+\fI@rundir@/ts\fR.
+.TP 18n
+timestampowner
+The owner of the lecture status directory, time stamp directory and all
+files stored therein.
+The default is
+\fBroot\fR.
+.if \n(SL \{\
+.TP 18n
+type
+The default SELinux type to use when constructing a new security
+context to run the command.
+The default type may be overridden on a per-command basis in the
+\fIsudoers\fR
+file or via command line options.
+This option is only available when
+\fBsudo\fR
+is built with SELinux support.
+.PP
+\fBStrings that can be used in a boolean context\fR:
+.TP 14n
+admin_flag
+The
+\fIadmin_flag\fR
+option specifies the path to a file that is created the first time
+a user that is a member of the
+\fIsudo\fR
+or
+\fIadmin\fR
+groups runs
+\fBsudo\fR.
+Only available if
+\fBsudo\fR
+is configured with the
+\fR--enable-admin-flag\fR
+option.
+The default value is
+\fI~/.sudo_as_admin_successful\fR.
+.TP 14n
+env_file
+The
+\fIenv_file\fR
+option specifies the fully qualified path to a file containing variables
+to be set in the environment of the program being run.
+Entries in this file should either be of the form
+\(oqVARIABLE=value\(cq
+or
+\(oqexport VARIABLE=value\(cq.
+The value may optionally be enclosed in single or double quotes.
+Variables in this file are only added if the variable does not already
+exist in the environment.
+This file is considered to be part of the security policy,
+its contents are not subject to other
+\fBsudo\fR
+environment restrictions such as
+\fIenv_keep\fR
+and
+\fIenv_check\fR.
+.TP 14n
+exempt_group
+Users in this group are exempt from password and PATH requirements.
+The group name specified should not include a
+\(oq%\(cq
+prefix.
+This is not set by default.
+.TP 14n
+fdexec
+Determines whether
+\fBsudo\fR
+will execute a command by its path or by an open file descriptor.
+It has the following possible values:
+.PP
+.RS 14n
+.PD 0
+.TP 8n
+always
+Always execute by file descriptor.
+.PD
+.TP 8n
+never
+Never execute by file descriptor.
+.TP 8n
+digest_only
+Only execute by file descriptor if the command has an associated digest
+in the
+\fIsudoers\fR
+file.
+.PP
+The default value is
+\fIdigest_only\fR.
+This avoids a time of check versus time of use race condition when
+the command is located in a directory writable by the invoking user.
+.sp
+\fIfdexec\fR
+will change the first element of the argument vector for scripts
+($0 in the shell) due to the way the kernel runs script interpreters.
+Instead of being a normal path, it will refer to a file descriptor.
+For example,
+\fI/dev/fd/4\fR
+on Solaris and
+\fI/proc/self/fd/4\fR
+on Linux.
+A workaround is to use the
+\fRSUDO_COMMAND\fR
+environment variable instead.
+.sp
+The
+\fIfdexec\fR
+setting is only used when the command is matched by path name.
+It has no effect if the command is matched by the built-in
+\fBALL\fR
+alias.
+.sp
+This setting is only supported by version 1.8.20 or higher.
+If the operating system does not support the
+fexecve(2)
+system call, this setting has no effect.
+.RE
+.TP 14n
+group_plugin
+A string containing a
+\fBsudoers\fR
+group plugin with optional arguments.
+The string should consist of the plugin
+path, either fully-qualified or relative to the
+\fI@plugindir@\fR
+directory, followed by any configuration arguments the plugin requires.
+These arguments (if any) will be passed to the plugin's initialization function.
+If arguments are present, the string must be enclosed in double quotes
+(\&"").
+.sp
+On 64-bit systems, if the plugin is present but cannot be loaded,
+\fBsudoers\fR
+will look for a 64-bit version and, if it exists, load that as a fallback.
+The exact rules for this vary by system.
+On Solaris, if the plugin is stored in a directory ending in
+\(lqlib\(rq,
+\fBsudoers\fR
+will create a fallback path by appending
+\(lq/64\(rq
+to the directory name;
+\fI@prefix@/lib/group_plugin.so\fR
+becomes
+\fI@prefix@/lib/64/group_plugin.so\fR.
+On Linux, a directory ending in
+\(lqlib\(rq
+will be transformed to
+\(lqlib64\(rq
+as the fallback path;
+\fI@prefix@/lib/group_plugin.so\fR
+becomes
+\fI@prefix@/lib64/group_plugin.so\fR.
+On all other systems, the fallback path is generated by adding a
+\(lq64\(rq
+before the file extension;
+\fIgroup_plugin.so\fR
+becomes
+\fIgroup_plugin64.so\fR.
+.sp
+On AIX systems, the plugin may be either a shared object
+ending in
+\(oq.so\(cq
+or an archive file containing a shared object ending in
+\(oq.a\(cq
+with the name of the shared object in parentheses at the end.
+.sp
+For more information see
+\fIGROUP PROVIDER PLUGINS\fR.
+.TP 14n
+lecture
+This option controls when a short lecture will be printed along with
+the password prompt.
+It has the following possible values:
+.PP
+.RS 14n
+.PD 0
+.TP 8n
+always
+Always lecture the user.
+.PD
+.TP 8n
+never
+Never lecture the user.
+.TP 8n
+once
+Only lecture the user the first time they run
+\fBsudo\fR.
+.PP
+If no value is specified, a value of
+\fIonce\fR
+is implied.
+Negating the option results in a value of
+\fInever\fR
+being used.
+The default value is
+\fI@lecture@\fR.
+.RE
+.TP 14n
+lecture_file
+Path to a file containing an alternate
+\fBsudo\fR
+lecture that will be used in place of the standard lecture if the named
+file exists.
+By default,
+\fBsudo\fR
+uses a built-in lecture.
+.TP 14n
+listpw
+This option controls when a password will be required when a user runs
+\fBsudo\fR
+with the
+\fB\-l\fR
+option.
+It has the following possible values:
+.PP
+.RS 14n
+.PD 0
+.TP 6n
+all
+All the user's
+\fIsudoers\fR
+file entries for the current host must have
+the
+\fRNOPASSWD\fR
+flag set to avoid entering a password.
+.PD
+.TP 6n
+always
+The user must always enter a password to use the
+\fB\-l\fR
+option.
+.TP 6n
+any
+At least one of the user's
+\fIsudoers\fR
+file entries for the current host
+must have the
+\fRNOPASSWD\fR
+flag set to avoid entering a password.
+.TP 6n
+never
+.br
+The user need never enter a password to use the
+\fB\-l\fR
+option.
+.PP
+If no value is specified, a value of
+\fIany\fR
+is implied.
+Negating the option results in a value of
+\fInever\fR
+being used.
+The default value is
+\fIany\fR.
+.RE
+.TP 14n
+log_format
+The event log format.
+Supported log formats are:
+.PP
+.RS 14n
+.PD 0
+.TP 6n
+json
+Logs in JSON format.
+JSON log entries contain the full user details as well as the execution
+environment if the command was allowed.
+Due to limitations of the protocol, JSON events sent via
+\fIsyslog\fR
+may be truncated.
+.PD
+.TP 6n
+sudo
+Traditional sudo-style logs, see
+\fIEVENT LOGGING\fR
+for a description of the log file format.
+.PP
+This setting affects logs sent via
+syslog(3)
+as well as the file specified by the
+\fIlogfile\fR
+setting, if any.
+The default value is
+\fIsudo\fR.
+.RE
+.TP 14n
+logfile
+Path to the
+\fBsudo\fR
+log file (not the syslog log file).
+Setting a path turns on logging to a file;
+negating this option turns it off.
+By default,
+\fBsudo\fR
+logs via syslog.
+.TP 14n
+mailerflags
+Flags to use when invoking mailer.
+Defaults to
+\fB\-t\fR.
+.TP 14n
+mailerpath
+Path to mail program used to send warning mail (negate to prevent
+\fBsudo\fR
+from sending mail).
+Defaults to the path to sendmail found at configure time.
+.TP 14n
+mailfrom
+Address to use for the
+\(lqfrom\(rq
+address when sending warning and error mail.
+The address should be enclosed in double quotes
+(\&"")
+to protect against
+\fBsudo\fR
+interpreting the
+\(oq@\(cq
+sign.
+Defaults to the name of the user running
+\fBsudo\fR.
+.TP 14n
+mailto
+Address to send warning and error mail to (negate to prevent
+\fBsudo\fR
+from sending mail).
+The address should be enclosed in double quotes
+(\&"")
+to protect against
+\fBsudo\fR
+interpreting the
+\(oq@\(cq
+sign.
+Defaults to @mailto@.
+.TP 14n
+rlimit_as
+The maximum size to which the process's address space may grow (in bytes),
+if supported by the operating system.
+See
+\fIResource limits\fR
+for more information.
+.TP 14n
+rlimit_core
+The largest size core dump file that may be created (in bytes).
+See
+\fIResource limits\fR
+for more information.
+Defaults to 0 (no core dump created).
+.TP 14n
+rlimit_cpu
+The maximum amount of CPU time that the process may use (in seconds).
+See
+\fIResource limits\fR
+for more information.
+.TP 14n
+rlimit_data
+The maximum size of the data segment for the process (in bytes).
+See
+\fIResource limits\fR
+for more information.
+.TP 14n
+rlimit_fsize
+The largest size file that the process may create (in bytes).
+See
+\fIResource limits\fR
+for more information.
+.TP 14n
+rlimit_locks
+The maximum number of locks that the process may establish,
+if supported by the operating system.
+See
+\fIResource limits\fR
+for more information.
+.TP 14n
+rlimit_memlock
+The maximum size that the process may lock in memory (in bytes),
+if supported by the operating system.
+See
+\fIResource limits\fR
+for more information.
+.TP 14n
+rlimit_nofile
+.br
+The maximum number of files that the process may have open.
+See
+\fIResource limits\fR
+for more information.
+.TP 14n
+rlimit_nproc
+The maximum number of processes that the user may run simultaneously.
+See
+\fIResource limits\fR
+for more information.
+.TP 14n
+rlimit_rss
+The maximum size to which the process's resident set size may grow (in bytes).
+See
+\fIResource limits\fR
+for more information.
+.TP 14n
+rlimit_stack
+The maximum size to which the process's stack may grow (in bytes).
+See
+\fIResource limits\fR
+for more information.
+.TP 14n
+restricted_env_file
+The
+\fIrestricted_env_file\fR
+option specifies the fully qualified path to a file containing variables
+to be set in the environment of the program being run.
+Entries in this file should either be of the form
+\(oqVARIABLE=value\(cq
+or
+\(oqexport VARIABLE=value\(cq.
+The value may optionally be enclosed in single or double quotes.
+Variables in this file are only added if the variable does not already
+exist in the environment.
+Unlike
+\fIenv_file\fR,
+the file's contents are not trusted and are processed in a manner
+similar to that of the invoking user's environment.
+If
+\fIenv_reset\fR
+is enabled, variables in the file will only be added if they are
+matched by either the
+\fIenv_check\fR
+or
+\fIenv_keep\fR
+list.
+If
+\fIenv_reset\fR
+is disabled, variables in the file are added as long as they
+are not matched by the
+\fIenv_delete\fR
+list.
+In either case, the contents of
+\fIrestricted_env_file\fR
+are processed before the contents of
+\fIenv_file\fR.
+.TP 14n
+runchroot
+If set,
+\fBsudo\fR
+will use this value for the root directory when running a command.
+The special value
+\(lq*\(rq
+will allow the user to specify the root directory via
+\fBsudo\fR's
+\fB\-R\fR
+option.
+See the
+\fIChroot_Spec\fR
+section for more details.
+.sp
+It is only possible to use
+\fIrunchroot\fR
+as a command-specific Defaults setting if the command exists with
+the same path both inside and outside the chroot jail.
+This restriction does not apply to global, host, or user-based
+Defaults settings or to a
+\fICmnd_Spec\fR
+that includes a
+\fIChroot_Spec\fR.
+.sp
+This setting is only supported by version 1.9.3 or higher.
+.TP 14n
+runcwd
+If set,
+\fBsudo\fR
+will use this value for the working directory when running a command.
+The special value
+\(lq*\(rq
+will allow the user to specify the working directory via
+\fBsudo\fR's
+\fB\-D\fR
+option.
+See the
+\fIChdir_Spec\fR
+section for more details.
+.sp
+This setting is only supported by version 1.9.3 or higher.
+.TP 14n
+secure_path
+If set,
+\fBsudo\fR
+will use this value in place of the user's
+\fRPATH\fR
+environment variable.
+This option can be used to reset the
+\fRPATH\fR
+to a known good value that contains directories for system administrator
+commands such as
+\fI/usr/sbin\fR.
+.sp
+Users in the group specified by the
+\fIexempt_group\fR
+option are not affected by
+\fIsecure_path\fR.
+This option is @secure_path@ by default.
+.TP 14n
+syslog
+Syslog facility if syslog is being used for logging (negate to
+disable syslog logging).
+Defaults to @logfac@.
+.sp
+The following syslog facilities are supported:
+\fBauthpriv\fR
+(if your
+OS supports it),
+\fBauth\fR,
+\fBdaemon\fR,
+\fBuser\fR,
+\fBlocal0\fR,
+\fBlocal1\fR,
+\fBlocal2\fR,
+\fBlocal3\fR,
+\fBlocal4\fR,
+\fBlocal5\fR,
+\fBlocal6\fR,
+and
+\fBlocal7\fR.
+.TP 14n
+syslog_badpri
+.br
+Syslog priority to use when the user is not allowed to run a command or
+when authentication is unsuccessful.
+Defaults to @badpri@.
+.sp
+The following syslog priorities are supported:
+\fBalert\fR,
+\fBcrit\fR,
+\fBdebug\fR,
+\fBemerg\fR,
+\fBerr\fR,
+\fBinfo\fR,
+\fBnotice\fR,
+\fBwarning\fR,
+and
+\fBnone\fR.
+Negating the option or setting it to a value of
+\fBnone\fR
+will disable logging of unsuccessful commands.
+.TP 14n
+syslog_goodpri
+Syslog priority to use when the user is allowed to run a command and
+authentication is successful.
+Defaults to @goodpri@.
+.sp
+See
+\fIsyslog_badpri\fR
+for the list of supported syslog priorities.
+Negating the option or setting it to a value of
+\fBnone\fR
+will disable logging of successful commands.
+.TP 14n
+verifypw
+This option controls when a password will be required when a user runs
+\fBsudo\fR
+with the
+\fB\-v\fR
+option.
+It has the following possible values:
+.PP
+.RS 14n
+.PD 0
+.TP 8n
+all
+All the user's
+\fIsudoers\fR
+file entries for the current host must have the
+\fRNOPASSWD\fR
+flag set to avoid entering a password.
+.PD
+.TP 8n
+always
+The user must always enter a password to use the
+\fB\-v\fR
+option.
+.TP 8n
+any
+At least one of the user's
+\fIsudoers\fR
+file entries for the current host must have the
+\fRNOPASSWD\fR
+flag set to avoid entering a password.
+.TP 8n
+never
+The user need never enter a password to use the
+\fB\-v\fR
+option.
+.PP
+If no value is specified, a value of
+\fIall\fR
+is implied.
+Negating the option results in a value of
+\fInever\fR
+being used.
+The default value is
+\fIall\fR.
+.RE
+.PP
+\fBLists that can be used in a boolean context\fR:
+.\}
+.TP 18n
+env_check
+Environment variables to be removed from the user's environment
+unless they are considered
+\(lqsafe\(rq.
+For all variables except
+\fRTZ\fR,
+\(lqsafe\(rq
+means that the variable's value does not contain any
+\(oq%\(cq
+or
+\(oq/\(cq
+characters.
+This can be used to guard against printf-style format vulnerabilities
+in poorly-written programs.
+The
+\fRTZ\fR
+variable is considered unsafe if any of the following are true:
+.PP
+.RS 18n
+.PD 0
+.TP 3n
+\fB\(bu\fR
+It consists of a fully-qualified path name,
+optionally prefixed with a colon
+(\(oq:\&\(cq),
+that does not match the location of the
+\fIzoneinfo\fR
+directory.
+.PD
+.TP 3n
+\fB\(bu\fR
+It contains a
+\fI..\fR
+path element.
+.TP 3n
+\fB\(bu\fR
+It contains white space or non-printable characters.
+.TP 3n
+\fB\(bu\fR
+It is longer than the value of
+\fRPATH_MAX\fR.
+.PP
+The argument may be a double-quoted, space-separated list or a
+single value without double-quotes.
+The list can be replaced, added to, deleted from, or disabled by using
+the
+\(oq=\(cq,
+\(oq+=\(cq,
+\(oq-=\(cq,
+and
+\(oq\&!\(cq
+operators respectively.
+Regardless of whether the
+\fIenv_reset\fR
+option is enabled or disabled, variables specified by
+\fIenv_check\fR
+will be preserved in the environment if they pass the aforementioned check.
+The global list of environment variables to check is displayed when
+\fBsudo\fR
+is run by
+\fBroot\fR
+with the
+\fB\-V\fR
+option.
+.RE
+.TP 18n
+env_delete
+Environment variables to be removed from the user's environment when the
+\fIenv_reset\fR
+option is not in effect.
+The argument may be a double-quoted, space-separated list or a
+single value without double-quotes.
+The list can be replaced, added to, deleted from, or disabled by using the
+\(oq=\(cq,
+\(oq+=\(cq,
+\(oq-=\(cq,
+and
+\(oq\&!\(cq
+operators respectively.
+The global list of environment variables to remove is displayed when
+\fBsudo\fR
+is run by
+\fBroot\fR
+with the
+\fB\-V\fR
+option.
+Many operating systems will remove potentially dangerous variables
+from the environment of any set-user-ID process (such as
+\fBsudo\fR).
+.TP 18n
+env_keep
+Environment variables to be preserved in the user's environment when the
+\fIenv_reset\fR
+option is in effect.
+This allows fine-grained control over the environment
+\fBsudo\fR-spawned
+processes will receive.
+The argument may be a double-quoted, space-separated list or a
+single value without double-quotes.
+The list can be replaced, added to, deleted from, or disabled by using the
+\(oq=\(cq,
+\(oq+=\(cq,
+\(oq-=\(cq,
+and
+\(oq\&!\(cq
+operators respectively.
+The global list of variables to keep
+is displayed when
+\fBsudo\fR
+is run by
+\fBroot\fR
+with the
+\fB\-V\fR
+option.
+.sp
+Preserving the
+\fRHOME\fR
+environment variable has security implications since many programs use it
+when searching for configuration or data files.
+Adding
+\fRHOME\fR
+to
+\fIenv_keep\fR
+may enable a user to run unrestricted commands via
+\fBsudo\fR
+and is strongly discouraged.
+Users wishing to edit files with
+\fBsudo\fR
+should run
+\fBsudoedit\fR
+(or
+\fBsudo\fR \fB\-e\fR)
+to get their accustomed editor configuration instead of
+invoking the editor directly.
+.TP 18n
+log_servers
+A list of one or more servers to use for remote event and I/O log storage,
+separated by white space.
+Log servers must be running
+\fBsudo_logsrvd\fR
+or another service that implements the protocol described by
+sudo_logsrv.proto(@mansectform@).
+.sp
+Server addresses should be of the form
+\(lqhost[:port][(tls)]\(rq.
+The host portion may be a host name, an IPv4 address, or an IPv6 address
+in square brackets.
+.sp
+If the optional
+\fItls\fR
+flag is present, the connection will be secured
+with Transport Layer Security (TLS) version 1.2 or 1.3.
+Versions of TLS prior to 1.2 are not supported.
+.sp
+If a port is specified, it may either be a port number or a well-known
+service name as defined by the system service name database.
+If no port is specified, port 30343 will be used for plaintext
+connections and port 30344 will be used for TLS connections.
+.sp
+When
+\fIlog_servers\fR
+is set, event log data will be logged both locally (see the
+\fIsyslog\fR
+and
+\fIlog_file\fR
+settings) as well as remotely, but I/O log data will only be logged remotely.
+If multiple hosts are specified, they will be attempted in reverse order.
+If no log servers are available, the user will not be able to run
+a command unless either the
+\fIignore_iolog_errors\fR
+flag (I/O logging enabled) or the
+\fIignore_log_errors\fR
+flag (I/O logging disabled) is set.
+Likewise, if the connection to the log server is interrupted while
+\fBsudo\fR
+is running, the command will be terminated unless the
+\fIignore_iolog_errors\fR
+flag (I/O logging enabled) or the
+\fIignore_log_errors\fR
+flag (I/O logging disabled) is set.
+.sp
+This setting is only supported by version 1.9.0 or higher.
+.TP 18n
+passprompt_regex
+A list of POSIX extended regular expressions used to
+match password prompts in the terminal output.
+As an extension, if the regular expression begins with
+\(lq(?i)\(rq,
+it will be matched in a case-insensitive manner.
+Each regular expression is limited to 1024 characters.
+This option is only used when
+\fIlog_passwords\fR
+has been disabled.
+The default value is
+\(lq[Pp]assword[: ]*\(rq
+.sp
+This setting is only supported by version 1.9.10 or higher.
+.SH "GROUP PROVIDER PLUGINS"
+The
+\fBsudoers\fR
+plugin supports its own plugin interface to allow non-Unix
+group lookups which can query a group source other
+than the standard Unix group database.
+This can be used to implement support for the
+\fInonunix_group\fR
+syntax described earlier.
+.PP
+Group provider plugins are specified via the
+\fIgroup_plugin\fR
+setting.
+The argument to
+\fIgroup_plugin\fR
+should consist of the plugin path, either fully-qualified or relative to the
+\fI@plugindir@\fR
+directory, followed by any configuration options the plugin requires.
+These options (if specified) will be passed to the plugin's initialization
+function.
+If options are present, the string must be enclosed in double quotes
+(\&"").
+.PP
+The following group provider plugins are installed by default:
+.TP 6n
+group_file
+The
+\fIgroup_file\fR
+plugin supports an alternate group file that uses the same syntax as the
+\fI/etc/group\fR
+file.
+The path to the group file should be specified as an option
+to the plugin.
+For example, if the group file to be used is
+\fI/etc/sudo-group\fR:
+.nf
+.sp
+.RS 6n
+Defaults group_plugin="group_file.so /etc/sudo-group"
+.RE
+.fi
+.TP 6n
+system_group
+The
+\fIsystem_group\fR
+plugin supports group lookups via the standard C library functions
+getgrnam(3)
+and
+getgrid(3).
+This plugin can be used in instances where the user belongs to
+groups not present in the user's supplemental group vector.
+This plugin takes no options:
+.nf
+.sp
+.RS 6n
+Defaults group_plugin=system_group.so
+.RE
+.fi
+.PP
+The group provider plugin API is described in detail in
+sudo_plugin(@mansectform@).
+.SH "EVENT LOGGING"
+\fBsudoers\fR
+can log events in either JSON or
+\fIsudo\fR
+format,
+this section describes the
+\fIsudo\fR
+log format.
+Depending on
+\fIsudoers\fR
+configuration,
+\fBsudoers\fR
+can log events via
+syslog(3),
+to a local log file, or both.
+The log format is almost identical in both cases.
+Any control characters present in the log data are formatted in octal
+with a leading
+\(oq#\(cq
+character.
+For example, a horizontal tab is stored as
+\(oq#011\(cq
+and an embedded carriage return is stored as
+\(oq#015\(cq.
+In addition, space characters in the command path are stored as
+\(oq#040\(cq.
+Command line arguments that contain spaces are enclosed in single quotes
+('').
+This makes it possible to distinguish multiple command line arguments
+from a single argument that contains spaces.
+Literal single quotes and backslash characters
+(\(oq\e\(cq)
+in command line arguments are escaped with a backslash.
+.SS "Accepted command log entries"
+Commands that sudo runs are logged using the following format (split
+into multiple lines for readability):
+.nf
+.sp
+.RS 4n
+date hostname progname: username : TTY=ttyname ; CHROOT=chroot ; \e
+ PWD=cwd ; USER=runasuser ; GROUP=runasgroup ; TSID=logid ; \e
+ ENV=env_vars COMMAND=command
+.RE
+.fi
+.PP
+Where the fields are as follows:
+.TP 14n
+date
+The date the command was run.
+Typically, this is in the format
+\(lqMMM, DD, HH:MM:SS\(rq.
+If logging via
+syslog(3),
+the actual date format is controlled by the syslog daemon.
+If logging to a file and the
+\fIlog_year\fR
+option is enabled,
+the date will also include the year.
+.TP 14n
+hostname
+The name of the host
+\fBsudo\fR
+was run on.
+This field is only present when logging via
+syslog(3).
+.TP 14n
+progname
+The name of the program, usually
+\fIsudo\fR
+or
+\fIsudoedit\fR.
+This field is only present when logging via
+syslog(3).
+.TP 14n
+username
+The login name of the user who ran
+\fBsudo\fR.
+.TP 14n
+ttyname
+The short name of the terminal (e.g.,
+\(lqconsole\(rq,
+\(lqtty01\(rq,
+or
+\(lqpts/0\(rq)
+\fBsudo\fR
+was run on, or
+\(lqunknown\(rq
+if there was no terminal present.
+.TP 14n
+chroot
+The root directory that the command was run in, if one was specified.
+.TP 14n
+cwd
+The current working directory that
+\fBsudo\fR
+was run in.
+.TP 14n
+runasuser
+The user the command was run as.
+.TP 14n
+runasgroup
+The group the command was run as if one was specified on the command line.
+.TP 14n
+logid
+An I/O log identifier that can be used to replay the command's output.
+This is only present when the
+\fIlog_input\fR
+or
+\fIlog_output\fR
+option is enabled.
+.TP 14n
+env_vars
+A list of environment variables specified on the command line,
+if specified.
+.TP 14n
+command
+The actual command that was executed, including any command line arguments.
+.PP
+Messages are logged using the locale specified by
+\fIsudoers_locale\fR,
+which defaults to the
+\(oqC\(cq
+locale.
+.SS "Denied command log entries"
+If the user is not allowed to run the command, the reason for the denial
+will follow the user name.
+Possible reasons include:
+.TP 3n
+user NOT in sudoers
+The user is not listed in the
+\fIsudoers\fR
+file.
+.TP 3n
+user NOT authorized on host
+The user is listed in the
+\fIsudoers\fR
+file but is not allowed to run commands on the host.
+.TP 3n
+command not allowed
+The user is listed in the
+\fIsudoers\fR
+file for the host but they are not allowed to run the specified command.
+.TP 3n
+3 incorrect password attempts
+The user failed to enter their password after 3 tries.
+The actual number of tries will vary based on the number of
+failed attempts and the value of the
+\fIpasswd_tries\fR
+option.
+.TP 3n
+a password is required
+The
+\fB\-n\fR
+option was specified but a password was required.
+.TP 3n
+sorry, you are not allowed to set the following environment variables
+The user specified environment variables on the command line that
+were not allowed by
+\fIsudoers\fR.
+.SS "Error log entries"
+If an error occurs,
+\fBsudoers\fR
+will log a message and, in most cases, send a message to the
+administrator via email.
+Possible errors include:
+.TP 3n
+parse error in @sysconfdir@/sudoers near line N
+\fBsudoers\fR
+encountered an error when parsing the specified file.
+In some cases, the actual error may be one line above or below the
+line number listed, depending on the type of error.
+.TP 3n
+problem with defaults entries
+The
+\fIsudoers\fR
+file contains one or more unknown Defaults settings.
+This does not prevent
+\fBsudo\fR
+from running, but the
+\fIsudoers\fR
+file should be checked using
+\fBvisudo\fR.
+.TP 3n
+timestamp owner (username): \&No such user
+The time stamp directory owner, as specified by the
+\fItimestampowner\fR
+setting, could not be found in the password database.
+.TP 3n
+unable to open/read @sysconfdir@/sudoers
+The
+\fIsudoers\fR
+file could not be opened for reading.
+This can happen when the
+\fIsudoers\fR
+file is located on a remote file system that maps user-ID 0 to
+a different value.
+Normally,
+\fBsudoers\fR
+tries to open the
+\fIsudoers\fR
+file using group permissions to avoid this problem.
+Consider either changing the ownership of
+\fI@sysconfdir@/sudoers\fR
+or adding an argument like
+\(lqsudoers_uid=N\(rq
+(where
+\(oqN\(cq
+is the user-ID that owns the
+\fIsudoers\fR
+file) to the end of the
+\fBsudoers\fR
+\fIPlugin\fR
+line in the
+sudo.conf(@mansectform@)
+file.
+.TP 3n
+unable to open @sysconfdir@/sudoers
+The
+\fI@sysconfdir@/sudoers\fR
+file is missing.
+.TP 3n
+@sysconfdir@/sudoers is not a regular file
+The
+\fI@sysconfdir@/sudoers\fR
+file exists but is not a regular file or symbolic link.
+.TP 3n
+@sysconfdir@/sudoers is owned by uid N, should be 0
+The
+\fIsudoers\fR
+file has the wrong owner.
+If you wish to change the
+\fIsudoers\fR
+file owner, add
+\(lqsudoers_uid=N\(rq
+(where
+\(oqN\(cq
+is the user-ID that owns the
+\fIsudoers\fR
+file) to the
+\fBsudoers\fR
+\fIPlugin\fR
+line in the
+sudo.conf(@mansectform@)
+file.
+.TP 3n
+@sysconfdir@/sudoers is world writable
+The permissions on the
+\fIsudoers\fR
+file allow all users to write to it.
+The
+\fIsudoers\fR
+file must not be world-writable, the default file mode
+is 0440 (readable by owner and group, writable by none).
+The default mode may be changed via the
+\(lqsudoers_mode\(rq
+option to the
+\fBsudoers\fR
+\fIPlugin\fR
+line in the
+sudo.conf(@mansectform@)
+file.
+.TP 3n
+@sysconfdir@/sudoers is owned by gid N, should be 1
+The
+\fIsudoers\fR
+file has the wrong group ownership.
+If you wish to change the
+\fIsudoers\fR
+file group ownership, add
+\(lqsudoers_gid=N\(rq
+(where
+\(oqN\(cq
+is the group-ID that owns the
+\fIsudoers\fR
+file) to the
+\fBsudoers\fR
+\fIPlugin\fR
+line in the
+sudo.conf(@mansectform@)
+file.
+.TP 3n
+unable to open @rundir@/ts/user-ID
+\fBsudoers\fR
+was unable to read or create the user's time stamp file.
+This can happen when
+\fItimestampowner\fR
+is set to a user other than
+\fBroot\fR
+and the mode on
+\fI@rundir@\fR
+is not searchable by group or other.
+The default mode for
+\fI@rundir@\fR
+is 0711.
+.TP 3n
+unable to write to @rundir@/ts/user-ID
+\fBsudoers\fR
+was unable to write to the user's time stamp file.
+.TP 3n
+@rundir@/ts is owned by uid X, should be Y
+The time stamp directory is owned by a user other than
+\fItimestampowner\fR.
+This can occur when the value of
+\fItimestampowner\fR
+has been changed.
+\fBsudoers\fR
+will ignore the time stamp directory until the owner is corrected.
+.TP 3n
+@rundir@/ts is group writable
+The time stamp directory is group-writable; it should be writable only by
+\fItimestampowner\fR.
+The default mode for the time stamp directory is 0700.
+\fBsudoers\fR
+will ignore the time stamp directory until the mode is corrected.
+.SS "Notes on logging via syslog"
+By default,
+\fBsudoers\fR
+logs messages via
+syslog(3).
+The
+\fIdate\fR,
+\fIhostname\fR,
+and
+\fIprogname\fR
+fields are added by the system's
+syslog(3)
+function, not
+\fBsudoers\fR
+itself.
+As such, they may vary in format on different systems.
+.PP
+The maximum size of syslog messages varies from system to system.
+The
+\fIsyslog_maxlen\fR
+setting can be used to change the maximum syslog message size
+from the default value of 980 bytes.
+For more information, see the description of
+\fIsyslog_maxlen\fR.
+.SS "Notes on logging to a file"
+If the
+\fIlogfile\fR
+option is set,
+\fBsudoers\fR
+will log to a local file, such as
+\fI@log_dir@/sudo\fR.
+When logging to a file,
+\fBsudoers\fR
+uses a format similar to
+syslog(3),
+with a few important differences:
+.TP 5n
+1.\&
+The
+\fIprogname\fR
+field is not present.
+.TP 5n
+2.\&
+The
+\fIhostname\fR
+is only logged if the
+\fIlog_host\fR
+option is enabled.
+.TP 5n
+3.\&
+The date does not include the year unless the
+\fIlog_year\fR
+option is enabled.
+.TP 5n
+4.\&
+Lines that are longer than
+\fIloglinelen\fR
+characters (80 by default) are word-wrapped and continued on the
+next line with a four character indent.
+This makes entries easier to read for a human being, but makes it
+more difficult to use
+grep(1)
+on the log files.
+If the
+\fIloglinelen\fR
+option is set to 0 (or negated with a
+\(oq\&!\(cq),
+word wrap will be disabled.
+.SH "I/O LOGGING"
+When I/O logging is enabled,
+\fBsudo\fR
+will runs the command in a pseudo-terminal, logging user input
+and/or output, depending on which
+\fBsudoers\fR
+flags are enabled.
+There are five distinct types of I/O that can be logged, each with
+a corresponding
+\fBsudoers\fR
+flag.
+.TS
+l l l.
+.PP
+\fBType\fR \fBFlag\fR \fBDescription\fR
+.PP
+terminal input log_ttyin keystrokes entered by the user
+.PP
+terminal output log_ttyout command output displayed to the screen
+.PP
+standard input log_stdin input from a pipe or a file
+.PP
+standard output log_stdout output to a pipe or a file
+.PP
+standard error log_stderr output to a pipe or a file
+.TE
+.PP
+In addition to flags described the above, the
+\fIlog_input\fR
+flag and
+\fRLOG_INPUT\fR
+command tag set both
+\fIlog_ttyin\fR
+and
+\fIlog_stdin\fR.
+The
+\fIlog_output\fR
+flag and
+\fRLOG_OUTPUT\fR
+command tag set
+\fIlog_ttyout\fR,
+\fIlog_stdout\fR,
+and
+\fIlog_stderr\fR.
+.PP
+To capture terminal input and output,
+\fBsudo\fR
+run the command in a pseudo-terminal, logging the input and
+output before passing it on to the user.
+To capture the standard input, standard output or standard error,
+\fBsudo\fR
+uses a pipe to interpose itself between the input or output stream,
+logging the I/O before passing it to the other end of the pipe.
+.PP
+I/O can be logged either to the local machine or to a remote log server.
+For local logs, I/O is logged to the directory specified by the
+\fIiolog_dir\fR
+option
+(\fI@iolog_dir@\fR
+by default)
+using a unique session ID that is included in the
+\fBsudo\fR
+log line, prefixed with
+\(oqTSID=\(cq.
+The
+\fIiolog_file\fR
+option may be used to control the format of the session ID.
+For remote logs, the
+\fIlog_servers\fR
+setting is used to specify one or more log servers running
+\fBsudo_logsrvd\fR
+or another server that implements the protocol described by
+sudo_logsrv.proto(@mansectform@).
+.SS "I/O logging pitfals"
+When logging standard input, anything sent to the standard input
+will be consumed, regardless of whether or not the command run via
+\fBsudo\fR
+is actively reading the standard input.
+This may have unexpected results when using
+\fBsudo\fR
+in a shell script that expects to process the standard input.
+For example, given the following shell script:
+.nf
+.sp
+.RS 4n
+#!/bin/sh
+sudo echo testing
+echo done
+.RE
+.fi
+.PP
+It will behave as expected when the script is passed to the shell as a
+an argument:
+.nf
+.sp
+.RS 4n
+$ sh test.sh
+testing
+done
+.RE
+.fi
+.PP
+However, if the script is passed to the shell on the standard input, the
+\(oqsudo echo testing\(cq
+command will consume the rest of the script.
+This means that the
+\(oqecho done\(cq
+statement is never executed.
+.nf
+.sp
+.RS 4n
+$ sh -s < test.sh
+testing
+.RE
+.fi
+.PP
+There are several ways to work around this problem:
+.TP 5n
+1.\&
+Redirect the standard input from
+\fI/dev/null\fR
+when running a command via
+\fBsudo\fR
+that does not need to read the standard input.
+.nf
+.sp
+.RS 9n
+sudo echo testing < /dev/null
+.RE
+.fi
+.TP 5n
+2.\&
+Pass the script to the shell by path name instead of via the standard input.
+.nf
+.sp
+.RS 9n
+sh test.sh
+.RE
+.fi
+.TP 5n
+3.\&
+Disable logging the standard input for commands that do not need
+to read the standard input.
+.nf
+.sp
+.RS 9n
+Defaults!/bin/echo !log_stdin
+.RE
+.fi
+.PP
+Depending on the command, it may not be desirable to log the
+standard input or standard output.
+For example, I/O logging of commands that send or receive large
+amount of data via the standard output or standard input such as
+rsync(1)
+and
+tar(1)
+could fill up the log file system with superfluous data.
+It is possible to disable logging of the standard input and standard
+output for such commands as follows:
+.nf
+.sp
+.RS 4n
+Cmnd_Alias COPY_CMDS = /usr/bin/tar, /usr/bin/cpio, /usr/bin/rsync
+
+# Log input and output but omit stdin and stdout when copying files.
+Defaults log_input, log_output
+Defaults!COPY_CMDS !log_stdin, !log_stdout
+.RE
+.fi
+.PP
+However, be aware that using the
+\fIlog_input\fR
+flag or the
+\fRLOG_INPUT\fR
+command tag will also enable
+\fIlog_stdin\fR.
+Likewise, the
+\fIlog_ouput\fR
+flag or the
+\fRLOG_OUTPUT\fR
+command tag will enable
+\fIlog_stdout\fR
+and
+\fIlog_stderr.\fR
+Careful ordering of rules may be necessary to achieve the results
+that you expect.
+.SS "I/O log format"
+For both local and remote I/O logs, each log is stored in a separate
+directory that contains the following files:
+.TP 10n
+\fIlog\fR
+A text file containing information about the command.
+The first line consists of the following colon-delimited fields:
+the time the command was run, the name of the user
+who ran
+\fBsudo\fR,
+the name of the target user, the name of the target group (optional),
+the terminal that
+\fBsudo\fR
+was run from, and the number of lines and columns of the terminal.
+The second and third lines contain the working directory the command
+was run from and the path name of the command itself (with arguments
+if present).
+.TP 10n
+\fIlog.json\fR
+A JSON-formatted file containing information about the command.
+This is similar to the
+\fIlog\fR
+file but contains additional information and is easily extensible.
+The
+\fIlog.json\fR
+file will be used by
+sudoreplay(@mansectsu@)
+in preference to the
+\fIlog\fR
+file if it exists.
+The file may contain the following elements:
+.PP
+.RS 10n
+.PD 0
+.TP 6n
+timestamp
+A JSON object containing time the command was run.
+It consists of two values,
+\fIseconds\fR
+and
+\fInanoseconds\fR.
+.PD
+.TP 6n
+columns
+The number of columns of the terminal the command ran on, or zero
+if no terminal was present.
+.TP 6n
+command
+The fully-qualified path of the command that was run.
+.TP 6n
+lines
+.br
+The number of lines of the terminal the command ran on, or zero
+if no terminal was present.
+.TP 6n
+runargv
+A JSON array representing the command's argument vector as passed to the
+execve(2)
+system call.
+.TP 6n
+runenv
+A JSON array representing the command's environment as passed to the
+execve(2)
+system call.
+.TP 6n
+rungid
+The group ID the command ran as.
+This element is only present when the user specifies a group on the
+command line.
+.TP 6n
+rungroup
+The name of the group the command ran as.
+This element is only present when the user specifies a group on the
+command line.
+.TP 6n
+runuid
+The user ID the command ran as.
+.TP 6n
+runuser
+The name of the user the command ran as.
+.TP 6n
+submitcwd
+The current working directory at the time
+\fBsudo\fR
+was run.
+.TP 6n
+submithost
+The name of the host the command was run on.
+.TP 6n
+submituser
+The name of the user who ran the command via
+\fBsudo\fR.
+.TP 6n
+ttyname
+The path name of the terminal the user invoked
+\fBsudo\fR
+from.
+If the command was run in a pseudo-terminal,
+\fIttyname\fR
+will be different from the terminal the command actually ran in.
+.PD 0
+.PP
+.RE
+.PD
+.TP 10n
+\fItiming\fR
+Timing information used to replay the session.
+Each line consists of the I/O log entry type and amount of time
+since the last entry, followed by type-specific data.
+The I/O log entry types and their corresponding type-specific data are:
+.PP
+.RS 10n
+.PD 0
+.TP 6n
+0
+standard input, number of bytes in the entry
+.TP 6n
+1
+standard output, number of bytes in the entry
+.TP 6n
+2
+standard error, number of bytes in the entry
+.TP 6n
+3
+terminal input, number of bytes in the entry
+.TP 6n
+4
+terminal output, number of bytes in the entry
+.TP 6n
+5
+window change, new number lines and columns
+.TP 6n
+6
+bug compatibility for
+\fBsudo\fR
+1.8.7 terminal output
+.TP 6n
+7
+command suspend or resume, signal received
+.PP
+.RE
+.PD
+.TP 10n
+\fIttyin\fR
+Raw input from the user's terminal, exactly as it was received.
+This file is only present if the
+\fIlog_input\fR
+or
+\fIlog_ttyin\fR
+flags are set and
+\fBsudo\fR
+was run from a terminal.
+No post-processing is performed.
+For manual viewing, you may wish to convert carriage return characters
+in the log to line feeds.
+For example:
+\(oqgunzip -c ttyin | tr \&"\er\&" \&"\en\&"\(cq
+.TP 10n
+\fIstdin\fR
+The standard input when no terminal is present, or input redirected from
+a pipe or file.
+This file is only present if the
+\fIlog_input\fR
+or
+\fIlog_stdin\fR
+flags are set and the standard input is not connected to a terminal.
+.TP 10n
+\fIttyout\fR
+Output from the pseudo-terminal (what the command writes to the screen).
+Terminal-specific post-processing is performed before the data is logged.
+This means that, for example, line feeds are usually converted to
+line feed/carriage return pairs and tabs may be expanded to spaces.
+This file is only present if the
+\fIlog_output\fR
+or
+\fIlog_ttyout\fR
+flags are set and
+\fBsudo\fR
+was run from a terminal.
+.TP 10n
+\fIstdout\fR
+The standard output when no terminal is present, or output redirected to
+a pipe or file.
+This file is only present if the
+\fIlog_output\fR
+or
+\fIlog_stdout\fR
+flags are set and the standard output is not connected to a terminal.
+.TP 10n
+\fIstderr\fR
+The standard error when no terminal is present, or output redirected to
+a pipe or file.
+This file is only present if the
+\fIlog_output\fR
+or
+\fIlog_stderr\fR
+flags are set and the standard error is not connected to a terminal.
+.PP
+All files other than
+\fIlog\fR
+are compressed in gzip format unless the
+\fIcompress_io\fR
+flag has been disabled.
+Due to buffering, it is not normally possible to display the I/O logs in
+real-time as the program is executing.
+The I/O log data will not be complete until the program run by
+\fBsudo\fR
+has exited or has been terminated by a signal.
+The
+\fIiolog_flush\fR
+flag can be used to disable buffering, in which case I/O log data
+is written to disk as soon as it is available.
+The output portion of an I/O log file can be viewed with the
+sudoreplay(@mansectsu@)
+utility, which can also be used to list or search the available logs.
+.PP
+User input may contain sensitive information such as passwords (even
+if they are not echoed to the screen), which will be stored in the
+log file unencrypted.
+In most cases, logging the command output via
+\fIlog_output\fR
+or
+\fRLOG_OUTPUT\fR
+is all that is required.
+When logging input, consider disabling the
+\fIlog_passwords\fR
+flag.
+.PP
+Since each session's I/O logs are stored in a separate directory,
+traditional log rotation utilities cannot be used to limit the
+number of I/O logs.
+The simplest way to limit the number of I/O is by setting the
+\fImaxseq\fR
+option to the maximum number of logs you wish to store.
+Once the I/O log sequence number reaches
+\fImaxseq\fR,
+it will be reset to zero and
+\fBsudoers\fR
+will truncate and re-use any existing I/O logs.
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/sudo.conf\fR
+Sudo front-end configuration
+.TP 26n
+\fI@sysconfdir@/sudoers\fR
+List of who can run what
+.TP 26n
+\fI/etc/group\fR
+Local groups file
+.TP 26n
+\fI/etc/netgroup\fR
+List of network groups
+.TP 26n
+\fI@iolog_dir@\fR
+I/O log files
+.TP 26n
+\fI@rundir@/ts\fR
+Directory containing time stamps for the
+\fBsudoers\fR
+security policy
+.TP 26n
+\fI@vardir@/lectured\fR
+Directory containing lecture status files for the
+\fBsudoers\fR
+security policy
+.TP 26n
+\fI/etc/environment\fR
+Initial environment for
+\fB\-i\fR
+mode on AIX and Linux systems
+.SH "EXAMPLES"
+Below are example
+\fIsudoers\fR
+file entries.
+Admittedly, some of these are a bit contrived.
+First, we allow a few environment variables to pass and then define our
+\fIaliases\fR:
+.nf
+.sp
+.RS 0n
+# Run X applications through sudo; HOME is used to find the
+# .Xauthority file. Other programs use HOME to locate configuration
+# files and this may lead to privilege escalation!
+Defaults env_keep += "DISPLAY HOME"
+
+# User alias specification
+User_Alias FULLTIMERS = millert, mikef, dowdy
+User_Alias PARTTIMERS = bostley, jwfox, crawl
+User_Alias WEBADMIN = will, wendy, wim
+
+# Runas alias specification
+Runas_Alias OP = root, operator
+Runas_Alias DB = oracle, sybase
+Runas_Alias ADMINGRP = adm, oper
+
+# Host alias specification
+Host_Alias SPARC = bigtime, eclipse, moet, anchor :\e
+ SGI = grolsch, dandelion, black :\e
+ ALPHA = widget, thalamus, foobar :\e
+ HPPA = boa, nag, python
+Host_Alias CUNETS = 128.138.0.0/255.255.0.0
+Host_Alias CSNETS = 128.138.243.0, 128.138.204.0/24, 128.138.242.0
+Host_Alias SERVERS = primary, mail, www, ns
+Host_Alias CDROM = orion, perseus, hercules
+
+# Cmnd alias specification
+Cmnd_Alias DUMPS = /usr/bin/mt, /usr/sbin/dump, /usr/sbin/rdump,\e
+ /usr/sbin/restore, /usr/sbin/rrestore,\e
+ sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ== \e
+ /home/operator/bin/start_backups
+Cmnd_Alias KILL = /usr/bin/kill
+Cmnd_Alias PRINTING = /usr/sbin/lpc, /usr/bin/lprm
+Cmnd_Alias SHUTDOWN = /usr/sbin/shutdown
+Cmnd_Alias HALT = /usr/sbin/halt
+Cmnd_Alias REBOOT = /usr/sbin/reboot
+Cmnd_Alias SHELLS = /usr/bin/sh, /usr/bin/csh, /usr/bin/ksh,\e
+ /usr/local/bin/tcsh, /usr/bin/rsh,\e
+ /usr/local/bin/zsh
+Cmnd_Alias SU = /usr/bin/su
+Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less
+.RE
+.fi
+.PP
+Here we override some of the compiled in default values.
+We want
+\fBsudo\fR
+to log via
+syslog(3)
+using the
+\fIauth\fR
+facility in all cases and for commands to be run with
+the target user's home directory as the working directory.
+We don't want to subject the full time staff to the
+\fBsudo\fR
+lecture and we want to allow them to run commands in a
+chroot(2)
+\(lqsandbox\(rq
+via the
+\fB\-R\fR
+option.
+User
+\fBmillert\fR
+need not provide a password and we don't want to reset the
+\fRLOGNAME\fR
+or
+\fRUSER\fR
+environment variables when running commands as
+\fBroot\fR.
+Additionally, on the machines in the
+\fRSERVERS\fR
+\fIHost_Alias\fR,
+we keep an additional local log file and make sure we log the year
+in each log line since the log entries will be kept around for several years.
+Lastly, we disable shell escapes for the commands in the PAGERS
+\fICmnd_Alias\fR
+(\fI/usr/bin/more\fR,
+\fI/usr/bin/pg\fR
+and
+\fI/usr/bin/less\fR)
+\&.
+This will not effectively constrain users with
+\fBsudo\fR
+\fBALL\fR
+privileges.
+.nf
+.sp
+.RS 0n
+# Override built-in defaults
+Defaults syslog=auth,runcwd=~
+Defaults>root !set_logname
+Defaults:FULLTIMERS !lecture,runchroot=*
+Defaults:millert !authenticate
+Defaults@SERVERS log_year, logfile=@log_dir@/sudo.log
+Defaults!PAGERS noexec
+.RE
+.fi
+.PP
+The
+\fIUser specification\fR
+is the part that actually determines who may run what.
+.nf
+.sp
+.RS 0n
+root ALL = (ALL) ALL
+%wheel ALL = (ALL) ALL
+.RE
+.fi
+.PP
+We let
+\fBroot\fR
+and any user in group
+\fBwheel\fR
+run any command on any host as any user.
+.nf
+.sp
+.RS 0n
+FULLTIMERS ALL = NOPASSWD: ALL
+.RE
+.fi
+.PP
+Full time sysadmins
+(\fBmillert\fR,
+\fBmikef\fR,
+and
+\fBdowdy\fR)
+may run any command on any host without authenticating themselves.
+.nf
+.sp
+.RS 0n
+PARTTIMERS ALL = ALL
+.RE
+.fi
+.PP
+Part time sysadmins
+\fBbostley\fR,
+\fBjwfox\fR,
+and
+\fBcrawl\fR)
+may run any command on any host but they must authenticate themselves
+first (since the entry lacks the
+\fRNOPASSWD\fR
+tag).
+.nf
+.sp
+.RS 0n
+jack CSNETS = ALL
+.RE
+.fi
+.PP
+The user
+\fBjack\fR
+may run any command on the machines in the
+\fRCSNETS\fR
+alias (the networks 128.138.243.0, 128.138.204.0, and 128.138.242.0).
+Of those networks, only 128.138.204.0 has an explicit netmask (in
+CIDR notation) indicating it is a class C network.
+For the other networks in
+\fRCSNETS\fR,
+the local machine's netmask will be used during matching.
+.nf
+.sp
+.RS 0n
+lisa CUNETS = ALL
+.RE
+.fi
+.PP
+The user
+\fBlisa\fR
+may run any command on any host in the
+\fRCUNETS\fR
+alias (the class B network 128.138.0.0).
+.nf
+.sp
+.RS 0n
+operator ALL = DUMPS, KILL, SHUTDOWN, HALT, REBOOT, PRINTING,\e
+ sudoedit /etc/printcap, /usr/oper/bin/
+.RE
+.fi
+.PP
+The
+\fBoperator\fR
+user may run commands limited to simple maintenance.
+Here, those are commands related to backups, killing processes, the
+printing system, shutting down the system, and any commands in the
+directory
+\fI/usr/oper/bin/\fR.
+One command in the
+\fRDUMPS\fR
+Cmnd_Alias includes a sha224 digest,
+\fI/home/operator/bin/start_backups\fR.
+This is because the directory containing the script is writable by the
+operator user.
+If the script is modified (resulting in a digest mismatch) it will no longer
+be possible to run it via
+\fBsudo\fR.
+.nf
+.sp
+.RS 0n
+joe ALL = /usr/bin/su operator
+.RE
+.fi
+.PP
+The user
+\fBjoe\fR
+may only
+su(1)
+to operator.
+.nf
+.sp
+.RS 0n
+pete HPPA = /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd *root*
+
+%opers ALL = (: ADMINGRP) /usr/sbin/
+.RE
+.fi
+.PP
+Users in the
+\fBopers\fR
+group may run commands in
+\fI/usr/sbin/\fR
+as themselves
+with any group in the
+\fRADMINGRP\fR
+\fIRunas_Alias\fR
+(the
+\fBadm\fR
+and
+\fBoper\fR
+groups).
+.PP
+The user
+\fBpete\fR
+is allowed to change anyone's password except for
+\fBroot\fR
+on the
+\fRHPPA\fR
+machines.
+Because command line arguments are matched as a single,
+concatenated string, the
+\(oq*\(cq
+wildcard will match
+\fImultiple\fR
+words.
+This example assumes that
+passwd(1)
+does not take multiple user names on the command line.
+On systems with GNU
+getopt(3),
+options to
+passwd(1)
+may be specified after the user argument.
+As a result, this rule will also allow:
+.nf
+.sp
+.RS 4n
+passwd username --expire
+.RE
+.fi
+.PP
+which may not be desirable.
+.nf
+.sp
+.RS 0n
+bob SPARC = (OP) ALL : SGI = (OP) ALL
+.RE
+.fi
+.PP
+The user
+\fBbob\fR
+may run anything on the
+\fRSPARC\fR
+and
+\fRSGI\fR
+machines as any user listed in the
+\fROP\fR
+\fIRunas_Alias\fR
+(\fBroot\fR
+and
+\fBoperator\fR.)
+.nf
+.sp
+.RS 0n
+jim +biglab = ALL
+.RE
+.fi
+.PP
+The user
+\fBjim\fR
+may run any command on machines in the
+\fIbiglab\fR
+netgroup.
+\fBsudo\fR
+knows that
+\(lqbiglab\(rq
+is a netgroup due to the
+\(oq+\(cq
+prefix.
+.nf
+.sp
+.RS 0n
++secretaries ALL = PRINTING, /usr/bin/adduser, /usr/bin/rmuser
+.RE
+.fi
+.PP
+Users in the
+\fBsecretaries\fR
+netgroup need to help manage the printers as well as add and remove users,
+so they are allowed to run those commands on all machines.
+.nf
+.sp
+.RS 0n
+fred ALL = (DB) NOPASSWD: ALL
+.RE
+.fi
+.PP
+The user
+\fBfred\fR
+can run commands as any user in the
+\fRDB\fR
+\fIRunas_Alias\fR
+(\fBoracle\fR
+or
+\fBsybase\fR)
+without giving a password.
+.nf
+.sp
+.RS 0n
+john ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root*
+.RE
+.fi
+.PP
+On the
+\fRALPHA\fR
+machines, user
+\fBjohn\fR
+may su to anyone except
+\fBroot\fR
+but he is not allowed to specify any options to the
+su(1)
+command.
+.nf
+.sp
+.RS 0n
+jen ALL, !SERVERS = ALL
+.RE
+.fi
+.PP
+The user
+\fBjen\fR
+may run any command on any machine except for those in the
+\fRSERVERS\fR
+\fIHost_Alias\fR
+(primary, mail, www, and ns).
+.nf
+.sp
+.RS 0n
+jill SERVERS = /usr/bin/, !SU, !SHELLS
+.RE
+.fi
+.PP
+For any machine in the
+\fRSERVERS\fR
+\fIHost_Alias\fR,
+\fBjill\fR
+may run
+any commands in the directory
+\fI/usr/bin/\fR
+except for those commands
+belonging to the
+\fRSU\fR
+and
+\fRSHELLS\fR
+\fICmnd_Aliases\fR.
+While not specifically mentioned in the rule, the commands in the
+\fRPAGERS\fR
+\fICmnd_Alias\fR
+all reside in
+\fI/usr/bin\fR
+and have the
+\fInoexec\fR
+option set.
+.nf
+.sp
+.RS 0n
+steve CSNETS = (operator) /usr/local/op_commands/
+.RE
+.fi
+.PP
+The user
+\fBsteve\fR
+may run any command in the directory /usr/local/op_commands/
+but only as user operator.
+.nf
+.sp
+.RS 0n
+matt valkyrie = KILL
+.RE
+.fi
+.PP
+On his personal workstation, valkyrie,
+\fBmatt\fR
+needs to be able to kill hung processes.
+.nf
+.sp
+.RS 0n
+WEBADMIN www = (www) ALL, (root) /usr/bin/su www
+.RE
+.fi
+.PP
+On the host www, any user in the
+\fRWEBADMIN\fR
+\fIUser_Alias\fR
+(will, wendy, and wim), may run any command as user www (which owns the
+web pages) or simply
+su(1)
+to www.
+.nf
+.sp
+.RS 0n
+ALL CDROM = NOPASSWD: /sbin/umount /CDROM,\e
+ /sbin/mount -o nosuid\e,nodev /dev/cd0a /CDROM
+.RE
+.fi
+.PP
+Any user may mount or unmount a CD-ROM on the machines in the CDROM
+\fIHost_Alias\fR
+(orion, perseus, hercules) without entering a password.
+This is a bit tedious for users to type, so it is a prime candidate
+for encapsulating in a shell script.
+.SH "SECURITY NOTES"
+.SS "Limitations of the \(oq!\&\(cq operator"
+It is generally not effective to
+\(lqsubtract\(rq
+commands from
+\fBALL\fR
+using the
+\(oq!\&\(cq
+operator.
+A user can trivially circumvent this by copying the desired command
+to a different name and then executing that.
+For example:
+.nf
+.sp
+.RS 0n
+bill ALL = ALL, !SU, !SHELLS
+.RE
+.fi
+.PP
+Doesn't really prevent
+\fBbill\fR
+from running the commands listed in
+\fRSU\fR
+or
+\fRSHELLS\fR
+since he can simply copy those commands to a different name, or use
+a shell escape from an editor or other program.
+Therefore, these kind of restrictions should be considered
+advisory at best (and reinforced by policy).
+.PP
+In general, if a user has sudo
+\fBALL\fR
+there is nothing to prevent them from creating their own program that gives
+them a
+\fBroot\fR
+shell (or making their own copy of a shell) regardless of any
+\(oq!\&\(cq
+elements in the user specification.
+.SS "Security implications of \fIfast_glob\fR"
+If the
+\fIfast_glob\fR
+option is in use, it is not possible to reliably negate commands where the
+path name includes globbing (aka wildcard) characters.
+This is because the C library's
+fnmatch(3)
+function cannot resolve relative paths.
+While this is typically only an inconvenience for rules that grant privileges,
+it can result in a security issue for rules that subtract or revoke privileges.
+.PP
+For example, given the following
+\fIsudoers\fR
+file entry:
+.nf
+.sp
+.RS 0n
+john ALL = /usr/bin/passwd [a-zA-Z0-9]*, /usr/bin/chsh [a-zA-Z0-9]*,\e
+ /usr/bin/chfn [a-zA-Z0-9]*, !/usr/bin/* root
+.RE
+.fi
+.PP
+User
+\fBjohn\fR
+can still run
+\(oq/usr/bin/passwd root\(cq
+if
+\fIfast_glob\fR
+is enabled by changing to
+\fI/usr/bin\fR
+and running
+\(oq./passwd root\(cq
+instead.
+.PP
+Another potential issue is that when
+\fBsudo\fR
+executes the command, it must use the command or path specified by
+the user instead of a path listed in the
+\fIsudoers\fR
+file.
+This may lead to a time of check versus time of use race condition.
+.SS "Wildcards in command arguments"
+Command line arguments are matched as a single, concatenated string.
+This mean a wildcard character such as
+\(oq\&?\(cq
+or
+\(oq*\(cq
+will match across word boundaries, which may be unexpected.
+For example, while a sudoers entry like:
+.nf
+.sp
+.RS 4n
+%operator ALL = /bin/cat @log_dir@/messages*
+.RE
+.fi
+.PP
+will allow command like:
+.nf
+.sp
+.RS 4n
+$ sudo cat @log_dir@/messages.1
+.RE
+.fi
+.PP
+It will also allow:
+.nf
+.sp
+.RS 4n
+$ sudo cat @log_dir@/messages /etc/shadow
+.RE
+.fi
+.PP
+which is probably not what was intended.
+A safer alternative is to use a regular expression for matching
+command line arguments.
+The above example can be rewritten as a regular expression:
+.nf
+.sp
+.RS 4n
+%operator ALL = /bin/cat ^@log_dir@/messages[^[:space:]]*$
+.RE
+.fi
+.PP
+The regular expression will only match a single file with a
+name that begins with
+\fI@log_dir@/messages\fR
+and does not include any white space in the name.
+It is often better to do command line processing outside of the
+\fIsudoers\fR
+file in a scripting language for anything non-trivial.
+.SS "Regular expressions in command names"
+Using a regular expression to match a command name has the same
+security implications as using the
+\fIfast_glob\fR
+option:
+.TP 3n
+\fB\(bu\fR
+It is not possible to reliably negate commands when the
+path name is a regular expression.
+.TP 3n
+\fB\(bu\fR
+When
+\fBsudo\fR
+executes the command, it must use the command or path specified by
+the user instead of a path listed in the
+\fIsudoers\fR
+file.
+This may lead to a time of check versus time of use race condition.
+.PP
+These issues do not apply to rules where only the command line
+options are matched using a regular expression.
+.SS "Preventing shell escapes"
+Once
+\fBsudo\fR
+executes a program, that program is free to do whatever
+it pleases, including run other programs.
+This can be a security issue since it is not uncommon for a program to
+allow shell escapes, which lets a user bypass
+\fBsudo\fR's
+access control and logging.
+Common programs that permit shell escapes include shells (obviously),
+editors, paginators, mail, and terminal programs.
+.PP
+There are four basic approaches to this problem:
+.TP 11n
+restrict
+Avoid giving users access to commands that allow the user to run
+arbitrary commands.
+Many editors have a restricted mode where shell
+escapes are disabled, though
+\fBsudoedit\fR
+is a better solution to
+running editors via
+\fBsudo\fR.
+Due to the large number of programs that
+offer shell escapes, restricting users to the set of programs that
+do not is often unworkable.
+.TP 11n
+intercept
+On most systems,
+\fBsudo\fR's
+\fIintercept\fR
+functionality can be used to transparently intercept an attempt to
+run a new command, allow or deny it based on
+\fIsudoers\fR
+rules, and log the result.
+For example, this can be used to restrict the commands run from
+within a privileged shell or editor.
+However, not all programs operate correctly when
+\fIintercept\fR
+is enabled.
+.sp
+There are two underlying mechanisms that may be used to implement
+\fIintercept\fR
+mode:
+\fIdso\fR
+and
+\fItrace\fR.
+The
+\fIintercept_type\fR
+setting can be used to select between them.
+.sp
+The first mechanism,
+\fIdso\fR,
+overrides the standard C library functions that are used to execute a
+command.
+It does this by setting an environment variable (usually
+\fRLD_PRELOAD\fR)
+to the path of a dynamic shared object, or shared library,
+containing custom versions of the
+execve(2),
+execl(3),
+execle(3),
+execlp(3),
+execv(3),
+execvp(3),
+execvpe(3),
+and
+system(3)
+library functions that connect back to
+\fBsudo\fR
+for a policy decision.
+Note, however, that this applies only to dynamically-linked
+executables.
+It is not possible to intercept commands for statically-linked executables
+or executables that run under binary emulation this way.
+Because most dynamic loaders ignore
+\fRLD_PRELOAD\fR
+(or the equivalent) when running set-user-ID and set-group-ID programs,
+\fBsudoers\fR
+will not permit such programs to be run in
+\fIintercept\fR
+mode by default.
+The
+\fIdso\fR
+mechanism is incompatible with
+\fBsudo\fR's
+SELinux RBAC support (but see below).
+SELinux disables
+\fRLD_PRELOAD\fR
+by default and interferes with file descriptor inheritance, which
+\fBsudo\fR
+relies on.
+.sp
+The second mechanism,
+\fItrace\fR,
+is available on Linux systems that support
+seccomp(2)
+filtering.
+It uses
+ptrace(2)
+and
+seccomp(2)
+to intercept the
+execve(2)
+system call instead of pre-loading a dynamic shared object.
+Both static and dynamic executables are supported and it is compatible with
+\fBsudo\fR's
+SELinux RBAC mode.
+Functions utilizing the
+execveat(2)
+system call, such as
+fexecve(3),
+are not currently intercepted.
+Programs that rely on
+ptrace(2)
+themselves, such as debuggers and system call tracers
+(such as
+strace(1)
+and
+truss(1))
+will be unable to function if
+\fIintercept\fR
+is enabled in
+\fItrace\fR
+mode.
+This same restriction applies to the
+\fIlog_subcmds\fR
+sudoers option.
+.sp
+The
+\fIintercept\fR
+feature is known to work on Solaris, *BSD, Linux, macOS, HP-UX 11.x
+and AIX 5.3 and above.
+It should be supported on most operating systems that support the
+\fRLD_PRELOAD\fR
+environment variable or an equivalent.
+It is not possible to intercept shell built-in commands or restrict
+the ability to read or write sensitive files from within a shell.
+.sp
+To enable intercept mode on a per-command basis, use the
+\fRINTERCEPT\fR
+tag as documented in the User Specification section above.
+Here is that example again:
+.nf
+.sp
+.RS 11n
+chuck research = INTERCEPT: ALL
+.RE
+.fi
+.RS 11n
+.sp
+This allows user
+\fBchuck\fR
+to run any command on the machine
+\(lqresearch\(rq
+in intercept mode.
+Any commands run via shell escapes will be validated and logged by
+\fBsudo\fR.
+If you are unsure whether or not your system is capable of supporting
+\fIintercept\fR,
+you can always just try it out and check whether or not external
+commands run via a shell are logged when
+\fIintercept\fR
+is enabled.
+.sp
+There is an inherent race condition between when a command is checked against
+\fBsudoers\fR
+rules and when it is actually executed.
+If a user is allowed to run arbitrary commands, they may be able
+to change the
+execve(2)
+arguments in the program after the
+\fBsudoers\fR
+policy check has completed but before the new command is executed.
+Starting with version 1.9.12, the
+\fItrace\fR
+method will verify that the command and its arguments have not
+changed after
+execve(2)
+has completed but before execution of the new program has had a chance to run.
+This is not the case with the
+\fIdso\fR
+method.
+See the description of the
+\fIintercept_verify\fR
+setting for more information.
+.RE
+.TP 11n
+log
+There are two separate but related ways to log additional commands.
+The first is to enable I/O logging using the
+\fIlog_output\fR
+flag.
+This will log the command's output but will not create an event log
+entry when the additional command is run.
+The second is to enable the
+\fIlog_subcmds\fR
+flag in
+\fIsudoers\fR
+which will create an event log entry every time a new command is run.
+If I/O logging is also enabled, the log entry will include a time offset
+into the I/O log to indicate when the command was run.
+This offset can be passed to the
+sudoreplay(@mansectsu@)
+utility to replay the I/O log at the exact moment when the command was run.
+The
+\fIlog_subcmds\fR
+flag uses the same mechanism as
+\fIintercept\fR
+(see above) and has the same limitations.
+.TP 11n
+noexec
+\fBsudo\fR's
+\fInoexec\fR
+functionality can be used to prevent a program run by
+\fBsudo\fR
+from executing any other programs.
+On most systems, it uses the same
+\fRLD_PRELOAD\fR
+mechanism as
+\fIintercept\fR
+(see above) and thus the same caveats apply.
+The
+\fInoexec\fR
+functionality
+is capable of blocking execution of commands run via the
+execve(2),
+execl(3),
+execle(3),
+execlp(3),
+exect(3),
+execv(3),
+execveat(3),
+execvP(3),
+execvp(3),
+execvpe(3),
+fexecve(3),
+popen(3),
+posix_spawn(3),
+posix_spawnp(3),
+system(3),
+and
+wordexp(3)
+functions.
+On Linux, a
+seccomp(2)
+filter is used to implement
+\fInoexec\fR.
+On Solaris 10 and higher,
+\fInoexec\fR
+uses Solaris privileges instead of the
+\fRLD_PRELOAD\fR
+environment variable.
+.sp
+To enable
+\fInoexec\fR
+for a command, use the
+\fRNOEXEC\fR
+tag as documented in the User Specification section above.
+Here is that example again:
+.nf
+.sp
+.RS 11n
+aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi
+.RE
+.fi
+.RS 11n
+.sp
+This allows user
+\fBaaron\fR
+to run
+\fI/usr/bin/more\fR
+and
+\fI/usr/bin/vi\fR
+with
+\fInoexec\fR
+enabled.
+This will prevent those two commands from
+executing other commands (such as a shell).
+If you are unsure whether or not your system is capable of supporting
+\fInoexec\fR
+you can always just try it out and check whether shell escapes work when
+\fInoexec\fR
+is enabled.
+.RE
+.PP
+Restricting shell escapes is not a panacea.
+Programs running as
+\fBroot\fR
+are still capable of many potentially hazardous operations (such
+as changing or overwriting files) that could lead to unintended
+privilege escalation.
+In the specific case of an editor, a safer approach is to give the
+user permission to run
+\fBsudoedit\fR
+(see below).
+.SS "Secure editing"
+The
+\fBsudoers\fR
+plugin includes
+\fBsudoedit\fR
+support which allows users to securely edit files with the editor
+of their choice.
+As
+\fBsudoedit\fR
+is a built-in command, it must be specified in the
+\fIsudoers\fR
+file without a leading path.
+However, it may take command line arguments just as a normal command does.
+Wildcards used in
+\fIsudoedit\fR
+command line arguments are expected to be path names, so a forward slash
+(\(oq/\(cq)
+will not be matched by a wildcard.
+.PP
+Unlike other
+\fBsudo\fR
+commands, the editor is run with the permissions of the invoking
+user and with the environment unmodified.
+More information may be found in the description of the
+\fB\-e\fR
+option in
+sudo(@mansectsu@).
+.PP
+For example, to allow user operator to edit the
+\(lqmessage of the day\(rq
+file on any machine:
+.nf
+.sp
+.RS 4n
+operator ALL = sudoedit /etc/motd
+.RE
+.fi
+.PP
+The operator user then runs
+\fBsudoedit\fR
+as follows:
+.nf
+.sp
+.RS 4n
+$ sudoedit /etc/motd
+.RE
+.fi
+.PP
+The editor will run as the operator user, not
+\fB@runas_default@\fR,
+on a temporary copy of
+\fI/etc/motd\fR.
+After the file has been edited,
+\fI/etc/motd\fR
+will be updated with the contents of the temporary copy.
+.PP
+Users should
+\fInever\fR
+be granted
+\fBsudoedit\fR
+permission to edit a file that resides in a directory the user
+has write access to, either directly or via a wildcard.
+If the user has write access to the directory it is possible to
+replace the legitimate file with a link to another file,
+allowing the editing of arbitrary files.
+To prevent this, starting with version 1.8.16, symbolic links will
+not be followed in writable directories and
+\fBsudoedit\fR
+will refuse to edit a file located in a writable directory
+unless the
+\fIsudoedit_checkdir\fR
+option has been disabled or the invoking user is
+\fBroot\fR.
+Additionally, in version 1.8.15 and higher,
+\fBsudoedit\fR
+will refuse to open a symbolic link unless either the
+\fIsudoedit_follow\fR
+option is enabled or the
+\fIsudoedit\fR
+command is prefixed with the
+\fRFOLLOW\fR
+tag in the
+\fIsudoers\fR
+file.
+.SS "Time stamp file checks"
+\fBsudoers\fR
+will check the ownership of its time stamp directory
+(\fI@rundir@/ts\fR
+by default)
+and ignore the directory's contents if it is not owned by
+\fBroot\fR
+or if it is writable by a user other than
+\fBroot\fR.
+Older versions of
+\fBsudo\fR
+stored time stamp files in
+\fI/tmp\fR;
+this is no longer recommended as it may be possible for a user
+to create the time stamp themselves on systems that allow
+unprivileged users to change the ownership of files they create.
+.PP
+While the time stamp directory
+\fIshould\fR
+be cleared at reboot time, not all systems contain a
+\fI/run\fR
+or
+\fI/var/run\fR
+directory.
+To avoid potential problems,
+\fBsudoers\fR
+will ignore time stamp files that date from before the machine booted
+on systems where the boot time is available.
+.PP
+Some systems with graphical desktop environments allow unprivileged
+users to change the system clock.
+Since
+\fBsudoers\fR
+relies on the system clock for time stamp validation, it may be
+possible on such systems for a user to run
+\fBsudo\fR
+for longer than
+\fItimestamp_timeout\fR
+by setting the clock back.
+To combat this,
+\fBsudoers\fR
+uses a monotonic clock (which never moves backwards) for its time stamps
+if the system supports it.
+.PP
+\fBsudoers\fR
+will not honor time stamps set far in the future.
+Time stamps with a date greater than current_time + 2 *
+\fRTIMEOUT\fR
+will be ignored and
+\fBsudoers\fR
+will log and complain.
+.PP
+If the
+\fItimestamp_type\fR
+option is set to
+\(lqtty\(rq,
+the time stamp record includes the device number of the terminal
+the user authenticated with.
+This provides per-terminal granularity but time stamp records may still
+outlive the user's session.
+.PP
+Unless the
+\fItimestamp_type\fR
+option is set to
+\(lqglobal\(rq,
+the time stamp record also includes the session ID of the process
+that last authenticated.
+This prevents processes in different terminal sessions from using
+the same time stamp record.
+On systems where a process's start time can be queried,
+the start time of the session leader
+is recorded in the time stamp record.
+If no terminal is present or the
+\fItimestamp_type\fR
+option is set to
+\(lqppid\(rq,
+the start time of the parent process is used instead.
+In most cases this will prevent a time stamp record from being re-used
+without the user entering a password when logging out and back in again.
+.SH "DEBUGGING"
+Versions 1.8.4 and higher of the
+\fBsudoers\fR
+plugin support a flexible debugging framework that can help track
+down what the plugin is doing internally if there is a problem.
+This can be configured in the
+sudo.conf(@mansectform@)
+file.
+.PP
+The
+\fBsudoers\fR
+plugin uses the same debug flag format as the
+\fBsudo\fR
+front-end:
+\fIsubsystem\fR@\fIpriority\fR.
+.PP
+The priorities used by
+\fBsudoers\fR,
+in order of decreasing severity,
+are:
+\fIcrit\fR, \fIerr\fR, \fIwarn\fR, \fInotice\fR, \fIdiag\fR, \fIinfo\fR, \fItrace\fR,
+and
+\fIdebug\fR.
+Each priority, when specified, also includes all priorities higher
+than it.
+For example, a priority of
+\fInotice\fR
+would include debug messages logged at
+\fInotice\fR
+and higher.
+.PP
+The following subsystems are used by the
+\fBsudoers\fR
+plugin:
+.TP 10n
+\fIalias\fR
+\fIUser_Alias\fR,
+\fIRunas_Alias\fR,
+\fIHost_Alias\fR
+and
+\fICmnd_Alias\fR
+processing
+.TP 10n
+\fIall\fR
+matches every subsystem
+.TP 10n
+\fIaudit\fR
+BSM and Linux audit code
+.TP 10n
+\fIauth\fR
+user authentication
+.TP 10n
+\fIdefaults\fR
+\fIsudoers\fR
+file
+\fIDefaults\fR
+settings
+.TP 10n
+\fIenv\fR
+environment handling
+.TP 10n
+\fIldap\fR
+LDAP-based sudoers
+.TP 10n
+\fIlogging\fR
+logging support
+.TP 10n
+\fImatch\fR
+matching of users, groups, hosts, and netgroups in the
+\fIsudoers\fR
+file
+.TP 10n
+\fInetif\fR
+network interface handling
+.TP 10n
+\fInss\fR
+network service switch handling in
+\fBsudoers\fR
+.TP 10n
+\fIparser\fR
+\fIsudoers\fR
+file parsing
+.TP 10n
+\fIperms\fR
+permission setting
+.TP 10n
+\fIplugin\fR
+The equivalent of
+\fImain\fR
+for the plugin.
+.TP 10n
+\fIpty\fR
+pseudo-terminal related code
+.TP 10n
+\fIrbtree\fR
+redblack tree internals
+.TP 10n
+\fIsssd\fR
+SSSD-based sudoers
+.TP 10n
+\fIutil\fR
+utility functions
+.PP
+For example:
+.nf
+.sp
+.RS 0n
+Debug @sudoers_plugin@ @log_dir@/sudoers_debug match@info,nss@info
+.RE
+.fi
+.PP
+For more information, see the
+sudo.conf(@mansectform@)
+manual.
+.SH "SEE ALSO"
+ssh(1),
+su(1),
+fnmatch(3),
+glob(3),
+mktemp(3),
+strftime(3),
+sudo.conf(@mansectform@),
+sudo_plugin(@mansectform@),
+sudoers.ldap(@mansectform@),
+sudoers_timestamp(@mansectform@),
+sudo(@mansectsu@),
+visudo(@mansectsu@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS.md file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "CAVEATS"
+The
+\fIsudoers\fR
+file should
+\fBalways\fR
+be edited by the
+\fBvisudo\fR
+utility which locks the file and checks for syntax errors.
+If
+\fIsudoers\fR
+contains syntax errors,
+\fBsudo\fR
+may refuse to run, which is a serious problem if
+\fBsudo\fR
+is your only method of obtaining superuser privileges.
+Recent versions of
+\fBsudoers\fR
+will attempt to recover after a syntax error by ignoring the rest of
+the line after encountering an error.
+Older versions of
+\fBsudo\fR
+will not run if
+\fIsudoers\fR
+contains a syntax error.
+.PP
+When using netgroups of machines (as opposed to users), if you
+store fully qualified host name in the netgroup (as is usually the
+case), you either need to have the machine's host name be fully qualified
+as returned by the
+\fIhostname\fR
+command or use the
+\fIfqdn\fR
+option in
+\fIsudoers\fR.
+.SH "BUGS"
+If you believe you have found a bug in
+\fBsudo\fR,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudoers.man.in.sed b/docs/sudoers.man.in.sed
new file mode 100644
index 0000000..eca83a3
--- /dev/null
+++ b/docs/sudoers.man.in.sed
@@ -0,0 +1,150 @@
+s/^\(.TH .*\)/.nr SL @SEMAN@\
+.nr BA @BAMAN@\
+.nr LC @LCMAN@\
+.nr PS @PSMAN@\
+\1/
+
+/^On$/N
+/^On\nBSD$/,/^.*\.$/ {
+ /^On\nBSD$/i\
+.if \\n(LC \\{\\
+ /\.$/a\
+.\\}
+}
+
+/^\.SS "SELinux_Spec"$/,/^\.SS/ {
+ /^\.SS / {
+ /^\.SS "SELinux_Spec"$/i\
+.if \\n(SL \\{\\
+ /^\.SS "SELinux_Spec"$/!i\
+.\\}
+ }
+}
+
+/^\.SS "Solaris_Priv_Spec"$/,/^\.SS/ {
+ /^\.SS / {
+ /^\.SS "Solaris_Priv_Spec"$/i\
+.if \\n(PS \\{\\
+ /^\.SS "Solaris_Priv_Spec"$/!i\
+.\\}
+ }
+}
+
+/^Option_Spec ::= / {
+ s/^.*$/.ie \\n(SL \\{\\\
+.ie \\n(PS Option_Spec ::= (SELinux_Spec | Solaris_Priv_Spec | Date_Spec | Timeout_Spec)\
+.el Option_Spec ::= (SELinux_Spec | Date_Spec | Timeout_Spec)\
+.\\}\
+.el \\{\\\
+.ie \\n(PS Option_Spec ::= (Solaris_Priv_Spec | Date_Spec | Timeout_Spec)\
+.el Option_Spec ::= (Date_Spec | Timeout_Spec)\
+.\\}/
+}
+
+/^SELinux_Spec ::=/ {
+ i\
+.if \\n(SL \\{\\
+ N
+ a\
+.\\}
+}
+
+/^Solaris_Priv_Spec ::=/ {
+ i\
+.if \\n(PS \\{\\
+ N
+ a\
+.\\}
+}
+
+/^SELinux roles.*types,/ {
+ i\
+.if \\n(SL \\{\\
+ a\
+.\\}
+}
+
+/^Solaris privileges sets,/ {
+ i\
+.if \\n(PS \\{\\
+ a\
+.\\}
+}
+
+/^\.TP 18n$/ {
+ N
+ /^\.TP 18n\nuse_loginclass$/,/^\.TP 18n/ {
+ /^\.TP 18n/ {
+ /^\.TP 18n\nuse_loginclass$/i\
+.if \\n(BA \\{\\
+ /^\.TP 18n\nuse_loginclass$/!i\
+.\\}
+ }
+ }
+ /^\.TP 18n\nlimitprivs$/,/^\.TP 18n/ {
+ /^\.TP 18n/ {
+ /^\.TP 18n\nlimitprivs$/i\
+.if \\n(PS \\{\\
+ /^\.TP 18n\nlimitprivs$/!i\
+.\\}
+ }
+ }
+ /^\.TP 18n\nprivs$/,/^\.TP 18n/ {
+ /^\.TP 18n/ {
+ /^\.TP 18n\nprivs$/i\
+.if \\n(PS \\{\\
+ /^\.TP 18n\nprivs$/!i\
+.\\}
+ }
+ }
+ /^\.TP 18n\nselinux$/,/^\.TP 18n/ {
+ /^\.TP 18n/ {
+ /^\.TP 18n\nselinux$/i\
+.if \\n(SL \\{\\
+ /^\.TP 18n\nselinux$/!i\
+.\\}
+ }
+ }
+ /^\.TP 18n\nrole$/,/^\.TP 18n/ {
+ /^\.TP 18n/ {
+ /^\.TP 18n\nrole$/i\
+.if \\n(SL \\{\\
+ /^\.TP 18n\nrole$/!i\
+.\\}
+ }
+ }
+ /^\.TP 18n\ntype$/,/^\.TP 18n/ {
+ /^\.TP 18n/ {
+ /^\.TP 18n\ntype$/i\
+.if \\n(SL \\{\\
+ /^\.TP 18n\ntype$/!i\
+.\\}
+ }
+ }
+}
+
+/^\\fRPRIVS\\fR,/ {
+ i\
+.if \\n(PS \\{\\
+ a\
+.\\}
+}
+/^\\fRLIMITPRIVS\\fR,/ {
+ i\
+.if \\n(PS \\{\\
+ a\
+.\\}
+}
+
+/^\\fRROLE\\fR,/ {
+ i\
+.if \\n(SL \\{\\
+ a\
+.\\}
+}
+/^\\fRTYPE\\fR,/ {
+ i\
+.if \\n(SL \\{\\
+ a\
+.\\}
+}
diff --git a/docs/sudoers.mdoc.in b/docs/sudoers.mdoc.in
new file mode 100644
index 0000000..8ec5c32
--- /dev/null
+++ b/docs/sudoers.mdoc.in
@@ -0,0 +1,7443 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 1994-1996, 1998-2005, 2007-2023
+.\" Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" Sponsored in part by the Defense Advanced Research Projects
+.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
+.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
+.\"
+.nr SL @SEMAN@
+.nr AA @AAMAN@
+.nr BA @BAMAN@
+.nr LC @LCMAN@
+.nr PS @PSMAN@
+.Dd December 19, 2023
+.Dt SUDOERS @mansectform@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudoers
+.Nd default sudo security policy plugin
+.Sh DESCRIPTION
+The
+.Nm
+policy plugin determines a user's
+.Nm sudo
+privileges.
+It is the default
+.Nm sudo
+policy plugin.
+The policy is driven by
+the
+.Pa @sysconfdir@/sudoers
+file or, optionally, in LDAP.
+The policy format is described in detail in the
+.Sx SUDOERS FILE FORMAT
+section.
+For information on storing
+.Nm
+policy information
+in LDAP, see
+.Xr sudoers.ldap @mansectform@ .
+.Ss Configuring sudo.conf for sudoers
+.Nm sudo
+consults the
+.Xr sudo.conf @mansectform@
+file to determine which plugins to load.
+If no
+.Xr sudo.conf @mansectform@
+file is present, or if it contains no
+.Em Plugin
+lines,
+.Nm
+will be used for auditing, policy decisions and I/O logging.
+To explicitly configure
+.Xr sudo.conf @mansectform@
+to use the
+.Nm
+plugin, the following configuration can be used.
+.Bd -literal -offset 4n
+Plugin sudoers_audit @sudoers_plugin@
+Plugin sudoers_policy @sudoers_plugin@
+Plugin sudoers_io @sudoers_plugin@
+.Ed
+.Pp
+Starting with
+.Nm sudo
+1.8.5, it is possible to specify optional arguments to the
+.Nm
+plugin in the
+.Xr sudo.conf @mansectform@
+file.
+Plugin arguments, if any, should be listed after the path to the plugin
+(i.e., after
+.Pa @sudoers_plugin@ ) .
+The arguments are only effective for the plugin that opens (and parses) the
+.Em sudoers
+file.
+.Pp
+For
+.Nm sudo
+version 1.9.1 and higher, this is the
+.Em sudoers_audit
+plugin.
+For older versions, it is the
+.Em sudoers_policy
+plugin.
+Multiple arguments may be specified, separated by white space.
+For example:
+.Bd -literal -offset 4n
+Plugin sudoers_audit @sudoers_plugin@ sudoers_mode=0400 error_recovery=false
+.Ed
+.Pp
+The following plugin arguments are supported:
+.Bl -tag -width 4n
+.It error_recovery=bool
+The
+.Em error_recovery
+argument can be used to control whether
+.Nm
+should attempt to recover from syntax errors in the
+.Em sudoers
+file.
+If set to
+.Em true
+(the default),
+.Nm
+will try to recover from a syntax error by discarding the portion
+of the line that contains the error until the end of the line.
+A value of
+.Em false
+will disable error recovery.
+Prior to version 1.9.3, no error recovery was performed.
+.It ignore_perms=bool
+The
+.Em ignore_perms
+argument can be used to disable security checks when loading the
+.Em sudoers
+file.
+If enabled, the
+.Em sudoers
+file will be loaded regardless of the owner or file mode.
+This argument is intended to be used for testing purposes and
+should not be enabled on production systems.
+.It ldap_conf=pathname
+The
+.Em ldap_conf
+argument can be used to override the default path to the
+.Pa ldap.conf
+file.
+.It ldap_secret=pathname
+The
+.Em ldap_secret
+argument can be used to override the default path to the
+.Pa ldap.secret
+file.
+.It sudoers_file=pathname
+The
+.Em sudoers_file
+argument can be used to override the default path to the
+.Em sudoers
+file.
+.It sudoers_uid=user-ID
+The
+.Em sudoers_uid
+argument can be used to override the default owner of the sudoers file.
+It should be specified as a numeric user-ID.
+.It sudoers_gid=group-ID
+The
+.Em sudoers_gid
+argument can be used to override the default group of the sudoers file.
+It must be specified as a numeric group-ID (not a group name).
+.It sudoers_mode=mode
+The
+.Em sudoers_mode
+argument can be used to override the default file mode for the sudoers file.
+It should be specified as an octal value.
+.El
+.Pp
+For more information on configuring
+.Xr sudo.conf @mansectform@ ,
+refer to its manual.
+.Ss User Authentication
+The
+.Nm
+security policy requires that most users authenticate
+themselves before they can use
+.Nm sudo .
+A password is not required
+if the invoking user is
+.Sy root ,
+if the target user is the same as the invoking user, or if the
+policy has disabled authentication for the user or command.
+Unlike
+.Xr su 1 ,
+when
+.Nm
+requires
+authentication, it validates the invoking user's credentials, not
+the target user's (or
+.Sy @runas_default@ Ns No 's)
+credentials.
+This can be changed via
+the
+.Em rootpw ,
+.Em targetpw
+and
+.Em runaspw
+flags, described later.
+.Pp
+If a user who is not listed in the policy tries to run a command
+via
+.Nm sudo ,
+mail is sent to the proper authorities.
+The address
+used for such mail is configurable via the
+.Em mailto
+Defaults entry
+(described later) and defaults to
+.Em @mailto@ .
+.Pp
+No mail will be sent if an unauthorized user tries to run
+.Nm sudo
+with the
+.Fl l
+or
+.Fl v
+option unless there is an authentication error and
+either the
+.Em mail_always
+or
+.Em mail_badpass
+flags are enabled.
+This allows users to
+determine for themselves whether or not they are allowed to use
+.Nm sudo .
+By default, all attempts to run
+.Nm sudo
+(successful or not)
+are logged, regardless of whether or not mail is sent.
+.Pp
+If
+.Nm sudo
+is run by
+.Sy root
+and the
+.Ev SUDO_USER
+environment variable
+is set, the
+.Nm
+policy will use this value to determine who
+the actual user is.
+This can be used by a user to log commands
+through sudo even when a
+.Sy root
+shell has been invoked.
+It also
+allows the
+.Fl e
+option to remain useful even when invoked via a
+sudo-run script or program.
+Note, however, that the
+.Em sudoers
+file lookup is still done for
+.Sy root ,
+not the user specified by
+.Ev SUDO_USER .
+.Pp
+.Nm
+uses per-user time stamp files for credential caching.
+Once a user has been authenticated, a record is written
+containing the user-ID that was used to authenticate, the
+terminal session ID, the start time of the session leader
+(or parent process) and a time stamp
+(using a monotonic clock if one is available).
+The user may then use
+.Nm sudo
+without a password for a short period of time (@timeout@ minutes
+unless overridden by the
+.Em timestamp_timeout
+option).
+By default,
+.Nm
+uses a separate record for each terminal, which means that
+a user's login sessions are authenticated separately.
+The
+.Em timestamp_type
+option can be used to select the type of time stamp record
+.Nm
+will use.
+.Ss Logging
+By default,
+.Nm
+logs both successful and unsuccessful attempts (as well
+as errors).
+The
+.Em log_allowed
+and
+.Em log_denied
+flags can be used to control this behavior.
+Messages can be logged to
+.Xr syslog 3 ,
+a log file, or both.
+The default is to log to
+.Xr syslog 3
+but this is configurable via the
+.Em syslog
+and
+.Em logfile
+settings.
+See
+.Sx "EVENT LOGGING"
+for a description of the log file format.
+.Pp
+.Nm
+is also capable of running a command in a pseudo-terminal and logging
+input and/or output.
+The standard input, standard output, and standard error can be logged
+even when not associated with a terminal.
+For more information about I/O logging, see the
+.Sx "I/O LOGGING"
+section.
+.Pp
+Starting with version 1.9, the
+.Em log_servers
+setting may be used to send event and I/O log data to a remote server running
+.Nm sudo_logsrvd
+or another service that implements the protocol described by
+.Xr sudo_logsrv.proto @mansectform@ .
+.Ss Command environment
+Since environment variables can influence program behavior,
+.Nm
+provides a means to restrict which variables from the user's
+environment are inherited by the command to be run.
+There are two
+distinct ways
+.Nm
+can deal with environment variables.
+.Pp
+By default, the
+.Em env_reset
+flag is enabled.
+This causes commands
+to be executed with a new, minimal environment.
+On AIX (and Linux
+systems without PAM), the environment is initialized with the
+contents of the
+.Pa /etc/environment
+file.
+.if \n(LC \{\
+On
+.Bx
+systems, if the
+.Em use_loginclass
+flag is enabled, the environment is initialized
+based on the
+.Em path
+and
+.Em setenv
+settings in
+.Pa /etc/login.conf .
+.\}
+The
+.Ev HOME ,
+.Ev MAIL ,
+.Ev SHELL ,
+.Ev LOGNAME
+and
+.Ev USER
+environment variables are initialized based on the target user
+and the
+.Ev SUDO_*
+variables are set based on the invoking user.
+Additional variables, such as
+.Ev DISPLAY ,
+.Ev PATH
+and
+.Ev TERM ,
+are preserved from the invoking user's environment if permitted by the
+.Em env_check ,
+or
+.Em env_keep
+options.
+A few environment variables are treated specially.
+If the
+.Ev PATH
+and
+.Ev TERM
+variables are not preserved from the user's environment, they will be set
+to default values.
+The
+.Ev LOGNAME
+and
+.Ev USER
+are handled as a single entity.
+If one of them is preserved (or removed) from the user's environment,
+the other will be as well.
+If
+.Ev LOGNAME
+and
+.Ev USER
+are to be preserved but only one of them is present in the user's environment,
+the other will be set to the same value.
+This avoids an inconsistent environment where one of the variables
+describing the user name is set to the invoking user and one is
+set to the target user.
+Environment variables with a value beginning with
+.Ql ()
+are removed unless both the name and value parts are matched by
+.Em env_keep
+or
+.Em env_check ,
+as they may be interpreted as functions by the
+.Sy bash
+shell.
+Prior to version 1.8.11, such variables were always removed.
+.Pp
+If, however, the
+.Em env_reset
+flag is disabled, any variables not
+explicitly denied by the
+.Em env_check
+and
+.Em env_delete
+options are allowed and their values are
+inherited from the invoking process.
+Prior to version 1.8.21, environment variables with a value beginning with
+.Ql ()
+were always removed.
+Beginning with version 1.8.21, a pattern in
+.Em env_delete
+is used to match
+.Sy bash
+shell functions instead.
+Since it is not possible
+to block all potentially dangerous environment variables, use
+of the default
+.Em env_reset
+behavior is encouraged.
+.Pp
+Environment variables specified by
+.Em env_check ,
+.Em env_delete ,
+or
+.Em env_keep
+may include one or more
+.Ql *
+characters which will match zero or more characters.
+No other wildcard characters are supported.
+.Pp
+By default, environment variables are matched by name.
+However, if the pattern includes an equal sign
+.Pq Ql =\& ,
+both the variables name and value must match.
+For example, a
+.Sy bash
+shell function could be matched as follows:
+.Bd -literal -offset 4n
+env_keep += "BASH_FUNC_my_func%%=()*"
+.Ed
+.Pp
+Without the
+.Ql =()*
+suffix, this would not match, as
+.Sy bash
+shell functions are not preserved by default.
+.Pp
+The complete list of environment variables that are preserved or removed,
+as modified by global Defaults parameters in
+.Em sudoers ,
+is displayed when
+.Nm sudo
+is run by
+.Sy root
+with the
+.Fl V
+option.
+The list of environment variables to remove
+varies based on the operating system
+.Nm sudo
+is running on.
+.Pp
+Other settings may influence the command environment:
+.Bl -bullet -width 1n
+.It
+.Nm
+options such as
+.Em always_set_home ,
+.Em secure_path ,
+.Em set_logname ,
+.Em set_home ,
+and
+.Em setenv .
+.It
+Command tags, such as
+.Dv SETENV
+and
+.Dv NOSETENV .
+Note that
+.Dv SETENV
+is implied if the command matched is
+.Sy ALL .
+.It
+.Nm sudo
+options, such as
+.Fl E
+and
+.Fl i .
+.El
+.Pp
+On systems that support PAM where the
+.Sy pam_env
+module is enabled for
+.Nm sudo ,
+variables in the PAM environment may be merged in to the environment.
+If a variable in the PAM environment is already present in the
+user's environment, the value will only be overridden if the variable
+was not preserved by
+.Nm .
+When
+.Em env_reset
+is enabled, variables preserved from the invoking user's environment
+by the
+.Em env_keep
+list take precedence over those in the PAM environment.
+When
+.Em env_reset
+is disabled, variables present the invoking user's environment
+take precedence over those in the PAM environment unless they
+match a pattern in the
+.Em env_delete
+list.
+.Pp
+The dynamic linker on most operating systems will remove variables
+that can control dynamic linking from the environment of set-user-ID
+executables, including
+.Nm sudo .
+Depending on the operating
+system this may include
+.Ev _RLD* ,
+.Ev DYLD_* ,
+.Ev LD_* ,
+.Ev LDR_* ,
+.Ev LIBPATH ,
+.Ev SHLIB_PATH ,
+and others.
+These type of variables are
+removed from the environment before
+.Nm sudo
+even begins execution
+and, as such, it is not possible for
+.Nm sudo
+to preserve them.
+.Pp
+As a special case, if the
+.Fl i
+option (initial login) is
+specified,
+.Nm
+will initialize the environment regardless
+of the value of
+.Em env_reset .
+The
+.Ev DISPLAY ,
+.Ev PATH
+and
+.Ev TERM
+variables remain unchanged;
+.Ev HOME ,
+.Ev MAIL ,
+.Ev SHELL ,
+.Ev USER ,
+and
+.Ev LOGNAME
+are set based on the target user.
+On AIX (and Linux
+systems without PAM), the contents of
+.Pa /etc/environment
+are also
+included.
+.if \n(LC \{\
+On
+.Bx
+systems, if the
+.Em use_loginclass
+flag is
+enabled, the
+.Em path
+and
+.Em setenv
+variables in
+.Pa /etc/login.conf
+are also applied.
+.\}
+All other environment variables are removed unless permitted by
+.Em env_keep
+or
+.Em env_check ,
+described above.
+.Pp
+Finally, the
+.Em restricted_env_file
+and
+.Em env_file
+files are applied, if present.
+The variables in
+.Em restricted_env_file
+are applied first and are subject to the same restrictions as the
+invoking user's environment, as detailed above.
+The variables in
+.Em env_file
+are applied last and are not subject to these restrictions.
+In both cases, variables present in the files will only be set to
+their specified values if they would not conflict with an existing
+environment variable.
+.Sh SUDOERS FILE FORMAT
+The
+.Em sudoers
+file is composed of two types of entries: aliases
+(basically variables) and user specifications (which specify who
+may run what).
+.Pp
+When multiple entries match for a user, they are applied in order.
+Where there are multiple matches, the last match is used (which is
+not necessarily the most specific match).
+.Pp
+The
+.Em sudoers
+file grammar will be described below in Extended Backus-Naur
+Form (EBNF).
+Don't despair if you are unfamiliar with EBNF; it is fairly simple,
+and the definitions below are annotated.
+.Ss Resource limits
+By default,
+.Nm
+uses the operating system's native method of setting resource limits
+for the target user.
+On Linux systems, resource limits are usually set by the
+.Pa pam_limits.so
+PAM module.
+On some BSD systems, the
+.Pa /etc/login.conf
+file specifies resource limits for the user.
+On AIX systems, resource limits are configured in the
+.Pa /etc/security/limits
+file.
+If there is no system mechanism to set per-user resource limits,
+the command will run with the same limits as the invoking user.
+The one exception to this is the core dump file size, which is set by
+.Nm
+to 0 by default.
+Disabling core dumps by default makes it possible to avoid potential
+security problems where the core file is treated as trusted input.
+.Pp
+Resource limits may also be set in the
+.Em sudoers
+file itself, in which case they override those set by the system.
+See the
+.Em rlimit_as,
+.Em rlimit_core,
+.Em rlimit_cpu,
+.Em rlimit_data,
+.Em rlimit_fsize,
+.Em rlimit_locks,
+.Em rlimit_memlock,
+.Em rlimit_nofile,
+.Em rlimit_nproc,
+.Em rlimit_rss,
+.Em rlimit_stack
+options described below.
+Resource limits in
+.Nm
+may be specified in one of the following formats:
+.Bl -tag -width 6n
+.It Dq value
+Both the soft and hard resource limits are set to the same value.
+The special value
+.Dq infinity
+can be used to indicate that the value is unlimited.
+.It Dq soft,hard
+Two comma-separated values.
+The soft limit is set to the first value and the hard limit is set
+to the second.
+Both values must either be enclosed in a set of double quotes,
+or the comma must be escaped with a backslash
+.Pq Ql \e .
+The special value
+.Dq infinity
+may be used in place of either value.
+.It Dq default
+The default resource limit for the user will be used.
+This may be a user-specific value (see above) or the value of the
+resource limit when
+.Nm sudo
+was invoked for systems that don't support per-user limits.
+.It Dq user
+The invoking user's resource limits will be preserved when running
+the command.
+.El
+.Pp
+For example, to restore the historic core dump file size behavior,
+a line like the following may be used.
+.sp
+.Dl Defaults rlimit_core=default
+.Pp
+Resource limits in
+.Nm
+are only supported by version 1.8.7 or higher.
+.Ss Quick guide to EBNF
+EBNF is a concise and exact way of describing the grammar of a language.
+Each EBNF definition is made up of
+.Em production rules .
+For example:
+.Bd -literal -offset 4n
+symbol ::= definition | alternate1 | alternate2 ...
+.Ed
+.Pp
+Each
+.Em production rule
+references others and thus makes up a
+grammar for the language.
+EBNF also contains the following
+operators, which many readers will recognize from regular
+expressions.
+Do not, however, confuse them with
+.Dq wildcard
+characters, which have different meanings.
+.Bl -tag -width 4n
+.It \&?
+Means that the preceding symbol (or group of symbols) is optional.
+That is, it may appear once or not at all.
+.It *
+Means that the preceding symbol (or group of symbols) may appear
+zero or more times.
+.It +
+Means that the preceding symbol (or group of symbols) may appear
+one or more times.
+.El
+.Pp
+Parentheses may be used to group symbols together.
+For clarity,
+we will use single quotes
+.Pq ''
+to designate what is a verbatim character string (as opposed to a symbol name).
+.Ss Aliases
+There are four kinds of aliases:
+.Em User_Alias ,
+.Em Runas_Alias ,
+.Em Host_Alias
+and
+.Em Cmnd_Alias .
+Beginning with
+.Nm sudo
+1.9.0,
+.Em Cmd_Alias
+may be used in place of
+.Em Cmnd_Alias
+if desired.
+.Bd -literal
+Alias ::= 'User_Alias' User_Alias_Spec (':' User_Alias_Spec)* |
+ 'Runas_Alias' Runas_Alias_Spec (':' Runas_Alias_Spec)* |
+ 'Host_Alias' Host_Alias_Spec (':' Host_Alias_Spec)* |
+ 'Cmnd_Alias' Cmnd_Alias_Spec (':' Cmnd_Alias_Spec)* |
+ 'Cmd_Alias' Cmnd_Alias_Spec (':' Cmnd_Alias_Spec)*
+
+User_Alias ::= NAME
+
+User_Alias_Spec ::= User_Alias '=' User_List
+
+Runas_Alias ::= NAME
+
+Runas_Alias_Spec ::= Runas_Alias '=' Runas_List
+
+Host_Alias ::= NAME
+
+Host_Alias_Spec ::= Host_Alias '=' Host_List
+
+Cmnd_Alias ::= NAME
+
+Cmnd_Alias_Spec ::= Cmnd_Alias '=' Cmnd_List
+
+NAME ::= [A-Z]([A-Z][0-9]_)*
+.Ed
+.Pp
+Each
+.Em alias
+definition is of the form
+.Bd -literal
+Alias_Type NAME = item1, item2, ...
+.Ed
+.Pp
+where
+.Em Alias_Type
+is one of
+.Em User_Alias ,
+.Em Runas_Alias ,
+.Em Host_Alias ,
+or
+.Em Cmnd_Alias .
+A
+.Dv NAME
+is a string of uppercase letters, numbers,
+and underscore characters
+.Pq Ql _ .
+A
+.Dv NAME
+.Sy must
+start with an
+uppercase letter.
+It is possible to put several alias definitions
+of the same type on a single line, joined by a colon
+.Pq Ql :\& .
+For example:
+.Bd -literal
+Alias_Type NAME = item1, item2, item3 : NAME = item4, item5
+.Ed
+.Pp
+It is a syntax error to redefine an existing
+.Em alias .
+It is possible to use the same name for
+.Em aliases
+of different types, but this is not recommended.
+.Pp
+The definitions of what constitutes a valid
+.Em alias
+member follow.
+.Bd -literal
+User_List ::= User |
+ User ',' User_List
+
+User ::= '!'* user name |
+ '!'* #user-ID |
+ '!'* %group |
+ '!'* %#group-ID |
+ '!'* +netgroup |
+ '!'* %:nonunix_group |
+ '!'* %:#nonunix_gid |
+ '!'* User_Alias
+.Ed
+.Pp
+A
+.Em User_List
+is made up of one or more user names, user-IDs
+(prefixed with
+.Ql # ) ,
+system group names and IDs (prefixed with
+.Ql %
+and
+.Ql %#
+respectively), netgroups (prefixed with
+.Ql + ) ,
+non-Unix group names and IDs (prefixed with
+.Ql %:
+and
+.Ql %:#
+respectively), and
+.Em User_Alias Ns es.
+Each list item may be prefixed with zero or more
+.Ql \&!
+operators.
+An odd number of
+.Ql \&!
+operators negate the value of
+the item; an even number just cancel each other out.
+User netgroups are matched using the user and domain members only;
+the host member is not used when matching.
+.Pp
+A
+.Em user name ,
+.Em user-ID ,
+.Em group ,
+.Em group-ID ,
+.Em netgroup ,
+.Em nonunix_group
+or
+.Em nonunix_gid
+may be enclosed in double quotes to avoid the
+need for escaping special characters.
+Alternately, special characters
+may be specified in escaped hex mode, e.g., \ex20 for space.
+When
+using double quotes, any prefix characters must be included inside
+the quotes.
+.Pp
+The actual
+.Em nonunix_group
+and
+.Em nonunix_gid
+syntax depends on
+the underlying group provider plugin.
+For instance, the QAS AD plugin supports the following formats:
+.Bl -bullet -width 1n
+.It
+Group in the same domain: "%:Group Name"
+.It
+Group in any domain: "%:Group Name@FULLY.QUALIFIED.DOMAIN"
+.It
+Group SID: "%:S-1-2-34-5678901234-5678901234-5678901234-567"
+.El
+.Pp
+See
+.Sx "GROUP PROVIDER PLUGINS"
+for more information.
+.Pp
+Quotes around group names are optional.
+Unquoted strings must use a backslash
+.Pq Ql \e
+to escape spaces and special characters.
+See
+.Sx Other special characters and reserved words
+for a list of
+characters that need to be escaped.
+.Bd -literal
+Runas_List ::= Runas_Member |
+ Runas_Member ',' Runas_List
+
+Runas_Member ::= '!'* user name |
+ '!'* #user-ID |
+ '!'* %group |
+ '!'* %#group-ID |
+ '!'* %:nonunix_group |
+ '!'* %:#nonunix_gid |
+ '!'* +netgroup |
+ '!'* Runas_Alias |
+ '!'* ALL
+.Ed
+.Pp
+A
+.Em Runas_List
+is similar to a
+.Em User_List
+except that instead
+of
+.Em User_Alias Ns es
+it can contain
+.Em Runas_Alias Ns es .
+User names and groups are matched as strings.
+In other words, two users (groups) with the same user (group) ID
+are considered to be distinct.
+If you wish to match all user names with the same user-ID (e.g.,
+.Sy root
+and
+.Sy toor ) ,
+you can use a user-ID instead of a name (#0 in the example given).
+The user-ID or group-ID specified in a
+.Em Runas_Member
+need not be listed in the password or group database.
+.Bd -literal
+Host_List ::= Host |
+ Host ',' Host_List
+
+Host ::= '!'* host name |
+ '!'* ip_addr |
+ '!'* network(/netmask)? |
+ '!'* +netgroup |
+ '!'* Host_Alias |
+ '!'* ALL
+.Ed
+.Pp
+A
+.Em Host_List
+is made up of one or more host names, IP addresses,
+network numbers, netgroups (prefixed with
+.Ql + ) ,
+and other aliases.
+Again, the value of an item may be negated with the
+.Ql \&!
+operator.
+Host netgroups are matched using the host (both qualified and unqualified)
+and domain members only; the user member is not used when matching.
+If you specify a network number without a netmask,
+.Nm sudo
+will query each of the local host's network interfaces and,
+if the network number corresponds to one of the hosts's network
+interfaces, will use the netmask of that interface.
+The netmask may be specified either in standard IP address notation
+(e.g., 255.255.255.0 or ffff:ffff:ffff:ffff::),
+or CIDR notation (number of bits, e.g., 24 or 64).
+A host name may include shell-style wildcards (see the
+.Sx Wildcards
+section below),
+but unless the
+.Em hostname
+command on your machine returns the fully
+qualified host name, you'll need to use the
+.Em fqdn
+flag for wildcards to be useful.
+.Nm sudo
+only inspects actual network interfaces; this means that IP address
+127.0.0.1 (localhost) will never match.
+Also, the host name
+.Dq localhost
+will only match if that is the actual host name, which is usually
+only the case for non-networked systems.
+.Bd -literal
+digest ::= [A-Fa-f0-9]+ |
+ [A-Za-z0-9\e+/=]+
+
+Digest_Spec ::= "sha224" ':' digest |
+ "sha256" ':' digest |
+ "sha384" ':' digest |
+ "sha512" ':' digest
+
+Digest_List ::= Digest_Spec |
+ Digest_Spec ',' Digest_List
+
+Cmnd_List ::= Cmnd |
+ Cmnd ',' Cmnd_List
+
+command name ::= regex |
+ file name
+
+command ::= command name |
+ command name args |
+ command name regex |
+ command name '""' |
+ ALL
+
+Edit_Spec ::= "sudoedit" file name+ |
+ "sudoedit" regex |
+ "sudoedit"
+
+List_Spec ::= "list"
+
+Cmnd ::= Digest_List? '!'* command |
+ '!'* directory |
+ '!'* Edit_Spec |
+ '!'* List_Spec |
+ '!'* Cmnd_Alias
+.Ed
+.Pp
+A
+.Em Cmnd_List
+is a list of one or more commands, directories, or aliases.
+A command is a fully qualified file name, which may include
+shell-style wildcards (see the
+.Sx Wildcards
+section below),
+or a regular expression that starts with
+.Ql ^
+and ends with
+.Ql $
+(see the
+.Sx Regular expressions
+section below).
+A directory is a
+fully qualified path name ending in a
+.Ql / .
+When you specify a directory in a
+.Em Cmnd_List ,
+the user will be able to run any file within that directory
+(but not in any sub-directories therein).
+If no command line arguments are specified, the user may run the
+command with any arguments they choose.
+Command line arguments can include wildcards or be a regular
+expression that starts with
+.Ql ^
+and ends with
+.Ql $ .
+If the command line arguments consist of
+.Ql \&"" ,
+the command may only be run with
+.Em no
+arguments.
+.Pp
+If a
+.Em Cmnd
+has associated command line arguments, the arguments
+in the
+.Em Cmnd
+must match those given by the user on the command line.
+If the arguments in a
+.Em Cmnd
+begin with the
+.Ql ^
+character, they will be interpreted as a regular expression
+and matched accordingly.
+Otherwise, shell-style wildcards are used when matching.
+Unless a regular expression is specified, the following characters must
+be escaped with a
+.Ql \e
+if they are used in command arguments:
+.Ql ,\& ,
+.Ql :\& ,
+.Ql =\& ,
+.Ql \e .
+To prevent arguments in a
+.Em Cmnd
+that begin with a
+.Ql ^
+character from being interpreted as a regular expression, the
+.Ql ^
+must be escaped with a
+.Ql \e .
+.Pp
+There are two commands built into
+.Nm sudo
+itself:
+.Dq list
+and
+.Dq sudoedit .
+Unlike other commands, these two must be specified in the
+.Em sudoers
+file
+.Em without
+a leading path.
+.Pp
+The
+.Dq list
+built-in can be used to permit a user to list another user's privileges with
+.Nm sudo Ns 's
+.Fl U
+option.
+For example,
+.Dq sudo -l -U otheruser .
+A user with the
+.Dq list
+privilege is able to list another user's privileges even if they
+don't have permission to run commands as that user.
+By default, only root or a user with the ability to run any command as
+either root or the specified
+.Ar user
+on the current host may use the
+.Fl U
+option.
+No command line arguments may be specified with the
+.Dq list
+built-in.
+.Pp
+The
+.Dq sudoedit
+built-in is used to permit a user to run
+.Nm sudo
+with the
+.Fl e
+option (or as
+.Nm sudoedit ) .
+It may take command line arguments just as a normal command does.
+Unlike other commands,
+.Dq sudoedit
+is built into
+.Nm sudo
+itself and must be specified in the
+.Em sudoers
+file
+.Em without
+a leading path.
+If a leading path is present, for example
+.Pa /usr/bin/sudoedit ,
+the path name will be silently converted to
+.Dq sudoedit .
+A fully-qualified path for
+.Nm sudoedit
+is treated as an error by
+.Nm visudo .
+.Pp
+A
+.Em command
+may be preceded by a
+.Em Digest_List ,
+a comma-separated list of one or more
+.Em Digest_Spec
+entries.
+If a
+.Em Digest_List
+is present, the command will only match successfully if it can be verified
+using one of the SHA-2 digests in the list.
+Starting with version 1.9.0, the
+.Sy ALL
+reserved word can be used in conjunction with a
+.Em Digest_List .
+The following digest formats are supported: sha224, sha256, sha384, and sha512.
+The string may be specified in either hex or base64 format
+(base64 is more compact).
+There are several utilities capable of generating SHA-2 digests in hex
+format such as openssl, shasum, sha224sum, sha256sum, sha384sum, sha512sum.
+.Pp
+For example, using openssl:
+.Bd -literal
+$ openssl dgst -sha224 /bin/ls
+SHA224(/bin/ls)= 118187da8364d490b4a7debbf483004e8f3e053ec954309de2c41a25
+.Ed
+.Pp
+It is also possible to use openssl to generate base64 output:
+.Bd -literal
+$ openssl dgst -binary -sha224 /bin/ls | openssl base64
+EYGH2oNk1JC0p9679IMATo8+BT7JVDCd4sQaJQ==
+.Ed
+.Pp
+Warning, if the user has write access to the command itself (directly or via a
+.Nm sudo
+command), it may be possible for the user to replace the command after the
+digest check has been performed but before the command is executed.
+A similar race condition exists on systems that lack the
+.Xr fexecve 2
+system call when the directory in which the command is located
+is writable by the user.
+See the description of the
+.Em fdexec
+setting for more information on how
+.Nm sudo
+executes commands that have an associated digest.
+.Pp
+Command digests are only supported by version 1.8.7 or higher.
+.Ss Defaults
+Certain configuration options may be changed from their default
+values at run-time via one or more
+.Em Default_Entry
+lines.
+These may affect all users on any host
+.Pq Sq Defaults ,
+all users on a specific host
+.Pq Sq Defaults@host ,
+a specific user
+.Pq Sq Defaults:user ,
+a specific command
+.Pq Sq Defaults!cmnd ,
+or commands being run as a specific user
+.Pq Sq Defaults>runasuser .
+.Pp
+White space is not permitted between
+.Sq Defaults
+and the
+.Ql @ ,
+.Ql \&: ,
+.Ql \&! ,
+or
+.Ql >
+characters.
+While a comma-separated list may be used in place of a single value after the
+.Ql @ ,
+.Ql \&: ,
+.Ql \&! ,
+or
+.Ql >
+character, using an alias instead of a list is often improve readability.
+Per-command entries may not include command line arguments.
+If you need to specify arguments, define a
+.Em Cmnd_Alias
+and reference that instead.
+.Bd -literal
+Default_Type ::= 'Defaults' |
+ 'Defaults@' Host_List |
+ 'Defaults:' User_List |
+ 'Defaults!' Cmnd_List |
+ 'Defaults>' Runas_List
+
+Default_Entry ::= Default_Type Parameter_List
+
+Parameter_List ::= Parameter |
+ Parameter ',' Parameter_List
+
+Parameter ::= Parameter '=' Value |
+ Parameter '+=' Value |
+ Parameter '-=' Value |
+ '!'* Parameter
+.Ed
+.Pp
+Parameters may be
+.Sy flags ,
+.Sy integer
+values,
+.Sy strings ,
+or
+.Sy lists .
+Flags are implicitly boolean and can be turned off via the
+.Ql \&!
+operator.
+Some integer, string and list parameters may also be
+used in a boolean context to disable them.
+Values may be enclosed
+in double quotes
+.Pq \&""
+when they contain multiple words.
+Special characters may be escaped with a backslash
+.Pq Ql \e .
+.Pp
+To include a literal backslash character in a command line argument
+you must escape the backslash twice.
+For example, to match
+.Ql \en
+as part of a command line argument, you must use
+.Ql \e\e\e\en
+in the
+.Em sudoers
+file.
+This is due to there being two levels of escaping, one in the
+.Em sudoers
+parser itself and another when command line arguments are matched by the
+.Xr fnmatch 3
+or
+.Xr regexec 3
+function.
+.Pp
+Lists have two additional assignment operators,
+.Ql +=
+and
+.Ql -= .
+These operators are used to add to and delete from a list respectively.
+It is not an error to use the
+.Ql -=
+operator to remove an element
+that does not exist in a list.
+.Pp
+Defaults entries are parsed in the following order: global, host,
+user, and runas Defaults first, then command defaults.
+If there are multiple Defaults settings of the same type, the last
+matching setting is used.
+The following Defaults settings are parsed before all others since
+they may affect subsequent entries:
+.Em fqdn ,
+.Em group_plugin ,
+.Em runas_default ,
+.Em sudoers_locale .
+.Pp
+See
+.Sx SUDOERS OPTIONS
+for a list of supported Defaults parameters.
+.Ss User specification
+.Bd -literal
+User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \e
+ (':' Host_List '=' Cmnd_Spec_List)*
+
+Cmnd_Spec_List ::= Cmnd_Spec |
+ Cmnd_Spec ',' Cmnd_Spec_List
+
+Cmnd_Spec ::= Runas_Spec? Option_Spec* (Tag_Spec ':')* Cmnd
+
+Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')'
+
+.ie \n(SL \{\
+.ie \n(PS Option_Spec ::= (SELinux_Spec | Solaris_Priv_Spec | Date_Spec | Timeout_Spec | Chdir_Spec | Chroot_Spec)
+.el Option_Spec ::= (SELinux_Spec | Date_Spec | Timeout_Spec | Chdir_Spec | Chroot_Spec)
+.\}
+.el \{\
+.ie \n(AA \{\
+.ie \n(PS Option_Spec ::= (AppArmor_Spec | Solaris_Priv_Spec | Date_Spec | Timeout_Spec | Chdir_Spec | Chroot_Spec)
+.el Option_Spec ::= (AppArmor_Spec | Date_Spec | Timeout_Spec | Chdir_Spec | Chroot_Spec)
+.\}
+.el \{\
+.ie \n(PS Option_Spec ::= (Solaris_Priv_Spec | Date_Spec | Timeout_Spec | Chdir_Spec | Chroot_Spec)
+.el Option_Spec ::= (Date_Spec | Timeout_Spec | Chdir_Spec | Chroot_Spec)
+.\}
+.\}
+
+.if \n(SL \{\
+SELinux_Spec ::= ('ROLE=role' | 'TYPE=type')
+
+.\}
+.if \n(AA \{\
+AppArmor_Spec ::= 'APPARMOR_PROFILE=profile'
+
+.\}
+.if \n(PS \{\
+Solaris_Priv_Spec ::= ('PRIVS=privset' | 'LIMITPRIVS=privset')
+
+.\}
+Date_Spec ::= ('NOTBEFORE=timestamp' | 'NOTAFTER=timestamp')
+
+Timeout_Spec ::= 'TIMEOUT=timeout'
+
+Chdir_Spec ::= 'CWD=directory'
+
+Chroot_Spec ::= 'CHROOT=directory'
+
+Tag_Spec ::= ('EXEC' | 'NOEXEC' | 'FOLLOW' | 'NOFOLLOW' |
+ 'LOG_INPUT' | 'NOLOG_INPUT' | 'LOG_OUTPUT' |
+ 'NOLOG_OUTPUT' | 'MAIL' | 'NOMAIL' | 'INTERCEPT' |
+ 'NOINTERCEPT' | 'PASSWD' | 'NOPASSWD' | 'SETENV' |
+ 'NOSETENV')
+.Ed
+.Pp
+A
+.Sy user specification
+determines which commands a user may run
+(and as what user) on specified hosts.
+By default, commands are run as
+.Sy @runas_default@
+(unless
+.Em runas_default
+has been set to a different value)
+but this can also be changed on a per-command basis.
+.Pp
+The basic structure of a user specification is
+.Dq who where = (as_whom) what .
+Let's break that down into its constituent parts:
+.Ss Runas_Spec
+A
+.Em Runas_Spec
+determines the user and/or the group that a command
+may be run as.
+A fully-specified
+.Em Runas_Spec
+consists of two
+.Em Runas_List Ns s
+(as defined above) separated by a colon
+.Pq Ql \&:
+and enclosed in a set of parentheses.
+The first
+.Em Runas_List
+indicates which users the command may be run as via the
+.Fl u
+option.
+The second defines a list of groups that may be specified via the
+.Fl g
+option (in addition to any of the target user's groups).
+If both
+.Em Runas_List Ns s
+are specified, the command may be run with any combination of users
+and groups listed in their respective
+.Em Runas_List Ns s.
+If only the first is specified, the command may be run as any user
+in the list and, optionally, with any group the target user belongs to.
+If the first
+.Em Runas_List
+is empty but the
+second is specified, the command may be run as the invoking user
+with the group set to any listed in the
+.Em Runas_List .
+If both
+.Em Runas_List Ns s
+are empty, the command may only be run as the invoking user and the
+group, if specified, must be one that the invoking user is a member of.
+If no
+.Em Runas_Spec
+is specified, the command may only be run as the
+.Em runas_default
+user
+.Sy ( @runas_default@
+by default) and the group,
+if specified, must be one that the
+.Em runas_default
+user is a member of.
+.Pp
+A
+.Em Runas_Spec
+sets the default for the commands that follow it.
+What this means is that for the entry:
+.Bd -literal
+dgb boulder = (operator) /bin/ls, /bin/kill, /usr/bin/lprm
+.Ed
+.Pp
+The user
+.Sy dgb
+may run
+.Pa /bin/ls ,
+.Pa /bin/kill ,
+and
+.Pa /usr/bin/lprm
+on the host
+.No boulder Ns \(em Ns but
+only as
+.Sy operator .
+For example:
+.Bd -literal
+$ sudo -u operator /bin/ls
+.Ed
+.Pp
+It is also possible to override a
+.Em Runas_Spec
+later on in an entry.
+If we modify the entry like so:
+.Bd -literal
+dgb boulder = (operator) /bin/ls, (root) /bin/kill, /usr/bin/lprm
+.Ed
+.Pp
+Then user
+.Sy dgb
+is now allowed to run
+.Pa /bin/ls
+as
+.Sy operator ,
+but
+.Pa /bin/kill
+and
+.Pa /usr/bin/lprm
+as
+.Sy root .
+.Pp
+We can extend this to allow
+.Sy dgb
+to run
+.Pa /bin/ls
+with either
+the user or group set to
+.Sy operator :
+.Bd -literal
+dgb boulder = (operator : operator) /bin/ls, (root) /bin/kill,\e
+ /usr/bin/lprm
+.Ed
+.Pp
+While the group portion of the
+.Em Runas_Spec
+permits the
+user to run as command with that group, it does not force the user
+to do so.
+If no group is specified on the command line, the command
+will run with the group listed in the target user's password database
+entry.
+The following would all be permitted by the sudoers entry above:
+.Bd -literal
+$ sudo -u operator /bin/ls
+$ sudo -u operator -g operator /bin/ls
+$ sudo -g operator /bin/ls
+.Ed
+.Pp
+In the following example, user
+.Sy tcm
+may run commands that access
+a modem device file with the dialer group.
+.Bd -literal
+tcm boulder = (:dialer) /usr/bin/tip, /usr/bin/cu,\e
+ /usr/local/bin/minicom
+.Ed
+.Pp
+In this example only the group will be set, the command still runs as user
+.Sy tcm .
+For example:
+.Bd -literal
+$ sudo -g dialer /usr/bin/cu
+.Ed
+.Pp
+Multiple users and groups may be present in a
+.Em Runas_Spec ,
+in which case the user may select any combination of users and groups via the
+.Fl u
+and
+.Fl g
+options.
+In this example:
+.Bd -literal
+alan ALL = (root, bin : operator, system) ALL
+.Ed
+.Pp
+user
+.Sy alan
+may run any command as either user
+.Sy root
+or
+.Sy bin ,
+optionally setting the group to operator or system.
+.Ss Option_Spec
+A
+.Em Cmnd
+may have zero or more options associated with it.
+Options may consist of
+.if \n(SL \{\
+SELinux roles and/or types,
+.\}
+.if \n(AA \{\
+AppArmor profiles,
+.\}
+.if \n(PS \{\
+Solaris privileges sets,
+.\}
+start and/or end dates and command timeouts.
+Once an option is set for a
+.Em Cmnd ,
+subsequent
+.Em Cmnd Ns s
+in the
+.Em Cmnd_Spec_List ,
+inherit that option unless it is overridden by another option.
+Option names are reserved words in
+.Em sudoers .
+This means that none of the valid option names (see below) can be used
+when declaring an alias.
+.if \n(SL \{\
+.Ss SELinux_Spec
+On systems with SELinux support,
+.Em sudoers
+file entries may optionally have an SELinux role and/or type associated
+with a command.
+This can be used to implement a form of role-based access control (RBAC).
+If a role or
+type is specified with the command it will override any default values
+specified in
+.Em sudoers .
+A role or type specified on the command line,
+however, will supersede the values in
+.Em sudoers .
+.\}
+.if \n(AA \{\
+.Ss AppArmor_Spec
+On systems supporting AppArmor,
+.Em sudoers
+file entries may optionally specify an AppArmor profile that should be
+used to confine a command.
+If an AppArmor profile is specified with the command, it will override
+any default values specified in
+.Em sudoers .
+Appropriate profile transition rules must be defined to support the
+profile change specified for a user.
+.Pp
+AppArmor profiles can be specified in any way that complies with the
+rules of
+.Xr aa_change_profile 2 .
+For instance, in the following
+.Em sudoers
+entry
+.Bd -literal
+alice ALL = (root) APPARMOR_PROFILE=my-profile ALL
+.Ed
+.Pp
+the user
+.Sy alice
+may run any command as
+.Sy root
+under confinement by the profile
+.Ql my-profile .
+You can also stack profiles, or allow a user to run commands unconfined by
+any profile.
+For example:
+.Bd -literal
+bob ALL = (root) APPARMOR_PROFILE=foo//&bar /usr/bin/vi
+cathy ALL = (root) APPARMOR_PROFILE=unconfined /bin/ls
+.Ed
+.Pp
+These
+.Em sudoers
+entries allow user
+.Sy bob
+to run
+.Pa /usr/bin/vi
+as
+.Sy root
+under the stacked profiles
+.Ql foo
+and
+.Ql bar ,
+and user
+.Sy cathy
+to run
+.Pa /bin/ls
+without any confinement at all.
+.\}
+.if \n(PS \{\
+.Ss Solaris_Priv_Spec
+On Solaris systems,
+.Em sudoers
+file entries may optionally specify Solaris privilege set and/or limit
+privilege set associated with a command.
+If privileges or limit privileges are specified with the command
+it will override any default values specified in
+.Em sudoers .
+.Pp
+A privilege set is a comma-separated list of privilege names.
+The
+.Xr ppriv 1
+command can be used to list all privileges known to the system.
+For example:
+.Bd -literal
+$ ppriv -l
+.Ed
+.Pp
+In addition, there are several
+.Dq special
+privilege strings:
+.Bl -tag -width "basic"
+.It none
+the empty set
+.It all
+the set of all privileges
+.It zone
+the set of all privileges available in the current zone
+.It basic
+the default set of privileges normal users are granted at login time
+.El
+.Pp
+Privileges can be excluded from a set by prefixing the privilege
+name with either an
+.Ql \&!
+or
+.Ql \-
+character.
+.\}
+.Ss Date_Spec
+.Nm
+rules can be specified with a start and end date via the
+.Dv NOTBEFORE
+and
+.Dv NOTAFTER
+settings.
+The time stamp must be specified in
+.Dq Generalized Time
+as defined by RFC 4517.
+The format is effectively
+.Ql yyyymmddHHMMSSZ
+where the minutes and seconds are optional.
+The
+.Ql Z
+suffix indicates that the time stamp is in Coordinated Universal Time (UTC).
+It is also possible to specify a timezone offset from UTC in hours
+and minutes instead of a
+.Ql Z .
+For example,
+.Ql -0500
+would correspond to Eastern Standard time in the US.
+As an extension, if no
+.Ql Z
+or timezone offset is specified, local time will be used.
+.Pp
+The following are all valid time stamps:
+.Bd -literal -offset 4n
+20170214083000Z
+2017021408Z
+20160315220000-0500
+20151201235900
+.Ed
+.Ss Timeout_Spec
+A command may have a timeout associated with it.
+If the timeout expires before the command has exited, the
+command will be terminated.
+The timeout may be specified in combinations of days, hours,
+minutes, and seconds with a single-letter case-insensitive suffix
+that indicates the unit of time.
+For example, a timeout of 7 days, 8 hours, 30 minutes, and
+10 seconds would be written as
+.Ql 7d8h30m10s .
+If a number is specified without a unit, seconds are assumed.
+Any of the days, minutes, hours, or seconds may be omitted.
+The order must be from largest to smallest unit and a unit
+may not be specified more than once.
+.Pp
+The following are all
+.Em valid
+timeout values:
+.Ql 7d8h30m10s ,
+.Ql 14d ,
+.Ql 8h30m ,
+.Ql 600s ,
+.Ql 3600 .
+The following are
+.Em invalid
+timeout values:
+.Ql 12m2w1d ,
+.Ql 30s10m4h ,
+.Ql 1d2d3h .
+.Pp
+This setting is only supported by version 1.8.20 or higher.
+.Ss Chdir_Spec
+The working directory that the command will be run in can be specified
+using the
+.Dv CWD
+setting.
+The
+.Fa directory
+must be a fully-qualified path name beginning with a
+.Sq /
+or
+.Sq ~
+character, or the special value
+.Dq * .
+A value of
+.Dq *
+indicates that the user may specify the working directory by running
+.Nm sudo
+with the
+.Fl D
+option.
+By default, commands are run from the invoking user's current working
+directory, unless the
+.Fl i
+option is given.
+Path names of the form
+.Pa ~user/path/name
+are interpreted as being relative to the named user's home directory.
+If the user name is omitted, the path will be relative to the runas
+user's home directory.
+.Pp
+This setting is only supported by version 1.9.3 or higher.
+.Ss Chroot_Spec
+The root directory that the command will be run in can be specified
+using the
+.Dv CHROOT
+setting.
+The
+.Fa directory
+must be a fully-qualified path name beginning with a
+.Sq /
+or
+.Sq ~
+character, or the special value
+.Dq * .
+A value of
+.Dq *
+indicates that the user may specify the root directory by running
+.Nm sudo
+with the
+.Fl R
+option.
+This setting can be used to run the command in a
+.Xr chroot 2
+.Dq sandbox
+similar to the
+.Xr chroot @mansectsu@
+utility.
+Path names of the form
+.Pa ~user/path/name
+are interpreted as being relative to the named user's home directory.
+If the user name is omitted, the path will be relative to the runas
+user's home directory.
+.Pp
+This setting is only supported by version 1.9.3 or higher.
+.Ss Tag_Spec
+A command may have zero or more tags associated with it.
+The following tag values are supported:
+.Dv EXEC ,
+.Dv NOEXEC ,
+.Dv FOLLOW ,
+.Dv NOFOLLOW ,
+.Dv LOG_INPUT ,
+.Dv NOLOG_INPUT ,
+.Dv LOG_OUTPUT ,
+.Dv NOLOG_OUTPUT ,
+.Dv MAIL ,
+.Dv NOMAIL ,
+.Dv INTERCEPT ,
+.Dv NOINTERCEPT ,
+.Dv PASSWD ,
+.Dv NOPASSWD ,
+.Dv SETENV ,
+and
+.Dv NOSETENV .
+Once a tag is set on a
+.Em Cmnd ,
+subsequent
+.Em Cmnd Ns s
+in the
+.Em Cmnd_Spec_List ,
+inherit the tag unless it is overridden by the opposite tag (in other words,
+.Dv PASSWD
+overrides
+.Dv NOPASSWD
+and
+.Dv NOEXEC
+overrides
+.Dv EXEC ) .
+.Bl -hang -width 0n
+.It Dv EXEC No and Dv NOEXEC
+.sp
+If
+.Nm sudo
+has been compiled with
+.Em noexec
+support and the underlying operating system supports it, the
+.Dv NOEXEC
+tag can be used to prevent a dynamically-linked executable from
+running further commands itself.
+.Pp
+In the following example, user
+.Sy aaron
+may run
+.Pa /usr/bin/more
+and
+.Pa /usr/bin/vi
+on the host shanty, but shell escapes will be disabled.
+.Bd -literal
+aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi
+.Ed
+.Pp
+See the
+.Sx Preventing shell escapes
+section below for more details on how
+.Dv NOEXEC
+works and whether or not it will work on your system.
+.It Dv FOLLOW No and Dv NOFOLLOW
+.sp
+Starting with version 1.8.15,
+.Nm sudoedit
+will not open a file that is a symbolic link unless the
+.Em sudoedit_follow
+flag is enabled.
+The
+.Dv FOLLOW
+and
+.Dv NOFOLLOW
+tags override the value of
+.Em sudoedit_follow
+and can be used to permit (or deny) the editing of symbolic links
+on a per-command basis.
+These tags are only effective for the
+.Em sudoedit
+command and are ignored for all other commands.
+.It Dv LOG_INPUT No and Dv NOLOG_INPUT
+.sp
+These tags override the value of the
+.Em log_input
+flag on a per-command basis.
+For more information, see
+.Sx "I/O LOGGING" .
+.It Dv LOG_OUTPUT No and Dv NOLOG_OUTPUT
+.sp
+These tags override the value of the
+.Em log_output
+flag on a per-command basis.
+For more information, see
+.Sx "I/O LOGGING" .
+.It Dv MAIL No and Dv NOMAIL
+.sp
+These tags provide fine-grained control over whether
+mail will be sent when a user runs a command by
+overriding the value of the
+.Em mail_all_cmnds
+flag on a per-command basis.
+They have no effect when
+.Nm sudo
+is run with the
+.Fl l
+or
+.Fl v
+options.
+A
+.Dv NOMAIL
+tag will also override the
+.Em mail_always
+and
+.Em mail_no_perms
+options.
+For more information, see the descriptions of
+.Em mail_all_cmnds ,
+.Em mail_always ,
+and
+.Em mail_no_perms
+in the
+.Sx SUDOERS OPTIONS
+section below.
+.It Dv PASSWD No and Dv NOPASSWD
+.sp
+By default,
+.Nm sudo
+requires that a user authenticate
+before running a command.
+This behavior can be modified via the
+.Dv NOPASSWD
+tag.
+Like a
+.Em Runas_Spec ,
+the
+.Dv NOPASSWD
+tag sets
+a default for the commands that follow it in the
+.Em Cmnd_Spec_List .
+Conversely, the
+.Dv PASSWD
+tag can be used to reverse things.
+For example:
+.Bd -literal
+ray rushmore = NOPASSWD: /bin/kill, /bin/ls, /usr/bin/lprm
+.Ed
+.Pp
+would allow the user
+.Sy ray
+to run
+.Pa /bin/kill ,
+.Pa /bin/ls ,
+and
+.Pa /usr/bin/lprm
+as
+.Sy @runas_default@
+on the machine
+.Dq rushmore
+without authenticating himself.
+If we only want
+.Sy ray
+to be able to
+run
+.Pa /bin/kill
+without a password the entry would be:
+.Bd -literal
+ray rushmore = NOPASSWD: /bin/kill, PASSWD: /bin/ls, /usr/bin/lprm
+.Ed
+.Pp
+Note, however, that the
+.Dv PASSWD
+tag has no effect on users who are in the group specified by the
+.Em exempt_group
+setting.
+.Pp
+By default, if the
+.Dv NOPASSWD
+tag is applied to any of a user's entries for the current host,
+the user will be able to run
+.Ql sudo -l
+without a password.
+Additionally, a user may only run
+.Ql sudo -v
+without a password if all of the user's entries for the current
+host have the
+.Dv NOPASSWD
+tag.
+This behavior may be overridden via the
+.Em verifypw
+and
+.Em listpw
+options.
+.It Dv SETENV No and Dv NOSETENV
+.sp
+These tags override the value of the
+.Em setenv
+flag on a per-command basis.
+If
+.Dv SETENV
+has been set for a command, the user may disable the
+.Em env_reset
+flag from the command line via the
+.Fl E
+option.
+Additionally, environment variables set on the command
+line are not subject to the restrictions imposed by
+.Em env_check ,
+.Em env_delete ,
+or
+.Em env_keep .
+As such, only trusted users should be allowed to set variables in this manner.
+If the command matched is
+.Sy ALL ,
+the
+.Dv SETENV
+tag is implied for that command; this default may be overridden by use of the
+.Dv NOSETENV
+tag.
+.It Dv INTERCEPT No and Dv NOINTERCEPT
+.sp
+If
+.Nm sudo
+has been compiled with
+.Em intercept
+support and the underlying operating system supports it, the
+.Dv INTERCEPT
+tag can be used to cause programs spawned by a command to be validated against
+.Em sudoers
+and logged just like they would be if run through
+.Nm sudo
+directly.
+This is useful in conjunction with commands that allow shell escapes
+such as editors, shells, and paginators.
+There is additional overhead due to the policy check that may add
+latency when running commands such as shell scripts that execute a
+large number of sub-commands.
+For interactive commands, such as a shell or editor,
+the overhead is not usually noticeable.
+.Pp
+In the following example, user
+.Sy chuck
+may run any command on the machine
+.Dq research
+in intercept mode.
+.Bd -literal
+chuck research = INTERCEPT: ALL
+.Ed
+.Pp
+See the
+.Sx Preventing shell escapes
+section below for more details on how
+.Dv INTERCEPT
+works and whether or not it will work on your system.
+.El
+.Ss Wildcards
+.Nm sudo
+allows shell-style
+.Em wildcards
+(aka meta or glob characters)
+to be used in host names, path names, and command line arguments in the
+.Em sudoers
+file.
+Wildcard matching is done via the
+.Xr glob 3
+and
+.Xr fnmatch 3
+functions as specified by
+.St -p1003.1 .
+.Bl -tag -width "[!...]"
+.It *
+Matches any set of zero or more characters (including white space).
+.It \&?
+Matches any single character (including white space).
+.It [...]
+Matches any character in the specified range.
+.It [!...]
+Matches any character
+.Em not
+in the specified range.
+.It \ex
+For any character
+.Sq x ,
+evaluates to
+.Sq x .
+This is used to escape special characters such as:
+.Ql * ,
+.Ql \&? ,
+.Ql [\& ,
+and
+.Ql ]\& .
+.El
+.Pp
+.Bf -symbolic
+These are not regular expressions.
+.Ef
+Unlike a regular expression there is no way to match one or more
+characters within a range.
+.Pp
+Character classes may be used if your system's
+.Xr glob 3
+and
+.Xr fnmatch 3
+functions support them.
+However, because the
+.Ql :\&
+character has special meaning in
+.Em sudoers ,
+it must be
+escaped.
+For example:
+.Bd -literal -offset 4n
+/bin/ls [[\e:\&alpha\e:\&]]*
+.Ed
+.Pp
+Would match any file name beginning with a letter.
+.Pp
+A forward slash
+.Pq Ql /
+will
+.Em not
+be matched by
+wildcards used in the file name portion of the command.
+This is to make a path like:
+.Bd -literal -offset 4n
+/usr/bin/*
+.Ed
+.Pp
+match
+.Pa /usr/bin/who
+but not
+.Pa /usr/bin/X11/xterm .
+.Pp
+When matching the command line arguments, however, a slash
+.Em does
+get matched by wildcards since command line arguments may contain
+arbitrary strings and not just path names.
+.Pp
+.Bf -symbolic
+Wildcards in command line arguments should be used with care.
+.Ef
+.br
+Wildcards can match any character, including white space.
+In most cases, it is safer to use a regular expression to match
+command line arguments.
+For more information, see
+.Sx Wildcards in command arguments
+below.
+.Ss Exceptions to wildcard rules
+The following exceptions apply to the above rules:
+.Bl -tag -width "sudoedit"
+.It \&""
+If the empty string
+.Ql \&""
+is the only command line argument in the
+.Em sudoers
+file entry it means that command is not allowed to be run with
+.Em any
+arguments.
+.It sudoedit
+Command line arguments to the
+.Em sudoedit
+built-in command should always be path names, so a forward slash
+.Pq Ql /
+will not be matched by a wildcard.
+.El
+.Ss Regular expressions
+Starting with version 1.9.10, it is possible to use
+regular expressions for path names and command line arguments.
+Regular expressions are more expressive than shell-style
+.Em wildcards
+and are usually safer because they provide a greater degree of
+control when matching.
+The type of regular expressions supported by
+.Nm
+are POSIX extended regular expressions, similar to those used by the
+.Xr egrep 1
+utility.
+They are usually documented in the
+.Xr regex @mansectmisc@
+or
+.Xr re_format @mansectmisc@
+manual, depending on the system.
+As an extension, if the regular expression begins with
+.Dq (?i) ,
+it will be matched in a case-insensitive manner.
+.Pp
+In
+.Em sudoers ,
+regular expressions must start with a
+.Ql ^
+character and end with a
+.Ql $ .
+This makes it explicit what is, or is not, a regular expression.
+Either the path name, the command line arguments or both may
+be regular expressions.
+Because the path name and arguments are matched separately, it is
+even possible to use wildcards for the path name and regular
+expressions for the arguments.
+It is not possible to use a single regular expression to match
+both the command and its arguments.
+Regular expressions in
+.Em sudoers
+are limited to 1024 characters.
+.Pp
+There is no need to escape
+.Em sudoers
+special characters in a regular expression other than the pound sign
+.Pq Ql # .
+.Pp
+In the following example, user
+.Sy john
+can run the
+.Xr passwd 1
+command as
+.Sy @runas_default@
+on any host but is not allowed to change
+.Sy root Ns No 's
+password.
+This kind of rule is impossible to express safely using wildcards.
+.Bd -literal -offset 4n
+john ALL = /usr/bin/passwd ^[a-zA-Z0-9_]+$,\e
+ !/usr/bin/passwd root
+.Ed
+.Pp
+It is also possible to use a regular expression in conjunction with
+.Nm sudoedit
+rules.
+The following rule would give user bob the ability to edit the
+.Pa /etc/motd ,
+.Pa /etc/issue ,
+and
+.Pa /etc/hosts
+files only.
+.Bd -literal -offset 4n
+bob ALL = sudoedit ^/etc/(motd|issue|hosts)$
+.Ed
+.Pp
+Regular expressions may also be used to match the command itself.
+In this example, a regular expression is used to allow user
+.Sy sid
+to run the
+.Pa /usr/sbin/groupadd ,
+.Pa /usr/sbin/groupmod ,
+.Pa /usr/sbin/groupdel ,
+.Pa /usr/sbin/useradd ,
+.Pa /usr/sbin/usermod ,
+and
+.Pa /usr/sbin/userdel
+commands as
+.Sy @runas_default@ .
+.Bd -literal -offset 4n
+sid ALL = ^/usr/sbin/(group|user)(add|mod|del)$
+.Ed
+.Pp
+One disadvantage of using a regular expression to match the command
+name is that it is not possible to match relative paths such as
+.Pa ./useradd
+or
+.Pa ../sbin/useradd .
+This has security implications when a regular expression is used
+for the command name in conjunction with the negation operator,
+.Ql !\& ,
+as such rules can be trivially bypassed.
+Because of this, using a negated regular expression for the command name is
+.Sy strongly discouraged .
+This does not apply to negated commands that only use a regular
+expression to match the command arguments.
+See
+.Sx Regular expressions in command names
+below for more information.
+.Ss Including other files from within sudoers
+It is possible to include other
+.Em sudoers
+files from within the
+.Em sudoers
+file currently being parsed using the
+.Em @include
+and
+.Em @includedir
+directives.
+For compatibility with sudo versions prior to 1.9.1,
+.Em #include
+and
+.Em #includedir
+are also accepted.
+.Pp
+An include file can be used, for example, to keep a site-wide
+.Em sudoers
+file in addition to a local, per-machine file.
+For the sake of this example the site-wide
+.Em sudoers
+file will be
+.Pa /etc/sudoers
+and the per-machine one will be
+.Pa /etc/sudoers.local .
+To include
+.Pa /etc/sudoers.local
+from within
+.Pa /etc/sudoers
+one would use the following line in
+.Pa /etc/sudoers :
+.Bd -literal -offset 4n
+@include /etc/sudoers.local
+.Ed
+.Pp
+When
+.Nm sudo
+reaches this line it will suspend processing of the current file
+.Pq Pa /etc/sudoers
+and switch to
+.Pa /etc/sudoers.local .
+Upon reaching the end of
+.Pa /etc/sudoers.local ,
+the rest of
+.Pa /etc/sudoers
+will be processed.
+Files that are included may themselves include other files.
+A hard limit of 128 nested include files is enforced to prevent include
+file loops.
+.Pp
+Starting with version 1.9.1, the path to the include file may contain
+white space if it is escaped with a backslash
+.Pq Ql \e .
+Alternately, the entire path may be enclosed in double quotes
+.Pq \&"" ,
+in which case no escaping is necessary.
+To include a literal backslash in the path,
+.Ql \e\e
+should be used.
+.Pp
+If the path to the include file is not fully-qualified (does not
+begin with a
+.Ql / ) ,
+it must be located in the same directory as the sudoers file it was
+included from.
+For example, if
+.Pa /etc/sudoers
+contains the line:
+.Bd -literal -offset 4n
+@include sudoers.local
+.Ed
+.Pp
+the file that will be included is
+.Pa /etc/sudoers.local .
+.Pp
+The file name may also include the
+.Ql %h
+escape, signifying the short form of the host name.
+In other words, if the machine's host name is
+.Dq xerxes ,
+then
+.Bd -literal -offset 4n
+@include /etc/sudoers.%h
+.Ed
+.Pp
+will cause
+.Nm sudo
+to include the file
+.Pa /etc/sudoers.xerxes .
+Any path name separator characters
+.Pq Ql /
+present in the host name will be replaced with an underbar
+.Pq Ql _
+during expansion.
+.Pp
+The
+.Em @includedir
+directive can be used to create a
+.Pa sudoers.d
+directory that the system package manager can drop
+.Em sudoers
+file rules into as part of package installation.
+For example, given:
+.Bd -literal -offset 4n
+@includedir /etc/sudoers.d
+.Ed
+.Pp
+.Nm sudo
+will suspend processing of the current file and read each file in
+.Pa /etc/sudoers.d ,
+skipping file names that end in
+.Ql ~
+or contain a
+.Ql .\&
+character to avoid causing problems with package manager or editor
+temporary/backup files.
+.Pp
+Files are parsed in sorted lexical order.
+That is,
+.Pa /etc/sudoers.d/01_first
+will be parsed before
+.Pa /etc/sudoers.d/10_second .
+Be aware that because the sorting is lexical, not numeric,
+.Pa /etc/sudoers.d/1_whoops
+would be loaded
+.Em after
+.Pa /etc/sudoers.d/10_second .
+Using a consistent number of leading zeroes in the file names can be used
+to avoid such problems.
+After parsing the files in the directory, control returns to the
+file that contained the
+.Em @includedir
+directive.
+.Pp
+Unlike files included via
+.Em @include ,
+.Nm visudo
+will not edit the files in a
+.Em @includedir
+directory unless one of them contains a syntax error.
+It is still possible to run
+.Nm visudo
+with the
+.Fl f
+flag to edit the files directly, but this will not catch the
+redefinition of an
+.Em alias
+that is also present in a different file.
+.Ss Other special characters and reserved words
+The pound sign
+.Pq Ql #
+is used to indicate a comment (unless it is part of a #include
+directive or unless it occurs in the context of a user name and is
+followed by one or more digits, in which case it is treated as a
+user-ID).
+Both the comment character and any text after it, up to the end of
+the line, are ignored.
+.Pp
+The reserved word
+.Sy ALL
+is a built-in
+.Em alias
+that always causes a match to succeed.
+It can be used wherever one might otherwise use a
+.Em Cmnd_Alias ,
+.Em User_Alias ,
+.Em Runas_Alias ,
+or
+.Em Host_Alias .
+Attempting to define an
+.Em alias
+named
+.Sy ALL
+will result in a syntax error.
+Using
+.Sy ALL
+can be dangerous since in a command context, it allows the user to run
+.Em any
+command on the system.
+.Pp
+The following option names permitted in an
+.Em Option_Spec
+are also considered reserved words:
+.Dv CHROOT ,
+.if \n(PS \{\
+.Dv PRIVS ,
+.Dv LIMITPRIVS ,
+.\}
+.if \n(SL \{\
+.Dv ROLE ,
+.Dv TYPE ,
+.\}
+.Dv TIMEOUT ,
+.Dv CWD ,
+.Dv NOTBEFORE
+and
+.Dv NOTAFTER .
+Attempting to define an
+.Em alias
+with the same name as one of the options will result in a syntax error.
+.Pp
+An exclamation point
+.Pq Ql \&!
+can be used as a logical
+.Em not
+operator in a list or
+.Em alias
+as well as in front of a
+.Em Cmnd .
+This allows one to exclude certain values.
+For the
+.Ql \&!
+operator to be effective, there must be something for it to exclude.
+For example, to match all users except for
+.Sy root
+one would use:
+.Bd -literal -offset 4n
+ALL, !root
+.Ed
+.Pp
+If the
+.Sy ALL ,
+is omitted, as in:
+.Bd -literal -offset 4n
+!root
+.Ed
+.Pp
+it would explicitly deny
+.Sy root
+but not match any other users.
+This is different from a true
+.Dq negation
+operator.
+.Pp
+Note, however, that using a
+.Ql \&!
+in conjunction with the built-in
+.Sy ALL
+alias to allow a user to run
+.Dq all but a few
+commands rarely works as intended (see
+.Sx SECURITY NOTES
+below).
+.Pp
+Long lines can be continued with a backslash
+.Pq Ql \e
+as the last character on the line.
+.Pp
+White space between elements in a list as well as special syntactic
+characters in a
+.Em User Specification
+.Po
+.Ql =\& ,
+.Ql :\& ,
+.Ql (\& ,
+.Ql )\&
+.Pc
+is optional.
+.Pp
+The following characters must be escaped with a backslash
+.Pq Ql \e
+when used as part of a word (e.g., a user name or host name):
+.Ql \&! ,
+.Ql =\& ,
+.Ql :\& ,
+.Ql ,\& ,
+.Ql (\& ,
+.Ql )\& ,
+.Ql \e .
+.Sh SUDOERS OPTIONS
+.Nm sudo Ns 's
+behavior can be modified by
+.Em Default_Entry
+lines, as explained earlier.
+A list of all supported Defaults parameters, grouped by type, are listed below.
+.Pp
+.Sy Boolean Flags :
+.Bl -tag -width 16n
+.It always_query_group_plugin
+If a
+.Em group_plugin
+is configured, use it to resolve groups of the form
+.Ql %group
+as long as there is not also a system group of the same name.
+Normally, only groups of the form
+.Ql %:group
+are passed to the
+.Em group_plugin .
+This flag is
+.Em off
+by default.
+.It always_set_home
+If enabled,
+.Nm sudo
+will set the
+.Ev HOME
+environment variable to the home directory of the target user
+(which is the
+.Em runas_default
+user unless the
+.Fl u
+option is used).
+This flag is largely obsolete and has no effect unless the
+.Em env_reset
+flag has been disabled or
+.Ev HOME
+is present in the
+.Em env_keep
+list, both of which are strongly discouraged.
+This flag is
+.Em off
+by default.
+.It authenticate
+If set, users must authenticate themselves via a password (or other
+means of authentication) before they may run commands.
+This default may be overridden via the
+.Dv PASSWD
+and
+.Dv NOPASSWD
+tags.
+This flag is
+.Em on
+by default.
+.It case_insensitive_group
+If enabled, group names in
+.Em sudoers
+will be matched in a case insensitive manner.
+This may be necessary when users are stored in LDAP or AD.
+This flag is
+.Em on
+by default.
+.It case_insensitive_user
+If enabled, user names in
+.Em sudoers
+will be matched in a case insensitive manner.
+This may be necessary when groups are stored in LDAP or AD.
+This flag is
+.Em on
+by default.
+.It closefrom_override
+If set, the user may use the
+.Fl C
+option which overrides the default starting point at which
+.Nm sudo
+begins closing open file descriptors.
+This flag is
+.Em off
+by default.
+.It compress_io
+If set, and
+.Nm sudo
+is configured to log a command's input or output,
+the I/O logs will be compressed using
+.Sy zlib .
+This flag is
+.Em on
+by default when
+.Nm sudo
+is compiled with
+.Sy zlib
+support.
+.It exec_background
+By default,
+.Nm sudo
+runs a command as the foreground process as long as
+.Nm sudo
+itself is running in the foreground.
+When the
+.Em exec_background
+flag is enabled and the command is being run in a pseudo-terminal
+(due to I/O logging or the
+.Em use_pty
+flag), the command will be run as a background process.
+Attempts to read from the controlling terminal (or to change terminal
+settings) will result in the command being suspended with the
+.Dv SIGTTIN
+signal (or
+.Dv SIGTTOU
+in the case of terminal settings).
+If this happens when
+.Nm sudo
+is a foreground process, the command will be granted the controlling terminal
+and resumed in the foreground with no user intervention required.
+The advantage of initially running the command in the background is that
+.Nm sudo
+need not read from the terminal unless the command explicitly requests it.
+Otherwise, any terminal input must be passed to the command, whether it
+has required it or not (the kernel buffers terminals so it is not possible
+to tell whether the command really wants the input).
+This is different from historic
+.Em sudo
+behavior or when the command is not being run in a pseudo-terminal.
+.Pp
+For this to work seamlessly, the operating system must support the
+automatic restarting of system calls.
+Unfortunately, not all operating systems do this by default,
+and even those that do may have bugs.
+For example, macOS fails to restart the
+.Xr tcgetattr 3
+and
+.Xr tcsetattr 3
+functions (this is a bug in macOS).
+Furthermore, because this behavior depends on the command stopping with the
+.Dv SIGTTIN
+or
+.Dv SIGTTOU
+signals, programs that catch these signals and suspend themselves
+with a different signal (usually
+.Dv SIGTOP )
+will not be automatically foregrounded.
+Some versions of the linux
+.Xr su 1
+command behave this way.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.8.7 or higher.
+It has no effect unless I/O logging is enabled or the
+.Em use_pty
+flag is enabled.
+.It env_editor
+If set,
+.Nm visudo
+will use the value of the
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+or
+.Ev EDITOR
+environment variables before falling back on the default editor list.
+.Nm visudo
+is typically run as
+.Sy root
+so this flag may allow a user with
+.Nm visudo
+privileges to run arbitrary commands as
+.Sy root
+without logging.
+An alternative is to place a colon-separated list of
+.Dq safe
+editors int the
+.Em editor
+setting.
+.Nm visudo
+will then only use
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+or
+.Ev EDITOR
+if they match a value specified in
+.Em editor .
+If the
+.Em env_reset
+flag is enabled, the
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+and/or
+.Ev EDITOR
+environment variables must be present in the
+.Em env_keep
+list for the
+.Em env_editor
+flag to function when
+.Nm visudo
+is invoked via
+.Nm sudo .
+This flag is
+.Em @env_editor@
+by default.
+.It env_reset
+If set,
+.Nm sudo
+will run the command in a minimal environment containing the
+.Ev TERM ,
+.Ev PATH ,
+.Ev HOME ,
+.Ev MAIL ,
+.Ev SHELL ,
+.Ev LOGNAME ,
+.Ev USER
+and
+.Ev SUDO_*
+variables.
+Any variables in the caller's environment or in the file specified
+by the
+.Em restricted_env_file
+setting that match the
+.Em env_keep
+and
+.Em env_check
+lists are then added, followed by any variables present in the file
+specified by the
+.Em env_file
+setting (if any).
+The contents of the
+.Em env_keep
+and
+.Em env_check
+lists, as modified by global Defaults parameters in
+.Em sudoers ,
+are displayed when
+.Nm sudo
+is run by
+.Sy root
+with the
+.Fl V
+option.
+If the
+.Em secure_path
+setting is enabled, its value will be used for the
+.Ev PATH
+environment variable.
+This flag is
+.Em @env_reset@
+by default.
+.It fast_glob
+Normally,
+.Nm sudo
+uses the
+.Xr glob 3
+function to do shell-style globbing when matching path names.
+However, since it accesses the file system,
+.Xr glob 3
+can take a long time to complete for some patterns, especially
+when the pattern references a network file system that is mounted
+on demand (auto mounted).
+The
+.Em fast_glob
+flag causes
+.Nm sudo
+to use the
+.Xr fnmatch 3
+function, which does not access the file system to do its matching.
+The disadvantage of
+.Em fast_glob
+is that it is unable to match relative paths such as
+.Pa ./ls
+or
+.Pa ../bin/ls .
+This has security implications when path names that include globbing
+characters are used with the negation operator,
+.Ql !\& ,
+as such rules can be trivially bypassed.
+As such, this flag should not be used when the
+.Em sudoers
+file contains rules that contain negated path names which include globbing
+characters.
+This flag is
+.Em off
+by default.
+.It log_passwords
+Most programs that require a user's password will disable echo before
+reading the password to avoid displaying the plaintext password on
+the screen.
+However, if terminal input is being logged (see
+.Sx "I/O LOGGING" ) ,
+the password will still be present in the I/O log.
+If the
+.Em log_passwords
+option is disabled,
+.Nm
+will attempt to prevent passwords from being logged.
+It does this by using the regular expressions in
+.Em passprompt_regex
+to match a password prompt in the terminal output buffer.
+When a match is found, input characters in the I/O log will be replaced with
+.Ql *
+until either a line feed or carriage return is found in the terminal input
+or a new terminal output buffer is received.
+If, however, a program displays characters as the user types
+(such as
+.Nm sudo
+when
+.Em pwfeedback
+is set), only the
+first character of the password will be replaced in the I/O log.
+This option has no effect unless
+.Em log_input
+or
+.Em log_ttyin
+are also set.
+This flag is
+.Em on
+by default.
+.Pp
+This setting is only supported by version 1.9.10 or higher.
+.It fqdn
+Set this flag if you want to put fully qualified host names in the
+.Em sudoers
+file when the local host name (as returned by the
+.Ql hostname
+command) does not contain the domain name.
+In other words, instead of myhost you would use myhost.mydomain.edu.
+You may still use the short form if you wish (and even mix the two).
+This flag is only effective when the
+.Dq canonical
+host name, as returned by the
+.Xr getaddrinfo 3
+or
+.Xr gethostbyname 3
+function, is a fully-qualified domain name.
+This is usually the case when the system is configured to use DNS
+for host name resolution.
+.Pp
+If the system is configured to use the
+.Pa /etc/hosts
+file in preference to DNS, the
+.Dq canonical
+host name may not be fully-qualified.
+The order that sources are queried for host name resolution
+is usually specified in the
+.Pa @nsswitch_conf@ ,
+.Pa @netsvc_conf@ ,
+.Pa /etc/host.conf ,
+or, in some cases,
+.Pa /etc/resolv.conf
+file.
+In the
+.Pa /etc/hosts
+file, the first host name of the entry is considered to be the
+.Dq canonical
+name; subsequent names are aliases that are not used by
+.Nm .
+For example, the following hosts file line for the machine
+.Dq xyzzy
+has the fully-qualified domain name as the
+.Dq canonical
+host name, and the short version as an alias.
+.sp
+.Dl 192.168.1.1 xyzzy.sudo.ws xyzzy
+.sp
+If the machine's hosts file entry is not formatted properly, the
+.Em fqdn
+flag will not be effective if it is queried before DNS.
+.Pp
+Beware that when using DNS for host name resolution, turning on
+.Em fqdn
+requires
+.Nm
+to make DNS lookups which renders
+.Nm sudo
+unusable if DNS stops working (for example if the machine is disconnected
+from the network).
+Just like with the hosts file, you must use the
+.Dq canonical
+name as DNS knows it.
+That is, you may not use a host alias (CNAME entry) due to performance
+issues and the fact that there is no way to get all aliases from DNS.
+.Pp
+This flag is
+.Em @fqdn@
+by default.
+.It ignore_audit_errors
+Allow commands to be run even if
+.Nm
+cannot write to the audit log.
+If enabled, an audit log write failure is not treated as a fatal error.
+If disabled, a command may only be run after the audit event is successfully
+written.
+This flag is only effective on systems for which
+.Nm
+supports audit logging, including
+.Fx ,
+Linux, macOS, and Solaris.
+This flag is
+.Em on
+by default.
+.It ignore_dot
+If set,
+.Nm sudo
+will ignore "." or "" (both denoting the current directory) in the
+.Ev PATH
+environment variable; the
+.Ev PATH
+itself is not modified.
+This flag is
+.Em @ignore_dot@
+by default.
+.It ignore_iolog_errors
+Allow commands to be run even if
+.Nm
+cannot write to the I/O log (local or remote).
+If enabled, an I/O log write failure is not treated as a fatal error.
+If disabled, the command will be terminated if the I/O log cannot be written to.
+This flag is
+.Em off
+by default.
+.It ignore_logfile_errors
+Allow commands to be run even if
+.Nm
+cannot write to the log file.
+If enabled, a log file write failure is not treated as a fatal error.
+If disabled, a command may only be run after the log file entry is successfully
+written.
+This flag only has an effect when
+.Nm
+is configured to use file-based logging via the
+.Em logfile
+setting.
+This flag is
+.Em on
+by default.
+.It ignore_local_sudoers
+If set via LDAP, parsing of
+.Pa @sysconfdir@/sudoers
+will be skipped.
+This is intended for sites that wish to prevent the usage of local
+sudoers files so that only LDAP is used.
+This thwarts the efforts of rogue operators who would attempt to add roles to
+.Pa @sysconfdir@/sudoers .
+When this flag is enabled,
+.Pa @sysconfdir@/sudoers
+does not even need to exist.
+Since this flag tells
+.Nm sudo
+how to behave when no specific LDAP entries have been matched, this
+sudoOption is only meaningful for the
+.Ql cn=defaults
+section.
+This flag is
+.Em off
+by default.
+.It ignore_unknown_defaults
+If set,
+.Nm sudo
+will not produce a warning if it encounters an unknown Defaults entry
+in the
+.Em sudoers
+file or an unknown sudoOption in LDAP.
+This flag is
+.Em off
+by default.
+.It insults
+If set,
+.Nm sudo
+will insult users when they enter an incorrect password.
+This flag is
+.Em @insults@
+by default.
+.It log_allowed
+If set,
+.Nm
+will log commands allowed by the policy to the system audit log
+(where supported) as well as to syslog and/or a log file.
+This flag is
+.Em on
+by default.
+.Pp
+This setting is only supported by version 1.8.29 or higher.
+.It log_denied
+If set,
+.Nm
+will log commands denied by the policy to the system audit log
+(where supported) as well as to syslog and/or a log file.
+This flag is
+.Em on
+by default.
+.Pp
+This setting is only supported by version 1.8.29 or higher.
+.It log_exit_status
+If set,
+.Nm
+will log the exit value of commands that are run to syslog and/or a log file.
+If a command was terminated by a signal, the signal name is logged as well.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.9.8 or higher.
+.It log_host
+If set, the host name will be included in log entries written to
+the file configured by the
+.Em logfile
+setting.
+This flag is
+.Em off
+by default.
+.It log_input
+If set,
+.Nm sudo
+will run the command in a pseudo-terminal (if
+.Nm sudo
+was run from a terminal) and log all user input.
+If the standard input is not connected to the user's terminal, due
+to I/O redirection or because the command is part of a pipeline,
+that input is also logged.
+For more information about I/O logging, see the
+.Sx "I/O LOGGING"
+section.
+This flag is
+.Em off
+by default.
+.It log_output
+If set,
+.Nm sudo
+will run the command in a pseudo-terminal (if
+.Nm sudo
+was run from a terminal) and log all output that is sent to the
+user's terminal, the standard output or the standard error.
+If the standard output or standard error is not connected to the
+user's terminal, due to I/O redirection or because the command is
+part of a pipeline, that output is also logged.
+For more information about I/O logging, see the
+.Sx "I/O LOGGING"
+section.
+This flag is
+.Em off
+by default.
+.It log_server_keepalive
+If set,
+.Nm sudo
+will enable the TCP keepalive socket option on the connection to the log server.
+This enables the periodic transmission of keepalive messages to the server.
+If the server does not respond to a message, the connection will
+be closed and the running command will be terminated unless the
+.Em ignore_iolog_errors
+flag (I/O logging enabled) or the
+.Em ignore_log_errors
+flag (I/O logging disabled) is set.
+This flag is
+.Em on
+by default.
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.It log_server_verify
+If set, the server certificate received during the TLS handshake
+must be valid and it must contain either the server name (from
+.Em log_servers )
+or its IP address.
+If either of these conditions is not met, the TLS handshake will fail.
+This flag is
+.Em on
+by default.
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.It log_stderr
+If set,
+.Nm sudo
+will log the standard error if it is not connected to the user's terminal.
+This can be used to log output to a pipe or redirected to a file.
+This flag is
+.Em off
+by default but is enabled when either the
+.Em log_output
+flag or the
+.Dv LOG_OUTPUT
+command tag is set.
+.It log_stdin
+If set,
+.Nm sudo
+will log the standard input if it is not connected to the user's terminal.
+This can be used to log input from a pipe or redirected from a file.
+This flag is
+.Em off
+by default but is enabled when either the
+.Em log_input
+flag or the
+.Dv LOG_INPUT
+command tag is set.
+.It log_stdout
+If set,
+.Nm sudo
+will log the standard output if it is not connected to the user's terminal.
+This can be used to log output to a pipe or redirected to a file.
+This flag is
+.Em off
+by default but is enabled when either the
+.Em log_output
+flag or the
+.Dv LOG_OUTPUT
+command tag is set.
+.It log_subcmds
+If set,
+.Nm
+will log when a command spawns a child process and executes a program
+using the
+.Xr execve 2 ,
+.Xr execl 3 ,
+.Xr execle 3 ,
+.Xr execlp 3 ,
+.Xr execv 3 ,
+.Xr execvp 3 ,
+.Xr execvpe 3 ,
+or
+.Xr system 3
+library functions.
+For example, if a shell is run by
+.Nm sudo ,
+the individual commands run via the shell will be logged.
+This flag is
+.Em off
+by default.
+.Pp
+The
+.Em log_subcmds
+flag uses the same underlying mechanism as the
+.Em intercept
+setting.
+Some commands may not work properly when
+.Em log_subcmds
+is enabled, due to the way it intercepts sub-commands.
+See
+.Sx Preventing shell escapes
+for more information on what systems support this option and its limitations.
+This setting is only supported by version 1.9.8 or higher
+and is incompatible with SELinux RBAC support unless the system supports
+.Xr seccomp 2
+filter mode.
+.It log_ttyin
+If set,
+.Nm sudo
+will run the command in a pseudo-terminal and log user keystrokes
+sent to the user's terminal, if one is present.
+This flag is
+.Em off
+by default but is enabled when either the
+.Em log_input
+flag or the
+.Dv LOG_INPUT
+command tag is set.
+If no terminal is present, for example when running a remote command using
+.Xr ssh 1 ,
+this flag will have no effect.
+.It log_ttyout
+If set,
+.Nm sudo
+will run the command in a pseudo-terminal and log all output displayed
+on the user's terminal, if one is present.
+This flag is
+.Em off
+by default but is enabled when either the
+.Em log_output
+flag or the
+.Dv LOG_OUTPUT
+command tag is set.
+If no terminal is present, for example when running a remote command using
+.Xr ssh 1 ,
+this flag will have no effect.
+.It log_year
+If set, the four-digit year will be logged in the (non-syslog)
+.Nm sudo
+log file.
+This flag is
+.Em off
+by default.
+.It long_otp_prompt
+When validating with a One Time Password (OTP) scheme such as
+.Sy S/Key
+or
+.Sy OPIE ,
+a two-line prompt is used to make it easier
+to cut and paste the challenge to a local window.
+It's not as pretty as the default but some people find it more convenient.
+This flag is
+.Em @long_otp_prompt@
+by default.
+.It mail_all_cmnds
+Send mail to the
+.Em mailto
+user every time a user attempts to run a command via
+.Nm sudo
+(this includes
+.Nm sudoedit ) .
+No mail will be sent if the user runs
+.Nm sudo
+with the
+.Fl l
+or
+.Fl v
+option unless there is an authentication error and the
+.Em mail_badpass
+flag is also set.
+This flag is
+.Em off
+by default.
+.It mail_always
+Send mail to the
+.Em mailto
+user every time a user runs
+.Nm sudo .
+This flag is
+.Em off
+by default.
+.It mail_badpass
+Send mail to the
+.Em mailto
+user if the user running
+.Nm sudo
+does not enter the correct password.
+If the command the user is attempting to run is not permitted by
+.Nm
+and one of the
+.Em mail_all_cmnds ,
+.Em mail_always ,
+.Em mail_no_host ,
+.Em mail_no_perms
+or
+.Em mail_no_user
+flags are set, this flag will have no effect.
+This flag is
+.Em off
+by default.
+.It mail_no_host
+If set, mail will be sent to the
+.Em mailto
+user if the invoking user exists in the
+.Em sudoers
+file, but is not allowed to run commands on the current host.
+This flag is
+.Em @mail_no_host@
+by default.
+.It mail_no_perms
+If set, mail will be sent to the
+.Em mailto
+user if the invoking user is allowed to use
+.Nm sudo
+but the command they are trying is not listed in their
+.Em sudoers
+file entry or is explicitly denied.
+This flag is
+.Em @mail_no_perms@
+by default.
+.It mail_no_user
+If set, mail will be sent to the
+.Em mailto
+user if the invoking user is not in the
+.Em sudoers
+file.
+This flag is
+.Em @mail_no_user@
+by default.
+.It match_group_by_gid
+By default,
+.Nm
+will look up each group the user is a member of by group-ID to
+determine the group name (this is only done once).
+The resulting list of the user's group names is used when matching
+groups listed in the
+.Em sudoers
+file.
+This works well on systems where the number of groups listed in the
+.Em sudoers
+file is larger than the number of groups a typical user belongs to.
+On systems where group lookups are slow, where users may belong
+to a large number of groups, or where the number of groups listed
+in the
+.Em sudoers
+file is relatively small, it may be prohibitively expensive and
+running commands via
+.Nm sudo
+may take longer than normal.
+On such systems it may be faster to use the
+.Em match_group_by_gid
+flag to avoid resolving the user's group-IDs to group names.
+In this case,
+.Nm
+must look up any group name listed in the
+.Em sudoers
+file and use the group-ID instead of the group name when determining
+whether the user is a member of the group.
+.Pp
+If
+.Em match_group_by_gid
+is enabled, group database lookups performed by
+.Nm
+will be keyed by group name as opposed to group-ID.
+On systems where there are multiple sources for the group database,
+it is possible to have conflicting group names or group-IDs in the local
+.Pa /etc/group
+file and the remote group database.
+On such systems, enabling or disabling
+.Em match_group_by_gid
+can be used to choose whether group database queries are performed
+by name (enabled) or ID (disabled), which may aid in working around
+group entry conflicts.
+.Pp
+The
+.Em match_group_by_gid
+flag has no effect when
+.Em sudoers
+data is stored in LDAP.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.8.18 or higher.
+.It intercept
+If set, all commands run via
+.Nm sudo
+will behave as if the
+.Dv INTERCEPT
+tag has been set, unless overridden by an
+.Dv NOINTERCEPT
+tag.
+Some commands may not work properly when
+.Em intercept
+is enabled, due to the way it intercept sub-commands.
+See the description of
+.Dv INTERCEPT and NOINTERCEPT
+above as well as the
+.Sx Preventing shell escapes
+section at the end of this manual.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.9.8 or higher
+and is incompatible with SELinux RBAC support unless the system supports
+.Xr seccomp 2
+filter mode.
+.It intercept_allow_setid
+On most systems, the dynamic loader will ignore
+.Ev LD_PRELOAD
+(or the equivalent) when running set-user-ID and set-group-ID
+programs, effectively disabling intercept mode.
+To prevent this from happening,
+.Nm
+will not permit a set-user-ID or set-group-ID program to be run in
+intercept mode unless
+.Em intercept_allow_setid
+is enable.
+This flag has no effect unless the
+.Em intercept
+flag is enabled or the
+.Dv INTERCEPT
+tag has been set for the command.
+This flag is
+.Em on
+by default when the
+.Em intercept_type
+option is set to
+.Em trace ,
+otherwise it default to
+.Em off .
+.Pp
+This setting is only supported by version 1.9.8 or higher.
+.It intercept_authenticate
+If set, commands run by an intercepted process must be authenticated
+when the user's time stamp is not current.
+For example, if a shell is run with
+.Em intercept
+enabled, as soon as the invoking user's time stamp is out of date,
+subsequent commands will need to be authenticated.
+This flag has no effect unless the
+.Em intercept
+flag is enabled or the
+.Dv INTERCEPT
+tag has been set for the command.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.9.8 or higher.
+.It intercept_verify
+If set,
+.Nm sudo
+will attempt to verify that a command run in intercept mode has
+the expected path name, command line arguments and environment.
+.Pp
+The process will be stopped after
+.Xr execve 2
+has completed but before the new command has had a chance to run.
+To verify the command,
+.Nm sudo
+will read the command's path from
+.Pa /proc/PID/exe ,
+the command line arguments and environment from the process's memory,
+and compare them against the arguments that were passed to
+.Xr execve 2 .
+In the event of a mismatch, the command will be sent a
+.Dv SIGKILL
+signal and terminated.
+.Pp
+This can help prevent a time of check versus time of use issue with
+intercept mode where the
+.Xr execve 2
+arguments could be altered after the
+.Nm
+policy check.
+The checks can only be performed if the
+.Xr proc @mansectform@
+file system is available.
+This flag has no effect unless the
+.Em intercept
+flag is enabled or the
+.Dv INTERCEPT
+tag has been set for the command and the
+.Em intercept_type
+option is set to
+.Em trace .
+.Pp
+This setting is incompatible with programs that change their root directory via
+.Xr chroot 2 .
+If a program changes its root directory, path names will no longer match
+those seen by the
+.Nm sudo
+parent process and sub-commands will be terminated before they have a chance
+to run.
+This flag is
+.Em on
+by default.
+.Pp
+This setting is only supported by version 1.9.12 or higher.
+.It netgroup_tuple
+If set, netgroup lookups will be performed using the full netgroup
+tuple: host name, user name, and domain (if one is set).
+Historically,
+.Nm sudo
+only matched the user name and domain for netgroups used in a
+.Em User_List
+and only matched the host name and domain for netgroups used in a
+.Em Host_List .
+This flag is
+.Em off
+by default.
+.It noexec
+If set, all commands run via
+.Nm sudo
+will behave as if the
+.Dv NOEXEC
+tag has been set, unless overridden by an
+.Dv EXEC
+tag.
+See the description of
+.Dv EXEC and NOEXEC
+above as well as the
+.Sx Preventing shell escapes
+section at the end of this manual.
+This flag is
+.Em off
+by default.
+.It noninteractive_auth
+If set, authentication will be attempted even in non-interactive mode
+(when
+.Nm sudo Ns 's
+.Fl n
+option is specified).
+This allows authentication methods that don't require user interaction
+to succeed.
+Authentication methods that require input from the user's terminal
+will still fail.
+If disabled, authentication will not be attempted in non-interactive mode.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.9.10 or higher.
+.It pam_acct_mgmt
+On systems that use PAM for authentication,
+.Nm sudo
+will perform PAM account validation for the invoking user by default.
+The actual checks performed depend on which PAM modules are configured.
+If enabled, account validation will be performed regardless of whether
+or not a password is required.
+This flag is
+.Em on
+by default.
+.Pp
+This setting is only supported by version 1.8.28 or higher.
+.It pam_rhost
+On systems that use PAM for authentication,
+.Nm sudo
+will set the PAM remote host value to the name of the local host
+when the
+.Em pam_rhost
+flag is enabled.
+On Linux systems, enabling
+.Em pam_rhost
+may result in DNS lookups of the local host name when PAM is initialized.
+On Solaris versions prior to Solaris 8,
+.Em pam_rhost
+must be enabled if
+.Em pam_ruser
+is also enabled to avoid a crash in the Solaris PAM implementation.
+.Pp
+This flag is
+.Em off
+by default on systems other than Solaris.
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.It pam_ruser
+On systems that use PAM for authentication,
+.Nm sudo
+will set the PAM remote user value to the name of the user that invoked sudo
+when the
+.Em pam_ruser
+flag is enabled.
+This flag is
+.Em on
+by default.
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.It pam_session
+On systems that use PAM for authentication,
+.Nm sudo
+will create a new PAM session for the command to be run in.
+Unless
+.Nm sudo
+is given the
+.Fl i
+or
+.Fl s
+options, PAM session modules are run with the
+.Dq silent
+flag enabled.
+This prevents last login information from being displayed for every
+command on some systems.
+Disabling
+.Em pam_session
+may be needed on older PAM implementations or on operating systems where
+opening a PAM session changes the utmp or wtmp files.
+If PAM session support is disabled, resource limits may not be updated
+for the command being run.
+If
+.Em pam_session ,
+.Em pam_setcred ,
+and
+.Em use_pty
+are disabled,
+.Em log_servers
+has not been set and I/O logging has not been configured,
+.Nm sudo
+will execute the command directly instead of running it as a child
+process.
+This flag is
+.Em @pam_session@
+by default.
+.Pp
+This setting is only supported by version 1.8.7 or higher.
+.It pam_setcred
+On systems that use PAM for authentication,
+.Nm sudo
+will attempt to establish credentials for the target user by default,
+if supported by the underlying authentication system.
+One example of a credential is a Kerberos ticket.
+If
+.Em pam_session ,
+.Em pam_setcred ,
+and
+.Em use_pty
+are disabled,
+.Em log_servers
+has not been set and I/O logging has not been configured,
+.Nm sudo
+will execute the command directly instead of running it as a child
+process.
+This flag is
+.Em on
+by default.
+.Pp
+This setting is only supported by version 1.8.8 or higher.
+.It passprompt_override
+If set, the prompt specified by
+.Em passprompt
+or the
+.Ev SUDO_PROMPT
+environment variable will always be used and will replace the
+prompt provided by a PAM module or other authentication method.
+This flag is
+.Em off
+by default.
+.It path_info
+Normally,
+.Nm sudo
+will tell the user when a command could not be
+found in their
+.Ev PATH
+environment variable.
+Some sites may wish to disable this as it could be used to gather
+information on the location of executables that the normal user does
+not have access to.
+The disadvantage is that if the executable is simply not in the user's
+.Ev PATH ,
+.Nm sudo
+will tell the user that they are not allowed to run it, which can be confusing.
+This flag is
+.Em @path_info@
+by default.
+.It preserve_groups
+By default,
+.Nm sudo
+will initialize the group vector to the list of groups the target user is in.
+When
+.Em preserve_groups
+is set, the user's existing group vector is left unaltered.
+The real and effective group-IDs, however, are still set to match the
+target user.
+This flag is
+.Em off
+by default.
+.It pwfeedback
+By default,
+.Nm sudo
+reads the password like most other Unix programs,
+by turning off echo until the user hits the return (or enter) key.
+Some users become confused by this as it appears to them that
+.Nm sudo
+has hung at this point.
+When
+.Em pwfeedback
+is set,
+.Nm sudo
+will provide visual feedback when the user presses a key.
+This does have a security impact as an onlooker may be able to
+determine the length of the password being entered.
+This flag is
+.Em off
+by default.
+.It requiretty
+If set,
+.Nm sudo
+will only run when the user is logged in to a real tty.
+When this flag is set,
+.Nm sudo
+can only be run from a login session and not via other means such as
+.Xr cron @mansectsu@
+or cgi-bin scripts.
+This flag is
+.Em off
+by default.
+.It root_sudo
+If set,
+.Sy root
+is allowed to run
+.Nm sudo
+too.
+Disabling this prevents users from
+.Dq chaining
+.Nm sudo
+commands to get a
+.Sy root
+shell by doing something like
+.Ql sudo sudo /bin/sh .
+Note, however, that turning off
+.Em root_sudo
+will also prevent
+.Sy root
+from running
+.Nm sudoedit .
+Disabling
+.Em root_sudo
+provides no real additional security; it exists purely for historical reasons.
+This flag is
+.Em @root_sudo@
+by default.
+.It rootpw
+If set,
+.Nm sudo
+will prompt for the
+.Sy root
+password instead of the password of the invoking user
+when running a command or editing a file.
+This flag is
+.Em off
+by default.
+.It runas_allow_unknown_id
+If enabled, allow matching of runas user and group IDs that are
+not present in the password or group databases.
+In addition to explicitly matching unknown user or group IDs in a
+.Em Runas_List ,
+this option also allows the
+.Sy ALL
+alias to match unknown IDs.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.8.30 or higher.
+Older versions of
+.Nm sudo
+always allowed matching of unknown user and group IDs.
+.It runas_check_shell
+If enabled,
+.Nm sudo
+will only run commands as a user whose shell appears in the
+.Pa /etc/shells
+file, even if the invoking user's
+.Em Runas_List
+would otherwise permit it.
+If no
+.Pa /etc/shells
+file is present, a system-dependent list of built-in default shells is used.
+On many operating systems, system users such as
+.Dq bin ,
+do not have a valid shell and this flag can be used to prevent
+commands from being run as those users.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.8.30 or higher.
+.It runaspw
+If set,
+.Nm sudo
+will prompt for the password of the user defined by the
+.Em runas_default
+option (defaults to
+.Sy @runas_default@ )
+instead of the password of the invoking user
+when running a command or editing a file.
+This flag is
+.Em off
+by default.
+.if \n(SL \{\
+.It selinux
+If enabled, the user may specify an SELinux role and/or type to use
+when running the command, as permitted by the SELinux policy.
+If SELinux is disabled on the system, this flag has no effect.
+This flag is
+.Em on
+by default.
+.\}
+.It set_home
+If enabled and
+.Nm sudo
+is invoked with the
+.Fl s
+option, the
+.Ev HOME
+environment variable will be set to the home directory of the target
+user (which is the
+.Em runas_default
+user unless the
+.Fl u
+option is used).
+This flag is largely obsolete and has no effect unless the
+.Em env_reset
+flag has been disabled or
+.Ev HOME
+is present in the
+.Em env_keep
+list, both of which are strongly discouraged.
+This flag is
+.Em off
+by default.
+.It set_logname
+Normally,
+.Nm sudo
+will set the
+.Ev LOGNAME
+and
+.Ev USER
+environment variables to the name of the target user (the user specified by
+.Em runas_default
+unless the
+.Fl u
+option is given).
+However, since some programs (including the RCS revision control system) use
+.Ev LOGNAME
+to determine the real identity of the user, it may be desirable to
+change this behavior.
+This can be done by negating the set_logname option.
+The
+.Em set_logname
+option will have no effect
+if the
+.Em env_reset
+option has not been disabled and the
+.Em env_keep
+list contains
+.Ev LOGNAME
+or
+.Ev USER .
+This flag is
+.Em on
+by default.
+.It set_utmp
+When enabled,
+.Nm sudo
+will create an entry in the utmp (or utmpx) file when a pseudo-terminal
+is allocated.
+A pseudo-terminal is allocated by
+.Nm sudo
+when it is running in a terminal and one or more of the
+.Em log_input ,
+.Em log_output ,
+.Em log_stdin ,
+.Em log_stdout ,
+.Em log_stderr ,
+.Em log_ttyin ,
+.Em log_ttyout ,
+or
+.Em use_pty
+flags is enabled.
+By default, the new entry will be a copy of the user's existing utmp
+entry (if any), with the tty, time, type, and pid fields updated.
+This flag is
+.Em on
+by default.
+.It setenv
+Allow the user to disable the
+.Em env_reset
+option from the command line via the
+.Fl E
+option.
+Additionally, environment variables set via the command line are
+not subject to the restrictions imposed by
+.Em env_check ,
+.Em env_delete ,
+or
+.Em env_keep .
+As such, only trusted users should be allowed to set variables in this manner.
+This flag is
+.Em off
+by default.
+.It shell_noargs
+If set and
+.Nm sudo
+is invoked with no arguments it acts as if the
+.Fl s
+option had been given.
+That is, it runs a shell as
+.Sy root
+(the shell is determined by the
+.Ev SHELL
+environment variable if it is set, falling back on the shell listed
+in the invoking user's /etc/passwd entry if not).
+This flag is
+.Em off
+by default.
+.It stay_setuid
+Normally, when
+.Nm sudo
+executes a command the real and effective user-IDs are set to the target
+user
+.Sy ( @runas_default@
+by default).
+This option changes that behavior such that the real user-ID is left
+as the invoking user's user-ID.
+In other words, this makes
+.Nm sudo
+act as a set-user-ID wrapper.
+This can be useful on systems that disable some potentially
+dangerous functionality when a program is run set-user-ID.
+This option is only effective on systems that support either the
+.Xr setreuid 2
+or
+.Xr setresuid 2
+system call.
+This flag is
+.Em off
+by default.
+.It sudoedit_checkdir
+If set,
+.Nm sudoedit
+will check all directory components of the path to be edited for writability
+by the invoking user.
+Symbolic links will not be followed in writable directories and
+.Nm sudoedit
+will refuse to edit a file located in a writable directory.
+These restrictions are not enforced when
+.Nm sudoedit
+is run by
+.Sy root .
+On some systems, if all directory components of the path to be edited
+are not readable by the target user,
+.Nm sudoedit
+will be unable to edit the file.
+This flag is
+.Em on
+by default.
+.Pp
+This setting was first introduced in version 1.8.15 but initially
+suffered from a race condition.
+The check for symbolic links in writable intermediate directories
+was added in version 1.8.16.
+.It sudoedit_follow
+By default,
+.Nm sudoedit
+will not follow symbolic links when opening files.
+The
+.Em sudoedit_follow
+option can be enabled to allow
+.Nm sudoedit
+to open symbolic links.
+It may be overridden on a per-command basis by the
+.Dv FOLLOW
+and
+.Dv NOFOLLOW
+tags.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.8.15 or higher.
+.It syslog_pid
+When logging via
+.Xr syslog 3 ,
+include the process ID in the log entry.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.8.21 or higher.
+.It targetpw
+If set,
+.Nm sudo
+will prompt for the password of the user specified
+by the
+.Fl u
+option (defaults to the value of
+.Em runas_default )
+instead of the password of the invoking user
+when running a command or editing a file.
+This flag precludes the use of a user-ID not listed in the passwd
+database as an argument to the
+.Fl u
+option.
+This flag is
+.Em off
+by default.
+.It tty_tickets
+If set, users must authenticate on a per-tty basis.
+With this flag enabled,
+.Nm sudo
+will use a separate record in the time stamp file for each terminal.
+If disabled, a single record is used for all login sessions.
+.Pp
+This option has been superseded by the
+.Em timestamp_type
+option.
+.It umask_override
+If set,
+.Nm sudo
+will set the umask as specified in the
+.Em sudoers
+file without modification.
+This makes it possible to specify a umask in the
+.Em sudoers
+file that is more permissive than the user's own umask and matches
+historical behavior.
+If
+.Em umask_override
+is not set,
+.Nm sudo
+will set the umask to be the union of the user's umask and what is specified in
+.Em sudoers .
+This flag is
+.Em @umask_override@
+by default.
+.if \n(LC \{\
+.It use_loginclass
+If set,
+.Nm sudo
+will apply the defaults specified for the target user's login class
+if one exists.
+Only available if
+.Nm sudo
+is configured with the
+.Li --with-logincap
+option.
+This flag is
+.Em off
+by default.
+.\}
+.It use_netgroups
+If set, netgroups (prefixed with
+.Ql + ) ,
+may be used in place of a user or host.
+For LDAP-based sudoers, netgroup support requires an expensive
+sub-string match on the server unless the
+.Sy NETGROUP_BASE
+directive is present in the
+.Pa @ldap_conf@
+file.
+If netgroups are not needed, this option can be disabled to reduce the
+load on the LDAP server.
+This flag is
+.Em on
+by default.
+.It use_pty
+If set, and
+.Nm sudo
+is running in a terminal, the command will be run in a new pseudo-terminal.
+If the
+.Nm sudo
+process is not attached to a terminal,
+.Em use_pty
+has no effect.
+.Pp
+A malicious program run under
+.Nm sudo
+may be capable of injecting commands into the user's
+terminal or running a background process that retains access to the
+user's terminal device even after the main program has finished
+executing.
+By running the command in a separate pseudo-terminal, this attack is
+no longer possible.
+This flag is
+.Em on
+by default for
+.Nm sudo
+1.9.14 and above.
+.It user_command_timeouts
+If set, the user may specify a timeout on the command line.
+If the timeout expires before the command has exited, the
+command will be terminated.
+If a timeout is specified both in the
+.Pa sudoers
+file and on the command line, the smaller of the two timeouts will be used.
+See the
+.Em Timeout_Spec
+section for a description of the timeout syntax.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.8.20 or higher.
+.It utmp_runas
+If set,
+.Nm sudo
+will store the name of the runas user when updating the utmp (or utmpx) file.
+By default,
+.Nm sudo
+stores the name of the invoking user.
+This flag is
+.Em off
+by default.
+.It visiblepw
+By default,
+.Nm sudo
+will refuse to run if the user must enter a password but it is not
+possible to disable echo on the terminal.
+If the
+.Em visiblepw
+flag is set,
+.Nm sudo
+will prompt for a password even when it would be visible on the screen.
+This makes it possible to run things like
+.Ql ssh somehost sudo ls
+since by default,
+.Xr ssh 1
+does
+not allocate a tty when running a command.
+This flag is
+.Em off
+by default.
+.El
+.Pp
+.Sy Integers :
+.Bl -tag -width 16n
+.It closefrom
+Before it executes a command,
+.Nm sudo
+will close all open file descriptors other than standard input,
+standard output, and standard error (file descriptors 0-2).
+The
+.Em closefrom
+option can be used to specify a different file descriptor at which
+to start closing.
+The default is 3.
+.It command_timeout
+The maximum amount of time a command is allowed to run before
+it is terminated.
+See the
+.Em Timeout_Spec
+section for a description of the timeout syntax.
+.Pp
+This setting is only supported by version 1.8.20 or higher.
+.It log_server_timeout
+The maximum amount of time to wait when connecting to a log server
+or waiting for a server response.
+See the
+.Em Timeout_Spec
+section for a description of the timeout syntax.
+The default value is 30 seconds.
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.It maxseq
+The maximum sequence number that will be substituted for the
+.Ql %{seq}
+escape in the I/O log file (see the
+.Em iolog_dir
+description below for more information).
+While the value substituted for
+.Ql %{seq}
+is in base 36,
+.Em maxseq
+itself should be expressed in decimal.
+Values larger than 2176782336 (which corresponds to the
+base 36 sequence number
+.Dq ZZZZZZ )
+will be silently truncated to 2176782336.
+The default value is 2176782336.
+.Pp
+Once the local sequence number reaches the value of
+.Em maxseq ,
+it will
+.Dq roll over
+to zero, after which
+.Nm
+will truncate and re-use any existing I/O log path names.
+.Pp
+This setting is only supported by version 1.8.7 or higher.
+.It passwd_tries
+The number of tries a user gets to enter his/her password before
+.Nm sudo
+logs the failure and exits.
+The default is @passwd_tries@.
+.It syslog_maxlen
+On many systems,
+.Xr syslog 3
+has a relatively small log buffer.
+IETF RFC 5424 states that syslog servers must support messages of
+at least 480 bytes and should support messages up to 2048 bytes.
+By default,
+.Nm
+creates log messages up to 980 bytes which corresponds to the
+historic
+.Bx
+syslog implementation which used a 1024 byte buffer
+to store the message, date, hostname, and program name.
+To prevent syslog messages from being truncated,
+.Nm
+will split up log messages that are larger than
+.Em syslog_maxlen
+bytes.
+When a message is split, additional parts will include the string
+.Dq Pq command continued
+after the user name and before the continued command line arguments.
+.Pp
+This setting is only supported by version 1.8.19 or higher.
+.El
+.Pp
+.Sy Integers that can be used in a boolean context :
+.Bl -tag -width 16n
+.It loglinelen
+Number of characters per line for the file log.
+This value is used to decide when to wrap lines for nicer log files.
+This has no effect on the syslog log file, only the file log.
+The default is @loglen@ (use 0 or negate the option to disable word wrap).
+.It passwd_timeout
+Number of minutes before the
+.Nm sudo
+password prompt times out, or 0 for no timeout.
+The timeout may include a fractional component
+if minute granularity is insufficient, for example 2.5.
+The default is @password_timeout@.
+.It timestamp_timeout
+Number of minutes that can elapse before
+.Nm sudo
+will ask for a password again.
+The timeout may include a fractional component if
+minute granularity is insufficient, for example 2.5.
+The default is @timeout@.
+Set this to 0 to always prompt for a password.
+If set to a value less than 0 the user's time stamp will not expire
+until the system is rebooted.
+This can be used to allow users to create or delete their own time stamps via
+.Ql sudo -v
+and
+.Ql sudo -k
+respectively.
+.It umask
+File mode creation mask to use when running the command.
+Negate this option or set it to 0777 to prevent
+.Nm
+from changing the umask.
+Unless the
+.Em umask_override
+flag is set, the actual umask will be the union of the
+user's umask and the value of the
+.Em umask
+setting, which defaults to @sudo_umask@.
+This guarantees that
+.Nm sudo
+never lowers the umask when running a command.
+.Pp
+If
+.Em umask
+is explicitly set in
+.Em sudoers ,
+it will override any umask setting in PAM or login.conf.
+If
+.Em umask
+is not set in
+.Em sudoers ,
+the umask specified by PAM or login.conf will take precedence.
+The umask setting in PAM is not used for
+.Nm sudoedit ,
+which does not create a new PAM session.
+.El
+.Pp
+.Sy Strings :
+.Bl -tag -width 16n
+.if \n(AA \{\
+.It apparmor_profile
+The default AppArmor profile to transition into when executing the
+command.
+The default
+.Em apparmor_profile
+can be overridden for individual
+.Em sudoers
+entries by specifying the
+.Dv APPARMOR_PROFILE
+option.
+This option is only available when sudo is built with AppArmor
+support.
+.\}
+.It authfail_message
+Message that is displayed after a user fails to authenticate.
+The message may include the
+.Ql %d
+escape which will expand to the number of failed password attempts.
+If set, it overrides the default message,
+.Dq %d incorrect password attempt(s) .
+.It badpass_message
+Message that is displayed if a user enters an incorrect password.
+The default is
+.Dq @badpass_message@
+unless insults are enabled.
+.It editor
+A colon
+.Pq Ql :\&
+separated list of editor path names used by
+.Nm sudoedit
+and
+.Nm visudo .
+For
+.Nm sudoedit ,
+this list is used to find an editor when none of the
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+or
+.Ev EDITOR
+environment variables are set to an editor that exists and is executable.
+For
+.Nm visudo ,
+it is used as a white list of allowed editors;
+.Nm visudo
+will choose the editor that matches the user's
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+or
+.Ev EDITOR
+environment variable if possible, or the first editor in the
+list that exists and is executable if not.
+Unless invoked as
+.Nm sudoedit ,
+.Nm sudo
+does not preserve the
+.Ev SUDO_EDITOR ,
+.Ev VISUAL
+or
+.Ev EDITOR
+environment variables unless they are present in the
+.Em env_keep
+list or the
+.Em env_reset
+option is disabled.
+The default is
+.Pa @editor@ .
+.It intercept_type
+The underlying mechanism used by the
+.Em intercept
+and
+.Em log_subcmds
+options.
+It has the following possible values:
+.Bl -tag -width 6n
+.It dso
+Preload a dynamic shared object (shared library) that intercepts the
+.Xr execve 2 ,
+.Xr execl 3 ,
+.Xr execle 3 ,
+.Xr execlp 3 ,
+.Xr execv 3 ,
+.Xr execvp 3 ,
+.Xr execvpe 3 ,
+and
+.Xr system 3
+library functions.
+A value of
+.Em dso
+is incompatible with
+.Nm sudo Ns 's
+SELinux RBAC support.
+.It trace
+Use
+.Xr ptrace 2
+to intercept the
+.Xr execve 2
+system call.
+This is only supported on Linux systems where
+.Xr seccomp 2
+filtering is enabled.
+If the
+.Pa /proc/sys/kernel/seccomp/actions_avail
+file is missing or does not contain a
+.Dq trap
+element, setting
+.Em intercept_type
+to
+.Em trace
+will have no effect and
+.Em dso
+will be used instead.
+.El
+.Pp
+The default is to use
+.Em trace
+if it is supported by the system and
+.Em dso
+if it is not.
+.It iolog_dir
+The top-level directory to use when constructing the path name for
+the input/output log directory.
+Only used if the
+.Em log_input
+or
+.Em log_output
+options are enabled or when the
+.Dv LOG_INPUT
+or
+.Dv LOG_OUTPUT
+tags are present for a command.
+The session sequence number, if any, is stored in the directory.
+The default is
+.Pa @iolog_dir@ .
+.Pp
+The following percent
+.Pq Ql %
+escape sequences are supported:
+.Bl -tag -width 4n
+.It %{seq}
+expanded to a monotonically increasing base-36 sequence number, such as 0100A5,
+where every two digits are used to form a new directory, e.g.,
+.Pa 01/00/A5
+.It %{user}
+expanded to the invoking user's login name
+.It %{group}
+expanded to the name of the invoking user's real group-ID
+.It %{runas_user}
+expanded to the login name of the user the command will
+be run as (e.g.,
+.Sy root )
+.It %{runas_group}
+expanded to the group name of the user the command will
+be run as (e.g.,
+.Sy wheel )
+.It %{hostname}
+expanded to the local host name without the domain name
+.It %{command}
+expanded to the base name of the command being run
+.El
+.Pp
+In addition, any escape sequences supported by the system's
+.Xr strftime 3
+function will be expanded.
+.Pp
+To include a literal
+.Ql %
+character, the string
+.Ql %%
+should be used.
+.Pp
+Any path name separator characters
+.Pq Ql /
+present in the user, group or host name will be replaced with an underbar
+.Pq Ql _
+during expansion.
+.It iolog_file
+The path name, relative to
+.Em iolog_dir ,
+in which to store input/output logs when the
+.Em log_input
+or
+.Em log_output
+options are enabled or when the
+.Dv LOG_INPUT
+or
+.Dv LOG_OUTPUT
+tags are present for a command.
+.Em iolog_file
+may contain directory components.
+The default is
+.Ql %{seq} .
+.Pp
+See the
+.Em iolog_dir
+option above for a list of supported percent
+.Pq Ql %
+escape sequences.
+.Pp
+In addition to the escape sequences, path names that end in six or
+more
+.Em X Ns s
+will have the
+.Em X Ns s
+replaced with a unique combination of digits and letters, similar to the
+.Xr mktemp 3
+function.
+.Pp
+If the path created by concatenating
+.Em iolog_dir
+and
+.Em iolog_file
+already exists, the existing I/O log file will be truncated and
+overwritten unless
+.Em iolog_file
+ends in six or
+more
+.Em X Ns s .
+.It iolog_flush
+If set,
+.Nm sudo
+will flush I/O log data to disk after each write instead of buffering it.
+This makes it possible to view the logs in real-time as the program
+is executing but may significantly reduce the effectiveness of I/O
+log compression.
+This flag is
+.Em off
+by default.
+.Pp
+This setting is only supported by version 1.8.20 or higher.
+.It iolog_group
+The group name to look up when setting the group-ID on new I/O log
+files and directories.
+If
+.Em iolog_group
+is not set,
+the primary group-ID of the user specified by
+.Em iolog_user
+is used.
+If neither
+.Em iolog_group
+nor
+.Em iolog_user
+are set, I/O log files and directories are created with group-ID 0.
+.Pp
+This setting is only supported by version 1.8.19 or higher.
+.It iolog_mode
+The file mode to use when creating I/O log files.
+Mode bits for read and write permissions for owner, group, or other
+are honored, everything else is ignored.
+The file permissions will always include the owner read and
+write bits, even if they are not present in the specified mode.
+When creating I/O log directories, search (execute) bits are added
+to match the read and write bits specified by
+.Em iolog_mode .
+Defaults to 0600 (read and write by user only).
+.Pp
+This setting is only supported by version 1.8.19 or higher.
+.It iolog_user
+The user name to look up when setting the user and group-IDs on new
+I/O log files and directories.
+If
+.Em iolog_group
+is set, it will be used instead of the user's primary group-ID.
+By default, I/O log files and directories are created with user and
+group-ID 0.
+.Pp
+This setting can be useful when the I/O logs are stored on a Network
+File System (NFS) share.
+Having a dedicated user own the I/O log files means that
+.Nm
+does not write to the log files as user-ID 0, which is usually
+not permitted by NFS.
+.Pp
+This setting is only supported by version 1.8.19 or higher.
+.It lecture_status_dir
+The directory in which
+.Nm sudo
+stores per-user lecture status files.
+Once a user has received the lecture, a zero-length file is
+created in this directory so that
+.Nm sudo
+will not lecture the user again.
+This directory should
+.Em not
+be cleared when the system reboots.
+The default is
+.Pa @vardir@/lectured .
+.if \n(PS \{\
+.It limitprivs
+The default Solaris limit privileges to use when constructing a new
+privilege set for a command.
+This bounds all privileges of the executing process.
+The default limit privileges may be overridden on a per-command basis in
+.Em sudoers .
+This option is only available if
+.Nm
+is built on Solaris 10 or higher.
+.\}
+.It log_server_cabundle
+The path to a certificate authority bundle file, in PEM format,
+to use instead of the system's default certificate authority database
+when authenticating the log server.
+The default is to use the system's default certificate authority database.
+This setting has no effect unless
+.Em log_servers
+is set and the remote log server is secured with TLS.
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.It log_server_peer_cert
+The path to the
+.Nm sudo
+client's certificate file, in PEM format.
+This setting is required when the remote log server is secured
+with TLS and client certificate validation is enabled.
+For
+.Nm sudo_logsrvd ,
+client certificate validation is controlled by the
+.Em tls_checkpeer
+option, which defaults to
+.Em false .
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.It log_server_peer_key
+The path to the
+.Nm sudo
+client's private key file, in PEM format.
+This setting is required when the remote log server is secured
+with TLS and client certificate validation is enabled.
+For
+.Nm sudo_logsrvd ,
+client certificate validation is controlled by the
+.Em tls_checkpeer
+flag, which defaults to
+.Em false .
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.It mailsub
+Subject of the mail sent to the
+.Em mailto
+user.
+The escape
+.Ql %h
+will expand to the host name of the machine.
+Default is
+.Dq @mailsub@ .
+.It noexec_file
+As of
+.Nm sudo
+version 1.8.1 this option is no longer supported.
+The path to the noexec file should now be set in the
+.Xr sudo.conf @mansectform@
+file.
+.It pam_askpass_service
+On systems that use PAM for authentication, this is the service
+name used when the
+.Fl A
+option is specified.
+The default value is either
+.Ql sudo
+or
+.Ql @pam_login_service@ ,
+depending on whether or not the
+.Fl i
+option is also specified.
+See the description of
+.Em pam_service
+for more information.
+.Pp
+This setting is only supported by version 1.9.9 or higher.
+.It pam_login_service
+On systems that use PAM for authentication, this is the service
+name used when the
+.Fl i
+option is specified.
+The default value is
+.Ql @pam_login_service@ .
+See the description of
+.Em pam_service
+for more information.
+.Pp
+This setting is only supported by version 1.8.8 or higher.
+.It pam_service
+On systems that use PAM for authentication, the service name
+specifies the PAM policy to apply.
+This usually corresponds to an entry in the
+.Pa pam.conf
+file or a file in the
+.Pa /etc/pam.d
+directory.
+The default value is
+.Ql sudo .
+.Pp
+This setting is only supported by version 1.8.8 or higher.
+.It passprompt
+The default prompt to use when asking for a password; can be overridden via the
+.Fl p
+option or the
+.Ev SUDO_PROMPT
+environment variable.
+The following percent
+.Pq Ql %
+escape sequences are supported:
+.Bl -tag -width 4n
+.It %H
+expanded to the local host name including the domain name
+(only if the machine's host name is fully qualified or the
+.Em fqdn
+option is set)
+.It %h
+expanded to the local host name without the domain name
+.It %p
+expanded to the user whose password is being asked for (respects the
+.Em rootpw ,
+.Em targetpw
+and
+.Em runaspw
+flags in
+.Em sudoers )
+.It \&%U
+expanded to the login name of the user the command will
+be run as (defaults to
+.Sy @runas_default@ )
+.It %u
+expanded to the invoking user's login name
+.It %%
+two consecutive
+.Ql %
+characters are collapsed into a single
+.Ql %
+character
+.El
+.Pp
+On systems that use PAM for authentication,
+.Em passprompt
+will only be used if the prompt provided by the PAM module matches the string
+.Dq "Password: "
+or
+.Dq "username's Password: " .
+This ensures that the
+.Em passprompt
+setting does not interfere with challenge-response style authentication.
+The
+.Em passprompt_override
+flag can be used to change this behavior.
+.Pp
+The default value is
+.Ql "@passprompt@" .
+.if \n(PS \{\
+.It privs
+The default Solaris privileges to use when constructing a new
+privilege set for a command.
+This is passed to the executing process via the inherited privilege set,
+but is bounded by the limit privileges.
+If the
+.Em privs
+option is specified but the
+.Em limitprivs
+option is not, the limit privileges of the executing process is set to
+.Em privs .
+The default privileges may be overridden on a per-command basis in
+.Em sudoers .
+This option is only available if
+.Nm
+is built on Solaris 10 or higher.
+.\}
+.if \n(SL \{\
+.It role
+The default SELinux role to use when constructing a new security
+context to run the command.
+The default role may be overridden on a per-command basis in the
+.Em sudoers
+file or via command line options.
+This option is only available when
+.Nm sudo
+is built with SELinux support.
+.\}
+.It runas_default
+The default user to run commands as if the
+.Fl u
+option is not specified on the command line.
+This defaults to
+.Sy @runas_default@ .
+.It sudoers_locale
+Locale to use when parsing the sudoers file, logging commands, and
+sending email.
+Changing the locale may affect how sudoers is interpreted.
+Defaults to
+.Ql C .
+.It timestamp_type
+.Nm
+uses per-user time stamp files for credential caching.
+The
+.Em timestamp_type
+option can be used to specify the type of time stamp record used.
+It has the following possible values:
+.Bl -tag -width 6n
+.It global
+A single time stamp record is used for all of a user's login sessions,
+regardless of the terminal or parent process ID.
+An additional record is used to serialize password prompts when
+.Nm sudo
+is used multiple times in a pipeline, but this does not affect authentication.
+.It ppid
+A single time stamp record is used for all processes with the same parent
+process ID (usually the shell).
+Commands run from the same shell (or other common parent process)
+will not require a password for
+.Em timestamp_timeout
+minutes (@timeout@ by default).
+Commands run via
+.Nm sudo
+with a different parent process ID, for example from a shell script,
+will be authenticated separately.
+.It tty
+One time stamp record is used for each terminal,
+which means that a user's login sessions are authenticated separately.
+If no terminal is present, the behavior is the same as
+.Em ppid .
+Commands run from the same terminal will not require a password for
+.Em timestamp_timeout
+minutes (@timeout@ by default).
+.It kernel
+The time stamp is stored in the kernel as an attribute of the terminal
+device.
+If no terminal is present, the behavior is the same as
+.Em ppid .
+Negative
+.Em timestamp_timeout
+values are not supported and positive values are limited to a maximum
+of 60 minutes.
+This is currently only supported on
+.Ox .
+.El
+.Pp
+The default value is
+.Em @timestamp_type@ .
+.Pp
+This setting is only supported by version 1.8.21 or higher.
+.It timestampdir
+The directory in which
+.Nm sudo
+stores its time stamp files.
+This directory should be cleared when the system reboots.
+The default is
+.Pa @rundir@/ts .
+.It timestampowner
+The owner of the lecture status directory, time stamp directory and all
+files stored therein.
+The default is
+.Sy root .
+.if \n(SL \{\
+.It type
+The default SELinux type to use when constructing a new security
+context to run the command.
+The default type may be overridden on a per-command basis in the
+.Em sudoers
+file or via command line options.
+This option is only available when
+.Nm sudo
+is built with SELinux support.
+.\}
+.El
+.Pp
+.Sy Strings that can be used in a boolean context :
+.Bl -tag -width 12n
+.It admin_flag
+The
+.Em admin_flag
+option specifies the path to a file that is created the first time
+a user that is a member of the
+.Em sudo
+or
+.Em admin
+groups runs
+.Nm sudo .
+Only available if
+.Nm sudo
+is configured with the
+.Li --enable-admin-flag
+option.
+The default value is
+.Pa ~/.sudo_as_admin_successful .
+.It env_file
+The
+.Em env_file
+option specifies the fully qualified path to a file containing variables
+to be set in the environment of the program being run.
+Entries in this file should either be of the form
+.Ql VARIABLE=value
+or
+.Ql export VARIABLE=value .
+The value may optionally be enclosed in single or double quotes.
+Variables in this file are only added if the variable does not already
+exist in the environment.
+This file is considered to be part of the security policy,
+its contents are not subject to other
+.Nm sudo
+environment restrictions such as
+.Em env_keep
+and
+.Em env_check .
+.It exempt_group
+Users in this group are exempt from password and PATH requirements.
+The group name specified should not include a
+.Ql %
+prefix.
+This is not set by default.
+.It fdexec
+Determines whether
+.Nm sudo
+will execute a command by its path or by an open file descriptor.
+It has the following possible values:
+.Bl -tag -width 6n
+.It always
+Always execute by file descriptor.
+.It never
+Never execute by file descriptor.
+.It digest_only
+Only execute by file descriptor if the command has an associated digest
+in the
+.Em sudoers
+file.
+.El
+.Pp
+The default value is
+.Em digest_only .
+This avoids a time of check versus time of use race condition when
+the command is located in a directory writable by the invoking user.
+.Pp
+.Em fdexec
+will change the first element of the argument vector for scripts
+($0 in the shell) due to the way the kernel runs script interpreters.
+Instead of being a normal path, it will refer to a file descriptor.
+For example,
+.Pa /dev/fd/4
+on Solaris and
+.Pa /proc/self/fd/4
+on Linux.
+A workaround is to use the
+.Dv SUDO_COMMAND
+environment variable instead.
+.Pp
+The
+.Em fdexec
+setting is only used when the command is matched by path name.
+It has no effect if the command is matched by the built-in
+.Sy ALL
+alias.
+.Pp
+This setting is only supported by version 1.8.20 or higher.
+If the operating system does not support the
+.Xr fexecve 2
+system call, this setting has no effect.
+.It group_plugin
+A string containing a
+.Nm
+group plugin with optional arguments.
+The string should consist of the plugin
+path, either fully-qualified or relative to the
+.Pa @plugindir@
+directory, followed by any configuration arguments the plugin requires.
+These arguments (if any) will be passed to the plugin's initialization function.
+If arguments are present, the string must be enclosed in double quotes
+.Pq \&"" .
+.Pp
+On 64-bit systems, if the plugin is present but cannot be loaded,
+.Nm
+will look for a 64-bit version and, if it exists, load that as a fallback.
+The exact rules for this vary by system.
+On Solaris, if the plugin is stored in a directory ending in
+.Dq lib ,
+.Nm
+will create a fallback path by appending
+.Dq /64
+to the directory name;
+.Pa @prefix@/lib/group_plugin.so
+becomes
+.Pa @prefix@/lib/64/group_plugin.so .
+On Linux, a directory ending in
+.Dq lib
+will be transformed to
+.Dq lib64
+as the fallback path;
+.Pa @prefix@/lib/group_plugin.so
+becomes
+.Pa @prefix@/lib64/group_plugin.so .
+On all other systems, the fallback path is generated by adding a
+.Dq 64
+before the file extension;
+.Pa group_plugin.so
+becomes
+.Pa group_plugin64.so .
+.Pp
+On AIX systems, the plugin may be either a shared object
+ending in
+.Ql .so
+or an archive file containing a shared object ending in
+.Ql .a
+with the name of the shared object in parentheses at the end.
+.Pp
+For more information see
+.Sx "GROUP PROVIDER PLUGINS" .
+.It lecture
+This option controls when a short lecture will be printed along with
+the password prompt.
+It has the following possible values:
+.Bl -tag -width 6n
+.It always
+Always lecture the user.
+.It never
+Never lecture the user.
+.It once
+Only lecture the user the first time they run
+.Nm sudo .
+.El
+.Pp
+If no value is specified, a value of
+.Em once
+is implied.
+Negating the option results in a value of
+.Em never
+being used.
+The default value is
+.Em @lecture@ .
+.It lecture_file
+Path to a file containing an alternate
+.Nm sudo
+lecture that will be used in place of the standard lecture if the named
+file exists.
+By default,
+.Nm sudo
+uses a built-in lecture.
+.It listpw
+This option controls when a password will be required when a user runs
+.Nm sudo
+with the
+.Fl l
+option.
+It has the following possible values:
+.Bl -tag -width 4n
+.It all
+All the user's
+.Em sudoers
+file entries for the current host must have
+the
+.Dv NOPASSWD
+flag set to avoid entering a password.
+.It always
+The user must always enter a password to use the
+.Fl l
+option.
+.It any
+At least one of the user's
+.Em sudoers
+file entries for the current host
+must have the
+.Dv NOPASSWD
+flag set to avoid entering a password.
+.It never
+The user need never enter a password to use the
+.Fl l
+option.
+.El
+.Pp
+If no value is specified, a value of
+.Em any
+is implied.
+Negating the option results in a value of
+.Em never
+being used.
+The default value is
+.Em any .
+.It log_format
+The event log format.
+Supported log formats are:
+.Bl -tag -width 4n
+.It json
+Logs in JSON format.
+JSON log entries contain the full user details as well as the execution
+environment if the command was allowed.
+Due to limitations of the protocol, JSON events sent via
+.Em syslog
+may be truncated.
+.It sudo
+Traditional sudo-style logs, see
+.Sx "EVENT LOGGING"
+for a description of the log file format.
+.El
+.Pp
+This setting affects logs sent via
+.Xr syslog 3
+as well as the file specified by the
+.Em logfile
+setting, if any.
+The default value is
+.Em sudo .
+.It logfile
+Path to the
+.Nm sudo
+log file (not the syslog log file).
+Setting a path turns on logging to a file;
+negating this option turns it off.
+By default,
+.Nm sudo
+logs via syslog.
+.It mailerflags
+Flags to use when invoking mailer.
+Defaults to
+.Fl t .
+.It mailerpath
+Path to mail program used to send warning mail (negate to prevent
+.Nm sudo
+from sending mail).
+Defaults to the path to sendmail found at configure time.
+.It mailfrom
+Address to use for the
+.Dq from
+address when sending warning and error mail.
+The address should be enclosed in double quotes
+.Pq \&""
+to protect against
+.Nm sudo
+interpreting the
+.Ql @
+sign.
+Defaults to the name of the user running
+.Nm sudo .
+.It mailto
+Address to send warning and error mail to (negate to prevent
+.Nm sudo
+from sending mail).
+The address should be enclosed in double quotes
+.Pq \&""
+to protect against
+.Nm sudo
+interpreting the
+.Ql @
+sign.
+Defaults to @mailto@.
+.It rlimit_as
+The maximum size to which the process's address space may grow (in bytes),
+if supported by the operating system.
+See
+.Sx "Resource limits"
+for more information.
+.It rlimit_core
+The largest size core dump file that may be created (in bytes).
+See
+.Sx "Resource limits"
+for more information.
+Defaults to 0 (no core dump created).
+.It rlimit_cpu
+The maximum amount of CPU time that the process may use (in seconds).
+See
+.Sx "Resource limits"
+for more information.
+.It rlimit_data
+The maximum size of the data segment for the process (in bytes).
+See
+.Sx "Resource limits"
+for more information.
+.It rlimit_fsize
+The largest size file that the process may create (in bytes).
+See
+.Sx "Resource limits"
+for more information.
+.It rlimit_locks
+The maximum number of locks that the process may establish,
+if supported by the operating system.
+See
+.Sx "Resource limits"
+for more information.
+.It rlimit_memlock
+The maximum size that the process may lock in memory (in bytes),
+if supported by the operating system.
+See
+.Sx "Resource limits"
+for more information.
+.It rlimit_nofile
+The maximum number of files that the process may have open.
+See
+.Sx "Resource limits"
+for more information.
+.It rlimit_nproc
+The maximum number of processes that the user may run simultaneously.
+See
+.Sx "Resource limits"
+for more information.
+.It rlimit_rss
+The maximum size to which the process's resident set size may grow (in bytes).
+See
+.Sx "Resource limits"
+for more information.
+.It rlimit_stack
+The maximum size to which the process's stack may grow (in bytes).
+See
+.Sx "Resource limits"
+for more information.
+.It restricted_env_file
+The
+.Em restricted_env_file
+option specifies the fully qualified path to a file containing variables
+to be set in the environment of the program being run.
+Entries in this file should either be of the form
+.Ql VARIABLE=value
+or
+.Ql export VARIABLE=value .
+The value may optionally be enclosed in single or double quotes.
+Variables in this file are only added if the variable does not already
+exist in the environment.
+Unlike
+.Em env_file ,
+the file's contents are not trusted and are processed in a manner
+similar to that of the invoking user's environment.
+If
+.Em env_reset
+is enabled, variables in the file will only be added if they are
+matched by either the
+.Em env_check
+or
+.Em env_keep
+list.
+If
+.Em env_reset
+is disabled, variables in the file are added as long as they
+are not matched by the
+.Em env_delete
+list.
+In either case, the contents of
+.Em restricted_env_file
+are processed before the contents of
+.Em env_file .
+.It runchroot
+If set,
+.Nm sudo
+will use this value for the root directory when running a command.
+The special value
+.Dq *
+will allow the user to specify the root directory via
+.Nm sudo Ns 's
+.Fl R
+option.
+See the
+.Sx Chroot_Spec
+section for more details.
+.Pp
+It is only possible to use
+.Em runchroot
+as a command-specific Defaults setting if the command exists with
+the same path both inside and outside the chroot jail.
+This restriction does not apply to global, host, or user-based
+Defaults settings or to a
+.Em Cmnd_Spec
+that includes a
+.Em Chroot_Spec .
+.Pp
+This setting is only supported by version 1.9.3 or higher.
+.It runcwd
+If set,
+.Nm sudo
+will use this value for the working directory when running a command.
+The special value
+.Dq *
+will allow the user to specify the working directory via
+.Nm sudo Ns 's
+.Fl D
+option.
+See the
+.Sx Chdir_Spec
+section for more details.
+.Pp
+This setting is only supported by version 1.9.3 or higher.
+.It secure_path
+If set,
+.Nm sudo
+will use this value in place of the user's
+.Ev PATH
+environment variable.
+This option can be used to reset the
+.Ev PATH
+to a known good value that contains directories for system administrator
+commands such as
+.Pa /usr/sbin .
+.Pp
+Users in the group specified by the
+.Em exempt_group
+option are not affected by
+.Em secure_path .
+This option is @secure_path@ by default.
+.It syslog
+Syslog facility if syslog is being used for logging (negate to
+disable syslog logging).
+Defaults to @logfac@.
+.Pp
+The following syslog facilities are supported:
+.Sy authpriv
+(if your
+OS supports it),
+.Sy auth ,
+.Sy daemon ,
+.Sy user ,
+.Sy local0 ,
+.Sy local1 ,
+.Sy local2 ,
+.Sy local3 ,
+.Sy local4 ,
+.Sy local5 ,
+.Sy local6 ,
+and
+.Sy local7 .
+.It syslog_badpri
+Syslog priority to use when the user is not allowed to run a command or
+when authentication is unsuccessful.
+Defaults to @badpri@.
+.Pp
+The following syslog priorities are supported:
+.Sy alert ,
+.Sy crit ,
+.Sy debug ,
+.Sy emerg ,
+.Sy err ,
+.Sy info ,
+.Sy notice ,
+.Sy warning ,
+and
+.Sy none .
+Negating the option or setting it to a value of
+.Sy none
+will disable logging of unsuccessful commands.
+.It syslog_goodpri
+Syslog priority to use when the user is allowed to run a command and
+authentication is successful.
+Defaults to @goodpri@.
+.Pp
+See
+.Em syslog_badpri
+for the list of supported syslog priorities.
+Negating the option or setting it to a value of
+.Sy none
+will disable logging of successful commands.
+.It verifypw
+This option controls when a password will be required when a user runs
+.Nm sudo
+with the
+.Fl v
+option.
+It has the following possible values:
+.Bl -tag -width 6n
+.It all
+All the user's
+.Em sudoers
+file entries for the current host must have the
+.Dv NOPASSWD
+flag set to avoid entering a password.
+.It always
+The user must always enter a password to use the
+.Fl v
+option.
+.It any
+At least one of the user's
+.Em sudoers
+file entries for the current host must have the
+.Dv NOPASSWD
+flag set to avoid entering a password.
+.It never
+The user need never enter a password to use the
+.Fl v
+option.
+.El
+.Pp
+If no value is specified, a value of
+.Em all
+is implied.
+Negating the option results in a value of
+.Em never
+being used.
+The default value is
+.Em all .
+.El
+.Pp
+.Sy Lists that can be used in a boolean context :
+.Bl -tag -width 16n
+.It env_check
+Environment variables to be removed from the user's environment
+unless they are considered
+.Dq safe .
+For all variables except
+.Ev TZ ,
+.Dq safe
+means that the variable's value does not contain any
+.Ql %
+or
+.Ql /
+characters.
+This can be used to guard against printf-style format vulnerabilities
+in poorly-written programs.
+The
+.Ev TZ
+variable is considered unsafe if any of the following are true:
+.Bl -bullet -width 1n
+.It
+It consists of a fully-qualified path name,
+optionally prefixed with a colon
+.Pq Ql :\& ,
+that does not match the location of the
+.Pa zoneinfo
+directory.
+.It
+It contains a
+.Pa ..
+path element.
+.It
+It contains white space or non-printable characters.
+.It
+It is longer than the value of
+.Dv PATH_MAX .
+.El
+.Pp
+The argument may be a double-quoted, space-separated list or a
+single value without double-quotes.
+The list can be replaced, added to, deleted from, or disabled by using
+the
+.Ql = ,
+.Ql += ,
+.Ql -= ,
+and
+.Ql \&!
+operators respectively.
+Regardless of whether the
+.Em env_reset
+option is enabled or disabled, variables specified by
+.Em env_check
+will be preserved in the environment if they pass the aforementioned check.
+The global list of environment variables to check is displayed when
+.Nm sudo
+is run by
+.Sy root
+with the
+.Fl V
+option.
+.It env_delete
+Environment variables to be removed from the user's environment when the
+.Em env_reset
+option is not in effect.
+The argument may be a double-quoted, space-separated list or a
+single value without double-quotes.
+The list can be replaced, added to, deleted from, or disabled by using the
+.Ql = ,
+.Ql += ,
+.Ql -= ,
+and
+.Ql \&!
+operators respectively.
+The global list of environment variables to remove is displayed when
+.Nm sudo
+is run by
+.Sy root
+with the
+.Fl V
+option.
+Many operating systems will remove potentially dangerous variables
+from the environment of any set-user-ID process (such as
+.Nm sudo ) .
+.It env_keep
+Environment variables to be preserved in the user's environment when the
+.Em env_reset
+option is in effect.
+This allows fine-grained control over the environment
+.Nm sudo Ns -spawned
+processes will receive.
+The argument may be a double-quoted, space-separated list or a
+single value without double-quotes.
+The list can be replaced, added to, deleted from, or disabled by using the
+.Ql = ,
+.Ql += ,
+.Ql -= ,
+and
+.Ql \&!
+operators respectively.
+The global list of variables to keep
+is displayed when
+.Nm sudo
+is run by
+.Sy root
+with the
+.Fl V
+option.
+.Pp
+Preserving the
+.Ev HOME
+environment variable has security implications since many programs use it
+when searching for configuration or data files.
+Adding
+.Ev HOME
+to
+.Em env_keep
+may enable a user to run unrestricted commands via
+.Nm sudo
+and is strongly discouraged.
+Users wishing to edit files with
+.Nm sudo
+should run
+.Nm sudoedit
+(or
+.Nm sudo Fl e )
+to get their accustomed editor configuration instead of
+invoking the editor directly.
+.It log_servers
+A list of one or more servers to use for remote event and I/O log storage,
+separated by white space.
+Log servers must be running
+.Nm sudo_logsrvd
+or another service that implements the protocol described by
+.Xr sudo_logsrv.proto @mansectform@ .
+.Pp
+Server addresses should be of the form
+.Dq host Ns Oo : Ns port Oc Ns Op (tls) .
+The host portion may be a host name, an IPv4 address, or an IPv6 address
+in square brackets.
+.Pp
+If the optional
+.Em tls
+flag is present, the connection will be secured
+with Transport Layer Security (TLS) version 1.2 or 1.3.
+Versions of TLS prior to 1.2 are not supported.
+.Pp
+If a port is specified, it may either be a port number or a well-known
+service name as defined by the system service name database.
+If no port is specified, port 30343 will be used for plaintext
+connections and port 30344 will be used for TLS connections.
+.Pp
+When
+.Em log_servers
+is set, event log data will be logged both locally (see the
+.Em syslog
+and
+.Em log_file
+settings) as well as remotely, but I/O log data will only be logged remotely.
+If multiple hosts are specified, they will be attempted in reverse order.
+If no log servers are available, the user will not be able to run
+a command unless either the
+.Em ignore_iolog_errors
+flag (I/O logging enabled) or the
+.Em ignore_log_errors
+flag (I/O logging disabled) is set.
+Likewise, if the connection to the log server is interrupted while
+.Nm sudo
+is running, the command will be terminated unless the
+.Em ignore_iolog_errors
+flag (I/O logging enabled) or the
+.Em ignore_log_errors
+flag (I/O logging disabled) is set.
+.Pp
+This setting is only supported by version 1.9.0 or higher.
+.It passprompt_regex
+A list of POSIX extended regular expressions used to
+match password prompts in the terminal output.
+As an extension, if the regular expression begins with
+.Dq (?i) ,
+it will be matched in a case-insensitive manner.
+Each regular expression is limited to 1024 characters.
+This option is only used when
+.Em log_passwords
+has been disabled.
+The default value is
+.Dq [Pp]assword[: ]*
+.Pp
+This setting is only supported by version 1.9.10 or higher.
+.El
+.Sh GROUP PROVIDER PLUGINS
+The
+.Nm
+plugin supports its own plugin interface to allow non-Unix
+group lookups which can query a group source other
+than the standard Unix group database.
+This can be used to implement support for the
+.Em nonunix_group
+syntax described earlier.
+.Pp
+Group provider plugins are specified via the
+.Em group_plugin
+setting.
+The argument to
+.Em group_plugin
+should consist of the plugin path, either fully-qualified or relative to the
+.Pa @plugindir@
+directory, followed by any configuration options the plugin requires.
+These options (if specified) will be passed to the plugin's initialization
+function.
+If options are present, the string must be enclosed in double quotes
+.Pq \&"" .
+.Pp
+The following group provider plugins are installed by default:
+.Bl -tag -width 4n
+.It group_file
+The
+.Em group_file
+plugin supports an alternate group file that uses the same syntax as the
+.Pa /etc/group
+file.
+The path to the group file should be specified as an option
+to the plugin.
+For example, if the group file to be used is
+.Pa /etc/sudo-group :
+.Bd -literal
+Defaults group_plugin="group_file.so /etc/sudo-group"
+.Ed
+.It system_group
+The
+.Em system_group
+plugin supports group lookups via the standard C library functions
+.Xr getgrnam 3
+and
+.Xr getgrid 3 .
+This plugin can be used in instances where the user belongs to
+groups not present in the user's supplemental group vector.
+This plugin takes no options:
+.Bd -literal
+Defaults group_plugin=system_group.so
+.Ed
+.El
+.Pp
+The group provider plugin API is described in detail in
+.Xr sudo_plugin @mansectform@ .
+.Sh EVENT LOGGING
+.Nm
+can log events in either JSON or
+.Em sudo
+format,
+this section describes the
+.Em sudo
+log format.
+Depending on
+.Em sudoers
+configuration,
+.Nm
+can log events via
+.Xr syslog 3 ,
+to a local log file, or both.
+The log format is almost identical in both cases.
+Any control characters present in the log data are formatted in octal
+with a leading
+.Ql #
+character.
+For example, a horizontal tab is stored as
+.Ql #011
+and an embedded carriage return is stored as
+.Ql #015 .
+In addition, space characters in the command path are stored as
+.Ql #040 .
+Command line arguments that contain spaces are enclosed in single quotes
+.Pq '' .
+This makes it possible to distinguish multiple command line arguments
+from a single argument that contains spaces.
+Literal single quotes and backslash characters
+.Pq Ql \e
+in command line arguments are escaped with a backslash.
+.Ss Accepted command log entries
+Commands that sudo runs are logged using the following format (split
+into multiple lines for readability):
+.Bd -literal -offset 4n
+date hostname progname: username : TTY=ttyname ; CHROOT=chroot ; \e
+ PWD=cwd ; USER=runasuser ; GROUP=runasgroup ; TSID=logid ; \e
+ ENV=env_vars COMMAND=command
+.Ed
+.Pp
+Where the fields are as follows:
+.Bl -tag -width 12n
+.It date
+The date the command was run.
+Typically, this is in the format
+.Dq MMM, DD, HH:MM:SS .
+If logging via
+.Xr syslog 3 ,
+the actual date format is controlled by the syslog daemon.
+If logging to a file and the
+.Em log_year
+option is enabled,
+the date will also include the year.
+.It hostname
+The name of the host
+.Nm sudo
+was run on.
+This field is only present when logging via
+.Xr syslog 3 .
+.It progname
+The name of the program, usually
+.Em sudo
+or
+.Em sudoedit .
+This field is only present when logging via
+.Xr syslog 3 .
+.It username
+The login name of the user who ran
+.Nm sudo .
+.It ttyname
+The short name of the terminal (e.g.,
+.Dq console ,
+.Dq tty01 ,
+or
+.Dq pts/0 )
+.Nm sudo
+was run on, or
+.Dq unknown
+if there was no terminal present.
+.It chroot
+The root directory that the command was run in, if one was specified.
+.It cwd
+The current working directory that
+.Nm sudo
+was run in.
+.It runasuser
+The user the command was run as.
+.It runasgroup
+The group the command was run as if one was specified on the command line.
+.It logid
+An I/O log identifier that can be used to replay the command's output.
+This is only present when the
+.Em log_input
+or
+.Em log_output
+option is enabled.
+.It env_vars
+A list of environment variables specified on the command line,
+if specified.
+.It command
+The actual command that was executed, including any command line arguments.
+.El
+.Pp
+Messages are logged using the locale specified by
+.Em sudoers_locale ,
+which defaults to the
+.Ql C
+locale.
+.Ss Denied command log entries
+If the user is not allowed to run the command, the reason for the denial
+will follow the user name.
+Possible reasons include:
+.Bl -tag -width 4
+.It user NOT in sudoers
+The user is not listed in the
+.Em sudoers
+file.
+.It user NOT authorized on host
+The user is listed in the
+.Em sudoers
+file but is not allowed to run commands on the host.
+.It command not allowed
+The user is listed in the
+.Em sudoers
+file for the host but they are not allowed to run the specified command.
+.It 3 incorrect password attempts
+The user failed to enter their password after 3 tries.
+The actual number of tries will vary based on the number of
+failed attempts and the value of the
+.Em passwd_tries
+option.
+.It a password is required
+The
+.Fl n
+option was specified but a password was required.
+.It sorry, you are not allowed to set the following environment variables
+The user specified environment variables on the command line that
+were not allowed by
+.Em sudoers .
+.El
+.Ss Error log entries
+If an error occurs,
+.Nm
+will log a message and, in most cases, send a message to the
+administrator via email.
+Possible errors include:
+.Bl -tag -width 4
+.It parse error in @sysconfdir@/sudoers near line N
+.Nm
+encountered an error when parsing the specified file.
+In some cases, the actual error may be one line above or below the
+line number listed, depending on the type of error.
+.It problem with defaults entries
+The
+.Em sudoers
+file contains one or more unknown Defaults settings.
+This does not prevent
+.Nm sudo
+from running, but the
+.Em sudoers
+file should be checked using
+.Nm visudo .
+.It timestamp owner (username): \&No such user
+The time stamp directory owner, as specified by the
+.Em timestampowner
+setting, could not be found in the password database.
+.It unable to open/read @sysconfdir@/sudoers
+The
+.Em sudoers
+file could not be opened for reading.
+This can happen when the
+.Em sudoers
+file is located on a remote file system that maps user-ID 0 to
+a different value.
+Normally,
+.Nm
+tries to open the
+.Em sudoers
+file using group permissions to avoid this problem.
+Consider either changing the ownership of
+.Pa @sysconfdir@/sudoers
+or adding an argument like
+.Dq sudoers_uid=N
+(where
+.Sq N
+is the user-ID that owns the
+.Em sudoers
+file) to the end of the
+.Nm
+.Em Plugin
+line in the
+.Xr sudo.conf @mansectform@
+file.
+.It unable to open @sysconfdir@/sudoers
+The
+.Pa @sysconfdir@/sudoers
+file is missing.
+.It @sysconfdir@/sudoers is not a regular file
+The
+.Pa @sysconfdir@/sudoers
+file exists but is not a regular file or symbolic link.
+.It @sysconfdir@/sudoers is owned by uid N, should be 0
+The
+.Em sudoers
+file has the wrong owner.
+If you wish to change the
+.Em sudoers
+file owner, add
+.Dq sudoers_uid=N
+(where
+.Sq N
+is the user-ID that owns the
+.Em sudoers
+file) to the
+.Nm
+.Em Plugin
+line in the
+.Xr sudo.conf @mansectform@
+file.
+.It @sysconfdir@/sudoers is world writable
+The permissions on the
+.Em sudoers
+file allow all users to write to it.
+The
+.Em sudoers
+file must not be world-writable, the default file mode
+is 0440 (readable by owner and group, writable by none).
+The default mode may be changed via the
+.Dq sudoers_mode
+option to the
+.Nm
+.Em Plugin
+line in the
+.Xr sudo.conf @mansectform@
+file.
+.It @sysconfdir@/sudoers is owned by gid N, should be 1
+The
+.Em sudoers
+file has the wrong group ownership.
+If you wish to change the
+.Em sudoers
+file group ownership, add
+.Dq sudoers_gid=N
+(where
+.Sq N
+is the group-ID that owns the
+.Em sudoers
+file) to the
+.Nm
+.Em Plugin
+line in the
+.Xr sudo.conf @mansectform@
+file.
+.It unable to open @rundir@/ts/user-ID
+.Nm
+was unable to read or create the user's time stamp file.
+This can happen when
+.Em timestampowner
+is set to a user other than
+.Sy root
+and the mode on
+.Pa @rundir@
+is not searchable by group or other.
+The default mode for
+.Pa @rundir@
+is 0711.
+.It unable to write to @rundir@/ts/user-ID
+.Nm
+was unable to write to the user's time stamp file.
+.It @rundir@/ts is owned by uid X, should be Y
+The time stamp directory is owned by a user other than
+.Em timestampowner .
+This can occur when the value of
+.Em timestampowner
+has been changed.
+.Nm
+will ignore the time stamp directory until the owner is corrected.
+.It @rundir@/ts is group writable
+The time stamp directory is group-writable; it should be writable only by
+.Em timestampowner .
+The default mode for the time stamp directory is 0700.
+.Nm
+will ignore the time stamp directory until the mode is corrected.
+.El
+.Ss Notes on logging via syslog
+By default,
+.Nm
+logs messages via
+.Xr syslog 3 .
+The
+.Em date ,
+.Em hostname ,
+and
+.Em progname
+fields are added by the system's
+.Xr syslog 3
+function, not
+.Nm
+itself.
+As such, they may vary in format on different systems.
+.Pp
+The maximum size of syslog messages varies from system to system.
+The
+.Em syslog_maxlen
+setting can be used to change the maximum syslog message size
+from the default value of 980 bytes.
+For more information, see the description of
+.Em syslog_maxlen .
+.Ss Notes on logging to a file
+If the
+.Em logfile
+option is set,
+.Nm
+will log to a local file, such as
+.Pa @log_dir@/sudo .
+When logging to a file,
+.Nm
+uses a format similar to
+.Xr syslog 3 ,
+with a few important differences:
+.Bl -enum
+.It
+The
+.Em progname
+field is not present.
+.It
+The
+.Em hostname
+is only logged if the
+.Em log_host
+option is enabled.
+.It
+The date does not include the year unless the
+.Em log_year
+option is enabled.
+.It
+Lines that are longer than
+.Em loglinelen
+characters (80 by default) are word-wrapped and continued on the
+next line with a four character indent.
+This makes entries easier to read for a human being, but makes it
+more difficult to use
+.Xr grep 1
+on the log files.
+If the
+.Em loglinelen
+option is set to 0 (or negated with a
+.Ql \&! ) ,
+word wrap will be disabled.
+.El
+.Sh I/O LOGGING
+When I/O logging is enabled,
+.Nm sudo
+will runs the command in a pseudo-terminal, logging user input
+and/or output, depending on which
+.Nm
+flags are enabled.
+There are five distinct types of I/O that can be logged, each with
+a corresponding
+.Nm
+flag.
+.Bl -column "standard output" "log_output" "command output displayed to the screen"
+.It Sy Type Ta Sy Flag Ta Sy Description
+.It terminal input Ta log_ttyin Ta keystrokes entered by the user
+.It terminal output Ta log_ttyout Ta command output displayed to the screen
+.It standard input Ta log_stdin Ta input from a pipe or a file
+.It standard output Ta log_stdout Ta output to a pipe or a file
+.It standard error Ta log_stderr Ta output to a pipe or a file
+.El
+.Pp
+In addition to flags described the above, the
+.Em log_input
+flag and
+.Dv LOG_INPUT
+command tag set both
+.Em log_ttyin
+and
+.Em log_stdin .
+The
+.Em log_output
+flag and
+.Dv LOG_OUTPUT
+command tag set
+.Em log_ttyout ,
+.Em log_stdout ,
+and
+.Em log_stderr .
+.Pp
+To capture terminal input and output,
+.Nm sudo
+run the command in a pseudo-terminal, logging the input and
+output before passing it on to the user.
+To capture the standard input, standard output or standard error,
+.Nm sudo
+uses a pipe to interpose itself between the input or output stream,
+logging the I/O before passing it to the other end of the pipe.
+.Pp
+I/O can be logged either to the local machine or to a remote log server.
+For local logs, I/O is logged to the directory specified by the
+.Em iolog_dir
+option
+.Po
+.Pa @iolog_dir@
+by default
+.Pc
+using a unique session ID that is included in the
+.Nm sudo
+log line, prefixed with
+.Ql TSID= .
+The
+.Em iolog_file
+option may be used to control the format of the session ID.
+For remote logs, the
+.Em log_servers
+setting is used to specify one or more log servers running
+.Nm sudo_logsrvd
+or another server that implements the protocol described by
+.Xr sudo_logsrv.proto @mansectform@ .
+.Ss I/O logging pitfals
+When logging standard input, anything sent to the standard input
+will be consumed, regardless of whether or not the command run via
+.Nm sudo
+is actively reading the standard input.
+This may have unexpected results when using
+.Nm sudo
+in a shell script that expects to process the standard input.
+For example, given the following shell script:
+.Bd -literal -offset 4n
+#!/bin/sh
+sudo echo testing
+echo done
+.Ed
+.Pp
+It will behave as expected when the script is passed to the shell as a
+an argument:
+.Bd -literal -offset 4n
+$ sh test.sh
+testing
+done
+.Ed
+.Pp
+However, if the script is passed to the shell on the standard input, the
+.Ql sudo echo testing
+command will consume the rest of the script.
+This means that the
+.Ql echo done
+statement is never executed.
+.Bd -literal -offset 4n
+$ sh -s < test.sh
+testing
+.Ed
+.Pp
+There are several ways to work around this problem:
+.Bl -enum
+.It
+Redirect the standard input from
+.Pa /dev/null
+when running a command via
+.Nm sudo
+that does not need to read the standard input.
+.Bd -literal -offset 4n
+sudo echo testing < /dev/null
+.Ed
+.It
+Pass the script to the shell by path name instead of via the standard input.
+.Bd -literal -offset 4n
+sh test.sh
+.Ed
+.It
+Disable logging the standard input for commands that do not need
+to read the standard input.
+.Bd -literal -offset 4n
+Defaults!/bin/echo !log_stdin
+.Ed
+.El
+.Pp
+Depending on the command, it may not be desirable to log the
+standard input or standard output.
+For example, I/O logging of commands that send or receive large
+amount of data via the standard output or standard input such as
+.Xr rsync 1
+and
+.Xr tar 1
+could fill up the log file system with superfluous data.
+It is possible to disable logging of the standard input and standard
+output for such commands as follows:
+.Bd -literal -offset 4n
+Cmnd_Alias COPY_CMDS = /usr/bin/tar, /usr/bin/cpio, /usr/bin/rsync
+
+# Log input and output but omit stdin and stdout when copying files.
+Defaults log_input, log_output
+Defaults!COPY_CMDS !log_stdin, !log_stdout
+.Ed
+.Pp
+However, be aware that using the
+.Em log_input
+flag or the
+.Dv LOG_INPUT
+command tag will also enable
+.Em log_stdin .
+Likewise, the
+.Em log_ouput
+flag or the
+.Dv LOG_OUTPUT
+command tag will enable
+.Em log_stdout
+and
+.Em log_stderr.
+Careful ordering of rules may be necessary to achieve the results
+that you expect.
+.Ss I/O log format
+For both local and remote I/O logs, each log is stored in a separate
+directory that contains the following files:
+.Bl -tag -width "log.json"
+.It Pa log
+A text file containing information about the command.
+The first line consists of the following colon-delimited fields:
+the time the command was run, the name of the user
+who ran
+.Nm sudo ,
+the name of the target user, the name of the target group (optional),
+the terminal that
+.Nm sudo
+was run from, and the number of lines and columns of the terminal.
+The second and third lines contain the working directory the command
+was run from and the path name of the command itself (with arguments
+if present).
+.It Pa log.json
+A JSON-formatted file containing information about the command.
+This is similar to the
+.Pa log
+file but contains additional information and is easily extensible.
+The
+.Pa log.json
+file will be used by
+.Xr sudoreplay @mansectsu@
+in preference to the
+.Pa log
+file if it exists.
+The file may contain the following elements:
+.Bl -tag -width 4n
+.It timestamp
+A JSON object containing time the command was run.
+It consists of two values,
+.Em seconds
+and
+.Em nanoseconds .
+.It columns
+The number of columns of the terminal the command ran on, or zero
+if no terminal was present.
+.It command
+The fully-qualified path of the command that was run.
+.It lines
+The number of lines of the terminal the command ran on, or zero
+if no terminal was present.
+.It runargv
+A JSON array representing the command's argument vector as passed to the
+.Xr execve 2
+system call.
+.It runenv
+A JSON array representing the command's environment as passed to the
+.Xr execve 2
+system call.
+.It rungid
+The group ID the command ran as.
+This element is only present when the user specifies a group on the
+command line.
+.It rungroup
+The name of the group the command ran as.
+This element is only present when the user specifies a group on the
+command line.
+.It runuid
+The user ID the command ran as.
+.It runuser
+The name of the user the command ran as.
+.It submitcwd
+The current working directory at the time
+.Nm sudo
+was run.
+.It submithost
+The name of the host the command was run on.
+.It submituser
+The name of the user who ran the command via
+.Nm sudo .
+.It ttyname
+The path name of the terminal the user invoked
+.Nm sudo
+from.
+If the command was run in a pseudo-terminal,
+.Em ttyname
+will be different from the terminal the command actually ran in.
+.El
+.It Pa timing
+Timing information used to replay the session.
+Each line consists of the I/O log entry type and amount of time
+since the last entry, followed by type-specific data.
+The I/O log entry types and their corresponding type-specific data are:
+.Pp
+.Bl -tag -width 4n -compact
+.It 0
+standard input, number of bytes in the entry
+.It 1
+standard output, number of bytes in the entry
+.It 2
+standard error, number of bytes in the entry
+.It 3
+terminal input, number of bytes in the entry
+.It 4
+terminal output, number of bytes in the entry
+.It 5
+window change, new number lines and columns
+.It 6
+bug compatibility for
+.Nm sudo
+1.8.7 terminal output
+.It 7
+command suspend or resume, signal received
+.El
+.It Pa ttyin
+Raw input from the user's terminal, exactly as it was received.
+This file is only present if the
+.Em log_input
+or
+.Em log_ttyin
+flags are set and
+.Nm sudo
+was run from a terminal.
+No post-processing is performed.
+For manual viewing, you may wish to convert carriage return characters
+in the log to line feeds.
+For example:
+.Ql gunzip -c ttyin | tr \&"\er\&" \&"\en\&"
+.It Pa stdin
+The standard input when no terminal is present, or input redirected from
+a pipe or file.
+This file is only present if the
+.Em log_input
+or
+.Em log_stdin
+flags are set and the standard input is not connected to a terminal.
+.It Pa ttyout
+Output from the pseudo-terminal (what the command writes to the screen).
+Terminal-specific post-processing is performed before the data is logged.
+This means that, for example, line feeds are usually converted to
+line feed/carriage return pairs and tabs may be expanded to spaces.
+This file is only present if the
+.Em log_output
+or
+.Em log_ttyout
+flags are set and
+.Nm sudo
+was run from a terminal.
+.It Pa stdout
+The standard output when no terminal is present, or output redirected to
+a pipe or file.
+This file is only present if the
+.Em log_output
+or
+.Em log_stdout
+flags are set and the standard output is not connected to a terminal.
+.It Pa stderr
+The standard error when no terminal is present, or output redirected to
+a pipe or file.
+This file is only present if the
+.Em log_output
+or
+.Em log_stderr
+flags are set and the standard error is not connected to a terminal.
+.El
+.Pp
+All files other than
+.Pa log
+are compressed in gzip format unless the
+.Em compress_io
+flag has been disabled.
+Due to buffering, it is not normally possible to display the I/O logs in
+real-time as the program is executing.
+The I/O log data will not be complete until the program run by
+.Nm sudo
+has exited or has been terminated by a signal.
+The
+.Em iolog_flush
+flag can be used to disable buffering, in which case I/O log data
+is written to disk as soon as it is available.
+The output portion of an I/O log file can be viewed with the
+.Xr sudoreplay @mansectsu@
+utility, which can also be used to list or search the available logs.
+.Pp
+User input may contain sensitive information such as passwords (even
+if they are not echoed to the screen), which will be stored in the
+log file unencrypted.
+In most cases, logging the command output via
+.Em log_output
+or
+.Dv LOG_OUTPUT
+is all that is required.
+When logging input, consider disabling the
+.Em log_passwords
+flag.
+.Pp
+Since each session's I/O logs are stored in a separate directory,
+traditional log rotation utilities cannot be used to limit the
+number of I/O logs.
+The simplest way to limit the number of I/O is by setting the
+.Em maxseq
+option to the maximum number of logs you wish to store.
+Once the I/O log sequence number reaches
+.Em maxseq ,
+it will be reset to zero and
+.Nm
+will truncate and re-use any existing I/O logs.
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/sudo.conf
+Sudo front-end configuration
+.It Pa @sysconfdir@/sudoers
+List of who can run what
+.It Pa /etc/group
+Local groups file
+.It Pa /etc/netgroup
+List of network groups
+.It Pa @iolog_dir@
+I/O log files
+.It Pa @rundir@/ts
+Directory containing time stamps for the
+.Nm
+security policy
+.It Pa @vardir@/lectured
+Directory containing lecture status files for the
+.Nm
+security policy
+.It Pa /etc/environment
+Initial environment for
+.Fl i
+mode on AIX and Linux systems
+.El
+.Sh EXAMPLES
+Below are example
+.Em sudoers
+file entries.
+Admittedly, some of these are a bit contrived.
+First, we allow a few environment variables to pass and then define our
+.Em aliases :
+.Bd -literal
+# Run X applications through sudo; HOME is used to find the
+# .Xauthority file. Other programs use HOME to locate configuration
+# files and this may lead to privilege escalation!
+Defaults env_keep += "DISPLAY HOME"
+
+# User alias specification
+User_Alias FULLTIMERS = millert, mikef, dowdy
+User_Alias PARTTIMERS = bostley, jwfox, crawl
+User_Alias WEBADMIN = will, wendy, wim
+
+# Runas alias specification
+Runas_Alias OP = root, operator
+Runas_Alias DB = oracle, sybase
+Runas_Alias ADMINGRP = adm, oper
+
+# Host alias specification
+Host_Alias SPARC = bigtime, eclipse, moet, anchor :\e
+ SGI = grolsch, dandelion, black :\e
+ ALPHA = widget, thalamus, foobar :\e
+ HPPA = boa, nag, python
+Host_Alias CUNETS = 128.138.0.0/255.255.0.0
+Host_Alias CSNETS = 128.138.243.0, 128.138.204.0/24, 128.138.242.0
+Host_Alias SERVERS = primary, mail, www, ns
+Host_Alias CDROM = orion, perseus, hercules
+
+# Cmnd alias specification
+Cmnd_Alias DUMPS = /usr/bin/mt, /usr/sbin/dump, /usr/sbin/rdump,\e
+ /usr/sbin/restore, /usr/sbin/rrestore,\e
+ sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ== \e
+ /home/operator/bin/start_backups
+Cmnd_Alias KILL = /usr/bin/kill
+Cmnd_Alias PRINTING = /usr/sbin/lpc, /usr/bin/lprm
+Cmnd_Alias SHUTDOWN = /usr/sbin/shutdown
+Cmnd_Alias HALT = /usr/sbin/halt
+Cmnd_Alias REBOOT = /usr/sbin/reboot
+Cmnd_Alias SHELLS = /usr/bin/sh, /usr/bin/csh, /usr/bin/ksh,\e
+ /usr/local/bin/tcsh, /usr/bin/rsh,\e
+ /usr/local/bin/zsh
+Cmnd_Alias SU = /usr/bin/su
+Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less
+.Ed
+.Pp
+Here we override some of the compiled in default values.
+We want
+.Nm sudo
+to log via
+.Xr syslog 3
+using the
+.Em auth
+facility in all cases and for commands to be run with
+the target user's home directory as the working directory.
+We don't want to subject the full time staff to the
+.Nm sudo
+lecture and we want to allow them to run commands in a
+.Xr chroot 2
+.Dq sandbox
+via the
+.Fl R
+option.
+User
+.Sy millert
+need not provide a password and we don't want to reset the
+.Ev LOGNAME
+or
+.Ev USER
+environment variables when running commands as
+.Sy root .
+Additionally, on the machines in the
+.Dv SERVERS
+.Em Host_Alias ,
+we keep an additional local log file and make sure we log the year
+in each log line since the log entries will be kept around for several years.
+Lastly, we disable shell escapes for the commands in the PAGERS
+.Em Cmnd_Alias
+.Po
+.Pa /usr/bin/more ,
+.Pa /usr/bin/pg
+and
+.Pa /usr/bin/less
+.Pc .
+This will not effectively constrain users with
+.Nm sudo
+.Sy ALL
+privileges.
+.Bd -literal
+# Override built-in defaults
+Defaults syslog=auth,runcwd=~
+Defaults>root !set_logname
+Defaults:FULLTIMERS !lecture,runchroot=*
+Defaults:millert !authenticate
+Defaults@SERVERS log_year, logfile=@log_dir@/sudo.log
+Defaults!PAGERS noexec
+.Ed
+.Pp
+The
+.Em User specification
+is the part that actually determines who may run what.
+.Bd -literal
+root ALL = (ALL) ALL
+%wheel ALL = (ALL) ALL
+.Ed
+.Pp
+We let
+.Sy root
+and any user in group
+.Sy wheel
+run any command on any host as any user.
+.Bd -literal
+FULLTIMERS ALL = NOPASSWD: ALL
+.Ed
+.Pp
+Full time sysadmins
+.Po
+.Sy millert ,
+.Sy mikef ,
+and
+.Sy dowdy
+.Pc
+may run any command on any host without authenticating themselves.
+.Bd -literal
+PARTTIMERS ALL = ALL
+.Ed
+.Pp
+Part time sysadmins
+.Sy bostley ,
+.Sy jwfox ,
+and
+.Sy crawl )
+may run any command on any host but they must authenticate themselves
+first (since the entry lacks the
+.Dv NOPASSWD
+tag).
+.Bd -literal
+jack CSNETS = ALL
+.Ed
+.Pp
+The user
+.Sy jack
+may run any command on the machines in the
+.Dv CSNETS
+alias (the networks 128.138.243.0, 128.138.204.0, and 128.138.242.0).
+Of those networks, only 128.138.204.0 has an explicit netmask (in
+CIDR notation) indicating it is a class C network.
+For the other networks in
+.Dv CSNETS ,
+the local machine's netmask will be used during matching.
+.Bd -literal
+lisa CUNETS = ALL
+.Ed
+.Pp
+The user
+.Sy lisa
+may run any command on any host in the
+.Dv CUNETS
+alias (the class B network 128.138.0.0).
+.Bd -literal
+operator ALL = DUMPS, KILL, SHUTDOWN, HALT, REBOOT, PRINTING,\e
+ sudoedit /etc/printcap, /usr/oper/bin/
+.Ed
+.Pp
+The
+.Sy operator
+user may run commands limited to simple maintenance.
+Here, those are commands related to backups, killing processes, the
+printing system, shutting down the system, and any commands in the
+directory
+.Pa /usr/oper/bin/ .
+One command in the
+.Dv DUMPS
+Cmnd_Alias includes a sha224 digest,
+.Pa /home/operator/bin/start_backups .
+This is because the directory containing the script is writable by the
+operator user.
+If the script is modified (resulting in a digest mismatch) it will no longer
+be possible to run it via
+.Nm sudo .
+.Bd -literal
+joe ALL = /usr/bin/su operator
+.Ed
+.Pp
+The user
+.Sy joe
+may only
+.Xr su 1
+to operator.
+.Bd -literal
+pete HPPA = /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd *root*
+
+%opers ALL = (: ADMINGRP) /usr/sbin/
+.Ed
+.Pp
+Users in the
+.Sy opers
+group may run commands in
+.Pa /usr/sbin/
+as themselves
+with any group in the
+.Dv ADMINGRP
+.Em Runas_Alias
+(the
+.Sy adm
+and
+.Sy oper
+groups).
+.Pp
+The user
+.Sy pete
+is allowed to change anyone's password except for
+.Sy root
+on the
+.Dv HPPA
+machines.
+Because command line arguments are matched as a single,
+concatenated string, the
+.Ql *
+wildcard will match
+.Em multiple
+words.
+This example assumes that
+.Xr passwd 1
+does not take multiple user names on the command line.
+On systems with GNU
+.Xr getopt 3 ,
+options to
+.Xr passwd 1
+may be specified after the user argument.
+As a result, this rule will also allow:
+.Bd -literal -offset 4n
+passwd username --expire
+.Ed
+.Pp
+which may not be desirable.
+.Bd -literal
+bob SPARC = (OP) ALL : SGI = (OP) ALL
+.Ed
+.Pp
+The user
+.Sy bob
+may run anything on the
+.Dv SPARC
+and
+.Dv SGI
+machines as any user listed in the
+.Dv OP
+.Em Runas_Alias
+.Po
+.Sy root
+and
+.Sy operator .
+.Pc
+.Bd -literal
+jim +biglab = ALL
+.Ed
+.Pp
+The user
+.Sy jim
+may run any command on machines in the
+.Em biglab
+netgroup.
+.Nm sudo
+knows that
+.Dq biglab
+is a netgroup due to the
+.Ql +
+prefix.
+.Bd -literal
++secretaries ALL = PRINTING, /usr/bin/adduser, /usr/bin/rmuser
+.Ed
+.Pp
+Users in the
+.Sy secretaries
+netgroup need to help manage the printers as well as add and remove users,
+so they are allowed to run those commands on all machines.
+.Bd -literal
+fred ALL = (DB) NOPASSWD: ALL
+.Ed
+.Pp
+The user
+.Sy fred
+can run commands as any user in the
+.Dv DB
+.Em Runas_Alias
+.Po
+.Sy oracle
+or
+.Sy sybase
+.Pc
+without giving a password.
+.Bd -literal
+john ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root*
+.Ed
+.Pp
+On the
+.Dv ALPHA
+machines, user
+.Sy john
+may su to anyone except
+.Sy root
+but he is not allowed to specify any options to the
+.Xr su 1
+command.
+.Bd -literal
+jen ALL, !SERVERS = ALL
+.Ed
+.Pp
+The user
+.Sy jen
+may run any command on any machine except for those in the
+.Dv SERVERS
+.Em Host_Alias
+(primary, mail, www, and ns).
+.Bd -literal
+jill SERVERS = /usr/bin/, !SU, !SHELLS
+.Ed
+.Pp
+For any machine in the
+.Dv SERVERS
+.Em Host_Alias ,
+.Sy jill
+may run
+any commands in the directory
+.Pa /usr/bin/
+except for those commands
+belonging to the
+.Dv SU
+and
+.Dv SHELLS
+.Em Cmnd_Aliases .
+While not specifically mentioned in the rule, the commands in the
+.Dv PAGERS
+.Em Cmnd_Alias
+all reside in
+.Pa /usr/bin
+and have the
+.Em noexec
+option set.
+.Bd -literal
+steve CSNETS = (operator) /usr/local/op_commands/
+.Ed
+.Pp
+The user
+.Sy steve
+may run any command in the directory /usr/local/op_commands/
+but only as user operator.
+.Bd -literal
+matt valkyrie = KILL
+.Ed
+.Pp
+On his personal workstation, valkyrie,
+.Sy matt
+needs to be able to kill hung processes.
+.Bd -literal
+WEBADMIN www = (www) ALL, (root) /usr/bin/su www
+.Ed
+.Pp
+On the host www, any user in the
+.Dv WEBADMIN
+.Em User_Alias
+(will, wendy, and wim), may run any command as user www (which owns the
+web pages) or simply
+.Xr su 1
+to www.
+.Bd -literal
+ALL CDROM = NOPASSWD: /sbin/umount /CDROM,\e
+ /sbin/mount -o nosuid\e,nodev /dev/cd0a /CDROM
+.Ed
+.Pp
+Any user may mount or unmount a CD-ROM on the machines in the CDROM
+.Em Host_Alias
+(orion, perseus, hercules) without entering a password.
+This is a bit tedious for users to type, so it is a prime candidate
+for encapsulating in a shell script.
+.Sh SECURITY NOTES
+.Ss Limitations of the So !\& Sc operator
+It is generally not effective to
+.Dq subtract
+commands from
+.Sy ALL
+using the
+.Ql !\&
+operator.
+A user can trivially circumvent this by copying the desired command
+to a different name and then executing that.
+For example:
+.Bd -literal
+bill ALL = ALL, !SU, !SHELLS
+.Ed
+.Pp
+Doesn't really prevent
+.Sy bill
+from running the commands listed in
+.Dv SU
+or
+.Dv SHELLS
+since he can simply copy those commands to a different name, or use
+a shell escape from an editor or other program.
+Therefore, these kind of restrictions should be considered
+advisory at best (and reinforced by policy).
+.Pp
+In general, if a user has sudo
+.Sy ALL
+there is nothing to prevent them from creating their own program that gives
+them a
+.Sy root
+shell (or making their own copy of a shell) regardless of any
+.Ql !\&
+elements in the user specification.
+.Ss Security implications of Em fast_glob
+If the
+.Em fast_glob
+option is in use, it is not possible to reliably negate commands where the
+path name includes globbing (aka wildcard) characters.
+This is because the C library's
+.Xr fnmatch 3
+function cannot resolve relative paths.
+While this is typically only an inconvenience for rules that grant privileges,
+it can result in a security issue for rules that subtract or revoke privileges.
+.Pp
+For example, given the following
+.Em sudoers
+file entry:
+.Bd -literal
+john ALL = /usr/bin/passwd [a-zA-Z0-9]*, /usr/bin/chsh [a-zA-Z0-9]*,\e
+ /usr/bin/chfn [a-zA-Z0-9]*, !/usr/bin/* root
+.Ed
+.Pp
+User
+.Sy john
+can still run
+.Ql /usr/bin/passwd root
+if
+.Em fast_glob
+is enabled by changing to
+.Pa /usr/bin
+and running
+.Ql ./passwd root
+instead.
+.Pp
+Another potential issue is that when
+.Nm sudo
+executes the command, it must use the command or path specified by
+the user instead of a path listed in the
+.Em sudoers
+file.
+This may lead to a time of check versus time of use race condition.
+.Ss Wildcards in command arguments
+Command line arguments are matched as a single, concatenated string.
+This mean a wildcard character such as
+.Ql \&?
+or
+.Ql *
+will match across word boundaries, which may be unexpected.
+For example, while a sudoers entry like:
+.Bd -literal -offset 4n
+%operator ALL = /bin/cat @log_dir@/messages*
+.Ed
+.Pp
+will allow command like:
+.Bd -literal -offset 4n
+$ sudo cat @log_dir@/messages.1
+.Ed
+.Pp
+It will also allow:
+.Bd -literal -offset 4n
+$ sudo cat @log_dir@/messages /etc/shadow
+.Ed
+.Pp
+which is probably not what was intended.
+A safer alternative is to use a regular expression for matching
+command line arguments.
+The above example can be rewritten as a regular expression:
+.Bd -literal -offset 4n
+%operator ALL = /bin/cat ^@log_dir@/messages[^[:space:]]*$
+.Ed
+.Pp
+The regular expression will only match a single file with a
+name that begins with
+.Pa @log_dir@/messages
+and does not include any white space in the name.
+It is often better to do command line processing outside of the
+.Em sudoers
+file in a scripting language for anything non-trivial.
+.Ss Regular expressions in command names
+Using a regular expression to match a command name has the same
+security implications as using the
+.Em fast_glob
+option:
+.Bl -bullet -width 1n
+.It
+It is not possible to reliably negate commands when the
+path name is a regular expression.
+.It
+When
+.Nm sudo
+executes the command, it must use the command or path specified by
+the user instead of a path listed in the
+.Em sudoers
+file.
+This may lead to a time of check versus time of use race condition.
+.El
+.Pp
+These issues do not apply to rules where only the command line
+options are matched using a regular expression.
+.Ss Preventing shell escapes
+Once
+.Nm sudo
+executes a program, that program is free to do whatever
+it pleases, including run other programs.
+This can be a security issue since it is not uncommon for a program to
+allow shell escapes, which lets a user bypass
+.Nm sudo Ns 's
+access control and logging.
+Common programs that permit shell escapes include shells (obviously),
+editors, paginators, mail, and terminal programs.
+.Pp
+There are four basic approaches to this problem:
+.Bl -tag -width "intercept"
+.It restrict
+Avoid giving users access to commands that allow the user to run
+arbitrary commands.
+Many editors have a restricted mode where shell
+escapes are disabled, though
+.Nm sudoedit
+is a better solution to
+running editors via
+.Nm sudo .
+Due to the large number of programs that
+offer shell escapes, restricting users to the set of programs that
+do not is often unworkable.
+.It intercept
+On most systems,
+.Nm sudo Ns 's
+.Em intercept
+functionality can be used to transparently intercept an attempt to
+run a new command, allow or deny it based on
+.Em sudoers
+rules, and log the result.
+For example, this can be used to restrict the commands run from
+within a privileged shell or editor.
+However, not all programs operate correctly when
+.Em intercept
+is enabled.
+.Pp
+There are two underlying mechanisms that may be used to implement
+.Em intercept
+mode:
+.Em dso
+and
+.Em trace .
+The
+.Em intercept_type
+setting can be used to select between them.
+.Pp
+The first mechanism,
+.Em dso ,
+overrides the standard C library functions that are used to execute a
+command.
+It does this by setting an environment variable (usually
+.Ev LD_PRELOAD )
+to the path of a dynamic shared object, or shared library,
+containing custom versions of the
+.Xr execve 2 ,
+.Xr execl 3 ,
+.Xr execle 3 ,
+.Xr execlp 3 ,
+.Xr execv 3 ,
+.Xr execvp 3 ,
+.Xr execvpe 3 ,
+and
+.Xr system 3
+library functions that connect back to
+.Nm sudo
+for a policy decision.
+Note, however, that this applies only to dynamically-linked
+executables.
+It is not possible to intercept commands for statically-linked executables
+or executables that run under binary emulation this way.
+Because most dynamic loaders ignore
+.Ev LD_PRELOAD
+(or the equivalent) when running set-user-ID and set-group-ID programs,
+.Nm
+will not permit such programs to be run in
+.Em intercept
+mode by default.
+The
+.Em dso
+mechanism is incompatible with
+.Nm sudo Ns 's
+SELinux RBAC support (but see below).
+SELinux disables
+.Ev LD_PRELOAD
+by default and interferes with file descriptor inheritance, which
+.Nm sudo
+relies on.
+.Pp
+The second mechanism,
+.Em trace ,
+is available on Linux systems that support
+.Xr seccomp 2
+filtering.
+It uses
+.Xr ptrace 2
+and
+.Xr seccomp 2
+to intercept the
+.Xr execve 2
+system call instead of pre-loading a dynamic shared object.
+Both static and dynamic executables are supported and it is compatible with
+.Nm sudo Ns 's
+SELinux RBAC mode.
+Functions utilizing the
+.Xr execveat 2
+system call, such as
+.Xr fexecve 3 ,
+are not currently intercepted.
+Programs that rely on
+.Xr ptrace 2
+themselves, such as debuggers and system call tracers
+.Po
+such as
+.Xr strace 1
+and
+.Xr truss 1
+.Pc
+will be unable to function if
+.Em intercept
+is enabled in
+.Em trace
+mode.
+This same restriction applies to the
+.Em log_subcmds
+sudoers option.
+.Pp
+The
+.Em intercept
+feature is known to work on Solaris, *BSD, Linux, macOS, HP-UX 11.x
+and AIX 5.3 and above.
+It should be supported on most operating systems that support the
+.Ev LD_PRELOAD
+environment variable or an equivalent.
+It is not possible to intercept shell built-in commands or restrict
+the ability to read or write sensitive files from within a shell.
+.Pp
+To enable intercept mode on a per-command basis, use the
+.Dv INTERCEPT
+tag as documented in the User Specification section above.
+Here is that example again:
+.Bd -literal
+chuck research = INTERCEPT: ALL
+.Ed
+.Pp
+This allows user
+.Sy chuck
+to run any command on the machine
+.Dq research
+in intercept mode.
+Any commands run via shell escapes will be validated and logged by
+.Nm sudo .
+If you are unsure whether or not your system is capable of supporting
+.Em intercept ,
+you can always just try it out and check whether or not external
+commands run via a shell are logged when
+.Em intercept
+is enabled.
+.Pp
+There is an inherent race condition between when a command is checked against
+.Nm
+rules and when it is actually executed.
+If a user is allowed to run arbitrary commands, they may be able
+to change the
+.Xr execve 2
+arguments in the program after the
+.Nm
+policy check has completed but before the new command is executed.
+Starting with version 1.9.12, the
+.Em trace
+method will verify that the command and its arguments have not
+changed after
+.Xr execve 2
+has completed but before execution of the new program has had a chance to run.
+This is not the case with the
+.Em dso
+method.
+See the description of the
+.Em intercept_verify
+setting for more information.
+.It log
+There are two separate but related ways to log additional commands.
+The first is to enable I/O logging using the
+.Em log_output
+flag.
+This will log the command's output but will not create an event log
+entry when the additional command is run.
+The second is to enable the
+.Em log_subcmds
+flag in
+.Em sudoers
+which will create an event log entry every time a new command is run.
+If I/O logging is also enabled, the log entry will include a time offset
+into the I/O log to indicate when the command was run.
+This offset can be passed to the
+.Xr sudoreplay @mansectsu@
+utility to replay the I/O log at the exact moment when the command was run.
+The
+.Em log_subcmds
+flag uses the same mechanism as
+.Em intercept
+(see above) and has the same limitations.
+.It noexec
+.Nm sudo Ns 's
+.Em noexec
+functionality can be used to prevent a program run by
+.Nm sudo
+from executing any other programs.
+On most systems, it uses the same
+.Ev LD_PRELOAD
+mechanism as
+.Em intercept
+(see above) and thus the same caveats apply.
+The
+.Em noexec
+functionality
+is capable of blocking execution of commands run via the
+.Xr execve 2 ,
+.Xr execl 3 ,
+.Xr execle 3 ,
+.Xr execlp 3 ,
+.Xr exect 3 ,
+.Xr execv 3 ,
+.Xr execveat 3 ,
+.Xr execvP 3 ,
+.Xr execvp 3 ,
+.Xr execvpe 3 ,
+.Xr fexecve 3 ,
+.Xr popen 3 ,
+.Xr posix_spawn 3 ,
+.Xr posix_spawnp 3 ,
+.Xr system 3 ,
+and
+.Xr wordexp 3
+functions.
+On Linux, a
+.Xr seccomp 2
+filter is used to implement
+.Em noexec .
+On Solaris 10 and higher,
+.Em noexec
+uses Solaris privileges instead of the
+.Ev LD_PRELOAD
+environment variable.
+.Pp
+To enable
+.Em noexec
+for a command, use the
+.Dv NOEXEC
+tag as documented in the User Specification section above.
+Here is that example again:
+.Bd -literal
+aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi
+.Ed
+.Pp
+This allows user
+.Sy aaron
+to run
+.Pa /usr/bin/more
+and
+.Pa /usr/bin/vi
+with
+.Em noexec
+enabled.
+This will prevent those two commands from
+executing other commands (such as a shell).
+If you are unsure whether or not your system is capable of supporting
+.Em noexec
+you can always just try it out and check whether shell escapes work when
+.Em noexec
+is enabled.
+.El
+.Pp
+Restricting shell escapes is not a panacea.
+Programs running as
+.Sy root
+are still capable of many potentially hazardous operations (such
+as changing or overwriting files) that could lead to unintended
+privilege escalation.
+In the specific case of an editor, a safer approach is to give the
+user permission to run
+.Nm sudoedit
+(see below).
+.Ss Secure editing
+The
+.Nm
+plugin includes
+.Nm sudoedit
+support which allows users to securely edit files with the editor
+of their choice.
+As
+.Nm sudoedit
+is a built-in command, it must be specified in the
+.Em sudoers
+file without a leading path.
+However, it may take command line arguments just as a normal command does.
+Wildcards used in
+.Em sudoedit
+command line arguments are expected to be path names, so a forward slash
+.Pq Ql /
+will not be matched by a wildcard.
+.Pp
+Unlike other
+.Nm sudo
+commands, the editor is run with the permissions of the invoking
+user and with the environment unmodified.
+More information may be found in the description of the
+.Fl e
+option in
+.Xr sudo @mansectsu@ .
+.Pp
+For example, to allow user operator to edit the
+.Dq message of the day
+file on any machine:
+.Bd -literal -offset 4n
+operator ALL = sudoedit /etc/motd
+.Ed
+.Pp
+The operator user then runs
+.Nm sudoedit
+as follows:
+.Bd -literal -offset 4n
+$ sudoedit /etc/motd
+.Ed
+.Pp
+The editor will run as the operator user, not
+.Sy @runas_default@ ,
+on a temporary copy of
+.Pa /etc/motd .
+After the file has been edited,
+.Pa /etc/motd
+will be updated with the contents of the temporary copy.
+.Pp
+Users should
+.Em never
+be granted
+.Nm sudoedit
+permission to edit a file that resides in a directory the user
+has write access to, either directly or via a wildcard.
+If the user has write access to the directory it is possible to
+replace the legitimate file with a link to another file,
+allowing the editing of arbitrary files.
+To prevent this, starting with version 1.8.16, symbolic links will
+not be followed in writable directories and
+.Nm sudoedit
+will refuse to edit a file located in a writable directory
+unless the
+.Em sudoedit_checkdir
+option has been disabled or the invoking user is
+.Sy root .
+Additionally, in version 1.8.15 and higher,
+.Nm sudoedit
+will refuse to open a symbolic link unless either the
+.Em sudoedit_follow
+option is enabled or the
+.Em sudoedit
+command is prefixed with the
+.Dv FOLLOW
+tag in the
+.Em sudoers
+file.
+.Ss Time stamp file checks
+.Nm
+will check the ownership of its time stamp directory
+.Po
+.Pa @rundir@/ts
+by default
+.Pc
+and ignore the directory's contents if it is not owned by
+.Sy root
+or if it is writable by a user other than
+.Sy root .
+Older versions of
+.Nm sudo
+stored time stamp files in
+.Pa /tmp ;
+this is no longer recommended as it may be possible for a user
+to create the time stamp themselves on systems that allow
+unprivileged users to change the ownership of files they create.
+.Pp
+While the time stamp directory
+.Em should
+be cleared at reboot time, not all systems contain a
+.Pa /run
+or
+.Pa /var/run
+directory.
+To avoid potential problems,
+.Nm
+will ignore time stamp files that date from before the machine booted
+on systems where the boot time is available.
+.Pp
+Some systems with graphical desktop environments allow unprivileged
+users to change the system clock.
+Since
+.Nm
+relies on the system clock for time stamp validation, it may be
+possible on such systems for a user to run
+.Nm sudo
+for longer than
+.Em timestamp_timeout
+by setting the clock back.
+To combat this,
+.Nm
+uses a monotonic clock (which never moves backwards) for its time stamps
+if the system supports it.
+.Pp
+.Nm
+will not honor time stamps set far in the future.
+Time stamps with a date greater than current_time + 2 *
+.Dv TIMEOUT
+will be ignored and
+.Nm
+will log and complain.
+.Pp
+If the
+.Em timestamp_type
+option is set to
+.Dq tty ,
+the time stamp record includes the device number of the terminal
+the user authenticated with.
+This provides per-terminal granularity but time stamp records may still
+outlive the user's session.
+.Pp
+Unless the
+.Em timestamp_type
+option is set to
+.Dq global ,
+the time stamp record also includes the session ID of the process
+that last authenticated.
+This prevents processes in different terminal sessions from using
+the same time stamp record.
+On systems where a process's start time can be queried,
+the start time of the session leader
+is recorded in the time stamp record.
+If no terminal is present or the
+.Em timestamp_type
+option is set to
+.Dq ppid ,
+the start time of the parent process is used instead.
+In most cases this will prevent a time stamp record from being re-used
+without the user entering a password when logging out and back in again.
+.Sh DEBUGGING
+Versions 1.8.4 and higher of the
+.Nm
+plugin support a flexible debugging framework that can help track
+down what the plugin is doing internally if there is a problem.
+This can be configured in the
+.Xr sudo.conf @mansectform@
+file.
+.Pp
+The
+.Nm
+plugin uses the same debug flag format as the
+.Nm sudo
+front-end:
+.Em subsystem Ns @ Ns Em priority .
+.Pp
+The priorities used by
+.Nm ,
+in order of decreasing severity,
+are:
+.Em crit , err , warn , notice , diag , info , trace ,
+and
+.Em debug .
+Each priority, when specified, also includes all priorities higher
+than it.
+For example, a priority of
+.Em notice
+would include debug messages logged at
+.Em notice
+and higher.
+.Pp
+The following subsystems are used by the
+.Nm
+plugin:
+.Bl -tag -width "defaults"
+.It Em alias
+.Em User_Alias ,
+.Em Runas_Alias ,
+.Em Host_Alias
+and
+.Em Cmnd_Alias
+processing
+.It Em all
+matches every subsystem
+.It Em audit
+BSM and Linux audit code
+.It Em auth
+user authentication
+.It Em defaults
+.Em sudoers
+file
+.Em Defaults
+settings
+.It Em env
+environment handling
+.It Em ldap
+LDAP-based sudoers
+.It Em logging
+logging support
+.It Em match
+matching of users, groups, hosts, and netgroups in the
+.Em sudoers
+file
+.It Em netif
+network interface handling
+.It Em nss
+network service switch handling in
+.Nm
+.It Em parser
+.Em sudoers
+file parsing
+.It Em perms
+permission setting
+.It Em plugin
+The equivalent of
+.Em main
+for the plugin.
+.It Em pty
+pseudo-terminal related code
+.It Em rbtree
+redblack tree internals
+.It Em sssd
+SSSD-based sudoers
+.It Em util
+utility functions
+.El
+.Pp
+For example:
+.Bd -literal
+Debug @sudoers_plugin@ @log_dir@/sudoers_debug match@info,nss@info
+.Ed
+.Pp
+For more information, see the
+.Xr sudo.conf @mansectform@
+manual.
+.Sh SEE ALSO
+.Xr ssh 1 ,
+.Xr su 1 ,
+.Xr fnmatch 3 ,
+.Xr glob 3 ,
+.Xr mktemp 3 ,
+.Xr strftime 3 ,
+.Xr sudo.conf @mansectform@ ,
+.Xr sudo_plugin @mansectform@ ,
+.Xr sudoers.ldap @mansectform@ ,
+.Xr sudoers_timestamp @mansectform@ ,
+.Xr sudo @mansectsu@ ,
+.Xr visudo @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS.md file in the
+.Nm sudo
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh CAVEATS
+The
+.Em sudoers
+file should
+.Sy always
+be edited by the
+.Nm visudo
+utility which locks the file and checks for syntax errors.
+If
+.Em sudoers
+contains syntax errors,
+.Nm sudo
+may refuse to run, which is a serious problem if
+.Nm sudo
+is your only method of obtaining superuser privileges.
+Recent versions of
+.Nm
+will attempt to recover after a syntax error by ignoring the rest of
+the line after encountering an error.
+Older versions of
+.Nm sudo
+will not run if
+.Em sudoers
+contains a syntax error.
+.Pp
+When using netgroups of machines (as opposed to users), if you
+store fully qualified host name in the netgroup (as is usually the
+case), you either need to have the machine's host name be fully qualified
+as returned by the
+.Em hostname
+command or use the
+.Em fqdn
+option in
+.Em sudoers .
+.Sh BUGS
+If you believe you have found a bug in
+.Nm sudo ,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm sudo
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+.Nm sudo
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudoers_timestamp.man.in b/docs/sudoers_timestamp.man.in
new file mode 100644
index 0000000..9256402
--- /dev/null
+++ b/docs/sudoers_timestamp.man.in
@@ -0,0 +1,318 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2017-2020, 2022-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.TH "SUDOERS_TIMESTAMP" "@mansectform@" "September 20, 2023" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudoers_timestamp\fR
+\- Sudoers Time Stamp Format
+.SH "DESCRIPTION"
+The
+\fBsudoers\fR
+plugin uses per-user-ID time stamp files for credential caching.
+Once a user has been authenticated, they may use
+\fBsudo\fR
+without a password for a short period of time
+(\fI@timeout@\fR
+minutes unless overridden by the
+\fItimestamp_timeout\fR
+option)
+\&.
+By default,
+\fBsudoers\fR
+uses a separate record for each terminal, which means that
+a user's login sessions are authenticated separately.
+The
+\fItimestamp_type\fR
+option can be used to select the type of time stamp record
+\fBsudoers\fR
+will use.
+.PP
+A multi-record time stamp file format was introduced in
+\fBsudo\fR
+1.8.10 that uses a single file per user.
+Previously, a separate file was used for each user and terminal
+combination unless tty-based time stamps were disabled.
+The new format is extensible and records of multiple types and versions
+may coexist within the same file.
+.PP
+All records, regardless of type or version, begin with a 16-bit version
+number and a 16-bit record size.
+.PP
+Time stamp records have the following structure:
+.nf
+.sp
+.RS 0n
+/* Time stamp entry types */
+#define TS_GLOBAL 0x01 /* not restricted by tty or ppid */
+#define TS_TTY 0x02 /* restricted by tty */
+#define TS_PPID 0x03 /* restricted by ppid */
+#define TS_LOCKEXCL 0x04 /* special lock record */
+
+/* Time stamp flags */
+#define TS_DISABLED 0x01 /* entry disabled */
+#define TS_ANYUID 0x02 /* ignore uid, only valid in key */
+
+struct timestamp_entry {
+ unsigned short version; /* version number */
+ unsigned short size; /* entry size */
+ unsigned short type; /* TS_GLOBAL, TS_TTY, TS_PPID */
+ unsigned short flags; /* TS_DISABLED, TS_ANYUID */
+ uid_t auth_uid; /* uid to authenticate as */
+ pid_t sid; /* session ID associated with tty/ppid */
+ struct timespec start_time; /* session/ppid start time */
+ struct timespec ts; /* time stamp (CLOCK_MONOTONIC) */
+ union {
+ dev_t ttydev; /* tty device number */
+ pid_t ppid; /* parent pid */
+ } u;
+};
+.RE
+.fi
+.PP
+The timestamp_entry struct fields are as follows:
+.TP 6n
+version
+The version number of the timestamp_entry struct.
+New entries are created with a version number of 2.
+Records with different version numbers may coexist in the
+same file but are not inter-operable.
+.TP 6n
+size
+The size of the record in bytes.
+.TP 6n
+type
+The record type, currently
+\fRTS_GLOBAL\fR,
+\fRTS_TTY\fR,
+or
+\fRTS_PPID\fR.
+.TP 6n
+flags
+.br
+Zero or more record flags which can be bit-wise ORed together.
+Supported flags are
+\fRTS_DISABLED\fR,
+for records disabled via
+\fBsudo\fR
+\fB\-k\fR
+and
+\fRTS_ANYUID\fR,
+which is used only when matching records.
+.TP 6n
+auth_uid
+The user-ID that was used for authentication.
+Depending on the value of the
+\fIrootpw\fR,
+\fIrunaspw\fR
+and
+\fItargetpw\fR
+options, the user-ID may be that of the invoking user, the root user,
+the default runas user or the target user.
+.TP 6n
+sid
+The ID of the user's terminal session, if present.
+The session ID is only used when matching records of type
+\fRTS_TTY\fR.
+.TP 6n
+start_time
+The start time of the session leader for records of type
+\fRTS_TTY\fR
+or of the parent process for records of type
+\fRTS_PPID\fR.
+The
+\fIstart_time\fR
+is used to help prevent re-use of a time stamp record after a
+user has logged out.
+Not all systems support a method to easily retrieve a process's
+start time.
+The
+\fIstart_time\fR
+field was added in
+\fBsudoers\fR
+version 1.8.22 for the second revision of the timestamp_entry struct.
+.TP 6n
+ts
+The actual time stamp.
+A monotonic time source (which does not move backward) is used if the
+system supports it.
+Where possible,
+\fBsudoers\fR
+uses a monotonic timer that increments even while the system
+is suspended.
+The value of
+\fIts\fR
+is updated each time a command is run via
+\fBsudo\fR.
+If the difference between
+\fIts\fR
+and the current time is less than the value of the
+\fItimestamp_timeout\fR
+option, no password is required.
+.TP 6n
+u.ttydev
+The device number of the terminal associated with the session for
+records of type
+\fRTS_TTY\fR.
+.TP 6n
+u.ppid
+The ID of the parent process for records of type
+\fRTS_PPID\fR.
+.SH "LOCKING"
+In
+\fBsudoers\fR
+versions 1.8.10 through 1.8.14, the entire time stamp file was
+locked for exclusive access when reading or writing to the file.
+Starting in
+\fBsudoers\fR
+1.8.15, individual records are locked in the time stamp file instead
+of the entire file and the lock is held for a longer period of time.
+This scheme is described below.
+.PP
+The first record in the time stamp file is of type
+\fRTS_LOCKEXCL\fR
+and is used as a
+\fIlock\fR
+record to prevent more than one
+\fBsudo\fR
+process from adding a new record at the same time.
+Once the desired time stamp record has been located or created (and
+locked), the
+\fRTS_LOCKEXCL\fR
+record is unlocked.
+The lock on the individual time stamp record, however, is held until
+authentication is complete.
+This allows
+\fBsudoers\fR
+to avoid prompting for a password multiple times when it
+is used more than once in a pipeline.
+.PP
+Records of type
+\fRTS_GLOBAL\fR
+cannot be locked for a long period of time since doing so would
+interfere with other
+\fBsudo\fR
+processes.
+Instead, a separate lock record is used to prevent multiple
+\fBsudo\fR
+processes using the same terminal (or parent process ID) from
+prompting for a password as the same time.
+.SH "SEE ALSO"
+sudoers(@mansectform@),
+sudo(@mansectsu@)
+.SH "HISTORY"
+Originally,
+\fBsudo\fR
+used a single zero-length file per user and the file's modification
+time was used as the time stamp.
+Later versions of
+\fBsudo\fR
+added restrictions on the ownership of the time stamp files and
+directory as well as checks on the validity of the time stamp itself.
+Notable changes were introduced in the following
+\fBsudo\fR
+versions:
+.TP 6n
+1.4.0
+.br
+Support for tty-based time stamp file was added
+by appending the terminal name to the time stamp file name.
+.TP 6n
+1.6.2
+.br
+The time stamp file was replaced by a per-user directory which
+contained any tty-based time stamp files.
+.TP 6n
+1.6.3p2
+The target user name was added to the time stamp file name when the
+\fItargetpw\fR
+option was set.
+.TP 6n
+1.7.3
+.br
+Information about the terminal device was stored in
+tty-based time stamp files for validity checks.
+This included the terminal device numbers, inode number and, on systems
+where it was not updated when the device was written to, the inode change time.
+This helped prevent re-use of the time stamp file after logout.
+.TP 6n
+1.8.6p7
+The terminal session ID was added to tty-based time stamp files to
+prevent re-use of the time stamp by the same user in a different
+terminal session.
+It also helped prevent re-use of the time stamp file on systems where
+the terminal device's inode change time was updated by writing.
+.TP 6n
+1.8.10
+A new, multi-record time stamp file format was introduced that uses a
+single file per user.
+The terminal device's change time was not included since most
+systems now update the change time after a write is performed
+as required by POSIX.
+.TP 6n
+1.8.15
+Individual records are locked in the time stamp file instead of the
+entire file and the lock is held until authentication is complete.
+.TP 6n
+1.8.22
+The start time of the terminal session leader or parent process is
+now stored in non-global time stamp records.
+This prevents re-use of the time stamp file after logout in most cases.
+.sp
+Support was added for the kernel-based tty time stamps available in
+OpenBSD
+which do not use an on-disk time stamp file.
+.TP 6n
+1.9.15
+Time stamp file path names are now based on the invoking user-ID
+instead of the user name.
+This avoids problems with user names that include a path separator
+character.
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS.md file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you believe you have found a bug in
+\fBsudo\fR,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudoers_timestamp.mdoc.in b/docs/sudoers_timestamp.mdoc.in
new file mode 100644
index 0000000..cc0ea9b
--- /dev/null
+++ b/docs/sudoers_timestamp.mdoc.in
@@ -0,0 +1,295 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2017-2020, 2022-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd September 20, 2023
+.Dt SUDOERS_TIMESTAMP @mansectform@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudoers_timestamp
+.Nd Sudoers Time Stamp Format
+.Sh DESCRIPTION
+The
+.Nm sudoers
+plugin uses per-user-ID time stamp files for credential caching.
+Once a user has been authenticated, they may use
+.Nm sudo
+without a password for a short period of time
+.Po
+.Em @timeout@
+minutes unless overridden by the
+.Em timestamp_timeout
+option
+.Pc .
+By default,
+.Nm sudoers
+uses a separate record for each terminal, which means that
+a user's login sessions are authenticated separately.
+The
+.Em timestamp_type
+option can be used to select the type of time stamp record
+.Nm sudoers
+will use.
+.Pp
+A multi-record time stamp file format was introduced in
+.Nm sudo
+1.8.10 that uses a single file per user.
+Previously, a separate file was used for each user and terminal
+combination unless tty-based time stamps were disabled.
+The new format is extensible and records of multiple types and versions
+may coexist within the same file.
+.Pp
+All records, regardless of type or version, begin with a 16-bit version
+number and a 16-bit record size.
+.Pp
+Time stamp records have the following structure:
+.Bd -literal
+/* Time stamp entry types */
+#define TS_GLOBAL 0x01 /* not restricted by tty or ppid */
+#define TS_TTY 0x02 /* restricted by tty */
+#define TS_PPID 0x03 /* restricted by ppid */
+#define TS_LOCKEXCL 0x04 /* special lock record */
+
+/* Time stamp flags */
+#define TS_DISABLED 0x01 /* entry disabled */
+#define TS_ANYUID 0x02 /* ignore uid, only valid in key */
+
+struct timestamp_entry {
+ unsigned short version; /* version number */
+ unsigned short size; /* entry size */
+ unsigned short type; /* TS_GLOBAL, TS_TTY, TS_PPID */
+ unsigned short flags; /* TS_DISABLED, TS_ANYUID */
+ uid_t auth_uid; /* uid to authenticate as */
+ pid_t sid; /* session ID associated with tty/ppid */
+ struct timespec start_time; /* session/ppid start time */
+ struct timespec ts; /* time stamp (CLOCK_MONOTONIC) */
+ union {
+ dev_t ttydev; /* tty device number */
+ pid_t ppid; /* parent pid */
+ } u;
+};
+.Ed
+.Pp
+The timestamp_entry struct fields are as follows:
+.Bl -tag -width 4n
+.It version
+The version number of the timestamp_entry struct.
+New entries are created with a version number of 2.
+Records with different version numbers may coexist in the
+same file but are not inter-operable.
+.It size
+The size of the record in bytes.
+.It type
+The record type, currently
+.Dv TS_GLOBAL ,
+.Dv TS_TTY ,
+or
+.Dv TS_PPID .
+.It flags
+Zero or more record flags which can be bit-wise ORed together.
+Supported flags are
+.Dv TS_DISABLED ,
+for records disabled via
+.Nm sudo
+.Fl k
+and
+.Dv TS_ANYUID ,
+which is used only when matching records.
+.It auth_uid
+The user-ID that was used for authentication.
+Depending on the value of the
+.Em rootpw ,
+.Em runaspw
+and
+.Em targetpw
+options, the user-ID may be that of the invoking user, the root user,
+the default runas user or the target user.
+.It sid
+The ID of the user's terminal session, if present.
+The session ID is only used when matching records of type
+.Dv TS_TTY .
+.It start_time
+The start time of the session leader for records of type
+.Dv TS_TTY
+or of the parent process for records of type
+.Dv TS_PPID .
+The
+.Em start_time
+is used to help prevent re-use of a time stamp record after a
+user has logged out.
+Not all systems support a method to easily retrieve a process's
+start time.
+The
+.Em start_time
+field was added in
+.Nm sudoers
+version 1.8.22 for the second revision of the timestamp_entry struct.
+.It ts
+The actual time stamp.
+A monotonic time source (which does not move backward) is used if the
+system supports it.
+Where possible,
+.Nm sudoers
+uses a monotonic timer that increments even while the system
+is suspended.
+The value of
+.Em ts
+is updated each time a command is run via
+.Nm sudo .
+If the difference between
+.Em ts
+and the current time is less than the value of the
+.Em timestamp_timeout
+option, no password is required.
+.It u.ttydev
+The device number of the terminal associated with the session for
+records of type
+.Dv TS_TTY .
+.It u.ppid
+The ID of the parent process for records of type
+.Dv TS_PPID .
+.El
+.Sh LOCKING
+In
+.Nm sudoers
+versions 1.8.10 through 1.8.14, the entire time stamp file was
+locked for exclusive access when reading or writing to the file.
+Starting in
+.Nm sudoers
+1.8.15, individual records are locked in the time stamp file instead
+of the entire file and the lock is held for a longer period of time.
+This scheme is described below.
+.Pp
+The first record in the time stamp file is of type
+.Dv TS_LOCKEXCL
+and is used as a
+.Em lock
+record to prevent more than one
+.Nm sudo
+process from adding a new record at the same time.
+Once the desired time stamp record has been located or created (and
+locked), the
+.Dv TS_LOCKEXCL
+record is unlocked.
+The lock on the individual time stamp record, however, is held until
+authentication is complete.
+This allows
+.Nm sudoers
+to avoid prompting for a password multiple times when it
+is used more than once in a pipeline.
+.Pp
+Records of type
+.Dv TS_GLOBAL
+cannot be locked for a long period of time since doing so would
+interfere with other
+.Nm sudo
+processes.
+Instead, a separate lock record is used to prevent multiple
+.Nm sudo
+processes using the same terminal (or parent process ID) from
+prompting for a password as the same time.
+.Sh SEE ALSO
+.Xr sudoers @mansectform@ ,
+.Xr sudo @mansectsu@
+.Sh HISTORY
+Originally,
+.Nm sudo
+used a single zero-length file per user and the file's modification
+time was used as the time stamp.
+Later versions of
+.Nm sudo
+added restrictions on the ownership of the time stamp files and
+directory as well as checks on the validity of the time stamp itself.
+Notable changes were introduced in the following
+.Nm sudo
+versions:
+.Bl -tag -width 4n
+.It 1.4.0
+Support for tty-based time stamp file was added
+by appending the terminal name to the time stamp file name.
+.It 1.6.2
+The time stamp file was replaced by a per-user directory which
+contained any tty-based time stamp files.
+.It 1.6.3p2
+The target user name was added to the time stamp file name when the
+.Em targetpw
+option was set.
+.It 1.7.3
+Information about the terminal device was stored in
+tty-based time stamp files for validity checks.
+This included the terminal device numbers, inode number and, on systems
+where it was not updated when the device was written to, the inode change time.
+This helped prevent re-use of the time stamp file after logout.
+.It 1.8.6p7
+The terminal session ID was added to tty-based time stamp files to
+prevent re-use of the time stamp by the same user in a different
+terminal session.
+It also helped prevent re-use of the time stamp file on systems where
+the terminal device's inode change time was updated by writing.
+.It 1.8.10
+A new, multi-record time stamp file format was introduced that uses a
+single file per user.
+The terminal device's change time was not included since most
+systems now update the change time after a write is performed
+as required by POSIX.
+.It 1.8.15
+Individual records are locked in the time stamp file instead of the
+entire file and the lock is held until authentication is complete.
+.It 1.8.22
+The start time of the terminal session leader or parent process is
+now stored in non-global time stamp records.
+This prevents re-use of the time stamp file after logout in most cases.
+.Pp
+Support was added for the kernel-based tty time stamps available in
+.Ox
+which do not use an on-disk time stamp file.
+.It 1.9.15
+Time stamp file path names are now based on the invoking user-ID
+instead of the user name.
+This avoids problems with user names that include a path separator
+character.
+.El
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS.md file in the
+.Nm sudo
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you believe you have found a bug in
+.Nm sudo ,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm sudo
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+.Nm sudo
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudoreplay.man.in b/docs/sudoreplay.man.in
new file mode 100644
index 0000000..73dbd52
--- /dev/null
+++ b/docs/sudoreplay.man.in
@@ -0,0 +1,534 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2009-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.TH "SUDOREPLAY" "@mansectsu@" "January 16, 2023" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBsudoreplay\fR
+\- replay sudo session logs
+.SH "SYNOPSIS"
+.HP 11n
+\fBsudoreplay\fR
+[\fB\-FhnRS\fR]
+[\fB\-d\fR\ \fIdir\fR]
+[\fB\-f\fR\ \fIfilter\fR]
+[\fB\-m\fR\ \fInum\fR]
+[\fB\-s\fR\ \fInum\fR]
+ID[\fI@offset\fR]
+.HP 11n
+\fBsudoreplay\fR
+[\fB\-h\fR]
+[\fB\-d\fR\ \fIdir\fR]
+\fB\-l\fR
+[search\ expression]
+.SH "DESCRIPTION"
+\fBsudoreplay\fR
+plays back or lists the output logs created by
+\fBsudo\fR.
+When replaying,
+\fBsudoreplay\fR
+can play the session back in real-time, or the playback speed may be
+adjusted (faster or slower) based on the command line options.
+.PP
+The
+\fIID\fR
+should either be a six character sequence of digits and
+upper case letters, e.g.,
+\(lq0100A5\(rq
+or a path name.
+The
+\fIID\fR
+may include an optional
+\fI@offset\fR
+suffix which may be used to start replaying at a specific time offset.
+The
+\fI@offset\fR
+is specified as a number in seconds since the start of the session
+with an optional decimal fraction.
+.PP
+Path names may be relative to the I/O log directory
+\fI@iolog_dir@\fR
+(unless overridden by the
+\fB\-d\fR
+option) or fully qualified, beginning with a
+\(oq/\(cq
+character.
+When a command is run via
+\fBsudo\fR
+with
+\fIlog_output\fR
+enabled in the
+\fIsudoers\fR
+file, a
+\(lqTSID=ID\(rq
+string is logged via
+syslog(3)
+or to the
+\fBsudo\fR
+log file.
+The
+\fIID\fR
+may also be determined using
+\fBsudoreplay\fR's
+list mode.
+.PP
+In list mode,
+\fBsudoreplay\fR
+can be used to find the ID of a session based on a number of criteria
+such as the user, tty, or command run.
+.PP
+In replay mode, if the standard input and output are connected to a terminal
+and the
+\fB\-n\fR
+option is not specified,
+\fBsudoreplay\fR
+will operate interactively.
+In interactive mode,
+\fBsudoreplay\fR
+will attempt to adjust the terminal size to match that of the session and
+write directly to the terminal (not all terminals support this).
+Additionally, it will poll the keyboard and act on the following keys:
+.TP 14n
+\(oq\fR\en\fR\(cq or \(oq\fR\er\fR\(cq
+Skip to the next replay event; useful for long pauses.
+.TP 14n
+\(oq\fR\ \fR\(cq (space)
+Pause output; press any key to resume.
+.TP 14n
+\(oq<\(cq
+Reduce the playback speed by one half.
+.TP 14n
+\(oq>\(cq
+Double the playback speed.
+.PP
+The session can be interrupted via control-C.
+When the session has finished, the terminal is restored to its
+original size if it was changed during playback.
+.PP
+The options are as follows:
+.TP 8n
+\fB\-d\fR \fIdir\fR, \fB\--directory\fR=\fIdir\fR
+Store session logs in
+\fIdir\fR
+instead of the default,
+\fI@iolog_dir@\fR.
+.TP 8n
+\fB\-f\fR \fIfilter\fR, \fB\--filter\fR=\fIfilter\fR
+Select which I/O type(s) to display.
+By default,
+\fBsudoreplay\fR
+will display the command's standard output, standard error, and tty output.
+The
+\fIfilter\fR
+argument is a comma-separated list, consisting of one or more of following:
+\fIstdin\fR,
+\fIstdout\fR,
+\fIstderr\fR,
+\fIttyin\fR,
+and
+\fIttyout\fR.
+.TP 8n
+\fB\-F\fR, \fB\--follow\fR
+Enable
+\(lqfollow mode\(rq.
+When replaying a session,
+\fBsudoreplay\fR
+will ignore end-of-file and keep replaying until the log is complete.
+This can be used to replay a session that is still in progress,
+similar to
+\(lqtail -f\(rq.
+An I/O log file is considered to be complete when the write bits
+have been cleared on the session's timing file.
+Versions of
+\fBsudo\fR
+prior to 1.9.1 do not clear the write bits upon completion.
+.TP 8n
+\fB\-h\fR, \fB\--help\fR
+Display a short help message to the standard output and exit.
+.TP 8n
+\fB\-l\fR, \fB\--list\fR [\fIsearch expression\fR]
+Enable
+\(lqlist mode\(rq.
+In this mode,
+\fBsudoreplay\fR
+will list available sessions in a format similar to the
+\fBsudo\fR
+log file format, sorted by file name (or sequence number).
+Any control characters present in the log data are formated in octal
+with a leading
+\(oq#\(cq
+character.
+For example, a horizontal tab is displayed as
+\(oq#011\(cq
+and an embedded carriage return is displayed as
+\(oq#015\(cq.
+.sp
+If a
+\fIsearch expression\fR
+is specified, it will be used to restrict the IDs that are displayed.
+An expression is composed of the following predicates:
+.PP
+.RS 8n
+.PD 0
+.TP 8n
+command \fIpattern\fR
+Evaluates to true if the command run matches the POSIX extended
+regular expression
+\fIpattern\fR.
+.PD
+.TP 8n
+cwd \fIdirectory\fR
+Evaluates to true if the command was run with the specified current
+working directory.
+.TP 8n
+fromdate \fIdate\fR
+Evaluates to true if the command was run on or after
+\fIdate\fR.
+See
+\fIDate and time format\fR
+for a description of supported date and time formats.
+.TP 8n
+group \fIrunas_group\fR
+Evaluates to true if the command was run with the specified
+\fIrunas_group\fR.
+Unless a
+\fIrunas_group\fR
+was explicitly specified when
+\fBsudo\fR
+was run this field will be empty in the log.
+.TP 8n
+host \fIhostname\fR
+Evaluates to true if the command was run on the specified
+\fIhostname\fR.
+.TP 8n
+runas \fIrunas_user\fR
+Evaluates to true if the command was run as the specified
+\fIrunas_user\fR.
+By default,
+\fBsudo\fR
+runs commands as the
+\fBroot\fR
+user.
+.TP 8n
+todate \fIdate\fR
+Evaluates to true if the command was run on or prior to
+\fIdate\fR.
+See
+\fIDate and time format\fR
+for a description of supported date and time formats.
+.TP 8n
+tty \fItty name\fR
+Evaluates to true if the command was run on the specified terminal device.
+The
+\fItty name\fR
+should be specified without the
+\fI/dev/\fR
+prefix, e.g.,
+\fItty01\fR
+instead of
+\fI/dev/tty01\fR.
+.TP 8n
+user \fIuser name\fR
+Evaluates to true if the ID matches a command run by
+\fIuser name\fR.
+.PP
+Predicates may be abbreviated to the shortest unique string.
+.sp
+Predicates may be combined using
+\fIand\fR,
+\fIor\fR,
+and
+\fI\&!\fR
+operators as well as
+\(oq\&(\(cq
+and
+\(oq\&)\(cq
+grouping (parentheses must generally be escaped from the shell).
+The
+\fIand\fR
+operator is optional, adjacent predicates have an implied
+\fIand\fR
+unless separated by an
+\fIor\fR.
+.RE
+.TP 8n
+\fB\-m\fR, \fB\--max-wait\fR \fImax_wait\fR
+Specify an upper bound on how long to wait between key presses or output data.
+By default,
+\fBsudoreplay\fR
+will accurately reproduce the delays between key presses or program output.
+However, this can be tedious when the session includes long pauses.
+When the
+\fB\-m\fR
+option is specified,
+\fBsudoreplay\fR
+will limit these pauses to at most
+\fImax_wait\fR
+seconds.
+The value may be specified as a floating point number, e.g.,
+\fI2.5\fR.
+A
+\fImax_wait\fR
+of zero or less will eliminate the pauses entirely.
+.TP 8n
+\fB\-n\fR, \fB\--non-interactive\fR
+Do not prompt for user input or attempt to re-size the terminal.
+The session is written to the standard output, not directly to
+the user's terminal.
+.TP 8n
+\fB\-R\fR, \fB\--no-resize\fR
+Do not attempt to re-size the terminal to match the terminal size
+of the session.
+.TP 8n
+\fB\-S\fR, \fB\--suspend-wait\fR
+Wait while the command was suspended.
+By default,
+\fBsudoreplay\fR
+will ignore the time interval between when the command was suspended
+and when it was resumed.
+If the
+\fB\-S\fR
+option is specified,
+\fBsudoreplay\fR
+will wait instead.
+.TP 8n
+\fB\-s\fR, \fB\--speed\fR \fIspeed_factor\fR
+This option causes
+\fBsudoreplay\fR
+to adjust the number of seconds it will wait between key presses or
+program output.
+This can be used to slow down or speed up the display.
+For example, a
+\fIspeed_factor\fR
+of
+\fI2\fR
+would make the output twice as fast whereas a
+\fIspeed_factor\fR
+of
+\fI.5\fR
+would make the output twice as slow.
+.TP 8n
+\fB\-V\fR, \fB\--version\fR
+Print the
+\fBsudoreplay\fR
+versions version number and exit.
+.SS "Date and time format"
+The time and date may be specified multiple ways, common formats include:
+.TP 8n
+HH:MM:SS am MM/DD/CCYY timezone
+24 hour time may be used in place of am/pm.
+.TP 8n
+HH:MM:SS am Month, Day Year timezone
+24 hour time may be used in place of am/pm, and month and day names
+may be abbreviated.
+Month and day of the week names must be specified in English.
+.TP 8n
+CCYY-MM-DD HH:MM:SS
+ISO time format
+.TP 8n
+DD Month CCYY HH:MM:SS
+The month name may be abbreviated.
+.PP
+Either time or date may be omitted, the am/pm and timezone are optional.
+If no date is specified, the current day is assumed; if no time is
+specified, the first second of the specified date is used.
+The less significant parts of both time and date may also be omitted,
+in which case zero is assumed.
+.PP
+The following are all valid time and date specifications:
+.TP 8n
+now
+The current time and date.
+.TP 8n
+tomorrow
+Exactly one day from now.
+.TP 8n
+yesterday
+24 hours ago.
+.TP 8n
+2 hours ago
+2 hours ago.
+.TP 8n
+next Friday
+The first second of the Friday in the next (upcoming) week.
+Not to be confused with
+\(lqthis Friday\(rq
+which would match the Friday of the current week.
+.TP 8n
+last week
+The current time but 7 days ago.
+This is equivalent to
+\(lqa week ago\(rq.
+.TP 8n
+a fortnight ago
+The current time but 14 days ago.
+.TP 8n
+10:01 am 9/17/2009
+10:01 am, September 17, 2009.
+.TP 8n
+10:01 am
+10:01 am on the current day.
+.TP 8n
+10
+10:00 am on the current day.
+.TP 8n
+9/17/2009
+00:00 am, September 17, 2009.
+.TP 8n
+10:01 am Sep 17, 2009
+10:01 am, September 17, 2009.
+.PP
+Relative time specifications do not always work as expected.
+For example, the
+\(lqnext\(rq
+qualifier is intended to be used in conjunction with a day such as
+\(lqnext Monday\(rq.
+When used with units of weeks, months, years, etc
+the result will be one more than expected.
+For example,
+\(lqnext week\(rq
+will result in a time exactly two weeks from now, which is probably
+not what was intended.
+This will be addressed in a future version of
+\fBsudoreplay\fR.
+.SS "Debugging sudoreplay"
+\fBsudoreplay\fR
+versions 1.8.4 and higher support a flexible debugging framework
+that is configured via
+\fIDebug\fR
+lines in the
+sudo.conf(@mansectform@)
+file.
+.PP
+For more information on configuring
+sudo.conf(@mansectform@),
+refer to its manual.
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/sudo.conf\fR
+Debugging framework configuration
+.TP 26n
+\fI@iolog_dir@\fR
+The default I/O log directory.
+.TP 26n
+\fI@iolog_dir@/00/00/01/log\fR
+Example session log info.
+.TP 26n
+\fI@iolog_dir@/00/00/01/log.json\fR
+Example session log info (JSON format).
+.TP 26n
+\fI@iolog_dir@/00/00/01/stdin\fR
+Example session standard input log.
+.TP 26n
+\fI@iolog_dir@/00/00/01/stdout\fR
+Example session standard output log.
+.TP 26n
+\fI@iolog_dir@/00/00/01/stderr\fR
+Example session standard error log.
+.TP 26n
+\fI@iolog_dir@/00/00/01/ttyin\fR
+Example session tty input file.
+.TP 26n
+\fI@iolog_dir@/00/00/01/ttyout\fR
+Example session tty output file.
+.TP 26n
+\fI@iolog_dir@/00/00/01/timing\fR
+Example session timing file.
+.PP
+The
+\fIstdin\fR,
+\fIstdout\fR
+and
+\fIstderr\fR
+files will be empty unless
+\fBsudo\fR
+was used as part of a pipeline for a particular command.
+.SH "EXAMPLES"
+List sessions run by user
+\fImillert\fR:
+.nf
+.sp
+.RS 4n
+# sudoreplay -l user millert
+.RE
+.fi
+.PP
+List sessions run by user
+\fIbob\fR
+with a command containing the string vi:
+.nf
+.sp
+.RS 4n
+# sudoreplay -l user bob command vi
+.RE
+.fi
+.PP
+List sessions run by user
+\fIjeff\fR
+that match a regular expression:
+.nf
+.sp
+.RS 4n
+# sudoreplay -l user jeff command '/bin/[a-z]*sh'
+.RE
+.fi
+.PP
+List sessions run by jeff or bob on the console:
+.nf
+.sp
+.RS 4n
+# sudoreplay -l ( user jeff or user bob ) tty console
+.RE
+.fi
+.SH "SEE ALSO"
+script(1),
+sudo.conf(@mansectform@),
+sudo(@mansectsu@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS.md file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "BUGS"
+If you believe you have found a bug in
+\fBsudoreplay\fR,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBsudoreplay\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/sudoreplay.mdoc.in b/docs/sudoreplay.mdoc.in
new file mode 100644
index 0000000..005cf1f
--- /dev/null
+++ b/docs/sudoreplay.mdoc.in
@@ -0,0 +1,477 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 2009-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd January 16, 2023
+.Dt SUDOREPLAY @mansectsu@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm sudoreplay
+.Nd replay sudo session logs
+.Sh SYNOPSIS
+.Nm sudoreplay
+.Op Fl FhnRS
+.Op Fl d Ar dir
+.Op Fl f Ar filter
+.Op Fl m Ar num
+.Op Fl s Ar num
+.No ID Ns Op Ar @offset
+.Pp
+.Nm
+.Op Fl h
+.Op Fl d Ar dir
+.Fl l
+.Op search expression
+.Sh DESCRIPTION
+.Nm
+plays back or lists the output logs created by
+.Nm sudo .
+When replaying,
+.Nm
+can play the session back in real-time, or the playback speed may be
+adjusted (faster or slower) based on the command line options.
+.Pp
+The
+.Em ID
+should either be a six character sequence of digits and
+upper case letters, e.g.,
+.Dq 0100A5
+or a path name.
+The
+.Em ID
+may include an optional
+.Ar @offset
+suffix which may be used to start replaying at a specific time offset.
+The
+.Ar @offset
+is specified as a number in seconds since the start of the session
+with an optional decimal fraction.
+.Pp
+Path names may be relative to the I/O log directory
+.Pa @iolog_dir@
+(unless overridden by the
+.Fl d
+option) or fully qualified, beginning with a
+.Ql /
+character.
+When a command is run via
+.Nm sudo
+with
+.Em log_output
+enabled in the
+.Em sudoers
+file, a
+.Dq TSID=ID
+string is logged via
+.Xr syslog 3
+or to the
+.Nm sudo
+log file.
+The
+.Em ID
+may also be determined using
+.Nm sudoreplay Ns 's
+list mode.
+.Pp
+In list mode,
+.Nm
+can be used to find the ID of a session based on a number of criteria
+such as the user, tty, or command run.
+.Pp
+In replay mode, if the standard input and output are connected to a terminal
+and the
+.Fl n
+option is not specified,
+.Nm
+will operate interactively.
+In interactive mode,
+.Nm
+will attempt to adjust the terminal size to match that of the session and
+write directly to the terminal (not all terminals support this).
+Additionally, it will poll the keyboard and act on the following keys:
+.Bl -tag -width 12n
+.It So Li \en Sc No or So Li \er Sc
+Skip to the next replay event; useful for long pauses.
+.It So Li \ Sc Pq space
+Pause output; press any key to resume.
+.It Ql <
+Reduce the playback speed by one half.
+.It Ql >
+Double the playback speed.
+.El
+.Pp
+The session can be interrupted via control-C.
+When the session has finished, the terminal is restored to its
+original size if it was changed during playback.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl d Ar dir , Fl -directory Ns = Ns Ar dir
+Store session logs in
+.Ar dir
+instead of the default,
+.Pa @iolog_dir@ .
+.It Fl f Ar filter , Fl -filter Ns = Ns Ar filter
+Select which I/O type(s) to display.
+By default,
+.Nm
+will display the command's standard output, standard error, and tty output.
+The
+.Ar filter
+argument is a comma-separated list, consisting of one or more of following:
+.Em stdin ,
+.Em stdout ,
+.Em stderr ,
+.Em ttyin ,
+and
+.Em ttyout .
+.It Fl F , -follow
+Enable
+.Dq follow mode .
+When replaying a session,
+.Nm
+will ignore end-of-file and keep replaying until the log is complete.
+This can be used to replay a session that is still in progress,
+similar to
+.Dq tail -f .
+An I/O log file is considered to be complete when the write bits
+have been cleared on the session's timing file.
+Versions of
+.Nm sudo
+prior to 1.9.1 do not clear the write bits upon completion.
+.It Fl h , -help
+Display a short help message to the standard output and exit.
+.It Fl l , -list Op Ar search expression
+Enable
+.Dq list mode .
+In this mode,
+.Nm
+will list available sessions in a format similar to the
+.Nm sudo
+log file format, sorted by file name (or sequence number).
+Any control characters present in the log data are formatted in octal
+with a leading
+.Ql #
+character.
+For example, a horizontal tab is displayed as
+.Ql #011
+and an embedded carriage return is displayed as
+.Ql #015 .
+Space characters in the command name and arguments are also formatted in octal.
+.Pp
+If a
+.Ar search expression
+is specified, it will be used to restrict the IDs that are displayed.
+An expression is composed of the following predicates:
+.Bl -tag -width 6n
+.It command Ar pattern
+Evaluates to true if the command run matches the POSIX extended
+regular expression
+.Ar pattern .
+.It cwd Ar directory
+Evaluates to true if the command was run with the specified current
+working directory.
+.It fromdate Ar date
+Evaluates to true if the command was run on or after
+.Ar date .
+See
+.Sx Date and time format
+for a description of supported date and time formats.
+.It group Ar runas_group
+Evaluates to true if the command was run with the specified
+.Ar runas_group .
+Unless a
+.Ar runas_group
+was explicitly specified when
+.Nm sudo
+was run this field will be empty in the log.
+.It host Ar hostname
+Evaluates to true if the command was run on the specified
+.Ar hostname .
+.It runas Ar runas_user
+Evaluates to true if the command was run as the specified
+.Ar runas_user .
+By default,
+.Nm sudo
+runs commands as the
+.Sy root
+user.
+.It todate Ar date
+Evaluates to true if the command was run on or prior to
+.Ar date .
+See
+.Sx Date and time format
+for a description of supported date and time formats.
+.It tty Ar tty name
+Evaluates to true if the command was run on the specified terminal device.
+The
+.Ar tty name
+should be specified without the
+.Pa /dev/
+prefix, e.g.,
+.Pa tty01
+instead of
+.Pa /dev/tty01 .
+.It user Ar user name
+Evaluates to true if the ID matches a command run by
+.Ar user name .
+.El
+.Pp
+Predicates may be abbreviated to the shortest unique string.
+.Pp
+Predicates may be combined using
+.Em and ,
+.Em or ,
+and
+.Em \&!
+operators as well as
+.Ql \&(
+and
+.Ql \&)
+grouping (parentheses must generally be escaped from the shell).
+The
+.Em and
+operator is optional, adjacent predicates have an implied
+.Em and
+unless separated by an
+.Em or .
+.It Fl m , -max-wait Ar max_wait
+Specify an upper bound on how long to wait between key presses or output data.
+By default,
+.Nm
+will accurately reproduce the delays between key presses or program output.
+However, this can be tedious when the session includes long pauses.
+When the
+.Fl m
+option is specified,
+.Nm
+will limit these pauses to at most
+.Em max_wait
+seconds.
+The value may be specified as a floating point number, e.g.,
+.Em 2.5 .
+A
+.Em max_wait
+of zero or less will eliminate the pauses entirely.
+.It Fl n , -non-interactive
+Do not prompt for user input or attempt to re-size the terminal.
+The session is written to the standard output, not directly to
+the user's terminal.
+.It Fl R , -no-resize
+Do not attempt to re-size the terminal to match the terminal size
+of the session.
+.It Fl S , -suspend-wait
+Wait while the command was suspended.
+By default,
+.Nm
+will ignore the time interval between when the command was suspended
+and when it was resumed.
+If the
+.Fl S
+option is specified,
+.Nm
+will wait instead.
+.It Fl s , -speed Ar speed_factor
+This option causes
+.Nm
+to adjust the number of seconds it will wait between key presses or
+program output.
+This can be used to slow down or speed up the display.
+For example, a
+.Ar speed_factor
+of
+.Em 2
+would make the output twice as fast whereas a
+.Ar speed_factor
+of
+.Em .5
+would make the output twice as slow.
+.It Fl V , -version
+Print the
+.Nm
+versions version number and exit.
+.El
+.Ss Date and time format
+The time and date may be specified multiple ways, common formats include:
+.Bl -tag -width 6n
+.It HH:MM:SS am MM/DD/CCYY timezone
+24 hour time may be used in place of am/pm.
+.It HH:MM:SS am Month, Day Year timezone
+24 hour time may be used in place of am/pm, and month and day names
+may be abbreviated.
+Month and day of the week names must be specified in English.
+.It CCYY-MM-DD HH:MM:SS
+ISO time format
+.It DD Month CCYY HH:MM:SS
+The month name may be abbreviated.
+.El
+.Pp
+Either time or date may be omitted, the am/pm and timezone are optional.
+If no date is specified, the current day is assumed; if no time is
+specified, the first second of the specified date is used.
+The less significant parts of both time and date may also be omitted,
+in which case zero is assumed.
+.Pp
+The following are all valid time and date specifications:
+.Bl -tag -width 6n
+.It now
+The current time and date.
+.It tomorrow
+Exactly one day from now.
+.It yesterday
+24 hours ago.
+.It 2 hours ago
+2 hours ago.
+.It next Friday
+The first second of the Friday in the next (upcoming) week.
+Not to be confused with
+.Dq this Friday
+which would match the Friday of the current week.
+.It last week
+The current time but 7 days ago.
+This is equivalent to
+.Dq a week ago .
+.It a fortnight ago
+The current time but 14 days ago.
+.It 10:01 am 9/17/2009
+10:01 am, September 17, 2009.
+.It 10:01 am
+10:01 am on the current day.
+.It 10
+10:00 am on the current day.
+.It 9/17/2009
+00:00 am, September 17, 2009.
+.It 10:01 am Sep 17, 2009
+10:01 am, September 17, 2009.
+.El
+.Pp
+Relative time specifications do not always work as expected.
+For example, the
+.Dq next
+qualifier is intended to be used in conjunction with a day such as
+.Dq next Monday .
+When used with units of weeks, months, years, etc
+the result will be one more than expected.
+For example,
+.Dq next week
+will result in a time exactly two weeks from now, which is probably
+not what was intended.
+This will be addressed in a future version of
+.Nm .
+.Ss Debugging sudoreplay
+.Nm
+versions 1.8.4 and higher support a flexible debugging framework
+that is configured via
+.Em Debug
+lines in the
+.Xr sudo.conf @mansectform@
+file.
+.Pp
+For more information on configuring
+.Xr sudo.conf @mansectform@ ,
+refer to its manual.
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/sudo.conf
+Debugging framework configuration
+.It Pa @iolog_dir@
+The default I/O log directory.
+.It Pa @iolog_dir@/00/00/01/log
+Example session log info.
+.It Pa @iolog_dir@/00/00/01/log.json
+Example session log info (JSON format).
+.It Pa @iolog_dir@/00/00/01/stdin
+Example session standard input log.
+.It Pa @iolog_dir@/00/00/01/stdout
+Example session standard output log.
+.It Pa @iolog_dir@/00/00/01/stderr
+Example session standard error log.
+.It Pa @iolog_dir@/00/00/01/ttyin
+Example session tty input file.
+.It Pa @iolog_dir@/00/00/01/ttyout
+Example session tty output file.
+.It Pa @iolog_dir@/00/00/01/timing
+Example session timing file.
+.El
+.Pp
+The
+.Em stdin ,
+.Em stdout
+and
+.Em stderr
+files will be empty unless
+.Nm sudo
+was used as part of a pipeline for a particular command.
+.Sh EXAMPLES
+List sessions run by user
+.Em millert :
+.Bd -literal -offset 4n
+# sudoreplay -l user millert
+.Ed
+.Pp
+List sessions run by user
+.Em bob
+with a command containing the string vi:
+.Bd -literal -offset 4n
+# sudoreplay -l user bob command vi
+.Ed
+.Pp
+List sessions run by user
+.Em jeff
+that match a regular expression:
+.Bd -literal -offset 4n
+# sudoreplay -l user jeff command '/bin/[a-z]*sh'
+.Ed
+.Pp
+List sessions run by jeff or bob on the console:
+.Bd -literal -offset 4n
+# sudoreplay -l ( user jeff or user bob ) tty console
+.Ed
+.Sh SEE ALSO
+.Xr script 1 ,
+.Xr sudo.conf @mansectform@ ,
+.Xr sudo @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS.md file in the
+.Nm sudo
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh BUGS
+If you believe you have found a bug in
+.Nm ,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+.Nm sudo
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/visudo.man.in b/docs/visudo.man.in
new file mode 100644
index 0000000..0bad136
--- /dev/null
+++ b/docs/visudo.man.in
@@ -0,0 +1,548 @@
+.\" Automatically generated from an mdoc input file. Do not edit.
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 1996,1998-2005, 2007-2023
+.\" Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" Sponsored in part by the Defense Advanced Research Projects
+.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
+.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
+.\"
+.TH "VISUDO" "@mansectsu@" "July 27, 2023" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBvisudo\fR
+\- edit the sudoers file
+.SH "SYNOPSIS"
+.HP 7n
+\fBvisudo\fR
+[\fB\-chIOPqsV\fR]
+[[\fB\-f\fR]\ \fIsudoers\fR]
+.SH "DESCRIPTION"
+\fBvisudo\fR
+edits the
+\fIsudoers\fR
+file in a safe fashion, analogous to
+vipw(@mansectsu@).
+\fBvisudo\fR
+locks the
+\fIsudoers\fR
+file against multiple simultaneous edits, performs basic validity checks,
+and checks for syntax errors before installing the edited file.
+If the
+\fIsudoers\fR
+file is currently being edited you will receive a message to try again later.
+.PP
+If the
+\fIsudoers\fR
+file does not exist, it will be created unless the editor exits
+without writing to the file.
+.PP
+\fBvisudo\fR
+parses the
+\fIsudoers\fR
+file after editing and will not save the changes if there is a syntax error.
+Upon finding an error,
+\fBvisudo\fR
+will print a message stating the line number(s)
+where the error occurred and the user will receive the
+\(lqWhat now?\(rq
+prompt.
+At this point the user may enter
+\(oqe\(cq
+to re-edit the
+\fIsudoers\fR
+file,
+\(oqx\(cq
+to exit without saving the changes, or
+\(oqQ\(cq
+to quit and save changes.
+The
+\(oqQ\(cq
+option should be used with extreme caution because if
+\fBvisudo\fR
+believes there to be a syntax error, so will
+\fBsudo\fR.
+If
+\(oqe\(cq
+is typed to edit the
+\fIsudoers\fR
+file after a syntax error has been detected, the cursor will be placed on
+the line where the error occurred (if the editor supports this feature).
+.PP
+There are two
+\fIsudoers\fR
+settings that determine which editor
+\fBvisudo\fR
+will run.
+.TP 12n
+editor
+A colon
+(\(oq:\&\(cq)
+separated list of editors allowed to be used with
+\fBvisudo\fR.
+\fBvisudo\fR
+will choose the editor that matches the user's
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR,
+or
+\fREDITOR\fR
+environment variable if possible, or the first editor in the
+list that exists and is executable.
+\fBsudo\fR
+does not preserve the
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR,
+or
+\fREDITOR\fR
+environment variables unless they are present in the
+\fIenv_keep\fR
+list or the
+\fIenv_reset\fR
+option is disabled in the
+\fIsudoers\fR
+file.
+The default editor path is
+\fI@editor@\fR
+which can be set at compile time via the
+\fR--with-editor\fR
+configure option.
+.TP 12n
+env_editor
+If set,
+\fBvisudo\fR
+will use the value of the
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR,
+or
+\fREDITOR\fR
+environment variables before falling back on the default editor list.
+\fBvisudo\fR
+is typically run as root so this option may allow a user with
+\fBvisudo\fR
+privileges to run arbitrary commands as root without logging.
+An alternative is to place a colon-separated list of
+\(lqsafe\(rq
+editors in the
+\fIeditor\fR
+variable.
+\fBvisudo\fR
+will then only use
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR,
+or
+\fREDITOR\fR
+if they match a value specified in
+\fIeditor\fR.
+If the
+\fIenv_reset\fR
+flag is enabled, the
+\fRSUDO_EDITOR\fR,
+\fRVISUAL\fR,
+and/or
+\fREDITOR\fR
+environment variables must be present in the
+\fIenv_keep\fR
+list for the
+\fIenv_editor\fR
+flag to function when
+\fBvisudo\fR
+is invoked via
+\fBsudo\fR.
+The default value is
+\fI@env_editor@\fR,
+which can be set at compile time via the
+\fR--with-env-editor\fR
+configure option.
+.PP
+The options are as follows:
+.TP 8n
+\fB\-c\fR, \fB\--check\fR
+Enable
+\fIcheck-only\fR
+mode.
+The existing
+\fIsudoers\fR
+file (and any other files it includes) will be
+checked for syntax errors.
+If the path to the
+\fIsudoers\fR
+file was not specified,
+\fBvisudo\fR
+will also check the file ownership and permissions (see the
+\fB\-O\fR
+and
+\fB\-P\fR
+options).
+A message will be printed to the standard output describing the status of
+\fIsudoers\fR
+unless the
+\fB\-q\fR
+option was specified.
+If the check completes successfully,
+\fBvisudo\fR
+will exit with a value of 0.
+If an error is encountered,
+\fBvisudo\fR
+will exit with a value of 1.
+.TP 8n
+\fB\-f\fR \fIsudoers\fR, \fB\--file\fR=\fIsudoers\fR
+Specify an alternate
+\fIsudoers\fR
+file location, see below.
+As of version 1.8.27, the
+\fIsudoers\fR
+path can be specified without using the
+\fB\-f\fR
+option.
+.TP 8n
+\fB\-h\fR, \fB\--help\fR
+Display a short help message to the standard output and exit.
+.TP 8n
+\fB\-I\fR, \fB\--no-includes\fR
+Disable the editing of include files unless there is a pre-existing
+syntax error.
+By default,
+\fBvisudo\fR
+will edit the main
+\fIsudoers\fR
+file and any files included via
+\fI@include\fR
+or
+\fI#include\fR
+directives.
+Files included via
+\fI@includedir\fR
+or
+\fI#includedir\fR
+are never edited unless they contain a syntax error.
+.TP 8n
+\fB\-O\fR, \fB\--owner\fR
+Enforce the default ownership (user and group) of the
+\fIsudoers\fR
+file.
+In edit mode, the owner of the edited file will be set to the default.
+In check mode
+(\fB\-c\fR),
+an error will be reported if the owner is incorrect.
+This option is enabled by default if the
+\fIsudoers\fR
+file was not specified.
+.TP 8n
+\fB\-P\fR, \fB\--perms\fR
+Enforce the default permissions (mode) of the
+\fIsudoers\fR
+file.
+In edit mode, the permissions of the edited file will be set to the default.
+In check mode
+(\fB\-c\fR),
+an error will be reported if the file permissions are incorrect.
+This option is enabled by default if the
+\fIsudoers\fR
+file was not specified.
+.TP 8n
+\fB\-q\fR, \fB\--quiet\fR
+Enable
+\fIquiet\fR
+mode.
+In this mode details about syntax errors are not printed.
+This option is only useful when combined with
+the
+\fB\-c\fR
+option.
+.TP 8n
+\fB\-s\fR, \fB\--strict\fR
+Enable
+\fIstrict\fR
+checking of the
+\fIsudoers\fR
+file.
+If an alias is referenced but not actually defined
+or if there is a cycle in an alias,
+\fBvisudo\fR
+will consider this a syntax error.
+It is not possible to differentiate between an alias and a host
+name or user name that consists solely of uppercase letters, digits,
+and the underscore
+(\(oq_\(cq)
+character.
+.TP 8n
+\fB\-V\fR, \fB\--version\fR
+Print the
+\fBvisudo\fR
+and
+\fIsudoers\fR
+grammar versions and exit.
+.PP
+A
+\fIsudoers\fR
+file may be specified instead of the default,
+\fI@sysconfdir@/sudoers\fR.
+The temporary file used is the specified
+\fIsudoers\fR
+file with
+\(lq\.tmp\(rq
+appended to it.
+In
+\fIcheck-only\fR
+mode only,
+\(oq-\(cq
+may be used to indicate that
+\fIsudoers\fR
+will be read from the standard input.
+Because the policy is evaluated in its entirety, it is not sufficient
+to check an individual
+\fIsudoers\fR
+include file for syntax errors.
+.SS "Debugging and sudoers plugin arguments"
+\fBvisudo\fR
+versions 1.8.4 and higher support a flexible debugging framework
+that is configured via
+\fIDebug\fR
+lines in the
+sudo.conf(@mansectform@)
+file.
+.PP
+Starting with
+\fBsudo\fR
+1.8.12,
+\fBvisudo\fR
+will also parse the arguments to the
+\fIsudoers\fR
+plugin to override the default
+\fIsudoers\fR
+path name, user-ID, group-ID, and file mode.
+These arguments, if present, should be listed after the path to the plugin
+(i.e., after
+\fI@sudoers_plugin@\fR).
+Multiple arguments may be specified, separated by white space.
+For example:
+.nf
+.sp
+.RS 4n
+Plugin sudoers_policy @sudoers_plugin@ sudoers_mode=0400
+.RE
+.fi
+.PP
+The following arguments are supported:
+.TP 6n
+sudoers_file=pathname
+The
+\fIsudoers_file\fR
+argument can be used to override the default path to the
+\fIsudoers\fR
+file.
+.TP 6n
+sudoers_uid=user-ID
+The
+\fIsudoers_uid\fR
+argument can be used to override the default owner of the sudoers file.
+It should be specified as a numeric user-ID.
+.TP 6n
+sudoers_gid=group-ID
+The
+\fIsudoers_gid\fR
+argument can be used to override the default group of the sudoers file.
+It must be specified as a numeric group-ID (not a group name).
+.TP 6n
+sudoers_mode=mode
+The
+\fIsudoers_mode\fR
+argument can be used to override the default file mode for the sudoers file.
+It should be specified as an octal value.
+.PP
+For more information on configuring
+sudo.conf(@mansectform@),
+refer to its manual.
+.SH "ENVIRONMENT"
+The following environment variables may be consulted depending on
+the value of the
+\fIeditor\fR
+and
+\fIenv_editor\fR
+\fIsudoers\fR
+settings:
+.TP 17n
+\fRSUDO_EDITOR\fR
+Invoked by
+\fBvisudo\fR
+as the editor to use
+.TP 17n
+\fRVISUAL\fR
+Used by
+\fBvisudo\fR
+if
+\fRSUDO_EDITOR\fR
+is not set
+.TP 17n
+\fREDITOR\fR
+Used by
+\fBvisudo\fR
+if neither
+\fRSUDO_EDITOR\fR
+nor
+\fRVISUAL\fR
+is set
+.SH "FILES"
+.TP 26n
+\fI@sysconfdir@/sudo.conf\fR
+Sudo front-end configuration
+.TP 26n
+\fI@sysconfdir@/sudoers\fR
+List of who can run what
+.TP 26n
+\fI@sysconfdir@/sudoers.tmp\fR
+Default temporary file used by visudo
+.SH "DIAGNOSTICS"
+In addition to reporting
+\fIsudoers\fR
+syntax errors,
+\fBvisudo\fR
+may produce the following messages:
+.TP 6n
+\fRsudoers file busy, try again later.\fR
+Someone else is currently editing the
+\fIsudoers\fR
+file.
+.TP 6n
+\fR@sysconfdir@/sudoers: Permission denied\fR
+You didn't run
+\fBvisudo\fR
+as root.
+.TP 6n
+\fRyou do not exist in the passwd database\fR
+Your user-ID does not appear in the system passwd database.
+.TP 6n
+\fRWarning: {User,Runas,Host,Cmnd}_Alias referenced but not defined\fR
+Either you are trying to use an undeclared {User,Runas,Host,Cmnd}_Alias
+or you have a user or host name listed that consists solely of
+uppercase letters, digits, and the underscore
+(\(oq_\(cq)
+character.
+In the latter case, you can ignore the warnings
+(\fBsudo\fR
+will not complain)
+\&.
+The message is prefixed with the path name of the
+\fIsudoers\fR
+file and the line number where the undefined alias was used.
+In
+\fB\-s\fR
+(strict) mode these are errors, not warnings.
+.TP 6n
+\fRWarning: unused {User,Runas,Host,Cmnd}_Alias\fR
+The specified {User,Runas,Host,Cmnd}_Alias was defined but never
+used.
+The message is prefixed with the path name of the
+\fIsudoers\fR
+file and the line number where the unused alias was defined.
+You may wish to comment out or remove the unused alias.
+.TP 6n
+\fRWarning: cycle in {User,Runas,Host,Cmnd}_Alias\fR
+The specified {User,Runas,Host,Cmnd}_Alias includes a reference to
+itself, either directly or through an alias it includes.
+The message is prefixed with the path name of the
+\fIsudoers\fR
+file and the line number where the cycle was detected.
+This is only a warning unless
+\fBvisudo\fR
+is run in
+\fB\-s\fR
+(strict) mode as
+\fBsudo\fR
+will ignore cycles when parsing
+the
+\fIsudoers\fR
+file.
+.TP 6n
+\fRignoring editor backup file\fR
+While processing a
+\fI@includedir\fR
+or
+\fI#includedir\fR,
+a file was found with a name that ends in
+\(oq~\(cq
+or
+\fI.bak\fR.
+Such files are skipped by
+\fBsudo\fR
+and
+\fBvisudo\fR.
+.TP 6n
+\fRignoring file name containing '.'\fR
+While processing a
+\fI@includedir\fR
+or
+\fI#includedir\fR,
+a file was found with a name that contains a
+\(oq.\&\(cq
+character.
+Such files are skipped by
+\fBsudo\fR
+and
+\fBvisudo\fR.
+.TP 6n
+\fRunknown defaults entry \&"name\&"\fR
+The
+\fIsudoers\fR
+file contains a
+\fIDefaults\fR
+setting not recognized by
+\fBvisudo\fR.
+.SH "SEE ALSO"
+vi(1),
+sudo.conf(@mansectform@),
+sudoers(@mansectform@),
+sudo(@mansectsu@),
+vipw(@mansectsu@)
+.SH "AUTHORS"
+Many people have worked on
+\fBsudo\fR
+over the years; this version consists of code written primarily by:
+.sp
+.RS 6n
+Todd C. Miller
+.RE
+.PP
+See the CONTRIBUTORS.md file in the
+\fBsudo\fR
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+\fBsudo\fR.
+.SH "CAVEATS"
+There is no easy way to prevent a user from gaining a root shell if
+the editor used by
+\fBvisudo\fR
+allows shell escapes.
+.SH "BUGS"
+If you believe you have found a bug in
+\fBvisudo\fR,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.SH "SUPPORT"
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.SH "DISCLAIMER"
+\fBvisudo\fR
+is provided
+\(lqAS IS\(rq
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+\fBsudo\fR
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/docs/visudo.mdoc.in b/docs/visudo.mdoc.in
new file mode 100644
index 0000000..f91430d
--- /dev/null
+++ b/docs/visudo.mdoc.in
@@ -0,0 +1,525 @@
+.\"
+.\" SPDX-License-Identifier: ISC
+.\"
+.\" Copyright (c) 1996,1998-2005, 2007-2023
+.\" Todd C. Miller <Todd.Miller@sudo.ws>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" Sponsored in part by the Defense Advanced Research Projects
+.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
+.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
+.\"
+.Dd July 27, 2023
+.Dt VISUDO @mansectsu@
+.Os Sudo @PACKAGE_VERSION@
+.Sh NAME
+.Nm visudo
+.Nd edit the sudoers file
+.Sh SYNOPSIS
+.Nm visudo
+.Op Fl chIOPqsV
+.Op Bo Fl f Bc Ar sudoers
+.Sh DESCRIPTION
+.Nm
+edits the
+.Em sudoers
+file in a safe fashion, analogous to
+.Xr vipw @mansectsu@ .
+.Nm
+locks the
+.Em sudoers
+file against multiple simultaneous edits, performs basic validity checks,
+and checks for syntax errors before installing the edited file.
+If the
+.Em sudoers
+file is currently being edited you will receive a message to try again later.
+.Pp
+If the
+.Em sudoers
+file does not exist, it will be created unless the editor exits
+without writing to the file.
+.Pp
+.Nm
+parses the
+.Em sudoers
+file after editing and will not save the changes if there is a syntax error.
+Upon finding an error,
+.Nm
+will print a message stating the line number(s)
+where the error occurred and the user will receive the
+.Dq What now?
+prompt.
+At this point the user may enter
+.Ql e
+to re-edit the
+.Em sudoers
+file,
+.Ql x
+to exit without saving the changes, or
+.Ql Q
+to quit and save changes.
+The
+.Ql Q
+option should be used with extreme caution because if
+.Nm
+believes there to be a syntax error, so will
+.Nm sudo .
+If
+.Ql e
+is typed to edit the
+.Em sudoers
+file after a syntax error has been detected, the cursor will be placed on
+the line where the error occurred (if the editor supports this feature).
+.Pp
+There are two
+.Em sudoers
+settings that determine which editor
+.Nm visudo
+will run.
+.Bl -tag -width "env_editor"
+.It editor
+A colon
+.Pq Ql :\&
+separated list of editors allowed to be used with
+.Nm .
+.Nm
+will choose the editor that matches the user's
+.Ev SUDO_EDITOR ,
+.Ev VISUAL ,
+or
+.Ev EDITOR
+environment variable if possible, or the first editor in the
+list that exists and is executable.
+.Nm sudo
+does not preserve the
+.Ev SUDO_EDITOR ,
+.Ev VISUAL ,
+or
+.Ev EDITOR
+environment variables unless they are present in the
+.Em env_keep
+list or the
+.Em env_reset
+option is disabled in the
+.Em sudoers
+file.
+The default editor path is
+.Pa @editor@
+which can be set at compile time via the
+.Li --with-editor
+configure option.
+.It env_editor
+If set,
+.Nm
+will use the value of the
+.Ev SUDO_EDITOR ,
+.Ev VISUAL ,
+or
+.Ev EDITOR
+environment variables before falling back on the default editor list.
+.Nm visudo
+is typically run as root so this option may allow a user with
+.Nm visudo
+privileges to run arbitrary commands as root without logging.
+An alternative is to place a colon-separated list of
+.Dq safe
+editors in the
+.Em editor
+variable.
+.Nm
+will then only use
+.Ev SUDO_EDITOR ,
+.Ev VISUAL ,
+or
+.Ev EDITOR
+if they match a value specified in
+.Em editor .
+If the
+.Em env_reset
+flag is enabled, the
+.Ev SUDO_EDITOR ,
+.Ev VISUAL ,
+and/or
+.Ev EDITOR
+environment variables must be present in the
+.Em env_keep
+list for the
+.Em env_editor
+flag to function when
+.Nm
+is invoked via
+.Nm sudo .
+The default value is
+.Em @env_editor@ ,
+which can be set at compile time via the
+.Li --with-env-editor
+configure option.
+.El
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl c , -check
+Enable
+.Em check-only
+mode.
+The existing
+.Em sudoers
+file (and any other files it includes) will be
+checked for syntax errors.
+If the path to the
+.Em sudoers
+file was not specified,
+.Nm
+will also check the file ownership and permissions (see the
+.Fl O
+and
+.Fl P
+options).
+A message will be printed to the standard output describing the status of
+.Em sudoers
+unless the
+.Fl q
+option was specified.
+If the check completes successfully,
+.Nm
+will exit with a value of 0.
+If an error is encountered,
+.Nm
+will exit with a value of 1.
+.It Fl f Ar sudoers , Fl -file Ns = Ns Ar sudoers
+Specify an alternate
+.Em sudoers
+file location, see below.
+As of version 1.8.27, the
+.Em sudoers
+path can be specified without using the
+.Fl f
+option.
+.It Fl h , -help
+Display a short help message to the standard output and exit.
+.It Fl I , -no-includes
+Disable the editing of include files unless there is a pre-existing
+syntax error.
+By default,
+.Nm
+will edit the main
+.Ar sudoers
+file and any files included via
+.Em @include
+or
+.Em #include
+directives.
+Files included via
+.Em @includedir
+or
+.Em #includedir
+are never edited unless they contain a syntax error.
+.It Fl O , -owner
+Enforce the default ownership (user and group) of the
+.Em sudoers
+file.
+In edit mode, the owner of the edited file will be set to the default.
+In check mode
+.Pq Fl c ,
+an error will be reported if the owner is incorrect.
+This option is enabled by default if the
+.Em sudoers
+file was not specified.
+.It Fl P , -perms
+Enforce the default permissions (mode) of the
+.Em sudoers
+file.
+In edit mode, the permissions of the edited file will be set to the default.
+In check mode
+.Pq Fl c ,
+an error will be reported if the file permissions are incorrect.
+This option is enabled by default if the
+.Em sudoers
+file was not specified.
+.It Fl q , -quiet
+Enable
+.Em quiet
+mode.
+In this mode details about syntax errors are not printed.
+This option is only useful when combined with
+the
+.Fl c
+option.
+.It Fl s , -strict
+Enable
+.Em strict
+checking of the
+.Em sudoers
+file.
+If an alias is referenced but not actually defined
+or if there is a cycle in an alias,
+.Nm
+will consider this a syntax error.
+It is not possible to differentiate between an alias and a host
+name or user name that consists solely of uppercase letters, digits,
+and the underscore
+.Pq Ql _
+character.
+.It Fl V , -version
+Print the
+.Nm
+and
+.Em sudoers
+grammar versions and exit.
+.El
+.Pp
+A
+.Em sudoers
+file may be specified instead of the default,
+.Pa @sysconfdir@/sudoers .
+The temporary file used is the specified
+.Em sudoers
+file with
+.Dq \.tmp
+appended to it.
+In
+.Em check-only
+mode only,
+.Ql -
+may be used to indicate that
+.Em sudoers
+will be read from the standard input.
+Because the policy is evaluated in its entirety, it is not sufficient
+to check an individual
+.Em sudoers
+include file for syntax errors.
+.Ss Debugging and sudoers plugin arguments
+.Nm
+versions 1.8.4 and higher support a flexible debugging framework
+that is configured via
+.Em Debug
+lines in the
+.Xr sudo.conf @mansectform@
+file.
+.Pp
+Starting with
+.Nm sudo
+1.8.12,
+.Nm
+will also parse the arguments to the
+.Em sudoers
+plugin to override the default
+.Em sudoers
+path name, user-ID, group-ID, and file mode.
+These arguments, if present, should be listed after the path to the plugin
+(i.e., after
+.Pa @sudoers_plugin@ ) .
+Multiple arguments may be specified, separated by white space.
+For example:
+.Bd -literal -offset 4n
+Plugin sudoers_policy @sudoers_plugin@ sudoers_mode=0400
+.Ed
+.Pp
+The following arguments are supported:
+.Bl -tag -width 4n
+.It sudoers_file=pathname
+The
+.Em sudoers_file
+argument can be used to override the default path to the
+.Em sudoers
+file.
+.It sudoers_uid=user-ID
+The
+.Em sudoers_uid
+argument can be used to override the default owner of the sudoers file.
+It should be specified as a numeric user-ID.
+.It sudoers_gid=group-ID
+The
+.Em sudoers_gid
+argument can be used to override the default group of the sudoers file.
+It must be specified as a numeric group-ID (not a group name).
+.It sudoers_mode=mode
+The
+.Em sudoers_mode
+argument can be used to override the default file mode for the sudoers file.
+It should be specified as an octal value.
+.El
+.Pp
+For more information on configuring
+.Xr sudo.conf @mansectform@ ,
+refer to its manual.
+.Sh ENVIRONMENT
+The following environment variables may be consulted depending on
+the value of the
+.Em editor
+and
+.Em env_editor
+.Em sudoers
+settings:
+.Bl -tag -width 15n
+.It Ev SUDO_EDITOR
+Invoked by
+.Nm
+as the editor to use
+.It Ev VISUAL
+Used by
+.Nm
+if
+.Ev SUDO_EDITOR
+is not set
+.It Ev EDITOR
+Used by
+.Nm
+if neither
+.Ev SUDO_EDITOR
+nor
+.Ev VISUAL
+is set
+.El
+.Sh FILES
+.Bl -tag -width 24n
+.It Pa @sysconfdir@/sudo.conf
+Sudo front-end configuration
+.It Pa @sysconfdir@/sudoers
+List of who can run what
+.It Pa @sysconfdir@/sudoers.tmp
+Default temporary file used by visudo
+.El
+.Sh DIAGNOSTICS
+In addition to reporting
+.Em sudoers
+syntax errors,
+.Nm
+may produce the following messages:
+.Bl -tag -width 4n
+.It Li sudoers file busy, try again later.
+Someone else is currently editing the
+.Em sudoers
+file.
+.It Li @sysconfdir@/sudoers: Permission denied
+You didn't run
+.Nm
+as root.
+.It Li you do not exist in the passwd database
+Your user-ID does not appear in the system passwd database.
+.It Li Warning: {User,Runas,Host,Cmnd}_Alias referenced but not defined
+Either you are trying to use an undeclared {User,Runas,Host,Cmnd}_Alias
+or you have a user or host name listed that consists solely of
+uppercase letters, digits, and the underscore
+.Pq Ql _
+character.
+In the latter case, you can ignore the warnings
+.Po
+.Nm sudo
+will not complain
+.Pc .
+The message is prefixed with the path name of the
+.Em sudoers
+file and the line number where the undefined alias was used.
+In
+.Fl s
+(strict) mode these are errors, not warnings.
+.It Li Warning: unused {User,Runas,Host,Cmnd}_Alias
+The specified {User,Runas,Host,Cmnd}_Alias was defined but never
+used.
+The message is prefixed with the path name of the
+.Em sudoers
+file and the line number where the unused alias was defined.
+You may wish to comment out or remove the unused alias.
+.It Li Warning: cycle in {User,Runas,Host,Cmnd}_Alias
+The specified {User,Runas,Host,Cmnd}_Alias includes a reference to
+itself, either directly or through an alias it includes.
+The message is prefixed with the path name of the
+.Em sudoers
+file and the line number where the cycle was detected.
+This is only a warning unless
+.Nm
+is run in
+.Fl s
+(strict) mode as
+.Nm sudo
+will ignore cycles when parsing
+the
+.Em sudoers
+file.
+.It Li ignoring editor backup file
+While processing a
+.Em @includedir
+or
+.Em #includedir ,
+a file was found with a name that ends in
+.Ql ~
+or
+.Em .bak .
+Such files are skipped by
+.Nm sudo
+and
+.Nm .
+.It Li ignoring file name containing '.'
+While processing a
+.Em @includedir
+or
+.Em #includedir ,
+a file was found with a name that contains a
+.Ql .\&
+character.
+Such files are skipped by
+.Nm sudo
+and
+.Nm .
+.It Li unknown defaults entry \&"name\&"
+The
+.Em sudoers
+file contains a
+.Em Defaults
+setting not recognized by
+.Nm .
+.El
+.Sh SEE ALSO
+.Xr vi 1 ,
+.Xr sudo.conf @mansectform@ ,
+.Xr sudoers @mansectform@ ,
+.Xr sudo @mansectsu@ ,
+.Xr vipw @mansectsu@
+.Sh AUTHORS
+Many people have worked on
+.Nm sudo
+over the years; this version consists of code written primarily by:
+.Bd -ragged -offset indent
+.An Todd C. Miller
+.Ed
+.Pp
+See the CONTRIBUTORS.md file in the
+.Nm sudo
+distribution (https://www.sudo.ws/about/contributors/) for an
+exhaustive list of people who have contributed to
+.Nm sudo .
+.Sh CAVEATS
+There is no easy way to prevent a user from gaining a root shell if
+the editor used by
+.Nm
+allows shell escapes.
+.Sh BUGS
+If you believe you have found a bug in
+.Nm ,
+you can submit a bug report at https://bugzilla.sudo.ws/
+.Sh SUPPORT
+Limited free support is available via the sudo-users mailing list,
+see https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or
+search the archives.
+.Sh DISCLAIMER
+.Nm
+is provided
+.Dq AS IS
+and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed.
+See the LICENSE.md file distributed with
+.Nm sudo
+or https://www.sudo.ws/about/license/ for complete details.
diff --git a/etc/codespell.exclude b/etc/codespell.exclude
new file mode 100644
index 0000000..b89f656
--- /dev/null
+++ b/etc/codespell.exclude
@@ -0,0 +1,35 @@
+ "You empty-headed animal food trough wiper!",
+ * Returns true if any tags set in nt differ between ot and nt, else false.
+#define TAGS_CHANGED(ot, nt) \
+ ((TAG_SET((nt).follow) && (nt).follow != (ot).follow) || \
+ (TAG_SET((nt).intercept) && (nt).intercept != (ot).intercept) || \
+ (TAG_SET((nt).log_input) && (nt).log_input != (ot).log_input) || \
+ (TAG_SET((nt).log_output) && (nt).log_output != (ot).log_output) || \
+ (TAG_SET((nt).noexec) && (nt).noexec != (ot).noexec) || \
+ (TAG_SET((nt).nopasswd) && (nt).nopasswd != (ot).nopasswd) || \
+ (TAG_SET((nt).setenv) && (nt).setenv != (ot).setenv) || \
+ (TAG_SET((nt).send_mail) && (nt).send_mail != (ot).send_mail))
+ sv sw ta te tg th tr uk ur vi wa wo zh_CN zh_HK
+ if (!PyArg_ParseTupleAndKeywords(py_args ? py_args : py_empty, py_kwargs, "Ois|i:sudo.ConvMessage", (char **)keywords,
+ $ans = <STDIN>;
+ if ($ans =~ /^[yY]/) {
+.nr BA @BAMAN@
+.if \n(BA \{\
+.Nd convert between sudoers file formats
+.Nd configuration for sudo front-end
+.Nd execute a command as another user
+.Nd Sudo log server protocol
+.Nd configuration for sudo_logsrvd
+.Nd sudo event and I/O log server
+.Nd Sudo Plugin API
+.Nd Sudo Plugin API (Python)
+.Nd send sudo I/O log to log server
+.Nd sudo LDAP configuration
+.Nd default sudo security policy plugin
+.Nd Sudoers Time Stamp Format
+.Nd replay sudo session logs
+.Nd edit the sudoers file
+ * If path doesn't end in /, return true iff cmnd & path name the same inode;
+ * Tim Fraser
+ echo ".Nd sudo" >> conftest
+ * as per FIPS 180-4: Secure Hash Standard (SHS)
diff --git a/etc/codespell.ignore b/etc/codespell.ignore
new file mode 100644
index 0000000..acf70b0
--- /dev/null
+++ b/etc/codespell.ignore
@@ -0,0 +1,19 @@
+SOM
+VAS
+alloced
+anull
+clen
+edn
+fIDN
+fpt
+ist
+nome
+numer
+pleas
+sav
+siz
+statics
+thur
+toke
+vas
+wit
diff --git a/etc/codespell.skip b/etc/codespell.skip
new file mode 100644
index 0000000..bbf3d02
--- /dev/null
+++ b/etc/codespell.skip
@@ -0,0 +1,25 @@
+\.in\.sed$
+/data
+Makefile\.in
+^ChangeLog$
+^MANIFEST$
+^aclocal\.m4$
+^autogen\.sh$
+^config\.h\.in$
+^configure$
+^docs/.*\.man\.in$
+^docs/CONTRIBUTORS$
+^etc/codespell
+^lib/util/fnmatch\.c$
+^lib/util/getaddrinfo\.c$
+^lib/zlib/
+^libtool$
+^m4/libtool\.m4$
+^m4/lt.*\.m4$
+^plugins/sudoers/po/
+^po/
+^scripts/config\.guess$
+^scripts/config\.sub$
+^scripts/ltmain\.sh$
+^scripts/mkinstalldirs$
+^scripts/pp$
diff --git a/etc/init.d/aix.sh.in b/etc/init.d/aix.sh.in
new file mode 100644
index 0000000..3d11241
--- /dev/null
+++ b/etc/init.d/aix.sh.in
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Simple AIX rc.d script to remove the sudo timestamp directory on boot.
+# This is needed because AIX does not have /var/run.
+# Install as /etc/rc.d/init.d/sudo with a link /etc/rc.d/rc2.d/S90sudo
+#
+
+PATH=/usr/sbin:/usr/bin:/sbin
+export PATH
+
+TSDIR="@rundir@/ts"
+rval=0
+
+case "$1" in
+start)
+ echo "Removing the $TSDIR directory"
+ rm -rf "$TSDIR"
+ ;;
+*)
+ echo "usage: $0 start"
+ rval=1
+ ;;
+esac
+
+exit $rval
diff --git a/etc/init.d/hpux.sh.in b/etc/init.d/hpux.sh.in
new file mode 100644
index 0000000..5a76bd2
--- /dev/null
+++ b/etc/init.d/hpux.sh.in
@@ -0,0 +1,27 @@
+#!/sbin/sh
+#
+# Simple HP-UX init.d script to remove the sudo timestamp directory on boot.
+# This is needed because HP-UX does not clear /var/run on its own.
+# Install as /sbin/init.d/sudo with a link /sbin/rc2.d/S900sudo
+#
+
+PATH=/usr/sbin:/usr/bin:/sbin
+export PATH
+
+TSDIR="@rundir@/ts"
+rval=0
+
+case "$1" in
+start_msg)
+ echo "Removing the $TSDIR directory"
+ ;;
+start)
+ rm -rf "$TSDIR"
+ ;;
+*)
+ echo "usage: $0 {start|start_msg}"
+ rval=1
+ ;;
+esac
+
+exit $rval
diff --git a/etc/init.d/sudo.conf.in b/etc/init.d/sudo.conf.in
new file mode 100644
index 0000000..dfae56b
--- /dev/null
+++ b/etc/init.d/sudo.conf.in
@@ -0,0 +1,6 @@
+# Create an empty sudo time stamp directory on OSes using systemd.
+# Sudo will create the directory itself but this can cause problems
+# on systems that have SELinux enabled since the directories will be
+# created with the user's security context.
+d @rundir@ 0711 root root
+D @rundir@/ts 0700 root root
diff --git a/etc/macos-background.png b/etc/macos-background.png
new file mode 100644
index 0000000..4153667
--- /dev/null
+++ b/etc/macos-background.png
Binary files differ
diff --git a/etc/sudo-logsrvd.pp b/etc/sudo-logsrvd.pp
new file mode 100644
index 0000000..dd65f51
--- /dev/null
+++ b/etc/sudo-logsrvd.pp
@@ -0,0 +1,272 @@
+%set
+ name="sudo-logsrvd"
+ summary="Sudo event and I/O log server"
+ description="The sudo_logsrvd daemon collects event and I/O logs \
+from sudo clients.
+This makes it possible to have all sudo I/O logs on a central server."
+ vendor="Todd C. Miller"
+ copyright="(c) 2019-2021 Todd C. Miller"
+
+%if [aix]
+ # Convert to 4 part version for AIX, including patch level
+ pp_aix_version=`echo $version|sed -e 's/^\([0-9]*\.[0-9]*\.[0-9]*\)p\([0-9]*\)$/\1.\2/' -e 's/^\([0-9]*\.[0-9]*\.[0-9]*\)[^0-9\.].*$/\1/' -e 's/^\([0-9]*\.[0-9]*\.[0-9]*\)$/\1.0/'`
+
+ # Don't use sudo to list the package.
+ pp_aix_sudo=
+%endif
+
+%if [sd]
+ pp_sd_vendor_tag="TCM"
+%endif
+
+%if [solaris]
+ pp_solaris_name="TCM${name}"
+ pp_solaris_pstamp=`/usr/bin/date "+%B %d, %Y"`
+%endif
+
+%if [macos]
+ # System Integrity Protection on macOS won't allow us to write
+ # directly to /etc or /var. We must install in /private instead.
+ case "$sysconfdir" in
+ /etc|/etc/*)
+ mkdir -p ${pp_destdir}/private
+ chmod 755 ${pp_destdir}/private
+ if test -d ${pp_destdir}/etc; then
+ mv ${pp_destdir}/etc ${pp_destdir}/private/etc
+ fi
+ sysconfdir="/private${sysconfdir}"
+ ;;
+ esac
+ case "$vardir" in
+ /var|/var/*)
+ mkdir -p ${pp_destdir}/private
+ chmod 755 ${pp_destdir}/private
+ if test -d ${pp_destdir}/var; then
+ mv ${pp_destdir}/var ${pp_destdir}/private/var
+ fi
+ vardir="/private${vardir}"
+ ;;
+ esac
+ case "$rundir" in
+ /var|/var/*)
+ mkdir -p ${pp_destdir}/private
+ chmod 755 ${pp_destdir}/private
+ if test -d ${pp_destdir}/var; then
+ mv ${pp_destdir}/var ${pp_destdir}/private/var
+ fi
+ rundir="/private${rundir}"
+ ;;
+ esac
+%endif
+
+%if [rpm,deb]
+ # Convert patch level into release and remove from version
+ pp_rpm_release="`expr \( $version : '.*p\([0-9][0-9]*\)$' \| 0 \) + 1`"
+ pp_rpm_version="`expr \( $version : '\(.*\)p[0-9][0-9]*$' \| $version \)`"
+ pp_rpm_license="BSD"
+ pp_rpm_url="https://www.sudo.ws"
+ pp_rpm_group="Applications/System"
+ pp_rpm_packager="Todd C. Miller <Todd.Miller@sudo.ws>"
+%else
+ # We install sudo_logsrvd.conf from the example dir during post-install
+ rm -f ${pp_destdir}$sysconfdir/sudo_logsrvd.conf
+%endif
+
+ # Stash original docdir and exampledir
+ odocdir="${docdir}"
+ oexampledir="${exampledir}"
+
+ # docdir and exampledir are installed with "sudo" as the package
+ # name which may not be correct.
+ docdir="`echo \"${docdir}\" | sed 's#/sudo$#/'\"${name}\"'#'`"
+ if test "${exampledir}" = "${odocdir}/examples"; then
+ exampledir="${docdir}/examples"
+ else
+ exampledir="`echo \"${exampledir}\" | sed 's#/sudo$#/'\"${name}\"'#'`"
+ fi
+
+ # For RedHat the doc dir is expected to include version and release
+ case "$pp_rpm_distro" in
+ centos*|rhel*|f[0-9]*)
+ docdir="${docdir}-${pp_rpm_version}-${pp_rpm_release}"
+ exampledir="${docdir}/examples"
+ ;;
+ esac
+
+ # Copy docdir and exampledir to new names if needed
+ if test ! -d "${pp_destdir}${docdir}"; then
+ cp -R ${pp_destdir}${odocdir} ${pp_destdir}${docdir}
+ find ${pp_destdir}${docdir} -depth | sed "s#^${pp_destdir}##" >> ${pp_wrkdir}/pp_cleanup
+ fi
+ if test ! -d "${pp_destdir}${exampledir}"; then
+ cp -R ${pp_destdir}${oexampledir} ${pp_destdir}${exampledir}
+ find ${pp_destdir}${exampledir} -depth | sed "s#^${pp_destdir}##" >> ${pp_wrkdir}/pp_cleanup
+ fi
+
+%if [deb]
+ pp_deb_maintainer="$pp_rpm_packager"
+ pp_deb_release="$pp_rpm_release"
+ pp_deb_version="$pp_rpm_version"
+ pp_deb_section=admin
+ install -D -m 644 ${pp_destdir}$docdir/LICENSE.md ${pp_wrkdir}/${name}/usr/share/doc/${name}/copyright
+ install -D -m 644 ${pp_destdir}$docdir/ChangeLog ${pp_wrkdir}/${name}/usr/share/doc/${name}/changelog
+ gzip -9f ${pp_wrkdir}/${name}/usr/share/doc/${name}/changelog
+ printf "$name ($pp_deb_version-$pp_deb_release) admin; urgency=low\n\n * see upstream changelog\n\n -- $pp_deb_maintainer `date '+%a, %d %b %Y %T %z'`\n" > ${pp_wrkdir}/${name}/usr/share/doc/${name}/changelog.Debian
+ chmod 644 ${pp_wrkdir}/${name}/usr/share/doc/${name}/changelog.Debian
+ gzip -9f ${pp_wrkdir}/${name}/usr/share/doc/${name}/changelog.Debian
+ # Create lintian override file
+ mkdir -p ${pp_wrkdir}/${name}/usr/share/lintian/overrides
+ cat >${pp_wrkdir}/${name}/usr/share/lintian/overrides/${name} <<-EOF
+ # Sudo ships with debugging symbols
+ $name: unstripped-binary-or-object
+ EOF
+ chmod 644 ${pp_wrkdir}/${name}/usr/share/lintian/overrides/${name}
+ # If libssl_dep not passed in, try to figure it out
+ if test -z "$libssl_dep"; then
+ libssl_dep="`ldd $libexecdir/sudo/sudoers.so 2>&1 | sed -n 's/^[ ]*libssl\.so\([0-9.]*\).*/libssl\1/p'`"
+ fi
+%endif
+
+%if [rpm]
+ # Add distro info to release
+ osrelease=`echo "$pp_rpm_distro" | sed -e 's/^[^0-9]*\([0-9]\{1,2\}\).*/\1/'`
+ case "$pp_rpm_distro" in
+ centos*|rhel*|f[0-9]*)
+ # CentOS Stream has a single-digit version
+ if test $osrelease -lt 10; then
+ osrelease="${osrelease}0"
+ fi
+ pp_rpm_release="$pp_rpm_release.el${osrelease%%[0-9]}"
+ ;;
+ sles*)
+ pp_rpm_release="$pp_rpm_release.sles$osrelease"
+ ;;
+ esac
+%endif
+
+%if [macos]
+ pp_macos_pkg_type=flat
+ pp_macos_bundle_id=ws.sudo.pkg.sudo-logsrvd
+ pp_macos_pkg_background=${srcdir}/etc/macos-background.png
+ pp_macos_pkg_background_dark=${srcdir}/etc/macos-background.png
+ pp_macos_pkg_license=${pp_destdir}$docdir/LICENSE.md
+ pp_macos_pkg_readme=${pp_wrkdir}/ReadMe.txt
+ perl -pe 'last if (/^What/i && $seen++)' ${pp_destdir}$docdir/NEWS > ${pp_wrkdir}/ReadMe.txt
+%endif
+
+%if X"$aix_freeware" = X"true"
+ # Create links from /opt/freeware/sbin -> /usr/sbin
+ mkdir -p ${pp_destdir}/usr/sbin
+ ln -s -f ${sbindir}/sudo_logsrvd ${pp_destdir}/usr/sbin
+%endif
+
+%if [!rpm,deb]
+ # Package parent directories when not installing under /usr
+ if test "${prefix}" != "/usr"; then
+ extradirs=`echo ${pp_destdir}${mandir}/[mc]* | sed "s#${pp_destdir}##g"`
+ extradirs="$extradirs `dirname $docdir` `dirname $rundir`"
+ test "`dirname $exampledir`" != "$docdir" && extradirs="$extradirs `dirname $exampledir`"
+ for dir in $sbindir $extradirs; do
+ while test "$dir" != "/"; do
+ parentdirs="${parentdirs}${parentdirs+ }$dir/"
+ dir=`dirname $dir`
+ done
+ done
+ parentdirs=`echo $parentdirs | tr " " "\n" | sort -u`
+ fi
+%endif
+
+%depend [deb]
+ libc6, zlib1g, sudo
+
+%fixup [deb]
+ if test -n "%{libssl_dep}"; then
+ DEPENDS="%{libssl_dep}"
+ cp -p %{pp_wrkdir}/%{name}/DEBIAN/control %{pp_wrkdir}/%{name}/DEBIAN/control.$$
+ sed "s/^\(Depends:.*\) *$/\1, ${DEPENDS}/" %{pp_wrkdir}/%{name}/DEBIAN/control.$$ > %{pp_wrkdir}/%{name}/DEBIAN/control
+ rm -f %{pp_wrkdir}/%{name}/DEBIAN/control.$$
+ fi
+ echo "Homepage: https://www.sudo.ws" >> %{pp_wrkdir}/%{name}/DEBIAN/control
+ echo "Bugs: https://bugzilla.sudo.ws" >> %{pp_wrkdir}/%{name}/DEBIAN/control
+
+%fixup [rpm]
+ cat > %{pp_wrkdir}/${name}.spec.sed <<-'EOF'
+ /^%files/ {
+ i\
+ %clean\
+ :\
+
+ }
+ EOF
+ mv %{pp_wrkdir}/${name}.spec %{pp_wrkdir}/${name}.spec.bak
+ sed -f %{pp_wrkdir}/${name}.spec.sed %{pp_wrkdir}/${name}.spec.bak > %{pp_wrkdir}/${name}.spec
+
+%files
+ /** ignore
+%if X"$parentdirs" != X""
+ $parentdirs - ignore-others
+%endif
+ $sbindir/sudo_logsrvd 0755 ignore-others
+ $mandir/man*/*logsrv* 0644 ignore-others
+ $rundir/ 0711 root: ignore-others
+ $docdir/ 0755 ignore-others
+ $exampledir/ 0755 ignore-others
+ $exampledir/*logsrv* 0644 ignore-others
+%if [rpm,deb]
+ $sysconfdir/sudo_logsrvd.conf 0644 root: volatile,ignore-others
+%endif
+%if X"$aix_freeware" = X"true"
+ # Links for binaries from /opt/freeware to /usr
+ /usr/sbin/sudo_logsrvd 0755 root: symlink,ignore-others $sbindir/logsrvd
+%endif
+
+%post [!rpm,deb]
+ # Don't overwrite existing sudo_logsrvd.conf files
+%if [solaris]
+ sysconfdir=${PKG_INSTALL_ROOT}%{sysconfdir}
+ exampledir=${PKG_INSTALL_ROOT}%{exampledir}
+%else
+ sysconfdir=%{sysconfdir}
+ exampledir=%{exampledir}
+%endif
+ if test ! -r $sysconfdir/sudo_logsrvd.conf; then
+ cp $exampledir/sudo_logsrvd.conf $sysconfdir/sudo_logsrvd.conf
+ chmod 644 $sysconfdir/sudo_logsrvd.conf
+ chown root $sysconfdir/sudo_logsrvd.conf
+ fi
+
+%service sudo_logsrvd
+%if [aix,macos]
+ cmd="${sbindir}/sudo_logsrvd -n"
+%else
+ cmd=${sbindir}/sudo_logsrvd
+ pidfile=${rundir}/sudo_logsrvd.pid
+%endif
+%if [macos]
+ pp_macos_service_id=ws.sudo.sudo_logsrvd
+%endif
+%if [rpm,deb]
+ # Only include systemd support if it exists on the build machine.
+ # This assumes that we are building on the same distro that the
+ # package will be installed on (which is the case for sudo).
+ if test -d /etc/systemd; then
+ for d in `pkg-config systemd --variable=systemdsystemunitdir 2>/dev/null` /lib/systemd/system /usr/lib/systemd/system; do
+ if test -d "$d"; then
+ break
+ fi
+ done
+ pp_systemd_service_description="Sudo central log server"
+ pp_systemd_service_dir="$d"
+ pp_systemd_service_exec="${cmd}"
+ pp_systemd_service_exec_args="-n"
+ pp_systemd_service_man="man:sudo_logsrvd(8) man:sudo_logsrvd.conf(5)"
+ pp_systemd_service_documentation="https://www.sudo.ws/man.html"
+ pp_systemd_service_after="syslog.target network.target auditd.service"
+ pp_systemd_service_killmode="process"
+ pp_systemd_service_type="exec"
+ pp_systemd_system_target="multi-user.target"
+ else
+ # No systemd support
+ pp_systemd_disabled=true
+ fi
+%endif
diff --git a/etc/sudo-python.pp b/etc/sudo-python.pp
new file mode 100644
index 0000000..098741d
--- /dev/null
+++ b/etc/sudo-python.pp
@@ -0,0 +1,161 @@
+%set
+ name="sudo-python"
+ summary="Sudo Python plugin framework"
+ description="The sudo Python plugin allows you to extend sudo using Python."
+ vendor="Todd C. Miller"
+ copyright="(c) 2019-2021 Todd C. Miller"
+
+%if [aix]
+ # Convert to 4 part version for AIX, including patch level
+ pp_aix_version=`echo $version|sed -e 's/^\([0-9]*\.[0-9]*\.[0-9]*\)p\([0-9]*\)$/\1.\2/' -e 's/^\([0-9]*\.[0-9]*\.[0-9]*\)[^0-9\.].*$/\1/' -e 's/^\([0-9]*\.[0-9]*\.[0-9]*\)$/\1.0/'`
+
+ # Don't use sudo to list the package.
+ pp_aix_sudo=
+%endif
+
+%if [sd]
+ pp_sd_vendor_tag="TCM"
+%endif
+
+%if [solaris]
+ pp_solaris_name="TCM${name}"
+ pp_solaris_pstamp=`/usr/bin/date "+%B %d, %Y"`
+%endif
+
+%if [rpm,deb]
+ # Convert patch level into release and remove from version
+ pp_rpm_release="`expr \( $version : '.*p\([0-9][0-9]*\)$' \| 0 \) + 1`"
+ pp_rpm_version="`expr \( $version : '\(.*\)p[0-9][0-9]*$' \| $version \)`"
+ pp_rpm_license="BSD"
+ pp_rpm_url="https://www.sudo.ws"
+ pp_rpm_group="Applications/System"
+ pp_rpm_packager="Todd C. Miller <Todd.Miller@sudo.ws>"
+%endif
+
+ # Stash original docdir and exampledir
+ odocdir="${docdir}"
+ oexampledir="${exampledir}"
+
+ # docdir and exampledir are installed with "sudo" as the package
+ # name which may not be correct.
+ docdir="`echo \"${docdir}\" | sed 's#/sudo$#/'\"${name}\"'#'`"
+ if test "${exampledir}" = "${odocdir}/examples"; then
+ exampledir="${docdir}/examples"
+ else
+ exampledir="`echo \"${exampledir}\" | sed 's#/sudo$#/'\"${name}\"'#'`"
+ fi
+
+ # For RedHat the doc dir is expected to include version and release
+ case "$pp_rpm_distro" in
+ centos*|rhel*|f[0-9]*)
+ docdir="${docdir}-${pp_rpm_version}-${pp_rpm_release}"
+ exampledir="${docdir}/examples"
+ ;;
+ esac
+
+ # Copy docdir and exampledir to new names if needed
+ if test ! -d "${pp_destdir}${docdir}"; then
+ cp -R ${pp_destdir}${odocdir} ${pp_destdir}${docdir}
+ find ${pp_destdir}${docdir} -depth | sed "s#^${pp_destdir}##" >> ${pp_wrkdir}/pp_cleanup
+ fi
+ if test ! -d "${pp_destdir}${exampledir}"; then
+ cp -R ${pp_destdir}${oexampledir} ${pp_destdir}${exampledir}
+ find ${pp_destdir}${exampledir} -depth | sed "s#^${pp_destdir}##" >> ${pp_wrkdir}/pp_cleanup
+ fi
+
+%if [deb]
+ pp_deb_maintainer="$pp_rpm_packager"
+ pp_deb_release="$pp_rpm_release"
+ pp_deb_version="$pp_rpm_version"
+ pp_deb_section=admin
+ install -D -m 644 ${pp_destdir}$docdir/LICENSE.md ${pp_wrkdir}/${name}/usr/share/doc/${name}/copyright
+ install -D -m 644 ${pp_destdir}$docdir/ChangeLog ${pp_wrkdir}/${name}/usr/share/doc/${name}/changelog
+ gzip -9f ${pp_wrkdir}/${name}/usr/share/doc/${name}/changelog
+ printf "$name ($pp_deb_version-$pp_deb_release) admin; urgency=low\n\n * see upstream changelog\n\n -- $pp_deb_maintainer `date '+%a, %d %b %Y %T %z'`\n" > ${pp_wrkdir}/${name}/usr/share/doc/${name}/changelog.Debian
+ chmod 644 ${pp_wrkdir}/${name}/usr/share/doc/${name}/changelog.Debian
+ gzip -9f ${pp_wrkdir}/${name}/usr/share/doc/${name}/changelog.Debian
+ # Create lintian override file
+ mkdir -p ${pp_wrkdir}/${name}/usr/share/lintian/overrides
+ cat >${pp_wrkdir}/${name}/usr/share/lintian/overrides/${name} <<-EOF
+ # Sudo ships with debugging symbols
+ $name: unstripped-binary-or-object
+ EOF
+ chmod 644 ${pp_wrkdir}/${name}/usr/share/lintian/overrides/${name}
+%endif
+
+%if [rpm]
+ # Add distro info to release
+ osrelease=`echo "$pp_rpm_distro" | sed -e 's/^[^0-9]*\([0-9]\{1,2\}\).*/\1/'`
+ case "$pp_rpm_distro" in
+ centos*|rhel*|f[0-9]*)
+ # CentOS Stream has a single-digit version
+ if test $osrelease -lt 10; then
+ osrelease="${osrelease}0"
+ fi
+ pp_rpm_release="$pp_rpm_release.el${osrelease%%[0-9]}"
+ ;;
+ sles*)
+ pp_rpm_release="$pp_rpm_release.sles$osrelease"
+ ;;
+ esac
+%endif
+
+%if [macos]
+ pp_macos_pkg_type=flat
+ pp_macos_bundle_id=ws.sudo.pkg.sudo-python
+ pp_macos_pkg_background=${srcdir}/etc/macos-background.png
+ pp_macos_pkg_background_dark=${srcdir}/etc/macos-background.png
+ pp_macos_pkg_license=${pp_destdir}$docdir/LICENSE.md
+ pp_macos_pkg_readme=${pp_wrkdir}/ReadMe.txt
+ perl -pe 'last if (/^What/i && $seen++)' ${pp_destdir}$docdir/NEWS > ${pp_wrkdir}/ReadMe.txt
+%endif
+
+%if [!rpm,deb]
+ # Package parent directories when not installing under /usr
+ if test "${prefix}" != "/usr"; then
+ extradirs=`echo ${pp_destdir}${mandir}/[mc]* | sed "s#${pp_destdir}##g"`
+ extradirs="$extradirs `dirname $docdir`"
+ test "`dirname $exampledir`" != "$docdir" && extradirs="$extradirs `dirname $exampledir`"
+ for dir in $libexecdir $extradirs; do
+ while test "$dir" != "/"; do
+ parentdirs="${parentdirs}${parentdirs+ }$dir/"
+ dir=`dirname $dir`
+ done
+ done
+ parentdirs=`echo $parentdirs | tr " " "\n" | sort -u`
+ fi
+%endif
+
+%depend [deb]
+ libc6, libpython@PYTHON_VERSION@, sudo
+
+%fixup [deb]
+ cp -p %{pp_wrkdir}/%{name}/DEBIAN/control %{pp_wrkdir}/%{name}/DEBIAN/control.$$
+ sed "s/@PYTHON_VERSION@/%{python_version}/g" %{pp_wrkdir}/%{name}/DEBIAN/control.$$ > %{pp_wrkdir}/%{name}/DEBIAN/control
+ rm -f %{pp_wrkdir}/%{name}/DEBIAN/control.$$
+ echo "Homepage: https://www.sudo.ws" >> %{pp_wrkdir}/%{name}/DEBIAN/control
+ echo "Bugs: https://bugzilla.sudo.ws" >> %{pp_wrkdir}/%{name}/DEBIAN/control
+
+%fixup [rpm]
+ cat > %{pp_wrkdir}/${name}.spec.sed <<-'EOF'
+ /^%files/ {
+ i\
+ %clean\
+ :\
+
+ }
+ EOF
+ mv %{pp_wrkdir}/${name}.spec %{pp_wrkdir}/${name}.spec.bak
+ sed -f %{pp_wrkdir}/${name}.spec.sed %{pp_wrkdir}/${name}.spec.bak > %{pp_wrkdir}/${name}.spec
+
+%files
+ /** ignore
+%if X"$parentdirs" != X""
+ $parentdirs - ignore-others
+%endif
+ $libexecdir/sudo/ 0755 ignore-others
+ $libexecdir/sudo/python* $shlib_mode ignore-others
+ $docdir/ 0755 ignore-others
+ $exampledir/ 0755 ignore-others
+ $exampledir/*.py 0644 ignore-others
+ $mandir/man*/*python* 0644 ignore-others
diff --git a/etc/sudo.pp b/etc/sudo.pp
new file mode 100644
index 0000000..9abc26b
--- /dev/null
+++ b/etc/sudo.pp
@@ -0,0 +1,571 @@
+%set
+ if test -n "$flavor"; then
+ name="sudo-$flavor"
+ else
+ name="sudo"
+ fi
+ summary="Provide limited super-user privileges to specific users"
+ description="Sudo is a program designed to allow a sysadmin to give \
+limited root privileges to users and log root activity. \
+The basic philosophy is to give as few privileges as possible but \
+still allow people to get their work done."
+ vendor="Todd C. Miller"
+ copyright="(c) 1993-1996,1998-2021 Todd C. Miller"
+ sudoedit_man=`echo ${pp_destdir}$mandir/*/sudoedit.*|sed "s:^${pp_destdir}::"`
+ sudoedit_man_target=`basename $sudoedit_man | sed 's/edit//'`
+
+%if [aix]
+ # AIX package summary is limited to 40 characters
+ summary="Configurable super-user privileges"
+
+ # Convert to 4 part version for AIX, including patch level
+ pp_aix_version=`echo $version|sed -e 's/^\([0-9]*\.[0-9]*\.[0-9]*\)p\([0-9]*\)$/\1.\2/' -e 's/^\([0-9]*\.[0-9]*\.[0-9]*\)[^0-9\.].*$/\1/' -e 's/^\([0-9]*\.[0-9]*\.[0-9]*\)$/\1.0/'`
+
+ # Don't use sudo to list the package.
+ pp_aix_sudo=
+%endif
+
+%if [sd]
+ pp_sd_vendor_tag="TCM"
+%endif
+
+%if [solaris]
+ pp_solaris_name="TCM${name}"
+ pp_solaris_pstamp=`/usr/bin/date "+%B %d, %Y"`
+%endif
+
+%if [macos]
+ # System Integrity Protection on macOS won't allow us to write
+ # directly to /etc or /var. We must install in /private instead.
+ case "$sysconfdir" in
+ /etc|/etc/*)
+ mkdir -p ${pp_destdir}/private
+ chmod 755 ${pp_destdir}/private
+ if test -d ${pp_destdir}/etc; then
+ mv ${pp_destdir}/etc ${pp_destdir}/private/etc
+ fi
+ sysconfdir="/private${sysconfdir}"
+ ;;
+ esac
+ case "$vardir" in
+ /var|/var/*)
+ mkdir -p ${pp_destdir}/private
+ chmod 755 ${pp_destdir}/private
+ if test -d ${pp_destdir}/var; then
+ mv ${pp_destdir}/var ${pp_destdir}/private/var
+ fi
+ vardir="/private${vardir}"
+ ;;
+ esac
+ case "$rundir" in
+ /var|/var/*)
+ mkdir -p ${pp_destdir}/private
+ chmod 755 ${pp_destdir}/private
+ if test -d ${pp_destdir}/var; then
+ mv ${pp_destdir}/var ${pp_destdir}/private/var
+ fi
+ rundir="/private${rundir}"
+ ;;
+ esac
+%endif
+
+%if [rpm,deb]
+ # Convert patch level into release and remove from version
+ pp_rpm_release="`expr \( $version : '.*p\([0-9][0-9]*\)$' \| 0 \) + 1`"
+ pp_rpm_version="`expr \( $version : '\(.*\)p[0-9][0-9]*$' \| $version \)`"
+ pp_rpm_license="BSD"
+ pp_rpm_url="https://www.sudo.ws"
+ pp_rpm_group="Applications/System"
+ pp_rpm_packager="Todd C. Miller <Todd.Miller@sudo.ws>"
+ if test -n "$linux_audit"; then
+ pp_rpm_requires="audit-libs >= $linux_audit"
+ fi
+ # The package manager will handle an existing sudoers file
+ rm -f ${pp_destdir}${sysconfdir}/sudoers.dist
+%else
+ # For all but RPM and Debian we copy sudoers in a post-install script.
+ rm -f ${pp_destdir}${sysconfdir}/sudoers
+ # We install sudo.conf from the example dir in a post-install script.
+ rm -f ${pp_destdir}${sysconfdir}/sudo.conf
+%endif
+
+ # Stash original docdir and exampledir
+ odocdir="${docdir}"
+ oexampledir="${exampledir}"
+
+ # For RedHat the doc dir is expected to include version and release
+ case "$pp_rpm_distro" in
+ centos*|rhel*|f[0-9]*)
+ docdir="${docdir}-${pp_rpm_version}-${pp_rpm_release}"
+ exampledir="${docdir}/examples"
+ ;;
+ esac
+
+ if test -n "$flavor"; then
+ # docdir and exampledir are installed with "sudo" as the package
+ # name which is not be correct for flavors.
+ docdir="`echo \"${docdir}\" | sed \"s#/sudo#/${name}#g\"`"
+ exampledir="`echo \"${exampledir}\" | sed \"s#/sudo#/${name}#g\"`"
+ fi
+
+ # Copy docdir and exampledir to new names if needed
+ if test ! -d "${pp_destdir}${docdir}"; then
+ cp -R ${pp_destdir}${odocdir} ${pp_destdir}${docdir}
+ find ${pp_destdir}${docdir} -depth | sed "s#^${pp_destdir}##" >> ${pp_wrkdir}/pp_cleanup
+ fi
+ if test ! -d "${pp_destdir}${exampledir}"; then
+ cp -R ${pp_destdir}${oexampledir} ${pp_destdir}${exampledir}
+ find ${pp_destdir}${exampledir} -depth | sed "s#^${pp_destdir}##" >> ${pp_wrkdir}/pp_cleanup
+ fi
+
+%if [deb]
+ pp_deb_maintainer="$pp_rpm_packager"
+ pp_deb_release="$pp_rpm_release"
+ pp_deb_version="$pp_rpm_version"
+ pp_deb_section=admin
+ install -D -m 644 ${pp_destdir}$docdir/LICENSE.md ${pp_wrkdir}/${name}/usr/share/doc/${name}/copyright
+ install -D -m 644 ${pp_destdir}$docdir/ChangeLog ${pp_wrkdir}/${name}/usr/share/doc/${name}/changelog
+ gzip -9f ${pp_wrkdir}/${name}/usr/share/doc/${name}/changelog
+ printf "$name ($pp_deb_version-$pp_deb_release) admin; urgency=low\n\n * see upstream changelog\n\n -- $pp_deb_maintainer `date '+%a, %d %b %Y %T %z'`\n" > ${pp_wrkdir}/${name}/usr/share/doc/${name}/changelog.Debian
+ chmod 644 ${pp_wrkdir}/${name}/usr/share/doc/${name}/changelog.Debian
+ gzip -9f ${pp_wrkdir}/${name}/usr/share/doc/${name}/changelog.Debian
+ # Create lintian override file, must be tab indented for "<<-"
+ mkdir -p ${pp_wrkdir}/${name}/usr/share/lintian/overrides
+ cat >${pp_wrkdir}/${name}/usr/share/lintian/overrides/${name} <<-EOF
+ # The sudo binary must be setuid root
+ $name: setuid-binary usr/bin/sudo 4755 root/root
+ # Sudo configuration and data dirs must not be world-readable
+ $name: non-standard-file-perm etc/sudoers 0440 != 0644
+ $name: non-standard-dir-perm etc/sudoers.d/ 0750 != 0755
+ $name: non-standard-dir-perm var/lib/sudo/ 0700 != 0755
+ # Sudo ships with debugging symbols
+ $name: unstripped-binary-or-object
+ EOF
+ chmod 644 ${pp_wrkdir}/${name}/usr/share/lintian/overrides/${name}
+ # If libssl_dep not passed in, try to figure it out
+ if test -z "$libssl_dep"; then
+ libssl_dep="`ldd $libexecdir/sudo/sudoers.so 2>&1 | sed -n 's/^[ ]*libssl\.so\([0-9.]*\).*/libssl\1/p'`"
+ fi
+%endif
+
+%if [rpm]
+ # Add distro info to release
+ osrelease=`echo "$pp_rpm_distro" | sed -e 's/^[^0-9]*\([0-9]\{1,2\}\).*/\1/'`
+ case "$pp_rpm_distro" in
+ centos*|rhel*|f[0-9]*)
+ # CentOS Stream has a single-digit version
+ if test $osrelease -lt 10; then
+ osrelease="${osrelease}0"
+ fi
+ pp_rpm_release="$pp_rpm_release.el${osrelease%%[0-9]}"
+ ;;
+ sles*)
+ pp_rpm_release="$pp_rpm_release.sles$osrelease"
+ ;;
+ esac
+
+ # Uncomment some Defaults in sudoers
+ case "$pp_rpm_distro" in
+ centos*|rhel*|f[0-9]*)
+ sed -e '/Locale settings/{ N;s/\(\n\)# /\1/; }' -e '/Desktop path settings/{ N;s/\(\n\)# /\1/; }' -e '/allow members of group wheel to execute any command/{ N;s/\(\n\)# /\1/; }' ${pp_destdir}${sysconfdir}/sudoers > ${pp_destdir}${sysconfdir}/sudoers.$$
+ mv -f ${pp_destdir}${sysconfdir}/sudoers.$$ ${pp_destdir}${sysconfdir}/sudoers
+ ;;
+ sles*)
+ sed -e '/Locale settings/{ N;s/\(\n\)# /\1/; }' -e '/ConsoleKit session/{ N;s/\(\n\)# /\1/; }' -e '/allow any user to run sudo if they know the password/{ N;N;N;s/\(\n\)# /\1/g; }' ${pp_destdir}${sysconfdir}/sudoers > ${pp_destdir}${sysconfdir}/sudoers.$$
+ mv -f ${pp_destdir}${sysconfdir}/sudoers.$$ ${pp_destdir}${sysconfdir}/sudoers
+ ;;
+ esac
+
+ # Choose the correct PAM file by distro, must be tab indented for "<<-"
+ case "$pp_rpm_distro" in
+ centos*|rhel*)
+ mkdir -p ${pp_destdir}/etc/pam.d
+ if test $osrelease -lt 50; then
+ cat > ${pp_destdir}/etc/pam.d/sudo <<-EOF
+ #%PAM-1.0
+ auth required pam_stack.so service=system-auth
+ account required pam_stack.so service=system-auth
+ password required pam_stack.so service=system-auth
+ session required pam_limits.so
+ EOF
+ else
+ cat > ${pp_destdir}/etc/pam.d/sudo <<-EOF
+ #%PAM-1.0
+ auth include system-auth
+ account include system-auth
+ password include system-auth
+ session optional pam_keyinit.so revoke
+ session required pam_limits.so
+ EOF
+ cat > ${pp_destdir}/etc/pam.d/sudo-i <<-EOF
+ #%PAM-1.0
+ auth include sudo
+ account include sudo
+ password include sudo
+ session optional pam_keyinit.so force revoke
+ session required pam_limits.so
+ EOF
+ fi
+ ;;
+ f[0-9]*)
+ # XXX - share with rhel
+ mkdir -p ${pp_destdir}/etc/pam.d
+ cat > ${pp_destdir}/etc/pam.d/sudo <<-EOF
+ #%PAM-1.0
+ auth include system-auth
+ account include system-auth
+ password include system-auth
+ session optional pam_keyinit.so revoke
+ session required pam_limits.so
+ EOF
+ cat > ${pp_destdir}/etc/pam.d/sudo-i <<-EOF
+ #%PAM-1.0
+ auth include sudo
+ account include sudo
+ password include sudo
+ session optional pam_keyinit.so force revoke
+ session required pam_limits.so
+ EOF
+ ;;
+ sles*)
+ mkdir -p ${pp_destdir}/etc/pam.d
+ if test $osrelease -lt 10; then
+ cat > ${pp_destdir}/etc/pam.d/sudo <<-EOF
+ #%PAM-1.0
+ auth required pam_unix2.so
+ session required pam_limits.so
+ EOF
+ else
+ cat > ${pp_destdir}/etc/pam.d/sudo <<-EOF
+ #%PAM-1.0
+ auth include common-auth
+ account include common-account
+ password include common-password
+ session include common-session
+ # session optional pam_xauth.so
+ EOF
+ fi
+ ;;
+ esac
+%endif
+
+%if [deb]
+ # Uncomment some Defaults and the %sudo rule in sudoers
+ sed -e '/Locale settings/{ N;s/\(\n\)# /\1/; }' -e '/X11 resource/{ N;s/\(\n\)# /\1/; }' -e 's/^# \(Defaults secure_path\)/\1/' -e 's/^# \(Defaults mail_badpass\)/\1/' -e 's/^# \(\%sudo\)/\1/' ${pp_destdir}${sysconfdir}/sudoers > ${pp_destdir}${sysconfdir}/sudoers.$$
+ mv -f ${pp_destdir}${sysconfdir}/sudoers.$$ ${pp_destdir}${sysconfdir}/sudoers
+ mkdir -p ${pp_destdir}/etc/pam.d
+ # Create Debian PAM file, must be tab indented for "<<-"
+ cat > ${pp_destdir}/etc/pam.d/sudo <<-EOF
+ #%PAM-1.0
+
+ @include common-auth
+ @include common-account
+
+ session required pam_permit.so
+ session required pam_limits.so
+ EOF
+%endif
+
+%if [macos]
+ pp_macos_pkg_type=flat
+ pp_macos_bundle_id=ws.sudo.pkg.sudo
+ pp_macos_pkg_background=${srcdir}/etc/macos-background.png
+ pp_macos_pkg_background_dark=${srcdir}/etc/macos-background.png
+ pp_macos_pkg_license=${pp_destdir}$docdir/LICENSE.md
+ pp_macos_pkg_readme=${pp_wrkdir}/ReadMe.txt
+ perl -pe 'last if (/^What/i && $seen++)' ${pp_destdir}$docdir/NEWS > ${pp_wrkdir}/ReadMe.txt
+%endif
+
+%if X"$aix_freeware" = X"true"
+ # Create links from /opt/freeware/{bin,sbin} -> /usr/{bin,sbin}
+ mkdir -p ${pp_destdir}/usr/bin ${pp_destdir}/usr/sbin
+ ln -s -f ${bindir}/cvtsudoers ${pp_destdir}/usr/bin
+ ln -s -f ${bindir}/sudo ${pp_destdir}/usr/bin
+ ln -s -f ${bindir}/sudoedit ${pp_destdir}/usr/bin
+ ln -s -f ${bindir}/sudoreplay ${pp_destdir}/usr/bin
+ ln -s -f ${sbindir}/sudo_sendlog ${pp_destdir}/usr/sbin
+ ln -s -f ${sbindir}/visudo ${pp_destdir}/usr/sbin
+%endif
+
+%if [!rpm,deb]
+ # Package parent directories when not installing under /usr
+ if test "${prefix}" != "/usr"; then
+ extradirs=`echo ${pp_destdir}${mandir}/[mc]* | sed "s#${pp_destdir}##g"`
+ extradirs="$extradirs `dirname $docdir` `dirname $rundir` `dirname $vardir`"
+ test "`dirname $exampledir`" != "$docdir" && extradirs="$extradirs `dirname $exampledir`"
+ test -d ${pp_destdir}${localedir} && extradirs="$extradirs $localedir"
+ for dir in $bindir $sbindir $libexecdir $includedir $extradirs; do
+ while test "$dir" != "/"; do
+ parentdirs="${parentdirs}${parentdirs+ }$dir/"
+ dir=`dirname $dir`
+ done
+ done
+ parentdirs=`echo $parentdirs | tr " " "\n" | sort -u`
+ fi
+%endif
+
+%depend [deb]
+ libc6, libpam0g, libpam-modules, zlib1g, libapparmor1
+
+%fixup [deb]
+ # Add Conflicts, Replaces headers and add libldap dependency as needed.
+ DEPENDS="%{linux_audit}"
+ if test -z "%{flavor}"; then
+ echo "Conflicts: sudo-ldap" >> %{pp_wrkdir}/%{name}/DEBIAN/control
+ echo "Replaces: sudo-ldap" >> %{pp_wrkdir}/%{name}/DEBIAN/control
+ elif test "%{flavor}" = "ldap"; then
+ echo "Conflicts: sudo" >> %{pp_wrkdir}/%{name}/DEBIAN/control
+ echo "Replaces: sudo" >> %{pp_wrkdir}/%{name}/DEBIAN/control
+ echo "Provides: sudo" >> %{pp_wrkdir}/%{name}/DEBIAN/control
+ DEPENDS="${DEPENDS}${DEPENDS:+, }libldap-2.4-2"
+ fi
+ if test -n "%{libssl_dep}"; then
+ DEPENDS="${DEPENDS}${DEPENDS:+, }%{libssl_dep}"
+ fi
+ cp -p %{pp_wrkdir}/%{name}/DEBIAN/control %{pp_wrkdir}/%{name}/DEBIAN/control.$$
+ if test -n "${DEPENDS}"; then
+ sed "s/^\(Depends:.*\) *$/\1, ${DEPENDS}/" %{pp_wrkdir}/%{name}/DEBIAN/control.$$ > %{pp_wrkdir}/%{name}/DEBIAN/control
+ fi
+ rm -f %{pp_wrkdir}/%{name}/DEBIAN/control.$$
+ echo "Homepage: https://www.sudo.ws" >> %{pp_wrkdir}/%{name}/DEBIAN/control
+ echo "Bugs: https://bugzilla.sudo.ws" >> %{pp_wrkdir}/%{name}/DEBIAN/control
+
+%fixup [rpm]
+ # Must be tab indented for "<<-".
+ cat > %{pp_wrkdir}/${name}.spec.sed <<-'EOF'
+ /^%files/ {
+ i\
+ %clean\
+ :\
+
+ }
+ EOF
+ mv %{pp_wrkdir}/${name}.spec %{pp_wrkdir}/${name}.spec.bak
+ sed -f %{pp_wrkdir}/${name}.spec.sed %{pp_wrkdir}/${name}.spec.bak > %{pp_wrkdir}/${name}.spec
+
+%files
+%if X"$parentdirs" != X""
+ $parentdirs -
+%endif
+%if X"$odocdir" != X"$docdir"
+ $odocdir/ ignore
+ $odocdir/** ignore
+%endif
+%if X"$oexampledir" != X"$exampledir" -a X"$exampledir" != X"$docdir/examples"
+ $oexampledir/ ignore
+ $oexampledir/** ignore
+%endif
+ $bindir/cvtsudoers 0755 root:
+ $bindir/sudo 4755 root:
+ $bindir/sudoedit 0755 root: symlink sudo
+ $bindir/sudoreplay 0755
+ $sbindir/sudo_sendlog 0755
+ $sbindir/sudo_logsrvd optional,ignore
+ $sbindir/visudo 0755
+ $includedir/sudo_plugin.h 0644
+ $libexecdir/sudo/ 0755
+ $libexecdir/sudo/sesh 0755 optional,ignore-others
+ $libexecdir/sudo/python* optional,ignore,ignore-others
+ $libexecdir/sudo/* $shlib_mode optional
+ $sysconfdir/sudoers.d/ 0750 $sudoers_uid:$sudoers_gid
+ $rundir/ 0711 root:
+ $vardir/ 0711 root: ignore-others
+ $vardir/lectured/ 0700 root:
+ $docdir/ 0755
+ $docdir/** 0644
+%if [deb]
+ $docdir/LICENSE.md ignore,ignore-others
+ $docdir/ChangeLog ignore,ignore-others
+%endif
+ $exampledir/ 0755 ignore-others
+%if X"$exampledir" != X"$docdir/examples"
+ $exampledir/* 0644
+%endif
+ $exampledir/sudo_logsrv* optional,ignore,ignore-others
+ $exampledir/*.py optional,ignore,ignore-others
+ $localedir/*/ - optional
+ $localedir/*/LC_MESSAGES/ - optional
+ $localedir/*/LC_MESSAGES/* 0644 optional
+ /etc/pam.d/* 0644 volatile,optional
+%if [rpm,deb]
+ $sysconfdir/sudoers $sudoers_mode $sudoers_uid:$sudoers_gid volatile
+ $sysconfdir/sudo.conf 0644 root: volatile
+%else
+ $sysconfdir/sudoers.dist $sudoers_mode $sudoers_uid:$sudoers_gid
+%endif
+ $sysconfdir/sudo_logsrvd.conf optional,ignore,ignore-others
+%if X"$aix_freeware" = X"true"
+ # Links for binaries from /opt/freeware to /usr
+ /usr/bin/cvtsudoers 0755 root: symlink $bindir/cvtsudoers
+ /usr/bin/sudo 0755 root: symlink $bindir/sudo
+ /usr/bin/sudoedit 0755 root: symlink $bindir/sudoedit
+ /usr/bin/sudoreplay 0755 root: symlink $bindir/sudoreplay
+ /usr/sbin/sudo_sendlog 0755 root: symlink $sbindir/sendlog
+ /usr/sbin/visudo 0755 root: symlink $sbindir/visudo
+%endif
+%if [rpm]
+ /etc/rc.d/init.d/sudo 0755 root: optional
+%endif
+%if [aix]
+ /etc/rc.d/ ignore
+ /etc/rc.d/rc2.d/ ignore
+ /etc/rc.d/rc2.d/** ignore
+ /etc/rc.d/init.d/ ignore
+ /etc/rc.d/init.d/sudo 0755 root:
+%endif
+%if [sd]
+ /sbin/ ignore
+ /sbin/rc2.d/ ignore
+ /sbin/rc2.d/** ignore
+ /sbin/init.d/ ignore
+ /sbin/init.d/sudo 0755 root:
+%endif
+ $mandir/man*/* 0644
+ $mandir/man*/sudo_logsrv* ignore,ignore-others
+ $mandir/man*/*python* ignore,ignore-others
+ $sudoedit_man 0644 symlink,ignore-others $sudoedit_man_target
+
+%pre [aix]
+ if rpm -q %{name} >/dev/null 2>&1; then
+ echo "Another version of sudo is currently installed via rpm." 2>&1
+ echo "Please either uninstall the rpm version of sudo by running \"rpm -e sudo\"" 2>&1
+ echo "or upgrade the existing version of sudo using the .rpm packagae instead" 2>&1
+ echo "instead of the .bff package." 2>&1
+ echo "" 2>&1
+ echo "Note that you may need to pass rpm the --oldpackage flag when upgrading" 2>&1
+ echo "the AIX Toolbox version of sudo to the latest sudo rpm from sudo.ws." 2>&1
+ echo "" 2>&1
+ exit 1
+ fi
+
+%post [!rpm,deb]
+ # Don't overwrite existing sudoers or sudo.conf files
+%if [solaris]
+ sysconfdir=${PKG_INSTALL_ROOT}%{sysconfdir}
+ exampledir=${PKG_INSTALL_ROOT}%{exampledir}
+%else
+ sysconfdir=%{sysconfdir}
+ exampledir=%{exampledir}
+%endif
+ if test ! -r $sysconfdir/sudoers; then
+ cp $sysconfdir/sudoers.dist $sysconfdir/sudoers
+ chmod %{sudoers_mode} $sysconfdir/sudoers
+ chown %{sudoers_uid} $sysconfdir/sudoers
+ chgrp %{sudoers_gid} $sysconfdir/sudoers
+ fi
+ if test ! -r $sysconfdir/sudo.conf; then
+ cp $exampledir/sudo.conf $sysconfdir/sudo.conf
+ chmod 644 $sysconfdir/sudo.conf
+ chown root $sysconfdir/sudo.conf
+ fi
+
+%post [deb]
+ set -e
+
+ # dpkg-deb does not maintain the mode on the sudoers file, and
+ # installs it 0640 when sudo requires 0440
+ chmod %{sudoers_mode} %{sysconfdir}/sudoers
+
+ # create symlink to ease transition to new path for ldap config
+ # if old config file exists and new one doesn't
+ if test X"%{flavor}" = X"ldap" -a \
+ -r /etc/ldap/ldap.conf -a ! -r /etc/sudo-ldap.conf; then
+ ln -s /etc/ldap/ldap.conf /etc/sudo-ldap.conf
+ fi
+
+ # Debian uses a sudo group in its default sudoers file
+ perl -e '
+ exit 0 if getgrnam("sudo");
+ $gid = 27; # default debian sudo gid
+ setgrent();
+ while (getgrgid($gid)) { $gid++; }
+ if ($gid != 27) {
+ print "On Debian we normally use gid 27 for \"sudo\".\n";
+ $gname = getgrgid(27);
+ print "However, on your system gid 27 is group \"$gname\".\n\n";
+ print "Would you like me to stop configuring sudo so that you can change this? [n] ";
+ $ans = <STDIN>;
+ if ($ans =~ /^[yY]/) {
+ print "\"dpkg --pending --configure\" will restart the configuration.\n\n";
+ exit 1;
+ }
+ }
+ print "Creating group \"sudo\" with gid = $gid\n";
+ system("groupadd -g $gid sudo");
+ exit 0;
+ '
+
+%post [rpm]
+ case "%{pp_rpm_distro}" in
+ aix*)
+ # Create /etc/rc.d/rc2.d/S90sudo link if possible
+ if [ -d /etc/rc.d/rc2.d ]; then
+ rm -f /etc/rc.d/rc2.d/S90sudo
+ ln -s /etc/rc.d/init.d/sudo /etc/rc.d/rc2.d/S90sudo
+ fi
+ ;;
+ esac
+
+%post [rpm,deb]
+ # Create /usr/lib/tmpfiles.d/sudo.conf if systemd is configured.
+ # Must be tab indented for "<<-".
+ if [ -f /usr/lib/tmpfiles.d/systemd.conf ]; then
+ cat > /usr/lib/tmpfiles.d/sudo.conf <<-EOF
+ # Create an empty sudo time stamp directory on OSes using systemd.
+ # Sudo will create the directory itself but this can cause problems
+ # on systems that have SELinux enabled since the directories will be
+ # created with the user's security context.
+ d %{rundir} 0711 root root
+ D %{rundir}/ts 0700 root root
+ EOF
+ fi
+
+%post [aix]
+ # Create /etc/rc.d/rc2.d/S90sudo link if /etc/rc.d exists
+ if [ -d /etc/rc.d ]; then
+ rm -f /etc/rc.d/rc2.d/S90sudo
+ ln -s /etc/rc.d/init.d/sudo /etc/rc.d/rc2.d/S90sudo
+ fi
+
+%post [sd]
+ # Create /sbin/rc2.d/S900sudo link
+ rm -f /sbin/rc2.d/S900sudo
+ ln -s /sbin/init.d/sudo /sbin/rc2.d/S900sudo
+
+%preun
+ # Remove the time stamp dir and its contents
+ # We currently leave the lecture status files installed
+ rm -rf %{rundir}/ts
+%if [deb]
+ set -e
+
+ # Remove the /etc/ldap/ldap.conf -> /etc/sudo-ldap.conf symlink if
+ # it matches what we created in the postinstall script.
+ if test X"%{flavor}" = X"ldap" -a \
+ X"`readlink /etc/sudo-ldap.conf 2>/dev/null`" = X"/etc/ldap/ldap.conf"; then
+ rm -f /etc/sudo-ldap.conf
+ fi
+
+ # Remove systemd tmpfile config
+ rm -f /usr/lib/tmpfiles.d/sudo.conf
+%endif
+%if [rpm]
+ case "%{pp_rpm_distro}" in
+ aix*)
+ # Remove /etc/rc.d/rc2.d/S90sudo link
+ rm -f /etc/rc.d/rc2.d/S90sudo
+ ;;
+ *)
+ # Remove systemd tmpfile config
+ rm -f /usr/lib/tmpfiles.d/sudo.conf
+ ;;
+ esac
+%endif
+%if [aix]
+ # Remove /etc/rc.d/rc2.d/S90sudo link
+ rm -f /etc/rc.d/rc2.d/S90sudo
+%endif
+%if [sd]
+ # Remove /sbin/rc2.d/S900sudo link
+ rm -f /sbin/rc2.d/S900sudo
+%endif
diff --git a/examples/Makefile.in b/examples/Makefile.in
new file mode 100644
index 0000000..710b492
--- /dev/null
+++ b/examples/Makefile.in
@@ -0,0 +1,138 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2014, 2017-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+exampledir = @exampledir@
+docdir = @docdir@
+scriptdir = $(top_srcdir)/scripts
+
+# Our install program supports extra flags...
+INSTALL = $(SHELL) $(scriptdir)/install-sh -c
+INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
+
+# Where to install things...
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+sysconfdir = @sysconfdir@
+adminconfdir = @adminconfdir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+localstatedir = @localstatedir@
+
+# User and group ids the installed files should be "owned" by
+install_uid = 0
+install_gid = 0
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+LOGSRVD_CONF = @LOGSRVD_CONF@
+
+EXAMPLES = $(srcdir)/cvtsudoers.conf $(srcdir)/pam.conf sudo.conf \
+ $(LOGSRVD_CONF) sudoers syslog.conf
+
+VERSION = @PACKAGE_VERSION@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+
+all: $(EXAMPLES)
+
+depend:
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file examples/Makefile
+
+sudoers: $(srcdir)/sudoers.in
+ cd $(top_builddir) && ./config.status --file examples/sudoers
+
+sudo.conf: $(srcdir)/sudo.conf.in
+ cd $(top_builddir) && ./config.status --file examples/sudo.conf
+
+sudo_logsrvd.conf: $(srcdir)/sudo_logsrvd.conf.in
+ cd $(top_builddir) && ./config.status --file examples/sudo_logsrvd.conf
+
+syslog.conf: $(srcdir)/syslog.conf.in
+ cd $(top_builddir) && ./config.status --file examples/syslog.conf
+
+pre-install:
+
+install: install-doc
+
+install-dirs:
+ $(SHELL) $(scriptdir)/mkinstalldirs $(DESTDIR)$(exampledir)
+
+install-binaries:
+
+install-includes:
+
+install-doc: install-dirs
+ for f in $(EXAMPLES); do $(INSTALL) $(INSTALL_OWNER) -m 0644 $$f $(DESTDIR)$(exampledir); done
+ test -r $(DESTDIR)$(sysconfdir)/sudo.conf || \
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 sudo.conf $(DESTDIR)$(sysconfdir)
+ if test -n "$(LOGSRVD_CONF)" -a ! -r $(DESTDIR)$(sysconfdir)/sudo_logsrvd.conf; then \
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 $(LOGSRVD_CONF) $(DESTDIR)$(sysconfdir); \
+ fi
+
+install-plugin:
+
+install-fuzzer:
+
+uninstall:
+ -rm -rf $(DESTDIR)$(exampledir)
+
+splint:
+
+cppcheck:
+
+pvs-log-files:
+
+pvs-studio:
+
+fuzz:
+
+check-fuzzer:
+
+check: check-fuzzer
+
+check-verbose: check
+
+clean:
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile sudo.conf sudo_logsrvd.conf sudoers syslog.conf
+
+clobber: distclean
+
+realclean: distclean
+
+cleandir: distclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean
diff --git a/examples/cvtsudoers.conf b/examples/cvtsudoers.conf
new file mode 100644
index 0000000..3d21154
--- /dev/null
+++ b/examples/cvtsudoers.conf
@@ -0,0 +1,82 @@
+#
+# Example /etc/cvtsudoers.conf file
+#
+# This file is optional and allows you to override the cvtsudoers
+# default values.
+#
+
+# Only convert Defaults entries of the specified types.
+# One or more Defaults types may be specified, separated by a comma (',').
+# The supported types are: all, global, user, runas, host, command.
+#defaults = all
+
+# Expand aliases in input_file. Aliases are preserved by
+# default when the output format is JSON or sudoers.
+#expand_aliases = no
+
+# Use an alternate group file. When "match_local" is also enabled, perform
+# group queries using the specified file instead of the system group database.
+#group_file = /etc/group
+
+# Default input format. Only the sudoers and LDIF formats are supported.
+#input_format = sudoers
+
+# Only output rules that match the specified filter. A filter expression
+# is made up of one or more key = value pairs, separated by a comma (',').
+# The key may be "cmnd" (or "cmd"), "host", "group", or "user".
+#match = user=www,group=wheel
+
+# Match locally. If enabled, use password and group database information
+# when matching users and groups in the filter. Only users and groups
+# in the filter that exist on the local system will match, and a user's
+# groups will automatically be added to the filter. By default, users and
+# groups in the filter do not need to exist on the local system, but all
+# groups used for matching must be explicitly listed in the filter.
+#match_local = no
+
+# When generating LDIF output, increment each sudoOrder attribute by the
+# specified number. Defaults to an increment of 1.
+#order_increment = 1
+
+# When generating LDIF output, use the number specified by "start_point"
+# in the sudoOrder attribute of the first sudoRole object. Subsequent
+# sudoRole object use a sudoOrder value generated by adding the
+# increment set by "order_increment". Defaults to a starting point
+# of 1. A starting point of 0 will disable the generation of sudoOrder
+# attributes in the resulting LDIF file.
+#order_start = 1
+
+# Specify the default output format (case-insensitive). The following
+# formats are supported: csv | json | ldif | sudoers.
+# Defaults to LDIF.
+#output_format = ldif
+
+# When generating LDIF output, construct the initial sudoOrder value
+# by concatenating order_start and increment, padding the increment
+# with zeros until it consists of padding digits. For example, if
+# order_start is 1027, padding is 3, and increment is 1, the value
+# of sudoOrder for the first entry will be 1027000, followed by
+# 1027001, 1027002, etc. If the number of sudoRole entries is larger
+# than the padding would allow, cvtsudoers will exit with an error.
+# By default, no padding is performed.
+#padding = 0
+
+# Use an alternate passwd file. When "match_local" is also enabled, perform
+# passwd queries using the specified file instead of the system passwd database.
+#passwd_file = /etc/passwd
+
+# When "match_local" is also enabled, cvtsudoers will prune
+# out non-matching users, groups and hosts from matching entries.
+# Defaults to no.
+#prune_matches = no
+
+# The base DN (distinguished name) that will be used when performing LDAP
+# queries. If this option is not specified, the value of the SUDOERS_BASE
+# environment variable will be used instead.
+#sudoers_base = ou=SUDOers,dc=my-domain,dc=com
+
+# Suppress the output of specific sections of the security policy.
+# One or more section names may be specified, separated by a comma (',').
+# The supported section name are: defaults, aliases and privileges
+# (which may be shortened to privs).
+#suppress = defaults,aliases,privs
diff --git a/examples/pam.conf b/examples/pam.conf
new file mode 100644
index 0000000..d56e712
--- /dev/null
+++ b/examples/pam.conf
@@ -0,0 +1,30 @@
+#%PAM-1.0
+# Sample /etc/pam.d/sudo file for RedHat 9 / Fedora Core.
+# For other Linux distributions you may want to
+# use /etc/pam.d/sshd or /etc/pam.d/su as a guide.
+#
+# There are two basic ways to configure PAM, either via pam_stack
+# or by explicitly specifying the various methods to use.
+#
+# Here we use pam_stack
+auth required pam_stack.so service=system-auth
+account required pam_stack.so service=system-auth
+password required pam_stack.so service=system-auth
+session required pam_stack.so service=system-auth
+#
+# Alternately, you can specify the authentication method directly.
+# Here we use pam_unix for normal password authentication.
+#auth required pam_env.so
+#auth sufficient pam_unix.so
+#account required pam_unix.so
+#password required pam_cracklib.so retry=3 type=
+#password required pam_unix.so nullok use_authtok md5 shadow
+#session required pam_limits.so
+#session required pam_unix.so
+#
+# Another option is to use SMB for authentication.
+#auth required pam_env.so
+#auth sufficient pam_smb_auth.so
+#account required pam_smb_auth.so
+#password required pam_smb_auth.so
+#session required pam_limits.so
diff --git a/examples/sudo.conf.in b/examples/sudo.conf.in
new file mode 100644
index 0000000..2187457
--- /dev/null
+++ b/examples/sudo.conf.in
@@ -0,0 +1,131 @@
+#
+# Default @sysconfdir@/sudo.conf file
+#
+# Sudo plugins:
+# Plugin plugin_name plugin_path plugin_options ...
+#
+# The plugin_path is relative to @plugindir@ unless
+# fully qualified.
+# The plugin_name corresponds to a global symbol in the plugin
+# that contains the plugin interface structure.
+# The plugin_options are optional.
+#
+# The sudoers plugin is used by default if no Plugin lines are present.
+#Plugin sudoers_policy @sudoers_plugin@
+#Plugin sudoers_io @sudoers_plugin@
+#Plugin sudoers_audit @sudoers_plugin@
+
+#
+# Sudo askpass:
+# Path askpass /path/to/askpass
+#
+# An askpass helper program may be specified to provide a graphical
+# password prompt for "sudo -A" support. Sudo does not ship with its
+# own askpass program but can use the OpenSSH askpass.
+#
+# Use the OpenSSH askpass
+#Path askpass /usr/X11R6/bin/ssh-askpass
+#
+# Use the Gnome OpenSSH askpass
+#Path askpass /usr/libexec/openssh/gnome-ssh-askpass
+
+#
+# Sudo device search path:
+# Path devsearch /dev/path1:/dev/path2:/dev
+#
+# A colon-separated list of paths to check when searching for a user's
+# terminal device.
+#
+#Path devsearch /dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev
+
+#
+# Sudo command interception:
+# Path intercept /path/to/sudo_intercept.so
+#
+# Path to a shared library containing replacements for the execv(),
+# execve() and fexecve() library functions that perform a policy check
+# to verify the command is allowed and simply return an error if not.
+# This is used to implement the "intercept" functionality on systems that
+# support LD_PRELOAD or its equivalent.
+#
+# The compiled-in value is usually sufficient and should only be changed
+# if you rename or move the sudo_intercept.so file.
+#
+#Path intercept @intercept_file@
+
+#
+# Sudo noexec:
+# Path noexec /path/to/sudo_noexec.so
+#
+# Path to a shared library containing replacements for the execv(),
+# execve() and fexecve() library functions that just return an error.
+# This is used to implement the "noexec" functionality on systems that
+# support LD_PRELOAD or its equivalent.
+#
+# The compiled-in value is usually sufficient and should only be changed
+# if you rename or move the sudo_noexec.so file.
+#
+#Path noexec @noexec_file@
+
+#
+# Sudo plugin directory:
+# Path plugin_dir /path/to/plugins
+#
+# The default directory to use when searching for plugins that are
+# specified without a fully qualified path name.
+#
+#Path plugin_dir @plugindir@
+
+#
+# Core dumps:
+# Set disable_coredump true|false
+#
+# By default, sudo disables core dumps while it is executing (they
+# are re-enabled for the command that is run).
+# To aid in debugging sudo problems, you may wish to enable core
+# dumps by setting "disable_coredump" to false.
+#
+#Set disable_coredump false
+
+#
+# User groups:
+# Set group_source static|dynamic|adaptive
+#
+# Sudo passes the user's group list to the policy plugin.
+# If the user is a member of the maximum number of groups (usually 16),
+# sudo will query the group database directly to be sure to include
+# the full list of groups.
+#
+# On some systems, this can be expensive so the behavior is configurable.
+# The "group_source" setting has three possible values:
+# static - use the user's list of groups returned by the kernel.
+# dynamic - query the group database to find the list of groups.
+# adaptive - if user is in less than the maximum number of groups.
+# use the kernel list, else query the group database.
+#
+#Set group_source static
+
+#
+# Sudo interface probing:
+# Set probe_interfaces true|false
+#
+# By default, sudo will probe the system's network interfaces and
+# pass the IP address of each enabled interface to the policy plugin.
+# On systems with a large number of virtual interfaces this may take
+# a noticeable amount of time.
+#
+#Set probe_interfaces false
+
+#
+# Sudo debug files:
+# Debug program /path/to/debug_log subsystem@priority[,subsyste@priority]
+#
+# Sudo and related programs support logging debug information to a file.
+# The program is typically sudo, sudoers.so, sudoreplay, or visudo.
+#
+# Subsystems vary based on the program; "all" matches all subsystems.
+# Priority may be crit, err, warn, notice, diag, info, trace, or debug.
+# Multiple subsystem@priority may be specified, separated by a comma.
+#
+#Debug sudo @log_dir@/sudo_debug all@debug
+#Debug sudoers.so @log_dir@/sudoers_debug all@debug
diff --git a/examples/sudo_logsrvd.conf.in b/examples/sudo_logsrvd.conf.in
new file mode 100644
index 0000000..86fda90
--- /dev/null
+++ b/examples/sudo_logsrvd.conf.in
@@ -0,0 +1,251 @@
+#
+# sudo logsrv daemon configuration
+#
+
+[server]
+# The host name or IP address and port to listen on with an optional TLS
+# flag. If no port is specified, port 30343 will be used for plaintext
+# connections and port 30344 will be used to TLS connections.
+# The following forms are accepted:
+# listen_address = hostname(tls)
+# listen_address = hostname:port(tls)
+# listen_address = IPv4_address(tls)
+# listen_address = IPv4_address:port(tls)
+# listen_address = [IPv6_address](tls)
+# listen_address = [IPv6_address]:port(tls)
+#
+# The (tls) suffix should be omitted for plaintext connections.
+#
+# Multiple listen_address settings may be specified.
+# The default is to listen on all addresses.
+#listen_address = *:30343
+#listen_address = *:30344(tls)
+
+# The file containing the ID of the running sudo_logsrvd process.
+#pid_file = @rundir@/sudo_logsrvd.pid
+
+# Where to log server warnings: none, stderr, syslog, or a path name.
+#server_log = syslog
+
+# If true, enable the SO_KEEPALIVE socket option on client connections.
+# Defaults to true.
+#tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the client to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+#timeout = 30
+
+# If true, the server will validate its own certificate at startup.
+# Defaults to true.
+#tls_verify = true
+
+# If true, client certificates will be validated by the server;
+# clients without a valid certificate will be unable to connect.
+# By default, client certs are not checked.
+#tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+#tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# Required for TLS connections.
+#tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# Required for TLS connections.
+#tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# This setting is only effective if the negotiated protocol is TLS version
+# 1.2. The default cipher list is HIGH:!aNULL.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default cipher list is TLS_AES_256_GCM_SHA384.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# If not set, the server will use the OpenSSL defaults.
+#tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[relay]
+# The host name or IP address and port to send logs to in relay mode.
+# The syntax is identical to listen_address with the exception of
+# the wild card ('*') syntax. When this setting is enabled, logs will
+# be relayed to the specified host instead of being stored locally.
+# This setting is not enabled by default.
+#relay_host = relayhost.dom.ain
+#relay_host = relayhost.dom.ain(tls)
+
+# The amount of time, in seconds, the server will wait for a connection
+# to the relay server to complete. A value of 0 will disable the timeout.
+# The default value is 30.
+#connect_timeout = 30
+
+# The directory to store messages in before they are sent to the relay.
+# Messages are stored in wire format.
+# The default value is @relay_dir@.
+#relay_dir = @relay_dir@
+
+# The number of seconds to wait after a connection error before
+# making a new attempt to forward a message to a relay host.
+# The default value is 30.
+#retry_interval = 30
+
+# Whether to store the log before relaying it. If true, enable store
+# and forward mode. If false, the client connection is immediately
+# relayed. Defaults to false.
+#store_first = true
+
+# If true, enable the SO_KEEPALIVE socket option on relay connections.
+# Defaults to true.
+#tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the relay to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+#timeout = 30
+
+# If true, the server's relay certificate will be verified at startup.
+# The default is to use the value in the [server] section.
+#tls_verify = true
+
+# Whether to verify the relay's certificate for TLS connections.
+# The default is to use the value in the [server] section.
+#tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+# The default is to use the value in the [server] section.
+#tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# The default is to use the certificate in the [server] section.
+#tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# The default is to use the key in the [server] section.
+#tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# this setting is only effective if the negotiated protocol is TLS version
+# 1.2. The default is to use the value in the [server] section.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default is to use the value in the [server] section.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# The default is to use the value in the [server] section.
+#tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[iolog]
+# The top-level directory to use when constructing the path name for the
+# I/O log directory. The session sequence number, if any, is stored here.
+#iolog_dir = @iolog_dir@
+
+# The path name, relative to iolog_dir, in which to store I/O logs.
+# It is possible for iolog_file to contain directory components.
+#iolog_file = %{seq}
+
+# If set, I/O logs will be compressed using zlib. Enabling compression can
+# make it harder to view the logs in real-time as the program is executing.
+#iolog_compress = false
+
+# If set, I/O log data is flushed to disk after each write instead of
+# buffering it. This makes it possible to view the logs in real-time
+# as the program is executing but reduces the effectiveness of compression.
+#iolog_flush = true
+
+# The group to use when creating new I/O log files and directories.
+# If iolog_group is not set, the primary group-ID of the user specified
+# by iolog_user is used. If neither iolog_group nor iolog_user
+# are set, I/O log files and directories are created with group-ID 0.
+#iolog_group = wheel
+
+# The user to use when setting the user-ID and group-ID of new I/O
+# log files and directories. If iolog_group is set, it will be used
+# instead of the user's primary group-ID. By default, I/O log files
+# and directories are created with user and group-ID 0.
+#iolog_user = root
+
+# The file mode to use when creating I/O log files. The file permissions
+# will always include the owner read and write bits, even if they are
+# not present in the specified mode. When creating I/O log directories,
+# search (execute) bits are added to match the read and write bits
+# specified by iolog_mode.
+#iolog_mode = 0600
+
+# If disabled, sudo_logsrvd will attempt to avoid logging plaintext
+# password in the terminal input using passprompt_regex.
+#log_passwords = true
+
+# The maximum sequence number that will be substituted for the "%{seq}"
+# escape in the I/O log file. While the value substituted for "%{seq}"
+# is in base 36, maxseq itself should be expressed in decimal. Values
+# larger than 2176782336 (which corresponds to the base 36 sequence
+# number "ZZZZZZ") will be silently truncated to 2176782336.
+#maxseq = 2176782336
+
+# One or more POSIX extended regular expressions used to match
+# password prompts in the terminal output when log_passwords is
+# disabled. Multiple passprompt_regex settings may be specified.
+#passprompt_regex = [Pp]assword[: ]*
+#passprompt_regex = [Pp]assword for [a-z0-9]+: *
+
+[eventlog]
+# Where to log accept, reject, exit, and alert events.
+# Accepted values are syslog, logfile, or none.
+# Defaults to syslog
+#log_type = syslog
+
+# Whether to log an event when a command exits or is terminated by a signal.
+# Defaults to false
+#log_exit = true
+
+# Event log format.
+# Supported log formats are "sudo" and "json"
+# Defaults to sudo
+#log_format = sudo
+
+[syslog]
+# The maximum length of a syslog payload.
+# On many systems, syslog(3) has a relatively small log buffer.
+# IETF RFC 5424 states that syslog servers must support messages
+# of at least 480 bytes and should support messages up to 2048 bytes.
+# Messages larger than this value will be split into multiple messages.
+#maxlen = 960
+
+# The syslog facility to use for event log messages.
+# The following syslog facilities are supported: authpriv (if your OS
+# supports it), auth, daemon, user, local0, local1, local2, local3,
+# local4, local5, local6, and local7.
+#facility = @logfac@
+
+# Syslog priority to use for event log accept messages, when the command
+# is allowed by the security policy. The following syslog priorities are
+# supported: alert, crit, debug, emerg, err, info, notice, warning, none.
+#accept_priority = @goodpri@
+
+# Syslog priority to use for event log reject messages, when the command
+# is not allowed by the security policy.
+#reject_priority = @badpri@
+
+# Syslog priority to use for event log alert messages reported by the
+# client.
+#alert_priority = @badpri@
+
+# The syslog facility to use for server warning messages.
+# Defaults to daemon.
+#server_facility = daemon
+
+[logfile]
+# The path to the file-based event log.
+# This path must be fully-qualified and start with a '/' character.
+#path = @logpath@
+
+# The format string used when formatting the date and time for
+# file-based event logs. Formatting is performed via strftime(3) so
+# any format string supported by that function is allowed.
+#time_format = %h %e %T
diff --git a/examples/sudoers.in b/examples/sudoers.in
new file mode 100644
index 0000000..46953d6
--- /dev/null
+++ b/examples/sudoers.in
@@ -0,0 +1,133 @@
+#
+# Sample /etc/sudoers file.
+#
+# This file MUST be edited with the 'visudo' command as root.
+#
+# See the sudoers man page for the details on how to write a sudoers file.
+
+##
+# Override built-in defaults
+##
+Defaults syslog=auth,runcwd=~
+Defaults>root !set_logname
+Defaults:FULLTIMERS !lecture,runchroot=*
+Defaults:millert !authenticate
+Defaults@SERVERS log_year, logfile=@log_dir@/sudo.log
+Defaults!PAGERS noexec
+
+##
+# User alias specification
+##
+User_Alias FULLTIMERS = millert, mikef, dowdy
+User_Alias PARTTIMERS = bostley, jwfox, crawl
+User_Alias WEBADMIN = will, wendy, wim
+
+##
+# Runas alias specification
+##
+Runas_Alias OP = root, operator
+Runas_Alias DB = oracle, sybase
+
+##
+# Host alias specification
+##
+Host_Alias SPARC = bigtime, eclipse, moet, anchor:\
+ SGI = grolsch, dandelion, black:\
+ ALPHA = widget, thalamus, foobar:\
+ HPPA = boa, nag, python
+Host_Alias CUNETS = 128.138.0.0/255.255.0.0
+Host_Alias CSNETS = 128.138.243.0, 128.138.204.0/24, 128.138.242.0
+Host_Alias SERVERS = primary, mail, www, ns
+Host_Alias CDROM = orion, perseus, hercules
+
+##
+# Cmnd alias specification
+##
+Cmnd_Alias DUMPS = /usr/sbin/dump, /usr/sbin/rdump, /usr/sbin/restore, \
+ /usr/sbin/rrestore, /usr/bin/mt, \
+ sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ== \
+ /home/operator/bin/start_backups
+Cmnd_Alias KILL = /usr/bin/kill, /usr/bin/top
+Cmnd_Alias PRINTING = /usr/sbin/lpc, /usr/bin/lprm
+Cmnd_Alias SHUTDOWN = /usr/sbin/shutdown
+Cmnd_Alias HALT = /usr/sbin/halt
+Cmnd_Alias REBOOT = /usr/sbin/reboot
+Cmnd_Alias SHELLS = /sbin/sh, /usr/bin/sh, /usr/bin/csh, /usr/bin/ksh, \
+ /usr/local/bin/tcsh, /usr/bin/rsh, \
+ /usr/local/bin/zsh
+Cmnd_Alias SU = /usr/bin/su
+Cmnd_Alias VIPW = /usr/sbin/vipw, /usr/bin/passwd, /usr/bin/chsh, \
+ /usr/bin/chfn
+Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less
+
+##
+# User specification
+##
+
+# root and users in group wheel can run anything on any machine as any user
+root ALL = (ALL:ALL) ALL
+%wheel ALL = (ALL:ALL) ALL
+
+# full time sysadmins can run anything on any machine without a password
+FULLTIMERS ALL = (ALL:ALL) NOPASSWD: ALL
+
+# part time sysadmins may run anything as root but need a password
+PARTTIMERS ALL = ALL
+
+# jack may run anything on machines in CSNETS
+jack CSNETS = ALL
+
+# lisa may run any command on any host in CUNETS (a class B network)
+lisa CUNETS = ALL
+
+# operator may run maintenance commands and anything in /usr/oper/bin/
+operator ALL = DUMPS, KILL, SHUTDOWN, HALT, REBOOT, PRINTING,\
+ sudoedit /etc/printcap, /usr/oper/bin/
+
+# joe may su only to operator
+joe ALL = /usr/bin/su operator
+
+# pete may change passwords for anyone but root on the hp snakes
+pete HPPA = /usr/bin/passwd ^[a-zA-Z0-9_]+$, !/usr/bin/passwd root
+
+# bob may run anything on the sparc and sgi machines as any user
+# listed in the Runas_Alias "OP" (ie: root and operator)
+bob SPARC = (OP) ALL : SGI = (OP) ALL
+
+# jim may run anything on machines in the biglab netgroup
+jim +biglab = ALL
+
+# users in the secretaries netgroup need to help manage the printers
+# as well as add and remove users
++secretaries ALL = PRINTING, /usr/bin/adduser, /usr/bin/rmuser
+
+# fred can run commands as oracle or sybase without a password
+fred ALL = (DB) NOPASSWD: ALL
+
+# on the alphas, john may su to anyone except root, no flags are allowed.
+john ALPHA = /usr/bin/su ^[a-zA-Z0-9_]+$, !/usr/bin/su root
+
+# jen can run anything on all machines except the ones
+# in the "SERVERS" Host_Alias
+jen ALL, !SERVERS = ALL
+
+# jill can run any commands in the directory /usr/bin/, except for
+# those in the SU and SHELLS aliases.
+jill SERVERS = /usr/bin/, !SU, !SHELLS
+
+# steve can run any command in the directory /usr/local/op_commands/
+# as user operator.
+steve CSNETS = (operator) /usr/local/op_commands/
+
+# matt needs to be able to kill things on his workstation when
+# they get hung.
+matt valkyrie = KILL
+
+# users in the WEBADMIN User_Alias (will, wendy, and wim)
+# may run any command as user www (which owns the web pages)
+# or simply su to www.
+WEBADMIN www = (www) ALL, (root) /usr/bin/su www
+
+# anyone can mount/unmount a cd-rom on the machines in the CDROM alias
+ALL CDROM = NOPASSWD: /sbin/umount /CDROM,\
+ /sbin/mount -o nosuid\,nodev /dev/cd0a /CDROM
diff --git a/examples/syslog.conf.in b/examples/syslog.conf.in
new file mode 100644
index 0000000..eff72ac
--- /dev/null
+++ b/examples/syslog.conf.in
@@ -0,0 +1,26 @@
+# This is a sample syslog.conf fragment for use with Sudo.
+#
+# By default, sudo logs to "authpriv" if your system supports it, else it
+# uses "auth". The facility can be set via the --with-logfac configure
+# option or in the sudoers file.
+# To see what syslog facility a sudo binary uses, run `sudo -V' as *root*.
+#
+# NOTES:
+# The whitespace in the following line is made up of <TAB>
+# characters, *not* spaces. You cannot just cut and paste!
+#
+# If you edit syslog.conf you need to send syslogd a HUP signal.
+# Ie: kill -HUP process_id
+#
+# Syslogd will not create new log files for you, you must first
+# create the file before syslogd will log to it. Eg.
+# 'touch @log_dir@/sudo'
+
+# This logs successful and failed sudo attempts to the file @log_dir@/auth
+# If your system has the authpriv syslog facility, use authpriv.debug
+auth.debug @log_dir@/auth
+
+# To log to a remote machine, use something like the following,
+# where "loghost" is the name of the remote machine.
+# If your system has the authpriv syslog facility, use authpriv.debug
+auth.debug @loghost
diff --git a/include/Makefile.in b/include/Makefile.in
new file mode 100644
index 0000000..da6d08d
--- /dev/null
+++ b/include/Makefile.in
@@ -0,0 +1,115 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2011-2015, 2017-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+includedir = @includedir@
+scriptdir = $(top_srcdir)/scripts
+cross_compiling = @CROSS_COMPILING@
+
+# Our install program supports extra flags...
+INSTALL = $(SHELL) $(scriptdir)/install-sh -c
+INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
+
+# Where to install things...
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+sysconfdir = @sysconfdir@
+adminconfdir = @adminconfdir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+localstatedir = @localstatedir@
+
+# User and group ids the installed files should be "owned" by
+install_uid = 0
+install_gid = 0
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+all:
+
+depend:
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file include/Makefile
+
+.SUFFIXES: .h
+
+pre-install:
+
+install: install-includes
+
+install-dirs:
+ $(SHELL) $(scriptdir)/mkinstalldirs $(DESTDIR)$(includedir)
+
+install-binaries:
+
+install-doc:
+
+install-includes: install-dirs
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 $(srcdir)/sudo_plugin.h $(DESTDIR)$(includedir)
+
+install-plugin:
+
+install-fuzzer:
+
+uninstall:
+ -rm -f $(DESTDIR)$(includedir)/sudo_plugin.h
+
+splint:
+
+cppcheck:
+
+pvs-log-files:
+
+pvs-studio:
+
+fuzz:
+
+check-fuzzer:
+
+check: check-fuzzer
+
+check-verbose: check
+
+clean:
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile
+
+clobber: distclean
+
+realclean: distclean
+
+cleandir: distclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean
diff --git a/include/compat/charclass.h b/include/compat/charclass.h
new file mode 100644
index 0000000..77c8d7f
--- /dev/null
+++ b/include/compat/charclass.h
@@ -0,0 +1,41 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2008, 2010 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * POSIX character class support for fnmatch() and glob().
+ */
+static struct cclass {
+ const char *name;
+ int (*isctype)(int);
+} cclasses[] = {
+ { "alnum", isalnum },
+ { "alpha", isalpha },
+ { "blank", isblank },
+ { "cntrl", iscntrl },
+ { "digit", isdigit },
+ { "graph", isgraph },
+ { "lower", islower },
+ { "print", isprint },
+ { "punct", ispunct },
+ { "space", isspace },
+ { "upper", isupper },
+ { "xdigit", isxdigit },
+ { NULL, NULL }
+};
+
+#define NCCLASSES (nitems(cclasses) - 1)
diff --git a/include/compat/endian.h b/include/compat/endian.h
new file mode 100644
index 0000000..fe6ee83
--- /dev/null
+++ b/include/compat/endian.h
@@ -0,0 +1,80 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013, 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef COMPAT_ENDIAN_H
+#define COMPAT_ENDIAN_H
+
+#ifndef BYTE_ORDER
+# undef LITTLE_ENDIAN
+# define LITTLE_ENDIAN 1234
+# undef BIG_ENDIAN
+# define BIG_ENDIAN 4321
+# undef UNKNOWN_ENDIAN
+# define UNKNOWN_ENDIAN 0
+
+/*
+ * Attempt to guess endianness.
+ * Solaris may define _LITTLE_ENDIAN and _BIG_ENDIAN to 1
+ * HP-UX may define __LITTLE_ENDIAN__ and __BIG_ENDIAN__ to 1
+ * Otherwise, check for cpu-specific cpp defines.
+ * Note that some CPUs are bi-endian, including: arm, powerpc, alpha,
+ * sparc64, mips, hppa, sh4 and ia64.
+ * We just check for the most common uses.
+ */
+
+# if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
+ (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+# define BYTE_ORDER LITTLE_ENDIAN
+# elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
+ (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+# define BYTE_ORDER BIG_ENDIAN
+# elif defined(__BYTE_ORDER)
+# define BYTE_ORDER __BYTE_ORDER
+# elif defined(_BYTE_ORDER)
+# define BYTE_ORDER _BYTE_ORDER
+# elif defined(_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__)
+# define BYTE_ORDER LITTLE_ENDIAN
+# elif defined(_BIG_ENDIAN) || defined(__BIG_ENDIAN__)
+# define BYTE_ORDER BIG_ENDIAN
+# elif defined(__alpha__) || defined(__alpha) || defined(__amd64) || \
+ defined(BIT_ZERO_ON_RIGHT) || defined(i386) || defined(__i386) || \
+ defined(MIPSEL) || defined(_MIPSEL) || defined(ns32000) || \
+ defined(__ns3200) || defined(sun386) || defined(vax) || \
+ defined(__vax) || defined(__x86__) || defined(__riscv) || \
+ (defined(sun) && defined(__powerpc)) || \
+ (!defined(__hpux) && defined(__ia64))
+# define BYTE_ORDER LITTLE_ENDIAN
+# elif defined(__68k__) || defined(apollo) || defined(BIT_ZERO_ON_LEFT) || \
+ defined(__convex__) || defined(_CRAY) || defined(DGUX) || \
+ defined(__hppa) || defined(__hp9000) || defined(__hp9000s300) || \
+ defined(__hp9000s700) || defined(__hp3000s900) || \
+ defined(ibm032) || defined(ibm370) || defined(_IBMR2) || \
+ defined(is68k) || defined(mc68000) || defined(m68k) || \
+ defined(__m68k) || defined(m88k) || defined(__m88k) || \
+ defined(MIPSEB) || defined(_MIPSEB) || defined(MPE) || \
+ defined(pyr) || defined(__powerpc) || defined(__powerpc__) || \
+ defined(sel) || defined(__sparc) || defined(__sparc__) || \
+ defined(tahoe) || (defined(__hpux) && defined(__ia64)) || \
+ (defined(sun) && defined(__powerpc))
+# define BYTE_ORDER BIG_ENDIAN
+# else
+# define BYTE_ORDER UNKNOWN_ENDIAN
+# endif
+#endif /* BYTE_ORDER */
+
+#endif /* COMPAT_ENDIAN_H */
diff --git a/include/compat/fnmatch.h b/include/compat/fnmatch.h
new file mode 100644
index 0000000..75cac1f
--- /dev/null
+++ b/include/compat/fnmatch.h
@@ -0,0 +1,34 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef COMPAT_FNMATCH_H
+#define COMPAT_FNMATCH_H
+
+#define FNM_NOMATCH 1 /* String does not match pattern */
+
+#define FNM_PATHNAME (1 << 0) /* Globbing chars don't match '/' */
+#define FNM_PERIOD (1 << 1) /* Leading '.' in string must exactly */
+#define FNM_NOESCAPE (1 << 2) /* Backslash treated as ordinary char */
+#define FNM_LEADING_DIR (1 << 3) /* Only match the leading directory */
+#define FNM_CASEFOLD (1 << 4) /* Case insensitive matching */
+
+sudo_dso_public int sudo_fnmatch(const char *pattern, const char *string, int flags);
+
+#define fnmatch(_a, _b, _c) sudo_fnmatch((_a), (_b), (_c))
+
+#endif /* COMPAT_FNMATCH_H */
diff --git a/include/compat/getaddrinfo.h b/include/compat/getaddrinfo.h
new file mode 100644
index 0000000..c1f87ef
--- /dev/null
+++ b/include/compat/getaddrinfo.h
@@ -0,0 +1,83 @@
+/*
+ * Replacement implementation of getaddrinfo.
+ *
+ * This is an implementation of the getaddrinfo family of functions for
+ * systems that lack it, so that code can use getaddrinfo always. It provides
+ * IPv4 support only; for IPv6 support, a system getaddrinfo implementation is
+ * required.
+ *
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Written by Russ Allbery <rra@stanford.edu>
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
+ */
+
+#ifndef COMPAT_GETADDRINFO_H
+#define COMPAT_GETADDRINFO_H
+
+#include <config.h>
+
+/* Skip this entire file if a system getaddrinfo was detected. */
+#ifndef HAVE_GETADDRINFO
+
+/* OpenBSD likes to have sys/types.h included before sys/socket.h. */
+#include <sys/types.h>
+#include <sys/socket.h>
+
+/* The struct returned by getaddrinfo, from RFC 3493. */
+struct addrinfo {
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME, .. */
+ int ai_family; /* AF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ socklen_t ai_addrlen; /* Length of ai_addr */
+ char *ai_canonname; /* Canonical name for nodename */
+ struct sockaddr *ai_addr; /* Binary address */
+ struct addrinfo *ai_next; /* Next structure in linked list */
+};
+
+/* Constants for ai_flags from RFC 3493, combined with binary or. */
+#define AI_PASSIVE 0x0001
+#define AI_CANONNAME 0x0002
+#define AI_NUMERICHOST 0x0004
+#define AI_NUMERICSERV 0x0008
+#define AI_V4MAPPED 0x0010
+#define AI_ALL 0x0020
+#define AI_ADDRCONFIG 0x0040
+
+/* Error return codes from RFC 3493. */
+#define EAI_AGAIN 1 /* Temporary name resolution failure */
+#define EAI_BADFLAGS 2 /* Invalid value in ai_flags parameter */
+#define EAI_FAIL 3 /* Permanent name resolution failure */
+#define EAI_FAMILY 4 /* Address family not recognized */
+#define EAI_MEMORY 5 /* Memory allocation failure */
+#define EAI_NONAME 6 /* nodename or servname unknown */
+#define EAI_SERVICE 7 /* Service not recognized for socket type */
+#define EAI_SOCKTYPE 8 /* Socket type not recognized */
+#define EAI_SYSTEM 9 /* System error occurred, see errno */
+#define EAI_OVERFLOW 10 /* An argument buffer overflowed */
+
+/* Function prototypes. */
+sudo_dso_public int sudo_getaddrinfo(const char *nodename, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res);
+sudo_dso_public void sudo_freeaddrinfo(struct addrinfo *ai);
+sudo_dso_public const char *sudo_gai_strerror(int ecode);
+
+/* Map sudo_* to RFC 3493 names. */
+#undef getaddrinfo
+#define getaddrinfo(_a, _b, _c, _d) sudo_getaddrinfo((_a), (_b), (_c), (_d))
+#undef freeaddrinfo
+#define freeaddrinfo(_a) sudo_freeaddrinfo((_a))
+#undef gai_strerror
+#define gai_strerror(_a) sudo_gai_strerror((_a))
+
+#endif /* !HAVE_GETADDRINFO */
+#endif /* COMPAT_GETADDRINFO_H */
diff --git a/include/compat/getopt.h b/include/compat/getopt.h
new file mode 100644
index 0000000..da99d34
--- /dev/null
+++ b/include/compat/getopt.h
@@ -0,0 +1,83 @@
+/* $OpenBSD: getopt.h,v 1.2 2008/06/26 05:42:04 ray Exp $ */
+/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */
+/* $FreeBSD: head/include/getopt.h 203963 2010-02-16 19:28:10Z imp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef COMPAT_GETOPT_H
+#define COMPAT_GETOPT_H
+
+/*
+ * GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension.
+ */
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+struct option {
+ /* name of long option */
+ const char *name;
+ /*
+ * one of no_argument, required_argument, and optional_argument:
+ * whether option takes an argument
+ */
+ int has_arg;
+ /* if not NULL, set *flag to val when option found */
+ int *flag;
+ /* if flag not NULL, value to set *flag to; else return value */
+ int val;
+};
+
+sudo_dso_public int sudo_getopt_long(int, char * const *, const char *,
+ const struct option *, int *);
+#undef getopt_long
+#define getopt_long(_a, _b, _c, _d, _e) \
+ sudo_getopt_long((_a), (_b), (_c), (_d), (_e))
+
+sudo_dso_public int sudo_getopt_long_only(int, char * const *, const char *,
+ const struct option *, int *);
+#undef getopt_long_only
+#define getopt_long_only(_a, _b, _c, _d, _e) \
+ sudo_getopt_long_only((_a), (_b), (_c), (_d), (_e))
+#if 0
+sudo_dso_public int sudo_getopt(int, char * const [], const char *);
+#undef getopt
+#define getopt(_a, _b, _c) sudo_getopt((_a), (_b), (_c))
+#endif
+
+extern char *optarg; /* getopt(3) external variables */
+extern int opterr;
+extern int optind;
+extern int optopt;
+extern int optreset;
+
+#endif /* !COMPAT_GETOPT_H */
diff --git a/include/compat/glob.h b/include/compat/glob.h
new file mode 100644
index 0000000..7c06a2e
--- /dev/null
+++ b/include/compat/glob.h
@@ -0,0 +1,78 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)glob.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef COMPAT_GLOB_H
+#define COMPAT_GLOB_H
+
+struct stat;
+typedef struct {
+ size_t gl_pathc; /* Count of total paths so far. */
+ size_t gl_matchc; /* Count of paths matching pattern. */
+ size_t gl_offs; /* Reserved at beginning of gl_pathv. */
+ int gl_flags; /* Copy of flags parameter to glob. */
+ char **gl_pathv; /* List of paths matching pattern. */
+ /* Copy of errfunc parameter to glob. */
+ int (*gl_errfunc)(const char *, int);
+} glob_t;
+
+/* Flags */
+#define GLOB_APPEND 0x0001 /* Append to output from previous call. */
+#define GLOB_DOOFFS 0x0002 /* Use gl_offs. */
+#define GLOB_ERR 0x0004 /* Return on error. */
+#define GLOB_MARK 0x0008 /* Append / to matching directories. */
+#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */
+#define GLOB_NOSORT 0x0020 /* Don't sort. */
+#define GLOB_NOESCAPE 0x0040 /* Disable backslash escaping. */
+
+/* Non-POSIX extensions */
+#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */
+#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */
+#define GLOB_TILDE 0x0200 /* Expand tilde names from the passwd file. */
+#define GLOB_LIMIT 0x0400 /* Limit pattern match output to ARG_MAX */
+
+/* Error values returned by glob(3) */
+#define GLOB_NOSPACE (-1) /* Malloc call failed. */
+#define GLOB_ABORTED (-2) /* Unignored error. */
+#define GLOB_NOMATCH (-3) /* No match and GLOB_NOCHECK not set. */
+#define GLOB_NOSYS (-4) /* Function not supported. */
+
+sudo_dso_public int sudo_glob(const char *, int, int (*)(const char *, int), glob_t *);
+sudo_dso_public void sudo_globfree(glob_t *);
+
+#define glob(_a, _b, _c, _d) sudo_glob((_a), (_b), (_c), (_d))
+#define globfree(_a) sudo_globfree((_a))
+
+#endif /* !COMPAT_GLOB_H */
diff --git a/include/compat/nss_dbdefs.h b/include/compat/nss_dbdefs.h
new file mode 100644
index 0000000..726beae
--- /dev/null
+++ b/include/compat/nss_dbdefs.h
@@ -0,0 +1,110 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef COMPAT_NSS_DBDEFS_H
+#define COMPAT_NSS_DBDEFS_H
+
+/*
+ * Bits of nss_dbdefs.h and nss_common.h needed to implement
+ * getgrouplist(3) using nss_search(3).
+ *
+ * HP-UX does not ship those headers so we need this compatibility header.
+ * It may also work on other systems that use a Solaris-derived nsswitch
+ * API.
+ */
+
+#ifdef NEED_HPUX_MUTEX
+# include <synch.h>
+#endif
+
+typedef enum {
+ NSS_SUCCESS,
+ NSS_NOTFOUND,
+ NSS_UNAVAIL,
+ NSS_TRYAGAIN
+} nss_status_t;
+
+typedef struct nss_db_params {
+ const char *name;
+ const char *config_name;
+ const char *default_config;
+ unsigned int max_active_per_src;
+ unsigned int max_dormant_per_src;
+ int flags;
+ void *finders;
+ void *private;
+ void (*cleanup)(struct nss_db_params *);
+} nss_db_params_t;
+
+struct nss_groupsbymem {
+ const char *username;
+ gid_t *gid_array;
+ int maxgids;
+ int force_slow_way;
+ int (*str2ent)(const char *instr, int instr_len, void *ent, char *buffer, int buflen);
+ nss_status_t (*process_cstr)(const char *instr, int instr_len, struct nss_groupsbymem *);
+ int numgids;
+};
+
+typedef struct {
+ void *result; /* group struct to fill in. */
+ char *buffer; /* string buffer for above */
+ int buflen; /* string buffer size */
+} nss_XbyY_buf_t;
+
+struct nss_db_state;
+typedef struct {
+ struct nss_db_state *s;
+#ifdef NEED_HPUX_MUTEX
+ lwp_mutex_t lock;
+#endif
+} nss_db_root_t;
+
+#ifdef NEED_HPUX_MUTEX
+# define NSS_DB_ROOT_INIT { 0, LWP_MUTEX_INITIALIZER }
+#else
+# define NSS_DB_ROOT_INIT { 0 }
+#endif
+#define DEFINE_NSS_DB_ROOT(name) nss_db_root_t name = NSS_DB_ROOT_INIT
+
+/* Backend function to find all groups a user belongs to for initgroups(). */
+#define NSS_DBOP_GROUP_BYMEMBER 6
+
+/* str2ent function return values */
+#define NSS_STR_PARSE_SUCCESS 0
+#define NSS_STR_PARSE_PARSE 1
+#define NSS_STR_PARSE_ERANGE 2
+
+/* Max length for an /etc/group file line. */
+#define NSS_BUFLEN_GROUP 8192
+
+/* HP-UX uses an extra underscore for these functions. */
+#ifdef HAVE___NSS_INITF_GROUP
+# define _nss_initf_group __nss_initf_group
+#endif
+#ifdef HAVE___NSS_XBYY_BUF_ALLOC
+# define _nss_XbyY_buf_alloc __nss_XbyY_buf_alloc
+# define _nss_XbyY_buf_free __nss_XbyY_buf_free
+#endif
+
+typedef void (*nss_db_initf_t)(nss_db_params_t *);
+extern nss_status_t nss_search(nss_db_root_t *, nss_db_initf_t, int search_fnum, void *search_args);
+extern nss_XbyY_buf_t *_nss_XbyY_buf_alloc(int struct_size, int buffer_size);
+extern void _nss_XbyY_buf_free(nss_XbyY_buf_t *);
+
+#endif /* COMPAT_NSS_DBDEFS_H */
diff --git a/include/compat/sha2.h b/include/compat/sha2.h
new file mode 100644
index 0000000..2908696
--- /dev/null
+++ b/include/compat/sha2.h
@@ -0,0 +1,100 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Derived from the public domain SHA-1 and SHA-2 implementations
+ * by Steve Reid and Wei Dai respectively.
+ */
+
+#ifndef COMPAT_SHA2_H
+#define COMPAT_SHA2_H
+
+#define SHA224_BLOCK_LENGTH 64
+#define SHA224_DIGEST_LENGTH 28
+#define SHA224_DIGEST_STRING_LENGTH (SHA224_DIGEST_LENGTH * 2 + 1)
+
+#define SHA256_BLOCK_LENGTH 64
+#define SHA256_DIGEST_LENGTH 32
+#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1)
+
+#define SHA384_BLOCK_LENGTH 128
+#define SHA384_DIGEST_LENGTH 48
+#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1)
+
+#define SHA512_BLOCK_LENGTH 128
+#define SHA512_DIGEST_LENGTH 64
+#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1)
+
+typedef struct {
+ union {
+ uint32_t st32[8]; /* sha224 and sha256 */
+ uint64_t st64[8]; /* sha384 and sha512 */
+ } state;
+ uint64_t count[2];
+ uint8_t buffer[SHA512_BLOCK_LENGTH];
+} SHA2_CTX;
+
+sudo_dso_public void sudo_SHA224Init(SHA2_CTX *ctx);
+sudo_dso_public void sudo_SHA224Pad(SHA2_CTX *ctx);
+sudo_dso_public void sudo_SHA224Transform(uint32_t state[8], const uint8_t buffer[SHA224_BLOCK_LENGTH]);
+sudo_dso_public void sudo_SHA224Update(SHA2_CTX *ctx, const uint8_t *data, size_t len);
+sudo_dso_public void sudo_SHA224Final(uint8_t digest[SHA224_DIGEST_LENGTH], SHA2_CTX *ctx);
+
+#define SHA224Init sudo_SHA224Init
+#define SHA224Pad sudo_SHA224Pad
+#define SHA224Transform sudo_SHA224Transform
+#define SHA224Update sudo_SHA224Update
+#define SHA224Final sudo_SHA224Final
+
+sudo_dso_public void sudo_SHA256Init(SHA2_CTX *ctx);
+sudo_dso_public void sudo_SHA256Pad(SHA2_CTX *ctx);
+sudo_dso_public void sudo_SHA256Transform(uint32_t state[8], const uint8_t buffer[SHA256_BLOCK_LENGTH]);
+sudo_dso_public void sudo_SHA256Update(SHA2_CTX *ctx, const uint8_t *data, size_t len);
+sudo_dso_public void sudo_SHA256Final(uint8_t digest[SHA256_DIGEST_LENGTH], SHA2_CTX *ctx);
+
+#define SHA256Init sudo_SHA256Init
+#define SHA256Pad sudo_SHA256Pad
+#define SHA256Transform sudo_SHA256Transform
+#define SHA256Update sudo_SHA256Update
+#define SHA256Final sudo_SHA256Final
+
+sudo_dso_public void sudo_SHA384Init(SHA2_CTX *ctx);
+sudo_dso_public void sudo_SHA384Pad(SHA2_CTX *ctx);
+sudo_dso_public void sudo_SHA384Transform(uint64_t state[8], const uint8_t buffer[SHA384_BLOCK_LENGTH]);
+sudo_dso_public void sudo_SHA384Update(SHA2_CTX *ctx, const uint8_t *data, size_t len);
+sudo_dso_public void sudo_SHA384Final(uint8_t digest[SHA384_DIGEST_LENGTH], SHA2_CTX *ctx);
+
+#define SHA384Init sudo_SHA384Init
+#define SHA384Pad sudo_SHA384Pad
+#define SHA384Transform sudo_SHA384Transform
+#define SHA384Update sudo_SHA384Update
+#define SHA384Final sudo_SHA384Final
+
+sudo_dso_public void sudo_SHA512Init(SHA2_CTX *ctx);
+sudo_dso_public void sudo_SHA512Pad(SHA2_CTX *ctx);
+sudo_dso_public void sudo_SHA512Transform(uint64_t state[8], const uint8_t buffer[SHA512_BLOCK_LENGTH]);
+sudo_dso_public void sudo_SHA512Update(SHA2_CTX *ctx, const uint8_t *data, size_t len);
+sudo_dso_public void sudo_SHA512Final(uint8_t digest[SHA512_DIGEST_LENGTH], SHA2_CTX *ctx);
+
+#define SHA512Init sudo_SHA512Init
+#define SHA512Pad sudo_SHA512Pad
+#define SHA512Transform sudo_SHA512Transform
+#define SHA512Update sudo_SHA512Update
+#define SHA512Final sudo_SHA512Final
+
+#endif /* COMPAT_SHA2_H */
diff --git a/include/compat/stdbool.h b/include/compat/stdbool.h
new file mode 100644
index 0000000..b865a46
--- /dev/null
+++ b/include/compat/stdbool.h
@@ -0,0 +1,44 @@
+/* $OpenBSD: stdbool.h,v 1.5 2010/07/24 22:17:03 guenther Exp $ */
+
+/*
+ * Written by Marc Espie, September 25, 1999
+ * Public domain.
+ */
+
+#ifndef COMPAT_STDBOOL_H
+#define COMPAT_STDBOOL_H
+
+#ifndef __cplusplus
+
+#if (defined(HAVE__BOOL) && HAVE__BOOL > 0) || defined(lint)
+/* Support for _C99: type _Bool is already built-in. */
+#define false 0
+#define true 1
+
+#else
+/* `_Bool' type must promote to `int' or `unsigned int'. */
+typedef enum {
+ false = 0,
+ true = 1
+} _Bool;
+
+/* And those constants must also be available as macros. */
+#define false false
+#define true true
+
+#endif
+
+/* User visible type `bool' is provided as a macro which may be redefined */
+#define bool _Bool
+
+#else /* __cplusplus */
+#define _Bool bool
+#define bool bool
+#define false false
+#define true true
+#endif /* __cplusplus */
+
+/* Inform that everything is fine */
+#define __bool_true_false_are_defined 1
+
+#endif /* COMPAT_STDBOOL_H */
diff --git a/include/hostcheck.h b/include/hostcheck.h
new file mode 100644
index 0000000..5c05d36
--- /dev/null
+++ b/include/hostcheck.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2020 Laszlo Orban <laszlo.orban@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_HOSTCHECK_H
+#define SUDO_HOSTCHECK_H
+
+#if defined(HAVE_OPENSSL)
+
+# include <openssl/x509v3.h>
+
+typedef enum {
+ MatchFound,
+ MatchNotFound,
+ NoSANPresent,
+ MalformedCertificate,
+ Error
+} HostnameValidationResult;
+
+HostnameValidationResult validate_hostname(const X509 *cert,
+ const char *hostname, const char *ipaddr, int resolve);
+
+#endif /* HAVE_OPENSSL */
+
+#endif /* SUDO_HOSTCHECK_H */
diff --git a/include/intercept.pb-c.h b/include/intercept.pb-c.h
new file mode 100644
index 0000000..2ea1683
--- /dev/null
+++ b/include/intercept.pb-c.h
@@ -0,0 +1,369 @@
+/* Generated by the protocol buffer compiler. DO NOT EDIT! */
+/* Generated from: intercept.proto */
+
+#ifndef PROTOBUF_C_intercept_2eproto__INCLUDED
+#define PROTOBUF_C_intercept_2eproto__INCLUDED
+
+#include <protobuf-c/protobuf-c.h>
+
+PROTOBUF_C__BEGIN_DECLS
+
+#if PROTOBUF_C_VERSION_NUMBER < 1003000
+# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers.
+#elif 1004000 < PROTOBUF_C_MIN_COMPILER_VERSION
+# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c.
+#endif
+
+
+typedef struct InterceptRequest InterceptRequest;
+typedef struct InterceptHello InterceptHello;
+typedef struct HelloResponse HelloResponse;
+typedef struct PolicyCheckRequest PolicyCheckRequest;
+typedef struct PolicyAcceptMessage PolicyAcceptMessage;
+typedef struct PolicyRejectMessage PolicyRejectMessage;
+typedef struct PolicyErrorMessage PolicyErrorMessage;
+typedef struct InterceptResponse InterceptResponse;
+
+
+/* --- enums --- */
+
+
+/* --- messages --- */
+
+typedef enum {
+ INTERCEPT_REQUEST__TYPE__NOT_SET = 0,
+ INTERCEPT_REQUEST__TYPE_POLICY_CHECK_REQ = 1,
+ INTERCEPT_REQUEST__TYPE_HELLO = 2
+ PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(INTERCEPT_REQUEST__TYPE__CASE)
+} InterceptRequest__TypeCase;
+
+/*
+ * Intercept message from sudo_intercept.so. Messages on the
+ * wire are prefixed with a 32-bit size in network byte order.
+ */
+struct InterceptRequest
+{
+ ProtobufCMessage base;
+ InterceptRequest__TypeCase type_case;
+ union {
+ PolicyCheckRequest *policy_check_req;
+ InterceptHello *hello;
+ } u;
+};
+#define INTERCEPT_REQUEST__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&intercept_request__descriptor) \
+ , INTERCEPT_REQUEST__TYPE__NOT_SET, {0} }
+
+
+/*
+ * Hello message from sudo_intercept.so to main sudo process.
+ * Sudo sends back the token and localhost port number.
+ */
+struct InterceptHello
+{
+ ProtobufCMessage base;
+ int32_t pid;
+};
+#define INTERCEPT_HELLO__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&intercept_hello__descriptor) \
+ , 0 }
+
+
+/*
+ * Sudo response to an InterceptHello from sudo_intercept.so.
+ * The client uses the port number and token to connect back to sudo.
+ * If log_only is set there is no InterceptResponse to a PolicyCheckRequest.
+ */
+struct HelloResponse
+{
+ ProtobufCMessage base;
+ uint64_t token_lo;
+ uint64_t token_hi;
+ int32_t portno;
+ protobuf_c_boolean log_only;
+};
+#define HELLO_RESPONSE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&hello_response__descriptor) \
+ , 0, 0, 0, 0 }
+
+
+/*
+ * Policy check request from sudo_intercept.so.
+ * Note that the plugin API only currently supports passing
+ * the new environment in to the open() function.
+ */
+struct PolicyCheckRequest
+{
+ ProtobufCMessage base;
+ char *command;
+ char *cwd;
+ size_t n_argv;
+ char **argv;
+ size_t n_envp;
+ char **envp;
+ int32_t intercept_fd;
+};
+#define POLICY_CHECK_REQUEST__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&policy_check_request__descriptor) \
+ , (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, 0,NULL, 0,NULL, 0 }
+
+
+struct PolicyAcceptMessage
+{
+ ProtobufCMessage base;
+ char *run_command;
+ size_t n_run_argv;
+ char **run_argv;
+ size_t n_run_envp;
+ char **run_envp;
+};
+#define POLICY_ACCEPT_MESSAGE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&policy_accept_message__descriptor) \
+ , (char *)protobuf_c_empty_string, 0,NULL, 0,NULL }
+
+
+struct PolicyRejectMessage
+{
+ ProtobufCMessage base;
+ char *reject_message;
+};
+#define POLICY_REJECT_MESSAGE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&policy_reject_message__descriptor) \
+ , (char *)protobuf_c_empty_string }
+
+
+struct PolicyErrorMessage
+{
+ ProtobufCMessage base;
+ char *error_message;
+};
+#define POLICY_ERROR_MESSAGE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&policy_error_message__descriptor) \
+ , (char *)protobuf_c_empty_string }
+
+
+typedef enum {
+ INTERCEPT_RESPONSE__TYPE__NOT_SET = 0,
+ INTERCEPT_RESPONSE__TYPE_HELLO_RESP = 1,
+ INTERCEPT_RESPONSE__TYPE_ACCEPT_MSG = 2,
+ INTERCEPT_RESPONSE__TYPE_REJECT_MSG = 3,
+ INTERCEPT_RESPONSE__TYPE_ERROR_MSG = 4
+ PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(INTERCEPT_RESPONSE__TYPE__CASE)
+} InterceptResponse__TypeCase;
+
+/*
+ * Response sent back to sudo_intercept.so.
+ */
+struct InterceptResponse
+{
+ ProtobufCMessage base;
+ InterceptResponse__TypeCase type_case;
+ union {
+ HelloResponse *hello_resp;
+ PolicyAcceptMessage *accept_msg;
+ PolicyRejectMessage *reject_msg;
+ PolicyErrorMessage *error_msg;
+ } u;
+};
+#define INTERCEPT_RESPONSE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&intercept_response__descriptor) \
+ , INTERCEPT_RESPONSE__TYPE__NOT_SET, {0} }
+
+
+/* InterceptRequest methods */
+void intercept_request__init
+ (InterceptRequest *message);
+size_t intercept_request__get_packed_size
+ (const InterceptRequest *message);
+size_t intercept_request__pack
+ (const InterceptRequest *message,
+ uint8_t *out);
+size_t intercept_request__pack_to_buffer
+ (const InterceptRequest *message,
+ ProtobufCBuffer *buffer);
+InterceptRequest *
+ intercept_request__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void intercept_request__free_unpacked
+ (InterceptRequest *message,
+ ProtobufCAllocator *allocator);
+/* InterceptHello methods */
+void intercept_hello__init
+ (InterceptHello *message);
+size_t intercept_hello__get_packed_size
+ (const InterceptHello *message);
+size_t intercept_hello__pack
+ (const InterceptHello *message,
+ uint8_t *out);
+size_t intercept_hello__pack_to_buffer
+ (const InterceptHello *message,
+ ProtobufCBuffer *buffer);
+InterceptHello *
+ intercept_hello__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void intercept_hello__free_unpacked
+ (InterceptHello *message,
+ ProtobufCAllocator *allocator);
+/* HelloResponse methods */
+void hello_response__init
+ (HelloResponse *message);
+size_t hello_response__get_packed_size
+ (const HelloResponse *message);
+size_t hello_response__pack
+ (const HelloResponse *message,
+ uint8_t *out);
+size_t hello_response__pack_to_buffer
+ (const HelloResponse *message,
+ ProtobufCBuffer *buffer);
+HelloResponse *
+ hello_response__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void hello_response__free_unpacked
+ (HelloResponse *message,
+ ProtobufCAllocator *allocator);
+/* PolicyCheckRequest methods */
+void policy_check_request__init
+ (PolicyCheckRequest *message);
+size_t policy_check_request__get_packed_size
+ (const PolicyCheckRequest *message);
+size_t policy_check_request__pack
+ (const PolicyCheckRequest *message,
+ uint8_t *out);
+size_t policy_check_request__pack_to_buffer
+ (const PolicyCheckRequest *message,
+ ProtobufCBuffer *buffer);
+PolicyCheckRequest *
+ policy_check_request__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void policy_check_request__free_unpacked
+ (PolicyCheckRequest *message,
+ ProtobufCAllocator *allocator);
+/* PolicyAcceptMessage methods */
+void policy_accept_message__init
+ (PolicyAcceptMessage *message);
+size_t policy_accept_message__get_packed_size
+ (const PolicyAcceptMessage *message);
+size_t policy_accept_message__pack
+ (const PolicyAcceptMessage *message,
+ uint8_t *out);
+size_t policy_accept_message__pack_to_buffer
+ (const PolicyAcceptMessage *message,
+ ProtobufCBuffer *buffer);
+PolicyAcceptMessage *
+ policy_accept_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void policy_accept_message__free_unpacked
+ (PolicyAcceptMessage *message,
+ ProtobufCAllocator *allocator);
+/* PolicyRejectMessage methods */
+void policy_reject_message__init
+ (PolicyRejectMessage *message);
+size_t policy_reject_message__get_packed_size
+ (const PolicyRejectMessage *message);
+size_t policy_reject_message__pack
+ (const PolicyRejectMessage *message,
+ uint8_t *out);
+size_t policy_reject_message__pack_to_buffer
+ (const PolicyRejectMessage *message,
+ ProtobufCBuffer *buffer);
+PolicyRejectMessage *
+ policy_reject_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void policy_reject_message__free_unpacked
+ (PolicyRejectMessage *message,
+ ProtobufCAllocator *allocator);
+/* PolicyErrorMessage methods */
+void policy_error_message__init
+ (PolicyErrorMessage *message);
+size_t policy_error_message__get_packed_size
+ (const PolicyErrorMessage *message);
+size_t policy_error_message__pack
+ (const PolicyErrorMessage *message,
+ uint8_t *out);
+size_t policy_error_message__pack_to_buffer
+ (const PolicyErrorMessage *message,
+ ProtobufCBuffer *buffer);
+PolicyErrorMessage *
+ policy_error_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void policy_error_message__free_unpacked
+ (PolicyErrorMessage *message,
+ ProtobufCAllocator *allocator);
+/* InterceptResponse methods */
+void intercept_response__init
+ (InterceptResponse *message);
+size_t intercept_response__get_packed_size
+ (const InterceptResponse *message);
+size_t intercept_response__pack
+ (const InterceptResponse *message,
+ uint8_t *out);
+size_t intercept_response__pack_to_buffer
+ (const InterceptResponse *message,
+ ProtobufCBuffer *buffer);
+InterceptResponse *
+ intercept_response__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void intercept_response__free_unpacked
+ (InterceptResponse *message,
+ ProtobufCAllocator *allocator);
+/* --- per-message closures --- */
+
+typedef void (*InterceptRequest_Closure)
+ (const InterceptRequest *message,
+ void *closure_data);
+typedef void (*InterceptHello_Closure)
+ (const InterceptHello *message,
+ void *closure_data);
+typedef void (*HelloResponse_Closure)
+ (const HelloResponse *message,
+ void *closure_data);
+typedef void (*PolicyCheckRequest_Closure)
+ (const PolicyCheckRequest *message,
+ void *closure_data);
+typedef void (*PolicyAcceptMessage_Closure)
+ (const PolicyAcceptMessage *message,
+ void *closure_data);
+typedef void (*PolicyRejectMessage_Closure)
+ (const PolicyRejectMessage *message,
+ void *closure_data);
+typedef void (*PolicyErrorMessage_Closure)
+ (const PolicyErrorMessage *message,
+ void *closure_data);
+typedef void (*InterceptResponse_Closure)
+ (const InterceptResponse *message,
+ void *closure_data);
+
+/* --- services --- */
+
+
+/* --- descriptors --- */
+
+extern const ProtobufCMessageDescriptor intercept_request__descriptor;
+extern const ProtobufCMessageDescriptor intercept_hello__descriptor;
+extern const ProtobufCMessageDescriptor hello_response__descriptor;
+extern const ProtobufCMessageDescriptor policy_check_request__descriptor;
+extern const ProtobufCMessageDescriptor policy_accept_message__descriptor;
+extern const ProtobufCMessageDescriptor policy_reject_message__descriptor;
+extern const ProtobufCMessageDescriptor policy_error_message__descriptor;
+extern const ProtobufCMessageDescriptor intercept_response__descriptor;
+
+PROTOBUF_C__END_DECLS
+
+
+#endif /* PROTOBUF_C_intercept_2eproto__INCLUDED */
diff --git a/include/log_server.pb-c.h b/include/log_server.pb-c.h
new file mode 100644
index 0000000..a7238c3
--- /dev/null
+++ b/include/log_server.pb-c.h
@@ -0,0 +1,790 @@
+/* Generated by the protocol buffer compiler. DO NOT EDIT! */
+/* Generated from: log_server.proto */
+
+#ifndef PROTOBUF_C_log_5fserver_2eproto__INCLUDED
+#define PROTOBUF_C_log_5fserver_2eproto__INCLUDED
+
+#include <protobuf-c/protobuf-c.h>
+
+PROTOBUF_C__BEGIN_DECLS
+
+#if PROTOBUF_C_VERSION_NUMBER < 1003000
+# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers.
+#elif 1004000 < PROTOBUF_C_MIN_COMPILER_VERSION
+# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c.
+#endif
+
+
+typedef struct ClientMessage ClientMessage;
+typedef struct TimeSpec TimeSpec;
+typedef struct IoBuffer IoBuffer;
+typedef struct InfoMessage InfoMessage;
+typedef struct InfoMessage__StringList InfoMessage__StringList;
+typedef struct InfoMessage__NumberList InfoMessage__NumberList;
+typedef struct AcceptMessage AcceptMessage;
+typedef struct RejectMessage RejectMessage;
+typedef struct ExitMessage ExitMessage;
+typedef struct AlertMessage AlertMessage;
+typedef struct RestartMessage RestartMessage;
+typedef struct ChangeWindowSize ChangeWindowSize;
+typedef struct CommandSuspend CommandSuspend;
+typedef struct ClientHello ClientHello;
+typedef struct ServerMessage ServerMessage;
+typedef struct ServerHello ServerHello;
+
+
+/* --- enums --- */
+
+
+/* --- messages --- */
+
+typedef enum {
+ CLIENT_MESSAGE__TYPE__NOT_SET = 0,
+ CLIENT_MESSAGE__TYPE_ACCEPT_MSG = 1,
+ CLIENT_MESSAGE__TYPE_REJECT_MSG = 2,
+ CLIENT_MESSAGE__TYPE_EXIT_MSG = 3,
+ CLIENT_MESSAGE__TYPE_RESTART_MSG = 4,
+ CLIENT_MESSAGE__TYPE_ALERT_MSG = 5,
+ CLIENT_MESSAGE__TYPE_TTYIN_BUF = 6,
+ CLIENT_MESSAGE__TYPE_TTYOUT_BUF = 7,
+ CLIENT_MESSAGE__TYPE_STDIN_BUF = 8,
+ CLIENT_MESSAGE__TYPE_STDOUT_BUF = 9,
+ CLIENT_MESSAGE__TYPE_STDERR_BUF = 10,
+ CLIENT_MESSAGE__TYPE_WINSIZE_EVENT = 11,
+ CLIENT_MESSAGE__TYPE_SUSPEND_EVENT = 12,
+ CLIENT_MESSAGE__TYPE_HELLO_MSG = 13
+ PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(CLIENT_MESSAGE__TYPE__CASE)
+} ClientMessage__TypeCase;
+
+/*
+ * Client message to the server. Messages on the wire are
+ * prefixed with a 32-bit size in network byte order.
+ */
+struct ClientMessage
+{
+ ProtobufCMessage base;
+ ClientMessage__TypeCase type_case;
+ union {
+ AcceptMessage *accept_msg;
+ RejectMessage *reject_msg;
+ ExitMessage *exit_msg;
+ RestartMessage *restart_msg;
+ AlertMessage *alert_msg;
+ IoBuffer *ttyin_buf;
+ IoBuffer *ttyout_buf;
+ IoBuffer *stdin_buf;
+ IoBuffer *stdout_buf;
+ IoBuffer *stderr_buf;
+ ChangeWindowSize *winsize_event;
+ CommandSuspend *suspend_event;
+ ClientHello *hello_msg;
+ } u;
+};
+#define CLIENT_MESSAGE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&client_message__descriptor) \
+ , CLIENT_MESSAGE__TYPE__NOT_SET, {0} }
+
+
+/*
+ * Equivalent of POSIX struct timespec
+ */
+struct TimeSpec
+{
+ ProtobufCMessage base;
+ /*
+ * seconds
+ */
+ int64_t tv_sec;
+ /*
+ * nanoseconds
+ */
+ int32_t tv_nsec;
+};
+#define TIME_SPEC__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&time_spec__descriptor) \
+ , 0, 0 }
+
+
+/*
+ * I/O buffer with keystroke data
+ */
+struct IoBuffer
+{
+ ProtobufCMessage base;
+ /*
+ * elapsed time since last record
+ */
+ TimeSpec *delay;
+ /*
+ * keystroke data
+ */
+ ProtobufCBinaryData data;
+};
+#define IO_BUFFER__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&io_buffer__descriptor) \
+ , NULL, {0,NULL} }
+
+
+struct InfoMessage__StringList
+{
+ ProtobufCMessage base;
+ size_t n_strings;
+ char **strings;
+};
+#define INFO_MESSAGE__STRING_LIST__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&info_message__string_list__descriptor) \
+ , 0,NULL }
+
+
+struct InfoMessage__NumberList
+{
+ ProtobufCMessage base;
+ size_t n_numbers;
+ int64_t *numbers;
+};
+#define INFO_MESSAGE__NUMBER_LIST__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&info_message__number_list__descriptor) \
+ , 0,NULL }
+
+
+typedef enum {
+ INFO_MESSAGE__VALUE__NOT_SET = 0,
+ INFO_MESSAGE__VALUE_NUMVAL = 2,
+ INFO_MESSAGE__VALUE_STRVAL = 3,
+ INFO_MESSAGE__VALUE_STRLISTVAL = 4,
+ INFO_MESSAGE__VALUE_NUMLISTVAL = 5
+ PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(INFO_MESSAGE__VALUE__CASE)
+} InfoMessage__ValueCase;
+
+/*
+ * Key/value pairs, like Privilege Manager struct info.
+ * The value may be a number, a string, or a list of strings.
+ */
+struct InfoMessage
+{
+ ProtobufCMessage base;
+ char *key;
+ InfoMessage__ValueCase value_case;
+ union {
+ int64_t numval;
+ char *strval;
+ InfoMessage__StringList *strlistval;
+ InfoMessage__NumberList *numlistval;
+ } u;
+};
+#define INFO_MESSAGE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&info_message__descriptor) \
+ , (char *)protobuf_c_empty_string, INFO_MESSAGE__VALUE__NOT_SET, {0} }
+
+
+/*
+ * Event log data for command accepted by the policy.
+ */
+struct AcceptMessage
+{
+ ProtobufCMessage base;
+ /*
+ * when command was submitted
+ */
+ TimeSpec *submit_time;
+ /*
+ * key,value event log data
+ */
+ size_t n_info_msgs;
+ InfoMessage **info_msgs;
+ /*
+ * true if I/O logging enabled
+ */
+ protobuf_c_boolean expect_iobufs;
+};
+#define ACCEPT_MESSAGE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&accept_message__descriptor) \
+ , NULL, 0,NULL, 0 }
+
+
+/*
+ * Event log data for command rejected by the policy.
+ */
+struct RejectMessage
+{
+ ProtobufCMessage base;
+ /*
+ * when command was submitted
+ */
+ TimeSpec *submit_time;
+ /*
+ * reason command was rejected
+ */
+ char *reason;
+ /*
+ * key,value event log data
+ */
+ size_t n_info_msgs;
+ InfoMessage **info_msgs;
+};
+#define REJECT_MESSAGE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&reject_message__descriptor) \
+ , NULL, (char *)protobuf_c_empty_string, 0,NULL }
+
+
+/*
+ * Might revisit runtime and use end_time instead
+ */
+struct ExitMessage
+{
+ ProtobufCMessage base;
+ /*
+ * total elapsed run time
+ */
+ TimeSpec *run_time;
+ /*
+ * 0-255
+ */
+ int32_t exit_value;
+ /*
+ * true if command dumped core
+ */
+ protobuf_c_boolean dumped_core;
+ /*
+ * signal name if killed by signal
+ */
+ char *signal;
+ /*
+ * if killed due to other error
+ */
+ char *error;
+};
+#define EXIT_MESSAGE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&exit_message__descriptor) \
+ , NULL, 0, 0, (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string }
+
+
+/*
+ * Alert message, policy module-specific.
+ */
+struct AlertMessage
+{
+ ProtobufCMessage base;
+ /*
+ * time alert message occurred
+ */
+ TimeSpec *alert_time;
+ /*
+ * policy alert error string
+ */
+ char *reason;
+ /*
+ * optional key,value event log data
+ */
+ size_t n_info_msgs;
+ InfoMessage **info_msgs;
+};
+#define ALERT_MESSAGE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&alert_message__descriptor) \
+ , NULL, (char *)protobuf_c_empty_string, 0,NULL }
+
+
+/*
+ * Used to restart an existing I/O log on the server.
+ */
+struct RestartMessage
+{
+ ProtobufCMessage base;
+ /*
+ * ID of log being restarted
+ */
+ char *log_id;
+ /*
+ * resume point (elapsed time)
+ */
+ TimeSpec *resume_point;
+};
+#define RESTART_MESSAGE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&restart_message__descriptor) \
+ , (char *)protobuf_c_empty_string, NULL }
+
+
+/*
+ * Window size change event.
+ */
+struct ChangeWindowSize
+{
+ ProtobufCMessage base;
+ /*
+ * elapsed time since last record
+ */
+ TimeSpec *delay;
+ /*
+ * new number of rows
+ */
+ int32_t rows;
+ /*
+ * new number of columns
+ */
+ int32_t cols;
+};
+#define CHANGE_WINDOW_SIZE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&change_window_size__descriptor) \
+ , NULL, 0, 0 }
+
+
+/*
+ * Command suspend/resume event.
+ */
+struct CommandSuspend
+{
+ ProtobufCMessage base;
+ /*
+ * elapsed time since last record
+ */
+ TimeSpec *delay;
+ /*
+ * signal that caused suspend/resume
+ */
+ char *signal;
+};
+#define COMMAND_SUSPEND__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&command_suspend__descriptor) \
+ , NULL, (char *)protobuf_c_empty_string }
+
+
+/*
+ * Hello message from client when connecting to server.
+ */
+struct ClientHello
+{
+ ProtobufCMessage base;
+ /*
+ * free-form client description
+ */
+ char *client_id;
+};
+#define CLIENT_HELLO__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&client_hello__descriptor) \
+ , (char *)protobuf_c_empty_string }
+
+
+typedef enum {
+ SERVER_MESSAGE__TYPE__NOT_SET = 0,
+ SERVER_MESSAGE__TYPE_HELLO = 1,
+ SERVER_MESSAGE__TYPE_COMMIT_POINT = 2,
+ SERVER_MESSAGE__TYPE_LOG_ID = 3,
+ SERVER_MESSAGE__TYPE_ERROR = 4,
+ SERVER_MESSAGE__TYPE_ABORT = 5
+ PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(SERVER_MESSAGE__TYPE__CASE)
+} ServerMessage__TypeCase;
+
+/*
+ * Server messages to the client. Messages on the wire are
+ * prefixed with a 32-bit size in network byte order.
+ */
+struct ServerMessage
+{
+ ProtobufCMessage base;
+ ServerMessage__TypeCase type_case;
+ union {
+ /*
+ * server hello message
+ */
+ ServerHello *hello;
+ /*
+ * cumulative time of records stored
+ */
+ TimeSpec *commit_point;
+ /*
+ * ID of server-side I/O log
+ */
+ char *log_id;
+ /*
+ * error message from server
+ */
+ char *error;
+ /*
+ * abort message, kill command
+ */
+ char *abort;
+ } u;
+};
+#define SERVER_MESSAGE__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&server_message__descriptor) \
+ , SERVER_MESSAGE__TYPE__NOT_SET, {0} }
+
+
+/*
+ * Hello message from server when client connects.
+ */
+struct ServerHello
+{
+ ProtobufCMessage base;
+ /*
+ * free-form server description
+ */
+ char *server_id;
+ /*
+ * optional redirect if busy
+ */
+ char *redirect;
+ /*
+ * optional list of known servers
+ */
+ size_t n_servers;
+ char **servers;
+ /*
+ * flag: server supports sub-commands
+ */
+ protobuf_c_boolean subcommands;
+};
+#define SERVER_HELLO__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&server_hello__descriptor) \
+ , (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, 0,NULL, 0 }
+
+
+/* ClientMessage methods */
+void client_message__init
+ (ClientMessage *message);
+size_t client_message__get_packed_size
+ (const ClientMessage *message);
+size_t client_message__pack
+ (const ClientMessage *message,
+ uint8_t *out);
+size_t client_message__pack_to_buffer
+ (const ClientMessage *message,
+ ProtobufCBuffer *buffer);
+ClientMessage *
+ client_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void client_message__free_unpacked
+ (ClientMessage *message,
+ ProtobufCAllocator *allocator);
+/* TimeSpec methods */
+void time_spec__init
+ (TimeSpec *message);
+size_t time_spec__get_packed_size
+ (const TimeSpec *message);
+size_t time_spec__pack
+ (const TimeSpec *message,
+ uint8_t *out);
+size_t time_spec__pack_to_buffer
+ (const TimeSpec *message,
+ ProtobufCBuffer *buffer);
+TimeSpec *
+ time_spec__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void time_spec__free_unpacked
+ (TimeSpec *message,
+ ProtobufCAllocator *allocator);
+/* IoBuffer methods */
+void io_buffer__init
+ (IoBuffer *message);
+size_t io_buffer__get_packed_size
+ (const IoBuffer *message);
+size_t io_buffer__pack
+ (const IoBuffer *message,
+ uint8_t *out);
+size_t io_buffer__pack_to_buffer
+ (const IoBuffer *message,
+ ProtobufCBuffer *buffer);
+IoBuffer *
+ io_buffer__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void io_buffer__free_unpacked
+ (IoBuffer *message,
+ ProtobufCAllocator *allocator);
+/* InfoMessage__StringList methods */
+void info_message__string_list__init
+ (InfoMessage__StringList *message);
+/* InfoMessage__NumberList methods */
+void info_message__number_list__init
+ (InfoMessage__NumberList *message);
+/* InfoMessage methods */
+void info_message__init
+ (InfoMessage *message);
+size_t info_message__get_packed_size
+ (const InfoMessage *message);
+size_t info_message__pack
+ (const InfoMessage *message,
+ uint8_t *out);
+size_t info_message__pack_to_buffer
+ (const InfoMessage *message,
+ ProtobufCBuffer *buffer);
+InfoMessage *
+ info_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void info_message__free_unpacked
+ (InfoMessage *message,
+ ProtobufCAllocator *allocator);
+/* AcceptMessage methods */
+void accept_message__init
+ (AcceptMessage *message);
+size_t accept_message__get_packed_size
+ (const AcceptMessage *message);
+size_t accept_message__pack
+ (const AcceptMessage *message,
+ uint8_t *out);
+size_t accept_message__pack_to_buffer
+ (const AcceptMessage *message,
+ ProtobufCBuffer *buffer);
+AcceptMessage *
+ accept_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void accept_message__free_unpacked
+ (AcceptMessage *message,
+ ProtobufCAllocator *allocator);
+/* RejectMessage methods */
+void reject_message__init
+ (RejectMessage *message);
+size_t reject_message__get_packed_size
+ (const RejectMessage *message);
+size_t reject_message__pack
+ (const RejectMessage *message,
+ uint8_t *out);
+size_t reject_message__pack_to_buffer
+ (const RejectMessage *message,
+ ProtobufCBuffer *buffer);
+RejectMessage *
+ reject_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void reject_message__free_unpacked
+ (RejectMessage *message,
+ ProtobufCAllocator *allocator);
+/* ExitMessage methods */
+void exit_message__init
+ (ExitMessage *message);
+size_t exit_message__get_packed_size
+ (const ExitMessage *message);
+size_t exit_message__pack
+ (const ExitMessage *message,
+ uint8_t *out);
+size_t exit_message__pack_to_buffer
+ (const ExitMessage *message,
+ ProtobufCBuffer *buffer);
+ExitMessage *
+ exit_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void exit_message__free_unpacked
+ (ExitMessage *message,
+ ProtobufCAllocator *allocator);
+/* AlertMessage methods */
+void alert_message__init
+ (AlertMessage *message);
+size_t alert_message__get_packed_size
+ (const AlertMessage *message);
+size_t alert_message__pack
+ (const AlertMessage *message,
+ uint8_t *out);
+size_t alert_message__pack_to_buffer
+ (const AlertMessage *message,
+ ProtobufCBuffer *buffer);
+AlertMessage *
+ alert_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void alert_message__free_unpacked
+ (AlertMessage *message,
+ ProtobufCAllocator *allocator);
+/* RestartMessage methods */
+void restart_message__init
+ (RestartMessage *message);
+size_t restart_message__get_packed_size
+ (const RestartMessage *message);
+size_t restart_message__pack
+ (const RestartMessage *message,
+ uint8_t *out);
+size_t restart_message__pack_to_buffer
+ (const RestartMessage *message,
+ ProtobufCBuffer *buffer);
+RestartMessage *
+ restart_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void restart_message__free_unpacked
+ (RestartMessage *message,
+ ProtobufCAllocator *allocator);
+/* ChangeWindowSize methods */
+void change_window_size__init
+ (ChangeWindowSize *message);
+size_t change_window_size__get_packed_size
+ (const ChangeWindowSize *message);
+size_t change_window_size__pack
+ (const ChangeWindowSize *message,
+ uint8_t *out);
+size_t change_window_size__pack_to_buffer
+ (const ChangeWindowSize *message,
+ ProtobufCBuffer *buffer);
+ChangeWindowSize *
+ change_window_size__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void change_window_size__free_unpacked
+ (ChangeWindowSize *message,
+ ProtobufCAllocator *allocator);
+/* CommandSuspend methods */
+void command_suspend__init
+ (CommandSuspend *message);
+size_t command_suspend__get_packed_size
+ (const CommandSuspend *message);
+size_t command_suspend__pack
+ (const CommandSuspend *message,
+ uint8_t *out);
+size_t command_suspend__pack_to_buffer
+ (const CommandSuspend *message,
+ ProtobufCBuffer *buffer);
+CommandSuspend *
+ command_suspend__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void command_suspend__free_unpacked
+ (CommandSuspend *message,
+ ProtobufCAllocator *allocator);
+/* ClientHello methods */
+void client_hello__init
+ (ClientHello *message);
+size_t client_hello__get_packed_size
+ (const ClientHello *message);
+size_t client_hello__pack
+ (const ClientHello *message,
+ uint8_t *out);
+size_t client_hello__pack_to_buffer
+ (const ClientHello *message,
+ ProtobufCBuffer *buffer);
+ClientHello *
+ client_hello__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void client_hello__free_unpacked
+ (ClientHello *message,
+ ProtobufCAllocator *allocator);
+/* ServerMessage methods */
+void server_message__init
+ (ServerMessage *message);
+size_t server_message__get_packed_size
+ (const ServerMessage *message);
+size_t server_message__pack
+ (const ServerMessage *message,
+ uint8_t *out);
+size_t server_message__pack_to_buffer
+ (const ServerMessage *message,
+ ProtobufCBuffer *buffer);
+ServerMessage *
+ server_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void server_message__free_unpacked
+ (ServerMessage *message,
+ ProtobufCAllocator *allocator);
+/* ServerHello methods */
+void server_hello__init
+ (ServerHello *message);
+size_t server_hello__get_packed_size
+ (const ServerHello *message);
+size_t server_hello__pack
+ (const ServerHello *message,
+ uint8_t *out);
+size_t server_hello__pack_to_buffer
+ (const ServerHello *message,
+ ProtobufCBuffer *buffer);
+ServerHello *
+ server_hello__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+void server_hello__free_unpacked
+ (ServerHello *message,
+ ProtobufCAllocator *allocator);
+/* --- per-message closures --- */
+
+typedef void (*ClientMessage_Closure)
+ (const ClientMessage *message,
+ void *closure_data);
+typedef void (*TimeSpec_Closure)
+ (const TimeSpec *message,
+ void *closure_data);
+typedef void (*IoBuffer_Closure)
+ (const IoBuffer *message,
+ void *closure_data);
+typedef void (*InfoMessage__StringList_Closure)
+ (const InfoMessage__StringList *message,
+ void *closure_data);
+typedef void (*InfoMessage__NumberList_Closure)
+ (const InfoMessage__NumberList *message,
+ void *closure_data);
+typedef void (*InfoMessage_Closure)
+ (const InfoMessage *message,
+ void *closure_data);
+typedef void (*AcceptMessage_Closure)
+ (const AcceptMessage *message,
+ void *closure_data);
+typedef void (*RejectMessage_Closure)
+ (const RejectMessage *message,
+ void *closure_data);
+typedef void (*ExitMessage_Closure)
+ (const ExitMessage *message,
+ void *closure_data);
+typedef void (*AlertMessage_Closure)
+ (const AlertMessage *message,
+ void *closure_data);
+typedef void (*RestartMessage_Closure)
+ (const RestartMessage *message,
+ void *closure_data);
+typedef void (*ChangeWindowSize_Closure)
+ (const ChangeWindowSize *message,
+ void *closure_data);
+typedef void (*CommandSuspend_Closure)
+ (const CommandSuspend *message,
+ void *closure_data);
+typedef void (*ClientHello_Closure)
+ (const ClientHello *message,
+ void *closure_data);
+typedef void (*ServerMessage_Closure)
+ (const ServerMessage *message,
+ void *closure_data);
+typedef void (*ServerHello_Closure)
+ (const ServerHello *message,
+ void *closure_data);
+
+/* --- services --- */
+
+
+/* --- descriptors --- */
+
+extern const ProtobufCMessageDescriptor client_message__descriptor;
+extern const ProtobufCMessageDescriptor time_spec__descriptor;
+extern const ProtobufCMessageDescriptor io_buffer__descriptor;
+extern const ProtobufCMessageDescriptor info_message__descriptor;
+extern const ProtobufCMessageDescriptor info_message__string_list__descriptor;
+extern const ProtobufCMessageDescriptor info_message__number_list__descriptor;
+extern const ProtobufCMessageDescriptor accept_message__descriptor;
+extern const ProtobufCMessageDescriptor reject_message__descriptor;
+extern const ProtobufCMessageDescriptor exit_message__descriptor;
+extern const ProtobufCMessageDescriptor alert_message__descriptor;
+extern const ProtobufCMessageDescriptor restart_message__descriptor;
+extern const ProtobufCMessageDescriptor change_window_size__descriptor;
+extern const ProtobufCMessageDescriptor command_suspend__descriptor;
+extern const ProtobufCMessageDescriptor client_hello__descriptor;
+extern const ProtobufCMessageDescriptor server_message__descriptor;
+extern const ProtobufCMessageDescriptor server_hello__descriptor;
+
+PROTOBUF_C__END_DECLS
+
+
+#endif /* PROTOBUF_C_log_5fserver_2eproto__INCLUDED */
diff --git a/include/protobuf-c/protobuf-c.h b/include/protobuf-c/protobuf-c.h
new file mode 100644
index 0000000..442abf6
--- /dev/null
+++ b/include/protobuf-c/protobuf-c.h
@@ -0,0 +1,1110 @@
+/*
+ * Copyright (c) 2008-2022, Dave Benson and the protobuf-c authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*! \file
+ * \mainpage Introduction
+ *
+ * This is [protobuf-c], a C implementation of [Protocol Buffers].
+ *
+ * This file defines the public API for the `libprotobuf-c` support library.
+ * This API includes interfaces that can be used directly by client code as well
+ * as the interfaces used by the code generated by the `protoc-c` compiler.
+ *
+ * The `libprotobuf-c` support library performs the actual serialization and
+ * deserialization of Protocol Buffers messages. It interacts with structures,
+ * definitions, and metadata generated by the `protoc-c` compiler from .proto
+ * files.
+ *
+ * \authors Dave Benson and the `protobuf-c` authors.
+ *
+ * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license.
+ *
+ * [protobuf-c]: https://github.com/protobuf-c/protobuf-c
+ * [Protocol Buffers]: https://developers.google.com/protocol-buffers/
+ * [BSD-2-Clause]: http://opensource.org/licenses/BSD-2-Clause
+ *
+ * \page gencode Generated Code
+ *
+ * For each enum, we generate a C enum. For each message, we generate a C
+ * structure which can be cast to a `ProtobufCMessage`.
+ *
+ * For each enum and message, we generate a descriptor object that allows us to
+ * implement a kind of reflection on the structures.
+ *
+ * First, some naming conventions:
+ *
+ * - The name of the type for enums and messages and services is camel case
+ * (meaning WordsAreCrammedTogether) except that double underscores are used
+ * to delimit scopes. For example, the following `.proto` file:
+ *
+~~~{.proto}
+ package foo.bar;
+ message BazBah {
+ optional int32 val = 1;
+ }
+~~~
+ *
+ * would generate a C type `Foo__Bar__BazBah`.
+ *
+ * - Identifiers for functions and globals are all lowercase, with camel case
+ * words separated by single underscores. For example, one of the function
+ * prototypes generated by `protoc-c` for the above example:
+ *
+~~~{.c}
+Foo__Bar__BazBah *
+ foo__bar__baz_bah__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+~~~
+ *
+ * - Identifiers for enum values contain an uppercase prefix which embeds the
+ * package name and the enum type name.
+ *
+ * - A double underscore is used to separate further components of identifier
+ * names.
+ *
+ * For example, in the name of the unpack function above, the package name
+ * `foo.bar` has become `foo__bar`, the message name BazBah has become
+ * `baz_bah`, and the method name is `unpack`. These are all joined with double
+ * underscores to form the C identifier `foo__bar__baz_bah__unpack`.
+ *
+ * We also generate descriptor objects for messages and enums. These are
+ * declared in the `.pb-c.h` files:
+ *
+~~~{.c}
+extern const ProtobufCMessageDescriptor foo__bar__baz_bah__descriptor;
+~~~
+ *
+ * The message structures all begin with `ProtobufCMessageDescriptor *` which is
+ * sufficient to allow them to be cast to `ProtobufCMessage`.
+ *
+ * For each message defined in a `.proto` file, we generate a number of
+ * functions and macros. Each function name contains a prefix based on the
+ * package name and message name in order to make it a unique C identifier.
+ *
+ * - `INIT`. Statically initializes a message object, initializing its
+ * descriptor and setting its fields to default values. Uninitialized
+ * messages cannot be processed by the protobuf-c library.
+ *
+~~~{.c}
+#define FOO__BAR__BAZ_BAH__INIT \
+ { PROTOBUF_C_MESSAGE_INIT (&foo__bar__baz_bah__descriptor), 0 }
+~~~
+ * - `init()`. Initializes a message object, initializing its descriptor and
+ * setting its fields to default values. Uninitialized messages cannot be
+ * processed by the protobuf-c library.
+ *
+~~~{.c}
+void foo__bar__baz_bah__init
+ (Foo__Bar__BazBah *message);
+~~~
+ * - `unpack()`. Unpacks data for a particular message format. Note that the
+ * `allocator` parameter is usually `NULL` to indicate that the system's
+ * `malloc()` and `free()` functions should be used for dynamically allocating
+ * memory.
+ *
+~~~{.c}
+Foo__Bar__BazBah *
+ foo__bar__baz_bah__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+~~~
+ *
+ * - `free_unpacked()`. Frees a message object obtained with the `unpack()`
+ * method. Freeing `NULL` is allowed (the same as with `free()`).
+ *
+~~~{.c}
+void foo__bar__baz_bah__free_unpacked
+ (Foo__Bar__BazBah *message,
+ ProtobufCAllocator *allocator);
+~~~
+ *
+ * - `get_packed_size()`. Calculates the length in bytes of the serialized
+ * representation of the message object.
+ *
+~~~{.c}
+size_t foo__bar__baz_bah__get_packed_size
+ (const Foo__Bar__BazBah *message);
+~~~
+ *
+ * - `pack()`. Pack a message object into a preallocated buffer. Assumes that
+ * the buffer is large enough. (Use `get_packed_size()` first.)
+ *
+~~~{.c}
+size_t foo__bar__baz_bah__pack
+ (const Foo__Bar__BazBah *message,
+ uint8_t *out);
+~~~
+ *
+ * - `pack_to_buffer()`. Packs a message into a "virtual buffer". This is an
+ * object which defines an "append bytes" callback to consume data as it is
+ * serialized.
+ *
+~~~{.c}
+size_t foo__bar__baz_bah__pack_to_buffer
+ (const Foo__Bar__BazBah *message,
+ ProtobufCBuffer *buffer);
+~~~
+ *
+ * \page pack Packing and unpacking messages
+ *
+ * To pack a message, first compute the packed size of the message with
+ * protobuf_c_message_get_packed_size(), then allocate a buffer of at least
+ * that size, then call protobuf_c_message_pack().
+ *
+ * Alternatively, a message can be serialized without calculating the final size
+ * first. Use the protobuf_c_message_pack_to_buffer() function and provide a
+ * ProtobufCBuffer object which implements an "append" method that consumes
+ * data.
+ *
+ * To unpack a message, call the protobuf_c_message_unpack() function. The
+ * result can be cast to an object of the type that matches the descriptor for
+ * the message.
+ *
+ * The result of unpacking a message should be freed with
+ * protobuf_c_message_free_unpacked().
+ */
+
+#ifndef PROTOBUF_C_H
+#define PROTOBUF_C_H
+
+#include <assert.h>
+#include <limits.h>
+#include <stddef.h>
+#include <inttypes.h> /* stdint.h not present on older systems */
+
+#ifdef __cplusplus
+# define PROTOBUF_C__BEGIN_DECLS extern "C" {
+# define PROTOBUF_C__END_DECLS }
+#else
+# define PROTOBUF_C__BEGIN_DECLS
+# define PROTOBUF_C__END_DECLS
+#endif
+
+PROTOBUF_C__BEGIN_DECLS
+
+#if defined(_WIN32) && defined(PROTOBUF_C_USE_SHARED_LIB)
+# ifdef PROTOBUF_C_EXPORT
+# define PROTOBUF_C__API __declspec(dllexport)
+# else
+# define PROTOBUF_C__API __declspec(dllimport)
+# endif
+#else
+# define PROTOBUF_C__API
+#endif
+
+#if !defined(PROTOBUF_C__NO_DEPRECATED) && \
+ ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+# define PROTOBUF_C__DEPRECATED __attribute__((__deprecated__))
+#else
+# define PROTOBUF_C__DEPRECATED
+#endif
+
+#ifndef PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE
+ #define PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(enum_name) \
+ , _##enum_name##_IS_INT_SIZE = INT_MAX
+#endif
+
+#define PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC 0x14159bc3
+#define PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC 0x28aaeef9
+#define PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC 0x114315af
+
+/* Empty string used for initializers */
+#if defined(_WIN32) && defined(PROTOBUF_C_USE_SHARED_LIB)
+static const char protobuf_c_empty_string[] = "";
+#else
+extern const char protobuf_c_empty_string[];
+#endif
+
+/**
+ * \defgroup api Public API
+ *
+ * This is the public API for `libprotobuf-c`. These interfaces are stable and
+ * subject to Semantic Versioning guarantees.
+ *
+ * @{
+ */
+
+/**
+ * Values for the `flags` word in `ProtobufCFieldDescriptor`.
+ */
+typedef enum {
+ /** Set if the field is repeated and marked with the `packed` option. */
+ PROTOBUF_C_FIELD_FLAG_PACKED = (1 << 0),
+
+ /** Set if the field is marked with the `deprecated` option. */
+ PROTOBUF_C_FIELD_FLAG_DEPRECATED = (1 << 1),
+
+ /** Set if the field is a member of a oneof (union). */
+ PROTOBUF_C_FIELD_FLAG_ONEOF = (1 << 2),
+} ProtobufCFieldFlag;
+
+/**
+ * Message field rules.
+ *
+ * \see [Defining A Message Type] in the Protocol Buffers documentation.
+ *
+ * [Defining A Message Type]:
+ * https://developers.google.com/protocol-buffers/docs/proto#simple
+ */
+typedef enum {
+ /** A well-formed message must have exactly one of this field. */
+ PROTOBUF_C_LABEL_REQUIRED,
+
+ /**
+ * A well-formed message can have zero or one of this field (but not
+ * more than one).
+ */
+ PROTOBUF_C_LABEL_OPTIONAL,
+
+ /**
+ * This field can be repeated any number of times (including zero) in a
+ * well-formed message. The order of the repeated values will be
+ * preserved.
+ */
+ PROTOBUF_C_LABEL_REPEATED,
+
+ /**
+ * This field has no label. This is valid only in proto3 and is
+ * equivalent to OPTIONAL but no "has" quantifier will be consulted.
+ */
+ PROTOBUF_C_LABEL_NONE,
+} ProtobufCLabel;
+
+/**
+ * Field value types.
+ *
+ * \see [Scalar Value Types] in the Protocol Buffers documentation.
+ *
+ * [Scalar Value Types]:
+ * https://developers.google.com/protocol-buffers/docs/proto#scalar
+ */
+typedef enum {
+ PROTOBUF_C_TYPE_INT32, /**< int32 */
+ PROTOBUF_C_TYPE_SINT32, /**< signed int32 */
+ PROTOBUF_C_TYPE_SFIXED32, /**< signed int32 (4 bytes) */
+ PROTOBUF_C_TYPE_INT64, /**< int64 */
+ PROTOBUF_C_TYPE_SINT64, /**< signed int64 */
+ PROTOBUF_C_TYPE_SFIXED64, /**< signed int64 (8 bytes) */
+ PROTOBUF_C_TYPE_UINT32, /**< unsigned int32 */
+ PROTOBUF_C_TYPE_FIXED32, /**< unsigned int32 (4 bytes) */
+ PROTOBUF_C_TYPE_UINT64, /**< unsigned int64 */
+ PROTOBUF_C_TYPE_FIXED64, /**< unsigned int64 (8 bytes) */
+ PROTOBUF_C_TYPE_FLOAT, /**< float */
+ PROTOBUF_C_TYPE_DOUBLE, /**< double */
+ PROTOBUF_C_TYPE_BOOL, /**< boolean */
+ PROTOBUF_C_TYPE_ENUM, /**< enumerated type */
+ PROTOBUF_C_TYPE_STRING, /**< UTF-8 or ASCII string */
+ PROTOBUF_C_TYPE_BYTES, /**< arbitrary byte sequence */
+ PROTOBUF_C_TYPE_MESSAGE, /**< nested message */
+} ProtobufCType;
+
+/**
+ * Field wire types.
+ *
+ * \see [Message Structure] in the Protocol Buffers documentation.
+ *
+ * [Message Structure]:
+ * https://developers.google.com/protocol-buffers/docs/encoding#structure
+ */
+typedef enum {
+ PROTOBUF_C_WIRE_TYPE_VARINT = 0,
+ PROTOBUF_C_WIRE_TYPE_64BIT = 1,
+ PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED = 2,
+ /* "Start group" and "end group" wire types are unsupported. */
+ PROTOBUF_C_WIRE_TYPE_32BIT = 5,
+} ProtobufCWireType;
+
+struct ProtobufCAllocator;
+struct ProtobufCBinaryData;
+struct ProtobufCBuffer;
+struct ProtobufCBufferSimple;
+struct ProtobufCEnumDescriptor;
+struct ProtobufCEnumValue;
+struct ProtobufCEnumValueIndex;
+struct ProtobufCFieldDescriptor;
+struct ProtobufCIntRange;
+struct ProtobufCMessage;
+struct ProtobufCMessageDescriptor;
+struct ProtobufCMessageUnknownField;
+struct ProtobufCMethodDescriptor;
+struct ProtobufCService;
+struct ProtobufCServiceDescriptor;
+
+typedef struct ProtobufCAllocator ProtobufCAllocator;
+typedef struct ProtobufCBinaryData ProtobufCBinaryData;
+typedef struct ProtobufCBuffer ProtobufCBuffer;
+typedef struct ProtobufCBufferSimple ProtobufCBufferSimple;
+typedef struct ProtobufCEnumDescriptor ProtobufCEnumDescriptor;
+typedef struct ProtobufCEnumValue ProtobufCEnumValue;
+typedef struct ProtobufCEnumValueIndex ProtobufCEnumValueIndex;
+typedef struct ProtobufCFieldDescriptor ProtobufCFieldDescriptor;
+typedef struct ProtobufCIntRange ProtobufCIntRange;
+typedef struct ProtobufCMessage ProtobufCMessage;
+typedef struct ProtobufCMessageDescriptor ProtobufCMessageDescriptor;
+typedef struct ProtobufCMessageUnknownField ProtobufCMessageUnknownField;
+typedef struct ProtobufCMethodDescriptor ProtobufCMethodDescriptor;
+typedef struct ProtobufCService ProtobufCService;
+typedef struct ProtobufCServiceDescriptor ProtobufCServiceDescriptor;
+
+/** Boolean type. */
+typedef int protobuf_c_boolean;
+
+typedef void (*ProtobufCClosure)(const ProtobufCMessage *, void *closure_data);
+typedef void (*ProtobufCMessageInit)(ProtobufCMessage *);
+typedef void (*ProtobufCServiceDestroy)(ProtobufCService *);
+
+/**
+ * Structure for defining a custom memory allocator.
+ */
+struct ProtobufCAllocator {
+ /** Function to allocate memory. */
+ void *(*alloc)(void *allocator_data, size_t size);
+
+ /** Function to free memory. */
+ void (*free)(void *allocator_data, void *pointer);
+
+ /** Opaque pointer passed to `alloc` and `free` functions. */
+ void *allocator_data;
+};
+
+/**
+ * Structure for the protobuf `bytes` scalar type.
+ *
+ * The data contained in a `ProtobufCBinaryData` is an arbitrary sequence of
+ * bytes. It may contain embedded `NUL` characters and is not required to be
+ * `NUL`-terminated.
+ */
+struct ProtobufCBinaryData {
+ size_t len; /**< Number of bytes in the `data` field. */
+ uint8_t *data; /**< Data bytes. */
+};
+
+/**
+ * Structure for defining a virtual append-only buffer. Used by
+ * protobuf_c_message_pack_to_buffer() to abstract the consumption of serialized
+ * bytes.
+ *
+ * `ProtobufCBuffer` "subclasses" may be defined on the stack. For example, to
+ * write to a `FILE` object:
+ *
+~~~{.c}
+typedef struct {
+ ProtobufCBuffer base;
+ FILE *fp;
+} BufferAppendToFile;
+
+static void
+my_buffer_file_append(ProtobufCBuffer *buffer,
+ size_t len,
+ const uint8_t *data)
+{
+ BufferAppendToFile *file_buf = (BufferAppendToFile *) buffer;
+ fwrite(data, len, 1, file_buf->fp); // XXX: No error handling!
+}
+~~~
+ *
+ * To use this new type of ProtobufCBuffer, it could be called as follows:
+ *
+~~~{.c}
+...
+BufferAppendToFile tmp = {0};
+tmp.base.append = my_buffer_file_append;
+tmp.fp = fp;
+protobuf_c_message_pack_to_buffer(&message, &tmp);
+...
+~~~
+ */
+struct ProtobufCBuffer {
+ /** Append function. Consumes the `len` bytes stored at `data`. */
+ void (*append)(ProtobufCBuffer *buffer,
+ size_t len,
+ const uint8_t *data);
+};
+
+/**
+ * Simple buffer "subclass" of `ProtobufCBuffer`.
+ *
+ * A `ProtobufCBufferSimple` object is declared on the stack and uses a
+ * scratch buffer provided by the user for the initial allocation. It performs
+ * exponential resizing, using dynamically allocated memory. A
+ * `ProtobufCBufferSimple` object can be created and used as follows:
+ *
+~~~{.c}
+uint8_t pad[128];
+ProtobufCBufferSimple simple = PROTOBUF_C_BUFFER_SIMPLE_INIT(pad);
+ProtobufCBuffer *buffer = (ProtobufCBuffer *) &simple;
+~~~
+ *
+ * `buffer` can now be used with `protobuf_c_message_pack_to_buffer()`. Once a
+ * message has been serialized to a `ProtobufCBufferSimple` object, the
+ * serialized data bytes can be accessed from the `.data` field.
+ *
+ * To free the memory allocated by a `ProtobufCBufferSimple` object, if any,
+ * call PROTOBUF_C_BUFFER_SIMPLE_CLEAR() on the object, for example:
+ *
+~~~{.c}
+PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple);
+~~~
+ *
+ * \see PROTOBUF_C_BUFFER_SIMPLE_INIT
+ * \see PROTOBUF_C_BUFFER_SIMPLE_CLEAR
+ */
+struct ProtobufCBufferSimple {
+ /** "Base class". */
+ ProtobufCBuffer base;
+ /** Number of bytes allocated in `data`. */
+ size_t alloced;
+ /** Number of bytes currently stored in `data`. */
+ size_t len;
+ /** Data bytes. */
+ uint8_t *data;
+ /** Whether `data` must be freed. */
+ protobuf_c_boolean must_free_data;
+ /** Allocator to use. May be NULL to indicate the system allocator. */
+ ProtobufCAllocator *allocator;
+};
+
+/**
+ * Describes an enumeration as a whole, with all of its values.
+ */
+struct ProtobufCEnumDescriptor {
+ /** Magic value checked to ensure that the API is used correctly. */
+ uint32_t magic;
+
+ /** The qualified name (e.g., "namespace.Type"). */
+ const char *name;
+ /** The unqualified name as given in the .proto file (e.g., "Type"). */
+ const char *short_name;
+ /** Identifier used in generated C code. */
+ const char *c_name;
+ /** The dot-separated namespace. */
+ const char *package_name;
+
+ /** Number elements in `values`. */
+ unsigned n_values;
+ /** Array of distinct values, sorted by numeric value. */
+ const ProtobufCEnumValue *values;
+
+ /** Number of elements in `values_by_name`. */
+ unsigned n_value_names;
+ /** Array of named values, including aliases, sorted by name. */
+ const ProtobufCEnumValueIndex *values_by_name;
+
+ /** Number of elements in `value_ranges`. */
+ unsigned n_value_ranges;
+ /** Value ranges, for faster lookups by numeric value. */
+ const ProtobufCIntRange *value_ranges;
+
+ /** Reserved for future use. */
+ void *reserved1;
+ /** Reserved for future use. */
+ void *reserved2;
+ /** Reserved for future use. */
+ void *reserved3;
+ /** Reserved for future use. */
+ void *reserved4;
+};
+
+/**
+ * Represents a single value of an enumeration.
+ */
+struct ProtobufCEnumValue {
+ /** The string identifying this value in the .proto file. */
+ const char *name;
+
+ /** The string identifying this value in generated C code. */
+ const char *c_name;
+
+ /** The numeric value assigned in the .proto file. */
+ int value;
+};
+
+/**
+ * Used by `ProtobufCEnumDescriptor` to look up enum values.
+ */
+struct ProtobufCEnumValueIndex {
+ /** Name of the enum value. */
+ const char *name;
+ /** Index into values[] array. */
+ unsigned index;
+};
+
+/**
+ * Describes a single field in a message.
+ */
+struct ProtobufCFieldDescriptor {
+ /** Name of the field as given in the .proto file. */
+ const char *name;
+
+ /** Tag value of the field as given in the .proto file. */
+ uint32_t id;
+
+ /** Whether the field is `REQUIRED`, `OPTIONAL`, or `REPEATED`. */
+ ProtobufCLabel label;
+
+ /** The type of the field. */
+ ProtobufCType type;
+
+ /**
+ * The offset in bytes of the message's C structure's quantifier field
+ * (the `has_MEMBER` field for optional members or the `n_MEMBER` field
+ * for repeated members or the case enum for oneofs).
+ */
+ unsigned quantifier_offset;
+
+ /**
+ * The offset in bytes into the message's C structure for the member
+ * itself.
+ */
+ unsigned offset;
+
+ /**
+ * A type-specific descriptor.
+ *
+ * If `type` is `PROTOBUF_C_TYPE_ENUM`, then `descriptor` points to the
+ * corresponding `ProtobufCEnumDescriptor`.
+ *
+ * If `type` is `PROTOBUF_C_TYPE_MESSAGE`, then `descriptor` points to
+ * the corresponding `ProtobufCMessageDescriptor`.
+ *
+ * Otherwise this field is NULL.
+ */
+ const void *descriptor; /* for MESSAGE and ENUM types */
+
+ /** The default value for this field, if defined. May be NULL. */
+ const void *default_value;
+
+ /**
+ * A flag word. Zero or more of the bits defined in the
+ * `ProtobufCFieldFlag` enum may be set.
+ */
+ uint32_t flags;
+
+ /** Reserved for future use. */
+ unsigned reserved_flags;
+ /** Reserved for future use. */
+ void *reserved2;
+ /** Reserved for future use. */
+ void *reserved3;
+};
+
+/**
+ * Helper structure for optimizing int => index lookups in the case
+ * where the keys are mostly consecutive values, as they presumably are for
+ * enums and fields.
+ *
+ * The data structures requires that the values in the original array are
+ * sorted.
+ */
+struct ProtobufCIntRange {
+ int start_value;
+ unsigned orig_index;
+ /*
+ * NOTE: the number of values in the range can be inferred by looking
+ * at the next element's orig_index. A dummy element is added to make
+ * this simple.
+ */
+};
+
+/**
+ * An instance of a message.
+ *
+ * `ProtobufCMessage` is a light-weight "base class" for all messages.
+ *
+ * In particular, `ProtobufCMessage` doesn't have any allocation policy
+ * associated with it. That's because it's common to create `ProtobufCMessage`
+ * objects on the stack. In fact, that's what we recommend for sending messages.
+ * If the object is allocated from the stack, you can't really have a memory
+ * leak.
+ *
+ * This means that calls to functions like protobuf_c_message_unpack() which
+ * return a `ProtobufCMessage` must be paired with a call to a free function,
+ * like protobuf_c_message_free_unpacked().
+ */
+struct ProtobufCMessage {
+ /** The descriptor for this message type. */
+ const ProtobufCMessageDescriptor *descriptor;
+ /** The number of elements in `unknown_fields`. */
+ unsigned n_unknown_fields;
+ /** The fields that weren't recognized by the parser. */
+ ProtobufCMessageUnknownField *unknown_fields;
+};
+
+/**
+ * Describes a message.
+ */
+struct ProtobufCMessageDescriptor {
+ /** Magic value checked to ensure that the API is used correctly. */
+ uint32_t magic;
+
+ /** The qualified name (e.g., "namespace.Type"). */
+ const char *name;
+ /** The unqualified name as given in the .proto file (e.g., "Type"). */
+ const char *short_name;
+ /** Identifier used in generated C code. */
+ const char *c_name;
+ /** The dot-separated namespace. */
+ const char *package_name;
+
+ /**
+ * Size in bytes of the C structure representing an instance of this
+ * type of message.
+ */
+ size_t sizeof_message;
+
+ /** Number of elements in `fields`. */
+ unsigned n_fields;
+ /** Field descriptors, sorted by tag number. */
+ const ProtobufCFieldDescriptor *fields;
+ /** Used for looking up fields by name. */
+ const unsigned *fields_sorted_by_name;
+
+ /** Number of elements in `field_ranges`. */
+ unsigned n_field_ranges;
+ /** Used for looking up fields by id. */
+ const ProtobufCIntRange *field_ranges;
+
+ /** Message initialisation function. */
+ ProtobufCMessageInit message_init;
+
+ /** Reserved for future use. */
+ void *reserved1;
+ /** Reserved for future use. */
+ void *reserved2;
+ /** Reserved for future use. */
+ void *reserved3;
+};
+
+/**
+ * An unknown message field.
+ */
+struct ProtobufCMessageUnknownField {
+ /** The tag number. */
+ uint32_t tag;
+ /** The wire type of the field. */
+ ProtobufCWireType wire_type;
+ /** Number of bytes in `data`. */
+ size_t len;
+ /** Field data. */
+ uint8_t *data;
+};
+
+/**
+ * Method descriptor.
+ */
+struct ProtobufCMethodDescriptor {
+ /** Method name. */
+ const char *name;
+ /** Input message descriptor. */
+ const ProtobufCMessageDescriptor *input;
+ /** Output message descriptor. */
+ const ProtobufCMessageDescriptor *output;
+};
+
+/**
+ * Service.
+ */
+struct ProtobufCService {
+ /** Service descriptor. */
+ const ProtobufCServiceDescriptor *descriptor;
+ /** Function to invoke the service. */
+ void (*invoke)(ProtobufCService *service,
+ unsigned method_index,
+ const ProtobufCMessage *input,
+ ProtobufCClosure closure,
+ void *closure_data);
+ /** Function to destroy the service. */
+ void (*destroy)(ProtobufCService *service);
+};
+
+/**
+ * Service descriptor.
+ */
+struct ProtobufCServiceDescriptor {
+ /** Magic value checked to ensure that the API is used correctly. */
+ uint32_t magic;
+
+ /** Service name. */
+ const char *name;
+ /** Short version of service name. */
+ const char *short_name;
+ /** C identifier for the service name. */
+ const char *c_name;
+ /** Package name. */
+ const char *package;
+ /** Number of elements in `methods`. */
+ unsigned n_methods;
+ /** Method descriptors, in the order defined in the .proto file. */
+ const ProtobufCMethodDescriptor *methods;
+ /** Sort index of methods. */
+ const unsigned *method_indices_by_name;
+};
+
+/**
+ * Get the version of the protobuf-c library. Note that this is the version of
+ * the library linked against, not the version of the headers compiled against.
+ *
+ * \return A string containing the version number of protobuf-c.
+ */
+PROTOBUF_C__API
+const char *
+protobuf_c_version(void);
+
+/**
+ * Get the version of the protobuf-c library. Note that this is the version of
+ * the library linked against, not the version of the headers compiled against.
+ *
+ * \return A 32 bit unsigned integer containing the version number of
+ * protobuf-c, represented in base-10 as (MAJOR*1E6) + (MINOR*1E3) + PATCH.
+ */
+PROTOBUF_C__API
+uint32_t
+protobuf_c_version_number(void);
+
+/**
+ * The version of the protobuf-c headers, represented as a string using the same
+ * format as protobuf_c_version().
+ */
+#define PROTOBUF_C_VERSION "1.4.1"
+
+/**
+ * The version of the protobuf-c headers, represented as an integer using the
+ * same format as protobuf_c_version_number().
+ */
+#define PROTOBUF_C_VERSION_NUMBER 1004001
+
+/**
+ * The minimum protoc-c version which works with the current version of the
+ * protobuf-c headers.
+ */
+#define PROTOBUF_C_MIN_COMPILER_VERSION 1000000
+
+/**
+ * Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by name.
+ *
+ * \param desc
+ * The `ProtobufCEnumDescriptor` object.
+ * \param name
+ * The `name` field from the corresponding `ProtobufCEnumValue` object to
+ * match.
+ * \return
+ * A `ProtobufCEnumValue` object.
+ * \retval NULL
+ * If not found or if the optimize_for = CODE_SIZE option was set.
+ */
+PROTOBUF_C__API
+const ProtobufCEnumValue *
+protobuf_c_enum_descriptor_get_value_by_name(
+ const ProtobufCEnumDescriptor *desc,
+ const char *name);
+
+/**
+ * Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by numeric
+ * value.
+ *
+ * \param desc
+ * The `ProtobufCEnumDescriptor` object.
+ * \param value
+ * The `value` field from the corresponding `ProtobufCEnumValue` object to
+ * match.
+ *
+ * \return
+ * A `ProtobufCEnumValue` object.
+ * \retval NULL
+ * If not found.
+ */
+PROTOBUF_C__API
+const ProtobufCEnumValue *
+protobuf_c_enum_descriptor_get_value(
+ const ProtobufCEnumDescriptor *desc,
+ int value);
+
+/**
+ * Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by
+ * the name of the field.
+ *
+ * \param desc
+ * The `ProtobufCMessageDescriptor` object.
+ * \param name
+ * The name of the field.
+ * \return
+ * A `ProtobufCFieldDescriptor` object.
+ * \retval NULL
+ * If not found or if the optimize_for = CODE_SIZE option was set.
+ */
+PROTOBUF_C__API
+const ProtobufCFieldDescriptor *
+protobuf_c_message_descriptor_get_field_by_name(
+ const ProtobufCMessageDescriptor *desc,
+ const char *name);
+
+/**
+ * Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by
+ * the tag value of the field.
+ *
+ * \param desc
+ * The `ProtobufCMessageDescriptor` object.
+ * \param value
+ * The tag value of the field.
+ * \return
+ * A `ProtobufCFieldDescriptor` object.
+ * \retval NULL
+ * If not found.
+ */
+PROTOBUF_C__API
+const ProtobufCFieldDescriptor *
+protobuf_c_message_descriptor_get_field(
+ const ProtobufCMessageDescriptor *desc,
+ unsigned value);
+
+/**
+ * Determine the number of bytes required to store the serialised message.
+ *
+ * \param message
+ * The message object to serialise.
+ * \return
+ * Number of bytes.
+ */
+PROTOBUF_C__API
+size_t
+protobuf_c_message_get_packed_size(const ProtobufCMessage *message);
+
+/**
+ * Serialise a message from its in-memory representation.
+ *
+ * This function stores the serialised bytes of the message in a pre-allocated
+ * buffer.
+ *
+ * \param message
+ * The message object to serialise.
+ * \param[out] out
+ * Buffer to store the bytes of the serialised message. This buffer must
+ * have enough space to store the packed message. Use
+ * protobuf_c_message_get_packed_size() to determine the number of bytes
+ * required.
+ * \return
+ * Number of bytes stored in `out`.
+ */
+PROTOBUF_C__API
+size_t
+protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out);
+
+/**
+ * Serialise a message from its in-memory representation to a virtual buffer.
+ *
+ * This function calls the `append` method of a `ProtobufCBuffer` object to
+ * consume the bytes generated by the serialiser.
+ *
+ * \param message
+ * The message object to serialise.
+ * \param buffer
+ * The virtual buffer object.
+ * \return
+ * Number of bytes passed to the virtual buffer.
+ */
+PROTOBUF_C__API
+size_t
+protobuf_c_message_pack_to_buffer(
+ const ProtobufCMessage *message,
+ ProtobufCBuffer *buffer);
+
+/**
+ * Unpack a serialised message into an in-memory representation.
+ *
+ * \param descriptor
+ * The message descriptor.
+ * \param allocator
+ * `ProtobufCAllocator` to use for memory allocation. May be NULL to
+ * specify the default allocator.
+ * \param len
+ * Length in bytes of the serialised message.
+ * \param data
+ * Pointer to the serialised message.
+ * \return
+ * An unpacked message object.
+ * \retval NULL
+ * If an error occurred during unpacking.
+ */
+PROTOBUF_C__API
+ProtobufCMessage *
+protobuf_c_message_unpack(
+ const ProtobufCMessageDescriptor *descriptor,
+ ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data);
+
+/**
+ * Free an unpacked message object.
+ *
+ * This function should be used to deallocate the memory used by a call to
+ * protobuf_c_message_unpack().
+ *
+ * \param message
+ * The message object to free. May be NULL.
+ * \param allocator
+ * `ProtobufCAllocator` to use for memory deallocation. May be NULL to
+ * specify the default allocator.
+ */
+PROTOBUF_C__API
+void
+protobuf_c_message_free_unpacked(
+ ProtobufCMessage *message,
+ ProtobufCAllocator *allocator);
+
+/**
+ * Check the validity of a message object.
+ *
+ * Makes sure all required fields (`PROTOBUF_C_LABEL_REQUIRED`) are present.
+ * Recursively checks nested messages.
+ *
+ * \retval TRUE
+ * Message is valid.
+ * \retval FALSE
+ * Message is invalid.
+ */
+PROTOBUF_C__API
+protobuf_c_boolean
+protobuf_c_message_check(const ProtobufCMessage *);
+
+/** Message initialiser. */
+#define PROTOBUF_C_MESSAGE_INIT(descriptor) { descriptor, 0, NULL }
+
+/**
+ * Initialise a message object from a message descriptor.
+ *
+ * \param descriptor
+ * Message descriptor.
+ * \param message
+ * Allocated block of memory of size `descriptor->sizeof_message`.
+ */
+PROTOBUF_C__API
+void
+protobuf_c_message_init(
+ const ProtobufCMessageDescriptor *descriptor,
+ void *message);
+
+/**
+ * Free a service.
+ *
+ * \param service
+ * The service object to free.
+ */
+PROTOBUF_C__API
+void
+protobuf_c_service_destroy(ProtobufCService *service);
+
+/**
+ * Look up a `ProtobufCMethodDescriptor` by name.
+ *
+ * \param desc
+ * Service descriptor.
+ * \param name
+ * Name of the method.
+ *
+ * \return
+ * A `ProtobufCMethodDescriptor` object.
+ * \retval NULL
+ * If not found or if the optimize_for = CODE_SIZE option was set.
+ */
+PROTOBUF_C__API
+const ProtobufCMethodDescriptor *
+protobuf_c_service_descriptor_get_method_by_name(
+ const ProtobufCServiceDescriptor *desc,
+ const char *name);
+
+/**
+ * Initialise a `ProtobufCBufferSimple` object.
+ */
+#define PROTOBUF_C_BUFFER_SIMPLE_INIT(array_of_bytes) \
+{ \
+ { protobuf_c_buffer_simple_append }, \
+ sizeof(array_of_bytes), \
+ 0, \
+ (array_of_bytes), \
+ 0, \
+ NULL \
+}
+
+/**
+ * Clear a `ProtobufCBufferSimple` object, freeing any allocated memory.
+ */
+#define PROTOBUF_C_BUFFER_SIMPLE_CLEAR(simp_buf) \
+do { \
+ if ((simp_buf)->must_free_data) { \
+ if ((simp_buf)->allocator != NULL) \
+ (simp_buf)->allocator->free( \
+ (simp_buf)->allocator, \
+ (simp_buf)->data); \
+ else \
+ free((simp_buf)->data); \
+ } \
+} while (0)
+
+/**
+ * The `append` method for `ProtobufCBufferSimple`.
+ *
+ * \param buffer
+ * The buffer object to append to. Must actually be a
+ * `ProtobufCBufferSimple` object.
+ * \param len
+ * Number of bytes in `data`.
+ * \param data
+ * Data to append.
+ */
+PROTOBUF_C__API
+void
+protobuf_c_buffer_simple_append(
+ ProtobufCBuffer *buffer,
+ size_t len,
+ const unsigned char *data);
+
+PROTOBUF_C__API
+void
+protobuf_c_service_generated_init(
+ ProtobufCService *service,
+ const ProtobufCServiceDescriptor *descriptor,
+ ProtobufCServiceDestroy destroy);
+
+PROTOBUF_C__API
+void
+protobuf_c_service_invoke_internal(
+ ProtobufCService *service,
+ unsigned method_index,
+ const ProtobufCMessage *input,
+ ProtobufCClosure closure,
+ void *closure_data);
+
+/**@}*/
+
+PROTOBUF_C__END_DECLS
+
+#endif /* PROTOBUF_C_H */
diff --git a/include/sudo_compat.h b/include/sudo_compat.h
new file mode 100644
index 0000000..c718182
--- /dev/null
+++ b/include/sudo_compat.h
@@ -0,0 +1,566 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2008, 2009-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#ifndef SUDO_COMPAT_H
+#define SUDO_COMPAT_H
+
+#include <sys/types.h> /* for gid_t, mode_t, size_t, ssize_t, time_t, uid_t */
+#include <sys/stat.h> /* to avoid problems with mismatched headers and libc */
+#include <unistd.h> /* to avoid problems with mismatched headers and libc */
+#include <stdio.h>
+#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_VASPRINTF) || \
+ !defined(HAVE_VSYSLOG) || defined(PREFER_PORTABLE_SNPRINTF)
+# include <stdarg.h>
+#endif
+
+/*
+ * Macros and functions that may be missing on some operating systems.
+ */
+
+/*
+ * Given the pointer x to the member m of the struct s, return
+ * a pointer to the containing structure.
+ */
+#ifndef __containerof
+# define __containerof(x, s, m) ((s *)((char *)(x) - offsetof(s, m)))
+#endif
+
+/*
+ * Pre-C99 compilers may lack a va_copy macro.
+ */
+#ifndef HAVE_VA_COPY
+# ifdef HAVE___VA_COPY
+# define va_copy(d, s) __va_copy(d, s)
+# else
+# define va_copy(d, s) memcpy(&(d), &(s), sizeof(d));
+# endif
+#endif
+
+/*
+ * Some systems lack full limit definitions.
+ */
+#if defined(HAVE_DECL_LLONG_MAX) && !HAVE_DECL_LLONG_MAX
+# if defined(HAVE_DECL_QUAD_MAX) && HAVE_DECL_QUAD_MAX
+# define LLONG_MAX QUAD_MAX
+# else
+# define LLONG_MAX 0x7fffffffffffffffLL
+# endif
+#endif
+
+#if defined(HAVE_DECL_LLONG_MIN) && !HAVE_DECL_LLONG_MIN
+# if defined(HAVE_DECL_QUAD_MIN) && HAVE_DECL_QUAD_MIN
+# define LLONG_MIN QUAD_MIN
+# else
+# define LLONG_MIN (-0x7fffffffffffffffLL-1)
+# endif
+#endif
+
+#if defined(HAVE_DECL_ULLONG_MAX) && !HAVE_DECL_ULLONG_MAX
+# if defined(HAVE_DECL_UQUAD_MAX) && HAVE_DECL_UQUAD_MAX
+# define ULLONG_MAX UQUAD_MAX
+# else
+# define ULLONG_MAX 0xffffffffffffffffULL
+# endif
+#endif
+
+#if defined(HAVE_DECL_SIZE_MAX) && !HAVE_DECL_SIZE_MAX
+# if defined(HAVE_DECL_SIZE_T_MAX) && HAVE_DECL_SIZE_T_MAX
+# define SIZE_MAX SIZE_T_MAX
+# else
+# define SIZE_MAX ULONG_MAX
+# endif
+#endif
+
+#if defined(HAVE_DECL_SSIZE_MAX) && !HAVE_DECL_SSIZE_MAX
+# define SSIZE_MAX LONG_MAX
+#endif
+
+#if defined(HAVE_DECL_PATH_MAX) && !HAVE_DECL_PATH_MAX
+# if defined(HAVE_DECL__POSIX_PATH_MAX) && HAVE_DECL__POSIX_PATH_MAX
+# define PATH_MAX _POSIX_PATH_MAX
+# else
+# define PATH_MAX 256
+# endif
+#endif
+
+/* ACCESSPERMS and ALLPERMS are handy BSDisms. */
+#ifndef ACCESSPERMS
+# define ACCESSPERMS 00777
+#endif /* ACCESSPERMS */
+#ifndef ALLPERMS
+# define ALLPERMS 07777
+#endif /* ALLPERMS */
+
+/* For futimens() and utimensat() emulation. */
+#if !defined(HAVE_FUTIMENS) && !defined(HAVE_UTIMENSAT)
+# ifndef UTIME_OMIT
+# define UTIME_OMIT -1L
+# endif
+# ifndef UTIME_NOW
+# define UTIME_NOW -2L
+# endif
+#endif
+#if !defined(HAVE_OPENAT) || (!defined(HAVE_FUTIMENS) && !defined(HAVE_UTIMENSAT)) || !defined(HAVE_FCHMODAT) || !defined(HAVE_FSTATAT) || !defined(HAVE_UNLINKAT)
+# ifndef AT_FDCWD
+# define AT_FDCWD -100
+# endif
+# ifndef AT_SYMLINK_NOFOLLOW
+# define AT_SYMLINK_NOFOLLOW 0x02
+# endif
+#endif
+
+/* For dup3() and pipe2() emulation. */
+#if (!defined(HAVE_PIPE2) || !defined(HAVE_DUP3)) && defined(O_NONBLOCK)
+# if !defined(O_CLOEXEC) || O_CLOEXEC > 0xffffffff
+# undef O_CLOEXEC
+# define O_CLOEXEC 0x80000000
+# endif
+#endif
+
+/*
+ * BSD defines these in <sys/param.h> but we don't include that anymore.
+ */
+#ifndef MIN
+# define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+#ifndef MAX
+# define MAX(a,b) (((a)>(b))?(a):(b))
+#endif
+
+/* Macros to set/clear/test flags. */
+#undef SET
+#define SET(t, f) ((t) |= (f))
+#undef CLR
+#define CLR(t, f) ((t) &= ~(f))
+#undef ISSET
+#define ISSET(t, f) ((t) & (f))
+
+/*
+ * Some systems define this in <sys/param.h> but we don't include that anymore.
+ */
+#ifndef howmany
+# define howmany(x, y) (((x) + ((y) - 1)) / (y))
+#endif
+
+/*
+ * Simple isblank() macro and function for systems without it.
+ */
+#ifndef HAVE_ISBLANK
+sudo_dso_public int isblank(int);
+# define isblank(_x) ((_x) == ' ' || (_x) == '\t')
+#endif
+
+/*
+ * NCR's SVr4 has _innetgr(3) instead of innetgr(3) for some reason.
+ */
+#ifdef HAVE__INNETGR
+# define innetgr(n, h, u, d) (_innetgr(n, h, u, d))
+# define HAVE_INNETGR 1
+#endif /* HAVE__INNETGR */
+
+/*
+ * The nitems macro may be defined in sys/param.h
+ */
+#ifndef nitems
+# define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
+#endif
+
+/*
+ * If dirfd() does not exists, hopefully dd_fd does.
+ */
+#if !defined(HAVE_DIRFD) && defined(HAVE_DD_FD)
+# define dirfd(_d) ((_d)->dd_fd)
+# define HAVE_DIRFD
+#endif
+
+#if !defined(HAVE_KILLPG) && !defined(killpg)
+# define killpg(p, s) kill(-(p), (s))
+#endif
+
+/*
+ * Declare errno if errno.h doesn't do it for us.
+ */
+#if defined(HAVE_DECL_ERRNO) && !HAVE_DECL_ERRNO
+extern int errno;
+#endif /* !HAVE_DECL_ERRNO */
+
+/* Not all systems define NSIG in signal.h */
+#if defined(HAVE_DECL_NSIG) && !HAVE_DECL_NSIG
+# if defined(HAVE_DECL__NSIG) && HAVE_DECL__NSIG
+# define NSIG _NSIG
+# elif defined(HAVE_DECL___NSIG) && HAVE_DECL___NSIG
+# define NSIG __NSIG
+# else
+# define NSIG 64
+# endif
+#endif
+
+/* For sig2str() */
+#if !defined(HAVE_DECL_SIG2STR_MAX) || !HAVE_DECL_SIG2STR_MAX
+# define SIG2STR_MAX 32
+#endif
+
+/* WCOREDUMP is not POSIX, this usually works (verified on AIX). */
+#ifndef WCOREDUMP
+# define WCOREDUMP(x) ((x) & 0x80)
+#endif
+
+/* W_EXITCODE is not POSIX but the encoding of wait status is. */
+#ifndef W_EXITCODE
+# define W_EXITCODE(ret, sig) ((ret) << 8 | (sig))
+#endif
+
+/* Number of bits in a byte. */
+#ifndef NBBY
+# ifdef __NBBY
+# define NBBY __NBBY
+# else
+# define NBBY 8
+# endif
+#endif
+
+#ifndef HAVE_SETEUID
+# if defined(HAVE_SETRESUID)
+# define seteuid(u) setresuid(-1, (u), -1)
+# define setegid(g) setresgid(-1, (g), -1)
+# define HAVE_SETEUID 1
+# elif defined(HAVE_SETREUID)
+# define seteuid(u) setreuid(-1, (u))
+# define setegid(g) setregid(-1, (g))
+# define HAVE_SETEUID 1
+# endif
+#endif /* HAVE_SETEUID */
+
+/*
+ * Older HP-UX does not declare setresuid() or setresgid().
+ */
+#if defined(HAVE_DECL_SETRESUID) && !HAVE_DECL_SETRESUID
+int setresuid(uid_t, uid_t, uid_t);
+int setresgid(gid_t, gid_t, gid_t);
+#endif
+#if defined(HAVE_DECL_GETRESUID) && !HAVE_DECL_GETRESUID
+int getresuid(uid_t *, uid_t *, uid_t *);
+int getresgid(gid_t *, gid_t *, gid_t *);
+#endif
+
+/*
+ * HP-UX does not declare innetgr() or getdomainname().
+ * Solaris does not declare getdomainname().
+ */
+#if defined(HAVE_DECL_INNETGR) && !HAVE_DECL_INNETGR
+int innetgr(const char *, const char *, const char *, const char *);
+#endif
+#if defined(HAVE_DECL__INNETGR) && !HAVE_DECL__INNETGR
+int _innetgr(const char *, const char *, const char *, const char *);
+#endif
+#if defined(HAVE_DECL_GETDOMAINNAME) && !HAVE_DECL_GETDOMAINNAME
+int getdomainname(char *, size_t);
+#endif
+
+/*
+ * HP-UX 11.00 has broken pread/pwrite on 32-bit machines when
+ * _FILE_OFFSET_BITS == 64. Use pread64/pwrite64 instead.
+ */
+#if defined(__hpux) && !defined(__LP64__)
+# ifdef HAVE_PREAD64
+# undef pread
+# define pread(_a, _b, _c, _d) pread64((_a), (_b), (_c), (_d))
+# if defined(HAVE_DECL_PREAD64) && !HAVE_DECL_PREAD64
+ ssize_t pread64(int fd, void *buf, size_t nbytes, off64_t offset);
+# endif
+# endif
+# ifdef HAVE_PWRITE64
+# undef pwrite
+# define pwrite(_a, _b, _c, _d) pwrite64((_a), (_b), (_c), (_d))
+# if defined(HAVE_DECL_PWRITE64) && !HAVE_DECL_PWRITE64
+ ssize_t pwrite64(int fd, const void *buf, size_t nbytes, off64_t offset);
+# endif
+# endif
+#endif /* __hpux && !__LP64__ */
+
+/*
+ * Older systems may lack fseeko(3), just use fseek(3) instead.
+ */
+#ifndef HAVE_FSEEKO
+# define fseeko(f, o, w) fseek((f), (long)(o), (w))
+#endif
+
+/*
+ * Functions "missing" from libc.
+ * All libc replacements are prefixed with "sudo_" to avoid namespace issues.
+ */
+
+struct passwd;
+struct stat;
+struct timespec;
+struct termios;
+struct tm;
+
+#ifndef HAVE_CFMAKERAW
+sudo_dso_public void sudo_cfmakeraw(struct termios *term);
+# undef cfmakeraw
+# define cfmakeraw(_a) sudo_cfmakeraw((_a))
+#endif /* HAVE_CFMAKERAW */
+#ifndef HAVE_CLOSEFROM
+sudo_dso_public void sudo_closefrom(int);
+# undef closefrom
+# define closefrom(_a) sudo_closefrom((_a))
+#endif /* HAVE_CLOSEFROM */
+#ifndef HAVE_EXPLICIT_BZERO
+sudo_dso_public void sudo_explicit_bzero(void *s, size_t n);
+# undef explicit_bzero
+# define explicit_bzero(_a, _b) sudo_explicit_bzero((_a), (_b))
+#endif /* HAVE_EXPLICIT_BZERO */
+#ifndef HAVE_FREEZERO
+sudo_dso_public void sudo_freezero(void *p, size_t n);
+# undef freezero
+# define freezero(_a, _b) sudo_freezero((_a), (_b))
+#endif /* HAVE_FREEZERO */
+#ifndef HAVE_GETGROUPLIST
+sudo_dso_public int sudo_getgrouplist(const char *name, GETGROUPS_T basegid, GETGROUPS_T *groups, int *ngroupsp);
+# undef getgrouplist
+# define getgrouplist(_a, _b, _c, _d) sudo_getgrouplist((_a), (_b), (_c), (_d))
+#endif /* GETGROUPLIST */
+#if !defined(HAVE_GETDELIM)
+sudo_dso_public ssize_t sudo_getdelim(char ** restrict bufp, size_t * restrict bufsizep, int delim, FILE * restrict fp);
+# undef getdelim
+# define getdelim(_a, _b, _c, _d) sudo_getdelim((_a), (_b), (_c), (_d))
+#elif defined(HAVE_DECL_GETDELIM) && !HAVE_DECL_GETDELIM
+/* getdelim present in libc but missing prototype (old gcc fixed includes?) */
+ssize_t getdelim(char **bufp, size_t *bufsizep, int delim, FILE *fp);
+#endif /* HAVE_GETDELIM */
+#ifndef HAVE_GETUSERSHELL
+sudo_dso_public char *sudo_getusershell(void);
+# undef getusershell
+# define getusershell() sudo_getusershell()
+sudo_dso_public void sudo_setusershell(void);
+# undef setusershell
+# define setusershell() sudo_setusershell()
+sudo_dso_public void sudo_endusershell(void);
+# undef endusershell
+# define endusershell() sudo_endusershell()
+#elif HAVE_DECL_GETUSERSHELL == 0
+/* Older Solaris has getusershell() et al but does not declare it. */
+char *getusershell(void);
+void setusershell(void);
+void endusershell(void);
+#endif /* HAVE_GETUSERSHELL */
+#ifndef HAVE_GMTIME_R
+sudo_dso_public struct tm *sudo_gmtime_r(const time_t *, struct tm *);
+# undef gmtime_r
+# define gmtime_r(_a, _b) sudo_gmtime_r((_a), (_b))
+#endif /* HAVE_GMTIME_R */
+#ifndef HAVE_LOCALTIME_R
+sudo_dso_public struct tm *sudo_localtime_r(const time_t *, struct tm *);
+# undef localtime_r
+# define localtime_r(_a, _b) sudo_localtime_r((_a), (_b))
+#endif /* HAVE_LOCALTIME_R */
+#ifndef HAVE_TIMEGM
+sudo_dso_public time_t sudo_timegm(struct tm *);
+#endif /* HAVE_TIMEGM */
+#ifndef HAVE_UTIMENSAT
+sudo_dso_public int sudo_utimensat(int fd, const char *file, const struct timespec *times, int flag);
+# undef utimensat
+# define utimensat(_a, _b, _c, _d) sudo_utimensat((_a), (_b), (_c), (_d))
+#endif /* HAVE_UTIMENSAT */
+#ifndef HAVE_FCHMODAT
+sudo_dso_public int sudo_fchmodat(int dfd, const char *path, mode_t mode, int flag);
+# undef fchmodat
+# define fchmodat(_a, _b, _c, _d) sudo_fchmodat((_a), (_b), (_c), (_d))
+#endif /* HAVE_FCHMODAT */
+#ifndef HAVE_FSTATAT
+sudo_dso_public int sudo_fstatat(int dfd, const char *path, struct stat *sb, int flag);
+# undef fstatat
+# define fstatat(_a, _b, _c, _d) sudo_fstatat((_a), (_b), (_c), (_d))
+#endif /* HAVE_FSTATAT */
+#ifndef HAVE_FUTIMENS
+sudo_dso_public int sudo_futimens(int fd, const struct timespec *times);
+# undef futimens
+# define futimens(_a, _b) sudo_futimens((_a), (_b))
+#endif /* HAVE_FUTIMENS */
+#if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
+sudo_dso_public int sudo_snprintf(char * restrict str, size_t n, char const * restrict fmt, ...) sudo_printflike(3, 4);
+# undef snprintf
+# define snprintf sudo_snprintf
+#endif /* HAVE_SNPRINTF */
+#if !defined(HAVE_VSNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
+sudo_dso_public int sudo_vsnprintf(char * restrict str, size_t n, const char * restrict fmt, va_list ap) sudo_printflike(3, 0);
+# undef vsnprintf
+# define vsnprintf sudo_vsnprintf
+#endif /* HAVE_VSNPRINTF */
+#if !defined(HAVE_ASPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
+sudo_dso_public int sudo_asprintf(char ** restrict str, char const * restrict fmt, ...) sudo_printflike(2, 3);
+# undef asprintf
+# define asprintf sudo_asprintf
+#endif /* HAVE_ASPRINTF */
+#if !defined(HAVE_VASPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
+sudo_dso_public int sudo_vasprintf(char ** restrict str, const char * restrict fmt, va_list ap) sudo_printflike(2, 0);
+# undef vasprintf
+# define vasprintf sudo_vasprintf
+#endif /* HAVE_VASPRINTF */
+#ifndef HAVE_STRLCAT
+sudo_dso_public size_t sudo_strlcat(char * restrict dst, const char * restrict src, size_t siz);
+# undef strlcat
+# define strlcat(_a, _b, _c) sudo_strlcat((_a), (_b), (_c))
+#endif /* HAVE_STRLCAT */
+#ifndef HAVE_STRLCPY
+sudo_dso_public size_t sudo_strlcpy(char * restrict dst, const char * restrict src, size_t siz);
+# undef strlcpy
+# define strlcpy(_a, _b, _c) sudo_strlcpy((_a), (_b), (_c))
+#endif /* HAVE_STRLCPY */
+#ifndef HAVE_STRNDUP
+sudo_dso_public char *sudo_strndup(const char *str, size_t maxlen);
+# undef strndup
+# define strndup(_a, _b) sudo_strndup((_a), (_b))
+#endif /* HAVE_STRNDUP */
+#ifndef HAVE_STRNLEN
+sudo_dso_public size_t sudo_strnlen(const char *str, size_t maxlen);
+# undef strnlen
+# define strnlen(_a, _b) sudo_strnlen((_a), (_b))
+#endif /* HAVE_STRNLEN */
+#ifndef HAVE_FCHOWNAT
+sudo_dso_public int sudo_fchownat(int dfd, const char *path, uid_t uid, gid_t gid, int flag);
+# undef fchownat
+# define fchownat(_a, _b, _c, _d, _e) sudo_fchownat((_a), (_b), (_c), (_d), (_e))
+#endif /* HAVE_FCHOWNAT */
+#ifndef HAVE_MEMRCHR
+sudo_dso_public void *sudo_memrchr(const void *s, int c, size_t n);
+# undef memrchr
+# define memrchr(_a, _b, _c) sudo_memrchr((_a), (_b), (_c))
+#endif /* HAVE_MEMRCHR */
+#ifndef HAVE_MKDIRAT
+sudo_dso_public int sudo_mkdirat(int dfd, const char *path, mode_t mode);
+# undef mkdirat
+# define mkdirat(_a, _b, _c) sudo_mkdirat((_a), (_b), (_c))
+#endif /* HAVE_MKDIRAT */
+#if !defined(HAVE_MKDTEMPAT) || !defined(HAVE_MKOSTEMPSAT)
+# if defined(HAVE_MKDTEMPAT_NP) && defined(HAVE_MKOSTEMPSAT_NP)
+# undef mkdtempat
+# define mkdtempat mkdtempat_np
+# undef mkostempsat
+# define mkostempsat mkostempsat_np
+# else
+sudo_dso_public char *sudo_mkdtemp(char *path);
+# undef mkdtemp
+# define mkdtemp(_a) sudo_mkdtemp((_a))
+sudo_dso_public char *sudo_mkdtempat(int dfd, char *path);
+# undef mkdtempat
+# define mkdtempat(_a, _b) sudo_mkdtempat((_a), (_b))
+sudo_dso_public int sudo_mkostempsat(int dfd, char *path, int slen, int flags);
+# undef mkostempsat
+# define mkostempsat(_a, _b, _c, _d) sudo_mkostempsat((_a), (_b), (_c), (_d))
+sudo_dso_public int sudo_mkstemp(char *path);
+# undef mkstemp
+# define mkstemp(_a) sudo_mkstemp((_a))
+sudo_dso_public int sudo_mkstemps(char *path, int slen);
+# undef mkstemps
+# define mkstemps(_a, _b) sudo_mkstemps((_a), (_b))
+# endif /* HAVE_MKDTEMPAT_NP || HAVE_MKOSTEMPSAT_NP */
+#endif /* !HAVE_MKDTEMPAT || !HAVE_MKOSTEMPSAT */
+#ifndef HAVE_NANOSLEEP
+sudo_dso_public int sudo_nanosleep(const struct timespec *timeout, struct timespec *remainder);
+#undef nanosleep
+# define nanosleep(_a, _b) sudo_nanosleep((_a), (_b))
+#endif /* HAVE_NANOSLEEP */
+#ifndef HAVE_OPENAT
+sudo_dso_public int sudo_openat(int dfd, const char *path, int flags, mode_t mode);
+# undef openat
+# define openat(_a, _b, _c, _d) sudo_openat((_a), (_b), (_c), (_d))
+#endif /* HAVE_OPENAT */
+#ifndef HAVE_PW_DUP
+sudo_dso_public struct passwd *sudo_pw_dup(const struct passwd *pw);
+# undef pw_dup
+# define pw_dup(_a) sudo_pw_dup((_a))
+#endif /* HAVE_PW_DUP */
+#ifndef HAVE_STRSIGNAL
+sudo_dso_public char *sudo_strsignal(int signo);
+# undef strsignal
+# define strsignal(_a) sudo_strsignal((_a))
+#endif /* HAVE_STRSIGNAL */
+#ifndef HAVE_SIG2STR
+sudo_dso_public int sudo_sig2str(int signo, char *signame);
+# undef sig2str
+# define sig2str(_a, _b) sudo_sig2str((_a), (_b))
+#endif /* HAVE_SIG2STR */
+#ifndef HAVE_STR2SIG
+sudo_dso_public int sudo_str2sig(const char *signame, int *signum);
+# undef str2sig
+# define str2sig(_a, _b) sudo_str2sig((_a), (_b))
+#endif /* HAVE_STR2SIG */
+#if !defined(HAVE_INET_NTOP) && defined(NEED_INET_NTOP)
+sudo_dso_public char *sudo_inet_ntop(int af, const void *src, char *dst, socklen_t size);
+# undef inet_ntop
+# define inet_ntop(_a, _b, _c, _d) sudo_inet_ntop((_a), (_b), (_c), (_d))
+#endif /* HAVE_INET_NTOP */
+#ifndef HAVE_INET_PTON
+sudo_dso_public int sudo_inet_pton(int af, const char *src, void *dst);
+# undef inet_pton
+# define inet_pton(_a, _b, _c) sudo_inet_pton((_a), (_b), (_c))
+#endif /* HAVE_INET_PTON */
+#ifndef HAVE_GETPROGNAME
+sudo_dso_public const char *sudo_getprogname(void);
+# undef getprogname
+# define getprogname() sudo_getprogname()
+#endif /* HAVE_GETPROGNAME */
+#ifndef HAVE_SETPROGNAME
+sudo_dso_public void sudo_setprogname(const char *name);
+# undef setprogname
+# define setprogname(_a) sudo_setprogname(_a)
+#endif /* HAVE_SETPROGNAME */
+#ifndef HAVE_REALLOCARRAY
+sudo_dso_public void *sudo_reallocarray(void *ptr, size_t nmemb, size_t size);
+# undef reallocarray
+# define reallocarray(_a, _b, _c) sudo_reallocarray((_a), (_b), (_c))
+#endif /* HAVE_REALLOCARRAY */
+#ifndef HAVE_REALPATH
+sudo_dso_public char *sudo_realpath(const char * restrict path, char * restrict resolved);
+# undef realpath
+# define realpath(_a, _b) sudo_realpath((_a), (_b))
+#endif /* HAVE_REALPATH */
+#ifndef HAVE_DUP3
+sudo_dso_public int sudo_dup3(int oldd, int newd, int flags);
+# undef dup3
+# define dup3(_a, _b, _c) sudo_dup3((_a), (_b), (_c))
+#endif /* HAVE_DUP3 */
+#ifndef HAVE_PIPE2
+sudo_dso_public int sudo_pipe2(int fildes[2], int flags);
+# undef pipe2
+# define pipe2(_a, _b) sudo_pipe2((_a), (_b))
+#endif /* HAVE_PIPE2 */
+#ifndef HAVE_PREAD
+sudo_dso_public ssize_t sudo_pread(int fd, void *buf, size_t nbytes, off_t offset);
+# undef pread
+# define pread(_a, _b, _c, _d) sudo_pread((_a), (_b), (_c), (_d))
+#endif /* HAVE_PREAD */
+#ifndef HAVE_PWRITE
+sudo_dso_public ssize_t sudo_pwrite(int fd, const void *buf, size_t nbytes, off_t offset);
+# undef pwrite
+# define pwrite(_a, _b, _c, _d) sudo_pwrite((_a), (_b), (_c), (_d))
+#endif /* HAVE_PWRITE */
+#ifndef HAVE_UNLINKAT
+sudo_dso_public int sudo_unlinkat(int dfd, const char *path, int flag);
+# undef unlinkat
+# define unlinkat(_a, _b, _c) sudo_unlinkat((_a), (_b), (_c))
+#endif /* HAVE_UNLINKAT */
+
+#endif /* SUDO_COMPAT_H */
diff --git a/include/sudo_conf.h b/include/sudo_conf.h
new file mode 100644
index 0000000..866e47d
--- /dev/null
+++ b/include/sudo_conf.h
@@ -0,0 +1,97 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011-2017, 2019-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_CONF_H
+#define SUDO_CONF_H
+
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+
+#include <sudo_queue.h>
+
+/* Flags for sudo_conf_read() */
+#define SUDO_CONF_DEBUG 0x01
+#define SUDO_CONF_PATHS 0x02
+#define SUDO_CONF_PLUGINS 0x04
+#define SUDO_CONF_SETTINGS 0x08
+#define SUDO_CONF_ALL 0x0f
+
+/* Values of sudo_conf_group_source() */
+#define GROUP_SOURCE_ADAPTIVE 0
+#define GROUP_SOURCE_STATIC 1
+#define GROUP_SOURCE_DYNAMIC 2
+
+struct sudo_debug_file;
+TAILQ_HEAD(sudo_conf_debug_file_list, sudo_debug_file);
+
+struct plugin_info {
+ TAILQ_ENTRY(plugin_info) entries;
+ char *path;
+ char *symbol_name;
+ char **options;
+ unsigned int lineno;
+};
+TAILQ_HEAD(plugin_info_list, plugin_info);
+
+struct sudo_conf_debug {
+ TAILQ_ENTRY(sudo_conf_debug) entries;
+ struct sudo_conf_debug_file_list debug_files;
+ char *progname;
+};
+TAILQ_HEAD(sudo_conf_debug_list, sudo_conf_debug);
+
+/* Read main sudo.conf file. */
+sudo_dso_public int sudo_conf_read_v1(const char *conf_file, int conf_types);
+#define sudo_conf_read(_a, _b) sudo_conf_read_v1((_a), (_b))
+
+/* Accessor functions. */
+sudo_dso_public const char *sudo_conf_askpass_path_v1(void);
+sudo_dso_public const char *sudo_conf_sesh_path_v1(void);
+sudo_dso_public const char *sudo_conf_intercept_path_v1(void);
+sudo_dso_public const char *sudo_conf_noexec_path_v1(void);
+sudo_dso_public const char *sudo_conf_plugin_dir_path_v1(void);
+sudo_dso_public const char *sudo_conf_devsearch_path_v1(void);
+sudo_dso_public struct sudo_conf_debug_list *sudo_conf_debugging_v1(void);
+sudo_dso_public struct sudo_conf_debug_file_list *sudo_conf_debug_files_v1(const char *progname);
+sudo_dso_public struct plugin_info_list *sudo_conf_plugins_v1(void);
+sudo_dso_public bool sudo_conf_disable_coredump_v1(void);
+sudo_dso_public bool sudo_conf_developer_mode_v1(void);
+sudo_dso_public bool sudo_conf_probe_interfaces_v1(void);
+sudo_dso_public int sudo_conf_group_source_v1(void);
+sudo_dso_public int sudo_conf_max_groups_v1(void);
+sudo_dso_public void sudo_conf_clear_paths_v1(void);
+#define sudo_conf_askpass_path() sudo_conf_askpass_path_v1()
+#define sudo_conf_sesh_path() sudo_conf_sesh_path_v1()
+#define sudo_conf_intercept_path() sudo_conf_intercept_path_v1()
+#define sudo_conf_noexec_path() sudo_conf_noexec_path_v1()
+#define sudo_conf_plugin_dir_path() sudo_conf_plugin_dir_path_v1()
+#define sudo_conf_devsearch_path() sudo_conf_devsearch_path_v1()
+#define sudo_conf_debugging() sudo_conf_debugging_v1()
+#define sudo_conf_debug_files(_a) sudo_conf_debug_files_v1((_a))
+#define sudo_conf_plugins() sudo_conf_plugins_v1()
+#define sudo_conf_disable_coredump() sudo_conf_disable_coredump_v1()
+#define sudo_conf_developer_mode() sudo_conf_developer_mode_v1()
+#define sudo_conf_probe_interfaces() sudo_conf_probe_interfaces_v1()
+#define sudo_conf_group_source() sudo_conf_group_source_v1()
+#define sudo_conf_max_groups() sudo_conf_max_groups_v1()
+#define sudo_conf_clear_paths() sudo_conf_clear_paths_v1()
+
+#endif /* SUDO_CONF_H */
diff --git a/include/sudo_debug.h b/include/sudo_debug.h
new file mode 100644
index 0000000..b8b2d6c
--- /dev/null
+++ b/include/sudo_debug.h
@@ -0,0 +1,435 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011-2017 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_DEBUG_H
+#define SUDO_DEBUG_H
+
+#include <sys/types.h> /* for id_t, mode_t, size_t, ssize_t, time_t */
+#include <stdarg.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <sudo_queue.h>
+
+/*
+ * List of debug files and flags for use in registration.
+ */
+struct sudo_debug_file {
+ TAILQ_ENTRY(sudo_debug_file) entries;
+ char *debug_file;
+ char *debug_flags;
+};
+struct sudo_conf_debug_file_list;
+
+/*
+ * The priority and subsystem are encoded in a single 32-bit value.
+ * The lower 4 bits are the priority and the top 26 bits are the subsystem.
+ * This allows for 16 priorities and a very large number of subsystems.
+ * Bit 5 is used as a flag to specify whether to log the errno value.
+ * Bit 6 specifies whether to log the function, file and line number data.
+ */
+
+/*
+ * Sudo debug priorities, ordered least to most verbose,
+ * in other words, highest to lowest priority. Max pri is 15.
+ * Note: order must match sudo_debug_priorities[]
+ */
+#define SUDO_DEBUG_CRIT 1 /* critical errors */
+#define SUDO_DEBUG_ERROR 2 /* non-critical errors */
+#define SUDO_DEBUG_WARN 3 /* non-fatal warnings */
+#define SUDO_DEBUG_NOTICE 4 /* non-error condition notices */
+#define SUDO_DEBUG_DIAG 5 /* diagnostic messages */
+#define SUDO_DEBUG_INFO 6 /* informational message */
+#define SUDO_DEBUG_TRACE 7 /* log function enter/exit */
+#define SUDO_DEBUG_DEBUG 8 /* very verbose debugging */
+
+/* Flag to include string version of errno in debug info. */
+#define SUDO_DEBUG_ERRNO (1<<4)
+
+/* Flag to include function, file and line number in debug info. */
+#define SUDO_DEBUG_LINENO (1<<5)
+
+/*
+ * Sudo debug subsystems.
+ * This includes subsystems in the sudoers plugin.
+ * Note: order must match sudo_debug_subsystems[]
+ */
+#define SUDO_DEBUG_ARGS ( 1<<6) /* command line argument handling */
+#define SUDO_DEBUG_CONV ( 2<<6) /* user conversation */
+#define SUDO_DEBUG_EDIT ( 3<<6) /* sudoedit */
+#define SUDO_DEBUG_EVENT ( 4<<6) /* event handling */
+#define SUDO_DEBUG_EXEC ( 5<<6) /* command execution */
+#define SUDO_DEBUG_HOOKS ( 6<<6) /* hook functions */
+#define SUDO_DEBUG_MAIN ( 7<<6) /* sudo main() */
+#define SUDO_DEBUG_NETIF ( 8<<6) /* network interface functions */
+#define SUDO_DEBUG_PCOMM ( 9<<6) /* plugin communications */
+#define SUDO_DEBUG_PLUGIN (10<<6) /* main plugin functions */
+#define SUDO_DEBUG_PTY (11<<6) /* pseudo-tty */
+#define SUDO_DEBUG_SELINUX (12<<6) /* selinux */
+#define SUDO_DEBUG_UTIL (13<<6) /* utility functions */
+#define SUDO_DEBUG_UTMP (14<<6) /* utmp file ops */
+#define SUDO_DEBUG_APPARMOR (15<<6) /* AppArmor */
+#define SUDO_DEBUG_ALL 0xffff0000 /* all subsystems */
+
+/* Error return for sudo_debug_register(). */
+#define SUDO_DEBUG_INSTANCE_ERROR -2
+
+/* Initializer for instance index to indicate that debugging is not setup. */
+#define SUDO_DEBUG_INSTANCE_INITIALIZER -1
+
+/* Extract priority number and convert to an index. */
+#define SUDO_DEBUG_PRI(n) (((n) & 0x0f) - 1)
+
+/* Extract subsystem number and convert to an index. */
+#define SUDO_DEBUG_SUBSYS(n) (((n) >> 6) - 1)
+
+/*
+ * Wrapper for sudo_debug_enter() that declares __func__ as needed
+ * and sets sudo_debug_subsys for sudo_debug_exit().
+ */
+#ifdef HAVE___FUNC__
+# define debug_decl_func(funcname)
+# define debug_decl_vars(funcname, subsys) \
+ const unsigned int sudo_debug_subsys = (subsys)
+#else
+# define debug_decl_func(funcname) \
+ const char __func__[] = #funcname;
+# define debug_decl_vars(funcname, subsys) \
+ debug_decl_func(funcname) \
+ const unsigned int sudo_debug_subsys = (subsys)
+#endif
+#define debug_decl(funcname, subsys) \
+ debug_decl_vars((funcname), (subsys)); \
+ sudo_debug_enter(__func__, __FILE__, __LINE__, sudo_debug_subsys)
+
+/*
+ * Different flavors of sudo_debug_exit() macros.
+ */
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+# define sudo_debug_enter(_func, _file, _line, _sys) \
+ do { \
+ sudo_debug_printf2(NULL, NULL, 0, (_sys) | SUDO_DEBUG_TRACE, \
+ "-> %s @ %s:%d", (_func), (_file), (_line)); \
+ } while (0)
+
+# define sudo_debug_exit(_func, _file, _line, _sys) \
+ do { \
+ sudo_debug_printf2(NULL, NULL, 0, (_sys) | SUDO_DEBUG_TRACE, \
+ "<- %s @ %s:%d", (_func), (_file), (_line)); \
+ } while (0)
+
+# define sudo_debug_exit_int(_func, _file, _line, _sys, _ret) \
+ do { \
+ sudo_debug_printf2(NULL, NULL, 0, (_sys) | SUDO_DEBUG_TRACE, \
+ "<- %s @ %s:%d := %d", (_func), (_file), (_line), (_ret)); \
+ } while (0)
+
+# define sudo_debug_exit_uint(_func, _file, _line, _sys, _ret) \
+ do { \
+ sudo_debug_printf2(NULL, NULL, 0, (_sys) | SUDO_DEBUG_TRACE, \
+ "<- %s @ %s:%d := %u", (_func), (_file), (_line), (_ret)); \
+ } while (0)
+
+# define sudo_debug_exit_long(_func, _file, _line, _sys, _ret) \
+ do { \
+ sudo_debug_printf2(NULL, NULL, 0, (_sys) | SUDO_DEBUG_TRACE, \
+ "<- %s @ %s:%d := %ld", (_func), (_file), (_line), (_ret)); \
+ } while (0)
+
+# if SIZEOF_ID_T == 8
+# define sudo_debug_exit_id_t(_func, _file, _line, _sys, _ret) \
+ do { \
+ sudo_debug_printf2(NULL, NULL, 0, (_sys) | SUDO_DEBUG_TRACE, \
+ "<- %s @ %s:%d := %lld", (_func), (_file), (_line), (long long)(_ret));\
+ } while (0)
+# else
+# define sudo_debug_exit_id_t(_func, _file, _line, _sys, _ret) \
+ do { \
+ sudo_debug_printf2(NULL, NULL, 0, (_sys) | SUDO_DEBUG_TRACE, \
+ "<- %s @ %s:%d := %d", (_func), (_file), (_line), (int)(_ret)); \
+ } while (0)
+# endif
+
+# define sudo_debug_exit_size_t(_func, _file, _line, _sys, _ret) \
+ do { \
+ sudo_debug_printf2(NULL, NULL, 0, (_sys) | SUDO_DEBUG_TRACE, \
+ "<- %s @ %s:%d := %zu", (_func), (_file), (_line), (_ret)); \
+ } while (0)
+
+# define sudo_debug_exit_ssize_t(_func, _file, _line, _sys, _ret) \
+ do { \
+ sudo_debug_printf2(NULL, NULL, 0, (_sys) | SUDO_DEBUG_TRACE, \
+ "<- %s @ %s:%d := %zd", (_func), (_file), (_line), (_ret)); \
+ } while (0)
+
+# if SIZEOF_TIME_T == 8
+# define sudo_debug_exit_time_t(_func, _file, _line, _sys, _ret) \
+ do { \
+ sudo_debug_printf2(NULL, NULL, 0, (_sys) | SUDO_DEBUG_TRACE, \
+ "<- %s @ %s:%d := %lld", (_func), (_file), (_line), (long long)(_ret));\
+ } while (0)
+# else
+# define sudo_debug_exit_time_t(_func, _file, _line, _sys, _ret) \
+ do { \
+ sudo_debug_printf2(NULL, NULL, 0, (_sys) | SUDO_DEBUG_TRACE, \
+ "<- %s @ %s:%d := %d", (_func), (_file), (_line), (int)(_ret)); \
+ } while (0)
+# endif
+
+# define sudo_debug_exit_mode_t(_func, _file, _line, _sys, _ret) \
+ do { \
+ sudo_debug_printf2(NULL, NULL, 0, (_sys) | SUDO_DEBUG_TRACE, \
+ "<- %s @ %s:%d := %d", (_func), (_file), (_line), (int)(_ret)); \
+ } while (0)
+
+# define sudo_debug_exit_bool(_func, _file, _line, _sys, _ret) \
+ do { \
+ sudo_debug_printf2(NULL, NULL, 0, (_sys) | SUDO_DEBUG_TRACE, \
+ "<- %s @ %s:%d := %s", (_func), (_file), (_line), (_ret) ? "true": "false");\
+ } while (0)
+
+# define sudo_debug_exit_str(_func, _file, _line, _sys, _ret) \
+ do { \
+ sudo_debug_printf2(NULL, NULL, 0, (_sys) | SUDO_DEBUG_TRACE, \
+ "<- %s @ %s:%d := %s", (_func), (_file), (_line), (_ret) ? (_ret) : "(null)");\
+ } while (0)
+
+# define sudo_debug_exit_str_masked(_func, _file, _line, _sys, _ret) \
+ do { \
+ const char _stars[] = "********************************************************************************"; \
+ const size_t _len = (_ret) ? strlen(_ret) : sizeof("(null)") - 1; \
+ const char *_s = (_ret) ? _stars : "(null)"; \
+ sudo_debug_printf2(NULL, NULL, 0, (_sys) | SUDO_DEBUG_TRACE, \
+ "<- %s @ %s:%d := %.*s", (_func), (_file), (_line), (int)_len, _s);\
+ } while (0)
+
+# define sudo_debug_exit_ptr(_func, _file, _line, _sys, _ret) \
+ do { \
+ sudo_debug_printf2(NULL, NULL, 0, (_sys) | SUDO_DEBUG_TRACE, \
+ "<- %s @ %s:%d := %p", (_func), (_file), (_line), (_ret)); \
+ } while (0)
+#else /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
+# define sudo_debug_enter(_a, _b, _c, _d) ((void)&(_d))
+# define sudo_debug_exit(_a, _b, _c, _d) ((void)&(_d))
+# define sudo_debug_exit_int(_a, _b, _c, _d, _e) ((void)&(_d))
+# define sudo_debug_exit_uint(_a, _b, _c, _d, _e) ((void)&(_d))
+# define sudo_debug_exit_long(_a, _b, _c, _d, _e) ((void)&(_d))
+# define sudo_debug_exit_id_t(_a, _b, _c, _d, _e) ((void)&(_d))
+# define sudo_debug_exit_size_t(_a, _b, _c, _d, _e) ((void)&(_d))
+# define sudo_debug_exit_ssize_t(_a, _b, _c, _d, _e) ((void)&(_d))
+# define sudo_debug_exit_time_t(_a, _b, _c, _d, _e) ((void)&(_d))
+# define sudo_debug_exit_mode_t(_a, _b, _c, _d, _e) ((void)&(_d))
+# define sudo_debug_exit_bool(_a, _b, _c, _d, _e) ((void)&(_d))
+# define sudo_debug_exit_str(_a, _b, _c, _d, _e) ((void)&(_d))
+# define sudo_debug_exit_str_masked(_a, _b, _c, _d, _e) ((void)&(_d))
+# define sudo_debug_exit_ptr(_a, _b, _c, _d, _e) ((void)&(_d))
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
+
+/*
+ * Wrappers for sudo_debug_exit() and friends.
+ */
+#define debug_return \
+ do { \
+ sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys); \
+ return; \
+ } while (0)
+
+#define debug_return_int(ret) \
+ do { \
+ int sudo_debug_ret = (ret); \
+ sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, \
+ sudo_debug_ret); \
+ return sudo_debug_ret; \
+ } while (0)
+
+#define debug_return_uint(ret) \
+ do { \
+ unsigned int sudo_debug_ret = (ret); \
+ sudo_debug_exit_uint(__func__, __FILE__, __LINE__, sudo_debug_subsys, \
+ sudo_debug_ret); \
+ return sudo_debug_ret; \
+ } while (0)
+
+#define debug_return_id_t(ret) \
+ do { \
+ id_t sudo_debug_ret = (ret); \
+ sudo_debug_exit_id_t(__func__, __FILE__, __LINE__, sudo_debug_subsys,\
+ sudo_debug_ret); \
+ return sudo_debug_ret; \
+ } while (0)
+
+#define debug_return_size_t(ret) \
+ do { \
+ size_t sudo_debug_ret = (ret); \
+ sudo_debug_exit_size_t(__func__, __FILE__, __LINE__, sudo_debug_subsys,\
+ sudo_debug_ret); \
+ return sudo_debug_ret; \
+ } while (0)
+
+#define debug_return_ssize_t(ret) \
+ do { \
+ ssize_t sudo_debug_ret = (ret); \
+ sudo_debug_exit_ssize_t(__func__, __FILE__, __LINE__, sudo_debug_subsys,\
+ sudo_debug_ret); \
+ return sudo_debug_ret; \
+ } while (0)
+
+#define debug_return_time_t(ret) \
+ do { \
+ time_t sudo_debug_ret = (ret); \
+ sudo_debug_exit_time_t(__func__, __FILE__, __LINE__, sudo_debug_subsys,\
+ sudo_debug_ret); \
+ return sudo_debug_ret; \
+ } while (0)
+
+#define debug_return_mode_t(ret) \
+ do { \
+ mode_t sudo_debug_ret = (ret); \
+ sudo_debug_exit_mode_t(__func__, __FILE__, __LINE__, sudo_debug_subsys,\
+ sudo_debug_ret); \
+ return sudo_debug_ret; \
+ } while (0)
+
+#define debug_return_long(ret) \
+ do { \
+ long sudo_debug_ret = (ret); \
+ sudo_debug_exit_long(__func__, __FILE__, __LINE__, sudo_debug_subsys, \
+ sudo_debug_ret); \
+ return sudo_debug_ret; \
+ } while (0)
+
+#define debug_return_bool(ret) \
+ do { \
+ bool sudo_debug_ret = (ret); \
+ sudo_debug_exit_bool(__func__, __FILE__, __LINE__, sudo_debug_subsys, \
+ sudo_debug_ret); \
+ return sudo_debug_ret; \
+ } while (0)
+
+#define debug_return_str(ret) \
+ do { \
+ char *sudo_debug_ret = (ret); \
+ sudo_debug_exit_str(__func__, __FILE__, __LINE__, sudo_debug_subsys, \
+ sudo_debug_ret); \
+ return sudo_debug_ret; \
+ } while (0)
+
+#define debug_return_const_str(ret) \
+ do { \
+ const char *sudo_debug_ret = (ret); \
+ sudo_debug_exit_str(__func__, __FILE__, __LINE__, sudo_debug_subsys, \
+ sudo_debug_ret); \
+ return sudo_debug_ret; \
+ } while (0)
+
+#define debug_return_str_masked(ret) \
+ do { \
+ char *sudo_debug_ret = (ret); \
+ sudo_debug_exit_str_masked(__func__, __FILE__, __LINE__, \
+ sudo_debug_subsys, sudo_debug_ret); \
+ return sudo_debug_ret; \
+ } while (0)
+
+#define debug_return_ptr(ret) \
+ do { \
+ void *sudo_debug_ret = (ret); \
+ sudo_debug_exit_ptr(__func__, __FILE__, __LINE__, sudo_debug_subsys, \
+ sudo_debug_ret); \
+ return sudo_debug_ret; \
+ } while (0)
+
+#define debug_return_const_ptr(ret) \
+ do { \
+ const void *sudo_debug_ret = (ret); \
+ sudo_debug_exit_ptr(__func__, __FILE__, __LINE__, sudo_debug_subsys, \
+ sudo_debug_ret); \
+ return sudo_debug_ret; \
+ } while (0)
+
+/*
+ * Variadic macros are a C99 feature but GNU cpp has supported
+ * a (different) version of them for a long time.
+ */
+#if defined(NO_VARIADIC_MACROS)
+# define sudo_debug_printf sudo_debug_printf_nvm
+#elif defined(__GNUC__) && __GNUC__ == 2
+# define sudo_debug_printf(pri, fmt...) \
+ sudo_debug_printf2(__func__, __FILE__, __LINE__, (pri)|sudo_debug_subsys, \
+ fmt)
+#else
+# define sudo_debug_printf(pri, ...) \
+ sudo_debug_printf2(__func__, __FILE__, __LINE__, (pri)|sudo_debug_subsys, \
+ __VA_ARGS__)
+#endif
+
+#define sudo_debug_execve(pri, path, argv, envp) \
+ sudo_debug_execve2((pri)|sudo_debug_subsys, (path), (argv), (envp))
+
+#define sudo_debug_write(fd, str, len, errnum) \
+ sudo_debug_write2(fd, NULL, NULL, 0, (str), (len), (errnum))
+
+sudo_dso_public int sudo_debug_deregister_v1(int instance_id);
+sudo_dso_public void sudo_debug_enter_v1(const char *func, const char *file, int line, unsigned int subsys);
+sudo_dso_public void sudo_debug_execve2_v1(unsigned int level, const char *path, char *const argv[], char *const envp[]);
+sudo_dso_public void sudo_debug_exit_v1(const char *func, const char *file, int line, unsigned int subsys);
+sudo_dso_public void sudo_debug_exit_bool_v1(const char *func, const char *file, int line, unsigned int subsys, bool ret);
+sudo_dso_public void sudo_debug_exit_int_v1(const char *func, const char *file, int line, unsigned int subsys, int ret);
+sudo_dso_public void sudo_debug_exit_uint_v1(const char *func, const char *file, int line, unsigned int subsys, unsigned int ret);
+sudo_dso_public void sudo_debug_exit_long_v1(const char *func, const char *file, int line, unsigned int subsys, long ret);
+sudo_dso_public void sudo_debug_exit_ptr_v1(const char *func, const char *file, int line, unsigned int subsys, const void *ret);
+sudo_dso_public void sudo_debug_exit_id_t_v1(const char *func, const char *file, int line, unsigned int subsys, id_t ret);
+sudo_dso_public void sudo_debug_exit_size_t_v1(const char *func, const char *file, int line, unsigned int subsys, size_t ret);
+sudo_dso_public void sudo_debug_exit_ssize_t_v1(const char *func, const char *file, int line, unsigned int subsys, ssize_t ret);
+sudo_dso_public void sudo_debug_exit_str_v1(const char *func, const char *file, int line, unsigned int subsys, const char *ret);
+sudo_dso_public void sudo_debug_exit_str_masked_v1(const char *func, const char *file, int line, unsigned int subsys, const char *ret);
+sudo_dso_public void sudo_debug_exit_time_t_v1(const char *func, const char *file, int line, unsigned int subsys, time_t ret);
+sudo_dso_public void sudo_debug_exit_mode_t_v1(const char *func, const char *file, int line, unsigned int subsys, mode_t ret);
+sudo_dso_public pid_t sudo_debug_fork_v1(void);
+sudo_dso_public int sudo_debug_get_active_instance_v1(void);
+sudo_dso_public int sudo_debug_get_fds_v1(unsigned char **fds);
+sudo_dso_public int sudo_debug_get_instance_v1(const char *program);
+sudo_dso_public int sudo_debug_parse_flags_v1(struct sudo_conf_debug_file_list *debug_files, const char *entry);
+sudo_dso_public void sudo_debug_printf2_v1(const char *func, const char *file, int line, unsigned int level, const char * restrict fmt, ...) sudo_printf0like(5, 6);
+sudo_dso_public void sudo_debug_printf_nvm_v1(int pri, const char * restrict fmt, ...) sudo_printf0like(2, 3);
+sudo_dso_public int sudo_debug_register_v1(const char *program, const char *const subsystems[], unsigned int ids[], struct sudo_conf_debug_file_list *debug_files);
+sudo_dso_public int sudo_debug_register_v2(const char *program, const char *const subsystems[], unsigned int ids[], struct sudo_conf_debug_file_list *debug_files, int minfd);
+sudo_dso_public int sudo_debug_set_active_instance_v1(int inst);
+sudo_dso_public void sudo_debug_update_fd_v1(int ofd, int nfd);
+sudo_dso_public void sudo_debug_vprintf2_v1(const char *func, const char *file, int line, unsigned int level, const char * restrict fmt, va_list ap) sudo_printf0like(5, 0);
+sudo_dso_public void sudo_debug_write2_v1(int fd, const char *func, const char *file, int line, const char *str, unsigned int len, int errnum);
+sudo_dso_public bool sudo_debug_needed_v1(unsigned int level);
+
+#define sudo_debug_needed(level) sudo_debug_needed_v1((level)|sudo_debug_subsys)
+#define sudo_debug_deregister(_a) sudo_debug_deregister_v1((_a))
+#define sudo_debug_execve2(_a, _b, _c, _d) sudo_debug_execve2_v1((_a), (_b), (_c), (_d))
+#define sudo_debug_fork() sudo_debug_fork_v1()
+#define sudo_debug_get_active_instance() sudo_debug_get_active_instance_v1()
+#define sudo_debug_get_fds(_a) sudo_debug_get_fds_v1((_a))
+#define sudo_debug_get_instance(_a) sudo_debug_get_instance_v1((_a))
+#define sudo_debug_parse_flags(_a, _b) sudo_debug_parse_flags_v1((_a), (_b))
+#define sudo_debug_printf2 sudo_debug_printf2_v1
+#define sudo_debug_printf_nvm sudo_debug_printf_nvm_v1
+#define sudo_debug_register(_a, _b, _c, _d, _e) sudo_debug_register_v2((_a), (_b), (_c), (_d), (_e))
+#define sudo_debug_set_active_instance(_a) sudo_debug_set_active_instance_v1((_a))
+#define sudo_debug_update_fd(_a, _b) sudo_debug_update_fd_v1((_a), (_b))
+#define sudo_debug_vprintf2(_a, _b, _c, _d, _e, _f) sudo_debug_vprintf2_v1((_a), (_b), (_c), (_d), (_e), (_f))
+#define sudo_debug_write2(_a, _b, _c, _d, _e, _f, _g) sudo_debug_write2_v1((_a), (_b), (_c), (_d), (_e), (_f), (_g))
+
+#endif /* SUDO_DEBUG_H */
diff --git a/include/sudo_digest.h b/include/sudo_digest.h
new file mode 100644
index 0000000..0e7f8ef
--- /dev/null
+++ b/include/sudo_digest.h
@@ -0,0 +1,47 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_DIGEST_H
+#define SUDO_DIGEST_H
+
+/* Digest types. */
+#define SUDO_DIGEST_SHA224 0
+#define SUDO_DIGEST_SHA256 1
+#define SUDO_DIGEST_SHA384 2
+#define SUDO_DIGEST_SHA512 3
+#define SUDO_DIGEST_INVALID 4
+
+struct sudo_digest;
+
+/* Public functions. */
+sudo_dso_public struct sudo_digest *sudo_digest_alloc_v1(unsigned int digest_type);
+sudo_dso_public void sudo_digest_free_v1(struct sudo_digest *dig);
+sudo_dso_public void sudo_digest_reset_v1(struct sudo_digest *dig);
+sudo_dso_public int sudo_digest_getlen_v1(unsigned int digest_type);
+sudo_dso_public size_t sudo_digest_getlen_v2(unsigned int digest_type);
+sudo_dso_public void sudo_digest_update_v1(struct sudo_digest *dig, const void *data, size_t len);
+sudo_dso_public void sudo_digest_final_v1(struct sudo_digest *dig, unsigned char *md);
+
+#define sudo_digest_alloc(_a) sudo_digest_alloc_v1((_a))
+#define sudo_digest_free(_a) sudo_digest_free_v1((_a))
+#define sudo_digest_reset(_a) sudo_digest_reset_v1((_a))
+#define sudo_digest_getlen(_a) sudo_digest_getlen_v2((_a))
+#define sudo_digest_update(_a, _b, _c) sudo_digest_update_v1((_a), (_b), (_c))
+#define sudo_digest_final(_a, _b) sudo_digest_final_v1((_a), (_b))
+
+#endif /* SUDO_DIGEST_H */
diff --git a/include/sudo_dso.h b/include/sudo_dso.h
new file mode 100644
index 0000000..c2e1aaf
--- /dev/null
+++ b/include/sudo_dso.h
@@ -0,0 +1,57 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010, 2013, 2014 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_DSO_H
+#define SUDO_DSO_H
+
+/* Values for sudo_dso_load() mode. */
+#define SUDO_DSO_LAZY 0x1
+#define SUDO_DSO_NOW 0x2
+#define SUDO_DSO_GLOBAL 0x4
+#define SUDO_DSO_LOCAL 0x8
+
+/* Special handle arguments for sudo_dso_findsym(). */
+#define SUDO_DSO_NEXT ((void *)-1) /* Search subsequent objects. */
+#define SUDO_DSO_DEFAULT ((void *)-2) /* Use default search algorithm. */
+#define SUDO_DSO_SELF ((void *)-3) /* Search the caller itself. */
+
+/* Internal structs for static linking of plugins. */
+struct sudo_preload_symbol {
+ const char *name;
+ void *addr;
+};
+struct sudo_preload_table {
+ const char *path;
+ void *handle;
+ struct sudo_preload_symbol *symbols;
+};
+
+/* Public functions. */
+sudo_dso_public char *sudo_dso_strerror_v1(void);
+sudo_dso_public int sudo_dso_unload_v1(void *handle);
+sudo_dso_public void *sudo_dso_findsym_v1(void *handle, const char *symbol);
+sudo_dso_public void *sudo_dso_load_v1(const char *path, int mode);
+sudo_dso_public void sudo_dso_preload_table_v1(struct sudo_preload_table *table);
+
+#define sudo_dso_strerror() sudo_dso_strerror_v1()
+#define sudo_dso_unload(_a) sudo_dso_unload_v1((_a))
+#define sudo_dso_findsym(_a, _b) sudo_dso_findsym_v1((_a), (_b))
+#define sudo_dso_load(_a, _b) sudo_dso_load_v1((_a), (_b))
+#define sudo_dso_preload_table(_a) sudo_dso_preload_table_v1((_a))
+
+#endif /* SUDO_DSO_H */
diff --git a/include/sudo_event.h b/include/sudo_event.h
new file mode 100644
index 0000000..27985c4
--- /dev/null
+++ b/include/sudo_event.h
@@ -0,0 +1,216 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2015, 2017 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_EVENT_H
+#define SUDO_EVENT_H
+
+#include <time.h> /* for struct timespec */
+#include <signal.h> /* for sigatomic_t and NSIG */
+#include <sudo_queue.h>
+
+struct timeval; /* for deprecated APIs */
+
+/* Event types (keep in sync with sudo_plugin.h) */
+#define SUDO_EV_TIMEOUT 0x01 /* fire after timeout */
+#define SUDO_EV_READ 0x02 /* fire when readable */
+#define SUDO_EV_WRITE 0x04 /* fire when writable */
+#define SUDO_EV_PERSIST 0x08 /* persist until deleted */
+#define SUDO_EV_SIGNAL 0x10 /* fire on signal receipt */
+#define SUDO_EV_SIGINFO 0x20 /* fire on signal receipt (siginfo) */
+
+/* User-settable events for sudo_ev_init() (SUDO_EV_TIMEOUT not valid here) */
+#define SUDO_EV_MASK (SUDO_EV_READ|SUDO_EV_WRITE|SUDO_EV_PERSIST|SUDO_EV_SIGNAL|SUDO_EV_SIGINFO)
+
+/* Event flags (internal) */
+#define SUDO_EVQ_INSERTED 0x01U /* event is on the event queue */
+#define SUDO_EVQ_ACTIVE 0x02U /* event is on the active queue */
+#define SUDO_EVQ_TIMEOUTS 0x04U /* event is on the timeouts queue */
+
+/* Event loop flags */
+#define SUDO_EVLOOP_ONCE 0x01U /* Only run once through the loop */
+#define SUDO_EVLOOP_NONBLOCK 0x02U /* Do not block in event loop */
+
+/* Event base flags (internal) */
+#define SUDO_EVBASE_LOOPONCE SUDO_EVLOOP_ONCE
+#define SUDO_EVBASE_LOOPEXIT 0x02U
+#define SUDO_EVBASE_LOOPBREAK 0x04U
+#define SUDO_EVBASE_LOOPCONT 0x08U
+#define SUDO_EVBASE_GOT_EXIT 0x10U
+#define SUDO_EVBASE_GOT_BREAK 0x20U
+#define SUDO_EVBASE_GOT_MASK 0xf0U
+
+/* Must match sudo_plugin_ev_callback_t in sudo_plugin.h */
+typedef void (*sudo_ev_callback_t)(int fd, int what, void *closure);
+
+/*
+ * Container for SUDO_EV_SIGINFO events that gets passed as the closure
+ * pointer. This allows us to pass a siginfo_t without changing everything.
+ */
+struct sudo_ev_siginfo_container {
+ void *closure;
+ siginfo_t *siginfo;
+ char si_buf[];
+};
+
+/* Member of struct sudo_event_base. */
+struct sudo_event {
+ TAILQ_ENTRY(sudo_event) entries;
+ TAILQ_ENTRY(sudo_event) active_entries;
+ TAILQ_ENTRY(sudo_event) timeouts_entries;
+ struct sudo_event_base *base; /* base this event belongs to */
+ int fd; /* fd/signal we are interested in */
+ short events; /* SUDO_EV_* flags (in) */
+ short revents; /* SUDO_EV_* flags (out) */
+ unsigned short flags; /* internal event flags */
+ short pfd_idx; /* index into pfds array (XXX) */
+ sudo_ev_callback_t callback;/* user-provided callback */
+ struct timespec timeout; /* for SUDO_EV_TIMEOUT */
+ void *closure; /* user-provided data pointer */
+};
+TAILQ_HEAD(sudo_event_list, sudo_event);
+
+struct sudo_event_base {
+ struct sudo_event_list events; /* tail queue of all events */
+ struct sudo_event_list active; /* tail queue of active events */
+ struct sudo_event_list timeouts; /* tail queue of timeout events */
+ struct sudo_event signal_event; /* storage for signal pipe event */
+ struct sudo_event_list signals[NSIG]; /* array of signal event tail queues */
+ struct sigaction *orig_handlers[NSIG]; /* original signal handlers */
+ siginfo_t *siginfo[NSIG]; /* detailed signal info */
+ sig_atomic_t signal_pending[NSIG]; /* pending signals */
+ sig_atomic_t signal_caught; /* at least one signal caught */
+ int num_handlers; /* number of installed handlers */
+ int signal_pipe[2]; /* so we can wake up on signal */
+#if defined(HAVE_POLL) || defined(HAVE_PPOLL)
+ struct pollfd *pfds; /* array of struct pollfd */
+ int pfd_max; /* size of the pfds array */
+ int pfd_high; /* highest slot used */
+ int pfd_free; /* idx of next free entry or pfd_max if full */
+#else
+ void *readfds_in; /* read I/O descriptor set (in) */
+ void *writefds_in; /* write I/O descriptor set (in) */
+ void *readfds_out; /* read I/O descriptor set (out) */
+ void *writefds_out; /* write I/O descriptor set (out) */
+ int maxfd; /* max fd we can store in readfds/writefds */
+ int highfd; /* highest fd to pass as 1st arg to select */
+#endif /* HAVE_POLL */
+ unsigned int flags; /* SUDO_EVBASE_* */
+};
+
+/* Allocate a new event base. */
+sudo_dso_public struct sudo_event_base *sudo_ev_base_alloc_v1(void);
+#define sudo_ev_base_alloc() sudo_ev_base_alloc_v1()
+
+/* Free an event base. */
+sudo_dso_public void sudo_ev_base_free_v1(struct sudo_event_base *base);
+#define sudo_ev_base_free(_a) sudo_ev_base_free_v1((_a))
+
+/* Set the default event base. */
+sudo_dso_public void sudo_ev_base_setdef_v1(struct sudo_event_base *base);
+#define sudo_ev_base_setdef(_a) sudo_ev_base_setdef_v1((_a))
+
+/* Allocate a new event. */
+sudo_dso_public struct sudo_event *sudo_ev_alloc_v1(int fd, short events, sudo_ev_callback_t callback, void *closure);
+sudo_dso_public struct sudo_event *sudo_ev_alloc_v2(int fd, int events, sudo_ev_callback_t callback, void *closure);
+#define sudo_ev_alloc(_a, _b, _c, _d) sudo_ev_alloc_v2((_a), (_b), (_c), (_d))
+
+/* Free an event. */
+sudo_dso_public void sudo_ev_free_v1(struct sudo_event *ev);
+#define sudo_ev_free(_a) sudo_ev_free_v1((_a))
+
+/* Set an event struct that was pre-allocated. */
+sudo_dso_public int sudo_ev_set_v1(struct sudo_event *ev, int fd, short events, sudo_ev_callback_t callback, void *closure);
+sudo_dso_public int sudo_ev_set_v2(struct sudo_event *ev, int fd, int events, sudo_ev_callback_t callback, void *closure);
+#define sudo_ev_set(_a, _b, _c, _d, _e) sudo_ev_set_v2((_a), (_b), (_c), (_d), (_e))
+
+/* Add an event, returns 0 on success, -1 on error */
+sudo_dso_public int sudo_ev_add_v1(struct sudo_event_base *head, struct sudo_event *ev, const struct timeval *timo, bool tohead);
+sudo_dso_public int sudo_ev_add_v2(struct sudo_event_base *head, struct sudo_event *ev, const struct timespec *timo, bool tohead);
+#define sudo_ev_add(_a, _b, _c, _d) sudo_ev_add_v2((_a), (_b), (_c), (_d))
+
+/* Delete an event, returns 0 on success, -1 on error */
+sudo_dso_public int sudo_ev_del_v1(struct sudo_event_base *head, struct sudo_event *ev);
+#define sudo_ev_del(_a, _b) sudo_ev_del_v1((_a), (_b))
+
+/* Dispatch events, returns SUDO_CB_SUCCESS, SUDO_CB_BREAK or SUDO_CB_ERROR */
+sudo_dso_public int sudo_ev_dispatch_v1(struct sudo_event_base *head);
+#define sudo_ev_dispatch(_a) sudo_ev_dispatch_v1((_a))
+
+/* Main event loop, returns SUDO_CB_SUCCESS, SUDO_CB_BREAK or SUDO_CB_ERROR */
+sudo_dso_public int sudo_ev_loop_v1(struct sudo_event_base *head, unsigned int flags);
+#define sudo_ev_loop(_a, _b) sudo_ev_loop_v1((_a), (_b))
+
+/* Return pending event types, fills in ts if non-NULL and there is a timeout */
+sudo_dso_public int sudo_ev_pending_v1(struct sudo_event *ev, short events, struct timespec *ts);
+sudo_dso_public int sudo_ev_pending_v2(struct sudo_event *ev, int events, struct timespec *ts);
+#define sudo_ev_pending(_a, _b, _c) sudo_ev_pending_v2((_a), (_b), (_c))
+
+/* Return the remaining timeout associated with an event (deprecated). */
+sudo_dso_public int sudo_ev_get_timeleft_v1(struct sudo_event *ev, struct timeval *tv);
+sudo_dso_public int sudo_ev_get_timeleft_v2(struct sudo_event *ev, struct timespec *tv);
+#define sudo_ev_get_timeleft(_a, _b) sudo_ev_get_timeleft_v2((_a), (_b))
+
+/* Cause the event loop to exit after one run through. */
+sudo_dso_public void sudo_ev_loopexit_v1(struct sudo_event_base *base);
+#define sudo_ev_loopexit(_a) sudo_ev_loopexit_v1((_a))
+
+/* Break out of the event loop right now. */
+sudo_dso_public void sudo_ev_loopbreak_v1(struct sudo_event_base *base);
+#define sudo_ev_loopbreak(_a) sudo_ev_loopbreak_v1((_a))
+
+/* Rescan for events and restart the event loop. */
+sudo_dso_public void sudo_ev_loopcontinue_v1(struct sudo_event_base *base);
+#define sudo_ev_loopcontinue(_a) sudo_ev_loopcontinue_v1((_a))
+
+/* Returns true if event loop stopped due to sudo_ev_loopexit(). */
+sudo_dso_public bool sudo_ev_got_exit_v1(struct sudo_event_base *base);
+#define sudo_ev_got_exit(_a) sudo_ev_got_exit_v1((_a))
+
+/* Returns true if event loop stopped due to sudo_ev_loopbreak(). */
+sudo_dso_public bool sudo_ev_got_break_v1(struct sudo_event_base *base);
+#define sudo_ev_got_break(_a) sudo_ev_got_break_v1((_a))
+
+/* Return the fd associated with an event. */
+#define sudo_ev_get_fd(_ev) ((_ev) ? (_ev)->fd : -1)
+
+/* Return the (absolute) timeout associated with an event or NULL. */
+#define sudo_ev_get_timeout(_ev) \
+ (ISSET((_ev)->flags, SUDO_EVQ_TIMEOUTS) ? &(_ev)->timeout : NULL)
+
+/* Return the base an event is associated with or NULL. */
+#define sudo_ev_get_base(_ev) ((_ev) ? (_ev)->base : NULL)
+
+/* Set the base an event is associated with. */
+#define sudo_ev_set_base(_ev, _b) ((_ev)->base = (_b))
+
+/* Magic pointer value to use self pointer as callback arg. */
+#define sudo_ev_self_cbarg() ((void *)-1)
+
+/* Add an event to the base's active queue and mark it active (internal). */
+void sudo_ev_activate(struct sudo_event_base *base, struct sudo_event *ev);
+
+/*
+ * Backend implementation.
+ */
+int sudo_ev_base_alloc_impl(struct sudo_event_base *base);
+void sudo_ev_base_free_impl(struct sudo_event_base *base);
+int sudo_ev_add_impl(struct sudo_event_base *base, struct sudo_event *ev);
+int sudo_ev_del_impl(struct sudo_event_base *base, struct sudo_event *ev);
+int sudo_ev_scan_impl(struct sudo_event_base *base, unsigned int flags);
+
+#endif /* SUDO_EVENT_H */
diff --git a/include/sudo_eventlog.h b/include/sudo_eventlog.h
new file mode 100644
index 0000000..d19a095
--- /dev/null
+++ b/include/sudo_eventlog.h
@@ -0,0 +1,175 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_EVENTLOG_H
+#define SUDO_EVENTLOG_H
+
+#include <sys/types.h> /* for gid_t, uid_t */
+#include <time.h> /* for struct timespec */
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+
+/* Supported event types. */
+enum event_type {
+ EVLOG_ACCEPT,
+ EVLOG_REJECT,
+ EVLOG_EXIT,
+ EVLOG_ALERT
+};
+
+/* Supported eventlog types (bitmask). */
+#define EVLOG_NONE 0x00
+#define EVLOG_SYSLOG 0x01
+#define EVLOG_FILE 0x02
+
+/* Supported eventlog formats. */
+enum eventlog_format {
+ EVLOG_SUDO,
+ EVLOG_JSON
+};
+
+/* Eventlog flag values. */
+#define EVLOG_RAW 0x01 /* only include message and errstr */
+#define EVLOG_MAIL 0x02 /* mail the log message too */
+#define EVLOG_MAIL_ONLY 0x04 /* only mail the message, no other logging */
+#define EVLOG_CWD 0x08 /* log cwd if no runcwd and use CWD, not PWD */
+
+/*
+ * Maximum number of characters to log per entry. The syslogger
+ * will log this much, after that, it truncates the log line.
+ * We need this here to make sure that we continue with another
+ * syslog(3) call if the internal buffer is more than 1023 characters.
+ */
+#ifndef MAXSYSLOGLEN
+# define MAXSYSLOGLEN 960
+#endif
+
+/*
+ * Indentation level for file-based logs when word wrap is enabled.
+ */
+#define EVENTLOG_INDENT " "
+
+/*
+ * Event log config, used with eventlog_getconf()
+ */
+struct eventlog_config {
+ int type;
+ enum eventlog_format format;
+ size_t file_maxlen;
+ size_t syslog_maxlen;
+ int syslog_acceptpri;
+ int syslog_rejectpri;
+ int syslog_alertpri;
+ uid_t mailuid;
+ bool omit_hostname;
+ const char *logpath;
+ const char *time_fmt;
+ const char *mailerpath;
+ const char *mailerflags;
+ const char *mailfrom;
+ const char *mailto;
+ const char *mailsub;
+ FILE *(*open_log)(int type, const char *);
+ void (*close_log)(int type, FILE *);
+};
+
+/*
+ * Info present in the eventlog file, regardless of format.
+ */
+struct eventlog {
+ char *iolog_path;
+ const char *iolog_file; /* substring of iolog_path, do not free */
+ char *command;
+ char *cwd;
+ char *runchroot;
+ char *runcwd;
+ char *rungroup;
+ char *runuser;
+ char *peeraddr;
+ char *signal_name;
+ char *source;
+ char *submithost;
+ char *submituser;
+ char *submitgroup;
+ char **submitenv;
+ char *ttyname;
+ char **runargv;
+ char **runenv;
+ char **env_add;
+ struct timespec submit_time;
+ struct timespec iolog_offset;
+ struct timespec run_time;
+ int exit_value;
+ int lines;
+ int columns;
+ uid_t runuid;
+ gid_t rungid;
+ bool dumped_core;
+ char sessid[7];
+ char uuid_str[37];
+};
+
+/* Callback from eventlog code to write log info */
+struct json_container;
+struct sudo_lbuf;
+typedef bool (*eventlog_json_callback_t)(struct json_container *, void *);
+
+/* eventlog.c */
+bool eventlog_accept(const struct eventlog *evlog, int flags, eventlog_json_callback_t info_cb, void *info);
+bool eventlog_exit(const struct eventlog *evlog, int flags);
+bool eventlog_alert(const struct eventlog *evlog, int flags, struct timespec *alert_time, const char *reason, const char *errstr);
+bool eventlog_mail(const struct eventlog *evlog, int flags, struct timespec *event_time, const char *reason, const char *errstr, char * const extra[]);
+bool eventlog_reject(const struct eventlog *evlog, int flags, const char *reason, eventlog_json_callback_t info_cb, void *info);
+bool eventlog_store_json(struct json_container *jsonc, const struct eventlog *evlog);
+bool eventlog_store_sudo(int event_type, const struct eventlog *evlog, struct sudo_lbuf *lbuf);
+void eventlog_free(struct eventlog *evlog);
+
+/* eventlog_conf.c */
+void eventlog_set_type(int type);
+void eventlog_set_format(enum eventlog_format format);
+void eventlog_set_syslog_acceptpri(int pri);
+void eventlog_set_syslog_rejectpri(int pri);
+void eventlog_set_syslog_alertpri(int pri);
+void eventlog_set_syslog_maxlen(size_t len);
+void eventlog_set_file_maxlen(size_t len);
+void eventlog_set_mailuid(uid_t uid);
+void eventlog_set_omit_hostname(bool omit_hostname);
+void eventlog_set_logpath(const char *path);
+void eventlog_set_time_fmt(const char *fmt);
+void eventlog_set_mailerpath(const char *path);
+void eventlog_set_mailerflags(const char *mflags);
+void eventlog_set_mailfrom(const char *from_addr);
+void eventlog_set_mailto(const char *to_addr);
+void eventlog_set_mailsub(const char *subject);
+void eventlog_set_open_log(FILE *(*fn)(int type, const char *));
+void eventlog_set_close_log(void (*fn)(int type, FILE *));
+const struct eventlog_config *eventlog_getconf(void);
+
+/* logwrap.c */
+size_t eventlog_writeln(FILE *fp, char *line, size_t len, size_t maxlen);
+
+/* parse_json.c */
+struct eventlog_json_object;
+struct eventlog_json_object *eventlog_json_read(FILE *fp, const char *filename);
+bool eventlog_json_parse(struct eventlog_json_object *object, struct eventlog *evlog);
+void eventlog_json_free(struct eventlog_json_object *root);
+
+#endif /* SUDO_EVENTLOG_H */
diff --git a/include/sudo_fatal.h b/include/sudo_fatal.h
new file mode 100644
index 0000000..194da08
--- /dev/null
+++ b/include/sudo_fatal.h
@@ -0,0 +1,211 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2004, 2010-2015, 2017-2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_FATAL_H
+#define SUDO_FATAL_H
+
+#include <stdarg.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+
+#include <sudo_plugin.h> /* for conversation function */
+
+/* No output to debug files when fuzzing. */
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+# define SUDO_ERROR_WRAP 0
+#endif
+
+/*
+ * We wrap fatal/fatalx and warn/warnx so that the same output can
+ * go to the debug file, if there is one.
+ */
+#if (defined(SUDO_ERROR_WRAP) && SUDO_ERROR_WRAP == 0) || defined(NO_VARIADIC_MACROS)
+# define sudo_fatal sudo_fatal_nodebug_v1
+# define sudo_fatalx sudo_fatalx_nodebug_v1
+# define sudo_gai_fatal sudo_gai_fatal_nodebug_v1
+# define sudo_warn sudo_warn_nodebug_v1
+# define sudo_warnx sudo_warnx_nodebug_v1
+# define sudo_gai_warn sudo_gai_warn_nodebug_v1
+# define sudo_vfatal(fmt, ap) sudo_vfatal_nodebug_v1((fmt), (ap))
+# define sudo_vfatalx(fmt, ap) sudo_vfatalx_nodebug_v1((fmt), (ap))
+# define sudo_gai_vfatal(en, fmt, ap) sudo_vfatal_nodebug_v1((en), (fmt), (ap))
+# define sudo_vwarn(fmt, ap) sudo_vwarn_nodebug_v1((fmt), (ap))
+# define sudo_vwarnx(fmt, ap) sudo_vwarnx_nodebug_v1((fmt), (ap))
+# define sudo_gai_vwarn(en, fmt, ap) sudo_vwarn_nodebug_v1((en), (fmt), (ap))
+#else /* SUDO_ERROR_WRAP */
+# if defined(__GNUC__) && __GNUC__ == 2
+# define sudo_fatal(fmt...) do { \
+ sudo_debug_printf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO|sudo_debug_subsys, \
+ fmt); \
+ sudo_fatal_nodebug_v1(fmt); \
+} while (0)
+# define sudo_fatalx(fmt...) do { \
+ sudo_debug_printf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|sudo_debug_subsys, fmt); \
+ sudo_fatalx_nodebug_v1(fmt); \
+} while (0)
+# define sudo_gai_fatal(en, fmt...) do { \
+ sudo_debug_printf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|sudo_debug_subsys, fmt); \
+ sudo_gai_fatal_nodebug_v1((en), fmt); \
+} while (0)
+# define sudo_warn(fmt...) do { \
+ sudo_debug_printf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO|sudo_debug_subsys, \
+ fmt); \
+ sudo_warn_nodebug_v1(fmt); \
+} while (0)
+# define sudo_warnx(fmt...) do { \
+ sudo_debug_printf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|sudo_debug_subsys, fmt); \
+ sudo_warnx_nodebug_v1(fmt); \
+} while (0)
+# define sudo_gai_warn(en, fmt...) do { \
+ sudo_debug_printf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|sudo_debug_subsys, fmt); \
+ sudo_gai_warn_nodebug_v1((en), fmt); \
+} while (0)
+# else
+# define sudo_fatal(...) do { \
+ sudo_debug_printf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO|sudo_debug_subsys, \
+ __VA_ARGS__); \
+ sudo_fatal_nodebug_v1(__VA_ARGS__); \
+} while (0)
+# define sudo_fatalx(...) do { \
+ sudo_debug_printf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|sudo_debug_subsys, __VA_ARGS__); \
+ sudo_fatalx_nodebug_v1(__VA_ARGS__); \
+} while (0)
+# define sudo_gai_fatal(en, ...) do { \
+ sudo_debug_printf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|sudo_debug_subsys, __VA_ARGS__); \
+ sudo_gai_fatal_nodebug_v1((en), __VA_ARGS__); \
+} while (0)
+# define sudo_warn(...) do { \
+ sudo_debug_printf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO|sudo_debug_subsys, \
+ __VA_ARGS__); \
+ sudo_warn_nodebug_v1(__VA_ARGS__); \
+} while (0)
+# define sudo_warnx(...) do { \
+ sudo_debug_printf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|sudo_debug_subsys, __VA_ARGS__); \
+ sudo_warnx_nodebug_v1(__VA_ARGS__); \
+} while (0)
+# define sudo_gai_warn(en, ...) do { \
+ sudo_debug_printf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|sudo_debug_subsys, __VA_ARGS__); \
+ sudo_gai_warn_nodebug_v1((en), __VA_ARGS__); \
+} while (0)
+# endif /* __GNUC__ == 2 */
+# define sudo_vfatal(fmt, ap) do { \
+ va_list ap2; \
+ va_copy(ap2, (ap)); \
+ sudo_debug_vprintf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO|sudo_debug_subsys, \
+ (fmt), ap2); \
+ sudo_vfatal_nodebug_v1((fmt), (ap)); \
+} while (0)
+# define sudo_vfatalx(fmt, ap) do { \
+ va_list ap2; \
+ va_copy(ap2, (ap)); \
+ sudo_debug_vprintf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|sudo_debug_subsys, (fmt), ap2); \
+ sudo_vfatalx_nodebug_v1((fmt), (ap)); \
+} while (0)
+# define sudo_gai_vfatal(en, fmt, ap) do { \
+ va_list ap2; \
+ va_copy(ap2, (ap)); \
+ sudo_debug_vprintf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|sudo_debug_subsys, (fmt), ap2); \
+ sudo_gai_vfatal_nodebug_v1((en), (fmt), (ap)); \
+} while (0)
+# define sudo_vwarn(fmt, ap) do { \
+ va_list ap2; \
+ va_copy(ap2, (ap)); \
+ sudo_debug_vprintf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO|sudo_debug_subsys, \
+ (fmt), ap2); \
+ sudo_vwarn_nodebug_v1((fmt), (ap)); \
+} while (0)
+# define sudo_vwarnx(fmt, ap) do { \
+ va_list ap2; \
+ va_copy(ap2, (ap)); \
+ sudo_debug_vprintf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|sudo_debug_subsys, (fmt), ap2); \
+ sudo_vwarnx_nodebug_v1((fmt), (ap)); \
+} while (0)
+# define sudo_gai_vwarn(en, fmt, ap) do { \
+ va_list ap2; \
+ va_copy(ap2, (ap)); \
+ sudo_debug_vprintf2(__func__, __FILE__, __LINE__, \
+ SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|sudo_debug_subsys, (fmt), ap2); \
+ sudo_gai_vwarn_nodebug_v1((en), (fmt), (ap)); \
+} while (0)
+#endif /* SUDO_ERROR_WRAP */
+
+typedef void (*sudo_fatal_callback_t)(void);
+typedef bool (*sudo_warn_setlocale_t)(bool, int *);
+
+sudo_dso_public int sudo_fatal_callback_deregister_v1(sudo_fatal_callback_t func);
+sudo_dso_public int sudo_fatal_callback_register_v1(sudo_fatal_callback_t func);
+sudo_dso_public char *sudo_warn_gettext_v1(const char *domainname, const char *msgid) sudo_attr_fmt_arg(2);
+sudo_dso_public void sudo_warn_set_locale_func_v1(sudo_warn_setlocale_t func);
+sudo_noreturn sudo_dso_public void sudo_fatal_nodebug_v1(const char * restrict fmt, ...) sudo_printf0like(1, 2);
+sudo_noreturn sudo_dso_public void sudo_fatalx_nodebug_v1(const char * restrict fmt, ...) sudo_printflike(1, 2);
+sudo_noreturn sudo_dso_public void sudo_gai_fatal_nodebug_v1(int errnum, const char * restrict fmt, ...) sudo_printflike(2, 3);
+sudo_noreturn sudo_dso_public void sudo_vfatal_nodebug_v1(const char * restrict fmt, va_list ap) sudo_printf0like(1, 0);
+sudo_noreturn sudo_dso_public void sudo_vfatalx_nodebug_v1(const char * restrict fmt, va_list ap) sudo_printflike(1, 0);
+sudo_noreturn sudo_dso_public void sudo_gai_vfatal_nodebug_v1(int errnum, const char * restrict fmt, va_list ap) sudo_printflike(2, 0);
+sudo_dso_public void sudo_warn_nodebug_v1(const char * restrict fmt, ...) sudo_printf0like(1, 2);
+sudo_dso_public void sudo_warnx_nodebug_v1(const char * restrict fmt, ...) sudo_printflike(1, 2);
+sudo_dso_public void sudo_gai_warn_nodebug_v1(int errnum, const char * restrict fmt, ...) sudo_printflike(2, 3);
+sudo_dso_public void sudo_vwarn_nodebug_v1(const char * restrict fmt, va_list ap) sudo_printf0like(1, 0);
+sudo_dso_public void sudo_vwarnx_nodebug_v1(const char * restrict fmt, va_list ap) sudo_printflike(1, 0);
+sudo_dso_public void sudo_gai_vwarn_nodebug_v1(int errnum, const char * restrict fmt, va_list ap) sudo_printflike(2, 0);
+sudo_dso_public void sudo_warn_set_conversation_v1(sudo_conv_t conv);
+
+#define sudo_fatal_callback_deregister(_a) sudo_fatal_callback_deregister_v1((_a))
+#define sudo_fatal_callback_register(_a) sudo_fatal_callback_register_v1((_a))
+#define sudo_warn_set_locale_func(_a) sudo_warn_set_locale_func_v1((_a))
+#define sudo_fatal_nodebug sudo_fatal_nodebug_v1
+#define sudo_fatalx_nodebug sudo_fatalx_nodebug_v1
+#define sudo_gai_fatal_nodebug sudo_gai_fatal_nodebug_v1
+#define sudo_vfatal_nodebug(_a, _b) sudo_vfatal_nodebug_v1((_a), (_b))
+#define sudo_vfatalx_nodebug(_a, _b) sudo_vfatalx_nodebug_v1((_a), (_b))
+#define sudo_gai_vfatal_nodebug(_a, _b, _c) sudo_gai_vfatal_nodebug_v1((_a), (_b), (_c))
+#define sudo_warn_nodebug sudo_warn_nodebug_v1
+#define sudo_warnx_nodebug sudo_warnx_nodebug_v1
+#define sudo_gai_warn_nodebug sudo_gai_warn_nodebug_v1
+#define sudo_vwarn_nodebug(_a, _b) sudo_vwarn_nodebug_v1((_a), (_b))
+#define sudo_vwarnx_nodebug(_a, _b) sudo_vwarnx_nodebug_v1((_a), (_b))
+#define sudo_gai_vwarn_nodebug(_a, _b, _c) sudo_gai_vwarn_nodebug_v1((_a), (_b), (_c))
+#define sudo_warn_set_conversation(_a) sudo_warn_set_conversation_v1(_a)
+
+#ifdef DEFAULT_TEXT_DOMAIN
+# define sudo_warn_gettext(_a) sudo_warn_gettext_v1(DEFAULT_TEXT_DOMAIN, (_a))
+#else
+# define sudo_warn_gettext(_a) sudo_warn_gettext_v1(NULL, (_a))
+#endif
+
+#endif /* SUDO_FATAL_H */
diff --git a/include/sudo_gettext.h b/include/sudo_gettext.h
new file mode 100644
index 0000000..16275ab
--- /dev/null
+++ b/include/sudo_gettext.h
@@ -0,0 +1,77 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011-2014 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_GETTEXT_H
+#define SUDO_GETTEXT_H
+
+/*
+ * Solaris locale.h includes libintl.h which causes problems when we
+ * redefine the gettext functions. We include it first to avoid this.
+ */
+#include <locale.h>
+
+#ifdef HAVE_LIBINTL_H
+
+# include <libintl.h>
+
+/*
+ * If DEFAULT_TEXT_DOMAIN is defined, use its value as the domain for
+ * gettext() and ngettext() instead of the value set by textdomain().
+ * This is used by the sudoers plugin as well as the convenience libraries.
+ */
+# ifdef DEFAULT_TEXT_DOMAIN
+# undef gettext
+# define gettext(String) \
+ dgettext(DEFAULT_TEXT_DOMAIN, String)
+# undef ngettext
+# define ngettext(String, String_Plural, N) \
+ dngettext(DEFAULT_TEXT_DOMAIN, String, String_Plural, N)
+# endif
+
+/*
+ * Older versions of Solaris lack ngettext() so we have to kludge it.
+ */
+# ifndef HAVE_NGETTEXT
+# undef ngettext
+# define ngettext(String, String_Plural, N) \
+ ((N) == 1 ? gettext(String) : gettext(String_Plural))
+# endif
+
+/* Gettext convenience macros */
+# define _(String) gettext(String)
+# define gettext_noop(String) String
+# define N_(String) gettext_noop(String)
+# define U_(String) sudo_warn_gettext(String)
+
+#else /* !HAVE_LIBINTL_H */
+
+/*
+ * Internationalization is either unavailable or has been disabled.
+ * Define away the gettext functions used by sudo.
+ */
+# define _(String) String
+# define N_(String) String
+# define U_(String) String
+# define textdomain(Domain)
+# define bindtextdomain(Package, Directory)
+# define ngettext(String, String_Plural, N) \
+ ((N) == 1 ? (String) : (String_Plural))
+
+#endif /* HAVE_LIBINTL_H */
+
+#endif /* SUDO_GETTEXT_H */
diff --git a/include/sudo_iolog.h b/include/sudo_iolog.h
new file mode 100644
index 0000000..052fcf3
--- /dev/null
+++ b/include/sudo_iolog.h
@@ -0,0 +1,158 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_IOLOG_H
+#define SUDO_IOLOG_H
+
+#include <sys/types.h> /* for gid_t, mode_t, size_t, ssize_t, uid_t */
+
+#ifdef HAVE_ZLIB_H
+# include <zlib.h> /* for gzFile */
+#endif
+
+/* Default maximum session ID */
+#define SESSID_MAX 2176782336U
+
+/* Default value for "iolog_file" */
+#define IOLOG_FILE "%{seq}"
+
+/*
+ * I/O log event types as stored as the first field in the timing file.
+ * Changing existing values will result in incompatible I/O log files.
+ */
+#define IO_EVENT_STDIN 0
+#define IO_EVENT_STDOUT 1
+#define IO_EVENT_STDERR 2
+#define IO_EVENT_TTYIN 3
+#define IO_EVENT_TTYOUT 4
+#define IO_EVENT_WINSIZE 5
+#define IO_EVENT_TTYOUT_1_8_7 6
+#define IO_EVENT_SUSPEND 7
+#define IO_EVENT_COUNT 8
+
+/*
+ * Indexes into iolog_files[] array.
+ * These must match the IO_EVENT_ defines above.
+ * TODO: eliminate use of IOFD_* and IO_EVENT_* as indexes in favor of
+ * a struct containing iolog_file *s for each (and names too?).
+ */
+#define IOFD_STDIN 0
+#define IOFD_STDOUT 1
+#define IOFD_STDERR 2
+#define IOFD_TTYIN 3
+#define IOFD_TTYOUT 4
+#define IOFD_TIMING 5
+#define IOFD_MAX 6
+
+/*
+ * Default password prompt regex.
+ */
+#define PASSPROMPT_REGEX "[Pp]assword[: ]*"
+
+struct timing_closure {
+ struct timespec delay;
+ const char *decimal;
+ struct iolog_file *iol;
+ int event;
+ union {
+ struct {
+ int lines;
+ int cols;
+ } winsize;
+ size_t nbytes;
+ int signo;
+ } u;
+};
+
+struct iolog_file {
+ bool enabled;
+ bool compressed;
+ bool writable;
+ union {
+ FILE *f;
+#ifdef HAVE_ZLIB_H
+ gzFile g;
+#endif
+ void *v;
+ } fd;
+};
+
+struct iolog_path_escape {
+ const char *name;
+ size_t (*copy_fn)(char *, size_t, void *);
+};
+
+/* host_port.c */
+bool iolog_parse_host_port(char *str, char **hostp, char **portp, bool *tlsp, const char *defport, const char *defport_tls);
+
+/* iolog_path.c */
+bool expand_iolog_path(const char *inpath, char *path, size_t pathlen, const struct iolog_path_escape *escapes, void *closure);
+
+/* iolog_util.c */
+bool iolog_parse_timing(const char *line, struct timing_closure *timing);
+char *iolog_parse_delay(const char *cp, struct timespec *delay, const char *decimal_point);
+int iolog_read_timing_record(struct iolog_file *iol, struct timing_closure *timing);
+struct eventlog *iolog_parse_loginfo(int dfd, const char *iolog_dir);
+bool iolog_parse_loginfo_json(FILE *fp, const char *iolog_dir, struct eventlog *evlog);
+bool iolog_parse_loginfo_legacy(FILE *fp, const char *iolog_dir, struct eventlog *evlog);
+void iolog_adjust_delay(struct timespec *delay, struct timespec *max_delay, double scale_factor);
+
+/* iolog_fileio.c */
+struct passwd;
+struct group;
+bool iolog_close(struct iolog_file *iol, const char **errstr);
+bool iolog_eof(struct iolog_file *iol);
+bool iolog_mkdtemp(char *path);
+bool iolog_mkpath(char *path);
+bool iolog_nextid(const char *iolog_dir, char sessid[7]);
+bool iolog_open(struct iolog_file *iol, int dfd, int iofd, const char *mode);
+bool iolog_write_info_file(int dfd, struct eventlog *evlog);
+char *iolog_gets(struct iolog_file *iol, char *buf, int bufsize, const char **errsttr);
+const char *iolog_fd_to_name(int iofd);
+int iolog_openat(int fdf, const char *path, int flags);
+off_t iolog_seek(struct iolog_file *iol, off_t offset, int whence);
+ssize_t iolog_read(struct iolog_file *iol, void *buf, size_t nbytes, const char **errstr);
+ssize_t iolog_write(struct iolog_file *iol, const void *buf, size_t len, const char **errstr);
+void iolog_clearerr(struct iolog_file *iol);
+bool iolog_flush(struct iolog_file *iol, const char **errstr);
+void iolog_rewind(struct iolog_file *iol);
+unsigned int iolog_get_maxseq(void);
+uid_t iolog_get_uid(void);
+gid_t iolog_get_gid(void);
+mode_t iolog_get_file_mode(void);
+mode_t iolog_get_dir_mode(void);
+bool iolog_get_compress(void);
+bool iolog_get_flush(void);
+void iolog_set_compress(bool);
+void iolog_set_defaults(void);
+void iolog_set_flush(bool);
+void iolog_set_gid(gid_t gid);
+void iolog_set_maxseq(unsigned int maxval);
+void iolog_set_mode(mode_t mode);
+void iolog_set_owner(uid_t uid, uid_t gid);
+bool iolog_swapids(bool restore);
+bool iolog_mkdirs(const char *path);
+
+/* iolog_filter.c */
+void *iolog_pwfilt_alloc(void);
+bool iolog_pwfilt_add(void *handle, const char *pattern);
+void iolog_pwfilt_free(void *handle);
+bool iolog_pwfilt_remove(void *handle, const char *pattern);
+bool iolog_pwfilt_run(void *handle, int event, const char *buf, size_t len, char **newbuf);
+
+#endif /* SUDO_IOLOG_H */
diff --git a/include/sudo_json.h b/include/sudo_json.h
new file mode 100644
index 0000000..be4bab5
--- /dev/null
+++ b/include/sudo_json.h
@@ -0,0 +1,100 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_JSON_H
+#define SUDO_JSON_H
+
+#include <sys/types.h> /* for id_t */
+
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+
+/*
+ * JSON values may be of the following types.
+ */
+enum json_value_type {
+ JSON_STRING,
+ JSON_ID,
+ JSON_NUMBER,
+ JSON_OBJECT,
+ JSON_ARRAY,
+ JSON_BOOL,
+ JSON_NULL
+};
+
+/*
+ * JSON value suitable for printing.
+ * Note: this does not support object values.
+ */
+struct json_value {
+ enum json_value_type type;
+ union {
+ const char *string;
+ long long number;
+ id_t id;
+ bool boolean;
+ } u;
+};
+
+struct json_container {
+ char *buf;
+ unsigned int buflen;
+ unsigned int bufsize;
+ unsigned int indent_level;
+ unsigned int indent_increment;
+ bool minimal;
+ bool memfatal;
+ bool need_comma;
+ bool quiet;
+};
+
+sudo_dso_public bool sudo_json_init_v1(struct json_container *jsonc, unsigned int indent, bool minimal, bool memfatal);
+sudo_dso_public bool sudo_json_init_v2(struct json_container *jsonc, unsigned int indent, bool minimal, bool memfatal, bool quiet);
+#define sudo_json_init(_a, _b, _c, _d, _e) sudo_json_init_v2((_a), (_b), (_c), (_d), (_e))
+
+sudo_dso_public void sudo_json_free_v1(struct json_container *jsonc);
+#define sudo_json_free(_a) sudo_json_free_v1((_a))
+
+sudo_dso_public bool sudo_json_open_object_v1(struct json_container *jsonc, const char *name);
+#define sudo_json_open_object(_a, _b) sudo_json_open_object_v1((_a), (_b))
+
+sudo_dso_public bool sudo_json_close_object_v1(struct json_container *jsonc);
+#define sudo_json_close_object(_a) sudo_json_close_object_v1((_a))
+
+sudo_dso_public bool sudo_json_open_array_v1(struct json_container *jsonc, const char *name);
+#define sudo_json_open_array(_a, _b) sudo_json_open_array_v1((_a), (_b))
+
+sudo_dso_public bool sudo_json_close_array_v1(struct json_container *jsonc);
+#define sudo_json_close_array(_a) sudo_json_close_array_v1((_a))
+
+sudo_dso_public bool sudo_json_add_value_v1(struct json_container *jsonc, const char *name, struct json_value *value);
+#define sudo_json_add_value(_a, _b, _c) sudo_json_add_value_v1((_a), (_b), (_c))
+
+sudo_dso_public bool sudo_json_add_value_as_object_v1(struct json_container *jsonc, const char *name, struct json_value *value);
+#define sudo_json_add_value_as_object(_a, _b, _c) sudo_json_add_value_as_object_v1((_a), (_b), (_c))
+
+sudo_dso_public char *sudo_json_get_buf_v1(struct json_container *jsonc);
+#define sudo_json_get_buf(_a) sudo_json_get_buf_v1((_a))
+
+sudo_dso_public unsigned int sudo_json_get_len_v1(struct json_container *jsonc);
+#define sudo_json_get_len(_a) sudo_json_get_len_v1((_a))
+
+#endif /* SUDO_JSON_H */
diff --git a/include/sudo_lbuf.h b/include/sudo_lbuf.h
new file mode 100644
index 0000000..c1b9fb4
--- /dev/null
+++ b/include/sudo_lbuf.h
@@ -0,0 +1,62 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2007, 2010, 2011, 2013-2015, 2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_LBUF_H
+#define SUDO_LBUF_H
+
+/*
+ * Line buffer struct.
+ */
+struct sudo_lbuf {
+ int (*output)(const char *);
+ char *buf;
+ const char *continuation;
+ unsigned int indent;
+ unsigned int len;
+ unsigned int size;
+ unsigned short cols;
+ unsigned short error;
+};
+
+typedef int (*sudo_lbuf_output_t)(const char *);
+
+/* Flags for sudo_lbuf_append_esc() */
+#define LBUF_ESC_CNTRL 0x01
+#define LBUF_ESC_BLANK 0x02
+#define LBUF_ESC_QUOTE 0x04
+
+sudo_dso_public void sudo_lbuf_init_v1(struct sudo_lbuf *lbuf, sudo_lbuf_output_t output, unsigned int indent, const char *continuation, int cols);
+sudo_dso_public void sudo_lbuf_destroy_v1(struct sudo_lbuf *lbuf);
+sudo_dso_public bool sudo_lbuf_append_v1(struct sudo_lbuf *lbuf, const char * restrict fmt, ...) sudo_printflike(2, 3);
+sudo_dso_public bool sudo_lbuf_append_esc_v1(struct sudo_lbuf *lbuf, int flags, const char * restrict fmt, ...) sudo_printflike(3, 4);
+sudo_dso_public bool sudo_lbuf_append_quoted_v1(struct sudo_lbuf *lbuf, const char *set, const char * restrict fmt, ...) sudo_printflike(3, 4);
+sudo_dso_public void sudo_lbuf_print_v1(struct sudo_lbuf *lbuf);
+sudo_dso_public bool sudo_lbuf_error_v1(struct sudo_lbuf *lbuf);
+sudo_dso_public void sudo_lbuf_clearerr_v1(struct sudo_lbuf *lbuf);
+
+#define sudo_lbuf_init(_a, _b, _c, _d, _e) sudo_lbuf_init_v1((_a), (_b), (_c), (_d), (_e))
+#define sudo_lbuf_destroy(_a) sudo_lbuf_destroy_v1((_a))
+#define sudo_lbuf_append sudo_lbuf_append_v1
+#define sudo_lbuf_append_esc sudo_lbuf_append_esc_v1
+#define sudo_lbuf_append_quoted sudo_lbuf_append_quoted_v1
+#define sudo_lbuf_print(_a) sudo_lbuf_print_v1((_a))
+#define sudo_lbuf_error(_a) sudo_lbuf_error_v1((_a))
+#define sudo_lbuf_clearerr(_a) sudo_lbuf_clearerr_v1((_a))
+
+#endif /* SUDO_LBUF_H */
diff --git a/include/sudo_plugin.h b/include/sudo_plugin.h
new file mode 100644
index 0000000..81a68aa
--- /dev/null
+++ b/include/sudo_plugin.h
@@ -0,0 +1,288 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_PLUGIN_H
+#define SUDO_PLUGIN_H
+
+/* API version major/minor */
+#define SUDO_API_VERSION_MAJOR 1
+#define SUDO_API_VERSION_MINOR 21
+#define SUDO_API_MKVERSION(x, y) (((x) << 16) | (y))
+#define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR, SUDO_API_VERSION_MINOR)
+
+/* Getters and setters for plugin API versions */
+#define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16)
+#define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffffU)
+#define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \
+ *(vp) = (*(vp) & 0x0000ffffU) | ((n) << 16); \
+} while(0)
+#define SUDO_API_VERSION_SET_MINOR(vp, n) do { \
+ *(vp) = (*(vp) & 0xffff0000U) | (n); \
+} while(0)
+
+/* "plugin type" for the sudo front end, as passed to an audit plugin */
+#define SUDO_FRONT_END 0
+
+/* Conversation function types and defines */
+struct sudo_conv_message {
+#define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */
+#define SUDO_CONV_PROMPT_ECHO_ON 0x0002 /* echo user input */
+#define SUDO_CONV_ERROR_MSG 0x0003 /* error message */
+#define SUDO_CONV_INFO_MSG 0x0004 /* informational message */
+#define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */
+#define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */
+#define SUDO_CONV_PREFER_TTY 0x2000 /* flag: use tty if possible */
+ int msg_type;
+ int timeout;
+ const char *msg;
+};
+
+/*
+ * Maximum length of a reply (not including the trailing NUL) when
+ * conversing with the user. In practical terms, this is the longest
+ * password sudo will support. This means that a buffer of size
+ * SUDO_CONV_REPL_MAX+1 is guaranteed to be able to hold any reply
+ * from the conversation function.
+ */
+#define SUDO_CONV_REPL_MAX 1023
+
+struct sudo_conv_reply {
+ char *reply;
+};
+
+/* Conversation callback API version major/minor */
+#define SUDO_CONV_CALLBACK_VERSION_MAJOR 1
+#define SUDO_CONV_CALLBACK_VERSION_MINOR 0
+#define SUDO_CONV_CALLBACK_VERSION SUDO_API_MKVERSION(SUDO_CONV_CALLBACK_VERSION_MAJOR, SUDO_CONV_CALLBACK_VERSION_MINOR)
+
+/*
+ * Callback struct to be passed to the conversation function.
+ * Can be used to perform operations on suspend/resume such
+ * as dropping/acquiring locks.
+ */
+typedef int (*sudo_conv_callback_fn_t)(int signo, void *closure);
+struct sudo_conv_callback {
+ unsigned int version;
+ void *closure;
+ sudo_conv_callback_fn_t on_suspend;
+ sudo_conv_callback_fn_t on_resume;
+};
+
+typedef int (*sudo_conv_t)(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback);
+typedef int (*sudo_printf_t)(int msg_type, const char * restrict fmt, ...);
+
+/*
+ * Hooks allow a plugin to hook into specific sudo and/or libc functions.
+ */
+
+#if defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 4) || __GNUC__ > 4)
+# pragma GCC diagnostic ignored "-Wstrict-prototypes"
+#endif
+
+/* Hook functions typedefs. */
+typedef int (*sudo_hook_fn_t)();
+typedef int (*sudo_hook_fn_setenv_t)(const char *name, const char *value, int overwrite, void *closure);
+typedef int (*sudo_hook_fn_putenv_t)(char *string, void *closure);
+typedef int (*sudo_hook_fn_getenv_t)(const char *name, char **value, void *closure);
+typedef int (*sudo_hook_fn_unsetenv_t)(const char *name, void *closure);
+
+/* Hook structure definition. */
+struct sudo_hook {
+ unsigned int hook_version;
+ unsigned int hook_type;
+ sudo_hook_fn_t hook_fn;
+ void *closure;
+};
+
+/* Hook API version major/minor */
+#define SUDO_HOOK_VERSION_MAJOR 1
+#define SUDO_HOOK_VERSION_MINOR 0
+#define SUDO_HOOK_VERSION SUDO_API_MKVERSION(SUDO_HOOK_VERSION_MAJOR, SUDO_HOOK_VERSION_MINOR)
+
+/*
+ * Hook function return values.
+ */
+#define SUDO_HOOK_RET_ERROR -1 /* error */
+#define SUDO_HOOK_RET_NEXT 0 /* go to the next hook in the list */
+#define SUDO_HOOK_RET_STOP 1 /* stop hook processing for this type */
+
+/*
+ * Hooks for setenv/unsetenv/putenv/getenv.
+ * This allows the plugin to be notified when a PAM module modifies
+ * the environment so it can update the copy of the environment that
+ * is passed to execve().
+ */
+#define SUDO_HOOK_SETENV 1
+#define SUDO_HOOK_UNSETENV 2
+#define SUDO_HOOK_PUTENV 3
+#define SUDO_HOOK_GETENV 4
+
+/*
+ * Plugin interface to sudo's main event loop.
+ */
+typedef void (*sudo_plugin_ev_callback_t)(int fd, int what, void *closure);
+
+struct timespec;
+struct sudo_plugin_event {
+ int (*set)(struct sudo_plugin_event *pev, int fd, int events, sudo_plugin_ev_callback_t callback, void *closure);
+ int (*add)(struct sudo_plugin_event *pev, struct timespec *timeout);
+ int (*del)(struct sudo_plugin_event *pev);
+ int (*pending)(struct sudo_plugin_event *pev, int events, struct timespec *ts);
+ int (*fd)(struct sudo_plugin_event *pev);
+ void (*setbase)(struct sudo_plugin_event *pev, void *base);
+ void (*loopbreak)(struct sudo_plugin_event *pev);
+ void (*free)(struct sudo_plugin_event *pev);
+ /* actually larger... */
+};
+
+/* Sudo plugin Event types */
+#define SUDO_PLUGIN_EV_TIMEOUT 0x01 /* fire after timeout */
+#define SUDO_PLUGIN_EV_READ 0x02 /* fire when readable */
+#define SUDO_PLUGIN_EV_WRITE 0x04 /* fire when writable */
+#define SUDO_PLUGIN_EV_PERSIST 0x08 /* persist until deleted */
+#define SUDO_PLUGIN_EV_SIGNAL 0x10 /* fire on signal receipt */
+
+/* Policy plugin type and defines. */
+struct passwd;
+struct policy_plugin {
+#define SUDO_POLICY_PLUGIN 1
+ unsigned int type; /* always SUDO_POLICY_PLUGIN */
+ unsigned int version; /* always SUDO_API_VERSION */
+ int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], char * const user_env[],
+ char * const plugin_options[], const char **errstr);
+ void (*close)(int exit_status, int error); /* wait status or error */
+ int (*show_version)(int verbose);
+ int (*check_policy)(int argc, char * const argv[],
+ char *env_add[], char **command_info[],
+ char **argv_out[], char **user_env_out[], const char **errstr);
+ int (*list)(int argc, char * const argv[], int verbose,
+ const char *user, const char **errstr);
+ int (*validate)(const char **errstr);
+ void (*invalidate)(int rmcred);
+ int (*init_session)(struct passwd *pwd, char **user_env_out[],
+ const char **errstr);
+ void (*register_hooks)(int version, int (*register_hook)(struct sudo_hook *hook));
+ void (*deregister_hooks)(int version, int (*deregister_hook)(struct sudo_hook *hook));
+ struct sudo_plugin_event * (*event_alloc)(void);
+};
+
+/* I/O plugin type and defines. */
+struct io_plugin {
+#define SUDO_IO_PLUGIN 2
+ unsigned int type; /* always SUDO_IO_PLUGIN */
+ unsigned int version; /* always SUDO_API_VERSION */
+ int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], char * const command_info[],
+ int argc, char * const argv[], char * const user_env[],
+ char * const plugin_options[], const char **errstr);
+ void (*close)(int exit_status, int error); /* wait status or error */
+ int (*show_version)(int verbose);
+ int (*log_ttyin)(const char *buf, unsigned int len, const char **errstr);
+ int (*log_ttyout)(const char *buf, unsigned int len, const char **errstr);
+ int (*log_stdin)(const char *buf, unsigned int len, const char **errstr);
+ int (*log_stdout)(const char *buf, unsigned int len, const char **errstr);
+ int (*log_stderr)(const char *buf, unsigned int len, const char **errstr);
+ void (*register_hooks)(int version,
+ int (*register_hook)(struct sudo_hook *hook));
+ void (*deregister_hooks)(int version,
+ int (*deregister_hook)(struct sudo_hook *hook));
+ int (*change_winsize)(unsigned int line, unsigned int cols,
+ const char **errstr);
+ int (*log_suspend)(int signo, const char **errstr);
+ struct sudo_plugin_event * (*event_alloc)(void);
+};
+
+/* Differ audit plugin close status types. */
+#define SUDO_PLUGIN_NO_STATUS 0
+#define SUDO_PLUGIN_WAIT_STATUS 1
+#define SUDO_PLUGIN_EXEC_ERROR 2
+#define SUDO_PLUGIN_SUDO_ERROR 3
+
+/* Audit plugin type and defines */
+struct audit_plugin {
+#define SUDO_AUDIT_PLUGIN 3
+ unsigned int type; /* always SUDO_AUDIT_PLUGIN */
+ unsigned int version; /* always SUDO_API_VERSION */
+ int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr);
+ void (*close)(int status_type, int status);
+ int (*accept)(const char *plugin_name, unsigned int plugin_type,
+ char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr);
+ int (*reject)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+ int (*error)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[],
+ const char **errstr);
+ int (*show_version)(int verbose);
+ void (*register_hooks)(int version, int (*register_hook)(struct sudo_hook *hook));
+ void (*deregister_hooks)(int version, int (*deregister_hook)(struct sudo_hook *hook));
+ struct sudo_plugin_event * (*event_alloc)(void);
+};
+
+/* Approval plugin type and defines */
+struct approval_plugin {
+#define SUDO_APPROVAL_PLUGIN 4
+ unsigned int type; /* always SUDO_APPROVAL_PLUGIN */
+ unsigned int version; /* always SUDO_API_VERSION */
+ int (*open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr);
+ void (*close)(void);
+ int (*check)(char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr);
+ int (*show_version)(int verbose);
+};
+
+/* Sudoers group plugin version major/minor */
+#define GROUP_API_VERSION_MAJOR 1
+#define GROUP_API_VERSION_MINOR 0
+#define GROUP_API_VERSION SUDO_API_MKVERSION(GROUP_API_VERSION_MAJOR, GROUP_API_VERSION_MINOR)
+
+/* Getters and setters for group version (for source compat only) */
+#define GROUP_API_VERSION_GET_MAJOR(v) SUDO_API_VERSION_GET_MAJOR(v)
+#define GROUP_API_VERSION_GET_MINOR(v) SUDO_API_VERSION_GET_MINOR(v)
+#define GROUP_API_VERSION_SET_MAJOR(vp, n) SUDO_API_VERSION_SET_MAJOR(vp, n)
+#define GROUP_API_VERSION_SET_MINOR(vp, n) SUDO_API_VERSION_SET_MINOR(vp, n)
+
+/*
+ * version: for compatibility checking
+ * group_init: return 1 on success, 0 if unconfigured, -1 on error.
+ * group_cleanup: called to clean up resources used by provider
+ * user_in_group: returns 1 if user is in group, 0 if not.
+ * note that pwd may be NULL if the user is not in passwd.
+ */
+struct sudoers_group_plugin {
+ unsigned int version;
+ int (*init)(int version, sudo_printf_t sudo_plugin_printf,
+ char *const argv[]);
+ void (*cleanup)(void);
+ int (*query)(const char *user, const char *group, const struct passwd *pwd);
+};
+
+#endif /* SUDO_PLUGIN_H */
diff --git a/include/sudo_queue.h b/include/sudo_queue.h
new file mode 100644
index 0000000..f055957
--- /dev/null
+++ b/include/sudo_queue.h
@@ -0,0 +1,823 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ * $FreeBSD: head/sys/sys/queue.h 251887 2013-06-18 02:57:56Z lstewart $
+ */
+
+#ifndef SUDO_QUEUE_H
+#define SUDO_QUEUE_H
+
+/*
+ * This file defines four types of data structures: singly-linked lists,
+ * singly-linked tail queues, lists and tail queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction. Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may be traversed in either direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A headless tail queue lacks a head structure, The first element acts
+ * as a de facto list head. It uses the same entry struct as a regular
+ * tail queue for easy conversion from headless to headful.
+ * It is capable of concatenating queues as well as individual elements.
+ * Traversing in reverse is more expensive due to lack of a list head.
+ * Note: elements must be initialized before use.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ * SLIST LIST STAILQ TAILQ
+ * _HEAD + + + +
+ * _HEAD_INITIALIZER + + + +
+ * _ENTRY + + + +
+ * _INIT + + + +
+ * _EMPTY + + + +
+ * _FIRST + + + +
+ * _NEXT + + + +
+ * _PREV - + - +
+ * _LAST - - + +
+ * _FOREACH + + + +
+ * _FOREACH_FROM + + + +
+ * _FOREACH_SAFE + + + +
+ * _FOREACH_FROM_SAFE + + + +
+ * _FOREACH_REVERSE - - - +
+ * _FOREACH_REVERSE_FROM - - - +
+ * _FOREACH_REVERSE_SAFE - - - +
+ * _FOREACH_REVERSE_FROM_SAFE - - - +
+ * _INSERT_HEAD + + + +
+ * _INSERT_BEFORE - + - +
+ * _INSERT_AFTER + + + +
+ * _INSERT_TAIL - - + +
+ * _CONCAT - - + +
+ * _REMOVE_AFTER + - + -
+ * _REMOVE_HEAD + - + -
+ * _REMOVE + + + +
+ * _SWAP + + + +
+ *
+ */
+#ifdef QUEUE_MACRO_DEBUG
+/* Store the last 2 places the queue element or head was altered */
+struct qm_trace {
+ unsigned long lastline;
+ unsigned long prevline;
+ const char *lastfile;
+ const char *prevfile;
+};
+
+#undef TRACEBUF
+#define TRACEBUF struct qm_trace trace;
+#undef TRACEBUF_INITIALIZER
+#define TRACEBUF_INITIALIZER { __FILE__, __LINE__, NULL, 0 } ,
+#undef TRASHIT
+#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
+#undef QMD_SAVELINK
+#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
+
+#undef QMD_TRACE_HEAD
+#define QMD_TRACE_HEAD(head) do { \
+ (head)->trace.prevline = (head)->trace.lastline; \
+ (head)->trace.prevfile = (head)->trace.lastfile; \
+ (head)->trace.lastline = __LINE__; \
+ (head)->trace.lastfile = __FILE__; \
+} while (0)
+
+#undef QMD_TRACE_ELEM
+#define QMD_TRACE_ELEM(elem) do { \
+ (elem)->trace.prevline = (elem)->trace.lastline; \
+ (elem)->trace.prevfile = (elem)->trace.lastfile; \
+ (elem)->trace.lastline = __LINE__; \
+ (elem)->trace.lastfile = __FILE__; \
+} while (0)
+
+#else
+#undef QMD_TRACE_ELEM
+#define QMD_TRACE_ELEM(elem)
+#undef QMD_TRACE_HEAD
+#define QMD_TRACE_HEAD(head)
+#undef QMD_SAVELINK
+#define QMD_SAVELINK(name, link)
+#undef TRACEBUF
+#define TRACEBUF
+#undef TRACEBUF_INITIALIZER
+#define TRACEBUF_INITIALIZER
+#undef TRASHIT
+#define TRASHIT(x)
+#endif /* QUEUE_MACRO_DEBUG */
+
+/*
+ * XXX - Work around a bug in the llvm static analyzer.
+ * https://bugs.llvm.org//show_bug.cgi?id=18222
+ */
+#ifdef __clang_analyzer__
+# define ANALYZER_ASSERT(x) do { \
+ if (!__builtin_expect(!(x), 0)) \
+ __builtin_trap(); \
+} while (0)
+#else
+# define ANALYZER_ASSERT(x) do {} while (0)
+#endif /* __clang_analyzer__ */
+
+ /*
+ * Singly-linked List declarations.
+ */
+#undef SLIST_HEAD
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#undef SLIST_HEAD_INITIALIZER
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#undef SLIST_ENTRY
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#undef SLIST_EMPTY
+#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
+
+#undef SLIST_FIRST
+#define SLIST_FIRST(head) ((head)->slh_first)
+
+#undef SLIST_FOREACH
+#define SLIST_FOREACH(var, head, field) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var); \
+ (var) = SLIST_NEXT((var), field))
+
+#undef SLIST_FOREACH_FROM
+#define SLIST_FOREACH_FROM(var, head, field) \
+ for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
+ (var); \
+ (var) = SLIST_NEXT((var), field))
+
+#undef SLIST_FOREACH_SAFE
+#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#undef SLIST_FOREACH_FROM_SAFE
+#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
+ for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
+ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#undef SLIST_FOREACH_PREVPTR
+#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
+ for ((varp) = &SLIST_FIRST((head)); \
+ ((var) = *(varp)) != NULL; \
+ (varp) = &SLIST_NEXT((var), field))
+
+#undef SLIST_INIT
+#define SLIST_INIT(head) do { \
+ SLIST_FIRST((head)) = NULL; \
+} while (0)
+
+#undef SLIST_INSERT_AFTER
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
+ SLIST_NEXT((slistelm), field) = (elm); \
+} while (0)
+
+#undef SLIST_INSERT_HEAD
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
+ SLIST_FIRST((head)) = (elm); \
+} while (0)
+
+#undef SLIST_NEXT
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+#undef SLIST_REMOVE
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
+ if (SLIST_FIRST((head)) == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = SLIST_FIRST((head)); \
+ while (SLIST_NEXT(curelm, field) != (elm)) \
+ curelm = SLIST_NEXT(curelm, field); \
+ SLIST_REMOVE_AFTER(curelm, field); \
+ } \
+ TRASHIT(*oldnext); \
+} while (0)
+
+#undef SLIST_REMOVE_AFTER
+#define SLIST_REMOVE_AFTER(elm, field) do { \
+ SLIST_NEXT(elm, field) = \
+ SLIST_NEXT(SLIST_NEXT(elm, field), field); \
+} while (0)
+
+#undef SLIST_REMOVE_HEAD
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
+} while (0)
+
+#undef SLIST_SWAP
+#define SLIST_SWAP(head1, head2, type) do { \
+ struct type *swap_first = SLIST_FIRST(head1); \
+ SLIST_FIRST(head1) = SLIST_FIRST(head2); \
+ SLIST_FIRST(head2) = swap_first; \
+} while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#undef STAILQ_HEAD
+#define STAILQ_HEAD(name, type) \
+struct name { \
+ struct type *stqh_first;/* first element */ \
+ struct type **stqh_last;/* addr of last next element */ \
+}
+
+#undef STAILQ_HEAD_INITIALIZER
+#define STAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).stqh_first }
+
+#undef STAILQ_ENTRY
+#define STAILQ_ENTRY(type) \
+struct { \
+ struct type *stqe_next; /* next element */ \
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#undef STAILQ_CONCAT
+#define STAILQ_CONCAT(head1, head2) do { \
+ if (!STAILQ_EMPTY((head2))) { \
+ *(head1)->stqh_last = (head2)->stqh_first; \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_INIT((head2)); \
+ } \
+} while (0)
+
+#undef STAILQ_EMPTY
+#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
+
+#undef STAILQ_FIRST
+#define STAILQ_FIRST(head) ((head)->stqh_first)
+
+#undef STAILQ_FOREACH
+#define STAILQ_FOREACH(var, head, field) \
+ for ((var) = STAILQ_FIRST((head)); \
+ (var); \
+ (var) = STAILQ_NEXT((var), field))
+
+#undef STAILQ_FOREACH_FROM
+#define STAILQ_FOREACH_FROM(var, head, field) \
+ for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
+ (var); \
+ (var) = STAILQ_NEXT((var), field))
+
+#undef STAILQ_FOREACH_SAFE
+#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = STAILQ_FIRST((head)); \
+ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#undef STAILQ_FOREACH_FROM_SAFE
+#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
+ for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
+ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#undef STAILQ_INIT
+#define STAILQ_INIT(head) do { \
+ STAILQ_FIRST((head)) = NULL; \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#undef STAILQ_INSERT_AFTER
+#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_NEXT((tqelm), field) = (elm); \
+} while (0)
+
+#undef STAILQ_INSERT_HEAD
+#define STAILQ_INSERT_HEAD(head, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_FIRST((head)) = (elm); \
+} while (0)
+
+#undef STAILQ_INSERT_TAIL
+#define STAILQ_INSERT_TAIL(head, elm, field) do { \
+ STAILQ_NEXT((elm), field) = NULL; \
+ *(head)->stqh_last = (elm); \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+} while (0)
+
+#undef STAILQ_LAST
+#define STAILQ_LAST(head, type, field) \
+ (STAILQ_EMPTY((head)) ? NULL : \
+ __containerof((head)->stqh_last, struct type, field.stqe_next))
+
+#undef STAILQ_NEXT
+#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+
+#undef STAILQ_REMOVE
+#define STAILQ_REMOVE(head, elm, type, field) do { \
+ QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
+ if (STAILQ_FIRST((head)) == (elm)) { \
+ STAILQ_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = STAILQ_FIRST((head)); \
+ while (STAILQ_NEXT(curelm, field) != (elm)) \
+ curelm = STAILQ_NEXT(curelm, field); \
+ STAILQ_REMOVE_AFTER(head, curelm, field); \
+ } \
+ TRASHIT(*oldnext); \
+} while (0)
+
+#undef STAILQ_REMOVE_AFTER
+#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
+ if ((STAILQ_NEXT(elm, field) = \
+ STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+} while (0)
+
+#undef STAILQ_REMOVE_HEAD
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if ((STAILQ_FIRST((head)) = \
+ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#undef STAILQ_SWAP
+#define STAILQ_SWAP(head1, head2, type) do { \
+ struct type *swap_first = STAILQ_FIRST(head1); \
+ struct type **swap_last = (head1)->stqh_last; \
+ STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_FIRST(head2) = swap_first; \
+ (head2)->stqh_last = swap_last; \
+ if (STAILQ_EMPTY(head1)) \
+ (head1)->stqh_last = &STAILQ_FIRST(head1); \
+ if (STAILQ_EMPTY(head2)) \
+ (head2)->stqh_last = &STAILQ_FIRST(head2); \
+} while (0)
+
+
+/*
+ * List declarations.
+ */
+#undef LIST_HEAD
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#undef LIST_HEAD_INITIALIZER
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#undef LIST_ENTRY
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List functions.
+ */
+#undef LIST_EMPTY
+#define LIST_EMPTY(head) ((head)->lh_first == NULL)
+
+#undef LIST_FIRST
+#define LIST_FIRST(head) ((head)->lh_first)
+
+#undef LIST_FOREACH
+#define LIST_FOREACH(var, head, field) \
+ for ((var) = LIST_FIRST((head)); \
+ (var); \
+ (var) = LIST_NEXT((var), field))
+
+#undef LIST_FOREACH_FROM
+#define LIST_FOREACH_FROM(var, head, field) \
+ for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
+ (var); \
+ (var) = LIST_NEXT((var), field))
+
+#undef LIST_FOREACH_SAFE
+#define LIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = LIST_FIRST((head)); \
+ (var) && ((tvar) = LIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#undef LIST_FOREACH_FROM_SAFE
+#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
+ for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
+ (var) && ((tvar) = LIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#undef LIST_INIT
+#define LIST_INIT(head) do { \
+ LIST_FIRST((head)) = NULL; \
+} while (0)
+
+#undef LIST_INSERT_AFTER
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
+ LIST_NEXT((listelm), field)->field.le_prev = \
+ &LIST_NEXT((elm), field); \
+ LIST_NEXT((listelm), field) = (elm); \
+ (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
+} while (0)
+
+#undef LIST_INSERT_BEFORE
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ LIST_NEXT((elm), field) = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
+} while (0)
+
+#undef LIST_INSERT_HEAD
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
+ LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
+ LIST_FIRST((head)) = (elm); \
+ (elm)->field.le_prev = &LIST_FIRST((head)); \
+} while (0)
+
+#undef LIST_NEXT
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+#undef LIST_PREV
+#define LIST_PREV(elm, head, type, field) \
+ ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
+ __containerof((elm)->field.le_prev, struct type, field.le_next))
+
+#undef LIST_REMOVE
+#define LIST_REMOVE(elm, field) do { \
+ ANALYZER_ASSERT(elm != NULL); \
+ QMD_SAVELINK(oldnext, (elm)->field.le_next); \
+ QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
+ if (LIST_NEXT((elm), field) != NULL) \
+ LIST_NEXT((elm), field)->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = LIST_NEXT((elm), field); \
+ TRASHIT(*oldnext); \
+ TRASHIT(*oldprev); \
+} while (0)
+
+#undef LIST_SWAP
+#define LIST_SWAP(head1, head2, type, field) do { \
+ struct type *swap_tmp = LIST_FIRST((head1)); \
+ LIST_FIRST((head1)) = LIST_FIRST((head2)); \
+ LIST_FIRST((head2)) = swap_tmp; \
+ if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
+ swap_tmp->field.le_prev = &LIST_FIRST((head1)); \
+ if ((swap_tmp = LIST_FIRST((head2))) != NULL) \
+ swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
+} while (0)
+
+/*
+ * Tail queue declarations.
+ */
+#undef TAILQ_HEAD
+#define TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+ TRACEBUF \
+}
+
+#undef TAILQ_HEAD_INITIALIZER
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
+
+#undef TAILQ_ENTRY
+#define TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+ TRACEBUF \
+}
+
+/*
+ * Tail queue functions.
+ */
+#undef TAILQ_CONCAT
+#define TAILQ_CONCAT(head1, head2, field) do { \
+ if (!TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ TAILQ_INIT((head2)); \
+ QMD_TRACE_HEAD(head1); \
+ QMD_TRACE_HEAD(head2); \
+ } \
+} while (0)
+
+#undef TAILQ_EMPTY
+#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
+
+#undef TAILQ_FIRST
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+
+#undef TAILQ_FOREACH
+#define TAILQ_FOREACH(var, head, field) \
+ for ((var) = TAILQ_FIRST((head)); \
+ (var); \
+ (var) = TAILQ_NEXT((var), field))
+
+#undef TAILQ_FOREACH_FROM
+#define TAILQ_FOREACH_FROM(var, head, field) \
+ for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
+ (var); \
+ (var) = TAILQ_NEXT((var), field))
+
+#undef TAILQ_FOREACH_SAFE
+#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = TAILQ_FIRST((head)); \
+ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#undef TAILQ_FOREACH_FROM_SAFE
+#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
+ for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
+ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#undef TAILQ_FOREACH_REVERSE
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var); \
+ (var) = TAILQ_PREV((var), headname, field))
+
+#undef TAILQ_FOREACH_REVERSE_FROM
+#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \
+ for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
+ (var); \
+ (var) = TAILQ_PREV((var), headname, field))
+
+#undef TAILQ_FOREACH_REVERSE_SAFE
+#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
+ (var) = (tvar))
+
+#undef TAILQ_FOREACH_REVERSE_FROM_SAFE
+#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \
+ for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
+ (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
+ (var) = (tvar))
+
+#undef TAILQ_INIT
+#define TAILQ_INIT(head) do { \
+ TAILQ_FIRST((head)) = NULL; \
+ (head)->tqh_last = &TAILQ_FIRST((head)); \
+ QMD_TRACE_HEAD(head); \
+} while (0)
+
+#undef TAILQ_INSERT_AFTER
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
+ &TAILQ_NEXT((elm), field); \
+ else { \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_HEAD(head); \
+ } \
+ TAILQ_NEXT((listelm), field) = (elm); \
+ (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+ QMD_TRACE_ELEM(&listelm->field); \
+} while (0)
+
+#undef TAILQ_INSERT_BEFORE
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ TAILQ_NEXT((elm), field) = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+ QMD_TRACE_ELEM(&listelm->field); \
+} while (0)
+
+#undef TAILQ_INSERT_HEAD
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
+ TAILQ_FIRST((head))->field.tqe_prev = \
+ &TAILQ_NEXT((elm), field); \
+ else \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ TAILQ_FIRST((head)) = (elm); \
+ (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
+ QMD_TRACE_HEAD(head); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+#undef TAILQ_INSERT_TAIL
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ TAILQ_NEXT((elm), field) = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_HEAD(head); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+#undef TAILQ_LAST
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#undef TAILQ_NEXT
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#undef TAILQ_PREV
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#undef TAILQ_REMOVE
+#define TAILQ_REMOVE(head, elm, field) do { \
+ ANALYZER_ASSERT(elm != NULL); \
+ QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
+ QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
+ if ((TAILQ_NEXT((elm), field)) != NULL) \
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else { \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ QMD_TRACE_HEAD(head); \
+ } \
+ *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
+ TRASHIT(*oldnext); \
+ TRASHIT(*oldprev); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+#undef TAILQ_SWAP
+#define TAILQ_SWAP(head1, head2, type, field) do { \
+ struct type *swap_first = (head1)->tqh_first; \
+ struct type **swap_last = (head1)->tqh_last; \
+ (head1)->tqh_first = (head2)->tqh_first; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ (head2)->tqh_first = swap_first; \
+ (head2)->tqh_last = swap_last; \
+ if ((swap_first = (head1)->tqh_first) != NULL) \
+ swap_first->field.tqe_prev = &(head1)->tqh_first; \
+ else \
+ (head1)->tqh_last = &(head1)->tqh_first; \
+ if ((swap_first = (head2)->tqh_first) != NULL) \
+ swap_first->field.tqe_prev = &(head2)->tqh_first; \
+ else \
+ (head2)->tqh_last = &(head2)->tqh_first; \
+} while (0)
+
+/*
+ * Headless Tail queue definitions.
+ */
+#undef HLTQ_ENTRY
+#define HLTQ_ENTRY(type) TAILQ_ENTRY(type)
+
+#undef HLTQ_INIT
+#define HLTQ_INIT(entry, field) do { \
+ (entry)->field.tqe_next = NULL; \
+ (entry)->field.tqe_prev = &(entry)->field.tqe_next; \
+} while (0)
+
+#undef HLTQ_INITIALIZER
+#define HLTQ_INITIALIZER(entry, field) \
+ { NULL, &(entry)->field.tqe_next }
+
+#undef HLTQ_FIRST
+#define HLTQ_FIRST(elm) (elm)
+
+#undef HLTQ_END
+#define HLTQ_END(elm) NULL
+
+#undef HLTQ_NEXT
+#define HLTQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#undef HLTQ_LAST
+#define HLTQ_LAST(elm, type, field) \
+ ((elm)->field.tqe_next == NULL ? (elm) : \
+ __containerof((elm)->field.tqe_prev, struct type, field.tqe_next))
+
+#undef HLTQ_PREV
+#define HLTQ_PREV(elm, type, field) \
+ (*(elm)->field.tqe_prev == NULL ? NULL : \
+ __containerof((elm)->field.tqe_prev, struct type, field.tqe_next))
+
+#undef HLTQ_FOREACH
+#define HLTQ_FOREACH(var, head, field) \
+ for ((var) = HLTQ_FIRST(head); \
+ (var) != HLTQ_END(head); \
+ (var) = HLTQ_NEXT(var, field))
+
+#undef HLTQ_FOREACH_SAFE
+#define HLTQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = HLTQ_FIRST(head); \
+ (var) != HLTQ_END(head) && \
+ ((tvar) = HLTQ_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+#undef HLTQ_FOREACH_REVERSE
+#define HLTQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = HLTQ_LAST(head, headname); \
+ (var) != HLTQ_END(head); \
+ (var) = HLTQ_PREV(var, headname, field))
+
+#undef HLTQ_FOREACH_REVERSE_SAFE
+#define HLTQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
+ for ((var) = HLTQ_LAST(head, headname); \
+ (var) != HLTQ_END(head) && \
+ ((tvar) = HLTQ_PREV(var, headname, field), 1); \
+ (var) = (tvar))
+
+/* Concatenate queue2 to the end of queue1. */
+#undef HLTQ_CONCAT
+#define HLTQ_CONCAT(queue1, queue2, field) do { \
+ (queue2)->field.tqe_prev = (queue1)->field.tqe_prev; \
+ *(queue1)->field.tqe_prev = (queue2); \
+ (queue1)->field.tqe_prev = &(queue2)->field.tqe_next; \
+} while (0)
+
+/* Convert a headless tailq to a headful one. */
+#define HLTQ_TO_TAILQ(head, hl, field) do { \
+ (head)->tqh_first = (hl); \
+ (head)->tqh_last = (hl)->field.tqe_prev; \
+ (hl)->field.tqe_prev = &(head)->tqh_first; \
+} while (0)
+
+/* Concatenate a headless tail queue to the end of a regular tail queue. */
+#define TAILQ_CONCAT_HLTQ(head, hl, field) do { \
+ void *last = (hl)->field.tqe_prev; \
+ (hl)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (hl); \
+ (head)->tqh_last = last; \
+} while (0)
+
+#endif /* !SUDO_QUEUE_H */
diff --git a/include/sudo_rand.h b/include/sudo_rand.h
new file mode 100644
index 0000000..d030ed0
--- /dev/null
+++ b/include/sudo_rand.h
@@ -0,0 +1,57 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#ifndef SUDO_RAND_H
+#define SUDO_RAND_H
+
+#include <stdlib.h> /* For arc4random() on systems that have it */
+
+/*
+ * All libc replacements are prefixed with "sudo_" to avoid namespace issues.
+ */
+
+#ifndef HAVE_ARC4RANDOM
+sudo_dso_public uint32_t sudo_arc4random(void);
+# undef arc4random
+# define arc4random() sudo_arc4random()
+#endif /* ARC4RANDOM */
+
+#ifndef HAVE_ARC4RANDOM_BUF
+sudo_dso_public void sudo_arc4random_buf(void *buf, size_t n);
+# undef arc4random_buf
+# define arc4random_buf(a, b) sudo_arc4random_buf((a), (b))
+#endif /* ARC4RANDOM_BUF */
+
+#ifndef HAVE_ARC4RANDOM_UNIFORM
+sudo_dso_public uint32_t sudo_arc4random_uniform(uint32_t upper_bound);
+# undef arc4random_uniform
+# define arc4random_uniform(_a) sudo_arc4random_uniform((_a))
+#endif /* ARC4RANDOM_UNIFORM */
+
+#ifndef HAVE_GETENTROPY
+/* Note: not exported by libutil. */
+int sudo_getentropy(void *buf, size_t buflen);
+# undef getentropy
+# define getentropy(_a, _b) sudo_getentropy((_a), (_b))
+#endif /* HAVE_GETENTROPY */
+
+#endif /* SUDO_RAND_H */
diff --git a/include/sudo_ssl_compat.h b/include/sudo_ssl_compat.h
new file mode 100644
index 0000000..1f09472
--- /dev/null
+++ b/include/sudo_ssl_compat.h
@@ -0,0 +1,46 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_SSL_COMPAT_H
+#define SUDO_SSL_COMPAT_H
+
+# ifdef HAVE_OPENSSL
+
+/*
+ * Compatibility defines for OpenSSL 1.0.2 (not needed for 1.1.x)
+ */
+# ifndef HAVE_WOLFSSL
+# ifndef HAVE_X509_STORE_CTX_GET0_CERT
+# define X509_STORE_CTX_get0_cert(x) ((x)->cert)
+# endif
+# ifndef HAVE_TLS_METHOD
+# define TLS_method() SSLv23_method()
+# endif
+# endif /* !HAVE_WOLFSSL */
+
+/*
+ * SSL_read_ex() and SSL_write_ex() were added in OpenSSL 1.1.1.
+ */
+# ifndef HAVE_SSL_READ_EX
+int SSL_read_ex(SSL *, void *, size_t, size_t *);
+int SSL_write_ex(SSL *, const void *, size_t, size_t *);
+# endif /* HAVE_SSL_READ_EX */
+
+# endif /* HAVE_OPENSSL */
+
+#endif /* SUDO_SSL_COMPAT_H */
diff --git a/include/sudo_util.h b/include/sudo_util.h
new file mode 100644
index 0000000..d534d40
--- /dev/null
+++ b/include/sudo_util.h
@@ -0,0 +1,358 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_UTIL_H
+#define SUDO_UTIL_H
+
+#include <sys/types.h> /* for dev_t, mode_t, gid_t, size_t, ssize_t, uid_t */
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+
+#ifdef __TANDEM
+# define ROOT_UID 65535
+#else
+# define ROOT_UID 0
+#endif
+#define ROOT_GID 0
+
+#ifndef TIME_T_MIN
+# if SIZEOF_TIME_T == 8
+# define TIME_T_MIN LLONG_MIN
+# else
+# define TIME_T_MIN INT_MIN
+# endif
+#endif
+#ifndef TIME_T_MAX
+# if SIZEOF_TIME_T == 8
+# define TIME_T_MAX LLONG_MAX
+# else
+# define TIME_T_MAX INT_MAX
+# endif
+#endif
+
+/*
+ * Macros for operating on struct timespec.
+ */
+#define sudo_timespecclear(ts) ((ts)->tv_sec = (ts)->tv_nsec = 0)
+
+#define sudo_timespecisset(ts) ((ts)->tv_sec || (ts)->tv_nsec)
+
+#define sudo_timespeccmp(ts1, ts2, op) \
+ (((ts1)->tv_sec == (ts2)->tv_sec) ? \
+ ((ts1)->tv_nsec op (ts2)->tv_nsec) : \
+ ((ts1)->tv_sec op (ts2)->tv_sec))
+
+#define sudo_timespecadd(ts1, ts2, ts3) \
+ do { \
+ (ts3)->tv_sec = (ts1)->tv_sec + (ts2)->tv_sec; \
+ (ts3)->tv_nsec = (ts1)->tv_nsec + (ts2)->tv_nsec; \
+ while ((ts3)->tv_nsec >= 1000000000) { \
+ (ts3)->tv_sec++; \
+ (ts3)->tv_nsec -= 1000000000; \
+ } \
+ } while (0)
+
+#define sudo_timespecsub(ts1, ts2, ts3) \
+ do { \
+ (ts3)->tv_sec = (ts1)->tv_sec - (ts2)->tv_sec; \
+ (ts3)->tv_nsec = (ts1)->tv_nsec - (ts2)->tv_nsec; \
+ while ((ts3)->tv_nsec < 0) { \
+ (ts3)->tv_sec--; \
+ (ts3)->tv_nsec += 1000000000; \
+ } \
+ } while (0)
+
+#ifndef TIMEVAL_TO_TIMESPEC
+# define TIMEVAL_TO_TIMESPEC(tv, ts) \
+ do { \
+ (ts)->tv_sec = (tv)->tv_sec; \
+ (ts)->tv_nsec = (tv)->tv_usec * 1000; \
+ } while (0)
+#endif
+
+#ifndef TIMESPEC_TO_TIMEVAL
+# define TIMESPEC_TO_TIMEVAL(tv, ts) \
+ do { \
+ (tv)->tv_sec = (ts)->tv_sec; \
+ (tv)->tv_usec = (ts)->tv_nsec / 1000; \
+ } while (0)
+#endif
+
+/*
+ * The timespec version of st_mtime may vary on different platforms.
+ */
+#if defined(HAVE_ST_MTIM)
+# if defined(HAVE_ST__TIM)
+# define SUDO_ST_MTIM st_mtim.st__tim
+# else
+# define SUDO_ST_MTIM st_mtim
+# endif
+#elif defined(HAVE_ST_MTIMESPEC)
+# define SUDO_ST_MTIM st_mtimespec
+#endif
+
+/*
+ * Macro to extract mtime as timespec.
+ * If there is no way to set the timestamp using nanosecond precision,
+ * we only fetch microsecond precision. Otherwise there is a mismatch
+ * between the timestamp we read and the one we wrote.
+ */
+#if defined(SUDO_ST_MTIM)
+# if defined(HAVE_FUTIMENS) && defined(HAVE_UTIMENSAT)
+# define mtim_get(_x, _y) do { (_y).tv_sec = (_x)->SUDO_ST_MTIM.tv_sec; (_y).tv_nsec = (_x)->SUDO_ST_MTIM.tv_nsec; } while (0)
+# else
+# define mtim_get(_x, _y) do { (_y).tv_sec = (_x)->SUDO_ST_MTIM.tv_sec; (_y).tv_nsec = ((_x)->SUDO_ST_MTIM.tv_nsec / 1000) * 1000; } while (0)
+# endif
+#elif defined(HAVE_ST_NMTIME)
+# define mtim_get(_x, _y) do { (_y).tv_sec = (_x)->st_mtime; (_y).tv_nsec = (_x)->st_nmtime; } while (0)
+#else
+# define mtim_get(_x, _y) do { (_y).tv_sec = (_x)->st_mtime; (_y).tv_nsec = 0; } while (0)
+#endif /* HAVE_ST_MTIM */
+
+/* sizeof() that returns a signed value */
+#define ssizeof(_x) ((ssize_t)sizeof(_x))
+
+/* Bit map macros. */
+#define sudo_setbit(_a, _i) ((_a)[(_i) / NBBY] |= 1U << ((_i) % NBBY))
+#define sudo_clrbit(_a, _i) ((_a)[(_i) / NBBY] &= ~(1U << ((_i) % NBBY)))
+#define sudo_isset(_a, _i) ((_a)[(_i) / NBBY] & (1U << ((_i) % NBBY)))
+#define sudo_isclr(_a, _i) (((_a)[(_i) / NBBY] & (1U << ((_i) % NBBY))) == 0)
+
+/* Macros to determine the length of a type in string form. */
+#define STRLEN_MAX_UNSIGNED(t) (((sizeof(t) * 8 * 1233) >> 12) + 1)
+#define STRLEN_MAX_SIGNED(t) (STRLEN_MAX_UNSIGNED(t) + ((sizeof(t) == 8) ? 0 : 1))
+
+/* sudo_parseln() flags */
+#define PARSELN_COMM_BOL 0x01 /* comments only at beginning of line */
+#define PARSELN_CONT_IGN 0x02 /* ignore line continuation char */
+
+/*
+ * Macros to quiet gcc's warn_unused_result attribute.
+ */
+#ifdef __GNUC__
+# define ignore_result(x) do { \
+ __typeof__(x) y = (x); \
+ (void)y; \
+} while(0)
+#else
+# define ignore_result(x) (void)(x)
+#endif
+
+/* Forward struct declarations. */
+struct stat;
+
+/* aix.c */
+sudo_dso_public int aix_getauthregistry_v1(char *user, char *saved_registry);
+#define aix_getauthregistry(_a, _b) aix_getauthregistry_v1((_a), (_b))
+sudo_dso_public int aix_prep_user_v1(char *user, const char *tty);
+#define aix_prep_user(_a, _b) aix_prep_user_v1((_a), (_b))
+sudo_dso_public int aix_restoreauthdb_v1(void);
+#define aix_restoreauthdb() aix_restoreauthdb_v1()
+sudo_dso_public int aix_setauthdb_v1(char *user);
+sudo_dso_public int aix_setauthdb_v2(char *user, char *registry);
+#define aix_setauthdb(_a, _b) aix_setauthdb_v2((_a), (_b))
+
+/* basename.c */
+sudo_dso_public char *sudo_basename_v1(const char *filename);
+#define sudo_basename(_a) sudo_basename_v1(_a)
+
+/* gethostname.c */
+sudo_dso_public char *sudo_gethostname_v1(void);
+#define sudo_gethostname() sudo_gethostname_v1()
+
+/* gettime.c */
+sudo_dso_public int sudo_gettime_awake_v1(struct timespec *ts);
+#define sudo_gettime_awake(_a) sudo_gettime_awake_v1((_a))
+sudo_dso_public int sudo_gettime_mono_v1(struct timespec *ts);
+#define sudo_gettime_mono(_a) sudo_gettime_mono_v1((_a))
+sudo_dso_public int sudo_gettime_real_v1(struct timespec *ts);
+#define sudo_gettime_real(_a) sudo_gettime_real_v1((_a))
+
+/* gidlist.c */
+sudo_dso_public int sudo_parse_gids_v1(const char *gidstr, const gid_t *basegid, GETGROUPS_T **gidsp);
+#define sudo_parse_gids(_a, _b, _c) sudo_parse_gids_v1((_a), (_b), (_c))
+
+/* getgrouplist.c */
+sudo_dso_public int sudo_getgrouplist2_v1(const char *name, gid_t basegid, GETGROUPS_T **groupsp, int *ngroupsp);
+#define sudo_getgrouplist2(_a, _b, _c, _d) sudo_getgrouplist2_v1((_a), (_b), (_c), (_d))
+
+/* hexchar.c */
+sudo_dso_public int sudo_hexchar_v1(const char *s);
+#define sudo_hexchar(_a) sudo_hexchar_v1(_a)
+
+/* key_val.c */
+sudo_dso_public char *sudo_new_key_val_v1(const char *key, const char *value);
+#define sudo_new_key_val(_a, _b) sudo_new_key_val_v1((_a), (_b))
+
+/* locking.c */
+#define SUDO_LOCK 1 /* lock a file */
+#define SUDO_TLOCK 2 /* test & lock a file (non-blocking) */
+#define SUDO_UNLOCK 4 /* unlock a file */
+sudo_dso_public bool sudo_lock_file_v1(int fd, int action);
+#define sudo_lock_file(_a, _b) sudo_lock_file_v1((_a), (_b))
+sudo_dso_public bool sudo_lock_region_v1(int fd, int action, off_t len);
+#define sudo_lock_region(_a, _b, _c) sudo_lock_region_v1((_a), (_b), (_c))
+
+/* logfac.c */
+sudo_dso_public bool sudo_str2logfac_v1(const char *str, int *logfac);
+#define sudo_str2logfac(_a, _b) sudo_str2logfac_v1((_a), (_b))
+sudo_dso_public const char *sudo_logfac2str_v1(int num);
+#define sudo_logfac2str(_a) sudo_logfac2str_v1((_a))
+
+/* logpri.c */
+sudo_dso_public bool sudo_str2logpri_v1(const char *str, int *logpri);
+#define sudo_str2logpri(_a, _b) sudo_str2logpri_v1((_a), (_b))
+sudo_dso_public const char *sudo_logpri2str_v1(int num);
+#define sudo_logpri2str(_a) sudo_logpri2str_v1((_a))
+
+/* mkdir_parents.c */
+sudo_dso_public bool sudo_mkdir_parents_v1(const char *path, uid_t uid, gid_t gid, mode_t mode, bool quiet);
+#define sudo_mkdir_parents(_a, _b, _c, _d, _e) sudo_mkdir_parents_v1((_a), (_b), (_c), (_d), (_e))
+sudo_dso_public int sudo_open_parent_dir_v1(const char *path, uid_t uid, gid_t gid, mode_t mode, bool quiet);
+#define sudo_open_parent_dir(_a, _b, _c, _d, _e) sudo_open_parent_dir_v1((_a), (_b), (_c), (_d), (_e))
+
+/* mmap_alloc.c */
+sudo_dso_public void *sudo_mmap_alloc_v1(size_t size) sudo_malloclike;
+#define sudo_mmap_alloc(_a) sudo_mmap_alloc_v1(_a)
+sudo_dso_public void *sudo_mmap_allocarray_v1(size_t count, size_t size) sudo_malloclike;
+#define sudo_mmap_allocarray(_a, _b) sudo_mmap_allocarray_v1((_a), (_b))
+sudo_dso_public char *sudo_mmap_strdup_v1(const char *str);
+#define sudo_mmap_strdup(_a) sudo_mmap_strdup_v1(_a)
+sudo_dso_public void sudo_mmap_free_v1(void *ptr);
+#define sudo_mmap_free(_a) sudo_mmap_free_v1(_a)
+sudo_dso_public int sudo_mmap_protect_v1(void *ptr);
+#define sudo_mmap_protect(_a) sudo_mmap_protect_v1(_a)
+
+/* multiarch.c */
+sudo_dso_public char *sudo_stat_multiarch_v1(const char *path, struct stat *sb);
+#define sudo_stat_multiarch(_a, _b) sudo_stat_multiarch_v1((_a), (_b))
+
+/* parseln.c */
+sudo_dso_public ssize_t sudo_parseln_v1(char **buf, size_t *bufsize, unsigned int *lineno, FILE *fp);
+sudo_dso_public ssize_t sudo_parseln_v2(char **buf, size_t *bufsize, unsigned int *lineno, FILE *fp, int flags);
+#define sudo_parseln(_a, _b, _c, _d, _e) sudo_parseln_v2((_a), (_b), (_c), (_d), (_e))
+
+/* progname.c */
+sudo_dso_public void initprogname(const char *);
+sudo_dso_public void initprogname2(const char *, const char * const *);
+
+/* rcstr.c */
+sudo_dso_public char *sudo_rcstr_dup(const char *src);
+sudo_dso_public char *sudo_rcstr_alloc(size_t len) sudo_malloclike;
+sudo_dso_public char *sudo_rcstr_addref(const char *s);
+sudo_dso_public void sudo_rcstr_delref(const char *s);
+
+/* regex.c */
+sudo_dso_public bool sudo_regex_compile_v1(void *v, const char *pattern, const char **errstr);
+#define sudo_regex_compile(_a, _b, _c) sudo_regex_compile_v1((_a), (_b), (_c))
+
+/* roundup.c */
+sudo_dso_public unsigned int sudo_pow2_roundup_v1(unsigned int len);
+sudo_dso_public size_t sudo_pow2_roundup_v2(size_t len);
+#define sudo_pow2_roundup(_a) sudo_pow2_roundup_v2((_a))
+
+/* secure_path.c */
+#define SUDO_PATH_SECURE 0
+#define SUDO_PATH_MISSING -1
+#define SUDO_PATH_BAD_TYPE -2
+#define SUDO_PATH_WRONG_OWNER -3
+#define SUDO_PATH_WORLD_WRITABLE -4
+#define SUDO_PATH_GROUP_WRITABLE -5
+sudo_dso_public int sudo_secure_dir_v1(const char *path, uid_t uid, gid_t gid, struct stat *sb);
+#define sudo_secure_dir(_a, _b, _c, _d) sudo_secure_dir_v1((_a), (_b), (_c), (_d))
+sudo_dso_public int sudo_secure_fd_v1(int fd, unsigned int type, uid_t uid, gid_t gid, struct stat *sb);
+#define sudo_secure_fd(_a, _b, _c, _d, _e) sudo_secure_fd_v1((_a), (_b), (_c), (_d), (_e))
+sudo_dso_public int sudo_secure_file_v1(const char *path, uid_t uid, gid_t gid, struct stat *sb);
+#define sudo_secure_file(_a, _b, _c, _d) sudo_secure_file_v1((_a), (_b), (_c), (_d))
+sudo_dso_public int sudo_secure_open_file_v1(const char *path, uid_t uid, gid_t gid, struct stat *sb, int *error);
+#define sudo_secure_open_file(_a, _b, _c, _d, _e) sudo_secure_open_file_v1((_a), (_b), (_c), (_d), (_e))
+sudo_dso_public int sudo_secure_open_dir_v1(const char *path, uid_t uid, gid_t gid, struct stat *sb, int *error);
+#define sudo_secure_open_dir(_a, _b, _c, _d, _e) sudo_secure_open_dir_v1((_a), (_b), (_c), (_d), (_e))
+sudo_dso_public int sudo_open_conf_path_v1(const char *path, char *name, size_t namesize, int (*fn)(const char *, int));
+#define sudo_open_conf_path(_a, _b, _c, _d) sudo_open_conf_path_v1((_a), (_b), (_c), (_d))
+
+/* setgroups.c */
+sudo_dso_public int sudo_setgroups_v1(int ngids, const GETGROUPS_T *gids);
+#define sudo_setgroups(_a, _b) sudo_setgroups_v1((_a), (_b))
+
+/* strsplit.c */
+sudo_dso_public const char *sudo_strsplit_v1(const char *str, const char *endstr, const char *sep, const char **last);
+#define sudo_strsplit(_a, _b, _c, _d) sudo_strsplit_v1(_a, _b, _c, _d)
+
+/* strtobool.c */
+sudo_dso_public int sudo_strtobool_v1(const char *str);
+#define sudo_strtobool(_a) sudo_strtobool_v1((_a))
+
+/* strtonum.c */
+/* Not versioned for historical reasons. */
+sudo_dso_public long long sudo_strtonum(const char *, long long, long long, const char **);
+/* Not currently exported. */
+long long sudo_strtonumx(const char *str, long long minval, long long maxval, char **endp, const char **errstrp);
+
+/* strtoid.c */
+sudo_dso_public id_t sudo_strtoid_v1(const char *str, const char *sep, char **endp, const char **errstr);
+sudo_dso_public id_t sudo_strtoid_v2(const char *str, const char **errstr);
+#define sudo_strtoid(_a, _b) sudo_strtoid_v2((_a), (_b))
+sudo_dso_public id_t sudo_strtoidx_v1(const char *str, const char *sep, char **endp, const char **errstr);
+#define sudo_strtoidx(_a, _b, _c, _d) sudo_strtoidx_v1((_a), (_b), (_c), (_d))
+
+/* strtomode.c */
+sudo_dso_public int sudo_strtomode_v1(const char *cp, const char **errstr);
+sudo_dso_public mode_t sudo_strtomode_v2(const char *cp, const char **errstr);
+#define sudo_strtomode(_a, _b) sudo_strtomode_v2((_a), (_b))
+
+/* sudo_printf.c */
+extern int (*sudo_printf)(int msg_type, const char * restrict fmt, ...);
+
+/* term.c */
+#define SUDO_TERM_ISIG 0x01U
+#define SUDO_TERM_OFLAG 0x02U
+sudo_dso_public bool sudo_isatty_v1(int fd, struct stat *sbp);
+#define sudo_isatty(_a, _b) sudo_isatty_v1((_a), (_b))
+sudo_dso_public bool sudo_term_cbreak_v1(int fd);
+#define sudo_term_cbreak(_a) sudo_term_cbreak_v1((_a))
+sudo_dso_public bool sudo_term_copy_v1(int src, int dst);
+#define sudo_term_copy(_a, _b) sudo_term_copy_v1((_a), (_b))
+sudo_dso_public bool sudo_term_noecho_v1(int fd);
+#define sudo_term_noecho(_a) sudo_term_noecho_v1((_a))
+sudo_dso_public bool sudo_term_raw_v1(int fd, unsigned int flags);
+#define sudo_term_raw(_a, _b) sudo_term_raw_v1((_a), (_b))
+sudo_dso_public bool sudo_term_restore_v1(int fd, bool flush);
+#define sudo_term_restore(_a, _b) sudo_term_restore_v1((_a), (_b))
+sudo_dso_public bool sudo_term_is_raw_v1(int fd);
+#define sudo_term_is_raw(_a) sudo_term_is_raw_v1((_a))
+
+/* ttyname_dev.c */
+sudo_dso_public char *sudo_ttyname_dev_v1(dev_t tdev, char *name, size_t namelen);
+#define sudo_ttyname_dev(_a, _b, _c) sudo_ttyname_dev_v1((_a), (_b), (_c))
+
+/* ttysize.c */
+sudo_dso_public void sudo_get_ttysize_v1(int *rowp, int *colp);
+sudo_dso_public void sudo_get_ttysize_v2(int fd, int *rowp, int *colp);
+#define sudo_get_ttysize(_a, _b, _c) sudo_get_ttysize_v2((_a), (_b), (_c))
+
+/* uuid.c */
+sudo_dso_public void sudo_uuid_create_v1(unsigned char uuid_out[16]);
+#define sudo_uuid_create(_a) sudo_uuid_create_v1((_a))
+sudo_dso_public char *sudo_uuid_to_string_v1(unsigned char uuid[16], char *dst, size_t dstsiz);
+#define sudo_uuid_to_string(_a, _b, _c) sudo_uuid_to_string_v1((_a), (_b), (_c))
+
+#endif /* SUDO_UTIL_H */
diff --git a/lib/eventlog/Makefile.in b/lib/eventlog/Makefile.in
new file mode 100644
index 0000000..8bfd959
--- /dev/null
+++ b/lib/eventlog/Makefile.in
@@ -0,0 +1,350 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2020-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+devdir = @devdir@
+scriptdir = $(top_srcdir)/scripts
+incdir = $(top_srcdir)/include
+
+# Compiler & tools to use
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+EGREP = @EGREP@
+SED = @SED@
+
+# C preprocessor flags
+CPPFLAGS = -I$(incdir) -I$(top_builddir) -I$(srcdir) -I$(top_srcdir) @CPPFLAGS@
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+
+# Flags to pass to the link stage
+LDFLAGS = @LDFLAGS@
+
+# Flags to pass to libtool
+LTFLAGS = @LT_STATIC@
+
+# Libraries
+LIBUTIL = $(top_builddir)/lib/util/libsudo_util.la
+LT_LIBS = $(LIBUTIL)
+LIBS = $(LT_LIBS)
+
+# Address sanitizer flags
+ASAN_CFLAGS = @ASAN_CFLAGS@
+ASAN_LDFLAGS = @ASAN_LDFLAGS@
+
+# PIE flags
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+
+# Stack smashing protection flags
+HARDENING_CFLAGS = @HARDENING_CFLAGS@
+HARDENING_LDFLAGS = @HARDENING_LDFLAGS@
+
+# cppcheck options, usually set in the top-level Makefile
+CPPCHECK_OPTS = -q --enable=warning,performance,portability --suppress=constStatement --suppress=compareBoolExpressionWithInt --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
+
+# splint options, usually set in the top-level Makefile
+SPLINT_OPTS = -D__restrict= -checks
+
+# PVS-studio options
+PVS_CFG = $(top_srcdir)/PVS-Studio.cfg
+PVS_IGNORE = 'V707,V011,V002,V536'
+PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
+
+# Set to non-empty for development mode
+DEVEL = @DEVEL@
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+TEST_PROGS = check_wrap check_parse_json store_json_test store_sudo_test
+TEST_VERBOSE =
+
+LIBEVENTLOG_OBJS = eventlog.lo eventlog_conf.lo eventlog_free.lo logwrap.lo \
+ parse_json.lo
+
+IOBJS = $(LIBEVENTLOG_OBJS:.lo=.i)
+
+POBJS = $(IOBJS:.i=.plog)
+
+CHECK_WRAP_OBJS = check_wrap.lo logwrap.lo
+
+CHECK_PARSE_JSON_OBJS = check_parse_json.lo parse_json.lo
+
+STORE_JSON_TEST_OBJS = store_json_test.lo
+
+STORE_SUDO_TEST_OBJS = store_sudo_test.lo
+
+all: libsudo_eventlog.la
+
+depend:
+ $(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
+ --builddir=$(abs_top_builddir) lib/eventlog/Makefile.in
+ cd $(top_builddir) && ./config.status --file lib/eventlog/Makefile
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file lib/eventlog/Makefile
+
+.SUFFIXES: .c .h .i .lo .plog
+
+.c.lo:
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.i:
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+
+.i.plog:
+ ifile=$<; rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $${ifile%i}c --i-file $< --output-file $@
+
+libsudo_eventlog.la: $(LIBEVENTLOG_OBJS) $(LT_LIBS)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LIBEVENTLOG_OBJS) $(LT_LIBS)
+
+check_parse_json: $(CHECK_PARSE_JSON_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_PARSE_JSON_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS)
+
+check_wrap: $(CHECK_WRAP_OBJS) $(LIBUTIL) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_WRAP_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS)
+
+store_json_test: $(STORE_JSON_TEST_OBJS) $(LIBUTIL) libsudo_eventlog.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(STORE_JSON_TEST_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS) libsudo_eventlog.la
+
+store_sudo_test: $(STORE_SUDO_TEST_OBJS) $(LIBUTIL) libsudo_eventlog.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(STORE_SUDO_TEST_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS) libsudo_eventlog.la
+
+pre-install:
+
+install:
+
+install-binaries:
+
+install-includes:
+
+install-doc:
+
+install-plugin:
+
+install-fuzzer:
+
+uninstall:
+
+splint:
+ splint $(SPLINT_OPTS) -I$(incdir) -I$(top_builddir) -I$(top_srcdir) $(srcdir)/*.c
+
+cppcheck:
+ cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) -I$(top_srcdir) $(srcdir)/*.c
+
+pvs-log-files: $(POBJS)
+
+pvs-studio: $(POBJS)
+ plog-converter $(PVS_LOG_OPTS) $(POBJS)
+
+fuzz:
+
+check-fuzzer:
+
+check: $(TEST_PROGS) check-fuzzer
+ @if test X"$(cross_compiling)" != X"yes"; then \
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ umask 022; \
+ rval=0; \
+ ./check_parse_json $(TEST_VERBOSE) $(srcdir)/regress/parse_json/*.in || rval=`expr $$rval + $$?`; \
+ ./store_json_test $(TEST_VERBOSE) $(srcdir)/regress/eventlog_store/*.json.in || rval=`expr $$rval + $$?`; \
+ ./store_sudo_test $(TEST_VERBOSE) $(srcdir)/regress/eventlog_store/*.json.in || rval=`expr $$rval + $$?`; \
+ mkdir -p regress/logwrap; \
+ ./check_wrap $(TEST_VERBOSE) $(srcdir)/regress/logwrap/check_wrap.in > regress/logwrap/check_wrap.out; \
+ diff regress/logwrap/check_wrap.out $(srcdir)/regress/logwrap/check_wrap.out.ok || rval=`expr $$rval + $$?`; \
+ exit $$rval; \
+ fi
+
+check-verbose:
+ exec $(MAKE) $(MFLAGS) TEST_VERBOSE=-v FUZZ_VERBOSE=-verbosity=1 check
+
+clean:
+ -$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f *.lo *.o *.la $(TEST_PROGS)
+ -rm -f *.i *.plog stamp-* core *.core core.* regress/*/*.out
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile .libs
+
+clobber: distclean
+
+realclean: distclean
+ rm -f TAGS tags
+
+cleandir: realclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean
+
+# Autogenerated dependencies, do not modify
+check_parse_json.lo: $(srcdir)/regress/parse_json/check_parse_json.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_json.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/parse_json.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/parse_json/check_parse_json.c
+check_parse_json.i: $(srcdir)/regress/parse_json/check_parse_json.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_json.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/parse_json.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_parse_json.plog: check_parse_json.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/parse_json/check_parse_json.c --i-file $< --output-file $@
+check_wrap.lo: $(srcdir)/regress/logwrap/check_wrap.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/logwrap/check_wrap.c
+check_wrap.i: $(srcdir)/regress/logwrap/check_wrap.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_wrap.plog: check_wrap.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/logwrap/check_wrap.c --i-file $< --output-file $@
+eventlog.lo: $(srcdir)/eventlog.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_json.h \
+ $(incdir)/sudo_lbuf.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/eventlog.c
+eventlog.i: $(srcdir)/eventlog.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_json.h \
+ $(incdir)/sudo_lbuf.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+eventlog.plog: eventlog.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/eventlog.c --i-file $< --output-file $@
+eventlog_conf.lo: $(srcdir)/eventlog_conf.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_json.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/eventlog_conf.c
+eventlog_conf.i: $(srcdir)/eventlog_conf.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_json.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+eventlog_conf.plog: eventlog_conf.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/eventlog_conf.c --i-file $< --output-file $@
+eventlog_free.lo: $(srcdir)/eventlog_free.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/eventlog_free.c
+eventlog_free.i: $(srcdir)/eventlog_free.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+eventlog_free.plog: eventlog_free.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/eventlog_free.c --i-file $< --output-file $@
+logwrap.lo: $(srcdir)/logwrap.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/logwrap.c
+logwrap.i: $(srcdir)/logwrap.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+logwrap.plog: logwrap.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/logwrap.c --i-file $< --output-file $@
+parse_json.lo: $(srcdir)/parse_json.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_json.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/parse_json.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/parse_json.c
+parse_json.i: $(srcdir)/parse_json.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_json.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/parse_json.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+parse_json.plog: parse_json.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/parse_json.c --i-file $< --output-file $@
+store_json_test.lo: $(srcdir)/regress/eventlog_store/store_json_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_json.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/parse_json.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/eventlog_store/store_json_test.c
+store_json_test.i: $(srcdir)/regress/eventlog_store/store_json_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_json.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/parse_json.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+store_json_test.plog: store_json_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/eventlog_store/store_json_test.c --i-file $< --output-file $@
+store_sudo_test.lo: $(srcdir)/regress/eventlog_store/store_sudo_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_lbuf.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/eventlog_store/store_sudo_test.c
+store_sudo_test.i: $(srcdir)/regress/eventlog_store/store_sudo_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_lbuf.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+store_sudo_test.plog: store_sudo_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/eventlog_store/store_sudo_test.c --i-file $< --output-file $@
diff --git a/lib/eventlog/eventlog.c b/lib/eventlog/eventlog.c
new file mode 100644
index 0000000..ab27227
--- /dev/null
+++ b/lib/eventlog/eventlog.c
@@ -0,0 +1,1462 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1994-1996, 1998-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <locale.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <pathnames.h>
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_eventlog.h>
+#include <sudo_lbuf.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_json.h>
+#include <sudo_queue.h>
+#include <sudo_util.h>
+
+#define IS_SESSID(s) ( \
+ isalnum((unsigned char)(s)[0]) && isalnum((unsigned char)(s)[1]) && \
+ (s)[2] == '/' && \
+ isalnum((unsigned char)(s)[3]) && isalnum((unsigned char)(s)[4]) && \
+ (s)[5] == '/' && \
+ isalnum((unsigned char)(s)[6]) && isalnum((unsigned char)(s)[7]) && \
+ (s)[8] == '\0')
+
+struct eventlog_args {
+ const char *reason;
+ const char *errstr;
+ const struct timespec *event_time;
+ eventlog_json_callback_t json_info_cb;
+ void *json_info;
+};
+
+/*
+ * Allocate and fill in a new logline.
+ */
+static bool
+new_logline(int event_type, int flags, struct eventlog_args *args,
+ const struct eventlog *evlog, struct sudo_lbuf *lbuf)
+{
+ const struct eventlog_config *evl_conf = eventlog_getconf();
+ const char *iolog_file;
+ const char *tty, *tsid = NULL;
+ char exit_str[STRLEN_MAX_SIGNED(int) + 1];
+ char sessid[7], offsetstr[64] = "";
+ size_t i;
+ debug_decl(new_logline, SUDO_DEBUG_UTIL);
+
+ if (ISSET(flags, EVLOG_RAW) || evlog == NULL) {
+ if (args->reason != NULL) {
+ if (args->errstr != NULL) {
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "%s: %s",
+ args->reason, args->errstr);
+ } else {
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "%s", args->reason);
+ }
+ if (sudo_lbuf_error(lbuf))
+ goto oom;
+ }
+ debug_return_bool(true);
+ }
+
+ /* A TSID may be a sudoers-style session ID or a free-form string. */
+ iolog_file = evlog->iolog_file;
+ if (iolog_file != NULL) {
+ if (IS_SESSID(iolog_file)) {
+ sessid[0] = iolog_file[0];
+ sessid[1] = iolog_file[1];
+ sessid[2] = iolog_file[3];
+ sessid[3] = iolog_file[4];
+ sessid[4] = iolog_file[6];
+ sessid[5] = iolog_file[7];
+ sessid[6] = '\0';
+ tsid = sessid;
+ } else {
+ tsid = iolog_file;
+ }
+ if (sudo_timespecisset(&evlog->iolog_offset)) {
+ /* Only write up to two significant digits for the decimal part. */
+ if (evlog->iolog_offset.tv_nsec > 10000000) {
+ (void)snprintf(offsetstr, sizeof(offsetstr), "@%lld.%02ld",
+ (long long)evlog->iolog_offset.tv_sec,
+ evlog->iolog_offset.tv_nsec / 10000000);
+ } else if (evlog->iolog_offset.tv_sec != 0) {
+ (void)snprintf(offsetstr, sizeof(offsetstr), "@%lld",
+ (long long)evlog->iolog_offset.tv_sec);
+ }
+ }
+ }
+
+ /* Sudo-format logs use the short form of the ttyname. */
+ if ((tty = evlog->ttyname) != NULL) {
+ if (strncmp(tty, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
+ tty += sizeof(_PATH_DEV) - 1;
+ }
+
+ /*
+ * Format the log line as an lbuf, escaping control characters in
+ * octal form (#0nn). Error checking (ENOMEM) is done at the end.
+ */
+ if (args->reason != NULL) {
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "%s%s", args->reason,
+ args->errstr ? " : " : " ; ");
+ }
+ if (args->errstr != NULL) {
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "%s ; ", args->errstr);
+ }
+ if (evlog->submithost != NULL && !evl_conf->omit_hostname) {
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "HOST=%s ; ",
+ evlog->submithost);
+ }
+ if (tty != NULL) {
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "TTY=%s ; ", tty);
+ }
+ if (evlog->runchroot != NULL) {
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "CHROOT=%s ; ",
+ evlog->runchroot);
+ }
+ if (evlog->runcwd != NULL || evlog->cwd != NULL) {
+ if (ISSET(flags, EVLOG_CWD)) {
+ /* For sudoreplay -l output format. */
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "CWD=%s ; ",
+ evlog->runcwd ? evlog->runcwd : evlog->cwd);
+ } else if (evlog->runcwd != NULL) {
+ /* For backwards compatibility with sudo log format. */
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "PWD=%s ; ",
+ evlog->runcwd);
+ }
+ }
+ if (evlog->runuser != NULL) {
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "USER=%s ; ",
+ evlog->runuser);
+ }
+ if (evlog->rungroup != NULL) {
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "GROUP=%s ; ",
+ evlog->rungroup);
+ }
+ if (tsid != NULL) {
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "TSID=%s%s ; ", tsid,
+ offsetstr);
+ }
+ if (evlog->env_add != NULL && evlog->env_add[0] != NULL) {
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "ENV=%s",
+ evlog->env_add[0]);
+ for (i = 1; evlog->env_add[i] != NULL; i++) {
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, " %s",
+ evlog->env_add[i]);
+ }
+ sudo_lbuf_append(lbuf, " ; ");
+ }
+ if (evlog->command != NULL && evlog->runargv != NULL) {
+ /* Command plus argv. */
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL|LBUF_ESC_BLANK,
+ "COMMAND=%s", evlog->command);
+ if (evlog->runargv[0] != NULL) {
+ for (i = 1; evlog->runargv[i] != NULL; i++) {
+ sudo_lbuf_append(lbuf, " ");
+ if (strchr(evlog->runargv[i], ' ') != NULL) {
+ /* Wrap args containing spaces in single quotes. */
+ sudo_lbuf_append(lbuf, "'");
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL|LBUF_ESC_QUOTE,
+ "%s", evlog->runargv[i]);
+ sudo_lbuf_append(lbuf, "'");
+ } else {
+ /* Escape quotes here too for consistency. */
+ sudo_lbuf_append_esc(lbuf,
+ LBUF_ESC_CNTRL|LBUF_ESC_BLANK|LBUF_ESC_QUOTE,
+ "%s", evlog->runargv[i]);
+ }
+ }
+ }
+ if (event_type == EVLOG_EXIT) {
+ if (evlog->signal_name != NULL) {
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, " ; SIGNAL=%s",
+ evlog->signal_name);
+ }
+ if (evlog->exit_value != -1) {
+ (void)snprintf(exit_str, sizeof(exit_str), "%d",
+ evlog->exit_value);
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, " ; EXIT=%s",
+ exit_str);
+ }
+ }
+ } else if (evlog->command != NULL) {
+ /* Just the command, no argv. */
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "COMMAND=%s",
+ evlog->command);
+ }
+
+ if (!sudo_lbuf_error(lbuf))
+ debug_return_bool(true);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+}
+
+bool
+eventlog_store_sudo(int event_type, const struct eventlog *evlog,
+ struct sudo_lbuf *lbuf)
+{
+ struct eventlog_args args = { NULL };
+
+ return new_logline(event_type, EVLOG_CWD, &args, evlog, lbuf);
+}
+
+static void
+closefrom_nodebug(int lowfd)
+{
+ unsigned char *debug_fds;
+ int fd, startfd;
+ debug_decl(closefrom_nodebug, SUDO_DEBUG_UTIL);
+
+ startfd = sudo_debug_get_fds(&debug_fds) + 1;
+ if (lowfd > startfd)
+ startfd = lowfd;
+
+ /* Close fds higher than the debug fds. */
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "closing fds >= %d", startfd);
+ closefrom(startfd);
+
+ /* Close fds [lowfd, startfd) that are not in debug_fds. */
+ for (fd = lowfd; fd < startfd; fd++) {
+ if (sudo_isset(debug_fds, fd))
+ continue;
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "closing fd %d", fd);
+#ifdef __APPLE__
+ /* Avoid potential libdispatch crash when we close its fds. */
+ (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
+#else
+ (void) close(fd);
+#endif
+ }
+ debug_return;
+}
+
+#define MAX_MAILFLAGS 63
+
+sudo_noreturn static void
+exec_mailer(int pipein)
+{
+ const struct eventlog_config *evl_conf = eventlog_getconf();
+ char *last, *mflags, *p, *argv[MAX_MAILFLAGS + 1];
+ const char *mpath = evl_conf->mailerpath;
+ size_t i;
+ const char * const root_envp[] = {
+ "HOME=/",
+ "PATH=/usr/bin:/bin:/usr/sbin:/sbin",
+ "LOGNAME=root",
+ "USER=root",
+# ifdef _AIX
+ "LOGIN=root",
+# endif
+ NULL
+ };
+ debug_decl(exec_mailer, SUDO_DEBUG_UTIL);
+
+ /* Set stdin to read side of the pipe. */
+ if (dup3(pipein, STDIN_FILENO, 0) == -1) {
+ syslog(LOG_ERR, _("unable to dup stdin: %m")); // -V618
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "unable to dup stdin: %s", strerror(errno));
+ sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
+ _exit(127);
+ }
+
+ /* Build up an argv based on the mailer path and flags */
+ if ((mflags = strdup(evl_conf->mailerflags)) == NULL) {
+ syslog(LOG_ERR, _("unable to allocate memory")); // -V618
+ sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
+ _exit(127);
+ }
+ argv[0] = sudo_basename(mpath);
+
+ i = 1;
+ for (p = strtok_r(mflags, " \t", &last); p != NULL;
+ p = strtok_r(NULL, " \t", &last)) {
+ if (i < MAX_MAILFLAGS)
+ argv[i++] = p;
+ }
+ argv[i] = NULL;
+
+ /*
+ * Depending on the config, either run the mailer as root
+ * (so user cannot kill it) or as the user (for the paranoid).
+ */
+ if (setuid(ROOT_UID) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to change uid to %u",
+ ROOT_UID);
+ }
+ if (evl_conf->mailuid != ROOT_UID) {
+ if (setuid(evl_conf->mailuid) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to change uid to %u",
+ (unsigned int)evl_conf->mailuid);
+ }
+ }
+ sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
+ if (evl_conf->mailuid == ROOT_UID)
+ execve(mpath, argv, (char **)root_envp);
+ else
+ execv(mpath, argv);
+ syslog(LOG_ERR, _("unable to execute %s: %m"), mpath); // -V618
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to execute %s: %s",
+ mpath, strerror(errno));
+ _exit(127);
+}
+
+/* Send a message to the mailto user */
+static bool
+send_mail(const struct eventlog *evlog, const char *message)
+{
+ const struct eventlog_config *evl_conf = eventlog_getconf();
+ const char *cp, *timefmt = evl_conf->time_fmt;
+ struct sigaction sa;
+ char timebuf[1024];
+ sigset_t chldmask;
+ struct tm tm;
+ time_t now;
+ FILE *mail;
+ int fd, pfd[2], status;
+ size_t len;
+ pid_t pid, rv;
+ struct stat sb;
+#if defined(HAVE_NL_LANGINFO) && defined(CODESET)
+ char *locale;
+#endif
+ debug_decl(send_mail, SUDO_DEBUG_UTIL);
+
+ /* If mailer is disabled just return. */
+ if (evl_conf->mailerpath == NULL || evl_conf->mailto == NULL)
+ debug_return_bool(true);
+
+ /* Make sure the mailer exists and is a regular file. */
+ if (stat(evl_conf->mailerpath, &sb) != 0 || !S_ISREG(sb.st_mode))
+ debug_return_bool(false);
+
+ time(&now);
+ if (localtime_r(&now, &tm) == NULL)
+ debug_return_bool(false);
+
+ /* Block SIGCHLD for the duration since we call waitpid() below. */
+ sigemptyset(&chldmask);
+ sigaddset(&chldmask, SIGCHLD);
+ (void)sigprocmask(SIG_BLOCK, &chldmask, NULL);
+
+ /* Fork and return, child will daemonize. */
+ switch (pid = sudo_debug_fork()) {
+ case -1:
+ /* Error. */
+ sudo_warn("%s", U_("unable to fork"));
+
+ /* Unblock SIGCHLD and return. */
+ (void)sigprocmask(SIG_UNBLOCK, &chldmask, NULL);
+ debug_return_bool(false);
+ case 0:
+ /* Child. */
+ switch (fork()) {
+ case -1:
+ /* Error. */
+ syslog(LOG_ERR, _("unable to fork: %m")); // -V618
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to fork: %s",
+ strerror(errno));
+ sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
+ _exit(EXIT_FAILURE);
+ /* NOTREACHED */
+ case 0:
+ /* Grandchild continues below. */
+ sudo_debug_enter(__func__, __FILE__, __LINE__, sudo_debug_subsys);
+ break;
+ default:
+ /* Parent will wait for us. */
+ _exit(EXIT_SUCCESS);
+ /* NOTREACHED */
+ }
+ break;
+ default:
+ /* Parent. */
+ for (;;) {
+ rv = waitpid(pid, &status, 0);
+ if (rv == -1 && errno != EINTR)
+ break;
+ if (rv != -1 && !WIFSTOPPED(status))
+ break;
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "child (%d) exit value %d", (int)rv, status);
+
+ /* Unblock SIGCHLD and return. */
+ (void)sigprocmask(SIG_UNBLOCK, &chldmask, NULL);
+ debug_return_bool(true);
+ }
+
+ /* Reset SIGCHLD to default and unblock it. */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = SIG_DFL;
+ (void)sigaction(SIGCHLD, &sa, NULL);
+ (void)sigprocmask(SIG_UNBLOCK, &chldmask, NULL);
+
+ /* Daemonize - disassociate from session/tty. */
+ if (setsid() == -1)
+ sudo_warn("setsid");
+ if (chdir("/") == -1)
+ sudo_warn("chdir(/)");
+ fd = open(_PATH_DEVNULL, O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if (fd != -1) {
+ (void) dup2(fd, STDIN_FILENO);
+ (void) dup2(fd, STDOUT_FILENO);
+ (void) dup2(fd, STDERR_FILENO);
+ }
+
+ /* Close non-debug fds so we don't leak anything. */
+ closefrom_nodebug(STDERR_FILENO + 1);
+
+ if (pipe2(pfd, O_CLOEXEC) == -1) {
+ syslog(LOG_ERR, _("unable to open pipe: %m")); // -V618
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to open pipe: %s",
+ strerror(errno));
+ sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
+ _exit(EXIT_FAILURE);
+ }
+
+ switch (pid = sudo_debug_fork()) {
+ case -1:
+ /* Error. */
+ syslog(LOG_ERR, _("unable to fork: %m")); // -V618
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to fork");
+ sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
+ _exit(EXIT_FAILURE);
+ /* NOTREACHED */
+ case 0:
+ /* Child. */
+ exec_mailer(pfd[0]);
+ /* NOTREACHED */
+ }
+
+ (void) close(pfd[0]);
+ if ((mail = fdopen(pfd[1], "w")) == NULL) {
+ syslog(LOG_ERR, "fdopen: %m");
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to fdopen pipe");
+ sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
+ _exit(EXIT_FAILURE);
+ }
+
+ /* Pipes are all setup, send message. */
+ (void) fprintf(mail, "To: %s\nFrom: %s\nAuto-Submitted: %s\nSubject: ",
+ evl_conf->mailto,
+ evl_conf->mailfrom ? evl_conf->mailfrom :
+ (evlog ? evlog->submituser : "root"),
+ "auto-generated");
+ for (cp = _(evl_conf->mailsub); *cp; cp++) {
+ /* Expand escapes in the subject */
+ if (*cp == '%' && *(cp+1) != '%') {
+ switch (*(++cp)) {
+ case 'h':
+ if (evlog != NULL)
+ (void) fputs(evlog->submithost, mail);
+ break;
+ case 'u':
+ if (evlog != NULL)
+ (void) fputs(evlog->submituser, mail);
+ break;
+ default:
+ cp--;
+ break;
+ }
+ } else
+ (void) fputc(*cp, mail);
+ }
+
+#if defined(HAVE_NL_LANGINFO) && defined(CODESET)
+ locale = setlocale(LC_ALL, NULL);
+ if (locale[0] != 'C' || locale[1] != '\0')
+ (void) fprintf(mail, "\nContent-Type: text/plain; charset=\"%s\"\nContent-Transfer-Encoding: 8bit", nl_langinfo(CODESET));
+#endif /* HAVE_NL_LANGINFO && CODESET */
+
+ timebuf[sizeof(timebuf) - 1] = '\0';
+ len = strftime(timebuf, sizeof(timebuf), timefmt, &tm);
+ if (len == 0 || timebuf[sizeof(timebuf) - 1] != '\0') {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_ERROR,
+ "strftime() failed to format time: %s", timefmt);
+ /* Fall back to default time format string. */
+ timebuf[sizeof(timebuf) - 1] = '\0';
+ len = strftime(timebuf, sizeof(timebuf), "%h %e %T", &tm);
+ if (len == 0 || timebuf[sizeof(timebuf) - 1] != '\0') {
+ timebuf[0] = '\0'; /* give up */
+ }
+ }
+ if (evlog != NULL) {
+ (void) fprintf(mail, "\n\n%s : %s : %s : ", evlog->submithost, timebuf,
+ evlog->submituser);
+ } else {
+ (void) fprintf(mail, "\n\n%s : ", timebuf);
+ }
+ fputs(message, mail);
+ fputs("\n\n", mail);
+
+ fclose(mail);
+ for (;;) {
+ rv = waitpid(pid, &status, 0);
+ if (rv == -1 && errno != EINTR)
+ break;
+ if (rv != -1 && !WIFSTOPPED(status))
+ break;
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "child (%d) exit value %d", (int)rv, status);
+ sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
+ _exit(EXIT_SUCCESS);
+}
+
+static bool
+json_add_timestamp(struct json_container *jsonc, const char *name,
+ const struct timespec *ts, bool format_timestamp)
+{
+ struct json_value json_value;
+ size_t len;
+ debug_decl(json_add_timestamp, SUDO_DEBUG_PLUGIN);
+
+ if (!sudo_json_open_object(jsonc, name))
+ goto oom;
+
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = ts->tv_sec;
+ if (!sudo_json_add_value(jsonc, "seconds", &json_value))
+ goto oom;
+
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = ts->tv_nsec;
+ if (!sudo_json_add_value(jsonc, "nanoseconds", &json_value))
+ goto oom;
+
+ if (format_timestamp) {
+ const struct eventlog_config *evl_conf = eventlog_getconf();
+ const char *timefmt = evl_conf->time_fmt;
+ time_t secs = ts->tv_sec;
+ char timebuf[1024];
+ struct tm tm;
+
+ if (gmtime_r(&secs, &tm) != NULL) {
+ timebuf[sizeof(timebuf) - 1] = '\0';
+ len = strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", &tm);
+ if (len != 0 && timebuf[sizeof(timebuf) - 1] == '\0') {
+ json_value.type = JSON_STRING;
+ json_value.u.string = timebuf; // -V507
+ if (!sudo_json_add_value(jsonc, "iso8601", &json_value))
+ goto oom;
+ }
+ }
+
+ if (localtime_r(&secs, &tm) != NULL) {
+ timebuf[sizeof(timebuf) - 1] = '\0';
+ len = strftime(timebuf, sizeof(timebuf), timefmt, &tm);
+ if (len != 0 && timebuf[sizeof(timebuf) - 1] == '\0') {
+ json_value.type = JSON_STRING;
+ json_value.u.string = timebuf; // -V507
+ if (!sudo_json_add_value(jsonc, "localtime", &json_value))
+ goto oom;
+ }
+ }
+ }
+
+ if (!sudo_json_close_object(jsonc))
+ goto oom;
+
+ debug_return_bool(true);
+oom:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "%s: %s", __func__, "unable to allocate memory");
+ debug_return_bool(false);
+}
+
+/*
+ * Store the contents of struct eventlog as JSON.
+ * The submit_time and iolog_path members are not stored, they should
+ * be stored and formatted by the caller.
+ */
+bool
+eventlog_store_json(struct json_container *jsonc, const struct eventlog *evlog)
+{
+ struct json_value json_value;
+ size_t i;
+ char *cp;
+ debug_decl(eventlog_store_json, SUDO_DEBUG_UTIL);
+
+ /* Required settings. */
+ if (evlog == NULL || evlog->submituser == NULL)
+ debug_return_bool(false);
+
+ /*
+ * The most important values are written first in case
+ * the log record gets truncated.
+ * Note: submit_time and iolog_path are not stored here.
+ */
+
+ json_value.type = JSON_STRING;
+ json_value.u.string = evlog->submituser;
+ if (!sudo_json_add_value(jsonc, "submituser", &json_value))
+ goto oom;
+
+ if (evlog->command != NULL) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = evlog->command;
+ if (!sudo_json_add_value(jsonc, "command", &json_value))
+ goto oom;
+ }
+
+ if (evlog->runuser != NULL) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = evlog->runuser;
+ if (!sudo_json_add_value(jsonc, "runuser", &json_value))
+ goto oom;
+ }
+
+ if (evlog->rungroup != NULL) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = evlog->rungroup;
+ if (!sudo_json_add_value(jsonc, "rungroup", &json_value))
+ goto oom;
+ }
+
+ if (evlog->runchroot != NULL) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = evlog->runchroot;
+ if (!sudo_json_add_value(jsonc, "runchroot", &json_value))
+ goto oom;
+ }
+
+ if (evlog->runcwd != NULL) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = evlog->runcwd;
+ if (!sudo_json_add_value(jsonc, "runcwd", &json_value))
+ goto oom;
+ }
+
+ if (evlog->source != NULL) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = evlog->source;
+ if (!sudo_json_add_value(jsonc, "source", &json_value))
+ goto oom;
+ }
+
+ if (evlog->ttyname != NULL) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = evlog->ttyname;
+ if (!sudo_json_add_value(jsonc, "ttyname", &json_value))
+ goto oom;
+ }
+
+ if (evlog->submithost != NULL) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = evlog->submithost;
+ if (!sudo_json_add_value(jsonc, "submithost", &json_value))
+ goto oom;
+ }
+
+ if (evlog->cwd != NULL) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = evlog->cwd;
+ if (!sudo_json_add_value(jsonc, "submitcwd", &json_value))
+ goto oom;
+ }
+
+ if (evlog->rungroup!= NULL && evlog->rungid != (gid_t)-1) {
+ json_value.type = JSON_ID;
+ json_value.u.id = evlog->rungid;
+ if (!sudo_json_add_value(jsonc, "rungid", &json_value))
+ goto oom;
+ }
+
+ if (evlog->runuid != (uid_t)-1) {
+ json_value.type = JSON_ID;
+ json_value.u.id = evlog->runuid;
+ if (!sudo_json_add_value(jsonc, "runuid", &json_value))
+ goto oom;
+ }
+
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = evlog->columns;
+ if (!sudo_json_add_value(jsonc, "columns", &json_value))
+ goto oom;
+
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = evlog->lines;
+ if (!sudo_json_add_value(jsonc, "lines", &json_value))
+ goto oom;
+
+ if (evlog->runargv != NULL) {
+ if (!sudo_json_open_array(jsonc, "runargv"))
+ goto oom;
+ for (i = 0; (cp = evlog->runargv[i]) != NULL; i++) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = cp;
+ if (!sudo_json_add_value(jsonc, NULL, &json_value))
+ goto oom;
+ }
+ if (!sudo_json_close_array(jsonc))
+ goto oom;
+ }
+
+ if (evlog->runenv != NULL) {
+ if (!sudo_json_open_array(jsonc, "runenv"))
+ goto oom;
+ for (i = 0; (cp = evlog->runenv[i]) != NULL; i++) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = cp;
+ if (!sudo_json_add_value(jsonc, NULL, &json_value))
+ goto oom;
+ }
+ if (!sudo_json_close_array(jsonc))
+ goto oom;
+ }
+
+ if (evlog->submitenv != NULL) {
+ if (!sudo_json_open_array(jsonc, "submitenv"))
+ goto oom;
+ for (i = 0; (cp = evlog->submitenv[i]) != NULL; i++) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = cp;
+ if (!sudo_json_add_value(jsonc, NULL, &json_value))
+ goto oom;
+ }
+ if (!sudo_json_close_array(jsonc))
+ goto oom;
+ }
+
+ debug_return_bool(true);
+
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+}
+
+static bool
+default_json_cb(struct json_container *jsonc, void *v)
+{
+ return eventlog_store_json(jsonc, v);
+}
+
+static char *
+format_json(int event_type, struct eventlog_args *args,
+ const struct eventlog *evlog, bool compact)
+{
+ eventlog_json_callback_t info_cb = args->json_info_cb;
+ void *info = args->json_info;
+ struct json_container jsonc = { 0 };
+ struct json_value json_value;
+ const char *time_str, *type_str;
+ struct timespec now;
+ debug_decl(format_json, SUDO_DEBUG_UTIL);
+
+ if (info_cb == NULL) {
+ info_cb = default_json_cb;
+ info = (void *)evlog;
+ }
+
+ if (sudo_gettime_real(&now) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to read the clock");
+ debug_return_str(NULL);
+ }
+
+ switch (event_type) {
+ case EVLOG_ACCEPT:
+ type_str = "accept";
+ time_str = "submit_time";
+ break;
+ case EVLOG_REJECT:
+ type_str = "reject";
+ time_str = "submit_time";
+ break;
+ case EVLOG_ALERT:
+ type_str = "alert";
+ time_str = "alert_time";
+ break;
+ case EVLOG_EXIT:
+ type_str = "exit";
+ time_str = "exit_time";
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unexpected event type %d", event_type);
+ debug_return_str(NULL);
+ }
+
+ if (!sudo_json_init(&jsonc, 4, compact, false, false))
+ goto bad;
+ if (!sudo_json_open_object(&jsonc, type_str))
+ goto bad;
+
+ if (evlog != NULL && evlog->uuid_str[0] != '\0') {
+ json_value.type = JSON_STRING;
+ json_value.u.string = evlog->uuid_str;
+ if (!sudo_json_add_value(&jsonc, "uuid", &json_value))
+ goto bad;
+ }
+
+ /* Reject and Alert events include a reason and optional error string. */
+ if (args->reason != NULL) {
+ char *ereason = NULL;
+
+ if (args->errstr != NULL) {
+ const int len = asprintf(&ereason, _("%s: %s"), args->reason,
+ args->errstr);
+ if (len == -1) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ json_value.type = JSON_STRING;
+ json_value.u.string = ereason ? ereason : args->reason;
+ if (!sudo_json_add_value(&jsonc, "reason", &json_value)) {
+ free(ereason);
+ goto bad;
+ }
+ free(ereason);
+ }
+
+ /* Log event time on server (set earlier) */
+ if (!json_add_timestamp(&jsonc, "server_time", &now, true)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable format timestamp");
+ goto bad;
+ }
+
+ /* Log event time from client */
+ if (args->event_time != NULL) {
+ if (!json_add_timestamp(&jsonc, time_str, args->event_time, true)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable format timestamp");
+ goto bad;
+ }
+ }
+
+ if (event_type == EVLOG_EXIT && evlog != NULL) {
+ /* Exit events don't need evlog details if there is a UUID. */
+ if (evlog->uuid_str[0] != '\0') {
+ if (args->json_info == NULL)
+ info = NULL;
+ }
+
+ if (sudo_timespecisset(&evlog->run_time)) {
+ if (!json_add_timestamp(&jsonc, "run_time", &evlog->run_time, false)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable format timestamp");
+ goto bad;
+ }
+ }
+ if (evlog->signal_name != NULL) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = evlog->signal_name;
+ if (!sudo_json_add_value(&jsonc, "signal", &json_value))
+ goto bad;
+
+ json_value.type = JSON_BOOL;
+ json_value.u.boolean = evlog->dumped_core;
+ if (!sudo_json_add_value(&jsonc, "dumped_core", &json_value))
+ goto bad;
+ }
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = evlog->exit_value;
+ if (!sudo_json_add_value(&jsonc, "exit_value", &json_value))
+ goto bad;
+ }
+
+ /* Event log info may be missing for alert messages. */
+ if (evlog != NULL) {
+ if (evlog->peeraddr != NULL) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = evlog->peeraddr;
+ if (!sudo_json_add_value(&jsonc, "peeraddr", &json_value))
+ goto bad;
+ }
+
+ if (evlog->iolog_path != NULL) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = evlog->iolog_path;
+ if (!sudo_json_add_value(&jsonc, "iolog_path", &json_value))
+ goto bad;
+
+ if (sudo_timespecisset(&evlog->iolog_offset)) {
+ if (!json_add_timestamp(&jsonc, "iolog_offset", &evlog->iolog_offset, false)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable format timestamp");
+ goto bad;
+ }
+ }
+ }
+
+ if (event_type == EVLOG_EXIT) {
+ /* Exit events don't need evlog details if there is a UUID. */
+ if (evlog->uuid_str[0] != '\0') {
+ if (args->json_info == NULL)
+ info = NULL;
+ }
+
+ if (sudo_timespecisset(&evlog->run_time)) {
+ if (!json_add_timestamp(&jsonc, "run_time", &evlog->run_time,
+ false)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable format timestamp");
+ goto bad;
+ }
+ }
+ if (evlog->signal_name != NULL) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = evlog->signal_name;
+ if (!sudo_json_add_value(&jsonc, "signal", &json_value))
+ goto bad;
+
+ json_value.type = JSON_BOOL;
+ json_value.u.boolean = evlog->dumped_core;
+ if (!sudo_json_add_value(&jsonc, "dumped_core", &json_value))
+ goto bad;
+ }
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = evlog->exit_value;
+ if (!sudo_json_add_value(&jsonc, "exit_value", &json_value))
+ goto bad;
+ }
+ }
+
+ /* Write log info. */
+ if (info != NULL) {
+ if (!info_cb(&jsonc, info))
+ goto bad;
+ }
+
+ if (!sudo_json_close_object(&jsonc))
+ goto bad;
+
+ /* Caller is responsible for freeing the buffer. */
+ debug_return_str(sudo_json_get_buf(&jsonc));
+
+bad:
+ sudo_json_free(&jsonc);
+ debug_return_str(NULL);
+}
+
+/*
+ * Log a message to syslog, prepending the username and splitting the
+ * message into parts if it is longer than syslog_maxlen.
+ */
+static bool
+do_syslog_sudo(int pri, char *logline, const struct eventlog *evlog)
+{
+ const struct eventlog_config *evl_conf = eventlog_getconf();
+ size_t len, maxlen;
+ char *p, *tmp, save;
+ const char *fmt;
+ debug_decl(do_syslog_sudo, SUDO_DEBUG_UTIL);
+
+ evl_conf->open_log(EVLOG_SYSLOG, NULL);
+
+ if (evlog == NULL) {
+ /* Not a command, just log it as-is. */
+ syslog(pri, "%s", logline);
+ goto done;
+ }
+
+ /*
+ * Log the full line, breaking into multiple syslog(3) calls if necessary
+ */
+ fmt = _("%8s : %s");
+ maxlen = evl_conf->syslog_maxlen -
+ (strlen(fmt) - 5 + strlen(evlog->submituser));
+ for (p = logline; *p != '\0'; ) {
+ len = strlen(p);
+ if (len > maxlen) {
+ /*
+ * Break up the line into what will fit on one syslog(3) line
+ * Try to avoid breaking words into several lines if possible.
+ */
+ tmp = memrchr(p, ' ', maxlen);
+ if (tmp == NULL)
+ tmp = p + maxlen;
+
+ /* NULL terminate line, but save the char to restore later */
+ save = *tmp;
+ *tmp = '\0';
+
+ syslog(pri, fmt, evlog->submituser, p);
+
+ *tmp = save; /* restore saved character */
+
+ /* Advance p and eliminate leading whitespace */
+ for (p = tmp; *p == ' '; p++)
+ continue;
+ } else {
+ syslog(pri, fmt, evlog->submituser, p);
+ p += len;
+ }
+ fmt = _("%8s : (command continued) %s");
+ maxlen = evl_conf->syslog_maxlen -
+ (strlen(fmt) - 5 + strlen(evlog->submituser));
+ }
+done:
+ evl_conf->close_log(EVLOG_SYSLOG, NULL);
+
+ debug_return_bool(true);
+}
+
+static bool
+do_syslog_json(int pri, int event_type, struct eventlog_args *args,
+ const struct eventlog *evlog)
+{
+ const struct eventlog_config *evl_conf = eventlog_getconf();
+ char *json_str;
+ debug_decl(do_syslog_json, SUDO_DEBUG_UTIL);
+
+ /* Format as a compact JSON message (no newlines) */
+ json_str = format_json(event_type, args, evlog, true);
+ if (json_str == NULL)
+ debug_return_bool(false);
+
+ /* Syslog it in a sudo object with a @cee: prefix. */
+ /* TODO: use evl_conf->syslog_maxlen to break up long messages. */
+ evl_conf->open_log(EVLOG_SYSLOG, NULL);
+ syslog(pri, "@cee:{\"sudo\":{%s}}", json_str);
+ evl_conf->close_log(EVLOG_SYSLOG, NULL);
+ free(json_str);
+ debug_return_bool(true);
+}
+
+/*
+ * Log a message to syslog in either sudo or JSON format.
+ */
+static bool
+do_syslog(int event_type, int flags, struct eventlog_args *args,
+ const struct eventlog *evlog)
+{
+ const struct eventlog_config *evl_conf = eventlog_getconf();
+ struct sudo_lbuf lbuf;
+ bool ret = false;
+ int pri;
+ debug_decl(do_syslog, SUDO_DEBUG_UTIL);
+
+ sudo_lbuf_init(&lbuf, NULL, 0, NULL, 0);
+
+ /* Sudo format logs and mailed logs use the same log line format. */
+ if (evl_conf->format == EVLOG_SUDO || ISSET(flags, EVLOG_MAIL)) {
+ if (!new_logline(event_type, flags, args, evlog, &lbuf))
+ goto done;
+
+ if (ISSET(flags, EVLOG_MAIL)) {
+ if (!send_mail(evlog, lbuf.buf)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to mail log line");
+ }
+ if (ISSET(flags, EVLOG_MAIL_ONLY)) {
+ ret = true;
+ goto done;
+ }
+ }
+ }
+
+ switch (event_type) {
+ case EVLOG_ACCEPT:
+ case EVLOG_EXIT:
+ pri = evl_conf->syslog_acceptpri;
+ break;
+ case EVLOG_REJECT:
+ pri = evl_conf->syslog_rejectpri;
+ break;
+ case EVLOG_ALERT:
+ pri = evl_conf->syslog_alertpri;
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unexpected event type %d", event_type);
+ pri = -1;
+ break;
+ }
+ if (pri == -1) {
+ /* syslog disabled for this message type */
+ ret = true;
+ goto done;
+ }
+
+ switch (evl_conf->format) {
+ case EVLOG_SUDO:
+ ret = do_syslog_sudo(pri, lbuf.buf, evlog);
+ break;
+ case EVLOG_JSON:
+ ret = do_syslog_json(pri, event_type, args, evlog);
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unexpected eventlog format %d", evl_conf->format);
+ break;
+ }
+done:
+ sudo_lbuf_destroy(&lbuf);
+ debug_return_bool(ret);
+}
+
+static bool
+do_logfile_sudo(const char *logline, const struct eventlog *evlog,
+ const struct timespec *event_time)
+{
+ const struct eventlog_config *evl_conf = eventlog_getconf();
+ char *full_line, timebuf[8192], *timestr = NULL;
+ const char *timefmt = evl_conf->time_fmt;
+ const char *logfile = evl_conf->logpath;
+ struct tm tm;
+ bool ret = false;
+ FILE *fp;
+ int len;
+ debug_decl(do_logfile_sudo, SUDO_DEBUG_UTIL);
+
+ if ((fp = evl_conf->open_log(EVLOG_FILE, logfile)) == NULL)
+ debug_return_bool(false);
+
+ if (!sudo_lock_file(fileno(fp), SUDO_LOCK)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to lock log file %s", logfile);
+ goto done;
+ }
+
+ if (event_time != NULL) {
+ time_t tv_sec = event_time->tv_sec;
+ if (localtime_r(&tv_sec, &tm) != NULL) {
+ /* strftime() does not guarantee to NUL-terminate so we must check. */
+ timebuf[sizeof(timebuf) - 1] = '\0';
+ if (strftime(timebuf, sizeof(timebuf), timefmt, &tm) != 0 &&
+ timebuf[sizeof(timebuf) - 1] == '\0') {
+ timestr = timebuf;
+ }
+ }
+ }
+ if (evlog != NULL) {
+ len = asprintf(&full_line, "%s : %s : %s",
+ timestr ? timestr : "invalid date", evlog->submituser, logline);
+ } else {
+ len = asprintf(&full_line, "%s : %s",
+ timestr ? timestr : "invalid date", logline);
+ }
+ if (len == -1) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ eventlog_writeln(fp, full_line, (size_t)len, evl_conf->file_maxlen);
+ free(full_line);
+ (void)fflush(fp);
+ if (ferror(fp)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to write log file %s", logfile);
+ goto done;
+ }
+ ret = true;
+
+done:
+ (void)sudo_lock_file(fileno(fp), SUDO_UNLOCK);
+ evl_conf->close_log(EVLOG_FILE, fp);
+ debug_return_bool(ret);
+}
+
+static bool
+do_logfile_json(int event_type, struct eventlog_args *args,
+ const struct eventlog *evlog)
+{
+ const struct eventlog_config *evl_conf = eventlog_getconf();
+ const char *logfile = evl_conf->logpath;
+ struct stat sb;
+ char *json_str;
+ int ret = false;
+ FILE *fp;
+ debug_decl(do_logfile_json, SUDO_DEBUG_UTIL);
+
+ if ((fp = evl_conf->open_log(EVLOG_FILE, logfile)) == NULL)
+ debug_return_bool(false);
+
+ json_str = format_json(event_type, args, evlog, false);
+ if (json_str == NULL)
+ goto done;
+
+ if (!sudo_lock_file(fileno(fp), SUDO_LOCK)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to lock log file %s", logfile);
+ goto done;
+ }
+
+ /* Note: assumes file ends in "\n}\n" */
+ if (fstat(fileno(fp), &sb) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "unable to stat %s", logfile);
+ goto done;
+ }
+ if (sb.st_size == 0) {
+ /* New file */
+ putc('{', fp);
+ } else if (fseeko(fp, -3, SEEK_END) == 0) {
+ /* Continue file, overwrite the final "\n}\n" */
+ putc(',', fp);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "unable to seek %s", logfile);
+ goto done;
+ }
+ fputs(json_str, fp);
+ fputs("\n}\n", fp); /* close JSON */
+ fflush(fp);
+ /* XXX - check for file error and recover */
+
+ ret = true;
+
+done:
+ free(json_str);
+ (void)sudo_lock_file(fileno(fp), SUDO_UNLOCK);
+ evl_conf->close_log(EVLOG_FILE, fp);
+ debug_return_bool(ret);
+}
+
+static bool
+do_logfile(int event_type, int flags, struct eventlog_args *args,
+ const struct eventlog *evlog)
+{
+ const struct eventlog_config *evl_conf = eventlog_getconf();
+ struct sudo_lbuf lbuf;
+ bool ret = false;
+ debug_decl(do_logfile, SUDO_DEBUG_UTIL);
+
+ sudo_lbuf_init(&lbuf, NULL, 0, NULL, 0);
+
+ /* Sudo format logs and mailed logs use the same log line format. */
+ if (evl_conf->format == EVLOG_SUDO || ISSET(flags, EVLOG_MAIL)) {
+ if (!new_logline(event_type, flags, args, evlog, &lbuf))
+ goto done;
+
+ if (ISSET(flags, EVLOG_MAIL)) {
+ if (!send_mail(evlog, lbuf.buf)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to mail log line");
+ }
+ if (ISSET(flags, EVLOG_MAIL_ONLY)) {
+ ret = true;
+ goto done;
+ }
+ }
+ }
+
+ switch (evl_conf->format) {
+ case EVLOG_SUDO:
+ ret = do_logfile_sudo(lbuf.buf ? lbuf.buf : args->reason, evlog,
+ args->event_time);
+ break;
+ case EVLOG_JSON:
+ ret = do_logfile_json(event_type, args, evlog);
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unexpected eventlog format %d", evl_conf->format);
+ break;
+ }
+
+done:
+ sudo_lbuf_destroy(&lbuf);
+ debug_return_bool(ret);
+}
+
+bool
+eventlog_accept(const struct eventlog *evlog, int flags,
+ eventlog_json_callback_t info_cb, void *info)
+{
+ const struct eventlog_config *evl_conf = eventlog_getconf();
+ const int log_type = evl_conf->type;
+ struct eventlog_args args = { NULL };
+ bool ret = true;
+ debug_decl(eventlog_accept, SUDO_DEBUG_UTIL);
+
+ args.event_time = &evlog->submit_time;
+ args.json_info_cb = info_cb;
+ args.json_info = info;
+
+ if (ISSET(log_type, EVLOG_SYSLOG)) {
+ if (!do_syslog(EVLOG_ACCEPT, flags, &args, evlog))
+ ret = false;
+ CLR(flags, EVLOG_MAIL);
+ }
+ if (ISSET(log_type, EVLOG_FILE)) {
+ if (!do_logfile(EVLOG_ACCEPT, flags, &args, evlog))
+ ret = false;
+ }
+
+ debug_return_bool(ret);
+}
+
+bool
+eventlog_reject(const struct eventlog *evlog, int flags, const char *reason,
+ eventlog_json_callback_t info_cb, void *info)
+{
+ const struct eventlog_config *evl_conf = eventlog_getconf();
+ const int log_type = evl_conf->type;
+ struct eventlog_args args = { NULL };
+ bool ret = true;
+ debug_decl(eventlog_reject, SUDO_DEBUG_UTIL);
+
+ args.reason = reason;
+ args.event_time = &evlog->submit_time;
+ args.json_info_cb = info_cb;
+ args.json_info = info;
+
+ if (ISSET(log_type, EVLOG_SYSLOG)) {
+ if (!do_syslog(EVLOG_REJECT, flags, &args, evlog))
+ ret = false;
+ CLR(flags, EVLOG_MAIL);
+ }
+ if (ISSET(log_type, EVLOG_FILE)) {
+ if (!do_logfile(EVLOG_REJECT, flags, &args, evlog))
+ ret = false;
+ }
+
+ debug_return_bool(ret);
+}
+
+bool
+eventlog_alert(const struct eventlog *evlog, int flags,
+ struct timespec *alert_time, const char *reason, const char *errstr)
+{
+ const struct eventlog_config *evl_conf = eventlog_getconf();
+ const int log_type = evl_conf->type;
+ struct eventlog_args args = { NULL };
+ bool ret = true;
+ debug_decl(eventlog_alert, SUDO_DEBUG_UTIL);
+
+ args.reason = reason;
+ args.errstr = errstr;
+ args.event_time = alert_time;
+
+ if (ISSET(log_type, EVLOG_SYSLOG)) {
+ if (!do_syslog(EVLOG_ALERT, flags, &args, evlog))
+ ret = false;
+ CLR(flags, EVLOG_MAIL);
+ }
+ if (ISSET(log_type, EVLOG_FILE)) {
+ if (!do_logfile(EVLOG_ALERT, flags, &args, evlog))
+ ret = false;
+ }
+
+ debug_return_bool(ret);
+}
+
+bool
+eventlog_mail(const struct eventlog *evlog, int flags,
+ struct timespec *event_time, const char *reason, const char *errstr,
+ char * const extra[])
+{
+ struct eventlog_args args = { NULL };
+ struct sudo_lbuf lbuf;
+ bool ret = false;
+ debug_decl(eventlog_mail, SUDO_DEBUG_UTIL);
+
+ args.reason = reason;
+ args.errstr = errstr;
+ args.event_time = event_time;
+
+ sudo_lbuf_init(&lbuf, NULL, 0, NULL, 0);
+ if (!new_logline(EVLOG_ALERT, flags, &args, evlog, &lbuf))
+ goto done;
+
+ if (extra != NULL) {
+ /* Each extra message is written on its own line. */
+ while (*extra != NULL) {
+ sudo_lbuf_append(&lbuf, "\n");
+ sudo_lbuf_append_esc(&lbuf, LBUF_ESC_CNTRL, "%s", *extra);
+ if (sudo_lbuf_error(&lbuf)) {
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to format mail message");
+ goto done;
+ }
+ extra++;
+ }
+ }
+
+ ret = send_mail(evlog, lbuf.buf);
+ if (!ret) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to mail log line");
+ }
+
+done:
+ sudo_lbuf_destroy(&lbuf);
+ debug_return_bool(ret);
+}
+
+bool
+eventlog_exit(const struct eventlog *evlog, int flags)
+{
+ const struct eventlog_config *evl_conf = eventlog_getconf();
+ const int log_type = evl_conf->type;
+ struct eventlog_args args = { NULL };
+ struct timespec exit_time;
+ bool ret = true;
+ debug_decl(eventlog_exit, SUDO_DEBUG_UTIL);
+
+ if (sudo_timespecisset(&evlog->run_time)) {
+ sudo_timespecadd(&evlog->submit_time, &evlog->run_time, &exit_time);
+ args.event_time = &exit_time;
+ }
+
+ if (ISSET(log_type, EVLOG_SYSLOG)) {
+ if (!do_syslog(EVLOG_EXIT, flags, &args, evlog))
+ ret = false;
+ CLR(flags, EVLOG_MAIL);
+ }
+ if (ISSET(log_type, EVLOG_FILE)) {
+ if (!do_logfile(EVLOG_EXIT, flags, &args, evlog))
+ ret = false;
+ }
+
+ debug_return_bool(ret);
+}
diff --git a/lib/eventlog/eventlog_conf.c b/lib/eventlog/eventlog_conf.c
new file mode 100644
index 0000000..0663a38
--- /dev/null
+++ b/lib/eventlog/eventlog_conf.c
@@ -0,0 +1,226 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1994-1996, 1998-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <locale.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <pathnames.h>
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_json.h>
+#include <sudo_queue.h>
+#include <sudo_util.h>
+
+static FILE *eventlog_stub_open_log(int type, const char *logfile);
+static void eventlog_stub_close_log(int type, FILE *fp);
+
+/* Eventlog config settings (default values). */
+static struct eventlog_config evl_conf = {
+ EVLOG_NONE, /* type */
+ EVLOG_SUDO, /* format */
+ LOG_NOTICE, /* syslog_acceptpri */
+ LOG_ALERT, /* syslog_rejectpri */
+ LOG_ALERT, /* syslog_alertpri */
+ MAXSYSLOGLEN, /* syslog_maxlen */
+ 0, /* file_maxlen */
+ ROOT_UID, /* mailuid */
+ false, /* omit_hostname */
+ _PATH_SUDO_LOGFILE, /* logpath */
+ "%h %e %T", /* time_fmt */
+#ifdef _PATH_SUDO_SENDMAIL
+ _PATH_SUDO_SENDMAIL, /* mailerpath */
+#else
+ NULL, /* mailerpath (disabled) */
+#endif
+ "-t", /* mailerflags */
+ NULL, /* mailfrom */
+ MAILTO, /* mailto */
+ N_(MAILSUBJECT), /* mailsub */
+ eventlog_stub_open_log, /* open_log */
+ eventlog_stub_close_log /* close_log */
+};
+
+static FILE *
+eventlog_stub_open_log(int type, const char *logfile)
+{
+ debug_decl(eventlog_stub_open_log, SUDO_DEBUG_UTIL);
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "open_log not set, using stub");
+ debug_return_ptr(NULL);
+}
+
+static void
+eventlog_stub_close_log(int type, FILE *fp)
+{
+ debug_decl(eventlog_stub_close_log, SUDO_DEBUG_UTIL);
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "close_log not set, using stub");
+ debug_return;
+}
+
+/*
+ * eventlog config setters.
+ */
+
+void
+eventlog_set_type(int type)
+{
+ evl_conf.type = type;
+}
+
+void
+eventlog_set_format(enum eventlog_format format)
+{
+ evl_conf.format = format;
+}
+
+void
+eventlog_set_syslog_acceptpri(int pri)
+{
+ evl_conf.syslog_acceptpri = pri;
+}
+
+void
+eventlog_set_syslog_rejectpri(int pri)
+{
+ evl_conf.syslog_rejectpri = pri;
+}
+
+void
+eventlog_set_syslog_alertpri(int pri)
+{
+ evl_conf.syslog_alertpri = pri;
+}
+
+void
+eventlog_set_syslog_maxlen(size_t len)
+{
+ evl_conf.syslog_maxlen = len;
+}
+
+void
+eventlog_set_file_maxlen(size_t len)
+{
+ evl_conf.file_maxlen = len;
+}
+
+void
+eventlog_set_mailuid(uid_t uid)
+{
+ evl_conf.mailuid = uid;
+}
+
+void
+eventlog_set_omit_hostname(bool omit_hostname)
+{
+ evl_conf.omit_hostname = omit_hostname;
+}
+
+void
+eventlog_set_logpath(const char *path)
+{
+ evl_conf.logpath = path;
+}
+
+void
+eventlog_set_time_fmt(const char *fmt)
+{
+ evl_conf.time_fmt = fmt;
+}
+
+void
+eventlog_set_mailerpath(const char *path)
+{
+ evl_conf.mailerpath = path;
+}
+
+void
+eventlog_set_mailerflags(const char *mflags)
+{
+ evl_conf.mailerflags = mflags;
+}
+
+void
+eventlog_set_mailfrom(const char *from_addr)
+{
+ evl_conf.mailfrom = from_addr;
+}
+
+void
+eventlog_set_mailto(const char *to_addr)
+{
+ evl_conf.mailto = to_addr;
+}
+
+void
+eventlog_set_mailsub(const char *subject)
+{
+ evl_conf.mailsub = subject;
+}
+
+void
+eventlog_set_open_log(FILE *(*fn)(int type, const char *))
+{
+ evl_conf.open_log = fn;
+}
+
+void
+eventlog_set_close_log(void (*fn)(int type, FILE *))
+{
+ evl_conf.close_log = fn;
+}
+
+/*
+ * get eventlog config.
+ */
+const struct eventlog_config *
+eventlog_getconf(void)
+{
+ return &evl_conf;
+}
diff --git a/lib/eventlog/eventlog_free.c b/lib/eventlog/eventlog_free.c
new file mode 100644
index 0000000..7643f52
--- /dev/null
+++ b/lib/eventlog/eventlog_free.c
@@ -0,0 +1,86 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_eventlog.h>
+#include <sudo_util.h>
+
+/*
+ * Free the strings in a struct eventlog.
+ */
+void
+eventlog_free(struct eventlog *evlog)
+{
+ size_t i;
+ debug_decl(eventlog_free, SUDO_DEBUG_UTIL);
+
+ if (evlog != NULL) {
+ free(evlog->iolog_path);
+ free(evlog->command);
+ free(evlog->cwd);
+ free(evlog->runchroot);
+ free(evlog->runcwd);
+ free(evlog->rungroup);
+ free(evlog->runuser);
+ free(evlog->peeraddr);
+ free(evlog->signal_name);
+ free(evlog->source);
+ if (evlog->submitenv != NULL) {
+ for (i = 0; evlog->submitenv[i] != NULL; i++)
+ free(evlog->submitenv[i]);
+ free(evlog->submitenv);
+ }
+ free(evlog->submithost);
+ free(evlog->submituser);
+ free(evlog->submitgroup);
+ free(evlog->ttyname);
+ if (evlog->runargv != NULL) {
+ for (i = 0; evlog->runargv[i] != NULL; i++)
+ free(evlog->runargv[i]);
+ free(evlog->runargv);
+ }
+ if (evlog->runenv != NULL) {
+ for (i = 0; evlog->runenv[i] != NULL; i++)
+ free(evlog->runenv[i]);
+ free(evlog->runenv);
+ }
+ if (evlog->env_add != NULL) {
+ for (i = 0; evlog->env_add[i] != NULL; i++)
+ free(evlog->env_add[i]);
+ free(evlog->env_add);
+ }
+ free(evlog);
+ }
+
+ debug_return;
+}
diff --git a/lib/eventlog/logwrap.c b/lib/eventlog/logwrap.c
new file mode 100644
index 0000000..849ccb4
--- /dev/null
+++ b/lib/eventlog/logwrap.c
@@ -0,0 +1,90 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011, 2014-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+#include <sudo_eventlog.h>
+
+size_t
+eventlog_writeln(FILE * restrict fp, char * restrict line, size_t linelen, size_t maxlen)
+{
+ const char *indent = "";
+ char *beg = line;
+ char *end;
+ int len;
+ size_t outlen = 0;
+ debug_decl(eventlog_writeln, SUDO_DEBUG_UTIL);
+
+ if (maxlen < sizeof(EVENTLOG_INDENT)) {
+ /* Maximum length too small, disable wrapping. */
+ outlen = fwrite(line, 1, linelen, fp);
+ if (outlen != linelen)
+ debug_return_size_t((size_t)-1);
+ if (fputc('\n', fp) == EOF)
+ debug_return_size_t((size_t)-1);
+ debug_return_size_t(outlen + 1);
+ }
+
+ /*
+ * Print out line with word wrap around maxlen characters.
+ */
+ while (linelen > maxlen) {
+ end = beg + maxlen;
+ while (end != beg && *end != ' ')
+ end--;
+ if (beg == end) {
+ /* Unable to find word break within maxlen, look beyond. */
+ end = strchr(beg + maxlen, ' ');
+ if (end == NULL)
+ break; /* no word break */
+ }
+ len = fprintf(fp, "%s%.*s\n", indent, (int)(end - beg), beg);
+ if (len < 0)
+ debug_return_size_t((size_t)-1);
+ outlen += (size_t)len;
+ while (*end == ' ')
+ end++;
+ linelen -= (size_t)(end - beg);
+ beg = end;
+ if (indent[0] == '\0') {
+ indent = EVENTLOG_INDENT;
+ maxlen -= sizeof(EVENTLOG_INDENT) - 1;
+ }
+ }
+ /* Print remainder, if any. */
+ if (linelen) {
+ len = fprintf(fp, "%s%s\n", indent, beg);
+ if (len < 0)
+ debug_return_size_t((size_t)-1);
+ outlen += (size_t)len;
+ }
+
+ debug_return_size_t(outlen);
+}
diff --git a/lib/eventlog/parse_json.c b/lib/eventlog/parse_json.c
new file mode 100644
index 0000000..9b5a168
--- /dev/null
+++ b/lib/eventlog/parse_json.c
@@ -0,0 +1,1071 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_util.h>
+
+#include <parse_json.h>
+
+struct json_stack {
+ unsigned int depth;
+ unsigned int maxdepth;
+ struct eventlog_json_object *frames[64];
+};
+#define JSON_STACK_INTIALIZER(s) { 0, nitems((s).frames) };
+
+static char *iolog_file;
+
+static bool
+json_store_columns(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_columns, SUDO_DEBUG_UTIL);
+
+ if (item->u.number < 1 || item->u.number > INT_MAX) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "tty cols %lld: out of range", item->u.number);
+ evlog->columns = 0;
+ debug_return_bool(false);
+ }
+
+ evlog->columns = (int)item->u.number;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_command(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_command, SUDO_DEBUG_UTIL);
+
+ /*
+ * Note: struct eventlog must store command + args.
+ * We don't have argv yet so we append the args later.
+ */
+ free(evlog->command);
+ evlog->command = item->u.string;
+ item->u.string = NULL;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_dumped_core(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_dumped_core, SUDO_DEBUG_UTIL);
+
+ evlog->dumped_core = item->u.boolean;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_exit_value(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_exit_value, SUDO_DEBUG_UTIL);
+
+ if (item->u.number < 0 || item->u.number > INT_MAX) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "exit value %lld: out of range", item->u.number);
+ evlog->exit_value = -1;
+ debug_return_bool(false);
+ }
+
+ evlog->exit_value = (int)item->u.number;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_iolog_file(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_iolog_file, SUDO_DEBUG_UTIL);
+
+ /* Do set evlog->iolog_file directly, it is a substring of iolog_path. */
+ free(iolog_file);
+ iolog_file = item->u.string;
+ item->u.string = NULL;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_iolog_path(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_iolog_path, SUDO_DEBUG_UTIL);
+
+ free(evlog->iolog_path);
+ evlog->iolog_path = item->u.string;
+ item->u.string = NULL;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_lines(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_lines, SUDO_DEBUG_UTIL);
+
+ if (item->u.number < 1 || item->u.number > INT_MAX) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "tty lines %lld: out of range", item->u.number);
+ evlog->lines = 0;
+ debug_return_bool(false);
+ }
+
+ evlog->lines = (int)item->u.number;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_peeraddr(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_peeraddr, SUDO_DEBUG_UTIL);
+
+ free(evlog->peeraddr);
+ evlog->peeraddr = item->u.string;
+ item->u.string = NULL;
+ debug_return_bool(true);
+}
+
+static char **
+json_array_to_strvec(struct eventlog_json_object *array)
+{
+ struct json_item *item;
+ size_t len = 0;
+ char **ret;
+ debug_decl(json_array_to_strvec, SUDO_DEBUG_UTIL);
+
+ TAILQ_FOREACH(item, &array->items, entries) {
+ /* Can only convert arrays of string. */
+ if (item->type != JSON_STRING) {
+ sudo_warnx(U_("expected JSON_STRING, got %d"), item->type);
+ debug_return_ptr(NULL);
+ }
+ /* Prevent integer overflow. */
+ if (++len == INT_MAX) {
+ sudo_warnx("%s", U_("JSON_ARRAY too large"));
+ debug_return_ptr(NULL);
+ }
+ }
+ if ((ret = reallocarray(NULL, len + 1, sizeof(char *))) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_ptr(NULL);
+ }
+ len = 0;
+ TAILQ_FOREACH(item, &array->items, entries) {
+ ret[len++] = item->u.string;
+ item->u.string = NULL;
+ }
+ ret[len] = NULL;
+
+ debug_return_ptr(ret);
+}
+
+static bool
+json_store_submitenv(struct json_item *item, struct eventlog *evlog)
+{
+ size_t i;
+ debug_decl(json_store_submitenv, SUDO_DEBUG_UTIL);
+
+ if (evlog->submitenv != NULL) {
+ for (i = 0; evlog->submitenv[i] != NULL; i++)
+ free(evlog->submitenv[i]);
+ free(evlog->submitenv);
+ }
+ evlog->submitenv = json_array_to_strvec(&item->u.child);
+
+ debug_return_bool(evlog->submitenv != NULL);
+}
+
+static bool
+json_store_runargv(struct json_item *item, struct eventlog *evlog)
+{
+ size_t i;
+ debug_decl(json_store_runargv, SUDO_DEBUG_UTIL);
+
+ if (evlog->runargv != NULL) {
+ for (i = 0; evlog->runargv[i] != NULL; i++)
+ free(evlog->runargv[i]);
+ free(evlog->runargv);
+ }
+ evlog->runargv = json_array_to_strvec(&item->u.child);
+
+ debug_return_bool(evlog->runargv != NULL);
+}
+
+static bool
+json_store_runenv(struct json_item *item, struct eventlog *evlog)
+{
+ size_t i;
+ debug_decl(json_store_runenv, SUDO_DEBUG_UTIL);
+
+ if (evlog->runenv != NULL) {
+ for (i = 0; evlog->runenv[i] != NULL; i++)
+ free(evlog->runenv[i]);
+ free(evlog->runenv);
+ }
+ evlog->runenv = json_array_to_strvec(&item->u.child);
+
+ debug_return_bool(evlog->runenv != NULL);
+}
+
+static bool
+json_store_runenv_override(struct json_item *item, struct eventlog *evlog)
+{
+ size_t i;
+ debug_decl(json_store_runenv_override, SUDO_DEBUG_UTIL);
+
+ if (evlog->env_add != NULL) {
+ for (i = 0; evlog->env_add[i] != NULL; i++)
+ free(evlog->env_add[i]);
+ free(evlog->env_add);
+ }
+ evlog->env_add = json_array_to_strvec(&item->u.child);
+
+ debug_return_bool(evlog->env_add != NULL);
+}
+
+static bool
+json_store_rungid(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_rungid, SUDO_DEBUG_UTIL);
+
+ evlog->rungid = (gid_t)item->u.number;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_rungroup(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_rungroup, SUDO_DEBUG_UTIL);
+
+ free(evlog->rungroup);
+ evlog->rungroup = item->u.string;
+ item->u.string = NULL;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_runuid(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_runuid, SUDO_DEBUG_UTIL);
+
+ evlog->runuid = (uid_t)item->u.number;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_runuser(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_runuser, SUDO_DEBUG_UTIL);
+
+ free(evlog->runuser);
+ evlog->runuser = item->u.string;
+ item->u.string = NULL;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_runchroot(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_runchroot, SUDO_DEBUG_UTIL);
+
+ free(evlog->runchroot);
+ evlog->runchroot = item->u.string;
+ item->u.string = NULL;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_runcwd(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_runcwd, SUDO_DEBUG_UTIL);
+
+ free(evlog->runcwd);
+ evlog->runcwd = item->u.string;
+ item->u.string = NULL;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_signal(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_signal, SUDO_DEBUG_UTIL);
+
+ free(evlog->signal_name);
+ evlog->signal_name = item->u.string;
+ item->u.string = NULL;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_source(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_source, SUDO_DEBUG_UTIL);
+
+ free(evlog->source);
+ evlog->source = item->u.string;
+ item->u.string = NULL;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_submitcwd(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_submitcwd, SUDO_DEBUG_UTIL);
+
+ free(evlog->cwd);
+ evlog->cwd = item->u.string;
+ item->u.string = NULL;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_submithost(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_submithost, SUDO_DEBUG_UTIL);
+
+ free(evlog->submithost);
+ evlog->submithost = item->u.string;
+ item->u.string = NULL;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_submituser(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_submituser, SUDO_DEBUG_UTIL);
+
+ free(evlog->submituser);
+ evlog->submituser = item->u.string;
+ item->u.string = NULL;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_submitgroup(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_submitgroup, SUDO_DEBUG_UTIL);
+
+ free(evlog->submitgroup);
+ evlog->submitgroup = item->u.string;
+ item->u.string = NULL;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_timespec(struct json_item *item, struct timespec *ts)
+{
+ struct eventlog_json_object *object;
+ debug_decl(json_store_timespec, SUDO_DEBUG_UTIL);
+
+ object = &item->u.child;
+ TAILQ_FOREACH(item, &object->items, entries) {
+ if (item->type != JSON_NUMBER)
+ continue;
+ if (strcmp(item->name, "seconds") == 0) {
+ ts->tv_sec = (time_t)item->u.number;
+ continue;
+ }
+ if (strcmp(item->name, "nanoseconds") == 0) {
+ ts->tv_nsec = (long)item->u.number;
+ continue;
+ }
+ }
+ debug_return_bool(true);
+}
+
+static bool
+json_store_iolog_offset(struct json_item *item, struct eventlog *evlog)
+{
+ return json_store_timespec(item, &evlog->iolog_offset);
+}
+
+static bool
+json_store_run_time(struct json_item *item, struct eventlog *evlog)
+{
+ return json_store_timespec(item, &evlog->run_time);
+}
+
+static bool
+json_store_timestamp(struct json_item *item, struct eventlog *evlog)
+{
+ return json_store_timespec(item, &evlog->submit_time);
+}
+
+static bool
+json_store_ttyname(struct json_item *item, struct eventlog *evlog)
+{
+ debug_decl(json_store_ttyname, SUDO_DEBUG_UTIL);
+
+ free(evlog->ttyname);
+ evlog->ttyname = item->u.string;
+ item->u.string = NULL;
+ debug_return_bool(true);
+}
+
+static bool
+json_store_uuid(struct json_item *item, struct eventlog *evlog)
+{
+ bool ret = false;
+ debug_decl(json_store_uuid, SUDO_DEBUG_UTIL);
+
+ if (strlen(item->u.string) == sizeof(evlog->uuid_str) - 1) {
+ memcpy(evlog->uuid_str, item->u.string, sizeof(evlog->uuid_str));
+ ret = true;
+ }
+ free(item->u.string);
+ item->u.string = NULL;
+ debug_return_bool(ret);
+}
+
+static struct evlog_json_key {
+ const char *name;
+ enum json_value_type type;
+ bool (*setter)(struct json_item *, struct eventlog *);
+} evlog_json_keys[] = {
+ { "columns", JSON_NUMBER, json_store_columns },
+ { "command", JSON_STRING, json_store_command },
+ { "dumped_core", JSON_BOOL, json_store_dumped_core },
+ { "exit_value", JSON_NUMBER, json_store_exit_value },
+ { "iolog_file", JSON_STRING, json_store_iolog_file },
+ { "iolog_path", JSON_STRING, json_store_iolog_path },
+ { "iolog_offset", JSON_OBJECT, json_store_iolog_offset },
+ { "lines", JSON_NUMBER, json_store_lines },
+ { "peeraddr", JSON_STRING, json_store_peeraddr },
+ { "run_time", JSON_OBJECT, json_store_run_time },
+ { "runargv", JSON_ARRAY, json_store_runargv },
+ { "runenv", JSON_ARRAY, json_store_runenv },
+ { "runenv_override", JSON_ARRAY, json_store_runenv_override },
+ { "rungid", JSON_ID, json_store_rungid },
+ { "rungroup", JSON_STRING, json_store_rungroup },
+ { "runuid", JSON_ID, json_store_runuid },
+ { "runuser", JSON_STRING, json_store_runuser },
+ { "runchroot", JSON_STRING, json_store_runchroot },
+ { "runcwd", JSON_STRING, json_store_runcwd },
+ { "source", JSON_STRING, json_store_source },
+ { "signal", JSON_STRING, json_store_signal },
+ { "submitcwd", JSON_STRING, json_store_submitcwd },
+ { "submitenv", JSON_ARRAY, json_store_submitenv },
+ { "submithost", JSON_STRING, json_store_submithost },
+ { "submitgroup", JSON_STRING, json_store_submitgroup },
+ { "submituser", JSON_STRING, json_store_submituser },
+ { "timestamp", JSON_OBJECT, json_store_timestamp },
+ { "ttyname", JSON_STRING, json_store_ttyname },
+ { "uuid", JSON_STRING, json_store_uuid },
+ { NULL }
+};
+
+static struct json_item *
+new_json_item(enum json_value_type type, char *name, unsigned int lineno)
+{
+ struct json_item *item;
+ debug_decl(new_json_item, SUDO_DEBUG_UTIL);
+
+ if ((item = malloc(sizeof(*item))) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ debug_return_ptr(NULL);
+ }
+ item->name = name;
+ item->type = type;
+ item->lineno = lineno;
+
+ debug_return_ptr(item);
+}
+
+static char *
+json_parse_string(char **strp)
+{
+ char *dst, *end, *ret, *src = *strp + 1;
+ size_t len;
+ debug_decl(json_parse_string, SUDO_DEBUG_UTIL);
+
+ for (end = src; *end != '"' && *end != '\0'; end++) {
+ if (end[0] == '\\' && end[1] == '"')
+ end++;
+ }
+ if (*end != '"') {
+ sudo_warnx("%s", U_("missing double quote in name"));
+ debug_return_str(NULL);
+ }
+ len = (size_t)(end - src);
+
+ /* Copy string, flattening escaped chars. */
+ dst = ret = malloc(len + 1);
+ if (dst == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_str(NULL);
+ }
+ while (src < end) {
+ int ch = *src++;
+ if (ch == '\\') {
+ switch (*src) {
+ case 'b':
+ ch = '\b';
+ break;
+ case 'f':
+ ch = '\f';
+ break;
+ case 'n':
+ ch = '\n';
+ break;
+ case 'r':
+ ch = '\r';
+ break;
+ case 't':
+ ch = '\t';
+ break;
+ case 'u':
+ /* Only currently handles 8-bit ASCII. */
+ if (src[1] == '0' && src[2] == '0') {
+ ch = sudo_hexchar(&src[3]);
+ if (ch != -1) {
+ src += 4;
+ break;
+ }
+ }
+ /* Not in \u00XX format. */
+ FALLTHROUGH;
+ case '"':
+ case '\\':
+ default:
+ /* Note: a bare \ at the end of a string will be removed. */
+ ch = *src;
+ break;
+ }
+ src++;
+ }
+ *dst++ = (char)ch;
+ }
+ *dst = '\0';
+
+ /* Trim trailing whitespace. */
+ do {
+ end++;
+ } while (isspace((unsigned char)*end));
+ *strp = end;
+
+ debug_return_str(ret);
+}
+
+static void
+free_json_items(struct json_item_list *items)
+{
+ struct json_item *item;
+ debug_decl(free_json_items, SUDO_DEBUG_UTIL);
+
+ while ((item = TAILQ_FIRST(items)) != NULL) {
+ TAILQ_REMOVE(items, item, entries);
+ switch (item->type) {
+ case JSON_STRING:
+ free(item->u.string);
+ break;
+ case JSON_ARRAY:
+ case JSON_OBJECT:
+ free_json_items(&item->u.child.items);
+ break;
+ case JSON_ID:
+ case JSON_NUMBER:
+ case JSON_BOOL:
+ case JSON_NULL:
+ /* Nothing to free. */
+ break;
+ default:
+ sudo_warnx("%s: internal error, invalid JSON type %d",
+ __func__, item->type);
+ break;
+ }
+ free(item->name);
+ free(item);
+ }
+
+ debug_return;
+}
+
+void
+eventlog_json_free(struct eventlog_json_object *root)
+{
+ debug_decl(eventlog_json_free, SUDO_DEBUG_UTIL);
+ if (root != NULL) {
+ free_json_items(&root->items);
+ free(root);
+ }
+ debug_return;
+}
+
+bool
+eventlog_json_parse(struct eventlog_json_object *object, struct eventlog *evlog)
+{
+ struct json_item *item;
+ bool ret = false;
+ debug_decl(eventlog_json_parse, SUDO_DEBUG_UTIL);
+
+ /* First object holds all the actual data. */
+ item = TAILQ_FIRST(&object->items);
+ if (item == NULL) {
+ sudo_warnx("%s", U_("missing JSON_OBJECT"));
+ goto done;
+ }
+ if (item->type != JSON_OBJECT) {
+ sudo_warnx(U_("expected JSON_OBJECT, got %d"), item->type);
+ goto done;
+ }
+ object = &item->u.child;
+
+ TAILQ_FOREACH(item, &object->items, entries) {
+ struct evlog_json_key *key;
+
+ /* expecting key:value pairs */
+ if (item->name == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "%s: missing object name", __func__);
+ goto done;
+ }
+
+ /* lookup name */
+ for (key = evlog_json_keys; key->name != NULL; key++) {
+ if (strcmp(item->name, key->name) == 0)
+ break;
+ }
+ if (key->name == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "%s: unknown key %s", __func__, item->name);
+ } else if (key->type != item->type &&
+ (key->type != JSON_ID || item->type != JSON_NUMBER)) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "%s: key mismatch %s type %d, expected %d", __func__,
+ item->name, item->type, key->type);
+ goto done;
+ } else {
+ /* Matched name and type. */
+ if (!key->setter(item, evlog)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to store %s", key->name);
+ goto done;
+ }
+ }
+ }
+
+ /*
+ * iolog_file must be a substring of iolog_path.
+ */
+ if (iolog_file != NULL && evlog->iolog_path != NULL) {
+ const size_t filelen = strlen(iolog_file);
+ const size_t pathlen = strlen(evlog->iolog_path);
+ if (filelen <= pathlen) {
+ const char *cp = &evlog->iolog_path[pathlen - filelen];
+ if (strcmp(cp, iolog_file) == 0) {
+ evlog->iolog_file = cp;
+ }
+ }
+ }
+
+ ret = true;
+
+done:
+ free(iolog_file);
+ iolog_file = NULL;
+
+ debug_return_bool(ret);
+}
+
+static bool
+json_insert_bool(struct json_item_list *items, char *name, bool value,
+ unsigned int lineno)
+{
+ struct json_item *item;
+ debug_decl(json_insert_bool, SUDO_DEBUG_UTIL);
+
+ if ((item = new_json_item(JSON_BOOL, name, lineno)) == NULL)
+ debug_return_bool(false);
+ item->u.boolean = value;
+ TAILQ_INSERT_TAIL(items, item, entries);
+
+ debug_return_bool(true);
+}
+
+static bool
+json_insert_null(struct json_item_list *items, char *name, unsigned int lineno)
+{
+ struct json_item *item;
+ debug_decl(json_insert_null, SUDO_DEBUG_UTIL);
+
+ if ((item = new_json_item(JSON_NULL, name, lineno)) == NULL)
+ debug_return_bool(false);
+ TAILQ_INSERT_TAIL(items, item, entries);
+
+ debug_return_bool(true);
+}
+
+static bool
+json_insert_num(struct json_item_list *items, char *name, long long value,
+ unsigned int lineno)
+{
+ struct json_item *item;
+ debug_decl(json_insert_num, SUDO_DEBUG_UTIL);
+
+ if ((item = new_json_item(JSON_NUMBER, name, lineno)) == NULL)
+ debug_return_bool(false);
+ item->u.number = value;
+ TAILQ_INSERT_TAIL(items, item, entries);
+
+ debug_return_bool(true);
+}
+
+static bool
+json_insert_str(struct json_item_list *items, char *name, char **strp,
+ unsigned int lineno)
+{
+ struct json_item *item;
+ debug_decl(json_insert_str, SUDO_DEBUG_UTIL);
+
+ if ((item = new_json_item(JSON_STRING, name, lineno)) == NULL)
+ debug_return_bool(false);
+ item->u.string = json_parse_string(strp);
+ if (item->u.string == NULL) {
+ free(item);
+ debug_return_bool(false);
+ }
+ TAILQ_INSERT_TAIL(items, item, entries);
+
+ debug_return_bool(true);
+}
+
+static struct eventlog_json_object *
+json_stack_push(struct json_stack *stack, struct json_item_list *items,
+ struct eventlog_json_object *frame, enum json_value_type type, char *name,
+ unsigned int lineno)
+{
+ struct json_item *item;
+ debug_decl(json_stack_push, SUDO_DEBUG_UTIL);
+
+ /* We limit the stack size rather than expanding it. */
+ if (stack->depth >= stack->maxdepth) {
+ sudo_warnx(U_("json stack exhausted (max %u frames)"), stack->maxdepth);
+ debug_return_ptr(NULL);
+ }
+
+ /* Allocate a new item and insert it into the list. */
+ if ((item = new_json_item(type, name, lineno)) == NULL)
+ debug_return_ptr(NULL);
+ TAILQ_INIT(&item->u.child.items);
+ item->u.child.parent = item;
+ TAILQ_INSERT_TAIL(items, item, entries);
+
+ /* Push the current frame onto the stack (depth check performed above). */
+ stack->frames[stack->depth++] = frame;
+
+ /* Return the new frame */
+ debug_return_ptr(&item->u.child);
+}
+
+/* Only expect a value if a name is defined or we are in an array. */
+#define expect_value (name != NULL || (frame->parent != NULL && frame->parent->type == JSON_ARRAY))
+
+struct eventlog_json_object *
+eventlog_json_read(FILE *fp, const char *filename)
+{
+ struct eventlog_json_object *frame, *root;
+ struct json_stack stack = JSON_STACK_INTIALIZER(stack);
+ unsigned int lineno = 0;
+ char *name = NULL;
+ char *cp, *line = NULL;
+ size_t len, linesize = 0;
+ ssize_t linelen;
+ bool saw_comma = false;
+ long long num;
+ char ch;
+ debug_decl(eventlog_json_read, SUDO_DEBUG_UTIL);
+
+ root = malloc(sizeof(*root));
+ if (root == NULL)
+ goto bad;
+
+ root->parent = NULL;
+ TAILQ_INIT(&root->items);
+
+ frame = root;
+ while ((linelen = getdelim(&line, &linesize, '\n', fp)) != -1) {
+ char *ep = line + linelen - 1;
+ cp = line;
+
+ lineno++;
+
+ /* Trim trailing whitespace. */
+ while (ep > cp && isspace((unsigned char)*ep))
+ ep--;
+ ep[1] = '\0';
+
+ for (;;) {
+ const char *errstr;
+
+ /* Trim leading whitespace, skip blank lines. */
+ while (isspace((unsigned char)*cp))
+ cp++;
+
+ /* Check for comma separator and strip it out. */
+ if (*cp == ',') {
+ saw_comma = true;
+ cp++;
+ while (isspace((unsigned char)*cp))
+ cp++;
+ }
+
+ /* End of line? */
+ if (*cp == '\0')
+ break;
+
+ switch (*cp) {
+ case '{':
+ if (name == NULL && frame->parent != NULL) {
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("objects must consist of name:value pairs"));
+ goto bad;
+ }
+ if (!saw_comma && !TAILQ_EMPTY(&frame->items)) {
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("missing separator between values"));
+ goto bad;
+ }
+ cp++;
+ saw_comma = false;
+ frame = json_stack_push(&stack, &frame->items, frame,
+ JSON_OBJECT, name, lineno);
+ if (frame == NULL)
+ goto bad;
+ name = NULL;
+ break;
+ case '}':
+ if (stack.depth == 0 || frame->parent == NULL ||
+ frame->parent->type != JSON_OBJECT) {
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("unmatched close brace"));
+ goto bad;
+ }
+ cp++;
+ frame = stack.frames[--stack.depth];
+ saw_comma = false;
+ break;
+ case '[':
+ if (frame->parent == NULL) {
+ /* Must have an enclosing object. */
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("unexpected array"));
+ goto bad;
+ }
+ if (!saw_comma && !TAILQ_EMPTY(&frame->items)) {
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("missing separator between values"));
+ goto bad;
+ }
+ cp++;
+ saw_comma = false;
+ frame = json_stack_push(&stack, &frame->items, frame,
+ JSON_ARRAY, name, lineno);
+ if (frame == NULL)
+ goto bad;
+ name = NULL;
+ break;
+ case ']':
+ if (stack.depth == 0 || frame->parent == NULL ||
+ frame->parent->type != JSON_ARRAY) {
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("unmatched close bracket"));
+ goto bad;
+ }
+ cp++;
+ frame = stack.frames[--stack.depth];
+ saw_comma = false;
+ break;
+ case '"':
+ if (frame->parent == NULL) {
+ /* Must have an enclosing object. */
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("unexpected string"));
+ goto bad;
+ }
+
+ if (!expect_value) {
+ /* Parse "name": */
+ if ((name = json_parse_string(&cp)) == NULL)
+ goto bad;
+ /* TODO: allow colon on next line? */
+ if (*cp != ':') {
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("missing colon after name"));
+ goto bad;
+ }
+ cp++;
+ } else {
+ if (!saw_comma && !TAILQ_EMPTY(&frame->items)) {
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("missing separator between values"));
+ goto bad;
+ }
+ saw_comma = false;
+ if (!json_insert_str(&frame->items, name, &cp, lineno))
+ goto bad;
+ name = NULL;
+ }
+ break;
+ case 't':
+ if (strncmp(cp, "true", sizeof("true") - 1) != 0)
+ goto parse_error;
+ if (!expect_value) {
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("unexpected boolean"));
+ goto bad;
+ }
+ cp += sizeof("true") - 1;
+ if (*cp != ',' && !isspace((unsigned char)*cp) && *cp != '\0')
+ goto parse_error;
+ if (!saw_comma && !TAILQ_EMPTY(&frame->items)) {
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("missing separator between values"));
+ goto bad;
+ }
+ saw_comma = false;
+
+ if (!json_insert_bool(&frame->items, name, true, lineno))
+ goto bad;
+ name = NULL;
+ break;
+ case 'f':
+ if (strncmp(cp, "false", sizeof("false") - 1) != 0)
+ goto parse_error;
+ if (!expect_value) {
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("unexpected boolean"));
+ goto bad;
+ }
+ cp += sizeof("false") - 1;
+ if (*cp != ',' && !isspace((unsigned char)*cp) && *cp != '\0')
+ goto parse_error;
+ if (!saw_comma && !TAILQ_EMPTY(&frame->items)) {
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("missing separator between values"));
+ goto bad;
+ }
+ saw_comma = false;
+
+ if (!json_insert_bool(&frame->items, name, false, lineno))
+ goto bad;
+ name = NULL;
+ break;
+ case 'n':
+ if (strncmp(cp, "null", sizeof("null") - 1) != 0)
+ goto parse_error;
+ if (!expect_value) {
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("unexpected null"));
+ goto bad;
+ }
+ cp += sizeof("null") - 1;
+ if (*cp != ',' && !isspace((unsigned char)*cp) && *cp != '\0')
+ goto parse_error;
+ if (!saw_comma && !TAILQ_EMPTY(&frame->items)) {
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("missing separator between values"));
+ goto bad;
+ }
+ saw_comma = false;
+
+ if (!json_insert_null(&frame->items, name, lineno))
+ goto bad;
+ name = NULL;
+ break;
+ case '+': case '-': case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7': case '8': case '9':
+ if (!expect_value) {
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("unexpected number"));
+ goto bad;
+ }
+ /* XXX - strtonumx() would be simpler here. */
+ len = strcspn(cp, " \f\n\r\t\v,");
+ ch = cp[len];
+ cp[len] = '\0';
+ if (!saw_comma && !TAILQ_EMPTY(&frame->items)) {
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("missing separator between values"));
+ goto bad;
+ }
+ saw_comma = false;
+ num = sudo_strtonum(cp, LLONG_MIN, LLONG_MAX, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx("%s:%u:%td: %s: %s", filename, lineno, cp - line,
+ cp, U_(errstr));
+ goto bad;
+ }
+ cp += len;
+ *cp = ch;
+
+ if (!json_insert_num(&frame->items, name, num, lineno))
+ goto bad;
+ name = NULL;
+ break;
+ default:
+ goto parse_error;
+ }
+ }
+ }
+ if (stack.depth != 0) {
+ frame = stack.frames[stack.depth - 1];
+ if (frame->parent == NULL || frame->parent->type == JSON_OBJECT) {
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("unmatched close brace"));
+ } else {
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line,
+ U_("unmatched close bracket"));
+ }
+ goto bad;
+ }
+
+ goto done;
+
+parse_error:
+ sudo_warnx("%s:%u:%td: %s", filename, lineno, cp - line, U_("parse error"));
+bad:
+ eventlog_json_free(root);
+ root = NULL;
+done:
+ free(line);
+ free(name);
+
+ debug_return_ptr(root);
+}
diff --git a/lib/eventlog/parse_json.h b/lib/eventlog/parse_json.h
new file mode 100644
index 0000000..e04efea
--- /dev/null
+++ b/lib/eventlog/parse_json.h
@@ -0,0 +1,46 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020, 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef PARSE_JSON_H
+#define PARSE_JSON_H
+
+#include <sudo_json.h>
+#include <sudo_queue.h>
+
+TAILQ_HEAD(json_item_list, json_item);
+
+struct eventlog_json_object {
+ struct json_item *parent;
+ struct json_item_list items;
+};
+
+struct json_item {
+ TAILQ_ENTRY(json_item) entries;
+ char *name; /* may be NULL for first brace */
+ unsigned int lineno;
+ enum json_value_type type;
+ union {
+ struct eventlog_json_object child;
+ char *string;
+ long long number;
+ id_t id;
+ bool boolean;
+ } u;
+};
+
+#endif /* PARSE_JSON_H */
diff --git a/lib/eventlog/regress/eventlog_store/store_json_test.c b/lib/eventlog/regress/eventlog_store/store_json_test.c
new file mode 100644
index 0000000..5c8f6fe
--- /dev/null
+++ b/lib/eventlog/regress/eventlog_store/store_json_test.c
@@ -0,0 +1,199 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020, 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_util.h>
+
+#include <parse_json.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+sudo_noreturn static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-cv] input_file ...\n",
+ getprogname());
+ exit(EXIT_FAILURE);
+}
+
+static bool
+compare(FILE *fp, const char *infile, struct json_container *jsonc)
+{
+ const char *cp;
+ unsigned int lineno = 0;
+ size_t linesize = 0;
+ char *line = NULL;
+ ssize_t len;
+
+ cp = sudo_json_get_buf(jsonc);
+
+ while ((len = getdelim(&line, &linesize, '\n', fp)) != -1) {
+ lineno++;
+
+ /* skip open/close brace, not present in formatted output */
+ if (lineno == 1 && strcmp(line, "{\n") == 0)
+ continue;
+ if (*cp == '\0' && strcmp(line, "}\n") == 0)
+ continue;
+
+ /* Ignore newlines in output to make comparison easier. */
+ if (*cp == '\n')
+ cp++;
+ if (line[len - 1] == '\n')
+ len--;
+
+ if (strncmp(line, cp, (size_t)len) != 0) {
+ fprintf(stderr, "%s: mismatch on line %u\n", infile, lineno);
+ fprintf(stderr, "expected: %s", line);
+ fprintf(stderr, "got : %.*s\n", (int)len, cp);
+ return false;
+ }
+ cp += len;
+ }
+ free(line);
+
+ return true;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch, i, ntests = 0, errors = 0;
+ bool cat = false;
+
+ initprogname(argc > 0 ? argv[0] : "store_json_test");
+
+ while ((ch = getopt(argc, argv, "cv")) != -1) {
+ switch (ch) {
+ case 'c':
+ cat = true;
+ break;
+ case 'v':
+ /* ignored */
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1)
+ usage();
+
+ for (i = 0; i < argc; i++) {
+ struct eventlog_json_object *root;
+ struct eventlog *evlog = NULL;
+ struct json_container jsonc;
+ const char *infile = argv[i];
+ const char *outfile = argv[i];
+ const char *cp;
+ char pathbuf[PATH_MAX];
+ FILE *infp = NULL;
+ FILE *outfp = NULL;
+
+ ntests++;
+
+ if (!sudo_json_init(&jsonc, 4, false, true, true)) {
+ errors++;
+ continue;
+ }
+
+ /* Parse input file. */
+ if ((infp = fopen(infile, "r")) == NULL) {
+ sudo_warn("%s", argv[i]);
+ errors++;
+ continue;
+ }
+ root = eventlog_json_read(infp, infile);
+ if (root == NULL) {
+ errors++;
+ goto next;
+ }
+
+ /* Convert JSON to event log. */
+ evlog = calloc(1, sizeof(*evlog));
+ if (evlog == NULL) {
+ sudo_warnx("%s: %s", __func__, "unable to allocate memory");
+ errors++;
+ goto next;
+ }
+ if (!eventlog_json_parse(root, evlog)) {
+ errors++;
+ goto next;
+ }
+
+ /* Format event log as JSON. */
+ if (!eventlog_store_json(&jsonc, evlog)) {
+ errors++;
+ goto next;
+ }
+
+ /* Check for a .out.ok file in the same location as the .in file. */
+ cp = strrchr(infile, '.');
+ if (cp != NULL && strcmp(cp, ".in") == 0) {
+ snprintf(pathbuf, sizeof(pathbuf), "%.*s.out.ok",
+ (int)(cp - infile), infile);
+ if ((outfp = fopen(pathbuf, "r")) != NULL)
+ outfile = pathbuf;
+ }
+ if (outfp == NULL)
+ outfp = infp;
+
+ /* Compare output to expected output. */
+ rewind(outfp);
+ if (!compare(outfp, outfile, &jsonc))
+ errors++;
+
+ /* Write the formatted output to stdout for -c (cat) */
+ if (cat) {
+ fprintf(stdout, "{%s\n}\n", sudo_json_get_buf(&jsonc));
+ fflush(stdout);
+ }
+
+next:
+ eventlog_free(evlog);
+ eventlog_json_free(root);
+ sudo_json_free(&jsonc);
+ if (infp != NULL)
+ fclose(infp);
+ if (outfp != NULL && outfp != infp)
+ fclose(outfp);
+ }
+
+ if (ntests != 0) {
+ printf("%s: %d test%s run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, ntests == 1 ? "" : "s", errors,
+ (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
diff --git a/lib/eventlog/regress/eventlog_store/store_sudo_test.c b/lib/eventlog/regress/eventlog_store/store_sudo_test.c
new file mode 100644
index 0000000..f873cd5
--- /dev/null
+++ b/lib/eventlog/regress/eventlog_store/store_sudo_test.c
@@ -0,0 +1,209 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020, 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_lbuf.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+sudo_noreturn static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-cv] input_file ...\n",
+ getprogname());
+ exit(EXIT_FAILURE);
+}
+
+static bool
+compare(FILE *fp, const char *infile, const char *output)
+{
+ static size_t linesize = 0;
+ static char *line = NULL;
+ int i;
+
+ /* Expect two log lines, one for accept, one for exit. */
+ for (i = 0; i < 2; i++) {
+ ssize_t output_len = (ssize_t)strcspn(output, "\n");
+ ssize_t len = getdelim(&line, &linesize, '\n', fp);
+ if (len == -1) {
+ sudo_warn("getdelim");
+ return false;
+ }
+ if (line[len - 1] == '\n')
+ len--;
+
+ if (len != output_len || strncmp(line, output, (size_t)len) != 0) {
+ fprintf(stderr, "%s: %s mismatch\n", infile, i ? "exit" : "accept");
+ fprintf(stderr, "expected: %.*s\n", (int)len, line);
+ fprintf(stderr, "got : %.*s\n", (int)output_len, output);
+ return false;
+ }
+ if (i == 0) {
+ /* Skip past newline in accept record output. */
+ output += output_len;
+ if (output[0] != '\n' || output[1] == '\0') {
+ sudo_warnx("missing exit record");
+ return false;
+ }
+ output++;
+ }
+ }
+
+ return true;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch, i, ntests = 0, errors = 0;
+ struct sudo_lbuf lbuf;
+ bool cat = false;
+
+ initprogname(argc > 0 ? argv[0] : "store_sudo_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'c':
+ cat = true;
+ break;
+ case 'v':
+ /* ignored */
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1)
+ usage();
+
+ sudo_lbuf_init(&lbuf, NULL, 0, NULL, 0);
+ for (i = 0; i < argc; i++) {
+ struct eventlog_json_object *root;
+ struct eventlog *evlog = NULL;
+ const char *infile = argv[i];
+ const char *outfile = argv[i];
+ char pathbuf[PATH_MAX];
+ FILE *infp = NULL;
+ FILE *outfp = NULL;
+ size_t len;
+
+ ntests++;
+
+ /* Parse input file. */
+ if ((infp = fopen(infile, "r")) == NULL) {
+ sudo_warn("%s", argv[i]);
+ errors++;
+ continue;
+ }
+ root = eventlog_json_read(infp, infile);
+ if (root == NULL) {
+ errors++;
+ goto next;
+ }
+
+ /* Convert JSON to event log. */
+ evlog = calloc(1, sizeof(*evlog));
+ if (evlog == NULL) {
+ sudo_warnx("%s: %s", __func__, "unable to allocate memory");
+ errors++;
+ goto next;
+ }
+ if (!eventlog_json_parse(root, evlog)) {
+ errors++;
+ goto next;
+ }
+
+ /* Format event log in sudo log format. */
+ if (!eventlog_store_sudo(EVLOG_ACCEPT, evlog, &lbuf)) {
+ errors++;
+ goto next;
+ }
+ sudo_lbuf_append(&lbuf, "\n");
+ if (!eventlog_store_sudo(EVLOG_EXIT, evlog, &lbuf)) {
+ errors++;
+ goto next;
+ }
+ sudo_lbuf_append(&lbuf, "\n");
+
+ /* Write the formatted output to stdout for -c (cat) */
+ if (cat) {
+ puts(lbuf.buf);
+ fflush(stdout);
+ }
+
+ /* Check for a .out.ok file in the same location as the .in file. */
+ len = strlen(infile);
+ if (len < sizeof(".json.in")) {
+ sudo_warnx("%s must end in .json.in", infile);
+ errors++;
+ goto next;
+ }
+ len -= sizeof(".json.in") - 1;
+ if (strcmp(&infile[len], ".json.in") != 0) {
+ sudo_warnx("%s must end in .json.in", infile);
+ errors++;
+ goto next;
+ }
+ snprintf(pathbuf, sizeof(pathbuf), "%.*s.sudo.out.ok",
+ (int)len, infile);
+ if ((outfp = fopen(pathbuf, "r")) == NULL) {
+ sudo_warn("%s", pathbuf);
+ errors++;
+ goto next;
+ }
+
+ /* Compare output to expected output. */
+ if (!compare(outfp, outfile, lbuf.buf))
+ errors++;
+
+next:
+ lbuf.len = 0;
+ eventlog_json_free(root);
+ eventlog_free(evlog);
+ if (infp != NULL)
+ fclose(infp);
+ if (outfp != NULL && outfp != infp)
+ fclose(outfp);
+ }
+ sudo_lbuf_destroy(&lbuf);
+
+ if (ntests != 0) {
+ printf("%s: %d test%s run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, ntests == 1 ? "" : "s", errors,
+ (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
diff --git a/lib/eventlog/regress/eventlog_store/test1.json.in b/lib/eventlog/regress/eventlog_store/test1.json.in
new file mode 100644
index 0000000..0e73df9
--- /dev/null
+++ b/lib/eventlog/regress/eventlog_store/test1.json.in
@@ -0,0 +1,52 @@
+{
+ "uuid": "94109a6eb8-9bed-41ba-0ff1-79926f3947",
+ "server_time": {
+ "seconds": 1677638673,
+ "nanoseconds": 98769807,
+ "iso8601": "20230301024433Z",
+ "localtime": "Tue Feb 28 19:44:33 MST 2023"
+ },
+ "submit_time": {
+ "seconds": 1677638673,
+ "nanoseconds": 93789768,
+ "iso8601": "20230301024433Z",
+ "localtime": "Tue Feb 28 19:44:33 MST 2023"
+ },
+ "peeraddr": "172.30.200.2",
+ "iolog_path": "/var/log/sudo-logsrvd/millert/00/03/FI",
+ "iolog_file": "00/03/FI",
+ "columns": 80,
+ "command": "/usr/bin/ci",
+ "lines": 24,
+ "runargv": [
+ "ci",
+ "-u",
+ "aliases\n"
+ ],
+ "runenv": [
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "TERM=tmux",
+ "LANG=en_US.UTF-8",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/bash",
+ "SUDO_COMMAND=/usr/bin/ci -u aliases",
+ "SUDO_USER=millert",
+ "SUDO_UID=8036",
+ "SUDO_GID=20"
+ ],
+ "runenv_override": [
+ "KRB5CCNAME=bogus",
+ "LD_LIBRARY_PATH=/opt/sudo/libexec"
+ ],
+ "runuid": 0,
+ "runuser": "root",
+ "source": "/etc/sudoers:89:24",
+ "submitcwd": "/etc/mail",
+ "submithost": "xerxes.sudo.ws",
+ "submituser": "millert",
+ "ttyname": "/dev/ttypb",
+ "exit_value": 1
+}
diff --git a/lib/eventlog/regress/eventlog_store/test1.json.out.ok b/lib/eventlog/regress/eventlog_store/test1.json.out.ok
new file mode 100644
index 0000000..2ddc8c5
--- /dev/null
+++ b/lib/eventlog/regress/eventlog_store/test1.json.out.ok
@@ -0,0 +1,31 @@
+{
+ "submituser": "millert",
+ "command": "/usr/bin/ci",
+ "runuser": "root",
+ "source": "/etc/sudoers:89:24",
+ "ttyname": "/dev/ttypb",
+ "submithost": "xerxes.sudo.ws",
+ "submitcwd": "/etc/mail",
+ "runuid": 0,
+ "columns": 80,
+ "lines": 24,
+ "runargv": [
+ "ci",
+ "-u",
+ "aliases\n"
+ ],
+ "runenv": [
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "TERM=tmux",
+ "LANG=en_US.UTF-8",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/bash",
+ "SUDO_COMMAND=/usr/bin/ci -u aliases",
+ "SUDO_USER=millert",
+ "SUDO_UID=8036",
+ "SUDO_GID=20"
+ ]
+}
diff --git a/lib/eventlog/regress/eventlog_store/test1.sudo.out.ok b/lib/eventlog/regress/eventlog_store/test1.sudo.out.ok
new file mode 100644
index 0000000..17c344e
--- /dev/null
+++ b/lib/eventlog/regress/eventlog_store/test1.sudo.out.ok
@@ -0,0 +1,2 @@
+HOST=xerxes.sudo.ws ; TTY=ttypb ; CWD=/etc/mail ; USER=root ; TSID=0003FI ; ENV=KRB5CCNAME=bogus LD_LIBRARY_PATH=/opt/sudo/libexec ; COMMAND=/usr/bin/ci -u aliases#012
+HOST=xerxes.sudo.ws ; TTY=ttypb ; CWD=/etc/mail ; USER=root ; TSID=0003FI ; ENV=KRB5CCNAME=bogus LD_LIBRARY_PATH=/opt/sudo/libexec ; COMMAND=/usr/bin/ci -u aliases#012 ; EXIT=1
diff --git a/lib/eventlog/regress/eventlog_store/test2.json.in b/lib/eventlog/regress/eventlog_store/test2.json.in
new file mode 100644
index 0000000..6af3a31
--- /dev/null
+++ b/lib/eventlog/regress/eventlog_store/test2.json.in
@@ -0,0 +1,48 @@
+{
+ "uuid": "a17521dd52-1b7f-4ca1-5086-6957336362",
+ "server_time": {
+ "seconds": 1671070212,
+ "nanoseconds": 246006550,
+ "iso8601": "20221215021012Z",
+ "localtime": "Wed Dec 14 19:10:12 MST 2022"
+ },
+ "submit_time": {
+ "seconds": 1671070212,
+ "nanoseconds": 243017337,
+ "iso8601": "20221215021012Z",
+ "localtime": "Wed Dec 14 19:10:12 MST 2022"
+ },
+ "peeraddr": "172.30.200.2",
+ "iolog_path": "/var/log/sudo-logsrvd/millert/00/03/5Q",
+ "iolog_file": "00/03/5Q",
+ "columns": 80,
+ "command": "/usr/bin/id",
+ "lines": 24,
+ "runargv": [
+ "id"
+ ],
+ "runenv": [
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "TERM=tmux",
+ "LANG=en_US.UTF-8",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/bash",
+ "SUDO_COMMAND=/usr/bin/id",
+ "SUDO_USER=millert",
+ "SUDO_UID=8036",
+ "SUDO_GID=20"
+ ],
+ "runenv_override": [
+ "KRB5CCNAME=bogus"
+ ],
+ "runuid": 0,
+ "runuser": "root",
+ "source": "sudoRole %wheel",
+ "submitcwd": "/usr/src/local/millert/sudo/trunk",
+ "submithost": "xerxes.sudo.ws",
+ "submituser": "millert",
+ "ttyname": "/dev/ttyp0"
+}
diff --git a/lib/eventlog/regress/eventlog_store/test2.json.out.ok b/lib/eventlog/regress/eventlog_store/test2.json.out.ok
new file mode 100644
index 0000000..e26290c
--- /dev/null
+++ b/lib/eventlog/regress/eventlog_store/test2.json.out.ok
@@ -0,0 +1,29 @@
+{
+ "submituser": "millert",
+ "command": "/usr/bin/id",
+ "runuser": "root",
+ "source": "sudoRole %wheel",
+ "ttyname": "/dev/ttyp0",
+ "submithost": "xerxes.sudo.ws",
+ "submitcwd": "/usr/src/local/millert/sudo/trunk",
+ "runuid": 0,
+ "columns": 80,
+ "lines": 24,
+ "runargv": [
+ "id"
+ ],
+ "runenv": [
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "TERM=tmux",
+ "LANG=en_US.UTF-8",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/bash",
+ "SUDO_COMMAND=/usr/bin/id",
+ "SUDO_USER=millert",
+ "SUDO_UID=8036",
+ "SUDO_GID=20"
+ ]
+}
diff --git a/lib/eventlog/regress/eventlog_store/test2.sudo.out.ok b/lib/eventlog/regress/eventlog_store/test2.sudo.out.ok
new file mode 100644
index 0000000..51faf04
--- /dev/null
+++ b/lib/eventlog/regress/eventlog_store/test2.sudo.out.ok
@@ -0,0 +1,2 @@
+HOST=xerxes.sudo.ws ; TTY=ttyp0 ; CWD=/usr/src/local/millert/sudo/trunk ; USER=root ; TSID=00035Q ; ENV=KRB5CCNAME=bogus ; COMMAND=/usr/bin/id
+HOST=xerxes.sudo.ws ; TTY=ttyp0 ; CWD=/usr/src/local/millert/sudo/trunk ; USER=root ; TSID=00035Q ; ENV=KRB5CCNAME=bogus ; COMMAND=/usr/bin/id ; EXIT=0
diff --git a/lib/eventlog/regress/eventlog_store/test3.json.in b/lib/eventlog/regress/eventlog_store/test3.json.in
new file mode 100644
index 0000000..184333f
--- /dev/null
+++ b/lib/eventlog/regress/eventlog_store/test3.json.in
@@ -0,0 +1,49 @@
+{
+ "uuid": "54e6806305-0f50-44bf-fe6a-c8fa7a65ac",
+ "server_time": {
+ "seconds": 1678475729,
+ "nanoseconds": 286796437,
+ "iso8601": "20230310191529Z",
+ "localtime": "Fri Mar 10 12:15:29 MST 2023"
+ },
+ "submit_time": {
+ "seconds": 1633116433,
+ "nanoseconds": 682537651,
+ "iso8601": "20211001192713Z",
+ "localtime": "Fri Oct 1 13:27:13 MDT 2021"
+ },
+ "peeraddr": "172.30.200.50",
+ "iolog_path": "/var/log/sudo-logsrvd/millert/00/00/5H",
+ "iolog_file": "00/00/5H",
+ "columns": 80,
+ "command": "/usr/bin/find",
+ "lines": 24,
+ "runargv": [
+ "find",
+ "build/out/sudoers/"
+ ],
+ "runenv": [
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "TERM=tmux",
+ "LANG=en_US.UTF-8",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/bash",
+ "SUDO_COMMAND=/usr/bin/find build/out/sudoers/",
+ "SUDO_USER=millert",
+ "SUDO_UID=8036",
+ "SUDO_GID=20"
+ ],
+ "runuid": 0,
+ "runuser": "root",
+ "source": "/etc/sudoers:89:24",
+ "submitcwd": "/home/millert/sudo/oss-fuzz",
+ "submithost": "linux-build",
+ "submituser": "millert",
+ "ttyname": "/dev/pts/1",
+ "exit_value": 131,
+ "signal": "QUIT",
+ "dumped_core": true
+}
diff --git a/lib/eventlog/regress/eventlog_store/test3.json.out.ok b/lib/eventlog/regress/eventlog_store/test3.json.out.ok
new file mode 100644
index 0000000..967a75c
--- /dev/null
+++ b/lib/eventlog/regress/eventlog_store/test3.json.out.ok
@@ -0,0 +1,30 @@
+{
+ "submituser": "millert",
+ "command": "/usr/bin/find",
+ "runuser": "root",
+ "source": "/etc/sudoers:89:24",
+ "ttyname": "/dev/pts/1",
+ "submithost": "linux-build",
+ "submitcwd": "/home/millert/sudo/oss-fuzz",
+ "runuid": 0,
+ "columns": 80,
+ "lines": 24,
+ "runargv": [
+ "find",
+ "build/out/sudoers/"
+ ],
+ "runenv": [
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "TERM=tmux",
+ "LANG=en_US.UTF-8",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/bash",
+ "SUDO_COMMAND=/usr/bin/find build/out/sudoers/",
+ "SUDO_USER=millert",
+ "SUDO_UID=8036",
+ "SUDO_GID=20"
+ ]
+}
diff --git a/lib/eventlog/regress/eventlog_store/test3.sudo.out.ok b/lib/eventlog/regress/eventlog_store/test3.sudo.out.ok
new file mode 100644
index 0000000..5f7fee2
--- /dev/null
+++ b/lib/eventlog/regress/eventlog_store/test3.sudo.out.ok
@@ -0,0 +1,2 @@
+HOST=linux-build ; TTY=pts/1 ; CWD=/home/millert/sudo/oss-fuzz ; USER=root ; TSID=00005H ; COMMAND=/usr/bin/find build/out/sudoers/
+HOST=linux-build ; TTY=pts/1 ; CWD=/home/millert/sudo/oss-fuzz ; USER=root ; TSID=00005H ; COMMAND=/usr/bin/find build/out/sudoers/ ; SIGNAL=QUIT ; EXIT=131
diff --git a/lib/eventlog/regress/eventlog_store/test4.json.in b/lib/eventlog/regress/eventlog_store/test4.json.in
new file mode 100644
index 0000000..8836a44
--- /dev/null
+++ b/lib/eventlog/regress/eventlog_store/test4.json.in
@@ -0,0 +1,47 @@
+{
+ "uuid": "0bf9f26a7c-5e8b-4f82-f6c1-24a49a254c",
+ "server_time": {
+ "seconds": 1677638637,
+ "nanoseconds": 369091862,
+ "iso8601": "20230301024357Z",
+ "localtime": "Tue Feb 28 19:43:57 MST 2023"
+ },
+ "submit_time": {
+ "seconds": 1677638637,
+ "nanoseconds": 364571747,
+ "iso8601": "20230301024357Z",
+ "localtime": "Tue Feb 28 19:43:57 MST 2023"
+ },
+ "peeraddr": "172.30.200.2",
+ "iolog_path": "/var/log/sudo-logsrvd/millert/00/03/FG",
+ "iolog_file": "00/03/FG",
+ "columns": 80,
+ "command": "/usr/bin/vi",
+ "lines": 24,
+ "runargv": [
+ "vi",
+ "aliases"
+ ],
+ "runenv": [
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "TERM=tmux",
+ "LANG=en_US.UTF-8",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/bash",
+ "SUDO_COMMAND=/usr/bin/vi aliases",
+ "SUDO_USER=millert",
+ "SUDO_UID=8036",
+ "SUDO_GID=20",
+ "KRB5CCNAME=bogus"
+ ],
+ "runuid": 0,
+ "runuser": "root",
+ "source": "/etc/sudoers:89:24",
+ "submitcwd": "/etc/mail",
+ "submithost": "xerxes.sudo.ws",
+ "submituser": "millert",
+ "ttyname": "/dev/ttypb"
+}
diff --git a/lib/eventlog/regress/eventlog_store/test4.json.out.ok b/lib/eventlog/regress/eventlog_store/test4.json.out.ok
new file mode 100644
index 0000000..2f15940
--- /dev/null
+++ b/lib/eventlog/regress/eventlog_store/test4.json.out.ok
@@ -0,0 +1,31 @@
+{
+ "submituser": "millert",
+ "command": "/usr/bin/vi",
+ "runuser": "root",
+ "source": "/etc/sudoers:89:24",
+ "ttyname": "/dev/ttypb",
+ "submithost": "xerxes.sudo.ws",
+ "submitcwd": "/etc/mail",
+ "runuid": 0,
+ "columns": 80,
+ "lines": 24,
+ "runargv": [
+ "vi",
+ "aliases"
+ ],
+ "runenv": [
+ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "TERM=tmux",
+ "LANG=en_US.UTF-8",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/bash",
+ "SUDO_COMMAND=/usr/bin/vi aliases",
+ "SUDO_USER=millert",
+ "SUDO_UID=8036",
+ "SUDO_GID=20",
+ "KRB5CCNAME=bogus"
+ ]
+}
diff --git a/lib/eventlog/regress/eventlog_store/test4.sudo.out.ok b/lib/eventlog/regress/eventlog_store/test4.sudo.out.ok
new file mode 100644
index 0000000..c1589d0
--- /dev/null
+++ b/lib/eventlog/regress/eventlog_store/test4.sudo.out.ok
@@ -0,0 +1,2 @@
+HOST=xerxes.sudo.ws ; TTY=ttypb ; CWD=/etc/mail ; USER=root ; TSID=0003FG ; COMMAND=/usr/bin/vi aliases
+HOST=xerxes.sudo.ws ; TTY=ttypb ; CWD=/etc/mail ; USER=root ; TSID=0003FG ; COMMAND=/usr/bin/vi aliases ; EXIT=0
diff --git a/lib/eventlog/regress/logwrap/check_wrap.c b/lib/eventlog/regress/logwrap/check_wrap.c
new file mode 100644
index 0000000..15134f0
--- /dev/null
+++ b/lib/eventlog/regress/logwrap/check_wrap.c
@@ -0,0 +1,124 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011-2013 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_plugin.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+sudo_noreturn static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-v] inputfile\n", getprogname());
+ exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch, lineno = 0, which = 0;
+ char *line, lines[2][2048];
+ const char *infile;
+ unsigned int len;
+ FILE *fp;
+
+ initprogname(argc > 0 ? argv[0] : "check_wrap");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignored */
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1)
+ usage();
+ infile = argv[0];
+
+ fp = fopen(infile, "r");
+ if (fp == NULL)
+ sudo_fatalx("unable to open %s", infile);
+
+ /*
+ * Each test record consists of a log entry on one line and a list of
+ * line lengths to test it with on the next. E.g.
+ *
+ * Jun 30 14:49:51 : millert : TTY=ttypn ; PWD=/usr/src/local/millert/hg/sudo/trunk/plugins/sudoers ; USER=root ; TSID=0004LD ; COMMAND=/usr/local/sbin/visudo
+ * 60-80,40
+ */
+ while ((line = fgets(lines[which], sizeof(lines[which]), fp)) != NULL) {
+ char *cp, *last;
+
+ line[strcspn(line, "\n")] = '\0';
+
+ /* If we read the 2nd line, parse list of line lengths and check. */
+ if (which) {
+ lineno++;
+ for (cp = strtok_r(lines[1], ",", &last); cp != NULL; cp = strtok_r(NULL, ",", &last)) {
+ unsigned int maxlen;
+ const char *errstr;
+ char *dash;
+
+ /* May be either a number or a range. */
+ dash = strchr(cp, '-');
+ if (dash != NULL) {
+ *dash = '\0';
+ len = (unsigned int)sudo_strtonum(cp, 0, INT_MAX, &errstr);
+ if (errstr == NULL)
+ maxlen = (unsigned int)sudo_strtonum(dash + 1, 0, INT_MAX, &errstr);
+ } else {
+ len = maxlen = (unsigned int)sudo_strtonum(cp, 0, INT_MAX, &errstr);
+ }
+ if (errstr != NULL) {
+ sudo_fatalx("%s: invalid length on line %d", infile, lineno);
+ }
+ while (len <= maxlen) {
+ if (len == 0) {
+ puts("# word wrap disabled");
+ } else {
+ printf("# word wrap at %u characters\n", len);
+ }
+ eventlog_writeln(stdout, lines[0], strlen(lines[0]), len);
+ len++;
+ }
+ }
+ }
+ which = !which;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/lib/eventlog/regress/logwrap/check_wrap.in b/lib/eventlog/regress/logwrap/check_wrap.in
new file mode 100644
index 0000000..e8e7081
--- /dev/null
+++ b/lib/eventlog/regress/logwrap/check_wrap.in
@@ -0,0 +1,4 @@
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ; PWD=/home/tu2sp3-a ; USER=root ; COMMAND=/opt/quest/bin/vastool list users
+0,60-80,120,140
+Jun 26 18:00:06 : millert : TTY=ttypm ; PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ; TSID=0004KT ; COMMAND=/bin/rm /root/.bash_profile
+0,60-80,120,140
diff --git a/lib/eventlog/regress/logwrap/check_wrap.out.ok b/lib/eventlog/regress/logwrap/check_wrap.out.ok
new file mode 100644
index 0000000..55e9da8
--- /dev/null
+++ b/lib/eventlog/regress/logwrap/check_wrap.out.ok
@@ -0,0 +1,179 @@
+# word wrap disabled
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ; PWD=/home/tu2sp3-a ; USER=root ; COMMAND=/opt/quest/bin/vastool list users
+# word wrap at 60 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1
+ ; PWD=/home/tu2sp3-a ; USER=root ;
+ COMMAND=/opt/quest/bin/vastool list users
+# word wrap at 61 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1
+ ; PWD=/home/tu2sp3-a ; USER=root ;
+ COMMAND=/opt/quest/bin/vastool list users
+# word wrap at 62 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ;
+ COMMAND=/opt/quest/bin/vastool list users
+# word wrap at 63 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ;
+ COMMAND=/opt/quest/bin/vastool list users
+# word wrap at 64 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ;
+ COMMAND=/opt/quest/bin/vastool list users
+# word wrap at 65 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ;
+ COMMAND=/opt/quest/bin/vastool list users
+# word wrap at 66 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ;
+ COMMAND=/opt/quest/bin/vastool list users
+# word wrap at 67 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ; COMMAND=/opt/quest/bin/vastool
+ list users
+# word wrap at 68 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ; COMMAND=/opt/quest/bin/vastool
+ list users
+# word wrap at 69 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ; COMMAND=/opt/quest/bin/vastool
+ list users
+# word wrap at 70 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ; COMMAND=/opt/quest/bin/vastool
+ list users
+# word wrap at 71 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ; COMMAND=/opt/quest/bin/vastool
+ list users
+# word wrap at 72 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ; COMMAND=/opt/quest/bin/vastool list
+ users
+# word wrap at 73 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ; COMMAND=/opt/quest/bin/vastool list
+ users
+# word wrap at 74 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ; COMMAND=/opt/quest/bin/vastool list
+ users
+# word wrap at 75 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ; COMMAND=/opt/quest/bin/vastool list
+ users
+# word wrap at 76 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ; COMMAND=/opt/quest/bin/vastool list
+ users
+# word wrap at 77 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ; COMMAND=/opt/quest/bin/vastool list
+ users
+# word wrap at 78 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ; COMMAND=/opt/quest/bin/vastool list users
+# word wrap at 79 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ; COMMAND=/opt/quest/bin/vastool list users
+# word wrap at 80 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ;
+ PWD=/home/tu2sp3-a ; USER=root ; COMMAND=/opt/quest/bin/vastool list users
+# word wrap at 120 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ; PWD=/home/tu2sp3-a ; USER=root ;
+ COMMAND=/opt/quest/bin/vastool list users
+# word wrap at 140 characters
+Jul 11 11:30:17 : tu2sp3-a : command not allowed ; TTY=pts/1 ; PWD=/home/tu2sp3-a ; USER=root ; COMMAND=/opt/quest/bin/vastool list users
+# word wrap disabled
+Jun 26 18:00:06 : millert : TTY=ttypm ; PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ; TSID=0004KT ; COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 60 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ;
+ TSID=0004KT ; COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 61 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ;
+ TSID=0004KT ; COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 62 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ;
+ TSID=0004KT ; COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 63 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ;
+ TSID=0004KT ; COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 64 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ;
+ TSID=0004KT ; COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 65 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ;
+ TSID=0004KT ; COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 66 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ;
+ TSID=0004KT ; COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 67 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ;
+ TSID=0004KT ; COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 68 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ;
+ TSID=0004KT ; COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 69 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ;
+ TSID=0004KT ; COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 70 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ; TSID=0004KT
+ ; COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 71 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ; TSID=0004KT
+ ; COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 72 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ; TSID=0004KT ;
+ COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 73 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ; TSID=0004KT ;
+ COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 74 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ; TSID=0004KT ;
+ COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 75 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ; TSID=0004KT ;
+ COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 76 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ; TSID=0004KT ;
+ COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 77 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ; TSID=0004KT ;
+ COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 78 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ; TSID=0004KT ;
+ COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 79 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ;
+ PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ; TSID=0004KT ;
+ COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 80 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ; PWD=/usr/src/local/millert/hg/sudo/build
+ ; USER=root ; TSID=0004KT ; COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 120 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ; PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ; TSID=0004KT ;
+ COMMAND=/bin/rm /root/.bash_profile
+# word wrap at 140 characters
+Jun 26 18:00:06 : millert : TTY=ttypm ; PWD=/usr/src/local/millert/hg/sudo/build ; USER=root ; TSID=0004KT ; COMMAND=/bin/rm
+ /root/.bash_profile
diff --git a/lib/eventlog/regress/parse_json/check_parse_json.c b/lib/eventlog/regress/parse_json/check_parse_json.c
new file mode 100644
index 0000000..496fac9
--- /dev/null
+++ b/lib/eventlog/regress/parse_json/check_parse_json.c
@@ -0,0 +1,270 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_util.h>
+
+#include <parse_json.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+static bool
+json_print_object(struct json_container *jsonc, struct eventlog_json_object *object)
+{
+ struct json_item *item;
+ struct json_value json_value;
+ bool ret = false;
+
+ TAILQ_FOREACH(item, &object->items, entries) {
+ switch (item->type) {
+ case JSON_STRING:
+ json_value.type = JSON_STRING;
+ json_value.u.string = item->u.string;
+ if (!sudo_json_add_value(jsonc, item->name, &json_value))
+ goto oom;
+ break;
+ case JSON_NUMBER:
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = item->u.number;
+ if (!sudo_json_add_value(jsonc, item->name, &json_value))
+ goto oom;
+ break;
+ case JSON_OBJECT:
+ if (!sudo_json_open_object(jsonc, item->name))
+ goto oom;
+ if (!json_print_object(jsonc, &item->u.child))
+ goto done;
+ if (!sudo_json_close_object(jsonc))
+ goto oom;
+ break;
+ case JSON_ARRAY:
+ if (!sudo_json_open_array(jsonc, item->name))
+ goto oom;
+ if (!json_print_object(jsonc, &item->u.child))
+ goto done;
+ if (!sudo_json_close_array(jsonc))
+ goto oom;
+ break;
+ case JSON_BOOL:
+ json_value.type = JSON_BOOL;
+ json_value.u.boolean = item->u.boolean;
+ if (!sudo_json_add_value(jsonc, item->name, &json_value))
+ goto oom;
+ break;
+ case JSON_NULL:
+ json_value.type = JSON_NULL;
+ if (!sudo_json_add_value(jsonc, item->name, &json_value))
+ goto oom;
+ break;
+ default:
+ sudo_warnx("unsupported JSON type %d", item->type);
+ goto done;
+ }
+ }
+
+ ret = true;
+ goto done;
+
+oom:
+ sudo_warnx("%s: %s", __func__, "unable to allocate memory");
+done:
+ return ret;
+}
+
+static bool
+json_format(struct json_container *jsonc, struct eventlog_json_object *object)
+{
+ struct json_item *item;
+ bool ret = false;
+
+ /* First object holds all the actual data. */
+ item = TAILQ_FIRST(&object->items);
+ if (item->type != JSON_OBJECT) {
+ sudo_warnx("expected JSON_OBJECT, got %d", item->type);
+ goto done;
+ }
+ object = &item->u.child;
+
+ if (!json_print_object(jsonc, object))
+ goto done;
+
+ ret = true;
+
+done:
+ return ret;
+}
+
+sudo_noreturn static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-cv] input_file ...\n",
+ getprogname());
+ exit(EXIT_FAILURE);
+}
+
+static bool
+compare(FILE *fp, const char *infile, struct json_container *jsonc)
+{
+ const char *cp;
+ unsigned int lineno = 0;
+ size_t linesize = 0;
+ char *line = NULL;
+ ssize_t len;
+
+ cp = sudo_json_get_buf(jsonc);
+
+ while ((len = getdelim(&line, &linesize, '\n', fp)) != -1) {
+ lineno++;
+
+ /* skip open/close brace, not present in formatted output */
+ if (lineno == 1 && strcmp(line, "{\n") == 0)
+ continue;
+ if (*cp == '\0' && strcmp(line, "}\n") == 0)
+ continue;
+
+ /* Ignore newlines in output to make comparison easier. */
+ if (*cp == '\n')
+ cp++;
+ if (line[len - 1] == '\n')
+ len--;
+
+ if (strncmp(line, cp, (size_t)len) != 0) {
+ fprintf(stderr, "%s: mismatch on line %u\n", infile, lineno);
+ fprintf(stderr, "expected: %s", line);
+ fprintf(stderr, "got : %.*s\n", (int)len, cp);
+ return false;
+ }
+ cp += len;
+ }
+ free(line);
+
+ return true;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch, i, ntests = 0, errors = 0;
+ bool cat = false;
+
+ initprogname(argc > 0 ? argv[0] : "check_parse_json");
+
+ while ((ch = getopt(argc, argv, "cv")) != -1) {
+ switch (ch) {
+ case 'c':
+ cat = true;
+ break;
+ case 'v':
+ /* ignored */
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1)
+ usage();
+
+ for (i = 0; i < argc; i++) {
+ struct eventlog_json_object *root;
+ struct json_container jsonc;
+ const char *infile = argv[i];
+ const char *outfile = argv[i];
+ const char *cp;
+ char pathbuf[PATH_MAX];
+ FILE *infp = NULL;
+ FILE *outfp = NULL;
+
+ ntests++;
+
+ if (!sudo_json_init(&jsonc, 4, false, true, true)) {
+ errors++;
+ continue;
+ }
+
+ /* Parse input file. */
+ if ((infp = fopen(infile, "r")) == NULL) {
+ sudo_warn("%s", argv[i]);
+ errors++;
+ continue;
+ }
+ root = eventlog_json_read(infp, infile);
+ if (root == NULL) {
+ errors++;
+ goto next;
+ }
+
+ /* Format as pretty-printed JSON */
+ if (!json_format(&jsonc, root)) {
+ errors++;
+ goto next;
+ }
+
+ /* Check for a .out.ok file in the same location as the .in file. */
+ cp = strrchr(infile, '.');
+ if (cp != NULL && strcmp(cp, ".in") == 0) {
+ snprintf(pathbuf, sizeof(pathbuf), "%.*s.out.ok",
+ (int)(cp - infile), infile);
+ if ((outfp = fopen(pathbuf, "r")) != NULL)
+ outfile = pathbuf;
+ }
+ if (outfp == NULL)
+ outfp = infp;
+
+ /* Compare output to expected output. */
+ rewind(outfp);
+ if (!compare(outfp, outfile, &jsonc))
+ errors++;
+
+ /* Write the formatted output to stdout for -c (cat) */
+ if (cat) {
+ fprintf(stdout, "{%s\n}\n", sudo_json_get_buf(&jsonc));
+ fflush(stdout);
+ }
+
+next:
+ eventlog_json_free(root);
+ sudo_json_free(&jsonc);
+ if (infp != NULL)
+ fclose(infp);
+ if (outfp != NULL && outfp != infp)
+ fclose(outfp);
+ }
+
+ if (ntests != 0) {
+ printf("%s: %d test%s run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, ntests == 1 ? "" : "s", errors,
+ (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
diff --git a/lib/eventlog/regress/parse_json/test1.in b/lib/eventlog/regress/parse_json/test1.in
new file mode 100644
index 0000000..8ad3689
--- /dev/null
+++ b/lib/eventlog/regress/parse_json/test1.in
@@ -0,0 +1,34 @@
+{
+ "timestamp": {
+ "seconds": 1584993067,
+ "nanoseconds": 880288287
+ },
+ "columns": 80,
+ "command": "/usr/bin/make",
+ "lines": 24,
+ "runargv": [
+ "make",
+ "test"
+ ],
+ "runenv": [
+ "LANG=en_US.UTF-8",
+ "PATH=/bin:/sbin:/usr/games:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin",
+ "TERM=vt100",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/ksh",
+ "SUDO_COMMAND=/usr/bin/make test",
+ "SUDO_USER=millert",
+ "SUDO_UID=8036",
+ "SUDO_GID=20",
+ "A__z=\"*SHLVL"
+ ],
+ "runuid": 0,
+ "runuser": "root",
+ "submitcwd": "/home/test",
+ "submithost": "sudo.ws",
+ "submituser": "millert",
+ "ttyname": "/dev/console"
+}
diff --git a/lib/eventlog/regress/parse_json/test2.in b/lib/eventlog/regress/parse_json/test2.in
new file mode 100644
index 0000000..df7170f
--- /dev/null
+++ b/lib/eventlog/regress/parse_json/test2.in
@@ -0,0 +1,28 @@
+{
+ "timestamp": { "seconds": 1584993067, "nanoseconds": 880288287 },
+ "columns": 80,
+ "command": "/usr/bin/make",
+ "lines": 24,
+ "runargv": [ "make", "test" ],
+ "runenv": [
+ "LANG=en_US.UTF-8",
+ "PATH=/bin:/sbin:/usr/games:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin",
+ "TERM=vt100",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/ksh",
+ "SUDO_COMMAND=/usr/bin/make test",
+ "SUDO_USER=millert",
+ "SUDO_UID=8036",
+ "SUDO_GID=20",
+ "A__z=\"*SHLVL"
+ ],
+ "runuid": 0,
+ "runuser": "root",
+ "submitcwd": "/home/test",
+ "submithost": "sudo.ws",
+ "submituser": "millert",
+ "ttyname": "/dev/console"
+}
diff --git a/lib/eventlog/regress/parse_json/test2.out.ok b/lib/eventlog/regress/parse_json/test2.out.ok
new file mode 100644
index 0000000..8ad3689
--- /dev/null
+++ b/lib/eventlog/regress/parse_json/test2.out.ok
@@ -0,0 +1,34 @@
+{
+ "timestamp": {
+ "seconds": 1584993067,
+ "nanoseconds": 880288287
+ },
+ "columns": 80,
+ "command": "/usr/bin/make",
+ "lines": 24,
+ "runargv": [
+ "make",
+ "test"
+ ],
+ "runenv": [
+ "LANG=en_US.UTF-8",
+ "PATH=/bin:/sbin:/usr/games:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin",
+ "TERM=vt100",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/ksh",
+ "SUDO_COMMAND=/usr/bin/make test",
+ "SUDO_USER=millert",
+ "SUDO_UID=8036",
+ "SUDO_GID=20",
+ "A__z=\"*SHLVL"
+ ],
+ "runuid": 0,
+ "runuser": "root",
+ "submitcwd": "/home/test",
+ "submithost": "sudo.ws",
+ "submituser": "millert",
+ "ttyname": "/dev/console"
+}
diff --git a/lib/eventlog/regress/parse_json/test3.in b/lib/eventlog/regress/parse_json/test3.in
new file mode 100644
index 0000000..6f243e3
--- /dev/null
+++ b/lib/eventlog/regress/parse_json/test3.in
@@ -0,0 +1,22 @@
+{
+ "true": false,
+ "false": true,
+ "number": 1234567890,
+ "null": null,
+ "string": "non\u0073ense",
+ "scope": {
+ "a": "b",
+ "bah": null
+ },
+ "array1": [
+ "foo",
+ "bar",
+ [
+ 123,
+ null,
+ false,
+ "fizz",
+ "buzz"
+ ]
+ ]
+}
diff --git a/lib/eventlog/regress/parse_json/test3.out.ok b/lib/eventlog/regress/parse_json/test3.out.ok
new file mode 100644
index 0000000..ea2df89
--- /dev/null
+++ b/lib/eventlog/regress/parse_json/test3.out.ok
@@ -0,0 +1,22 @@
+{
+ "true": false,
+ "false": true,
+ "number": 1234567890,
+ "null": null,
+ "string": "nonsense",
+ "scope": {
+ "a": "b",
+ "bah": null
+ },
+ "array1": [
+ "foo",
+ "bar",
+ [
+ 123,
+ null,
+ false,
+ "fizz",
+ "buzz"
+ ]
+ ]
+}
diff --git a/lib/fuzzstub/Makefile.in b/lib/fuzzstub/Makefile.in
new file mode 100644
index 0000000..8c472b5
--- /dev/null
+++ b/lib/fuzzstub/Makefile.in
@@ -0,0 +1,176 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+devdir = @devdir@
+scriptdir = $(top_srcdir)/scripts
+incdir = $(top_srcdir)/include
+
+# Compiler & tools to use
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+
+# C preprocessor flags
+CPPFLAGS = -I$(incdir) -I$(top_builddir) -I$(srcdir) -I$(top_srcdir) @CPPFLAGS@
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+
+# Flags to pass to the link stage
+LDFLAGS = @LDFLAGS@
+
+# Flags to pass to libtool
+LTFLAGS = @LT_STATIC@
+
+# Libraries
+LT_LIBS =
+LIBS = $(LT_LIBS)
+
+# Address sanitizer flags
+ASAN_CFLAGS = @ASAN_CFLAGS@
+ASAN_LDFLAGS = @ASAN_LDFLAGS@
+
+# PIE flags
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+
+# Stack smashing protection flags
+HARDENING_CFLAGS = @HARDENING_CFLAGS@
+HARDENING_LDFLAGS = @HARDENING_LDFLAGS@
+
+# cppcheck options, usually set in the top-level Makefile
+CPPCHECK_OPTS = -q --enable=warning,performance,portability --suppress=constStatement --suppress=compareBoolExpressionWithInt --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
+
+# splint options, usually set in the top-level Makefile
+SPLINT_OPTS = -D__restrict= -checks
+
+# PVS-studio options
+PVS_CFG = $(top_srcdir)/PVS-Studio.cfg
+PVS_IGNORE = 'V707,V011,V002,V536'
+PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
+
+# Set to non-empty for development mode
+DEVEL = @DEVEL@
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+LIBFUZZSTUB_OBJS = fuzzstub.lo
+
+IOBJS = $(LIBFUZZSTUB_OBJS:.lo=.i)
+
+POBJS = $(IOBJS:.i=.plog)
+
+all: libsudo_fuzzstub.la
+
+depend:
+ $(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
+ --builddir=$(abs_top_builddir) lib/fuzzstub/Makefile.in
+ cd $(top_builddir) && ./config.status --file lib/fuzzstub/Makefile
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file lib/fuzzstub/Makefile
+
+.SUFFIXES: .c .h .i .lo .plog
+
+.c.lo:
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.i:
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+
+.i.plog:
+ ifile=$<; rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $${ifile%i}c --i-file $< --output-file $@
+
+libsudo_fuzzstub.la: $(LIBFUZZSTUB_OBJS)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LIBFUZZSTUB_OBJS) $(LT_LIBS)
+
+pre-install:
+
+install:
+
+install-binaries:
+
+install-includes:
+
+install-doc:
+
+install-plugin:
+
+install-fuzzer:
+
+uninstall:
+
+splint:
+ splint $(SPLINT_OPTS) -I$(incdir) -I$(top_builddir) -I$(top_srcdir) $(srcdir)/*.c
+
+cppcheck:
+ cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) -I$(top_srcdir) $(srcdir)/*.c
+
+pvs-log-files: $(POBJS)
+
+pvs-studio: $(POBJS)
+ plog-converter $(PVS_LOG_OPTS) $(POBJS)
+
+fuzz:
+
+check-fuzzer:
+
+check: check-fuzzer
+
+check-verbose: check
+
+clean:
+ -$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f *.lo *.o *.la
+ -rm -f *.i *.plog stamp-* core *.core core.*
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile .libs
+
+clobber: distclean
+
+realclean: distclean
+ rm -f TAGS tags
+
+cleandir: realclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean
+
+# Autogenerated dependencies, do not modify
+fuzzstub.lo: $(srcdir)/fuzzstub.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/fuzzstub.c
+fuzzstub.i: $(srcdir)/fuzzstub.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fuzzstub.plog: fuzzstub.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/fuzzstub.c --i-file $< --output-file $@
diff --git a/lib/fuzzstub/fuzzstub.c b/lib/fuzzstub/fuzzstub.c
new file mode 100644
index 0000000..abe8e7f
--- /dev/null
+++ b/lib/fuzzstub/fuzzstub.c
@@ -0,0 +1,133 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/*
+ * Simple driver for fuzzers built for LLVM libfuzzer.
+ * This stub library allows fuzz targets to be built and run without
+ * libfuzzer. No actual fuzzing will occur but the provided inputs
+ * will be tested.
+ */
+int
+main(int argc, char *argv[])
+{
+ struct timespec start_time, stop_time;
+ size_t filesize, bufsize = 0;
+ ssize_t nread;
+ struct stat sb;
+ uint8_t *buf = NULL;
+ int fd, i, errors = 0;
+ int verbose = 0;
+ long ms;
+
+ /* Test provided input files. */
+ for (i = 1; i < argc; i++) {
+ const char *arg = argv[i];
+ if (*arg == '-') {
+ if (strncmp(arg, "-verbosity=", sizeof("-verbosity=") - 1) == 0) {
+ verbose = atoi(arg + sizeof("-verbosity=") - 1);
+ }
+ continue;
+ }
+ fd = open(arg, O_RDONLY);
+ if (fd == -1 || fstat(fd, &sb) != 0) {
+ fprintf(stderr, "open %s: %s\n", arg, strerror(errno));
+ if (fd != -1)
+ close(fd);
+ errors++;
+ continue;
+ }
+#ifndef __LP64__
+ if (sizeof(sb.st_size) > sizeof(size_t) && sb.st_size > SSIZE_MAX) {
+ errno = E2BIG;
+ fprintf(stderr, "%s: %s\n", arg, strerror(errno));
+ close(fd);
+ errors++;
+ continue;
+ }
+#endif
+ filesize = (size_t)sb.st_size;
+ if (bufsize < filesize) {
+ void *tmp = realloc(buf, filesize);
+ if (tmp == NULL) {
+ fprintf(stderr, "realloc: %s\n", strerror(errno));
+ close(fd);
+ errors++;
+ continue;
+ }
+ buf = tmp;
+ bufsize = filesize;
+ }
+ nread = read(fd, buf, filesize);
+ if ((size_t)nread != filesize) {
+ if (nread == -1)
+ fprintf(stderr, "read %s: %s\n", arg, strerror(errno));
+ else
+ fprintf(stderr, "read %s: short read\n", arg);
+ close(fd);
+ errors++;
+ continue;
+ }
+ close(fd);
+
+ /* NOTE: doesn't support LLVMFuzzerInitialize() (but we don't use it) */
+ if (verbose > 0) {
+ fprintf(stderr, "Running: %s\n", arg);
+ sudo_gettime_mono(&start_time);
+ }
+ LLVMFuzzerTestOneInput(buf, (size_t)nread);
+ if (verbose > 0) {
+ sudo_gettime_mono(&stop_time);
+ sudo_timespecsub(&stop_time, &start_time, &stop_time);
+ ms = (stop_time.tv_sec * 1000) + (stop_time.tv_nsec / 1000000);
+ fprintf(stderr, "Executed %s in %ld ms\n", arg, ms);
+ }
+ }
+ free(buf);
+
+ return errors;
+}
diff --git a/lib/iolog/Makefile.in b/lib/iolog/Makefile.in
new file mode 100644
index 0000000..75dc534
--- /dev/null
+++ b/lib/iolog/Makefile.in
@@ -0,0 +1,823 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2011-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+devdir = @devdir@
+incdir = $(top_srcdir)/include
+scriptdir = $(top_srcdir)/scripts
+cross_compiling = @CROSS_COMPILING@
+
+# Compiler & tools to use
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+SHA1SUM = @SHA1SUM@
+EGREP = @EGREP@
+SED = @SED@
+
+# Libraries
+LIBEVENTLOG = $(top_builddir)/lib/eventlog/libsudo_eventlog.la
+LIBFUZZSTUB = $(top_builddir)/lib/fuzzstub/libsudo_fuzzstub.la
+LIBUTIL = $(top_builddir)/lib/util/libsudo_util.la
+LT_LIBS = $(LIBUTIL)
+LIBS = @LIBS@ @ZLIB@ $(LT_LIBS)
+
+# C preprocessor flags
+CPPFLAGS = -I$(incdir) -I$(top_builddir) -I$(srcdir) @CPPFLAGS@
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+
+# Flags to pass to the link stage
+LDFLAGS = @LDFLAGS@
+
+# Flags to pass to libtool
+LTFLAGS = @LT_STATIC@
+
+# Address sanitizer flags
+ASAN_CFLAGS = @ASAN_CFLAGS@
+ASAN_LDFLAGS = @ASAN_LDFLAGS@
+
+# PIE flags
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+
+# Stack smashing protection flags
+HARDENING_CFLAGS = @HARDENING_CFLAGS@
+HARDENING_LDFLAGS = @HARDENING_LDFLAGS@
+
+# cppcheck options, usually set in the top-level Makefile
+CPPCHECK_OPTS = -q --enable=warning,performance,portability --suppress=constStatement --suppress=compareBoolExpressionWithInt --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
+
+# splint options, usually set in the top-level Makefile
+SPLINT_OPTS = -D__restrict= -checks
+
+# PVS-studio options
+PVS_CFG = $(top_srcdir)/PVS-Studio.cfg
+PVS_IGNORE = 'V707,V011,V002,V536'
+PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
+
+# Regression tests
+TEST_PROGS = check_iolog_filter check_iolog_mkpath check_iolog_path \
+ check_iolog_timing host_port_test
+TEST_LIBS = @LIBS@
+TEST_LDFLAGS = @LDFLAGS@
+TEST_VERBOSE =
+
+# Fuzzers
+LIB_FUZZING_ENGINE = @FUZZ_ENGINE@
+FUZZ_PROGS = fuzz_iolog_json fuzz_iolog_legacy fuzz_iolog_timing
+FUZZ_SEED_CORPUS = ${FUZZ_PROGS:=_seed_corpus.zip}
+FUZZ_LIBS = libsudo_iolog.la $(LIBEVENTLOG) $(LIB_FUZZING_ENGINE) $(LIBS)
+FUZZ_LDFLAGS = @LDFLAGS@
+FUZZ_MAX_LEN = 4096
+FUZZ_RUNS = 8192
+FUZZ_VERBOSE =
+
+# Set to non-empty for development mode
+DEVEL = @DEVEL@
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+LIBIOLOG_OBJS = host_port.lo hostcheck.lo iolog_clearerr.lo iolog_close.lo \
+ iolog_conf.lo iolog_eof.lo iolog_filter.lo iolog_flush.lo \
+ iolog_gets.lo iolog_json.lo iolog_legacy.lo iolog_loginfo.lo \
+ iolog_mkdirs.lo iolog_mkdtemp.lo iolog_mkpath.lo \
+ iolog_nextid.lo iolog_open.lo iolog_openat.lo iolog_path.lo \
+ iolog_read.lo iolog_seek.lo iolog_swapids.lo iolog_timing.lo \
+ iolog_util.lo iolog_write.lo
+
+IOBJS = $(LIBIOLOG_OBJS:.lo=.i)
+
+POBJS = $(IOBJS:.i=.plog)
+
+CHECK_IOLOG_MKPATH_OBJS = check_iolog_mkpath.lo
+
+CHECK_IOLOG_PATH_OBJS = check_iolog_path.lo
+
+CHECK_IOLOG_TIMING_OBJS = check_iolog_timing.lo
+
+CHECK_IOLOG_FILTER_OBJS = check_iolog_filter.lo
+
+HOST_PORT_TEST_OBJS = host_port_test.lo
+
+FUZZ_IOLOG_JSON_OBJS = fuzz_iolog_json.lo
+
+FUZZ_IOLOG_JSON_CORPUS = $(srcdir)/regress/corpus/seed/log_json/*.json
+
+FUZZ_IOLOG_LEGACY_OBJS = fuzz_iolog_legacy.lo
+
+FUZZ_IOLOG_LEGACY_CORPUS = $(srcdir)/regress/corpus/seed/log_legacy/*.log
+
+FUZZ_IOLOG_TIMING_OBJS = fuzz_iolog_timing.lo
+
+FUZZ_IOLOG_TIMING_CORPUS = $(srcdir)/regress/corpus/seed/timing/timing.*
+
+all: libsudo_iolog.la
+
+depend:
+ $(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
+ --builddir=$(abs_top_builddir) lib/iolog/Makefile.in
+ cd $(top_builddir) && ./config.status --file lib/iolog/Makefile
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file lib/iolog/Makefile
+
+.SUFFIXES: .c .h .i .lo .plog
+
+.c.lo:
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.i:
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+
+.i.plog:
+ ifile=$<; rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $${ifile%i}c --i-file $< --output-file $@
+
+libsudo_iolog.la: $(LIBIOLOG_OBJS) $(LT_LIBS)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LIBIOLOG_OBJS) $(LT_LIBS) @ZLIB@ @NET_LIBS@
+
+check_iolog_path: $(CHECK_IOLOG_PATH_OBJS) $(LIBUTIL) libsudo_iolog.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_PATH_OBJS) libsudo_iolog.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+check_iolog_mkpath: $(CHECK_IOLOG_MKPATH_OBJS) $(LIBUTIL) libsudo_iolog.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_MKPATH_OBJS) libsudo_iolog.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+check_iolog_timing: $(CHECK_IOLOG_TIMING_OBJS) $(LIBUTIL) libsudo_iolog.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_TIMING_OBJS) libsudo_iolog.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+check_iolog_filter: $(CHECK_IOLOG_FILTER_OBJS) $(LIBUTIL) libsudo_iolog.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_FILTER_OBJS) libsudo_iolog.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+host_port_test: $(HOST_PORT_TEST_OBJS) $(LIBUTIL) libsudo_iolog.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(HOST_PORT_TEST_OBJS) libsudo_iolog.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+fuzz_iolog_json: $(FUZZ_IOLOG_JSON_OBJS) $(LIBFUZZSTUB) $(LIBEVENTLOG) $(LIBUTIL) libsudo_iolog.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link @FUZZ_LD@ -o $@ $(FUZZ_IOLOG_JSON_OBJS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(FUZZ_LDFLAGS) $(FUZZ_LIBS)
+
+fuzz_iolog_legacy: $(FUZZ_IOLOG_LEGACY_OBJS) $(LIBFUZZSTUB) $(LIBEVENTLOG) $(LIBUTIL) libsudo_iolog.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link @FUZZ_LD@ -o $@ $(FUZZ_IOLOG_LEGACY_OBJS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(FUZZ_LDFLAGS) $(FUZZ_LIBS)
+
+fuzz_iolog_timing: $(FUZZ_IOLOG_TIMING_OBJS) $(LIBFUZZSTUB) $(LIBEVENTLOG) $(LIBUTIL) libsudo_iolog.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link @FUZZ_LD@ -o $@ $(FUZZ_IOLOG_TIMING_OBJS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(FUZZ_LDFLAGS) $(FUZZ_LIBS)
+
+fuzz_iolog_json_seed_corpus.zip:
+ tdir=fuzz_iolog_json.$$$$; \
+ mkdir $$tdir; \
+ for f in $(FUZZ_IOLOG_JSON_CORPUS); do \
+ cp $$f $$tdir/`$(SHA1SUM) $$f | $(SED) -e 's/^.*= *//' -e 's/ .*//'`; \
+ done; \
+ zip -j $@ $$tdir/*; \
+ rm -rf $$tdir
+
+run-fuzz_iolog_json: fuzz_iolog_json
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ umask 022; \
+ corpus=regress/corpus/iolog_json; \
+ mkdir -p $$corpus; \
+ for f in $(FUZZ_IOLOG_JSON_CORPUS); do \
+ cp $$f $$corpus; \
+ done; \
+ ./fuzz_iolog_json -dict=$(srcdir)/regress/fuzz/fuzz_iolog_json.dict -max_len=$(FUZZ_MAX_LEN) -runs=$(FUZZ_RUNS) $(FUZZ_VERBOSE) $$corpus
+
+fuzz_iolog_legacy_seed_corpus.zip:
+ tdir=fuzz_iolog_legacy.$$$$; \
+ mkdir $$tdir; \
+ for f in $(FUZZ_IOLOG_LEGACY_CORPUS); do \
+ cp $$f $$tdir/`$(SHA1SUM) $$f | $(SED) -e 's/^.*= *//' -e 's/ .*//'`; \
+ done; \
+ zip -j $@ $$tdir/*; \
+ rm -rf $$tdir
+
+run-fuzz_iolog_legacy: fuzz_iolog_legacy
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ umask 022; \
+ corpus=regress/corpus/iolog_legacy; \
+ mkdir -p $$corpus; \
+ for f in $(FUZZ_IOLOG_LEGACY_CORPUS); do \
+ cp $$f $$corpus; \
+ done; \
+ ./fuzz_iolog_legacy -dict=$(srcdir)/regress/fuzz/fuzz_iolog_legacy.dict -max_len=$(FUZZ_MAX_LEN) -runs=$(FUZZ_RUNS) $(FUZZ_VERBOSE) $$corpus
+
+fuzz_iolog_timing_seed_corpus.zip:
+ tdir=fuzz_iolog_timing.$$$$; \
+ mkdir $$tdir; \
+ for f in $(FUZZ_IOLOG_TIMING_CORPUS); do \
+ cp $$f $$tdir/`$(SHA1SUM) $$f | $(SED) -e 's/^.*= *//' -e 's/ .*//'`; \
+ done; \
+ zip -j $@ $$tdir/*; \
+ rm -rf $$tdir
+
+run-fuzz_iolog_timing: fuzz_iolog_timing
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ umask 022; \
+ corpus=regress/corpus/iolog_timing; \
+ mkdir -p $$corpus; \
+ for f in $(FUZZ_IOLOG_TIMING_CORPUS); do \
+ cp $$f $$corpus; \
+ done; \
+ ./fuzz_iolog_timing -dict=$(srcdir)/regress/fuzz/fuzz_iolog_timing.dict -max_len=$(FUZZ_MAX_LEN) -runs=$(FUZZ_RUNS) $(FUZZ_VERBOSE) $$corpus
+
+pre-install:
+
+install:
+
+install-binaries:
+
+install-includes:
+
+install-doc:
+
+install-plugin:
+
+install-fuzzer: $(FUZZ_PROGS) $(FUZZ_SEED_CORPUS)
+ @if test X"$(FUZZ_DESTDIR)" = X""; then \
+ echo "must set FUZZ_DESTDIR for install-fuzzer target"; \
+ else \
+ cp $(FUZZ_PROGS) $(FUZZ_SEED_CORPUS) $(FUZZ_DESTDIR); \
+ cp $(srcdir)/regress/fuzz/*.dict $(FUZZ_DESTDIR); \
+ fi
+
+uninstall:
+
+splint:
+ splint $(SPLINT_OPTS) -I$(incdir) -I$(top_builddir) $(srcdir)/*.c
+
+cppcheck:
+ cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) $(srcdir)/*.c
+
+pvs-log-files: $(POBJS)
+
+pvs-studio: $(POBJS)
+ plog-converter $(PVS_LOG_OPTS) $(POBJS)
+
+fuzz: run-fuzz_iolog_json run-fuzz_iolog_legacy run-fuzz_iolog_timing
+
+check-fuzzer: $(FUZZ_PROGS)
+ @if test X"$(cross_compiling)" != X"yes"; then \
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ echo "fuzz_iolog_legacy: verifying corpus"; \
+ ./fuzz_iolog_legacy $(FUZZ_VERBOSE) $(FUZZ_IOLOG_LEGACY_CORPUS); \
+ echo "fuzz_iolog_json: verifying corpus"; \
+ ./fuzz_iolog_json $(FUZZ_VERBOSE) $(FUZZ_IOLOG_JSON_CORPUS); \
+ echo "fuzz_iolog_timing: verifying corpus"; \
+ ./fuzz_iolog_timing $(FUZZ_VERBOSE) $(FUZZ_IOLOG_TIMING_CORPUS); \
+ fi
+
+check: $(TEST_PROGS) check-fuzzer
+ @if test X"$(cross_compiling)" != X"yes"; then \
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ rval=0; \
+ ./check_iolog_filter $(TEST_VERBOSE) $(srcdir)/regress/iolog_filter/test[1-9]* || rval=`expr $$rval + $$?`; \
+ ./check_iolog_path $(TEST_VERBOSE) $(srcdir)/regress/iolog_path/data || rval=`expr $$rval + $$?`; \
+ ./check_iolog_mkpath $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./check_iolog_timing $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./host_port_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ exit $$rval; \
+ fi
+
+check-verbose:
+ exec $(MAKE) $(MFLAGS) TEST_VERBOSE=-v FUZZ_VERBOSE=-verbosity=1 check
+
+clean:
+ -$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f $(TEST_PROGS) $(FUZZ_PROGS) \
+ *.lo *.o *.la
+ -rm -f *.i *.plog stamp-* core *.core core.* regress/*/*.out \
+ regress/*/*.err
+ -rm -rf regress/corpus/iolog_json regress/corpus/iolog_legacy \
+ regress/corpus/iolog_timing
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile .libs
+
+clobber: distclean
+
+realclean: distclean
+ rm -f TAGS tags
+
+cleandir: realclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean \
+ $(FUZZ_SEED_CORPUS) run-fuzz_iolog_json run-fuzz_iolog_legacy \
+ run-fuzz_iolog_timing
+
+# Autogenerated dependencies, do not modify
+check_iolog_filter.lo: $(srcdir)/regress/iolog_filter/check_iolog_filter.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/iolog_filter/check_iolog_filter.c
+check_iolog_filter.i: $(srcdir)/regress/iolog_filter/check_iolog_filter.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_iolog_filter.plog: check_iolog_filter.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/iolog_filter/check_iolog_filter.c --i-file $< --output-file $@
+check_iolog_mkpath.lo: $(srcdir)/regress/iolog_mkpath/check_iolog_mkpath.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/iolog_mkpath/check_iolog_mkpath.c
+check_iolog_mkpath.i: $(srcdir)/regress/iolog_mkpath/check_iolog_mkpath.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_iolog_mkpath.plog: check_iolog_mkpath.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/iolog_mkpath/check_iolog_mkpath.c --i-file $< --output-file $@
+check_iolog_path.lo: $(srcdir)/regress/iolog_path/check_iolog_path.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/iolog_path/check_iolog_path.c
+check_iolog_path.i: $(srcdir)/regress/iolog_path/check_iolog_path.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_iolog_path.plog: check_iolog_path.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/iolog_path/check_iolog_path.c --i-file $< --output-file $@
+check_iolog_timing.lo: $(srcdir)/regress/iolog_timing/check_iolog_timing.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/iolog_timing/check_iolog_timing.c
+check_iolog_timing.i: $(srcdir)/regress/iolog_timing/check_iolog_timing.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_iolog_timing.plog: check_iolog_timing.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/iolog_timing/check_iolog_timing.c --i-file $< --output-file $@
+fuzz_iolog_json.lo: $(srcdir)/regress/fuzz/fuzz_iolog_json.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/fuzz/fuzz_iolog_json.c
+fuzz_iolog_json.i: $(srcdir)/regress/fuzz/fuzz_iolog_json.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fuzz_iolog_json.plog: fuzz_iolog_json.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/fuzz/fuzz_iolog_json.c --i-file $< --output-file $@
+fuzz_iolog_legacy.lo: $(srcdir)/regress/fuzz/fuzz_iolog_legacy.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/fuzz/fuzz_iolog_legacy.c
+fuzz_iolog_legacy.i: $(srcdir)/regress/fuzz/fuzz_iolog_legacy.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fuzz_iolog_legacy.plog: fuzz_iolog_legacy.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/fuzz/fuzz_iolog_legacy.c --i-file $< --output-file $@
+fuzz_iolog_timing.lo: $(srcdir)/regress/fuzz/fuzz_iolog_timing.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/fuzz/fuzz_iolog_timing.c
+fuzz_iolog_timing.i: $(srcdir)/regress/fuzz/fuzz_iolog_timing.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fuzz_iolog_timing.plog: fuzz_iolog_timing.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/fuzz/fuzz_iolog_timing.c --i-file $< --output-file $@
+host_port.lo: $(srcdir)/host_port.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/host_port.c
+host_port.i: $(srcdir)/host_port.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+host_port.plog: host_port.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/host_port.c --i-file $< --output-file $@
+host_port_test.lo: $(srcdir)/regress/host_port/host_port_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/host_port/host_port_test.c
+host_port_test.i: $(srcdir)/regress/host_port/host_port_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+host_port_test.plog: host_port_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/host_port/host_port_test.c --i-file $< --output-file $@
+hostcheck.lo: $(srcdir)/hostcheck.c $(incdir)/compat/stdbool.h \
+ $(incdir)/hostcheck.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/hostcheck.c
+hostcheck.i: $(srcdir)/hostcheck.c $(incdir)/compat/stdbool.h \
+ $(incdir)/hostcheck.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+hostcheck.plog: hostcheck.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/hostcheck.c --i-file $< --output-file $@
+iolog_clearerr.lo: $(srcdir)/iolog_clearerr.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_clearerr.c
+iolog_clearerr.i: $(srcdir)/iolog_clearerr.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_clearerr.plog: iolog_clearerr.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_clearerr.c --i-file $< --output-file $@
+iolog_close.lo: $(srcdir)/iolog_close.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_close.c
+iolog_close.i: $(srcdir)/iolog_close.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_close.plog: iolog_close.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_close.c --i-file $< --output-file $@
+iolog_conf.lo: $(srcdir)/iolog_conf.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_conf.c
+iolog_conf.i: $(srcdir)/iolog_conf.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_conf.plog: iolog_conf.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_conf.c --i-file $< --output-file $@
+iolog_eof.lo: $(srcdir)/iolog_eof.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_eof.c
+iolog_eof.i: $(srcdir)/iolog_eof.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_eof.plog: iolog_eof.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_eof.c --i-file $< --output-file $@
+iolog_filter.lo: $(srcdir)/iolog_filter.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_filter.c
+iolog_filter.i: $(srcdir)/iolog_filter.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_filter.plog: iolog_filter.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_filter.c --i-file $< --output-file $@
+iolog_flush.lo: $(srcdir)/iolog_flush.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_flush.c
+iolog_flush.i: $(srcdir)/iolog_flush.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_flush.plog: iolog_flush.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_flush.c --i-file $< --output-file $@
+iolog_gets.lo: $(srcdir)/iolog_gets.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_gets.c
+iolog_gets.i: $(srcdir)/iolog_gets.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_gets.plog: iolog_gets.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_gets.c --i-file $< --output-file $@
+iolog_json.lo: $(srcdir)/iolog_json.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_queue.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_json.c
+iolog_json.i: $(srcdir)/iolog_json.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_queue.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_json.plog: iolog_json.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_json.c --i-file $< --output-file $@
+iolog_legacy.lo: $(srcdir)/iolog_legacy.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_legacy.c
+iolog_legacy.i: $(srcdir)/iolog_legacy.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_legacy.plog: iolog_legacy.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_legacy.c --i-file $< --output-file $@
+iolog_loginfo.lo: $(srcdir)/iolog_loginfo.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_json.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_loginfo.c
+iolog_loginfo.i: $(srcdir)/iolog_loginfo.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_json.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_loginfo.plog: iolog_loginfo.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_loginfo.c --i-file $< --output-file $@
+iolog_mkdirs.lo: $(srcdir)/iolog_mkdirs.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_mkdirs.c
+iolog_mkdirs.i: $(srcdir)/iolog_mkdirs.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_mkdirs.plog: iolog_mkdirs.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_mkdirs.c --i-file $< --output-file $@
+iolog_mkdtemp.lo: $(srcdir)/iolog_mkdtemp.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_mkdtemp.c
+iolog_mkdtemp.i: $(srcdir)/iolog_mkdtemp.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_mkdtemp.plog: iolog_mkdtemp.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_mkdtemp.c --i-file $< --output-file $@
+iolog_mkpath.lo: $(srcdir)/iolog_mkpath.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_mkpath.c
+iolog_mkpath.i: $(srcdir)/iolog_mkpath.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_mkpath.plog: iolog_mkpath.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_mkpath.c --i-file $< --output-file $@
+iolog_nextid.lo: $(srcdir)/iolog_nextid.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_nextid.c
+iolog_nextid.i: $(srcdir)/iolog_nextid.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_nextid.plog: iolog_nextid.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_nextid.c --i-file $< --output-file $@
+iolog_open.lo: $(srcdir)/iolog_open.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_open.c
+iolog_open.i: $(srcdir)/iolog_open.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_open.plog: iolog_open.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_open.c --i-file $< --output-file $@
+iolog_openat.lo: $(srcdir)/iolog_openat.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_openat.c
+iolog_openat.i: $(srcdir)/iolog_openat.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_openat.plog: iolog_openat.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_openat.c --i-file $< --output-file $@
+iolog_path.lo: $(srcdir)/iolog_path.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_path.c
+iolog_path.i: $(srcdir)/iolog_path.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_path.plog: iolog_path.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_path.c --i-file $< --output-file $@
+iolog_read.lo: $(srcdir)/iolog_read.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_read.c
+iolog_read.i: $(srcdir)/iolog_read.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_read.plog: iolog_read.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_read.c --i-file $< --output-file $@
+iolog_seek.lo: $(srcdir)/iolog_seek.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_seek.c
+iolog_seek.i: $(srcdir)/iolog_seek.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_seek.plog: iolog_seek.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_seek.c --i-file $< --output-file $@
+iolog_swapids.lo: $(srcdir)/iolog_swapids.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_swapids.c
+iolog_swapids.i: $(srcdir)/iolog_swapids.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_swapids.plog: iolog_swapids.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_swapids.c --i-file $< --output-file $@
+iolog_timing.lo: $(srcdir)/iolog_timing.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_timing.c
+iolog_timing.i: $(srcdir)/iolog_timing.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_timing.plog: iolog_timing.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_timing.c --i-file $< --output-file $@
+iolog_util.lo: $(srcdir)/iolog_util.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_util.c
+iolog_util.i: $(srcdir)/iolog_util.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_util.plog: iolog_util.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_util.c --i-file $< --output-file $@
+iolog_write.lo: $(srcdir)/iolog_write.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_write.c
+iolog_write.i: $(srcdir)/iolog_write.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_write.plog: iolog_write.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_write.c --i-file $< --output-file $@
diff --git a/lib/iolog/host_port.c b/lib/iolog/host_port.c
new file mode 100644
index 0000000..615dade
--- /dev/null
+++ b/lib/iolog/host_port.c
@@ -0,0 +1,109 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_gettext.h>
+#include <sudo_util.h>
+#include <sudo_iolog.h>
+
+/*
+ * Parse a string in the form host[:port] where host can also be
+ * an IPv4 address or an IPv6 address in square brackets.
+ * Fills in hostp and portp which may point within str, which is modified.
+ */
+bool
+iolog_parse_host_port(char *str, char **hostp, char **portp, bool *tlsp,
+ const char *defport, const char *defport_tls)
+{
+ char *flags, *port, *host = str;
+ bool ret = false;
+ bool tls = false;
+ debug_decl(iolog_parse_host_port, SUDO_DEBUG_UTIL);
+
+ /* Check for IPv6 address like [::0] followed by optional port */
+ if (*host == '[') {
+ host++;
+ port = strchr(host, ']');
+ if (port == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "invalid IPv6 address %s", str);
+ goto done;
+ }
+ *port++ = '\0';
+ switch (*port) {
+ case ':':
+ port++;
+ break;
+ case '\0':
+ port = NULL; /* no port specified */
+ break;
+ case '(':
+ /* flag, handled below */
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "invalid IPv6 address %s", str);
+ goto done;
+ }
+ } else {
+ port = strrchr(host, ':');
+ if (port != NULL)
+ *port++ = '\0';
+ }
+
+ /* Check for optional tls flag at the end. */
+ flags = strchr(port ? port : host, '(');
+ if (flags != NULL) {
+ if (strcasecmp(flags, "(tls)") == 0)
+ tls = true;
+ *flags = '\0';
+ if (port == flags)
+ port = NULL;
+ }
+
+ if (port == NULL)
+ port = tls ? (char *)defport_tls : (char *)defport;
+ else if (*port == '\0')
+ goto done;
+
+ *hostp = host;
+ *portp = port;
+ *tlsp = tls;
+
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
diff --git a/lib/iolog/hostcheck.c b/lib/iolog/hostcheck.c
new file mode 100644
index 0000000..efb016c
--- /dev/null
+++ b/lib/iolog/hostcheck.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2020 Laszlo Orban <laszlo.orban@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#if defined(HAVE_OPENSSL)
+# if defined(HAVE_WOLFSSL)
+# include <wolfssl/options.h>
+# endif
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <stdlib.h>
+# include <string.h>
+# include <netdb.h>
+
+# define NEED_INET_NTOP /* to expose sudo_inet_ntop in sudo_compat.h */
+
+# include <sudo_compat.h>
+# include <sudo_debug.h>
+# include <sudo_util.h>
+# include <hostcheck.h>
+
+#ifndef INET_ADDRSTRLEN
+# define INET_ADDRSTRLEN 16
+#endif
+#ifndef INET6_ADDRSTRLEN
+# define INET6_ADDRSTRLEN 46
+#endif
+
+#if !defined(HAVE_ASN1_STRING_GET0_DATA) && !defined(HAVE_WOLFSSL)
+# define ASN1_STRING_get0_data(x) ASN1_STRING_data(x)
+#endif /* !HAVE_ASN1_STRING_GET0_DATA && !HAVE_WOLFSSL */
+
+/**
+ * @brief Checks if given hostname resolves to the given IP address.
+ *
+ * @param hostname hostname to be resolved
+ * @param ipaddr ip address to be checked
+ *
+ * @return 1 if hostname resolves to the given IP address
+ * 0 otherwise
+ */
+static int
+forward_lookup_match(const char *hostname, const char *ipaddr)
+{
+ int rc, ret = 0;
+ struct addrinfo *res = NULL, *p;
+ void *addr;
+ struct sockaddr_in *ipv4;
+#if defined(HAVE_STRUCT_IN6_ADDR)
+ struct sockaddr_in6 *ipv6;
+ char ipstr[INET6_ADDRSTRLEN];
+#else
+ char ipstr[INET_ADDRSTRLEN];
+#endif
+ debug_decl(forward_lookup_match, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "verify %s resolves to %s", hostname, ipaddr);
+
+ if ((rc = getaddrinfo(hostname, NULL, NULL, &res)) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to resolve %s: %s", hostname, gai_strerror(rc));
+ goto exit;
+ }
+
+ for (p = res; p != NULL; p = p->ai_next) {
+ if (p->ai_family == AF_INET) {
+ ipv4 = (struct sockaddr_in *)p->ai_addr;
+ addr = &(ipv4->sin_addr);
+#if defined(HAVE_STRUCT_IN6_ADDR)
+ } else if (p->ai_family == AF_INET6) {
+ ipv6 = (struct sockaddr_in6 *)p->ai_addr;
+ addr = &(ipv6->sin6_addr);
+#endif
+ } else {
+ goto exit;
+ }
+
+ if (inet_ntop(p->ai_family, addr, ipstr, sizeof(ipstr)) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "comparing %s to %s", ipstr, ipaddr);
+ if (strcmp(ipaddr, ipstr) == 0) {
+ ret = 1;
+ break;
+ }
+ }
+ }
+
+exit:
+ if (res != NULL) {
+ freeaddrinfo(res);
+ }
+ debug_return_int(ret);
+}
+
+/**
+ * @brief Compares the given hostname with a DNS entry in a certificate.
+ *
+ * The certificate DNS name can contain wildcards in the left-most label.
+ * A wildcard can match only one label.
+ * Accepted names:
+ * - foo.bar.example.com
+ * - *.example.com
+ * - *.bar.example.com
+ *
+ * @param hostname peer's name
+ * @param certname_asn1 hostname in the certificate
+ *
+ * @return MatchFound
+ * MatchNotFound
+ */
+static HostnameValidationResult
+validate_name(const char *hostname, ASN1_STRING *certname_asn1)
+{
+ char *certname_s = (char *)ASN1_STRING_get0_data(certname_asn1);
+ size_t certname_len = (size_t)ASN1_STRING_length(certname_asn1);
+ size_t hostname_len = strlen(hostname);
+ debug_decl(validate_name, SUDO_DEBUG_UTIL);
+
+ /* remove last '.' from hostname if exists */
+ if (hostname_len != 0 && hostname[hostname_len - 1] == '.') {
+ --hostname_len;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "comparing %.*s to %.*s in cert", (int)hostname_len, hostname,
+ (int)certname_len, certname_s);
+
+ /* skip the first label if wildcard */
+ if (certname_len > 2 && certname_s[0] == '*' && certname_s[1] == '.') {
+ while (hostname_len != 0) {
+ --hostname_len;
+ if (*hostname++ == '.') {
+ break;
+ }
+ }
+ certname_s += 2;
+ certname_len -= 2;
+ }
+ /* Compare expected hostname with the DNS name */
+ if (certname_len != hostname_len) {
+ debug_return_int(MatchNotFound);
+ }
+ if (strncasecmp(hostname, certname_s, hostname_len) != 0) {
+ debug_return_int(MatchNotFound);
+ }
+
+ debug_return_int(MatchFound);
+}
+
+/**
+ * @brief Matches a hostname with the cert's CN.
+ *
+ * @param hostname peer's name
+ * on client side: it is the name where the client is connected to
+ * on server side, it is in fact an IP address of the remote client
+ * @param ipaddr peer's IP address
+ * @param cert peer's X509 certificate
+ * @param resolve if the value is not 0, the function checks that the value of the CN
+ * resolves to the given ipaddr or not.
+ *
+ * @return MatchFound
+ * MatchNotFound
+ * MalformedCertificate
+ * Error
+ */
+static HostnameValidationResult
+matches_common_name(const char *hostname, const char *ipaddr, const X509 *cert, int resolve)
+{
+ X509_NAME_ENTRY *common_name_entry = NULL;
+ ASN1_STRING *common_name_asn1 = NULL;
+ int common_name_loc;
+ debug_decl(matches_common_name, SUDO_DEBUG_UTIL);
+
+ /* Find the position of the CN field in the Subject field of the certificate */
+ common_name_loc = X509_NAME_get_index_by_NID(X509_get_subject_name((X509 *) cert), NID_commonName, -1);
+ if (common_name_loc < 0) {
+ debug_return_int(Error);
+ }
+
+ /* Extract the CN field */
+ common_name_entry = X509_NAME_get_entry(X509_get_subject_name((X509 *) cert), common_name_loc);
+ if (common_name_entry == NULL) {
+ debug_return_int(Error);
+ }
+
+ /* Convert the CN field to a C string */
+ common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
+ if (common_name_asn1 == NULL) {
+ debug_return_int(Error);
+ }
+ const unsigned char *common_name_str = ASN1_STRING_get0_data(common_name_asn1);
+ const size_t common_name_length = (size_t)ASN1_STRING_length(common_name_asn1);
+
+ /* Make sure there isn't an embedded NUL character in the CN */
+ if (memchr(common_name_str, '\0', common_name_length) != NULL) {
+ debug_return_int(MalformedCertificate);
+ }
+
+ /* Compare expected hostname with the CN */
+ if (validate_name(hostname, common_name_asn1) == MatchFound) {
+ debug_return_int(MatchFound);
+ }
+
+ char *nullterm_common_name = malloc(common_name_length + 1);
+ if (nullterm_common_name == NULL) {
+ debug_return_int(Error);
+ }
+
+ memcpy(nullterm_common_name, common_name_str, common_name_length);
+ nullterm_common_name[common_name_length] = '\0';
+
+
+ /* check if hostname in the CN field resolves to the given ip address */
+ if (resolve && forward_lookup_match(nullterm_common_name, ipaddr)) {
+ free(nullterm_common_name);
+ debug_return_int(MatchFound);
+ }
+
+ free(nullterm_common_name);
+ debug_return_int(MatchNotFound);
+}
+
+/**
+ * @brief Matches a hostname or ipaddr with the cert's corresponding SAN field.
+ *
+ * SAN can have different fields. For hostname matching, the GEN_DNS field is used,
+ * for IP address matching, the GEN_IPADD field is used.
+ * Since SAN is an X503 v3 extension, it can happen that the cert does
+ * not contain SAN at all.
+ *
+ * @param hostname remote peer's name
+ * on client side: it is the name where the client is connected to
+ * on server side, it is in fact an IP address of the remote client
+ * @param ipaddr remote peer's IP address
+ * @param cert peer's X509 certificate
+ * @param resolve if the value is not 0, the function checks that the value of the
+ * SAN GEN_DNS resolves to the given ipaddr or not.
+ *
+ * @return MatchFound
+ * MatchNotFound
+ * NoSANPresent
+ * MalformedCertificate
+ * Error
+ */
+static HostnameValidationResult
+matches_subject_alternative_name(const char *hostname, const char *ipaddr, const X509 *cert, int resolve)
+{
+ HostnameValidationResult result = MatchNotFound;
+ int i;
+ int san_names_nb;
+ STACK_OF(GENERAL_NAME) *san_names = NULL;
+ debug_decl(matches_subject_alternative_name, SUDO_DEBUG_UTIL);
+
+ /* Try to extract the names within the SAN extension from the certificate */
+ san_names = X509_get_ext_d2i((X509 *) cert, NID_subject_alt_name, NULL, NULL);
+ if (san_names == NULL) {
+ debug_return_int(NoSANPresent);
+ }
+ san_names_nb = sk_GENERAL_NAME_num(san_names);
+
+ /* Check each name within the extension */
+ for (i=0; i<san_names_nb; i++) {
+ const GENERAL_NAME *current_name = sk_GENERAL_NAME_value(san_names, i);
+
+ if (current_name->type == GEN_DNS) {
+ const unsigned char *dns_name = ASN1_STRING_get0_data(current_name->d.dNSName);
+ const size_t dns_name_length = (size_t)ASN1_STRING_length(current_name->d.dNSName);
+
+ /* Make sure there isn't an embedded NUL character in the DNS name */
+ if (memchr(dns_name, '\0', dns_name_length) != NULL) {
+ result = MalformedCertificate;
+ break;
+ } else {
+ /* Compare expected hostname with the DNS name */
+ if (validate_name(hostname, current_name->d.dNSName) == MatchFound) {
+ result = MatchFound;
+ break;
+ }
+
+ char *nullterm_dns_name = malloc(dns_name_length + 1);
+ if (nullterm_dns_name == NULL) {
+ debug_return_int(Error);
+ }
+
+ memcpy(nullterm_dns_name, dns_name, dns_name_length);
+ nullterm_dns_name[dns_name_length] = '\0';
+
+ if (resolve && forward_lookup_match(nullterm_dns_name, ipaddr)) {
+ free(nullterm_dns_name);
+ result = MatchFound;
+ break;
+ }
+ free(nullterm_dns_name);
+ }
+ } else if (current_name->type == GEN_IPADD) {
+ const unsigned char *san_ip = ASN1_STRING_get0_data(current_name->d.iPAddress);
+#if defined(HAVE_STRUCT_IN6_ADDR)
+ char san_ip_str[INET6_ADDRSTRLEN];
+#else
+ char san_ip_str[INET_ADDRSTRLEN];
+#endif
+
+ /* IPV4 address */
+ if(current_name->d.iPAddress->length == 4) {
+ if (inet_ntop(AF_INET, san_ip, san_ip_str, INET_ADDRSTRLEN) == NULL) {
+ result = MalformedCertificate;
+ break;
+ }
+#if defined(HAVE_STRUCT_IN6_ADDR)
+ /* IPV6 address */
+ } else if (current_name->d.iPAddress->length == 16) {
+ if (inet_ntop(AF_INET6, san_ip, san_ip_str, INET6_ADDRSTRLEN) == NULL) {
+ result = MalformedCertificate;
+ break;
+ }
+# endif
+ } else {
+ result = MalformedCertificate;
+ break;
+ }
+
+ if (strcasecmp(ipaddr, san_ip_str) == 0) {
+ result = MatchFound;
+ break;
+ }
+ }
+ }
+ sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free);
+
+ debug_return_int(result);
+}
+
+/**
+ * @brief Do hostname/IP validation on the given X509 certificate.
+ *
+ * According to RFC 6125 section 6.4.4, first the certificate's SAN field
+ * has to be checked. If there is no SAN field, the certificate's CN field
+ * has to be checked.
+ *
+ * @param cert X509 certificate
+ * @param hostname remote peer's name
+ * on client side: it is the name where the client is connected to
+ * on server side, it is in fact an IP address of the remote client
+ * @param ipaddr remote peer's IP address
+ * @param resolve if the value is not 0, the function checks that the value of the
+ * SAN GEN_DNS or the value of CN resolves to the given ipaddr or not.
+ *
+ * @return MatchFound
+ * MatchNotFound
+ * MalformedCertificate
+ * Error
+ */
+HostnameValidationResult
+validate_hostname(const X509 *cert, const char *hostname, const char *ipaddr, int resolve)
+{
+ HostnameValidationResult res = MatchFound;
+ debug_decl(validate_hostname, SUDO_DEBUG_UTIL);
+
+ /* hostname can be also an ip address, if client connects
+ * to ip instead of FQDN
+ */
+ if((ipaddr == NULL) || (cert == NULL)) {
+ debug_return_int(Error);
+ }
+
+ /* check SAN first if exists */
+ res = matches_subject_alternative_name(hostname, ipaddr, cert, resolve);
+
+ /* According to RFC 6125 section 6.4.4, check CN only,
+ * if no SAN name was provided
+ */
+ if (res == NoSANPresent) {
+ res = matches_common_name(hostname, ipaddr, cert, resolve);
+ }
+
+ debug_return_int(res);
+}
+#endif /* HAVE_OPENSSL */
diff --git a/lib/iolog/iolog_clearerr.c b/lib/iolog/iolog_clearerr.c
new file mode 100644
index 0000000..44a9b34
--- /dev/null
+++ b/lib/iolog/iolog_clearerr.c
@@ -0,0 +1,45 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_iolog.h>
+
+void
+iolog_clearerr(struct iolog_file *iol)
+{
+ debug_decl(iolog_eof, SUDO_DEBUG_UTIL);
+
+#ifdef HAVE_ZLIB_H
+ if (iol->compressed)
+ gzclearerr(iol->fd.g);
+ else
+#endif
+ clearerr(iol->fd.f);
+ debug_return;
+}
diff --git a/lib/iolog/iolog_close.c b/lib/iolog/iolog_close.c
new file mode 100644
index 0000000..29add54
--- /dev/null
+++ b/lib/iolog/iolog_close.c
@@ -0,0 +1,80 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_iolog.h>
+
+/*
+ * Close an I/O log.
+ */
+bool
+iolog_close(struct iolog_file *iol, const char **errstr)
+{
+ bool ret = true;
+ debug_decl(iolog_close, SUDO_DEBUG_UTIL);
+
+#ifdef HAVE_ZLIB_H
+ if (iol->compressed) {
+ int errnum;
+
+ /* Must check error indicator before closing. */
+ if (iol->writable) {
+ if (gzflush(iol->fd.g, Z_SYNC_FLUSH) != Z_OK) {
+ ret = false;
+ if (errstr != NULL) {
+ *errstr = gzerror(iol->fd.g, &errnum);
+ if (errnum == Z_ERRNO)
+ *errstr = strerror(errno);
+ }
+ }
+ }
+ errnum = gzclose(iol->fd.g);
+ if (ret && errnum != Z_OK) {
+ ret = false;
+ if (errstr != NULL)
+ *errstr = errnum == Z_ERRNO ? strerror(errno) : "unknown error";
+ }
+ } else
+#endif
+ if (fclose(iol->fd.f) != 0) {
+ ret = false;
+ if (errstr != NULL)
+ *errstr = strerror(errno);
+ }
+
+ debug_return_bool(ret);
+}
diff --git a/lib/iolog/iolog_conf.c b/lib/iolog/iolog_conf.c
new file mode 100644
index 0000000..1921b8f
--- /dev/null
+++ b/lib/iolog/iolog_conf.c
@@ -0,0 +1,202 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+
+#include <pathnames.h>
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+#include <sudo_iolog.h>
+
+static unsigned int sessid_max = SESSID_MAX;
+static mode_t iolog_filemode = S_IRUSR|S_IWUSR;
+static mode_t iolog_dirmode = S_IRWXU;
+static uid_t iolog_uid = ROOT_UID;
+static gid_t iolog_gid = ROOT_GID;
+static bool iolog_gid_set;
+static bool iolog_docompress;
+static bool iolog_doflush;
+
+/*
+ * Reset I/O log settings to default values.
+ */
+void
+iolog_set_defaults(void)
+{
+ sessid_max = SESSID_MAX;
+ iolog_filemode = S_IRUSR|S_IWUSR;
+ iolog_dirmode = S_IRWXU;
+ iolog_uid = ROOT_UID;
+ iolog_gid = ROOT_GID;
+ iolog_gid_set = false;
+ iolog_docompress = false;
+ iolog_doflush = false;
+}
+
+/*
+ * Set max sequence number (aka session ID)
+ */
+void
+iolog_set_maxseq(unsigned int newval)
+{
+ debug_decl(iolog_set_maxseq, SUDO_DEBUG_UTIL);
+
+ /* Clamp to SESSID_MAX as documented. */
+ if (newval > SESSID_MAX)
+ newval = SESSID_MAX;
+ sessid_max = newval;
+
+ debug_return;
+}
+
+/*
+ * Set iolog_uid (and iolog_gid if gid not explicitly set).
+ */
+void
+iolog_set_owner(uid_t uid, gid_t gid)
+{
+ debug_decl(iolog_set_owner, SUDO_DEBUG_UTIL);
+
+ iolog_uid = uid;
+ if (!iolog_gid_set)
+ iolog_gid = gid;
+
+ debug_return;
+}
+
+/*
+ * Set iolog_gid.
+ */
+void
+iolog_set_gid(gid_t gid)
+{
+ debug_decl(iolog_set_gid, SUDO_DEBUG_UTIL);
+
+ iolog_gid = gid;
+ iolog_gid_set = true;
+
+ debug_return;
+}
+
+/*
+ * Set iolog_filemode and iolog_dirmode.
+ */
+void
+iolog_set_mode(mode_t mode)
+{
+ debug_decl(iolog_set_mode, SUDO_DEBUG_UTIL);
+
+ /* I/O log files must be readable and writable by owner. */
+ iolog_filemode = S_IRUSR|S_IWUSR;
+
+ /* Add in group and other read/write if specified. */
+ iolog_filemode |= mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+
+ /* For directory mode, add execute bits as needed. */
+ iolog_dirmode = iolog_filemode | S_IXUSR;
+ if (iolog_dirmode & (S_IRGRP|S_IWGRP))
+ iolog_dirmode |= S_IXGRP;
+ if (iolog_dirmode & (S_IROTH|S_IWOTH))
+ iolog_dirmode |= S_IXOTH;
+
+ debug_return;
+}
+
+/*
+ * Set iolog_docompress
+ */
+void
+iolog_set_compress(bool newval)
+{
+ debug_decl(iolog_set_compress, SUDO_DEBUG_UTIL);
+ iolog_docompress = newval;
+ debug_return;
+}
+
+/*
+ * Set iolog_doflush
+ */
+void
+iolog_set_flush(bool newval)
+{
+ debug_decl(iolog_set_flush, SUDO_DEBUG_UTIL);
+ iolog_doflush = newval;
+ debug_return;
+}
+
+/*
+ * Getters.
+ */
+
+unsigned int
+iolog_get_maxseq(void)
+{
+ return sessid_max;
+}
+
+uid_t
+iolog_get_uid(void)
+{
+ return iolog_uid;
+}
+
+gid_t
+iolog_get_gid(void)
+{
+ return iolog_gid;
+}
+
+mode_t
+iolog_get_file_mode(void)
+{
+ return iolog_filemode;
+}
+
+mode_t
+iolog_get_dir_mode(void)
+{
+ return iolog_dirmode;
+}
+
+bool
+iolog_get_compress(void)
+{
+ return iolog_docompress;
+}
+
+bool
+iolog_get_flush(void)
+{
+ return iolog_doflush;
+}
diff --git a/lib/iolog/iolog_eof.c b/lib/iolog/iolog_eof.c
new file mode 100644
index 0000000..4f4eb05
--- /dev/null
+++ b/lib/iolog/iolog_eof.c
@@ -0,0 +1,54 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_iolog.h>
+
+/*
+ * Returns true if at end of I/O log file, else false.
+ */
+bool
+iolog_eof(struct iolog_file *iol)
+{
+ bool ret;
+ debug_decl(iolog_eof, SUDO_DEBUG_UTIL);
+
+#ifdef HAVE_ZLIB_H
+ if (iol->compressed)
+ ret = gzeof(iol->fd.g) != 0;
+ else
+#endif
+ ret = feof(iol->fd.f) != 0;
+ debug_return_int(ret);
+}
diff --git a/lib/iolog/iolog_filter.c b/lib/iolog/iolog_filter.c
new file mode 100644
index 0000000..e78f2ae
--- /dev/null
+++ b/lib/iolog/iolog_filter.c
@@ -0,0 +1,248 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <regex.h>
+#include <string.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_iolog.h>
+#include <sudo_queue.h>
+#include <sudo_util.h>
+
+struct pwfilt_regex {
+ TAILQ_ENTRY(pwfilt_regex) entries;
+ char *pattern;
+ regex_t regex;
+};
+TAILQ_HEAD(pwfilt_regex_list, pwfilt_regex);
+
+struct pwfilt_handle {
+ struct pwfilt_regex_list filters;
+ bool is_filtered;
+};
+
+/*
+ * Allocate a new filter handle.
+ */
+void *
+iolog_pwfilt_alloc(void)
+{
+ struct pwfilt_handle *handle;
+ debug_decl(iolog_pwfilt_alloc, SUDO_DEBUG_UTIL);
+
+ handle = malloc(sizeof(*handle));
+ if (handle != NULL) {
+ TAILQ_INIT(&handle->filters);
+ handle->is_filtered = false;
+ }
+
+ debug_return_ptr(handle);
+}
+
+/*
+ * Unlink filt from filters and free it.
+ */
+static void
+iolog_pwfilt_free_filter(struct pwfilt_regex_list *filters,
+ struct pwfilt_regex *filt)
+{
+ debug_decl(iolog_pwfilt_free_filter, SUDO_DEBUG_UTIL);
+
+ if (filt != NULL) {
+ TAILQ_REMOVE(filters, filt, entries);
+ regfree(&filt->regex);
+ free(filt->pattern);
+ free(filt);
+ }
+
+ debug_return;
+}
+
+/*
+ * Free the given password filter handle.
+ */
+void
+iolog_pwfilt_free(void *vhandle)
+{
+ struct pwfilt_handle *handle = vhandle;
+ struct pwfilt_regex *filt;
+ debug_decl(iolog_pwfilt_free, SUDO_DEBUG_UTIL);
+
+ if (handle != NULL) {
+ while ((filt = TAILQ_FIRST(&handle->filters)) != NULL) {
+ iolog_pwfilt_free_filter(&handle->filters, filt);
+ }
+ free(handle);
+ }
+ debug_return;
+}
+
+/*
+ * Add a pattern to the password filter list.
+ */
+bool
+iolog_pwfilt_add(void *vhandle, const char *pattern)
+{
+ struct pwfilt_handle *handle = vhandle;
+ struct pwfilt_regex *filt;
+ const char *errstr;
+ debug_decl(iolog_pwfilt_add, SUDO_DEBUG_UTIL);
+
+ filt = malloc(sizeof(*filt));
+ if (filt == NULL)
+ goto oom;
+ filt->pattern = strdup(pattern);
+ if (filt->pattern == NULL)
+ goto oom;
+
+ if (!sudo_regex_compile(&filt->regex, filt->pattern, &errstr)) {
+ sudo_warnx(U_("invalid regular expression \"%s\": %s"),
+ pattern, U_(errstr));
+ goto bad;
+ }
+
+ TAILQ_INSERT_TAIL(&handle->filters, filt, entries);
+ debug_return_bool(true);
+
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+bad:
+ if (filt != NULL) {
+ free(filt->pattern);
+ free(filt);
+ }
+ debug_return_bool(false);
+}
+
+/*
+ * Remove a pattern from the password filter list.
+ */
+bool
+iolog_pwfilt_remove(void *vhandle, const char *pattern)
+{
+ struct pwfilt_handle *handle = vhandle;
+ struct pwfilt_regex *filt, *next;
+ bool ret = false;
+ debug_decl(iolog_pwfilt_remove, SUDO_DEBUG_UTIL);
+
+ TAILQ_FOREACH_SAFE(filt, &handle->filters, entries, next) {
+ if (strcmp(filt->pattern, pattern) == 0) {
+ iolog_pwfilt_free_filter(&handle->filters, filt);
+ ret = true;
+ }
+ }
+ debug_return_bool(ret);
+}
+
+/*
+ * If logging output and filtering is _not_ enabled, match buf against the
+ * password filter list patterns and, if there is a match, enable filtering.
+ * If logging output and filtering _is_ enabled, disable filtering.
+ * If logging input and filtering is enabled, replace all characters in
+ * buf with stars ('*') up to the next linefeed or carriage return.
+ */
+bool
+iolog_pwfilt_run(void *vhandle, int event, const char *buf,
+ size_t len, char **newbuf)
+{
+ struct pwfilt_handle *handle = vhandle;
+ struct pwfilt_regex *filt;
+ char *copy;
+ debug_decl(iolog_pwfilt_run, SUDO_DEBUG_UTIL);
+
+ /*
+ * We only filter ttyin/ttyout. It is only possible to disable
+ * echo when a tty is present. Filtering passwords in the input
+ * log when they appear in the output is pointless. This does
+ * assume that the password prompt is written to the tty as well.
+ */
+ switch (event) {
+ case IO_EVENT_TTYOUT:
+ /* If filtering passwords and we receive output, disable it. */
+ if (handle->is_filtered)
+ handle->is_filtered = false;
+
+ /* Make a copy of buf that is NUL-terminated. */
+ copy = malloc(len + 1);
+ if (copy == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ memcpy(copy, buf, len);
+ copy[len] = '\0';
+
+ /* Check output for a password prompt. */
+ TAILQ_FOREACH(filt, &handle->filters, entries) {
+ if (regexec(&filt->regex, copy, 0, NULL, 0) == 0) {
+ handle->is_filtered = true;
+ break;
+ }
+ }
+ free(copy);
+ break;
+ case IO_EVENT_TTYIN:
+ if (handle->is_filtered) {
+ unsigned int i;
+
+ for (i = 0; i < len; i++) {
+ /* We will stop filtering after reaching cr/nl. */
+ if (buf[i] == '\r' || buf[i] == '\n') {
+ handle->is_filtered = false;
+ break;
+ }
+ }
+ if (i != 0) {
+ /* Filtered, replace buffer with '*' chars. */
+ copy = malloc(len);
+ if (copy == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ memset(copy, '*', i);
+ if (i != len) {
+ /* Done filtering, copy cr/nl and subsequent characters. */
+ memcpy(copy + i, buf + i, len - i);
+ }
+ *newbuf = copy;
+ }
+ }
+ break;
+ }
+
+ debug_return_bool(true);
+}
diff --git a/lib/iolog/iolog_flush.c b/lib/iolog/iolog_flush.c
new file mode 100644
index 0000000..9104473
--- /dev/null
+++ b/lib/iolog/iolog_flush.c
@@ -0,0 +1,66 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_iolog.h>
+
+/*
+ * I/O log wrapper for fflush/gzflush.
+ */
+bool
+iolog_flush(struct iolog_file *iol, const char **errstr)
+{
+ debug_decl(iolog_flush, SUDO_DEBUG_UTIL);
+ bool ret = true;
+
+#ifdef HAVE_ZLIB_H
+ if (iol->compressed) {
+ int errnum;
+ if (gzflush(iol->fd.g, Z_SYNC_FLUSH) != Z_OK) {
+ if (errstr != NULL) {
+ *errstr = gzerror(iol->fd.g, &errnum);
+ if (errnum == Z_ERRNO)
+ *errstr = strerror(errno);
+ }
+ ret = false;
+ }
+ } else
+#endif
+ {
+ if (fflush(iol->fd.f) != 0) {
+ if (errstr != NULL)
+ *errstr = strerror(errno);
+ ret = false;
+ }
+ }
+
+ debug_return_bool(ret);
+}
diff --git a/lib/iolog/iolog_gets.c b/lib/iolog/iolog_gets.c
new file mode 100644
index 0000000..f60c3b0
--- /dev/null
+++ b/lib/iolog/iolog_gets.c
@@ -0,0 +1,78 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_iolog.h>
+
+/*
+ * Like fgets() but for struct iolog_file.
+ */
+char *
+iolog_gets(struct iolog_file *iol, char *buf, int bufsize,
+ const char **errstr)
+{
+ char *str;
+ debug_decl(iolog_gets, SUDO_DEBUG_UTIL);
+
+ if (bufsize < 0) {
+ errno = EINVAL;
+ if (errstr != NULL)
+ *errstr = strerror(errno);
+ debug_return_str(NULL);
+ }
+
+#ifdef HAVE_ZLIB_H
+ if (iol->compressed) {
+ if ((str = gzgets(iol->fd.g, buf, bufsize)) == NULL) {
+ if (errstr != NULL) {
+ int errnum;
+ *errstr = gzerror(iol->fd.g, &errnum);
+ if (errnum == Z_ERRNO)
+ *errstr = strerror(errno);
+ }
+ }
+ } else
+#endif
+ {
+ if ((str = fgets(buf, bufsize, iol->fd.f)) == NULL) {
+ if (errstr != NULL)
+ *errstr = strerror(errno);
+ }
+ }
+ debug_return_str(str);
+}
diff --git a/lib/iolog/iolog_json.c b/lib/iolog/iolog_json.c
new file mode 100644
index 0000000..8ae68a0
--- /dev/null
+++ b/lib/iolog/iolog_json.c
@@ -0,0 +1,56 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_eventlog.h>
+#include <sudo_iolog.h>
+
+bool
+iolog_parse_loginfo_json(FILE *fp, const char *iolog_dir, struct eventlog *evlog)
+{
+ struct eventlog_json_object *root;
+ bool ret = false;
+ debug_decl(iolog_parse_loginfo_json, SUDO_DEBUG_UTIL);
+
+ root = eventlog_json_read(fp, iolog_dir);
+ if (root != NULL) {
+ /* Parse the JSON into an eventlog. */
+ ret = eventlog_json_parse(root, evlog);
+
+ /* Cleanup. */
+ eventlog_json_free(root);
+ }
+
+ debug_return_bool(ret);
+}
diff --git a/lib/iolog/iolog_legacy.c b/lib/iolog/iolog_legacy.c
new file mode 100644
index 0000000..5ebe537
--- /dev/null
+++ b/lib/iolog/iolog_legacy.c
@@ -0,0 +1,169 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+#include <signal.h>
+#include <limits.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_iolog.h>
+#include <sudo_util.h>
+
+bool
+iolog_parse_loginfo_legacy(FILE *fp, const char *iolog_dir,
+ struct eventlog *evlog)
+{
+ char *buf = NULL, *cp, *ep;
+ const char *errstr;
+ size_t bufsize = 0, cwdsize = 0, cmdsize = 0;
+ bool ret = false;
+ debug_decl(iolog_parse_loginfo_legacy, SUDO_DEBUG_UTIL);
+
+ /*
+ * Info file has three lines:
+ * 1) a log info line
+ * 2) cwd
+ * 3) command with args
+ */
+ if (getdelim(&buf, &bufsize, '\n', fp) == -1 ||
+ getdelim(&evlog->cwd, &cwdsize, '\n', fp) == -1 ||
+ getdelim(&evlog->command, &cmdsize, '\n', fp) == -1) {
+ sudo_warn(U_("%s: invalid log file"), iolog_dir);
+ goto done;
+ }
+
+ /* Strip the newline from the cwd and command. */
+ evlog->cwd[strcspn(evlog->cwd, "\n")] = '\0';
+ evlog->command[strcspn(evlog->command, "\n")] = '\0';
+
+ /*
+ * Crack the log line (lines and cols not present in old versions).
+ * timestamp:user:runas_user:runas_group:tty:lines:cols
+ * XXX - probably better to use strtok and switch on the state.
+ */
+ buf[strcspn(buf, "\n")] = '\0';
+ cp = buf;
+
+ /* timestamp */
+ if ((ep = strchr(cp, ':')) == NULL) {
+ sudo_warn(U_("%s: time stamp field is missing"), iolog_dir);
+ goto done;
+ }
+ *ep = '\0';
+ evlog->submit_time.tv_sec =
+ (time_t)sudo_strtonum(cp, 0, TIME_T_MAX, &errstr);
+ if (errstr != NULL) {
+ sudo_warn(U_("%s: time stamp %s: %s"), iolog_dir, cp, errstr);
+ goto done;
+ }
+
+ /* submit user */
+ cp = ep + 1;
+ if ((ep = strchr(cp, ':')) == NULL) {
+ sudo_warn(U_("%s: user field is missing"), iolog_dir);
+ goto done;
+ }
+ if ((evlog->submituser = strndup(cp, (size_t)(ep - cp))) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+
+ /* runas user */
+ cp = ep + 1;
+ if ((ep = strchr(cp, ':')) == NULL) {
+ sudo_warn(U_("%s: runas user field is missing"), iolog_dir);
+ goto done;
+ }
+ if ((evlog->runuser = strndup(cp, (size_t)(ep - cp))) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+
+ /* runas group */
+ cp = ep + 1;
+ if ((ep = strchr(cp, ':')) == NULL) {
+ sudo_warn(U_("%s: runas group field is missing"), iolog_dir);
+ goto done;
+ }
+ if (cp != ep) {
+ if ((evlog->rungroup = strndup(cp, (size_t)(ep - cp))) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ }
+
+ /* tty, followed by optional lines + cols */
+ cp = ep + 1;
+ if ((ep = strchr(cp, ':')) == NULL) {
+ /* just the tty */
+ if ((evlog->ttyname = strdup(cp)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ } else {
+ /* tty followed by lines + cols */
+ if ((evlog->ttyname = strndup(cp, (size_t)(ep - cp))) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ cp = ep + 1;
+ /* need to NULL out separator to use sudo_strtonum() */
+ /* XXX - use sudo_strtonumx */
+ if ((ep = strchr(cp, ':')) != NULL) {
+ *ep = '\0';
+ }
+ evlog->lines = (int)sudo_strtonum(cp, 1, INT_MAX, &errstr);
+ if (errstr != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: tty lines %s: %s", iolog_dir, cp, errstr);
+ }
+ if (ep != NULL) {
+ cp = ep + 1;
+ evlog->columns = (int)sudo_strtonum(cp, 1, INT_MAX, &errstr);
+ if (errstr != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: tty cols %s: %s", iolog_dir, cp, errstr);
+ }
+ }
+ }
+
+ ret = true;
+
+done:
+ free(buf);
+ debug_return_bool(ret);
+}
diff --git a/lib/iolog/iolog_loginfo.c b/lib/iolog/iolog_loginfo.c
new file mode 100644
index 0000000..3527cce
--- /dev/null
+++ b/lib/iolog/iolog_loginfo.c
@@ -0,0 +1,238 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_json.h>
+#include <sudo_iolog.h>
+#include <sudo_util.h>
+
+struct eventlog *
+iolog_parse_loginfo(int dfd, const char *iolog_dir)
+{
+ struct eventlog *evlog = NULL;
+ FILE *fp = NULL;
+ int fd = -1;
+ int tmpfd = -1;
+ bool ok, legacy = false;
+ debug_decl(iolog_parse_loginfo, SUDO_DEBUG_UTIL);
+
+ if (dfd == -1) {
+ if ((tmpfd = open(iolog_dir, O_RDONLY)) == -1) {
+ sudo_warn("%s", iolog_dir);
+ goto bad;
+ }
+ dfd = tmpfd;
+ }
+ if ((fd = openat(dfd, "log.json", O_RDONLY, 0)) == -1) {
+ fd = openat(dfd, "log", O_RDONLY, 0);
+ legacy = true;
+ }
+ if (tmpfd != -1)
+ close(tmpfd);
+ if (fd == -1 || (fp = fdopen(fd, "r")) == NULL) {
+ sudo_warn("%s/log", iolog_dir);
+ goto bad;
+ }
+ fd = -1;
+
+ if ((evlog = calloc(1, sizeof(*evlog))) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ evlog->runuid = (uid_t)-1;
+ evlog->rungid = (gid_t)-1;
+ evlog->exit_value = -1;
+
+ ok = legacy ? iolog_parse_loginfo_legacy(fp, iolog_dir, evlog) :
+ iolog_parse_loginfo_json(fp, iolog_dir, evlog);
+ if (ok) {
+ fclose(fp);
+ debug_return_ptr(evlog);
+ }
+
+bad:
+ if (fd != -1)
+ close(fd);
+ if (fp != NULL)
+ fclose(fp);
+ eventlog_free(evlog);
+ debug_return_ptr(NULL);
+}
+
+/*
+ * Write the legacy I/O log file that contains the user and command info.
+ * This file is not compressed.
+ */
+static bool
+iolog_write_info_file_legacy(int dfd, struct eventlog *evlog)
+{
+ char * const *av;
+ FILE *fp;
+ int error, fd;
+ debug_decl(iolog_info_write_log, SUDO_DEBUG_UTIL);
+
+ fd = iolog_openat(dfd, "log", O_CREAT|O_TRUNC|O_WRONLY);
+ if (fd == -1 || (fp = fdopen(fd, "w")) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to %sopen %s/log", fd == -1 ? "" : "fd", evlog->iolog_path);
+ if (fd != -1)
+ close(fd);
+ debug_return_bool(false);
+ }
+ if (fchown(fd, iolog_get_uid(), iolog_get_gid()) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to fchown %d:%d %s/log", __func__,
+ (int)iolog_get_uid(), (int)iolog_get_gid(), evlog->iolog_path);
+ }
+
+ fprintf(fp, "%lld:%s:%s:%s:%s:%d:%d\n%s\n",
+ (long long)evlog->submit_time.tv_sec,
+ evlog->submituser ? evlog->submituser : "unknown",
+ evlog->runuser ? evlog->runuser : RUNAS_DEFAULT,
+ evlog->rungroup ? evlog->rungroup : "",
+ evlog->ttyname ? evlog->ttyname : "unknown",
+ evlog->lines, evlog->columns,
+ evlog->cwd ? evlog->cwd : "unknown");
+ fputs(evlog->command ? evlog->command : "unknown", fp);
+ for (av = evlog->runargv + 1; *av != NULL; av++) {
+ fputc(' ', fp);
+ fputs(*av, fp);
+ }
+ fputc('\n', fp);
+ fflush(fp);
+ if ((error = ferror(fp))) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to write to I/O log file %s/log", evlog->iolog_path);
+ }
+ fclose(fp);
+
+ debug_return_bool(!error);
+}
+
+/*
+ * Write the "log.json" file that contains the user and command info.
+ * This file is not compressed.
+ */
+static bool
+iolog_write_info_file_json(int dfd, struct eventlog *evlog)
+{
+ struct json_container jsonc;
+ struct json_value json_value;
+ bool ret = false;
+ FILE *fp = NULL;
+ int fd = -1;
+ debug_decl(iolog_write_info_file_json, SUDO_DEBUG_UTIL);
+
+ if (!sudo_json_init(&jsonc, 4, false, false, false))
+ debug_return_bool(false);
+
+ /* Timestamp */
+ if (!sudo_json_open_object(&jsonc, "timestamp"))
+ goto oom;
+
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = evlog->submit_time.tv_sec;
+ if (!sudo_json_add_value(&jsonc, "seconds", &json_value))
+ goto oom;
+
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = evlog->submit_time.tv_nsec;
+ if (!sudo_json_add_value(&jsonc, "nanoseconds", &json_value))
+ goto oom;
+
+ if (!sudo_json_close_object(&jsonc))
+ goto oom;
+
+ if (!eventlog_store_json(&jsonc, evlog))
+ goto done;
+
+ fd = iolog_openat(dfd, "log.json", O_CREAT|O_TRUNC|O_WRONLY);
+ if (fd == -1 || (fp = fdopen(fd, "w")) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to %sopen %s/log.json", fd == -1 ? "" : "fd",
+ evlog->iolog_path);
+ goto done;
+ }
+ if (fchown(fd, iolog_get_uid(), iolog_get_gid()) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to fchown %d:%d %s/log.json", __func__,
+ (int)iolog_get_uid(), (int)iolog_get_gid(), evlog->iolog_path);
+ }
+ fd = -1;
+
+ fprintf(fp, "{%s\n}\n", sudo_json_get_buf(&jsonc));
+ fflush(fp);
+ if (ferror(fp)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to write to I/O log file %s/log.json", evlog->iolog_path);
+ goto done;
+ }
+
+ ret = true;
+ goto done;
+
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+done:
+ sudo_json_free(&jsonc);
+ if (fp != NULL)
+ fclose(fp);
+ if (fd != -1)
+ close(fd);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Write the I/O log and log.json files that contain user and command info.
+ * These files are not compressed.
+ */
+bool
+iolog_write_info_file(int dfd, struct eventlog *evlog)
+{
+ debug_decl(iolog_write_info_file, SUDO_DEBUG_UTIL);
+
+ if (!iolog_write_info_file_legacy(dfd, evlog))
+ debug_return_bool(false);
+ if (!iolog_write_info_file_json(dfd, evlog))
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
diff --git a/lib/iolog/iolog_mkdirs.c b/lib/iolog/iolog_mkdirs.c
new file mode 100644
index 0000000..2c69e84
--- /dev/null
+++ b/lib/iolog/iolog_mkdirs.c
@@ -0,0 +1,145 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_iolog.h>
+#include <sudo_util.h>
+
+/*
+ * Create directory and any parent directories as needed.
+ */
+bool
+iolog_mkdirs(const char *path)
+{
+ const mode_t iolog_filemode = iolog_get_file_mode();
+ const mode_t iolog_dirmode = iolog_get_dir_mode();
+ const uid_t iolog_uid = iolog_get_uid();
+ const gid_t iolog_gid = iolog_get_gid();
+ bool ok = true, uid_changed = false;
+ struct stat sb;
+ mode_t omask;
+ int dfd;
+ debug_decl(iolog_mkdirs, SUDO_DEBUG_UTIL);
+
+ dfd = open(path, O_RDONLY|O_NONBLOCK);
+ if (dfd == -1 && errno == EACCES) {
+ /* Try again as the I/O log owner (for NFS). */
+ if (iolog_swapids(false)) {
+ dfd = open(path, O_RDONLY|O_NONBLOCK);
+ if (!iolog_swapids(true)) {
+ ok = false;
+ goto done;
+ }
+ }
+ }
+ if (dfd != -1 && fstat(dfd, &sb) != -1) {
+ if (S_ISDIR(sb.st_mode)) {
+ if (sb.st_uid != iolog_uid || sb.st_gid != iolog_gid) {
+ if (fchown(dfd, iolog_uid, iolog_gid) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to chown %d:%d %s", __func__,
+ (int)iolog_uid, (int)iolog_gid, path);
+ }
+ }
+ if ((sb.st_mode & ALLPERMS) != iolog_dirmode) {
+ if (fchmod(dfd, iolog_dirmode) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to chmod 0%o %s", __func__,
+ (int)iolog_dirmode, path);
+ }
+ }
+ } else {
+ sudo_warnx(U_("%s exists but is not a directory (0%o)"),
+ path, (unsigned int) sb.st_mode);
+ errno = ENOTDIR;
+ ok = false;
+ }
+ goto done;
+ }
+
+ /* umask must not be more restrictive than the file modes. */
+ omask = umask(ACCESSPERMS & ~(iolog_filemode|iolog_dirmode));
+
+ ok = false;
+ if (dfd != -1)
+ close(dfd);
+ dfd = sudo_open_parent_dir(path, iolog_uid, iolog_gid, iolog_dirmode, true);
+ if (dfd == -1 && errno == EACCES) {
+ /* Try again as the I/O log owner (for NFS). */
+ uid_changed = iolog_swapids(false);
+ if (uid_changed)
+ dfd = sudo_open_parent_dir(path, (uid_t)-1, (gid_t)-1,
+ iolog_dirmode, false);
+ }
+ if (dfd != -1) {
+ /* Create final path component. */
+ const char *base = sudo_basename(path);
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "mkdir %s, mode 0%o", path, (unsigned int) iolog_dirmode);
+ ok = mkdirat(dfd, base, iolog_dirmode) == 0 || errno == EEXIST;
+ if (!ok) {
+ if (errno == EACCES && !uid_changed) {
+ /* Try again as the I/O log owner (for NFS). */
+ uid_changed = iolog_swapids(false);
+ if (uid_changed)
+ ok = mkdirat(dfd, base, iolog_dirmode) == 0 || errno == EEXIST;
+ }
+ if (!ok)
+ sudo_warn(U_("unable to mkdir %s"), path);
+ } else {
+ if (fchownat(dfd, base, iolog_uid, iolog_gid, AT_SYMLINK_NOFOLLOW) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to chown %d:%d %s", __func__,
+ (int)iolog_uid, (int)iolog_gid, path);
+ }
+ }
+ }
+ if (uid_changed) {
+ if (!iolog_swapids(true))
+ ok = false;
+ }
+
+ umask(omask);
+
+done:
+ if (dfd != -1)
+ close(dfd);
+ debug_return_bool(ok);
+}
diff --git a/lib/iolog/iolog_mkdtemp.c b/lib/iolog/iolog_mkdtemp.c
new file mode 100644
index 0000000..6ac9c8f
--- /dev/null
+++ b/lib/iolog/iolog_mkdtemp.c
@@ -0,0 +1,100 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <time.h>
+#include <errno.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_util.h>
+#include <sudo_iolog.h>
+
+/*
+ * Create temporary directory and any parent directories as needed.
+ */
+bool
+iolog_mkdtemp(char *path)
+{
+ const mode_t iolog_filemode = iolog_get_file_mode();
+ const mode_t iolog_dirmode = iolog_get_dir_mode();
+ const uid_t iolog_uid = iolog_get_uid();
+ const gid_t iolog_gid = iolog_get_gid();
+ bool ok = false, uid_changed = false;
+ char *dir = sudo_basename(path);
+ mode_t omask;
+ int dfd;
+ debug_decl(iolog_mkdtemp, SUDO_DEBUG_UTIL);
+
+ /* umask must not be more restrictive than the file modes. */
+ omask = umask(ACCESSPERMS & ~(iolog_filemode|iolog_dirmode));
+
+ dfd = sudo_open_parent_dir(path, iolog_uid, iolog_gid, iolog_dirmode, true);
+ if (dfd == -1 && errno == EACCES) {
+ /* Try again as the I/O log owner (for NFS). */
+ uid_changed = iolog_swapids(false);
+ if (uid_changed)
+ dfd = sudo_open_parent_dir(path, (uid_t)-1, (gid_t)-1,
+ iolog_dirmode, false);
+ }
+ if (dfd != -1) {
+ /* Create final path component. */
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "mkdtemp %s", path);
+ /* We cannot retry mkdtemp() so always open as iolog user */
+ if (!uid_changed)
+ uid_changed = iolog_swapids(false);
+ if (mkdtempat(dfd, dir) == NULL) {
+ sudo_warn(U_("unable to mkdir %s"), path);
+ ok = false;
+ } else {
+ if (fchmodat(dfd, dir, iolog_dirmode, 0) != 0) {
+ /* Not a fatal error, pre-existing mode is 0700. */
+ sudo_warn(U_("unable to change mode of %s to 0%o"),
+ path, (unsigned int)iolog_dirmode);
+ }
+ ok = true;
+ }
+ close(dfd);
+ }
+
+ umask(omask);
+
+ if (uid_changed) {
+ if (!iolog_swapids(true))
+ ok = false;
+ }
+ debug_return_bool(ok);
+}
diff --git a/lib/iolog/iolog_mkpath.c b/lib/iolog/iolog_mkpath.c
new file mode 100644
index 0000000..75a79e1
--- /dev/null
+++ b/lib/iolog/iolog_mkpath.c
@@ -0,0 +1,65 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <string.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_iolog.h>
+
+/*
+ * Create path and any intermediate directories.
+ * If path ends in 'XXXXXX', use mkdtemp().
+ */
+bool
+iolog_mkpath(char *path)
+{
+ size_t len;
+ bool ret;
+ debug_decl(iolog_mkpath, SUDO_DEBUG_UTIL);
+
+ /*
+ * Create path and intermediate subdirs as needed.
+ * If path ends in at least 6 Xs (ala POSIX mktemp), use mkdtemp().
+ * Sets iolog_gid (if it is not already set) as a side effect.
+ */
+ len = strlen(path);
+ if (len >= 6 && strcmp(&path[len - 6], "XXXXXX") == 0)
+ ret = iolog_mkdtemp(path);
+ else
+ ret = iolog_mkdirs(path);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, "iolog path %s", path);
+
+ debug_return_bool(ret);
+}
diff --git a/lib/iolog/iolog_nextid.c b/lib/iolog/iolog_nextid.c
new file mode 100644
index 0000000..3cc1609
--- /dev/null
+++ b/lib/iolog/iolog_nextid.c
@@ -0,0 +1,151 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_iolog.h>
+#include <sudo_util.h>
+
+/*
+ * Read the on-disk sequence number, set sessid to the next
+ * number, and update the on-disk copy.
+ * Uses file locking to avoid sequence number collisions.
+ */
+bool
+iolog_nextid(const char *iolog_dir, char sessid[7])
+{
+ char buf[32], *ep;
+ int i, fd = -1;
+ unsigned long id = 0;
+ size_t len;
+ ssize_t nread;
+ bool ret = false;
+ char pathbuf[PATH_MAX];
+ static const char b36char[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ const uid_t iolog_uid = iolog_get_uid();
+ const gid_t iolog_gid = iolog_get_gid();
+ debug_decl(iolog_nextid, SUDO_DEBUG_UTIL);
+
+ /*
+ * Create I/O log directory if it doesn't already exist.
+ */
+ len = strlcpy(pathbuf, iolog_dir, sizeof(pathbuf));
+ if (len >= sizeof(pathbuf)) {
+ errno = ENAMETOOLONG;
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: %s", __func__, iolog_dir);
+ goto done;
+ }
+ if (!iolog_mkdirs(pathbuf))
+ goto done;
+
+ /*
+ * Open sequence file
+ */
+ len = strlcat(pathbuf, "/seq", sizeof(pathbuf));
+ if (len >= sizeof(pathbuf)) {
+ errno = ENAMETOOLONG;
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: %s/seq", __func__, iolog_dir);
+ goto done;
+ }
+ fd = iolog_openat(AT_FDCWD, pathbuf, O_RDWR|O_CREAT);
+ if (fd == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to open %s", __func__, pathbuf);
+ goto done;
+ }
+ if (!sudo_lock_file(fd, SUDO_LOCK)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to lock %s", pathbuf);
+ goto done;
+ }
+ if (fchown(fd, iolog_uid, iolog_gid) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to fchown %d:%d %s", __func__,
+ (int)iolog_uid, (int)iolog_gid, pathbuf);
+ }
+
+ /* Read current seq number (base 36). */
+ nread = read(fd, buf, sizeof(buf) - 1);
+ if (nread != 0) {
+ if (nread == -1) {
+ goto done;
+ }
+ if (buf[nread - 1] == '\n')
+ nread--;
+ buf[nread] = '\0';
+ id = strtoul(buf, &ep, 36);
+ if (ep == buf || *ep != '\0' || id >= iolog_get_maxseq()) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: bad sequence number: %s", pathbuf, buf);
+ id = 0;
+ }
+ }
+ id++;
+
+ /*
+ * Convert id to a string and stash in sessid.
+ * Note that that least significant digits go at the end of the string.
+ */
+ for (i = 5; i >= 0; i--) {
+ buf[i] = b36char[id % 36];
+ id /= 36;
+ }
+ buf[6] = '\n';
+
+ /* Stash id for logging purposes. */
+ memcpy(sessid, buf, 6);
+ sessid[6] = '\0';
+
+ /* Rewind and overwrite old seq file, including the NUL byte. */
+ if (pwrite(fd, buf, 7, 0) != 7) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to write %s", __func__, pathbuf);
+ goto done;
+ }
+ ret = true;
+
+done:
+ if (fd != -1)
+ close(fd);
+ debug_return_bool(ret);
+}
diff --git a/lib/iolog/iolog_open.c b/lib/iolog/iolog_open.c
new file mode 100644
index 0000000..24e19d8
--- /dev/null
+++ b/lib/iolog/iolog_open.c
@@ -0,0 +1,127 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_iolog.h>
+#include <sudo_util.h>
+
+static unsigned char const gzip_magic[2] = {0x1f, 0x8b};
+
+/*
+ * Open the specified I/O log file and store in iol.
+ * Stores the open file handle which has the close-on-exec flag set.
+ */
+bool
+iolog_open(struct iolog_file *iol, int dfd, int iofd, const char *mode)
+{
+ int flags;
+ const char *file;
+ unsigned char magic[2];
+ const uid_t iolog_uid = iolog_get_uid();
+ const gid_t iolog_gid = iolog_get_gid();
+ debug_decl(iolog_open, SUDO_DEBUG_UTIL);
+
+ if (mode[0] == 'r') {
+ flags = mode[1] == '+' ? O_RDWR : O_RDONLY;
+ } else if (mode[0] == 'w') {
+ flags = O_CREAT|O_TRUNC;
+ flags |= mode[1] == '+' ? O_RDWR : O_WRONLY;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: invalid I/O mode %s", __func__, mode);
+ debug_return_bool(false);
+ }
+ if ((file = iolog_fd_to_name(iofd)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: invalid iofd %d", __func__, iofd);
+ debug_return_bool(false);
+ }
+
+ iol->writable = false;
+ iol->compressed = false;
+ if (iol->enabled) {
+ int fd = iolog_openat(dfd, file, flags);
+ if (fd != -1) {
+ if (*mode == 'w') {
+ if (fchown(fd, iolog_uid, iolog_gid) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to fchown %d:%d %s", __func__,
+ (int)iolog_uid, (int)iolog_gid, file);
+ }
+ iol->compressed = iolog_get_compress();
+ } else {
+ /* check for gzip magic number */
+ if (pread(fd, magic, sizeof(magic), 0) == ssizeof(magic)) {
+ if (magic[0] == gzip_magic[0] && magic[1] == gzip_magic[1])
+ iol->compressed = true;
+ }
+ }
+ if (fcntl(fd, F_SETFD, FD_CLOEXEC) != -1) {
+#ifdef HAVE_ZLIB_H
+ if (iol->compressed)
+ iol->fd.g = gzdopen(fd, mode);
+ else
+#endif
+ iol->fd.f = fdopen(fd, mode);
+ }
+ if (iol->fd.v != NULL) {
+ switch ((flags & O_ACCMODE)) {
+ case O_WRONLY:
+ case O_RDWR:
+ iol->writable = true;
+ break;
+ }
+ } else {
+ int save_errno = errno;
+ close(fd);
+ errno = save_errno;
+ fd = -1;
+ }
+ }
+ if (fd == -1) {
+ iol->enabled = false;
+ debug_return_bool(false);
+ }
+ } else {
+ if (*mode == 'w') {
+ /* Remove old log file in case we recycled sequence numbers. */
+ (void)unlinkat(dfd, file, 0);
+ }
+ }
+ debug_return_bool(true);
+}
diff --git a/lib/iolog/iolog_openat.c b/lib/iolog/iolog_openat.c
new file mode 100644
index 0000000..75146a5
--- /dev/null
+++ b/lib/iolog/iolog_openat.c
@@ -0,0 +1,90 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_iolog.h>
+#include <sudo_util.h>
+
+/*
+ * Wrapper for openat(2) that sets umask and retries as iolog_uid/iolog_gid
+ * if openat(2) returns EACCES.
+ */
+int
+iolog_openat(int dfd, const char *path, int flags)
+{
+ const mode_t iolog_filemode = iolog_get_file_mode();
+ const mode_t iolog_dirmode = iolog_get_dir_mode();
+ mode_t omask = S_IRWXG|S_IRWXO;
+ int fd;
+ debug_decl(iolog_openat, SUDO_DEBUG_UTIL);
+
+ if (ISSET(flags, O_CREAT)) {
+ /* umask must not be more restrictive than the file modes. */
+ omask = umask(ACCESSPERMS & ~(iolog_filemode|iolog_dirmode));
+ }
+ fd = openat(dfd, path, flags, iolog_filemode);
+ if (fd == -1 && errno == EACCES) {
+ /* Enable write bit if it is missing. */
+ struct stat sb;
+ if (fstatat(dfd, path, &sb, 0) == 0) {
+ mode_t write_bits = iolog_filemode & (S_IWUSR|S_IWGRP|S_IWOTH);
+ if ((sb.st_mode & write_bits) != write_bits) {
+ if (fchmodat(dfd, path, iolog_filemode, 0) == 0)
+ fd = openat(dfd, path, flags, iolog_filemode);
+ }
+ }
+ }
+ if (fd == -1 && errno == EACCES) {
+ /* Try again as the I/O log owner (for NFS). */
+ if (iolog_swapids(false)) {
+ fd = openat(dfd, path, flags, iolog_filemode);
+ if (!iolog_swapids(true)) {
+ /* iolog_swapids() warns on error. */
+ if (fd != -1) {
+ close(fd);
+ fd = -1;
+ }
+ }
+ }
+ }
+ if (ISSET(flags, O_CREAT))
+ umask(omask);
+ debug_return_int(fd);
+}
diff --git a/lib/iolog/iolog_path.c b/lib/iolog/iolog_path.c
new file mode 100644
index 0000000..ef018e1
--- /dev/null
+++ b/lib/iolog/iolog_path.c
@@ -0,0 +1,130 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+#include <limits.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_iolog.h>
+#include <sudo_util.h>
+
+/*
+ * Expand any escape sequences in inpath, returning the expanded path.
+ */
+bool
+expand_iolog_path(const char *inpath, char *path, size_t pathlen,
+ const struct iolog_path_escape *escapes, void *closure)
+{
+ char *dst, *pathend, tmpbuf[PATH_MAX];
+ const char *endbrace, *src;
+ bool strfit = false;
+ size_t len;
+ debug_decl(expand_iolog_path, SUDO_DEBUG_UTIL);
+
+ /* Collapse multiple leading slashes. */
+ while (inpath[0] == '/' && inpath[1] == '/')
+ inpath++;
+
+ pathend = path + pathlen;
+ for (src = inpath, dst = path; *src != '\0'; src++) {
+ if (src[0] == '%') {
+ if (src[1] == '{') {
+ endbrace = strchr(src + 2, '}');
+ if (endbrace != NULL) {
+ const struct iolog_path_escape *esc;
+ len = (size_t)(endbrace - src - 2);
+ for (esc = escapes; esc->name != NULL; esc++) {
+ if (strncmp(src + 2, esc->name, len) == 0 &&
+ esc->name[len] == '\0')
+ break;
+ }
+ if (esc->name != NULL) {
+ len = esc->copy_fn(dst, (size_t)(pathend - dst),
+ closure);
+ if (len >= (size_t)(pathend - dst))
+ goto bad;
+ dst += len;
+ src = endbrace;
+ continue;
+ }
+ }
+ } else if (src[1] == '%') {
+ /* Collapse %% -> % */
+ src++;
+ } else {
+ /* May need strftime() */
+ strfit = true;
+ }
+ }
+ /* Need at least 2 chars, including the NUL terminator. */
+ if (dst + 1 >= pathend)
+ goto bad;
+ *dst++ = *src;
+ }
+
+ /* Trim trailing slashes and NUL terminate. */
+ while (dst > path && dst[-1] == '/')
+ dst--;
+ *dst = '\0';
+
+ /* Expand strftime escapes as needed. */
+ if (strfit) {
+ struct tm tm;
+ time_t now;
+
+ time(&now);
+ if (localtime_r(&now, &tm) == NULL)
+ goto bad;
+
+ /* We only call strftime() on the current part of the buffer. */
+ tmpbuf[sizeof(tmpbuf) - 1] = '\0';
+ len = strftime(tmpbuf, sizeof(tmpbuf), path, &tm);
+
+ if (len == 0 || tmpbuf[sizeof(tmpbuf) - 1] != '\0')
+ goto bad; /* strftime() failed, buf too small? */
+
+ if (len >= (size_t)(pathend - path))
+ goto bad; /* expanded buffer too big to fit. */
+ memcpy(path, tmpbuf, len);
+ dst = path + len;
+ *dst = '\0';
+ }
+
+ debug_return_bool(true);
+bad:
+ debug_return_bool(false);
+}
diff --git a/lib/iolog/iolog_read.c b/lib/iolog/iolog_read.c
new file mode 100644
index 0000000..013ecaa
--- /dev/null
+++ b/lib/iolog/iolog_read.c
@@ -0,0 +1,79 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_iolog.h>
+
+/*
+ * Read from a (possibly compressed) I/O log file.
+ */
+ssize_t
+iolog_read(struct iolog_file *iol, void *buf, size_t nbytes,
+ const char **errstr)
+{
+ ssize_t nread;
+ debug_decl(iolog_read, SUDO_DEBUG_UTIL);
+
+ if (nbytes > UINT_MAX || nbytes > SSIZE_MAX) { // -V590
+ errno = EINVAL;
+ if (errstr != NULL)
+ *errstr = strerror(errno);
+ debug_return_ssize_t(-1);
+ }
+
+#ifdef HAVE_ZLIB_H
+ if (iol->compressed) {
+ if ((nread = gzread(iol->fd.g, buf, (unsigned int)nbytes)) == -1) {
+ if (errstr != NULL) {
+ int errnum;
+ *errstr = gzerror(iol->fd.g, &errnum);
+ if (errnum == Z_ERRNO)
+ *errstr = strerror(errno);
+ }
+ }
+ } else
+#endif
+ {
+ nread = (ssize_t)fread(buf, 1, nbytes, iol->fd.f);
+ if (nread <= 0 && ferror(iol->fd.f)) {
+ nread = -1;
+ if (errstr != NULL)
+ *errstr = strerror(errno);
+ }
+ }
+ debug_return_ssize_t(nread);
+}
diff --git a/lib/iolog/iolog_seek.c b/lib/iolog/iolog_seek.c
new file mode 100644
index 0000000..d08799a
--- /dev/null
+++ b/lib/iolog/iolog_seek.c
@@ -0,0 +1,69 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_iolog.h>
+
+/*
+ * I/O log wrapper for fseek/gzseek.
+ */
+off_t
+iolog_seek(struct iolog_file *iol, off_t offset, int whence)
+{
+ off_t ret;
+ //debug_decl(iolog_seek, SUDO_DEBUG_UTIL);
+
+#ifdef HAVE_ZLIB_H
+ if (iol->compressed)
+ ret = gzseek(iol->fd.g, offset, whence);
+ else
+#endif
+ ret = fseeko(iol->fd.f, offset, whence);
+
+ //debug_return_off_t(ret);
+ return ret;
+}
+
+/*
+ * I/O log wrapper for rewind/gzrewind.
+ */
+void
+iolog_rewind(struct iolog_file *iol)
+{
+ debug_decl(iolog_rewind, SUDO_DEBUG_UTIL);
+
+#ifdef HAVE_ZLIB_H
+ if (iol->compressed)
+ (void)gzrewind(iol->fd.g);
+ else
+#endif
+ rewind(iol->fd.f);
+
+ debug_return;
+}
diff --git a/lib/iolog/iolog_swapids.c b/lib/iolog/iolog_swapids.c
new file mode 100644
index 0000000..d55123b
--- /dev/null
+++ b/lib/iolog/iolog_swapids.c
@@ -0,0 +1,102 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <time.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_iolog.h>
+
+/*
+ * Set effective user and group-IDs to iolog_uid and iolog_gid.
+ * If restore flag is set, swap them back.
+ */
+bool
+iolog_swapids(bool restore)
+{
+#ifdef HAVE_SETEUID
+ static uid_t user_euid = (uid_t)-1;
+ static gid_t user_egid = (gid_t)-1;
+ const uid_t iolog_uid = iolog_get_uid();
+ const gid_t iolog_gid = iolog_get_gid();
+ debug_decl(io_swapids, SUDO_DEBUG_UTIL);
+
+ if (user_euid == (uid_t)-1)
+ user_euid = geteuid();
+ if (user_egid == (gid_t)-1)
+ user_egid = getegid();
+
+ if (user_euid == iolog_uid && user_egid == iolog_gid) {
+ sudo_debug_printf(SUDO_DEBUG_NOTICE,
+ "%s: effective uid/gid matches iolog uid/gid, nothing to do",
+ __func__);
+ debug_return_bool(true);
+ }
+
+ if (restore) {
+ if (seteuid(user_euid) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to restore effective uid to %d", __func__,
+ (int)user_euid);
+ sudo_warn("seteuid() %d -> %d", (int)iolog_uid, (int)user_euid);
+ debug_return_bool(false);
+ }
+ if (setegid(user_egid) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to restore effective gid to %d", __func__,
+ (int)user_egid);
+ sudo_warn("setegid() %d -> %d", (int)iolog_gid, (int)user_egid);
+ debug_return_bool(false);
+ }
+ } else {
+ /* Fail silently if the user has insufficient privileges. */
+ if (setegid(iolog_gid) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to set effective gid to %d", __func__,
+ (int)iolog_gid);
+ debug_return_bool(false);
+ }
+ if (seteuid(iolog_uid) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to set effective uid to %d", __func__,
+ (int)iolog_uid);
+ debug_return_bool(false);
+ }
+ }
+ debug_return_bool(true);
+#else
+ return false;
+#endif
+}
diff --git a/lib/iolog/iolog_timing.c b/lib/iolog/iolog_timing.c
new file mode 100644
index 0000000..c933b4c
--- /dev/null
+++ b/lib/iolog/iolog_timing.c
@@ -0,0 +1,273 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_iolog.h>
+#include <sudo_util.h>
+
+static int timing_event_adj;
+
+void
+iolog_adjust_delay(struct timespec *delay, struct timespec *max_delay,
+ double scale_factor)
+{
+ debug_decl(iolog_adjust_delay, SUDO_DEBUG_UTIL);
+
+ if (scale_factor != 1.0) {
+ /* Order is important: we don't want to double the remainder. */
+ const double seconds = (double)delay->tv_sec / scale_factor;
+ const double nseconds = (double)delay->tv_nsec / scale_factor;
+ delay->tv_sec = (time_t)seconds;
+ delay->tv_nsec = (long)nseconds;
+ delay->tv_nsec += (long)((seconds - (double)delay->tv_sec) * 1000000000);
+ while (delay->tv_nsec >= 1000000000) {
+ delay->tv_sec++;
+ delay->tv_nsec -= 1000000000;
+ }
+ }
+
+ /* Clamp to max delay. */
+ if (max_delay != NULL) {
+ if (sudo_timespeccmp(delay, max_delay, >)) {
+ delay->tv_sec = max_delay->tv_sec;
+ delay->tv_nsec = max_delay->tv_nsec;
+ }
+ }
+
+ debug_return;
+}
+
+/*
+ * Parse the delay as seconds and nanoseconds: %lld.%09ld
+ * Sudo used to write this as a double, but since timing data is logged
+ * in the C locale this may not match the current locale.
+ */
+char *
+iolog_parse_delay(const char *cp, struct timespec *delay,
+ const char *decimal_point)
+{
+ char numbuf[STRLEN_MAX_SIGNED(long long) + 1];
+ const char *errstr, *ep;
+ long long llval;
+ size_t len;
+ debug_decl(iolog_parse_delay, SUDO_DEBUG_UTIL);
+
+ /* Parse seconds (whole number portion). */
+ for (ep = cp; isdigit((unsigned char)*ep); ep++)
+ continue;
+ len = (size_t)(ep - cp);
+ if (len >= sizeof(numbuf)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: number of seconds is too large", cp);
+ debug_return_ptr(NULL);
+ }
+ memcpy(numbuf, cp, len);
+ numbuf[len] = '\0';
+ delay->tv_sec = (time_t)sudo_strtonum(numbuf, 0, TIME_T_MAX, &errstr);
+ if (errstr != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: number of seconds is %s", numbuf, errstr);
+ debug_return_ptr(NULL);
+ }
+
+ /* Radix may be in user's locale for sudo < 1.7.4 so accept that too. */
+ if (*ep != '.' && *ep != *decimal_point) {
+ if (*ep == '\0' || isspace((unsigned char)*ep)) {
+ /* No fractional part. */
+ delay->tv_nsec = 0;
+ goto done;
+ }
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "invalid characters after seconds: %s", ep);
+ debug_return_ptr(NULL);
+ }
+ cp = ep + 1;
+
+ /* Parse fractional part, we may read more precision than we can store. */
+ for (ep = cp; isdigit((unsigned char)*ep); ep++)
+ continue;
+ len = (size_t)(ep - cp);
+ if (len >= sizeof(numbuf)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: number of nanoseconds is too large", cp);
+ debug_return_ptr(NULL);
+ }
+ memcpy(numbuf, cp, len);
+ numbuf[len] = '\0';
+ llval = sudo_strtonum(numbuf, 0, LLONG_MAX, &errstr);
+ if (errstr != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: number of nanoseconds is %s", numbuf, errstr);
+ debug_return_ptr(NULL);
+ }
+
+ /* Adjust fractional part to nanosecond precision. */
+ if (len < 9) {
+ /* Convert to nanosecond precision. */
+ do {
+ llval *= 10;
+ } while (++len < 9);
+ } else if (len > 9) {
+ /* Clamp to nanoseconds. */
+ do {
+ llval /= 10;
+ } while (--len > 9);
+ }
+ delay->tv_nsec = (long)llval;
+
+done:
+ /* Advance to the next field. */
+ while (isspace((unsigned char)*ep))
+ ep++;
+
+ debug_return_str((char *)ep);
+}
+
+/*
+ * Parse a timing line, which is formatted as:
+ * IO_EVENT_TTYOUT sleep_time num_bytes
+ * IO_EVENT_WINSIZE sleep_time lines cols
+ * IO_EVENT_SUSPEND sleep_time signo
+ * Where type is IO_EVENT_*, sleep_time is the number of seconds to sleep
+ * before writing the data and num_bytes is the number of bytes to output.
+ * Returns true on success and false on failure.
+ */
+bool
+iolog_parse_timing(const char *line, struct timing_closure *timing)
+{
+ unsigned long ulval;
+ char *cp, *ep;
+ debug_decl(iolog_parse_timing, SUDO_DEBUG_UTIL);
+
+ /* Clear iolog descriptor. */
+ timing->iol = NULL;
+
+ /* Parse event type. */
+ ulval = strtoul(line, &ep, 10);
+ if (ep == line || !isspace((unsigned char) *ep))
+ goto bad;
+ if (ulval >= IO_EVENT_COUNT)
+ goto bad;
+ if (ulval == IO_EVENT_TTYOUT_1_8_7) {
+ /* work around a bug in timing files generated by sudo 1.8.7 */
+ timing_event_adj = 2;
+ }
+ timing->event = (int)ulval - timing_event_adj;
+ for (cp = ep + 1; isspace((unsigned char) *cp); cp++)
+ continue;
+
+ /* Parse delay, returns the next field or NULL on error. */
+ if ((cp = iolog_parse_delay(cp, &timing->delay, timing->decimal)) == NULL)
+ goto bad;
+
+ switch (timing->event) {
+ case IO_EVENT_SUSPEND:
+ /* Signal name (no leading SIG prefix) or number. */
+ if (str2sig(cp, &timing->u.signo) == -1)
+ goto bad;
+ break;
+ case IO_EVENT_WINSIZE:
+ ulval = strtoul(cp, &ep, 10);
+ if (ep == cp || !isspace((unsigned char) *ep))
+ goto bad;
+ if (ulval > INT_MAX)
+ goto bad;
+ timing->u.winsize.lines = (int)ulval;
+ for (cp = ep + 1; isspace((unsigned char) *cp); cp++)
+ continue;
+
+ ulval = strtoul(cp, &ep, 10);
+ if (ep == cp || *ep != '\0')
+ goto bad;
+ if (ulval > INT_MAX)
+ goto bad;
+ timing->u.winsize.cols = (int)ulval;
+ break;
+ default:
+ errno = 0;
+ ulval = strtoul(cp, &ep, 10);
+ if (ep == cp || *ep != '\0')
+ goto bad;
+ /* Note: assumes SIZE_MAX == ULONG_MAX */
+ if (errno == ERANGE && ulval == ULONG_MAX)
+ goto bad;
+ timing->u.nbytes = (size_t)ulval;
+ break;
+ }
+
+ debug_return_bool(true);
+bad:
+ debug_return_bool(false);
+}
+
+/*
+ * Read the next record from the timing file.
+ * Return 0 on success, 1 on EOF and -1 on error.
+ */
+int
+iolog_read_timing_record(struct iolog_file *iol, struct timing_closure *timing)
+{
+ char line[LINE_MAX];
+ const char *errstr;
+ debug_decl(iolog_read_timing_record, SUDO_DEBUG_UTIL);
+
+ /* Read next record from timing file. */
+ if (iolog_gets(iol, line, sizeof(line), &errstr) == NULL) {
+ /* EOF or error reading timing file, we are done. */
+ if (iolog_eof(iol))
+ debug_return_int(1);
+ sudo_warnx(U_("error reading timing file: %s"), errstr);
+ debug_return_int(-1);
+ }
+
+ /* Parse timing file record. */
+ line[strcspn(line, "\n")] = '\0';
+ if (!iolog_parse_timing(line, timing)) {
+ sudo_warnx(U_("invalid timing file line: %s"), line);
+ debug_return_int(-1);
+ }
+
+ debug_return_int(0);
+}
diff --git a/lib/iolog/iolog_util.c b/lib/iolog/iolog_util.c
new file mode 100644
index 0000000..8ff5b83
--- /dev/null
+++ b/lib/iolog/iolog_util.c
@@ -0,0 +1,74 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_iolog.h>
+
+/*
+ * Map IOFD_* -> name.
+ */
+const char *
+iolog_fd_to_name(int iofd)
+{
+ const char *ret;
+ debug_decl(iolog_fd_to_name, SUDO_DEBUG_UTIL);
+
+ switch (iofd) {
+ case IOFD_STDIN:
+ ret = "stdin";
+ break;
+ case IOFD_STDOUT:
+ ret = "stdout";
+ break;
+ case IOFD_STDERR:
+ ret = "stderr";
+ break;
+ case IOFD_TTYIN:
+ ret = "ttyin";
+ break;
+ case IOFD_TTYOUT:
+ ret = "ttyout";
+ break;
+ case IOFD_TIMING:
+ ret = "timing";
+ break;
+ default:
+ ret = "unknown";
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "%s: unexpected iofd %d",
+ __func__, iofd);
+ break;
+ }
+ debug_return_const_str(ret);
+}
diff --git a/lib/iolog/iolog_write.c b/lib/iolog/iolog_write.c
new file mode 100644
index 0000000..0ce5a81
--- /dev/null
+++ b/lib/iolog/iolog_write.c
@@ -0,0 +1,105 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_iolog.h>
+
+/*
+ * Write to an I/O log, optionally compressing.
+ */
+ssize_t
+iolog_write(struct iolog_file *iol, const void *buf, size_t len,
+ const char **errstr)
+{
+ ssize_t ret;
+ debug_decl(iolog_write, SUDO_DEBUG_UTIL);
+
+ if (len > UINT_MAX || len > SSIZE_MAX) { // -V590
+ errno = EINVAL;
+ if (errstr != NULL)
+ *errstr = strerror(errno);
+ debug_return_ssize_t(-1);
+ }
+
+#ifdef HAVE_ZLIB_H
+ if (iol->compressed) {
+ int errnum;
+
+ ret = gzwrite(iol->fd.g, buf, (unsigned int)len);
+ if (ret == 0) {
+ ret = -1;
+ if (errstr != NULL) {
+ *errstr = gzerror(iol->fd.g, &errnum);
+ if (errnum == Z_ERRNO)
+ *errstr = strerror(errno);
+ }
+ goto done;
+ }
+ if (iolog_get_flush()) {
+ if (gzflush(iol->fd.g, Z_SYNC_FLUSH) != Z_OK) {
+ ret = -1;
+ if (errstr != NULL) {
+ *errstr = gzerror(iol->fd.g, &errnum);
+ if (errnum == Z_ERRNO)
+ *errstr = strerror(errno);
+ }
+ goto done;
+ }
+ }
+ } else
+#endif
+ {
+ ret = (ssize_t)fwrite(buf, 1, len, iol->fd.f);
+ if (ret <= 0) {
+ ret = -1;
+ if (errstr != NULL)
+ *errstr = strerror(errno);
+ goto done;
+ }
+ if (iolog_get_flush()) {
+ if (fflush(iol->fd.f) != 0) {
+ ret = -1;
+ if (errstr != NULL)
+ *errstr = strerror(errno);
+ goto done;
+ }
+ }
+ }
+
+done:
+ debug_return_ssize_t(ret);
+}
diff --git a/lib/iolog/regress/corpus/seed/log_json/id.json b/lib/iolog/regress/corpus/seed/log_json/id.json
new file mode 100644
index 0000000..5655639
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/log_json/id.json
@@ -0,0 +1,36 @@
+{
+ "timestamp": {
+ "seconds": 1603746837,
+ "nanoseconds": 16450063
+ },
+ "columns": 80,
+ "command": "/usr/bin/id",
+ "lines": 24,
+ "runargv": [
+ "id"
+ ],
+ "runenv": [
+ "PATH=/home/millert/bin/OpenBSD.amd64:/home/millert/bin:/home/millert/bin/scripts:/home/millert/node_modules/.bin:/usr/local/gnu/bin:/usr/local/bin:/usr/local/sbin:/usr/local/etc:/usr/local/rcs/bin:/usr/local/nmh/bin:/usr/local/news/bin:/usr/local/emacs/bin:/usr/local/netpbm/bin:/usr/local/mtools/bin:/usr/local/netscape/bin:/usr/local/ghostscript/bin:/usr/local/frame-5.5.6/bin:/usr/local/teTeX/bin:/usr/local/cvs-1.10.1/bin:/usr/local/games/bin:/usr/local/archivers/bin:/usr/local/skey/bin:/usr/local/audio/bin:/usr/local/rtty/bin:/bin:/sbin:/usr/games:/usr/bin:/usr/sbin:/usr/etc:/etc:/usr/X11R6/bin:/usr/local/bin:/usr/obj/bin:/usr/src/bin",
+ "TERM=xterm-color",
+ "LANG=en_US.UTF-8",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/ksh",
+ "SUDO_COMMAND=/usr/bin/id",
+ "SUDO_USER=millert",
+ "SUDO_UID=8036",
+ "SUDO_GID=20",
+ "KRB5CCNAME=bogus"
+ ],
+ "runuid": 0,
+ "rungid": 0,
+ "runcwd": "/usr/src/local/millert/sudo/trunk/lib/eventlog/regress",
+ "runuser": "root",
+ "rungroup": "wheel",
+ "submitcwd": "/usr/src/local/millert/sudo/trunk/lib/eventlog/regress",
+ "submithost": "xerxes.sudo.ws",
+ "submituser": "millert",
+ "ttyname": "/dev/ttypb"
+}
diff --git a/lib/iolog/regress/corpus/seed/log_json/ls.json b/lib/iolog/regress/corpus/seed/log_json/ls.json
new file mode 100644
index 0000000..17c99d8
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/log_json/ls.json
@@ -0,0 +1,31 @@
+{
+ "timestamp": {
+ "seconds": 1584790549,
+ "nanoseconds": 782859154
+ },
+ "columns": 80,
+ "command": "/bin/ls",
+ "lines": 24,
+ "runargv": [ "ls" ],
+ "runenv": [
+ "LANG=en_US.UTF-8",
+ "TERM=tmux",
+ "PATH=/home/millert/bin/OpenBSD.amd64:/home/millert/bin:/home/millert/bin/scripts:/home/millert/node_modules/.bin:/usr/local/gnu/bin:/usr/local/bin:/usr/local/sbin:/usr/local/etc:/usr/local/rcs/bin:/usr/local/nmh/bin:/usr/local/news/bin:/usr/local/emacs/bin:/usr/local/netpbm/bin:/usr/local/mtools/bin:/usr/local/netscape/bin:/usr/local/ghostscript/bin:/usr/local/frame-5.5.6/bin:/usr/local/teTeX/bin:/usr/local/cvs-1.10.1/bin:/usr/local/games/bin:/usr/local/archivers/bin:/usr/local/skey/bin:/usr/local/audio/bin:/usr/local/rtty/bin:/bin:/sbin:/usr/games:/usr/bin:/usr/sbin:/usr/etc:/etc:/usr/X11R6/bin:/usr/local/bin:/usr/obj/bin:/usr/src/bin",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/ksh",
+ "SUDO_COMMAND=/bin/ls",
+ "SUDO_USER=millert",
+ "SUDO_UID=8036",
+ "SUDO_GID=20",
+ "KRB5CCNAME=bogus"
+ ],
+ "runuid": 0,
+ "runuser": "root",
+ "submitcwd": "/usr/src/local/millert/hg/sudo/1.7",
+ "submithost": "xerxes.sudo.ws",
+ "submituser": "millert",
+ "ttyname": "/dev/ttyp3"
+}
diff --git a/lib/iolog/regress/corpus/seed/log_json/mailq.json b/lib/iolog/regress/corpus/seed/log_json/mailq.json
new file mode 100644
index 0000000..669090d
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/log_json/mailq.json
@@ -0,0 +1,31 @@
+{
+ "timestamp": {
+ "seconds": 1584884264,
+ "nanoseconds": 499794755
+ },
+ "columns": 80,
+ "command": "/usr/bin/mailq",
+ "lines": 24,
+ "runargv": [ "mailq" ],
+ "runenv": [
+ "LANG=en_US.UTF-8",
+ "PATH=/home/millert/bin/OpenBSD.amd64:/home/millert/bin:/home/millert/bin/scripts:/home/millert/node_modules/.bin:/usr/local/gnu/bin:/usr/local/bin:/usr/local/sbin:/usr/local/etc:/usr/local/rcs/bin:/usr/local/nmh/bin:/usr/local/news/bin:/usr/local/emacs/bin:/usr/local/netpbm/bin:/usr/local/mtools/bin:/usr/local/netscape/bin:/usr/local/ghostscript/bin:/usr/local/frame-5.5.6/bin:/usr/local/teTeX/bin:/usr/local/cvs-1.10.1/bin:/usr/local/games/bin:/usr/local/archivers/bin:/usr/local/skey/bin:/usr/local/audio/bin:/usr/local/rtty/bin:/bin:/sbin:/usr/games:/usr/bin:/usr/sbin:/usr/etc:/etc:/usr/X11R6/bin:/usr/local/bin:/usr/obj/bin:/usr/src/bin",
+ "TERM=tmux",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/ksh",
+ "SUDO_COMMAND=/usr/bin/mailq",
+ "SUDO_USER=millert",
+ "SUDO_UID=8036",
+ "SUDO_GID=20",
+ "KRB5CCNAME=bogus"
+ ],
+ "runuid": 0,
+ "runuser": "root",
+ "submitcwd": "/home/millert",
+ "submithost": "xerxes.sudo.ws",
+ "submituser": "millert",
+ "ttyname": "/dev/ttyp3"
+}
diff --git a/lib/iolog/regress/corpus/seed/log_json/make.json b/lib/iolog/regress/corpus/seed/log_json/make.json
new file mode 100644
index 0000000..dcc4736
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/log_json/make.json
@@ -0,0 +1,36 @@
+{
+ "timestamp": {
+ "seconds": 1584977889,
+ "nanoseconds": 510217787
+ },
+ "columns": 80,
+ "command": "/usr/bin/make",
+ "lines": 24,
+ "runargv": [
+ "make",
+ "-C",
+ "/usr/src/usr.bin/sort",
+ "install"
+ ],
+ "runenv": [
+ "PATH=/home/millert/bin/OpenBSD.amd64:/home/millert/bin:/home/millert/bin/scripts:/home/millert/node_modules/.bin:/usr/local/gnu/bin:/usr/local/bin:/usr/local/sbin:/usr/local/etc:/usr/local/rcs/bin:/usr/local/nmh/bin:/usr/local/news/bin:/usr/local/emacs/bin:/usr/local/netpbm/bin:/usr/local/mtools/bin:/usr/local/netscape/bin:/usr/local/ghostscript/bin:/usr/local/frame-5.5.6/bin:/usr/local/teTeX/bin:/usr/local/cvs-1.10.1/bin:/usr/local/games/bin:/usr/local/archivers/bin:/usr/local/skey/bin:/usr/local/audio/bin:/usr/local/rtty/bin:/bin:/sbin:/usr/games:/usr/bin:/usr/sbin:/usr/etc:/etc:/usr/X11R6/bin:/usr/local/bin:/usr/obj/bin:/usr/src/bin",
+ "TERM=xterm-color",
+ "LANG=en_US.UTF-8",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/ksh",
+ "SUDO_COMMAND=/usr/bin/make -C /usr/src/usr.bin/sort install",
+ "SUDO_USER=millert",
+ "SUDO_UID=8036",
+ "SUDO_GID=20",
+ "KRB5CCNAME=bogus"
+ ],
+ "runuid": 0,
+ "runuser": "root",
+ "submitcwd": "/home/millert/tmp/src/usr.bin/sort",
+ "submithost": "xerxes.sudo.ws",
+ "submituser": "millert",
+ "ttyname": "/dev/ttypi"
+}
diff --git a/lib/iolog/regress/corpus/seed/log_json/pkg_add.json b/lib/iolog/regress/corpus/seed/log_json/pkg_add.json
new file mode 100644
index 0000000..bfebc76
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/log_json/pkg_add.json
@@ -0,0 +1,34 @@
+{
+ "timestamp": {
+ "seconds": 1595281300,
+ "nanoseconds": 130458256
+ },
+ "columns": 80,
+ "command": "/usr/sbin/pkg_add",
+ "lines": 24,
+ "runargv": [
+ "pkg_add",
+ "p5-PDF-API2"
+ ],
+ "runenv": [
+ "PATH=/home/millert/bin/OpenBSD.amd64:/home/millert/bin:/home/millert/bin/scripts:/home/millert/node_modules/.bin:/usr/local/gnu/bin:/usr/local/bin:/usr/local/sbin:/usr/local/etc:/usr/local/rcs/bin:/usr/local/nmh/bin:/usr/local/news/bin:/usr/local/emacs/bin:/usr/local/netpbm/bin:/usr/local/mtools/bin:/usr/local/netscape/bin:/usr/local/ghostscript/bin:/usr/local/frame-5.5.6/bin:/usr/local/teTeX/bin:/usr/local/cvs-1.10.1/bin:/usr/local/games/bin:/usr/local/archivers/bin:/usr/local/skey/bin:/usr/local/audio/bin:/usr/local/rtty/bin:/bin:/sbin:/usr/games:/usr/bin:/usr/sbin:/usr/etc:/etc:/usr/X11R6/bin:/usr/local/bin:/usr/obj/bin:/usr/src/bin",
+ "TERM=xterm-color",
+ "LANG=en_US.UTF-8",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/ksh",
+ "SUDO_COMMAND=/usr/sbin/pkg_add p5-PDF-API2",
+ "SUDO_USER=millert",
+ "SUDO_UID=8036",
+ "SUDO_GID=20",
+ "KRB5CCNAME=bogus"
+ ],
+ "runuid": 0,
+ "runuser": "root",
+ "submitcwd": "/usr/src/local/Music/chordpro",
+ "submithost": "xerxes.sudo.ws",
+ "submituser": "millert",
+ "ttyname": "/dev/ttypd"
+}
diff --git a/lib/iolog/regress/corpus/seed/log_json/pkg_delete.json b/lib/iolog/regress/corpus/seed/log_json/pkg_delete.json
new file mode 100644
index 0000000..f0e4fba
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/log_json/pkg_delete.json
@@ -0,0 +1,34 @@
+{
+ "timestamp": {
+ "seconds": 1595620314,
+ "nanoseconds": 965982512
+ },
+ "columns": 80,
+ "command": "/usr/sbin/pkg_delete",
+ "lines": 24,
+ "runargv": [
+ "pkg_delete",
+ "chordpro"
+ ],
+ "runenv": [
+ "PATH=/home/millert/bin/OpenBSD.amd64:/home/millert/bin:/home/millert/bin/scripts:/home/millert/node_modules/.bin:/usr/local/gnu/bin:/usr/local/bin:/usr/local/sbin:/usr/local/etc:/usr/local/rcs/bin:/usr/local/nmh/bin:/usr/local/news/bin:/usr/local/emacs/bin:/usr/local/netpbm/bin:/usr/local/mtools/bin:/usr/local/netscape/bin:/usr/local/ghostscript/bin:/usr/local/frame-5.5.6/bin:/usr/local/teTeX/bin:/usr/local/cvs-1.10.1/bin:/usr/local/games/bin:/usr/local/archivers/bin:/usr/local/skey/bin:/usr/local/audio/bin:/usr/local/rtty/bin:/bin:/sbin:/usr/games:/usr/bin:/usr/sbin:/usr/etc:/etc:/usr/X11R6/bin:/usr/local/bin:/usr/obj/bin:/usr/src/bin",
+ "TERM=xterm-color",
+ "LANG=en_US.UTF-8",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/ksh",
+ "SUDO_COMMAND=/usr/sbin/pkg_delete chordpro",
+ "SUDO_USER=millert",
+ "SUDO_UID=8036",
+ "SUDO_GID=20",
+ "KRB5CCNAME=bogus"
+ ],
+ "runuid": 0,
+ "runuser": "root",
+ "submitcwd": "/usr/ports/textproc/chordpro/pkg",
+ "submithost": "xerxes.sudo.ws",
+ "submituser": "millert",
+ "ttyname": "/dev/ttypd"
+}
diff --git a/lib/iolog/regress/corpus/seed/log_json/printenv.json b/lib/iolog/regress/corpus/seed/log_json/printenv.json
new file mode 100644
index 0000000..6e78719
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/log_json/printenv.json
@@ -0,0 +1,34 @@
+{
+ "timestamp": {
+ "seconds": 1601411718,
+ "nanoseconds": 269131020
+ },
+ "columns": 80,
+ "command": "/usr/bin/printenv",
+ "lines": 24,
+ "runargv": [
+ "/usr/bin/printenv"
+ ],
+ "runenv": [
+ "KRB5CCNAME=bogus",
+ "LANG=en_US.UTF-8",
+ "PATH=/tmp",
+ "TERM=xterm-color",
+ "MAIL=/var/mail/root",
+ "LOGNAME=root",
+ "USER=root",
+ "HOME=/root",
+ "SHELL=/bin/ksh",
+ "SUDO_COMMAND=/usr/bin/printenv",
+ "SUDO_USER=testdude",
+ "SUDO_UID=1000",
+ "SUDO_GID=1000"
+ ],
+ "runuid": 0,
+ "runcwd": "/usr/src/local/millert/sudo/trunk/plugins/sudoers",
+ "runuser": "root",
+ "submitcwd": "/usr/src/local/millert/sudo/trunk/plugins/sudoers",
+ "submithost": "xerxes.sudo.ws",
+ "submituser": "testdude",
+ "ttyname": "/dev/ttypb"
+}
diff --git a/lib/iolog/regress/corpus/seed/log_legacy/id.log b/lib/iolog/regress/corpus/seed/log_legacy/id.log
new file mode 100644
index 0000000..e59965e
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/log_legacy/id.log
@@ -0,0 +1,3 @@
+1603746837:millert:root::/dev/ttypb:24:80
+/usr/src/local/millert/sudo/trunk/lib/eventlog/regress
+/usr/bin/id
diff --git a/lib/iolog/regress/corpus/seed/log_legacy/less.log b/lib/iolog/regress/corpus/seed/log_legacy/less.log
new file mode 100644
index 0000000..66e2929
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/log_legacy/less.log
@@ -0,0 +1,3 @@
+1611859113:bob:bob:ldap:/dev/console:24:80
+/var/tmp
+/usr/bin/less /etc/ldapd.conf
diff --git a/lib/iolog/regress/corpus/seed/log_legacy/ls.log b/lib/iolog/regress/corpus/seed/log_legacy/ls.log
new file mode 100644
index 0000000..808605c
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/log_legacy/ls.log
@@ -0,0 +1,3 @@
+1584790549:millert:root::/dev/ttyp3:24:80
+/usr/src/local/millert/hg/sudo/1.7
+/bin/ls
diff --git a/lib/iolog/regress/corpus/seed/log_legacy/mailq.log b/lib/iolog/regress/corpus/seed/log_legacy/mailq.log
new file mode 100644
index 0000000..9b1fdd6
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/log_legacy/mailq.log
@@ -0,0 +1,3 @@
+1584884264:millert:root::/dev/ttyp3:24:80
+/home/millert
+/usr/bin/mailq
diff --git a/lib/iolog/regress/corpus/seed/log_legacy/make.log b/lib/iolog/regress/corpus/seed/log_legacy/make.log
new file mode 100644
index 0000000..c27798a
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/log_legacy/make.log
@@ -0,0 +1,3 @@
+1584977889:millert:root::/dev/ttypi:24:80
+/home/millert/tmp/src/usr.bin/sort
+/usr/bin/make -C /usr/src/usr.bin/sort install
diff --git a/lib/iolog/regress/corpus/seed/log_legacy/pkg_add.log b/lib/iolog/regress/corpus/seed/log_legacy/pkg_add.log
new file mode 100644
index 0000000..78358e7
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/log_legacy/pkg_add.log
@@ -0,0 +1,3 @@
+1595281300:millert:root::/dev/ttypd:24:80
+/usr/src/local/Music/chordpro
+/usr/sbin/pkg_add p5-PDF-API2
diff --git a/lib/iolog/regress/corpus/seed/log_legacy/pkg_delete.log b/lib/iolog/regress/corpus/seed/log_legacy/pkg_delete.log
new file mode 100644
index 0000000..ce0899a
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/log_legacy/pkg_delete.log
@@ -0,0 +1,3 @@
+1595620314:millert:root::/dev/ttypd:24:80
+/usr/ports/textproc/chordpro/pkg
+/usr/sbin/pkg_delete chordpro
diff --git a/lib/iolog/regress/corpus/seed/log_legacy/printenv.log b/lib/iolog/regress/corpus/seed/log_legacy/printenv.log
new file mode 100644
index 0000000..dbc739a
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/log_legacy/printenv.log
@@ -0,0 +1,3 @@
+1601411718:testdude:root::/dev/ttypb:24:80
+/usr/src/local/millert/sudo/trunk/plugins/sudoers
+/usr/bin/printenv
diff --git a/lib/iolog/regress/corpus/seed/log_legacy/smtpctl.log b/lib/iolog/regress/corpus/seed/log_legacy/smtpctl.log
new file mode 100644
index 0000000..d365617
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/log_legacy/smtpctl.log
@@ -0,0 +1,3 @@
+1666108884:aemon:root::/dev/pts/4:64:128
+/home/aemon
+/usr/sbin/smtpctl remove 272a4d27e1fd732e
diff --git a/lib/iolog/regress/corpus/seed/log_legacy/vi.log b/lib/iolog/regress/corpus/seed/log_legacy/vi.log
new file mode 100644
index 0000000..c95f061
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/log_legacy/vi.log
@@ -0,0 +1,3 @@
+1611849879:alice:root::/dev/pts/0:24:80
+/export/home/alice
+/usr/bin/vi /etc/nsswitch.conf
diff --git a/lib/iolog/regress/corpus/seed/timing/timing.1 b/lib/iolog/regress/corpus/seed/timing/timing.1
new file mode 100644
index 0000000..e954cda
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/timing/timing.1
@@ -0,0 +1,51 @@
+4 0.032200538 32
+4 0.000461816 917
+4 0.000260488 41
+3 0.748747801 1
+4 0.002709345 1040
+3 0.605486330 1
+4 0.002136958 792
+3 0.981620620 1
+4 0.001898021 39
+7 0.002496718 TSTP
+7 11.781181911 CONT
+5 0.000331519 59 120
+4 0.002261240 7
+4 0.005713594 7
+4 0.001005416 974
+4 0.004255422 2064
+4 0.001929362 445
+3 0.632938830 1
+4 0.001316335 15
+3 0.989972022 1
+4 0.001419091 39
+7 0.002164759 TSTP
+7 1.195700989 CONT
+4 0.001525087 7
+7 0.002025577 TTOU
+7 0.908621867 CONT
+4 0.001755079 7
+4 0.001712634 2064
+4 0.001236879 467
+3 0.347054501 1
+4 0.003931829 2082
+3 0.236017124 1
+4 0.002960088 618
+3 0.285032645 1
+4 0.000951230 1
+3 0.470931231 1
+4 0.001103587 8
+3 0.142977268 1
+4 0.001048037 1
+3 0.126189543 1
+4 0.000255520 1
+4 0.000641997 2064
+4 0.000298772 176
+3 3.183861587 1
+4 0.001098032 9
+3 0.142511842 1
+4 0.000995141 1
+3 0.191337037 1
+4 0.001096192 1
+4 0.001180378 7
+4 0.000838979 28
diff --git a/lib/iolog/regress/corpus/seed/timing/timing.2 b/lib/iolog/regress/corpus/seed/timing/timing.2
new file mode 100644
index 0000000..d3e8da0
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/timing/timing.2
@@ -0,0 +1,196 @@
+4 0.017420446 378
+4 0.101673410 78
+4 0.020237132 106
+4 32.406835619 258
+4 0.071903094 51
+4 0.044405150 53
+4 0.002465527 153
+4 0.061104878 37
+4 0.037284253 3
+4 0.035933494 3
+4 0.035405047 3
+4 0.035096439 3
+4 0.035427343 3
+4 0.035278610 3
+4 0.035503923 3
+4 0.034726429 3
+4 0.035415822 3
+4 0.035642850 4
+4 0.035104123 3
+4 0.035177940 3
+4 0.035114787 3
+4 0.035398463 3
+4 0.035774228 3
+4 0.034687088 3
+4 0.035231607 3
+4 0.035235355 3
+4 0.035430098 3
+4 0.035238761 3
+4 0.035310472 3
+4 0.035678834 6
+4 0.035098980 3
+4 0.034974643 3
+4 0.034769832 3
+4 0.035066706 3
+4 0.034910781 3
+4 0.034939164 3
+4 0.035387880 3
+4 0.036229124 3
+4 0.035210123 6
+4 0.034996626 6
+4 0.034484929 2
+4 0.014762481 40
+4 0.034798156 3
+4 0.035382724 3
+4 0.035200992 3
+4 0.035793731 3
+4 0.036046635 3
+4 0.035232505 3
+4 0.035596184 3
+4 0.034359958 3
+4 0.034881742 3
+4 0.036581308 4
+4 0.035716612 3
+4 0.034981224 3
+4 0.034653311 3
+4 0.035700405 3
+4 0.035204600 3
+4 0.035080066 3
+4 0.035072298 3
+4 0.035950557 3
+4 0.034524949 3
+4 0.035231401 3
+4 0.035918148 6
+4 0.035009022 3
+4 0.034086126 3
+4 0.034031601 3
+4 0.035507794 3
+4 0.035359991 3
+4 0.035451670 3
+4 0.034207436 3
+4 0.036154464 3
+4 0.034687026 6
+4 0.034511000 6
+4 0.035712971 2
+4 0.001114632 280
+4 0.013357954 70
+4 0.009099934 250
+4 0.345595767 59
+4 0.014672692 168
+4 0.165009111 119
+4 0.037129573 168
+4 0.163729717 119
+4 0.046685595 70
+4 0.010058716 205
+4 0.335682997 62
+4 0.009757680 403
+4 0.764539162 234
+4 0.126274733 133
+4 0.035954324 133
+4 0.160744133 706
+4 0.012594228 389
+4 0.000600099 337
+4 0.008974842 70
+4 0.009992828 205
+4 0.333655416 62
+4 0.009799688 415
+4 0.768206552 251
+4 0.123329919 133
+4 0.036529633 133
+4 0.131658603 706
+4 0.009965871 452
+4 0.000352099 274
+4 0.006881291 70
+4 0.007616147 210
+4 0.258108895 67
+4 0.007582335 418
+4 0.592632286 244
+4 0.096206429 143
+4 0.028539423 143
+4 0.124772846 706
+4 0.009854967 389
+4 0.000365510 337
+4 0.038009729 245
+4 0.044260031 73
+4 0.013835442 72
+4 0.013734457 81
+4 0.013966252 260
+4 0.233058895 59
+4 0.007278138 869
+4 1.481039643 148
+4 0.089258162 158
+4 0.082642822 151
+4 0.051838211 2202
+4 0.164269353 45
+4 0.014776451 127
+4 0.033523033 127
+4 0.102601946 706
+4 0.009758392 475
+4 0.000371524 251
+4 0.006895216 149
+4 0.101515800 117
+4 0.049231011 149
+4 0.100724385 117
+4 0.028593605 142
+4 0.100398116 110
+4 0.033582408 74
+4 0.013919259 82
+4 0.020859788 63
+4 0.007864945 70
+4 0.007803279 207
+4 0.258587972 64
+4 0.007479117 409
+4 0.590341346 238
+4 0.095587884 137
+4 0.028246058 137
+4 0.125974303 706
+4 0.009846897 475
+4 0.000398383 251
+4 0.007711302 101
+4 0.013103236 208
+4 0.261674900 65
+4 0.007528283 730
+4 0.890361622 601
+4 0.126547307 139
+4 0.034250610 139
+4 0.126209288 706
+4 0.009859395 475
+4 0.000386854 251
+4 0.002122077 310
+4 0.153210769 179
+4 0.014128026 253
+4 0.007009755 152
+4 0.127577685 103
+4 0.029587241 31
+4 0.001733173 36
+4 0.001730350 187
+4 0.002311429 334
+4 0.002449265 165
+4 0.089927714 131
+4 0.028627022 132
+4 0.124746485 706
+4 0.009744954 452
+4 0.000377336 274
+4 0.006732444 62
+4 0.006519788 106
+4 0.024636847 130
+4 0.018143227 294
+4 0.177574909 150
+4 0.124543833 104
+4 0.021106187 92
+4 0.021020993 108
+4 0.019733705 106
+4 0.021929696 120
+4 0.021340851 108
+4 0.020144663 104
+4 0.019972905 96
+4 0.019911985 102
+4 0.020978336 118
+4 0.020270010 118
+4 0.020800394 98
+4 0.023331698 118
+4 0.020625734 108
+4 0.024362590 45
+4 0.006712794 74
+4 0.008052322 209
+4 0.088262080 95
diff --git a/lib/iolog/regress/corpus/seed/timing/timing.3 b/lib/iolog/regress/corpus/seed/timing/timing.3
new file mode 100644
index 0000000..4034898
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/timing/timing.3
@@ -0,0 +1,988 @@
+4 0.004667517 65
+1 0.000204598 16384
+1 0.000232870 16384
+1 0.000182715 16384
+1 0.000233631 16384
+1 0.000180381 16384
+1 0.000175649 16384
+1 0.000175959 16384
+1 0.000214345 16384
+1 0.000184234 16384
+1 0.000227610 16384
+1 0.000185340 16384
+1 0.000176307 16384
+1 0.000175898 16384
+1 0.000268993 16384
+1 0.000183674 16384
+1 0.000215319 16384
+1 0.000175147 16384
+1 0.000175248 16384
+1 0.000175224 16384
+1 0.000215165 16384
+1 0.000186660 16384
+1 0.000175657 16384
+1 0.000212448 16384
+1 0.000176406 16384
+1 0.000176418 16384
+1 0.000175909 16384
+1 0.000233918 16384
+1 0.000175175 16384
+1 0.000210767 16384
+1 0.000176349 16384
+1 0.000175932 16384
+1 0.000223892 16384
+1 0.000204215 16384
+1 0.000182071 16384
+1 0.000174307 16384
+1 0.000212948 16384
+1 0.000174008 16384
+1 0.000183305 16384
+1 0.000210859 16384
+1 0.000173624 16384
+1 0.000174269 16384
+1 0.000173759 16384
+1 0.000211001 16384
+1 0.000188432 16384
+1 0.000208482 16384
+1 0.000173818 16384
+1 0.000173706 16384
+1 0.000172848 16384
+1 0.000219983 16384
+1 0.000173715 16384
+1 0.000173231 16384
+1 0.000207740 16384
+1 0.000172355 16384
+1 0.000173862 16384
+1 0.000218171 16384
+1 0.000172711 16384
+1 0.000171980 16384
+1 0.000173769 16384
+1 0.000209693 16384
+1 0.000182913 16384
+1 0.000213414 16384
+1 0.000174563 16384
+1 0.000176066 16384
+1 0.000178416 16384
+1 0.000211025 16384
+1 0.000184019 16384
+1 0.000172715 16384
+1 0.000211906 16384
+1 0.000172898 16384
+1 0.000172698 16384
+1 0.000172687 16384
+1 0.000219835 16384
+1 0.000175073 16384
+1 0.000172194 16384
+1 0.000210039 16384
+1 0.000172651 16384
+1 0.000180363 16384
+1 0.000207814 16384
+1 0.000181339 16384
+1 0.000172957 16384
+1 0.000210462 16384
+1 0.000173359 16384
+1 0.000183117 16384
+1 0.000211472 16384
+1 0.000172785 16384
+1 0.000173065 16384
+1 0.000172556 16384
+1 0.000219412 16384
+1 0.000175049 16384
+1 0.000172688 16384
+1 0.000212409 16384
+1 0.000173995 16384
+1 0.000173362 16384
+1 0.000217888 16384
+1 0.000174519 16384
+1 0.000179535 16384
+1 0.000210660 16384
+1 0.000173236 16384
+1 0.000172656 16384
+1 0.000218333 16384
+1 0.000175598 16384
+1 0.000173390 16384
+1 0.000174078 16384
+1 0.000210326 16384
+1 0.000182926 16384
+1 0.000173350 16384
+1 0.000211036 16384
+1 0.000174038 16384
+1 0.000173647 16384
+1 0.000173506 16384
+1 0.000219713 16384
+1 0.000173048 16384
+1 0.000216544 16384
+1 0.000173473 16384
+1 0.000173584 16384
+1 0.000217290 16384
+1 0.000221436 16384
+1 0.000181452 16384
+1 0.000175981 16384
+1 0.000216787 16384
+1 0.000176126 16384
+1 0.000192080 16384
+1 0.000218372 16384
+1 0.000176383 16384
+1 0.000175741 16384
+1 0.000176882 16384
+1 0.000211760 16384
+1 0.000180460 16384
+1 0.000171301 16384
+1 0.000217254 16384
+1 0.000171345 16384
+1 0.000171068 16384
+1 0.000217296 16384
+1 0.000171584 16384
+1 0.000171382 16384
+1 0.000211004 16384
+1 0.000171735 16384
+1 0.000171288 16384
+1 0.000217634 16384
+1 0.000171509 16384
+1 0.000171665 16384
+1 0.000171047 16384
+1 0.000232622 16384
+1 0.000200850 16384
+1 0.000186185 16384
+1 0.000236223 16384
+1 0.000189277 16384
+1 0.000184901 16384
+1 0.000218248 16384
+1 0.000186495 16384
+1 0.000197206 16384
+1 0.000211952 16384
+1 0.000175248 16384
+1 0.000173748 16384
+1 0.000174236 16384
+1 0.000222111 16384
+1 0.000174574 16384
+1 0.000174434 16384
+1 0.000212226 16384
+1 0.000174342 16384
+1 0.000184829 16384
+1 0.000213260 16384
+1 0.000173502 16384
+1 0.000173093 16384
+1 0.000221162 16384
+1 0.000174153 16384
+1 0.000182299 16384
+1 0.000210864 16384
+1 0.000203068 16384
+1 0.000219136 16384
+1 0.000174002 16384
+1 0.000213188 16384
+1 0.000183505 16384
+1 0.000172565 16384
+1 0.000209734 16384
+1 0.000174341 16384
+1 0.000172264 16384
+1 0.000221781 16384
+1 0.000174790 16384
+1 0.000172739 16384
+1 0.000174020 16384
+1 0.000221785 16384
+1 0.000172995 16384
+1 0.000222941 16384
+1 0.000173977 16384
+1 0.000172728 16384
+1 0.000173524 16384
+1 0.000214508 16384
+1 0.000180455 16384
+1 0.000173688 16384
+1 0.000218400 16384
+1 0.000173836 16384
+1 0.000173021 16384
+1 0.000174233 16384
+1 0.000211773 16384
+1 0.000173345 16384
+1 0.000172586 16384
+1 0.000209547 16384
+1 0.000173828 16384
+1 0.000177025 16384
+1 0.000219995 16384
+1 0.000172918 16384
+1 0.000173449 16384
+1 0.000209423 16384
+1 0.000181676 16384
+1 0.000183441 16384
+1 0.000209581 16384
+1 0.000173832 16384
+1 0.000173270 16384
+1 0.000172904 16384
+1 0.000210702 16384
+1 0.000182215 16384
+1 0.000189641 16384
+1 0.000284181 16384
+1 0.000175365 16384
+1 0.000172881 16384
+1 0.000228551 16384
+1 0.000183598 16384
+1 0.000212813 16384
+1 0.000171234 16384
+1 0.000171113 16384
+1 0.000265216 16384
+1 0.000256766 16384
+1 0.000177761 16384
+1 0.000176795 16384
+1 0.000216366 16384
+1 0.000176847 16384
+1 0.000176382 16384
+1 0.000196256 16384
+1 0.000185652 16384
+1 0.000191254 16384
+1 0.000184776 16384
+1 0.000217719 16384
+1 0.000196783 16384
+1 0.000214624 16384
+1 0.000176543 16384
+1 0.000176621 16384
+1 0.000176781 16384
+1 0.000214375 16384
+1 0.000187073 16384
+1 0.000175881 16384
+1 0.000214427 16384
+1 0.000176819 16384
+1 0.000186002 16384
+1 0.000223983 16384
+1 0.000173340 16384
+1 0.000180282 16384
+1 0.000175780 16384
+1 0.000216125 16384
+1 0.000176193 16384
+1 0.000234609 16384
+1 0.000175698 16384
+1 0.000174926 16384
+1 0.000175740 16384
+1 0.000213854 16384
+1 0.000176984 16384
+1 0.000186810 16384
+1 0.000210152 16384
+1 0.000174875 16384
+1 0.000174813 16384
+1 0.000175036 16384
+1 0.000226974 16384
+1 0.000174660 16384
+1 0.000174744 16384
+1 0.000204522 16384
+1 0.000174780 16384
+1 0.000174814 16384
+1 0.000221269 16384
+1 0.000188334 16384
+1 0.000175739 16384
+1 0.000209695 16384
+1 0.000193824 16384
+1 0.000188632 16384
+1 0.000210526 16384
+1 0.000174158 16384
+1 0.000174339 16384
+1 0.000174180 16384
+1 0.000206907 16384
+1 0.000182368 16384
+1 0.000173833 16384
+1 0.000209012 16384
+1 0.000173131 16384
+1 0.000172859 16384
+1 0.000172674 16384
+1 0.000219815 16384
+1 0.000182668 16384
+1 0.000212487 16384
+1 0.000173833 16384
+1 0.000173242 16384
+1 0.000221886 16384
+1 0.000174126 16384
+1 0.000173782 16384
+1 0.000173083 16384
+1 0.000212048 16384
+1 0.000173991 16384
+1 0.000183737 16384
+1 0.000212986 16384
+1 0.000175737 16384
+1 0.000171877 16384
+1 0.000173977 16384
+1 0.000212917 16384
+1 0.000183401 16384
+1 0.000220644 16384
+1 0.000174845 16384
+1 0.000173519 16384
+1 0.000173358 16384
+1 0.000221424 16384
+1 0.000174225 16384
+1 0.000174026 16384
+1 0.000181262 16384
+1 0.000181238 16384
+1 0.000179989 16384
+1 0.000234088 16384
+1 0.000174627 16384
+1 0.000174688 16384
+1 0.000175388 16384
+1 0.000214217 16384
+1 0.000182064 16384
+1 0.000175192 16384
+1 0.000221012 16384
+1 0.000175500 16384
+1 0.000173344 16384
+1 0.000212621 16384
+1 0.000182532 16384
+1 0.000174054 16384
+1 0.000213046 16384
+1 0.000178598 16384
+1 0.000172744 16384
+1 0.000174442 16384
+1 0.000224111 16384
+1 0.000174925 16384
+1 0.000173327 16384
+1 0.000212011 16384
+1 0.000174397 16384
+1 0.000183846 16384
+1 0.000211973 16384
+1 0.000174197 16384
+1 0.000181158 16384
+1 0.000211734 16384
+1 0.000174521 16384
+1 0.000185459 16384
+1 0.000210420 16384
+1 0.000173614 16384
+1 0.000174063 16384
+1 0.000173928 16384
+1 0.000221641 16384
+1 0.000174892 16384
+1 0.000173602 16384
+1 0.000213548 16384
+1 0.000173288 16384
+1 0.000174566 16384
+1 0.000221746 16384
+1 0.000173691 16384
+1 0.000172544 16384
+1 0.000221593 16384
+1 0.000174859 16384
+1 0.000174593 16384
+1 0.000221470 16384
+1 0.000174906 16384
+1 0.000174414 16384
+1 0.000174643 16384
+1 0.000180381 16384
+1 0.000228118 16384
+1 0.000174372 16384
+1 0.000172894 16384
+1 0.000174088 16384
+1 0.000210179 16384
+1 0.000173018 16384
+1 0.000183585 16384
+1 0.000212582 16384
+1 0.000174028 16384
+1 0.000180274 16384
+1 0.000210011 16384
+1 0.000181061 16384
+1 0.000171667 16384
+1 0.000212975 16384
+1 0.000173474 16384
+1 0.000174824 16384
+1 0.000174770 16384
+1 0.000259517 16384
+1 0.000175254 16384
+1 0.000174674 16384
+1 0.000211257 16384
+1 0.000173914 16384
+1 0.000173226 16384
+1 0.000218736 16384
+1 0.000174777 16384
+1 0.000174287 16384
+1 0.000173806 16384
+1 0.000223350 16384
+1 0.000182470 16384
+1 0.000173368 16384
+1 0.000210632 16384
+1 0.000173962 16384
+1 0.000174398 16384
+1 0.000173870 16384
+1 0.000219226 16384
+1 0.000174328 16384
+1 0.000173605 16384
+1 0.000207352 16384
+1 0.000175893 16384
+1 0.000181901 16384
+1 0.000210141 16384
+1 0.000174263 16384
+1 0.000174436 16384
+1 0.000173800 16384
+1 0.000218953 16384
+1 0.000182143 16384
+1 0.000209929 16384
+1 0.000181286 16384
+1 0.000175206 16384
+1 0.000175289 16384
+1 0.000211021 16384
+1 0.000184189 16384
+1 0.000173899 16384
+1 0.000208349 16384
+1 0.000173540 16384
+1 0.000173470 16384
+1 0.000218306 16384
+1 0.000174466 16384
+1 0.000173733 16384
+1 0.000174997 16384
+1 0.000208404 16384
+1 0.000183404 16384
+1 0.000216987 16384
+1 0.000174787 16384
+1 0.000172001 16384
+1 0.000174352 16384
+1 0.000210113 16384
+1 0.000174975 16384
+1 0.000181474 16384
+1 0.000208027 16384
+1 0.000220815 16384
+1 0.000182672 16384
+1 0.000177670 16384
+1 0.000226754 16384
+1 0.000176226 16384
+1 0.000176257 16384
+1 0.000213945 16384
+1 0.000177178 16384
+1 0.000184848 16384
+1 0.000227104 16384
+1 0.000176737 16384
+1 0.000176047 16384
+1 0.000213861 16384
+1 0.000176249 16384
+1 0.000192460 16384
+1 0.000213055 16384
+1 0.000176122 16384
+1 0.000175803 16384
+1 0.000176855 16384
+1 0.000213759 16384
+1 0.000183896 16384
+1 0.000176042 16384
+1 0.000215572 16384
+1 0.000177052 16384
+1 0.000176248 16384
+1 0.000176225 16384
+1 0.000232080 16384
+1 0.000175961 16384
+1 0.000214198 16384
+1 0.000176799 16384
+1 0.000175935 16384
+1 0.000223226 16384
+1 0.000176909 16384
+1 0.000176795 16384
+1 0.000176510 16384
+1 0.000214109 16384
+1 0.000176961 16384
+1 0.000186460 16384
+1 0.000211960 16384
+1 0.000176559 16384
+1 0.000175660 16384
+1 0.000176204 16384
+1 0.000219927 16384
+1 0.000189594 16384
+1 0.000214824 16384
+1 0.000176935 16384
+1 0.000176513 16384
+1 0.000176800 16384
+1 0.000224628 16384
+1 0.000176509 16384
+1 0.000175911 16384
+1 0.000214526 16384
+1 0.000185996 16384
+1 0.000177260 16384
+1 0.000222187 16384
+1 0.000176306 16384
+1 0.000175852 16384
+1 0.000176047 16384
+1 0.000213267 16384
+1 0.000187775 16384
+1 0.000223034 16384
+1 0.000178203 16384
+1 0.000176681 16384
+1 0.000176577 16384
+1 0.000211623 16384
+1 0.000187933 16384
+1 0.000176091 16384
+1 0.000213563 16384
+1 0.000176665 16384
+1 0.000175972 16384
+1 0.000221236 16384
+1 0.000177542 16384
+1 0.000176816 16384
+1 0.000176855 16384
+1 0.000214626 16384
+1 0.000176270 16384
+1 0.000187315 16384
+1 0.000213606 16384
+1 0.000185588 16384
+1 0.000175148 16384
+1 0.000211150 16384
+1 0.000175119 16384
+1 0.000186448 16384
+1 0.000212381 16384
+1 0.000177247 16384
+1 0.000175999 16384
+1 0.000176495 16384
+1 0.000222973 16384
+1 0.000175776 16384
+1 0.000176586 16384
+1 0.000212810 16384
+1 0.000176501 16384
+1 0.000176409 16384
+1 0.000223551 16384
+1 0.000177325 16384
+1 0.000185881 16384
+1 0.000212232 16384
+1 0.000176149 16384
+1 0.000182616 16384
+1 0.000216249 16384
+1 0.000183941 16384
+1 0.000179989 16384
+1 0.000176223 16384
+1 0.000212771 16384
+1 0.000187318 16384
+1 0.000336166 16384
+1 0.000219610 16384
+1 0.000176123 16384
+1 0.000176534 16384
+1 0.000176734 16384
+1 0.000224839 16384
+1 0.000176819 16384
+1 0.000222734 16384
+1 0.000177474 16384
+1 0.000176537 16384
+1 0.000225175 16384
+1 0.000177148 16384
+1 0.000176676 16384
+1 0.000176364 16384
+1 0.000211976 16384
+1 0.000176519 16384
+1 0.000186739 16384
+1 0.000213745 16384
+1 0.000176337 16384
+1 0.000175372 16384
+1 0.000175256 16384
+1 0.000191167 16384
+1 0.000227098 16384
+1 0.000203959 16384
+1 0.000194934 16384
+1 0.000214879 16384
+1 0.000174297 16384
+1 0.000184364 16384
+1 0.000215725 16384
+1 0.000173186 16384
+1 0.000174405 16384
+1 0.000173021 16384
+1 0.000212846 16384
+1 0.000181787 16384
+1 0.000173693 16384
+1 0.000211996 16384
+1 0.000174205 16384
+1 0.000175232 16384
+1 0.000222319 16384
+1 0.000174473 16384
+1 0.000173905 16384
+1 0.000174245 16384
+1 0.000222767 16384
+1 0.000174680 16384
+1 0.000217322 16384
+1 0.000175657 16384
+1 0.000172138 16384
+1 0.000173154 16384
+1 0.000181922 16384
+1 0.000211261 16384
+1 0.000184041 16384
+1 0.000173746 16384
+1 0.000243145 16384
+1 0.000179559 16384
+1 0.000176514 16384
+1 0.000228488 16384
+1 0.000177394 16384
+1 0.000177116 16384
+1 0.000176330 16384
+1 0.000223859 16384
+1 0.000182981 16384
+1 0.000227680 16384
+1 0.000177529 16384
+1 0.000177276 16384
+1 0.000176643 16384
+1 0.000213851 16384
+1 0.000184064 16384
+1 0.000178917 16384
+1 0.000183389 16384
+1 0.000213760 16384
+1 0.000176615 16384
+1 0.000177014 16384
+1 0.000222460 16384
+1 0.000177618 16384
+1 0.000177433 16384
+1 0.000176751 16384
+1 0.000220289 16384
+1 0.000183874 16384
+1 0.000223291 16384
+1 0.000176584 16384
+1 0.000175356 16384
+1 0.000176131 16384
+1 0.000238184 16384
+1 0.000193171 16384
+1 0.000174034 16384
+1 0.000215225 16384
+1 0.000174230 16384
+1 0.000174692 16384
+1 0.000175198 16384
+1 0.000220923 16384
+1 0.000174519 16384
+1 0.000173328 16384
+1 0.000210593 16384
+1 0.000175280 16384
+1 0.000223725 16384
+1 0.000174043 16384
+1 0.000172213 16384
+1 0.000174386 16384
+1 0.000210062 16384
+1 0.000172668 16384
+1 0.000182741 16384
+1 0.000209600 16384
+1 0.000173388 16384
+1 0.000174516 16384
+1 0.000204938 16384
+1 0.000219722 16384
+1 0.000186264 16384
+1 0.000175835 16384
+1 0.000216579 16384
+1 0.000176859 16384
+1 0.000185424 16384
+1 0.000256274 16384
+1 0.000177038 16384
+1 0.000177028 16384
+1 0.000177097 16384
+1 0.000218396 16384
+1 0.000176244 16384
+1 0.000186753 16384
+1 0.000216613 16384
+1 0.000177165 16384
+1 0.000175987 16384
+1 0.000176194 16384
+1 0.000224954 16384
+1 0.000176241 16384
+1 0.000179706 16384
+1 0.000215687 16384
+1 0.000176822 16384
+1 0.000176959 16384
+1 0.000238809 16384
+1 0.000176021 16384
+1 0.000176005 16384
+1 0.000215081 16384
+1 0.000176917 16384
+1 0.000176841 16384
+1 0.000226806 16384
+1 0.000176823 16384
+1 0.000176219 16384
+1 0.000176206 16384
+1 0.000215191 16384
+1 0.000187089 16384
+1 0.000175357 16384
+1 0.000215160 16384
+1 0.000175506 16384
+1 0.000176262 16384
+1 0.000176893 16384
+1 0.000234077 16384
+1 0.000179820 16384
+1 0.000216583 16384
+1 0.000179626 16384
+1 0.000177220 16384
+1 0.000176652 16384
+1 0.000227752 16384
+1 0.000176586 16384
+1 0.000176687 16384
+1 0.000214614 16384
+1 0.000177012 16384
+1 0.000195925 16384
+1 0.000217877 16384
+1 0.000176660 16384
+1 0.000176628 16384
+1 0.000176518 16384
+1 0.000215128 16384
+1 0.000187158 16384
+1 0.000225865 16384
+1 0.000176883 16384
+1 0.000176479 16384
+1 0.000176918 16384
+1 0.000224584 16384
+1 0.000180642 16384
+1 0.000176575 16384
+1 0.000244591 16384
+1 0.000178884 16384
+1 0.000174478 16384
+1 0.000226308 16384
+1 0.000174493 16384
+1 0.000174253 16384
+1 0.000176100 16384
+1 0.000215833 16384
+1 0.000176009 16384
+1 0.000183651 16384
+1 0.000223742 16384
+1 0.000174847 16384
+1 0.000174555 16384
+1 0.000213911 16384
+1 0.000182787 16384
+1 0.000174312 16384
+1 0.000213740 16384
+1 0.000175147 16384
+1 0.000174444 16384
+1 0.000174608 16384
+1 0.000222736 16384
+1 0.000174226 16384
+1 0.000174346 16384
+1 0.000216076 16384
+1 0.000174753 16384
+1 0.000182164 16384
+1 0.000217255 16384
+1 0.000182199 16384
+1 0.000176654 16384
+1 0.000184926 16384
+1 0.000214193 16384
+1 0.000184332 16384
+1 0.000175061 16384
+1 0.000214842 16384
+1 0.000174290 16384
+1 0.000175230 16384
+1 0.000174584 16384
+1 0.000222141 16384
+1 0.000175004 16384
+1 0.000221859 16384
+1 0.000215405 16384
+1 0.000174805 16384
+1 0.000184484 16384
+1 0.000212251 16384
+1 0.000173998 16384
+1 0.000179855 16384
+1 0.000214218 16384
+1 0.000173891 16384
+1 0.000183743 16384
+1 0.000213744 16384
+1 0.000173599 16384
+1 0.000173705 16384
+1 0.000172790 16384
+1 0.000220443 16384
+1 0.000176454 16384
+1 0.000174052 16384
+1 0.000182942 16384
+1 0.000182499 16384
+1 0.000182752 16384
+1 0.000218520 16384
+1 0.000174344 16384
+1 0.000174067 16384
+1 0.000221027 16384
+1 0.000174479 16384
+1 0.000173231 16384
+1 0.000219055 16384
+1 0.000173519 16384
+1 0.000173592 16384
+1 0.000187641 16384
+1 0.000180615 16384
+1 0.000221532 16384
+1 0.000173358 16384
+1 0.000173716 16384
+1 0.000212930 16384
+1 0.000173799 16384
+1 0.000173265 16384
+1 0.000220938 16384
+1 0.000174478 16384
+1 0.000174193 16384
+1 0.000218225 16384
+1 0.000175334 16384
+1 0.000174731 16384
+1 0.000221306 16384
+1 0.000173339 16384
+1 0.000172534 16384
+1 0.000174621 16384
+1 0.000211371 16384
+1 0.000184274 16384
+1 0.000173693 16384
+1 0.000210738 16384
+1 0.000172870 16384
+1 0.000173658 16384
+1 0.000174610 16384
+1 0.000227013 16384
+1 0.000174377 16384
+1 0.000173774 16384
+1 0.000216715 16384
+1 0.000174562 16384
+1 0.000184457 16384
+1 0.000212227 16384
+1 0.000174285 16384
+1 0.000172947 16384
+1 0.000172874 16384
+1 0.000209950 16384
+1 0.000183721 16384
+1 0.000173842 16384
+1 0.000181812 16384
+1 0.000209234 16384
+1 0.000173865 16384
+1 0.000174440 16384
+1 0.000219158 16384
+1 0.000173688 16384
+1 0.000186204 16384
+1 0.000187117 16384
+1 0.000224835 16384
+1 0.000186466 16384
+1 0.000215016 16384
+1 0.000173500 16384
+1 0.000172877 16384
+1 0.000173607 16384
+1 0.000212322 16384
+1 0.000183453 16384
+1 0.000173058 16384
+1 0.000212908 16384
+1 0.000174174 16384
+1 0.000173832 16384
+1 0.000220095 16384
+1 0.000174213 16384
+1 0.000173628 16384
+1 0.000173636 16384
+1 0.000214330 16384
+1 0.000181537 16384
+1 0.000218378 16384
+1 0.000176719 16384
+1 0.000173799 16384
+1 0.000175342 16384
+1 0.000180003 16384
+1 0.000180824 16384
+1 0.000206418 16384
+1 0.000180934 16384
+1 0.000213981 16384
+1 0.000173692 16384
+1 0.000174841 16384
+1 0.000219890 16384
+1 0.000174085 16384
+1 0.000178707 16384
+1 0.000173240 16384
+1 0.000212296 16384
+1 0.000183092 16384
+1 0.000223713 16384
+1 0.000174196 16384
+1 0.000174774 16384
+1 0.000176585 16384
+1 0.000213063 16384
+1 0.000181023 16384
+1 0.000174437 16384
+1 0.000212119 16384
+1 0.000174637 16384
+1 0.000174680 16384
+1 0.000172043 16384
+1 0.000225831 16384
+1 0.000174957 16384
+1 0.000173717 16384
+1 0.000204836 16384
+1 0.000174480 16384
+1 0.000174503 16384
+1 0.000227562 16384
+1 0.000174648 16384
+1 0.000173883 16384
+1 0.000210909 16384
+1 0.000175163 16384
+1 0.000185280 16384
+1 0.000188143 16384
+1 0.000213442 16384
+1 0.000175698 16384
+1 0.000174523 16384
+1 0.000173744 16384
+1 0.000222276 16384
+1 0.000173932 16384
+1 0.000174101 16384
+1 0.000228212 16384
+1 0.000179652 16384
+1 0.000182744 16384
+1 0.000219840 16384
+1 0.000171827 16384
+1 0.000172109 16384
+1 0.000213111 16384
+1 0.000175428 16384
+1 0.000182643 16384
+1 0.000180712 16384
+1 0.000212075 16384
+1 0.000174431 16384
+1 0.000174165 16384
+1 0.000173958 16384
+1 0.000221502 16384
+1 0.000174430 16384
+1 0.000172987 16384
+1 0.000213347 16384
+1 0.000179394 16384
+1 0.000184413 16384
+1 0.000221817 16384
+1 0.000173676 16384
+1 0.000173467 16384
+1 0.000211345 16384
+1 0.000173427 16384
+1 0.000183070 16384
+1 0.000214273 16384
+1 0.000173861 16384
+1 0.000172542 16384
+1 0.000172972 16384
+1 0.000212044 16384
+1 0.000179707 16384
+1 0.000173853 16384
+1 0.000214614 16384
+1 0.000175333 16384
+1 0.000174546 16384
+1 0.000219227 16384
+1 0.000182069 16384
+1 0.000174346 16384
+1 0.000213209 16384
+1 0.000174893 16384
+1 0.000173416 16384
+1 0.000220164 16384
+1 0.000174433 16384
+1 0.000173567 16384
+1 0.000174038 16384
+1 0.000211480 16384
+1 0.000181584 16384
+1 0.000174524 16384
+1 0.000212783 16384
+1 0.000173224 16384
+1 0.000173899 16384
+1 0.000173311 16384
+1 0.000227583 16384
+1 0.000173853 16384
+1 0.000181100 16384
+1 0.000210033 16384
+1 0.000173540 16384
+1 0.000173247 16384
+1 0.000216875 16384
+1 0.000176372 16384
+1 0.000174152 16384
+1 0.000173313 16384
+1 0.000180973 16384
+1 0.000219101 16384
+1 0.000174160 16384
+1 0.000173459 16384
+1 0.000208939 16384
+1 0.000173989 16384
+1 0.000173410 16384
+1 0.000218716 16384
+1 0.000177116 16384
+1 0.000182663 16384
+1 0.000212028 16384
+1 0.000173705 16384
+1 0.000181046 16384
+1 0.000209238 16384
+1 0.000174394 16384
+1 0.000174024 16384
+1 0.000173850 16384
+1 0.000210442 16384
+1 0.000181175 16384
+1 0.000171863 16384
+1 0.000211097 16384
+1 0.000174362 16384
+1 0.000174110 16384
+1 0.000174258 16384
+1 0.000222086 16384
+1 0.000173989 16384
+1 0.000232996 16384
+1 0.000178935 16384
+1 0.000174268 16384
+1 0.000224038 16384
+1 0.000174040 16384
+1 0.000174231 16384
+1 0.000174277 16384
+1 0.000216674 16384
+1 0.000175634 16384
+4 0.000634865 54
+1 0.000552527 10240
diff --git a/lib/iolog/regress/corpus/seed/timing/timing.4 b/lib/iolog/regress/corpus/seed/timing/timing.4
new file mode 100644
index 0000000..20e0bb0
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/timing/timing.4
@@ -0,0 +1,8 @@
+2 0.025750192 5
+0 0.670737828 2
+0 2.832110312 2
+0 0.903947334 2
+0 1.727798521 3
+0 2.040329883 2
+2 0.001192523 2
+1 0.001253839 77
diff --git a/lib/iolog/regress/corpus/seed/timing/timing.5 b/lib/iolog/regress/corpus/seed/timing/timing.5
new file mode 100644
index 0000000..53e6c24
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/timing/timing.5
@@ -0,0 +1,110 @@
+4 0.094338301 36
+4 0.000886452 454
+4 0.000419509 47
+3 0.578593257 1
+4 0.000401105 9
+3 0.239515513 1
+4 0.000346806 1
+3 0.087693564 1
+4 0.000347787 1
+3 0.143659822 1
+4 0.000358177 1
+3 0.144622999 1
+4 0.000365053 1
+3 0.334698655 1
+4 0.000383718 1
+3 0.143675707 1
+4 0.000490451 38
+3 0.607406896 1
+4 0.000371268 14
+3 0.215742108 1
+4 0.000405734 20
+3 0.167496479 1
+4 0.000397476 32
+3 0.231540616 2
+4 0.001466590 36
+4 0.000350286 42
+3 0.158274203 1
+4 0.000370821 60
+3 0.120308265 1
+4 0.000415876 15
+3 0.142813715 1
+4 0.000334956 44
+3 0.303764107 1
+4 0.000391847 8
+3 0.095659280 1
+4 0.000378759 1
+3 0.175643525 1
+4 0.000322526 1
+3 0.135538631 1
+4 0.000350139 1
+4 0.000387250 43
+4 0.000294911 14
+3 1.167339458 1
+4 0.000459546 34
+7 0.000701240 TSTP
+7 14.031400225 CONT
+4 0.000703876 7
+4 0.000318515 552
+3 0.519022507 1
+4 0.000353381 8
+3 0.151484068 1
+4 0.000408559 1
+3 0.111526674 1
+4 0.000332701 1
+3 0.640246014 1
+4 0.000595362 2
+3 0.262836266 1
+4 0.000548454 34
+3 0.431603931 1
+4 0.000412839 34
+7 0.000525770 TSTP
+7 14.791352365 CONT
+4 0.000694230 7
+4 0.000302349 493
+3 0.727405050 1
+4 0.000500700 34
+7 0.000535360 TSTP
+7 3.670976441 CONT
+4 0.000618883 7
+4 0.000329643 493
+3 0.726805533 1
+4 0.000401741 15
+3 0.169615608 1
+4 0.000404146 14
+3 0.149519005 1
+4 0.000346040 14
+3 0.153626768 1
+4 0.000374982 14
+3 10.982612173 1
+3 0.499604568 1
+4 0.000430040 54
+3 0.082890262 1
+3 0.083639576 1
+4 0.000372554 36
+3 0.083005173 1
+3 0.083770729 1
+4 0.000362184 30
+3 0.082958130 1
+3 0.083891314 1
+4 0.000406165 69
+3 0.083110106 1
+3 0.083892294 1
+4 0.000367886 54
+3 0.224878822 1
+3 0.197955553 1
+4 0.000374885 45
+3 1.639667508 1
+4 0.000391391 8
+3 0.127675700 1
+4 0.000336583 1
+3 0.159694034 1
+4 0.000460055 1
+4 0.000356674 57
+3 12.784074969 1
+4 0.000383899 8
+3 0.319071776 1
+4 0.000350990 1
+3 0.375753852 1
+4 0.000391679 1
+4 0.000470435 31
diff --git a/lib/iolog/regress/corpus/seed/timing/timing.6 b/lib/iolog/regress/corpus/seed/timing/timing.6
new file mode 100644
index 0000000..2cfb414
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/timing/timing.6
@@ -0,0 +1,15185 @@
+4 0.097693988 36
+4 0.000957658 581
+3 1.103319620 1
+4 0.000458372 9
+3 0.343116579 1
+4 0.000338600 1
+3 0.167807742 1
+4 0.000347723 1
+3 0.168370615 1
+4 0.000331790 1
+3 0.126841177 1
+4 0.000494776 21
+4 0.000389804 737
+3 3.911758825 1
+4 0.000589551 589
+3 1.199213488 1
+4 0.000571867 671
+3 0.175283013 1
+4 0.000551106 788
+3 0.927605729 1
+4 0.000592528 778
+3 0.727361437 1
+4 0.000600088 810
+3 0.151449161 1
+4 0.000549159 703
+3 0.151365424 1
+4 0.000521802 579
+3 0.175504252 1
+4 0.000572822 841
+3 1.479559831 1
+4 0.000566667 671
+3 1.215437518 1
+4 0.000560614 732
+3 6.359874366 1
+4 0.000586055 517
+3 0.711069519 1
+4 0.000624372 678
+3 1.967625161 1
+4 0.000587631 788
+3 2.959415103 1
+4 0.000467050 52
+3 0.258284691 1
+4 0.000359406 17
+3 0.150663754 1
+4 0.000345830 16
+3 0.629841487 1
+3 0.130078374 1
+4 0.000427154 28
+3 1.573712476 1
+4 0.000597951 683
+3 0.679455332 1
+4 0.000624382 625
+3 0.863325943 1
+4 0.000589350 849
+3 0.871257287 1
+4 0.000377259 15
+3 0.500679027 1
+4 0.000338887 15
+3 0.082915074 1
+4 0.000418604 17
+3 0.082596070 1
+4 0.000321263 17
+3 0.083131776 1
+4 0.000330500 17
+3 0.083371296 1
+4 0.000345874 15
+3 0.083108756 1
+4 0.000389047 15
+3 0.082748138 1
+4 0.000315527 16
+3 0.083950965 1
+4 0.000325339 16
+3 0.548314643 1
+4 0.000410020 17
+3 0.429723783 1
+4 0.001632651 37
+4 0.000426417 133
+3 0.693988537 1
+4 0.000351760 16
+3 0.463602549 1
+4 0.000356594 10
+3 0.415613181 1
+4 0.000366763 1
+3 0.135780117 1
+4 0.000335017 1
+3 0.175462207 1
+4 0.000330054 1
+3 0.079900650 1
+4 0.000334757 1
+3 0.103456346 1
+4 0.000319517 1
+3 0.103817387 1
+4 0.000323711 1
+3 0.063555555 1
+4 0.000319964 1
+3 0.119579686 1
+4 0.000404602 1
+3 0.223797910 1
+4 0.000389022 40
+3 2.503757937 1
+4 0.000390701 10
+3 0.055447548 1
+4 0.000533591 690
+3 2.903881053 1
+4 0.000568568 726
+3 0.145177548 1
+4 0.000362889 102
+3 1.894563020 1
+4 0.000338633 18
+3 0.168988785 1
+4 0.000374107 18
+3 0.173551488 1
+4 0.000384121 17
+3 0.161628071 1
+4 0.000403103 18
+3 0.149569901 1
+4 0.000370231 17
+3 0.201795897 1
+4 0.000371537 17
+3 0.277452123 1
+3 0.312120348 1
+4 0.000382358 65
+3 0.135528556 1
+4 0.000376779 79
+3 0.655753048 2
+4 0.000393158 103
+3 0.311981813 1
+4 0.000358735 18
+3 0.153241402 1
+4 0.000357208 18
+3 0.149367912 1
+4 0.000341365 17
+3 0.153758664 1
+4 0.000409446 18
+3 0.141572461 1
+4 0.000334930 17
+3 0.281753655 1
+4 0.000313237 17
+3 0.253785106 1
+3 0.048044598 1
+4 0.000390744 29
+3 0.199848389 1
+4 0.000351924 18
+3 0.095365075 1
+4 0.000367343 18
+3 0.103384570 1
+4 0.000330248 18
+3 0.087929267 1
+4 0.000363207 18
+3 0.263566078 2
+4 0.000365425 28
+3 0.129673483 1
+4 0.000418293 18
+3 0.245509930 1
+3 0.072023907 1
+4 0.000346915 27
+3 0.233641617 1
+4 0.000371518 18
+3 0.149968246 1
+4 0.000329324 18
+3 0.750253477 1
+4 0.109987655 37
+3 24.356082499 2
+4 0.000575072 18
+3 0.311960778 1
+4 0.000363365 17
+3 6.328346132 1
+4 0.000383670 31
+3 0.374564260 1
+4 0.000364229 31
+3 4.263853812 1
+4 0.000385394 31
+3 0.072217819 1
+4 0.000359701 31
+3 0.142867118 1
+4 0.000386346 31
+3 0.127731426 1
+4 0.000511355 31
+3 0.055387421 1
+4 0.000385155 31
+3 1.695812701 1
+4 0.000358800 31
+3 0.697693334 1
+4 0.109968812 31
+3 3.968687583 1
+4 0.000582462 652
+3 2.087163132 1
+4 0.000600691 922
+3 1.671266499 1
+4 0.000436508 36
+3 0.500227380 1
+4 0.000409164 78
+3 0.083208834 1
+4 0.000483458 69
+3 0.082631972 1
+4 0.000394210 73
+3 0.083382084 1
+4 0.000400565 84
+3 13.617030561 1
+4 0.000354061 15
+3 0.500733232 1
+4 0.000347347 15
+3 0.082671126 1
+4 0.000355244 15
+3 0.082945476 1
+4 0.000365822 18
+3 0.082683300 1
+4 0.000403621 17
+3 0.083034469 1
+4 0.000356155 15
+3 0.083001633 1
+4 0.000378724 15
+3 0.082987035 1
+4 0.000356646 15
+3 0.083172601 1
+4 0.000347790 17
+3 0.082982191 1
+4 0.000354769 18
+3 0.083231707 1
+4 0.000356674 16
+3 0.083455577 1
+4 0.000375342 16
+3 0.082774961 1
+4 0.000345080 16
+3 0.083148577 1
+4 0.000372898 17
+3 0.082488084 1
+4 0.000351168 18
+3 0.361137018 1
+4 0.000520394 16
+3 0.557563133 1
+4 0.000365756 16
+3 0.217686213 1
+4 0.000405765 16
+3 0.213411640 1
+4 0.000437376 16
+3 0.201749904 1
+4 0.000417367 16
+3 1.077644672 1
+3 0.183765838 1
+3 0.114281411 1
+4 0.000415479 29
+3 1.797684026 1
+4 0.000592681 817
+3 2.423564964 1
+4 0.000635387 721
+3 0.735894059 1
+4 0.000366561 16
+3 0.499433634 1
+4 0.000403990 18
+3 0.083697754 1
+4 0.000353510 16
+3 0.082821690 1
+4 0.000460907 16
+3 0.083470466 1
+4 0.000391016 18
+3 0.351749864 1
+4 0.000435746 219
+3 0.335662878 1
+4 0.000385166 36
+3 0.455599429 2
+4 0.000450086 32
+3 0.311480720 1
+3 0.130132593 1
+4 0.000422315 30
+3 0.141538312 1
+4 0.000350580 18
+3 0.161698419 1
+4 0.000450382 16
+3 0.149595861 1
+4 0.000357490 16
+3 0.216118106 1
+4 0.000392863 80
+3 0.287025425 1
+4 0.000368499 16
+3 0.217810528 1
+4 0.000368675 16
+3 0.173583780 1
+4 0.000612887 16
+3 0.185363502 1
+4 0.000357218 16
+3 0.558456948 1
+4 0.000384082 18
+3 0.478831088 1
+4 0.000373041 47
+3 0.143904945 1
+4 0.000423017 19
+3 0.143222621 1
+4 0.000362659 17
+3 1.143703843 1
+4 0.000371411 18
+3 0.167600427 1
+4 0.000358131 18
+3 0.175738166 1
+4 0.000372615 18
+3 0.119668569 1
+4 0.000396472 18
+3 0.095593535 1
+4 0.000371665 18
+3 0.191668990 1
+4 0.000415434 18
+3 0.215453670 1
+4 0.000353548 18
+3 0.215843292 1
+4 0.000368685 18
+3 0.543724152 1
+4 0.000363077 18
+3 0.423428920 1
+4 0.000565616 18
+3 0.119487325 1
+4 0.000392118 18
+3 0.135715995 1
+4 0.000360686 18
+3 0.071574120 1
+4 0.000439295 18
+3 0.191534353 1
+4 0.000349726 18
+3 0.231687599 1
+4 0.000350854 18
+3 0.247590333 1
+4 0.000349565 18
+3 0.399664247 1
+4 0.000399287 17
+3 0.199694033 1
+4 0.000399199 18
+3 0.103461914 1
+4 0.000385370 18
+3 0.095701982 1
+4 0.000393397 18
+3 0.295621485 1
+4 0.000348993 19
+3 0.144437413 1
+4 0.000379088 18
+3 0.198764313 1
+4 0.000397818 18
+3 12.245000582 1
+3 0.067286171 1
+4 0.000930451 647
+3 1.271066901 1
+4 0.000611308 785
+3 0.967396885 1
+4 0.000391811 9
+3 2.013803015 12
+4 0.000359778 12
+3 0.354058672 1
+4 0.000442726 15
+4 0.000353259 38
+3 0.454372890 1
+4 0.000353679 43
+3 0.201776929 1
+4 0.000449372 21
+3 0.165645069 1
+4 0.000388749 56
+4 0.000394368 7
+3 0.369116907 1
+4 0.000346666 43
+3 0.381642743 1
+4 0.000350900 21
+3 0.489700692 1
+4 0.000403145 56
+4 0.000284088 7
+3 0.357448445 1
+4 0.000432074 43
+3 1.625632487 1
+4 0.000561739 21
+3 2.749500295 1
+4 0.000382505 32
+3 0.127541732 1
+4 0.000349587 17
+3 0.879715291 1
+4 0.000422238 18
+3 0.079504711 1
+4 0.000358804 18
+3 0.071640554 1
+4 0.000462190 17
+3 1.511581913 1
+4 0.000370736 18
+3 0.137723663 1
+4 0.000576506 18
+3 0.157423583 1
+4 0.000359301 18
+3 0.111569388 1
+4 0.000370080 19
+3 0.175788910 1
+4 0.000390579 18
+3 0.127548586 1
+4 0.000517405 16
+3 0.087543039 1
+4 0.000389857 13
+3 0.087475036 1
+4 0.000385001 11
+3 0.263652341 1
+4 0.000362769 11
+3 0.079606457 1
+4 0.000456234 13
+3 0.151586763 1
+4 0.000576884 16
+3 0.119449667 1
+4 0.000391357 18
+3 0.248391442 1
+4 0.000348267 18
+3 0.070873604 1
+4 0.000395821 19
+3 0.031479523 1
+4 0.000339832 18
+3 0.215879653 1
+4 0.000371564 18
+3 0.208675804 1
+4 0.000364165 18
+3 0.781127774 1
+4 0.110104180 31
+3 0.347449927 1
+4 0.000391058 17
+3 0.759576804 1
+4 0.000399054 17
+3 0.719475822 1
+4 0.000363481 16
+3 0.209764674 1
+4 0.000420853 18
+3 0.181543921 1
+4 0.000446865 18
+3 0.695649553 1
+4 0.000364348 17
+3 5.655914971 1
+4 0.000371102 17
+3 0.501146264 1
+4 0.000390485 19
+3 0.082334811 1
+4 0.000389853 104
+3 0.082770985 1
+4 0.000640857 35
+3 0.082634854 1
+4 0.000391535 63
+3 0.082831129 1
+4 0.000395020 74
+3 0.083338259 1
+4 0.000765883 37
+3 0.305557932 1
+4 0.000358155 22
+3 0.500134468 1
+4 0.000373010 20
+3 0.082875224 1
+4 0.000369529 17
+3 0.083206683 1
+4 0.000650077 20
+3 0.820266736 1
+4 0.000372327 17
+3 0.500281203 1
+4 0.000356297 20
+3 0.083495657 1
+4 0.000352191 20
+3 0.082911125 1
+4 0.000345727 17
+3 0.084251862 1
+4 0.000421566 63
+3 0.198985382 1
+4 0.000347753 17
+3 0.169733060 1
+4 0.000561367 22
+3 0.165295001 1
+4 0.000351808 20
+3 2.623960816 1
+3 0.199877174 1
+3 0.154622991 1
+4 0.000424027 149
+3 0.116976645 1
+4 0.000356668 39
+3 0.500771628 1
+4 0.000453280 18
+3 0.083310622 1
+4 0.000333387 16
+3 0.083360523 1
+4 0.000588696 16
+3 0.083278747 1
+4 0.000364923 16
+3 0.083317744 1
+4 0.000363486 16
+3 0.082785265 1
+4 0.000334722 17
+3 0.083134633 1
+4 0.000327780 18
+3 0.388953653 1
+4 0.000397659 17
+3 0.279631899 1
+4 0.000443440 116
+3 0.735498889 1
+4 0.000402995 40
+3 0.161654066 1
+4 0.000360349 18
+3 0.645690164 1
+3 0.122095192 1
+4 0.000550745 75
+3 0.861346110 1
+4 0.000368374 18
+3 0.297657683 1
+4 0.000409950 16
+3 0.221573357 1
+4 0.000359706 17
+3 0.201590265 1
+4 0.000420145 18
+3 0.725891565 1
+4 0.000410403 94
+3 2.343419099 1
+3 0.138014095 1
+4 0.000406190 75
+3 0.149528893 1
+4 0.000376405 18
+3 0.233967970 1
+4 0.000362616 16
+3 0.181388607 1
+4 0.000375845 17
+3 0.169715363 1
+4 0.000358644 18
+3 0.421516995 1
+4 0.000423347 16
+3 0.223600858 1
+4 0.000351994 16
+3 0.169858347 1
+4 0.000372798 18
+3 0.165442069 1
+4 0.000437843 18
+3 47.612015956 1
+4 0.000420777 17
+3 7.645117521 1
+4 0.000357043 17
+3 0.203064792 1
+4 0.000404651 19
+3 0.148078594 1
+4 0.000372767 20
+3 14.800360987 1
+4 0.000372152 19
+3 0.193409434 1
+4 0.000360058 20
+3 0.181573590 1
+4 0.000334749 17
+3 4.672137645 1
+4 0.000547796 17
+3 0.201216303 1
+4 0.000350221 17
+3 0.493727268 1
+4 0.000394587 79
+3 1.239531925 1
+4 0.000411232 17
+3 0.201577596 1
+4 0.000363153 17
+3 0.181839196 1
+4 0.000365743 17
+3 0.217580259 1
+4 0.000419291 17
+3 0.413603793 1
+4 0.000389252 17
+3 4.879696734 1
+3 0.087993182 1
+4 0.000359318 28
+3 1.183741831 1
+4 0.000392000 18
+3 0.072371680 1
+4 0.000344036 18
+3 0.102840326 1
+4 0.000339979 18
+3 0.263644252 1
+4 0.000364716 18
+3 0.239809832 1
+4 0.000367180 107
+3 1.841911098 1
+4 0.109988327 33
+3 0.183660214 1
+4 0.000468781 9
+3 0.439556740 1
+4 0.000343767 1
+3 0.455845269 1
+4 0.000558674 54
+3 0.735274963 1
+4 0.000346882 9
+3 0.343642094 1
+4 0.000339960 1
+3 1.135630546 1
+4 0.000319323 1
+3 0.336150973 1
+4 0.002246722 58
+3 0.725368029 1
+4 0.000365124 9
+3 0.513883520 1
+4 0.000327517 1
+3 0.245487314 1
+4 0.000376272 1
+3 0.207695699 1
+4 0.000583922 779
+3 3.047550138 1
+3 0.129914536 1
+4 0.000361284 30
+3 0.517742428 1
+4 0.000876578 750
+3 0.153144700 1
+4 0.000827063 111
+3 1.077031634 1
+4 0.000385969 71
+3 0.671823909 1
+4 0.000700510 18
+3 0.177114177 1
+4 0.000365033 18
+3 0.165687178 1
+4 0.000364717 17
+3 0.351744220 1
+3 0.071908205 1
+4 0.000407900 28
+3 0.151677345 1
+4 0.000736606 18
+3 0.079541471 1
+4 0.000340519 18
+3 0.063463155 1
+4 0.000367949 18
+3 0.223506778 1
+4 0.000413034 18
+3 0.191692925 1
+4 0.000356857 26
+3 0.731677511 1
+4 0.109976927 33
+3 0.637929593 1
+4 0.000343755 17
+3 2.143779663 1
+4 0.000397634 4
+3 1.194158239 1
+4 0.000365274 4
+3 0.333180352 1
+4 0.000422079 17
+3 0.153395992 1
+4 0.000325371 17
+3 0.277789897 1
+4 0.000338965 4
+3 2.791906961 1
+4 0.000353063 17
+3 0.447635092 1
+3 0.138080657 1
+4 0.000566001 123
+3 0.253283500 1
+4 0.000734297 18
+3 2.401408669 1
+4 0.000329021 17
+3 0.229622809 1
+4 0.000368301 17
+3 0.249743461 1
+4 0.000332259 18
+3 1.405520404 1
+4 0.000626065 17
+3 0.513922219 1
+4 0.000352021 4
+3 0.317143072 1
+3 0.096174521 1
+4 0.000367483 33
+3 0.289500737 1
+4 0.000337331 18
+3 0.141681003 1
+4 0.000524692 18
+3 0.137672726 1
+4 0.000685531 18
+3 0.133085948 1
+4 0.000369897 18
+3 0.231827680 1
+4 0.000447277 18
+3 0.095501521 1
+4 0.000366060 18
+3 0.119494082 1
+4 0.001318263 18
+3 0.086667164 1
+4 0.000415062 19
+3 0.279538386 1
+4 0.000366880 18
+3 0.111882109 1
+4 0.000655035 18
+3 0.151184959 1
+4 0.000339245 18
+3 1.025459480 1
+3 0.006208551 1
+4 0.000357062 24
+3 0.219848723 1
+4 0.000409328 17
+3 3.732349804 1
+4 0.000364343 33
+3 0.593127057 13
+4 0.000410474 31
+3 0.797100093 1
+4 0.109976757 36
+3 1.778343138 1
+4 0.000499455 19
+3 0.217486897 1
+4 0.000362913 20
+3 1.989787928 1
+3 0.138144962 1
+4 0.000396217 89
+3 0.117343236 1
+4 0.000350336 18
+3 0.185752941 1
+4 0.000436495 16
+3 0.181922256 1
+4 0.000521924 16
+3 1.039959830 1
+4 0.000421118 16
+3 0.302818771 1
+3 0.121940521 1
+4 0.000714028 29
+3 0.197500732 1
+4 0.000364824 41
+3 1.223352169 1
+4 0.000384389 98
+3 0.368054015 1
+3 0.145929723 1
+4 0.000360153 22
+3 0.349490946 1
+4 0.000403415 18
+3 0.185711754 1
+4 0.000411094 18
+3 3.309560066 1
+4 0.000424639 17
+3 0.201622600 1
+4 0.000332911 17
+3 0.165514358 1
+4 0.000442890 18
+3 0.161627298 1
+4 0.000349309 17
+3 0.174031062 1
+4 0.000359363 17
+3 0.233245167 1
+4 0.000367185 17
+3 0.421696528 1
+4 0.000411396 17
+3 0.137662000 1
+4 0.000391667 17
+3 0.149641485 1
+4 0.000356515 18
+3 0.167537597 1
+4 0.000361277 24
+3 0.263817838 1
+4 0.000694390 31
+3 0.087126940 1
+4 0.000318414 31
+3 0.047574605 1
+4 0.000421695 31
+3 0.199647884 1
+4 0.000311776 31
+3 0.167877106 1
+4 0.000365130 31
+3 0.167451081 1
+4 0.000321456 31
+3 0.689076734 1
+4 0.110105163 33
+3 0.584921459 1
+4 0.000348307 9
+3 0.143224088 1
+4 0.000343586 1
+3 0.071732407 1
+4 0.000409628 1
+4 0.000372659 70
+3 0.655337176 1
+4 0.000404457 35
+3 0.499593688 1
+4 0.000366052 22
+3 0.083397439 1
+4 0.000368501 20
+3 0.083071213 1
+4 0.000340792 16
+3 0.083428883 1
+4 0.000350381 16
+3 0.083093697 1
+4 0.000392045 17
+3 0.083057376 1
+4 0.000365675 16
+3 0.083710948 1
+4 0.000327269 18
+3 0.083119476 1
+4 0.000474101 85
+3 0.083493053 1
+4 0.000360764 47
+3 0.082641058 1
+4 0.000398974 46
+3 0.083186621 1
+4 0.000365016 35
+3 0.083157636 1
+4 0.000398605 55
+3 0.082965738 1
+4 0.000428731 55
+3 0.160742908 1
+4 0.000439591 20
+3 0.500151554 1
+4 0.000351208 17
+3 0.084287672 1
+4 0.000493732 19
+3 0.082375156 1
+4 0.000384640 18
+3 0.082970019 1
+4 0.000397199 16
+3 0.082867805 1
+4 0.000318173 20
+3 0.083465407 1
+4 0.000390887 20
+3 0.082803369 1
+4 0.000334778 17
+3 0.083401403 1
+4 0.000375336 17
+3 0.082724495 1
+4 0.000320315 20
+3 0.247278331 1
+4 0.000447587 20
+3 0.575539980 1
+4 0.000355606 20
+3 0.185633872 1
+4 0.000356683 20
+3 0.149543565 1
+4 0.000362475 20
+3 0.439731864 1
+4 0.000424684 20
+3 0.233648427 1
+4 0.000350978 20
+3 0.213624195 1
+4 0.000395175 20
+3 0.225668560 1
+4 0.000421855 17
+3 0.221519026 1
+4 0.000369391 17
+3 0.209697790 1
+4 0.000352732 20
+3 0.229431459 1
+4 0.000408315 16
+3 0.233795367 1
+4 0.000353754 19
+3 0.349714972 1
+4 0.000374089 16
+3 0.499556051 1
+4 0.000350045 20
+3 0.082976420 1
+4 0.000426476 20
+3 0.082721495 1
+4 0.000346098 17
+3 0.082736431 1
+4 0.000369046 17
+3 0.083222016 1
+4 0.000406594 20
+3 0.083347906 1
+4 0.000343270 20
+3 0.083681978 1
+4 0.000476449 20
+3 0.082863415 1
+4 0.000529778 20
+3 0.443298219 1
+4 0.000822688 22
+3 0.729154569 1
+4 0.000334348 20
+3 0.237781665 1
+4 0.000355457 20
+3 0.249570764 1
+4 0.000354909 20
+3 0.221637136 1
+4 0.000349387 17
+3 0.217649492 1
+4 0.000389379 17
+3 0.213410528 1
+4 0.000345541 20
+3 0.257915898 1
+4 0.000375323 16
+3 0.317549640 1
+4 0.000351138 19
+3 0.327647625 1
+4 0.000508773 16
+3 0.499759639 1
+4 0.000351912 20
+3 0.083489529 1
+4 0.000340082 20
+3 0.083360580 1
+4 0.000341345 17
+3 0.083050464 1
+4 0.000348861 17
+3 0.083594027 1
+4 0.000410636 20
+3 0.083859543 1
+4 0.000339867 20
+3 0.378370667 1
+4 0.000353882 20
+3 26.654551214 2
+4 0.000299370 1
+4 0.000385007 20
+3 0.185788276 1
+4 0.000347829 19
+3 0.165558740 1
+4 0.000378265 18
+3 0.177115827 1
+4 0.000434495 19
+3 0.165615248 1
+4 0.000539262 19
+3 0.167652319 1
+4 0.000582877 17
+3 0.185338981 1
+4 0.000352150 16
+3 0.149631534 1
+4 0.000340936 16
+3 0.327728843 1
+4 0.000355118 16
+3 0.207710858 1
+4 0.000356196 22
+3 0.247467447 1
+4 0.000408781 27
+3 0.730114735 1
+4 0.110011184 32
+3 0.639487397 1
+4 0.000361215 30
+3 0.239789830 1
+4 0.000414086 27
+3 0.143501290 1
+4 0.000357619 27
+3 0.137600846 1
+4 0.000349030 29
+3 0.117672637 1
+4 0.000345332 27
+3 0.335762608 1
+4 0.000371813 16
+3 0.151515079 1
+4 0.000333398 17
+3 0.687814969 1
+4 0.000343303 27
+3 0.009771867 1
+4 0.000327767 27
+3 0.437553675 1
+4 0.000342484 16
+3 0.319573265 2
+4 0.000350629 35
+3 0.175819045 1
+4 0.000402475 30
+3 0.439484588 1
+4 0.000423719 39
+3 0.709999823 1
+4 0.000148519 17
+4 0.109827205 30
+3 8.507894554 1
+4 0.000410327 10
+3 0.151626335 1
+4 0.000353842 1
+3 0.087531531 1
+4 0.000371017 1
+4 0.000383910 69
+3 26.896906288 1
+4 0.000458838 38
+3 0.184859903 1
+4 0.000353687 18
+3 0.149756379 1
+4 0.000376787 19
+3 0.137592999 1
+4 0.000388187 18
+3 0.133791741 1
+4 0.000365782 22
+3 0.385421417 1
+4 0.000438732 20
+3 0.181646957 1
+4 0.000398813 20
+3 0.193545413 1
+4 0.000339360 20
+3 0.189661040 1
+4 0.000577231 17
+3 0.201388878 1
+4 0.000354544 17
+3 0.181736570 1
+4 0.000359366 17
+3 0.201709891 1
+4 0.000362687 17
+3 0.181657511 1
+4 0.000434378 19
+3 0.287459023 1
+4 0.000347569 20
+3 0.499939467 1
+4 0.000399194 17
+3 0.083057931 1
+4 0.000326400 17
+3 0.083236239 1
+4 0.000434921 17
+3 0.083397703 1
+4 0.000359935 17
+3 0.082995075 1
+4 0.000348933 20
+3 0.083447945 1
+4 0.000441606 20
+3 0.082804793 1
+4 0.000374644 20
+3 0.328091598 1
+4 0.000353006 20
+3 0.749778667 1
+3 0.159831338 1
+3 0.138127251 1
+4 0.000507113 453
+3 2.181672845 1
+4 0.000491811 452
+3 0.703366636 1
+3 0.199981256 1
+4 0.000352191 41
+3 0.567809983 1
+4 0.000527156 16
+3 0.499777301 1
+4 0.000341032 16
+3 0.083424938 1
+4 0.000359035 16
+3 0.083015258 1
+4 0.000314614 16
+3 0.083460885 1
+4 0.000361793 16
+3 0.083777579 1
+4 0.000313755 16
+3 0.083579493 1
+4 0.000367356 16
+3 0.083140437 1
+4 0.000317726 16
+3 0.278778522 1
+4 0.000341987 19
+3 0.141637962 1
+3 0.144050458 1
+3 0.127942512 1
+3 0.155207765 1
+4 0.000490014 479
+3 0.748564240 1
+4 0.000373697 40
+3 0.655960408 1
+4 0.000679698 869
+3 0.646826081 1
+4 0.000418888 15
+3 0.500527307 1
+4 0.000346354 15
+3 0.081843651 1
+4 0.000374311 17
+3 0.083519997 1
+4 0.000347824 17
+3 0.083477961 1
+4 0.000344511 15
+3 0.083426619 1
+4 0.000355385 15
+3 0.082727163 1
+4 0.000347717 15
+3 0.082932280 1
+4 0.000389440 17
+3 0.083334199 1
+4 0.000622308 19
+3 0.082558753 1
+4 0.000355512 16
+3 0.082872242 1
+4 0.000351363 16
+3 0.260990699 1
+4 0.000542866 646
+3 1.655439535 1
+4 0.000819821 437
+3 0.806961778 1
+4 0.000393280 66
+3 0.775566971 1
+4 0.000423759 18
+3 0.783885933 1
+4 0.000485141 363
+3 1.831723483 1
+4 0.000554379 40
+3 0.279058688 1
+4 0.000359222 15
+3 0.281709081 1
+4 0.000352527 17
+3 0.213643780 1
+4 0.000615478 23
+3 0.175421229 1
+4 0.000702794 32
+3 0.223239931 1
+4 0.000612203 32
+3 0.151359913 1
+4 0.000733272 32
+3 0.055356863 1
+4 0.000504130 32
+3 0.063391699 1
+4 0.000438785 32
+3 0.343892463 2
+4 0.000677091 23
+3 0.119234648 1
+4 0.000610279 17
+3 1.159306399 1
+4 0.000532996 10
+3 0.135332780 1
+4 0.000370068 1
+3 0.119678333 1
+4 0.000371365 1
+4 0.000295812 53
+4 0.000412108 16
+3 1.455822582 1
+4 0.000619925 646
+3 0.862826551 1
+4 0.000884052 592
+3 2.015014662 1
+4 0.000601988 628
+3 1.559569350 1
+4 0.000797895 926
+3 1.839221425 1
+4 0.000452782 47
+3 0.499724782 1
+4 0.000394463 34
+3 0.083061436 1
+4 0.000461010 74
+3 0.083213071 1
+4 0.000394094 72
+3 0.082597592 1
+4 0.000629094 87
+3 1.210968921 1
+4 0.000429352 47
+3 0.498607568 1
+4 0.000631607 34
+3 0.082584482 1
+4 0.000639306 64
+3 0.083305880 1
+4 0.000400040 72
+3 0.083135273 1
+4 0.000621457 104
+3 0.082893886 1
+4 0.000670785 47
+3 3.940356908 1
+4 0.000388271 34
+3 0.499602664 1
+4 0.000411279 56
+3 0.082931528 1
+4 0.000386802 72
+3 0.192151484 1
+4 0.000412085 17
+3 0.500050387 1
+4 0.000354066 17
+3 0.082906636 1
+4 0.000379668 18
+3 0.083693206 1
+4 0.000423020 20
+3 0.082953035 1
+4 0.000441869 18
+3 0.168429833 1
+4 0.000500791 18
+3 0.171526741 1
+4 0.000367870 19
+3 0.179690436 1
+4 0.000467217 16
+3 0.215673132 1
+4 0.000363513 18
+3 0.500350987 1
+4 0.000410286 20
+3 0.083205181 1
+4 0.000333549 18
+3 0.082500549 1
+4 0.000329966 17
+3 0.083050700 1
+4 0.000395420 17
+3 0.082862144 1
+4 0.000335598 18
+3 0.082684797 1
+4 0.000383548 20
+3 0.274747992 1
+4 0.000613396 839
+3 8.831964575 1
+4 0.000640423 801
+3 1.631181039 1
+4 0.000375831 17
+3 1.305627476 1
+4 0.000428633 15
+3 0.497733854 1
+4 0.000360959 15
+3 0.083122017 1
+4 0.000368287 15
+3 0.083642407 1
+4 0.000333844 15
+3 0.083295622 1
+4 0.000370535 16
+3 1.736553561 1
+4 0.000629246 838
+3 1.335539707 1
+4 0.000438005 16
+3 0.499718772 1
+4 0.000376280 18
+3 0.082613486 1
+4 0.000373838 16
+3 0.083636145 1
+4 0.000364210 16
+3 0.082920470 1
+4 0.000359328 16
+3 0.456951382 1
+4 0.000352142 16
+3 0.201656565 1
+4 0.000439855 16
+3 0.205465187 1
+4 0.000371276 16
+3 0.297745871 1
+4 0.000412243 16
+3 0.469760981 1
+4 0.000450415 18
+3 0.695465699 1
+4 0.000564386 801
+3 1.519622937 1
+4 0.000587351 836
+3 1.439344375 1
+4 0.000483671 115
+3 0.499715623 1
+4 0.000578789 133
+3 0.082560675 1
+4 0.000401248 44
+3 0.082898904 1
+4 0.000463999 115
+3 0.083267781 1
+4 0.000428878 130
+3 0.083135862 1
+4 0.000374468 44
+3 0.301722353 1
+4 0.000497865 16
+3 0.499837789 1
+4 0.000339484 17
+3 0.082709505 1
+4 0.000413937 16
+3 0.083176641 1
+4 0.000330187 16
+3 0.083139526 1
+4 0.000543854 16
+3 0.394988957 1
+4 0.000343115 16
+3 0.269629692 1
+4 0.000348912 28
+3 0.071635991 1
+4 0.000362496 17
+3 0.159759804 1
+4 0.000347896 18
+3 0.183536253 1
+4 0.000423127 18
+3 0.183529976 1
+4 0.000359333 18
+3 0.111615035 1
+4 0.000361619 18
+3 0.175838486 1
+4 0.000358092 35
+3 0.343534013 2
+4 0.000377489 31
+3 0.169506249 1
+4 0.000329047 17
+3 0.205756115 1
+4 0.000343659 17
+3 0.265598752 1
+4 0.000374504 17
+3 0.277776817 1
+4 0.000385196 18
+3 0.623607466 1
+4 0.000465991 17
+3 0.407578830 1
+4 0.000377308 17
+3 0.383596590 1
+4 0.000344645 17
+3 0.287624982 1
+4 0.000338938 17
+3 0.500058529 1
+4 0.000361373 18
+3 0.083005940 1
+4 0.000368949 18
+3 0.083199114 1
+4 0.000331711 20
+3 0.083023505 1
+4 0.000487715 17
+3 0.083150658 1
+4 0.000352183 17
+3 0.083005686 1
+4 0.000420446 19
+3 0.082645909 1
+4 0.000443195 17
+3 0.082880092 1
+4 0.000348592 19
+3 0.084370020 1
+4 0.000554421 19
+3 0.082753405 1
+4 0.000344666 19
+3 0.082759368 1
+4 0.000370472 18
+3 0.273664109 1
+4 0.000349786 20
+3 0.414549669 2
+4 0.000469361 31
+3 0.183558246 1
+4 0.000349709 31
+3 0.079685759 1
+4 0.000383733 16
+3 0.207556160 1
+4 0.000425055 17
+3 0.175532538 1
+4 0.000353824 17
+3 0.151619008 1
+4 0.000454891 17
+3 0.127532347 1
+4 0.000370301 18
+3 0.151735505 1
+4 0.000380548 34
+4 0.703909264 17
+3 0.079980896 1
+4 0.110019529 30
+3 0.905877768 1
+4 0.000445492 24
+3 1.047415902 1
+4 0.000332007 19
+3 0.499902514 1
+4 0.000439156 19
+3 0.082836836 1
+4 0.000478012 18
+3 0.082851279 1
+4 0.000358081 17
+3 0.083713388 1
+4 0.000610451 21
+3 0.082968659 1
+4 0.000359505 17
+3 0.277418759 1
+4 0.000341648 10
+3 0.135643786 1
+4 0.000345552 1
+3 0.087654054 1
+4 0.000422437 1
+4 0.000449764 70
+3 0.503010874 1
+4 0.000354564 39
+3 0.501454976 1
+4 0.000364633 19
+3 0.081948991 1
+4 0.000319512 17
+3 0.082820842 1
+4 0.000330816 20
+3 0.083311309 1
+4 0.000348309 20
+3 0.083663099 1
+4 0.000353884 17
+3 0.082662925 1
+4 0.000340642 19
+3 0.084299043 1
+4 0.000352433 20
+3 0.081663755 1
+4 0.000380282 18
+3 0.082756710 1
+4 0.000316548 19
+3 0.083824192 1
+4 0.000345942 34
+3 0.083168918 1
+4 0.000445371 74
+3 0.082953951 1
+4 0.000355228 73
+3 0.083088287 1
+4 0.000367068 90
+3 0.083149922 1
+4 0.000348080 47
+3 0.688053329 1
+4 0.000381554 34
+3 0.497613523 1
+4 0.000366693 64
+3 0.083561312 1
+4 0.000419851 75
+3 0.199676372 1
+4 0.000672162 20
+3 0.201352501 1
+4 0.000605369 17
+3 0.498124334 1
+4 0.000639937 18
+3 0.082473199 1
+4 0.000457451 20
+3 0.083307226 1
+4 0.000353384 20
+3 0.082727515 1
+4 0.000534145 17
+3 0.082859004 1
+4 0.000345422 17
+3 0.082716025 1
+4 0.000444831 18
+3 0.083456421 1
+4 0.000566420 20
+3 0.082288311 1
+4 0.000575933 18
+3 0.083136546 1
+4 0.000336951 19
+3 0.083151116 1
+4 0.000532592 20
+3 0.082635042 1
+4 0.000346929 16
+3 0.083301988 1
+4 0.000532397 19
+3 0.083170403 1
+4 0.000414279 18
+3 0.083016143 1
+4 0.000369031 17
+3 0.166586961 1
+4 0.000586191 17
+3 0.201647795 1
+4 0.000355931 19
+3 0.157534136 1
+4 0.000355658 16
+3 0.185688458 1
+4 0.000350437 16
+3 0.405343831 1
+4 0.000338913 16
+3 2.776772946 1
+4 0.000765659 16
+3 0.498951429 1
+4 0.000358422 17
+3 0.082649556 1
+4 0.000356330 19
+3 0.083223260 1
+4 0.000434303 20
+3 0.082959209 1
+4 0.000343712 18
+3 0.083665361 1
+4 0.000351377 19
+3 0.082729431 1
+4 0.000343251 16
+3 0.083766736 1
+4 0.000369217 20
+3 0.082957236 1
+4 0.000506694 20
+3 0.514406159 1
+4 0.000384271 17
+3 0.135711038 1
+4 0.000448742 27
+3 0.095642611 1
+4 0.000353778 18
+3 0.143502669 1
+4 0.000343133 18
+3 0.191824914 1
+4 0.000345515 18
+3 0.167508155 1
+4 0.000439012 18
+3 0.119586152 1
+4 0.000364246 14
+3 0.199599029 1
+4 0.000394824 31
+3 0.359494159 2
+4 0.000360391 31
+3 0.500491661 1
+4 0.000348030 14
+3 0.083022059 1
+4 0.000354076 19
+3 0.082658870 1
+4 0.000334284 16
+3 0.082744416 1
+4 0.000375206 20
+3 0.082793199 1
+4 0.000335734 20
+3 0.083032690 1
+4 0.000390111 102
+3 0.083169309 1
+4 0.000564309 47
+3 0.082834177 1
+4 0.000370394 34
+3 0.083161897 1
+4 0.000555561 56
+3 0.083027258 1
+4 0.000411563 72
+3 0.083065270 1
+4 0.000438012 111
+3 0.083244716 1
+4 0.000388982 61
+3 5.390076001 1
+4 0.000361755 17
+3 0.500376102 1
+4 0.000346290 20
+3 0.083773871 1
+4 0.000339582 19
+3 0.082705021 1
+4 0.000343591 17
+3 0.083076161 1
+4 0.000351006 18
+3 0.083267781 1
+4 0.000353708 20
+3 0.860627549 1
+4 0.000413376 9
+3 0.159561144 1
+4 0.000536985 1
+3 0.055446008 1
+4 0.000397264 1
+4 0.000412078 70
+3 0.303331126 1
+4 0.000419620 37
+3 0.500407349 1
+4 0.000345294 16
+3 0.083195438 1
+4 0.000349955 20
+3 0.083323730 1
+4 0.000359940 19
+3 0.083153203 1
+4 0.000351876 17
+3 0.083203532 1
+4 0.000348572 19
+3 0.083551307 1
+4 0.000405705 34
+3 0.083713520 1
+4 0.000475964 63
+3 0.082759958 1
+4 0.000642429 67
+3 0.082355568 1
+4 0.000391276 36
+3 0.150523447 1
+4 0.000359130 21
+3 0.499631795 1
+4 0.000429306 20
+3 0.082668851 1
+4 0.000394256 17
+3 0.083587363 1
+4 0.000550229 18
+3 0.083265075 1
+4 0.000418526 20
+3 0.082872392 1
+4 0.000485616 20
+3 0.084466364 1
+4 0.000508445 19
+3 1.586077941 1
+4 0.000347002 18
+3 0.565763557 1
+4 0.000371357 18
+3 1.121561378 1
+4 0.000438793 20
+3 0.165842554 1
+4 0.000511685 21
+3 0.161127237 1
+4 0.000424980 20
+3 3.077818632 1
+4 0.000452650 20
+3 0.185586315 1
+4 0.000371881 21
+3 0.181483248 1
+4 0.000352713 19
+3 0.265640013 1
+4 0.000356845 17
+3 0.237734230 1
+4 0.000335245 18
+3 0.169878470 1
+4 0.000349162 20
+3 0.157400611 1
+4 0.000384050 21
+3 0.137767120 1
+4 0.000353454 20
+3 0.885723127 1
+3 0.127835187 1
+3 0.146006447 1
+4 0.000416838 248
+3 0.325825520 1
+4 0.000662162 941
+3 0.399307036 1
+4 0.000356040 18
+3 0.499876896 1
+4 0.000349176 19
+3 0.082827014 1
+4 0.000409474 20
+3 0.083267243 1
+4 0.000498996 17
+3 0.083253106 1
+4 0.000358544 17
+3 0.083263726 1
+4 0.000337032 17
+3 0.083042359 1
+4 0.000358627 18
+3 0.083620693 1
+4 0.000350194 20
+3 0.082760510 1
+4 0.000630143 17
+3 0.082784874 1
+4 0.000550076 17
+3 0.082704841 1
+4 0.000574716 19
+3 0.082744908 1
+4 0.000418352 17
+3 0.082774202 1
+4 0.000354258 19
+3 0.082677819 1
+4 0.000378462 16
+3 0.083521815 1
+4 0.000768416 16
+3 0.083022700 1
+4 0.000438248 18
+3 0.450666400 1
+4 0.000497195 188
+3 1.007600483 1
+4 0.000581024 778
+3 0.599384935 1
+4 0.000360129 15
+3 0.500500421 1
+4 0.000365977 15
+3 0.083046809 1
+4 0.000346430 15
+3 0.083022384 1
+4 0.000366479 15
+3 0.083224960 1
+4 0.000465202 15
+3 0.082781315 1
+4 0.001236088 17
+3 0.082531962 1
+4 0.000465791 18
+3 0.083206979 1
+4 0.000429056 16
+3 0.083211682 1
+4 0.000333562 17
+3 0.082977928 1
+4 0.000367388 16
+3 0.082943957 1
+4 0.000365290 17
+3 0.315483208 1
+4 0.000393839 51
+3 1.167665625 2
+4 0.000913033 53
+3 0.182978821 1
+4 0.000398811 41
+3 0.153587089 1
+4 0.000595040 16
+3 0.157539637 1
+4 0.000569714 17
+3 0.137512376 1
+4 0.000658573 16
+3 0.309205758 1
+4 0.000382197 16
+3 0.185911600 1
+4 0.000512091 17
+3 0.149111251 1
+4 0.000396892 16
+3 0.169839512 1
+4 0.000356643 17
+3 0.197498698 1
+4 0.000403258 18
+3 0.169593924 1
+4 0.000339724 16
+3 0.133707454 1
+4 0.000411193 17
+3 0.145624323 1
+4 0.000402009 16
+3 0.613718602 1
+3 0.143849770 1
+3 0.113977538 1
+4 0.000399485 30
+3 0.189809136 1
+4 0.000489080 184
+3 0.207464929 1
+4 0.000396541 41
+3 0.185688210 1
+4 0.000382841 17
+3 0.173560003 1
+4 0.000349710 16
+3 0.169557571 1
+4 0.000380527 17
+3 0.141625411 1
+4 0.000349480 18
+3 0.143540418 1
+4 0.000404076 18
+3 0.500446448 1
+4 0.000528431 18
+3 0.083456864 1
+4 0.000358381 17
+3 0.082908576 1
+4 0.000332441 18
+3 0.082997287 1
+4 0.000323440 17
+3 0.084391379 1
+4 0.000338972 18
+3 0.363607768 1
+4 0.000372113 18
+3 0.153661829 1
+4 0.000360189 17
+3 0.149657377 1
+4 0.000337623 18
+3 0.153708359 1
+4 0.000371589 17
+3 0.197639231 1
+3 0.071919331 1
+4 0.000535106 6
+3 0.281484931 1
+4 0.000363947 17
+3 0.149715247 1
+4 0.000446534 17
+3 0.185630636 1
+4 0.000352668 18
+3 0.301625584 1
+4 0.000420794 17
+3 0.111541731 1
+4 0.000362384 17
+3 0.153487339 1
+4 0.000384289 17
+3 1.077671578 1
+4 0.000373787 29
+3 1.135694313 2
+4 0.000455849 38
+3 0.161894671 1
+4 0.000424980 17
+3 0.157286557 1
+4 0.000414068 24
+3 0.215649944 1
+4 0.000362453 27
+3 0.279634478 1
+4 0.000382029 27
+3 0.079771511 1
+4 0.000338178 27
+3 0.111424942 1
+4 0.000389236 27
+3 0.103723776 1
+4 0.000408895 27
+3 0.279611650 1
+4 0.000438696 28
+3 0.167489619 1
+4 0.000340970 27
+3 0.121779530 1
+4 0.000381886 29
+3 0.141467726 1
+4 0.000342816 27
+3 0.263712595 1
+4 0.000389215 27
+3 0.111460903 1
+4 0.000341648 27
+3 0.207878690 1
+4 0.000441034 27
+3 0.063483895 1
+4 0.000337227 27
+3 0.391866272 1
+4 0.000430578 45
+3 0.087431813 1
+4 0.000346458 36
+3 0.786929049 1
+4 0.109919332 33
+3 0.750768305 1
+4 0.000369786 17
+3 0.295716194 1
+4 0.000366326 17
+3 0.218629147 1
+4 0.000367947 17
+3 5.636919818 1
+4 0.000374497 17
+3 1355.286048369 1
+4 0.109011400 1
+3 1.490559382 1
+4 0.000357441 17
+3 0.295055507 1
+4 0.000315393 17
+3 2.111778287 1
+3 0.096511683 1
+3 0.105319373 1
+4 0.000335261 30
+3 0.253704552 1
+4 0.000436942 149
+3 0.343686706 1
+4 0.000328610 43
+3 0.170833496 1
+4 0.000336496 18
+3 0.164434028 1
+4 0.000314439 17
+3 0.177767839 1
+4 0.000322700 17
+3 0.197573428 1
+4 0.000324172 18
+3 0.177835910 1
+4 0.000312284 17
+3 0.309632372 1
+4 0.000343358 17
+3 0.271619755 1
+3 0.104063983 1
+4 0.000372121 26
+3 0.287775040 1
+4 0.000363707 18
+3 0.111377554 1
+4 0.000349460 18
+3 0.239645302 1
+4 0.000336576 27
+3 0.071735089 1
+4 0.000330810 27
+3 0.151774365 1
+4 0.000323559 27
+3 0.207685137 1
+4 0.000352612 27
+3 0.743594889 1
+4 0.109994294 33
+3 0.402123637 1
+4 0.000459725 31
+3 0.847552031 2
+4 0.000372091 31
+3 2.015571160 1
+4 0.000385207 31
+3 1.631737529 1
+4 0.000360234 27
+3 0.679716084 1
+4 0.000367304 17
+3 0.279650564 1
+4 0.000324321 18
+3 0.655637050 1
+4 0.000411043 27
+3 9.936312957 1
+4 0.000350518 27
+3 0.431347782 1
+4 0.000355531 28
+3 0.503565171 1
+4 0.000398839 27
+3 0.503617679 1
+4 0.000357867 27
+3 0.423588873 1
+4 0.000358174 27
+3 1.847873914 1
+4 0.000405355 27
+3 0.319511106 1
+4 0.000318428 45
+4 0.707294448 18
+3 0.689969912 1
+4 0.110044320 31
+3 1.717323869 1
+4 0.000346123 17
+3 0.414922328 1
+4 0.000333108 9
+3 3.656376669 1
+4 0.000355126 24
+3 0.294989399 1
+4 0.000325068 28
+3 0.167577032 1
+4 0.000325343 28
+3 0.176570876 1
+4 0.000355360 28
+3 0.062913079 1
+4 0.000319204 28
+3 0.183638201 1
+4 0.000305624 29
+3 0.063720709 1
+4 0.000330903 28
+3 0.151643423 1
+4 0.000309986 28
+3 0.087702635 1
+4 0.000315924 28
+3 0.687627731 1
+4 0.000334813 28
+3 1.759871422 1
+4 0.000380929 28
+3 0.215524344 1
+4 0.000325008 28
+3 0.167570983 1
+4 0.000308543 28
+3 0.112563005 1
+4 0.000324025 28
+3 1.343008921 1
+4 0.000329887 28
+3 0.071597918 1
+4 0.000323210 29
+3 0.079624009 1
+4 0.000298985 28
+3 1.015958588 1
+4 0.000369154 17
+3 0.135463553 1
+4 0.000307810 18
+3 0.128003674 1
+4 0.000334953 28
+3 0.111341087 1
+4 0.000312659 28
+3 0.167803786 1
+4 0.000307857 28
+3 1.735851319 1
+4 0.000370105 28
+3 0.383452951 2
+4 0.000317159 24
+3 0.832455739 1
+3 0.079253131 1
+4 0.000431951 28
+3 0.415703583 1
+4 0.000328586 18
+3 0.311548333 1
+4 0.000328201 18
+3 0.698955582 1
+4 0.109992859 37
+3 0.462971498 1
+4 0.000380718 23
+3 0.135433447 1
+4 0.000336163 24
+3 62.410493085 1
+4 0.000358077 19
+3 0.176982743 1
+4 0.000323854 20
+3 0.582668503 1
+3 0.215073430 1
+3 0.129961162 1
+4 0.000381255 162
+3 0.158277679 1
+4 0.000346224 41
+3 0.145075471 1
+4 0.000349158 16
+3 0.165624343 1
+4 0.000418271 16
+3 0.155440827 1
+4 0.000319586 16
+3 0.211726570 1
+4 0.000356541 158
+3 5.368078153 1
+4 0.000354072 43
+3 0.218658167 1
+4 0.000325955 18
+3 0.196551091 1
+4 0.000302677 17
+3 0.201642786 1
+4 0.000340321 17
+3 0.149635875 1
+4 0.000300915 18
+3 2.184866499 1
+4 0.000345788 4
+3 0.272660452 1
+4 0.000348781 4
+3 0.277607983 1
+4 0.000316319 24
+3 0.327564491 1
+4 0.000322444 27
+3 2.751905926 1
+4 0.000336694 27
+3 0.423623387 1
+4 0.000352361 27
+3 0.511757455 1
+4 0.000344154 27
+3 0.071574193 1
+4 0.000315063 27
+3 0.175774578 1
+4 0.000321676 27
+3 0.207621572 1
+4 0.000312464 27
+3 0.319717021 1
+4 0.000340340 27
+3 4.391800618 2
+3 0.138077046 1
+4 0.000353195 94
+3 0.261583195 1
+4 0.000408997 85
+3 0.327629465 1
+4 0.000339131 29
+3 0.217602626 1
+4 0.000355921 18
+3 0.469620162 1
+4 0.000331587 19
+3 0.305749384 1
+4 0.000477633 166
+3 0.597426029 1
+4 0.000373177 150
+3 0.471823730 1
+4 0.000384326 41
+3 0.233567792 1
+4 0.000416471 16
+3 0.165717168 1
+4 0.000363228 16
+3 4.759691707 1
+3 0.167982627 1
+3 0.090004510 1
+4 0.000374936 29
+3 0.333497762 1
+4 0.000442909 142
+3 0.279708427 1
+4 0.000354939 43
+3 0.500668158 1
+4 0.000342487 18
+3 0.083288958 1
+4 0.000393562 17
+3 0.083496591 1
+4 0.000305439 17
+3 0.509420052 1
+4 0.000345250 18
+3 0.181420224 1
+4 0.000338016 17
+3 0.186424176 1
+4 0.000408116 16
+3 0.292862348 1
+4 0.000327081 14
+3 0.239622003 1
+4 0.000405427 17
+3 0.185653517 1
+4 0.000326735 17
+3 0.301690532 1
+4 0.000333015 17
+3 0.185686888 1
+4 0.000320161 17
+3 0.133603576 1
+4 0.000389670 17
+3 0.121537455 1
+4 0.000349007 17
+3 0.133756554 1
+4 0.000348035 17
+3 0.113708278 1
+4 0.000375077 17
+3 0.181588197 1
+4 0.000320146 17
+3 0.247725864 1
+4 0.000345665 4
+3 0.145694291 1
+4 0.000395946 4
+3 0.165451544 1
+4 0.000323197 4
+3 0.161705030 1
+4 0.000344935 4
+3 0.125705497 1
+4 0.000306407 4
+3 0.139302910 1
+4 0.000407498 4
+3 0.164048481 1
+4 0.000320381 4
+3 0.417597010 1
+4 0.000379491 4
+3 0.173635897 1
+4 0.000319662 24
+3 0.193688535 1
+4 0.000335694 27
+3 0.093672109 1
+4 0.000419259 27
+3 0.071599550 1
+4 0.000311541 28
+3 0.183773162 1
+4 0.000338949 27
+3 0.215666458 1
+4 0.000321816 27
+3 0.671793710 2
+4 0.000341553 33
+3 1.047583259 1
+4 0.000344162 16
+3 0.183654957 1
+4 0.000323913 18
+3 0.233793694 1
+4 0.000390101 17
+3 0.509576860 1
+4 0.000325925 17
+3 0.689747099 1
+4 0.000366075 17
+3 2.157542223 1
+4 0.000414784 26
+3 0.199608787 1
+4 0.000327154 18
+3 0.996848027 1
+4 0.109971083 36
+3 5.677291390 1
+4 0.000352075 20
+3 0.287541649 1
+4 0.000324724 20
+3 0.303777177 1
+4 0.000335877 20
+3 4.027017614 1
+4 0.000376221 19
+3 0.148151160 1
+4 0.000318898 20
+3 0.153996016 1
+4 0.000336099 20
+3 0.141326062 1
+4 0.000301818 20
+3 0.247873353 1
+3 0.113937336 1
+4 0.000345598 29
+3 0.229781504 1
+4 0.000361327 43
+3 0.121498710 1
+4 0.000317212 20
+3 0.141844049 1
+4 0.000337465 19
+3 0.247712021 1
+4 0.000355190 88
+3 0.703645321 1
+4 0.000419216 45
+3 0.207377514 2
+4 0.000328790 34
+3 0.159694452 1
+4 0.000339405 16
+3 0.161693631 1
+4 0.000303017 18
+3 0.341763799 1
+4 0.000344438 18
+3 1.015607522 1
+4 0.000337297 33
+3 0.231808474 1
+4 0.000345310 18
+3 0.183609427 1
+4 0.000348803 18
+3 0.151621169 1
+4 0.000340968 18
+3 0.071617354 1
+4 0.000340082 18
+3 0.151636128 1
+4 0.000326752 18
+3 0.127790406 1
+4 0.000347013 18
+3 0.167664123 1
+4 0.000361627 18
+3 0.119539753 1
+4 0.000334043 18
+3 0.303835058 1
+4 0.000393910 18
+3 0.087515898 1
+4 0.000330357 19
+3 0.375829127 1
+4 0.000381315 18
+3 0.129554274 1
+4 0.000329974 17
+3 0.085547027 1
+4 0.000333917 18
+3 0.159760955 1
+4 0.000319214 19
+3 0.119675564 1
+4 0.000324081 18
+3 0.231671824 1
+4 0.000344584 17
+3 0.081850440 1
+4 0.000328694 18
+3 0.133533946 1
+4 0.000338481 18
+3 0.207610747 1
+4 0.000320407 18
+3 0.095620195 1
+4 0.000305295 18
+3 0.519738841 1
+4 0.000347186 18
+3 0.095699160 1
+4 0.000321257 18
+3 0.103615810 1
+4 0.000349111 17
+3 0.719747780 1
+4 0.000329712 18
+3 0.263761306 1
+4 0.000343076 18
+3 0.199484445 1
+4 0.000335516 16
+3 0.128462380 1
+4 0.000339980 13
+3 0.118964420 1
+4 0.000322799 11
+3 0.079629165 1
+4 0.000320585 11
+3 0.119613685 1
+4 0.000365738 13
+3 0.071779378 1
+4 0.000333589 16
+3 0.119539596 1
+4 0.000330669 18
+3 0.191683622 1
+4 0.000320680 18
+3 0.183700306 1
+4 0.000306913 19
+3 0.183773381 1
+4 0.000328223 18
+3 0.095678195 1
+4 0.000312077 18
+3 0.175588035 1
+4 0.000333542 18
+3 0.087738779 1
+4 0.000302918 18
+3 0.047544625 1
+4 0.000384855 18
+3 0.255723045 1
+4 0.000313346 18
+3 0.160157003 1
+4 0.000324507 18
+3 0.111359765 1
+4 0.000333551 18
+3 0.151767421 1
+4 0.000312405 18
+3 0.303397461 2
+4 0.000363249 33
+3 0.177841572 1
+4 0.000320580 17
+3 0.149535897 1
+4 0.000335614 17
+3 0.154196825 1
+4 0.000320025 17
+3 0.109240108 1
+4 0.000315702 4
+3 0.639770085 1
+4 0.000346749 19
+3 0.535670249 1
+4 0.000331265 17
+3 0.185671951 1
+4 0.000350951 16
+3 5.125904385 1
+4 0.000431425 88
+3 0.186977482 1
+4 0.000385201 104
+3 0.452241058 1
+4 0.000375841 44
+3 0.121656381 1
+4 0.000360525 34
+3 0.165573345 1
+4 0.000356146 54
+3 0.263466455 1
+4 0.000328059 16
+3 0.209585261 1
+4 0.000316103 18
+3 0.157813780 1
+4 0.000328357 16
+3 0.169852196 1
+4 0.000395202 16
+3 3.461723285 1
+4 0.000362811 16
+3 0.255532421 1
+4 0.000339689 18
+3 0.119616008 1
+4 0.000325998 18
+3 0.170355554 1
+4 0.000367394 17
+3 0.285071366 1
+3 0.071817285 1
+4 0.000412397 4
+3 0.143702867 1
+3 0.055910855 1
+4 0.000414719 5
+3 14.440866789 1
+4 0.000355757 24
+3 0.270870488 1
+4 0.000344692 19
+3 1.003915582 1
+4 0.109901407 33
+3 7.398756208 1
+4 0.000565541 905
+3 2.151348317 1
+4 0.000597751 775
+3 0.535104159 1
+4 0.000567414 885
+3 3.455623341 1
+4 0.000356962 15
+3 0.499621583 1
+4 0.000334991 15
+3 0.082746921 1
+4 0.000367092 15
+3 0.082809523 1
+4 0.000307765 17
+3 0.083042775 1
+4 0.000305767 18
+3 0.083620957 1
+4 0.000303635 15
+3 0.083543148 1
+4 0.000395460 15
+3 0.082977878 1
+4 0.000345953 15
+3 0.083546396 1
+4 0.000356394 17
+3 0.083402942 1
+4 0.000380225 18
+3 0.083511060 1
+4 0.000337833 16
+3 0.317250225 1
+4 0.000347420 16
+3 3.269957967 1
+4 0.000411221 16
+3 0.500100450 1
+4 0.000332747 16
+3 0.083269372 1
+4 0.000375851 17
+3 0.083184899 1
+4 0.000355772 17
+3 0.084111434 1
+4 0.000404485 15
+3 0.082862947 1
+4 0.000324645 15
+3 0.082880334 1
+4 0.000364168 15
+3 0.082942671 1
+4 0.000348189 18
+3 1.733670017 1
+4 0.000367479 18
+3 0.169798494 1
+4 0.000316243 15
+3 0.165723069 1
+4 0.000409110 15
+3 0.359556527 1
+3 0.146319761 1
+4 0.000380726 28
+3 0.421481252 1
+4 0.000588725 806
+3 0.399268717 1
+4 0.000413960 19
+3 0.499965393 1
+4 0.000374304 18
+3 0.083201716 1
+4 0.000362287 17
+3 0.083516925 1
+4 0.000308564 19
+3 0.083207789 1
+4 0.000305446 19
+3 0.083147296 1
+4 0.000321533 20
+3 0.495046928 1
+4 0.000326144 18
+3 0.497512357 1
+4 0.000354661 17
+3 0.083577867 1
+4 0.000325406 20
+3 0.082751067 1
+4 0.000332784 20
+3 0.083050111 1
+4 0.000325669 20
+3 0.083128025 1
+4 0.000339349 19
+3 0.083053302 1
+4 0.000322173 17
+3 0.083069129 1
+4 0.000329116 20
+3 0.082803835 1
+4 0.000342221 20
+3 0.083184165 1
+4 0.000319960 21
+3 0.083367062 1
+4 0.000313845 19
+3 0.082733046 1
+4 0.000314193 20
+3 1.273743625 1
+4 0.000382171 61
+3 0.911675042 2
+4 0.000413945 91
+3 0.335606840 1
+4 0.000338940 17
+3 0.223600080 1
+3 0.154015266 1
+4 0.000350944 40
+3 0.237638708 1
+4 0.000387173 18
+3 0.137585301 1
+4 0.000364394 17
+3 6.941973560 1
+3 0.169994410 1
+4 0.000351093 57
+3 5.229817087 1
+4 0.000353408 17
+3 0.895529177 1
+4 0.000378019 63
+3 1.823769261 1
+4 0.000558188 48
+3 0.727480849 1
+4 0.000346612 9
+3 0.103564042 1
+4 0.000418594 43
+3 0.479619362 1
+4 0.000581226 17
+3 0.783466733 1
+4 0.000397266 10
+3 0.311567758 1
+4 0.000468045 1
+3 0.183529936 1
+4 0.000446948 1
+3 0.175665108 1
+4 0.000347008 1
+3 0.295546700 1
+4 0.000488259 1
+3 0.311713969 1
+4 0.000708820 426
+3 0.543277569 1
+4 0.000468093 191
+3 0.370453129 1
+4 0.000436304 195
+3 0.332492711 1
+4 0.000516417 629
+3 2.297769577 1
+4 0.000375844 17
+3 1.349639570 1
+4 0.000539640 516
+3 0.169431993 1
+4 0.000381393 58
+3 0.957581268 1
+4 0.000369523 10
+3 0.159576813 1
+4 0.000359247 1
+3 0.087702014 1
+4 0.000325770 1
+4 0.000404527 71
+3 0.471205359 1
+4 0.000347201 37
+3 0.499925798 1
+4 0.000339188 20
+3 0.083415211 1
+4 0.000310028 17
+3 0.083391046 1
+4 0.000307447 16
+3 0.082895739 1
+4 0.000307431 18
+3 0.083394592 1
+4 0.000310969 17
+3 0.083139837 1
+4 0.000339507 19
+3 0.082927037 1
+4 0.000310078 16
+3 8.255292921 1
+4 0.000399911 16
+3 0.154649653 1
+4 0.000327368 18
+3 0.156068589 1
+4 0.000333478 17
+3 0.185684061 1
+4 0.000303888 19
+3 0.645740718 1
+4 0.000339869 17
+3 0.209568252 1
+4 0.000352399 16
+3 0.181665352 1
+4 0.000300823 17
+3 1.183886754 1
+3 0.079931813 1
+4 0.000368609 24
+3 0.135650054 1
+4 0.000331397 17
+3 0.287578764 1
+4 0.000408887 17
+3 0.511566421 2
+4 0.000358917 32
+3 0.183823846 1
+4 0.000359244 22
+3 0.175544051 1
+4 0.000339007 23
+3 0.743690311 1
+4 0.000388158 16
+3 0.242018541 1
+4 0.000324740 18
+3 0.205240057 1
+4 0.000326932 19
+3 0.201744955 1
+4 0.000384731 20
+3 0.197564455 1
+4 0.000331179 17
+3 0.202047265 1
+4 0.000343138 19
+3 0.205735276 1
+4 0.000394812 16
+3 0.279264151 1
+4 0.000323404 18
+3 0.499895957 1
+4 0.000369741 20
+3 0.083569476 1
+4 0.000307162 17
+3 0.083267533 1
+4 0.000382126 19
+3 0.083133696 1
+4 0.000319785 20
+3 0.083082217 1
+4 0.000311716 17
+3 0.438926962 1
+4 0.000308596 16
+3 0.381920137 1
+3 0.223951188 1
+3 0.105984888 1
+4 0.000342800 30
+3 0.373632952 1
+4 0.000429730 329
+3 0.671880020 1
+4 0.000368303 42
+3 0.145342356 1
+4 0.000319131 17
+3 0.405714676 1
+3 0.064015291 1
+4 0.000407190 28
+3 0.159571256 1
+4 0.000359129 17
+3 0.135739925 1
+4 0.000342254 17
+3 0.095414506 1
+4 0.000385877 17
+3 0.263781157 1
+4 0.000341915 17
+3 0.143633585 1
+4 0.000341779 17
+3 0.127773709 1
+4 0.000326438 17
+3 0.096178447 1
+4 0.000407714 17
+3 0.150944671 1
+4 0.000324320 17
+3 1.167778613 2
+4 0.000450760 32
+3 1.151657400 1
+3 0.087857087 1
+4 0.000353619 28
+3 1.343853416 2
+4 0.000410493 36
+3 0.767628835 1
+4 0.000393689 17
+3 0.823535322 1
+4 0.000350832 17
+3 0.607779189 1
+4 0.000330991 23
+3 0.567719946 1
+4 0.000345112 41
+3 0.415541324 1
+4 0.000342291 40
+3 0.215587583 1
+4 0.000332996 40
+3 0.271815338 1
+4 0.000356992 40
+3 0.726008674 1
+4 0.110033117 32
+3 0.739536474 1
+4 0.000366927 16
+3 0.431716905 1
+4 0.000367342 20
+3 0.247730542 1
+4 0.000435044 16
+3 0.153581531 1
+4 0.000328017 18
+3 0.165388638 1
+4 0.000321800 19
+3 0.161953265 1
+4 0.000356221 20
+3 0.157434805 1
+4 0.000324051 17
+3 0.137776152 1
+4 0.000331819 19
+3 0.166259555 1
+4 0.000312381 16
+3 0.247121126 1
+4 0.000392045 18
+3 0.499770198 1
+4 0.000333407 20
+3 0.083248530 1
+4 0.000307234 17
+3 0.083307513 1
+4 0.000409962 19
+3 0.082946162 1
+4 0.000312854 20
+3 0.363169418 1
+4 0.000346906 17
+3 8.429939840 1
+4 0.000355388 16
+3 0.239519158 1
+3 0.079944635 1
+4 0.000446971 28
+3 0.999708399 1
+4 0.000371364 17
+3 0.231399429 1
+4 0.000337278 17
+3 0.247770548 1
+4 0.000331658 17
+3 0.807599971 2
+4 0.000440067 27
+3 0.137837192 1
+4 0.000320814 16
+3 3.277671637 1
+4 0.000349084 23
+3 2.479738186 1
+4 0.000437566 31
+3 0.383502557 1
+4 0.000352195 31
+3 0.815744863 1
+4 0.000353932 31
+3 2.607751895 1
+4 0.000414627 31
+3 0.471841722 1
+4 0.000350908 31
+3 4.223463535 1
+4 0.000364000 32
+3 0.895657056 1
+4 0.000342411 31
+3 6.560153255 2
+4 0.000392008 35
+3 0.487401076 1
+4 0.000331628 19
+3 0.359759861 1
+4 0.000431837 16
+3 0.727411615 1
+3 0.071871017 1
+4 0.000334399 28
+3 0.184029362 1
+4 0.000357277 17
+3 0.271597042 1
+4 0.000333227 17
+3 0.007953852 1
+4 0.000353027 17
+3 0.407629558 1
+4 0.000342284 16
+3 0.239440204 1
+4 0.000399439 16
+3 0.271562646 1
+4 0.000315251 17
+3 0.015736464 1
+4 0.000328911 17
+3 0.463671983 1
+4 0.000386971 16
+3 0.255520313 1
+4 0.000396876 17
+3 0.255575574 1
+4 0.000319696 17
+3 0.327885831 1
+4 0.000370830 17
+3 0.135785420 1
+4 0.000308482 26
+3 0.063340907 1
+4 0.000354097 26
+3 0.760099189 2
+4 0.000349488 35
+3 0.263620209 1
+4 0.000430686 19
+3 2.655481019 1
+4 0.000352994 16
+3 0.201493229 1
+4 0.000388037 17
+3 0.565590496 1
+4 0.000340637 17
+3 0.279623962 1
+4 0.000403302 16
+3 0.217726250 1
+4 0.000330488 16
+3 0.157942626 1
+4 0.000341139 16
+3 0.153577727 1
+4 0.000391217 16
+3 1.629471085 1
+4 0.000365359 4
+3 0.153936121 1
+4 0.000353264 4
+3 0.157494105 1
+4 0.000387426 23
+3 3.815804737 2
+4 0.000555868 607
+3 0.185304508 1
+3 0.726180765 1
+4 0.000587305 896
+3 0.145166099 1
+4 0.000343318 17
+3 0.453717138 1
+4 0.000343318 18
+3 0.423806171 1
+4 0.000328304 32
+3 0.311473677 1
+4 0.000356712 51
+3 0.463701906 2
+4 0.000363047 31
+3 0.162468850 1
+4 0.000381771 17
+3 0.212936288 1
+4 0.000328744 17
+3 0.201572542 1
+4 0.000318393 17
+3 0.158188635 1
+4 0.000346781 17
+3 0.153086812 1
+4 0.000310759 17
+3 0.181748570 1
+4 0.000327495 17
+3 0.224633589 1
+4 0.000327160 24
+3 3.083265476 7
+4 0.000413328 55
+4 0.708396562 17
+3 0.109938943 1
+4 0.110046238 33
+3 1.131997691 1
+4 0.000368514 18
+3 0.614589204 1
+4 0.000348852 17
+3 7.328427097 1
+3 0.071398870 1
+4 0.000340671 29
+3 0.247583410 1
+4 0.000325206 18
+3 0.191682188 1
+4 0.000318153 18
+3 0.103684604 1
+4 0.000308663 17
+3 0.119653908 1
+4 0.000354466 18
+3 0.007920117 1
+4 0.000312124 19
+3 0.503678429 1
+4 0.000342666 18
+3 0.247490366 1
+4 0.000315711 19
+3 0.879814337 1
+4 0.000355112 18
+3 0.191647045 1
+4 0.000415816 18
+3 0.095496496 1
+4 0.000324130 18
+3 1.727941926 2
+4 0.000390151 24
+3 0.145311050 1
+4 0.000361530 17
+3 0.351067244 1
+3 0.086891293 1
+4 0.000376008 33
+3 1.159520811 1
+4 0.000356484 18
+3 1.631586569 1
+4 0.000360394 18
+3 2.223806976 1
+4 0.000348027 18
+3 5.303916208 2
+4 0.000397893 42
+3 0.383392549 1
+4 0.000343944 17
+3 0.153586044 1
+4 0.000327230 17
+3 0.165955767 1
+4 0.000350745 17
+3 0.145506471 1
+4 0.000327568 17
+3 0.149646704 1
+4 0.000394312 17
+3 0.177641094 1
+4 0.000337041 17
+3 0.165864558 1
+4 0.000322018 18
+3 0.137981608 1
+4 0.000327508 17
+3 0.485219823 1
+4 0.000357033 4
+3 0.311700882 1
+4 0.000414137 17
+3 0.500029320 1
+4 0.000351715 18
+3 0.082610702 1
+4 0.000335635 17
+3 0.083552630 1
+4 0.000323946 17
+3 0.083191415 1
+4 0.000311562 17
+3 0.250983064 1
+4 0.000322803 17
+3 0.189509172 1
+4 0.000311570 24
+3 0.367953067 1
+4 0.000402579 44
+4 0.708053942 18
+3 0.083378469 2
+4 0.000421970 37
+3 1.377642309 1
+4 0.000354773 19
+3 0.197731080 1
+4 0.000340457 20
+3 0.385502092 1
+4 0.000390110 20
+3 0.541627942 1
+4 0.000395369 18
+3 0.215837621 1
+4 0.000316576 24
+3 0.311575327 1
+4 0.000375469 19
+3 0.399886694 1
+4 0.000335074 20
+3 0.863526521 1
+4 0.000439261 19
+3 0.699983695 1
+4 0.110027389 33
+3 5.894499112 1
+4 0.000451518 20
+3 0.202621066 1
+4 0.000320801 19
+3 0.155971941 1
+4 0.000410889 20
+3 1.207458435 1
+4 0.000353441 17
+3 0.519857411 1
+4 0.000348953 24
+3 0.335643444 1
+4 0.000335709 20
+3 0.935719660 1
+4 0.000407745 20
+3 0.745725890 1
+4 0.110057260 33
+3 5.096001875 1
+4 0.000375705 18
+3 0.208285701 1
+4 0.000335118 17
+3 0.500229484 1
+4 0.000351746 17
+3 0.082089645 1
+4 0.000304275 17
+3 0.082961955 1
+4 0.000381201 18
+3 0.083131641 1
+4 0.000306994 17
+3 0.083585185 1
+4 0.000395186 18
+3 0.373142920 1
+4 0.000344102 18
+3 0.169563174 1
+4 0.000352400 17
+3 0.229835133 1
+4 0.000324837 17
+3 4.448064965 1
+4 0.000354894 18
+3 0.225338934 1
+4 0.000348300 17
+3 0.293659106 1
+4 0.000321764 17
+3 0.201812583 1
+4 0.000386869 18
+3 0.405460344 1
+4 0.000346744 17
+3 0.500122367 1
+4 0.000358785 17
+3 0.083259233 1
+4 0.000314479 17
+3 0.083574798 1
+4 0.000311706 17
+3 0.082828057 1
+4 0.000319412 17
+3 0.083388392 1
+4 0.000321179 17
+3 0.083681547 1
+4 0.000355028 18
+3 0.466832397 1
+4 0.000344230 17
+3 26.935338372 1
+4 0.000437200 17
+3 0.499741069 1
+4 0.000354244 17
+3 0.082820682 1
+4 0.000311809 17
+3 0.082888909 1
+4 0.000309663 17
+3 0.083270332 1
+4 0.000323716 17
+3 0.083815610 1
+4 0.000312243 17
+3 0.082827600 1
+4 0.000321313 17
+3 0.083498993 1
+4 0.000338685 17
+3 0.082869333 1
+4 0.000321419 18
+3 0.083316232 1
+4 0.000312199 17
+3 5.871279492 1
+4 0.000344698 18
+3 0.249514726 1
+4 0.000383238 19
+3 0.317703189 1
+4 0.000323249 20
+3 0.193482584 1
+4 0.000305137 18
+3 0.949820398 1
+3 0.096099933 1
+3 0.122987696 1
+4 0.000418853 31
+3 0.212453658 1
+4 0.000364048 179
+3 0.287711755 1
+4 0.000331579 41
+3 0.153836709 1
+4 0.000311394 16
+3 0.373422885 1
+4 0.000355467 16
+3 0.263747926 1
+4 0.000343796 16
+3 0.185613747 1
+4 0.000355462 16
+3 0.253735948 1
+4 0.000305528 16
+3 0.185902430 1
+4 0.000346254 16
+3 0.157376420 1
+4 0.000314771 17
+3 0.145911915 1
+4 0.000322312 16
+3 0.101681818 1
+4 0.000309979 18
+3 0.137425196 1
+4 0.000309656 18
+3 0.373925187 1
+4 0.000365363 24
+3 0.191397497 1
+4 0.000334851 31
+3 0.152638766 1
+4 0.000332264 31
+3 0.062935512 1
+4 0.000317057 31
+3 0.191640837 1
+4 0.000332105 31
+3 0.111562845 1
+4 0.000334212 31
+3 0.087713075 1
+4 0.000307308 31
+3 0.023895233 1
+4 0.000376620 31
+3 0.071305173 1
+4 0.000314625 31
+3 0.135882091 1
+4 0.000331895 31
+3 0.112892436 1
+4 0.000318745 32
+3 0.398540363 2
+4 0.000347929 36
+3 0.145543747 1
+4 0.000310408 18
+3 0.181733383 1
+4 0.000310710 19
+3 0.225791287 1
+4 0.000358431 20
+3 0.293422000 1
+4 0.000413438 19
+3 0.287674279 1
+4 0.000331060 20
+3 1.751776737 1
+4 0.000386746 18
+3 0.255480713 1
+4 0.000355248 17
+3 0.193905578 1
+4 0.000354053 18
+3 0.277552573 1
+3 0.056022450 1
+4 0.000337430 28
+3 0.215669320 1
+4 0.000392293 18
+3 0.751567284 1
+4 0.000343946 18
+3 0.159544512 1
+4 0.000339343 18
+3 0.738907235 1
+4 0.110079893 37
+3 0.046918166 1
+4 0.000346342 17
+3 1.951583337 1
+4 0.000336705 17
+3 0.271900166 1
+4 0.000329704 17
+3 0.201801219 1
+4 0.000320399 17
+3 0.181508584 1
+4 0.000311770 17
+3 0.169907266 1
+4 0.000367005 17
+3 0.661357828 1
+4 0.000358258 17
+3 2.167868078 1
+4 0.000422447 19
+3 0.201708762 1
+4 0.000321464 20
+3 0.285464595 1
+4 0.000333990 18
+3 1.951700809 1
+4 0.000347358 4
+3 0.391721772 1
+4 0.000337571 18
+3 0.185483810 1
+4 0.000353506 19
+3 0.213953442 1
+4 0.000308516 20
+3 1.199619712 1
+4 0.000420574 4
+3 1.935588071 1
+4 0.000340007 17
+3 0.500493774 1
+4 0.000344335 19
+3 0.082886485 1
+4 0.000376775 20
+3 0.083138078 1
+4 0.000321539 17
+3 0.083191881 1
+4 0.000305872 19
+3 0.083334596 1
+4 0.000308127 16
+3 0.083456869 1
+4 0.000337756 20
+3 0.083357583 1
+4 0.000327672 19
+3 0.245553300 1
+4 0.000334643 21
+3 0.217664280 1
+4 0.000336961 17
+3 0.189667138 1
+4 0.000313081 18
+3 0.169903078 1
+4 0.000322471 20
+3 0.149403068 1
+4 0.000373311 17
+3 0.583752446 1
+4 0.000365052 9
+3 0.311420326 1
+4 0.000334050 1
+3 0.113709736 1
+4 0.000328754 1
+3 0.269629311 1
+4 0.000334443 1
+3 0.199817057 1
+4 0.000336559 13
+4 0.000338588 45
+3 1.063427309 1
+4 0.000394966 41
+3 0.500115589 1
+4 0.000345806 20
+3 0.083139629 1
+4 0.000358336 17
+3 0.082598810 1
+4 0.000345737 19
+3 0.084031462 1
+4 0.000343220 20
+3 0.208172960 1
+4 0.000333316 19
+3 0.353593933 1
+4 0.000364028 20
+3 1.638053347 1
+4 0.000376336 4
+3 0.455382229 1
+4 0.000333648 17
+3 0.247648687 1
+4 0.000335276 31
+3 0.711882600 1
+4 0.000350656 39
+4 0.708294247 18
+3 0.319934314 1
+4 0.110026734 31
+3 31.510486412 1
+4 0.000365444 19
+3 0.217423519 1
+4 0.000342183 20
+3 0.165727326 1
+4 0.000373901 18
+3 0.193576422 1
+4 0.000389807 20
+3 0.501809418 1
+4 0.000370361 18
+3 0.185479186 1
+4 0.000353245 17
+3 0.165738100 1
+4 0.000391552 17
+3 0.185568811 1
+4 0.000326827 17
+3 0.389645144 1
+3 0.079955068 1
+4 0.000362696 7
+3 0.239817965 1
+4 0.000337478 17
+3 0.499804687 1
+4 0.000329867 18
+3 0.083927622 1
+4 0.000336878 19
+3 0.082239166 1
+4 0.000320152 20
+3 0.083317108 1
+4 0.000311769 17
+3 0.083328906 1
+4 0.000349950 19
+3 10.398342245 1
+4 0.000339689 20
+3 0.190926873 1
+4 0.000343843 17
+3 0.193983113 1
+4 0.000311998 17
+3 0.181405177 1
+4 0.000335518 18
+3 0.743747351 1
+3 0.080750263 1
+4 0.000362917 29
+3 0.983969402 2
+4 0.000361177 28
+3 0.326649869 1
+4 0.000392960 6
+3 0.185789164 1
+4 0.000325462 4
+3 0.157535507 1
+4 0.000411977 4
+3 0.129429124 1
+4 0.000316986 4
+3 0.134168711 1
+4 0.000349959 4
+3 0.161309787 1
+4 0.000338609 4
+3 0.117658051 1
+4 0.000363040 4
+3 0.249687333 1
+4 0.000333827 4
+3 0.397558284 1
+4 0.000342014 4
+3 0.143659469 1
+4 0.000318067 24
+3 0.223862839 1
+4 0.000406197 27
+3 0.159432209 1
+4 0.000353186 27
+3 0.183718252 1
+4 0.000352853 27
+3 0.560775341 2
+4 0.000342059 36
+3 0.366510501 1
+4 0.000346896 17
+3 0.169856402 1
+4 0.000338191 15
+3 0.181495702 1
+4 0.000381002 9
+3 0.959741177 1
+3 0.063922857 1
+4 0.000342183 29
+3 0.231615735 1
+4 0.000340924 13
+3 0.135678664 1
+4 0.000323864 16
+3 0.111820454 1
+4 0.000345612 17
+3 0.111566508 1
+4 0.000389733 18
+3 0.415649943 2
+4 0.000341770 28
+3 0.137739006 1
+4 0.000318061 18
+3 0.445512459 1
+3 0.072001743 1
+4 0.000404452 33
+3 0.159687980 1
+4 0.000323236 18
+3 0.087563053 1
+4 0.000315358 18
+3 0.095820094 1
+4 0.000368675 18
+3 0.207459649 1
+4 0.000327594 18
+3 0.143768333 1
+4 0.000349465 18
+3 0.511556634 1
+4 0.000336677 18
+3 0.137695863 1
+4 0.000335991 18
+3 0.397707766 1
+4 0.000343216 18
+3 0.423783351 2
+4 0.000347446 28
+3 1.055613217 1
+4 0.000340383 17
+3 0.215749254 1
+4 0.000342298 33
+3 0.199529985 1
+4 0.000397427 18
+3 0.191675036 1
+4 0.000346706 18
+3 0.359683867 2
+4 0.000369961 12
+3 0.119499816 1
+4 0.000316543 1
+3 0.071884463 1
+4 0.000337752 1
+4 0.000406056 71
+3 16.864636688 1
+4 0.000417982 39
+3 1.982761857 1
+4 0.000364483 16
+3 0.201773522 1
+4 0.000370579 19
+3 0.197459498 1
+4 0.000330729 20
+3 0.185686403 1
+4 0.000365432 20
+3 0.325699985 1
+3 0.279889565 1
+3 0.122194256 1
+4 0.000397331 158
+3 0.141506476 1
+4 0.000328477 41
+3 0.161643732 1
+4 0.000402495 16
+3 0.133583723 1
+4 0.000327938 16
+3 0.146028919 1
+4 0.000349062 16
+3 0.117267672 1
+4 0.000323723 16
+3 0.121732123 1
+4 0.000382146 17
+3 0.181705721 1
+4 0.000361214 16
+3 0.295675391 1
+4 0.000433182 164
+3 36.441560549 1
+4 0.000394892 41
+3 0.176818774 1
+4 0.000337521 16
+3 0.157633029 1
+4 0.000312926 16
+3 0.185768636 1
+4 0.000395215 16
+3 0.381511190 1
+4 0.000334361 16
+3 0.167888328 1
+4 0.000342384 18
+3 0.153562610 1
+4 0.000304993 17
+3 0.181654295 1
+4 0.000423831 18
+3 0.161419461 1
+4 0.000311281 17
+3 0.141734011 1
+4 0.000325034 17
+3 0.169768560 1
+4 0.000328403 18
+3 0.149646269 1
+4 0.000346239 18
+3 0.319604919 1
+4 0.000331568 18
+3 0.431854030 1
+4 0.000383382 18
+3 0.500341945 1
+4 0.000361535 17
+3 0.082386950 1
+4 0.000334650 17
+3 0.082928473 1
+4 0.000324967 17
+3 0.083439928 1
+4 0.000338704 17
+3 0.082800886 1
+4 0.000320995 17
+3 0.083070466 1
+4 0.000375476 17
+3 0.083388393 1
+4 0.000332583 17
+3 0.083681173 1
+4 0.000338640 17
+3 0.732952042 1
+4 0.000336557 17
+3 0.477571104 1
+4 0.000341230 4
+3 0.111584609 1
+4 0.000329798 39
+3 0.807798820 1
+4 0.000371883 31
+3 1.879777050 1
+4 0.000346880 38
+3 0.575594195 2
+4 0.000403331 34
+3 0.279481085 1
+4 0.000341609 17
+3 0.193731862 1
+4 0.000353646 17
+3 0.133635967 1
+4 0.000326808 17
+3 0.199653806 1
+4 0.000343865 18
+3 0.217632124 1
+4 0.000327499 17
+3 0.333914145 1
+4 0.000346748 17
+3 0.201475101 1
+4 0.000325034 17
+3 0.253845553 1
+4 0.000353298 17
+3 0.217519276 1
+4 0.000317614 17
+3 0.197699767 1
+4 0.000341367 17
+3 0.279697713 1
+4 0.000347395 4
+3 4.391931838 1
+4 0.000382826 9
+3 0.159420283 1
+4 0.000335654 1
+3 0.111719368 1
+4 0.000347944 1
+4 0.000972742 10
+4 0.000403494 61
+3 2.110386452 1
+4 0.000369178 39
+3 17.034834764 1
+4 0.000383986 19
+3 0.497234888 1
+4 0.000337602 20
+3 0.084271274 1
+4 0.000325667 21
+3 0.082062227 1
+4 0.000307956 20
+3 0.083458142 1
+4 0.000378024 18
+3 0.083199922 1
+4 0.000337838 17
+3 0.082989013 1
+4 0.000313158 19
+3 0.082832977 1
+4 0.000348033 19
+3 0.083541463 1
+4 0.000328121 19
+3 0.082929197 1
+4 0.000313910 18
+3 0.083452781 1
+4 0.000309767 17
+3 0.082767924 1
+4 0.000311219 19
+3 0.083015240 1
+4 0.000346502 20
+3 0.082732345 1
+4 0.000313155 19
+3 0.083514591 1
+4 0.000374006 37
+3 0.083202819 1
+4 0.000344767 46
+3 0.082762877 1
+4 0.000359216 94
+3 0.083311882 1
+4 0.000376838 152
+3 0.082723059 1
+4 0.000363037 47
+3 0.083441576 1
+4 0.000382240 98
+3 0.083381556 1
+4 0.000379171 152
+3 0.082387028 1
+4 0.000371299 86
+3 0.083603851 1
+4 0.000352149 38
+3 13.187291173 1
+4 0.000364475 20
+3 0.201591490 1
+4 0.000341083 19
+3 0.181550902 1
+4 0.000331003 16
+3 0.351762681 1
+4 0.000348213 16
+3 0.218037835 1
+4 0.000314279 19
+3 0.141360603 1
+4 0.000334775 16
+3 0.217421174 1
+4 0.000347537 16
+3 1.613955996 1
+4 0.000399838 20
+3 0.153400809 1
+4 0.000326442 4
+3 0.605790128 1
+4 0.000375715 16
+3 0.159963188 1
+4 0.000369091 20
+3 0.175264072 1
+4 0.000390057 17
+3 0.201687192 1
+4 0.000344551 16
+3 0.157495908 1
+4 0.000339017 17
+3 0.169631706 1
+4 0.000328428 16
+3 0.325859306 1
+4 0.000351315 16
+3 0.201655096 1
+4 0.000338171 16
+3 0.197485573 1
+4 0.000406494 18
+3 0.375701536 1
+4 0.000333841 19
+3 8.552199557 1
+4 0.000384966 16
+3 0.499368787 1
+4 0.000326486 17
+3 0.083035429 1
+4 0.000395329 17
+3 0.082744859 1
+4 0.000316918 16
+3 0.083822819 1
+4 0.000348257 16
+3 2.153854370 1
+4 0.000359777 16
+3 0.454970727 1
+4 0.000381231 16
+3 2.903628235 1
+4 0.000397139 4
+3 0.137652738 1
+4 0.000370089 4
+3 14.879197379 1
+4 0.000588898 762
+3 5.222678102 1
+4 0.000550454 793
+3 0.153450247 1
+4 0.000348693 4
+3 1.341483527 1
+4 0.000389025 17
+3 0.199684507 1
+4 0.000320075 24
+3 0.119439232 1
+4 0.000384750 34
+3 0.143774044 1
+4 0.000316257 34
+3 0.079693380 1
+4 0.000378889 34
+3 0.111870144 1
+4 0.000321397 34
+3 0.191442427 1
+4 0.000335188 35
+3 0.495698254 2
+4 0.000347889 34
+3 0.135636537 1
+4 0.000331297 17
+3 0.169760444 1
+4 0.000355278 17
+3 0.165496749 1
+4 0.000346968 17
+3 0.153680419 1
+4 0.000318333 17
+3 0.125792663 1
+4 0.000339694 17
+3 0.183624102 1
+4 0.000334578 4
+3 0.153758616 1
+4 0.000342895 4
+3 0.165566675 1
+4 0.000329560 4
+3 0.137908416 1
+4 0.000404009 7
+3 0.349276207 1
+4 0.000346136 5
+3 18.160593708 1
+4 0.000363397 19
+3 0.337569975 1
+4 0.000330696 20
+3 0.165697402 1
+4 0.000342986 20
+3 0.169507433 1
+4 0.000333203 19
+3 0.413625250 1
+4 0.000359561 20
+3 0.271674243 1
+4 0.000361874 17
+3 0.169540245 1
+4 0.000346444 17
+3 0.173734662 1
+4 0.000349677 17
+3 0.169738408 1
+4 0.000351974 17
+3 0.197583944 1
+4 0.000319564 18
+3 0.185640509 1
+4 0.000343136 17
+3 0.285756461 1
+4 0.000326809 17
+3 0.232292994 1
+4 0.000388610 17
+3 0.110906483 1
+4 0.000307183 24
+3 0.623734540 2
+4 0.000376785 33
+3 0.223759608 1
+4 0.000342357 24
+3 0.160654122 1
+4 0.000315471 32
+3 0.134793593 1
+4 0.000329562 32
+3 0.167385993 1
+4 0.000319999 32
+3 0.087692138 1
+4 0.000358351 32
+3 0.199660073 1
+4 0.000344751 33
+3 0.407927178 2
+4 0.000420648 36
+3 0.543366155 1
+4 0.000340478 17
+3 0.375853191 1
+4 0.000378380 18
+3 0.217433113 1
+4 0.000328987 17
+3 1.405781702 1
+4 0.000347724 4
+3 0.137652772 1
+4 0.000364203 4
+3 2.253770331 1
+4 0.000337139 17
+3 0.257778530 1
+4 0.000387409 17
+3 3.269870180 1
+4 0.000343585 17
+3 0.271446679 1
+3 0.095813564 1
+4 0.000386545 28
+3 0.359667828 1
+4 0.000342076 18
+3 0.143686060 1
+4 0.000393273 18
+3 0.095738892 1
+4 0.000330771 19
+3 6.037626129 1
+4 0.110016314 38
+3 23.541898745 1
+4 0.000366452 17
+3 0.094576810 1
+4 0.000364105 18
+3 0.439953748 1
+4 0.000334744 17
+3 0.143475210 1
+4 0.000412452 17
+3 0.499995276 1
+4 0.000361066 18
+3 0.083070390 1
+4 0.000359463 17
+3 0.083581776 1
+4 0.000306816 17
+3 0.083458877 1
+4 0.000343769 18
+3 0.082669993 1
+4 0.000315571 17
+3 0.083198248 1
+4 0.000384370 17
+3 0.083694700 1
+4 0.000314496 18
+3 0.082887020 1
+4 0.000375129 17
+3 0.083594365 1
+4 0.000312188 17
+3 20.247243326 1
+4 0.000431676 23
+3 0.239385283 1
+4 0.000340447 23
+3 0.399672296 1
+4 0.000362638 24
+3 0.295931090 1
+4 0.000348452 19
+3 0.359425905 2
+4 0.000382605 36
+3 0.154451375 1
+4 0.000362061 19
+3 0.148799278 1
+4 0.000368235 20
+3 0.279663320 1
+4 0.000353554 24
+3 0.295672037 1
+4 0.000346773 19
+3 0.623692871 2
+4 0.000390137 10
+3 0.167677853 1
+4 0.000353614 1
+3 0.135699710 1
+4 0.000381724 1
+4 0.000311595 71
+3 35.888691525 1
+4 0.000380571 39
+3 5.423523165 1
+4 0.000341236 17
+3 0.217798218 1
+4 0.000344187 19
+3 0.397690449 1
+4 0.000366442 20
+3 2.513732807 1
+4 0.000387679 17
+3 0.197384328 1
+4 0.000331356 19
+3 0.335674728 1
+4 0.000339958 20
+3 0.185593608 1
+4 0.000311937 17
+3 1.334051578 1
+3 0.359853017 1
+3 0.155216835 1
+4 0.000430781 184
+3 0.140258689 1
+4 0.000335231 41
+3 0.169686067 1
+4 0.000345717 16
+3 0.157818890 1
+4 0.000347461 16
+3 0.303708008 1
+4 0.000444404 233
+3 4.759801138 1
+4 0.000363526 41
+3 0.499823451 1
+4 0.000347010 16
+3 0.083712879 1
+4 0.000317597 16
+3 0.082796797 1
+4 0.000326708 16
+3 0.083007561 1
+4 0.000341557 16
+3 0.083728222 1
+4 0.000327262 16
+3 0.082587059 1
+4 0.000378164 18
+3 0.082926527 1
+4 0.000327341 16
+3 1.312661937 1
+4 0.000398033 17
+3 0.709613047 1
+4 0.000346253 17
+3 0.169590463 1
+4 0.000412545 16
+3 0.421534122 1
+4 0.000403937 15
+3 0.991714169 1
+4 0.000427131 13
+3 0.241399307 1
+4 0.000356090 17
+3 0.453824047 1
+4 0.000379495 18
+3 0.320876867 1
+4 0.000359400 21
+3 0.782515366 1
+4 0.000389596 17
+3 0.217394721 1
+4 0.000363849 16
+3 3.470053717 1
+4 0.000447022 15
+3 0.345406299 1
+4 0.000347561 9
+3 24.583114102 1
+4 0.000394154 24
+3 0.286974944 1
+4 0.000370130 25
+3 0.135644134 1
+4 0.000373238 26
+3 0.263746811 1
+4 0.000351969 28
+3 0.145520398 1
+4 0.000370469 30
+3 0.093587014 1
+4 0.000329265 29
+3 0.055637504 1
+4 0.000358894 28
+3 0.079593004 1
+4 0.000356934 28
+3 0.175807494 1
+4 0.000369155 28
+3 0.335557147 2
+4 0.000401615 24
+3 0.169616376 1
+4 0.000346995 17
+3 0.365655153 1
+3 0.079819032 1
+4 0.000359693 4
+3 0.351689460 1
+3 0.088197773 1
+4 0.000344617 28
+3 0.111462078 1
+4 0.000376654 18
+3 0.664739248 1
+4 0.110064490 37
+3 3.473586517 1
+4 0.000625635 794
+3 1.015071437 1
+4 0.000386082 34
+3 0.499932551 1
+4 0.000430947 92
+3 0.082826258 1
+4 0.000386639 96
+3 0.082746645 1
+4 0.000372811 93
+3 0.083326197 1
+4 0.000379790 44
+3 0.083016049 1
+4 0.000432717 34
+3 0.083078196 1
+4 0.000361275 76
+3 9.652630453 1
+4 0.000418614 115
+3 0.497876596 1
+4 0.000388240 132
+3 0.082670210 1
+4 0.000418183 44
+3 0.082847437 1
+4 0.000361215 115
+3 0.083045506 1
+4 0.000420881 132
+3 0.083327586 1
+4 0.000358546 44
+3 0.173799235 1
+4 0.000399280 16
+3 0.500016895 1
+4 0.000351978 16
+3 0.082774164 1
+4 0.000347894 16
+3 0.083041816 1
+4 0.000321530 16
+3 0.083247592 1
+4 0.000333520 16
+3 0.083307658 1
+4 0.000353112 16
+3 0.083097481 1
+4 0.000378219 18
+3 0.586188721 1
+4 0.000361755 9
+3 0.135471484 1
+4 0.000324248 1
+3 0.103678962 1
+4 0.000339098 1
+4 0.000603521 69
+3 1.103030135 1
+4 0.000396260 37
+3 0.169851746 1
+4 0.000331487 16
+3 6.261932030 1
+4 0.000339833 16
+3 0.265472283 1
+4 0.000313612 18
+3 0.381799465 1
+4 0.000334484 18
+3 0.951572234 1
+4 0.000348900 17
+3 1.735823832 1
+4 0.000404114 17
+3 0.201548379 1
+4 0.000334137 19
+3 0.197764185 1
+4 0.000410260 18
+3 0.177546445 1
+4 0.000371907 20
+3 2.429781261 1
+4 0.000610228 797
+3 0.879438495 1
+4 0.000585346 869
+3 10.951858610 1
+4 0.000440909 15
+3 10.799940923 1
+4 0.000341886 10
+3 0.303350678 1
+4 0.000343017 1
+3 0.167643177 1
+4 0.000374399 1
+3 0.175754245 1
+4 0.000347929 1
+3 0.647646181 1
+4 0.000353274 1
+3 0.175767904 1
+4 0.000379161 1
+3 0.271525075 1
+4 0.000347821 38
+3 1.639717397 1
+4 0.000588717 732
+3 3.839532834 1
+4 0.000340486 10
+3 0.087734228 1
+4 0.000652134 783
+3 3.535513042 1
+4 0.000356527 19
+3 0.500583414 1
+4 0.000399680 17
+3 0.083518452 1
+4 0.000321724 21
+3 0.083699460 1
+4 0.000391997 20
+3 0.082616070 1
+4 0.000323285 20
+3 0.083314663 1
+4 0.000339676 19
+3 0.083051219 1
+4 0.000339791 16
+3 0.083546343 1
+4 0.000381123 20
+3 0.083323899 1
+4 0.000324578 20
+3 0.082941783 1
+4 0.000349620 17
+3 0.082666144 1
+4 0.000313653 19
+3 0.082949171 1
+4 0.000384689 34
+3 0.083319014 1
+4 0.000363061 76
+3 0.084397062 1
+4 0.000456607 118
+3 0.082312231 1
+4 0.000361616 133
+3 1.734451501 1
+4 0.000426216 47
+3 0.381438416 1
+4 0.000343299 20
+3 0.455708441 1
+3 0.122319633 1
+4 0.000364578 29
+3 0.245415055 1
+4 0.000343142 39
+3 0.500119816 1
+4 0.000342403 19
+3 0.083415591 1
+4 0.000325276 15
+3 0.083065498 1
+4 0.000321760 18
+3 0.083456733 1
+4 0.000371619 20
+3 0.083754254 1
+4 0.000325312 17
+3 0.082940409 1
+4 0.000332374 20
+3 0.082932899 1
+4 0.000312083 18
+3 0.083389380 1
+4 0.000315540 18
+3 0.083010926 1
+4 0.000317392 20
+3 0.082698803 1
+4 0.000315490 20
+3 0.083225849 1
+4 0.000330847 19
+3 0.082970489 1
+4 0.000337374 19
+3 0.083452587 1
+4 0.000341626 17
+3 0.083398248 1
+4 0.000383430 19
+3 0.573224781 1
+4 0.000391364 109
+3 0.871546645 1
+4 0.000360210 17
+3 0.577727169 1
+4 0.000331132 16
+3 0.229592433 1
+4 0.000362804 16
+3 1.057743977 1
+4 0.000350083 17
+3 1.765762623 1
+4 0.000428124 16
+3 1.383694692 1
+4 0.000358331 17
+3 0.297640829 1
+4 0.000327893 16
+3 4.910395239 1
+4 0.000406035 31
+3 1.397314945 21
+4 0.000359083 37
+3 1.609793354 1
+4 0.000384455 17
+3 1.696416598 1
+4 0.109980578 35
+3 13.121523751 1
+4 0.000366600 16
+3 0.809510869 1
+4 0.000352286 19
+3 0.317591826 1
+4 0.000394635 16
+3 0.143487508 1
+4 0.000321175 15
+3 0.217761934 1
+4 0.000319186 17
+3 0.149758961 1
+4 0.000324585 17
+3 0.161655829 1
+4 0.000324805 16
+3 0.325490170 1
+4 0.000367580 16
+3 0.391654555 1
+4 0.000365332 4
+3 0.159725048 1
+4 0.000383846 16
+3 0.161781642 1
+4 0.000363862 16
+3 0.133365775 1
+4 0.000316864 16
+3 0.113801837 1
+4 0.000380328 16
+3 0.117553141 1
+4 0.000313111 16
+3 0.145746732 1
+4 0.000370316 16
+3 0.301631901 1
+4 0.000324591 4
+3 0.223737158 1
+4 0.000420746 16
+3 0.295476548 1
+4 0.000341334 16
+3 0.767843686 1
+4 0.000394438 16
+3 0.695710039 1
+4 0.000332074 16
+3 0.471539808 1
+4 0.000386183 16
+3 0.495629753 1
+4 0.000364721 16
+3 0.169471254 1
+4 0.000395600 17
+3 0.157824880 1
+4 0.000343854 16
+3 0.439781914 1
+4 0.000356489 16
+3 0.111383855 1
+4 0.000325492 4
+3 0.185756624 1
+4 0.000356705 4
+3 0.117635696 1
+4 0.000335667 6
+3 0.151711751 1
+4 0.000414281 23
+3 0.231635316 1
+4 0.000328243 24
+3 0.087619785 1
+4 0.000356361 24
+3 0.223603835 1
+4 0.000338573 24
+3 0.479888257 1
+4 0.000351910 16
+3 0.071516472 1
+4 0.000333981 17
+3 0.167572694 1
+4 0.000344816 25
+3 0.103655085 1
+4 0.000349044 24
+3 0.031695949 1
+4 0.000326415 24
+3 0.774499266 1
+4 0.110011972 32
+3 0.035262855 1
+4 0.000332976 30
+3 0.168385201 1
+4 0.000354280 24
+3 0.494758039 2
+4 0.000380367 33
+3 0.303743033 1
+3 0.139108924 1
+4 0.000390353 47
+3 8.332910848 1
+4 0.000343885 10
+3 0.143572664 1
+4 0.000304229 1
+3 0.071928794 1
+4 0.000353615 1
+4 0.000389971 70
+3 4.743276758 1
+4 0.000417445 36
+3 0.499719386 1
+4 0.000360638 17
+3 0.083358699 1
+4 0.000352661 20
+3 0.082721814 1
+4 0.000313192 17
+3 3.870979071 1
+4 0.000383594 17
+3 0.498026409 1
+4 0.000375845 19
+3 0.083003383 1
+4 0.000386986 17
+3 0.083129783 1
+4 0.000326125 20
+3 0.083434987 1
+4 0.000323584 17
+3 0.084191069 1
+4 0.000320855 17
+3 0.081883819 1
+4 0.000322254 19
+3 0.083758626 1
+4 0.000327114 16
+3 0.084057046 1
+4 0.000392717 21
+3 0.082125748 1
+4 0.000322579 17
+3 0.083188434 1
+4 0.000311301 17
+3 0.084080430 1
+4 0.000373902 19
+3 0.082827532 1
+4 0.000358945 119
+3 0.083087590 1
+4 0.000373025 133
+3 0.083085520 1
+4 0.000383822 47
+3 0.082890926 1
+4 0.000432347 34
+3 0.083149409 1
+4 0.000365709 74
+3 0.083323885 1
+4 0.000360498 72
+3 0.082904465 1
+4 0.000363469 92
+3 0.083277200 1
+4 0.000353641 47
+3 0.083035549 1
+4 0.000364001 34
+3 0.083024694 1
+4 0.000354147 85
+3 0.436548943 1
+4 0.000391764 17
+3 0.501119745 1
+4 0.000334290 18
+3 0.082300439 1
+4 0.000338687 20
+3 0.083169014 1
+4 0.000322771 18
+3 0.082941715 1
+4 0.000309774 17
+3 0.083080152 1
+4 0.000331539 17
+3 0.083061608 1
+4 0.000316191 18
+3 0.083320427 1
+4 0.000363945 20
+3 0.254308068 1
+4 0.000313941 19
+3 0.392092048 1
+4 0.000561957 754
+3 4.767660373 1
+4 0.000562641 699
+3 1.224209205 1
+4 0.000584624 755
+3 1.086712767 1
+4 0.000554301 858
+3 173.398125109 1
+4 0.000597114 751
+3 3.710424528 1
+4 0.000434863 92
+3 0.499993413 1
+4 0.000383464 96
+3 0.084353418 1
+4 0.000379985 93
+3 0.082259439 1
+4 0.000359586 44
+3 0.083467923 1
+4 0.000352713 34
+3 0.082973101 1
+4 0.000356854 76
+3 0.083846608 1
+4 0.000371618 115
+3 25.122087962 1
+4 0.000567705 880
+3 7.942980934 1
+4 0.000356889 15
+3 0.500276063 1
+4 0.000385987 15
+3 0.083330134 1
+4 0.000317600 15
+3 0.082887076 1
+4 0.000314367 15
+3 0.083197735 1
+4 0.000324356 15
+3 0.083567058 1
+4 0.000337583 15
+3 0.082868538 1
+4 0.000310929 17
+3 0.083759940 1
+4 0.000324532 18
+3 0.082131535 1
+4 0.000349180 16
+3 0.083376306 1
+4 0.000311864 17
+3 0.083677997 1
+4 0.000324080 16
+3 0.083654014 1
+4 0.000313726 16
+3 0.083737061 1
+4 0.000314814 18
+3 0.082964153 1
+4 0.000336715 16
+3 0.082726858 1
+4 0.000312325 16
+3 0.083101948 1
+4 0.000348739 16
+3 0.083329035 1
+4 0.000320928 16
+3 0.083216977 1
+4 0.000319246 18
+3 0.082672314 1
+4 0.000307806 16
+3 0.084325873 1
+4 0.000348140 17
+3 0.082422366 1
+4 0.000363604 44
+3 0.083049231 1
+4 0.000363395 97
+3 0.082753897 1
+4 0.000393840 91
+3 0.083559486 1
+4 0.000386767 44
+3 0.082939324 1
+4 0.000373976 95
+3 0.082706022 1
+4 0.000386850 92
+3 0.083500496 1
+4 0.000358572 44
+3 0.885104924 1
+4 0.000421535 34
+3 39.951501347 1
+4 0.000583653 755
+3 0.926849683 1
+4 0.000617545 735
+3 0.559514961 1
+4 0.000566334 818
+3 0.959282192 1
+4 0.000479931 72
+3 0.499546453 1
+4 0.000396574 62
+3 0.083434377 1
+4 0.000398163 37
+3 40.722109863 1
+4 0.000577903 859
+3 1.430611693 1
+4 0.000391510 15
+3 0.500163171 1
+4 0.000337607 15
+3 0.083759610 1
+4 0.000359738 17
+3 0.082655315 1
+4 0.000343770 17
+3 0.082732761 1
+4 0.000335851 15
+3 0.082743430 1
+4 0.000319388 16
+3 0.083822318 1
+4 0.000352233 15
+3 0.083089759 1
+4 0.000321641 17
+3 0.082825352 1
+4 0.000349164 18
+3 0.083791797 1
+4 0.000325299 16
+3 0.083068212 1
+4 0.000370780 16
+3 0.083765591 1
+4 0.000323828 16
+3 0.082813122 1
+4 0.000339110 16
+3 0.083608168 1
+4 0.000322280 18
+3 0.083010845 1
+4 0.000341757 16
+3 9.471316892 1
+4 0.000343512 17
+3 0.498328117 1
+4 0.000368632 16
+3 0.083500772 1
+4 0.000364604 16
+3 0.083649960 1
+4 0.000343547 16
+3 0.083296348 1
+4 0.000348931 16
+3 0.084231077 1
+4 0.000367471 16
+3 0.081395597 1
+4 0.000362010 92
+3 0.083224218 1
+4 0.000388863 44
+3 0.083188442 1
+4 0.000366450 34
+3 0.083088798 1
+4 0.000405215 93
+3 15.687256348 1
+4 0.000365620 16
+3 0.499769431 1
+4 0.000377466 18
+3 0.082966183 1
+4 0.000326121 16
+3 0.083061395 1
+4 0.000345310 16
+3 0.082797922 1
+4 0.000323222 16
+3 0.083003183 1
+4 0.000322430 16
+3 0.083640542 1
+4 0.000343474 16
+3 0.082662134 1
+4 0.000329010 16
+3 0.083433826 1
+4 0.000326679 16
+3 0.717295792 1
+4 0.000362489 17
+3 9.246256414 1
+3 0.121762406 1
+4 0.000372802 29
+3 0.261669317 1
+4 0.000374347 103
+3 0.471606299 1
+4 0.000349599 18
+3 0.177723317 1
+4 0.000320525 18
+3 0.149531376 1
+4 0.000317570 17
+3 0.145788692 1
+4 0.000327977 17
+3 0.261597392 1
+4 0.000354466 18
+3 0.360741810 1
+4 0.000357309 17
+3 0.200460328 1
+4 0.000321081 17
+3 0.149905846 1
+4 0.000357241 17
+3 6.279812516 1
+4 0.000353334 4
+3 0.599555710 1
+4 0.000335743 17
+3 0.127714321 1
+3 0.080017049 1
+4 0.000382513 28
+3 0.639577091 1
+4 0.000358401 18
+3 0.767003151 1
+4 0.109989259 37
+3 0.187151499 1
+4 0.000346591 40
+3 0.287392683 1
+4 0.000385092 40
+3 0.343723079 2
+4 0.000368831 33
+3 0.463491583 1
+4 0.000435988 59
+3 0.327520206 1
+4 0.000348395 18
+3 4.636741822 7
+4 0.000401747 25
+3 0.339403889 1
+4 0.000331128 17
+3 33.096554304 2
+4 0.000410601 36
+7 0.000507670 TSTP
+7 33.592008232 CONT
+4 0.000786179 7
+4 0.000280514 799
+3 2.606784744 1
+4 0.000379428 31
+3 4.594248745 20
+4 0.000361507 37
+3 0.325405936 1
+4 0.000357059 17
+3 7.476120404 34
+4 0.000555940 52
+3 0.325399978 1
+4 0.000542024 17
+3 4.543750298 34
+4 0.000453705 98
+3 4.538399418 1
+3 0.034736034 1
+4 0.000347439 9
+3 0.111485082 1
+4 0.000389472 1
+3 0.191836691 1
+4 0.000349003 43
+3 0.623558211 1
+4 0.000440117 33
+3 0.143477527 1
+4 0.000352203 17
+3 0.231866390 1
+4 0.000362754 18
+3 0.159597752 1
+4 0.000336335 18
+3 0.167693314 1
+4 0.000347364 19
+3 0.207554391 1
+4 0.000341936 15
+3 0.343822076 1
+4 0.000344344 16
+3 0.215594862 1
+4 0.000368821 17
+3 0.135544701 1
+4 0.000334504 17
+3 0.047720903 1
+4 0.000328578 17
+3 0.183610492 1
+4 0.000331143 17
+3 0.271651176 1
+4 0.000376779 17
+3 0.503763620 2
+4 0.000394028 36
+3 37.745595101 1
+4 0.000349121 19
+3 0.217034267 1
+4 0.000399334 20
+3 0.205427082 1
+4 0.000354892 16
+3 1.065863721 1
+4 0.000425449 19
+3 0.533513377 1
+4 0.000380448 20
+3 0.567672251 1
+3 0.130101959 1
+4 0.000424973 29
+3 0.269547621 1
+4 0.000352307 41
+3 0.161465729 1
+4 0.000365436 20
+3 0.149596147 1
+4 0.000333491 20
+3 0.153692873 1
+4 0.000313810 15
+3 0.133632562 1
+4 0.000321132 20
+3 0.311801949 1
+4 0.000361249 104
+3 0.639725752 1
+3 0.135963947 1
+4 0.000352421 84
+3 0.311597013 1
+3 0.064147385 1
+4 0.000357800 29
+3 1.630121451 7
+4 0.000369118 25
+3 0.313043225 2
+4 0.000350825 37
+3 0.255962410 1
+3 0.047636991 1
+4 0.000408675 6
+3 1.608788858 1
+4 0.000456490 18
+3 1.238824509 1
+4 0.000384430 25
+3 4.331991931 36
+4 0.000410721 95
+3 0.971262804 1
+3 0.079976027 1
+4 0.000361427 28
+3 0.287589060 1
+4 0.000339987 19
+3 2.168861266 4
+4 0.000371567 28
+3 1.252918183 5
+4 0.000370132 23
+3 0.699263778 1
+4 0.110142043 33
+3 0.199951622 1
+4 0.000324229 22
+3 0.145600189 1
+4 0.000345335 20
+3 0.149617621 1
+4 0.000318206 16
+3 0.153737423 1
+4 0.000312236 19
+3 0.133659447 1
+4 0.000325207 20
+3 0.129660650 1
+4 0.000317376 20
+3 0.133666439 1
+4 0.000389246 47
+3 0.161655933 1
+4 0.000362612 99
+3 0.117684704 1
+4 0.000437356 94
+3 0.177589087 1
+4 0.000369371 47
+3 0.285712479 1
+4 0.000324828 20
+3 0.360734950 1
+3 0.112810885 1
+4 0.000351088 29
+3 0.245748660 1
+4 0.000356700 43
+3 0.153487510 1
+4 0.000317802 19
+3 0.157776976 1
+4 0.000397700 20
+3 0.161456001 1
+4 0.000324479 20
+3 0.141774119 1
+4 0.000336573 19
+3 0.153774037 1
+4 0.000386267 20
+3 0.141530271 1
+4 0.000359167 20
+3 0.153608292 1
+4 0.000322263 19
+3 0.333868354 1
+4 0.000409765 20
+3 0.311476384 1
+4 0.000372037 100
+3 2.152494115 1
+3 0.079338693 1
+4 0.000362088 29
+3 0.315948467 7
+4 0.000515412 67
+3 0.323213155 2
+4 0.000377947 33
+3 0.535531343 1
+3 0.047994706 1
+4 0.000354636 6
+3 2.440374530 1
+4 0.000373870 24
+3 3.805683567 39
+4 0.000449189 135
+3 1.001622387 1
+4 0.000369665 62
+3 0.479049305 2
+4 0.000365282 34
+3 0.143687740 1
+4 0.000360857 24
+3 0.159547482 1
+4 0.000343495 19
+3 1.880106562 9
+4 0.000356396 33
+3 0.627014310 1
+4 0.110003044 33
+3 13.303015767 1
+4 0.000429375 17
+3 0.193335351 1
+4 0.000328035 21
+3 0.485715287 1
+4 0.000337050 22
+3 9.129944515 1
+4 0.000391862 17
+3 0.498215899 1
+4 0.000338218 22
+3 0.082904375 1
+4 0.000355741 20
+3 0.082657933 1
+4 0.000328584 16
+3 0.084061572 1
+4 0.000314004 19
+3 0.082824895 1
+4 0.000324312 20
+3 0.083443491 1
+4 0.000334772 20
+3 0.082809770 1
+4 0.000334535 19
+3 0.082798218 1
+4 0.000313383 21
+3 0.243187561 1
+4 0.000365955 20
+3 0.500230870 1
+4 0.000341683 20
+3 0.083274854 1
+4 0.000325193 20
+3 0.082818560 1
+4 0.000308637 19
+3 0.083960978 1
+4 0.000333325 20
+3 0.426000229 1
+4 0.000336973 20
+3 0.213830366 1
+3 0.500687773 1
+4 0.000446693 97
+3 0.082796026 1
+3 0.083635363 1
+4 0.000355972 48
+3 0.082901407 1
+3 0.084268407 1
+4 0.000398718 30
+3 0.082863130 1
+3 0.083385320 1
+4 0.000346105 97
+3 0.083059996 1
+3 0.083058962 1
+4 0.000381019 89
+3 0.083075946 1
+3 0.206334017 1
+4 0.000373633 91
+3 0.181859768 1
+3 0.169812993 1
+4 0.000375620 49
+3 0.165644564 1
+3 0.185971061 1
+4 0.000363444 92
+3 0.165789845 1
+3 0.385925308 1
+4 0.000391649 101
+3 0.365499576 1
+4 0.000350679 18
+3 0.500122316 1
+4 0.000344882 16
+3 0.082779027 1
+4 0.000333228 16
+3 0.082804862 1
+4 0.000310371 16
+3 0.082768243 1
+4 0.000428173 16
+3 0.083085458 1
+4 0.000322093 17
+3 0.082817450 1
+4 0.000373640 44
+3 0.082831867 1
+4 0.000374277 34
+3 0.083265891 1
+4 0.000400726 54
+3 0.082799250 1
+4 0.000359395 71
+3 0.083042042 1
+4 0.000421075 112
+3 0.205828346 1
+4 0.000350861 16
+3 0.500128122 1
+4 0.000374088 16
+3 0.082996870 1
+4 0.000316414 16
+3 0.083574926 1
+4 0.000330608 18
+3 0.083434733 1
+4 0.000319073 16
+3 0.082945777 1
+4 0.000327451 17
+3 0.083062480 1
+4 0.000326098 16
+3 12.468055977 1
+4 0.000403075 16
+3 0.229340834 1
+4 0.000334437 16
+3 0.170011338 1
+4 0.000350252 16
+3 305.080853416 1
+4 0.000357297 16
+3 0.499712144 1
+4 0.000390246 16
+3 0.082811528 1
+4 0.000342959 16
+3 0.082280939 1
+4 0.000605643 16
+3 0.083090027 1
+4 0.000350823 17
+3 0.082792526 1
+4 0.000353048 16
+3 0.082663170 1
+4 0.000369943 16
+3 0.083655848 1
+4 0.000418055 18
+3 0.083146383 1
+4 0.000405476 16
+3 0.082986955 1
+4 0.000338767 16
+3 0.083275055 1
+4 0.000521216 58
+3 0.082562989 1
+4 0.000640961 34
+3 0.083339019 1
+4 0.000398237 61
+3 0.082783475 1
+4 0.000397557 63
+3 0.185961846 1
+4 0.000350742 16
+3 0.153606324 1
+4 0.000351134 16
+3 0.150396884 1
+4 0.000351210 18
+3 0.136918460 1
+4 0.000371616 16
+3 0.117674373 1
+4 0.000356828 16
+3 0.145572057 1
+4 0.000367855 16
+3 0.309608021 1
+4 0.000435564 32
+3 0.080303026 1
+4 0.000348265 18
+3 0.167081174 1
+4 0.000362195 18
+3 0.287604394 1
+4 0.000365589 18
+3 0.119596079 1
+4 0.000332452 17
+3 0.423673342 1
+4 0.000366852 18
+3 0.160327894 1
+4 0.000360262 18
+3 0.158978615 1
+4 0.000364156 18
+3 0.575597191 1
+4 0.000344260 17
+3 0.111804373 1
+4 0.000347689 18
+3 0.439457400 2
+4 0.000358797 31
+3 0.281796283 1
+4 0.000352656 17
+3 0.357515641 1
+4 0.000370017 21
+3 0.559558022 1
+4 0.000448963 31
+3 0.079815133 1
+4 0.000348358 18
+3 0.591688138 2
+4 0.000374344 32
+3 0.327539528 1
+4 0.000330647 9
+3 0.143633680 1
+4 0.000590716 1
+3 0.087503013 1
+4 0.000756019 11
+4 0.000400148 61
+3 31.448295918 1
+4 0.000629257 883
+3 5.111258039 1
+4 0.000351808 17
+3 0.499703034 1
+4 0.000400652 18
+3 0.082635319 1
+4 0.000540967 17
+3 0.082868149 1
+4 0.000494295 17
+3 0.082901520 1
+4 0.000313138 18
+3 0.083421936 1
+4 0.000373402 20
+3 0.083218793 1
+4 0.000328879 17
+3 0.083214530 1
+4 0.000346025 17
+3 0.082578627 1
+4 0.000346003 18
+3 8.150269658 1
+4 0.000363903 18
+3 0.213378491 1
+4 0.000461823 20
+3 0.186770439 1
+4 0.000581424 18
+3 0.164286182 1
+4 0.000380816 16
+3 4.903982535 1
+4 0.000367656 17
+3 0.153510666 1
+4 0.000341938 18
+3 0.149697119 1
+4 0.000343747 19
+3 0.211556218 1
+4 0.000342054 17
+3 0.195592296 1
+4 0.000378550 20
+3 0.463600866 1
+3 0.106134844 1
+4 0.000357633 30
+3 0.261639119 1
+4 0.000384154 36
+3 0.145573011 1
+4 0.000357779 18
+3 0.677693415 1
+4 0.000439066 20
+3 0.145508251 1
+4 0.000342164 18
+3 0.149604994 1
+4 0.000364306 16
+3 0.161842107 1
+4 0.000355461 18
+3 0.221457848 1
+4 0.000361987 17
+3 0.311692567 1
+4 0.000369625 22
+3 0.879888862 1
+4 0.000711855 830
+3 1.271520325 1
+4 0.000610571 862
+3 1.279280274 1
+4 0.000383892 18
+3 0.499390638 1
+4 0.000348084 18
+3 0.083076480 1
+4 0.000413453 18
+3 0.083421410 1
+4 0.000354474 18
+3 0.082785003 1
+4 0.000367550 18
+3 0.082898553 1
+4 0.000341109 17
+3 0.083529978 1
+4 0.000385285 19
+3 0.083015081 1
+4 0.000339409 20
+3 0.082823787 1
+4 0.000429733 21
+3 0.083276952 1
+4 0.000352359 19
+3 0.083412063 1
+4 0.000367975 17
+3 0.082673286 1
+4 0.000343524 20
+3 0.721130396 1
+3 0.154070246 1
+4 0.000379984 84
+3 0.229604850 1
+3 0.170532585 1
+4 0.000436692 117
+3 0.285020611 1
+3 0.170262550 1
+4 0.000389631 74
+3 0.197440319 1
+3 0.121861653 1
+4 0.000376338 46
+3 0.197838152 1
+3 0.113796320 1
+4 0.000378746 39
+3 0.349874483 1
+4 0.000398965 10
+3 0.199647430 1
+4 0.000331110 1
+3 0.071427202 1
+4 0.000348580 1
+4 0.000415405 70
+3 2.887476526 1
+4 0.000583736 861
+3 5.975968449 1
+4 0.000599183 878
+3 1.639218505 1
+4 0.000676829 840
+3 18.640117849 1
+4 0.000708879 878
+3 1.351029379 1
+4 0.000338065 18
+3 0.551726408 1
+4 0.000638251 708
+3 1.592390050 1
+4 0.000614038 17
+3 0.499281201 1
+4 0.000361723 18
+3 0.082802459 1
+4 0.000331499 15
+3 0.082807536 1
+4 0.000364739 15
+3 0.083525030 1
+4 0.000333271 15
+3 0.083423790 1
+4 0.000431876 15
+3 0.082820704 1
+4 0.000334049 15
+3 0.083016323 1
+4 0.000374775 15
+3 0.083125769 1
+4 0.000453713 17
+3 0.082969191 1
+4 0.000428278 18
+3 0.083106971 1
+4 0.000319947 16
+3 1.419992144 1
+4 0.000550351 570
+3 1.263381917 1
+4 0.000390523 76
+3 0.185466776 1
+4 0.000397981 65
+3 0.173625432 1
+4 0.000416718 36
+3 0.519672264 1
+4 0.000353401 17
+3 0.177834237 1
+4 0.000342628 15
+3 8.141768786 1
+4 0.000534125 663
+3 2.503599942 1
+4 0.000580856 741
+3 0.711629519 1
+4 0.000690980 716
+3 0.591114578 1
+4 0.000781048 597
+3 0.487249694 1
+4 0.000577707 733
+3 3.063293774 1
+4 0.000333000 16
+3 0.500323845 1
+4 0.000417908 18
+3 0.082467932 1
+4 0.000337739 16
+3 0.082923122 1
+4 0.000454304 16
+3 0.082945644 1
+4 0.000330324 18
+3 0.083710325 1
+4 0.000365034 16
+3 0.083364206 1
+4 0.000433299 17
+3 0.083042008 1
+4 0.000342279 16
+3 0.083093016 1
+4 0.000400053 17
+3 0.082978936 1
+4 0.000351761 18
+3 2.063541504 1
+4 0.000395230 54
+3 0.287753625 1
+4 0.000378037 38
+3 0.359454900 1
+4 0.000361308 19
+3 0.111878081 1
+4 0.000458391 17
+3 3.319525627 1
+4 0.000335753 18
+3 0.223942086 1
+4 0.000385710 18
+3 0.127326902 1
+4 0.000334250 18
+3 0.135655063 1
+4 0.000365659 17
+3 0.479710733 1
+4 0.000346918 17
+3 2.327788491 1
+4 0.000347750 18
+3 0.175614082 1
+4 0.000383315 18
+3 0.119598238 1
+4 0.000337943 18
+3 0.071602147 1
+4 0.000395307 18
+3 0.328027592 1
+4 0.000367378 18
+3 0.119221737 1
+4 0.000337344 18
+3 0.129844131 1
+4 0.000343188 18
+3 0.109624618 1
+4 0.000334550 18
+3 0.239511917 1
+4 0.000385675 19
+3 0.191870639 1
+4 0.000452720 18
+3 0.351475579 1
+4 0.000440246 17
+3 0.121703509 1
+4 0.000364897 18
+3 0.093347207 1
+4 0.000344195 19
+3 0.135668364 1
+4 0.000341657 17
+3 0.248582905 1
+4 0.000347392 18
+3 0.007185995 1
+4 0.000356981 18
+3 0.839249703 1
+4 0.000482206 17
+3 0.139523516 1
+4 0.000378338 17
+3 0.115728849 1
+4 0.000341072 18
+3 0.087463961 1
+4 0.000341446 18
+3 0.103741610 1
+4 0.000467615 17
+3 1.031668138 1
+4 0.000373832 18
+3 0.111444149 1
+4 0.000341171 18
+3 0.135576625 1
+4 0.000360623 18
+3 0.095768198 1
+4 0.000389785 18
+3 0.071643746 1
+4 0.000382010 17
+3 0.111541595 1
+4 0.000337322 19
+3 0.119745737 1
+4 0.000367651 18
+3 0.152010598 1
+4 0.000336790 18
+3 0.071249469 1
+4 0.000355612 18
+3 0.111595064 1
+4 0.000347300 18
+3 0.127714645 1
+4 0.000395856 18
+3 0.167639654 1
+4 0.000350440 18
+3 0.175765275 1
+4 0.000433003 18
+3 0.759538185 1
+4 0.000359089 18
+3 0.709730548 1
+4 0.109927658 33
+3 4.268095613 1
+4 0.000426077 61
+3 14.006783454 53
+4 0.000444446 71
+3 0.936872940 2
+3 0.151954890 1
+4 0.000383324 39
+3 0.471870533 1
+4 0.000369988 22
+3 1.175527431 1
+4 0.000429277 62
+3 0.239737011 1
+4 0.000341658 40
+3 0.439415420 2
+4 0.000383170 33
+3 0.175640302 1
+4 0.000349671 18
+3 0.169845963 1
+4 0.000433399 18
+3 0.197402764 1
+4 0.000346099 17
+3 0.161737299 1
+4 0.000359958 17
+3 0.157603293 1
+4 0.000746578 18
+3 0.185302491 1
+4 0.000515689 17
+3 0.293429490 1
+4 0.000369115 17
+3 51.473362785 2
+4 0.000339224 18
+3 0.320202308 1
+4 0.000376746 61
+3 0.935101651 2
+4 0.000353311 9
+3 0.111679022 1
+4 0.000316888 1
+3 0.167660090 1
+4 0.000323413 1
+3 0.191624800 1
+4 0.000319812 1
+3 0.031835341 1
+4 0.000373940 1
+3 0.127624294 1
+4 0.000367299 1
+3 0.081461257 1
+4 0.000311281 1
+3 0.069641656 1
+4 0.000295870 1
+3 0.055794153 1
+4 0.000295469 1
+3 0.335808944 1
+4 0.000319378 1
+4 0.000324449 39
+3 0.223383309 1
+4 0.000385035 21
+3 0.220343199 339
+4 0.000652037 372
+4 0.000353694 167
+3 0.506204321 2
+4 0.000364502 32
+3 0.169938430 1
+4 0.000364254 47
+3 0.181399879 1
+4 0.000405858 34
+3 0.185574231 1
+4 0.000362139 57
+3 0.149529480 1
+4 0.000386950 18
+3 0.137724101 1
+4 0.000361077 18
+3 0.157610025 1
+4 0.000349608 20
+3 0.169682124 1
+4 0.000329677 12
+3 0.181623016 1
+4 0.000355865 18
+3 0.231693664 1
+4 0.000328066 15
+3 0.103674216 1
+4 0.000411816 17
+3 0.185557476 1
+4 0.000351002 17
+3 0.693724611 1
+3 0.063986470 1
+4 0.000414948 4
+3 3.599898900 1
+4 0.000366572 6
+3 0.487570874 1
+3 0.080006699 1
+4 0.000328093 5
+3 0.807685354 1
+4 0.000391036 25
+3 1.007602547 1
+4 0.000336740 17
+3 0.495687132 1
+4 0.000388623 4
+3 0.377692091 1
+4 0.000381859 4
+3 0.197468637 1
+4 0.000381306 4
+3 0.177657772 1
+4 0.000334142 4
+3 0.149706863 1
+4 0.000371475 4
+3 0.161661316 1
+4 0.000329386 4
+3 1.093766694 1
+4 0.000420679 24
+3 4.439891434 10
+4 0.000348675 37
+3 0.352440612 1
+4 0.000403922 16
+3 0.446694400 1
+4 0.000401831 17
+3 0.479474969 1
+4 0.000375148 18
+3 0.503577308 1
+4 0.000339713 19
+3 0.151622771 1
+4 0.000390220 18
+3 0.119655893 1
+4 0.000327642 28
+3 0.095751225 1
+4 0.000334422 26
+3 0.271708489 1
+4 0.000401127 25
+3 1.479669755 1
+4 0.000379663 24
+3 0.111444615 1
+4 0.000347160 25
+3 0.007708330 1
+4 0.000390990 26
+3 0.223674227 1
+4 0.000327520 28
+3 0.143656115 1
+4 0.000344246 28
+3 0.095909278 1
+4 0.000319979 29
+3 0.127422801 1
+4 0.000406591 28
+3 0.359643369 1
+4 0.000333786 28
+3 0.327801354 1
+4 0.000378689 28
+3 0.063505708 1
+4 0.000332085 28
+3 0.111747253 1
+4 0.000337853 28
+3 0.127691320 1
+4 0.000319370 28
+3 0.079634322 1
+4 0.000373251 28
+3 0.896332843 1
+4 0.000359424 28
+3 3.653371335 12
+4 0.000369213 40
+3 0.593809187 1
+4 0.000376704 28
+3 5.631641259 12
+4 0.000391907 62
+3 2.632260317 1
+4 0.000363200 27
+3 1.094876417 1
+4 0.000392616 27
+3 0.047462202 1
+4 0.000323871 27
+3 0.223743446 1
+4 0.000385249 27
+3 0.103613398 1
+4 0.000329889 27
+3 0.063570291 1
+4 0.000363991 27
+3 0.055665091 1
+4 0.000321541 29
+3 0.119674787 1
+4 0.000339864 28
+3 1.071411539 1
+4 0.110001408 33
+3 1.122489595 1
+4 0.000350324 31
+3 0.207610556 1
+4 0.000360506 28
+3 0.271567088 1
+4 0.000338646 28
+3 0.151734822 1
+4 0.000371033 28
+3 0.103646643 1
+4 0.000337889 28
+3 0.055549958 1
+4 0.000331959 28
+3 0.071686557 1
+4 0.000324418 28
+3 0.153778079 1
+4 0.000318098 28
+3 0.719215427 1
+4 0.110062736 31
+3 0.152536689 1
+4 0.000325753 17
+3 0.727619168 1
+4 0.000368041 23
+3 6.023891164 1
+4 0.000336216 22
+3 0.095570673 1
+4 0.000318568 16
+3 0.499855446 1
+4 0.000353077 18
+3 0.082638388 1
+4 0.000326471 18
+3 0.082879773 1
+4 0.000315071 17
+3 0.083689718 1
+4 0.000333563 17
+3 0.083360147 1
+4 0.000393187 18
+3 0.083148721 1
+4 0.000322239 17
+3 0.083354258 1
+4 0.000329533 17
+3 0.082806829 1
+4 0.000339056 16
+3 0.629283940 1
+4 0.000340408 11
+3 0.389693443 1
+4 0.000353240 15
+3 0.265630733 1
+4 0.000321777 17
+3 0.181760862 1
+4 0.000380341 17
+3 0.500533616 1
+4 0.000338907 17
+3 0.082780232 1
+4 0.000308097 18
+3 0.083082240 1
+4 0.000322838 17
+3 0.082938916 1
+4 0.000311577 17
+3 0.609047833 1
+4 0.000360384 19
+3 0.281657639 1
+4 0.000341025 14
+3 0.253757988 1
+4 0.000368631 57
+3 0.215391235 1
+4 0.000331700 18
+3 0.177775992 1
+4 0.000330974 18
+3 0.173604257 1
+4 0.000320234 19
+3 0.500281398 1
+4 0.000333548 20
+3 0.083166069 1
+4 0.000351326 17
+3 0.083450551 1
+4 0.000328254 16
+3 0.083462620 1
+4 0.000342748 17
+3 0.083735805 1
+4 0.000319693 20
+3 0.082628406 1
+4 0.000308331 20
+3 0.083855967 1
+4 0.000324968 20
+3 0.082664905 1
+4 0.000308269 21
+3 0.243994363 1
+4 0.000439045 20
+3 0.197383047 1
+4 0.000357385 20
+3 1.168840173 1
+4 0.000444723 20
+3 0.184593663 1
+4 0.000330398 18
+3 0.141457719 1
+4 0.000338424 17
+3 0.161879283 1
+4 0.000319779 19
+3 0.253472046 1
+3 0.106079505 1
+4 0.000355040 29
+3 0.262307417 1
+4 0.000345156 40
+3 0.499552302 1
+4 0.000327899 17
+3 0.082863917 1
+4 0.000309780 20
+3 0.083328104 1
+4 0.000316051 20
+3 0.083075176 1
+4 0.000336459 21
+3 0.083178617 1
+4 0.000301976 20
+3 0.083526705 1
+4 0.000321293 20
+3 0.082815633 1
+4 0.000309968 20
+3 0.082956521 1
+4 0.000321659 17
+3 0.082694681 1
+4 0.000314372 20
+3 0.083698296 1
+4 0.000321880 16
+3 0.286269190 1
+4 0.000394631 17
+3 0.205612385 1
+4 0.000318983 19
+3 0.439725478 1
+4 0.000417959 92
+3 0.751637278 1
+4 0.000346364 40
+3 0.263542843 1
+4 0.000348710 94
+3 0.487682780 1
+4 0.000325684 18
+3 0.169702256 1
+4 0.000326697 17
+3 0.181639480 1
+4 0.000380232 17
+3 0.185691871 1
+4 0.000319615 18
+3 0.173642179 1
+4 0.000331672 15
+3 0.185625540 1
+4 0.000348856 9
+3 3.133919522 1
+3 0.087839815 1
+4 0.000409867 29
+3 0.479718852 1
+4 0.000363015 13
+3 0.096415306 1
+4 0.000357976 16
+3 0.190844518 1
+4 0.000336645 18
+3 0.071557006 1
+4 0.000339644 17
+3 0.079679438 1
+4 0.000345309 19
+3 0.623703198 2
+4 0.000436476 28
+3 0.457657334 1
+4 0.000341136 17
+3 0.277631894 1
+3 0.056041376 1
+4 0.000334450 5
+3 0.575568521 1
+4 0.000382138 6
+3 37.135276709 1
+4 0.109949460 1
+3 0.532250295 1
+4 0.000382436 17
+3 0.487109631 1
+4 0.000347002 17
+3 0.169619784 1
+4 0.000475929 17
+3 0.365596129 1
+4 0.000336175 17
+3 0.279601149 1
+3 0.055955606 1
+4 0.000368805 43
+3 0.215822365 1
+4 0.000335052 42
+3 11.816224383 1
+4 0.000418215 20
+3 0.273365040 1
+4 0.000342733 19
+3 6.333922854 1
+4 0.000360305 20
+3 0.217709489 1
+4 0.000409785 20
+3 0.245465986 1
+4 0.000341101 20
+3 0.311678496 1
+4 0.000371672 20
+3 1.199840369 1
+3 0.159795890 1
+3 0.121940449 1
+4 0.000340981 30
+3 0.285755030 1
+4 0.000386875 109
+3 0.367693758 1
+4 0.000333904 43
+3 0.169692707 1
+4 0.000372716 18
+3 0.173550378 1
+4 0.000337946 17
+3 0.177683749 1
+4 0.000411044 17
+3 0.165552334 1
+4 0.000328781 18
+3 0.169847364 1
+4 0.000343848 17
+3 0.349475197 1
+4 0.000338459 17
+3 0.199688020 1
+3 0.048091986 1
+4 0.000373727 69
+3 0.183600558 1
+3 0.071954096 1
+4 0.000341226 69
+3 0.143583093 1
+3 0.072123557 1
+4 0.000351541 70
+3 0.143624734 1
+3 0.071961404 1
+4 0.000345451 21
+3 0.159839162 1
+3 0.055884309 1
+4 0.000407696 105
+3 0.143631378 1
+3 0.072088178 1
+4 0.000421948 4
+3 0.159495000 1
+3 0.055895829 1
+4 0.000337136 4
+3 0.167754686 1
+3 0.056028754 1
+4 0.000406078 4
+3 0.223455056 1
+3 0.031991668 1
+4 0.000387841 5
+3 0.400327077 1
+3 0.063267058 1
+4 0.000353785 4
+3 0.383868089 1
+3 0.079890355 1
+4 0.000333697 4
+3 0.455722661 1
+4 0.000398118 17
+3 0.167692715 1
+4 0.000337065 4
+3 0.383631375 1
+3 0.087948554 1
+4 0.000343360 4
+3 0.191610058 1
+3 0.056338319 1
+4 0.000357270 4
+3 0.335332459 1
+4 0.000332694 4
+3 0.191988912 1
+4 0.000388017 24
+3 0.255408656 1
+4 0.000327531 27
+3 0.311964670 1
+4 0.000329936 27
+3 0.535282635 1
+4 0.000351203 25
+3 0.647773276 2
+4 0.000455207 36
+3 0.391515669 1
+4 0.000351281 17
+3 0.169667094 1
+4 0.000405985 15
+3 0.149563591 1
+4 0.000334695 9
+3 0.441740673 1
+4 0.000380755 16
+3 0.333631683 1
+4 0.000341236 17
+3 0.263603265 1
+4 0.000353596 17
+3 0.207649137 1
+4 0.000346167 4
+3 0.145751757 1
+4 0.000332387 7
+3 0.109543845 1
+4 0.000311179 24
+3 0.183897677 1
+4 0.000328809 20
+3 0.007351151 1
+4 0.000312790 20
+3 0.129932470 1
+4 0.000339756 22
+3 0.397882668 1
+4 0.000351199 17
+3 0.191341819 1
+4 0.000365951 18
+3 0.135882881 1
+4 0.000329121 20
+3 0.143446050 1
+4 0.000319704 20
+3 0.199607207 1
+4 0.000351943 20
+3 0.167824352 1
+4 0.000315567 20
+3 0.247614467 1
+4 0.000342691 20
+3 0.055736817 1
+4 0.000307130 21
+3 0.063593990 1
+4 0.000331799 20
+3 0.015658267 1
+4 0.000312669 20
+3 0.543777302 1
+4 0.000406003 20
+3 0.757150037 1
+4 0.110005761 33
+3 8.530119335 1
+4 0.109944528 1
+3 37.460552135 1
+3 0.097390628 1
+4 0.000319727 21
+3 1.408422266 1
+4 0.000364515 16
+3 0.200914972 1
+4 0.000369363 19
+3 0.253657346 1
+4 0.000311340 20
+3 0.145663954 1
+4 0.000402758 20
+3 1.141692288 1
+3 0.144013908 1
+3 0.122031340 1
+4 0.000500023 30
+3 0.181343851 1
+4 0.000381788 118
+3 0.159761862 1
+4 0.000369254 43
+3 0.153674795 1
+4 0.000330265 18
+3 0.173816829 1
+4 0.000349210 17
+3 0.169495023 1
+4 0.000341292 17
+3 0.181618874 1
+4 0.000352165 18
+3 0.217642100 1
+4 0.000347284 17
+3 0.229581941 1
+4 0.000395292 17
+3 0.103730075 1
+3 0.080645875 1
+4 0.000334303 27
+3 0.199303016 1
+4 0.000314887 18
+3 0.095439448 1
+4 0.000409778 18
+3 0.119587852 1
+4 0.000327680 18
+3 0.103733059 1
+4 0.000326631 24
+3 0.271534140 2
+4 0.000416677 36
+3 0.159607458 1
+4 0.000328158 15
+3 0.162032829 1
+4 0.000336834 9
+3 0.909222034 1
+3 0.072113027 1
+4 0.000401278 4
+3 0.295626428 1
+3 0.055830914 1
+4 0.000342416 6
+3 0.551895662 1
+3 0.079965287 1
+4 0.000383645 7
+3 0.415814232 1
+4 0.000398259 7
+3 1.095530830 1
+4 0.000332068 24
+3 0.249480319 1
+4 0.000367411 16
+3 0.069703592 1
+4 0.000309604 17
+3 0.031736612 1
+4 0.000332510 19
+3 0.135653206 1
+4 0.000344851 19
+3 0.151760722 1
+4 0.000414377 20
+3 0.135442232 1
+4 0.000320695 19
+3 0.215735795 1
+4 0.000379862 19
+3 0.143675662 1
+4 0.000333069 19
+3 0.119611034 1
+4 0.000388026 19
+3 0.095667408 1
+4 0.000322488 19
+3 0.391754973 2
+4 0.000406533 9
+3 0.095435400 1
+4 0.000352384 1
+3 0.103698735 1
+4 0.000337172 1
+4 0.000406655 71
+3 2.807345891 1
+4 0.000352232 39
+3 0.193837807 1
+4 0.000430656 17
+3 0.277359668 1
+4 0.000492549 14
+3 0.207629890 1
+3 0.096070940 1
+4 0.000406128 21
+3 0.201357121 1
+3 0.062198393 1
+4 0.000509318 4
+3 0.647524515 1
+3 0.058847717 1
+4 0.001006521 5
+3 0.268140710 1
+4 0.000355018 9
+3 0.127573024 1
+4 0.000314944 1
+3 0.087755708 1
+4 0.000373545 1
+4 0.000733677 71
+3 25.680327100 2
+4 0.000415360 40
+3 0.500168461 1
+4 0.000345733 17
+3 0.082014980 1
+4 0.000343734 17
+3 0.082732160 1
+4 0.000308449 16
+3 0.083085216 1
+4 0.000347725 17
+3 0.083293791 1
+4 0.000335752 20
+3 0.083300563 1
+4 0.000333679 20
+3 0.082744557 1
+4 0.000336053 20
+3 0.083491280 1
+4 0.000332338 21
+3 0.379409860 1
+3 0.500660526 1
+4 0.000392326 56
+3 0.082903979 1
+3 0.083893553 1
+4 0.000359338 109
+3 0.082775650 1
+3 0.083271789 1
+4 0.000351209 50
+3 0.082798483 1
+3 0.083266529 1
+4 0.000380645 79
+3 0.083243559 1
+3 0.083454583 1
+4 0.000356844 37
+3 0.083466983 1
+3 0.083394091 1
+4 0.000347213 30
+3 0.082976787 1
+3 0.083665025 1
+4 0.000350425 46
+3 0.083447438 1
+3 0.496309135 1
+4 0.000396465 76
+3 0.413792647 1
+4 0.000332448 10
+3 0.127516669 1
+4 0.000319480 1
+3 0.135976584 1
+4 0.000330092 1
+4 0.000371342 70
+3 0.615159903 1
+4 0.000381340 37
+3 0.193423073 1
+4 0.000311446 16
+3 0.197763128 1
+4 0.000365698 16
+3 0.201717774 1
+4 0.000326641 16
+3 0.165578714 1
+4 0.000378396 16
+3 0.561741684 1
+4 0.000330516 16
+3 31.791327930 1
+4 0.000410781 16
+3 0.144878230 1
+4 0.000313374 16
+3 0.166528198 1
+4 0.000355110 16
+3 0.255128716 1
+4 0.000327253 18
+3 0.623592858 1
+4 0.000398111 56
+3 0.484581327 482
+4 0.000648644 327
+4 0.000281574 297
+3 0.474031925 2
+4 0.000390452 51
+3 0.499760537 1
+4 0.000362859 57
+3 0.147600416 1
+4 0.000328532 18
+3 0.499730413 1
+4 0.000367052 20
+3 0.082609608 1
+4 0.000308948 20
+3 0.083518076 1
+4 0.000336197 17
+3 0.083368597 1
+4 0.000363839 20
+3 0.083226698 1
+4 0.000314125 14
+3 0.083626568 1
+4 0.000320239 20
+3 0.083315917 1
+4 0.000311907 20
+3 0.082827275 1
+4 0.000348916 20
+3 0.083415597 1
+4 0.000308781 20
+3 0.084330134 1
+4 0.000372289 18
+3 0.082708926 1
+4 0.000318105 19
+3 0.083442131 1
+4 0.000309499 19
+3 0.082831846 1
+4 0.000324884 19
+3 0.083502220 1
+4 0.000310053 16
+3 0.083391652 1
+4 0.000336717 18
+3 0.312867040 1
+4 0.000343477 19
+3 0.967726339 1
+3 0.183872709 1
+3 0.114021623 1
+4 0.000351377 30
+3 0.421787047 1
+4 0.000331517 42
+3 0.177689750 1
+4 0.000331284 19
+3 0.165569011 1
+4 0.000315404 20
+3 0.649914652 1
+4 0.000356583 19
+3 0.498184093 1
+4 0.000340550 18
+3 0.083446321 1
+4 0.000323868 20
+3 0.081995170 1
+4 0.000313058 20
+3 0.083345668 1
+4 0.000321728 20
+3 0.083106825 1
+4 0.000311740 20
+3 0.083763827 1
+4 0.000342292 17
+3 0.083422989 1
+4 0.000343899 17
+3 0.083296303 1
+4 0.000382450 20
+3 0.386287427 1
+4 0.000340438 17
+3 0.303729371 1
+4 0.000390762 139
+3 1.743796971 1
+4 0.000366338 43
+3 0.249498115 1
+4 0.000349871 18
+3 0.229570730 1
+4 0.000331705 17
+3 15.760889770 1
+4 0.000409383 92
+3 0.248996787 1
+4 0.000555008 47
+3 0.237465819 1
+4 0.000370083 20
+3 0.201728425 1
+4 0.000330774 18
+3 1.597483199 1
+4 0.000359256 17
+3 0.187300351 1
+4 0.000325557 18
+3 0.196007135 1
+4 0.000402731 17
+3 0.271755807 1
+4 0.000330358 17
+3 0.135391799 1
+3 0.064279766 1
+4 0.000345506 29
+3 0.471782423 2
+4 0.000401253 29
+3 0.295480571 1
+3 0.615908125 2
+4 0.000351774 17
+3 0.423865831 1
+4 0.000414001 24
+3 0.167449862 1
+4 0.000337963 90
+3 0.143709501 1
+4 0.000399620 90
+3 0.351544993 2
+4 0.000433133 97
+3 0.175501386 1
+4 0.000364540 17
+3 0.247753373 1
+3 0.071950244 1
+4 0.000350965 29
+3 0.199788929 1
+4 0.000362167 18
+3 0.327454931 1
+4 0.000340203 18
+3 0.415799497 1
+4 0.000388320 17
+3 0.039693974 1
+4 0.000325919 18
+3 0.159589337 1
+4 0.000354441 18
+3 0.167737055 1
+4 0.000329736 18
+3 0.135529240 1
+4 0.000323341 18
+3 0.111785235 1
+4 0.000370118 18
+3 0.327533134 2
+4 0.000359409 79
+3 0.153678584 1
+4 0.000342212 17
+3 0.373732092 1
+4 0.000344131 28
+4 0.000335541 99
+3 0.607480075 1
+4 0.000421897 28
+3 0.503372723 1
+4 0.000353922 73
+3 0.231700166 1
+4 0.000387482 74
+3 0.087547841 1
+4 0.000343386 75
+3 0.967852369 1
+4 0.000357882 77
+3 0.119760772 1
+4 0.000327700 77
+3 0.495430199 2
+4 0.000409435 22
+3 1.455670962 1
+3 0.136049650 1
+4 0.000407127 9
+3 0.607658736 1
+4 0.000334196 1
+3 0.111608823 1
+4 0.000422528 138
+3 0.847566104 1
+4 0.000337607 18
+3 0.239593294 1
+4 0.000453913 13
+3 0.815744351 1
+3 0.095810438 1
+4 0.000563110 29
+3 0.335618566 1
+4 0.000473371 13
+3 0.063541474 1
+4 0.000356626 16
+3 0.127674719 1
+4 0.000572425 18
+3 0.135320159 1
+4 0.000468512 18
+3 0.167562653 1
+4 0.000349390 19
+3 0.423803062 1
+4 0.000356501 23
+3 0.151579025 1
+4 0.000365639 23
+3 0.184373685 1
+4 0.000494081 23
+3 0.166790569 1
+4 0.000351437 23
+3 0.143673253 1
+4 0.000340845 23
+3 0.143583097 1
+4 0.000329542 23
+3 1.061800155 1
+4 0.110035826 33
+3 11.230177681 1
+4 0.109894286 1
+3 0.144779688 1
+4 0.000313719 18
+3 0.499170658 1
+4 0.000355520 20
+3 0.082890827 1
+4 0.000326134 20
+3 0.082812159 1
+4 0.000353703 17
+3 0.083534823 1
+4 0.000321899 20
+3 0.083823155 1
+4 0.000328459 17
+3 0.083063504 1
+4 0.000326317 20
+3 0.082630883 1
+4 0.000349978 20
+3 0.082977332 1
+4 0.000362105 20
+3 0.082647748 1
+4 0.000538387 20
+3 0.083605349 1
+4 0.000352822 18
+3 0.083226123 1
+4 0.000341422 18
+3 0.432770428 1
+3 0.500922303 1
+4 0.000402545 55
+3 0.082605686 1
+3 0.083208646 1
+4 0.000365150 65
+3 0.083378933 1
+3 0.083849630 1
+4 0.000385798 104
+3 0.398970997 1
+3 0.438007413 1
+4 0.000393754 38
+3 6.970020862 1
+3 0.125928496 1
+4 0.000363261 36
+3 20.400806501 1
+4 0.000457508 15
+3 0.499017393 1
+4 0.000333411 16
+3 0.082977503 1
+4 0.000339093 15
+3 0.083176300 1
+4 0.000338799 15
+3 0.083177846 1
+4 0.000390102 15
+3 0.083624712 1
+4 0.000325837 18
+3 0.471595615 1
+4 0.000389240 16
+3 0.181397975 1
+4 0.000406234 16
+3 0.183472337 1
+4 0.000328933 16
+3 0.201743125 1
+4 0.000345084 16
+3 1.157743437 1
+3 0.167917005 1
+3 0.114115602 1
+4 0.000348750 29
+3 0.205470455 1
+4 0.000412451 168
+3 0.239697388 1
+4 0.000335225 41
+3 0.153641480 1
+4 0.000406105 16
+3 0.173497615 1
+4 0.000328928 16
+3 0.169690697 1
+4 0.000389667 16
+3 0.437681597 1
+4 0.000331343 18
+3 0.167688715 1
+4 0.000340679 18
+3 0.186123336 1
+4 0.000324602 17
+3 0.181070872 1
+4 0.000391565 17
+3 0.185935537 1
+4 0.000351646 17
+3 0.205541082 1
+3 0.079898558 1
+4 0.000347454 4
+3 0.183833396 1
+4 0.000350846 6
+3 0.255464528 1
+4 0.000356907 17
+3 0.103755323 1
+4 0.000338515 18
+3 0.201671821 1
+4 0.000391423 18
+3 0.149456132 1
+4 0.000311397 17
+3 0.185895976 1
+4 0.000348917 17
+3 1.766458957 1
+3 0.111748001 1
+4 0.000342213 29
+3 3.009475648 13
+4 0.000366756 50
+3 3.533449180 2
+4 0.000377710 35
+3 0.193494105 1
+4 0.000372244 20
+3 0.245805875 1
+4 0.000360129 38
+3 0.215558489 1
+4 0.000355014 19
+3 0.169780542 1
+4 0.000328647 20
+3 0.157458487 1
+4 0.000396414 17
+3 0.137650747 1
+4 0.000347145 17
+3 0.126381715 1
+4 0.000320292 17
+3 0.121045758 1
+4 0.000313152 17
+3 0.141670376 1
+4 0.000323232 17
+3 0.129670629 1
+4 0.000357552 18
+3 0.134123742 1
+4 0.000321029 16
+3 0.199272519 1
+3 0.154085494 1
+4 0.000405687 114
+3 3.414143106 1
+3 0.145794378 1
+4 0.000366336 38
+3 0.773973986 1
+4 0.000346917 9
+3 0.263659920 1
+4 0.000331238 1
+3 0.063057300 1
+4 0.000312699 1
+3 0.039609940 1
+4 0.000310816 1
+3 0.199833113 1
+4 0.000354866 1
+3 0.183408742 1
+4 0.000321901 1
+3 0.151895847 1
+4 0.000312409 1
+3 0.143668554 1
+4 0.000345163 42
+3 4.816406965 1
+4 0.000356929 17
+3 0.169107106 1
+4 0.000320840 18
+3 0.133669171 1
+4 0.000307794 17
+3 0.153798546 1
+4 0.000375121 17
+3 0.221497804 1
+3 0.080011551 1
+4 0.000339785 29
+3 0.135585549 1
+4 0.000366028 18
+3 0.416084841 1
+4 0.000345946 17
+3 0.119140269 1
+4 0.000385091 18
+3 0.071633955 1
+4 0.000339052 18
+3 0.063691059 1
+4 0.000335902 18
+3 0.199683965 1
+4 0.000337395 18
+3 0.183745149 1
+4 0.000363842 18
+3 0.055538150 1
+4 0.000354163 18
+3 0.121754583 1
+4 0.000405515 42
+3 0.221720024 2
+4 0.000341910 24
+3 0.129582201 1
+4 0.000342469 17
+3 0.237651901 1
+3 0.064652588 1
+4 0.000357747 33
+3 0.134849167 1
+4 0.000360703 19
+3 0.135710909 1
+4 0.000316010 18
+3 0.095563112 1
+4 0.000387194 18
+3 0.120230822 1
+4 0.000339029 18
+3 0.055130444 1
+4 0.000409056 18
+3 1.374432178 1
+4 0.109982395 37
+3 48.370700967 1
+4 0.109937620 1
+3 0.356890712 1
+4 0.000327038 18
+3 0.407155126 1
+4 0.000352911 24
+3 0.255744725 1
+4 0.000335455 34
+3 0.135529116 1
+4 0.000330631 33
+3 0.143803776 1
+4 0.000311379 33
+3 0.487583780 1
+4 0.000342134 33
+3 0.671346413 1
+4 0.109925140 33
+3 4.546670271 1
+3 0.143813430 1
+3 0.122041644 1
+4 0.000413285 31
+3 0.237567793 1
+4 0.000397703 174
+3 0.639827081 1
+4 0.000348563 43
+3 0.201765239 1
+4 0.000413365 18
+3 0.197467535 1
+4 0.000325038 17
+3 0.185511784 1
+4 0.000363859 17
+3 0.317787633 1
+4 0.000360147 17
+3 0.185639356 1
+4 0.000394657 17
+3 0.149574807 1
+4 0.000313383 18
+3 0.287591136 1
+3 0.088011658 1
+4 0.000363159 4
+3 0.199715538 1
+3 0.064018271 1
+4 0.000358743 4
+3 0.519699010 1
+4 0.000408737 4
+3 0.255615399 1
+4 0.000360562 17
+3 0.423601363 1
+4 0.000382063 4
+3 0.719940695 1
+4 0.000436410 17
+3 0.287256454 1
+4 0.000327343 18
+3 0.209763170 1
+4 0.000341903 17
+3 0.229558968 1
+4 0.000324724 17
+3 0.201843917 1
+4 0.000387559 18
+3 0.277373847 1
+3 0.072253667 1
+4 0.000386864 29
+3 0.135401781 1
+4 0.000369952 18
+3 0.135684962 1
+4 0.000336159 18
+3 0.079554769 1
+4 0.000345051 18
+3 0.103783530 1
+4 0.000325816 18
+3 0.071570269 1
+4 0.000316469 18
+3 0.455813369 2
+4 0.000351968 40
+3 0.359747698 1
+4 0.000331253 20
+3 0.203367315 1
+4 0.000322835 19
+3 0.180023613 1
+4 0.000341577 20
+3 0.231451705 1
+4 0.000405716 17
+3 0.185669610 1
+4 0.000339183 18
+3 0.165678940 1
+4 0.000313232 18
+3 0.146003186 1
+4 0.000311441 17
+3 0.597478758 1
+4 0.000337850 19
+3 0.201801336 1
+4 0.000318510 20
+3 0.149506466 1
+4 0.000313023 17
+3 0.162112343 1
+4 0.000351940 17
+3 0.109200955 1
+4 0.000327850 17
+3 0.137872830 1
+4 0.000333502 18
+3 0.117568342 1
+4 0.000333679 16
+3 0.311639974 1
+3 0.162003130 1
+4 0.000379755 75
+3 0.261545399 1
+3 0.122065898 1
+4 0.000456392 104
+3 0.117453068 1
+4 0.000373602 15
+3 1.409741982 1
+4 0.000446896 19
+3 0.181656097 1
+4 0.000329522 16
+3 0.169639882 1
+4 0.000373205 16
+3 0.165528402 1
+4 0.000335128 16
+3 9.040562010 1
+4 0.000370820 16
+3 0.161235472 1
+4 0.000332626 18
+3 0.157502963 1
+4 0.000419027 18
+3 0.138188933 1
+4 0.000314842 17
+3 0.157156218 1
+4 0.000379167 17
+3 0.153473962 1
+4 0.000315378 18
+3 0.133800302 1
+4 0.000388554 17
+3 0.145594867 1
+4 0.000337298 17
+3 0.277627903 1
+3 0.072079917 1
+4 0.000347425 33
+3 0.103483251 1
+4 0.000356924 19
+3 0.135734917 1
+4 0.000323910 18
+3 0.199753900 1
+4 0.000334302 17
+3 0.063635876 1
+4 0.000341138 18
+3 0.183611705 1
+4 0.000364358 18
+3 0.119829742 1
+4 0.000337920 18
+3 0.263566945 1
+4 0.000333138 18
+3 0.063997843 1
+4 0.000328836 18
+3 0.055383715 1
+4 0.000317688 18
+3 0.716639951 1
+4 0.110075430 33
+3 0.805765447 1
+4 0.000508410 17
+3 0.222761693 1
+4 0.000394105 17
+3 0.185504503 1
+4 0.000321400 18
+3 1.677965485 1
+3 0.039881330 1
+4 0.000369242 4
+3 0.199610204 1
+4 0.000347055 6
+3 5.135801847 2
+4 0.000452682 12
+3 0.288286666 1
+4 0.000394276 19
+3 0.168847062 1
+4 0.000343905 37
+3 0.501746799 1
+4 0.000419846 85
+3 0.575522020 1
+4 0.000385413 104
+3 0.279741971 1
+4 0.000389606 38
+3 0.703500287 1
+4 0.000347354 35
+3 0.367655223 1
+4 0.000440241 17
+3 0.169886001 1
+4 0.000322410 19
+3 0.165459397 1
+4 0.000343386 20
+3 0.783680443 1
+3 1.728216886 2
+4 0.000360084 18
+3 0.170121193 1
+4 0.000340091 18
+3 0.236945841 1
+4 0.000355168 17
+3 0.175714857 1
+4 0.000334692 17
+3 0.567775846 1
+4 0.000380103 17
+3 0.127481824 1
+4 0.000316456 24
+3 0.111589708 1
+4 0.000357462 22
+3 0.127897662 1
+4 0.000314507 22
+3 0.191536188 1
+4 0.000362848 22
+3 0.167705788 1
+4 0.000352659 22
+3 0.095456418 1
+4 0.000356951 22
+3 0.103850853 1
+4 0.000349034 22
+3 0.744244200 1
+4 0.000355774 17
+3 0.319046499 1
+4 0.000442546 17
+3 0.143575233 1
+4 0.000360203 17
+3 0.183669560 1
+4 0.000358766 17
+3 0.183618884 1
+4 0.000353155 17
+3 0.071676335 1
+4 0.000406601 18
+3 0.135535452 1
+4 0.000424665 17
+3 0.135675891 1
+4 0.000400942 22
+3 0.407376145 2
+4 0.000442732 36
+3 0.201778282 1
+4 0.000379741 19
+3 0.165544242 1
+4 0.000363140 20
+3 0.881872514 1
+4 0.000443857 17
+3 0.709387659 1
+4 0.000355279 17
+3 0.185624354 1
+4 0.000430600 17
+3 0.165649264 1
+4 0.000342672 18
+3 0.209736385 1
+4 0.000368710 18
+3 0.925502720 1
+3 0.103977414 1
+4 0.000346841 33
+3 3.192451814 1
+4 0.000363895 19
+3 0.126932545 1
+4 0.000319243 18
+3 0.199693950 1
+4 0.000339547 17
+3 0.111660863 1
+4 0.000331957 18
+3 0.247850101 1
+4 0.000338948 18
+3 0.175556736 1
+4 0.000389250 18
+3 0.231664064 1
+4 0.000337667 18
+3 0.071549899 1
+4 0.000315591 18
+3 0.071706185 1
+4 0.000309370 18
+3 0.375803703 2
+4 0.000395729 10
+3 0.127643695 1
+4 0.000307878 1
+3 0.071834668 1
+4 0.000355001 1
+4 0.000417061 71
+3 0.375146422 1
+4 0.000339288 39
+3 0.151503993 1
+4 0.000321562 17
+3 0.169772264 1
+4 0.000325145 18
+3 1.045757585 1
+3 0.095851424 1
+4 0.000379875 21
+3 0.167626919 1
+4 0.000353220 6
+3 1.975821698 1
+4 0.000408611 17
+3 0.177503624 1
+4 0.000334285 19
+3 0.173754324 1
+4 0.000328232 20
+3 0.703659513 1
+4 0.000322992 17
+3 0.456054539 1
+4 0.000342364 4
+3 0.169341293 1
+4 0.000360693 4
+3 0.141649340 1
+4 0.000346621 7
+3 4.439967084 1
+4 0.000355890 20
+3 0.185564983 1
+4 0.000336582 21
+3 0.181527451 1
+4 0.000375780 21
+3 0.185605030 1
+4 0.000333384 20
+3 0.133758247 1
+4 0.000319822 19
+3 1.890366705 1
+4 0.000424785 20
+3 0.268973084 1
+4 0.000383056 17
+3 0.135742214 1
+4 0.000324542 17
+3 0.185611026 1
+4 0.000329502 17
+3 0.157585660 1
+4 0.000319498 18
+3 0.137843567 1
+4 0.000322983 18
+3 0.421548220 1
+4 0.000347243 18
+3 0.167696564 1
+4 0.000363056 31
+3 0.183842979 1
+4 0.000363409 28
+3 0.543684667 1
+4 0.000396383 17
+3 0.199383764 1
+4 0.000354674 18
+3 3.312107842 15
+4 0.000361784 43
+3 0.575321321 2
+4 0.000410440 33
+3 0.193579312 1
+4 0.000343675 20
+3 0.165802683 1
+4 0.000390893 20
+3 0.155701490 1
+4 0.000336779 21
+3 0.155391198 1
+4 0.000442939 19
+3 0.192317929 1
+3 0.167344553 1
+3 0.153916527 1
+4 0.000442250 57
+3 1.965674558 1
+4 0.000451457 40
+3 0.499764594 1
+4 0.000396980 15
+3 0.082979766 1
+4 0.000325901 15
+3 0.083061258 1
+4 0.000394347 15
+3 0.082997320 1
+4 0.000349944 15
+3 0.082916734 1
+4 0.000353710 15
+3 0.082907630 1
+4 0.000321255 15
+3 0.084252453 1
+4 0.000385319 77
+3 0.082080906 1
+4 0.000348032 78
+3 0.082745791 1
+4 0.000444184 72
+3 0.082981982 1
+4 0.000346113 36
+3 0.083731417 1
+4 0.000385605 46
+3 0.082942554 1
+4 0.000378678 100
+3 0.083760268 1
+4 0.000439603 88
+3 0.082953919 1
+4 0.000360369 44
+3 0.174291698 1
+4 0.000337277 15
+3 0.500579794 1
+4 0.000402079 15
+3 0.083593537 1
+4 0.000343839 15
+3 0.083042831 1
+4 0.000330159 17
+3 0.083311131 1
+4 0.000383417 17
+3 0.083070405 1
+4 0.000322192 15
+3 0.082817202 1
+4 0.000324962 16
+3 0.082955668 1
+4 0.000352557 15
+3 0.551931053 1
+4 0.000422846 16
+3 2.029544042 1
+4 0.000380646 53
+3 0.263684538 1
+4 0.000403640 36
+3 1.071617388 2
+4 0.000404052 120
+3 0.879674421 1
+4 0.000392763 41
+3 0.500303514 1
+4 0.000344169 16
+3 0.084517571 1
+4 0.000383004 16
+3 0.081634254 1
+4 0.000357732 16
+3 1.142049302 1
+4 0.000390219 16
+3 0.221699701 1
+4 0.000424641 16
+3 0.521657225 1
+4 0.000350753 16
+3 0.581563664 1
+4 0.000367152 17
+3 0.257531636 1
+4 0.000395919 16
+3 0.229855554 1
+4 0.000345921 16
+3 0.499956178 1
+4 0.000387651 16
+3 0.083525574 1
+4 0.000328273 16
+3 0.083559651 1
+4 0.000448435 92
+3 0.082634412 1
+4 0.000371538 44
+3 0.084196617 1
+4 0.000374507 34
+3 0.082463247 1
+4 0.000368721 54
+3 0.225010916 1
+4 0.000343039 16
+3 0.217584858 1
+4 0.000343449 18
+3 0.165678539 1
+4 0.000323934 16
+3 0.521585543 1
+4 0.000374796 16
+3 1.421720860 1
+4 0.000342931 16
+3 0.623662268 1
+4 0.000356870 16
+3 0.415818209 1
+4 0.000338788 16
+3 0.185610370 1
+4 0.000327341 16
+3 56.863558864 2
+4 0.000372835 17
+3 0.500188793 1
+4 0.000338762 16
+3 0.082791915 1
+4 0.000373587 16
+3 0.082892994 1
+4 0.000310608 16
+3 0.083644957 1
+4 0.000323414 16
+3 0.082564517 1
+4 0.000316353 16
+3 0.082823382 1
+4 0.000327113 17
+3 0.420762239 1
+4 0.000341057 16
+3 0.725683280 1
+4 0.000347385 16
+3 0.169601783 1
+4 0.000349340 17
+3 0.149560568 1
+4 0.000310762 16
+3 0.296088444 1
+4 0.000367454 52
+3 0.111316743 1
+4 0.000342702 16
+3 0.159628313 1
+4 0.000317998 16
+3 0.487871378 1
+4 0.000351865 17
+3 0.015419206 1
+4 0.000327941 17
+3 0.183829312 1
+4 0.000369127 17
+3 1.016087062 1
+4 0.000342832 14
+3 0.359359352 1
+4 0.000348427 20
+3 0.015437651 1
+4 0.000321955 18
+3 0.159885333 1
+4 0.000340734 16
+3 0.671697063 1
+4 0.000354526 16
+3 0.271587848 1
+4 0.000326924 20
+3 0.247596505 1
+4 0.000360905 14
+3 0.167722031 1
+4 0.000326457 1
+3 0.224174607 1
+4 0.000419383 16
+3 0.215153787 1
+4 0.000333891 16
+3 0.391504699 1
+4 0.000333100 19
+3 0.103595519 1
+4 0.000394378 17
+3 0.279805680 1
+4 0.000404785 18
+3 0.159573060 1
+4 0.000390699 18
+3 0.095574834 1
+4 0.000331628 18
+3 0.111597223 1
+4 0.000318922 17
+3 0.135793057 1
+4 0.000363708 18
+3 0.087540509 1
+4 0.000336322 17
+3 0.159752029 1
+4 0.000390604 18
+3 0.087611800 1
+4 0.000383487 18
+3 0.056742351 1
+4 0.000465323 19
+3 0.104304822 1
+4 0.000356671 18
+3 0.085617326 1
+4 0.000358310 18
+3 0.071768679 1
+4 0.000304527 18
+3 0.087588588 1
+4 0.000401929 18
+3 0.095604151 1
+4 0.000315903 17
+3 0.103694046 1
+4 0.000346116 18
+3 0.087606667 1
+4 0.000375860 18
+3 0.079815608 1
+4 0.000340996 18
+3 0.232588017 1
+4 0.000325128 18
+3 0.254726895 1
+4 0.000353367 19
+3 0.111576060 1
+4 0.000339386 18
+3 0.095602835 1
+4 0.000339095 18
+3 0.103790138 1
+4 0.000339718 18
+3 0.087671506 1
+4 0.000415849 18
+3 0.985995502 1
+4 0.110005593 33
+3 2.607663495 1
+4 0.000374918 19
+3 0.225767927 1
+4 0.000345812 21
+3 0.277624993 1
+4 0.000404794 17
+3 0.407409999 1
+4 0.000343714 17
+3 0.201843922 1
+4 0.000373062 20
+3 0.173597223 1
+4 0.000400054 20
+3 0.185479258 1
+4 0.000322413 17
+3 0.717710421 1
+4 0.000344428 17
+3 0.209787831 1
+4 0.000395843 17
+3 0.525563477 1
+4 0.000337454 31
+3 0.479842633 1
+4 0.000379006 54
+3 0.143380297 1
+4 0.000333983 53
+3 0.047700484 1
+4 0.000405173 53
+3 0.143889187 1
+4 0.000341593 53
+3 0.055310108 1
+4 0.000335033 53
+3 0.223859077 1
+4 0.000345699 49
+3 0.367648069 2
+4 0.000413740 34
+3 0.201608958 1
+4 0.000355101 19
+3 1.117664776 1
+4 0.000363813 21
+3 0.201520385 1
+4 0.000366371 17
+3 0.525715747 1
+3 0.216059662 1
+3 0.139194879 1
+4 0.000420538 177
+3 0.980364282 1
+4 0.000359846 10
+3 0.143577346 1
+4 0.000324217 1
+3 0.103734730 1
+4 0.000388367 1
+4 0.000325011 70
+3 34.000539382 2
+4 0.000409555 38
+3 0.170109040 1
+4 0.000332830 17
+3 0.133255641 1
+4 0.000337807 16
+3 0.161597428 1
+4 0.000350663 16
+3 0.117553372 1
+4 0.000335532 16
+3 0.145851410 1
+4 0.000366825 16
+3 0.557738013 1
+4 0.000375498 54
+3 0.503544954 1
+4 0.000354412 35
+3 0.196026505 312
+4 0.000580006 327
+4 0.000364241 109
+3 0.482383695 2
+4 0.000418500 36
+3 0.225817667 1
+4 0.000331601 14
+3 0.149639782 1
+4 0.000322562 20
+3 0.399640121 1
+4 0.000352179 14
+3 0.185857789 1
+4 0.000364838 21
+3 0.133867146 1
+4 0.000362586 10
+3 0.255247637 1
+3 0.138165075 1
+4 0.000359884 38
+3 0.325583677 1
+4 0.000355319 14
+3 0.500205808 1
+4 0.000355091 15
+3 0.083618019 1
+4 0.000398399 14
+3 0.087175131 1
+4 0.000318895 14
+3 0.185452694 1
+4 0.000374563 15
+3 0.157599866 1
+4 0.000323648 14
+3 0.153792848 1
+4 0.000368093 14
+3 0.125478695 1
+4 0.000318600 14
+3 0.153909002 1
+4 0.000408088 14
+3 0.117457249 1
+4 0.000342417 18
+3 0.500068003 1
+4 0.000349528 16
+3 0.082970902 1
+4 0.000324961 16
+3 0.083438608 1
+4 0.000341588 16
+3 0.083172836 1
+4 0.000363292 16
+3 0.083089491 1
+4 0.000389105 17
+3 0.863300330 1
+4 0.000378973 15
+3 0.285475036 1
+4 0.000375948 15
+3 0.256278631 1
+4 0.000584535 894
+3 0.446763867 1
+4 0.000404832 16
+3 0.500276476 1
+4 0.000363390 16
+3 0.083456225 1
+4 0.000336862 17
+3 0.082927433 1
+4 0.000328319 16
+3 0.083688812 1
+4 0.000339892 16
+3 0.082802915 1
+4 0.000358656 18
+3 0.082716245 1
+4 0.000348332 16
+3 0.082738342 1
+4 0.000357387 16
+3 0.083145079 1
+4 0.000328128 16
+3 0.082874154 1
+4 0.000322745 16
+3 0.083506173 1
+4 0.000314595 16
+3 0.082634175 1
+4 0.000309010 16
+3 0.113315995 1
+4 0.000351674 18
+3 2.711790189 1
+3 0.121811708 1
+4 0.000342354 30
+3 1.350780677 1
+4 0.000484288 43
+3 0.499582593 1
+4 0.000364018 17
+3 0.082898191 1
+4 0.000411469 19
+3 0.082727601 1
+4 0.000316052 20
+3 0.083071661 1
+4 0.000344978 17
+3 0.083232812 1
+4 0.000314568 19
+3 0.082802022 1
+4 0.000650484 16
+3 0.082775725 1
+4 0.000390980 20
+3 0.082924623 1
+4 0.000372701 17
+3 0.082767449 1
+4 0.000413153 18
+3 0.082665069 1
+4 0.000335966 19
+3 0.083807830 1
+4 0.000323808 20
+3 0.082809994 1
+4 0.000442159 97
+3 0.083449431 1
+4 0.000360868 47
+3 0.082590256 1
+4 0.000410985 119
+3 0.083417111 1
+4 0.000363701 110
+3 0.082967041 1
+4 0.000441623 47
+3 0.083131456 1
+4 0.000353412 72
+3 0.083159443 1
+4 0.000398348 115
+3 0.082743335 1
+4 0.000361302 87
+3 0.173665158 1
+4 0.000346653 18
+3 0.500511599 1
+4 0.000381397 17
+3 0.082614069 1
+4 0.000344279 19
+3 0.083045344 1
+4 0.000389864 20
+3 0.083123871 1
+4 0.000325308 17
+3 0.083441137 1
+4 0.000311326 19
+3 0.083141430 1
+4 0.000396549 20
+3 0.082617036 1
+4 0.000319848 17
+3 0.083321903 1
+4 0.000365649 19
+3 0.082906019 1
+4 0.000325418 20
+3 0.083867395 1
+4 0.000387734 18
+3 0.082253100 1
+4 0.000327111 17
+3 5.209306135 1
+4 0.000356936 17
+3 0.499498038 1
+4 0.000338429 18
+3 0.083248941 1
+4 0.000349050 19
+3 0.082998680 1
+4 0.000338105 20
+3 0.083409580 1
+4 0.000370794 17
+3 0.248980850 1
+4 0.000336665 17
+3 0.500064336 1
+4 0.000378903 19
+3 0.083450003 1
+4 0.000327997 20
+3 0.083058283 1
+4 0.000348129 18
+3 0.342141965 1
+4 0.000344336 17
+3 2.309742734 1
+4 0.000361916 32
+3 0.023594273 1
+4 0.000341553 17
+3 0.455682228 1
+4 0.000391532 19
+3 0.239511887 1
+4 0.000330122 18
+3 0.095768258 1
+4 0.000318396 18
+3 0.191721877 1
+4 0.000330911 18
+3 0.071563823 1
+4 0.000317252 18
+3 0.055776677 1
+4 0.000334562 18
+3 0.239666474 1
+4 0.000316451 36
+3 0.359606042 2
+3 0.130090139 1
+4 0.000333990 30
+3 0.277709067 1
+4 0.000407820 43
+3 0.499829756 1
+4 0.000372602 21
+3 0.083237824 1
+4 0.000358203 19
+3 0.082780471 1
+4 0.000314001 20
+3 0.083331423 1
+4 0.000364130 20
+3 0.082893794 1
+4 0.000313460 19
+3 0.241005525 1
+4 0.000560889 16
+3 0.172332582 1
+4 0.000362109 17
+3 0.161543688 1
+4 0.000383005 19
+3 0.141590926 1
+4 0.000316806 20
+3 0.831752554 1
+4 0.000452418 173
+3 0.431577690 1
+4 0.000357268 112
+3 0.255558635 2
+4 0.000368567 34
+3 0.153660452 1
+4 0.000311132 17
+3 0.181775527 1
+4 0.000403350 114
+3 0.161501956 1
+4 0.000406326 85
+3 0.157630278 1
+4 0.000440968 44
+3 0.175647759 1
+4 0.000337343 16
+3 0.169626426 1
+4 0.000363192 16
+3 0.157530000 1
+4 0.000394097 16
+3 0.145792064 1
+4 0.000346868 17
+3 0.341531021 1
+4 0.000334808 14
+3 0.295732817 1
+4 0.000407270 14
+3 2.871705613 1
+3 0.095882751 1
+4 0.000343000 29
+3 0.231720463 1
+4 0.000344213 18
+3 0.119827603 1
+4 0.000329884 16
+3 0.111545685 1
+4 0.000376956 13
+3 0.087503250 1
+4 0.000330464 11
+3 0.343792660 2
+4 0.000351276 41
+3 0.500314061 1
+4 0.000349806 16
+3 0.083047818 1
+4 0.000333175 12
+3 0.082653704 1
+4 0.000318647 17
+3 0.083646378 1
+4 0.000379608 93
+3 0.082873806 1
+4 0.000389031 88
+3 0.083588092 1
+4 0.000348052 47
+3 0.082953785 1
+4 0.000418760 34
+3 0.083057976 1
+4 0.000363325 83
+3 0.082940781 1
+4 0.000363256 87
+3 0.083293536 1
+4 0.000377127 87
+3 0.082681683 1
+4 0.000362138 87
+3 0.272565953 1
+4 0.000435778 17
+3 0.499770637 1
+4 0.000340514 17
+3 0.083160135 1
+4 0.000358875 18
+3 0.082910009 1
+4 0.000334212 14
+3 0.083181014 1
+4 0.000344586 18
+3 0.083669914 1
+4 0.000373685 20
+3 0.082643920 1
+4 0.000399210 17
+3 0.083361848 1
+4 0.000346453 19
+3 0.082790860 1
+4 0.000341810 20
+3 0.083299434 1
+4 0.000312008 17
+3 0.083016580 1
+4 0.000347551 19
+3 0.082919542 1
+4 0.000314294 20
+3 0.313175103 1
+3 0.146080553 1
+4 0.000344070 30
+3 0.229642077 1
+4 0.000339589 43
+3 0.137635985 1
+4 0.000326642 19
+3 0.133717887 1
+4 0.000321032 17
+3 0.145653934 1
+4 0.000369265 19
+3 0.133492222 1
+4 0.000312544 20
+3 0.137737194 1
+4 0.000321177 17
+3 0.117801793 1
+4 0.000333762 19
+3 0.343597995 1
+4 0.000380476 85
+3 0.287646986 1
+4 0.000361537 52
+3 0.231510696 2
+4 0.000336455 34
+3 0.175869250 1
+4 0.000383886 15
+3 0.119538844 1
+4 0.000334277 13
+3 0.351730609 1
+3 0.095873721 1
+4 0.000372055 28
+3 0.175831831 1
+4 0.000360643 18
+3 0.151492854 1
+4 0.000393452 16
+3 0.087491223 1
+4 0.000345820 13
+3 0.121899184 1
+4 0.000363901 11
+3 0.197590595 1
+4 0.000350851 13
+3 0.008260737 1
+4 0.000353771 16
+3 0.127012728 1
+4 0.000339277 17
+3 0.327792032 1
+4 0.000381745 14
+3 0.123116629 1
+4 0.000374609 11
+3 0.236049131 1
+4 0.000386290 13
+3 0.047514475 1
+4 0.000406455 13
+3 0.263703469 2
+4 0.000370569 33
+3 0.500296560 1
+4 0.000360875 20
+3 0.082780693 1
+4 0.000416335 12
+3 0.082633911 1
+4 0.000381199 84
+3 0.083575166 1
+4 0.000418162 86
+3 0.082666881 1
+4 0.000376174 81
+3 0.083380645 1
+4 0.000371076 94
+3 0.083205627 1
+4 0.000371207 35
+3 0.082737781 1
+4 0.000481356 56
+3 0.083041576 1
+4 0.000423818 72
+3 0.071806079 1
+4 0.000339931 19
+3 0.500183823 1
+4 0.000385364 17
+3 0.082827724 1
+4 0.000353565 17
+3 0.083656119 1
+4 0.000341832 20
+3 0.082794864 1
+4 0.000338655 14
+3 0.083175690 1
+4 0.000316477 20
+3 0.082761809 1
+4 0.000403365 20
+3 0.082924047 1
+4 0.000317314 20
+3 0.082885107 1
+4 0.000347656 19
+3 0.082790687 1
+4 0.000331263 20
+3 0.083246887 1
+4 0.000326722 18
+3 0.083814619 1
+4 0.000331605 18
+3 0.082931200 1
+4 0.000331613 20
+3 0.083060683 1
+4 0.000378291 16
+3 0.083759840 1
+4 0.000322280 18
+3 0.083622004 1
+4 0.000361180 19
+3 0.308971204 1
+4 0.000319377 16
+3 0.868939444 1
+3 0.103877213 1
+3 0.105874567 1
+4 0.000334379 30
+3 0.261832718 1
+4 0.000348964 42
+3 0.161559851 1
+4 0.000366215 18
+3 0.149614795 1
+4 0.000344224 19
+3 0.137701948 1
+4 0.000358859 17
+3 0.125690550 1
+4 0.000337707 19
+3 0.137576502 1
+4 0.000322554 17
+3 0.214943184 1
+4 0.000355615 20
+3 0.262553259 1
+4 0.000392429 177
+3 0.879507130 1
+4 0.000382009 43
+3 0.499698962 1
+4 0.000356425 18
+3 0.082880019 1
+4 0.000346907 17
+3 0.626329712 1
+4 0.000359114 17
+3 0.197623254 1
+4 0.000329710 18
+3 0.185875211 1
+4 0.000351555 17
+3 0.989598679 1
+4 0.000360673 17
+3 11.816695526 1
+3 0.079221270 1
+4 0.000364779 29
+3 0.271784652 1
+4 0.000358693 18
+3 0.103629336 1
+4 0.000396262 18
+3 0.136661000 1
+4 0.000355047 18
+3 0.136461950 1
+4 0.000346455 18
+3 0.109841872 1
+4 0.000366960 18
+3 0.063581292 1
+4 0.000463782 18
+3 0.583768705 2
+4 0.000388785 28
+3 0.121456522 1
+4 0.000369572 17
+3 0.229573850 1
+3 0.080078948 1
+4 0.000376905 29
+3 0.168466698 1
+4 0.000367279 18
+3 0.086775728 1
+4 0.000376735 19
+3 0.143609462 1
+4 0.000386832 18
+3 0.087614344 1
+4 0.000364885 18
+3 0.191548043 1
+4 0.000456479 18
+3 0.135645856 1
+4 0.000381937 54
+3 0.047636999 1
+4 0.000359263 54
+3 0.215682793 1
+4 0.000375939 95
+3 0.600259093 2
+4 0.000518686 36
+7 0.000524969 TSTP
+7 0.934500773 CONT
+4 0.000608780 7
+4 0.000283100 902
+3 12.831529799 2
+4 0.000406864 19
+3 0.193942526 1
+4 0.000331562 19
+3 0.141002438 1
+4 0.000349896 16
+3 0.154083839 1
+4 0.000318132 20
+3 0.269538392 1
+3 0.137867205 1
+4 0.000367111 97
+3 2.573897292 1
+3 0.121815978 1
+4 0.000423477 30
+3 0.125502227 1
+4 0.000342705 14
+3 0.177671569 1
+4 0.000392414 18
+3 0.165702251 1
+4 0.000355251 16
+3 0.161611438 1
+4 0.000358127 17
+3 0.157739165 1
+4 0.000399045 16
+3 0.201530843 1
+4 0.000385973 18
+3 0.181540334 1
+4 0.000344512 18
+3 0.177678136 1
+4 0.000372884 17
+3 0.133790538 1
+4 0.000328319 17
+3 0.177633734 1
+4 0.000381932 18
+3 0.134352460 1
+4 0.000326386 17
+3 0.144902210 1
+4 0.000422863 17
+3 0.149559996 1
+4 0.000338509 18
+3 0.153694128 1
+4 0.000338244 17
+3 4.206426919 1
+3 0.103717321 1
+4 0.000360936 33
+3 0.619710519 16
+4 0.000530304 67
+3 0.822678487 1
+4 0.110011343 33
+3 2.430491651 1
+4 0.000383286 17
+3 0.489593323 1
+4 0.000336921 17
+3 0.261771486 1
+3 0.055956088 1
+4 0.000425498 30
+3 1.317893619 6
+4 0.000381459 24
+3 0.513259308 2
+4 0.000379054 53
+3 0.251556729 6
+4 0.000429874 6
+3 0.123850490 1
+4 0.000376758 43
+3 0.455590257 1
+4 0.000373481 17
+3 0.009327020 1
+4 0.000336126 18
+3 0.895963662 1
+4 0.000447140 18
+3 0.589748576 1
+3 0.071809754 1
+4 0.000350926 4
+3 0.199565306 1
+4 0.000413549 4
+3 0.319747540 1
+4 0.000350618 17
+3 0.201699161 1
+4 0.000347274 18
+3 1.549587898 1
+4 0.000352369 18
+3 0.177712722 1
+4 0.000339430 19
+3 0.149611635 1
+4 0.000330970 16
+3 0.145801068 1
+4 0.000337969 20
+3 0.317648862 1
+4 0.000421408 15
+4 0.018480285 86
+3 0.485114517 1
+4 0.000499266 39
+3 0.201386408 1
+4 0.000462504 18
+3 0.189506678 1
+4 0.000355374 16
+3 0.170158573 1
+4 0.000436753 17
+3 0.965253218 1
+4 0.000369171 17
+3 0.185558447 1
+4 0.000345242 16
+3 0.149548076 1
+4 0.000345254 16
+3 0.155337511 1
+4 0.000346110 14
+3 0.332079954 1
+3 0.153896742 1
+4 0.000394003 65
+3 0.189619752 1
+4 0.000359015 14
+3 0.201770281 1
+4 0.000322599 18
+3 0.165592397 1
+4 0.000371551 16
+3 0.169598000 1
+4 0.000372484 17
+3 0.141619226 1
+4 0.000426226 16
+3 0.499911586 1
+4 0.000358731 18
+3 0.083382753 1
+4 0.000369646 18
+3 0.082957105 1
+4 0.000327406 17
+3 0.082715862 1
+4 0.000349219 17
+3 0.082762668 1
+4 0.000334275 18
+3 0.083555638 1
+4 0.000430642 17
+3 0.083462271 1
+4 0.000330495 18
+3 0.083430157 1
+4 0.000377314 18
+3 0.083701151 1
+4 0.000322508 17
+3 0.494763645 1
+4 0.000433546 18
+3 0.215492413 1
+4 0.000384989 31
+3 0.815854569 1
+4 0.000391280 28
+3 0.583465415 1
+4 0.000394001 17
+3 0.591890813 1
+4 0.000386881 18
+3 67.177561192 2
+4 0.105917815 49
+3 0.038088666 1
+4 0.000352776 17
+3 0.199862087 1
+4 0.000339868 16
+3 0.151309765 1
+4 0.000355404 17
+3 0.320348551 1
+4 0.000358010 16
+3 0.185209753 1
+4 0.000413594 16
+3 0.125500032 1
+4 0.000329879 15
+3 0.464186187 1
+4 0.000389574 19
+3 0.143198480 1
+4 0.000386303 16
+3 0.335490147 1
+4 0.000343078 19
+3 0.127700355 1
+4 0.000331710 17
+3 0.119411202 1
+4 0.000343321 18
+3 0.167759692 1
+4 0.000375966 18
+3 0.119802854 1
+4 0.000354809 18
+3 0.119509308 1
+4 0.000324820 17
+3 0.143667106 1
+4 0.000382790 18
+3 0.103673680 1
+4 0.000335793 17
+3 0.135643969 1
+4 0.000340830 18
+3 0.119781457 1
+4 0.000414540 18
+3 0.151559279 1
+4 0.000376428 19
+3 0.103502352 1
+4 0.000343095 18
+3 0.327918937 1
+4 0.000369007 18
+3 0.191386211 1
+4 0.000323451 18
+3 0.055833584 1
+4 0.000339316 18
+3 0.183497133 1
+4 0.000341701 18
+3 2.759884215 1
+4 0.000353817 17
+3 1.343698374 1
+4 0.000398678 18
+3 0.263597194 1
+4 0.000351283 18
+3 0.136171086 1
+4 0.000323570 18
+3 0.383311119 1
+4 0.000368396 17
+3 0.129580242 1
+4 0.000326319 17
+3 0.125535686 1
+4 0.000356268 18
+3 0.119521654 1
+4 0.000334366 17
+3 0.071742130 1
+4 0.000373644 19
+3 0.103629767 1
+4 0.000352929 17
+3 0.143690325 1
+4 0.000332635 18
+3 0.111666624 1
+4 0.000331586 18
+3 0.087678783 1
+4 0.000335957 17
+3 0.087739242 1
+4 0.000345426 18
+3 0.087665513 1
+4 0.000329670 18
+3 0.135534046 1
+4 0.000408805 18
+3 0.063614214 1
+4 0.000326288 17
+3 0.503854866 1
+4 0.000386003 18
+3 0.079473988 1
+4 0.000341047 19
+3 0.007840380 1
+4 0.000339496 18
+3 0.183870771 1
+4 0.000329080 18
+3 0.063320318 1
+4 0.000322379 18
+3 0.135725119 1
+4 0.000358219 18
+3 0.111524351 1
+4 0.000343725 18
+3 0.359700050 2
+4 0.000378278 37
+3 0.343740597 1
+4 0.000348623 18
+3 0.185974011 1
+4 0.000324519 17
+3 0.221497352 1
+4 0.000348255 18
+3 61.266181291 1
+4 0.000354372 31
+3 0.551303471 1
+4 0.000368484 29
+3 0.599410219 1
+4 0.000400874 29
+3 0.127552920 1
+4 0.000362578 29
+3 0.071716928 1
+4 0.000344303 29
+3 0.087544652 1
+4 0.000340316 29
+3 0.722100185 1
+4 0.110021264 31
+3 20.680890782 1
+4 0.000373634 20
+3 0.185089699 1
+4 0.000362602 19
+3 0.165544295 1
+4 0.000352237 16
+3 0.257714646 1
+4 0.000382170 17
+3 4.566358379 1
+3 0.169459880 1
+4 0.000375644 75
+3 0.190699375 1
+3 0.152920201 1
+4 0.000380041 106
+3 0.205688285 1
+3 0.154039503 1
+4 0.000492548 38
+3 0.189318760 1
+3 0.124691703 1
+4 0.000364730 47
+3 1.411224968 1
+4 0.000369994 9
+3 0.167522151 1
+4 0.000349130 1
+3 0.143891438 1
+4 0.000383205 1
+4 0.000545951 10
+4 0.000360470 60
+3 1.470625810 1
+4 0.000386167 35
+3 0.153570765 1
+4 0.000350691 18
+3 0.149620068 1
+4 0.000365596 16
+3 0.137623239 1
+4 0.000387301 16
+3 0.149520210 1
+4 0.000415206 17
+3 0.151625465 1
+4 0.000371854 28
+3 0.080573318 1
+4 0.000357410 17
+3 0.110579480 1
+4 0.000325456 18
+3 0.239863880 1
+4 0.000385086 18
+3 0.183564586 1
+4 0.000366174 18
+3 0.087765549 1
+4 0.000427781 19
+3 0.239509128 1
+4 0.000346854 18
+3 0.007633165 1
+4 0.000373394 18
+3 0.087639180 1
+4 0.000337988 18
+3 0.319775512 1
+4 0.000505715 17
+3 0.161491658 1
+4 0.000352871 17
+3 0.085589099 1
+4 0.000370120 17
+3 0.184838360 1
+4 0.000409714 18
+3 0.094224328 1
+4 0.000370512 18
+3 0.047660818 1
+4 0.000328388 18
+3 0.111610547 1
+4 0.000404627 18
+3 0.055751577 1
+4 0.000325479 18
+3 0.127599689 1
+4 0.000375926 18
+3 0.071769878 1
+4 0.000327629 18
+3 0.087684664 1
+4 0.000416728 17
+3 0.111457791 1
+4 0.000327898 18
+3 0.087812327 1
+4 0.000351461 19
+3 0.055612649 1
+4 0.000328030 18
+3 0.072130867 1
+4 0.000369877 18
+3 0.167161278 1
+4 0.000329555 18
+3 0.087618415 1
+4 0.000413663 18
+3 0.063484181 1
+4 0.000352491 17
+3 0.567916037 1
+4 0.000387987 18
+3 0.103339604 1
+4 0.000330244 18
+3 0.103795367 1
+4 0.000370998 18
+3 0.095640338 1
+4 0.000342275 17
+3 1.007620119 1
+4 0.000417762 19
+3 0.063692281 1
+4 0.000343725 18
+3 0.193859611 1
+4 0.000369170 18
+3 0.085516875 1
+4 0.000350647 18
+3 0.111527754 1
+4 0.000404490 18
+3 0.639826877 1
+4 0.000376295 18
+3 0.135447001 1
+4 0.000358152 18
+3 0.239822952 1
+4 0.000348368 17
+3 0.138692136 1
+4 0.000337824 17
+3 0.220537966 1
+4 0.000384335 18
+3 0.063512962 1
+4 0.000341670 18
+3 0.135704602 1
+4 0.000330981 18
+3 0.327799432 1
+4 0.000380412 36
+4 0.705157028 18
+3 0.019950283 1
+4 0.110054367 29
+3 2.316470417 1
+4 0.000419398 10
+3 0.095529461 1
+4 0.000330058 1
+3 0.111813412 1
+4 0.000463456 1
+4 0.000412210 71
+3 2.943675520 1
+4 0.000400463 39
+3 2.063298340 1
+4 0.000355686 19
+3 0.185555546 1
+4 0.000362504 18
+3 0.165455731 1
+4 0.000345161 20
+3 0.153747794 1
+4 0.000330354 19
+3 0.301780484 1
+4 0.000382464 20
+3 0.177433698 1
+4 0.000348824 20
+3 0.133755788 1
+4 0.000339111 18
+3 0.233597558 1
+4 0.000335806 19
+3 0.773747586 1
+3 0.272072108 1
+3 0.113925233 1
+4 0.000355719 31
+3 0.237636070 1
+4 0.000413470 284
+3 0.223648251 1
+4 0.000386499 41
+3 0.161577638 1
+4 0.000347935 17
+3 0.141694835 1
+4 0.000323027 16
+3 0.161769830 1
+4 0.000321395 16
+3 0.133603573 1
+4 0.000358816 16
+3 0.129628258 1
+4 0.000324973 18
+3 15.158245983 2
+4 0.000381351 17
+3 0.144128400 1
+4 0.000402588 17
+3 0.311178227 1
+3 0.071831442 1
+4 0.000370743 29
+3 0.215685324 1
+4 0.000337607 18
+3 0.127651179 1
+4 0.000407826 17
+3 0.087480453 1
+4 0.000371903 13
+3 0.079895733 1
+4 0.000341664 11
+3 0.175686154 1
+4 0.000346960 11
+3 0.183434115 1
+4 0.000425501 13
+3 0.183686290 1
+4 0.000371790 16
+3 0.119704637 1
+4 0.000422827 19
+3 0.658458051 1
+4 0.110009419 33
+3 4.095778374 1
+4 0.000412939 17
+3 0.499871945 1
+4 0.000365514 17
+3 0.083258950 1
+4 0.000457382 17
+3 0.083555168 1
+4 0.000333139 19
+3 0.082757480 1
+4 0.000427081 34
+3 0.082955737 1
+4 0.000369778 57
+3 0.083140434 1
+4 0.000400397 72
+3 0.168959595 1
+4 0.000427643 19
+3 0.500214531 1
+4 0.000366360 18
+3 0.082637030 1
+4 0.000321226 18
+3 0.083382411 1
+4 0.000321180 18
+3 0.083317085 1
+4 0.000352069 17
+3 0.083060249 1
+4 0.000326548 17
+3 0.083291726 1
+4 0.000320362 17
+3 0.769933000 1
+4 0.000393975 17
+3 0.919667510 1
+4 0.000352380 17
+3 0.311512747 1
+4 0.000342246 17
+3 0.201904768 1
+4 0.000337561 17
+3 0.149354708 1
+4 0.000330234 17
+3 0.161865319 1
+4 0.000344640 19
+3 0.197546984 1
+4 0.000398805 16
+3 0.263704802 1
+4 0.000365442 18
+3 0.209456425 1
+4 0.000346204 18
+3 0.149810929 1
+4 0.000326993 17
+3 0.145647497 1
+4 0.000336915 17
+3 0.117654947 1
+4 0.000326396 17
+3 0.711858350 1
+3 0.215794237 1
+3 0.098692624 1
+4 0.000352279 30
+3 0.245072663 1
+4 0.000413162 152
+3 0.343589827 1
+4 0.000353535 43
+3 0.217628262 1
+4 0.000388389 17
+3 0.285641658 1
+4 0.000349375 17
+3 0.169616288 1
+4 0.000329603 18
+3 0.181998092 1
+4 0.000355735 17
+3 0.185294964 1
+4 0.000335426 17
+3 0.197804731 1
+4 0.000561390 18
+3 0.167404808 1
+4 0.000356999 18
+3 0.185860111 1
+4 0.000339021 17
+3 0.781427426 1
+4 0.000345923 17
+3 0.185697121 1
+4 0.000347099 18
+3 0.413672727 1
+3 0.072009864 1
+4 0.000367795 29
+3 1.239791419 1
+4 0.000372411 18
+3 0.071340348 1
+4 0.000349935 18
+3 0.087787090 1
+4 0.000341787 18
+3 0.064184380 1
+4 0.000373641 18
+3 0.343127607 2
+4 0.000363811 40
+3 0.495728208 1
+3 0.153866919 1
+4 0.000381217 117
+3 0.317668622 1
+4 0.000343528 18
+3 0.201756661 1
+4 0.000357579 18
+3 0.181438883 1
+4 0.000431407 17
+3 0.169782035 1
+4 0.000355737 17
+3 0.158459464 1
+4 0.000368564 18
+3 0.168862312 1
+4 0.000353069 17
+3 0.309583374 1
+4 0.000341940 17
+3 6.528430103 1
+3 0.055462031 1
+4 0.000367215 29
+3 0.351596495 1
+4 0.000434845 18
+3 0.055556172 1
+4 0.000345054 18
+3 0.127601700 1
+4 0.000369145 18
+3 0.119719841 1
+4 0.000352897 18
+3 0.071669428 1
+4 0.000421346 18
+3 0.263567769 2
+4 0.000393053 28
+3 0.153564993 1
+4 0.000338198 17
+3 0.229730832 1
+3 0.063895311 1
+4 0.000359651 33
+3 0.127722731 1
+4 0.000449988 18
+3 0.103515795 1
+4 0.000359790 18
+3 0.151624155 1
+4 0.000389670 18
+3 0.151650854 1
+4 0.000371329 18
+3 0.624624544 2
+4 0.000416918 29
+3 0.168504380 1
+4 0.000421755 17
+3 10.654173843 2
+4 0.000352326 18
+3 0.424138296 1
+3 0.055311738 1
+4 0.000356667 4
+3 0.183672243 1
+3 0.047968635 1
+4 0.000396462 4
+3 0.183787577 1
+3 0.063925096 1
+4 0.000358036 4
+3 0.319605460 1
+3 0.071929449 1
+4 0.000465348 4
+3 0.223722878 1
+4 0.000363252 10
+3 0.183587733 1
+4 0.000433712 14
+3 0.647630308 1
+3 0.063895585 1
+4 0.000417815 4
+3 0.535615893 1
+3 0.064012416 1
+4 0.000348669 4
+3 0.175726381 1
+4 0.000365969 17
+3 0.169966104 1
+4 0.000357277 17
+3 0.133255650 1
+4 0.000403378 17
+3 0.137644548 1
+4 0.000350718 18
+3 0.229589398 1
+4 0.000365216 20
+3 0.463682245 1
+4 0.000350292 17
+3 0.503710571 1
+3 0.071984253 1
+4 0.000365719 28
+3 0.239651030 1
+4 0.000371735 18
+3 0.135639150 1
+4 0.000347031 18
+3 0.375716854 1
+4 0.000353884 18
+3 0.145568976 1
+4 0.000359135 18
+3 0.141844499 1
+4 0.000342832 24
+3 0.055394243 1
+4 0.000427838 23
+3 0.055635519 1
+4 0.000326181 23
+3 0.591843859 2
+4 0.000389100 35
+3 0.499738355 1
+4 0.000369830 16
+3 0.083117755 1
+4 0.000333179 20
+3 0.082622531 1
+4 0.000326263 20
+3 0.082752732 1
+4 0.000351052 20
+3 0.082639690 1
+4 0.000397694 19
+3 0.083120133 1
+4 0.000365561 16
+3 0.084210436 1
+4 0.000333697 20
+3 0.082058788 1
+4 0.000410842 21
+3 0.083103481 1
+4 0.000345452 17
+3 0.083358651 1
+4 0.000425225 86
+3 0.082712757 1
+4 0.000367934 47
+3 0.330067959 1
+4 0.000525402 20
+3 0.191546795 1
+4 0.000484461 18
+3 0.161572675 1
+4 0.000409905 13
+3 0.229427039 1
+3 0.072238531 1
+4 0.000384219 28
+3 0.199416678 1
+4 0.000369245 13
+3 0.159740429 1
+4 0.000359174 16
+3 0.103384937 1
+4 0.000342926 17
+3 0.111719927 1
+4 0.000334395 18
+3 0.191704946 1
+4 0.000351843 24
+3 0.135694345 1
+4 0.000385816 23
+3 0.183679105 1
+4 0.000341780 23
+3 0.135643465 1
+4 0.000409507 23
+3 0.263719585 2
+4 0.000430565 36
+3 0.745526976 1
+4 0.000349700 17
+3 0.221526461 1
+3 0.154139252 1
+4 0.000363741 40
+3 0.197648612 1
+4 0.000380234 18
+3 0.145592219 1
+4 0.000347438 18
+3 0.497692162 1
+4 0.000559334 17
+3 0.083258084 1
+4 0.000366159 17
+3 0.082714433 1
+4 0.000363401 18
+3 0.284743957 1
+4 0.000380457 17
+3 0.983705644 1
+4 0.000455424 17
+3 4.128251235 1
+3 0.055263603 1
+4 0.000392117 29
+3 0.311678075 1
+4 0.000364203 17
+3 0.183681414 1
+4 0.000440272 18
+3 0.055707892 1
+4 0.000336896 18
+3 0.127524254 1
+4 0.000347727 18
+3 0.119410661 1
+4 0.000362210 17
+3 0.352201070 2
+4 0.000382496 28
+3 0.161470026 1
+4 0.000366634 17
+3 0.981529955 1
+3 0.071904396 1
+4 0.000375458 33
+3 1.687914699 1
+4 0.000375000 18
+3 0.095554075 1
+4 0.000395143 18
+3 0.335928270 1
+4 0.000415245 19
+3 0.151152635 1
+4 0.000403090 18
+3 0.223691617 1
+4 0.000382719 16
+3 0.095596121 1
+4 0.000552478 13
+3 0.479860646 2
+4 0.000394744 29
+3 0.145244202 1
+4 0.000428117 11
+3 0.334356045 1
+3 0.047245638 1
+4 0.000364391 29
+3 0.231474679 1
+4 0.000366527 11
+3 0.127831282 1
+4 0.000348438 13
+3 0.119706825 1
+4 0.000413701 16
+3 0.159493916 1
+4 0.000337168 18
+3 0.063503681 1
+4 0.000413528 18
+3 0.017324370 1
+4 0.000363635 19
+3 0.037925101 1
+4 0.000359329 34
+3 0.447799378 1
+4 0.000354927 17
+3 0.155150106 1
+4 0.000358097 18
+3 0.548165767 1
+4 0.000435383 19
+3 0.709231736 1
+4 0.110013539 39
+3 2.317003920 1
+4 0.000370810 18
+3 0.137062672 1
+4 0.000451671 17
+3 0.269450345 1
+3 0.055962476 1
+4 0.000376465 28
+3 0.143660940 1
+4 0.000324800 18
+3 0.047648307 1
+4 0.000324962 18
+3 0.159709120 1
+4 0.000330247 18
+3 0.055824884 1
+4 0.000344909 18
+3 0.175503094 1
+4 0.000417635 29
+3 0.071590626 1
+4 0.000343271 29
+3 0.183678892 1
+4 0.000381034 29
+3 0.319724383 2
+4 0.000383703 24
+3 0.191668805 1
+4 0.000371153 4
+3 0.631573623 1
+4 0.000351948 9
+3 3.567896880 1
+4 0.000413212 1
+3 0.351539578 1
+4 0.000365350 1
+3 0.191536273 1
+4 0.000372288 43
+3 1.055699949 1
+4 0.000397684 4
+3 1.199544502 1
+4 0.000366758 20
+3 1.959891454 1
+4 0.000383916 4
+3 0.391505464 1
+4 0.000517804 21
+4 0.000377686 41
+3 0.623122013 1
+4 0.000404023 43
+3 0.500068594 1
+4 0.000367278 19
+3 0.082673669 1
+4 0.000414010 17
+3 0.083212499 1
+4 0.000361841 20
+3 0.083398609 1
+4 0.000378938 20
+3 0.083503493 1
+4 0.000339474 20
+3 0.083548955 1
+4 0.000350817 19
+3 0.082922183 1
+4 0.000380499 16
+3 0.082633674 1
+4 0.000419267 20
+3 0.346679965 1
+4 0.000345699 9
+3 0.127600231 1
+4 0.000348823 1
+3 0.079852974 1
+4 0.000384659 1
+4 0.000487278 71
+3 1.047053399 1
+4 0.000371454 35
+3 0.201577612 1
+4 0.000346492 18
+3 0.141620220 1
+4 0.000434290 20
+3 0.161725379 1
+4 0.000349536 17
+3 0.381540104 1
+4 0.000458714 20
+3 0.255538554 1
+4 0.000362273 20
+3 0.217589396 1
+4 0.000442248 17
+3 0.197745827 1
+4 0.000361737 19
+3 0.217592627 1
+4 0.000417554 16
+3 0.237510507 1
+4 0.000365859 18
+3 0.185442213 1
+4 0.000383843 20
+3 0.157776099 1
+4 0.000388969 17
+3 0.145656120 1
+4 0.000432544 20
+3 0.725571649 1
+3 0.224026841 1
+3 0.130120797 1
+4 0.000463027 195
+3 0.413944645 1
+4 0.000590754 739
+3 3.767186937 1
+4 0.000401657 17
+3 0.501150681 1
+4 0.000383413 17
+3 0.083052650 1
+4 0.000406041 18
+3 0.082919414 1
+4 0.000341142 17
+3 0.083048449 1
+4 0.000389613 18
+3 0.083058567 1
+4 0.000341517 20
+3 0.083738747 1
+4 0.000401697 17
+3 0.083487118 1
+4 0.000318078 19
+3 0.082386624 1
+4 0.000349825 20
+3 0.083549970 1
+4 0.000348323 17
+3 0.083216984 1
+4 0.000357428 19
+3 2.002381804 1
+4 0.000472399 182
+3 0.391433807 1
+4 0.000415113 41
+3 0.153619892 1
+4 0.000339569 16
+3 0.157579095 1
+4 0.000381298 16
+3 0.137710185 1
+4 0.000331000 15
+3 0.237609414 1
+3 0.154038387 1
+4 0.000386302 28
+3 0.085678700 1
+4 0.000342804 15
+3 0.137577797 1
+4 0.000325385 17
+3 0.125663214 1
+4 0.000339410 16
+3 0.129648391 1
+4 0.000371056 16
+3 0.133745687 1
+4 0.000344839 16
+3 0.121870473 1
+4 0.000344271 16
+3 0.141414753 1
+4 0.000349286 16
+3 0.279635191 1
+4 0.000368680 83
+3 0.919741389 1
+4 0.000372528 16
+3 0.185634184 1
+4 0.000334268 18
+3 0.149643991 1
+4 0.000381864 16
+3 0.178813890 1
+4 0.000340575 16
+3 0.132512157 1
+4 0.000326605 16
+3 0.207669487 1
+3 0.130001555 1
+4 0.000373613 30
+3 0.101685025 1
+4 0.000359406 16
+3 0.169496704 1
+4 0.000347369 16
+3 0.117830690 1
+4 0.000346260 15
+3 0.271560924 1
+4 0.000378261 70
+3 0.335674560 1
+4 0.000334295 17
+3 0.319680454 1
+4 0.000381445 17
+3 0.111605973 1
+4 0.000330906 16
+3 0.351541311 1
+3 0.055960494 1
+4 0.000350943 27
+3 0.231761623 1
+4 0.000365793 17
+3 0.071605203 1
+4 0.000375718 17
+3 0.063717020 1
+4 0.000426567 17
+3 0.167512881 1
+4 0.000373898 17
+3 0.215669475 1
+4 0.000387267 18
+3 0.119543451 1
+4 0.000350589 18
+3 0.119698085 1
+4 0.000383518 18
+3 0.063626059 1
+4 0.000331352 18
+3 0.151709723 1
+4 0.000444992 18
+3 0.415446226 2
+4 0.000358904 10
+3 0.111754384 1
+4 0.000375156 1
+3 0.087635169 1
+4 0.000352317 1
+4 0.000356910 70
+3 0.647287901 1
+4 0.000418985 38
+3 0.500906857 1
+4 0.000359649 21
+3 0.082239879 1
+4 0.000401465 19
+3 0.082678794 1
+4 0.000349987 20
+3 6.253213528 1
+4 0.000594687 818
+3 0.943207476 1
+4 0.000359186 18
+3 0.500411947 1
+4 0.000363800 17
+3 0.082935185 1
+4 0.000364544 19
+3 0.083270215 1
+4 0.000324230 16
+3 0.082879840 1
+4 0.000328773 16
+3 0.394701064 1
+4 0.000342138 16
+3 0.498004689 1
+4 0.000343189 18
+3 0.084036201 1
+4 0.000328291 19
+3 0.082809036 1
+4 0.000320226 18
+3 0.083381699 1
+4 0.000356306 19
+3 0.082845594 1
+4 0.000362854 17
+3 0.082591044 1
+4 0.000330810 20
+3 0.274046350 1
+4 0.000358247 17
+3 1.663733384 1
+4 0.000385247 17
+3 0.169387535 1
+4 0.000338773 18
+3 0.453821805 1
+4 0.000364475 17
+3 0.815670849 1
+4 0.000397658 21
+3 3.463852526 1
+4 0.000372814 10
+3 0.135519697 1
+4 0.000323566 1
+3 0.087713390 1
+4 0.000342568 1
+4 0.000308209 14
+4 0.000365143 57
+3 0.366888761 1
+4 0.000410446 39
+3 0.500676434 1
+4 0.000348263 17
+3 0.083090874 1
+4 0.000434494 19
+3 0.082830339 1
+4 0.000324887 16
+3 0.083566806 1
+4 0.000402301 20
+3 0.083173820 1
+4 0.000334397 18
+3 0.082730980 1
+4 0.000393689 17
+3 0.082825052 1
+4 0.000341337 19
+3 0.083170302 1
+4 0.000377153 14
+3 0.083072838 1
+4 0.000390173 56
+3 0.082999886 1
+4 0.000439470 75
+3 0.082762651 1
+4 0.000395232 113
+3 0.082620995 1
+4 0.000397350 61
+3 0.082871001 1
+4 0.000373226 34
+3 0.083575770 1
+4 0.000409959 63
+3 0.082917348 1
+4 0.000372697 69
+3 0.163160664 1
+4 0.000430026 22
+3 0.499891634 1
+4 0.000363031 17
+3 0.083667974 1
+4 0.000358611 18
+3 0.083655556 1
+4 0.000331308 20
+3 0.082933196 1
+4 0.000406880 17
+3 0.083358936 1
+4 0.000338614 20
+3 0.082833576 1
+4 0.000352971 17
+3 0.083692508 1
+4 0.000408021 18
+3 0.082857776 1
+4 0.000367410 20
+3 0.083019645 1
+4 0.000332219 17
+3 21.927781806 1
+4 0.000441868 10
+3 0.502837059 1
+4 0.000350164 1
+3 0.151681189 1
+4 0.000353626 1
+3 0.151622397 1
+4 0.000311634 1
+3 0.087826712 1
+4 0.000353519 1
+3 0.151558813 1
+4 0.000327227 1
+3 0.231730506 1
+4 0.000651083 903
+3 32.501930553 1
+4 0.109975552 1
+3 0.028943050 1
+4 0.000370553 17
+3 0.193248641 1
+4 0.000388154 19
+3 0.197569088 1
+4 0.000387741 19
+3 0.337809277 1
+4 0.000368492 16
+3 1.509640262 1
+4 0.000364843 16
+3 0.169678380 1
+4 0.000390517 16
+3 0.149422705 1
+4 0.000422957 17
+3 0.177633505 1
+4 0.000350401 16
+3 0.149621210 1
+4 0.000384687 16
+3 0.327694270 1
+4 0.000358998 22
+3 0.911712189 1
+4 0.000401784 38
+3 0.504510471 1
+4 0.000396015 38
+3 0.526653542 2
+4 0.000493199 32
+3 0.169493494 1
+4 0.000336623 16
+3 0.149703387 1
+4 0.000357534 17
+3 0.105766267 1
+4 0.000329302 16
+3 0.245599159 1
+4 0.000406078 16
+3 0.575618562 1
+4 0.000364879 16
+3 0.311608382 1
+4 0.000349871 16
+3 0.185596270 1
+4 0.000398002 16
+3 1.365688778 1
+4 0.000363466 16
+3 0.255699476 1
+4 0.000359577 16
+3 0.153604076 1
+4 0.000329306 16
+3 0.389581420 1
+4 0.000348745 30
+3 0.335840754 1
+4 0.000400729 43
+3 0.447431650 2
+4 0.000390504 30
+3 0.185734624 1
+4 0.000385907 16
+3 0.285715442 1
+4 0.000366225 16
+3 0.319421703 1
+4 0.000358107 16
+3 0.207748026 1
+4 0.000353624 23
+3 0.143468126 1
+4 0.000390232 40
+3 0.199737673 1
+4 0.000360893 40
+3 0.151876766 1
+4 0.000363927 40
+3 0.103505994 1
+4 0.000400039 40
+3 0.127470683 1
+4 0.000351737 40
+3 0.087789128 1
+4 0.000364161 40
+3 0.103384124 1
+4 0.000355439 40
+3 0.127838284 1
+4 0.000363215 40
+3 0.647731652 2
+4 0.000391568 10
+3 0.095454269 1
+4 0.000345634 1
+3 0.119803172 1
+4 0.000395598 1
+4 0.000411305 70
+3 2.687757586 1
+4 0.000771462 909
+3 0.831467981 1
+4 0.003215880 778
+3 11.679345950 1
+3 0.021098554 1
+4 0.000353074 16
+3 0.500492644 1
+4 0.000350399 15
+3 16.339427653 2
+4 0.000483019 18
+3 0.234059151 1
+4 0.000399213 17
+3 0.181245736 1
+4 0.000373271 16
+3 0.377574752 1
+4 0.000399487 15
+3 0.213541131 1
+4 0.000363939 15
+3 0.455592358 1
+4 0.000368419 15
+3 0.217860660 1
+4 0.000362396 15
+3 0.829822342 1
+3 0.199520605 1
+3 0.122077648 1
+4 0.000371995 29
+3 0.301692078 1
+4 0.000429013 168
+3 0.263429942 1
+4 0.000439329 42
+3 0.185772461 1
+4 0.000367660 17
+3 0.173522004 1
+4 0.000351702 16
+3 0.169723295 1
+4 0.000353912 16
+3 0.181558878 1
+4 0.000346110 17
+3 0.360811073 1
+4 0.000384036 16
+3 0.406733402 1
+3 0.071723810 1
+4 0.000435085 4
+3 0.183594255 1
+3 0.064832901 1
+4 0.000364702 4
+3 0.182897521 1
+3 0.063976876 1
+4 0.000447247 4
+3 0.183453955 1
+3 0.063996744 1
+4 0.000368818 4
+3 0.199914064 1
+3 0.055782650 1
+4 0.000429917 4
+3 0.527557291 1
+3 0.081236809 1
+4 0.000396926 4
+3 0.958840513 1
+4 0.000419130 4
+3 0.239238446 1
+4 0.000358296 16
+3 0.383668436 1
+4 0.000430813 4
+3 0.311593779 1
+4 0.000372858 16
+3 0.255700878 1
+4 0.000468984 17
+3 0.170610780 1
+4 0.000348450 16
+3 0.180469947 1
+4 0.000550694 17
+3 0.201643938 1
+4 0.000372859 16
+3 0.229538559 1
+4 0.000382536 16
+3 0.185532139 1
+4 0.000356124 16
+3 0.261601985 1
+4 0.000387245 16
+3 0.135920173 1
+4 0.000364712 4
+3 0.137582828 1
+4 0.000406378 7
+3 0.101406308 1
+4 0.000378019 23
+3 0.127611094 1
+4 0.000416266 19
+3 0.063597802 1
+4 0.000351139 19
+3 0.135777101 1
+4 0.000383814 19
+3 0.071872137 1
+4 0.000347966 19
+3 0.183497136 1
+4 0.000388051 19
+3 0.087333908 1
+4 0.000347077 20
+3 0.167728912 1
+4 0.000446104 19
+3 0.152024080 1
+4 0.000347542 19
+3 0.055241445 1
+4 0.000385482 19
+3 0.719955348 1
+4 0.109930592 32
+3 4.609864082 1
+4 0.000458471 18
+3 0.185496737 1
+4 0.000353455 19
+3 0.173481209 1
+4 0.000412202 16
+3 0.185800042 1
+4 0.000371954 17
+3 0.165563687 1
+4 0.000383396 16
+3 0.455705316 1
+4 0.000519137 16
+3 0.183502619 1
+3 0.087954866 1
+4 0.000398623 4
+3 0.127667464 1
+3 0.048005922 1
+4 0.000556711 4
+3 0.271606905 1
+4 0.000365658 10
+3 0.111439488 1
+4 0.000364614 1
+3 0.119629265 1
+4 0.000356249 1
+4 0.000358164 70
+3 23.456782660 1
+4 0.000420244 39
+3 0.185036269 1
+4 0.000378673 19
+3 0.261464712 1
+4 0.000358112 20
+3 0.185802233 1
+4 0.000354946 16
+3 0.133526698 1
+4 0.000351124 18
+3 0.145720194 1
+4 0.000346442 19
+3 0.141404511 1
+4 0.000347248 19
+3 0.903765278 1
+3 0.160022307 1
+3 0.122095060 1
+4 0.000359637 30
+3 0.229676169 1
+4 0.000458957 160
+3 0.281155229 1
+4 0.000370937 40
+3 0.176037772 1
+4 0.000338887 15
+3 0.141472526 1
+4 0.000364237 15
+3 0.087748400 1
+4 0.000345260 17
+3 0.185814611 1
+4 0.000402835 17
+3 0.157522572 1
+4 0.000354716 16
+3 0.145735709 1
+4 0.000442894 16
+3 0.157390360 1
+4 0.000374352 17
+3 0.519794542 1
+3 0.071877963 1
+4 0.000385470 28
+3 2.666067450 16
+4 0.000385961 42
+3 0.653306438 2
+4 0.000389654 32
+3 0.335636999 1
+3 0.055882266 1
+4 0.000376155 4
+3 0.191644598 1
+4 0.000421996 4
+3 0.159629868 1
+4 0.000380822 17
+3 0.247669348 1
+4 0.000354744 17
+3 0.233607882 1
+4 0.000474290 17
+3 0.237582654 1
+4 0.000391815 18
+3 0.265544774 1
+4 0.000403142 17
+3 2.045831577 1
+3 0.071988213 1
+4 0.000365710 33
+3 0.183567304 1
+4 0.000340983 18
+3 0.135520945 1
+4 0.000339207 18
+3 0.375758029 1
+4 0.000437595 18
+3 0.255608738 1
+4 0.000342984 18
+3 0.231779299 1
+4 0.000385756 18
+3 0.623567503 1
+4 0.000408780 19
+3 0.706978607 1
+3 0.092654921 1
+4 0.000392070 40
+3 0.151447284 1
+4 0.000397522 16
+3 0.177694701 1
+4 0.000349486 16
+3 0.237684625 1
+4 0.000395108 16
+3 0.169524623 1
+4 0.000332610 16
+3 0.109663657 1
+4 0.000393453 4
+3 18.720866665 1
+4 0.000378684 10
+3 0.183076196 1
+4 0.000372289 1
+3 0.143478724 1
+4 0.000321412 1
+3 0.223863235 1
+4 0.000329886 1
+3 0.095739590 1
+4 0.000344349 1
+3 0.255589294 1
+4 0.000381290 42
+3 6.352356328 1
+4 0.000370173 10
+3 0.247069394 1
+4 0.000358856 1
+3 0.111615287 1
+4 0.000352443 1
+3 0.095530677 1
+4 0.000320066 1
+3 0.119880870 1
+4 0.000346334 1
+3 0.071569135 1
+4 0.000389853 1
+3 0.135694663 1
+4 0.000369364 21
+4 0.000400694 626
+3 0.903231822 1
+4 0.000640086 932
+3 0.137505949 1
+4 0.000414885 4
+3 0.293443410 1
+4 0.000342797 10
+3 0.095633509 1
+4 0.000321921 1
+3 0.111824456 1
+4 0.000392877 1
+4 0.000692568 10
+4 0.000315916 61
+3 51.768343604 2
+4 0.000413690 38
+3 0.178048003 1
+4 0.000354008 20
+3 0.181050315 1
+4 0.000399295 16
+3 0.367773466 1
+4 0.000350064 17
+3 0.185496152 1
+4 0.000457337 19
+3 0.165580652 1
+4 0.000373275 20
+3 0.943666684 1
+3 0.143938971 1
+3 0.138092960 1
+4 0.000446899 31
+3 0.189573253 1
+4 0.000434622 166
+3 0.415594353 1
+4 0.000353175 43
+3 0.119498545 1
+4 0.000416279 17
+3 0.153622082 1
+4 0.000325486 17
+3 0.149797383 1
+4 0.000364900 17
+3 0.145463973 1
+4 0.000320115 18
+3 0.245861873 1
+3 0.055899416 1
+4 0.000346184 33
+3 0.145440842 1
+4 0.000330750 18
+3 0.093927827 1
+4 0.000402535 18
+3 0.151636302 1
+4 0.000334025 18
+3 0.137649589 1
+4 0.000327258 18
+3 0.165641957 1
+4 0.000344676 18
+3 0.103530501 1
+4 0.000394530 18
+3 0.119730331 1
+4 0.000344489 18
+3 0.191797816 1
+4 0.000345030 18
+3 0.519553219 1
+4 0.000375999 17
+3 0.271649244 2
+4 0.000369176 40
+3 0.159664026 1
+4 0.000343802 18
+3 0.079615085 1
+4 0.000343537 17
+3 0.145638061 1
+4 0.000343617 18
+3 0.213673268 1
+3 0.072064928 1
+4 0.000393468 29
+3 0.159540889 1
+4 0.000361177 18
+3 0.184772577 1
+4 0.000362006 18
+3 0.182583209 1
+4 0.000390393 18
+3 0.063563677 1
+4 0.000353075 18
+3 0.087721187 1
+4 0.000352908 18
+3 0.063547733 1
+4 0.000347315 19
+3 0.359639301 2
+4 0.000394679 10
+3 0.127782684 1
+4 0.000360020 1
+3 0.071659375 1
+4 0.000364721 1
+4 0.000372040 71
+3 6.634229053 1
+4 0.000421555 39
+3 2.772844912 1
+3 0.183934845 1
+3 0.122103896 1
+4 0.000367222 31
+3 0.206475986 1
+4 0.000393142 162
+3 0.398737041 1
+4 0.000358632 43
+3 0.169656431 1
+4 0.000426268 18
+3 0.141499927 1
+4 0.000324744 17
+3 0.129908896 1
+4 0.000431243 17
+3 0.157477718 1
+4 0.000331106 18
+3 0.169510188 1
+4 0.000371123 17
+3 0.349819526 1
+4 0.000346283 17
+3 0.135620817 1
+3 0.063908244 1
+4 0.000349393 29
+3 0.639705380 1
+4 0.000358994 18
+3 0.079608415 1
+4 0.000349582 18
+3 0.167641208 1
+4 0.000333097 18
+3 0.119635150 1
+4 0.000325893 18
+3 0.335988537 2
+4 0.000388503 40
+3 0.151517652 1
+4 0.000335407 18
+3 0.127531426 1
+4 0.000328917 17
+3 0.169831361 1
+4 0.000355114 18
+3 0.133559681 1
+3 0.063905257 1
+4 0.000385249 29
+3 0.183692948 1
+4 0.000348863 18
+3 0.159623972 1
+4 0.000374389 18
+3 0.063535418 1
+4 0.000350747 18
+3 0.119697622 1
+4 0.000358409 18
+3 0.151553538 1
+4 0.000402518 17
+3 0.629201687 1
+4 0.109983114 38
+3 298.263891899 1
+4 0.000588358 699
+3 1.606355242 1
+4 0.000872215 897
+3 76.011148005 2
+4 0.000390311 10
+3 0.312238015 1
+4 0.000502056 1
+3 0.102935471 1
+4 0.000351174 1
+3 0.127581255 1
+4 0.000380726 1
+3 0.103742863 1
+4 0.000384563 1
+3 0.063444415 1
+4 0.000359179 1
+3 0.359878770 1
+4 0.000473029 315
+3 0.935393460 1
+4 0.000483869 72
+3 0.217488870 1
+4 0.000383700 83
+3 0.197755857 1
+4 0.000399680 37
+3 0.353532689 1
+4 0.000393040 46
+3 0.445939810 1
+4 0.000403231 17
+3 0.193269546 1
+4 0.000384174 19
+3 0.141479206 1
+4 0.000416231 19
+3 0.185773593 1
+4 0.000344559 19
+3 1.013564710 1
+4 0.000371861 19
+3 0.500236837 1
+4 0.000349341 19
+3 0.083152533 1
+4 0.000362027 18
+3 0.083278402 1
+4 0.000337363 17
+3 0.082801903 1
+4 0.000476148 90
+3 0.082979424 1
+4 0.000371072 138
+3 0.082892788 1
+4 0.000404162 48
+3 0.083297138 1
+4 0.000374667 100
+3 0.082743191 1
+4 0.000454006 77
+3 0.171217027 1
+4 0.000357358 16
+3 0.499821948 1
+4 0.000389587 18
+3 0.083044901 1
+4 0.000359768 20
+3 0.083408324 1
+4 0.000361675 16
+3 0.083595084 1
+4 0.000345073 18
+3 0.082858679 1
+4 0.000353379 17
+3 0.083066037 1
+4 0.000364008 19
+3 0.082619739 1
+4 0.000372550 20
+3 0.083322360 1
+4 0.000335888 20
+3 0.659095664 1
+3 0.064103392 1
+4 0.000413047 4
+3 0.199480585 1
+4 0.000369964 6
+3 0.983673021 1
+3 0.192162767 1
+3 0.137843351 1
+4 0.000374780 31
+3 0.253735860 1
+4 0.000416276 35
+3 0.007498793 1
+4 0.000332880 17
+3 0.567618789 2
+4 0.000441430 56
+3 0.791639884 1
+3 0.216076388 1
+3 0.113871034 1
+4 0.000397392 30
+3 0.269670795 1
+4 0.000500106 176
+3 0.575691826 1
+4 0.000411222 43
+3 0.201417974 1
+4 0.000358402 18
+3 0.213703365 1
+4 0.000369426 17
+3 0.233813941 1
+4 0.000335005 17
+3 0.357464711 1
+4 0.000368953 18
+3 0.431768171 1
+4 0.000345909 17
+3 0.119700892 1
+3 0.063770807 1
+4 0.000352332 4
+3 0.167672569 1
+3 0.063967435 1
+4 0.000368483 4
+3 0.143672983 1
+3 0.056030855 1
+4 0.000352227 4
+3 0.160407573 1
+3 0.071172537 1
+4 0.000355767 4
+3 0.159739816 1
+3 0.039912535 1
+4 0.000347316 4
+3 0.447779307 1
+3 0.055839304 1
+4 0.000379150 5
+3 0.279712819 1
+4 0.000386731 4
+3 0.095611959 1
+4 0.000400849 24
+3 0.207798321 1
+4 0.000337390 27
+3 0.087597784 1
+4 0.000389358 27
+3 0.111494118 1
+4 0.000360532 27
+3 0.119583518 1
+4 0.000460045 27
+3 0.079741611 1
+4 0.000374955 27
+3 0.343562146 2
+4 0.000420269 36
+3 0.143619037 1
+4 0.000485945 17
+3 0.161838563 1
+4 0.000410377 17
+3 0.165388957 1
+4 0.000503584 17
+3 0.351458028 1
+4 0.002150537 18
+3 0.181744478 1
+4 0.000567521 4
+3 0.145375184 1
+4 0.000549998 7
+3 0.445548680 1
+4 0.000495244 24
+3 3.452580790 12
+4 0.000391347 32
+3 0.578726807 2
+4 0.000391488 34
+3 0.359677949 1
+4 0.000383036 17
+3 0.011477617 1
+4 0.000333260 16
+3 0.755720694 2
+4 0.000352425 1
+4 0.000440325 31
+3 0.505727615 1
+4 0.000386077 32
+3 0.341197056 1
+4 0.000373183 18
+3 0.295516508 1
+4 0.000360937 18
+3 7.173168110 1
+3 0.026864958 1
+4 0.000303644 11
+3 0.176044754 1
+4 0.000355252 1
+3 0.111242246 1
+4 0.000392288 1
+4 0.000366758 71
+3 3.295308862 1
+4 0.000416904 37
+3 0.401523517 1
+4 0.000360580 20
+3 0.405717920 1
+4 0.000389768 18
+3 0.577791745 1
+4 0.000400066 17
+3 0.181468215 1
+4 0.000401772 18
+3 0.209541880 1
+4 0.000374824 17
+3 0.213643227 1
+4 0.000387221 17
+3 0.327539140 1
+4 0.000439965 23
+3 0.143698704 1
+4 0.000385017 61
+3 0.119542477 1
+4 0.000354853 61
+3 0.095593840 1
+4 0.000456266 61
+3 0.295655918 1
+4 0.000372849 61
+3 0.375733076 1
+4 0.000403936 61
+3 0.119288440 1
+4 0.000337659 61
+3 0.056065244 1
+4 0.000361086 61
+3 0.143433148 1
+4 0.000362130 102
+3 0.087713046 1
+4 0.000372159 69
+3 1.919627989 2
+4 0.000464314 187
+3 3.551728192 1
+4 0.000393181 19
+3 0.201557515 1
+4 0.000372588 20
+3 0.349688057 1
+4 0.000420833 17
+3 4.831747260 1
+3 0.111871581 1
+3 0.114122553 1
+4 0.000354640 31
+3 0.221585743 1
+4 0.000391777 163
+3 0.240467032 1
+4 0.000434937 41
+3 0.152672352 1
+4 0.000344560 16
+3 0.149768362 1
+4 0.000434848 16
+3 0.127472340 1
+4 0.000339760 18
+3 0.178623535 1
+4 0.000353469 18
+3 0.148709804 1
+4 0.000343942 17
+3 0.153727092 1
+4 0.000386014 17
+3 0.142593698 1
+4 0.000368171 18
+3 0.208699427 1
+4 0.000396993 17
+3 0.333603582 1
+4 0.000538131 17
+3 0.135265076 1
+4 0.000339192 24
+3 0.127829179 1
+4 0.000323979 32
+3 0.119545651 1
+4 0.000342267 32
+3 0.119718848 1
+4 0.000346974 32
+3 0.223585570 1
+4 0.000369503 32
+3 0.288598091 2
+4 0.000382734 37
+3 0.286827308 1
+4 0.000406692 17
+3 0.111520326 1
+4 0.000324944 17
+3 0.153897651 1
+4 0.000346842 18
+3 0.197541026 1
+3 0.071959249 1
+4 0.000341812 33
+3 0.151570364 1
+4 0.000366159 18
+3 0.135625141 1
+4 0.000356074 18
+3 0.063913211 1
+4 0.000401265 18
+3 0.135397091 1
+4 0.000357625 17
+3 0.063550006 1
+4 0.000362082 17
+3 0.279790276 2
+4 0.000441836 42
+3 0.145473116 1
+4 0.000368696 19
+3 0.158423711 1
+4 0.000538310 20
+3 0.152974603 1
+4 0.000396211 20
+3 0.229515269 1
+4 0.000358456 19
+3 0.375529290 1
+3 0.122053636 1
+4 0.000396379 86
+3 5.117682119 1
+4 0.000355614 10
+3 0.143687036 1
+4 0.000342123 1
+3 0.103779058 1
+4 0.000338014 1
+4 0.000471743 70
+3 36.697316637 1
+4 0.000360502 36
+7 0.000559521 TSTP
+7 1.118239345 CONT
+4 0.000607646 7
+4 0.000313754 926
+3 137.956669383 1
+4 0.000608610 896
+3 4.694772644 1
+4 0.000627083 865
+3 0.527194435 1
+4 0.000635130 878
+3 0.743371590 1
+4 0.000677426 934
+3 1.135313487 1
+4 0.000611580 865
+3 31.114191724 1
+4 0.000400871 16
+3 0.498748730 1
+4 0.000370612 17
+3 0.083393608 1
+4 0.000349957 18
+3 0.083228301 1
+4 0.000357796 16
+3 0.083284779 1
+4 0.000421892 16
+3 0.083464480 1
+4 0.000364048 16
+3 0.083115757 1
+4 0.000365411 16
+3 0.545452921 1
+4 0.000375613 18
+3 0.184571070 1
+4 0.000356358 16
+3 2.197804352 1
+4 0.000397371 18
+3 0.201554287 1
+4 0.000400853 18
+3 0.405725695 1
+4 0.000372011 17
+3 2.775555603 1
+4 0.000390934 21
+3 0.501263659 1
+4 0.000381829 4
+3 0.082749646 1
+4 0.000342354 4
+3 0.082921972 1
+4 0.000334667 4
+3 0.084067835 1
+4 0.000353635 4
+3 0.083089249 1
+4 0.000368937 4
+3 0.082963484 1
+4 0.000354061 4
+3 0.242701309 1
+4 0.000354086 4
+3 1.477591715 1
+4 0.000353246 9
+3 0.592358558 1
+4 0.000377591 1
+3 0.174795711 1
+4 0.000321748 1
+3 0.247794938 1
+4 0.000338889 1
+3 0.112209648 1
+4 0.000340485 1
+3 0.135029439 1
+4 0.000341037 1
+3 0.055554909 1
+4 0.000345707 1
+3 0.191736684 1
+4 0.000358563 43
+3 0.319684203 1
+4 0.000365506 17
+3 0.399790968 1
+4 0.000361879 17
+3 0.241394863 1
+4 0.000352882 17
+3 0.725887828 1
+4 0.000477986 17
+3 0.353608370 1
+4 0.000354885 21
+3 0.429584062 1
+4 0.000396938 133
+3 0.279378180 1
+4 0.000358585 17
+3 0.175723038 1
+4 0.000409308 17
+3 4.095816823 1
+3 0.095825766 1
+4 0.000392721 79
+3 0.271896964 1
+3 0.063763870 1
+4 0.000434312 79
+3 12.400029830 2
+4 0.000385072 18
+3 0.500489311 1
+4 0.000381535 18
+3 0.082115608 1
+4 0.000331586 18
+3 0.083558181 1
+4 0.000322628 20
+3 0.082878969 1
+4 0.000412686 17
+3 0.083102007 1
+4 0.000331306 17
+3 0.083058770 1
+4 0.000368108 18
+3 0.083335584 1
+4 0.000328856 18
+3 0.083122443 1
+4 0.000375361 20
+3 0.083140106 1
+4 0.000329073 17
+3 0.535854127 1
+4 0.000363332 17
+3 0.303667929 1
+4 0.000345811 16
+3 0.127414119 1
+4 0.000329253 16
+3 0.575842927 1
+4 0.000372816 18
+3 0.207521448 1
+4 0.000380002 33
+3 0.191680395 1
+4 0.000415139 18
+3 0.239721569 1
+4 0.000359173 18
+3 0.135707566 1
+4 0.000348263 18
+3 0.127456151 1
+4 0.000345213 18
+3 0.113021388 1
+4 0.000349421 18
+3 0.070170448 1
+4 0.000383365 18
+3 0.175705240 1
+4 0.000341282 18
+3 0.039635955 1
+4 0.000448486 18
+3 0.023475627 1
+4 0.000329365 19
+3 0.151772167 1
+4 0.000355765 18
+3 0.151811396 1
+4 0.000345209 18
+3 0.311602242 1
+4 0.000376122 17
+3 0.145722459 1
+4 0.000374938 17
+3 0.141488289 1
+4 0.000411336 18
+3 0.121640620 1
+4 0.000343935 17
+3 0.157504669 1
+4 0.000368814 18
+3 0.095638665 1
+4 0.000335562 18
+3 0.151826083 1
+4 0.000370317 17
+3 0.159537640 1
+4 0.000337397 17
+3 0.200748674 1
+4 0.000433909 17
+3 0.152593300 1
+4 0.000336655 17
+3 0.157635603 1
+4 0.000376891 18
+3 0.137603741 1
+4 0.000350292 17
+3 0.061550084 1
+4 0.000403425 18
+3 0.167783816 1
+4 0.000358165 19
+3 0.159454522 1
+4 0.000356062 18
+3 0.111783645 1
+4 0.000402895 18
+3 0.071540835 1
+4 0.000352165 18
+3 0.079665713 1
+4 0.000441442 18
+3 0.087580841 1
+4 0.000427823 18
+3 0.359989306 1
+4 0.000358601 18
+3 0.239226909 1
+4 0.000373383 17
+3 0.143514814 1
+4 0.000349556 17
+3 0.167751454 1
+4 0.000392330 19
+3 0.159585858 1
+4 0.000355057 17
+3 0.111688172 1
+4 0.000435191 17
+3 0.039591792 1
+4 0.000333307 17
+3 0.079745614 1
+4 0.000380560 17
+3 0.087569485 1
+4 0.000327945 17
+3 0.143716242 1
+4 0.000362228 18
+3 0.151621835 1
+4 0.000377097 18
+3 0.119543924 1
+4 0.000402925 18
+3 0.087366870 1
+4 0.000347471 18
+3 0.087783726 1
+4 0.000351720 19
+3 0.119580802 1
+4 0.000327089 18
+3 1.399803885 1
+4 0.000373000 18
+3 0.135758540 1
+4 0.000388294 18
+3 0.063433900 1
+4 0.000389975 18
+3 0.087873763 1
+4 0.000346176 18
+3 0.015454620 1
+4 0.000345227 18
+3 0.183740784 1
+4 0.000340555 17
+3 0.183687529 1
+4 0.000350207 18
+3 0.087651959 1
+4 0.000354004 18
+3 0.095470793 1
+4 0.000329564 18
+3 0.344080703 1
+4 0.000407214 18
+3 0.375679144 1
+4 0.000386215 18
+3 0.151253567 1
+4 0.000376792 18
+3 0.368260780 1
+4 0.000426592 18
+3 0.463141441 2
+4 0.000372831 39
+3 0.499616728 1
+4 0.000349728 20
+3 0.083258270 1
+4 0.000321692 19
+3 0.082820913 1
+4 0.000371649 17
+3 0.083827042 1
+4 0.000332168 20
+3 0.083185308 1
+4 0.000332464 17
+3 0.083697529 1
+4 0.000339107 17
+3 0.083415893 1
+4 0.000364753 19
+3 0.083598749 1
+4 0.000352820 16
+3 0.083088290 1
+4 0.000427827 21
+3 0.083525197 1
+4 0.000368018 14
+3 0.506039084 1
+4 0.000379518 13
+3 0.095386336 1
+4 0.000367863 16
+3 0.161923430 1
+4 0.000354726 18
+3 0.157560479 1
+4 0.000358988 18
+3 0.423659737 1
+4 0.000353732 17
+3 0.847670925 1
+4 0.000393746 17
+3 0.431620650 1
+4 0.000403175 17
+3 1.167679625 1
+4 0.000387411 79
+3 0.249536457 1
+4 0.000365653 79
+3 0.605670872 1
+4 0.000369650 79
+3 1.783802629 2
+4 0.000379593 18
+3 0.186118123 1
+4 0.000378437 47
+3 0.180976931 1
+4 0.000351710 20
+3 0.217856920 1
+4 0.000408993 17
+3 3.517731838 1
+4 0.000373305 17
+3 0.201450541 1
+4 0.000356815 19
+3 0.245571264 1
+4 0.000341944 20
+3 0.239848248 1
+4 0.000359928 17
+3 0.311511301 1
+4 0.000351362 17
+3 0.161756301 1
+4 0.000334570 18
+3 0.205588500 1
+4 0.000426037 17
+3 0.169868284 1
+4 0.000338882 17
+3 0.109390361 1
+4 0.000355237 23
+3 0.151655281 1
+4 0.000384306 24
+3 0.327530229 1
+4 0.000345480 9
+3 0.127757608 1
+4 0.000403946 1
+3 0.175935105 1
+4 0.000454742 11
+4 0.000420094 61
+3 1.103044519 1
+4 0.000612613 922
+3 0.415175455 1
+4 0.000358090 19
+3 0.527767062 1
+4 0.000379689 16
+3 0.351574936 1
+4 0.000384239 86
+3 0.500235440 1
+4 0.000400092 77
+3 0.082757413 1
+4 0.000376150 77
+3 0.083308781 1
+4 0.000340141 77
+3 0.082992475 1
+4 0.000435990 77
+3 0.178905212 1
+4 0.000364419 77
+3 0.173403319 1
+4 0.000354806 77
+3 0.225831910 1
+4 0.000359714 77
+3 0.749493093 1
+4 0.000391440 22
+3 0.191682853 1
+4 0.000370273 22
+3 0.223780980 1
+4 0.000332007 16
+3 0.217892668 1
+4 0.000356396 17
+3 0.165424257 1
+4 0.000364054 16
+3 0.287407138 1
+4 0.000385048 16
+3 0.113280849 1
+4 0.000358545 22
+3 0.150104957 1
+4 0.000385980 23
+3 0.303582804 1
+4 0.000361146 19
+3 0.743725373 1
+4 0.000360773 16
+3 1.167690376 1
+3 0.087968963 1
+4 0.000380787 4
+3 0.159570709 1
+3 0.072026816 1
+4 0.000350365 4
+3 0.287679924 1
+4 0.000368317 4
+3 0.169859422 1
+4 0.000673128 4
+3 7.632381569 1
+4 0.109950952 1
+3 1.959673015 1
+4 0.000376965 16
+3 1.287215620 1
+3 0.210513588 1
+4 0.000391697 98
+3 0.172921613 1
+3 0.154136665 1
+4 0.000415202 100
+3 0.141822554 1
+3 0.161743453 1
+4 0.000507720 46
+3 0.157412835 1
+3 0.162251948 1
+4 0.000409228 89
+3 0.157538347 1
+3 0.401929979 1
+4 0.000406217 101
+3 0.317547177 1
+4 0.000423142 10
+3 0.151581196 1
+4 0.000518330 1
+3 0.143492974 1
+4 0.000373153 1
+3 0.079624129 1
+4 0.000337376 1
+3 0.047604678 1
+4 0.000383266 1
+3 0.184669164 1
+4 0.000601798 918
+3 3.046839043 1
+4 0.000371088 17
+3 0.145363443 1
+4 0.000371312 18
+3 0.837658318 1
+4 0.000444343 24
+3 0.575418335 1
+4 0.000377676 39
+3 0.055609717 1
+4 0.000364620 39
+3 0.287765120 1
+4 0.000386080 40
+3 0.703784086 2
+4 0.000653224 828
+3 0.319288655 1
+4 0.000622814 874
+3 0.215393969 1
+4 0.000638096 800
+3 0.631478728 1
+4 0.000380618 8
+3 0.151549926 1
+4 0.000337736 1
+3 0.039574688 1
+4 0.000329953 1
+4 0.000375688 632
+3 0.135215715 1
+4 0.000359826 9
+3 0.255687730 1
+4 0.000415834 1
+3 0.135563818 1
+4 0.000346850 1
+3 0.367827358 1
+4 0.000369753 1
+3 0.103438993 1
+4 0.000352540 1
+3 0.103648809 1
+4 0.000327471 1
+3 0.071756608 1
+4 0.000380862 1
+3 0.183704141 1
+4 0.000601790 861
+3 1.415585005 1
+4 0.000682731 1087
+3 0.167337750 1
+4 0.000612615 728
+3 0.455244017 1
+4 0.000448561 31
+4 0.000374506 698
+3 0.745164190 1
+4 0.000372895 21
+3 1.309719317 1
+4 0.000599452 914
+3 0.255336273 1
+4 0.000354554 19
+3 0.825640669 1
+4 0.000387518 21
+3 1.621708460 1
+4 0.000355082 18
+3 0.255636360 1
+4 0.000373358 18
+3 0.199571666 1
+4 0.000368407 17
+3 1.007788881 1
+4 0.000374963 4
+3 0.201587592 1
+4 0.000358092 4
+3 0.133609220 1
+4 0.000452236 4
+3 0.145869939 1
+4 0.000382109 4
+3 0.149274181 1
+4 0.000343534 4
+3 0.145708143 1
+4 0.000351243 4
+3 0.437543032 1
+4 0.000399236 4
+3 0.289909705 1
+4 0.000334891 4
+3 2.605615048 1
+4 0.000409755 18
+3 0.295695513 1
+4 0.000378715 19
+3 0.153513460 1
+4 0.000349889 20
+3 0.213713492 1
+4 0.000411932 21
+3 0.401647731 1
+4 0.000377474 22
+3 0.797560567 1
+4 0.000396681 23
+3 0.425614010 1
+4 0.000359595 24
+3 0.549657260 1
+4 0.000349846 25
+3 2.551724694 1
+4 0.000399019 18
+3 0.499929100 1
+4 0.000352614 17
+3 0.083705797 1
+4 0.000380299 117
+3 0.082983597 1
+4 0.000377553 85
+3 0.082727485 1
+4 0.000455291 34
+3 0.083219394 1
+4 0.000374830 95
+3 0.083604190 1
+4 0.000388504 97
+3 0.169736721 1
+4 0.000350924 17
+3 0.499883640 1
+4 0.000361798 17
+3 0.082699677 1
+4 0.000340410 18
+3 0.082924380 1
+4 0.000368512 20
+3 0.083266795 1
+4 0.000404601 17
+3 0.082798017 1
+4 0.000374351 17
+3 0.082640844 1
+4 0.000347335 18
+3 0.083292975 1
+4 0.000426983 17
+3 0.286914609 1
+4 0.000340747 17
+3 0.295806957 1
+4 0.000376555 4
+3 0.500023921 1
+4 0.000363726 4
+3 0.082953992 1
+4 0.000433494 4
+3 0.082709404 1
+4 0.000336450 4
+3 0.083676007 1
+4 0.000364435 4
+3 0.082964062 1
+4 0.000340507 4
+3 0.082922325 1
+4 0.000365499 4
+3 0.788259159 1
+4 0.000370031 4
+3 1.253521471 1
+4 0.000391511 4
+3 6.599914770 1
+4 0.000380933 18
+3 0.319446621 1
+4 0.000385693 17
+3 3.439896624 1
+4 0.000432834 78
+3 0.500445476 1
+4 0.000417865 78
+3 0.702340298 1
+4 0.000370513 78
+3 0.496989320 1
+4 0.000420677 79
+3 0.083494250 1
+4 0.000359145 78
+3 0.083621482 1
+4 0.000402832 159
+3 0.084331945 1
+4 0.000340128 4
+3 0.742005260 1
+4 0.000404598 4
+3 0.353637154 1
+4 0.000363675 4
+3 5.509918559 1
+4 0.000383274 17
+3 1.479529377 1
+4 0.000380697 78
+3 0.500411556 1
+4 0.000459808 78
+3 0.082778013 1
+4 0.000340857 78
+3 0.083111298 1
+4 0.000404997 78
+3 0.082735630 1
+4 0.000384490 78
+3 0.083630656 1
+4 0.000371814 78
+3 0.359183488 1
+4 0.000355458 78
+3 0.189465730 1
+4 0.000356717 78
+3 0.553740617 1
+4 0.000452195 78
+3 1.621707077 1
+4 0.000382454 18
+3 0.207563026 1
+4 0.000345149 17
+3 0.177616185 1
+4 0.000463753 17
+3 0.133458797 1
+4 0.000328028 16
+3 0.311812562 1
+4 0.000375537 16
+3 0.209715537 1
+4 0.000365633 16
+3 0.213545705 1
+4 0.000386233 22
+3 0.167579291 1
+4 0.000372100 23
+3 0.135611283 1
+4 0.000410175 16
+3 0.209722417 1
+4 0.000362663 16
+3 0.157486100 1
+4 0.000350318 22
+3 0.231957603 1
+4 0.000371729 23
+3 0.512250024 1
+4 0.000429872 16
+3 0.550878919 1
+4 0.000376199 22
+3 0.135440425 1
+4 0.000332319 23
+3 0.170257807 1
+4 0.000325663 17
+3 0.285265098 1
+4 0.000363966 17
+3 0.201519231 1
+4 0.000339678 17
+3 0.181742156 1
+4 0.000331342 17
+3 0.170582676 1
+4 0.000354224 17
+3 0.204709227 1
+4 0.000332339 17
+3 0.521756570 1
+4 0.000364615 17
+3 0.197634097 1
+4 0.000336843 17
+3 0.255701032 1
+4 0.000382266 2
+3 0.159464709 1
+4 0.000368805 17
+3 0.169720266 1
+4 0.000348238 17
+3 0.165632676 1
+4 0.000349272 17
+3 0.351517390 1
+3 0.464418734 1
+4 0.000404631 2
+3 0.743489820 1
+4 0.000405586 17
+3 0.127375207 1
+4 0.000337043 18
+3 0.170141567 1
+4 0.000393307 18
+3 0.333178526 1
+4 0.000357925 17
+3 0.183833666 1
+4 0.000467932 78
+3 0.500190251 1
+4 0.000373160 78
+3 0.082685764 1
+4 0.000385147 78
+3 0.083008182 1
+4 0.000351039 78
+3 0.083037265 1
+4 0.000434460 78
+3 0.082892682 1
+4 0.000355135 78
+3 0.083533921 1
+4 0.000377191 78
+3 0.243935726 1
+4 0.000449754 78
+3 0.213479932 1
+4 0.000382132 78
+3 2.239710334 1
+4 0.000401714 9
+3 0.159516587 1
+4 0.000408303 1
+3 0.063670632 1
+4 0.000355716 1
+4 0.000381180 71
+3 3.663406855 1
+4 0.000379384 37
+3 0.201655132 1
+4 0.000378782 16
+3 0.182043250 1
+4 0.000334297 20
+3 0.153295765 1
+4 0.000329281 17
+3 0.645757822 1
+4 0.000363122 17
+3 0.351475229 1
+4 0.000338047 17
+3 0.231540164 1
+4 0.000365529 17
+3 0.287723036 1
+4 0.000345992 17
+3 0.500168935 1
+4 0.000408512 47
+3 0.082426580 1
+4 0.000367480 92
+3 0.083224488 1
+4 0.000370449 102
+3 0.116669549 1
+4 0.000346915 18
+3 0.500213750 1
+4 0.000350082 19
+3 0.083127552 1
+4 0.000360786 20
+3 0.082980819 1
+4 0.000363822 17
+3 6.310589126 1
+4 0.000394153 17
+3 0.498354169 1
+4 0.000387554 17
+3 0.083219103 1
+4 0.000342153 18
+3 0.083160066 1
+4 0.000360452 20
+3 0.083474179 1
+4 0.000333867 17
+3 0.083153173 1
+4 0.000345219 17
+3 0.082945600 1
+4 0.000324201 18
+3 0.082839985 1
+4 0.000400573 16
+3 0.253944964 1
+4 0.000364001 17
+3 0.303707859 1
+4 0.000380456 23
+3 0.319493883 1
+4 0.000337420 26
+3 0.439684657 2
+4 0.000456120 37
+3 0.231704010 1
+4 0.000364217 17
+3 0.279796722 1
+4 0.000405976 24
+3 0.343401231 1
+4 0.000388183 74
+3 0.303555553 2
+4 0.000394285 36
+3 0.439664416 1
+4 0.000382079 134
+3 0.215740167 1
+4 0.000413677 17
+3 0.154031244 1
+4 0.000370217 19
+3 0.317173508 1
+4 0.000398654 20
+3 0.312109507 1
+4 0.000384129 133
+3 1.311086895 1
+4 0.000468258 17
+3 0.247670264 1
+4 0.000566957 765
+3 2.135572935 1
+4 0.000401778 17
+3 0.559496218 1
+4 0.000356911 17
+3 0.257605602 1
+4 0.000370437 18
+3 0.557561536 1
+4 0.000365280 17
+3 0.183589462 1
+4 0.000407185 24
+3 0.335713990 1
+4 0.000399405 104
+3 0.455592372 2
+4 0.000428032 36
+3 0.201827538 1
+4 0.000396177 47
+3 0.165325141 1
+4 0.000398182 119
+3 0.169743508 1
+4 0.000503484 125
+3 0.197465764 1
+4 0.000403824 47
+3 0.367566207 1
+4 0.000345422 20
+3 0.499948646 1
+4 0.000450718 17
+3 0.082916345 1
+4 0.000334208 19
+3 0.083743043 1
+4 0.000365424 20
+3 0.668027305 1
+4 0.000344319 9
+3 0.127616885 1
+4 0.000389556 1
+3 0.063698609 1
+4 0.000367317 1
+4 0.000308014 14
+4 0.000311920 57
+3 3.103058907 1
+4 0.000420309 37
+3 0.281430416 1
+4 0.000391572 20
+3 0.653620110 1
+4 0.000346649 17
+3 0.441696601 1
+4 0.000351826 19
+3 2.981870284 1
+4 0.000420171 34
+3 0.945760713 1
+4 0.000431728 70
+3 14.926277405 1
+4 0.000381836 17
+3 0.500010040 1
+4 0.000418235 18
+3 0.083287212 1
+4 0.000331118 20
+3 0.083248663 1
+4 0.000425143 17
+3 0.083076968 1
+4 0.000322811 19
+3 0.082702205 1
+4 0.000337987 20
+3 0.575256615 1
+4 0.000363130 17
+3 0.677561508 1
+4 0.000396849 17
+3 0.500089770 1
+4 0.000405668 17
+3 0.082727833 1
+4 0.000337580 17
+3 0.083052744 1
+4 0.000341862 18
+3 0.083609893 1
+4 0.000352462 17
+3 0.082848311 1
+4 0.000321241 17
+3 0.083823926 1
+4 0.000348848 17
+3 0.082284757 1
+4 0.000328215 18
+3 0.083189559 1
+4 0.000355194 17
+3 0.082971342 1
+4 0.000357883 18
+3 0.083156952 1
+4 0.000344987 17
+3 0.082919646 1
+4 0.000320014 18
+3 0.083883272 1
+4 0.000332894 17
+3 0.082801049 1
+4 0.000335230 17
+3 0.083369966 1
+4 0.000331249 18
+3 0.083247646 1
+4 0.000409715 17
+3 0.083043049 1
+4 0.000342522 14
+3 0.084233866 1
+4 0.000339196 16
+3 0.082430678 1
+4 0.000338452 16
+3 0.495768575 1
+4 0.000369233 18
+3 3.663651029 1
+4 0.000357787 17
+3 0.311840767 1
+4 0.000358067 22
+3 0.447516612 1
+4 0.000444672 31
+3 0.527438065 2
+4 0.000368557 24
+3 0.145854319 1
+4 0.000357463 17
+3 0.389686435 1
+4 0.000377187 17
+3 0.295524943 1
+4 0.000347405 31
+3 0.431602915 1
+4 0.000385636 42
+3 0.351714465 1
+4 0.000396298 30
+3 1.175715288 2
+4 0.000417190 37
+3 0.359523623 1
+4 0.000350170 17
+3 0.287663316 1
+4 0.000361177 31
+3 0.287672759 1
+4 0.000377838 43
+3 0.487561501 1
+4 0.000392311 31
+3 0.623635902 2
+4 0.000416460 22
+3 0.231611039 1
+4 0.000358732 24
+3 0.271842044 1
+4 0.000406813 26
+3 0.343370365 2
+4 0.000380928 33
+3 0.170726284 1
+4 0.000380691 17
+3 0.180613035 1
+4 0.000350015 17
+3 0.439559561 1
+4 0.000350252 16
+3 0.169573482 1
+4 0.000362390 18
+3 0.157768876 1
+4 0.000333562 24
+3 0.327944225 1
+4 0.000376491 33
+3 0.823624768 1
+4 0.109929671 33
+3 11.346442722 1
+4 0.000384715 17
+3 0.135385039 1
+4 0.000346971 16
+3 0.153650783 1
+4 0.000366514 18
+3 0.181638007 1
+4 0.000355682 18
+3 0.304121026 1
+4 0.000348081 17
+3 0.185381126 1
+4 0.000349748 17
+3 0.237505223 1
+4 0.000355453 24
+3 1.863642855 1
+4 0.000413811 109
+3 1.328116581 1
+4 0.000406424 109
+3 0.527169793 1
+4 0.000378795 109
+3 0.279499340 1
+4 0.000384060 109
+3 0.695805322 1
+4 0.000379395 109
+3 0.327475776 1
+4 0.000400691 126
+3 0.287808853 1
+4 0.000365527 113
+3 0.811365647 1
+4 0.110066681 33
+3 3.790382320 1
+4 0.000384889 23
+3 2.559652278 1
+3 0.279861622 1
+4 0.000346426 23
+3 0.327756463 1
+4 0.000345382 17
+3 0.169619186 1
+4 0.000355833 18
+3 0.141625037 1
+4 0.000345513 17
+3 0.279692210 1
+4 0.000350600 17
+3 0.135688208 1
+4 0.000339452 23
+3 0.087794348 1
+4 0.000357403 24
+3 4.679945306 1
+4 0.000391928 19
+3 0.369277719 1
+4 0.000362685 20
+3 0.541904679 1
+3 0.169919904 1
+4 0.000407758 146
+3 0.189486320 1
+3 0.154049223 1
+4 0.000376602 116
+3 0.173563108 1
+3 0.122124061 1
+4 0.000379450 64
+3 0.485534711 1
+4 0.000431899 8
+3 0.143536054 1
+4 0.000322833 1
+3 0.103805995 1
+4 0.000353146 1
+4 0.000876790 10
+4 0.000394966 58
+3 0.366300801 1
+4 0.000446745 37
+3 0.169506941 1
+4 0.000361830 16
+3 0.157737806 1
+4 0.000384886 16
+3 0.249607015 1
+4 0.000427266 16
+3 0.181405289 1
+4 0.000362563 16
+3 0.143733834 1
+4 0.000354720 16
+3 0.500558910 1
+4 0.000415658 18
+3 0.083461755 1
+4 0.000349338 18
+3 0.082788023 1
+4 0.000359309 17
+3 0.082908063 1
+4 0.000324597 17
+3 3.224714789 1
+4 0.000379721 17
+3 0.499538503 1
+4 0.000353926 19
+3 0.083267339 1
+4 0.000360067 16
+3 0.083652153 1
+4 0.000335256 20
+3 0.083433569 1
+4 0.000356133 17
+3 0.082976121 1
+4 0.000390926 17
+3 0.083053557 1
+4 0.000419727 17
+3 0.082594671 1
+4 0.000405612 117
+3 0.082932847 1
+4 0.000421645 78
+3 0.082956612 1
+4 0.000375613 34
+3 0.083414152 1
+4 0.000636990 95
+3 0.291714750 1
+4 0.000490907 17
+3 0.499951467 1
+4 0.000568886 18
+3 0.082670852 1
+4 0.000498291 21
+3 0.082713051 1
+4 0.000590882 17
+3 0.083230712 1
+4 0.000519918 17
+3 0.083090766 1
+4 0.000561212 17
+3 1.709356913 1
+4 0.000384305 17
+3 0.499886762 1
+4 0.000363184 17
+3 0.083006562 1
+4 0.000345084 17
+3 0.083533142 1
+4 0.000346778 20
+3 0.083482127 1
+4 0.000365645 16
+3 0.083693772 1
+4 0.000322166 20
+3 0.083716517 1
+4 0.000396755 97
+3 0.082845649 1
+4 0.000373926 98
+3 0.083463729 1
+4 0.000382354 47
+3 0.082898629 1
+4 0.000381183 92
+3 0.083018539 1
+4 0.000389878 101
+3 0.083403555 1
+4 0.000388824 47
+3 0.175108423 1
+4 0.000347562 20
+3 0.217146999 1
+4 0.000350923 17
+3 0.165603007 1
+4 0.000346764 19
+3 0.137694771 1
+4 0.000349303 20
+3 0.157613162 1
+4 0.000382712 17
+3 0.167650866 1
+4 0.000342564 17
+3 0.311745700 1
+4 0.000378919 17
+3 0.153516781 1
+4 0.000389323 17
+3 0.325654480 1
+4 0.000391744 21
+3 0.169688353 1
+4 0.000357614 4
+3 0.157534808 1
+4 0.000353330 4
+3 0.154886136 1
+4 0.000425480 4
+3 0.124415471 1
+4 0.000353887 4
+3 0.137713377 1
+4 0.000385011 4
+3 0.149458119 1
+4 0.000354594 4
+3 0.121685638 1
+4 0.000361286 4
+3 0.973709966 1
+4 0.000376678 17
+3 1.009665186 1
+4 0.000377569 19
+3 0.205524115 1
+4 0.000387418 20
+3 0.495785323 1
+4 0.000385730 4
+3 0.499647967 1
+4 0.000375708 4
+3 0.083155548 1
+4 0.000381245 4
+3 0.083038932 1
+4 0.000350367 4
+3 0.083074377 1
+4 0.000350422 4
+3 0.082811653 1
+4 0.000345684 4
+3 0.082843827 1
+4 0.000429483 4
+3 0.082536445 1
+4 0.000329136 4
+3 0.744076080 1
+4 0.000388774 17
+3 0.303425704 1
+4 0.000346177 18
+3 0.119614101 1
+4 0.000332779 17
+3 0.140024791 1
+4 0.000347506 17
+3 0.107287043 1
+4 0.000413799 23
+3 0.207633584 1
+4 0.000427452 24
+3 0.495798375 1
+4 0.000591242 838
+3 0.415387430 1
+4 0.000400310 18
+3 0.185488924 1
+4 0.000353861 17
+3 0.165759249 1
+4 0.000397123 20
+3 0.169620639 1
+4 0.000359521 16
+3 0.718012984 1
+4 0.000402799 16
+3 0.177357060 1
+4 0.000365666 17
+3 0.325489631 1
+4 0.000397737 16
+3 0.167680709 1
+4 0.000400409 4
+3 0.499983596 1
+4 0.000443905 4
+3 0.082783046 1
+4 0.000424726 4
+3 0.082516554 1
+4 0.000366547 4
+3 0.083271276 1
+4 0.000338383 4
+3 0.083111548 1
+4 0.000445116 4
+3 0.082715200 1
+4 0.000343684 4
+3 0.444670136 1
+4 0.000424947 4
+3 1.461772429 1
+4 0.000372625 16
+3 0.161544881 1
+4 0.000389758 18
+3 0.133779295 1
+4 0.000356464 19
+3 0.375657353 1
+4 0.000409811 4
+3 0.500130550 1
+4 0.000446349 4
+3 0.084072290 1
+4 0.000405097 4
+3 0.081983605 1
+4 0.000433410 4
+3 0.083212407 1
+4 0.000385627 4
+3 0.082625138 1
+4 0.000355126 4
+3 0.082970102 1
+4 0.000433675 4
+3 0.083703605 1
+4 0.000355807 4
+3 0.941974868 1
+4 0.000401594 16
+3 0.287662486 1
+4 0.000370377 17
+3 0.175662421 1
+4 0.000450268 16
+3 0.137429599 1
+4 0.000349171 16
+3 0.117702694 1
+4 0.000364947 22
+3 0.207886655 1
+4 0.000341449 23
+3 1.104204534 1
+4 0.000595586 19
+3 0.499726414 1
+4 0.000412254 17
+3 0.082763129 1
+4 0.000422345 20
+3 0.083462409 1
+4 0.000367752 20
+3 0.083536698 1
+4 0.000350644 21
+3 0.663735900 1
+4 0.000378557 21
+3 0.263573715 1
+4 0.000380666 17
+3 0.047575241 1
+4 0.000343907 16
+3 0.170558034 1
+4 0.000366080 18
+3 0.156796717 1
+4 0.000415633 18
+3 0.359565909 1
+4 0.000389897 18
+3 0.119534956 1
+4 0.000333576 18
+3 0.225726019 1
+4 0.000418449 17
+3 0.205589490 1
+4 0.000353991 4
+3 0.499804267 1
+4 0.000354127 4
+3 0.083319670 1
+4 0.000579498 4
+3 0.082781763 1
+4 0.000385999 4
+3 0.082551312 1
+4 0.000360121 4
+3 0.083515411 1
+4 0.000336331 4
+3 0.084003421 1
+4 0.000330381 4
+3 0.363489014 1
+4 0.000365388 4
+3 0.165517621 1
+4 0.000341948 18
+3 0.201602455 1
+4 0.000426000 19
+3 0.269700353 1
+4 0.000346176 20
+3 0.287606038 1
+4 0.000387541 79
+3 0.500757622 1
+4 0.000381185 79
+3 0.082492019 1
+4 0.000348990 79
+3 0.083543179 1
+4 0.000357938 79
+3 0.083056603 1
+4 0.000356201 79
+3 0.082954796 1
+4 0.000390463 79
+3 0.083051835 1
+4 0.000340912 79
+3 0.082798583 1
+4 0.000374209 79
+3 1.262590706 1
+4 0.000395391 17
+3 0.199750642 1
+4 0.000340637 20
+3 0.287499305 1
+4 0.000344857 17
+3 0.153627834 1
+4 0.000361415 17
+3 0.133617182 1
+4 0.000423563 23
+3 0.183659316 1
+4 0.000363558 24
+3 0.175599840 1
+4 0.000340404 19
+3 0.241835755 1
+4 0.000348606 16
+3 0.229516546 1
+4 0.000345795 17
+3 0.185609469 1
+4 0.000340789 18
+3 0.149637670 1
+4 0.000345723 18
+3 0.500791570 1
+4 0.000445016 47
+3 0.082583390 1
+4 0.000377035 83
+3 0.083365873 1
+4 0.000460660 92
+3 0.082824087 1
+4 0.000376083 47
+3 0.083414413 1
+4 0.000371807 112
+3 0.083491880 1
+4 0.000376482 86
+3 0.083854113 1
+4 0.000371886 47
+3 0.300784350 1
+4 0.000492564 20
+3 0.499820846 1
+4 0.000378588 17
+3 0.083179389 1
+4 0.000362515 19
+3 0.083469929 1
+4 0.000340053 20
+3 0.082670043 1
+4 0.000349875 20
+3 0.083500008 1
+4 0.000342594 20
+3 0.082973318 1
+4 0.000343174 20
+3 0.217746683 1
+4 0.000363125 17
+3 0.128338762 1
+4 0.000334453 18
+3 0.168770898 1
+4 0.000443666 18
+3 0.213671488 1
+4 0.000328120 17
+3 0.025716945 1
+4 0.000370642 17
+3 0.357758108 1
+4 0.000351117 17
+3 0.169543519 1
+4 0.000392530 17
+3 0.141609781 1
+4 0.000347500 17
+3 0.727612317 1
+4 0.000399071 4
+3 0.187152626 1
+4 0.000362028 4
+3 0.148122889 1
+4 0.000444145 4
+3 0.145526596 1
+4 0.000342455 4
+3 0.197732554 1
+4 0.000376040 4
+3 0.177643966 1
+4 0.000342032 4
+3 0.181679284 1
+4 0.000394013 4
+3 0.593474459 1
+4 0.000369757 4
+3 0.237802186 1
+4 0.000452974 17
+3 0.201487042 1
+4 0.000346969 19
+3 0.181551425 1
+4 0.000373977 21
+3 0.711760029 1
+3 0.088219534 1
+4 0.000357894 4
+3 1.759548545 1
+4 0.000542106 17
+3 0.217450484 1
+4 0.000543141 19
+3 0.277457836 1
+4 0.000376117 20
+3 0.399547567 1
+4 0.000372843 4
+3 0.239770273 1
+4 0.000341606 17
+3 0.239459643 1
+4 0.000354375 18
+3 0.167748072 1
+4 0.000368185 17
+3 0.161714100 1
+4 0.000331686 17
+3 0.141647695 1
+4 0.000343859 23
+3 0.175629679 1
+4 0.000372694 24
+3 0.103554779 1
+4 0.000439057 19
+3 0.169664638 1
+4 0.000417062 95
+3 0.165604493 1
+4 0.000408782 93
+3 0.169626978 1
+4 0.000388267 47
+3 0.197489319 1
+4 0.000353575 20
+3 0.169870056 1
+4 0.000355273 17
+3 0.213649084 1
+4 0.000350989 17
+3 0.047486240 1
+4 0.000324129 16
+3 0.161671274 1
+4 0.000346250 18
+3 0.141689031 1
+4 0.000379799 18
+3 0.183639098 1
+4 0.000335563 17
+3 0.431604394 1
+3 0.072073842 1
+4 0.000397484 4
+3 0.199608915 1
+4 0.000333885 17
+3 0.711716130 1
+4 0.000444465 18
+3 0.111475471 1
+4 0.000342124 16
+3 0.143705701 1
+4 0.000364229 1
+3 0.072023722 1
+4 0.000315558 1
+3 0.447214710 2
+4 0.000338835 1
+4 0.000399088 67
+3 0.162072418 1
+4 0.000343971 4
+3 0.492889031 1
+4 0.000433418 17
+3 0.183511417 1
+4 0.000338202 18
+3 0.151760080 1
+4 0.000353876 18
+3 0.177669887 1
+4 0.000373866 17
+3 0.101681943 1
+4 0.000427001 23
+3 0.167488100 1
+4 0.000346252 24
+3 0.079733083 1
+4 0.000378997 19
+3 0.161602206 1
+4 0.000383186 34
+3 0.158769842 1
+4 0.000424969 82
+3 0.168544633 1
+4 0.000383672 115
+3 0.469599939 1
+4 0.000497017 116
+3 0.169647661 1
+4 0.000401025 92
+3 0.181501628 1
+4 0.000412609 47
+3 0.201461558 1
+4 0.000376930 34
+3 0.469729442 1
+4 0.000517278 18
+3 3.634148108 1
+4 0.000353365 20
+3 0.197171038 1
+4 0.000395122 20
+3 0.439500765 1
+4 0.000381673 20
+3 0.319544893 1
+4 0.000367765 17
+3 0.153726098 1
+4 0.000350973 17
+3 0.149624446 1
+4 0.000421456 17
+3 0.095585004 1
+4 0.000353419 23
+3 0.439530502 2
+4 0.000366432 29
+3 0.144480307 1
+4 0.000346839 23
+3 0.214910498 1
+4 0.000544866 24
+3 0.239634133 1
+4 0.000347315 17
+3 0.151450031 1
+4 0.000421811 18
+3 0.193713288 1
+4 0.000350838 18
+3 0.053541780 1
+4 0.000395381 17
+3 0.159637998 1
+4 0.000349715 17
+3 0.343839411 1
+4 0.000424118 17
+3 0.169593905 1
+4 0.000361401 17
+3 0.213455686 1
+3 0.088162845 1
+4 0.000349742 4
+3 0.807653749 1
+4 0.000590419 811
+3 0.327398399 1
+4 0.000350294 10
+3 0.135653423 1
+4 0.000360454 1
+3 0.119713405 1
+4 0.000366595 1
+4 0.000367560 69
+3 0.391102699 1
+4 0.000393085 36
+3 0.171125079 1
+4 0.000346290 17
+3 0.164187638 1
+4 0.000370940 15
+3 0.279596206 1
+4 0.000339502 17
+3 0.187105726 1
+4 0.000333155 17
+3 0.468493314 1
+4 0.000376724 16
+3 0.463535375 1
+3 0.151953765 1
+4 0.000383799 20
+3 0.335625730 1
+4 0.000356158 16
+3 0.177858248 1
+4 0.000444427 18
+3 0.318031680 1
+4 0.000354948 20
+3 0.598943884 1
+4 0.000419828 4
+3 0.376477818 1
+4 0.000405880 16
+3 0.200943755 1
+4 0.000380972 18
+3 0.197394866 1
+4 0.000346636 20
+3 0.311586026 1
+4 0.000444641 4
+3 0.343674151 1
+4 0.000364287 17
+3 0.169615881 1
+4 0.000388487 19
+3 0.181685338 1
+4 0.000348924 20
+3 1.599598489 1
+4 0.000580054 4
+3 0.383449244 1
+4 0.000377671 17
+3 0.185655545 1
+4 0.000488395 19
+3 0.165740137 1
+4 0.000484289 20
+3 0.407297798 1
+4 0.000410615 4
+3 0.239601119 1
+4 0.000369584 19
+3 0.199583063 1
+4 0.000379429 18
+3 0.199690679 1
+4 0.000387326 17
+3 0.185636739 1
+4 0.000375703 17
+3 0.389683301 1
+4 0.000375682 23
+3 0.168057557 1
+4 0.000387858 24
+3 0.343110087 1
+4 0.000351349 19
+3 0.201702332 1
+4 0.000364174 16
+3 0.189587561 1
+4 0.000338508 20
+3 0.233660534 1
+4 0.000392796 19
+3 1.573761567 1
+4 0.000390660 9
+3 0.095555823 1
+4 0.000343815 1
+3 0.159632041 1
+4 0.000337522 1
+3 0.079673356 1
+4 0.000359858 1
+4 0.000980505 10
+4 0.000359183 61
+3 0.342306424 1
+4 0.000389909 35
+3 0.500321479 1
+4 0.000444199 51
+3 0.083255876 1
+4 0.000405104 34
+3 0.082790624 1
+4 0.000375824 63
+3 0.172274916 1
+4 0.000340301 17
+3 0.500388717 1
+4 0.000371203 18
+3 0.083013323 1
+4 0.000343404 20
+3 0.083474899 1
+4 0.000325347 17
+3 0.083312871 1
+4 0.000372762 19
+3 0.083168494 1
+4 0.000358499 17
+3 0.082694849 1
+4 0.000328069 18
+3 0.083686067 1
+4 0.000327436 20
+3 0.082873073 1
+4 0.000334989 19
+3 7.891431332 1
+4 0.000664983 937
+3 0.286472250 1
+4 0.000579445 770
+3 0.247373909 1
+4 0.000576050 932
+3 0.455528649 1
+4 0.000573675 716
+3 0.383576281 1
+4 0.000669928 615
+3 0.551140399 1
+4 0.000697621 647
+3 1.335153592 1
+4 0.000522782 15
+3 0.500175251 1
+4 0.000382502 15
+3 0.083026774 1
+4 0.000352613 16
+3 0.083259074 1
+4 0.000372923 15
+3 0.083595977 1
+4 0.000378020 17
+3 0.082989066 1
+4 0.000411759 17
+3 0.188640354 1
+4 0.000355060 16
+3 0.247867350 1
+4 0.000468442 22
+3 1.399357655 1
+4 0.000366174 18
+3 0.759786035 1
+4 0.000413566 18
+3 0.071606423 1
+4 0.000394679 18
+3 0.112732241 1
+4 0.000412462 18
+3 0.118313899 1
+4 0.000430946 18
+3 0.071392479 1
+4 0.000368698 18
+3 0.103767191 1
+4 0.000387429 19
+3 0.721284357 1
+4 0.110006112 33
+3 0.424351588 1
+4 0.000378997 16
+3 0.161596483 1
+4 0.000498455 16
+3 0.349667671 1
+4 0.000375140 23
+3 0.223531420 1
+4 0.000411806 25
+3 0.991724465 1
+4 0.000381443 25
+3 0.167557833 1
+4 0.000442192 25
+3 0.137535956 1
+4 0.000360285 27
+3 0.117626571 1
+4 0.000390086 25
+3 0.703759347 1
+4 0.000371237 25
+3 0.119686952 1
+4 0.000374561 26
+3 0.191588087 1
+4 0.000395497 25
+3 0.088293034 1
+4 0.000380320 25
+3 0.742746392 2
+4 0.105697838 37
+3 0.023053975 1
+4 0.000383199 17
+3 0.126989308 1
+4 0.000356697 15
+3 0.751825140 1
+4 0.000381633 15
+3 1.159592105 1
+4 0.000371959 18
+3 0.151667092 1
+4 0.000393159 15
+3 0.423468492 1
+4 0.000361709 18
+3 0.143701173 1
+4 0.000417394 16
+3 0.135456882 1
+4 0.000361989 17
+3 0.151678345 1
+4 0.000369964 17
+3 0.135731878 1
+4 0.000344024 17
+3 2.919857971 1
+4 0.000396250 16
+3 0.279536198 1
+4 0.000398445 17
+3 0.511886168 1
+4 0.000397594 16
+3 0.231441322 1
+4 0.000356468 17
+3 0.103510344 1
+4 0.000380772 16
+3 0.135673632 1
+4 0.000350063 17
+3 0.135497894 1
+4 0.000436801 17
+3 0.095578070 1
+4 0.000354244 18
+3 0.135695039 1
+4 0.000452497 17
+3 0.055691179 1
+4 0.000363124 17
+3 0.143563638 1
+4 0.000361664 17
+3 0.399694195 1
+4 0.000367626 16
+3 0.231529790 1
+4 0.000433258 17
+3 0.063518663 1
+4 0.000336569 17
+3 0.063690859 1
+4 0.000359410 16
+3 0.200158477 1
+4 0.000396737 17
+3 0.167138258 1
+4 0.000376001 17
+3 0.055644122 1
+4 0.000374781 18
+3 0.167654564 1
+4 0.000349898 17
+3 0.063605224 1
+4 0.000354548 16
+3 0.152392989 1
+4 0.000354777 17
+3 0.062843544 1
+4 0.000342127 17
+3 0.103807551 1
+4 0.000404765 17
+3 0.111572012 1
+4 0.000351588 17
+3 0.367715454 2
+4 0.000376739 10
+3 0.111597239 1
+4 0.000337430 1
+3 0.207800105 1
+4 0.000373721 1
+3 0.927574858 1
+4 0.000378119 1
+4 0.000910395 10
+4 0.000349291 60
+3 13.327831835 1
+4 0.000645291 927
+3 0.526431244 1
+4 0.000596756 751
+3 0.567378071 1
+4 0.000653579 861
+3 0.439652125 1
+4 0.000583643 774
+3 1.063130218 1
+4 0.000562647 610
+3 2.735568898 1
+4 0.000545164 558
+3 0.591456258 1
+4 0.000606715 830
+3 1.023525670 1
+4 0.000649515 694
+3 0.455261151 1
+4 0.000556382 473
+3 1.135566027 1
+4 0.000598606 612
+3 0.231338607 1
+4 0.000627040 879
+3 0.215256263 1
+4 0.000554070 616
+3 0.191478140 1
+4 0.000579073 606
+3 0.719585214 1
+4 0.000578407 753
+3 19.504875154 1
+4 0.000361189 34
+7 0.000562995 TSTP
+7 3.126512649 CONT
+4 0.000588769 7
+4 0.000380269 7
+4 0.000354194 750
+3 311.641897994 1
+4 0.000604112 877
+3 0.998748534 1
+4 0.000585499 736
+3 0.543243285 1
+4 0.000590598 920
+3 1.215382810 1
+4 0.000626907 748
+3 0.759577586 1
+4 0.000378405 16
+3 0.500355277 1
+4 0.000378008 16
+3 0.082934555 1
+4 0.000333983 16
+3 0.083181849 1
+4 0.000345495 16
+3 0.083045391 1
+4 0.000332502 18
+3 0.322425180 1
+4 0.000333350 16
+3 0.189693383 1
+4 0.000364966 16
+3 0.151719082 1
+4 0.000328601 16
+3 0.201621575 1
+4 0.000353389 16
+3 0.317554951 1
+4 0.000368242 16
+3 0.169513519 1
+4 0.000344426 16
+3 4.302883350 1
+3 0.183082352 1
+3 0.130055613 1
+4 0.000367496 29
+3 0.333626376 1
+4 0.000364249 37
+3 0.169648346 1
+4 0.000332523 16
+3 0.213809620 1
+4 0.000450185 131
+3 0.383346101 1
+4 0.000393992 126
+3 0.295802735 2
+4 0.000356949 34
+3 0.137805466 1
+4 0.000356504 16
+3 0.141251852 1
+4 0.000328164 18
+3 0.186312331 1
+4 0.000325851 18
+3 0.157293999 1
+4 0.000357570 17
+3 0.119801855 1
+4 0.000392268 17
+3 0.711658819 1
+3 0.079877700 1
+4 0.000364041 28
+3 0.191593101 1
+4 0.000405981 18
+3 0.111644357 1
+4 0.000330638 18
+3 0.111417820 1
+4 0.000400641 18
+3 0.215732039 1
+4 0.000356014 18
+3 0.423839652 2
+4 0.000368967 36
+3 1.359666507 1
+4 0.000360121 17
+3 22.696217775 2
+4 0.000364050 18
+3 0.240160250 1
+4 0.000372361 17
+3 2.479207069 1
+3 0.071960936 1
+4 0.000361362 28
+3 0.175536104 1
+4 0.000345406 18
+3 0.111798617 1
+4 0.000344638 18
+3 0.135680226 1
+4 0.000374027 18
+3 0.175718654 1
+4 0.000354925 18
+3 0.543588816 2
+4 0.000353300 33
+3 0.407616585 1
+4 0.000341374 17
+3 0.153794364 1
+4 0.000357012 17
+3 2.813745145 1
+4 0.000360069 24
+3 3.687602308 2
+4 0.000404036 33
+3 0.423620674 1
+4 0.000373787 17
+3 2.545818720 1
+4 0.000377595 17
+3 0.781588378 1
+4 0.000374532 24
+3 1.895694680 1
+4 0.000362996 21
+3 0.137583514 1
+4 0.000363227 23
+3 0.125608581 1
+4 0.000354598 21
+3 0.255686021 1
+4 0.000384391 19
+3 0.129658171 1
+4 0.000383271 20
+3 0.109489916 1
+4 0.000431427 17
+3 13.248049988 2
+4 0.000424076 31
+3 0.319697438 1
+4 0.000367284 20
+3 0.671588544 1
+4 0.000382924 49
+3 0.800196597 1
+4 0.000395701 16
+3 0.168100866 1
+4 0.000346183 16
+3 0.110656936 1
+4 0.000371000 18
+3 1.584289938 1
+4 0.000362400 18
+3 0.199015099 1
+4 0.000442427 18
+3 0.129483498 1
+4 0.000348687 18
+3 0.189607259 1
+4 0.000393515 18
+3 0.167777309 1
+4 0.000361169 17
+3 3.546079966 15
+4 0.000455112 33
+3 9.347909578 1
+4 0.109990815 33
+3 0.627551628 1
+4 0.000381786 18
+3 0.399697487 1
+4 0.000395214 29
+3 0.243427135 13
+4 0.000446506 31
+3 1.248157353 1
+4 0.109995515 34
+3 4.490067760 1
+3 0.083856092 1
+4 0.000387412 16
+3 0.528023063 1
+3 0.153386148 1
+4 0.000397320 74
+3 0.413628130 1
+4 0.000351231 18
+3 0.471818832 1
+4 0.000500237 25
+3 0.207428342 1
+4 0.000377993 19
+3 0.311628436 2
+4 0.000388215 9
+3 0.143596403 1
+4 0.000347411 1
+3 0.175732792 1
+4 0.000407666 1
+3 0.079541562 1
+4 0.000370632 1
+4 0.000314804 54
+4 0.000331122 15
+3 52.370415160 1
+4 0.000650054 891
+3 0.589851841 1
+4 0.000625414 814
+3 0.559417946 1
+4 0.000662742 922
+3 2.183633578 1
+4 0.000600612 797
+3 1.111368831 1
+4 0.000580402 680
+3 3.023420204 1
+4 0.000783246 783
+3 0.303155855 1
+4 0.000851199 923
+3 0.383194869 1
+4 0.000791889 809
+3 0.607230184 1
+4 0.000745230 883
+3 2.695368393 1
+4 0.000589889 689
+3 2.607443931 1
+4 0.000423971 18
+3 0.249494793 1
+4 0.000343334 16
+3 25.495109330 1
+4 0.000397043 16
+3 0.185120056 1
+4 0.000355099 16
+3 0.151116361 1
+4 0.000361796 18
+3 0.160043361 1
+4 0.000346922 16
+3 0.301642111 1
+3 0.137906881 1
+4 0.000349964 28
+3 0.205709678 1
+4 0.000366959 37
+3 0.162539226 1
+4 0.000344278 16
+3 0.156614882 1
+4 0.000390682 18
+3 0.217739910 1
+4 0.000412163 16
+3 0.293620538 1
+4 0.000371324 71
+3 4.383928242 1
+4 0.000384727 18
+3 0.201504645 1
+4 0.000342978 17
+3 1.421781402 1
+3 0.055847564 1
+4 0.000363371 28
+3 0.255754333 1
+4 0.000376076 18
+3 0.159453995 1
+4 0.000341660 18
+3 0.136324941 1
+4 0.000381340 18
+3 0.246976566 1
+4 0.000365764 18
+3 0.782015232 1
+4 0.110026089 33
+3 1.003877816 1
+4 0.000423505 9
+3 0.127449232 1
+4 0.000350303 1
+3 0.159619209 1
+4 0.000328406 1
+3 0.192771301 1
+4 0.000410219 1
+4 0.000369259 10
+4 0.000297636 61
+3 9.231636766 1
+4 0.000364204 35
+7 0.000533543 TSTP
+7 1.677861371 CONT
+4 0.000709404 7
+4 0.000258601 722
+3 3.296041959 1
+4 0.000394331 35
+7 0.000524420 TSTP
+7 9.622426511 CONT
+4 0.000536008 7
+4 0.000294990 664
+3 32.720725744 1
+4 0.000462659 17
+3 0.359159217 1
+3 0.138045550 1
+4 0.000394501 81
+3 0.053564869 1
+4 0.000376500 63
+3 41.185576701 1
+4 0.000378621 17
+3 0.374911082 1
+3 0.130036236 1
+4 0.000385894 54
+3 0.077434689 1
+4 0.000387997 61
+3 3.256007840 1
+4 0.000380680 9
+3 0.111427215 1
+4 0.000329944 1
+3 0.151767387 1
+4 0.000401364 1
+3 0.119783561 1
+4 0.000357625 1
+4 0.000330857 14
+4 0.000321627 57
+3 26.432783973 1
+4 0.000360734 35
+7 0.000540272 TSTP
+7 1.638401958 CONT
+4 0.000620050 7
+4 0.000263276 722
+3 20.040125363 1
+4 0.000376103 19
+3 0.499356754 1
+4 0.000396980 35
+3 0.082717724 1
+4 0.000378205 94
+3 0.083076036 1
+4 0.000423738 89
+3 0.083778095 1
+4 0.000408547 94
+3 4.960955350 1
+4 0.000381038 17
+3 0.201194482 1
+4 0.000357095 17
+3 0.149608263 1
+4 0.000362816 17
+3 0.170104859 1
+4 0.000347020 19
+3 0.421481515 1
+4 0.000344429 20
+3 1.311561552 1
+4 0.000419294 18
+3 1.215535250 1
+4 0.000406120 23
+3 0.111510392 1
+4 0.000342121 19
+3 0.127732346 1
+4 0.000333493 19
+3 0.079906920 1
+4 0.000340861 20
+3 0.135354815 1
+4 0.000336685 19
+3 0.215895431 1
+4 0.000359662 16
+3 0.471864560 2
+4 0.000427681 9
+3 0.103542921 1
+4 0.000380301 1
+3 0.111394516 1
+4 0.000623447 1
+3 0.135586436 1
+4 0.000662568 11
+4 0.000491916 57
+3 0.367199525 1
+4 0.000417002 35
+7 0.000579930 TSTP
+7 3.190750507 CONT
+4 0.000593766 7
+4 0.000284779 774
+3 5.471359994 1
+4 0.000459874 16
+3 0.153533655 1
+4 0.000361816 20
+3 0.469318465 1
+3 0.007847296 1
+3 0.845079062 1
+3 0.035052113 1
+4 0.000355537 18
+3 0.208313541 1
+4 0.000436611 22
+3 0.206993239 1
+4 0.000425016 17
+3 0.231936612 2
+4 0.000426777 34
+3 0.159141599 1
+4 0.000405512 55
+3 0.135576787 1
+4 0.000343081 18
+3 0.175634789 1
+4 0.000441921 55
+3 0.072012783 1
+4 0.000351657 18
+3 0.127822426 1
+4 0.000455363 55
+3 0.327044101 1
+4 0.000375474 8
+3 0.063577551 1
+4 0.000349591 1
+3 0.159970670 1
+4 0.000353036 1
+3 0.103682984 1
+4 0.000424628 1
+4 0.000792283 10
+4 0.000364645 58
+3 1.078671651 1
+4 0.000391093 34
+7 0.000513596 TSTP
+7 2.591065402 CONT
+4 0.000601346 7
+4 0.000287188 791
+3 37.760831992 1
+4 0.000443768 14
+3 0.160747888 1
+4 0.000344691 14
+3 0.133686815 1
+4 0.000334620 14
+3 0.263782102 1
+4 0.000373509 44
+3 0.191557949 1
+4 0.000363541 16
+3 0.295618804 1
+4 0.000389317 16
+3 0.415866786 1
+4 0.000372879 19
+3 0.175714516 1
+4 0.000381307 18
+3 0.095311527 1
+4 0.000376169 18
+3 0.143728133 1
+4 0.000357376 17
+3 0.143807808 1
+4 0.000395966 18
+3 0.095362582 1
+4 0.000329435 17
+3 0.576008873 1
+4 0.000456409 18
+3 0.135118685 1
+4 0.000373175 18
+3 0.023614825 1
+4 0.000400278 18
+3 0.199667163 1
+4 0.000344809 18
+3 0.087976135 1
+4 0.000370895 18
+3 0.095574375 1
+4 0.000329680 18
+3 0.199431335 1
+4 0.000372131 18
+3 0.127554755 1
+4 0.000392708 18
+3 0.192014997 1
+4 0.000427810 18
+3 0.215260752 1
+4 0.000394722 18
+3 0.183626456 1
+4 0.000400192 18
+3 0.079732331 1
+4 0.000387065 17
+3 0.232420431 1
+4 0.000491812 18
+3 0.166613868 1
+4 0.000495342 18
+3 0.071768069 1
+4 0.000442951 19
+3 0.127220424 1
+4 0.000356692 18
+3 0.137877295 1
+4 0.000415021 17
+3 0.181293341 1
+4 0.000358763 18
+3 0.095706054 1
+4 0.000354026 18
+3 0.088033930 1
+4 0.000345101 17
+3 0.375264587 1
+4 0.000490245 18
+3 0.071473917 1
+4 0.000417871 18
+3 0.135625942 1
+4 0.000380041 18
+3 0.119745699 1
+4 0.000368423 18
+3 0.071518698 1
+4 0.000412694 19
+3 0.087535976 1
+4 0.000355199 18
+3 0.095721416 1
+4 0.000397695 17
+3 0.167747682 1
+4 0.000332670 18
+3 0.079805314 1
+4 0.000417932 18
+3 0.119643272 1
+4 0.000352331 18
+3 0.223328679 1
+4 0.000396868 18
+3 0.303678505 2
+4 0.000380271 9
+3 0.047529437 1
+4 0.000363105 1
+3 0.224008517 1
+4 0.000337254 1
+3 0.207354297 1
+4 0.000399690 1
+4 0.000906479 10
+4 0.000402682 61
+3 1444.511782296 1
+4 0.000357469 35
+3 1.342687924 1
+4 0.000366400 14
+3 0.407610514 1
+4 0.000351696 33
+3 0.520420433 1
+4 0.000350931 16
+3 0.230857014 1
+4 0.000341388 14
+3 0.159793954 1
+4 0.000346996 28
+3 0.159601748 1
+4 0.000366510 16
+3 0.247626520 1
+4 0.000406626 14
+3 0.143416056 1
+4 0.000355414 28
+3 0.143689211 1
+4 0.000331886 17
+3 0.247721225 1
+4 0.000343072 14
+3 0.112647575 1
+4 0.000342353 24
+3 0.222669051 1
+4 0.000339199 17
+3 0.185998654 1
+4 0.000370907 16
+3 1.949534608 1
+4 0.000351397 16
+3 3.199702184 1
+4 0.000367257 18
+3 0.177412774 1
+4 0.000310564 17
+3 0.149758084 1
+4 0.000399511 18
+3 0.137634608 1
+4 0.000328197 17
+3 0.630029674 1
+4 0.000364345 31
+3 0.008581525 1
+4 0.000315502 26
+3 0.606622757 1
+4 0.000342426 17
+3 0.183407419 1
+4 0.000354683 18
+3 0.551780711 2
+4 0.000353001 34
+3 0.319603902 1
+4 0.000324205 17
+3 37.505124390 2
+4 0.109937326 1
+4 0.000284505 53
+3 0.314168709 1
+4 0.000448015 16
+3 0.351243330 1
+4 0.000329283 14
+3 0.247724391 1
+4 0.000348110 19
+3 0.935489659 2
+4 0.000358535 34
+3 0.255623807 1
+4 0.000348768 1
+3 0.186146414 1
+4 0.000360970 1
+3 0.213625304 1
+4 0.000367568 16
+3 0.191209864 1
+4 0.000348053 30
+3 0.311505848 1
+4 0.000407475 19
+3 0.111493980 1
+4 0.000336532 18
+3 0.047993277 1
+4 0.000317649 17
+3 0.415678954 1
+4 0.000349863 18
+3 62.666060129 2
+4 0.000606532 931
+3 4.375431732 1
+4 0.000582261 864
+3 4.007561683 1
+4 0.000606428 920
+3 0.615130627 1
+4 0.000395265 152
+3 0.623644967 1
+4 0.000464766 85
+3 0.500366140 1
+4 0.000387863 36
+3 0.082937457 1
+4 0.000538294 46
+3 0.082774391 1
+4 0.000439587 69
+3 0.900148919 1
+4 0.000413634 15
+3 0.500630508 1
+4 0.000370006 17
+3 0.082212526 1
+4 0.000358776 17
+3 0.458020142 1
+4 0.000352446 15
+3 0.741673343 1
+3 0.153841053 1
+4 0.000382350 111
+3 8.134125152 1
+4 0.000409732 15
+3 0.185466395 1
+4 0.000328110 15
+3 0.101576738 1
+4 0.000327092 17
+3 0.185854954 1
+4 0.000335670 17
+3 0.149600279 1
+4 0.000362093 16
+3 0.423566779 1
+4 0.000340985 30
+3 0.247704807 1
+4 0.000415144 33
+3 0.698039358 1
+4 0.109954509 30
+3 1.183854845 1
+4 0.000587227 743
+3 6.823896413 1
+4 0.000639671 794
+3 3.543257902 1
+4 0.000353344 18
+3 0.217631915 1
+4 0.000336459 17
+3 0.197417741 1
+4 0.000349473 19
+3 0.187658067 1
+4 0.000335192 16
+3 151.345510542 1
+4 0.000365247 16
+3 0.590975836 1
+4 0.000393298 16
+3 0.463692786 1
+3 0.145831771 1
+4 0.000398722 114
+3 0.557795268 1
+4 0.000392380 52
+3 0.936298833 1
+4 0.000358777 15
+3 0.680089190 1
+4 0.000346781 17
+3 5.979960398 44
+4 0.000422221 96
+3 0.554367727 2
+3 0.162133998 1
+4 0.000396206 82
+3 0.141456616 1
+4 0.000407998 19
+3 0.191551242 1
+3 0.146260670 1
+4 0.000428847 112
+3 0.205228187 1
+4 0.000340512 16
+3 0.127846804 1
+4 0.000330859 16
+3 0.185792950 1
+4 0.000331302 16
+3 3.933610220 1
+4 0.000343234 16
+3 1.863725787 1
+4 0.000356375 23
+3 0.327644144 1
+4 0.000344743 48
+3 0.063482729 1
+4 0.000348582 48
+3 0.279936861 1
+4 0.000340867 48
+3 0.271691438 1
+4 0.000336898 48
+3 0.319538697 1
+4 0.000331634 48
+3 1.167651877 1
+4 0.000356329 48
+3 0.167654474 1
+4 0.000345840 49
+3 0.071693547 1
+4 0.000326721 48
+3 0.247570408 1
+4 0.000370740 48
+3 0.615741893 1
+4 0.000464667 16
+3 0.215612366 1
+4 0.000355715 17
+3 0.599537487 1
+4 0.000358534 48
+3 0.087817960 1
+4 0.000340005 48
+3 0.087692776 1
+4 0.000326620 48
+3 0.239713026 1
+4 0.000346762 48
+3 0.255488394 1
+4 0.000369661 48
+3 0.280455348 1
+4 0.000349905 48
+3 0.310991988 1
+4 0.000369127 16
+3 0.359660061 1
+4 0.000341556 17
+3 0.119479788 1
+4 0.000413928 48
+3 0.105672374 1
+4 0.000362396 49
+3 0.453571012 1
+4 0.000373295 48
+3 0.799768052 1
+4 0.000408525 48
+3 0.487553934 1
+4 0.000443791 48
+3 2.456102815 1
+4 0.000354594 48
+3 79.488811236 1
+4 0.110023221 32
+3 0.715179515 1
+4 0.000381592 16
+3 0.391509277 1
+4 0.000393526 29
+3 0.943740666 1
+4 0.000349374 17
+3 0.207526246 1
+4 0.000485668 17
+3 0.143704057 1
+4 0.000348007 17
+3 0.143435378 1
+4 0.000368142 17
+3 0.772597412 1
+4 0.110063985 36
+3 13.022095358 1
+4 0.000403981 16
+3 0.318925791 1
+4 0.000336517 16
+3 0.231729783 1
+4 0.000376458 22
+3 0.327623023 1
+4 0.000356997 23
+3 4.863969747 1
+4 0.000400224 19
+3 0.271571541 1
+3 0.121996556 1
+4 0.000371499 114
+3 1.221527164 1
+4 0.000358054 10
+3 0.135648707 1
+4 0.000346341 1
+3 0.191734839 1
+4 0.000327609 1
+3 0.855719441 1
+4 0.000405426 1
+4 0.000913135 10
+4 0.000366858 59
+3 1.639324634 1
+4 0.000346597 36
+7 0.000524874 TSTP
+7 7.390665382 CONT
+4 0.000577837 7
+4 0.000278006 890
+3 0.943025876 1
+4 0.000390314 36
+7 0.000583277 TSTP
+7 3.655223483 CONT
+4 0.000662626 7
+4 0.000274567 832
+3 0.238863751 1
+4 0.000341171 10
+3 0.151505929 1
+4 0.000391834 1
+3 0.137883068 1
+4 0.000322436 1
+3 0.109515330 1
+4 0.000404666 1
+3 0.103717451 1
+4 0.000357360 37
+3 0.815709527 1
+4 0.000352853 15
+3 0.159532468 1
+4 0.000363590 27
+3 0.135611441 1
+4 0.000325560 17
+3 0.279702847 2
+4 0.000381860 10
+3 0.111647606 1
+4 0.000319571 1
+3 0.151625318 1
+4 0.000400472 1
+3 0.111620405 1
+4 0.000357341 1
+4 0.000349341 70
+3 0.271431357 1
+4 0.000442392 36
+7 0.000589559 TSTP
+7 5.007416369 CONT
+4 0.000611646 7
+4 0.000285315 894
+3 139.067795008 1
+4 0.000366007 10
+3 0.175382851 1
+4 0.000358223 1
+3 0.111476767 1
+4 0.000329678 1
+3 0.175716778 1
+4 0.000320858 1
+3 0.079671236 1
+4 0.000316534 1
+3 0.151560952 1
+4 0.000326277 1
+3 0.488409850 1
+4 0.000363235 2
+3 0.190930680 1
+4 0.000375687 1
+3 0.087882121 1
+4 0.000362324 1
+3 0.191550670 1
+4 0.000377130 1
+3 0.079498486 1
+4 0.000329328 1
+3 0.159837929 1
+4 0.000368066 1
+3 0.191679354 1
+4 0.000347134 1
+3 0.111522730 1
+4 0.000495846 230
+3 0.935864352 1
+4 0.000425402 92
+3 0.471305015 1
+4 0.000458137 99
+3 0.500865580 1
+4 0.000398986 47
+3 0.082631283 1
+4 0.000414903 84
+3 0.183422133 1
+4 0.000400867 19
+3 0.500266352 1
+4 0.000375323 20
+3 0.083307165 1
+4 0.000331403 18
+3 0.415194545 1
+4 0.000402584 20
+3 1.023936226 1
+4 0.000497916 101
+3 0.500055301 1
+4 0.000417051 47
+3 0.082510846 1
+4 0.000372054 34
+3 0.224011651 1
+4 0.000378891 18
+3 0.500202057 1
+4 0.000358539 20
+3 0.082465930 1
+4 0.000364336 17
+3 1.576237965 1
+4 0.000351901 17
+3 0.500393152 1
+4 0.000424266 17
+3 0.082998040 1
+4 0.000337146 17
+3 0.083361640 1
+4 0.000366396 17
+3 0.083026828 1
+4 0.000328046 17
+3 0.322675228 1
+4 0.000358470 17
+3 0.197462184 1
+4 0.000327079 17
+3 8.983859141 1
+4 0.000370774 19
+3 0.185493393 1
+4 0.000377384 20
+3 0.245713013 1
+4 0.000360578 18
+3 1.775859748 1
+4 0.000390726 17
+3 0.217434224 1
+4 0.000437951 17
+3 0.613590208 1
+4 0.000343518 17
+3 0.401991192 1
+4 0.000365295 17
+3 0.613633274 1
+4 0.000386015 23
+3 4.831604582 2
+4 0.000418606 24
+3 0.609550222 1
+4 0.000349183 17
+3 1.197892808 1
+4 0.000392443 18
+3 0.743417992 1
+4 0.000355778 31
+3 0.135791222 1
+4 0.000363517 41
+3 0.255623210 1
+4 0.000348819 41
+3 0.135439706 1
+4 0.000355313 41
+3 0.127642166 1
+4 0.000343773 41
+3 0.087597337 1
+4 0.000413648 41
+3 0.511757339 1
+4 0.000386501 17
+3 0.295549405 1
+4 0.000354872 17
+3 0.247871391 1
+4 0.000336372 18
+3 0.423687804 1
+4 0.000366803 18
+3 0.312824699 1
+4 0.000346374 18
+3 0.166498953 1
+4 0.000392980 18
+3 0.175434190 1
+4 0.000342254 18
+3 0.048255175 1
+4 0.000380756 41
+3 0.407030000 2
+4 0.000370220 22
+3 0.217738714 1
+4 0.000353696 17
+3 0.181536597 1
+4 0.000332401 18
+3 0.231541475 1
+4 0.000345720 13
+3 0.415750621 1
+4 0.000338210 32
+4 0.000414623 47
+3 0.759277247 1
+4 0.000397349 17
+3 0.169834065 1
+4 0.000337775 17
+3 0.261383628 1
+3 0.064153359 1
+4 0.000348148 4
+3 0.231520166 1
+3 0.056531856 1
+4 0.000382853 4
+3 1.895342307 1
+4 0.000456643 17
+3 0.201356339 1
+4 0.000378326 17
+3 0.181691568 1
+4 0.000363113 17
+3 0.249584295 1
+4 0.000389502 14
+3 0.165768928 1
+4 0.000340410 17
+3 0.305572986 1
+4 0.000431361 18
+3 0.317493918 1
+4 0.000350985 24
+3 0.184487115 1
+4 0.000458530 40
+3 0.126821620 1
+4 0.000338513 41
+3 0.151634183 1
+4 0.000388402 40
+3 0.087626685 1
+4 0.000340338 40
+3 0.175741439 1
+4 0.000438664 40
+3 0.191535949 1
+4 0.000441000 40
+3 2.983589796 1
+4 0.000394143 36
+3 3.876142022 1
+4 0.110035167 33
+3 2.245808557 1
+4 0.000385760 9
+3 0.479480256 1
+4 0.000346419 1
+3 0.175540002 1
+4 0.000401919 1
+3 0.144704507 1
+4 0.000414907 1
+4 0.000994584 33
+4 0.000359030 234
+3 1.077365878 1
+4 0.000452370 1
+4 0.000529473 39
+3 0.975461430 1
+4 0.000369082 10
+3 0.079079752 1
+4 0.000333556 1
+3 0.111602431 1
+4 0.000355467 1
+3 0.143759103 1
+4 0.000351076 1
+3 0.079804287 1
+4 0.000390138 1
+3 0.159501313 1
+4 0.000336925 1
+3 0.191638893 1
+4 0.000321370 1
+3 0.087790847 1
+4 0.000365868 39
+3 0.951692897 1
+4 0.000388405 20
+4 0.000296957 44
+3 0.943170547 1
+4 0.000385451 39
+3 1.015715447 1
+4 0.000368926 18
+3 0.495572904 1
+4 0.000357103 27
+3 0.271727558 1
+4 0.000354500 41
+3 0.279593281 1
+4 0.000368767 41
+3 0.279729949 1
+4 0.000344578 41
+3 0.119512584 1
+4 0.000335820 41
+3 0.127658598 1
+4 0.000350615 41
+3 0.112015544 1
+4 0.000350583 41
+3 0.359414507 2
+4 0.001179038 37
+4 0.000369617 50
+3 0.152403225 1
+4 0.000364549 18
+3 0.157671627 1
+4 0.000394073 17
+3 0.145641042 1
+4 0.000347979 17
+3 0.309696044 1
+4 0.000435866 79
+3 0.375578806 1
+4 0.000369602 17
+3 0.367673524 1
+4 0.000357062 17
+3 0.159409371 1
+3 0.072207178 1
+4 0.000343349 4
+3 0.159688152 1
+3 0.055847137 1
+4 0.000362818 4
+3 0.671784890 1
+4 0.000363347 7
+3 0.343688525 1
+4 0.000415495 6
+3 0.543510360 1
+4 0.000344138 17
+3 0.209642619 1
+4 0.000352097 17
+3 0.181762731 1
+4 0.000331216 17
+3 0.201586802 1
+4 0.000345010 18
+3 0.365829346 1
+4 0.000350518 17
+3 0.137561319 1
+4 0.000347562 18
+3 0.197610494 1
+4 0.000367008 17
+3 0.319585496 1
+4 0.000425341 31
+3 0.223569372 1
+4 0.000376930 22
+3 0.263653708 1
+4 0.000353015 22
+3 0.095704747 1
+4 0.000337212 22
+3 0.031598269 1
+4 0.000390594 23
+3 0.159870952 1
+4 0.000373548 22
+3 0.087394680 1
+4 0.000441986 22
+3 0.135671073 1
+4 0.000346682 17
+3 0.171746131 1
+4 0.000372517 17
+3 0.123510868 1
+4 0.000334221 18
+3 0.039498943 1
+4 0.000397046 19
+3 0.095672146 1
+4 0.000325363 18
+3 0.143754279 1
+4 0.000368239 18
+3 0.223605386 1
+4 0.000426063 22
+3 0.471610261 2
+4 0.000363802 10
+3 0.015554665 1
+4 0.000331508 1
+3 0.519817760 1
+4 0.000334263 1
+3 0.095415578 1
+4 0.000337575 1
+3 0.207982629 1
+4 0.000324473 1
+3 0.199753320 1
+4 0.000356718 1
+4 0.000355183 71
+3 0.631202493 1
+4 0.000368000 36
+7 0.000533702 TSTP
+7 9.719803852 CONT
+4 0.000717076 7
+4 0.000281202 935
+3 1.910931388 1
+4 0.000374954 27
+3 0.791476970 1
+4 0.000428506 22
+3 0.503506447 1
+4 0.000359931 22
+3 0.783341366 1
+4 0.110007030 31
+3 1.274470397 1
+4 0.000387502 10
+3 0.535680050 1
+4 0.000383579 1
+3 0.231451119 1
+4 0.000348086 1
+3 0.567827770 1
+4 0.000370217 1
+4 0.000969074 10
+4 0.000368597 61
+3 0.390582206 1
+4 0.000343682 36
+7 0.000550450 TSTP
+7 7.671269982 CONT
+4 0.000521260 7
+4 0.000313171 937
+3 3.359782410 1
+4 0.000585741 735
+3 0.582616667 1
+4 0.000372238 9
+3 0.239602178 1
+4 0.000379157 1
+3 0.071530109 1
+4 0.000409901 1
+3 0.047637382 1
+4 0.000337421 1
+3 0.151664776 1
+4 0.000346153 1
+3 0.159637490 1
+4 0.000337865 1
+3 0.095592779 1
+4 0.000543052 483
+3 1.175692739 1
+4 0.000522195 459
+3 0.959460007 1
+4 0.000413312 10
+3 0.087665908 1
+4 0.000588781 901
+3 20.248284711 1
+4 0.000628499 735
+3 0.703151451 1
+4 0.000394160 16
+3 0.500440767 1
+4 0.000364519 19
+3 0.083350811 1
+4 0.000339014 16
+3 0.083368775 1
+4 0.000367441 16
+3 0.082421879 1
+4 0.000334253 16
+3 0.083399387 1
+4 0.000373818 16
+3 0.082500566 1
+4 0.000352212 18
+3 0.083488959 1
+4 0.000393128 16
+3 0.083496147 1
+4 0.000331955 16
+3 0.083871243 1
+4 0.000343925 16
+3 0.081931645 1
+4 0.000370064 17
+3 0.082703361 1
+4 0.000366468 19
+3 0.083019623 1
+4 0.000334439 15
+3 20.326566240 1
+4 0.000471274 48
+3 0.327106449 1
+4 0.000353524 17
+3 0.311706322 1
+4 0.000347343 15
+3 0.303618878 1
+4 0.000346708 18
+3 0.728839583 1
+4 0.000354561 17
+3 0.238385696 1
+4 0.000352209 17
+3 0.112615975 1
+4 0.000399816 17
+3 0.120579656 1
+4 0.000385619 17
+3 0.133655702 1
+4 0.000344040 17
+3 0.095466522 1
+4 0.000360328 16
+3 3.910454605 17
+4 0.000387696 34
+3 0.882055600 1
+4 0.000366495 17
+3 0.703083657 1
+4 0.109998917 32
+3 12.138355281 1
+4 0.000353524 17
+3 0.391376221 1
+3 0.114111346 1
+4 0.000390180 30
+3 0.733514800 2
+4 0.000318313 43
+3 0.296185035 1
+4 0.000370741 10
+3 0.095073316 1
+4 0.000320445 1
+3 0.159714469 1
+4 0.000398610 1
+3 0.671756082 1
+4 0.000389472 1
+4 0.000316261 54
+4 0.000335938 16
+3 3.918991433 1
+4 0.000381639 39
+3 1.391820866 1
+3 0.122572983 1
+4 0.000360413 30
+3 0.204894183 1
+4 0.000384831 86
+3 0.271578260 1
+4 0.000331163 18
+3 0.191741559 1
+4 0.000335189 24
+3 0.199800770 1
+4 0.000354462 54
+3 0.303563006 2
+4 0.000393336 37
+3 0.479595529 1
+4 0.000347304 17
+3 0.169714473 1
+4 0.000343137 17
+3 1.181838714 1
+4 0.000350867 17
+3 0.215787302 1
+3 0.055719028 1
+4 0.000390356 4
+3 0.183565376 1
+3 0.048098033 1
+4 0.000346186 4
+3 0.183546432 1
+3 0.064027289 1
+4 0.000349285 4
+3 0.183726774 1
+3 0.064156076 1
+4 0.000362277 4
+3 0.215339578 1
+3 0.072071346 1
+4 0.000363777 4
+3 0.231873889 1
+3 0.063969603 1
+4 0.000402839 4
+3 0.263444177 1
+3 0.063964083 1
+4 0.000342881 4
+3 0.343905078 1
+3 0.071787058 1
+4 0.000406727 4
+3 0.383604382 1
+4 0.000364356 4
+3 0.487710026 1
+4 0.000347111 10
+3 0.111479835 1
+4 0.000339801 1
+3 0.159905658 1
+4 0.000329563 1
+3 0.151681622 1
+4 0.000380117 1
+4 0.000362919 71
+3 0.351505640 1
+4 0.000382206 36
+7 0.000580633 TSTP
+7 32.463933608 CONT
+4 0.000537317 7
+4 0.000244099 818
+3 47.356867926 1
+4 0.109957000 1
+3 0.806463708 1
+4 0.000358654 26
+3 0.263077121 1
+4 0.000404056 21
+3 0.201777643 1
+4 0.000340541 22
+3 0.181498047 1
+4 0.000391365 25
+3 0.201749986 1
+4 0.000410354 26
+3 0.213830902 1
+4 0.000374860 29
+3 0.242743477 1
+4 0.000394934 30
+3 0.244272733 1
+4 0.000385118 33
+3 0.209309059 1
+4 0.000340397 34
+3 0.214094906 1
+4 0.000378032 32
+3 0.251108045 1
+4 0.000372349 41
+3 0.587937535 1
+4 0.000481045 90
+3 0.841658979 1
+4 0.000494395 486
+3 1.341390713 1
+4 0.000486133 24
+3 0.519694376 1
+4 0.000393747 155
+3 0.831485644 1
+4 0.000447253 77
+3 0.169721938 1
+4 0.000424379 89
+3 0.173329315 1
+4 0.000399653 37
+3 0.695943082 1
+4 0.000396328 19
+3 0.217744022 1
+4 0.000371435 19
+3 1.013539345 1
+4 0.000351822 19
+3 0.201679794 1
+4 0.000371668 16
+3 0.381651959 1
+4 0.000347085 16
+3 0.111281352 1
+4 0.000372287 17
+3 40.945109689 2
+4 0.000383051 1
+3 0.146046290 1
+4 0.000424718 114
+3 0.293110069 1
+4 0.000349116 18
+3 0.343611868 1
+4 0.000465799 21
+3 0.152039383 1
+4 0.000341033 18
+3 0.895491197 1
+4 0.000431804 85
+3 0.121643026 1
+4 0.000380059 114
+3 0.717740102 1
+4 0.000388116 10
+3 0.136135528 1
+4 0.000338595 1
+3 0.159004015 1
+4 0.000358829 1
+3 0.127435366 1
+4 0.000419382 1
+4 0.000360168 69
+3 0.351579698 1
+4 0.000340105 36
+7 0.000542662 TSTP
+7 3.574908791 CONT
+4 0.000647797 7
+4 0.000365803 7
+4 0.000333531 932
+3 25.144213797 1
+4 0.000398416 15
+3 0.498848979 1
+4 0.000351256 15
+3 0.082812596 1
+4 0.000329004 15
+3 0.083143137 1
+4 0.000348013 14
+3 0.082660556 1
+4 0.000387320 46
+3 0.082704152 1
+4 0.000439266 69
+3 0.083314713 1
+4 0.000433380 68
+3 1.363337851 1
+4 0.000425625 15
+3 0.535453563 1
+3 0.131077452 1
+4 0.000364806 28
+3 0.476484778 1
+4 0.000402903 36
+3 0.169805705 1
+4 0.000360465 17
+3 0.157433074 1
+4 0.000344571 17
+3 0.161739168 1
+4 0.000359301 15
+3 0.165484321 1
+4 0.000349031 15
+3 1.320462291 1
+4 0.000400814 85
+3 0.855094187 1
+4 0.000374453 17
+3 0.185572957 1
+4 0.000418129 16
+3 0.558124604 1
+3 0.063631937 1
+4 0.000407487 27
+3 0.199283070 1
+4 0.000443065 17
+3 0.112006975 1
+4 0.000373057 17
+3 0.151304036 1
+4 0.000393661 17
+3 0.223637698 1
+4 0.000412293 17
+3 0.239479322 1
+4 0.000353837 28
+3 0.758172425 1
+4 0.109982937 32
+3 3.740049129 1
+4 0.000367935 10
+3 0.119621049 1
+4 0.000373245 1
+3 0.143618739 1
+4 0.000352990 1
+3 0.127356695 1
+4 0.000448660 1
+4 0.000735504 10
+4 0.000317788 60
+3 0.254609036 1
+4 0.000391575 38
+3 0.153508364 1
+4 0.000345369 16
+3 0.158001131 1
+4 0.000370827 16
+3 0.407492826 1
+3 0.122224923 1
+4 0.000402076 121
+3 0.213027993 1
+4 0.000368828 10
+3 0.160033352 1
+4 0.000312779 1
+3 0.127679358 1
+4 0.000325689 1
+3 0.111858366 1
+4 0.000427966 1
+4 0.000728807 10
+4 0.000310549 59
+3 0.358674147 1
+4 0.000381775 36
+7 0.000556280 TSTP
+7 3.398953112 CONT
+4 0.000585693 7
+4 0.000258047 816
+3 8.359823493 1
+4 0.000364980 15
+3 0.398872193 1
+4 0.000355369 15
+3 0.223880601 1
+3 0.113803831 1
+4 0.000440426 124
+3 0.093815211 1
+4 0.000425262 71
+3 0.311346433 1
+4 0.000346301 10
+3 0.079595192 1
+4 0.000380864 1
+3 0.144039791 1
+4 0.000317825 1
+3 0.135665510 1
+4 0.000416861 1
+4 0.000694595 10
+4 0.000313831 60
+3 0.631121519 1
+4 0.000437524 36
+7 0.000499301 TSTP
+7 1.455005436 CONT
+4 0.000590497 7
+4 0.000254139 819
+3 9.727355907 1
+4 0.000415913 18
+3 0.463029287 1
+4 0.000347850 19
+3 0.202215316 1
+4 0.000372760 16
+3 0.829066678 1
+3 0.122203769 1
+4 0.000439313 114
+3 0.453506556 1
+4 0.000421375 10
+3 0.167711639 1
+4 0.000365479 1
+3 0.159427775 1
+4 0.000336347 1
+3 0.175990250 1
+4 0.000538887 11
+4 0.000378672 60
+3 0.439932577 1
+4 0.000405067 36
+7 0.000552412 TSTP
+7 1.518019485 CONT
+4 0.000663787 7
+4 0.000252195 864
+3 19.912570325 1
+4 0.000392436 16
+3 0.192646540 1
+4 0.000357344 18
+3 0.165647707 1
+4 0.000375569 17
+3 0.156129872 1
+4 0.000346051 19
+3 0.259497708 1
+3 0.122179663 1
+4 0.000393729 29
+3 0.213048153 1
+4 0.000370261 36
+3 0.146222355 1
+4 0.000344307 17
+3 0.141011473 1
+4 0.000349990 19
+3 0.231654842 1
+4 0.000402098 82
+3 1.559949739 1
+4 0.000411193 17
+3 0.231403233 1
+4 0.000346807 23
+3 0.071911835 1
+4 0.000379667 18
+3 0.119365932 1
+4 0.000346694 18
+3 0.071560426 1
+4 0.000376899 19
+3 0.159663650 1
+4 0.000362636 18
+3 0.167663410 1
+4 0.000353339 18
+3 0.079650029 1
+4 0.000406404 18
+3 0.527922390 2
+4 0.000543237 32
+3 0.151624218 1
+4 0.001092944 17
+3 0.160825397 1
+4 0.000389846 17
+3 0.165772322 1
+4 0.000392250 16
+3 0.391473104 1
+3 0.071853894 1
+4 0.000411310 27
+3 0.175424679 1
+4 0.000350117 17
+3 0.095606766 1
+4 0.000384163 17
+3 0.095548028 1
+4 0.000345581 17
+3 0.176055076 1
+4 0.000386596 17
+3 0.199374962 1
+4 0.000351586 34
+3 0.671730466 2
+4 0.000465209 10
+3 0.087443393 1
+4 0.000336542 1
+3 0.127659853 1
+4 0.000395755 1
+3 0.111659148 1
+4 0.000357388 1
+4 0.000365768 70
+3 0.359942717 1
+4 0.000474416 36
+7 0.000526799 TSTP
+7 16.391336233 CONT
+4 0.000606739 7
+4 0.000252703 825
+3 9.423126066 1
+4 0.000404453 17
+3 0.103478360 1
+4 0.000379639 17
+3 0.215753975 1
+3 0.055777719 1
+4 0.000374798 27
+3 2.192310846 1
+4 0.000364538 18
+3 0.095017669 1
+4 0.000374579 17
+3 0.167858272 1
+4 0.000394995 17
+3 0.183487470 1
+4 0.000328229 17
+3 0.424749918 2
+4 0.000375944 14
+3 0.086373079 1
+4 0.000342026 1
+3 0.143957741 1
+4 0.000323698 1
+3 0.095552429 1
+4 0.000351824 1
+4 0.000369679 14
+4 0.000331407 56
+3 0.407347448 1
+4 0.000387372 36
+7 0.000639935 TSTP
+7 3.249297749 CONT
+4 0.000674732 7
+4 0.000254330 824
+3 83.655961172 1
+4 0.000430093 19
+3 0.271188534 1
+4 0.000394617 19
+3 27.608941812 1
+3 0.161186568 1
+4 0.000450516 124
+3 0.437705088 1
+3 0.079896297 1
+4 0.000395445 27
+3 0.207743933 1
+4 0.000356038 17
+3 0.111692035 1
+4 0.000370128 17
+3 0.095509613 1
+4 0.000337918 16
+3 0.112097732 1
+4 0.000401108 17
+3 0.063059306 1
+4 0.000361219 36
+3 0.552280978 1
+4 0.000415916 16
+3 0.135428657 1
+4 0.000336479 16
+3 0.367466610 1
+4 0.000411259 16
+3 0.247878161 1
+4 0.000349830 16
+3 0.103207817 1
+4 0.000381731 17
+3 0.207641973 1
+4 0.000394821 17
+3 0.111713293 1
+4 0.000365416 16
+3 0.079649048 1
+4 0.000356122 16
+3 0.795727480 1
+4 0.110053931 32
+3 0.038080066 1
+4 0.000342743 17
+3 0.279446216 1
+4 0.000374827 23
+3 0.295697084 1
+4 0.000354596 18
+3 0.535620025 1
+4 0.000454264 18
+3 0.095457715 1
+4 0.000349601 18
+3 0.103619461 1
+4 0.000371113 19
+3 0.247658136 1
+4 0.000352418 18
+3 0.223712040 1
+4 0.000394071 18
+3 0.215535872 1
+4 0.000349938 18
+3 0.399676754 2
+4 0.000391624 10
+3 0.120019780 1
+4 0.000385700 1
+3 0.287262291 1
+4 0.000410793 1
+3 5.687972903 1
+4 0.000422720 1
+4 0.000835771 10
+4 0.000338408 60
+3 3.654443851 1
+4 0.000358954 36
+7 0.000568777 TSTP
+7 2.735311839 CONT
+4 0.000617805 7
+4 0.000258026 872
+3 6.247684694 1
+4 0.000381665 17
+3 0.271033476 1
+3 0.080017407 1
+4 0.000376864 21
+3 0.183514484 1
+4 0.000400388 7
+3 0.543949651 1
+4 0.000355286 10
+3 0.119603286 1
+4 0.000363348 1
+3 0.127447163 1
+4 0.000341483 1
+3 0.327721799 1
+4 0.000428809 1
+4 0.000707831 10
+4 0.000323420 60
+3 0.343068111 1
+4 0.000514657 36
+7 0.000473004 TSTP
+7 14.439862195 CONT
+4 0.000539168 7
+4 0.000254087 866
+3 0.614218693 1
+4 0.000363210 16
+3 0.177673946 1
+4 0.000353681 16
+3 0.157793450 1
+4 0.000325782 16
+3 0.161671660 1
+4 0.000395594 17
+3 0.157483187 1
+4 0.000332878 16
+3 0.123732328 1
+4 0.000401784 16
+3 0.187796972 1
+4 0.000357585 22
+3 0.119318881 1
+4 0.000324225 31
+3 0.138162368 1
+4 0.000379037 33
+3 0.117380233 1
+4 0.000358787 35
+3 0.359435429 2
+4 0.000397934 10
+3 0.479762921 1
+4 0.000361008 42
+3 0.311959467 1
+4 0.000390897 30
+3 0.135228283 1
+4 0.000363360 31
+3 0.592821208 2
+4 0.000371179 32
+3 0.102464558 1
+4 0.000401580 23
+3 0.271758514 1
+4 0.000352094 10
+3 0.095461652 1
+4 0.000352317 1
+3 0.175740178 1
+4 0.000360447 1
+3 0.119944584 1
+4 0.000369823 1
+4 0.000418330 54
+4 0.000290714 16
+3 0.535003752 1
+4 0.000347906 36
+7 0.000540252 TSTP
+7 8.119422644 CONT
+4 0.000550546 7
+4 0.000270883 7
+4 0.000309568 863
+3 4.439312397 1
+4 0.000422377 10
+3 0.126842073 1
+4 0.000374980 1
+3 0.191573294 1
+4 0.000343883 1
+3 0.104338672 1
+4 0.000337400 1
+3 0.095097124 1
+4 0.000333834 1
+3 0.183571932 1
+4 0.000343439 1
+3 0.071851031 1
+4 0.000341209 1
+3 0.215747016 1
+4 0.000416855 21
+4 0.000328367 433
+3 1.303495007 1
+3 0.105633305 1
+4 0.000369836 30
+3 0.317692992 1
+4 0.000596648 512
+3 2.639519736 1
+4 0.000636971 842
+3 0.153213684 1
+4 0.000353795 2
+3 0.445780954 1
+4 0.000386371 61
+3 0.823774769 1
+4 0.000441965 10
+3 0.097360557 1
+4 0.000493182 1
+3 0.157577353 1
+4 0.000729707 11
+4 0.000470530 61
+3 3.390825751 1
+4 0.000405386 39
+3 0.255568652 1
+3 0.055907219 1
+4 0.000356174 28
+3 0.223697836 1
+4 0.000363714 18
+3 0.071906737 1
+4 0.000392293 18
+3 0.137411001 1
+4 0.000339774 18
+3 0.069925847 1
+4 0.000366418 18
+3 0.415281632 2
+4 0.000369014 14
+3 0.175719944 1
+4 0.000341084 1
+3 0.159555979 1
+4 0.000344904 1
+3 0.111749441 1
+4 0.000375281 1
+4 0.000410804 71
+3 6.504533238 1
+4 0.000361531 36
+7 0.000558118 TSTP
+7 1.278101661 CONT
+4 0.000811650 7
+4 0.000376336 769
+3 11.511743118 1
+4 0.000364527 17
+3 0.161438531 1
+4 0.000345224 17
+3 0.157323414 1
+4 0.000537486 18
+3 0.121528105 1
+4 0.000498558 17
+3 0.125526397 1
+4 0.000482108 19
+3 0.255732231 1
+3 0.121881198 1
+4 0.000345581 29
+3 0.213459919 1
+4 0.000395734 36
+3 0.161822173 1
+4 0.000357575 17
+3 0.157298340 1
+4 0.000412710 20
+3 0.178299484 1
+4 0.000327592 17
+3 0.237035658 1
+4 0.000416700 88
+3 0.631761843 1
+4 0.000402040 17
+3 0.151418917 1
+3 0.154220895 1
+4 0.000423284 70
+3 0.101389342 1
+4 0.000335849 17
+3 0.359970840 1
+4 0.000403114 64
+3 0.255375492 1
+4 0.000350430 17
+3 0.153935811 1
+4 0.000325999 17
+3 0.357694905 1
+4 0.000363787 18
+3 0.137455631 1
+4 0.000495269 17
+3 0.565508737 1
+3 0.047830147 1
+4 0.000532450 28
+3 0.351524429 1
+4 0.000467173 18
+3 0.071666434 1
+4 0.000641468 18
+3 0.167194718 1
+4 0.000489431 18
+3 0.200295616 1
+4 0.000551093 18
+3 0.224195045 1
+4 0.000490351 29
+3 0.942128105 2
+4 0.000420457 10
+3 0.159520647 1
+4 0.000340538 1
+3 0.191674682 1
+4 0.000341809 1
+3 0.162114470 1
+4 0.000403173 1
+4 0.000370828 71
+3 3.453730031 1
+4 0.000407152 36
+7 0.000532697 TSTP
+7 1.279692927 CONT
+4 0.000594321 7
+4 0.000338319 766
+3 20.543075366 1
+3 0.161678515 1
+4 0.000393388 89
+3 0.109518649 1
+4 0.000377129 77
+3 0.487449518 1
+4 0.000414332 10
+3 0.103420818 1
+4 0.000327642 1
+3 0.160021081 1
+4 0.000339209 1
+3 0.103534453 1
+4 0.000352986 1
+4 0.000362220 71
+3 11.872264722 1
+4 0.000426217 10
+3 0.143175518 1
+4 0.000337384 1
+3 0.143330589 1
+4 0.000347866 1
+3 0.095812134 1
+4 0.000395322 1
+4 0.000374560 71
+3 0.719728666 1
+4 0.000364309 36
+7 0.000545907 TSTP
+7 1.382542565 CONT
+4 0.000623723 7
+4 0.000296046 766
+3 9.311903448 1
+3 0.145546621 1
+4 0.000387557 79
+3 0.597650202 1
+4 0.000355720 10
+3 0.127432037 1
+4 0.000369744 1
+3 0.175848436 1
+4 0.000346841 1
+3 0.111455892 1
+4 0.000363654 1
+4 0.000784986 10
+4 0.000316427 61
+3 2.342798974 1
+4 0.000586526 81
+3 0.263320080 1
+4 0.000396667 17
+3 0.175857695 1
+4 0.000346577 18
+3 0.175300181 1
+4 0.000422884 18
+3 0.151615841 1
+4 0.000365608 5
+3 0.255672928 1
+4 0.000377346 20
+3 1.335841010 1
+4 0.000350921 10
+3 0.103478377 1
+4 0.000340388 1
+3 0.079799956 1
+4 0.000377597 1
+4 0.000340277 619
+3 0.088604932 1
+4 0.000347462 9
+3 0.110282970 1
+4 0.000362487 1
+3 0.112068737 1
+4 0.000335578 1
+3 0.137441147 1
+4 0.000356006 1
+3 0.021400111 1
+4 0.000315926 1
+3 0.343808846 1
+4 0.000695257 21
+4 0.000443236 818
+3 1.342789495 1
+4 0.000576959 740
+3 0.153934670 1
+4 0.000389186 5
+3 0.645080930 1
+4 0.000358932 10
+3 0.095733242 1
+4 0.000334965 1
+3 0.143733003 1
+4 0.000330461 1
+3 0.079904187 1
+4 0.000340350 1
+4 0.000651650 10
+4 0.000323088 61
+3 1.886982413 1
+4 0.000364249 36
+7 0.000518790 TSTP
+7 1.438859082 CONT
+4 0.000639886 7
+4 0.000308077 765
+3 19.960179842 1
+3 0.137318544 1
+4 0.000425193 89
+3 0.101456129 1
+4 0.000385837 78
+3 0.687735193 1
+4 0.000344463 10
+3 0.111760772 1
+4 0.000372205 1
+3 0.143536207 1
+4 0.000334583 1
+3 0.095671266 1
+4 0.000382623 1
+4 0.000308090 14
+4 0.000326265 57
+3 0.287477689 1
+4 0.000340497 36
+7 0.000549212 TSTP
+7 1.334882104 CONT
+4 0.000566744 7
+4 0.000445456 7
+4 0.000310448 758
+3 21.919165309 1
+4 0.000389164 17
+3 1.607860009 1
+3 0.145916570 1
+4 0.000550629 79
+3 40.887569204 1
+3 0.063226887 1
+4 0.000407176 28
+3 0.231577718 1
+4 0.000347207 18
+3 0.135826371 1
+4 0.000348097 18
+3 0.135755107 1
+4 0.000342546 18
+3 0.513437669 1
+4 0.000352245 17
+3 0.333870129 1
+4 0.000348692 17
+3 0.271457790 1
+4 0.000354921 17
+3 0.567782986 1
+4 0.000403925 17
+3 0.087387382 1
+4 0.000330600 18
+3 0.064692221 1
+4 0.000374641 41
+3 0.334386122 2
+4 0.000368782 36
+3 0.095813194 1
+4 0.000326974 17
+3 0.319688238 1
+4 0.000400214 4
+3 0.217758066 1
+4 0.000382550 6
+3 0.181472137 1
+4 0.000377069 4
+3 0.351749687 1
+4 0.000351451 17
+3 0.337577822 1
+4 0.000361249 18
+3 0.477870170 1
+4 0.000357175 17
+3 0.249462376 1
+4 0.000361629 17
+3 0.205554148 1
+4 0.000429511 17
+3 0.271772888 1
+4 0.000366700 4
+3 0.185663908 1
+4 0.000801799 4
+3 0.149332116 1
+4 0.000354948 4
+3 0.137604340 1
+4 0.000341941 4
+3 0.149596246 1
+4 0.000347968 7
+3 0.879575837 1
+4 0.000371385 6
+3 0.495575891 1
+4 0.000410648 7
+3 0.535996334 1
+4 0.000346507 17
+3 3.031472869 1
+4 0.000383621 10
+3 0.111534733 1
+4 0.000341148 1
+3 0.127793429 1
+4 0.000314986 1
+3 0.135521274 1
+4 0.000370481 1
+4 0.000315991 10
+4 0.000321545 61
+3 0.287211223 1
+4 0.000349261 36
+7 0.000625125 TSTP
+7 18.263683258 CONT
+4 0.000498815 7
+4 0.000274045 761
+3 1.023194790 1
+4 0.000373438 18
+3 0.143586996 1
+4 0.000363107 23
+3 0.295540816 1
+4 0.000393611 19
+3 0.455657673 2
+4 0.000426373 10
+3 0.113703338 1
+4 0.000378402 1
+3 0.157390675 1
+4 0.000357087 1
+3 0.151742623 1
+4 0.000372121 1
+4 0.000389981 71
+3 4.695812081 1
+4 0.000435116 47
+3 0.279470887 1
+4 0.000352451 20
+3 0.135503138 1
+4 0.000416970 17
+3 0.264941187 1
+4 0.000350779 17
+3 0.150132591 1
+4 0.000411483 4
+3 0.311846550 1
+4 0.000391644 8
+3 0.183614576 1
+4 0.000404638 17
+3 0.175683730 1
+4 0.000357988 7
+3 0.423533239 1
+4 0.000398142 10
+3 0.095915760 1
+4 0.000332763 1
+3 0.143141796 1
+4 0.000384253 1
+3 0.127668348 1
+4 0.000355276 1
+4 0.000376278 71
+3 2.375919235 1
+4 0.000378363 36
+7 0.000560572 TSTP
+7 15.551189540 CONT
+4 0.000539521 7
+4 0.000299553 760
+3 23.695858735 2
+4 0.000359908 18
+3 0.170196607 1
+4 0.000348039 17
+3 0.573067146 2
+4 0.000315257 18
+3 0.664401104 1
+3 0.105229177 1
+4 0.000345009 30
+3 0.221703840 1
+4 0.000407918 101
+3 0.527554619 1
+4 0.000353805 17
+3 0.135802397 1
+3 0.071781394 1
+4 0.000350908 29
+3 0.247749684 1
+4 0.000361118 18
+3 0.103453369 1
+4 0.000336479 18
+3 0.137722936 1
+4 0.000361246 18
+3 0.517919323 2
+4 0.000389552 40
+3 1.831522136 1
+4 0.000398435 17
+3 0.249614782 1
+4 0.000388303 18
+3 3.541891503 1
+4 0.000378322 17
+3 0.295458712 1
+4 0.000363984 17
+3 0.095756287 1
+4 0.000364362 18
+3 0.199627897 1
+3 0.055865953 1
+4 0.000355114 27
+3 0.223763732 1
+4 0.000376939 18
+3 0.064087461 1
+4 0.000346247 17
+3 0.145196165 1
+4 0.000374948 18
+3 0.077578841 1
+4 0.000345534 41
+3 0.703167850 1
+4 0.110020471 33
+3 0.538607790 1
+4 0.000410711 17
+3 0.161582846 1
+4 0.000363956 17
+3 0.141494482 1
+4 0.000353886 18
+3 0.169681414 1
+4 0.000383409 17
+3 0.421508228 1
+4 0.000358304 17
+3 0.568001575 1
+4 0.000413829 17
+3 0.209401778 1
+4 0.000350372 18
+3 2.102060980 1
+3 0.055601917 1
+4 0.000394102 4
+3 0.215605473 1
+3 0.064149899 1
+4 0.000341844 4
+3 0.215470952 1
+3 0.040040524 1
+4 0.000342404 4
+3 0.615762246 1
+3 0.032063265 1
+4 0.000365036 4
+3 0.247519203 1
+3 0.056030347 1
+4 0.000378459 4
+3 0.224142535 1
+3 0.031523638 1
+4 0.000358178 4
+3 0.423666972 1
+4 0.000376999 4
+3 0.255643217 1
+4 0.000343531 17
+3 4.856027841 1
+4 0.000500863 18
+3 0.193366280 1
+4 0.000389063 17
+3 0.165522421 1
+4 0.000344857 17
+3 0.473753484 1
+4 0.000400177 17
+3 0.437554096 1
+4 0.000359468 18
+3 1.607761052 1
+4 0.000366734 33
+3 0.151682280 1
+4 0.000346026 18
+3 0.407553246 2
+4 0.000364683 13
+3 0.127618024 1
+4 0.000319068 1
+3 0.143660206 1
+4 0.000364479 1
+3 0.143742384 1
+4 0.000406650 1
+4 0.000367797 71
+3 0.351557499 1
+4 0.000402956 36
+7 0.000565724 TSTP
+7 2.191516357 CONT
+4 0.000601223 7
+4 0.000313328 736
+3 0.486301431 1
+4 0.000401910 27
+3 0.719571416 1
+4 0.000386112 38
+3 0.369728756 1
+4 0.000378489 21
+3 0.349666198 1
+4 0.000466278 22
+3 0.361397835 1
+4 0.000376363 25
+3 0.381641787 1
+4 0.000422633 26
+3 0.386758659 1
+4 0.000357995 29
+3 0.556543071 1
+4 0.000385322 30
+3 0.543559098 1
+4 0.000354657 4
+3 0.191664837 1
+4 0.000384254 4
+3 0.153687121 1
+4 0.000395274 4
+3 0.133534453 1
+4 0.000396348 4
+3 0.121659912 1
+4 0.000413405 4
+3 0.125573096 1
+4 0.000387566 4
+3 0.139150330 1
+4 0.000327305 4
+3 0.148154366 1
+4 0.000372650 32
+3 0.249863620 1
+4 0.000339958 1
+3 0.637929725 1
+4 0.000396127 10
+3 0.111347453 1
+4 0.000349649 1
+3 0.239519890 1
+4 0.000376892 1
+4 0.000894005 10
+4 0.000362047 61
+3 0.718355866 1
+4 0.000378376 36
+7 0.000534690 TSTP
+7 5.191647462 CONT
+4 0.000706786 7
+4 0.000362129 736
+3 0.686656947 1
+4 0.000446177 27
+3 0.295649306 1
+4 0.000566542 38
+3 0.409198821 1
+4 0.000441251 21
+3 0.621630445 1
+4 0.000366152 22
+3 0.305683015 1
+4 0.000432894 25
+3 0.309555663 1
+4 0.000358268 26
+3 0.361574083 1
+4 0.000411224 29
+3 0.381625199 1
+4 0.000357855 30
+3 0.961682942 1
+4 0.000419125 33
+3 0.669684753 1
+4 0.000434909 44
+3 0.655678777 1
+4 0.000427507 17
+3 20.106525371 1
+3 0.045647273 1
+4 0.000365446 18
+3 0.186268181 1
+4 0.000372156 17
+3 0.132866873 1
+4 0.000376959 17
+3 0.185773537 1
+4 0.000351543 18
+3 0.221453445 1
+4 0.000393827 31
+3 0.184683590 1
+4 0.000337990 20
+3 0.651084582 1
+3 0.091972978 1
+4 0.000436889 34
+3 0.247353084 1
+4 0.000389987 17
+3 0.087558484 1
+4 0.000370313 18
+3 0.159730348 1
+4 0.000342223 24
+3 0.223550409 1
+4 0.000404235 45
+3 0.279483799 2
+4 0.000368998 36
+3 0.207881506 1
+4 0.000385223 17
+3 0.217550024 1
+4 0.000377422 18
+3 0.293652368 1
+4 0.000374239 17
+3 0.231611804 1
+4 0.000354648 24
+3 0.255771372 1
+4 0.000396653 19
+3 0.709843468 1
+4 0.109945476 33
+3 2.772403375 1
+4 0.000405016 10
+3 0.159034249 1
+4 0.000343155 1
+3 0.175485925 1
+4 0.000390619 1
+3 0.127848732 1
+4 0.000380434 1
+4 0.000358212 71
+3 0.751855132 1
+4 0.000404622 36
+7 0.000608357 TSTP
+7 2.502601867 CONT
+4 0.000660954 7
+4 0.000292705 761
+3 42.344294221 2
+4 0.000346361 21
+3 0.232300274 1
+4 0.000397957 17
+3 0.110977267 1
+4 0.000347456 18
+3 0.191542148 1
+4 0.000421802 23
+3 0.191648097 1
+4 0.000390839 31
+3 0.423642384 2
+4 0.000417125 10
+3 0.095563652 1
+4 0.000328914 1
+3 0.162289389 1
+4 0.000386050 1
+3 0.132960135 1
+4 0.000421188 1
+4 0.000357036 71
+3 2.528509506 1
+4 0.000374574 36
+7 0.000558417 TSTP
+7 1.326200172 CONT
+4 0.000651198 7
+4 0.000368984 7
+4 0.000333315 755
+3 10.759500663 1
+4 0.000424380 21
+3 0.366812536 1
+4 0.000354543 18
+3 0.127689176 1
+4 0.000369158 17
+3 0.175591974 1
+3 0.048660960 1
+4 0.000359942 26
+3 0.087772999 1
+4 0.000337647 17
+3 0.110972447 1
+4 0.000331622 18
+3 0.129662149 1
+4 0.000359074 21
+3 0.341590744 2
+4 0.000418281 10
+3 0.175657585 1
+4 0.000350980 1
+3 0.119880120 1
+4 0.000393669 1
+3 0.143461878 1
+4 0.000387547 1
+4 0.000367203 10
+4 0.000313262 61
+3 1.423356906 1
+4 0.000369190 36
+7 0.000544947 TSTP
+7 1.086855932 CONT
+4 0.000600841 7
+4 0.000259936 762
+3 29.456688546 1
+4 0.000382210 17
+3 0.166860376 1
+3 0.072853854 1
+4 0.000486510 26
+3 0.094686413 1
+4 0.000397296 17
+3 0.055880947 1
+4 0.000550370 18
+3 0.359221233 2
+4 0.000388415 14
+3 0.111920171 1
+4 0.000344960 1
+3 0.119262715 1
+4 0.000351551 1
+3 0.135698555 1
+4 0.000358834 1
+4 0.000370376 71
+3 7.200064723 1
+4 0.000396296 39
+3 0.201124997 1
+4 0.000353353 17
+3 12.583077072 1
+4 0.000405715 36
+7 0.000556650 TSTP
+7 2.166256425 CONT
+4 0.000595403 7
+4 0.000284965 701
+3 34.464618235 1
+3 0.137495155 1
+4 0.000393855 89
+3 6.333858500 1
+4 0.000421474 17
+3 0.247499316 1
+4 0.000344421 17
+3 0.201481700 1
+4 0.000396558 17
+3 0.165632278 1
+4 0.000384607 19
+3 0.287697103 1
+4 0.000394441 20
+3 0.185936115 1
+4 0.000389601 17
+3 0.197247752 1
+4 0.000421181 17
+3 10.256287285 1
+4 0.000401831 17
+3 0.463252389 1
+4 0.000411884 24
+3 0.919761790 1
+4 0.000376261 27
+3 0.599663943 1
+4 0.000430115 28
+3 1.727519207 1
+4 0.000366528 27
+3 0.775678123 2
+4 0.000446678 33
+3 0.127615264 1
+4 0.000336915 17
+3 0.169691032 1
+4 0.000404518 17
+3 14.214084103 2
+4 0.000406930 31
+3 1.064172346 1
+4 0.000446106 82
+3 0.462979744 1
+4 0.000425667 80
+3 0.455412593 1
+4 0.000399671 17
+3 1.015850622 1
+3 0.200009465 1
+3 0.121842965 1
+4 0.000413815 31
+3 0.197469351 1
+4 0.000429019 144
+3 0.313156262 1
+4 0.000562658 43
+3 0.168267990 1
+4 0.000376310 17
+3 0.149529087 1
+4 0.000561536 18
+3 0.161330526 1
+4 0.000487524 17
+3 0.333469617 1
+4 0.000432119 7
+3 2.407756190 1
+4 0.000399637 18
+3 0.185510385 1
+4 0.000403515 17
+3 0.397545429 1
+4 0.000349287 24
+3 0.455775587 1
+4 0.000382010 26
+3 0.119660765 1
+4 0.000344743 27
+3 0.983754654 1
+4 0.000391754 26
+3 0.367444466 2
+4 0.000479735 24
+3 0.153584990 1
+4 0.000518767 17
+3 0.333432343 1
+4 0.000451263 31
+3 0.951762306 1
+4 0.000390342 20
+3 0.799717393 1
+4 0.110050651 31
+3 6.394224606 1
+4 0.000399427 17
+3 0.201242861 1
+4 0.000362093 17
+3 0.805831872 1
+4 0.000492597 24
+3 0.463611154 1
+4 0.000353344 28
+3 0.495490410 2
+4 0.000435363 33
+3 0.153574646 1
+4 0.000344398 17
+3 0.205530768 1
+4 0.000359665 17
+3 0.368002084 1
+4 0.000369806 31
+3 5.543652529 1
+4 0.000405256 21
+3 2.319551608 2
+4 0.000402605 31
+3 0.127672928 1
+4 0.000396047 16
+3 0.145521021 1
+4 0.000370101 18
+3 0.198850123 1
+4 0.000380497 18
+3 0.374518191 1
+4 0.000376497 4
+3 0.071763335 1
+4 0.000357445 29
+3 1.991623930 1
+4 0.000360230 17
+3 0.153682265 1
+4 0.000355502 17
+3 0.141566970 1
+4 0.000343818 17
+3 0.319546316 1
+4 0.000381425 32
+3 0.415753148 1
+4 0.000376296 20
+3 0.111609906 1
+4 0.000376038 20
+3 0.111683841 1
+4 0.000339838 20
+3 0.223663238 1
+4 0.000345139 20
+3 1.735836126 1
+4 0.000383634 20
+3 1.431546931 1
+4 0.000376084 20
+3 0.471593841 1
+4 0.000359976 38
+4 0.703414565 18
+3 0.529968458 1
+4 0.110004687 31
+3 0.344443632 1
+4 0.000377377 17
+3 0.161592431 1
+4 0.000373603 20
+3 0.149541334 1
+4 0.000376216 19
+3 0.169770415 1
+4 0.000380554 21
+3 0.237617326 1
+4 0.000353075 17
+3 0.271492043 1
+4 0.000393653 23
+3 0.847577958 1
+4 0.000355919 17
+3 0.215824561 2
+4 0.000420253 34
+3 0.159446820 1
+4 0.000385845 55
+3 0.119529700 1
+4 0.000443729 18
+3 0.143622153 1
+4 0.000371709 55
+3 0.087744678 1
+4 0.000432932 18
+3 0.135547822 1
+4 0.000387780 55
+3 0.367740510 1
+4 0.000403129 8
+3 0.119486192 1
+4 0.000352406 1
+3 0.159480106 1
+4 0.000381349 1
+3 0.095840317 1
+4 0.000406279 1
+4 0.000347860 68
+3 0.296854807 1
+4 0.000333832 34
+7 0.000530929 TSTP
+7 18.711040311 CONT
+4 0.000722739 7
+4 0.000294419 720
+3 1.878490908 1
+4 0.000385552 14
+3 0.499457577 1
+4 0.000364101 14
+3 0.083000133 1
+4 0.000374483 14
+3 0.083512020 1
+4 0.000330702 19
+3 0.082876543 1
+4 0.000450885 16
+3 0.082872661 1
+4 0.000348207 16
+3 0.455801267 1
+4 0.000408033 16
+3 22.718850312 1
+4 0.000367782 16
+3 0.499319128 1
+4 0.000440603 18
+3 0.083031219 1
+4 0.000339332 18
+3 5.992261219 1
+4 0.000404772 17
+3 1.015513604 1
+4 0.000428246 21
+3 0.343708648 1
+4 0.000407440 17
+3 0.499501973 1
+4 0.000404036 17
+3 0.082759959 1
+4 0.000405669 17
+3 0.082706521 1
+4 0.000350717 17
+3 0.082937503 1
+4 0.000415135 17
+3 0.204004487 1
+4 0.000358586 17
+3 2.061676979 1
+3 0.178034321 1
+4 0.000458403 41
+3 0.157662119 1
+3 0.162192601 1
+4 0.000462507 71
+3 0.173246535 1
+3 0.153994123 1
+4 0.000444605 119
+3 0.173440035 1
+3 0.122042974 1
+4 0.000383053 77
+3 0.357731675 1
+4 0.000408902 18
+3 0.735691322 1
+4 0.000400895 16
+3 0.367560977 1
+4 0.000392665 24
+3 0.143760259 1
+4 0.000398216 16
+3 0.367347853 1
+4 0.000417748 15
+3 0.119692664 1
+4 0.000357595 28
+3 0.175609639 1
+4 0.000389132 16
+3 0.215606599 1
+4 0.000346514 15
+3 0.079667984 1
+4 0.000454884 28
+3 0.175582670 1
+4 0.000358310 16
+3 0.239689561 1
+4 0.000413015 15
+3 0.079470073 1
+4 0.000357373 24
+3 0.391674008 1
+4 0.000382927 16
+3 0.153648702 1
+4 0.000342793 16
+3 0.149695017 1
+4 0.000398179 16
+3 0.119534529 1
+4 0.000382745 18
+3 0.207754094 1
+4 0.000381072 17
+3 0.185524250 1
+4 0.000387534 17
+3 0.117594633 1
+4 0.000385616 7
+3 0.527773376 1
+4 0.000363479 10
+3 0.143658968 1
+4 0.000374950 1
+3 0.151534283 1
+4 0.000338832 1
+3 0.247642362 1
+4 0.000414888 1
+4 0.000623078 10
+4 0.000327615 61
+3 0.679143212 1
+4 0.000428228 36
+7 0.000498302 TSTP
+7 15.759302739 CONT
+4 0.000709658 7
+4 0.000259898 761
+3 1.447011203 1
+4 0.000422073 52
+3 0.111465797 1
+4 0.000378643 17
+3 0.112301851 1
+4 0.000341490 16
+3 0.599047398 1
+4 0.000373061 16
+3 0.137569975 1
+4 0.000351584 15
+3 0.133686062 1
+4 0.000363926 19
+3 0.455652573 1
+4 0.000404204 19
+3 0.095485987 1
+4 0.000330733 17
+3 3.896053197 1
+4 0.000419108 18
+3 0.103484157 1
+4 0.000355073 18
+3 0.103427073 1
+4 0.000339638 18
+3 0.088569795 1
+4 0.000347190 18
+3 0.054934884 1
+4 0.000344192 17
+3 0.071779814 1
+4 0.000390972 18
+3 0.103236039 1
+4 0.000394154 18
+3 0.079809854 1
+4 0.000388847 18
+3 0.207558980 1
+4 0.000358322 19
+3 0.119757145 1
+4 0.000373061 18
+3 0.079697457 1
+4 0.000366006 18
+3 0.207569155 1
+4 0.000635030 18
+3 0.263316887 1
+4 0.000556093 18
+3 0.183554241 1
+4 0.000414673 18
+3 0.095605329 1
+4 0.000367209 18
+3 0.088897668 1
+4 0.000400849 18
+3 0.023143466 1
+4 0.000358736 18
+3 0.086779107 1
+4 0.000390339 17
+3 0.079564663 1
+4 0.000339080 19
+3 0.119593603 1
+4 0.000432584 18
+3 0.095575470 1
+4 0.000338328 18
+3 0.015961962 1
+4 0.000398069 18
+3 0.151235025 1
+4 0.000341615 18
+3 0.263735292 2
+4 0.000416151 36
+3 0.344262441 1
+4 0.000347914 17
+3 0.162363392 1
+4 0.000380379 17
+3 0.188195394 1
+4 0.000401011 7
+3 0.175818950 1
+4 0.000394224 17
+3 0.537388667 1
+4 0.000378779 17
+3 1.661891035 1
+4 0.000410197 10
+3 0.089165673 1
+4 0.000321823 1
+3 0.149978075 1
+4 0.000387317 1
+3 0.095732547 1
+4 0.000376913 1
+4 0.000309348 54
+4 0.000366179 17
+3 1.463359603 1
+4 0.000359983 36
+7 0.000588293 TSTP
+7 1.494986237 CONT
+4 0.000710772 7
+4 0.000476110 755
+3 0.815254487 1
+4 0.000413124 36
+7 0.000500056 TSTP
+7 5.470841894 CONT
+4 0.000537987 7
+4 0.000309014 695
+3 1.103014779 1
+4 0.000479227 10
+3 0.255480340 1
+4 0.000377261 1
+3 0.095464134 1
+4 0.000369958 1
+3 0.239785146 1
+4 0.000349997 1
+3 0.111606627 1
+4 0.000387143 1
+3 0.095592443 1
+4 0.000362436 1
+3 0.209546330 1
+4 0.000383199 1
+3 0.069908389 1
+4 0.000388572 13
+4 0.000356399 40
+3 0.391033583 1
+4 0.000463571 22
+4 0.000339472 36
+3 22.904792991 1
+4 0.000415262 10
+3 0.142951874 1
+4 0.000403144 1
+3 0.128583126 1
+4 0.000412641 1
+3 0.166690878 1
+4 0.000689289 739
+3 2.624041365 1
+4 0.000400916 9
+3 0.174887138 1
+4 0.000384252 1
+3 0.119405108 1
+4 0.000372425 1
+3 0.167720375 1
+4 0.000332687 1
+4 0.000349403 35
+3 0.423713292 1
+4 0.000375338 35
+7 0.000583271 TSTP
+7 70.969129284 CONT
+4 0.000697139 7
+4 0.000259336 690
+3 0.222944020 1
+4 0.000347798 9
+3 0.111816210 1
+4 0.000335574 1
+3 0.103568627 1
+4 0.000378947 1
+3 0.135595030 1
+4 0.000396827 1
+3 0.137532828 1
+4 0.000358634 1
+3 0.117757171 1
+4 0.000375277 1
+3 0.055587721 1
+4 0.000394197 1
+3 0.191608522 1
+4 0.000361412 1
+3 0.199704361 1
+4 0.000402536 1
+3 0.207616763 1
+4 0.000411565 25
+4 0.000397031 586
+3 0.631256050 1
+4 0.000424291 33
+4 0.000316004 581
+3 0.521136839 1
+4 0.000435811 57
+4 0.000341314 400
+3 0.813835754 1
+4 0.000377370 34
+4 0.000433569 581
+3 0.352584941 1
+4 0.000397390 57
+4 0.000363548 400
+3 0.733347389 1
+4 0.000405165 10
+3 0.167473344 1
+4 0.000351018 1
+3 0.079771169 1
+4 0.000353889 1
+4 0.000318311 603
+3 0.103143305 1
+4 0.000341409 9
+3 0.087795642 1
+4 0.000383953 18
+4 0.000367685 594
+3 2.327546392 1
+4 0.000646503 717
+3 0.519264719 1
+4 0.000577177 820
+3 0.487328825 1
+4 0.000621281 777
+3 0.255472449 1
+4 0.000560288 838
+3 0.431395389 1
+4 0.000543030 491
+3 1.815692773 1
+4 0.000376360 36
+7 0.000559203 TSTP
+7 36.256087000 CONT
+4 0.000670313 7
+4 0.000314670 514
+3 1.007150321 1
+4 0.000371526 10
+3 0.111658445 1
+4 0.000365925 1
+3 0.127497532 1
+4 0.000344023 1
+3 0.008585145 1
+4 0.000359333 1
+3 0.062918881 1
+4 0.000337433 1
+3 0.520163861 1
+4 0.000437412 2
+3 0.294795978 1
+4 0.000381118 1
+3 0.071692988 1
+4 0.000376974 1
+3 0.143539792 1
+4 0.000323794 1
+3 0.183757372 1
+4 0.000393274 1
+3 0.063755161 1
+4 0.000544230 660
+3 0.639400190 1
+4 0.000381233 17
+3 0.185646026 1
+4 0.000387918 17
+3 0.165576131 1
+4 0.000370784 17
+3 0.169594206 1
+4 0.000346486 20
+3 0.165630517 1
+4 0.000379258 16
+3 0.247663006 1
+4 0.000384711 18
+3 0.153654800 1
+4 0.000384127 21
+3 0.133594381 1
+4 0.000358222 17
+3 0.153676469 1
+4 0.000411504 17
+3 0.143149979 1
+4 0.000355384 17
+3 0.702200221 1
+3 0.144007022 1
+3 0.129890903 1
+4 0.000355329 31
+3 0.797783059 1
+4 0.000398510 39
+3 0.615529280 1
+4 0.000363986 10
+3 0.095683598 1
+4 0.000325788 1
+3 0.103551436 1
+4 0.000383441 1
+3 0.119607986 1
+4 0.000347694 1
+3 0.145819004 1
+4 0.000319052 1
+3 0.125546782 1
+4 0.000367240 1
+3 0.039546567 1
+4 0.000326530 1
+3 0.183922235 1
+4 0.000373559 21
+4 0.000353866 702
+3 2.087798526 1
+4 0.000539051 571
+3 0.487204393 1
+4 0.000612492 688
+3 0.567301355 1
+4 0.000529935 569
+3 0.183352643 1
+4 0.000572020 259
+3 1.895653835 1
+4 0.000559693 676
+3 0.183349956 1
+4 0.000627051 788
+3 0.311439753 1
+4 0.000520169 684
+3 0.223235251 1
+4 0.000556696 706
+3 1.855807818 1
+4 0.000623383 754
+3 0.399430211 1
+4 0.000666082 755
+3 0.678992219 1
+4 0.000407642 9
+3 0.071844278 1
+4 0.000408252 39
+3 2.271730493 1
+4 0.000695074 754
+3 0.951239040 1
+4 0.000655239 755
+3 0.199279212 1
+4 0.000524359 568
+3 0.351523060 1
+4 0.000597140 688
+3 0.375552882 1
+4 0.000572100 882
+3 0.335236477 1
+4 0.000595587 797
+3 0.335527330 1
+4 0.000590118 858
+3 0.335478957 1
+4 0.000645679 720
+3 0.335412572 1
+4 0.000564452 692
+3 0.447292502 1
+4 0.000617332 631
+3 0.439511370 1
+4 0.000599395 551
+3 1.255467302 1
+4 0.000612853 695
+3 0.975312065 1
+4 0.000556515 535
+3 0.849295704 1
+4 0.000409538 21
+4 0.000423212 591
+3 0.821288316 1
+4 0.000544036 588
+3 0.503545779 1
+4 0.000591477 688
+3 0.759494154 1
+4 0.000630742 882
+3 0.383301604 1
+4 0.000361161 32
+4 0.000355504 586
+3 0.425292376 1
+4 0.000427732 57
+4 0.000374856 555
+3 0.213333573 1
+4 0.000533322 588
+3 0.440372326 1
+4 0.000558654 688
+3 0.478209058 1
+4 0.000375810 9
+3 0.135845091 1
+4 0.000342553 1
+3 0.055731981 1
+4 0.000322099 1
+4 0.000333614 606
+3 0.095106089 1
+4 0.000343483 9
+3 0.511910900 1
+4 0.000395045 18
+4 0.000423280 594
+3 0.551397717 1
+4 0.000373563 62
+3 0.831401151 1
+4 0.000373044 33
+4 0.000436827 581
+3 0.359415188 1
+4 0.000369864 62
+3 1.559405239 1
+4 0.000385266 21
+4 0.000454423 436
+3 0.720007528 1
+4 0.000685988 734
+3 0.422694195 1
+4 0.000616489 820
+3 0.319316852 1
+4 0.000618298 761
+3 1.575514606 1
+4 0.000601742 540
+3 0.191314674 1
+4 0.000505078 21
+3 2.239427678 1
+4 0.000379643 17
+3 0.489926311 1
+4 0.000480378 18
+3 0.261299017 1
+4 0.000443556 156
+3 0.727585489 1
+4 0.000403010 43
+3 0.279611069 1
+3 0.079889305 1
+4 0.000401246 28
+3 0.239587313 1
+4 0.000397168 18
+3 0.072427298 1
+4 0.000333939 18
+3 0.342923416 1
+4 0.000398306 18
+3 0.183637399 1
+4 0.000381758 18
+3 0.111595657 1
+4 0.000361019 37
+3 0.063655434 1
+4 0.000399939 37
+3 0.503644352 2
+4 0.000390806 36
+3 0.161502231 1
+4 0.000365327 17
+3 0.141749408 1
+4 0.000369984 17
+3 0.185648138 1
+4 0.000356033 18
+3 0.165731462 1
+4 0.000352816 17
+3 0.161555741 1
+4 0.000359941 17
+3 0.149736702 1
+4 0.000425806 17
+3 0.113442477 1
+4 0.000355350 17
+3 0.149749419 1
+4 0.000381168 18
+3 0.201596848 1
+4 0.000367273 17
+3 0.213610750 1
+4 0.000357214 17
+3 0.233632365 1
+4 0.000352405 17
+3 0.237703831 1
+3 0.080015656 1
+4 0.000390973 28
+3 0.127528045 1
+4 0.000376775 18
+3 0.079637141 1
+4 0.000351734 18
+3 0.311727166 1
+4 0.000398259 18
+3 0.167561704 1
+4 0.000358484 19
+3 0.103706101 1
+4 0.000403651 20
+3 0.047631111 1
+4 0.000352065 20
+3 0.615677935 2
+4 0.000405081 10
+3 0.112025215 1
+4 0.000345942 1
+3 0.119151839 1
+4 0.000395602 1
+4 0.000393444 71
+3 7.400109465 1
+4 0.000377879 10
+3 0.182947979 1
+4 0.000348115 1
+3 0.063744236 1
+4 0.000406283 1
+4 0.000387358 71
+3 0.535224823 1
+4 0.000495439 39
+3 1.033667865 1
+4 0.000395791 32
+4 0.000389749 580
+3 2.085715205 1
+4 0.000595160 571
+3 1.063184152 1
+4 0.000601361 688
+3 4.184426491 1
+4 0.000611529 882
+3 198.294712987 1
+4 0.000500980 9
+3 0.189589980 1
+4 0.000719043 1
+3 0.119318988 1
+4 0.000564771 1
+3 0.151441953 1
+4 0.000358560 1
+3 0.137706675 1
+4 0.000460100 1
+3 0.149441070 1
+4 0.000384899 1
+3 0.071650668 1
+4 0.000445636 1
+3 0.191711996 1
+4 0.000613876 706
+3 1.015888491 1
+4 0.000617595 571
+3 0.438878102 1
+4 0.000577367 688
+3 0.447478114 1
+4 0.000689566 882
+3 0.359286096 1
+4 0.000640649 797
+3 0.335430267 1
+4 0.000677678 858
+3 0.472182198 1
+4 0.000627037 720
+3 0.366435323 1
+4 0.001010110 692
+3 4.511252143 1
+4 0.000650383 695
+3 0.255194042 1
+4 0.000405046 27
+4 0.000383570 722
+3 32.216371870 1
+4 0.000375360 10
+3 0.359619347 1
+4 0.000373969 1
+3 0.015453064 1
+4 0.000338365 1
+3 0.135960195 1
+4 0.000425283 1
+3 0.327618492 1
+4 0.000378966 1
+3 0.137620317 1
+4 0.000466152 1
+3 0.061246195 1
+4 0.000375182 1
+3 0.183740916 1
+4 0.000390135 1
+3 0.087550652 1
+4 0.000351053 1
+3 0.239890261 1
+4 0.000688894 800
+3 0.799211665 1
+4 0.000379792 20
+3 0.337657412 1
+4 0.000425576 20
+3 0.613410916 1
+4 0.000437220 9
+3 0.231802960 1
+4 0.000363706 1
+3 0.095550999 1
+4 0.000355948 1
+3 0.311690991 1
+4 0.000360403 1
+3 0.119493793 1
+4 0.000381406 1
+3 0.145015673 1
+4 0.000614387 1
+3 0.062048669 1
+4 0.000369418 1
+3 0.191858922 1
+4 0.000451365 46
+4 0.000332511 12
+3 0.783070466 1
+4 0.000399820 9
+3 0.231602050 1
+4 0.000506878 1
+3 0.079371339 1
+4 0.000374732 1
+3 0.143672519 1
+4 0.000357272 1
+3 0.063707147 1
+4 0.000360474 1
+3 0.199859218 1
+4 0.000407986 39
+3 0.463330673 1
+4 0.000427909 41
+4 0.000329585 727
+3 4.048292042 1
+4 0.000659682 987
+3 1.046745489 1
+4 0.000708998 1031
+3 0.623413444 1
+4 0.000606119 737
+3 1.391046737 1
+4 0.000385105 10
+3 0.103821049 1
+4 0.000344610 1
+3 0.151389382 1
+4 0.000492370 1
+3 0.135684531 1
+4 0.000350529 1
+3 0.167734456 1
+4 0.000379684 1
+3 0.063573356 1
+4 0.000336023 1
+3 0.063502987 1
+4 0.000363503 1
+3 0.223733380 1
+4 0.000655733 700
+3 25.104799626 1
+4 0.000399281 10
+3 0.159008041 1
+4 0.000402494 1
+3 0.159700848 1
+4 0.000402276 1
+3 0.063353917 1
+4 0.000404021 1
+3 0.215798492 1
+4 0.000405804 1
+3 0.119647512 1
+4 0.000477310 191
+3 0.871404448 1
+4 0.000469989 63
+3 0.663591548 1
+4 0.000421793 71
+3 0.499801607 1
+4 0.000527248 58
+3 0.083029044 1
+4 0.000401822 47
+3 0.083244748 1
+4 0.000470973 34
+3 38.037421477 1
+4 0.000348897 8
+3 0.079604312 1
+4 0.000382227 1
+3 0.159674301 1
+4 0.000343747 1
+3 0.088281992 1
+4 0.000366830 1
+3 0.087830069 1
+4 0.000359714 1
+3 0.150800262 1
+4 0.000394596 1
+3 0.167596087 1
+4 0.000375193 1
+3 0.191569013 1
+4 0.000356516 1
+3 0.247780823 1
+4 0.000422578 24
+4 0.000446540 801
+3 1.551406059 1
+4 0.000405220 57
+4 0.000399134 749
+3 1.166934863 1
+4 0.000381655 10
+3 0.087671380 1
+4 0.000582668 41
+4 0.000415955 771
+3 6.511197329 1
+4 0.000613896 34
+4 0.000290759 791
+3 17.855985952 1
+4 0.000392818 17
+3 0.569405413 1
+4 0.000358391 17
+3 0.497800637 1
+4 0.000387651 17
+3 0.083195865 1
+4 0.000355967 17
+3 0.083425185 1
+4 0.000856532 18
+3 1.547546742 1
+4 0.000503055 23
+3 0.183568509 1
+4 0.000385734 23
+3 0.071482783 1
+4 0.000413536 19
+3 0.119783893 1
+4 0.000374924 20
+3 0.175621531 1
+4 0.000688902 19
+3 0.111129585 1
+4 0.000543899 19
+3 0.007492305 1
+4 0.000320451 19
+3 0.328076834 1
+4 0.000603112 17
+3 0.161056013 1
+4 0.000377849 17
+3 0.141748645 1
+4 0.000437131 18
+3 0.239569515 1
+4 0.000391192 18
+3 0.175630219 1
+4 0.000559085 19
+3 0.095322294 1
+4 0.000536504 19
+3 0.111530509 1
+4 0.000359670 19
+3 0.055675989 1
+4 0.000385189 19
+3 0.247503945 1
+4 0.000392250 19
+3 0.103561293 1
+4 0.000360224 19
+3 0.127872954 1
+4 0.000366021 20
+3 0.511480153 2
+4 0.000401829 10
+3 0.103750841 1
+4 0.000506651 1
+3 0.143407021 1
+4 0.000400126 1
+3 0.095528275 1
+4 0.000406794 1
+4 0.000373737 71
+3 0.287782083 1
+4 0.000341659 36
+7 0.000558827 TSTP
+7 25.999831488 CONT
+4 0.000523441 7
+4 0.000236712 754
+3 3.303725066 1
+4 0.000699688 639
+3 0.558943365 1
+4 0.000358426 9
+3 0.375464515 1
+4 0.000728486 1
+3 0.007507401 1
+4 0.000316351 1
+3 0.055107562 1
+4 0.000363764 1
+3 0.415905885 1
+4 0.000376008 1
+3 0.147347883 1
+4 0.000412975 1
+3 0.163923920 1
+4 0.000377046 1
+3 18.472815831 1
+4 0.000455734 1
+3 0.303014397 1
+4 0.000357172 1
+3 0.224750112 1
+4 0.000406001 1
+3 0.136844895 1
+4 0.000346398 1
+3 0.109232604 1
+4 0.000427810 1
+3 0.392148315 1
+4 0.000344556 2
+3 0.263814421 1
+4 0.000428066 1
+3 0.166663903 1
+4 0.000342941 1
+3 0.137990258 1
+4 0.001053470 1
+3 0.100790618 1
+4 0.000343833 1
+3 0.207661471 1
+4 0.000377886 40
+3 0.473599768 1
+4 0.000391002 32
+4 0.000360855 705
+3 1.261382162 1
+4 0.000364648 10
+3 0.087533109 1
+4 0.000377866 18
+4 0.000361082 674
+3 11.896125981 1
+4 0.001620248 10
+3 0.101985297 1
+4 0.000430458 18
+4 0.000294990 689
+3 184.533873636 1
+4 0.000421301 10
+3 0.599060170 1
+4 0.000463651 1
+3 0.087494112 1
+4 0.000321414 1
+3 0.256043716 1
+4 0.000326971 1
+3 0.047318053 1
+4 0.000334214 1
+3 0.095759799 1
+4 0.000512111 1
+3 0.239470833 1
+4 0.000347820 1
+3 0.191631063 1
+4 0.000347219 1
+3 0.119784608 1
+4 0.000438453 41
+4 0.000335714 585
+3 106.586128074 1
+4 0.000418614 39
+3 1.752608685 1
+4 0.000380543 20
+3 0.197628987 1
+4 0.000427663 19
+3 0.153554957 1
+4 0.000366344 20
+3 0.725566286 1
+4 0.000597954 19
+3 0.201493802 1
+4 0.000352051 20
+3 0.149624969 1
+4 0.000355754 20
+3 0.304030193 1
+3 0.122005589 1
+4 0.000429672 30
+3 0.253251625 1
+4 0.000383425 100
+3 0.279685150 1
+4 0.000355705 18
+3 1.263760746 2
+4 0.000459528 73
+3 0.624090280 1
+4 0.000353236 17
+3 0.318943178 1
+4 0.000359400 23
+3 0.959672316 1
+4 0.000342497 18
+3 0.231808080 2
+4 0.000363647 34
+3 0.159515378 1
+4 0.000358754 56
+3 0.087619052 1
+4 0.000318953 18
+3 0.151754660 1
+4 0.000323220 55
+3 0.207648573 1
+4 0.000323762 15
+3 0.169611195 1
+4 0.000337631 15
+3 0.101863938 1
+4 0.000344067 18
+3 0.247531118 1
+3 0.311838031 2
+4 0.000341970 16
+3 0.207759216 1
+3 0.146055428 1
+4 0.000332071 29
+3 0.477715855 2
+4 0.000389217 1
+3 0.168124794 1
+3 0.130429375 1
+4 0.000514504 26
+3 0.172489164 1
+4 0.000548759 158
+3 0.431574679 1
+4 0.000379927 49
+3 0.127541264 1
+4 0.000340955 16
+3 0.431668893 1
+4 0.000460327 15
+3 0.127600772 1
+4 0.000499579 28
+3 0.127808975 1
+4 0.000355777 16
+3 0.199339957 1
+4 0.000432400 14
+3 0.095445357 1
+4 0.000358959 24
+3 0.143812536 1
+4 0.000343400 16
+3 0.169745514 1
+4 0.000382521 16
+3 0.109556607 1
+4 0.000352115 16
+3 0.177670917 1
+4 0.000384687 18
+3 0.149600436 1
+4 0.000343239 18
+3 0.247641731 1
+4 0.000340803 18
+3 0.185516724 1
+4 0.000495872 17
+3 0.205772317 1
+4 0.000346917 4
+3 0.217825586 1
+4 0.000364003 6
+3 0.213423459 1
+4 0.000365457 4
+3 0.319585038 1
+4 0.000363926 17
+3 0.743639537 1
+3 0.080133792 1
+4 0.000416927 4
+3 0.167620249 1
+3 0.063765726 1
+4 0.000355550 4
+3 0.215720694 1
+3 0.048014069 1
+4 0.000424490 4
+3 0.367576945 1
+4 0.000384582 4
+3 0.500931653 1
+4 0.000368133 4
+3 0.082891603 1
+4 0.000385176 4
+3 0.083267710 1
+4 0.000363598 4
+3 0.083295317 1
+4 0.000413402 4
+3 0.082848953 1
+4 0.000331234 4
+3 0.083350265 1
+4 0.000547179 4
+3 0.082820949 1
+4 0.000361568 4
+3 0.083960695 1
+4 0.000599924 7
+3 1.097009841 1
+4 0.000362618 17
+3 4.935746168 1
+4 0.000391970 18
+3 0.207704955 1
+4 0.000365172 18
+3 0.169509675 1
+4 0.000379055 17
+3 0.589730872 1
+4 0.000369999 31
+3 0.255624532 1
+4 0.000519728 31
+3 0.031432160 1
+4 0.000429333 31
+3 1.407646041 2
+4 0.000394802 37
+3 2.151660008 1
+4 0.000461818 19
+3 0.185651627 1
+4 0.000432896 20
+3 0.165569201 1
+4 0.000345574 20
+3 0.169659802 1
+4 0.000422324 19
+3 0.405722651 1
+4 0.000363552 18
+3 3.271568134 1
+4 0.000350266 17
+3 0.137754674 1
+4 0.000365437 20
+3 0.213454126 1
+4 0.000397014 20
+3 0.169607523 1
+4 0.000371113 19
+3 0.213714772 1
+4 0.000342087 20
+3 7.642107866 1
+4 0.000376375 20
+3 0.509523548 1
+3 0.161824934 1
+4 0.000463161 68
+3 0.189569262 1
+3 0.153980331 1
+4 0.000399471 74
+3 0.173817347 1
+3 0.145850395 1
+4 0.000417591 70
+3 0.661702198 1
+4 0.000438025 15
+3 0.169527617 1
+4 0.000463697 14
+3 0.149577133 1
+4 0.000424375 18
+3 0.295466207 1
+4 0.000352364 18
+3 0.263549511 1
+4 0.000393437 18
+3 0.194132483 1
+4 0.000343541 17
+3 0.149512046 1
+4 0.000382610 17
+3 0.201498788 1
+4 0.000370958 18
+3 0.421511751 1
+4 0.000417087 18
+3 0.199729040 1
+3 0.071874021 1
+4 0.000343081 4
+3 0.247672408 1
+4 0.000396139 6
+3 0.319652955 1
+4 0.000346619 18
+3 0.199599960 1
+4 0.000357428 24
+3 0.231697594 1
+4 0.000359225 19
+3 0.223551535 1
+4 0.000672168 19
+3 0.047319029 1
+4 0.000387753 19
+3 0.087690646 1
+4 0.000363889 19
+3 0.247534002 1
+4 0.000352289 19
+3 0.191815082 1
+4 0.000347206 19
+3 0.367633035 2
+4 0.000392641 35
+3 0.351613781 1
+4 0.000353246 14
+3 0.271717046 1
+4 0.000497230 15
+3 0.290351570 1
+4 0.000373981 15
+3 0.460691814 1
+4 0.000381376 24
+3 0.167560576 1
+4 0.000364462 16
+3 0.471798818 1
+4 0.000361187 15
+3 0.143835098 1
+4 0.000479757 28
+3 0.159300413 1
+4 0.000361310 16
+3 0.295658858 1
+4 0.000359389 14
+3 0.103530627 1
+4 0.000376373 24
+3 0.295767100 1
+4 0.000347813 9
+3 0.927716879 1
+4 0.000483703 1
+3 0.199479229 1
+4 0.000474704 1
+3 0.151658838 1
+4 0.000428612 1
+4 0.000433767 70
+3 0.439462066 1
+4 0.000355872 35
+7 0.000597311 TSTP
+7 5.374814287 CONT
+4 0.000587921 7
+4 0.000356356 7
+4 0.000298048 646
+3 4.015465365 1
+4 0.000391700 16
+3 0.727171357 1
+4 0.000368542 18
+3 0.591349323 1
+4 0.000354578 18
+3 0.177802364 1
+4 0.000347755 17
+3 0.381697828 1
+4 0.000367834 21
+3 0.343728825 1
+4 0.000563400 10
+3 0.135223999 1
+4 0.000362096 1
+3 0.247882945 1
+4 0.000394669 1
+3 0.247599306 1
+4 0.000403518 1
+4 0.000402784 71
+3 1.639191893 1
+4 0.000430769 36
+7 0.000577903 TSTP
+7 1.455151930 CONT
+4 0.000599454 7
+4 0.000277477 655
+3 19.808624383 1
+4 0.000620969 730
+3 1.550627339 1
+4 0.000575359 607
+3 2.135387686 1
+4 0.000551566 16
+3 0.499508523 1
+4 0.000368551 17
+3 0.082895069 1
+4 0.000407322 16
+3 0.082724768 1
+4 0.000355119 16
+3 0.083289719 1
+4 0.000359989 16
+3 0.082972034 1
+4 0.000358664 18
+3 0.083550867 1
+4 0.000357394 18
+3 0.682393143 1
+4 0.000514469 18
+3 5.239464747 1
+4 0.000357573 17
+3 0.303718219 1
+4 0.000389341 16
+3 0.153497530 1
+4 0.000362550 16
+3 0.197645169 1
+4 0.000344754 16
+3 1.015752224 1
+3 0.247971976 1
+4 0.000381490 22
+3 0.191674293 1
+4 0.000436538 18
+3 0.207618715 2
+4 0.000372068 34
+3 0.175537166 1
+4 0.000369702 23
+4 0.000358929 33
+3 0.127364793 1
+4 0.000354324 18
+3 0.151376226 1
+4 0.000366593 55
+3 0.255738152 1
+4 0.000344903 18
+3 0.257391796 1
+3 0.104301529 1
+4 0.000360991 28
+3 0.237644139 1
+4 0.000392513 120
+3 0.255590357 1
+4 0.000351348 16
+3 0.775731688 1
+4 0.000417487 16
+3 0.255723760 1
+4 0.000358589 23
+3 0.183461158 1
+4 0.000403981 17
+3 0.295703357 2
+4 0.000381414 34
+3 0.224477384 1
+4 0.000394858 16
+3 0.152747648 1
+4 0.000333163 18
+3 0.318739023 1
+4 0.000365360 18
+3 0.166589978 1
+4 0.000330995 17
+3 0.169695514 1
+4 0.000365565 17
+3 0.453575751 1
+4 0.000391533 20
+3 3.511826680 1
+4 0.000379165 9
+3 0.231519861 1
+4 0.000355888 1
+3 0.151728131 1
+4 0.000402742 1
+3 0.191560006 1
+4 0.000330002 1
+3 0.111720453 1
+4 0.000427301 141
+3 1.015593541 1
+4 0.000366551 20
+3 0.499780992 1
+4 0.000390781 13
+3 0.083591972 1
+4 0.000338616 20
+3 0.083173877 1
+4 0.000348954 17
+3 0.082791217 1
+4 0.000315724 20
+3 0.082888571 1
+4 0.000324345 17
+3 0.082877315 1
+4 0.000342978 18
+3 0.228477607 1
+4 0.000354424 20
+3 0.253676349 1
+4 0.000352173 17
+3 0.177609442 1
+4 0.000324841 18
+3 0.997767898 1
+4 0.000411047 4
+3 0.399462155 1
+4 0.000341911 19
+3 0.401740314 1
+4 0.000350008 16
+3 0.498318919 1
+4 0.000342628 20
+3 0.083051030 1
+4 0.001183443 20
+3 0.082368509 1
+4 0.000430734 21
+3 0.083436563 1
+4 0.000409277 15
+3 0.083261267 1
+4 0.000520477 14
+3 0.082682237 1
+4 0.000479996 12
+3 0.083276505 1
+4 0.000406351 47
+3 0.083040343 1
+4 0.000376074 55
+3 0.083884389 1
+4 0.000367499 82
+3 0.083670398 1
+4 0.000460801 83
+3 0.121882354 1
+4 0.000333662 14
+3 0.499710087 1
+4 0.000350508 18
+3 0.083149838 1
+4 0.000329768 19
+3 0.082760868 1
+4 0.000338668 20
+3 0.083287297 1
+4 0.000329723 15
+3 0.083433722 1
+4 0.000318367 17
+3 0.082885103 1
+4 0.000391176 17
+3 0.083185700 1
+4 0.000338025 21
+3 0.082696974 1
+4 0.000339598 20
+3 0.083223383 1
+4 0.000339001 18
+3 0.280193383 1
+4 0.000362337 9
+3 0.119712471 1
+4 0.000323805 1
+3 0.167634103 1
+4 0.000324327 1
+3 0.095701181 1
+4 0.000382500 1
+4 0.000612131 10
+4 0.000366488 59
+3 0.310748273 1
+4 0.000361886 35
+7 0.000565278 TSTP
+7 1.319347496 CONT
+4 0.000644159 7
+4 0.000301609 786
+3 1.446800162 1
+4 0.000415385 15
+3 0.147274104 1
+4 0.000411903 18
+3 0.156549622 1
+4 0.000342514 28
+3 0.158945907 1
+4 0.000383638 18
+3 0.407592647 2
+4 0.107006610 32
+3 0.134968216 1
+4 0.000374285 10
+3 0.093619166 1
+4 0.000321406 1
+3 0.135669132 1
+4 0.000418615 1
+3 0.111632584 1
+4 0.000440515 1
+4 0.000418319 71
+3 0.223294460 1
+4 0.000391684 36
+7 0.000579182 TSTP
+7 1.231321848 CONT
+4 0.000599653 7
+4 0.000272461 792
+3 22.632186080 1
+4 0.000378197 10
+3 0.159171346 1
+4 0.000358639 1
+3 0.175482875 1
+4 0.000330726 1
+3 0.295940912 1
+4 0.000358370 1
+4 0.000559630 10
+4 0.000318172 61
+3 4.462731189 1
+4 0.000387862 10
+3 0.871705771 1
+4 0.000359601 1
+3 0.087987496 1
+4 0.000319220 1
+3 0.070927565 1
+4 0.000390511 1
+3 0.199889669 1
+4 0.000351310 1
+3 0.175724658 1
+4 0.000332611 1
+3 0.119842732 1
+4 0.000370593 13
+4 0.000387753 39
+3 0.767555090 1
+4 0.000493540 36
+7 0.000508215 TSTP
+7 1.966763075 CONT
+4 0.000741179 7
+4 0.000279981 775
+3 25.824754391 1
+4 0.000470756 36
+7 0.000494758 TSTP
+7 65.088723394 CONT
+4 0.000679719 7
+4 0.000275667 733
+3 6.927156213 1
+4 0.000373384 16
+3 0.496363737 1
+4 0.000376392 15
+3 0.470682080 1
+4 0.000349852 15
+3 0.391716421 1
+4 0.000394592 32
+3 0.247584509 1
+4 0.000420580 15
+3 0.311530292 1
+4 0.000370720 15
+3 0.183777268 1
+4 0.000363324 26
+3 0.151478625 1
+4 0.000446062 15
+3 0.231612927 1
+4 0.000339645 15
+3 0.127583911 1
+4 0.000373080 23
+3 0.176030220 1
+4 0.000348512 16
+3 0.335461954 1
+4 0.000445479 15
+3 1.183603443 1
+4 0.000391993 24
+3 0.159550415 1
+4 0.000429718 16
+3 1.815580809 1
+3 0.138366471 1
+4 0.000385973 75
+3 0.357256096 1
+4 0.000370503 10
+3 0.103593163 1
+4 0.000327301 1
+3 0.135668931 1
+4 0.000339880 1
+3 0.135758729 1
+4 0.000374779 1
+4 0.000383260 14
+4 0.000381334 56
+3 1.295293307 1
+4 0.000397081 36
+7 0.000524204 TSTP
+7 26.187658124 CONT
+4 0.000555116 7
+4 0.000279669 721
+4 0.000500127 37
+3 2.138534979 1
+4 0.000382233 18
+3 1.319434356 1
+4 0.000371323 18
+3 0.391746191 1
+4 0.000430419 118
+3 2.183749419 1
+4 0.000416517 16
+3 0.499887990 1
+4 0.000346047 16
+3 0.083137968 1
+4 0.000364435 16
+3 0.082712342 1
+4 0.000410273 18
+3 0.083108498 1
+4 0.000332183 19
+3 0.083055230 1
+4 0.000334342 16
+3 0.083178624 1
+4 0.000350218 18
+3 0.083412336 1
+4 0.000324054 21
+3 0.083131851 1
+4 0.000336146 17
+3 0.082551557 1
+4 0.000353136 17
+3 31.721861726 1
+4 0.000361401 10
+3 0.223027249 1
+4 0.000363075 1
+3 0.143735767 1
+4 0.000404044 1
+3 0.047432050 1
+4 0.000315162 1
+3 0.183901229 1
+4 0.000344476 1
+3 0.103401044 1
+4 0.000342643 1
+3 0.519775970 1
+4 0.000387978 1
+3 0.023680438 1
+4 0.000321479 1
+3 0.521798478 1
+4 0.000343976 1
+3 0.109494999 1
+4 0.000336452 1
+3 0.143885891 1
+4 0.000339551 1
+3 0.047382978 1
+4 0.000312934 1
+3 0.039850761 1
+4 0.000335274 1
+3 0.223626456 1
+4 0.000598221 357
+3 2.759557850 1
+4 0.000454453 165
+3 6.463847512 1
+4 0.000484059 69
+3 0.233266723 1
+4 0.000376357 45
+3 0.189701742 1
+4 0.000378185 34
+3 2.088931237 1
+4 0.000487228 18
+3 0.498740683 1
+4 0.000530493 17
+3 0.083294029 1
+4 0.000517648 16
+3 0.082933704 1
+4 0.000589034 16
+3 0.083121594 1
+4 0.000381672 16
+3 0.083190653 1
+4 0.000378804 18
+3 0.083077548 1
+4 0.000584605 16
+3 0.082964696 1
+4 0.000477948 16
+3 1.229635017 1
+3 0.111955978 1
+3 0.106424974 1
+4 0.000402502 29
+3 0.701155126 1
+4 0.000353726 9
+3 0.072668400 1
+4 0.000476573 243
+3 0.862667867 1
+4 0.000408783 87
+3 0.169676459 1
+4 0.000385322 38
+3 0.245570905 1
+4 0.000340632 19
+3 0.169687251 1
+4 0.000347165 15
+3 0.597576864 1
+4 0.000498113 136
+3 5.727928438 1
+4 0.000378035 42
+3 0.249524958 1
+4 0.000421281 17
+3 0.365535485 1
+4 0.000362850 16
+3 6.880479377 1
+3 0.087821755 1
+4 0.000404628 28
+3 0.367357626 12
+4 0.000426716 55
+4 0.707348201 17
+3 0.130074470 1
+4 0.109903231 32
+3 1.027983646 1
+4 0.000356073 16
+3 0.655678250 1
+4 0.000371281 16
+3 0.537767701 1
+4 0.000346343 16
+3 0.349609359 1
+3 0.047872207 1
+4 0.000418273 28
+3 0.215773114 1
+4 0.000347070 17
+3 0.087473202 1
+4 0.000346937 17
+3 0.103719147 1
+4 0.000344838 17
+3 0.063617875 1
+4 0.000328166 18
+3 0.583689531 1
+4 0.000365628 17
+3 0.311682441 1
+4 0.000360082 16
+3 0.527836560 2
+4 0.000441033 27
+3 0.167394327 1
+4 0.000340744 16
+3 0.247578360 1
+3 0.048043305 1
+4 0.000443248 26
+3 0.225666468 1
+4 0.000344870 17
+3 0.213619058 1
+4 0.000394568 17
+3 0.559562890 2
+4 0.000394478 27
+3 15.848324193 1
+4 0.000419279 19
+3 0.183489003 1
+4 0.000345899 17
+3 2.687855479 1
+4 0.000386428 16
+3 0.231489856 1
+4 0.000344842 16
+3 0.500614309 1
+4 0.000372932 16
+3 0.082950621 1
+4 0.000424711 16
+3 0.082927846 1
+4 0.000359324 16
+3 0.082941249 1
+4 0.000359952 16
+3 0.083537449 1
+4 0.000432234 16
+3 0.083639033 1
+4 0.000319760 17
+3 0.082940801 1
+4 0.000367004 16
+3 0.082525413 1
+4 0.000343394 16
+3 0.364577942 1
+4 0.000374545 16
+3 0.221683183 1
+4 0.000344868 4
+3 0.175628924 1
+4 0.000394552 23
+3 0.487635634 1
+4 0.000354558 20
+3 0.304027953 1
+4 0.000420292 20
+3 0.716794830 1
+4 0.109962082 32
+3 0.588597619 1
+4 0.000363484 18
+3 0.153596439 1
+4 0.000393960 19
+3 0.205857650 1
+4 0.000340264 16
+3 0.279444090 1
+4 0.000355102 22
+3 0.223662246 1
+4 0.000430116 18
+3 0.823680490 2
+4 0.000386804 39
+3 0.367559652 1
+4 0.000371871 22
+3 0.231607979 1
+4 0.000350902 18
+3 0.803025775 1
+4 0.110021990 31
+3 0.142996783 1
+4 0.000338813 17
+3 0.247082307 1
+4 0.000455963 55
+3 0.175699074 1
+4 0.000337278 17
+3 0.159629093 1
+4 0.000409539 55
+3 8.752156863 1
+4 0.000371058 9
+3 0.159565505 1
+4 0.000362081 1
+3 0.159543856 1
+4 0.000364929 1
+3 0.135718484 1
+4 0.000430600 11
+4 0.000388491 59
+3 0.879830763 1
+4 0.000351088 35
+7 0.000591714 TSTP
+7 10.775074428 CONT
+4 0.000532260 7
+4 0.000283695 801
+3 122.379680708 1
+4 0.000338202 1
+3 0.975616476 1
+4 0.000372258 17
+3 0.471044194 1
+4 0.000365445 21
+3 0.319595247 1
+4 0.000347971 18
+3 0.479822759 2
+4 0.000381076 10
+3 0.087500836 1
+4 0.000372536 1
+3 0.143525511 1
+4 0.000343071 1
+3 0.095868843 1
+4 0.000446368 1
+4 0.000368224 69
+3 0.375411408 1
+4 0.000338057 35
+7 0.000563565 TSTP
+7 34.800073031 CONT
+4 0.000746321 7
+4 0.000257701 806
+3 1.343129903 1
+4 0.000460083 15
+3 0.499812064 1
+4 0.000412548 15
+3 0.083184054 1
+4 0.000376452 15
+3 0.083522459 1
+4 0.000408231 17
+3 0.082785596 1
+4 0.000371098 15
+3 0.488374234 1
+4 0.000340219 17
+3 0.143810199 1
+4 0.000418250 16
+3 0.153628152 1
+4 0.000340937 16
+3 0.149498016 1
+4 0.000371942 16
+3 0.153786227 1
+4 0.000337495 16
+3 0.157573629 1
+4 0.000438718 22
+3 0.312586383 1
+4 0.000370158 22
+3 0.730315193 1
+4 0.110086103 32
+3 0.382311887 2
+4 0.000382288 11
+3 0.224281839 1
+4 0.000428709 1
+3 0.126845647 1
+4 0.000438222 1
+3 0.103578691 1
+4 0.000389511 1
+4 0.000367224 70
+3 0.327889257 1
+4 0.000461851 36
+7 0.000523766 TSTP
+7 14.535079922 CONT
+4 0.000670302 7
+4 0.000265270 810
+3 9.103631881 1
+4 0.000367466 18
+3 0.217331832 1
+4 0.000399854 19
+3 1.421553205 1
+4 0.000361412 19
+3 0.193680658 1
+4 0.000361545 18
+3 0.141506554 1
+4 0.000387865 19
+3 0.199722276 1
+4 0.000355568 16
+3 0.223687340 1
+4 0.000436533 32
+3 0.311582460 1
+4 0.000362446 10
+3 0.119464594 1
+4 0.000321298 1
+3 0.127769465 1
+4 0.000342437 1
+3 0.103694545 1
+4 0.000358101 1
+4 0.000603249 10
+4 0.000399811 59
+3 8.535483151 1
+4 0.000405372 36
+7 0.000583666 TSTP
+7 5.998846396 CONT
+4 0.000580307 7
+4 0.000295594 766
+4 0.000503637 36
+3 2.294722820 1
+4 0.000388838 26
+3 3.503556579 1
+4 0.000373627 9
+3 0.143605993 1
+4 0.000330021 1
+3 0.175570042 1
+4 0.000329775 1
+3 0.119669497 1
+4 0.000384506 1
+4 0.000341788 54
+4 0.000338318 15
+3 21.992383039 1
+4 0.000380385 9
+3 0.334960478 1
+4 0.000376254 1
+3 0.159566818 1
+4 0.000360293 1
+3 0.175726678 1
+4 0.000340187 1
+3 0.215654078 1
+4 0.000324899 1
+3 0.127898264 1
+4 0.000574071 755
+3 1.687538943 1
+3 0.129829547 1
+4 0.000370848 30
+3 0.957674306 1
+4 0.000593030 675
+3 0.137423633 1
+4 0.000468474 17
+3 0.909460482 1
+4 0.000495247 15
+3 0.169503370 1
+4 0.000378756 15
+3 0.157521154 1
+4 0.000329270 15
+3 0.153895847 1
+4 0.000350257 17
+3 0.141571021 1
+4 0.000342057 15
+3 0.121773778 1
+4 0.000365563 15
+3 0.101450868 1
+4 0.000354511 15
+3 0.248445006 1
+4 0.000408703 76
+3 0.446846618 1
+3 0.135861200 1
+4 0.000378781 21
+3 0.399849423 1
+4 0.000333820 17
+3 0.167659310 1
+4 0.000360256 23
+3 0.087678898 1
+4 0.000330257 18
+3 0.223584124 1
+4 0.000395566 18
+3 0.015619789 1
+4 0.000336952 18
+3 0.392545632 1
+4 0.000342836 16
+3 0.118843946 1
+4 0.000372277 17
+3 0.151461990 1
+4 0.000336400 18
+3 0.264330546 1
+4 0.000391538 18
+3 0.167508769 1
+4 0.000346292 18
+3 0.151135765 1
+4 0.000432924 19
+3 0.111685031 1
+4 0.000331441 18
+3 0.079619828 1
+4 0.000361622 18
+3 0.119696776 1
+4 0.000336516 18
+3 0.713742396 1
+3 0.086780048 1
+4 0.000360976 32
+3 0.110696559 1
+4 0.000325357 15
+3 0.153844943 1
+4 0.000350991 17
+3 0.335340094 1
+4 0.000353421 16
+3 5.974912521 1
+4 0.000358901 16
+3 0.129029239 1
+4 0.000374149 16
+3 0.237395351 1
+3 0.088025697 1
+4 0.000363525 4
+3 0.167722244 1
+3 0.055909963 1
+4 0.000352863 4
+3 0.175656873 1
+3 0.040047222 1
+4 0.000400447 6
+3 0.247662054 1
+3 0.055969909 1
+4 0.000361014 4
+3 0.591591932 1
+4 0.000389174 21
+3 0.599701281 1
+4 0.000383012 4
+3 0.185704845 1
+4 0.000340460 4
+3 0.117530795 1
+4 0.000336025 4
+3 0.127651288 1
+4 0.000326314 23
+3 0.227617576 21
+4 0.000394931 49
+3 0.739762936 1
+4 0.000364907 28
+3 2.933895249 24
+4 0.000409806 52
+3 0.809380993 2
+4 0.000386852 35
+3 0.359707158 1
+3 0.145967481 1
+4 0.000488735 83
+3 0.245435757 1
+3 0.153976145 1
+4 0.000379350 87
+3 0.205686113 1
+3 0.171590848 1
+4 0.000383419 73
+3 0.180070094 1
+3 0.169972937 1
+4 0.000411777 62
+3 0.205778448 1
+3 0.170474122 1
+4 0.000392368 62
+3 0.228967146 1
+3 0.154108572 1
+4 0.000466808 84
+3 0.669659733 1
+4 0.000357843 17
+3 0.279718786 1
+4 0.000387121 58
+3 3.863563779 2
+3 0.129957922 1
+4 0.000396599 98
+3 0.717649806 1
+4 0.000393166 23
+3 0.399692174 1
+4 0.000384597 10
+3 0.112958508 1
+4 0.000337201 1
+3 0.126218681 1
+4 0.000316153 1
+3 0.095579406 1
+4 0.000400509 1
+4 0.000780511 10
+4 0.000384998 59
+3 1.879097413 1
+4 0.000405332 36
+7 0.000520590 TSTP
+7 119.826827916 CONT
+4 0.000775849 7
+4 0.000260731 821
+3 4.375067531 1
+4 0.000381934 10
+3 0.279467306 1
+4 0.000361364 1
+3 0.207587374 1
+4 0.000343894 1
+3 0.167709587 1
+4 0.000368746 1
+3 0.215741233 1
+4 0.000337767 1
+3 0.223551818 1
+4 0.000538641 264
+3 2.239531984 1
+4 0.000353768 9
+3 0.087861376 1
+4 0.000434604 172
+3 0.591198116 1
+4 0.000413197 87
+3 27.650282086 1
+4 0.000375320 15
+3 0.216036186 1
+4 0.000339618 15
+3 0.557577555 1
+4 0.000361545 17
+3 0.135514992 1
+4 0.000849186 16
+3 0.209302149 1
+4 0.000328994 16
+3 0.213714076 1
+4 0.000342101 17
+3 0.169517039 1
+4 0.000346635 17
+3 0.421847735 1
+4 0.000351468 17
+3 0.151544748 1
+3 0.080143076 1
+4 0.000351960 20
+3 0.263690201 1
+3 0.055774217 1
+4 0.000399576 5
+3 0.367654328 1
+4 0.000375681 6
+3 0.719657836 1
+4 0.000434688 16
+3 0.263521851 1
+4 0.000346499 23
+3 0.279746476 1
+4 0.000380054 18
+3 0.710073289 1
+4 0.110008539 32
+3 2.347598243 1
+4 0.000393924 10
+3 0.079685270 1
+4 0.000401395 1
+3 0.135456431 1
+4 0.000371437 1
+3 0.103691393 1
+4 0.000349437 1
+4 0.000385114 70
+3 0.239821236 1
+4 0.000335297 36
+7 0.000505632 TSTP
+7 1.230823148 CONT
+4 0.000675817 7
+4 0.000350616 7
+4 0.000294831 850
+3 23.808037641 1
+4 0.000483238 16
+3 0.200756075 1
+4 0.000342844 16
+3 0.165768291 1
+4 0.000389865 39
+3 0.161467370 1
+4 0.000407762 73
+3 0.317657050 1
+4 0.000374583 18
+3 0.185507615 1
+4 0.000350344 21
+3 1.685930882 1
+4 0.000430918 10
+3 0.199468221 1
+4 0.000349579 1
+3 0.143750021 1
+4 0.000326515 1
+3 0.119605560 1
+4 0.000326526 1
+3 0.119984250 1
+4 0.000409566 39
+3 0.615348721 1
+4 0.000597532 913
+3 1.681877265 1
+4 0.000578058 666
+3 1.213063033 1
+4 0.000566762 724
+3 0.953636042 1
+4 0.000630790 344
+3 0.957197011 1
+4 0.000371631 20
+4 0.000424486 669
+3 31.555179780 1
+4 0.000616650 744
+3 1.020593190 1
+4 0.000362479 10
+3 0.071589347 1
+4 0.000625290 674
+3 3.136312054 1
+4 0.000364258 62
+3 0.679052733 1
+4 0.000576460 579
+3 0.487292331 1
+4 0.000395222 55
+3 1.047614227 1
+4 0.000459645 19
+4 0.000402406 782
+3 0.689108023 1
+4 0.000509481 408
+3 0.709404492 1
+4 0.000578293 720
+3 1.201603521 1
+4 0.000570565 855
+3 0.661291698 1
+4 0.000581138 748
+3 3.121724722 1
+4 0.000605819 657
+3 0.933460490 1
+4 0.000563268 560
+3 0.655363138 1
+4 0.000617957 838
+3 0.895563613 1
+4 0.000555777 612
+3 0.471409918 1
+4 0.000558188 583
+3 0.503285278 1
+4 0.000412215 55
+4 0.000375934 748
+3 0.999404469 1
+4 0.000397323 10
+3 0.119496582 1
+4 0.000334729 1
+3 0.119657542 1
+4 0.000366361 1
+4 0.001255341 8
+4 0.000320612 23
diff --git a/lib/iolog/regress/corpus/seed/timing/timing.7 b/lib/iolog/regress/corpus/seed/timing/timing.7
new file mode 100644
index 0000000..320a868
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/timing/timing.7
@@ -0,0 +1,10 @@
+3 0.731998581 1
+4 0.001916416 2
+7 0.002850082 TSTP
+7 0.683456735 CONT
+3 0.688967687 1
+4 0.001667674 2
+7 0.002277631 TSTP
+7 0.515107145 CONT
+3 0.343713993 1
+4 0.002050968 2
diff --git a/lib/iolog/regress/corpus/seed/timing/timing.8 b/lib/iolog/regress/corpus/seed/timing/timing.8
new file mode 100644
index 0000000..5fabcc4
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/timing/timing.8
@@ -0,0 +1,891 @@
+4 0.064664132 32
+4 0.000859566 850
+3 1.028898872 1
+4 0.001747739 9
+3 0.926126566 1
+4 0.001425060 1
+3 0.198414833 1
+4 0.001499542 1
+3 0.134447257 1
+4 0.001506297 1
+3 0.118268537 1
+4 0.001541057 1
+3 0.086780988 1
+4 0.001622847 1
+3 0.062239852 1
+4 0.001588923 1
+3 0.214384951 1
+4 0.001460651 1
+3 0.086510579 1
+4 0.003193030 911
+3 1.981206350 1
+4 0.001460605 17
+3 0.342451860 1
+3 0.121863647 1
+4 0.001573592 30
+3 0.260718112 1
+4 0.104455308 53
+3 0.215829722 1
+4 0.001744179 18
+3 0.365827912 1
+4 0.001569107 23
+3 0.846427645 1
+4 0.001572957 19
+3 0.814749657 1
+4 0.001575922 19
+3 0.182163938 1
+4 0.001568547 19
+3 0.414578434 1
+4 0.001656973 19
+3 0.318272879 1
+4 0.001584842 19
+3 0.262367325 1
+4 0.001488336 19
+3 0.230410279 1
+4 0.109315456 37
+4 0.001609717 49
+3 0.353056895 1
+4 0.001788404 10
+3 0.094128417 1
+4 0.001531837 1
+3 0.142508934 1
+4 0.001593153 1
+3 0.126357885 1
+4 0.002388055 15
+4 0.001432636 58
+3 1.228902472 1
+4 0.002391036 40
+7 0.002743419 TSTP
+7 5025.564659632 CONT
+4 0.003192704 7
+4 0.001526602 997
+3 0.793028278 1
+4 0.003000277 40
+7 0.002235214 TSTP
+7 5925.171790777 CONT
+4 0.002096058 7
+4 0.001318204 7
+4 0.001159538 900
+3 0.984554657 1
+4 0.001469616 40
+7 0.002327650 TSTP
+7 6189.225069749 CONT
+4 0.002104678 7
+4 0.001037801 7
+4 0.001216318 900
+3 1.161146125 1
+4 0.001439585 16
+3 0.814606611 1
+4 0.001606528 21
+3 0.230277078 1
+4 0.001975296 53
+3 0.190021728 1
+3 0.096129999 1
+4 0.001594887 33
+3 0.182291714 1
+4 0.001773170 4
+3 0.326454021 1
+4 0.001484961 9
+3 0.366715902 1
+4 0.001543752 1
+3 0.446210491 1
+4 0.001689363 1
+3 0.006253433 1
+4 0.001433390 1
+3 0.064300445 1
+4 0.001604202 1
+3 0.340813942 1
+4 0.001517377 1
+3 0.160276062 1
+4 0.002970366 1
+3 0.058797601 1
+4 0.001392200 1
+3 0.127730195 1
+4 0.001667163 1
+3 0.094630017 1
+4 0.001782949 1
+4 0.001676588 70
+3 0.355976786 1
+4 0.001506307 39
+7 0.002105798 TSTP
+7 14.292867168 CONT
+4 0.002398126 7
+4 0.001008191 7
+4 0.001088992 984
+3 1.219079321 1
+4 0.001760534 21
+3 0.285906574 1
+4 0.001752349 60
+3 0.190367416 1
+4 0.105561951 31
+3 0.022256270 1
+4 0.001478141 15
+3 0.206781774 1
+4 0.001554002 4
+3 0.270277605 1
+4 0.001420215 9
+3 0.118523501 1
+4 0.001731089 1
+3 0.126173273 1
+4 0.001409300 1
+3 0.118763318 1
+4 0.001517062 1
+4 0.001639842 70
+3 0.293063491 1
+4 0.001358755 39
+7 0.002350591 TSTP
+7 88449.593270142 CONT
+4 0.002494607 7
+4 0.001958302 991
+3 0.825250499 1
+4 0.001436475 9
+3 0.438398078 1
+4 0.001697468 32
+3 1.350305447 1
+4 0.001477446 15
+3 0.168253265 1
+4 0.001493751 15
+3 0.180841618 1
+4 0.001722349 21
+3 0.182231663 1
+4 0.001695639 47
+3 0.230290135 1
+4 0.109360689 31
+3 0.178605949 1
+4 0.111499107 1
+3 0.144875484 1
+4 0.001417120 9
+3 0.150117516 1
+4 0.001488857 1
+3 0.110446391 1
+4 0.001616968 1
+3 0.110541552 1
+4 0.001419525 1
+4 0.001945622 10
+4 0.001402320 60
+3 6.452086794 1
+4 0.001500216 73
+3 0.405864230 1
+4 0.001626618 9
+3 0.134289323 1
+4 0.001338674 1
+3 0.142601704 1
+4 0.001527262 1
+3 0.102629985 1
+4 0.001900211 11
+4 0.001350750 60
+3 0.405180113 1
+4 0.001535457 39
+7 0.002495892 TSTP
+7 221561.264483987 CONT
+4 0.002009587 7
+4 0.001101567 7
+4 0.001442021 919
+4 0.001278489 65
+3 5.463826160 1
+4 0.001484976 15
+3 0.184226629 1
+4 0.001414341 15
+3 0.292783684 1
+3 0.153810375 1
+4 0.001446971 27
+3 0.268656044 1
+4 0.002896326 120
+3 0.285181477 1
+4 0.001661168 15
+3 0.150478007 1
+4 0.001453396 22
+3 0.230540344 1
+4 0.001440316 53
+3 0.166485119 1
+3 0.087962359 1
+4 0.001508426 33
+3 0.222749504 1
+4 0.001509546 18
+3 1.894427201 1
+4 0.001588127 26
+3 1.518514800 1
+4 0.001448627 18
+3 0.222417824 1
+4 0.001472537 24
+3 0.190411167 1
+4 0.001525827 19
+3 0.838594711 1
+3 0.031760695 1
+4 0.001551002 38
+3 0.870824301 1
+4 0.001489017 16
+3 1.014356232 1
+4 0.001701719 18
+3 0.822415083 1
+4 0.001494696 24
+3 0.222596147 1
+4 0.001432681 19
+3 0.310526270 1
+4 0.001596028 19
+3 0.126330981 1
+4 0.001500257 19
+3 0.174752799 1
+4 0.001638468 20
+3 0.253981113 1
+4 0.001461846 37
+3 0.254649605 1
+4 0.103883614 34
+3 0.200314766 1
+4 0.001387905 20
+3 0.406667304 1
+4 0.001731770 17
+3 0.110003286 1
+4 0.001520397 23
+3 0.230621930 1
+4 0.001493146 24
+3 0.446629930 1
+4 0.001496936 16
+3 0.254613349 1
+4 0.001397571 15
+3 0.166240486 1
+4 0.001700974 22
+3 0.190319056 1
+4 0.001517261 58
+3 0.254819347 1
+4 0.107582560 31
+3 0.292233944 1
+4 0.001445151 9
+3 0.110475422 1
+4 0.001698858 1
+3 0.094333824 1
+4 0.001586513 77
+3 0.326387580 1
+4 0.001661283 39
+7 0.002204689 TSTP
+7 0.556717292 CONT
+4 0.002623429 7
+4 0.001179768 1027
+3 0.267631453 1
+4 0.001424285 9
+3 0.110521878 1
+4 0.001441585 1
+3 0.127356593 1
+4 0.001510382 1
+3 0.077681400 1
+4 0.001539912 1
+4 0.001640563 70
+3 0.388998560 1
+4 0.001719929 39
+7 0.002200549 TSTP
+7 13.244385459 CONT
+4 0.000729218 7
+4 0.000294418 1005
+3 7.079466151 1
+4 0.001791190 45
+3 0.205970549 1
+4 0.001643508 17
+3 0.414571661 1
+4 0.001531132 16
+3 0.222850249 1
+4 0.001640468 17
+3 0.205982399 1
+4 0.001558167 17
+3 0.134087222 1
+4 0.001465226 17
+3 0.166847603 1
+4 0.001662358 17
+3 0.126370137 1
+4 0.001446416 17
+3 0.550630445 1
+4 0.001435360 16
+3 0.334496380 1
+4 0.001602892 19
+3 1.686172041 1
+4 0.000346437 17
+3 0.151576266 1
+4 0.000349729 16
+3 0.319957850 1
+4 0.001433906 17
+3 0.166454049 1
+4 0.001689503 17
+3 0.062391632 1
+4 0.001573468 17
+3 0.150461777 1
+4 0.001457996 16
+3 0.070532447 1
+4 0.001422680 17
+3 0.086873802 1
+4 0.001815970 16
+3 0.189849021 1
+4 0.001595918 19
+3 0.126580914 1
+4 0.001572067 18
+3 0.102119195 1
+4 0.001489716 18
+3 0.110616169 1
+4 0.001610073 18
+3 0.142382103 1
+4 0.001462456 18
+3 0.062502293 1
+4 0.001701379 17
+3 0.214412562 1
+4 0.001462741 18
+3 1.198409314 1
+4 0.000460850 17
+3 0.999678958 1
+4 0.000331997 17
+3 0.127804986 1
+4 0.000303396 18
+3 0.151363097 1
+4 0.000316266 18
+3 0.112134826 1
+4 0.001454656 18
+3 0.150624064 1
+4 0.001407951 37
+3 0.222441090 1
+4 0.111006972 33
+3 0.281208333 1
+4 0.001415495 17
+3 0.150437782 1
+3 0.063714477 1
+4 0.001565847 27
+3 0.214617624 1
+4 0.001526422 18
+3 0.062489458 1
+4 0.001570842 18
+3 0.166474689 1
+4 0.001500832 18
+3 0.030451545 1
+4 0.001512782 20
+3 0.222611776 1
+4 0.001628519 19
+3 0.030120866 1
+4 0.001466336 19
+3 0.030404355 1
+4 0.001619698 19
+3 0.334815583 1
+4 0.108865834 33
+3 0.187010010 1
+4 0.001488371 17
+3 0.126381232 1
+4 0.001505957 14
+3 0.126545303 1
+3 0.112060040 1
+4 0.001389665 9
+3 0.422737541 1
+4 0.001438741 1
+3 0.286661427 1
+4 0.001490682 1
+3 0.152535520 1
+4 0.001536577 36
+3 0.324257351 1
+4 0.001444521 9
+3 0.142471479 1
+4 0.001356360 1
+3 0.158776959 1
+4 0.001371060 1
+3 0.094594897 1
+4 0.001367810 33
+4 0.001464076 23
+3 0.549135158 1
+4 0.001431856 9
+3 0.126501453 1
+4 0.001472637 1
+3 0.126547613 1
+4 0.001491527 1
+3 0.078728327 1
+4 0.001626128 11
+4 0.001487806 59
+3 0.340831284 1
+4 0.001617373 39
+7 0.002583839 TSTP
+7 514445.097903843 CONT
+4 0.002257030 7
+4 0.002294835 1007
+3 0.945625170 1
+4 0.002777691 39
+7 0.002355126 TSTP
+7 86184.341362582 CONT
+4 0.002221120 7
+4 0.001443996 7
+4 0.001283714 914
+3 2.392062045 1
+4 0.002652904 12
+4 0.001409386 27
+7 0.002425876 TSTP
+7 21288.589641005 CONT
+4 0.002742450 7
+4 0.001324494 7
+4 0.002229915 914
+3 1.223042554 1
+4 0.001448160 39
+7 0.002279495 TSTP
+7 2137.685708492 CONT
+4 0.004071430 7
+4 0.001616922 7
+4 0.001927357 914
+3 0.830124110 1
+4 0.001490492 39
+7 0.003177815 TSTP
+7 17415.985595701 CONT
+4 0.002433577 7
+4 0.000994215 7
+4 0.001078497 914
+3 1.240972872 1
+4 0.001393460 39
+7 0.002303475 TSTP
+7 601.486631680 CONT
+4 0.002426206 7
+4 0.001210918 7
+4 0.001102268 914
+3 0.857339012 1
+4 0.001674773 39
+7 0.002435617 TSTP
+7 391818.529264947 CONT
+4 0.000657391 7
+4 0.000218089 7
+4 0.000220770 914
+3 0.357849108 1
+4 0.001405050 9
+3 0.166742233 1
+4 0.001567897 1
+3 0.438304127 1
+4 0.001349665 1
+3 0.168918821 1
+4 0.001550563 32
+3 0.308645085 1
+4 0.001736869 39
+7 0.002554823 TSTP
+7 303016.218109119 CONT
+4 0.002752175 7
+4 0.001469450 7
+4 0.001455036 914
+3 0.887365475 1
+4 0.001395045 39
+7 0.002446251 TSTP
+7 215139.725383626 CONT
+4 0.002051468 7
+4 0.001705964 7
+4 0.001550202 914
+3 2.231928411 1
+4 0.001527117 15
+3 0.498266348 1
+4 0.001486902 15
+3 0.082105873 1
+4 0.001468756 15
+3 0.081830336 1
+4 0.001803544 15
+3 0.081630069 1
+4 0.001465996 15
+3 0.082089163 1
+4 0.001416686 15
+3 0.081225139 1
+4 0.001559182 15
+3 0.081618058 1
+4 0.001515897 15
+3 0.358906691 1
+4 0.001396906 14
+3 0.470357374 1
+4 0.001615638 20
+3 0.590548039 1
+4 0.001531272 52
+3 0.318289227 1
+4 0.106849942 30
+3 0.589134119 1
+4 0.001647973 13
+3 0.238312812 1
+4 0.001495872 14
+3 0.254615192 1
+3 0.680285637 1
+4 0.001795360 57
+3 0.013906154 1
+3 0.616146242 1
+3 0.409887356 1
+4 0.001467901 76
+3 0.516728247 1
+4 0.001690474 38
+3 0.382235119 1
+4 0.001520617 8
+3 0.142389056 1
+4 0.001473906 1
+3 0.142420386 1
+4 0.001444666 1
+3 0.174696653 1
+4 0.001473371 1
+4 0.001439716 69
+3 19.886035460 1
+4 0.001387176 8
+3 0.198563762 1
+4 0.001444846 1
+3 0.150104471 1
+4 0.001389040 1
+3 0.070689737 1
+4 0.001632588 1
+3 0.222393421 1
+4 0.001440621 1
+3 0.238663600 1
+4 0.001475092 1
+3 0.062492711 1
+4 0.001421216 1
+3 0.182816888 1
+4 0.002090833 97
+3 1.334082056 1
+4 0.001590818 13
+3 0.305939475 1
+4 0.001700324 67
+3 0.235779724 1
+4 0.001464116 19
+4 0.001492152 35
+3 0.964004231 1
+4 0.001741719 50
+3 0.278959707 1
+4 0.001432251 21
+3 0.182114085 1
+4 0.001620368 47
+3 0.350179179 1
+4 0.107922284 31
+3 0.131951961 1
+4 0.001523742 9
+3 0.094135896 1
+4 0.001403400 1
+3 0.142636459 1
+4 0.001577172 1
+3 0.094638578 1
+4 0.001459331 1
+4 0.001541516 70
+3 96.145045437 1
+4 0.001549497 73
+3 0.341566794 1
+4 0.001548772 24
+3 0.498636188 1
+4 0.001599858 36
+3 0.081953121 1
+4 0.001685429 80
+3 0.081549192 1
+4 0.001707554 73
+3 0.081462547 1
+4 0.001545412 29
+3 0.081530717 1
+4 0.001500116 28
+3 0.082355147 1
+4 0.001531262 66
+3 0.081767874 1
+4 0.001744160 38
+3 0.789979541 1
+4 0.001606227 4
+3 0.358523227 1
+4 0.001604633 82
+3 0.272270038 1
+4 0.001443841 34
+3 0.332620240 1
+4 0.001770160 29
+3 0.624231837 1
+4 0.001632883 64
+3 1.652451899 1
+4 0.001654788 70
+3 0.734505012 1
+4 0.001562342 93
+3 1.880416967 1
+4 0.001634748 95
+3 0.428543082 1
+4 0.001622603 82
+3 0.984350791 1
+4 0.001579713 61
+3 2.260460546 1
+4 0.001487417 4
+3 1.174634347 1
+4 0.109238624 1
+3 0.122995541 1
+4 0.001469521 9
+3 0.205892618 1
+4 0.001436966 1
+3 0.190721400 1
+4 0.001453656 1
+3 0.230410960 1
+4 0.001382565 1
+4 0.001685329 10
+4 0.001422790 60
+3 497.229682755 1
+4 0.001702369 64
+3 0.373140824 1
+4 0.001650363 53
+3 0.222094912 1
+4 0.108091981 31
+3 0.020290645 1
+4 0.002822676 16
+3 0.429852456 1
+4 0.001597523 4
+3 0.309925354 1
+4 0.004018280 9
+3 0.107818588 1
+4 0.002077103 1
+3 0.157934667 1
+4 0.001607838 1
+3 0.142065202 1
+4 0.001527667 1
+4 0.001288279 70
+3 3.669505533 1
+4 0.001787579 112
+3 0.333964666 1
+4 0.001474371 16
+3 0.350737976 1
+4 0.001566112 4
+3 0.390887715 1
+4 0.002744260 9
+3 0.140604781 1
+4 0.001397456 1
+3 0.142504391 1
+4 0.001401601 1
+3 0.134659340 1
+4 0.001721459 11
+4 0.001419231 60
+3 26.822251418 1
+4 0.001519201 39
+7 0.002500413 TSTP
+7 525.340953853 CONT
+4 0.002230704 7
+4 0.001091722 7
+4 0.001688199 989
+3 11.498496123 1
+4 0.001568418 21
+3 0.270488068 1
+4 0.001494706 53
+3 0.181928393 1
+4 0.108733447 31
+3 0.011220234 1
+4 0.000300299 16
+3 0.186000031 1
+4 0.000368706 15
+3 0.165946487 1
+4 0.001458631 15
+3 0.206296603 1
+4 0.001388705 4
+3 0.398763618 1
+4 0.001733419 9
+3 0.134039163 1
+4 0.001352560 1
+3 0.150563986 1
+4 0.001774664 1
+3 0.118604493 1
+4 0.001889116 1
+4 0.001338740 10
+4 0.001224763 60
+3 39.317057656 1
+4 0.001529292 114
+3 0.526420139 1
+4 0.001762420 24
+3 1.453889027 1
+4 0.001660013 9
+3 0.142498857 1
+4 0.001503141 1
+3 0.158253476 1
+4 0.001575483 1
+3 0.126616056 1
+4 0.001599948 11
+4 0.001609493 60
+3 18.669558170 1
+4 0.001706343 39
+7 0.002530179 TSTP
+7 899.138795805 CONT
+4 0.002583274 7
+4 0.001100897 996
+3 22.924250602 1
+4 0.001534347 39
+7 0.002390422 TSTP
+7 33.389385737 CONT
+4 0.002581218 7
+4 0.001103253 909
+3 1.300181276 1
+4 0.001546257 21
+3 0.222059492 1
+4 0.001546522 53
+3 0.238415013 1
+4 0.109184843 31
+3 0.379042919 1
+4 0.001510807 16
+3 0.728577452 1
+4 0.001415450 15
+3 0.348526297 1
+4 0.001532597 15
+3 0.238429373 1
+4 0.001420890 4
+3 0.494674934 1
+4 0.001382005 9
+3 0.142381471 1
+4 0.001641738 1
+3 0.158314351 1
+4 0.001517022 1
+3 0.110660725 1
+4 0.001756579 11
+4 0.001475116 60
+3 4.469140151 1
+4 0.001770309 114
+3 1.342163731 1
+4 0.001480936 15
+3 0.120459473 1
+4 0.001589178 15
+3 0.356430164 1
+4 0.001456581 4
+3 0.334376125 1
+4 0.001466151 9
+3 0.126632301 1
+4 0.001454071 1
+3 0.126422069 1
+4 0.001605663 1
+3 0.150550710 1
+4 0.001745935 11
+4 0.001392925 60
+3 4.325068886 1
+4 0.001720604 39
+7 0.002486903 TSTP
+7 891.514393588 CONT
+4 0.002117423 7
+4 0.001018707 7
+4 0.001061871 989
+3 0.962925345 1
+4 0.001912621 39
+7 0.002395502 TSTP
+7 223.988309212 CONT
+4 0.004026484 7
+4 0.003277921 909
+3 0.824140274 1
+4 0.001467277 39
+7 0.002166324 TSTP
+7 165.969859204 CONT
+4 0.002685960 7
+4 0.001102062 909
+3 1.204357411 1
+4 0.001592647 39
+7 0.002600499 TSTP
+7 365.952349812 CONT
+4 0.002136278 7
+4 0.001015612 7
+4 0.001090512 902
+3 2.587193742 1
+4 0.001677088 21
+3 0.238212841 1
+4 0.001453711 58
+3 0.182738187 1
+4 0.103895514 31
+3 0.015860486 1
+4 0.001442766 16
+3 0.175100452 1
+4 0.001623353 4
+3 0.317922373 1
+4 0.001434376 9
+3 0.118643218 1
+4 0.001451876 1
+3 0.143568628 1
+4 0.001493967 1
+3 0.133445736 1
+4 0.001666329 11
+4 0.001563117 60
+3 10.886975712 1
+4 0.001788550 107
+3 1.028357489 1
+4 0.001568272 16
+3 0.222512547 1
+4 0.001624668 4
+3 0.422244017 1
+4 0.001640078 9
+3 0.118441936 1
+4 0.001454661 1
+3 0.190559708 1
+4 0.001502192 1
+3 0.063679725 1
+4 0.001555767 1
+4 0.001457386 70
+3 1.371874710 1
+4 0.001718184 39
+7 0.002116473 TSTP
+7 1576.050026568 CONT
+4 0.002127468 7
+4 0.001049282 7
+4 0.001639418 924
+4 0.001391265 65
+3 1.523879474 1
+4 0.001548957 21
+3 0.250838772 1
+4 0.001700133 58
+3 0.230340197 1
+4 0.104563743 31
+3 0.239123573 1
+4 0.001496932 15
+3 0.729816646 1
+4 0.001550162 15
+3 1.187192299 1
+4 0.001481971 9
+3 0.110402577 1
+4 0.001412975 1
+3 0.158515493 1
+4 0.001436916 1
+3 0.094598474 1
+4 0.001499411 1
+4 0.001518196 70
+3 9.365579810 1
+4 0.001831315 77
+3 1.182085879 1
+4 0.001472681 43
+3 0.390399757 1
+4 0.001662683 15
+3 0.184476161 1
+4 0.001397095 15
+3 0.348555334 1
+4 0.001499592 4
+3 0.270318004 1
+4 0.001536837 9
+3 0.150522705 1
+4 0.001440726 1
+3 0.150446974 1
+4 0.001533892 1
+3 0.102548415 1
+4 0.001787650 11
+4 0.001647433 60
+3 2.916930093 1
+4 0.001625608 114
+3 0.214224046 1
+4 0.001634898 15
+3 0.184268399 1
+4 0.001487721 15
+3 0.564812318 1
+4 0.001470741 4
+3 0.342338326 1
+4 0.001475527 9
+3 0.102308113 1
+4 0.001503831 1
+3 0.142560303 1
+4 0.001449421 1
+3 0.086868864 1
+4 0.001684149 11
+4 0.001568817 60
+3 2.300776175 1
+4 0.001568797 65
+3 0.182344003 1
+4 0.001525456 19
+3 0.270439101 1
+4 0.001373955 9
+3 0.126832641 1
+4 0.001451926 1
+3 0.126404321 1
+4 0.001414901 1
+3 0.102456485 1
+4 0.001882240 11
+4 0.001455061 60
+3 2.589161412 1
+4 0.001532046 107
+3 0.310199760 1
+4 0.001553737 9
+3 0.102485115 1
+4 0.001450441 1
+3 0.142337871 1
+4 0.001438495 1
+3 0.102649342 1
+4 0.001621893 11
+4 0.001480321 60
+3 1.557961175 1
+4 0.000416039 39
+7 0.000477545 TSTP
+7 8128.685130733 CONT
+4 0.002319896 7
+4 0.001163737 996
+3 0.290820915 1
+4 0.000331067 9
+3 0.616107098 1
+4 0.001559643 32
+3 0.238160217 1
diff --git a/lib/iolog/regress/corpus/seed/timing/timing.9 b/lib/iolog/regress/corpus/seed/timing/timing.9
new file mode 100644
index 0000000..2d566ba
--- /dev/null
+++ b/lib/iolog/regress/corpus/seed/timing/timing.9
@@ -0,0 +1,416 @@
+4 0.026820058 32
+4 0.001711422 762
+4 0.000339736 53
+3 0.905773982 1
+4 0.000700765 860
+3 0.407034180 1
+4 0.001790364 9
+3 0.510563157 1
+4 0.002274839 29
+3 0.269760922 1
+4 0.002799020 895
+3 0.261256015 1
+4 0.001780719 8
+3 0.285937300 1
+4 0.002033227 1
+3 0.062079447 1
+4 0.001816029 1
+3 0.198257089 1
+4 0.001487481 1
+3 0.128223837 1
+4 0.001924376 1
+3 0.108202451 1
+4 0.002071588 1
+3 0.069737343 1
+4 0.001511027 1
+3 0.174650250 1
+4 0.001780474 1
+3 0.062641443 1
+4 0.002176683 40
+3 0.877270244 1
+4 0.000430823 16
+3 0.289936925 1
+4 0.002316440 15
+3 0.363768246 1
+4 0.001806569 15
+3 0.320027982 1
+4 0.002890541 232
+3 8.683563015 1
+4 0.000607468 172
+3 0.735169546 1
+4 0.000381425 40
+7 0.000714068 TSTP
+7 4.679016635 CONT
+4 0.001236107 7
+4 0.000355486 868
+3 0.486326156 1
+4 0.000368280 16
+3 0.500332044 1
+4 0.001645467 19
+3 0.081610572 1
+4 0.002250109 18
+3 0.081911959 1
+4 0.001516567 17
+3 0.082431635 1
+4 0.001610247 18
+3 0.082161797 1
+4 0.003386766 17
+3 0.080508120 1
+4 0.001542922 18
+3 0.082616917 1
+4 0.001645122 16
+3 0.081939075 1
+4 0.001501656 16
+3 0.511385566 1
+4 0.002390561 15
+3 0.245498856 1
+4 0.001952776 21
+3 0.223035995 1
+4 0.003835676 55
+3 0.186797228 1
+3 0.047844172 1
+4 0.000732686 37
+4 0.000319482 45
+3 0.143148267 1
+4 0.000323210 22
+4 0.000313341 53
+3 0.167541047 1
+4 0.001531157 15
+3 0.126430707 1
+4 0.001452986 73
+3 0.142488895 1
+4 0.001809904 15
+3 0.158496117 1
+4 0.001794434 70
+3 0.206419877 1
+4 0.002088947 16
+3 0.143391926 1
+4 0.000370251 15
+3 0.141381098 1
+4 0.000358046 15
+3 0.191688547 1
+4 0.000427144 46
+3 0.208167967 1
+4 0.102311817 22
+3 0.089357005 1
+4 0.000398479 9
+3 0.127420516 1
+4 0.000380604 1
+3 0.143659945 1
+4 0.000327122 1
+3 0.096070029 1
+4 0.002590102 1
+4 0.002764385 70
+3 0.506400385 1
+4 0.000377794 39
+7 0.000611796 TSTP
+7 2.327330424 CONT
+4 0.000495748 7
+4 0.000441282 7
+4 0.000373026 881
+3 0.735006268 1
+4 0.001573642 9
+3 0.342034557 1
+4 0.000484931 1
+3 0.103713531 1
+4 0.000637123 1
+3 0.183071121 1
+4 0.000357114 1
+3 0.119472186 1
+4 0.000380389 1
+3 0.207816458 1
+4 0.000336918 1
+3 0.079764969 1
+4 0.000396629 1
+3 0.063696314 1
+4 0.001863508 1
+3 0.270414990 1
+4 0.003903627 1
+3 0.276201466 1
+4 0.002198988 1
+3 0.149500975 1
+4 0.001513607 1
+3 0.215266651 1
+4 0.002604633 13
+4 0.002562303 871
+3 0.738702176 1
+4 0.002825906 1002
+3 2.005235450 1
+4 0.004513134 16
+3 0.523238388 1
+4 0.001690173 21
+3 0.293580307 1
+4 0.000509384 59
+3 0.279677930 1
+4 0.106364722 31
+3 0.661572887 1
+4 0.000362005 9
+3 0.127723461 1
+4 0.000433533 1
+3 0.143495220 1
+4 0.000559143 1
+3 0.095541842 1
+4 0.000617635 1
+4 0.000341242 55
+4 0.000258160 15
+3 0.302985707 1
+4 0.000369362 69
+3 0.353548453 1
+4 0.000657140 1249
+3 0.934092779 1
+4 0.002462327 53
+4 0.002104332 869
+3 0.634609718 1
+4 0.000441319 40
+7 0.000443732 TSTP
+7 1.744019170 CONT
+4 0.001795958 7
+4 0.000416107 7
+4 0.000539438 866
+4 0.000421610 53
+3 0.588160440 1
+4 0.001847652 773
+3 0.382350930 1
+4 0.002998357 995
+3 0.212912612 1
+4 0.001679020 988
+3 0.454277400 1
+4 0.000594016 763
+3 0.608608241 1
+4 0.003235459 255
+3 0.619577351 1
+4 0.000444752 12
+3 0.576479814 1
+4 0.003941878 9
+3 0.267043488 1
+4 0.000498001 1
+3 0.143318045 1
+4 0.000893037 1
+3 0.191448484 1
+4 0.000462690 1
+3 0.071606137 1
+4 0.000681691 1
+3 1.055203591 1
+4 0.000340939 1
+3 0.151234915 1
+4 0.000386658 1
+3 0.231980036 1
+4 0.000384274 1
+3 0.224097550 1
+4 0.002980857 1
+3 0.316956963 1
+4 0.002499527 41
+3 0.765698516 1
+4 0.004091634 814
+3 0.811449495 1
+4 0.000770341 56
+3 0.487224212 1
+4 0.000351782 15
+3 4.072509089 1
+3 0.129548871 1
+4 0.002049532 27
+3 0.212133148 1
+4 0.001864670 127
+3 0.293976096 1
+3 0.079927799 1
+4 0.001776949 13
+3 0.456159524 1
+4 0.000484628 16
+3 0.181365177 1
+4 0.000330693 17
+3 0.241967560 1
+4 0.003597134 16
+3 0.242152690 1
+4 0.001952176 17
+3 0.477814310 1
+4 0.000393908 19
+3 1.279717661 1
+4 0.000354247 10
+3 0.161660774 1
+4 0.001684608 1
+3 0.116305564 1
+4 0.000545227 1
+3 0.111377593 1
+4 0.000357819 1
+3 0.121894944 1
+4 0.000372917 1
+3 0.133460281 1
+4 0.000348850 1
+3 0.136188546 1
+4 0.003970087 951
+3 0.563603446 1
+4 0.000905922 1231
+3 0.505214773 1
+4 0.000614466 885
+3 0.693135780 1
+4 0.000384251 10
+3 0.071878551 1
+4 0.000600843 1209
+3 5.919638901 1
+4 0.000618364 947
+3 1.023329385 1
+4 0.000765748 975
+3 0.170239029 1
+4 0.004114269 20
+3 0.944977220 1
+4 0.000813752 923
+3 0.591209323 1
+4 0.000642505 1013
+3 0.855854140 1
+4 0.002983512 910
+3 0.468501621 1
+4 0.001040724 747
+3 0.630997945 1
+4 0.000557718 627
+3 0.568268097 1
+4 0.002969451 604
+3 0.372751868 1
+4 0.003244305 597
+3 1.748017891 1
+4 0.000318899 9
+3 0.112209702 1
+4 0.001585602 1
+3 0.126237191 1
+4 0.001430490 55
+4 0.002520732 19
+3 0.332580571 1
+4 0.003443457 1341
+3 0.555906216 1
+4 0.000345676 9
+3 0.127700075 1
+4 0.000364774 1
+3 0.191792996 1
+4 0.001614682 1
+3 0.430688655 1
+4 0.002797525 1
+4 0.002209299 67
+3 0.578767196 1
+4 0.000721267 664
+3 2.103369630 1
+4 0.000778525 1285
+3 2.487079900 1
+4 0.000722413 1131
+3 1.743405354 1
+4 0.000701480 876
+3 1.551102701 1
+4 0.000365233 15
+3 0.186125212 1
+4 0.002986112 15
+3 0.346545258 1
+3 0.121964530 1
+4 0.000408994 27
+3 0.285901647 1
+4 0.000553920 102
+3 0.287259743 1
+4 0.000348243 15
+3 0.223770096 1
+4 0.000406451 22
+3 0.240395190 1
+4 0.004131039 37
+3 0.203426649 1
+4 0.111240280 31
+3 0.016527422 1
+4 0.001560067 15
+3 0.958779715 1
+4 0.001824469 4
+3 0.014727259 1
+3 0.447093611 1
+3 0.320953147 1
+3 0.070854407 1
+4 0.000362686 27
+3 0.248016393 1
+4 0.001856075 17
+3 0.181888557 1
+4 0.000362541 16
+3 0.095577241 1
+4 0.000446013 16
+3 0.143582924 1
+4 0.000641692 16
+3 0.087370271 1
+4 0.000410273 16
+3 0.255775198 1
+4 0.000349423 30
+3 0.159417098 1
+4 0.101629346 31
+3 0.106812822 1
+4 0.001794174 10
+3 0.150640833 1
+4 0.001973111 1
+3 0.229540234 1
+4 0.002537393 1
+3 0.189596890 1
+4 0.001555707 1
+3 0.166481893 1
+4 0.001832689 1
+3 0.086653686 1
+4 0.002660778 1
+3 0.196235441 1
+4 0.000767079 42
+3 0.319661955 1
+4 0.000409364 29
+4 0.000770391 950
+3 1.230617822 1
+4 0.000497367 10
+3 0.071849269 1
+4 0.001265887 18
+4 0.001255668 849
+3 0.309179080 1
+4 0.001531469 9
+3 0.230462157 1
+4 0.001149025 1
+3 0.158773274 1
+4 0.000864557 1
+3 0.087581903 1
+4 0.002618648 71
+3 0.325070173 1
+4 0.000861044 39
+7 0.001361477 TSTP
+7 2.677917273 CONT
+4 0.001090445 7
+4 0.000695543 914
+3 1.566157098 1
+3 0.130276992 1
+4 0.003990123 27
+3 0.201715122 1
+4 0.000382345 105
+3 0.239728138 1
+4 0.000703854 15
+3 0.183585413 1
+4 0.001608753 22
+3 0.198057579 1
+4 0.000422730 37
+3 0.167314657 1
+4 0.101159452 31
+3 0.043125007 1
+4 0.000340134 16
+3 0.167883234 1
+3 0.056208548 1
+4 0.001792780 28
+3 0.317497649 1
+4 0.000387046 17
+3 0.103776317 1
+4 0.000373976 17
+3 0.135697848 1
+4 0.000467905 17
+3 0.135580381 1
+4 0.000480750 17
+3 0.031618064 1
+4 0.000861943 17
+3 0.110813826 1
+4 0.000349600 17
+3 0.183789669 1
+4 0.000339386 31
+3 0.216650735 1
+4 0.112823566 32
+3 0.174864673 1
+4 0.003063388 10
+3 0.180669765 1
+4 0.001724638 1
+3 0.174368732 1
+4 0.002114123 1
+3 0.134554835 1
+4 0.002041362 1
+4 0.001560387 71
+3 0.980188224 1
+3 0.135913384 1
+4 0.002612273 41
diff --git a/lib/iolog/regress/fuzz/fuzz_iolog_json.c b/lib/iolog/regress/fuzz/fuzz_iolog_json.c
new file mode 100644
index 0000000..b4cfcaf
--- /dev/null
+++ b/lib/iolog/regress/fuzz/fuzz_iolog_json.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_iolog.h>
+#include <sudo_plugin.h>
+#include <sudo_util.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+static FILE *
+open_data(const uint8_t *data, size_t size)
+{
+#ifdef HAVE_FMEMOPEN
+ /* Operate in-memory. */
+ return fmemopen((void *)data, size, "r");
+#else
+ char tempfile[] = "/tmp/json.XXXXXX";
+ size_t nwritten;
+ int fd;
+
+ /* Use (unlinked) temporary file. */
+ fd = mkstemp(tempfile);
+ if (fd == -1)
+ return NULL;
+ unlink(tempfile);
+ nwritten = write(fd, data, size);
+ if (nwritten != size) {
+ close(fd);
+ return NULL;
+ }
+ lseek(fd, 0, SEEK_SET);
+ return fdopen(fd, "r");
+#endif
+}
+
+static int
+fuzz_conversation(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
+{
+ int n;
+
+ for (n = 0; n < num_msgs; n++) {
+ const struct sudo_conv_message *msg = &msgs[n];
+
+ switch (msg->msg_type & 0xff) {
+ case SUDO_CONV_PROMPT_ECHO_ON:
+ case SUDO_CONV_PROMPT_MASK:
+ case SUDO_CONV_PROMPT_ECHO_OFF:
+ /* input not supported */
+ return -1;
+ case SUDO_CONV_ERROR_MSG:
+ case SUDO_CONV_INFO_MSG:
+ /* no output for fuzzers */
+ break;
+ default:
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ struct eventlog *evlog = NULL;
+ FILE *fp;
+
+ initprogname("fuzz_iolog_json");
+ if (getenv("SUDO_FUZZ_VERBOSE") == NULL)
+ sudo_warn_set_conversation(fuzz_conversation);
+
+ fp = open_data(data, size);
+ if (fp == NULL)
+ return 0;
+
+ /* Parsed contents of an log.json file are stored in evlog. */
+ evlog = calloc(1, sizeof(*evlog));
+ if (evlog != NULL) {
+ evlog->runuid = (uid_t)-1;
+ evlog->rungid = (gid_t)-1;
+ evlog->exit_value = -1;
+
+ /* Try to parse buffer as a JSON-format I/O log info file. */
+ iolog_parse_loginfo_json(fp, "fuzz.json", evlog);
+ eventlog_free(evlog);
+ }
+ fclose(fp);
+
+ fflush(stdout);
+
+ return 0;
+}
diff --git a/lib/iolog/regress/fuzz/fuzz_iolog_json.dict b/lib/iolog/regress/fuzz/fuzz_iolog_json.dict
new file mode 100644
index 0000000..2caf63d
--- /dev/null
+++ b/lib/iolog/regress/fuzz/fuzz_iolog_json.dict
@@ -0,0 +1,21 @@
+# I/O log JSON keywords
+"\"columns\""
+"\"command\""
+"\"dumped_core\""
+"\"exit_value\""
+"\"lines\""
+"\"run_time\""
+"\"runargv\""
+"\"runenv\""
+"\"rungid\""
+"\"rungroup\""
+"\"runuid\""
+"\"runuser\""
+"\"runchroot\""
+"\"runcwd\""
+"\"signal\""
+"\"submitcwd\""
+"\"submithost\""
+"\"submituser\""
+"\"timestamp\""
+"\"ttyname\"""
diff --git a/lib/iolog/regress/fuzz/fuzz_iolog_legacy.c b/lib/iolog/regress/fuzz/fuzz_iolog_legacy.c
new file mode 100644
index 0000000..fae456e
--- /dev/null
+++ b/lib/iolog/regress/fuzz/fuzz_iolog_legacy.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_iolog.h>
+#include <sudo_plugin.h>
+#include <sudo_util.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+static FILE *
+open_data(const uint8_t *data, size_t size)
+{
+#ifdef HAVE_FMEMOPEN
+ /* Operate in-memory. */
+ return fmemopen((void *)data, size, "r");
+#else
+ char tempfile[] = "/tmp/legacy.XXXXXX";
+ size_t nwritten;
+ int fd;
+
+ /* Use (unlinked) temporary file. */
+ fd = mkstemp(tempfile);
+ if (fd == -1)
+ return NULL;
+ unlink(tempfile);
+ nwritten = write(fd, data, size);
+ if (nwritten != size) {
+ close(fd);
+ return NULL;
+ }
+ lseek(fd, 0, SEEK_SET);
+ return fdopen(fd, "r");
+#endif
+}
+
+static int
+fuzz_conversation(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
+{
+ int n;
+
+ for (n = 0; n < num_msgs; n++) {
+ const struct sudo_conv_message *msg = &msgs[n];
+
+ switch (msg->msg_type & 0xff) {
+ case SUDO_CONV_PROMPT_ECHO_ON:
+ case SUDO_CONV_PROMPT_MASK:
+ case SUDO_CONV_PROMPT_ECHO_OFF:
+ /* input not supported */
+ return -1;
+ case SUDO_CONV_ERROR_MSG:
+ case SUDO_CONV_INFO_MSG:
+ /* no output for fuzzers */
+ break;
+ default:
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ struct eventlog *evlog = NULL;
+ FILE *fp;
+
+ initprogname("fuzz_iolog_legacy");
+ if (getenv("SUDO_FUZZ_VERBOSE") == NULL)
+ sudo_warn_set_conversation(fuzz_conversation);
+
+ fp = open_data(data, size);
+ if (fp == NULL)
+ return 0;
+
+ /* Parsed contents of an I/O log info file are stored in evlog. */
+ evlog = calloc(1, sizeof(*evlog));
+ if (evlog != NULL) {
+ evlog->runuid = (uid_t)-1;
+ evlog->rungid = (gid_t)-1;
+
+ /* Try to parse buffer as a legacy-format I/O log info file. */
+ iolog_parse_loginfo_legacy(fp, "fuzz.legacy", evlog);
+ eventlog_free(evlog);
+ }
+ fclose(fp);
+ fflush(stdout);
+
+ return 0;
+}
diff --git a/lib/iolog/regress/fuzz/fuzz_iolog_legacy.dict b/lib/iolog/regress/fuzz/fuzz_iolog_legacy.dict
new file mode 100644
index 0000000..d524d49
--- /dev/null
+++ b/lib/iolog/regress/fuzz/fuzz_iolog_legacy.dict
@@ -0,0 +1,42 @@
+# Legacy I/O log info file:
+# timestamp:submit_user:run_user:run_group:tty:lines:columns
+# working directory
+# command [args]
+
+# users and groups
+"millert"
+"root"
+"bin"
+"wheel"
+"operator"
+"testuser"
+"alice"
+"bob"
+"users"
+
+# terminals
+"/dev/console"
+"/dev/tty00"
+"/dev/tty01"
+"/dev/pts/0"
+"/dev/pts/1"
+"/dev/ttyp2"
+"/dev/ttyp3"
+
+# directories
+"/root"
+"/home/millert"
+"/home/alice"
+"/home/bob"
+"/tmp"
+"/usr/local"
+"/usr/src"
+
+# commands
+"/bin/ls"
+"/usr/bin/id -u"
+"/usr/bin/su -"
+"/usr/bin/mailq"
+"/usr/bin/make -C /usr/src/usr.bin/sort install"
+"/usr/bin/apt update"
+"/usr/bin/rpm -e sudo"
diff --git a/lib/iolog/regress/fuzz/fuzz_iolog_timing.c b/lib/iolog/regress/fuzz/fuzz_iolog_timing.c
new file mode 100644
index 0000000..87a5fcf
--- /dev/null
+++ b/lib/iolog/regress/fuzz/fuzz_iolog_timing.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_iolog.h>
+#include <sudo_plugin.h>
+#include <sudo_util.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+static int
+fuzz_conversation(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
+{
+ int n;
+
+ for (n = 0; n < num_msgs; n++) {
+ const struct sudo_conv_message *msg = &msgs[n];
+
+ switch (msg->msg_type & 0xff) {
+ case SUDO_CONV_PROMPT_ECHO_ON:
+ case SUDO_CONV_PROMPT_MASK:
+ case SUDO_CONV_PROMPT_ECHO_OFF:
+ /* input not supported */
+ return -1;
+ case SUDO_CONV_ERROR_MSG:
+ case SUDO_CONV_INFO_MSG:
+ /* no output for fuzzers */
+ break;
+ default:
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ struct iolog_file iolog_file = { true };
+ struct timing_closure closure;
+ char logdir[] = "/tmp/timing.XXXXXX";
+ int dfd = -1, fd = -1;
+
+ initprogname("fuzz_iolog_timing");
+ if (getenv("SUDO_FUZZ_VERBOSE") == NULL)
+ sudo_warn_set_conversation(fuzz_conversation);
+
+ /* I/O logs consist of multiple files in a directory. */
+ if (mkdtemp(logdir) == NULL)
+ return 0;
+
+ /* Create a timing file from the supplied data. */
+ dfd = open(logdir, O_RDONLY);
+ if (dfd == -1)
+ goto cleanup;
+
+ fd = openat(dfd, "timing", O_WRONLY|O_CREAT|O_EXCL, S_IRWXU);
+ if (fd == -1)
+ goto cleanup;
+
+ if (write(fd, data, size) != (ssize_t)size)
+ goto cleanup;
+ close(fd);
+ fd = -1;
+
+ /* Open the timing file we wrote and try to parse it. */
+ if (!iolog_open(&iolog_file, dfd, IOFD_TIMING, "r"))
+ goto cleanup;
+
+ memset(&closure, 0, sizeof(closure));
+ closure.decimal = ".";
+ for (;;) {
+ if (iolog_read_timing_record(&iolog_file, &closure) != 0)
+ break;
+ }
+ iolog_close(&iolog_file, NULL);
+
+cleanup:
+ if (dfd != -1) {
+ if (fd != -1)
+ close(fd);
+ unlinkat(dfd, "timing", 0);
+ close(dfd);
+ }
+ rmdir(logdir);
+ fflush(stdout);
+
+ return 0;
+}
+
+/* STUB */
+bool
+iolog_swapids(bool restore)
+{
+ return false;
+}
diff --git a/lib/iolog/regress/fuzz/fuzz_iolog_timing.dict b/lib/iolog/regress/fuzz/fuzz_iolog_timing.dict
new file mode 100644
index 0000000..42bdeb5
--- /dev/null
+++ b/lib/iolog/regress/fuzz/fuzz_iolog_timing.dict
@@ -0,0 +1,89 @@
+# I/O log timing lines are formatted as:
+# [0-4] sleep_time num_bytes
+# 5 sleep_time lines cols
+# 7 sleep_time signum|sigabbrev
+
+# Signal abbreviations
+"ABRT"
+"ALRM"
+"BUS"
+"CANCEL"
+"CHLD"
+"CLD"
+"CONT"
+"CONT"
+"EMT"
+"FPE"
+"FREEZE"
+"HUP"
+"ILL"
+"INFO"
+"INT"
+"IO"
+"IOT"
+"KILL"
+"LOST"
+"LWP"
+"PIPE"
+"POLL"
+"PROF"
+"PWR"
+"QUIT"
+"SEGV"
+"STKFLT"
+"STOP"
+"STOP"
+"SYS"
+"TERM"
+"THAW"
+"TRAP"
+"TSTP"
+"TSTP"
+"TTIN"
+"TTIN"
+"TTOU"
+"TTOU"
+"UNUSED"
+"URG"
+"USR1"
+"USR2"
+"VTALRM"
+"WAITING"
+"WINCH"
+"XCPU"
+"XFSZ"
+
+# Signal numbers, 0-32
+"0"
+"1"
+"2"
+"3"
+"4"
+"5"
+"6"
+"7"
+"8"
+"9"
+"10"
+"11"
+"12"
+"13"
+"14"
+"15"
+"16"
+"17"
+"18"
+"19"
+"20"
+"21"
+"22"
+"23"
+"24"
+"25"
+"26"
+"27"
+"28"
+"29"
+"30"
+"31"
+"32"
diff --git a/lib/iolog/regress/host_port/host_port_test.c b/lib/iolog/regress/host_port/host_port_test.c
new file mode 100644
index 0000000..128e0f9
--- /dev/null
+++ b/lib/iolog/regress/host_port/host_port_test.c
@@ -0,0 +1,158 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <time.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_iolog.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/*
+ * Test that iolog_parse_host_port() works as expected.
+ */
+
+struct host_port_test {
+ const char *str; /* input string */
+ const char *host; /* parsed host */
+ const char *port; /* parsed port */
+ bool tls; /* parsed TLS flag */
+ const char *defport; /* default port */
+ const char *defport_tls; /* default port */
+ bool ret; /* return value */
+};
+
+static struct host_port_test test_data[] = {
+ /* No TLS */
+ { "xerxes", "xerxes", "12345", false, "12345", NULL, true },
+ { "xerxes:12345", "xerxes", "12345", false, "67890", NULL, true },
+ { "127.0.0.1", "127.0.0.1", "12345", false, "12345", NULL, true },
+ { "127.0.0.1:12345", "127.0.0.1", "12345", false, "67890", NULL, true },
+ { "[::1]", "::1", "12345", false, "12345", NULL, true },
+ { "[::1]:12345", "::1", "12345", false, "67890", NULL, true },
+
+ /* With TLS */
+ { "xerxes(tls)", "xerxes", "12345", true, "5678", "12345", true },
+ { "xerxes:12345(tls)", "xerxes", "12345", true, "5678", "67890", true },
+ { "127.0.0.1(tls)", "127.0.0.1", "12345", true, "5678", "12345", true },
+ { "127.0.0.1:12345(tls)", "127.0.0.1", "12345", true, "5678", "67890", true },
+ { "[::1](tls)", "::1", "12345", true, "5678", "12345", true },
+ { "[::1]:12345(tls)", "::1", "12345", true, "5678", "67890", true },
+
+ /* Errors */
+ { "xerxes:", NULL, NULL, false, "12345", NULL, false }, /* missing port */
+ { "127.0.0.1:", NULL, NULL, false, "12345", NULL, false }, /* missing port */
+ { "[::1:12345", NULL, NULL, false, "67890", NULL, false }, /* missing bracket */
+ { "[::1]:", NULL, NULL, false, "12345", NULL, false }, /* missing port */
+ { NULL }
+};
+
+int
+main(int argc, char *argv[])
+{
+ int ch, i, errors = 0, ntests = 0;
+ char *host, *port, *copy = NULL;
+ bool ret, tls;
+
+ initprogname(argc > 0 ? argv[0] : "host_port_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ for (i = 0; test_data[i].str != NULL; i++) {
+ host = port = NULL;
+ tls = false;
+ free(copy);
+ if ((copy = strdup(test_data[i].str)) == NULL)
+ sudo_fatal_nodebug(NULL);
+
+ ntests++;
+ ret = iolog_parse_host_port(copy, &host, &port, &tls,
+ test_data[i].defport, test_data[i].defport_tls);
+ if (ret != test_data[i].ret) {
+ sudo_warnx_nodebug("test #%d: %s: returned %s, expected %s",
+ ntests, test_data[i].str, ret ? "true" : "false",
+ test_data[i].ret ? "true" : "false");
+ errors++;
+ continue;
+ }
+ if (!ret)
+ continue;
+
+ if (host == NULL) {
+ sudo_warnx_nodebug("test #%d: %s: NULL host",
+ ntests, test_data[i].str);
+ errors++;
+ continue;
+ }
+ if (strcmp(host, test_data[i].host) != 0) {
+ sudo_warnx_nodebug("test #%d: %s: bad host, expected %s, got %s",
+ ntests, test_data[i].str, test_data[i].host, host);
+ errors++;
+ continue;
+ }
+ if (port == NULL) {
+ sudo_warnx_nodebug("test #%d: %s: NULL port",
+ ntests, test_data[i].str);
+ errors++;
+ continue;
+ }
+ if (strcmp(port, test_data[i].port) != 0) {
+ sudo_warnx_nodebug("test #%d: %s: bad port, expected %s, got %s",
+ ntests, test_data[i].str, test_data[i].port, port);
+ errors++;
+ continue;
+ }
+ if (tls != test_data[i].tls) {
+ sudo_warnx_nodebug("test #%d: %s: bad tls, expected %s, got %s",
+ ntests, test_data[i].str, test_data[i].tls ? "true" : "false",
+ tls ? "true" : "false");
+ errors++;
+ continue;
+ }
+ }
+ free(copy);
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+ return errors;
+}
diff --git a/lib/iolog/regress/iolog_filter/check_iolog_filter.c b/lib/iolog/regress/iolog_filter/check_iolog_filter.c
new file mode 100644
index 0000000..bb51420
--- /dev/null
+++ b/lib/iolog/regress/iolog_filter/check_iolog_filter.c
@@ -0,0 +1,203 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_fatal.h>
+
+#include <sudo_iolog.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+int
+main(int argc, char *argv[])
+{
+ int dfd = -1, ttyin_fd = -1, ttyout_fd = -1, ttyin_ok_fd = -1;
+ int ch, i, ntests = 0, errors = 0;
+ void *passprompt_regex = NULL;
+
+ initprogname(argc > 0 ? argv[0] : "check_iolog_filter");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v] iolog_dir ...\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ passprompt_regex = iolog_pwfilt_alloc();
+ if (passprompt_regex == NULL)
+ sudo_fatalx("unable to allocate memory");
+ if (!iolog_pwfilt_add(passprompt_regex, "(?i)password[: ]*"))
+ exit(1);
+
+ for (i = 0; i < argc; i++) {
+ struct iolog_file iolog_timing = { true };
+ struct timing_closure timing;
+ const char *logdir = argv[i];
+ char tbuf[8192], fbuf[8192];
+ ssize_t nread;
+
+ ntests++;
+
+ /* I/O logs consist of multiple files in a directory. */
+ dfd = open(logdir, O_RDONLY);
+ if (dfd == -1) {
+ sudo_warn("%s", logdir);
+ errors++;
+ continue;
+ }
+
+ if (!iolog_open(&iolog_timing, dfd, IOFD_TIMING, "r")) {
+ sudo_warn("timing");
+ errors++;
+ goto next;
+ }
+
+ ttyout_fd = openat(dfd, "ttyout", O_RDONLY, 0644);
+ if (ttyout_fd == -1) {
+ sudo_warn("ttyout");
+ errors++;
+ goto next;
+ }
+
+ ttyin_fd = openat(dfd, "ttyin", O_RDONLY, 0644);
+ if (ttyin_fd == -1) {
+ sudo_warn("ttyin");
+ errors++;
+ goto next;
+ }
+
+ ttyin_ok_fd = openat(dfd, "ttyin.filtered", O_RDONLY, 0644);
+ if (ttyin_ok_fd == -1) {
+ sudo_warn("ttyin.filtered");
+ errors++;
+ goto next;
+ }
+
+ memset(&timing, 0, sizeof(timing));
+ timing.decimal = ".";
+ for (;;) {
+ char *newbuf = NULL;
+ const char *name;
+ int fd;
+
+ if (iolog_read_timing_record(&iolog_timing, &timing) != 0)
+ break;
+
+ switch (timing.event) {
+ case IO_EVENT_TTYOUT:
+ fd = ttyout_fd;
+ name = "ttyout";
+ break;
+ case IO_EVENT_TTYIN:
+ fd = ttyin_fd;
+ name = "ttyin";
+ break;
+ default:
+ continue;
+ }
+
+ if (timing.u.nbytes > sizeof(tbuf)) {
+ sudo_warn("buffer too small, %zu > %zu", timing.u.nbytes,
+ sizeof(tbuf));
+ errors++;
+ continue;
+ }
+
+ nread = read(fd, tbuf, timing.u.nbytes);
+ if ((size_t)nread != timing.u.nbytes) {
+ if (nread == -1)
+ sudo_warn("%s/%s", argv[i], name);
+ else
+ sudo_warnx("%s/%s: short read", argv[i], name);
+ errors++;
+ continue;
+ }
+
+ /* Apply filter. */
+ if (!iolog_pwfilt_run(passprompt_regex, timing.event, tbuf,
+ timing.u.nbytes, &newbuf)) {
+ errors++;
+ continue;
+ }
+
+ if (timing.event == IO_EVENT_TTYIN) {
+ nread = read(ttyin_ok_fd, fbuf, timing.u.nbytes);
+ if (nread == -1) {
+ if (nread == -1)
+ sudo_warn("%s/ttyin.filtered", argv[i]);
+ else
+ sudo_warnx("%s/ttyin.filtered: short read", argv[i]);
+ errors++;
+ free(newbuf);
+ break;
+ }
+ if (memcmp(fbuf, newbuf ? newbuf : tbuf, timing.u.nbytes) != 0) {
+ sudo_warnx("%s: ttyin mismatch at byte %lld", argv[i],
+ (long long)lseek(fd, 0, SEEK_CUR));
+ errors++;
+ free(newbuf);
+ break;
+ }
+ }
+
+ free(newbuf);
+ }
+next:
+ if (ttyin_fd != -1) {
+ close(ttyin_fd);
+ ttyin_fd = -1;
+ }
+ if (ttyin_ok_fd != -1) {
+ close(ttyin_ok_fd);
+ ttyin_ok_fd = -1;
+ }
+ if (dfd != -1) {
+ close(dfd);
+ dfd = -1;
+ }
+ if (iolog_timing.enabled)
+ iolog_close(&iolog_timing, NULL);
+ }
+ iolog_pwfilt_free(passprompt_regex);
+
+ if (ntests != 0) {
+ printf("iolog_filter: %d test%s run, %d errors, %d%% success rate\n",
+ ntests, ntests == 1 ? "" : "s", errors,
+ (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
diff --git a/lib/iolog/regress/iolog_filter/test1/log b/lib/iolog/regress/iolog_filter/test1/log
new file mode 100644
index 0000000..551adfb
--- /dev/null
+++ b/lib/iolog/regress/iolog_filter/test1/log
@@ -0,0 +1,3 @@
+1645151020:millert:root::/dev/ttypb:24:80
+/home/millert
+/usr/bin/passwd
diff --git a/lib/iolog/regress/iolog_filter/test1/timing b/lib/iolog/regress/iolog_filter/test1/timing
new file mode 100644
index 0000000..3a62388
--- /dev/null
+++ b/lib/iolog/regress/iolog_filter/test1/timing
@@ -0,0 +1,44 @@
+4 0.087089703 32
+4 0.000503221 13
+3 1.617732029 1
+3 0.671818399 1
+3 0.632182533 1
+3 0.135484597 1
+3 0.120171445 1
+3 0.120200768 1
+3 0.239782513 1
+3 0.064059449 1
+3 0.184048364 1
+3 0.135992479 1
+3 0.167905298 1
+3 0.087948033 1
+3 0.135913060 1
+3 0.136306311 1
+3 0.279830387 1
+3 0.280221744 1
+4 0.000453682 2
+4 0.001188404 20
+3 0.678534827 1
+3 1.912119627 1
+3 0.303804149 1
+3 0.071831900 1
+3 0.248608651 1
+3 0.088758738 1
+3 0.262821628 1
+3 0.111839737 1
+3 0.184326849 1
+3 0.119709565 1
+3 0.184446495 1
+3 0.089439595 1
+3 0.150353799 1
+3 0.152035883 1
+3 0.392237165 1
+3 0.183498720 1
+3 0.136099560 1
+3 0.256165394 1
+4 0.000392254 2
+4 0.000348360 35
+4 0.000330782 13
+3 0.871580665 1
+4 0.000434371 2
+4 0.001150945 23
diff --git a/lib/iolog/regress/iolog_filter/test1/ttyin b/lib/iolog/regress/iolog_filter/test1/ttyin
new file mode 100644
index 0000000..5a2067d
--- /dev/null
+++ b/lib/iolog/regress/iolog_filter/test1/ttyin
@@ -0,0 +1 @@
+A new password? A bad password...  \ No newline at end of file
diff --git a/lib/iolog/regress/iolog_filter/test1/ttyin.filtered b/lib/iolog/regress/iolog_filter/test1/ttyin.filtered
new file mode 100644
index 0000000..d4943b3
--- /dev/null
+++ b/lib/iolog/regress/iolog_filter/test1/ttyin.filtered
@@ -0,0 +1 @@
+*************** ***************** * \ No newline at end of file
diff --git a/lib/iolog/regress/iolog_filter/test1/ttyout b/lib/iolog/regress/iolog_filter/test1/ttyout
new file mode 100644
index 0000000..bac1f87
--- /dev/null
+++ b/lib/iolog/regress/iolog_filter/test1/ttyout
@@ -0,0 +1,7 @@
+Changing password for millert.
+New password:
+Retype new password:
+Mismatch; try again, EOF to quit.
+New password:
+
+Password unchanged.
diff --git a/lib/iolog/regress/iolog_filter/test2/log b/lib/iolog/regress/iolog_filter/test2/log
new file mode 100644
index 0000000..8790573
--- /dev/null
+++ b/lib/iolog/regress/iolog_filter/test2/log
@@ -0,0 +1,3 @@
+1645153850:millert:millert::/dev/ttypb:24:80
+/home/millert
+/usr/bin/su testdude
diff --git a/lib/iolog/regress/iolog_filter/test2/timing b/lib/iolog/regress/iolog_filter/test2/timing
new file mode 100644
index 0000000..7e6b1cc
--- /dev/null
+++ b/lib/iolog/regress/iolog_filter/test2/timing
@@ -0,0 +1,73 @@
+4 0.077895153 9
+3 9.876530326 1
+3 0.191980568 1
+3 0.168017746 1
+3 0.088081740 1
+3 0.183886638 1
+3 0.071966892 1
+3 0.175772878 1
+3 0.672270691 1
+4 0.000336085 2
+4 0.022264031 8
+3 4.721817713 1
+4 0.001379444 1
+3 0.086406844 1
+4 0.000383615 1
+3 0.055583229 1
+4 0.000353543 1
+3 0.079726966 1
+4 0.000336390 1
+3 0.063626746 1
+4 0.000719018 1
+3 0.135204338 1
+4 0.000342720 1
+3 0.095976209 1
+4 0.000338049 1
+3 0.047259669 1
+4 0.000339501 1
+3 0.399809817 1
+4 0.000345392 1
+3 0.111587761 1
+4 0.000366589 1
+3 0.087582640 1
+4 0.000328160 1
+3 0.480159500 1
+4 0.000370778 3
+3 0.143285883 1
+4 0.000332529 3
+3 0.135841236 1
+4 0.000343729 3
+3 0.223401313 1
+4 0.000329496 1
+3 0.063760060 1
+4 0.000382349 1
+3 0.087442363 1
+4 0.000345787 1
+3 0.095598655 1
+4 0.000343712 1
+3 0.560106197 1
+4 0.000405183 3
+3 0.151363786 1
+4 0.000345085 3
+3 0.167809002 1
+4 0.000326037 3
+3 0.135471962 1
+4 0.000378004 3
+3 0.111681517 1
+4 0.000329093 1
+3 0.127537491 1
+4 0.000355403 1
+3 0.103896235 1
+4 0.000320608 1
+3 0.095563437 1
+4 0.000327463 1
+3 0.087808248 1
+4 0.000321244 1
+3 0.503531970 1
+4 0.000338699 1
+3 1.383887942 1
+4 0.000324499 3
+4 0.000334583 11
+4 0.000324866 8
+3 0.999440679 1
+4 0.000365851 5
diff --git a/lib/iolog/regress/iolog_filter/test2/ttyin b/lib/iolog/regress/iolog_filter/test2/ttyin
new file mode 100644
index 0000000..29482c0
--- /dev/null
+++ b/lib/iolog/regress/iolog_filter/test2/ttyin
@@ -0,0 +1 @@
+test123 echo hi ereherethere!  \ No newline at end of file
diff --git a/lib/iolog/regress/iolog_filter/test2/ttyin.filtered b/lib/iolog/regress/iolog_filter/test2/ttyin.filtered
new file mode 100644
index 0000000..e3c303d
--- /dev/null
+++ b/lib/iolog/regress/iolog_filter/test2/ttyin.filtered
@@ -0,0 +1 @@
+******* echo hi ereherethere!  \ No newline at end of file
diff --git a/lib/iolog/regress/iolog_filter/test2/ttyout b/lib/iolog/regress/iolog_filter/test2/ttyout
new file mode 100644
index 0000000..dbb7124
--- /dev/null
+++ b/lib/iolog/regress/iolog_filter/test2/ttyout
@@ -0,0 +1,4 @@
+Password:
+xerxes$ echo hi ere   here    there!
+hi there!
+xerxes$ ^D
diff --git a/lib/iolog/regress/iolog_filter/test3/log b/lib/iolog/regress/iolog_filter/test3/log
new file mode 100644
index 0000000..f0500f4
--- /dev/null
+++ b/lib/iolog/regress/iolog_filter/test3/log
@@ -0,0 +1,3 @@
+1645201461:millert:root::/dev/ttyp0:24:80
+/home/millert
+/usr/bin/ssh -oPubkeyAuthentication=no localhost
diff --git a/lib/iolog/regress/iolog_filter/test3/timing b/lib/iolog/regress/iolog_filter/test3/timing
new file mode 100644
index 0000000..03b67f4
--- /dev/null
+++ b/lib/iolog/regress/iolog_filter/test3/timing
@@ -0,0 +1,54 @@
+4 0.158768144 1
+4 0.000406264 27
+3 4.390837642 1
+3 0.119705081 1
+3 0.175600726 1
+3 0.064357615 1
+3 0.239945395 1
+3 0.088142451 1
+3 0.143665762 1
+3 0.071941169 1
+3 0.208359675 1
+3 0.145706215 1
+3 0.302231926 1
+3 0.079805215 1
+3 0.112114024 1
+3 0.143802378 1
+3 0.160033289 1
+4 0.000416283 2
+4 0.042939142 40
+4 0.000399448 27
+3 1.084753026 1
+3 0.087720859 1
+3 0.215896027 1
+3 0.167921572 1
+3 0.304253899 1
+3 0.103807201 1
+3 0.191962088 1
+3 0.071989566 1
+3 0.296183440 1
+3 0.162262688 1
+3 0.125661454 1
+3 0.192164590 1
+4 0.000394039 2
+4 0.034617321 40
+4 0.000414822 27
+3 0.796676353 1
+3 0.119589531 1
+3 0.120189440 1
+3 0.080002264 1
+3 0.120104599 1
+3 0.087897523 1
+3 0.088072936 1
+3 0.111980459 1
+3 0.064099904 1
+3 0.440166638 1
+3 0.159957933 1
+3 0.063988834 1
+3 0.247906778 1
+3 0.167767797 1
+3 0.151961605 1
+3 0.176237322 1
+3 0.368288839 1
+4 0.000364019 2
+4 0.034413644 79
diff --git a/lib/iolog/regress/iolog_filter/test3/ttyin b/lib/iolog/regress/iolog_filter/test3/ttyin
new file mode 100644
index 0000000..224e0b4
--- /dev/null
+++ b/lib/iolog/regress/iolog_filter/test3/ttyin
@@ -0,0 +1 @@
+not a password nope, sorry try again please \ No newline at end of file
diff --git a/lib/iolog/regress/iolog_filter/test3/ttyin.filtered b/lib/iolog/regress/iolog_filter/test3/ttyin.filtered
new file mode 100644
index 0000000..bc6dfb5
--- /dev/null
+++ b/lib/iolog/regress/iolog_filter/test3/ttyin.filtered
@@ -0,0 +1 @@
+************** *********** **************** \ No newline at end of file
diff --git a/lib/iolog/regress/iolog_filter/test3/ttyout b/lib/iolog/regress/iolog_filter/test3/ttyout
new file mode 100644
index 0000000..b6befb9
--- /dev/null
+++ b/lib/iolog/regress/iolog_filter/test3/ttyout
@@ -0,0 +1,6 @@
+ root@localhost's password:
+Permission denied, please try again.
+ root@localhost's password:
+Permission denied, please try again.
+ root@localhost's password:
+root@localhost: Permission denied (publickey,password,keyboard-interactive).
diff --git a/lib/iolog/regress/iolog_mkpath/check_iolog_mkpath.c b/lib/iolog/regress/iolog_mkpath/check_iolog_mkpath.c
new file mode 100644
index 0000000..c11992f
--- /dev/null
+++ b/lib/iolog/regress/iolog_mkpath/check_iolog_mkpath.c
@@ -0,0 +1,115 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_fatal.h>
+#include <sudo_iolog.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+static const char *test_paths[] = {
+ "testdir/a/b/c/user", /* create new */
+ "testdir/a/b/c/user", /* open existing */
+ "testdir/a/b/c/user.XXXXXX", /* mkdtemp new */
+ NULL
+};
+
+static void
+test_iolog_mkpath(const char *testdir, int *ntests, int *nerrors)
+{
+ const char **tp;
+ char *path;
+
+ iolog_set_owner(geteuid(), getegid());
+
+ for (tp = test_paths; *tp != NULL; tp++) {
+ if (asprintf(&path, "%s/%s", testdir, *tp) == -1)
+ sudo_fatalx("unable to allocate memory");
+
+ (*ntests)++;
+ if (!iolog_mkpath(path)) {
+ sudo_warnx("unable to mkpath %s", path);
+ (*nerrors)++;
+ }
+ free(path);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ char testdir[] = "mkpath.XXXXXX";
+ const char *rmargs[] = { "rm", "-rf", NULL, NULL };
+ int ch, status, ntests = 0, errors = 0;
+
+ initprogname(argc > 0 ? argv[0] : "check_iolog_mkpath");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (mkdtemp(testdir) == NULL)
+ sudo_fatal("unable to create test dir");
+ rmargs[2] = testdir;
+
+ test_iolog_mkpath(testdir, &ntests, &errors);
+
+ if (ntests != 0) {
+ printf("iolog_mkpath: %d test%s run, %d errors, %d%% success rate\n",
+ ntests, ntests == 1 ? "" : "s", errors,
+ (ntests - errors) * 100 / ntests);
+ }
+
+ /* Clean up (avoid running via shell) */
+ switch (fork()) {
+ case -1:
+ sudo_warn("fork");
+ _exit(1);
+ case 0:
+ execvp("rm", (char **)rmargs);
+ _exit(1);
+ default:
+ wait(&status);
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+ errors++;
+ break;
+ }
+
+ return errors;
+}
diff --git a/lib/iolog/regress/iolog_path/check_iolog_path.c b/lib/iolog/regress/iolog_path/check_iolog_path.c
new file mode 100644
index 0000000..882135a
--- /dev/null
+++ b/lib/iolog/regress/iolog_path/check_iolog_path.c
@@ -0,0 +1,296 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011-2013 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <time.h>
+#include <unistd.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_fatal.h>
+#include <sudo_iolog.h>
+
+static struct iolog_escape_data {
+ char sessid[7];
+ char *user;
+ char *group;
+ char *runas_user;
+ char *runas_group;
+ char *host;
+ char *command;
+} escape_data;
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+sudo_noreturn static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s datafile\n", getprogname());
+ exit(EXIT_FAILURE);
+}
+
+static void
+reset_escape_data(struct iolog_escape_data *data)
+{
+ free(data->user);
+ free(data->group);
+ free(data->runas_user);
+ free(data->runas_group);
+ free(data->host);
+ free(data->command);
+ memset(data, 0, sizeof(*data));
+}
+
+static size_t
+fill_seq(char *str, size_t strsize, void *unused)
+{
+ int len;
+
+ /* Path is of the form /var/log/sudo-io/00/00/01. */
+ len = snprintf(str, strsize, "%c%c/%c%c/%c%c", escape_data.sessid[0],
+ escape_data.sessid[1], escape_data.sessid[2], escape_data.sessid[3],
+ escape_data.sessid[4], escape_data.sessid[5]);
+ if (len < 0)
+ return strsize; /* handle non-standard snprintf() */
+ return (size_t)len;
+}
+
+static size_t
+fill_user(char *str, size_t strsize, void *unused)
+{
+ return strlcpy(str, escape_data.user, strsize);
+}
+
+static size_t
+fill_group(char *str, size_t strsize, void *unused)
+{
+ return strlcpy(str, escape_data.group, strsize);
+}
+
+static size_t
+fill_runas_user(char *str, size_t strsize, void *unused)
+{
+ return strlcpy(str, escape_data.runas_user, strsize);
+}
+
+static size_t
+fill_runas_group(char *str, size_t strsize, void *unused)
+{
+ return strlcpy(str, escape_data.runas_group, strsize);
+}
+
+static size_t
+fill_hostname(char *str, size_t strsize, void *unused)
+{
+ return strlcpy(str, escape_data.host, strsize);
+}
+
+static size_t
+fill_command(char *str, size_t strsize, void *unused)
+{
+ return strlcpy(str, escape_data.command, strsize);
+}
+
+/* Note: "seq" must be first in the list. */
+static struct iolog_path_escape path_escapes[] = {
+ { "seq", fill_seq },
+ { "user", fill_user },
+ { "group", fill_group },
+ { "runas_user", fill_runas_user },
+ { "runas_group", fill_runas_group },
+ { "hostname", fill_hostname },
+ { "command", fill_command },
+ { NULL, NULL }
+};
+
+static int
+do_check(char *dir_in, char *file_in, char *tdir_out, char *tfile_out)
+{
+ char dir[PATH_MAX], dir_out[PATH_MAX] = "";
+ char file[PATH_MAX], file_out[PATH_MAX] = "";
+ int error = 0;
+ struct tm tm;
+ time_t now;
+ size_t len;
+
+ /*
+ * Expand any strftime(3) escapes
+ * XXX - want to pass tm to expand_iolog_path
+ */
+ time(&now);
+ if (localtime_r(&now, &tm) == NULL)
+ sudo_fatal("localtime_r");
+ if (tdir_out[0] != '\0') {
+ len = strftime(dir_out, sizeof(dir_out), tdir_out, &tm);
+ if (len == 0 || dir_out[sizeof(dir_out) - 1] != '\0')
+ sudo_fatalx("dir_out: strftime overflow");
+ }
+ if (tfile_out[0] != '\0') {
+ len = strftime(file_out, sizeof(file_out), tfile_out, &tm);
+ if (len == 0 || file_out[sizeof(file_out) - 1] != '\0')
+ sudo_fatalx("file_out: strftime overflow");
+ }
+
+ if (!expand_iolog_path(dir_in, dir, sizeof(dir), &path_escapes[1], NULL))
+ sudo_fatalx("unable to expand I/O log dir");
+ if (!expand_iolog_path(file_in, file, sizeof(file), &path_escapes[0], dir))
+ sudo_fatalx("unable to expand I/O log file");
+
+ if (strcmp(dir, dir_out) != 0) {
+ sudo_warnx("%s: expected %s, got %s", dir_in, dir_out, dir);
+ error = 1;
+ }
+ if (strcmp(file, file_out) != 0) {
+ sudo_warnx("%s: expected %s, got %s", file_in, file_out, file);
+ error = 1;
+ }
+
+ return error;
+}
+
+#define MAX_STATE 12
+
+int
+main(int argc, char *argv[])
+{
+ size_t len;
+ FILE *fp;
+ char line[2048];
+ char *file_in = NULL, *file_out = NULL;
+ char *dir_in = NULL, *dir_out = NULL;
+ int ch, state = 0, errors = 0, ntests = 0;
+
+ initprogname(argc > 0 ? argv[0] : "check_iolog_path");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v] data\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1)
+ usage();
+
+ fp = fopen(argv[0], "r");
+ if (fp == NULL)
+ sudo_fatalx("unable to open %s", argv[0]);
+
+ /*
+ * Input consists of 12 lines:
+ * sequence number
+ * user name
+ * user gid
+ * runas user name
+ * runas gid
+ * hostname [short form]
+ * command
+ * dir [with escapes]
+ * file [with escapes]
+ * expanded dir
+ * expanded file
+ * empty line
+ */
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ len = strcspn(line, "\n");
+ line[len] = '\0';
+
+ switch (state) {
+ case 0:
+ strlcpy(escape_data.sessid, line, sizeof(escape_data.sessid));
+ break;
+ case 1:
+ if ((escape_data.user = strdup(line)) == NULL)
+ sudo_fatal(NULL);
+ break;
+ case 2:
+ if ((escape_data.group = strdup(line)) == NULL)
+ sudo_fatal(NULL);
+ break;
+ case 3:
+ if ((escape_data.runas_user = strdup(line)) == NULL)
+ sudo_fatal(NULL);
+ break;
+ case 4:
+ if ((escape_data.runas_group = strdup(line)) == NULL)
+ sudo_fatal(NULL);
+ break;
+ case 5:
+ if ((escape_data.host = strdup(line)) == NULL)
+ sudo_fatal(NULL);
+ break;
+ case 6:
+ if ((escape_data.command = strdup(line)) == NULL)
+ sudo_fatal(NULL);
+ break;
+ case 7:
+ if (dir_in != NULL)
+ free(dir_in);
+ dir_in = strdup(line);
+ break;
+ case 8:
+ if (file_in != NULL)
+ free(file_in);
+ file_in = strdup(line);
+ break;
+ case 9:
+ if (dir_out != NULL)
+ free(dir_out);
+ dir_out = strdup(line);
+ break;
+ case 10:
+ if (file_out != NULL)
+ free(file_out);
+ file_out = strdup(line);
+ break;
+ case 11:
+ errors += do_check(dir_in, file_in, dir_out, file_out);
+ ntests++;
+ reset_escape_data(&escape_data);
+ break;
+ default:
+ sudo_fatalx("internal error, invalid state %d", state);
+ }
+ state = (state + 1) % MAX_STATE;
+ }
+ free(dir_in);
+ free(dir_out);
+ free(file_in);
+ free(file_out);
+
+ if (ntests != 0) {
+ printf("iolog_path: %d test%s run, %d errors, %d%% success rate\n",
+ ntests, ntests == 1 ? "" : "s", errors,
+ (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
diff --git a/lib/iolog/regress/iolog_path/data b/lib/iolog/regress/iolog_path/data
new file mode 100644
index 0000000..48dc87e
--- /dev/null
+++ b/lib/iolog/regress/iolog_path/data
@@ -0,0 +1,96 @@
+000001
+nobody
+nogroup
+root
+root
+somehost
+id
+/var/log/sudo-io
+%%{bogus}
+/var/log/sudo-io
+%%{bogus}
+
+000001
+nobody
+nogroup
+root
+wheel
+somehost
+id
+/var/log/sudo-io
+%%{seq}
+/var/log/sudo-io
+%%{seq}
+
+000001
+nobody
+nogroup
+root
+wheel
+somehost
+id
+/var/log/sudo-io
+%{seq}
+/var/log/sudo-io
+00/00/01
+
+000001
+nobody
+nogroup
+root
+wheel
+somehost
+id
+/var/log/sudo-io/%{user}
+%{seq}
+/var/log/sudo-io/nobody
+00/00/01
+
+000001
+nobody
+nogroup
+root
+wheel
+somehost
+su
+/var/log/sudo-io/%{user}/%{runas_user}
+%{command}_%Y%m%s_%H%M
+/var/log/sudo-io/nobody/root
+su_%Y%m%s_%H%M
+
+000001
+nobody
+nogroup
+root
+wheel
+somehost
+su
+/var/log/sudo-io/
+//%{user}/%{runas_user}/%{command}_%Y%m%s_%H%M
+/var/log/sudo-io
+/nobody/root/su_%Y%m%s_%H%M
+
+000001
+nobody
+nogroup
+root
+wheel
+somehost
+su
+/var/log/sudo-io/%d%m%Y
+%{user}/%{runas_user}/%{command}
+/var/log/sudo-io/%d%m%Y
+nobody/root/su
+
+000001
+nobody
+nogroup
+root
+wheel
+somehost
+su
+////////
+%{user}/%{runas_user}/%{command}
+
+nobody/root/su
+
diff --git a/lib/iolog/regress/iolog_timing/check_iolog_timing.c b/lib/iolog/regress/iolog_timing/check_iolog_timing.c
new file mode 100644
index 0000000..5fa34b8
--- /dev/null
+++ b/lib/iolog/regress/iolog_timing/check_iolog_timing.c
@@ -0,0 +1,161 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_fatal.h>
+#include <sudo_iolog.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+static struct parse_delay_test {
+ const char *input;
+ const char *next_field;
+ struct timespec expected_delay;
+} parse_delay_tests[] = {
+ { "10.99999999999 X", "X", { 10, 999999999 } }, /* clamp to nsec */
+ { "10.999999999 X", "X", { 10, 999999999 } }, /* nsec */
+ { "10.999999 X", "X", { 10, 999999000 } }, /* usec -> nsec */
+ { "10.000999999 X", "X", { 10, 999999 } },
+ { "10.9 X", "X", { 10, 900000000 } },
+ { "10.0 X", "X", { 10, 0 } }
+};
+
+/*
+ * Test iolog_parse_delay()
+ */
+static void
+test_parse_delay(int *ntests, int *nerrors)
+{
+ unsigned int i;
+
+ for (i = 0; i < nitems(parse_delay_tests); i++) {
+ struct timespec delay;
+ struct parse_delay_test *test = &parse_delay_tests[i];
+ char *cp = iolog_parse_delay(test->input, &delay, ".");
+ if (cp == NULL) {
+ sudo_warnx("%s:%u failed to parse delay: %s", __func__,
+ i, test->input);
+ (*nerrors)++;
+ continue;
+ }
+ if (strcmp(cp, test->next_field) != 0) {
+ sudo_warnx("%s:%u next field (want \"%s\", got \"%s\"", __func__,
+ i, test->next_field, cp);
+ (*nerrors)++;
+ continue;
+ }
+ if (delay.tv_sec != test->expected_delay.tv_sec) {
+ sudo_warnx("%s:%u wrong seconds (want %lld, got %lld)", __func__,
+ i, (long long)test->expected_delay.tv_sec,
+ (long long)delay.tv_sec);
+ (*nerrors)++;
+ continue;
+ }
+ if (delay.tv_nsec != test->expected_delay.tv_nsec) {
+ sudo_warnx("%s:%u wrong nanoseconds (want %ld, got %ld)", __func__,
+ i, test->expected_delay.tv_nsec, delay.tv_nsec);
+ (*nerrors)++;
+ continue;
+ }
+ }
+ (*ntests) += (int)i;
+}
+
+static struct adjust_delay_test {
+ struct timespec in_delay;
+ struct timespec out_delay;
+ struct timespec max_delay;
+ double scale_factor;
+} adjust_delay_tests[] = {
+ { { 10, 300 }, { 10, 300 }, { 0, 0 }, 1.0 },
+ { { 10, 300 }, { 5, 150 }, { 0, 0 }, 2.0 },
+ { { 5, 300 }, { 2, 500000150 }, { 0, 0 }, 2.0 },
+ { { 0, 1000000 }, { 0, 333333 }, { 0, 0 }, 3 },
+ { { 10, 1000000 }, { 3, 333666666 }, { 0, 0 }, 3 },
+ { { 5, 150 }, { 10, 300 }, { 0, 0 }, 0.5 },
+ { { 5, 500000000 }, { 11, 0 }, { 0, 0 }, 0.5 },
+ { { 5, 150 }, { 5, 0 }, { 5, 0 }, 0.5 }
+};
+
+/*
+ * Test iolog_adjust_delay()
+ */
+static void
+test_adjust_delay(int *ntests, int *nerrors)
+{
+ unsigned int i;
+
+ for (i = 0; i < nitems(adjust_delay_tests); i++) {
+ struct adjust_delay_test *test = &adjust_delay_tests[i];
+
+ iolog_adjust_delay(&test->in_delay,
+ sudo_timespecisset(&test->max_delay) ? &test->max_delay : NULL,
+ test->scale_factor);
+ if (!sudo_timespeccmp(&test->in_delay, &test->out_delay, ==)) {
+ sudo_warnx("%s:%u want {%lld, %ld}, got {%lld, %ld}", __func__, i,
+ (long long)test->out_delay.tv_sec, test->out_delay.tv_nsec,
+ (long long)test->in_delay.tv_sec, test->in_delay.tv_nsec);
+ (*nerrors)++;
+ }
+ }
+ (*ntests) += (int)i;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch, ntests = 0, errors = 0;
+
+ initprogname(argc > 0 ? argv[0] : "check_iolog_timing");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ test_parse_delay(&ntests, &errors);
+
+ test_adjust_delay(&ntests, &errors);
+
+ if (ntests != 0) {
+ printf("iolog_timing: %d test%s run, %d errors, %d%% success rate\n",
+ ntests, ntests == 1 ? "" : "s", errors,
+ (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
diff --git a/lib/logsrv/Makefile.in b/lib/logsrv/Makefile.in
new file mode 100644
index 0000000..f81698f
--- /dev/null
+++ b/lib/logsrv/Makefile.in
@@ -0,0 +1,186 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+devdir = @devdir@
+scriptdir = $(top_srcdir)/scripts
+incdir = $(top_srcdir)/include
+
+# Compiler & tools to use
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+
+# Libraries
+LT_LIBS =
+
+# C preprocessor flags
+CPPFLAGS = -I$(incdir) -I$(top_builddir) -I$(srcdir) -I$(top_srcdir) @CPPFLAGS@
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+
+# Flags to pass to libtool
+LTFLAGS = @LT_STATIC@
+
+# Address sanitizer flags
+ASAN_CFLAGS = @ASAN_CFLAGS@
+ASAN_LDFLAGS = @ASAN_LDFLAGS@
+
+# PIE flags
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+
+# Stack smashing protection flags
+HARDENING_CFLAGS = @HARDENING_CFLAGS@
+HARDENING_LDFLAGS = @HARDENING_LDFLAGS@
+
+# cppcheck options, usually set in the top-level Makefile
+CPPCHECK_OPTS = -q --enable=warning,performance,portability --suppress=constStatement --suppress=compareBoolExpressionWithInt --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
+
+# splint options, usually set in the top-level Makefile
+SPLINT_OPTS = -D__restrict= -checks
+
+# PVS-studio options
+PVS_CFG = $(top_srcdir)/PVS-Studio.cfg
+PVS_IGNORE = 'V707,V011,V002,V536'
+PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
+
+# Set to non-empty for development mode
+DEVEL = @DEVEL@
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+LIBLOGSRV_OBJS = log_server.pb-c.lo
+
+IOBJS = $(LIBLOGSRV_OBJS:.lo=.i)
+
+POBJS = $(IOBJS:.i=.plog)
+
+GENERATED = log_server.pb-c.h log_server.pb-c.c
+
+all: liblogsrv.la
+
+depend:
+ $(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
+ --builddir=$(abs_top_builddir) lib/logsrv/Makefile.in
+ cd $(top_builddir) && ./config.status --file lib/logsrv/Makefile
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file lib/logsrv/Makefile
+
+.SUFFIXES: .c .h .i .lo .plog
+
+.c.lo:
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.i:
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+
+.i.plog:
+ ifile=$<; rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $${ifile%i}c --i-file $< --output-file $@
+
+$(devdir)/log_server.pb-c.c: $(srcdir)/log_server.proto
+ @if [ -n "$(DEVEL)" ]; then \
+ cmd='protoc-c --c_out=$(devdir) --proto_path=$(srcdir) $(srcdir)/log_server.proto'; \
+ echo "$$cmd"; eval $$cmd; \
+ cmd='$(scriptdir)/unanon $(devdir)/log_server.pb-c.h $(devdir)/log_server.pb-c.c'; \
+ echo "$$cmd"; eval $$cmd; \
+ if [ "$(devdir)" == "$(srcdir)" ]; then \
+ cmd='mv -f $(devdir)/log_server.pb-c.h $(incdir)/log_server.pb-c.h'; \
+ else \
+ cmd='mv -f $(devdir)/log_server.pb-c.h $(top_builddir)/log_server.pb-c.h'; \
+ fi; \
+ echo "$$cmd"; eval $$cmd; \
+ fi
+
+liblogsrv.la: $(LIBLOGSRV_OBJS) $(LT_LIBS)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LIBLOGSRV_OBJS) $(LT_LIBS)
+
+pre-install:
+
+install:
+
+install-binaries:
+
+install-includes:
+
+install-doc:
+
+install-plugin:
+
+install-fuzzer:
+
+uninstall:
+
+splint:
+ splint $(SPLINT_OPTS) -I$(incdir) -I$(top_builddir) -I$(top_srcdir) $(srcdir)/*.c
+
+cppcheck:
+ cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) -I$(top_srcdir) $(srcdir)/*.c
+
+pvs-log-files:
+
+pvs-studio:
+
+fuzz:
+
+check-fuzzer:
+
+check: check-fuzzer
+
+check-verbose: check
+
+clean:
+ -$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f *.lo *.o *.la
+ -rm -f *.i *.plog stamp-* core *.core core.*
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile .libs
+ @if [ -n "$(DEVEL)" -a "$(devdir)" != "$(srcdir)" ]; then \
+ cmd='rm -rf $(GENERATED)'; \
+ echo "$$cmd"; eval $$cmd; \
+ fi
+
+clobber: distclean
+
+realclean: distclean
+ rm -f TAGS tags
+
+cleandir: realclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean
+
+# Autogenerated dependencies, do not modify
+log_server.pb-c.lo: $(srcdir)/log_server.pb-c.c $(incdir)/log_server.pb-c.h \
+ $(incdir)/protobuf-c/protobuf-c.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/log_server.pb-c.c
+log_server.pb-c.plog: $(srcdir)/log_server.pb-c.c
+ touch $@
diff --git a/lib/logsrv/log_server.pb-c.c b/lib/logsrv/log_server.pb-c.c
new file mode 100644
index 0000000..21c87b8
--- /dev/null
+++ b/lib/logsrv/log_server.pb-c.c
@@ -0,0 +1,1766 @@
+/* Generated by the protocol buffer compiler. DO NOT EDIT! */
+/* Generated from: log_server.proto */
+
+/* Do not generate deprecated warnings for self */
+#ifndef PROTOBUF_C__NO_DEPRECATED
+#define PROTOBUF_C__NO_DEPRECATED
+#endif
+
+#include <log_server.pb-c.h>
+void client_message__init
+ (ClientMessage *message)
+{
+ static const ClientMessage init_value = CLIENT_MESSAGE__INIT;
+ *message = init_value;
+}
+size_t client_message__get_packed_size
+ (const ClientMessage *message)
+{
+ assert(message->base.descriptor == &client_message__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t client_message__pack
+ (const ClientMessage *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &client_message__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t client_message__pack_to_buffer
+ (const ClientMessage *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &client_message__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+ClientMessage *
+ client_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (ClientMessage *)
+ protobuf_c_message_unpack (&client_message__descriptor,
+ allocator, len, data);
+}
+void client_message__free_unpacked
+ (ClientMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &client_message__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void time_spec__init
+ (TimeSpec *message)
+{
+ static const TimeSpec init_value = TIME_SPEC__INIT;
+ *message = init_value;
+}
+size_t time_spec__get_packed_size
+ (const TimeSpec *message)
+{
+ assert(message->base.descriptor == &time_spec__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t time_spec__pack
+ (const TimeSpec *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &time_spec__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t time_spec__pack_to_buffer
+ (const TimeSpec *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &time_spec__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+TimeSpec *
+ time_spec__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (TimeSpec *)
+ protobuf_c_message_unpack (&time_spec__descriptor,
+ allocator, len, data);
+}
+void time_spec__free_unpacked
+ (TimeSpec *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &time_spec__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void io_buffer__init
+ (IoBuffer *message)
+{
+ static const IoBuffer init_value = IO_BUFFER__INIT;
+ *message = init_value;
+}
+size_t io_buffer__get_packed_size
+ (const IoBuffer *message)
+{
+ assert(message->base.descriptor == &io_buffer__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t io_buffer__pack
+ (const IoBuffer *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &io_buffer__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t io_buffer__pack_to_buffer
+ (const IoBuffer *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &io_buffer__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+IoBuffer *
+ io_buffer__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (IoBuffer *)
+ protobuf_c_message_unpack (&io_buffer__descriptor,
+ allocator, len, data);
+}
+void io_buffer__free_unpacked
+ (IoBuffer *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &io_buffer__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void info_message__string_list__init
+ (InfoMessage__StringList *message)
+{
+ static const InfoMessage__StringList init_value = INFO_MESSAGE__STRING_LIST__INIT;
+ *message = init_value;
+}
+void info_message__number_list__init
+ (InfoMessage__NumberList *message)
+{
+ static const InfoMessage__NumberList init_value = INFO_MESSAGE__NUMBER_LIST__INIT;
+ *message = init_value;
+}
+void info_message__init
+ (InfoMessage *message)
+{
+ static const InfoMessage init_value = INFO_MESSAGE__INIT;
+ *message = init_value;
+}
+size_t info_message__get_packed_size
+ (const InfoMessage *message)
+{
+ assert(message->base.descriptor == &info_message__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t info_message__pack
+ (const InfoMessage *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &info_message__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t info_message__pack_to_buffer
+ (const InfoMessage *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &info_message__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+InfoMessage *
+ info_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (InfoMessage *)
+ protobuf_c_message_unpack (&info_message__descriptor,
+ allocator, len, data);
+}
+void info_message__free_unpacked
+ (InfoMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &info_message__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void accept_message__init
+ (AcceptMessage *message)
+{
+ static const AcceptMessage init_value = ACCEPT_MESSAGE__INIT;
+ *message = init_value;
+}
+size_t accept_message__get_packed_size
+ (const AcceptMessage *message)
+{
+ assert(message->base.descriptor == &accept_message__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t accept_message__pack
+ (const AcceptMessage *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &accept_message__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t accept_message__pack_to_buffer
+ (const AcceptMessage *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &accept_message__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+AcceptMessage *
+ accept_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (AcceptMessage *)
+ protobuf_c_message_unpack (&accept_message__descriptor,
+ allocator, len, data);
+}
+void accept_message__free_unpacked
+ (AcceptMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &accept_message__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void reject_message__init
+ (RejectMessage *message)
+{
+ static const RejectMessage init_value = REJECT_MESSAGE__INIT;
+ *message = init_value;
+}
+size_t reject_message__get_packed_size
+ (const RejectMessage *message)
+{
+ assert(message->base.descriptor == &reject_message__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t reject_message__pack
+ (const RejectMessage *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &reject_message__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t reject_message__pack_to_buffer
+ (const RejectMessage *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &reject_message__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+RejectMessage *
+ reject_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (RejectMessage *)
+ protobuf_c_message_unpack (&reject_message__descriptor,
+ allocator, len, data);
+}
+void reject_message__free_unpacked
+ (RejectMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &reject_message__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void exit_message__init
+ (ExitMessage *message)
+{
+ static const ExitMessage init_value = EXIT_MESSAGE__INIT;
+ *message = init_value;
+}
+size_t exit_message__get_packed_size
+ (const ExitMessage *message)
+{
+ assert(message->base.descriptor == &exit_message__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t exit_message__pack
+ (const ExitMessage *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &exit_message__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t exit_message__pack_to_buffer
+ (const ExitMessage *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &exit_message__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+ExitMessage *
+ exit_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (ExitMessage *)
+ protobuf_c_message_unpack (&exit_message__descriptor,
+ allocator, len, data);
+}
+void exit_message__free_unpacked
+ (ExitMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &exit_message__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void alert_message__init
+ (AlertMessage *message)
+{
+ static const AlertMessage init_value = ALERT_MESSAGE__INIT;
+ *message = init_value;
+}
+size_t alert_message__get_packed_size
+ (const AlertMessage *message)
+{
+ assert(message->base.descriptor == &alert_message__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t alert_message__pack
+ (const AlertMessage *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &alert_message__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t alert_message__pack_to_buffer
+ (const AlertMessage *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &alert_message__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+AlertMessage *
+ alert_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (AlertMessage *)
+ protobuf_c_message_unpack (&alert_message__descriptor,
+ allocator, len, data);
+}
+void alert_message__free_unpacked
+ (AlertMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &alert_message__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void restart_message__init
+ (RestartMessage *message)
+{
+ static const RestartMessage init_value = RESTART_MESSAGE__INIT;
+ *message = init_value;
+}
+size_t restart_message__get_packed_size
+ (const RestartMessage *message)
+{
+ assert(message->base.descriptor == &restart_message__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t restart_message__pack
+ (const RestartMessage *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &restart_message__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t restart_message__pack_to_buffer
+ (const RestartMessage *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &restart_message__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+RestartMessage *
+ restart_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (RestartMessage *)
+ protobuf_c_message_unpack (&restart_message__descriptor,
+ allocator, len, data);
+}
+void restart_message__free_unpacked
+ (RestartMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &restart_message__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void change_window_size__init
+ (ChangeWindowSize *message)
+{
+ static const ChangeWindowSize init_value = CHANGE_WINDOW_SIZE__INIT;
+ *message = init_value;
+}
+size_t change_window_size__get_packed_size
+ (const ChangeWindowSize *message)
+{
+ assert(message->base.descriptor == &change_window_size__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t change_window_size__pack
+ (const ChangeWindowSize *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &change_window_size__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t change_window_size__pack_to_buffer
+ (const ChangeWindowSize *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &change_window_size__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+ChangeWindowSize *
+ change_window_size__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (ChangeWindowSize *)
+ protobuf_c_message_unpack (&change_window_size__descriptor,
+ allocator, len, data);
+}
+void change_window_size__free_unpacked
+ (ChangeWindowSize *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &change_window_size__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void command_suspend__init
+ (CommandSuspend *message)
+{
+ static const CommandSuspend init_value = COMMAND_SUSPEND__INIT;
+ *message = init_value;
+}
+size_t command_suspend__get_packed_size
+ (const CommandSuspend *message)
+{
+ assert(message->base.descriptor == &command_suspend__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t command_suspend__pack
+ (const CommandSuspend *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &command_suspend__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t command_suspend__pack_to_buffer
+ (const CommandSuspend *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &command_suspend__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+CommandSuspend *
+ command_suspend__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (CommandSuspend *)
+ protobuf_c_message_unpack (&command_suspend__descriptor,
+ allocator, len, data);
+}
+void command_suspend__free_unpacked
+ (CommandSuspend *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &command_suspend__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void client_hello__init
+ (ClientHello *message)
+{
+ static const ClientHello init_value = CLIENT_HELLO__INIT;
+ *message = init_value;
+}
+size_t client_hello__get_packed_size
+ (const ClientHello *message)
+{
+ assert(message->base.descriptor == &client_hello__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t client_hello__pack
+ (const ClientHello *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &client_hello__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t client_hello__pack_to_buffer
+ (const ClientHello *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &client_hello__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+ClientHello *
+ client_hello__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (ClientHello *)
+ protobuf_c_message_unpack (&client_hello__descriptor,
+ allocator, len, data);
+}
+void client_hello__free_unpacked
+ (ClientHello *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &client_hello__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void server_message__init
+ (ServerMessage *message)
+{
+ static const ServerMessage init_value = SERVER_MESSAGE__INIT;
+ *message = init_value;
+}
+size_t server_message__get_packed_size
+ (const ServerMessage *message)
+{
+ assert(message->base.descriptor == &server_message__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t server_message__pack
+ (const ServerMessage *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &server_message__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t server_message__pack_to_buffer
+ (const ServerMessage *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &server_message__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+ServerMessage *
+ server_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (ServerMessage *)
+ protobuf_c_message_unpack (&server_message__descriptor,
+ allocator, len, data);
+}
+void server_message__free_unpacked
+ (ServerMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &server_message__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void server_hello__init
+ (ServerHello *message)
+{
+ static const ServerHello init_value = SERVER_HELLO__INIT;
+ *message = init_value;
+}
+size_t server_hello__get_packed_size
+ (const ServerHello *message)
+{
+ assert(message->base.descriptor == &server_hello__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t server_hello__pack
+ (const ServerHello *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &server_hello__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t server_hello__pack_to_buffer
+ (const ServerHello *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &server_hello__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+ServerHello *
+ server_hello__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (ServerHello *)
+ protobuf_c_message_unpack (&server_hello__descriptor,
+ allocator, len, data);
+}
+void server_hello__free_unpacked
+ (ServerHello *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &server_hello__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+static const ProtobufCFieldDescriptor client_message__field_descriptors[13] =
+{
+ {
+ "accept_msg",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(ClientMessage, type_case),
+ offsetof(ClientMessage, u.accept_msg),
+ &accept_message__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "reject_msg",
+ 2,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(ClientMessage, type_case),
+ offsetof(ClientMessage, u.reject_msg),
+ &reject_message__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "exit_msg",
+ 3,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(ClientMessage, type_case),
+ offsetof(ClientMessage, u.exit_msg),
+ &exit_message__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "restart_msg",
+ 4,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(ClientMessage, type_case),
+ offsetof(ClientMessage, u.restart_msg),
+ &restart_message__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "alert_msg",
+ 5,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(ClientMessage, type_case),
+ offsetof(ClientMessage, u.alert_msg),
+ &alert_message__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "ttyin_buf",
+ 6,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(ClientMessage, type_case),
+ offsetof(ClientMessage, u.ttyin_buf),
+ &io_buffer__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "ttyout_buf",
+ 7,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(ClientMessage, type_case),
+ offsetof(ClientMessage, u.ttyout_buf),
+ &io_buffer__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "stdin_buf",
+ 8,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(ClientMessage, type_case),
+ offsetof(ClientMessage, u.stdin_buf),
+ &io_buffer__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "stdout_buf",
+ 9,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(ClientMessage, type_case),
+ offsetof(ClientMessage, u.stdout_buf),
+ &io_buffer__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "stderr_buf",
+ 10,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(ClientMessage, type_case),
+ offsetof(ClientMessage, u.stderr_buf),
+ &io_buffer__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "winsize_event",
+ 11,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(ClientMessage, type_case),
+ offsetof(ClientMessage, u.winsize_event),
+ &change_window_size__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "suspend_event",
+ 12,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(ClientMessage, type_case),
+ offsetof(ClientMessage, u.suspend_event),
+ &command_suspend__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "hello_msg",
+ 13,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(ClientMessage, type_case),
+ offsetof(ClientMessage, u.hello_msg),
+ &client_hello__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned client_message__field_indices_by_name[] = {
+ 0, /* field[0] = accept_msg */
+ 4, /* field[4] = alert_msg */
+ 2, /* field[2] = exit_msg */
+ 12, /* field[12] = hello_msg */
+ 1, /* field[1] = reject_msg */
+ 3, /* field[3] = restart_msg */
+ 9, /* field[9] = stderr_buf */
+ 7, /* field[7] = stdin_buf */
+ 8, /* field[8] = stdout_buf */
+ 11, /* field[11] = suspend_event */
+ 5, /* field[5] = ttyin_buf */
+ 6, /* field[6] = ttyout_buf */
+ 10, /* field[10] = winsize_event */
+};
+static const ProtobufCIntRange client_message__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 13 }
+};
+const ProtobufCMessageDescriptor client_message__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "ClientMessage",
+ "ClientMessage",
+ "ClientMessage",
+ "",
+ sizeof(ClientMessage),
+ 13,
+ client_message__field_descriptors,
+ client_message__field_indices_by_name,
+ 1, client_message__number_ranges,
+ (ProtobufCMessageInit) client_message__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor time_spec__field_descriptors[2] =
+{
+ {
+ "tv_sec",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_INT64,
+ 0, /* quantifier_offset */
+ offsetof(TimeSpec, tv_sec),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "tv_nsec",
+ 2,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_INT32,
+ 0, /* quantifier_offset */
+ offsetof(TimeSpec, tv_nsec),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned time_spec__field_indices_by_name[] = {
+ 1, /* field[1] = tv_nsec */
+ 0, /* field[0] = tv_sec */
+};
+static const ProtobufCIntRange time_spec__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 2 }
+};
+const ProtobufCMessageDescriptor time_spec__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "TimeSpec",
+ "TimeSpec",
+ "TimeSpec",
+ "",
+ sizeof(TimeSpec),
+ 2,
+ time_spec__field_descriptors,
+ time_spec__field_indices_by_name,
+ 1, time_spec__number_ranges,
+ (ProtobufCMessageInit) time_spec__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor io_buffer__field_descriptors[2] =
+{
+ {
+ "delay",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ 0, /* quantifier_offset */
+ offsetof(IoBuffer, delay),
+ &time_spec__descriptor,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "data",
+ 2,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_BYTES,
+ 0, /* quantifier_offset */
+ offsetof(IoBuffer, data),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned io_buffer__field_indices_by_name[] = {
+ 1, /* field[1] = data */
+ 0, /* field[0] = delay */
+};
+static const ProtobufCIntRange io_buffer__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 2 }
+};
+const ProtobufCMessageDescriptor io_buffer__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "IoBuffer",
+ "IoBuffer",
+ "IoBuffer",
+ "",
+ sizeof(IoBuffer),
+ 2,
+ io_buffer__field_descriptors,
+ io_buffer__field_indices_by_name,
+ 1, io_buffer__number_ranges,
+ (ProtobufCMessageInit) io_buffer__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor info_message__string_list__field_descriptors[1] =
+{
+ {
+ "strings",
+ 1,
+ PROTOBUF_C_LABEL_REPEATED,
+ PROTOBUF_C_TYPE_STRING,
+ offsetof(InfoMessage__StringList, n_strings),
+ offsetof(InfoMessage__StringList, strings),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned info_message__string_list__field_indices_by_name[] = {
+ 0, /* field[0] = strings */
+};
+static const ProtobufCIntRange info_message__string_list__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 1 }
+};
+const ProtobufCMessageDescriptor info_message__string_list__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "InfoMessage.StringList",
+ "StringList",
+ "InfoMessage__StringList",
+ "",
+ sizeof(InfoMessage__StringList),
+ 1,
+ info_message__string_list__field_descriptors,
+ info_message__string_list__field_indices_by_name,
+ 1, info_message__string_list__number_ranges,
+ (ProtobufCMessageInit) info_message__string_list__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor info_message__number_list__field_descriptors[1] =
+{
+ {
+ "numbers",
+ 1,
+ PROTOBUF_C_LABEL_REPEATED,
+ PROTOBUF_C_TYPE_INT64,
+ offsetof(InfoMessage__NumberList, n_numbers),
+ offsetof(InfoMessage__NumberList, numbers),
+ NULL,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_PACKED, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned info_message__number_list__field_indices_by_name[] = {
+ 0, /* field[0] = numbers */
+};
+static const ProtobufCIntRange info_message__number_list__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 1 }
+};
+const ProtobufCMessageDescriptor info_message__number_list__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "InfoMessage.NumberList",
+ "NumberList",
+ "InfoMessage__NumberList",
+ "",
+ sizeof(InfoMessage__NumberList),
+ 1,
+ info_message__number_list__field_descriptors,
+ info_message__number_list__field_indices_by_name,
+ 1, info_message__number_list__number_ranges,
+ (ProtobufCMessageInit) info_message__number_list__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor info_message__field_descriptors[5] =
+{
+ {
+ "key",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(InfoMessage, key),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "numval",
+ 2,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_INT64,
+ offsetof(InfoMessage, value_case),
+ offsetof(InfoMessage, u.numval),
+ NULL,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "strval",
+ 3,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ offsetof(InfoMessage, value_case),
+ offsetof(InfoMessage, u.strval),
+ NULL,
+ &protobuf_c_empty_string,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "strlistval",
+ 4,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(InfoMessage, value_case),
+ offsetof(InfoMessage, u.strlistval),
+ &info_message__string_list__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "numlistval",
+ 5,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(InfoMessage, value_case),
+ offsetof(InfoMessage, u.numlistval),
+ &info_message__number_list__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned info_message__field_indices_by_name[] = {
+ 0, /* field[0] = key */
+ 4, /* field[4] = numlistval */
+ 1, /* field[1] = numval */
+ 3, /* field[3] = strlistval */
+ 2, /* field[2] = strval */
+};
+static const ProtobufCIntRange info_message__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 5 }
+};
+const ProtobufCMessageDescriptor info_message__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "InfoMessage",
+ "InfoMessage",
+ "InfoMessage",
+ "",
+ sizeof(InfoMessage),
+ 5,
+ info_message__field_descriptors,
+ info_message__field_indices_by_name,
+ 1, info_message__number_ranges,
+ (ProtobufCMessageInit) info_message__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor accept_message__field_descriptors[3] =
+{
+ {
+ "submit_time",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ 0, /* quantifier_offset */
+ offsetof(AcceptMessage, submit_time),
+ &time_spec__descriptor,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "info_msgs",
+ 2,
+ PROTOBUF_C_LABEL_REPEATED,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(AcceptMessage, n_info_msgs),
+ offsetof(AcceptMessage, info_msgs),
+ &info_message__descriptor,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "expect_iobufs",
+ 3,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_BOOL,
+ 0, /* quantifier_offset */
+ offsetof(AcceptMessage, expect_iobufs),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned accept_message__field_indices_by_name[] = {
+ 2, /* field[2] = expect_iobufs */
+ 1, /* field[1] = info_msgs */
+ 0, /* field[0] = submit_time */
+};
+static const ProtobufCIntRange accept_message__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 3 }
+};
+const ProtobufCMessageDescriptor accept_message__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "AcceptMessage",
+ "AcceptMessage",
+ "AcceptMessage",
+ "",
+ sizeof(AcceptMessage),
+ 3,
+ accept_message__field_descriptors,
+ accept_message__field_indices_by_name,
+ 1, accept_message__number_ranges,
+ (ProtobufCMessageInit) accept_message__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor reject_message__field_descriptors[3] =
+{
+ {
+ "submit_time",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ 0, /* quantifier_offset */
+ offsetof(RejectMessage, submit_time),
+ &time_spec__descriptor,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "reason",
+ 2,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(RejectMessage, reason),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "info_msgs",
+ 3,
+ PROTOBUF_C_LABEL_REPEATED,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(RejectMessage, n_info_msgs),
+ offsetof(RejectMessage, info_msgs),
+ &info_message__descriptor,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned reject_message__field_indices_by_name[] = {
+ 2, /* field[2] = info_msgs */
+ 1, /* field[1] = reason */
+ 0, /* field[0] = submit_time */
+};
+static const ProtobufCIntRange reject_message__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 3 }
+};
+const ProtobufCMessageDescriptor reject_message__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "RejectMessage",
+ "RejectMessage",
+ "RejectMessage",
+ "",
+ sizeof(RejectMessage),
+ 3,
+ reject_message__field_descriptors,
+ reject_message__field_indices_by_name,
+ 1, reject_message__number_ranges,
+ (ProtobufCMessageInit) reject_message__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor exit_message__field_descriptors[5] =
+{
+ {
+ "run_time",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ 0, /* quantifier_offset */
+ offsetof(ExitMessage, run_time),
+ &time_spec__descriptor,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "exit_value",
+ 2,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_INT32,
+ 0, /* quantifier_offset */
+ offsetof(ExitMessage, exit_value),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "dumped_core",
+ 3,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_BOOL,
+ 0, /* quantifier_offset */
+ offsetof(ExitMessage, dumped_core),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "signal",
+ 4,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(ExitMessage, signal),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "error",
+ 5,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(ExitMessage, error),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned exit_message__field_indices_by_name[] = {
+ 2, /* field[2] = dumped_core */
+ 4, /* field[4] = error */
+ 1, /* field[1] = exit_value */
+ 0, /* field[0] = run_time */
+ 3, /* field[3] = signal */
+};
+static const ProtobufCIntRange exit_message__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 5 }
+};
+const ProtobufCMessageDescriptor exit_message__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "ExitMessage",
+ "ExitMessage",
+ "ExitMessage",
+ "",
+ sizeof(ExitMessage),
+ 5,
+ exit_message__field_descriptors,
+ exit_message__field_indices_by_name,
+ 1, exit_message__number_ranges,
+ (ProtobufCMessageInit) exit_message__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor alert_message__field_descriptors[3] =
+{
+ {
+ "alert_time",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ 0, /* quantifier_offset */
+ offsetof(AlertMessage, alert_time),
+ &time_spec__descriptor,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "reason",
+ 2,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(AlertMessage, reason),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "info_msgs",
+ 3,
+ PROTOBUF_C_LABEL_REPEATED,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(AlertMessage, n_info_msgs),
+ offsetof(AlertMessage, info_msgs),
+ &info_message__descriptor,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned alert_message__field_indices_by_name[] = {
+ 0, /* field[0] = alert_time */
+ 2, /* field[2] = info_msgs */
+ 1, /* field[1] = reason */
+};
+static const ProtobufCIntRange alert_message__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 3 }
+};
+const ProtobufCMessageDescriptor alert_message__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "AlertMessage",
+ "AlertMessage",
+ "AlertMessage",
+ "",
+ sizeof(AlertMessage),
+ 3,
+ alert_message__field_descriptors,
+ alert_message__field_indices_by_name,
+ 1, alert_message__number_ranges,
+ (ProtobufCMessageInit) alert_message__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor restart_message__field_descriptors[2] =
+{
+ {
+ "log_id",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(RestartMessage, log_id),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "resume_point",
+ 2,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ 0, /* quantifier_offset */
+ offsetof(RestartMessage, resume_point),
+ &time_spec__descriptor,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned restart_message__field_indices_by_name[] = {
+ 0, /* field[0] = log_id */
+ 1, /* field[1] = resume_point */
+};
+static const ProtobufCIntRange restart_message__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 2 }
+};
+const ProtobufCMessageDescriptor restart_message__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "RestartMessage",
+ "RestartMessage",
+ "RestartMessage",
+ "",
+ sizeof(RestartMessage),
+ 2,
+ restart_message__field_descriptors,
+ restart_message__field_indices_by_name,
+ 1, restart_message__number_ranges,
+ (ProtobufCMessageInit) restart_message__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor change_window_size__field_descriptors[3] =
+{
+ {
+ "delay",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ 0, /* quantifier_offset */
+ offsetof(ChangeWindowSize, delay),
+ &time_spec__descriptor,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "rows",
+ 2,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_INT32,
+ 0, /* quantifier_offset */
+ offsetof(ChangeWindowSize, rows),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "cols",
+ 3,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_INT32,
+ 0, /* quantifier_offset */
+ offsetof(ChangeWindowSize, cols),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned change_window_size__field_indices_by_name[] = {
+ 2, /* field[2] = cols */
+ 0, /* field[0] = delay */
+ 1, /* field[1] = rows */
+};
+static const ProtobufCIntRange change_window_size__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 3 }
+};
+const ProtobufCMessageDescriptor change_window_size__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "ChangeWindowSize",
+ "ChangeWindowSize",
+ "ChangeWindowSize",
+ "",
+ sizeof(ChangeWindowSize),
+ 3,
+ change_window_size__field_descriptors,
+ change_window_size__field_indices_by_name,
+ 1, change_window_size__number_ranges,
+ (ProtobufCMessageInit) change_window_size__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor command_suspend__field_descriptors[2] =
+{
+ {
+ "delay",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ 0, /* quantifier_offset */
+ offsetof(CommandSuspend, delay),
+ &time_spec__descriptor,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "signal",
+ 2,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(CommandSuspend, signal),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned command_suspend__field_indices_by_name[] = {
+ 0, /* field[0] = delay */
+ 1, /* field[1] = signal */
+};
+static const ProtobufCIntRange command_suspend__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 2 }
+};
+const ProtobufCMessageDescriptor command_suspend__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "CommandSuspend",
+ "CommandSuspend",
+ "CommandSuspend",
+ "",
+ sizeof(CommandSuspend),
+ 2,
+ command_suspend__field_descriptors,
+ command_suspend__field_indices_by_name,
+ 1, command_suspend__number_ranges,
+ (ProtobufCMessageInit) command_suspend__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor client_hello__field_descriptors[1] =
+{
+ {
+ "client_id",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(ClientHello, client_id),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned client_hello__field_indices_by_name[] = {
+ 0, /* field[0] = client_id */
+};
+static const ProtobufCIntRange client_hello__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 1 }
+};
+const ProtobufCMessageDescriptor client_hello__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "ClientHello",
+ "ClientHello",
+ "ClientHello",
+ "",
+ sizeof(ClientHello),
+ 1,
+ client_hello__field_descriptors,
+ client_hello__field_indices_by_name,
+ 1, client_hello__number_ranges,
+ (ProtobufCMessageInit) client_hello__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor server_message__field_descriptors[5] =
+{
+ {
+ "hello",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(ServerMessage, type_case),
+ offsetof(ServerMessage, u.hello),
+ &server_hello__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "commit_point",
+ 2,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(ServerMessage, type_case),
+ offsetof(ServerMessage, u.commit_point),
+ &time_spec__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "log_id",
+ 3,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ offsetof(ServerMessage, type_case),
+ offsetof(ServerMessage, u.log_id),
+ NULL,
+ &protobuf_c_empty_string,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "error",
+ 4,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ offsetof(ServerMessage, type_case),
+ offsetof(ServerMessage, u.error),
+ NULL,
+ &protobuf_c_empty_string,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "abort",
+ 5,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ offsetof(ServerMessage, type_case),
+ offsetof(ServerMessage, u.abort),
+ NULL,
+ &protobuf_c_empty_string,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned server_message__field_indices_by_name[] = {
+ 4, /* field[4] = abort */
+ 1, /* field[1] = commit_point */
+ 3, /* field[3] = error */
+ 0, /* field[0] = hello */
+ 2, /* field[2] = log_id */
+};
+static const ProtobufCIntRange server_message__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 5 }
+};
+const ProtobufCMessageDescriptor server_message__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "ServerMessage",
+ "ServerMessage",
+ "ServerMessage",
+ "",
+ sizeof(ServerMessage),
+ 5,
+ server_message__field_descriptors,
+ server_message__field_indices_by_name,
+ 1, server_message__number_ranges,
+ (ProtobufCMessageInit) server_message__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor server_hello__field_descriptors[4] =
+{
+ {
+ "server_id",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(ServerHello, server_id),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "redirect",
+ 2,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(ServerHello, redirect),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "servers",
+ 3,
+ PROTOBUF_C_LABEL_REPEATED,
+ PROTOBUF_C_TYPE_STRING,
+ offsetof(ServerHello, n_servers),
+ offsetof(ServerHello, servers),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "subcommands",
+ 4,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_BOOL,
+ 0, /* quantifier_offset */
+ offsetof(ServerHello, subcommands),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned server_hello__field_indices_by_name[] = {
+ 1, /* field[1] = redirect */
+ 0, /* field[0] = server_id */
+ 2, /* field[2] = servers */
+ 3, /* field[3] = subcommands */
+};
+static const ProtobufCIntRange server_hello__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 4 }
+};
+const ProtobufCMessageDescriptor server_hello__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "ServerHello",
+ "ServerHello",
+ "ServerHello",
+ "",
+ sizeof(ServerHello),
+ 4,
+ server_hello__field_descriptors,
+ server_hello__field_indices_by_name,
+ 1, server_hello__number_ranges,
+ (ProtobufCMessageInit) server_hello__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
diff --git a/lib/logsrv/log_server.proto b/lib/logsrv/log_server.proto
new file mode 100644
index 0000000..23b716e
--- /dev/null
+++ b/lib/logsrv/log_server.proto
@@ -0,0 +1,136 @@
+syntax = "proto3";
+
+/*
+ * Client message to the server. Messages on the wire are
+ * prefixed with a 32-bit size in network byte order.
+ */
+message ClientMessage {
+ oneof type {
+ AcceptMessage accept_msg = 1;
+ RejectMessage reject_msg = 2;
+ ExitMessage exit_msg = 3;
+ RestartMessage restart_msg = 4;
+ AlertMessage alert_msg = 5;
+ IoBuffer ttyin_buf = 6;
+ IoBuffer ttyout_buf = 7;
+ IoBuffer stdin_buf = 8;
+ IoBuffer stdout_buf = 9;
+ IoBuffer stderr_buf = 10;
+ ChangeWindowSize winsize_event = 11;
+ CommandSuspend suspend_event = 12;
+ ClientHello hello_msg = 13;
+ }
+}
+
+/* Equivalent of POSIX struct timespec */
+message TimeSpec {
+ int64 tv_sec = 1; /* seconds */
+ int32 tv_nsec = 2; /* nanoseconds */
+}
+
+/* I/O buffer with keystroke data */
+message IoBuffer {
+ TimeSpec delay = 1; /* elapsed time since last record */
+ bytes data = 2; /* keystroke data */
+}
+
+/*
+ * Key/value pairs, like Privilege Manager struct info.
+ * The value may be a number, a string, or a list of strings.
+ */
+message InfoMessage {
+ message StringList {
+ repeated string strings = 1;
+ }
+ message NumberList {
+ repeated int64 numbers = 1;
+ }
+ string key = 1;
+ oneof value {
+ int64 numval = 2;
+ string strval = 3;
+ StringList strlistval = 4;
+ NumberList numlistval = 5;
+ }
+}
+
+/*
+ * Event log data for command accepted by the policy.
+ */
+message AcceptMessage {
+ TimeSpec submit_time = 1; /* when command was submitted */
+ repeated InfoMessage info_msgs = 2; /* key,value event log data */
+ bool expect_iobufs = 3; /* true if I/O logging enabled */
+}
+
+/*
+ * Event log data for command rejected by the policy.
+ */
+message RejectMessage {
+ TimeSpec submit_time = 1; /* when command was submitted */
+ string reason = 2; /* reason command was rejected */
+ repeated InfoMessage info_msgs = 3; /* key,value event log data */
+}
+
+/* Message sent by client when command exits. */
+/* Might revisit runtime and use end_time instead */
+message ExitMessage {
+ TimeSpec run_time = 1; /* total elapsed run time */
+ int32 exit_value = 2; /* 0-255 */
+ bool dumped_core = 3; /* true if command dumped core */
+ string signal = 4; /* signal name if killed by signal */
+ string error = 5; /* if killed due to other error */
+}
+
+/* Alert message, policy module-specific. */
+message AlertMessage {
+ TimeSpec alert_time = 1; /* time alert message occurred */
+ string reason = 2; /* policy alert error string */
+ repeated InfoMessage info_msgs = 3; /* optional key,value event log data */
+}
+
+/* Used to restart an existing I/O log on the server. */
+message RestartMessage {
+ string log_id = 1; /* ID of log being restarted */
+ TimeSpec resume_point = 2; /* resume point (elapsed time) */
+}
+
+/* Window size change event. */
+message ChangeWindowSize {
+ TimeSpec delay = 1; /* elapsed time since last record */
+ int32 rows = 2; /* new number of rows */
+ int32 cols = 3; /* new number of columns */
+}
+
+/* Command suspend/resume event. */
+message CommandSuspend {
+ TimeSpec delay = 1; /* elapsed time since last record */
+ string signal = 2; /* signal that caused suspend/resume */
+}
+
+/* Hello message from client when connecting to server. */
+message ClientHello {
+ string client_id = 1; /* free-form client description */
+}
+
+/*
+ * Server messages to the client. Messages on the wire are
+ * prefixed with a 32-bit size in network byte order.
+ */
+message ServerMessage {
+ oneof type {
+ ServerHello hello = 1; /* server hello message */
+ TimeSpec commit_point = 2; /* cumulative time of records stored */
+ string log_id = 3; /* ID of server-side I/O log */
+ string error = 4; /* error message from server */
+ string abort = 5; /* abort message, kill command */
+ }
+}
+
+/* Hello message from server when client connects. */
+message ServerHello {
+ string server_id = 1; /* free-form server description */
+ string redirect = 2; /* optional redirect if busy */
+ repeated string servers = 3; /* optional list of known servers */
+ bool subcommands = 4; /* flag: server supports sub-commands */
+}
diff --git a/lib/protobuf-c/Makefile.in b/lib/protobuf-c/Makefile.in
new file mode 100644
index 0000000..49b1e9d
--- /dev/null
+++ b/lib/protobuf-c/Makefile.in
@@ -0,0 +1,180 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+devdir = @devdir@
+scriptdir = $(top_srcdir)/scripts
+incdir = $(top_srcdir)/include
+
+# Compiler & tools to use
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+
+# C preprocessor flags
+CPPFLAGS = -I$(incdir) -I$(top_builddir) -I$(srcdir) -I$(top_srcdir) @CPPFLAGS@
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+
+# Flags to pass to libtool
+LTFLAGS = @LT_STATIC@
+
+# Address sanitizer flags
+ASAN_CFLAGS = @ASAN_CFLAGS@
+ASAN_LDFLAGS = @ASAN_LDFLAGS@
+
+# PIE flags
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+
+# Stack smashing protection flags
+HARDENING_CFLAGS = @HARDENING_CFLAGS@
+HARDENING_LDFLAGS = @HARDENING_LDFLAGS@
+
+# cppcheck options, usually set in the top-level Makefile
+CPPCHECK_OPTS = -q --enable=warning,performance,portability --suppress=constStatement --suppress=compareBoolExpressionWithInt --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
+
+# splint options, usually set in the top-level Makefile
+SPLINT_OPTS = -D__restrict= -checks
+
+# PVS-studio options
+PVS_CFG = $(top_srcdir)/PVS-Studio.cfg
+PVS_IGNORE = 'V707,V011,V002,V536'
+PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
+
+# Set to non-empty for development mode
+DEVEL = @DEVEL@
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+LIBPROTOBUF_C_OBJS = protobuf-c.lo
+
+IOBJS = $(LIBPROTOBUF_C_OBJS:.lo=.i)
+
+POBJS = $(IOBJS:.i=.plog)
+
+all: libprotobuf-c.la
+
+depend:
+ $(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
+ --builddir=$(abs_top_builddir) lib/protobuf-c/Makefile.in
+ cd $(top_builddir) && ./config.status --file lib/protobuf-c/Makefile
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file lib/protobuf-c/Makefile
+
+.SUFFIXES: .c .h .i .lo .plog
+
+.c.lo:
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.i:
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+
+.i.plog:
+ ifile=$<; rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $${ifile%i}c --i-file $< --output-file $@
+
+$(devdir)/log_server.pb-c.c: $(srcdir)/log_server.proto
+ @if [ -n "$(DEVEL)" ]; then \
+ cmd='protoc-c --c_out=$(devdir) --proto_path=$(srcdir) $(srcdir)/log_server.proto'; \
+ echo "$$cmd"; eval $$cmd; \
+ cmd='$(scriptdir)/unanon $(devdir)/log_server.pb-c.h $(devdir)/log_server.pb-c.c'; \
+ echo "$$cmd"; eval $$cmd; \
+ if [ "$(devdir)" == "$(srcdir)" ]; then \
+ cmd='mv -f $(devdir)/log_server.pb-c.h $(incdir)/log_server.pb-c.h'; \
+ else \
+ cmd='mv -f $(devdir)/log_server.pb-c.h $(top_builddir)/log_server.pb-c.h'; \
+ fi; \
+ echo "$$cmd"; eval $$cmd; \
+ fi
+
+libprotobuf-c.la: $(LIBPROTOBUF_C_OBJS)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LIBPROTOBUF_C_OBJS)
+
+pre-install:
+
+install:
+
+install-binaries:
+
+install-includes:
+
+install-doc:
+
+install-plugin:
+
+install-fuzzer:
+
+uninstall:
+
+splint:
+ splint $(SPLINT_OPTS) -I$(incdir) -I$(top_builddir) -I$(top_srcdir) $(srcdir)/*.c
+
+cppcheck:
+ cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) -I$(top_srcdir) $(srcdir)/*.c
+
+pvs-log-files:
+
+pvs-studio:
+
+fuzz:
+
+check-fuzzer:
+
+check: check-fuzzer
+
+check-verbose: check
+
+clean:
+ -$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f *.lo *.o *.la
+ -rm -f *.i *.plog stamp-* core *.core core.*
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile .libs
+
+clobber: distclean
+
+realclean: distclean
+ rm -f TAGS tags
+
+cleandir: realclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean
+
+# Autogenerated dependencies, do not modify
+protobuf-c.lo: $(srcdir)/protobuf-c.c $(incdir)/compat/endian.h \
+ $(incdir)/protobuf-c/protobuf-c.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/protobuf-c.c
+protobuf-c.i: $(srcdir)/protobuf-c.c $(incdir)/compat/endian.h \
+ $(incdir)/protobuf-c/protobuf-c.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+protobuf-c.plog: protobuf-c.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/protobuf-c.c --i-file $< --output-file $@
diff --git a/lib/protobuf-c/protobuf-c.c b/lib/protobuf-c/protobuf-c.c
new file mode 100644
index 0000000..9d7da26
--- /dev/null
+++ b/lib/protobuf-c/protobuf-c.c
@@ -0,0 +1,3687 @@
+/*
+ * Copyright (c) 2008-2022, Dave Benson and the protobuf-c authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*! \file
+ * Support library for `protoc-c` generated code.
+ *
+ * This file implements the public API used by the code generated
+ * by `protoc-c`.
+ *
+ * \authors Dave Benson and the protobuf-c authors
+ *
+ * \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license.
+ */
+
+/**
+ * \todo 64-BIT OPTIMIZATION: certain implementations use 32-bit math
+ * even on 64-bit platforms (uint64_size, uint64_pack, parse_uint64).
+ *
+ * \todo Use size_t consistently.
+ */
+
+#include <config.h>
+
+#include <stdlib.h> /* for malloc, free */
+#include <string.h> /* for strcmp, strlen, memcpy, memmove, memset */
+#if defined(HAVE_ENDIAN_H)
+# include <endian.h>
+#elif defined(HAVE_SYS_ENDIAN_H)
+# include <sys/endian.h>
+#elif defined(HAVE_MACHINE_ENDIAN_H)
+# include <machine/endian.h>
+#else
+# include <compat/endian.h>
+#endif
+
+#include <protobuf-c/protobuf-c.h>
+
+#if BYTE_ORDER == BIG_ENDIAN
+# define WORDS_BIGENDIAN
+#endif
+
+#define TRUE 1
+#define FALSE 0
+
+#define PROTOBUF_C__ASSERT_NOT_REACHED() assert(0)
+
+/* Workaround for Microsoft compilers. */
+#ifdef _MSC_VER
+# define inline __inline
+#endif
+
+/**
+ * \defgroup internal Internal functions and macros
+ *
+ * These are not exported by the library but are useful to developers working
+ * on `libprotobuf-c` itself.
+ */
+
+/**
+ * \defgroup macros Utility macros for manipulating structures
+ *
+ * Macros and constants used to manipulate the base "classes" generated by
+ * `protobuf-c`. They also define limits and check correctness.
+ *
+ * \ingroup internal
+ * @{
+ */
+
+/** The maximum length of a 64-bit integer in varint encoding. */
+#define MAX_UINT64_ENCODED_SIZE 10
+
+#ifndef PROTOBUF_C_UNPACK_ERROR
+# define PROTOBUF_C_UNPACK_ERROR(...)
+#endif
+
+#if !defined(_WIN32) || !defined(PROTOBUF_C_USE_SHARED_LIB)
+const char protobuf_c_empty_string[] = "";
+#endif
+
+/**
+ * Internal `ProtobufCMessage` manipulation macro.
+ *
+ * Base macro for manipulating a `ProtobufCMessage`. Used by STRUCT_MEMBER() and
+ * STRUCT_MEMBER_PTR().
+ */
+#define STRUCT_MEMBER_P(struct_p, struct_offset) \
+ ((void *) ((uint8_t *) (struct_p) + (struct_offset)))
+
+/**
+ * Return field in a `ProtobufCMessage` based on offset.
+ *
+ * Take a pointer to a `ProtobufCMessage` and find the field at the offset.
+ * Cast it to the passed type.
+ */
+#define STRUCT_MEMBER(member_type, struct_p, struct_offset) \
+ (*(member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset)))
+
+/**
+ * Return field in a `ProtobufCMessage` based on offset.
+ *
+ * Take a pointer to a `ProtobufCMessage` and find the field at the offset. Cast
+ * it to a pointer to the passed type.
+ */
+#define STRUCT_MEMBER_PTR(member_type, struct_p, struct_offset) \
+ ((member_type *) STRUCT_MEMBER_P((struct_p), (struct_offset)))
+
+/* Assertions for magic numbers. */
+
+#define ASSERT_IS_ENUM_DESCRIPTOR(desc) \
+ assert((desc)->magic == PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC)
+
+#define ASSERT_IS_MESSAGE_DESCRIPTOR(desc) \
+ assert((desc)->magic == PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC)
+
+#define ASSERT_IS_MESSAGE(message) \
+ ASSERT_IS_MESSAGE_DESCRIPTOR((message)->descriptor)
+
+#define ASSERT_IS_SERVICE_DESCRIPTOR(desc) \
+ assert((desc)->magic == PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC)
+
+/**@}*/
+
+/* --- version --- */
+
+const char *
+protobuf_c_version(void)
+{
+ return PROTOBUF_C_VERSION;
+}
+
+uint32_t
+protobuf_c_version_number(void)
+{
+ return PROTOBUF_C_VERSION_NUMBER;
+}
+
+/* --- allocator --- */
+
+static void *
+system_alloc(void *allocator_data, size_t size)
+{
+ (void)allocator_data;
+ return malloc(size);
+}
+
+static void
+system_free(void *allocator_data, void *data)
+{
+ (void)allocator_data;
+ free(data);
+}
+
+static inline void *
+do_alloc(ProtobufCAllocator *allocator, size_t size)
+{
+ return allocator->alloc(allocator->allocator_data, size);
+}
+
+static inline void
+do_free(ProtobufCAllocator *allocator, void *data)
+{
+ if (data != NULL)
+ allocator->free(allocator->allocator_data, data);
+}
+
+/*
+ * This allocator uses the system's malloc() and free(). It is the default
+ * allocator used if NULL is passed as the ProtobufCAllocator to an exported
+ * function.
+ */
+static ProtobufCAllocator protobuf_c__allocator = {
+ .alloc = &system_alloc,
+ .free = &system_free,
+ .allocator_data = NULL,
+};
+
+/* === buffer-simple === */
+
+void
+protobuf_c_buffer_simple_append(ProtobufCBuffer *buffer,
+ size_t len, const uint8_t *data)
+{
+ ProtobufCBufferSimple *simp = (ProtobufCBufferSimple *) buffer;
+ size_t new_len = simp->len + len;
+
+ if (new_len > simp->alloced) {
+ ProtobufCAllocator *allocator = simp->allocator;
+ size_t new_alloced = simp->alloced * 2;
+ uint8_t *new_data;
+
+ if (allocator == NULL)
+ allocator = &protobuf_c__allocator;
+ while (new_alloced < new_len)
+ new_alloced += new_alloced;
+ new_data = do_alloc(allocator, new_alloced);
+ if (!new_data)
+ return;
+ memcpy(new_data, simp->data, simp->len);
+ if (simp->must_free_data)
+ do_free(allocator, simp->data);
+ else
+ simp->must_free_data = TRUE;
+ simp->data = new_data;
+ simp->alloced = new_alloced;
+ }
+ memcpy(simp->data + simp->len, data, len);
+ simp->len = new_len;
+}
+
+/**
+ * \defgroup packedsz protobuf_c_message_get_packed_size() implementation
+ *
+ * Routines mainly used by protobuf_c_message_get_packed_size().
+ *
+ * \ingroup internal
+ * @{
+ */
+
+/**
+ * Return the number of bytes required to store the tag for the field. Includes
+ * 3 bits for the wire-type, and a single bit that denotes the end-of-tag.
+ *
+ * \param number
+ * Field tag to encode.
+ * \return
+ * Number of bytes required.
+ */
+static inline size_t
+get_tag_size(uint32_t number)
+{
+ if (number < (1UL << 4)) {
+ return 1;
+ } else if (number < (1UL << 11)) {
+ return 2;
+ } else if (number < (1UL << 18)) {
+ return 3;
+ } else if (number < (1UL << 25)) {
+ return 4;
+ } else {
+ return 5;
+ }
+}
+
+/**
+ * Return the number of bytes required to store a variable-length unsigned
+ * 32-bit integer in base-128 varint encoding.
+ *
+ * \param v
+ * Value to encode.
+ * \return
+ * Number of bytes required.
+ */
+static inline size_t
+uint32_size(uint32_t v)
+{
+ if (v < (1UL << 7)) {
+ return 1;
+ } else if (v < (1UL << 14)) {
+ return 2;
+ } else if (v < (1UL << 21)) {
+ return 3;
+ } else if (v < (1UL << 28)) {
+ return 4;
+ } else {
+ return 5;
+ }
+}
+
+/**
+ * Return the number of bytes required to store a variable-length signed 32-bit
+ * integer in base-128 varint encoding.
+ *
+ * \param v
+ * Value to encode.
+ * \return
+ * Number of bytes required.
+ */
+static inline size_t
+int32_size(int32_t v)
+{
+ if (v < 0) {
+ return 10;
+ } else if (v < (1L << 7)) {
+ return 1;
+ } else if (v < (1L << 14)) {
+ return 2;
+ } else if (v < (1L << 21)) {
+ return 3;
+ } else if (v < (1L << 28)) {
+ return 4;
+ } else {
+ return 5;
+ }
+}
+
+/**
+ * Return the ZigZag-encoded 32-bit unsigned integer form of a 32-bit signed
+ * integer.
+ *
+ * \param v
+ * Value to encode.
+ * \return
+ * ZigZag encoded integer.
+ */
+static inline uint32_t
+zigzag32(int32_t v)
+{
+ // Note: Using unsigned types prevents undefined behavior
+ return ((uint32_t)v << 1) ^ -((uint32_t)v >> 31);
+}
+
+/**
+ * Return the number of bytes required to store a signed 32-bit integer,
+ * converted to an unsigned 32-bit integer with ZigZag encoding, using base-128
+ * varint encoding.
+ *
+ * \param v
+ * Value to encode.
+ * \return
+ * Number of bytes required.
+ */
+static inline size_t
+sint32_size(int32_t v)
+{
+ return uint32_size(zigzag32(v));
+}
+
+/**
+ * Return the number of bytes required to store a 64-bit unsigned integer in
+ * base-128 varint encoding.
+ *
+ * \param v
+ * Value to encode.
+ * \return
+ * Number of bytes required.
+ */
+static inline size_t
+uint64_size(uint64_t v)
+{
+ uint32_t upper_v = (uint32_t) (v >> 32);
+
+ if (upper_v == 0) {
+ return uint32_size((uint32_t) v);
+ } else if (upper_v < (1UL << 3)) {
+ return 5;
+ } else if (upper_v < (1UL << 10)) {
+ return 6;
+ } else if (upper_v < (1UL << 17)) {
+ return 7;
+ } else if (upper_v < (1UL << 24)) {
+ return 8;
+ } else if (upper_v < (1UL << 31)) {
+ return 9;
+ } else {
+ return 10;
+ }
+}
+
+/**
+ * Return the ZigZag-encoded 64-bit unsigned integer form of a 64-bit signed
+ * integer.
+ *
+ * \param v
+ * Value to encode.
+ * \return
+ * ZigZag encoded integer.
+ */
+static inline uint64_t
+zigzag64(int64_t v)
+{
+ // Note: Using unsigned types prevents undefined behavior
+ return ((uint64_t)v << 1) ^ -((uint64_t)v >> 63);
+}
+
+/**
+ * Return the number of bytes required to store a signed 64-bit integer,
+ * converted to an unsigned 64-bit integer with ZigZag encoding, using base-128
+ * varint encoding.
+ *
+ * \param v
+ * Value to encode.
+ * \return
+ * Number of bytes required.
+ */
+static inline size_t
+sint64_size(int64_t v)
+{
+ return uint64_size(zigzag64(v));
+}
+
+/**
+ * Calculate the serialized size of a single required message field, including
+ * the space needed by the preceding tag.
+ *
+ * \param field
+ * Field descriptor for member.
+ * \param member
+ * Field to encode.
+ * \return
+ * Number of bytes required.
+ */
+static size_t
+required_field_get_packed_size(const ProtobufCFieldDescriptor *field,
+ const void *member)
+{
+ size_t rv = get_tag_size(field->id);
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_SINT32:
+ return rv + sint32_size(*(const int32_t *) member);
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32:
+ return rv + int32_size(*(const int32_t *) member);
+ case PROTOBUF_C_TYPE_UINT32:
+ return rv + uint32_size(*(const uint32_t *) member);
+ case PROTOBUF_C_TYPE_SINT64:
+ return rv + sint64_size(*(const int64_t *) member);
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ return rv + uint64_size(*(const uint64_t *) member);
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ return rv + 4;
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ return rv + 8;
+ case PROTOBUF_C_TYPE_BOOL:
+ return rv + 1;
+ case PROTOBUF_C_TYPE_FLOAT:
+ return rv + 4;
+ case PROTOBUF_C_TYPE_DOUBLE:
+ return rv + 8;
+ case PROTOBUF_C_TYPE_STRING: {
+ const char *str = *(char * const *) member;
+ size_t len = str ? strlen(str) : 0;
+ return rv + uint32_size(len) + len;
+ }
+ case PROTOBUF_C_TYPE_BYTES: {
+ size_t len = ((const ProtobufCBinaryData *) member)->len;
+ return rv + uint32_size(len) + len;
+ }
+ case PROTOBUF_C_TYPE_MESSAGE: {
+ const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
+ size_t subrv = msg ? protobuf_c_message_get_packed_size(msg) : 0;
+ return rv + uint32_size(subrv) + subrv;
+ }
+ }
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ return 0;
+}
+
+/**
+ * Calculate the serialized size of a single oneof message field, including
+ * the space needed by the preceding tag. Returns 0 if the oneof field isn't
+ * selected or is not set.
+ *
+ * \param field
+ * Field descriptor for member.
+ * \param oneof_case
+ * Enum value that selects the field in the oneof.
+ * \param member
+ * Field to encode.
+ * \return
+ * Number of bytes required.
+ */
+static size_t
+oneof_field_get_packed_size(const ProtobufCFieldDescriptor *field,
+ uint32_t oneof_case,
+ const void *member)
+{
+ if (oneof_case != field->id) {
+ return 0;
+ }
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
+ field->type == PROTOBUF_C_TYPE_STRING)
+ {
+ const void *ptr = *(const void * const *) member;
+ if (ptr == NULL || ptr == field->default_value)
+ return 0;
+ }
+ return required_field_get_packed_size(field, member);
+}
+
+/**
+ * Calculate the serialized size of a single optional message field, including
+ * the space needed by the preceding tag. Returns 0 if the optional field isn't
+ * set.
+ *
+ * \param field
+ * Field descriptor for member.
+ * \param has
+ * True if the field exists, false if not.
+ * \param member
+ * Field to encode.
+ * \return
+ * Number of bytes required.
+ */
+static size_t
+optional_field_get_packed_size(const ProtobufCFieldDescriptor *field,
+ const protobuf_c_boolean has,
+ const void *member)
+{
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
+ field->type == PROTOBUF_C_TYPE_STRING)
+ {
+ const void *ptr = *(const void * const *) member;
+ if (ptr == NULL || ptr == field->default_value)
+ return 0;
+ } else {
+ if (!has)
+ return 0;
+ }
+ return required_field_get_packed_size(field, member);
+}
+
+static protobuf_c_boolean
+field_is_zeroish(const ProtobufCFieldDescriptor *field,
+ const void *member)
+{
+ protobuf_c_boolean ret = FALSE;
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_BOOL:
+ ret = (0 == *(const protobuf_c_boolean *) member);
+ break;
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_SINT32:
+ case PROTOBUF_C_TYPE_INT32:
+ case PROTOBUF_C_TYPE_UINT32:
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ ret = (0 == *(const uint32_t *) member);
+ break;
+ case PROTOBUF_C_TYPE_SINT64:
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ ret = (0 == *(const uint64_t *) member);
+ break;
+ case PROTOBUF_C_TYPE_FLOAT:
+ ret = (0 == *(const float *) member);
+ break;
+ case PROTOBUF_C_TYPE_DOUBLE:
+ ret = (0 == *(const double *) member);
+ break;
+ case PROTOBUF_C_TYPE_STRING:
+ ret = (NULL == *(const char * const *) member) ||
+ ('\0' == **(const char * const *) member);
+ break;
+ case PROTOBUF_C_TYPE_BYTES:
+ case PROTOBUF_C_TYPE_MESSAGE:
+ ret = (NULL == *(const void * const *) member);
+ break;
+ default:
+ ret = TRUE;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * Calculate the serialized size of a single unlabeled message field, including
+ * the space needed by the preceding tag. Returns 0 if the field isn't set or
+ * if it is set to a "zeroish" value (null pointer or 0 for numerical values).
+ * Unlabeled fields are supported only in proto3.
+ *
+ * \param field
+ * Field descriptor for member.
+ * \param member
+ * Field to encode.
+ * \return
+ * Number of bytes required.
+ */
+static size_t
+unlabeled_field_get_packed_size(const ProtobufCFieldDescriptor *field,
+ const void *member)
+{
+ if (field_is_zeroish(field, member))
+ return 0;
+ return required_field_get_packed_size(field, member);
+}
+
+/**
+ * Calculate the serialized size of repeated message fields, which may consist
+ * of any number of values (including 0). Includes the space needed by the
+ * preceding tags (as needed).
+ *
+ * \param field
+ * Field descriptor for member.
+ * \param count
+ * Number of repeated field members.
+ * \param member
+ * Field to encode.
+ * \return
+ * Number of bytes required.
+ */
+static size_t
+repeated_field_get_packed_size(const ProtobufCFieldDescriptor *field,
+ size_t count, const void *member)
+{
+ size_t header_size;
+ size_t rv = 0;
+ unsigned i;
+ void *array = *(void * const *) member;
+
+ if (count == 0)
+ return 0;
+ header_size = get_tag_size(field->id);
+ if (0 == (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED))
+ header_size *= count;
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_SINT32:
+ for (i = 0; i < count; i++)
+ rv += sint32_size(((int32_t *) array)[i]);
+ break;
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32:
+ for (i = 0; i < count; i++)
+ rv += int32_size(((int32_t *) array)[i]);
+ break;
+ case PROTOBUF_C_TYPE_UINT32:
+ for (i = 0; i < count; i++)
+ rv += uint32_size(((uint32_t *) array)[i]);
+ break;
+ case PROTOBUF_C_TYPE_SINT64:
+ for (i = 0; i < count; i++)
+ rv += sint64_size(((int64_t *) array)[i]);
+ break;
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ for (i = 0; i < count; i++)
+ rv += uint64_size(((uint64_t *) array)[i]);
+ break;
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ rv += 4 * count;
+ break;
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ rv += 8 * count;
+ break;
+ case PROTOBUF_C_TYPE_BOOL:
+ rv += count;
+ break;
+ case PROTOBUF_C_TYPE_STRING:
+ for (i = 0; i < count; i++) {
+ size_t len = strlen(((char **) array)[i]);
+ rv += uint32_size(len) + len;
+ }
+ break;
+ case PROTOBUF_C_TYPE_BYTES:
+ for (i = 0; i < count; i++) {
+ size_t len = ((ProtobufCBinaryData *) array)[i].len;
+ rv += uint32_size(len) + len;
+ }
+ break;
+ case PROTOBUF_C_TYPE_MESSAGE:
+ for (i = 0; i < count; i++) {
+ size_t len = protobuf_c_message_get_packed_size(
+ ((ProtobufCMessage **) array)[i]);
+ rv += uint32_size(len) + len;
+ }
+ break;
+ }
+
+ if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED))
+ header_size += uint32_size(rv);
+ return header_size + rv;
+}
+
+/**
+ * Calculate the serialized size of an unknown field, i.e. one that is passed
+ * through mostly uninterpreted. This is required for forward compatibility if
+ * new fields are added to the message descriptor.
+ *
+ * \param field
+ * Unknown field type.
+ * \return
+ * Number of bytes required.
+ */
+static inline size_t
+unknown_field_get_packed_size(const ProtobufCMessageUnknownField *field)
+{
+ return get_tag_size(field->tag) + field->len;
+}
+
+/**@}*/
+
+/*
+ * Calculate the serialized size of the message.
+ */
+size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message)
+{
+ unsigned i;
+ size_t rv = 0;
+
+ ASSERT_IS_MESSAGE(message);
+ for (i = 0; i < message->descriptor->n_fields; i++) {
+ const ProtobufCFieldDescriptor *field =
+ message->descriptor->fields + i;
+ const void *member =
+ ((const char *) message) + field->offset;
+ const void *qmember =
+ ((const char *) message) + field->quantifier_offset;
+
+ if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
+ rv += required_field_get_packed_size(field, member);
+ } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL ||
+ field->label == PROTOBUF_C_LABEL_NONE) &&
+ (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) {
+ rv += oneof_field_get_packed_size(
+ field,
+ *(const uint32_t *) qmember,
+ member
+ );
+ } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
+ rv += optional_field_get_packed_size(
+ field,
+ *(protobuf_c_boolean *) qmember,
+ member
+ );
+ } else if (field->label == PROTOBUF_C_LABEL_NONE) {
+ rv += unlabeled_field_get_packed_size(
+ field,
+ member
+ );
+ } else {
+ rv += repeated_field_get_packed_size(
+ field,
+ *(const size_t *) qmember,
+ member
+ );
+ }
+ }
+ for (i = 0; i < message->n_unknown_fields; i++)
+ rv += unknown_field_get_packed_size(&message->unknown_fields[i]);
+ return rv;
+}
+
+/**
+ * \defgroup pack protobuf_c_message_pack() implementation
+ *
+ * Routines mainly used by protobuf_c_message_pack().
+ *
+ * \ingroup internal
+ * @{
+ */
+
+/**
+ * Pack an unsigned 32-bit integer in base-128 varint encoding and return the
+ * number of bytes written, which must be 5 or less.
+ *
+ * \param value
+ * Value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+uint32_pack(uint32_t value, uint8_t *out)
+{
+ unsigned rv = 0;
+
+ if (value >= 0x80) {
+ out[rv++] = value | 0x80;
+ value >>= 7;
+ if (value >= 0x80) {
+ out[rv++] = value | 0x80;
+ value >>= 7;
+ if (value >= 0x80) {
+ out[rv++] = value | 0x80;
+ value >>= 7;
+ if (value >= 0x80) {
+ out[rv++] = value | 0x80;
+ value >>= 7;
+ }
+ }
+ }
+ }
+ /* assert: value<128 */
+ out[rv++] = value;
+ return rv;
+}
+
+/**
+ * Pack a signed 32-bit integer and return the number of bytes written,
+ * passed as unsigned to avoid implementation-specific behavior.
+ * Negative numbers are encoded as two's complement 64-bit integers.
+ *
+ * \param value
+ * Value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+int32_pack(uint32_t value, uint8_t *out)
+{
+ if ((int32_t)value < 0) {
+ out[0] = value | 0x80;
+ out[1] = (value >> 7) | 0x80;
+ out[2] = (value >> 14) | 0x80;
+ out[3] = (value >> 21) | 0x80;
+ out[4] = (value >> 28) | 0xf0;
+ out[5] = out[6] = out[7] = out[8] = 0xff;
+ out[9] = 0x01;
+ return 10;
+ } else {
+ return uint32_pack(value, out);
+ }
+}
+
+/**
+ * Pack a signed 32-bit integer using ZigZag encoding and return the number of
+ * bytes written.
+ *
+ * \param value
+ * Value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+sint32_pack(int32_t value, uint8_t *out)
+{
+ return uint32_pack(zigzag32(value), out);
+}
+
+/**
+ * Pack a 64-bit unsigned integer using base-128 varint encoding and return the
+ * number of bytes written.
+ *
+ * \param value
+ * Value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static size_t
+uint64_pack(uint64_t value, uint8_t *out)
+{
+ uint32_t hi = (uint32_t) (value >> 32);
+ uint32_t lo = (uint32_t) value;
+ unsigned rv;
+
+ if (hi == 0)
+ return uint32_pack((uint32_t) lo, out);
+ out[0] = (lo) | 0x80;
+ out[1] = (lo >> 7) | 0x80;
+ out[2] = (lo >> 14) | 0x80;
+ out[3] = (lo >> 21) | 0x80;
+ if (hi < 8) {
+ out[4] = (hi << 4) | (lo >> 28);
+ return 5;
+ } else {
+ out[4] = ((hi & 7) << 4) | (lo >> 28) | 0x80;
+ hi >>= 3;
+ }
+ rv = 5;
+ while (hi >= 128) {
+ out[rv++] = hi | 0x80;
+ hi >>= 7;
+ }
+ out[rv++] = hi;
+ return rv;
+}
+
+/**
+ * Pack a 64-bit signed integer in ZigZag encoding and return the number of
+ * bytes written.
+ *
+ * \param value
+ * Value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+sint64_pack(int64_t value, uint8_t *out)
+{
+ return uint64_pack(zigzag64(value), out);
+}
+
+/**
+ * Pack a 32-bit quantity in little-endian byte order. Used for protobuf wire
+ * types fixed32, sfixed32, float. Similar to "htole32".
+ *
+ * \param value
+ * Value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+fixed32_pack(uint32_t value, void *out)
+{
+#if !defined(WORDS_BIGENDIAN)
+ memcpy(out, &value, 4);
+#else
+ uint8_t *buf = out;
+
+ buf[0] = value;
+ buf[1] = value >> 8;
+ buf[2] = value >> 16;
+ buf[3] = value >> 24;
+#endif
+ return 4;
+}
+
+/**
+ * Pack a 64-bit quantity in little-endian byte order. Used for protobuf wire
+ * types fixed64, sfixed64, double. Similar to "htole64".
+ *
+ * \todo The big-endian impl is really only good for 32-bit machines, a 64-bit
+ * version would be appreciated, plus a way to decide to use 64-bit math where
+ * convenient.
+ *
+ * \param value
+ * Value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+fixed64_pack(uint64_t value, void *out)
+{
+#if !defined(WORDS_BIGENDIAN)
+ memcpy(out, &value, 8);
+#else
+ fixed32_pack(value, out);
+ fixed32_pack(value >> 32, ((char *) out) + 4);
+#endif
+ return 8;
+}
+
+/**
+ * Pack a boolean value as an integer and return the number of bytes written.
+ *
+ * \todo Perhaps on some platforms *out = !!value would be a better impl, b/c
+ * that is idiomatic C++ in some STL implementations.
+ *
+ * \param value
+ * Value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+boolean_pack(protobuf_c_boolean value, uint8_t *out)
+{
+ *out = value ? TRUE : FALSE;
+ return 1;
+}
+
+/**
+ * Pack a NUL-terminated C string and return the number of bytes written. The
+ * output includes a length delimiter.
+ *
+ * The NULL pointer is treated as an empty string. This isn't really necessary,
+ * but it allows people to leave required strings blank. (See Issue #13 in the
+ * bug tracker for a little more explanation).
+ *
+ * \param str
+ * String to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+string_pack(const char *str, uint8_t *out)
+{
+ if (str == NULL) {
+ out[0] = 0;
+ return 1;
+ } else {
+ size_t len = strlen(str);
+ size_t rv = uint32_pack(len, out);
+ memcpy(out + rv, str, len);
+ return rv + len;
+ }
+}
+
+/**
+ * Pack a ProtobufCBinaryData and return the number of bytes written. The output
+ * includes a length delimiter.
+ *
+ * \param bd
+ * ProtobufCBinaryData to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+binary_data_pack(const ProtobufCBinaryData *bd, uint8_t *out)
+{
+ size_t len = bd->len;
+ size_t rv = uint32_pack(len, out);
+ memcpy(out + rv, bd->data, len);
+ return rv + len;
+}
+
+/**
+ * Pack a ProtobufCMessage and return the number of bytes written. The output
+ * includes a length delimiter.
+ *
+ * \param message
+ * ProtobufCMessage object to pack.
+ * \param[out] out
+ * Packed message.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static inline size_t
+prefixed_message_pack(const ProtobufCMessage *message, uint8_t *out)
+{
+ if (message == NULL) {
+ out[0] = 0;
+ return 1;
+ } else {
+ size_t rv = protobuf_c_message_pack(message, out + 1);
+ uint32_t rv_packed_size = uint32_size(rv);
+ if (rv_packed_size != 1)
+ memmove(out + rv_packed_size, out + 1, rv);
+ return uint32_pack(rv, out) + rv;
+ }
+}
+
+/**
+ * Pack a field tag.
+ *
+ * Wire-type will be added in required_field_pack().
+ *
+ * \todo Just call uint64_pack on 64-bit platforms.
+ *
+ * \param id
+ * Tag value to encode.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static size_t
+tag_pack(uint32_t id, uint8_t *out)
+{
+ if (id < (1UL << (32 - 3)))
+ return uint32_pack(id << 3, out);
+ else
+ return uint64_pack(((uint64_t) id) << 3, out);
+}
+
+/**
+ * Pack a required field and return the number of bytes written.
+ *
+ * \param field
+ * Field descriptor.
+ * \param member
+ * The field member.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static size_t
+required_field_pack(const ProtobufCFieldDescriptor *field,
+ const void *member, uint8_t *out)
+{
+ size_t rv = tag_pack(field->id, out);
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_SINT32:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ return rv + sint32_pack(*(const int32_t *) member, out + rv);
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ return rv + int32_pack(*(const int32_t *) member, out + rv);
+ case PROTOBUF_C_TYPE_UINT32:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ return rv + uint32_pack(*(const uint32_t *) member, out + rv);
+ case PROTOBUF_C_TYPE_SINT64:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ return rv + sint64_pack(*(const int64_t *) member, out + rv);
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ return rv + uint64_pack(*(const uint64_t *) member, out + rv);
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
+ return rv + fixed32_pack(*(const uint32_t *) member, out + rv);
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
+ return rv + fixed64_pack(*(const uint64_t *) member, out + rv);
+ case PROTOBUF_C_TYPE_BOOL:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ return rv + boolean_pack(*(const protobuf_c_boolean *) member, out + rv);
+ case PROTOBUF_C_TYPE_STRING:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+ return rv + string_pack(*(char *const *) member, out + rv);
+ case PROTOBUF_C_TYPE_BYTES:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+ return rv + binary_data_pack((const ProtobufCBinaryData *) member, out + rv);
+ case PROTOBUF_C_TYPE_MESSAGE:
+ out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+ return rv + prefixed_message_pack(*(ProtobufCMessage * const *) member, out + rv);
+ }
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ return 0;
+}
+
+/**
+ * Pack a oneof field and return the number of bytes written. Only packs the
+ * field that is selected by the case enum.
+ *
+ * \param field
+ * Field descriptor.
+ * \param oneof_case
+ * Enum value that selects the field in the oneof.
+ * \param member
+ * The field member.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static size_t
+oneof_field_pack(const ProtobufCFieldDescriptor *field,
+ uint32_t oneof_case,
+ const void *member, uint8_t *out)
+{
+ if (oneof_case != field->id) {
+ return 0;
+ }
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
+ field->type == PROTOBUF_C_TYPE_STRING)
+ {
+ const void *ptr = *(const void * const *) member;
+ if (ptr == NULL || ptr == field->default_value)
+ return 0;
+ }
+ return required_field_pack(field, member, out);
+}
+
+/**
+ * Pack an optional field and return the number of bytes written.
+ *
+ * \param field
+ * Field descriptor.
+ * \param has
+ * Whether the field is set.
+ * \param member
+ * The field member.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static size_t
+optional_field_pack(const ProtobufCFieldDescriptor *field,
+ const protobuf_c_boolean has,
+ const void *member, uint8_t *out)
+{
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
+ field->type == PROTOBUF_C_TYPE_STRING)
+ {
+ const void *ptr = *(const void * const *) member;
+ if (ptr == NULL || ptr == field->default_value)
+ return 0;
+ } else {
+ if (!has)
+ return 0;
+ }
+ return required_field_pack(field, member, out);
+}
+
+/**
+ * Pack an unlabeled field and return the number of bytes written.
+ *
+ * \param field
+ * Field descriptor.
+ * \param member
+ * The field member.
+ * \param[out] out
+ * Packed value.
+ * \return
+ * Number of bytes written to `out`.
+ */
+static size_t
+unlabeled_field_pack(const ProtobufCFieldDescriptor *field,
+ const void *member, uint8_t *out)
+{
+ if (field_is_zeroish(field, member))
+ return 0;
+ return required_field_pack(field, member, out);
+}
+
+/**
+ * Given a field type, return the in-memory size.
+ *
+ * \todo Implement as a table lookup.
+ *
+ * \param type
+ * Field type.
+ * \return
+ * Size of the field.
+ */
+static inline size_t
+sizeof_elt_in_repeated_array(ProtobufCType type)
+{
+ switch (type) {
+ case PROTOBUF_C_TYPE_SINT32:
+ case PROTOBUF_C_TYPE_INT32:
+ case PROTOBUF_C_TYPE_UINT32:
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ case PROTOBUF_C_TYPE_ENUM:
+ return 4;
+ case PROTOBUF_C_TYPE_SINT64:
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ return 8;
+ case PROTOBUF_C_TYPE_BOOL:
+ return sizeof(protobuf_c_boolean);
+ case PROTOBUF_C_TYPE_STRING:
+ case PROTOBUF_C_TYPE_MESSAGE:
+ return sizeof(void *);
+ case PROTOBUF_C_TYPE_BYTES:
+ return sizeof(ProtobufCBinaryData);
+ }
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ return 0;
+}
+
+/**
+ * Pack an array of 32-bit quantities.
+ *
+ * \param[out] out
+ * Destination.
+ * \param[in] in
+ * Source.
+ * \param[in] n
+ * Number of elements in the source array.
+ */
+static void
+copy_to_little_endian_32(void *out, const void *in, const unsigned n)
+{
+#if !defined(WORDS_BIGENDIAN)
+ memcpy(out, in, n * 4);
+#else
+ unsigned i;
+ const uint32_t *ini = in;
+ for (i = 0; i < n; i++)
+ fixed32_pack(ini[i], (uint32_t *) out + i);
+#endif
+}
+
+/**
+ * Pack an array of 64-bit quantities.
+ *
+ * \param[out] out
+ * Destination.
+ * \param[in] in
+ * Source.
+ * \param[in] n
+ * Number of elements in the source array.
+ */
+static void
+copy_to_little_endian_64(void *out, const void *in, const unsigned n)
+{
+#if !defined(WORDS_BIGENDIAN)
+ memcpy(out, in, n * 8);
+#else
+ unsigned i;
+ const uint64_t *ini = in;
+ for (i = 0; i < n; i++)
+ fixed64_pack(ini[i], (uint64_t *) out + i);
+#endif
+}
+
+/**
+ * Get the minimum number of bytes required to pack a field value of a
+ * particular type.
+ *
+ * \param type
+ * Field type.
+ * \return
+ * Number of bytes.
+ */
+static unsigned
+get_type_min_size(ProtobufCType type)
+{
+ if (type == PROTOBUF_C_TYPE_SFIXED32 ||
+ type == PROTOBUF_C_TYPE_FIXED32 ||
+ type == PROTOBUF_C_TYPE_FLOAT)
+ {
+ return 4;
+ }
+ if (type == PROTOBUF_C_TYPE_SFIXED64 ||
+ type == PROTOBUF_C_TYPE_FIXED64 ||
+ type == PROTOBUF_C_TYPE_DOUBLE)
+ {
+ return 8;
+ }
+ return 1;
+}
+
+/**
+ * Packs the elements of a repeated field and returns the serialised field and
+ * its length.
+ *
+ * \param field
+ * Field descriptor.
+ * \param count
+ * Number of elements in the repeated field array.
+ * \param member
+ * Pointer to the elements for this repeated field.
+ * \param[out] out
+ * Serialised representation of the repeated field.
+ * \return
+ * Number of bytes serialised to `out`.
+ */
+static size_t
+repeated_field_pack(const ProtobufCFieldDescriptor *field,
+ size_t count, const void *member, uint8_t *out)
+{
+ void *array = *(void * const *) member;
+ unsigned i;
+
+ if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) {
+ unsigned header_len;
+ unsigned len_start;
+ unsigned min_length;
+ unsigned payload_len;
+ unsigned length_size_min;
+ unsigned actual_length_size;
+ uint8_t *payload_at;
+
+ if (count == 0)
+ return 0;
+ header_len = tag_pack(field->id, out);
+ out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+ len_start = header_len;
+ min_length = get_type_min_size(field->type) * count;
+ length_size_min = uint32_size(min_length);
+ header_len += length_size_min;
+ payload_at = out + header_len;
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ copy_to_little_endian_32(payload_at, array, count);
+ payload_at += count * 4;
+ break;
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ copy_to_little_endian_64(payload_at, array, count);
+ payload_at += count * 8;
+ break;
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32: {
+ const int32_t *arr = (const int32_t *) array;
+ for (i = 0; i < count; i++)
+ payload_at += int32_pack(arr[i], payload_at);
+ break;
+ }
+ case PROTOBUF_C_TYPE_SINT32: {
+ const int32_t *arr = (const int32_t *) array;
+ for (i = 0; i < count; i++)
+ payload_at += sint32_pack(arr[i], payload_at);
+ break;
+ }
+ case PROTOBUF_C_TYPE_SINT64: {
+ const int64_t *arr = (const int64_t *) array;
+ for (i = 0; i < count; i++)
+ payload_at += sint64_pack(arr[i], payload_at);
+ break;
+ }
+ case PROTOBUF_C_TYPE_UINT32: {
+ const uint32_t *arr = (const uint32_t *) array;
+ for (i = 0; i < count; i++)
+ payload_at += uint32_pack(arr[i], payload_at);
+ break;
+ }
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64: {
+ const uint64_t *arr = (const uint64_t *) array;
+ for (i = 0; i < count; i++)
+ payload_at += uint64_pack(arr[i], payload_at);
+ break;
+ }
+ case PROTOBUF_C_TYPE_BOOL: {
+ const protobuf_c_boolean *arr = (const protobuf_c_boolean *) array;
+ for (i = 0; i < count; i++)
+ payload_at += boolean_pack(arr[i], payload_at);
+ break;
+ }
+ default:
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ }
+
+ payload_len = payload_at - (out + header_len);
+ actual_length_size = uint32_size(payload_len);
+ if (length_size_min != actual_length_size) {
+ assert(actual_length_size == length_size_min + 1);
+ memmove(out + header_len + 1, out + header_len,
+ payload_len);
+ header_len++;
+ }
+ uint32_pack(payload_len, out + len_start);
+ return header_len + payload_len;
+ } else {
+ /* not "packed" cased */
+ /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
+ size_t rv = 0;
+ unsigned siz = sizeof_elt_in_repeated_array(field->type);
+
+ for (i = 0; i < count; i++) {
+ rv += required_field_pack(field, array, out + rv);
+ array = (char *)array + siz;
+ }
+ return rv;
+ }
+}
+
+static size_t
+unknown_field_pack(const ProtobufCMessageUnknownField *field, uint8_t *out)
+{
+ size_t rv = tag_pack(field->tag, out);
+ out[0] |= field->wire_type;
+ memcpy(out + rv, field->data, field->len);
+ return rv + field->len;
+}
+
+/**@}*/
+
+size_t
+protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out)
+{
+ unsigned i;
+ size_t rv = 0;
+
+ ASSERT_IS_MESSAGE(message);
+ for (i = 0; i < message->descriptor->n_fields; i++) {
+ const ProtobufCFieldDescriptor *field =
+ message->descriptor->fields + i;
+ const void *member = ((const char *) message) + field->offset;
+
+ /*
+ * It doesn't hurt to compute qmember (a pointer to the
+ * quantifier field of the structure), but the pointer is only
+ * valid if the field is:
+ * - a repeated field, or
+ * - a field that is part of a oneof
+ * - an optional field that isn't a pointer type
+ * (Meaning: not a message or a string).
+ */
+ const void *qmember =
+ ((const char *) message) + field->quantifier_offset;
+
+ if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
+ rv += required_field_pack(field, member, out + rv);
+ } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL ||
+ field->label == PROTOBUF_C_LABEL_NONE) &&
+ (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) {
+ rv += oneof_field_pack(
+ field,
+ *(const uint32_t *) qmember,
+ member,
+ out + rv
+ );
+ } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
+ rv += optional_field_pack(
+ field,
+ *(const protobuf_c_boolean *) qmember,
+ member,
+ out + rv
+ );
+ } else if (field->label == PROTOBUF_C_LABEL_NONE) {
+ rv += unlabeled_field_pack(field, member, out + rv);
+ } else {
+ rv += repeated_field_pack(field, *(const size_t *) qmember,
+ member, out + rv);
+ }
+ }
+ for (i = 0; i < message->n_unknown_fields; i++)
+ rv += unknown_field_pack(&message->unknown_fields[i], out + rv);
+ return rv;
+}
+
+/**
+ * \defgroup packbuf protobuf_c_message_pack_to_buffer() implementation
+ *
+ * Routines mainly used by protobuf_c_message_pack_to_buffer().
+ *
+ * \ingroup internal
+ * @{
+ */
+
+/**
+ * Pack a required field to a virtual buffer.
+ *
+ * \param field
+ * Field descriptor.
+ * \param member
+ * The element to be packed.
+ * \param[out] buffer
+ * Virtual buffer to append data to.
+ * \return
+ * Number of bytes packed.
+ */
+static size_t
+required_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
+ const void *member, ProtobufCBuffer *buffer)
+{
+ size_t rv;
+ uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
+
+ rv = tag_pack(field->id, scratch);
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_SINT32:
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ rv += sint32_pack(*(const int32_t *) member, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ break;
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32:
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ rv += int32_pack(*(const int32_t *) member, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ break;
+ case PROTOBUF_C_TYPE_UINT32:
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ rv += uint32_pack(*(const uint32_t *) member, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ break;
+ case PROTOBUF_C_TYPE_SINT64:
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ rv += sint64_pack(*(const int64_t *) member, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ break;
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ rv += uint64_pack(*(const uint64_t *) member, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ break;
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_32BIT;
+ rv += fixed32_pack(*(const uint32_t *) member, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ break;
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_64BIT;
+ rv += fixed64_pack(*(const uint64_t *) member, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ break;
+ case PROTOBUF_C_TYPE_BOOL:
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_VARINT;
+ rv += boolean_pack(*(const protobuf_c_boolean *) member, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ break;
+ case PROTOBUF_C_TYPE_STRING: {
+ const char *str = *(char *const *) member;
+ size_t sublen = str ? strlen(str) : 0;
+
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+ rv += uint32_pack(sublen, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ buffer->append(buffer, sublen, (const uint8_t *) str);
+ rv += sublen;
+ break;
+ }
+ case PROTOBUF_C_TYPE_BYTES: {
+ const ProtobufCBinaryData *bd = ((const ProtobufCBinaryData *) member);
+ size_t sublen = bd->len;
+
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+ rv += uint32_pack(sublen, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ buffer->append(buffer, sublen, bd->data);
+ rv += sublen;
+ break;
+ }
+ case PROTOBUF_C_TYPE_MESSAGE: {
+ const ProtobufCMessage *msg = *(ProtobufCMessage * const *) member;
+
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+ if (msg == NULL) {
+ rv += uint32_pack(0, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ } else {
+ size_t sublen = protobuf_c_message_get_packed_size(msg);
+ rv += uint32_pack(sublen, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ protobuf_c_message_pack_to_buffer(msg, buffer);
+ rv += sublen;
+ }
+ break;
+ }
+ default:
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ }
+ return rv;
+}
+
+/**
+ * Pack a oneof field to a buffer. Only packs the field that is selected by the case enum.
+ *
+ * \param field
+ * Field descriptor.
+ * \param oneof_case
+ * Enum value that selects the field in the oneof.
+ * \param member
+ * The element to be packed.
+ * \param[out] buffer
+ * Virtual buffer to append data to.
+ * \return
+ * Number of bytes serialised to `buffer`.
+ */
+static size_t
+oneof_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
+ uint32_t oneof_case,
+ const void *member, ProtobufCBuffer *buffer)
+{
+ if (oneof_case != field->id) {
+ return 0;
+ }
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
+ field->type == PROTOBUF_C_TYPE_STRING)
+ {
+ const void *ptr = *(const void *const *) member;
+ if (ptr == NULL || ptr == field->default_value)
+ return 0;
+ }
+ return required_field_pack_to_buffer(field, member, buffer);
+}
+
+/**
+ * Pack an optional field to a buffer.
+ *
+ * \param field
+ * Field descriptor.
+ * \param has
+ * Whether the field is set.
+ * \param member
+ * The element to be packed.
+ * \param[out] buffer
+ * Virtual buffer to append data to.
+ * \return
+ * Number of bytes serialised to `buffer`.
+ */
+static size_t
+optional_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
+ const protobuf_c_boolean has,
+ const void *member, ProtobufCBuffer *buffer)
+{
+ if (field->type == PROTOBUF_C_TYPE_MESSAGE ||
+ field->type == PROTOBUF_C_TYPE_STRING)
+ {
+ const void *ptr = *(const void *const *) member;
+ if (ptr == NULL || ptr == field->default_value)
+ return 0;
+ } else {
+ if (!has)
+ return 0;
+ }
+ return required_field_pack_to_buffer(field, member, buffer);
+}
+
+/**
+ * Pack an unlabeled field to a buffer.
+ *
+ * \param field
+ * Field descriptor.
+ * \param member
+ * The element to be packed.
+ * \param[out] buffer
+ * Virtual buffer to append data to.
+ * \return
+ * Number of bytes serialised to `buffer`.
+ */
+static size_t
+unlabeled_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
+ const void *member, ProtobufCBuffer *buffer)
+{
+ if (field_is_zeroish(field, member))
+ return 0;
+ return required_field_pack_to_buffer(field, member, buffer);
+}
+
+/**
+ * Get the packed size of an array of same field type.
+ *
+ * \param field
+ * Field descriptor.
+ * \param count
+ * Number of elements of this type.
+ * \param array
+ * The elements to get the size of.
+ * \return
+ * Number of bytes required.
+ */
+static size_t
+get_packed_payload_length(const ProtobufCFieldDescriptor *field,
+ unsigned count, const void *array)
+{
+ unsigned rv = 0;
+ unsigned i;
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ return count * 4;
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ return count * 8;
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32: {
+ const int32_t *arr = (const int32_t *) array;
+ for (i = 0; i < count; i++)
+ rv += int32_size(arr[i]);
+ break;
+ }
+ case PROTOBUF_C_TYPE_SINT32: {
+ const int32_t *arr = (const int32_t *) array;
+ for (i = 0; i < count; i++)
+ rv += sint32_size(arr[i]);
+ break;
+ }
+ case PROTOBUF_C_TYPE_UINT32: {
+ const uint32_t *arr = (const uint32_t *) array;
+ for (i = 0; i < count; i++)
+ rv += uint32_size(arr[i]);
+ break;
+ }
+ case PROTOBUF_C_TYPE_SINT64: {
+ const int64_t *arr = (const int64_t *) array;
+ for (i = 0; i < count; i++)
+ rv += sint64_size(arr[i]);
+ break;
+ }
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64: {
+ const uint64_t *arr = (const uint64_t *) array;
+ for (i = 0; i < count; i++)
+ rv += uint64_size(arr[i]);
+ break;
+ }
+ case PROTOBUF_C_TYPE_BOOL:
+ return count;
+ default:
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ }
+ return rv;
+}
+
+/**
+ * Pack an array of same field type to a virtual buffer.
+ *
+ * \param field
+ * Field descriptor.
+ * \param count
+ * Number of elements of this type.
+ * \param array
+ * The elements to get the size of.
+ * \param[out] buffer
+ * Virtual buffer to append data to.
+ * \return
+ * Number of bytes packed.
+ */
+static size_t
+pack_buffer_packed_payload(const ProtobufCFieldDescriptor *field,
+ unsigned count, const void *array,
+ ProtobufCBuffer *buffer)
+{
+ uint8_t scratch[16];
+ size_t rv = 0;
+ unsigned i;
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+#if !defined(WORDS_BIGENDIAN)
+ rv = count * 4;
+ goto no_packing_needed;
+#else
+ for (i = 0; i < count; i++) {
+ unsigned len = fixed32_pack(((uint32_t *) array)[i], scratch);
+ buffer->append(buffer, len, scratch);
+ rv += len;
+ }
+ break;
+#endif
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+#if !defined(WORDS_BIGENDIAN)
+ rv = count * 8;
+ goto no_packing_needed;
+#else
+ for (i = 0; i < count; i++) {
+ unsigned len = fixed64_pack(((uint64_t *) array)[i], scratch);
+ buffer->append(buffer, len, scratch);
+ rv += len;
+ }
+ break;
+#endif
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32:
+ for (i = 0; i < count; i++) {
+ unsigned len = int32_pack(((int32_t *) array)[i], scratch);
+ buffer->append(buffer, len, scratch);
+ rv += len;
+ }
+ break;
+ case PROTOBUF_C_TYPE_SINT32:
+ for (i = 0; i < count; i++) {
+ unsigned len = sint32_pack(((int32_t *) array)[i], scratch);
+ buffer->append(buffer, len, scratch);
+ rv += len;
+ }
+ break;
+ case PROTOBUF_C_TYPE_UINT32:
+ for (i = 0; i < count; i++) {
+ unsigned len = uint32_pack(((uint32_t *) array)[i], scratch);
+ buffer->append(buffer, len, scratch);
+ rv += len;
+ }
+ break;
+ case PROTOBUF_C_TYPE_SINT64:
+ for (i = 0; i < count; i++) {
+ unsigned len = sint64_pack(((int64_t *) array)[i], scratch);
+ buffer->append(buffer, len, scratch);
+ rv += len;
+ }
+ break;
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ for (i = 0; i < count; i++) {
+ unsigned len = uint64_pack(((uint64_t *) array)[i], scratch);
+ buffer->append(buffer, len, scratch);
+ rv += len;
+ }
+ break;
+ case PROTOBUF_C_TYPE_BOOL:
+ for (i = 0; i < count; i++) {
+ unsigned len = boolean_pack(((protobuf_c_boolean *) array)[i], scratch);
+ buffer->append(buffer, len, scratch);
+ rv += len;
+ }
+ return count;
+ default:
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ }
+ return rv;
+
+#if !defined(WORDS_BIGENDIAN)
+no_packing_needed:
+ buffer->append(buffer, rv, array);
+ return rv;
+#endif
+}
+
+static size_t
+repeated_field_pack_to_buffer(const ProtobufCFieldDescriptor *field,
+ unsigned count, const void *member,
+ ProtobufCBuffer *buffer)
+{
+ char *array = *(char * const *) member;
+
+ if (count == 0)
+ return 0;
+ if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED)) {
+ uint8_t scratch[MAX_UINT64_ENCODED_SIZE * 2];
+ size_t rv = tag_pack(field->id, scratch);
+ size_t payload_len = get_packed_payload_length(field, count, array);
+ size_t tmp;
+
+ scratch[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
+ rv += uint32_pack(payload_len, scratch + rv);
+ buffer->append(buffer, rv, scratch);
+ tmp = pack_buffer_packed_payload(field, count, array, buffer);
+ assert(tmp == payload_len);
+ return rv + payload_len;
+ } else {
+ size_t siz;
+ unsigned i;
+ /* CONSIDER: optimize this case a bit (by putting the loop inside the switch) */
+ unsigned rv = 0;
+
+ siz = sizeof_elt_in_repeated_array(field->type);
+ for (i = 0; i < count; i++) {
+ rv += required_field_pack_to_buffer(field, array, buffer);
+ array += siz;
+ }
+ return rv;
+ }
+}
+
+static size_t
+unknown_field_pack_to_buffer(const ProtobufCMessageUnknownField *field,
+ ProtobufCBuffer *buffer)
+{
+ uint8_t header[MAX_UINT64_ENCODED_SIZE];
+ size_t rv = tag_pack(field->tag, header);
+
+ header[0] |= field->wire_type;
+ buffer->append(buffer, rv, header);
+ buffer->append(buffer, field->len, field->data);
+ return rv + field->len;
+}
+
+/**@}*/
+
+size_t
+protobuf_c_message_pack_to_buffer(const ProtobufCMessage *message,
+ ProtobufCBuffer *buffer)
+{
+ unsigned i;
+ size_t rv = 0;
+
+ ASSERT_IS_MESSAGE(message);
+ for (i = 0; i < message->descriptor->n_fields; i++) {
+ const ProtobufCFieldDescriptor *field =
+ message->descriptor->fields + i;
+ const void *member =
+ ((const char *) message) + field->offset;
+ const void *qmember =
+ ((const char *) message) + field->quantifier_offset;
+
+ if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
+ rv += required_field_pack_to_buffer(field, member, buffer);
+ } else if ((field->label == PROTOBUF_C_LABEL_OPTIONAL ||
+ field->label == PROTOBUF_C_LABEL_NONE) &&
+ (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF))) {
+ rv += oneof_field_pack_to_buffer(
+ field,
+ *(const uint32_t *) qmember,
+ member,
+ buffer
+ );
+ } else if (field->label == PROTOBUF_C_LABEL_OPTIONAL) {
+ rv += optional_field_pack_to_buffer(
+ field,
+ *(const protobuf_c_boolean *) qmember,
+ member,
+ buffer
+ );
+ } else if (field->label == PROTOBUF_C_LABEL_NONE) {
+ rv += unlabeled_field_pack_to_buffer(
+ field,
+ member,
+ buffer
+ );
+ } else {
+ rv += repeated_field_pack_to_buffer(
+ field,
+ *(const size_t *) qmember,
+ member,
+ buffer
+ );
+ }
+ }
+ for (i = 0; i < message->n_unknown_fields; i++)
+ rv += unknown_field_pack_to_buffer(&message->unknown_fields[i], buffer);
+
+ return rv;
+}
+
+/**
+ * \defgroup unpack unpacking implementation
+ *
+ * Routines mainly used by the unpacking functions.
+ *
+ * \ingroup internal
+ * @{
+ */
+
+static inline int
+int_range_lookup(unsigned n_ranges, const ProtobufCIntRange *ranges, int value)
+{
+ unsigned n;
+ unsigned start;
+
+ if (n_ranges == 0)
+ return -1;
+ start = 0;
+ n = n_ranges;
+ while (n > 1) {
+ unsigned mid = start + n / 2;
+
+ if (value < ranges[mid].start_value) {
+ n = mid - start;
+ } else if (value >= ranges[mid].start_value +
+ (int) (ranges[mid + 1].orig_index -
+ ranges[mid].orig_index))
+ {
+ unsigned new_start = mid + 1;
+ n = start + n - new_start;
+ start = new_start;
+ } else
+ return (value - ranges[mid].start_value) +
+ ranges[mid].orig_index;
+ }
+ if (n > 0) {
+ unsigned start_orig_index = ranges[start].orig_index;
+ unsigned range_size =
+ ranges[start + 1].orig_index - start_orig_index;
+
+ if (ranges[start].start_value <= value &&
+ value < (int) (ranges[start].start_value + range_size))
+ {
+ return (value - ranges[start].start_value) +
+ start_orig_index;
+ }
+ }
+ return -1;
+}
+
+static size_t
+parse_tag_and_wiretype(size_t len,
+ const uint8_t *data,
+ uint32_t *tag_out,
+ uint8_t *wiretype_out)
+{
+ unsigned max_rv = len > 5 ? 5 : len;
+ uint32_t tag = (data[0] & 0x7f) >> 3;
+ unsigned shift = 4;
+ unsigned rv;
+
+ /* 0 is not a valid tag value */
+ if ((data[0] & 0xf8) == 0) {
+ return 0;
+ }
+
+ *wiretype_out = data[0] & 7;
+ if ((data[0] & 0x80) == 0) {
+ *tag_out = tag;
+ return 1;
+ }
+ for (rv = 1; rv < max_rv; rv++) {
+ if (data[rv] & 0x80) {
+ tag |= (data[rv] & 0x7f) << shift;
+ shift += 7;
+ } else {
+ tag |= data[rv] << shift;
+ *tag_out = tag;
+ return rv + 1;
+ }
+ }
+ return 0; /* error: bad header */
+}
+
+/* sizeof(ScannedMember) must be <= (1UL<<BOUND_SIZEOF_SCANNED_MEMBER_LOG2) */
+#define BOUND_SIZEOF_SCANNED_MEMBER_LOG2 5
+typedef struct ScannedMember ScannedMember;
+/** Field as it's being read. */
+struct ScannedMember {
+ uint32_t tag; /**< Field tag. */
+ uint8_t wire_type; /**< Field type. */
+ uint8_t length_prefix_len; /**< Prefix length. */
+ const ProtobufCFieldDescriptor *field; /**< Field descriptor. */
+ size_t len; /**< Field length. */
+ const uint8_t *data; /**< Pointer to field data. */
+};
+
+static inline size_t
+scan_length_prefixed_data(size_t len, const uint8_t *data,
+ size_t *prefix_len_out)
+{
+ unsigned hdr_max = len < 5 ? len : 5;
+ unsigned hdr_len;
+ size_t val = 0;
+ unsigned i;
+ unsigned shift = 0;
+
+ for (i = 0; i < hdr_max; i++) {
+ val |= ((size_t)data[i] & 0x7f) << shift;
+ shift += 7;
+ if ((data[i] & 0x80) == 0)
+ break;
+ }
+ if (i == hdr_max) {
+ PROTOBUF_C_UNPACK_ERROR("error parsing length for length-prefixed data");
+ return 0;
+ }
+ hdr_len = i + 1;
+ *prefix_len_out = hdr_len;
+ if (val > INT_MAX) {
+ // Protobuf messages should always be less than 2 GiB in size.
+ // We also want to return early here so that hdr_len + val does
+ // not overflow on 32-bit systems.
+ PROTOBUF_C_UNPACK_ERROR("length prefix of %lu is too large",
+ (unsigned long int)val);
+ return 0;
+ }
+ if (hdr_len + val > len) {
+ PROTOBUF_C_UNPACK_ERROR("data too short after length-prefix of %lu",
+ (unsigned long int)val);
+ return 0;
+ }
+ return hdr_len + val;
+}
+
+static size_t
+max_b128_numbers(size_t len, const uint8_t *data)
+{
+ size_t rv = 0;
+ while (len--)
+ if ((*data++ & 0x80) == 0)
+ ++rv;
+ return rv;
+}
+
+/**@}*/
+
+/**
+ * Merge earlier message into a latter message.
+ *
+ * For numeric types and strings, if the same value appears multiple
+ * times, the parser accepts the last value it sees. For embedded
+ * message fields, the parser merges multiple instances of the same
+ * field. That is, all singular scalar fields in the latter instance
+ * replace those in the former, singular embedded messages are merged,
+ * and repeated fields are concatenated.
+ *
+ * The earlier message should be freed after calling this function, as
+ * some of its fields may have been reused and changed to their default
+ * values during the merge.
+ */
+static protobuf_c_boolean
+merge_messages(ProtobufCMessage *earlier_msg,
+ ProtobufCMessage *latter_msg,
+ ProtobufCAllocator *allocator)
+{
+ unsigned i;
+ const ProtobufCFieldDescriptor *fields =
+ latter_msg->descriptor->fields;
+ for (i = 0; i < latter_msg->descriptor->n_fields; i++) {
+ if (fields[i].label == PROTOBUF_C_LABEL_REPEATED) {
+ size_t *n_earlier =
+ STRUCT_MEMBER_PTR(size_t, earlier_msg,
+ fields[i].quantifier_offset);
+ uint8_t **p_earlier =
+ STRUCT_MEMBER_PTR(uint8_t *, earlier_msg,
+ fields[i].offset);
+ size_t *n_latter =
+ STRUCT_MEMBER_PTR(size_t, latter_msg,
+ fields[i].quantifier_offset);
+ uint8_t **p_latter =
+ STRUCT_MEMBER_PTR(uint8_t *, latter_msg,
+ fields[i].offset);
+
+ if (*n_earlier > 0) {
+ if (*n_latter > 0) {
+ /* Concatenate the repeated field */
+ size_t el_size =
+ sizeof_elt_in_repeated_array(fields[i].type);
+ uint8_t *new_field;
+
+ new_field = do_alloc(allocator,
+ (*n_earlier + *n_latter) * el_size);
+ if (!new_field)
+ return FALSE;
+
+ memcpy(new_field, *p_earlier,
+ *n_earlier * el_size);
+ memcpy(new_field +
+ *n_earlier * el_size,
+ *p_latter,
+ *n_latter * el_size);
+
+ do_free(allocator, *p_latter);
+ do_free(allocator, *p_earlier);
+ *p_latter = new_field;
+ *n_latter = *n_earlier + *n_latter;
+ } else {
+ /* Zero copy the repeated field from the earlier message */
+ *n_latter = *n_earlier;
+ *p_latter = *p_earlier;
+ }
+ /* Make sure the field does not get double freed */
+ *n_earlier = 0;
+ *p_earlier = 0;
+ }
+ } else if (fields[i].label == PROTOBUF_C_LABEL_OPTIONAL ||
+ fields[i].label == PROTOBUF_C_LABEL_NONE) {
+ const ProtobufCFieldDescriptor *field;
+ uint32_t *earlier_case_p = STRUCT_MEMBER_PTR(uint32_t,
+ earlier_msg,
+ fields[i].
+ quantifier_offset);
+ uint32_t *latter_case_p = STRUCT_MEMBER_PTR(uint32_t,
+ latter_msg,
+ fields[i].
+ quantifier_offset);
+ protobuf_c_boolean need_to_merge = FALSE;
+ void *earlier_elem;
+ void *latter_elem;
+ const void *def_val;
+
+ if (fields[i].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) {
+ if (*latter_case_p == 0) {
+ /* lookup correct oneof field */
+ int field_index =
+ int_range_lookup(
+ latter_msg->descriptor
+ ->n_field_ranges,
+ latter_msg->descriptor
+ ->field_ranges,
+ *earlier_case_p);
+ if (field_index < 0)
+ return FALSE;
+ field = latter_msg->descriptor->fields +
+ field_index;
+ } else {
+ /* Oneof is present in the latter message, move on */
+ continue;
+ }
+ } else {
+ field = &fields[i];
+ }
+
+ earlier_elem = STRUCT_MEMBER_P(earlier_msg, field->offset);
+ latter_elem = STRUCT_MEMBER_P(latter_msg, field->offset);
+ def_val = field->default_value;
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_MESSAGE: {
+ ProtobufCMessage *em = *(ProtobufCMessage **) earlier_elem;
+ ProtobufCMessage *lm = *(ProtobufCMessage **) latter_elem;
+ if (em != NULL) {
+ if (lm != NULL) {
+ if (!merge_messages(em, lm, allocator))
+ return FALSE;
+ /* Already merged */
+ need_to_merge = FALSE;
+ } else {
+ /* Zero copy the message */
+ need_to_merge = TRUE;
+ }
+ }
+ break;
+ }
+ case PROTOBUF_C_TYPE_BYTES: {
+ uint8_t *e_data =
+ ((ProtobufCBinaryData *) earlier_elem)->data;
+ uint8_t *l_data =
+ ((ProtobufCBinaryData *) latter_elem)->data;
+ const ProtobufCBinaryData *d_bd =
+ (ProtobufCBinaryData *) def_val;
+
+ need_to_merge =
+ (e_data != NULL &&
+ (d_bd == NULL ||
+ e_data != d_bd->data)) &&
+ (l_data == NULL ||
+ (d_bd != NULL &&
+ l_data == d_bd->data));
+ break;
+ }
+ case PROTOBUF_C_TYPE_STRING: {
+ char *e_str = *(char **) earlier_elem;
+ char *l_str = *(char **) latter_elem;
+ const char *d_str = def_val;
+
+ need_to_merge = e_str != d_str && l_str == d_str;
+ break;
+ }
+ default: {
+ /* Could be has field or case enum, the logic is
+ * equivalent, since 0 (FALSE) means not set for
+ * oneof */
+ need_to_merge = (*earlier_case_p != 0) &&
+ (*latter_case_p == 0);
+ break;
+ }
+ }
+
+ if (need_to_merge) {
+ size_t el_size =
+ sizeof_elt_in_repeated_array(field->type);
+ memcpy(latter_elem, earlier_elem, el_size);
+ /*
+ * Reset the element from the old message to 0
+ * to make sure earlier message deallocation
+ * doesn't corrupt zero-copied data in the new
+ * message, earlier message will be freed after
+ * this function is called anyway
+ */
+ memset(earlier_elem, 0, el_size);
+
+ if (field->quantifier_offset != 0) {
+ /* Set the has field or the case enum,
+ * if applicable */
+ *latter_case_p = *earlier_case_p;
+ *earlier_case_p = 0;
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Count packed elements.
+ *
+ * Given a raw slab of packed-repeated values, determine the number of
+ * elements. This function detects certain kinds of errors but not
+ * others; the remaining error checking is done by
+ * parse_packed_repeated_member().
+ */
+static protobuf_c_boolean
+count_packed_elements(ProtobufCType type,
+ size_t len, const uint8_t *data, size_t *count_out)
+{
+ switch (type) {
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ if (len % 4 != 0) {
+ PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 4 for fixed-length 32-bit types");
+ return FALSE;
+ }
+ *count_out = len / 4;
+ return TRUE;
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ if (len % 8 != 0) {
+ PROTOBUF_C_UNPACK_ERROR("length must be a multiple of 8 for fixed-length 64-bit types");
+ return FALSE;
+ }
+ *count_out = len / 8;
+ return TRUE;
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32:
+ case PROTOBUF_C_TYPE_SINT32:
+ case PROTOBUF_C_TYPE_UINT32:
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_SINT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ *count_out = max_b128_numbers(len, data);
+ return TRUE;
+ case PROTOBUF_C_TYPE_BOOL:
+ *count_out = len;
+ return TRUE;
+ case PROTOBUF_C_TYPE_STRING:
+ case PROTOBUF_C_TYPE_BYTES:
+ case PROTOBUF_C_TYPE_MESSAGE:
+ default:
+ PROTOBUF_C_UNPACK_ERROR("bad protobuf-c type %u for packed-repeated", type);
+ return FALSE;
+ }
+}
+
+static inline uint32_t
+parse_uint32(unsigned len, const uint8_t *data)
+{
+ uint32_t rv = data[0] & 0x7f;
+ if (len > 1) {
+ rv |= ((uint32_t) (data[1] & 0x7f) << 7);
+ if (len > 2) {
+ rv |= ((uint32_t) (data[2] & 0x7f) << 14);
+ if (len > 3) {
+ rv |= ((uint32_t) (data[3] & 0x7f) << 21);
+ if (len > 4)
+ rv |= ((uint32_t) (data[4]) << 28);
+ }
+ }
+ }
+ return rv;
+}
+
+static inline uint32_t
+parse_int32(unsigned len, const uint8_t *data)
+{
+ return parse_uint32(len, data);
+}
+
+static inline int32_t
+unzigzag32(uint32_t v)
+{
+ // Note: Using unsigned types prevents undefined behavior
+ return (int32_t)((v >> 1) ^ -(v & 1));
+}
+
+static inline uint32_t
+parse_fixed_uint32(const uint8_t *data)
+{
+#if !defined(WORDS_BIGENDIAN)
+ uint32_t t;
+ memcpy(&t, data, 4);
+ return t;
+#else
+ return data[0] |
+ ((uint32_t) (data[1]) << 8) |
+ ((uint32_t) (data[2]) << 16) |
+ ((uint32_t) (data[3]) << 24);
+#endif
+}
+
+static uint64_t
+parse_uint64(unsigned len, const uint8_t *data)
+{
+ unsigned shift, i;
+ uint64_t rv;
+
+ if (len < 5)
+ return parse_uint32(len, data);
+ rv = ((uint64_t) (data[0] & 0x7f)) |
+ ((uint64_t) (data[1] & 0x7f) << 7) |
+ ((uint64_t) (data[2] & 0x7f) << 14) |
+ ((uint64_t) (data[3] & 0x7f) << 21);
+ shift = 28;
+ for (i = 4; i < len; i++) {
+ rv |= (((uint64_t) (data[i] & 0x7f)) << shift);
+ shift += 7;
+ }
+ return rv;
+}
+
+static inline int64_t
+unzigzag64(uint64_t v)
+{
+ // Note: Using unsigned types prevents undefined behavior
+ return (int64_t)((v >> 1) ^ -(v & 1));
+}
+
+static inline uint64_t
+parse_fixed_uint64(const uint8_t *data)
+{
+#if !defined(WORDS_BIGENDIAN)
+ uint64_t t;
+ memcpy(&t, data, 8);
+ return t;
+#else
+ return (uint64_t) parse_fixed_uint32(data) |
+ (((uint64_t) parse_fixed_uint32(data + 4)) << 32);
+#endif
+}
+
+static protobuf_c_boolean
+parse_boolean(unsigned len, const uint8_t *data)
+{
+ unsigned i;
+ for (i = 0; i < len; i++)
+ if (data[i] & 0x7f)
+ return TRUE;
+ return FALSE;
+}
+
+static protobuf_c_boolean
+parse_required_member(ScannedMember *scanned_member,
+ void *member,
+ ProtobufCAllocator *allocator,
+ protobuf_c_boolean maybe_clear)
+{
+ unsigned len = scanned_member->len;
+ const uint8_t *data = scanned_member->data;
+ uint8_t wire_type = scanned_member->wire_type;
+
+ switch (scanned_member->field->type) {
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32:
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
+ return FALSE;
+ *(int32_t *) member = parse_int32(len, data);
+ return TRUE;
+ case PROTOBUF_C_TYPE_UINT32:
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
+ return FALSE;
+ *(uint32_t *) member = parse_uint32(len, data);
+ return TRUE;
+ case PROTOBUF_C_TYPE_SINT32:
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
+ return FALSE;
+ *(int32_t *) member = unzigzag32(parse_uint32(len, data));
+ return TRUE;
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_32BIT)
+ return FALSE;
+ *(uint32_t *) member = parse_fixed_uint32(data);
+ return TRUE;
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
+ return FALSE;
+ *(uint64_t *) member = parse_uint64(len, data);
+ return TRUE;
+ case PROTOBUF_C_TYPE_SINT64:
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_VARINT)
+ return FALSE;
+ *(int64_t *) member = unzigzag64(parse_uint64(len, data));
+ return TRUE;
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_64BIT)
+ return FALSE;
+ *(uint64_t *) member = parse_fixed_uint64(data);
+ return TRUE;
+ case PROTOBUF_C_TYPE_BOOL:
+ *(protobuf_c_boolean *) member = parse_boolean(len, data);
+ return TRUE;
+ case PROTOBUF_C_TYPE_STRING: {
+ char **pstr = member;
+ unsigned pref_len = scanned_member->length_prefix_len;
+
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
+ return FALSE;
+
+ if (maybe_clear && *pstr != NULL) {
+ const char *def = scanned_member->field->default_value;
+ if (*pstr != NULL && *pstr != def)
+ do_free(allocator, *pstr);
+ }
+ *pstr = do_alloc(allocator, len - pref_len + 1);
+ if (*pstr == NULL)
+ return FALSE;
+ memcpy(*pstr, data + pref_len, len - pref_len);
+ (*pstr)[len - pref_len] = 0;
+ return TRUE;
+ }
+ case PROTOBUF_C_TYPE_BYTES: {
+ ProtobufCBinaryData *bd = member;
+ const ProtobufCBinaryData *def_bd;
+ unsigned pref_len = scanned_member->length_prefix_len;
+
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
+ return FALSE;
+
+ def_bd = scanned_member->field->default_value;
+ if (maybe_clear &&
+ bd->data != NULL &&
+ (def_bd == NULL || bd->data != def_bd->data))
+ {
+ do_free(allocator, bd->data);
+ }
+ if (len > pref_len) {
+ bd->data = do_alloc(allocator, len - pref_len);
+ if (bd->data == NULL)
+ return FALSE;
+ memcpy(bd->data, data + pref_len, len - pref_len);
+ } else {
+ bd->data = NULL;
+ }
+ bd->len = len - pref_len;
+ return TRUE;
+ }
+ case PROTOBUF_C_TYPE_MESSAGE: {
+ ProtobufCMessage **pmessage = member;
+ ProtobufCMessage *subm;
+ const ProtobufCMessage *def_mess;
+ protobuf_c_boolean merge_successful = TRUE;
+ unsigned pref_len = scanned_member->length_prefix_len;
+
+ if (wire_type != PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED)
+ return FALSE;
+
+ def_mess = scanned_member->field->default_value;
+ if (len >= pref_len)
+ subm = protobuf_c_message_unpack(scanned_member->field->descriptor,
+ allocator,
+ len - pref_len,
+ data + pref_len);
+ else
+ subm = NULL;
+
+ if (maybe_clear &&
+ *pmessage != NULL &&
+ *pmessage != def_mess)
+ {
+ if (subm != NULL)
+ merge_successful = merge_messages(*pmessage, subm, allocator);
+ /* Delete the previous message */
+ protobuf_c_message_free_unpacked(*pmessage, allocator);
+ }
+ *pmessage = subm;
+ if (subm == NULL || !merge_successful)
+ return FALSE;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static protobuf_c_boolean
+parse_oneof_member (ScannedMember *scanned_member,
+ void *member,
+ ProtobufCMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ uint32_t *oneof_case = STRUCT_MEMBER_PTR(uint32_t, message,
+ scanned_member->field->quantifier_offset);
+
+ /* If we have already parsed a member of this oneof, free it. */
+ if (*oneof_case != 0) {
+ const ProtobufCFieldDescriptor *old_field;
+ size_t el_size;
+ /* lookup field */
+ int field_index =
+ int_range_lookup(message->descriptor->n_field_ranges,
+ message->descriptor->field_ranges,
+ *oneof_case);
+ if (field_index < 0)
+ return FALSE;
+ old_field = message->descriptor->fields + field_index;
+ el_size = sizeof_elt_in_repeated_array(old_field->type);
+
+ switch (old_field->type) {
+ case PROTOBUF_C_TYPE_STRING: {
+ char **pstr = member;
+ const char *def = old_field->default_value;
+ if (*pstr != NULL && *pstr != def)
+ do_free(allocator, *pstr);
+ break;
+ }
+ case PROTOBUF_C_TYPE_BYTES: {
+ ProtobufCBinaryData *bd = member;
+ const ProtobufCBinaryData *def_bd = old_field->default_value;
+ if (bd->data != NULL &&
+ (def_bd == NULL || bd->data != def_bd->data))
+ {
+ do_free(allocator, bd->data);
+ }
+ break;
+ }
+ case PROTOBUF_C_TYPE_MESSAGE: {
+ ProtobufCMessage **pmessage = member;
+ const ProtobufCMessage *def_mess = old_field->default_value;
+ if (*pmessage != NULL && *pmessage != def_mess)
+ protobuf_c_message_free_unpacked(*pmessage, allocator);
+ break;
+ }
+ default:
+ break;
+ }
+
+ memset (member, 0, el_size);
+ }
+ if (!parse_required_member (scanned_member, member, allocator, TRUE))
+ return FALSE;
+
+ *oneof_case = scanned_member->tag;
+ return TRUE;
+}
+
+
+static protobuf_c_boolean
+parse_optional_member(ScannedMember *scanned_member,
+ void *member,
+ ProtobufCMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ if (!parse_required_member(scanned_member, member, allocator, TRUE))
+ return FALSE;
+ if (scanned_member->field->quantifier_offset != 0)
+ STRUCT_MEMBER(protobuf_c_boolean,
+ message,
+ scanned_member->field->quantifier_offset) = TRUE;
+ return TRUE;
+}
+
+static protobuf_c_boolean
+parse_repeated_member(ScannedMember *scanned_member,
+ void *member,
+ ProtobufCMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ const ProtobufCFieldDescriptor *field = scanned_member->field;
+ size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
+ size_t siz = sizeof_elt_in_repeated_array(field->type);
+ char *array = *(char **) member;
+
+ if (!parse_required_member(scanned_member, array + siz * (*p_n),
+ allocator, FALSE))
+ {
+ return FALSE;
+ }
+ *p_n += 1;
+ return TRUE;
+}
+
+static unsigned
+scan_varint(unsigned len, const uint8_t *data)
+{
+ unsigned i;
+ if (len > 10)
+ len = 10;
+ for (i = 0; i < len; i++)
+ if ((data[i] & 0x80) == 0)
+ break;
+ if (i == len)
+ return 0;
+ return i + 1;
+}
+
+static protobuf_c_boolean
+parse_packed_repeated_member(ScannedMember *scanned_member,
+ void *member,
+ ProtobufCMessage *message)
+{
+ const ProtobufCFieldDescriptor *field = scanned_member->field;
+ size_t *p_n = STRUCT_MEMBER_PTR(size_t, message, field->quantifier_offset);
+ size_t siz = sizeof_elt_in_repeated_array(field->type);
+ void *array = *(char **) member + siz * (*p_n);
+ const uint8_t *at = scanned_member->data + scanned_member->length_prefix_len;
+ size_t rem = scanned_member->len - scanned_member->length_prefix_len;
+ size_t count = 0;
+#if defined(WORDS_BIGENDIAN)
+ unsigned i;
+#endif
+
+ switch (field->type) {
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ count = (scanned_member->len - scanned_member->length_prefix_len) / 4;
+#if !defined(WORDS_BIGENDIAN)
+ goto no_unpacking_needed;
+#else
+ for (i = 0; i < count; i++) {
+ ((uint32_t *) array)[i] = parse_fixed_uint32(at);
+ at += 4;
+ }
+ break;
+#endif
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ count = (scanned_member->len - scanned_member->length_prefix_len) / 8;
+#if !defined(WORDS_BIGENDIAN)
+ goto no_unpacking_needed;
+#else
+ for (i = 0; i < count; i++) {
+ ((uint64_t *) array)[i] = parse_fixed_uint64(at);
+ at += 8;
+ }
+ break;
+#endif
+ case PROTOBUF_C_TYPE_ENUM:
+ case PROTOBUF_C_TYPE_INT32:
+ while (rem > 0) {
+ unsigned s = scan_varint(rem, at);
+ if (s == 0) {
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int32 value");
+ return FALSE;
+ }
+ ((int32_t *) array)[count++] = parse_int32(s, at);
+ at += s;
+ rem -= s;
+ }
+ break;
+ case PROTOBUF_C_TYPE_SINT32:
+ while (rem > 0) {
+ unsigned s = scan_varint(rem, at);
+ if (s == 0) {
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint32 value");
+ return FALSE;
+ }
+ ((int32_t *) array)[count++] = unzigzag32(parse_uint32(s, at));
+ at += s;
+ rem -= s;
+ }
+ break;
+ case PROTOBUF_C_TYPE_UINT32:
+ while (rem > 0) {
+ unsigned s = scan_varint(rem, at);
+ if (s == 0) {
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated enum or uint32 value");
+ return FALSE;
+ }
+ ((uint32_t *) array)[count++] = parse_uint32(s, at);
+ at += s;
+ rem -= s;
+ }
+ break;
+
+ case PROTOBUF_C_TYPE_SINT64:
+ while (rem > 0) {
+ unsigned s = scan_varint(rem, at);
+ if (s == 0) {
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated sint64 value");
+ return FALSE;
+ }
+ ((int64_t *) array)[count++] = unzigzag64(parse_uint64(s, at));
+ at += s;
+ rem -= s;
+ }
+ break;
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_UINT64:
+ while (rem > 0) {
+ unsigned s = scan_varint(rem, at);
+ if (s == 0) {
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated int64/uint64 value");
+ return FALSE;
+ }
+ ((int64_t *) array)[count++] = parse_uint64(s, at);
+ at += s;
+ rem -= s;
+ }
+ break;
+ case PROTOBUF_C_TYPE_BOOL:
+ while (rem > 0) {
+ unsigned s = scan_varint(rem, at);
+ if (s == 0) {
+ PROTOBUF_C_UNPACK_ERROR("bad packed-repeated boolean value");
+ return FALSE;
+ }
+ ((protobuf_c_boolean *) array)[count++] = parse_boolean(s, at);
+ at += s;
+ rem -= s;
+ }
+ break;
+ default:
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ }
+ *p_n += count;
+ return TRUE;
+
+#if !defined(WORDS_BIGENDIAN)
+no_unpacking_needed:
+ memcpy(array, at, count * siz);
+ *p_n += count;
+ return TRUE;
+#endif
+}
+
+static protobuf_c_boolean
+is_packable_type(ProtobufCType type)
+{
+ return
+ type != PROTOBUF_C_TYPE_STRING &&
+ type != PROTOBUF_C_TYPE_BYTES &&
+ type != PROTOBUF_C_TYPE_MESSAGE;
+}
+
+static protobuf_c_boolean
+parse_member(ScannedMember *scanned_member,
+ ProtobufCMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ const ProtobufCFieldDescriptor *field = scanned_member->field;
+ void *member;
+
+ if (field == NULL) {
+ ProtobufCMessageUnknownField *ufield =
+ message->unknown_fields +
+ (message->n_unknown_fields++);
+ ufield->tag = scanned_member->tag;
+ ufield->wire_type = scanned_member->wire_type;
+ ufield->len = scanned_member->len;
+ ufield->data = do_alloc(allocator, scanned_member->len);
+ if (ufield->data == NULL)
+ return FALSE;
+ memcpy(ufield->data, scanned_member->data, ufield->len);
+ return TRUE;
+ }
+ member = (char *) message + field->offset;
+ switch (field->label) {
+ case PROTOBUF_C_LABEL_REQUIRED:
+ return parse_required_member(scanned_member, member,
+ allocator, TRUE);
+ case PROTOBUF_C_LABEL_OPTIONAL:
+ case PROTOBUF_C_LABEL_NONE:
+ if (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_ONEOF)) {
+ return parse_oneof_member(scanned_member, member,
+ message, allocator);
+ } else {
+ return parse_optional_member(scanned_member, member,
+ message, allocator);
+ }
+ case PROTOBUF_C_LABEL_REPEATED:
+ if (scanned_member->wire_type ==
+ PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED &&
+ (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) ||
+ is_packable_type(field->type)))
+ {
+ return parse_packed_repeated_member(scanned_member,
+ member, message);
+ } else {
+ return parse_repeated_member(scanned_member,
+ member, message,
+ allocator);
+ }
+ }
+ PROTOBUF_C__ASSERT_NOT_REACHED();
+ return 0;
+}
+
+/**
+ * Initialise messages generated by old code.
+ *
+ * This function is used if desc->message_init == NULL (which occurs
+ * for old code, and which would be useful to support allocating
+ * descriptors dynamically).
+ */
+static void
+message_init_generic(const ProtobufCMessageDescriptor *desc,
+ ProtobufCMessage *message)
+{
+ unsigned i;
+
+ memset(message, 0, desc->sizeof_message);
+ message->descriptor = desc;
+ for (i = 0; i < desc->n_fields; i++) {
+ if (desc->fields[i].default_value != NULL &&
+ desc->fields[i].label != PROTOBUF_C_LABEL_REPEATED)
+ {
+ void *field =
+ STRUCT_MEMBER_P(message, desc->fields[i].offset);
+ const void *dv = desc->fields[i].default_value;
+
+ switch (desc->fields[i].type) {
+ case PROTOBUF_C_TYPE_INT32:
+ case PROTOBUF_C_TYPE_SINT32:
+ case PROTOBUF_C_TYPE_SFIXED32:
+ case PROTOBUF_C_TYPE_UINT32:
+ case PROTOBUF_C_TYPE_FIXED32:
+ case PROTOBUF_C_TYPE_FLOAT:
+ case PROTOBUF_C_TYPE_ENUM:
+ memcpy(field, dv, 4);
+ break;
+ case PROTOBUF_C_TYPE_INT64:
+ case PROTOBUF_C_TYPE_SINT64:
+ case PROTOBUF_C_TYPE_SFIXED64:
+ case PROTOBUF_C_TYPE_UINT64:
+ case PROTOBUF_C_TYPE_FIXED64:
+ case PROTOBUF_C_TYPE_DOUBLE:
+ memcpy(field, dv, 8);
+ break;
+ case PROTOBUF_C_TYPE_BOOL:
+ memcpy(field, dv, sizeof(protobuf_c_boolean));
+ break;
+ case PROTOBUF_C_TYPE_BYTES:
+ memcpy(field, dv, sizeof(ProtobufCBinaryData));
+ break;
+
+ case PROTOBUF_C_TYPE_STRING:
+ case PROTOBUF_C_TYPE_MESSAGE:
+ /*
+ * The next line essentially implements a cast
+ * from const, which is totally unavoidable.
+ */
+ *(const void **) field = dv;
+ break;
+ }
+ }
+ }
+}
+
+/**@}*/
+
+/*
+ * ScannedMember slabs (an unpacking implementation detail). Before doing real
+ * unpacking, we first scan through the elements to see how many there are (for
+ * repeated fields), and which field to use (for non-repeated fields given
+ * twice).
+ *
+ * In order to avoid allocations for small messages, we keep a stack-allocated
+ * slab of ScannedMembers of size FIRST_SCANNED_MEMBER_SLAB_SIZE (16). After we
+ * fill that up, we allocate each slab twice as large as the previous one.
+ */
+#define FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2 4
+
+/*
+ * The number of slabs, including the stack-allocated ones; choose the number so
+ * that we would overflow if we needed a slab larger than provided.
+ */
+#define MAX_SCANNED_MEMBER_SLAB \
+ (sizeof(unsigned int)*8 - 1 \
+ - BOUND_SIZEOF_SCANNED_MEMBER_LOG2 \
+ - FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)
+
+#define REQUIRED_FIELD_BITMAP_SET(index) \
+ (required_fields_bitmap[(index)/8] |= (1UL<<((index)%8)))
+
+#define REQUIRED_FIELD_BITMAP_IS_SET(index) \
+ (required_fields_bitmap[(index)/8] & (1UL<<((index)%8)))
+
+ProtobufCMessage *
+protobuf_c_message_unpack(const ProtobufCMessageDescriptor *desc,
+ ProtobufCAllocator *allocator,
+ size_t len, const uint8_t *data)
+{
+ ProtobufCMessage *rv;
+ size_t rem = len;
+ const uint8_t *at = data;
+ const ProtobufCFieldDescriptor *last_field = desc->fields + 0;
+ ScannedMember first_member_slab[1UL <<
+ FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2];
+
+ /*
+ * scanned_member_slabs[i] is an array of arrays of ScannedMember.
+ * The first slab (scanned_member_slabs[0] is just a pointer to
+ * first_member_slab), above. All subsequent slabs will be allocated
+ * using the allocator.
+ */
+ ScannedMember *scanned_member_slabs[MAX_SCANNED_MEMBER_SLAB + 1];
+ unsigned which_slab = 0; /* the slab we are currently populating */
+ unsigned in_slab_index = 0; /* number of members in the slab */
+ size_t n_unknown = 0;
+ unsigned f;
+ unsigned j;
+ unsigned i_slab;
+ unsigned last_field_index = 0;
+ unsigned required_fields_bitmap_len;
+ unsigned char required_fields_bitmap_stack[16];
+ unsigned char *required_fields_bitmap = required_fields_bitmap_stack;
+ protobuf_c_boolean required_fields_bitmap_alloced = FALSE;
+
+ ASSERT_IS_MESSAGE_DESCRIPTOR(desc);
+
+ if (allocator == NULL)
+ allocator = &protobuf_c__allocator;
+
+ rv = do_alloc(allocator, desc->sizeof_message);
+ if (!rv)
+ return (NULL);
+ scanned_member_slabs[0] = first_member_slab;
+
+ required_fields_bitmap_len = (desc->n_fields + 7) / 8;
+ if (required_fields_bitmap_len > sizeof(required_fields_bitmap_stack)) {
+ required_fields_bitmap = do_alloc(allocator, required_fields_bitmap_len);
+ if (!required_fields_bitmap) {
+ do_free(allocator, rv);
+ return (NULL);
+ }
+ required_fields_bitmap_alloced = TRUE;
+ }
+ memset(required_fields_bitmap, 0, required_fields_bitmap_len);
+
+ /*
+ * Generated code always defines "message_init". However, we provide a
+ * fallback for (1) users of old protobuf-c generated-code that do not
+ * provide the function, and (2) descriptors constructed from some other
+ * source (most likely, direct construction from the .proto file).
+ */
+ if (desc->message_init != NULL)
+ protobuf_c_message_init(desc, rv);
+ else
+ message_init_generic(desc, rv);
+
+ while (rem > 0) {
+ uint32_t tag;
+ uint8_t wire_type;
+ size_t used = parse_tag_and_wiretype(rem, at, &tag, &wire_type);
+ const ProtobufCFieldDescriptor *field;
+ ScannedMember tmp;
+
+ if (used == 0) {
+ PROTOBUF_C_UNPACK_ERROR("error parsing tag/wiretype at offset %u",
+ (unsigned) (at - data));
+ goto error_cleanup_during_scan;
+ }
+ /*
+ * \todo Consider optimizing for field[1].id == tag, if field[1]
+ * exists!
+ */
+ if (last_field == NULL || last_field->id != tag) {
+ /* lookup field */
+ int field_index =
+ int_range_lookup(desc->n_field_ranges,
+ desc->field_ranges,
+ tag);
+ if (field_index < 0) {
+ field = NULL;
+ n_unknown++;
+ } else {
+ field = desc->fields + field_index;
+ last_field = field;
+ last_field_index = field_index;
+ }
+ } else {
+ field = last_field;
+ }
+
+ if (field != NULL && field->label == PROTOBUF_C_LABEL_REQUIRED)
+ REQUIRED_FIELD_BITMAP_SET(last_field_index);
+
+ at += used;
+ rem -= used;
+ tmp.tag = tag;
+ tmp.wire_type = wire_type;
+ tmp.field = field;
+ tmp.data = at;
+ tmp.length_prefix_len = 0;
+
+ switch (wire_type) {
+ case PROTOBUF_C_WIRE_TYPE_VARINT: {
+ unsigned max_len = rem < 10 ? rem : 10;
+ unsigned i;
+
+ for (i = 0; i < max_len; i++)
+ if ((at[i] & 0x80) == 0)
+ break;
+ if (i == max_len) {
+ PROTOBUF_C_UNPACK_ERROR("unterminated varint at offset %u",
+ (unsigned) (at - data));
+ goto error_cleanup_during_scan;
+ }
+ tmp.len = i + 1;
+ break;
+ }
+ case PROTOBUF_C_WIRE_TYPE_64BIT:
+ if (rem < 8) {
+ PROTOBUF_C_UNPACK_ERROR("too short after 64bit wiretype at offset %u",
+ (unsigned) (at - data));
+ goto error_cleanup_during_scan;
+ }
+ tmp.len = 8;
+ break;
+ case PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED: {
+ size_t pref_len;
+
+ tmp.len = scan_length_prefixed_data(rem, at, &pref_len);
+ if (tmp.len == 0) {
+ /* NOTE: scan_length_prefixed_data calls UNPACK_ERROR */
+ goto error_cleanup_during_scan;
+ }
+ tmp.length_prefix_len = pref_len;
+ break;
+ }
+ case PROTOBUF_C_WIRE_TYPE_32BIT:
+ if (rem < 4) {
+ PROTOBUF_C_UNPACK_ERROR("too short after 32bit wiretype at offset %u",
+ (unsigned) (at - data));
+ goto error_cleanup_during_scan;
+ }
+ tmp.len = 4;
+ break;
+ default:
+ PROTOBUF_C_UNPACK_ERROR("unsupported tag %u at offset %u",
+ wire_type, (unsigned) (at - data));
+ goto error_cleanup_during_scan;
+ }
+
+ if (in_slab_index == (1UL <<
+ (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2)))
+ {
+ size_t size;
+
+ in_slab_index = 0;
+ if (which_slab == MAX_SCANNED_MEMBER_SLAB) {
+ PROTOBUF_C_UNPACK_ERROR("too many fields");
+ goto error_cleanup_during_scan;
+ }
+ which_slab++;
+ size = sizeof(ScannedMember)
+ << (which_slab + FIRST_SCANNED_MEMBER_SLAB_SIZE_LOG2);
+ scanned_member_slabs[which_slab] = do_alloc(allocator, size);
+ if (scanned_member_slabs[which_slab] == NULL)
+ goto error_cleanup_during_scan;
+ }
+ scanned_member_slabs[which_slab][in_slab_index++] = tmp;
+
+ if (field != NULL && field->label == PROTOBUF_C_LABEL_REPEATED) {
+ size_t *n = STRUCT_MEMBER_PTR(size_t, rv,
+ field->quantifier_offset);
+ if (wire_type == PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED &&
+ (0 != (field->flags & PROTOBUF_C_FIELD_FLAG_PACKED) ||
+ is_packable_type(field->type)))
+ {
+ size_t count;
+ if (!count_packed_elements(field->type,
+ tmp.len -
+ tmp.length_prefix_len,
+ tmp.data +
+ tmp.length_prefix_len,
+ &count))
+ {
+ PROTOBUF_C_UNPACK_ERROR("counting packed elements");
+ goto error_cleanup_during_scan;
+ }
+ *n += count;
+ } else {
+ *n += 1;
+ }
+ }
+
+ at += tmp.len;
+ rem -= tmp.len;
+ }
+
+ /* allocate space for repeated fields, also check that all required fields have been set */
+ for (f = 0; f < desc->n_fields; f++) {
+ const ProtobufCFieldDescriptor *field = desc->fields + f;
+ if (field == NULL) {
+ continue;
+ }
+ if (field->label == PROTOBUF_C_LABEL_REPEATED) {
+ size_t siz =
+ sizeof_elt_in_repeated_array(field->type);
+ size_t *n_ptr =
+ STRUCT_MEMBER_PTR(size_t, rv,
+ field->quantifier_offset);
+ if (*n_ptr != 0) {
+ unsigned n = *n_ptr;
+ void *a;
+ *n_ptr = 0;
+ assert(rv->descriptor != NULL);
+#define CLEAR_REMAINING_N_PTRS() \
+ for(f++;f < desc->n_fields; f++) \
+ { \
+ field = desc->fields + f; \
+ if (field->label == PROTOBUF_C_LABEL_REPEATED) \
+ STRUCT_MEMBER (size_t, rv, field->quantifier_offset) = 0; \
+ }
+ a = do_alloc(allocator, siz * n);
+ if (!a) {
+ CLEAR_REMAINING_N_PTRS();
+ goto error_cleanup;
+ }
+ STRUCT_MEMBER(void *, rv, field->offset) = a;
+ }
+ } else if (field->label == PROTOBUF_C_LABEL_REQUIRED) {
+ if (field->default_value == NULL &&
+ !REQUIRED_FIELD_BITMAP_IS_SET(f))
+ {
+ CLEAR_REMAINING_N_PTRS();
+ PROTOBUF_C_UNPACK_ERROR("message '%s': missing required field '%s'",
+ desc->name, field->name);
+ goto error_cleanup;
+ }
+ }
+ }
+#undef CLEAR_REMAINING_N_PTRS
+
+ /* allocate space for unknown fields */
+ if (n_unknown) {
+ rv->unknown_fields = do_alloc(allocator,
+ n_unknown * sizeof(ProtobufCMessageUnknownField));
+ if (rv->unknown_fields == NULL)
+ goto error_cleanup;
+ }
+
+ /* do real parsing */
+ for (i_slab = 0; i_slab <= which_slab; i_slab++) {
+ unsigned max = (i_slab == which_slab) ?
+ in_slab_index : (1UL << (i_slab + 4));
+ ScannedMember *slab = scanned_member_slabs[i_slab];
+
+ for (j = 0; j < max; j++) {
+ if (!parse_member(slab + j, rv, allocator)) {
+ PROTOBUF_C_UNPACK_ERROR("error parsing member %s of %s",
+ slab->field ? slab->field->name : "*unknown-field*",
+ desc->name);
+ goto error_cleanup;
+ }
+ }
+ }
+
+ /* cleanup */
+ for (j = 1; j <= which_slab; j++)
+ do_free(allocator, scanned_member_slabs[j]);
+ if (required_fields_bitmap_alloced)
+ do_free(allocator, required_fields_bitmap);
+ return rv;
+
+error_cleanup:
+ protobuf_c_message_free_unpacked(rv, allocator);
+ for (j = 1; j <= which_slab; j++)
+ do_free(allocator, scanned_member_slabs[j]);
+ if (required_fields_bitmap_alloced)
+ do_free(allocator, required_fields_bitmap);
+ return NULL;
+
+error_cleanup_during_scan:
+ do_free(allocator, rv);
+ for (j = 1; j <= which_slab; j++)
+ do_free(allocator, scanned_member_slabs[j]);
+ if (required_fields_bitmap_alloced)
+ do_free(allocator, required_fields_bitmap);
+ return NULL;
+}
+
+void
+protobuf_c_message_free_unpacked(ProtobufCMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ const ProtobufCMessageDescriptor *desc;
+ unsigned f;
+
+ if (message == NULL)
+ return;
+
+ desc = message->descriptor;
+
+ ASSERT_IS_MESSAGE(message);
+
+ if (allocator == NULL)
+ allocator = &protobuf_c__allocator;
+ message->descriptor = NULL;
+ for (f = 0; f < desc->n_fields; f++) {
+ if (0 != (desc->fields[f].flags & PROTOBUF_C_FIELD_FLAG_ONEOF) &&
+ desc->fields[f].id !=
+ STRUCT_MEMBER(uint32_t, message, desc->fields[f].quantifier_offset))
+ {
+ /* This is not the selected oneof, skip it */
+ continue;
+ }
+
+ if (desc->fields[f].label == PROTOBUF_C_LABEL_REPEATED) {
+ size_t n = STRUCT_MEMBER(size_t,
+ message,
+ desc->fields[f].quantifier_offset);
+ void *arr = STRUCT_MEMBER(void *,
+ message,
+ desc->fields[f].offset);
+
+ if (arr != NULL) {
+ if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) {
+ unsigned i;
+ for (i = 0; i < n; i++)
+ do_free(allocator, ((char **) arr)[i]);
+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) {
+ unsigned i;
+ for (i = 0; i < n; i++)
+ do_free(allocator, ((ProtobufCBinaryData *) arr)[i].data);
+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) {
+ unsigned i;
+ for (i = 0; i < n; i++)
+ protobuf_c_message_free_unpacked(
+ ((ProtobufCMessage **) arr)[i],
+ allocator
+ );
+ }
+ do_free(allocator, arr);
+ }
+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_STRING) {
+ char *str = STRUCT_MEMBER(char *, message,
+ desc->fields[f].offset);
+
+ if (str && str != desc->fields[f].default_value)
+ do_free(allocator, str);
+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_BYTES) {
+ void *data = STRUCT_MEMBER(ProtobufCBinaryData, message,
+ desc->fields[f].offset).data;
+ const ProtobufCBinaryData *default_bd;
+
+ default_bd = desc->fields[f].default_value;
+ if (data != NULL &&
+ (default_bd == NULL ||
+ default_bd->data != data))
+ {
+ do_free(allocator, data);
+ }
+ } else if (desc->fields[f].type == PROTOBUF_C_TYPE_MESSAGE) {
+ ProtobufCMessage *sm;
+
+ sm = STRUCT_MEMBER(ProtobufCMessage *, message,
+ desc->fields[f].offset);
+ if (sm && sm != desc->fields[f].default_value)
+ protobuf_c_message_free_unpacked(sm, allocator);
+ }
+ }
+
+ for (f = 0; f < message->n_unknown_fields; f++)
+ do_free(allocator, message->unknown_fields[f].data);
+ if (message->unknown_fields != NULL)
+ do_free(allocator, message->unknown_fields);
+
+ do_free(allocator, message);
+}
+
+void
+protobuf_c_message_init(const ProtobufCMessageDescriptor * descriptor,
+ void *message)
+{
+ descriptor->message_init((ProtobufCMessage *) (message));
+}
+
+protobuf_c_boolean
+protobuf_c_message_check(const ProtobufCMessage *message)
+{
+ unsigned i;
+
+ if (!message ||
+ !message->descriptor ||
+ message->descriptor->magic != PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC)
+ {
+ return FALSE;
+ }
+
+ for (i = 0; i < message->descriptor->n_fields; i++) {
+ const ProtobufCFieldDescriptor *f = message->descriptor->fields + i;
+ ProtobufCType type = f->type;
+ ProtobufCLabel label = f->label;
+ void *field = STRUCT_MEMBER_P (message, f->offset);
+
+ if (f->flags & PROTOBUF_C_FIELD_FLAG_ONEOF) {
+ const uint32_t *oneof_case = STRUCT_MEMBER_P (message, f->quantifier_offset);
+ if (f->id != *oneof_case) {
+ continue; //Do not check if it is an unpopulated oneof member.
+ }
+ }
+
+ if (label == PROTOBUF_C_LABEL_REPEATED) {
+ size_t *quantity = STRUCT_MEMBER_P (message, f->quantifier_offset);
+
+ if (*quantity > 0 && *(void **) field == NULL) {
+ return FALSE;
+ }
+
+ if (type == PROTOBUF_C_TYPE_MESSAGE) {
+ ProtobufCMessage **submessage = *(ProtobufCMessage ***) field;
+ unsigned j;
+ for (j = 0; j < *quantity; j++) {
+ if (!protobuf_c_message_check(submessage[j]))
+ return FALSE;
+ }
+ } else if (type == PROTOBUF_C_TYPE_STRING) {
+ char **string = *(char ***) field;
+ unsigned j;
+ for (j = 0; j < *quantity; j++) {
+ if (!string[j])
+ return FALSE;
+ }
+ } else if (type == PROTOBUF_C_TYPE_BYTES) {
+ ProtobufCBinaryData *bd = *(ProtobufCBinaryData **) field;
+ unsigned j;
+ for (j = 0; j < *quantity; j++) {
+ if (bd[j].len > 0 && bd[j].data == NULL)
+ return FALSE;
+ }
+ }
+
+ } else { /* PROTOBUF_C_LABEL_REQUIRED or PROTOBUF_C_LABEL_OPTIONAL */
+
+ if (type == PROTOBUF_C_TYPE_MESSAGE) {
+ ProtobufCMessage *submessage = *(ProtobufCMessage **) field;
+ if (label == PROTOBUF_C_LABEL_REQUIRED || submessage != NULL) {
+ if (!protobuf_c_message_check(submessage))
+ return FALSE;
+ }
+ } else if (type == PROTOBUF_C_TYPE_STRING) {
+ char *string = *(char **) field;
+ if (label == PROTOBUF_C_LABEL_REQUIRED && string == NULL)
+ return FALSE;
+ } else if (type == PROTOBUF_C_TYPE_BYTES) {
+ protobuf_c_boolean *has = STRUCT_MEMBER_P (message, f->quantifier_offset);
+ ProtobufCBinaryData *bd = field;
+ if (label == PROTOBUF_C_LABEL_REQUIRED || *has == TRUE) {
+ if (bd->len > 0 && bd->data == NULL)
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/* === services === */
+
+typedef void (*GenericHandler) (void *service,
+ const ProtobufCMessage *input,
+ ProtobufCClosure closure,
+ void *closure_data);
+void
+protobuf_c_service_invoke_internal(ProtobufCService *service,
+ unsigned method_index,
+ const ProtobufCMessage *input,
+ ProtobufCClosure closure,
+ void *closure_data)
+{
+ GenericHandler *handlers;
+ GenericHandler handler;
+
+ /*
+ * Verify that method_index is within range. If this fails, you are
+ * likely invoking a newly added method on an old service. (Although
+ * other memory corruption bugs can cause this assertion too.)
+ */
+ assert(method_index < service->descriptor->n_methods);
+
+ /*
+ * Get the array of virtual methods (which are enumerated by the
+ * generated code).
+ */
+ handlers = (GenericHandler *) (service + 1);
+
+ /*
+ * Get our method and invoke it.
+ * \todo Seems like handler == NULL is a situation that needs handling.
+ */
+ handler = handlers[method_index];
+ (*handler)(service, input, closure, closure_data);
+}
+
+void
+protobuf_c_service_generated_init(ProtobufCService *service,
+ const ProtobufCServiceDescriptor *descriptor,
+ ProtobufCServiceDestroy destroy)
+{
+ ASSERT_IS_SERVICE_DESCRIPTOR(descriptor);
+ service->descriptor = descriptor;
+ service->destroy = destroy;
+ service->invoke = protobuf_c_service_invoke_internal;
+ memset(&service[1], 0, descriptor->n_methods * sizeof(GenericHandler));
+}
+
+void protobuf_c_service_destroy(ProtobufCService *service)
+{
+ service->destroy(service);
+}
+
+/* --- querying the descriptors --- */
+
+const ProtobufCEnumValue *
+protobuf_c_enum_descriptor_get_value_by_name(const ProtobufCEnumDescriptor *desc,
+ const char *name)
+{
+ unsigned start = 0;
+ unsigned count;
+
+ if (desc == NULL || desc->values_by_name == NULL)
+ return NULL;
+
+ count = desc->n_value_names;
+
+ while (count > 1) {
+ unsigned mid = start + count / 2;
+ int rv = strcmp(desc->values_by_name[mid].name, name);
+ if (rv == 0)
+ return desc->values + desc->values_by_name[mid].index;
+ else if (rv < 0) {
+ count = start + count - (mid + 1);
+ start = mid + 1;
+ } else
+ count = mid - start;
+ }
+ if (count == 0)
+ return NULL;
+ if (strcmp(desc->values_by_name[start].name, name) == 0)
+ return desc->values + desc->values_by_name[start].index;
+ return NULL;
+}
+
+const ProtobufCEnumValue *
+protobuf_c_enum_descriptor_get_value(const ProtobufCEnumDescriptor *desc,
+ int value)
+{
+ int rv = int_range_lookup(desc->n_value_ranges, desc->value_ranges, value);
+ if (rv < 0)
+ return NULL;
+ return desc->values + rv;
+}
+
+const ProtobufCFieldDescriptor *
+protobuf_c_message_descriptor_get_field_by_name(const ProtobufCMessageDescriptor *desc,
+ const char *name)
+{
+ unsigned start = 0;
+ unsigned count;
+ const ProtobufCFieldDescriptor *field;
+
+ if (desc == NULL || desc->fields_sorted_by_name == NULL)
+ return NULL;
+
+ count = desc->n_fields;
+
+ while (count > 1) {
+ unsigned mid = start + count / 2;
+ int rv;
+ field = desc->fields + desc->fields_sorted_by_name[mid];
+ rv = strcmp(field->name, name);
+ if (rv == 0)
+ return field;
+ else if (rv < 0) {
+ count = start + count - (mid + 1);
+ start = mid + 1;
+ } else
+ count = mid - start;
+ }
+ if (count == 0)
+ return NULL;
+ field = desc->fields + desc->fields_sorted_by_name[start];
+ if (strcmp(field->name, name) == 0)
+ return field;
+ return NULL;
+}
+
+const ProtobufCFieldDescriptor *
+protobuf_c_message_descriptor_get_field(const ProtobufCMessageDescriptor *desc,
+ unsigned value)
+{
+ int rv = int_range_lookup(desc->n_field_ranges,desc->field_ranges, value);
+ if (rv < 0)
+ return NULL;
+ return desc->fields + rv;
+}
+
+const ProtobufCMethodDescriptor *
+protobuf_c_service_descriptor_get_method_by_name(const ProtobufCServiceDescriptor *desc,
+ const char *name)
+{
+ unsigned start = 0;
+ unsigned count;
+
+ if (desc == NULL || desc->method_indices_by_name == NULL)
+ return NULL;
+
+ count = desc->n_methods;
+
+ while (count > 1) {
+ unsigned mid = start + count / 2;
+ unsigned mid_index = desc->method_indices_by_name[mid];
+ const char *mid_name = desc->methods[mid_index].name;
+ int rv = strcmp(mid_name, name);
+
+ if (rv == 0)
+ return desc->methods + desc->method_indices_by_name[mid];
+ if (rv < 0) {
+ count = start + count - (mid + 1);
+ start = mid + 1;
+ } else {
+ count = mid - start;
+ }
+ }
+ if (count == 0)
+ return NULL;
+ if (strcmp(desc->methods[desc->method_indices_by_name[start]].name, name) == 0)
+ return desc->methods + desc->method_indices_by_name[start];
+ return NULL;
+}
diff --git a/lib/ssl_compat/Makefile.in b/lib/ssl_compat/Makefile.in
new file mode 100644
index 0000000..7fef9ad
--- /dev/null
+++ b/lib/ssl_compat/Makefile.in
@@ -0,0 +1,189 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+devdir = @devdir@
+scriptdir = $(top_srcdir)/scripts
+incdir = $(top_srcdir)/include
+
+# Compiler & tools to use
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+
+# Libraries
+LT_LIBS =
+
+# C preprocessor flags
+CPPFLAGS = -I$(incdir) -I$(top_builddir) -I$(srcdir) -I$(top_srcdir) @CPPFLAGS@
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+
+# Flags to pass to libtool
+LTFLAGS = @LT_STATIC@
+
+# Address sanitizer flags
+ASAN_CFLAGS = @ASAN_CFLAGS@
+ASAN_LDFLAGS = @ASAN_LDFLAGS@
+
+# PIE flags
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+
+# Stack smashing protection flags
+HARDENING_CFLAGS = @HARDENING_CFLAGS@
+HARDENING_LDFLAGS = @HARDENING_LDFLAGS@
+
+# cppcheck options, usually set in the top-level Makefile
+CPPCHECK_OPTS = -q --enable=warning,performance,portability --suppress=constStatement --suppress=compareBoolExpressionWithInt --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
+
+# splint options, usually set in the top-level Makefile
+SPLINT_OPTS = -D__restrict= -checks
+
+# PVS-studio options
+PVS_CFG = $(top_srcdir)/PVS-Studio.cfg
+PVS_IGNORE = 'V707,V011,V002,V536'
+PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
+
+# Set to non-empty for development mode
+DEVEL = @DEVEL@
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+LIBSSL_COMPAT_OBJS = ssl_compat.lo
+
+IOBJS = $(LIBSSL_COMPAT_OBJS:.lo=.i)
+
+POBJS = $(IOBJS:.i=.plog)
+
+GENERATED =
+
+all: libssl_compat.la
+
+depend:
+ $(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
+ --builddir=$(abs_top_builddir) lib/ssl_compat/Makefile.in
+ cd $(top_builddir) && ./config.status --file lib/ssl_compat/Makefile
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file lib/ssl_compat/Makefile
+
+.SUFFIXES: .c .h .i .lo .plog
+
+.c.lo:
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.i:
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+
+.i.plog:
+ ifile=$<; rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $${ifile%i}c --i-file $< --output-file $@
+
+$(devdir)/log_server.pb-c.c: $(srcdir)/log_server.proto
+ @if [ -n "$(DEVEL)" ]; then \
+ cmd='protoc-c --c_out=$(devdir) --proto_path=$(srcdir) $(srcdir)/log_server.proto'; \
+ echo "$$cmd"; eval $$cmd; \
+ cmd='$(scriptdir)/unanon $(devdir)/log_server.pb-c.h $(devdir)/log_server.pb-c.c'; \
+ echo "$$cmd"; eval $$cmd; \
+ if [ "$(devdir)" == "$(srcdir)" ]; then \
+ cmd='mv -f $(devdir)/log_server.pb-c.h $(incdir)/log_server.pb-c.h'; \
+ else \
+ cmd='mv -f $(devdir)/log_server.pb-c.h $(top_builddir)/log_server.pb-c.h'; \
+ fi; \
+ echo "$$cmd"; eval $$cmd; \
+ fi
+
+libssl_compat.la: $(LIBSSL_COMPAT_OBJS) $(LT_LIBS)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LIBSSL_COMPAT_OBJS) $(LT_LIBS)
+
+pre-install:
+
+install:
+
+install-binaries:
+
+install-includes:
+
+install-doc:
+
+install-plugin:
+
+install-fuzzer:
+
+uninstall:
+
+splint:
+ splint $(SPLINT_OPTS) -I$(incdir) -I$(top_builddir) -I$(top_srcdir) $(srcdir)/*.c
+
+cppcheck:
+ cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) -I$(top_srcdir) $(srcdir)/*.c
+
+pvs-log-files:
+
+pvs-studio:
+
+fuzz:
+
+check-fuzzer:
+
+check: check-fuzzer
+
+check-verbose: check
+
+clean:
+ -$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f *.lo *.o *.la
+ -rm -f *.i *.plog stamp-* core *.core core.*
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile .libs
+ @if [ -n "$(DEVEL)" -a "$(devdir)" != "$(srcdir)" ]; then \
+ cmd='rm -rf $(GENERATED)'; \
+ echo "$$cmd"; eval $$cmd; \
+ fi
+
+clobber: distclean
+
+realclean: distclean
+ rm -f TAGS tags
+
+cleandir: realclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean
+
+# Autogenerated dependencies, do not modify
+ssl_compat.lo: $(srcdir)/ssl_compat.c $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_ssl_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/ssl_compat.c
+ssl_compat.i: $(srcdir)/ssl_compat.c $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_ssl_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+ssl_compat.plog: ssl_compat.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/ssl_compat.c --i-file $< --output-file $@
diff --git a/lib/ssl_compat/ssl_compat.c b/lib/ssl_compat/ssl_compat.c
new file mode 100644
index 0000000..2942807
--- /dev/null
+++ b/lib/ssl_compat/ssl_compat.c
@@ -0,0 +1,64 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#if defined(HAVE_OPENSSL) && !defined(HAVE_SSL_READ_EX)
+
+# include <sys/types.h>
+# if defined(HAVE_WOLFSSL)
+# include <wolfssl/options.h>
+# endif
+# include <openssl/ssl.h>
+
+# include <sudo_compat.h>
+# include <sudo_ssl_compat.h>
+
+/*
+ * Emulate SSL_read_ex() using SSL_read().
+ * Unlike the real SSL_read_ex(), this can return -1 on error.
+ */
+int
+SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes)
+{
+ int nr = SSL_read(ssl, buf, (int)num);
+ if (nr <= 0)
+ return nr;
+ *readbytes = (size_t)nr;
+ return 1;
+}
+
+/*
+ * Emulate SSL_write_ex() using SSL_write().
+ * Unlike the real SSL_write_ex(), this can return -1 on error.
+ */
+int
+SSL_write_ex(SSL *ssl, const void *buf, size_t num, size_t *written)
+{
+ int nw = SSL_write(ssl, buf, (int)num);
+ if (nw <= 0)
+ return nw;
+ *written = (size_t)nw;
+ return 1;
+}
+#endif /* HAVE_OPENSSL && !HAVE_SSL_READ_EX */
diff --git a/lib/util/Makefile.in b/lib/util/Makefile.in
new file mode 100644
index 0000000..05455f7
--- /dev/null
+++ b/lib/util/Makefile.in
@@ -0,0 +1,1730 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2011-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+devdir = @devdir@
+scriptdir = $(top_srcdir)/scripts
+incdir = $(top_srcdir)/include
+cross_compiling = @CROSS_COMPILING@
+
+# Where to install things...
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+sysconfdir = @sysconfdir@
+adminconfdir = @adminconfdir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+localstatedir = @localstatedir@
+
+# File extension, mode and map file to use for shared libraries/objects
+shlib_enable = @SHLIB_ENABLE@
+shlib_mode = @SHLIB_MODE@
+shlib_exp = ./util.exp
+shlib_map = util.map
+shlib_opt = util.opt
+
+# Compiler & tools to use
+CC = @CC@
+HOSTCC = @CC_FOR_BUILD@
+CPP = @CPP@
+HOSTCPP = @CPP_FOR_BUILD@
+LIBTOOL = @LIBTOOL@
+SHA1SUM = @SHA1SUM@
+EGREP = @EGREP@
+SED = @SED@
+AWK = @AWK@
+
+# Our install program supports extra flags...
+INSTALL = $(SHELL) $(scriptdir)/install-sh -c
+INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
+INSTALL_BACKUP = @INSTALL_BACKUP@
+
+# C preprocessor defines
+CPPDEFS = -D_PATH_SUDO_CONF=\"@sudo_conf@\"
+
+# C preprocessor flags
+CPPFLAGS = -I$(incdir) -I$(top_builddir) -I. -I$(srcdir) $(CPPDEFS) \
+ @CPPFLAGS@ -DDEFAULT_TEXT_DOMAIN=\"@PACKAGE_NAME@\"
+HOSTCPPFLAGS = -I$(incdir) -I$(top_builddir) -I. -I$(srcdir) $(CPPDEFS) \
+ @CPPFLAGS_FOR_BUILD@ -DDEFAULT_TEXT_DOMAIN=\"@PACKAGE_NAME@\"
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+HOSTCFLAGS = @CFLAGS_FOR_BUILD@
+
+# Flags to pass to the link stage
+LDFLAGS = @LDFLAGS@
+LT_LDFLAGS = @LIBUTIL_LDFLAGS@ @LT_LDFLAGS@ @LT_LDEXPORTS@
+
+# Flags to pass to libtool
+LTFLAGS = @LT_STATIC@
+
+# Address sanitizer flags
+ASAN_CFLAGS = @ASAN_CFLAGS@
+ASAN_LDFLAGS = @ASAN_LDFLAGS@
+
+# PIE flags
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+
+# Stack smashing protection flags
+HARDENING_CFLAGS = @HARDENING_CFLAGS@
+HARDENING_LDFLAGS = @HARDENING_LDFLAGS@
+
+# Libtool style shared library version
+SHLIB_VERSION = 0:0:0
+
+# cppcheck options, usually set in the top-level Makefile
+CPPCHECK_OPTS = -q --enable=warning,performance,portability --suppress=constStatement --suppress=compareBoolExpressionWithInt --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
+
+# splint options, usually set in the top-level Makefile
+SPLINT_OPTS = -D__restrict= -checks
+
+# PVS-studio options
+PVS_CFG = $(top_srcdir)/PVS-Studio.cfg
+PVS_IGNORE = 'V707,V011,V002,V536'
+PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
+
+# Regression tests
+TEST_PROGS = conf_test digest_test getgids getgrouplist_test hexchar_test \
+ hltq_test json_test multiarch_test open_parent_dir_test \
+ parse_gids_test parseln_test progname_test regex_test \
+ strsplit_test strtobool_test strtoid_test strtomode_test \
+ strtonum_test uuid_test @COMPAT_TEST_PROGS@
+
+TEST_LIBS = @LIBS@
+TEST_LDFLAGS = @LDFLAGS@
+TEST_VERBOSE =
+HARNESS = $(SHELL) regress/harness $(TEST_VERBOSE)
+
+# Fuzzers
+LIBFUZZSTUB = $(top_builddir)/lib/fuzzstub/libsudo_fuzzstub.la
+LIB_FUZZING_ENGINE = @FUZZ_ENGINE@
+FUZZ_PROGS = fuzz_sudo_conf
+FUZZ_SEED_CORPUS = ${FUZZ_PROGS:=_seed_corpus.zip}
+FUZZ_LIBS = $(LIB_FUZZING_ENGINE) @LIBS@
+FUZZ_LDFLAGS = @LDFLAGS@
+FUZZ_MAX_LEN = 4096
+FUZZ_RUNS = 8192
+FUZZ_VERBOSE =
+
+# User and group ids the installed files should be "owned" by
+install_uid = 0
+install_gid = 0
+
+# Set to non-empty for development mode
+DEVEL = @DEVEL@
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+LTOBJS = basename.lo @DIGEST@ event.lo fatal.lo key_val.lo gethostname.lo \
+ gettime.lo getgrouplist.lo gidlist.lo hexchar.lo json.lo lbuf.lo \
+ locking.lo logfac.lo logpri.lo mkdir_parents.lo mmap_alloc.lo \
+ multiarch.lo parseln.lo progname.lo rcstr.lo regex.lo roundup.lo \
+ secure_path.lo setgroups.lo strsplit.lo strtobool.lo strtoid.lo \
+ strtomode.lo strtonum.lo sudo_conf.lo sudo_debug.lo sudo_dso.lo \
+ term.lo ttyname_dev.lo ttysize.lo uuid.lo \
+ @COMMON_OBJS@ @LTLIBOBJS@
+
+IOBJS = $(LTOBJS:.lo=.i)
+
+POBJS = $(IOBJS:.i=.plog)
+
+MKTEMP_TEST_OBJS = mktemp_test.lo mktemp.lo
+
+PARSELN_TEST_OBJS = parseln_test.lo parseln.lo
+
+PROGNAME_TEST_OBJS = progname_test.lo progname.lo basename.lo
+
+CLOSEFROM_TEST_OBJS = closefrom_test.lo closefrom.lo
+
+CONF_TEST_OBJS = conf_test.lo sudo_conf.lo
+
+DIGEST_TEST_OBJS = digest_test.lo @DIGEST@
+
+FNM_TEST_OBJS = fnm_test.lo fnmatch.lo
+
+GLOBTEST_OBJS = globtest.lo glob.lo
+
+GETDELIM_TEST_OBJS = getdelim_test.lo getdelim.lo
+
+HLTQ_TEST_OBJS = hltq_test.lo
+
+HEXCHAR_TEST_OBJS = hexchar_test.lo hexchar.lo
+
+JSON_TEST_OBJS = json_test.lo json.lo
+
+MULTIARCH_TEST_OBJS = multiarch_test.lo multiarch.lo
+
+OPEN_PARENT_DIR_TEST_OBJS = open_parent_dir_test.lo mkdir_parents.lo
+
+REGEX_TEST_OBJS = regex_test.lo regex.lo
+
+STRTOBOOL_TEST_OBJS = strtobool_test.lo strtobool.lo
+
+STRTOMODE_TEST_OBJS = strtomode_test.lo strtomode.lo
+
+STRTOID_TEST_OBJS = strtoid_test.lo strtoid.lo strtonum.lo
+
+STRTONUM_TEST_OBJS = strtonum_test.lo strtonum.lo
+
+STRSPLIT_TEST_OBJS = strsplit_test.lo strsplit.lo
+
+PARSE_GIDS_TEST_OBJS = parse_gids_test.lo gidlist.lo
+
+GETGIDS_OBJS = getgids.lo getgrouplist.lo
+
+GETGROUPLIST_TEST_OBJS = getgrouplist_test.lo getgrouplist.lo
+
+STRSIG_TEST_OBJS = strsig_test.lo sig2str.lo str2sig.lo @SIGNAME@
+
+UUID_TEST_OBJS = uuid_test.lo uuid.lo
+
+FUZZ_SUDO_CONF_OBJS = fuzz_sudo_conf.lo
+
+FUZZ_SUDO_CONF_CORPUS = $(srcdir)/regress/corpus/seed/sudo_conf/sudo.conf.*
+
+all: libsudo_util.la
+
+depend: siglist.c signame.c
+ $(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
+ --builddir=$(abs_top_builddir) lib/util/Makefile.in
+ cd $(top_builddir) && ./config.status --file lib/util/Makefile
+
+harness: $(srcdir)/regress/harness.in
+ cd $(top_builddir) && ./config.status --file lib/util/regress/harness
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file lib/util/Makefile
+
+.SUFFIXES: .c .h .i .lo .plog
+
+.c.lo:
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.i:
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+
+.i.plog:
+ ifile=$<; rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $${ifile%i}c --i-file $< --output-file $@
+
+$(shlib_map): $(shlib_exp)
+ @$(AWK) 'BEGIN { print "{\n\tglobal:" } { print "\t\t"$$0";" } END { print "\tlocal:\n\t\t*;\n};" }' $(shlib_exp) > $@
+
+$(shlib_opt): $(shlib_exp)
+ @$(SED) 's/^/+e /' $(shlib_exp) > $@
+
+libsudo_util.la: $(LTOBJS) @LT_LDDEP@
+ case "$(LT_LDFLAGS)" in \
+ *-no-install*) \
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LDFLAGS) $(LT_LDFLAGS) $(LTOBJS) @LT_DEP_LIBS@ @LIBINTL@ @LIBCRYPTO@ @LIBPTHREAD@ @LIBDL@ @LIBRT@ @NET_LIBS@;; \
+ *) \
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LDFLAGS) $(ASAN_LDFLAGS) $(HARDENING_LDFLAGS) $(LT_LDFLAGS) $(LTOBJS) -version-info $(SHLIB_VERSION) -rpath $(libexecdir)/sudo @LT_DEP_LIBS@ @LIBINTL@ @LIBCRYPTO@ @LIBPTHREAD@ @LIBDL@ @LIBRT@ @NET_LIBS@;; \
+ esac
+
+siglist.c: mksiglist
+ ./mksiglist > $@
+
+signame.c: mksigname
+ ./mksigname > $@
+
+mksiglist: $(srcdir)/mksiglist.c mksiglist.h $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(HOSTCC) $(HOSTCPPFLAGS) $(HOSTCFLAGS) $(srcdir)/mksiglist.c -o $@
+
+mksigname: $(srcdir)/mksigname.c mksigname.h $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(HOSTCC) $(HOSTCPPFLAGS) $(HOSTCFLAGS) $(srcdir)/mksigname.c -o $@
+
+$(srcdir)/sys_siglist.h: $(srcdir)/siglist.in
+ @if [ -n "$(DEVEL)" ]; then \
+ $(AWK) 'BEGIN {print "/* public domain */\n\n#include <config.h>\n#include <sys/types.h>\n#include <signal.h>\n#include \"sudo_compat.h\"\n\nint sudo_end_of_headers;\nstatic char *sudo_sys_siglist[NSIG];\n"} /^ [A-Z]/ {printf("#ifdef SIG%s\n if (sudo_sys_siglist[SIG%s] == NULL)\n\tsudo_sys_siglist[SIG%s] = \"%s\";\n#endif\n", $$1, $$1, $$1, substr($$0, 13))}' < $(srcdir)/siglist.in > $@; \
+ fi
+
+$(srcdir)/sys_signame.h: $(srcdir)/siglist.in
+ @if [ -n "$(DEVEL)" ]; then \
+ $(AWK) 'BEGIN {print "/* public domain */\n\n#include <config.h>\n#include <sys/types.h>\n#include <signal.h>\n#include \"sudo_compat.h\"\n\nint sudo_end_of_headers;\nstatic char *sudo_sys_signame[NSIG];\n"} /^ [A-Z]/ {printf("#ifdef SIG%s\n if (sudo_sys_signame[SIG%s] == NULL)\n\tsudo_sys_signame[SIG%s] = \"%s\";\n#endif\n", $$1, $$1, $$1, $$1)}' < $(srcdir)/siglist.in > $@; \
+ fi
+
+mksiglist.h: $(srcdir)/sys_siglist.h
+ $(CPP) $(CPPFLAGS) $(srcdir)/sys_siglist.h | $(SED) -e '1,/^int sudo_end_of_headers;/d' -e '/^#/d' > mksiglist.h
+
+mksigname.h: $(srcdir)/sys_signame.h
+ $(CPP) $(CPPFLAGS) $(srcdir)/sys_signame.h | $(SED) -e '1,/^int sudo_end_of_headers;/d' -e '/^#/d' > mksigname.h
+
+closefrom_test: $(CLOSEFROM_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CLOSEFROM_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+conf_test: $(CONF_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CONF_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+digest_test: $(DIGEST_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(DIGEST_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS) @LIBCRYPTO@
+
+fnm_test: $(FNM_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(FNM_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+globtest: $(GLOBTEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(GLOBTEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+getdelim_test: $(GETDELIM_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(GETDELIM_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+hltq_test: $(HLTQ_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(HLTQ_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+hexchar_test: $(HEXCHAR_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(HEXCHAR_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+json_test: $(JSON_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(JSON_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+mktemp_test: $(MKTEMP_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(MKTEMP_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+multiarch_test: $(MULTIARCH_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(MULTIARCH_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+open_parent_dir_test: $(OPEN_PARENT_DIR_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(OPEN_PARENT_DIR_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+parseln_test: $(PARSELN_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(PARSELN_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+progname_test: $(PROGNAME_TEST_OBJS)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(PROGNAME_TEST_OBJS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+parse_gids_test: $(PARSE_GIDS_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(PARSE_GIDS_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+getgids: $(GETGIDS_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(GETGIDS_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+getgrouplist_test: $(GETGROUPLIST_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(GETGROUPLIST_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+strsplit_test: $(STRSPLIT_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(STRSPLIT_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+regex_test: $(REGEX_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(REGEX_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+strsig_test: $(STRSIG_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(STRSIG_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+strtobool_test: $(STRTOBOOL_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(STRTOBOOL_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+strtomode_test: $(STRTOMODE_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(STRTOMODE_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+strtonum_test: $(STRTONUM_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(STRTONUM_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+strtoid_test: $(STRTOID_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(STRTOID_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+uuid_test: $(UUID_TEST_OBJS) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(UUID_TEST_OBJS) libsudo_util.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+fuzz_sudo_conf: $(FUZZ_SUDO_CONF_OBJS) $(LIBFUZZSTUB) libsudo_util.la
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(FUZZ_SUDO_CONF_OBJS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(FUZZ_LDFLAGS) $(FUZZ_LIBS) libsudo_util.la
+
+fuzz_sudo_conf_seed_corpus.zip:
+ tdir=fuzz_sudo_conf.$$$$; \
+ mkdir $$tdir; \
+ for f in $(FUZZ_SUDO_CONF_CORPUS); do \
+ cp $$f $$tdir/`$(SHA1SUM) $$f | $(SED) -e 's/^.*= *//' -e 's/ .*//'`; \
+ done; \
+ zip -j $@ $$tdir/*; \
+ rm -rf $$tdir
+
+run-fuzz_sudo_conf: fuzz_sudo_conf
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ umask 022; \
+ corpus=regress/corpus/sudo_conf; \
+ mkdir -p $$corpus; \
+ for f in $(FUZZ_SUDO_CONF_CORPUS); do \
+ cp $$f $$corpus; \
+ done; \
+ ./fuzz_sudo_conf -dict=$(srcdir)/regress/fuzz/fuzz_sudo_conf.dict -max_len=$(FUZZ_MAX_LEN) -runs=$(FUZZ_RUNS) $(FUZZ_VERBOSE) $$corpus
+
+pre-install:
+
+install: install-dirs
+ case "$(LT_LDFLAGS)" in \
+ *-no-install*) ;; \
+ *) if [ X"$(shlib_enable)" = X"yes" ]; then \
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --quiet --mode=install $(INSTALL) $(INSTALL_OWNER) libsudo_util.la $(DESTDIR)$(libexecdir)/sudo; \
+ fi;; \
+ esac
+
+install-dirs:
+ $(SHELL) $(scriptdir)/mkinstalldirs $(DESTDIR)$(libexecdir)/sudo
+
+install-binaries:
+
+install-includes:
+
+install-doc:
+
+install-plugin:
+
+install-fuzzer: $(FUZZ_PROGS) $(FUZZ_SEED_CORPUS)
+ @if test X"$(FUZZ_DESTDIR)" = X""; then \
+ echo "must set FUZZ_DESTDIR for install-fuzzer target"; \
+ else \
+ cp $(FUZZ_PROGS) $(FUZZ_SEED_CORPUS) $(FUZZ_DESTDIR); \
+ cp $(srcdir)/regress/fuzz/*.dict $(FUZZ_DESTDIR); \
+ fi
+
+uninstall:
+ $(LIBTOOL) $(LTFLAGS) --mode=uninstall rm -f $(DESTDIR)$(libexecdir)/sudo/libsudo_util.la
+ -test -z "$(INSTALL_BACKUP)" || \
+ rm -f $(DESTDIR)$(libexecdir)/sudo/libsudo_util.*~
+
+splint:
+ splint $(SPLINT_OPTS) -I$(incdir) -I$(top_builddir) $(srcdir)/*.c
+
+cppcheck:
+ cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) $(srcdir)/*.c
+
+pvs-log-files: $(POBJS)
+
+pvs-studio: $(POBJS)
+ plog-converter $(PVS_LOG_OPTS) $(POBJS)
+
+fuzz: run-fuzz_sudo_conf
+
+check-fuzzer: $(FUZZ_PROGS)
+ @if test X"$(cross_compiling)" != X"yes"; then \
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ echo "fuzz_sudo_conf: verifying corpus"; \
+ ./fuzz_sudo_conf $(FUZZ_VERBOSE) $(FUZZ_SUDO_CONF_CORPUS); \
+ fi
+
+# Note: some regress checks are run from srcdir for consistent error messages
+check: $(TEST_PROGS) check-fuzzer
+ @if test X"$(cross_compiling)" != X"yes"; then \
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ rval=0; \
+ if test -f closefrom_test; then \
+ ./closefrom_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ fi; \
+ ./digest_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ if test -f fnm_test; then \
+ ./fnm_test $(TEST_VERBOSE) $(srcdir)/regress/fnmatch/fnm_test.in || rval=`expr $$rval + $$?`; \
+ fi; \
+ if test -f globtest; then \
+ mkdir -p `$(SED) 's@/[^/]*$$@@' $(srcdir)/regress/glob/files | sort -u`; \
+ touch `cat $(srcdir)/regress/glob/files`; \
+ chmod 0755 `$(EGREP) '/r[^/]*$$' $(srcdir)/regress/glob/files`; \
+ chmod 0444 `$(EGREP) '/s[^/]*$$' $(srcdir)/regress/glob/files`; \
+ chmod 0711 `$(EGREP) '/t[^/]*$$' $(srcdir)/regress/glob/files`; \
+ ./globtest $(TEST_VERBOSE) $(srcdir)/regress/glob/globtest.in || rval=`expr $$rval + $$?`; \
+ rm -rf fake; \
+ fi; \
+ if test -f getdelim_test; then \
+ ./getdelim_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ fi; \
+ if test -f mktemp_test; then \
+ ./mktemp_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ fi; \
+ if test -f strsig_test; then \
+ ./strsig_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ fi; \
+ ./getgrouplist_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./hexchar_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./hltq_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./json_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./multiarch_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./open_parent_dir_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./parse_gids_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./progname_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ rm -f ./progname_test2 $(TEST_VERBOSE); ln -s ./progname_test ./progname_test2; \
+ ./progname_test2 $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ rm -f ./progname_test2; \
+ ./regex_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./strsplit_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./strtobool_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./strtoid_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./strtomode_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./strtonum_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./uuid_test $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ AWK=$(AWK) $(HARNESS) sudo_conf || rval=`expr $$rval + $$?`; \
+ AWK=$(AWK) $(HARNESS) sudo_parseln || rval=`expr $$rval + $$?`; \
+ exit $$rval; \
+ fi
+
+check-verbose:
+ exec $(MAKE) $(MFLAGS) TEST_VERBOSE=-v FUZZ_VERBOSE=-verbosity=1 check
+
+clean:
+ -$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f $(TEST_PROGS) $(FUZZ_PROGS) \
+ *.lo *.o *.la
+ -rm -f *.i *.plog stamp-* core *.core core.* regress/*/*.out \
+ regress/*/*.err
+ -rm -rf regress/corpus/sudo_conf
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile mksiglist mksiglist.h siglist.c \
+ mksigname mksigname.h signame.c regress/harness \
+ .libs $(shlib_exp) $(shlib_map) $(shlib_opt)
+
+clobber: distclean
+
+realclean: distclean
+ rm -f TAGS tags
+
+cleandir: realclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean \
+ harness $(FUZZ_SEED_CORPUS) run-fuzz_sudo_conf
+
+# Autogenerated dependencies, do not modify
+aix.lo: $(srcdir)/aix.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/aix.c
+aix.i: $(srcdir)/aix.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+aix.plog: aix.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/aix.c --i-file $< --output-file $@
+arc4random.lo: $(srcdir)/arc4random.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_rand.h \
+ $(srcdir)/chacha_private.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/arc4random.c
+arc4random.i: $(srcdir)/arc4random.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_rand.h \
+ $(srcdir)/chacha_private.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+arc4random.plog: arc4random.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/arc4random.c --i-file $< --output-file $@
+arc4random_buf.lo: $(srcdir)/arc4random_buf.c $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_rand.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/arc4random_buf.c
+arc4random_buf.i: $(srcdir)/arc4random_buf.c $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_rand.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+arc4random_buf.plog: arc4random_buf.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/arc4random_buf.c --i-file $< --output-file $@
+arc4random_uniform.lo: $(srcdir)/arc4random_uniform.c $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_rand.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/arc4random_uniform.c
+arc4random_uniform.i: $(srcdir)/arc4random_uniform.c $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_rand.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+arc4random_uniform.plog: arc4random_uniform.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/arc4random_uniform.c --i-file $< --output-file $@
+basename.lo: $(srcdir)/basename.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/basename.c
+basename.i: $(srcdir)/basename.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+basename.plog: basename.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/basename.c --i-file $< --output-file $@
+cfmakeraw.lo: $(srcdir)/cfmakeraw.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/cfmakeraw.c
+cfmakeraw.i: $(srcdir)/cfmakeraw.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+cfmakeraw.plog: cfmakeraw.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/cfmakeraw.c --i-file $< --output-file $@
+closefrom.lo: $(srcdir)/closefrom.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/closefrom.c
+closefrom.i: $(srcdir)/closefrom.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+closefrom.plog: closefrom.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/closefrom.c --i-file $< --output-file $@
+closefrom_test.lo: $(srcdir)/regress/closefrom/closefrom_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/closefrom/closefrom_test.c
+closefrom_test.i: $(srcdir)/regress/closefrom/closefrom_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+closefrom_test.plog: closefrom_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/closefrom/closefrom_test.c --i-file $< --output-file $@
+conf_test.lo: $(srcdir)/regress/sudo_conf/conf_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/sudo_conf/conf_test.c
+conf_test.i: $(srcdir)/regress/sudo_conf/conf_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+conf_test.plog: conf_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/sudo_conf/conf_test.c --i-file $< --output-file $@
+digest.lo: $(srcdir)/digest.c $(incdir)/compat/sha2.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_digest.h \
+ $(incdir)/sudo_queue.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/digest.c
+digest.i: $(srcdir)/digest.c $(incdir)/compat/sha2.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_digest.h \
+ $(incdir)/sudo_queue.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+digest.plog: digest.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/digest.c --i-file $< --output-file $@
+digest_gcrypt.lo: $(srcdir)/digest_gcrypt.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/digest_gcrypt.c
+digest_gcrypt.i: $(srcdir)/digest_gcrypt.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+digest_gcrypt.plog: digest_gcrypt.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/digest_gcrypt.c --i-file $< --output-file $@
+digest_openssl.lo: $(srcdir)/digest_openssl.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/digest_openssl.c
+digest_openssl.i: $(srcdir)/digest_openssl.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+digest_openssl.plog: digest_openssl.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/digest_openssl.c --i-file $< --output-file $@
+digest_test.lo: $(srcdir)/regress/digest/digest_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/digest/digest_test.c
+digest_test.i: $(srcdir)/regress/digest/digest_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+digest_test.plog: digest_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/digest/digest_test.c --i-file $< --output-file $@
+dup3.lo: $(srcdir)/dup3.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/dup3.c
+dup3.i: $(srcdir)/dup3.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+dup3.plog: dup3.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/dup3.c --i-file $< --output-file $@
+event.lo: $(srcdir)/event.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/event.c
+event.i: $(srcdir)/event.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+event.plog: event.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/event.c --i-file $< --output-file $@
+event_poll.lo: $(srcdir)/event_poll.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/event_poll.c
+event_poll.i: $(srcdir)/event_poll.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+event_poll.plog: event_poll.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/event_poll.c --i-file $< --output-file $@
+event_select.lo: $(srcdir)/event_select.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/event_select.c
+event_select.i: $(srcdir)/event_select.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+event_select.plog: event_select.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/event_select.c --i-file $< --output-file $@
+explicit_bzero.lo: $(srcdir)/explicit_bzero.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/explicit_bzero.c
+explicit_bzero.i: $(srcdir)/explicit_bzero.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+explicit_bzero.plog: explicit_bzero.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/explicit_bzero.c --i-file $< --output-file $@
+fatal.lo: $(srcdir)/fatal.c $(incdir)/compat/getaddrinfo.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/fatal.c
+fatal.i: $(srcdir)/fatal.c $(incdir)/compat/getaddrinfo.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fatal.plog: fatal.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/fatal.c --i-file $< --output-file $@
+fchmodat.lo: $(srcdir)/fchmodat.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/fchmodat.c
+fchmodat.i: $(srcdir)/fchmodat.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fchmodat.plog: fchmodat.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/fchmodat.c --i-file $< --output-file $@
+fchownat.lo: $(srcdir)/fchownat.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/fchownat.c
+fchownat.i: $(srcdir)/fchownat.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fchownat.plog: fchownat.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/fchownat.c --i-file $< --output-file $@
+fnm_test.lo: $(srcdir)/regress/fnmatch/fnm_test.c $(incdir)/compat/fnmatch.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/fnmatch/fnm_test.c
+fnm_test.i: $(srcdir)/regress/fnmatch/fnm_test.c $(incdir)/compat/fnmatch.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fnm_test.plog: fnm_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/fnmatch/fnm_test.c --i-file $< --output-file $@
+fnmatch.lo: $(srcdir)/fnmatch.c $(incdir)/compat/charclass.h \
+ $(incdir)/compat/fnmatch.h $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/fnmatch.c
+fnmatch.i: $(srcdir)/fnmatch.c $(incdir)/compat/charclass.h \
+ $(incdir)/compat/fnmatch.h $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fnmatch.plog: fnmatch.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/fnmatch.c --i-file $< --output-file $@
+freezero.lo: $(srcdir)/freezero.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/freezero.c
+freezero.i: $(srcdir)/freezero.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+freezero.plog: freezero.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/freezero.c --i-file $< --output-file $@
+fstatat.lo: $(srcdir)/fstatat.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/fstatat.c
+fstatat.i: $(srcdir)/fstatat.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fstatat.plog: fstatat.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/fstatat.c --i-file $< --output-file $@
+fuzz_sudo_conf.lo: $(srcdir)/regress/fuzz/fuzz_sudo_conf.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/fuzz/fuzz_sudo_conf.c
+fuzz_sudo_conf.i: $(srcdir)/regress/fuzz/fuzz_sudo_conf.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fuzz_sudo_conf.plog: fuzz_sudo_conf.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/fuzz/fuzz_sudo_conf.c --i-file $< --output-file $@
+getaddrinfo.lo: $(srcdir)/getaddrinfo.c $(incdir)/compat/getaddrinfo.h \
+ $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/getaddrinfo.c
+getaddrinfo.i: $(srcdir)/getaddrinfo.c $(incdir)/compat/getaddrinfo.h \
+ $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+getaddrinfo.plog: getaddrinfo.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/getaddrinfo.c --i-file $< --output-file $@
+getdelim.lo: $(srcdir)/getdelim.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/getdelim.c
+getdelim.i: $(srcdir)/getdelim.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+getdelim.plog: getdelim.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/getdelim.c --i-file $< --output-file $@
+getdelim_test.lo: $(srcdir)/regress/getdelim/getdelim_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/getdelim/getdelim_test.c
+getdelim_test.i: $(srcdir)/regress/getdelim/getdelim_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+getdelim_test.plog: getdelim_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/getdelim/getdelim_test.c --i-file $< --output-file $@
+getentropy.lo: $(srcdir)/getentropy.c $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_rand.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/getentropy.c
+getentropy.i: $(srcdir)/getentropy.c $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_rand.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+getentropy.plog: getentropy.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/getentropy.c --i-file $< --output-file $@
+getgids.lo: $(srcdir)/regress/getgrouplist/getgids.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/getgrouplist/getgids.c
+getgids.i: $(srcdir)/regress/getgrouplist/getgids.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+getgids.plog: getgids.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/getgrouplist/getgids.c --i-file $< --output-file $@
+getgrouplist.lo: $(srcdir)/getgrouplist.c $(incdir)/compat/nss_dbdefs.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/getgrouplist.c
+getgrouplist.i: $(srcdir)/getgrouplist.c $(incdir)/compat/nss_dbdefs.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+getgrouplist.plog: getgrouplist.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/getgrouplist.c --i-file $< --output-file $@
+getgrouplist_test.lo: $(srcdir)/regress/getgrouplist/getgrouplist_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/getgrouplist/getgrouplist_test.c
+getgrouplist_test.i: $(srcdir)/regress/getgrouplist/getgrouplist_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+getgrouplist_test.plog: getgrouplist_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/getgrouplist/getgrouplist_test.c --i-file $< --output-file $@
+gethostname.lo: $(srcdir)/gethostname.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/gethostname.c
+gethostname.i: $(srcdir)/gethostname.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+gethostname.plog: gethostname.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/gethostname.c --i-file $< --output-file $@
+getopt_long.lo: $(srcdir)/getopt_long.c $(incdir)/compat/getopt.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/getopt_long.c
+getopt_long.i: $(srcdir)/getopt_long.c $(incdir)/compat/getopt.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+getopt_long.plog: getopt_long.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/getopt_long.c --i-file $< --output-file $@
+gettime.lo: $(srcdir)/gettime.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/gettime.c
+gettime.i: $(srcdir)/gettime.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+gettime.plog: gettime.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/gettime.c --i-file $< --output-file $@
+getusershell.lo: $(srcdir)/getusershell.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/getusershell.c
+getusershell.i: $(srcdir)/getusershell.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+getusershell.plog: getusershell.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/getusershell.c --i-file $< --output-file $@
+gidlist.lo: $(srcdir)/gidlist.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/gidlist.c
+gidlist.i: $(srcdir)/gidlist.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+gidlist.plog: gidlist.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/gidlist.c --i-file $< --output-file $@
+glob.lo: $(srcdir)/glob.c $(incdir)/compat/charclass.h $(incdir)/compat/glob.h \
+ $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/glob.c
+glob.i: $(srcdir)/glob.c $(incdir)/compat/charclass.h $(incdir)/compat/glob.h \
+ $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+glob.plog: glob.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/glob.c --i-file $< --output-file $@
+globtest.lo: $(srcdir)/regress/glob/globtest.c $(incdir)/compat/glob.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/glob/globtest.c
+globtest.i: $(srcdir)/regress/glob/globtest.c $(incdir)/compat/glob.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+globtest.plog: globtest.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/glob/globtest.c --i-file $< --output-file $@
+gmtime_r.lo: $(srcdir)/gmtime_r.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/gmtime_r.c
+gmtime_r.i: $(srcdir)/gmtime_r.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+gmtime_r.plog: gmtime_r.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/gmtime_r.c --i-file $< --output-file $@
+hexchar.lo: $(srcdir)/hexchar.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/hexchar.c
+hexchar.i: $(srcdir)/hexchar.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+hexchar.plog: hexchar.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/hexchar.c --i-file $< --output-file $@
+hexchar_test.lo: $(srcdir)/regress/hexchar/hexchar_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/hexchar/hexchar_test.c
+hexchar_test.i: $(srcdir)/regress/hexchar/hexchar_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+hexchar_test.plog: hexchar_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/hexchar/hexchar_test.c --i-file $< --output-file $@
+hltq_test.lo: $(srcdir)/regress/tailq/hltq_test.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/tailq/hltq_test.c
+hltq_test.i: $(srcdir)/regress/tailq/hltq_test.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+hltq_test.plog: hltq_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/tailq/hltq_test.c --i-file $< --output-file $@
+inet_pton.lo: $(srcdir)/inet_pton.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/inet_pton.c
+inet_pton.i: $(srcdir)/inet_pton.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+inet_pton.plog: inet_pton.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/inet_pton.c --i-file $< --output-file $@
+isblank.lo: $(srcdir)/isblank.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/isblank.c
+isblank.i: $(srcdir)/isblank.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+isblank.plog: isblank.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/isblank.c --i-file $< --output-file $@
+json.lo: $(srcdir)/json.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_json.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/json.c
+json.i: $(srcdir)/json.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_json.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+json.plog: json.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/json.c --i-file $< --output-file $@
+json_test.lo: $(srcdir)/regress/json/json_test.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_json.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/json/json_test.c
+json_test.i: $(srcdir)/regress/json/json_test.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_json.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+json_test.plog: json_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/json/json_test.c --i-file $< --output-file $@
+key_val.lo: $(srcdir)/key_val.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/key_val.c
+key_val.i: $(srcdir)/key_val.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+key_val.plog: key_val.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/key_val.c --i-file $< --output-file $@
+lbuf.lo: $(srcdir)/lbuf.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_lbuf.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/lbuf.c
+lbuf.i: $(srcdir)/lbuf.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_lbuf.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+lbuf.plog: lbuf.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/lbuf.c --i-file $< --output-file $@
+localtime_r.lo: $(srcdir)/localtime_r.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/localtime_r.c
+localtime_r.i: $(srcdir)/localtime_r.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+localtime_r.plog: localtime_r.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/localtime_r.c --i-file $< --output-file $@
+locking.lo: $(srcdir)/locking.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/locking.c
+locking.i: $(srcdir)/locking.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+locking.plog: locking.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/locking.c --i-file $< --output-file $@
+logfac.lo: $(srcdir)/logfac.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/logfac.c
+logfac.i: $(srcdir)/logfac.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+logfac.plog: logfac.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/logfac.c --i-file $< --output-file $@
+logpri.lo: $(srcdir)/logpri.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/logpri.c
+logpri.i: $(srcdir)/logpri.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+logpri.plog: logpri.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/logpri.c --i-file $< --output-file $@
+memrchr.lo: $(srcdir)/memrchr.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/memrchr.c
+memrchr.i: $(srcdir)/memrchr.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+memrchr.plog: memrchr.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/memrchr.c --i-file $< --output-file $@
+mkdir_parents.lo: $(srcdir)/mkdir_parents.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/mkdir_parents.c
+mkdir_parents.i: $(srcdir)/mkdir_parents.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+mkdir_parents.plog: mkdir_parents.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/mkdir_parents.c --i-file $< --output-file $@
+mkdirat.lo: $(srcdir)/mkdirat.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/mkdirat.c
+mkdirat.i: $(srcdir)/mkdirat.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+mkdirat.plog: mkdirat.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/mkdirat.c --i-file $< --output-file $@
+mksiglist.lo: $(srcdir)/mksiglist.c $(incdir)/sudo_compat.h \
+ $(srcdir)/mksiglist.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/mksiglist.c
+mksiglist.i: $(srcdir)/mksiglist.c $(incdir)/sudo_compat.h \
+ $(srcdir)/mksiglist.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+mksiglist.plog: mksiglist.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/mksiglist.c --i-file $< --output-file $@
+mksigname.lo: $(srcdir)/mksigname.c $(incdir)/sudo_compat.h \
+ $(srcdir)/mksigname.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/mksigname.c
+mksigname.i: $(srcdir)/mksigname.c $(incdir)/sudo_compat.h \
+ $(srcdir)/mksigname.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+mksigname.plog: mksigname.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/mksigname.c --i-file $< --output-file $@
+mktemp.lo: $(srcdir)/mktemp.c $(incdir)/sudo_compat.h $(incdir)/sudo_rand.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/mktemp.c
+mktemp.i: $(srcdir)/mktemp.c $(incdir)/sudo_compat.h $(incdir)/sudo_rand.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+mktemp.plog: mktemp.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/mktemp.c --i-file $< --output-file $@
+mktemp_test.lo: $(srcdir)/regress/mktemp/mktemp_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/mktemp/mktemp_test.c
+mktemp_test.i: $(srcdir)/regress/mktemp/mktemp_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+mktemp_test.plog: mktemp_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/mktemp/mktemp_test.c --i-file $< --output-file $@
+mmap_alloc.lo: $(srcdir)/mmap_alloc.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/mmap_alloc.c
+mmap_alloc.i: $(srcdir)/mmap_alloc.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+mmap_alloc.plog: mmap_alloc.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/mmap_alloc.c --i-file $< --output-file $@
+multiarch.lo: $(srcdir)/multiarch.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/multiarch.c
+multiarch.i: $(srcdir)/multiarch.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+multiarch.plog: multiarch.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/multiarch.c --i-file $< --output-file $@
+multiarch_test.lo: $(srcdir)/regress/multiarch/multiarch_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/multiarch/multiarch_test.c
+multiarch_test.i: $(srcdir)/regress/multiarch/multiarch_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+multiarch_test.plog: multiarch_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/multiarch/multiarch_test.c --i-file $< --output-file $@
+nanosleep.lo: $(srcdir)/nanosleep.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/nanosleep.c
+nanosleep.i: $(srcdir)/nanosleep.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+nanosleep.plog: nanosleep.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/nanosleep.c --i-file $< --output-file $@
+open_parent_dir_test.lo: \
+ $(srcdir)/regress/open_parent_dir/open_parent_dir_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/open_parent_dir/open_parent_dir_test.c
+open_parent_dir_test.i: \
+ $(srcdir)/regress/open_parent_dir/open_parent_dir_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+open_parent_dir_test.plog: open_parent_dir_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/open_parent_dir/open_parent_dir_test.c --i-file $< --output-file $@
+openat.lo: $(srcdir)/openat.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/openat.c
+openat.i: $(srcdir)/openat.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+openat.plog: openat.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/openat.c --i-file $< --output-file $@
+parse_gids_test.lo: $(srcdir)/regress/parse_gids/parse_gids_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/parse_gids/parse_gids_test.c
+parse_gids_test.i: $(srcdir)/regress/parse_gids/parse_gids_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+parse_gids_test.plog: parse_gids_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/parse_gids/parse_gids_test.c --i-file $< --output-file $@
+parseln.lo: $(srcdir)/parseln.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/parseln.c
+parseln.i: $(srcdir)/parseln.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+parseln.plog: parseln.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/parseln.c --i-file $< --output-file $@
+parseln_test.lo: $(srcdir)/regress/sudo_parseln/parseln_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/sudo_parseln/parseln_test.c
+parseln_test.i: $(srcdir)/regress/sudo_parseln/parseln_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+parseln_test.plog: parseln_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/sudo_parseln/parseln_test.c --i-file $< --output-file $@
+pipe2.lo: $(srcdir)/pipe2.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/pipe2.c
+pipe2.i: $(srcdir)/pipe2.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+pipe2.plog: pipe2.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/pipe2.c --i-file $< --output-file $@
+pread.lo: $(srcdir)/pread.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/pread.c
+pread.i: $(srcdir)/pread.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+pread.plog: pread.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/pread.c --i-file $< --output-file $@
+progname.lo: $(srcdir)/progname.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/progname.c
+progname.i: $(srcdir)/progname.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+progname.plog: progname.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/progname.c --i-file $< --output-file $@
+progname_test.lo: $(srcdir)/regress/progname/progname_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/progname/progname_test.c
+progname_test.i: $(srcdir)/regress/progname/progname_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+progname_test.plog: progname_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/progname/progname_test.c --i-file $< --output-file $@
+pw_dup.lo: $(srcdir)/pw_dup.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/pw_dup.c
+pw_dup.i: $(srcdir)/pw_dup.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+pw_dup.plog: pw_dup.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/pw_dup.c --i-file $< --output-file $@
+pwrite.lo: $(srcdir)/pwrite.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/pwrite.c
+pwrite.i: $(srcdir)/pwrite.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+pwrite.plog: pwrite.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/pwrite.c --i-file $< --output-file $@
+rcstr.lo: $(srcdir)/rcstr.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/rcstr.c
+rcstr.i: $(srcdir)/rcstr.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+rcstr.plog: rcstr.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/rcstr.c --i-file $< --output-file $@
+reallocarray.lo: $(srcdir)/reallocarray.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/reallocarray.c
+reallocarray.i: $(srcdir)/reallocarray.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+reallocarray.plog: reallocarray.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/reallocarray.c --i-file $< --output-file $@
+realpath.lo: $(srcdir)/realpath.c $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/realpath.c
+realpath.i: $(srcdir)/realpath.c $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+realpath.plog: realpath.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/realpath.c --i-file $< --output-file $@
+regex.lo: $(srcdir)/regex.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regex.c
+regex.i: $(srcdir)/regex.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+regex.plog: regex.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regex.c --i-file $< --output-file $@
+regex_test.lo: $(srcdir)/regress/regex/regex_test.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/regex/regex_test.c
+regex_test.i: $(srcdir)/regress/regex/regex_test.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+regex_test.plog: regex_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/regex/regex_test.c --i-file $< --output-file $@
+roundup.lo: $(srcdir)/roundup.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/roundup.c
+roundup.i: $(srcdir)/roundup.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+roundup.plog: roundup.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/roundup.c --i-file $< --output-file $@
+secure_path.lo: $(srcdir)/secure_path.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/secure_path.c
+secure_path.i: $(srcdir)/secure_path.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+secure_path.plog: secure_path.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/secure_path.c --i-file $< --output-file $@
+setgroups.lo: $(srcdir)/setgroups.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/setgroups.c
+setgroups.i: $(srcdir)/setgroups.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+setgroups.plog: setgroups.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/setgroups.c --i-file $< --output-file $@
+sha2.lo: $(srcdir)/sha2.c $(incdir)/compat/endian.h $(incdir)/compat/sha2.h \
+ $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sha2.c
+sha2.i: $(srcdir)/sha2.c $(incdir)/compat/endian.h $(incdir)/compat/sha2.h \
+ $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sha2.plog: sha2.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sha2.c --i-file $< --output-file $@
+sig2str.lo: $(srcdir)/sig2str.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sig2str.c
+sig2str.i: $(srcdir)/sig2str.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sig2str.plog: sig2str.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sig2str.c --i-file $< --output-file $@
+siglist.lo: siglist.c
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) siglist.c
+siglist.i: siglist.c
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+siglist.plog: siglist.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file siglist.c --i-file $< --output-file $@
+signame.lo: signame.c
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) signame.c
+signame.i: signame.c
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+signame.plog: signame.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file signame.c --i-file $< --output-file $@
+snprintf.lo: $(srcdir)/snprintf.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/snprintf.c
+snprintf.i: $(srcdir)/snprintf.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+snprintf.plog: snprintf.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/snprintf.c --i-file $< --output-file $@
+str2sig.lo: $(srcdir)/str2sig.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/str2sig.c
+str2sig.i: $(srcdir)/str2sig.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+str2sig.plog: str2sig.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/str2sig.c --i-file $< --output-file $@
+strlcat.lo: $(srcdir)/strlcat.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/strlcat.c
+strlcat.i: $(srcdir)/strlcat.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strlcat.plog: strlcat.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/strlcat.c --i-file $< --output-file $@
+strlcpy.lo: $(srcdir)/strlcpy.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/strlcpy.c
+strlcpy.i: $(srcdir)/strlcpy.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strlcpy.plog: strlcpy.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/strlcpy.c --i-file $< --output-file $@
+strndup.lo: $(srcdir)/strndup.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/strndup.c
+strndup.i: $(srcdir)/strndup.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strndup.plog: strndup.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/strndup.c --i-file $< --output-file $@
+strnlen.lo: $(srcdir)/strnlen.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/strnlen.c
+strnlen.i: $(srcdir)/strnlen.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strnlen.plog: strnlen.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/strnlen.c --i-file $< --output-file $@
+strsig_test.lo: $(srcdir)/regress/strsig/strsig_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/strsig/strsig_test.c
+strsig_test.i: $(srcdir)/regress/strsig/strsig_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strsig_test.plog: strsig_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/strsig/strsig_test.c --i-file $< --output-file $@
+strsignal.lo: $(srcdir)/strsignal.c $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_gettext.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/strsignal.c
+strsignal.i: $(srcdir)/strsignal.c $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_gettext.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strsignal.plog: strsignal.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/strsignal.c --i-file $< --output-file $@
+strsplit.lo: $(srcdir)/strsplit.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/strsplit.c
+strsplit.i: $(srcdir)/strsplit.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strsplit.plog: strsplit.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/strsplit.c --i-file $< --output-file $@
+strsplit_test.lo: $(srcdir)/regress/strsplit/strsplit_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/strsplit/strsplit_test.c
+strsplit_test.i: $(srcdir)/regress/strsplit/strsplit_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strsplit_test.plog: strsplit_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/strsplit/strsplit_test.c --i-file $< --output-file $@
+strtobool.lo: $(srcdir)/strtobool.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/strtobool.c
+strtobool.i: $(srcdir)/strtobool.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strtobool.plog: strtobool.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/strtobool.c --i-file $< --output-file $@
+strtobool_test.lo: $(srcdir)/regress/strtofoo/strtobool_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/strtofoo/strtobool_test.c
+strtobool_test.i: $(srcdir)/regress/strtofoo/strtobool_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strtobool_test.plog: strtobool_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/strtofoo/strtobool_test.c --i-file $< --output-file $@
+strtoid.lo: $(srcdir)/strtoid.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/strtoid.c
+strtoid.i: $(srcdir)/strtoid.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strtoid.plog: strtoid.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/strtoid.c --i-file $< --output-file $@
+strtoid_test.lo: $(srcdir)/regress/strtofoo/strtoid_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/strtofoo/strtoid_test.c
+strtoid_test.i: $(srcdir)/regress/strtofoo/strtoid_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strtoid_test.plog: strtoid_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/strtofoo/strtoid_test.c --i-file $< --output-file $@
+strtomode.lo: $(srcdir)/strtomode.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/strtomode.c
+strtomode.i: $(srcdir)/strtomode.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strtomode.plog: strtomode.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/strtomode.c --i-file $< --output-file $@
+strtomode_test.lo: $(srcdir)/regress/strtofoo/strtomode_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/strtofoo/strtomode_test.c
+strtomode_test.i: $(srcdir)/regress/strtofoo/strtomode_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strtomode_test.plog: strtomode_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/strtofoo/strtomode_test.c --i-file $< --output-file $@
+strtonum.lo: $(srcdir)/strtonum.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/strtonum.c
+strtonum.i: $(srcdir)/strtonum.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strtonum.plog: strtonum.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/strtonum.c --i-file $< --output-file $@
+strtonum_test.lo: $(srcdir)/regress/strtofoo/strtonum_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/strtofoo/strtonum_test.c
+strtonum_test.i: $(srcdir)/regress/strtofoo/strtonum_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strtonum_test.plog: strtonum_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/strtofoo/strtonum_test.c --i-file $< --output-file $@
+sudo_conf.lo: $(srcdir)/sudo_conf.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudo_conf.c
+sudo_conf.i: $(srcdir)/sudo_conf.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudo_conf.plog: sudo_conf.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_conf.c --i-file $< --output-file $@
+sudo_debug.lo: $(srcdir)/sudo_debug.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudo_debug.c
+sudo_debug.i: $(srcdir)/sudo_debug.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudo_debug.plog: sudo_debug.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_debug.c --i-file $< --output-file $@
+sudo_dso.lo: $(srcdir)/sudo_dso.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_dso.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudo_dso.c
+sudo_dso.i: $(srcdir)/sudo_dso.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_dso.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudo_dso.plog: sudo_dso.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_dso.c --i-file $< --output-file $@
+term.lo: $(srcdir)/term.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/term.c
+term.i: $(srcdir)/term.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+term.plog: term.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/term.c --i-file $< --output-file $@
+timegm.lo: $(srcdir)/timegm.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/timegm.c
+timegm.i: $(srcdir)/timegm.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+timegm.plog: timegm.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/timegm.c --i-file $< --output-file $@
+ttyname_dev.lo: $(srcdir)/ttyname_dev.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/ttyname_dev.c
+ttyname_dev.i: $(srcdir)/ttyname_dev.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+ttyname_dev.plog: ttyname_dev.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/ttyname_dev.c --i-file $< --output-file $@
+ttysize.lo: $(srcdir)/ttysize.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/ttysize.c
+ttysize.i: $(srcdir)/ttysize.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+ttysize.plog: ttysize.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/ttysize.c --i-file $< --output-file $@
+unlinkat.lo: $(srcdir)/unlinkat.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/unlinkat.c
+unlinkat.i: $(srcdir)/unlinkat.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+unlinkat.plog: unlinkat.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/unlinkat.c --i-file $< --output-file $@
+utimens.lo: $(srcdir)/utimens.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/utimens.c
+utimens.i: $(srcdir)/utimens.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+utimens.plog: utimens.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/utimens.c --i-file $< --output-file $@
+uuid.lo: $(srcdir)/uuid.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_rand.h $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/uuid.c
+uuid.i: $(srcdir)/uuid.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_rand.h $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+uuid.plog: uuid.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/uuid.c --i-file $< --output-file $@
+uuid_test.lo: $(srcdir)/regress/uuid/uuid_test.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/uuid/uuid_test.c
+uuid_test.i: $(srcdir)/regress/uuid/uuid_test.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+uuid_test.plog: uuid_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/uuid/uuid_test.c --i-file $< --output-file $@
diff --git a/lib/util/aix.c b/lib/util/aix.c
new file mode 100644
index 0000000..3751f58
--- /dev/null
+++ b/lib/util/aix.c
@@ -0,0 +1,290 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2008, 2010-2016 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/resource.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <usersec.h>
+#include <uinfo.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_util.h>
+
+#ifdef HAVE_GETUSERATTR
+
+#ifndef HAVE_SETRLIMIT64
+# define setrlimit64(a, b) setrlimit(a, b)
+# define rlimit64 rlimit
+# define rlim64_t rlim_t
+# define RLIM64_INFINITY RLIM_INFINITY
+#endif /* HAVE_SETRLIMIT64 */
+
+#ifndef RLIM_SAVED_MAX
+# define RLIM_SAVED_MAX RLIM64_INFINITY
+#endif
+
+struct aix_limit {
+ int resource;
+ const char *soft;
+ const char *hard;
+ int factor;
+};
+
+static struct aix_limit aix_limits[] = {
+ { RLIMIT_FSIZE, S_UFSIZE, S_UFSIZE_HARD, 512 },
+ { RLIMIT_CPU, S_UCPU, S_UCPU_HARD, 1 },
+ { RLIMIT_DATA, S_UDATA, S_UDATA_HARD, 512 },
+ { RLIMIT_STACK, S_USTACK, S_USTACK_HARD, 512 },
+ { RLIMIT_RSS, S_URSS, S_URSS_HARD, 512 },
+ { RLIMIT_CORE, S_UCORE, S_UCORE_HARD, 512 },
+ { RLIMIT_NOFILE, S_UNOFILE, S_UNOFILE_HARD, 1 }
+};
+
+static int
+aix_getlimit(const char *user, const char *lim, int *valp)
+{
+ debug_decl(aix_getlimit, SUDO_DEBUG_UTIL);
+
+ if (getuserattr((char *)user, (char *)lim, valp, SEC_INT) != 0)
+ debug_return_int(-1);
+ debug_return_int(0);
+}
+
+static int
+aix_setlimits(char *user)
+{
+ struct rlimit64 rlim;
+ int val;
+ size_t n;
+ debug_decl(aix_setlimits, SUDO_DEBUG_UTIL);
+
+ if (setuserdb(S_READ) != 0) {
+ sudo_warn("%s", U_("unable to open userdb"));
+ debug_return_int(-1);
+ }
+
+ /*
+ * For each resource limit, get the soft/hard values for the user
+ * and set those values via setrlimit64(). Must be run as euid 0.
+ */
+ for (n = 0; n < nitems(aix_limits); n++) {
+ /*
+ * We have two strategies, depending on whether or not the
+ * hard limit has been defined.
+ */
+ if (aix_getlimit(user, aix_limits[n].hard, &val) == 0) {
+ rlim.rlim_max = val == -1 ? RLIM64_INFINITY : (rlim64_t)val * aix_limits[n].factor;
+ if (aix_getlimit(user, aix_limits[n].soft, &val) == 0)
+ rlim.rlim_cur = val == -1 ? RLIM64_INFINITY : (rlim64_t)val * aix_limits[n].factor;
+ else
+ rlim.rlim_cur = rlim.rlim_max; /* soft not specd, use hard */
+ } else {
+ /* No hard limit set, try soft limit, if it exists. */
+ if (aix_getlimit(user, aix_limits[n].soft, &val) == -1)
+ continue;
+ rlim.rlim_cur = val == -1 ? RLIM64_INFINITY : (rlim64_t)val * aix_limits[n].factor;
+
+ /* Set default hard limit as per limits(4). */
+ switch (aix_limits[n].resource) {
+ case RLIMIT_CPU:
+ case RLIMIT_FSIZE:
+ rlim.rlim_max = rlim.rlim_cur;
+ break;
+ case RLIMIT_STACK:
+ rlim.rlim_max = 4194304UL * aix_limits[n].factor;
+ break;
+ default:
+ rlim.rlim_max = RLIM64_INFINITY;
+ break;
+ }
+ }
+ (void)setrlimit64(aix_limits[n].resource, &rlim);
+ }
+ enduserdb();
+ debug_return_int(0);
+}
+
+#ifdef HAVE_SETAUTHDB
+
+# ifndef HAVE_AUTHDB_T
+typedef char authdb_t[16];
+# endif
+
+/* The empty string means to access all defined authentication registries. */
+static authdb_t old_registry;
+
+# if defined(HAVE_DECL_SETAUTHDB) && !HAVE_DECL_SETAUTHDB
+int setauthdb(authdb_t new, authdb_t old);
+int getauthdb(authdb_t val);
+# endif
+# if defined(HAVE_DECL_USRINFO) && !HAVE_DECL_USRINFO
+int usrinfo(int cmd, char *buf, int count);
+# endif
+
+/*
+ * Look up authentication registry for user (SYSTEM in /etc/security/user) and
+ * set it as the default for the process. This ensures that password and
+ * group lookups are made against the correct source (files, NIS, LDAP, etc).
+ * Does not modify errno even on error since callers do not check return value.
+ */
+int
+aix_getauthregistry_v1(char *user, char *saved_registry)
+{
+ int serrno = errno;
+ int ret = -1;
+ debug_decl(aix_getauthregistry, SUDO_DEBUG_UTIL);
+
+ saved_registry[0] = '\0';
+ if (user != NULL) {
+ char *registry;
+
+ if (setuserdb(S_READ) != 0) {
+ sudo_warn("%s", U_("unable to open userdb"));
+ goto done;
+ }
+ ret = getuserattr(user, (char *)S_REGISTRY, &registry, SEC_CHAR);
+ if (ret == 0) {
+ /* sizeof(authdb_t) is guaranteed to be 16 */
+ if (strlcpy(saved_registry, registry, 16) >= 16) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "registry for user %s too long: %s", user, registry);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: saved authentication registry for user %s is %s",
+ __func__, user, saved_registry);
+ }
+ enduserdb();
+ } else {
+ /* Get the process-wide registry. */
+ ret = getauthdb(saved_registry);
+ }
+done:
+ errno = serrno;
+ debug_return_int(ret);
+}
+
+/*
+ * Set the specified authentication registry for user (SYSTEM in
+ * /etc/security/user) and set it as the default for the process.
+ * This ensures that password and group lookups are made against
+ * the correct source (files, NIS, LDAP, etc).
+ * If registry is NULL, look it up based on the user name.
+ * Does not modify errno even on error since callers do not check return value.
+ */
+int
+aix_setauthdb_v1(char *user)
+{
+ return aix_setauthdb_v2(user, NULL);
+}
+
+int
+aix_setauthdb_v2(char *user, char *registry)
+{
+ authdb_t regbuf;
+ int serrno = errno;
+ int ret = -1;
+ debug_decl(aix_setauthdb, SUDO_DEBUG_UTIL);
+
+ if (user != NULL) {
+ /* Look up authentication registry if one is not provided. */
+ if (registry == NULL) {
+ if (aix_getauthregistry(user, regbuf) != 0)
+ goto done;
+ registry = regbuf;
+ }
+ ret = setauthdb(registry, old_registry);
+ if (ret != 0) {
+ sudo_warn(U_("unable to switch to registry \"%s\" for %s"),
+ registry, user);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: setting authentication registry to %s",
+ __func__, registry);
+ }
+ }
+done:
+ errno = serrno;
+ debug_return_int(ret);
+}
+
+/*
+ * Restore the saved authentication registry, if any.
+ * Does not modify errno even on error since callers do not check return value.
+ */
+int
+aix_restoreauthdb_v1(void)
+{
+ int serrno = errno;
+ int ret = 0;
+ debug_decl(aix_setauthdb, SUDO_DEBUG_UTIL);
+
+ if (setauthdb(old_registry, NULL) != 0) {
+ sudo_warn("%s", U_("unable to restore registry"));
+ ret = -1;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: setting authentication registry to %s",
+ __func__, old_registry);
+ }
+ errno = serrno;
+ debug_return_int(ret);
+}
+#endif
+
+int
+aix_prep_user_v1(char *user, const char *tty)
+{
+ char *info;
+ int len;
+ debug_decl(aix_setauthdb, SUDO_DEBUG_UTIL);
+
+ /* set usrinfo, like login(1) does */
+ len = asprintf(&info, "NAME=%s%cLOGIN=%s%cLOGNAME=%s%cTTY=%s%c",
+ user, '\0', user, '\0', user, '\0', tty ? tty : "", '\0');
+ if (len == -1) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(-1);
+ }
+ (void)usrinfo(SETUINFO, info, len);
+ free(info);
+
+#ifdef HAVE_SETAUTHDB
+ /* set authentication registry */
+ if (aix_setauthdb(user, NULL) != 0)
+ debug_return_int(-1);
+#endif
+
+ /* set resource limits */
+ if (aix_setlimits(user) != 0)
+ debug_return_int(-1);
+
+ debug_return_int(0);
+}
+#endif /* HAVE_GETUSERATTR */
diff --git a/lib/util/arc4random.c b/lib/util/arc4random.c
new file mode 100644
index 0000000..20ff4e1
--- /dev/null
+++ b/lib/util/arc4random.c
@@ -0,0 +1,206 @@
+/* $OpenBSD: arc4random.c,v 1.54 2015/09/13 08:31:47 guenther Exp $ */
+
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, David Mazieres <dm@uun.org>
+ * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
+ * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+/*
+ * ChaCha based random number generator for OpenBSD.
+ */
+
+#include <config.h>
+
+#ifndef HAVE_ARC4RANDOM
+
+#ifdef HAVE_SYS_RANDOM_H
+# include <sys/random.h>
+#endif
+
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_rand.h>
+
+#define KEYSTREAM_ONLY
+#include "chacha_private.h"
+
+#define minimum(a, b) ((a) < (b) ? (a) : (b))
+
+#ifdef __GNUC__
+# define inline __inline
+#else /* !__GNUC__ */
+# define inline
+#endif /* !__GNUC__ */
+
+/* Sudo isn't multithreaded */
+#define _ARC4_LOCK()
+#define _ARC4_UNLOCK()
+
+#define KEYSZ 32
+#define IVSZ 8
+#define BLOCKSZ 64
+#define RSBUFSZ (16*BLOCKSZ)
+static int rs_initialized;
+static pid_t rs_stir_pid;
+static chacha_ctx rs; /* chacha context for random keystream */
+static u_char rs_buf[RSBUFSZ]; /* keystream blocks */
+static size_t rs_have; /* valid bytes at end of rs_buf */
+static size_t rs_count; /* bytes till reseed */
+
+static inline void _rs_rekey(unsigned char *dat, size_t datlen);
+
+static inline void
+_rs_init(unsigned char *buf, size_t n)
+{
+ if (n < KEYSZ + IVSZ)
+ return;
+ chacha_keysetup(&rs, buf, KEYSZ * 8, 0);
+ chacha_ivsetup(&rs, buf + KEYSZ);
+}
+
+static void
+_rs_stir(void)
+{
+ unsigned char rnd[KEYSZ + IVSZ];
+
+ if (getentropy(rnd, sizeof rnd) == -1)
+ sudo_fatal_nodebug("getentropy");
+
+ if (!rs_initialized) {
+ rs_initialized = 1;
+ _rs_init(rnd, sizeof(rnd));
+ } else
+ _rs_rekey(rnd, sizeof(rnd));
+ explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */
+
+ /* invalidate rs_buf */
+ rs_have = 0;
+ memset(rs_buf, 0, sizeof(rs_buf));
+
+ rs_count = 1600000;
+}
+
+static inline void
+_rs_stir_if_needed(size_t len)
+{
+ pid_t pid = getpid();
+
+ if (rs_count <= len || !rs_initialized || rs_stir_pid != pid) {
+ rs_stir_pid = pid;
+ _rs_stir();
+ } else
+ rs_count -= len;
+}
+
+static inline void
+_rs_rekey(unsigned char *dat, size_t datlen)
+{
+#ifndef KEYSTREAM_ONLY
+ memset(rs_buf, 0, sizeof(rs_buf));
+#endif
+ /* fill rs_buf with the keystream */
+ chacha_encrypt_bytes(&rs, rs_buf, rs_buf, sizeof(rs_buf));
+ /* mix in optional user provided data */
+ if (dat) {
+ size_t i, m;
+
+ m = minimum(datlen, KEYSZ + IVSZ);
+ for (i = 0; i < m; i++)
+ rs_buf[i] ^= dat[i];
+ }
+ /* immediately reinit for backtracking resistance */
+ _rs_init(rs_buf, KEYSZ + IVSZ);
+ memset(rs_buf, 0, KEYSZ + IVSZ); // -V::512, 1086
+ rs_have = sizeof(rs_buf) - KEYSZ - IVSZ;
+}
+
+static inline void
+_rs_random_buf(void *_buf, size_t n)
+{
+ unsigned char *buf = _buf;
+ unsigned char *keystream;
+ size_t m;
+
+ _rs_stir_if_needed(n);
+ while (n > 0) {
+ if (rs_have > 0) {
+ m = minimum(n, rs_have);
+ keystream = rs_buf + sizeof(rs_buf) - rs_have;
+ memcpy(buf, keystream, m);
+ memset(keystream, 0, m);
+ buf += m;
+ n -= m;
+ rs_have -= m;
+ }
+ if (rs_have == 0)
+ _rs_rekey(NULL, 0);
+ }
+}
+
+static inline void
+_rs_random_u32(uint32_t *val)
+{
+ unsigned char *keystream;
+
+ _rs_stir_if_needed(sizeof(*val));
+ if (rs_have < sizeof(*val))
+ _rs_rekey(NULL, 0);
+ keystream = rs_buf + sizeof(rs_buf) - rs_have;
+ memcpy(val, keystream, sizeof(*val));
+ memset(keystream, 0, sizeof(*val));
+ rs_have -= sizeof(*val);
+}
+
+uint32_t
+sudo_arc4random(void)
+{
+ uint32_t val;
+
+ _ARC4_LOCK();
+ _rs_random_u32(&val);
+ _ARC4_UNLOCK();
+ return val;
+}
+
+void
+sudo_arc4random_buf(void *buf, size_t n)
+{
+ _ARC4_LOCK();
+ _rs_random_buf(buf, n);
+ _ARC4_UNLOCK();
+}
+
+#endif /* HAVE_ARC4RANDOM */
diff --git a/lib/util/arc4random_buf.c b/lib/util/arc4random_buf.c
new file mode 100644
index 0000000..c0fbe70
--- /dev/null
+++ b/lib/util/arc4random_buf.c
@@ -0,0 +1,70 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_ARC4RANDOM_BUF
+
+#include <stdlib.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_rand.h>
+
+#define minimum(a, b) ((a) < (b) ? (a) : (b))
+
+/*
+ * Call arc4random() repeatedly to fill buf with n bytes of random data.
+ */
+void
+sudo_arc4random_buf(void *buf, size_t n)
+{
+ char *cp = buf;
+
+ while (n != 0) {
+ size_t m = minimum(n, 4);
+ uint32_t val = arc4random();
+
+ switch (m) {
+ case 4:
+ *cp++ = (val >> 24) & 0xff;
+ FALLTHROUGH;
+ case 3:
+ *cp++ = (val >> 16) & 0xff;
+ FALLTHROUGH;
+ case 2:
+ *cp++ = (val >> 8) & 0xff;
+ FALLTHROUGH;
+ case 1:
+ *cp++ = val & 0xff;
+ break;
+ }
+ n -= m;
+ }
+}
+
+#endif /* HAVE_ARC4RANDOM_BUF */
diff --git a/lib/util/arc4random_uniform.c b/lib/util/arc4random_uniform.c
new file mode 100644
index 0000000..ad3c5aa
--- /dev/null
+++ b/lib/util/arc4random_uniform.c
@@ -0,0 +1,76 @@
+/* $OpenBSD: arc4random_uniform.c,v 1.2 2015/09/13 08:31:47 guenther Exp $ */
+
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_ARC4RANDOM_UNIFORM
+
+#include <stdlib.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_rand.h>
+
+/*
+ * Calculate a uniformly distributed random number less than upper_bound
+ * avoiding "modulo bias".
+ *
+ * Uniformity is achieved by generating new random numbers until the one
+ * returned is outside the range [0, 2**32 % upper_bound). This
+ * guarantees the selected random number will be inside
+ * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
+ * after reduction modulo upper_bound.
+ */
+uint32_t
+sudo_arc4random_uniform(uint32_t upper_bound)
+{
+ uint32_t r, min;
+
+ if (upper_bound < 2)
+ return 0;
+
+ /* 2**32 % x == (2**32 - x) % x */
+ min = -upper_bound % upper_bound;
+
+ /*
+ * This could theoretically loop forever but each retry has
+ * p > 0.5 (worst case, usually far better) of selecting a
+ * number inside the range we need, so it should rarely need
+ * to re-roll.
+ */
+ for (;;) {
+ r = arc4random();
+ if (r >= min)
+ break;
+ }
+
+ return r % upper_bound;
+}
+
+#endif /* HAVE_ARC4RANDOM_UNIFORM */
diff --git a/lib/util/basename.c b/lib/util/basename.c
new file mode 100644
index 0000000..a2c2c39
--- /dev/null
+++ b/lib/util/basename.c
@@ -0,0 +1,52 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+/*
+ * GNU-compatible basename(3)
+ * Unlike the POSIX version, this version never modifies its argument
+ * and returns an empty string if filename ends in a slash.
+ */
+char *
+sudo_basename_v1(const char *filename)
+{
+ char *base;
+
+ if ((base = strrchr(filename, '/')) != NULL)
+ base++;
+ else
+ base = (char *)filename;
+
+ return base;
+}
diff --git a/lib/util/cfmakeraw.c b/lib/util/cfmakeraw.c
new file mode 100644
index 0000000..f0dd41e
--- /dev/null
+++ b/lib/util/cfmakeraw.c
@@ -0,0 +1,58 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <termios.h>
+
+#include <sudo_compat.h>
+
+/* Non-standard termios input flags */
+#ifndef IUCLC
+# define IUCLC 0
+#endif
+#ifndef IMAXBEL
+# define IMAXBEL 0
+#endif
+
+/* Non-standard termios local flags */
+#ifndef IEXTEN
+# define IEXTEN 0
+#endif
+
+/*
+ * Set termios to raw mode (BSD extension).
+ */
+void
+sudo_cfmakeraw(struct termios *term)
+{
+ /* Set terminal to raw mode */
+ CLR(term->c_iflag,
+ IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IMAXBEL|IUCLC);
+ CLR(term->c_oflag, OPOST);
+ CLR(term->c_lflag, ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ CLR(term->c_cflag, CSIZE|PARENB);
+ SET(term->c_cflag, CS8);
+ term->c_cc[VMIN] = 1;
+ term->c_cc[VTIME] = 0;
+}
diff --git a/lib/util/chacha_private.h b/lib/util/chacha_private.h
new file mode 100644
index 0000000..7c3680f
--- /dev/null
+++ b/lib/util/chacha_private.h
@@ -0,0 +1,222 @@
+/*
+chacha-merged.c version 20080118
+D. J. Bernstein
+Public domain.
+*/
+
+/* $OpenBSD: chacha_private.h,v 1.2 2013/10/04 07:02:27 djm Exp $ */
+
+typedef unsigned char u8;
+typedef unsigned int u32;
+
+typedef struct
+{
+ u32 input[16]; /* could be compressed */
+} chacha_ctx;
+
+#define U8C(v) (v##U)
+#define U32C(v) (v##U)
+
+#define U8V(v) ((u8)(v) & U8C(0xFF))
+#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
+
+#define ROTL32(v, n) \
+ (U32V((v) << (n)) | ((v) >> (32 - (n))))
+
+#define U8TO32_LITTLE(p) \
+ (((u32)((p)[0]) ) | \
+ ((u32)((p)[1]) << 8) | \
+ ((u32)((p)[2]) << 16) | \
+ ((u32)((p)[3]) << 24))
+
+#define U32TO8_LITTLE(p, v) \
+ do { \
+ (p)[0] = U8V((v) ); \
+ (p)[1] = U8V((v) >> 8); \
+ (p)[2] = U8V((v) >> 16); \
+ (p)[3] = U8V((v) >> 24); \
+ } while (0)
+
+#define ROTATE(v,c) (ROTL32(v,c))
+#define XOR(v,w) ((v) ^ (w))
+#define PLUS(v,w) (U32V((v) + (w)))
+#define PLUSONE(v) (PLUS((v),1))
+
+#define QUARTERROUND(a,b,c,d) \
+ a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
+ c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
+ a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
+ c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
+
+static const char sigma[16] = "expand 32-byte k";
+static const char tau[16] = "expand 16-byte k";
+
+static void
+chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
+{
+ const char *constants;
+
+ x->input[4] = U8TO32_LITTLE(k + 0);
+ x->input[5] = U8TO32_LITTLE(k + 4);
+ x->input[6] = U8TO32_LITTLE(k + 8);
+ x->input[7] = U8TO32_LITTLE(k + 12);
+ if (kbits == 256) { /* recommended */
+ k += 16;
+ constants = sigma;
+ } else { /* kbits == 128 */
+ constants = tau;
+ }
+ x->input[8] = U8TO32_LITTLE(k + 0);
+ x->input[9] = U8TO32_LITTLE(k + 4);
+ x->input[10] = U8TO32_LITTLE(k + 8);
+ x->input[11] = U8TO32_LITTLE(k + 12);
+ x->input[0] = U8TO32_LITTLE(constants + 0);
+ x->input[1] = U8TO32_LITTLE(constants + 4);
+ x->input[2] = U8TO32_LITTLE(constants + 8);
+ x->input[3] = U8TO32_LITTLE(constants + 12);
+}
+
+static void
+chacha_ivsetup(chacha_ctx *x,const u8 *iv)
+{
+ x->input[12] = 0;
+ x->input[13] = 0;
+ x->input[14] = U8TO32_LITTLE(iv + 0);
+ x->input[15] = U8TO32_LITTLE(iv + 4);
+}
+
+static void
+chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
+{
+ u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
+ u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
+ u8 *ctarget = NULL;
+ u8 tmp[64];
+ u_int i;
+
+ if (!bytes) return;
+
+ j0 = x->input[0];
+ j1 = x->input[1];
+ j2 = x->input[2];
+ j3 = x->input[3];
+ j4 = x->input[4];
+ j5 = x->input[5];
+ j6 = x->input[6];
+ j7 = x->input[7];
+ j8 = x->input[8];
+ j9 = x->input[9];
+ j10 = x->input[10];
+ j11 = x->input[11];
+ j12 = x->input[12];
+ j13 = x->input[13];
+ j14 = x->input[14];
+ j15 = x->input[15];
+
+ for (;;) {
+ if (bytes < 64) {
+ for (i = 0;i < bytes;++i) tmp[i] = m[i];
+ m = tmp;
+ ctarget = c;
+ c = tmp;
+ }
+ x0 = j0;
+ x1 = j1;
+ x2 = j2;
+ x3 = j3;
+ x4 = j4;
+ x5 = j5;
+ x6 = j6;
+ x7 = j7;
+ x8 = j8;
+ x9 = j9;
+ x10 = j10;
+ x11 = j11;
+ x12 = j12;
+ x13 = j13;
+ x14 = j14;
+ x15 = j15;
+ for (i = 20;i > 0;i -= 2) {
+ QUARTERROUND( x0, x4, x8,x12)
+ QUARTERROUND( x1, x5, x9,x13)
+ QUARTERROUND( x2, x6,x10,x14)
+ QUARTERROUND( x3, x7,x11,x15)
+ QUARTERROUND( x0, x5,x10,x15)
+ QUARTERROUND( x1, x6,x11,x12)
+ QUARTERROUND( x2, x7, x8,x13)
+ QUARTERROUND( x3, x4, x9,x14)
+ }
+ x0 = PLUS(x0,j0);
+ x1 = PLUS(x1,j1);
+ x2 = PLUS(x2,j2);
+ x3 = PLUS(x3,j3);
+ x4 = PLUS(x4,j4);
+ x5 = PLUS(x5,j5);
+ x6 = PLUS(x6,j6);
+ x7 = PLUS(x7,j7);
+ x8 = PLUS(x8,j8);
+ x9 = PLUS(x9,j9);
+ x10 = PLUS(x10,j10);
+ x11 = PLUS(x11,j11);
+ x12 = PLUS(x12,j12);
+ x13 = PLUS(x13,j13);
+ x14 = PLUS(x14,j14);
+ x15 = PLUS(x15,j15);
+
+#ifndef KEYSTREAM_ONLY
+ x0 = XOR(x0,U8TO32_LITTLE(m + 0));
+ x1 = XOR(x1,U8TO32_LITTLE(m + 4));
+ x2 = XOR(x2,U8TO32_LITTLE(m + 8));
+ x3 = XOR(x3,U8TO32_LITTLE(m + 12));
+ x4 = XOR(x4,U8TO32_LITTLE(m + 16));
+ x5 = XOR(x5,U8TO32_LITTLE(m + 20));
+ x6 = XOR(x6,U8TO32_LITTLE(m + 24));
+ x7 = XOR(x7,U8TO32_LITTLE(m + 28));
+ x8 = XOR(x8,U8TO32_LITTLE(m + 32));
+ x9 = XOR(x9,U8TO32_LITTLE(m + 36));
+ x10 = XOR(x10,U8TO32_LITTLE(m + 40));
+ x11 = XOR(x11,U8TO32_LITTLE(m + 44));
+ x12 = XOR(x12,U8TO32_LITTLE(m + 48));
+ x13 = XOR(x13,U8TO32_LITTLE(m + 52));
+ x14 = XOR(x14,U8TO32_LITTLE(m + 56));
+ x15 = XOR(x15,U8TO32_LITTLE(m + 60));
+#endif
+
+ j12 = PLUSONE(j12);
+ if (!j12) {
+ j13 = PLUSONE(j13);
+ /* stopping at 2^70 bytes per nonce is user's responsibility */
+ }
+
+ U32TO8_LITTLE(c + 0,x0);
+ U32TO8_LITTLE(c + 4,x1);
+ U32TO8_LITTLE(c + 8,x2);
+ U32TO8_LITTLE(c + 12,x3);
+ U32TO8_LITTLE(c + 16,x4);
+ U32TO8_LITTLE(c + 20,x5);
+ U32TO8_LITTLE(c + 24,x6);
+ U32TO8_LITTLE(c + 28,x7);
+ U32TO8_LITTLE(c + 32,x8);
+ U32TO8_LITTLE(c + 36,x9);
+ U32TO8_LITTLE(c + 40,x10);
+ U32TO8_LITTLE(c + 44,x11);
+ U32TO8_LITTLE(c + 48,x12);
+ U32TO8_LITTLE(c + 52,x13);
+ U32TO8_LITTLE(c + 56,x14);
+ U32TO8_LITTLE(c + 60,x15);
+
+ if (bytes <= 64) {
+ if (bytes < 64) {
+ for (i = 0;i < bytes;++i) ctarget[i] = c[i];
+ }
+ x->input[12] = j12;
+ x->input[13] = j13;
+ return;
+ }
+ bytes -= 64;
+ c += 64;
+#ifndef KEYSTREAM_ONLY
+ m += 64;
+#endif
+ }
+}
diff --git a/lib/util/closefrom.c b/lib/util/closefrom.c
new file mode 100644
index 0000000..ef8e20c
--- /dev/null
+++ b/lib/util/closefrom.c
@@ -0,0 +1,183 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2004-2005, 2007, 2010, 2012-2015, 2017-2022
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_CLOSEFROM
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+#ifdef HAVE_PSTAT_GETPROC
+# include <sys/pstat.h>
+#else
+# include <dirent.h>
+#endif
+#ifdef HAVE_LIBPROC_H
+# include <libproc.h>
+#endif
+#ifdef HAVE_LINUX_CLOSE_RANGE_H
+# include <linux/close_range.h>
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <pathnames.h>
+
+#ifndef OPEN_MAX
+# define OPEN_MAX 256
+#endif
+
+/* Avoid potential libdispatch crash on macOS when we close its fds. */
+#ifdef __APPLE__
+# define closefrom_close(x) fcntl((x), F_SETFD, FD_CLOEXEC)
+#else
+# define closefrom_close(x) close(x)
+#endif
+
+/*
+ * Close all file descriptors greater than or equal to lowfd.
+ * This is the expensive (fallback) method.
+ */
+static void
+closefrom_fallback(int lowfd)
+{
+ long fd, maxfd;
+
+ /*
+ * Fall back on sysconf(_SC_OPEN_MAX). This is equivalent to
+ * checking the RLIMIT_NOFILE soft limit. It is possible for
+ * there to be open file descriptors past this limit but there's
+ * not much we can do about that since the hard limit may be
+ * RLIM_INFINITY (LLONG_MAX or ULLONG_MAX on modern systems).
+ */
+ maxfd = sysconf(_SC_OPEN_MAX);
+ if (maxfd < OPEN_MAX)
+ maxfd = OPEN_MAX;
+
+ /* Make sure we didn't get RLIM_INFINITY as the upper limit. */
+ if (maxfd > INT_MAX)
+ maxfd = INT_MAX;
+
+ for (fd = lowfd; fd < maxfd; fd++) {
+ (void)closefrom_close((int)fd);
+ }
+}
+
+/*
+ * Close all file descriptors greater than or equal to lowfd.
+ * We try the fast way first, falling back on the slow method.
+ */
+void
+sudo_closefrom(int lowfd)
+{
+#if defined(HAVE_PSTAT_GETPROC)
+ struct pst_status pst;
+#elif defined(HAVE_DIRFD)
+ const char *path;
+ DIR *dirp;
+#endif
+#if defined(HAVE_PROC_PIDINFO)
+ struct proc_fdinfo *buf = NULL;
+ const pid_t pid = getpid();
+ int i, n, len;
+#endif
+
+ /* Try the fast method first, if possible. */
+#if defined(HAVE_FCNTL_CLOSEM)
+ if (fcntl(lowfd, F_CLOSEM, 0) != -1)
+ return;
+#elif defined(HAVE_CLOSE_RANGE)
+ if (close_range((unsigned int)lowfd, ~0U, 0) != -1)
+ return;
+#elif defined(HAVE_PROC_PIDINFO)
+ len = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
+ switch (len) {
+ case 0:
+ /* No open files. */
+ return;
+ case -1:
+ /* Fall back on other methods. */
+ break;
+ default:
+ /* Allocate space for 4 extra fds to leave some wiggle room. */
+ buf = malloc(len + (PROC_PIDLISTFD_SIZE * 4));
+ if (buf == NULL)
+ break;
+ n = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, buf, len);
+ if (n == -1 || n > len) {
+ free(buf);
+ break;
+ }
+ n /= PROC_PIDLISTFD_SIZE;
+ for (i = 0; i < n; i++) {
+ if (buf[i].proc_fd >= lowfd) {
+ (void)closefrom_close(buf[i].proc_fd);
+ }
+ }
+ free(buf);
+ return;
+ }
+#endif /* HAVE_PROC_PIDINFO */
+#if defined(HAVE_PSTAT_GETPROC)
+ /*
+ * EOVERFLOW is not a fatal error for the fields we use.
+ * See the "EOVERFLOW Error" section of pstat_getvminfo(3).
+ */
+ if (pstat_getproc(&pst, sizeof(pst), 0, getpid()) != -1 ||
+ errno == EOVERFLOW) {
+ int fd;
+
+ for (fd = lowfd; fd <= pst.pst_highestfd; fd++)
+ (void)closefrom_close(fd);
+ return;
+ }
+#elif defined(HAVE_DIRFD)
+ /* Use /proc/self/fd (or /dev/fd on macOS) if it exists. */
+# ifdef __APPLE__
+ path = _PATH_DEV "fd";
+# else
+ path = "/proc/self/fd";
+# endif
+ if ((dirp = opendir(path)) != NULL) {
+ struct dirent *dent;
+ while ((dent = readdir(dirp)) != NULL) {
+ const char *errstr;
+ int fd = (int)sudo_strtonum(dent->d_name, lowfd, INT_MAX, &errstr);
+ if (errstr == NULL && fd != dirfd(dirp)) {
+ (void)closefrom_close(fd);
+ }
+ }
+ (void)closedir(dirp);
+ return;
+ }
+#endif /* HAVE_DIRFD */
+
+ /* Do things the slow way. */
+ closefrom_fallback(lowfd);
+}
+
+#endif /* HAVE_CLOSEFROM */
diff --git a/lib/util/digest.c b/lib/util/digest.c
new file mode 100644
index 0000000..b3a3b87
--- /dev/null
+++ b/lib/util/digest.c
@@ -0,0 +1,172 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <unistd.h>
+#include <errno.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_digest.h>
+
+#ifdef HAVE_SHA224UPDATE
+# include <sha2.h>
+#else
+# include <compat/sha2.h>
+#endif
+
+static struct digest_function {
+ const size_t digest_len;
+ void (*init)(SHA2_CTX *);
+#ifdef SHA2_VOID_PTR
+ void (*update)(SHA2_CTX *, const void *, size_t);
+ void (*final)(void *, SHA2_CTX *);
+#else
+ void (*update)(SHA2_CTX *, const unsigned char *, size_t);
+ void (*final)(unsigned char *, SHA2_CTX *);
+#endif
+} digest_functions[] = {
+ {
+ SHA224_DIGEST_LENGTH,
+ SHA224Init,
+ SHA224Update,
+ SHA224Final
+ }, {
+ SHA256_DIGEST_LENGTH,
+ SHA256Init,
+ SHA256Update,
+ SHA256Final
+ }, {
+ SHA384_DIGEST_LENGTH,
+ SHA384Init,
+ SHA384Update,
+ SHA384Final
+ }, {
+ SHA512_DIGEST_LENGTH,
+ SHA512Init,
+ SHA512Update,
+ SHA512Final
+ }, {
+ 0
+ }
+};
+
+struct sudo_digest {
+ struct digest_function *func;
+ SHA2_CTX ctx;
+};
+
+struct sudo_digest *
+sudo_digest_alloc_v1(unsigned int digest_type)
+{
+ debug_decl(sudo_digest_alloc, SUDO_DEBUG_UTIL);
+ struct digest_function *func = NULL;
+ struct sudo_digest *dig;
+ unsigned int i;
+
+ for (i = 0; digest_functions[i].digest_len != 0; i++) {
+ if (digest_type == i) {
+ func = &digest_functions[i];
+ break;
+ }
+ }
+ if (func == NULL) {
+ errno = EINVAL;
+ debug_return_ptr(NULL);
+ }
+
+ if ((dig = malloc(sizeof(*dig))) == NULL)
+ debug_return_ptr(NULL);
+ func->init(&dig->ctx);
+ dig->func = func;
+
+ debug_return_ptr(dig);
+}
+
+void
+sudo_digest_free_v1(struct sudo_digest *dig)
+{
+ debug_decl(sudo_digest_free, SUDO_DEBUG_UTIL);
+
+ free(dig);
+
+ debug_return;
+}
+
+void
+sudo_digest_reset_v1(struct sudo_digest *dig)
+{
+ debug_decl(sudo_digest_reset, SUDO_DEBUG_UTIL);
+
+ dig->func->init(&dig->ctx);
+
+ debug_return;
+}
+
+size_t
+sudo_digest_getlen_v2(unsigned int digest_type)
+{
+ debug_decl(sudo_digest_getlen, SUDO_DEBUG_UTIL);
+ unsigned int i;
+
+ for (i = 0; digest_functions[i].digest_len != 0; i++) {
+ if (digest_type == i)
+ debug_return_size_t(digest_functions[i].digest_len);
+ }
+
+ debug_return_size_t(0);
+}
+
+int
+sudo_digest_getlen_v1(unsigned int digest_type)
+{
+ size_t len = sudo_digest_getlen_v2(digest_type);
+ return len ? (int)len : -1;
+}
+
+void
+sudo_digest_update_v1(struct sudo_digest *dig, const void *data, size_t len)
+{
+ debug_decl(sudo_digest_update, SUDO_DEBUG_UTIL);
+
+ dig->func->update(&dig->ctx, data, len);
+
+ debug_return;
+}
+
+void
+sudo_digest_final_v1(struct sudo_digest *dig, unsigned char *md)
+{
+ debug_decl(sudo_digest_final, SUDO_DEBUG_UTIL);
+
+ dig->func->final(md, &dig->ctx);
+
+ debug_return;
+}
diff --git a/lib/util/digest_gcrypt.c b/lib/util/digest_gcrypt.c
new file mode 100644
index 0000000..7deae2d
--- /dev/null
+++ b/lib/util/digest_gcrypt.c
@@ -0,0 +1,167 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2017-2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <gcrypt.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_digest.h>
+
+#define SUDO_LIBGCRYPT_VERSION_MIN "1.3.0"
+
+struct sudo_digest {
+ int gcry_digest_type;
+ unsigned int digest_len;
+ gcry_md_hd_t ctx;
+};
+
+/* Map sudo digest type to gcrypt digest type. */
+static int
+sudo_digest_type_to_gcry(unsigned int digest_type)
+{
+ switch (digest_type) {
+ case SUDO_DIGEST_SHA224:
+ return GCRY_MD_SHA224;
+ case SUDO_DIGEST_SHA256:
+ return GCRY_MD_SHA256;
+ case SUDO_DIGEST_SHA384:
+ return GCRY_MD_SHA384;
+ case SUDO_DIGEST_SHA512:
+ return GCRY_MD_SHA512;
+ default:
+ return -1;
+ }
+}
+
+struct sudo_digest *
+sudo_digest_alloc_v1(unsigned int digest_type)
+{
+ debug_decl(sudo_digest_alloc, SUDO_DEBUG_UTIL);
+ static bool initialized = false;
+ struct sudo_digest *dig;
+ int gcry_digest_type;
+
+ if (!initialized) {
+ if (!gcry_check_version(SUDO_LIBGCRYPT_VERSION_MIN)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "libgcrypt too old (need %s, have %s)",
+ SUDO_LIBGCRYPT_VERSION_MIN, gcry_check_version(NULL));
+ debug_return_ptr(NULL);
+ }
+ gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
+ initialized = true;
+ }
+
+ gcry_digest_type = sudo_digest_type_to_gcry(digest_type);
+ if (gcry_digest_type == -1) {
+ errno = EINVAL;
+ debug_return_ptr(NULL);
+ }
+
+ if ((dig = malloc(sizeof(*dig))) == NULL)
+ debug_return_ptr(NULL);
+ dig->gcry_digest_type = gcry_digest_type;
+ dig->digest_len = gcry_md_get_algo_dlen(gcry_digest_type);
+
+ if (gcry_md_open(&dig->ctx, gcry_digest_type, 0) != 0) {
+ free(dig);
+ debug_return_ptr(NULL);
+ }
+
+ debug_return_ptr(dig);
+}
+
+void
+sudo_digest_free_v1(struct sudo_digest *dig)
+{
+ debug_decl(sudo_digest_free, SUDO_DEBUG_UTIL);
+
+ if (dig != NULL) {
+ gcry_md_close(dig->ctx);
+ free(dig);
+ }
+
+ debug_return;
+}
+
+void
+sudo_digest_reset_v1(struct sudo_digest *dig)
+{
+ debug_decl(sudo_digest_reset, SUDO_DEBUG_UTIL);
+
+ gcry_md_reset(dig->ctx);
+
+ debug_return;
+}
+
+size_t
+sudo_digest_getlen_v2(unsigned int digest_type)
+{
+ debug_decl(sudo_digest_getlen, SUDO_DEBUG_UTIL);
+ int gcry_digest_type;
+
+ gcry_digest_type = sudo_digest_type_to_gcry(digest_type);
+ if (gcry_digest_type == -1)
+ debug_return_size_t(0);
+
+ debug_return_size_t(gcry_md_get_algo_dlen(gcry_digest_type));
+}
+
+int
+sudo_digest_getlen_v1(unsigned int digest_type)
+{
+ size_t len = sudo_digest_getlen_v2(digest_type);
+ return len ? (int)len : -1;
+}
+
+void
+sudo_digest_update_v1(struct sudo_digest *dig, const void *data, size_t len)
+{
+ debug_decl(sudo_digest_update, SUDO_DEBUG_UTIL);
+
+ gcry_md_write(dig->ctx, data, len);
+
+ debug_return;
+}
+
+void
+sudo_digest_final_v1(struct sudo_digest *dig, unsigned char *md)
+{
+ debug_decl(sudo_digest_final, SUDO_DEBUG_UTIL);
+
+ gcry_md_final(dig->ctx);
+ memcpy(md, gcry_md_read(dig->ctx, 0), dig->digest_len);
+
+ debug_return;
+}
diff --git a/lib/util/digest_openssl.c b/lib/util/digest_openssl.c
new file mode 100644
index 0000000..712b20b
--- /dev/null
+++ b/lib/util/digest_openssl.c
@@ -0,0 +1,159 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <errno.h>
+
+#if defined(HAVE_WOLFSSL)
+# include <wolfssl/options.h>
+#endif
+#include <openssl/evp.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_digest.h>
+
+struct sudo_digest {
+ EVP_MD_CTX *ctx;
+ const EVP_MD *md;
+};
+
+static const EVP_MD *
+sudo_digest_type_to_md(unsigned int digest_type)
+{
+ const EVP_MD *md = NULL;
+ debug_decl(sudo_digest_type_to_md, SUDO_DEBUG_UTIL);
+
+ switch (digest_type) {
+ case SUDO_DIGEST_SHA224:
+ md = EVP_sha224();
+ break;
+ case SUDO_DIGEST_SHA256:
+ md = EVP_sha256();
+ break;
+ case SUDO_DIGEST_SHA384:
+ md = EVP_sha384();
+ break;
+ case SUDO_DIGEST_SHA512:
+ md = EVP_sha512();
+ break;
+ default:
+ errno = EINVAL;
+ break;
+ }
+ debug_return_const_ptr(md);
+}
+
+struct sudo_digest *
+sudo_digest_alloc_v1(unsigned int digest_type)
+{
+ struct sudo_digest *dig;
+ EVP_MD_CTX *mdctx = NULL;
+ const EVP_MD *md;
+ debug_decl(sudo_digest_alloc, SUDO_DEBUG_UTIL);
+
+ md = sudo_digest_type_to_md(digest_type);
+ if (md == NULL)
+ goto bad;
+
+ mdctx = EVP_MD_CTX_new();
+ if (mdctx == NULL || !EVP_DigestInit_ex(mdctx, md, NULL))
+ goto bad;
+
+ if ((dig = malloc(sizeof(*dig))) == NULL)
+ goto bad;
+ dig->md = md;
+ dig->ctx = mdctx;
+
+ debug_return_ptr(dig);
+bad:
+ EVP_MD_CTX_free(mdctx);
+ debug_return_ptr(NULL);
+}
+
+void
+sudo_digest_free_v1(struct sudo_digest *dig)
+{
+ debug_decl(sudo_digest_free, SUDO_DEBUG_UTIL);
+
+ if (dig != NULL) {
+ EVP_MD_CTX_free(dig->ctx);
+ free(dig);
+ }
+
+ debug_return;
+}
+
+void
+sudo_digest_reset_v1(struct sudo_digest *dig)
+{
+ debug_decl(sudo_digest_reset, SUDO_DEBUG_UTIL);
+
+ /* These cannot fail. */
+ EVP_MD_CTX_reset(dig->ctx);
+ EVP_DigestInit_ex(dig->ctx, dig->md, NULL);
+
+ debug_return;
+}
+
+size_t
+sudo_digest_getlen_v2(unsigned int digest_type)
+{
+ const EVP_MD *md;
+ debug_decl(sudo_digest_getlen, SUDO_DEBUG_UTIL);
+
+ md = sudo_digest_type_to_md(digest_type);
+ if (md == NULL)
+ debug_return_size_t(0);
+
+ debug_return_size_t((size_t)EVP_MD_size(md));
+}
+
+int
+sudo_digest_getlen_v1(unsigned int digest_type)
+{
+ size_t len = sudo_digest_getlen_v2(digest_type);
+ return len ? (int)len : -1;
+}
+
+void
+sudo_digest_update_v1(struct sudo_digest *dig, const void *data, size_t len)
+{
+ debug_decl(sudo_digest_update, SUDO_DEBUG_UTIL);
+
+ EVP_DigestUpdate(dig->ctx, data, len);
+
+ debug_return;
+}
+
+void
+sudo_digest_final_v1(struct sudo_digest *dig, unsigned char *md)
+{
+ debug_decl(sudo_digest_final, SUDO_DEBUG_UTIL);
+
+ EVP_DigestFinal_ex(dig->ctx, md, NULL);
+
+ debug_return;
+}
diff --git a/lib/util/dup3.c b/lib/util/dup3.c
new file mode 100644
index 0000000..c3ab141
--- /dev/null
+++ b/lib/util/dup3.c
@@ -0,0 +1,74 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_DUP3
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+
+int
+sudo_dup3(int oldd, int newd, int flags)
+{
+ int oflags;
+
+ if (oldd == newd) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (dup2(oldd, newd) == -1)
+ return -1;
+
+ oflags = fcntl(newd, F_GETFL, 0);
+ if (oflags == -1)
+ goto bad;
+
+ if (ISSET(flags, O_NONBLOCK)) {
+ if (!ISSET(oflags, O_NONBLOCK)) {
+ SET(oflags, O_NONBLOCK);
+ if (fcntl(newd, F_SETFL, oflags) == -1)
+ goto bad;
+ }
+ } else {
+ if (ISSET(oflags, O_NONBLOCK)) {
+ CLR(oflags, O_NONBLOCK);
+ if (fcntl(newd, F_SETFL, oflags) == -1)
+ goto bad;
+ }
+ }
+ if (ISSET(flags, O_CLOEXEC)) {
+ if (fcntl(newd, F_SETFD, FD_CLOEXEC) == -1)
+ goto bad;
+ }
+ return 0;
+bad:
+ close(newd);
+ return -1;
+}
+
+#endif /* HAVE_DUP3 */
diff --git a/lib/util/event.c b/lib/util/event.c
new file mode 100644
index 0000000..e49f657
--- /dev/null
+++ b/lib/util/event.c
@@ -0,0 +1,881 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_debug.h>
+#include <sudo_event.h>
+#include <sudo_util.h>
+
+static void sudo_ev_init(struct sudo_event *ev, int fd, int events,
+ sudo_ev_callback_t callback, void *closure);
+
+/* Default event base when none is specified. */
+static struct sudo_event_base *default_base;
+
+/* We need the event base to be available from the signal handler. */
+static struct sudo_event_base *signal_base;
+
+/*
+ * Add an event to the base's active queue and mark it active.
+ * This is extern so sudo_ev_scan_impl() can call it.
+ */
+void
+sudo_ev_activate(struct sudo_event_base *base, struct sudo_event *ev)
+{
+ TAILQ_INSERT_TAIL(&base->active, ev, active_entries);
+ SET(ev->flags, SUDO_EVQ_ACTIVE);
+}
+
+/*
+ * Remove an event from the base's active queue and mark it inactive.
+ */
+static inline void
+sudo_ev_deactivate(struct sudo_event_base *base, struct sudo_event *ev)
+{
+ CLR(ev->flags, SUDO_EVQ_ACTIVE);
+ TAILQ_REMOVE(&base->active, ev, active_entries);
+}
+
+/*
+ * Clear out the base's active queue and mark all events as inactive.
+ */
+static void
+sudo_ev_deactivate_all(struct sudo_event_base *base)
+{
+ struct sudo_event *ev;
+ debug_decl(sudo_ev_deactivate_all, SUDO_DEBUG_EVENT);
+
+ while ((ev = TAILQ_FIRST(&base->active)) != NULL)
+ sudo_ev_deactivate(base, ev);
+
+ debug_return;
+}
+
+/*
+ * Activate all signal events for which the corresponding signal_pending[]
+ * flag is set.
+ */
+static void
+sudo_ev_activate_sigevents(struct sudo_event_base *base)
+{
+ struct sudo_event *ev;
+ sigset_t set, oset;
+ unsigned int i;
+ debug_decl(sudo_ev_activate_sigevents, SUDO_DEBUG_EVENT);
+
+ /*
+ * We treat this as a critical section since the signal handler
+ * could modify the siginfo[] entry.
+ */
+ sigfillset(&set);
+ sigprocmask(SIG_BLOCK, &set, &oset);
+ base->signal_caught = 0;
+ for (i = 0; i < NSIG; i++) {
+ if (!base->signal_pending[i])
+ continue;
+ base->signal_pending[i] = 0;
+ TAILQ_FOREACH(ev, &base->signals[i], entries) {
+ if (ISSET(ev->events, SUDO_EV_SIGINFO)) {
+ struct sudo_ev_siginfo_container *sc = ev->closure;
+ if (base->siginfo[i]->si_signo == 0) {
+ /* No siginfo available. */
+ sc->siginfo = NULL;
+ } else {
+ sc->siginfo = (siginfo_t *)sc->si_buf;
+ memcpy(sc->siginfo, base->siginfo[i], sizeof(siginfo_t));
+ }
+ }
+ /* Make event active. */
+ ev->revents = ev->events & (SUDO_EV_SIGNAL|SUDO_EV_SIGINFO);
+ TAILQ_INSERT_TAIL(&base->active, ev, active_entries);
+ SET(ev->flags, SUDO_EVQ_ACTIVE);
+ }
+ }
+ sigprocmask(SIG_SETMASK, &oset, NULL);
+
+ debug_return;
+}
+
+/*
+ * Internal callback for SUDO_EV_SIGNAL and SUDO_EV_SIGINFO.
+ */
+static void
+signal_pipe_cb(int fd, int what, void *v)
+{
+ struct sudo_event_base *base = v;
+ unsigned char ch;
+ ssize_t nread;
+ debug_decl(signal_pipe_cb, SUDO_DEBUG_EVENT);
+
+ /*
+ * Drain signal_pipe, the signal handler updated base->signals_pending.
+ * Actual processing of signal events is done when poll/select is
+ * interrupted by a signal.
+ */
+ while ((nread = read(fd, &ch, 1)) > 0) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: received signal %d", __func__, (int)ch);
+ }
+ if (nread == -1 && errno != EAGAIN) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "%s: error reading from signal pipe fd %d", __func__, fd);
+ }
+
+ /* Activate signal events. */
+ sudo_ev_activate_sigevents(base);
+
+ debug_return;
+}
+
+static int
+sudo_ev_base_init(struct sudo_event_base *base)
+{
+ unsigned int i;
+ debug_decl(sudo_ev_base_init, SUDO_DEBUG_EVENT);
+
+ TAILQ_INIT(&base->events);
+ TAILQ_INIT(&base->timeouts);
+ for (i = 0; i < NSIG; i++)
+ TAILQ_INIT(&base->signals[i]);
+ if (sudo_ev_base_alloc_impl(base) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: unable to allocate impl base", __func__);
+ goto bad;
+ }
+ if (pipe2(base->signal_pipe, O_NONBLOCK|O_CLOEXEC) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: unable to create signal pipe", __func__);
+ goto bad;
+ }
+ sudo_ev_init(&base->signal_event, base->signal_pipe[0],
+ SUDO_EV_READ|SUDO_EV_PERSIST, signal_pipe_cb, base);
+
+ debug_return_int(0);
+bad:
+ /* Note: signal_pipe[] not filled in. */
+ sudo_ev_base_free_impl(base);
+ debug_return_int(-1);
+}
+
+struct sudo_event_base *
+sudo_ev_base_alloc_v1(void)
+{
+ struct sudo_event_base *base;
+ debug_decl(sudo_ev_base_alloc, SUDO_DEBUG_EVENT);
+
+ base = calloc(1, sizeof(*base));
+ if (base == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: unable to allocate base", __func__);
+ debug_return_ptr(NULL);
+ }
+ if (sudo_ev_base_init(base) != 0) {
+ free(base);
+ debug_return_ptr(NULL);
+ }
+ debug_return_ptr(base);
+}
+
+void
+sudo_ev_base_free_v1(struct sudo_event_base *base)
+{
+ struct sudo_event *ev, *next;
+ unsigned int i;
+ debug_decl(sudo_ev_base_free, SUDO_DEBUG_EVENT);
+
+ if (base == NULL)
+ debug_return;
+
+ /* Reset the default base if necessary. */
+ if (default_base == base)
+ default_base = NULL;
+
+ /* Remove any existing events before freeing the base. */
+ TAILQ_FOREACH_SAFE(ev, &base->events, entries, next) {
+ sudo_ev_del(base, ev);
+ ev->base = NULL;
+ }
+ for (i = 0; i < NSIG; i++) {
+ TAILQ_FOREACH_SAFE(ev, &base->signals[i], entries, next) {
+ sudo_ev_del(base, ev);
+ ev->base = NULL;
+ }
+ free(base->siginfo[i]);
+ free(base->orig_handlers[i]);
+ }
+ sudo_ev_base_free_impl(base);
+ close(base->signal_pipe[0]);
+ close(base->signal_pipe[1]);
+ free(base);
+
+ debug_return;
+}
+
+void
+sudo_ev_base_setdef_v1(struct sudo_event_base *base)
+{
+ debug_decl(sudo_ev_base_setdef, SUDO_DEBUG_EVENT);
+
+ default_base = base;
+
+ debug_return;
+}
+
+/*
+ * Clear and fill in a struct sudo_event.
+ */
+static void
+sudo_ev_init(struct sudo_event *ev, int fd, int events,
+ sudo_ev_callback_t callback, void *closure)
+{
+ debug_decl(sudo_ev_init, SUDO_DEBUG_EVENT);
+
+ memset(ev, 0, sizeof(*ev));
+ ev->fd = fd;
+ ev->events = events & SUDO_EV_MASK;
+ ev->pfd_idx = -1;
+ ev->callback = callback;
+ ev->closure = closure;
+
+ debug_return;
+}
+
+/*
+ * Set a pre-allocated struct sudo_event.
+ * Allocates space for siginfo_t for SUDO_EV_SIGINFO as needed.
+ */
+int
+sudo_ev_set_v2(struct sudo_event *ev, int fd, int events,
+ sudo_ev_callback_t callback, void *closure)
+{
+ debug_decl(sudo_ev_set, SUDO_DEBUG_EVENT);
+
+ /* For SUDO_EV_SIGINFO we use a container to store closure + siginfo_t */
+ if (ISSET(events, SUDO_EV_SIGINFO)) {
+ struct sudo_ev_siginfo_container *container =
+ malloc(sizeof(*container) + sizeof(siginfo_t));
+ if (container == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: unable to allocate siginfo container", __func__);
+ debug_return_int(-1);
+ }
+ container->closure = closure;
+ closure = container;
+ }
+ sudo_ev_init(ev, fd, events, callback, closure);
+
+ debug_return_int(0);
+}
+
+int
+sudo_ev_set_v1(struct sudo_event *ev, int fd, short events,
+ sudo_ev_callback_t callback, void *closure)
+{
+ return sudo_ev_set_v2(ev, fd, events, callback, closure);
+}
+
+struct sudo_event *
+sudo_ev_alloc_v2(int fd, int events, sudo_ev_callback_t callback, void *closure)
+{
+ struct sudo_event *ev;
+ debug_decl(sudo_ev_alloc, SUDO_DEBUG_EVENT);
+
+ ev = malloc(sizeof(*ev));
+ if (ev == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: unable to allocate event", __func__);
+ debug_return_ptr(NULL);
+ }
+ if (sudo_ev_set(ev, fd, events, callback, closure) == -1) {
+ free(ev);
+ debug_return_ptr(NULL);
+ }
+ debug_return_ptr(ev);
+}
+
+struct sudo_event *
+sudo_ev_alloc_v1(int fd, short events, sudo_ev_callback_t callback, void *closure)
+{
+ return sudo_ev_alloc_v2(fd, events, callback, closure);
+}
+
+void
+sudo_ev_free_v1(struct sudo_event *ev)
+{
+ debug_decl(sudo_ev_free, SUDO_DEBUG_EVENT);
+
+ if (ev == NULL)
+ debug_return;
+
+ /* Make sure ev is not in use before freeing it. */
+ if (ISSET(ev->flags, SUDO_EVQ_INSERTED))
+ (void)sudo_ev_del(NULL, ev);
+ if (ISSET(ev->events, SUDO_EV_SIGINFO))
+ free(ev->closure);
+ free(ev);
+
+ debug_return;
+}
+
+static void
+sudo_ev_handler(int signo, siginfo_t *info, void *context)
+{
+ unsigned char ch = (unsigned char)signo;
+
+ if (signal_base != NULL) {
+ /*
+ * Update signals_pending[] and siginfo[].
+ * All signals must be blocked any time siginfo[] is accessed.
+ * If no siginfo available, zero out the struct in base.
+ */
+ if (info == NULL)
+ memset(signal_base->siginfo[signo], 0, sizeof(*info));
+ else
+ memcpy(signal_base->siginfo[signo], info, sizeof(*info));
+ signal_base->signal_pending[signo] = 1;
+ signal_base->signal_caught = 1;
+
+ /* Wake up the other end of the pipe. */
+ ignore_result(write(signal_base->signal_pipe[1], &ch, 1));
+ }
+}
+
+static int
+sudo_ev_add_signal(struct sudo_event_base *base, struct sudo_event *ev,
+ bool tohead)
+{
+ const int signo = ev->fd;
+ debug_decl(sudo_ev_add_signal, SUDO_DEBUG_EVENT);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: adding event %p to base %p, signal %d, events %d",
+ __func__, ev, base, signo, ev->events);
+ if (signo >= NSIG) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: signo %d larger than max %d", __func__, signo, NSIG - 1);
+ debug_return_int(-1);
+ }
+ if ((ev->events & ~(SUDO_EV_SIGNAL|SUDO_EV_SIGINFO|SUDO_EV_PERSIST)) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: invalid event set 0x%x", __func__, ev->events);
+ debug_return_int(-1);
+ }
+
+ /*
+ * Allocate base->siginfo[signo] and base->orig_handlers[signo] as needed.
+ */
+ if (base->siginfo[signo] == NULL) {
+ base->siginfo[signo] = malloc(sizeof(*base->siginfo[signo]));
+ if (base->siginfo[signo] == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: unable to allocate siginfo for signo %d",
+ __func__, signo);
+ debug_return_int(-1);
+ }
+ }
+ if (base->orig_handlers[signo] == NULL) {
+ base->orig_handlers[signo] =
+ malloc(sizeof(*base->orig_handlers[signo]));
+ if (base->orig_handlers[signo] == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: unable to allocate orig_handlers for signo %d",
+ __func__, signo);
+ debug_return_int(-1);
+ }
+ }
+
+ /* Install signal handler as needed, saving the original value. */
+ if (TAILQ_EMPTY(&base->signals[signo])) {
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sigfillset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART|SA_SIGINFO;
+ sa.sa_sigaction = sudo_ev_handler;
+ if (sigaction(signo, &sa, base->orig_handlers[signo]) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: unable to install handler for signo %d", __func__, signo);
+ debug_return_int(-1);
+ }
+ base->num_handlers++;
+ }
+
+ /*
+ * Insert signal event into the proper tail queue.
+ * Signal events are always persistent.
+ */
+ ev->base = base;
+ if (tohead) {
+ TAILQ_INSERT_HEAD(&base->signals[signo], ev, entries);
+ } else {
+ TAILQ_INSERT_TAIL(&base->signals[signo], ev, entries);
+ }
+ SET(ev->events, SUDO_EV_PERSIST);
+ SET(ev->flags, SUDO_EVQ_INSERTED);
+
+ /* Add the internal signal_pipe event on demand. */
+ if (!ISSET(base->signal_event.flags, SUDO_EVQ_INSERTED))
+ sudo_ev_add(base, &base->signal_event, NULL, true);
+
+ /* Update global signal base so handler to update signals_pending[] */
+ signal_base = base;
+
+ debug_return_int(0);
+}
+
+int
+sudo_ev_add_v1(struct sudo_event_base *base, struct sudo_event *ev,
+ const struct timeval *timo, bool tohead)
+{
+ struct timespec tsbuf, *ts = NULL;
+
+ if (timo != NULL) {
+ TIMEVAL_TO_TIMESPEC(timo, &tsbuf);
+ ts = &tsbuf;
+ }
+
+ return sudo_ev_add_v2(base, ev, ts, tohead);
+}
+
+int
+sudo_ev_add_v2(struct sudo_event_base *base, struct sudo_event *ev,
+ const struct timespec *timo, bool tohead)
+{
+ debug_decl(sudo_ev_add, SUDO_DEBUG_EVENT);
+
+ /* If no base specified, use existing or default base. */
+ if (base == NULL) {
+ if (ev->base != NULL) {
+ base = ev->base;
+ } else if (default_base != NULL) {
+ base = default_base;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "%s: no base specified",
+ __func__);
+ debug_return_int(-1);
+ }
+ }
+
+ /* Only add new events to the events list. */
+ if (ISSET(ev->flags, SUDO_EVQ_INSERTED)) {
+ /* If event no longer has a timeout, remove from timeouts queue. */
+ if (timo == NULL && ISSET(ev->flags, SUDO_EVQ_TIMEOUTS)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: removing event %p from timeouts queue", __func__, ev);
+ CLR(ev->flags, SUDO_EVQ_TIMEOUTS);
+ TAILQ_REMOVE(&base->timeouts, ev, timeouts_entries);
+ }
+ } else {
+ /* Special handling for signal events. */
+ if (ev->events & (SUDO_EV_SIGNAL|SUDO_EV_SIGINFO))
+ debug_return_int(sudo_ev_add_signal(base, ev, tohead));
+
+ /* Add event to the base. */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: adding event %p to base %p, fd %d, events %d",
+ __func__, ev, base, ev->fd, ev->events);
+ if (ev->events & (SUDO_EV_READ|SUDO_EV_WRITE)) {
+ if (sudo_ev_add_impl(base, ev) != 0)
+ debug_return_int(-1);
+ }
+ ev->base = base;
+ if (tohead) {
+ TAILQ_INSERT_HEAD(&base->events, ev, entries);
+ } else {
+ TAILQ_INSERT_TAIL(&base->events, ev, entries);
+ }
+ SET(ev->flags, SUDO_EVQ_INSERTED);
+ }
+ /* Timeouts can be changed for existing events. */
+ if (timo != NULL) {
+ struct sudo_event *evtmp;
+ if (ISSET(ev->flags, SUDO_EVQ_TIMEOUTS)) {
+ /* Remove from timeouts list, then add back. */
+ TAILQ_REMOVE(&base->timeouts, ev, timeouts_entries);
+ }
+ /* Convert to absolute time and insert in sorted order; O(n). */
+ sudo_gettime_mono(&ev->timeout);
+ sudo_timespecadd(&ev->timeout, timo, &ev->timeout);
+ TAILQ_FOREACH(evtmp, &base->timeouts, timeouts_entries) {
+ if (sudo_timespeccmp(&ev->timeout, &evtmp->timeout, <))
+ break;
+ }
+ if (evtmp != NULL) {
+ TAILQ_INSERT_BEFORE(evtmp, ev, timeouts_entries);
+ } else {
+ TAILQ_INSERT_TAIL(&base->timeouts, ev, timeouts_entries);
+ }
+ SET(ev->flags, SUDO_EVQ_TIMEOUTS);
+ }
+ debug_return_int(0);
+}
+
+/*
+ * Remove an event from the base, if specified, or the base embedded
+ * in the event if not. Note that there are multiple tail queues.
+ */
+int
+sudo_ev_del_v1(struct sudo_event_base *base, struct sudo_event *ev)
+{
+ debug_decl(sudo_ev_del, SUDO_DEBUG_EVENT);
+
+ /* Make sure event is really in the queue. */
+ if (!ISSET(ev->flags, SUDO_EVQ_INSERTED)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: event %p not in queue",
+ __func__, ev);
+ debug_return_int(0);
+ }
+
+ /* Check for event base mismatch, if one is specified. */
+ if (base == NULL) {
+ if (ev->base == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "%s: no base specified",
+ __func__);
+ debug_return_int(-1);
+ }
+ base = ev->base;
+ } else if (base != ev->base) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "%s: mismatch base %p, ev->base %p",
+ __func__, base, ev->base);
+ debug_return_int(-1);
+ }
+
+ if (ev->events & (SUDO_EV_SIGNAL|SUDO_EV_SIGINFO)) {
+ const int signo = ev->fd;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: removing event %p from base %p, signo %d, events %d",
+ __func__, ev, base, signo, ev->events);
+
+ /* Unlink from signal event list. */
+ TAILQ_REMOVE(&base->signals[signo], ev, entries);
+ if (TAILQ_EMPTY(&base->signals[signo])) {
+ if (sigaction(signo, base->orig_handlers[signo], NULL) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: unable to restore handler for signo %d",
+ __func__, signo);
+ debug_return_int(-1);
+ }
+ base->num_handlers--;
+ }
+ if (base->num_handlers == 0) {
+ /* No registered signal events, remove internal event. */
+ sudo_ev_del(base, &base->signal_event);
+ }
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: removing event %p from base %p, fd %d, events %d",
+ __func__, ev, base, ev->fd, ev->events);
+
+ /* Call backend. */
+ if (ev->events & (SUDO_EV_READ|SUDO_EV_WRITE)) {
+ if (sudo_ev_del_impl(base, ev) != 0)
+ debug_return_int(-1);
+ }
+
+ /* Unlink from event list. */
+ TAILQ_REMOVE(&base->events, ev, entries);
+
+ /* Unlink from timeouts list. */
+ if (ISSET(ev->flags, SUDO_EVQ_TIMEOUTS))
+ TAILQ_REMOVE(&base->timeouts, ev, timeouts_entries);
+ }
+
+ /* Unlink from active list. */
+ if (ISSET(ev->flags, SUDO_EVQ_ACTIVE))
+ TAILQ_REMOVE(&base->active, ev, active_entries);
+
+ /* Mark event unused. */
+ ev->flags = 0;
+ ev->pfd_idx = -1;
+
+ debug_return_int(0);
+}
+
+int
+sudo_ev_dispatch_v1(struct sudo_event_base *base)
+{
+ return sudo_ev_loop_v1(base, 0);
+}
+
+/*
+ * Run main event loop.
+ * Returns 0 on success, 1 if no events registered and -1 on error
+ */
+int
+sudo_ev_loop_v1(struct sudo_event_base *base, unsigned int flags)
+{
+ struct timespec now;
+ struct sudo_event *ev;
+ int nready, rc = 0;
+ debug_decl(sudo_ev_loop, SUDO_DEBUG_EVENT);
+
+ /*
+ * If sudo_ev_loopexit() was called when events were not running
+ * the next invocation of sudo_ev_loop() only runs once.
+ * All other base flags are ignored unless we are running events.
+ * Note that SUDO_EVLOOP_ONCE and SUDO_EVBASE_LOOPONCE are equivalent.
+ */
+ base->flags |= (flags & SUDO_EVLOOP_ONCE);
+ base->flags &= (SUDO_EVBASE_LOOPEXIT|SUDO_EVBASE_LOOPONCE);
+
+ for (;;) {
+rescan:
+ /* Make sure we have some events. */
+ if (TAILQ_EMPTY(&base->events)) {
+ rc = 1;
+ break;
+ }
+
+ /* Call backend to scan for I/O events. */
+ TAILQ_INIT(&base->active);
+ nready = sudo_ev_scan_impl(base, flags);
+ switch (nready) {
+ case -1:
+ if (errno == ENOMEM || errno == EAGAIN)
+ continue;
+ if (errno == EINTR) {
+ /* Interrupted by signal, check for sigevents. */
+ if (base->signal_caught) {
+ signal_pipe_cb(base->signal_pipe[0], SUDO_EV_READ, base);
+ break;
+ }
+ continue;
+ }
+ rc = -1;
+ goto done;
+ case 0:
+ /* Timed out, activate timeout events. */
+ sudo_gettime_mono(&now);
+ while ((ev = TAILQ_FIRST(&base->timeouts)) != NULL) {
+ if (sudo_timespeccmp(&ev->timeout, &now, >))
+ break;
+ /* Remove from timeouts list. */
+ CLR(ev->flags, SUDO_EVQ_TIMEOUTS);
+ TAILQ_REMOVE(&base->timeouts, ev, timeouts_entries);
+ /* Make event active. */
+ ev->revents = SUDO_EV_TIMEOUT;
+ TAILQ_INSERT_TAIL(&base->active, ev, active_entries);
+ SET(ev->flags, SUDO_EVQ_ACTIVE);
+ }
+ if (ISSET(flags, SUDO_EVLOOP_NONBLOCK)) {
+ /* If nonblocking, return immediately if no active events. */
+ if (TAILQ_EMPTY(&base->active))
+ goto done;
+ }
+ break;
+ default:
+ /* I/O events active, sudo_ev_scan_impl() already added them. */
+ break;
+ }
+
+ /*
+ * Service each event in the active queue.
+ * We store the current event pointer in the base so that
+ * it can be cleared by sudo_ev_del(). This prevents a use
+ * after free if the callback frees its own event.
+ */
+ while ((ev = TAILQ_FIRST(&base->active)) != NULL) {
+ /* Pop first event off the active queue. */
+ sudo_ev_deactivate(base, ev);
+ /* Remove from base unless persistent. */
+ if (!ISSET(ev->events, SUDO_EV_PERSIST))
+ sudo_ev_del(base, ev);
+ ev->callback(ev->fd, ev->revents,
+ ev->closure == sudo_ev_self_cbarg() ? ev : ev->closure);
+ if (ISSET(base->flags, SUDO_EVBASE_LOOPBREAK)) {
+ /* Stop processing events immediately. */
+ SET(base->flags, SUDO_EVBASE_GOT_BREAK);
+ sudo_ev_deactivate_all(base);
+ goto done;
+ }
+ if (ISSET(base->flags, SUDO_EVBASE_LOOPCONT)) {
+ /* Rescan events and start polling again. */
+ CLR(base->flags, SUDO_EVBASE_LOOPCONT);
+ sudo_ev_deactivate_all(base);
+ goto rescan;
+ }
+ }
+ if (ISSET(base->flags, SUDO_EVBASE_LOOPONCE)) {
+ /* SUDO_EVBASE_LOOPEXIT is always set w/ SUDO_EVBASE_LOOPONCE */
+ if (ISSET(base->flags, SUDO_EVBASE_LOOPEXIT))
+ SET(base->flags, SUDO_EVBASE_GOT_EXIT);
+ sudo_ev_deactivate_all(base);
+ break;
+ }
+ }
+done:
+ base->flags &= SUDO_EVBASE_GOT_MASK;
+ debug_return_int(rc);
+}
+
+void
+sudo_ev_loopexit_v1(struct sudo_event_base *base)
+{
+ debug_decl(sudo_ev_loopexit, SUDO_DEBUG_EVENT);
+
+ if (base == NULL) {
+ if ((base = default_base) == NULL)
+ debug_return;
+ }
+
+ /* SUDO_EVBASE_LOOPBREAK trumps SUDO_EVBASE_LOOPEXIT */
+ if (!ISSET(base->flags, SUDO_EVBASE_LOOPBREAK)) {
+ /* SUDO_EVBASE_LOOPEXIT trumps SUDO_EVBASE_LOOPCONT */
+ CLR(base->flags, SUDO_EVBASE_LOOPCONT);
+ SET(base->flags, (SUDO_EVBASE_LOOPEXIT|SUDO_EVBASE_LOOPONCE));
+ }
+ debug_return;
+}
+
+void
+sudo_ev_loopbreak_v1(struct sudo_event_base *base)
+{
+ debug_decl(sudo_ev_loopbreak, SUDO_DEBUG_EVENT);
+
+ if (base == NULL) {
+ if ((base = default_base) == NULL)
+ debug_return;
+ }
+
+ /* SUDO_EVBASE_LOOPBREAK trumps SUDO_EVBASE_LOOP{CONT,EXIT,ONCE}. */
+ CLR(base->flags, (SUDO_EVBASE_LOOPCONT|SUDO_EVBASE_LOOPEXIT|SUDO_EVBASE_LOOPONCE));
+ SET(base->flags, SUDO_EVBASE_LOOPBREAK);
+ debug_return;
+}
+
+void
+sudo_ev_loopcontinue_v1(struct sudo_event_base *base)
+{
+ debug_decl(sudo_ev_loopcontinue, SUDO_DEBUG_EVENT);
+
+ if (base == NULL) {
+ if ((base = default_base) == NULL)
+ debug_return;
+ }
+
+ /* SUDO_EVBASE_LOOP{BREAK,EXIT} trumps SUDO_EVBASE_LOOPCONT */
+ if (!ISSET(base->flags, SUDO_EVBASE_LOOPONCE|SUDO_EVBASE_LOOPBREAK)) {
+ SET(base->flags, SUDO_EVBASE_LOOPCONT);
+ }
+ debug_return;
+}
+
+bool
+sudo_ev_got_exit_v1(struct sudo_event_base *base)
+{
+ debug_decl(sudo_ev_got_exit, SUDO_DEBUG_EVENT);
+
+ if (base == NULL) {
+ if ((base = default_base) == NULL)
+ debug_return_bool(false);
+ }
+ debug_return_bool(ISSET(base->flags, SUDO_EVBASE_GOT_EXIT));
+}
+
+bool
+sudo_ev_got_break_v1(struct sudo_event_base *base)
+{
+ debug_decl(sudo_ev_got_break, SUDO_DEBUG_EVENT);
+
+ if (base == NULL) {
+ if ((base = default_base) == NULL)
+ debug_return_bool(false);
+ }
+ debug_return_bool(ISSET(base->flags, SUDO_EVBASE_GOT_BREAK));
+}
+
+int
+sudo_ev_get_timeleft_v1(struct sudo_event *ev, struct timeval *tv)
+{
+ struct timespec ts;
+ int ret;
+
+ ret = sudo_ev_get_timeleft_v2(ev, &ts);
+ TIMESPEC_TO_TIMEVAL(tv, &ts);
+
+ return ret;
+}
+
+int
+sudo_ev_get_timeleft_v2(struct sudo_event *ev, struct timespec *ts)
+{
+ debug_decl(sudo_ev_get_timeleft, SUDO_DEBUG_EVENT);
+
+ sudo_timespecclear(ts);
+ if (sudo_ev_pending_v1(ev, SUDO_EV_TIMEOUT, ts) != SUDO_EV_TIMEOUT)
+ debug_return_int(-1);
+ debug_return_int(0);
+}
+
+int
+sudo_ev_pending_v2(struct sudo_event *ev, int events, struct timespec *ts)
+{
+ int ret;
+ debug_decl(sudo_ev_pending, SUDO_DEBUG_EVENT);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: event %p, flags 0x%x, events 0x%x",
+ __func__, ev, ev->flags, ev->events);
+
+ if (!ISSET(ev->flags, SUDO_EVQ_INSERTED))
+ debug_return_int(0);
+
+ ret = ev->events & events;
+ CLR(ret, SUDO_EV_TIMEOUT);
+ if (ISSET(ev->flags, SUDO_EVQ_TIMEOUTS) && ISSET(events, SUDO_EV_TIMEOUT)) {
+ ret |= SUDO_EV_TIMEOUT;
+ if (ts != NULL) {
+ struct timespec now;
+
+ sudo_gettime_mono(&now);
+ sudo_timespecsub(&ev->timeout, &now, ts);
+ if (ts->tv_sec < 0)
+ sudo_timespecclear(ts);
+ }
+ }
+
+ debug_return_int(ret);
+}
+
+int
+sudo_ev_pending_v1(struct sudo_event *ev, short events, struct timespec *ts)
+{
+ return sudo_ev_pending_v2(ev, events, ts);
+}
diff --git a/lib/util/event_poll.c b/lib/util/event_poll.c
new file mode 100644
index 0000000..245fe59
--- /dev/null
+++ b/lib/util/event_poll.c
@@ -0,0 +1,236 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/resource.h>
+
+#include <limits.h>
+#include <poll.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_fatal.h>
+#include <sudo_debug.h>
+#include <sudo_event.h>
+
+#if defined(OPEN_MAX) && OPEN_MAX > 256
+# define SUDO_OPEN_MAX OPEN_MAX
+#else
+# define SUDO_OPEN_MAX 256
+#endif
+
+int
+sudo_ev_base_alloc_impl(struct sudo_event_base *base)
+{
+ int i;
+ debug_decl(sudo_ev_base_alloc_impl, SUDO_DEBUG_EVENT);
+
+ base->pfd_high = -1;
+ base->pfd_max = 32;
+ base->pfds = reallocarray(NULL, (size_t)base->pfd_max, sizeof(struct pollfd));
+ if (base->pfds == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: unable to allocate %d pollfds", __func__, base->pfd_max);
+ base->pfd_max = 0;
+ debug_return_int(-1);
+ }
+ for (i = 0; i < base->pfd_max; i++) {
+ base->pfds[i].fd = -1;
+ }
+
+ debug_return_int(0);
+}
+
+void
+sudo_ev_base_free_impl(struct sudo_event_base *base)
+{
+ debug_decl(sudo_ev_base_free_impl, SUDO_DEBUG_EVENT);
+ free(base->pfds);
+ debug_return;
+}
+
+int
+sudo_ev_add_impl(struct sudo_event_base *base, struct sudo_event *ev)
+{
+ static int nofile_max = -1;
+ struct pollfd *pfd;
+ debug_decl(sudo_ev_add_impl, SUDO_DEBUG_EVENT);
+
+ if (nofile_max == -1) {
+ struct rlimit rlim;
+ if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
+ nofile_max = (int)rlim.rlim_cur;
+ } else {
+ nofile_max = SUDO_OPEN_MAX;
+ }
+ }
+
+ /* If out of space in pfds array, realloc. */
+ if (base->pfd_free == base->pfd_max) {
+ struct pollfd *pfds;
+ int i, new_max;
+
+ /* Don't allow pfd_max to go over RLIM_NOFILE */
+ new_max = base->pfd_max * 2;
+ if (new_max > nofile_max)
+ new_max = nofile_max;
+ if (base->pfd_free == new_max) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: out of fds (max %d)", __func__, nofile_max);
+ debug_return_int(-1);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "%s: pfd_max %d -> %d", __func__, base->pfd_max, new_max);
+ pfds = reallocarray(base->pfds, (size_t)new_max, sizeof(struct pollfd));
+ if (pfds == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: unable to allocate %d pollfds", __func__, new_max);
+ debug_return_int(-1);
+ }
+ base->pfds = pfds;
+ base->pfd_max = new_max;
+ for (i = base->pfd_free; i < base->pfd_max; i++) {
+ base->pfds[i].fd = -1;
+ }
+ }
+
+ /* Fill in pfd entry. */
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "%s: choosing free slot %d", __func__, base->pfd_free);
+ ev->pfd_idx = (short)base->pfd_free;
+ pfd = &base->pfds[ev->pfd_idx];
+ pfd->fd = ev->fd;
+ pfd->events = 0;
+ if (ISSET(ev->events, SUDO_EV_READ))
+ pfd->events |= POLLIN;
+ if (ISSET(ev->events, SUDO_EV_WRITE))
+ pfd->events |= POLLOUT;
+
+ /* Update pfd_high and pfd_free. */
+ if (ev->pfd_idx > base->pfd_high)
+ base->pfd_high = ev->pfd_idx;
+ for (;;) {
+ if (++base->pfd_free == base->pfd_max)
+ break;
+ if (base->pfds[base->pfd_free].fd == -1)
+ break;
+ }
+
+ debug_return_int(0);
+}
+
+int
+sudo_ev_del_impl(struct sudo_event_base *base, struct sudo_event *ev)
+{
+ debug_decl(sudo_ev_del_impl, SUDO_DEBUG_EVENT);
+
+ /* Mark pfd entry unused, add to free list and adjust high slot. */
+ base->pfds[ev->pfd_idx].fd = -1;
+ if (ev->pfd_idx < base->pfd_free) {
+ base->pfd_free = ev->pfd_idx;
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "%s: new free slot %d", __func__, base->pfd_free);
+ }
+ while (base->pfd_high >= 0 && base->pfds[base->pfd_high].fd == -1)
+ base->pfd_high--;
+
+ debug_return_int(0);
+}
+
+#ifdef HAVE_PPOLL
+static int
+sudo_ev_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timo)
+{
+ return ppoll(fds, nfds, timo, NULL);
+}
+#else
+static int
+sudo_ev_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timo)
+{
+ const int timeout =
+ timo ? (timo->tv_sec * 1000) + (timo->tv_nsec / 1000000) : -1;
+
+ return poll(fds, nfds, timeout);
+}
+#endif /* HAVE_PPOLL */
+
+int
+sudo_ev_scan_impl(struct sudo_event_base *base, unsigned int flags)
+{
+ struct timespec now, ts, *timeout;
+ struct sudo_event *ev;
+ int nready;
+ debug_decl(sudo_ev_scan_impl, SUDO_DEBUG_EVENT);
+
+ if ((ev = TAILQ_FIRST(&base->timeouts)) != NULL) {
+ sudo_gettime_mono(&now);
+ sudo_timespecsub(&ev->timeout, &now, &ts);
+ if (ts.tv_sec < 0)
+ sudo_timespecclear(&ts);
+ timeout = &ts;
+ } else {
+ if (ISSET(flags, SUDO_EVLOOP_NONBLOCK)) {
+ sudo_timespecclear(&ts);
+ timeout = &ts;
+ } else {
+ timeout = NULL;
+ }
+ }
+
+ nready = sudo_ev_poll(base->pfds, (nfds_t)base->pfd_high + 1, timeout);
+ switch (nready) {
+ case -1:
+ /* Error: EINTR (signal) or EINVAL (nfds > RLIMIT_NOFILE) */
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "sudo_ev_poll");
+ break;
+ case 0:
+ /* Front end will activate timeout events. */
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: timeout", __func__);
+ break;
+ default:
+ /* Activate each I/O event that fired. */
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: %d fds ready", __func__,
+ nready);
+ TAILQ_FOREACH(ev, &base->events, entries) {
+ if (ev->pfd_idx != -1 && base->pfds[ev->pfd_idx].revents) {
+ int what = 0;
+ if (base->pfds[ev->pfd_idx].revents & (POLLIN|POLLHUP|POLLNVAL|POLLERR))
+ what |= (ev->events & SUDO_EV_READ);
+ if (base->pfds[ev->pfd_idx].revents & (POLLOUT|POLLHUP|POLLNVAL|POLLERR))
+ what |= (ev->events & SUDO_EV_WRITE);
+ /* Make event active. */
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s: polled fd %d, events %d, activating %p",
+ __func__, ev->fd, what, ev);
+ ev->revents = (short)what;
+ sudo_ev_activate(base, ev);
+ }
+ }
+ break;
+ }
+ debug_return_int(nready);
+}
diff --git a/lib/util/event_select.c b/lib/util/event_select.c
new file mode 100644
index 0000000..74e6e2f
--- /dev/null
+++ b/lib/util/event_select.c
@@ -0,0 +1,250 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/param.h> /* for howmany() on Linux */
+#include <sys/time.h>
+#ifdef HAVE_SYS_SYSMACROS_H
+# include <sys/sysmacros.h> /* for howmany() on Solaris */
+#endif
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif /* HAVE_SYS_SELECT_H */
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_fatal.h>
+#include <sudo_debug.h>
+#include <sudo_event.h>
+
+int
+sudo_ev_base_alloc_impl(struct sudo_event_base *base)
+{
+ debug_decl(sudo_ev_base_alloc_impl, SUDO_DEBUG_EVENT);
+
+ base->maxfd = NFDBITS - 1;
+ base->readfds_in = calloc(1, sizeof(fd_mask));
+ base->writefds_in = calloc(1, sizeof(fd_mask));
+ base->readfds_out = calloc(1, sizeof(fd_mask));
+ base->writefds_out = calloc(1, sizeof(fd_mask));
+
+ if (base->readfds_in == NULL || base->writefds_in == NULL ||
+ base->readfds_out == NULL || base->writefds_out == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: unable to calloc(1, %zu)", __func__, sizeof(fd_mask));
+ sudo_ev_base_free_impl(base);
+ debug_return_int(-1);
+ }
+ debug_return_int(0);
+}
+
+void
+sudo_ev_base_free_impl(struct sudo_event_base *base)
+{
+ debug_decl(sudo_ev_base_free_impl, SUDO_DEBUG_EVENT);
+ free(base->readfds_in);
+ free(base->writefds_in);
+ free(base->readfds_out);
+ free(base->writefds_out);
+ debug_return;
+}
+
+int
+sudo_ev_add_impl(struct sudo_event_base *base, struct sudo_event *ev)
+{
+ debug_decl(sudo_ev_add_impl, SUDO_DEBUG_EVENT);
+
+ /* If out of space in fd sets, realloc. */
+ if (ev->fd > base->maxfd) {
+ const int o = (base->maxfd + 1) / NFDBITS;
+ const int n = howmany(ev->fd + 1, NFDBITS);
+ const size_t used_bytes = (size_t)o * sizeof(fd_mask);
+ const size_t new_bytes = (size_t)(n - o) * sizeof(fd_mask);
+ fd_set *rfds_in, *wfds_in, *rfds_out, *wfds_out;
+
+ rfds_in = reallocarray(base->readfds_in, (size_t)n, sizeof(fd_mask));
+ wfds_in = reallocarray(base->writefds_in, (size_t)n, sizeof(fd_mask));
+ rfds_out = reallocarray(base->readfds_out, (size_t)n, sizeof(fd_mask));
+ wfds_out = reallocarray(base->writefds_out, (size_t)n, sizeof(fd_mask));
+ if (rfds_in == NULL || wfds_in == NULL ||
+ rfds_out == NULL || wfds_out == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: unable to reallocarray(%d, %zu)",
+ __func__, n, sizeof(fd_mask));
+ free(rfds_in);
+ free(wfds_in);
+ free(rfds_out);
+ free(wfds_out);
+ debug_return_int(-1);
+ }
+
+ /* Clear newly allocated space. */
+ memset((char *)rfds_in + used_bytes, 0, new_bytes);
+ memset((char *)wfds_in + used_bytes, 0, new_bytes);
+ memset((char *)rfds_out + used_bytes, 0, new_bytes);
+ memset((char *)wfds_out + used_bytes, 0, new_bytes);
+
+ /* Update base. */
+ base->readfds_in = rfds_in;
+ base->writefds_in = wfds_in;
+ base->readfds_out = rfds_out;
+ base->writefds_out = wfds_out;
+ base->maxfd = (n * NFDBITS) - 1;
+ }
+
+ /* Set events and adjust high fd as needed. */
+ if (ISSET(ev->events, SUDO_EV_READ)) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: added fd %d to readfs",
+ __func__, ev->fd);
+ FD_SET(ev->fd, (fd_set *)base->readfds_in);
+ }
+ if (ISSET(ev->events, SUDO_EV_WRITE)) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: added fd %d to writefds",
+ __func__, ev->fd);
+ FD_SET(ev->fd, (fd_set *)base->writefds_in);
+ }
+ if (ev->fd > base->highfd)
+ base->highfd = ev->fd;
+
+ debug_return_int(0);
+}
+
+int
+sudo_ev_del_impl(struct sudo_event_base *base, struct sudo_event *ev)
+{
+ debug_decl(sudo_ev_del_impl, SUDO_DEBUG_EVENT);
+
+ /* Remove from readfds and writefds and adjust high fd. */
+ if (ISSET(ev->events, SUDO_EV_READ)) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: removed fd %d from readfds",
+ __func__, ev->fd);
+ FD_CLR(ev->fd, (fd_set *)base->readfds_in);
+ }
+ if (ISSET(ev->events, SUDO_EV_WRITE)) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: removed fd %d from writefds",
+ __func__, ev->fd);
+ FD_CLR(ev->fd, (fd_set *)base->writefds_in);
+ }
+ if (base->highfd == ev->fd) {
+ for (;;) {
+ if (FD_ISSET(base->highfd, (fd_set *)base->readfds_in) ||
+ FD_ISSET(base->highfd, (fd_set *)base->writefds_in))
+ break;
+ if (--base->highfd < 0)
+ break;
+ }
+ }
+
+ debug_return_int(0);
+}
+
+#ifdef HAVE_PSELECT
+static int
+sudo_ev_select(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, const struct timespec *timeout)
+{
+ return pselect(nfds, readfds, writefds, exceptfds, timeout, NULL);
+}
+#else
+static int
+sudo_ev_select(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, const struct timespec *timeout)
+{
+ struct timeval tvbuf, *tv = NULL;
+
+ if (timeout != NULL) {
+ TIMESPEC_TO_TIMEVAL(&tvbuf, timeout);
+ tv = &tvbuf;
+ }
+ return select(nfds, readfds, writefds, exceptfds, tv);
+}
+#endif /* HAVE_PSELECT */
+
+int
+sudo_ev_scan_impl(struct sudo_event_base *base, unsigned int flags)
+{
+ struct timespec now, ts, *timeout;
+ struct sudo_event *ev;
+ size_t setsize;
+ int nready;
+ debug_decl(sudo_ev_loop, SUDO_DEBUG_EVENT);
+
+ if ((ev = TAILQ_FIRST(&base->timeouts)) != NULL) {
+ sudo_gettime_mono(&now);
+ sudo_timespecsub(&ev->timeout, &now, &ts);
+ if (ts.tv_sec < 0)
+ sudo_timespecclear(&ts);
+ timeout = &ts;
+ } else {
+ if (ISSET(flags, SUDO_EVLOOP_NONBLOCK)) {
+ sudo_timespecclear(&ts);
+ timeout = &ts;
+ } else {
+ timeout = NULL;
+ }
+ }
+
+ /* select() overwrites readfds/writefds so make a copy. */
+ setsize = (size_t)howmany(base->highfd + 1, NFDBITS) * sizeof(fd_mask);
+ memcpy(base->readfds_out, base->readfds_in, setsize);
+ memcpy(base->writefds_out, base->writefds_in, setsize);
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: select high fd %d",
+ __func__, base->highfd);
+ nready = sudo_ev_select(base->highfd + 1, base->readfds_out,
+ base->writefds_out, NULL, timeout);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: %d fds ready", __func__, nready);
+ switch (nready) {
+ case -1:
+ /* Error or interrupted by signal. */
+ break;
+ case 0:
+ /* Front end will activate timeout events. */
+ break;
+ default:
+ /* Activate each I/O event that fired. */
+ TAILQ_FOREACH(ev, &base->events, entries) {
+ if (ev->fd >= 0) {
+ short what = 0;
+ if (FD_ISSET(ev->fd, (fd_set *)base->readfds_out))
+ what |= (ev->events & SUDO_EV_READ);
+ if (FD_ISSET(ev->fd, (fd_set *)base->writefds_out))
+ what |= (ev->events & SUDO_EV_WRITE);
+ if (what != 0) {
+ /* Make event active. */
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s: selected fd %d, events %hd, activating %p",
+ __func__, ev->fd, what, ev);
+ ev->revents = what;
+ sudo_ev_activate(base, ev);
+ }
+ }
+ }
+ break;
+ }
+ debug_return_int(nready);
+}
diff --git a/lib/util/explicit_bzero.c b/lib/util/explicit_bzero.c
new file mode 100644
index 0000000..3d0ee1f
--- /dev/null
+++ b/lib/util/explicit_bzero.c
@@ -0,0 +1,77 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s() */
+
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+
+#include <sudo_compat.h>
+
+#ifndef HAVE_EXPLICIT_BZERO
+
+# if defined(HAVE_EXPLICIT_MEMSET)
+void
+sudo_explicit_bzero(void *s, size_t n)
+{
+ explicit_memset(s, 0, n);
+}
+# elif defined(HAVE_MEMSET_EXPLICIT)
+void
+sudo_explicit_bzero(void *s, size_t n)
+{
+ memset_explicit(s, 0, n);
+}
+# elif defined(HAVE_MEMSET_S)
+void
+sudo_explicit_bzero(void *s, size_t n)
+{
+ (void)memset_s(s, n, 0, n);
+}
+# elif defined(HAVE_BZERO)
+/* Jumping through a volatile function pointer should not be optimized away. */
+void (* volatile sudo_explicit_bzero_impl)(void *, size_t) =
+ (void (*)(void *, size_t))bzero;
+
+void
+sudo_explicit_bzero(void *s, size_t n)
+{
+ sudo_explicit_bzero_impl(s, n);
+}
+# else
+void
+sudo_explicit_bzero(void *v, size_t n)
+{
+ volatile unsigned char *s = v;
+
+ /* Updating through a volatile pointer should not be optimized away. */
+ while (n--)
+ *s++ = 0;
+}
+# endif /* HAVE_BZERO */
+
+#endif /* HAVE_EXPLICIT_BZERO */
diff --git a/lib/util/fatal.c b/lib/util/fatal.c
new file mode 100644
index 0000000..bdee6a1
--- /dev/null
+++ b/lib/util/fatal.c
@@ -0,0 +1,345 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2004-2005, 2010-2015, 2017-2018
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <unistd.h>
+#ifndef HAVE_GETADDRINFO
+# include <compat/getaddrinfo.h>
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_queue.h>
+#include <sudo_util.h>
+#include <sudo_plugin.h>
+
+struct sudo_fatal_callback {
+ SLIST_ENTRY(sudo_fatal_callback) entries;
+ void (*func)(void);
+};
+SLIST_HEAD(sudo_fatal_callback_list, sudo_fatal_callback);
+
+static struct sudo_fatal_callback_list callbacks = SLIST_HEAD_INITIALIZER(&callbacks);
+static sudo_conv_t sudo_warn_conversation;
+static sudo_warn_setlocale_t sudo_warn_setlocale;
+static sudo_warn_setlocale_t sudo_warn_setlocale_prev;
+
+static void warning(const char * restrict errstr, const char * restrict fmt, va_list ap);
+
+static void
+do_cleanup(void)
+{
+ struct sudo_fatal_callback *cb;
+
+ /* Run callbacks, removing them from the list as we go. */
+ while ((cb = SLIST_FIRST(&callbacks)) != NULL) {
+ SLIST_REMOVE_HEAD(&callbacks, entries);
+ cb->func();
+ free(cb);
+ }
+}
+
+sudo_noreturn void
+sudo_fatal_nodebug_v1(const char * restrict fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ warning(strerror(errno), fmt, ap);
+ va_end(ap);
+ do_cleanup();
+ exit(EXIT_FAILURE);
+}
+
+sudo_noreturn void
+sudo_fatalx_nodebug_v1(const char * restrict fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ warning(NULL, fmt, ap);
+ va_end(ap);
+ do_cleanup();
+ exit(EXIT_FAILURE);
+}
+
+sudo_noreturn void
+sudo_vfatal_nodebug_v1(const char * restrict fmt, va_list ap)
+{
+ warning(strerror(errno), fmt, ap);
+ do_cleanup();
+ exit(EXIT_FAILURE);
+}
+
+sudo_noreturn void
+sudo_vfatalx_nodebug_v1(const char * restrict fmt, va_list ap)
+{
+ warning(NULL, fmt, ap);
+ do_cleanup();
+ exit(EXIT_FAILURE);
+}
+
+void
+sudo_warn_nodebug_v1(const char * restrict fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ warning(strerror(errno), fmt, ap);
+ va_end(ap);
+}
+
+void
+sudo_warnx_nodebug_v1(const char * restrict fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ warning(NULL, fmt, ap);
+ va_end(ap);
+}
+
+void
+sudo_vwarn_nodebug_v1(const char * restrict fmt, va_list ap)
+{
+ warning(strerror(errno), fmt, ap);
+}
+
+void
+sudo_vwarnx_nodebug_v1(const char * restrict fmt, va_list ap)
+{
+ warning(NULL, fmt, ap);
+}
+
+sudo_noreturn void
+sudo_gai_fatal_nodebug_v1(int errnum, const char * restrict fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ warning(gai_strerror(errnum), fmt, ap);
+ va_end(ap);
+ do_cleanup();
+ exit(EXIT_FAILURE);
+}
+
+sudo_noreturn void
+sudo_gai_vfatal_nodebug_v1(int errnum, const char * restrict fmt, va_list ap)
+{
+ warning(gai_strerror(errnum), fmt, ap);
+ do_cleanup();
+ exit(EXIT_FAILURE);
+}
+
+void
+sudo_gai_warn_nodebug_v1(int errnum, const char * restrict fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ warning(gai_strerror(errnum), fmt, ap);
+ va_end(ap);
+}
+
+void
+sudo_gai_vwarn_nodebug_v1(int errnum, const char * restrict fmt, va_list ap)
+{
+ warning(gai_strerror(errnum), fmt, ap);
+}
+
+static void
+warning(const char * restrict errstr, const char * restrict fmt, va_list ap)
+{
+ int cookie;
+ const int saved_errno = errno;
+
+ /* Set user locale if setter was specified. */
+ if (sudo_warn_setlocale != NULL)
+ sudo_warn_setlocale(false, &cookie);
+
+ if (sudo_warn_conversation != NULL) {
+ struct sudo_conv_message msgs[6];
+ char static_buf[1024], *buf = static_buf;
+ int nmsgs = 0;
+
+ /* Use conversation function. */
+ msgs[nmsgs].msg_type = SUDO_CONV_ERROR_MSG;
+ msgs[nmsgs++].msg = getprogname();
+ if (fmt != NULL) {
+ va_list ap2;
+ int buflen;
+
+ /* Use static buffer if possible, else dynamic. */
+ va_copy(ap2, ap);
+ buflen = vsnprintf(static_buf, sizeof(static_buf), fmt, ap2);
+ va_end(ap2);
+ if (buflen >= ssizeof(static_buf)) {
+ /* Not enough room in static buf, allocate dynamically. */
+ if (vasprintf(&buf, fmt, ap) == -1)
+ buf = static_buf;
+ }
+ if (buflen > 0) {
+ msgs[nmsgs].msg_type = SUDO_CONV_ERROR_MSG;
+ msgs[nmsgs++].msg = ": ";
+ msgs[nmsgs].msg_type = SUDO_CONV_ERROR_MSG;
+ msgs[nmsgs++].msg = buf;
+ }
+ }
+ if (errstr != NULL) {
+ msgs[nmsgs].msg_type = SUDO_CONV_ERROR_MSG;
+ msgs[nmsgs++].msg = ": ";
+ msgs[nmsgs].msg_type = SUDO_CONV_ERROR_MSG;
+ msgs[nmsgs++].msg = errstr;
+ }
+ msgs[nmsgs].msg_type = SUDO_CONV_ERROR_MSG;
+ msgs[nmsgs++].msg = "\n";
+ sudo_warn_conversation(nmsgs, msgs, NULL, NULL);
+ if (buf != static_buf)
+ free(buf);
+ } else {
+ /* Write to the standard error. */
+ fputs(getprogname(), stderr);
+ if (fmt != NULL) {
+ fputs(": ", stderr);
+ vfprintf(stderr, fmt, ap);
+ }
+ if (errstr != NULL) {
+ fputs(": ", stderr);
+ fputs(errstr, stderr);
+ }
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ if (sudo_term_is_raw(fileno(stderr)))
+ putc('\r', stderr);
+#endif
+ putc('\n', stderr);
+ }
+
+ /* Restore old locale as needed. */
+ if (sudo_warn_setlocale != NULL)
+ sudo_warn_setlocale(true, &cookie);
+
+ /* Do not clobber errno. */
+ errno = saved_errno;
+}
+
+/*
+ * Register a callback to be run when sudo_fatal()/sudo_fatalx() is called.
+ */
+int
+sudo_fatal_callback_register_v1(sudo_fatal_callback_t func)
+{
+ struct sudo_fatal_callback *cb;
+
+ /* Do not register the same callback twice. */
+ SLIST_FOREACH(cb, &callbacks, entries) {
+ if (func == cb->func)
+ return -1; /* dupe! */
+ }
+
+ /* Allocate and insert new callback. */
+ cb = malloc(sizeof(*cb));
+ if (cb == NULL)
+ return -1;
+ cb->func = func;
+ SLIST_INSERT_HEAD(&callbacks, cb, entries);
+
+ return 0;
+}
+
+/*
+ * Deregister a sudo_fatal()/sudo_fatalx() callback.
+ */
+int
+sudo_fatal_callback_deregister_v1(sudo_fatal_callback_t func)
+{
+ struct sudo_fatal_callback *cb, *prev = NULL;
+
+ /* Search for callback and remove if found, dupes are not allowed. */
+ SLIST_FOREACH(cb, &callbacks, entries) {
+ if (cb->func == func) {
+ if (prev == NULL)
+ SLIST_REMOVE_HEAD(&callbacks, entries);
+ else
+ SLIST_REMOVE_AFTER(prev, entries);
+ free(cb);
+ return 0;
+ }
+ prev = cb;
+ }
+
+ return -1;
+}
+
+/*
+ * Set the conversation function to use for output insteaf of the
+ * standard error. If conv is NULL, switch back to standard error.
+ */
+void
+sudo_warn_set_conversation_v1(sudo_conv_t conv)
+{
+ sudo_warn_conversation = conv;
+}
+
+/*
+ * Set the locale function so the plugin can use a non-default
+ * locale for user warnings.
+ */
+void
+sudo_warn_set_locale_func_v1(sudo_warn_setlocale_t func)
+{
+ sudo_warn_setlocale_prev = sudo_warn_setlocale;
+ sudo_warn_setlocale = func;
+}
+
+#ifdef HAVE_LIBINTL_H
+char *
+sudo_warn_gettext_v1(const char *domainname, const char *msgid)
+{
+ int cookie;
+ char *msg;
+
+ /* Set user locale if setter was specified. */
+ if (sudo_warn_setlocale != NULL)
+ sudo_warn_setlocale(false, &cookie);
+
+ msg = dgettext(domainname, msgid);
+
+ /* Restore old locale as needed. */
+ if (sudo_warn_setlocale != NULL)
+ sudo_warn_setlocale(true, &cookie);
+
+ return msg;
+}
+#endif /* HAVE_LIBINTL_H */
diff --git a/lib/util/fchmodat.c b/lib/util/fchmodat.c
new file mode 100644
index 0000000..39d294e
--- /dev/null
+++ b/lib/util/fchmodat.c
@@ -0,0 +1,69 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+
+#ifndef HAVE_FCHMODAT
+int
+sudo_fchmodat(int dfd, const char *path, mode_t mode, int flag)
+{
+ int odfd, ret = -1;
+
+ if (ISSET(flag, AT_SYMLINK_NOFOLLOW)) {
+ errno = ENOTSUP;
+ return -1;
+ }
+
+ if (dfd == (int)AT_FDCWD)
+ return chmod(path, mode);
+
+ /* Save cwd */
+ if ((odfd = open(".", O_RDONLY)) == -1)
+ goto done;
+
+ if (fchdir(dfd) == -1)
+ goto done;
+
+ ret = chmod(path, mode);
+
+ /* Restore cwd */
+ if (fchdir(odfd) == -1) {
+ /* Should not happen */
+ ret = -1;
+ }
+
+done:
+ if (odfd != -1)
+ close(odfd);
+
+ return ret;
+}
+#endif /* HAVE_FCHMODAT */
diff --git a/lib/util/fchownat.c b/lib/util/fchownat.c
new file mode 100644
index 0000000..035f239
--- /dev/null
+++ b/lib/util/fchownat.c
@@ -0,0 +1,67 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+
+#ifndef HAVE_FCHOWNAT
+int
+sudo_fchownat(int dfd, const char *path, uid_t uid, gid_t gid, int flags)
+{
+ int odfd, ret;
+
+ if (dfd == AT_FDCWD) {
+ if (flags & AT_SYMLINK_NOFOLLOW)
+ return lchown(path, uid, gid);
+ else
+ return chown(path, uid, gid);
+ }
+
+ /* Save cwd */
+ if ((odfd = open(".", O_RDONLY)) == -1)
+ return -1;
+
+ if (fchdir(dfd) == -1) {
+ close(odfd);
+ return -1;
+ }
+
+ if (flags & AT_SYMLINK_NOFOLLOW)
+ ret = lchown(path, uid, gid);
+ else
+ ret = chown(path, uid, gid);
+
+ /* Restore cwd */
+ if (fchdir(odfd) == -1) {
+ /* Should not happen */
+ ret = -1;
+ }
+ close(odfd);
+
+ return ret;
+}
+#endif /* HAVE_FCHOWNAT */
diff --git a/lib/util/fnmatch.c b/lib/util/fnmatch.c
new file mode 100644
index 0000000..729d546
--- /dev/null
+++ b/lib/util/fnmatch.c
@@ -0,0 +1,499 @@
+/* $OpenBSD: fnmatch.c,v 1.15 2011/02/10 21:31:59 stsp Exp $ */
+
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2011, VMware, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the VMware, Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2008, 2016 Todd C. Miller <millert@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+/* Authored by William A. Rowe Jr. <wrowe; apache.org, vmware.com>, April 2011
+ *
+ * Derived from The Open Group Base Specifications Issue 7, IEEE Std 1003.1-2008
+ * as described in;
+ * http://pubs.opengroup.org/onlinepubs/9699919799/functions/fnmatch.html
+ *
+ * Filename pattern matches defined in section 2.13, "Pattern Matching Notation"
+ * from chapter 2. "Shell Command Language"
+ * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13
+ * where; 1. A bracket expression starting with an unquoted <circumflex> '^'
+ * character CONTINUES to specify a non-matching list; 2. an explicit <period> '.'
+ * in a bracket expression matching list, e.g. "[.abc]" does NOT match a leading
+ * <period> in a filename; 3. a <left-square-bracket> '[' which does not introduce
+ * a valid bracket expression is treated as an ordinary character; 4. a differing
+ * number of consecutive slashes within pattern and string will NOT match;
+ * 5. a trailing '\' in FNM_ESCAPE mode is treated as an ordinary '\' character.
+ *
+ * Bracket expansion defined in section 9.3.5, "RE Bracket Expression",
+ * from chapter 9, "Regular Expressions"
+ * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_05
+ * with no support for collating symbols, equivalence class expressions or
+ * character class expressions. A partial range expression with a leading
+ * hyphen following a valid range expression will match only the ordinary
+ * <hyphen> and the ending character (e.g. "[a-m-z]" will match characters
+ * 'a' through 'm', a <hyphen> '-', or a 'z').
+ *
+ * Supports BSD extensions FNM_LEADING_DIR to match pattern to the end of one
+ * path segment of string, and FNM_CASEFOLD to ignore alpha case.
+ *
+ * NOTE: Only POSIX/C single byte locales are correctly supported at this time.
+ * Notably, non-POSIX locales with FNM_CASEFOLD produce undefined results,
+ * particularly in ranges of mixed case (e.g. "[A-z]") or spanning alpha and
+ * nonalpha characters within a range.
+ *
+ * XXX comments below indicate porting required for multi-byte character sets
+ * and non-POSIX locale collation orders; requires mbr* APIs to track shift
+ * state of pattern and string (rewinding pattern and string repeatedly).
+ *
+ * Certain parts of the code assume 0x00-0x3F are unique with any MBCS (e.g.
+ * UTF-8, SHIFT-JIS, etc). Any implementation allowing '\' as an alternate
+ * path delimiter must be aware that 0x5C is NOT unique within SHIFT-JIS.
+ */
+
+#include <config.h>
+
+#ifndef HAVE_FNMATCH
+
+#include <ctype.h>
+#include <string.h>
+
+#include <sudo_compat.h>
+#include <compat/charclass.h>
+#include <compat/fnmatch.h>
+
+#define RANGE_MATCH 1
+#define RANGE_NOMATCH 0
+#define RANGE_ERROR (-1)
+
+static int
+classmatch(const char *pattern, char test, int foldcase, const char **ep)
+{
+ const char * const mismatch = pattern;
+ const char *colon;
+ struct cclass *cc;
+ int result = RANGE_NOMATCH;
+ size_t len;
+
+ if (pattern[0] != '[' || pattern[1] != ':') {
+ *ep = mismatch;
+ return RANGE_ERROR;
+ }
+ pattern += 2;
+
+ if ((colon = strchr(pattern, ':')) == NULL || colon[1] != ']') {
+ *ep = mismatch;
+ return RANGE_ERROR;
+ }
+ *ep = colon + 2;
+ len = (size_t)(colon - pattern);
+
+ if (foldcase && strncmp(pattern, "upper:]", 7) == 0)
+ pattern = "lower:]";
+ for (cc = cclasses; cc->name != NULL; cc++) {
+ if (!strncmp(pattern, cc->name, len) && cc->name[len] == '\0') {
+ if (cc->isctype((unsigned char)test))
+ result = RANGE_MATCH;
+ break;
+ }
+ }
+ if (cc->name == NULL) {
+ /* invalid character class, treat as normal text */
+ *ep = mismatch;
+ result = RANGE_ERROR;
+ }
+ return result;
+}
+
+/* Most MBCS/collation/case issues handled here. Wildcard '*' is not handled.
+ * EOS '\0' and the FNM_PATHNAME '/' delimiters are not advanced over,
+ * however the "\/" sequence is advanced to '/'.
+ *
+ * Both pattern and string are **char to support pointer increment of arbitrary
+ * multibyte characters for the given locale, in a later iteration of this code
+ */
+static int fnmatch_ch(const char **pattern, const char **string, int flags)
+{
+ const char * const mismatch = *pattern;
+ const int nocase = !!(flags & FNM_CASEFOLD);
+ const int escape = !(flags & FNM_NOESCAPE);
+ const int slash = !!(flags & FNM_PATHNAME);
+ int result = FNM_NOMATCH;
+ const char *startch;
+ int negate;
+
+ if (**pattern == '[')
+ {
+ ++*pattern;
+
+ /* Handle negation, either leading ! or ^ operators (never both) */
+ negate = ((**pattern == '!') || (**pattern == '^'));
+ if (negate)
+ ++*pattern;
+
+ /* ']' is an ordinary character at the start of the range pattern */
+ if (**pattern == ']')
+ goto leadingclosebrace;
+
+ while (**pattern)
+ {
+ if (**pattern == ']') {
+ ++*pattern;
+ /* XXX: Fix for MBCS character width */
+ ++*string;
+ return (result ^ negate);
+ }
+
+ if (escape && (**pattern == '\\')) {
+ ++*pattern;
+
+ /* Patterns must be terminated with ']', not EOS */
+ if (!**pattern)
+ break;
+ }
+
+ /* Patterns must be terminated with ']' not '/' */
+ if (slash && (**pattern == '/'))
+ break;
+
+ /* Match character classes. */
+ switch (classmatch(*pattern, **string, nocase, pattern)) {
+ case RANGE_MATCH:
+ result = 0;
+ continue;
+ case RANGE_NOMATCH:
+ /* Valid character class but no match. */
+ continue;
+ default:
+ /* Not a valid character class. */
+ break;
+ }
+ if (!**pattern)
+ break;
+
+leadingclosebrace:
+ /* Look at only well-formed range patterns;
+ * "x-]" is not allowed unless escaped ("x-\]")
+ * XXX: Fix for locale/MBCS character width
+ */
+ if (((*pattern)[1] == '-') && ((*pattern)[2] != ']'))
+ {
+ startch = *pattern;
+ *pattern += (escape && ((*pattern)[2] == '\\')) ? 3 : 2;
+
+ /* NOT a properly balanced [expr] pattern, EOS terminated
+ * or ranges containing a slash in FNM_PATHNAME mode pattern
+ * fall out to to the rewind and test '[' literal code path
+ */
+ if (!**pattern || (slash && (**pattern == '/')))
+ break;
+
+ /* XXX: handle locale/MBCS comparison, advance by MBCS char width */
+ if ((**string >= *startch) && (**string <= **pattern))
+ result = 0;
+ else if (nocase && (isupper((unsigned char)**string) ||
+ isupper((unsigned char)*startch) ||
+ isupper((unsigned char)**pattern))
+ && (tolower((unsigned char)**string) >= tolower((unsigned char)*startch))
+ && (tolower((unsigned char)**string) <= tolower((unsigned char)**pattern)))
+ result = 0;
+
+ ++*pattern;
+ continue;
+ }
+
+ /* XXX: handle locale/MBCS comparison, advance by MBCS char width */
+ if ((**string == **pattern))
+ result = 0;
+ else if (nocase && (isupper((unsigned char)**string) ||
+ isupper((unsigned char)**pattern))
+ && (tolower((unsigned char)**string) == tolower((unsigned char)**pattern)))
+ result = 0;
+
+ ++*pattern;
+ }
+
+ /* NOT a properly balanced [expr] pattern; Rewind
+ * and reset result to test '[' literal
+ */
+ *pattern = mismatch;
+ result = FNM_NOMATCH;
+ }
+ else if (**pattern == '?') {
+ /* Optimize '?' match before unescaping **pattern */
+ if (!**string || (slash && (**string == '/')))
+ return FNM_NOMATCH;
+ result = 0;
+ goto fnmatch_ch_success;
+ }
+ else if (escape && (**pattern == '\\') && (*pattern)[1]) {
+ ++*pattern;
+ }
+
+ /* XXX: handle locale/MBCS comparison, advance by the MBCS char width */
+ if (**string == **pattern)
+ result = 0;
+ else if (nocase && (isupper((unsigned char)**string) || isupper((unsigned char)**pattern))
+ && (tolower((unsigned char)**string) == tolower((unsigned char)**pattern)))
+ result = 0;
+
+ /* Refuse to advance over trailing slash or nulls
+ */
+ if (!**string || !**pattern || (slash && ((**string == '/') || (**pattern == '/'))))
+ return result;
+
+fnmatch_ch_success:
+ ++*pattern;
+ ++*string;
+ return result;
+}
+
+int sudo_fnmatch(const char *pattern, const char *string, int flags)
+{
+ static const char dummystring[2] = {' ', 0};
+ const int escape = !(flags & FNM_NOESCAPE);
+ const int slash = !!(flags & FNM_PATHNAME);
+ const int leading_dir = !!(flags & FNM_LEADING_DIR);
+ const char *strendseg;
+ const char *dummyptr;
+ const char *matchptr;
+ int wild;
+ /* For '*' wild processing only; suppress 'used before initialization'
+ * warnings with dummy initialization values;
+ */
+ const char *strstartseg = NULL;
+ const char *mismatch = NULL;
+ int matchlen = 0;
+
+ if (*pattern == '*')
+ goto firstsegment;
+
+ while (*pattern && *string)
+ {
+ /* Pre-decode "\/" which has no special significance, and
+ * match balanced slashes, starting a new segment pattern
+ */
+ if (slash && escape && (*pattern == '\\') && (pattern[1] == '/'))
+ ++pattern;
+ if (slash && (*pattern == '/') && (*string == '/')) {
+ ++pattern;
+ ++string;
+ }
+
+firstsegment:
+ /* At the beginning of each segment, validate leading period behavior.
+ */
+ if ((flags & FNM_PERIOD) && (*string == '.'))
+ {
+ if (*pattern == '.')
+ ++pattern;
+ else if (escape && (*pattern == '\\') && (pattern[1] == '.'))
+ pattern += 2;
+ else
+ return FNM_NOMATCH;
+ ++string;
+ }
+
+ /* Determine the end of string segment
+ *
+ * Presumes '/' character is unique, not composite in any MBCS encoding
+ */
+ if (slash) {
+ strendseg = strchr(string, '/');
+ if (!strendseg)
+ strendseg = strchr(string, '\0');
+ }
+ else {
+ strendseg = strchr(string, '\0');
+ }
+
+ /* Allow pattern '*' to be consumed even with no remaining string to match
+ */
+ while (*pattern)
+ {
+ if ((string > strendseg)
+ || ((string == strendseg) && (*pattern != '*')))
+ break;
+
+ if (slash && ((*pattern == '/')
+ || (escape && (*pattern == '\\')
+ && (pattern[1] == '/'))))
+ break;
+
+ /* Reduce groups of '*' and '?' to n '?' matches
+ * followed by one '*' test for simplicity
+ */
+ for (wild = 0; ((*pattern == '*') || (*pattern == '?')); ++pattern)
+ {
+ if (*pattern == '*') {
+ wild = 1;
+ }
+ else if (string < strendseg) { /* && (*pattern == '?') */
+ /* XXX: Advance 1 char for MBCS locale */
+ ++string;
+ }
+ else { /* (string >= strendseg) && (*pattern == '?') */
+ return FNM_NOMATCH;
+ }
+ }
+
+ if (wild)
+ {
+ strstartseg = string;
+ mismatch = pattern;
+
+ /* Count fixed (non '*') char matches remaining in pattern
+ * excluding '/' (or "\/") and '*'
+ */
+ for (matchptr = pattern, matchlen = 0; 1; ++matchlen)
+ {
+ if ((*matchptr == '\0')
+ || (slash && ((*matchptr == '/')
+ || (escape && (*matchptr == '\\')
+ && (matchptr[1] == '/')))))
+ {
+ /* Compare precisely this many trailing string chars,
+ * the resulting match needs no wildcard loop
+ */
+ /* XXX: Adjust for MBCS */
+ if (string + matchlen > strendseg)
+ return FNM_NOMATCH;
+
+ string = strendseg - matchlen;
+ wild = 0;
+ break;
+ }
+
+ if (*matchptr == '*')
+ {
+ /* Ensure at least this many trailing string chars remain
+ * for the first comparison
+ */
+ /* XXX: Adjust for MBCS */
+ if (string + matchlen > strendseg)
+ return FNM_NOMATCH;
+
+ /* Begin first wild comparison at the current position */
+ break;
+ }
+
+ /* Skip forward in pattern by a single character match
+ * Use a dummy fnmatch_ch() test to count one "[range]" escape
+ */
+ /* XXX: Adjust for MBCS */
+ if (escape && (*matchptr == '\\') && matchptr[1]) {
+ matchptr += 2;
+ }
+ else if (*matchptr == '[') {
+ dummyptr = dummystring;
+ fnmatch_ch(&matchptr, &dummyptr, flags);
+ }
+ else {
+ ++matchptr;
+ }
+ }
+ }
+
+ /* Incrementally match string against the pattern
+ */
+ while (*pattern && (string < strendseg))
+ {
+ /* Success; begin a new wild pattern search
+ */
+ if (*pattern == '*')
+ break;
+
+ if (slash && ((*string == '/')
+ || (*pattern == '/')
+ || (escape && (*pattern == '\\')
+ && (pattern[1] == '/'))))
+ break;
+
+ /* Compare ch's (the pattern is advanced over "\/" to the '/',
+ * but slashes will mismatch, and are not consumed)
+ */
+ if (!fnmatch_ch(&pattern, &string, flags))
+ continue;
+
+ /* Failed to match, loop against next char offset of string segment
+ * until not enough string chars remain to match the fixed pattern
+ */
+ if (wild) {
+ /* XXX: Advance 1 char for MBCS locale */
+ string = ++strstartseg;
+ if (string + matchlen > strendseg)
+ return FNM_NOMATCH;
+
+ pattern = mismatch;
+ continue;
+ }
+ else
+ return FNM_NOMATCH;
+ }
+ }
+
+ if (*string && !((slash || leading_dir) && (*string == '/')))
+ return FNM_NOMATCH;
+
+ if (*pattern && !(slash && ((*pattern == '/')
+ || (escape && (*pattern == '\\')
+ && (pattern[1] == '/')))))
+ return FNM_NOMATCH;
+
+ if (leading_dir && !*pattern && *string == '/')
+ return 0;
+ }
+
+ /* Where both pattern and string are at EOS, declare success
+ */
+ if (!*string && !*pattern)
+ return 0;
+
+ /* pattern didn't match to the end of string */
+ return FNM_NOMATCH;
+}
+#endif /* HAVE_FNMATCH */
diff --git a/lib/util/freezero.c b/lib/util/freezero.c
new file mode 100644
index 0000000..dae48b5
--- /dev/null
+++ b/lib/util/freezero.c
@@ -0,0 +1,38 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudo_compat.h>
+
+#ifndef HAVE_FREEZERO
+void
+sudo_freezero(void *p, size_t n)
+{
+ explicit_bzero(p, n);
+ free(p);
+}
+#endif /* HAVE_FREEZERO */
diff --git a/lib/util/fstatat.c b/lib/util/fstatat.c
new file mode 100644
index 0000000..983085d
--- /dev/null
+++ b/lib/util/fstatat.c
@@ -0,0 +1,70 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+
+#ifndef HAVE_FSTATAT
+int
+sudo_fstatat(int dfd, const char *path, struct stat *sb, int flag)
+{
+ int odfd, ret = -1;
+
+ if (dfd == (int)AT_FDCWD) {
+ if (ISSET(flag, AT_SYMLINK_NOFOLLOW))
+ return lstat(path, sb);
+ else
+ return stat(path, sb);
+ }
+
+ /* Save cwd */
+ if ((odfd = open(".", O_RDONLY)) == -1)
+ goto done;
+
+ if (fchdir(dfd) == -1)
+ goto done;
+
+ if (ISSET(flag, AT_SYMLINK_NOFOLLOW))
+ ret = lstat(path, sb);
+ else
+ ret = stat(path, sb);
+
+ /* Restore cwd */
+ if (fchdir(odfd) == -1) {
+ /* Should not happen */
+ ret = -1;
+ }
+
+done:
+ if (odfd != -1)
+ close(odfd);
+
+ return ret;
+}
+#endif /* HAVE_FSTATAT */
diff --git a/lib/util/getaddrinfo.c b/lib/util/getaddrinfo.c
new file mode 100644
index 0000000..4d8256e
--- /dev/null
+++ b/lib/util/getaddrinfo.c
@@ -0,0 +1,406 @@
+/*
+ * Replacement for a missing getaddrinfo.
+ *
+ * This is an implementation of getaddrinfo for systems that don't have one so
+ * that networking code can use a consistent interface without #ifdef. It is
+ * a fairly minimal implementation, with the following limitations:
+ *
+ * - IPv4 support only. IPv6 is not supported.
+ * - AI_ADDRCONFIG is ignored.
+ * - Not thread-safe due to gethostbyname and getservbyname.
+ * - SOCK_DGRAM and SOCK_STREAM only.
+ * - Multiple possible socket types only generate one addrinfo struct.
+ * - Protocol hints aren't used correctly.
+ *
+ * The last four issues could probably be easily remedied, but haven't been
+ * needed to date. Adding IPv6 support isn't worth it; systems with IPv6
+ * support should already have getaddrinfo.
+ *
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Written by Russ Allbery <rra@stanford.edu>
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
+ */
+
+#include <config.h>
+
+#ifndef HAVE_GETADDRINFO
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <netdb.h>
+#include <errno.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#ifdef NEED_RESOLV_H
+# include <arpa/nameser.h>
+# include <resolv.h>
+#endif /* NEED_RESOLV_H */
+
+#include <sudo_compat.h>
+#include <compat/getaddrinfo.h>
+
+/* We need access to h_errno to map errors from gethostbyname. */
+#ifndef HAVE_DECL_H_ERRNO
+extern int h_errno;
+#endif
+
+/*
+ * The netdb constants, which aren't always defined (particularly if h_errno
+ * isn't declared). We also make sure that a few of the less-used ones are
+ * defined so that we can deal with them in case statements.
+ */
+#ifndef HOST_NOT_FOUND
+# define HOST_NOT_FOUND 1
+# define TRY_AGAIN 2
+# define NO_RECOVERY 3
+# define NO_DATA 4
+#endif
+#ifndef NETDB_INTERNAL
+# define NETDB_INTERNAL -1
+#endif
+
+/*
+ * If we're running the test suite, rename the functions to avoid conflicts
+ * with the system version. Note that we don't rename the structures and
+ * constants, but that should be okay (except possibly for gai_strerror).
+ */
+#ifdef TESTING
+# define gai_strerror test_gai_strerror
+# define freeaddrinfo test_freeaddrinfo
+# define getaddrinfo test_getaddrinfo
+const char *test_gai_strerror(int);
+void test_freeaddrinfo(struct addrinfo *);
+int test_getaddrinfo(const char *, const char *, const struct addrinfo *,
+ struct addrinfo **);
+#endif
+
+/*
+ * If the platform doesn't support AI_NUMERICSERV or AI_NUMERICHOST,
+ * pick some other values for them.
+ */
+#ifdef TESTING
+# if AI_NUMERICSERV == 0
+# undef AI_NUMERICSERV
+# define AI_NUMERICSERV 0x0080
+# endif
+# if AI_NUMERICHOST == 0
+# undef AI_NUMERICHOST
+# define AI_NUMERICHOST 0x0100
+# endif
+#endif
+
+/*
+ * Value representing all of the hint flags set. Linux uses flags up to
+ * 0x0400, so be sure not to break when testing on that platform.
+ */
+#ifdef TESTING
+# ifdef HAVE_GETADDRINFO
+# define AI_INTERNAL_ALL 0x04ff
+# else
+# define AI_INTERNAL_ALL 0x01ff
+# endif
+#else
+# define AI_INTERNAL_ALL 0x007f
+#endif
+
+/* Table of strings corresponding to the EAI_* error codes. */
+static const char * const gai_errors[] = {
+ "Host name lookup failure", /* 1 EAI_AGAIN */
+ "Invalid flag value", /* 2 EAI_BADFLAGS */
+ "Unknown server error", /* 3 EAI_FAIL */
+ "Unsupported address family", /* 4 EAI_FAMILY */
+ "Memory allocation failure", /* 5 EAI_MEMORY */
+ "Host unknown or not given", /* 6 EAI_NONAME */
+ "Service not supported for socket", /* 7 EAI_SERVICE */
+ "Unsupported socket type", /* 8 EAI_SOCKTYPE */
+ "System error", /* 9 EAI_SYSTEM */
+ "Supplied buffer too small", /* 10 EAI_OVERFLOW */
+};
+
+/* Macro to set the len attribute of sockaddr_in. */
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+# define sin_set_length(s) ((s)->sin_len = sizeof(struct sockaddr_in))
+#else
+# define sin_set_length(s) /* empty */
+#endif
+
+/*
+ * Return a constant string for a given EAI_* error code or a string
+ * indicating an unknown error.
+ */
+const char *
+sudo_gai_strerror(int ecode)
+{
+ if (ecode < 1 || (size_t) ecode > nitems(gai_errors))
+ return "Unknown error";
+ else
+ return gai_errors[ecode - 1];
+}
+
+
+/*
+ * Free a linked list of addrinfo structs.
+ */
+void
+sudo_freeaddrinfo(struct addrinfo *ai)
+{
+ struct addrinfo *next;
+
+ while (ai != NULL) {
+ next = ai->ai_next;
+ if (ai->ai_addr != NULL)
+ free(ai->ai_addr);
+ if (ai->ai_canonname != NULL)
+ free(ai->ai_canonname);
+ free(ai);
+ ai = next;
+ }
+}
+
+
+/*
+ * Allocate a new addrinfo struct, setting some defaults given that this
+ * implementation is IPv4 only. Also allocates an attached sockaddr_in and
+ * zeroes it, per the requirement for getaddrinfo. Takes the socktype,
+ * canonical name (which is copied if not NULL), address, and port. Returns
+ * NULL on a memory allocation failure.
+ */
+static struct addrinfo *
+gai_addrinfo_new(int socktype, const char *canonical, struct in_addr addr,
+ unsigned short port)
+{
+ struct addrinfo *ai;
+
+ ai = malloc(sizeof(*ai));
+ if (ai == NULL)
+ return NULL;
+ ai->ai_addr = malloc(sizeof(struct sockaddr_in));
+ if (ai->ai_addr == NULL) {
+ free(ai);
+ return NULL;
+ }
+ ai->ai_next = NULL;
+ if (canonical == NULL)
+ ai->ai_canonname = NULL;
+ else {
+ ai->ai_canonname = strdup(canonical);
+ if (ai->ai_canonname == NULL) {
+ freeaddrinfo(ai);
+ return NULL;
+ }
+ }
+ memset(ai->ai_addr, 0, sizeof(struct sockaddr_in));
+ ai->ai_flags = 0;
+ ai->ai_family = AF_INET;
+ ai->ai_socktype = socktype;
+ ai->ai_protocol = (socktype == SOCK_DGRAM) ? IPPROTO_UDP : IPPROTO_TCP;
+ ai->ai_addrlen = sizeof(struct sockaddr_in);
+ ((struct sockaddr_in *) ai->ai_addr)->sin_family = AF_INET;
+ ((struct sockaddr_in *) ai->ai_addr)->sin_addr = addr;
+ ((struct sockaddr_in *) ai->ai_addr)->sin_port = htons(port);
+ sin_set_length((struct sockaddr_in *) ai->ai_addr);
+ return ai;
+}
+
+
+/*
+ * Look up a service. Takes the service name (which may be numeric), the hint
+ * flags, a pointer to the socket type (used to determine whether TCP or UDP
+ * services are of interest and, if 0, is filled in with the result of
+ * getservbyname if the service was not numeric), and a pointer to the
+ * addrinfo struct to fill in. Returns 0 on success or an EAI_* error on
+ * failure.
+ */
+static int
+gai_service(const char *servname, int flags, int *type, unsigned short *port)
+{
+ struct servent *servent;
+ const char *protocol;
+ const char *errstr;
+ unsigned short value;
+
+ value = sudo_strtonum(servname, 0, USHRT_MAX, &errstr);
+ if (errstr == NULL) {
+ *port = value;
+ } else if (errno == ERANGE) {
+ return EAI_SERVICE;
+ } else {
+ if (flags & AI_NUMERICSERV)
+ return EAI_NONAME;
+ if (*type != 0)
+ protocol = (*type == SOCK_DGRAM) ? "udp" : "tcp";
+ else
+ protocol = NULL;
+
+ /*
+ * We really technically should be generating an addrinfo struct for
+ * each possible protocol unless type is set, but this works well
+ * enough for what I need this for.
+ */
+ servent = getservbyname(servname, protocol);
+ if (servent == NULL)
+ return EAI_NONAME;
+ if (strcmp(servent->s_proto, "udp") == 0)
+ *type = SOCK_DGRAM;
+ else if (strcmp(servent->s_proto, "tcp") == 0)
+ *type = SOCK_STREAM;
+ else
+ return EAI_SERVICE;
+ *port = htons(servent->s_port);
+ }
+ return 0;
+}
+
+
+/*
+ * Look up a host and fill in a linked list of addrinfo structs with the
+ * results, one per IP address of the returned host. Takes the name or IP
+ * address of the host as a string, the lookup flags, the type of socket (to
+ * fill into the addrinfo structs), the port (likewise), and a pointer to
+ * where the head of the linked list should be put. Returns 0 on success or
+ * the appropriate EAI_* error.
+ */
+static int
+gai_lookup(const char *nodename, int flags, int socktype, unsigned short port,
+ struct addrinfo **res)
+{
+ struct addrinfo *ai, *first, *prev;
+ struct in_addr addr;
+ struct hostent *host;
+ const char *canonical;
+ size_t i;
+
+ if (inet_pton(AF_INET, nodename, &addr)) {
+ canonical = (flags & AI_CANONNAME) ? nodename : NULL;
+ ai = gai_addrinfo_new(socktype, canonical, addr, port);
+ if (ai == NULL)
+ return EAI_MEMORY;
+ *res = ai;
+ return 0;
+ } else {
+ if (flags & AI_NUMERICHOST)
+ return EAI_NONAME;
+ host = gethostbyname(nodename);
+ if (host == NULL)
+ switch (h_errno) {
+ case HOST_NOT_FOUND:
+ return EAI_NONAME;
+ case TRY_AGAIN:
+ case NO_DATA:
+ return EAI_AGAIN;
+ case NO_RECOVERY:
+ return EAI_FAIL;
+ case NETDB_INTERNAL:
+ default:
+ return EAI_SYSTEM;
+ }
+ if (host->h_addr_list[0] == NULL)
+ return EAI_FAIL;
+ canonical = (flags & AI_CANONNAME)
+ ? ((host->h_name != NULL) ? host->h_name : nodename)
+ : NULL;
+ first = NULL;
+ prev = NULL;
+ for (i = 0; host->h_addr_list[i] != NULL; i++) {
+ if (host->h_length != sizeof(addr)) {
+ freeaddrinfo(first);
+ return EAI_FAIL;
+ }
+ memcpy(&addr, host->h_addr_list[i], sizeof(addr));
+ ai = gai_addrinfo_new(socktype, canonical, addr, port);
+ if (ai == NULL) {
+ freeaddrinfo(first);
+ return EAI_MEMORY;
+ }
+ if (first == NULL) {
+ first = ai;
+ prev = ai;
+ } else {
+ prev->ai_next = ai;
+ prev = ai;
+ }
+ }
+ *res = first;
+ return 0;
+ }
+}
+
+
+/*
+ * The actual getaddrinfo implementation.
+ */
+int
+sudo_getaddrinfo(const char *nodename, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res)
+{
+ struct addrinfo *ai;
+ struct in_addr addr;
+ int flags, socktype, status;
+ unsigned short port;
+
+ /* Take the hints into account and check them for validity. */
+ if (hints != NULL) {
+ flags = hints->ai_flags;
+ socktype = hints->ai_socktype;
+ if ((flags & AI_INTERNAL_ALL) != flags)
+ return EAI_BADFLAGS;
+ if (hints->ai_family != AF_UNSPEC && hints->ai_family != AF_INET)
+ return EAI_FAMILY;
+ if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM)
+ return EAI_SOCKTYPE;
+
+ /* EAI_SOCKTYPE isn't quite right, but there isn't anything better. */
+ if (hints->ai_protocol != 0) {
+ int protocol = hints->ai_protocol;
+ if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP)
+ return EAI_SOCKTYPE;
+ }
+ } else {
+ flags = 0;
+ socktype = 0;
+ }
+
+ /*
+ * See what we're doing. If nodename is null, either AI_PASSIVE is set or
+ * we're getting information for connecting to a service on the loopback
+ * address. Otherwise, we're getting information for connecting to a
+ * remote system.
+ */
+ if (servname == NULL)
+ port = 0;
+ else {
+ status = gai_service(servname, flags, &socktype, &port);
+ if (status != 0)
+ return status;
+ }
+ if (nodename != NULL)
+ return gai_lookup(nodename, flags, socktype, port, res);
+ else {
+ if (servname == NULL)
+ return EAI_NONAME;
+ if ((flags & AI_PASSIVE) == AI_PASSIVE)
+ addr.s_addr = INADDR_ANY;
+ else
+ addr.s_addr = htonl(0x7f000001UL);
+ ai = gai_addrinfo_new(socktype, NULL, addr, port);
+ if (ai == NULL)
+ return EAI_MEMORY;
+ *res = ai;
+ return 0;
+ }
+}
+#endif /* HAVE_GETADDRINFO */
diff --git a/lib/util/getdelim.c b/lib/util/getdelim.c
new file mode 100644
index 0000000..1c95705
--- /dev/null
+++ b/lib/util/getdelim.c
@@ -0,0 +1,83 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_GETDELIM
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include <sudo_compat.h>
+
+ssize_t
+sudo_getdelim(char ** restrict buf, size_t * restrict bufsize, int delim,
+ FILE * restrict fp)
+{
+ char *cp, *ep;
+ int ch;
+
+ if (*buf == NULL || *bufsize == 0) {
+ char *tmp = realloc(*buf, LINE_MAX);
+ if (tmp == NULL)
+ return -1;
+ *buf = tmp;
+ *bufsize = LINE_MAX;
+ }
+ cp = *buf;
+ ep = cp + *bufsize;
+
+ do {
+ if (cp + 1 >= ep) {
+ char *newbuf = reallocarray(*buf, *bufsize, 2);
+ if (newbuf == NULL)
+ goto bad;
+ *bufsize *= 2;
+ cp = newbuf + (cp - *buf);
+ ep = newbuf + *bufsize;
+ *buf = newbuf;
+ }
+ if ((ch = getc(fp)) == EOF) {
+ if (feof(fp))
+ break;
+ goto bad;
+ }
+ *cp++ = ch;
+ } while (ch != delim);
+
+ /* getdelim(3) should never return a length of 0. */
+ if (cp != *buf) {
+ *cp = '\0';
+ return (ssize_t)(cp - *buf);
+ }
+bad:
+ /* Error, push back what was read if possible. */
+ while (cp > *buf) {
+ if (ungetc(*cp--, fp) == EOF)
+ break;
+ }
+ return -1;
+}
+#endif /* HAVE_GETDELIM */
diff --git a/lib/util/getentropy.c b/lib/util/getentropy.c
new file mode 100644
index 0000000..5daf0f7
--- /dev/null
+++ b/lib/util/getentropy.c
@@ -0,0 +1,649 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
+ * Copyright (c) 2014 Bob Beck <beck@obtuse.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Emulation of getentropy(2) as documented at:
+ * http://man.openbsd.org/getentropy.2
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_GETENTROPY
+
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_SYSCTL_H
+# include <sys/sysctl.h>
+#endif
+#ifdef HAVE_SYS_STATVFS_H
+# include <sys/statvfs.h>
+#endif
+#include <sys/stat.h>
+#include <sys/time.h>
+#ifdef HAVE_SYS_SYSCALL_H
+# include <sys/syscall.h>
+#endif
+#ifdef HAVE_LINUX_RANDOM_H
+# include <linux/types.h>
+# include <linux/random.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#ifdef HAVE_GETAUXVAL
+# include <sys/auxv.h>
+#endif
+#ifdef HAVE_DL_ITERATE_PHDR
+# include <link.h>
+#endif
+#ifdef HAVE_OPENSSL
+# if defined(HAVE_WOLFSSL)
+# include <wolfssl/options.h>
+# endif
+# include <openssl/rand.h>
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_digest.h>
+#include <sudo_rand.h>
+
+#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
+# define MAP_ANON MAP_ANONYMOUS
+#endif
+
+#ifndef MAP_FAILED
+# define MAP_FAILED ((void *) -1)
+#endif
+
+#define REPEAT 5
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+
+#define HX(a, b) \
+ do { \
+ if ((a)) \
+ HD(errno); \
+ else \
+ HD(b); \
+ } while (0)
+
+#define HR(x, l) (sudo_digest_update(ctx, (char *)(x), (l)))
+#define HD(x) (sudo_digest_update(ctx, (char *)&(x), sizeof (x)))
+#define HF(x) (sudo_digest_update(ctx, (char *)&(x), sizeof (void*)))
+
+int sudo_getentropy(void *buf, size_t len);
+
+static int getentropy_getrandom(void *buf, size_t len);
+static int getentropy_sysctl(void *buf, size_t len);
+static int getentropy_urandom(void *buf, size_t len, const char *path,
+ int devfscheck);
+static int getentropy_fallback(void *buf, size_t len);
+static int gotdata(char *buf, size_t len);
+#ifdef HAVE_DL_ITERATE_PHDR
+static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
+#endif
+
+static void *
+mmap_anon(void *addr, size_t len, int prot, int flags, off_t offset)
+{
+#ifdef MAP_ANON
+ return mmap(addr, len, prot, flags | MAP_ANON, -1, offset);
+#else
+ int fd;
+
+ if ((fd = open("/dev/zero", O_RDWR)) == -1)
+ return MAP_FAILED;
+ addr = mmap(addr, len, prot, flags, fd, offset);
+ close(fd);
+ return addr;
+#endif
+}
+
+int
+sudo_getentropy(void *buf, size_t len)
+{
+ int ret = -1;
+
+ if (len > 256) {
+ errno = EIO;
+ return (-1);
+ }
+
+ ret = getentropy_getrandom(buf, len);
+ if (ret != -1)
+ return (ret);
+
+#ifdef HAVE_OPENSSL
+ if (RAND_bytes(buf, (int)len) == 1)
+ return (0);
+#endif
+
+ ret = getentropy_sysctl(buf, len);
+ if (ret != -1)
+ return (ret);
+
+ /*
+ * Try to get entropy with /dev/urandom
+ */
+ ret = getentropy_urandom(buf, len, "/dev/urandom", 0);
+ if (ret != -1)
+ return (ret);
+
+ /*
+ * Entropy collection via /dev/urandom has failed.
+ *
+ * No other API exists for collecting entropy, and we have no
+ * failsafe way to get it that is not sensitive to resource exhaustion.
+ *
+ * We have very few options:
+ * - Even syslog_r is unsafe to call at this low level, so
+ * there is no way to alert the user or program.
+ * - Cannot call abort() because some systems have unsafe
+ * corefiles.
+ * - Could raise(SIGKILL) resulting in silent program termination.
+ * - Return EIO, to hint that arc4random's stir function
+ * should raise(SIGKILL)
+ * - Do the best under the circumstances....
+ *
+ * This code path exists to bring light to the issue that the OS
+ * does not provide a failsafe API for entropy collection.
+ *
+ * We hope this demonstrates that the OS should consider
+ * providing a new failsafe API which works in a chroot or
+ * when file descriptors are exhausted.
+ */
+#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
+#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
+ raise(SIGKILL);
+#endif
+ ret = getentropy_fallback(buf, len);
+ if (ret != -1)
+ return (ret);
+
+ errno = EIO;
+ return (ret);
+}
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+/*
+ * Basic validity checking; wish we could do better.
+ */
+static int
+gotdata(char *buf, size_t len)
+{
+ char any_set = 0;
+ size_t i;
+
+ for (i = 0; i < len; ++i)
+ any_set |= buf[i];
+ if (any_set == 0)
+ return (-1);
+ return (0);
+}
+
+static int
+getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
+{
+ struct stat st;
+ size_t i;
+ int fd, flags;
+ int save_errno = errno;
+
+start:
+
+ /* We do not use O_NOFOLLOW since /dev/urandom is a link on Solaris. */
+ flags = O_RDONLY;
+#ifdef O_CLOEXEC
+ flags |= O_CLOEXEC;
+#endif
+ fd = open(path, flags, 0);
+ if (fd == -1) {
+ if (errno == EINTR)
+ goto start;
+ goto nodevrandom;
+ }
+#ifndef O_CLOEXEC
+ fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+#endif
+
+ /* Lightly verify that the device node looks OK */
+ if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
+ close(fd);
+ goto nodevrandom;
+ }
+ for (i = 0; i < len; ) {
+ size_t wanted = len - i;
+ size_t ret = (size_t)read(fd, (char *)buf + i, wanted);
+
+ if (ret == (size_t)-1) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ close(fd);
+ goto nodevrandom;
+ }
+ i += ret;
+ }
+ close(fd);
+ if (gotdata(buf, len) == 0) {
+ errno = save_errno;
+ return (0); /* satisfied */
+ }
+nodevrandom:
+ errno = EIO;
+ return (-1);
+}
+
+#if defined(HAVE_SYSCTL) && defined(KERN_ARND)
+static int
+getentropy_sysctl(void *buf, size_t len)
+{
+ int save_errno = errno;
+ int mib[2];
+ size_t i;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_ARND;
+
+ for (i = 0; i < len; ) {
+ size_t chunk = len - i;
+
+ if (sysctl(mib, 2, (char *)buf + i, &chunk, NULL, 0) == -1)
+ goto sysctlfailed;
+ i += chunk;
+ }
+ if (gotdata(buf, len) == 0) {
+ errno = save_errno;
+ return (0); /* satisfied */
+ }
+sysctlfailed:
+ errno = EIO;
+ return (-1);
+}
+#elif defined(SYS__sysctl) && defined(RANDOM_UUID)
+static int
+getentropy_sysctl(void *buf, size_t len)
+{
+ static int mib[3];
+ size_t i;
+ int save_errno = errno;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_RANDOM;
+ mib[2] = RANDOM_UUID;
+
+ for (i = 0; i < len; ) {
+ size_t chunk = min(len - i, 16);
+
+ /* SYS__sysctl because some systems already removed sysctl() */
+ struct __sysctl_args args = {
+ .name = mib,
+ .nlen = 3,
+ .oldval = (char *)buf + i,
+ .oldlenp = &chunk,
+ };
+ if (syscall(SYS__sysctl, &args) != 0)
+ goto sysctlfailed;
+ i += chunk;
+ }
+ if (gotdata(buf, len) == 0) {
+ errno = save_errno;
+ return (0); /* satisfied */
+ }
+sysctlfailed:
+ errno = EIO;
+ return (-1);
+}
+#else
+static int
+getentropy_sysctl(void *buf, size_t len)
+{
+ errno = ENOTSUP;
+ return (-1);
+}
+#endif
+
+#if defined(SYS_getrandom) && defined(GRND_NONBLOCK)
+static int
+getentropy_getrandom(void *buf, size_t len)
+{
+ int pre_errno = errno;
+ long ret;
+
+ /*
+ * Try descriptor-less getrandom(), in non-blocking mode.
+ *
+ * The design of Linux getrandom is broken. It has an
+ * uninitialized phase coupled with blocking behaviour, which
+ * is unacceptable from within a library at boot time without
+ * possible recovery. See http://bugs.python.org/issue26839#msg267745
+ */
+ do {
+ ret = syscall(SYS_getrandom, buf, len, GRND_NONBLOCK);
+ } while (ret == -1 && errno == EINTR);
+
+ if (ret < 0 || (size_t)ret != len)
+ return (-1);
+ errno = pre_errno;
+ return (0);
+}
+#else
+static int
+getentropy_getrandom(void *buf, size_t len)
+{
+ errno = ENOTSUP;
+ return (-1);
+}
+#endif
+
+#ifdef HAVE_CLOCK_GETTIME
+static const int cl[] = {
+ CLOCK_REALTIME,
+#ifdef CLOCK_MONOTONIC
+ CLOCK_MONOTONIC,
+#endif
+#ifdef CLOCK_MONOTONIC_RAW
+ CLOCK_MONOTONIC_RAW,
+#endif
+#ifdef CLOCK_TAI
+ CLOCK_TAI,
+#endif
+#ifdef CLOCK_VIRTUAL
+ CLOCK_VIRTUAL,
+#endif
+#ifdef CLOCK_UPTIME
+ CLOCK_UPTIME,
+#endif
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+ CLOCK_PROCESS_CPUTIME_ID,
+#endif
+#ifdef CLOCK_THREAD_CPUTIME_ID
+ CLOCK_THREAD_CPUTIME_ID,
+#endif
+};
+#endif /* HAVE_CLOCK_GETTIME */
+
+#ifdef HAVE_DL_ITERATE_PHDR
+static int
+getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
+{
+ struct sudo_digest *ctx = data;
+
+ sudo_digest_update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
+ return (0);
+}
+#endif
+
+static int
+getentropy_fallback(void *buf, size_t len)
+{
+ unsigned char *results = NULL;
+ int save_errno = errno, e, faster = 0;
+ int ret = -1;
+ static size_t cnt;
+ unsigned int repeat;
+ size_t pgs;
+ struct timespec ts;
+ struct timeval tv;
+ struct rusage ru;
+ sigset_t set;
+ struct stat st;
+ struct sudo_digest *ctx;
+ static pid_t lastpid;
+ pid_t pid;
+ size_t i, ii, m, digest_len;
+ char *p;
+
+ if (len == 0)
+ return 0;
+ pgs = (size_t)sysconf(_SC_PAGESIZE);
+ if (pgs == (size_t)-1)
+ return -1;
+ if ((ctx = sudo_digest_alloc(SUDO_DIGEST_SHA512)) == NULL)
+ return -1;
+ digest_len = sudo_digest_getlen(SUDO_DIGEST_SHA512);
+ if (digest_len == 0 || (results = malloc(digest_len)) == NULL)
+ goto done;
+
+ pid = getpid();
+ if (lastpid == pid) {
+ faster = 1;
+ repeat = 2;
+ } else {
+ faster = 0;
+ lastpid = pid;
+ repeat = REPEAT;
+ }
+ i = 0;
+ do {
+ unsigned int j;
+ for (j = 0; j < repeat; j++) {
+ HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+ if (e != -1) {
+ cnt += (size_t)tv.tv_sec;
+ cnt += (size_t)tv.tv_usec;
+ }
+#ifdef HAVE_DL_ITERATE_PHDR
+ dl_iterate_phdr(getentropy_phdr, ctx);
+#endif
+
+#ifdef HAVE_CLOCK_GETTIME
+ for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
+ HX(clock_gettime(cl[ii], &ts) == -1, ts);
+#endif /* HAVE_CLOCK_GETTIME */
+
+ HX((pid = getpid()) == -1, pid);
+ HX((pid = getsid(pid)) == -1, pid);
+ HX((pid = getppid()) == -1, pid);
+ HX((pid = getpgid(0)) == -1, pid);
+ HX((e = getpriority(0, 0)) == -1, e);
+
+ if (!faster) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1;
+ (void) nanosleep(&ts, NULL);
+ }
+
+ HX(sigpending(&set) == -1, set);
+ HX(sigprocmask(SIG_BLOCK, NULL, &set) == -1, set);
+
+ HF(sudo_getentropy); /* an addr in this library */
+ HF(printf); /* an addr in libc */
+ p = (char *)&p;
+ HD(p); /* an addr on stack */
+ p = (char *)&errno;
+ HD(p); /* the addr of errno */
+
+ if (i == 0) {
+#ifdef HAVE_SYS_STATVFS_H
+ struct statvfs stvfs;
+#endif
+ struct termios tios;
+ off_t off;
+
+ /*
+ * Prime-sized mappings encourage fragmentation;
+ * thus exposing some address entropy.
+ */
+ struct mm {
+ size_t npg;
+ void *p;
+ } mm[] = {
+ { 17, MAP_FAILED }, { 3, MAP_FAILED },
+ { 11, MAP_FAILED }, { 2, MAP_FAILED },
+ { 5, MAP_FAILED }, { 3, MAP_FAILED },
+ { 7, MAP_FAILED }, { 1, MAP_FAILED },
+ { 57, MAP_FAILED }, { 3, MAP_FAILED },
+ { 131, MAP_FAILED }, { 1, MAP_FAILED },
+ };
+
+ for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+ HX(mm[m].p = mmap_anon(NULL,
+ mm[m].npg * pgs,
+ PROT_READ|PROT_WRITE,
+ MAP_PRIVATE,
+ (off_t)0), mm[m].p);
+ if (mm[m].p != MAP_FAILED) {
+ size_t mo;
+
+ /* Touch some memory... */
+ p = mm[m].p;
+ mo = cnt %
+ (mm[m].npg * pgs - 1);
+ p[mo] = 1;
+ cnt += (size_t)mm[m].p / pgs;
+ }
+
+#ifdef HAVE_CLOCK_GETTIME
+ /* Check cnts and times... */
+ for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
+ ii++) {
+ HX((e = clock_gettime(cl[ii],
+ &ts)) == -1, ts);
+ if (e != -1)
+ cnt += (size_t)ts.tv_nsec;
+ }
+#endif /* HAVE_CLOCK_GETTIME */
+
+ HX((e = getrusage(RUSAGE_SELF,
+ &ru)) == -1, ru);
+ if (e != -1) {
+ cnt += (size_t)ru.ru_utime.tv_sec;
+ cnt += (size_t)ru.ru_utime.tv_usec;
+ }
+ }
+
+ for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+ if (mm[m].p != MAP_FAILED)
+ munmap(mm[m].p, mm[m].npg * pgs);
+ mm[m].p = MAP_FAILED;
+ }
+
+ HX(stat(".", &st) == -1, st);
+ HX(stat("/", &st) == -1, st);
+
+#ifdef HAVE_SYS_STATVFS_H
+ HX(statvfs(".", &stvfs) == -1, stvfs);
+ HX(statvfs("/", &stvfs) == -1, stvfs);
+#endif
+ HX((e = fstat(0, &st)) == -1, st);
+ if (e == -1) {
+ if (S_ISREG(st.st_mode) ||
+ S_ISFIFO(st.st_mode) ||
+ S_ISSOCK(st.st_mode)) {
+#ifdef HAVE_SYS_STATVFS_H
+ HX(fstatvfs(0, &stvfs) == -1,
+ stvfs);
+#endif
+ HX((off = lseek(0, (off_t)0,
+ SEEK_CUR)) < 0, off);
+ }
+ if (S_ISCHR(st.st_mode)) {
+ HX(tcgetattr(0, &tios) == -1,
+ tios);
+#if 0
+ } else if (S_ISSOCK(st.st_mode)) {
+ struct sockaddr_storage ss;
+ socklen_t ssl;
+ memset(&ss, 0, sizeof ss);
+ ssl = sizeof(ss);
+ HX(getpeername(0,
+ (void *)&ss, &ssl) == -1,
+ ss);
+#endif
+ }
+ }
+
+ HX((e = getrusage(RUSAGE_CHILDREN,
+ &ru)) == -1, ru);
+ if (e != -1) {
+ cnt += (size_t)ru.ru_utime.tv_sec;
+ cnt += (size_t)ru.ru_utime.tv_usec;
+ }
+ } else {
+ /* Subsequent hashes absorb previous result */
+ HR(results, digest_len);
+ }
+
+ HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+ if (e != -1) {
+ cnt += (size_t)tv.tv_sec;
+ cnt += (size_t)tv.tv_usec;
+ }
+
+ HD(cnt);
+ }
+
+#ifdef HAVE_GETAUXVAL
+#ifdef AT_RANDOM
+ /* Not as random as you think but we take what we are given */
+ p = (char *) getauxval(AT_RANDOM);
+ if (p)
+ HR(p, 16);
+#endif
+#ifdef AT_SYSINFO_EHDR
+ p = (char *) getauxval(AT_SYSINFO_EHDR);
+ if (p)
+ HR(p, pgs);
+#endif
+#ifdef AT_BASE
+ p = (char *) getauxval(AT_BASE);
+ if (p)
+ HD(p);
+#endif
+#endif /* HAVE_GETAUXVAL */
+
+ sudo_digest_final(ctx, results);
+ sudo_digest_reset(ctx);
+ memcpy((char *)buf + i, results, min(digest_len, len - i));
+ i += min(digest_len, len - i);
+ } while (i < len);
+ if (gotdata(buf, len) == 0) {
+ errno = save_errno;
+ ret = 0; /* satisfied */
+ } else {
+ errno = EIO;
+ }
+done:
+ sudo_digest_free(ctx);
+ if (results != NULL)
+ freezero(results, digest_len);
+ return (ret);
+}
+
+#endif /* HAVE_GETENTROPY */
diff --git a/lib/util/getgrouplist.c b/lib/util/getgrouplist.c
new file mode 100644
index 0000000..48d1fbe
--- /dev/null
+++ b/lib/util/getgrouplist.c
@@ -0,0 +1,530 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010, 2011, 2013-2021
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <grp.h>
+#include <limits.h>
+#include <unistd.h>
+#ifdef HAVE_NSS_SEARCH
+# include <errno.h>
+# include <limits.h>
+# include <nsswitch.h>
+# ifdef HAVE_NSS_DBDEFS_H
+# include <nss_dbdefs.h>
+# else
+# include <compat/nss_dbdefs.h>
+# endif
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+
+#ifndef HAVE_GETGROUPLIST
+int
+sudo_getgrouplist(const char *name, GETGROUPS_T basegid, GETGROUPS_T *groups,
+ int *ngroupsp)
+{
+ return sudo_getgrouplist2(name, basegid, &groups, ngroupsp);
+}
+#endif /* HAVE_GETGROUPLIST */
+
+#if defined(HAVE_GETGROUPLIST)
+
+#if defined(HAVE_GETGROUPLIST_2) && !HAVE_DECL_GETGROUPLIST_2
+int getgrouplist_2(const char *name, GETGROUPS_T basegid, GETGROUPS_T **groups);
+#endif /* HAVE_GETGROUPLIST_2 && !HAVE_DECL_GETGROUPLIST_2 */
+
+/*
+ * Extended getgrouplist(3) using getgrouplist(3) and getgrouplist_2(3)
+ */
+int
+sudo_getgrouplist2_v1(const char *name, GETGROUPS_T basegid,
+ GETGROUPS_T **groupsp, int *ngroupsp)
+{
+#ifdef __APPLE__
+ int *groups = (int *)*groupsp;
+#else
+ GETGROUPS_T *groups = *groupsp;
+#endif
+ int ngroups;
+#ifndef HAVE_GETGROUPLIST_2
+ long grpsize;
+ int tries;
+#endif
+ debug_decl(sudo_getgrouplist2, SUDO_DEBUG_UTIL);
+
+ /* For static group vector, just use getgrouplist(3). */
+ if (groups != NULL)
+ debug_return_int(getgrouplist(name, basegid, groups, ngroupsp));
+
+#ifdef HAVE_GETGROUPLIST_2
+ if ((ngroups = getgrouplist_2(name, basegid, groupsp)) == -1)
+ debug_return_int(-1);
+ *ngroupsp = ngroups;
+ debug_return_int(0);
+#else
+ grpsize = sysconf(_SC_NGROUPS_MAX);
+ if (grpsize < 0 || grpsize > INT_MAX)
+ grpsize = NGROUPS_MAX;
+ grpsize++; /* include space for the primary gid */
+ /*
+ * It is possible to belong to more groups in the group database
+ * than NGROUPS_MAX.
+ */
+ for (tries = 0; tries < 10; tries++) {
+ free(groups);
+ groups = reallocarray(NULL, (size_t)grpsize, sizeof(*groups));
+ if (groups == NULL)
+ debug_return_int(-1);
+ ngroups = (int)grpsize;
+ if (getgrouplist(name, basegid, groups, &ngroups) != -1) {
+ *groupsp = groups;
+ *ngroupsp = ngroups;
+ debug_return_int(0);
+ }
+ if (ngroups == grpsize) {
+ /* Failed for some reason other than ngroups too small. */
+ break;
+ }
+ /* getgrouplist(3) set ngroups to the required length, use it. */
+ grpsize = ngroups;
+ }
+ free(groups);
+ debug_return_int(-1);
+#endif /* HAVE_GETGROUPLIST_2 */
+}
+
+#elif defined(HAVE_GETGRSET)
+
+/*
+ * Extended getgrouplist(3) using AIX getgrset(3)
+ */
+int
+sudo_getgrouplist2_v1(const char *name, GETGROUPS_T basegid,
+ GETGROUPS_T **groupsp, int *ngroupsp)
+{
+ GETGROUPS_T *groups = *groupsp;
+ char *cp, *last, *grset = NULL;
+ const char *errstr;
+ int ngroups = 1;
+ int grpsize = *ngroupsp;
+ int ret = -1;
+ gid_t gid;
+ debug_decl(sudo_getgrouplist2, SUDO_DEBUG_UTIL);
+
+#ifdef HAVE_SETAUTHDB
+ aix_setauthdb((char *) name, NULL);
+#endif
+ if ((grset = getgrset(name)) == NULL)
+ goto done;
+
+ if (groups == NULL) {
+ /* Dynamically-sized group vector, count groups and alloc. */
+ grpsize = 1; /* reserve one for basegid */
+ if (*grset != '\0') {
+ grpsize++; /* at least one supplementary group */
+ for (cp = grset; *cp != '\0'; cp++) {
+ if (*cp == ',')
+ grpsize++;
+ }
+ }
+ groups = reallocarray(NULL, grpsize, sizeof(*groups));
+ if (groups == NULL)
+ debug_return_int(-1);
+ } else {
+ /* Static group vector. */
+ if (grpsize < 1)
+ debug_return_int(-1);
+ }
+
+ /* We support BSD semantics where the first element is the base gid */
+ groups[0] = basegid;
+
+ for (cp = strtok_r(grset, ",", &last); cp != NULL; cp = strtok_r(NULL, ",", &last)) {
+ gid = sudo_strtoid(cp, &errstr);
+ if (errstr == NULL && gid != basegid) {
+ if (ngroups == grpsize)
+ goto done;
+ groups[ngroups++] = gid;
+ }
+ }
+ ret = 0;
+
+done:
+ free(grset);
+#ifdef HAVE_SETAUTHDB
+ aix_restoreauthdb();
+#endif
+ *groupsp = groups;
+ *ngroupsp = ngroups;
+
+ debug_return_int(ret);
+}
+
+#elif defined(HAVE_NSS_SEARCH)
+
+#ifndef ALIGNBYTES
+# define ALIGNBYTES (sizeof(long) - 1L)
+#endif
+#ifndef ALIGN
+# define ALIGN(p) (((unsigned long)(p) + ALIGNBYTES) & ~ALIGNBYTES)
+#endif
+
+#if defined(HAVE__NSS_INITF_GROUP) || defined(HAVE___NSS_INITF_GROUP)
+extern void _nss_initf_group(nss_db_params_t *params);
+#else
+static void
+_nss_initf_group(nss_db_params_t *params)
+{
+ params->name = NSS_DBNAM_GROUP;
+ params->default_config = NSS_DEFCONF_GROUP;
+}
+#endif
+
+/*
+ * Convert a groups file string (instr) to a struct group (ent) using
+ * buf for storage.
+ */
+static int
+str2grp(const char *instr, int inlen, void *ent, char *buf, int buflen)
+{
+ struct group *grp = ent;
+ char *cp, *fieldsep = buf;
+ char **gr_mem, **gr_end;
+ const char *errstr;
+ int yp = 0;
+ id_t id;
+ debug_decl(str2grp, SUDO_DEBUG_UTIL);
+
+ /* Must at least have space to copy instr -> buf. */
+ if (inlen >= buflen)
+ debug_return_int(NSS_STR_PARSE_ERANGE);
+
+ /* Paranoia: buf and instr should be distinct. */
+ if (buf != instr) {
+ memmove(buf, instr, inlen);
+ buf[inlen] = '\0';
+ }
+
+ if ((fieldsep = strchr(cp = fieldsep, ':')) == NULL)
+ debug_return_int(NSS_STR_PARSE_PARSE);
+ *fieldsep++ = '\0';
+ grp->gr_name = cp;
+
+ /* Check for YP inclusion/exclusion entries. */
+ if (*cp == '+' || *cp == '-') {
+ /* Only the name is required for YP inclusion/exclusion entries. */
+ grp->gr_passwd = (char *)"";
+ grp->gr_gid = 0;
+ grp->gr_mem = NULL;
+ yp = 1;
+ }
+
+ if ((fieldsep = strchr(cp = fieldsep, ':')) == NULL)
+ debug_return_int(yp ? NSS_STR_PARSE_SUCCESS : NSS_STR_PARSE_PARSE);
+ *fieldsep++ = '\0';
+ grp->gr_passwd = cp;
+
+ if ((fieldsep = strchr(cp = fieldsep, ':')) == NULL)
+ debug_return_int(yp ? NSS_STR_PARSE_SUCCESS : NSS_STR_PARSE_PARSE);
+ *fieldsep++ = '\0';
+ id = sudo_strtoid(cp, &errstr);
+ if (errstr != NULL) {
+ /*
+ * A range error is always a fatal error, but ignore garbage
+ * at the end of YP entries since it has no meaning.
+ */
+ if (errno == ERANGE)
+ debug_return_int(NSS_STR_PARSE_ERANGE);
+ debug_return_int(yp ? NSS_STR_PARSE_SUCCESS : NSS_STR_PARSE_PARSE);
+ }
+#ifdef GID_NOBODY
+ /* Negative gids get mapped to nobody on Solaris. */
+ if (*cp == '-' && id != 0)
+ grp->gr_gid = GID_NOBODY;
+ else
+#endif
+ grp->gr_gid = (gid_t)id;
+
+ /* Store group members, taking care to use proper alignment. */
+ grp->gr_mem = NULL;
+ if (*fieldsep != '\0') {
+ grp->gr_mem = gr_mem = (char **)ALIGN(buf + inlen + 1);
+ gr_end = (char **)((unsigned long)(buf + buflen) & ~ALIGNBYTES) - 1;
+ for (;;) {
+ if (gr_mem >= gr_end)
+ debug_return_int(NSS_STR_PARSE_ERANGE); /* out of space! */
+ *gr_mem++ = cp;
+ if (fieldsep == NULL)
+ break;
+ if ((fieldsep = strchr(cp = fieldsep, ',')) != NULL)
+ *fieldsep++ = '\0';
+ }
+ *gr_mem = NULL;
+ }
+ debug_return_int(NSS_STR_PARSE_SUCCESS);
+}
+
+static nss_status_t
+process_cstr(const char *instr, int inlen, struct nss_groupsbymem *gbm,
+ int dynamic)
+{
+ const char *user = gbm->username;
+ nss_status_t ret = NSS_NOTFOUND;
+ nss_XbyY_buf_t *buf;
+ struct group *grp;
+ char **gr_mem;
+ int error, i;
+ debug_decl(process_cstr, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: parsing %.*s", __func__,
+ inlen, instr);
+
+ /* Hack to let us check whether the query was handled by nscd or us. */
+ if (gbm->force_slow_way != 0)
+ gbm->force_slow_way = 2;
+
+ buf = _nss_XbyY_buf_alloc(sizeof(struct group), NSS_BUFLEN_GROUP);
+ if (buf == NULL)
+ debug_return_int(NSS_UNAVAIL);
+
+ /* Parse groups file string -> struct group. */
+ grp = buf->result;
+ error = (*gbm->str2ent)(instr, inlen, grp, buf->buffer, buf->buflen);
+ if (error != NSS_STR_PARSE_SUCCESS || grp->gr_mem == NULL)
+ goto done;
+
+ for (gr_mem = grp->gr_mem; *gr_mem != NULL; gr_mem++) {
+ if (strcmp(*gr_mem, user) == 0) {
+ const int numgids = MIN(gbm->numgids, gbm->maxgids);
+
+ /* Append to gid_array unless gr_gid is a dupe. */
+ for (i = 0; i < numgids; i++) {
+ if (gbm->gid_array[i] == grp->gr_gid)
+ goto done; /* already present */
+ }
+ if (i == gbm->maxgids && dynamic) {
+ GETGROUPS_T *tmp = reallocarray(gbm->gid_array, gbm->maxgids,
+ 2 * sizeof(GETGROUPS_T));
+ if (tmp == NULL) {
+ /* Out of memory, just return what we have. */
+ dynamic = 0;
+ } else {
+ gbm->gid_array = tmp;
+ gbm->maxgids <<= 1;
+ }
+ }
+ /* Store gid if there is space. */
+ if (i < gbm->maxgids)
+ gbm->gid_array[i] = grp->gr_gid;
+ /* Always increment numgids so we can detect when out of space. */
+ gbm->numgids++;
+ goto done;
+ }
+ }
+done:
+ _nss_XbyY_buf_free(buf);
+ debug_return_int(ret);
+}
+
+static nss_status_t
+process_cstr_static(const char *instr, int inlen, struct nss_groupsbymem *gbm)
+{
+ return process_cstr(instr, inlen, gbm, 0);
+}
+
+static nss_status_t
+process_cstr_dynamic(const char *instr, int inlen, struct nss_groupsbymem *gbm)
+{
+ return process_cstr(instr, inlen, gbm, 1);
+}
+
+/*
+ * Extended getgrouplist(3) using nss_search(3)
+ */
+int
+sudo_getgrouplist2_v1(const char *name, GETGROUPS_T basegid,
+ GETGROUPS_T **groupsp, int *ngroupsp)
+{
+ struct nss_groupsbymem gbm;
+ static DEFINE_NSS_DB_ROOT(db_root);
+ debug_decl(sudo_getgrouplist2, SUDO_DEBUG_UTIL);
+
+ memset(&gbm, 0, sizeof(gbm));
+ gbm.username = name;
+ gbm.gid_array = *groupsp;
+ gbm.maxgids = *ngroupsp;
+ gbm.numgids = 1; /* for basegid */
+ gbm.force_slow_way = 1;
+ gbm.str2ent = str2grp;
+
+ if (gbm.gid_array == NULL) {
+ /* Dynamically-sized group vector. */
+ gbm.maxgids = (int)sysconf(_SC_NGROUPS_MAX);
+ if (gbm.maxgids < 0)
+ gbm.maxgids = NGROUPS_MAX;
+ gbm.gid_array = reallocarray(NULL, gbm.maxgids, 4 * sizeof(GETGROUPS_T));
+ if (gbm.gid_array == NULL)
+ debug_return_int(-1);
+ gbm.maxgids <<= 2;
+ gbm.process_cstr = process_cstr_dynamic;
+ } else {
+ /* Static group vector. */
+ if (gbm.maxgids <= 0)
+ debug_return_int(-1);
+ gbm.process_cstr = process_cstr_static;
+ }
+
+ /* We support BSD semantics where the first element is the base gid */
+ gbm.gid_array[0] = basegid;
+
+ /*
+ * Can't use nss_search return value since it may return NSS_UNAVAIL
+ * when no nsswitch.conf entry (e.g. compat mode).
+ */
+ for (;;) {
+ GETGROUPS_T *tmp;
+
+ (void)nss_search(&db_root, _nss_initf_group, NSS_DBOP_GROUP_BYMEMBER,
+ &gbm);
+
+ /*
+ * If this was a statically-sized group vector or nscd was not used
+ * we are done.
+ */
+ if (gbm.process_cstr != process_cstr_dynamic || gbm.force_slow_way == 2)
+ break;
+
+ /*
+ * If gid_array is full and the query was handled by nscd, there
+ * may be more data, so double gid_array and try again.
+ */
+ if (gbm.numgids != gbm.maxgids)
+ break;
+
+ tmp = reallocarray(gbm.gid_array, gbm.maxgids, 2 * sizeof(GETGROUPS_T));
+ if (tmp == NULL) {
+ free(gbm.gid_array);
+ debug_return_int(-1);
+ }
+ gbm.gid_array = tmp;
+ gbm.maxgids <<= 1;
+ }
+
+ /* Note: we can only detect a too-small group list if nscd is not used. */
+ *groupsp = gbm.gid_array;
+ if (gbm.numgids <= gbm.maxgids) {
+ *ngroupsp = gbm.numgids;
+ debug_return_int(0);
+ }
+ *ngroupsp = gbm.maxgids;
+ debug_return_int(-1);
+}
+
+#else /* !HAVE_GETGROUPLIST && !HAVE_GETGRSET && !HAVE__GETGROUPSBYMEMBER */
+
+/*
+ * Extended getgrouplist(3) using getgrent(3)
+ */
+int
+sudo_getgrouplist2_v1(const char *name, GETGROUPS_T basegid,
+ GETGROUPS_T **groupsp, int *ngroupsp)
+{
+ GETGROUPS_T *groups = *groupsp;
+ int grpsize = *ngroupsp;
+ int i, ngroups = 1;
+ int ret = -1;
+ struct group *grp;
+ debug_decl(sudo_getgrouplist2, SUDO_DEBUG_UTIL);
+
+ if (groups == NULL) {
+ /* Dynamically-sized group vector. */
+ grpsize = (int)sysconf(_SC_NGROUPS_MAX);
+ if (grpsize < 0)
+ grpsize = NGROUPS_MAX;
+ groups = reallocarray(NULL, grpsize, 4 * sizeof(*groups));
+ if (groups == NULL)
+ debug_return_int(-1);
+ grpsize <<= 2;
+ } else {
+ /* Static group vector. */
+ if (grpsize < 1)
+ debug_return_int(-1);
+ }
+
+ /* We support BSD semantics where the first element is the base gid */
+ groups[0] = basegid;
+
+ setgrent();
+ while ((grp = getgrent()) != NULL) {
+ if (grp->gr_gid == basegid || grp->gr_mem == NULL)
+ continue;
+
+ for (i = 0; grp->gr_mem[i] != NULL; i++) {
+ if (strcmp(name, grp->gr_mem[i]) == 0)
+ break;
+ }
+ if (grp->gr_mem[i] == NULL)
+ continue; /* user not found */
+
+ /* Only add if it is not the same as an existing gid */
+ for (i = 0; i < ngroups; i++) {
+ if (grp->gr_gid == groups[i])
+ break;
+ }
+ if (i == ngroups) {
+ if (ngroups == grpsize) {
+ GETGROUPS_T *tmp;
+
+ if (*groupsp != NULL) {
+ /* Static group vector. */
+ goto done;
+ }
+ tmp = reallocarray(groups, grpsize, 2 * sizeof(*groups));
+ if (tmp == NULL) {
+ free(groups);
+ groups = NULL;
+ ngroups = 0;
+ goto done;
+ }
+ groups = tmp;
+ grpsize <<= 1;
+ }
+ groups[ngroups++] = grp->gr_gid;
+ }
+ }
+ ret = 0;
+
+done:
+ endgrent();
+ *groupsp = groups;
+ *ngroupsp = ngroups;
+
+ debug_return_int(ret);
+}
+#endif /* !HAVE_GETGROUPLIST && !HAVE_GETGRSET && !HAVE__GETGROUPSBYMEMBER */
diff --git a/lib/util/gethostname.c b/lib/util/gethostname.c
new file mode 100644
index 0000000..34f714b
--- /dev/null
+++ b/lib/util/gethostname.c
@@ -0,0 +1,59 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+/*
+ * Return a malloc()ed copy of the system hostname, or NULL if
+ * malloc() or gethostname() fails.
+ */
+char *
+sudo_gethostname_v1(void)
+{
+ char *hname;
+ size_t host_name_max;
+
+#ifdef _SC_HOST_NAME_MAX
+ host_name_max = (size_t)sysconf(_SC_HOST_NAME_MAX);
+ if (host_name_max == (size_t)-1)
+#endif
+ host_name_max = 255; /* POSIX and historic BSD */
+
+ hname = malloc(host_name_max + 1);
+ if (hname != NULL) {
+ if (gethostname(hname, host_name_max + 1) == 0 && *hname != '\0') {
+ /* Old gethostname() may not NUL-terminate if there is no room. */
+ hname[host_name_max] = '\0';
+ } else {
+ free(hname);
+ hname = NULL;
+ }
+ }
+ return hname;
+}
diff --git a/lib/util/getopt_long.c b/lib/util/getopt_long.c
new file mode 100644
index 0000000..04f6d47
--- /dev/null
+++ b/lib/util/getopt_long.c
@@ -0,0 +1,624 @@
+/* $OpenBSD: getopt_long.c,v 1.26 2013/06/08 22:47:56 millert Exp $ */
+/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
+/* $FreeBSD: head/lib/libc/stdlib/getopt_long.c 236936 2012-06-11 22:25:20Z delphij $ */
+
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2002 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <compat/getopt.h>
+
+#define GNU_COMPATIBLE /* Be more compatible with GNU getopt. */
+
+#ifdef REPLACE_GETOPT
+int opterr = 1; /* if error message should be printed */
+int optind = 1; /* index into parent argv vector */
+int optopt = '?'; /* character checked for validity */
+char *optarg; /* argument associated with option */
+#else
+extern int opterr; /* if error message should be printed */
+extern int optind; /* index into parent argv vector */
+extern int optopt; /* character checked for validity */
+extern char *optarg; /* argument associated with option */
+#endif
+#if !defined(REPLACE_GETOPT) && !defined(HAVE_OPTRESET)
+int optreset; /* reset getopt */
+#endif
+
+#define PRINT_ERROR ((opterr) && (*options != ':'))
+
+#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
+#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
+#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
+
+/* return values */
+#define BADCH (int)'?'
+#define BADARG ((*options == ':') ? (int)':' : (int)'?')
+#define INORDER (int)1
+
+#define EMSG (char *)""
+
+#ifdef GNU_COMPATIBLE
+#define NO_PREFIX (-1)
+#define D_PREFIX 0
+#define DD_PREFIX 1
+#define W_PREFIX 2
+#endif
+
+static int getopt_internal(int, char * const *, const char *,
+ const struct option *, int *, int);
+static int parse_long_options(char * const *, const char *,
+ const struct option *, int *, int, int);
+static int gcd(int, int);
+static void permute_args(int, int, int, char * const *);
+
+static char *place = EMSG; /* option letter processing */
+
+/* XXX: set optreset to 1 rather than these two */
+static int nonopt_start = -1; /* first non option argument (for permute) */
+static int nonopt_end = -1; /* first option after non options (for permute) */
+
+/* Error messages */
+static const char recargchar[] = "option requires an argument -- %c";
+static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */
+#ifdef GNU_COMPATIBLE
+static int dash_prefix = NO_PREFIX;
+static const char gnuoptchar[] = "invalid option -- %c";
+
+static const char recargstring[] = "option `%s%s' requires an argument";
+static const char ambig[] = "option `%s%.*s' is ambiguous";
+static const char noarg[] = "option `%s%.*s' doesn't allow an argument";
+static const char illoptstring[] = "unrecognized option `%s%s'";
+#else
+static const char recargstring[] = "option requires an argument -- %s";
+static const char ambig[] = "ambiguous option -- %.*s";
+static const char noarg[] = "option doesn't take an argument -- %.*s";
+static const char illoptstring[] = "unknown option -- %s";
+#endif
+
+/*
+ * Compute the greatest common divisor of a and b.
+ */
+static int
+gcd(int a, int b)
+{
+ int c;
+
+ c = a % b;
+ while (c != 0) {
+ a = b;
+ b = c;
+ c = a % b;
+ }
+
+ return (b);
+}
+
+/*
+ * Exchange the block from nonopt_start to nonopt_end with the block
+ * from nonopt_end to opt_end (keeping the same order of arguments
+ * in each block).
+ */
+static void
+permute_args(int panonopt_start, int panonopt_end, int opt_end,
+ char * const *nargv)
+{
+ int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
+ char *swap;
+
+ /*
+ * compute lengths of blocks and number and size of cycles
+ */
+ nnonopts = panonopt_end - panonopt_start;
+ nopts = opt_end - panonopt_end;
+ ncycle = gcd(nnonopts, nopts);
+ cyclelen = (opt_end - panonopt_start) / ncycle;
+
+ for (i = 0; i < ncycle; i++) {
+ cstart = panonopt_end+i;
+ pos = cstart;
+ for (j = 0; j < cyclelen; j++) {
+ if (pos >= panonopt_end)
+ pos -= nnonopts;
+ else
+ pos += nopts;
+ swap = nargv[pos];
+ /* LINTED const cast */
+ ((char **) nargv)[pos] = nargv[cstart];
+ /* LINTED const cast */
+ ((char **)nargv)[cstart] = swap;
+ }
+ }
+}
+
+/*
+ * parse_long_options --
+ * Parse long options in argc/argv argument vector.
+ * Returns -1 if short_too is set and the option does not match long_options.
+ */
+static int
+parse_long_options(char * const *nargv, const char *options,
+ const struct option *long_options, int *idx, int short_too, int flags)
+{
+ char *current_argv, *has_equal;
+#ifdef GNU_COMPATIBLE
+ const char *current_dash;
+#endif
+ size_t current_argv_len;
+ int i, match, exact_match, second_partial_match;
+
+ current_argv = place;
+#ifdef GNU_COMPATIBLE
+ switch (dash_prefix) {
+ case D_PREFIX:
+ current_dash = "-";
+ break;
+ case DD_PREFIX:
+ current_dash = "--";
+ break;
+ case W_PREFIX:
+ current_dash = "-W ";
+ break;
+ default:
+ current_dash = "";
+ break;
+ }
+#endif
+ match = -1;
+ exact_match = 0;
+ second_partial_match = 0;
+
+ optind++;
+
+ if ((has_equal = strchr(current_argv, '=')) != NULL) {
+ /* argument found (--option=arg) */
+ current_argv_len = has_equal - current_argv;
+ has_equal++;
+ } else
+ current_argv_len = strlen(current_argv);
+
+ for (i = 0; long_options[i].name; i++) {
+ /* find matching long option */
+ if (strncmp(current_argv, long_options[i].name,
+ current_argv_len))
+ continue;
+
+ if (strlen(long_options[i].name) == current_argv_len) {
+ /* exact match */
+ match = i;
+ exact_match = 1;
+ break;
+ }
+ /*
+ * If this is a known short option, don't allow
+ * a partial match of a single character.
+ */
+ if (short_too && current_argv_len == 1)
+ continue;
+
+ if (match == -1) /* first partial match */
+ match = i;
+ else if ((flags & FLAG_LONGONLY) ||
+ long_options[i].has_arg !=
+ long_options[match].has_arg ||
+ long_options[i].flag != long_options[match].flag ||
+ long_options[i].val != long_options[match].val)
+ second_partial_match = 1;
+ }
+ if (!exact_match && second_partial_match) {
+ /* ambiguous abbreviation */
+ if (PRINT_ERROR)
+ sudo_warnx(ambig,
+#ifdef GNU_COMPATIBLE
+ current_dash,
+#endif
+ (int)current_argv_len,
+ current_argv);
+ optopt = 0;
+ return (BADCH);
+ }
+ if (match != -1) { /* option found */
+ if (long_options[match].has_arg == no_argument
+ && has_equal) {
+ if (PRINT_ERROR)
+ sudo_warnx(noarg,
+#ifdef GNU_COMPATIBLE
+ current_dash,
+#endif
+ (int)current_argv_len,
+ current_argv);
+ /*
+ * XXX: GNU sets optopt to val regardless of flag
+ */
+ if (long_options[match].flag == NULL)
+ optopt = long_options[match].val;
+ else
+ optopt = 0;
+#ifdef GNU_COMPATIBLE
+ return (BADCH);
+#else
+ return (BADARG);
+#endif
+ }
+ if (long_options[match].has_arg == required_argument ||
+ long_options[match].has_arg == optional_argument) {
+ if (has_equal)
+ optarg = has_equal;
+ else if (long_options[match].has_arg ==
+ required_argument) {
+ /*
+ * optional argument doesn't use next nargv
+ */
+ optarg = nargv[optind++];
+ }
+ }
+ if ((long_options[match].has_arg == required_argument)
+ && (optarg == NULL)) {
+ /*
+ * Missing argument; leading ':' indicates no error
+ * should be generated.
+ */
+ if (PRINT_ERROR)
+ sudo_warnx(recargstring,
+#ifdef GNU_COMPATIBLE
+ current_dash,
+#endif
+ current_argv);
+ /*
+ * XXX: GNU sets optopt to val regardless of flag
+ */
+ if (long_options[match].flag == NULL)
+ optopt = long_options[match].val;
+ else
+ optopt = 0;
+ --optind;
+ return (BADARG);
+ }
+ } else { /* unknown option */
+ if (short_too) {
+ --optind;
+ return (-1);
+ }
+ if (PRINT_ERROR)
+ sudo_warnx(illoptstring,
+#ifdef GNU_COMPATIBLE
+ current_dash,
+#endif
+ current_argv);
+ optopt = 0;
+ return (BADCH);
+ }
+ if (idx)
+ *idx = match;
+ if (long_options[match].flag) {
+ *long_options[match].flag = long_options[match].val;
+ return (0);
+ } else
+ return (long_options[match].val);
+}
+
+/*
+ * getopt_internal --
+ * Parse argc/argv argument vector. Called by user level routines.
+ */
+static int
+getopt_internal(int nargc, char * const *nargv, const char *options,
+ const struct option *long_options, int *idx, int flags)
+{
+ char *oli; /* option letter list index */
+ int optchar, short_too;
+ int posixly_correct; /* no static, can be changed on the fly */
+
+ if (options == NULL)
+ return (-1);
+
+ /*
+ * Disable GNU extensions if POSIXLY_CORRECT is set or options
+ * string begins with a '+'.
+ */
+ posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+#ifdef GNU_COMPATIBLE
+ if (*options == '-')
+ flags |= FLAG_ALLARGS;
+ else if (posixly_correct || *options == '+')
+ flags &= ~FLAG_PERMUTE;
+#else
+ if (posixly_correct || *options == '+')
+ flags &= ~FLAG_PERMUTE;
+ else if (*options == '-')
+ flags |= FLAG_ALLARGS;
+#endif
+ if (*options == '+' || *options == '-')
+ options++;
+
+ /*
+ * XXX Some GNU programs (like cvs) set optind to 0 instead of
+ * XXX using optreset. Work around this braindamage.
+ */
+ if (optind == 0)
+ optind = optreset = 1;
+
+ optarg = NULL;
+ if (optreset)
+ nonopt_start = nonopt_end = -1;
+start:
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc) { /* end of argument vector */
+ place = EMSG;
+ if (nonopt_end != -1) {
+ /* do permutation, if we have to */
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ else if (nonopt_start != -1) {
+ /*
+ * If we skipped non-options, set optind
+ * to the first of them.
+ */
+ optind = nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ return (-1);
+ }
+ if (*(place = nargv[optind]) != '-' ||
+#ifdef GNU_COMPATIBLE
+ place[1] == '\0') {
+#else
+ (place[1] == '\0' && strchr(options, '-') == NULL)) {
+#endif
+ place = EMSG; /* found non-option */
+ if (flags & FLAG_ALLARGS) {
+ /*
+ * GNU extension:
+ * return non-option as argument to option 1
+ */
+ optarg = nargv[optind++];
+ return (INORDER);
+ }
+ if (!(flags & FLAG_PERMUTE)) {
+ /*
+ * If no permutation wanted, stop parsing
+ * at first non-option.
+ */
+ return (-1);
+ }
+ /* do permutation */
+ if (nonopt_start == -1)
+ nonopt_start = optind;
+ else if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ nonopt_start = optind -
+ (nonopt_end - nonopt_start);
+ nonopt_end = -1;
+ }
+ optind++;
+ /* process next argument */
+ goto start;
+ }
+ if (nonopt_start != -1 && nonopt_end == -1)
+ nonopt_end = optind;
+
+ /*
+ * If we have "-" do nothing, if "--" we are done.
+ */
+ if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
+ optind++;
+ place = EMSG;
+ /*
+ * We found an option (--), so if we skipped
+ * non-options, we have to permute.
+ */
+ if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ return (-1);
+ }
+ }
+
+ /*
+ * Check long options if:
+ * 1) we were passed some
+ * 2) the arg is not just "-"
+ * 3) either the arg starts with -- we are getopt_long_only()
+ */
+ if (long_options != NULL && place != nargv[optind] &&
+ (*place == '-' || (flags & FLAG_LONGONLY))) {
+ short_too = 0;
+#ifdef GNU_COMPATIBLE
+ dash_prefix = D_PREFIX;
+#endif
+ if (*place == '-') {
+ place++; /* --foo long option */
+#ifdef GNU_COMPATIBLE
+ dash_prefix = DD_PREFIX;
+#endif
+ } else if (*place != ':' && strchr(options, *place) != NULL)
+ short_too = 1; /* could be short option too */
+
+ optchar = parse_long_options(nargv, options, long_options,
+ idx, short_too, flags);
+ if (optchar != -1) {
+ place = EMSG;
+ return (optchar);
+ }
+ }
+
+ if ((optchar = (int)*place++) == (int)':' ||
+ (optchar == (int)'-' && *place != '\0') ||
+ (oli = strchr(options, optchar)) == NULL) {
+ /*
+ * If the user specified "-" and '-' isn't listed in
+ * options, return -1 (non-option) as per POSIX.
+ * Otherwise, it is an unknown option character (or ':').
+ */
+ if (optchar == (int)'-' && *place == '\0')
+ return (-1);
+ if (!*place)
+ ++optind;
+#ifdef GNU_COMPATIBLE
+ if (PRINT_ERROR)
+ sudo_warnx(posixly_correct ? illoptchar : gnuoptchar,
+ optchar);
+#else
+ if (PRINT_ERROR)
+ sudo_warnx(illoptchar, optchar);
+#endif
+ optopt = optchar;
+ return (BADCH);
+ }
+ if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
+ /* -W long-option */
+ if (*place) /* no space */
+ /* NOTHING */;
+ else if (++optind >= nargc) { /* no arg */
+ place = EMSG;
+ if (PRINT_ERROR)
+ sudo_warnx(recargchar, optchar);
+ optopt = optchar;
+ return (BADARG);
+ } else /* white space */
+ place = nargv[optind];
+#ifdef GNU_COMPATIBLE
+ dash_prefix = W_PREFIX;
+#endif
+ optchar = parse_long_options(nargv, options, long_options,
+ idx, 0, flags);
+ place = EMSG;
+ return (optchar);
+ }
+ if (*++oli != ':') { /* doesn't take argument */
+ if (!*place)
+ ++optind;
+ } else { /* takes (optional) argument */
+ optarg = NULL;
+ if (*place) /* no white space */
+ optarg = place;
+ else if (oli[1] != ':') { /* arg not optional */
+ if (++optind >= nargc) { /* no arg */
+ place = EMSG;
+ if (PRINT_ERROR)
+ sudo_warnx(recargchar, optchar);
+ optopt = optchar;
+ return (BADARG);
+ } else
+ optarg = nargv[optind];
+ }
+ place = EMSG;
+ ++optind;
+ }
+ /* dump back option letter */
+ return (optchar);
+}
+
+#ifdef REPLACE_GETOPT
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ */
+int
+sudo_getopt(int nargc, char * const *nargv, const char *options)
+{
+
+ /*
+ * We don't pass FLAG_PERMUTE to getopt_internal() since
+ * the BSD getopt(3) (unlike GNU) has never done this.
+ *
+ * Furthermore, since many privileged programs call getopt()
+ * before dropping privileges it makes sense to keep things
+ * as simple (and bug-free) as possible.
+ */
+ return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
+}
+#endif /* REPLACE_GETOPT */
+
+/*
+ * getopt_long --
+ * Parse argc/argv argument vector.
+ */
+int
+sudo_getopt_long(int nargc, char * const *nargv, const char *options,
+ const struct option *long_options, int *idx)
+{
+
+ return (getopt_internal(nargc, nargv, options, long_options, idx,
+ FLAG_PERMUTE));
+}
+
+/*
+ * getopt_long_only --
+ * Parse argc/argv argument vector.
+ */
+int
+sudo_getopt_long_only(int nargc, char * const *nargv, const char *options,
+ const struct option *long_options, int *idx)
+{
+
+ return (getopt_internal(nargc, nargv, options, long_options, idx,
+ FLAG_PERMUTE|FLAG_LONGONLY));
+}
diff --git a/lib/util/gettime.c b/lib/util/gettime.c
new file mode 100644
index 0000000..54fbcb3
--- /dev/null
+++ b/lib/util/gettime.c
@@ -0,0 +1,224 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2014-2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+#if defined(__MACH__) && !defined(HAVE_CLOCK_GETTIME)
+# include <mach/mach.h>
+# include <mach/mach_time.h>
+# include <mach/clock.h>
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+
+/*
+ * On Linux and FreeBSD, CLOCK_MONOTONIC does not run while sleeping.
+ * Linux provides CLOCK_BOOTTIME which runs while sleeping (FreeBSD does not).
+ * Some systems provide CLOCK_UPTIME which only runs while awake.
+ */
+#if defined(CLOCK_BOOTTIME)
+# define SUDO_CLOCK_BOOTTIME CLOCK_BOOTTIME
+#elif defined(CLOCK_MONOTONIC_RAW)
+# define SUDO_CLOCK_BOOTTIME CLOCK_MONOTONIC_RAW
+#elif defined(CLOCK_MONOTONIC)
+# define SUDO_CLOCK_BOOTTIME CLOCK_MONOTONIC
+#endif
+#if defined(CLOCK_UPTIME_RAW)
+# define SUDO_CLOCK_UPTIME CLOCK_UPTIME_RAW
+#elif defined(CLOCK_UPTIME)
+# define SUDO_CLOCK_UPTIME CLOCK_UPTIME
+#elif defined(CLOCK_MONOTONIC)
+# define SUDO_CLOCK_UPTIME CLOCK_MONOTONIC
+#endif
+
+/*
+ * Wall clock time, may run backward.
+ */
+#if defined(HAVE_CLOCK_GETTIME)
+int
+sudo_gettime_real_v1(struct timespec *ts)
+{
+ debug_decl(sudo_gettime_real, SUDO_DEBUG_UTIL);
+
+ if (clock_gettime(CLOCK_REALTIME, ts) == -1) {
+ struct timeval tv;
+
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "clock_gettime(CLOCK_REALTIME) failed, trying gettimeofday()");
+ if (gettimeofday(&tv, NULL) == -1)
+ debug_return_int(-1);
+ TIMEVAL_TO_TIMESPEC(&tv, ts);
+ }
+ debug_return_int(0);
+}
+#else
+int
+sudo_gettime_real_v1(struct timespec *ts)
+{
+ struct timeval tv;
+ debug_decl(sudo_gettime_real, SUDO_DEBUG_UTIL);
+
+ if (gettimeofday(&tv, NULL) == -1)
+ debug_return_int(-1);
+ TIMEVAL_TO_TIMESPEC(&tv, ts);
+ debug_return_int(0);
+}
+#endif
+
+/*
+ * Monotonic time, only runs forward.
+ * We use a timer that only increments while sleeping, if possible.
+ */
+#if defined(HAVE_CLOCK_GETTIME) && defined(SUDO_CLOCK_BOOTTIME)
+int
+sudo_gettime_mono_v1(struct timespec *ts)
+{
+ static int has_monoclock = -1;
+ debug_decl(sudo_gettime_mono, SUDO_DEBUG_UTIL);
+
+ /* Check whether the kernel/libc actually supports a monotonic clock. */
+# ifdef _SC_MONOTONIC_CLOCK
+ if (has_monoclock == -1)
+ has_monoclock = sysconf(_SC_MONOTONIC_CLOCK) != -1;
+# endif
+ if (!has_monoclock)
+ debug_return_int(sudo_gettime_real(ts));
+ if (clock_gettime(SUDO_CLOCK_BOOTTIME, ts) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "clock_gettime(%d) failed, using wall clock",
+ (int)SUDO_CLOCK_BOOTTIME);
+ has_monoclock = 0;
+ debug_return_int(sudo_gettime_real(ts));
+ }
+ debug_return_int(0);
+}
+#elif defined(HAVE_GETHRTIME)
+int
+sudo_gettime_mono_v1(struct timespec *ts)
+{
+ hrtime_t nsec;
+ debug_decl(sudo_gettime_mono, SUDO_DEBUG_UTIL);
+
+ nsec = gethrtime();
+ ts->tv_sec = nsec / 1000000000;
+ ts->tv_nsec = nsec % 1000000000;
+ debug_return_int(0);
+}
+#elif defined(__MACH__)
+int
+sudo_gettime_mono_v1(struct timespec *ts)
+{
+ uint64_t abstime, nsec;
+ static mach_timebase_info_data_t timebase_info;
+ debug_decl(sudo_gettime_mono, SUDO_DEBUG_UTIL);
+
+ if (timebase_info.denom == 0)
+ (void) mach_timebase_info(&timebase_info);
+#ifdef HAVE_MACH_CONTINUOUS_TIME
+ abstime = mach_continuous_time(); /* runs while asleep */
+#else
+ abstime = mach_absolute_time(); /* doesn't run while asleep */
+#endif
+ nsec = abstime * timebase_info.numer / timebase_info.denom;
+ ts->tv_sec = nsec / 1000000000;
+ ts->tv_nsec = nsec % 1000000000;
+ debug_return_int(0);
+}
+#else
+int
+sudo_gettime_mono_v1(struct timespec *ts)
+{
+ /* No monotonic clock available, use wall clock. */
+ return sudo_gettime_real(ts);
+}
+#endif
+
+/*
+ * Monotonic time, only runs forward.
+ * We use a timer that only increments while awake, if possible.
+ */
+#if defined(HAVE_CLOCK_GETTIME) && defined(SUDO_CLOCK_UPTIME)
+int
+sudo_gettime_awake_v1(struct timespec *ts)
+{
+ static int has_monoclock = -1;
+ debug_decl(sudo_gettime_awake, SUDO_DEBUG_UTIL);
+
+ /* Check whether the kernel/libc actually supports a monotonic clock. */
+# ifdef _SC_MONOTONIC_CLOCK
+ if (has_monoclock == -1)
+ has_monoclock = sysconf(_SC_MONOTONIC_CLOCK) != -1;
+# endif
+ if (!has_monoclock)
+ debug_return_int(sudo_gettime_real(ts));
+ if (clock_gettime(SUDO_CLOCK_UPTIME, ts) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "clock_gettime(%d) failed, using wall clock",
+ (int)SUDO_CLOCK_UPTIME);
+ has_monoclock = 0;
+ debug_return_int(sudo_gettime_real(ts));
+ }
+ debug_return_int(0);
+}
+#elif defined(HAVE_GETHRTIME)
+int
+sudo_gettime_awake_v1(struct timespec *ts)
+{
+ hrtime_t nsec;
+ debug_decl(sudo_gettime_awake, SUDO_DEBUG_UTIL);
+
+ /* Currently the same as sudo_gettime_mono() */
+ nsec = gethrtime();
+ ts->tv_sec = nsec / 1000000000;
+ ts->tv_nsec = nsec % 1000000000;
+ debug_return_int(0);
+}
+#elif defined(__MACH__)
+int
+sudo_gettime_awake_v1(struct timespec *ts)
+{
+ uint64_t abstime, nsec;
+ static mach_timebase_info_data_t timebase_info;
+ debug_decl(sudo_gettime_awake, SUDO_DEBUG_UTIL);
+
+ if (timebase_info.denom == 0)
+ (void) mach_timebase_info(&timebase_info);
+ abstime = mach_absolute_time();
+ nsec = abstime * timebase_info.numer / timebase_info.denom;
+ ts->tv_sec = nsec / 1000000000;
+ ts->tv_nsec = nsec % 1000000000;
+ debug_return_int(0);
+}
+#else
+int
+sudo_gettime_awake_v1(struct timespec *ts)
+{
+ /* No monotonic uptime clock available, use wall clock. */
+ return sudo_gettime_real(ts);
+}
+#endif
diff --git a/lib/util/getusershell.c b/lib/util/getusershell.c
new file mode 100644
index 0000000..05bbc44
--- /dev/null
+++ b/lib/util/getusershell.c
@@ -0,0 +1,145 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+
+#ifdef TESTSUDOERS
+# include <tsgetgrpw.h>
+#endif
+
+static const char *shellfile = "/etc/shell";
+static char **allowed_shells, * const *current_shell;
+static const char *default_shells[] = {
+ "/bin/sh",
+ "/bin/ksh",
+ "/bin/ksh93",
+ "/bin/bash",
+ "/bin/dash",
+ "/bin/zsh",
+ "/bin/csh",
+ "/bin/tcsh",
+ NULL
+};
+
+static char **
+read_shells(void)
+{
+ size_t maxshells = 16, nshells = 0;
+ size_t linesize = 0;
+ char *line = NULL;
+ FILE *fp;
+ debug_decl(read_shells, SUDO_DEBUG_UTIL);
+
+ if ((fp = fopen(shellfile, "r")) == NULL)
+ goto bad;
+
+ free(allowed_shells);
+ allowed_shells = reallocarray(NULL, maxshells, sizeof(char *));
+ if (allowed_shells == NULL)
+ goto bad;
+
+ while (sudo_parseln(&line, &linesize, NULL, fp, PARSELN_CONT_IGN) != -1) {
+ if (nshells + 1 >= maxshells) {
+ char **new_shells;
+
+ new_shells = reallocarray(NULL, maxshells + 16, sizeof(char *));
+ if (new_shells == NULL)
+ goto bad;
+ allowed_shells = new_shells;
+ maxshells += 16;
+ }
+ if ((allowed_shells[nshells] = strdup(line)) == NULL)
+ goto bad;
+ nshells++;
+ }
+ allowed_shells[nshells] = NULL;
+
+ free(line);
+ fclose(fp);
+ debug_return_ptr(allowed_shells);
+bad:
+ free(line);
+ if (fp != NULL)
+ fclose(fp);
+ while (nshells != 0)
+ free(allowed_shells[--nshells]);
+ free(allowed_shells);
+ allowed_shells = NULL;
+ debug_return_ptr(default_shells);
+}
+
+void
+sudo_setusershell(void)
+{
+ debug_decl(setusershell, SUDO_DEBUG_UTIL);
+
+ current_shell = read_shells();
+
+ debug_return;
+}
+
+void
+sudo_endusershell(void)
+{
+ debug_decl(endusershell, SUDO_DEBUG_UTIL);
+
+ if (allowed_shells != NULL) {
+ char **shell;
+
+ for (shell = allowed_shells; *shell != NULL; shell++)
+ free(*shell);
+ free(allowed_shells);
+ allowed_shells = NULL;
+ }
+ current_shell = NULL;
+
+ debug_return;
+}
+
+char *
+sudo_getusershell(void)
+{
+ debug_decl(getusershell, SUDO_DEBUG_UTIL);
+
+ if (current_shell == NULL)
+ current_shell = read_shells();
+
+ debug_return_str(*current_shell++);
+}
+
+#ifdef TESTSUDOERS
+void
+testsudoers_setshellfile(const char *file)
+{
+ testsudoers_endusershell();
+ shellfile = file;
+}
+#endif /* TESTSUDOERS */
diff --git a/lib/util/gidlist.c b/lib/util/gidlist.c
new file mode 100644
index 0000000..efcb7df
--- /dev/null
+++ b/lib/util/gidlist.c
@@ -0,0 +1,87 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <grp.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_util.h>
+
+/*
+ * Parse a comma-separated list of gids into an allocated array of GETGROUPS_T.
+ * If a pointer to the base gid is specified, it is stored as the first element
+ * in the array.
+ * Returns the number of gids in the allocated array.
+ */
+int
+sudo_parse_gids_v1(const char *gidstr, const gid_t *basegid, GETGROUPS_T **gidsp)
+{
+ int ngids = 0;
+ GETGROUPS_T *gids;
+ const char *cp = gidstr;
+ const char *errstr;
+ char *ep;
+ debug_decl(sudo_parse_gids, SUDO_DEBUG_UTIL);
+
+ /* Count groups. */
+ if (*cp != '\0') {
+ ngids++;
+ do {
+ if (*cp++ == ',')
+ ngids++;
+ } while (*cp != '\0');
+ }
+ /* Base gid is optional. */
+ if (basegid != NULL)
+ ngids++;
+ /* Allocate and fill in array. */
+ if (ngids != 0) {
+ gids = reallocarray(NULL, (size_t)ngids, sizeof(GETGROUPS_T));
+ if (gids == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(-1);
+ }
+ ngids = 0;
+ if (basegid != NULL)
+ gids[ngids++] = *basegid;
+ cp = gidstr;
+ do {
+ gids[ngids] = (GETGROUPS_T) sudo_strtoidx(cp, ",", &ep, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), cp, U_(errstr));
+ free(gids);
+ debug_return_int(-1);
+ }
+ if (basegid == NULL || gids[ngids] != *basegid)
+ ngids++;
+ cp = ep + 1;
+ } while (*ep != '\0');
+ *gidsp = gids;
+ }
+ debug_return_int(ngids);
+}
diff --git a/lib/util/glob.c b/lib/util/glob.c
new file mode 100644
index 0000000..d546837
--- /dev/null
+++ b/lib/util/glob.c
@@ -0,0 +1,953 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2008-2014 Todd C. Miller <Todd.Miller@sudo.ws>
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)glob.c 8.3 (Berkeley) 10/13/93
+ */
+
+/*
+ * glob(3) -- a superset of the one defined in POSIX 1003.2.
+ *
+ * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
+ *
+ * Optional extra services, controlled by flags not defined by POSIX:
+ *
+ * GLOB_MAGCHAR:
+ * Set in gl_flags if pattern contained a globbing character.
+ * GLOB_TILDE:
+ * expand ~user/foo to the /home/dir/of/user/foo
+ * GLOB_BRACE:
+ * expand {1,2}{a,b} to 1a 1b 2a 2b
+ * gl_matchc:
+ * Number of matches in the current invocation of glob.
+ */
+
+#include <config.h>
+
+#ifndef HAVE_GLOB
+
+#include <sys/stat.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <limits.h>
+#include <pwd.h>
+
+#include <sudo_compat.h>
+#include <compat/glob.h>
+#include <compat/charclass.h>
+
+#define DOLLAR '$'
+#define DOT '.'
+#define EOS '\0'
+#define LBRACKET '['
+#define NOT '!'
+#define QUESTION '?'
+#define QUOTE '\\'
+#define RANGE '-'
+#define RBRACKET ']'
+#define SEP '/'
+#define STAR '*'
+#define TILDE '~'
+#define UNDERSCORE '_'
+#define LBRACE '{'
+#define RBRACE '}'
+#define SLASH '/'
+#define COMMA ','
+
+#ifndef DEBUG
+
+#define M_QUOTE 0x8000
+#define M_PROTECT 0x4000
+#define M_MASK 0xffff
+#define M_ASCII 0x00ff
+
+typedef unsigned short Char;
+
+#else
+
+#define M_QUOTE 0x80
+#define M_PROTECT 0x40
+#define M_MASK 0xff
+#define M_ASCII 0x7f
+
+typedef char Char;
+
+#endif
+
+
+#define CHAR(c) ((Char)((c)&M_ASCII))
+#define META(c) ((Char)((c)|M_QUOTE))
+#define M_ALL META('*')
+#define M_END META(']')
+#define M_NOT META('!')
+#define M_ONE META('?')
+#define M_RNG META('-')
+#define M_SET META('[')
+#define M_CLASS META(':')
+#define ismeta(c) (((c)&M_QUOTE) != 0)
+
+#define GLOB_LIMIT_MALLOC 65536
+#define GLOB_LIMIT_STAT 2048
+#define GLOB_LIMIT_READDIR 16384
+
+struct glob_lim {
+ size_t glim_malloc;
+ size_t glim_stat;
+ size_t glim_readdir;
+};
+
+static int compare(const void *, const void *);
+static int g_Ctoc(const Char *, char *, size_t);
+static int g_lstat(Char *, struct stat *, glob_t *);
+static DIR *g_opendir(Char *, glob_t *);
+static Char *g_strchr(const Char *, int);
+static int g_strncmp(const Char *, const char *, size_t);
+static int g_stat(Char *, struct stat *, glob_t *);
+static int glob0(const Char *, glob_t *, struct glob_lim *);
+static int glob1(Char *, Char *, glob_t *, struct glob_lim *);
+static int glob2(Char *, Char *, Char *, Char *, Char *, Char *,
+ glob_t *, struct glob_lim *);
+static int glob3(Char *, Char *, Char *, Char *, Char *,
+ Char *, Char *, glob_t *, struct glob_lim *);
+static int globextend(const Char *, glob_t *, struct glob_lim *,
+ struct stat *);
+static const Char *
+ globtilde(const Char *, Char *, size_t, glob_t *);
+static int globexp1(const Char *, glob_t *, struct glob_lim *);
+static int globexp2(const Char *, const Char *, glob_t *,
+ struct glob_lim *);
+static int match(Char *, Char *, Char *);
+#ifdef DEBUG
+static void qprintf(const char *, Char *);
+#endif
+
+int
+sudo_glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
+ glob_t *pglob)
+{
+ const unsigned char *patnext;
+ int c;
+ Char *bufnext, *bufend, patbuf[PATH_MAX];
+ struct glob_lim limit = { 0, 0, 0 };
+
+ patnext = (unsigned char *) pattern;
+ if (!(flags & GLOB_APPEND)) {
+ pglob->gl_pathc = 0;
+ pglob->gl_pathv = NULL;
+ if (!(flags & GLOB_DOOFFS))
+ pglob->gl_offs = 0;
+ }
+ pglob->gl_flags = flags & ~GLOB_MAGCHAR;
+ pglob->gl_errfunc = errfunc;
+ pglob->gl_matchc = 0;
+
+ if (pglob->gl_offs >= SSIZE_MAX || pglob->gl_pathc >= SSIZE_MAX ||
+ pglob->gl_pathc >= SSIZE_MAX - pglob->gl_offs - 1)
+ return GLOB_NOSPACE;
+
+ if (strnlen(pattern, PATH_MAX) == PATH_MAX)
+ return GLOB_NOMATCH;
+
+ bufnext = patbuf;
+ bufend = bufnext + PATH_MAX - 1;
+ if (flags & GLOB_NOESCAPE)
+ while (bufnext < bufend && (c = *patnext++) != EOS)
+ *bufnext++ = c;
+ else {
+ /* Protect the quoted characters. */
+ while (bufnext < bufend && (c = *patnext++) != EOS)
+ if (c == QUOTE) {
+ if ((c = *patnext++) == EOS) {
+ c = QUOTE;
+ --patnext;
+ }
+ *bufnext++ = c | M_PROTECT;
+ } else
+ *bufnext++ = c;
+ }
+ *bufnext = EOS;
+
+ if (flags & GLOB_BRACE)
+ return globexp1(patbuf, pglob, &limit);
+ else
+ return glob0(patbuf, pglob, &limit);
+}
+
+/*
+ * Expand recursively a glob {} pattern. When there is no more expansion
+ * invoke the standard globbing routine to glob the rest of the magic
+ * characters
+ */
+static int
+globexp1(const Char *pattern, glob_t *pglob, struct glob_lim *limitp)
+{
+ const Char* ptr = pattern;
+
+ /* Protect a single {}, for find(1), like csh */
+ if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
+ return glob0(pattern, pglob, limitp);
+
+ if ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL)
+ return globexp2(ptr, pattern, pglob, limitp);
+
+ return glob0(pattern, pglob, limitp);
+}
+
+
+/*
+ * Recursive brace globbing helper. Tries to expand a single brace.
+ * If it succeeds then it invokes globexp1 with the new pattern.
+ * If it fails then it tries to glob the rest of the pattern and returns.
+ */
+static int
+globexp2(const Char *ptr, const Char *pattern, glob_t *pglob,
+ struct glob_lim *limitp)
+{
+ int i, rv;
+ Char *lm, *ls;
+ const Char *pe, *pm, *pl;
+ Char patbuf[PATH_MAX];
+
+ /* copy part up to the brace */
+ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
+ continue;
+ *lm = EOS;
+ ls = lm;
+
+ /* Find the balanced brace */
+ for (i = 0, pe = ++ptr; *pe; pe++)
+ if (*pe == LBRACKET) {
+ /* Ignore everything between [] */
+ for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
+ continue;
+ if (*pe == EOS) {
+ /*
+ * We could not find a matching RBRACKET.
+ * Ignore and just look for RBRACE
+ */
+ pe = pm;
+ }
+ } else if (*pe == LBRACE)
+ i++;
+ else if (*pe == RBRACE) {
+ if (i == 0)
+ break;
+ i--;
+ }
+
+ /* Non matching braces; just glob the pattern */
+ if (i != 0 || *pe == EOS)
+ return glob0(patbuf, pglob, limitp);
+
+ for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
+ switch (*pm) {
+ case LBRACKET:
+ /* Ignore everything between [] */
+ for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
+ continue;
+ if (*pm == EOS) {
+ /*
+ * We could not find a matching RBRACKET.
+ * Ignore and just look for RBRACE
+ */
+ pm = pl;
+ }
+ break;
+
+ case LBRACE:
+ i++;
+ break;
+
+ case RBRACE:
+ if (i) {
+ i--;
+ break;
+ }
+ FALLTHROUGH;
+ case COMMA:
+ if (i && *pm == COMMA)
+ break;
+ else {
+ /* Append the current string */
+ for (lm = ls; (pl < pm); *lm++ = *pl++)
+ continue;
+
+ /*
+ * Append the rest of the pattern after the
+ * closing brace
+ */
+ for (pl = pe + 1; (*lm++ = *pl++) != EOS; )
+ continue;
+
+ /* Expand the current pattern */
+#ifdef DEBUG
+ qprintf("globexp2:", patbuf);
+#endif
+ rv = globexp1(patbuf, pglob, limitp);
+ if (rv && rv != GLOB_NOMATCH)
+ return rv;
+
+ /* move after the comma, to the next string */
+ pl = pm + 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+
+
+/*
+ * expand tilde from the passwd file.
+ */
+static const Char *
+globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
+{
+ struct passwd *pwd;
+ char *h;
+ const Char *p;
+ Char *b, *eb;
+
+ if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
+ return pattern;
+
+ /* Copy up to the end of the string or / */
+ eb = &patbuf[patbuf_len - 1];
+ for (p = pattern + 1, h = (char *) patbuf;
+ h < (char *)eb && *p && *p != SLASH; *h++ = *p++)
+ continue;
+
+ *h = EOS;
+
+ if (((char *) patbuf)[0] == EOS) {
+ /*
+ * handle a plain ~ or ~/ by expanding $HOME
+ * first and then trying the password file
+ */
+ if ((h = getenv("HOME")) == NULL) {
+ if ((pwd = getpwuid(getuid())) == NULL)
+ return pattern;
+ else
+ h = pwd->pw_dir;
+ }
+ } else {
+ /*
+ * Expand a ~user
+ */
+ if ((pwd = getpwnam((char*) patbuf)) == NULL)
+ return pattern;
+ else
+ h = pwd->pw_dir;
+ }
+
+ /* Copy the home directory */
+ for (b = patbuf; b < eb && *h; *b++ = *h++)
+ continue;
+
+ /* Append the rest of the pattern */
+ while (b < eb && (*b++ = *p++) != EOS)
+ continue;
+ *b = EOS;
+
+ return patbuf;
+}
+
+static int
+g_strncmp(const Char *s1, const char *s2, size_t n)
+{
+ int rv = 0;
+
+ while (n--) {
+ rv = *(Char *)s1 - *(const unsigned char *)s2++;
+ if (rv)
+ break;
+ if (*s1++ == '\0')
+ break;
+ }
+ return rv;
+}
+
+static int
+g_charclass(const Char **patternp, Char **bufnextp)
+{
+ const Char *pattern = *patternp + 1;
+ Char *bufnext = *bufnextp;
+ const Char *colon;
+ struct cclass *cc;
+ size_t len;
+
+ if ((colon = g_strchr(pattern, ':')) == NULL || colon[1] != ']')
+ return 1; /* not a character class */
+
+ len = (size_t)(colon - pattern);
+ for (cc = cclasses; cc->name != NULL; cc++) {
+ if (!g_strncmp(pattern, cc->name, len) && cc->name[len] == '\0')
+ break;
+ }
+ if (cc->name == NULL)
+ return -1; /* invalid character class */
+ *bufnext++ = M_CLASS;
+ *bufnext++ = (Char)(cc - &cclasses[0]);
+ *bufnextp = bufnext;
+ *patternp += len + 3;
+
+ return 0;
+}
+
+/*
+ * The main glob() routine: compiles the pattern (optionally processing
+ * quotes), calls glob1() to do the real pattern matching, and finally
+ * sorts the list (unless unsorted operation is requested). Returns 0
+ * if things went well, nonzero if errors occurred. It is not an error
+ * to find no matches.
+ */
+static int
+glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp)
+{
+ const Char *qpatnext;
+ int c, err;
+ size_t oldpathc;
+ Char *bufnext, patbuf[PATH_MAX];
+
+ qpatnext = globtilde(pattern, patbuf, PATH_MAX, pglob);
+ oldpathc = pglob->gl_pathc;
+ bufnext = patbuf;
+
+ /* We don't need to check for buffer overflow any more. */
+ while ((c = *qpatnext++) != EOS) {
+ switch (c) {
+ case LBRACKET:
+ c = *qpatnext;
+ if (c == NOT)
+ ++qpatnext;
+ if (*qpatnext == EOS ||
+ g_strchr(qpatnext+1, RBRACKET) == NULL) {
+ *bufnext++ = LBRACKET;
+ if (c == NOT)
+ --qpatnext;
+ break;
+ }
+ *bufnext++ = M_SET;
+ if (c == NOT)
+ *bufnext++ = M_NOT;
+ c = *qpatnext++;
+ do {
+ if (c == LBRACKET && *qpatnext == ':') {
+ do {
+ err = g_charclass(&qpatnext,
+ &bufnext);
+ if (err)
+ break;
+ c = *qpatnext++;
+ } while (c == LBRACKET && *qpatnext == ':');
+ if (err == -1 &&
+ !(pglob->gl_flags & GLOB_NOCHECK))
+ return GLOB_NOMATCH;
+ if (c == RBRACKET)
+ break;
+ }
+ *bufnext++ = CHAR(c);
+ if (*qpatnext == RANGE &&
+ (c = qpatnext[1]) != RBRACKET) {
+ *bufnext++ = M_RNG;
+ *bufnext++ = CHAR(c);
+ qpatnext += 2;
+ }
+ } while ((c = *qpatnext++) != RBRACKET);
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_END;
+ break;
+ case QUESTION:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_ONE;
+ break;
+ case STAR:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ /* collapse adjacent stars to one,
+ * to avoid exponential behavior
+ */
+ if (bufnext == patbuf || bufnext[-1] != M_ALL)
+ *bufnext++ = M_ALL;
+ break;
+ default:
+ *bufnext++ = CHAR(c);
+ break;
+ }
+ }
+ *bufnext = EOS;
+#ifdef DEBUG
+ qprintf("glob0:", patbuf);
+#endif
+
+ if ((err = glob1(patbuf, patbuf + PATH_MAX - 1, pglob, limitp)) != 0)
+ return err;
+
+ /*
+ * If there was no match we are going to append the pattern
+ * if GLOB_NOCHECK was specified.
+ */
+ if (pglob->gl_pathc == oldpathc) {
+ if ((pglob->gl_flags & GLOB_NOCHECK))
+ return globextend(pattern, pglob, limitp, NULL);
+ else
+ return GLOB_NOMATCH;
+ }
+ if (!(pglob->gl_flags & GLOB_NOSORT)) {
+ qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
+ pglob->gl_pathc - oldpathc, sizeof(char *), compare);
+ }
+ return 0;
+}
+
+static int
+compare(const void *p, const void *q)
+{
+ return strcmp(*(char **)p, *(char **)q);
+}
+
+static int
+glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp)
+{
+ Char pathbuf[PATH_MAX];
+
+ /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
+ if (*pattern == EOS)
+ return 0;
+ return glob2(pathbuf, pathbuf + PATH_MAX - 1,
+ pathbuf, pathbuf + PATH_MAX - 1,
+ pattern, pattern_last, pglob, limitp);
+}
+
+/*
+ * The functions glob2 and glob3 are mutually recursive; there is one level
+ * of recursion for each segment in the pattern that contains one or more
+ * meta characters.
+ */
+static int
+glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
+ Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp)
+{
+ struct stat sb;
+ Char *p, *q;
+ int anymeta;
+
+ /*
+ * Loop over pattern segments until end of pattern or until
+ * segment with meta character found.
+ */
+ for (anymeta = 0;;) {
+ if (*pattern == EOS) { /* End of pattern? */
+ *pathend = EOS;
+
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limitp->glim_stat++ >= GLOB_LIMIT_STAT) {
+ errno = 0;
+ *pathend++ = SEP;
+ *pathend = EOS;
+ return GLOB_NOSPACE;
+ }
+ if (g_lstat(pathbuf, &sb, pglob))
+ return 0;
+
+ if (((pglob->gl_flags & GLOB_MARK) &&
+ pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
+ (S_ISLNK(sb.st_mode) &&
+ (g_stat(pathbuf, &sb, pglob) == 0) &&
+ S_ISDIR(sb.st_mode)))) {
+ if (pathend+1 > pathend_last)
+ return 1;
+ *pathend++ = SEP;
+ *pathend = EOS;
+ }
+ ++pglob->gl_matchc;
+ return globextend(pathbuf, pglob, limitp, &sb);
+ }
+
+ /* Find end of next segment, copy tentatively to pathend. */
+ q = pathend;
+ p = pattern;
+ while (*p != EOS && *p != SEP) {
+ if (ismeta(*p))
+ anymeta = 1;
+ if (q+1 > pathend_last)
+ return 1;
+ *q++ = *p++;
+ }
+
+ if (!anymeta) { /* No expansion, do next segment. */
+ pathend = q;
+ pattern = p;
+ while (*pattern == SEP) {
+ if (pathend+1 > pathend_last)
+ return 1;
+ *pathend++ = *pattern++;
+ }
+ } else
+ /* Need expansion, recurse. */
+ return glob3(pathbuf, pathbuf_last, pathend,
+ pathend_last, pattern, p, pattern_last,
+ pglob, limitp);
+ }
+ /* NOTREACHED */
+}
+
+static int
+glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
+ Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob,
+ struct glob_lim *limitp)
+{
+ struct dirent *dp;
+ DIR *dirp;
+ int err;
+ char buf[PATH_MAX];
+
+ if (pathend > pathend_last)
+ return 1;
+ *pathend = EOS;
+ errno = 0;
+
+ if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
+ /* TODO: don't call for ENOENT or ENOTDIR? */
+ if (pglob->gl_errfunc) {
+ if (g_Ctoc(pathbuf, buf, sizeof(buf)))
+ return GLOB_ABORTED;
+ if (pglob->gl_errfunc(buf, errno) ||
+ pglob->gl_flags & GLOB_ERR)
+ return GLOB_ABORTED;
+ }
+ return 0;
+ }
+
+ err = 0;
+
+ /* Search directory for matching names. */
+ while ((dp = readdir(dirp))) {
+ unsigned char *sc;
+ Char *dc;
+
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limitp->glim_readdir++ >= GLOB_LIMIT_READDIR) {
+ errno = 0;
+ *pathend++ = SEP;
+ *pathend = EOS;
+ err = GLOB_NOSPACE;
+ break;
+ }
+
+ /* Initial DOT must be matched literally. */
+ if (dp->d_name[0] == DOT && *pattern != DOT)
+ continue;
+ dc = pathend;
+ sc = (unsigned char *) dp->d_name;
+ while (dc < pathend_last && (*dc++ = *sc++) != EOS)
+ continue;
+ if (dc >= pathend_last) {
+ *dc = EOS;
+ err = 1;
+ break;
+ }
+
+ if (!match(pathend, pattern, restpattern)) {
+ *pathend = EOS;
+ continue;
+ }
+ err = glob2(pathbuf, pathbuf_last, --dc, pathend_last,
+ restpattern, restpattern_last, pglob, limitp);
+ if (err)
+ break;
+ }
+
+ closedir(dirp);
+ return err;
+}
+
+/*
+ * Extend the gl_pathv member of a glob_t structure to accommodate a new item,
+ * add the new item, and update gl_pathc.
+ *
+ * This assumes the BSD realloc, which only copies the block when its size
+ * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
+ * behavior.
+ *
+ * Return 0 if new item added, error code if memory couldn't be allocated.
+ *
+ * Invariant of the glob_t structure:
+ * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
+ * gl_pathv points to (gl_offs + gl_pathc + 1) items.
+ */
+static int
+globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp,
+ struct stat *sb)
+{
+ char **pathv;
+ size_t i, newn, len;
+ char *copy = NULL;
+ const Char *p;
+
+ newn = 2 + pglob->gl_pathc + pglob->gl_offs;
+ if (pglob->gl_offs >= SSIZE_MAX ||
+ pglob->gl_pathc >= SSIZE_MAX ||
+ newn >= SSIZE_MAX ||
+ SIZE_MAX / sizeof(*pathv) <= newn) {
+ nospace:
+ for (i = pglob->gl_offs; i < newn - 2; i++) {
+ if (pglob->gl_pathv && pglob->gl_pathv[i])
+ free(pglob->gl_pathv[i]);
+ }
+ if (pglob->gl_pathv) {
+ free(pglob->gl_pathv);
+ pglob->gl_pathv = NULL;
+ }
+ return GLOB_NOSPACE;
+ }
+
+ pathv = reallocarray(pglob->gl_pathv, newn, sizeof(*pathv));
+ if (pathv == NULL)
+ goto nospace;
+ if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
+ /* first time around -- clear initial gl_offs items */
+ pathv += pglob->gl_offs;
+ for (i = pglob->gl_offs; i > 0; i--)
+ *--pathv = NULL;
+ }
+ pglob->gl_pathv = pathv;
+
+ for (p = path; *p++;)
+ continue;
+ len = (size_t)(p - path);
+ limitp->glim_malloc += len;
+ if ((copy = malloc(len)) != NULL) {
+ if (g_Ctoc(path, copy, len)) {
+ free(copy);
+ return GLOB_NOSPACE;
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ (newn * sizeof(*pathv)) + limitp->glim_malloc >
+ GLOB_LIMIT_MALLOC) {
+ errno = 0;
+ return GLOB_NOSPACE;
+ }
+ return copy == NULL ? GLOB_NOSPACE : 0;
+}
+
+
+/*
+ * pattern matching function for filenames. Each occurrence of the *
+ * pattern causes an iteration.
+ *
+ * Note, this function differs from the original as per the discussion
+ * here: https://research.swtch.com/glob
+ *
+ * Basically we removed the recursion and made it use the algorithm
+ * from Russ Cox to not go quadratic on cases like a file called
+ * ("a" x 100) . "x" matched against a pattern like "a*a*a*a*a*a*a*y".
+ */
+static int
+match(Char *name, Char *pat, Char *patend)
+{
+ int ok, negate_range;
+ Char c, k;
+ Char *nextp = NULL;
+ Char *nextn = NULL;
+
+loop:
+ while (pat < patend) {
+ c = *pat++;
+ switch (c & M_MASK) {
+ case M_ALL:
+ while (pat < patend && (*pat & M_MASK) == M_ALL)
+ pat++; /* eat consecutive '*' */
+ if (pat == patend)
+ return 1;
+ if (*name == EOS)
+ return 0;
+ nextn = name + 1;
+ nextp = pat - 1;
+ break;
+ case M_ONE:
+ if (*name++ == EOS)
+ goto fail;
+ break;
+ case M_SET:
+ ok = 0;
+ if ((k = *name++) == EOS)
+ goto fail;
+ if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
+ ++pat;
+ while (((c = *pat++) & M_MASK) != M_END) {
+ if ((c & M_MASK) == M_CLASS) {
+ Char idx = *pat & M_MASK;
+ if (idx < NCCLASSES &&
+ cclasses[idx].isctype(k))
+ ok = 1;
+ ++pat;
+ }
+ if ((*pat & M_MASK) == M_RNG) {
+ if (c <= k && k <= pat[1])
+ ok = 1;
+ pat += 2;
+ } else if (c == k)
+ ok = 1;
+ }
+ if (ok == negate_range)
+ goto fail;
+ break;
+ default:
+ if (*name++ != c)
+ goto fail;
+ break;
+ }
+ }
+ if (*name == EOS)
+ return 1;
+fail:
+ if (nextn) {
+ pat = nextp;
+ name = nextn;
+ goto loop;
+ }
+ return 0;
+}
+
+/* Free allocated data belonging to a glob_t structure. */
+void
+sudo_globfree(glob_t *pglob)
+{
+ size_t i;
+ char **pp;
+
+ if (pglob->gl_pathv != NULL) {
+ pp = pglob->gl_pathv + pglob->gl_offs;
+ for (i = pglob->gl_pathc; i--; ++pp)
+ if (*pp)
+ free(*pp);
+ free(pglob->gl_pathv);
+ pglob->gl_pathv = NULL;
+ }
+}
+
+static DIR *
+g_opendir(Char *str, glob_t *pglob)
+{
+ char buf[PATH_MAX];
+
+ if (!*str) {
+ buf[0] = '.';
+ buf[1] = '\0';
+ } else {
+ if (g_Ctoc(str, buf, sizeof(buf)))
+ return NULL;
+ }
+
+ return opendir(buf);
+}
+
+static int
+g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
+{
+ char buf[PATH_MAX];
+
+ if (g_Ctoc(fn, buf, sizeof(buf)))
+ return -1;
+ return lstat(buf, sb);
+}
+
+static int
+g_stat(Char *fn, struct stat *sb, glob_t *pglob)
+{
+ char buf[PATH_MAX];
+
+ if (g_Ctoc(fn, buf, sizeof(buf)))
+ return -1;
+ return stat(buf, sb);
+}
+
+static Char *
+g_strchr(const Char *str, int ch)
+{
+ do {
+ if (*str == ch)
+ return (Char *)str;
+ } while (*str++);
+ return NULL;
+}
+
+static int
+g_Ctoc(const Char *str, char *buf, size_t len)
+{
+
+ while (len--) {
+ if ((*buf++ = *str++) == EOS)
+ return 0;
+ }
+ return 1;
+}
+
+#ifdef DEBUG
+static void
+qprintf(const char *str, Char *s)
+{
+ Char *p;
+
+ (void)printf("%s:\n", str);
+ for (p = s; *p; p++)
+ (void)fputc(CHAR(*p), stdout);
+ (void)fputc('\n', stdout);
+ for (p = s; *p; p++)
+ (void)fputc(*p & M_PROTECT ? '"' : ' ', stdout);
+ (void)fputc('\n', stdout);
+ for (p = s; *p; p++)
+ (void)fputc(ismeta(*p) ? '_' : ' ', stdout);
+ (void)fputc('\n', stdout);
+}
+#endif /* DEBUG */
+#endif /* HAVE_GLOB */
diff --git a/lib/util/gmtime_r.c b/lib/util/gmtime_r.c
new file mode 100644
index 0000000..11e2651
--- /dev/null
+++ b/lib/util/gmtime_r.c
@@ -0,0 +1,49 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_GMTIME_R
+
+#include <sys/types.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+/*
+ * Fake gmtime_r() that just stores the result.
+ * Still has the normal gmtime() side effects.
+ */
+struct tm *
+sudo_gmtime_r(const time_t *timer, struct tm *result)
+{
+ struct tm *tm;
+
+ if ((tm = gmtime(timer)) == NULL)
+ return NULL;
+ memcpy(result, tm, sizeof(struct tm));
+
+ return result;
+}
+#endif /* HAVE_GMTIME_T */
diff --git a/lib/util/hexchar.c b/lib/util/hexchar.c
new file mode 100644
index 0000000..0650843
--- /dev/null
+++ b/lib/util/hexchar.c
@@ -0,0 +1,103 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2015, 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+
+/*
+ * Converts a two-byte hex string to decimal.
+ * Returns a value 0-255 on success or -1 for invalid input.
+ */
+int
+sudo_hexchar_v1(const char *s)
+{
+ unsigned char result[2];
+ unsigned int i;
+ debug_decl(sudo_hexchar, SUDO_DEBUG_UTIL);
+
+ for (i = 0; i < 2; i++) {
+ switch (s[i]) {
+ case '0':
+ result[i] = 0;
+ break;
+ case '1':
+ result[i] = 1;
+ break;
+ case '2':
+ result[i] = 2;
+ break;
+ case '3':
+ result[i] = 3;
+ break;
+ case '4':
+ result[i] = 4;
+ break;
+ case '5':
+ result[i] = 5;
+ break;
+ case '6':
+ result[i] = 6;
+ break;
+ case '7':
+ result[i] = 7;
+ break;
+ case '8':
+ result[i] = 8;
+ break;
+ case '9':
+ result[i] = 9;
+ break;
+ case 'A':
+ case 'a':
+ result[i] = 10;
+ break;
+ case 'B':
+ case 'b':
+ result[i] = 11;
+ break;
+ case 'C':
+ case 'c':
+ result[i] = 12;
+ break;
+ case 'D':
+ case 'd':
+ result[i] = 13;
+ break;
+ case 'E':
+ case 'e':
+ result[i] = 14;
+ break;
+ case 'F':
+ case 'f':
+ result[i] = 15;
+ break;
+ default:
+ /* Invalid input. */
+ debug_return_int(-1);
+ }
+ }
+ debug_return_int((result[0] << 4) | result[1]);
+}
diff --git a/lib/util/inet_ntop.c b/lib/util/inet_ntop.c
new file mode 100644
index 0000000..e456d6e
--- /dev/null
+++ b/lib/util/inet_ntop.c
@@ -0,0 +1,229 @@
+/* $OpenBSD: inet_ntop.c,v 1.9 2014/02/05 14:20:43 millert Exp $ */
+
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include <config.h>
+
+#if !defined(HAVE_INET_NTOP)
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include <sudo_compat.h>
+
+#ifndef EAFNOSUPPORT
+# define EAFNOSUPPORT EINVAL
+#endif
+
+#ifndef NS_IN6ADDRSZ
+# ifdef IN6ADDRSZ
+# define NS_IN6ADDRSZ IN6ADDRSZ
+# else
+# define NS_IN6ADDRSZ 16
+# endif
+#endif
+#ifndef NS_INT16SZ
+# ifdef INT16SZ
+# define NS_INT16SZ INT16SZ
+# else
+# define NS_INT16SZ 2
+# endif
+#endif
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ * format an IPv4 address, more or less like inet_ntoa()
+ * return:
+ * `dst' (as a const)
+ * notes:
+ * (1) uses no statics
+ * (2) takes a unsigned char* not an in_addr as input
+ * author:
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop4(const unsigned char * restrict src, char * restrict dst, socklen_t size)
+{
+ const char fmt[] = "%u.%u.%u.%u";
+ int len;
+
+ len = snprintf(dst, size, fmt, src[0], src[1], src[2], src[3]);
+ if (len < 0 || (socklen_t)len >= size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ return (dst);
+}
+
+#ifdef HAVE_STRUCT_IN6_ADDR
+/* const char *
+ * inet_ntop6(src, dst, size)
+ * convert IPv6 binary address into presentation (printable) format
+ * author:
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop6(const unsigned char * restrict src, char * restrict dst, socklen_t size)
+{
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char *cp, *ep;
+ struct { int base, len; } best, cur;
+ unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
+ int i;
+ int advance;
+
+ /*
+ * Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, 0, sizeof(words));
+ for (i = 0; i < NS_IN6ADDRSZ; i++)
+ words[i / 2] |= (src[i] << ((1 - (i & 1)) << 3));
+ best.base = -1;
+ best.len = 0;
+ cur.base = -1;
+ cur.len = 0;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ if (words[i] == 0) {
+ if (cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ } else {
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ cp = dst;
+ ep = dst + size;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ) && cp < ep; i++) {
+ /* Are we inside the best run of 0x00's? */
+ if (best.base != -1 && i >= best.base &&
+ i < (best.base + best.len)) {
+ if (i == best.base) {
+ if (cp + 1 >= ep) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ *cp++ = ':';
+ }
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0) {
+ if (cp + 1 >= ep) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ *cp++ = ':';
+ }
+ /* Is this address an encapsulated IPv4? */
+ if (i == 6 && best.base == 0 &&
+ (best.len == 6 ||
+ (best.len == 7 && words[7] != 0x0001) ||
+ (best.len == 5 && words[5] == 0xffff))) {
+ if (!inet_ntop4(src + 12, cp, (socklen_t)(ep - cp)))
+ return (NULL);
+ cp += strlen(cp);
+ break;
+ }
+ advance = snprintf(cp, (size_t)(ep - cp), "%x", words[i]);
+ if (advance <= 0 || advance >= ep - cp) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ cp += advance;
+ }
+ /* Was it a trailing run of 0x00's? */
+ if (best.base != -1 &&
+ (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ)) {
+ if (cp + 1 >= ep) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ *cp++ = ':';
+ }
+ if (cp + 1 >= ep) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ *cp++ = '\0';
+
+ return (dst);
+}
+#endif /* HAVE_STRUCT_IN6_ADDR */
+
+/* const char *
+ * inet_ntop(af, src, dst, size)
+ * convert a network format address to presentation format.
+ * return:
+ * pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ * Paul Vixie, 1996.
+ */
+const char *
+sudo_inet_ntop(int af, const void * restrict src, char * restrict dst, socklen_t size)
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_ntop4(src, dst, size));
+#ifdef HAVE_STRUCT_IN6_ADDR
+ case AF_INET6:
+ return (inet_ntop6(src, dst, size));
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+ /* NOTREACHED */
+}
+
+#endif /* !HAVE_INET_NTOP */
diff --git a/lib/util/inet_pton.c b/lib/util/inet_pton.c
new file mode 100644
index 0000000..d3b4b4b
--- /dev/null
+++ b/lib/util/inet_pton.c
@@ -0,0 +1,252 @@
+/* $OpenBSD: inet_pton.c,v 1.8 2010/05/06 15:47:14 claudio Exp $ */
+
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include <config.h>
+
+#if !defined(HAVE_INET_PTON)
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sudo_compat.h>
+
+#ifndef EAFNOSUPPORT
+# define EAFNOSUPPORT EINVAL
+#endif
+
+#ifndef NS_INADDRSZ
+# ifdef INADDRSZ
+# define NS_INADDRSZ INADDRSZ
+# else
+# define NS_INADDRSZ 4
+# endif
+#endif
+#ifndef NS_IN6ADDRSZ
+# ifdef IN6ADDRSZ
+# define NS_IN6ADDRSZ IN6ADDRSZ
+# else
+# define NS_IN6ADDRSZ 16
+# endif
+#endif
+#ifndef NS_INT16SZ
+# ifdef INT16SZ
+# define NS_INT16SZ INT16SZ
+# else
+# define NS_INT16SZ 2
+# endif
+#endif
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+/* int
+ * inet_pton4(src, dst)
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ * 1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton4(const char *src, u_char *dst)
+{
+ const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ u_char tmp[NS_INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ /* cppcheck-suppress uninitvar */
+ *(tp = tmp) = '\0';
+ while ((ch = (unsigned char)*src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr(digits, ch)) != NULL) {
+ u_int new = *tp * 10 + (pch - digits);
+
+ if (new > 255)
+ return (0);
+ if (!saw_digit) {
+ if (++octets > 4)
+ return (0);
+ saw_digit = 1;
+ }
+ *tp = new;
+ } else if (ch == '.' && saw_digit) {
+ if (octets == 4)
+ return (0);
+ *++tp = 0;
+ saw_digit = 0;
+ } else
+ return (0);
+ }
+ if (octets < 4)
+ return (0);
+
+ memcpy(dst, tmp, NS_INADDRSZ);
+ return (1);
+}
+
+#ifdef HAVE_STRUCT_IN6_ADDR
+/* int
+ * inet_pton6(src, dst)
+ * convert presentation level address to network order binary form.
+ * return:
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * credit:
+ * inspired by Mark Andrews.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton6(const char *src, u_char *dst)
+{
+ const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit, count_xdigit;
+ u_int val;
+
+ /* cppcheck-suppress uninitvar */
+ memset((tp = tmp), 0, NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return (0);
+ curtok = src;
+ saw_xdigit = count_xdigit = 0;
+ val = 0;
+ while ((ch = (unsigned char)*src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ if (count_xdigit >= 4)
+ return (0);
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (val > 0xffff)
+ return (0);
+ saw_xdigit = 1;
+ count_xdigit++;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!saw_xdigit) {
+ if (colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ } else if (*src == '\0') {
+ return (0);
+ }
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ saw_xdigit = 0;
+ count_xdigit = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp) > 0) {
+ tp += NS_INADDRSZ;
+ saw_xdigit = 0;
+ count_xdigit = 0;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ return (0);
+ }
+ if (saw_xdigit) {
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ }
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const long n = tp - colonp;
+ long i;
+
+ if (tp == endp)
+ return (0);
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ return (0);
+ memcpy(dst, tmp, NS_IN6ADDRSZ);
+ return (1);
+}
+#endif /* HAVE_STRUCT_IN6_ADDR */
+
+/* int
+ * inet_pton(af, src, dst)
+ * convert from presentation format (which usually means ASCII printable)
+ * to network format (which is usually some kind of binary format).
+ * return:
+ * 1 if the address was valid for the specified address family
+ * 0 if the address wasn't valid (`dst' is untouched in this case)
+ * -1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ * Paul Vixie, 1996.
+ */
+int
+sudo_inet_pton(int af, const char *src, void *dst)
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_pton4(src, dst));
+#ifdef HAVE_STRUCT_IN6_ADDR
+ case AF_INET6:
+ return (inet_pton6(src, dst));
+#endif /* HAVE_STRUCT_IN6_ADDR */
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+ /* NOTREACHED */
+}
+
+#endif /* HAVE_INET_PTON */
diff --git a/lib/util/isblank.c b/lib/util/isblank.c
new file mode 100644
index 0000000..cc099c0
--- /dev/null
+++ b/lib/util/isblank.c
@@ -0,0 +1,37 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2008, 2010-2011, 2013
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_ISBLANK
+
+#include <sudo_compat.h>
+
+#undef isblank
+int
+isblank(int ch)
+{
+ return ch == ' ' || ch == '\t';
+}
+#endif /* HAVE_ISBLANK */
diff --git a/lib/util/json.c b/lib/util/json.c
new file mode 100644
index 0000000..e0bd286
--- /dev/null
+++ b/lib/util/json.c
@@ -0,0 +1,423 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_json.h>
+#include <sudo_util.h>
+
+/*
+ * Double the size of the json buffer.
+ * Returns true on success, false if out of memory.
+ */
+static bool
+json_expand_buf(struct json_container *jsonc)
+{
+ char *newbuf;
+ debug_decl(json_expand_buf, SUDO_DEBUG_UTIL);
+
+ if ((newbuf = reallocarray(jsonc->buf, 2, jsonc->bufsize)) == NULL) {
+ if (jsonc->memfatal) {
+ sudo_fatalx(U_("%s: %s"),
+ __func__, U_("unable to allocate memory"));
+ }
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "%s: %s", __func__, "unable to allocate memory");
+ debug_return_bool(false);
+ }
+ jsonc->buf = newbuf;
+ jsonc->bufsize *= 2;
+
+ debug_return_bool(true);
+}
+
+/*
+ * Start a new line and indent unless formatting as minimal JSON.
+ * Append "indent" number of blank characters.
+ */
+static bool
+json_new_line(struct json_container *jsonc)
+{
+ unsigned int indent = jsonc->indent_level;
+ debug_decl(json_new_line, SUDO_DEBUG_UTIL);
+
+ /* No non-essential white space in minimal mode. */
+ if (jsonc->minimal)
+ debug_return_bool(true);
+
+ while (jsonc->buflen + 1 + indent >= jsonc->bufsize) {
+ if (!json_expand_buf(jsonc))
+ debug_return_bool(false);
+ }
+ jsonc->buf[jsonc->buflen++] = '\n';
+ while (indent--) {
+ jsonc->buf[jsonc->buflen++] = ' ';
+ }
+ jsonc->buf[jsonc->buflen] = '\0';
+
+ debug_return_bool(true);
+}
+
+/*
+ * Append a string to the JSON buffer, expanding as needed.
+ * Does not perform any quoting.
+ */
+static bool
+json_append_buf(struct json_container *jsonc, const char *str)
+{
+ size_t len;
+ debug_decl(json_append_buf, SUDO_DEBUG_UTIL);
+
+ len = strlen(str);
+ while (jsonc->buflen + len >= jsonc->bufsize) {
+ if (!json_expand_buf(jsonc))
+ debug_return_bool(false);
+ }
+
+ memcpy(jsonc->buf + jsonc->buflen, str, len);
+ jsonc->buflen += (unsigned int)len;
+ jsonc->buf[jsonc->buflen] = '\0';
+
+ debug_return_bool(true);
+}
+
+/*
+ * Append a quoted JSON string, escaping special chars and expanding as needed.
+ * Treats strings as 8-bit ASCII, escaping control characters.
+ */
+static bool
+json_append_string(struct json_container *jsonc, const char *str)
+{
+ const char hex[] = "0123456789abcdef";
+ char ch;
+ debug_decl(json_append_string, SUDO_DEBUG_UTIL);
+
+ if (!json_append_buf(jsonc, "\""))
+ debug_return_bool(false);
+ while ((ch = *str++) != '\0') {
+ char buf[sizeof("\\u0000")], *cp = buf;
+
+ switch (ch) {
+ case '"':
+ case '\\':
+ *cp++ = '\\';
+ break;
+ case '\b':
+ *cp++ = '\\';
+ ch = 'b';
+ break;
+ case '\f':
+ *cp++ = '\\';
+ ch = 'f';
+ break;
+ case '\n':
+ *cp++ = '\\';
+ ch = 'n';
+ break;
+ case '\r':
+ *cp++ = '\\';
+ ch = 'r';
+ break;
+ case '\t':
+ *cp++ = '\\';
+ ch = 't';
+ break;
+ default:
+ if (iscntrl((unsigned char)ch)) {
+ /* Escape control characters like \u0000 */
+ *cp++ = '\\';
+ *cp++ = 'u';
+ *cp++ = '0';
+ *cp++ = '0';
+ *cp++ = hex[ch >> 4];
+ ch = hex[ch & 0x0f];
+ }
+ break;
+ }
+ *cp++ = ch;
+ *cp = '\0';
+ if (!json_append_buf(jsonc, buf))
+ debug_return_bool(false);
+ }
+ if (!json_append_buf(jsonc, "\""))
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+bool
+sudo_json_init_v2(struct json_container *jsonc, unsigned int indent,
+ bool minimal, bool memfatal, bool quiet)
+{
+ debug_decl(sudo_json_init, SUDO_DEBUG_UTIL);
+
+ memset(jsonc, 0, sizeof(*jsonc));
+ jsonc->indent_level = indent;
+ jsonc->indent_increment = indent;
+ jsonc->minimal = minimal;
+ jsonc->memfatal = memfatal;
+ jsonc->quiet = quiet;
+ jsonc->buf = malloc(64 * 1024);
+ if (jsonc->buf == NULL) {
+ if (jsonc->memfatal) {
+ sudo_fatalx(U_("%s: %s"),
+ __func__, U_("unable to allocate memory"));
+ }
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "%s: %s", __func__, "unable to allocate memory");
+ debug_return_bool(false);
+ }
+ *jsonc->buf = '\0';
+ jsonc->bufsize = 64 * 1024;
+
+ debug_return_bool(true);
+}
+
+bool
+sudo_json_init_v1(struct json_container *jsonc, unsigned int indent,
+ bool minimal, bool memfatal)
+{
+ return sudo_json_init_v2(jsonc, indent, minimal, memfatal, false);
+}
+
+void
+sudo_json_free_v1(struct json_container *jsonc)
+{
+ debug_decl(sudo_json_free, SUDO_DEBUG_UTIL);
+
+ free(jsonc->buf);
+ memset(jsonc, 0, sizeof(*jsonc));
+
+ debug_return;
+}
+
+bool
+sudo_json_open_object_v1(struct json_container *jsonc, const char *name)
+{
+ debug_decl(sudo_json_open_object, SUDO_DEBUG_UTIL);
+
+ /* Add comma if we are continuing an object/array. */
+ if (jsonc->need_comma) {
+ if (!json_append_buf(jsonc, ","))
+ debug_return_bool(false);
+ }
+ if (!json_new_line(jsonc))
+ debug_return_bool(false);
+
+ if (name != NULL) {
+ json_append_string(jsonc, name);
+ if (!json_append_buf(jsonc, jsonc->minimal ? ":{" : ": {"))
+ debug_return_bool(false);
+ } else {
+ if (!json_append_buf(jsonc, "{"))
+ debug_return_bool(false);
+ }
+
+ jsonc->indent_level += jsonc->indent_increment;
+ jsonc->need_comma = false;
+
+ debug_return_bool(true);
+}
+
+bool
+sudo_json_close_object_v1(struct json_container *jsonc)
+{
+ debug_decl(sudo_json_close_object, SUDO_DEBUG_UTIL);
+
+ if (!jsonc->minimal) {
+ jsonc->indent_level -= jsonc->indent_increment;
+ if (!json_new_line(jsonc))
+ debug_return_bool(false);
+ }
+ if (!json_append_buf(jsonc, "}"))
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+bool
+sudo_json_open_array_v1(struct json_container *jsonc, const char *name)
+{
+ debug_decl(sudo_json_open_array, SUDO_DEBUG_UTIL);
+
+ /* Add comma if we are continuing an object/array. */
+ if (jsonc->need_comma) {
+ if (!json_append_buf(jsonc, ","))
+ debug_return_bool(false);
+ }
+ if (!json_new_line(jsonc))
+ debug_return_bool(false);
+
+ if (name != NULL) {
+ json_append_string(jsonc, name);
+ if (!json_append_buf(jsonc, jsonc->minimal ? ":[" : ": ["))
+ debug_return_bool(false);
+ } else {
+ if (!json_append_buf(jsonc, "["))
+ debug_return_bool(false);
+ }
+
+ jsonc->indent_level += jsonc->indent_increment;
+ jsonc->need_comma = false;
+
+ debug_return_bool(true);
+}
+
+bool
+sudo_json_close_array_v1(struct json_container *jsonc)
+{
+ debug_decl(sudo_json_close_array, SUDO_DEBUG_UTIL);
+
+ if (!jsonc->minimal) {
+ jsonc->indent_level -= jsonc->indent_increment;
+ if (!json_new_line(jsonc))
+ debug_return_bool(false);
+ }
+ if (!json_append_buf(jsonc, "]"))
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+static bool
+sudo_json_add_value_int(struct json_container *jsonc, const char *name,
+ struct json_value *value, bool as_object)
+{
+ struct json_container saved_container = *jsonc;
+ char numbuf[STRLEN_MAX_SIGNED(long long) + 1];
+ debug_decl(sudo_json_add_value, SUDO_DEBUG_UTIL);
+
+ /* Add comma if we are continuing an object/array. */
+ if (jsonc->need_comma) {
+ if (!json_append_buf(jsonc, ","))
+ goto bad;
+ }
+ if (!json_new_line(jsonc))
+ goto bad;
+ jsonc->need_comma = true;
+
+ if (as_object) {
+ if (!json_append_buf(jsonc, jsonc->minimal ? "{" : "{ "))
+ goto bad;
+ }
+
+ /* name */
+ if (name != NULL) {
+ if (!json_append_string(jsonc, name))
+ goto bad;
+ if (!json_append_buf(jsonc, jsonc->minimal ? ":" : ": "))
+ goto bad;
+ }
+
+ /* value */
+ switch (value->type) {
+ case JSON_STRING:
+ if (!json_append_string(jsonc, value->u.string))
+ goto bad;
+ break;
+ case JSON_ID:
+ snprintf(numbuf, sizeof(numbuf), "%u", (unsigned int)value->u.id);
+ if (!json_append_buf(jsonc, numbuf))
+ goto bad;
+ break;
+ case JSON_NUMBER:
+ snprintf(numbuf, sizeof(numbuf), "%lld", value->u.number);
+ if (!json_append_buf(jsonc, numbuf))
+ goto bad;
+ break;
+ case JSON_NULL:
+ if (!json_append_buf(jsonc, "null"))
+ goto bad;
+ break;
+ case JSON_BOOL:
+ if (!json_append_buf(jsonc, value->u.boolean ? "true" : "false"))
+ goto bad;
+ break;
+ case JSON_ARRAY:
+ if (!jsonc->quiet)
+ sudo_warnx("internal error: add JSON_ARRAY as a value");
+ goto bad;
+ case JSON_OBJECT:
+ if (!jsonc->quiet)
+ sudo_warnx("internal error: add JSON_OBJECT as a value");
+ goto bad;
+ default:
+ if (!jsonc->quiet)
+ sudo_warnx("internal error: unknown JSON type %d", value->type);
+ goto bad;
+ }
+
+ if (as_object) {
+ if (!json_append_buf(jsonc, jsonc->minimal ? "}" : " }"))
+ goto bad;
+ }
+
+ debug_return_bool(true);
+bad:
+ /* Restore container but handle reallocation of buf. */
+ saved_container.buf = jsonc->buf;
+ saved_container.bufsize = jsonc->bufsize;
+ *jsonc = saved_container;
+ jsonc->buf[jsonc->buflen] = '\0';
+ debug_return_bool(false);
+}
+
+bool
+sudo_json_add_value_v1(struct json_container *jsonc, const char *name,
+ struct json_value *value)
+{
+ return sudo_json_add_value_int(jsonc, name, value, false);
+}
+
+bool
+sudo_json_add_value_as_object_v1(struct json_container *jsonc, const char *name,
+ struct json_value *value)
+{
+ return sudo_json_add_value_int(jsonc, name, value, true);
+}
+
+char *
+sudo_json_get_buf_v1(struct json_container *jsonc)
+{
+ return jsonc->buf;
+}
+
+unsigned int
+sudo_json_get_len_v1(struct json_container *jsonc)
+{
+ return jsonc->buflen;
+}
diff --git a/lib/util/key_val.c b/lib/util/key_val.c
new file mode 100644
index 0000000..89ba4ac
--- /dev/null
+++ b/lib/util/key_val.c
@@ -0,0 +1,56 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2012, 2014-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+
+/*
+ * Create a new key=value pair and return it.
+ * The caller is responsible for freeing the string.
+ */
+char *
+sudo_new_key_val_v1(const char *key, const char *val)
+{
+ size_t key_len = strlen(key);
+ size_t val_len = strlen(val);
+ char *cp, *str;
+ debug_decl(sudo_new_key_val, SUDO_DEBUG_UTIL);
+
+ cp = str = malloc(key_len + 1 + val_len + 1);
+ if (cp != NULL) {
+ memcpy(cp, key, key_len);
+ cp += key_len;
+ *cp++ = '=';
+ memcpy(cp, val, val_len);
+ cp += val_len;
+ *cp = '\0';
+ }
+
+ debug_return_str(str);
+}
diff --git a/lib/util/lbuf.c b/lib/util/lbuf.c
new file mode 100644
index 0000000..6bc74ee
--- /dev/null
+++ b/lib/util/lbuf.c
@@ -0,0 +1,496 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2007-2015, 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_lbuf.h>
+#include <sudo_util.h>
+
+void
+sudo_lbuf_init_v1(struct sudo_lbuf *lbuf, sudo_lbuf_output_t output,
+ unsigned int indent, const char *continuation, int cols)
+{
+ debug_decl(sudo_lbuf_init, SUDO_DEBUG_UTIL);
+
+ if (cols < 0)
+ cols = 0;
+
+ lbuf->output = output;
+ lbuf->continuation = continuation;
+ lbuf->indent = indent;
+ lbuf->cols = (unsigned short)cols;
+ lbuf->error = 0;
+ lbuf->len = 0;
+ lbuf->size = 0;
+ lbuf->buf = NULL;
+
+ debug_return;
+}
+
+void
+sudo_lbuf_destroy_v1(struct sudo_lbuf *lbuf)
+{
+ debug_decl(sudo_lbuf_destroy, SUDO_DEBUG_UTIL);
+
+ free(lbuf->buf);
+ lbuf->error = 0;
+ lbuf->len = 0;
+ lbuf->size = 0;
+ lbuf->buf = NULL;
+
+ debug_return;
+}
+
+static bool
+sudo_lbuf_expand(struct sudo_lbuf *lbuf, unsigned int extra)
+{
+ debug_decl(sudo_lbuf_expand, SUDO_DEBUG_UTIL);
+
+ if (lbuf->len + extra + 1 <= lbuf->len) {
+ errno = ENOMEM;
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "integer overflow updating lbuf->len");
+ lbuf->error = 1;
+ debug_return_bool(false);
+ }
+
+ if (lbuf->len + extra + 1 > lbuf->size) {
+ const size_t size = lbuf->len + extra + 1;
+ size_t new_size = sudo_pow2_roundup(size);
+ char *new_buf;
+
+ if (new_size > UINT_MAX || new_size < lbuf->size) {
+ errno = ENOMEM;
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "integer overflow updating lbuf->size");
+ lbuf->error = 1;
+ debug_return_bool(false);
+ }
+ if (new_size < 1024)
+ new_size = 1024;
+ if ((new_buf = realloc(lbuf->buf, new_size)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ lbuf->error = 1;
+ debug_return_bool(false);
+ }
+ lbuf->buf = new_buf;
+ lbuf->size = (unsigned int)new_size;
+ }
+ debug_return_bool(true);
+}
+
+/*
+ * Escape a character in octal form (#0n) and store it as a string
+ * in buf, which must have at least 6 bytes available.
+ * Returns the length of buf, not counting the terminating NUL byte.
+ */
+static unsigned int
+escape(char ch, char *buf)
+{
+ unsigned char uch = (unsigned char)ch;
+ const unsigned int len = uch < 0100 ? (uch < 010 ? 3 : 4) : 5;
+
+ /* Work backwards from the least significant digit to most significant. */
+ switch (len) {
+ case 5:
+ buf[4] = (uch & 7) + '0';
+ uch >>= 3;
+ FALLTHROUGH;
+ case 4:
+ buf[3] = (uch & 7) + '0';
+ uch >>= 3;
+ FALLTHROUGH;
+ case 3:
+ buf[2] = (uch & 7) + '0';
+ buf[1] = '0';
+ buf[0] = '#';
+ break;
+ }
+ buf[len] = '\0';
+
+ return len;
+}
+
+/*
+ * Parse the format and append strings, only %s and %% escapes are supported.
+ * Any non-printable characters are escaped in octal as #0nn.
+ */
+bool
+sudo_lbuf_append_esc_v1(struct sudo_lbuf *lbuf, int flags, const char * restrict fmt, ...)
+{
+ unsigned int saved_len = lbuf->len;
+ bool ret = false;
+ const char *s;
+ va_list ap;
+ debug_decl(sudo_lbuf_append_esc, SUDO_DEBUG_UTIL);
+
+ if (sudo_lbuf_error(lbuf))
+ debug_return_bool(false);
+
+#define should_escape(ch) \
+ ((ISSET(flags, LBUF_ESC_CNTRL) && iscntrl((unsigned char)ch)) || \
+ (ISSET(flags, LBUF_ESC_BLANK) && isblank((unsigned char)ch)))
+#define should_quote(ch) \
+ (ISSET(flags, LBUF_ESC_QUOTE) && (ch == '\'' || ch == '\\'))
+
+ va_start(ap, fmt);
+ while (*fmt != '\0') {
+ if (fmt[0] == '%' && fmt[1] == 's') {
+ if ((s = va_arg(ap, char *)) == NULL)
+ s = "(NULL)";
+ while (*s != '\0') {
+ if (should_escape(*s)) {
+ if (!sudo_lbuf_expand(lbuf, sizeof("#0177") - 1))
+ goto done;
+ lbuf->len += escape(*s++, lbuf->buf + lbuf->len);
+ continue;
+ }
+ if (should_quote(*s)) {
+ if (!sudo_lbuf_expand(lbuf, 2))
+ goto done;
+ lbuf->buf[lbuf->len++] = '\\';
+ lbuf->buf[lbuf->len++] = *s++;
+ continue;
+ }
+ if (!sudo_lbuf_expand(lbuf, 1))
+ goto done;
+ lbuf->buf[lbuf->len++] = *s++;
+ }
+ fmt += 2;
+ continue;
+ }
+ if (should_escape(*fmt)) {
+ if (!sudo_lbuf_expand(lbuf, sizeof("#0177") - 1))
+ goto done;
+ if (*fmt == '\'') {
+ lbuf->buf[lbuf->len++] = '\\';
+ lbuf->buf[lbuf->len++] = *fmt++;
+ } else {
+ lbuf->len += escape(*fmt++, lbuf->buf + lbuf->len);
+ }
+ continue;
+ }
+ if (!sudo_lbuf_expand(lbuf, 1))
+ goto done;
+ lbuf->buf[lbuf->len++] = *fmt++;
+ }
+ ret = true;
+
+done:
+ if (!ret)
+ lbuf->len = saved_len;
+ if (lbuf->size != 0)
+ lbuf->buf[lbuf->len] = '\0';
+ va_end(ap);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Parse the format and append strings, only %s and %% escapes are supported.
+ * Any characters in set are quoted with a backslash.
+ */
+bool
+sudo_lbuf_append_quoted_v1(struct sudo_lbuf *lbuf, const char *set, const char * restrict fmt, ...)
+{
+ unsigned int saved_len = lbuf->len;
+ bool ret = false;
+ const char *cp, *s;
+ va_list ap;
+ unsigned int len;
+ debug_decl(sudo_lbuf_append_quoted, SUDO_DEBUG_UTIL);
+
+ if (sudo_lbuf_error(lbuf))
+ debug_return_bool(false);
+
+ va_start(ap, fmt);
+ while (*fmt != '\0') {
+ if (fmt[0] == '%' && fmt[1] == 's') {
+ if ((s = va_arg(ap, char *)) == NULL)
+ s = "(NULL)";
+ while ((cp = strpbrk(s, set)) != NULL) {
+ len = (unsigned int)(cp - s);
+ if (!sudo_lbuf_expand(lbuf, len + 2))
+ goto done;
+ memcpy(lbuf->buf + lbuf->len, s, len);
+ lbuf->len += len;
+ lbuf->buf[lbuf->len++] = '\\';
+ lbuf->buf[lbuf->len++] = *cp;
+ s = cp + 1;
+ }
+ if (*s != '\0') {
+ len = (unsigned int)strlen(s);
+ if (!sudo_lbuf_expand(lbuf, len))
+ goto done;
+ memcpy(lbuf->buf + lbuf->len, s, len);
+ lbuf->len += len;
+ }
+ fmt += 2;
+ continue;
+ }
+ if (!sudo_lbuf_expand(lbuf, 2))
+ goto done;
+ if (strchr(set, *fmt) != NULL)
+ lbuf->buf[lbuf->len++] = '\\';
+ lbuf->buf[lbuf->len++] = *fmt++;
+ }
+ ret = true;
+
+done:
+ if (!ret)
+ lbuf->len = saved_len;
+ if (lbuf->size != 0)
+ lbuf->buf[lbuf->len] = '\0';
+ va_end(ap);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Parse the format and append strings, only %s, %n$s and %% escapes are supported.
+ */
+bool
+sudo_lbuf_append_v1(struct sudo_lbuf *lbuf, const char * restrict fmt, ...)
+{
+ unsigned int saved_len = lbuf->len;
+ bool ret = false;
+ va_list ap;
+ const char *s;
+ unsigned int len;
+ debug_decl(sudo_lbuf_append, SUDO_DEBUG_UTIL);
+
+ if (sudo_lbuf_error(lbuf))
+ debug_return_bool(false);
+
+ va_start(ap, fmt);
+ while (*fmt != '\0') {
+ if (fmt[0] == '%' && isdigit((unsigned char)fmt[1])) {
+ const char *num_start = fmt + 1;
+ const char *num_end = num_start;
+ int arg_num;
+ /* Find the end of the numeric part */
+ while (isdigit((unsigned char)*num_end))
+ num_end++;
+ if (num_end[0] == '$' && num_end[1] == 's' && num_end > num_start) {
+ /* Convert the numeric part to an integer */
+ char numbuf[STRLEN_MAX_SIGNED(int) + 1];
+ len = (unsigned int)(num_end - num_start);
+ if (len >= sizeof(numbuf)) {
+ errno = EINVAL;
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "integer overflow parsing $n");
+ lbuf->error = 1;
+ goto done;
+ }
+ memcpy(numbuf, num_start, len);
+ numbuf[len] = '\0';
+ arg_num = atoi(numbuf);
+ if (arg_num > 0) {
+ va_list arg_copy;
+ va_copy(arg_copy, ap);
+ for (int i = 1; i < arg_num; i++) {
+ (void)va_arg(arg_copy, char *);
+ }
+ if ((s = va_arg(arg_copy, char *)) == NULL)
+ s = "(NULL)";
+ len = (unsigned int)strlen(s);
+ if (!sudo_lbuf_expand(lbuf, len)) {
+ va_end(arg_copy);
+ goto done;
+ }
+ memcpy(lbuf->buf + lbuf->len, s, len);
+ lbuf->len += len;
+ fmt = num_end + 2;
+ va_end(arg_copy);
+ continue;
+ }
+ }
+ }
+ if (fmt[0] == '%' && fmt[1] == 's') {
+ if ((s = va_arg(ap, char *)) == NULL)
+ s = "(NULL)";
+ len = (unsigned int)strlen(s);
+ if (!sudo_lbuf_expand(lbuf, len))
+ goto done;
+ memcpy(lbuf->buf + lbuf->len, s, len);
+ lbuf->len += len;
+ fmt += 2;
+ continue;
+ }
+ if (!sudo_lbuf_expand(lbuf, 1))
+ goto done;
+ lbuf->buf[lbuf->len++] = *fmt++;
+ }
+ ret = true;
+
+done:
+ if (!ret)
+ lbuf->len = saved_len;
+ if (lbuf->size != 0)
+ lbuf->buf[lbuf->len] = '\0';
+ va_end(ap);
+
+ debug_return_bool(ret);
+}
+
+/* XXX - check output function return value */
+static void
+sudo_lbuf_println(struct sudo_lbuf *lbuf, char *line, size_t len)
+{
+ char *cp, save;
+ size_t i, have, contlen = 0;
+ unsigned int indent = lbuf->indent;
+ bool is_comment = false;
+ debug_decl(sudo_lbuf_println, SUDO_DEBUG_UTIL);
+
+ /* Comment lines don't use continuation and only indent is for "# " */
+ if (line[0] == '#' && isblank((unsigned char)line[1])) {
+ is_comment = true;
+ indent = 2;
+ }
+ if (lbuf->continuation != NULL && !is_comment)
+ contlen = strlen(lbuf->continuation);
+
+ /*
+ * Print the buffer, splitting the line as needed on a word
+ * boundary.
+ */
+ cp = line;
+ have = lbuf->cols;
+ while (cp != NULL && *cp != '\0') {
+ char *ep = NULL;
+ size_t need = len - (size_t)(cp - line);
+
+ if (need > have) {
+ have -= contlen; /* subtract for continuation char */
+ if ((ep = memrchr(cp, ' ', have)) == NULL)
+ ep = memchr(cp + have, ' ', need - have);
+ if (ep != NULL)
+ need = (size_t)(ep - cp);
+ }
+ if (cp != line) {
+ if (is_comment) {
+ lbuf->output("# ");
+ } else {
+ /* indent continued lines */
+ /* XXX - build up string instead? */
+ for (i = 0; i < indent; i++)
+ lbuf->output(" ");
+ }
+ }
+ /* NUL-terminate cp for the output function and restore afterwards */
+ save = cp[need];
+ cp[need] = '\0';
+ lbuf->output(cp);
+ cp[need] = save;
+ cp = ep;
+
+ /*
+ * If there is more to print, reset have, incremement cp past
+ * the whitespace, and print a line continuaton char if needed.
+ */
+ if (cp != NULL) {
+ have = lbuf->cols - indent;
+ ep = line + len;
+ while (cp < ep && isblank((unsigned char)*cp)) {
+ cp++;
+ }
+ if (contlen)
+ lbuf->output(lbuf->continuation);
+ }
+ lbuf->output("\n");
+ }
+
+ debug_return;
+}
+
+/*
+ * Print the buffer with word wrap based on the tty width.
+ * The lbuf is reset on return.
+ * XXX - check output function return value
+ */
+void
+sudo_lbuf_print_v1(struct sudo_lbuf *lbuf)
+{
+ char *cp, *ep;
+ size_t len;
+ debug_decl(sudo_lbuf_print, SUDO_DEBUG_UTIL);
+
+ if (lbuf->buf == NULL || lbuf->len == 0)
+ goto done;
+
+ /* For very small widths just give up... */
+ len = lbuf->continuation ? strlen(lbuf->continuation) : 0;
+ if (lbuf->cols <= lbuf->indent + len + 20) {
+ lbuf->buf[lbuf->len] = '\0';
+ lbuf->output(lbuf->buf);
+ if (lbuf->buf[lbuf->len - 1] != '\n')
+ lbuf->output("\n");
+ goto done;
+ }
+
+ /* Print each line in the buffer */
+ for (cp = lbuf->buf; cp != NULL && *cp != '\0'; ) {
+ if (*cp == '\n') {
+ lbuf->output("\n");
+ cp++;
+ } else {
+ len = lbuf->len - (size_t)(cp - lbuf->buf);
+ if ((ep = memchr(cp, '\n', len)) != NULL)
+ len = (size_t)(ep - cp);
+ if (len)
+ sudo_lbuf_println(lbuf, cp, len);
+ cp = ep ? ep + 1 : NULL;
+ }
+ }
+
+done:
+ lbuf->len = 0; /* reset the buffer for re-use. */
+ lbuf->error = 0;
+
+ debug_return;
+}
+
+bool
+sudo_lbuf_error_v1(struct sudo_lbuf *lbuf)
+{
+ if (lbuf != NULL && lbuf->error != 0)
+ return true;
+ return false;
+}
+
+void
+sudo_lbuf_clearerr_v1(struct sudo_lbuf *lbuf)
+{
+ if (lbuf != NULL)
+ lbuf->error = 0;
+}
diff --git a/lib/util/localtime_r.c b/lib/util/localtime_r.c
new file mode 100644
index 0000000..180c890
--- /dev/null
+++ b/lib/util/localtime_r.c
@@ -0,0 +1,49 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_LOCALTIME_R
+
+#include <sys/types.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+/*
+ * Fake localtime_r() that just stores the result.
+ * Still has the normal localtime() side effects.
+ */
+struct tm *
+sudo_localtime_r(const time_t *timer, struct tm *result)
+{
+ struct tm *tm;
+
+ if ((tm = localtime(timer)) == NULL)
+ return NULL;
+ memcpy(result, tm, sizeof(struct tm));
+
+ return result;
+}
+#endif /* HAVE_LOCALTIME_T */
diff --git a/lib/util/locking.c b/lib/util/locking.c
new file mode 100644
index 0000000..a6bce60
--- /dev/null
+++ b/lib/util/locking.c
@@ -0,0 +1,143 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999-2005, 2007, 2009-2015
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_debug.h>
+
+bool
+sudo_lock_file_v1(int fd, int type)
+{
+ return sudo_lock_region_v1(fd, type, 0);
+}
+
+/*
+ * Lock/unlock all or part of a file.
+ */
+#ifdef HAVE_LOCKF
+bool
+sudo_lock_region_v1(int fd, int type, off_t len)
+{
+ int op, rc;
+ off_t oldpos = -1;
+ debug_decl(sudo_lock_region, SUDO_DEBUG_UTIL);
+
+ switch (type) {
+ case SUDO_LOCK:
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: lock %d:%lld",
+ __func__, fd, (long long)len);
+ op = F_LOCK;
+ break;
+ case SUDO_TLOCK:
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: tlock %d:%lld",
+ __func__, fd, (long long)len);
+ op = F_TLOCK;
+ break;
+ case SUDO_UNLOCK:
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: unlock %d:%lld",
+ __func__, fd, (long long)len);
+ op = F_ULOCK;
+ /* Must seek to start of file to unlock the entire thing. */
+ if (len == 0 && (oldpos = lseek(fd, 0, SEEK_CUR)) != -1) {
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to seek to beginning");
+ }
+ }
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: bad lock type %d",
+ __func__, type);
+ errno = EINVAL;
+ debug_return_bool(false);
+ }
+ rc = lockf(fd, op, len);
+ if (oldpos != -1) {
+ if (lseek(fd, oldpos, SEEK_SET) == -1) {
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to restore offset");
+ }
+ }
+ debug_return_bool(rc == 0);
+}
+#else
+bool
+sudo_lock_region_v1(int fd, int type, off_t len)
+{
+ struct flock lock;
+ int func;
+ debug_decl(sudo_lock_file, SUDO_DEBUG_UTIL);
+
+ switch (type) {
+ case SUDO_LOCK:
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: lock %d:%lld",
+ __func__, fd, (long long)len);
+ lock.l_type = F_WRLCK;
+ func = F_SETLKW;
+ break;
+ case SUDO_TLOCK:
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: tlock %d:%lld",
+ __func__, fd, (long long)len);
+ lock.l_type = F_WRLCK;
+ func = F_SETLK;
+ break;
+ case SUDO_UNLOCK:
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: unlock %d:%lld",
+ __func__, fd, (long long)len);
+ lock.l_type = F_UNLCK;
+ func = F_SETLK;
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: bad lock type %d",
+ __func__, type);
+ errno = EINVAL;
+ debug_return_bool(false);
+ }
+ lock.l_start = 0;
+ lock.l_len = len;
+ lock.l_pid = 0;
+ lock.l_whence = len ? SEEK_CUR : SEEK_SET;
+
+ debug_return_bool(fcntl(fd, func, &lock) == 0);
+}
+#endif
diff --git a/lib/util/logfac.c b/lib/util/logfac.c
new file mode 100644
index 0000000..cb9c3ce
--- /dev/null
+++ b/lib/util/logfac.c
@@ -0,0 +1,90 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999-2005, 2007-2019
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <syslog.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+
+/*
+ * For converting between syslog numbers and strings.
+ */
+struct strmap {
+ const char *name;
+ int num;
+};
+
+static const struct strmap facilities[] = {
+#ifdef LOG_AUTHPRIV
+ { "authpriv", LOG_AUTHPRIV },
+#endif
+ { "auth", LOG_AUTH },
+ { "daemon", LOG_DAEMON },
+ { "user", LOG_USER },
+ { "local0", LOG_LOCAL0 },
+ { "local1", LOG_LOCAL1 },
+ { "local2", LOG_LOCAL2 },
+ { "local3", LOG_LOCAL3 },
+ { "local4", LOG_LOCAL4 },
+ { "local5", LOG_LOCAL5 },
+ { "local6", LOG_LOCAL6 },
+ { "local7", LOG_LOCAL7 },
+ { NULL, -1 }
+};
+
+bool
+sudo_str2logfac_v1(const char *str, int *logfac)
+{
+ const struct strmap *fac;
+ debug_decl(sudo_str2logfac, SUDO_DEBUG_UTIL);
+
+ for (fac = facilities; fac->name != NULL; fac++) {
+ if (strcmp(str, fac->name) == 0) {
+ *logfac = fac->num;
+ debug_return_bool(true);
+ }
+ }
+ debug_return_bool(false);
+}
+
+const char *
+sudo_logfac2str_v1(int num)
+{
+ const struct strmap *fac;
+ debug_decl(sudo_logfac2str, SUDO_DEBUG_UTIL);
+
+ for (fac = facilities; fac->name != NULL; fac++) {
+ if (fac->num == num)
+ break;
+ }
+ debug_return_const_str(fac->name);
+}
diff --git a/lib/util/logpri.c b/lib/util/logpri.c
new file mode 100644
index 0000000..3fd1f6c
--- /dev/null
+++ b/lib/util/logpri.c
@@ -0,0 +1,85 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999-2005, 2007-2019
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <syslog.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+
+/*
+ * For converting between syslog numbers and strings.
+ */
+struct strmap {
+ const char *name;
+ int num;
+};
+
+static const struct strmap priorities[] = {
+ { "alert", LOG_ALERT },
+ { "crit", LOG_CRIT },
+ { "debug", LOG_DEBUG },
+ { "emerg", LOG_EMERG },
+ { "err", LOG_ERR },
+ { "info", LOG_INFO },
+ { "notice", LOG_NOTICE },
+ { "warning", LOG_WARNING },
+ { "none", -1 },
+ { NULL, -1 }
+};
+
+bool
+sudo_str2logpri_v1(const char *str, int *logpri)
+{
+ const struct strmap *pri;
+ debug_decl(sudo_str2logpri, SUDO_DEBUG_UTIL);
+
+ for (pri = priorities; pri->name != NULL; pri++) {
+ if (strcmp(str, pri->name) == 0) {
+ *logpri = pri->num;
+ debug_return_bool(true);
+ }
+ }
+ debug_return_bool(false);
+}
+
+const char *
+sudo_logpri2str_v1(int num)
+{
+ const struct strmap *pri;
+ debug_decl(sudo_logpri2str, SUDO_DEBUG_UTIL);
+
+ for (pri = priorities; pri->name != NULL; pri++) {
+ if (pri->num == num)
+ break;
+ }
+ debug_return_const_str(pri->name);
+}
diff --git a/lib/util/memrchr.c b/lib/util/memrchr.c
new file mode 100644
index 0000000..0a042e4
--- /dev/null
+++ b/lib/util/memrchr.c
@@ -0,0 +1,51 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2007, 2010-2014
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_MEMRCHR
+
+#include <sys/types.h>
+
+#include <sudo_compat.h>
+
+/*
+ * Reverse memchr()
+ * Find the last occurrence of 'c' in the buffer 's' of size 'n'.
+ */
+void *
+sudo_memrchr(const void *s, int c, size_t n)
+{
+ const unsigned char *cp;
+
+ if (n != 0) {
+ cp = (unsigned char *)s + n;
+ do {
+ if (*(--cp) == (unsigned char)c)
+ return (void *)cp;
+ } while (--n != 0);
+ }
+ return (void *)0;
+}
+#endif /* HAVE_MEMRCHR */
diff --git a/lib/util/mkdir_parents.c b/lib/util/mkdir_parents.c
new file mode 100644
index 0000000..b483748
--- /dev/null
+++ b/lib/util/mkdir_parents.c
@@ -0,0 +1,199 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+
+#ifndef O_NOFOLLOW
+# define O_NOFOLLOW 0
+#endif
+
+/*
+ * Returns true if fd is a directory, else false.
+ * Warns on failure if not quiet.
+ */
+static bool
+is_dir(int dfd, const char *name, int namelen, bool quiet)
+{
+ struct stat sb;
+ debug_decl(is_dir, SUDO_DEBUG_UTIL);
+
+ if (fstat(dfd, &sb) != 0) {
+ if (!quiet) {
+ sudo_warn(U_("unable to stat %.*s"), namelen, name);
+ }
+ debug_return_bool(false);
+ }
+ if (!S_ISDIR(sb.st_mode)) {
+ if (!quiet) {
+ sudo_warnx(U_("%.*s exists but is not a directory (0%o)"),
+ namelen, name, (unsigned int) sb.st_mode);
+ }
+ debug_return_bool(false);
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Create any parent directories needed by path (but not path itself)
+ * and return an open fd for the parent directory or -1 on error.
+ */
+int
+sudo_open_parent_dir_v1(const char *path, uid_t uid, gid_t gid, mode_t mode,
+ bool quiet)
+{
+ const char *cp, *ep, *pathend;
+ char name[PATH_MAX];
+ int parentfd;
+ debug_decl(sudo_open_parent_dir, SUDO_DEBUG_UTIL);
+
+ /* Starting parent dir is either root or cwd. */
+ cp = path;
+ if (*cp == '/') {
+ do {
+ cp++;
+ } while (*cp == '/');
+ parentfd = open("/", O_RDONLY|O_NONBLOCK);
+ } else {
+ parentfd = open(".", O_RDONLY|O_NONBLOCK);
+ }
+ if (parentfd == -1) {
+ if (!quiet)
+ sudo_warn(U_("unable to open %s"), *path == '/' ? "/" : ".");
+ debug_return_int(-1);
+ }
+
+ /* Iterate over path components, skipping the last one. */
+ pathend = cp + strlen(cp);
+ for (cp = sudo_strsplit(cp, pathend, "/", &ep); cp != NULL && ep < pathend;
+ cp = sudo_strsplit(NULL, pathend, "/", &ep)) {
+ size_t len = (size_t)(ep - cp);
+ int dfd;
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "mkdir %.*s, mode 0%o, uid %d, gid %d", (int)(ep - path), path,
+ (unsigned int)mode, (int)uid, (int)gid);
+ if (len >= sizeof(name)) {
+ errno = ENAMETOOLONG;
+ if (!quiet)
+ sudo_warn(U_("unable to mkdir %.*s"), (int)(ep - path), path);
+ goto bad;
+ }
+ memcpy(name, cp, len);
+ name[len] = '\0';
+reopen:
+ dfd = openat(parentfd, name, O_RDONLY|O_NONBLOCK, 0);
+ if (dfd == -1) {
+ if (errno != ENOENT) {
+ if (!quiet) {
+ sudo_warn(U_("unable to open %.*s"),
+ (int)(ep - path), path);
+ }
+ goto bad;
+ }
+ if (mkdirat(parentfd, name, mode) == 0) {
+ dfd = openat(parentfd, name, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0);
+ if (dfd == -1) {
+ if (!quiet) {
+ sudo_warn(U_("unable to open %.*s"),
+ (int)(ep - path), path);
+ }
+ goto bad;
+ }
+ /* Make sure the path we created is still a directory. */
+ if (!is_dir(dfd, path, (int)(ep - path), quiet)) {
+ close(dfd);
+ goto bad;
+ }
+ if (uid != (uid_t)-1 && gid != (gid_t)-1) {
+ if (fchown(dfd, uid, gid) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to chown %d:%d %.*s", __func__,
+ (int)uid, (int)gid, (int)(ep - path), path);
+ }
+ }
+ } else {
+ if (errno == EEXIST)
+ goto reopen;
+ if (!quiet) {
+ sudo_warn(U_("unable to mkdir %.*s"),
+ (int)(ep - path), path);
+ }
+ goto bad;
+ }
+ } else {
+ /* Already exists, make sure it is a directory. */
+ if (!is_dir(dfd, path, (int)(ep - path), quiet)) {
+ close(dfd);
+ goto bad;
+ }
+ }
+ close(parentfd);
+ parentfd = dfd;
+ }
+
+ debug_return_int(parentfd);
+bad:
+ if (parentfd != -1)
+ close(parentfd);
+ debug_return_int(-1);
+}
+
+/*
+ * Create any parent directories needed by path (but not path itself).
+ * Not currently used.
+ */
+bool
+sudo_mkdir_parents_v1(const char *path, uid_t uid, gid_t gid, mode_t mode,
+ bool quiet)
+{
+ int fd;
+ debug_decl(sudo_mkdir_parents, SUDO_DEBUG_UTIL);
+
+ fd = sudo_open_parent_dir(path, uid, gid, mode, quiet);
+ if (fd == -1)
+ debug_return_bool(false);
+ close(fd);
+ debug_return_bool(true);
+}
diff --git a/lib/util/mkdirat.c b/lib/util/mkdirat.c
new file mode 100644
index 0000000..18649b1
--- /dev/null
+++ b/lib/util/mkdirat.c
@@ -0,0 +1,61 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2015, 2019-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+
+#ifndef HAVE_MKDIRAT
+int
+sudo_mkdirat(int dfd, const char *path, mode_t mode)
+{
+ int ret, odfd;
+
+ if (dfd == (int)AT_FDCWD)
+ return mkdir(path, mode);
+
+ /* Save cwd */
+ if ((odfd = open(".", O_RDONLY)) == -1)
+ return -1;
+
+ if (fchdir(dfd) == -1) {
+ close(odfd);
+ return -1;
+ }
+
+ ret = mkdir(path, mode);
+
+ /* Restore cwd */
+ if (fchdir(odfd) == -1) {
+ /* Should not happen */
+ ret = -1;
+ }
+ close(odfd);
+
+ return ret;
+}
+#endif /* HAVE_MKDIRAT */
diff --git a/lib/util/mksiglist.c b/lib/util/mksiglist.c
new file mode 100644
index 0000000..6495e22
--- /dev/null
+++ b/lib/util/mksiglist.c
@@ -0,0 +1,57 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2012, 2015, 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <signal.h>
+
+#include <sudo_compat.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+int
+main(int argc, char *argv[])
+{
+ unsigned int i;
+
+#include "mksiglist.h"
+
+ /*
+ * For portability we must not use %zu below.
+ * This program is compiled with the host C compiler,
+ * so it cannot use any of the functions in libsudo_util.
+ */
+ puts("const char *const sudo_sys_siglist[] = {");
+ for (i = 0; i < NSIG; i++) {
+ if (sudo_sys_siglist[i] != NULL) {
+ printf(" \"%s\",\n", sudo_sys_siglist[i]);
+ } else {
+ printf(" \"Signal %u\",\n", i);
+ }
+ }
+ puts("};");
+
+ return EXIT_SUCCESS;
+}
diff --git a/lib/util/mksigname.c b/lib/util/mksigname.c
new file mode 100644
index 0000000..1b51199
--- /dev/null
+++ b/lib/util/mksigname.c
@@ -0,0 +1,57 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2012, 2015, 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <signal.h>
+
+#include <sudo_compat.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+int
+main(int argc, char *argv[])
+{
+ unsigned int i;
+
+#include "mksigname.h"
+
+ /*
+ * For portability we must not use %zu below.
+ * This program is compiled with the host C compiler,
+ * so it cannot use any of the functions in libsudo_util.
+ */
+ puts("const char *const sudo_sys_signame[] = {");
+ for (i = 0; i < NSIG; i++) {
+ if (sudo_sys_signame[i] != NULL) {
+ printf(" \"%s\",\n", sudo_sys_signame[i]);
+ } else {
+ printf(" \"Signal %u\",\n", i);
+ }
+ }
+ puts("};");
+
+ return EXIT_SUCCESS;
+}
diff --git a/lib/util/mktemp.c b/lib/util/mktemp.c
new file mode 100644
index 0000000..08f289a
--- /dev/null
+++ b/lib/util/mktemp.c
@@ -0,0 +1,172 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2001, 2003, 2004, 2008-2011, 2013, 2015, 2017, 2018, 2022
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#if (!defined(HAVE_MKDTEMPAT) && !defined(HAVE_MKDTEMPAT_NP)) || \
+ (!defined(HAVE_MKOSTEMPSAT) && !defined(HAVE_MKOSTEMPSAT_NP))
+
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_rand.h>
+#include <pathnames.h>
+
+#define MKTEMP_FILE 1
+#define MKTEMP_DIR 2
+
+#define TEMPCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+#define NUM_CHARS (sizeof(TEMPCHARS) - 1)
+#define MIN_X 6
+
+#define MKOTEMP_FLAGS (O_APPEND | O_CLOEXEC | O_SYNC)
+
+static int
+mktemp_internal(int dfd, char *path, int slen, int mode, int flags)
+{
+ char *start, *cp, *ep;
+ const char tempchars[] = TEMPCHARS;
+ unsigned int tries;
+ size_t len;
+ int fd;
+
+ len = strlen(path);
+ if (len < MIN_X || slen < 0 || (size_t)slen > len - MIN_X) {
+ errno = EINVAL;
+ return -1;
+ }
+ ep = path + len - slen;
+
+ for (start = ep; start > path && start[-1] == 'X'; start--)
+ ;
+ if (ep - start < MIN_X) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (flags & ~MKOTEMP_FLAGS) {
+ errno = EINVAL;
+ return -1;
+ }
+ flags |= O_CREAT | O_EXCL | O_RDWR;
+
+ tries = INT_MAX;
+ do {
+ cp = start;
+ do {
+ unsigned short rbuf[16];
+ size_t i;
+
+ /*
+ * Avoid lots of arc4random() calls by using
+ * a buffer sized for up to 16 Xs at a time.
+ */
+ arc4random_buf(rbuf, sizeof(rbuf));
+ for (i = 0; i < nitems(rbuf) && cp != ep; i++)
+ *cp++ = tempchars[rbuf[i] % NUM_CHARS];
+ } while (cp != ep);
+
+ switch (mode) {
+ case MKTEMP_FILE:
+ fd = openat(dfd, path, flags, S_IRUSR|S_IWUSR);
+ if (fd != -1 || errno != EEXIST)
+ return fd;
+ break;
+ case MKTEMP_DIR:
+ if (mkdirat(dfd, path, S_IRWXU) == 0)
+ return 0;
+ if (errno != EEXIST)
+ return -1;
+ break;
+ }
+ } while (--tries);
+
+ errno = EEXIST;
+ return -1;
+}
+
+char *
+sudo_mkdtemp(char *path)
+{
+ if (mktemp_internal(AT_FDCWD, path, 0, MKTEMP_DIR, 0) == -1)
+ return NULL;
+ return path;
+}
+
+char *
+sudo_mkdtempat(int dfd, char *path)
+{
+ if (mktemp_internal(dfd, path, 0, MKTEMP_DIR, 0) == -1)
+ return NULL;
+ return path;
+}
+
+int
+sudo_mkostempsat(int dfd, char *path, int slen, int flags)
+{
+ return mktemp_internal(dfd, path, slen, MKTEMP_FILE, flags);
+}
+
+#ifdef notyet
+int
+sudo_mkostemps(char *path, int slen, int flags)
+{
+ return mktemp_internal(AT_FDCWD, path, slen, MKTEMP_FILE, flags);
+}
+#endif
+
+int
+sudo_mkstemp(char *path)
+{
+ return mktemp_internal(AT_FDCWD, path, 0, MKTEMP_FILE, 0);
+}
+
+#ifdef notyet
+int
+sudo_mkostemp(char *path, int flags)
+{
+ return mktemp_internal(AT_FDCWD, path, 0, MKTEMP_FILE, flags);
+}
+#endif
+
+int
+sudo_mkstemps(char *path, int slen)
+{
+ return mktemp_internal(AT_FDCWD, path, slen, MKTEMP_FILE, 0);
+}
+#endif /* !HAVE_MKDTEMPAT || !HAVE_MKOSTEMPSAT */
diff --git a/lib/util/mmap_alloc.c b/lib/util/mmap_alloc.c
new file mode 100644
index 0000000..b587338
--- /dev/null
+++ b/lib/util/mmap_alloc.c
@@ -0,0 +1,160 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
+ * Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
+# define MAP_ANON MAP_ANONYMOUS
+#endif
+
+#ifndef MAP_FAILED
+# define MAP_FAILED ((void *)-1)
+#endif
+
+/*
+ * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+ * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+ */
+#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
+
+/*
+ * Allocate "size" bytes via mmap().
+ * Space is allocated to store the size for later unmapping.
+ */
+void *
+sudo_mmap_alloc_v1(size_t size)
+{
+ void *ptr;
+ unsigned long *ulp;
+#ifndef MAP_ANON
+ int fd;
+
+ /* SunOS-style mmap allocation using /dev/zero. */
+ if ((fd = open("/dev/zero", O_RDWR)) == -1)
+ return NULL;
+ size += sizeof(unsigned long);
+ ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ close(fd);
+#else
+ size += sizeof(unsigned long);
+ ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
+#endif
+ if (ptr == MAP_FAILED) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ /* Store size before the actual data. */
+ ulp = (unsigned long *)ptr;
+ ulp[0] = size;
+ return (void *)&ulp[1];
+}
+
+/*
+ * Allocate "nmemb" elements of "size" bytes via mmap().
+ * If overflow would occur, errno is set to ENOMEM and
+ * NULL is returned.
+ */
+void *
+sudo_mmap_allocarray_v1(size_t nmemb, size_t size)
+{
+ if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+ nmemb > 0 && SIZE_MAX / nmemb < size) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ return sudo_mmap_alloc_v1(nmemb * size);
+}
+
+/*
+ * Make a copy of "str" via mmap() and return it.
+ */
+char *
+sudo_mmap_strdup_v1(const char *str)
+{
+ size_t len = strlen(str);
+ char *newstr;
+
+ if (len == SIZE_MAX) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ newstr = sudo_mmap_alloc_v1(len + 1);
+ if (newstr != NULL) {
+ memcpy(newstr, str, len);
+ newstr[len] = '\0';
+ }
+
+ return newstr;
+}
+
+/*
+ * Set the page permissions for the allocation represented by "ptr" to
+ * read-only. Returns 0 on success, -1 on failure.
+ */
+int
+sudo_mmap_protect_v1(void *ptr)
+{
+ if (ptr != NULL) {
+ unsigned long *ulp = ptr;
+ const unsigned long size = ulp[-1];
+ return mprotect((void *)&ulp[-1], size, PROT_READ);
+ }
+
+ /* Can't protect NULL. */
+ errno = EINVAL;
+ return -1;
+}
+
+/*
+ * Free "ptr" allocated by sudo_mmap_alloc().
+ * The allocated size is stored (as unsigned long) in ptr[-1].
+ */
+void
+sudo_mmap_free_v1(void *ptr)
+{
+ if (ptr != NULL) {
+ unsigned long *ulp = (unsigned long *)ptr - 1;
+ const unsigned long size = ulp[0];
+ int saved_errno = errno;
+
+ (void)munmap((void *)ulp, size);
+ errno = saved_errno;
+ }
+}
diff --git a/lib/util/multiarch.c b/lib/util/multiarch.c
new file mode 100644
index 0000000..0b79de5
--- /dev/null
+++ b/lib/util/multiarch.c
@@ -0,0 +1,103 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef __linux__
+# include <sys/stat.h>
+# include <sys/utsname.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+# if defined(__linux__)
+/*
+ * On Linux systems that use multi-arch, the actual DSO may be in a
+ * machine-specific subdirectory. If the specified path contains
+ * /lib/ or /libexec/, insert a multi-arch directory after it.
+ * If sb is non-NULL, stat(2) will be called on the new path, filling in sb.
+ * Returns a dynamically allocated string on success and NULL on failure.
+ */
+char *
+sudo_stat_multiarch_v1(const char *path, struct stat *sb)
+{
+# if defined(__ILP32__)
+ const char *libdirs[] = { "/libx32/", "/lib/", "/libexec/", NULL };
+# elif defined(__LP64__)
+ const char *libdirs[] = { "/lib64/", "/lib/", "/libexec/", NULL };
+# else
+ const char *libdirs[] = { "/lib32/", "/lib/", "/libexec/", NULL };
+# endif
+ const char **lp, *lib, *slash;
+ struct utsname unamebuf;
+ char *newpath = NULL;
+ size_t len;
+
+ if (uname(&unamebuf) == -1)
+ return NULL;
+
+ for (lp = libdirs; *lp != NULL; lp++) {
+ /* Replace lib64, lib32, libx32 with lib in new path. */
+ const char *newlib = lp == libdirs ? "/lib/" : *lp;
+
+ /* Search for lib dir in path, find the trailing slash. */
+ lib = strstr(path, *lp);
+ if (lib == NULL)
+ continue;
+ slash = lib + strlen(*lp) - 1;
+
+ /* Make sure there isn't already a machine-linux-gnu dir. */
+ len = strcspn(slash + 1, "/-");
+ if (strncmp(slash + 1 + len, "-linux-gnu/", 11) == 0) {
+ /* Multiarch already present. */
+ break;
+ }
+
+ /* Add machine-linux-gnu dir after /lib/ or /libexec/. */
+ if (asprintf(&newpath, "%.*s%s%s-linux-gnu%s",
+ (int)(lib - path), path, newlib, unamebuf.machine, slash) == -1) {
+ newpath = NULL;
+ break;
+ }
+
+ /* If sb was set, use stat(2) to make sure newpath exists. */
+ if (sb == NULL || stat(newpath, sb) == 0)
+ break;
+ free(newpath);
+ newpath = NULL;
+ }
+
+ return newpath;
+}
+#else
+char *
+sudo_stat_multiarch_v1(const char *path, struct stat *sb)
+{
+ return NULL;
+}
+#endif /* __linux__ */
diff --git a/lib/util/nanosleep.c b/lib/util/nanosleep.c
new file mode 100644
index 0000000..84c41b8
--- /dev/null
+++ b/lib/util/nanosleep.c
@@ -0,0 +1,74 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2011, 2013, 2017-2018, 2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_NANOSLEEP
+
+#include <sys/types.h>
+#include <sys/time.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif /* HAVE_SYS_SELECT_H */
+#include <time.h>
+#include <errno.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+int
+sudo_nanosleep(const struct timespec *timeout, struct timespec *remainder)
+{
+ struct timespec endtime, now;
+ struct timeval tv;
+ int rval;
+
+ if (timeout->tv_sec == 0 && timeout->tv_nsec < 1000) {
+ tv.tv_sec = 0;
+ tv.tv_usec = 1;
+ } else {
+ TIMESPEC_TO_TIMEVAL(&tv, timeout);
+ }
+ if (remainder != NULL) {
+ if (sudo_gettime_real(&endtime) == -1)
+ return -1;
+ sudo_timespecadd(&endtime, timeout, &endtime);
+ }
+ rval = select(0, NULL, NULL, NULL, &tv);
+ if (remainder != NULL) {
+ if (rval == 0) {
+ /* Timeout expired, no remaining time. */
+ sudo_timespecclear(remainder);
+ } else if (errno == EINTR) {
+ /* Interrupted, compute remaining time. */
+ if (sudo_gettime_real(&now) == -1)
+ return -1;
+ sudo_timespecsub(&endtime, &now, remainder);
+ if (remainder->tv_sec < 0 || remainder->tv_nsec < 0)
+ sudo_timespecclear(remainder);
+ }
+ }
+ return rval;
+}
+#endif /* HAVE_NANOSLEEP */
diff --git a/lib/util/openat.c b/lib/util/openat.c
new file mode 100644
index 0000000..b748be9
--- /dev/null
+++ b/lib/util/openat.c
@@ -0,0 +1,63 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2015, 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+
+#ifndef HAVE_OPENAT
+int
+sudo_openat(int dfd, const char *path, int flags, mode_t mode)
+{
+ int fd, odfd;
+
+ if (dfd == AT_FDCWD)
+ return open(path, flags, mode);
+
+ /* Save cwd */
+ if ((odfd = open(".", O_RDONLY)) == -1)
+ return -1;
+
+ if (fchdir(dfd) == -1) {
+ close(odfd);
+ return -1;
+ }
+
+ fd = open(path, flags, mode);
+
+ /* Restore cwd */
+ if (fchdir(odfd) == -1) {
+ /* Should not happen */
+ if (fd != -1) {
+ close(fd);
+ fd = -1;
+ }
+ }
+ close(odfd);
+
+ return fd;
+}
+#endif /* HAVE_OPENAT */
diff --git a/lib/util/parseln.c b/lib/util/parseln.c
new file mode 100644
index 0000000..ec10d9d
--- /dev/null
+++ b/lib/util/parseln.c
@@ -0,0 +1,130 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2007, 2013-2016 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_debug.h>
+
+/*
+ * Read a line of input, honoring line continuation chars.
+ * Remove comments and strip off leading and trailing spaces.
+ * Returns the line length and updates the buf and bufsize pointers.
+ * XXX - just use a struct w/ state, including getdelim buffer?
+ * could also make comment char and line continuation configurable
+ */
+ssize_t
+sudo_parseln_v2(char **bufp, size_t *bufsizep, unsigned int *lineno, FILE *fp, int flags)
+{
+ ssize_t len, total = 0;
+ size_t bufsize, linesize = 0;
+ char *cp, *line = NULL;
+ bool continued, comment;
+ debug_decl(sudo_parseln, SUDO_DEBUG_UTIL);
+
+ do {
+ comment = false;
+ continued = false;
+ len = getdelim(&line, &linesize, '\n', fp);
+ if (len == -1)
+ break;
+ if (lineno != NULL)
+ (*lineno)++;
+
+ /* Remove trailing newline(s) if present. */
+ while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r'))
+ line[--len] = '\0';
+
+ /* Remove comments or check for line continuation (but not both) */
+ if ((cp = strchr(line, '#')) != NULL) {
+ if (cp == line || !ISSET(flags, PARSELN_COMM_BOL)) {
+ *cp = '\0';
+ len = (ssize_t)(cp - line);
+ comment = true;
+ }
+ }
+ if (!comment && !ISSET(flags, PARSELN_CONT_IGN)) {
+ if (len > 0 && line[len - 1] == '\\' && (len == 1 || line[len - 2] != '\\')) {
+ line[--len] = '\0';
+ continued = true;
+ }
+ }
+
+ /* Trim leading and trailing whitespace */
+ if (!continued) {
+ while (len > 0 && isblank((unsigned char)line[len - 1]))
+ line[--len] = '\0';
+ }
+ for (cp = line; isblank((unsigned char)*cp); cp++)
+ len--;
+
+ bufsize = (size_t)(total + len + 1);
+ if (*bufp == NULL || bufsize > *bufsizep) {
+ const size_t newsize = sudo_pow2_roundup(bufsize);
+ void *newbuf;
+
+ if (newsize < bufsize) {
+ /* overflow */
+ errno = ENOMEM;
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ len = -1;
+ total = 0;
+ break;
+ }
+ if ((newbuf = realloc(*bufp, newsize)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ len = -1;
+ total = 0;
+ break;
+ }
+ *bufp = newbuf;
+ *bufsizep = newsize;
+ }
+ memcpy(*bufp + total, cp, (size_t)(len + 1));
+ total += len;
+ } while (continued);
+ free(line);
+ if (len == -1 && total == 0)
+ debug_return_ssize_t(-1);
+ debug_return_ssize_t(total);
+}
+
+ssize_t
+sudo_parseln_v1(char **bufp, size_t *bufsizep, unsigned int *lineno, FILE *fp)
+{
+ return sudo_parseln_v2(bufp, bufsizep, lineno, fp, 0);
+}
diff --git a/lib/util/pipe2.c b/lib/util/pipe2.c
new file mode 100644
index 0000000..1ffcad0
--- /dev/null
+++ b/lib/util/pipe2.c
@@ -0,0 +1,64 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2017 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_PIPE2
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+
+int
+sudo_pipe2(int fildes[2], int flags)
+{
+ if (pipe(fildes) != 0)
+ return -1;
+
+ if (ISSET(flags, O_CLOEXEC)) {
+ if (fcntl(fildes[0], F_SETFD, FD_CLOEXEC) == -1)
+ goto bad;
+ if (fcntl(fildes[1], F_SETFD, FD_CLOEXEC) == -1)
+ goto bad;
+ }
+ if (ISSET(flags, O_NONBLOCK)) {
+ int oflags = fcntl(fildes[0], F_GETFL, 0);
+ if (oflags == -1)
+ goto bad;
+ if (fcntl(fildes[0], F_SETFL, oflags | O_NONBLOCK) == -1)
+ goto bad;
+ oflags = fcntl(fildes[1], F_GETFL, 0);
+ if (oflags == -1)
+ goto bad;
+ if (fcntl(fildes[1], F_SETFL, oflags | O_NONBLOCK) == -1)
+ goto bad;
+ }
+ return 0;
+bad:
+ close(fildes[0]);
+ close(fildes[1]);
+ return -1;
+}
+
+#endif /* HAVE_PIPE2 */
diff --git a/lib/util/pread.c b/lib/util/pread.c
new file mode 100644
index 0000000..a8a4774
--- /dev/null
+++ b/lib/util/pread.c
@@ -0,0 +1,48 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+
+#if !defined(HAVE_PREAD) && !defined(HAVE_PREAD64)
+ssize_t
+sudo_pread(int fd, void *buf, size_t nbytes, off_t offset)
+{
+ ssize_t nread;
+ off_t old_offset;
+
+ old_offset = lseek(fd, (off_t)0, SEEK_CUR);
+ if (old_offset == -1 || lseek(fd, offset, SEEK_SET) == -1)
+ return -1;
+
+ nread = read(fd, buf, nbytes);
+ if (lseek(fd, old_offset, SEEK_SET) == -1)
+ return -1;
+
+ return nread;
+}
+#endif /* !HAVE_PREAD && !HAVE_PREAD64 */
diff --git a/lib/util/progname.c b/lib/util/progname.c
new file mode 100644
index 0000000..9355b6a
--- /dev/null
+++ b/lib/util/progname.c
@@ -0,0 +1,100 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2015, 2020-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+/*
+ * Declare/define __progname[] if necessary.
+ * Assumes __progname[] is present if we have getprogname(3).
+ */
+#ifndef HAVE_SETPROGNAME
+# if defined(HAVE_GETPROGNAME) || defined(HAVE___PROGNAME)
+extern const char *__progname;
+# else
+static const char *__progname = "";
+# endif /* HAVE_GETPROGNAME || HAVE___PROGNAME */
+#endif /* HAVE_SETPROGNAME */
+
+#ifndef HAVE_GETPROGNAME
+const char *
+sudo_getprogname(void)
+{
+ return __progname;
+}
+#endif
+
+#ifndef HAVE_SETPROGNAME
+void
+sudo_setprogname(const char *name)
+{
+ __progname = sudo_basename(name);
+}
+#endif
+
+void
+initprogname2(const char *name, const char * const * allowed)
+{
+ const char *progname;
+ size_t i;
+
+ /* Fall back on "name" if getprogname() returns an empty string. */
+ if ((progname = getprogname()) != NULL && *progname != '\0') {
+ name = progname;
+ } else {
+ /* Make sure user-specified name is relative. */
+ name = sudo_basename(name);
+ }
+
+ /* Check for libtool prefix and strip it if present. */
+ if (name[0] == 'l' && name[1] == 't' && name[2] == '-' && name[3] != '\0')
+ name += 3;
+
+ /* Check allow list if present (first element is the default). */
+ if (allowed != NULL) {
+ for (i = 0; ; i++) {
+ if (allowed[i] == NULL) {
+ name = allowed[0];
+ break;
+ }
+ if (strcmp(allowed[i], name) == 0)
+ break;
+ }
+ }
+
+ /* Update internal progname if needed. */
+ if (name != progname)
+ setprogname(name);
+ return;
+}
+
+void
+initprogname(const char *name)
+{
+ initprogname2(name, NULL);
+}
diff --git a/lib/util/pw_dup.c b/lib/util/pw_dup.c
new file mode 100644
index 0000000..d643b5b
--- /dev/null
+++ b/lib/util/pw_dup.c
@@ -0,0 +1,99 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2000, 2002, 2012-2014
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_PW_DUP
+
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+
+#include <sudo_compat.h>
+
+#define PW_SIZE(name, size) \
+do { \
+ if (pw->name) { \
+ size = strlen(pw->name) + 1; \
+ total += size; \
+ } \
+} while (0)
+
+#define PW_COPY(name, size) \
+do { \
+ if (pw->name) { \
+ (void)memcpy(cp, pw->name, size); \
+ newpw->name = cp; \
+ cp += size; \
+ } \
+} while (0)
+
+struct passwd *
+sudo_pw_dup(const struct passwd *pw)
+{
+ size_t nsize = 0, psize = 0, gsize = 0, dsize = 0, ssize = 0, total;
+#ifdef HAVE_LOGIN_CAP_H
+ size_t csize = 0;
+#endif
+ struct passwd *newpw;
+ char *cp;
+
+ /* Allocate in one big chunk for easy freeing */
+ total = sizeof(struct passwd);
+ PW_SIZE(pw_name, nsize);
+ PW_SIZE(pw_passwd, psize);
+#ifdef HAVE_LOGIN_CAP_H
+ PW_SIZE(pw_class, csize);
+#endif
+ PW_SIZE(pw_gecos, gsize);
+ PW_SIZE(pw_dir, dsize);
+ PW_SIZE(pw_shell, ssize);
+
+ if ((cp = malloc(total)) == NULL)
+ return NULL;
+ newpw = (struct passwd *)cp;
+
+ /*
+ * Copy in passwd contents and make strings relative to space
+ * at the end of the buffer.
+ */
+ (void)memcpy(newpw, pw, sizeof(struct passwd));
+ cp += sizeof(struct passwd);
+
+ PW_COPY(pw_name, nsize);
+ PW_COPY(pw_passwd, psize);
+#ifdef HAVE_LOGIN_CAP_H
+ PW_COPY(pw_class, csize);
+#endif
+ PW_COPY(pw_gecos, gsize);
+ PW_COPY(pw_dir, dsize);
+ PW_COPY(pw_shell, ssize);
+
+ return newpw;
+}
+#endif /* HAVE_PW_DUP */
diff --git a/lib/util/pwrite.c b/lib/util/pwrite.c
new file mode 100644
index 0000000..24dba6c
--- /dev/null
+++ b/lib/util/pwrite.c
@@ -0,0 +1,48 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+
+#if !defined(HAVE_PWRITE) && !defined(HAVE_PWRITE64)
+ssize_t
+sudo_pwrite(int fd, const void *buf, size_t nbytes, off_t offset)
+{
+ ssize_t nwritten;
+ off_t old_offset;
+
+ old_offset = lseek(fd, (off_t)0, SEEK_CUR);
+ if (old_offset == -1 || lseek(fd, offset, SEEK_SET) == -1)
+ return -1;
+
+ nwritten = write(fd, buf, nbytes);
+ if (lseek(fd, old_offset, SEEK_SET) == -1)
+ return -1;
+
+ return nwritten;
+}
+#endif /* HAVE_PWRITE && !HAVE_PWRITE64 */
diff --git a/lib/util/rcstr.c b/lib/util/rcstr.c
new file mode 100644
index 0000000..1fefbad
--- /dev/null
+++ b/lib/util/rcstr.c
@@ -0,0 +1,103 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2016-2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+
+/* Trivial reference-counted strings. */
+struct rcstr {
+ int refcnt;
+ char str[];
+};
+
+/*
+ * Allocate a reference-counted string and copy src to it.
+ * Returns the newly-created string with a refcnt of 1.
+ */
+char *
+sudo_rcstr_dup(const char *src)
+{
+ size_t len = strlen(src);
+ char *dst;
+ debug_decl(sudo_rcstr_dup, SUDO_DEBUG_UTIL);
+
+ dst = sudo_rcstr_alloc(len);
+ if (dst != NULL) {
+ memcpy(dst, src, len);
+ dst[len] = '\0';
+ }
+ debug_return_ptr(dst);
+}
+
+char *
+sudo_rcstr_alloc(size_t len)
+{
+ struct rcstr *rcs;
+ debug_decl(sudo_rcstr_dup, SUDO_DEBUG_UTIL);
+
+ rcs = malloc(sizeof(struct rcstr) + len + 1);
+ if (rcs == NULL)
+ return NULL;
+
+ rcs->refcnt = 1;
+ rcs->str[0] = '\0';
+ /* cppcheck-suppress memleak */
+ debug_return_ptr(rcs->str); // -V773
+}
+
+char *
+sudo_rcstr_addref(const char *s)
+{
+ struct rcstr *rcs;
+ debug_decl(sudo_rcstr_dup, SUDO_DEBUG_UTIL);
+
+ if (s == NULL)
+ debug_return_ptr(NULL);
+
+ rcs = __containerof((const void *)s, struct rcstr, str);
+ rcs->refcnt++;
+ debug_return_ptr(rcs->str);
+}
+
+void
+sudo_rcstr_delref(const char *s)
+{
+ struct rcstr *rcs;
+ debug_decl(sudo_rcstr_dup, SUDO_DEBUG_UTIL);
+
+ if (s != NULL) {
+ rcs = __containerof((const void *)s, struct rcstr, str);
+ if (--rcs->refcnt == 0) {
+ rcs->str[0] = '\0';
+ free(rcs);
+ }
+ }
+ debug_return;
+}
diff --git a/lib/util/reallocarray.c b/lib/util/reallocarray.c
new file mode 100644
index 0000000..63d7882
--- /dev/null
+++ b/lib/util/reallocarray.c
@@ -0,0 +1,57 @@
+/* $OpenBSD: reallocarray.c,v 1.2 2014/12/08 03:45:00 bcook Exp $ */
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_REALLOCARRAY
+
+#include <stdlib.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <errno.h>
+#include <limits.h>
+
+#include <sudo_compat.h>
+
+/*
+ * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+ * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+ */
+#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
+
+void *
+sudo_reallocarray(void *optr, size_t nmemb, size_t size)
+{
+ if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+ nmemb > 0 && SIZE_MAX / nmemb < size) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ return realloc(optr, size * nmemb);
+}
+
+#endif /* HAVE_REALLOCARRAY */
diff --git a/lib/util/realpath.c b/lib/util/realpath.c
new file mode 100644
index 0000000..9e945af
--- /dev/null
+++ b/lib/util/realpath.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 1989, 1991, 1993, 1995
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)getcwd.c 8.5 (Berkeley) 2/7/95
+ */
+
+#include <config.h>
+
+#ifndef HAVE_REALPATH
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * char *realpath(const char *path, char *resolved);
+ *
+ * Find the real name of path, by removing all ".", ".." and symlink
+ * components. Returns (resolved) on success, or (NULL) on failure,
+ * in which case the path which caused trouble is left in (resolved).
+ */
+char *
+sudo_realpath(const char * restrict path, char * restrict resolved)
+{
+ struct stat sb;
+ int idx = 0, nlnk = 0;
+ const char *q;
+ char *p, wbuf[2][PATH_MAX], *fres = NULL;
+ static long symloop_max;
+ size_t len;
+ ssize_t n;
+
+ if (path == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (symloop_max == 0) {
+ if ((symloop_max = sysconf(_SC_SYMLOOP_MAX)) <= 0)
+ symloop_max = 8; /* POSIX */
+ }
+
+ if (resolved == NULL) {
+ fres = resolved = malloc(PATH_MAX);
+ if (resolved == NULL)
+ return NULL;
+ }
+
+
+ /*
+ * Build real path one by one with paying an attention to .,
+ * .. and symbolic link.
+ */
+
+ /*
+ * `p' is where we'll put a new component with prepending
+ * a delimiter.
+ */
+ p = resolved;
+
+ if (*path == '\0') {
+ *p = '\0';
+ errno = ENOENT;
+ goto out;
+ }
+
+ /* If relative path, start from current working directory. */
+ if (*path != '/') {
+ if (getcwd(resolved, PATH_MAX) == NULL) {
+ p[0] = '.';
+ p[1] = '\0';
+ goto out;
+ }
+ len = strlen(resolved);
+ if (len > 1)
+ p += len;
+ }
+
+loop:
+ /* Skip any slash. */
+ while (*path == '/')
+ path++;
+
+ if (*path == '\0') {
+ if (p == resolved)
+ *p++ = '/';
+ *p = '\0';
+ return resolved;
+ }
+
+ /* Find the end of this component. */
+ q = path;
+ do {
+ q++;
+ } while (*q != '/' && *q != '\0');
+
+ /* Test . or .. */
+ if (path[0] == '.') {
+ if (q - path == 1) {
+ path = q;
+ goto loop;
+ }
+ if (path[1] == '.' && q - path == 2) {
+ /* Trim the last component. */
+ if (p != resolved)
+ while (*--p != '/')
+ continue;
+ path = q;
+ goto loop;
+ }
+ }
+
+ /* Append this component. */
+ if (p - resolved + 1 + q - path + 1 > PATH_MAX) {
+ errno = ENAMETOOLONG;
+ if (p == resolved)
+ *p++ = '/';
+ *p = '\0';
+ goto out;
+ }
+ p[0] = '/';
+ memcpy(&p[1], path, (size_t)(q - path));
+ p[1 + q - path] = '\0';
+
+ /*
+ * If this component is a symlink, toss it and prepend link
+ * target to unresolved path.
+ */
+ if (lstat(resolved, &sb) == -1)
+ goto out;
+
+ if (S_ISLNK(sb.st_mode)) {
+ if (nlnk++ >= symloop_max) {
+ errno = ELOOP;
+ goto out;
+ }
+ n = readlink(resolved, wbuf[idx], sizeof(wbuf[0]) - 1);
+ if (n < 0)
+ goto out;
+ if (n == 0) {
+ errno = ENOENT;
+ goto out;
+ }
+
+ /* Append unresolved path to link target and switch to it. */
+ if ((size_t)n + (len = strlen(q)) + 1 > sizeof(wbuf[0])) {
+ errno = ENAMETOOLONG;
+ goto out;
+ }
+ memcpy(&wbuf[idx][n], q, len + 1);
+ path = wbuf[idx];
+ idx ^= 1;
+
+ /* If absolute symlink, start from root. */
+ if (*path == '/')
+ p = resolved;
+ goto loop;
+ }
+ if (*q == '/' && !S_ISDIR(sb.st_mode)) {
+ errno = ENOTDIR;
+ goto out;
+ }
+
+ /* Advance both resolved and unresolved path. */
+ p += 1 + q - path;
+ path = q;
+ goto loop;
+out:
+ free(fres);
+ return NULL;
+}
+#endif /* HAVE_REALPATH */
diff --git a/lib/util/regex.c b/lib/util/regex.c
new file mode 100644
index 0000000..1f91b4d
--- /dev/null
+++ b/lib/util/regex.c
@@ -0,0 +1,194 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <regex.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+#include <sudo_gettext.h>
+
+static char errbuf[1024];
+
+/*
+ * Parse a number between 0 and INT_MAX, handling escaped digits.
+ * Returns the number on success or -1 on error.
+ * Sets endp to the first non-matching character.
+ */
+static int
+parse_num(const char *str, char **endp)
+{
+ debug_decl(check_pattern, SUDO_DEBUG_UTIL);
+ const int lastval = INT_MAX / 10;
+ const int remainder = INT_MAX % 10;
+ int result = 0;
+ char ch;
+
+ while ((ch = *str++) != '\0') {
+ if (ch == '\\' && isdigit((unsigned char)str[0]))
+ ch = *str++;
+ else if (!isdigit((unsigned char)ch))
+ break;
+ ch -= '0';
+ if (result > lastval || (result == lastval && ch > remainder)) {
+ result = -1;
+ break;
+ }
+ result *= 10;
+ result += ch;
+ }
+ *endp = (char *)(str - 1);
+
+ debug_return_int(result);
+}
+
+/*
+ * Check pattern for invalid repetition sequences.
+ * This is implementation-specific behavior, not all regcomp(3) forbid them.
+ * Glibc allows it but uses excessive memory for repeated '+' ops.
+ */
+static int
+check_pattern(const char *pattern)
+{
+ debug_decl(check_pattern, SUDO_DEBUG_UTIL);
+ const char *cp = pattern;
+ int b1, b2 = 0;
+ char ch, *ep, prev = '\0';
+
+ while ((ch = *cp++) != '\0') {
+ switch (ch) {
+ case '\\':
+ if (*cp != '\0') {
+ /* Skip escaped character. */
+ cp++;
+ prev = '\0';
+ continue;
+ }
+ break;
+ case '?':
+ case '*':
+ case '+':
+ if (prev == '?' || prev == '*' || prev == '+' || prev == '{' ) {
+ /* Invalid repetition operator. */
+ debug_return_int(REG_BADRPT);
+ }
+ break;
+ case '{':
+ /*
+ * Try to match bound: {[0-9\\]*\?,[0-9\\]*}
+ * GNU libc supports escaped digits and commas.
+ */
+ b1 = parse_num(cp, &ep);
+ switch (ep[0]) {
+ case '\\':
+ if (ep[1] != ',')
+ break;
+ ep++;
+ FALLTHROUGH;
+ case ',':
+ cp = ep + 1;
+ b2 = parse_num(cp, &ep);
+ break;
+ }
+ cp = ep;
+ if (*cp == '}') {
+ if (b1 < 0 || b1 > 255 || b2 < 0 || b2 > 255) {
+ /* Invalid bound value. */
+ debug_return_int(REG_BADBR);
+ }
+ if (prev == '?' || prev == '*' || prev == '+' || prev == '{' ) {
+ /* Invalid repetition operator. */
+ debug_return_int(REG_BADRPT);
+ }
+ /* Skip past '}', prev will be set to '{' below */
+ cp++;
+ break;
+ }
+ prev = '\0';
+ continue;
+ }
+ prev = ch;
+ }
+
+ debug_return_int(0);
+}
+
+/*
+ * Wrapper around regcomp() that handles a regex starting with (?i).
+ * Avoid using regex_t in the function args so we don't need to
+ * include regex.h everywhere.
+ */
+bool
+sudo_regex_compile_v1(void *v, const char *pattern, const char **errstr)
+{
+ int errcode, cflags = REG_EXTENDED|REG_NOSUB;
+ regex_t *preg;
+ char *copy = NULL;
+ const char *cp;
+ regex_t rebuf;
+ debug_decl(regex_compile, SUDO_DEBUG_UTIL);
+
+ /* Some callers just want to check the validity of the pattern. */
+ preg = v ? v : &rebuf;
+
+ /* Limit the length of regular expressions to avoid fuzzer issues. */
+ if (strlen(pattern) > 1024) {
+ *errstr = N_("regular expression too large");
+ debug_return_bool(false);
+ }
+
+ /* Check for (?i) to enable case-insensitive matching. */
+ cp = pattern[0] == '^' ? pattern + 1 : pattern;
+ if (strncmp(cp, "(?i)", 4) == 0) {
+ cflags |= REG_ICASE;
+ copy = strdup(pattern + 4);
+ if (copy == NULL) {
+ *errstr = N_("unable to allocate memory");
+ debug_return_bool(false);
+ }
+ if (pattern[0] == '^')
+ copy[0] = '^';
+ pattern = copy;
+ }
+
+ errcode = check_pattern(pattern);
+ if (errcode == 0)
+ errcode = regcomp(preg, pattern, cflags);
+ if (errcode == 0) {
+ if (preg == &rebuf)
+ regfree(&rebuf);
+ } else {
+ regerror(errcode, preg, errbuf, sizeof(errbuf));
+ *errstr = errbuf;
+ }
+ free(copy);
+
+ debug_return_bool(errcode == 0);
+}
diff --git a/lib/util/regress/closefrom/closefrom_test.c b/lib/util/regress/closefrom/closefrom_test.c
new file mode 100644
index 0000000..750c951
--- /dev/null
+++ b/lib/util/regress/closefrom/closefrom_test.c
@@ -0,0 +1,121 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/*
+ * Test that sudo_closefrom() works as expected.
+ */
+
+int
+main(int argc, char *argv[])
+{
+ int ch, fds[2], flag, maxfd, minfd, errors = 0, ntests = 0;
+ initprogname(argc > 0 ? argv[0] : "closefrom_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* We use pipe() because it doesn't rely on the filesystem. */
+ ntests++;
+ if (pipe(fds) == -1) {
+ sudo_warn("%s", "pipe");
+ errors++;
+ goto done;
+ }
+ maxfd = MAX(fds[0], fds[1]);
+ minfd = MIN(fds[0], fds[1]);
+
+ /* Close any fds greater than fds[0] and fds[1]. */
+ sudo_closefrom(maxfd + 1);
+
+ /* Verify that sudo_closefrom() didn't close fds[0] or fds[1]. */
+ ntests++;
+ if (fcntl(fds[0], F_GETFL, 0) == -1) {
+ sudo_warnx("fd %d closed prematurely", fds[0]);
+ errors++;
+ goto done;
+ }
+ ntests++;
+ if (fcntl(fds[1], F_GETFL, 0) == -1) {
+ sudo_warnx("fd %d closed prematurely", fds[1]);
+ errors++;
+ goto done;
+ }
+
+ /* Close fds[0], fds[1] and above. */
+ sudo_closefrom(minfd);
+
+ /* Verify that sudo_closefrom() closed both fds. */
+ ntests++;
+ flag = fcntl(fds[0], F_GETFD, 0);
+#ifdef __APPLE__
+ /* We only set the close-on-exec flag on macOS. */
+ if (flag == 1)
+ flag = -1;
+#endif
+ if (flag != -1) {
+ sudo_warnx("fd %d still open", fds[0]);
+ errors++;
+ goto done;
+ }
+ ntests++;
+ flag = fcntl(fds[1], F_GETFD, 0);
+#ifdef __APPLE__
+ /* We only set the close-on-exec flag on macOS. */
+ if (flag == 1)
+ flag = -1;
+#endif
+ if (flag != -1) {
+ sudo_warnx("fd %d still open", fds[1]);
+ errors++;
+ goto done;
+ }
+
+done:
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+ return errors;
+}
diff --git a/lib/util/regress/corpus/seed/sudo_conf/sudo.conf.1 b/lib/util/regress/corpus/seed/sudo_conf/sudo.conf.1
new file mode 100644
index 0000000..1a58c87
--- /dev/null
+++ b/lib/util/regress/corpus/seed/sudo_conf/sudo.conf.1
@@ -0,0 +1,116 @@
+#
+# Default /etc/sudo.conf file
+#
+# Sudo plugins:
+# Plugin plugin_name plugin_path plugin_options ...
+#
+# The plugin_path is relative to /usr/local/libexec/sudo unless
+# fully qualified.
+# The plugin_name corresponds to a global symbol in the plugin
+# that contains the plugin interface structure.
+# The plugin_options are optional.
+#
+# The sudoers plugin is used by default if no Plugin lines are present.
+#Plugin sudoers_policy sudoers.so
+#Plugin sudoers_io sudoers.so
+#Plugin sudoers_audit sudoers.so
+
+#
+# Sudo askpass:
+# Path askpass /path/to/askpass
+#
+# An askpass helper program may be specified to provide a graphical
+# password prompt for "sudo -A" support. Sudo does not ship with its
+# own askpass program but can use the OpenSSH askpass.
+#
+# Use the OpenSSH askpass
+#Path askpass /usr/X11R6/bin/ssh-askpass
+#
+# Use the Gnome OpenSSH askpass
+#Path askpass /usr/libexec/openssh/gnome-ssh-askpass
+
+#
+# Sudo device search path:
+# Path devsearch /dev/path1:/dev/path2:/dev
+#
+# A colon-separated list of paths to check when searching for a user's
+# terminal device.
+#
+#Path devsearch /dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev
+
+#
+# Sudo noexec:
+# Path noexec /path/to/sudo_noexec.so
+#
+# Path to a shared library containing replacements for the execv(),
+# execve() and fexecve() library functions that just return an error.
+# This is used to implement the "noexec" functionality on systems that
+# support LD_PRELOAD or its equivalent.
+#
+# The compiled-in value is usually sufficient and should only be changed
+# if you rename or move the sudo_noexec.so file.
+#
+#Path noexec /usr/local/libexec/sudo/sudo_noexec.so
+
+#
+# Sudo plugin directory:
+# Path plugin_dir /path/to/plugins
+#
+# The default directory to use when searching for plugins that are
+# specified without a fully qualified path name.
+#
+#Path plugin_dir /usr/local/libexec/sudo
+
+#
+# Core dumps:
+# Set disable_coredump true|false
+#
+# By default, sudo disables core dumps while it is executing (they
+# are re-enabled for the command that is run).
+# To aid in debugging sudo problems, you may wish to enable core
+# dumps by setting "disable_coredump" to false.
+#
+#Set disable_coredump false
+
+#
+# User groups:
+# Set group_source static|dynamic|adaptive
+#
+# Sudo passes the user's group list to the policy plugin.
+# If the user is a member of the maximum number of groups (usually 16),
+# sudo will query the group database directly to be sure to include
+# the full list of groups.
+#
+# On some systems, this can be expensive so the behavior is configurable.
+# The "group_source" setting has three possible values:
+# static - use the user's list of groups returned by the kernel.
+# dynamic - query the group database to find the list of groups.
+# adaptive - if user is in less than the maximum number of groups.
+# use the kernel list, else query the group database.
+#
+#Set group_source static
+
+#
+# Sudo interface probing:
+# Set probe_interfaces true|false
+#
+# By default, sudo will probe the system's network interfaces and
+# pass the IP address of each enabled interface to the policy plugin.
+# On systems with a large number of virtual interfaces this may take
+# a noticeable amount of time.
+#
+#Set probe_interfaces false
+
+#
+# Sudo debug files:
+# Debug program /path/to/debug_log subsystem@priority[,subsyste@priority]
+#
+# Sudo and related programs support logging debug information to a file.
+# The program is typically sudo, sudoers.so, sudoreplay or visudo.
+#
+# Subsystems vary based on the program; "all" matches all subsystems.
+# Priority may be crit, err, warn, notice, diag, info, trace or debug.
+# Multiple subsystem@priority may be specified, separated by a comma.
+#
+#Debug sudo /var/log/sudo_debug all@debug
+#Debug sudoers.so /var/log/sudoers_debug all@debug
diff --git a/lib/util/regress/corpus/seed/sudo_conf/sudo.conf.2 b/lib/util/regress/corpus/seed/sudo_conf/sudo.conf.2
new file mode 100644
index 0000000..05039a5
--- /dev/null
+++ b/lib/util/regress/corpus/seed/sudo_conf/sudo.conf.2
@@ -0,0 +1,116 @@
+#
+# Default /etc/sudo.conf file
+#
+# Sudo plugins:
+# Plugin plugin_name plugin_path plugin_options ...
+#
+# The plugin_path is relative to /usr/local/libexec/sudo unless
+# fully qualified.
+# The plugin_name corresponds to a global symbol in the plugin
+# that contains the plugin interface structure.
+# The plugin_options are optional.
+#
+# The sudoers plugin is used by default if no Plugin lines are present.
+Plugin sudoers_policy sudoers.so
+Plugin sudoers_io sudoers.so
+Plugin sudoers_audit sudoers.so
+
+#
+# Sudo askpass:
+# Path askpass /path/to/askpass
+#
+# An askpass helper program may be specified to provide a graphical
+# password prompt for "sudo -A" support. Sudo does not ship with its
+# own askpass program but can use the OpenSSH askpass.
+#
+# Use the OpenSSH askpass
+Path askpass /usr/X11R6/bin/ssh-askpass
+#
+# Use the Gnome OpenSSH askpass
+Path askpass /usr/libexec/openssh/gnome-ssh-askpass
+
+#
+# Sudo device search path:
+# Path devsearch /dev/path1:/dev/path2:/dev
+#
+# A colon-separated list of paths to check when searching for a user's
+# terminal device.
+#
+Path devsearch /dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev
+
+#
+# Sudo noexec:
+# Path noexec /path/to/sudo_noexec.so
+#
+# Path to a shared library containing replacements for the execv(),
+# execve() and fexecve() library functions that just return an error.
+# This is used to implement the "noexec" functionality on systems that
+# support LD_PRELOAD or its equivalent.
+#
+# The compiled-in value is usually sufficient and should only be changed
+# if you rename or move the sudo_noexec.so file.
+#
+Path noexec /usr/local/libexec/sudo/sudo_noexec.so
+
+#
+# Sudo plugin directory:
+# Path plugin_dir /path/to/plugins
+#
+# The default directory to use when searching for plugins that are
+# specified without a fully qualified path name.
+#
+Path plugin_dir /usr/local/libexec/sudo
+
+#
+# Core dumps:
+# Set disable_coredump true|false
+#
+# By default, sudo disables core dumps while it is executing (they
+# are re-enabled for the command that is run).
+# To aid in debugging sudo problems, you may wish to enable core
+# dumps by setting "disable_coredump" to false.
+#
+Set disable_coredump false
+
+#
+# User groups:
+# Set group_source static|dynamic|adaptive
+#
+# Sudo passes the user's group list to the policy plugin.
+# If the user is a member of the maximum number of groups (usually 16),
+# sudo will query the group database directly to be sure to include
+# the full list of groups.
+#
+# On some systems, this can be expensive so the behavior is configurable.
+# The "group_source" setting has three possible values:
+# static - use the user's list of groups returned by the kernel.
+# dynamic - query the group database to find the list of groups.
+# adaptive - if user is in less than the maximum number of groups.
+# use the kernel list, else query the group database.
+#
+Set group_source static
+
+#
+# Sudo interface probing:
+# Set probe_interfaces true|false
+#
+# By default, sudo will probe the system's network interfaces and
+# pass the IP address of each enabled interface to the policy plugin.
+# On systems with a large number of virtual interfaces this may take
+# a noticeable amount of time.
+#
+Set probe_interfaces false
+
+#
+# Sudo debug files:
+# Debug program /path/to/debug_log subsystem@priority[,subsyste@priority]
+#
+# Sudo and related programs support logging debug information to a file.
+# The program is typically sudo, sudoers.so, sudoreplay or visudo.
+#
+# Subsystems vary based on the program; "all" matches all subsystems.
+# Priority may be crit, err, warn, notice, diag, info, trace or debug.
+# Multiple subsystem@priority may be specified, separated by a comma.
+#
+Debug sudo /var/log/sudo_debug all@debug
+Debug sudoers.so /var/log/sudoers_debug all@debug
diff --git a/lib/util/regress/corpus/seed/sudo_conf/sudo.conf.3 b/lib/util/regress/corpus/seed/sudo_conf/sudo.conf.3
new file mode 100644
index 0000000..bcfafb2
--- /dev/null
+++ b/lib/util/regress/corpus/seed/sudo_conf/sudo.conf.3
@@ -0,0 +1,126 @@
+#
+# Default /etc/sudo.conf file
+#
+# Sudo plugins:
+# Plugin plugin_name plugin_path plugin_options ...
+#
+# The plugin_path is relative to /usr/local/libexec/sudo unless
+# fully qualified.
+# The plugin_name corresponds to a global symbol in the plugin
+# that contains the plugin interface structure.
+# The plugin_options are optional.
+#
+# The sudoers plugin is used by default if no Plugin lines are present.
+Plugin sudoers_policy sudoers.so
+Plugin sudoers_io sudoers.so
+Plugin sudoers_audit sudoers.so
+
+#
+# Sudo askpass:
+# Path askpass /path/to/askpass
+#
+# An askpass helper program may be specified to provide a graphical
+# password prompt for "sudo -A" support. Sudo does not ship with its
+# own askpass program but can use the OpenSSH askpass.
+#
+# Use the OpenSSH askpass
+Path askpass /usr/X11R6/bin/ssh-askpass
+#
+# Use the Gnome OpenSSH askpass
+Path askpass /usr/libexec/openssh/gnome-ssh-askpass
+
+#
+# Sudo device search path:
+# Path devsearch /dev/path1:/dev/path2:/dev
+#
+# A colon-separated list of paths to check when searching for a user's
+# terminal device.
+#
+Path devsearch /dev/pts:/dev/vt:/dev/term:/dev/zcons:/dev/pty:/dev
+
+#
+# Sudo noexec:
+# Path noexec /path/to/sudo_noexec.so
+#
+# Path to a shared library containing replacements for the execv(),
+# execve() and fexecve() library functions that just return an error.
+# This is used to implement the "noexec" functionality on systems that
+# support LD_PRELOAD or its equivalent.
+#
+# The compiled-in value is usually sufficient and should only be changed
+# if you rename or move the sudo_noexec.so file.
+#
+Path noexec /usr/local/libexec/sudo/sudo_noexec.so
+
+#
+# Sudo plugin directory:
+# Path plugin_dir /path/to/plugins
+#
+# The default directory to use when searching for plugins that are
+# specified without a fully qualified path name.
+#
+Path plugin_dir /usr/local/libexec/sudo
+
+#
+# Path to the sesh binary for SELinux support
+#
+Path sesh /usr/local/libexec/sudo/sesh
+
+#
+# Core dumps:
+# Set disable_coredump true|false
+#
+# By default, sudo disables core dumps while it is executing (they
+# are re-enabled for the command that is run).
+# To aid in debugging sudo problems, you may wish to enable core
+# dumps by setting "disable_coredump" to false.
+#
+Set disable_coredump true
+
+#
+# User groups:
+# Set group_source static|dynamic|adaptive
+#
+# Sudo passes the user's group list to the policy plugin.
+# If the user is a member of the maximum number of groups (usually 16),
+# sudo will query the group database directly to be sure to include
+# the full list of groups.
+#
+# On some systems, this can be expensive so the behavior is configurable.
+# The "group_source" setting has three possible values:
+# static - use the user's list of groups returned by the kernel.
+# dynamic - query the group database to find the list of groups.
+# adaptive - if user is in less than the maximum number of groups.
+# use the kernel list, else query the group database.
+#
+Set group_source dynamic
+
+#
+# Maximum number of groups to use
+#
+Set max_groups 8
+
+#
+# Sudo interface probing:
+# Set probe_interfaces true|false
+#
+# By default, sudo will probe the system's network interfaces and
+# pass the IP address of each enabled interface to the policy plugin.
+# On systems with a large number of virtual interfaces this may take
+# a noticeable amount of time.
+#
+Set probe_interfaces true
+
+#
+# Sudo debug files:
+# Debug program /path/to/debug_log subsystem@priority[,subsyste@priority]
+#
+# Sudo and related programs support logging debug information to a file.
+# The program is typically sudo, sudoers.so, sudoreplay or visudo.
+#
+# Subsystems vary based on the program; "all" matches all subsystems.
+# Priority may be crit, err, warn, notice, diag, info, trace or debug.
+# Multiple subsystem@priority may be specified, separated by a comma.
+#
+Debug sudo /var/log/sudo_debug all@debug
+Debug sudoers.so /var/log/sudoers_debug all@debug
diff --git a/lib/util/regress/digest/digest_test.c b/lib/util/regress/digest/digest_test.c
new file mode 100644
index 0000000..69740a9
--- /dev/null
+++ b/lib/util/regress/digest/digest_test.c
@@ -0,0 +1,1179 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_digest.h>
+#include <sudo_util.h>
+#include <sudo_fatal.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+static int errors, ntests;
+static const char hex[] = "0123456789abcdef";
+
+struct test_vector {
+ size_t len; /* length in bytes */
+ const char *str; /* input string (hex bytes) */
+ const char *md; /* message digest */
+};
+
+/* SHA224 short messages test vectors. */
+static struct test_vector sha224_vectors[] = {
+ {
+ 0,
+ "",
+ "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"
+ }, {
+ 1,
+ "\x84",
+ "3cd36921df5d6963e73739cf4d20211e2d8877c19cff087ade9d0e3a"
+ }, {
+ 2,
+ "\x5c\x7b",
+ "daff9bce685eb831f97fc1225b03c275a6c112e2d6e76f5faf7a36e6"
+ }, {
+ 3,
+ "\x51\xca\x3d",
+ "2c8959023515476e38388abb43599a29876b4b33d56adc06032de3a2"
+ }, {
+ 4,
+ "\x60\x84\x34\x7e",
+ "ae57c0a6d49739ba338adfa53bdae063e5c09122b77604780a8eeaa3"
+ }, {
+ 5,
+ "\x49\x3e\x14\x62\x3c",
+ "7f631f295e024e74552083245ca8f988a3fb65680ae97c3040d2e65c"
+ }, {
+ 6,
+ "\xd7\x29\xd8\xcd\x16\x31",
+ "342e8e6b23c1c6a54910631f098e08e836259c57e49c1b1d023d166d"
+ }, {
+ 7,
+ "\xcb\xf2\x06\x1e\x10\xfa\xa5",
+ "3aa702b1b66dc57d7aec3ccdbdfbd88592d7520f843ba5d0fa481168"
+ }, {
+ 8,
+ "\x5f\x77\xb3\x66\x48\x23\xc3\x3e",
+ "bdf21ff325f754157ccf417f4855360a72e8fd117d28c8fe7da3ea38"
+ }, {
+ 9,
+ "\x10\x71\x3b\x89\x4d\xe4\xa7\x34\xc0",
+ "03842600c86f5cd60c3a2147a067cb962a05303c3488b05cb45327bd"
+ }, {
+ 10,
+ "\x00\x64\x70\xd5\x7d\xad\x98\x93\xdc\x03",
+ "c90026cda5ad24115059c62ae9add57793ade445d4742273288bbce7"
+ }, {
+ 11,
+ "\x6f\x29\xca\x27\x41\x90\x40\x07\x20\xbb\xa2",
+ "ac53157947aa4b2a19089182382a4363d182dd8e4ca79cd8571390be"
+ }, {
+ 12,
+ "\x17\xe8\x55\x61\x76\xfc\xca\x2a\xdd\xbd\xde\x29",
+ "cc6ad0488db0222066f740557b5758a19b30372b302332295d8c3aff"
+ }, {
+ 13,
+ "\xdb\xf1\x63\x60\x1d\xb9\xa1\x22\xa4\x02\x68\x24\xde",
+ "9849845f4e47e1ece9a1c1e01a0d896ffea61c6c8894a75a11ce5f49"
+ }, {
+ 14,
+ "\x5e\x1e\xf2\xad\x86\xce\xaf\x54\x39\xfe\x87\xd2\xec\x9b",
+ "223c5d5d4a0116b32cea044f9af0fe44babea1c5ab201502591bcd5f"
+ }, {
+ 15,
+ "\x65\xf3\xb9\x86\x6f\xb8\x00\x2b\x53\xcf\xaf\x80\x6f\x70\x2f",
+ "b1e0806a218d593821fde8e9eacc44ab5287c32209a94f011ab66b75"
+ }, {
+ 16,
+ "\xb7\x76\x70\x8f\xfb\x91\xb3\x51\x5a\xc4\x65\x98\xab\x9f\xa7\x96",
+ "427311b1d7ab2488791c4deeb4251d783fe5f9806bfdfb5188c5443d"
+ }, {
+ 17,
+ "\xa4\xbc\x10\xb1\xa6\x2c\x96\xd4\x59\xfb\xaf\x3a\x5a\xa3\xfa\xce\x73",
+ "d7e6634723ac25cb1879bdb1508da05313530419013fe255967a39e1"
+ }, {
+ 18,
+ "\x9e\x8f\x3c\x66\x45\xc1\x74\x9b\x55\xc5\x0d\x20\x18\xce\x40\xdc\x24\x27",
+ "2f5a583bf588c8988a572d128a95bea5ef1b66780a7d4be9c29efc31"
+ }, {
+ 19,
+ "\x2d\xb6\xd2\x07\xc0\xb7\xd9\x11\x7f\x24\xd7\x8e\xe5\x9a\xbf\x2f\x31\x69\x78",
+ "35681fce28307cae19522c23cbd4a77969347f7d8ee4a3088ba90ada"
+ }, {
+ 20,
+ "\x3d\xf5\xe7\xf3\x99\xf6\xdd\x61\xa1\x2a\x9d\x4e\x94\x64\xfc\x49\x97\xc1\xf3\x7b",
+ "a3e68076e30751085a843a6cbfbf0f3dee63d9c4219c914372e50b28"
+ }, {
+ 21,
+ "\x65\x78\x1d\x01\x8f\x27\xca\x0c\x72\xa9\xfa\x9a\xb4\x64\x8e\xd3\x69\x64\x6d\xd3\xce",
+ "d15ef0d872d02da6427b8d0349dea2f204e67133b7365b4b150efc3c"
+ }, {
+ 22,
+ "\xaf\x48\xee\xdd\xd9\x3f\xee\x69\xd1\xbd\x7d\xe4\x28\xa6\x39\x86\x01\x1d\x10\x94\x5e\xaf",
+ "b89d428ee42e397cf11029ecbb27baddd036c8938f51c8ab56b875ac"
+ }, {
+ 23,
+ "\xdf\x2b\xf0\xd5\xf9\xc9\x94\xac\x69\xd7\x8b\xaa\x0d\x51\x2e\xce\xb7\x4d\x8a\x04\x75\x31\xc1",
+ "db8e1ce68c8c6b84d6db755c2b8bf54f3c4b081a881efcddaf303294"
+ }, {
+ 24,
+ "\x48\xd2\xf2\x09\x55\xea\x2d\x13\x43\x3c\x20\xbc\x04\x04\xeb\x2e\x6a\xd7\x9e\xd2\x8f\x7c\xb4\xc0",
+ "3617cc3179f8b59adce181eebeed5e2763f62650949224a67e53694b"
+ }, {
+ 25,
+ "\x21\x8f\x74\xa4\x2d\x3a\x47\xef\x3b\x80\x66\x01\xfb\xa0\x24\xb0\x78\xcb\xff\x4e\x4b\x85\x77\x2e\x0e",
+ "b5f40b95dcc363b97e9d00b67c5d7c37f17ab563297d2d67a4df20c9"
+ }, {
+ 26,
+ "\xef\x55\xb1\xe7\x97\x00\x0b\x04\xfc\xdb\x9b\x30\x21\xb0\x93\x27\xe3\xb4\xe2\x69\xd2\x0c\xab\xdf\x41\x8f",
+ "827b223d51240c2e3271c534c19c5637b6fe10083e85bcf06761ef21"
+ }, {
+ 27,
+ "\x96\xdf\x43\x87\xdc\x2c\x40\x29\x70\x43\xbe\xa3\x64\x83\xf6\x5e\x4e\xb1\xe0\x7e\x93\x35\x9c\xb7\xe6\x86\x10",
+ "98e430a63fcdedafc9419010f7f59a4d816a45b4f973beb62530ff8c"
+ }, {
+ 28,
+ "\x3e\xc0\xaa\x8d\x30\xd5\xed\x82\x5b\x77\xdc\x70\x95\xf4\x21\xb1\xe6\x08\x15\x87\x97\xa3\x77\xff\x8b\xed\x64\x1b",
+ "3108321eb7ff857f6aae69101b937f32a51ea279a6c14ba5232ac8c1"
+ }, {
+ 29,
+ "\x8b\x02\x39\x71\x20\x39\xf0\x77\xce\x32\x3b\x35\xf4\xe3\x06\x78\x7b\x9b\x35\x27\x00\x96\xe5\x77\x35\xcf\xf4\x5d\x84",
+ "a5c740d3ce46bb2e0a048488f2b0605c6d0ca0ea2f382d043d13db97"
+ }, {
+ 30,
+ "\x04\x4b\xe3\x01\x67\xa9\x75\x8c\x46\xc7\x27\x92\x1d\xc4\xeb\x4e\x0d\xcb\x96\x56\x23\x42\x3e\x6f\xdd\x44\xe7\xa4\xea\x52",
+ "6eb78313c743ea8769d8340f284dda6ded64a1db64392f21abb82c5c"
+ }, {
+ 31,
+ "\x57\xf6\x11\x8b\xac\xce\x47\xec\xc3\x1c\xe8\xb0\xc0\x83\xd3\xc9\x21\x9e\x0d\xbe\x9e\x4f\xbe\xa1\x54\x53\x7c\x41\x23\x1a\xcc",
+ "0dbb53c866d63af44c222c76c825df0e379dcedfb958db03b6fd29a5"
+ }, {
+ 32,
+ "\xfe\x1f\x0f\xb0\x2c\x90\x11\xf4\xc8\xc5\x90\x59\x34\xed\x15\x13\x67\x71\x73\x7c\xe3\x1c\x58\x59\xe6\x7f\x23\x5f\xe5\x94\xf5\xf6",
+ "bbeaacc632c2a3db2a9b47f157ab54aa27776c6e74cf0bcaa91b06d5"
+ }, {
+ 33,
+ "\x14\xfb\x01\xae\x9d\x60\x15\xec\xb3\xe5\x6d\x6e\xcd\xfa\x4b\xc0\x53\x31\x86\xad\xf8\x45\x7f\x5e\x4a\x5c\x57\xc6\x87\x89\x5f\x3d\xb3",
+ "178272c7d7cc71b15074c27e3b7997d4a3ba99626986a1a16cf30030"
+ }, {
+ 34,
+ "\xff\x6c\x49\x71\x2f\x04\x4f\x40\x63\xc1\x41\x25\xc0\xcd\xfb\xa1\x8e\xd8\xb7\x13\x84\x53\x76\x8a\x45\xdf\xa2\xd8\x2a\x05\xf1\xe8\x42\x27",
+ "403284c888a7280bc8bfc25f0c34182cd378306a21a1404d4e1c40cf"
+ }, {
+ 35,
+ "\xf9\x00\xbd\x7e\x01\x17\x24\x7f\x97\xc8\xfc\x7a\x66\x5c\x76\xa3\x5f\x57\x1c\x33\x66\x57\x1d\x6c\x4a\x3e\xe5\xd7\xfb\x93\xf1\xd1\xf7\x26\xe2",
+ "48235b9820d66d8885faabf6a9ede63ba2a21b6177e987a33242373e"
+ }, {
+ 36,
+ "\x42\xd3\x81\x88\xac\x49\x44\x0c\xfe\xfb\x77\xdb\x97\x5e\x08\x3e\x6b\x22\x34\x8c\x4c\x67\xf0\xf8\x69\x2e\x88\xad\x14\x0d\x86\x1d\xc8\x28\xd5\x95",
+ "615344f890e5bcf71b5efe39de1fc942ba1fe30dd9e9146adb6a41bf"
+ }, {
+ 37,
+ "\x74\xfd\xd7\xd9\x58\xb8\xae\x7c\x2c\x3c\x5c\xff\x42\x66\xdf\xb2\xb3\xb8\x42\xc9\xf5\x9e\xcb\xbc\xaf\xf5\x75\xed\xcb\xcd\xa0\x8c\xcd\x6e\x08\xb7\x64",
+ "66d7d6c54fc7775a0ba845ba3e11719fa535b9289f20b098c5f7a342"
+ }, {
+ 38,
+ "\x93\x44\x16\xdd\x05\x81\xe2\x2f\x2b\xfb\xec\xe7\xbb\x64\xaf\xe8\x20\x45\x1f\xa2\x13\x42\xdf\x7e\x6f\x9f\xb3\x7c\x41\x03\x38\x1a\x1f\x7c\xd3\x79\xbc\xc4",
+ "fae8f1aa22def4dbaa814c5b0babdec43394951792c937050d2963a6"
+ }, {
+ 39,
+ "\x10\x24\x01\xc8\x4a\x71\x6a\xe7\x25\x79\xc6\xae\x79\xc3\x59\xea\x30\x9f\xfd\x95\xab\xff\xae\x4c\x61\x88\x4c\x03\xc9\xe9\x9d\xf7\x7b\x6c\x92\xe4\x92\xca\xcb",
+ "8f34812d57a16ef8a51ad987660c5f8623e0fa9d89846e28d46d14d9"
+ }, {
+ 40,
+ "\x79\xbc\x8f\xb6\x0f\x85\xd1\x5a\x23\x86\x56\x6e\x3e\x73\x14\xdf\x28\x45\x33\x08\x5a\xdd\x1c\x7b\xb6\xea\xd3\xff\x76\x0c\x86\xd5\x63\x3a\x66\x40\x47\x61\xb5\x44",
+ "65c54014cfa30f0bc27d1c6efa96ae8481f4c2505bff272956eab0df"
+ }, {
+ 41,
+ "\xdb\x31\x21\xea\x71\x29\x49\x83\xb1\x85\x20\x7a\x9d\x8d\xe3\xe4\x84\xa6\x6c\x04\x31\xbf\x07\xc9\x62\xeb\x82\x97\x7c\x4f\x83\x4b\x7c\x3f\x1e\x79\x31\xa4\xa7\xf7\xa9",
+ "9316d2f021c2913d63a7e66924c87c161c3cfde0ea7ba07f54772862"
+ }, {
+ 42,
+ "\x0d\xd5\x1a\xa6\x60\xc5\xcb\x4b\x7f\x78\xc4\x68\x52\xc1\xdb\x87\x07\xab\x45\x1c\x13\x67\xb6\x18\x73\x88\xc8\xbb\x38\x73\xa1\xaa\x42\x10\xd0\x41\x4c\xc6\x79\x2a\x29\xa7",
+ "31989e7a62a5132a5070d77250d8904bb82d457dc63469d06b50185e"
+ }, {
+ 43,
+ "\x48\x7f\xd2\xe5\xb6\x94\xb7\x07\x1d\x37\x89\xa2\x58\xa5\x1e\x86\x04\xdc\x0d\x3e\x8f\x5d\x62\xf3\x91\x31\x96\x8e\x60\x2a\xbe\x1d\xdf\x6b\x02\x78\x96\x2a\x51\x24\x08\xb5\x53",
+ "e798683438284626d710877d9eea3a0e02f349fc43acb7f9f8f9e81c"
+ }, {
+ 44,
+ "\x11\x18\x3b\xde\xbf\xef\x58\xe4\xda\x5b\x1c\xb7\x3b\xe0\xd3\x0b\x20\xda\x30\x4d\x86\x59\xd9\x21\xda\x2e\x27\x0f\xd1\x46\x26\x79\x95\x37\xe4\xd1\x21\x19\xe8\x09\xee\x97\x00\x4a",
+ "96870657d6cb668be3995aa8bd31df77840d1d1915d72482e83b6b2c"
+ }, {
+ 45,
+ "\xa2\x39\xde\x5c\x8e\x26\x44\xe8\xf0\x30\xd9\x4d\x98\xf1\xa3\x06\x64\xe6\xfd\x96\x1d\xc2\x97\x7a\x9c\x08\xbe\x5c\x31\xd8\xde\x89\x45\x09\x45\xa5\x3d\x79\x29\x9e\xa2\xa1\xed\xde\x7f",
+ "e99743d4fd26c8800c36a67b6762247c29da6b62794123c59de06dc0"
+ }, {
+ 46,
+ "\x91\x7c\x45\x77\xaa\x6b\x0f\x9d\xf4\x99\x99\xfc\x1c\x95\x8c\xb0\x9b\x7f\xd5\xfc\x80\xbe\x94\x96\x70\xf0\x35\x45\xeb\x27\xdc\xae\xd0\x52\x07\x6b\x24\xf9\x6f\x5e\x0f\x2e\x2f\x45\x27\xc0",
+ "7ecd693d4d9cf43929464698efa0bac33c2e1424f816edc769260978"
+ }, {
+ 47,
+ "\xc3\xf1\xe7\x35\xa6\x74\x1a\xa4\x81\xad\x57\x7a\x98\xdb\xac\x1f\x03\xcc\x80\xea\x0d\xae\x1b\x94\xdb\x23\x69\xed\x4e\x93\xfa\xcd\x29\xc6\x4e\x4e\x77\xb2\x50\x38\x27\x91\x20\xbd\xfa\x37\x15",
+ "86f0d89d8e14fd8b6606412d71a7a54a347b304ea5d49c208f2266ab"
+ }, {
+ 48,
+ "\xde\x4f\xbf\xd5\x53\xcd\xf3\x70\x19\xf2\x5a\xfa\x82\xdc\x6b\x99\x70\xf4\xbb\x1e\xbb\xc3\x7f\x80\xd3\x08\x4c\x88\xa7\x07\x22\xcd\xc5\x23\xa9\xe3\xc2\xaf\xba\xd0\xdc\x02\x21\xbf\xde\xc9\xa2\xf9",
+ "4c5262acb4a2a44eaa9bc6757024fb202ef4d5a7a16fa37252a422b5"
+ }, {
+ 49,
+ "\xdb\x2e\x2e\xb6\x36\x61\x0c\xf4\x2e\x9b\x33\x43\x3a\xcc\xe1\xb3\xb9\x25\x94\x9f\x29\x7d\xd8\x31\x99\xf4\x5d\x28\x61\xd6\x4c\xd9\x10\xc2\xdb\x74\xa6\x0b\x20\x89\x04\x5e\x22\xcb\xa0\xa5\x36\x13\x7d",
+ "16bf4e45bcdc60447c68dcb30e6b08f55ce9f4124a29cf1f9a9d065d"
+ }, {
+ 50,
+ "\xa8\xe7\x29\xd3\x36\xd5\xd6\xac\x50\xe1\xe2\x2f\x0b\x19\x3b\x66\xe2\x60\x42\xfc\x64\x59\x21\x41\x29\x87\x5e\x74\x0a\xb2\xb1\x42\x91\x8c\x13\x8a\xaf\x94\x18\x63\xad\x3b\x7e\x60\x65\x45\x06\x13\xb2\x73",
+ "452bf2e5ebfc4e451cc434bc09e2a10032eed0b7627cf55e7e5ed0e2"
+ }, {
+ 51,
+ "\xd0\x53\x17\xd4\xb5\x35\xf9\xd1\x0f\x73\x9d\x0c\x2d\xed\xf3\xff\xb0\x90\xc1\xad\x9d\x20\x50\x89\xb1\x34\x66\x93\xf5\x82\x73\xc4\x92\x5c\x0f\xac\xe5\x7b\xa4\x5a\xd6\xfc\x68\x7c\x66\xa8\x8f\xc7\x88\x78\xbe",
+ "4f03c439e097b51b00e314f675937c4d911505859fb7ab16adc65e44"
+ }, {
+ 52,
+ "\x26\xbb\x4e\xd4\xf0\x42\x4c\x60\xfe\x42\x12\xff\x8c\x95\x5e\x89\xe2\xf5\x53\xa7\xd7\x70\x1b\xe5\x94\x16\xd2\x08\x9a\xf5\x9f\xa1\x07\x47\x24\xe2\x14\xe9\x19\xb1\xe3\x0f\x33\xfb\x78\x37\x4b\x4b\x05\x5b\xbc\x9b",
+ "e7c899e27009d4dc77c2d300f191b757e52c9e7eac4b023bfab2b52a"
+ }, {
+ 53,
+ "\xf0\x15\xec\x83\x94\x4f\x03\x29\x24\x63\xc4\x34\x5f\xdb\x1c\x26\xd1\xea\x07\x64\x5f\xac\xbc\x95\x20\xae\x24\x4b\x6e\xb1\x91\xe5\x3d\xab\xad\xb4\xac\x0f\xb1\x5c\xda\x4e\xd7\x7d\xfb\x9e\x11\x93\xab\xfa\xfb\x1b\x81",
+ "459e40b3fbd612912f0217c60099379ce077cd02505871b0c9c14e7a"
+ }, {
+ 54,
+ "\x07\x86\x70\x6f\x68\x0c\x27\xb7\x92\xd0\x54\xfa\xa6\x3f\x49\x9a\x8e\x6b\x5d\xdb\x90\x50\x29\x46\x23\x5b\xf7\x4c\x02\x2d\x77\x2c\x80\x9c\xb4\x17\x1b\xfa\x47\x91\x53\x9a\xca\x1a\xbd\x91\x90\x0e\x53\xba\x93\xca\x0e\xfd",
+ "fadebab7c3d0fb8e97e429b79083087735e4ab385a789521260ef3ad"
+ }, {
+ 55,
+ "\x44\x5e\x86\x98\xee\xb8\xac\xcb\xaa\xc4\xff\xa7\xd9\x34\xff\xfd\x16\x01\x4a\x43\x0e\xf7\x0f\x3a\x91\x74\xc6\xcf\xe9\x6d\x1e\x3f\x6a\xb1\x37\x7f\x4a\x72\x12\xdb\xb3\x01\x46\xdd\x17\xd9\xf4\x70\xc4\xdf\xfc\x45\xb8\xe8\x71",
+ "4c7ae028c0fe61f2a9cada61fae30685b77f04c6442576e912af9fa6"
+ }, {
+ 56,
+ "\x52\x83\x9f\x2f\x08\x53\xa3\x0d\xf1\x4e\xc8\x97\xa1\x91\x4c\x68\x5c\x1a\xc2\x14\x70\xd0\x06\x54\xc8\xc3\x76\x63\xbf\xb6\x5f\xa7\x32\xdb\xb6\x94\xd9\xdd\x09\xce\xd7\x23\xb4\x8d\x8f\x54\x58\x46\xba\x16\x89\x88\xb6\x1c\xc7\x24",
+ "2f755a57674b49d5c25cb37348f35b6fd2de2552c749f2645ba63d20"
+ }, {
+ 57,
+ "\x5f\xe8\xc2\x07\x2d\x89\x00\x28\x7c\xca\xf0\x7f\x3f\x66\xb0\xc2\x2a\xcd\x3e\x0b\xb9\x1d\x95\x73\x75\x4e\x19\xe3\x73\xac\x35\x27\x1d\x8b\x43\x44\x34\x36\xac\x0c\x16\x28\x50\xef\x3d\x7f\x28\x14\x09\xad\x29\xa9\xbf\x71\x6c\x77\xd1",
+ "42909757f6e229f69f04cc7a863c4e70e48c7c3575057b455c959775"
+ }, {
+ 58,
+ "\xe8\x06\x4d\x83\xf3\xd6\x43\xaf\x87\x18\xc8\x7e\x3c\xcd\x6a\x97\x33\x68\x5e\xac\x61\xd5\x72\xa2\x2a\xb9\x43\xf2\x32\xfc\xb0\x4f\x70\x85\x8e\x89\x84\x44\x9d\xb1\x4a\x76\xbb\x7e\xaf\x24\x58\xef\xc3\xed\x2a\x32\x10\x06\x22\xc5\x2b\x7f",
+ "1a1d8ed54cb45c97bc970754b43eb93d9eabde4c7b07f76ad82d8ede"
+ }, {
+ 59,
+ "\x87\xc9\xa5\x17\xe2\x8d\x1b\xb5\x4a\xd2\x0f\xca\x76\x46\x0e\xfd\x89\x4d\x77\x86\xe6\x8e\xe8\xd7\x46\xb2\xf6\x82\x08\x68\x21\x57\xc8\xad\x06\xcc\x32\x4a\xd7\xa3\x18\x9e\x09\xc6\xc3\x9d\x4c\x76\x87\x19\xc0\xa4\x9a\x41\x66\x9f\x27\x67\xd5",
+ "605977cf87b9b309bbddaaa64e528ace66b04df9f72c0e7ec88be1da"
+ }, {
+ 60,
+ "\x59\xfd\xac\x3b\x6b\x32\x03\x92\x91\x80\x1c\x7d\x6f\x46\xed\xe8\xd2\x6d\xc5\xb7\xa1\x92\xe0\x07\x11\x67\x39\xb6\x17\x56\x9f\x25\x23\x68\x0b\x3c\x0b\x66\x31\xaf\x45\x3e\x55\x80\x5a\xa7\x60\xc6\x97\x08\x33\xac\x06\x96\x3b\xbc\x9d\xbd\x45\x5e",
+ "e9f0cb1dc8337e906385892f2348a8ba4412318ecad9b96e3711531f"
+ }, {
+ 61,
+ "\x30\x35\x0a\x4d\xf0\xb5\x8f\xf4\x9c\x0f\xa0\x9e\x42\x6f\xcd\x70\x07\xb2\x90\xc7\x60\xc8\x25\xc1\x85\x5d\x9b\x00\x23\xb8\x2c\xaa\x51\xe3\xca\xb4\xc6\x0c\xfa\x61\x49\x2b\xe5\x05\x68\xe5\xac\x0f\x6d\xb0\xfd\x46\x8e\x39\xe4\x53\x64\x03\xe3\x80\x9f",
+ "776cc6636c02408fbf65ace73ae80017108b917c16c5a912fd860241"
+ }, {
+ 62,
+ "\xef\x79\x7a\x0d\x43\xc3\x0b\x4f\xe1\x01\x4b\xdb\x94\x20\x87\x9c\x2f\xf8\x45\xd2\x7e\x73\xd5\x5a\x7d\xf2\x29\x30\xc8\xec\xe7\x32\x53\xd8\xbb\x26\x5b\x4e\xf2\xff\x9c\x69\x45\x5c\xc5\x6f\xf2\x52\x29\xb4\x12\x6b\xb7\xbb\x26\xee\x2c\x9f\xf3\x61\x87\xb1",
+ "f5b9ffb102affac352a4a535a00f89b06c268cf4881d712668906025"
+ }, {
+ 63,
+ "\x71\x69\x44\xde\x41\x71\x0c\x29\xb6\x59\xbe\x10\x48\x0b\xb2\x5a\x35\x1a\x39\xe5\x77\xee\x30\xe8\xf4\x22\xd5\x7c\xf6\x2a\xd9\x5b\xda\x39\xb6\xe7\x0c\x61\x42\x6e\x33\xfd\x84\xac\xa8\x4c\xc7\x91\x2d\x5e\xee\x45\xdc\x34\x07\x6a\x5d\x23\x23\xa1\x5c\x79\x64",
+ "61645ac748db567ac862796b8d06a47afebfa2e1783d5c5f3bcd81e2"
+ }, {
+ 64,
+ "\xa3\x31\x0b\xa0\x64\xbe\x2e\x14\xad\x32\x27\x6e\x18\xcd\x03\x10\xc9\x33\xa6\xe6\x50\xc3\xc7\x54\xd0\x24\x3c\x6c\x61\x20\x78\x65\xb4\xb6\x52\x48\xf6\x6a\x08\xed\xf6\xe0\x83\x26\x89\xa9\xdc\x3a\x2e\x5d\x20\x95\xee\xea\x50\xbd\x86\x2b\xac\x88\xc8\xbd\x31\x8d",
+ "b2a5586d9cbf0baa999157b4af06d88ae08d7c9faab4bc1a96829d65"
+ }, {
+ 0,
+ NULL,
+ NULL
+ }
+};
+
+/* SHA256 short messages test vectors. */
+static struct test_vector sha256_vectors[] = {
+ {
+ 0,
+ "",
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+ }, {
+ 1,
+ "\xd3",
+ "28969cdfa74a12c82f3bad960b0b000aca2ac329deea5c2328ebc6f2ba9802c1"
+ }, {
+ 2,
+ "\x11\xaf",
+ "5ca7133fa735326081558ac312c620eeca9970d1e70a4b95533d956f072d1f98"
+ }, {
+ 3,
+ "\xb4\x19\x0e",
+ "dff2e73091f6c05e528896c4c831b9448653dc2ff043528f6769437bc7b975c2"
+ }, {
+ 4,
+ "\x74\xba\x25\x21",
+ "b16aa56be3880d18cd41e68384cf1ec8c17680c45a02b1575dc1518923ae8b0e"
+ }, {
+ 5,
+ "\xc2\x99\x20\x96\x82",
+ "f0887fe961c9cd3beab957e8222494abb969b1ce4c6557976df8b0f6d20e9166"
+ }, {
+ 6,
+ "\xe1\xdc\x72\x4d\x56\x21",
+ "eca0a060b489636225b4fa64d267dabbe44273067ac679f20820bddc6b6a90ac"
+ }, {
+ 7,
+ "\x06\xe0\x76\xf5\xa4\x42\xd5",
+ "3fd877e27450e6bbd5d74bb82f9870c64c66e109418baa8e6bbcff355e287926"
+ }, {
+ 8,
+ "\x57\x38\xc9\x29\xc4\xf4\xcc\xb6",
+ "963bb88f27f512777aab6c8b1a02c70ec0ad651d428f870036e1917120fb48bf"
+ }, {
+ 9,
+ "\x33\x34\xc5\x80\x75\xd3\xf4\x13\x9e",
+ "078da3d77ed43bd3037a433fd0341855023793f9afd08b4b08ea1e5597ceef20"
+ }, {
+ 10,
+ "\x74\xcb\x93\x81\xd8\x9f\x5a\xa7\x33\x68",
+ "73d6fad1caaa75b43b21733561fd3958bdc555194a037c2addec19dc2d7a52bd"
+ }, {
+ 11,
+ "\x76\xed\x24\xa0\xf4\x0a\x41\x22\x1e\xbf\xcf",
+ "044cef802901932e46dc46b2545e6c99c0fc323a0ed99b081bda4216857f38ac"
+ }, {
+ 12,
+ "\x9b\xaf\x69\xcb\xa3\x17\xf4\x22\xfe\x26\xa9\xa0",
+ "fe56287cd657e4afc50dba7a3a54c2a6324b886becdcd1fae473b769e551a09b"
+ }, {
+ 13,
+ "\x68\x51\x1c\xdb\x2d\xbb\xf3\x53\x0d\x7f\xb6\x1c\xbc",
+ "af53430466715e99a602fc9f5945719b04dd24267e6a98471f7a7869bd3b4313"
+ }, {
+ 14,
+ "\xaf\x39\x7a\x8b\x8d\xd7\x3a\xb7\x02\xce\x8e\x53\xaa\x9f",
+ "d189498a3463b18e846b8ab1b41583b0b7efc789dad8a7fb885bbf8fb5b45c5c"
+ }, {
+ 15,
+ "\x29\x4a\xf4\x80\x2e\x5e\x92\x5e\xb1\xc6\xcc\x9c\x72\x4f\x09",
+ "dcbaf335360de853b9cddfdafb90fa75567d0d3d58af8db9d764113aef570125"
+ }, {
+ 16,
+ "\x0a\x27\x84\x7c\xdc\x98\xbd\x6f\x62\x22\x0b\x04\x6e\xdd\x76\x2b",
+ "80c25ec1600587e7f28b18b1b18e3cdc89928e39cab3bc25e4d4a4c139bcedc4"
+ }, {
+ 17,
+ "\x1b\x50\x3f\xb9\xa7\x3b\x16\xad\xa3\xfc\xf1\x04\x26\x23\xae\x76\x10",
+ "d5c30315f72ed05fe519a1bf75ab5fd0ffec5ac1acb0daf66b6b769598594509"
+ }, {
+ 18,
+ "\x59\xeb\x45\xbb\xbe\xb0\x54\xb0\xb9\x73\x34\xd5\x35\x80\xce\x03\xf6\x99",
+ "32c38c54189f2357e96bd77eb00c2b9c341ebebacc2945f97804f59a93238288"
+ }, {
+ 19,
+ "\x58\xe5\xa3\x25\x9c\xb0\xb6\xd1\x2c\x83\xf7\x23\x37\x9e\x35\xfd\x29\x8b\x60",
+ "9b5b37816de8fcdf3ec10b745428708df8f391c550ea6746b2cafe019c2b6ace"
+ }, {
+ 20,
+ "\xc1\xef\x39\xce\xe5\x8e\x78\xf6\xfc\xdc\x12\xe0\x58\xb7\xf9\x02\xac\xd1\xa9\x3b",
+ "6dd52b0d8b48cc8146cebd0216fbf5f6ef7eeafc0ff2ff9d1422d6345555a142"
+ }, {
+ 21,
+ "\x9c\xab\x7d\x7d\xca\xec\x98\xcb\x3a\xc6\xc6\x4d\xd5\xd4\x47\x0d\x0b\x10\x3a\x81\x0c",
+ "44d34809fc60d1fcafa7f37b794d1d3a765dd0d23194ebbe340f013f0c39b613"
+ }, {
+ 22,
+ "\xea\x15\x7c\x02\xeb\xaf\x1b\x22\xde\x22\x1b\x53\xf2\x35\x39\x36\xd2\x35\x9d\x1e\x1c\x97",
+ "9df5c16a3f580406f07d96149303d8c408869b32053b726cf3defd241e484957"
+ }, {
+ 23,
+ "\xda\x99\x9b\xc1\xf9\xc7\xac\xff\x32\x82\x8a\x73\xe6\x72\xd0\xa4\x92\xf6\xee\x89\x5c\x68\x67",
+ "672b54e43f41ee77584bdf8bf854d97b6252c918f7ea2d26bc4097ea53a88f10"
+ }, {
+ 24,
+ "\x47\x99\x13\x01\x15\x6d\x1d\x97\x7c\x03\x38\xef\xbc\xad\x41\x00\x41\x33\xae\xfb\xca\x6b\xcf\x7e",
+ "feeb4b2b59fec8fdb1e55194a493d8c871757b5723675e93d3ac034b380b7fc9"
+ }, {
+ 25,
+ "\x2e\x7e\xa8\x4d\xa4\xbc\x4d\x7c\xfb\x46\x3e\x3f\x2c\x86\x47\x05\x7a\xff\xf3\xfb\xec\xec\xa1\xd2\x00",
+ "76e3acbc718836f2df8ad2d0d2d76f0cfa5fea0986be918f10bcee730df441b9"
+ }, {
+ 26,
+ "\x47\xc7\x70\xeb\x45\x49\xb6\xef\xf6\x38\x1d\x62\xe9\xbe\xb4\x64\xcd\x98\xd3\x41\xcc\x1c\x09\x98\x1a\x7a",
+ "6733809c73e53666c735b3bd3daf87ebc77c72756150a616a194108d71231272"
+ }, {
+ 27,
+ "\xac\x4c\x26\xd8\xb4\x3b\x85\x79\xd8\xf6\x1c\x98\x07\x02\x6e\x83\xe9\xb5\x86\xe1\x15\x9b\xd4\x3b\x85\x19\x37",
+ "0e6e3c143c3a5f7f38505ed6adc9b48c18edf6dedf11635f6e8f9ac73c39fe9e"
+ }, {
+ 28,
+ "\x07\x77\xfc\x1e\x1c\xa4\x73\x04\xc2\xe2\x65\x69\x28\x38\x10\x9e\x26\xaa\xb9\xe5\xc4\xae\x4e\x86\x00\xdf\x4b\x1f",
+ "ffb4fc03e054f8ecbc31470fc023bedcd4a406b9dd56c71da1b660dcc4842c65"
+ }, {
+ 29,
+ "\x1a\x57\x25\x1c\x43\x1d\x4e\x6c\x2e\x06\xd6\x52\x46\xa2\x96\x91\x50\x71\xa5\x31\x42\x5e\xcf\x25\x59\x89\x42\x2a\x66",
+ "c644612cd326b38b1c6813b1daded34448805aef317c35f548dfb4a0d74b8106"
+ }, {
+ 30,
+ "\x9b\x24\x5f\xda\xd9\xba\xeb\x89\x0d\x9c\x0d\x0e\xff\x81\x6e\xfb\x4c\xa1\x38\x61\x0b\xc7\xd7\x8c\xb1\xa8\x01\xed\x32\x73",
+ "c0e29eeeb0d3a7707947e623cdc7d1899adc70dd7861205ea5e5813954fb7957"
+ }, {
+ 31,
+ "\x95\xa7\x65\x80\x9c\xaf\x30\xad\xa9\x0a\xd6\xd6\x1c\x2b\x4b\x30\x25\x0d\xf0\xa7\xce\x23\xb7\x75\x3c\x91\x87\xf4\x31\x9c\xe2",
+ "a4139b74b102cf1e2fce229a6cd84c87501f50afa4c80feacf7d8cf5ed94f042"
+ }, {
+ 32,
+ "\x09\xfc\x1a\xcc\xc2\x30\xa2\x05\xe4\xa2\x08\xe6\x4a\x8f\x20\x42\x91\xf5\x81\xa1\x27\x56\x39\x2d\xa4\xb8\xc0\xcf\x5e\xf0\x2b\x95",
+ "4f44c1c7fbebb6f9601829f3897bfd650c56fa07844be76489076356ac1886a4"
+ }, {
+ 33,
+ "\x05\x46\xf7\xb8\x68\x2b\x5b\x95\xfd\x32\x38\x5f\xaf\x25\x85\x4c\xb3\xf7\xb4\x0c\xc8\xfa\x22\x9f\xbd\x52\xb1\x69\x34\xaa\xb3\x88\xa7",
+ "b31ad3cd02b10db282b3576c059b746fb24ca6f09fef69402dc90ece7421cbb7"
+ }, {
+ 34,
+ "\xb1\x2d\xb4\xa1\x02\x55\x29\xb3\xb7\xb1\xe4\x5c\x6d\xbc\x7b\xaa\x88\x97\xa0\x57\x6e\x66\xf6\x4b\xf3\xf8\x23\x61\x13\xa6\x27\x6e\xe7\x7d",
+ "1c38bf6bbfd32292d67d1d651fd9d5b623b6ec1e854406223f51d0df46968712"
+ }, {
+ 35,
+ "\xe6\x8c\xb6\xd8\xc1\x86\x6c\x0a\x71\xe7\x31\x3f\x83\xdc\x11\xa5\x80\x9c\xf5\xcf\xbe\xed\x1a\x58\x7c\xe9\xc2\xc9\x2e\x02\x2a\xbc\x16\x44\xbb",
+ "c2684c0dbb85c232b6da4fb5147dd0624429ec7e657991edd95eda37a587269e"
+ }, {
+ 36,
+ "\x4e\x3d\x8a\xc3\x6d\x61\xd9\xe5\x14\x80\x83\x11\x55\xb2\x53\xb3\x79\x69\xfe\x7e\xf4\x9d\xb3\xb3\x99\x26\xf3\xa0\x0b\x69\xa3\x67\x74\x36\x60\x00",
+ "bf9d5e5b5393053f055b380baed7e792ae85ad37c0ada5fd4519542ccc461cf3"
+ }, {
+ 37,
+ "\x03\xb2\x64\xbe\x51\xe4\xb9\x41\x86\x4f\x9b\x70\xb4\xc9\x58\xf5\x35\x5a\xac\x29\x4b\x4b\x87\xcb\x03\x7f\x11\xf8\x5f\x07\xeb\x57\xb3\xf0\xb8\x95\x50",
+ "d1f8bd684001ac5a4b67bbf79f87de524d2da99ac014dec3e4187728f4557471"
+ }, {
+ 38,
+ "\xd0\xfe\xfd\x96\x78\x7c\x65\xff\xa7\xf9\x10\xd6\xd0\xad\xa6\x3d\x64\xd5\xc4\x67\x99\x60\xe7\xf0\x6a\xeb\x8c\x70\xdf\xef\x95\x4f\x8e\x39\xef\xdb\x62\x9b",
+ "49ba38db85c2796f85ffd57dd5ec337007414528ae33935b102d16a6b91ba6c1"
+ }, {
+ 39,
+ "\xb7\xc7\x9d\x7e\x5f\x1e\xec\xcd\xfe\xdf\x0e\x7b\xf4\x3e\x73\x0d\x44\x7e\x60\x7d\x8d\x14\x89\x82\x3d\x09\xe1\x12\x01\xa0\xb1\x25\x80\x39\xe7\xbd\x48\x75\xb1",
+ "725e6f8d888ebaf908b7692259ab8839c3248edd22ca115bb13e025808654700"
+ }, {
+ 40,
+ "\x64\xcd\x36\x3e\xcc\xe0\x5f\xdf\xda\x24\x86\xd0\x11\xa3\xdb\x95\xb5\x20\x6a\x19\xd3\x05\x40\x46\x81\x9d\xd0\xd3\x67\x83\x95\x5d\x7e\x5b\xf8\xba\x18\xbf\x73\x8a",
+ "32caef024f84e97c30b4a7b9d04b678b3d8a6eb2259dff5b7f7c011f090845f8"
+ }, {
+ 41,
+ "\x6a\xc6\xc6\x3d\x61\x8e\xaf\x00\xd9\x1c\x5e\x28\x07\xe8\x3c\x09\x39\x12\xb8\xe2\x02\xf7\x8e\x13\x97\x03\x49\x8a\x79\xc6\x06\x7f\x54\x49\x7c\x61\x27\xa2\x39\x10\xa6",
+ "4bb33e7c6916e08a9b3ed6bcef790aaaee0dcf2e7a01afb056182dea2dad7d63"
+ }, {
+ 42,
+ "\xd2\x68\x26\xdb\x9b\xae\xaa\x89\x26\x91\xb6\x89\x00\xb9\x61\x63\x20\x8e\x80\x6a\x1d\xa0\x77\x42\x9e\x45\x4f\xa0\x11\x84\x09\x51\xa0\x31\x32\x7e\x60\x5a\xb8\x2e\xcc\xe2",
+ "3ac7ac6bed82fdc8cd15b746f0ee7489158192c238f371c1883c9fe90b3e2831"
+ }, {
+ 43,
+ "\x3f\x7a\x05\x9b\x65\xd6\xcb\x02\x49\x20\x4a\xac\x10\xb9\xf1\xa4\xac\x9e\x58\x68\xad\xeb\xbe\x93\x5a\x9e\xb5\xb9\x01\x9e\x1c\x93\x8b\xfc\x4e\x5c\x53\x78\x99\x7a\x39\x47\xf2",
+ "bfce809534eefe871273964d32f091fe756c71a7f512ef5f2300bcd57f699e74"
+ }, {
+ 44,
+ "\x60\xff\xcb\x23\xd6\xb8\x8e\x48\x5b\x92\x0a\xf8\x1d\x10\x83\xf6\x29\x1d\x06\xac\x8c\xa3\xa9\x65\xb8\x59\x14\xbc\x2a\xdd\x40\x54\x4a\x02\x7f\xca\x93\x6b\xbd\xe8\xf3\x59\x05\x1c",
+ "1d26f3e04f89b4eaa9dbed9231bb051eef2e8311ad26fe53d0bf0b821eaf7567"
+ }, {
+ 45,
+ "\x9e\xcd\x07\xb6\x84\xbb\x9e\x0e\x66\x92\xe3\x20\xce\xc4\x51\x0c\xa7\x9f\xcd\xb3\xa2\x21\x2c\x26\xd9\x0d\xf6\x5d\xb3\x3e\x69\x2d\x07\x3c\xc1\x74\x84\x0d\xb7\x97\x50\x4e\x48\x2e\xef",
+ "0ffeb644a49e787ccc6970fe29705a4f4c2bfcfe7d19741c158333ff6982cc9c"
+ }, {
+ 46,
+ "\x9d\x64\xde\x71\x61\x89\x58\x84\xe7\xfa\x3d\x6e\x9e\xb9\x96\xe7\xeb\xe5\x11\xb0\x1f\xe1\x9c\xd4\xa6\xb3\x32\x2e\x80\xaa\xf5\x2b\xf6\x44\x7e\xd1\x85\x4e\x71\x00\x1f\x4d\x54\xf8\x93\x1d",
+ "d048ee1524014adf9a56e60a388277de194c694cc787fc5a1b554ea9f07abfdf"
+ }, {
+ 47,
+ "\xc4\xad\x3c\x5e\x78\xd9\x17\xec\xb0\xcb\xbc\xd1\xc4\x81\xfc\x2a\xaf\x23\x2f\x7e\x28\x97\x79\xf4\x0e\x50\x4c\xc3\x09\x66\x2e\xe9\x6f\xec\xbd\x20\x64\x7e\xf0\x0e\x46\x19\x9f\xbc\x48\x2f\x46",
+ "50dbf40066f8d270484ee2ef6632282dfa300a85a8530eceeb0e04275e1c1efd"
+ }, {
+ 48,
+ "\x4e\xef\x51\x07\x45\x9b\xdd\xf8\xf2\x4f\xc7\x65\x6f\xd4\x89\x6d\xa8\x71\x1d\xb5\x04\x00\xc0\x16\x48\x47\xf6\x92\xb8\x86\xce\x8d\x7f\x4d\x67\x39\x50\x90\xb3\x53\x4e\xfd\x7b\x0d\x29\x8d\xa3\x4b",
+ "7c5d14ed83dab875ac25ce7feed6ef837d58e79dc601fb3c1fca48d4464e8b83"
+ }, {
+ 49,
+ "\x04\x7d\x27\x58\xe7\xc2\xc9\x62\x3f\x9b\xdb\x93\xb6\x59\x7c\x5e\x84\xa0\xcd\x34\xe6\x10\x01\x4b\xcb\x25\xb4\x9e\xd0\x5c\x7e\x35\x6e\x98\xc7\xa6\x72\xc3\xdd\xdc\xae\xb8\x43\x17\xef\x61\x4d\x34\x2f",
+ "7d53eccd03da37bf58c1962a8f0f708a5c5c447f6a7e9e26137c169d5bdd82e4"
+ }, {
+ 50,
+ "\x3d\x83\xdf\x37\x17\x2c\x81\xaf\xd0\xde\x11\x51\x39\xfb\xf4\x39\x0c\x22\xe0\x98\xc5\xaf\x4c\x5a\xb4\x85\x24\x06\x51\x0b\xc0\xe6\xcf\x74\x17\x69\xf4\x44\x30\xc5\x27\x0f\xda\xe0\xcb\x84\x9d\x71\xcb\xab",
+ "99dc772e91ea02d9e421d552d61901016b9fd4ad2df4a8212c1ec5ba13893ab2"
+ }, {
+ 51,
+ "\x33\xfd\x9b\xc1\x7e\x2b\x27\x1f\xa0\x4c\x6b\x93\xc0\xbd\xea\xe9\x86\x54\xa7\x68\x2d\x31\xd9\xb4\xda\xb7\xe6\xf3\x2c\xd5\x8f\x2f\x14\x8a\x68\xfb\xe7\xa8\x8c\x5a\xb1\xd8\x8e\xdc\xcd\xde\xb3\x0a\xb2\x1e\x5e",
+ "cefdae1a3d75e792e8698d5e71f177cc761314e9ad5df9602c6e60ae65c4c267"
+ }, {
+ 52,
+ "\x77\xa8\x79\xcf\xa1\x1d\x7f\xca\xc7\xa8\x28\x2c\xc3\x8a\x43\xdc\xf3\x76\x43\xcc\x90\x98\x37\x21\x3b\xd6\xfd\x95\xd9\x56\xb2\x19\xa1\x40\x6c\xbe\x73\xc5\x2c\xd5\x6c\x60\x0e\x55\xb7\x5b\xc3\x7e\xa6\x96\x41\xbc",
+ "c99d64fa4dadd4bc8a389531c68b4590c6df0b9099c4d583bc00889fb7b98008"
+ }, {
+ 53,
+ "\x45\xa3\xe6\xb8\x65\x27\xf2\x0b\x45\x37\xf5\xaf\x96\xcf\xc5\xad\x87\x77\xa2\xdd\xe6\xcf\x75\x11\x88\x6c\x55\x90\xec\xe2\x4f\xc6\x1b\x22\x67\x39\xd2\x07\xda\xbf\xe3\x2b\xa6\xef\xd9\xff\x4c\xd5\xdb\x1b\xd5\xea\xd3",
+ "4d12a849047c6acd4b2eee6be35fa9051b02d21d50d419543008c1d82c427072"
+ }, {
+ 54,
+ "\x25\x36\x2a\x4b\x9d\x74\xbd\xe6\x12\x8c\x4f\xdc\x67\x23\x05\x90\x09\x47\xbc\x3a\xda\x9d\x9d\x31\x6e\xbc\xf1\x66\x7a\xd4\x36\x31\x89\x93\x72\x51\xf1\x49\xc7\x2e\x06\x4a\x48\x60\x8d\x94\x0b\x75\x74\xb1\x7f\xef\xc0\xdf",
+ "f8e4ccab6c979229f6066cc0cb0cfa81bb21447c16c68773be7e558e9f9d798d"
+ }, {
+ 55,
+ "\x3e\xbf\xb0\x6d\xb8\xc3\x8d\x5b\xa0\x37\xf1\x36\x3e\x11\x85\x50\xaa\xd9\x46\x06\xe2\x68\x35\xa0\x1a\xf0\x50\x78\x53\x3c\xc2\x5f\x2f\x39\x57\x3c\x04\xb6\x32\xf6\x2f\x68\xc2\x94\xab\x31\xf2\xa3\xe2\xa1\xa0\xd8\xc2\xbe\x51",
+ "6595a2ef537a69ba8583dfbf7f5bec0ab1f93ce4c8ee1916eff44a93af5749c4"
+ }, {
+ 56,
+ "\x2d\x52\x44\x7d\x12\x44\xd2\xeb\xc2\x86\x50\xe7\xb0\x56\x54\xba\xd3\x5b\x3a\x68\xee\xdc\x7f\x85\x15\x30\x6b\x49\x6d\x75\xf3\xe7\x33\x85\xdd\x1b\x00\x26\x25\x02\x4b\x81\xa0\x2f\x2f\xd6\xdf\xfb\x6e\x6d\x56\x1c\xb7\xd0\xbd\x7a",
+ "cfb88d6faf2de3a69d36195acec2e255e2af2b7d933997f348e09f6ce5758360"
+ }, {
+ 57,
+ "\x4c\xac\xe4\x22\xe4\xa0\x15\xa7\x54\x92\xb3\xb3\xbb\xfb\xdf\x37\x58\xea\xff\x4f\xe5\x04\xb4\x6a\x26\xc9\x0d\xac\xc1\x19\xfa\x90\x50\xf6\x03\xd2\xb5\x8b\x39\x8c\xad\x6d\x6d\x9f\xa9\x22\xa1\x54\xd9\xe0\xbc\x43\x89\x96\x82\x74\xb0",
+ "4d54b2d284a6794581224e08f675541c8feab6eefa3ac1cfe5da4e03e62f72e4"
+ }, {
+ 58,
+ "\x86\x20\xb8\x6f\xbc\xaa\xce\x4f\xf3\xc2\x92\x1b\x84\x66\xdd\xd7\xba\xca\xe0\x7e\xef\xef\x69\x3c\xf1\x77\x62\xdc\xab\xb8\x9a\x84\x01\x0f\xc9\xa0\xfb\x76\xce\x1c\x26\x59\x3a\xd6\x37\xa6\x12\x53\xf2\x24\xd1\xb1\x4a\x05\xad\xdc\xca\xbe",
+ "dba490256c9720c54c612a5bd1ef573cd51dc12b3e7bd8c6db2eabe0aacb846b"
+ }, {
+ 59,
+ "\xd1\xbe\x3f\x13\xfe\xba\xfe\xfc\x14\x41\x4d\x9f\xb7\xf6\x93\xdb\x16\xdc\x1a\xe2\x70\xc5\xb6\x47\xd8\x0d\xa8\x58\x35\x87\xc1\xad\x8c\xb8\xcb\x01\x82\x43\x24\x41\x1c\xa5\xac\xe3\xca\x22\xe1\x79\xa4\xff\x49\x86\xf3\xf2\x11\x90\xf3\xd7\xf3",
+ "02804978eba6e1de65afdbc6a6091ed6b1ecee51e8bff40646a251de6678b7ef"
+ }, {
+ 60,
+ "\xf4\x99\xcc\x3f\x6e\x3c\xf7\xc3\x12\xff\xdf\xba\x61\xb1\x26\x0c\x37\x12\x9c\x1a\xfb\x39\x10\x47\x19\x33\x67\xb7\xb2\xed\xeb\x57\x92\x53\xe5\x1d\x62\xba\x6d\x91\x1e\x7b\x81\x8c\xca\xe1\x55\x3f\x61\x46\xea\x78\x0f\x78\xe2\x21\x9f\x62\x93\x09",
+ "0b66c8b4fefebc8dc7da0bbedc1114f228aa63c37d5c30e91ab500f3eadfcec5"
+ }, {
+ 61,
+ "\x6d\xd6\xef\xd6\xf6\xca\xa6\x3b\x72\x9a\xa8\x18\x6e\x30\x8b\xc1\xbd\xa0\x63\x07\xc0\x5a\x2c\x0a\xe5\xa3\x68\x4e\x6e\x46\x08\x11\x74\x86\x90\xdc\x2b\x58\x77\x59\x67\xcf\xcc\x64\x5f\xd8\x20\x64\xb1\x27\x9f\xdc\xa7\x71\x80\x3d\xb9\xdc\xa0\xff\x53",
+ "c464a7bf6d180de4f744bb2fe5dc27a3f681334ffd54a9814650e60260a478e3"
+ }, {
+ 62,
+ "\x65\x11\xa2\x24\x2d\xdb\x27\x31\x78\xe1\x9a\x82\xc5\x7c\x85\xcb\x05\xa6\x88\x7f\xf2\x01\x4c\xf1\xa3\x1c\xb9\xba\x5d\xf1\x69\x5a\xad\xb2\x5c\x22\xb3\xc5\xed\x51\xc1\x0d\x04\x7d\x25\x6b\x8e\x34\x42\x84\x2a\xe4\xe6\xc5\x25\xf8\xd7\xa5\xa9\x44\xaf\x2a",
+ "d6859c0b5a0b66376a24f56b2ab104286ed0078634ba19112ace0d6d60a9c1ae"
+ }, {
+ 63,
+ "\xe2\xf7\x6e\x97\x60\x6a\x87\x2e\x31\x74\x39\xf1\xa0\x3f\xcd\x92\xe6\x32\xe5\xbd\x4e\x7c\xbc\x4e\x97\xf1\xaf\xc1\x9a\x16\xfd\xe9\x2d\x77\xcb\xe5\x46\x41\x6b\x51\x64\x0c\xdd\xb9\x2a\xf9\x96\x53\x4d\xfd\x81\xed\xb1\x7c\x44\x24\xcf\x1a\xc4\xd7\x5a\xce\xeb",
+ "18041bd4665083001fba8c5411d2d748e8abbfdcdfd9218cb02b68a78e7d4c23"
+ }, {
+ 64,
+ "\x5a\x86\xb7\x37\xea\xea\x8e\xe9\x76\xa0\xa2\x4d\xa6\x3e\x7e\xd7\xee\xfa\xd1\x8a\x10\x1c\x12\x11\xe2\xb3\x65\x0c\x51\x87\xc2\xa8\xa6\x50\x54\x72\x08\x25\x1f\x6d\x42\x37\xe6\x61\xc7\xbf\x4c\x77\xf3\x35\x39\x03\x94\xc3\x7f\xa1\xa9\xf9\xbe\x83\x6a\xc2\x85\x09",
+ "42e61e174fbb3897d6dd6cef3dd2802fe67b331953b06114a65c772859dfc1aa"
+ }, {
+ 0,
+ NULL,
+ NULL
+ }
+};
+
+/* SHA512 short messages test vectors. */
+static struct test_vector sha512_vectors[] = {
+ {
+ 0,
+ "",
+ "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
+ }, {
+ 1,
+ "\x21",
+ "3831a6a6155e509dee59a7f451eb35324d8f8f2df6e3708894740f98fdee23889f4de5adb0c5010dfb555cda77c8ab5dc902094c52de3278f35a75ebc25f093a"
+ }, {
+ 2,
+ "\x90\x83",
+ "55586ebba48768aeb323655ab6f4298fc9f670964fc2e5f2731e34dfa4b0c09e6e1e12e3d7286b3145c61c2047fb1a2a1297f36da64160b31fa4c8c2cddd2fb4"
+ }, {
+ 3,
+ "\x0a\x55\xdb",
+ "7952585e5330cb247d72bae696fc8a6b0f7d0804577e347d99bc1b11e52f384985a428449382306a89261ae143c2f3fb613804ab20b42dc097e5bf4a96ef919b"
+ }, {
+ 4,
+ "\x23\xbe\x86\xd5",
+ "76d42c8eadea35a69990c63a762f330614a4699977f058adb988f406fb0be8f2ea3dce3a2bbd1d827b70b9b299ae6f9e5058ee97b50bd4922d6d37ddc761f8eb"
+ }, {
+ 5,
+ "\xeb\x0c\xa9\x46\xc1",
+ "d39ecedfe6e705a821aee4f58bfc489c3d9433eb4ac1b03a97e321a2586b40dd0522f40fa5aef36afff591a78c916bfc6d1ca515c4983dd8695b1ec7951d723e"
+ }, {
+ 6,
+ "\x38\x66\x7f\x39\x27\x7b",
+ "85708b8ff05d974d6af0801c152b95f5fa5c06af9a35230c5bea2752f031f9bd84bd844717b3add308a70dc777f90813c20b47b16385664eefc88449f04f2131"
+ }, {
+ 7,
+ "\xb3\x9f\x71\xaa\xa8\xa1\x08",
+ "258b8efa05b4a06b1e63c7a3f925c5ef11fa03e3d47d631bf4d474983783d8c0b09449009e842fc9fa15de586c67cf8955a17d790b20f41dadf67ee8cdcdfce6"
+ }, {
+ 8,
+ "\x6f\x8d\x58\xb7\xca\xb1\x88\x8c",
+ "a3941def2803c8dfc08f20c06ba7e9a332ae0c67e47ae57365c243ef40059b11be22c91da6a80c2cff0742a8f4bcd941bdee0b861ec872b215433ce8dcf3c031"
+ }, {
+ 9,
+ "\x16\x2b\x0c\xf9\xb3\x75\x0f\x94\x38",
+ "ade217305dc34392aa4b8e57f64f5a3afdd27f1fa969a9a2608353f82b95cfb4ae84598d01575a578a1068a59b34b5045ff6d5299c5cb7ee17180701b2d1d695"
+ }, {
+ 10,
+ "\xba\xd7\xc6\x18\xf4\x5b\xe2\x07\x97\x5e",
+ "5886828959d1f82254068be0bd14b6a88f59f534061fb20376a0541052dd3635edf3c6f0ca3d08775e13525df9333a2113c0b2af76515887529910b6c793c8a5"
+ }, {
+ 11,
+ "\x62\x13\xe1\x0a\x44\x20\xe0\xd9\xb7\x70\x37",
+ "9982dc2a04dff165567f276fd463efef2b369fa2fbca8cee31ce0de8a79a2eb0b53e437f7d9d1f41c71d725cabb949b513075bad1740c9eefbf6a5c6633400c7"
+ }, {
+ 12,
+ "\x63\x32\xc3\xc2\xa0\xa6\x25\xa6\x1d\xf7\x18\x58",
+ "9d60375d9858d9f2416fb86fa0a2189ee4213e8710314fd1ebed0fd158b043e6e7c9a76d62c6ba1e1d411a730902309ec676dd491433c6ef66c8f116233d6ce7"
+ }, {
+ 13,
+ "\xf4\x7b\xe3\xa2\xb0\x19\xd1\xbe\xed\xed\xf5\xb8\x0c",
+ "b94292625caa28c7be24a0997eb7328062a76d9b529c0f1d568f850df6d569b5e84df07e9e246be232033ffac3adf2d18f92ab9dacfc0ecf08aff7145f0b833b"
+ }, {
+ 14,
+ "\xb1\x71\x5f\x78\x2f\xf0\x2c\x6b\x88\x93\x7f\x05\x41\x16",
+ "ee1a56ee78182ec41d2c3ab33d4c41871d437c5c1ca060ee9e219cb83689b4e5a4174dfdab5d1d1096a31a7c8d3abda75c1b5e6da97e1814901c505b0bc07f25"
+ }, {
+ 15,
+ "\x9b\xcd\x52\x62\x86\x8c\xd9\xc8\xa9\x6c\x9e\x82\x98\x7f\x03",
+ "2e07662a001b9755ae922c8e8a95756db5341dc0f2e62ae1cf827038f33ce055f63ad5c00b65391428434ddc01e5535e7fecbf53db66d93099b8e0b7e44e4b25"
+ }, {
+ 16,
+ "\xcd\x67\xbd\x40\x54\xaa\xa3\xba\xa0\xdb\x17\x8c\xe2\x32\xfd\x5a",
+ "0d8521f8f2f3900332d1a1a55c60ba81d04d28dfe8c504b6328ae787925fe0188f2ba91c3a9f0c1653c4bf0ada356455ea36fd31f8e73e3951cad4ebba8c6e04"
+ }, {
+ 17,
+ "\x6b\xa0\x04\xfd\x17\x67\x91\xef\xb3\x81\xb8\x62\xe2\x98\xc6\x7b\x08",
+ "112e19144a9c51a223a002b977459920e38afd4ca610bd1c532349e9fa7c0d503215c01ad70e1b2ac5133cf2d10c9e8c1a4c9405f291da2dc45f706761c5e8fe"
+ }, {
+ 18,
+ "\xc6\xa1\x70\x93\x65\x68\x65\x10\x20\xed\xfe\x15\xdf\x80\x12\xac\xda\x8d",
+ "c36c100cdb6c8c45b072f18256d63a66c9843acb4d07de62e0600711d4fbe64c8cf314ec3457c90308147cb7ac7e4d073ba10f0ced78ea724a474b32dae71231"
+ }, {
+ 19,
+ "\x61\xbe\x0c\x9f\x5c\xf6\x27\x45\xc7\xda\x47\xc1\x04\x59\x71\x94\xdb\x24\x5c",
+ "b379249a3ca5f14c29456710114ba6f6136b34c3fc9f6fb91b59d491af782d6b237eb71aaffdd38079461cf690a46d9a4ddd602d19808ab6235d1d8aa01e8200"
+ }, {
+ 20,
+ "\xe0\x70\x56\xd4\xf7\x27\x7b\xc5\x48\x09\x95\x77\x72\x0a\x58\x1e\xec\x94\x14\x1d",
+ "59f1856303ff165e2ab5683dddeb6e8ad81f15bb578579b999eb5746680f22cfec6dba741e591ca4d9e53904837701b374be74bbc0847a92179ac2b67496d807"
+ }, {
+ 21,
+ "\x67\xeb\xda\x0a\x35\x73\xa9\xa5\x87\x51\xd4\x16\x9e\x10\xc7\xe8\x66\x3f\xeb\xb3\xa8",
+ "13963f81cfabfca71de4739fd24a10ce3897bba1d716907fc0a28490c192a7fc3ccb8db1f91af7a2d250d6617f0dfd1519d221d618a02e3e3fa9041cf35ed1ea"
+ }, {
+ 22,
+ "\x63\xe0\x9d\xb9\x9e\xb4\xcd\x62\x38\x67\x78\x59\xa5\x67\xdf\x31\x3c\x85\x20\xd8\x45\xb4",
+ "9083e5348b08eb9810b2d15781d8265845410de54fe61750d4b93853690649adc6e72490bc2b7c365e2390573d9414becc0939719e0cb78eca6b2c80c2fda920"
+ }, {
+ 23,
+ "\xf3\xe0\x6b\x4b\xd7\x9e\x38\x0a\x65\xcb\x67\x9a\x98\xcc\xd7\x32\x56\x3c\xc5\xeb\xe8\x92\xe2",
+ "6b315f106b07c59eedc5ab1df813b3c0b903060e7217cc010e9070278512a885008dac8b2472a521e77835a7f4deadc1d591aa23b624b69948a99bb60121c54e"
+ }, {
+ 24,
+ "\x16\xb1\x70\x74\xd3\xe3\xd9\x75\x57\xf9\xed\x77\xd9\x20\xb4\xb1\xbf\xf4\xe8\x45\xb3\x45\xa9\x22",
+ "6884134582a760046433abcbd53db8ff1a89995862f305b887020f6da6c7b903a314721e972bf438483f452a8b09596298a576c903c91df4a414c7bd20fd1d07"
+ }, {
+ 25,
+ "\x3e\xdf\x93\x25\x13\x49\xd2\x28\x06\xbe\xd2\x53\x45\xfd\x5c\x19\x0a\xac\x96\xd6\xcd\xb2\xd7\x58\xb8",
+ "299e0daf6605e5b0c30e1ec8bb98e7a3bd7b33b388bdb457452dab509594406c8e7b841e6f4e75c8d6fbd614d5eb9e56c359bfafb4285754787ab72b46dd33f0"
+ }, {
+ 26,
+ "\xb2\xd5\xa1\x4f\x01\xe6\xb7\x78\x88\x8c\x56\x2a\x05\x9e\xc8\x19\xad\x89\x99\x2d\x16\xa0\x9f\x7a\x54\xb4",
+ "ab2e7d745d8ad393439af2a3fbc9cdc25510d4a04e78b526e12b1c0be3b22966872ebe652e2f46ed5c5acecd2f233a9175dd295ebeb3a0706fc66fa1b137042b"
+ }, {
+ 27,
+ "\x84\x4b\x66\xf1\x2b\xa0\xc5\xf9\xe9\x27\x31\xf5\x71\x53\x9d\x1e\xef\x33\x2e\x15\x49\xa4\x9d\xbf\xa4\xc6\xde",
+ "c3f9c5781925774783ae9d839772d7513dfcea8c5af8da262c196f9fe80135b2b0c8c6ca0a1604e0a3460247620de20b299f2db7871982d27c2176ae5fa7ad65"
+ }, {
+ 28,
+ "\x6b\x6c\xc6\x92\xd3\x98\x60\xb1\xf3\x02\x03\x65\x3e\x25\xd0\x9c\x01\xe6\xa8\x04\x3c\x1a\x9c\xb8\xb2\x49\xa4\x1e",
+ "2e5263d9a4f21b210e0e161ed39df44102864325788647261a6e70ea4b1ee0abb57b57499bc82158d82336dd53f1ef4464c6a08126e138b2cc0892f765f6af85"
+ }, {
+ 29,
+ "\xab\x1f\xc9\xee\x84\x5e\xeb\x20\x5e\xc1\x37\x25\xda\xf1\xfb\x1f\x5d\x50\x62\x9b\x14\xea\x9a\x22\x35\xa9\x35\x0a\x88",
+ "72d188a9df5f3b00057bca22c92c0f8228422d974302d22d4b322e7a6c8fc3b2b50ec74c6842781f29f7075c3d4bd065878648846c39bb3e4e2692c0f053f7ed"
+ }, {
+ 30,
+ "\x59\x4e\xd8\x2a\xcf\xc0\x3c\x0e\x35\x9c\xc5\x60\xb8\xe4\xb8\x5f\x6e\xe7\x7e\xe5\x9a\x70\x02\x3c\x2b\x3d\x5b\x32\x85\xb2",
+ "5ef322cb4014ecbb713a13659612a222225984d31c187debc4459ba7901f03dac775400acfe3510b306b79894fb0e8437b412150c9193ee5a2164306ebb78301"
+ }, {
+ 31,
+ "\xf2\xc6\x6e\xfb\xf2\xa7\x6c\x5b\x04\x18\x60\xea\x57\x61\x03\xcd\x8c\x6b\x25\xe5\x0e\xca\x9f\xf6\xa2\xfa\x88\x08\x3f\xe9\xac",
+ "7978f93ef7ed02c4a24abecba124d14dd214e1492ff1e168304c0eab89637da0f7a569c43dc4562bdb9404a018b6314fe0eebaccfb25ba76506aa7e9dcd956a7"
+ }, {
+ 32,
+ "\x8c\xcb\x08\xd2\xa1\xa2\x82\xaa\x8c\xc9\x99\x02\xec\xaf\x0f\x67\xa9\xf2\x1c\xff\xe2\x80\x05\xcb\x27\xfc\xf1\x29\xe9\x63\xf9\x9d",
+ "4551def2f9127386eea8d4dae1ea8d8e49b2add0509f27ccbce7d9e950ac7db01d5bca579c271b9f2d806730d88f58252fd0c2587851c3ac8a0e72b4e1dc0da6"
+ }, {
+ 33,
+ "\x9f\x8c\x49\x32\x0a\xf9\x37\x0c\xd3\xdb\x20\xe9\xb5\x0d\x3e\xaa\x59\xa6\x23\x2d\x7a\x86\xfb\x7d\x47\x2f\x12\x45\x08\xd7\x96\x8b\x05",
+ "81b002f15c4d48be8517f7ed89df302fb1435c9435efefed58f3eb8ea11910623f1eb9028a66e02121a7f08a7c604226f2324f483e91548dbbd2c441ab704ce5"
+ }, {
+ 34,
+ "\x4a\xb9\xaa\x06\x94\x75\xe5\x4b\x25\xe5\x68\x8a\x52\xdd\x4a\xcd\x13\x41\x69\xc8\x58\x10\x5f\x01\xa0\xa1\xb1\x34\xc7\x2d\x4a\xf5\x1f\x8e",
+ "48ba5a63aba7e7bd8e420475331125a947928c67fdb00f65c4080d9a0b99c0672424e76a1ba6bd76dfe492c730f6f9adccaee7bb11571aadb31f6bb628cfa933"
+ }, {
+ 35,
+ "\xf0\xc1\xd3\x40\x7d\xe9\x2e\xf7\x42\x1e\x42\xdf\x5c\x9a\xb3\x1d\x2e\xc0\xa7\x50\xa9\x52\x28\x69\xcb\xe4\xca\xbd\x66\x90\x8d\x58\x23\xec\x04",
+ "9e75c5bca2c2af1d7739787f46e1d981c4f98e493d0724b5252c2fbae3c526719f1d27e6ccd0d705240281e8fbf3db75b9b3205c1413436d3b5d140004b8cca1"
+ }, {
+ 36,
+ "\xae\x8c\x9f\x8f\xb4\x1b\x51\x9b\x6d\x94\x38\x33\xfe\x1c\x32\xd1\xc4\x29\x2f\xb1\xdd\xf1\xdb\xe2\xeb\x22\x7d\x9e\x14\xd3\x1e\xd7\x4e\xba\xef\x12",
+ "042f9fd0a4ed3d9fec3655ae11011c6f2bc7e457e8812b6d8be2cd45fc6c432a94558c88f22c01439618865e8e49e509c448b342ca914b120344aaf7bcbdca18"
+ }, {
+ 37,
+ "\xda\x39\xfb\x86\x23\x7f\x00\x30\x38\x44\xe6\x1f\xc6\xcf\xe7\x79\xe4\x2a\xf5\x33\x49\x83\x95\x90\xbc\xd2\xf0\xe4\xcb\xbc\x27\x9e\xc0\xb7\xe8\x85\xd1",
+ "ecb43de8c233a731b38e30c5696f8876761b7ea72efe283fd07bedf20029f47c6d2a4427823e100fb087abaf22d7eff42a951c97c3dd05f48a20163fa4367cba"
+ }, {
+ 38,
+ "\x3e\x72\x71\xd2\x07\x0e\xf0\x95\x39\x46\x20\xc4\xb0\x16\x57\x6c\x15\x0f\x34\xbe\xa6\x07\x84\x61\x3a\x0f\x66\x0d\x7f\xa5\xae\x56\x87\x2b\x88\xc5\x83\x98",
+ "8154d0da634ab2266061acc123acb407650ffe9164a22de3fe29bf05393b2aece92cf4db00ea5b4341c31ddb7de151683c8a71b5a44d5c3175790feac67d18ee"
+ }, {
+ 39,
+ "\x31\x1f\xb6\x7f\x6a\x07\x84\xbb\x01\xa2\xd5\xa3\xf3\x09\x2c\x40\x7a\x9d\x33\x22\x31\x9d\xff\x9a\x79\xf8\x94\x29\x1c\x5f\xac\x37\x31\x9f\xb4\x08\x40\x2e\x18",
+ "1870fe913abb0a4b4f53b6581ae18322cd05328514556607f3f4d7b6a2ac8e9185d94d947d8b9c88e0efa66d89b59f7439c75fdadd1816f7412306ab2b59d664"
+ }, {
+ 40,
+ "\x76\x51\xab\x49\x1b\x8f\xa8\x6f\x96\x9d\x42\x97\x7d\x09\xdf\x5f\x8b\xee\x3e\x58\x99\x18\x0b\x52\xc9\x68\xb0\xdb\x05\x7a\x6f\x02\xa8\x86\xad\x61\x7a\x84\x91\x5a",
+ "f35e50e2e02b8781345f8ceb2198f068ba103476f715cfb487a452882c9f0de0c720b2a088a39d06a8a6b64ce4d6470dfeadc4f65ae06672c057e29f14c4daf9"
+ }, {
+ 41,
+ "\xdb\xe5\xdb\x68\x5e\xd7\xcb\x84\x8c\x09\x45\x24\xc1\x72\x35\x19\xd4\x9d\xc6\x6e\xf9\xfe\x6d\x57\xe6\x86\x2a\x64\x35\x75\x0b\xfa\x0a\x70\xf1\x04\xf5\xd3\x96\xe6\x1a",
+ "2fa6e5b2c443a68050f093e7fb713bd6b18f6274c061ed61d79bf0688a61dba1940bcc30998276860943ab038902896d0fbf59b88b07c80de927037097150c40"
+ }, {
+ 42,
+ "\x9f\xa8\x3e\x96\xb2\xa6\xdf\x23\xfb\x37\x28\x95\x01\x56\x78\xe0\xb2\xc9\xcd\x18\xa8\x54\x2c\x3e\xaa\x2c\x43\x5a\x76\xae\x4d\xc9\xbd\x51\x36\xd9\x70\xda\xff\x93\x3a\xcf",
+ "3a2c0ec88a3e5347cf0ea9c078838300ef7356f9a6c342063277c106b880a00ed2be205c13064097bd372fde38007bc306561eb4e74bba2bb20bd354aa690ca6"
+ }, {
+ 43,
+ "\x8a\x5a\x45\xe3\x98\xba\xc1\xd9\xb8\x96\xb5\xa2\xb4\xe3\x56\x6b\x91\xd8\x0a\xd2\x0c\x97\x7e\xa7\x45\x0f\xf2\xef\xb5\x21\xd8\x2f\x65\x01\x9e\xe7\x62\xe0\xc8\x5c\x6c\xc8\x41",
+ "3c704620f4066d79c1ff67752980f39ef3d9c1023fa5a213a5265376b14a15166ffe069b51df7710d8907fef9406bf375d502ce086ac82aff17229aaa7a5a334"
+ }, {
+ 44,
+ "\x49\xcf\xff\xda\xf4\xd0\x31\xe3\x3b\x1d\x28\xa4\x47\x45\x05\x45\xf6\xc4\x29\x3b\x38\xd5\xaf\xbc\xb9\x88\x39\x76\xc0\x14\xf0\x80\x57\x6e\xc6\x91\xac\x1b\xff\x70\xb7\x42\xef\xab",
+ "8bcc4f1ea2b7862ef1591bfa73916665de8faf65439ddf5cc1be43cebfd5f60f205e835a2b186b675b041258c5cff42669316ce25b46a2f4d4218e102f0f5d6f"
+ }, {
+ 45,
+ "\x2f\xf8\x45\xd8\x5e\xfb\xc4\xfa\x56\x37\xe9\x44\x8d\x95\x04\x96\xf1\x9d\x8d\x57\xda\x99\xb7\xbd\x3d\xf7\x47\x48\x22\xf0\xa7\x90\x58\x67\x36\x41\x67\x14\xe3\x64\xc6\xe1\xfa\xe0\x4e",
+ "236f6f4ed6e858c02d51787e60c578f731f694f8e52b5df4ecd5b04dff14c78e56bad1028d6f626c29d85aeee151a2a2846d3eed5cfafa9854a69fea8af6d04a"
+ }, {
+ 46,
+ "\xcf\xca\x05\xfd\x89\x3c\x0f\x00\x5f\x5f\xf7\x96\xf4\xda\x19\xba\x27\xa1\xe7\x29\x95\x6b\x8b\x71\x5e\x67\xce\x4b\x2d\x2a\x38\x2a\x72\xec\x78\x14\xf2\xf5\x07\xb1\x82\x52\x09\xa2\x0f\xcc",
+ "d80969284a4565add4dad6ab9b3bdf53446142f84aaf92d4b23dd22ee7241e6c81489ac8b246edcb6df9bd7b23d91a0c517f546feba4ed5790a2be6e165c1709"
+ }, {
+ 47,
+ "\xcf\xc4\x25\x75\x9a\x9c\x36\xbb\x9f\x4b\x32\xee\xd7\x76\x7a\xf6\x56\x6f\x68\xde\xd0\xad\xea\xe2\x5c\x7a\x70\xca\x78\xec\x09\x77\x4d\x16\xc8\xbc\x35\x7f\x6d\x6f\x7b\xd4\x41\xbf\x62\xd9\x42",
+ "b587a785cdf455cc9c544e756c1e306300aa3c59f8725012e68ab4d54020b6d227a164d9f83c905e86f8cebeef708a69f976d6e7b18b9bf78e9b98cc4a5cd1b6"
+ }, {
+ 48,
+ "\x09\x7c\x9d\xb9\x19\x51\x52\x42\xc9\x9d\x97\x3a\xcb\x1d\xc4\xed\x48\x27\x68\xf9\x74\xeb\x83\xb4\x65\xf9\xf6\xc8\x25\x03\x37\x20\x06\xe4\x49\x08\x35\xe2\xec\x8f\x92\x30\x11\x30\xbf\xb7\x90\xb2",
+ "ff5a376f938e73014caef7fe3962944a7230d020b7087869ebe7ec70302721cd06fcdc981c893a425d05e2f99fe198e4db50a088aee2bf1263212110efed422c"
+ }, {
+ 49,
+ "\x77\xe7\x3d\x38\x7e\x7b\xc8\x04\x19\xeb\xf5\x48\x2b\x61\xd5\x25\x5c\xaf\x81\x9f\xb5\x92\x51\xff\x6a\x38\x4e\x75\xf6\x01\xea\x02\x6d\x83\xef\x95\x0e\xd0\xb6\x75\x18\xfb\x99\xde\xe0\xd8\xaa\xef\x1f",
+ "c4c89cd882ec945cc888fb9a0127d35e585ecc14a75e4b5b3d8330538d22da28cf6af1ebec96dc247f109cd2aaab9756e6946a3d80db8363a4da3e6ddbb510a1"
+ }, {
+ 50,
+ "\x31\x7e\x5d\x9a\xc7\x3e\xd0\x63\x3f\xa1\x8e\xbe\xbb\xca\x79\x09\xec\x3a\x5e\xf7\x90\x47\x8f\x9c\x38\xca\xce\xc4\x4f\x19\x6d\x89\x58\x35\xb4\x25\x77\x44\x83\x04\x33\x41\x38\x1e\x7a\xf2\xd3\x83\xe5\x1a",
+ "b10bb04491b9c0c334709b407cda1d503efb6b63ee944f2d366b6855e6e63e5b80115be4be7ff63edecdfb5923792e68123976d79212b3884dec2179d1fcf382"
+ }, {
+ 51,
+ "\x20\x94\x61\xf2\x06\x66\xa3\x46\xfe\xdf\x4a\x53\x0f\x41\xa6\xfa\x28\x0c\x43\x66\x57\x67\xbe\x92\x3b\xc1\xd8\x0b\xbc\xb8\xc9\xf8\xf9\x3a\xd7\x57\x82\xea\x26\x89\xc8\xc5\xd2\x11\xd2\x05\x3b\x99\x31\x45\xa0",
+ "67b7a328d9444056a52ca2f695c5d3f3baafb625a14fb32eee8ff26a40ccb296bec1771a826b55f7ddb6170d4caf7795b612448e66a0f19356fe505927149b47"
+ }, {
+ 52,
+ "\x5d\x61\xaa\x45\xc4\x46\xf3\xbf\x93\x60\x4b\x05\x11\x31\x3b\x4e\x2f\x30\x6d\x6b\x04\x6f\xbd\x94\x79\x7b\x92\x67\x46\x83\x6f\x2e\x1d\xbd\xc5\x61\x24\x06\x0c\x6c\xa9\xc9\x11\xb1\x12\x21\x92\xd1\x12\x42\x08\x27",
+ "d3931bde2bde8271ed18ca0b9148b12f6f16161e637e376fc961f65bc33bcacf2f6addf26a3eaa81b196653cc37e8a739ec5b3df870d8c38c8f28691c22a39bb"
+ }, {
+ 53,
+ "\x92\x88\xc7\x95\xbb\x0b\x86\xc0\x41\x9d\x9c\x56\x37\xdc\xc3\x7b\x39\xbf\xa1\x8d\x44\x1e\x3f\xbf\xca\x75\xbc\x03\x06\xe5\x43\x2e\x8e\x7b\x3a\x56\x27\xb5\xbc\x7f\xdc\x42\x4a\x77\x52\x0a\xbd\xff\x56\x6e\x7f\x2b\xb8",
+ "e363d0e95d8cd18c384016ebeed6d99c4fa2768e2bd58fca019c5108b9cde1cb46f3f884028a55ce282ec310a10037faa1b16b4a6a669957f0b00f350bbd63d0"
+ }, {
+ 54,
+ "\x78\x04\x27\xdc\x16\x4b\x2f\x69\xb8\xc7\xd5\x69\x26\x6f\x46\x1e\x2d\x30\xc8\x8c\x4c\xd6\x05\x7f\xb0\x30\xa6\xcf\x63\x6f\x24\xe3\xc0\xd0\xdb\x74\x2a\x7b\x61\x93\xfd\xaa\x15\xee\xc5\x0d\xfb\x4f\xae\x6e\xc7\x65\x3c\x91",
+ "2964b009fb1bf996de12e030b9d6e0608ae8b9dbf2acfb9beb76fc5361cc104ee85c2a46fb7b4cee90848312da302de49afe61c546477e2b25d223d5e3d33560"
+ }, {
+ 55,
+ "\xec\x2a\x92\xe4\x7f\x69\x2b\x53\xc1\x35\x54\x75\xc7\x1c\xef\xf0\xb0\x95\x2a\x8b\x35\x41\xb2\x93\x82\x70\x24\x7d\x44\xe7\xc5\xcc\x04\xe1\x72\x36\xb3\x53\xda\x02\x86\x74\xea\xb4\x04\x7d\x89\xec\x5d\xad\x86\x8c\xfd\x91\xce",
+ "c83aca6147bfcbbc72c377efa8d53654ba0830c5a6a89e1d2a19b713e68fb534640deb833ca512247166dd273b5897e57d526f88eef58f6ff97baee0b4ee5644"
+ }, {
+ 56,
+ "\xc9\x9e\x31\xad\x4e\x23\xac\x68\xe1\x5e\x60\x5d\x0b\x02\x43\x7f\x81\x47\xc4\x4f\x54\x45\xa5\x5b\x68\xa1\x09\x05\x27\x6c\xce\x86\x76\x48\x1c\x33\xe8\xcd\x3e\xfe\x32\x2b\xb1\x3f\xe0\x10\x7b\xb5\x46\xcc\xbe\xc7\xb8\xb3\x8d\x10",
+ "52992d45a88221d972958e9f2854adaa9a21d2bf7051e1f1019ae78004da50c5b55c144a02afffe539d753949a2b056534f5b4c21f248a05baa52a6c38c7f5dd"
+ }, {
+ 57,
+ "\x9a\xa3\xe8\xad\x92\x77\x7d\xfe\xb1\x21\xa6\x46\xce\x2e\x91\x8d\x1e\x12\xb3\x07\x54\xbc\x09\x47\x0d\x6d\xa4\xaf\x6c\xc9\x64\x2b\x01\x2f\x04\x1f\xf0\x46\x56\x9d\x4f\xd8\xd0\xdc\xcf\xe4\x48\xe5\x9f\xee\xfc\x90\x8d\x9a\xd5\xaf\x6f",
+ "994d1cda4de40aff4713237cf9f78f7033af83369ac9c64e504091ea2f1caff6c5152d6a0c5608f82886c0093b3d7fbadd49dfd1f9e0f85accf23bc7dad48904"
+ }, {
+ 58,
+ "\x58\x42\x51\x2c\x37\x31\x25\x11\xa3\xd8\xae\x41\xf5\x80\x1d\xf6\x0c\xd6\x82\xd5\x8b\x4a\x99\x73\x42\xb6\xe7\x17\xe9\x40\x06\xc2\x14\x81\x3e\x6c\x63\xe7\x55\x91\xf9\x57\xa7\xec\x30\x17\x79\x83\x8b\xec\x8a\xe3\xed\x7f\xeb\xad\x08\x05",
+ "9763c43331ad0eb279d704c5f6e97e02da8724115026827f889e9fcda21f60fd230894ab35abb719890f3afa51afd31bc6852183b9c51059910af460abd2474d"
+ }, {
+ 59,
+ "\xca\x14\xe2\xea\x2f\x37\xc7\x8f\x78\xef\x28\x0f\x58\x70\x7e\xc5\x49\xa3\x1a\x94\x36\x10\x73\xe3\x77\x01\xbf\xe5\x03\xe4\xc0\x1e\xe1\xf2\xe1\x23\xe0\x0e\x81\xa1\x88\xf0\x8f\xa0\x50\x82\x57\x09\x12\x8a\x9b\x66\xbb\x8a\xe6\xea\x47\xe4\x1d",
+ "4600e022a02258739f67fdd367cc1e662631fb087918768352062b9b3c8de8dbca0e9ec751b91f284694fbddb8d325c0637bccb21dd2efa92e48dbab2e5e9c26"
+ }, {
+ 60,
+ "\x64\x76\x29\xc7\x79\xb2\x4c\x1e\x76\xf4\x17\x44\xab\xa1\x71\x59\x48\x75\x32\xa0\x15\x6a\x7d\x82\x64\xdb\x50\xd6\x45\xe9\x59\x5f\xf8\x1e\x0c\x96\xa8\x50\xf2\xaa\x56\xc8\x44\xc6\x13\xa4\xb8\x92\x72\x7a\x9b\xfc\x3d\x3e\x20\x38\x67\x66\xf8\x05",
+ "5bc842fc2d3b7eb31d2d3044df3ec32af114feaa7cfc27ebc8630f46ab6f0c543f59b812e776e5303861d17da3f1f16097641f3b808d4d5cb3e483946409746c"
+ }, {
+ 61,
+ "\x1c\x5d\xc0\xd1\xdd\x2e\x4c\x71\x76\x35\xff\x3e\x9b\x67\xca\xf9\x57\xae\xc0\xf8\xf6\x3c\x1b\x1e\x22\x1e\x80\x0a\x4c\x14\x84\x8f\x4e\xa0\x6e\x64\x4e\x5d\x3e\x1d\xe5\x92\xef\x5a\x80\x07\xfa\x3f\x07\x17\x1b\x24\xbd\x07\x57\x8d\x68\x96\x3e\x5c\xb1",
+ "cbf1ea86fa5b3dbf67be82fac41e84cccd0d296c757169b37837d273ccc015eecd102b9ce1cff68fdc7f05d22f2b774734f62ded54c8ee0bf57a5a82010d74f5"
+ }, {
+ 62,
+ "\x8a\x55\x5e\x75\x47\x7d\x06\x5b\x3a\xf7\xe6\x15\x47\x5f\x37\xc0\xa6\x67\xf7\x3a\x4c\x7a\xf5\xe4\xa6\x9f\x28\xa6\x8d\x9f\x44\x34\x77\x6a\x8f\x90\xea\xb7\xf1\xd1\x37\xeb\x4b\x22\x64\x3c\x0a\x0d\x6a\x16\xfc\xfa\xa1\xbd\x62\xf2\x78\x35\x46\xa9\x69\x5f",
+ "c088e4a3d7da2f6f99a8f3f717361108872b8ffef921b383c24b8061d4e7c27fc56f4f20dc8f952a14043c5650b5a9e777c49c41cfeb3f2de97ee2e16b2c3924"
+ }, {
+ 63,
+ "\xeb\xb3\xe2\xad\x78\x03\x50\x8b\xa4\x6e\x81\xe2\x20\xb1\xcf\xf3\x3e\xa8\x38\x15\x04\x11\x0e\x9f\x80\x92\xef\x08\x5a\xfe\xf8\x4d\xb0\xd4\x36\x93\x1d\x08\x5d\x0e\x1b\x06\xbd\x21\x8c\xf5\x71\xc7\x93\x38\xda\x31\xa8\x3b\x4c\xb1\xec\x6c\x06\xd6\xb9\x87\x68",
+ "f33428d8fc67aa2cc1adcb2822f37f29cbd72abff68190483e415824f0bcecd447cb4f05a9c47031b9c50e0411c552f31cd04c30cea2bc64bcf825a5f8a66028"
+ }, {
+ 64,
+ "\xc1\xca\x70\xae\x12\x79\xba\x0b\x91\x81\x57\x55\x8b\x49\x20\xd6\xb7\xfb\xa8\xa0\x6b\xe5\x15\x17\x0f\x20\x2f\xaf\xd3\x6f\xb7\xf7\x9d\x69\xfa\xd7\x45\xdb\xa6\x15\x05\x68\xdb\x1e\x2b\x72\x85\x04\x11\x3e\xea\xc3\x4f\x52\x7f\xc8\x2f\x22\x00\xb4\x62\xec\xbf\x5d",
+ "046e46623912b3932b8d662ab42583423843206301b58bf20ab6d76fd47f1cbbcf421df536ecd7e56db5354e7e0f98822d2129c197f6f0f222b8ec5231f3967d"
+ }, {
+ 65,
+ "\xd3\xdd\xdd\xf8\x05\xb1\x67\x8a\x02\xe3\x92\x00\xf6\x44\x00\x47\xac\xbb\x06\x2e\x4a\x2f\x04\x6a\x3c\xa7\xf1\xdd\x6e\xb0\x3a\x18\xbe\x00\xcd\x1e\xb1\x58\x70\x6a\x64\xaf\x58\x34\xc6\x8c\xf7\xf1\x05\xb4\x15\x19\x46\x05\x22\x2c\x99\xa2\xcb\xf7\x2c\x50\xcb\x14\xbf",
+ "bae7c5d590bf25a493d8f48b8b4638ccb10541c67996e47287b984322009d27d1348f3ef2999f5ee0d38e112cd5a807a57830cdc318a1181e6c4653cdb8cf122"
+ }, {
+ 66,
+ "\x8e\x8e\xf8\xaa\x33\x6b\x3b\x98\x89\x4c\x31\x26\xc7\x18\x78\x91\x06\x18\x83\x8c\x00\xac\x85\x90\x17\x3c\x91\x74\x99\x72\xff\x3d\x42\xa6\x11\x37\x02\x9a\xd7\x45\x01\x68\x4f\x75\xe1\xb8\xd1\xd7\x43\x36\xaa\x90\x8c\x44\x08\x2a\xe9\xeb\x16\x2e\x90\x18\x67\xf5\x49\x05",
+ "41672931558a93762522b1d55389ecf1b8c0feb8b88f4587fbd417ca809055b0cb630d8bea133ab7f6cf1f21c6b35e2e25c0d19583258808e6c23e1a75336103"
+ }, {
+ 67,
+ "\x52\x76\x1e\x1d\xac\x0e\xae\xa8\x98\xe0\xb0\x7c\xd2\x4f\x4b\x2e\x6b\xb7\xbc\x20\x0e\xa4\xb0\x52\x88\x42\xf1\x7b\x87\x15\x45\x59\xa2\xea\x94\x45\x9a\x0e\x48\x0a\xe0\xbd\xf9\xf7\x57\xdd\x4a\x33\x5a\xed\x0e\x51\x01\x38\xb0\x24\xa0\x4e\xd1\xd5\x91\xb4\x32\x32\x34\xdb\xd5",
+ "b826fe80494e19c51b42f2582b2d080ba6b90512f35f2db67dd7fd5ee532eaa16498afba08b4996cbcfdf8d1a2df6b1da939e8265115a48aefa42f38205db436"
+ }, {
+ 68,
+ "\x38\x04\xeb\xc4\x3c\xbe\xa8\x0c\x2b\xd7\xe4\xfd\xa5\xc5\x51\x55\x00\xcd\x2d\x2b\x84\x6a\x13\x78\xdb\xf2\x18\xd5\xc3\x77\x13\x86\x06\xeb\x3c\xb8\xac\x88\xf9\x07\x6f\x6f\xf4\x43\x6f\x90\x71\x74\x27\xc9\xdf\x1b\xa0\x52\xac\xbb\xe4\x58\x5e\x98\xb6\xe8\xe0\xbf\x80\x0f\x19\x46",
+ "17dd6d87bc6773051e52047fd444996afa8124b0483fe121877f98553448772bd0e7751fc655e9cc2d29830211015d310f191474ca6adc0477a187c03b8fe252"
+ }, {
+ 69,
+ "\x22\x49\xd6\x98\xc4\xd8\x07\xa8\xe7\xb4\xde\x21\xc4\x85\x73\x89\x59\xa0\xd6\x7e\x5d\x2c\xa6\xf7\x79\x83\xdf\xcc\xb5\xdb\xf4\x79\x31\x26\x1e\x1f\x15\x37\xf3\xcb\xca\x25\x3a\xfb\x6b\xf4\xfe\x5e\x76\x72\xe1\xdc\xc8\x60\xb3\xd6\xc8\xd2\x43\xaf\xe2\xd9\x75\x8b\x37\x5e\x95\x56\x92",
+ "6af44563fc468d51182f6c3be58d45932af1d985c6f283976c91a9ff421f383fe21dc7322f397ccead583e26b3e3fda067976a7f34665df25a2ced7b4b09cdec"
+ }, {
+ 70,
+ "\x32\xa9\xc1\x70\x33\x65\x8c\x54\xf2\x2c\x71\x35\xdd\xfc\x87\x9d\xe9\x4d\x79\x59\x3e\xf2\xdc\x7d\x30\x41\xbf\xa8\x72\x73\x83\x89\x86\x4e\xed\xa2\x78\x01\x79\x4c\xcc\x4f\xf1\xfc\xb5\xef\x3f\xc4\x88\x33\x80\x1d\x6f\xe9\x59\xe3\x62\x7f\x8e\xa1\x53\x6a\xd0\x0f\xa9\xc7\xd7\xd9\xf0\x43",
+ "6a47699dd3ada2f11bc4ea42072b06cc20857bf164497df1285400c250f5848b6f71957dbdc845f5daeab913036661f69387893fc2d61c25fa59b9d85b19f401"
+ }, {
+ 71,
+ "\x3d\x65\xf6\x9a\x59\x0a\x5b\xaa\xab\xcd\x27\x4f\xe3\xef\x9e\x88\x92\x0f\xfc\x7a\xdf\x05\xc1\x6d\x7b\x0f\x4d\x18\xd7\x2b\xac\x1e\x94\xc3\xb3\xd8\x3b\x8f\x4c\x55\x2e\xb8\x0e\x9f\xde\x39\x11\x40\x3f\x8b\x00\x05\x79\x81\x6f\x02\xe1\x71\x6f\xd6\x27\x94\x60\x31\xd0\xaf\x07\x93\xe7\xf3\xe1",
+ "ffb2d9450943c24b5933c24812459b75d3d9f380344c9bc06fa3e17ee448eca2f98ff79f7e2235ccd9f9a8176f68a2254bbc9b834d6ac8d2bfdbc1597c432c9f"
+ }, {
+ 72,
+ "\x76\xff\x8b\x20\xa1\x8c\xf1\x04\xf6\xcd\xb6\x5e\x2b\xa8\xf6\x6e\xcf\x84\x4a\xf7\xe8\x5e\x8e\xf2\xda\x19\xe8\x84\x8a\x16\x05\x2e\xc4\x05\xa6\x44\xda\xfb\x5c\xa0\x8e\xc4\x8f\x97\x32\x7a\xc5\x2c\x0e\x56\x21\x84\x02\xc7\x2a\x9a\x6d\xc1\xcf\x34\x4d\x58\xa7\x16\xa7\x8d\x7d\x75\x29\x68\x0b\xae",
+ "f8858144c6d709dd0689a526a548a43f17494950ba2ac20544799e8ea27201d78bce5b921e29a7b4029278e68341ef2a0ca4ba3894566b3c8f8950e3e545a689"
+ }, {
+ 73,
+ "\xca\x88\xdd\xdf\xc8\x76\xa1\x2f\x45\xf1\x95\x62\xbc\x9c\xa2\x50\xf4\x32\x67\xab\x25\x1a\x7f\x34\x5c\x3c\x02\x2e\x20\x14\x4e\x13\x56\x04\x07\x87\x62\xef\x5c\x8a\x8f\x03\x8c\xf1\xb1\xd6\xa9\x17\x09\xb5\x9d\xd0\x68\x39\x6a\x9e\x97\x1a\xb6\x28\xf7\x48\x86\xe7\x65\x38\x4a\x23\x60\x7c\x1a\x1e\x6e",
+ "4f3d9eeef349ca51a7e419af1686f42795abde58a85335ce68d496e81e4436a80a61dc143a4300008c23a3e71f4ba98743195a3694a8d02fee11bd314569abc0"
+ }, {
+ 74,
+ "\x0a\x78\xb1\x6b\x40\x26\xf7\xec\x06\x3d\xb4\xe7\xb7\x7c\x42\xa2\x98\xe5\x24\xe2\x68\x09\x3c\x50\x38\x85\x3e\x21\x7d\xcd\x65\xf6\x64\x28\x65\x01\x65\xfc\xa0\x6a\x1b\x4c\x9c\xf1\x53\x7f\xb5\xd4\x63\x63\x0f\xf3\xbd\x71\xcf\x32\xc3\x53\x8b\x1f\xdd\xa3\xfe\xd5\xc9\xf6\x01\x20\x33\x19\xb7\xe1\x86\x9a",
+ "6095c3df5b9db7ce524d76123f77421ce888b86a477ae8c6db1d0be8d326d22c852915ab03c0c81a5b7ac71e2c14e74bda17a78d2b10585fa214f6546eb710a0"
+ }, {
+ 75,
+ "\x20\xf1\x0e\xf9\xa0\xe6\x12\x86\x75\x34\x01\x71\xcd\x24\x8d\xf3\x0b\x58\x65\x57\x62\x0b\x61\x5c\xa3\x9a\x00\xdb\x53\x43\x15\xa9\x01\x2d\xbd\xbf\xd6\xa9\x94\x98\x6e\xb8\x29\xdb\xe6\xcd\xaf\x3a\x37\xd4\xf5\x9a\xc2\x72\x98\x74\x2c\x8f\x77\x7b\x6b\x12\x67\x7f\x21\xeb\x28\x91\x29\x57\x98\x68\x70\x5f\x27",
+ "b4ead3f860eabbd36c770d66c7356f8107acd1485c7c94178c2eaabd50266d7645d009972586ef83ed43ed92882137df5117b88f35231b894ec1741ae7501145"
+ }, {
+ 76,
+ "\x99\x5c\x8f\x74\x7e\xa4\x18\xf7\xd6\x3a\xba\x22\x60\xb3\x4a\xc3\xc7\xdc\xee\xbb\x78\x43\x8c\xa4\xb1\xf9\x82\xb7\xdb\x97\x98\xec\x1a\x7f\x32\x62\x22\x64\xcb\x02\x4c\x0d\x9e\x60\xe9\x55\xa6\xe1\xd6\x77\xc9\x23\x51\x88\x51\x99\x0a\x45\x9b\x76\x7d\x0f\x13\xcd\x80\x34\x60\xf6\x18\x70\xdb\x33\x91\xb4\x46\x93",
+ "a00a601edeaca83041dc452d438a8de549594e25d843c2cf60a0e009fb92d87abe28a72690ab657c8d35b43cd02d22ec0755de229d1f922fa6ca18a6d6c2aaae"
+ }, {
+ 77,
+ "\x0f\xeb\x23\xc7\xe4\xa1\x9b\xcb\xd7\x0b\xd3\x00\xd7\x6e\xc9\x04\x5d\x69\x6f\x8c\x96\x87\xf4\x9e\xc4\x15\x44\x00\xe2\x31\xd2\xf0\x86\x24\x95\x15\x0c\xf2\x50\xb6\xf1\x2f\x17\x2a\x7d\x13\x0f\x8f\xa5\xd1\x75\xbf\x2f\x25\xe2\x80\x17\x2c\xcd\xfb\x32\x79\x51\x70\x11\x65\x30\x27\x28\xa6\x19\xaa\x2f\x24\x26\x31\xc9",
+ "eeb6dee30c119fb1e1eb5c15ff2b32d8b9c7464a4e4cc6815cd251a6bae29b49961dd5c2fa9c44a9b142ca062c7072cbf3db04299b767789040196bf0c06aa76"
+ }, {
+ 78,
+ "\xac\x59\xa1\x10\x62\x3f\x1a\x64\x66\x6f\x16\x0e\xd3\x29\x26\x67\x6c\xb5\xbe\x25\xdd\x9d\x96\x2f\x44\x19\x51\xb0\xef\xcb\x5d\x6a\x67\xac\x1a\x4e\xae\x47\x3e\x49\xc6\x25\x78\x60\x72\x88\x53\xff\x41\x5c\x5e\x8e\xc7\x6a\x8a\x46\x2e\xcf\xd3\x43\xee\xac\x22\xda\xd8\x20\x72\x2c\x59\x73\x32\xfb\xfd\x94\xeb\xbd\x32\xc6",
+ "f65ea942ae0a47e73b02b1442e5b26083db79307f64dd34a039c476faf18d5c514bb77a2c412a6074a7afc326ea66c74e5705fe2abbabf274333325a15b61fd9"
+ }, {
+ 79,
+ "\x9e\x3e\x10\x77\xe1\x33\x3a\x1f\xb1\xaa\x63\x3c\xcf\x2f\x74\x65\x88\xad\x42\x64\x89\xea\x08\xdf\xf5\x51\x14\x38\xb5\xf4\xc0\xb1\x10\xd1\xa4\xd4\x7b\x54\x0a\x12\xb2\x1e\xa2\xaa\x07\x05\x78\xcc\xfa\x5c\x22\xfe\x0b\x74\x3e\xc0\xcc\x62\x1c\x6b\x3a\x03\xb7\x5f\x4d\x3e\xea\x5d\xce\x89\xe0\x32\x69\xaf\xcd\x96\x03\xd0\xdb",
+ "4b5c5df80c344c12388c723856cd06965b2190af652480476747dc2195ea3716f87c1762359583a5f31522f83f7833bec30f1f47d14540417dd463f5d258cd4a"
+ }, {
+ 80,
+ "\xe8\x81\xe3\x28\x4c\x79\xd8\xf5\x23\x7e\x69\x9e\x4f\xbc\xa8\x40\x90\xc6\x64\xbb\x53\x22\x9f\x58\xcb\x08\x42\xb0\x43\x67\x10\xc9\xb3\x29\xd9\x81\x91\xb8\xf0\x30\xe9\xc1\xdf\x89\xb0\x38\x58\xc1\x56\x9c\x6f\xf4\x9a\x7c\x07\xc4\xa2\x3a\x8a\x43\x4b\x0f\xde\x13\xbe\x4f\x94\xcb\x44\xee\x62\x9d\x5b\x44\xd3\x36\x09\x0d\x3d\xe6",
+ "147d8071c7871ef9256cff32aa63ea031404fa5ee4ec09c56afdd5da919b0cc84a9d35d142c417715203316011cc620cd6855bb117063a5e52867facc680d5f4"
+ }, {
+ 81,
+ "\xe5\x85\x21\x09\x89\x11\x50\x3d\xe8\x43\x11\x38\x7d\x37\x5c\x25\x92\x9e\x6e\x55\x07\x6e\xb6\x93\x4f\xd8\xf2\xb1\xbb\x7b\x96\x67\xfb\xd7\x6d\x5e\xe2\x04\x82\x87\x69\xa3\x41\xb1\xf7\x16\xda\x5b\xdf\xec\xe6\xc6\x2a\x9f\x4d\x4f\x98\x82\x67\xfc\xe1\xf5\x61\x55\x40\xdb\xe3\x75\x32\x4e\xef\x60\x7c\x91\x0d\x97\x6b\x45\xa5\xea\x5f",
+ "f97ba056fa41f43b8e1987072a09e828c71c5ff6ad4e37f9ab6b89e2a078933dd23052fa72c6615b613904259e9ff9b55ef7b923b89bc8752f6babddd256e117"
+ }, {
+ 82,
+ "\x37\x96\xcf\x51\xb8\x72\x66\x52\xa4\x20\x47\x33\xb8\xfb\xb0\x47\xcf\x00\xfb\x91\xa9\x83\x7e\x22\xec\x22\xb1\xa2\x68\xf8\x8e\x2c\x9f\x13\x3e\x5f\x85\x27\xf1\xb1\x84\x83\x0e\x07\xc3\x45\x8c\x83\xa8\xca\x9f\x9d\x9c\x69\x98\x76\x0e\x61\x06\x68\xba\x0f\x22\xe2\x2b\x65\x6a\x73\x7e\x97\x8b\x24\x6a\x17\x84\x0b\x7d\xc4\x09\x1d\xa8\x5f",
+ "c8a466199acbcbc93f2ce042968508c046901631e3118a2d0bf39a9b42b4197a379b3a86cdeca9df2de1a3eb71b79ae9bf2d6575eadf1878029c4093133f54d3"
+ }, {
+ 83,
+ "\x9a\xf6\x08\xd0\x31\xcc\xf3\x09\xd7\x27\x3c\x60\x7a\x8e\x5e\x36\x84\x0d\x44\x9b\x55\xdb\x5b\x13\xf0\x3a\xeb\x9a\xf4\x9f\xa7\xe7\xcf\x13\x83\xee\x2e\xd9\xc5\xa8\xb7\x51\x5f\x16\xfb\x1c\x7c\x84\xa6\x81\x59\x0b\xf9\x0f\x56\x59\x7b\x84\x4d\xb5\xeb\xee\x22\x3d\x78\x10\x9b\x72\x35\x07\x72\xf7\xc7\x2e\xa9\x96\x60\x3e\x1e\x84\xf2\xba\x5f",
+ "f0ded9495b4f64cac585be8a737cfa14247a4a81cdf7f01ebcb134ace71f5a83df2cd72e7773fea1e82beae17e13857372792c8231e2ab9fbeb633e399d5f0ae"
+ }, {
+ 84,
+ "\xd0\xdf\x1b\xdf\x1d\xf6\x20\x32\x41\x72\x2f\xb9\xc9\xc1\xcf\x74\x05\x01\x74\x97\xae\x15\x45\x38\xcc\xf9\x22\x4a\xd7\x52\xe6\xce\x1d\x4a\xe9\x48\x63\x9a\xca\x70\xcf\xe8\x6b\x2b\x06\x54\x3c\xb9\x91\x4e\xbd\x30\x85\xaa\x3e\x29\x63\xf6\xe9\xb9\x3d\x0b\x03\xa3\x1a\xe2\x6f\xcb\x9c\xa9\x74\xee\xe0\x16\xc0\x91\xa6\xfc\xac\x37\xb2\x1c\xc1\xd7",
+ "c2da3ea3c8a3fd88a5bc5dea2bc076f861abedefae5a5fbd941ddfd1c41cc3312eb2dc826c2c0f65414fe72ebee447d2f9b1a6a56302660d1f86632ee80a175f"
+ }, {
+ 85,
+ "\x8c\xbc\x94\x80\x55\x3a\xce\xf7\xbc\xdb\xa9\x71\x6e\xa8\xd6\x6b\x41\x31\x78\x09\x17\xde\x2b\x0b\x04\x80\x45\xfc\xb3\x2b\x5c\xac\x05\x48\x08\xe1\xfc\xe6\xe9\x4a\xd8\x51\xec\xb4\x7f\xe6\xcb\x80\x22\x25\xd3\x55\x1e\x08\xea\x12\x20\x93\xd0\x07\x8d\xad\xa5\x64\x21\x2e\xac\xf1\xd6\x39\x4e\x00\x07\xcc\x62\xa1\xd5\x95\xab\x14\xca\x08\xa2\x84\xbc",
+ "63b39b88ceb848188b37316e04560e75a5340ab8d417932d231c997e892b41daa69d9fe3e9a14dd19ccfbbfa01488c208e7b946cfaf16ca2b1bf7c8d8da4e6b2"
+ }, {
+ 86,
+ "\x38\xf1\x84\x44\x8f\x3c\xf8\x2a\x54\xca\xfc\x55\x6a\xff\x33\x6f\x23\xf9\x14\x9e\x61\x21\x34\xb3\xfc\x00\xc8\xa5\x64\x55\x65\x3d\x88\x64\x0b\x12\xf6\x90\x62\xb8\x43\x2c\x43\x35\xad\x8f\x7a\xb4\xff\x66\xcb\x7e\xb5\x4f\x33\x25\x61\xa3\x6f\x02\x4d\x92\xc3\xe2\x62\x76\xf4\xfd\x48\x61\x96\x28\xcf\xf8\x8e\x4b\x8e\x85\xcf\x14\xca\x47\x67\xed\x99\x0d",
+ "9a49265fc641c59f1a91872cdae490d3da73c0c60fd59648e1d17dba1a647a5b95629392bb4ff5163d1a3cb45427c1437a3b2e1d9f030c0a8bcc5ed22da9e2ed"
+ }, {
+ 87,
+ "\x70\x90\x06\x18\xb1\xe9\xe9\xdb\x62\x29\x6f\xb6\xc6\x59\x0c\x9f\x10\xb0\xa6\x32\x76\x5c\x48\x9c\x88\x7f\x1a\xb7\xc0\x77\x91\x76\x5a\x62\xe3\x84\x65\xe1\xbe\x28\x1b\x1d\x39\x6c\x6e\x08\x0b\x7e\xe3\xe6\xfa\x56\xa3\x0b\x97\x99\xd0\xe6\x29\xbe\x15\x3e\xe7\x6f\x81\xbc\x6a\x32\x95\xaa\x61\x48\x9b\xfa\x87\xd5\x3a\x8a\xd2\x42\x48\xa6\xed\xe0\xdf\xcf\xe9",
+ "1c8c3357ff1f8d6ac4defb3af462a73e09159e3a20c6506edd8cd3052df941c81f68c5fbb893912619e28640977fe8eaae8e9d5d4e7d5f132552cefab4540bac"
+ }, {
+ 88,
+ "\x4e\x6d\xda\xe0\xd8\x05\xaf\xcd\x10\xa0\x55\xbc\xe5\x84\xc8\x48\xd0\x50\xfb\x29\xfe\x8f\x1c\x64\xb1\x8e\x1a\xbf\xe4\x6b\x65\x78\x2e\x6f\xf5\x36\xe8\x9d\x8d\x40\x92\x8b\x41\xed\x73\x71\x36\x5c\x80\x80\xa9\x64\x7f\x75\x32\xce\x6c\x6d\x4a\xc2\x1c\xfb\x0c\x80\x20\x78\x38\x51\xec\x9a\x7d\xbc\x39\x48\xf8\xfc\xa7\xad\xf8\xb2\xa7\x8c\x04\xd8\x98\xd3\x1f\xf6",
+ "5c2f996c779b91b3c4639311f54fabbdde7e2212b53dbae4828c8399588fc00d3b2ae60918aaaf6bb48bc757e52b2bcea84f5d15bf4ec25d5519fb54f6f26e1b"
+ }, {
+ 89,
+ "\x69\x68\x25\xf6\xd6\xea\x81\x73\xec\x47\xd0\x95\x9a\x40\x1c\x4d\xdf\x69\xf8\xf0\x8d\xdd\x67\x8a\x4d\x2f\xf9\x76\xe3\xa4\x37\x2b\xb3\x9f\x41\x59\x84\x5c\xb6\x35\x85\xe1\xd4\x10\x8d\x32\xe1\x2f\xa7\xc5\xc9\xd7\xce\x35\x08\xa7\xf5\x3a\xca\x2b\x4b\xd9\x51\xad\xbc\xd8\x98\x4e\xbb\x75\x36\x56\x3f\x58\x84\xc9\x0b\xc5\x02\x3b\x33\x16\xf7\xe4\xdc\x69\x58\xf7\x43",
+ "3ce940ca96b00011375daa95c65f66907d69b3eb3b8d779e6fc971afcc05e990bc4c541f434590f6b18b68c080d0f24475a3e764e9cb85343301314ee2fb661e"
+ }, {
+ 90,
+ "\x79\xec\xdf\xd4\x7a\x29\xa7\x42\x20\xa5\x28\x19\xce\x45\x89\x74\x7f\x2b\x30\xb3\x64\xd0\x85\x2c\xce\x52\xf9\x1e\x4f\x0f\x48\xe6\x1c\x72\xfa\x76\xb6\x0d\x30\x02\xca\xe8\x9d\xfc\x55\x19\xd3\x43\x0b\x95\xc0\x98\xfa\x46\x78\x51\x6b\x5e\x35\x51\x09\xea\x9b\x37\x45\xaa\x41\xd6\xf8\x20\x6e\xe6\x4a\xe7\x20\xf8\xd4\x46\x53\xb0\x01\x05\x7f\x2e\xba\x7f\x63\xcd\x42\xf9",
+ "ba3d0fe04470f4cf8f08c46d82ae3afd1caea8c13bebbe026b5c1777aa59860af2e3da7751844e0be24072af48bc8a6fd77678aaee04e08f63395f5c8a465763"
+ }, {
+ 91,
+ "\x92\x63\xfe\x75\xe8\xf6\xc7\xd5\xd6\x42\xe2\xca\x6a\x6e\xea\x4f\x44\xe9\xa0\xf2\x49\x51\x3e\xd7\x9c\x94\x09\xff\xca\x55\x26\xca\x44\x91\xae\xbb\x13\x82\x05\x7c\xc7\xc3\x67\x22\xb0\xb6\xc3\xb1\x51\x23\xcd\xe3\x12\x21\x4f\x25\x35\x3a\xbf\xe3\x0b\xca\x17\x05\x68\xa8\xe1\xba\x54\x08\x91\x74\x03\xa0\x18\x34\x08\x0a\xb6\x07\xc5\x6a\x10\xd0\x26\x50\x82\x49\x8f\xe0\xb6",
+ "7736d7a7fc1eb05857ce7d88abfffa87f58c670bfdfc0a8031f60f379e4b6ad94ac8f13ffe28c697809b5cfac7f13be01e7496a85237c4025539051fb2e32fb6"
+ }, {
+ 92,
+ "\x78\xc1\x7b\xfe\x0e\x02\xeb\x52\x6d\x1a\x44\xa1\xac\x12\x7b\xe0\x82\x18\x14\x52\xb6\x25\x39\x4b\xd6\xdc\x09\x3a\x2c\xb4\x32\xe6\xee\x59\xc2\xf8\xb5\x50\x3a\xba\x30\xda\xe4\x1e\x1a\x1c\x67\x02\x69\x7c\x99\xb2\xc9\x4e\x94\xaf\x48\xb0\x0c\xaf\x53\xb2\xe0\xe4\xe1\xbb\xee\x81\xee\x28\x2c\x7b\x2b\x35\xf5\x8c\xf4\x21\xa0\x7e\x82\x8d\x57\xa6\x62\x26\x26\xaf\x25\x83\x53\x99",
+ "b56b6e343166328523e0d1693e5174da643ae83cf69c85a7b3c3bee247b77b84702069d9e6b4cab03bf17fe612009bf4239683ca78ca7e876aca7d07603ba714"
+ }, {
+ 93,
+ "\x29\x8b\xb3\x04\xa9\x20\xf9\x60\x44\x7d\x8f\xd3\x8b\x06\x1b\xf8\xfe\x4a\xc1\xf8\x71\xd8\xa0\xfe\xb4\x54\x9f\xeb\x72\xca\x69\x4a\x5a\x41\xb6\x86\x7d\x94\xcd\x5a\xf7\x7d\x46\x8a\xd2\xf3\x15\xd1\x27\xb6\xc4\x1a\x86\x28\x00\xf3\x98\x5e\x57\x3e\x03\x77\x40\x29\x8e\x2c\x5c\x61\x86\xa9\xfb\x83\x60\x9b\xe2\xd4\x9f\x8b\x4c\x31\xf9\x6a\x2e\x49\xb5\x6d\xbf\x09\x57\x1b\x38\x58\x7f",
+ "34e3878627904ffbbbd85266cc973c34f931e3cab5d4c31f841c553dd69f84838206067df4f9f3b9102001be19267151e673f5c2d4c2f8438a6999a0a325487d"
+ }, {
+ 94,
+ "\xa3\xcf\x71\x4b\xf1\x12\x64\x7e\x72\x7e\x8c\xfd\x46\x49\x9a\xcd\x35\xa6\x40\xdd\x39\x3d\xdd\x26\x3c\xd8\x5c\xf6\x22\x5f\x59\x89\x0a\x06\x86\xda\xd1\xc5\x4e\xb8\xd8\x09\xb8\x1c\x08\xa9\x8d\xba\x13\x1b\xbd\xd6\xfc\xe8\xff\x59\xd9\x5d\xb8\x24\xd8\x83\x1e\xa4\x80\x52\x9d\xa7\x39\x22\x7a\x6e\x0f\x62\xb6\x03\xb3\x8c\x35\xcd\xc2\x58\x1f\x61\x4a\x31\x87\x9b\x8b\xe5\x4a\xee\xfa\xa0",
+ "6f230ae4903ddbef0ba384c2e3506eab318bfd1a46ea76099f65a3fd529c91bc2865b9fd943e346de64626b8529f9db1377bf2c5e0129c66b50c6a5cfb364b3a"
+ }, {
+ 95,
+ "\x0a\x42\x7a\xe5\x5e\xf3\xa7\xe6\x04\x4a\x08\xcf\x61\x28\xcb\xaa\xab\xfd\x77\x6c\x4e\x93\x74\x70\x8f\x2e\xce\x24\x6f\xd7\x36\x03\xd2\xf5\x4a\xc3\xe0\x1d\x16\xcf\xac\x2b\xda\xf7\x13\x92\x0d\x66\xe8\xf0\xa3\xd5\x4e\xe6\x8c\xff\x64\x26\x7d\x55\x28\xcd\xf2\xf2\x95\xf4\x74\xd1\x0f\x81\x17\x3e\x01\x43\x48\x8a\xc5\x3f\xc5\x03\xc4\x44\xed\x23\xde\xc6\x3a\x08\x0c\xe9\x0c\x24\x43\xdb\xa8",
+ "f6bbe5d0cf13ddf41c1436748a5d1ccae2948547b452c2171c7c8e8b66c6ae4de3c0e8b2962bcb60d3de3608479f80e455c9024d9716c38f6f1206861ab1eaac"
+ }, {
+ 96,
+ "\x2c\xbb\xb8\x75\x11\xf4\x94\x8e\xfe\xc3\xa6\x1b\x51\x1e\xde\xdb\x1d\xda\x8b\x6e\xcf\xc0\x21\x0c\x11\xe4\x3a\x77\xee\x32\xdc\x2e\x37\x4a\xfa\xe4\x26\x8e\x3d\x30\x42\x78\x04\x86\x82\x32\xa9\x66\xb5\x60\x06\xd3\x21\x40\x37\x07\x6b\xf6\xa2\x65\xb7\x21\x35\xaf\x0f\xb2\xef\x79\x09\xfe\xa2\xde\xa4\x12\xf7\x71\x74\x46\xb2\x76\xff\x15\x37\x53\x66\x2b\x4d\x41\x48\xc0\x23\x47\xe3\x25\x91\x69",
+ "76897b87a8a1cf835c434f6d391c9e5227351af9d3e20a3389c796b98b424281a59068d9c8d567ec2bebc435b0126b059e2d86394a9854d6611e1c922f385496"
+ }, {
+ 97,
+ "\x2b\x23\x32\x4c\x99\x92\xf6\x0a\x7f\xc0\x10\x15\x9a\x03\xcb\x9a\x2b\x29\x0d\xf4\xfa\x6a\x82\x35\x9b\x9a\xf6\x02\xf0\xa4\x03\xa5\xef\x33\xed\x5d\xa5\xb2\xca\xf8\x7b\x77\xe6\xa4\xb9\x3b\x65\x03\x48\xce\x2a\x7d\xbc\x08\xf8\xda\x92\x03\xd7\x10\xb5\x87\xba\x59\x47\xc6\x5e\x89\x9f\x4a\x75\x9f\x8e\x2b\x04\x9a\xe7\x85\x0a\x8e\x3e\x29\x62\xf6\xef\x93\xea\x4c\x63\x1d\xe5\xd7\x8e\x72\x9e\xc5\xbc",
+ "3beea0b373ed09cf1c919c51d86d642c9125e0ee81698dc4cbadf02e9e6925efb562fd9b87301a6377ca192be79c4118deabc450b54639000c2e312945451fb5"
+ }, {
+ 98,
+ "\x40\x22\xf9\x30\xc7\x03\x3b\x00\xd9\x86\xc6\x5f\xf6\xbb\xbd\xf9\xeb\xd0\xe5\x8c\x52\x84\x4f\xf6\x58\xdf\x38\x93\xc3\x20\x2d\xc5\x33\xf8\x73\xd4\xa7\xf5\xa5\xf9\x44\x41\x9f\xb5\x52\x8c\x9b\x67\x88\x47\x9a\x1e\x89\x13\x06\xac\xae\x79\x95\xfc\x06\xdb\x70\xa5\x9b\xaa\x95\xbe\xf7\xda\x79\xf5\xe7\x93\xf2\xdb\x7f\x2a\x55\x82\x5e\x4f\xdb\x4a\x34\x88\x4a\xf8\x81\xde\xd1\x08\x9f\xd5\x33\x45\x02\xa2",
+ "0358775bbb733ccc49e78f544aeee512370d480d0e13c7e8d5c444c423e592146b45fdb91a1b694d35e36b60e4bc8397fca8bb9790e619339778b9cd1abe3fe9"
+ }, {
+ 99,
+ "\x1c\xb7\x7b\xa4\x3c\xe7\x7e\x23\x6b\x9f\xc9\x25\xf5\x89\xb1\xc0\x70\x78\x0a\x84\xf9\x9e\x8f\x50\xc1\xff\x84\x6a\xc9\x25\x99\xcf\xe9\x16\x12\xc8\x17\x83\x25\xbe\xe6\x42\xa3\x4f\x4d\xff\xdb\xa2\xaa\x2e\xbc\xf7\x06\x43\x39\x82\x9b\x26\xf2\x79\x93\xe1\x10\x6c\x13\x9c\x70\xd5\x78\xcc\x05\xf0\xe1\xa7\x77\xcc\xed\xdb\x10\xa2\xc6\x7f\xd9\x67\x5e\x4a\x00\x9d\xf8\x03\x7d\x6e\xeb\x38\xf5\xfb\xa2\x33\xdf",
+ "6502f46551a3fab3a96428fb97801d7a4aa2f17fef6603238df84e17c74309ed3d9489c8b16a9384ee634a3f86d0b3ba9a4dbc9c51ec8bd4bf8d61de6d3d87d7"
+ }, {
+ 100,
+ "\x52\x16\x7d\xe2\xd6\xc5\x02\xd9\x9f\xa1\x0c\x27\xb2\xab\x62\x03\xbd\xeb\xc2\xca\xfb\xbf\xde\xf1\x58\x72\xa4\x3d\xd6\x10\xc2\x36\x2f\x79\x6a\xd9\xbc\xb5\x52\x8d\x95\x87\x00\x58\xfa\x45\x44\x53\xf1\xe6\x06\x5b\x31\x5d\x41\x0a\x3f\x26\x50\xe5\xd7\x1e\x69\xd7\x8d\x97\x67\xdf\xb4\xac\xcc\x05\x7f\xd2\x06\x92\x66\xb0\xf1\x80\xcb\x31\x9e\x30\xde\xd7\x53\x5b\xbe\x52\xd2\x4b\xe1\x51\xde\x4b\xb5\x98\xfc\x5c",
+ "25cb3ed3983a91b4cf37a65193916c5e3e211b63e943e2f7b50a85d349a463b941aad33eff16561bdfdc92fda06a4e1d94b162de48f06d3c626940b31020925f"
+ }, {
+ 101,
+ "\xce\xde\x66\x97\xd4\x22\xdd\xaa\x78\xe2\xd5\x5a\xe0\x80\xb8\xb9\xe9\x35\x6c\x69\xbc\x55\x82\x01\xa2\xd4\xb0\xb3\x19\x0a\x81\x2c\x27\xb3\x4b\xbc\xee\x3a\x62\xb7\x81\x37\x8b\x1b\xf6\x36\xb3\x72\xbc\xba\xe1\xfa\x2f\x81\x6a\x04\x6a\x0a\x64\x9a\x5c\x55\x5c\x64\x1f\xea\x4c\xcd\x84\x1c\xc7\x61\xf3\x8f\x77\x79\x72\xf8\xc9\x1b\x03\x24\xe7\x1c\x33\x3c\xe7\x87\xf0\x47\x41\x43\x9b\xf0\x87\xef\x5e\x89\x50\x11\xc0",
+ "0be42a25d77ac6ad995c6be48e783380bad25a61732f87cefb0cce1a769cd69081f494a1a12d657664ef2b4d9c41f2ee83f6e9a84327d8756af9f985595e7d3b"
+ }, {
+ 102,
+ "\x56\xd1\x8d\x3e\x2e\x49\x64\x40\xd0\xa5\xc9\xe1\xbc\xb4\x64\xfa\xf5\xbc\x70\xa8\xb5\x62\x12\x4f\x5f\xc9\xe9\xde\xb5\xfe\xe6\x54\x4b\x94\x5e\x83\x3b\x8b\x5d\x13\x1b\x77\x3e\xcb\x2c\xdd\x78\x0c\xd4\xe1\xbb\x9e\x4f\x1e\x3c\xb0\xa1\xd6\x4d\x19\xcf\x4b\x30\xe4\x4e\x6c\x2d\x0c\xbc\xb4\xe2\x84\xce\x50\xdb\x7a\x8a\x80\x62\xdd\xb6\x3f\x98\x1d\x90\x26\xc5\x32\xbf\x8e\xed\xdf\x8a\xf5\xa4\x38\x48\xa3\x22\x62\x17\x8c",
+ "982dc61c91a93770582eee8025aa55da8e9edb966bf5cf70d4a6534c0d53a2789a8c4fb65b7fed478cda02ed1e0d198d85c5c735b2417c5fab5d34e969fc8e7e"
+ }, {
+ 103,
+ "\x25\xa7\x32\x0d\xfa\xec\x5a\xf6\x5d\xa4\xd0\xf8\x68\x8e\x29\xe8\xe9\x55\x32\xec\xc1\x66\x79\xea\x8a\xff\x0f\x40\x7d\x89\x8d\xb6\x92\x28\x55\xb0\xe8\x90\x1a\xa9\x68\x1a\xa3\xdc\xa6\x17\xcb\x44\x07\x64\xcd\xc7\x29\x3f\xbe\xaf\x7f\x58\x5b\x59\x3c\x2b\x05\x31\x73\x8e\x0a\xde\x7c\x86\x26\xb9\x99\x5f\x4a\x84\xd9\xfc\x9b\x59\x3d\x6b\xbe\xe0\x1a\xbc\x53\xc5\xbe\x14\xbf\x69\x56\xfd\x2f\xd8\x10\x00\xda\xfc\x7c\x76\x86",
+ "749c928c3d5510925bfe98659025b0ed7c01acd4d59a9bf1c54863a088091771dc9d407bdbf83b0f44b0902e10349ba79c84d0981d5e8c4f5c733a117fed0790"
+ }, {
+ 104,
+ "\x3d\x71\x77\xb2\x8f\xfd\x91\x6e\x7e\x06\x34\x89\x58\x33\xba\x0b\xd9\xe0\x65\x3d\xf2\xcc\x42\x02\xc8\x11\x53\x6a\x00\x5a\xec\x85\x3a\x50\x5e\x75\xdb\x55\xd3\xc7\x10\x75\x79\x04\x10\x99\xe3\x82\xa1\xfe\xac\x80\xdd\xe6\x5d\x72\x36\x8e\x90\x9a\xb8\x5f\x56\xd8\x8e\x68\xd7\xc3\xc8\x0c\x38\xf8\x5b\xf8\xc2\xb3\x69\x59\x40\x9c\xc3\x4b\xa8\xe3\xad\x94\xfe\x8e\xe1\x92\x76\x12\xd6\x72\xd9\x21\x41\xa3\x29\xc4\xdd\x8a\x88\xa9",
+ "14a331508cd7d94fcce56a66bf65f20870a281c8442f8dbd4c2371454a2b66f8d0994a0b67692e771efc6a5e0b887acae7d6f4ec7338e1aa89f2abc7034c4e4c"
+ }, {
+ 105,
+ "\xc0\x33\xe4\xa5\x12\x29\x7c\xae\xcd\xbe\xad\x89\x2b\x11\xa9\xf7\x00\x7a\xf9\xa7\x4b\xca\xb8\x9e\x0b\xd4\xff\xdd\x54\x2c\xa0\x3e\xa1\x2e\x17\xa0\x6c\x42\xbd\x43\xfc\x5f\x3f\x75\x7f\xce\x4f\x6f\x58\x31\x99\x7a\xba\xc3\xf9\x56\x76\xe1\xeb\xdb\x11\xca\x43\xe1\x1a\xa3\x1e\x5e\xba\xbe\x18\xce\x8d\x1b\xbf\xd8\xb0\x2f\x48\x2e\x1c\xe5\x81\xb5\x32\xe3\x07\xe6\x96\x0e\xb9\x74\x41\x50\x6c\x2e\xd2\x99\xe1\x28\x25\x23\xf4\x15\x27",
+ "95ac9b7d22aa458921874c4b4331e7d64761853217c3f83c601abcbccd7e2eaa6ca6ce9a22ebcfe5046d52f8a09097f043ab8bc59243fd770090bb432c3155e9"
+ }, {
+ 106,
+ "\x69\xff\xf0\xf1\xa3\xdb\xfb\x36\xe3\x2f\x02\x58\x19\xfa\x99\xea\x9a\x0e\xda\xef\x73\x14\x5b\xf7\xfc\xd0\x5d\x8b\xb0\xa6\x46\xcb\x3b\x5d\x52\x56\xd5\x24\x85\x6a\xcf\xd2\xe4\x4d\x6b\x72\xe4\xeb\xf1\xff\x23\xc0\xff\x6c\x56\xf8\x21\xe7\x82\xd5\xa1\x5f\x70\x52\xa1\x44\x5b\x06\x66\x8e\xeb\x4a\xf7\x00\x67\x9e\xe7\xae\x26\x49\x6f\xbd\x46\x40\xc0\x6a\xa1\x49\x96\x4d\xfd\x60\x11\xdf\x83\x5a\xc1\x3b\x73\xc8\xff\x21\x15\x1e\x84\x40",
+ "45d4daa652558d1c12beb0f5662c712f325b4c802fc6eb9ee039c949d002bb786f1a732712be941f9c5c79b3e5c43064d63a38578e5a54ee526acb735b9ad45f"
+ }, {
+ 107,
+ "\xb2\xc4\x39\xc9\x7a\xb7\xc6\x37\x36\xb3\x79\x63\x24\xd6\x8e\xeb\x7a\x47\x1e\xd1\x42\xbd\x96\x22\x68\x41\x67\xd6\x12\x34\xff\xf8\x2f\x93\xf9\x07\x53\x7a\x90\x9b\xc2\xe7\x5a\x4b\xcb\xc1\x33\xcf\x57\x19\x76\x62\xc1\xaf\x74\x6a\xe8\xb8\x1e\x5b\x83\xde\x05\xd9\xb5\x89\x85\x1d\xe2\x5d\x3c\x99\xc0\x04\xc1\xdf\xb1\x2d\x93\xbf\x50\xd4\x50\xaf\x49\xc4\x28\x71\x6f\x5b\x90\xef\x08\x8e\x3b\x6a\x6b\x2c\x46\xd3\xce\x67\xb3\x79\x59\x90\x18",
+ "c48ec83be5fa669e6ec8db90aca9676cfe2ec0d5e8e7a2431687bb953c0a300be3db4075cca3bac4dfa4d971baf0fa1aff46639db4b238856ff36d1dfcd520f1"
+ }, {
+ 108,
+ "\xc0\x16\xf5\x22\xf2\x6b\x74\x70\xe9\x22\xb9\xa2\x87\xe6\xd4\x5f\x6c\x28\x81\x3b\x68\xc1\x45\x7e\x36\xd9\xba\x26\x67\x08\x27\x2f\x9c\xbc\x54\x11\xf8\xdb\x9d\x8b\xd5\xa9\x44\x9f\xb6\xeb\x0c\xde\x7d\x4d\x03\xe5\xdf\x01\x9f\x28\x14\xa9\x0c\xee\xd3\x77\xc5\x9d\x7d\x92\x62\x38\x99\xbc\xb0\x26\x80\x33\x07\x35\x59\xd4\xd8\xde\x48\x86\x86\xcb\xe3\xd6\x77\x96\xe6\xdf\x6a\xd4\x27\x6d\x0b\x52\xcc\x62\xc4\x9e\xbb\x58\xd7\xc9\x52\x87\xaa\x6c",
+ "7402f1a99b47e102b3b73140c6771b07ee6c33b3715e9c4027c441bee40511b735d95e508baea78da26fded9b7038e9a53defa58448aba40dc1e62d7ec592107"
+ }, {
+ 109,
+ "\xa7\x66\xb2\xa7\xef\x91\x67\x21\xf4\x67\x7b\x67\xdb\xc6\x5e\xf9\xb4\xd1\xbd\xa1\xad\x4e\x53\xfc\x85\x4b\x02\x36\x44\x08\x22\x15\x2a\x11\x19\x39\xe5\xab\x2b\xa2\x07\x71\x94\x72\xb6\x3f\xd4\xf4\xa5\x4f\x4b\xde\x44\xa2\x05\xd3\x34\xa2\xd7\x2c\xfe\x05\xab\xf8\x04\xf4\x18\x41\xb8\x6d\x36\x92\x0b\xe6\xb0\xb5\x29\x33\x1a\xc1\x63\xa9\x85\x55\x6c\x84\x51\x1e\xc9\x86\x43\x9f\x83\xe1\xd7\x31\x1f\x57\xd8\x48\xcf\xa0\x2d\xf9\xea\x0c\xf6\xb9\x9a",
+ "ddd60f93a3babc78299cf763e7919d45ac6f479700e1adb05ab137acdf89c1521ecb9dfeacd091e58ca57a1db964a9c3cd1fa39192cc1e9f734caa1c5fa62975"
+ }, {
+ 110,
+ "\x10\xf2\xbe\x77\xa4\x05\x57\x71\xa6\x70\x07\xcd\x86\x30\xe3\x23\x0e\x38\x28\x84\x99\xcb\x16\x03\x80\x29\x01\x74\xd6\x6d\xa5\x74\x55\xb6\xba\xaa\x97\x85\xc8\x4c\x8a\x66\x3d\xe4\x1e\xd3\xbd\x54\x40\x55\xb9\x17\x0c\xec\x43\xcb\x3e\xb1\x20\xec\xea\xba\x1f\xe3\x6e\x3e\xaa\x3f\xa4\xf9\x9b\x42\x5c\xd2\x51\x9f\x09\xbc\x02\x82\xba\xda\x52\xd1\x4c\xe6\x25\xb1\xde\xd3\xb2\x4d\x86\xb1\xda\xd3\x42\xd2\xb7\xbe\x32\x2b\x77\x5b\x04\xfc\x6b\x86\xaf\xb4",
+ "a872fa33d463b3343cec57c20c66979c33e1ad067bfc703454696aab5dd0003bc194318f4a8ebbc74503feb7211a472dadee991efe3e38f21a1310f8a76eac80"
+ }, {
+ 111,
+ "\x32\x45\x33\xe6\x85\xf1\x85\x2e\x35\x8e\xea\x8e\xa8\xb8\x1c\x28\x8b\x3f\x3b\xeb\x1f\x2b\xc2\xb8\xd3\xfd\xba\xc3\x18\x38\x2e\x3d\x71\x20\xde\x30\xc9\xc2\x37\xaa\x0a\x34\x83\x1d\xeb\x1e\x5e\x06\x0a\x79\x69\xcd\x3a\x97\x42\xec\x1e\x64\xb3\x54\xf7\xeb\x29\x0c\xba\x1c\x68\x1c\x66\xcc\x7e\xa9\x94\xfd\xf5\x61\x4f\x60\x4d\x1a\x27\x18\xaa\xb5\x81\xc1\xc9\x49\x31\xb1\x38\x7e\x4b\x7d\xc7\x36\x35\xbf\x3a\x73\x01\x17\x40\x75\xfa\x70\xa9\x22\x7d\x85\xd3",
+ "3b26c5170729d0814153becb95f1b65cd42f9a6d0649d914e4f69d938b5e9dc041cd0f5c8da0b484d7c7bc7b1bdefb08fe8b1bfedc81109345bc9e9a399feedf"
+ }, {
+ 112,
+ "\x51\x89\x85\x97\x7e\xe2\x1d\x2b\xf6\x22\xa2\x05\x67\x12\x4f\xcb\xf1\x1c\x72\xdf\x80\x53\x65\x83\x5a\xb3\xc0\x41\xf4\xa9\xcd\x8a\x0a\xd6\x3c\x9d\xee\x10\x18\xaa\x21\xa9\xfa\x37\x20\xf4\x7d\xc4\x80\x06\xf1\xaa\x3d\xba\x54\x49\x50\xf8\x7e\x62\x7f\x36\x9b\xc2\x79\x3e\xde\x21\x22\x32\x74\x49\x2c\xce\xb7\x7b\xe7\xee\xa5\x0e\x5a\x50\x90\x59\x92\x9a\x16\xd3\x3a\x9f\x54\x79\x6c\xde\x57\x70\xc7\x4b\xd3\xec\xc2\x53\x18\x50\x3f\x1a\x41\x97\x64\x07\xaf\xf2",
+ "c00926a374cde55b8fbd77f50da1363da19744d3f464e07ce31794c5a61b6f9c85689fa1cfe136553527fd876be91673c2cac2dd157b2defea360851b6d92cf4"
+ }, {
+ 113,
+ "\x91\x59\x76\x72\x75\xba\x6f\x79\xcb\xb3\xd5\x8c\x01\x08\x33\x9d\x8c\x6a\x41\x13\x89\x91\xab\x7a\xa5\x8b\x14\x79\x3b\x54\x5b\x04\xbd\xa6\x1d\xd2\x55\x12\x7b\x12\xcc\x50\x1d\x5a\xaa\xd4\x76\xe0\x9f\xa1\x4a\xec\x21\x62\x6e\x8d\x57\xb7\xd0\x8c\x36\xcd\xb7\x9e\xea\x31\x4b\xdd\x77\xe6\x57\x79\xa0\xb5\x4e\xab\x08\xc4\x8c\xeb\x97\x6a\xdf\x63\x1f\x42\x46\xa3\x3f\x7e\xf8\x96\x88\x7e\xa8\xb5\xdf\xa2\x08\x7a\x22\x5c\x8c\x18\x0f\x89\x70\x69\x61\x01\xfc\x28\x3b",
+ "3cd3380a90868de17dee4bd4d7f90d7512696f0a92b2d089240d61a9d20cd3af094c78bf466c2d404dd2f662ec5f4a299be2adeadf627b98e50e1c072b769d62"
+ }, {
+ 114,
+ "\xfe\x2d\x8a\xe2\x00\xe6\x65\x7f\xdc\x74\x94\xaf\x5a\x12\xb2\xae\x94\x03\x48\xf1\xf9\x83\xf0\xba\x98\xfe\xbb\xe9\x9c\x80\xd1\x15\x12\x6d\x57\xdb\xf3\x72\x96\x76\x5e\xbb\x59\x90\x25\x66\x96\x58\x8b\x38\x51\xd5\x4c\x8f\xbe\x7a\xde\x98\xa6\xfa\xf7\xc2\x0b\x5e\x4f\x73\x0f\x54\xa7\xf9\x12\xca\x0a\xc3\x1b\xbb\x53\xd1\x79\x49\xef\x69\xaa\x0d\xe4\x0c\x7b\xab\x12\xa8\x71\xa9\xb9\x0f\x68\x81\x3c\xa8\x7a\xf4\x25\x64\x22\xa2\x68\xf4\xa1\xd8\xec\x3a\xa1\xa9\x47\xfd",
+ "8025a8608df0f6a01c34cdec012d4cb25852e1b100b68172fc4e86ac8b7126b64859cb9e767a7e59060989cedbd925afc475ca7369bd43f85ae590e224e036dd"
+ }, {
+ 115,
+ "\xdc\x28\x48\x4e\xbf\xd2\x93\xd6\x2a\xc7\x59\xd5\x75\x4b\xdf\x50\x24\x23\xe4\xd4\x19\xfa\x79\x02\x08\x05\x13\x4b\x2c\xe3\xdf\xf7\x38\xc7\x55\x6c\x91\xd8\x10\xad\xba\xd8\xdd\x21\x0f\x04\x12\x96\xb7\x3c\x21\x85\xd4\x64\x6c\x97\xfc\x0a\x5b\x69\xed\x49\xac\x8c\x7c\xed\x0b\xd1\xcf\xd7\xe3\xc3\xcc\xa4\x73\x74\xd1\x89\x24\x7d\xa6\x81\x1a\x40\xb0\xab\x09\x70\x67\xed\x4a\xd4\x0a\xde\x2e\x47\x91\xe3\x92\x04\xe3\x98\xb3\x20\x49\x71\x44\x58\x22\xa1\xbe\x0d\xd9\x3a\xf8",
+ "615115d2e8b62e345adaa4bdb95395a3b4fe27d71c4a111b86c1841463c5f03d6b20d164a39948ab08ae060720d05c10f6022e5c8caf2fa3bca2e04d9c539ded"
+ }, {
+ 116,
+ "\x5a\xf8\xc0\xf2\x6d\xb4\xe9\x9b\x47\xec\x2e\x4a\x01\xa7\x86\xe7\x78\x99\xe4\x6d\x46\x4a\xc3\x37\xf1\x75\x02\x7b\x61\xae\xf3\x14\x98\x48\xaf\x84\x9d\x76\xac\x39\xb9\xb0\x91\x0f\xe6\x59\x48\x17\x85\x9e\x55\x97\x4f\xa1\x67\x51\x8e\xd7\x2d\x08\x8d\xae\x6b\x41\x4d\x74\x4d\x47\x79\x74\xfb\x71\x9c\x62\x6d\xa7\x92\xf9\x81\x23\x3d\xe2\x4b\x75\x79\xd8\xac\xca\x51\x0a\x26\x6d\x73\xc0\xee\x8e\xe1\x42\x43\x43\xea\xf6\xff\xcc\x59\xc8\x6c\x1b\xec\xce\x58\x94\x07\x2c\x6c\x11",
+ "09da284d5b6556508be54c8ab6c97bbd472995c6bbd585917ecdb54ea9167208daaa070a7b2b7d8e93ce1315f0d1ef8d69667429c44dc5ee1499de57b229a398"
+ }, {
+ 117,
+ "\x49\xcd\x0b\xa0\xdf\x5b\xb3\xf4\x3f\x68\x46\x4e\x3e\x83\xe9\xcb\xd5\xd5\xee\x07\x7f\xfa\x55\x91\xe3\x0f\x93\x9c\xb3\x0c\x93\xf7\xd4\x54\xfb\x3f\xbf\x8b\xb0\x53\x27\xa8\x9c\x08\xdc\x4b\xaf\x1e\xef\x50\x23\x73\x17\xa4\x05\x77\x53\x57\xf1\xe0\xd1\xf3\x1d\x9f\x0f\x0d\x98\x12\x40\x19\xd4\x7b\xf1\x83\x63\xb1\xec\xfb\xfe\x15\x5c\x10\xcb\xc8\x33\x00\xe0\x1b\xc9\xce\x03\x47\xc5\x96\xb3\x5f\x41\x1e\x6d\x82\x29\xad\x28\x55\xe4\x20\x22\xb0\x37\x3a\xde\x98\x66\x3c\x6d\x6e\x9c",
+ "30cbf0679a97c871574d2fc05d7aa760c6bc8a864b7d246c39b9e812f9b7ff7b4ef5197dd5b69493306688b8564de1ad47d75505c913ba6a78788f8caf5788bd"
+ }, {
+ 118,
+ "\xa8\xa3\x7d\xfc\x08\x3a\xd2\xf4\x7f\xff\x46\x87\x38\xbf\x8b\x72\x8e\xb7\xf1\x90\x7e\x42\x7f\xa1\x5c\xb4\x42\x4b\xc6\x85\xe5\x5e\xd7\xb2\x82\x5c\x9c\x60\xb8\x39\xcc\xc2\xfe\x5f\xb3\x3e\x36\xf5\x70\xcb\x86\x61\x60\x9e\x63\x0b\xda\x05\xee\x64\x1d\x93\x84\x28\x86\x7d\x90\xe0\x07\x44\xa4\xaa\xd4\x94\xc9\x3c\x5f\x6d\x13\x27\x87\x80\x78\x59\x0c\xdc\xe1\xe6\x47\xc9\x82\x08\x18\xf4\x67\x64\x1f\xcd\x50\x8e\x2f\x2e\xbf\xd0\xff\x3d\x4f\x27\x23\x93\x47\x8f\x3b\x9e\x6f\x80\x6b\x43",
+ "8e1c91729be8eb40226f6c58a029380ef7edb9dc166a5c3cdbcefe90bd30d85cb7c4b248e66abf0a3a4c842281299bef6db88858d9e5ab5244f70b7969e1c072"
+ }, {
+ 119,
+ "\x36\xaf\x17\x59\x54\x94\xef\x79\x3c\x42\xf4\x84\x10\x24\x6d\xf0\x7d\x05\x93\x6a\x91\x8a\xfe\x74\xcd\x00\x5e\x53\x7c\x58\x6b\x28\x43\x70\x1f\x5d\xf8\x95\x22\x42\xb7\x45\x86\xf8\x33\x39\xb4\x8f\x4b\xa3\xa6\x6b\xde\xb4\x57\xec\xdf\x61\x78\x4e\xac\x67\x65\xcd\x9b\x8c\x57\x0d\xd6\x28\xdb\xba\x6a\xe5\x83\x6b\x9a\xc3\xdb\xcd\x79\x5f\x9e\xfd\xb8\x74\x2a\x35\xbc\xa2\x32\xab\xf3\x6e\xb3\xb6\x69\x8b\x29\x33\x96\x58\x02\x27\x7b\xa9\x53\xa6\xed\xca\xca\xf3\x30\xc1\xe4\xe8\xc7\xd4\x5f",
+ "158bfc348a30b4fabbe355a7d44bdc2122a4c850444c03f289003ce01bfc1ebf3ecc0febb6a8ff523d25db7681b05bdce048d11943ab476c1967cf6556c4a120"
+ }, {
+ 120,
+ "\x42\xd6\x6e\xdc\x5f\x22\xe0\xc1\x3c\x25\x50\x4c\x51\x01\xa5\xd1\x72\xd2\xdb\x72\x09\xe4\x61\xef\xa3\x23\xc0\xbf\xae\xd2\x7e\x5f\x80\x80\x42\xea\x9c\x38\x38\xea\x31\xf9\xb7\x6d\xe4\x65\x22\x5c\xcf\xbd\x0c\x09\xca\x0d\x9f\x07\xe9\xa4\x3e\x3e\x46\xc7\x69\x3e\x00\xa7\xe1\xd4\x83\x90\x0d\xdb\x0a\x62\x9d\x55\x63\x45\x6d\xbb\xf2\x99\xac\x91\xf9\x2c\x3d\x3c\x17\xb0\x5d\x18\x0e\x6c\x87\xc6\xc9\x31\x94\xc3\x9d\x90\x27\x3f\xcf\x4a\x48\x2c\x56\x08\x4f\x95\xe3\x4c\x04\x31\x1f\xa8\x04\x38",
+ "061afb119a3c60876e04c10f12ad0f4b977593dc5a2d21096a57e7d3f7d4d44fdef934b2c17d7530674e4f4a1c176dbdcc54811a22e1b8712e4192fc2d4bf8e8"
+ }, {
+ 121,
+ "\xf9\x1b\xb2\xe1\xa9\xc4\xcd\x96\xbf\x25\x04\x26\xb3\xa6\xaf\xd9\xb8\x7a\xc5\x1e\x93\x25\x4d\x2d\xae\x3b\x16\xec\x68\x6b\xa8\x0f\xb0\xbd\x7a\x84\xd2\x18\x66\x0e\x90\x07\x59\x30\x75\xbc\x4f\x4c\x66\x56\x7f\x0c\x7a\x5f\xd2\x01\x0c\x99\x9a\x8a\x0e\xfa\x81\xf8\x9f\xf5\xbf\xef\xe0\xfb\x91\x0f\x04\x42\xe6\xd4\xa7\xc5\x5b\xbb\x61\x8c\x69\xa7\x9a\x2d\xdd\x82\xa0\x93\x89\x27\xf6\xfe\x3a\x80\xf0\x4b\xea\xeb\x7c\x76\x36\xe3\x43\x5d\x12\xdc\xf1\xc6\xbb\x6e\xd0\xa4\xed\xb6\x9c\x96\x57\xfa\x93",
+ "6e692c8c694ee0a3565f37a299e0006b85ab4a821b20e76798220229f656efc6a20211a4e7e4ed77facde0d70e4d5d95bc8ed1d7a56d8df1446d562f044b344c"
+ }, {
+ 122,
+ "\xd1\xeb\x96\x1c\xa6\xa8\xf6\x7c\x49\xb6\x1e\x4d\x3c\xea\xa2\xa1\xde\x6f\x0e\xa9\x27\xb1\x32\xbf\x98\x7a\xbd\xaa\x72\x5b\x0e\x1e\x27\x4e\x46\x83\x0e\x99\xa2\xf7\x5a\xf6\x08\x96\x4d\xf0\xdf\xf9\xa9\x90\x24\xfc\x68\x39\xba\xc5\xac\xd1\x02\x02\xf9\x21\xac\x71\xa2\x7f\xcd\xa6\x81\xaa\x31\x09\xeb\xf5\xf2\x1e\xe3\xa8\x49\x09\x8e\xa3\xa5\x51\xe8\x44\xfa\xe4\xb4\x8b\x5c\x5b\xb9\x7c\xcc\x80\x2b\xc5\x52\x0d\x68\xa1\x4c\xb7\xe5\xfc\x05\x6b\x67\xd8\x89\xd8\x76\xef\xb8\x2d\x0e\x9a\x9a\x24\x99\xf1",
+ "39b2c76ec207120de4b320c7fe069e602c9c38f257596da7369395e87eb64b3acff988c1839ac269d5012c093f9edd4b7cabf13bdea7d42e969ab108269c6ab0"
+ }, {
+ 123,
+ "\xad\xf2\x26\x32\x00\xf3\x76\x88\x6b\xa7\xb6\xf5\xe4\x41\x1d\x5f\x07\xf7\xd9\xd1\x01\x59\x0c\x73\xac\xe1\x14\xba\xfb\xcb\x0f\xdc\x99\x26\x9e\x87\xcd\x2c\xea\xd2\xa1\xcf\xe5\x74\x43\x94\xd3\x33\xab\xa4\x08\xa0\x7e\x21\xf3\x02\x33\xb6\x5b\x90\x74\x72\xe9\xe3\xc7\xd6\xe7\xaa\x6d\x2c\x47\xa0\x8a\x1b\xe7\xbb\x87\x79\x13\xa6\xb5\x60\x4c\x72\x33\x84\x47\x89\x11\xc3\x39\xe3\xb5\xfe\x52\x7c\x7e\x28\x87\x05\xa8\x9c\x95\xd9\x70\xb4\x43\x34\x78\x97\xe7\x9f\x6c\x52\x2b\xaf\xe6\x2b\x11\xef\x8f\x31\x35",
+ "3c23d2d8cf4db6ac6a42e27208180f37668bef5ee0a3f879483c8e604e7f42583f202037b8d242c04a87345b8be6dc8b121d6484b9edad0d73c894c1288f5cae"
+ }, {
+ 124,
+ "\x18\xe7\x5b\x47\xd8\x98\xac\x62\x9c\x48\xe8\x0d\xbf\xb7\x5d\xae\x1e\x17\x00\xb7\x71\x16\x5e\xcc\xdb\x18\xd6\x28\xbf\xc4\x06\x3d\xd6\xc3\x83\x9a\x7e\xc4\xcd\x12\x55\xc4\x82\x1b\x07\x8c\xd1\x74\x64\x7b\x32\x0b\xb6\x85\x54\x1d\x51\x7c\x57\x9f\x6b\x8e\x3c\xdd\x2e\x10\x9a\x61\x0c\x7a\x92\x16\x53\xb2\x04\xad\x01\x8d\x03\x40\xd9\x93\x87\x35\xb6\x02\x62\x66\x20\x16\x76\x7e\x1d\x88\x24\xa6\x49\x54\x08\x62\x29\xc0\xe3\xb5\xbd\x9a\xd8\x8c\x54\xc1\xdc\x5a\xa4\xe7\x68\xff\x1a\x94\x70\xee\x6f\x6e\x99\x8f",
+ "01c756b7c20b5f95fd2b079ab6a50f28b946fb16266b07c6060945dc4fe9e0d279c5b1505b9ec7d8f8f3c9ebf0c5ee9365aec08cf278d65b64daeccc19d3cbf4"
+ }, {
+ 125,
+ "\xc2\x96\x33\x42\xcf\xaa\x88\xcc\xd1\x02\xa2\x58\xe6\xd6\x29\xf6\xb0\xd3\x67\xdd\x55\x11\x65\x02\xca\x44\x51\xea\x52\x36\x23\xbc\x41\x75\x81\x9a\x06\x48\xdf\x31\x68\xe8\xea\x8f\x10\xed\x27\x35\x48\x07\xd7\x6e\x02\xee\x1f\xdf\x1c\x9c\x65\x5e\xe2\xb9\xfd\x08\xd5\x57\x05\x8d\xab\xdf\x8d\xcf\x96\x4b\xfc\xac\xc9\x96\xae\x17\x39\x71\xe2\x6e\xa0\x38\xd4\x07\xc8\x24\x26\x0d\x06\xc2\x84\x8a\x04\xa4\x88\xc4\xc4\x56\xdb\xcd\xe2\x93\x9e\x56\x1a\xb9\x08\xc4\x09\x7b\x50\x86\x38\xd6\xcd\xa5\x56\x46\x5c\x9c\xc5",
+ "a4d2f59393a5fea612c3c745f4bb9f41aaf3a3ce1679aa8afc1a62baa4ed452819418c8ae1a1e658757976692390fc43d4decf7d855cd8b498b6dc60cae05a90"
+ }, {
+ 126,
+ "\x85\x36\x0c\x3d\x42\x57\xd9\x87\x8e\x2f\x5c\x16\xd3\xcd\x7d\x07\x47\xdf\x3d\x23\x1e\x1a\x8f\x63\xfd\xdc\x69\xb3\xb1\x10\x1a\xf7\x21\x53\xde\x4c\x81\x54\xb0\x90\xc9\x81\x5f\x24\x66\xe0\xe4\xf0\x2f\x3a\xf3\xa8\x9a\x7f\xd0\x4e\x30\x66\x64\xf9\x3e\x54\x90\xd4\xce\x7f\xc1\x69\xd5\x53\xc5\x20\xae\x15\xdd\x02\xc7\xc6\x13\xc3\x9b\x4a\xcd\x00\xe0\xc9\xa3\xc5\x01\x56\x6e\x52\xce\xce\xa1\x1f\x73\x03\xdd\x1d\xa6\x1a\xbf\x3f\x25\x32\xfd\x39\x60\x47\xb1\x88\x72\x55\xf4\xb2\x56\xc0\xaf\xcf\x58\xf3\xae\x48\xc9\x47",
+ "e8352ddcac59e377ea0f9c32bbb43dfd1b6c829fad1954240c41b7c45b0b09db11064b64e2442a96f6530aac2c4abf3beb1eae77f2bce4efe88fee1a70cf5423"
+ }, {
+ 127,
+ "\xc1\x3e\x6c\xa3\xab\xb8\x93\xaa\x5f\x82\xc4\xa8\xef\x75\x44\x60\x62\x8a\xf6\xb7\x5a\xf0\x21\x68\xf4\x5b\x72\xf8\xf0\x9e\x45\xed\x12\x7c\x20\x3b\xc7\xbb\x80\xff\x0c\x7b\xd9\x6f\x8c\xc6\xd8\x11\x08\x68\xeb\x2c\xfc\x01\x03\x7d\x80\x58\x99\x2a\x6c\xf2\xef\xfc\xbf\xe4\x98\xc8\x42\xe5\x3a\x2e\x68\xa7\x93\x86\x79\x68\xba\x18\xef\xc4\xa7\x8b\x21\xcd\xf6\xa1\x1e\x5d\xe8\x21\xdc\xab\xab\x14\x92\x1d\xdb\x33\x62\x5d\x48\xa1\x3b\xaf\xfa\xd6\xfe\x82\x72\xdb\xdf\x44\x33\xbd\x0f\x7b\x81\x3c\x98\x12\x69\xc3\x88\xf0\x01",
+ "6e56f77f6883d0bd4face8b8d557f144661989f66d51b1fe4b8fc7124d66d9d20218616fea1bcf86c08d63bf8f2f21845a3e519083b937e70aa7c358310b5a7c"
+ }, {
+ 128,
+ "\xfd\x22\x03\xe4\x67\x57\x4e\x83\x4a\xb0\x7c\x90\x97\xae\x16\x45\x32\xf2\x4b\xe1\xeb\x5d\x88\xf1\xaf\x77\x48\xce\xff\x0d\x2c\x67\xa2\x1f\x4e\x40\x97\xf9\xd3\xbb\x4e\x9f\xbf\x97\x18\x6e\x0d\xb6\xdb\x01\x00\x23\x0a\x52\xb4\x53\xd4\x21\xf8\xab\x9c\x9a\x60\x43\xaa\x32\x95\xea\x20\xd2\xf0\x6a\x2f\x37\x47\x0d\x8a\x99\x07\x5f\x1b\x8a\x83\x36\xf6\x22\x8c\xf0\x8b\x59\x42\xfc\x1f\xb4\x29\x9c\x7d\x24\x80\xe8\xe8\x2b\xce\x17\x55\x40\xbd\xfa\xd7\x75\x2b\xc9\x5b\x57\x7f\x22\x95\x15\x39\x4f\x3a\xe5\xce\xc8\x70\xa4\xb2\xf8",
+ "a21b1077d52b27ac545af63b32746c6e3c51cb0cb9f281eb9f3580a6d4996d5c9917d2a6e484627a9d5a06fa1b25327a9d710e027387fc3e07d7c4d14c6086cc"
+ }, {
+ 0,
+ NULL,
+ NULL
+ }
+};
+
+static void
+run_tests(unsigned int digest_type, struct test_vector *test_vectors)
+{
+ struct sudo_digest *ctx;
+ unsigned char md[64]; /* SHA512_DIGEST_LENGTH */
+ char mdhex[128 + 1]; /* SHA512_DIGEST_LENGTH * 2 + 1 */
+ size_t i, j, digest_len;
+
+ digest_len = sudo_digest_getlen(digest_type);
+ if (digest_len == 0)
+ sudo_fatalx("unable to get digest length for type %d", digest_type);
+ if (digest_len > ssizeof(md))
+ sudo_fatalx("digest length too big for type %d", digest_type);
+
+ ctx = sudo_digest_alloc(digest_type);
+ if (ctx == NULL)
+ sudo_fatal(NULL);
+
+ for (i = 0; test_vectors[i].str != NULL; i++) {
+ ntests++;
+ sudo_digest_update(ctx, test_vectors[i].str, test_vectors[i].len);
+ sudo_digest_final(ctx, md);
+
+ /* Convert md to a hex string. */
+ for (j = 0; j < digest_len; j++) {
+ mdhex[j * 2] = hex[md[j] >> 4];
+ mdhex[(j * 2) + 1] = hex[md[j] & 0x0f];
+ }
+ mdhex[j * 2] = '\0';
+
+ if (strcmp(test_vectors[i].md, mdhex) != 0) {
+ sudo_warnx("test %u:%zu: expected %s, got %s", digest_type, i,
+ mdhex, test_vectors[i].md);
+ errors++;
+ }
+ sudo_digest_reset(ctx);
+ }
+ sudo_digest_free(ctx);
+
+ return;
+}
+
+/*
+ * Verify SHA2 functions using NIST byte-oriented short message test vectors.
+ */
+int
+main(int argc, char *argv[])
+{
+ int ch;
+
+ initprogname(argc > 0 ? argv[0] : "digest_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+
+ run_tests(SUDO_DIGEST_SHA224, sha224_vectors);
+ run_tests(SUDO_DIGEST_SHA256, sha256_vectors);
+ run_tests(SUDO_DIGEST_SHA512, sha512_vectors);
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
diff --git a/lib/util/regress/fnmatch/fnm_test.c b/lib/util/regress/fnmatch/fnm_test.c
new file mode 100644
index 0000000..e4689c8
--- /dev/null
+++ b/lib/util/regress/fnmatch/fnm_test.c
@@ -0,0 +1,92 @@
+/* $OpenBSD: fnm_test.c,v 1.1 2008/10/01 23:04:58 millert Exp $ */
+
+/*
+ * Public domain, 2008, Todd C. Miller <Todd.Miller@sudo.ws>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_FNMATCH
+# include <fnmatch.h>
+#else
+# include <compat/fnmatch.h>
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+int
+main(int argc, char *argv[])
+{
+ FILE *fp = stdin;
+ char pattern[1024], string[1024], flagstr[1024];
+ int ch, errors = 0, ntests = 0, flags, got, want;
+
+ initprogname(argc > 0 ? argv[0] : "fnm_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0) {
+ if ((fp = fopen(argv[0], "r")) == NULL) {
+ perror(argv[0]);
+ return EXIT_FAILURE;
+ }
+ }
+
+ /*
+ * Read in test file, which is formatted thusly:
+ *
+ * pattern string flags expected_result
+ *
+ */
+ for (;;) {
+ got = fscanf(fp, "%s %s %s %d\n", pattern, string, flagstr,
+ &want);
+ if (got == EOF)
+ break;
+ if (got == 4) {
+ flags = 0;
+ if (strcmp(flagstr, "FNM_NOESCAPE") == 0)
+ flags |= FNM_NOESCAPE;
+ else if (strcmp(flagstr, "FNM_PATHNAME") == 0)
+ flags |= FNM_PATHNAME;
+ else if (strcmp(flagstr, "FNM_PERIOD") == 0)
+ flags |= FNM_PERIOD;
+ else if (strcmp(flagstr, "FNM_LEADING_DIR") == 0)
+ flags |= FNM_LEADING_DIR;
+ else if (strcmp(flagstr, "FNM_CASEFOLD") == 0)
+ flags |= FNM_CASEFOLD;
+ got = fnmatch(pattern, string, flags);
+ if (got != want) {
+ fprintf(stderr,
+ "fnmatch: %s %s %d: want %d, got %d\n",
+ pattern, string, flags, want, got);
+ errors++;
+ }
+ ntests++;
+ }
+ }
+ if (ntests != 0) {
+ printf("fnmatch: %d test%s run, %d errors, %d%% success rate\n",
+ ntests, ntests == 1 ? "" : "s", errors,
+ (ntests - errors) * 100 / ntests);
+ }
+ return errors;
+}
diff --git a/lib/util/regress/fnmatch/fnm_test.in b/lib/util/regress/fnmatch/fnm_test.in
new file mode 100644
index 0000000..3f53f93
--- /dev/null
+++ b/lib/util/regress/fnmatch/fnm_test.in
@@ -0,0 +1,6 @@
+/bin/[[:alpha:][:alnum:]]* /bin/ls FNM_PATHNAME 0
+/bin/[[:alpha:][:alnum:]]* /bin/LS FNM_CASEFOLD 0
+/bin/[[:opper:][:alnum:]]* /bin/ls NONE 1
+[[:alpha:][:alnum:]]*.c foo1.c FNM_PERIOD 0
+[[:upper:]]* FOO NONE 0
+[![:space:]]* bar NONE 0
diff --git a/lib/util/regress/fuzz/fuzz_sudo_conf.c b/lib/util/regress/fuzz/fuzz_sudo_conf.c
new file mode 100644
index 0000000..e2e2723
--- /dev/null
+++ b/lib/util/regress/fuzz/fuzz_sudo_conf.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_conf.h>
+#include <sudo_debug.h>
+#include <sudo_fatal.h>
+#include <sudo_plugin.h>
+#include <sudo_util.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+static int
+fuzz_conversation(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
+{
+ int n;
+
+ for (n = 0; n < num_msgs; n++) {
+ const struct sudo_conv_message *msg = &msgs[n];
+
+ switch (msg->msg_type & 0xff) {
+ case SUDO_CONV_PROMPT_ECHO_ON:
+ case SUDO_CONV_PROMPT_MASK:
+ case SUDO_CONV_PROMPT_ECHO_OFF:
+ /* input not supported */
+ return -1;
+ case SUDO_CONV_ERROR_MSG:
+ case SUDO_CONV_INFO_MSG:
+ /* no output for fuzzers */
+ break;
+ default:
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ struct plugin_info_list *plugins = sudo_conf_plugins();
+ struct sudo_conf_debug_list *debug_list = sudo_conf_debugging();
+ struct sudo_conf_debug_file_list *debug_files;
+ char tempfile[] = "/tmp/sudo_conf.XXXXXX";
+ struct sudo_conf_debug *debug_spec;
+ struct sudo_debug_file *debug_file;
+ struct plugin_info *info;
+ ssize_t nwritten;
+ int fd;
+
+ initprogname("fuzz_sudo_conf");
+ if (getenv("SUDO_FUZZ_VERBOSE") == NULL)
+ sudo_warn_set_conversation(fuzz_conversation);
+
+ /* sudo_conf_read() uses a conf file path, not an open file. */
+ fd = mkstemp(tempfile);
+ if (fd == -1)
+ return 0;
+ nwritten = write(fd, data, size);
+ if (nwritten == -1) {
+ close(fd);
+ return 0;
+ }
+ close(fd);
+
+ /* sudo_conf_read() will re-init and free old data each time it runs. */
+ sudo_conf_clear_paths();
+ sudo_conf_read(tempfile, SUDO_CONF_ALL);
+
+ /* Path settings. */
+ if (sudo_conf_askpass_path() != NULL)
+ sudo_warnx("Path askpass %s", sudo_conf_askpass_path());
+ if (sudo_conf_sesh_path() != NULL)
+ sudo_warnx("Path sesh %s", sudo_conf_sesh_path());
+ if (sudo_conf_intercept_path() != NULL)
+ sudo_warnx("Path intercept %s", sudo_conf_intercept_path());
+ if (sudo_conf_noexec_path() != NULL)
+ sudo_warnx("Path noexec %s", sudo_conf_noexec_path());
+ if (sudo_conf_plugin_dir_path() != NULL)
+ sudo_warnx("Path plugin_dir %s", sudo_conf_plugin_dir_path());
+
+ /* Other settings. */
+ sudo_warnx("Set disable_coredump %s",
+ sudo_conf_disable_coredump() ? "true" : "false");
+ sudo_warnx("Set group_source %s",
+ sudo_conf_group_source() == GROUP_SOURCE_ADAPTIVE ? "adaptive" :
+ sudo_conf_group_source() == GROUP_SOURCE_STATIC ? "static" : "dynamic");
+ sudo_warnx("Set max_groups %d", sudo_conf_max_groups());
+ sudo_warnx("Set probe_interfaces %s",
+ sudo_conf_probe_interfaces() ? "true" : "false");
+
+ /* Plugins. */
+ plugins = sudo_conf_plugins();
+ TAILQ_FOREACH(info, plugins, entries) {
+ /* We don't bother with the plugin options. */
+ sudo_warnx("Plugin %s %s", info->symbol_name, info->path);
+ }
+
+ /* Debug settings. */
+ debug_list = sudo_conf_debugging();
+ TAILQ_FOREACH(debug_spec, debug_list, entries) {
+ TAILQ_FOREACH(debug_file, &debug_spec->debug_files, entries) {
+ sudo_warnx("Debug %s %s %s", debug_spec->progname,
+ debug_file->debug_file, debug_file->debug_flags);
+ }
+ }
+
+ debug_files = sudo_conf_debug_files(getprogname());
+ if (debug_files != NULL) {
+ TAILQ_FOREACH(debug_file, debug_files, entries) {
+ sudo_warnx("Debug %s %s %s", getprogname(),
+ debug_file->debug_file, debug_file->debug_flags);
+ }
+ }
+
+ unlink(tempfile);
+
+ fflush(stdout);
+
+ return 0;
+}
diff --git a/lib/util/regress/fuzz/fuzz_sudo_conf.dict b/lib/util/regress/fuzz/fuzz_sudo_conf.dict
new file mode 100644
index 0000000..4b26917
--- /dev/null
+++ b/lib/util/regress/fuzz/fuzz_sudo_conf.dict
@@ -0,0 +1,18 @@
+# sudo.conf keywords
+"Debug"
+"Path"
+"Plugin"
+"Set"
+
+# Paths
+"askpass"
+"sesh"
+"noexec"
+"plugin_dir"
+"devsearch"
+
+# Variables
+"disable_coredump"
+"group_source"
+"max_groups"
+"probe_interfaces"
diff --git a/lib/util/regress/getdelim/getdelim_test.c b/lib/util/regress/getdelim/getdelim_test.c
new file mode 100644
index 0000000..31548cc
--- /dev/null
+++ b/lib/util/regress/getdelim/getdelim_test.c
@@ -0,0 +1,186 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <limits.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+ssize_t sudo_getdelim(char ** restrict bufp, size_t * restrict bufsizep,
+ int delim, FILE * restrict fp);
+
+/*
+ * Test that sudo_getdelim() works as expected.
+ */
+
+struct getdelim_test {
+ const char *input;
+ const char *output[4];
+ int delim;
+};
+
+static char longstr[LINE_MAX * 4];
+static struct getdelim_test test_data[] = {
+ { "a\nb\nc\n", { "a\n", "b\n", "c\n", NULL }, '\n' },
+ { "a\nb\nc", { "a\n", "b\n", "c", NULL }, '\n' },
+ { "a\tb\tc\t", { "a\t", "b\t", "c\t", NULL }, '\t' },
+ { "a\tb\tc", { "a\t", "b\t", "c", NULL }, '\t' },
+ { longstr, { longstr, NULL }, '\n' },
+ { NULL, { NULL }, '\0' }
+};
+
+static int errors = 0, ntests = 0;
+
+static void
+runtests(char **buf, size_t *buflen)
+{
+ int i, j, sv[2];
+ pid_t pid;
+ FILE *fp;
+
+ /* Exercise realloc case by injecting an entry > LINE_MAX. */
+ memset(longstr, 'A', sizeof(longstr) - 2);
+ longstr[sizeof(longstr) - 2] = '\n';
+ longstr[sizeof(longstr) - 1] = '\0';
+
+ for (i = 0; test_data[i].input != NULL; i++) {
+ if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1)
+ sudo_fatal_nodebug("socketpair");
+
+ switch ((pid = fork())) {
+ case -1:
+ sudo_fatal_nodebug("fork");
+ case 0:
+ /* child */
+ close(sv[0]);
+ if (send(sv[1], test_data[i].input, strlen(test_data[i].input), 0) == -1) {
+ sudo_warn_nodebug("send");
+ _exit(127);
+ }
+ _exit(EXIT_SUCCESS);
+ break;
+ default:
+ /* parent */
+ break;
+ }
+
+ close(sv[1]);
+ if ((fp = fdopen(sv[0], "r")) == NULL)
+ sudo_fatal_nodebug("fdopen");
+
+ for (j = 0; test_data[i].output[j] != NULL; j++) {
+ ntests++;
+ alarm(10);
+ if (sudo_getdelim(buf, buflen, test_data[i].delim, fp) == -1)
+ sudo_fatal_nodebug("sudo_getdelim");
+ alarm(0);
+ if (strcmp(*buf, test_data[i].output[j]) != 0) {
+ sudo_warnx_nodebug("failed test #%d: expected %s, got %s",
+ ntests, test_data[i].output[j], *buf);
+ errors++;
+ }
+ }
+
+ /* test EOF */
+ ntests++;
+ alarm(30);
+ if (sudo_getdelim(buf, buflen, test_data[i].delim, fp) != -1) {
+ sudo_warnx_nodebug("failed test #%d: expected EOF, got %s",
+ ntests, *buf);
+ errors++;
+ } else {
+ if (!feof(fp)) {
+ sudo_warn_nodebug("failed test #%d: expected EOF, got error",
+ ntests);
+ errors++;
+ }
+ }
+
+ /* test error by closing the underlying fd. */
+ clearerr(fp);
+ close(fileno(fp));
+ ntests++;
+ alarm(30);
+ if (sudo_getdelim(buf, buflen, test_data[i].delim, fp) != -1) {
+ sudo_warnx_nodebug("failed test #%d: expected error, got %s",
+ ntests, *buf);
+ errors++;
+ } else {
+ /* Use feof(3), not ferror(3) so we can detect out of memory. */
+ if (feof(fp)) {
+ sudo_warn_nodebug("failed test #%d: expected error, got EOF",
+ ntests);
+ errors++;
+ }
+ }
+
+ fclose(fp);
+ waitpid(pid, NULL, 0);
+ alarm(0);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ size_t buflen = 0;
+ char *buf = NULL;
+ int ch;
+
+ initprogname(argc > 0 ? argv[0] : "getdelim_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ runtests(&buf, &buflen);
+ free(buf);
+
+ /* XXX - redo tests with preallocated buffer filled with junk */
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+ return errors;
+}
diff --git a/lib/util/regress/getgrouplist/getgids.c b/lib/util/regress/getgrouplist/getgids.c
new file mode 100644
index 0000000..83518f3
--- /dev/null
+++ b/lib/util/regress/getgrouplist/getgids.c
@@ -0,0 +1,91 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/*
+ * Implement "id -G" using sudo_getgrouplist2().
+ */
+
+int
+main(int argc, char *argv[])
+{
+ char *username = NULL;
+ GETGROUPS_T *groups = NULL;
+ struct passwd *pw;
+ int ch, i, ngroups;
+ gid_t basegid;
+
+ initprogname(argc > 0 ? argv[0] : "getgids");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v] [user]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0)
+ username = argv[0];
+
+ if (username != NULL) {
+ if ((pw = getpwnam(username)) == NULL)
+ sudo_fatalx("unknown user name %s", username);
+ } else {
+ if ((pw = getpwuid(getuid())) == NULL)
+ sudo_fatalx("unknown user ID %u", (unsigned int)getuid());
+ }
+ basegid = pw->pw_gid;
+ if ((username = strdup(pw->pw_name)) == NULL)
+ sudo_fatal(NULL);
+
+ if (sudo_getgrouplist2(username, basegid, &groups, &ngroups) == -1)
+ sudo_fatal("sudo_getgroulist2");
+
+ for (i = 0; i < ngroups; i++) {
+ printf("%s%u", i ? " " : "", (unsigned int)groups[i]);
+ }
+ putchar('\n');
+ return EXIT_SUCCESS;
+}
diff --git a/lib/util/regress/getgrouplist/getgrouplist_test.c b/lib/util/regress/getgrouplist/getgrouplist_test.c
new file mode 100644
index 0000000..e400e60
--- /dev/null
+++ b/lib/util/regress/getgrouplist/getgrouplist_test.c
@@ -0,0 +1,117 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/*
+ * Test that sudo_getgrouplist2() works as expected.
+ */
+
+int
+main(int argc, char *argv[])
+{
+ int errors = 0;
+#ifndef HAVE_GETGROUPLIST_2
+ GETGROUPS_T *groups = NULL;
+ struct passwd *pw;
+ struct group *grp;
+ char *username;
+ int ch, i, j, ntests = 0;
+ int ngroups;
+ gid_t basegid;
+
+ initprogname(argc > 0 ? argv[0] : "getgrouplist_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if ((pw = getpwuid(0)) == NULL)
+ sudo_fatal_nodebug("getpwuid(0)");
+ basegid = pw->pw_gid;
+ if ((username = strdup(pw->pw_name)) == NULL)
+ sudo_fatal_nodebug(NULL);
+
+ if (sudo_getgrouplist2(username, basegid, &groups, &ngroups) == -1)
+ sudo_fatal_nodebug("sudo_getgroulist2");
+
+ for (i = 0; i < ngroups; i++) {
+ ntests++;
+
+ /* Verify group ID exists. */
+ if ((grp = getgrgid(groups[i])) == NULL) {
+ sudo_warnx_nodebug("unable to look up group ID %u",
+ (unsigned int)groups[i]);
+ errors++;
+ continue;
+ }
+
+ /* Check user's primary gid from the passwd file. */
+ if (grp->gr_gid == basegid)
+ continue;
+
+ /* Verify group membership. */
+ for (j = 0; grp->gr_mem[j] != NULL; j++) {
+ if (strcmp(username, grp->gr_mem[j]) == 0) {
+ /* match */
+ break;
+ }
+ }
+ if (grp->gr_mem[j] == NULL) {
+ sudo_warnx_nodebug("unable to find %s in group %s",
+ username, grp->gr_name);
+ errors++;
+ continue;
+ }
+ }
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+ free(username);
+ free(groups);
+#endif /* HAVE_GETGROUPLIST_2 */
+ return errors;
+}
diff --git a/lib/util/regress/glob/files b/lib/util/regress/glob/files
new file mode 100644
index 0000000..c5e92aa
--- /dev/null
+++ b/lib/util/regress/glob/files
@@ -0,0 +1,47 @@
+fake/bin/[
+fake/bin/cat
+fake/bin/chgrp
+fake/bin/chio
+fake/bin/chmod
+fake/bin/cksum
+fake/bin/cp
+fake/bin/cpio
+fake/bin/csh
+fake/bin/date
+fake/bin/dd
+fake/bin/df
+fake/bin/domainname
+fake/bin/echo
+fake/bin/ed
+fake/bin/eject
+fake/bin/expr
+fake/bin/hostname
+fake/bin/kill
+fake/bin/ksh
+fake/bin/ln
+fake/bin/ls
+fake/bin/md5
+fake/bin/mkdir
+fake/bin/mt
+fake/bin/mv
+fake/bin/pax
+fake/bin/ps
+fake/bin/pwd
+fake/bin/rcp
+fake/bin/rksh
+fake/bin/rm
+fake/bin/rmail
+fake/bin/rmd160
+fake/bin/rmdir
+fake/bin/sh
+fake/bin/sha1
+fake/bin/sha256
+fake/bin/sha384
+fake/bin/sha512
+fake/bin/sleep
+fake/bin/stty
+fake/bin/sum
+fake/bin/sync
+fake/bin/systrace
+fake/bin/tar
+fake/bin/test
diff --git a/lib/util/regress/glob/globtest.c b/lib/util/regress/glob/globtest.c
new file mode 100644
index 0000000..f3623a7
--- /dev/null
+++ b/lib/util/regress/glob/globtest.c
@@ -0,0 +1,224 @@
+/* $OpenBSD: globtest.c,v 1.1 2008/10/01 23:04:36 millert Exp $ */
+
+/*
+ * Public domain, 2008, Todd C. Miller <Todd.Miller@sudo.ws>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_GLOB
+# include <glob.h>
+#else
+# include <compat/glob.h>
+#endif
+#include <errno.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+#define MAX_RESULTS 256
+
+struct gl_entry {
+ int flags;
+ int nresults;
+ char pattern[1024];
+ char *results[MAX_RESULTS];
+};
+
+int test_glob(struct gl_entry *);
+sudo_dso_public int main(int argc, char *argv[]);
+
+int
+main(int argc, char **argv)
+{
+ FILE *fp = stdin;
+ char buf[2048], *cp, *ep;
+ int ch, errors = 0, ntests = 0, lineno;
+ struct gl_entry entry;
+ size_t len;
+
+ initprogname(argc > 0 ? argv[0] : "globtest");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0) {
+ if ((fp = fopen(argv[0], "r")) == NULL) {
+ perror(argv[0]);
+ return EXIT_FAILURE;
+ }
+ }
+
+ /*
+ * Read in test file, which is formatted thusly:
+ *
+ * [pattern] <flags>
+ * result1
+ * result2
+ * result3
+ * ...
+ *
+ */
+ lineno = 0;
+ memset(&entry, 0, sizeof(entry));
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ lineno++;
+ len = strlen(buf);
+ if (len > 0) {
+ if (buf[len - 1] != '\n') {
+ fputs("globtest: missing newline at EOF\n", stderr);
+ return EXIT_FAILURE;
+ }
+ buf[--len] = '\0';
+ }
+ if (len == 0)
+ continue; /* blank line */
+
+ if (buf[0] == '[') {
+ /* check previous pattern */
+ if (entry.pattern[0]) {
+ errors += test_glob(&entry);
+ ntests++;
+ }
+
+ /* start new entry */
+ if ((cp = strrchr(buf + 1, ']')) == NULL) {
+ fprintf(stderr,
+ "globtest: invalid entry on line %d\n",
+ lineno);
+ return EXIT_FAILURE;
+ }
+ len = cp - buf - 1;
+ if (len >= sizeof(entry.pattern)) {
+ fprintf(stderr,
+ "globtest: pattern too big on line %d\n",
+ lineno);
+ return EXIT_FAILURE;
+ }
+ memcpy(entry.pattern, buf + 1, len);
+ entry.pattern[len] = '\0';
+
+ cp += 2;
+ if (*cp++ != '<') {
+ fprintf(stderr,
+ "globtest: invalid entry on line %d\n",
+ lineno);
+ return EXIT_FAILURE;
+ }
+ ep = strchr(cp, '>');
+ if (ep == NULL) {
+ fprintf(stderr,
+ "globtest: invalid entry on line %d\n",
+ lineno);
+ return EXIT_FAILURE;
+ }
+ *ep = '\0';
+ entry.flags = 0;
+ for ((cp = strtok_r(cp, "|", &ep)); cp != NULL; (cp = strtok_r(NULL, "|", &ep))) {
+ if (strcmp(cp, "GLOB_APPEND") == 0)
+ entry.flags |= GLOB_APPEND;
+ else if (strcmp(cp, "GLOB_DOOFFS") == 0)
+ entry.flags |= GLOB_DOOFFS;
+ else if (strcmp(cp, "GLOB_ERR") == 0)
+ entry.flags |= GLOB_ERR;
+ else if (strcmp(cp, "GLOB_MARK") == 0)
+ entry.flags |= GLOB_MARK;
+ else if (strcmp(cp, "GLOB_NOCHECK") == 0)
+ entry.flags |= GLOB_NOCHECK;
+ else if (strcmp(cp, "GLOB_NOSORT") == 0)
+ entry.flags |= GLOB_NOSORT;
+ else if (strcmp(cp, "GLOB_NOESCAPE") == 0)
+ entry.flags |= GLOB_NOESCAPE;
+ else if (strcmp(cp, "GLOB_BRACE") == 0)
+ entry.flags |= GLOB_BRACE;
+ else if (strcmp(cp, "GLOB_TILDE") == 0)
+ entry.flags |= GLOB_TILDE;
+ else if (strcmp(cp, "NONE") != 0) {
+ fprintf(stderr,
+ "globtest: invalid flags on line %d\n",
+ lineno);
+ return EXIT_FAILURE;
+ }
+ }
+ entry.nresults = 0;
+ continue;
+ }
+ if (!entry.pattern[0]) {
+ fprintf(stderr, "globtest: missing entry on line %d\n",
+ lineno);
+ return EXIT_FAILURE;
+ }
+
+ if (entry.nresults + 1 > MAX_RESULTS) {
+ fprintf(stderr,
+ "globtest: too many results for %s, max %d\n",
+ entry.pattern, MAX_RESULTS);
+ return EXIT_FAILURE;
+ }
+ entry.results[entry.nresults++] = strdup(buf);
+ }
+ if (entry.pattern[0]) {
+ errors += test_glob(&entry); /* test last pattern */
+ ntests++;
+ }
+ if (ntests != 0) {
+ printf("glob: %d test%s run, %d errors, %d%% success rate\n",
+ ntests, ntests == 1 ? "" : "s", errors,
+ (ntests - errors) * 100 / ntests);
+ }
+ return errors;
+}
+
+static int
+test_glob(struct gl_entry *entry)
+{
+ glob_t gl;
+ char **ap;
+ int nmatches = 0, i = 0;
+
+ if (glob(entry->pattern, entry->flags, NULL, &gl) != 0) {
+ fprintf(stderr, "glob failed: %s: %s\n", entry->pattern,
+ strerror(errno));
+ return 1;
+ }
+
+ for (ap = gl.gl_pathv; *ap != NULL; ap++)
+ nmatches++;
+
+ if (nmatches != entry->nresults)
+ goto mismatch;
+
+ for (i = 0; i < entry->nresults; i++) {
+ if (strcmp(gl.gl_pathv[i], entry->results[i]) != 0)
+ goto mismatch;
+ free(entry->results[i]);
+ }
+ return 0;
+ mismatch:
+ if (nmatches != entry->nresults) {
+ fprintf(stderr,
+ "globtest: mismatch in number of results (found %d, expected %d) for pattern %s\n",
+ nmatches, entry->nresults, entry->pattern);
+ } else {
+ fprintf(stderr, "globtest: mismatch for pattern %s, flags 0x%x "
+ "(found \"%s\", expected \"%s\")\n", entry->pattern, entry->flags,
+ gl.gl_pathv[i], entry->results[i]);
+ while (i < entry->nresults)
+ free(entry->results[i++]);
+ }
+ return 1;
+}
diff --git a/lib/util/regress/glob/globtest.in b/lib/util/regress/glob/globtest.in
new file mode 100644
index 0000000..20a86c1
--- /dev/null
+++ b/lib/util/regress/glob/globtest.in
@@ -0,0 +1,64 @@
+[fake/bin/[[:alpha:]]*] <NONE>
+fake/bin/cat
+fake/bin/chgrp
+fake/bin/chio
+fake/bin/chmod
+fake/bin/cksum
+fake/bin/cp
+fake/bin/cpio
+fake/bin/csh
+fake/bin/date
+fake/bin/dd
+fake/bin/df
+fake/bin/domainname
+fake/bin/echo
+fake/bin/ed
+fake/bin/eject
+fake/bin/expr
+fake/bin/hostname
+fake/bin/kill
+fake/bin/ksh
+fake/bin/ln
+fake/bin/ls
+fake/bin/md5
+fake/bin/mkdir
+fake/bin/mt
+fake/bin/mv
+fake/bin/pax
+fake/bin/ps
+fake/bin/pwd
+fake/bin/rcp
+fake/bin/rksh
+fake/bin/rm
+fake/bin/rmail
+fake/bin/rmd160
+fake/bin/rmdir
+fake/bin/sh
+fake/bin/sha1
+fake/bin/sha256
+fake/bin/sha384
+fake/bin/sha512
+fake/bin/sleep
+fake/bin/stty
+fake/bin/sum
+fake/bin/sync
+fake/bin/systrace
+fake/bin/tar
+fake/bin/test
+
+[fake/bin/rm{,dir,ail}] <GLOB_BRACE>
+fake/bin/rm
+fake/bin/rmdir
+fake/bin/rmail
+
+[fake/bin/sha[[:digit:]]] <NONE>
+fake/bin/sha1
+
+[fake/bin/sha[[:digit:]]*] <NONE>
+fake/bin/sha1
+fake/bin/sha256
+fake/bin/sha384
+fake/bin/sha512
+
+[fake/bin/ca[a-z]] <NONE>
+fake/bin/cat
diff --git a/lib/util/regress/harness.in b/lib/util/regress/harness.in
new file mode 100755
index 0000000..05fd298
--- /dev/null
+++ b/lib/util/regress/harness.in
@@ -0,0 +1,109 @@
+#!/bin/sh
+#
+# Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# Simple test harness for libsudo_util tests.
+# usage: harness [-v] test_group [test_name ...]
+#
+srcdir="@abs_srcdir@"
+builddir="@abs_builddir@"
+SHELL=@SHELL@
+verbose=0
+rval=0
+ntests=0
+errors=0
+
+umask 022
+
+if [ "$1" = "-v" ]; then
+ verbose=1
+ shift
+fi
+
+if [ $# -eq 0 ]; then
+ echo "usage: harness test_group [test_name ...]" >&2
+ exit 1
+fi
+group="$1"
+shift
+srcdir=${srcdir%"/regress"}
+builddir=${builddir%"/regress"}
+
+cd $srcdir || exit 1
+
+if [ ! -d "regress/$group" ]; then
+ echo "missing test group: regress/$group" >&2
+ exit 1
+fi
+
+mkdir -p "$builddir/regress/$group"
+if [ $# -eq 0 ]; then
+ tests=
+ for t in regress/$group/*.in; do
+ tests="$tests `basename $t .in`"
+ done
+ set -- $tests
+fi
+
+
+while [ $# -ne 0 ]; do
+ test="$1"
+ shift
+ in="regress/$group/${test}.in"
+ out="$builddir/regress/$group/${test}.out"
+ out_ok="regress/$group/${test}.out.ok"
+ err="$builddir/regress/$group/${test}.err"
+ err_ok="regress/$group/${test}.err.ok"
+
+ if [ "$group" = "sudo_conf" ]; then
+ $builddir/conf_test $in >$out 2>$err
+ else
+ $builddir/parseln_test <$in >$out 2>$err
+ fi
+
+ ntests=`expr $ntests + 1`
+ if cmp $out $out_ok >/dev/null; then
+ if [ $verbose -eq 1 ]; then
+ echo "$group/$test: OK"
+ fi
+ else
+ errors=`expr $errors + 1`
+ echo "$group/$test: FAIL"
+ diff $out $out_ok || true
+ fi
+
+ ntests=`expr $ntests + 1`
+ if test -s $err_ok; then
+ if cmp $err $err_ok >/dev/null; then
+ if [ $verbose -eq 1 ]; then
+ echo "$group/$test (stderr): OK"
+ fi
+ else
+ errors=`expr $errors + 1`
+ echo "$group/$test (stderr): FAIL"
+ diff $err $err_ok || true
+ fi
+ elif test -s $err; then
+ errors=`expr $errors + 1`
+ echo "$group/$test (stderr): FAIL"
+ fi
+done
+${AWK-awk} -v group=$group -v ntests=$ntests -v errors=$errors \
+ 'END {printf("%s: %d tests run, %d errors, %d%% success rate\n", group, ntests, errors, (ntests - errors) * 100 / ntests)}' < /dev/null
+if test $errors -ne 0; then
+ rval=`expr $rval + $errors`
+fi
+
+exit $rval
diff --git a/lib/util/regress/hexchar/hexchar_test.c b/lib/util/regress/hexchar/hexchar_test.c
new file mode 100644
index 0000000..097cbcd
--- /dev/null
+++ b/lib/util/regress/hexchar/hexchar_test.c
@@ -0,0 +1,81 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2014-2015, 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+struct hexchar_test {
+ char hex[3];
+ int value;
+};
+
+int
+main(int argc, char *argv[])
+{
+ struct hexchar_test *test_data;
+ int i, ntests, result, errors = 0;
+ static const char xdigs_lower[] = "0123456789abcdef";
+ static const char xdigs_upper[] = "0123456789ABCDEF";
+
+ initprogname(argc > 0 ? argv[0] : "hexchar_test");
+
+ /* Build up test data. */
+ ntests = 256 + 256 + 3;
+ test_data = calloc((size_t)ntests, sizeof(*test_data));
+ for (i = 0; i < 256; i++) {
+ /* lower case */
+ test_data[i].value = i;
+ test_data[i].hex[1] = xdigs_lower[ (i & 0x0f)];
+ test_data[i].hex[0] = xdigs_lower[((i & 0xf0) >> 4)];
+ /* upper case */
+ test_data[i + 256].value = i;
+ test_data[i + 256].hex[1] = xdigs_upper[ (i & 0x0f)];
+ test_data[i + 256].hex[0] = xdigs_upper[((i & 0xf0) >> 4)];
+ }
+ /* Also test invalid data */
+ test_data[ntests - 3].hex[0] = '\0';
+ test_data[ntests - 3].value = -1;
+ strlcpy(test_data[ntests - 2].hex, "AG", sizeof(test_data[ntests - 2].hex));
+ test_data[ntests - 2].value = -1;
+ strlcpy(test_data[ntests - 1].hex, "-1", sizeof(test_data[ntests - 1].hex));
+ test_data[ntests - 1].value = -1;
+
+ for (i = 0; i < ntests; i++) {
+ result = sudo_hexchar(test_data[i].hex);
+ if (result != test_data[i].value) {
+ fprintf(stderr, "%s: expected %d, got %d\n", getprogname(),
+ test_data[i].value, result);
+ errors++;
+ }
+ }
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+ return errors;
+}
diff --git a/lib/util/regress/json/json_test.c b/lib/util/regress/json/json_test.c
new file mode 100644
index 0000000..5acaeb5
--- /dev/null
+++ b/lib/util/regress/json/json_test.c
@@ -0,0 +1,235 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_json.h>
+#include <sudo_util.h>
+#include <sudo_fatal.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/* Expected JSON output */
+const char outbuf[] = "\n"
+ " \"test1\": {\n"
+ " \"string1\": \"test\\\\\\b\\f\\n\\r\\t string1\",\n"
+ " \"id1\": 4294967295,\n"
+ " \"number1\": -1,\n"
+ " \"bool1\": true,\n"
+ " \"bool2\": false,\n"
+ " \"null1\": null,\n"
+ " \"array1\": [\n"
+ " \"string2\": \"test\\f\\u0011string2\",\n"
+ " \"number2\": -9223372036854775808,\n"
+ " \"number3\": 9223372036854775807\n"
+ " ]\n"
+ " }";
+
+/*
+ * Simple tests for sudo json functions()
+ */
+int
+main(int argc, char *argv[])
+{
+ struct json_container jsonc;
+ struct json_value value;
+ int ch, errors = 0, ntests = 0;
+
+ initprogname(argc > 0 ? argv[0] : "json_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ ntests++;
+ if (!sudo_json_init(&jsonc, 4, false, true, true)) {
+ sudo_warnx("unable to initialize json");
+ errors++;
+ goto done;
+ }
+
+ /* Open main JSON object. */
+ ntests++;
+ if (!sudo_json_open_object(&jsonc, "test1")) {
+ sudo_warnx("unable to open json object");
+ errors++;
+ goto done;
+ }
+
+ /* Verify invalid value is detected. */
+ value.type = -1;
+ value.u.string = NULL;
+ ntests++;
+ if (sudo_json_add_value(&jsonc, "bogus1", &value)) {
+ /* should have failed, not a fatal error */
+ sudo_warnx("should not be able to add bogus type value");
+ errors++;
+ }
+
+ /* Verify that adding an array is not allowed. */
+ value.type = JSON_ARRAY;
+ value.u.string = NULL;
+ ntests++;
+ if (sudo_json_add_value(&jsonc, "bogus2", &value)) {
+ /* should have failed, not a fatal error */
+ sudo_warnx("should not be able to add array type value");
+ errors++;
+ }
+
+ /* Verify that adding an object is not allowed. */
+ value.type = JSON_OBJECT;
+ value.u.string = NULL;
+ ntests++;
+ if (sudo_json_add_value(&jsonc, "bogus3", &value)) {
+ /* should have failed, not a fatal error */
+ sudo_warnx("should not be able to add object type value");
+ errors++;
+ }
+
+ value.type = JSON_STRING;
+ value.u.string = "test\\\b\f\n\r\t string1";
+ ntests++;
+ if (!sudo_json_add_value(&jsonc, "string1", &value)) {
+ /* not a fatal error */
+ sudo_warnx("unable to add string value (string1)");
+ errors++;
+ }
+
+ value.type = JSON_ID;
+ value.u.id = 0xffffffff;
+ ntests++;
+ if (!sudo_json_add_value(&jsonc, "id1", &value)) {
+ /* not a fatal error */
+ sudo_warnx("unable to add ID value (0xffffffff)");
+ errors++;
+ }
+
+ value.type = JSON_NUMBER;
+ value.u.number = -1;
+ ntests++;
+ if (!sudo_json_add_value(&jsonc, "number1", &value)) {
+ /* not a fatal error */
+ sudo_warnx("unable to add number value (-1)");
+ errors++;
+ }
+
+ value.type = JSON_BOOL;
+ value.u.boolean = true;
+ ntests++;
+ if (!sudo_json_add_value(&jsonc, "bool1", &value)) {
+ /* not a fatal error */
+ sudo_warnx("unable to add bool value (true)");
+ errors++;
+ }
+ value.u.boolean = false;
+ ntests++;
+ if (!sudo_json_add_value(&jsonc, "bool2", &value)) {
+ /* not a fatal error */
+ sudo_warnx("unable to add bool value (false)");
+ errors++;
+ }
+
+ value.type = JSON_NULL;
+ ntests++;
+ if (!sudo_json_add_value(&jsonc, "null1", &value)) {
+ /* not a fatal error */
+ sudo_warnx("unable to add null value");
+ errors++;
+ }
+
+ /* Open JSON array. */
+ ntests++;
+ if (!sudo_json_open_array(&jsonc, "array1")) {
+ sudo_warnx("unable to open json array");
+ errors++;
+ goto done;
+ }
+
+ value.type = JSON_STRING;
+ value.u.string = "test\x0c\x11string2";
+ ntests++;
+ if (!sudo_json_add_value(&jsonc, "string2", &value)) {
+ /* not a fatal error */
+ sudo_warnx("unable to add string value (string2)");
+ errors++;
+ }
+
+ value.type = JSON_NUMBER;
+ value.u.number = LLONG_MIN;
+ ntests++;
+ if (!sudo_json_add_value(&jsonc, "number2", &value)) {
+ /* not a fatal error */
+ sudo_warnx("unable to add number value (LLONG_MIN)");
+ errors++;
+ }
+ value.u.number = LLONG_MAX;
+ ntests++;
+ if (!sudo_json_add_value(&jsonc, "number3", &value)) {
+ /* not a fatal error */
+ sudo_warnx("unable to add number value (LLONG_MAX)");
+ errors++;
+ }
+
+ /* Close JSON array. */
+ if (!sudo_json_close_array(&jsonc)) {
+ sudo_warnx("unable to close json array");
+ errors++;
+ goto done;
+ }
+
+ /* Close main JSON object. */
+ if (!sudo_json_close_object(&jsonc)) {
+ sudo_warnx("unable to close json object");
+ errors++;
+ goto done;
+ }
+
+ if (strcmp(outbuf, jsonc.buf) != 0) {
+ fprintf(stderr, "Expected:\n%s\n", outbuf);
+ fprintf(stderr, "Received:\n%s\n", jsonc.buf);
+ }
+
+done:
+ sudo_json_free(&jsonc);
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
diff --git a/lib/util/regress/mktemp/mktemp_test.c b/lib/util/regress/mktemp/mktemp_test.c
new file mode 100644
index 0000000..b441431
--- /dev/null
+++ b/lib/util/regress/mktemp/mktemp_test.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2010 Philip Guenther <guenther@openbsd.org>
+ *
+ * Public domain.
+ *
+ * Verify that mkdtemp() and mkstemps() doesn't overrun or underrun
+ * the template buffer and that it can generate names that don't
+ * contain any X's
+ */
+
+#include <config.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_fatal.h>
+
+#ifndef MAP_ANON
+# if defined(MAP_ANONYMOUS)
+# define MAP_ANON MAP_ANONYMOUS
+# endif
+#endif
+
+#ifndef MAP_FAILED
+# define MAP_FAILED ((void *) -1)
+#endif
+
+#define MAX_TEMPLATE_LEN 10
+#define MAX_TRIES 100
+#define MIN_Xs 6
+
+#define SUFFIX ".suff"
+#define SLEN (sizeof SUFFIX - 1)
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/*
+ * verify that a path generated by mkdtemp() or mkstemp() looks like a
+ * reasonable expansion of the template and matches the fd. Returns true
+ * if all the X's were replaced with non-X's
+ */
+static int
+check(int fd, char const *kind, char const *path, char const *prefix,
+ size_t plen, char const *suffix, size_t slen, size_t tlen)
+{
+ struct stat sb, fsb;
+ char const *p;
+
+ if (tlen < MIN_Xs) {
+ if (fd != -1)
+ sudo_fatalx("%s(%s) succeed with too few Xs", kind, path);
+ if (errno != EINVAL)
+ sudo_fatal("%s(%s) failed with wrong errno: %d", kind, path, errno);
+ return 1;
+ }
+ if (fd == -1)
+ sudo_fatal("%s(%s)", kind, path);
+ if (stat(path, &sb))
+ sudo_fatal("%s: stat(%s)", kind, path);
+ if (fd >= 0) {
+ if (fstat(fd, &fsb))
+ sudo_fatal("%s: fstat(%d==%s)", kind, fd, path);
+ if (sb.st_dev != fsb.st_dev || sb.st_ino != fsb.st_ino)
+ sudo_fatalx("%s: stat mismatch", kind);
+ }
+ if (memcmp(path, prefix, plen) != 0)
+ sudo_fatalx("%s: prefix changed! %s vs %s", kind, prefix, path);
+ if (memcmp(path + plen + tlen, suffix, slen + 1) != 0)
+ sudo_fatalx("%s: suffix changed! %s vs %s", kind, suffix, path);
+ for (p = path + plen; p < path + plen + tlen; p++)
+ if (*p == '\0')
+ sudo_fatalx("%s: unexpected truncation", kind);
+ else if (*p == 'X')
+ return 0;
+ return 1;
+}
+
+static void
+try_mkdtemp(char *p, char const *prefix, size_t len)
+{
+ size_t plen = strlen(prefix);
+ int fd, tries, ok;
+
+ for (tries = 0; tries < MAX_TRIES; tries++) {
+ memcpy(p, prefix, plen);
+ memset(p + plen, 'X', len);
+ p[plen + len] = '\0';
+ fd = mkdtemp(p) ? -2 : -1;
+ ok = check(fd, "mkdtemp", p, prefix, plen, "", 0, len);
+ rmdir(p);
+ if (ok)
+ return;
+ }
+ sudo_fatalx("mkdtemp: exceeded MAX_TRIES");
+}
+
+static void
+try_mkstemps(char *p, char const *prefix, size_t len, char const *suffix)
+{
+ size_t plen = strlen(prefix);
+ size_t slen = strlen(suffix);
+ int tries, fd, ok;
+
+ for (tries = 0; tries < MAX_TRIES; tries++) {
+ memcpy(p, prefix, plen);
+ memset(p + plen, 'X', len);
+ memcpy(p + plen + len, suffix, slen + 1);
+ fd = mkstemps(p, (int)slen);
+ ok = check(fd, "mkstemp", p, prefix, plen, suffix, slen, len);
+ close(fd);
+ unlink(p);
+ if (ok)
+ return;
+ }
+ sudo_fatalx("mkstemps: exceeded MAX_TRIES");
+}
+
+int
+main(int argc, char *argv[])
+{
+ char cwd[PATH_MAX + 1];
+ char *p;
+ size_t clen, i;
+ size_t pg;
+ int ch;
+
+ initprogname(argc > 0 ? argv[0] : "mktemp_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ pg = (size_t)sysconf(_SC_PAGESIZE);
+ if (getcwd(cwd, sizeof cwd - 1) == NULL)
+ sudo_fatal("getcwd");
+ clen = strlen(cwd);
+ cwd[clen++] = '/';
+ cwd[clen] = '\0';
+#ifdef MAP_ANON
+ p = mmap(NULL, pg * 3, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
+#else
+ ch = open("/dev/zero", O_RDWR);
+ if (ch == -1)
+ sudo_fatal("/dev/zero");
+ p = mmap(NULL, pg * 3, PROT_READ | PROT_WRITE, MAP_PRIVATE, ch, 0);
+#endif
+ if (p == MAP_FAILED)
+ sudo_fatal("mmap");
+ if (mprotect(p, pg, PROT_NONE) || mprotect(p + pg * 2, pg, PROT_NONE))
+ sudo_fatal("mprotect");
+ p += pg;
+
+ for (i = MAX_TEMPLATE_LEN; i != 0; i--) {
+ /* try first at the start of a page, no prefix */
+ try_mkdtemp(p, "", i);
+ /* now at the end of the page, no prefix */
+ try_mkdtemp(p + pg - i - 1, "", i);
+ /* start of the page, prefixed with the cwd */
+ try_mkdtemp(p, cwd, i);
+ /* how about at the end of the page, prefixed with cwd? */
+ try_mkdtemp(p + pg - clen - i - 1, cwd, i);
+
+ /* again, with mkstemps() and an empty suffix */
+ /* try first at the start of a page, no prefix */
+ try_mkstemps(p, "", i, "");
+ /* now at the end of the page, no prefix */
+ try_mkstemps(p + pg - i - 1, "", i, "");
+ /* start of the page, prefixed with the cwd */
+ try_mkstemps(p, cwd, i, "");
+ /* how about at the end of the page, prefixed with cwd? */
+ try_mkstemps(p + pg - clen - i - 1, cwd, i, "");
+
+ /* mkstemps() and a non-empty suffix */
+ /* try first at the start of a page, no prefix */
+ try_mkstemps(p, "", i, SUFFIX);
+ /* now at the end of the page, no prefix */
+ try_mkstemps(p + pg - i - SLEN - 1, "", i, SUFFIX);
+ /* start of the page, prefixed with the cwd */
+ try_mkstemps(p, cwd, i, SUFFIX);
+ /* how about at the end of the page, prefixed with cwd? */
+ try_mkstemps(p + pg - clen - i - SLEN - 1, cwd, i, SUFFIX);
+ }
+
+ return 0;
+}
diff --git a/lib/util/regress/multiarch/multiarch_test.c b/lib/util/regress/multiarch/multiarch_test.c
new file mode 100644
index 0000000..a6e70c1
--- /dev/null
+++ b/lib/util/regress/multiarch/multiarch_test.c
@@ -0,0 +1,184 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+#ifdef __linux__
+# include <sys/utsname.h>
+
+# if defined(__ILP32__)
+# define ARCH_LIB "libx32"
+# elif defined(__LP64__)
+# define ARCH_LIB "lib64"
+# else
+# define ARCH_LIB "lib32"
+# endif
+
+struct multiarch_test {
+ const char *inpath;
+ char *outpath;
+};
+
+static struct multiarch_test *
+make_test_data(void)
+{
+ struct multiarch_test *test_data;
+ struct utsname unamebuf;
+ int i;
+
+ if (uname(&unamebuf) == -1)
+ return NULL;
+
+ test_data = calloc(7, sizeof(*test_data));
+ if (test_data == NULL)
+ return NULL;
+
+ test_data[0].inpath = "/usr/" ARCH_LIB "/libfoo.so";
+ i = asprintf(&test_data[0].outpath, "/usr/lib/%s-linux-gnu/libfoo.so",
+ unamebuf.machine);
+ if (i == -1) {
+ test_data[0].outpath = NULL;
+ goto bad;
+ }
+
+ test_data[1].inpath = "/usr/lib/something.so";
+ i = asprintf(&test_data[1].outpath, "/usr/lib/%s-linux-gnu/something.so",
+ unamebuf.machine);
+ if (i == -1) {
+ test_data[1].outpath = NULL;
+ goto bad;
+ }
+
+ test_data[2].inpath = "/usr/libexec/libbar.so";
+ i = asprintf(&test_data[2].outpath, "/usr/libexec/%s-linux-gnu/libbar.so",
+ unamebuf.machine);
+ if (i == -1) {
+ test_data[2].outpath = NULL;
+ goto bad;
+ }
+
+ test_data[3].inpath = "/usr/local/lib/sudo/libsudo_util.so";
+ i = asprintf(&test_data[3].outpath, "/usr/local/lib/%s-linux-gnu/sudo/libsudo_util.so",
+ unamebuf.machine);
+ if (i == -1) {
+ test_data[3].outpath = NULL;
+ goto bad;
+ }
+
+ test_data[4].inpath = "/opt/sudo/lib/sudoers.so";
+ i = asprintf(&test_data[4].outpath, "/opt/sudo/lib/%s-linux-gnu/sudoers.so",
+ unamebuf.machine);
+ if (i == -1) {
+ test_data[4].outpath = NULL;
+ goto bad;
+ }
+
+ i = asprintf(&test_data[5].outpath, "/usr/lib/%s-linux-gnu/something.so",
+ unamebuf.machine);
+ if (i == -1) {
+ test_data[5].outpath = NULL;
+ goto bad;
+ }
+ test_data[5].inpath = test_data[5].outpath;
+ test_data[5].outpath = NULL;
+
+ return test_data;
+bad:
+ for (i = 0; test_data[i].outpath != NULL; i++)
+ free(test_data[i].outpath);
+ free(test_data);
+ return NULL;
+}
+#endif /* __linux__ */
+
+int
+main(int argc, char *argv[])
+{
+ int ch, errors = 0;
+#ifdef __linux__
+ int ntests = 0;
+ struct multiarch_test *test_data;
+#endif
+
+ initprogname(argc > 0 ? argv[0] : "multiarch_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+#ifdef __linux__
+ test_data = make_test_data();
+ if (test_data == NULL) {
+ sudo_warnx("%s", "failed to generate test data");
+ return EXIT_FAILURE;
+ }
+
+ for (ch = 0; test_data[ch].inpath != NULL; ch++) {
+ char *outpath = sudo_stat_multiarch(test_data[ch].inpath, NULL);
+ ntests++;
+ if (outpath == NULL) {
+ if (test_data[ch].outpath != NULL) {
+ sudo_warnx("%s: sudo_stat_multiarch failed",
+ test_data[ch].inpath);
+ errors++;
+ }
+ } else if (strcmp(outpath, test_data[ch].outpath) != 0) {
+ sudo_warnx("%s: expected %s got %s", test_data[ch].inpath,
+ test_data[ch].outpath, outpath);
+ errors++;
+ }
+ /* For test_data[5], inpath is allocated and outpath is NULL. */
+ if (test_data[ch].outpath != NULL)
+ free(test_data[ch].outpath);
+ else
+ free((char *)test_data[ch].inpath);
+ free(outpath);
+ }
+ free(test_data);
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+#endif /* __linux__ */
+ return errors;
+}
diff --git a/lib/util/regress/open_parent_dir/open_parent_dir_test.c b/lib/util/regress/open_parent_dir/open_parent_dir_test.c
new file mode 100644
index 0000000..0a4f252
--- /dev/null
+++ b/lib/util/regress/open_parent_dir/open_parent_dir_test.c
@@ -0,0 +1,166 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+static int errors = 0, ntests = 0;
+
+static int
+run_test(const char *tdir, const char *path, uid_t uid, gid_t gid)
+{
+ char *cp, fullpath[PATH_MAX];
+ struct stat sb1, sb2;
+ int dfd, len;
+ int ret = -1;
+
+ /* Test creating full path. */
+ len = snprintf(fullpath, sizeof(fullpath), "%s/%s", tdir, path);
+ if (len < 0 || len >= ssizeof(fullpath)) {
+ errno = ENAMETOOLONG;
+ sudo_fatal("%s/%s", tdir, path);
+ }
+ ntests++;
+ dfd = sudo_open_parent_dir(fullpath, uid, gid, 0700, false);
+ if (dfd == -1) {
+ errors++;
+ goto done;
+ }
+
+ /* Verify that we only created the parent dir, not full path. */
+ ntests++;
+ if (stat(fullpath, &sb1) == 0) {
+ sudo_warnx("created full path \"%s\", not just parent dir",
+ fullpath);
+ errors++;
+ goto done;
+ }
+
+ /* Verify that dfd refers to the parent dir. */
+ ntests++;
+ cp = strrchr(fullpath, '/');
+ *cp = '\0';
+ if (stat(fullpath, &sb1) == -1) {
+ sudo_warn("%s", fullpath);
+ errors++;
+ goto done;
+ }
+ if (fstat(dfd, &sb2) == -1) {
+ sudo_warn("%s", fullpath);
+ errors++;
+ goto done;
+ }
+ if (sb1.st_dev != sb2.st_dev || sb1.st_ino != sb2.st_ino) {
+ sudo_warn("%s: sudo_open_parent_dir fd mismatch", fullpath);
+ errors++;
+ goto done;
+ }
+
+done:
+ if (dfd != -1)
+ close(dfd);
+ return ret;
+}
+
+int
+main(int argc, char *argv[])
+{
+ char tdir[] = "open_parent_dir.XXXXXXXX";
+ int ch, dfd, fd, len;
+ char cmd[1024];
+ uid_t uid;
+ gid_t gid;
+
+ initprogname(argc > 0 ? argv[0] : "open_parent_dir_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ uid = geteuid();
+ gid = getegid();
+
+ /* All tests relative to tdir. */
+ if (mkdtemp(tdir) == NULL)
+ sudo_fatal("%s", tdir);
+
+ /* Test creating new path. */
+ dfd = run_test(tdir, "level1/level2/level3", uid, gid);
+
+ /* Verify we can create a new file in the new parent dir. */
+ if (dfd != -1) {
+ ntests++;
+ fd = openat(dfd, "testfile", O_WRONLY|O_CREAT|O_EXCL, 0600);
+ if (fd == -1) {
+ errors++;
+ } else {
+ close(fd);
+ }
+ close(dfd);
+ dfd = -1;
+ }
+
+ /* Test exiting path when final component exists. */
+ dfd = run_test(tdir, "level1/level2/testfile", uid, gid);
+ if (dfd != -1) {
+ unlinkat(dfd, "testfile", 0);
+ close(dfd);
+ }
+
+ /* Test exiting path when final component doesn't exist. */
+ dfd = run_test(tdir, "level1/level2/testfile", uid, gid);
+ if (dfd != -1)
+ close(dfd);
+
+ /* Cleanup */
+ len = snprintf(cmd, sizeof(cmd), "rm -rf \"%s\"", tdir);
+ if (len < 0 || len >= ssizeof(cmd)) {
+ errno = ENAMETOOLONG;
+ sudo_fatalx("rm -rf %s", tdir);
+ }
+ ignore_result(system(cmd));
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+ return errors;
+}
diff --git a/lib/util/regress/parse_gids/parse_gids_test.c b/lib/util/regress/parse_gids/parse_gids_test.c
new file mode 100644
index 0000000..3a94a72
--- /dev/null
+++ b/lib/util/regress/parse_gids/parse_gids_test.c
@@ -0,0 +1,124 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/*
+ * Test that sudo_parse_gids() works as expected.
+ */
+
+struct parse_gids_test {
+ const char *gids;
+ gid_t *baseptr;
+ gid_t basegid;
+ int ngids;
+ const GETGROUPS_T *gidlist;
+};
+
+static const GETGROUPS_T test1_out[] = { 0, 1, 2, 3, 4 };
+static const GETGROUPS_T test2_out[] = { 1, 2, 3, 4 };
+static const GETGROUPS_T test3_out[] = { 0, 1, (gid_t)-2, 3, 4 };
+
+/* XXX - test syntax errors too */
+static struct parse_gids_test test_data[] = {
+ { "1,2,3,4", &test_data[0].basegid, 0, 5, test1_out },
+ { "1,2,3,4", NULL, 0, 4, test2_out },
+ { "1,-2,3,4", &test_data[2].basegid, 0, 5, test3_out },
+ { NULL, false, 0, 0, NULL }
+};
+
+static void
+dump_gids(const char *prefix, int ngids, const GETGROUPS_T *gidlist)
+{
+ int i;
+
+ fprintf(stderr, "%s: %s: ", getprogname(), prefix);
+ for (i = 0; i < ngids; i++) {
+ fprintf(stderr, "%s%d", i ? ", " : "", (int)gidlist[i]);
+ }
+ fputc('\n', stderr);
+}
+
+int
+main(int argc, char *argv[])
+{
+ GETGROUPS_T *gidlist = NULL;
+ size_t i;
+ int j, errors = 0, ntests = 0;
+ int ch, ngids;
+
+ initprogname(argc > 0 ? argv[0] : "parse_gids_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ for (i = 0; test_data[i].gids != NULL; i++) {
+ free(gidlist);
+ gidlist = NULL;
+ ngids = sudo_parse_gids(test_data[i].gids, test_data[i].baseptr, &gidlist);
+ if (ngids == -1)
+ sudo_fatal_nodebug("sudo_parse_gids");
+ ntests++;
+ if (ngids != test_data[i].ngids) {
+ sudo_warnx_nodebug("test #%d: expected %d gids, got %d",
+ ntests, test_data[i].ngids, ngids);
+ dump_gids("expected", test_data[i].ngids, test_data[i].gidlist);
+ dump_gids("received", ngids, gidlist);
+ errors++;
+ continue;
+ }
+ ntests++;
+ for (j = 0; j < ngids; j++) {
+ if (test_data[i].gidlist[j] != gidlist[j]) {
+ sudo_warnx_nodebug("test #%d: gid mismatch", ntests);
+ dump_gids("expected", test_data[i].ngids, test_data[i].gidlist);
+ dump_gids("received", ngids, gidlist);
+ errors++;
+ break;
+ }
+ }
+ }
+ free(gidlist);
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+ return errors;
+}
diff --git a/lib/util/regress/progname/progname_test.c b/lib/util/regress/progname/progname_test.c
new file mode 100644
index 0000000..330736c
--- /dev/null
+++ b/lib/util/regress/progname/progname_test.c
@@ -0,0 +1,67 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2014 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/*
+ * Test that getprogname() returns the expected result.
+ * On some systems (AIX), we may have issues with symbolic links.
+ */
+
+int
+main(int argc, char *argv[])
+{
+ const char *progbase = "progname_test";
+ int ch;
+
+ if (argc > 0)
+ progbase = sudo_basename(argv[0]);
+ initprogname(progbase);
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", progbase);
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* Make sure getprogname() matches basename of argv[0]. */
+ if (strcmp(getprogname(), progbase) != 0) {
+ printf("%s: FAIL: incorrect program name \"%s\"\n",
+ progbase, getprogname());
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/lib/util/regress/regex/regex_test.c b/lib/util/regress/regex/regex_test.c
new file mode 100644
index 0000000..ce629c6
--- /dev/null
+++ b/lib/util/regress/regex/regex_test.c
@@ -0,0 +1,126 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+struct regex_test {
+ const char *pattern;
+ bool result;
+};
+
+static struct regex_test test_data[] = {
+ { "ab++", false },
+ { "ab\\++", true },
+ { "ab+\\+", true },
+ { "ab**", false },
+ { "ab\\**", true },
+ { "ab*\\*", true },
+ { "ab??", false },
+ { "ab\\??", true },
+ { "ab?\\?", true },
+ { "ab{1}{1}", false },
+ { "ab{1}{1,1}", false },
+ { "ab{1}{,1}", false },
+ { "ab{1}{1,}", false },
+ { "ab{1}\\{1}", true },
+ { "ab{1}\\{1,1}", true },
+ { "ab{1}\\{,1}", true },
+ { "ab{1}\\{1,}", true },
+ { "ab+*", false },
+ { "ab\\+*", true },
+ { "ab+\\*", true },
+ { "ab*+", false },
+ { "ab\\*+", true },
+ { "ab*\\+", true },
+ { "ab?*", false },
+ { "ab\\?*", true },
+ { "ab?\\*", true },
+ { "ab{1}*", false },
+ { "ab\\{1}*", true },
+ { "ab{1}\\*", true },
+ { "ab{256}", false },
+ { "ab{,256}", false },
+ { "ab{256,}", false },
+ { "ab{1,256}", false },
+ { "ab{1,\\256}", false },
+ { "ab{1,2\\56}", false },
+ { "ab{256,1}", false },
+ { "ab{\\256,1}", false },
+ { "ab{2\\56,1}", false },
+ { NULL }
+};
+
+int
+main(int argc, char *argv[])
+{
+ struct regex_test *td;
+ const char *errstr;
+ int errors = 0, ntests = 0;
+ bool result;
+ int ch;
+
+ initprogname(argc > 0 ? argv[0] : "regex_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ for (td = test_data; td->pattern != NULL; td++) {
+ ntests++;
+ result = sudo_regex_compile(NULL, td->pattern, &errstr);
+ if (result != td->result) {
+ sudo_warnx("%s: expected %d, got %d", td->pattern, (int)td->result,
+ (int)result);
+ errors++;
+ }
+ }
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+ return errors;
+}
diff --git a/lib/util/regress/strsig/strsig_test.c b/lib/util/regress/strsig/strsig_test.c
new file mode 100644
index 0000000..79b40fa
--- /dev/null
+++ b/lib/util/regress/strsig/strsig_test.c
@@ -0,0 +1,319 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_fatal.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/*
+ * Note: we do not test SIGUNUSED as it may not appear in sys_sigabbrev[]
+ * on Linux. FreeBSD is missing SIGLWP (aka SIGTHR) in sys_signame[].
+ */
+static struct signal_data {
+ int rval;
+ int signo;
+ const char *sigstr;
+ const char *altstr;
+} signal_data[] = {
+#ifdef SIGHUP
+ { 0, SIGHUP, "HUP", NULL },
+#endif
+#ifdef SIGINT
+ { 0, SIGINT, "INT", NULL },
+#endif
+#ifdef SIGQUIT
+ { 0, SIGQUIT, "QUIT", NULL },
+#endif
+#ifdef SIGILL
+ { 0, SIGILL, "ILL", NULL },
+#endif
+#ifdef SIGTRAP
+ { 0, SIGTRAP, "TRAP", NULL },
+#endif
+#ifdef SIGABRT
+ { 0, SIGABRT, "ABRT", "IOT" },
+#endif
+#ifdef SIGIOT
+ { 0, SIGIOT, "IOT", "ABRT" },
+#endif
+#ifdef SIGEMT
+ { 0, SIGEMT, "EMT", NULL },
+#endif
+#ifdef SIGFPE
+ { 0, SIGFPE, "FPE", NULL },
+#endif
+#ifdef SIGKILL
+ { 0, SIGKILL, "KILL", NULL },
+#endif
+#ifdef SIGBUS
+ { 0, SIGBUS, "BUS", NULL },
+#endif
+#ifdef SIGSEGV
+ { 0, SIGSEGV, "SEGV", NULL },
+#endif
+#ifdef SIGSYS
+ { 0, SIGSYS, "SYS", NULL },
+#endif
+#ifdef SIGPIPE
+ { 0, SIGPIPE, "PIPE", NULL },
+#endif
+#ifdef SIGALRM
+ { 0, SIGALRM, "ALRM", NULL },
+#endif
+#ifdef SIGTERM
+ { 0, SIGTERM, "TERM", NULL },
+#endif
+#ifdef SIGSTKFLT
+ { 0, SIGSTKFLT, "STKFLT", NULL },
+#endif
+#ifdef SIGIO
+ { 0, SIGIO, "IO", "POLL"},
+#endif
+#ifdef SIGXCPU
+ { 0, SIGXCPU, "XCPU", NULL },
+#endif
+#ifdef SIGXFSZ
+ { 0, SIGXFSZ, "XFSZ", NULL },
+#endif
+#ifdef SIGVTALRM
+ { 0, SIGVTALRM, "VTALRM", NULL },
+#endif
+#ifdef SIGPROF
+ { 0, SIGPROF, "PROF", NULL },
+#endif
+#ifdef SIGWINCH
+ { 0, SIGWINCH, "WINCH", NULL },
+#endif
+#ifdef SIGLOST
+ { 0, SIGLOST, "LOST", NULL },
+#endif
+#ifdef SIGUSR1
+ { 0, SIGUSR1, "USR1", NULL },
+#endif
+#ifdef SIGUSR2
+ { 0, SIGUSR2, "USR2", NULL },
+#endif
+#ifdef SIGPWR
+ { 0, SIGPWR, "PWR", NULL },
+#endif
+#ifdef SIGPOLL
+ { 0, SIGPOLL, "POLL", "IO" },
+#endif
+#ifdef SIGSTOP
+ { 0, SIGSTOP, "STOP", NULL },
+#endif
+#ifdef SIGTSTP
+ { 0, SIGTSTP, "TSTP", NULL },
+#endif
+#ifdef SIGCONT
+ { 0, SIGCONT, "CONT", NULL },
+#endif
+#ifdef SIGCHLD
+ { 0, SIGCHLD, "CHLD", "CLD" },
+#endif
+#ifdef SIGCLD
+ { 0, SIGCLD, "CLD", "CHLD" },
+#endif
+#ifdef SIGTTIN
+ { 0, SIGTTIN, "TTIN", NULL },
+#endif
+#ifdef SIGTTOU
+ { 0, SIGTTOU, "TTOU", NULL },
+#endif
+#ifdef SIGINFO
+ { 0, SIGINFO, "INFO", NULL },
+#endif
+#ifdef SIGURG
+ { 0, SIGURG, "URG", NULL },
+#endif
+#ifdef SIGWAITING
+ { 0, SIGWAITING, "WAITING", NULL },
+#endif
+#if defined(SIGLWP) && !defined(__FreeBSD__)
+ { 0, SIGLWP, "LWP", NULL },
+#endif
+#ifdef SIGFREEZE
+ { 0, SIGFREEZE, "FREEZE", NULL },
+#endif
+#ifdef SIGTHAW
+ { 0, SIGTHAW, "THAW", NULL },
+#endif
+#ifdef SIGCANCEL
+ { 0, SIGCANCEL, "CANCEL", NULL },
+#endif
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+ { 0, -1, "RTMIN", NULL },
+ { 0, -1, "RTMIN+1", NULL },
+ { 0, -1, "RTMIN+2", NULL },
+ { 0, -1, "RTMIN+3", NULL },
+ { 0, -1, "RTMAX-3", NULL },
+ { 0, -1, "RTMAX-2", NULL },
+ { 0, -1, "RTMAX-1", NULL },
+ { 0, -1, "RTMAX", NULL },
+#endif
+ { -1, 1024, "QWERT", NULL }, /* invalid */
+ { -1, 0, NULL, NULL }
+};
+
+#ifndef HAVE_SIG2STR
+static int
+test_sig2str(int *ntests)
+{
+ struct signal_data *d;
+ int rval, errors = 0;
+ char sigstr[SIG2STR_MAX];
+
+ for (d = signal_data; d->signo != 0; d++) {
+ (*ntests)++;
+ rval = sudo_sig2str(d->signo, sigstr);
+ if (rval != d->rval) {
+ sudo_warnx_nodebug("FAIL: sig2str(SIG%s): %d != %d",
+ d->sigstr, rval, d->rval);
+ errors++;
+ continue;
+ }
+ if (rval != 0)
+ continue;
+ if (strcmp(sigstr, d->sigstr) != 0 &&
+ (d->altstr != NULL && strcmp(sigstr, d->altstr) != 0)) {
+ sudo_warnx_nodebug("FAIL: signal %d: %s != %s", d->signo,
+ sigstr, d->sigstr);
+ errors++;
+ continue;
+ }
+ }
+
+ return errors;
+}
+#else
+static int
+test_sig2str(int *ntests)
+{
+ return 0;
+}
+#endif /* HAVE_SIG2STR */
+
+#ifndef HAVE_STR2SIG
+static int
+test_str2sig(int *ntests)
+{
+ struct signal_data *d;
+ int rval, errors = 0;
+ int signo;
+
+ for (d = signal_data; d->sigstr != NULL; d++) {
+ (*ntests)++;
+ rval = sudo_str2sig(d->sigstr, &signo);
+ if (rval != d->rval) {
+ sudo_warnx_nodebug("FAIL: str2sig(SIG%s): %d != %d",
+ d->sigstr, rval, d->rval);
+ errors++;
+ continue;
+ }
+ if (rval != 0)
+ continue;
+ if (signo != d->signo) {
+ sudo_warnx_nodebug("FAIL: signal SIG%s: %d != %d", d->sigstr,
+ signo, d->signo);
+ errors++;
+ continue;
+ }
+ }
+
+ return errors;
+}
+#else
+static int
+test_str2sig(int *ntests)
+{
+ return 0;
+}
+#endif /* HAVE_STR2SIG */
+
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+static
+void init_sigrt(void)
+{
+ int i;
+
+ /* Initialize real-time signal values. */
+ for (i = 0; signal_data[i].signo != -1; i++)
+ continue;
+ signal_data[i++].signo = SIGRTMIN;
+ signal_data[i++].signo = SIGRTMIN + 1;
+ signal_data[i++].signo = SIGRTMIN + 2;
+ signal_data[i++].signo = SIGRTMIN + 3;
+ signal_data[i++].signo = SIGRTMAX - 3;
+ signal_data[i++].signo = SIGRTMAX - 2;
+ signal_data[i++].signo = SIGRTMAX - 1;
+ signal_data[i++].signo = SIGRTMAX;
+
+}
+#else
+static
+void init_sigrt(void)
+{
+ /* No real-time signals. */
+ return;
+}
+#endif
+
+/*
+ * Simple tests for sig2str() and str2sig().
+ */
+int
+main(int argc, char *argv[])
+{
+ int ch, errors = 0, ntests = 0;
+
+ initprogname(argc > 0 ? argv[0] : "strsig_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ init_sigrt();
+ errors += test_sig2str(&ntests);
+ errors += test_str2sig(&ntests);
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
diff --git a/lib/util/regress/strsplit/strsplit_test.c b/lib/util/regress/strsplit/strsplit_test.c
new file mode 100644
index 0000000..fb868f4
--- /dev/null
+++ b/lib/util/regress/strsplit/strsplit_test.c
@@ -0,0 +1,117 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/*
+ * Test that sudo_strsplit() works as expected.
+ */
+
+struct strsplit_test {
+ const char *input;
+ size_t input_len;
+ const char **output;
+};
+
+static const char test1_in[] = " vi ";
+static const char *test1_out[] = { "vi", NULL };
+static const char test2_in[] = "vi -r ";
+static const char *test2_out[] = { "vi", "-r", NULL };
+static const char test3_in[] = "vi -r -R abc\tdef ";
+static const char *test3_out[] = { "vi", "-r", "-R", "abc", "def", NULL };
+static const char test4_in[] = "vi -r -R abc\tdef ";
+static const char *test4_out[] = { "vi", "-r", "-R", "abc", NULL };
+static const char test5_in[] = "";
+static const char *test5_out[] = { NULL };
+
+static struct strsplit_test test_data[] = {
+ { test1_in, sizeof(test1_in) - 1, test1_out },
+ { test2_in, sizeof(test2_in) - 1, test2_out },
+ { test3_in, sizeof(test3_in) - 1, test3_out },
+ { test4_in, sizeof(test4_in) - 5, test4_out },
+ { test5_in, sizeof(test5_in) - 1, test5_out },
+ { NULL, 0, NULL }
+};
+
+int
+main(int argc, char *argv[])
+{
+ const char *cp, *ep, *input_end;
+ int ch, i, j, errors = 0, ntests = 0;
+ size_t len;
+
+ initprogname(argc > 0 ? argv[0] : "strsplit_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ for (i = 0; test_data[i].input != NULL; i++) {
+ input_end = test_data[i].input + test_data[i].input_len;
+ cp = sudo_strsplit(test_data[i].input, input_end, " \t", &ep);
+ for (j = 0; test_data[i].output[j] != NULL; j++) {
+ ntests++;
+ len = strlen(test_data[i].output[j]);
+ if ((size_t)(ep - cp) != len) {
+ sudo_warnx_nodebug("failed test #%d: bad length, expected "
+ "%zu, got %zu", ntests, len, (size_t)(ep - cp));
+ errors++;
+ continue;
+ }
+ ntests++;
+ if (strncmp(cp, test_data[i].output[j], len) != 0) {
+ sudo_warnx_nodebug("failed test #%d: expected %s, got %.*s",
+ ntests, test_data[i].output[j], (int)(ep - cp), cp);
+ errors++;
+ continue;
+ }
+ cp = sudo_strsplit(NULL, input_end, " \t", &ep);
+ }
+ ntests++;
+ if (cp != NULL) {
+ sudo_warnx_nodebug("failed test #%d: extra tokens \"%.*s\"",
+ ntests, (int)(input_end - cp), cp);
+ errors++;
+ }
+ }
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+ return errors;
+}
diff --git a/lib/util/regress/strtofoo/strtobool_test.c b/lib/util/regress/strtofoo/strtobool_test.c
new file mode 100644
index 0000000..8264d4f
--- /dev/null
+++ b/lib/util/regress/strtofoo/strtobool_test.c
@@ -0,0 +1,98 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2014-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_fatal.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/* sudo_strtobool() tests */
+static struct strtobool_data {
+ const char *bool_str;
+ int value;
+} strtobool_data[] = {
+ { "true", true },
+ { "false", false },
+ { "TrUe", true },
+ { "fAlSe", false },
+ { "1", true },
+ { "0", false },
+ { "on", true },
+ { "off", false },
+ { "yes", true },
+ { "no", false },
+ { "nope", -1 },
+ { "10", -1 },
+ { "one", -1 },
+ { "zero", -1 },
+ { NULL, 0 }
+};
+
+/*
+ * Simple tests for sudo_strtobool()
+ */
+int
+main(int argc, char *argv[])
+{
+ struct strtobool_data *d;
+ int errors = 0, ntests = 0;
+ int ch, value;
+
+ initprogname(argc > 0 ? argv[0] : "strtobool_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ for (d = strtobool_data; d->bool_str != NULL; d++) {
+ ntests++;
+ value = sudo_strtobool(d->bool_str);
+ if (value != d->value) {
+ sudo_warnx_nodebug("FAIL: %s != %d", d->bool_str, d->value);
+ errors++;
+ }
+ }
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
diff --git a/lib/util/regress/strtofoo/strtoid_test.c b/lib/util/regress/strtofoo/strtoid_test.c
new file mode 100644
index 0000000..6e5998f
--- /dev/null
+++ b/lib/util/regress/strtofoo/strtoid_test.c
@@ -0,0 +1,118 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2014-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_fatal.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/* sudo_strtoidx() tests */
+static struct strtoidx_data {
+ const char *idstr;
+ id_t id;
+ const char *sep;
+ const char *ep;
+ int errnum;
+} strtoidx_data[] = {
+ { "0,1", 0, ",", ",", 0 },
+ { "10", 10, NULL, NULL, 0 },
+ { "-1", 0, NULL, NULL, EINVAL },
+ { "4294967295", 0, NULL, NULL, EINVAL },
+ { "4294967296", 0, NULL, NULL, ERANGE },
+ { "-2147483649", 0, NULL, NULL, ERANGE },
+ { "-2", (id_t)-2, NULL, NULL, 0 },
+#if SIZEOF_ID_T != SIZEOF_LONG_LONG
+ { "-2", (id_t)4294967294U, NULL, NULL, 0 },
+#endif
+ { "4294967294", (id_t)4294967294U, NULL, NULL, 0 },
+ { NULL, 0, NULL, NULL, 0 }
+};
+
+/*
+ * Simple tests for sudo_strtoidx()
+ */
+int
+main(int argc, char *argv[])
+{
+ int ch, errors = 0, ntests = 0;
+ struct strtoidx_data *d;
+ const char *errstr;
+ char *ep;
+ id_t value;
+
+ initprogname(argc > 0 ? argv[0] : "strtoid_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ for (d = strtoidx_data; d->idstr != NULL; d++) {
+ ntests++;
+ errstr = "some error";
+ value = sudo_strtoidx(d->idstr, d->sep, &ep, &errstr);
+ if (d->errnum != 0) {
+ if (errstr == NULL) {
+ sudo_warnx_nodebug("FAIL: %s: missing errstr for errno %d",
+ d->idstr, d->errnum);
+ errors++;
+ } else if (value != 0) {
+ sudo_warnx_nodebug("FAIL: %s should return 0 on error",
+ d->idstr);
+ errors++;
+ } else if (errno != d->errnum) {
+ sudo_warnx_nodebug("FAIL: %s: errno mismatch, %d != %d",
+ d->idstr, errno, d->errnum);
+ errors++;
+ }
+ } else if (errstr != NULL) {
+ sudo_warnx_nodebug("FAIL: %s: %s", d->idstr, errstr);
+ errors++;
+ } else if (value != d->id) {
+ sudo_warnx_nodebug("FAIL: %s != %u", d->idstr, (unsigned int)d->id);
+ errors++;
+ } else if (d->ep != NULL && ep[0] != d->ep[0]) {
+ sudo_warnx_nodebug("FAIL: ep[0] %d != %d", (int)(unsigned char)ep[0],
+ (int)(unsigned char)d->ep[0]);
+ errors++;
+ }
+ }
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
diff --git a/lib/util/regress/strtofoo/strtomode_test.c b/lib/util/regress/strtofoo/strtomode_test.c
new file mode 100644
index 0000000..c7a31b0
--- /dev/null
+++ b/lib/util/regress/strtofoo/strtomode_test.c
@@ -0,0 +1,91 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2014-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_fatal.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/* sudo_strtomode() tests */
+static struct strtomode_data {
+ const char *mode_str;
+ mode_t mode;
+} strtomode_data[] = {
+ { "755", 0755 },
+ { "007", 007 },
+ { "7", 7 },
+ { "8", (mode_t)-1 },
+ { NULL, 0 }
+};
+
+/*
+ * Simple tests for sudo_strtomode().
+ */
+int
+main(int argc, char *argv[])
+{
+ struct strtomode_data *d;
+ const char *errstr;
+ int ch, errors = 0, ntests = 0;
+ mode_t mode;
+
+ initprogname(argc > 0 ? argv[0] : "strtomode_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ for (d = strtomode_data; d->mode_str != NULL; d++) {
+ ntests++;
+ errstr = "some error";
+ mode = sudo_strtomode(d->mode_str, &errstr);
+ if (errstr != NULL) {
+ if (d->mode != (mode_t)-1) {
+ sudo_warnx_nodebug("FAIL: %s: %s", d->mode_str, errstr);
+ errors++;
+ }
+ } else if (mode != d->mode) {
+ sudo_warnx_nodebug("FAIL: %s != 0%o", d->mode_str,
+ (unsigned int) d->mode);
+ errors++;
+ }
+ }
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
diff --git a/lib/util/regress/strtofoo/strtonum_test.c b/lib/util/regress/strtofoo/strtonum_test.c
new file mode 100644
index 0000000..a90ed02
--- /dev/null
+++ b/lib/util/regress/strtofoo/strtonum_test.c
@@ -0,0 +1,135 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_fatal.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/* sudo_strtonum() tests */
+static struct strtonum_data {
+ const char *str;
+ long long minval;
+ long long maxval;
+ long long retval;
+ int errnum;
+} strtonum_data[] = {
+ { "0,1", LLONG_MIN, LLONG_MAX, 0, EINVAL },
+ { "0", INT_MAX, INT_MIN, 0, EINVAL },
+ { "", 0, UINT_MAX, 0, EINVAL },
+ { " ", 0, UINT_MAX, 0, EINVAL },
+ { "-1 ", 0, UINT_MAX, 0, EINVAL },
+ { "9223372036854775808X", LLONG_MIN, LLONG_MAX, 0, EINVAL },
+ { "-9223372036854775809X", LLONG_MIN, LLONG_MAX, 0, EINVAL },
+
+ { "10", 0, 255, 10, 0 },
+ { "-1", 0, UINT_MAX, 0, ERANGE },
+
+ { "-40", -100, -50, 0, ERANGE },
+ { "-60", -100, -50, -60, 0 },
+ { "-200", -100, -50, 0, ERANGE },
+
+ { "42", 42, 42, 42, 0 },
+ { "-42", -42, -42, -42, 0 },
+
+ { "4294967295", 0, UINT_MAX, UINT_MAX, 0 },
+ { "4294967295", INT_MIN, INT_MAX, 0, ERANGE },
+ { "4294967296", 0, UINT_MAX, 0, ERANGE },
+
+ { "2147483647", INT_MIN, INT_MAX, INT_MAX, 0 },
+ { "-2147483648", INT_MIN, INT_MAX, INT_MIN, 0 },
+ { "2147483648", INT_MIN, INT_MAX, 0, ERANGE },
+ { "-2147483649", INT_MIN, INT_MAX, 0, ERANGE },
+
+ { "9223372036854775807", LLONG_MIN, LLONG_MAX, LLONG_MAX, 0 },
+ { "-9223372036854775808", LLONG_MIN, LLONG_MAX, LLONG_MIN, 0 },
+ { "9223372036854775808", LLONG_MIN, LLONG_MAX, 0, ERANGE },
+ { "-9223372036854775809", LLONG_MIN, LLONG_MAX, 0, ERANGE },
+
+ { NULL, 0, 0, 0, 0 }
+};
+
+/*
+ * Simple tests for sudo_strtonum()
+ */
+int
+main(int argc, char *argv[])
+{
+ int ch, errors = 0, ntests = 0;
+ struct strtonum_data *d;
+ const char *errstr;
+ long long value;
+
+ initprogname(argc > 0 ? argv[0] : "strtonum_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ for (d = strtonum_data; d->str != NULL; d++) {
+ ntests++;
+ errstr = "some error";
+ value = sudo_strtonum(d->str, d->minval, d->maxval, &errstr);
+ if (d->errnum != 0) {
+ if (errstr == NULL) {
+ sudo_warnx_nodebug("FAIL: \"%s\": missing errstr for errno %d",
+ d->str, d->errnum);
+ errors++;
+ } else if (value != 0) {
+ sudo_warnx_nodebug("FAIL: %s should return 0 on error",
+ d->str);
+ errors++;
+ } else if (errno != d->errnum) {
+ sudo_warnx_nodebug("FAIL: \"%s\": errno mismatch, %d != %d",
+ d->str, errno, d->errnum);
+ errors++;
+ }
+ } else if (errstr != NULL) {
+ sudo_warnx_nodebug("FAIL: \"%s\": %s", d->str, errstr);
+ errors++;
+ } else if (value != d->retval) {
+ sudo_warnx_nodebug("FAIL: %s != %lld", d->str, d->retval);
+ errors++;
+ }
+ }
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
diff --git a/lib/util/regress/sudo_conf/conf_test.c b/lib/util/regress/sudo_conf/conf_test.c
new file mode 100644
index 0000000..dc65bc3
--- /dev/null
+++ b/lib/util/regress/sudo_conf/conf_test.c
@@ -0,0 +1,126 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_conf.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+
+static void sudo_conf_dump(void);
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/* Awful hack for macOS where the default group source is dynamic. */
+#ifdef __APPLE__
+# undef GROUP_SOURCE_ADAPTIVE
+# define GROUP_SOURCE_ADAPTIVE GROUP_SOURCE_DYNAMIC
+#endif
+
+sudo_noreturn static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-v] conf_file\n", getprogname());
+ exit(EXIT_FAILURE);
+}
+
+/*
+ * Simple test driver for sudo_conf().
+ * Parses the given configuration file and dumps the resulting
+ * sudo_conf_data struct to the standard output.
+ */
+int
+main(int argc, char *argv[])
+{
+ int ch;
+
+ initprogname(argc > 0 ? argv[0] : "conf_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1)
+ usage();
+
+ sudo_conf_clear_paths();
+ if (sudo_conf_read(argv[0], SUDO_CONF_ALL) == -1)
+ return EXIT_FAILURE;
+ sudo_conf_dump();
+
+ return EXIT_SUCCESS;
+}
+
+static void
+sudo_conf_dump(void)
+{
+ struct plugin_info_list *plugins = sudo_conf_plugins();
+ struct sudo_conf_debug_list *debug_list = sudo_conf_debugging();
+ struct sudo_conf_debug *debug_spec;
+ struct sudo_debug_file *debug_file;
+ struct plugin_info *info;
+
+ printf("Set disable_coredump %s\n",
+ sudo_conf_disable_coredump() ? "true" : "false");
+ printf("Set group_source %s\n",
+ sudo_conf_group_source() == GROUP_SOURCE_ADAPTIVE ? "adaptive" :
+ sudo_conf_group_source() == GROUP_SOURCE_STATIC ? "static" : "dynamic");
+ printf("Set max_groups %d\n", sudo_conf_max_groups());
+ printf("Set probe_interfaces %s\n",
+ sudo_conf_probe_interfaces() ? "true" : "false");
+ if (sudo_conf_askpass_path() != NULL)
+ printf("Path askpass %s\n", sudo_conf_askpass_path());
+ if (sudo_conf_sesh_path() != NULL)
+ printf("Path sesh %s\n", sudo_conf_sesh_path());
+ if (sudo_conf_intercept_path() != NULL)
+ printf("Path intercept %s\n", sudo_conf_intercept_path());
+ if (sudo_conf_noexec_path() != NULL)
+ printf("Path noexec %s\n", sudo_conf_noexec_path());
+ if (sudo_conf_plugin_dir_path() != NULL)
+ printf("Path plugin_dir %s\n", sudo_conf_plugin_dir_path());
+ TAILQ_FOREACH(info, plugins, entries) {
+ printf("Plugin %s %s", info->symbol_name, info->path);
+ if (info->options) {
+ char * const * op;
+ for (op = info->options; *op != NULL; op++)
+ printf(" %s", *op);
+ }
+ putchar('\n');
+ }
+ TAILQ_FOREACH(debug_spec, debug_list, entries) {
+ TAILQ_FOREACH(debug_file, &debug_spec->debug_files, entries) {
+ printf("Debug %s %s %s\n", debug_spec->progname,
+ debug_file->debug_file, debug_file->debug_flags);
+ }
+ }
+}
diff --git a/lib/util/regress/sudo_conf/test1.in b/lib/util/regress/sudo_conf/test1.in
new file mode 100644
index 0000000..bc9f626
--- /dev/null
+++ b/lib/util/regress/sudo_conf/test1.in
@@ -0,0 +1,73 @@
+#
+# Sample /etc/sudo.conf file
+#
+# Format:
+# Plugin plugin_name plugin_path plugin_options ...
+# Path askpass /path/to/askpass
+# Path noexec /path/to/sudo_noexec.so
+# Debug sudo /var/log/sudo_debug all@warn
+# Set disable_coredump true
+#
+# Sudo plugins:
+#
+# The plugin_path is relative to ${prefix}/libexec unless fully qualified.
+# The plugin_name corresponds to a global symbol in the plugin
+# that contains the plugin interface structure.
+# The plugin_options are optional.
+#
+# The sudoers plugin is used by default if no Plugin lines are present.
+Plugin sudoers_policy sudoers.so
+Plugin sudoers_io sudoers.so
+
+#
+# Sudo askpass:
+#
+# An askpass helper program may be specified to provide a graphical
+# password prompt for "sudo -A" support. Sudo does not ship with its
+# own askpass program but can use the OpenSSH askpass.
+#
+# Use the OpenSSH askpass
+Path askpass /usr/X11R6/bin/ssh-askpass
+#
+# Use the Gnome OpenSSH askpass
+#Path askpass /usr/libexec/openssh/gnome-ssh-askpass
+
+#
+# Sudo noexec:
+#
+# Path to a shared library containing replacements for the execv(),
+# execve() and fexecve() library functions that just return an error.
+# This is used to implement the "noexec" functionality on systems that
+# support LD_PRELOAD or its equivalent.
+# The compiled-in value is usually sufficient and should only be changed
+# if you rename or move the sudo_noexec.so file.
+#
+Path noexec /usr/local/libexec/sudo_noexec.so
+Path noexec /usr/libexec/sudo_noexec.so
+
+#
+# Core dumps:
+#
+# By default, sudo disables core dumps while it is executing (they
+# are re-enabled for the command that is run).
+# To aid in debugging sudo problems, you may wish to enable core
+# dumps by setting "disable_coredump" to false.
+#
+Set disable_coredump false
+
+#
+# User groups:
+#
+# Sudo passes the user's group list to the policy plugin.
+# If the user is a member of the maximum number of groups (usually 16),
+# sudo will query the group database directly to be sure to include
+# the full list of groups.
+#
+# On some systems, this can be expensive so the behavior is configurable.
+# The "group_source" setting has three possible values:
+# static - use the user's list of groups returned by the kernel.
+# dynamic - query the group database to find the list of groups.
+# adaptive - if user is in less than the maximum number of groups.
+# use the kernel list, else query the group database.
+#
+Set group_source static
diff --git a/lib/util/regress/sudo_conf/test1.out.ok b/lib/util/regress/sudo_conf/test1.out.ok
new file mode 100644
index 0000000..d5b784c
--- /dev/null
+++ b/lib/util/regress/sudo_conf/test1.out.ok
@@ -0,0 +1,8 @@
+Set disable_coredump false
+Set group_source static
+Set max_groups -1
+Set probe_interfaces true
+Path askpass /usr/X11R6/bin/ssh-askpass
+Path noexec /usr/libexec/sudo_noexec.so
+Plugin sudoers_policy sudoers.so
+Plugin sudoers_io sudoers.so
diff --git a/lib/util/regress/sudo_conf/test2.in b/lib/util/regress/sudo_conf/test2.in
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/util/regress/sudo_conf/test2.in
diff --git a/lib/util/regress/sudo_conf/test2.out.ok b/lib/util/regress/sudo_conf/test2.out.ok
new file mode 100644
index 0000000..cfd8a08
--- /dev/null
+++ b/lib/util/regress/sudo_conf/test2.out.ok
@@ -0,0 +1,4 @@
+Set disable_coredump true
+Set group_source adaptive
+Set max_groups -1
+Set probe_interfaces true
diff --git a/lib/util/regress/sudo_conf/test3.in b/lib/util/regress/sudo_conf/test3.in
new file mode 100644
index 0000000..b111a23
--- /dev/null
+++ b/lib/util/regress/sudo_conf/test3.in
@@ -0,0 +1,2 @@
+Plugin sudoers_policy sudoers.so sudoers_file=/etc/sudoers sudoers_mode=0400 sudoers_gid=0 sudoers_uid=0
+Plugin sudoers_io sudoers.so
diff --git a/lib/util/regress/sudo_conf/test3.out.ok b/lib/util/regress/sudo_conf/test3.out.ok
new file mode 100644
index 0000000..3ff2284
--- /dev/null
+++ b/lib/util/regress/sudo_conf/test3.out.ok
@@ -0,0 +1,6 @@
+Set disable_coredump true
+Set group_source adaptive
+Set max_groups -1
+Set probe_interfaces true
+Plugin sudoers_policy sudoers.so sudoers_file=/etc/sudoers sudoers_mode=0400 sudoers_gid=0 sudoers_uid=0
+Plugin sudoers_io sudoers.so
diff --git a/lib/util/regress/sudo_conf/test4.err.ok b/lib/util/regress/sudo_conf/test4.err.ok
new file mode 100644
index 0000000..2d68831
--- /dev/null
+++ b/lib/util/regress/sudo_conf/test4.err.ok
@@ -0,0 +1 @@
+conf_test: invalid value for disable_coredump "foo" in regress/sudo_conf/test4.in, line 1
diff --git a/lib/util/regress/sudo_conf/test4.in b/lib/util/regress/sudo_conf/test4.in
new file mode 100644
index 0000000..a60236a
--- /dev/null
+++ b/lib/util/regress/sudo_conf/test4.in
@@ -0,0 +1 @@
+Set disable_coredump foo
diff --git a/lib/util/regress/sudo_conf/test4.out.ok b/lib/util/regress/sudo_conf/test4.out.ok
new file mode 100644
index 0000000..cfd8a08
--- /dev/null
+++ b/lib/util/regress/sudo_conf/test4.out.ok
@@ -0,0 +1,4 @@
+Set disable_coredump true
+Set group_source adaptive
+Set max_groups -1
+Set probe_interfaces true
diff --git a/lib/util/regress/sudo_conf/test5.err.ok b/lib/util/regress/sudo_conf/test5.err.ok
new file mode 100644
index 0000000..85ef46b
--- /dev/null
+++ b/lib/util/regress/sudo_conf/test5.err.ok
@@ -0,0 +1 @@
+conf_test: invalid max groups "0" in regress/sudo_conf/test5.in, line 1
diff --git a/lib/util/regress/sudo_conf/test5.in b/lib/util/regress/sudo_conf/test5.in
new file mode 100644
index 0000000..3a20495
--- /dev/null
+++ b/lib/util/regress/sudo_conf/test5.in
@@ -0,0 +1 @@
+Set max_groups 0
diff --git a/lib/util/regress/sudo_conf/test5.out.ok b/lib/util/regress/sudo_conf/test5.out.ok
new file mode 100644
index 0000000..cfd8a08
--- /dev/null
+++ b/lib/util/regress/sudo_conf/test5.out.ok
@@ -0,0 +1,4 @@
+Set disable_coredump true
+Set group_source adaptive
+Set max_groups -1
+Set probe_interfaces true
diff --git a/lib/util/regress/sudo_conf/test6.in b/lib/util/regress/sudo_conf/test6.in
new file mode 100644
index 0000000..537fa57
--- /dev/null
+++ b/lib/util/regress/sudo_conf/test6.in
@@ -0,0 +1 @@
+Set max_groups 16
diff --git a/lib/util/regress/sudo_conf/test6.out.ok b/lib/util/regress/sudo_conf/test6.out.ok
new file mode 100644
index 0000000..674ae38
--- /dev/null
+++ b/lib/util/regress/sudo_conf/test6.out.ok
@@ -0,0 +1,4 @@
+Set disable_coredump true
+Set group_source adaptive
+Set max_groups 16
+Set probe_interfaces true
diff --git a/lib/util/regress/sudo_conf/test7.in b/lib/util/regress/sudo_conf/test7.in
new file mode 100644
index 0000000..7438131
--- /dev/null
+++ b/lib/util/regress/sudo_conf/test7.in
@@ -0,0 +1,4 @@
+Debug sudo /var/log/sudo_debug all@info
+Debug sudo /var/log/sudo_debug util@debug
+Debug visudo /var/log/sudo_debug match@debug
+Debug sudoers.so /var/log/sudoers_debug match@debug,nss@info
diff --git a/lib/util/regress/sudo_conf/test7.out.ok b/lib/util/regress/sudo_conf/test7.out.ok
new file mode 100644
index 0000000..7ec856d
--- /dev/null
+++ b/lib/util/regress/sudo_conf/test7.out.ok
@@ -0,0 +1,8 @@
+Set disable_coredump true
+Set group_source adaptive
+Set max_groups -1
+Set probe_interfaces true
+Debug sudo /var/log/sudo_debug all@info
+Debug sudo /var/log/sudo_debug util@debug
+Debug visudo /var/log/sudo_debug match@debug
+Debug sudoers.so /var/log/sudoers_debug match@debug,nss@info
diff --git a/lib/util/regress/sudo_parseln/parseln_test.c b/lib/util/regress/sudo_parseln/parseln_test.c
new file mode 100644
index 0000000..9463767
--- /dev/null
+++ b/lib/util/regress/sudo_parseln/parseln_test.c
@@ -0,0 +1,64 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/*
+ * Simple test driver for sudo_parseln().
+ * Behaves similarly to "cat -n" but with comment removal
+ * and line continuation.
+ */
+
+int
+main(int argc, char *argv[])
+{
+ unsigned int lineno = 0;
+ size_t linesize = 0;
+ char *line = NULL;
+ int ch;
+
+ initprogname(argc > 0 ? argv[0] : "parseln_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ while (sudo_parseln(&line, &linesize, &lineno, stdin, 0) != -1)
+ printf("%6u\t%s\n", lineno, line);
+ free(line);
+ return EXIT_SUCCESS;
+}
diff --git a/lib/util/regress/sudo_parseln/test1.in b/lib/util/regress/sudo_parseln/test1.in
new file mode 100644
index 0000000..8f417dd
--- /dev/null
+++ b/lib/util/regress/sudo_parseln/test1.in
@@ -0,0 +1,72 @@
+#
+# Sample /etc/sudo.conf file
+#
+# Format:
+# Plugin plugin_name plugin_path plugin_options ...
+# Path askpass /path/to/askpass
+# Path noexec /path/to/sudo_noexec.so
+# Debug sudo /var/log/sudo_debug all@warn
+# Set disable_coredump true
+#
+# Sudo plugins:
+#
+# The plugin_path is relative to ${prefix}/libexec unless fully qualified.
+# The plugin_name corresponds to a global symbol in the plugin
+# that contains the plugin interface structure.
+# The plugin_options are optional.
+#
+# The sudoers plugin is used by default if no Plugin lines are present.
+Plugin sudoers_policy sudoers.so
+Plugin sudoers_io sudoers.so
+
+#
+# Sudo askpass:
+#
+# An askpass helper program may be specified to provide a graphical
+# password prompt for "sudo -A" support. Sudo does not ship with its
+# own askpass program but can use the OpenSSH askpass.
+#
+# Use the OpenSSH askpass
+#Path askpass /usr/X11R6/bin/ssh-askpass
+#
+# Use the Gnome OpenSSH askpass
+#Path askpass /usr/libexec/openssh/gnome-ssh-askpass
+
+#
+# Sudo noexec:
+#
+# Path to a shared library containing replacements for the execv(),
+# execve() and fexecve() library functions that just return an error.
+# This is used to implement the "noexec" functionality on systems that
+# support LD_PRELOAD or its equivalent.
+# The compiled-in value is usually sufficient and should only be changed
+# if you rename or move the sudo_noexec.so file.
+#
+#Path noexec /usr/libexec/sudo_noexec.so
+
+#
+# Core dumps:
+#
+# By default, sudo disables core dumps while it is executing (they
+# are re-enabled for the command that is run).
+# To aid in debugging sudo problems, you may wish to enable core
+# dumps by setting "disable_coredump" to false.
+#
+#Set disable_coredump false
+
+#
+# User groups:
+#
+# Sudo passes the user's group list to the policy plugin.
+# If the user is a member of the maximum number of groups (usually 16),
+# sudo will query the group database directly to be sure to include
+# the full list of groups.
+#
+# On some systems, this can be expensive so the behavior is configurable.
+# The "group_source" setting has three possible values:
+# static - use the user's list of groups returned by the kernel.
+# dynamic - query the group database to find the list of groups.
+# adaptive - if user is in less than the maximum number of groups.
+# use the kernel list, else query the group database.
+#
+#Set group_source static
diff --git a/lib/util/regress/sudo_parseln/test1.out.ok b/lib/util/regress/sudo_parseln/test1.out.ok
new file mode 100644
index 0000000..c98ca77
--- /dev/null
+++ b/lib/util/regress/sudo_parseln/test1.out.ok
@@ -0,0 +1,72 @@
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19 Plugin sudoers_policy sudoers.so
+ 20 Plugin sudoers_io sudoers.so
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
diff --git a/lib/util/regress/sudo_parseln/test2.in b/lib/util/regress/sudo_parseln/test2.in
new file mode 100644
index 0000000..49166ee
--- /dev/null
+++ b/lib/util/regress/sudo_parseln/test2.in
@@ -0,0 +1,8 @@
+this \
+is all \
+one line
+# this is a comment, and does not get continued\
+trim the \
+ leading \
+ white \
+space
diff --git a/lib/util/regress/sudo_parseln/test2.out.ok b/lib/util/regress/sudo_parseln/test2.out.ok
new file mode 100644
index 0000000..d921968
--- /dev/null
+++ b/lib/util/regress/sudo_parseln/test2.out.ok
@@ -0,0 +1,3 @@
+ 3 this is all one line
+ 4
+ 8 trim the leading white space
diff --git a/lib/util/regress/sudo_parseln/test3.in b/lib/util/regress/sudo_parseln/test3.in
new file mode 100644
index 0000000..e372c07
--- /dev/null
+++ b/lib/util/regress/sudo_parseln/test3.in
@@ -0,0 +1 @@
+line continuation at EOF \
diff --git a/lib/util/regress/sudo_parseln/test3.out.ok b/lib/util/regress/sudo_parseln/test3.out.ok
new file mode 100644
index 0000000..2e8d16d
--- /dev/null
+++ b/lib/util/regress/sudo_parseln/test3.out.ok
@@ -0,0 +1 @@
+ 1 line continuation at EOF
diff --git a/lib/util/regress/sudo_parseln/test4.in b/lib/util/regress/sudo_parseln/test4.in
new file mode 100644
index 0000000..3583f3b
--- /dev/null
+++ b/lib/util/regress/sudo_parseln/test4.in
@@ -0,0 +1,4 @@
+line contin\
+uation raw
+line contin\
+ uation indented
diff --git a/lib/util/regress/sudo_parseln/test4.out.ok b/lib/util/regress/sudo_parseln/test4.out.ok
new file mode 100644
index 0000000..38afbeb
--- /dev/null
+++ b/lib/util/regress/sudo_parseln/test4.out.ok
@@ -0,0 +1,2 @@
+ 2 line continuation raw
+ 4 line continuation indented
diff --git a/lib/util/regress/sudo_parseln/test5.in b/lib/util/regress/sudo_parseln/test5.in
new file mode 100644
index 0000000..57ddad2
--- /dev/null
+++ b/lib/util/regress/sudo_parseln/test5.in
@@ -0,0 +1 @@
+\
diff --git a/lib/util/regress/sudo_parseln/test5.out.ok b/lib/util/regress/sudo_parseln/test5.out.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/util/regress/sudo_parseln/test5.out.ok
diff --git a/lib/util/regress/sudo_parseln/test6.in b/lib/util/regress/sudo_parseln/test6.in
new file mode 100644
index 0000000..95cac84
--- /dev/null
+++ b/lib/util/regress/sudo_parseln/test6.in
@@ -0,0 +1,3 @@
+ leading and trailing white space
+ # a comment
+\
diff --git a/lib/util/regress/sudo_parseln/test6.out.ok b/lib/util/regress/sudo_parseln/test6.out.ok
new file mode 100644
index 0000000..340765e
--- /dev/null
+++ b/lib/util/regress/sudo_parseln/test6.out.ok
@@ -0,0 +1,2 @@
+ 1 leading and trailing white space
+ 2
diff --git a/lib/util/regress/tailq/hltq_test.c b/lib/util/regress/tailq/hltq_test.c
new file mode 100644
index 0000000..412d7a9
--- /dev/null
+++ b/lib/util/regress/tailq/hltq_test.c
@@ -0,0 +1,205 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_queue.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/*
+ * Note: HLTQ_ENTRY is intentionally in the middle of the struct
+ * to catch bad assumptions in the PREV/NEXT macros.
+ */
+struct test_data {
+ int a;
+ HLTQ_ENTRY(test_data) entries;
+ char b;
+};
+
+TAILQ_HEAD(test_data_list, test_data);
+
+/*
+ * Simple tests for headless tail queue macros.
+ */
+int
+main(int argc, char *argv[])
+{
+ struct test_data d1, d2, d3;
+ struct test_data *hltq;
+ struct test_data_list tq;
+ int ch, errors = 0, ntests = 0;
+
+ initprogname(argc > 0 ? argv[0] : "hltq_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /*
+ * Initialize three data elements and concatenate them in order.
+ */
+ HLTQ_INIT(&d1, entries);
+ d1.a = 1;
+ d1.b = 'a';
+ if (HLTQ_FIRST(&d1) != &d1) {
+ sudo_warnx_nodebug("FAIL: HLTQ_FIRST(1 entry) doesn't return first element: got %p, expected %p", HLTQ_FIRST(&d1), &d1);
+ errors++;
+ }
+ ntests++;
+ if (HLTQ_LAST(&d1, test_data, entries) != &d1) {
+ sudo_warnx_nodebug("FAIL: HLTQ_LAST(1 entry) doesn't return first element: got %p, expected %p", HLTQ_LAST(&d1, test_data, entries), &d1);
+ errors++;
+ }
+ ntests++;
+ if (HLTQ_PREV(&d1, test_data, entries) != NULL) {
+ sudo_warnx_nodebug("FAIL: HLTQ_PREV(1 entry) doesn't return NULL: got %p", HLTQ_PREV(&d1, test_data, entries));
+ errors++;
+ }
+ ntests++;
+
+ HLTQ_INIT(&d2, entries);
+ d2.a = 2;
+ d2.b = 'b';
+
+ HLTQ_INIT(&d3, entries);
+ d3.a = 3;
+ d3.b = 'c';
+
+ HLTQ_CONCAT(&d1, &d2, entries);
+ HLTQ_CONCAT(&d1, &d3, entries);
+ hltq = &d1;
+
+ /*
+ * Verify that HLTQ_FIRST, HLTQ_LAST, HLTQ_NEXT, HLTQ_PREV
+ * work as expected.
+ */
+ if (HLTQ_FIRST(hltq) != &d1) {
+ sudo_warnx_nodebug("FAIL: HLTQ_FIRST(3 entries) doesn't return first element: got %p, expected %p", HLTQ_FIRST(hltq), &d1);
+ errors++;
+ }
+ ntests++;
+ if (HLTQ_LAST(hltq, test_data, entries) != &d3) {
+ sudo_warnx_nodebug("FAIL: HLTQ_LAST(3 entries) doesn't return third element: got %p, expected %p", HLTQ_LAST(hltq, test_data, entries), &d3);
+ errors++;
+ }
+ ntests++;
+
+ if (HLTQ_NEXT(&d1, entries) != &d2) {
+ sudo_warnx_nodebug("FAIL: HLTQ_NEXT(&d1) doesn't return &d2: got %p, expected %p", HLTQ_NEXT(&d1, entries), &d2);
+ errors++;
+ }
+ ntests++;
+ if (HLTQ_NEXT(&d2, entries) != &d3) {
+ sudo_warnx_nodebug("FAIL: HLTQ_NEXT(&d2) doesn't return &d3: got %p, expected %p", HLTQ_NEXT(&d2, entries), &d3);
+ errors++;
+ }
+ ntests++;
+ if (HLTQ_NEXT(&d3, entries) != NULL) {
+ sudo_warnx_nodebug("FAIL: HLTQ_NEXT(&d3) doesn't return NULL: got %p", HLTQ_NEXT(&d3, entries));
+ errors++;
+ }
+ ntests++;
+
+ if (HLTQ_PREV(&d1, test_data, entries) != NULL) {
+ sudo_warnx_nodebug("FAIL: HLTQ_PREV(&d1) doesn't return NULL: got %p", HLTQ_PREV(&d1, test_data, entries));
+ errors++;
+ }
+ ntests++;
+ if (HLTQ_PREV(&d2, test_data, entries) != &d1) {
+ sudo_warnx_nodebug("FAIL: HLTQ_PREV(&d2) doesn't return &d1: got %p, expected %p", HLTQ_PREV(&d2, test_data, entries), &d1);
+ errors++;
+ }
+ ntests++;
+ if (HLTQ_PREV(&d3, test_data, entries) != &d2) {
+ sudo_warnx_nodebug("FAIL: HLTQ_PREV(&d3) doesn't return &d2: got %p, expected %p", HLTQ_PREV(&d3, test_data, entries), &d2);
+ errors++;
+ }
+ ntests++;
+
+ /* Test conversion to TAILQ. */
+ HLTQ_TO_TAILQ(&tq, hltq, entries);
+
+ if (TAILQ_FIRST(&tq) != &d1) {
+ sudo_warnx_nodebug("FAIL: TAILQ_FIRST(&tq) doesn't return first element: got %p, expected %p", TAILQ_FIRST(&tq), &d1);
+ errors++;
+ }
+ ntests++;
+ if (TAILQ_LAST(&tq, test_data_list) != &d3) {
+ sudo_warnx_nodebug("FAIL: TAILQ_LAST(&tq) doesn't return third element: got %p, expected %p", TAILQ_LAST(&tq, test_data_list), &d3);
+ errors++;
+ }
+ ntests++;
+
+ if (TAILQ_NEXT(&d1, entries) != &d2) {
+ sudo_warnx_nodebug("FAIL: TAILQ_NEXT(&d1) doesn't return &d2: got %p, expected %p", TAILQ_NEXT(&d1, entries), &d2);
+ errors++;
+ }
+ ntests++;
+ if (TAILQ_NEXT(&d2, entries) != &d3) {
+ sudo_warnx_nodebug("FAIL: TAILQ_NEXT(&d2) doesn't return &d3: got %p, expected %p", TAILQ_NEXT(&d2, entries), &d3);
+ errors++;
+ }
+ ntests++;
+ if (TAILQ_NEXT(&d3, entries) != NULL) {
+ sudo_warnx_nodebug("FAIL: TAILQ_NEXT(&d3) doesn't return NULL: got %p", TAILQ_NEXT(&d3, entries));
+ errors++;
+ }
+ ntests++;
+
+ if (TAILQ_PREV(&d1, test_data_list, entries) != NULL) {
+ sudo_warnx_nodebug("FAIL: TAILQ_PREV(&d1) doesn't return NULL: got %p", TAILQ_PREV(&d1, test_data_list, entries));
+ errors++;
+ }
+ ntests++;
+ if (TAILQ_PREV(&d2, test_data_list, entries) != &d1) {
+ sudo_warnx_nodebug("FAIL: TAILQ_PREV(&d2) doesn't return &d1: got %p, expected %p", TAILQ_PREV(&d2, test_data_list, entries), &d1);
+ errors++;
+ }
+ ntests++;
+ if (TAILQ_PREV(&d3, test_data_list, entries) != &d2) {
+ sudo_warnx_nodebug("FAIL: TAILQ_PREV(&d3) doesn't return &d2: got %p, expected %p", TAILQ_PREV(&d3, test_data_list, entries), &d2);
+ errors++;
+ }
+ ntests++;
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
diff --git a/lib/util/regress/uuid/uuid_test.c b/lib/util/regress/uuid/uuid_test.c
new file mode 100644
index 0000000..411266c
--- /dev/null
+++ b/lib/util/regress/uuid/uuid_test.c
@@ -0,0 +1,105 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <string.h>
+#include <unistd.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/*
+ * Test that sudo_uuid_create() generates a variant 1, version 4 uuid.
+ */
+
+/* From RFC 4122. */
+struct uuid {
+ uint32_t time_low;
+ uint16_t time_mid;
+ uint16_t time_hi_and_version;
+ uint8_t clock_seq_hi_and_reserved;
+ uint8_t clock_seq_low;
+ uint8_t node[6];
+};
+
+int
+main(int argc, char *argv[])
+{
+ int ch, errors = 0, ntests = 0;
+ union {
+ struct uuid id;
+ unsigned char u8[16];
+ } uuid;
+
+ initprogname(argc > 0 ? argv[0] : "uuid_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignore */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* Do 16 passes. */
+ for (ntests = 0; ntests < 16; ntests++) {
+ sudo_uuid_create(uuid.u8);
+
+ /* Variant: two most significant bits (6 and 7) are 0 and 1. */
+ if (ISSET(uuid.id.clock_seq_hi_and_reserved, (1 << 6))) {
+ sudo_warnx("uuid bit 6 set, should be clear");
+ errors++;
+ continue;
+ }
+ if (!ISSET(uuid.id.clock_seq_hi_and_reserved, (1 << 7))) {
+ sudo_warnx("uuid bit 7 clear, should be set");
+ errors++;
+ continue;
+ }
+
+ /* Version: bits 12-15 are 0010. */
+ if ((uuid.id.time_hi_and_version & 0xf000) != 0x4000) {
+ sudo_warnx("bad version: 0x%x", uuid.id.time_hi_and_version & 0xf000);
+ errors++;
+ continue;
+ }
+ }
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+ return errors;
+}
diff --git a/lib/util/roundup.c b/lib/util/roundup.c
new file mode 100644
index 0000000..73cf4af
--- /dev/null
+++ b/lib/util/roundup.c
@@ -0,0 +1,81 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+
+/*
+ * Round 32-bit unsigned length to the next highest power of two.
+ * Always returns at least 64.
+ */
+unsigned int
+sudo_pow2_roundup_v1(unsigned int len)
+{
+ if (len < 64)
+ return 64;
+
+#ifdef HAVE___BUILTIN_CLZ
+ return 1U << (32 - __builtin_clz(len - 1));
+#else
+ len--;
+ len |= len >> 1;
+ len |= len >> 2;
+ len |= len >> 4;
+ len |= len >> 8;
+ len |= len >> 16;
+ len++;
+ return len;
+#endif
+}
+
+/*
+ * Round a size_t length to the next highest power of two.
+ * Always returns at least 64.
+ */
+size_t
+sudo_pow2_roundup_v2(size_t len)
+{
+ if (len < 64)
+ return 64;
+
+#if defined(__LP64__) && defined(HAVE___BUILTIN_CLZL)
+ return 1UL << (64 - __builtin_clzl(len - 1));
+#elif !defined(__LP64__) && defined(HAVE___BUILTIN_CLZ)
+ return 1U << (32 - __builtin_clz(len - 1));
+#else
+ len--;
+ len |= len >> 1;
+ len |= len >> 2;
+ len |= len >> 4;
+ len |= len >> 8;
+ len |= len >> 16;
+# ifdef __LP64__
+ len |= len >> 32;
+# endif
+ len++;
+ return len;
+#endif
+}
diff --git a/lib/util/secure_path.c b/lib/util/secure_path.c
new file mode 100644
index 0000000..aaceb57
--- /dev/null
+++ b/lib/util/secure_path.c
@@ -0,0 +1,203 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2012, 2014-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_debug.h>
+
+/*
+ * Verify that path is the right type and not writable by other users.
+ */
+static int
+sudo_check_secure(struct stat *sb, unsigned int type, uid_t uid, gid_t gid)
+{
+ int ret = SUDO_PATH_SECURE;
+ debug_decl(sudo_check_secure, SUDO_DEBUG_UTIL);
+
+ if ((sb->st_mode & S_IFMT) != type) {
+ ret = SUDO_PATH_BAD_TYPE;
+ } else if (uid != (uid_t)-1 && sb->st_uid != uid) {
+ ret = SUDO_PATH_WRONG_OWNER;
+ } else if (sb->st_mode & S_IWOTH) {
+ ret = SUDO_PATH_WORLD_WRITABLE;
+ } else if (ISSET(sb->st_mode, S_IWGRP) &&
+ (gid == (gid_t)-1 || sb->st_gid != gid)) {
+ ret = SUDO_PATH_GROUP_WRITABLE;
+ }
+
+ debug_return_int(ret);
+}
+
+/*
+ * Verify that path is the right type and not writable by other users.
+ */
+static int
+sudo_secure_path(const char *path, unsigned int type, uid_t uid, gid_t gid,
+ struct stat *sb)
+{
+ int ret = SUDO_PATH_MISSING;
+ struct stat stat_buf;
+ debug_decl(sudo_secure_path, SUDO_DEBUG_UTIL);
+
+ if (sb == NULL)
+ sb = &stat_buf;
+
+ if (path != NULL && stat(path, sb) == 0)
+ ret = sudo_check_secure(sb, type, uid, gid);
+
+ debug_return_int(ret);
+}
+
+/*
+ * Verify that path is a regular file and not writable by other users.
+ * Not currently used.
+ */
+int
+sudo_secure_file_v1(const char *path, uid_t uid, gid_t gid, struct stat *sb)
+{
+ return sudo_secure_path(path, S_IFREG, uid, gid, sb);
+}
+
+/*
+ * Verify that path is a directory and not writable by other users.
+ */
+int
+sudo_secure_dir_v1(const char *path, uid_t uid, gid_t gid, struct stat *sb)
+{
+ return sudo_secure_path(path, S_IFDIR, uid, gid, sb);
+}
+
+/*
+ * Verify that fd matches type and not writable by other users.
+ */
+int
+sudo_secure_fd_v1(int fd, unsigned int type, uid_t uid, gid_t gid,
+ struct stat *sb)
+{
+ int ret = SUDO_PATH_MISSING;
+ debug_decl(sudo_secure_fd, SUDO_DEBUG_UTIL);
+
+ if (fd != -1 && fstat(fd, sb) == 0)
+ ret = sudo_check_secure(sb, type, uid, gid);
+ debug_return_int(ret);
+}
+
+/*
+ * Open path read-only as long as it is not writable by other users.
+ * Returns an open file descriptor on success, else -1.
+ * Sets error to SUDO_PATH_SECURE on success, and a value < 0 on failure.
+ */
+static int
+sudo_secure_open(const char *path, unsigned int type, uid_t uid, gid_t gid,
+ struct stat *sb, int *error)
+{
+ struct stat stat_buf;
+ int fd;
+ debug_decl(sudo_secure_open, SUDO_DEBUG_UTIL);
+
+ if (sb == NULL)
+ sb = &stat_buf;
+
+ fd = open(path, O_RDONLY|O_NONBLOCK);
+ if (fd == -1 || fstat(fd, sb) != 0) {
+ if (fd != -1)
+ close(fd);
+ *error = SUDO_PATH_MISSING;
+ debug_return_int(-1);
+ }
+
+ *error = sudo_check_secure(sb, type, uid, gid);
+ if (*error == SUDO_PATH_SECURE) {
+ (void)fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
+ } else {
+ /* Not secure, caller can check error flag. */
+ close(fd);
+ fd = -1;
+ }
+
+ debug_return_int(fd);
+}
+
+int
+sudo_secure_open_file_v1(const char *path, uid_t uid, gid_t gid,
+ struct stat *sb, int *error)
+{
+ return sudo_secure_open(path, S_IFREG, uid, gid, sb, error);
+}
+
+int
+sudo_secure_open_dir_v1(const char *path, uid_t uid, gid_t gid,
+ struct stat *sb, int *error)
+{
+ return sudo_secure_open(path, S_IFDIR, uid, gid, sb, error);
+}
+
+/*
+ * Open the first file found in a colon-separated list of paths.
+ * Subsequent files in the path are only attempted if the
+ * previous file does not exist. Errors other than ENOENT are
+ * considered fatal and will stop processing the path.
+ * Sets name based on the last file it tried to open, even on error.
+ */
+int
+sudo_open_conf_path_v1(const char *path, char *name, size_t namesize,
+ int (*fn)(const char *, int))
+{
+ const char *cp, *ep, *path_end;
+ int fd = -1;
+ debug_decl(sudo_open_conf_path, SUDO_DEBUG_UTIL);
+
+ path_end = path + strlen(path);
+ for (cp = sudo_strsplit(path, path_end, ":", &ep);
+ cp != NULL; cp = sudo_strsplit(NULL, path_end, ":", &ep)) {
+
+ const size_t len = (size_t)(ep - cp);
+ if (len >= namesize) {
+ /* We always set name, even on error. */
+ memcpy(name, cp, namesize - 1);
+ name[namesize - 1] = '\0';
+ errno = ENAMETOOLONG;
+ break;
+ }
+ memcpy(name, cp, len);
+ name[len] = '\0';
+
+ fd = fn ?
+ fn(name, O_RDONLY|O_NONBLOCK) : open(name, O_RDONLY|O_NONBLOCK);
+ if (fd != -1) {
+ (void)fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
+ break;
+ }
+ if (errno != ENOENT)
+ break;
+ }
+ debug_return_int(fd);
+}
diff --git a/lib/util/setgroups.c b/lib/util/setgroups.c
new file mode 100644
index 0000000..7298fcc
--- /dev/null
+++ b/lib/util/setgroups.c
@@ -0,0 +1,56 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011-2012, 2014-2016 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <grp.h>
+#include <limits.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+
+int
+sudo_setgroups_v1(int ngids, const GETGROUPS_T *gids)
+{
+ long maxgids;
+ int ret;
+ debug_decl(sudo_setgroups, SUDO_DEBUG_UTIL);
+
+ if (ngids < 0)
+ debug_return_int(-1);
+
+ ret = setgroups(ngids, (GETGROUPS_T *)gids);
+ if (ret == -1 && errno == EINVAL) {
+ /* Too many groups, try again with fewer. */
+ maxgids = sysconf(_SC_NGROUPS_MAX);
+ if (maxgids == -1)
+ maxgids = NGROUPS_MAX;
+ if (ngids > maxgids)
+ ret = setgroups(maxgids, (GETGROUPS_T *)gids);
+ }
+ debug_return_int(ret);
+}
diff --git a/lib/util/sha2.c b/lib/util/sha2.c
new file mode 100644
index 0000000..7ec6504
--- /dev/null
+++ b/lib/util/sha2.c
@@ -0,0 +1,515 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+/*
+ * Implementation of SHA-224, SHA-256, SHA-384 and SHA-512
+ * as per FIPS 180-4: Secure Hash Standard (SHS)
+ * http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
+ *
+ * Derived from the public domain SHA-1 and SHA-2 implementations
+ * by Steve Reid and Wei Dai respectively.
+ */
+
+#include <config.h>
+#include <string.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#if defined(HAVE_ENDIAN_H)
+# include <endian.h>
+#elif defined(HAVE_SYS_ENDIAN_H)
+# include <sys/endian.h>
+#elif defined(HAVE_MACHINE_ENDIAN_H)
+# include <machine/endian.h>
+#else
+# include <compat/endian.h>
+#endif
+
+#include <sudo_compat.h>
+#include <compat/sha2.h>
+
+/*
+ * SHA-2 operates on 32-bit and 64-bit words in big endian byte order.
+ * The following macros convert between character arrays and big endian words.
+ */
+#define BE8TO32(x, y) do { \
+ (x) = (((uint32_t)((y)[0] & 255) << 24) | \
+ ((uint32_t)((y)[1] & 255) << 16) | \
+ ((uint32_t)((y)[2] & 255) << 8) | \
+ ((uint32_t)((y)[3] & 255))); \
+} while (0)
+
+#define BE8TO64(x, y) do { \
+ (x) = (((uint64_t)((y)[0] & 255) << 56) | \
+ ((uint64_t)((y)[1] & 255) << 48) | \
+ ((uint64_t)((y)[2] & 255) << 40) | \
+ ((uint64_t)((y)[3] & 255) << 32) | \
+ ((uint64_t)((y)[4] & 255) << 24) | \
+ ((uint64_t)((y)[5] & 255) << 16) | \
+ ((uint64_t)((y)[6] & 255) << 8) | \
+ ((uint64_t)((y)[7] & 255))); \
+} while (0)
+
+#define BE32TO8(x, y) do { \
+ (x)[0] = (uint8_t)(((y) >> 24) & 255); \
+ (x)[1] = (uint8_t)(((y) >> 16) & 255); \
+ (x)[2] = (uint8_t)(((y) >> 8) & 255); \
+ (x)[3] = (uint8_t)((y) & 255); \
+} while (0)
+
+#define BE64TO8(x, y) do { \
+ (x)[0] = (uint8_t)(((y) >> 56) & 255); \
+ (x)[1] = (uint8_t)(((y) >> 48) & 255); \
+ (x)[2] = (uint8_t)(((y) >> 40) & 255); \
+ (x)[3] = (uint8_t)(((y) >> 32) & 255); \
+ (x)[4] = (uint8_t)(((y) >> 24) & 255); \
+ (x)[5] = (uint8_t)(((y) >> 16) & 255); \
+ (x)[6] = (uint8_t)(((y) >> 8) & 255); \
+ (x)[7] = (uint8_t)((y) & 255); \
+} while (0)
+
+#define rotrFixed(x,y) (y ? ((x>>y) | (x<<(sizeof(x)*8-y))) : x)
+
+#define blk0(i) (W[i])
+#define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15]))
+
+#define Ch(x,y,z) (z^(x&(y^z)))
+#define Maj(x,y,z) (y^((x^y)&(y^z)))
+
+#define a(i) T[(0-i)&7]
+#define b(i) T[(1-i)&7]
+#define c(i) T[(2-i)&7]
+#define d(i) T[(3-i)&7]
+#define e(i) T[(4-i)&7]
+#define f(i) T[(5-i)&7]
+#define g(i) T[(6-i)&7]
+#define h(i) T[(7-i)&7]
+
+void
+SHA224Init(SHA2_CTX *ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->state.st32[0] = 0xc1059ed8UL;
+ ctx->state.st32[1] = 0x367cd507UL;
+ ctx->state.st32[2] = 0x3070dd17UL;
+ ctx->state.st32[3] = 0xf70e5939UL;
+ ctx->state.st32[4] = 0xffc00b31UL;
+ ctx->state.st32[5] = 0x68581511UL;
+ ctx->state.st32[6] = 0x64f98fa7UL;
+ ctx->state.st32[7] = 0xbefa4fa4UL;
+}
+
+void
+SHA224Transform(uint32_t state[8], const uint8_t buffer[SHA224_BLOCK_LENGTH])
+{
+ SHA256Transform(state, buffer);
+}
+
+void
+SHA224Update(SHA2_CTX *ctx, const uint8_t *data, size_t len)
+{
+ SHA256Update(ctx, data, len);
+}
+
+void
+SHA224Pad(SHA2_CTX *ctx)
+{
+ SHA256Pad(ctx);
+}
+
+void
+SHA224Final(uint8_t digest[SHA224_DIGEST_LENGTH], SHA2_CTX *ctx)
+{
+ SHA256Pad(ctx);
+ if (digest != NULL) {
+#if BYTE_ORDER == BIG_ENDIAN
+ memcpy(digest, ctx->state.st32, SHA224_DIGEST_LENGTH);
+#else
+ unsigned int i;
+
+ for (i = 0; i < 7; i++)
+ BE32TO8(digest + (i * 4), ctx->state.st32[i]);
+#endif
+ memset(ctx, 0, sizeof(*ctx));
+ }
+}
+
+static const uint32_t SHA256_K[64] = {
+ 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+ 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+ 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+ 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+ 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+ 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+ 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+ 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+ 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+ 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+ 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+ 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+ 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+ 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+ 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+ 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+void
+SHA256Init(SHA2_CTX *ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->state.st32[0] = 0x6a09e667UL;
+ ctx->state.st32[1] = 0xbb67ae85UL;
+ ctx->state.st32[2] = 0x3c6ef372UL;
+ ctx->state.st32[3] = 0xa54ff53aUL;
+ ctx->state.st32[4] = 0x510e527fUL;
+ ctx->state.st32[5] = 0x9b05688cUL;
+ ctx->state.st32[6] = 0x1f83d9abUL;
+ ctx->state.st32[7] = 0x5be0cd19UL;
+}
+
+/* Round macros for SHA256 */
+#define R(i) do { \
+ h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA256_K[i+j]+(j?blk2(i):blk0(i)); \
+ d(i)+=h(i); \
+ h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)); \
+} while (0)
+
+#define S0(x) (rotrFixed(x,2)^rotrFixed(x,13)^rotrFixed(x,22))
+#define S1(x) (rotrFixed(x,6)^rotrFixed(x,11)^rotrFixed(x,25))
+#define s0(x) (rotrFixed(x,7)^rotrFixed(x,18)^(x>>3))
+#define s1(x) (rotrFixed(x,17)^rotrFixed(x,19)^(x>>10))
+
+void
+SHA256Transform(uint32_t state[8], const uint8_t data[SHA256_BLOCK_LENGTH])
+{
+ uint32_t W[16];
+ uint32_t T[8];
+ unsigned int j;
+
+ /* Copy context state to working vars. */
+ memcpy(T, state, sizeof(T));
+ /* Copy data to W in big endian format. */
+#if BYTE_ORDER == BIG_ENDIAN
+ memcpy(W, data, sizeof(W));
+#else
+ for (j = 0; j < 16; j++) {
+ BE8TO32(W[j], data);
+ data += 4;
+ }
+#endif
+ /* 64 operations, partially loop unrolled. */
+ for (j = 0; j < 64; j += 16)
+ {
+ R( 0); R( 1); R( 2); R( 3);
+ R( 4); R( 5); R( 6); R( 7);
+ R( 8); R( 9); R(10); R(11);
+ R(12); R(13); R(14); R(15);
+ }
+ /* Add the working vars back into context state. */
+ state[0] += a(0);
+ state[1] += b(0);
+ state[2] += c(0);
+ state[3] += d(0);
+ state[4] += e(0);
+ state[5] += f(0);
+ state[6] += g(0);
+ state[7] += h(0);
+ /* Cleanup */
+ explicit_bzero(T, sizeof(T));
+ explicit_bzero(W, sizeof(W));
+}
+
+#undef S0
+#undef S1
+#undef s0
+#undef s1
+#undef R
+
+void
+SHA256Update(SHA2_CTX *ctx, const uint8_t *data, size_t len)
+{
+ size_t i = 0, j;
+
+ j = (size_t)((ctx->count[0] >> 3) & (SHA256_BLOCK_LENGTH - 1));
+ ctx->count[0] += ((uint64_t)len << 3);
+ if ((j + len) > SHA256_BLOCK_LENGTH - 1) {
+ memcpy(&ctx->buffer[j], data, (i = SHA256_BLOCK_LENGTH - j));
+ SHA256Transform(ctx->state.st32, ctx->buffer);
+ for ( ; i + SHA256_BLOCK_LENGTH - 1 < len; i += SHA256_BLOCK_LENGTH)
+ SHA256Transform(ctx->state.st32, (uint8_t *)&data[i]);
+ j = 0;
+ }
+ memcpy(&ctx->buffer[j], &data[i], len - i);
+}
+
+void
+SHA256Pad(SHA2_CTX *ctx)
+{
+ uint8_t finalcount[8];
+
+ /* Store unpadded message length in bits in big endian format. */
+ BE64TO8(finalcount, ctx->count[0]);
+
+ /* Append a '1' bit (0x80) to the message. */
+ SHA256Update(ctx, (uint8_t *)"\200", 1);
+
+ /* Pad message such that the resulting length modulo 512 is 448. */
+ while ((ctx->count[0] & 511) != 448)
+ SHA256Update(ctx, (uint8_t *)"\0", 1);
+
+ /* Append length of message in bits and do final SHA256Transform(). */
+ SHA256Update(ctx, finalcount, sizeof(finalcount));
+}
+
+void
+SHA256Final(uint8_t digest[SHA256_DIGEST_LENGTH], SHA2_CTX *ctx)
+{
+ SHA256Pad(ctx);
+ if (digest != NULL) {
+#if BYTE_ORDER == BIG_ENDIAN
+ memcpy(digest, ctx->state.st32, SHA256_DIGEST_LENGTH);
+#else
+ unsigned int i;
+
+ for (i = 0; i < 8; i++)
+ BE32TO8(digest + (i * 4), ctx->state.st32[i]);
+#endif
+ memset(ctx, 0, sizeof(*ctx));
+ }
+}
+
+void
+SHA384Init(SHA2_CTX *ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->state.st64[0] = 0xcbbb9d5dc1059ed8ULL;
+ ctx->state.st64[1] = 0x629a292a367cd507ULL;
+ ctx->state.st64[2] = 0x9159015a3070dd17ULL;
+ ctx->state.st64[3] = 0x152fecd8f70e5939ULL;
+ ctx->state.st64[4] = 0x67332667ffc00b31ULL;
+ ctx->state.st64[5] = 0x8eb44a8768581511ULL;
+ ctx->state.st64[6] = 0xdb0c2e0d64f98fa7ULL;
+ ctx->state.st64[7] = 0x47b5481dbefa4fa4ULL;
+}
+
+void
+SHA384Transform(uint64_t state[8], const uint8_t data[SHA384_BLOCK_LENGTH])
+{
+ SHA512Transform(state, data);
+}
+
+void
+SHA384Update(SHA2_CTX *ctx, const uint8_t *data, size_t len)
+{
+ SHA512Update(ctx, data, len);
+}
+
+void
+SHA384Pad(SHA2_CTX *ctx)
+{
+ SHA512Pad(ctx);
+}
+
+void
+SHA384Final(uint8_t digest[SHA384_DIGEST_LENGTH], SHA2_CTX *ctx)
+{
+ SHA384Pad(ctx);
+ if (digest != NULL) {
+#if BYTE_ORDER == BIG_ENDIAN
+ memcpy(digest, ctx->state.st64, SHA384_DIGEST_LENGTH);
+#else
+ unsigned int i;
+
+ for (i = 0; i < 6; i++)
+ BE64TO8(digest + (i * 8), ctx->state.st64[i]);
+#endif
+ memset(ctx, 0, sizeof(*ctx));
+ }
+}
+
+static const uint64_t SHA512_K[80] = {
+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+ 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+ 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+ 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+ 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+ 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+ 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+ 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+ 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+ 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+ 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+ 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+ 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+ 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+void
+SHA512Init(SHA2_CTX *ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->state.st64[0] = 0x6a09e667f3bcc908ULL;
+ ctx->state.st64[1] = 0xbb67ae8584caa73bULL;
+ ctx->state.st64[2] = 0x3c6ef372fe94f82bULL;
+ ctx->state.st64[3] = 0xa54ff53a5f1d36f1ULL;
+ ctx->state.st64[4] = 0x510e527fade682d1ULL;
+ ctx->state.st64[5] = 0x9b05688c2b3e6c1fULL;
+ ctx->state.st64[6] = 0x1f83d9abfb41bd6bULL;
+ ctx->state.st64[7] = 0x5be0cd19137e2179ULL;
+}
+
+/* Round macros for SHA512 */
+#define R(i) do { \
+ h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA512_K[i+j]+(j?blk2(i):blk0(i)); \
+ d(i)+=h(i); \
+ h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)); \
+} while (0)
+
+#define S0(x) (rotrFixed(x,28)^rotrFixed(x,34)^rotrFixed(x,39))
+#define S1(x) (rotrFixed(x,14)^rotrFixed(x,18)^rotrFixed(x,41))
+#define s0(x) (rotrFixed(x,1)^rotrFixed(x,8)^(x>>7))
+#define s1(x) (rotrFixed(x,19)^rotrFixed(x,61)^(x>>6))
+
+void
+SHA512Transform(uint64_t state[8], const uint8_t data[SHA512_BLOCK_LENGTH])
+{
+ uint64_t W[16];
+ uint64_t T[8];
+ unsigned int j;
+
+ /* Copy context state to working vars. */
+ memcpy(T, state, sizeof(T));
+ /* Copy data to W in big endian format. */
+#if BYTE_ORDER == BIG_ENDIAN
+ memcpy(W, data, sizeof(W));
+#else
+ for (j = 0; j < 16; j++) {
+ BE8TO64(W[j], data);
+ data += 8;
+ }
+#endif
+ /* 80 operations, partially loop unrolled. */
+ for (j = 0; j < 80; j += 16)
+ {
+ R( 0); R( 1); R( 2); R( 3);
+ R( 4); R( 5); R( 6); R( 7);
+ R( 8); R( 9); R(10); R(11);
+ R(12); R(13); R(14); R(15);
+ }
+ /* Add the working vars back into context state. */
+ state[0] += a(0);
+ state[1] += b(0);
+ state[2] += c(0);
+ state[3] += d(0);
+ state[4] += e(0);
+ state[5] += f(0);
+ state[6] += g(0);
+ state[7] += h(0);
+ /* Cleanup. */
+ explicit_bzero(T, sizeof(T));
+ explicit_bzero(W, sizeof(W));
+}
+
+void
+SHA512Update(SHA2_CTX *ctx, const uint8_t *data, size_t len)
+{
+ size_t i = 0, j;
+
+ j = (size_t)((ctx->count[0] >> 3) & (SHA512_BLOCK_LENGTH - 1));
+ ctx->count[0] += ((uint64_t)len << 3);
+ if (ctx->count[0] < ((uint64_t)len << 3))
+ ctx->count[1]++;
+ if ((j + len) > SHA512_BLOCK_LENGTH - 1) {
+ memcpy(&ctx->buffer[j], data, (i = SHA512_BLOCK_LENGTH - j));
+ SHA512Transform(ctx->state.st64, ctx->buffer);
+ for ( ; i + SHA512_BLOCK_LENGTH - 1 < len; i += SHA512_BLOCK_LENGTH)
+ SHA512Transform(ctx->state.st64, (uint8_t *)&data[i]);
+ j = 0;
+ }
+ memcpy(&ctx->buffer[j], &data[i], len - i);
+}
+
+void
+SHA512Pad(SHA2_CTX *ctx)
+{
+ uint8_t finalcount[16];
+
+ /* Store unpadded message length in bits in big endian format. */
+ BE64TO8(finalcount, ctx->count[1]);
+ BE64TO8(finalcount + 8, ctx->count[0]);
+
+ /* Append a '1' bit (0x80) to the message. */
+ SHA512Update(ctx, (uint8_t *)"\200", 1);
+
+ /* Pad message such that the resulting length modulo 1024 is 896. */
+ while ((ctx->count[0] & 1023) != 896)
+ SHA512Update(ctx, (uint8_t *)"\0", 1);
+
+ /* Append length of message in bits and do final SHA512Transform(). */
+ SHA512Update(ctx, finalcount, sizeof(finalcount));
+}
+
+void
+SHA512Final(uint8_t digest[SHA512_DIGEST_LENGTH], SHA2_CTX *ctx)
+{
+ SHA512Pad(ctx);
+ if (digest != NULL) {
+#if BYTE_ORDER == BIG_ENDIAN
+ memcpy(digest, ctx->state.st64, SHA512_DIGEST_LENGTH);
+#else
+ unsigned int i;
+
+ for (i = 0; i < 8; i++)
+ BE64TO8(digest + (i * 8), ctx->state.st64[i]);
+#endif
+ memset(ctx, 0, sizeof(*ctx));
+ }
+}
diff --git a/lib/util/sig2str.c b/lib/util/sig2str.c
new file mode 100644
index 0000000..11acc5e
--- /dev/null
+++ b/lib/util/sig2str.c
@@ -0,0 +1,100 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2012-2015, 2017-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_SIG2STR
+
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+#if !defined(HAVE_SIGABBREV_NP)
+# if defined(HAVE_DECL_SYS_SIGNAME) && HAVE_DECL_SYS_SIGNAME == 1
+# define sigabbrev_np(_x) sys_signame[(_x)]
+# elif defined(HAVE_DECL__SYS_SIGNAME) && HAVE_DECL__SYS_SIGNAME == 1
+# define sigabbrev_np(_x) _sys_signame[(_x)]
+# elif defined(HAVE_SYS_SIGABBREV)
+# define sigabbrev_np(_x) sys_sigabbrev[(_x)]
+# if defined(HAVE_DECL_SYS_SIGABBREV) && HAVE_DECL_SYS_SIGABBREV == 0
+ /* sys_sigabbrev is not declared by glibc */
+ extern const char *const sys_sigabbrev[NSIG];
+# endif
+# else
+# define sigabbrev_np(_x) sudo_sys_signame[(_x)]
+ extern const char *const sudo_sys_signame[NSIG];
+# endif
+#endif /* !HAVE_SIGABBREV_NP */
+
+/*
+ * Translate signal number to name.
+ */
+int
+sudo_sig2str(int signo, char *signame)
+{
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+ /* Realtime signal support. */
+ if (signo >= SIGRTMIN && signo <= SIGRTMAX) {
+# ifdef _SC_RTSIG_MAX
+ const long rtmax = sysconf(_SC_RTSIG_MAX);
+# else
+ const long rtmax = SIGRTMAX - SIGRTMIN;
+# endif
+ if (rtmax > 0) {
+ if (signo == SIGRTMIN) {
+ strlcpy(signame, "RTMIN", SIG2STR_MAX);
+ } else if (signo == SIGRTMAX) {
+ strlcpy(signame, "RTMAX", SIG2STR_MAX);
+ } else if (signo <= SIGRTMIN + (rtmax / 2) - 1) {
+ (void)snprintf(signame, SIG2STR_MAX, "RTMIN+%d",
+ (signo - SIGRTMIN));
+ } else {
+ (void)snprintf(signame, SIG2STR_MAX, "RTMAX-%d",
+ (SIGRTMAX - signo));
+ }
+ }
+ return 0;
+ }
+#endif
+ if (signo > 0 && signo < NSIG) {
+ const char *cp = sigabbrev_np(signo);
+ if (cp != NULL) {
+ strlcpy(signame, cp, SIG2STR_MAX);
+ /* Make sure we always return an upper case signame. */
+ if (islower((unsigned char)signame[0])) {
+ size_t i;
+ for (i = 0; signame[i] != '\0'; i++)
+ signame[i] = (char)toupper((unsigned char)signame[i]);
+ }
+ return 0;
+ }
+ }
+ errno = EINVAL;
+ return -1;
+}
+#endif /* HAVE_SIG2STR */
diff --git a/lib/util/siglist.in b/lib/util/siglist.in
new file mode 100644
index 0000000..aa57a7a
--- /dev/null
+++ b/lib/util/siglist.in
@@ -0,0 +1,56 @@
+#
+# List of signals used to build sys_siglist (see mksiglist.c)
+# Adapted from pdksh; public domain
+#
+# Note that if a system has multiple defines for the same signal
+# (eg, SIGABRT vs SIGIOT, SIGCHLD vs SIGCLD), only the first one
+# will be seen, so the order in this list is important.
+#
+ HUP Hangup
+ INT Interrupt
+ QUIT Quit
+ ILL Illegal instruction
+ TRAP Trace trap
+# before IOT (ABRT is posix and ABRT is sometimes the same as IOT)
+ ABRT Abort
+ IOT IOT instruction
+ EMT EMT trap
+ FPE Floating point exception
+ KILL Killed
+ BUS Bus error
+ SEGV Memory fault
+# before UNUSED (SYS and UNUSED share the same value in musl libc).
+ SYS Bad system call
+ UNUSED Unused
+ PIPE Broken pipe
+ ALRM Alarm clock
+ TERM Terminated
+ STKFLT Stack fault
+# before POLL (POLL is sometimes the same as IO)
+ IO I/O possible
+ XCPU CPU time limit exceeded
+ XFSZ File size limit exceeded
+ VTALRM Virtual timer expired
+ PROF Profiling timer expired
+ WINCH Window size change
+ LOST File lock lost
+ USR1 User defined signal 1
+ USR2 User defined signal 2
+ PWR Power-fail/Restart
+ POLL Pollable event occurred
+ STOP Stopped (signal)
+ TSTP Stopped
+ CONT Continued
+# before CLD (CHLD is posix and CHLD is sometimes the same as CLD)
+ CHLD Child exited
+ CLD Child exited
+ TTIN Stopped (tty input)
+ TTOU Stopped (tty output)
+ INFO Information request
+ URG Urgent I/O condition
+# Solaris (svr4?) signals
+ WAITING No runnable LWPs
+ LWP Inter-LWP signal
+ FREEZE Checkpoint freeze
+ THAW Checkpoint thaw
+ CANCEL Thread cancellation
diff --git a/lib/util/snprintf.c b/lib/util/snprintf.c
new file mode 100644
index 0000000..64765da
--- /dev/null
+++ b/lib/util/snprintf.c
@@ -0,0 +1,1546 @@
+/* $OpenBSD: vfprintf.c,v 1.67 2014/12/21 00:23:30 daniel Exp $ */
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1999-2005, 2008, 2010-2016
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * From: @(#)vfprintf.c 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * v?snprintf/v?asprintf based on OpenBSD vfprintf.c.
+ */
+
+#include <config.h>
+
+#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_SNPRINTF) || \
+ !defined(HAVE_VASPRINTF) || !defined(HAVE_ASPRINTF) || \
+ defined(PREFER_PORTABLE_SNPRINTF)
+
+#include <errno.h>
+#ifdef HAVE_NL_LANGINFO
+# include <langinfo.h>
+#endif
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stddef.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef PRINTF_WIDE_CHAR
+# include <wchar.h>
+#endif
+#include <fcntl.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+/* Avoid printf format attacks by ignoring the %n escape. */
+#define NO_PRINTF_PERCENT_N
+
+union arg {
+ int intarg;
+ unsigned int uintarg;
+ long longarg;
+ unsigned long ulongarg;
+ long long longlongarg;
+ unsigned long long ulonglongarg;
+ ptrdiff_t ptrdiffarg;
+ size_t sizearg;
+ ssize_t ssizearg;
+ intmax_t intmaxarg;
+ uintmax_t uintmaxarg;
+ void *pvoidarg;
+ char *pchararg;
+ signed char *pschararg;
+ short *pshortarg;
+ int *pintarg;
+ long *plongarg;
+ long long *plonglongarg;
+ ptrdiff_t *pptrdiffarg;
+ ssize_t *pssizearg;
+ intmax_t *pintmaxarg;
+#ifdef FLOATING_POINT
+ double doublearg;
+ long double longdoublearg;
+#endif
+#ifdef PRINTF_WIDE_CHAR
+ wint_t wintarg;
+ wchar_t *pwchararg;
+#endif
+};
+
+static int __find_arguments(const char * restrict fmt0, va_list ap, union arg **argtable);
+static int __grow_type_table(unsigned char **typetable, int *tablesize);
+static int xxxprintf(char ** restrict, size_t, int, const char * restrict, va_list);
+
+#ifdef PRINTF_WIDE_CHAR
+/*
+ * Convert a wide character string argument for the %ls format to a multibyte
+ * string representation. If not -1, prec specifies the maximum number of
+ * bytes to output, and also means that we can't assume that the wide char
+ * string is null-terminated.
+ */
+static char *
+__wcsconv(wchar_t *wcsarg, int prec)
+{
+ mbstate_t mbs;
+ char buf[MB_LEN_MAX];
+ wchar_t *p;
+ char *convbuf;
+ size_t clen, nbytes;
+
+ /* Allocate space for the maximum number of bytes we could output. */
+ if (prec < 0) {
+ memset(&mbs, 0, sizeof(mbs));
+ p = wcsarg;
+ nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
+ if (nbytes == (size_t)-1)
+ return NULL;
+ } else {
+ /*
+ * Optimisation: if the output precision is small enough,
+ * just allocate enough memory for the maximum instead of
+ * scanning the string.
+ */
+ if (prec < 128)
+ nbytes = prec;
+ else {
+ nbytes = 0;
+ p = wcsarg;
+ memset(&mbs, 0, sizeof(mbs));
+ for (;;) {
+ clen = wcrtomb(buf, *p++, &mbs);
+ if (clen == 0 || clen == (size_t)-1 ||
+ nbytes + clen > (size_t)prec)
+ break;
+ nbytes += clen;
+ }
+ if (clen == (size_t)-1)
+ return NULL;
+ }
+ }
+ if ((convbuf = malloc(nbytes + 1)) == NULL)
+ return NULL;
+
+ /* Fill the output buffer. */
+ p = wcsarg;
+ memset(&mbs, 0, sizeof(mbs));
+ if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p,
+ nbytes, &mbs)) == (size_t)-1) {
+ free(convbuf);
+ return NULL;
+ }
+ convbuf[nbytes] = '\0';
+ return convbuf;
+}
+#endif
+
+#ifdef FLOATING_POINT
+#include <float.h>
+#include <locale.h>
+#include <math.h>
+#include "floatio.h"
+#include "gdtoa.h"
+
+#define DEFPREC 6
+
+static int exponent(char *, int, int);
+#endif /* FLOATING_POINT */
+
+/*
+ * The size of the buffer we use as scratch space for integer
+ * conversions, among other things. Technically, we would need the
+ * most space for base 10 conversions with thousands' grouping
+ * characters between each pair of digits. 100 bytes is a
+ * conservative overestimate even for a 128-bit uintmax_t.
+ */
+#define BUF 100
+
+#define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */
+
+
+/*
+ * Macros for converting digits to letters and vice versa
+ */
+#define to_digit(c) ((c) - '0')
+#define is_digit(c) ((unsigned int)to_digit(c) <= 9)
+#define to_char(n) ((n) + '0')
+
+/*
+ * Flags used during conversion.
+ */
+#define ALT 0x0001 /* alternate form */
+#define LADJUST 0x0004 /* left adjustment */
+#define LONGDBL 0x0008 /* long double */
+#define LONGINT 0x0010 /* long integer */
+#define LLONGINT 0x0020 /* long long integer */
+#define SHORTINT 0x0040 /* short integer */
+#define ZEROPAD 0x0080 /* zero (as opposed to blank) pad */
+#define FPT 0x0100 /* Floating point number */
+#define PTRINT 0x0200 /* (unsigned) ptrdiff_t */
+#define SIZEINT 0x0400 /* (signed) size_t */
+#define CHARINT 0x0800 /* 8 bit integer */
+#undef MAXINT /* Also defined by HP-UX param.h... */
+#define MAXINT 0x1000 /* largest integer size (intmax_t) */
+
+/*
+ * Actual printf innards.
+ */
+static int
+xxxprintf(char ** restrict strp, size_t strsize, int alloc, const char * restrict fmt0, va_list ap)
+{
+ char *fmt; /* format string */
+ int ch; /* character from fmt */
+ int n; /* handy integers (short term usage) */
+ char *cp; /* handy char pointer (short term usage) */
+ int flags; /* flags as above */
+ int ret; /* return value accumulator */
+ int width; /* width from format (%8d), or 0 */
+ int prec; /* precision from format; <0 for N/A */
+ char sign; /* sign prefix (' ', '+', '-', or \0) */
+#ifdef FLOATING_POINT
+ /*
+ * We can decompose the printed representation of floating
+ * point numbers into several parts, some of which may be empty:
+ *
+ * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
+ * A B ---C--- D E F
+ *
+ * A: 'sign' holds this value if present; '\0' otherwise
+ * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
+ * C: cp points to the string MMMNNN. Leading and trailing
+ * zeros are not in the string and must be added.
+ * D: expchar holds this character; '\0' if no exponent, e.g. %f
+ * F: at least two digits for decimal, at least one digit for hex
+ */
+#ifdef HAVE_NL_LANGINFO
+ const char *decimal_point = NULL;
+#else
+ const char *decimal_point = ".";
+#endif
+ int signflag; /* true if float is negative */
+ union { /* floating point arguments %[aAeEfFgG] */
+ double dbl;
+ long double ldbl;
+ } fparg;
+ int expt; /* integer value of exponent */
+ char expchar; /* exponent character: [eEpP\0] */
+ char *dtoaend; /* pointer to end of converted digits */
+ int expsize; /* character count for expstr */
+ int lead; /* sig figs before decimal or group sep */
+ int ndig; /* actual number of digits returned by dtoa */
+ char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
+ char *dtoaresult = NULL;
+#endif
+
+ uintmax_t _umax; /* integer arguments %[diouxX] */
+ enum { OCT, DEC, HEX } base; /* base for %[diouxX] conversion */
+ int dprec; /* a copy of prec if %[diouxX], 0 otherwise */
+ int realsz; /* field size expanded by dprec */
+ int size; /* size of converted field or string */
+ const char *xdigs = ""; /* digits for %[xX] conversion */
+#define NIOV 8
+ char buf[BUF]; /* buffer with space for digits of uintmax_t */
+ char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */
+ char *str; /* pointer to string to fill */
+ char *estr; /* pointer to last char in str */
+ union arg *argtable; /* args, built due to positional arg */
+ union arg statargtable[STATIC_ARG_TBL_SIZE];
+ int nextarg; /* 1-based argument index */
+ va_list orgap; /* original argument pointer */
+#ifdef PRINTF_WIDE_CHAR
+ char *convbuf; /* buffer for wide to multi-byte conversion */
+#endif
+
+ /*
+ * Choose PADSIZE to trade efficiency vs. size. If larger printf
+ * fields occur frequently, increase PADSIZE and make the initialisers
+ * below longer.
+ */
+#define PADSIZE 16 /* pad chunk size */
+ static char blanks[PADSIZE] =
+ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
+ static char zeroes[PADSIZE] =
+ {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
+
+ static const char xdigs_lower[16] = "0123456789abcdef";
+ static const char xdigs_upper[16] = "0123456789ABCDEF";
+
+ /*
+ * BEWARE, these `goto done' on error, and PAD uses `n'.
+ */
+ /* Print chars to "str", (allocate as needed if alloc is set). */
+#define PRINT(ptr, len) do { \
+ const char *p = ptr; \
+ const char *endp = ptr + len; \
+ while (p < endp && (str < estr || alloc)) { \
+ if (alloc && str >= estr) { \
+ char *t; \
+ strsize = (strsize << 1) + 1; \
+ if (!(t = realloc(*strp, strsize))) { \
+ free(str); \
+ *strp = NULL; \
+ ret = -1; \
+ goto done; \
+ } \
+ str = t + (str - *strp); \
+ estr = t + strsize - 1; \
+ *strp = t; \
+ } \
+ *str++ = *p++; \
+ } \
+} while (0)
+
+#define PAD(plen, pstr) do { \
+ if ((n = (plen)) > 0) { \
+ while (n > PADSIZE) { \
+ PRINT(pstr, PADSIZE); \
+ n -= PADSIZE; \
+ } \
+ PRINT(pstr, n); \
+ } \
+} while (0)
+#define PRINTANDPAD(p, ep, len, with) do { \
+ int n2 = (ep) - (p); \
+ if (n2 > (len)) \
+ n2 = (len); \
+ if (n2 > 0) \
+ PRINT((p), n2); \
+ PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
+} while(0)
+
+ /*
+ * To extend shorts properly, we need both signed and unsigned
+ * argument extraction methods.
+ */
+#define SARG() \
+ ((intmax_t)(flags&MAXINT ? GETARG(intmax_t) : \
+ flags&LLONGINT ? GETARG(long long) : \
+ flags&LONGINT ? GETARG(long) : \
+ flags&PTRINT ? GETARG(ptrdiff_t) : \
+ flags&SIZEINT ? GETARG(ssize_t) : \
+ flags&SHORTINT ? (short)GETARG(int) : \
+ flags&CHARINT ? (signed char)GETARG(int) : \
+ GETARG(int)))
+#define UARG() \
+ ((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \
+ flags&LLONGINT ? GETARG(unsigned long long) : \
+ flags&LONGINT ? GETARG(unsigned long) : \
+ flags&PTRINT ? (uintptr_t)GETARG(ptrdiff_t) : /* XXX */ \
+ flags&SIZEINT ? GETARG(size_t) : \
+ flags&SHORTINT ? (unsigned short)GETARG(int) : \
+ flags&CHARINT ? (unsigned char)GETARG(int) : \
+ GETARG(unsigned int)))
+
+ /*
+ * Append a digit to a value and check for overflow.
+ */
+#define APPEND_DIGIT(val, dig) do { \
+ if ((val) > INT_MAX / 10) \
+ goto overflow; \
+ (val) *= 10; \
+ if ((val) > INT_MAX - to_digit((dig))) \
+ goto overflow; \
+ (val) += to_digit((dig)); \
+} while (0)
+
+ /*
+ * Get * arguments, including the form *nn$. Preserve the nextarg
+ * that the argument can be gotten once the type is determined.
+ */
+#define GETASTER(val) do { \
+ int n2 = 0; \
+ cp = fmt; \
+ while (is_digit(*cp)) { \
+ APPEND_DIGIT(n2, *cp); \
+ cp++; \
+ } \
+ if (*cp == '$') { \
+ int hold = nextarg; \
+ if (argtable == NULL) { \
+ argtable = statargtable; \
+ if (__find_arguments(fmt0, orgap, &argtable) == -1) { \
+ ret = -1; \
+ goto done; \
+ } \
+ } \
+ nextarg = n2; \
+ val = GETARG(int); \
+ nextarg = hold; \
+ fmt = ++cp; \
+ } else { \
+ val = GETARG(int); \
+ } \
+} while (0)
+
+/*
+* Get the argument indexed by nextarg. If the argument table is
+* built, use it to get the argument. If its not, get the next
+* argument (and arguments must be gotten sequentially).
+*/
+#define GETARG(type) \
+ ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
+ (nextarg++, va_arg(ap, type)))
+
+ fmt = (char *)fmt0;
+ argtable = NULL;
+ nextarg = 1;
+ va_copy(orgap, ap);
+ ret = 0;
+#ifdef PRINTF_WIDE_CHAR
+ convbuf = NULL;
+#endif
+
+ if (alloc) {
+ strsize = 128;
+ *strp = str = malloc(strsize);
+ if (str == NULL) {
+ ret = -1;
+ goto done;
+ }
+ estr = str + 127;
+ } else {
+ str = *strp;
+ if (strsize)
+ estr = str + strsize - 1;
+ else
+ estr = NULL;
+ }
+
+ /*
+ * Scan the format for conversions (`%' character).
+ */
+ for (;;) {
+ for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
+ continue;
+
+ if (fmt != cp) {
+ ptrdiff_t m = fmt - cp;
+ if (m < 0 || m > INT_MAX - ret)
+ goto overflow;
+ PRINT(cp, m);
+ ret += m;
+ }
+ if (ch == '\0')
+ goto done;
+ fmt++; /* skip over '%' */
+
+ flags = 0;
+ dprec = 0;
+ width = 0;
+ prec = -1;
+ sign = '\0';
+ ox[1] = '\0';
+
+rflag: ch = *fmt++;
+reswitch: switch (ch) {
+ case ' ':
+ /*
+ * ``If the space and + flags both appear, the space
+ * flag will be ignored.''
+ * -- ANSI X3J11
+ */
+ if (!sign)
+ sign = ' ';
+ goto rflag;
+ case '#':
+ flags |= ALT;
+ goto rflag;
+ case '\'':
+ /* grouping not implemented */
+ goto rflag;
+ case '*':
+ /*
+ * ``A negative field width argument is taken as a
+ * - flag followed by a positive field width.''
+ * -- ANSI X3J11
+ * They don't exclude field widths read from args.
+ */
+ GETASTER(width);
+ if (width >= 0)
+ goto rflag;
+ if (width == INT_MIN)
+ goto overflow;
+ width = -width;
+ FALLTHROUGH;
+ case '-':
+ flags |= LADJUST;
+ goto rflag;
+ case '+':
+ sign = '+';
+ goto rflag;
+ case '.':
+ if ((ch = *fmt++) == '*') {
+ GETASTER(n);
+ prec = n < 0 ? -1 : n;
+ goto rflag;
+ }
+ n = 0;
+ while (is_digit(ch)) {
+ APPEND_DIGIT(n, ch);
+ ch = *fmt++;
+ }
+ if (ch == '$') {
+ nextarg = n;
+ if (argtable == NULL) {
+ argtable = statargtable;
+ if (__find_arguments(fmt0, orgap,
+ &argtable) == -1) {
+ ret = -1;
+ goto done;
+ }
+ }
+ goto rflag;
+ }
+ prec = n;
+ goto reswitch;
+ case '0':
+ /*
+ * ``Note that 0 is taken as a flag, not as the
+ * beginning of a field width.''
+ * -- ANSI X3J11
+ */
+ flags |= ZEROPAD;
+ goto rflag;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = 0;
+ do {
+ APPEND_DIGIT(n, ch);
+ ch = *fmt++;
+ } while (is_digit(ch));
+ if (ch == '$') {
+ nextarg = n;
+ if (argtable == NULL) {
+ argtable = statargtable;
+ if (__find_arguments(fmt0, orgap,
+ &argtable) == -1) {
+ ret = -1;
+ goto done;
+ }
+ }
+ goto rflag;
+ }
+ width = n;
+ goto reswitch;
+#ifdef FLOATING_POINT
+ case 'L':
+ flags |= LONGDBL;
+ goto rflag;
+#endif
+ case 'h':
+ if (*fmt == 'h') {
+ fmt++;
+ flags |= CHARINT;
+ } else {
+ flags |= SHORTINT;
+ }
+ goto rflag;
+ case 'j':
+ flags |= MAXINT;
+ goto rflag;
+ case 'l':
+ if (*fmt == 'l') {
+ fmt++;
+ flags |= LLONGINT;
+ } else {
+ flags |= LONGINT;
+ }
+ goto rflag;
+ case 'q':
+ flags |= LLONGINT;
+ goto rflag;
+ case 't':
+ flags |= PTRINT;
+ goto rflag;
+ case 'z':
+ flags |= SIZEINT;
+ goto rflag;
+ case 'c':
+#ifdef PRINTF_WIDE_CHAR
+ if (flags & LONGINT) {
+ mbstate_t mbs;
+ size_t mbseqlen;
+
+ memset(&mbs, 0, sizeof(mbs));
+ mbseqlen = wcrtomb(buf,
+ (wchar_t)GETARG(wint_t), &mbs);
+ if (mbseqlen == (size_t)-1) {
+ ret = -1;
+ goto done;
+ }
+ cp = buf;
+ size = (int)mbseqlen;
+ } else {
+#endif
+ *(cp = buf) = GETARG(int);
+ size = 1;
+#ifdef PRINTF_WIDE_CHAR
+ }
+#endif
+ sign = '\0';
+ break;
+ case 'D':
+ flags |= LONGINT;
+ FALLTHROUGH;
+ case 'd':
+ case 'i':
+ _umax = SARG();
+ if ((intmax_t)_umax < 0) {
+ _umax = -_umax;
+ sign = '-';
+ }
+ base = DEC;
+ goto number;
+#ifdef FLOATING_POINT
+ case 'a':
+ case 'A':
+ if (ch == 'a') {
+ ox[1] = 'x';
+ xdigs = xdigs_lower;
+ expchar = 'p';
+ } else {
+ ox[1] = 'X';
+ xdigs = xdigs_upper;
+ expchar = 'P';
+ }
+ if (prec >= 0)
+ prec++;
+ if (dtoaresult)
+ __freedtoa(dtoaresult);
+ if (flags & LONGDBL) {
+ fparg.ldbl = GETARG(long double);
+ dtoaresult = cp =
+ __hldtoa(fparg.ldbl, xdigs, prec,
+ &expt, &signflag, &dtoaend);
+ if (dtoaresult == NULL) {
+ errno = ENOMEM;
+ goto done;
+ }
+ } else {
+ fparg.dbl = GETARG(double);
+ dtoaresult = cp =
+ __hdtoa(fparg.dbl, xdigs, prec,
+ &expt, &signflag, &dtoaend);
+ if (dtoaresult == NULL) {
+ errno = ENOMEM;
+ goto done;
+ }
+ }
+ if (prec < 0)
+ prec = dtoaend - cp;
+ if (expt == INT_MAX)
+ ox[1] = '\0';
+ goto fp_common;
+ case 'e':
+ case 'E':
+ expchar = ch;
+ if (prec < 0) /* account for digit before decpt */
+ prec = DEFPREC + 1;
+ else
+ prec++;
+ goto fp_begin;
+ case 'f':
+ case 'F':
+ expchar = '\0';
+ goto fp_begin;
+ case 'g':
+ case 'G':
+ expchar = ch - ('g' - 'e');
+ if (prec == 0)
+ prec = 1;
+fp_begin:
+ if (prec < 0)
+ prec = DEFPREC;
+ if (dtoaresult)
+ __freedtoa(dtoaresult);
+ if (flags & LONGDBL) {
+ fparg.ldbl = GETARG(long double);
+ dtoaresult = cp =
+ __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
+ &expt, &signflag, &dtoaend);
+ if (dtoaresult == NULL) {
+ errno = ENOMEM;
+ goto done;
+ }
+ } else {
+ fparg.dbl = GETARG(double);
+ dtoaresult = cp =
+ __dtoa(fparg.dbl, expchar ? 2 : 3, prec,
+ &expt, &signflag, &dtoaend);
+ if (dtoaresult == NULL) {
+ errno = ENOMEM;
+ goto done;
+ }
+ if (expt == 9999)
+ expt = INT_MAX;
+ }
+fp_common:
+ if (signflag)
+ sign = '-';
+ if (expt == INT_MAX) { /* inf or nan */
+ if (*cp == 'N')
+ cp = (ch >= 'a') ? "nan" : "NAN";
+ else
+ cp = (ch >= 'a') ? "inf" : "INF";
+ size = 3;
+ flags &= ~ZEROPAD;
+ break;
+ }
+ flags |= FPT;
+ ndig = dtoaend - cp;
+ if (ch == 'g' || ch == 'G') {
+ if (expt > -4 && expt <= prec) {
+ /* Make %[gG] smell like %[fF] */
+ expchar = '\0';
+ if (flags & ALT)
+ prec -= expt;
+ else
+ prec = ndig - expt;
+ if (prec < 0)
+ prec = 0;
+ } else {
+ /*
+ * Make %[gG] smell like %[eE], but
+ * trim trailing zeroes if no # flag.
+ */
+ if (!(flags & ALT))
+ prec = ndig;
+ }
+ }
+ if (expchar) {
+ expsize = exponent(expstr, expt - 1, expchar);
+ size = expsize + prec;
+ if (prec > 1 || flags & ALT)
+ ++size;
+ } else {
+ /* space for digits before decimal point */
+ if (expt > 0)
+ size = expt;
+ else /* "0" */
+ size = 1;
+ /* space for decimal pt and following digits */
+ if (prec || flags & ALT)
+ size += prec + 1;
+ lead = expt;
+ }
+ break;
+#endif /* FLOATING_POINT */
+#ifndef NO_PRINTF_PERCENT_N
+ case 'n':
+ if (flags & LLONGINT)
+ *GETARG(long long *) = ret;
+ else if (flags & LONGINT)
+ *GETARG(long *) = ret;
+ else if (flags & SHORTINT)
+ *GETARG(short *) = ret;
+ else if (flags & CHARINT)
+ *GETARG(signed char *) = ret;
+ else if (flags & PTRINT)
+ *GETARG(ptrdiff_t *) = ret;
+ else if (flags & SIZEINT)
+ *GETARG(ssize_t *) = ret;
+ else if (flags & MAXINT)
+ *GETARG(intmax_t *) = ret;
+ else
+ *GETARG(int *) = ret;
+ continue; /* no output */
+#endif /* NO_PRINTF_PERCENT_N */
+ case 'O':
+ flags |= LONGINT;
+ FALLTHROUGH;
+ case 'o':
+ _umax = UARG();
+ base = OCT;
+ goto nosign;
+ case 'p':
+ /*
+ * ``The argument shall be a pointer to void. The
+ * value of the pointer is converted to a sequence
+ * of printable characters, in an implementation-
+ * defined manner.''
+ * -- ANSI X3J11
+ */
+ /* NOSTRICT */
+ _umax = (u_long)GETARG(void *);
+ base = HEX;
+ xdigs = xdigs_lower;
+ ox[1] = 'x';
+ goto nosign;
+ case 's': {
+ size_t len;
+
+#ifdef PRINTF_WIDE_CHAR
+ if (flags & LONGINT) {
+ wchar_t *wcp;
+
+ free(convbuf);
+ convbuf = NULL;
+ if ((wcp = GETARG(wchar_t *)) == NULL) {
+ cp = (char *)"(null)";
+ } else {
+ convbuf = __wcsconv(wcp, prec);
+ if (convbuf == NULL) {
+ ret = -1;
+ goto done;
+ }
+ cp = convbuf;
+ }
+ } else
+#endif /* PRINTF_WIDE_CHAR */
+ if ((cp = GETARG(char *)) == NULL)
+ cp = (char *)"(null)";
+ len = prec >= 0 ? strnlen(cp, prec) : strlen(cp);
+ if (len > INT_MAX)
+ goto overflow;
+ size = (int)len;
+ sign = '\0';
+ }
+ break;
+ case 'U':
+ flags |= LONGINT;
+ FALLTHROUGH;
+ case 'u':
+ _umax = UARG();
+ base = DEC;
+ goto nosign;
+ case 'X':
+ xdigs = xdigs_upper;
+ goto hex;
+ case 'x':
+ xdigs = xdigs_lower;
+hex: _umax = UARG();
+ base = HEX;
+ /* leading 0x/X only if non-zero */
+ if (flags & ALT && _umax != 0)
+ ox[1] = ch;
+
+ /* unsigned conversions */
+nosign: sign = '\0';
+ /*
+ * ``... diouXx conversions ... if a precision is
+ * specified, the 0 flag will be ignored.''
+ * -- ANSI X3J11
+ */
+number: if ((dprec = prec) >= 0)
+ flags &= ~ZEROPAD;
+
+ /*
+ * ``The result of converting a zero value with an
+ * explicit precision of zero is no characters.''
+ * -- ANSI X3J11
+ */
+ cp = buf + BUF;
+ if (_umax != 0 || prec != 0) {
+ /*
+ * Unsigned mod is hard, and unsigned mod
+ * by a constant is easier than that by
+ * a variable; hence this switch.
+ */
+ switch (base) {
+ case OCT:
+ do {
+ *--cp = to_char(_umax & 7);
+ _umax >>= 3;
+ } while (_umax);
+ /* handle octal leading 0 */
+ if (flags & ALT && *cp != '0')
+ *--cp = '0';
+ break;
+
+ case DEC:
+ /* many numbers are 1 digit */
+ while (_umax >= 10) {
+ *--cp = to_char(_umax % 10);
+ _umax /= 10;
+ }
+ *--cp = to_char(_umax);
+ break;
+
+ case HEX:
+ do {
+ *--cp = xdigs[_umax & 15];
+ _umax >>= 4;
+ } while (_umax);
+ break;
+
+ default:
+ cp = (char *)"bug in xxxprintf: bad base";
+ size = strlen(cp);
+ goto skipsize;
+ }
+ }
+ size = buf + BUF - cp;
+ if (size > BUF) /* should never happen */
+ abort();
+ skipsize:
+ break;
+ default: /* "%?" prints ?, unless ? is NUL */
+ if (ch == '\0')
+ goto done;
+ /* pretend it was %c with argument ch */
+ cp = buf;
+ *cp = ch;
+ size = 1;
+ sign = '\0';
+ break;
+ }
+
+ /*
+ * All reasonable formats wind up here. At this point, `cp'
+ * points to a string which (if not flags&LADJUST) should be
+ * padded out to `width' places. If flags&ZEROPAD, it should
+ * first be prefixed by any sign or other prefix; otherwise,
+ * it should be blank padded before the prefix is emitted.
+ * After any left-hand padding and prefixing, emit zeroes
+ * required by a decimal %[diouxX] precision, then print the
+ * string proper, then emit zeroes required by any leftover
+ * floating precision; finally, if LADJUST, pad with blanks.
+ *
+ * Compute actual size, so we know how much to pad.
+ * size excludes decimal prec; realsz includes it.
+ */
+ realsz = dprec > size ? dprec : size;
+ if (sign)
+ realsz++;
+ if (ox[1])
+ realsz+= 2;
+
+ /* right-adjusting blank padding */
+ if ((flags & (LADJUST|ZEROPAD)) == 0)
+ PAD(width - realsz, blanks);
+
+ /* prefix */
+ if (sign)
+ PRINT(&sign, 1);
+ if (ox[1]) { /* ox[1] is either x, X, or \0 */
+ ox[0] = '0';
+ PRINT(ox, 2);
+ }
+
+ /* right-adjusting zero padding */
+ if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
+ PAD(width - realsz, zeroes);
+
+ /* leading zeroes from decimal precision */
+ PAD(dprec - size, zeroes);
+
+ /* the string or number proper */
+#ifdef FLOATING_POINT
+ if ((flags & FPT) == 0) {
+ PRINT(cp, size);
+ } else { /* glue together f_p fragments */
+#ifdef HAVE_NL_LANGINFO
+ if (decimal_point == NULL)
+ decimal_point = nl_langinfo(RADIXCHAR);
+#endif
+ if (!expchar) { /* %[fF] or sufficiently short %[gG] */
+ if (expt <= 0) {
+ PRINT(zeroes, 1);
+ if (prec || flags & ALT)
+ PRINT(decimal_point, 1);
+ PAD(-expt, zeroes);
+ /* already handled initial 0's */
+ prec += expt;
+ } else {
+ PRINTANDPAD(cp, dtoaend, lead, zeroes);
+ cp += lead;
+ if (prec || flags & ALT)
+ PRINT(decimal_point, 1);
+ }
+ PRINTANDPAD(cp, dtoaend, prec, zeroes);
+ } else { /* %[eE] or sufficiently long %[gG] */
+ if (prec > 1 || flags & ALT) {
+ buf[0] = *cp++;
+ buf[1] = *decimal_point;
+ PRINT(buf, 2);
+ PRINT(cp, ndig-1);
+ PAD(prec - ndig, zeroes);
+ } else { /* XeYYY */
+ PRINT(cp, 1);
+ }
+ PRINT(expstr, expsize);
+ }
+ }
+#else
+ PRINT(cp, size);
+#endif
+ /* left-adjusting padding (always blank) */
+ if (flags & LADJUST)
+ PAD(width - realsz, blanks);
+
+ /* finally, adjust ret */
+ if (width < realsz)
+ width = realsz;
+ if (width > INT_MAX - ret)
+ goto overflow;
+ ret += width;
+ }
+done:
+ va_end(orgap);
+ if (strsize)
+ *str = '\0';
+ goto finish;
+
+overflow:
+ errno = EOVERFLOW;
+ ret = -1;
+
+finish:
+#ifdef PRINTF_WIDE_CHAR
+ free(convbuf);
+#endif
+#ifdef FLOATING_POINT
+ if (dtoaresult)
+ __freedtoa(dtoaresult);
+#endif
+ if (argtable != NULL && argtable != statargtable) {
+ sudo_mmap_free(argtable);
+ argtable = NULL;
+ }
+ return ret;
+}
+
+/*
+ * Type ids for argument type table.
+ */
+#define T_UNUSED 0
+#define T_SHORT 1
+#define T_U_SHORT 2
+#define TP_SHORT 3
+#define T_INT 4
+#define T_U_INT 5
+#define TP_INT 6
+#define T_LONG 7
+#define T_U_LONG 8
+#define TP_LONG 9
+#define T_LLONG 10
+#define T_U_LLONG 11
+#define TP_LLONG 12
+#define T_DOUBLE 13
+#define T_LONG_DOUBLE 14
+#define TP_CHAR 15
+#define TP_VOID 16
+#define T_PTRINT 17
+#define TP_PTRINT 18
+#define T_SIZEINT 19
+#define T_SSIZEINT 20
+#define TP_SSIZEINT 21
+#define T_MAXINT 22
+#define T_MAXUINT 23
+#define TP_MAXINT 24
+#define T_CHAR 25
+#define T_U_CHAR 26
+#define T_WINT 27
+#define TP_WCHAR 28
+
+/*
+ * Find all arguments when a positional parameter is encountered. Returns a
+ * table, indexed by argument number, of pointers to each arguments. The
+ * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
+ * It will be replaced with a mmap-ed one if it overflows (malloc cannot be
+ * used since we are attempting to make snprintf thread safe, and alloca is
+ * problematic since we have nested functions..)
+ */
+static int
+__find_arguments(const char *fmt0, va_list ap, union arg **argtable)
+{
+ char *fmt; /* format string */
+ int ch; /* character from fmt */
+ int n; /* handy integer (short term usage) */
+ char *cp; /* handy char pointer (short term usage) */
+ int flags; /* flags as above */
+ unsigned char *typetable; /* table of types */
+ unsigned char stattypetable[STATIC_ARG_TBL_SIZE];
+ int tablesize; /* current size of type table */
+ int tablemax; /* largest used index in table */
+ int nextarg; /* 1-based argument index */
+ int ret = 0; /* return value */
+
+ /*
+ * Add an argument type to the table, expanding if necessary.
+ */
+#define ADDTYPE(type) \
+ ((nextarg >= tablesize) ? \
+ __grow_type_table(&typetable, &tablesize) : 0, \
+ (nextarg > tablemax) ? tablemax = nextarg : 0, \
+ typetable[nextarg++] = type)
+
+#define ADDSARG() \
+ ((flags&MAXINT) ? ADDTYPE(T_MAXINT) : \
+ ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
+ ((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \
+ ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
+ ((flags&LONGINT) ? ADDTYPE(T_LONG) : \
+ ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : \
+ ((flags&CHARINT) ? ADDTYPE(T_CHAR) : ADDTYPE(T_INT))))))))
+
+#define ADDUARG() \
+ ((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \
+ ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
+ ((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \
+ ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
+ ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
+ ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : \
+ ((flags&CHARINT) ? ADDTYPE(T_U_CHAR) : ADDTYPE(T_U_INT))))))))
+
+ /*
+ * Add * arguments to the type array.
+ */
+#define ADDASTER() do { \
+ int n2 = 0; \
+ cp = fmt; \
+ while (is_digit(*cp)) { \
+ APPEND_DIGIT(n2, *cp); \
+ cp++; \
+ } \
+ if (*cp == '$') { \
+ int hold = nextarg; \
+ nextarg = n2; \
+ ADDTYPE(T_INT); \
+ nextarg = hold; \
+ fmt = ++cp; \
+ } else { \
+ ADDTYPE(T_INT); \
+ } \
+} while (0)
+ fmt = (char *)fmt0;
+ typetable = stattypetable;
+ tablesize = STATIC_ARG_TBL_SIZE;
+ tablemax = 0;
+ nextarg = 1;
+ memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
+
+ /*
+ * Scan the format for conversions (`%' character).
+ */
+ for (;;) {
+ for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
+ continue;
+ if (ch == '\0')
+ goto done;
+ fmt++; /* skip over '%' */
+
+ flags = 0;
+
+rflag: ch = *fmt++;
+reswitch: switch (ch) {
+ case ' ':
+ case '#':
+ case '\'':
+ goto rflag;
+ case '*':
+ ADDASTER();
+ goto rflag;
+ case '-':
+ case '+':
+ goto rflag;
+ case '.':
+ if ((ch = *fmt++) == '*') {
+ ADDASTER();
+ goto rflag;
+ }
+ while (is_digit(ch)) {
+ ch = *fmt++;
+ }
+ goto reswitch;
+ case '0':
+ goto rflag;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = 0;
+ do {
+ APPEND_DIGIT(n ,ch);
+ ch = *fmt++;
+ } while (is_digit(ch));
+ if (ch == '$') {
+ nextarg = n;
+ goto rflag;
+ }
+ goto reswitch;
+#ifdef FLOATING_POINT
+ case 'L':
+ flags |= LONGDBL;
+ goto rflag;
+#endif
+ case 'h':
+ if (*fmt == 'h') {
+ fmt++;
+ flags |= CHARINT;
+ } else {
+ flags |= SHORTINT;
+ }
+ goto rflag;
+ case 'j':
+ flags |= MAXINT;
+ goto rflag;
+ case 'l':
+ if (*fmt == 'l') {
+ fmt++;
+ flags |= LLONGINT;
+ } else {
+ flags |= LONGINT;
+ }
+ goto rflag;
+ case 'q':
+ flags |= LLONGINT;
+ goto rflag;
+ case 't':
+ flags |= PTRINT;
+ goto rflag;
+ case 'z':
+ flags |= SIZEINT;
+ goto rflag;
+ case 'c':
+#ifdef PRINTF_WIDE_CHAR
+ if (flags & LONGINT)
+ ADDTYPE(T_WINT);
+ else
+#endif
+ ADDTYPE(T_INT);
+ break;
+ case 'D':
+ flags |= LONGINT;
+ FALLTHROUGH;
+ case 'd':
+ case 'i':
+ ADDSARG();
+ break;
+#ifdef FLOATING_POINT
+ case 'a':
+ case 'A':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ case 'g':
+ case 'G':
+ if (flags & LONGDBL)
+ ADDTYPE(T_LONG_DOUBLE);
+ else
+ ADDTYPE(T_DOUBLE);
+ break;
+#endif /* FLOATING_POINT */
+#ifndef NO_PRINTF_PERCENT_N
+ case 'n':
+ if (flags & LLONGINT)
+ ADDTYPE(TP_LLONG);
+ else if (flags & LONGINT)
+ ADDTYPE(TP_LONG);
+ else if (flags & SHORTINT)
+ ADDTYPE(TP_SHORT);
+ else if (flags & PTRINT)
+ ADDTYPE(TP_PTRINT);
+ else if (flags & SIZEINT)
+ ADDTYPE(TP_SSIZEINT);
+ else if (flags & MAXINT)
+ ADDTYPE(TP_MAXINT);
+ else
+ ADDTYPE(TP_INT);
+ continue; /* no output */
+#endif /* NO_PRINTF_PERCENT_N */
+ case 'O':
+ flags |= LONGINT;
+ FALLTHROUGH;
+ case 'o':
+ ADDUARG();
+ break;
+ case 'p':
+ ADDTYPE(TP_VOID);
+ break;
+ case 's':
+#ifdef PRINTF_WIDE_CHAR
+ if (flags & LONGINT)
+ ADDTYPE(TP_WCHAR);
+ else
+#endif
+ ADDTYPE(TP_CHAR);
+ break;
+ case 'U':
+ flags |= LONGINT;
+ FALLTHROUGH;
+ case 'u':
+ case 'X':
+ case 'x':
+ ADDUARG();
+ break;
+ default: /* "%?" prints ?, unless ? is NUL */
+ if (ch == '\0')
+ goto done;
+ break;
+ }
+ }
+done:
+ /*
+ * Build the argument table.
+ */
+ if (tablemax >= STATIC_ARG_TBL_SIZE) {
+ *argtable = sudo_mmap_allocarray(tablemax + 1,
+ sizeof(union arg));
+ if (*argtable == NULL)
+ return -1;
+ }
+
+ for (n = 1; n <= tablemax; n++) {
+ switch (typetable[n]) {
+ case T_UNUSED:
+ case T_CHAR:
+ case T_U_CHAR:
+ case T_SHORT:
+ case T_U_SHORT:
+ case T_INT:
+ (*argtable)[n].intarg = va_arg(ap, int);
+ break;
+ case TP_SHORT:
+ (*argtable)[n].pshortarg = va_arg(ap, short *);
+ break;
+ case T_U_INT:
+ (*argtable)[n].uintarg = va_arg(ap, unsigned int);
+ break;
+ case TP_INT:
+ (*argtable)[n].pintarg = va_arg(ap, int *);
+ break;
+ case T_LONG:
+ (*argtable)[n].longarg = va_arg(ap, long);
+ break;
+ case T_U_LONG:
+ (*argtable)[n].ulongarg = va_arg(ap, unsigned long);
+ break;
+ case TP_LONG:
+ (*argtable)[n].plongarg = va_arg(ap, long *);
+ break;
+ case T_LLONG:
+ (*argtable)[n].longlongarg = va_arg(ap, long long);
+ break;
+ case T_U_LLONG:
+ (*argtable)[n].ulonglongarg = va_arg(ap, unsigned long long);
+ break;
+ case TP_LLONG:
+ (*argtable)[n].plonglongarg = va_arg(ap, long long *);
+ break;
+#ifdef FLOATING_POINT
+ case T_DOUBLE:
+ (*argtable)[n].doublearg = va_arg(ap, double);
+ break;
+ case T_LONG_DOUBLE:
+ (*argtable)[n].longdoublearg = va_arg(ap, long double);
+ break;
+#endif
+ case TP_CHAR:
+ (*argtable)[n].pchararg = va_arg(ap, char *);
+ break;
+ case TP_VOID:
+ (*argtable)[n].pvoidarg = va_arg(ap, void *);
+ break;
+ case T_PTRINT:
+ (*argtable)[n].ptrdiffarg = va_arg(ap, ptrdiff_t);
+ break;
+ case TP_PTRINT:
+ (*argtable)[n].pptrdiffarg = va_arg(ap, ptrdiff_t *);
+ break;
+ case T_SIZEINT:
+ (*argtable)[n].sizearg = va_arg(ap, size_t);
+ break;
+ case T_SSIZEINT:
+ (*argtable)[n].ssizearg = va_arg(ap, ssize_t);
+ break;
+ case TP_SSIZEINT:
+ (*argtable)[n].pssizearg = va_arg(ap, ssize_t *);
+ break;
+ case T_MAXINT:
+ (*argtable)[n].intmaxarg = va_arg(ap, intmax_t);
+ break;
+ case T_MAXUINT:
+ (*argtable)[n].uintmaxarg = va_arg(ap, uintmax_t);
+ break;
+ case TP_MAXINT:
+ (*argtable)[n].pintmaxarg = va_arg(ap, intmax_t *);
+ break;
+#ifdef PRINTF_WIDE_CHAR
+ case T_WINT:
+ (*argtable)[n].wintarg = va_arg(ap, wint_t);
+ break;
+ case TP_WCHAR:
+ (*argtable)[n].pwchararg = va_arg(ap, wchar_t *);
+ break;
+#endif
+ }
+ }
+ goto finish;
+
+overflow:
+ errno = EOVERFLOW;
+ ret = -1;
+
+finish:
+ if (typetable != NULL && typetable != stattypetable) {
+ sudo_mmap_free(typetable);
+ typetable = NULL;
+ }
+ return ret;
+}
+
+/*
+ * Increase the size of the type table.
+ */
+static int
+__grow_type_table(unsigned char **typetable, int *tablesize)
+{
+ unsigned char *oldtable = *typetable;
+ int newsize = *tablesize * 2;
+
+ if (*tablesize == STATIC_ARG_TBL_SIZE) {
+ *typetable = sudo_mmap_alloc(newsize);
+ if (*typetable == NULL)
+ return -1;
+ memcpy(*typetable, oldtable, *tablesize);
+ } else {
+ unsigned char *new = sudo_mmap_alloc(newsize);
+ if (new == NULL)
+ return -1;
+ memcpy(new, *typetable, *tablesize);
+ sudo_mmap_free(*typetable);
+ *typetable = new;
+ }
+ memset(*typetable + *tablesize, T_UNUSED, (newsize - *tablesize));
+
+ *tablesize = newsize;
+ return 0;
+}
+
+#ifdef FLOATING_POINT
+static int
+exponent(char *p0, int exp, int fmtch)
+{
+ char *p, *t;
+ char expbuf[MAXEXPDIG];
+
+ p = p0;
+ *p++ = fmtch;
+ if (exp < 0) {
+ exp = -exp;
+ *p++ = '-';
+ } else
+ *p++ = '+';
+ t = expbuf + MAXEXPDIG;
+ if (exp > 9) {
+ do {
+ *--t = to_char(exp % 10);
+ } while ((exp /= 10) > 9);
+ *--t = to_char(exp);
+ for (; t < expbuf + MAXEXPDIG; *p++ = *t++)
+ /* nothing */;
+ } else {
+ /*
+ * Exponents for decimal floating point conversions
+ * (%[eEgG]) must be at least two characters long,
+ * whereas exponents for hexadecimal conversions can
+ * be only one character long.
+ */
+ if (fmtch == 'e' || fmtch == 'E')
+ *p++ = '0';
+ *p++ = to_char(exp);
+ }
+ return p - p0;
+}
+#endif /* FLOATING_POINT */
+
+#if !defined(HAVE_VSNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
+int
+sudo_vsnprintf(char * restrict str, size_t n, const char * restrict fmt, va_list ap)
+{
+ if (n > INT_MAX) {
+ errno = EOVERFLOW;
+ *str = '\0';
+ return -1;
+ }
+ return xxxprintf(&str, n, 0, fmt, ap);
+}
+#endif /* !HAVE_VSNPRINTF || PREFER_PORTABLE_SNPRINTF */
+
+#if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
+int
+sudo_snprintf(char * restrict str, size_t n, char const * restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ if (n > INT_MAX) {
+ errno = EOVERFLOW;
+ *str = '\0';
+ return -1;
+ }
+ va_start(ap, fmt);
+ ret = xxxprintf(&str, n, 0, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+#endif /* !HAVE_SNPRINTF || PREFER_PORTABLE_SNPRINTF */
+
+#if !defined(HAVE_VASPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
+int
+sudo_vasprintf(char ** restrict str, const char * restrict fmt, va_list ap)
+{
+ int ret;
+
+ ret = xxxprintf(str, 0, 1, fmt, ap);
+ if (ret == -1)
+ *str = NULL;
+ return ret;
+}
+#endif /* !HAVE_VASPRINTF || PREFER_PORTABLE_SNPRINTF */
+
+#if !defined(HAVE_ASPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
+int
+sudo_asprintf(char ** restrict str, char const * restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = xxxprintf(str, 0, 1, fmt, ap);
+ va_end(ap);
+ if (ret == -1)
+ *str = NULL;
+ return ret;
+}
+#endif /* !HAVE_ASPRINTF || PREFER_PORTABLE_SNPRINTF */
+
+#endif /* !HAVE_VSNPRINTF || !HAVE_SNPRINTF || !HAVE_VASPRINTF || !HAVE_ASPRINTF || PREFER_PORTABLE_SNPRINTF */
diff --git a/lib/util/str2sig.c b/lib/util/str2sig.c
new file mode 100644
index 0000000..5b0bcbf
--- /dev/null
+++ b/lib/util/str2sig.c
@@ -0,0 +1,174 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_STR2SIG
+
+#include <errno.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <ctype.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+#if !defined(HAVE_SIGABBREV_NP)
+# if defined(HAVE_DECL_SYS_SIGNAME) && HAVE_DECL_SYS_SIGNAME == 1
+# define sigabbrev_np(_x) sys_signame[(_x)]
+# elif defined(HAVE_DECL__SYS_SIGNAME) && HAVE_DECL__SYS_SIGNAME == 1
+# define sigabbrev_np(_x) _sys_signame[(_x)]
+# elif defined(HAVE_SYS_SIGABBREV)
+# define sigabbrev_np(_x) sys_sigabbrev[(_x)]
+# if defined(HAVE_DECL_SYS_SIGABBREV) && HAVE_DECL_SYS_SIGABBREV == 0
+ /* sys_sigabbrev is not declared by glibc */
+ extern const char *const sys_sigabbrev[NSIG];
+# endif
+# else
+# define sigabbrev_np(_x) sudo_sys_signame[(_x)]
+ extern const char *const sudo_sys_signame[NSIG];
+# endif
+#endif /* !HAVE_SIGABBREV_NP */
+
+/*
+ * Many systems use aliases for source backward compatibility.
+ */
+static struct sigalias {
+ const char *name;
+ int number;
+} sigaliases[] = {
+#ifdef SIGABRT
+ { "ABRT", SIGABRT },
+#endif
+#ifdef SIGCLD
+ { "CLD", SIGCLD },
+#endif
+#ifdef SIGIO
+ { "IO", SIGIO },
+#endif
+#ifdef SIGIOT
+ { "IOT", SIGIOT },
+#endif
+#ifdef SIGLOST
+ { "LOST", SIGLOST },
+#endif
+#ifdef SIGPOLL
+ { "POLL", SIGPOLL },
+#endif
+ { NULL, -1 }
+};
+
+/*
+ * Translate signal name to number.
+ */
+int
+sudo_str2sig(const char *signame, int *result)
+{
+ struct sigalias *alias;
+ const char *errstr;
+ int signo;
+
+ /* Could be a signal number encoded as a string. */
+ if (isdigit((unsigned char)signame[0])) {
+ signo = (int)sudo_strtonum(signame, 0, NSIG - 1, &errstr);
+ if (errstr != NULL)
+ return -1;
+ *result = signo;
+ return 0;
+ }
+
+ /* Check real-time signals. */
+#if defined(SIGRTMIN)
+ if (strncmp(signame, "RTMIN", 5) == 0) {
+ if (signame[5] == '\0') {
+ *result = SIGRTMIN;
+ return 0;
+ }
+ if (signame[5] == '+') {
+ if (isdigit((unsigned char)signame[6])) {
+# ifdef _SC_RTSIG_MAX
+ const long rtmax = sysconf(_SC_RTSIG_MAX);
+# else
+ const long rtmax = SIGRTMAX - SIGRTMIN;
+# endif
+ const int off = signame[6] - '0';
+
+ if (rtmax > 0 && off < rtmax / 2) {
+ *result = SIGRTMIN + off;
+ return 0;
+ }
+ }
+ }
+ }
+#endif
+#if defined(SIGRTMAX)
+ if (strncmp(signame, "RTMAX", 5) == 0) {
+ if (signame[5] == '\0') {
+ *result = SIGRTMAX;
+ return 0;
+ }
+ if (signame[5] == '-') {
+ if (isdigit((unsigned char)signame[6])) {
+# ifdef _SC_RTSIG_MAX
+ const long rtmax = sysconf(_SC_RTSIG_MAX);
+# else
+ const long rtmax = SIGRTMAX - SIGRTMIN;
+# endif
+ const int off = signame[6] - '0';
+
+ if (rtmax > 0 && off < rtmax / 2) {
+ *result = SIGRTMAX - off;
+ return 0;
+ }
+ }
+ }
+ }
+#endif
+
+ /* Check aliases. */
+ for (alias = sigaliases; alias->name != NULL; alias++) {
+ if (strcmp(signame, alias->name) == 0) {
+ *result = alias->number;
+ return 0;
+ }
+ }
+
+ for (signo = 1; signo < NSIG; signo++) {
+ const char *cp = sigabbrev_np(signo);
+ if (cp != NULL) {
+ /* On macOS sys_signame[] may contain lower-case names. */
+ if (strcasecmp(signame, cp) == 0) {
+ *result = signo;
+ return 0;
+ }
+ }
+ }
+
+ errno = EINVAL;
+ return -1;
+}
+#endif /* HAVE_STR2SIG */
diff --git a/lib/util/strlcat.c b/lib/util/strlcat.c
new file mode 100644
index 0000000..a124a4f
--- /dev/null
+++ b/lib/util/strlcat.c
@@ -0,0 +1,69 @@
+/* $OpenBSD: strlcat.c,v 1.15 2015/03/02 21:41:08 millert Exp $ */
+
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1998, 2003-2005, 2010-2011, 2013-2015
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_STRLCAT
+
+#include <string.h>
+
+#include <sudo_compat.h>
+
+/*
+ * Appends src to string dst of size dsize (unlike strncat, dsize is the
+ * full size of dst, not space left). At most dsize-1 characters
+ * will be copied. Always NUL terminates (unless dsize <= strlen(dst)).
+ * Returns strlen(src) + MIN(dsize, strlen(initial dst)).
+ * If retval >= dsize, truncation occurred.
+ */
+size_t
+sudo_strlcat(char * restrict dst, const char * restrict src, size_t dsize)
+{
+ const char *odst = dst;
+ const char *osrc = src;
+ size_t n = dsize;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end. */
+ while (n-- != 0 && *dst != '\0')
+ dst++;
+ dlen = (size_t)(dst - odst);
+ n = dsize - dlen;
+
+ if (n-- == 0)
+ return(dlen + strlen(src));
+ while (*src != '\0') {
+ if (n != 0) {
+ *dst++ = *src;
+ n--;
+ }
+ src++;
+ }
+ *dst = '\0';
+
+ return(dlen + (size_t)(src - osrc)); /* count does not include NUL */
+}
+#endif /* HAVE_STRLCAT */
diff --git a/lib/util/strlcpy.c b/lib/util/strlcpy.c
new file mode 100644
index 0000000..c2daada
--- /dev/null
+++ b/lib/util/strlcpy.c
@@ -0,0 +1,64 @@
+/* $OpenBSD: strlcpy.c,v 1.12 2015/01/15 03:54:12 millert Exp $ */
+
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1998, 2003-2005, 2010-2011, 2013-2015
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_STRLCPY
+
+#include <string.h>
+
+#include <sudo_compat.h>
+
+/*
+ * Copy string src to buffer dst of size dsize. At most dsize-1
+ * chars will be copied. Always NUL terminates (unless dsize == 0).
+ * Returns strlen(src); if retval >= dsize, truncation occurred.
+ */
+size_t
+sudo_strlcpy(char * restrict dst, const char * restrict src, size_t dsize)
+{
+ const char *osrc = src;
+ size_t nleft = dsize;
+
+ /* Copy as many bytes as will fit. */
+ if (nleft != 0) {
+ while (--nleft != 0) {
+ if ((*dst++ = *src++) == '\0')
+ break;
+ }
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src. */
+ if (nleft == 0) {
+ if (dsize != 0)
+ *dst = '\0'; /* NUL-terminate dst */
+ while (*src++)
+ continue;
+ }
+
+ return((size_t)(src - osrc) - 1); /* count does not include NUL */
+}
+#endif /* HAVE_STRLCPY */
diff --git a/lib/util/strndup.c b/lib/util/strndup.c
new file mode 100644
index 0000000..f44fc8d
--- /dev/null
+++ b/lib/util/strndup.c
@@ -0,0 +1,51 @@
+/* $OpenBSD: strndup.c,v 1.1 2010/05/18 22:24:55 tedu Exp $ */
+
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_STRNDUP
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudo_compat.h>
+
+char *
+sudo_strndup(const char *str, size_t maxlen)
+{
+ char *copy;
+ size_t len;
+
+ len = strnlen(str, maxlen);
+ copy = malloc(len + 1);
+ if (copy != NULL) {
+ (void)memcpy(copy, str, len);
+ copy[len] = '\0';
+ }
+
+ return copy;
+}
+
+#endif /* HAVE_STRNDUP */
diff --git a/lib/util/strnlen.c b/lib/util/strnlen.c
new file mode 100644
index 0000000..c394515
--- /dev/null
+++ b/lib/util/strnlen.c
@@ -0,0 +1,45 @@
+/* $OpenBSD: strnlen.c,v 1.5 2014/06/10 04:17:37 deraadt Exp $ */
+
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_STRNLEN
+
+#include <sys/types.h>
+
+#include <sudo_compat.h>
+
+size_t
+sudo_strnlen(const char *str, size_t maxlen)
+{
+ const char *cp;
+
+ for (cp = str; maxlen != 0 && *cp != '\0'; cp++, maxlen--)
+ continue;
+
+ return (size_t)(cp - str);
+}
+
+#endif /* HAVE_STRNLEN */
diff --git a/lib/util/strsignal.c b/lib/util/strsignal.c
new file mode 100644
index 0000000..411252f
--- /dev/null
+++ b/lib/util/strsignal.c
@@ -0,0 +1,52 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2014 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_STRSIGNAL
+
+#include <signal.h>
+
+#include <sudo_compat.h>
+#include <sudo_gettext.h>
+
+#if defined(HAVE_DECL_SYS_SIGLIST) && HAVE_DECL_SYS_SIGLIST == 1
+# define sudo_sys_siglist sys_siglist
+#elif defined(HAVE_DECL__SYS_SIGLIST) && HAVE_DECL__SYS_SIGLIST == 1
+# define sudo_sys_siglist _sys_siglist
+#else
+extern const char *const sudo_sys_siglist[NSIG];
+#endif
+
+/*
+ * Get signal description string
+ */
+char *
+sudo_strsignal(int signo)
+{
+ if (signo > 0 && signo < NSIG && sudo_sys_siglist[signo] != NULL)
+ return (char *)sudo_sys_siglist[signo];
+ /* XXX - should be "Unknown signal: %d" */
+ return (char *)_("Unknown signal");
+}
+#endif /* HAVE_STRSIGNAL */
diff --git a/lib/util/strsplit.c b/lib/util/strsplit.c
new file mode 100644
index 0000000..2343975
--- /dev/null
+++ b/lib/util/strsplit.c
@@ -0,0 +1,73 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+
+/*
+ * Like strtok_r but non-destructive and works w/o a NUL terminator.
+ * TODO: Optimize by storing current char in a variable ch
+ */
+const char *
+sudo_strsplit_v1(const char *str, const char *endstr, const char *sep, const char **last)
+{
+ const char *cp, *s;
+ debug_decl(sudo_strsplit, SUDO_DEBUG_UTIL);
+
+ /* If no str specified, use last ptr (if any). */
+ if (str == NULL)
+ str = *last;
+
+ /* Skip leading separator characters. */
+ while (str < endstr) {
+ for (s = sep; *s != '\0'; s++) {
+ if (*str == *s) {
+ str++;
+ break;
+ }
+ }
+ if (*s == '\0')
+ break;
+ }
+
+ /* Empty string? */
+ if (str >= endstr) {
+ *last = endstr;
+ debug_return_ptr(NULL);
+ }
+
+ /* Scan str until we hit a char from sep. */
+ for (cp = str; cp < endstr; cp++) {
+ for (s = sep; *s != '\0'; s++) {
+ if (*cp == *s)
+ break;
+ }
+ if (*s != '\0')
+ break;
+ }
+ *last = cp;
+ debug_return_const_ptr(str);
+}
diff --git a/lib/util/strtobool.c b/lib/util/strtobool.c
new file mode 100644
index 0000000..61aebbc
--- /dev/null
+++ b/lib/util/strtobool.c
@@ -0,0 +1,77 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2016 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+
+int
+sudo_strtobool_v1(const char *str)
+{
+ debug_decl(sudo_strtobool, SUDO_DEBUG_UTIL);
+
+ switch (*str) {
+ case '0':
+ case '1':
+ if (str[1] == '\0')
+ debug_return_int(*str - '0');
+ break;
+ case 'y':
+ case 'Y':
+ if (strcasecmp(str, "yes") == 0)
+ debug_return_int(1);
+ break;
+ case 't':
+ case 'T':
+ if (strcasecmp(str, "true") == 0)
+ debug_return_int(1);
+ break;
+ case 'o':
+ case 'O':
+ if (strcasecmp(str, "on") == 0)
+ debug_return_int(1);
+ if (strcasecmp(str, "off") == 0)
+ debug_return_int(0);
+ break;
+ case 'n':
+ case 'N':
+ if (strcasecmp(str, "no") == 0)
+ debug_return_int(0);
+ break;
+ case 'f':
+ case 'F':
+ if (strcasecmp(str, "false") == 0)
+ debug_return_int(0);
+ break;
+ }
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "invalid boolean value \"%s\"", str);
+
+ debug_return_int(-1);
+}
diff --git a/lib/util/strtoid.c b/lib/util/strtoid.c
new file mode 100644
index 0000000..7e66a53
--- /dev/null
+++ b/lib/util/strtoid.c
@@ -0,0 +1,108 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h> /* for id_t */
+
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_gettext.h>
+#include <sudo_util.h>
+
+/*
+ * Make sure that the ID ends with a valid separator char.
+ */
+static bool
+valid_separator(const char *p, const char *ep, const char *sep)
+{
+ bool valid = false;
+
+ if (ep != p) {
+ /* check for valid separator (including '\0') */
+ if (sep == NULL)
+ sep = "";
+ do {
+ if (*ep == *sep)
+ valid = true;
+ } while (*sep++ != '\0');
+ }
+ return valid;
+}
+
+/*
+ * Parse a uid/gid in string form.
+ * If sep is non-NULL, it contains valid separator characters (e.g. comma, space)
+ * If endp is non-NULL it is set to the next char after the ID.
+ * On success, returns the parsed ID and clears errstr.
+ * On error, returns 0 and sets errstr.
+ */
+id_t
+sudo_strtoidx_v1(const char *p, const char *sep, char **endp, const char **errstrp)
+{
+ const char *errstr;
+ char *ep;
+ id_t ret;
+ debug_decl(sudo_strtoid, SUDO_DEBUG_UTIL);
+
+ ret = (id_t)sudo_strtonumx(p, INT_MIN, UINT_MAX, &ep, &errstr);
+ if (errstr == NULL) {
+ /*
+ * Disallow id -1 (UINT_MAX), which means "no change"
+ * and check for a valid separator (if specified).
+ */
+ if (ret == (id_t)-1 || ret == (id_t)UINT_MAX || !valid_separator(p, ep, sep)) {
+ errstr = N_("invalid value");
+ errno = EINVAL;
+ ret = 0;
+ }
+ }
+ if (errstrp != NULL)
+ *errstrp = errstr;
+ if (endp != NULL)
+ *endp = ep;
+ debug_return_id_t(ret);
+}
+
+/* Backward compatibility */
+id_t
+sudo_strtoid_v1(const char *p, const char *sep, char **endp, const char **errstrp)
+{
+ return sudo_strtoidx_v1(p, sep, endp, errstrp);
+}
+
+/* Simplified interface */
+id_t
+sudo_strtoid_v2(const char *p, const char **errstrp)
+{
+ return sudo_strtoidx_v1(p, NULL, NULL, errstrp);
+}
diff --git a/lib/util/strtomode.c b/lib/util/strtomode.c
new file mode 100644
index 0000000..1902031
--- /dev/null
+++ b/lib/util/strtomode.c
@@ -0,0 +1,71 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_gettext.h>
+#include <sudo_util.h>
+
+/*
+ * Parse an octal file mode in the range [0, 0777].
+ * On success, returns the parsed mode and clears errstr.
+ * On error, returns 0 and sets errstr.
+ */
+mode_t
+sudo_strtomode_v2(const char *cp, const char **errstr)
+{
+ char *ep;
+ long lval;
+ debug_decl(sudo_strtomode, SUDO_DEBUG_UTIL);
+
+ errno = 0;
+ lval = strtol(cp, &ep, 8);
+ if (ep == cp || *ep != '\0') {
+ if (errstr != NULL)
+ *errstr = N_("invalid value");
+ errno = EINVAL;
+ debug_return_mode_t(0);
+ }
+ if (lval < 0 || lval > ACCESSPERMS) {
+ if (errstr != NULL)
+ *errstr = lval < 0 ? N_("value too small") : N_("value too large");
+ errno = ERANGE;
+ debug_return_mode_t(0);
+ }
+ if (errstr != NULL)
+ *errstr = NULL;
+ debug_return_mode_t((mode_t)lval);
+}
+
+int
+sudo_strtomode_v1(const char *cp, const char **errstr)
+{
+ return (int)sudo_strtomode_v2(cp, errstr);
+}
diff --git a/lib/util/strtonum.c b/lib/util/strtonum.c
new file mode 100644
index 0000000..78e42e9
--- /dev/null
+++ b/lib/util/strtonum.c
@@ -0,0 +1,192 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2015, 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <errno.h>
+
+#include <sudo_compat.h>
+#include <sudo_gettext.h>
+#include <sudo_util.h>
+
+enum strtonum_err {
+ STN_INITIAL,
+ STN_VALID,
+ STN_INVALID,
+ STN_TOOSMALL,
+ STN_TOOBIG
+};
+
+/*
+ * Convert a string to a number in the range [minval, maxval]
+ * Unlike strtonum(), this returns the first non-digit in endp (if not NULL).
+ */
+long long
+sudo_strtonumx(const char *str, long long minval, long long maxval, char **endp,
+ const char **errstrp)
+{
+ enum strtonum_err errval = STN_INITIAL;
+ long long lastval, result = 0;
+ const char *cp = str;
+ int remainder;
+ char ch, sign;
+
+ if (minval > maxval) {
+ errval = STN_INVALID;
+ goto done;
+ }
+
+ /* Trim leading space and check sign, if any. */
+ do {
+ ch = *cp++;
+ } while (isspace((unsigned char)ch));
+ switch (ch) {
+ case '-':
+ sign = '-';
+ ch = *cp++;
+ break;
+ case '+':
+ ch = *cp++;
+ FALLTHROUGH;
+ default:
+ sign = '+';
+ break;
+ }
+
+ /*
+ * To prevent overflow we determine the highest (or lowest in
+ * the case of negative numbers) value result can have *before*
+ * if its multiplied (divided) by 10 as well as the remainder.
+ * If result matches this value and the next digit is larger than
+ * the remainder, we know the result is out of range.
+ * The remainder is always positive since it is compared against
+ * an unsigned digit.
+ */
+ if (sign == '-') {
+ lastval = minval / 10;
+ remainder = -(int)(minval % 10);
+ if (remainder < 0) {
+ lastval += 1;
+ remainder += 10;
+ }
+ for (;; ch = *cp++) {
+ if (!isdigit((unsigned char)ch))
+ break;
+ ch -= '0';
+ if (result < lastval || (result == lastval && ch > remainder)) {
+ /* Skip remaining digits. */
+ do {
+ ch = *cp++;
+ } while (isdigit((unsigned char)ch));
+ errval = STN_TOOSMALL;
+ break;
+ } else {
+ result *= 10;
+ result -= ch;
+ errval = STN_VALID;
+ }
+ }
+ if (result > maxval)
+ errval = STN_TOOBIG;
+ } else {
+ lastval = maxval / 10;
+ remainder = (int)(maxval % 10);
+ for (;; ch = *cp++) {
+ if (!isdigit((unsigned char)ch))
+ break;
+ ch -= '0';
+ if (result > lastval || (result == lastval && ch > remainder)) {
+ /* Skip remaining digits. */
+ do {
+ ch = *cp++;
+ } while (isdigit((unsigned char)ch));
+ errval = STN_TOOBIG;
+ break;
+ } else {
+ result *= 10;
+ result += ch;
+ errval = STN_VALID;
+ }
+ }
+ if (result < minval)
+ errval = STN_TOOSMALL;
+ }
+
+done:
+ switch (errval) {
+ case STN_INITIAL:
+ case STN_VALID:
+ if (errstrp != NULL)
+ *errstrp = NULL;
+ break;
+ case STN_INVALID:
+ result = 0;
+ errno = EINVAL;
+ if (errstrp != NULL)
+ *errstrp = N_("invalid value");
+ break;
+ case STN_TOOSMALL:
+ result = 0;
+ errno = ERANGE;
+ if (errstrp != NULL)
+ *errstrp = N_("value too small");
+ break;
+ case STN_TOOBIG:
+ result = 0;
+ errno = ERANGE;
+ if (errstrp != NULL)
+ *errstrp = N_("value too large");
+ break;
+ }
+ if (endp != NULL) {
+ if (errval == STN_INITIAL || errval == STN_INVALID)
+ *endp = (char *)str;
+ else
+ *endp = (char *)(cp - 1);
+ }
+ return result;
+}
+
+/*
+ * Convert a string to a number in the range [minval, maxval]
+ */
+long long
+sudo_strtonum(const char *str, long long minval, long long maxval,
+ const char **errstrp)
+{
+ const char *errstr;
+ char *ep;
+ long long ret;
+
+ ret = sudo_strtonumx(str, minval, maxval, &ep, &errstr);
+ /* Check for empty string and terminating NUL. */
+ if (str == ep || *ep != '\0') {
+ errno = EINVAL;
+ errstr = N_("invalid value");
+ ret = 0;
+ }
+ if (errstrp != NULL)
+ *errstrp = errstr;
+ return ret;
+}
diff --git a/lib/util/sudo_conf.c b/lib/util/sudo_conf.c
new file mode 100644
index 0000000..be22e45
--- /dev/null
+++ b/lib/util/sudo_conf.c
@@ -0,0 +1,809 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#ifdef HAVE_DLOPEN
+# include <dlfcn.h>
+#endif
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_conf.h>
+#include <sudo_debug.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_plugin.h>
+#include <sudo_util.h>
+#include <pathnames.h>
+
+#ifndef _PATH_SUDO_INTERCEPT
+# define _PATH_SUDO_INTERCEPT NULL
+#endif
+#ifndef _PATH_SUDO_NOEXEC
+# define _PATH_SUDO_NOEXEC NULL
+#endif
+
+struct sudo_conf_table {
+ const char *name;
+ unsigned int namelen;
+ int (*parser)(const char *entry, const char *conf_file, unsigned int lineno);
+};
+
+struct sudo_conf_path_table {
+ const char *pname;
+ unsigned int pnamelen;
+ bool dynamic;
+ const char *pval;
+};
+
+struct sudo_conf_settings {
+ bool updated;
+ bool disable_coredump;
+ bool probe_interfaces;
+ int group_source;
+ int max_groups;
+};
+
+static int parse_debug(const char *entry, const char *conf_file, unsigned int lineno);
+static int parse_path(const char *entry, const char *conf_file, unsigned int lineno);
+static int parse_plugin(const char *entry, const char *conf_file, unsigned int lineno);
+static int parse_variable(const char *entry, const char *conf_file, unsigned int lineno);
+
+static struct sudo_conf_table sudo_conf_table[] = {
+ { "Debug", sizeof("Debug") - 1, parse_debug },
+ { "Path", sizeof("Path") - 1, parse_path },
+ { "Plugin", sizeof("Plugin") - 1, parse_plugin },
+ { "Set", sizeof("Set") - 1, parse_variable },
+ { NULL }
+};
+
+static int set_var_disable_coredump(const char *entry, const char *conf_file, unsigned int);
+static int set_var_group_source(const char *entry, const char *conf_file, unsigned int);
+static int set_var_max_groups(const char *entry, const char *conf_file, unsigned int);
+static int set_var_probe_interfaces(const char *entry, const char *conf_file, unsigned int);
+
+static struct sudo_conf_table sudo_conf_var_table[] = {
+ { "disable_coredump", sizeof("disable_coredump") - 1, set_var_disable_coredump },
+ { "group_source", sizeof("group_source") - 1, set_var_group_source },
+ { "max_groups", sizeof("max_groups") - 1, set_var_max_groups },
+ { "probe_interfaces", sizeof("probe_interfaces") - 1, set_var_probe_interfaces },
+ { NULL }
+};
+
+/* Indexes into path_table[] below (order is important). */
+#define SUDO_CONF_PATH_ASKPASS 0
+#define SUDO_CONF_PATH_SESH 1
+#define SUDO_CONF_PATH_INTERCEPT 2
+#define SUDO_CONF_PATH_NOEXEC 3
+#define SUDO_CONF_PATH_PLUGIN_DIR 4
+#define SUDO_CONF_PATH_DEVSEARCH 5
+
+#define SUDO_CONF_PATH_INITIALIZER { \
+ { "askpass", sizeof("askpass") - 1, false, _PATH_SUDO_ASKPASS }, \
+ { "sesh", sizeof("sesh") - 1, false, _PATH_SUDO_SESH }, \
+ { "intercept", sizeof("intercept") - 1, false, _PATH_SUDO_INTERCEPT }, \
+ { "noexec", sizeof("noexec") - 1, false, _PATH_SUDO_NOEXEC }, \
+ { "plugin_dir", sizeof("plugin_dir") - 1, false, _PATH_SUDO_PLUGIN_DIR }, \
+ { "devsearch", sizeof("devsearch") - 1, false, _PATH_SUDO_DEVSEARCH }, \
+ { NULL } \
+}
+
+/*
+ * getgroups(2) on macOS is flakey with respect to non-local groups.
+ * Even with _DARWIN_UNLIMITED_GETGROUPS set we may not get all groups./
+ * See bug #946 for details.
+ */
+#ifdef __APPLE__
+# define GROUP_SOURCE_DEFAULT GROUP_SOURCE_DYNAMIC
+#else
+# define GROUP_SOURCE_DEFAULT GROUP_SOURCE_ADAPTIVE
+#endif
+
+#define SUDO_CONF_SETTINGS_INITIALIZER { \
+ false, /* updated */ \
+ true, /* disable_coredump */ \
+ true, /* probe_interfaces */ \
+ GROUP_SOURCE_DEFAULT, /* group_source */ \
+ -1 /* max_groups */ \
+}
+
+static struct sudo_conf_data {
+ struct sudo_conf_settings settings;
+ struct sudo_conf_debug_list debugging;
+ struct plugin_info_list plugins;
+ struct sudo_conf_path_table path_table[7];
+} sudo_conf_data = {
+ SUDO_CONF_SETTINGS_INITIALIZER,
+ TAILQ_HEAD_INITIALIZER(sudo_conf_data.debugging),
+ TAILQ_HEAD_INITIALIZER(sudo_conf_data.plugins),
+ SUDO_CONF_PATH_INITIALIZER
+};
+
+/*
+ * "Set variable_name value"
+ */
+static int
+parse_variable(const char *entry, const char *conf_file, unsigned int lineno)
+{
+ struct sudo_conf_table *var;
+ int ret;
+ debug_decl(parse_variable, SUDO_DEBUG_UTIL);
+
+ for (var = sudo_conf_var_table; var->name != NULL; var++) {
+ if (strncmp(entry, var->name, var->namelen) == 0 &&
+ isblank((unsigned char)entry[var->namelen])) {
+ entry += var->namelen + 1;
+ while (isblank((unsigned char)*entry))
+ entry++;
+ ret = var->parser(entry, conf_file, lineno);
+ sudo_debug_printf(ret ? SUDO_DEBUG_INFO : SUDO_DEBUG_ERROR,
+ "%s: %s:%u: Set %s %s", __func__, conf_file,
+ lineno, var->name, entry);
+ debug_return_int(ret);
+ }
+ }
+ sudo_debug_printf(SUDO_DEBUG_WARN, "%s: %s:%u: unknown setting %s",
+ __func__, conf_file, lineno, entry);
+ debug_return_int(false);
+}
+
+/*
+ * "Path name /path/to/file"
+ * If path is missing it will be set to the NULL pointer.
+ */
+static int
+parse_path(const char *entry, const char *conf_file, unsigned int lineno)
+{
+ const char *entry_end = entry + strlen(entry);
+ const char *ep, *name, *path;
+ struct sudo_conf_path_table *cur;
+ size_t namelen;
+ debug_decl(parse_path, SUDO_DEBUG_UTIL);
+
+ /* Parse name. */
+ name = sudo_strsplit(entry, entry_end, " \t", &ep);
+ if (name == NULL)
+ goto bad;
+ namelen = (size_t)(ep - name);
+
+ /* Parse path (if present). */
+ path = sudo_strsplit(NULL, entry_end, " \t", &ep);
+
+ /* Match supported paths, ignoring unknown paths. */
+ for (cur = sudo_conf_data.path_table; cur->pname != NULL; cur++) {
+ if (namelen == cur->pnamelen &&
+ strncasecmp(name, cur->pname, cur->pnamelen) == 0) {
+ char *pval = NULL;
+ if (path != NULL) {
+ if ((pval = strdup(path)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ debug_return_int(-1);
+ }
+ }
+ if (cur->dynamic)
+ free((char *)cur->pval);
+ cur->pval = pval;
+ cur->dynamic = true;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: %s:%u: Path %s %s",
+ __func__, conf_file, lineno, cur->pname,
+ pval ? pval : "(none)");
+ debug_return_int(true);
+ }
+ }
+ sudo_debug_printf(SUDO_DEBUG_WARN, "%s: %s:%u: unknown path %s",
+ __func__, conf_file, lineno, entry);
+ debug_return_int(false);
+bad:
+ sudo_warnx(U_("invalid Path value \"%s\" in %s, line %u"),
+ entry, conf_file, lineno);
+ debug_return_int(false);
+}
+
+/*
+ * "Debug program /path/to/log flags,..."
+ */
+static int
+parse_debug(const char *entry, const char *conf_file, unsigned int lineno)
+{
+ struct sudo_conf_debug *debug_spec;
+ struct sudo_debug_file *debug_file = NULL;
+ const char *ep, *path, *progname, *flags;
+ const char *entry_end = entry + strlen(entry);
+ size_t pathlen, prognamelen;
+ debug_decl(parse_debug, SUDO_DEBUG_UTIL);
+
+ /* Parse progname. */
+ progname = sudo_strsplit(entry, entry_end, " \t", &ep);
+ if (progname == NULL)
+ debug_return_int(false); /* not enough fields */
+ prognamelen = (size_t)(ep - progname);
+
+ /* Parse path. */
+ path = sudo_strsplit(NULL, entry_end, " \t", &ep);
+ if (path == NULL)
+ debug_return_int(false); /* not enough fields */
+ pathlen = (size_t)(ep - path);
+
+ /* Remainder is flags (freeform). */
+ flags = sudo_strsplit(NULL, entry_end, " \t", &ep);
+ if (flags == NULL)
+ debug_return_int(false); /* not enough fields */
+
+ /* If progname already exists, use it, else alloc a new one. */
+ TAILQ_FOREACH(debug_spec, &sudo_conf_data.debugging, entries) {
+ if (strncmp(debug_spec->progname, progname, prognamelen) == 0 &&
+ debug_spec->progname[prognamelen] == '\0')
+ break;
+ }
+ if (debug_spec == NULL) {
+ debug_spec = malloc(sizeof(*debug_spec));
+ if (debug_spec == NULL)
+ goto oom;
+ debug_spec->progname = strndup(progname, prognamelen);
+ if (debug_spec->progname == NULL) {
+ free(debug_spec);
+ debug_spec = NULL;
+ goto oom;
+ }
+ TAILQ_INIT(&debug_spec->debug_files);
+ TAILQ_INSERT_TAIL(&sudo_conf_data.debugging, debug_spec, entries);
+ }
+ debug_file = calloc(1, sizeof(*debug_file));
+ if (debug_file == NULL)
+ goto oom;
+ debug_file->debug_file = strndup(path, pathlen);
+ if (debug_file->debug_file == NULL)
+ goto oom;
+ debug_file->debug_flags = strdup(flags);
+ if (debug_file->debug_flags == NULL)
+ goto oom;
+ TAILQ_INSERT_TAIL(&debug_spec->debug_files, debug_file, entries);
+
+ debug_return_int(true);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (debug_file != NULL) {
+ free(debug_file->debug_file);
+ free(debug_file->debug_flags);
+ free(debug_file);
+ }
+ debug_return_int(-1);
+}
+
+/*
+ * "Plugin symbol /path/to/log args..."
+ */
+static int
+parse_plugin(const char *entry, const char *conf_file, unsigned int lineno)
+{
+ struct plugin_info *info = NULL;
+ const char *ep, *path, *symbol;
+ const char *entry_end = entry + strlen(entry);
+ char **options = NULL;
+ size_t pathlen, symlen;
+ unsigned int nopts = 0;
+ debug_decl(parse_plugin, SUDO_DEBUG_UTIL);
+
+ /* Parse symbol. */
+ symbol = sudo_strsplit(entry, entry_end, " \t", &ep);
+ if (symbol == NULL)
+ debug_return_int(false); /* not enough fields */
+ symlen = (size_t)(ep - symbol);
+
+ /* Parse path. */
+ path = sudo_strsplit(NULL, entry_end, " \t", &ep);
+ if (path == NULL)
+ debug_return_int(false); /* not enough fields */
+ pathlen = (size_t)(ep - path);
+
+ /* Split options into an array if present. */
+ while (isblank((unsigned char)*ep))
+ ep++;
+ if (*ep != '\0') {
+ /* Count number of options and allocate array. */
+ const char *cp, *opt = ep;
+
+ /* Count and allocate options array. */
+ for (nopts = 0, cp = sudo_strsplit(opt, entry_end, " \t", &ep);
+ cp != NULL; cp = sudo_strsplit(NULL, entry_end, " \t", &ep)) {
+ nopts++;
+ }
+ options = reallocarray(NULL, nopts + 1, sizeof(*options));
+ if (options == NULL)
+ goto oom;
+
+ /* Fill in options array. */
+ for (nopts = 0, cp = sudo_strsplit(opt, entry_end, " \t", &ep);
+ cp != NULL; cp = sudo_strsplit(NULL, entry_end, " \t", &ep)) {
+ options[nopts] = strndup(cp, (size_t)(ep - cp));
+ if (options[nopts] == NULL)
+ goto oom;
+ nopts++;
+ }
+ options[nopts] = NULL;
+ }
+
+ info = calloc(1, sizeof(*info));
+ if (info == NULL)
+ goto oom;
+ info->symbol_name = strndup(symbol, symlen);
+ if (info->symbol_name == NULL)
+ goto oom;
+ info->path = strndup(path, pathlen);
+ if (info->path == NULL)
+ goto oom;
+ info->options = options;
+ info->lineno = lineno;
+ TAILQ_INSERT_TAIL(&sudo_conf_data.plugins, info, entries);
+
+ debug_return_int(true);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (options != NULL) {
+ while (nopts)
+ free(options[--nopts]);
+ free(options);
+ }
+ if (info != NULL) {
+ free(info->symbol_name);
+ free(info->path);
+ free(info);
+ }
+ debug_return_int(-1);
+}
+
+static int
+set_var_disable_coredump(const char *strval, const char *conf_file,
+ unsigned int lineno)
+{
+ int val = sudo_strtobool(strval);
+ debug_decl(set_var_disable_coredump, SUDO_DEBUG_UTIL);
+
+ if (val == -1) {
+ sudo_warnx(U_("invalid value for %s \"%s\" in %s, line %u"),
+ "disable_coredump", strval, conf_file, lineno);
+ debug_return_int(false);
+ }
+ sudo_conf_data.settings.disable_coredump = val;
+ debug_return_int(true);
+}
+
+static int
+set_var_group_source(const char *strval, const char *conf_file,
+ unsigned int lineno)
+{
+ debug_decl(set_var_group_source, SUDO_DEBUG_UTIL);
+
+ if (strcasecmp(strval, "adaptive") == 0) {
+ sudo_conf_data.settings.group_source = GROUP_SOURCE_ADAPTIVE;
+ } else if (strcasecmp(strval, "static") == 0) {
+ sudo_conf_data.settings.group_source = GROUP_SOURCE_STATIC;
+ } else if (strcasecmp(strval, "dynamic") == 0) {
+ sudo_conf_data.settings.group_source = GROUP_SOURCE_DYNAMIC;
+ } else {
+ sudo_warnx(U_("unsupported group source \"%s\" in %s, line %u"), strval,
+ conf_file, lineno);
+ debug_return_int(false);
+ }
+ debug_return_int(true);
+}
+
+static int
+set_var_max_groups(const char *strval, const char *conf_file,
+ unsigned int lineno)
+{
+ int max_groups;
+ debug_decl(set_var_max_groups, SUDO_DEBUG_UTIL);
+
+ max_groups = (int)sudo_strtonum(strval, 1, 1024, NULL);
+ if (max_groups <= 0) {
+ sudo_warnx(U_("invalid max groups \"%s\" in %s, line %u"), strval,
+ conf_file, lineno);
+ debug_return_int(false);
+ }
+ sudo_conf_data.settings.max_groups = max_groups;
+ debug_return_int(true);
+}
+
+static int
+set_var_probe_interfaces(const char *strval, const char *conf_file,
+ unsigned int lineno)
+{
+ int val = sudo_strtobool(strval);
+ debug_decl(set_var_probe_interfaces, SUDO_DEBUG_UTIL);
+
+ if (val == -1) {
+ sudo_warnx(U_("invalid value for %s \"%s\" in %s, line %u"),
+ "probe_interfaces", strval, conf_file, lineno);
+ debug_return_int(false);
+ }
+ sudo_conf_data.settings.probe_interfaces = val;
+ debug_return_int(true);
+}
+
+const char *
+sudo_conf_askpass_path_v1(void)
+{
+ return sudo_conf_data.path_table[SUDO_CONF_PATH_ASKPASS].pval;
+}
+
+const char *
+sudo_conf_sesh_path_v1(void)
+{
+ return sudo_conf_data.path_table[SUDO_CONF_PATH_SESH].pval;
+}
+
+const char *
+sudo_conf_intercept_path_v1(void)
+{
+ return sudo_conf_data.path_table[SUDO_CONF_PATH_INTERCEPT].pval;
+}
+
+const char *
+sudo_conf_noexec_path_v1(void)
+{
+ return sudo_conf_data.path_table[SUDO_CONF_PATH_NOEXEC].pval;
+}
+
+const char *
+sudo_conf_plugin_dir_path_v1(void)
+{
+ return sudo_conf_data.path_table[SUDO_CONF_PATH_PLUGIN_DIR].pval;
+}
+
+const char *
+sudo_conf_devsearch_path_v1(void)
+{
+ return sudo_conf_data.path_table[SUDO_CONF_PATH_DEVSEARCH].pval;
+}
+
+int
+sudo_conf_group_source_v1(void)
+{
+ return sudo_conf_data.settings.group_source;
+}
+
+int
+sudo_conf_max_groups_v1(void)
+{
+ return sudo_conf_data.settings.max_groups;
+}
+
+struct plugin_info_list *
+sudo_conf_plugins_v1(void)
+{
+ return &sudo_conf_data.plugins;
+}
+
+struct sudo_conf_debug_list *
+sudo_conf_debugging_v1(void)
+{
+ return &sudo_conf_data.debugging;
+}
+
+/* Return the debug files list for a program, or NULL if none. */
+struct sudo_conf_debug_file_list *
+sudo_conf_debug_files_v1(const char *progname)
+{
+ struct sudo_conf_debug *debug_spec;
+ const char *progbase;
+ debug_decl(sudo_conf_debug_files, SUDO_DEBUG_UTIL);
+
+ /* Determine basename if program is fully qualified (like for plugins). */
+ progbase = progname[0] == '/' ? sudo_basename(progname) : progname;
+
+ /* Convert sudoedit -> sudo. */
+ if (strcmp(progbase, "sudoedit") == 0)
+ progbase = "sudo";
+
+ TAILQ_FOREACH(debug_spec, &sudo_conf_data.debugging, entries) {
+ const char *prog = progbase;
+
+ if (debug_spec->progname[0] == '/') {
+ /* Match fully-qualified name, if possible. */
+ prog = progname;
+ }
+ if (strcmp(debug_spec->progname, prog) == 0)
+ debug_return_ptr(&debug_spec->debug_files);
+
+#ifdef RTLD_MEMBER
+ /* Handle names like sudoers.a(sudoers.so) for AIX. */
+ const char *cp = strchr(prog, '(');
+ const char *ep = strchr(prog, ')');
+ if (cp != NULL && ep != NULL) {
+ /* Match on the program name without the member. */
+ size_t len = (size_t)(cp - prog);
+ if (strncmp(debug_spec->progname, prog, len) == 0 &&
+ debug_spec->progname[len] == '\0') {
+ debug_return_ptr(&debug_spec->debug_files);
+ }
+
+ /* Match on the member itself. */
+ cp++;
+ len = (size_t)(ep - cp);
+ if (strncmp(debug_spec->progname, cp, len) == 0 &&
+ debug_spec->progname[len] == '\0') {
+ debug_return_ptr(&debug_spec->debug_files);
+ }
+ }
+#endif
+ }
+ debug_return_ptr(NULL);
+}
+
+bool
+sudo_conf_developer_mode_v1(void)
+{
+ /* Developer mode was removed in sudo 1.9.13. */
+ return false;
+}
+
+bool
+sudo_conf_disable_coredump_v1(void)
+{
+ return sudo_conf_data.settings.disable_coredump;
+}
+
+bool
+sudo_conf_probe_interfaces_v1(void)
+{
+ return sudo_conf_data.settings.probe_interfaces;
+}
+
+/*
+ * Free dynamically allocated parts of sudo_conf_data and
+ * reset to initial values.
+ */
+static void
+sudo_conf_init(int conf_types)
+{
+ struct sudo_conf_debug *debug_spec;
+ struct sudo_debug_file *debug_file;
+ struct plugin_info *plugin_info;
+ size_t i;
+ debug_decl(sudo_conf_init, SUDO_DEBUG_UTIL);
+
+ /* Free and reset paths. */
+ if (ISSET(conf_types, SUDO_CONF_PATHS)) {
+ const struct sudo_conf_path_table path_table[] = SUDO_CONF_PATH_INITIALIZER;
+ sudo_conf_clear_paths();
+ memcpy(sudo_conf_data.path_table, path_table,
+ sizeof(sudo_conf_data.path_table));
+ }
+
+ /* Free and reset debug settings. */
+ if (ISSET(conf_types, SUDO_CONF_DEBUG)) {
+ while ((debug_spec = TAILQ_FIRST(&sudo_conf_data.debugging))) {
+ TAILQ_REMOVE(&sudo_conf_data.debugging, debug_spec, entries);
+ free(debug_spec->progname);
+ while ((debug_file = TAILQ_FIRST(&debug_spec->debug_files))) {
+ TAILQ_REMOVE(&debug_spec->debug_files, debug_file, entries);
+ free(debug_file->debug_file);
+ free(debug_file->debug_flags);
+ free(debug_file);
+ }
+ free(debug_spec);
+ }
+ }
+
+ /* Free and reset plugins. */
+ if (ISSET(conf_types, SUDO_CONF_PLUGINS)) {
+ while ((plugin_info = TAILQ_FIRST(&sudo_conf_data.plugins))) {
+ TAILQ_REMOVE(&sudo_conf_data.plugins, plugin_info, entries);
+ free(plugin_info->symbol_name);
+ free(plugin_info->path);
+ if (plugin_info->options != NULL) {
+ for (i = 0; plugin_info->options[i] != NULL; i++)
+ free(plugin_info->options[i]);
+ free(plugin_info->options);
+ }
+ free(plugin_info);
+ }
+ }
+
+ /* Set initial values. */
+ if (ISSET(conf_types, SUDO_CONF_SETTINGS)) {
+ const struct sudo_conf_settings settings = SUDO_CONF_SETTINGS_INITIALIZER;
+ sudo_conf_data.settings = settings;
+ }
+
+ debug_return;
+}
+
+/*
+ * Read in /etc/sudo.conf and populates sudo_conf_data.
+ */
+int
+sudo_conf_read_v1(const char *path, int conf_types)
+{
+ FILE *fp = NULL;
+ int fd = -1, ret = false;
+ char *prev_locale, *line = NULL;
+ unsigned int conf_lineno = 0;
+ char conf_file[PATH_MAX];
+ size_t linesize = 0;
+ debug_decl(sudo_conf_read, SUDO_DEBUG_UTIL);
+
+ if ((prev_locale = setlocale(LC_ALL, NULL)) == NULL) {
+ sudo_warn("setlocale(LC_ALL, NULL)");
+ debug_return_int(-1);
+ }
+ if ((prev_locale = strdup(prev_locale)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(-1);
+ }
+
+ /* Parse sudo.conf in the "C" locale. */
+ if (prev_locale[0] != 'C' || prev_locale[1] != '\0')
+ setlocale(LC_ALL, "C");
+
+ if (path != NULL) {
+ /* Caller specified a single file, which must exist. */
+ if (strlcpy(conf_file, path, sizeof(conf_file)) >= sizeof(conf_file)) {
+ errno = ENAMETOOLONG;
+ sudo_warn("%s", path);
+ goto done;
+ }
+ fd = open(conf_file, O_RDONLY);
+ if (fd == -1) {
+ sudo_warn(U_("unable to open %s"), conf_file);
+ goto done;
+ }
+ } else {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ struct stat sb;
+ int error;
+
+ /* _PATH_SUDO_CONF is a colon-separated list of path. */
+ fd = sudo_open_conf_path(_PATH_SUDO_CONF, conf_file,
+ sizeof(conf_file), NULL);
+ error = sudo_secure_fd(fd, S_IFREG, ROOT_UID, (gid_t)-1, &sb);
+ switch (error) {
+ case SUDO_PATH_SECURE:
+ /* OK! */
+ break;
+ case SUDO_PATH_MISSING:
+ /* Root should always be able to read sudo.conf. */
+ if (errno != ENOENT && geteuid() == ROOT_UID)
+ sudo_warn(U_("unable to open %s"), conf_file);
+ goto done;
+ case SUDO_PATH_BAD_TYPE:
+ sudo_warnx(U_("%s is not a regular file"), conf_file);
+ goto done;
+ case SUDO_PATH_WRONG_OWNER:
+ sudo_warnx(U_("%s is owned by uid %u, should be %u"),
+ conf_file, (unsigned int) sb.st_uid, ROOT_UID);
+ goto done;
+ case SUDO_PATH_WORLD_WRITABLE:
+ sudo_warnx(U_("%s is world writable"), conf_file);
+ goto done;
+ case SUDO_PATH_GROUP_WRITABLE:
+ sudo_warnx(U_("%s is group writable"), conf_file);
+ goto done;
+ default:
+ sudo_warnx("%s: internal error, unexpected error %d",
+ __func__, error);
+ goto done;
+ }
+#else
+ /* No default sudo.conf when fuzzing. */
+ goto done;
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
+ }
+
+ if ((fp = fdopen(fd, "r")) == NULL) {
+ sudo_warn(U_("unable to open %s"), conf_file);
+ goto done;
+ }
+
+ /* Reset to initial values if necessary. */
+ if (sudo_conf_data.settings.updated)
+ sudo_conf_init(conf_types);
+
+ while (sudo_parseln(&line, &linesize, &conf_lineno, fp, 0) != -1) {
+ struct sudo_conf_table *cur;
+ size_t i;
+ char *cp;
+
+ if (*(cp = line) == '\0')
+ continue; /* empty line or comment */
+
+ for (i = 0, cur = sudo_conf_table; cur->name != NULL; i++, cur++) {
+ if (strncasecmp(cp, cur->name, cur->namelen) == 0 &&
+ isblank((unsigned char)cp[cur->namelen])) {
+ if (ISSET(conf_types, (1 << i))) {
+ cp += cur->namelen;
+ while (isblank((unsigned char)*cp))
+ cp++;
+ ret = cur->parser(cp, conf_file, conf_lineno);
+ switch (ret) {
+ case true:
+ sudo_conf_data.settings.updated = true;
+ break;
+ case false:
+ break;
+ default:
+ goto done;
+ }
+ }
+ break;
+ }
+ }
+ if (cur->name == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_WARN,
+ "%s: %s:%u: unsupported entry: %s", __func__, conf_file,
+ conf_lineno, line);
+ }
+ }
+ ret = true;
+
+done:
+ if (fp != NULL)
+ fclose(fp);
+ else if (fd != -1)
+ close(fd);
+ free(line);
+
+ /* Restore locale if needed. */
+ if (prev_locale[0] != 'C' || prev_locale[1] != '\0')
+ setlocale(LC_ALL, prev_locale);
+ free(prev_locale);
+ debug_return_int(ret);
+}
+
+/*
+ * Used by the sudo_conf regress test to clear compile-time path settings.
+ */
+void
+sudo_conf_clear_paths_v1(void)
+{
+ struct sudo_conf_path_table *cur;
+ debug_decl(sudo_conf_clear_paths, SUDO_DEBUG_UTIL);
+
+ for (cur = sudo_conf_data.path_table; cur->pname != NULL; cur++) {
+ if (cur->dynamic)
+ free((char *)cur->pval);
+ cur->pval = NULL;
+ cur->dynamic = false;
+ }
+}
diff --git a/lib/util/sudo_debug.c b/lib/util/sudo_debug.c
new file mode 100644
index 0000000..47a7ba7
--- /dev/null
+++ b/lib/util/sudo_debug.c
@@ -0,0 +1,1184 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_conf.h>
+#include <sudo_debug.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_plugin.h>
+#include <sudo_util.h>
+
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+/*
+ * The debug priorities and subsystems are currently hard-coded.
+ * In the future we might consider allowing plugins to register their
+ * own subsystems and provide direct access to the debugging API.
+ */
+
+/* Note: this must match the order in sudo_debug.h */
+static const char *const sudo_debug_priorities[] = {
+ "crit",
+ "err",
+ "warn",
+ "notice",
+ "diag",
+ "info",
+ "trace",
+ "debug",
+ NULL
+};
+
+/* Note: this must match the order in sudo_debug.h */
+static const char *const sudo_debug_default_subsystems[] = {
+ "args",
+ "conv",
+ "edit",
+ "event",
+ "exec",
+ "hooks",
+ "main",
+ "netif",
+ "pcomm",
+ "plugin",
+ "pty",
+ "selinux",
+ "util",
+ "utmp",
+ NULL
+};
+
+#define NUM_DEF_SUBSYSTEMS (nitems(sudo_debug_default_subsystems) - 1)
+
+/*
+ * For multiple programs/plugins there is a per-program instance
+ * and one or more outputs (files).
+ */
+struct sudo_debug_output {
+ SLIST_ENTRY(sudo_debug_output) entries;
+ char *filename;
+ int *settings;
+ int fd;
+};
+SLIST_HEAD(sudo_debug_output_list, sudo_debug_output);
+struct sudo_debug_instance {
+ char *program;
+ const char *const *subsystems;
+ const unsigned int *subsystem_ids;
+ unsigned int max_subsystem;
+ unsigned int refcnt;
+ struct sudo_debug_output_list outputs;
+};
+
+/* Support up to 10 instances. */
+#define SUDO_DEBUG_INSTANCE_MAX 10
+static struct sudo_debug_instance *sudo_debug_instances[SUDO_DEBUG_INSTANCE_MAX];
+static int sudo_debug_last_instance = -1;
+
+static char sudo_debug_pidstr[STRLEN_MAX_SIGNED(int) + 3];
+static size_t sudo_debug_pidlen;
+
+#define round_nfds(_n) (((_n) + (4 * NBBY) - 1) & ~((4 * NBBY) - 1))
+static int sudo_debug_fds_size;
+static unsigned char *sudo_debug_fds;
+static int sudo_debug_max_fd = -1;
+
+/* Default instance index to use for common utility functions. */
+static int sudo_debug_active_instance = -1;
+
+/*
+ * Free the specified output structure.
+ */
+static void
+sudo_debug_free_output(struct sudo_debug_output *output)
+{
+ free(output->filename);
+ free(output->settings);
+ if (output->fd != -1)
+ close(output->fd);
+ free(output);
+}
+
+/*
+ * Create a new output file for the specified debug instance.
+ * Returns NULL if the file cannot be opened or memory cannot be allocated.
+ * XXX - check for duplicates
+ */
+static struct sudo_debug_output *
+sudo_debug_new_output(struct sudo_debug_instance *instance,
+ struct sudo_debug_file *debug_file, int minfd)
+{
+ char *buf, *cp, *last, *subsys, *pri;
+ struct sudo_debug_output *output;
+ unsigned int j;
+ int i;
+
+ /* Create new output for the instance. */
+ /* XXX - reuse fd for existing filename? */
+ output = calloc(1, sizeof(*output));
+ if (output == NULL)
+ goto oom;
+ output->fd = -1;
+ output->settings = reallocarray(NULL, instance->max_subsystem + 1,
+ sizeof(int));
+ if (output->settings == NULL)
+ goto oom;
+ output->filename = strdup(debug_file->debug_file);
+ if (output->filename == NULL)
+ goto oom;
+
+ /* Init per-subsystems settings to -1 since 0 is a valid priority. */
+ for (j = 0; j <= instance->max_subsystem; j++)
+ output->settings[j] = -1;
+
+ /* Open debug file. */
+ output->fd = open(output->filename, O_WRONLY|O_APPEND, S_IRUSR|S_IWUSR);
+ if (output->fd == -1) {
+ /* Create debug file as needed and set group ownership. */
+ if (errno == ENOENT) {
+ output->fd = open(output->filename, O_WRONLY|O_APPEND|O_CREAT,
+ S_IRUSR|S_IWUSR);
+ }
+ if (output->fd == -1) {
+ sudo_warn_nodebug("%s", output->filename);
+ goto bad;
+ }
+ ignore_result(fchown(output->fd, (uid_t)-1, 0));
+ }
+ if (output->fd < minfd) {
+ int newfd = fcntl(output->fd, F_DUPFD, minfd);
+ if (newfd == -1) {
+ sudo_warn_nodebug("%s", output->filename);
+ goto bad;
+ }
+ close(output->fd);
+ output->fd = newfd;
+ }
+ if (fcntl(output->fd, F_SETFD, FD_CLOEXEC) == -1) {
+ sudo_warn_nodebug("%s", output->filename);
+ goto bad;
+ }
+ if (sudo_debug_fds_size < output->fd) {
+ /* Bump fds size to the next multiple of 4 * NBBY. */
+ const int old_size = sudo_debug_fds_size / NBBY;
+ const int new_size = round_nfds(output->fd + 1) / NBBY;
+ unsigned char *new_fds;
+
+ new_fds = realloc(sudo_debug_fds, (size_t)new_size);
+ if (new_fds == NULL)
+ goto oom;
+ memset(new_fds + old_size, 0, (size_t)(new_size - old_size));
+ sudo_debug_fds = new_fds;
+ sudo_debug_fds_size = new_size * NBBY;
+ }
+ sudo_setbit(sudo_debug_fds, output->fd);
+ if (output->fd > sudo_debug_max_fd)
+ sudo_debug_max_fd = output->fd;
+
+ /* Parse Debug conf string. */
+ buf = strdup(debug_file->debug_flags);
+ if (buf == NULL)
+ goto oom;
+ for ((cp = strtok_r(buf, ",", &last)); cp != NULL; (cp = strtok_r(NULL, ",", &last))) {
+ /* Should be in the form subsys@pri. */
+ subsys = cp;
+ if ((pri = strchr(cp, '@')) == NULL)
+ continue;
+ *pri++ = '\0';
+
+ /* Look up priority and subsystem, fill in sudo_debug_settings[]. */
+ for (i = 0; sudo_debug_priorities[i] != NULL; i++) {
+ if (strcasecmp(pri, sudo_debug_priorities[i]) == 0) {
+ for (j = 0; instance->subsystems[j] != NULL; j++) {
+ if (strcasecmp(subsys, "all") == 0) {
+ const unsigned int idx = instance->subsystem_ids ?
+ SUDO_DEBUG_SUBSYS(instance->subsystem_ids[j]) : j;
+ if (i > output->settings[idx])
+ output->settings[idx] = i;
+ continue;
+ }
+ if (strcasecmp(subsys, instance->subsystems[j]) == 0) {
+ const unsigned int idx = instance->subsystem_ids ?
+ SUDO_DEBUG_SUBSYS(instance->subsystem_ids[j]) : j;
+ if (i > output->settings[idx])
+ output->settings[idx] = i;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ free(buf);
+
+ return output;
+oom:
+ // -V:sudo_warn_nodebug:575, 618
+ sudo_warn_nodebug(NULL);
+bad:
+ if (output != NULL)
+ sudo_debug_free_output(output);
+ return NULL;
+}
+
+/*
+ * Register a program/plugin with the debug framework,
+ * parses settings string from sudo.conf and opens debug_files.
+ * If subsystem names are specified they override the default values.
+ * NOTE: subsystems must not be freed by caller unless deregistered.
+ * Sets the active instance to the newly registered instance.
+ * Returns instance index on success, SUDO_DEBUG_INSTANCE_INITIALIZER
+ * if no debug files are specified and SUDO_DEBUG_INSTANCE_ERROR
+ * on error.
+ */
+int
+sudo_debug_register_v2(const char *program, const char *const subsystems[],
+ unsigned int ids[], struct sudo_conf_debug_file_list *debug_files,
+ int minfd)
+{
+ struct sudo_debug_instance *instance = NULL;
+ struct sudo_debug_output *output;
+ struct sudo_debug_file *debug_file;
+ int idx, free_idx = -1;
+ debug_decl_func(sudo_debug_register);
+
+ if (debug_files == NULL)
+ return SUDO_DEBUG_INSTANCE_INITIALIZER;
+
+ /* Use default subsystem names if none are provided. */
+ if (subsystems == NULL) {
+ subsystems = sudo_debug_default_subsystems;
+ } else if (ids == NULL) {
+ /* If subsystems are specified we must have ids[] too. */
+ return SUDO_DEBUG_INSTANCE_ERROR;
+ }
+
+ /* Search for existing instance. */
+ for (idx = 0; idx <= sudo_debug_last_instance; idx++) {
+ if (sudo_debug_instances[idx] == NULL) {
+ free_idx = idx;
+ continue;
+ }
+ if (sudo_debug_instances[idx]->subsystems == subsystems &&
+ strcmp(sudo_debug_instances[idx]->program, program) == 0) {
+ instance = sudo_debug_instances[idx];
+ break;
+ }
+ }
+
+ if (instance == NULL) {
+ size_t i;
+ unsigned int j, max_id = NUM_DEF_SUBSYSTEMS - 1;
+
+ /* Fill in subsystem name -> id mapping as needed. */
+ if (ids != NULL) {
+ for (i = 0; subsystems[i] != NULL; i++) {
+ /* Check default subsystems. */
+ for (j = 0; j < NUM_DEF_SUBSYSTEMS; j++) {
+ if (strcmp(subsystems[i], sudo_debug_default_subsystems[j]) == 0)
+ break;
+ }
+ if (j == NUM_DEF_SUBSYSTEMS)
+ j = ++max_id;
+ ids[i] = ((j + 1) << 6);
+ }
+ }
+
+ if (free_idx != -1)
+ idx = free_idx;
+ if (idx == SUDO_DEBUG_INSTANCE_MAX) {
+ /* XXX - realloc? */
+ sudo_warnx_nodebug("too many debug instances (max %d)", SUDO_DEBUG_INSTANCE_MAX);
+ return SUDO_DEBUG_INSTANCE_ERROR;
+ }
+ if (idx != sudo_debug_last_instance + 1 && idx != free_idx) {
+ sudo_warnx_nodebug("%s: instance number mismatch: expected %d or %d, got %d", __func__, sudo_debug_last_instance + 1, free_idx, idx);
+ return SUDO_DEBUG_INSTANCE_ERROR;
+ }
+ if ((instance = malloc(sizeof(*instance))) == NULL)
+ return SUDO_DEBUG_INSTANCE_ERROR;
+ if ((instance->program = strdup(program)) == NULL) {
+ free(instance);
+ return SUDO_DEBUG_INSTANCE_ERROR;
+ }
+ instance->subsystems = subsystems;
+ instance->subsystem_ids = ids;
+ instance->max_subsystem = max_id;
+ instance->refcnt = 1;
+ SLIST_INIT(&instance->outputs);
+ sudo_debug_instances[idx] = instance;
+ if (idx != free_idx)
+ sudo_debug_last_instance++;
+ } else {
+ /* Check for matching instance but different ids[]. */
+ if (ids != NULL && instance->subsystem_ids != ids) {
+ size_t i;
+
+ for (i = 0; subsystems[i] != NULL; i++)
+ ids[i] = instance->subsystem_ids[i];
+ }
+ instance->refcnt++;
+ }
+
+ TAILQ_FOREACH(debug_file, debug_files, entries) {
+ output = sudo_debug_new_output(instance, debug_file, minfd);
+ if (output != NULL)
+ SLIST_INSERT_HEAD(&instance->outputs, output, entries);
+ }
+
+ /* Set active instance. */
+ sudo_debug_active_instance = idx;
+
+ /* Stash the pid string so we only have to format it once. */
+ if (sudo_debug_pidlen == 0) {
+ (void)snprintf(sudo_debug_pidstr, sizeof(sudo_debug_pidstr), "[%d] ",
+ (int)getpid());
+ sudo_debug_pidlen = strlen(sudo_debug_pidstr);
+ }
+
+ return idx;
+}
+
+int
+sudo_debug_register_v1(const char *program, const char *const subsystems[],
+ unsigned int ids[], struct sudo_conf_debug_file_list *debug_files)
+{
+ return sudo_debug_register_v2(program, subsystems, ids, debug_files, -1);
+}
+
+/*
+ * De-register the specified instance from the debug subsystem
+ * and free up any associated data structures.
+ * Returns the number of remaining references for the instance or -1 on error.
+ */
+int
+sudo_debug_deregister_v1(int idx)
+{
+ struct sudo_debug_instance *instance;
+ struct sudo_debug_output *output, *next;
+ debug_decl_func(sudo_debug_deregister);
+
+ if (idx < 0 || idx > sudo_debug_last_instance) {
+ sudo_warnx_nodebug("%s: invalid instance ID %d, max %d",
+ __func__, idx, sudo_debug_last_instance);
+ return -1;
+ }
+ /* Reset active instance as needed. */
+ if (sudo_debug_active_instance == idx)
+ sudo_debug_active_instance = -1;
+
+ instance = sudo_debug_instances[idx];
+ if (instance == NULL)
+ return -1; /* already deregistered */
+
+ if (--instance->refcnt != 0)
+ return (int)instance->refcnt; /* ref held by other caller */
+
+ /* Free up instance data, note that subsystems[] is owned by caller. */
+ sudo_debug_instances[idx] = NULL;
+ SLIST_FOREACH_SAFE(output, &instance->outputs, entries, next) {
+ close(output->fd);
+ free(output->filename);
+ free(output->settings);
+ free(output);
+ }
+ free(instance->program);
+ free(instance);
+
+ if (idx == sudo_debug_last_instance)
+ sudo_debug_last_instance--;
+
+ return 0;
+}
+
+/*
+ * Parse the "filename flags,..." debug_flags entry from sudo.conf
+ * and insert a new sudo_debug_file struct into the list.
+ * Returns 0 on success, 1 on parse error or -1 on malloc failure.
+ */
+int
+sudo_debug_parse_flags_v1(struct sudo_conf_debug_file_list *debug_files,
+ const char *entry)
+{
+ struct sudo_debug_file *debug_file;
+ const char *filename, *flags;
+ size_t namelen;
+
+ /* Only process new-style debug flags: filename flags,... */
+ filename = entry;
+ if (*filename != '/' || (flags = strpbrk(filename, " \t")) == NULL)
+ return 1;
+ namelen = (size_t)(flags - filename);
+ while (isblank((unsigned char)*flags))
+ flags++;
+ if (*flags != '\0') {
+ if ((debug_file = calloc(1, sizeof(*debug_file))) == NULL)
+ goto oom;
+ if ((debug_file->debug_file = strndup(filename, namelen)) == NULL)
+ goto oom;
+ if ((debug_file->debug_flags = strdup(flags)) == NULL)
+ goto oom;
+ TAILQ_INSERT_TAIL(debug_files, debug_file, entries);
+ }
+ return 0;
+oom:
+ if (debug_file != NULL) {
+ free(debug_file->debug_file);
+ free(debug_file->debug_flags);
+ free(debug_file);
+ }
+ return -1;
+}
+
+int
+sudo_debug_get_instance_v1(const char *program)
+{
+ int idx;
+
+ for (idx = 0; idx <= sudo_debug_last_instance; idx++) {
+ if (sudo_debug_instances[idx] == NULL)
+ continue;
+ if (strcmp(sudo_debug_instances[idx]->program, program) == 0)
+ return idx;
+ }
+ return SUDO_DEBUG_INSTANCE_INITIALIZER;
+}
+
+pid_t
+sudo_debug_fork_v1(void)
+{
+ pid_t pid;
+
+ if ((pid = fork()) == 0) {
+ (void)snprintf(sudo_debug_pidstr, sizeof(sudo_debug_pidstr), "[%d] ",
+ (int)getpid());
+ sudo_debug_pidlen = strlen(sudo_debug_pidstr);
+ }
+
+ return pid;
+}
+
+/* Functions versions of sudo_debug_enter* for backwards compatibility. */
+void
+sudo_debug_enter_v1(const char *func, const char *file, int line,
+ unsigned int subsys)
+{
+ sudo_debug_enter(func, file, line, subsys);
+}
+
+void
+sudo_debug_exit_v1(const char *func, const char *file, int line,
+ unsigned int subsys)
+{
+ sudo_debug_exit(func, file, line, subsys);
+}
+
+void
+sudo_debug_exit_int_v1(const char *func, const char *file, int line,
+ unsigned int subsys, int ret)
+{
+ sudo_debug_exit_int(func, file, line, subsys, ret);
+}
+
+void
+sudo_debug_exit_uint_v1(const char *func, const char *file, int line,
+ unsigned int subsys, unsigned int ret)
+{
+ sudo_debug_exit_uint(func, file, line, subsys, ret);
+}
+
+void
+sudo_debug_exit_long_v1(const char *func, const char *file, int line,
+ unsigned int subsys, long ret)
+{
+ sudo_debug_exit_long(func, file, line, subsys, ret);
+}
+
+void
+sudo_debug_exit_id_t_v1(const char *func, const char *file, int line,
+ unsigned int subsys, id_t ret)
+{
+ sudo_debug_exit_id_t(func, file, line, subsys, ret);
+}
+
+void
+sudo_debug_exit_size_t_v1(const char *func, const char *file, int line,
+ unsigned int subsys, size_t ret)
+{
+ sudo_debug_exit_size_t(func, file, line, subsys, ret);
+}
+
+void
+sudo_debug_exit_ssize_t_v1(const char *func, const char *file, int line,
+ unsigned int subsys, ssize_t ret)
+{
+ sudo_debug_exit_ssize_t(func, file, line, subsys, ret);
+}
+
+void
+sudo_debug_exit_time_t_v1(const char *func, const char *file, int line,
+ unsigned int subsys, time_t ret)
+{
+ sudo_debug_exit_time_t(func, file, line, subsys, ret);
+}
+
+void
+sudo_debug_exit_mode_t_v1(const char *func, const char *file, int line,
+ unsigned int subsys, mode_t ret)
+{
+ sudo_debug_exit_mode_t(func, file, line, subsys, ret);
+}
+
+void
+sudo_debug_exit_bool_v1(const char *func, const char *file, int line,
+ unsigned int subsys, bool ret)
+{
+ sudo_debug_exit_bool(func, file, line, subsys, ret);
+}
+
+void
+sudo_debug_exit_str_v1(const char *func, const char *file, int line,
+ unsigned int subsys, const char *ret)
+{
+ sudo_debug_exit_str(func, file, line, subsys, ret);
+}
+
+void
+sudo_debug_exit_str_masked_v1(const char *func, const char *file, int line,
+ unsigned int subsys, const char *ret)
+{
+ sudo_debug_exit_str_masked(func, file, line, subsys, ret);
+}
+
+void
+sudo_debug_exit_ptr_v1(const char *func, const char *file, int line,
+ unsigned int subsys, const void *ret)
+{
+ sudo_debug_exit_ptr(func, file, line, subsys, ret);
+}
+
+void
+sudo_debug_write2_v1(int fd, const char *func, const char *file, int lineno,
+ const char *str, unsigned int len, int errnum)
+{
+ char numbuf[(((sizeof(int) * 8) + 2) / 3) + 2];
+ char timebuf[64];
+ struct timeval tv;
+ struct iovec iov[12];
+ int iovcnt = 3;
+
+ /* Cannot use sudo_gettime_real() here since it calls sudo_debug. */
+ timebuf[0] = '\0';
+ if (gettimeofday(&tv, NULL) != -1) {
+ time_t now = tv.tv_sec;
+ struct tm tm;
+ size_t tlen;
+ if (localtime_r(&now, &tm) != NULL) {
+ timebuf[sizeof(timebuf) - 1] = '\0';
+ tlen = strftime(timebuf, sizeof(timebuf), "%b %e %H:%M:%S", &tm);
+ if (tlen == 0 || timebuf[sizeof(timebuf) - 1] != '\0') {
+ /* contents are undefined on error */
+ timebuf[0] = '\0';
+ } else {
+ (void)snprintf(timebuf + tlen, sizeof(timebuf) - tlen,
+ ".%03d ", (int)tv.tv_usec / 1000);
+ }
+ }
+ }
+ iov[0].iov_base = timebuf;
+ iov[0].iov_len = strlen(timebuf);
+
+ /* Prepend program name and pid with a trailing space. */
+ iov[1].iov_base = (char *)getprogname();
+ iov[1].iov_len = strlen(iov[1].iov_base);
+ iov[2].iov_base = sudo_debug_pidstr;
+ iov[2].iov_len = sudo_debug_pidlen;
+
+ /* Add string, trimming any trailing newlines. */
+ while (len > 0 && str[len - 1] == '\n')
+ len--;
+ if (len != 0) {
+ iov[iovcnt].iov_base = (char *)str;
+ iov[iovcnt].iov_len = len;
+ iovcnt++;
+ }
+
+ /* Append error string if errno is specified. */
+ if (errnum) {
+ if (len != 0) {
+ iov[iovcnt].iov_base = (char *)": ";
+ iov[iovcnt].iov_len = 2;
+ iovcnt++;
+ }
+ iov[iovcnt].iov_base = strerror(errnum);
+ iov[iovcnt].iov_len = strlen(iov[iovcnt].iov_base);
+ iovcnt++;
+ }
+
+ /* If function, file and lineno are specified, append them. */
+ if (func != NULL && file != NULL && lineno != 0) {
+ iov[iovcnt].iov_base = (char *)" @ ";
+ iov[iovcnt].iov_len = 3;
+ iovcnt++;
+
+ iov[iovcnt].iov_base = (char *)func;
+ iov[iovcnt].iov_len = strlen(func);
+ iovcnt++;
+
+ iov[iovcnt].iov_base = (char *)"() ";
+ iov[iovcnt].iov_len = 3;
+ iovcnt++;
+
+ iov[iovcnt].iov_base = (char *)file;
+ iov[iovcnt].iov_len = strlen(file);
+ iovcnt++;
+
+ (void)snprintf(numbuf, sizeof(numbuf), ":%d", lineno);
+ iov[iovcnt].iov_base = numbuf;
+ iov[iovcnt].iov_len = strlen(numbuf);
+ iovcnt++;
+ }
+
+ /* Append newline. */
+ iov[iovcnt].iov_base = (char *)"\n";
+ iov[iovcnt].iov_len = 1;
+ iovcnt++;
+
+ /* Write message in a single syscall */
+ ignore_result(writev(fd, iov, iovcnt));
+}
+
+bool
+sudo_debug_needed_v1(unsigned int level)
+{
+ unsigned int subsys;
+ int pri;
+ struct sudo_debug_instance *instance;
+ struct sudo_debug_output *output;
+ bool result = false;
+
+ if (sudo_debug_active_instance == -1)
+ goto out;
+
+ /* Extract priority and subsystem from level. */
+ pri = (int)SUDO_DEBUG_PRI(level);
+ subsys = SUDO_DEBUG_SUBSYS(level);
+
+ if (sudo_debug_active_instance > sudo_debug_last_instance)
+ goto out;
+
+ instance = sudo_debug_instances[sudo_debug_active_instance];
+ if (instance == NULL)
+ goto out;
+
+ if (subsys <= instance->max_subsystem) {
+ SLIST_FOREACH(output, &instance->outputs, entries) {
+ if (output->settings[subsys] >= pri) {
+ result = true;
+ break;
+ }
+ }
+ }
+out:
+ return result;
+}
+
+void
+sudo_debug_vprintf2_v1(const char *func, const char *file, int lineno,
+ unsigned int level, const char * restrict fmt, va_list ap)
+{
+ int pri, saved_errno = errno;
+ unsigned int subsys;
+ char static_buf[1024], *buf = static_buf;
+ struct sudo_debug_instance *instance;
+ struct sudo_debug_output *output;
+ debug_decl_func(sudo_debug_vprintf2);
+
+ if (sudo_debug_active_instance == -1)
+ goto out;
+
+ /* Extract priority and subsystem from level. */
+ pri = (int)SUDO_DEBUG_PRI(level);
+ subsys = SUDO_DEBUG_SUBSYS(level);
+
+ /* Disable extra info if SUDO_DEBUG_LINENO is not enabled. */
+ if (!ISSET(level, SUDO_DEBUG_LINENO)) {
+ func = NULL;
+ file = NULL;
+ lineno = 0;
+ }
+
+ /* Find matching instance. */
+ if (sudo_debug_active_instance > sudo_debug_last_instance) {
+ sudo_warnx_nodebug("%s: invalid instance ID %d, max %d",
+ __func__, sudo_debug_active_instance, sudo_debug_last_instance);
+ goto out;
+ }
+ instance = sudo_debug_instances[sudo_debug_active_instance];
+ if (instance == NULL) {
+ sudo_warnx_nodebug("%s: unregistered instance index %d", __func__,
+ sudo_debug_active_instance);
+ goto out;
+ }
+
+ SLIST_FOREACH(output, &instance->outputs, entries) {
+ /* Make sure we want debug info at this level. */
+ if (subsys <= instance->max_subsystem && output->settings[subsys] >= pri) {
+ int errcode, buflen = 0;
+ va_list ap2;
+
+ if (fmt != NULL) {
+ /* Operate on a copy of ap to support multiple outputs. */
+ va_copy(ap2, ap);
+ buflen = vsnprintf(static_buf, sizeof(static_buf), fmt, ap2);
+ va_end(ap2);
+ if (buflen < 0) {
+ sudo_warnx_nodebug("%s: invalid format string \"%s\"",
+ __func__, fmt);
+ buflen = 0;
+ } else if (buflen >= ssizeof(static_buf)) {
+ /* Not enough room in static buf, allocate dynamically. */
+ va_copy(ap2, ap);
+ buflen = vasprintf(&buf, fmt, ap2);
+ if (buflen == -1) {
+ buf = static_buf;
+ buflen = (int)strlen(buf);
+ }
+ va_end(ap2);
+ }
+ }
+ errcode = ISSET(level, SUDO_DEBUG_ERRNO) ? saved_errno : 0;
+ sudo_debug_write2(output->fd, func, file, lineno, buf,
+ (unsigned int)buflen, errcode);
+ if (buf != static_buf) {
+ free(buf);
+ buf = static_buf;
+ }
+ }
+ }
+out:
+ errno = saved_errno;
+}
+
+#ifdef NO_VARIADIC_MACROS
+void
+sudo_debug_printf_nvm_v1(int pri, const char * restrict fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ sudo_debug_vprintf2(NULL, NULL, 0, pri, fmt, ap);
+ va_end(ap);
+}
+#endif /* NO_VARIADIC_MACROS */
+
+void
+sudo_debug_printf2_v1(const char *func, const char *file, int lineno,
+ unsigned int level, const char * restrict fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ sudo_debug_vprintf2(func, file, lineno, level, fmt, ap);
+ va_end(ap);
+}
+
+#define EXEC_PREFIX "exec "
+
+void
+sudo_debug_execve2_v1(unsigned int level, const char *path, char *const argv[],
+ char *const envp[])
+{
+ int pri, saved_errno = errno;
+ unsigned int subsys;
+ struct sudo_debug_instance *instance;
+ struct sudo_debug_output *output;
+ char * const *av;
+ char *cp, static_buf[4096], *buf = static_buf;
+ size_t buflen, plen;
+ debug_decl_func(sudo_debug_execve2);
+
+ if (sudo_debug_active_instance == -1 || path == NULL)
+ goto out;
+
+ /* Extract priority and subsystem from level. */
+ pri = (int)SUDO_DEBUG_PRI(level);
+ subsys = SUDO_DEBUG_SUBSYS(level);
+
+ /* Find matching instance. */
+ if (sudo_debug_active_instance > sudo_debug_last_instance) {
+ sudo_warnx_nodebug("%s: invalid instance ID %d, max %d",
+ __func__, sudo_debug_active_instance, sudo_debug_last_instance);
+ goto out;
+ }
+ instance = sudo_debug_instances[sudo_debug_active_instance];
+ if (instance == NULL) {
+ sudo_warnx_nodebug("%s: unregistered instance index %d", __func__,
+ sudo_debug_active_instance);
+ goto out;
+ }
+ if (subsys > instance->max_subsystem)
+ goto out;
+
+ SLIST_FOREACH(output, &instance->outputs, entries) {
+ bool log_envp = false;
+
+ /* Make sure we want debug info at this level. */
+ if (output->settings[subsys] < pri)
+ continue;
+
+ /* Log envp for debug level "debug". */
+ if (output->settings[subsys] >= SUDO_DEBUG_DEBUG - 1 && envp != NULL)
+ log_envp = true;
+
+ /* Alloc and build up buffer. */
+ plen = strlen(path);
+ buflen = sizeof(EXEC_PREFIX) -1 + plen;
+ if (argv != NULL && argv[0] != NULL) {
+ buflen += sizeof(" []") - 1;
+ for (av = argv; *av; av++)
+ buflen += strlen(*av) + 1;
+ buflen--;
+ }
+ if (log_envp && envp[0] != NULL) {
+ buflen += sizeof(" []") - 1;
+ for (av = envp; *av; av++)
+ buflen += strlen(*av) + 1;
+ buflen--;
+ }
+ if (buflen >= sizeof(static_buf)) {
+ buf = malloc(buflen + 1);
+ if (buf == NULL)
+ goto out;
+ }
+
+ /* Copy prefix and command. */
+ memcpy(buf, EXEC_PREFIX, sizeof(EXEC_PREFIX) - 1);
+ cp = buf + sizeof(EXEC_PREFIX) - 1;
+ memcpy(cp, path, plen);
+ cp += plen;
+
+ /* Copy argv. */
+ if (argv != NULL && argv[0] != NULL) {
+ *cp++ = ' ';
+ *cp++ = '[';
+ for (av = argv; *av; av++) {
+ size_t avlen = strlen(*av);
+ memcpy(cp, *av, avlen);
+ cp += avlen;
+ *cp++ = ' ';
+ }
+ cp[-1] = ']';
+ }
+
+ if (log_envp && envp[0] != NULL) {
+ *cp++ = ' ';
+ *cp++ = '[';
+ for (av = envp; *av; av++) {
+ size_t avlen = strlen(*av);
+ memcpy(cp, *av, avlen);
+ cp += avlen;
+ *cp++ = ' ';
+ }
+ cp[-1] = ']';
+ }
+
+ *cp = '\0';
+
+ sudo_debug_write(output->fd, buf, (unsigned int)buflen, 0);
+ if (buf != static_buf) {
+ free(buf);
+ buf = static_buf;
+ }
+ }
+out:
+ errno = saved_errno;
+}
+
+/*
+ * Returns the active instance or SUDO_DEBUG_INSTANCE_INITIALIZER
+ * if no instance is active.
+ */
+int
+sudo_debug_get_active_instance_v1(void)
+{
+ return sudo_debug_active_instance;
+}
+
+/*
+ * Sets a new active instance, returning the old one.
+ * Note that the old instance may be SUDO_DEBUG_INSTANCE_INITIALIZER
+ * if this is the only instance.
+ */
+int
+sudo_debug_set_active_instance_v1(int idx)
+{
+ const int old_idx = sudo_debug_active_instance;
+
+ if (idx >= -1 && idx <= sudo_debug_last_instance)
+ sudo_debug_active_instance = idx;
+ return old_idx;
+}
+
+/*
+ * Replace the ofd with nfd in all outputs if present.
+ * Also updates sudo_debug_fds.
+ */
+void
+sudo_debug_update_fd_v1(int ofd, int nfd)
+{
+ int idx;
+
+ if (ofd <= sudo_debug_max_fd && sudo_isset(sudo_debug_fds, ofd)) {
+ /* Update sudo_debug_fds. */
+ sudo_clrbit(sudo_debug_fds, ofd);
+ sudo_setbit(sudo_debug_fds, nfd);
+
+ /* Update the outputs. */
+ for (idx = 0; idx <= sudo_debug_last_instance; idx++) {
+ struct sudo_debug_instance *instance;
+ struct sudo_debug_output *output;
+
+ instance = sudo_debug_instances[idx];
+ if (instance == NULL)
+ continue;
+ SLIST_FOREACH(output, &instance->outputs, entries) {
+ if (output->fd == ofd)
+ output->fd = nfd;
+ }
+ }
+ }
+}
+
+/*
+ * Returns the highest debug output fd or -1 if no debug files open.
+ * Fills in fds with the value of sudo_debug_fds.
+ */
+int
+sudo_debug_get_fds_v1(unsigned char **fds)
+{
+ *fds = sudo_debug_fds;
+ return sudo_debug_max_fd;
+}
+#else /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
+int
+sudo_debug_register_v2(const char *program, const char *const subsystems[],
+ unsigned int ids[], struct sudo_conf_debug_file_list *debug_files,
+ int minfd)
+{
+ return SUDO_DEBUG_INSTANCE_INITIALIZER;
+}
+
+int
+sudo_debug_register_v1(const char *program, const char *const subsystems[],
+ unsigned int ids[], struct sudo_conf_debug_file_list *debug_files)
+{
+ return SUDO_DEBUG_INSTANCE_INITIALIZER;
+}
+
+int
+sudo_debug_deregister_v1(int idx)
+{
+ return -1;
+}
+
+int
+sudo_debug_parse_flags_v1(struct sudo_conf_debug_file_list *debug_files,
+ const char *entry)
+{
+ return 0;
+}
+
+int
+sudo_debug_get_instance_v1(const char *program)
+{
+ return SUDO_DEBUG_INSTANCE_INITIALIZER;
+}
+
+pid_t
+sudo_debug_fork_v1(void)
+{
+ return fork();
+}
+
+void
+sudo_debug_enter_v1(const char *func, const char *file, int line,
+ unsigned int subsys)
+{
+}
+
+void
+sudo_debug_exit_v1(const char *func, const char *file, int line,
+ unsigned int subsys)
+{
+}
+
+void
+sudo_debug_exit_int_v1(const char *func, const char *file, int line,
+ unsigned int subsys, int ret)
+{
+}
+
+void
+sudo_debug_exit_uint_v1(const char *func, const char *file, int line,
+ unsigned int subsys, unsigned int ret)
+{
+}
+
+void
+sudo_debug_exit_long_v1(const char *func, const char *file, int line,
+ unsigned int subsys, long ret)
+{
+}
+
+void
+sudo_debug_exit_id_t_v1(const char *func, const char *file, int line,
+ unsigned int subsys, id_t ret)
+{
+}
+
+void
+sudo_debug_exit_size_t_v1(const char *func, const char *file, int line,
+ unsigned int subsys, size_t ret)
+{
+}
+
+void
+sudo_debug_exit_ssize_t_v1(const char *func, const char *file, int line,
+ unsigned int subsys, ssize_t ret)
+{
+}
+
+void
+sudo_debug_exit_time_t_v1(const char *func, const char *file, int line,
+ unsigned int subsys, time_t ret)
+{
+}
+
+void
+sudo_debug_exit_mode_t_v1(const char *func, const char *file, int line,
+ unsigned int subsys, mode_t ret)
+{
+}
+
+void
+sudo_debug_exit_bool_v1(const char *func, const char *file, int line,
+ unsigned int subsys, bool ret)
+{
+}
+
+void
+sudo_debug_exit_str_v1(const char *func, const char *file, int line,
+ unsigned int subsys, const char *ret)
+{
+}
+
+void
+sudo_debug_exit_str_masked_v1(const char *func, const char *file, int line,
+ unsigned int subsys, const char *ret)
+{
+}
+
+void
+sudo_debug_exit_ptr_v1(const char *func, const char *file, int line,
+ unsigned int subsys, const void *ret)
+{
+}
+
+void
+sudo_debug_write2_v1(int fd, const char *func, const char *file, int lineno,
+ const char *str, unsigned int len, int errnum)
+{
+}
+
+bool
+sudo_debug_needed_v1(unsigned int level)
+{
+ return false;
+}
+
+void
+sudo_debug_vprintf2_v1(const char *func, const char *file, int lineno,
+ unsigned int level, const char * restrict fmt, va_list ap)
+{
+}
+
+#ifdef NO_VARIADIC_MACROS
+void
+sudo_debug_printf_nvm_v1(int pri, const char * restrict fmt, ...)
+{
+}
+#endif /* NO_VARIADIC_MACROS */
+
+void
+sudo_debug_printf2_v1(const char *func, const char *file, int lineno,
+ unsigned int level, const char * restrict fmt, ...)
+{
+}
+
+void
+sudo_debug_execve2_v1(unsigned int level, const char *path, char *const argv[],
+ char *const envp[])
+{
+}
+
+int
+sudo_debug_get_active_instance_v1(void)
+{
+ return SUDO_DEBUG_INSTANCE_INITIALIZER;
+}
+
+int
+sudo_debug_set_active_instance_v1(int idx)
+{
+ return SUDO_DEBUG_INSTANCE_INITIALIZER;
+}
+
+void
+sudo_debug_update_fd_v1(int ofd, int nfd)
+{
+}
+
+int
+sudo_debug_get_fds_v1(unsigned char **fds)
+{
+ return -1;
+}
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
diff --git a/lib/util/sudo_dso.c b/lib/util/sudo_dso.c
new file mode 100644
index 0000000..0124b20
--- /dev/null
+++ b/lib/util/sudo_dso.c
@@ -0,0 +1,432 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010, 2012-2014, 2021-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef __linux__
+# include <sys/stat.h>
+# include <sys/utsname.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(HAVE_SHL_LOAD)
+# include <dl.h>
+#elif defined(HAVE_DLOPEN)
+# include <dlfcn.h>
+#endif
+#include <errno.h>
+
+#include <sudo_compat.h>
+#include <sudo_dso.h>
+#include <sudo_util.h>
+
+/*
+ * Pointer for statically compiled symbols.
+ */
+static struct sudo_preload_table *preload_table;
+
+void
+sudo_dso_preload_table_v1(struct sudo_preload_table *table)
+{
+ preload_table = table;
+}
+
+#if defined(HAVE_SHL_LOAD)
+
+# ifndef DYNAMIC_PATH
+# define DYNAMIC_PATH 0
+# endif
+
+void *
+sudo_dso_load_v1(const char *path, int mode)
+{
+ struct sudo_preload_table *pt;
+ int flags = DYNAMIC_PATH | BIND_VERBOSE;
+
+ if (mode == 0)
+ mode = SUDO_DSO_LAZY; /* default behavior */
+
+ /* Check prelinked symbols first. */
+ if (preload_table != NULL) {
+ for (pt = preload_table; pt->handle != NULL; pt++) {
+ if (pt->path != NULL && strcmp(path, pt->path) == 0)
+ return pt->handle;
+ }
+ }
+
+ /* We don't support SUDO_DSO_GLOBAL or SUDO_DSO_LOCAL yet. */
+ if (ISSET(mode, SUDO_DSO_LAZY))
+ flags |= BIND_DEFERRED;
+ if (ISSET(mode, SUDO_DSO_NOW))
+ flags |= BIND_IMMEDIATE;
+
+ return (void *)shl_load(path, flags, 0L);
+}
+
+int
+sudo_dso_unload_v1(void *handle)
+{
+ struct sudo_preload_table *pt;
+
+ /* Check prelinked symbols first. */
+ if (preload_table != NULL) {
+ for (pt = preload_table; pt->handle != NULL; pt++) {
+ if (pt->handle == handle)
+ return 0;
+ }
+ }
+
+ return shl_unload((shl_t)handle);
+}
+
+void *
+sudo_dso_findsym_v1(void *vhandle, const char *symbol)
+{
+ struct sudo_preload_table *pt;
+ shl_t handle = vhandle;
+ void *value = NULL;
+
+ /* Check prelinked symbols first. */
+ if (preload_table != NULL) {
+ for (pt = preload_table; pt->handle != NULL; pt++) {
+ if (pt->handle == handle) {
+ struct sudo_preload_symbol *sym;
+ for (sym = pt->symbols; sym->name != NULL; sym++) {
+ if (strcmp(sym->name, symbol) == 0)
+ return sym->addr;
+ }
+ errno = ENOENT;
+ return NULL;
+ }
+ }
+ }
+
+ /*
+ * Note that the behavior of of SUDO_DSO_NEXT and SUDO_DSO_SELF
+ * differs from most implementations when called from
+ * a shared library.
+ */
+ if (vhandle == SUDO_DSO_NEXT) {
+ /* Iterate over all shared libs looking for symbol. */
+ shl_t myhandle = PROG_HANDLE;
+ struct shl_descriptor *desc;
+ int idx = 0;
+
+ /* Find program's real handle. */
+ if (shl_gethandle(PROG_HANDLE, &desc) == 0)
+ myhandle = desc->handle;
+ while (shl_get(idx++, &desc) == 0) {
+ if (desc->handle == myhandle)
+ continue;
+ if (shl_findsym(&desc->handle, symbol, TYPE_UNDEFINED, &value) == 0)
+ break;
+ }
+ } else {
+ if (vhandle == SUDO_DSO_DEFAULT)
+ handle = NULL;
+ else if (vhandle == SUDO_DSO_SELF)
+ handle = PROG_HANDLE;
+ (void)shl_findsym(&handle, symbol, TYPE_UNDEFINED, &value);
+ }
+
+ return value;
+}
+
+char *
+sudo_dso_strerror_v1(void)
+{
+ return strerror(errno);
+}
+
+#elif defined(HAVE_DLOPEN)
+
+# ifndef RTLD_GLOBAL
+# define RTLD_GLOBAL 0
+# endif
+
+/* Default member names for AIX when dlopen()ing an ar (.a) file. */
+# ifdef RTLD_MEMBER
+# ifdef __LP64__
+# define SUDO_DSO_MEMBER "shr_64.o"
+# else
+# define SUDO_DSO_MEMBER "shr.o"
+# endif
+# endif
+
+# if defined(__linux__)
+/*
+ * On Linux systems that use multi-arch, the actual DSO may be
+ * in a machine-specific subdirectory. If the specified path
+ * contains /lib/ or /libexec/, insert a multi-arch directory
+ * after it.
+ */
+static void *
+dlopen_multi_arch(const char *path, int flags)
+{
+ void *ret = NULL;
+ struct stat sb;
+ char *newpath;
+
+ /* Only try multi-arch if the original path does not exist. */
+ if (stat(path, &sb) == -1 && errno == ENOENT) {
+ newpath = sudo_stat_multiarch(path, &sb);
+ if (newpath != NULL) {
+ ret = dlopen(newpath, flags);
+ free(newpath);
+ }
+ }
+ return ret;
+}
+# else
+static void *
+dlopen_multi_arch(const char *path, int flags)
+{
+ return NULL;
+}
+# endif /* __linux__ */
+
+void *
+sudo_dso_load_v1(const char *path, int mode)
+{
+ struct sudo_preload_table *pt;
+ int flags = 0;
+ void *ret;
+# ifdef RTLD_MEMBER
+ char *cp;
+ size_t pathlen;
+# endif
+
+ /* Check prelinked symbols first. */
+ if (preload_table != NULL) {
+ for (pt = preload_table; pt->handle != NULL; pt++) {
+ if (pt->path != NULL && strcmp(path, pt->path) == 0)
+ return pt->handle;
+ }
+ }
+
+ /* Map SUDO_DSO_* -> RTLD_* */
+ if (ISSET(mode, SUDO_DSO_LAZY))
+ SET(flags, RTLD_LAZY);
+ if (ISSET(mode, SUDO_DSO_NOW))
+ SET(flags, RTLD_NOW);
+ if (ISSET(mode, SUDO_DSO_GLOBAL))
+ SET(flags, RTLD_GLOBAL);
+ if (ISSET(mode, SUDO_DSO_LOCAL))
+ SET(flags, RTLD_LOCAL);
+
+# ifdef RTLD_MEMBER
+ /* Check for AIX shlib.a(member) syntax and dlopen() with RTLD_MEMBER. */
+ pathlen = strlen(path);
+ if (pathlen > 2 && path[pathlen - 1] == ')') {
+ cp = strrchr(path, '(');
+ if (cp != NULL && cp > path + 2 && cp[-2] == '.' && cp[-1] == 'a') {
+ /* Only for archive files (e.g. sudoers.a). */
+ SET(flags, RTLD_MEMBER);
+ }
+ }
+# endif /* RTLD_MEMBER */
+ ret = dlopen(path, flags);
+# if defined(RTLD_MEMBER)
+ /* Special fallback handling for AIX shared objects. */
+ if (ret == NULL && !ISSET(flags, RTLD_MEMBER)) {
+ switch (errno) {
+ case ENOEXEC:
+ /*
+ * If we try to dlopen() an AIX .a file without an explicit member
+ * it will fail with ENOEXEC. Try again using the default member.
+ */
+ if (pathlen > 2 && strcmp(&path[pathlen - 2], ".a") == 0) {
+ int len = asprintf(&cp, "%s(%s)", path, SUDO_DSO_MEMBER);
+ if (len != -1) {
+ ret = dlopen(cp, flags|RTLD_MEMBER);
+ free(cp);
+ }
+ if (ret == NULL) {
+ /* Retry with the original path to get the correct error. */
+ ret = dlopen(path, flags);
+ }
+ }
+ break;
+ case ENOENT:
+ /*
+ * If the .so file is missing but the .a file exists, try to
+ * dlopen() the AIX .a file using the .so name as the member.
+ * This is for compatibility with versions of sudo that use
+ * SVR4-style shared libs, not AIX-style shared libs.
+ */
+ if (pathlen > 3 && strcmp(&path[pathlen - 3], ".so") == 0) {
+ int len = asprintf(&cp, "%.*s.a(%s)", (int)(pathlen - 3),
+ path, sudo_basename(path));
+ if (len != -1) {
+ ret = dlopen(cp, flags|RTLD_MEMBER);
+ free(cp);
+ }
+ if (ret == NULL) {
+ /* Retry with the original path to get the correct error. */
+ ret = dlopen(path, flags);
+ }
+ }
+ break;
+ }
+ }
+# endif /* RTLD_MEMBER */
+ /* On failure, try again with a multi-arch path where possible. */
+ if (ret == NULL)
+ ret = dlopen_multi_arch(path, flags); // -V1048
+
+ return ret;
+}
+
+int
+sudo_dso_unload_v1(void *handle)
+{
+ struct sudo_preload_table *pt;
+
+ /* Check prelinked symbols first. */
+ if (preload_table != NULL) {
+ for (pt = preload_table; pt->handle != NULL; pt++) {
+ if (pt->handle == handle)
+ return 0;
+ }
+ }
+
+ return dlclose(handle);
+}
+
+void *
+sudo_dso_findsym_v1(void *handle, const char *symbol)
+{
+ struct sudo_preload_table *pt;
+
+ /* Check prelinked symbols first. */
+ if (preload_table != NULL) {
+ for (pt = preload_table; pt->handle != NULL; pt++) {
+ if (pt->handle == handle) {
+ struct sudo_preload_symbol *sym;
+ for (sym = pt->symbols; sym->name != NULL; sym++) {
+ if (strcmp(sym->name, symbol) == 0)
+ return sym->addr;
+ }
+ errno = ENOENT;
+ return NULL;
+ }
+ }
+ }
+
+ /*
+ * Not all implementations support the special handles.
+ */
+ if (handle == SUDO_DSO_NEXT) {
+# ifdef RTLD_NEXT
+ handle = RTLD_NEXT;
+# else
+ errno = ENOENT;
+ return NULL;
+# endif
+ } else if (handle == SUDO_DSO_DEFAULT) {
+# ifdef RTLD_DEFAULT
+ handle = RTLD_DEFAULT;
+# else
+ errno = ENOENT;
+ return NULL;
+# endif
+ } else if (handle == SUDO_DSO_SELF) {
+# ifdef RTLD_SELF
+ handle = RTLD_SELF;
+# else
+ errno = ENOENT;
+ return NULL;
+# endif
+ }
+
+ return dlsym(handle, symbol);
+}
+
+char *
+sudo_dso_strerror_v1(void)
+{
+ return dlerror();
+}
+
+#else /* !HAVE_SHL_LOAD && !HAVE_DLOPEN */
+
+/*
+ * Emulate dlopen() using a static list of symbols compiled into sudo.
+ */
+void *
+sudo_dso_load_v1(const char *path, int mode)
+{
+ struct sudo_preload_table *pt;
+
+ /* Check prelinked symbols first. */
+ if (preload_table != NULL) {
+ for (pt = preload_table; pt->handle != NULL; pt++) {
+ if (pt->path != NULL && strcmp(path, pt->path) == 0)
+ return pt->handle;
+ }
+ }
+ return NULL;
+}
+
+int
+sudo_dso_unload_v1(void *handle)
+{
+ struct sudo_preload_table *pt;
+
+ if (preload_table != NULL) {
+ for (pt = preload_table; pt->handle != NULL; pt++) {
+ if (pt->handle == handle)
+ return 0;
+ }
+ }
+ return -1;
+}
+
+void *
+sudo_dso_findsym_v1(void *handle, const char *symbol)
+{
+ struct sudo_preload_table *pt;
+
+ if (preload_table != NULL) {
+ for (pt = preload_table; pt->handle != NULL; pt++) {
+ if (pt->handle == handle) {
+ struct sudo_preload_symbol *sym;
+ for (sym = pt->symbols; sym->name != NULL; sym++) {
+ if (strcmp(sym->name, symbol) == 0)
+ return sym->addr;
+ }
+ }
+ }
+ }
+ errno = ENOENT;
+ return NULL;
+}
+
+char *
+sudo_dso_strerror_v1(void)
+{
+ return strerror(errno);
+}
+#endif /* !HAVE_SHL_LOAD && !HAVE_DLOPEN */
diff --git a/lib/util/sys_siglist.h b/lib/util/sys_siglist.h
new file mode 100644
index 0000000..561c00e
--- /dev/null
+++ b/lib/util/sys_siglist.h
@@ -0,0 +1,182 @@
+/* public domain */
+
+#include <config.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <sudo_compat.h>
+
+int sudo_end_of_headers;
+static char *sudo_sys_siglist[NSIG];
+
+#ifdef SIGHUP
+ if (sudo_sys_siglist[SIGHUP] == NULL)
+ sudo_sys_siglist[SIGHUP] = "Hangup";
+#endif
+#ifdef SIGINT
+ if (sudo_sys_siglist[SIGINT] == NULL)
+ sudo_sys_siglist[SIGINT] = "Interrupt";
+#endif
+#ifdef SIGQUIT
+ if (sudo_sys_siglist[SIGQUIT] == NULL)
+ sudo_sys_siglist[SIGQUIT] = "Quit";
+#endif
+#ifdef SIGILL
+ if (sudo_sys_siglist[SIGILL] == NULL)
+ sudo_sys_siglist[SIGILL] = "Illegal instruction";
+#endif
+#ifdef SIGTRAP
+ if (sudo_sys_siglist[SIGTRAP] == NULL)
+ sudo_sys_siglist[SIGTRAP] = "Trace trap";
+#endif
+#ifdef SIGABRT
+ if (sudo_sys_siglist[SIGABRT] == NULL)
+ sudo_sys_siglist[SIGABRT] = "Abort";
+#endif
+#ifdef SIGIOT
+ if (sudo_sys_siglist[SIGIOT] == NULL)
+ sudo_sys_siglist[SIGIOT] = "IOT instruction";
+#endif
+#ifdef SIGEMT
+ if (sudo_sys_siglist[SIGEMT] == NULL)
+ sudo_sys_siglist[SIGEMT] = "EMT trap";
+#endif
+#ifdef SIGFPE
+ if (sudo_sys_siglist[SIGFPE] == NULL)
+ sudo_sys_siglist[SIGFPE] = "Floating point exception";
+#endif
+#ifdef SIGKILL
+ if (sudo_sys_siglist[SIGKILL] == NULL)
+ sudo_sys_siglist[SIGKILL] = "Killed";
+#endif
+#ifdef SIGBUS
+ if (sudo_sys_siglist[SIGBUS] == NULL)
+ sudo_sys_siglist[SIGBUS] = "Bus error";
+#endif
+#ifdef SIGSEGV
+ if (sudo_sys_siglist[SIGSEGV] == NULL)
+ sudo_sys_siglist[SIGSEGV] = "Memory fault";
+#endif
+#ifdef SIGSYS
+ if (sudo_sys_siglist[SIGSYS] == NULL)
+ sudo_sys_siglist[SIGSYS] = "Bad system call";
+#endif
+#ifdef SIGUNUSED
+ if (sudo_sys_siglist[SIGUNUSED] == NULL)
+ sudo_sys_siglist[SIGUNUSED] = "Unused";
+#endif
+#ifdef SIGPIPE
+ if (sudo_sys_siglist[SIGPIPE] == NULL)
+ sudo_sys_siglist[SIGPIPE] = "Broken pipe";
+#endif
+#ifdef SIGALRM
+ if (sudo_sys_siglist[SIGALRM] == NULL)
+ sudo_sys_siglist[SIGALRM] = "Alarm clock";
+#endif
+#ifdef SIGTERM
+ if (sudo_sys_siglist[SIGTERM] == NULL)
+ sudo_sys_siglist[SIGTERM] = "Terminated";
+#endif
+#ifdef SIGSTKFLT
+ if (sudo_sys_siglist[SIGSTKFLT] == NULL)
+ sudo_sys_siglist[SIGSTKFLT] = "Stack fault";
+#endif
+#ifdef SIGIO
+ if (sudo_sys_siglist[SIGIO] == NULL)
+ sudo_sys_siglist[SIGIO] = "I/O possible";
+#endif
+#ifdef SIGXCPU
+ if (sudo_sys_siglist[SIGXCPU] == NULL)
+ sudo_sys_siglist[SIGXCPU] = "CPU time limit exceeded";
+#endif
+#ifdef SIGXFSZ
+ if (sudo_sys_siglist[SIGXFSZ] == NULL)
+ sudo_sys_siglist[SIGXFSZ] = "File size limit exceeded";
+#endif
+#ifdef SIGVTALRM
+ if (sudo_sys_siglist[SIGVTALRM] == NULL)
+ sudo_sys_siglist[SIGVTALRM] = "Virtual timer expired";
+#endif
+#ifdef SIGPROF
+ if (sudo_sys_siglist[SIGPROF] == NULL)
+ sudo_sys_siglist[SIGPROF] = "Profiling timer expired";
+#endif
+#ifdef SIGWINCH
+ if (sudo_sys_siglist[SIGWINCH] == NULL)
+ sudo_sys_siglist[SIGWINCH] = "Window size change";
+#endif
+#ifdef SIGLOST
+ if (sudo_sys_siglist[SIGLOST] == NULL)
+ sudo_sys_siglist[SIGLOST] = "File lock lost";
+#endif
+#ifdef SIGUSR1
+ if (sudo_sys_siglist[SIGUSR1] == NULL)
+ sudo_sys_siglist[SIGUSR1] = "User defined signal 1";
+#endif
+#ifdef SIGUSR2
+ if (sudo_sys_siglist[SIGUSR2] == NULL)
+ sudo_sys_siglist[SIGUSR2] = "User defined signal 2";
+#endif
+#ifdef SIGPWR
+ if (sudo_sys_siglist[SIGPWR] == NULL)
+ sudo_sys_siglist[SIGPWR] = "Power-fail/Restart";
+#endif
+#ifdef SIGPOLL
+ if (sudo_sys_siglist[SIGPOLL] == NULL)
+ sudo_sys_siglist[SIGPOLL] = "Pollable event occurred";
+#endif
+#ifdef SIGSTOP
+ if (sudo_sys_siglist[SIGSTOP] == NULL)
+ sudo_sys_siglist[SIGSTOP] = "Stopped (signal)";
+#endif
+#ifdef SIGTSTP
+ if (sudo_sys_siglist[SIGTSTP] == NULL)
+ sudo_sys_siglist[SIGTSTP] = "Stopped";
+#endif
+#ifdef SIGCONT
+ if (sudo_sys_siglist[SIGCONT] == NULL)
+ sudo_sys_siglist[SIGCONT] = "Continued";
+#endif
+#ifdef SIGCHLD
+ if (sudo_sys_siglist[SIGCHLD] == NULL)
+ sudo_sys_siglist[SIGCHLD] = "Child exited";
+#endif
+#ifdef SIGCLD
+ if (sudo_sys_siglist[SIGCLD] == NULL)
+ sudo_sys_siglist[SIGCLD] = "Child exited";
+#endif
+#ifdef SIGTTIN
+ if (sudo_sys_siglist[SIGTTIN] == NULL)
+ sudo_sys_siglist[SIGTTIN] = "Stopped (tty input)";
+#endif
+#ifdef SIGTTOU
+ if (sudo_sys_siglist[SIGTTOU] == NULL)
+ sudo_sys_siglist[SIGTTOU] = "Stopped (tty output)";
+#endif
+#ifdef SIGINFO
+ if (sudo_sys_siglist[SIGINFO] == NULL)
+ sudo_sys_siglist[SIGINFO] = "Information request";
+#endif
+#ifdef SIGURG
+ if (sudo_sys_siglist[SIGURG] == NULL)
+ sudo_sys_siglist[SIGURG] = "Urgent I/O condition";
+#endif
+#ifdef SIGWAITING
+ if (sudo_sys_siglist[SIGWAITING] == NULL)
+ sudo_sys_siglist[SIGWAITING] = "No runnable LWPs";
+#endif
+#ifdef SIGLWP
+ if (sudo_sys_siglist[SIGLWP] == NULL)
+ sudo_sys_siglist[SIGLWP] = "Inter-LWP signal";
+#endif
+#ifdef SIGFREEZE
+ if (sudo_sys_siglist[SIGFREEZE] == NULL)
+ sudo_sys_siglist[SIGFREEZE] = "Checkpoint freeze";
+#endif
+#ifdef SIGTHAW
+ if (sudo_sys_siglist[SIGTHAW] == NULL)
+ sudo_sys_siglist[SIGTHAW] = "Checkpoint thaw";
+#endif
+#ifdef SIGCANCEL
+ if (sudo_sys_siglist[SIGCANCEL] == NULL)
+ sudo_sys_siglist[SIGCANCEL] = "Thread cancellation";
+#endif
diff --git a/lib/util/sys_signame.h b/lib/util/sys_signame.h
new file mode 100644
index 0000000..8c06829
--- /dev/null
+++ b/lib/util/sys_signame.h
@@ -0,0 +1,182 @@
+/* public domain */
+
+#include <config.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <sudo_compat.h>
+
+int sudo_end_of_headers;
+static char *sudo_sys_signame[NSIG];
+
+#ifdef SIGHUP
+ if (sudo_sys_signame[SIGHUP] == NULL)
+ sudo_sys_signame[SIGHUP] = "HUP";
+#endif
+#ifdef SIGINT
+ if (sudo_sys_signame[SIGINT] == NULL)
+ sudo_sys_signame[SIGINT] = "INT";
+#endif
+#ifdef SIGQUIT
+ if (sudo_sys_signame[SIGQUIT] == NULL)
+ sudo_sys_signame[SIGQUIT] = "QUIT";
+#endif
+#ifdef SIGILL
+ if (sudo_sys_signame[SIGILL] == NULL)
+ sudo_sys_signame[SIGILL] = "ILL";
+#endif
+#ifdef SIGTRAP
+ if (sudo_sys_signame[SIGTRAP] == NULL)
+ sudo_sys_signame[SIGTRAP] = "TRAP";
+#endif
+#ifdef SIGABRT
+ if (sudo_sys_signame[SIGABRT] == NULL)
+ sudo_sys_signame[SIGABRT] = "ABRT";
+#endif
+#ifdef SIGIOT
+ if (sudo_sys_signame[SIGIOT] == NULL)
+ sudo_sys_signame[SIGIOT] = "IOT";
+#endif
+#ifdef SIGEMT
+ if (sudo_sys_signame[SIGEMT] == NULL)
+ sudo_sys_signame[SIGEMT] = "EMT";
+#endif
+#ifdef SIGFPE
+ if (sudo_sys_signame[SIGFPE] == NULL)
+ sudo_sys_signame[SIGFPE] = "FPE";
+#endif
+#ifdef SIGKILL
+ if (sudo_sys_signame[SIGKILL] == NULL)
+ sudo_sys_signame[SIGKILL] = "KILL";
+#endif
+#ifdef SIGBUS
+ if (sudo_sys_signame[SIGBUS] == NULL)
+ sudo_sys_signame[SIGBUS] = "BUS";
+#endif
+#ifdef SIGSEGV
+ if (sudo_sys_signame[SIGSEGV] == NULL)
+ sudo_sys_signame[SIGSEGV] = "SEGV";
+#endif
+#ifdef SIGSYS
+ if (sudo_sys_signame[SIGSYS] == NULL)
+ sudo_sys_signame[SIGSYS] = "SYS";
+#endif
+#ifdef SIGUNUSED
+ if (sudo_sys_signame[SIGUNUSED] == NULL)
+ sudo_sys_signame[SIGUNUSED] = "UNUSED";
+#endif
+#ifdef SIGPIPE
+ if (sudo_sys_signame[SIGPIPE] == NULL)
+ sudo_sys_signame[SIGPIPE] = "PIPE";
+#endif
+#ifdef SIGALRM
+ if (sudo_sys_signame[SIGALRM] == NULL)
+ sudo_sys_signame[SIGALRM] = "ALRM";
+#endif
+#ifdef SIGTERM
+ if (sudo_sys_signame[SIGTERM] == NULL)
+ sudo_sys_signame[SIGTERM] = "TERM";
+#endif
+#ifdef SIGSTKFLT
+ if (sudo_sys_signame[SIGSTKFLT] == NULL)
+ sudo_sys_signame[SIGSTKFLT] = "STKFLT";
+#endif
+#ifdef SIGIO
+ if (sudo_sys_signame[SIGIO] == NULL)
+ sudo_sys_signame[SIGIO] = "IO";
+#endif
+#ifdef SIGXCPU
+ if (sudo_sys_signame[SIGXCPU] == NULL)
+ sudo_sys_signame[SIGXCPU] = "XCPU";
+#endif
+#ifdef SIGXFSZ
+ if (sudo_sys_signame[SIGXFSZ] == NULL)
+ sudo_sys_signame[SIGXFSZ] = "XFSZ";
+#endif
+#ifdef SIGVTALRM
+ if (sudo_sys_signame[SIGVTALRM] == NULL)
+ sudo_sys_signame[SIGVTALRM] = "VTALRM";
+#endif
+#ifdef SIGPROF
+ if (sudo_sys_signame[SIGPROF] == NULL)
+ sudo_sys_signame[SIGPROF] = "PROF";
+#endif
+#ifdef SIGWINCH
+ if (sudo_sys_signame[SIGWINCH] == NULL)
+ sudo_sys_signame[SIGWINCH] = "WINCH";
+#endif
+#ifdef SIGLOST
+ if (sudo_sys_signame[SIGLOST] == NULL)
+ sudo_sys_signame[SIGLOST] = "LOST";
+#endif
+#ifdef SIGUSR1
+ if (sudo_sys_signame[SIGUSR1] == NULL)
+ sudo_sys_signame[SIGUSR1] = "USR1";
+#endif
+#ifdef SIGUSR2
+ if (sudo_sys_signame[SIGUSR2] == NULL)
+ sudo_sys_signame[SIGUSR2] = "USR2";
+#endif
+#ifdef SIGPWR
+ if (sudo_sys_signame[SIGPWR] == NULL)
+ sudo_sys_signame[SIGPWR] = "PWR";
+#endif
+#ifdef SIGPOLL
+ if (sudo_sys_signame[SIGPOLL] == NULL)
+ sudo_sys_signame[SIGPOLL] = "POLL";
+#endif
+#ifdef SIGSTOP
+ if (sudo_sys_signame[SIGSTOP] == NULL)
+ sudo_sys_signame[SIGSTOP] = "STOP";
+#endif
+#ifdef SIGTSTP
+ if (sudo_sys_signame[SIGTSTP] == NULL)
+ sudo_sys_signame[SIGTSTP] = "TSTP";
+#endif
+#ifdef SIGCONT
+ if (sudo_sys_signame[SIGCONT] == NULL)
+ sudo_sys_signame[SIGCONT] = "CONT";
+#endif
+#ifdef SIGCHLD
+ if (sudo_sys_signame[SIGCHLD] == NULL)
+ sudo_sys_signame[SIGCHLD] = "CHLD";
+#endif
+#ifdef SIGCLD
+ if (sudo_sys_signame[SIGCLD] == NULL)
+ sudo_sys_signame[SIGCLD] = "CLD";
+#endif
+#ifdef SIGTTIN
+ if (sudo_sys_signame[SIGTTIN] == NULL)
+ sudo_sys_signame[SIGTTIN] = "TTIN";
+#endif
+#ifdef SIGTTOU
+ if (sudo_sys_signame[SIGTTOU] == NULL)
+ sudo_sys_signame[SIGTTOU] = "TTOU";
+#endif
+#ifdef SIGINFO
+ if (sudo_sys_signame[SIGINFO] == NULL)
+ sudo_sys_signame[SIGINFO] = "INFO";
+#endif
+#ifdef SIGURG
+ if (sudo_sys_signame[SIGURG] == NULL)
+ sudo_sys_signame[SIGURG] = "URG";
+#endif
+#ifdef SIGWAITING
+ if (sudo_sys_signame[SIGWAITING] == NULL)
+ sudo_sys_signame[SIGWAITING] = "WAITING";
+#endif
+#ifdef SIGLWP
+ if (sudo_sys_signame[SIGLWP] == NULL)
+ sudo_sys_signame[SIGLWP] = "LWP";
+#endif
+#ifdef SIGFREEZE
+ if (sudo_sys_signame[SIGFREEZE] == NULL)
+ sudo_sys_signame[SIGFREEZE] = "FREEZE";
+#endif
+#ifdef SIGTHAW
+ if (sudo_sys_signame[SIGTHAW] == NULL)
+ sudo_sys_signame[SIGTHAW] = "THAW";
+#endif
+#ifdef SIGCANCEL
+ if (sudo_sys_signame[SIGCANCEL] == NULL)
+ sudo_sys_signame[SIGCANCEL] = "CANCEL";
+#endif
diff --git a/lib/util/term.c b/lib/util/term.c
new file mode 100644
index 0000000..a74e9d0
--- /dev/null
+++ b/lib/util/term.c
@@ -0,0 +1,491 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011-2015, 2017-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+
+/* TCSASOFT is a BSD extension that ignores control flags and speed. */
+#ifndef TCSASOFT
+# define TCSASOFT 0
+#endif
+
+/* Non-standard termios input flags */
+#ifndef IUCLC
+# define IUCLC 0
+#endif
+#ifndef IMAXBEL
+# define IMAXBEL 0
+#endif
+#ifndef IUTF8
+# define IUTF8 0
+#endif
+
+/* Non-standard termios output flags */
+#ifndef OLCUC
+# define OLCUC 0
+#endif
+#ifndef ONLCR
+# define ONLCR 0
+#endif
+#ifndef OCRNL
+# define OCRNL 0
+#endif
+#ifndef ONOCR
+# define ONOCR 0
+#endif
+#ifndef ONLRET
+# define ONLRET 0
+#endif
+
+/* Non-standard termios local flags */
+#ifndef XCASE
+# define XCASE 0
+#endif
+#ifndef IEXTEN
+# define IEXTEN 0
+#endif
+#ifndef ECHOCTL
+# define ECHOCTL 0
+#endif
+#ifndef ECHOKE
+# define ECHOKE 0
+#endif
+
+/* Termios flags to copy between terminals. */
+#define INPUT_FLAGS (IGNPAR|PARMRK|INPCK|ISTRIP|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF|IMAXBEL|IUTF8)
+#define OUTPUT_FLAGS (OPOST|OLCUC|ONLCR|OCRNL|ONOCR|ONLRET)
+#define CONTROL_FLAGS (CS7|CS8|PARENB|PARODD)
+#define LOCAL_FLAGS (ISIG|ICANON|XCASE|ECHO|ECHOE|ECHOK|ECHONL|NOFLSH|TOSTOP|IEXTEN|ECHOCTL|ECHOKE)
+
+static struct termios orig_term;
+static struct termios cur_term;
+static bool changed;
+
+/* tgetpass() needs to know the erase and kill chars for cbreak mode. */
+sudo_dso_public int sudo_term_eof;
+sudo_dso_public int sudo_term_erase;
+sudo_dso_public int sudo_term_kill;
+
+static volatile sig_atomic_t got_sigttou;
+
+/*
+ * SIGTTOU signal handler for tcsetattr_nobg() that just sets a flag.
+ */
+static void
+sigttou(int signo)
+{
+ got_sigttou = 1;
+}
+
+/*
+ * Like tcsetattr() but restarts on EINTR _except_ for SIGTTOU.
+ * Returns 0 on success or -1 on failure, setting errno.
+ * Sets got_sigttou on failure if interrupted by SIGTTOU.
+ */
+static int
+tcsetattr_nobg(int fd, int flags, struct termios *tp)
+{
+ struct sigaction sa, osa;
+ int rc;
+ debug_decl(tcsetattr_nobg, SUDO_DEBUG_UTIL);
+
+ /*
+ * If we receive SIGTTOU from tcsetattr() it means we are
+ * not in the foreground process group.
+ * This should be less racy than using tcgetpgrp().
+ */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = sigttou;
+ got_sigttou = 0;
+ sigaction(SIGTTOU, &sa, &osa);
+ do {
+ rc = tcsetattr(fd, flags, tp);
+ } while (rc == -1 && errno == EINTR && !got_sigttou);
+ sigaction(SIGTTOU, &osa, NULL);
+
+ debug_return_int(rc);
+}
+
+/*
+ * Restore saved terminal settings if we are in the foreground process group.
+ * Returns true on success or false on failure.
+ */
+bool
+sudo_term_restore_v1(int fd, bool flush)
+{
+ const int flags = flush ? (TCSASOFT|TCSAFLUSH) : (TCSASOFT|TCSADRAIN);
+ struct termios term = { 0 };
+ bool ret = false;
+ debug_decl(sudo_term_restore, SUDO_DEBUG_UTIL);
+
+ if (!changed)
+ debug_return_bool(true);
+
+ sudo_lock_file(fd, SUDO_LOCK);
+
+ /* Avoid changing term settings if changed out from under us. */
+ if (tcgetattr(fd, &term) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: tcgetattr(%d)", __func__, fd);
+ goto unlock;
+ }
+ if ((term.c_iflag & INPUT_FLAGS) != (cur_term.c_iflag & INPUT_FLAGS)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: not restoring terminal, "
+ "c_iflag changed; 0x%x, expected 0x%x", __func__,
+ (unsigned int)term.c_iflag, (unsigned int)cur_term.c_iflag);
+ /* Not an error. */
+ ret = true;
+ goto unlock;
+ }
+ if ((term.c_oflag & OUTPUT_FLAGS) != (cur_term.c_oflag & OUTPUT_FLAGS)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: not restoring terminal, "
+ "c_oflag changed; 0x%x, expected 0x%x", __func__,
+ (unsigned int)term.c_oflag, (unsigned int)cur_term.c_oflag);
+ /* Not an error. */
+ ret = true;
+ goto unlock;
+ }
+#if !TCSASOFT
+ /* Only systems without TCSASOFT make changes to c_cflag. */
+ if ((term.c_cflag & CONTROL_FLAGS) != (cur_term.c_cflag & CONTROL_FLAGS)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: not restoring terminal, "
+ "c_cflag changed; 0x%x, expected 0x%x", __func__,
+ (unsigned int)term.c_cflag, (unsigned int)cur_term.c_cflag);
+ /* Not an error. */
+ ret = true;
+ goto unlock;
+ }
+#endif
+ if ((term.c_lflag & LOCAL_FLAGS) != (cur_term.c_lflag & LOCAL_FLAGS)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: not restoring terminal, "
+ "c_lflag changed; 0x%x, expected 0x%x", __func__,
+ (unsigned int)term.c_lflag, (unsigned int)cur_term.c_lflag);
+ /* Not an error. */
+ ret = true;
+ goto unlock;
+ }
+ if (memcmp(term.c_cc, cur_term.c_cc, sizeof(term.c_cc)) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: not restoring terminal, c_cc[] changed", __func__);
+ /* Not an error. */
+ ret = true;
+ goto unlock;
+ }
+
+ if (tcsetattr_nobg(fd, flags, &orig_term) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: tcsetattr(%d)", __func__, fd);
+ goto unlock;
+ }
+ cur_term = orig_term;
+ changed = false;
+ ret = true;
+
+unlock:
+ sudo_lock_file(fd, SUDO_UNLOCK);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Disable terminal echo.
+ * Returns true on success or false on failure.
+ */
+bool
+sudo_term_noecho_v1(int fd)
+{
+ struct termios term = { 0 };
+ bool ret = false;
+ debug_decl(sudo_term_noecho, SUDO_DEBUG_UTIL);
+
+ sudo_lock_file(fd, SUDO_LOCK);
+ if (!changed && tcgetattr(fd, &orig_term) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: tcgetattr(%d)", __func__, fd);
+ goto unlock;
+ }
+
+ term = orig_term;
+ CLR(term.c_lflag, ECHO|ECHONL);
+#ifdef VSTATUS
+ term.c_cc[VSTATUS] = _POSIX_VDISABLE;
+#endif
+ if (tcsetattr_nobg(fd, TCSASOFT|TCSADRAIN, &term) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: tcsetattr(%d)", __func__, fd);
+ goto unlock;
+ }
+ cur_term = term;
+ changed = true;
+ ret = true;
+
+unlock:
+ sudo_lock_file(fd, SUDO_UNLOCK);
+ debug_return_bool(ret);
+}
+
+/*
+ * Returns true if term is in raw mode, else false.
+ */
+static bool
+sudo_term_is_raw_int(struct termios *term)
+{
+ debug_decl(sudo_term_is_raw_int, SUDO_DEBUG_UTIL);
+
+ if (term->c_cc[VMIN] != 1 || term->c_cc[VTIME] != 0)
+ debug_return_bool(false);
+
+ if (ISSET(term->c_oflag, OPOST))
+ debug_return_bool(false);
+
+ if (ISSET(term->c_oflag, ECHO|ECHONL|ICANON))
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+/*
+ * Returns true if fd refers to a tty in raw mode, else false.
+ */
+bool
+sudo_term_is_raw_v1(int fd)
+{
+ struct termios term = { 0 };
+ debug_decl(sudo_term_is_raw, SUDO_DEBUG_UTIL);
+
+ if (!sudo_isatty(fd, NULL))
+ debug_return_bool(false);
+
+ sudo_lock_file(fd, SUDO_LOCK);
+ if (tcgetattr(fd, &term) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: tcgetattr(%d)", __func__, fd);
+ sudo_lock_file(fd, SUDO_UNLOCK);
+ debug_return_bool(false);
+ }
+ sudo_lock_file(fd, SUDO_UNLOCK);
+
+ debug_return_bool(sudo_term_is_raw_int(&term));
+}
+
+/*
+ * Set terminal to raw mode as modified by flags.
+ * Returns true on success or false on failure.
+ */
+bool
+sudo_term_raw_v1(int fd, unsigned int flags)
+{
+ struct termios term = { 0 };
+ bool ret = false;
+ tcflag_t oflag;
+ debug_decl(sudo_term_raw, SUDO_DEBUG_UTIL);
+
+ sudo_lock_file(fd, SUDO_LOCK);
+ if (!changed && tcgetattr(fd, &orig_term) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: tcgetattr(%d)", __func__, fd);
+ goto unlock;
+ }
+
+ if (sudo_term_is_raw_int(&term)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: fd %d already in raw mode",
+ __func__, fd);
+ ret = true;
+ goto unlock;
+ }
+
+ /*
+ * Set terminal to raw mode but optionally enable terminal signals
+ * and/or preserve output flags.
+ */
+ term = orig_term;
+ oflag = term.c_oflag;
+ cfmakeraw(&term);
+ if (ISSET(flags, SUDO_TERM_ISIG))
+ SET(term.c_lflag, ISIG);
+ if (ISSET(flags, SUDO_TERM_OFLAG))
+ term.c_oflag = oflag;
+ if (tcsetattr_nobg(fd, TCSASOFT|TCSADRAIN, &term) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: tcsetattr(%d)", __func__, fd);
+ goto unlock;
+ }
+ cur_term = term;
+ changed = true;
+ ret = true;
+
+unlock:
+ sudo_lock_file(fd, SUDO_UNLOCK);
+ debug_return_bool(ret);
+}
+
+/*
+ * Set terminal to cbreak mode.
+ * Returns true on success or false on failure.
+ */
+bool
+sudo_term_cbreak_v1(int fd)
+{
+ struct termios term = { 0 };
+ bool ret = false;
+ debug_decl(sudo_term_cbreak, SUDO_DEBUG_UTIL);
+
+ sudo_lock_file(fd, SUDO_LOCK);
+ if (!changed && tcgetattr(fd, &orig_term) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: tcgetattr(%d)", __func__, fd);
+ goto unlock;
+ }
+
+ /* Set terminal to half-cooked mode */
+ term = orig_term;
+ term.c_cc[VMIN] = 1;
+ term.c_cc[VTIME] = 0;
+ /* cppcheck-suppress redundantAssignment */
+ CLR(term.c_lflag, ECHO | ECHONL | ICANON | IEXTEN);
+ /* cppcheck-suppress redundantAssignment */
+ SET(term.c_lflag, ISIG);
+#ifdef VSTATUS
+ term.c_cc[VSTATUS] = _POSIX_VDISABLE;
+#endif
+ if (tcsetattr_nobg(fd, TCSASOFT|TCSADRAIN, &term) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: tcsetattr(%d)", __func__, fd);
+ goto unlock;
+ }
+ sudo_term_eof = term.c_cc[VEOF];
+ sudo_term_erase = term.c_cc[VERASE];
+ sudo_term_kill = term.c_cc[VKILL];
+ cur_term = term;
+ changed = true;
+ ret = true;
+
+unlock:
+ sudo_lock_file(fd, SUDO_UNLOCK);
+ debug_return_bool(ret);
+}
+
+/*
+ * Copy terminal settings from one descriptor to another.
+ * We cannot simply copy the struct termios as src and dst may be
+ * different terminal types (pseudo-tty vs. console or glass tty).
+ * Returns true on success or false on failure.
+ */
+bool
+sudo_term_copy_v1(int src, int dst)
+{
+ struct termios tt_src, tt_dst;
+ struct winsize wsize;
+ speed_t speed;
+ unsigned int i;
+ bool ret = false;
+ debug_decl(sudo_term_copy, SUDO_DEBUG_UTIL);
+
+ sudo_lock_file(src, SUDO_LOCK);
+ sudo_lock_file(dst, SUDO_LOCK);
+ if (tcgetattr(src, &tt_src) == -1 || tcgetattr(dst, &tt_dst) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: tcgetattr", __func__);
+ goto unlock;
+ }
+
+ /* Clear select input, output, control and local flags. */
+ CLR(tt_dst.c_iflag, INPUT_FLAGS);
+ CLR(tt_dst.c_oflag, OUTPUT_FLAGS);
+ CLR(tt_dst.c_cflag, CONTROL_FLAGS);
+ CLR(tt_dst.c_lflag, LOCAL_FLAGS);
+
+ /* Copy select input, output, control and local flags. */
+ SET(tt_dst.c_iflag, (tt_src.c_iflag & INPUT_FLAGS));
+ SET(tt_dst.c_oflag, (tt_src.c_oflag & OUTPUT_FLAGS));
+ SET(tt_dst.c_cflag, (tt_src.c_cflag & CONTROL_FLAGS));
+ SET(tt_dst.c_lflag, (tt_src.c_lflag & LOCAL_FLAGS));
+
+ /* Copy special chars from src verbatim. */
+ for (i = 0; i < NCCS; i++)
+ tt_dst.c_cc[i] = tt_src.c_cc[i];
+
+ /* Copy speed from src (zero output speed closes the connection). */
+ if ((speed = cfgetospeed(&tt_src)) == B0)
+ speed = B38400;
+ cfsetospeed(&tt_dst, speed);
+ speed = cfgetispeed(&tt_src);
+ cfsetispeed(&tt_dst, speed);
+
+ if (tcsetattr_nobg(dst, TCSASOFT|TCSAFLUSH, &tt_dst) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: tcsetattr(%d)", __func__, dst);
+ goto unlock;
+ }
+ ret = true;
+
+ if (ioctl(src, TIOCGWINSZ, &wsize) == 0)
+ (void)ioctl(dst, IOCTL_REQ_CAST TIOCSWINSZ, &wsize);
+
+unlock:
+ sudo_lock_file(dst, SUDO_UNLOCK);
+ sudo_lock_file(src, SUDO_UNLOCK);
+ debug_return_bool(ret);
+}
+
+/*
+ * Like isatty(3) but stats the fd and stores the result in sb.
+ * Only calls isatty(3) if fd is a character special device.
+ * Returns true if a tty, else returns false and sets errno.
+ */
+bool
+sudo_isatty_v1(int fd, struct stat *sbp)
+{
+ bool ret = false;
+ struct stat sb;
+ debug_decl(sudo_isatty, SUDO_DEBUG_EXEC);
+
+ if (sbp == NULL)
+ sbp = &sb;
+
+ if (fstat(fd, sbp) == 0) {
+ if (!S_ISCHR(sbp->st_mode)) {
+ errno = ENOTTY;
+ } else {
+ ret = isatty(fd) == 1;
+ }
+ } else if (sbp != &sb) {
+ /* Always initialize sbp. */
+ memset(sbp, 0, sizeof(*sbp));
+ }
+ debug_return_bool(ret);
+}
diff --git a/lib/util/timegm.c b/lib/util/timegm.c
new file mode 100644
index 0000000..acb5190
--- /dev/null
+++ b/lib/util/timegm.c
@@ -0,0 +1,99 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2017, 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifndef HAVE_TIMEGM
+
+#include <stdio.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+
+/*
+ * Returns the offset from GMT in seconds (algorithm taken from sendmail).
+ */
+#ifdef HAVE_STRUCT_TM_TM_GMTOFF
+static long
+get_gmtoff(time_t *when)
+{
+ struct tm local;
+
+ if (localtime_r(when, &local) == NULL)
+ return 0;
+
+ /* Adjust for DST. */
+ if (local.tm_isdst != 0)
+ local.tm_gmtoff -= local.tm_isdst * 3600;
+
+ return local.tm_gmtoff;
+}
+#else
+static long
+get_gmtoff(time_t *when)
+{
+ struct tm gmt, local;
+ long offset;
+
+ if (gmtime_r(when, &gmt) == NULL)
+ return 0;
+ if (localtime_r(when, &local) == NULL)
+ return 0;
+
+ offset = (local.tm_sec - gmt.tm_sec) +
+ ((local.tm_min - gmt.tm_min) * 60) +
+ ((local.tm_hour - gmt.tm_hour) * 3600);
+
+ /* Timezone may cause year rollover to happen on a different day. */
+ if (local.tm_year < gmt.tm_year)
+ offset -= 24 * 3600;
+ else if (local.tm_year > gmt.tm_year)
+ offset -= 24 * 3600;
+ else if (local.tm_yday < gmt.tm_yday)
+ offset -= 24 * 3600;
+ else if (local.tm_yday > gmt.tm_yday)
+ offset += 24 * 3600;
+
+ /* Adjust for DST. */
+ if (local.tm_isdst != 0)
+ offset -= local.tm_isdst * 3600;
+
+ return offset;
+}
+#endif /* HAVE_TM_GMTOFF */
+
+time_t
+sudo_timegm(struct tm *tm)
+{
+ time_t result;
+
+ tm->tm_isdst = 0;
+ result = mktime(tm);
+ if (result != -1)
+ result += get_gmtoff(&result);
+
+ return result;
+}
+
+#endif /* HAVE_TIMEGM */
diff --git a/lib/util/ttyname_dev.c b/lib/util/ttyname_dev.c
new file mode 100644
index 0000000..3236925
--- /dev/null
+++ b/lib/util/ttyname_dev.c
@@ -0,0 +1,311 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2012-2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined(MAJOR_IN_MKDEV)
+# include <sys/mkdev.h>
+#elif defined(MAJOR_IN_SYSMACROS)
+# include <sys/sysmacros.h>
+#else
+# include <sys/param.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <dirent.h>
+
+#include <pathnames.h>
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_conf.h>
+#include <sudo_util.h>
+
+#if defined(HAVE_DEVNAME)
+/*
+ * Like ttyname() but uses a dev_t instead of an open fd.
+ * Returns name on success and NULL on failure, setting errno.
+ * The BSD version uses devname().
+ */
+char *
+sudo_ttyname_dev_v1(dev_t tdev, char *name, size_t namelen)
+{
+ char *dev;
+ debug_decl(sudo_ttyname_dev, SUDO_DEBUG_UTIL);
+
+ /* Some versions of devname() return NULL on failure, others do not. */
+ dev = devname(tdev, S_IFCHR);
+ if (dev != NULL && *dev != '?' && *dev != '#') {
+ if (strlcpy(name, _PATH_DEV, namelen) < namelen &&
+ strlcat(name, dev, namelen) < namelen)
+ debug_return_str(name);
+ errno = ERANGE;
+ } else {
+ /* Not all versions of devname() set errno. */
+ errno = ENOENT;
+ }
+ debug_return_str(NULL);
+}
+#elif defined(HAVE__TTYNAME_DEV)
+extern char *_ttyname_dev(dev_t rdev, char *buffer, size_t buflen);
+
+/*
+ * Like ttyname() but uses a dev_t instead of an open fd.
+ * Returns name on success and NULL on failure, setting errno.
+ * This version is just a wrapper around _ttyname_dev().
+ */
+char *
+sudo_ttyname_dev_v1(dev_t tdev, char *name, size_t namelen)
+{
+ int serrno = errno;
+ debug_decl(sudo_ttyname_dev, SUDO_DEBUG_UTIL);
+
+ /*
+ * _ttyname_dev() sets errno to ERANGE if namelen is too small
+ * but does not modify it if tdev is not found.
+ */
+ errno = ENOENT;
+ if (_ttyname_dev(tdev, name, namelen) == NULL)
+ debug_return_str(NULL);
+ errno = serrno;
+
+ debug_return_str(name);
+}
+#else
+/*
+ * Device nodes to ignore.
+ */
+static const char *ignore_devs[] = {
+ _PATH_DEV "stdin",
+ _PATH_DEV "stdout",
+ _PATH_DEV "stderr",
+ NULL
+};
+
+/*
+ * Do a scan of a directory looking for the specified device.
+ * Does not descend into subdirectories.
+ * Returns name on success and NULL on failure, setting errno.
+ */
+static char *
+sudo_ttyname_scan(const char *dir, dev_t rdev, char *name, size_t namelen)
+{
+ size_t sdlen;
+ char pathbuf[PATH_MAX];
+ char *ret = NULL;
+ struct dirent *dp;
+ struct stat sb;
+ size_t i;
+ DIR *d = NULL;
+ debug_decl(sudo_ttyname_scan, SUDO_DEBUG_UTIL);
+
+ if (dir[0] == '\0') {
+ errno = ENOENT;
+ goto done;
+ }
+ if ((d = opendir(dir)) == NULL)
+ goto done;
+
+ if (fstat(dirfd(d), &sb) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to fstat %s", dir);
+ goto done;
+ }
+ if ((sb.st_mode & S_IWOTH) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring world-writable directory %s", dir);
+ errno = ENOENT;
+ goto done;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "scanning for dev %u in %s", (unsigned int)rdev, dir);
+
+ sdlen = strlen(dir);
+ while (sdlen > 0 && dir[sdlen - 1] == '/')
+ sdlen--;
+ if (sdlen + 1 >= sizeof(pathbuf)) {
+ errno = ERANGE;
+ goto done;
+ }
+ memcpy(pathbuf, dir, sdlen);
+ pathbuf[sdlen++] = '/';
+
+ while ((dp = readdir(d)) != NULL) {
+ /* Skip anything starting with "." */
+ if (dp->d_name[0] == '.')
+ continue;
+
+ pathbuf[sdlen] = '\0';
+ if (strlcat(pathbuf, dp->d_name, sizeof(pathbuf)) >= sizeof(pathbuf)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s%s is too big to fit in pathbuf", pathbuf, dp->d_name);
+ continue;
+ }
+
+ /* Ignore device nodes listed in ignore_devs[]. */
+ for (i = 0; ignore_devs[i] != NULL; i++) {
+ if (strcmp(pathbuf, ignore_devs[i]) == 0)
+ break;
+ }
+ if (ignore_devs[i] != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "ignoring %s", pathbuf);
+ continue;
+ }
+
+# if defined(HAVE_STRUCT_DIRENT_D_TYPE)
+ /*
+ * Avoid excessive stat() calls by checking dp->d_type.
+ */
+ switch (dp->d_type) {
+ case DT_CHR:
+ case DT_LNK:
+ case DT_UNKNOWN:
+ break;
+ default:
+ /* Not a character device or link, skip it. */
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "skipping non-device %s", pathbuf);
+ continue;
+ }
+# endif
+ if (stat(pathbuf, &sb) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to stat %s", pathbuf);
+ continue;
+ }
+ if (S_ISCHR(sb.st_mode) && sb.st_rdev == rdev) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "resolved dev %u as %s", (unsigned int)rdev, pathbuf);
+ if (strlcpy(name, pathbuf, namelen) < namelen) {
+ ret = name;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to store %s, have %zu, need %zu",
+ pathbuf, namelen, strlen(pathbuf) + 1);
+ errno = ERANGE;
+ }
+ goto done;
+ }
+ }
+
+done:
+ if (d != NULL)
+ closedir(d);
+ debug_return_str(ret);
+}
+
+static char *
+sudo_dev_check(dev_t rdev, const char * restrict devname, char * restrict buf, size_t buflen)
+{
+ struct stat sb;
+ debug_decl(sudo_dev_check, SUDO_DEBUG_UTIL);
+
+ if (stat(devname, &sb) == 0) {
+ if (S_ISCHR(sb.st_mode) && sb.st_rdev == rdev) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "comparing dev %u to %s: match!",
+ (unsigned int)rdev, devname);
+ if (strlcpy(buf, devname, buflen) < buflen)
+ debug_return_str(buf);
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to store %s, have %zu, need %zu",
+ devname, buflen, strlen(devname) + 1);
+ errno = ERANGE;
+ }
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "comparing dev %u to %s: no", (unsigned int)rdev, devname);
+ debug_return_str(NULL);
+}
+
+/*
+ * Like ttyname() but uses a dev_t instead of an open fd.
+ * Returns name on success and NULL on failure, setting errno.
+ * Generic version.
+ */
+char *
+sudo_ttyname_dev_v1(dev_t rdev, char *buf, size_t buflen)
+{
+ const char *devsearch, *devsearch_end;
+ char path[PATH_MAX], *ret;
+ const char *cp, *ep;
+ size_t len;
+ debug_decl(sudo_ttyname_dev, SUDO_DEBUG_UTIL);
+
+ /*
+ * First, check /dev/console.
+ */
+ ret = sudo_dev_check(rdev, _PATH_DEV "console", buf, buflen);
+ if (ret != NULL)
+ goto done;
+
+ /*
+ * Then check the device search path.
+ */
+ devsearch = sudo_conf_devsearch_path();
+ devsearch_end = devsearch + strlen(devsearch);
+ for (cp = sudo_strsplit(devsearch, devsearch_end, ":", &ep);
+ cp != NULL; cp = sudo_strsplit(NULL, devsearch_end, ":", &ep)) {
+
+ len = (size_t)(ep - cp);
+ if (len >= sizeof(path)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "devsearch entry %.*s too long", (int)len, cp);
+ continue;
+ }
+ memcpy(path, cp, len);
+ path[len] = '\0';
+
+ if (strcmp(path, _PATH_DEV "pts") == 0) {
+ /* Special case /dev/pts */
+ len = (size_t)snprintf(path, sizeof(path), "%spts/%u",
+ _PATH_DEV, (unsigned int)minor(rdev));
+ if (len >= sizeof(path)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "devsearch entry %spts/%u too long",
+ _PATH_DEV, (unsigned int)minor(rdev));
+ continue;
+ }
+ ret = sudo_dev_check(rdev, path, buf, buflen);
+ if (ret != NULL)
+ goto done;
+ } else {
+ /* Scan path, looking for rdev. */
+ ret = sudo_ttyname_scan(path, rdev, buf, buflen);
+ if (ret != NULL || errno == ENOMEM)
+ goto done;
+ }
+ }
+
+done:
+ debug_return_str(ret);
+}
+#endif
diff --git a/lib/util/ttysize.c b/lib/util/ttysize.c
new file mode 100644
index 0000000..0b582d0
--- /dev/null
+++ b/lib/util/ttysize.c
@@ -0,0 +1,80 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2012, 2014-2015, 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <termios.h> /* for struct winsize on HP-UX */
+#include <limits.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+
+static int
+get_ttysize_ioctl(int fd, int *rowp, int *colp)
+{
+ struct winsize wsize;
+ debug_decl(get_ttysize_ioctl, SUDO_DEBUG_UTIL);
+
+ if (fd != -1 && sudo_isatty(fd, NULL)) {
+ if (ioctl(fd, TIOCGWINSZ, &wsize) == 0) {
+ if (wsize.ws_row != 0 && wsize.ws_col != 0) {
+ *rowp = wsize.ws_row;
+ *colp = wsize.ws_col;
+ debug_return_int(0);
+ }
+ }
+ }
+ debug_return_int(-1);
+}
+
+void
+sudo_get_ttysize_v1(int *rowp, int *colp)
+{
+ sudo_get_ttysize_v2(STDERR_FILENO, rowp, colp);
+}
+
+void
+sudo_get_ttysize_v2(int fd, int *rowp, int *colp)
+{
+ debug_decl(sudo_get_ttysize, SUDO_DEBUG_UTIL);
+
+ if (get_ttysize_ioctl(fd, rowp, colp) == -1) {
+ char *p;
+
+ /* Fall back on $LINES and $COLUMNS. */
+ if ((p = getenv("LINES")) == NULL ||
+ (*rowp = (int)sudo_strtonum(p, 1, INT_MAX, NULL)) <= 0) {
+ *rowp = 24;
+ }
+ if ((p = getenv("COLUMNS")) == NULL ||
+ (*colp = (int)sudo_strtonum(p, 1, INT_MAX, NULL)) <= 0) {
+ *colp = 80;
+ }
+ }
+
+ debug_return;
+}
diff --git a/lib/util/unlinkat.c b/lib/util/unlinkat.c
new file mode 100644
index 0000000..b62902e
--- /dev/null
+++ b/lib/util/unlinkat.c
@@ -0,0 +1,60 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+
+#ifndef HAVE_UNLINKAT
+int
+sudo_unlinkat(int dfd, const char *path, int flag)
+{
+ int odfd, ret;
+
+ if (dfd == AT_FDCWD)
+ return unlink(path);
+
+ /* Save cwd */
+ if ((odfd = open(".", O_RDONLY)) == -1)
+ return -1;
+
+ if (fchdir(dfd) == -1) {
+ close(odfd);
+ return -1;
+ }
+
+ ret = unlink(path);
+
+ /* Restore cwd */
+ if (fchdir(odfd) == -1) {
+ /* Should not happen */
+ ret = -1;
+ }
+ close(odfd);
+
+ return ret;
+}
+#endif /* HAVE_UNLINKAT */
diff --git a/lib/util/util.exp.in b/lib/util/util.exp.in
new file mode 100644
index 0000000..ca9dced
--- /dev/null
+++ b/lib/util/util.exp.in
@@ -0,0 +1,178 @@
+@COMPAT_EXP@initprogname
+initprogname2
+sudo_basename_v1
+sudo_conf_askpass_path_v1
+sudo_conf_clear_paths_v1
+sudo_conf_debug_files_v1
+sudo_conf_debugging_v1
+sudo_conf_developer_mode_v1
+sudo_conf_devsearch_path_v1
+sudo_conf_disable_coredump_v1
+sudo_conf_group_source_v1
+sudo_conf_intercept_path_v1
+sudo_conf_max_groups_v1
+sudo_conf_noexec_path_v1
+sudo_conf_plugin_dir_path_v1
+sudo_conf_plugins_v1
+sudo_conf_probe_interfaces_v1
+sudo_conf_read_v1
+sudo_conf_sesh_path_v1
+sudo_debug_deregister_v1
+sudo_debug_enter_v1
+sudo_debug_execve2_v1
+sudo_debug_exit_bool_v1
+sudo_debug_exit_id_t_v1
+sudo_debug_exit_int_v1
+sudo_debug_exit_long_v1
+sudo_debug_exit_mode_t_v1
+sudo_debug_exit_ptr_v1
+sudo_debug_exit_size_t_v1
+sudo_debug_exit_ssize_t_v1
+sudo_debug_exit_str_masked_v1
+sudo_debug_exit_str_v1
+sudo_debug_exit_time_t_v1
+sudo_debug_exit_uint_v1
+sudo_debug_exit_v1
+sudo_debug_fork_v1
+sudo_debug_get_active_instance_v1
+sudo_debug_get_fds_v1
+sudo_debug_get_instance_v1
+sudo_debug_needed_v1
+sudo_debug_parse_flags_v1
+sudo_debug_printf2_v1
+sudo_debug_register_v1
+sudo_debug_register_v2
+sudo_debug_set_active_instance_v1
+sudo_debug_update_fd_v1
+sudo_debug_vprintf2_v1
+sudo_debug_write2_v1
+sudo_digest_alloc_v1
+sudo_digest_final_v1
+sudo_digest_free_v1
+sudo_digest_getlen_v1
+sudo_digest_getlen_v2
+sudo_digest_reset_v1
+sudo_digest_update_v1
+sudo_dso_findsym_v1
+sudo_dso_load_v1
+sudo_dso_preload_table_v1
+sudo_dso_strerror_v1
+sudo_dso_unload_v1
+sudo_ev_add_v1
+sudo_ev_add_v2
+sudo_ev_alloc_v1
+sudo_ev_alloc_v2
+sudo_ev_base_alloc_v1
+sudo_ev_base_free_v1
+sudo_ev_base_setdef_v1
+sudo_ev_del_v1
+sudo_ev_dispatch_v1
+sudo_ev_free_v1
+sudo_ev_get_timeleft_v1
+sudo_ev_get_timeleft_v2
+sudo_ev_got_break_v1
+sudo_ev_got_exit_v1
+sudo_ev_loop_v1
+sudo_ev_loopbreak_v1
+sudo_ev_loopcontinue_v1
+sudo_ev_loopexit_v1
+sudo_ev_pending_v1
+sudo_ev_pending_v2
+sudo_ev_set_v1
+sudo_ev_set_v2
+sudo_fatal_callback_deregister_v1
+sudo_fatal_callback_register_v1
+sudo_fatal_nodebug_v1
+sudo_fatalx_nodebug_v1
+sudo_gai_fatal_nodebug_v1
+sudo_gai_vfatal_nodebug_v1
+sudo_gai_vwarn_nodebug_v1
+sudo_gai_warn_nodebug_v1
+sudo_get_ttysize_v1
+sudo_get_ttysize_v2
+sudo_getgrouplist2_v1
+sudo_gethostname_v1
+sudo_gettime_awake_v1
+sudo_gettime_mono_v1
+sudo_gettime_real_v1
+sudo_hexchar_v1
+sudo_isatty_v1
+sudo_json_add_value_as_object_v1
+sudo_json_add_value_v1
+sudo_json_close_array_v1
+sudo_json_close_object_v1
+sudo_json_free_v1
+sudo_json_get_buf_v1
+sudo_json_get_len_v1
+sudo_json_init_v1
+sudo_json_init_v2
+sudo_json_open_array_v1
+sudo_json_open_object_v1
+sudo_lbuf_append_esc_v1
+sudo_lbuf_append_quoted_v1
+sudo_lbuf_append_v1
+sudo_lbuf_clearerr_v1
+sudo_lbuf_destroy_v1
+sudo_lbuf_error_v1
+sudo_lbuf_init_v1
+sudo_lbuf_print_v1
+sudo_lock_file_v1
+sudo_lock_region_v1
+sudo_logfac2str_v1
+sudo_logpri2str_v1
+sudo_mkdir_parents_v1
+sudo_mmap_alloc_v1
+sudo_mmap_allocarray_v1
+sudo_mmap_free_v1
+sudo_mmap_protect_v1
+sudo_mmap_strdup_v1
+sudo_new_key_val_v1
+sudo_open_conf_path_v1
+sudo_open_parent_dir_v1
+sudo_parse_gids_v1
+sudo_parseln_v1
+sudo_parseln_v2
+sudo_pow2_roundup_v1
+sudo_pow2_roundup_v2
+sudo_rcstr_addref
+sudo_rcstr_alloc
+sudo_rcstr_delref
+sudo_rcstr_dup
+sudo_regex_compile_v1
+sudo_secure_dir_v1
+sudo_secure_fd_v1
+sudo_secure_file_v1
+sudo_secure_open_dir_v1
+sudo_secure_open_file_v1
+sudo_setgroups_v1
+sudo_stat_multiarch_v1
+sudo_str2logfac_v1
+sudo_str2logpri_v1
+sudo_strsplit_v1
+sudo_strtobool_v1
+sudo_strtoid_v1
+sudo_strtoid_v2
+sudo_strtoidx_v1
+sudo_strtomode_v1
+sudo_strtomode_v2
+sudo_strtonum
+sudo_term_cbreak_v1
+sudo_term_copy_v1
+sudo_term_eof
+sudo_term_erase
+sudo_term_is_raw_v1
+sudo_term_kill
+sudo_term_noecho_v1
+sudo_term_raw_v1
+sudo_term_restore_v1
+sudo_ttyname_dev_v1
+sudo_uuid_create_v1
+sudo_uuid_to_string_v1
+sudo_vfatal_nodebug_v1
+sudo_vfatalx_nodebug_v1
+sudo_vwarn_nodebug_v1
+sudo_vwarnx_nodebug_v1
+sudo_warn_nodebug_v1
+sudo_warn_set_conversation_v1
+sudo_warn_set_locale_func_v1
+sudo_warnx_nodebug_v1
diff --git a/lib/util/utimens.c b/lib/util/utimens.c
new file mode 100644
index 0000000..74d6c65
--- /dev/null
+++ b/lib/util/utimens.c
@@ -0,0 +1,200 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2015, 2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#if !defined(HAVE_FUTIMENS) || !defined(HAVE_UTIMENSAT)
+
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <time.h>
+#if !defined(HAVE_UTIMES) || defined(HAVE_FUTIME)
+# include <utime.h>
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+#if !defined(HAVE_FUTIMES) && defined(HAVE_FUTIMESAT)
+# define futimes(_f, _tv) futimesat(_f, NULL, _tv)
+# define HAVE_FUTIMES
+#endif
+
+#if defined(HAVE_ST_MTIM)
+# ifdef HAVE_ST__TIM
+# define ATIME_TO_TIMEVAL(_x, _y) TIMESPEC_TO_TIMEVAL((_x), &(_y)->st_atim.st__tim)
+# define MTIME_TO_TIMEVAL(_x, _y) TIMESPEC_TO_TIMEVAL((_x), &(_y)->st_mtim.st__tim)
+# else
+# define ATIME_TO_TIMEVAL(_x, _y) TIMESPEC_TO_TIMEVAL((_x), &(_y)->st_atim)
+# define MTIME_TO_TIMEVAL(_x, _y) TIMESPEC_TO_TIMEVAL((_x), &(_y)->st_mtim)
+# endif
+#elif defined(HAVE_ST_MTIMESPEC)
+# define ATIME_TO_TIMEVAL(_x, _y) TIMESPEC_TO_TIMEVAL((_x), &(_y)->st_atimespec)
+# define MTIME_TO_TIMEVAL(_x, _y) TIMESPEC_TO_TIMEVAL((_x), &(_y)->st_mtimespec)
+#elif defined(HAVE_ST_NMTIME)
+# define ATIME_TO_TIMEVAL(_x, _y) do { (_x)->tv_sec = (_y)->st_atime; (_x)->tv_usec = (_y)->st_natime; } while (0)
+# define MTIME_TO_TIMEVAL(_x, _y) do { (_x)->tv_sec = (_y)->st_mtime; (_x)->tv_usec = (_y)->st_nmtime; } while (0)
+#else
+# define ATIME_TO_TIMEVAL(_x, _y) do { (_x)->tv_sec = (_y)->st_atime; (_x)->tv_usec = 0; } while (0)
+# define MTIME_TO_TIMEVAL(_x, _y) do { (_x)->tv_sec = (_y)->st_mtime; (_x)->tv_usec = 0; } while (0)
+#endif /* HAVE_ST_MTIM */
+
+/*
+ * Convert the pair of timespec structs passed to futimens() / utimensat()
+ * to a pair of timeval structs, handling UTIME_OMIT and UTIME_NOW.
+ * Returns 0 on success and -1 on failure (setting errno).
+ */
+static int
+utimens_ts_to_tv(int fd, const char *file, const struct timespec *ts,
+ struct timeval *tv)
+{
+ TIMESPEC_TO_TIMEVAL(&tv[0], &ts[0]);
+ TIMESPEC_TO_TIMEVAL(&tv[1], &ts[1]);
+ if (ts[0].tv_nsec == UTIME_OMIT || ts[1].tv_nsec == UTIME_OMIT) {
+ struct stat sb;
+
+ if (fd != -1) {
+ /* For futimens() */
+ if (fstat(fd, &sb) == -1)
+ return -1;
+ } else {
+ /* For utimensat() */
+ if (stat(file, &sb) == -1)
+ return -1;
+ }
+ if (ts[0].tv_nsec == UTIME_OMIT)
+ ATIME_TO_TIMEVAL(&tv[0], &sb);
+ if (ts[1].tv_nsec == UTIME_OMIT)
+ MTIME_TO_TIMEVAL(&tv[1], &sb);
+ }
+ if (ts[0].tv_nsec == UTIME_NOW || ts[1].tv_nsec == UTIME_NOW) {
+ struct timeval now;
+
+ if (gettimeofday(&now, NULL) == -1)
+ return -1;
+ if (ts[0].tv_nsec == UTIME_NOW)
+ tv[0] = now;
+ if (ts[1].tv_nsec == UTIME_NOW)
+ tv[1] = now;
+ }
+ return 0;
+}
+
+#if defined(HAVE_FUTIMES)
+/*
+ * Emulate futimens() via futimes()
+ */
+int
+sudo_futimens(int fd, const struct timespec *ts)
+{
+ struct timeval tv[2], *times = NULL;
+
+ if (ts != NULL) {
+ if (utimens_ts_to_tv(fd, NULL, ts, tv) == -1)
+ return -1;
+ times = tv;
+ }
+ return futimes(fd, times);
+}
+#elif defined(HAVE_FUTIME)
+/*
+ * Emulate futimens() via futime()
+ */
+int
+sudo_futimens(int fd, const struct timespec *ts)
+{
+ struct utimbuf utb, *times = NULL;
+
+ if (ts != NULL) {
+ struct timeval tv[2];
+
+ if (utimens_ts_to_tv(fd, NULL, ts, tv) == -1)
+ return -1;
+ utb.actime = (time_t)(tv[0].tv_sec + tv[0].tv_usec / 1000000);
+ utb.modtime = (time_t)(tv[1].tv_sec + tv[1].tv_usec / 1000000);
+ times = &utb;
+ }
+ return futime(fd, times);
+}
+#else
+/*
+ * Nothing to do but fail.
+ */
+int
+sudo_futimens(int fd, const struct timespec *ts)
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif /* HAVE_FUTIMES */
+
+#if defined(HAVE_UTIMES)
+/*
+ * Emulate utimensat() via utimes()
+ */
+int
+sudo_utimensat(int fd, const char *file, const struct timespec *ts, int flag)
+{
+ struct timeval tv[2], *times = NULL;
+
+ if (fd != AT_FDCWD || flag != 0) {
+ errno = ENOTSUP;
+ return -1;
+ }
+
+ if (ts != NULL) {
+ if (utimens_ts_to_tv(-1, file, ts, tv) == -1)
+ return -1;
+ times = tv;
+ }
+ return utimes(file, times);
+}
+#else
+/*
+ * Emulate utimensat() via utime()
+ */
+int
+sudo_utimensat(int fd, const char *file, const struct timespec *ts, int flag)
+{
+ struct utimbuf utb, *times = NULL;
+
+ if (fd != AT_FDCWD || flag != 0) {
+ errno = ENOTSUP;
+ return -1;
+ }
+
+ if (ts != NULL) {
+ struct timeval tv[2];
+
+ if (utimens_ts_to_tv(-1, file, ts, tv) == -1)
+ return -1;
+ utb.actime = (time_t)(tv[0].tv_sec + tv[0].tv_usec / 1000000);
+ utb.modtime = (time_t)(tv[1].tv_sec + tv[1].tv_usec / 1000000);
+ times = &utb;
+ }
+ return utime(file, times);
+}
+#endif /* !HAVE_UTIMES */
+
+#endif /* !HAVE_FUTIMENS && !HAVE_UTIMENSAT */
diff --git a/lib/util/uuid.c b/lib/util/uuid.c
new file mode 100644
index 0000000..764c8db
--- /dev/null
+++ b/lib/util/uuid.c
@@ -0,0 +1,99 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <string.h>
+#include <arpa/inet.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_rand.h>
+
+struct uuid {
+ uint32_t time_low;
+ uint16_t time_mid;
+ uint16_t time_hi_and_version;
+ uint8_t clock_seq_hi_and_reserved;
+ uint8_t clock_seq_low;
+ uint8_t node[6];
+};
+
+/*
+ * Create a type 4 (random), variant 1 universally unique identifier (UUID).
+ * As per RFC 4122 section 4.4.
+ */
+void
+sudo_uuid_create_v1(unsigned char uuid_out[16])
+{
+ struct uuid uuid;
+
+ arc4random_buf(&uuid, sizeof(uuid));
+
+ /* Set version to 4 (random), 4 most significant bits (12-15) are 0010. */
+ uuid.time_hi_and_version &= 0x0fff;
+ uuid.time_hi_and_version |= 0x4000;
+
+ /* Set variant to 1: two most significant bits (6 and 7) are 01. */
+ uuid.clock_seq_hi_and_reserved &= 0x3f;
+ uuid.clock_seq_hi_and_reserved |= 0x80;
+
+ memcpy(uuid_out, &uuid, 16);
+}
+
+/*
+ * Format a uuid as a 36-byte string (plus one for the NUL).
+ */
+char *
+sudo_uuid_to_string_v1(unsigned char uuid[16], char *dst, size_t dstsiz)
+{
+ const char hex[] = "0123456789abcdef";
+ char *cp = dst;
+ unsigned int i;
+
+ if (dstsiz < sizeof("123e4567-e89b-12d3-a456-426655440000"))
+ return NULL;
+
+ for (i = 0; i < 16; i++) {
+ *cp++ = hex[uuid[i] >> 4];
+ *cp++ = hex[uuid[i] & 0x0f];
+
+ switch (i) {
+ case 4:
+ case 6:
+ case 8:
+ case 10:
+ *cp++ = '-';
+ break;
+ }
+ }
+ *cp = '\0';
+
+ return dst;
+}
diff --git a/lib/zlib/Makefile.in b/lib/zlib/Makefile.in
new file mode 100644
index 0000000..df44c2a
--- /dev/null
+++ b/lib/zlib/Makefile.in
@@ -0,0 +1,231 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2011-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+scriptdir = $(top_srcdir)/scripts
+cross_compiling = @CROSS_COMPILING@
+
+# Where to install things...
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+sysconfdir = @sysconfdir@
+adminconfdir = @adminconfdir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+localstatedir = @localstatedir@
+
+# File extension, mode and map file to use for shared libraries/objects
+shlib_enable = @SHLIB_ENABLE@
+shlib_mode = @SHLIB_MODE@
+shlib_exp = $(srcdir)/zlib.exp
+shlib_map = zlib.map
+shlib_opt = zlib.opt
+
+# Compiler & tools to use
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+SED = @SED@
+AWK = @AWK@
+
+# Our install program supports extra flags...
+INSTALL = $(SHELL) $(scriptdir)/install-sh -c
+INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
+INSTALL_BACKUP = @INSTALL_BACKUP@
+
+# C preprocessor flags
+CPPFLAGS = -I. -I$(srcdir)
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+
+# Flags to pass to the link stage
+LDFLAGS =
+LT_LDFLAGS = @ZLIB_LDFLAGS@ @LT_LDFLAGS@ @LT_LDEXPORTS@
+
+# Flags to pass to libtool
+LTFLAGS =
+
+# Address sanitizer flags
+ASAN_CFLAGS = @ASAN_CFLAGS@
+ASAN_LDFLAGS = @ASAN_LDFLAGS@
+
+# PIE flags
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+
+# Stack smashing protection flags
+HARDENING_CFLAGS = @HARDENING_CFLAGS@
+HARDENING_LDFLAGS = @HARDENING_LDFLAGS@
+
+# Libtool style shared library version
+SHLIB_VERSION = 0:0:0
+
+# User and group ids the installed files should be "owned" by
+install_uid = 0
+install_gid = 0
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+LTOBJS = adler32.lo compress.lo crc32.lo deflate.lo gzclose.lo gzlib.lo \
+ gzread.lo gzwrite.lo infback.lo inffast.lo inflate.lo inftrees.lo \
+ trees.lo uncompr.lo zutil.lo
+
+all: libsudo_z.la
+
+depend:
+ $(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
+ --builddir=$(abs_top_builddir) lib/zlib/Makefile.in
+ cd $(top_builddir) && ./config.status --file lib/zlib/Makefile
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file lib/zlib/Makefile
+
+.SUFFIXES: .c .h .lo
+
+.c.lo:
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+$(shlib_map): $(shlib_exp)
+ @$(AWK) 'BEGIN { print "{\n\tglobal:" } { print "\t\t"$$0";" } END { print "\tlocal:\n\t\t*;\n};" }' $(shlib_exp) > $@
+
+$(shlib_opt): $(shlib_exp)
+ @$(SED) 's/^/+e /' $(shlib_exp) > $@
+
+libsudo_z.la: $(LTOBJS) @LT_LDDEP@
+ case "$(LT_LDFLAGS)" in \
+ *-no-install*) \
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LDFLAGS) $(LT_LDFLAGS) $(LTOBJS);; \
+ *) \
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LDFLAGS) $(ASAN_LDFLAGS) $(HARDENING_LDFLAGS) $(LT_LDFLAGS) $(LTOBJS) -version-info $(SHLIB_VERSION) -rpath $(libexecdir)/sudo;; \
+ esac
+
+pre-install:
+
+install:
+ case "$(LT_LDFLAGS)" in \
+ *-no-install*) ;; \
+ *) if [ X"$(shlib_enable)" = X"yes" ]; then \
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --quiet --mode=install $(INSTALL) $(INSTALL_OWNER) libsudo_z.la $(DESTDIR)$(libexecdir)/sudo; \
+ fi;; \
+ esac
+
+install-dirs:
+
+install-binaries:
+
+install-includes:
+
+install-doc:
+
+install-plugin:
+
+install-fuzzer:
+
+uninstall:
+ $(LIBTOOL) $(LTFLAGS) --mode=uninstall rm -f $(DESTDIR)$(libexecdir)/sudo/libsudo_z.la
+ -test -z "$(INSTALL_BACKUP)" || \
+ rm -f $(DESTDIR)$(libexecdir)/sudo/libsudo_z.*~
+
+splint:
+
+cppcheck:
+
+pvs-log-files:
+
+pvs-studio:
+
+fuzz:
+
+check-fuzzer:
+
+check: check-fuzzer
+
+check-verbose: check
+
+clean:
+ -$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f *.lo *.o *.la
+ -rm -f stamp-* core *.core core.*
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile .libs zconf.h
+
+clobber: distclean
+
+realclean: distclean
+ rm -f TAGS tags
+
+cleandir: realclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean
+
+# Autogenerated dependencies, do not modify
+adler32.lo: $(srcdir)/adler32.c $(srcdir)/zlib.h $(srcdir)/zutil.h ./zconf.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/adler32.c
+compress.lo: $(srcdir)/compress.c $(srcdir)/zlib.h ./zconf.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/compress.c
+crc32.lo: $(srcdir)/crc32.c $(srcdir)/crc32.h $(srcdir)/zlib.h \
+ $(srcdir)/zutil.h ./zconf.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/crc32.c
+deflate.lo: $(srcdir)/deflate.c $(srcdir)/deflate.h $(srcdir)/zlib.h \
+ $(srcdir)/zutil.h ./zconf.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/deflate.c
+gzclose.lo: $(srcdir)/gzclose.c $(srcdir)/gzguts.h $(srcdir)/zlib.h ./zconf.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/gzclose.c
+gzlib.lo: $(srcdir)/gzlib.c $(srcdir)/gzguts.h $(srcdir)/zlib.h ./zconf.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/gzlib.c
+gzread.lo: $(srcdir)/gzread.c $(srcdir)/gzguts.h $(srcdir)/zlib.h ./zconf.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/gzread.c
+gzwrite.lo: $(srcdir)/gzwrite.c $(srcdir)/gzguts.h $(srcdir)/zlib.h ./zconf.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/gzwrite.c
+infback.lo: $(srcdir)/infback.c $(srcdir)/inffast.h $(srcdir)/inffixed.h \
+ $(srcdir)/inflate.h $(srcdir)/inftrees.h $(srcdir)/zlib.h \
+ $(srcdir)/zutil.h ./zconf.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/infback.c
+inffast.lo: $(srcdir)/inffast.c $(srcdir)/inffast.h $(srcdir)/inflate.h \
+ $(srcdir)/inftrees.h $(srcdir)/zlib.h $(srcdir)/zutil.h ./zconf.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/inffast.c
+inflate.lo: $(srcdir)/inflate.c $(srcdir)/inffast.h $(srcdir)/inffixed.h \
+ $(srcdir)/inflate.h $(srcdir)/inftrees.h $(srcdir)/zlib.h \
+ $(srcdir)/zutil.h ./zconf.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/inflate.c
+inftrees.lo: $(srcdir)/inftrees.c $(srcdir)/inftrees.h $(srcdir)/zlib.h \
+ $(srcdir)/zutil.h ./zconf.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/inftrees.c
+trees.lo: $(srcdir)/trees.c $(srcdir)/deflate.h $(srcdir)/trees.h \
+ $(srcdir)/zlib.h $(srcdir)/zutil.h ./zconf.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/trees.c
+uncompr.lo: $(srcdir)/uncompr.c $(srcdir)/zlib.h ./zconf.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/uncompr.c
+zutil.lo: $(srcdir)/zutil.c $(srcdir)/gzguts.h $(srcdir)/zlib.h \
+ $(srcdir)/zutil.h ./zconf.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/zutil.c
diff --git a/lib/zlib/adler32.c b/lib/zlib/adler32.c
new file mode 100644
index 0000000..04b81d2
--- /dev/null
+++ b/lib/zlib/adler32.c
@@ -0,0 +1,164 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2011, 2016 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+
+#define BASE 65521U /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* use NO_DIVIDE if your processor does not do division in hardware --
+ try it both ways to see which is faster */
+#ifdef NO_DIVIDE
+/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
+ (thank you to John Reiser for pointing this out) */
+# define CHOP(a) \
+ do { \
+ unsigned long tmp = a >> 16; \
+ a &= 0xffffUL; \
+ a += (tmp << 4) - tmp; \
+ } while (0)
+# define MOD28(a) \
+ do { \
+ CHOP(a); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+# define MOD(a) \
+ do { \
+ CHOP(a); \
+ MOD28(a); \
+ } while (0)
+# define MOD63(a) \
+ do { /* this assumes a is not negative */ \
+ z_off64_t tmp = a >> 32; \
+ a &= 0xffffffffL; \
+ a += (tmp << 8) - (tmp << 5) + tmp; \
+ tmp = a >> 16; \
+ a &= 0xffffL; \
+ a += (tmp << 4) - tmp; \
+ tmp = a >> 16; \
+ a &= 0xffffL; \
+ a += (tmp << 4) - tmp; \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+#else
+# define MOD(a) a %= BASE
+# define MOD28(a) a %= BASE
+# define MOD63(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len) {
+ unsigned long sum2;
+ unsigned n;
+
+ /* split Adler-32 into component sums */
+ sum2 = (adler >> 16) & 0xffff;
+ adler &= 0xffff;
+
+ /* in case user likes doing a byte at a time, keep it fast */
+ if (len == 1) {
+ adler += buf[0];
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 += adler;
+ if (sum2 >= BASE)
+ sum2 -= BASE;
+ return adler | (sum2 << 16);
+ }
+
+ /* initial Adler-32 value (deferred check for len == 1 speed) */
+ if (buf == Z_NULL)
+ return 1L;
+
+ /* in case short lengths are provided, keep it somewhat fast */
+ if (len < 16) {
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ if (adler >= BASE)
+ adler -= BASE;
+ MOD28(sum2); /* only added so many BASE's */
+ return adler | (sum2 << 16);
+ }
+
+ /* do length NMAX blocks -- requires just one modulo operation */
+ while (len >= NMAX) {
+ len -= NMAX;
+ n = NMAX / 16; /* NMAX is divisible by 16 */
+ do {
+ DO16(buf); /* 16 sums unrolled */
+ buf += 16;
+ } while (--n);
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* do remaining bytes (less than NMAX, still just one modulo) */
+ if (len) { /* avoid modulos if none remaining */
+ while (len >= 16) {
+ len -= 16;
+ DO16(buf);
+ buf += 16;
+ }
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* return recombined sums */
+ return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) {
+ return adler32_z(adler, buf, len);
+}
+
+/* ========================================================================= */
+local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) {
+ unsigned long sum1;
+ unsigned long sum2;
+ unsigned rem;
+
+ /* for negative len, return invalid adler32 as a clue for debugging */
+ if (len2 < 0)
+ return 0xffffffffUL;
+
+ /* the derivation of this formula is left as an exercise for the reader */
+ MOD63(len2); /* assumes len2 >= 0 */
+ rem = (unsigned)len2;
+ sum1 = adler1 & 0xffff;
+ sum2 = rem * sum1;
+ MOD(sum2);
+ sum1 += (adler2 & 0xffff) + BASE - 1;
+ sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
+ if (sum1 >= BASE) sum1 -= BASE;
+ if (sum1 >= BASE) sum1 -= BASE;
+ if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1);
+ if (sum2 >= BASE) sum2 -= BASE;
+ return sum1 | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) {
+ return adler32_combine_(adler1, adler2, len2);
+}
+
+uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) {
+ return adler32_combine_(adler1, adler2, len2);
+}
diff --git a/lib/zlib/compress.c b/lib/zlib/compress.c
new file mode 100644
index 0000000..f43bacf
--- /dev/null
+++ b/lib/zlib/compress.c
@@ -0,0 +1,75 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least 0.1% larger than sourceLen plus
+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+int ZEXPORT compress2(Bytef *dest, uLongf *destLen, const Bytef *source,
+ uLong sourceLen, int level) {
+ z_stream stream;
+ int err;
+ const uInt max = (uInt)-1;
+ uLong left;
+
+ left = *destLen;
+ *destLen = 0;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ err = deflateInit(&stream, level);
+ if (err != Z_OK) return err;
+
+ stream.next_out = dest;
+ stream.avail_out = 0;
+ stream.next_in = (z_const Bytef *)source;
+ stream.avail_in = 0;
+
+ do {
+ if (stream.avail_out == 0) {
+ stream.avail_out = left > (uLong)max ? max : (uInt)left;
+ left -= stream.avail_out;
+ }
+ if (stream.avail_in == 0) {
+ stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen;
+ sourceLen -= stream.avail_in;
+ }
+ err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH);
+ } while (err == Z_OK);
+
+ *destLen = stream.total_out;
+ deflateEnd(&stream);
+ return err == Z_STREAM_END ? Z_OK : err;
+}
+
+/* ===========================================================================
+ */
+int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source,
+ uLong sourceLen) {
+ return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
+}
+
+/* ===========================================================================
+ If the default memLevel or windowBits for deflateInit() is changed, then
+ this function needs to be updated.
+ */
+uLong ZEXPORT compressBound(uLong sourceLen) {
+ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
+ (sourceLen >> 25) + 13;
+}
diff --git a/lib/zlib/crc32.c b/lib/zlib/crc32.c
new file mode 100644
index 0000000..6c38f5c
--- /dev/null
+++ b/lib/zlib/crc32.c
@@ -0,0 +1,1049 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-2022 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * This interleaved implementation of a CRC makes use of pipelined multiple
+ * arithmetic-logic units, commonly found in modern CPU cores. It is due to
+ * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution.
+ */
+
+/* @(#) $Id$ */
+
+/*
+ Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
+ protection on the static variables used to control the first-use generation
+ of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
+ first call get_crc_table() to initialize the tables before allowing more than
+ one thread to use crc32().
+
+ MAKECRCH can be #defined to write out crc32.h. A main() routine is also
+ produced, so that this one source file can be compiled to an executable.
+ */
+
+#ifdef MAKECRCH
+# include <stdio.h>
+# ifndef DYNAMIC_CRC_TABLE
+# define DYNAMIC_CRC_TABLE
+# endif /* !DYNAMIC_CRC_TABLE */
+#endif /* MAKECRCH */
+
+#include "zutil.h" /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */
+
+ /*
+ A CRC of a message is computed on N braids of words in the message, where
+ each word consists of W bytes (4 or 8). If N is 3, for example, then three
+ running sparse CRCs are calculated respectively on each braid, at these
+ indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ...
+ This is done starting at a word boundary, and continues until as many blocks
+ of N * W bytes as are available have been processed. The results are combined
+ into a single CRC at the end. For this code, N must be in the range 1..6 and
+ W must be 4 or 8. The upper limit on N can be increased if desired by adding
+ more #if blocks, extending the patterns apparent in the code. In addition,
+ crc32.h would need to be regenerated, if the maximum N value is increased.
+
+ N and W are chosen empirically by benchmarking the execution time on a given
+ processor. The choices for N and W below were based on testing on Intel Kaby
+ Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64
+ Octeon II processors. The Intel, AMD, and ARM processors were all fastest
+ with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4.
+ They were all tested with either gcc or clang, all using the -O3 optimization
+ level. Your mileage may vary.
+ */
+
+/* Define N */
+#ifdef Z_TESTN
+# define N Z_TESTN
+#else
+# define N 5
+#endif
+#if N < 1 || N > 6
+# error N must be in 1..6
+#endif
+
+/*
+ z_crc_t must be at least 32 bits. z_word_t must be at least as long as
+ z_crc_t. It is assumed here that z_word_t is either 32 bits or 64 bits, and
+ that bytes are eight bits.
+ */
+
+/*
+ Define W and the associated z_word_t type. If W is not defined, then a
+ braided calculation is not used, and the associated tables and code are not
+ compiled.
+ */
+#ifdef Z_TESTW
+# if Z_TESTW-1 != -1
+# define W Z_TESTW
+# endif
+#else
+# ifdef MAKECRCH
+# define W 8 /* required for MAKECRCH */
+# else
+# if defined(__x86_64__) || defined(__aarch64__)
+# define W 8
+# else
+# define W 4
+# endif
+# endif
+#endif
+#ifdef W
+# if W == 8 && defined(Z_U8)
+ typedef Z_U8 z_word_t;
+# elif defined(Z_U4)
+# undef W
+# define W 4
+ typedef Z_U4 z_word_t;
+# else
+# undef W
+# endif
+#endif
+
+/* If available, use the ARM processor CRC32 instruction. */
+#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8
+# define ARMCRC32
+#endif
+
+#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE))
+/*
+ Swap the bytes in a z_word_t to convert between little and big endian. Any
+ self-respecting compiler will optimize this to a single machine byte-swap
+ instruction, if one is available. This assumes that word_t is either 32 bits
+ or 64 bits.
+ */
+local z_word_t byte_swap(z_word_t word) {
+# if W == 8
+ return
+ (word & 0xff00000000000000) >> 56 |
+ (word & 0xff000000000000) >> 40 |
+ (word & 0xff0000000000) >> 24 |
+ (word & 0xff00000000) >> 8 |
+ (word & 0xff000000) << 8 |
+ (word & 0xff0000) << 24 |
+ (word & 0xff00) << 40 |
+ (word & 0xff) << 56;
+# else /* W == 4 */
+ return
+ (word & 0xff000000) >> 24 |
+ (word & 0xff0000) >> 8 |
+ (word & 0xff00) << 8 |
+ (word & 0xff) << 24;
+# endif
+}
+#endif
+
+#ifdef DYNAMIC_CRC_TABLE
+/* =========================================================================
+ * Table of powers of x for combining CRC-32s, filled in by make_crc_table()
+ * below.
+ */
+ local z_crc_t FAR x2n_table[32];
+#else
+/* =========================================================================
+ * Tables for byte-wise and braided CRC-32 calculations, and a table of powers
+ * of x for combining CRC-32s, all made by make_crc_table().
+ */
+# include "crc32.h"
+#endif
+
+/* CRC polynomial. */
+#define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */
+
+/*
+ Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial,
+ reflected. For speed, this requires that a not be zero.
+ */
+local z_crc_t multmodp(z_crc_t a, z_crc_t b) {
+ z_crc_t m, p;
+
+ m = (z_crc_t)1 << 31;
+ p = 0;
+ for (;;) {
+ if (a & m) {
+ p ^= b;
+ if ((a & (m - 1)) == 0)
+ break;
+ }
+ m >>= 1;
+ b = b & 1 ? (b >> 1) ^ POLY : b >> 1;
+ }
+ return p;
+}
+
+/*
+ Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been
+ initialized.
+ */
+local z_crc_t x2nmodp(z_off64_t n, unsigned k) {
+ z_crc_t p;
+
+ p = (z_crc_t)1 << 31; /* x^0 == 1 */
+ while (n) {
+ if (n & 1)
+ p = multmodp(x2n_table[k & 31], p);
+ n >>= 1;
+ k++;
+ }
+ return p;
+}
+
+#ifdef DYNAMIC_CRC_TABLE
+/* =========================================================================
+ * Build the tables for byte-wise and braided CRC-32 calculations, and a table
+ * of powers of x for combining CRC-32s.
+ */
+local z_crc_t FAR crc_table[256];
+#ifdef W
+ local z_word_t FAR crc_big_table[256];
+ local z_crc_t FAR crc_braid_table[W][256];
+ local z_word_t FAR crc_braid_big_table[W][256];
+ local void braid(z_crc_t [][256], z_word_t [][256], int, int);
+#endif
+#ifdef MAKECRCH
+ local void write_table(FILE *, const z_crc_t FAR *, int);
+ local void write_table32hi(FILE *, const z_word_t FAR *, int);
+ local void write_table64(FILE *, const z_word_t FAR *, int);
+#endif /* MAKECRCH */
+
+/*
+ Define a once() function depending on the availability of atomics. If this is
+ compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in
+ multiple threads, and if atomics are not available, then get_crc_table() must
+ be called to initialize the tables and must return before any threads are
+ allowed to compute or combine CRCs.
+ */
+
+/* Definition of once functionality. */
+typedef struct once_s once_t;
+
+/* Check for the availability of atomics. */
+#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \
+ !defined(__STDC_NO_ATOMICS__)
+
+#include <stdatomic.h>
+
+/* Structure for once(), which must be initialized with ONCE_INIT. */
+struct once_s {
+ atomic_flag begun;
+ atomic_int done;
+};
+#define ONCE_INIT {ATOMIC_FLAG_INIT, 0}
+
+/*
+ Run the provided init() function exactly once, even if multiple threads
+ invoke once() at the same time. The state must be a once_t initialized with
+ ONCE_INIT.
+ */
+local void once(once_t *state, void (*init)(void)) {
+ if (!atomic_load(&state->done)) {
+ if (atomic_flag_test_and_set(&state->begun))
+ while (!atomic_load(&state->done))
+ ;
+ else {
+ init();
+ atomic_store(&state->done, 1);
+ }
+ }
+}
+
+#else /* no atomics */
+
+/* Structure for once(), which must be initialized with ONCE_INIT. */
+struct once_s {
+ volatile int begun;
+ volatile int done;
+};
+#define ONCE_INIT {0, 0}
+
+/* Test and set. Alas, not atomic, but tries to minimize the period of
+ vulnerability. */
+local int test_and_set(int volatile *flag) {
+ int was;
+
+ was = *flag;
+ *flag = 1;
+ return was;
+}
+
+/* Run the provided init() function once. This is not thread-safe. */
+local void once(once_t *state, void (*init)(void)) {
+ if (!state->done) {
+ if (test_and_set(&state->begun))
+ while (!state->done)
+ ;
+ else {
+ init();
+ state->done = 1;
+ }
+ }
+}
+
+#endif
+
+/* State for once(). */
+local once_t made = ONCE_INIT;
+
+/*
+ Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
+ x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+ Polynomials over GF(2) are represented in binary, one bit per coefficient,
+ with the lowest powers in the most significant bit. Then adding polynomials
+ is just exclusive-or, and multiplying a polynomial by x is a right shift by
+ one. If we call the above polynomial p, and represent a byte as the
+ polynomial q, also with the lowest power in the most significant bit (so the
+ byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p,
+ where a mod b means the remainder after dividing a by b.
+
+ This calculation is done using the shift-register method of multiplying and
+ taking the remainder. The register is initialized to zero, and for each
+ incoming bit, x^32 is added mod p to the register if the bit is a one (where
+ x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x
+ (which is shifting right by one and adding x^32 mod p if the bit shifted out
+ is a one). We start with the highest power (least significant bit) of q and
+ repeat for all eight bits of q.
+
+ The table is simply the CRC of all possible eight bit values. This is all the
+ information needed to generate CRCs on data a byte at a time for all
+ combinations of CRC register values and incoming bytes.
+ */
+
+local void make_crc_table(void) {
+ unsigned i, j, n;
+ z_crc_t p;
+
+ /* initialize the CRC of bytes tables */
+ for (i = 0; i < 256; i++) {
+ p = i;
+ for (j = 0; j < 8; j++)
+ p = p & 1 ? (p >> 1) ^ POLY : p >> 1;
+ crc_table[i] = p;
+#ifdef W
+ crc_big_table[i] = byte_swap(p);
+#endif
+ }
+
+ /* initialize the x^2^n mod p(x) table */
+ p = (z_crc_t)1 << 30; /* x^1 */
+ x2n_table[0] = p;
+ for (n = 1; n < 32; n++)
+ x2n_table[n] = p = multmodp(p, p);
+
+#ifdef W
+ /* initialize the braiding tables -- needs x2n_table[] */
+ braid(crc_braid_table, crc_braid_big_table, N, W);
+#endif
+
+#ifdef MAKECRCH
+ {
+ /*
+ The crc32.h header file contains tables for both 32-bit and 64-bit
+ z_word_t's, and so requires a 64-bit type be available. In that case,
+ z_word_t must be defined to be 64-bits. This code then also generates
+ and writes out the tables for the case that z_word_t is 32 bits.
+ */
+#if !defined(W) || W != 8
+# error Need a 64-bit integer type in order to generate crc32.h.
+#endif
+ FILE *out;
+ int k, n;
+ z_crc_t ltl[8][256];
+ z_word_t big[8][256];
+
+ out = fopen("crc32.h", "w");
+ if (out == NULL) return;
+
+ /* write out little-endian CRC table to crc32.h */
+ fprintf(out,
+ "/* crc32.h -- tables for rapid CRC calculation\n"
+ " * Generated automatically by crc32.c\n */\n"
+ "\n"
+ "local const z_crc_t FAR crc_table[] = {\n"
+ " ");
+ write_table(out, crc_table, 256);
+ fprintf(out,
+ "};\n");
+
+ /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#ifdef W\n"
+ "\n"
+ "#if W == 8\n"
+ "\n"
+ "local const z_word_t FAR crc_big_table[] = {\n"
+ " ");
+ write_table64(out, crc_big_table, 256);
+ fprintf(out,
+ "};\n");
+
+ /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#else /* W == 4 */\n"
+ "\n"
+ "local const z_word_t FAR crc_big_table[] = {\n"
+ " ");
+ write_table32hi(out, crc_big_table, 256);
+ fprintf(out,
+ "};\n"
+ "\n"
+ "#endif\n");
+
+ /* write out braid tables for each value of N */
+ for (n = 1; n <= 6; n++) {
+ fprintf(out,
+ "\n"
+ "#if N == %d\n", n);
+
+ /* compute braid tables for this N and 64-bit word_t */
+ braid(ltl, big, n, 8);
+
+ /* write out braid tables for 64-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#if W == 8\n"
+ "\n"
+ "local const z_crc_t FAR crc_braid_table[][256] = {\n");
+ for (k = 0; k < 8; k++) {
+ fprintf(out, " {");
+ write_table(out, ltl[k], 256);
+ fprintf(out, "}%s", k < 7 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
+ for (k = 0; k < 8; k++) {
+ fprintf(out, " {");
+ write_table64(out, big[k], 256);
+ fprintf(out, "}%s", k < 7 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n");
+
+ /* compute braid tables for this N and 32-bit word_t */
+ braid(ltl, big, n, 4);
+
+ /* write out braid tables for 32-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#else /* W == 4 */\n"
+ "\n"
+ "local const z_crc_t FAR crc_braid_table[][256] = {\n");
+ for (k = 0; k < 4; k++) {
+ fprintf(out, " {");
+ write_table(out, ltl[k], 256);
+ fprintf(out, "}%s", k < 3 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
+ for (k = 0; k < 4; k++) {
+ fprintf(out, " {");
+ write_table32hi(out, big[k], 256);
+ fprintf(out, "}%s", k < 3 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "#endif\n"
+ "\n"
+ "#endif\n");
+ }
+ fprintf(out,
+ "\n"
+ "#endif\n");
+
+ /* write out zeros operator table to crc32.h */
+ fprintf(out,
+ "\n"
+ "local const z_crc_t FAR x2n_table[] = {\n"
+ " ");
+ write_table(out, x2n_table, 32);
+ fprintf(out,
+ "};\n");
+ fclose(out);
+ }
+#endif /* MAKECRCH */
+}
+
+#ifdef MAKECRCH
+
+/*
+ Write the 32-bit values in table[0..k-1] to out, five per line in
+ hexadecimal separated by commas.
+ */
+local void write_table(FILE *out, const z_crc_t FAR *table, int k) {
+ int n;
+
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ",
+ (unsigned long)(table[n]),
+ n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
+}
+
+/*
+ Write the high 32-bits of each value in table[0..k-1] to out, five per line
+ in hexadecimal separated by commas.
+ */
+local void write_table32hi(FILE *out, const z_word_t FAR *table, int k) {
+ int n;
+
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ",
+ (unsigned long)(table[n] >> 32),
+ n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
+}
+
+/*
+ Write the 64-bit values in table[0..k-1] to out, three per line in
+ hexadecimal separated by commas. This assumes that if there is a 64-bit
+ type, then there is also a long long integer type, and it is at least 64
+ bits. If not, then the type cast and format string can be adjusted
+ accordingly.
+ */
+local void write_table64(FILE *out, const z_word_t FAR *table, int k) {
+ int n;
+
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : " ",
+ (unsigned long long)(table[n]),
+ n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", "));
+}
+
+/* Actually do the deed. */
+int main(void) {
+ make_crc_table();
+ return 0;
+}
+
+#endif /* MAKECRCH */
+
+#ifdef W
+/*
+ Generate the little and big-endian braid tables for the given n and z_word_t
+ size w. Each array must have room for w blocks of 256 elements.
+ */
+local void braid(z_crc_t ltl[][256], z_word_t big[][256], int n, int w) {
+ int k;
+ z_crc_t i, p, q;
+ for (k = 0; k < w; k++) {
+ p = x2nmodp((n * w + 3 - k) << 3, 0);
+ ltl[k][0] = 0;
+ big[w - 1 - k][0] = 0;
+ for (i = 1; i < 256; i++) {
+ ltl[k][i] = q = multmodp(i << 24, p);
+ big[w - 1 - k][i] = byte_swap(q);
+ }
+ }
+}
+#endif
+
+#endif /* DYNAMIC_CRC_TABLE */
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32(), and to force the
+ * generation of the CRC tables in a threaded application.
+ */
+const z_crc_t FAR * ZEXPORT get_crc_table(void) {
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+ return (const z_crc_t FAR *)crc_table;
+}
+
+/* =========================================================================
+ * Use ARM machine instructions if available. This will compute the CRC about
+ * ten times faster than the braided calculation. This code does not check for
+ * the presence of the CRC instruction at run time. __ARM_FEATURE_CRC32 will
+ * only be defined if the compilation specifies an ARM processor architecture
+ * that has the instructions. For example, compiling with -march=armv8.1-a or
+ * -march=armv8-a+crc, or -march=native if the compile machine has the crc32
+ * instructions.
+ */
+#ifdef ARMCRC32
+
+/*
+ Constants empirically determined to maximize speed. These values are from
+ measurements on a Cortex-A57. Your mileage may vary.
+ */
+#define Z_BATCH 3990 /* number of words in a batch */
+#define Z_BATCH_ZEROS 0xa10d3d0c /* computed from Z_BATCH = 3990 */
+#define Z_BATCH_MIN 800 /* fewest words in a final batch */
+
+unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf,
+ z_size_t len) {
+ z_crc_t val;
+ z_word_t crc1, crc2;
+ const z_word_t *word;
+ z_word_t val0, val1, val2;
+ z_size_t last, last2, i;
+ z_size_t num;
+
+ /* Return initial CRC, if requested. */
+ if (buf == Z_NULL) return 0;
+
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+
+ /* Pre-condition the CRC */
+ crc = (~crc) & 0xffffffff;
+
+ /* Compute the CRC up to a word boundary. */
+ while (len && ((z_size_t)buf & 7) != 0) {
+ len--;
+ val = *buf++;
+ __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
+ }
+
+ /* Prepare to compute the CRC on full 64-bit words word[0..num-1]. */
+ word = (z_word_t const *)buf;
+ num = len >> 3;
+ len &= 7;
+
+ /* Do three interleaved CRCs to realize the throughput of one crc32x
+ instruction per cycle. Each CRC is calculated on Z_BATCH words. The
+ three CRCs are combined into a single CRC after each set of batches. */
+ while (num >= 3 * Z_BATCH) {
+ crc1 = 0;
+ crc2 = 0;
+ for (i = 0; i < Z_BATCH; i++) {
+ val0 = word[i];
+ val1 = word[i + Z_BATCH];
+ val2 = word[i + 2 * Z_BATCH];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
+ }
+ word += 3 * Z_BATCH;
+ num -= 3 * Z_BATCH;
+ crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc1;
+ crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc2;
+ }
+
+ /* Do one last smaller batch with the remaining words, if there are enough
+ to pay for the combination of CRCs. */
+ last = num / 3;
+ if (last >= Z_BATCH_MIN) {
+ last2 = last << 1;
+ crc1 = 0;
+ crc2 = 0;
+ for (i = 0; i < last; i++) {
+ val0 = word[i];
+ val1 = word[i + last];
+ val2 = word[i + last2];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
+ }
+ word += 3 * last;
+ num -= 3 * last;
+ val = x2nmodp(last, 6);
+ crc = multmodp(val, crc) ^ crc1;
+ crc = multmodp(val, crc) ^ crc2;
+ }
+
+ /* Compute the CRC on any remaining words. */
+ for (i = 0; i < num; i++) {
+ val0 = word[i];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ }
+ word += num;
+
+ /* Complete the CRC on any remaining bytes. */
+ buf = (const unsigned char FAR *)word;
+ while (len) {
+ len--;
+ val = *buf++;
+ __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
+ }
+
+ /* Return the CRC, post-conditioned. */
+ return crc ^ 0xffffffff;
+}
+
+#else
+
+#ifdef W
+
+/*
+ Return the CRC of the W bytes in the word_t data, taking the
+ least-significant byte of the word as the first byte of data, without any pre
+ or post conditioning. This is used to combine the CRCs of each braid.
+ */
+local z_crc_t crc_word(z_word_t data) {
+ int k;
+ for (k = 0; k < W; k++)
+ data = (data >> 8) ^ crc_table[data & 0xff];
+ return (z_crc_t)data;
+}
+
+local z_word_t crc_word_big(z_word_t data) {
+ int k;
+ for (k = 0; k < W; k++)
+ data = (data << 8) ^
+ crc_big_table[(data >> ((W - 1) << 3)) & 0xff];
+ return data;
+}
+
+#endif
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf,
+ z_size_t len) {
+ /* Return initial CRC, if requested. */
+ if (buf == Z_NULL) return 0;
+
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+
+ /* Pre-condition the CRC */
+ crc = (~crc) & 0xffffffff;
+
+#ifdef W
+
+ /* If provided enough bytes, do a braided CRC calculation. */
+ if (len >= N * W + W - 1) {
+ z_size_t blks;
+ z_word_t const *words;
+ unsigned endian;
+ int k;
+
+ /* Compute the CRC up to a z_word_t boundary. */
+ while (len && ((z_size_t)buf & (W - 1)) != 0) {
+ len--;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ }
+
+ /* Compute the CRC on as many N z_word_t blocks as are available. */
+ blks = len / (N * W);
+ len -= blks * N * W;
+ words = (z_word_t const *)buf;
+
+ /* Do endian check at execution time instead of compile time, since ARM
+ processors can change the endianness at execution time. If the
+ compiler knows what the endianness will be, it can optimize out the
+ check and the unused branch. */
+ endian = 1;
+ if (*(unsigned char *)&endian) {
+ /* Little endian. */
+
+ z_crc_t crc0;
+ z_word_t word0;
+#if N > 1
+ z_crc_t crc1;
+ z_word_t word1;
+#if N > 2
+ z_crc_t crc2;
+ z_word_t word2;
+#if N > 3
+ z_crc_t crc3;
+ z_word_t word3;
+#if N > 4
+ z_crc_t crc4;
+ z_word_t word4;
+#if N > 5
+ z_crc_t crc5;
+ z_word_t word5;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /* Initialize the CRC for each braid. */
+ crc0 = crc;
+#if N > 1
+ crc1 = 0;
+#if N > 2
+ crc2 = 0;
+#if N > 3
+ crc3 = 0;
+#if N > 4
+ crc4 = 0;
+#if N > 5
+ crc5 = 0;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /*
+ Process the first blks-1 blocks, computing the CRCs on each braid
+ independently.
+ */
+ while (--blks) {
+ /* Load the word for each braid into registers. */
+ word0 = crc0 ^ words[0];
+#if N > 1
+ word1 = crc1 ^ words[1];
+#if N > 2
+ word2 = crc2 ^ words[2];
+#if N > 3
+ word3 = crc3 ^ words[3];
+#if N > 4
+ word4 = crc4 ^ words[4];
+#if N > 5
+ word5 = crc5 ^ words[5];
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+
+ /* Compute and update the CRC for each word. The loop should
+ get unrolled. */
+ crc0 = crc_braid_table[0][word0 & 0xff];
+#if N > 1
+ crc1 = crc_braid_table[0][word1 & 0xff];
+#if N > 2
+ crc2 = crc_braid_table[0][word2 & 0xff];
+#if N > 3
+ crc3 = crc_braid_table[0][word3 & 0xff];
+#if N > 4
+ crc4 = crc_braid_table[0][word4 & 0xff];
+#if N > 5
+ crc5 = crc_braid_table[0][word5 & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ for (k = 1; k < W; k++) {
+ crc0 ^= crc_braid_table[k][(word0 >> (k << 3)) & 0xff];
+#if N > 1
+ crc1 ^= crc_braid_table[k][(word1 >> (k << 3)) & 0xff];
+#if N > 2
+ crc2 ^= crc_braid_table[k][(word2 >> (k << 3)) & 0xff];
+#if N > 3
+ crc3 ^= crc_braid_table[k][(word3 >> (k << 3)) & 0xff];
+#if N > 4
+ crc4 ^= crc_braid_table[k][(word4 >> (k << 3)) & 0xff];
+#if N > 5
+ crc5 ^= crc_braid_table[k][(word5 >> (k << 3)) & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ }
+ }
+
+ /*
+ Process the last block, combining the CRCs of the N braids at the
+ same time.
+ */
+ crc = crc_word(crc0 ^ words[0]);
+#if N > 1
+ crc = crc_word(crc1 ^ words[1] ^ crc);
+#if N > 2
+ crc = crc_word(crc2 ^ words[2] ^ crc);
+#if N > 3
+ crc = crc_word(crc3 ^ words[3] ^ crc);
+#if N > 4
+ crc = crc_word(crc4 ^ words[4] ^ crc);
+#if N > 5
+ crc = crc_word(crc5 ^ words[5] ^ crc);
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+ }
+ else {
+ /* Big endian. */
+
+ z_word_t crc0, word0, comb;
+#if N > 1
+ z_word_t crc1, word1;
+#if N > 2
+ z_word_t crc2, word2;
+#if N > 3
+ z_word_t crc3, word3;
+#if N > 4
+ z_word_t crc4, word4;
+#if N > 5
+ z_word_t crc5, word5;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /* Initialize the CRC for each braid. */
+ crc0 = byte_swap(crc);
+#if N > 1
+ crc1 = 0;
+#if N > 2
+ crc2 = 0;
+#if N > 3
+ crc3 = 0;
+#if N > 4
+ crc4 = 0;
+#if N > 5
+ crc5 = 0;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /*
+ Process the first blks-1 blocks, computing the CRCs on each braid
+ independently.
+ */
+ while (--blks) {
+ /* Load the word for each braid into registers. */
+ word0 = crc0 ^ words[0];
+#if N > 1
+ word1 = crc1 ^ words[1];
+#if N > 2
+ word2 = crc2 ^ words[2];
+#if N > 3
+ word3 = crc3 ^ words[3];
+#if N > 4
+ word4 = crc4 ^ words[4];
+#if N > 5
+ word5 = crc5 ^ words[5];
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+
+ /* Compute and update the CRC for each word. The loop should
+ get unrolled. */
+ crc0 = crc_braid_big_table[0][word0 & 0xff];
+#if N > 1
+ crc1 = crc_braid_big_table[0][word1 & 0xff];
+#if N > 2
+ crc2 = crc_braid_big_table[0][word2 & 0xff];
+#if N > 3
+ crc3 = crc_braid_big_table[0][word3 & 0xff];
+#if N > 4
+ crc4 = crc_braid_big_table[0][word4 & 0xff];
+#if N > 5
+ crc5 = crc_braid_big_table[0][word5 & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ for (k = 1; k < W; k++) {
+ crc0 ^= crc_braid_big_table[k][(word0 >> (k << 3)) & 0xff];
+#if N > 1
+ crc1 ^= crc_braid_big_table[k][(word1 >> (k << 3)) & 0xff];
+#if N > 2
+ crc2 ^= crc_braid_big_table[k][(word2 >> (k << 3)) & 0xff];
+#if N > 3
+ crc3 ^= crc_braid_big_table[k][(word3 >> (k << 3)) & 0xff];
+#if N > 4
+ crc4 ^= crc_braid_big_table[k][(word4 >> (k << 3)) & 0xff];
+#if N > 5
+ crc5 ^= crc_braid_big_table[k][(word5 >> (k << 3)) & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ }
+ }
+
+ /*
+ Process the last block, combining the CRCs of the N braids at the
+ same time.
+ */
+ comb = crc_word_big(crc0 ^ words[0]);
+#if N > 1
+ comb = crc_word_big(crc1 ^ words[1] ^ comb);
+#if N > 2
+ comb = crc_word_big(crc2 ^ words[2] ^ comb);
+#if N > 3
+ comb = crc_word_big(crc3 ^ words[3] ^ comb);
+#if N > 4
+ comb = crc_word_big(crc4 ^ words[4] ^ comb);
+#if N > 5
+ comb = crc_word_big(crc5 ^ words[5] ^ comb);
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+ crc = byte_swap(comb);
+ }
+
+ /*
+ Update the pointer to the remaining bytes to process.
+ */
+ buf = (unsigned char const *)words;
+ }
+
+#endif /* W */
+
+ /* Complete the computation of the CRC on any remaining bytes. */
+ while (len >= 8) {
+ len -= 8;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ }
+ while (len) {
+ len--;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ }
+
+ /* Return the CRC, post-conditioned. */
+ return crc ^ 0xffffffff;
+}
+
+#endif
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf,
+ uInt len) {
+ return crc32_z(crc, buf, len);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2) {
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+ return multmodp(x2nmodp(len2, 3), crc1) ^ (crc2 & 0xffffffff);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2) {
+ return crc32_combine64(crc1, crc2, (z_off64_t)len2);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine_gen64(z_off64_t len2) {
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+ return x2nmodp(len2, 3);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine_gen(z_off_t len2) {
+ return crc32_combine_gen64((z_off64_t)len2);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op) {
+ return multmodp(op, crc1) ^ (crc2 & 0xffffffff);
+}
diff --git a/lib/zlib/crc32.h b/lib/zlib/crc32.h
new file mode 100644
index 0000000..137df68
--- /dev/null
+++ b/lib/zlib/crc32.h
@@ -0,0 +1,9446 @@
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+local const z_crc_t FAR crc_table[] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d};
+
+#ifdef W
+
+#if W == 8
+
+local const z_word_t FAR crc_big_table[] = {
+ 0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000,
+ 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000,
+ 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000,
+ 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000,
+ 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000,
+ 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000,
+ 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000,
+ 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000,
+ 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000,
+ 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000,
+ 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000,
+ 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000,
+ 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000,
+ 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000,
+ 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000,
+ 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000,
+ 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000,
+ 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000,
+ 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000,
+ 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000,
+ 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000,
+ 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000,
+ 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000,
+ 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000,
+ 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000,
+ 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000,
+ 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000,
+ 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000,
+ 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000,
+ 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000,
+ 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000,
+ 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000,
+ 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000,
+ 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000,
+ 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000,
+ 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000,
+ 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000,
+ 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000,
+ 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000,
+ 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000,
+ 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000,
+ 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000,
+ 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000,
+ 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000,
+ 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000,
+ 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000,
+ 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000,
+ 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000,
+ 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000,
+ 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000,
+ 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000,
+ 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000,
+ 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000,
+ 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000,
+ 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000,
+ 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000,
+ 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000,
+ 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000,
+ 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000,
+ 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000,
+ 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000,
+ 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000,
+ 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000,
+ 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000,
+ 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000,
+ 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000,
+ 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000,
+ 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000,
+ 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000,
+ 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000,
+ 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000,
+ 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000,
+ 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000,
+ 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000,
+ 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000,
+ 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000,
+ 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000,
+ 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000,
+ 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000,
+ 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000,
+ 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000,
+ 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000,
+ 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000,
+ 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000,
+ 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000,
+ 0x8def022d00000000};
+
+#else /* W == 4 */
+
+local const z_word_t FAR crc_big_table[] = {
+ 0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07,
+ 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79,
+ 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7,
+ 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84,
+ 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13,
+ 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663,
+ 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5,
+ 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5,
+ 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832,
+ 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51,
+ 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf,
+ 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1,
+ 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76,
+ 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606,
+ 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996,
+ 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6,
+ 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c,
+ 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712,
+ 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c,
+ 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4,
+ 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943,
+ 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333,
+ 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe,
+ 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce,
+ 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359,
+ 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a,
+ 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04,
+ 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a,
+ 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0,
+ 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580,
+ 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10,
+ 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060,
+ 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1,
+ 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf,
+ 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31,
+ 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852,
+ 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5,
+ 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5,
+ 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75,
+ 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005,
+ 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292,
+ 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1,
+ 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f,
+ 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111,
+ 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0,
+ 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0,
+ 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40,
+ 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530,
+ 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba,
+ 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4,
+ 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a,
+ 0x8def022d};
+
+#endif
+
+#if N == 1
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa,
+ 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b,
+ 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232,
+ 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8,
+ 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e,
+ 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa,
+ 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b,
+ 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f,
+ 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719,
+ 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3,
+ 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa,
+ 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b,
+ 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed,
+ 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89,
+ 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25,
+ 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041,
+ 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c,
+ 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed,
+ 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4,
+ 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758,
+ 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e,
+ 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a,
+ 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed,
+ 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889,
+ 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df,
+ 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544,
+ 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d,
+ 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c,
+ 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1,
+ 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95,
+ 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839,
+ 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d,
+ 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976,
+ 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7,
+ 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be,
+ 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144,
+ 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12,
+ 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376,
+ 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a,
+ 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e,
+ 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278,
+ 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682,
+ 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b,
+ 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a,
+ 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561,
+ 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05,
+ 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9,
+ 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd,
+ 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0,
+ 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61,
+ 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678,
+ 0x264b06e6},
+ {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413,
+ 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3,
+ 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d,
+ 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653,
+ 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9,
+ 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e,
+ 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5,
+ 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712,
+ 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8,
+ 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6,
+ 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068,
+ 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8,
+ 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579,
+ 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade,
+ 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37,
+ 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590,
+ 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4,
+ 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64,
+ 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea,
+ 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678,
+ 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282,
+ 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25,
+ 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102,
+ 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5,
+ 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f,
+ 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146,
+ 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8,
+ 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08,
+ 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c,
+ 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b,
+ 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972,
+ 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5,
+ 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d,
+ 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd,
+ 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833,
+ 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d,
+ 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7,
+ 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60,
+ 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2,
+ 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105,
+ 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff,
+ 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1,
+ 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f,
+ 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf,
+ 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617,
+ 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0,
+ 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959,
+ 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe,
+ 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca,
+ 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a,
+ 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184,
+ 0x92364a30},
+ {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216,
+ 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8,
+ 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170,
+ 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035,
+ 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6,
+ 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145,
+ 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d,
+ 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e,
+ 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d,
+ 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408,
+ 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0,
+ 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e,
+ 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c,
+ 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf,
+ 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a,
+ 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9,
+ 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1,
+ 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f,
+ 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987,
+ 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4,
+ 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37,
+ 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84,
+ 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca,
+ 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79,
+ 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba,
+ 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d,
+ 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5,
+ 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b,
+ 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643,
+ 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0,
+ 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525,
+ 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496,
+ 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8,
+ 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026,
+ 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e,
+ 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db,
+ 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118,
+ 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab,
+ 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf,
+ 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c,
+ 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf,
+ 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a,
+ 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32,
+ 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec,
+ 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82,
+ 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31,
+ 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4,
+ 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957,
+ 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f,
+ 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1,
+ 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869,
+ 0xe4c4abcc},
+ {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0,
+ 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271,
+ 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61,
+ 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52,
+ 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43,
+ 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333,
+ 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64,
+ 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314,
+ 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205,
+ 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136,
+ 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26,
+ 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997,
+ 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849,
+ 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739,
+ 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8,
+ 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98,
+ 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b,
+ 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba,
+ 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa,
+ 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d,
+ 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c,
+ 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc,
+ 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af,
+ 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf,
+ 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce,
+ 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922,
+ 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532,
+ 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183,
+ 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710,
+ 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860,
+ 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1,
+ 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1,
+ 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956,
+ 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7,
+ 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7,
+ 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4,
+ 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5,
+ 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5,
+ 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb,
+ 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb,
+ 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da,
+ 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9,
+ 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9,
+ 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48,
+ 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df,
+ 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af,
+ 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e,
+ 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e,
+ 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d,
+ 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c,
+ 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c,
+ 0xca64c78c},
+ {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757,
+ 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a,
+ 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733,
+ 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
+ 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,
+ 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42,
+ 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5,
+ 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
+ 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086,
+ 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4,
+ 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,
+ 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
+ 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d,
+ 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f,
+ 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859,
+ 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
+ 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,
+ 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028,
+ 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891,
+ 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
+ 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec,
+ 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde,
+ 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,
+ 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
+ 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24,
+ 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e,
+ 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7,
+ 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
+ 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,
+ 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196,
+ 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0,
+ 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
+ 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52,
+ 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f,
+ 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,
+ 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
+ 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675,
+ 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647,
+ 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d,
+ 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
+ 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,
+ 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc,
+ 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645,
+ 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
+ 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138,
+ 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a,
+ 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,
+ 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
+ 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0,
+ 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d,
+ 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194,
+ 0xde0506f1},
+ {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc,
+ 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f,
+ 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a,
+ 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
+ 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,
+ 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023,
+ 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e,
+ 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
+ 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84,
+ 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7,
+ 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,
+ 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
+ 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0,
+ 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b,
+ 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816,
+ 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
+ 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,
+ 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f,
+ 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba,
+ 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
+ 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98,
+ 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873,
+ 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,
+ 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
+ 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134,
+ 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7,
+ 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732,
+ 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
+ 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,
+ 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b,
+ 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26,
+ 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
+ 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc,
+ 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef,
+ 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,
+ 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
+ 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8,
+ 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43,
+ 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e,
+ 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
+ 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,
+ 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07,
+ 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982,
+ 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
+ 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0,
+ 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b,
+ 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,
+ 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
+ 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c,
+ 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f,
+ 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda,
+ 0xbe9834ed},
+ {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504,
+ 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49,
+ 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e,
+ 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
+ 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,
+ 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c,
+ 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620,
+ 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
+ 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae,
+ 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2,
+ 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,
+ 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
+ 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05,
+ 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40,
+ 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f,
+ 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
+ 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,
+ 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d,
+ 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da,
+ 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
+ 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af,
+ 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea,
+ 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,
+ 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
+ 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa,
+ 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a,
+ 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd,
+ 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
+ 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,
+ 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f,
+ 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290,
+ 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
+ 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed,
+ 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0,
+ 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,
+ 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
+ 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0,
+ 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5,
+ 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc,
+ 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
+ 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,
+ 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e,
+ 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299,
+ 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
+ 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec,
+ 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9,
+ 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,
+ 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
+ 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9,
+ 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4,
+ 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33,
+ 0x9324fd72},
+ {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000,
+ 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000,
+ 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000,
+ 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000,
+ 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000,
+ 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000,
+ 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000,
+ 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000,
+ 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000,
+ 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000,
+ 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000,
+ 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000,
+ 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000,
+ 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000,
+ 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000,
+ 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000,
+ 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000,
+ 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000,
+ 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000,
+ 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000,
+ 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000,
+ 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000,
+ 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000,
+ 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000,
+ 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000,
+ 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000,
+ 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000,
+ 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000,
+ 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000,
+ 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000,
+ 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000,
+ 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000,
+ 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000,
+ 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000,
+ 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000,
+ 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000,
+ 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000,
+ 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000,
+ 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000,
+ 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000,
+ 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000,
+ 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000,
+ 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000,
+ 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000,
+ 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000,
+ 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000,
+ 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000,
+ 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000,
+ 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000,
+ 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000,
+ 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000,
+ 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000,
+ 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000,
+ 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000,
+ 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000,
+ 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000,
+ 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000,
+ 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000,
+ 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000,
+ 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000,
+ 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000,
+ 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000,
+ 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000,
+ 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000,
+ 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000,
+ 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000,
+ 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000,
+ 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000,
+ 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000,
+ 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000,
+ 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000,
+ 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000,
+ 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000,
+ 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000,
+ 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000,
+ 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000,
+ 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000,
+ 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000,
+ 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000,
+ 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000,
+ 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000,
+ 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000,
+ 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000,
+ 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000,
+ 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000,
+ 0x8def022d00000000},
+ {0x0000000000000000, 0x41311b1900000000, 0x8262363200000000,
+ 0xc3532d2b00000000, 0x04c56c6400000000, 0x45f4777d00000000,
+ 0x86a75a5600000000, 0xc796414f00000000, 0x088ad9c800000000,
+ 0x49bbc2d100000000, 0x8ae8effa00000000, 0xcbd9f4e300000000,
+ 0x0c4fb5ac00000000, 0x4d7eaeb500000000, 0x8e2d839e00000000,
+ 0xcf1c988700000000, 0x5112c24a00000000, 0x1023d95300000000,
+ 0xd370f47800000000, 0x9241ef6100000000, 0x55d7ae2e00000000,
+ 0x14e6b53700000000, 0xd7b5981c00000000, 0x9684830500000000,
+ 0x59981b8200000000, 0x18a9009b00000000, 0xdbfa2db000000000,
+ 0x9acb36a900000000, 0x5d5d77e600000000, 0x1c6c6cff00000000,
+ 0xdf3f41d400000000, 0x9e0e5acd00000000, 0xa224849500000000,
+ 0xe3159f8c00000000, 0x2046b2a700000000, 0x6177a9be00000000,
+ 0xa6e1e8f100000000, 0xe7d0f3e800000000, 0x2483dec300000000,
+ 0x65b2c5da00000000, 0xaaae5d5d00000000, 0xeb9f464400000000,
+ 0x28cc6b6f00000000, 0x69fd707600000000, 0xae6b313900000000,
+ 0xef5a2a2000000000, 0x2c09070b00000000, 0x6d381c1200000000,
+ 0xf33646df00000000, 0xb2075dc600000000, 0x715470ed00000000,
+ 0x30656bf400000000, 0xf7f32abb00000000, 0xb6c231a200000000,
+ 0x75911c8900000000, 0x34a0079000000000, 0xfbbc9f1700000000,
+ 0xba8d840e00000000, 0x79dea92500000000, 0x38efb23c00000000,
+ 0xff79f37300000000, 0xbe48e86a00000000, 0x7d1bc54100000000,
+ 0x3c2ade5800000000, 0x054f79f000000000, 0x447e62e900000000,
+ 0x872d4fc200000000, 0xc61c54db00000000, 0x018a159400000000,
+ 0x40bb0e8d00000000, 0x83e823a600000000, 0xc2d938bf00000000,
+ 0x0dc5a03800000000, 0x4cf4bb2100000000, 0x8fa7960a00000000,
+ 0xce968d1300000000, 0x0900cc5c00000000, 0x4831d74500000000,
+ 0x8b62fa6e00000000, 0xca53e17700000000, 0x545dbbba00000000,
+ 0x156ca0a300000000, 0xd63f8d8800000000, 0x970e969100000000,
+ 0x5098d7de00000000, 0x11a9ccc700000000, 0xd2fae1ec00000000,
+ 0x93cbfaf500000000, 0x5cd7627200000000, 0x1de6796b00000000,
+ 0xdeb5544000000000, 0x9f844f5900000000, 0x58120e1600000000,
+ 0x1923150f00000000, 0xda70382400000000, 0x9b41233d00000000,
+ 0xa76bfd6500000000, 0xe65ae67c00000000, 0x2509cb5700000000,
+ 0x6438d04e00000000, 0xa3ae910100000000, 0xe29f8a1800000000,
+ 0x21cca73300000000, 0x60fdbc2a00000000, 0xafe124ad00000000,
+ 0xeed03fb400000000, 0x2d83129f00000000, 0x6cb2098600000000,
+ 0xab2448c900000000, 0xea1553d000000000, 0x29467efb00000000,
+ 0x687765e200000000, 0xf6793f2f00000000, 0xb748243600000000,
+ 0x741b091d00000000, 0x352a120400000000, 0xf2bc534b00000000,
+ 0xb38d485200000000, 0x70de657900000000, 0x31ef7e6000000000,
+ 0xfef3e6e700000000, 0xbfc2fdfe00000000, 0x7c91d0d500000000,
+ 0x3da0cbcc00000000, 0xfa368a8300000000, 0xbb07919a00000000,
+ 0x7854bcb100000000, 0x3965a7a800000000, 0x4b98833b00000000,
+ 0x0aa9982200000000, 0xc9fab50900000000, 0x88cbae1000000000,
+ 0x4f5def5f00000000, 0x0e6cf44600000000, 0xcd3fd96d00000000,
+ 0x8c0ec27400000000, 0x43125af300000000, 0x022341ea00000000,
+ 0xc1706cc100000000, 0x804177d800000000, 0x47d7369700000000,
+ 0x06e62d8e00000000, 0xc5b500a500000000, 0x84841bbc00000000,
+ 0x1a8a417100000000, 0x5bbb5a6800000000, 0x98e8774300000000,
+ 0xd9d96c5a00000000, 0x1e4f2d1500000000, 0x5f7e360c00000000,
+ 0x9c2d1b2700000000, 0xdd1c003e00000000, 0x120098b900000000,
+ 0x533183a000000000, 0x9062ae8b00000000, 0xd153b59200000000,
+ 0x16c5f4dd00000000, 0x57f4efc400000000, 0x94a7c2ef00000000,
+ 0xd596d9f600000000, 0xe9bc07ae00000000, 0xa88d1cb700000000,
+ 0x6bde319c00000000, 0x2aef2a8500000000, 0xed796bca00000000,
+ 0xac4870d300000000, 0x6f1b5df800000000, 0x2e2a46e100000000,
+ 0xe136de6600000000, 0xa007c57f00000000, 0x6354e85400000000,
+ 0x2265f34d00000000, 0xe5f3b20200000000, 0xa4c2a91b00000000,
+ 0x6791843000000000, 0x26a09f2900000000, 0xb8aec5e400000000,
+ 0xf99fdefd00000000, 0x3accf3d600000000, 0x7bfde8cf00000000,
+ 0xbc6ba98000000000, 0xfd5ab29900000000, 0x3e099fb200000000,
+ 0x7f3884ab00000000, 0xb0241c2c00000000, 0xf115073500000000,
+ 0x32462a1e00000000, 0x7377310700000000, 0xb4e1704800000000,
+ 0xf5d06b5100000000, 0x3683467a00000000, 0x77b25d6300000000,
+ 0x4ed7facb00000000, 0x0fe6e1d200000000, 0xccb5ccf900000000,
+ 0x8d84d7e000000000, 0x4a1296af00000000, 0x0b238db600000000,
+ 0xc870a09d00000000, 0x8941bb8400000000, 0x465d230300000000,
+ 0x076c381a00000000, 0xc43f153100000000, 0x850e0e2800000000,
+ 0x42984f6700000000, 0x03a9547e00000000, 0xc0fa795500000000,
+ 0x81cb624c00000000, 0x1fc5388100000000, 0x5ef4239800000000,
+ 0x9da70eb300000000, 0xdc9615aa00000000, 0x1b0054e500000000,
+ 0x5a314ffc00000000, 0x996262d700000000, 0xd85379ce00000000,
+ 0x174fe14900000000, 0x567efa5000000000, 0x952dd77b00000000,
+ 0xd41ccc6200000000, 0x138a8d2d00000000, 0x52bb963400000000,
+ 0x91e8bb1f00000000, 0xd0d9a00600000000, 0xecf37e5e00000000,
+ 0xadc2654700000000, 0x6e91486c00000000, 0x2fa0537500000000,
+ 0xe836123a00000000, 0xa907092300000000, 0x6a54240800000000,
+ 0x2b653f1100000000, 0xe479a79600000000, 0xa548bc8f00000000,
+ 0x661b91a400000000, 0x272a8abd00000000, 0xe0bccbf200000000,
+ 0xa18dd0eb00000000, 0x62defdc000000000, 0x23efe6d900000000,
+ 0xbde1bc1400000000, 0xfcd0a70d00000000, 0x3f838a2600000000,
+ 0x7eb2913f00000000, 0xb924d07000000000, 0xf815cb6900000000,
+ 0x3b46e64200000000, 0x7a77fd5b00000000, 0xb56b65dc00000000,
+ 0xf45a7ec500000000, 0x370953ee00000000, 0x763848f700000000,
+ 0xb1ae09b800000000, 0xf09f12a100000000, 0x33cc3f8a00000000,
+ 0x72fd249300000000},
+ {0x0000000000000000, 0x376ac20100000000, 0x6ed4840300000000,
+ 0x59be460200000000, 0xdca8090700000000, 0xebc2cb0600000000,
+ 0xb27c8d0400000000, 0x85164f0500000000, 0xb851130e00000000,
+ 0x8f3bd10f00000000, 0xd685970d00000000, 0xe1ef550c00000000,
+ 0x64f91a0900000000, 0x5393d80800000000, 0x0a2d9e0a00000000,
+ 0x3d475c0b00000000, 0x70a3261c00000000, 0x47c9e41d00000000,
+ 0x1e77a21f00000000, 0x291d601e00000000, 0xac0b2f1b00000000,
+ 0x9b61ed1a00000000, 0xc2dfab1800000000, 0xf5b5691900000000,
+ 0xc8f2351200000000, 0xff98f71300000000, 0xa626b11100000000,
+ 0x914c731000000000, 0x145a3c1500000000, 0x2330fe1400000000,
+ 0x7a8eb81600000000, 0x4de47a1700000000, 0xe0464d3800000000,
+ 0xd72c8f3900000000, 0x8e92c93b00000000, 0xb9f80b3a00000000,
+ 0x3cee443f00000000, 0x0b84863e00000000, 0x523ac03c00000000,
+ 0x6550023d00000000, 0x58175e3600000000, 0x6f7d9c3700000000,
+ 0x36c3da3500000000, 0x01a9183400000000, 0x84bf573100000000,
+ 0xb3d5953000000000, 0xea6bd33200000000, 0xdd01113300000000,
+ 0x90e56b2400000000, 0xa78fa92500000000, 0xfe31ef2700000000,
+ 0xc95b2d2600000000, 0x4c4d622300000000, 0x7b27a02200000000,
+ 0x2299e62000000000, 0x15f3242100000000, 0x28b4782a00000000,
+ 0x1fdeba2b00000000, 0x4660fc2900000000, 0x710a3e2800000000,
+ 0xf41c712d00000000, 0xc376b32c00000000, 0x9ac8f52e00000000,
+ 0xada2372f00000000, 0xc08d9a7000000000, 0xf7e7587100000000,
+ 0xae591e7300000000, 0x9933dc7200000000, 0x1c25937700000000,
+ 0x2b4f517600000000, 0x72f1177400000000, 0x459bd57500000000,
+ 0x78dc897e00000000, 0x4fb64b7f00000000, 0x16080d7d00000000,
+ 0x2162cf7c00000000, 0xa474807900000000, 0x931e427800000000,
+ 0xcaa0047a00000000, 0xfdcac67b00000000, 0xb02ebc6c00000000,
+ 0x87447e6d00000000, 0xdefa386f00000000, 0xe990fa6e00000000,
+ 0x6c86b56b00000000, 0x5bec776a00000000, 0x0252316800000000,
+ 0x3538f36900000000, 0x087faf6200000000, 0x3f156d6300000000,
+ 0x66ab2b6100000000, 0x51c1e96000000000, 0xd4d7a66500000000,
+ 0xe3bd646400000000, 0xba03226600000000, 0x8d69e06700000000,
+ 0x20cbd74800000000, 0x17a1154900000000, 0x4e1f534b00000000,
+ 0x7975914a00000000, 0xfc63de4f00000000, 0xcb091c4e00000000,
+ 0x92b75a4c00000000, 0xa5dd984d00000000, 0x989ac44600000000,
+ 0xaff0064700000000, 0xf64e404500000000, 0xc124824400000000,
+ 0x4432cd4100000000, 0x73580f4000000000, 0x2ae6494200000000,
+ 0x1d8c8b4300000000, 0x5068f15400000000, 0x6702335500000000,
+ 0x3ebc755700000000, 0x09d6b75600000000, 0x8cc0f85300000000,
+ 0xbbaa3a5200000000, 0xe2147c5000000000, 0xd57ebe5100000000,
+ 0xe839e25a00000000, 0xdf53205b00000000, 0x86ed665900000000,
+ 0xb187a45800000000, 0x3491eb5d00000000, 0x03fb295c00000000,
+ 0x5a456f5e00000000, 0x6d2fad5f00000000, 0x801b35e100000000,
+ 0xb771f7e000000000, 0xeecfb1e200000000, 0xd9a573e300000000,
+ 0x5cb33ce600000000, 0x6bd9fee700000000, 0x3267b8e500000000,
+ 0x050d7ae400000000, 0x384a26ef00000000, 0x0f20e4ee00000000,
+ 0x569ea2ec00000000, 0x61f460ed00000000, 0xe4e22fe800000000,
+ 0xd388ede900000000, 0x8a36abeb00000000, 0xbd5c69ea00000000,
+ 0xf0b813fd00000000, 0xc7d2d1fc00000000, 0x9e6c97fe00000000,
+ 0xa90655ff00000000, 0x2c101afa00000000, 0x1b7ad8fb00000000,
+ 0x42c49ef900000000, 0x75ae5cf800000000, 0x48e900f300000000,
+ 0x7f83c2f200000000, 0x263d84f000000000, 0x115746f100000000,
+ 0x944109f400000000, 0xa32bcbf500000000, 0xfa958df700000000,
+ 0xcdff4ff600000000, 0x605d78d900000000, 0x5737bad800000000,
+ 0x0e89fcda00000000, 0x39e33edb00000000, 0xbcf571de00000000,
+ 0x8b9fb3df00000000, 0xd221f5dd00000000, 0xe54b37dc00000000,
+ 0xd80c6bd700000000, 0xef66a9d600000000, 0xb6d8efd400000000,
+ 0x81b22dd500000000, 0x04a462d000000000, 0x33cea0d100000000,
+ 0x6a70e6d300000000, 0x5d1a24d200000000, 0x10fe5ec500000000,
+ 0x27949cc400000000, 0x7e2adac600000000, 0x494018c700000000,
+ 0xcc5657c200000000, 0xfb3c95c300000000, 0xa282d3c100000000,
+ 0x95e811c000000000, 0xa8af4dcb00000000, 0x9fc58fca00000000,
+ 0xc67bc9c800000000, 0xf1110bc900000000, 0x740744cc00000000,
+ 0x436d86cd00000000, 0x1ad3c0cf00000000, 0x2db902ce00000000,
+ 0x4096af9100000000, 0x77fc6d9000000000, 0x2e422b9200000000,
+ 0x1928e99300000000, 0x9c3ea69600000000, 0xab54649700000000,
+ 0xf2ea229500000000, 0xc580e09400000000, 0xf8c7bc9f00000000,
+ 0xcfad7e9e00000000, 0x9613389c00000000, 0xa179fa9d00000000,
+ 0x246fb59800000000, 0x1305779900000000, 0x4abb319b00000000,
+ 0x7dd1f39a00000000, 0x3035898d00000000, 0x075f4b8c00000000,
+ 0x5ee10d8e00000000, 0x698bcf8f00000000, 0xec9d808a00000000,
+ 0xdbf7428b00000000, 0x8249048900000000, 0xb523c68800000000,
+ 0x88649a8300000000, 0xbf0e588200000000, 0xe6b01e8000000000,
+ 0xd1dadc8100000000, 0x54cc938400000000, 0x63a6518500000000,
+ 0x3a18178700000000, 0x0d72d58600000000, 0xa0d0e2a900000000,
+ 0x97ba20a800000000, 0xce0466aa00000000, 0xf96ea4ab00000000,
+ 0x7c78ebae00000000, 0x4b1229af00000000, 0x12ac6fad00000000,
+ 0x25c6adac00000000, 0x1881f1a700000000, 0x2feb33a600000000,
+ 0x765575a400000000, 0x413fb7a500000000, 0xc429f8a000000000,
+ 0xf3433aa100000000, 0xaafd7ca300000000, 0x9d97bea200000000,
+ 0xd073c4b500000000, 0xe71906b400000000, 0xbea740b600000000,
+ 0x89cd82b700000000, 0x0cdbcdb200000000, 0x3bb10fb300000000,
+ 0x620f49b100000000, 0x55658bb000000000, 0x6822d7bb00000000,
+ 0x5f4815ba00000000, 0x06f653b800000000, 0x319c91b900000000,
+ 0xb48adebc00000000, 0x83e01cbd00000000, 0xda5e5abf00000000,
+ 0xed3498be00000000},
+ {0x0000000000000000, 0x6567bcb800000000, 0x8bc809aa00000000,
+ 0xeeafb51200000000, 0x5797628f00000000, 0x32f0de3700000000,
+ 0xdc5f6b2500000000, 0xb938d79d00000000, 0xef28b4c500000000,
+ 0x8a4f087d00000000, 0x64e0bd6f00000000, 0x018701d700000000,
+ 0xb8bfd64a00000000, 0xddd86af200000000, 0x3377dfe000000000,
+ 0x5610635800000000, 0x9f57195000000000, 0xfa30a5e800000000,
+ 0x149f10fa00000000, 0x71f8ac4200000000, 0xc8c07bdf00000000,
+ 0xada7c76700000000, 0x4308727500000000, 0x266fcecd00000000,
+ 0x707fad9500000000, 0x1518112d00000000, 0xfbb7a43f00000000,
+ 0x9ed0188700000000, 0x27e8cf1a00000000, 0x428f73a200000000,
+ 0xac20c6b000000000, 0xc9477a0800000000, 0x3eaf32a000000000,
+ 0x5bc88e1800000000, 0xb5673b0a00000000, 0xd00087b200000000,
+ 0x6938502f00000000, 0x0c5fec9700000000, 0xe2f0598500000000,
+ 0x8797e53d00000000, 0xd187866500000000, 0xb4e03add00000000,
+ 0x5a4f8fcf00000000, 0x3f28337700000000, 0x8610e4ea00000000,
+ 0xe377585200000000, 0x0dd8ed4000000000, 0x68bf51f800000000,
+ 0xa1f82bf000000000, 0xc49f974800000000, 0x2a30225a00000000,
+ 0x4f579ee200000000, 0xf66f497f00000000, 0x9308f5c700000000,
+ 0x7da740d500000000, 0x18c0fc6d00000000, 0x4ed09f3500000000,
+ 0x2bb7238d00000000, 0xc518969f00000000, 0xa07f2a2700000000,
+ 0x1947fdba00000000, 0x7c20410200000000, 0x928ff41000000000,
+ 0xf7e848a800000000, 0x3d58149b00000000, 0x583fa82300000000,
+ 0xb6901d3100000000, 0xd3f7a18900000000, 0x6acf761400000000,
+ 0x0fa8caac00000000, 0xe1077fbe00000000, 0x8460c30600000000,
+ 0xd270a05e00000000, 0xb7171ce600000000, 0x59b8a9f400000000,
+ 0x3cdf154c00000000, 0x85e7c2d100000000, 0xe0807e6900000000,
+ 0x0e2fcb7b00000000, 0x6b4877c300000000, 0xa20f0dcb00000000,
+ 0xc768b17300000000, 0x29c7046100000000, 0x4ca0b8d900000000,
+ 0xf5986f4400000000, 0x90ffd3fc00000000, 0x7e5066ee00000000,
+ 0x1b37da5600000000, 0x4d27b90e00000000, 0x284005b600000000,
+ 0xc6efb0a400000000, 0xa3880c1c00000000, 0x1ab0db8100000000,
+ 0x7fd7673900000000, 0x9178d22b00000000, 0xf41f6e9300000000,
+ 0x03f7263b00000000, 0x66909a8300000000, 0x883f2f9100000000,
+ 0xed58932900000000, 0x546044b400000000, 0x3107f80c00000000,
+ 0xdfa84d1e00000000, 0xbacff1a600000000, 0xecdf92fe00000000,
+ 0x89b82e4600000000, 0x67179b5400000000, 0x027027ec00000000,
+ 0xbb48f07100000000, 0xde2f4cc900000000, 0x3080f9db00000000,
+ 0x55e7456300000000, 0x9ca03f6b00000000, 0xf9c783d300000000,
+ 0x176836c100000000, 0x720f8a7900000000, 0xcb375de400000000,
+ 0xae50e15c00000000, 0x40ff544e00000000, 0x2598e8f600000000,
+ 0x73888bae00000000, 0x16ef371600000000, 0xf840820400000000,
+ 0x9d273ebc00000000, 0x241fe92100000000, 0x4178559900000000,
+ 0xafd7e08b00000000, 0xcab05c3300000000, 0x3bb659ed00000000,
+ 0x5ed1e55500000000, 0xb07e504700000000, 0xd519ecff00000000,
+ 0x6c213b6200000000, 0x094687da00000000, 0xe7e932c800000000,
+ 0x828e8e7000000000, 0xd49eed2800000000, 0xb1f9519000000000,
+ 0x5f56e48200000000, 0x3a31583a00000000, 0x83098fa700000000,
+ 0xe66e331f00000000, 0x08c1860d00000000, 0x6da63ab500000000,
+ 0xa4e140bd00000000, 0xc186fc0500000000, 0x2f29491700000000,
+ 0x4a4ef5af00000000, 0xf376223200000000, 0x96119e8a00000000,
+ 0x78be2b9800000000, 0x1dd9972000000000, 0x4bc9f47800000000,
+ 0x2eae48c000000000, 0xc001fdd200000000, 0xa566416a00000000,
+ 0x1c5e96f700000000, 0x79392a4f00000000, 0x97969f5d00000000,
+ 0xf2f123e500000000, 0x05196b4d00000000, 0x607ed7f500000000,
+ 0x8ed162e700000000, 0xebb6de5f00000000, 0x528e09c200000000,
+ 0x37e9b57a00000000, 0xd946006800000000, 0xbc21bcd000000000,
+ 0xea31df8800000000, 0x8f56633000000000, 0x61f9d62200000000,
+ 0x049e6a9a00000000, 0xbda6bd0700000000, 0xd8c101bf00000000,
+ 0x366eb4ad00000000, 0x5309081500000000, 0x9a4e721d00000000,
+ 0xff29cea500000000, 0x11867bb700000000, 0x74e1c70f00000000,
+ 0xcdd9109200000000, 0xa8beac2a00000000, 0x4611193800000000,
+ 0x2376a58000000000, 0x7566c6d800000000, 0x10017a6000000000,
+ 0xfeaecf7200000000, 0x9bc973ca00000000, 0x22f1a45700000000,
+ 0x479618ef00000000, 0xa939adfd00000000, 0xcc5e114500000000,
+ 0x06ee4d7600000000, 0x6389f1ce00000000, 0x8d2644dc00000000,
+ 0xe841f86400000000, 0x51792ff900000000, 0x341e934100000000,
+ 0xdab1265300000000, 0xbfd69aeb00000000, 0xe9c6f9b300000000,
+ 0x8ca1450b00000000, 0x620ef01900000000, 0x07694ca100000000,
+ 0xbe519b3c00000000, 0xdb36278400000000, 0x3599929600000000,
+ 0x50fe2e2e00000000, 0x99b9542600000000, 0xfcdee89e00000000,
+ 0x12715d8c00000000, 0x7716e13400000000, 0xce2e36a900000000,
+ 0xab498a1100000000, 0x45e63f0300000000, 0x208183bb00000000,
+ 0x7691e0e300000000, 0x13f65c5b00000000, 0xfd59e94900000000,
+ 0x983e55f100000000, 0x2106826c00000000, 0x44613ed400000000,
+ 0xaace8bc600000000, 0xcfa9377e00000000, 0x38417fd600000000,
+ 0x5d26c36e00000000, 0xb389767c00000000, 0xd6eecac400000000,
+ 0x6fd61d5900000000, 0x0ab1a1e100000000, 0xe41e14f300000000,
+ 0x8179a84b00000000, 0xd769cb1300000000, 0xb20e77ab00000000,
+ 0x5ca1c2b900000000, 0x39c67e0100000000, 0x80fea99c00000000,
+ 0xe599152400000000, 0x0b36a03600000000, 0x6e511c8e00000000,
+ 0xa716668600000000, 0xc271da3e00000000, 0x2cde6f2c00000000,
+ 0x49b9d39400000000, 0xf081040900000000, 0x95e6b8b100000000,
+ 0x7b490da300000000, 0x1e2eb11b00000000, 0x483ed24300000000,
+ 0x2d596efb00000000, 0xc3f6dbe900000000, 0xa691675100000000,
+ 0x1fa9b0cc00000000, 0x7ace0c7400000000, 0x9461b96600000000,
+ 0xf10605de00000000},
+ {0x0000000000000000, 0xb029603d00000000, 0x6053c07a00000000,
+ 0xd07aa04700000000, 0xc0a680f500000000, 0x708fe0c800000000,
+ 0xa0f5408f00000000, 0x10dc20b200000000, 0xc14b703000000000,
+ 0x7162100d00000000, 0xa118b04a00000000, 0x1131d07700000000,
+ 0x01edf0c500000000, 0xb1c490f800000000, 0x61be30bf00000000,
+ 0xd197508200000000, 0x8297e06000000000, 0x32be805d00000000,
+ 0xe2c4201a00000000, 0x52ed402700000000, 0x4231609500000000,
+ 0xf21800a800000000, 0x2262a0ef00000000, 0x924bc0d200000000,
+ 0x43dc905000000000, 0xf3f5f06d00000000, 0x238f502a00000000,
+ 0x93a6301700000000, 0x837a10a500000000, 0x3353709800000000,
+ 0xe329d0df00000000, 0x5300b0e200000000, 0x042fc1c100000000,
+ 0xb406a1fc00000000, 0x647c01bb00000000, 0xd455618600000000,
+ 0xc489413400000000, 0x74a0210900000000, 0xa4da814e00000000,
+ 0x14f3e17300000000, 0xc564b1f100000000, 0x754dd1cc00000000,
+ 0xa537718b00000000, 0x151e11b600000000, 0x05c2310400000000,
+ 0xb5eb513900000000, 0x6591f17e00000000, 0xd5b8914300000000,
+ 0x86b821a100000000, 0x3691419c00000000, 0xe6ebe1db00000000,
+ 0x56c281e600000000, 0x461ea15400000000, 0xf637c16900000000,
+ 0x264d612e00000000, 0x9664011300000000, 0x47f3519100000000,
+ 0xf7da31ac00000000, 0x27a091eb00000000, 0x9789f1d600000000,
+ 0x8755d16400000000, 0x377cb15900000000, 0xe706111e00000000,
+ 0x572f712300000000, 0x4958f35800000000, 0xf971936500000000,
+ 0x290b332200000000, 0x9922531f00000000, 0x89fe73ad00000000,
+ 0x39d7139000000000, 0xe9adb3d700000000, 0x5984d3ea00000000,
+ 0x8813836800000000, 0x383ae35500000000, 0xe840431200000000,
+ 0x5869232f00000000, 0x48b5039d00000000, 0xf89c63a000000000,
+ 0x28e6c3e700000000, 0x98cfa3da00000000, 0xcbcf133800000000,
+ 0x7be6730500000000, 0xab9cd34200000000, 0x1bb5b37f00000000,
+ 0x0b6993cd00000000, 0xbb40f3f000000000, 0x6b3a53b700000000,
+ 0xdb13338a00000000, 0x0a84630800000000, 0xbaad033500000000,
+ 0x6ad7a37200000000, 0xdafec34f00000000, 0xca22e3fd00000000,
+ 0x7a0b83c000000000, 0xaa71238700000000, 0x1a5843ba00000000,
+ 0x4d77329900000000, 0xfd5e52a400000000, 0x2d24f2e300000000,
+ 0x9d0d92de00000000, 0x8dd1b26c00000000, 0x3df8d25100000000,
+ 0xed82721600000000, 0x5dab122b00000000, 0x8c3c42a900000000,
+ 0x3c15229400000000, 0xec6f82d300000000, 0x5c46e2ee00000000,
+ 0x4c9ac25c00000000, 0xfcb3a26100000000, 0x2cc9022600000000,
+ 0x9ce0621b00000000, 0xcfe0d2f900000000, 0x7fc9b2c400000000,
+ 0xafb3128300000000, 0x1f9a72be00000000, 0x0f46520c00000000,
+ 0xbf6f323100000000, 0x6f15927600000000, 0xdf3cf24b00000000,
+ 0x0eaba2c900000000, 0xbe82c2f400000000, 0x6ef862b300000000,
+ 0xded1028e00000000, 0xce0d223c00000000, 0x7e24420100000000,
+ 0xae5ee24600000000, 0x1e77827b00000000, 0x92b0e6b100000000,
+ 0x2299868c00000000, 0xf2e326cb00000000, 0x42ca46f600000000,
+ 0x5216664400000000, 0xe23f067900000000, 0x3245a63e00000000,
+ 0x826cc60300000000, 0x53fb968100000000, 0xe3d2f6bc00000000,
+ 0x33a856fb00000000, 0x838136c600000000, 0x935d167400000000,
+ 0x2374764900000000, 0xf30ed60e00000000, 0x4327b63300000000,
+ 0x102706d100000000, 0xa00e66ec00000000, 0x7074c6ab00000000,
+ 0xc05da69600000000, 0xd081862400000000, 0x60a8e61900000000,
+ 0xb0d2465e00000000, 0x00fb266300000000, 0xd16c76e100000000,
+ 0x614516dc00000000, 0xb13fb69b00000000, 0x0116d6a600000000,
+ 0x11caf61400000000, 0xa1e3962900000000, 0x7199366e00000000,
+ 0xc1b0565300000000, 0x969f277000000000, 0x26b6474d00000000,
+ 0xf6cce70a00000000, 0x46e5873700000000, 0x5639a78500000000,
+ 0xe610c7b800000000, 0x366a67ff00000000, 0x864307c200000000,
+ 0x57d4574000000000, 0xe7fd377d00000000, 0x3787973a00000000,
+ 0x87aef70700000000, 0x9772d7b500000000, 0x275bb78800000000,
+ 0xf72117cf00000000, 0x470877f200000000, 0x1408c71000000000,
+ 0xa421a72d00000000, 0x745b076a00000000, 0xc472675700000000,
+ 0xd4ae47e500000000, 0x648727d800000000, 0xb4fd879f00000000,
+ 0x04d4e7a200000000, 0xd543b72000000000, 0x656ad71d00000000,
+ 0xb510775a00000000, 0x0539176700000000, 0x15e537d500000000,
+ 0xa5cc57e800000000, 0x75b6f7af00000000, 0xc59f979200000000,
+ 0xdbe815e900000000, 0x6bc175d400000000, 0xbbbbd59300000000,
+ 0x0b92b5ae00000000, 0x1b4e951c00000000, 0xab67f52100000000,
+ 0x7b1d556600000000, 0xcb34355b00000000, 0x1aa365d900000000,
+ 0xaa8a05e400000000, 0x7af0a5a300000000, 0xcad9c59e00000000,
+ 0xda05e52c00000000, 0x6a2c851100000000, 0xba56255600000000,
+ 0x0a7f456b00000000, 0x597ff58900000000, 0xe95695b400000000,
+ 0x392c35f300000000, 0x890555ce00000000, 0x99d9757c00000000,
+ 0x29f0154100000000, 0xf98ab50600000000, 0x49a3d53b00000000,
+ 0x983485b900000000, 0x281de58400000000, 0xf86745c300000000,
+ 0x484e25fe00000000, 0x5892054c00000000, 0xe8bb657100000000,
+ 0x38c1c53600000000, 0x88e8a50b00000000, 0xdfc7d42800000000,
+ 0x6feeb41500000000, 0xbf94145200000000, 0x0fbd746f00000000,
+ 0x1f6154dd00000000, 0xaf4834e000000000, 0x7f3294a700000000,
+ 0xcf1bf49a00000000, 0x1e8ca41800000000, 0xaea5c42500000000,
+ 0x7edf646200000000, 0xcef6045f00000000, 0xde2a24ed00000000,
+ 0x6e0344d000000000, 0xbe79e49700000000, 0x0e5084aa00000000,
+ 0x5d50344800000000, 0xed79547500000000, 0x3d03f43200000000,
+ 0x8d2a940f00000000, 0x9df6b4bd00000000, 0x2ddfd48000000000,
+ 0xfda574c700000000, 0x4d8c14fa00000000, 0x9c1b447800000000,
+ 0x2c32244500000000, 0xfc48840200000000, 0x4c61e43f00000000,
+ 0x5cbdc48d00000000, 0xec94a4b000000000, 0x3cee04f700000000,
+ 0x8cc764ca00000000},
+ {0x0000000000000000, 0xa5d35ccb00000000, 0x0ba1c84d00000000,
+ 0xae72948600000000, 0x1642919b00000000, 0xb391cd5000000000,
+ 0x1de359d600000000, 0xb830051d00000000, 0x6d8253ec00000000,
+ 0xc8510f2700000000, 0x66239ba100000000, 0xc3f0c76a00000000,
+ 0x7bc0c27700000000, 0xde139ebc00000000, 0x70610a3a00000000,
+ 0xd5b256f100000000, 0x9b02d60300000000, 0x3ed18ac800000000,
+ 0x90a31e4e00000000, 0x3570428500000000, 0x8d40479800000000,
+ 0x28931b5300000000, 0x86e18fd500000000, 0x2332d31e00000000,
+ 0xf68085ef00000000, 0x5353d92400000000, 0xfd214da200000000,
+ 0x58f2116900000000, 0xe0c2147400000000, 0x451148bf00000000,
+ 0xeb63dc3900000000, 0x4eb080f200000000, 0x3605ac0700000000,
+ 0x93d6f0cc00000000, 0x3da4644a00000000, 0x9877388100000000,
+ 0x20473d9c00000000, 0x8594615700000000, 0x2be6f5d100000000,
+ 0x8e35a91a00000000, 0x5b87ffeb00000000, 0xfe54a32000000000,
+ 0x502637a600000000, 0xf5f56b6d00000000, 0x4dc56e7000000000,
+ 0xe81632bb00000000, 0x4664a63d00000000, 0xe3b7faf600000000,
+ 0xad077a0400000000, 0x08d426cf00000000, 0xa6a6b24900000000,
+ 0x0375ee8200000000, 0xbb45eb9f00000000, 0x1e96b75400000000,
+ 0xb0e423d200000000, 0x15377f1900000000, 0xc08529e800000000,
+ 0x6556752300000000, 0xcb24e1a500000000, 0x6ef7bd6e00000000,
+ 0xd6c7b87300000000, 0x7314e4b800000000, 0xdd66703e00000000,
+ 0x78b52cf500000000, 0x6c0a580f00000000, 0xc9d904c400000000,
+ 0x67ab904200000000, 0xc278cc8900000000, 0x7a48c99400000000,
+ 0xdf9b955f00000000, 0x71e901d900000000, 0xd43a5d1200000000,
+ 0x01880be300000000, 0xa45b572800000000, 0x0a29c3ae00000000,
+ 0xaffa9f6500000000, 0x17ca9a7800000000, 0xb219c6b300000000,
+ 0x1c6b523500000000, 0xb9b80efe00000000, 0xf7088e0c00000000,
+ 0x52dbd2c700000000, 0xfca9464100000000, 0x597a1a8a00000000,
+ 0xe14a1f9700000000, 0x4499435c00000000, 0xeaebd7da00000000,
+ 0x4f388b1100000000, 0x9a8adde000000000, 0x3f59812b00000000,
+ 0x912b15ad00000000, 0x34f8496600000000, 0x8cc84c7b00000000,
+ 0x291b10b000000000, 0x8769843600000000, 0x22bad8fd00000000,
+ 0x5a0ff40800000000, 0xffdca8c300000000, 0x51ae3c4500000000,
+ 0xf47d608e00000000, 0x4c4d659300000000, 0xe99e395800000000,
+ 0x47ecadde00000000, 0xe23ff11500000000, 0x378da7e400000000,
+ 0x925efb2f00000000, 0x3c2c6fa900000000, 0x99ff336200000000,
+ 0x21cf367f00000000, 0x841c6ab400000000, 0x2a6efe3200000000,
+ 0x8fbda2f900000000, 0xc10d220b00000000, 0x64de7ec000000000,
+ 0xcaacea4600000000, 0x6f7fb68d00000000, 0xd74fb39000000000,
+ 0x729cef5b00000000, 0xdcee7bdd00000000, 0x793d271600000000,
+ 0xac8f71e700000000, 0x095c2d2c00000000, 0xa72eb9aa00000000,
+ 0x02fde56100000000, 0xbacde07c00000000, 0x1f1ebcb700000000,
+ 0xb16c283100000000, 0x14bf74fa00000000, 0xd814b01e00000000,
+ 0x7dc7ecd500000000, 0xd3b5785300000000, 0x7666249800000000,
+ 0xce56218500000000, 0x6b857d4e00000000, 0xc5f7e9c800000000,
+ 0x6024b50300000000, 0xb596e3f200000000, 0x1045bf3900000000,
+ 0xbe372bbf00000000, 0x1be4777400000000, 0xa3d4726900000000,
+ 0x06072ea200000000, 0xa875ba2400000000, 0x0da6e6ef00000000,
+ 0x4316661d00000000, 0xe6c53ad600000000, 0x48b7ae5000000000,
+ 0xed64f29b00000000, 0x5554f78600000000, 0xf087ab4d00000000,
+ 0x5ef53fcb00000000, 0xfb26630000000000, 0x2e9435f100000000,
+ 0x8b47693a00000000, 0x2535fdbc00000000, 0x80e6a17700000000,
+ 0x38d6a46a00000000, 0x9d05f8a100000000, 0x33776c2700000000,
+ 0x96a430ec00000000, 0xee111c1900000000, 0x4bc240d200000000,
+ 0xe5b0d45400000000, 0x4063889f00000000, 0xf8538d8200000000,
+ 0x5d80d14900000000, 0xf3f245cf00000000, 0x5621190400000000,
+ 0x83934ff500000000, 0x2640133e00000000, 0x883287b800000000,
+ 0x2de1db7300000000, 0x95d1de6e00000000, 0x300282a500000000,
+ 0x9e70162300000000, 0x3ba34ae800000000, 0x7513ca1a00000000,
+ 0xd0c096d100000000, 0x7eb2025700000000, 0xdb615e9c00000000,
+ 0x63515b8100000000, 0xc682074a00000000, 0x68f093cc00000000,
+ 0xcd23cf0700000000, 0x189199f600000000, 0xbd42c53d00000000,
+ 0x133051bb00000000, 0xb6e30d7000000000, 0x0ed3086d00000000,
+ 0xab0054a600000000, 0x0572c02000000000, 0xa0a19ceb00000000,
+ 0xb41ee81100000000, 0x11cdb4da00000000, 0xbfbf205c00000000,
+ 0x1a6c7c9700000000, 0xa25c798a00000000, 0x078f254100000000,
+ 0xa9fdb1c700000000, 0x0c2eed0c00000000, 0xd99cbbfd00000000,
+ 0x7c4fe73600000000, 0xd23d73b000000000, 0x77ee2f7b00000000,
+ 0xcfde2a6600000000, 0x6a0d76ad00000000, 0xc47fe22b00000000,
+ 0x61acbee000000000, 0x2f1c3e1200000000, 0x8acf62d900000000,
+ 0x24bdf65f00000000, 0x816eaa9400000000, 0x395eaf8900000000,
+ 0x9c8df34200000000, 0x32ff67c400000000, 0x972c3b0f00000000,
+ 0x429e6dfe00000000, 0xe74d313500000000, 0x493fa5b300000000,
+ 0xececf97800000000, 0x54dcfc6500000000, 0xf10fa0ae00000000,
+ 0x5f7d342800000000, 0xfaae68e300000000, 0x821b441600000000,
+ 0x27c818dd00000000, 0x89ba8c5b00000000, 0x2c69d09000000000,
+ 0x9459d58d00000000, 0x318a894600000000, 0x9ff81dc000000000,
+ 0x3a2b410b00000000, 0xef9917fa00000000, 0x4a4a4b3100000000,
+ 0xe438dfb700000000, 0x41eb837c00000000, 0xf9db866100000000,
+ 0x5c08daaa00000000, 0xf27a4e2c00000000, 0x57a912e700000000,
+ 0x1919921500000000, 0xbccacede00000000, 0x12b85a5800000000,
+ 0xb76b069300000000, 0x0f5b038e00000000, 0xaa885f4500000000,
+ 0x04facbc300000000, 0xa129970800000000, 0x749bc1f900000000,
+ 0xd1489d3200000000, 0x7f3a09b400000000, 0xdae9557f00000000,
+ 0x62d9506200000000, 0xc70a0ca900000000, 0x6978982f00000000,
+ 0xccabc4e400000000},
+ {0x0000000000000000, 0xb40b77a600000000, 0x29119f9700000000,
+ 0x9d1ae83100000000, 0x13244ff400000000, 0xa72f385200000000,
+ 0x3a35d06300000000, 0x8e3ea7c500000000, 0x674eef3300000000,
+ 0xd345989500000000, 0x4e5f70a400000000, 0xfa54070200000000,
+ 0x746aa0c700000000, 0xc061d76100000000, 0x5d7b3f5000000000,
+ 0xe97048f600000000, 0xce9cde6700000000, 0x7a97a9c100000000,
+ 0xe78d41f000000000, 0x5386365600000000, 0xddb8919300000000,
+ 0x69b3e63500000000, 0xf4a90e0400000000, 0x40a279a200000000,
+ 0xa9d2315400000000, 0x1dd946f200000000, 0x80c3aec300000000,
+ 0x34c8d96500000000, 0xbaf67ea000000000, 0x0efd090600000000,
+ 0x93e7e13700000000, 0x27ec969100000000, 0x9c39bdcf00000000,
+ 0x2832ca6900000000, 0xb528225800000000, 0x012355fe00000000,
+ 0x8f1df23b00000000, 0x3b16859d00000000, 0xa60c6dac00000000,
+ 0x12071a0a00000000, 0xfb7752fc00000000, 0x4f7c255a00000000,
+ 0xd266cd6b00000000, 0x666dbacd00000000, 0xe8531d0800000000,
+ 0x5c586aae00000000, 0xc142829f00000000, 0x7549f53900000000,
+ 0x52a563a800000000, 0xe6ae140e00000000, 0x7bb4fc3f00000000,
+ 0xcfbf8b9900000000, 0x41812c5c00000000, 0xf58a5bfa00000000,
+ 0x6890b3cb00000000, 0xdc9bc46d00000000, 0x35eb8c9b00000000,
+ 0x81e0fb3d00000000, 0x1cfa130c00000000, 0xa8f164aa00000000,
+ 0x26cfc36f00000000, 0x92c4b4c900000000, 0x0fde5cf800000000,
+ 0xbbd52b5e00000000, 0x79750b4400000000, 0xcd7e7ce200000000,
+ 0x506494d300000000, 0xe46fe37500000000, 0x6a5144b000000000,
+ 0xde5a331600000000, 0x4340db2700000000, 0xf74bac8100000000,
+ 0x1e3be47700000000, 0xaa3093d100000000, 0x372a7be000000000,
+ 0x83210c4600000000, 0x0d1fab8300000000, 0xb914dc2500000000,
+ 0x240e341400000000, 0x900543b200000000, 0xb7e9d52300000000,
+ 0x03e2a28500000000, 0x9ef84ab400000000, 0x2af33d1200000000,
+ 0xa4cd9ad700000000, 0x10c6ed7100000000, 0x8ddc054000000000,
+ 0x39d772e600000000, 0xd0a73a1000000000, 0x64ac4db600000000,
+ 0xf9b6a58700000000, 0x4dbdd22100000000, 0xc38375e400000000,
+ 0x7788024200000000, 0xea92ea7300000000, 0x5e999dd500000000,
+ 0xe54cb68b00000000, 0x5147c12d00000000, 0xcc5d291c00000000,
+ 0x78565eba00000000, 0xf668f97f00000000, 0x42638ed900000000,
+ 0xdf7966e800000000, 0x6b72114e00000000, 0x820259b800000000,
+ 0x36092e1e00000000, 0xab13c62f00000000, 0x1f18b18900000000,
+ 0x9126164c00000000, 0x252d61ea00000000, 0xb83789db00000000,
+ 0x0c3cfe7d00000000, 0x2bd068ec00000000, 0x9fdb1f4a00000000,
+ 0x02c1f77b00000000, 0xb6ca80dd00000000, 0x38f4271800000000,
+ 0x8cff50be00000000, 0x11e5b88f00000000, 0xa5eecf2900000000,
+ 0x4c9e87df00000000, 0xf895f07900000000, 0x658f184800000000,
+ 0xd1846fee00000000, 0x5fbac82b00000000, 0xebb1bf8d00000000,
+ 0x76ab57bc00000000, 0xc2a0201a00000000, 0xf2ea168800000000,
+ 0x46e1612e00000000, 0xdbfb891f00000000, 0x6ff0feb900000000,
+ 0xe1ce597c00000000, 0x55c52eda00000000, 0xc8dfc6eb00000000,
+ 0x7cd4b14d00000000, 0x95a4f9bb00000000, 0x21af8e1d00000000,
+ 0xbcb5662c00000000, 0x08be118a00000000, 0x8680b64f00000000,
+ 0x328bc1e900000000, 0xaf9129d800000000, 0x1b9a5e7e00000000,
+ 0x3c76c8ef00000000, 0x887dbf4900000000, 0x1567577800000000,
+ 0xa16c20de00000000, 0x2f52871b00000000, 0x9b59f0bd00000000,
+ 0x0643188c00000000, 0xb2486f2a00000000, 0x5b3827dc00000000,
+ 0xef33507a00000000, 0x7229b84b00000000, 0xc622cfed00000000,
+ 0x481c682800000000, 0xfc171f8e00000000, 0x610df7bf00000000,
+ 0xd506801900000000, 0x6ed3ab4700000000, 0xdad8dce100000000,
+ 0x47c234d000000000, 0xf3c9437600000000, 0x7df7e4b300000000,
+ 0xc9fc931500000000, 0x54e67b2400000000, 0xe0ed0c8200000000,
+ 0x099d447400000000, 0xbd9633d200000000, 0x208cdbe300000000,
+ 0x9487ac4500000000, 0x1ab90b8000000000, 0xaeb27c2600000000,
+ 0x33a8941700000000, 0x87a3e3b100000000, 0xa04f752000000000,
+ 0x1444028600000000, 0x895eeab700000000, 0x3d559d1100000000,
+ 0xb36b3ad400000000, 0x07604d7200000000, 0x9a7aa54300000000,
+ 0x2e71d2e500000000, 0xc7019a1300000000, 0x730aedb500000000,
+ 0xee10058400000000, 0x5a1b722200000000, 0xd425d5e700000000,
+ 0x602ea24100000000, 0xfd344a7000000000, 0x493f3dd600000000,
+ 0x8b9f1dcc00000000, 0x3f946a6a00000000, 0xa28e825b00000000,
+ 0x1685f5fd00000000, 0x98bb523800000000, 0x2cb0259e00000000,
+ 0xb1aacdaf00000000, 0x05a1ba0900000000, 0xecd1f2ff00000000,
+ 0x58da855900000000, 0xc5c06d6800000000, 0x71cb1ace00000000,
+ 0xfff5bd0b00000000, 0x4bfecaad00000000, 0xd6e4229c00000000,
+ 0x62ef553a00000000, 0x4503c3ab00000000, 0xf108b40d00000000,
+ 0x6c125c3c00000000, 0xd8192b9a00000000, 0x56278c5f00000000,
+ 0xe22cfbf900000000, 0x7f3613c800000000, 0xcb3d646e00000000,
+ 0x224d2c9800000000, 0x96465b3e00000000, 0x0b5cb30f00000000,
+ 0xbf57c4a900000000, 0x3169636c00000000, 0x856214ca00000000,
+ 0x1878fcfb00000000, 0xac738b5d00000000, 0x17a6a00300000000,
+ 0xa3add7a500000000, 0x3eb73f9400000000, 0x8abc483200000000,
+ 0x0482eff700000000, 0xb089985100000000, 0x2d93706000000000,
+ 0x999807c600000000, 0x70e84f3000000000, 0xc4e3389600000000,
+ 0x59f9d0a700000000, 0xedf2a70100000000, 0x63cc00c400000000,
+ 0xd7c7776200000000, 0x4add9f5300000000, 0xfed6e8f500000000,
+ 0xd93a7e6400000000, 0x6d3109c200000000, 0xf02be1f300000000,
+ 0x4420965500000000, 0xca1e319000000000, 0x7e15463600000000,
+ 0xe30fae0700000000, 0x5704d9a100000000, 0xbe74915700000000,
+ 0x0a7fe6f100000000, 0x97650ec000000000, 0x236e796600000000,
+ 0xad50dea300000000, 0x195ba90500000000, 0x8441413400000000,
+ 0x304a369200000000},
+ {0x0000000000000000, 0x9e00aacc00000000, 0x7d07254200000000,
+ 0xe3078f8e00000000, 0xfa0e4a8400000000, 0x640ee04800000000,
+ 0x87096fc600000000, 0x1909c50a00000000, 0xb51be5d300000000,
+ 0x2b1b4f1f00000000, 0xc81cc09100000000, 0x561c6a5d00000000,
+ 0x4f15af5700000000, 0xd115059b00000000, 0x32128a1500000000,
+ 0xac1220d900000000, 0x2b31bb7c00000000, 0xb53111b000000000,
+ 0x56369e3e00000000, 0xc83634f200000000, 0xd13ff1f800000000,
+ 0x4f3f5b3400000000, 0xac38d4ba00000000, 0x32387e7600000000,
+ 0x9e2a5eaf00000000, 0x002af46300000000, 0xe32d7bed00000000,
+ 0x7d2dd12100000000, 0x6424142b00000000, 0xfa24bee700000000,
+ 0x1923316900000000, 0x87239ba500000000, 0x566276f900000000,
+ 0xc862dc3500000000, 0x2b6553bb00000000, 0xb565f97700000000,
+ 0xac6c3c7d00000000, 0x326c96b100000000, 0xd16b193f00000000,
+ 0x4f6bb3f300000000, 0xe379932a00000000, 0x7d7939e600000000,
+ 0x9e7eb66800000000, 0x007e1ca400000000, 0x1977d9ae00000000,
+ 0x8777736200000000, 0x6470fcec00000000, 0xfa70562000000000,
+ 0x7d53cd8500000000, 0xe353674900000000, 0x0054e8c700000000,
+ 0x9e54420b00000000, 0x875d870100000000, 0x195d2dcd00000000,
+ 0xfa5aa24300000000, 0x645a088f00000000, 0xc848285600000000,
+ 0x5648829a00000000, 0xb54f0d1400000000, 0x2b4fa7d800000000,
+ 0x324662d200000000, 0xac46c81e00000000, 0x4f41479000000000,
+ 0xd141ed5c00000000, 0xedc29d2900000000, 0x73c237e500000000,
+ 0x90c5b86b00000000, 0x0ec512a700000000, 0x17ccd7ad00000000,
+ 0x89cc7d6100000000, 0x6acbf2ef00000000, 0xf4cb582300000000,
+ 0x58d978fa00000000, 0xc6d9d23600000000, 0x25de5db800000000,
+ 0xbbdef77400000000, 0xa2d7327e00000000, 0x3cd798b200000000,
+ 0xdfd0173c00000000, 0x41d0bdf000000000, 0xc6f3265500000000,
+ 0x58f38c9900000000, 0xbbf4031700000000, 0x25f4a9db00000000,
+ 0x3cfd6cd100000000, 0xa2fdc61d00000000, 0x41fa499300000000,
+ 0xdffae35f00000000, 0x73e8c38600000000, 0xede8694a00000000,
+ 0x0eefe6c400000000, 0x90ef4c0800000000, 0x89e6890200000000,
+ 0x17e623ce00000000, 0xf4e1ac4000000000, 0x6ae1068c00000000,
+ 0xbba0ebd000000000, 0x25a0411c00000000, 0xc6a7ce9200000000,
+ 0x58a7645e00000000, 0x41aea15400000000, 0xdfae0b9800000000,
+ 0x3ca9841600000000, 0xa2a92eda00000000, 0x0ebb0e0300000000,
+ 0x90bba4cf00000000, 0x73bc2b4100000000, 0xedbc818d00000000,
+ 0xf4b5448700000000, 0x6ab5ee4b00000000, 0x89b261c500000000,
+ 0x17b2cb0900000000, 0x909150ac00000000, 0x0e91fa6000000000,
+ 0xed9675ee00000000, 0x7396df2200000000, 0x6a9f1a2800000000,
+ 0xf49fb0e400000000, 0x17983f6a00000000, 0x899895a600000000,
+ 0x258ab57f00000000, 0xbb8a1fb300000000, 0x588d903d00000000,
+ 0xc68d3af100000000, 0xdf84fffb00000000, 0x4184553700000000,
+ 0xa283dab900000000, 0x3c83707500000000, 0xda853b5300000000,
+ 0x4485919f00000000, 0xa7821e1100000000, 0x3982b4dd00000000,
+ 0x208b71d700000000, 0xbe8bdb1b00000000, 0x5d8c549500000000,
+ 0xc38cfe5900000000, 0x6f9ede8000000000, 0xf19e744c00000000,
+ 0x1299fbc200000000, 0x8c99510e00000000, 0x9590940400000000,
+ 0x0b903ec800000000, 0xe897b14600000000, 0x76971b8a00000000,
+ 0xf1b4802f00000000, 0x6fb42ae300000000, 0x8cb3a56d00000000,
+ 0x12b30fa100000000, 0x0bbacaab00000000, 0x95ba606700000000,
+ 0x76bdefe900000000, 0xe8bd452500000000, 0x44af65fc00000000,
+ 0xdaafcf3000000000, 0x39a840be00000000, 0xa7a8ea7200000000,
+ 0xbea12f7800000000, 0x20a185b400000000, 0xc3a60a3a00000000,
+ 0x5da6a0f600000000, 0x8ce74daa00000000, 0x12e7e76600000000,
+ 0xf1e068e800000000, 0x6fe0c22400000000, 0x76e9072e00000000,
+ 0xe8e9ade200000000, 0x0bee226c00000000, 0x95ee88a000000000,
+ 0x39fca87900000000, 0xa7fc02b500000000, 0x44fb8d3b00000000,
+ 0xdafb27f700000000, 0xc3f2e2fd00000000, 0x5df2483100000000,
+ 0xbef5c7bf00000000, 0x20f56d7300000000, 0xa7d6f6d600000000,
+ 0x39d65c1a00000000, 0xdad1d39400000000, 0x44d1795800000000,
+ 0x5dd8bc5200000000, 0xc3d8169e00000000, 0x20df991000000000,
+ 0xbedf33dc00000000, 0x12cd130500000000, 0x8ccdb9c900000000,
+ 0x6fca364700000000, 0xf1ca9c8b00000000, 0xe8c3598100000000,
+ 0x76c3f34d00000000, 0x95c47cc300000000, 0x0bc4d60f00000000,
+ 0x3747a67a00000000, 0xa9470cb600000000, 0x4a40833800000000,
+ 0xd44029f400000000, 0xcd49ecfe00000000, 0x5349463200000000,
+ 0xb04ec9bc00000000, 0x2e4e637000000000, 0x825c43a900000000,
+ 0x1c5ce96500000000, 0xff5b66eb00000000, 0x615bcc2700000000,
+ 0x7852092d00000000, 0xe652a3e100000000, 0x05552c6f00000000,
+ 0x9b5586a300000000, 0x1c761d0600000000, 0x8276b7ca00000000,
+ 0x6171384400000000, 0xff71928800000000, 0xe678578200000000,
+ 0x7878fd4e00000000, 0x9b7f72c000000000, 0x057fd80c00000000,
+ 0xa96df8d500000000, 0x376d521900000000, 0xd46add9700000000,
+ 0x4a6a775b00000000, 0x5363b25100000000, 0xcd63189d00000000,
+ 0x2e64971300000000, 0xb0643ddf00000000, 0x6125d08300000000,
+ 0xff257a4f00000000, 0x1c22f5c100000000, 0x82225f0d00000000,
+ 0x9b2b9a0700000000, 0x052b30cb00000000, 0xe62cbf4500000000,
+ 0x782c158900000000, 0xd43e355000000000, 0x4a3e9f9c00000000,
+ 0xa939101200000000, 0x3739bade00000000, 0x2e307fd400000000,
+ 0xb030d51800000000, 0x53375a9600000000, 0xcd37f05a00000000,
+ 0x4a146bff00000000, 0xd414c13300000000, 0x37134ebd00000000,
+ 0xa913e47100000000, 0xb01a217b00000000, 0x2e1a8bb700000000,
+ 0xcd1d043900000000, 0x531daef500000000, 0xff0f8e2c00000000,
+ 0x610f24e000000000, 0x8208ab6e00000000, 0x1c0801a200000000,
+ 0x0501c4a800000000, 0x9b016e6400000000, 0x7806e1ea00000000,
+ 0xe6064b2600000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757,
+ 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a,
+ 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733,
+ 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
+ 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,
+ 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42,
+ 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5,
+ 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
+ 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086,
+ 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4,
+ 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,
+ 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
+ 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d,
+ 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f,
+ 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859,
+ 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
+ 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,
+ 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028,
+ 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891,
+ 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
+ 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec,
+ 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde,
+ 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,
+ 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
+ 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24,
+ 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e,
+ 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7,
+ 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
+ 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,
+ 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196,
+ 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0,
+ 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
+ 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52,
+ 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f,
+ 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,
+ 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
+ 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675,
+ 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647,
+ 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d,
+ 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
+ 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,
+ 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc,
+ 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645,
+ 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
+ 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138,
+ 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a,
+ 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,
+ 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
+ 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0,
+ 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d,
+ 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194,
+ 0xde0506f1},
+ {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc,
+ 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f,
+ 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a,
+ 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
+ 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,
+ 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023,
+ 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e,
+ 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
+ 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84,
+ 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7,
+ 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,
+ 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
+ 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0,
+ 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b,
+ 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816,
+ 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
+ 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,
+ 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f,
+ 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba,
+ 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
+ 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98,
+ 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873,
+ 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,
+ 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
+ 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134,
+ 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7,
+ 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732,
+ 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
+ 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,
+ 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b,
+ 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26,
+ 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
+ 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc,
+ 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef,
+ 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,
+ 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
+ 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8,
+ 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43,
+ 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e,
+ 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
+ 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,
+ 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07,
+ 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982,
+ 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
+ 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0,
+ 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b,
+ 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,
+ 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
+ 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c,
+ 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f,
+ 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda,
+ 0xbe9834ed},
+ {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504,
+ 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49,
+ 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e,
+ 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
+ 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,
+ 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c,
+ 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620,
+ 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
+ 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae,
+ 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2,
+ 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,
+ 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
+ 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05,
+ 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40,
+ 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f,
+ 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
+ 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,
+ 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d,
+ 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da,
+ 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
+ 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af,
+ 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea,
+ 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,
+ 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
+ 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa,
+ 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a,
+ 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd,
+ 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
+ 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,
+ 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f,
+ 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290,
+ 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
+ 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed,
+ 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0,
+ 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,
+ 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
+ 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0,
+ 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5,
+ 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc,
+ 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
+ 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,
+ 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e,
+ 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299,
+ 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
+ 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec,
+ 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9,
+ 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,
+ 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
+ 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9,
+ 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4,
+ 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33,
+ 0x9324fd72},
+ {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07,
+ 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79,
+ 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7,
+ 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84,
+ 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13,
+ 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663,
+ 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5,
+ 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5,
+ 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832,
+ 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51,
+ 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf,
+ 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1,
+ 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76,
+ 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606,
+ 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996,
+ 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6,
+ 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c,
+ 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712,
+ 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c,
+ 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4,
+ 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943,
+ 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333,
+ 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe,
+ 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce,
+ 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359,
+ 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a,
+ 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04,
+ 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a,
+ 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0,
+ 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580,
+ 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10,
+ 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060,
+ 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1,
+ 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf,
+ 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31,
+ 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852,
+ 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5,
+ 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5,
+ 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75,
+ 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005,
+ 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292,
+ 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1,
+ 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f,
+ 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111,
+ 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0,
+ 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0,
+ 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40,
+ 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530,
+ 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba,
+ 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4,
+ 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a,
+ 0x8def022d},
+ {0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64,
+ 0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1,
+ 0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e,
+ 0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61,
+ 0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82,
+ 0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff,
+ 0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7,
+ 0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da,
+ 0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139,
+ 0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6,
+ 0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89,
+ 0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c,
+ 0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0,
+ 0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d,
+ 0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a,
+ 0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177,
+ 0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de,
+ 0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b,
+ 0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824,
+ 0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e,
+ 0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad,
+ 0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0,
+ 0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d,
+ 0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60,
+ 0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83,
+ 0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822,
+ 0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d,
+ 0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8,
+ 0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171,
+ 0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c,
+ 0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b,
+ 0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6,
+ 0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca,
+ 0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f,
+ 0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430,
+ 0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf,
+ 0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c,
+ 0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51,
+ 0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9,
+ 0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84,
+ 0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67,
+ 0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398,
+ 0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7,
+ 0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62,
+ 0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e,
+ 0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923,
+ 0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4,
+ 0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9,
+ 0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070,
+ 0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5,
+ 0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a,
+ 0x72fd2493},
+ {0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907,
+ 0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f,
+ 0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a,
+ 0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e,
+ 0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512,
+ 0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14,
+ 0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b,
+ 0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d,
+ 0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731,
+ 0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925,
+ 0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620,
+ 0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28,
+ 0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70,
+ 0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176,
+ 0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d,
+ 0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b,
+ 0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b,
+ 0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63,
+ 0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266,
+ 0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a,
+ 0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446,
+ 0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40,
+ 0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557,
+ 0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51,
+ 0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d,
+ 0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0,
+ 0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5,
+ 0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed,
+ 0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd,
+ 0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb,
+ 0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0,
+ 0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6,
+ 0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de,
+ 0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6,
+ 0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3,
+ 0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7,
+ 0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb,
+ 0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd,
+ 0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92,
+ 0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094,
+ 0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598,
+ 0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c,
+ 0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489,
+ 0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81,
+ 0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9,
+ 0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af,
+ 0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4,
+ 0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2,
+ 0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2,
+ 0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba,
+ 0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf,
+ 0xed3498be},
+ {0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f,
+ 0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d,
+ 0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0,
+ 0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42,
+ 0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95,
+ 0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2,
+ 0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a,
+ 0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d,
+ 0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea,
+ 0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748,
+ 0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5,
+ 0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27,
+ 0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b,
+ 0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac,
+ 0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4,
+ 0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3,
+ 0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44,
+ 0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6,
+ 0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b,
+ 0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329,
+ 0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe,
+ 0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9,
+ 0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1,
+ 0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6,
+ 0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921,
+ 0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555,
+ 0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8,
+ 0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a,
+ 0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd,
+ 0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a,
+ 0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2,
+ 0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5,
+ 0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2,
+ 0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330,
+ 0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad,
+ 0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f,
+ 0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8,
+ 0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef,
+ 0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc,
+ 0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb,
+ 0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c,
+ 0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e,
+ 0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03,
+ 0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1,
+ 0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6,
+ 0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1,
+ 0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9,
+ 0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e,
+ 0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409,
+ 0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb,
+ 0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966,
+ 0xf10605de}};
+
+#endif
+
+#endif
+
+#if N == 2
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87,
+ 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede,
+ 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab,
+ 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c,
+ 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1,
+ 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7,
+ 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e,
+ 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308,
+ 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5,
+ 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472,
+ 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07,
+ 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e,
+ 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa,
+ 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec,
+ 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6,
+ 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0,
+ 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3,
+ 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba,
+ 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf,
+ 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975,
+ 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8,
+ 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde,
+ 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a,
+ 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c,
+ 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1,
+ 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65,
+ 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410,
+ 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649,
+ 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a,
+ 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c,
+ 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946,
+ 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450,
+ 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e,
+ 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857,
+ 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022,
+ 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5,
+ 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758,
+ 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e,
+ 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d,
+ 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b,
+ 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6,
+ 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401,
+ 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74,
+ 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d,
+ 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073,
+ 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65,
+ 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f,
+ 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749,
+ 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a,
+ 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033,
+ 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846,
+ 0x0d7139d7},
+ {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563,
+ 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f,
+ 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875,
+ 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536,
+ 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8,
+ 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43,
+ 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f,
+ 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184,
+ 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a,
+ 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39,
+ 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523,
+ 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f,
+ 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d,
+ 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6,
+ 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b,
+ 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0,
+ 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151,
+ 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d,
+ 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47,
+ 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a,
+ 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964,
+ 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef,
+ 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d,
+ 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6,
+ 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348,
+ 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53,
+ 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449,
+ 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645,
+ 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4,
+ 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f,
+ 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2,
+ 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69,
+ 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46,
+ 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a,
+ 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650,
+ 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13,
+ 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded,
+ 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366,
+ 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57,
+ 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc,
+ 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222,
+ 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61,
+ 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b,
+ 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277,
+ 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558,
+ 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3,
+ 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e,
+ 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5,
+ 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74,
+ 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78,
+ 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262,
+ 0x1c53e98a},
+ {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b,
+ 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40,
+ 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580,
+ 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7,
+ 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a,
+ 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37,
+ 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75,
+ 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218,
+ 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5,
+ 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2,
+ 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02,
+ 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59,
+ 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1,
+ 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c,
+ 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a,
+ 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307,
+ 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486,
+ 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd,
+ 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d,
+ 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2,
+ 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f,
+ 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72,
+ 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8,
+ 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985,
+ 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268,
+ 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94,
+ 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454,
+ 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f,
+ 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e,
+ 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3,
+ 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915,
+ 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778,
+ 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821,
+ 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a,
+ 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba,
+ 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d,
+ 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560,
+ 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d,
+ 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe,
+ 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3,
+ 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e,
+ 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509,
+ 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9,
+ 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92,
+ 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb,
+ 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6,
+ 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50,
+ 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d,
+ 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc,
+ 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7,
+ 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927,
+ 0x3f88e851},
+ {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96,
+ 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8,
+ 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0,
+ 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14,
+ 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7,
+ 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4,
+ 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe,
+ 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad,
+ 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e,
+ 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa,
+ 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2,
+ 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c,
+ 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab,
+ 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8,
+ 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d,
+ 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e,
+ 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7,
+ 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99,
+ 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1,
+ 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690,
+ 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933,
+ 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20,
+ 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf,
+ 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc,
+ 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f,
+ 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92,
+ 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca,
+ 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4,
+ 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd,
+ 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de,
+ 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb,
+ 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8,
+ 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474,
+ 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a,
+ 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252,
+ 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6,
+ 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55,
+ 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846,
+ 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7,
+ 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4,
+ 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47,
+ 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3,
+ 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb,
+ 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5,
+ 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49,
+ 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a,
+ 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f,
+ 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c,
+ 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305,
+ 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b,
+ 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523,
+ 0x3dee8ca6},
+ {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f,
+ 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91,
+ 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e,
+ 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c,
+ 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02,
+ 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12,
+ 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567,
+ 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277,
+ 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679,
+ 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b,
+ 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4,
+ 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a,
+ 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0,
+ 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0,
+ 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91,
+ 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881,
+ 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173,
+ 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d,
+ 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912,
+ 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8,
+ 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6,
+ 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6,
+ 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b,
+ 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b,
+ 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75,
+ 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f,
+ 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00,
+ 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee,
+ 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c,
+ 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c,
+ 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d,
+ 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d,
+ 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67,
+ 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89,
+ 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706,
+ 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14,
+ 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a,
+ 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a,
+ 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f,
+ 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f,
+ 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591,
+ 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983,
+ 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c,
+ 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2,
+ 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8,
+ 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8,
+ 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89,
+ 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99,
+ 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b,
+ 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485,
+ 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a,
+ 0x36197165},
+ {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382,
+ 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85,
+ 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06,
+ 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca,
+ 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e,
+ 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc,
+ 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616,
+ 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54,
+ 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10,
+ 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc,
+ 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f,
+ 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58,
+ 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef,
+ 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad,
+ 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b,
+ 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29,
+ 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6,
+ 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1,
+ 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622,
+ 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039,
+ 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d,
+ 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f,
+ 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32,
+ 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770,
+ 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034,
+ 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f,
+ 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc,
+ 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db,
+ 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154,
+ 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16,
+ 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0,
+ 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592,
+ 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca,
+ 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd,
+ 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e,
+ 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882,
+ 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6,
+ 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384,
+ 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1,
+ 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3,
+ 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7,
+ 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b,
+ 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8,
+ 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff,
+ 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7,
+ 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5,
+ 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23,
+ 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761,
+ 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee,
+ 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9,
+ 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a,
+ 0x1a3b93aa},
+ {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a,
+ 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca,
+ 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3,
+ 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb,
+ 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c,
+ 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58,
+ 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed,
+ 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9,
+ 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e,
+ 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906,
+ 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f,
+ 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf,
+ 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0,
+ 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4,
+ 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769,
+ 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d,
+ 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632,
+ 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82,
+ 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb,
+ 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73,
+ 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484,
+ 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0,
+ 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5,
+ 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1,
+ 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516,
+ 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f,
+ 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946,
+ 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6,
+ 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9,
+ 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad,
+ 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820,
+ 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364,
+ 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab,
+ 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b,
+ 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62,
+ 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a,
+ 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd,
+ 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089,
+ 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c,
+ 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8,
+ 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f,
+ 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477,
+ 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e,
+ 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be,
+ 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71,
+ 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635,
+ 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8,
+ 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc,
+ 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3,
+ 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753,
+ 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a,
+ 0xe147d714},
+ {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c,
+ 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b,
+ 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92,
+ 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4,
+ 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069,
+ 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526,
+ 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25,
+ 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a,
+ 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7,
+ 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491,
+ 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958,
+ 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f,
+ 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307,
+ 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648,
+ 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999,
+ 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6,
+ 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a,
+ 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d,
+ 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4,
+ 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61,
+ 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc,
+ 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3,
+ 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53,
+ 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c,
+ 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1,
+ 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c,
+ 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5,
+ 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92,
+ 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e,
+ 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771,
+ 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0,
+ 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def,
+ 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0,
+ 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7,
+ 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e,
+ 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58,
+ 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285,
+ 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca,
+ 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce,
+ 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81,
+ 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c,
+ 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a,
+ 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3,
+ 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4,
+ 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb,
+ 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4,
+ 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75,
+ 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a,
+ 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296,
+ 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1,
+ 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808,
+ 0x494f0c4b}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x43147b1700000000, 0x8628f62e00000000,
+ 0xc53c8d3900000000, 0x0c51ec5d00000000, 0x4f45974a00000000,
+ 0x8a791a7300000000, 0xc96d616400000000, 0x18a2d8bb00000000,
+ 0x5bb6a3ac00000000, 0x9e8a2e9500000000, 0xdd9e558200000000,
+ 0x14f334e600000000, 0x57e74ff100000000, 0x92dbc2c800000000,
+ 0xd1cfb9df00000000, 0x7142c0ac00000000, 0x3256bbbb00000000,
+ 0xf76a368200000000, 0xb47e4d9500000000, 0x7d132cf100000000,
+ 0x3e0757e600000000, 0xfb3bdadf00000000, 0xb82fa1c800000000,
+ 0x69e0181700000000, 0x2af4630000000000, 0xefc8ee3900000000,
+ 0xacdc952e00000000, 0x65b1f44a00000000, 0x26a58f5d00000000,
+ 0xe399026400000000, 0xa08d797300000000, 0xa382f18200000000,
+ 0xe0968a9500000000, 0x25aa07ac00000000, 0x66be7cbb00000000,
+ 0xafd31ddf00000000, 0xecc766c800000000, 0x29fbebf100000000,
+ 0x6aef90e600000000, 0xbb20293900000000, 0xf834522e00000000,
+ 0x3d08df1700000000, 0x7e1ca40000000000, 0xb771c56400000000,
+ 0xf465be7300000000, 0x3159334a00000000, 0x724d485d00000000,
+ 0xd2c0312e00000000, 0x91d44a3900000000, 0x54e8c70000000000,
+ 0x17fcbc1700000000, 0xde91dd7300000000, 0x9d85a66400000000,
+ 0x58b92b5d00000000, 0x1bad504a00000000, 0xca62e99500000000,
+ 0x8976928200000000, 0x4c4a1fbb00000000, 0x0f5e64ac00000000,
+ 0xc63305c800000000, 0x85277edf00000000, 0x401bf3e600000000,
+ 0x030f88f100000000, 0x070392de00000000, 0x4417e9c900000000,
+ 0x812b64f000000000, 0xc23f1fe700000000, 0x0b527e8300000000,
+ 0x4846059400000000, 0x8d7a88ad00000000, 0xce6ef3ba00000000,
+ 0x1fa14a6500000000, 0x5cb5317200000000, 0x9989bc4b00000000,
+ 0xda9dc75c00000000, 0x13f0a63800000000, 0x50e4dd2f00000000,
+ 0x95d8501600000000, 0xd6cc2b0100000000, 0x7641527200000000,
+ 0x3555296500000000, 0xf069a45c00000000, 0xb37ddf4b00000000,
+ 0x7a10be2f00000000, 0x3904c53800000000, 0xfc38480100000000,
+ 0xbf2c331600000000, 0x6ee38ac900000000, 0x2df7f1de00000000,
+ 0xe8cb7ce700000000, 0xabdf07f000000000, 0x62b2669400000000,
+ 0x21a61d8300000000, 0xe49a90ba00000000, 0xa78eebad00000000,
+ 0xa481635c00000000, 0xe795184b00000000, 0x22a9957200000000,
+ 0x61bdee6500000000, 0xa8d08f0100000000, 0xebc4f41600000000,
+ 0x2ef8792f00000000, 0x6dec023800000000, 0xbc23bbe700000000,
+ 0xff37c0f000000000, 0x3a0b4dc900000000, 0x791f36de00000000,
+ 0xb07257ba00000000, 0xf3662cad00000000, 0x365aa19400000000,
+ 0x754eda8300000000, 0xd5c3a3f000000000, 0x96d7d8e700000000,
+ 0x53eb55de00000000, 0x10ff2ec900000000, 0xd9924fad00000000,
+ 0x9a8634ba00000000, 0x5fbab98300000000, 0x1caec29400000000,
+ 0xcd617b4b00000000, 0x8e75005c00000000, 0x4b498d6500000000,
+ 0x085df67200000000, 0xc130971600000000, 0x8224ec0100000000,
+ 0x4718613800000000, 0x040c1a2f00000000, 0x4f00556600000000,
+ 0x0c142e7100000000, 0xc928a34800000000, 0x8a3cd85f00000000,
+ 0x4351b93b00000000, 0x0045c22c00000000, 0xc5794f1500000000,
+ 0x866d340200000000, 0x57a28ddd00000000, 0x14b6f6ca00000000,
+ 0xd18a7bf300000000, 0x929e00e400000000, 0x5bf3618000000000,
+ 0x18e71a9700000000, 0xdddb97ae00000000, 0x9ecfecb900000000,
+ 0x3e4295ca00000000, 0x7d56eedd00000000, 0xb86a63e400000000,
+ 0xfb7e18f300000000, 0x3213799700000000, 0x7107028000000000,
+ 0xb43b8fb900000000, 0xf72ff4ae00000000, 0x26e04d7100000000,
+ 0x65f4366600000000, 0xa0c8bb5f00000000, 0xe3dcc04800000000,
+ 0x2ab1a12c00000000, 0x69a5da3b00000000, 0xac99570200000000,
+ 0xef8d2c1500000000, 0xec82a4e400000000, 0xaf96dff300000000,
+ 0x6aaa52ca00000000, 0x29be29dd00000000, 0xe0d348b900000000,
+ 0xa3c733ae00000000, 0x66fbbe9700000000, 0x25efc58000000000,
+ 0xf4207c5f00000000, 0xb734074800000000, 0x72088a7100000000,
+ 0x311cf16600000000, 0xf871900200000000, 0xbb65eb1500000000,
+ 0x7e59662c00000000, 0x3d4d1d3b00000000, 0x9dc0644800000000,
+ 0xded41f5f00000000, 0x1be8926600000000, 0x58fce97100000000,
+ 0x9191881500000000, 0xd285f30200000000, 0x17b97e3b00000000,
+ 0x54ad052c00000000, 0x8562bcf300000000, 0xc676c7e400000000,
+ 0x034a4add00000000, 0x405e31ca00000000, 0x893350ae00000000,
+ 0xca272bb900000000, 0x0f1ba68000000000, 0x4c0fdd9700000000,
+ 0x4803c7b800000000, 0x0b17bcaf00000000, 0xce2b319600000000,
+ 0x8d3f4a8100000000, 0x44522be500000000, 0x074650f200000000,
+ 0xc27addcb00000000, 0x816ea6dc00000000, 0x50a11f0300000000,
+ 0x13b5641400000000, 0xd689e92d00000000, 0x959d923a00000000,
+ 0x5cf0f35e00000000, 0x1fe4884900000000, 0xdad8057000000000,
+ 0x99cc7e6700000000, 0x3941071400000000, 0x7a557c0300000000,
+ 0xbf69f13a00000000, 0xfc7d8a2d00000000, 0x3510eb4900000000,
+ 0x7604905e00000000, 0xb3381d6700000000, 0xf02c667000000000,
+ 0x21e3dfaf00000000, 0x62f7a4b800000000, 0xa7cb298100000000,
+ 0xe4df529600000000, 0x2db233f200000000, 0x6ea648e500000000,
+ 0xab9ac5dc00000000, 0xe88ebecb00000000, 0xeb81363a00000000,
+ 0xa8954d2d00000000, 0x6da9c01400000000, 0x2ebdbb0300000000,
+ 0xe7d0da6700000000, 0xa4c4a17000000000, 0x61f82c4900000000,
+ 0x22ec575e00000000, 0xf323ee8100000000, 0xb037959600000000,
+ 0x750b18af00000000, 0x361f63b800000000, 0xff7202dc00000000,
+ 0xbc6679cb00000000, 0x795af4f200000000, 0x3a4e8fe500000000,
+ 0x9ac3f69600000000, 0xd9d78d8100000000, 0x1ceb00b800000000,
+ 0x5fff7baf00000000, 0x96921acb00000000, 0xd58661dc00000000,
+ 0x10baece500000000, 0x53ae97f200000000, 0x82612e2d00000000,
+ 0xc175553a00000000, 0x0449d80300000000, 0x475da31400000000,
+ 0x8e30c27000000000, 0xcd24b96700000000, 0x0818345e00000000,
+ 0x4b0c4f4900000000},
+ {0x0000000000000000, 0x3e6bc2ef00000000, 0x3dd0f50400000000,
+ 0x03bb37eb00000000, 0x7aa0eb0900000000, 0x44cb29e600000000,
+ 0x47701e0d00000000, 0x791bdce200000000, 0xf440d71300000000,
+ 0xca2b15fc00000000, 0xc990221700000000, 0xf7fbe0f800000000,
+ 0x8ee03c1a00000000, 0xb08bfef500000000, 0xb330c91e00000000,
+ 0x8d5b0bf100000000, 0xe881ae2700000000, 0xd6ea6cc800000000,
+ 0xd5515b2300000000, 0xeb3a99cc00000000, 0x9221452e00000000,
+ 0xac4a87c100000000, 0xaff1b02a00000000, 0x919a72c500000000,
+ 0x1cc1793400000000, 0x22aabbdb00000000, 0x21118c3000000000,
+ 0x1f7a4edf00000000, 0x6661923d00000000, 0x580a50d200000000,
+ 0x5bb1673900000000, 0x65daa5d600000000, 0xd0035d4f00000000,
+ 0xee689fa000000000, 0xedd3a84b00000000, 0xd3b86aa400000000,
+ 0xaaa3b64600000000, 0x94c874a900000000, 0x9773434200000000,
+ 0xa91881ad00000000, 0x24438a5c00000000, 0x1a2848b300000000,
+ 0x19937f5800000000, 0x27f8bdb700000000, 0x5ee3615500000000,
+ 0x6088a3ba00000000, 0x6333945100000000, 0x5d5856be00000000,
+ 0x3882f36800000000, 0x06e9318700000000, 0x0552066c00000000,
+ 0x3b39c48300000000, 0x4222186100000000, 0x7c49da8e00000000,
+ 0x7ff2ed6500000000, 0x41992f8a00000000, 0xccc2247b00000000,
+ 0xf2a9e69400000000, 0xf112d17f00000000, 0xcf79139000000000,
+ 0xb662cf7200000000, 0x88090d9d00000000, 0x8bb23a7600000000,
+ 0xb5d9f89900000000, 0xa007ba9e00000000, 0x9e6c787100000000,
+ 0x9dd74f9a00000000, 0xa3bc8d7500000000, 0xdaa7519700000000,
+ 0xe4cc937800000000, 0xe777a49300000000, 0xd91c667c00000000,
+ 0x54476d8d00000000, 0x6a2caf6200000000, 0x6997988900000000,
+ 0x57fc5a6600000000, 0x2ee7868400000000, 0x108c446b00000000,
+ 0x1337738000000000, 0x2d5cb16f00000000, 0x488614b900000000,
+ 0x76edd65600000000, 0x7556e1bd00000000, 0x4b3d235200000000,
+ 0x3226ffb000000000, 0x0c4d3d5f00000000, 0x0ff60ab400000000,
+ 0x319dc85b00000000, 0xbcc6c3aa00000000, 0x82ad014500000000,
+ 0x811636ae00000000, 0xbf7df44100000000, 0xc66628a300000000,
+ 0xf80dea4c00000000, 0xfbb6dda700000000, 0xc5dd1f4800000000,
+ 0x7004e7d100000000, 0x4e6f253e00000000, 0x4dd412d500000000,
+ 0x73bfd03a00000000, 0x0aa40cd800000000, 0x34cfce3700000000,
+ 0x3774f9dc00000000, 0x091f3b3300000000, 0x844430c200000000,
+ 0xba2ff22d00000000, 0xb994c5c600000000, 0x87ff072900000000,
+ 0xfee4dbcb00000000, 0xc08f192400000000, 0xc3342ecf00000000,
+ 0xfd5fec2000000000, 0x988549f600000000, 0xa6ee8b1900000000,
+ 0xa555bcf200000000, 0x9b3e7e1d00000000, 0xe225a2ff00000000,
+ 0xdc4e601000000000, 0xdff557fb00000000, 0xe19e951400000000,
+ 0x6cc59ee500000000, 0x52ae5c0a00000000, 0x51156be100000000,
+ 0x6f7ea90e00000000, 0x166575ec00000000, 0x280eb70300000000,
+ 0x2bb580e800000000, 0x15de420700000000, 0x010905e600000000,
+ 0x3f62c70900000000, 0x3cd9f0e200000000, 0x02b2320d00000000,
+ 0x7ba9eeef00000000, 0x45c22c0000000000, 0x46791beb00000000,
+ 0x7812d90400000000, 0xf549d2f500000000, 0xcb22101a00000000,
+ 0xc89927f100000000, 0xf6f2e51e00000000, 0x8fe939fc00000000,
+ 0xb182fb1300000000, 0xb239ccf800000000, 0x8c520e1700000000,
+ 0xe988abc100000000, 0xd7e3692e00000000, 0xd4585ec500000000,
+ 0xea339c2a00000000, 0x932840c800000000, 0xad43822700000000,
+ 0xaef8b5cc00000000, 0x9093772300000000, 0x1dc87cd200000000,
+ 0x23a3be3d00000000, 0x201889d600000000, 0x1e734b3900000000,
+ 0x676897db00000000, 0x5903553400000000, 0x5ab862df00000000,
+ 0x64d3a03000000000, 0xd10a58a900000000, 0xef619a4600000000,
+ 0xecdaadad00000000, 0xd2b16f4200000000, 0xabaab3a000000000,
+ 0x95c1714f00000000, 0x967a46a400000000, 0xa811844b00000000,
+ 0x254a8fba00000000, 0x1b214d5500000000, 0x189a7abe00000000,
+ 0x26f1b85100000000, 0x5fea64b300000000, 0x6181a65c00000000,
+ 0x623a91b700000000, 0x5c51535800000000, 0x398bf68e00000000,
+ 0x07e0346100000000, 0x045b038a00000000, 0x3a30c16500000000,
+ 0x432b1d8700000000, 0x7d40df6800000000, 0x7efbe88300000000,
+ 0x40902a6c00000000, 0xcdcb219d00000000, 0xf3a0e37200000000,
+ 0xf01bd49900000000, 0xce70167600000000, 0xb76bca9400000000,
+ 0x8900087b00000000, 0x8abb3f9000000000, 0xb4d0fd7f00000000,
+ 0xa10ebf7800000000, 0x9f657d9700000000, 0x9cde4a7c00000000,
+ 0xa2b5889300000000, 0xdbae547100000000, 0xe5c5969e00000000,
+ 0xe67ea17500000000, 0xd815639a00000000, 0x554e686b00000000,
+ 0x6b25aa8400000000, 0x689e9d6f00000000, 0x56f55f8000000000,
+ 0x2fee836200000000, 0x1185418d00000000, 0x123e766600000000,
+ 0x2c55b48900000000, 0x498f115f00000000, 0x77e4d3b000000000,
+ 0x745fe45b00000000, 0x4a3426b400000000, 0x332ffa5600000000,
+ 0x0d4438b900000000, 0x0eff0f5200000000, 0x3094cdbd00000000,
+ 0xbdcfc64c00000000, 0x83a404a300000000, 0x801f334800000000,
+ 0xbe74f1a700000000, 0xc76f2d4500000000, 0xf904efaa00000000,
+ 0xfabfd84100000000, 0xc4d41aae00000000, 0x710de23700000000,
+ 0x4f6620d800000000, 0x4cdd173300000000, 0x72b6d5dc00000000,
+ 0x0bad093e00000000, 0x35c6cbd100000000, 0x367dfc3a00000000,
+ 0x08163ed500000000, 0x854d352400000000, 0xbb26f7cb00000000,
+ 0xb89dc02000000000, 0x86f602cf00000000, 0xffedde2d00000000,
+ 0xc1861cc200000000, 0xc23d2b2900000000, 0xfc56e9c600000000,
+ 0x998c4c1000000000, 0xa7e78eff00000000, 0xa45cb91400000000,
+ 0x9a377bfb00000000, 0xe32ca71900000000, 0xdd4765f600000000,
+ 0xdefc521d00000000, 0xe09790f200000000, 0x6dcc9b0300000000,
+ 0x53a759ec00000000, 0x501c6e0700000000, 0x6e77ace800000000,
+ 0x176c700a00000000, 0x2907b2e500000000, 0x2abc850e00000000,
+ 0x14d747e100000000},
+ {0x0000000000000000, 0xc0df8ec100000000, 0xc1b96c5800000000,
+ 0x0166e29900000000, 0x8273d9b000000000, 0x42ac577100000000,
+ 0x43cab5e800000000, 0x83153b2900000000, 0x45e1c3ba00000000,
+ 0x853e4d7b00000000, 0x8458afe200000000, 0x4487212300000000,
+ 0xc7921a0a00000000, 0x074d94cb00000000, 0x062b765200000000,
+ 0xc6f4f89300000000, 0xcbc4f6ae00000000, 0x0b1b786f00000000,
+ 0x0a7d9af600000000, 0xcaa2143700000000, 0x49b72f1e00000000,
+ 0x8968a1df00000000, 0x880e434600000000, 0x48d1cd8700000000,
+ 0x8e25351400000000, 0x4efabbd500000000, 0x4f9c594c00000000,
+ 0x8f43d78d00000000, 0x0c56eca400000000, 0xcc89626500000000,
+ 0xcdef80fc00000000, 0x0d300e3d00000000, 0xd78f9c8600000000,
+ 0x1750124700000000, 0x1636f0de00000000, 0xd6e97e1f00000000,
+ 0x55fc453600000000, 0x9523cbf700000000, 0x9445296e00000000,
+ 0x549aa7af00000000, 0x926e5f3c00000000, 0x52b1d1fd00000000,
+ 0x53d7336400000000, 0x9308bda500000000, 0x101d868c00000000,
+ 0xd0c2084d00000000, 0xd1a4ead400000000, 0x117b641500000000,
+ 0x1c4b6a2800000000, 0xdc94e4e900000000, 0xddf2067000000000,
+ 0x1d2d88b100000000, 0x9e38b39800000000, 0x5ee73d5900000000,
+ 0x5f81dfc000000000, 0x9f5e510100000000, 0x59aaa99200000000,
+ 0x9975275300000000, 0x9813c5ca00000000, 0x58cc4b0b00000000,
+ 0xdbd9702200000000, 0x1b06fee300000000, 0x1a601c7a00000000,
+ 0xdabf92bb00000000, 0xef1948d600000000, 0x2fc6c61700000000,
+ 0x2ea0248e00000000, 0xee7faa4f00000000, 0x6d6a916600000000,
+ 0xadb51fa700000000, 0xacd3fd3e00000000, 0x6c0c73ff00000000,
+ 0xaaf88b6c00000000, 0x6a2705ad00000000, 0x6b41e73400000000,
+ 0xab9e69f500000000, 0x288b52dc00000000, 0xe854dc1d00000000,
+ 0xe9323e8400000000, 0x29edb04500000000, 0x24ddbe7800000000,
+ 0xe40230b900000000, 0xe564d22000000000, 0x25bb5ce100000000,
+ 0xa6ae67c800000000, 0x6671e90900000000, 0x67170b9000000000,
+ 0xa7c8855100000000, 0x613c7dc200000000, 0xa1e3f30300000000,
+ 0xa085119a00000000, 0x605a9f5b00000000, 0xe34fa47200000000,
+ 0x23902ab300000000, 0x22f6c82a00000000, 0xe22946eb00000000,
+ 0x3896d45000000000, 0xf8495a9100000000, 0xf92fb80800000000,
+ 0x39f036c900000000, 0xbae50de000000000, 0x7a3a832100000000,
+ 0x7b5c61b800000000, 0xbb83ef7900000000, 0x7d7717ea00000000,
+ 0xbda8992b00000000, 0xbcce7bb200000000, 0x7c11f57300000000,
+ 0xff04ce5a00000000, 0x3fdb409b00000000, 0x3ebda20200000000,
+ 0xfe622cc300000000, 0xf35222fe00000000, 0x338dac3f00000000,
+ 0x32eb4ea600000000, 0xf234c06700000000, 0x7121fb4e00000000,
+ 0xb1fe758f00000000, 0xb098971600000000, 0x704719d700000000,
+ 0xb6b3e14400000000, 0x766c6f8500000000, 0x770a8d1c00000000,
+ 0xb7d503dd00000000, 0x34c038f400000000, 0xf41fb63500000000,
+ 0xf57954ac00000000, 0x35a6da6d00000000, 0x9f35e17700000000,
+ 0x5fea6fb600000000, 0x5e8c8d2f00000000, 0x9e5303ee00000000,
+ 0x1d4638c700000000, 0xdd99b60600000000, 0xdcff549f00000000,
+ 0x1c20da5e00000000, 0xdad422cd00000000, 0x1a0bac0c00000000,
+ 0x1b6d4e9500000000, 0xdbb2c05400000000, 0x58a7fb7d00000000,
+ 0x987875bc00000000, 0x991e972500000000, 0x59c119e400000000,
+ 0x54f117d900000000, 0x942e991800000000, 0x95487b8100000000,
+ 0x5597f54000000000, 0xd682ce6900000000, 0x165d40a800000000,
+ 0x173ba23100000000, 0xd7e42cf000000000, 0x1110d46300000000,
+ 0xd1cf5aa200000000, 0xd0a9b83b00000000, 0x107636fa00000000,
+ 0x93630dd300000000, 0x53bc831200000000, 0x52da618b00000000,
+ 0x9205ef4a00000000, 0x48ba7df100000000, 0x8865f33000000000,
+ 0x890311a900000000, 0x49dc9f6800000000, 0xcac9a44100000000,
+ 0x0a162a8000000000, 0x0b70c81900000000, 0xcbaf46d800000000,
+ 0x0d5bbe4b00000000, 0xcd84308a00000000, 0xcce2d21300000000,
+ 0x0c3d5cd200000000, 0x8f2867fb00000000, 0x4ff7e93a00000000,
+ 0x4e910ba300000000, 0x8e4e856200000000, 0x837e8b5f00000000,
+ 0x43a1059e00000000, 0x42c7e70700000000, 0x821869c600000000,
+ 0x010d52ef00000000, 0xc1d2dc2e00000000, 0xc0b43eb700000000,
+ 0x006bb07600000000, 0xc69f48e500000000, 0x0640c62400000000,
+ 0x072624bd00000000, 0xc7f9aa7c00000000, 0x44ec915500000000,
+ 0x84331f9400000000, 0x8555fd0d00000000, 0x458a73cc00000000,
+ 0x702ca9a100000000, 0xb0f3276000000000, 0xb195c5f900000000,
+ 0x714a4b3800000000, 0xf25f701100000000, 0x3280fed000000000,
+ 0x33e61c4900000000, 0xf339928800000000, 0x35cd6a1b00000000,
+ 0xf512e4da00000000, 0xf474064300000000, 0x34ab888200000000,
+ 0xb7beb3ab00000000, 0x77613d6a00000000, 0x7607dff300000000,
+ 0xb6d8513200000000, 0xbbe85f0f00000000, 0x7b37d1ce00000000,
+ 0x7a51335700000000, 0xba8ebd9600000000, 0x399b86bf00000000,
+ 0xf944087e00000000, 0xf822eae700000000, 0x38fd642600000000,
+ 0xfe099cb500000000, 0x3ed6127400000000, 0x3fb0f0ed00000000,
+ 0xff6f7e2c00000000, 0x7c7a450500000000, 0xbca5cbc400000000,
+ 0xbdc3295d00000000, 0x7d1ca79c00000000, 0xa7a3352700000000,
+ 0x677cbbe600000000, 0x661a597f00000000, 0xa6c5d7be00000000,
+ 0x25d0ec9700000000, 0xe50f625600000000, 0xe46980cf00000000,
+ 0x24b60e0e00000000, 0xe242f69d00000000, 0x229d785c00000000,
+ 0x23fb9ac500000000, 0xe324140400000000, 0x60312f2d00000000,
+ 0xa0eea1ec00000000, 0xa188437500000000, 0x6157cdb400000000,
+ 0x6c67c38900000000, 0xacb84d4800000000, 0xaddeafd100000000,
+ 0x6d01211000000000, 0xee141a3900000000, 0x2ecb94f800000000,
+ 0x2fad766100000000, 0xef72f8a000000000, 0x2986003300000000,
+ 0xe9598ef200000000, 0xe83f6c6b00000000, 0x28e0e2aa00000000,
+ 0xabf5d98300000000, 0x6b2a574200000000, 0x6a4cb5db00000000,
+ 0xaa933b1a00000000},
+ {0x0000000000000000, 0x6f4ca59b00000000, 0x9f9e3bec00000000,
+ 0xf0d29e7700000000, 0x7f3b060300000000, 0x1077a39800000000,
+ 0xe0a53def00000000, 0x8fe9987400000000, 0xfe760c0600000000,
+ 0x913aa99d00000000, 0x61e837ea00000000, 0x0ea4927100000000,
+ 0x814d0a0500000000, 0xee01af9e00000000, 0x1ed331e900000000,
+ 0x719f947200000000, 0xfced180c00000000, 0x93a1bd9700000000,
+ 0x637323e000000000, 0x0c3f867b00000000, 0x83d61e0f00000000,
+ 0xec9abb9400000000, 0x1c4825e300000000, 0x7304807800000000,
+ 0x029b140a00000000, 0x6dd7b19100000000, 0x9d052fe600000000,
+ 0xf2498a7d00000000, 0x7da0120900000000, 0x12ecb79200000000,
+ 0xe23e29e500000000, 0x8d728c7e00000000, 0xf8db311800000000,
+ 0x9797948300000000, 0x67450af400000000, 0x0809af6f00000000,
+ 0x87e0371b00000000, 0xe8ac928000000000, 0x187e0cf700000000,
+ 0x7732a96c00000000, 0x06ad3d1e00000000, 0x69e1988500000000,
+ 0x993306f200000000, 0xf67fa36900000000, 0x79963b1d00000000,
+ 0x16da9e8600000000, 0xe60800f100000000, 0x8944a56a00000000,
+ 0x0436291400000000, 0x6b7a8c8f00000000, 0x9ba812f800000000,
+ 0xf4e4b76300000000, 0x7b0d2f1700000000, 0x14418a8c00000000,
+ 0xe49314fb00000000, 0x8bdfb16000000000, 0xfa40251200000000,
+ 0x950c808900000000, 0x65de1efe00000000, 0x0a92bb6500000000,
+ 0x857b231100000000, 0xea37868a00000000, 0x1ae518fd00000000,
+ 0x75a9bd6600000000, 0xf0b7633000000000, 0x9ffbc6ab00000000,
+ 0x6f2958dc00000000, 0x0065fd4700000000, 0x8f8c653300000000,
+ 0xe0c0c0a800000000, 0x10125edf00000000, 0x7f5efb4400000000,
+ 0x0ec16f3600000000, 0x618dcaad00000000, 0x915f54da00000000,
+ 0xfe13f14100000000, 0x71fa693500000000, 0x1eb6ccae00000000,
+ 0xee6452d900000000, 0x8128f74200000000, 0x0c5a7b3c00000000,
+ 0x6316dea700000000, 0x93c440d000000000, 0xfc88e54b00000000,
+ 0x73617d3f00000000, 0x1c2dd8a400000000, 0xecff46d300000000,
+ 0x83b3e34800000000, 0xf22c773a00000000, 0x9d60d2a100000000,
+ 0x6db24cd600000000, 0x02fee94d00000000, 0x8d17713900000000,
+ 0xe25bd4a200000000, 0x12894ad500000000, 0x7dc5ef4e00000000,
+ 0x086c522800000000, 0x6720f7b300000000, 0x97f269c400000000,
+ 0xf8becc5f00000000, 0x7757542b00000000, 0x181bf1b000000000,
+ 0xe8c96fc700000000, 0x8785ca5c00000000, 0xf61a5e2e00000000,
+ 0x9956fbb500000000, 0x698465c200000000, 0x06c8c05900000000,
+ 0x8921582d00000000, 0xe66dfdb600000000, 0x16bf63c100000000,
+ 0x79f3c65a00000000, 0xf4814a2400000000, 0x9bcdefbf00000000,
+ 0x6b1f71c800000000, 0x0453d45300000000, 0x8bba4c2700000000,
+ 0xe4f6e9bc00000000, 0x142477cb00000000, 0x7b68d25000000000,
+ 0x0af7462200000000, 0x65bbe3b900000000, 0x95697dce00000000,
+ 0xfa25d85500000000, 0x75cc402100000000, 0x1a80e5ba00000000,
+ 0xea527bcd00000000, 0x851ede5600000000, 0xe06fc76000000000,
+ 0x8f2362fb00000000, 0x7ff1fc8c00000000, 0x10bd591700000000,
+ 0x9f54c16300000000, 0xf01864f800000000, 0x00cafa8f00000000,
+ 0x6f865f1400000000, 0x1e19cb6600000000, 0x71556efd00000000,
+ 0x8187f08a00000000, 0xeecb551100000000, 0x6122cd6500000000,
+ 0x0e6e68fe00000000, 0xfebcf68900000000, 0x91f0531200000000,
+ 0x1c82df6c00000000, 0x73ce7af700000000, 0x831ce48000000000,
+ 0xec50411b00000000, 0x63b9d96f00000000, 0x0cf57cf400000000,
+ 0xfc27e28300000000, 0x936b471800000000, 0xe2f4d36a00000000,
+ 0x8db876f100000000, 0x7d6ae88600000000, 0x12264d1d00000000,
+ 0x9dcfd56900000000, 0xf28370f200000000, 0x0251ee8500000000,
+ 0x6d1d4b1e00000000, 0x18b4f67800000000, 0x77f853e300000000,
+ 0x872acd9400000000, 0xe866680f00000000, 0x678ff07b00000000,
+ 0x08c355e000000000, 0xf811cb9700000000, 0x975d6e0c00000000,
+ 0xe6c2fa7e00000000, 0x898e5fe500000000, 0x795cc19200000000,
+ 0x1610640900000000, 0x99f9fc7d00000000, 0xf6b559e600000000,
+ 0x0667c79100000000, 0x692b620a00000000, 0xe459ee7400000000,
+ 0x8b154bef00000000, 0x7bc7d59800000000, 0x148b700300000000,
+ 0x9b62e87700000000, 0xf42e4dec00000000, 0x04fcd39b00000000,
+ 0x6bb0760000000000, 0x1a2fe27200000000, 0x756347e900000000,
+ 0x85b1d99e00000000, 0xeafd7c0500000000, 0x6514e47100000000,
+ 0x0a5841ea00000000, 0xfa8adf9d00000000, 0x95c67a0600000000,
+ 0x10d8a45000000000, 0x7f9401cb00000000, 0x8f469fbc00000000,
+ 0xe00a3a2700000000, 0x6fe3a25300000000, 0x00af07c800000000,
+ 0xf07d99bf00000000, 0x9f313c2400000000, 0xeeaea85600000000,
+ 0x81e20dcd00000000, 0x713093ba00000000, 0x1e7c362100000000,
+ 0x9195ae5500000000, 0xfed90bce00000000, 0x0e0b95b900000000,
+ 0x6147302200000000, 0xec35bc5c00000000, 0x837919c700000000,
+ 0x73ab87b000000000, 0x1ce7222b00000000, 0x930eba5f00000000,
+ 0xfc421fc400000000, 0x0c9081b300000000, 0x63dc242800000000,
+ 0x1243b05a00000000, 0x7d0f15c100000000, 0x8ddd8bb600000000,
+ 0xe2912e2d00000000, 0x6d78b65900000000, 0x023413c200000000,
+ 0xf2e68db500000000, 0x9daa282e00000000, 0xe803954800000000,
+ 0x874f30d300000000, 0x779daea400000000, 0x18d10b3f00000000,
+ 0x9738934b00000000, 0xf87436d000000000, 0x08a6a8a700000000,
+ 0x67ea0d3c00000000, 0x1675994e00000000, 0x79393cd500000000,
+ 0x89eba2a200000000, 0xe6a7073900000000, 0x694e9f4d00000000,
+ 0x06023ad600000000, 0xf6d0a4a100000000, 0x999c013a00000000,
+ 0x14ee8d4400000000, 0x7ba228df00000000, 0x8b70b6a800000000,
+ 0xe43c133300000000, 0x6bd58b4700000000, 0x04992edc00000000,
+ 0xf44bb0ab00000000, 0x9b07153000000000, 0xea98814200000000,
+ 0x85d424d900000000, 0x7506baae00000000, 0x1a4a1f3500000000,
+ 0x95a3874100000000, 0xfaef22da00000000, 0x0a3dbcad00000000,
+ 0x6571193600000000},
+ {0x0000000000000000, 0x85d996dd00000000, 0x4bb55c6000000000,
+ 0xce6ccabd00000000, 0x966ab9c000000000, 0x13b32f1d00000000,
+ 0xdddfe5a000000000, 0x5806737d00000000, 0x6dd3035a00000000,
+ 0xe80a958700000000, 0x26665f3a00000000, 0xa3bfc9e700000000,
+ 0xfbb9ba9a00000000, 0x7e602c4700000000, 0xb00ce6fa00000000,
+ 0x35d5702700000000, 0xdaa607b400000000, 0x5f7f916900000000,
+ 0x91135bd400000000, 0x14cacd0900000000, 0x4cccbe7400000000,
+ 0xc91528a900000000, 0x0779e21400000000, 0x82a074c900000000,
+ 0xb77504ee00000000, 0x32ac923300000000, 0xfcc0588e00000000,
+ 0x7919ce5300000000, 0x211fbd2e00000000, 0xa4c62bf300000000,
+ 0x6aaae14e00000000, 0xef73779300000000, 0xf54b7eb300000000,
+ 0x7092e86e00000000, 0xbefe22d300000000, 0x3b27b40e00000000,
+ 0x6321c77300000000, 0xe6f851ae00000000, 0x28949b1300000000,
+ 0xad4d0dce00000000, 0x98987de900000000, 0x1d41eb3400000000,
+ 0xd32d218900000000, 0x56f4b75400000000, 0x0ef2c42900000000,
+ 0x8b2b52f400000000, 0x4547984900000000, 0xc09e0e9400000000,
+ 0x2fed790700000000, 0xaa34efda00000000, 0x6458256700000000,
+ 0xe181b3ba00000000, 0xb987c0c700000000, 0x3c5e561a00000000,
+ 0xf2329ca700000000, 0x77eb0a7a00000000, 0x423e7a5d00000000,
+ 0xc7e7ec8000000000, 0x098b263d00000000, 0x8c52b0e000000000,
+ 0xd454c39d00000000, 0x518d554000000000, 0x9fe19ffd00000000,
+ 0x1a38092000000000, 0xab918dbd00000000, 0x2e481b6000000000,
+ 0xe024d1dd00000000, 0x65fd470000000000, 0x3dfb347d00000000,
+ 0xb822a2a000000000, 0x764e681d00000000, 0xf397fec000000000,
+ 0xc6428ee700000000, 0x439b183a00000000, 0x8df7d28700000000,
+ 0x082e445a00000000, 0x5028372700000000, 0xd5f1a1fa00000000,
+ 0x1b9d6b4700000000, 0x9e44fd9a00000000, 0x71378a0900000000,
+ 0xf4ee1cd400000000, 0x3a82d66900000000, 0xbf5b40b400000000,
+ 0xe75d33c900000000, 0x6284a51400000000, 0xace86fa900000000,
+ 0x2931f97400000000, 0x1ce4895300000000, 0x993d1f8e00000000,
+ 0x5751d53300000000, 0xd28843ee00000000, 0x8a8e309300000000,
+ 0x0f57a64e00000000, 0xc13b6cf300000000, 0x44e2fa2e00000000,
+ 0x5edaf30e00000000, 0xdb0365d300000000, 0x156faf6e00000000,
+ 0x90b639b300000000, 0xc8b04ace00000000, 0x4d69dc1300000000,
+ 0x830516ae00000000, 0x06dc807300000000, 0x3309f05400000000,
+ 0xb6d0668900000000, 0x78bcac3400000000, 0xfd653ae900000000,
+ 0xa563499400000000, 0x20badf4900000000, 0xeed615f400000000,
+ 0x6b0f832900000000, 0x847cf4ba00000000, 0x01a5626700000000,
+ 0xcfc9a8da00000000, 0x4a103e0700000000, 0x12164d7a00000000,
+ 0x97cfdba700000000, 0x59a3111a00000000, 0xdc7a87c700000000,
+ 0xe9aff7e000000000, 0x6c76613d00000000, 0xa21aab8000000000,
+ 0x27c33d5d00000000, 0x7fc54e2000000000, 0xfa1cd8fd00000000,
+ 0x3470124000000000, 0xb1a9849d00000000, 0x17256aa000000000,
+ 0x92fcfc7d00000000, 0x5c9036c000000000, 0xd949a01d00000000,
+ 0x814fd36000000000, 0x049645bd00000000, 0xcafa8f0000000000,
+ 0x4f2319dd00000000, 0x7af669fa00000000, 0xff2fff2700000000,
+ 0x3143359a00000000, 0xb49aa34700000000, 0xec9cd03a00000000,
+ 0x694546e700000000, 0xa7298c5a00000000, 0x22f01a8700000000,
+ 0xcd836d1400000000, 0x485afbc900000000, 0x8636317400000000,
+ 0x03efa7a900000000, 0x5be9d4d400000000, 0xde30420900000000,
+ 0x105c88b400000000, 0x95851e6900000000, 0xa0506e4e00000000,
+ 0x2589f89300000000, 0xebe5322e00000000, 0x6e3ca4f300000000,
+ 0x363ad78e00000000, 0xb3e3415300000000, 0x7d8f8bee00000000,
+ 0xf8561d3300000000, 0xe26e141300000000, 0x67b782ce00000000,
+ 0xa9db487300000000, 0x2c02deae00000000, 0x7404add300000000,
+ 0xf1dd3b0e00000000, 0x3fb1f1b300000000, 0xba68676e00000000,
+ 0x8fbd174900000000, 0x0a64819400000000, 0xc4084b2900000000,
+ 0x41d1ddf400000000, 0x19d7ae8900000000, 0x9c0e385400000000,
+ 0x5262f2e900000000, 0xd7bb643400000000, 0x38c813a700000000,
+ 0xbd11857a00000000, 0x737d4fc700000000, 0xf6a4d91a00000000,
+ 0xaea2aa6700000000, 0x2b7b3cba00000000, 0xe517f60700000000,
+ 0x60ce60da00000000, 0x551b10fd00000000, 0xd0c2862000000000,
+ 0x1eae4c9d00000000, 0x9b77da4000000000, 0xc371a93d00000000,
+ 0x46a83fe000000000, 0x88c4f55d00000000, 0x0d1d638000000000,
+ 0xbcb4e71d00000000, 0x396d71c000000000, 0xf701bb7d00000000,
+ 0x72d82da000000000, 0x2ade5edd00000000, 0xaf07c80000000000,
+ 0x616b02bd00000000, 0xe4b2946000000000, 0xd167e44700000000,
+ 0x54be729a00000000, 0x9ad2b82700000000, 0x1f0b2efa00000000,
+ 0x470d5d8700000000, 0xc2d4cb5a00000000, 0x0cb801e700000000,
+ 0x8961973a00000000, 0x6612e0a900000000, 0xe3cb767400000000,
+ 0x2da7bcc900000000, 0xa87e2a1400000000, 0xf078596900000000,
+ 0x75a1cfb400000000, 0xbbcd050900000000, 0x3e1493d400000000,
+ 0x0bc1e3f300000000, 0x8e18752e00000000, 0x4074bf9300000000,
+ 0xc5ad294e00000000, 0x9dab5a3300000000, 0x1872ccee00000000,
+ 0xd61e065300000000, 0x53c7908e00000000, 0x49ff99ae00000000,
+ 0xcc260f7300000000, 0x024ac5ce00000000, 0x8793531300000000,
+ 0xdf95206e00000000, 0x5a4cb6b300000000, 0x94207c0e00000000,
+ 0x11f9ead300000000, 0x242c9af400000000, 0xa1f50c2900000000,
+ 0x6f99c69400000000, 0xea40504900000000, 0xb246233400000000,
+ 0x379fb5e900000000, 0xf9f37f5400000000, 0x7c2ae98900000000,
+ 0x93599e1a00000000, 0x168008c700000000, 0xd8ecc27a00000000,
+ 0x5d3554a700000000, 0x053327da00000000, 0x80eab10700000000,
+ 0x4e867bba00000000, 0xcb5fed6700000000, 0xfe8a9d4000000000,
+ 0x7b530b9d00000000, 0xb53fc12000000000, 0x30e657fd00000000,
+ 0x68e0248000000000, 0xed39b25d00000000, 0x235578e000000000,
+ 0xa68cee3d00000000},
+ {0x0000000000000000, 0x76e10f9d00000000, 0xadc46ee100000000,
+ 0xdb25617c00000000, 0x1b8fac1900000000, 0x6d6ea38400000000,
+ 0xb64bc2f800000000, 0xc0aacd6500000000, 0x361e593300000000,
+ 0x40ff56ae00000000, 0x9bda37d200000000, 0xed3b384f00000000,
+ 0x2d91f52a00000000, 0x5b70fab700000000, 0x80559bcb00000000,
+ 0xf6b4945600000000, 0x6c3cb26600000000, 0x1addbdfb00000000,
+ 0xc1f8dc8700000000, 0xb719d31a00000000, 0x77b31e7f00000000,
+ 0x015211e200000000, 0xda77709e00000000, 0xac967f0300000000,
+ 0x5a22eb5500000000, 0x2cc3e4c800000000, 0xf7e685b400000000,
+ 0x81078a2900000000, 0x41ad474c00000000, 0x374c48d100000000,
+ 0xec6929ad00000000, 0x9a88263000000000, 0xd87864cd00000000,
+ 0xae996b5000000000, 0x75bc0a2c00000000, 0x035d05b100000000,
+ 0xc3f7c8d400000000, 0xb516c74900000000, 0x6e33a63500000000,
+ 0x18d2a9a800000000, 0xee663dfe00000000, 0x9887326300000000,
+ 0x43a2531f00000000, 0x35435c8200000000, 0xf5e991e700000000,
+ 0x83089e7a00000000, 0x582dff0600000000, 0x2eccf09b00000000,
+ 0xb444d6ab00000000, 0xc2a5d93600000000, 0x1980b84a00000000,
+ 0x6f61b7d700000000, 0xafcb7ab200000000, 0xd92a752f00000000,
+ 0x020f145300000000, 0x74ee1bce00000000, 0x825a8f9800000000,
+ 0xf4bb800500000000, 0x2f9ee17900000000, 0x597feee400000000,
+ 0x99d5238100000000, 0xef342c1c00000000, 0x34114d6000000000,
+ 0x42f042fd00000000, 0xf1f7b94100000000, 0x8716b6dc00000000,
+ 0x5c33d7a000000000, 0x2ad2d83d00000000, 0xea78155800000000,
+ 0x9c991ac500000000, 0x47bc7bb900000000, 0x315d742400000000,
+ 0xc7e9e07200000000, 0xb108efef00000000, 0x6a2d8e9300000000,
+ 0x1ccc810e00000000, 0xdc664c6b00000000, 0xaa8743f600000000,
+ 0x71a2228a00000000, 0x07432d1700000000, 0x9dcb0b2700000000,
+ 0xeb2a04ba00000000, 0x300f65c600000000, 0x46ee6a5b00000000,
+ 0x8644a73e00000000, 0xf0a5a8a300000000, 0x2b80c9df00000000,
+ 0x5d61c64200000000, 0xabd5521400000000, 0xdd345d8900000000,
+ 0x06113cf500000000, 0x70f0336800000000, 0xb05afe0d00000000,
+ 0xc6bbf19000000000, 0x1d9e90ec00000000, 0x6b7f9f7100000000,
+ 0x298fdd8c00000000, 0x5f6ed21100000000, 0x844bb36d00000000,
+ 0xf2aabcf000000000, 0x3200719500000000, 0x44e17e0800000000,
+ 0x9fc41f7400000000, 0xe92510e900000000, 0x1f9184bf00000000,
+ 0x69708b2200000000, 0xb255ea5e00000000, 0xc4b4e5c300000000,
+ 0x041e28a600000000, 0x72ff273b00000000, 0xa9da464700000000,
+ 0xdf3b49da00000000, 0x45b36fea00000000, 0x3352607700000000,
+ 0xe877010b00000000, 0x9e960e9600000000, 0x5e3cc3f300000000,
+ 0x28ddcc6e00000000, 0xf3f8ad1200000000, 0x8519a28f00000000,
+ 0x73ad36d900000000, 0x054c394400000000, 0xde69583800000000,
+ 0xa88857a500000000, 0x68229ac000000000, 0x1ec3955d00000000,
+ 0xc5e6f42100000000, 0xb307fbbc00000000, 0xe2ef738300000000,
+ 0x940e7c1e00000000, 0x4f2b1d6200000000, 0x39ca12ff00000000,
+ 0xf960df9a00000000, 0x8f81d00700000000, 0x54a4b17b00000000,
+ 0x2245bee600000000, 0xd4f12ab000000000, 0xa210252d00000000,
+ 0x7935445100000000, 0x0fd44bcc00000000, 0xcf7e86a900000000,
+ 0xb99f893400000000, 0x62bae84800000000, 0x145be7d500000000,
+ 0x8ed3c1e500000000, 0xf832ce7800000000, 0x2317af0400000000,
+ 0x55f6a09900000000, 0x955c6dfc00000000, 0xe3bd626100000000,
+ 0x3898031d00000000, 0x4e790c8000000000, 0xb8cd98d600000000,
+ 0xce2c974b00000000, 0x1509f63700000000, 0x63e8f9aa00000000,
+ 0xa34234cf00000000, 0xd5a33b5200000000, 0x0e865a2e00000000,
+ 0x786755b300000000, 0x3a97174e00000000, 0x4c7618d300000000,
+ 0x975379af00000000, 0xe1b2763200000000, 0x2118bb5700000000,
+ 0x57f9b4ca00000000, 0x8cdcd5b600000000, 0xfa3dda2b00000000,
+ 0x0c894e7d00000000, 0x7a6841e000000000, 0xa14d209c00000000,
+ 0xd7ac2f0100000000, 0x1706e26400000000, 0x61e7edf900000000,
+ 0xbac28c8500000000, 0xcc23831800000000, 0x56aba52800000000,
+ 0x204aaab500000000, 0xfb6fcbc900000000, 0x8d8ec45400000000,
+ 0x4d24093100000000, 0x3bc506ac00000000, 0xe0e067d000000000,
+ 0x9601684d00000000, 0x60b5fc1b00000000, 0x1654f38600000000,
+ 0xcd7192fa00000000, 0xbb909d6700000000, 0x7b3a500200000000,
+ 0x0ddb5f9f00000000, 0xd6fe3ee300000000, 0xa01f317e00000000,
+ 0x1318cac200000000, 0x65f9c55f00000000, 0xbedca42300000000,
+ 0xc83dabbe00000000, 0x089766db00000000, 0x7e76694600000000,
+ 0xa553083a00000000, 0xd3b207a700000000, 0x250693f100000000,
+ 0x53e79c6c00000000, 0x88c2fd1000000000, 0xfe23f28d00000000,
+ 0x3e893fe800000000, 0x4868307500000000, 0x934d510900000000,
+ 0xe5ac5e9400000000, 0x7f2478a400000000, 0x09c5773900000000,
+ 0xd2e0164500000000, 0xa40119d800000000, 0x64abd4bd00000000,
+ 0x124adb2000000000, 0xc96fba5c00000000, 0xbf8eb5c100000000,
+ 0x493a219700000000, 0x3fdb2e0a00000000, 0xe4fe4f7600000000,
+ 0x921f40eb00000000, 0x52b58d8e00000000, 0x2454821300000000,
+ 0xff71e36f00000000, 0x8990ecf200000000, 0xcb60ae0f00000000,
+ 0xbd81a19200000000, 0x66a4c0ee00000000, 0x1045cf7300000000,
+ 0xd0ef021600000000, 0xa60e0d8b00000000, 0x7d2b6cf700000000,
+ 0x0bca636a00000000, 0xfd7ef73c00000000, 0x8b9ff8a100000000,
+ 0x50ba99dd00000000, 0x265b964000000000, 0xe6f15b2500000000,
+ 0x901054b800000000, 0x4b3535c400000000, 0x3dd43a5900000000,
+ 0xa75c1c6900000000, 0xd1bd13f400000000, 0x0a98728800000000,
+ 0x7c797d1500000000, 0xbcd3b07000000000, 0xca32bfed00000000,
+ 0x1117de9100000000, 0x67f6d10c00000000, 0x9142455a00000000,
+ 0xe7a34ac700000000, 0x3c862bbb00000000, 0x4a67242600000000,
+ 0x8acde94300000000, 0xfc2ce6de00000000, 0x270987a200000000,
+ 0x51e8883f00000000},
+ {0x0000000000000000, 0xe8dbfbb900000000, 0x91b186a800000000,
+ 0x796a7d1100000000, 0x63657c8a00000000, 0x8bbe873300000000,
+ 0xf2d4fa2200000000, 0x1a0f019b00000000, 0x87cc89cf00000000,
+ 0x6f17727600000000, 0x167d0f6700000000, 0xfea6f4de00000000,
+ 0xe4a9f54500000000, 0x0c720efc00000000, 0x751873ed00000000,
+ 0x9dc3885400000000, 0x4f9f624400000000, 0xa74499fd00000000,
+ 0xde2ee4ec00000000, 0x36f51f5500000000, 0x2cfa1ece00000000,
+ 0xc421e57700000000, 0xbd4b986600000000, 0x559063df00000000,
+ 0xc853eb8b00000000, 0x2088103200000000, 0x59e26d2300000000,
+ 0xb139969a00000000, 0xab36970100000000, 0x43ed6cb800000000,
+ 0x3a8711a900000000, 0xd25cea1000000000, 0x9e3ec58800000000,
+ 0x76e53e3100000000, 0x0f8f432000000000, 0xe754b89900000000,
+ 0xfd5bb90200000000, 0x158042bb00000000, 0x6cea3faa00000000,
+ 0x8431c41300000000, 0x19f24c4700000000, 0xf129b7fe00000000,
+ 0x8843caef00000000, 0x6098315600000000, 0x7a9730cd00000000,
+ 0x924ccb7400000000, 0xeb26b66500000000, 0x03fd4ddc00000000,
+ 0xd1a1a7cc00000000, 0x397a5c7500000000, 0x4010216400000000,
+ 0xa8cbdadd00000000, 0xb2c4db4600000000, 0x5a1f20ff00000000,
+ 0x23755dee00000000, 0xcbaea65700000000, 0x566d2e0300000000,
+ 0xbeb6d5ba00000000, 0xc7dca8ab00000000, 0x2f07531200000000,
+ 0x3508528900000000, 0xddd3a93000000000, 0xa4b9d42100000000,
+ 0x4c622f9800000000, 0x7d7bfbca00000000, 0x95a0007300000000,
+ 0xecca7d6200000000, 0x041186db00000000, 0x1e1e874000000000,
+ 0xf6c57cf900000000, 0x8faf01e800000000, 0x6774fa5100000000,
+ 0xfab7720500000000, 0x126c89bc00000000, 0x6b06f4ad00000000,
+ 0x83dd0f1400000000, 0x99d20e8f00000000, 0x7109f53600000000,
+ 0x0863882700000000, 0xe0b8739e00000000, 0x32e4998e00000000,
+ 0xda3f623700000000, 0xa3551f2600000000, 0x4b8ee49f00000000,
+ 0x5181e50400000000, 0xb95a1ebd00000000, 0xc03063ac00000000,
+ 0x28eb981500000000, 0xb528104100000000, 0x5df3ebf800000000,
+ 0x249996e900000000, 0xcc426d5000000000, 0xd64d6ccb00000000,
+ 0x3e96977200000000, 0x47fcea6300000000, 0xaf2711da00000000,
+ 0xe3453e4200000000, 0x0b9ec5fb00000000, 0x72f4b8ea00000000,
+ 0x9a2f435300000000, 0x802042c800000000, 0x68fbb97100000000,
+ 0x1191c46000000000, 0xf94a3fd900000000, 0x6489b78d00000000,
+ 0x8c524c3400000000, 0xf538312500000000, 0x1de3ca9c00000000,
+ 0x07eccb0700000000, 0xef3730be00000000, 0x965d4daf00000000,
+ 0x7e86b61600000000, 0xacda5c0600000000, 0x4401a7bf00000000,
+ 0x3d6bdaae00000000, 0xd5b0211700000000, 0xcfbf208c00000000,
+ 0x2764db3500000000, 0x5e0ea62400000000, 0xb6d55d9d00000000,
+ 0x2b16d5c900000000, 0xc3cd2e7000000000, 0xbaa7536100000000,
+ 0x527ca8d800000000, 0x4873a94300000000, 0xa0a852fa00000000,
+ 0xd9c22feb00000000, 0x3119d45200000000, 0xbbf0874e00000000,
+ 0x532b7cf700000000, 0x2a4101e600000000, 0xc29afa5f00000000,
+ 0xd895fbc400000000, 0x304e007d00000000, 0x49247d6c00000000,
+ 0xa1ff86d500000000, 0x3c3c0e8100000000, 0xd4e7f53800000000,
+ 0xad8d882900000000, 0x4556739000000000, 0x5f59720b00000000,
+ 0xb78289b200000000, 0xcee8f4a300000000, 0x26330f1a00000000,
+ 0xf46fe50a00000000, 0x1cb41eb300000000, 0x65de63a200000000,
+ 0x8d05981b00000000, 0x970a998000000000, 0x7fd1623900000000,
+ 0x06bb1f2800000000, 0xee60e49100000000, 0x73a36cc500000000,
+ 0x9b78977c00000000, 0xe212ea6d00000000, 0x0ac911d400000000,
+ 0x10c6104f00000000, 0xf81debf600000000, 0x817796e700000000,
+ 0x69ac6d5e00000000, 0x25ce42c600000000, 0xcd15b97f00000000,
+ 0xb47fc46e00000000, 0x5ca43fd700000000, 0x46ab3e4c00000000,
+ 0xae70c5f500000000, 0xd71ab8e400000000, 0x3fc1435d00000000,
+ 0xa202cb0900000000, 0x4ad930b000000000, 0x33b34da100000000,
+ 0xdb68b61800000000, 0xc167b78300000000, 0x29bc4c3a00000000,
+ 0x50d6312b00000000, 0xb80dca9200000000, 0x6a51208200000000,
+ 0x828adb3b00000000, 0xfbe0a62a00000000, 0x133b5d9300000000,
+ 0x09345c0800000000, 0xe1efa7b100000000, 0x9885daa000000000,
+ 0x705e211900000000, 0xed9da94d00000000, 0x054652f400000000,
+ 0x7c2c2fe500000000, 0x94f7d45c00000000, 0x8ef8d5c700000000,
+ 0x66232e7e00000000, 0x1f49536f00000000, 0xf792a8d600000000,
+ 0xc68b7c8400000000, 0x2e50873d00000000, 0x573afa2c00000000,
+ 0xbfe1019500000000, 0xa5ee000e00000000, 0x4d35fbb700000000,
+ 0x345f86a600000000, 0xdc847d1f00000000, 0x4147f54b00000000,
+ 0xa99c0ef200000000, 0xd0f673e300000000, 0x382d885a00000000,
+ 0x222289c100000000, 0xcaf9727800000000, 0xb3930f6900000000,
+ 0x5b48f4d000000000, 0x89141ec000000000, 0x61cfe57900000000,
+ 0x18a5986800000000, 0xf07e63d100000000, 0xea71624a00000000,
+ 0x02aa99f300000000, 0x7bc0e4e200000000, 0x931b1f5b00000000,
+ 0x0ed8970f00000000, 0xe6036cb600000000, 0x9f6911a700000000,
+ 0x77b2ea1e00000000, 0x6dbdeb8500000000, 0x8566103c00000000,
+ 0xfc0c6d2d00000000, 0x14d7969400000000, 0x58b5b90c00000000,
+ 0xb06e42b500000000, 0xc9043fa400000000, 0x21dfc41d00000000,
+ 0x3bd0c58600000000, 0xd30b3e3f00000000, 0xaa61432e00000000,
+ 0x42bab89700000000, 0xdf7930c300000000, 0x37a2cb7a00000000,
+ 0x4ec8b66b00000000, 0xa6134dd200000000, 0xbc1c4c4900000000,
+ 0x54c7b7f000000000, 0x2dadcae100000000, 0xc576315800000000,
+ 0x172adb4800000000, 0xfff120f100000000, 0x869b5de000000000,
+ 0x6e40a65900000000, 0x744fa7c200000000, 0x9c945c7b00000000,
+ 0xe5fe216a00000000, 0x0d25dad300000000, 0x90e6528700000000,
+ 0x783da93e00000000, 0x0157d42f00000000, 0xe98c2f9600000000,
+ 0xf3832e0d00000000, 0x1b58d5b400000000, 0x6232a8a500000000,
+ 0x8ae9531c00000000},
+ {0x0000000000000000, 0x919168ae00000000, 0x6325a08700000000,
+ 0xf2b4c82900000000, 0x874c31d400000000, 0x16dd597a00000000,
+ 0xe469915300000000, 0x75f8f9fd00000000, 0x4f9f137300000000,
+ 0xde0e7bdd00000000, 0x2cbab3f400000000, 0xbd2bdb5a00000000,
+ 0xc8d322a700000000, 0x59424a0900000000, 0xabf6822000000000,
+ 0x3a67ea8e00000000, 0x9e3e27e600000000, 0x0faf4f4800000000,
+ 0xfd1b876100000000, 0x6c8aefcf00000000, 0x1972163200000000,
+ 0x88e37e9c00000000, 0x7a57b6b500000000, 0xebc6de1b00000000,
+ 0xd1a1349500000000, 0x40305c3b00000000, 0xb284941200000000,
+ 0x2315fcbc00000000, 0x56ed054100000000, 0xc77c6def00000000,
+ 0x35c8a5c600000000, 0xa459cd6800000000, 0x7d7b3f1700000000,
+ 0xecea57b900000000, 0x1e5e9f9000000000, 0x8fcff73e00000000,
+ 0xfa370ec300000000, 0x6ba6666d00000000, 0x9912ae4400000000,
+ 0x0883c6ea00000000, 0x32e42c6400000000, 0xa37544ca00000000,
+ 0x51c18ce300000000, 0xc050e44d00000000, 0xb5a81db000000000,
+ 0x2439751e00000000, 0xd68dbd3700000000, 0x471cd59900000000,
+ 0xe34518f100000000, 0x72d4705f00000000, 0x8060b87600000000,
+ 0x11f1d0d800000000, 0x6409292500000000, 0xf598418b00000000,
+ 0x072c89a200000000, 0x96bde10c00000000, 0xacda0b8200000000,
+ 0x3d4b632c00000000, 0xcfffab0500000000, 0x5e6ec3ab00000000,
+ 0x2b963a5600000000, 0xba0752f800000000, 0x48b39ad100000000,
+ 0xd922f27f00000000, 0xfaf67e2e00000000, 0x6b67168000000000,
+ 0x99d3dea900000000, 0x0842b60700000000, 0x7dba4ffa00000000,
+ 0xec2b275400000000, 0x1e9fef7d00000000, 0x8f0e87d300000000,
+ 0xb5696d5d00000000, 0x24f805f300000000, 0xd64ccdda00000000,
+ 0x47dda57400000000, 0x32255c8900000000, 0xa3b4342700000000,
+ 0x5100fc0e00000000, 0xc09194a000000000, 0x64c859c800000000,
+ 0xf559316600000000, 0x07edf94f00000000, 0x967c91e100000000,
+ 0xe384681c00000000, 0x721500b200000000, 0x80a1c89b00000000,
+ 0x1130a03500000000, 0x2b574abb00000000, 0xbac6221500000000,
+ 0x4872ea3c00000000, 0xd9e3829200000000, 0xac1b7b6f00000000,
+ 0x3d8a13c100000000, 0xcf3edbe800000000, 0x5eafb34600000000,
+ 0x878d413900000000, 0x161c299700000000, 0xe4a8e1be00000000,
+ 0x7539891000000000, 0x00c170ed00000000, 0x9150184300000000,
+ 0x63e4d06a00000000, 0xf275b8c400000000, 0xc812524a00000000,
+ 0x59833ae400000000, 0xab37f2cd00000000, 0x3aa69a6300000000,
+ 0x4f5e639e00000000, 0xdecf0b3000000000, 0x2c7bc31900000000,
+ 0xbdeaabb700000000, 0x19b366df00000000, 0x88220e7100000000,
+ 0x7a96c65800000000, 0xeb07aef600000000, 0x9eff570b00000000,
+ 0x0f6e3fa500000000, 0xfddaf78c00000000, 0x6c4b9f2200000000,
+ 0x562c75ac00000000, 0xc7bd1d0200000000, 0x3509d52b00000000,
+ 0xa498bd8500000000, 0xd160447800000000, 0x40f12cd600000000,
+ 0xb245e4ff00000000, 0x23d48c5100000000, 0xf4edfd5c00000000,
+ 0x657c95f200000000, 0x97c85ddb00000000, 0x0659357500000000,
+ 0x73a1cc8800000000, 0xe230a42600000000, 0x10846c0f00000000,
+ 0x811504a100000000, 0xbb72ee2f00000000, 0x2ae3868100000000,
+ 0xd8574ea800000000, 0x49c6260600000000, 0x3c3edffb00000000,
+ 0xadafb75500000000, 0x5f1b7f7c00000000, 0xce8a17d200000000,
+ 0x6ad3daba00000000, 0xfb42b21400000000, 0x09f67a3d00000000,
+ 0x9867129300000000, 0xed9feb6e00000000, 0x7c0e83c000000000,
+ 0x8eba4be900000000, 0x1f2b234700000000, 0x254cc9c900000000,
+ 0xb4dda16700000000, 0x4669694e00000000, 0xd7f801e000000000,
+ 0xa200f81d00000000, 0x339190b300000000, 0xc125589a00000000,
+ 0x50b4303400000000, 0x8996c24b00000000, 0x1807aae500000000,
+ 0xeab362cc00000000, 0x7b220a6200000000, 0x0edaf39f00000000,
+ 0x9f4b9b3100000000, 0x6dff531800000000, 0xfc6e3bb600000000,
+ 0xc609d13800000000, 0x5798b99600000000, 0xa52c71bf00000000,
+ 0x34bd191100000000, 0x4145e0ec00000000, 0xd0d4884200000000,
+ 0x2260406b00000000, 0xb3f128c500000000, 0x17a8e5ad00000000,
+ 0x86398d0300000000, 0x748d452a00000000, 0xe51c2d8400000000,
+ 0x90e4d47900000000, 0x0175bcd700000000, 0xf3c174fe00000000,
+ 0x62501c5000000000, 0x5837f6de00000000, 0xc9a69e7000000000,
+ 0x3b12565900000000, 0xaa833ef700000000, 0xdf7bc70a00000000,
+ 0x4eeaafa400000000, 0xbc5e678d00000000, 0x2dcf0f2300000000,
+ 0x0e1b837200000000, 0x9f8aebdc00000000, 0x6d3e23f500000000,
+ 0xfcaf4b5b00000000, 0x8957b2a600000000, 0x18c6da0800000000,
+ 0xea72122100000000, 0x7be37a8f00000000, 0x4184900100000000,
+ 0xd015f8af00000000, 0x22a1308600000000, 0xb330582800000000,
+ 0xc6c8a1d500000000, 0x5759c97b00000000, 0xa5ed015200000000,
+ 0x347c69fc00000000, 0x9025a49400000000, 0x01b4cc3a00000000,
+ 0xf300041300000000, 0x62916cbd00000000, 0x1769954000000000,
+ 0x86f8fdee00000000, 0x744c35c700000000, 0xe5dd5d6900000000,
+ 0xdfbab7e700000000, 0x4e2bdf4900000000, 0xbc9f176000000000,
+ 0x2d0e7fce00000000, 0x58f6863300000000, 0xc967ee9d00000000,
+ 0x3bd326b400000000, 0xaa424e1a00000000, 0x7360bc6500000000,
+ 0xe2f1d4cb00000000, 0x10451ce200000000, 0x81d4744c00000000,
+ 0xf42c8db100000000, 0x65bde51f00000000, 0x97092d3600000000,
+ 0x0698459800000000, 0x3cffaf1600000000, 0xad6ec7b800000000,
+ 0x5fda0f9100000000, 0xce4b673f00000000, 0xbbb39ec200000000,
+ 0x2a22f66c00000000, 0xd8963e4500000000, 0x490756eb00000000,
+ 0xed5e9b8300000000, 0x7ccff32d00000000, 0x8e7b3b0400000000,
+ 0x1fea53aa00000000, 0x6a12aa5700000000, 0xfb83c2f900000000,
+ 0x09370ad000000000, 0x98a6627e00000000, 0xa2c188f000000000,
+ 0x3350e05e00000000, 0xc1e4287700000000, 0x507540d900000000,
+ 0x258db92400000000, 0xb41cd18a00000000, 0x46a819a300000000,
+ 0xd739710d00000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa,
+ 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b,
+ 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232,
+ 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8,
+ 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e,
+ 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa,
+ 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b,
+ 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f,
+ 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719,
+ 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3,
+ 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa,
+ 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b,
+ 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed,
+ 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89,
+ 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25,
+ 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041,
+ 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c,
+ 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed,
+ 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4,
+ 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758,
+ 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e,
+ 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a,
+ 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed,
+ 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889,
+ 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df,
+ 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544,
+ 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d,
+ 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c,
+ 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1,
+ 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95,
+ 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839,
+ 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d,
+ 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976,
+ 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7,
+ 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be,
+ 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144,
+ 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12,
+ 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376,
+ 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a,
+ 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e,
+ 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278,
+ 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682,
+ 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b,
+ 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a,
+ 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561,
+ 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05,
+ 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9,
+ 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd,
+ 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0,
+ 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61,
+ 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678,
+ 0x264b06e6},
+ {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413,
+ 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3,
+ 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d,
+ 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653,
+ 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9,
+ 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e,
+ 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5,
+ 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712,
+ 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8,
+ 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6,
+ 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068,
+ 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8,
+ 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579,
+ 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade,
+ 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37,
+ 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590,
+ 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4,
+ 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64,
+ 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea,
+ 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678,
+ 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282,
+ 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25,
+ 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102,
+ 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5,
+ 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f,
+ 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146,
+ 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8,
+ 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08,
+ 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c,
+ 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b,
+ 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972,
+ 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5,
+ 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d,
+ 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd,
+ 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833,
+ 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d,
+ 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7,
+ 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60,
+ 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2,
+ 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105,
+ 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff,
+ 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1,
+ 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f,
+ 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf,
+ 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617,
+ 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0,
+ 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959,
+ 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe,
+ 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca,
+ 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a,
+ 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184,
+ 0x92364a30},
+ {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216,
+ 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8,
+ 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170,
+ 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035,
+ 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6,
+ 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145,
+ 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d,
+ 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e,
+ 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d,
+ 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408,
+ 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0,
+ 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e,
+ 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c,
+ 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf,
+ 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a,
+ 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9,
+ 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1,
+ 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f,
+ 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987,
+ 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4,
+ 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37,
+ 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84,
+ 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca,
+ 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79,
+ 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba,
+ 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d,
+ 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5,
+ 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b,
+ 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643,
+ 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0,
+ 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525,
+ 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496,
+ 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8,
+ 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026,
+ 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e,
+ 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db,
+ 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118,
+ 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab,
+ 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf,
+ 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c,
+ 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf,
+ 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a,
+ 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32,
+ 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec,
+ 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82,
+ 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31,
+ 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4,
+ 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957,
+ 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f,
+ 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1,
+ 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869,
+ 0xe4c4abcc},
+ {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0,
+ 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271,
+ 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61,
+ 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52,
+ 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43,
+ 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333,
+ 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64,
+ 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314,
+ 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205,
+ 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136,
+ 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26,
+ 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997,
+ 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849,
+ 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739,
+ 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8,
+ 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98,
+ 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b,
+ 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba,
+ 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa,
+ 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d,
+ 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c,
+ 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc,
+ 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af,
+ 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf,
+ 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce,
+ 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922,
+ 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532,
+ 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183,
+ 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710,
+ 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860,
+ 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1,
+ 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1,
+ 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956,
+ 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7,
+ 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7,
+ 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4,
+ 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5,
+ 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5,
+ 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb,
+ 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb,
+ 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da,
+ 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9,
+ 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9,
+ 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48,
+ 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df,
+ 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af,
+ 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e,
+ 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e,
+ 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d,
+ 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c,
+ 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c,
+ 0xca64c78c}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0xb029603d, 0x6053c07a, 0xd07aa047, 0xc0a680f5,
+ 0x708fe0c8, 0xa0f5408f, 0x10dc20b2, 0xc14b7030, 0x7162100d,
+ 0xa118b04a, 0x1131d077, 0x01edf0c5, 0xb1c490f8, 0x61be30bf,
+ 0xd1975082, 0x8297e060, 0x32be805d, 0xe2c4201a, 0x52ed4027,
+ 0x42316095, 0xf21800a8, 0x2262a0ef, 0x924bc0d2, 0x43dc9050,
+ 0xf3f5f06d, 0x238f502a, 0x93a63017, 0x837a10a5, 0x33537098,
+ 0xe329d0df, 0x5300b0e2, 0x042fc1c1, 0xb406a1fc, 0x647c01bb,
+ 0xd4556186, 0xc4894134, 0x74a02109, 0xa4da814e, 0x14f3e173,
+ 0xc564b1f1, 0x754dd1cc, 0xa537718b, 0x151e11b6, 0x05c23104,
+ 0xb5eb5139, 0x6591f17e, 0xd5b89143, 0x86b821a1, 0x3691419c,
+ 0xe6ebe1db, 0x56c281e6, 0x461ea154, 0xf637c169, 0x264d612e,
+ 0x96640113, 0x47f35191, 0xf7da31ac, 0x27a091eb, 0x9789f1d6,
+ 0x8755d164, 0x377cb159, 0xe706111e, 0x572f7123, 0x4958f358,
+ 0xf9719365, 0x290b3322, 0x9922531f, 0x89fe73ad, 0x39d71390,
+ 0xe9adb3d7, 0x5984d3ea, 0x88138368, 0x383ae355, 0xe8404312,
+ 0x5869232f, 0x48b5039d, 0xf89c63a0, 0x28e6c3e7, 0x98cfa3da,
+ 0xcbcf1338, 0x7be67305, 0xab9cd342, 0x1bb5b37f, 0x0b6993cd,
+ 0xbb40f3f0, 0x6b3a53b7, 0xdb13338a, 0x0a846308, 0xbaad0335,
+ 0x6ad7a372, 0xdafec34f, 0xca22e3fd, 0x7a0b83c0, 0xaa712387,
+ 0x1a5843ba, 0x4d773299, 0xfd5e52a4, 0x2d24f2e3, 0x9d0d92de,
+ 0x8dd1b26c, 0x3df8d251, 0xed827216, 0x5dab122b, 0x8c3c42a9,
+ 0x3c152294, 0xec6f82d3, 0x5c46e2ee, 0x4c9ac25c, 0xfcb3a261,
+ 0x2cc90226, 0x9ce0621b, 0xcfe0d2f9, 0x7fc9b2c4, 0xafb31283,
+ 0x1f9a72be, 0x0f46520c, 0xbf6f3231, 0x6f159276, 0xdf3cf24b,
+ 0x0eaba2c9, 0xbe82c2f4, 0x6ef862b3, 0xded1028e, 0xce0d223c,
+ 0x7e244201, 0xae5ee246, 0x1e77827b, 0x92b0e6b1, 0x2299868c,
+ 0xf2e326cb, 0x42ca46f6, 0x52166644, 0xe23f0679, 0x3245a63e,
+ 0x826cc603, 0x53fb9681, 0xe3d2f6bc, 0x33a856fb, 0x838136c6,
+ 0x935d1674, 0x23747649, 0xf30ed60e, 0x4327b633, 0x102706d1,
+ 0xa00e66ec, 0x7074c6ab, 0xc05da696, 0xd0818624, 0x60a8e619,
+ 0xb0d2465e, 0x00fb2663, 0xd16c76e1, 0x614516dc, 0xb13fb69b,
+ 0x0116d6a6, 0x11caf614, 0xa1e39629, 0x7199366e, 0xc1b05653,
+ 0x969f2770, 0x26b6474d, 0xf6cce70a, 0x46e58737, 0x5639a785,
+ 0xe610c7b8, 0x366a67ff, 0x864307c2, 0x57d45740, 0xe7fd377d,
+ 0x3787973a, 0x87aef707, 0x9772d7b5, 0x275bb788, 0xf72117cf,
+ 0x470877f2, 0x1408c710, 0xa421a72d, 0x745b076a, 0xc4726757,
+ 0xd4ae47e5, 0x648727d8, 0xb4fd879f, 0x04d4e7a2, 0xd543b720,
+ 0x656ad71d, 0xb510775a, 0x05391767, 0x15e537d5, 0xa5cc57e8,
+ 0x75b6f7af, 0xc59f9792, 0xdbe815e9, 0x6bc175d4, 0xbbbbd593,
+ 0x0b92b5ae, 0x1b4e951c, 0xab67f521, 0x7b1d5566, 0xcb34355b,
+ 0x1aa365d9, 0xaa8a05e4, 0x7af0a5a3, 0xcad9c59e, 0xda05e52c,
+ 0x6a2c8511, 0xba562556, 0x0a7f456b, 0x597ff589, 0xe95695b4,
+ 0x392c35f3, 0x890555ce, 0x99d9757c, 0x29f01541, 0xf98ab506,
+ 0x49a3d53b, 0x983485b9, 0x281de584, 0xf86745c3, 0x484e25fe,
+ 0x5892054c, 0xe8bb6571, 0x38c1c536, 0x88e8a50b, 0xdfc7d428,
+ 0x6feeb415, 0xbf941452, 0x0fbd746f, 0x1f6154dd, 0xaf4834e0,
+ 0x7f3294a7, 0xcf1bf49a, 0x1e8ca418, 0xaea5c425, 0x7edf6462,
+ 0xcef6045f, 0xde2a24ed, 0x6e0344d0, 0xbe79e497, 0x0e5084aa,
+ 0x5d503448, 0xed795475, 0x3d03f432, 0x8d2a940f, 0x9df6b4bd,
+ 0x2ddfd480, 0xfda574c7, 0x4d8c14fa, 0x9c1b4478, 0x2c322445,
+ 0xfc488402, 0x4c61e43f, 0x5cbdc48d, 0xec94a4b0, 0x3cee04f7,
+ 0x8cc764ca},
+ {0x00000000, 0xa5d35ccb, 0x0ba1c84d, 0xae729486, 0x1642919b,
+ 0xb391cd50, 0x1de359d6, 0xb830051d, 0x6d8253ec, 0xc8510f27,
+ 0x66239ba1, 0xc3f0c76a, 0x7bc0c277, 0xde139ebc, 0x70610a3a,
+ 0xd5b256f1, 0x9b02d603, 0x3ed18ac8, 0x90a31e4e, 0x35704285,
+ 0x8d404798, 0x28931b53, 0x86e18fd5, 0x2332d31e, 0xf68085ef,
+ 0x5353d924, 0xfd214da2, 0x58f21169, 0xe0c21474, 0x451148bf,
+ 0xeb63dc39, 0x4eb080f2, 0x3605ac07, 0x93d6f0cc, 0x3da4644a,
+ 0x98773881, 0x20473d9c, 0x85946157, 0x2be6f5d1, 0x8e35a91a,
+ 0x5b87ffeb, 0xfe54a320, 0x502637a6, 0xf5f56b6d, 0x4dc56e70,
+ 0xe81632bb, 0x4664a63d, 0xe3b7faf6, 0xad077a04, 0x08d426cf,
+ 0xa6a6b249, 0x0375ee82, 0xbb45eb9f, 0x1e96b754, 0xb0e423d2,
+ 0x15377f19, 0xc08529e8, 0x65567523, 0xcb24e1a5, 0x6ef7bd6e,
+ 0xd6c7b873, 0x7314e4b8, 0xdd66703e, 0x78b52cf5, 0x6c0a580f,
+ 0xc9d904c4, 0x67ab9042, 0xc278cc89, 0x7a48c994, 0xdf9b955f,
+ 0x71e901d9, 0xd43a5d12, 0x01880be3, 0xa45b5728, 0x0a29c3ae,
+ 0xaffa9f65, 0x17ca9a78, 0xb219c6b3, 0x1c6b5235, 0xb9b80efe,
+ 0xf7088e0c, 0x52dbd2c7, 0xfca94641, 0x597a1a8a, 0xe14a1f97,
+ 0x4499435c, 0xeaebd7da, 0x4f388b11, 0x9a8adde0, 0x3f59812b,
+ 0x912b15ad, 0x34f84966, 0x8cc84c7b, 0x291b10b0, 0x87698436,
+ 0x22bad8fd, 0x5a0ff408, 0xffdca8c3, 0x51ae3c45, 0xf47d608e,
+ 0x4c4d6593, 0xe99e3958, 0x47ecadde, 0xe23ff115, 0x378da7e4,
+ 0x925efb2f, 0x3c2c6fa9, 0x99ff3362, 0x21cf367f, 0x841c6ab4,
+ 0x2a6efe32, 0x8fbda2f9, 0xc10d220b, 0x64de7ec0, 0xcaacea46,
+ 0x6f7fb68d, 0xd74fb390, 0x729cef5b, 0xdcee7bdd, 0x793d2716,
+ 0xac8f71e7, 0x095c2d2c, 0xa72eb9aa, 0x02fde561, 0xbacde07c,
+ 0x1f1ebcb7, 0xb16c2831, 0x14bf74fa, 0xd814b01e, 0x7dc7ecd5,
+ 0xd3b57853, 0x76662498, 0xce562185, 0x6b857d4e, 0xc5f7e9c8,
+ 0x6024b503, 0xb596e3f2, 0x1045bf39, 0xbe372bbf, 0x1be47774,
+ 0xa3d47269, 0x06072ea2, 0xa875ba24, 0x0da6e6ef, 0x4316661d,
+ 0xe6c53ad6, 0x48b7ae50, 0xed64f29b, 0x5554f786, 0xf087ab4d,
+ 0x5ef53fcb, 0xfb266300, 0x2e9435f1, 0x8b47693a, 0x2535fdbc,
+ 0x80e6a177, 0x38d6a46a, 0x9d05f8a1, 0x33776c27, 0x96a430ec,
+ 0xee111c19, 0x4bc240d2, 0xe5b0d454, 0x4063889f, 0xf8538d82,
+ 0x5d80d149, 0xf3f245cf, 0x56211904, 0x83934ff5, 0x2640133e,
+ 0x883287b8, 0x2de1db73, 0x95d1de6e, 0x300282a5, 0x9e701623,
+ 0x3ba34ae8, 0x7513ca1a, 0xd0c096d1, 0x7eb20257, 0xdb615e9c,
+ 0x63515b81, 0xc682074a, 0x68f093cc, 0xcd23cf07, 0x189199f6,
+ 0xbd42c53d, 0x133051bb, 0xb6e30d70, 0x0ed3086d, 0xab0054a6,
+ 0x0572c020, 0xa0a19ceb, 0xb41ee811, 0x11cdb4da, 0xbfbf205c,
+ 0x1a6c7c97, 0xa25c798a, 0x078f2541, 0xa9fdb1c7, 0x0c2eed0c,
+ 0xd99cbbfd, 0x7c4fe736, 0xd23d73b0, 0x77ee2f7b, 0xcfde2a66,
+ 0x6a0d76ad, 0xc47fe22b, 0x61acbee0, 0x2f1c3e12, 0x8acf62d9,
+ 0x24bdf65f, 0x816eaa94, 0x395eaf89, 0x9c8df342, 0x32ff67c4,
+ 0x972c3b0f, 0x429e6dfe, 0xe74d3135, 0x493fa5b3, 0xececf978,
+ 0x54dcfc65, 0xf10fa0ae, 0x5f7d3428, 0xfaae68e3, 0x821b4416,
+ 0x27c818dd, 0x89ba8c5b, 0x2c69d090, 0x9459d58d, 0x318a8946,
+ 0x9ff81dc0, 0x3a2b410b, 0xef9917fa, 0x4a4a4b31, 0xe438dfb7,
+ 0x41eb837c, 0xf9db8661, 0x5c08daaa, 0xf27a4e2c, 0x57a912e7,
+ 0x19199215, 0xbccacede, 0x12b85a58, 0xb76b0693, 0x0f5b038e,
+ 0xaa885f45, 0x04facbc3, 0xa1299708, 0x749bc1f9, 0xd1489d32,
+ 0x7f3a09b4, 0xdae9557f, 0x62d95062, 0xc70a0ca9, 0x6978982f,
+ 0xccabc4e4},
+ {0x00000000, 0xb40b77a6, 0x29119f97, 0x9d1ae831, 0x13244ff4,
+ 0xa72f3852, 0x3a35d063, 0x8e3ea7c5, 0x674eef33, 0xd3459895,
+ 0x4e5f70a4, 0xfa540702, 0x746aa0c7, 0xc061d761, 0x5d7b3f50,
+ 0xe97048f6, 0xce9cde67, 0x7a97a9c1, 0xe78d41f0, 0x53863656,
+ 0xddb89193, 0x69b3e635, 0xf4a90e04, 0x40a279a2, 0xa9d23154,
+ 0x1dd946f2, 0x80c3aec3, 0x34c8d965, 0xbaf67ea0, 0x0efd0906,
+ 0x93e7e137, 0x27ec9691, 0x9c39bdcf, 0x2832ca69, 0xb5282258,
+ 0x012355fe, 0x8f1df23b, 0x3b16859d, 0xa60c6dac, 0x12071a0a,
+ 0xfb7752fc, 0x4f7c255a, 0xd266cd6b, 0x666dbacd, 0xe8531d08,
+ 0x5c586aae, 0xc142829f, 0x7549f539, 0x52a563a8, 0xe6ae140e,
+ 0x7bb4fc3f, 0xcfbf8b99, 0x41812c5c, 0xf58a5bfa, 0x6890b3cb,
+ 0xdc9bc46d, 0x35eb8c9b, 0x81e0fb3d, 0x1cfa130c, 0xa8f164aa,
+ 0x26cfc36f, 0x92c4b4c9, 0x0fde5cf8, 0xbbd52b5e, 0x79750b44,
+ 0xcd7e7ce2, 0x506494d3, 0xe46fe375, 0x6a5144b0, 0xde5a3316,
+ 0x4340db27, 0xf74bac81, 0x1e3be477, 0xaa3093d1, 0x372a7be0,
+ 0x83210c46, 0x0d1fab83, 0xb914dc25, 0x240e3414, 0x900543b2,
+ 0xb7e9d523, 0x03e2a285, 0x9ef84ab4, 0x2af33d12, 0xa4cd9ad7,
+ 0x10c6ed71, 0x8ddc0540, 0x39d772e6, 0xd0a73a10, 0x64ac4db6,
+ 0xf9b6a587, 0x4dbdd221, 0xc38375e4, 0x77880242, 0xea92ea73,
+ 0x5e999dd5, 0xe54cb68b, 0x5147c12d, 0xcc5d291c, 0x78565eba,
+ 0xf668f97f, 0x42638ed9, 0xdf7966e8, 0x6b72114e, 0x820259b8,
+ 0x36092e1e, 0xab13c62f, 0x1f18b189, 0x9126164c, 0x252d61ea,
+ 0xb83789db, 0x0c3cfe7d, 0x2bd068ec, 0x9fdb1f4a, 0x02c1f77b,
+ 0xb6ca80dd, 0x38f42718, 0x8cff50be, 0x11e5b88f, 0xa5eecf29,
+ 0x4c9e87df, 0xf895f079, 0x658f1848, 0xd1846fee, 0x5fbac82b,
+ 0xebb1bf8d, 0x76ab57bc, 0xc2a0201a, 0xf2ea1688, 0x46e1612e,
+ 0xdbfb891f, 0x6ff0feb9, 0xe1ce597c, 0x55c52eda, 0xc8dfc6eb,
+ 0x7cd4b14d, 0x95a4f9bb, 0x21af8e1d, 0xbcb5662c, 0x08be118a,
+ 0x8680b64f, 0x328bc1e9, 0xaf9129d8, 0x1b9a5e7e, 0x3c76c8ef,
+ 0x887dbf49, 0x15675778, 0xa16c20de, 0x2f52871b, 0x9b59f0bd,
+ 0x0643188c, 0xb2486f2a, 0x5b3827dc, 0xef33507a, 0x7229b84b,
+ 0xc622cfed, 0x481c6828, 0xfc171f8e, 0x610df7bf, 0xd5068019,
+ 0x6ed3ab47, 0xdad8dce1, 0x47c234d0, 0xf3c94376, 0x7df7e4b3,
+ 0xc9fc9315, 0x54e67b24, 0xe0ed0c82, 0x099d4474, 0xbd9633d2,
+ 0x208cdbe3, 0x9487ac45, 0x1ab90b80, 0xaeb27c26, 0x33a89417,
+ 0x87a3e3b1, 0xa04f7520, 0x14440286, 0x895eeab7, 0x3d559d11,
+ 0xb36b3ad4, 0x07604d72, 0x9a7aa543, 0x2e71d2e5, 0xc7019a13,
+ 0x730aedb5, 0xee100584, 0x5a1b7222, 0xd425d5e7, 0x602ea241,
+ 0xfd344a70, 0x493f3dd6, 0x8b9f1dcc, 0x3f946a6a, 0xa28e825b,
+ 0x1685f5fd, 0x98bb5238, 0x2cb0259e, 0xb1aacdaf, 0x05a1ba09,
+ 0xecd1f2ff, 0x58da8559, 0xc5c06d68, 0x71cb1ace, 0xfff5bd0b,
+ 0x4bfecaad, 0xd6e4229c, 0x62ef553a, 0x4503c3ab, 0xf108b40d,
+ 0x6c125c3c, 0xd8192b9a, 0x56278c5f, 0xe22cfbf9, 0x7f3613c8,
+ 0xcb3d646e, 0x224d2c98, 0x96465b3e, 0x0b5cb30f, 0xbf57c4a9,
+ 0x3169636c, 0x856214ca, 0x1878fcfb, 0xac738b5d, 0x17a6a003,
+ 0xa3add7a5, 0x3eb73f94, 0x8abc4832, 0x0482eff7, 0xb0899851,
+ 0x2d937060, 0x999807c6, 0x70e84f30, 0xc4e33896, 0x59f9d0a7,
+ 0xedf2a701, 0x63cc00c4, 0xd7c77762, 0x4add9f53, 0xfed6e8f5,
+ 0xd93a7e64, 0x6d3109c2, 0xf02be1f3, 0x44209655, 0xca1e3190,
+ 0x7e154636, 0xe30fae07, 0x5704d9a1, 0xbe749157, 0x0a7fe6f1,
+ 0x97650ec0, 0x236e7966, 0xad50dea3, 0x195ba905, 0x84414134,
+ 0x304a3692},
+ {0x00000000, 0x9e00aacc, 0x7d072542, 0xe3078f8e, 0xfa0e4a84,
+ 0x640ee048, 0x87096fc6, 0x1909c50a, 0xb51be5d3, 0x2b1b4f1f,
+ 0xc81cc091, 0x561c6a5d, 0x4f15af57, 0xd115059b, 0x32128a15,
+ 0xac1220d9, 0x2b31bb7c, 0xb53111b0, 0x56369e3e, 0xc83634f2,
+ 0xd13ff1f8, 0x4f3f5b34, 0xac38d4ba, 0x32387e76, 0x9e2a5eaf,
+ 0x002af463, 0xe32d7bed, 0x7d2dd121, 0x6424142b, 0xfa24bee7,
+ 0x19233169, 0x87239ba5, 0x566276f9, 0xc862dc35, 0x2b6553bb,
+ 0xb565f977, 0xac6c3c7d, 0x326c96b1, 0xd16b193f, 0x4f6bb3f3,
+ 0xe379932a, 0x7d7939e6, 0x9e7eb668, 0x007e1ca4, 0x1977d9ae,
+ 0x87777362, 0x6470fcec, 0xfa705620, 0x7d53cd85, 0xe3536749,
+ 0x0054e8c7, 0x9e54420b, 0x875d8701, 0x195d2dcd, 0xfa5aa243,
+ 0x645a088f, 0xc8482856, 0x5648829a, 0xb54f0d14, 0x2b4fa7d8,
+ 0x324662d2, 0xac46c81e, 0x4f414790, 0xd141ed5c, 0xedc29d29,
+ 0x73c237e5, 0x90c5b86b, 0x0ec512a7, 0x17ccd7ad, 0x89cc7d61,
+ 0x6acbf2ef, 0xf4cb5823, 0x58d978fa, 0xc6d9d236, 0x25de5db8,
+ 0xbbdef774, 0xa2d7327e, 0x3cd798b2, 0xdfd0173c, 0x41d0bdf0,
+ 0xc6f32655, 0x58f38c99, 0xbbf40317, 0x25f4a9db, 0x3cfd6cd1,
+ 0xa2fdc61d, 0x41fa4993, 0xdffae35f, 0x73e8c386, 0xede8694a,
+ 0x0eefe6c4, 0x90ef4c08, 0x89e68902, 0x17e623ce, 0xf4e1ac40,
+ 0x6ae1068c, 0xbba0ebd0, 0x25a0411c, 0xc6a7ce92, 0x58a7645e,
+ 0x41aea154, 0xdfae0b98, 0x3ca98416, 0xa2a92eda, 0x0ebb0e03,
+ 0x90bba4cf, 0x73bc2b41, 0xedbc818d, 0xf4b54487, 0x6ab5ee4b,
+ 0x89b261c5, 0x17b2cb09, 0x909150ac, 0x0e91fa60, 0xed9675ee,
+ 0x7396df22, 0x6a9f1a28, 0xf49fb0e4, 0x17983f6a, 0x899895a6,
+ 0x258ab57f, 0xbb8a1fb3, 0x588d903d, 0xc68d3af1, 0xdf84fffb,
+ 0x41845537, 0xa283dab9, 0x3c837075, 0xda853b53, 0x4485919f,
+ 0xa7821e11, 0x3982b4dd, 0x208b71d7, 0xbe8bdb1b, 0x5d8c5495,
+ 0xc38cfe59, 0x6f9ede80, 0xf19e744c, 0x1299fbc2, 0x8c99510e,
+ 0x95909404, 0x0b903ec8, 0xe897b146, 0x76971b8a, 0xf1b4802f,
+ 0x6fb42ae3, 0x8cb3a56d, 0x12b30fa1, 0x0bbacaab, 0x95ba6067,
+ 0x76bdefe9, 0xe8bd4525, 0x44af65fc, 0xdaafcf30, 0x39a840be,
+ 0xa7a8ea72, 0xbea12f78, 0x20a185b4, 0xc3a60a3a, 0x5da6a0f6,
+ 0x8ce74daa, 0x12e7e766, 0xf1e068e8, 0x6fe0c224, 0x76e9072e,
+ 0xe8e9ade2, 0x0bee226c, 0x95ee88a0, 0x39fca879, 0xa7fc02b5,
+ 0x44fb8d3b, 0xdafb27f7, 0xc3f2e2fd, 0x5df24831, 0xbef5c7bf,
+ 0x20f56d73, 0xa7d6f6d6, 0x39d65c1a, 0xdad1d394, 0x44d17958,
+ 0x5dd8bc52, 0xc3d8169e, 0x20df9910, 0xbedf33dc, 0x12cd1305,
+ 0x8ccdb9c9, 0x6fca3647, 0xf1ca9c8b, 0xe8c35981, 0x76c3f34d,
+ 0x95c47cc3, 0x0bc4d60f, 0x3747a67a, 0xa9470cb6, 0x4a408338,
+ 0xd44029f4, 0xcd49ecfe, 0x53494632, 0xb04ec9bc, 0x2e4e6370,
+ 0x825c43a9, 0x1c5ce965, 0xff5b66eb, 0x615bcc27, 0x7852092d,
+ 0xe652a3e1, 0x05552c6f, 0x9b5586a3, 0x1c761d06, 0x8276b7ca,
+ 0x61713844, 0xff719288, 0xe6785782, 0x7878fd4e, 0x9b7f72c0,
+ 0x057fd80c, 0xa96df8d5, 0x376d5219, 0xd46add97, 0x4a6a775b,
+ 0x5363b251, 0xcd63189d, 0x2e649713, 0xb0643ddf, 0x6125d083,
+ 0xff257a4f, 0x1c22f5c1, 0x82225f0d, 0x9b2b9a07, 0x052b30cb,
+ 0xe62cbf45, 0x782c1589, 0xd43e3550, 0x4a3e9f9c, 0xa9391012,
+ 0x3739bade, 0x2e307fd4, 0xb030d518, 0x53375a96, 0xcd37f05a,
+ 0x4a146bff, 0xd414c133, 0x37134ebd, 0xa913e471, 0xb01a217b,
+ 0x2e1a8bb7, 0xcd1d0439, 0x531daef5, 0xff0f8e2c, 0x610f24e0,
+ 0x8208ab6e, 0x1c0801a2, 0x0501c4a8, 0x9b016e64, 0x7806e1ea,
+ 0xe6064b26}};
+
+#endif
+
+#endif
+
+#if N == 3
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f,
+ 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999,
+ 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee,
+ 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615,
+ 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383,
+ 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb,
+ 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275,
+ 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d,
+ 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b,
+ 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460,
+ 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317,
+ 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1,
+ 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5,
+ 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd,
+ 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04,
+ 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c,
+ 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7,
+ 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11,
+ 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66,
+ 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7,
+ 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871,
+ 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309,
+ 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd,
+ 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85,
+ 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913,
+ 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d,
+ 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a,
+ 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc,
+ 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57,
+ 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f,
+ 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6,
+ 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e,
+ 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f,
+ 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289,
+ 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe,
+ 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05,
+ 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893,
+ 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb,
+ 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0,
+ 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8,
+ 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e,
+ 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5,
+ 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2,
+ 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574,
+ 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5,
+ 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add,
+ 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114,
+ 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c,
+ 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7,
+ 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701,
+ 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076,
+ 0x09cd8551},
+ {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193,
+ 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2,
+ 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c,
+ 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71,
+ 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a,
+ 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d,
+ 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71,
+ 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436,
+ 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d,
+ 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000,
+ 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae,
+ 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf,
+ 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930,
+ 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277,
+ 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff,
+ 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8,
+ 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef,
+ 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e,
+ 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20,
+ 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95,
+ 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e,
+ 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9,
+ 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d,
+ 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a,
+ 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151,
+ 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4,
+ 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a,
+ 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b,
+ 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c,
+ 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b,
+ 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3,
+ 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4,
+ 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b,
+ 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a,
+ 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4,
+ 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189,
+ 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92,
+ 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5,
+ 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9,
+ 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe,
+ 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5,
+ 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8,
+ 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66,
+ 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707,
+ 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8,
+ 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f,
+ 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707,
+ 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40,
+ 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017,
+ 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876,
+ 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8,
+ 0x7bc97a0c},
+ {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300,
+ 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0,
+ 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80,
+ 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701,
+ 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41,
+ 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81,
+ 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43,
+ 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83,
+ 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3,
+ 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42,
+ 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202,
+ 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2,
+ 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7,
+ 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407,
+ 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47,
+ 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87,
+ 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86,
+ 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46,
+ 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506,
+ 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44,
+ 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704,
+ 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4,
+ 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5,
+ 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505,
+ 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45,
+ 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f,
+ 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f,
+ 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f,
+ 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e,
+ 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e,
+ 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e,
+ 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce,
+ 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c,
+ 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc,
+ 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c,
+ 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d,
+ 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d,
+ 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d,
+ 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88,
+ 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48,
+ 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708,
+ 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89,
+ 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9,
+ 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309,
+ 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb,
+ 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b,
+ 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b,
+ 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b,
+ 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a,
+ 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a,
+ 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a,
+ 0x7851a2ca},
+ {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb,
+ 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8,
+ 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0,
+ 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f,
+ 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a,
+ 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf,
+ 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5,
+ 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380,
+ 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815,
+ 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa,
+ 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2,
+ 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1,
+ 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1,
+ 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4,
+ 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa,
+ 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df,
+ 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6,
+ 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5,
+ 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad,
+ 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca,
+ 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f,
+ 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a,
+ 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8,
+ 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d,
+ 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708,
+ 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d,
+ 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865,
+ 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636,
+ 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f,
+ 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a,
+ 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744,
+ 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061,
+ 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0,
+ 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293,
+ 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb,
+ 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874,
+ 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1,
+ 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4,
+ 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f,
+ 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a,
+ 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f,
+ 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120,
+ 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778,
+ 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b,
+ 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a,
+ 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af,
+ 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81,
+ 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4,
+ 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd,
+ 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e,
+ 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6,
+ 0x566b6848},
+ {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59,
+ 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4,
+ 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67,
+ 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef,
+ 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97,
+ 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88,
+ 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687,
+ 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698,
+ 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0,
+ 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068,
+ 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb,
+ 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056,
+ 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016,
+ 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009,
+ 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028,
+ 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037,
+ 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a,
+ 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7,
+ 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054,
+ 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7,
+ 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af,
+ 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0,
+ 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4,
+ 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab,
+ 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3,
+ 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a,
+ 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9,
+ 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54,
+ 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09,
+ 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16,
+ 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37,
+ 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28,
+ 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e,
+ 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3,
+ 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40,
+ 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8,
+ 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0,
+ 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf,
+ 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6,
+ 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9,
+ 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1,
+ 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059,
+ 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca,
+ 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067,
+ 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031,
+ 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e,
+ 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f,
+ 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010,
+ 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d,
+ 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0,
+ 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073,
+ 0xd8ac6b35},
+ {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2,
+ 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd,
+ 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696,
+ 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3,
+ 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f,
+ 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35,
+ 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5,
+ 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f,
+ 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673,
+ 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46,
+ 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d,
+ 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632,
+ 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28,
+ 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192,
+ 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c,
+ 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6,
+ 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0,
+ 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff,
+ 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4,
+ 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95,
+ 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9,
+ 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03,
+ 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7,
+ 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d,
+ 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151,
+ 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808,
+ 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343,
+ 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c,
+ 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a,
+ 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0,
+ 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e,
+ 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594,
+ 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6,
+ 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399,
+ 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2,
+ 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7,
+ 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb,
+ 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571,
+ 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289,
+ 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33,
+ 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f,
+ 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a,
+ 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461,
+ 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e,
+ 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c,
+ 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6,
+ 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918,
+ 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2,
+ 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484,
+ 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb,
+ 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0,
+ 0xa140efa8},
+ {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706,
+ 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed,
+ 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289,
+ 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a,
+ 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214,
+ 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3,
+ 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3,
+ 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254,
+ 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a,
+ 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9,
+ 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad,
+ 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746,
+ 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060,
+ 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187,
+ 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef,
+ 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408,
+ 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e,
+ 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495,
+ 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1,
+ 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532,
+ 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c,
+ 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb,
+ 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb,
+ 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c,
+ 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42,
+ 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060,
+ 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04,
+ 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef,
+ 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99,
+ 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e,
+ 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16,
+ 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1,
+ 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7,
+ 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c,
+ 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38,
+ 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb,
+ 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5,
+ 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42,
+ 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62,
+ 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85,
+ 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb,
+ 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18,
+ 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c,
+ 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997,
+ 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1,
+ 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36,
+ 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e,
+ 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9,
+ 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf,
+ 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24,
+ 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040,
+ 0x917cd6a1},
+ {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf,
+ 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd,
+ 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896,
+ 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9,
+ 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3,
+ 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f,
+ 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d,
+ 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1,
+ 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab,
+ 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4,
+ 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f,
+ 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d,
+ 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4,
+ 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978,
+ 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad,
+ 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621,
+ 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46,
+ 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854,
+ 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f,
+ 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a,
+ 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890,
+ 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c,
+ 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4,
+ 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238,
+ 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622,
+ 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab,
+ 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0,
+ 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2,
+ 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295,
+ 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19,
+ 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc,
+ 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140,
+ 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd,
+ 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf,
+ 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184,
+ 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb,
+ 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1,
+ 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d,
+ 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb,
+ 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257,
+ 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d,
+ 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22,
+ 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069,
+ 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b,
+ 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6,
+ 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a,
+ 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf,
+ 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33,
+ 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254,
+ 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146,
+ 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d,
+ 0x18ba364e}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x43cba68700000000, 0xc7903cd400000000,
+ 0x845b9a5300000000, 0xcf27087300000000, 0x8cecaef400000000,
+ 0x08b734a700000000, 0x4b7c922000000000, 0x9e4f10e600000000,
+ 0xdd84b66100000000, 0x59df2c3200000000, 0x1a148ab500000000,
+ 0x5168189500000000, 0x12a3be1200000000, 0x96f8244100000000,
+ 0xd53382c600000000, 0x7d99511700000000, 0x3e52f79000000000,
+ 0xba096dc300000000, 0xf9c2cb4400000000, 0xb2be596400000000,
+ 0xf175ffe300000000, 0x752e65b000000000, 0x36e5c33700000000,
+ 0xe3d641f100000000, 0xa01de77600000000, 0x24467d2500000000,
+ 0x678ddba200000000, 0x2cf1498200000000, 0x6f3aef0500000000,
+ 0xeb61755600000000, 0xa8aad3d100000000, 0xfa32a32e00000000,
+ 0xb9f905a900000000, 0x3da29ffa00000000, 0x7e69397d00000000,
+ 0x3515ab5d00000000, 0x76de0dda00000000, 0xf285978900000000,
+ 0xb14e310e00000000, 0x647db3c800000000, 0x27b6154f00000000,
+ 0xa3ed8f1c00000000, 0xe026299b00000000, 0xab5abbbb00000000,
+ 0xe8911d3c00000000, 0x6cca876f00000000, 0x2f0121e800000000,
+ 0x87abf23900000000, 0xc46054be00000000, 0x403bceed00000000,
+ 0x03f0686a00000000, 0x488cfa4a00000000, 0x0b475ccd00000000,
+ 0x8f1cc69e00000000, 0xccd7601900000000, 0x19e4e2df00000000,
+ 0x5a2f445800000000, 0xde74de0b00000000, 0x9dbf788c00000000,
+ 0xd6c3eaac00000000, 0x95084c2b00000000, 0x1153d67800000000,
+ 0x529870ff00000000, 0xf465465d00000000, 0xb7aee0da00000000,
+ 0x33f57a8900000000, 0x703edc0e00000000, 0x3b424e2e00000000,
+ 0x7889e8a900000000, 0xfcd272fa00000000, 0xbf19d47d00000000,
+ 0x6a2a56bb00000000, 0x29e1f03c00000000, 0xadba6a6f00000000,
+ 0xee71cce800000000, 0xa50d5ec800000000, 0xe6c6f84f00000000,
+ 0x629d621c00000000, 0x2156c49b00000000, 0x89fc174a00000000,
+ 0xca37b1cd00000000, 0x4e6c2b9e00000000, 0x0da78d1900000000,
+ 0x46db1f3900000000, 0x0510b9be00000000, 0x814b23ed00000000,
+ 0xc280856a00000000, 0x17b307ac00000000, 0x5478a12b00000000,
+ 0xd0233b7800000000, 0x93e89dff00000000, 0xd8940fdf00000000,
+ 0x9b5fa95800000000, 0x1f04330b00000000, 0x5ccf958c00000000,
+ 0x0e57e57300000000, 0x4d9c43f400000000, 0xc9c7d9a700000000,
+ 0x8a0c7f2000000000, 0xc170ed0000000000, 0x82bb4b8700000000,
+ 0x06e0d1d400000000, 0x452b775300000000, 0x9018f59500000000,
+ 0xd3d3531200000000, 0x5788c94100000000, 0x14436fc600000000,
+ 0x5f3ffde600000000, 0x1cf45b6100000000, 0x98afc13200000000,
+ 0xdb6467b500000000, 0x73ceb46400000000, 0x300512e300000000,
+ 0xb45e88b000000000, 0xf7952e3700000000, 0xbce9bc1700000000,
+ 0xff221a9000000000, 0x7b7980c300000000, 0x38b2264400000000,
+ 0xed81a48200000000, 0xae4a020500000000, 0x2a11985600000000,
+ 0x69da3ed100000000, 0x22a6acf100000000, 0x616d0a7600000000,
+ 0xe536902500000000, 0xa6fd36a200000000, 0xe8cb8cba00000000,
+ 0xab002a3d00000000, 0x2f5bb06e00000000, 0x6c9016e900000000,
+ 0x27ec84c900000000, 0x6427224e00000000, 0xe07cb81d00000000,
+ 0xa3b71e9a00000000, 0x76849c5c00000000, 0x354f3adb00000000,
+ 0xb114a08800000000, 0xf2df060f00000000, 0xb9a3942f00000000,
+ 0xfa6832a800000000, 0x7e33a8fb00000000, 0x3df80e7c00000000,
+ 0x9552ddad00000000, 0xd6997b2a00000000, 0x52c2e17900000000,
+ 0x110947fe00000000, 0x5a75d5de00000000, 0x19be735900000000,
+ 0x9de5e90a00000000, 0xde2e4f8d00000000, 0x0b1dcd4b00000000,
+ 0x48d66bcc00000000, 0xcc8df19f00000000, 0x8f46571800000000,
+ 0xc43ac53800000000, 0x87f163bf00000000, 0x03aaf9ec00000000,
+ 0x40615f6b00000000, 0x12f92f9400000000, 0x5132891300000000,
+ 0xd569134000000000, 0x96a2b5c700000000, 0xddde27e700000000,
+ 0x9e15816000000000, 0x1a4e1b3300000000, 0x5985bdb400000000,
+ 0x8cb63f7200000000, 0xcf7d99f500000000, 0x4b2603a600000000,
+ 0x08eda52100000000, 0x4391370100000000, 0x005a918600000000,
+ 0x84010bd500000000, 0xc7caad5200000000, 0x6f607e8300000000,
+ 0x2cabd80400000000, 0xa8f0425700000000, 0xeb3be4d000000000,
+ 0xa04776f000000000, 0xe38cd07700000000, 0x67d74a2400000000,
+ 0x241ceca300000000, 0xf12f6e6500000000, 0xb2e4c8e200000000,
+ 0x36bf52b100000000, 0x7574f43600000000, 0x3e08661600000000,
+ 0x7dc3c09100000000, 0xf9985ac200000000, 0xba53fc4500000000,
+ 0x1caecae700000000, 0x5f656c6000000000, 0xdb3ef63300000000,
+ 0x98f550b400000000, 0xd389c29400000000, 0x9042641300000000,
+ 0x1419fe4000000000, 0x57d258c700000000, 0x82e1da0100000000,
+ 0xc12a7c8600000000, 0x4571e6d500000000, 0x06ba405200000000,
+ 0x4dc6d27200000000, 0x0e0d74f500000000, 0x8a56eea600000000,
+ 0xc99d482100000000, 0x61379bf000000000, 0x22fc3d7700000000,
+ 0xa6a7a72400000000, 0xe56c01a300000000, 0xae10938300000000,
+ 0xeddb350400000000, 0x6980af5700000000, 0x2a4b09d000000000,
+ 0xff788b1600000000, 0xbcb32d9100000000, 0x38e8b7c200000000,
+ 0x7b23114500000000, 0x305f836500000000, 0x739425e200000000,
+ 0xf7cfbfb100000000, 0xb404193600000000, 0xe69c69c900000000,
+ 0xa557cf4e00000000, 0x210c551d00000000, 0x62c7f39a00000000,
+ 0x29bb61ba00000000, 0x6a70c73d00000000, 0xee2b5d6e00000000,
+ 0xade0fbe900000000, 0x78d3792f00000000, 0x3b18dfa800000000,
+ 0xbf4345fb00000000, 0xfc88e37c00000000, 0xb7f4715c00000000,
+ 0xf43fd7db00000000, 0x70644d8800000000, 0x33afeb0f00000000,
+ 0x9b0538de00000000, 0xd8ce9e5900000000, 0x5c95040a00000000,
+ 0x1f5ea28d00000000, 0x542230ad00000000, 0x17e9962a00000000,
+ 0x93b20c7900000000, 0xd079aafe00000000, 0x054a283800000000,
+ 0x46818ebf00000000, 0xc2da14ec00000000, 0x8111b26b00000000,
+ 0xca6d204b00000000, 0x89a686cc00000000, 0x0dfd1c9f00000000,
+ 0x4e36ba1800000000},
+ {0x0000000000000000, 0xe1b652ef00000000, 0x836bd40500000000,
+ 0x62dd86ea00000000, 0x06d7a80b00000000, 0xe761fae400000000,
+ 0x85bc7c0e00000000, 0x640a2ee100000000, 0x0cae511700000000,
+ 0xed1803f800000000, 0x8fc5851200000000, 0x6e73d7fd00000000,
+ 0x0a79f91c00000000, 0xebcfabf300000000, 0x89122d1900000000,
+ 0x68a47ff600000000, 0x185ca32e00000000, 0xf9eaf1c100000000,
+ 0x9b37772b00000000, 0x7a8125c400000000, 0x1e8b0b2500000000,
+ 0xff3d59ca00000000, 0x9de0df2000000000, 0x7c568dcf00000000,
+ 0x14f2f23900000000, 0xf544a0d600000000, 0x9799263c00000000,
+ 0x762f74d300000000, 0x12255a3200000000, 0xf39308dd00000000,
+ 0x914e8e3700000000, 0x70f8dcd800000000, 0x30b8465d00000000,
+ 0xd10e14b200000000, 0xb3d3925800000000, 0x5265c0b700000000,
+ 0x366fee5600000000, 0xd7d9bcb900000000, 0xb5043a5300000000,
+ 0x54b268bc00000000, 0x3c16174a00000000, 0xdda045a500000000,
+ 0xbf7dc34f00000000, 0x5ecb91a000000000, 0x3ac1bf4100000000,
+ 0xdb77edae00000000, 0xb9aa6b4400000000, 0x581c39ab00000000,
+ 0x28e4e57300000000, 0xc952b79c00000000, 0xab8f317600000000,
+ 0x4a39639900000000, 0x2e334d7800000000, 0xcf851f9700000000,
+ 0xad58997d00000000, 0x4ceecb9200000000, 0x244ab46400000000,
+ 0xc5fce68b00000000, 0xa721606100000000, 0x4697328e00000000,
+ 0x229d1c6f00000000, 0xc32b4e8000000000, 0xa1f6c86a00000000,
+ 0x40409a8500000000, 0x60708dba00000000, 0x81c6df5500000000,
+ 0xe31b59bf00000000, 0x02ad0b5000000000, 0x66a725b100000000,
+ 0x8711775e00000000, 0xe5ccf1b400000000, 0x047aa35b00000000,
+ 0x6cdedcad00000000, 0x8d688e4200000000, 0xefb508a800000000,
+ 0x0e035a4700000000, 0x6a0974a600000000, 0x8bbf264900000000,
+ 0xe962a0a300000000, 0x08d4f24c00000000, 0x782c2e9400000000,
+ 0x999a7c7b00000000, 0xfb47fa9100000000, 0x1af1a87e00000000,
+ 0x7efb869f00000000, 0x9f4dd47000000000, 0xfd90529a00000000,
+ 0x1c26007500000000, 0x74827f8300000000, 0x95342d6c00000000,
+ 0xf7e9ab8600000000, 0x165ff96900000000, 0x7255d78800000000,
+ 0x93e3856700000000, 0xf13e038d00000000, 0x1088516200000000,
+ 0x50c8cbe700000000, 0xb17e990800000000, 0xd3a31fe200000000,
+ 0x32154d0d00000000, 0x561f63ec00000000, 0xb7a9310300000000,
+ 0xd574b7e900000000, 0x34c2e50600000000, 0x5c669af000000000,
+ 0xbdd0c81f00000000, 0xdf0d4ef500000000, 0x3ebb1c1a00000000,
+ 0x5ab132fb00000000, 0xbb07601400000000, 0xd9dae6fe00000000,
+ 0x386cb41100000000, 0x489468c900000000, 0xa9223a2600000000,
+ 0xcbffbccc00000000, 0x2a49ee2300000000, 0x4e43c0c200000000,
+ 0xaff5922d00000000, 0xcd2814c700000000, 0x2c9e462800000000,
+ 0x443a39de00000000, 0xa58c6b3100000000, 0xc751eddb00000000,
+ 0x26e7bf3400000000, 0x42ed91d500000000, 0xa35bc33a00000000,
+ 0xc18645d000000000, 0x2030173f00000000, 0x81e66bae00000000,
+ 0x6050394100000000, 0x028dbfab00000000, 0xe33bed4400000000,
+ 0x8731c3a500000000, 0x6687914a00000000, 0x045a17a000000000,
+ 0xe5ec454f00000000, 0x8d483ab900000000, 0x6cfe685600000000,
+ 0x0e23eebc00000000, 0xef95bc5300000000, 0x8b9f92b200000000,
+ 0x6a29c05d00000000, 0x08f446b700000000, 0xe942145800000000,
+ 0x99bac88000000000, 0x780c9a6f00000000, 0x1ad11c8500000000,
+ 0xfb674e6a00000000, 0x9f6d608b00000000, 0x7edb326400000000,
+ 0x1c06b48e00000000, 0xfdb0e66100000000, 0x9514999700000000,
+ 0x74a2cb7800000000, 0x167f4d9200000000, 0xf7c91f7d00000000,
+ 0x93c3319c00000000, 0x7275637300000000, 0x10a8e59900000000,
+ 0xf11eb77600000000, 0xb15e2df300000000, 0x50e87f1c00000000,
+ 0x3235f9f600000000, 0xd383ab1900000000, 0xb78985f800000000,
+ 0x563fd71700000000, 0x34e251fd00000000, 0xd554031200000000,
+ 0xbdf07ce400000000, 0x5c462e0b00000000, 0x3e9ba8e100000000,
+ 0xdf2dfa0e00000000, 0xbb27d4ef00000000, 0x5a91860000000000,
+ 0x384c00ea00000000, 0xd9fa520500000000, 0xa9028edd00000000,
+ 0x48b4dc3200000000, 0x2a695ad800000000, 0xcbdf083700000000,
+ 0xafd526d600000000, 0x4e63743900000000, 0x2cbef2d300000000,
+ 0xcd08a03c00000000, 0xa5acdfca00000000, 0x441a8d2500000000,
+ 0x26c70bcf00000000, 0xc771592000000000, 0xa37b77c100000000,
+ 0x42cd252e00000000, 0x2010a3c400000000, 0xc1a6f12b00000000,
+ 0xe196e61400000000, 0x0020b4fb00000000, 0x62fd321100000000,
+ 0x834b60fe00000000, 0xe7414e1f00000000, 0x06f71cf000000000,
+ 0x642a9a1a00000000, 0x859cc8f500000000, 0xed38b70300000000,
+ 0x0c8ee5ec00000000, 0x6e53630600000000, 0x8fe531e900000000,
+ 0xebef1f0800000000, 0x0a594de700000000, 0x6884cb0d00000000,
+ 0x893299e200000000, 0xf9ca453a00000000, 0x187c17d500000000,
+ 0x7aa1913f00000000, 0x9b17c3d000000000, 0xff1ded3100000000,
+ 0x1eabbfde00000000, 0x7c76393400000000, 0x9dc06bdb00000000,
+ 0xf564142d00000000, 0x14d246c200000000, 0x760fc02800000000,
+ 0x97b992c700000000, 0xf3b3bc2600000000, 0x1205eec900000000,
+ 0x70d8682300000000, 0x916e3acc00000000, 0xd12ea04900000000,
+ 0x3098f2a600000000, 0x5245744c00000000, 0xb3f326a300000000,
+ 0xd7f9084200000000, 0x364f5aad00000000, 0x5492dc4700000000,
+ 0xb5248ea800000000, 0xdd80f15e00000000, 0x3c36a3b100000000,
+ 0x5eeb255b00000000, 0xbf5d77b400000000, 0xdb57595500000000,
+ 0x3ae10bba00000000, 0x583c8d5000000000, 0xb98adfbf00000000,
+ 0xc972036700000000, 0x28c4518800000000, 0x4a19d76200000000,
+ 0xabaf858d00000000, 0xcfa5ab6c00000000, 0x2e13f98300000000,
+ 0x4cce7f6900000000, 0xad782d8600000000, 0xc5dc527000000000,
+ 0x246a009f00000000, 0x46b7867500000000, 0xa701d49a00000000,
+ 0xc30bfa7b00000000, 0x22bda89400000000, 0x40602e7e00000000,
+ 0xa1d67c9100000000},
+ {0x0000000000000000, 0x5880e2d700000000, 0xf106b47400000000,
+ 0xa98656a300000000, 0xe20d68e900000000, 0xba8d8a3e00000000,
+ 0x130bdc9d00000000, 0x4b8b3e4a00000000, 0x851da10900000000,
+ 0xdd9d43de00000000, 0x741b157d00000000, 0x2c9bf7aa00000000,
+ 0x6710c9e000000000, 0x3f902b3700000000, 0x96167d9400000000,
+ 0xce969f4300000000, 0x0a3b421300000000, 0x52bba0c400000000,
+ 0xfb3df66700000000, 0xa3bd14b000000000, 0xe8362afa00000000,
+ 0xb0b6c82d00000000, 0x19309e8e00000000, 0x41b07c5900000000,
+ 0x8f26e31a00000000, 0xd7a601cd00000000, 0x7e20576e00000000,
+ 0x26a0b5b900000000, 0x6d2b8bf300000000, 0x35ab692400000000,
+ 0x9c2d3f8700000000, 0xc4addd5000000000, 0x1476842600000000,
+ 0x4cf666f100000000, 0xe570305200000000, 0xbdf0d28500000000,
+ 0xf67beccf00000000, 0xaefb0e1800000000, 0x077d58bb00000000,
+ 0x5ffdba6c00000000, 0x916b252f00000000, 0xc9ebc7f800000000,
+ 0x606d915b00000000, 0x38ed738c00000000, 0x73664dc600000000,
+ 0x2be6af1100000000, 0x8260f9b200000000, 0xdae01b6500000000,
+ 0x1e4dc63500000000, 0x46cd24e200000000, 0xef4b724100000000,
+ 0xb7cb909600000000, 0xfc40aedc00000000, 0xa4c04c0b00000000,
+ 0x0d461aa800000000, 0x55c6f87f00000000, 0x9b50673c00000000,
+ 0xc3d085eb00000000, 0x6a56d34800000000, 0x32d6319f00000000,
+ 0x795d0fd500000000, 0x21dded0200000000, 0x885bbba100000000,
+ 0xd0db597600000000, 0x28ec084d00000000, 0x706cea9a00000000,
+ 0xd9eabc3900000000, 0x816a5eee00000000, 0xcae160a400000000,
+ 0x9261827300000000, 0x3be7d4d000000000, 0x6367360700000000,
+ 0xadf1a94400000000, 0xf5714b9300000000, 0x5cf71d3000000000,
+ 0x0477ffe700000000, 0x4ffcc1ad00000000, 0x177c237a00000000,
+ 0xbefa75d900000000, 0xe67a970e00000000, 0x22d74a5e00000000,
+ 0x7a57a88900000000, 0xd3d1fe2a00000000, 0x8b511cfd00000000,
+ 0xc0da22b700000000, 0x985ac06000000000, 0x31dc96c300000000,
+ 0x695c741400000000, 0xa7caeb5700000000, 0xff4a098000000000,
+ 0x56cc5f2300000000, 0x0e4cbdf400000000, 0x45c783be00000000,
+ 0x1d47616900000000, 0xb4c137ca00000000, 0xec41d51d00000000,
+ 0x3c9a8c6b00000000, 0x641a6ebc00000000, 0xcd9c381f00000000,
+ 0x951cdac800000000, 0xde97e48200000000, 0x8617065500000000,
+ 0x2f9150f600000000, 0x7711b22100000000, 0xb9872d6200000000,
+ 0xe107cfb500000000, 0x4881991600000000, 0x10017bc100000000,
+ 0x5b8a458b00000000, 0x030aa75c00000000, 0xaa8cf1ff00000000,
+ 0xf20c132800000000, 0x36a1ce7800000000, 0x6e212caf00000000,
+ 0xc7a77a0c00000000, 0x9f2798db00000000, 0xd4aca69100000000,
+ 0x8c2c444600000000, 0x25aa12e500000000, 0x7d2af03200000000,
+ 0xb3bc6f7100000000, 0xeb3c8da600000000, 0x42badb0500000000,
+ 0x1a3a39d200000000, 0x51b1079800000000, 0x0931e54f00000000,
+ 0xa0b7b3ec00000000, 0xf837513b00000000, 0x50d8119a00000000,
+ 0x0858f34d00000000, 0xa1dea5ee00000000, 0xf95e473900000000,
+ 0xb2d5797300000000, 0xea559ba400000000, 0x43d3cd0700000000,
+ 0x1b532fd000000000, 0xd5c5b09300000000, 0x8d45524400000000,
+ 0x24c304e700000000, 0x7c43e63000000000, 0x37c8d87a00000000,
+ 0x6f483aad00000000, 0xc6ce6c0e00000000, 0x9e4e8ed900000000,
+ 0x5ae3538900000000, 0x0263b15e00000000, 0xabe5e7fd00000000,
+ 0xf365052a00000000, 0xb8ee3b6000000000, 0xe06ed9b700000000,
+ 0x49e88f1400000000, 0x11686dc300000000, 0xdffef28000000000,
+ 0x877e105700000000, 0x2ef846f400000000, 0x7678a42300000000,
+ 0x3df39a6900000000, 0x657378be00000000, 0xccf52e1d00000000,
+ 0x9475ccca00000000, 0x44ae95bc00000000, 0x1c2e776b00000000,
+ 0xb5a821c800000000, 0xed28c31f00000000, 0xa6a3fd5500000000,
+ 0xfe231f8200000000, 0x57a5492100000000, 0x0f25abf600000000,
+ 0xc1b334b500000000, 0x9933d66200000000, 0x30b580c100000000,
+ 0x6835621600000000, 0x23be5c5c00000000, 0x7b3ebe8b00000000,
+ 0xd2b8e82800000000, 0x8a380aff00000000, 0x4e95d7af00000000,
+ 0x1615357800000000, 0xbf9363db00000000, 0xe713810c00000000,
+ 0xac98bf4600000000, 0xf4185d9100000000, 0x5d9e0b3200000000,
+ 0x051ee9e500000000, 0xcb8876a600000000, 0x9308947100000000,
+ 0x3a8ec2d200000000, 0x620e200500000000, 0x29851e4f00000000,
+ 0x7105fc9800000000, 0xd883aa3b00000000, 0x800348ec00000000,
+ 0x783419d700000000, 0x20b4fb0000000000, 0x8932ada300000000,
+ 0xd1b24f7400000000, 0x9a39713e00000000, 0xc2b993e900000000,
+ 0x6b3fc54a00000000, 0x33bf279d00000000, 0xfd29b8de00000000,
+ 0xa5a95a0900000000, 0x0c2f0caa00000000, 0x54afee7d00000000,
+ 0x1f24d03700000000, 0x47a432e000000000, 0xee22644300000000,
+ 0xb6a2869400000000, 0x720f5bc400000000, 0x2a8fb91300000000,
+ 0x8309efb000000000, 0xdb890d6700000000, 0x9002332d00000000,
+ 0xc882d1fa00000000, 0x6104875900000000, 0x3984658e00000000,
+ 0xf712facd00000000, 0xaf92181a00000000, 0x06144eb900000000,
+ 0x5e94ac6e00000000, 0x151f922400000000, 0x4d9f70f300000000,
+ 0xe419265000000000, 0xbc99c48700000000, 0x6c429df100000000,
+ 0x34c27f2600000000, 0x9d44298500000000, 0xc5c4cb5200000000,
+ 0x8e4ff51800000000, 0xd6cf17cf00000000, 0x7f49416c00000000,
+ 0x27c9a3bb00000000, 0xe95f3cf800000000, 0xb1dfde2f00000000,
+ 0x1859888c00000000, 0x40d96a5b00000000, 0x0b52541100000000,
+ 0x53d2b6c600000000, 0xfa54e06500000000, 0xa2d402b200000000,
+ 0x6679dfe200000000, 0x3ef93d3500000000, 0x977f6b9600000000,
+ 0xcfff894100000000, 0x8474b70b00000000, 0xdcf455dc00000000,
+ 0x7572037f00000000, 0x2df2e1a800000000, 0xe3647eeb00000000,
+ 0xbbe49c3c00000000, 0x1262ca9f00000000, 0x4ae2284800000000,
+ 0x0169160200000000, 0x59e9f4d500000000, 0xf06fa27600000000,
+ 0xa8ef40a100000000},
+ {0x0000000000000000, 0x463b676500000000, 0x8c76ceca00000000,
+ 0xca4da9af00000000, 0x59ebed4e00000000, 0x1fd08a2b00000000,
+ 0xd59d238400000000, 0x93a644e100000000, 0xb2d6db9d00000000,
+ 0xf4edbcf800000000, 0x3ea0155700000000, 0x789b723200000000,
+ 0xeb3d36d300000000, 0xad0651b600000000, 0x674bf81900000000,
+ 0x21709f7c00000000, 0x25abc6e000000000, 0x6390a18500000000,
+ 0xa9dd082a00000000, 0xefe66f4f00000000, 0x7c402bae00000000,
+ 0x3a7b4ccb00000000, 0xf036e56400000000, 0xb60d820100000000,
+ 0x977d1d7d00000000, 0xd1467a1800000000, 0x1b0bd3b700000000,
+ 0x5d30b4d200000000, 0xce96f03300000000, 0x88ad975600000000,
+ 0x42e03ef900000000, 0x04db599c00000000, 0x0b50fc1a00000000,
+ 0x4d6b9b7f00000000, 0x872632d000000000, 0xc11d55b500000000,
+ 0x52bb115400000000, 0x1480763100000000, 0xdecddf9e00000000,
+ 0x98f6b8fb00000000, 0xb986278700000000, 0xffbd40e200000000,
+ 0x35f0e94d00000000, 0x73cb8e2800000000, 0xe06dcac900000000,
+ 0xa656adac00000000, 0x6c1b040300000000, 0x2a20636600000000,
+ 0x2efb3afa00000000, 0x68c05d9f00000000, 0xa28df43000000000,
+ 0xe4b6935500000000, 0x7710d7b400000000, 0x312bb0d100000000,
+ 0xfb66197e00000000, 0xbd5d7e1b00000000, 0x9c2de16700000000,
+ 0xda16860200000000, 0x105b2fad00000000, 0x566048c800000000,
+ 0xc5c60c2900000000, 0x83fd6b4c00000000, 0x49b0c2e300000000,
+ 0x0f8ba58600000000, 0x16a0f83500000000, 0x509b9f5000000000,
+ 0x9ad636ff00000000, 0xdced519a00000000, 0x4f4b157b00000000,
+ 0x0970721e00000000, 0xc33ddbb100000000, 0x8506bcd400000000,
+ 0xa47623a800000000, 0xe24d44cd00000000, 0x2800ed6200000000,
+ 0x6e3b8a0700000000, 0xfd9dcee600000000, 0xbba6a98300000000,
+ 0x71eb002c00000000, 0x37d0674900000000, 0x330b3ed500000000,
+ 0x753059b000000000, 0xbf7df01f00000000, 0xf946977a00000000,
+ 0x6ae0d39b00000000, 0x2cdbb4fe00000000, 0xe6961d5100000000,
+ 0xa0ad7a3400000000, 0x81dde54800000000, 0xc7e6822d00000000,
+ 0x0dab2b8200000000, 0x4b904ce700000000, 0xd836080600000000,
+ 0x9e0d6f6300000000, 0x5440c6cc00000000, 0x127ba1a900000000,
+ 0x1df0042f00000000, 0x5bcb634a00000000, 0x9186cae500000000,
+ 0xd7bdad8000000000, 0x441be96100000000, 0x02208e0400000000,
+ 0xc86d27ab00000000, 0x8e5640ce00000000, 0xaf26dfb200000000,
+ 0xe91db8d700000000, 0x2350117800000000, 0x656b761d00000000,
+ 0xf6cd32fc00000000, 0xb0f6559900000000, 0x7abbfc3600000000,
+ 0x3c809b5300000000, 0x385bc2cf00000000, 0x7e60a5aa00000000,
+ 0xb42d0c0500000000, 0xf2166b6000000000, 0x61b02f8100000000,
+ 0x278b48e400000000, 0xedc6e14b00000000, 0xabfd862e00000000,
+ 0x8a8d195200000000, 0xccb67e3700000000, 0x06fbd79800000000,
+ 0x40c0b0fd00000000, 0xd366f41c00000000, 0x955d937900000000,
+ 0x5f103ad600000000, 0x192b5db300000000, 0x2c40f16b00000000,
+ 0x6a7b960e00000000, 0xa0363fa100000000, 0xe60d58c400000000,
+ 0x75ab1c2500000000, 0x33907b4000000000, 0xf9ddd2ef00000000,
+ 0xbfe6b58a00000000, 0x9e962af600000000, 0xd8ad4d9300000000,
+ 0x12e0e43c00000000, 0x54db835900000000, 0xc77dc7b800000000,
+ 0x8146a0dd00000000, 0x4b0b097200000000, 0x0d306e1700000000,
+ 0x09eb378b00000000, 0x4fd050ee00000000, 0x859df94100000000,
+ 0xc3a69e2400000000, 0x5000dac500000000, 0x163bbda000000000,
+ 0xdc76140f00000000, 0x9a4d736a00000000, 0xbb3dec1600000000,
+ 0xfd068b7300000000, 0x374b22dc00000000, 0x717045b900000000,
+ 0xe2d6015800000000, 0xa4ed663d00000000, 0x6ea0cf9200000000,
+ 0x289ba8f700000000, 0x27100d7100000000, 0x612b6a1400000000,
+ 0xab66c3bb00000000, 0xed5da4de00000000, 0x7efbe03f00000000,
+ 0x38c0875a00000000, 0xf28d2ef500000000, 0xb4b6499000000000,
+ 0x95c6d6ec00000000, 0xd3fdb18900000000, 0x19b0182600000000,
+ 0x5f8b7f4300000000, 0xcc2d3ba200000000, 0x8a165cc700000000,
+ 0x405bf56800000000, 0x0660920d00000000, 0x02bbcb9100000000,
+ 0x4480acf400000000, 0x8ecd055b00000000, 0xc8f6623e00000000,
+ 0x5b5026df00000000, 0x1d6b41ba00000000, 0xd726e81500000000,
+ 0x911d8f7000000000, 0xb06d100c00000000, 0xf656776900000000,
+ 0x3c1bdec600000000, 0x7a20b9a300000000, 0xe986fd4200000000,
+ 0xafbd9a2700000000, 0x65f0338800000000, 0x23cb54ed00000000,
+ 0x3ae0095e00000000, 0x7cdb6e3b00000000, 0xb696c79400000000,
+ 0xf0ada0f100000000, 0x630be41000000000, 0x2530837500000000,
+ 0xef7d2ada00000000, 0xa9464dbf00000000, 0x8836d2c300000000,
+ 0xce0db5a600000000, 0x04401c0900000000, 0x427b7b6c00000000,
+ 0xd1dd3f8d00000000, 0x97e658e800000000, 0x5dabf14700000000,
+ 0x1b90962200000000, 0x1f4bcfbe00000000, 0x5970a8db00000000,
+ 0x933d017400000000, 0xd506661100000000, 0x46a022f000000000,
+ 0x009b459500000000, 0xcad6ec3a00000000, 0x8ced8b5f00000000,
+ 0xad9d142300000000, 0xeba6734600000000, 0x21ebdae900000000,
+ 0x67d0bd8c00000000, 0xf476f96d00000000, 0xb24d9e0800000000,
+ 0x780037a700000000, 0x3e3b50c200000000, 0x31b0f54400000000,
+ 0x778b922100000000, 0xbdc63b8e00000000, 0xfbfd5ceb00000000,
+ 0x685b180a00000000, 0x2e607f6f00000000, 0xe42dd6c000000000,
+ 0xa216b1a500000000, 0x83662ed900000000, 0xc55d49bc00000000,
+ 0x0f10e01300000000, 0x492b877600000000, 0xda8dc39700000000,
+ 0x9cb6a4f200000000, 0x56fb0d5d00000000, 0x10c06a3800000000,
+ 0x141b33a400000000, 0x522054c100000000, 0x986dfd6e00000000,
+ 0xde569a0b00000000, 0x4df0deea00000000, 0x0bcbb98f00000000,
+ 0xc186102000000000, 0x87bd774500000000, 0xa6cde83900000000,
+ 0xe0f68f5c00000000, 0x2abb26f300000000, 0x6c80419600000000,
+ 0xff26057700000000, 0xb91d621200000000, 0x7350cbbd00000000,
+ 0x356bacd800000000},
+ {0x0000000000000000, 0x9e83da9f00000000, 0x7d01c4e400000000,
+ 0xe3821e7b00000000, 0xbb04f91200000000, 0x2587238d00000000,
+ 0xc6053df600000000, 0x5886e76900000000, 0x7609f22500000000,
+ 0xe88a28ba00000000, 0x0b0836c100000000, 0x958bec5e00000000,
+ 0xcd0d0b3700000000, 0x538ed1a800000000, 0xb00ccfd300000000,
+ 0x2e8f154c00000000, 0xec12e44b00000000, 0x72913ed400000000,
+ 0x911320af00000000, 0x0f90fa3000000000, 0x57161d5900000000,
+ 0xc995c7c600000000, 0x2a17d9bd00000000, 0xb494032200000000,
+ 0x9a1b166e00000000, 0x0498ccf100000000, 0xe71ad28a00000000,
+ 0x7999081500000000, 0x211fef7c00000000, 0xbf9c35e300000000,
+ 0x5c1e2b9800000000, 0xc29df10700000000, 0xd825c89700000000,
+ 0x46a6120800000000, 0xa5240c7300000000, 0x3ba7d6ec00000000,
+ 0x6321318500000000, 0xfda2eb1a00000000, 0x1e20f56100000000,
+ 0x80a32ffe00000000, 0xae2c3ab200000000, 0x30afe02d00000000,
+ 0xd32dfe5600000000, 0x4dae24c900000000, 0x1528c3a000000000,
+ 0x8bab193f00000000, 0x6829074400000000, 0xf6aadddb00000000,
+ 0x34372cdc00000000, 0xaab4f64300000000, 0x4936e83800000000,
+ 0xd7b532a700000000, 0x8f33d5ce00000000, 0x11b00f5100000000,
+ 0xf232112a00000000, 0x6cb1cbb500000000, 0x423edef900000000,
+ 0xdcbd046600000000, 0x3f3f1a1d00000000, 0xa1bcc08200000000,
+ 0xf93a27eb00000000, 0x67b9fd7400000000, 0x843be30f00000000,
+ 0x1ab8399000000000, 0xf14de1f400000000, 0x6fce3b6b00000000,
+ 0x8c4c251000000000, 0x12cfff8f00000000, 0x4a4918e600000000,
+ 0xd4cac27900000000, 0x3748dc0200000000, 0xa9cb069d00000000,
+ 0x874413d100000000, 0x19c7c94e00000000, 0xfa45d73500000000,
+ 0x64c60daa00000000, 0x3c40eac300000000, 0xa2c3305c00000000,
+ 0x41412e2700000000, 0xdfc2f4b800000000, 0x1d5f05bf00000000,
+ 0x83dcdf2000000000, 0x605ec15b00000000, 0xfedd1bc400000000,
+ 0xa65bfcad00000000, 0x38d8263200000000, 0xdb5a384900000000,
+ 0x45d9e2d600000000, 0x6b56f79a00000000, 0xf5d52d0500000000,
+ 0x1657337e00000000, 0x88d4e9e100000000, 0xd0520e8800000000,
+ 0x4ed1d41700000000, 0xad53ca6c00000000, 0x33d010f300000000,
+ 0x2968296300000000, 0xb7ebf3fc00000000, 0x5469ed8700000000,
+ 0xcaea371800000000, 0x926cd07100000000, 0x0cef0aee00000000,
+ 0xef6d149500000000, 0x71eece0a00000000, 0x5f61db4600000000,
+ 0xc1e201d900000000, 0x22601fa200000000, 0xbce3c53d00000000,
+ 0xe465225400000000, 0x7ae6f8cb00000000, 0x9964e6b000000000,
+ 0x07e73c2f00000000, 0xc57acd2800000000, 0x5bf917b700000000,
+ 0xb87b09cc00000000, 0x26f8d35300000000, 0x7e7e343a00000000,
+ 0xe0fdeea500000000, 0x037ff0de00000000, 0x9dfc2a4100000000,
+ 0xb3733f0d00000000, 0x2df0e59200000000, 0xce72fbe900000000,
+ 0x50f1217600000000, 0x0877c61f00000000, 0x96f41c8000000000,
+ 0x757602fb00000000, 0xebf5d86400000000, 0xa39db33200000000,
+ 0x3d1e69ad00000000, 0xde9c77d600000000, 0x401fad4900000000,
+ 0x18994a2000000000, 0x861a90bf00000000, 0x65988ec400000000,
+ 0xfb1b545b00000000, 0xd594411700000000, 0x4b179b8800000000,
+ 0xa89585f300000000, 0x36165f6c00000000, 0x6e90b80500000000,
+ 0xf013629a00000000, 0x13917ce100000000, 0x8d12a67e00000000,
+ 0x4f8f577900000000, 0xd10c8de600000000, 0x328e939d00000000,
+ 0xac0d490200000000, 0xf48bae6b00000000, 0x6a0874f400000000,
+ 0x898a6a8f00000000, 0x1709b01000000000, 0x3986a55c00000000,
+ 0xa7057fc300000000, 0x448761b800000000, 0xda04bb2700000000,
+ 0x82825c4e00000000, 0x1c0186d100000000, 0xff8398aa00000000,
+ 0x6100423500000000, 0x7bb87ba500000000, 0xe53ba13a00000000,
+ 0x06b9bf4100000000, 0x983a65de00000000, 0xc0bc82b700000000,
+ 0x5e3f582800000000, 0xbdbd465300000000, 0x233e9ccc00000000,
+ 0x0db1898000000000, 0x9332531f00000000, 0x70b04d6400000000,
+ 0xee3397fb00000000, 0xb6b5709200000000, 0x2836aa0d00000000,
+ 0xcbb4b47600000000, 0x55376ee900000000, 0x97aa9fee00000000,
+ 0x0929457100000000, 0xeaab5b0a00000000, 0x7428819500000000,
+ 0x2cae66fc00000000, 0xb22dbc6300000000, 0x51afa21800000000,
+ 0xcf2c788700000000, 0xe1a36dcb00000000, 0x7f20b75400000000,
+ 0x9ca2a92f00000000, 0x022173b000000000, 0x5aa794d900000000,
+ 0xc4244e4600000000, 0x27a6503d00000000, 0xb9258aa200000000,
+ 0x52d052c600000000, 0xcc53885900000000, 0x2fd1962200000000,
+ 0xb1524cbd00000000, 0xe9d4abd400000000, 0x7757714b00000000,
+ 0x94d56f3000000000, 0x0a56b5af00000000, 0x24d9a0e300000000,
+ 0xba5a7a7c00000000, 0x59d8640700000000, 0xc75bbe9800000000,
+ 0x9fdd59f100000000, 0x015e836e00000000, 0xe2dc9d1500000000,
+ 0x7c5f478a00000000, 0xbec2b68d00000000, 0x20416c1200000000,
+ 0xc3c3726900000000, 0x5d40a8f600000000, 0x05c64f9f00000000,
+ 0x9b45950000000000, 0x78c78b7b00000000, 0xe64451e400000000,
+ 0xc8cb44a800000000, 0x56489e3700000000, 0xb5ca804c00000000,
+ 0x2b495ad300000000, 0x73cfbdba00000000, 0xed4c672500000000,
+ 0x0ece795e00000000, 0x904da3c100000000, 0x8af59a5100000000,
+ 0x147640ce00000000, 0xf7f45eb500000000, 0x6977842a00000000,
+ 0x31f1634300000000, 0xaf72b9dc00000000, 0x4cf0a7a700000000,
+ 0xd2737d3800000000, 0xfcfc687400000000, 0x627fb2eb00000000,
+ 0x81fdac9000000000, 0x1f7e760f00000000, 0x47f8916600000000,
+ 0xd97b4bf900000000, 0x3af9558200000000, 0xa47a8f1d00000000,
+ 0x66e77e1a00000000, 0xf864a48500000000, 0x1be6bafe00000000,
+ 0x8565606100000000, 0xdde3870800000000, 0x43605d9700000000,
+ 0xa0e243ec00000000, 0x3e61997300000000, 0x10ee8c3f00000000,
+ 0x8e6d56a000000000, 0x6def48db00000000, 0xf36c924400000000,
+ 0xabea752d00000000, 0x3569afb200000000, 0xd6ebb1c900000000,
+ 0x48686b5600000000},
+ {0x0000000000000000, 0xc064281700000000, 0x80c9502e00000000,
+ 0x40ad783900000000, 0x0093a15c00000000, 0xc0f7894b00000000,
+ 0x805af17200000000, 0x403ed96500000000, 0x002643b900000000,
+ 0xc0426bae00000000, 0x80ef139700000000, 0x408b3b8000000000,
+ 0x00b5e2e500000000, 0xc0d1caf200000000, 0x807cb2cb00000000,
+ 0x40189adc00000000, 0x414af7a900000000, 0x812edfbe00000000,
+ 0xc183a78700000000, 0x01e78f9000000000, 0x41d956f500000000,
+ 0x81bd7ee200000000, 0xc11006db00000000, 0x01742ecc00000000,
+ 0x416cb41000000000, 0x81089c0700000000, 0xc1a5e43e00000000,
+ 0x01c1cc2900000000, 0x41ff154c00000000, 0x819b3d5b00000000,
+ 0xc136456200000000, 0x01526d7500000000, 0xc3929f8800000000,
+ 0x03f6b79f00000000, 0x435bcfa600000000, 0x833fe7b100000000,
+ 0xc3013ed400000000, 0x036516c300000000, 0x43c86efa00000000,
+ 0x83ac46ed00000000, 0xc3b4dc3100000000, 0x03d0f42600000000,
+ 0x437d8c1f00000000, 0x8319a40800000000, 0xc3277d6d00000000,
+ 0x0343557a00000000, 0x43ee2d4300000000, 0x838a055400000000,
+ 0x82d8682100000000, 0x42bc403600000000, 0x0211380f00000000,
+ 0xc275101800000000, 0x824bc97d00000000, 0x422fe16a00000000,
+ 0x0282995300000000, 0xc2e6b14400000000, 0x82fe2b9800000000,
+ 0x429a038f00000000, 0x02377bb600000000, 0xc25353a100000000,
+ 0x826d8ac400000000, 0x4209a2d300000000, 0x02a4daea00000000,
+ 0xc2c0f2fd00000000, 0xc7234eca00000000, 0x074766dd00000000,
+ 0x47ea1ee400000000, 0x878e36f300000000, 0xc7b0ef9600000000,
+ 0x07d4c78100000000, 0x4779bfb800000000, 0x871d97af00000000,
+ 0xc7050d7300000000, 0x0761256400000000, 0x47cc5d5d00000000,
+ 0x87a8754a00000000, 0xc796ac2f00000000, 0x07f2843800000000,
+ 0x475ffc0100000000, 0x873bd41600000000, 0x8669b96300000000,
+ 0x460d917400000000, 0x06a0e94d00000000, 0xc6c4c15a00000000,
+ 0x86fa183f00000000, 0x469e302800000000, 0x0633481100000000,
+ 0xc657600600000000, 0x864ffada00000000, 0x462bd2cd00000000,
+ 0x0686aaf400000000, 0xc6e282e300000000, 0x86dc5b8600000000,
+ 0x46b8739100000000, 0x06150ba800000000, 0xc67123bf00000000,
+ 0x04b1d14200000000, 0xc4d5f95500000000, 0x8478816c00000000,
+ 0x441ca97b00000000, 0x0422701e00000000, 0xc446580900000000,
+ 0x84eb203000000000, 0x448f082700000000, 0x049792fb00000000,
+ 0xc4f3baec00000000, 0x845ec2d500000000, 0x443aeac200000000,
+ 0x040433a700000000, 0xc4601bb000000000, 0x84cd638900000000,
+ 0x44a94b9e00000000, 0x45fb26eb00000000, 0x859f0efc00000000,
+ 0xc53276c500000000, 0x05565ed200000000, 0x456887b700000000,
+ 0x850cafa000000000, 0xc5a1d79900000000, 0x05c5ff8e00000000,
+ 0x45dd655200000000, 0x85b94d4500000000, 0xc514357c00000000,
+ 0x05701d6b00000000, 0x454ec40e00000000, 0x852aec1900000000,
+ 0xc587942000000000, 0x05e3bc3700000000, 0xcf41ed4f00000000,
+ 0x0f25c55800000000, 0x4f88bd6100000000, 0x8fec957600000000,
+ 0xcfd24c1300000000, 0x0fb6640400000000, 0x4f1b1c3d00000000,
+ 0x8f7f342a00000000, 0xcf67aef600000000, 0x0f0386e100000000,
+ 0x4faefed800000000, 0x8fcad6cf00000000, 0xcff40faa00000000,
+ 0x0f9027bd00000000, 0x4f3d5f8400000000, 0x8f59779300000000,
+ 0x8e0b1ae600000000, 0x4e6f32f100000000, 0x0ec24ac800000000,
+ 0xcea662df00000000, 0x8e98bbba00000000, 0x4efc93ad00000000,
+ 0x0e51eb9400000000, 0xce35c38300000000, 0x8e2d595f00000000,
+ 0x4e49714800000000, 0x0ee4097100000000, 0xce80216600000000,
+ 0x8ebef80300000000, 0x4edad01400000000, 0x0e77a82d00000000,
+ 0xce13803a00000000, 0x0cd372c700000000, 0xccb75ad000000000,
+ 0x8c1a22e900000000, 0x4c7e0afe00000000, 0x0c40d39b00000000,
+ 0xcc24fb8c00000000, 0x8c8983b500000000, 0x4cedaba200000000,
+ 0x0cf5317e00000000, 0xcc91196900000000, 0x8c3c615000000000,
+ 0x4c58494700000000, 0x0c66902200000000, 0xcc02b83500000000,
+ 0x8cafc00c00000000, 0x4ccbe81b00000000, 0x4d99856e00000000,
+ 0x8dfdad7900000000, 0xcd50d54000000000, 0x0d34fd5700000000,
+ 0x4d0a243200000000, 0x8d6e0c2500000000, 0xcdc3741c00000000,
+ 0x0da75c0b00000000, 0x4dbfc6d700000000, 0x8ddbeec000000000,
+ 0xcd7696f900000000, 0x0d12beee00000000, 0x4d2c678b00000000,
+ 0x8d484f9c00000000, 0xcde537a500000000, 0x0d811fb200000000,
+ 0x0862a38500000000, 0xc8068b9200000000, 0x88abf3ab00000000,
+ 0x48cfdbbc00000000, 0x08f102d900000000, 0xc8952ace00000000,
+ 0x883852f700000000, 0x485c7ae000000000, 0x0844e03c00000000,
+ 0xc820c82b00000000, 0x888db01200000000, 0x48e9980500000000,
+ 0x08d7416000000000, 0xc8b3697700000000, 0x881e114e00000000,
+ 0x487a395900000000, 0x4928542c00000000, 0x894c7c3b00000000,
+ 0xc9e1040200000000, 0x09852c1500000000, 0x49bbf57000000000,
+ 0x89dfdd6700000000, 0xc972a55e00000000, 0x09168d4900000000,
+ 0x490e179500000000, 0x896a3f8200000000, 0xc9c747bb00000000,
+ 0x09a36fac00000000, 0x499db6c900000000, 0x89f99ede00000000,
+ 0xc954e6e700000000, 0x0930cef000000000, 0xcbf03c0d00000000,
+ 0x0b94141a00000000, 0x4b396c2300000000, 0x8b5d443400000000,
+ 0xcb639d5100000000, 0x0b07b54600000000, 0x4baacd7f00000000,
+ 0x8bcee56800000000, 0xcbd67fb400000000, 0x0bb257a300000000,
+ 0x4b1f2f9a00000000, 0x8b7b078d00000000, 0xcb45dee800000000,
+ 0x0b21f6ff00000000, 0x4b8c8ec600000000, 0x8be8a6d100000000,
+ 0x8abacba400000000, 0x4adee3b300000000, 0x0a739b8a00000000,
+ 0xca17b39d00000000, 0x8a296af800000000, 0x4a4d42ef00000000,
+ 0x0ae03ad600000000, 0xca8412c100000000, 0x8a9c881d00000000,
+ 0x4af8a00a00000000, 0x0a55d83300000000, 0xca31f02400000000,
+ 0x8a0f294100000000, 0x4a6b015600000000, 0x0ac6796f00000000,
+ 0xcaa2517800000000},
+ {0x0000000000000000, 0xd4ea739b00000000, 0xe9d396ed00000000,
+ 0x3d39e57600000000, 0x93a15c0000000000, 0x474b2f9b00000000,
+ 0x7a72caed00000000, 0xae98b97600000000, 0x2643b90000000000,
+ 0xf2a9ca9b00000000, 0xcf902fed00000000, 0x1b7a5c7600000000,
+ 0xb5e2e50000000000, 0x6108969b00000000, 0x5c3173ed00000000,
+ 0x88db007600000000, 0x4c86720100000000, 0x986c019a00000000,
+ 0xa555e4ec00000000, 0x71bf977700000000, 0xdf272e0100000000,
+ 0x0bcd5d9a00000000, 0x36f4b8ec00000000, 0xe21ecb7700000000,
+ 0x6ac5cb0100000000, 0xbe2fb89a00000000, 0x83165dec00000000,
+ 0x57fc2e7700000000, 0xf964970100000000, 0x2d8ee49a00000000,
+ 0x10b701ec00000000, 0xc45d727700000000, 0x980ce50200000000,
+ 0x4ce6969900000000, 0x71df73ef00000000, 0xa535007400000000,
+ 0x0badb90200000000, 0xdf47ca9900000000, 0xe27e2fef00000000,
+ 0x36945c7400000000, 0xbe4f5c0200000000, 0x6aa52f9900000000,
+ 0x579ccaef00000000, 0x8376b97400000000, 0x2dee000200000000,
+ 0xf904739900000000, 0xc43d96ef00000000, 0x10d7e57400000000,
+ 0xd48a970300000000, 0x0060e49800000000, 0x3d5901ee00000000,
+ 0xe9b3727500000000, 0x472bcb0300000000, 0x93c1b89800000000,
+ 0xaef85dee00000000, 0x7a122e7500000000, 0xf2c92e0300000000,
+ 0x26235d9800000000, 0x1b1ab8ee00000000, 0xcff0cb7500000000,
+ 0x6168720300000000, 0xb582019800000000, 0x88bbe4ee00000000,
+ 0x5c51977500000000, 0x3019ca0500000000, 0xe4f3b99e00000000,
+ 0xd9ca5ce800000000, 0x0d202f7300000000, 0xa3b8960500000000,
+ 0x7752e59e00000000, 0x4a6b00e800000000, 0x9e81737300000000,
+ 0x165a730500000000, 0xc2b0009e00000000, 0xff89e5e800000000,
+ 0x2b63967300000000, 0x85fb2f0500000000, 0x51115c9e00000000,
+ 0x6c28b9e800000000, 0xb8c2ca7300000000, 0x7c9fb80400000000,
+ 0xa875cb9f00000000, 0x954c2ee900000000, 0x41a65d7200000000,
+ 0xef3ee40400000000, 0x3bd4979f00000000, 0x06ed72e900000000,
+ 0xd207017200000000, 0x5adc010400000000, 0x8e36729f00000000,
+ 0xb30f97e900000000, 0x67e5e47200000000, 0xc97d5d0400000000,
+ 0x1d972e9f00000000, 0x20aecbe900000000, 0xf444b87200000000,
+ 0xa8152f0700000000, 0x7cff5c9c00000000, 0x41c6b9ea00000000,
+ 0x952cca7100000000, 0x3bb4730700000000, 0xef5e009c00000000,
+ 0xd267e5ea00000000, 0x068d967100000000, 0x8e56960700000000,
+ 0x5abce59c00000000, 0x678500ea00000000, 0xb36f737100000000,
+ 0x1df7ca0700000000, 0xc91db99c00000000, 0xf4245cea00000000,
+ 0x20ce2f7100000000, 0xe4935d0600000000, 0x30792e9d00000000,
+ 0x0d40cbeb00000000, 0xd9aab87000000000, 0x7732010600000000,
+ 0xa3d8729d00000000, 0x9ee197eb00000000, 0x4a0be47000000000,
+ 0xc2d0e40600000000, 0x163a979d00000000, 0x2b0372eb00000000,
+ 0xffe9017000000000, 0x5171b80600000000, 0x859bcb9d00000000,
+ 0xb8a22eeb00000000, 0x6c485d7000000000, 0x6032940b00000000,
+ 0xb4d8e79000000000, 0x89e102e600000000, 0x5d0b717d00000000,
+ 0xf393c80b00000000, 0x2779bb9000000000, 0x1a405ee600000000,
+ 0xceaa2d7d00000000, 0x46712d0b00000000, 0x929b5e9000000000,
+ 0xafa2bbe600000000, 0x7b48c87d00000000, 0xd5d0710b00000000,
+ 0x013a029000000000, 0x3c03e7e600000000, 0xe8e9947d00000000,
+ 0x2cb4e60a00000000, 0xf85e959100000000, 0xc56770e700000000,
+ 0x118d037c00000000, 0xbf15ba0a00000000, 0x6bffc99100000000,
+ 0x56c62ce700000000, 0x822c5f7c00000000, 0x0af75f0a00000000,
+ 0xde1d2c9100000000, 0xe324c9e700000000, 0x37ceba7c00000000,
+ 0x9956030a00000000, 0x4dbc709100000000, 0x708595e700000000,
+ 0xa46fe67c00000000, 0xf83e710900000000, 0x2cd4029200000000,
+ 0x11ede7e400000000, 0xc507947f00000000, 0x6b9f2d0900000000,
+ 0xbf755e9200000000, 0x824cbbe400000000, 0x56a6c87f00000000,
+ 0xde7dc80900000000, 0x0a97bb9200000000, 0x37ae5ee400000000,
+ 0xe3442d7f00000000, 0x4ddc940900000000, 0x9936e79200000000,
+ 0xa40f02e400000000, 0x70e5717f00000000, 0xb4b8030800000000,
+ 0x6052709300000000, 0x5d6b95e500000000, 0x8981e67e00000000,
+ 0x27195f0800000000, 0xf3f32c9300000000, 0xcecac9e500000000,
+ 0x1a20ba7e00000000, 0x92fbba0800000000, 0x4611c99300000000,
+ 0x7b282ce500000000, 0xafc25f7e00000000, 0x015ae60800000000,
+ 0xd5b0959300000000, 0xe88970e500000000, 0x3c63037e00000000,
+ 0x502b5e0e00000000, 0x84c12d9500000000, 0xb9f8c8e300000000,
+ 0x6d12bb7800000000, 0xc38a020e00000000, 0x1760719500000000,
+ 0x2a5994e300000000, 0xfeb3e77800000000, 0x7668e70e00000000,
+ 0xa282949500000000, 0x9fbb71e300000000, 0x4b51027800000000,
+ 0xe5c9bb0e00000000, 0x3123c89500000000, 0x0c1a2de300000000,
+ 0xd8f05e7800000000, 0x1cad2c0f00000000, 0xc8475f9400000000,
+ 0xf57ebae200000000, 0x2194c97900000000, 0x8f0c700f00000000,
+ 0x5be6039400000000, 0x66dfe6e200000000, 0xb235957900000000,
+ 0x3aee950f00000000, 0xee04e69400000000, 0xd33d03e200000000,
+ 0x07d7707900000000, 0xa94fc90f00000000, 0x7da5ba9400000000,
+ 0x409c5fe200000000, 0x94762c7900000000, 0xc827bb0c00000000,
+ 0x1ccdc89700000000, 0x21f42de100000000, 0xf51e5e7a00000000,
+ 0x5b86e70c00000000, 0x8f6c949700000000, 0xb25571e100000000,
+ 0x66bf027a00000000, 0xee64020c00000000, 0x3a8e719700000000,
+ 0x07b794e100000000, 0xd35de77a00000000, 0x7dc55e0c00000000,
+ 0xa92f2d9700000000, 0x9416c8e100000000, 0x40fcbb7a00000000,
+ 0x84a1c90d00000000, 0x504bba9600000000, 0x6d725fe000000000,
+ 0xb9982c7b00000000, 0x1700950d00000000, 0xc3eae69600000000,
+ 0xfed303e000000000, 0x2a39707b00000000, 0xa2e2700d00000000,
+ 0x7608039600000000, 0x4b31e6e000000000, 0x9fdb957b00000000,
+ 0x31432c0d00000000, 0xe5a95f9600000000, 0xd890bae000000000,
+ 0x0c7ac97b00000000},
+ {0x0000000000000000, 0x2765258100000000, 0x0fcc3bd900000000,
+ 0x28a91e5800000000, 0x5f9e066900000000, 0x78fb23e800000000,
+ 0x50523db000000000, 0x7737183100000000, 0xbe3c0dd200000000,
+ 0x9959285300000000, 0xb1f0360b00000000, 0x9695138a00000000,
+ 0xe1a20bbb00000000, 0xc6c72e3a00000000, 0xee6e306200000000,
+ 0xc90b15e300000000, 0x3d7f6b7f00000000, 0x1a1a4efe00000000,
+ 0x32b350a600000000, 0x15d6752700000000, 0x62e16d1600000000,
+ 0x4584489700000000, 0x6d2d56cf00000000, 0x4a48734e00000000,
+ 0x834366ad00000000, 0xa426432c00000000, 0x8c8f5d7400000000,
+ 0xabea78f500000000, 0xdcdd60c400000000, 0xfbb8454500000000,
+ 0xd3115b1d00000000, 0xf4747e9c00000000, 0x7afed6fe00000000,
+ 0x5d9bf37f00000000, 0x7532ed2700000000, 0x5257c8a600000000,
+ 0x2560d09700000000, 0x0205f51600000000, 0x2aaceb4e00000000,
+ 0x0dc9cecf00000000, 0xc4c2db2c00000000, 0xe3a7fead00000000,
+ 0xcb0ee0f500000000, 0xec6bc57400000000, 0x9b5cdd4500000000,
+ 0xbc39f8c400000000, 0x9490e69c00000000, 0xb3f5c31d00000000,
+ 0x4781bd8100000000, 0x60e4980000000000, 0x484d865800000000,
+ 0x6f28a3d900000000, 0x181fbbe800000000, 0x3f7a9e6900000000,
+ 0x17d3803100000000, 0x30b6a5b000000000, 0xf9bdb05300000000,
+ 0xded895d200000000, 0xf6718b8a00000000, 0xd114ae0b00000000,
+ 0xa623b63a00000000, 0x814693bb00000000, 0xa9ef8de300000000,
+ 0x8e8aa86200000000, 0xb5fadc2600000000, 0x929ff9a700000000,
+ 0xba36e7ff00000000, 0x9d53c27e00000000, 0xea64da4f00000000,
+ 0xcd01ffce00000000, 0xe5a8e19600000000, 0xc2cdc41700000000,
+ 0x0bc6d1f400000000, 0x2ca3f47500000000, 0x040aea2d00000000,
+ 0x236fcfac00000000, 0x5458d79d00000000, 0x733df21c00000000,
+ 0x5b94ec4400000000, 0x7cf1c9c500000000, 0x8885b75900000000,
+ 0xafe092d800000000, 0x87498c8000000000, 0xa02ca90100000000,
+ 0xd71bb13000000000, 0xf07e94b100000000, 0xd8d78ae900000000,
+ 0xffb2af6800000000, 0x36b9ba8b00000000, 0x11dc9f0a00000000,
+ 0x3975815200000000, 0x1e10a4d300000000, 0x6927bce200000000,
+ 0x4e42996300000000, 0x66eb873b00000000, 0x418ea2ba00000000,
+ 0xcf040ad800000000, 0xe8612f5900000000, 0xc0c8310100000000,
+ 0xe7ad148000000000, 0x909a0cb100000000, 0xb7ff293000000000,
+ 0x9f56376800000000, 0xb83312e900000000, 0x7138070a00000000,
+ 0x565d228b00000000, 0x7ef43cd300000000, 0x5991195200000000,
+ 0x2ea6016300000000, 0x09c324e200000000, 0x216a3aba00000000,
+ 0x060f1f3b00000000, 0xf27b61a700000000, 0xd51e442600000000,
+ 0xfdb75a7e00000000, 0xdad27fff00000000, 0xade567ce00000000,
+ 0x8a80424f00000000, 0xa2295c1700000000, 0x854c799600000000,
+ 0x4c476c7500000000, 0x6b2249f400000000, 0x438b57ac00000000,
+ 0x64ee722d00000000, 0x13d96a1c00000000, 0x34bc4f9d00000000,
+ 0x1c1551c500000000, 0x3b70744400000000, 0x6af5b94d00000000,
+ 0x4d909ccc00000000, 0x6539829400000000, 0x425ca71500000000,
+ 0x356bbf2400000000, 0x120e9aa500000000, 0x3aa784fd00000000,
+ 0x1dc2a17c00000000, 0xd4c9b49f00000000, 0xf3ac911e00000000,
+ 0xdb058f4600000000, 0xfc60aac700000000, 0x8b57b2f600000000,
+ 0xac32977700000000, 0x849b892f00000000, 0xa3feacae00000000,
+ 0x578ad23200000000, 0x70eff7b300000000, 0x5846e9eb00000000,
+ 0x7f23cc6a00000000, 0x0814d45b00000000, 0x2f71f1da00000000,
+ 0x07d8ef8200000000, 0x20bdca0300000000, 0xe9b6dfe000000000,
+ 0xced3fa6100000000, 0xe67ae43900000000, 0xc11fc1b800000000,
+ 0xb628d98900000000, 0x914dfc0800000000, 0xb9e4e25000000000,
+ 0x9e81c7d100000000, 0x100b6fb300000000, 0x376e4a3200000000,
+ 0x1fc7546a00000000, 0x38a271eb00000000, 0x4f9569da00000000,
+ 0x68f04c5b00000000, 0x4059520300000000, 0x673c778200000000,
+ 0xae37626100000000, 0x895247e000000000, 0xa1fb59b800000000,
+ 0x869e7c3900000000, 0xf1a9640800000000, 0xd6cc418900000000,
+ 0xfe655fd100000000, 0xd9007a5000000000, 0x2d7404cc00000000,
+ 0x0a11214d00000000, 0x22b83f1500000000, 0x05dd1a9400000000,
+ 0x72ea02a500000000, 0x558f272400000000, 0x7d26397c00000000,
+ 0x5a431cfd00000000, 0x9348091e00000000, 0xb42d2c9f00000000,
+ 0x9c8432c700000000, 0xbbe1174600000000, 0xccd60f7700000000,
+ 0xebb32af600000000, 0xc31a34ae00000000, 0xe47f112f00000000,
+ 0xdf0f656b00000000, 0xf86a40ea00000000, 0xd0c35eb200000000,
+ 0xf7a67b3300000000, 0x8091630200000000, 0xa7f4468300000000,
+ 0x8f5d58db00000000, 0xa8387d5a00000000, 0x613368b900000000,
+ 0x46564d3800000000, 0x6eff536000000000, 0x499a76e100000000,
+ 0x3ead6ed000000000, 0x19c84b5100000000, 0x3161550900000000,
+ 0x1604708800000000, 0xe2700e1400000000, 0xc5152b9500000000,
+ 0xedbc35cd00000000, 0xcad9104c00000000, 0xbdee087d00000000,
+ 0x9a8b2dfc00000000, 0xb22233a400000000, 0x9547162500000000,
+ 0x5c4c03c600000000, 0x7b29264700000000, 0x5380381f00000000,
+ 0x74e51d9e00000000, 0x03d205af00000000, 0x24b7202e00000000,
+ 0x0c1e3e7600000000, 0x2b7b1bf700000000, 0xa5f1b39500000000,
+ 0x8294961400000000, 0xaa3d884c00000000, 0x8d58adcd00000000,
+ 0xfa6fb5fc00000000, 0xdd0a907d00000000, 0xf5a38e2500000000,
+ 0xd2c6aba400000000, 0x1bcdbe4700000000, 0x3ca89bc600000000,
+ 0x1401859e00000000, 0x3364a01f00000000, 0x4453b82e00000000,
+ 0x63369daf00000000, 0x4b9f83f700000000, 0x6cfaa67600000000,
+ 0x988ed8ea00000000, 0xbfebfd6b00000000, 0x9742e33300000000,
+ 0xb027c6b200000000, 0xc710de8300000000, 0xe075fb0200000000,
+ 0xc8dce55a00000000, 0xefb9c0db00000000, 0x26b2d53800000000,
+ 0x01d7f0b900000000, 0x297eeee100000000, 0x0e1bcb6000000000,
+ 0x792cd35100000000, 0x5e49f6d000000000, 0x76e0e88800000000,
+ 0x5185cd0900000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f,
+ 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91,
+ 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e,
+ 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c,
+ 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02,
+ 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12,
+ 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567,
+ 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277,
+ 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679,
+ 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b,
+ 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4,
+ 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a,
+ 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0,
+ 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0,
+ 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91,
+ 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881,
+ 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173,
+ 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d,
+ 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912,
+ 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8,
+ 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6,
+ 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6,
+ 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b,
+ 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b,
+ 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75,
+ 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f,
+ 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00,
+ 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee,
+ 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c,
+ 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c,
+ 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d,
+ 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d,
+ 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67,
+ 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89,
+ 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706,
+ 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14,
+ 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a,
+ 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a,
+ 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f,
+ 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f,
+ 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591,
+ 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983,
+ 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c,
+ 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2,
+ 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8,
+ 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8,
+ 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89,
+ 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99,
+ 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b,
+ 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485,
+ 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a,
+ 0x36197165},
+ {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382,
+ 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85,
+ 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06,
+ 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca,
+ 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e,
+ 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc,
+ 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616,
+ 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54,
+ 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10,
+ 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc,
+ 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f,
+ 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58,
+ 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef,
+ 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad,
+ 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b,
+ 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29,
+ 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6,
+ 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1,
+ 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622,
+ 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039,
+ 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d,
+ 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f,
+ 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32,
+ 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770,
+ 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034,
+ 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f,
+ 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc,
+ 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db,
+ 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154,
+ 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16,
+ 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0,
+ 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592,
+ 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca,
+ 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd,
+ 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e,
+ 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882,
+ 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6,
+ 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384,
+ 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1,
+ 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3,
+ 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7,
+ 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b,
+ 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8,
+ 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff,
+ 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7,
+ 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5,
+ 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23,
+ 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761,
+ 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee,
+ 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9,
+ 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a,
+ 0x1a3b93aa},
+ {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a,
+ 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca,
+ 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3,
+ 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb,
+ 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c,
+ 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58,
+ 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed,
+ 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9,
+ 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e,
+ 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906,
+ 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f,
+ 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf,
+ 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0,
+ 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4,
+ 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769,
+ 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d,
+ 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632,
+ 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82,
+ 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb,
+ 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73,
+ 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484,
+ 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0,
+ 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5,
+ 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1,
+ 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516,
+ 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f,
+ 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946,
+ 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6,
+ 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9,
+ 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad,
+ 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820,
+ 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364,
+ 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab,
+ 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b,
+ 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62,
+ 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a,
+ 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd,
+ 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089,
+ 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c,
+ 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8,
+ 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f,
+ 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477,
+ 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e,
+ 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be,
+ 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71,
+ 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635,
+ 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8,
+ 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc,
+ 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3,
+ 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753,
+ 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a,
+ 0xe147d714},
+ {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c,
+ 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b,
+ 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92,
+ 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4,
+ 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069,
+ 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526,
+ 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25,
+ 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a,
+ 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7,
+ 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491,
+ 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958,
+ 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f,
+ 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307,
+ 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648,
+ 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999,
+ 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6,
+ 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a,
+ 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d,
+ 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4,
+ 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61,
+ 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc,
+ 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3,
+ 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53,
+ 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c,
+ 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1,
+ 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c,
+ 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5,
+ 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92,
+ 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e,
+ 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771,
+ 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0,
+ 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def,
+ 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0,
+ 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7,
+ 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e,
+ 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58,
+ 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285,
+ 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca,
+ 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce,
+ 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81,
+ 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c,
+ 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a,
+ 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3,
+ 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4,
+ 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb,
+ 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4,
+ 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75,
+ 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a,
+ 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296,
+ 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1,
+ 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808,
+ 0x494f0c4b}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x43147b17, 0x8628f62e, 0xc53c8d39, 0x0c51ec5d,
+ 0x4f45974a, 0x8a791a73, 0xc96d6164, 0x18a2d8bb, 0x5bb6a3ac,
+ 0x9e8a2e95, 0xdd9e5582, 0x14f334e6, 0x57e74ff1, 0x92dbc2c8,
+ 0xd1cfb9df, 0x7142c0ac, 0x3256bbbb, 0xf76a3682, 0xb47e4d95,
+ 0x7d132cf1, 0x3e0757e6, 0xfb3bdadf, 0xb82fa1c8, 0x69e01817,
+ 0x2af46300, 0xefc8ee39, 0xacdc952e, 0x65b1f44a, 0x26a58f5d,
+ 0xe3990264, 0xa08d7973, 0xa382f182, 0xe0968a95, 0x25aa07ac,
+ 0x66be7cbb, 0xafd31ddf, 0xecc766c8, 0x29fbebf1, 0x6aef90e6,
+ 0xbb202939, 0xf834522e, 0x3d08df17, 0x7e1ca400, 0xb771c564,
+ 0xf465be73, 0x3159334a, 0x724d485d, 0xd2c0312e, 0x91d44a39,
+ 0x54e8c700, 0x17fcbc17, 0xde91dd73, 0x9d85a664, 0x58b92b5d,
+ 0x1bad504a, 0xca62e995, 0x89769282, 0x4c4a1fbb, 0x0f5e64ac,
+ 0xc63305c8, 0x85277edf, 0x401bf3e6, 0x030f88f1, 0x070392de,
+ 0x4417e9c9, 0x812b64f0, 0xc23f1fe7, 0x0b527e83, 0x48460594,
+ 0x8d7a88ad, 0xce6ef3ba, 0x1fa14a65, 0x5cb53172, 0x9989bc4b,
+ 0xda9dc75c, 0x13f0a638, 0x50e4dd2f, 0x95d85016, 0xd6cc2b01,
+ 0x76415272, 0x35552965, 0xf069a45c, 0xb37ddf4b, 0x7a10be2f,
+ 0x3904c538, 0xfc384801, 0xbf2c3316, 0x6ee38ac9, 0x2df7f1de,
+ 0xe8cb7ce7, 0xabdf07f0, 0x62b26694, 0x21a61d83, 0xe49a90ba,
+ 0xa78eebad, 0xa481635c, 0xe795184b, 0x22a99572, 0x61bdee65,
+ 0xa8d08f01, 0xebc4f416, 0x2ef8792f, 0x6dec0238, 0xbc23bbe7,
+ 0xff37c0f0, 0x3a0b4dc9, 0x791f36de, 0xb07257ba, 0xf3662cad,
+ 0x365aa194, 0x754eda83, 0xd5c3a3f0, 0x96d7d8e7, 0x53eb55de,
+ 0x10ff2ec9, 0xd9924fad, 0x9a8634ba, 0x5fbab983, 0x1caec294,
+ 0xcd617b4b, 0x8e75005c, 0x4b498d65, 0x085df672, 0xc1309716,
+ 0x8224ec01, 0x47186138, 0x040c1a2f, 0x4f005566, 0x0c142e71,
+ 0xc928a348, 0x8a3cd85f, 0x4351b93b, 0x0045c22c, 0xc5794f15,
+ 0x866d3402, 0x57a28ddd, 0x14b6f6ca, 0xd18a7bf3, 0x929e00e4,
+ 0x5bf36180, 0x18e71a97, 0xdddb97ae, 0x9ecfecb9, 0x3e4295ca,
+ 0x7d56eedd, 0xb86a63e4, 0xfb7e18f3, 0x32137997, 0x71070280,
+ 0xb43b8fb9, 0xf72ff4ae, 0x26e04d71, 0x65f43666, 0xa0c8bb5f,
+ 0xe3dcc048, 0x2ab1a12c, 0x69a5da3b, 0xac995702, 0xef8d2c15,
+ 0xec82a4e4, 0xaf96dff3, 0x6aaa52ca, 0x29be29dd, 0xe0d348b9,
+ 0xa3c733ae, 0x66fbbe97, 0x25efc580, 0xf4207c5f, 0xb7340748,
+ 0x72088a71, 0x311cf166, 0xf8719002, 0xbb65eb15, 0x7e59662c,
+ 0x3d4d1d3b, 0x9dc06448, 0xded41f5f, 0x1be89266, 0x58fce971,
+ 0x91918815, 0xd285f302, 0x17b97e3b, 0x54ad052c, 0x8562bcf3,
+ 0xc676c7e4, 0x034a4add, 0x405e31ca, 0x893350ae, 0xca272bb9,
+ 0x0f1ba680, 0x4c0fdd97, 0x4803c7b8, 0x0b17bcaf, 0xce2b3196,
+ 0x8d3f4a81, 0x44522be5, 0x074650f2, 0xc27addcb, 0x816ea6dc,
+ 0x50a11f03, 0x13b56414, 0xd689e92d, 0x959d923a, 0x5cf0f35e,
+ 0x1fe48849, 0xdad80570, 0x99cc7e67, 0x39410714, 0x7a557c03,
+ 0xbf69f13a, 0xfc7d8a2d, 0x3510eb49, 0x7604905e, 0xb3381d67,
+ 0xf02c6670, 0x21e3dfaf, 0x62f7a4b8, 0xa7cb2981, 0xe4df5296,
+ 0x2db233f2, 0x6ea648e5, 0xab9ac5dc, 0xe88ebecb, 0xeb81363a,
+ 0xa8954d2d, 0x6da9c014, 0x2ebdbb03, 0xe7d0da67, 0xa4c4a170,
+ 0x61f82c49, 0x22ec575e, 0xf323ee81, 0xb0379596, 0x750b18af,
+ 0x361f63b8, 0xff7202dc, 0xbc6679cb, 0x795af4f2, 0x3a4e8fe5,
+ 0x9ac3f696, 0xd9d78d81, 0x1ceb00b8, 0x5fff7baf, 0x96921acb,
+ 0xd58661dc, 0x10baece5, 0x53ae97f2, 0x82612e2d, 0xc175553a,
+ 0x0449d803, 0x475da314, 0x8e30c270, 0xcd24b967, 0x0818345e,
+ 0x4b0c4f49},
+ {0x00000000, 0x3e6bc2ef, 0x3dd0f504, 0x03bb37eb, 0x7aa0eb09,
+ 0x44cb29e6, 0x47701e0d, 0x791bdce2, 0xf440d713, 0xca2b15fc,
+ 0xc9902217, 0xf7fbe0f8, 0x8ee03c1a, 0xb08bfef5, 0xb330c91e,
+ 0x8d5b0bf1, 0xe881ae27, 0xd6ea6cc8, 0xd5515b23, 0xeb3a99cc,
+ 0x9221452e, 0xac4a87c1, 0xaff1b02a, 0x919a72c5, 0x1cc17934,
+ 0x22aabbdb, 0x21118c30, 0x1f7a4edf, 0x6661923d, 0x580a50d2,
+ 0x5bb16739, 0x65daa5d6, 0xd0035d4f, 0xee689fa0, 0xedd3a84b,
+ 0xd3b86aa4, 0xaaa3b646, 0x94c874a9, 0x97734342, 0xa91881ad,
+ 0x24438a5c, 0x1a2848b3, 0x19937f58, 0x27f8bdb7, 0x5ee36155,
+ 0x6088a3ba, 0x63339451, 0x5d5856be, 0x3882f368, 0x06e93187,
+ 0x0552066c, 0x3b39c483, 0x42221861, 0x7c49da8e, 0x7ff2ed65,
+ 0x41992f8a, 0xccc2247b, 0xf2a9e694, 0xf112d17f, 0xcf791390,
+ 0xb662cf72, 0x88090d9d, 0x8bb23a76, 0xb5d9f899, 0xa007ba9e,
+ 0x9e6c7871, 0x9dd74f9a, 0xa3bc8d75, 0xdaa75197, 0xe4cc9378,
+ 0xe777a493, 0xd91c667c, 0x54476d8d, 0x6a2caf62, 0x69979889,
+ 0x57fc5a66, 0x2ee78684, 0x108c446b, 0x13377380, 0x2d5cb16f,
+ 0x488614b9, 0x76edd656, 0x7556e1bd, 0x4b3d2352, 0x3226ffb0,
+ 0x0c4d3d5f, 0x0ff60ab4, 0x319dc85b, 0xbcc6c3aa, 0x82ad0145,
+ 0x811636ae, 0xbf7df441, 0xc66628a3, 0xf80dea4c, 0xfbb6dda7,
+ 0xc5dd1f48, 0x7004e7d1, 0x4e6f253e, 0x4dd412d5, 0x73bfd03a,
+ 0x0aa40cd8, 0x34cfce37, 0x3774f9dc, 0x091f3b33, 0x844430c2,
+ 0xba2ff22d, 0xb994c5c6, 0x87ff0729, 0xfee4dbcb, 0xc08f1924,
+ 0xc3342ecf, 0xfd5fec20, 0x988549f6, 0xa6ee8b19, 0xa555bcf2,
+ 0x9b3e7e1d, 0xe225a2ff, 0xdc4e6010, 0xdff557fb, 0xe19e9514,
+ 0x6cc59ee5, 0x52ae5c0a, 0x51156be1, 0x6f7ea90e, 0x166575ec,
+ 0x280eb703, 0x2bb580e8, 0x15de4207, 0x010905e6, 0x3f62c709,
+ 0x3cd9f0e2, 0x02b2320d, 0x7ba9eeef, 0x45c22c00, 0x46791beb,
+ 0x7812d904, 0xf549d2f5, 0xcb22101a, 0xc89927f1, 0xf6f2e51e,
+ 0x8fe939fc, 0xb182fb13, 0xb239ccf8, 0x8c520e17, 0xe988abc1,
+ 0xd7e3692e, 0xd4585ec5, 0xea339c2a, 0x932840c8, 0xad438227,
+ 0xaef8b5cc, 0x90937723, 0x1dc87cd2, 0x23a3be3d, 0x201889d6,
+ 0x1e734b39, 0x676897db, 0x59035534, 0x5ab862df, 0x64d3a030,
+ 0xd10a58a9, 0xef619a46, 0xecdaadad, 0xd2b16f42, 0xabaab3a0,
+ 0x95c1714f, 0x967a46a4, 0xa811844b, 0x254a8fba, 0x1b214d55,
+ 0x189a7abe, 0x26f1b851, 0x5fea64b3, 0x6181a65c, 0x623a91b7,
+ 0x5c515358, 0x398bf68e, 0x07e03461, 0x045b038a, 0x3a30c165,
+ 0x432b1d87, 0x7d40df68, 0x7efbe883, 0x40902a6c, 0xcdcb219d,
+ 0xf3a0e372, 0xf01bd499, 0xce701676, 0xb76bca94, 0x8900087b,
+ 0x8abb3f90, 0xb4d0fd7f, 0xa10ebf78, 0x9f657d97, 0x9cde4a7c,
+ 0xa2b58893, 0xdbae5471, 0xe5c5969e, 0xe67ea175, 0xd815639a,
+ 0x554e686b, 0x6b25aa84, 0x689e9d6f, 0x56f55f80, 0x2fee8362,
+ 0x1185418d, 0x123e7666, 0x2c55b489, 0x498f115f, 0x77e4d3b0,
+ 0x745fe45b, 0x4a3426b4, 0x332ffa56, 0x0d4438b9, 0x0eff0f52,
+ 0x3094cdbd, 0xbdcfc64c, 0x83a404a3, 0x801f3348, 0xbe74f1a7,
+ 0xc76f2d45, 0xf904efaa, 0xfabfd841, 0xc4d41aae, 0x710de237,
+ 0x4f6620d8, 0x4cdd1733, 0x72b6d5dc, 0x0bad093e, 0x35c6cbd1,
+ 0x367dfc3a, 0x08163ed5, 0x854d3524, 0xbb26f7cb, 0xb89dc020,
+ 0x86f602cf, 0xffedde2d, 0xc1861cc2, 0xc23d2b29, 0xfc56e9c6,
+ 0x998c4c10, 0xa7e78eff, 0xa45cb914, 0x9a377bfb, 0xe32ca719,
+ 0xdd4765f6, 0xdefc521d, 0xe09790f2, 0x6dcc9b03, 0x53a759ec,
+ 0x501c6e07, 0x6e77ace8, 0x176c700a, 0x2907b2e5, 0x2abc850e,
+ 0x14d747e1},
+ {0x00000000, 0xc0df8ec1, 0xc1b96c58, 0x0166e299, 0x8273d9b0,
+ 0x42ac5771, 0x43cab5e8, 0x83153b29, 0x45e1c3ba, 0x853e4d7b,
+ 0x8458afe2, 0x44872123, 0xc7921a0a, 0x074d94cb, 0x062b7652,
+ 0xc6f4f893, 0xcbc4f6ae, 0x0b1b786f, 0x0a7d9af6, 0xcaa21437,
+ 0x49b72f1e, 0x8968a1df, 0x880e4346, 0x48d1cd87, 0x8e253514,
+ 0x4efabbd5, 0x4f9c594c, 0x8f43d78d, 0x0c56eca4, 0xcc896265,
+ 0xcdef80fc, 0x0d300e3d, 0xd78f9c86, 0x17501247, 0x1636f0de,
+ 0xd6e97e1f, 0x55fc4536, 0x9523cbf7, 0x9445296e, 0x549aa7af,
+ 0x926e5f3c, 0x52b1d1fd, 0x53d73364, 0x9308bda5, 0x101d868c,
+ 0xd0c2084d, 0xd1a4ead4, 0x117b6415, 0x1c4b6a28, 0xdc94e4e9,
+ 0xddf20670, 0x1d2d88b1, 0x9e38b398, 0x5ee73d59, 0x5f81dfc0,
+ 0x9f5e5101, 0x59aaa992, 0x99752753, 0x9813c5ca, 0x58cc4b0b,
+ 0xdbd97022, 0x1b06fee3, 0x1a601c7a, 0xdabf92bb, 0xef1948d6,
+ 0x2fc6c617, 0x2ea0248e, 0xee7faa4f, 0x6d6a9166, 0xadb51fa7,
+ 0xacd3fd3e, 0x6c0c73ff, 0xaaf88b6c, 0x6a2705ad, 0x6b41e734,
+ 0xab9e69f5, 0x288b52dc, 0xe854dc1d, 0xe9323e84, 0x29edb045,
+ 0x24ddbe78, 0xe40230b9, 0xe564d220, 0x25bb5ce1, 0xa6ae67c8,
+ 0x6671e909, 0x67170b90, 0xa7c88551, 0x613c7dc2, 0xa1e3f303,
+ 0xa085119a, 0x605a9f5b, 0xe34fa472, 0x23902ab3, 0x22f6c82a,
+ 0xe22946eb, 0x3896d450, 0xf8495a91, 0xf92fb808, 0x39f036c9,
+ 0xbae50de0, 0x7a3a8321, 0x7b5c61b8, 0xbb83ef79, 0x7d7717ea,
+ 0xbda8992b, 0xbcce7bb2, 0x7c11f573, 0xff04ce5a, 0x3fdb409b,
+ 0x3ebda202, 0xfe622cc3, 0xf35222fe, 0x338dac3f, 0x32eb4ea6,
+ 0xf234c067, 0x7121fb4e, 0xb1fe758f, 0xb0989716, 0x704719d7,
+ 0xb6b3e144, 0x766c6f85, 0x770a8d1c, 0xb7d503dd, 0x34c038f4,
+ 0xf41fb635, 0xf57954ac, 0x35a6da6d, 0x9f35e177, 0x5fea6fb6,
+ 0x5e8c8d2f, 0x9e5303ee, 0x1d4638c7, 0xdd99b606, 0xdcff549f,
+ 0x1c20da5e, 0xdad422cd, 0x1a0bac0c, 0x1b6d4e95, 0xdbb2c054,
+ 0x58a7fb7d, 0x987875bc, 0x991e9725, 0x59c119e4, 0x54f117d9,
+ 0x942e9918, 0x95487b81, 0x5597f540, 0xd682ce69, 0x165d40a8,
+ 0x173ba231, 0xd7e42cf0, 0x1110d463, 0xd1cf5aa2, 0xd0a9b83b,
+ 0x107636fa, 0x93630dd3, 0x53bc8312, 0x52da618b, 0x9205ef4a,
+ 0x48ba7df1, 0x8865f330, 0x890311a9, 0x49dc9f68, 0xcac9a441,
+ 0x0a162a80, 0x0b70c819, 0xcbaf46d8, 0x0d5bbe4b, 0xcd84308a,
+ 0xcce2d213, 0x0c3d5cd2, 0x8f2867fb, 0x4ff7e93a, 0x4e910ba3,
+ 0x8e4e8562, 0x837e8b5f, 0x43a1059e, 0x42c7e707, 0x821869c6,
+ 0x010d52ef, 0xc1d2dc2e, 0xc0b43eb7, 0x006bb076, 0xc69f48e5,
+ 0x0640c624, 0x072624bd, 0xc7f9aa7c, 0x44ec9155, 0x84331f94,
+ 0x8555fd0d, 0x458a73cc, 0x702ca9a1, 0xb0f32760, 0xb195c5f9,
+ 0x714a4b38, 0xf25f7011, 0x3280fed0, 0x33e61c49, 0xf3399288,
+ 0x35cd6a1b, 0xf512e4da, 0xf4740643, 0x34ab8882, 0xb7beb3ab,
+ 0x77613d6a, 0x7607dff3, 0xb6d85132, 0xbbe85f0f, 0x7b37d1ce,
+ 0x7a513357, 0xba8ebd96, 0x399b86bf, 0xf944087e, 0xf822eae7,
+ 0x38fd6426, 0xfe099cb5, 0x3ed61274, 0x3fb0f0ed, 0xff6f7e2c,
+ 0x7c7a4505, 0xbca5cbc4, 0xbdc3295d, 0x7d1ca79c, 0xa7a33527,
+ 0x677cbbe6, 0x661a597f, 0xa6c5d7be, 0x25d0ec97, 0xe50f6256,
+ 0xe46980cf, 0x24b60e0e, 0xe242f69d, 0x229d785c, 0x23fb9ac5,
+ 0xe3241404, 0x60312f2d, 0xa0eea1ec, 0xa1884375, 0x6157cdb4,
+ 0x6c67c389, 0xacb84d48, 0xaddeafd1, 0x6d012110, 0xee141a39,
+ 0x2ecb94f8, 0x2fad7661, 0xef72f8a0, 0x29860033, 0xe9598ef2,
+ 0xe83f6c6b, 0x28e0e2aa, 0xabf5d983, 0x6b2a5742, 0x6a4cb5db,
+ 0xaa933b1a},
+ {0x00000000, 0x6f4ca59b, 0x9f9e3bec, 0xf0d29e77, 0x7f3b0603,
+ 0x1077a398, 0xe0a53def, 0x8fe99874, 0xfe760c06, 0x913aa99d,
+ 0x61e837ea, 0x0ea49271, 0x814d0a05, 0xee01af9e, 0x1ed331e9,
+ 0x719f9472, 0xfced180c, 0x93a1bd97, 0x637323e0, 0x0c3f867b,
+ 0x83d61e0f, 0xec9abb94, 0x1c4825e3, 0x73048078, 0x029b140a,
+ 0x6dd7b191, 0x9d052fe6, 0xf2498a7d, 0x7da01209, 0x12ecb792,
+ 0xe23e29e5, 0x8d728c7e, 0xf8db3118, 0x97979483, 0x67450af4,
+ 0x0809af6f, 0x87e0371b, 0xe8ac9280, 0x187e0cf7, 0x7732a96c,
+ 0x06ad3d1e, 0x69e19885, 0x993306f2, 0xf67fa369, 0x79963b1d,
+ 0x16da9e86, 0xe60800f1, 0x8944a56a, 0x04362914, 0x6b7a8c8f,
+ 0x9ba812f8, 0xf4e4b763, 0x7b0d2f17, 0x14418a8c, 0xe49314fb,
+ 0x8bdfb160, 0xfa402512, 0x950c8089, 0x65de1efe, 0x0a92bb65,
+ 0x857b2311, 0xea37868a, 0x1ae518fd, 0x75a9bd66, 0xf0b76330,
+ 0x9ffbc6ab, 0x6f2958dc, 0x0065fd47, 0x8f8c6533, 0xe0c0c0a8,
+ 0x10125edf, 0x7f5efb44, 0x0ec16f36, 0x618dcaad, 0x915f54da,
+ 0xfe13f141, 0x71fa6935, 0x1eb6ccae, 0xee6452d9, 0x8128f742,
+ 0x0c5a7b3c, 0x6316dea7, 0x93c440d0, 0xfc88e54b, 0x73617d3f,
+ 0x1c2dd8a4, 0xecff46d3, 0x83b3e348, 0xf22c773a, 0x9d60d2a1,
+ 0x6db24cd6, 0x02fee94d, 0x8d177139, 0xe25bd4a2, 0x12894ad5,
+ 0x7dc5ef4e, 0x086c5228, 0x6720f7b3, 0x97f269c4, 0xf8becc5f,
+ 0x7757542b, 0x181bf1b0, 0xe8c96fc7, 0x8785ca5c, 0xf61a5e2e,
+ 0x9956fbb5, 0x698465c2, 0x06c8c059, 0x8921582d, 0xe66dfdb6,
+ 0x16bf63c1, 0x79f3c65a, 0xf4814a24, 0x9bcdefbf, 0x6b1f71c8,
+ 0x0453d453, 0x8bba4c27, 0xe4f6e9bc, 0x142477cb, 0x7b68d250,
+ 0x0af74622, 0x65bbe3b9, 0x95697dce, 0xfa25d855, 0x75cc4021,
+ 0x1a80e5ba, 0xea527bcd, 0x851ede56, 0xe06fc760, 0x8f2362fb,
+ 0x7ff1fc8c, 0x10bd5917, 0x9f54c163, 0xf01864f8, 0x00cafa8f,
+ 0x6f865f14, 0x1e19cb66, 0x71556efd, 0x8187f08a, 0xeecb5511,
+ 0x6122cd65, 0x0e6e68fe, 0xfebcf689, 0x91f05312, 0x1c82df6c,
+ 0x73ce7af7, 0x831ce480, 0xec50411b, 0x63b9d96f, 0x0cf57cf4,
+ 0xfc27e283, 0x936b4718, 0xe2f4d36a, 0x8db876f1, 0x7d6ae886,
+ 0x12264d1d, 0x9dcfd569, 0xf28370f2, 0x0251ee85, 0x6d1d4b1e,
+ 0x18b4f678, 0x77f853e3, 0x872acd94, 0xe866680f, 0x678ff07b,
+ 0x08c355e0, 0xf811cb97, 0x975d6e0c, 0xe6c2fa7e, 0x898e5fe5,
+ 0x795cc192, 0x16106409, 0x99f9fc7d, 0xf6b559e6, 0x0667c791,
+ 0x692b620a, 0xe459ee74, 0x8b154bef, 0x7bc7d598, 0x148b7003,
+ 0x9b62e877, 0xf42e4dec, 0x04fcd39b, 0x6bb07600, 0x1a2fe272,
+ 0x756347e9, 0x85b1d99e, 0xeafd7c05, 0x6514e471, 0x0a5841ea,
+ 0xfa8adf9d, 0x95c67a06, 0x10d8a450, 0x7f9401cb, 0x8f469fbc,
+ 0xe00a3a27, 0x6fe3a253, 0x00af07c8, 0xf07d99bf, 0x9f313c24,
+ 0xeeaea856, 0x81e20dcd, 0x713093ba, 0x1e7c3621, 0x9195ae55,
+ 0xfed90bce, 0x0e0b95b9, 0x61473022, 0xec35bc5c, 0x837919c7,
+ 0x73ab87b0, 0x1ce7222b, 0x930eba5f, 0xfc421fc4, 0x0c9081b3,
+ 0x63dc2428, 0x1243b05a, 0x7d0f15c1, 0x8ddd8bb6, 0xe2912e2d,
+ 0x6d78b659, 0x023413c2, 0xf2e68db5, 0x9daa282e, 0xe8039548,
+ 0x874f30d3, 0x779daea4, 0x18d10b3f, 0x9738934b, 0xf87436d0,
+ 0x08a6a8a7, 0x67ea0d3c, 0x1675994e, 0x79393cd5, 0x89eba2a2,
+ 0xe6a70739, 0x694e9f4d, 0x06023ad6, 0xf6d0a4a1, 0x999c013a,
+ 0x14ee8d44, 0x7ba228df, 0x8b70b6a8, 0xe43c1333, 0x6bd58b47,
+ 0x04992edc, 0xf44bb0ab, 0x9b071530, 0xea988142, 0x85d424d9,
+ 0x7506baae, 0x1a4a1f35, 0x95a38741, 0xfaef22da, 0x0a3dbcad,
+ 0x65711936}};
+
+#endif
+
+#endif
+
+#if N == 4
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xf1da05aa, 0x38c50d15, 0xc91f08bf, 0x718a1a2a,
+ 0x80501f80, 0x494f173f, 0xb8951295, 0xe3143454, 0x12ce31fe,
+ 0xdbd13941, 0x2a0b3ceb, 0x929e2e7e, 0x63442bd4, 0xaa5b236b,
+ 0x5b8126c1, 0x1d596ee9, 0xec836b43, 0x259c63fc, 0xd4466656,
+ 0x6cd374c3, 0x9d097169, 0x541679d6, 0xa5cc7c7c, 0xfe4d5abd,
+ 0x0f975f17, 0xc68857a8, 0x37525202, 0x8fc74097, 0x7e1d453d,
+ 0xb7024d82, 0x46d84828, 0x3ab2ddd2, 0xcb68d878, 0x0277d0c7,
+ 0xf3add56d, 0x4b38c7f8, 0xbae2c252, 0x73fdcaed, 0x8227cf47,
+ 0xd9a6e986, 0x287cec2c, 0xe163e493, 0x10b9e139, 0xa82cf3ac,
+ 0x59f6f606, 0x90e9feb9, 0x6133fb13, 0x27ebb33b, 0xd631b691,
+ 0x1f2ebe2e, 0xeef4bb84, 0x5661a911, 0xa7bbacbb, 0x6ea4a404,
+ 0x9f7ea1ae, 0xc4ff876f, 0x352582c5, 0xfc3a8a7a, 0x0de08fd0,
+ 0xb5759d45, 0x44af98ef, 0x8db09050, 0x7c6a95fa, 0x7565bba4,
+ 0x84bfbe0e, 0x4da0b6b1, 0xbc7ab31b, 0x04efa18e, 0xf535a424,
+ 0x3c2aac9b, 0xcdf0a931, 0x96718ff0, 0x67ab8a5a, 0xaeb482e5,
+ 0x5f6e874f, 0xe7fb95da, 0x16219070, 0xdf3e98cf, 0x2ee49d65,
+ 0x683cd54d, 0x99e6d0e7, 0x50f9d858, 0xa123ddf2, 0x19b6cf67,
+ 0xe86ccacd, 0x2173c272, 0xd0a9c7d8, 0x8b28e119, 0x7af2e4b3,
+ 0xb3edec0c, 0x4237e9a6, 0xfaa2fb33, 0x0b78fe99, 0xc267f626,
+ 0x33bdf38c, 0x4fd76676, 0xbe0d63dc, 0x77126b63, 0x86c86ec9,
+ 0x3e5d7c5c, 0xcf8779f6, 0x06987149, 0xf74274e3, 0xacc35222,
+ 0x5d195788, 0x94065f37, 0x65dc5a9d, 0xdd494808, 0x2c934da2,
+ 0xe58c451d, 0x145640b7, 0x528e089f, 0xa3540d35, 0x6a4b058a,
+ 0x9b910020, 0x230412b5, 0xd2de171f, 0x1bc11fa0, 0xea1b1a0a,
+ 0xb19a3ccb, 0x40403961, 0x895f31de, 0x78853474, 0xc01026e1,
+ 0x31ca234b, 0xf8d52bf4, 0x090f2e5e, 0xeacb7748, 0x1b1172e2,
+ 0xd20e7a5d, 0x23d47ff7, 0x9b416d62, 0x6a9b68c8, 0xa3846077,
+ 0x525e65dd, 0x09df431c, 0xf80546b6, 0x311a4e09, 0xc0c04ba3,
+ 0x78555936, 0x898f5c9c, 0x40905423, 0xb14a5189, 0xf79219a1,
+ 0x06481c0b, 0xcf5714b4, 0x3e8d111e, 0x8618038b, 0x77c20621,
+ 0xbedd0e9e, 0x4f070b34, 0x14862df5, 0xe55c285f, 0x2c4320e0,
+ 0xdd99254a, 0x650c37df, 0x94d63275, 0x5dc93aca, 0xac133f60,
+ 0xd079aa9a, 0x21a3af30, 0xe8bca78f, 0x1966a225, 0xa1f3b0b0,
+ 0x5029b51a, 0x9936bda5, 0x68ecb80f, 0x336d9ece, 0xc2b79b64,
+ 0x0ba893db, 0xfa729671, 0x42e784e4, 0xb33d814e, 0x7a2289f1,
+ 0x8bf88c5b, 0xcd20c473, 0x3cfac1d9, 0xf5e5c966, 0x043fcccc,
+ 0xbcaade59, 0x4d70dbf3, 0x846fd34c, 0x75b5d6e6, 0x2e34f027,
+ 0xdfeef58d, 0x16f1fd32, 0xe72bf898, 0x5fbeea0d, 0xae64efa7,
+ 0x677be718, 0x96a1e2b2, 0x9faeccec, 0x6e74c946, 0xa76bc1f9,
+ 0x56b1c453, 0xee24d6c6, 0x1ffed36c, 0xd6e1dbd3, 0x273bde79,
+ 0x7cbaf8b8, 0x8d60fd12, 0x447ff5ad, 0xb5a5f007, 0x0d30e292,
+ 0xfceae738, 0x35f5ef87, 0xc42fea2d, 0x82f7a205, 0x732da7af,
+ 0xba32af10, 0x4be8aaba, 0xf37db82f, 0x02a7bd85, 0xcbb8b53a,
+ 0x3a62b090, 0x61e39651, 0x903993fb, 0x59269b44, 0xa8fc9eee,
+ 0x10698c7b, 0xe1b389d1, 0x28ac816e, 0xd97684c4, 0xa51c113e,
+ 0x54c61494, 0x9dd91c2b, 0x6c031981, 0xd4960b14, 0x254c0ebe,
+ 0xec530601, 0x1d8903ab, 0x4608256a, 0xb7d220c0, 0x7ecd287f,
+ 0x8f172dd5, 0x37823f40, 0xc6583aea, 0x0f473255, 0xfe9d37ff,
+ 0xb8457fd7, 0x499f7a7d, 0x808072c2, 0x715a7768, 0xc9cf65fd,
+ 0x38156057, 0xf10a68e8, 0x00d06d42, 0x5b514b83, 0xaa8b4e29,
+ 0x63944696, 0x924e433c, 0x2adb51a9, 0xdb015403, 0x121e5cbc,
+ 0xe3c45916},
+ {0x00000000, 0x0ee7e8d1, 0x1dcfd1a2, 0x13283973, 0x3b9fa344,
+ 0x35784b95, 0x265072e6, 0x28b79a37, 0x773f4688, 0x79d8ae59,
+ 0x6af0972a, 0x64177ffb, 0x4ca0e5cc, 0x42470d1d, 0x516f346e,
+ 0x5f88dcbf, 0xee7e8d10, 0xe09965c1, 0xf3b15cb2, 0xfd56b463,
+ 0xd5e12e54, 0xdb06c685, 0xc82efff6, 0xc6c91727, 0x9941cb98,
+ 0x97a62349, 0x848e1a3a, 0x8a69f2eb, 0xa2de68dc, 0xac39800d,
+ 0xbf11b97e, 0xb1f651af, 0x078c1c61, 0x096bf4b0, 0x1a43cdc3,
+ 0x14a42512, 0x3c13bf25, 0x32f457f4, 0x21dc6e87, 0x2f3b8656,
+ 0x70b35ae9, 0x7e54b238, 0x6d7c8b4b, 0x639b639a, 0x4b2cf9ad,
+ 0x45cb117c, 0x56e3280f, 0x5804c0de, 0xe9f29171, 0xe71579a0,
+ 0xf43d40d3, 0xfadaa802, 0xd26d3235, 0xdc8adae4, 0xcfa2e397,
+ 0xc1450b46, 0x9ecdd7f9, 0x902a3f28, 0x8302065b, 0x8de5ee8a,
+ 0xa55274bd, 0xabb59c6c, 0xb89da51f, 0xb67a4dce, 0x0f1838c2,
+ 0x01ffd013, 0x12d7e960, 0x1c3001b1, 0x34879b86, 0x3a607357,
+ 0x29484a24, 0x27afa2f5, 0x78277e4a, 0x76c0969b, 0x65e8afe8,
+ 0x6b0f4739, 0x43b8dd0e, 0x4d5f35df, 0x5e770cac, 0x5090e47d,
+ 0xe166b5d2, 0xef815d03, 0xfca96470, 0xf24e8ca1, 0xdaf91696,
+ 0xd41efe47, 0xc736c734, 0xc9d12fe5, 0x9659f35a, 0x98be1b8b,
+ 0x8b9622f8, 0x8571ca29, 0xadc6501e, 0xa321b8cf, 0xb00981bc,
+ 0xbeee696d, 0x089424a3, 0x0673cc72, 0x155bf501, 0x1bbc1dd0,
+ 0x330b87e7, 0x3dec6f36, 0x2ec45645, 0x2023be94, 0x7fab622b,
+ 0x714c8afa, 0x6264b389, 0x6c835b58, 0x4434c16f, 0x4ad329be,
+ 0x59fb10cd, 0x571cf81c, 0xe6eaa9b3, 0xe80d4162, 0xfb257811,
+ 0xf5c290c0, 0xdd750af7, 0xd392e226, 0xc0badb55, 0xce5d3384,
+ 0x91d5ef3b, 0x9f3207ea, 0x8c1a3e99, 0x82fdd648, 0xaa4a4c7f,
+ 0xa4ada4ae, 0xb7859ddd, 0xb962750c, 0x1e307184, 0x10d79955,
+ 0x03ffa026, 0x0d1848f7, 0x25afd2c0, 0x2b483a11, 0x38600362,
+ 0x3687ebb3, 0x690f370c, 0x67e8dfdd, 0x74c0e6ae, 0x7a270e7f,
+ 0x52909448, 0x5c777c99, 0x4f5f45ea, 0x41b8ad3b, 0xf04efc94,
+ 0xfea91445, 0xed812d36, 0xe366c5e7, 0xcbd15fd0, 0xc536b701,
+ 0xd61e8e72, 0xd8f966a3, 0x8771ba1c, 0x899652cd, 0x9abe6bbe,
+ 0x9459836f, 0xbcee1958, 0xb209f189, 0xa121c8fa, 0xafc6202b,
+ 0x19bc6de5, 0x175b8534, 0x0473bc47, 0x0a945496, 0x2223cea1,
+ 0x2cc42670, 0x3fec1f03, 0x310bf7d2, 0x6e832b6d, 0x6064c3bc,
+ 0x734cfacf, 0x7dab121e, 0x551c8829, 0x5bfb60f8, 0x48d3598b,
+ 0x4634b15a, 0xf7c2e0f5, 0xf9250824, 0xea0d3157, 0xe4ead986,
+ 0xcc5d43b1, 0xc2baab60, 0xd1929213, 0xdf757ac2, 0x80fda67d,
+ 0x8e1a4eac, 0x9d3277df, 0x93d59f0e, 0xbb620539, 0xb585ede8,
+ 0xa6add49b, 0xa84a3c4a, 0x11284946, 0x1fcfa197, 0x0ce798e4,
+ 0x02007035, 0x2ab7ea02, 0x245002d3, 0x37783ba0, 0x399fd371,
+ 0x66170fce, 0x68f0e71f, 0x7bd8de6c, 0x753f36bd, 0x5d88ac8a,
+ 0x536f445b, 0x40477d28, 0x4ea095f9, 0xff56c456, 0xf1b12c87,
+ 0xe29915f4, 0xec7efd25, 0xc4c96712, 0xca2e8fc3, 0xd906b6b0,
+ 0xd7e15e61, 0x886982de, 0x868e6a0f, 0x95a6537c, 0x9b41bbad,
+ 0xb3f6219a, 0xbd11c94b, 0xae39f038, 0xa0de18e9, 0x16a45527,
+ 0x1843bdf6, 0x0b6b8485, 0x058c6c54, 0x2d3bf663, 0x23dc1eb2,
+ 0x30f427c1, 0x3e13cf10, 0x619b13af, 0x6f7cfb7e, 0x7c54c20d,
+ 0x72b32adc, 0x5a04b0eb, 0x54e3583a, 0x47cb6149, 0x492c8998,
+ 0xf8dad837, 0xf63d30e6, 0xe5150995, 0xebf2e144, 0xc3457b73,
+ 0xcda293a2, 0xde8aaad1, 0xd06d4200, 0x8fe59ebf, 0x8102766e,
+ 0x922a4f1d, 0x9ccda7cc, 0xb47a3dfb, 0xba9dd52a, 0xa9b5ec59,
+ 0xa7520488},
+ {0x00000000, 0x3c60e308, 0x78c1c610, 0x44a12518, 0xf1838c20,
+ 0xcde36f28, 0x89424a30, 0xb522a938, 0x38761e01, 0x0416fd09,
+ 0x40b7d811, 0x7cd73b19, 0xc9f59221, 0xf5957129, 0xb1345431,
+ 0x8d54b739, 0x70ec3c02, 0x4c8cdf0a, 0x082dfa12, 0x344d191a,
+ 0x816fb022, 0xbd0f532a, 0xf9ae7632, 0xc5ce953a, 0x489a2203,
+ 0x74fac10b, 0x305be413, 0x0c3b071b, 0xb919ae23, 0x85794d2b,
+ 0xc1d86833, 0xfdb88b3b, 0xe1d87804, 0xddb89b0c, 0x9919be14,
+ 0xa5795d1c, 0x105bf424, 0x2c3b172c, 0x689a3234, 0x54fad13c,
+ 0xd9ae6605, 0xe5ce850d, 0xa16fa015, 0x9d0f431d, 0x282dea25,
+ 0x144d092d, 0x50ec2c35, 0x6c8ccf3d, 0x91344406, 0xad54a70e,
+ 0xe9f58216, 0xd595611e, 0x60b7c826, 0x5cd72b2e, 0x18760e36,
+ 0x2416ed3e, 0xa9425a07, 0x9522b90f, 0xd1839c17, 0xede37f1f,
+ 0x58c1d627, 0x64a1352f, 0x20001037, 0x1c60f33f, 0x18c1f649,
+ 0x24a11541, 0x60003059, 0x5c60d351, 0xe9427a69, 0xd5229961,
+ 0x9183bc79, 0xade35f71, 0x20b7e848, 0x1cd70b40, 0x58762e58,
+ 0x6416cd50, 0xd1346468, 0xed548760, 0xa9f5a278, 0x95954170,
+ 0x682dca4b, 0x544d2943, 0x10ec0c5b, 0x2c8cef53, 0x99ae466b,
+ 0xa5cea563, 0xe16f807b, 0xdd0f6373, 0x505bd44a, 0x6c3b3742,
+ 0x289a125a, 0x14faf152, 0xa1d8586a, 0x9db8bb62, 0xd9199e7a,
+ 0xe5797d72, 0xf9198e4d, 0xc5796d45, 0x81d8485d, 0xbdb8ab55,
+ 0x089a026d, 0x34fae165, 0x705bc47d, 0x4c3b2775, 0xc16f904c,
+ 0xfd0f7344, 0xb9ae565c, 0x85ceb554, 0x30ec1c6c, 0x0c8cff64,
+ 0x482dda7c, 0x744d3974, 0x89f5b24f, 0xb5955147, 0xf134745f,
+ 0xcd549757, 0x78763e6f, 0x4416dd67, 0x00b7f87f, 0x3cd71b77,
+ 0xb183ac4e, 0x8de34f46, 0xc9426a5e, 0xf5228956, 0x4000206e,
+ 0x7c60c366, 0x38c1e67e, 0x04a10576, 0x3183ec92, 0x0de30f9a,
+ 0x49422a82, 0x7522c98a, 0xc00060b2, 0xfc6083ba, 0xb8c1a6a2,
+ 0x84a145aa, 0x09f5f293, 0x3595119b, 0x71343483, 0x4d54d78b,
+ 0xf8767eb3, 0xc4169dbb, 0x80b7b8a3, 0xbcd75bab, 0x416fd090,
+ 0x7d0f3398, 0x39ae1680, 0x05cef588, 0xb0ec5cb0, 0x8c8cbfb8,
+ 0xc82d9aa0, 0xf44d79a8, 0x7919ce91, 0x45792d99, 0x01d80881,
+ 0x3db8eb89, 0x889a42b1, 0xb4faa1b9, 0xf05b84a1, 0xcc3b67a9,
+ 0xd05b9496, 0xec3b779e, 0xa89a5286, 0x94fab18e, 0x21d818b6,
+ 0x1db8fbbe, 0x5919dea6, 0x65793dae, 0xe82d8a97, 0xd44d699f,
+ 0x90ec4c87, 0xac8caf8f, 0x19ae06b7, 0x25cee5bf, 0x616fc0a7,
+ 0x5d0f23af, 0xa0b7a894, 0x9cd74b9c, 0xd8766e84, 0xe4168d8c,
+ 0x513424b4, 0x6d54c7bc, 0x29f5e2a4, 0x159501ac, 0x98c1b695,
+ 0xa4a1559d, 0xe0007085, 0xdc60938d, 0x69423ab5, 0x5522d9bd,
+ 0x1183fca5, 0x2de31fad, 0x29421adb, 0x1522f9d3, 0x5183dccb,
+ 0x6de33fc3, 0xd8c196fb, 0xe4a175f3, 0xa00050eb, 0x9c60b3e3,
+ 0x113404da, 0x2d54e7d2, 0x69f5c2ca, 0x559521c2, 0xe0b788fa,
+ 0xdcd76bf2, 0x98764eea, 0xa416ade2, 0x59ae26d9, 0x65cec5d1,
+ 0x216fe0c9, 0x1d0f03c1, 0xa82daaf9, 0x944d49f1, 0xd0ec6ce9,
+ 0xec8c8fe1, 0x61d838d8, 0x5db8dbd0, 0x1919fec8, 0x25791dc0,
+ 0x905bb4f8, 0xac3b57f0, 0xe89a72e8, 0xd4fa91e0, 0xc89a62df,
+ 0xf4fa81d7, 0xb05ba4cf, 0x8c3b47c7, 0x3919eeff, 0x05790df7,
+ 0x41d828ef, 0x7db8cbe7, 0xf0ec7cde, 0xcc8c9fd6, 0x882dbace,
+ 0xb44d59c6, 0x016ff0fe, 0x3d0f13f6, 0x79ae36ee, 0x45ced5e6,
+ 0xb8765edd, 0x8416bdd5, 0xc0b798cd, 0xfcd77bc5, 0x49f5d2fd,
+ 0x759531f5, 0x313414ed, 0x0d54f7e5, 0x800040dc, 0xbc60a3d4,
+ 0xf8c186cc, 0xc4a165c4, 0x7183ccfc, 0x4de32ff4, 0x09420aec,
+ 0x3522e9e4},
+ {0x00000000, 0x6307d924, 0xc60fb248, 0xa5086b6c, 0x576e62d1,
+ 0x3469bbf5, 0x9161d099, 0xf26609bd, 0xaedcc5a2, 0xcddb1c86,
+ 0x68d377ea, 0x0bd4aece, 0xf9b2a773, 0x9ab57e57, 0x3fbd153b,
+ 0x5cbacc1f, 0x86c88d05, 0xe5cf5421, 0x40c73f4d, 0x23c0e669,
+ 0xd1a6efd4, 0xb2a136f0, 0x17a95d9c, 0x74ae84b8, 0x281448a7,
+ 0x4b139183, 0xee1bfaef, 0x8d1c23cb, 0x7f7a2a76, 0x1c7df352,
+ 0xb975983e, 0xda72411a, 0xd6e01c4b, 0xb5e7c56f, 0x10efae03,
+ 0x73e87727, 0x818e7e9a, 0xe289a7be, 0x4781ccd2, 0x248615f6,
+ 0x783cd9e9, 0x1b3b00cd, 0xbe336ba1, 0xdd34b285, 0x2f52bb38,
+ 0x4c55621c, 0xe95d0970, 0x8a5ad054, 0x5028914e, 0x332f486a,
+ 0x96272306, 0xf520fa22, 0x0746f39f, 0x64412abb, 0xc14941d7,
+ 0xa24e98f3, 0xfef454ec, 0x9df38dc8, 0x38fbe6a4, 0x5bfc3f80,
+ 0xa99a363d, 0xca9def19, 0x6f958475, 0x0c925d51, 0x76b13ed7,
+ 0x15b6e7f3, 0xb0be8c9f, 0xd3b955bb, 0x21df5c06, 0x42d88522,
+ 0xe7d0ee4e, 0x84d7376a, 0xd86dfb75, 0xbb6a2251, 0x1e62493d,
+ 0x7d659019, 0x8f0399a4, 0xec044080, 0x490c2bec, 0x2a0bf2c8,
+ 0xf079b3d2, 0x937e6af6, 0x3676019a, 0x5571d8be, 0xa717d103,
+ 0xc4100827, 0x6118634b, 0x021fba6f, 0x5ea57670, 0x3da2af54,
+ 0x98aac438, 0xfbad1d1c, 0x09cb14a1, 0x6acccd85, 0xcfc4a6e9,
+ 0xacc37fcd, 0xa051229c, 0xc356fbb8, 0x665e90d4, 0x055949f0,
+ 0xf73f404d, 0x94389969, 0x3130f205, 0x52372b21, 0x0e8de73e,
+ 0x6d8a3e1a, 0xc8825576, 0xab858c52, 0x59e385ef, 0x3ae45ccb,
+ 0x9fec37a7, 0xfcebee83, 0x2699af99, 0x459e76bd, 0xe0961dd1,
+ 0x8391c4f5, 0x71f7cd48, 0x12f0146c, 0xb7f87f00, 0xd4ffa624,
+ 0x88456a3b, 0xeb42b31f, 0x4e4ad873, 0x2d4d0157, 0xdf2b08ea,
+ 0xbc2cd1ce, 0x1924baa2, 0x7a236386, 0xed627dae, 0x8e65a48a,
+ 0x2b6dcfe6, 0x486a16c2, 0xba0c1f7f, 0xd90bc65b, 0x7c03ad37,
+ 0x1f047413, 0x43beb80c, 0x20b96128, 0x85b10a44, 0xe6b6d360,
+ 0x14d0dadd, 0x77d703f9, 0xd2df6895, 0xb1d8b1b1, 0x6baaf0ab,
+ 0x08ad298f, 0xada542e3, 0xcea29bc7, 0x3cc4927a, 0x5fc34b5e,
+ 0xfacb2032, 0x99ccf916, 0xc5763509, 0xa671ec2d, 0x03798741,
+ 0x607e5e65, 0x921857d8, 0xf11f8efc, 0x5417e590, 0x37103cb4,
+ 0x3b8261e5, 0x5885b8c1, 0xfd8dd3ad, 0x9e8a0a89, 0x6cec0334,
+ 0x0febda10, 0xaae3b17c, 0xc9e46858, 0x955ea447, 0xf6597d63,
+ 0x5351160f, 0x3056cf2b, 0xc230c696, 0xa1371fb2, 0x043f74de,
+ 0x6738adfa, 0xbd4aece0, 0xde4d35c4, 0x7b455ea8, 0x1842878c,
+ 0xea248e31, 0x89235715, 0x2c2b3c79, 0x4f2ce55d, 0x13962942,
+ 0x7091f066, 0xd5999b0a, 0xb69e422e, 0x44f84b93, 0x27ff92b7,
+ 0x82f7f9db, 0xe1f020ff, 0x9bd34379, 0xf8d49a5d, 0x5ddcf131,
+ 0x3edb2815, 0xccbd21a8, 0xafbaf88c, 0x0ab293e0, 0x69b54ac4,
+ 0x350f86db, 0x56085fff, 0xf3003493, 0x9007edb7, 0x6261e40a,
+ 0x01663d2e, 0xa46e5642, 0xc7698f66, 0x1d1bce7c, 0x7e1c1758,
+ 0xdb147c34, 0xb813a510, 0x4a75acad, 0x29727589, 0x8c7a1ee5,
+ 0xef7dc7c1, 0xb3c70bde, 0xd0c0d2fa, 0x75c8b996, 0x16cf60b2,
+ 0xe4a9690f, 0x87aeb02b, 0x22a6db47, 0x41a10263, 0x4d335f32,
+ 0x2e348616, 0x8b3ced7a, 0xe83b345e, 0x1a5d3de3, 0x795ae4c7,
+ 0xdc528fab, 0xbf55568f, 0xe3ef9a90, 0x80e843b4, 0x25e028d8,
+ 0x46e7f1fc, 0xb481f841, 0xd7862165, 0x728e4a09, 0x1189932d,
+ 0xcbfbd237, 0xa8fc0b13, 0x0df4607f, 0x6ef3b95b, 0x9c95b0e6,
+ 0xff9269c2, 0x5a9a02ae, 0x399ddb8a, 0x65271795, 0x0620ceb1,
+ 0xa328a5dd, 0xc02f7cf9, 0x32497544, 0x514eac60, 0xf446c70c,
+ 0x97411e28},
+ {0x00000000, 0x01b5fd1d, 0x036bfa3a, 0x02de0727, 0x06d7f474,
+ 0x07620969, 0x05bc0e4e, 0x0409f353, 0x0dafe8e8, 0x0c1a15f5,
+ 0x0ec412d2, 0x0f71efcf, 0x0b781c9c, 0x0acde181, 0x0813e6a6,
+ 0x09a61bbb, 0x1b5fd1d0, 0x1aea2ccd, 0x18342bea, 0x1981d6f7,
+ 0x1d8825a4, 0x1c3dd8b9, 0x1ee3df9e, 0x1f562283, 0x16f03938,
+ 0x1745c425, 0x159bc302, 0x142e3e1f, 0x1027cd4c, 0x11923051,
+ 0x134c3776, 0x12f9ca6b, 0x36bfa3a0, 0x370a5ebd, 0x35d4599a,
+ 0x3461a487, 0x306857d4, 0x31ddaac9, 0x3303adee, 0x32b650f3,
+ 0x3b104b48, 0x3aa5b655, 0x387bb172, 0x39ce4c6f, 0x3dc7bf3c,
+ 0x3c724221, 0x3eac4506, 0x3f19b81b, 0x2de07270, 0x2c558f6d,
+ 0x2e8b884a, 0x2f3e7557, 0x2b378604, 0x2a827b19, 0x285c7c3e,
+ 0x29e98123, 0x204f9a98, 0x21fa6785, 0x232460a2, 0x22919dbf,
+ 0x26986eec, 0x272d93f1, 0x25f394d6, 0x244669cb, 0x6d7f4740,
+ 0x6ccaba5d, 0x6e14bd7a, 0x6fa14067, 0x6ba8b334, 0x6a1d4e29,
+ 0x68c3490e, 0x6976b413, 0x60d0afa8, 0x616552b5, 0x63bb5592,
+ 0x620ea88f, 0x66075bdc, 0x67b2a6c1, 0x656ca1e6, 0x64d95cfb,
+ 0x76209690, 0x77956b8d, 0x754b6caa, 0x74fe91b7, 0x70f762e4,
+ 0x71429ff9, 0x739c98de, 0x722965c3, 0x7b8f7e78, 0x7a3a8365,
+ 0x78e48442, 0x7951795f, 0x7d588a0c, 0x7ced7711, 0x7e337036,
+ 0x7f868d2b, 0x5bc0e4e0, 0x5a7519fd, 0x58ab1eda, 0x591ee3c7,
+ 0x5d171094, 0x5ca2ed89, 0x5e7ceaae, 0x5fc917b3, 0x566f0c08,
+ 0x57daf115, 0x5504f632, 0x54b10b2f, 0x50b8f87c, 0x510d0561,
+ 0x53d30246, 0x5266ff5b, 0x409f3530, 0x412ac82d, 0x43f4cf0a,
+ 0x42413217, 0x4648c144, 0x47fd3c59, 0x45233b7e, 0x4496c663,
+ 0x4d30ddd8, 0x4c8520c5, 0x4e5b27e2, 0x4feedaff, 0x4be729ac,
+ 0x4a52d4b1, 0x488cd396, 0x49392e8b, 0xdafe8e80, 0xdb4b739d,
+ 0xd99574ba, 0xd82089a7, 0xdc297af4, 0xdd9c87e9, 0xdf4280ce,
+ 0xdef77dd3, 0xd7516668, 0xd6e49b75, 0xd43a9c52, 0xd58f614f,
+ 0xd186921c, 0xd0336f01, 0xd2ed6826, 0xd358953b, 0xc1a15f50,
+ 0xc014a24d, 0xc2caa56a, 0xc37f5877, 0xc776ab24, 0xc6c35639,
+ 0xc41d511e, 0xc5a8ac03, 0xcc0eb7b8, 0xcdbb4aa5, 0xcf654d82,
+ 0xced0b09f, 0xcad943cc, 0xcb6cbed1, 0xc9b2b9f6, 0xc80744eb,
+ 0xec412d20, 0xedf4d03d, 0xef2ad71a, 0xee9f2a07, 0xea96d954,
+ 0xeb232449, 0xe9fd236e, 0xe848de73, 0xe1eec5c8, 0xe05b38d5,
+ 0xe2853ff2, 0xe330c2ef, 0xe73931bc, 0xe68ccca1, 0xe452cb86,
+ 0xe5e7369b, 0xf71efcf0, 0xf6ab01ed, 0xf47506ca, 0xf5c0fbd7,
+ 0xf1c90884, 0xf07cf599, 0xf2a2f2be, 0xf3170fa3, 0xfab11418,
+ 0xfb04e905, 0xf9daee22, 0xf86f133f, 0xfc66e06c, 0xfdd31d71,
+ 0xff0d1a56, 0xfeb8e74b, 0xb781c9c0, 0xb63434dd, 0xb4ea33fa,
+ 0xb55fcee7, 0xb1563db4, 0xb0e3c0a9, 0xb23dc78e, 0xb3883a93,
+ 0xba2e2128, 0xbb9bdc35, 0xb945db12, 0xb8f0260f, 0xbcf9d55c,
+ 0xbd4c2841, 0xbf922f66, 0xbe27d27b, 0xacde1810, 0xad6be50d,
+ 0xafb5e22a, 0xae001f37, 0xaa09ec64, 0xabbc1179, 0xa962165e,
+ 0xa8d7eb43, 0xa171f0f8, 0xa0c40de5, 0xa21a0ac2, 0xa3aff7df,
+ 0xa7a6048c, 0xa613f991, 0xa4cdfeb6, 0xa57803ab, 0x813e6a60,
+ 0x808b977d, 0x8255905a, 0x83e06d47, 0x87e99e14, 0x865c6309,
+ 0x8482642e, 0x85379933, 0x8c918288, 0x8d247f95, 0x8ffa78b2,
+ 0x8e4f85af, 0x8a4676fc, 0x8bf38be1, 0x892d8cc6, 0x889871db,
+ 0x9a61bbb0, 0x9bd446ad, 0x990a418a, 0x98bfbc97, 0x9cb64fc4,
+ 0x9d03b2d9, 0x9fddb5fe, 0x9e6848e3, 0x97ce5358, 0x967bae45,
+ 0x94a5a962, 0x9510547f, 0x9119a72c, 0x90ac5a31, 0x92725d16,
+ 0x93c7a00b},
+ {0x00000000, 0x6e8c1b41, 0xdd183682, 0xb3942dc3, 0x61416b45,
+ 0x0fcd7004, 0xbc595dc7, 0xd2d54686, 0xc282d68a, 0xac0ecdcb,
+ 0x1f9ae008, 0x7116fb49, 0xa3c3bdcf, 0xcd4fa68e, 0x7edb8b4d,
+ 0x1057900c, 0x5e74ab55, 0x30f8b014, 0x836c9dd7, 0xede08696,
+ 0x3f35c010, 0x51b9db51, 0xe22df692, 0x8ca1edd3, 0x9cf67ddf,
+ 0xf27a669e, 0x41ee4b5d, 0x2f62501c, 0xfdb7169a, 0x933b0ddb,
+ 0x20af2018, 0x4e233b59, 0xbce956aa, 0xd2654deb, 0x61f16028,
+ 0x0f7d7b69, 0xdda83def, 0xb32426ae, 0x00b00b6d, 0x6e3c102c,
+ 0x7e6b8020, 0x10e79b61, 0xa373b6a2, 0xcdffade3, 0x1f2aeb65,
+ 0x71a6f024, 0xc232dde7, 0xacbec6a6, 0xe29dfdff, 0x8c11e6be,
+ 0x3f85cb7d, 0x5109d03c, 0x83dc96ba, 0xed508dfb, 0x5ec4a038,
+ 0x3048bb79, 0x201f2b75, 0x4e933034, 0xfd071df7, 0x938b06b6,
+ 0x415e4030, 0x2fd25b71, 0x9c4676b2, 0xf2ca6df3, 0xa2a3ab15,
+ 0xcc2fb054, 0x7fbb9d97, 0x113786d6, 0xc3e2c050, 0xad6edb11,
+ 0x1efaf6d2, 0x7076ed93, 0x60217d9f, 0x0ead66de, 0xbd394b1d,
+ 0xd3b5505c, 0x016016da, 0x6fec0d9b, 0xdc782058, 0xb2f43b19,
+ 0xfcd70040, 0x925b1b01, 0x21cf36c2, 0x4f432d83, 0x9d966b05,
+ 0xf31a7044, 0x408e5d87, 0x2e0246c6, 0x3e55d6ca, 0x50d9cd8b,
+ 0xe34de048, 0x8dc1fb09, 0x5f14bd8f, 0x3198a6ce, 0x820c8b0d,
+ 0xec80904c, 0x1e4afdbf, 0x70c6e6fe, 0xc352cb3d, 0xadded07c,
+ 0x7f0b96fa, 0x11878dbb, 0xa213a078, 0xcc9fbb39, 0xdcc82b35,
+ 0xb2443074, 0x01d01db7, 0x6f5c06f6, 0xbd894070, 0xd3055b31,
+ 0x609176f2, 0x0e1d6db3, 0x403e56ea, 0x2eb24dab, 0x9d266068,
+ 0xf3aa7b29, 0x217f3daf, 0x4ff326ee, 0xfc670b2d, 0x92eb106c,
+ 0x82bc8060, 0xec309b21, 0x5fa4b6e2, 0x3128ada3, 0xe3fdeb25,
+ 0x8d71f064, 0x3ee5dda7, 0x5069c6e6, 0x9e36506b, 0xf0ba4b2a,
+ 0x432e66e9, 0x2da27da8, 0xff773b2e, 0x91fb206f, 0x226f0dac,
+ 0x4ce316ed, 0x5cb486e1, 0x32389da0, 0x81acb063, 0xef20ab22,
+ 0x3df5eda4, 0x5379f6e5, 0xe0eddb26, 0x8e61c067, 0xc042fb3e,
+ 0xaecee07f, 0x1d5acdbc, 0x73d6d6fd, 0xa103907b, 0xcf8f8b3a,
+ 0x7c1ba6f9, 0x1297bdb8, 0x02c02db4, 0x6c4c36f5, 0xdfd81b36,
+ 0xb1540077, 0x638146f1, 0x0d0d5db0, 0xbe997073, 0xd0156b32,
+ 0x22df06c1, 0x4c531d80, 0xffc73043, 0x914b2b02, 0x439e6d84,
+ 0x2d1276c5, 0x9e865b06, 0xf00a4047, 0xe05dd04b, 0x8ed1cb0a,
+ 0x3d45e6c9, 0x53c9fd88, 0x811cbb0e, 0xef90a04f, 0x5c048d8c,
+ 0x328896cd, 0x7cabad94, 0x1227b6d5, 0xa1b39b16, 0xcf3f8057,
+ 0x1deac6d1, 0x7366dd90, 0xc0f2f053, 0xae7eeb12, 0xbe297b1e,
+ 0xd0a5605f, 0x63314d9c, 0x0dbd56dd, 0xdf68105b, 0xb1e40b1a,
+ 0x027026d9, 0x6cfc3d98, 0x3c95fb7e, 0x5219e03f, 0xe18dcdfc,
+ 0x8f01d6bd, 0x5dd4903b, 0x33588b7a, 0x80cca6b9, 0xee40bdf8,
+ 0xfe172df4, 0x909b36b5, 0x230f1b76, 0x4d830037, 0x9f5646b1,
+ 0xf1da5df0, 0x424e7033, 0x2cc26b72, 0x62e1502b, 0x0c6d4b6a,
+ 0xbff966a9, 0xd1757de8, 0x03a03b6e, 0x6d2c202f, 0xdeb80dec,
+ 0xb03416ad, 0xa06386a1, 0xceef9de0, 0x7d7bb023, 0x13f7ab62,
+ 0xc122ede4, 0xafaef6a5, 0x1c3adb66, 0x72b6c027, 0x807cadd4,
+ 0xeef0b695, 0x5d649b56, 0x33e88017, 0xe13dc691, 0x8fb1ddd0,
+ 0x3c25f013, 0x52a9eb52, 0x42fe7b5e, 0x2c72601f, 0x9fe64ddc,
+ 0xf16a569d, 0x23bf101b, 0x4d330b5a, 0xfea72699, 0x902b3dd8,
+ 0xde080681, 0xb0841dc0, 0x03103003, 0x6d9c2b42, 0xbf496dc4,
+ 0xd1c57685, 0x62515b46, 0x0cdd4007, 0x1c8ad00b, 0x7206cb4a,
+ 0xc192e689, 0xaf1efdc8, 0x7dcbbb4e, 0x1347a00f, 0xa0d38dcc,
+ 0xce5f968d},
+ {0x00000000, 0xe71da697, 0x154a4b6f, 0xf257edf8, 0x2a9496de,
+ 0xcd893049, 0x3fdeddb1, 0xd8c37b26, 0x55292dbc, 0xb2348b2b,
+ 0x406366d3, 0xa77ec044, 0x7fbdbb62, 0x98a01df5, 0x6af7f00d,
+ 0x8dea569a, 0xaa525b78, 0x4d4ffdef, 0xbf181017, 0x5805b680,
+ 0x80c6cda6, 0x67db6b31, 0x958c86c9, 0x7291205e, 0xff7b76c4,
+ 0x1866d053, 0xea313dab, 0x0d2c9b3c, 0xd5efe01a, 0x32f2468d,
+ 0xc0a5ab75, 0x27b80de2, 0x8fd5b0b1, 0x68c81626, 0x9a9ffbde,
+ 0x7d825d49, 0xa541266f, 0x425c80f8, 0xb00b6d00, 0x5716cb97,
+ 0xdafc9d0d, 0x3de13b9a, 0xcfb6d662, 0x28ab70f5, 0xf0680bd3,
+ 0x1775ad44, 0xe52240bc, 0x023fe62b, 0x2587ebc9, 0xc29a4d5e,
+ 0x30cda0a6, 0xd7d00631, 0x0f137d17, 0xe80edb80, 0x1a593678,
+ 0xfd4490ef, 0x70aec675, 0x97b360e2, 0x65e48d1a, 0x82f92b8d,
+ 0x5a3a50ab, 0xbd27f63c, 0x4f701bc4, 0xa86dbd53, 0xc4da6723,
+ 0x23c7c1b4, 0xd1902c4c, 0x368d8adb, 0xee4ef1fd, 0x0953576a,
+ 0xfb04ba92, 0x1c191c05, 0x91f34a9f, 0x76eeec08, 0x84b901f0,
+ 0x63a4a767, 0xbb67dc41, 0x5c7a7ad6, 0xae2d972e, 0x493031b9,
+ 0x6e883c5b, 0x89959acc, 0x7bc27734, 0x9cdfd1a3, 0x441caa85,
+ 0xa3010c12, 0x5156e1ea, 0xb64b477d, 0x3ba111e7, 0xdcbcb770,
+ 0x2eeb5a88, 0xc9f6fc1f, 0x11358739, 0xf62821ae, 0x047fcc56,
+ 0xe3626ac1, 0x4b0fd792, 0xac127105, 0x5e459cfd, 0xb9583a6a,
+ 0x619b414c, 0x8686e7db, 0x74d10a23, 0x93ccacb4, 0x1e26fa2e,
+ 0xf93b5cb9, 0x0b6cb141, 0xec7117d6, 0x34b26cf0, 0xd3afca67,
+ 0x21f8279f, 0xc6e58108, 0xe15d8cea, 0x06402a7d, 0xf417c785,
+ 0x130a6112, 0xcbc91a34, 0x2cd4bca3, 0xde83515b, 0x399ef7cc,
+ 0xb474a156, 0x536907c1, 0xa13eea39, 0x46234cae, 0x9ee03788,
+ 0x79fd911f, 0x8baa7ce7, 0x6cb7da70, 0x52c5c807, 0xb5d86e90,
+ 0x478f8368, 0xa09225ff, 0x78515ed9, 0x9f4cf84e, 0x6d1b15b6,
+ 0x8a06b321, 0x07ece5bb, 0xe0f1432c, 0x12a6aed4, 0xf5bb0843,
+ 0x2d787365, 0xca65d5f2, 0x3832380a, 0xdf2f9e9d, 0xf897937f,
+ 0x1f8a35e8, 0xedddd810, 0x0ac07e87, 0xd20305a1, 0x351ea336,
+ 0xc7494ece, 0x2054e859, 0xadbebec3, 0x4aa31854, 0xb8f4f5ac,
+ 0x5fe9533b, 0x872a281d, 0x60378e8a, 0x92606372, 0x757dc5e5,
+ 0xdd1078b6, 0x3a0dde21, 0xc85a33d9, 0x2f47954e, 0xf784ee68,
+ 0x109948ff, 0xe2cea507, 0x05d30390, 0x8839550a, 0x6f24f39d,
+ 0x9d731e65, 0x7a6eb8f2, 0xa2adc3d4, 0x45b06543, 0xb7e788bb,
+ 0x50fa2e2c, 0x774223ce, 0x905f8559, 0x620868a1, 0x8515ce36,
+ 0x5dd6b510, 0xbacb1387, 0x489cfe7f, 0xaf8158e8, 0x226b0e72,
+ 0xc576a8e5, 0x3721451d, 0xd03ce38a, 0x08ff98ac, 0xefe23e3b,
+ 0x1db5d3c3, 0xfaa87554, 0x961faf24, 0x710209b3, 0x8355e44b,
+ 0x644842dc, 0xbc8b39fa, 0x5b969f6d, 0xa9c17295, 0x4edcd402,
+ 0xc3368298, 0x242b240f, 0xd67cc9f7, 0x31616f60, 0xe9a21446,
+ 0x0ebfb2d1, 0xfce85f29, 0x1bf5f9be, 0x3c4df45c, 0xdb5052cb,
+ 0x2907bf33, 0xce1a19a4, 0x16d96282, 0xf1c4c415, 0x039329ed,
+ 0xe48e8f7a, 0x6964d9e0, 0x8e797f77, 0x7c2e928f, 0x9b333418,
+ 0x43f04f3e, 0xa4ede9a9, 0x56ba0451, 0xb1a7a2c6, 0x19ca1f95,
+ 0xfed7b902, 0x0c8054fa, 0xeb9df26d, 0x335e894b, 0xd4432fdc,
+ 0x2614c224, 0xc10964b3, 0x4ce33229, 0xabfe94be, 0x59a97946,
+ 0xbeb4dfd1, 0x6677a4f7, 0x816a0260, 0x733def98, 0x9420490f,
+ 0xb39844ed, 0x5485e27a, 0xa6d20f82, 0x41cfa915, 0x990cd233,
+ 0x7e1174a4, 0x8c46995c, 0x6b5b3fcb, 0xe6b16951, 0x01accfc6,
+ 0xf3fb223e, 0x14e684a9, 0xcc25ff8f, 0x2b385918, 0xd96fb4e0,
+ 0x3e721277},
+ {0x00000000, 0xa58b900e, 0x9066265d, 0x35edb653, 0xfbbd4afb,
+ 0x5e36daf5, 0x6bdb6ca6, 0xce50fca8, 0x2c0b93b7, 0x898003b9,
+ 0xbc6db5ea, 0x19e625e4, 0xd7b6d94c, 0x723d4942, 0x47d0ff11,
+ 0xe25b6f1f, 0x5817276e, 0xfd9cb760, 0xc8710133, 0x6dfa913d,
+ 0xa3aa6d95, 0x0621fd9b, 0x33cc4bc8, 0x9647dbc6, 0x741cb4d9,
+ 0xd19724d7, 0xe47a9284, 0x41f1028a, 0x8fa1fe22, 0x2a2a6e2c,
+ 0x1fc7d87f, 0xba4c4871, 0xb02e4edc, 0x15a5ded2, 0x20486881,
+ 0x85c3f88f, 0x4b930427, 0xee189429, 0xdbf5227a, 0x7e7eb274,
+ 0x9c25dd6b, 0x39ae4d65, 0x0c43fb36, 0xa9c86b38, 0x67989790,
+ 0xc213079e, 0xf7feb1cd, 0x527521c3, 0xe83969b2, 0x4db2f9bc,
+ 0x785f4fef, 0xddd4dfe1, 0x13842349, 0xb60fb347, 0x83e20514,
+ 0x2669951a, 0xc432fa05, 0x61b96a0b, 0x5454dc58, 0xf1df4c56,
+ 0x3f8fb0fe, 0x9a0420f0, 0xafe996a3, 0x0a6206ad, 0xbb2d9bf9,
+ 0x1ea60bf7, 0x2b4bbda4, 0x8ec02daa, 0x4090d102, 0xe51b410c,
+ 0xd0f6f75f, 0x757d6751, 0x9726084e, 0x32ad9840, 0x07402e13,
+ 0xa2cbbe1d, 0x6c9b42b5, 0xc910d2bb, 0xfcfd64e8, 0x5976f4e6,
+ 0xe33abc97, 0x46b12c99, 0x735c9aca, 0xd6d70ac4, 0x1887f66c,
+ 0xbd0c6662, 0x88e1d031, 0x2d6a403f, 0xcf312f20, 0x6ababf2e,
+ 0x5f57097d, 0xfadc9973, 0x348c65db, 0x9107f5d5, 0xa4ea4386,
+ 0x0161d388, 0x0b03d525, 0xae88452b, 0x9b65f378, 0x3eee6376,
+ 0xf0be9fde, 0x55350fd0, 0x60d8b983, 0xc553298d, 0x27084692,
+ 0x8283d69c, 0xb76e60cf, 0x12e5f0c1, 0xdcb50c69, 0x793e9c67,
+ 0x4cd32a34, 0xe958ba3a, 0x5314f24b, 0xf69f6245, 0xc372d416,
+ 0x66f94418, 0xa8a9b8b0, 0x0d2228be, 0x38cf9eed, 0x9d440ee3,
+ 0x7f1f61fc, 0xda94f1f2, 0xef7947a1, 0x4af2d7af, 0x84a22b07,
+ 0x2129bb09, 0x14c40d5a, 0xb14f9d54, 0xad2a31b3, 0x08a1a1bd,
+ 0x3d4c17ee, 0x98c787e0, 0x56977b48, 0xf31ceb46, 0xc6f15d15,
+ 0x637acd1b, 0x8121a204, 0x24aa320a, 0x11478459, 0xb4cc1457,
+ 0x7a9ce8ff, 0xdf1778f1, 0xeafacea2, 0x4f715eac, 0xf53d16dd,
+ 0x50b686d3, 0x655b3080, 0xc0d0a08e, 0x0e805c26, 0xab0bcc28,
+ 0x9ee67a7b, 0x3b6dea75, 0xd936856a, 0x7cbd1564, 0x4950a337,
+ 0xecdb3339, 0x228bcf91, 0x87005f9f, 0xb2ede9cc, 0x176679c2,
+ 0x1d047f6f, 0xb88fef61, 0x8d625932, 0x28e9c93c, 0xe6b93594,
+ 0x4332a59a, 0x76df13c9, 0xd35483c7, 0x310fecd8, 0x94847cd6,
+ 0xa169ca85, 0x04e25a8b, 0xcab2a623, 0x6f39362d, 0x5ad4807e,
+ 0xff5f1070, 0x45135801, 0xe098c80f, 0xd5757e5c, 0x70feee52,
+ 0xbeae12fa, 0x1b2582f4, 0x2ec834a7, 0x8b43a4a9, 0x6918cbb6,
+ 0xcc935bb8, 0xf97eedeb, 0x5cf57de5, 0x92a5814d, 0x372e1143,
+ 0x02c3a710, 0xa748371e, 0x1607aa4a, 0xb38c3a44, 0x86618c17,
+ 0x23ea1c19, 0xedbae0b1, 0x483170bf, 0x7ddcc6ec, 0xd85756e2,
+ 0x3a0c39fd, 0x9f87a9f3, 0xaa6a1fa0, 0x0fe18fae, 0xc1b17306,
+ 0x643ae308, 0x51d7555b, 0xf45cc555, 0x4e108d24, 0xeb9b1d2a,
+ 0xde76ab79, 0x7bfd3b77, 0xb5adc7df, 0x102657d1, 0x25cbe182,
+ 0x8040718c, 0x621b1e93, 0xc7908e9d, 0xf27d38ce, 0x57f6a8c0,
+ 0x99a65468, 0x3c2dc466, 0x09c07235, 0xac4be23b, 0xa629e496,
+ 0x03a27498, 0x364fc2cb, 0x93c452c5, 0x5d94ae6d, 0xf81f3e63,
+ 0xcdf28830, 0x6879183e, 0x8a227721, 0x2fa9e72f, 0x1a44517c,
+ 0xbfcfc172, 0x719f3dda, 0xd414add4, 0xe1f91b87, 0x44728b89,
+ 0xfe3ec3f8, 0x5bb553f6, 0x6e58e5a5, 0xcbd375ab, 0x05838903,
+ 0xa008190d, 0x95e5af5e, 0x306e3f50, 0xd235504f, 0x77bec041,
+ 0x42537612, 0xe7d8e61c, 0x29881ab4, 0x8c038aba, 0xb9ee3ce9,
+ 0x1c65ace7}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x0e908ba500000000, 0x5d26669000000000,
+ 0x53b6ed3500000000, 0xfb4abdfb00000000, 0xf5da365e00000000,
+ 0xa66cdb6b00000000, 0xa8fc50ce00000000, 0xb7930b2c00000000,
+ 0xb903808900000000, 0xeab56dbc00000000, 0xe425e61900000000,
+ 0x4cd9b6d700000000, 0x42493d7200000000, 0x11ffd04700000000,
+ 0x1f6f5be200000000, 0x6e27175800000000, 0x60b79cfd00000000,
+ 0x330171c800000000, 0x3d91fa6d00000000, 0x956daaa300000000,
+ 0x9bfd210600000000, 0xc84bcc3300000000, 0xc6db479600000000,
+ 0xd9b41c7400000000, 0xd72497d100000000, 0x84927ae400000000,
+ 0x8a02f14100000000, 0x22fea18f00000000, 0x2c6e2a2a00000000,
+ 0x7fd8c71f00000000, 0x71484cba00000000, 0xdc4e2eb000000000,
+ 0xd2dea51500000000, 0x8168482000000000, 0x8ff8c38500000000,
+ 0x2704934b00000000, 0x299418ee00000000, 0x7a22f5db00000000,
+ 0x74b27e7e00000000, 0x6bdd259c00000000, 0x654dae3900000000,
+ 0x36fb430c00000000, 0x386bc8a900000000, 0x9097986700000000,
+ 0x9e0713c200000000, 0xcdb1fef700000000, 0xc321755200000000,
+ 0xb26939e800000000, 0xbcf9b24d00000000, 0xef4f5f7800000000,
+ 0xe1dfd4dd00000000, 0x4923841300000000, 0x47b30fb600000000,
+ 0x1405e28300000000, 0x1a95692600000000, 0x05fa32c400000000,
+ 0x0b6ab96100000000, 0x58dc545400000000, 0x564cdff100000000,
+ 0xfeb08f3f00000000, 0xf020049a00000000, 0xa396e9af00000000,
+ 0xad06620a00000000, 0xf99b2dbb00000000, 0xf70ba61e00000000,
+ 0xa4bd4b2b00000000, 0xaa2dc08e00000000, 0x02d1904000000000,
+ 0x0c411be500000000, 0x5ff7f6d000000000, 0x51677d7500000000,
+ 0x4e08269700000000, 0x4098ad3200000000, 0x132e400700000000,
+ 0x1dbecba200000000, 0xb5429b6c00000000, 0xbbd210c900000000,
+ 0xe864fdfc00000000, 0xe6f4765900000000, 0x97bc3ae300000000,
+ 0x992cb14600000000, 0xca9a5c7300000000, 0xc40ad7d600000000,
+ 0x6cf6871800000000, 0x62660cbd00000000, 0x31d0e18800000000,
+ 0x3f406a2d00000000, 0x202f31cf00000000, 0x2ebfba6a00000000,
+ 0x7d09575f00000000, 0x7399dcfa00000000, 0xdb658c3400000000,
+ 0xd5f5079100000000, 0x8643eaa400000000, 0x88d3610100000000,
+ 0x25d5030b00000000, 0x2b4588ae00000000, 0x78f3659b00000000,
+ 0x7663ee3e00000000, 0xde9fbef000000000, 0xd00f355500000000,
+ 0x83b9d86000000000, 0x8d2953c500000000, 0x9246082700000000,
+ 0x9cd6838200000000, 0xcf606eb700000000, 0xc1f0e51200000000,
+ 0x690cb5dc00000000, 0x679c3e7900000000, 0x342ad34c00000000,
+ 0x3aba58e900000000, 0x4bf2145300000000, 0x45629ff600000000,
+ 0x16d472c300000000, 0x1844f96600000000, 0xb0b8a9a800000000,
+ 0xbe28220d00000000, 0xed9ecf3800000000, 0xe30e449d00000000,
+ 0xfc611f7f00000000, 0xf2f194da00000000, 0xa14779ef00000000,
+ 0xafd7f24a00000000, 0x072ba28400000000, 0x09bb292100000000,
+ 0x5a0dc41400000000, 0x549d4fb100000000, 0xb3312aad00000000,
+ 0xbda1a10800000000, 0xee174c3d00000000, 0xe087c79800000000,
+ 0x487b975600000000, 0x46eb1cf300000000, 0x155df1c600000000,
+ 0x1bcd7a6300000000, 0x04a2218100000000, 0x0a32aa2400000000,
+ 0x5984471100000000, 0x5714ccb400000000, 0xffe89c7a00000000,
+ 0xf17817df00000000, 0xa2cefaea00000000, 0xac5e714f00000000,
+ 0xdd163df500000000, 0xd386b65000000000, 0x80305b6500000000,
+ 0x8ea0d0c000000000, 0x265c800e00000000, 0x28cc0bab00000000,
+ 0x7b7ae69e00000000, 0x75ea6d3b00000000, 0x6a8536d900000000,
+ 0x6415bd7c00000000, 0x37a3504900000000, 0x3933dbec00000000,
+ 0x91cf8b2200000000, 0x9f5f008700000000, 0xcce9edb200000000,
+ 0xc279661700000000, 0x6f7f041d00000000, 0x61ef8fb800000000,
+ 0x3259628d00000000, 0x3cc9e92800000000, 0x9435b9e600000000,
+ 0x9aa5324300000000, 0xc913df7600000000, 0xc78354d300000000,
+ 0xd8ec0f3100000000, 0xd67c849400000000, 0x85ca69a100000000,
+ 0x8b5ae20400000000, 0x23a6b2ca00000000, 0x2d36396f00000000,
+ 0x7e80d45a00000000, 0x70105fff00000000, 0x0158134500000000,
+ 0x0fc898e000000000, 0x5c7e75d500000000, 0x52eefe7000000000,
+ 0xfa12aebe00000000, 0xf482251b00000000, 0xa734c82e00000000,
+ 0xa9a4438b00000000, 0xb6cb186900000000, 0xb85b93cc00000000,
+ 0xebed7ef900000000, 0xe57df55c00000000, 0x4d81a59200000000,
+ 0x43112e3700000000, 0x10a7c30200000000, 0x1e3748a700000000,
+ 0x4aaa071600000000, 0x443a8cb300000000, 0x178c618600000000,
+ 0x191cea2300000000, 0xb1e0baed00000000, 0xbf70314800000000,
+ 0xecc6dc7d00000000, 0xe25657d800000000, 0xfd390c3a00000000,
+ 0xf3a9879f00000000, 0xa01f6aaa00000000, 0xae8fe10f00000000,
+ 0x0673b1c100000000, 0x08e33a6400000000, 0x5b55d75100000000,
+ 0x55c55cf400000000, 0x248d104e00000000, 0x2a1d9beb00000000,
+ 0x79ab76de00000000, 0x773bfd7b00000000, 0xdfc7adb500000000,
+ 0xd157261000000000, 0x82e1cb2500000000, 0x8c71408000000000,
+ 0x931e1b6200000000, 0x9d8e90c700000000, 0xce387df200000000,
+ 0xc0a8f65700000000, 0x6854a69900000000, 0x66c42d3c00000000,
+ 0x3572c00900000000, 0x3be24bac00000000, 0x96e429a600000000,
+ 0x9874a20300000000, 0xcbc24f3600000000, 0xc552c49300000000,
+ 0x6dae945d00000000, 0x633e1ff800000000, 0x3088f2cd00000000,
+ 0x3e18796800000000, 0x2177228a00000000, 0x2fe7a92f00000000,
+ 0x7c51441a00000000, 0x72c1cfbf00000000, 0xda3d9f7100000000,
+ 0xd4ad14d400000000, 0x871bf9e100000000, 0x898b724400000000,
+ 0xf8c33efe00000000, 0xf653b55b00000000, 0xa5e5586e00000000,
+ 0xab75d3cb00000000, 0x0389830500000000, 0x0d1908a000000000,
+ 0x5eafe59500000000, 0x503f6e3000000000, 0x4f5035d200000000,
+ 0x41c0be7700000000, 0x1276534200000000, 0x1ce6d8e700000000,
+ 0xb41a882900000000, 0xba8a038c00000000, 0xe93ceeb900000000,
+ 0xe7ac651c00000000},
+ {0x0000000000000000, 0x97a61de700000000, 0x6f4b4a1500000000,
+ 0xf8ed57f200000000, 0xde96942a00000000, 0x493089cd00000000,
+ 0xb1ddde3f00000000, 0x267bc3d800000000, 0xbc2d295500000000,
+ 0x2b8b34b200000000, 0xd366634000000000, 0x44c07ea700000000,
+ 0x62bbbd7f00000000, 0xf51da09800000000, 0x0df0f76a00000000,
+ 0x9a56ea8d00000000, 0x785b52aa00000000, 0xeffd4f4d00000000,
+ 0x171018bf00000000, 0x80b6055800000000, 0xa6cdc68000000000,
+ 0x316bdb6700000000, 0xc9868c9500000000, 0x5e20917200000000,
+ 0xc4767bff00000000, 0x53d0661800000000, 0xab3d31ea00000000,
+ 0x3c9b2c0d00000000, 0x1ae0efd500000000, 0x8d46f23200000000,
+ 0x75aba5c000000000, 0xe20db82700000000, 0xb1b0d58f00000000,
+ 0x2616c86800000000, 0xdefb9f9a00000000, 0x495d827d00000000,
+ 0x6f2641a500000000, 0xf8805c4200000000, 0x006d0bb000000000,
+ 0x97cb165700000000, 0x0d9dfcda00000000, 0x9a3be13d00000000,
+ 0x62d6b6cf00000000, 0xf570ab2800000000, 0xd30b68f000000000,
+ 0x44ad751700000000, 0xbc4022e500000000, 0x2be63f0200000000,
+ 0xc9eb872500000000, 0x5e4d9ac200000000, 0xa6a0cd3000000000,
+ 0x3106d0d700000000, 0x177d130f00000000, 0x80db0ee800000000,
+ 0x7836591a00000000, 0xef9044fd00000000, 0x75c6ae7000000000,
+ 0xe260b39700000000, 0x1a8de46500000000, 0x8d2bf98200000000,
+ 0xab503a5a00000000, 0x3cf627bd00000000, 0xc41b704f00000000,
+ 0x53bd6da800000000, 0x2367dac400000000, 0xb4c1c72300000000,
+ 0x4c2c90d100000000, 0xdb8a8d3600000000, 0xfdf14eee00000000,
+ 0x6a57530900000000, 0x92ba04fb00000000, 0x051c191c00000000,
+ 0x9f4af39100000000, 0x08ecee7600000000, 0xf001b98400000000,
+ 0x67a7a46300000000, 0x41dc67bb00000000, 0xd67a7a5c00000000,
+ 0x2e972dae00000000, 0xb931304900000000, 0x5b3c886e00000000,
+ 0xcc9a958900000000, 0x3477c27b00000000, 0xa3d1df9c00000000,
+ 0x85aa1c4400000000, 0x120c01a300000000, 0xeae1565100000000,
+ 0x7d474bb600000000, 0xe711a13b00000000, 0x70b7bcdc00000000,
+ 0x885aeb2e00000000, 0x1ffcf6c900000000, 0x3987351100000000,
+ 0xae2128f600000000, 0x56cc7f0400000000, 0xc16a62e300000000,
+ 0x92d70f4b00000000, 0x057112ac00000000, 0xfd9c455e00000000,
+ 0x6a3a58b900000000, 0x4c419b6100000000, 0xdbe7868600000000,
+ 0x230ad17400000000, 0xb4accc9300000000, 0x2efa261e00000000,
+ 0xb95c3bf900000000, 0x41b16c0b00000000, 0xd61771ec00000000,
+ 0xf06cb23400000000, 0x67caafd300000000, 0x9f27f82100000000,
+ 0x0881e5c600000000, 0xea8c5de100000000, 0x7d2a400600000000,
+ 0x85c717f400000000, 0x12610a1300000000, 0x341ac9cb00000000,
+ 0xa3bcd42c00000000, 0x5b5183de00000000, 0xccf79e3900000000,
+ 0x56a174b400000000, 0xc107695300000000, 0x39ea3ea100000000,
+ 0xae4c234600000000, 0x8837e09e00000000, 0x1f91fd7900000000,
+ 0xe77caa8b00000000, 0x70dab76c00000000, 0x07c8c55200000000,
+ 0x906ed8b500000000, 0x68838f4700000000, 0xff2592a000000000,
+ 0xd95e517800000000, 0x4ef84c9f00000000, 0xb6151b6d00000000,
+ 0x21b3068a00000000, 0xbbe5ec0700000000, 0x2c43f1e000000000,
+ 0xd4aea61200000000, 0x4308bbf500000000, 0x6573782d00000000,
+ 0xf2d565ca00000000, 0x0a38323800000000, 0x9d9e2fdf00000000,
+ 0x7f9397f800000000, 0xe8358a1f00000000, 0x10d8dded00000000,
+ 0x877ec00a00000000, 0xa10503d200000000, 0x36a31e3500000000,
+ 0xce4e49c700000000, 0x59e8542000000000, 0xc3bebead00000000,
+ 0x5418a34a00000000, 0xacf5f4b800000000, 0x3b53e95f00000000,
+ 0x1d282a8700000000, 0x8a8e376000000000, 0x7263609200000000,
+ 0xe5c57d7500000000, 0xb67810dd00000000, 0x21de0d3a00000000,
+ 0xd9335ac800000000, 0x4e95472f00000000, 0x68ee84f700000000,
+ 0xff48991000000000, 0x07a5cee200000000, 0x9003d30500000000,
+ 0x0a55398800000000, 0x9df3246f00000000, 0x651e739d00000000,
+ 0xf2b86e7a00000000, 0xd4c3ada200000000, 0x4365b04500000000,
+ 0xbb88e7b700000000, 0x2c2efa5000000000, 0xce23427700000000,
+ 0x59855f9000000000, 0xa168086200000000, 0x36ce158500000000,
+ 0x10b5d65d00000000, 0x8713cbba00000000, 0x7ffe9c4800000000,
+ 0xe85881af00000000, 0x720e6b2200000000, 0xe5a876c500000000,
+ 0x1d45213700000000, 0x8ae33cd000000000, 0xac98ff0800000000,
+ 0x3b3ee2ef00000000, 0xc3d3b51d00000000, 0x5475a8fa00000000,
+ 0x24af1f9600000000, 0xb309027100000000, 0x4be4558300000000,
+ 0xdc42486400000000, 0xfa398bbc00000000, 0x6d9f965b00000000,
+ 0x9572c1a900000000, 0x02d4dc4e00000000, 0x988236c300000000,
+ 0x0f242b2400000000, 0xf7c97cd600000000, 0x606f613100000000,
+ 0x4614a2e900000000, 0xd1b2bf0e00000000, 0x295fe8fc00000000,
+ 0xbef9f51b00000000, 0x5cf44d3c00000000, 0xcb5250db00000000,
+ 0x33bf072900000000, 0xa4191ace00000000, 0x8262d91600000000,
+ 0x15c4c4f100000000, 0xed29930300000000, 0x7a8f8ee400000000,
+ 0xe0d9646900000000, 0x777f798e00000000, 0x8f922e7c00000000,
+ 0x1834339b00000000, 0x3e4ff04300000000, 0xa9e9eda400000000,
+ 0x5104ba5600000000, 0xc6a2a7b100000000, 0x951fca1900000000,
+ 0x02b9d7fe00000000, 0xfa54800c00000000, 0x6df29deb00000000,
+ 0x4b895e3300000000, 0xdc2f43d400000000, 0x24c2142600000000,
+ 0xb36409c100000000, 0x2932e34c00000000, 0xbe94feab00000000,
+ 0x4679a95900000000, 0xd1dfb4be00000000, 0xf7a4776600000000,
+ 0x60026a8100000000, 0x98ef3d7300000000, 0x0f49209400000000,
+ 0xed4498b300000000, 0x7ae2855400000000, 0x820fd2a600000000,
+ 0x15a9cf4100000000, 0x33d20c9900000000, 0xa474117e00000000,
+ 0x5c99468c00000000, 0xcb3f5b6b00000000, 0x5169b1e600000000,
+ 0xc6cfac0100000000, 0x3e22fbf300000000, 0xa984e61400000000,
+ 0x8fff25cc00000000, 0x1859382b00000000, 0xe0b46fd900000000,
+ 0x7712723e00000000},
+ {0x0000000000000000, 0x411b8c6e00000000, 0x823618dd00000000,
+ 0xc32d94b300000000, 0x456b416100000000, 0x0470cd0f00000000,
+ 0xc75d59bc00000000, 0x8646d5d200000000, 0x8ad682c200000000,
+ 0xcbcd0eac00000000, 0x08e09a1f00000000, 0x49fb167100000000,
+ 0xcfbdc3a300000000, 0x8ea64fcd00000000, 0x4d8bdb7e00000000,
+ 0x0c90571000000000, 0x55ab745e00000000, 0x14b0f83000000000,
+ 0xd79d6c8300000000, 0x9686e0ed00000000, 0x10c0353f00000000,
+ 0x51dbb95100000000, 0x92f62de200000000, 0xd3eda18c00000000,
+ 0xdf7df69c00000000, 0x9e667af200000000, 0x5d4bee4100000000,
+ 0x1c50622f00000000, 0x9a16b7fd00000000, 0xdb0d3b9300000000,
+ 0x1820af2000000000, 0x593b234e00000000, 0xaa56e9bc00000000,
+ 0xeb4d65d200000000, 0x2860f16100000000, 0x697b7d0f00000000,
+ 0xef3da8dd00000000, 0xae2624b300000000, 0x6d0bb00000000000,
+ 0x2c103c6e00000000, 0x20806b7e00000000, 0x619be71000000000,
+ 0xa2b673a300000000, 0xe3adffcd00000000, 0x65eb2a1f00000000,
+ 0x24f0a67100000000, 0xe7dd32c200000000, 0xa6c6beac00000000,
+ 0xfffd9de200000000, 0xbee6118c00000000, 0x7dcb853f00000000,
+ 0x3cd0095100000000, 0xba96dc8300000000, 0xfb8d50ed00000000,
+ 0x38a0c45e00000000, 0x79bb483000000000, 0x752b1f2000000000,
+ 0x3430934e00000000, 0xf71d07fd00000000, 0xb6068b9300000000,
+ 0x30405e4100000000, 0x715bd22f00000000, 0xb276469c00000000,
+ 0xf36dcaf200000000, 0x15aba3a200000000, 0x54b02fcc00000000,
+ 0x979dbb7f00000000, 0xd686371100000000, 0x50c0e2c300000000,
+ 0x11db6ead00000000, 0xd2f6fa1e00000000, 0x93ed767000000000,
+ 0x9f7d216000000000, 0xde66ad0e00000000, 0x1d4b39bd00000000,
+ 0x5c50b5d300000000, 0xda16600100000000, 0x9b0dec6f00000000,
+ 0x582078dc00000000, 0x193bf4b200000000, 0x4000d7fc00000000,
+ 0x011b5b9200000000, 0xc236cf2100000000, 0x832d434f00000000,
+ 0x056b969d00000000, 0x44701af300000000, 0x875d8e4000000000,
+ 0xc646022e00000000, 0xcad6553e00000000, 0x8bcdd95000000000,
+ 0x48e04de300000000, 0x09fbc18d00000000, 0x8fbd145f00000000,
+ 0xcea6983100000000, 0x0d8b0c8200000000, 0x4c9080ec00000000,
+ 0xbffd4a1e00000000, 0xfee6c67000000000, 0x3dcb52c300000000,
+ 0x7cd0dead00000000, 0xfa960b7f00000000, 0xbb8d871100000000,
+ 0x78a013a200000000, 0x39bb9fcc00000000, 0x352bc8dc00000000,
+ 0x743044b200000000, 0xb71dd00100000000, 0xf6065c6f00000000,
+ 0x704089bd00000000, 0x315b05d300000000, 0xf276916000000000,
+ 0xb36d1d0e00000000, 0xea563e4000000000, 0xab4db22e00000000,
+ 0x6860269d00000000, 0x297baaf300000000, 0xaf3d7f2100000000,
+ 0xee26f34f00000000, 0x2d0b67fc00000000, 0x6c10eb9200000000,
+ 0x6080bc8200000000, 0x219b30ec00000000, 0xe2b6a45f00000000,
+ 0xa3ad283100000000, 0x25ebfde300000000, 0x64f0718d00000000,
+ 0xa7dde53e00000000, 0xe6c6695000000000, 0x6b50369e00000000,
+ 0x2a4bbaf000000000, 0xe9662e4300000000, 0xa87da22d00000000,
+ 0x2e3b77ff00000000, 0x6f20fb9100000000, 0xac0d6f2200000000,
+ 0xed16e34c00000000, 0xe186b45c00000000, 0xa09d383200000000,
+ 0x63b0ac8100000000, 0x22ab20ef00000000, 0xa4edf53d00000000,
+ 0xe5f6795300000000, 0x26dbede000000000, 0x67c0618e00000000,
+ 0x3efb42c000000000, 0x7fe0ceae00000000, 0xbccd5a1d00000000,
+ 0xfdd6d67300000000, 0x7b9003a100000000, 0x3a8b8fcf00000000,
+ 0xf9a61b7c00000000, 0xb8bd971200000000, 0xb42dc00200000000,
+ 0xf5364c6c00000000, 0x361bd8df00000000, 0x770054b100000000,
+ 0xf146816300000000, 0xb05d0d0d00000000, 0x737099be00000000,
+ 0x326b15d000000000, 0xc106df2200000000, 0x801d534c00000000,
+ 0x4330c7ff00000000, 0x022b4b9100000000, 0x846d9e4300000000,
+ 0xc576122d00000000, 0x065b869e00000000, 0x47400af000000000,
+ 0x4bd05de000000000, 0x0acbd18e00000000, 0xc9e6453d00000000,
+ 0x88fdc95300000000, 0x0ebb1c8100000000, 0x4fa090ef00000000,
+ 0x8c8d045c00000000, 0xcd96883200000000, 0x94adab7c00000000,
+ 0xd5b6271200000000, 0x169bb3a100000000, 0x57803fcf00000000,
+ 0xd1c6ea1d00000000, 0x90dd667300000000, 0x53f0f2c000000000,
+ 0x12eb7eae00000000, 0x1e7b29be00000000, 0x5f60a5d000000000,
+ 0x9c4d316300000000, 0xdd56bd0d00000000, 0x5b1068df00000000,
+ 0x1a0be4b100000000, 0xd926700200000000, 0x983dfc6c00000000,
+ 0x7efb953c00000000, 0x3fe0195200000000, 0xfccd8de100000000,
+ 0xbdd6018f00000000, 0x3b90d45d00000000, 0x7a8b583300000000,
+ 0xb9a6cc8000000000, 0xf8bd40ee00000000, 0xf42d17fe00000000,
+ 0xb5369b9000000000, 0x761b0f2300000000, 0x3700834d00000000,
+ 0xb146569f00000000, 0xf05ddaf100000000, 0x33704e4200000000,
+ 0x726bc22c00000000, 0x2b50e16200000000, 0x6a4b6d0c00000000,
+ 0xa966f9bf00000000, 0xe87d75d100000000, 0x6e3ba00300000000,
+ 0x2f202c6d00000000, 0xec0db8de00000000, 0xad1634b000000000,
+ 0xa18663a000000000, 0xe09defce00000000, 0x23b07b7d00000000,
+ 0x62abf71300000000, 0xe4ed22c100000000, 0xa5f6aeaf00000000,
+ 0x66db3a1c00000000, 0x27c0b67200000000, 0xd4ad7c8000000000,
+ 0x95b6f0ee00000000, 0x569b645d00000000, 0x1780e83300000000,
+ 0x91c63de100000000, 0xd0ddb18f00000000, 0x13f0253c00000000,
+ 0x52eba95200000000, 0x5e7bfe4200000000, 0x1f60722c00000000,
+ 0xdc4de69f00000000, 0x9d566af100000000, 0x1b10bf2300000000,
+ 0x5a0b334d00000000, 0x9926a7fe00000000, 0xd83d2b9000000000,
+ 0x810608de00000000, 0xc01d84b000000000, 0x0330100300000000,
+ 0x422b9c6d00000000, 0xc46d49bf00000000, 0x8576c5d100000000,
+ 0x465b516200000000, 0x0740dd0c00000000, 0x0bd08a1c00000000,
+ 0x4acb067200000000, 0x89e692c100000000, 0xc8fd1eaf00000000,
+ 0x4ebbcb7d00000000, 0x0fa0471300000000, 0xcc8dd3a000000000,
+ 0x8d965fce00000000},
+ {0x0000000000000000, 0x1dfdb50100000000, 0x3afa6b0300000000,
+ 0x2707de0200000000, 0x74f4d70600000000, 0x6909620700000000,
+ 0x4e0ebc0500000000, 0x53f3090400000000, 0xe8e8af0d00000000,
+ 0xf5151a0c00000000, 0xd212c40e00000000, 0xcfef710f00000000,
+ 0x9c1c780b00000000, 0x81e1cd0a00000000, 0xa6e6130800000000,
+ 0xbb1ba60900000000, 0xd0d15f1b00000000, 0xcd2cea1a00000000,
+ 0xea2b341800000000, 0xf7d6811900000000, 0xa425881d00000000,
+ 0xb9d83d1c00000000, 0x9edfe31e00000000, 0x8322561f00000000,
+ 0x3839f01600000000, 0x25c4451700000000, 0x02c39b1500000000,
+ 0x1f3e2e1400000000, 0x4ccd271000000000, 0x5130921100000000,
+ 0x76374c1300000000, 0x6bcaf91200000000, 0xa0a3bf3600000000,
+ 0xbd5e0a3700000000, 0x9a59d43500000000, 0x87a4613400000000,
+ 0xd457683000000000, 0xc9aadd3100000000, 0xeead033300000000,
+ 0xf350b63200000000, 0x484b103b00000000, 0x55b6a53a00000000,
+ 0x72b17b3800000000, 0x6f4cce3900000000, 0x3cbfc73d00000000,
+ 0x2142723c00000000, 0x0645ac3e00000000, 0x1bb8193f00000000,
+ 0x7072e02d00000000, 0x6d8f552c00000000, 0x4a888b2e00000000,
+ 0x57753e2f00000000, 0x0486372b00000000, 0x197b822a00000000,
+ 0x3e7c5c2800000000, 0x2381e92900000000, 0x989a4f2000000000,
+ 0x8567fa2100000000, 0xa260242300000000, 0xbf9d912200000000,
+ 0xec6e982600000000, 0xf1932d2700000000, 0xd694f32500000000,
+ 0xcb69462400000000, 0x40477f6d00000000, 0x5dbaca6c00000000,
+ 0x7abd146e00000000, 0x6740a16f00000000, 0x34b3a86b00000000,
+ 0x294e1d6a00000000, 0x0e49c36800000000, 0x13b4766900000000,
+ 0xa8afd06000000000, 0xb552656100000000, 0x9255bb6300000000,
+ 0x8fa80e6200000000, 0xdc5b076600000000, 0xc1a6b26700000000,
+ 0xe6a16c6500000000, 0xfb5cd96400000000, 0x9096207600000000,
+ 0x8d6b957700000000, 0xaa6c4b7500000000, 0xb791fe7400000000,
+ 0xe462f77000000000, 0xf99f427100000000, 0xde989c7300000000,
+ 0xc365297200000000, 0x787e8f7b00000000, 0x65833a7a00000000,
+ 0x4284e47800000000, 0x5f79517900000000, 0x0c8a587d00000000,
+ 0x1177ed7c00000000, 0x3670337e00000000, 0x2b8d867f00000000,
+ 0xe0e4c05b00000000, 0xfd19755a00000000, 0xda1eab5800000000,
+ 0xc7e31e5900000000, 0x9410175d00000000, 0x89eda25c00000000,
+ 0xaeea7c5e00000000, 0xb317c95f00000000, 0x080c6f5600000000,
+ 0x15f1da5700000000, 0x32f6045500000000, 0x2f0bb15400000000,
+ 0x7cf8b85000000000, 0x61050d5100000000, 0x4602d35300000000,
+ 0x5bff665200000000, 0x30359f4000000000, 0x2dc82a4100000000,
+ 0x0acff44300000000, 0x1732414200000000, 0x44c1484600000000,
+ 0x593cfd4700000000, 0x7e3b234500000000, 0x63c6964400000000,
+ 0xd8dd304d00000000, 0xc520854c00000000, 0xe2275b4e00000000,
+ 0xffdaee4f00000000, 0xac29e74b00000000, 0xb1d4524a00000000,
+ 0x96d38c4800000000, 0x8b2e394900000000, 0x808efeda00000000,
+ 0x9d734bdb00000000, 0xba7495d900000000, 0xa78920d800000000,
+ 0xf47a29dc00000000, 0xe9879cdd00000000, 0xce8042df00000000,
+ 0xd37df7de00000000, 0x686651d700000000, 0x759be4d600000000,
+ 0x529c3ad400000000, 0x4f618fd500000000, 0x1c9286d100000000,
+ 0x016f33d000000000, 0x2668edd200000000, 0x3b9558d300000000,
+ 0x505fa1c100000000, 0x4da214c000000000, 0x6aa5cac200000000,
+ 0x77587fc300000000, 0x24ab76c700000000, 0x3956c3c600000000,
+ 0x1e511dc400000000, 0x03aca8c500000000, 0xb8b70ecc00000000,
+ 0xa54abbcd00000000, 0x824d65cf00000000, 0x9fb0d0ce00000000,
+ 0xcc43d9ca00000000, 0xd1be6ccb00000000, 0xf6b9b2c900000000,
+ 0xeb4407c800000000, 0x202d41ec00000000, 0x3dd0f4ed00000000,
+ 0x1ad72aef00000000, 0x072a9fee00000000, 0x54d996ea00000000,
+ 0x492423eb00000000, 0x6e23fde900000000, 0x73de48e800000000,
+ 0xc8c5eee100000000, 0xd5385be000000000, 0xf23f85e200000000,
+ 0xefc230e300000000, 0xbc3139e700000000, 0xa1cc8ce600000000,
+ 0x86cb52e400000000, 0x9b36e7e500000000, 0xf0fc1ef700000000,
+ 0xed01abf600000000, 0xca0675f400000000, 0xd7fbc0f500000000,
+ 0x8408c9f100000000, 0x99f57cf000000000, 0xbef2a2f200000000,
+ 0xa30f17f300000000, 0x1814b1fa00000000, 0x05e904fb00000000,
+ 0x22eedaf900000000, 0x3f136ff800000000, 0x6ce066fc00000000,
+ 0x711dd3fd00000000, 0x561a0dff00000000, 0x4be7b8fe00000000,
+ 0xc0c981b700000000, 0xdd3434b600000000, 0xfa33eab400000000,
+ 0xe7ce5fb500000000, 0xb43d56b100000000, 0xa9c0e3b000000000,
+ 0x8ec73db200000000, 0x933a88b300000000, 0x28212eba00000000,
+ 0x35dc9bbb00000000, 0x12db45b900000000, 0x0f26f0b800000000,
+ 0x5cd5f9bc00000000, 0x41284cbd00000000, 0x662f92bf00000000,
+ 0x7bd227be00000000, 0x1018deac00000000, 0x0de56bad00000000,
+ 0x2ae2b5af00000000, 0x371f00ae00000000, 0x64ec09aa00000000,
+ 0x7911bcab00000000, 0x5e1662a900000000, 0x43ebd7a800000000,
+ 0xf8f071a100000000, 0xe50dc4a000000000, 0xc20a1aa200000000,
+ 0xdff7afa300000000, 0x8c04a6a700000000, 0x91f913a600000000,
+ 0xb6fecda400000000, 0xab0378a500000000, 0x606a3e8100000000,
+ 0x7d978b8000000000, 0x5a90558200000000, 0x476de08300000000,
+ 0x149ee98700000000, 0x09635c8600000000, 0x2e64828400000000,
+ 0x3399378500000000, 0x8882918c00000000, 0x957f248d00000000,
+ 0xb278fa8f00000000, 0xaf854f8e00000000, 0xfc76468a00000000,
+ 0xe18bf38b00000000, 0xc68c2d8900000000, 0xdb71988800000000,
+ 0xb0bb619a00000000, 0xad46d49b00000000, 0x8a410a9900000000,
+ 0x97bcbf9800000000, 0xc44fb69c00000000, 0xd9b2039d00000000,
+ 0xfeb5dd9f00000000, 0xe348689e00000000, 0x5853ce9700000000,
+ 0x45ae7b9600000000, 0x62a9a59400000000, 0x7f54109500000000,
+ 0x2ca7199100000000, 0x315aac9000000000, 0x165d729200000000,
+ 0x0ba0c79300000000},
+ {0x0000000000000000, 0x24d9076300000000, 0x48b20fc600000000,
+ 0x6c6b08a500000000, 0xd1626e5700000000, 0xf5bb693400000000,
+ 0x99d0619100000000, 0xbd0966f200000000, 0xa2c5dcae00000000,
+ 0x861cdbcd00000000, 0xea77d36800000000, 0xceaed40b00000000,
+ 0x73a7b2f900000000, 0x577eb59a00000000, 0x3b15bd3f00000000,
+ 0x1fccba5c00000000, 0x058dc88600000000, 0x2154cfe500000000,
+ 0x4d3fc74000000000, 0x69e6c02300000000, 0xd4efa6d100000000,
+ 0xf036a1b200000000, 0x9c5da91700000000, 0xb884ae7400000000,
+ 0xa748142800000000, 0x8391134b00000000, 0xeffa1bee00000000,
+ 0xcb231c8d00000000, 0x762a7a7f00000000, 0x52f37d1c00000000,
+ 0x3e9875b900000000, 0x1a4172da00000000, 0x4b1ce0d600000000,
+ 0x6fc5e7b500000000, 0x03aeef1000000000, 0x2777e87300000000,
+ 0x9a7e8e8100000000, 0xbea789e200000000, 0xd2cc814700000000,
+ 0xf615862400000000, 0xe9d93c7800000000, 0xcd003b1b00000000,
+ 0xa16b33be00000000, 0x85b234dd00000000, 0x38bb522f00000000,
+ 0x1c62554c00000000, 0x70095de900000000, 0x54d05a8a00000000,
+ 0x4e91285000000000, 0x6a482f3300000000, 0x0623279600000000,
+ 0x22fa20f500000000, 0x9ff3460700000000, 0xbb2a416400000000,
+ 0xd74149c100000000, 0xf3984ea200000000, 0xec54f4fe00000000,
+ 0xc88df39d00000000, 0xa4e6fb3800000000, 0x803ffc5b00000000,
+ 0x3d369aa900000000, 0x19ef9dca00000000, 0x7584956f00000000,
+ 0x515d920c00000000, 0xd73eb17600000000, 0xf3e7b61500000000,
+ 0x9f8cbeb000000000, 0xbb55b9d300000000, 0x065cdf2100000000,
+ 0x2285d84200000000, 0x4eeed0e700000000, 0x6a37d78400000000,
+ 0x75fb6dd800000000, 0x51226abb00000000, 0x3d49621e00000000,
+ 0x1990657d00000000, 0xa499038f00000000, 0x804004ec00000000,
+ 0xec2b0c4900000000, 0xc8f20b2a00000000, 0xd2b379f000000000,
+ 0xf66a7e9300000000, 0x9a01763600000000, 0xbed8715500000000,
+ 0x03d117a700000000, 0x270810c400000000, 0x4b63186100000000,
+ 0x6fba1f0200000000, 0x7076a55e00000000, 0x54afa23d00000000,
+ 0x38c4aa9800000000, 0x1c1dadfb00000000, 0xa114cb0900000000,
+ 0x85cdcc6a00000000, 0xe9a6c4cf00000000, 0xcd7fc3ac00000000,
+ 0x9c2251a000000000, 0xb8fb56c300000000, 0xd4905e6600000000,
+ 0xf049590500000000, 0x4d403ff700000000, 0x6999389400000000,
+ 0x05f2303100000000, 0x212b375200000000, 0x3ee78d0e00000000,
+ 0x1a3e8a6d00000000, 0x765582c800000000, 0x528c85ab00000000,
+ 0xef85e35900000000, 0xcb5ce43a00000000, 0xa737ec9f00000000,
+ 0x83eeebfc00000000, 0x99af992600000000, 0xbd769e4500000000,
+ 0xd11d96e000000000, 0xf5c4918300000000, 0x48cdf77100000000,
+ 0x6c14f01200000000, 0x007ff8b700000000, 0x24a6ffd400000000,
+ 0x3b6a458800000000, 0x1fb342eb00000000, 0x73d84a4e00000000,
+ 0x57014d2d00000000, 0xea082bdf00000000, 0xced12cbc00000000,
+ 0xa2ba241900000000, 0x8663237a00000000, 0xae7d62ed00000000,
+ 0x8aa4658e00000000, 0xe6cf6d2b00000000, 0xc2166a4800000000,
+ 0x7f1f0cba00000000, 0x5bc60bd900000000, 0x37ad037c00000000,
+ 0x1374041f00000000, 0x0cb8be4300000000, 0x2861b92000000000,
+ 0x440ab18500000000, 0x60d3b6e600000000, 0xdddad01400000000,
+ 0xf903d77700000000, 0x9568dfd200000000, 0xb1b1d8b100000000,
+ 0xabf0aa6b00000000, 0x8f29ad0800000000, 0xe342a5ad00000000,
+ 0xc79ba2ce00000000, 0x7a92c43c00000000, 0x5e4bc35f00000000,
+ 0x3220cbfa00000000, 0x16f9cc9900000000, 0x093576c500000000,
+ 0x2dec71a600000000, 0x4187790300000000, 0x655e7e6000000000,
+ 0xd857189200000000, 0xfc8e1ff100000000, 0x90e5175400000000,
+ 0xb43c103700000000, 0xe561823b00000000, 0xc1b8855800000000,
+ 0xadd38dfd00000000, 0x890a8a9e00000000, 0x3403ec6c00000000,
+ 0x10daeb0f00000000, 0x7cb1e3aa00000000, 0x5868e4c900000000,
+ 0x47a45e9500000000, 0x637d59f600000000, 0x0f16515300000000,
+ 0x2bcf563000000000, 0x96c630c200000000, 0xb21f37a100000000,
+ 0xde743f0400000000, 0xfaad386700000000, 0xe0ec4abd00000000,
+ 0xc4354dde00000000, 0xa85e457b00000000, 0x8c87421800000000,
+ 0x318e24ea00000000, 0x1557238900000000, 0x793c2b2c00000000,
+ 0x5de52c4f00000000, 0x4229961300000000, 0x66f0917000000000,
+ 0x0a9b99d500000000, 0x2e429eb600000000, 0x934bf84400000000,
+ 0xb792ff2700000000, 0xdbf9f78200000000, 0xff20f0e100000000,
+ 0x7943d39b00000000, 0x5d9ad4f800000000, 0x31f1dc5d00000000,
+ 0x1528db3e00000000, 0xa821bdcc00000000, 0x8cf8baaf00000000,
+ 0xe093b20a00000000, 0xc44ab56900000000, 0xdb860f3500000000,
+ 0xff5f085600000000, 0x933400f300000000, 0xb7ed079000000000,
+ 0x0ae4616200000000, 0x2e3d660100000000, 0x42566ea400000000,
+ 0x668f69c700000000, 0x7cce1b1d00000000, 0x58171c7e00000000,
+ 0x347c14db00000000, 0x10a513b800000000, 0xadac754a00000000,
+ 0x8975722900000000, 0xe51e7a8c00000000, 0xc1c77def00000000,
+ 0xde0bc7b300000000, 0xfad2c0d000000000, 0x96b9c87500000000,
+ 0xb260cf1600000000, 0x0f69a9e400000000, 0x2bb0ae8700000000,
+ 0x47dba62200000000, 0x6302a14100000000, 0x325f334d00000000,
+ 0x1686342e00000000, 0x7aed3c8b00000000, 0x5e343be800000000,
+ 0xe33d5d1a00000000, 0xc7e45a7900000000, 0xab8f52dc00000000,
+ 0x8f5655bf00000000, 0x909aefe300000000, 0xb443e88000000000,
+ 0xd828e02500000000, 0xfcf1e74600000000, 0x41f881b400000000,
+ 0x652186d700000000, 0x094a8e7200000000, 0x2d93891100000000,
+ 0x37d2fbcb00000000, 0x130bfca800000000, 0x7f60f40d00000000,
+ 0x5bb9f36e00000000, 0xe6b0959c00000000, 0xc26992ff00000000,
+ 0xae029a5a00000000, 0x8adb9d3900000000, 0x9517276500000000,
+ 0xb1ce200600000000, 0xdda528a300000000, 0xf97c2fc000000000,
+ 0x4475493200000000, 0x60ac4e5100000000, 0x0cc746f400000000,
+ 0x281e419700000000},
+ {0x0000000000000000, 0x08e3603c00000000, 0x10c6c17800000000,
+ 0x1825a14400000000, 0x208c83f100000000, 0x286fe3cd00000000,
+ 0x304a428900000000, 0x38a922b500000000, 0x011e763800000000,
+ 0x09fd160400000000, 0x11d8b74000000000, 0x193bd77c00000000,
+ 0x2192f5c900000000, 0x297195f500000000, 0x315434b100000000,
+ 0x39b7548d00000000, 0x023cec7000000000, 0x0adf8c4c00000000,
+ 0x12fa2d0800000000, 0x1a194d3400000000, 0x22b06f8100000000,
+ 0x2a530fbd00000000, 0x3276aef900000000, 0x3a95cec500000000,
+ 0x03229a4800000000, 0x0bc1fa7400000000, 0x13e45b3000000000,
+ 0x1b073b0c00000000, 0x23ae19b900000000, 0x2b4d798500000000,
+ 0x3368d8c100000000, 0x3b8bb8fd00000000, 0x0478d8e100000000,
+ 0x0c9bb8dd00000000, 0x14be199900000000, 0x1c5d79a500000000,
+ 0x24f45b1000000000, 0x2c173b2c00000000, 0x34329a6800000000,
+ 0x3cd1fa5400000000, 0x0566aed900000000, 0x0d85cee500000000,
+ 0x15a06fa100000000, 0x1d430f9d00000000, 0x25ea2d2800000000,
+ 0x2d094d1400000000, 0x352cec5000000000, 0x3dcf8c6c00000000,
+ 0x0644349100000000, 0x0ea754ad00000000, 0x1682f5e900000000,
+ 0x1e6195d500000000, 0x26c8b76000000000, 0x2e2bd75c00000000,
+ 0x360e761800000000, 0x3eed162400000000, 0x075a42a900000000,
+ 0x0fb9229500000000, 0x179c83d100000000, 0x1f7fe3ed00000000,
+ 0x27d6c15800000000, 0x2f35a16400000000, 0x3710002000000000,
+ 0x3ff3601c00000000, 0x49f6c11800000000, 0x4115a12400000000,
+ 0x5930006000000000, 0x51d3605c00000000, 0x697a42e900000000,
+ 0x619922d500000000, 0x79bc839100000000, 0x715fe3ad00000000,
+ 0x48e8b72000000000, 0x400bd71c00000000, 0x582e765800000000,
+ 0x50cd166400000000, 0x686434d100000000, 0x608754ed00000000,
+ 0x78a2f5a900000000, 0x7041959500000000, 0x4bca2d6800000000,
+ 0x43294d5400000000, 0x5b0cec1000000000, 0x53ef8c2c00000000,
+ 0x6b46ae9900000000, 0x63a5cea500000000, 0x7b806fe100000000,
+ 0x73630fdd00000000, 0x4ad45b5000000000, 0x42373b6c00000000,
+ 0x5a129a2800000000, 0x52f1fa1400000000, 0x6a58d8a100000000,
+ 0x62bbb89d00000000, 0x7a9e19d900000000, 0x727d79e500000000,
+ 0x4d8e19f900000000, 0x456d79c500000000, 0x5d48d88100000000,
+ 0x55abb8bd00000000, 0x6d029a0800000000, 0x65e1fa3400000000,
+ 0x7dc45b7000000000, 0x75273b4c00000000, 0x4c906fc100000000,
+ 0x44730ffd00000000, 0x5c56aeb900000000, 0x54b5ce8500000000,
+ 0x6c1cec3000000000, 0x64ff8c0c00000000, 0x7cda2d4800000000,
+ 0x74394d7400000000, 0x4fb2f58900000000, 0x475195b500000000,
+ 0x5f7434f100000000, 0x579754cd00000000, 0x6f3e767800000000,
+ 0x67dd164400000000, 0x7ff8b70000000000, 0x771bd73c00000000,
+ 0x4eac83b100000000, 0x464fe38d00000000, 0x5e6a42c900000000,
+ 0x568922f500000000, 0x6e20004000000000, 0x66c3607c00000000,
+ 0x7ee6c13800000000, 0x7605a10400000000, 0x92ec833100000000,
+ 0x9a0fe30d00000000, 0x822a424900000000, 0x8ac9227500000000,
+ 0xb26000c000000000, 0xba8360fc00000000, 0xa2a6c1b800000000,
+ 0xaa45a18400000000, 0x93f2f50900000000, 0x9b11953500000000,
+ 0x8334347100000000, 0x8bd7544d00000000, 0xb37e76f800000000,
+ 0xbb9d16c400000000, 0xa3b8b78000000000, 0xab5bd7bc00000000,
+ 0x90d06f4100000000, 0x98330f7d00000000, 0x8016ae3900000000,
+ 0x88f5ce0500000000, 0xb05cecb000000000, 0xb8bf8c8c00000000,
+ 0xa09a2dc800000000, 0xa8794df400000000, 0x91ce197900000000,
+ 0x992d794500000000, 0x8108d80100000000, 0x89ebb83d00000000,
+ 0xb1429a8800000000, 0xb9a1fab400000000, 0xa1845bf000000000,
+ 0xa9673bcc00000000, 0x96945bd000000000, 0x9e773bec00000000,
+ 0x86529aa800000000, 0x8eb1fa9400000000, 0xb618d82100000000,
+ 0xbefbb81d00000000, 0xa6de195900000000, 0xae3d796500000000,
+ 0x978a2de800000000, 0x9f694dd400000000, 0x874cec9000000000,
+ 0x8faf8cac00000000, 0xb706ae1900000000, 0xbfe5ce2500000000,
+ 0xa7c06f6100000000, 0xaf230f5d00000000, 0x94a8b7a000000000,
+ 0x9c4bd79c00000000, 0x846e76d800000000, 0x8c8d16e400000000,
+ 0xb424345100000000, 0xbcc7546d00000000, 0xa4e2f52900000000,
+ 0xac01951500000000, 0x95b6c19800000000, 0x9d55a1a400000000,
+ 0x857000e000000000, 0x8d9360dc00000000, 0xb53a426900000000,
+ 0xbdd9225500000000, 0xa5fc831100000000, 0xad1fe32d00000000,
+ 0xdb1a422900000000, 0xd3f9221500000000, 0xcbdc835100000000,
+ 0xc33fe36d00000000, 0xfb96c1d800000000, 0xf375a1e400000000,
+ 0xeb5000a000000000, 0xe3b3609c00000000, 0xda04341100000000,
+ 0xd2e7542d00000000, 0xcac2f56900000000, 0xc221955500000000,
+ 0xfa88b7e000000000, 0xf26bd7dc00000000, 0xea4e769800000000,
+ 0xe2ad16a400000000, 0xd926ae5900000000, 0xd1c5ce6500000000,
+ 0xc9e06f2100000000, 0xc1030f1d00000000, 0xf9aa2da800000000,
+ 0xf1494d9400000000, 0xe96cecd000000000, 0xe18f8cec00000000,
+ 0xd838d86100000000, 0xd0dbb85d00000000, 0xc8fe191900000000,
+ 0xc01d792500000000, 0xf8b45b9000000000, 0xf0573bac00000000,
+ 0xe8729ae800000000, 0xe091fad400000000, 0xdf629ac800000000,
+ 0xd781faf400000000, 0xcfa45bb000000000, 0xc7473b8c00000000,
+ 0xffee193900000000, 0xf70d790500000000, 0xef28d84100000000,
+ 0xe7cbb87d00000000, 0xde7cecf000000000, 0xd69f8ccc00000000,
+ 0xceba2d8800000000, 0xc6594db400000000, 0xfef06f0100000000,
+ 0xf6130f3d00000000, 0xee36ae7900000000, 0xe6d5ce4500000000,
+ 0xdd5e76b800000000, 0xd5bd168400000000, 0xcd98b7c000000000,
+ 0xc57bd7fc00000000, 0xfdd2f54900000000, 0xf531957500000000,
+ 0xed14343100000000, 0xe5f7540d00000000, 0xdc40008000000000,
+ 0xd4a360bc00000000, 0xcc86c1f800000000, 0xc465a1c400000000,
+ 0xfccc837100000000, 0xf42fe34d00000000, 0xec0a420900000000,
+ 0xe4e9223500000000},
+ {0x0000000000000000, 0xd1e8e70e00000000, 0xa2d1cf1d00000000,
+ 0x7339281300000000, 0x44a39f3b00000000, 0x954b783500000000,
+ 0xe672502600000000, 0x379ab72800000000, 0x88463f7700000000,
+ 0x59aed87900000000, 0x2a97f06a00000000, 0xfb7f176400000000,
+ 0xcce5a04c00000000, 0x1d0d474200000000, 0x6e346f5100000000,
+ 0xbfdc885f00000000, 0x108d7eee00000000, 0xc16599e000000000,
+ 0xb25cb1f300000000, 0x63b456fd00000000, 0x542ee1d500000000,
+ 0x85c606db00000000, 0xf6ff2ec800000000, 0x2717c9c600000000,
+ 0x98cb419900000000, 0x4923a69700000000, 0x3a1a8e8400000000,
+ 0xebf2698a00000000, 0xdc68dea200000000, 0x0d8039ac00000000,
+ 0x7eb911bf00000000, 0xaf51f6b100000000, 0x611c8c0700000000,
+ 0xb0f46b0900000000, 0xc3cd431a00000000, 0x1225a41400000000,
+ 0x25bf133c00000000, 0xf457f43200000000, 0x876edc2100000000,
+ 0x56863b2f00000000, 0xe95ab37000000000, 0x38b2547e00000000,
+ 0x4b8b7c6d00000000, 0x9a639b6300000000, 0xadf92c4b00000000,
+ 0x7c11cb4500000000, 0x0f28e35600000000, 0xdec0045800000000,
+ 0x7191f2e900000000, 0xa07915e700000000, 0xd3403df400000000,
+ 0x02a8dafa00000000, 0x35326dd200000000, 0xe4da8adc00000000,
+ 0x97e3a2cf00000000, 0x460b45c100000000, 0xf9d7cd9e00000000,
+ 0x283f2a9000000000, 0x5b06028300000000, 0x8aeee58d00000000,
+ 0xbd7452a500000000, 0x6c9cb5ab00000000, 0x1fa59db800000000,
+ 0xce4d7ab600000000, 0xc238180f00000000, 0x13d0ff0100000000,
+ 0x60e9d71200000000, 0xb101301c00000000, 0x869b873400000000,
+ 0x5773603a00000000, 0x244a482900000000, 0xf5a2af2700000000,
+ 0x4a7e277800000000, 0x9b96c07600000000, 0xe8afe86500000000,
+ 0x39470f6b00000000, 0x0eddb84300000000, 0xdf355f4d00000000,
+ 0xac0c775e00000000, 0x7de4905000000000, 0xd2b566e100000000,
+ 0x035d81ef00000000, 0x7064a9fc00000000, 0xa18c4ef200000000,
+ 0x9616f9da00000000, 0x47fe1ed400000000, 0x34c736c700000000,
+ 0xe52fd1c900000000, 0x5af3599600000000, 0x8b1bbe9800000000,
+ 0xf822968b00000000, 0x29ca718500000000, 0x1e50c6ad00000000,
+ 0xcfb821a300000000, 0xbc8109b000000000, 0x6d69eebe00000000,
+ 0xa324940800000000, 0x72cc730600000000, 0x01f55b1500000000,
+ 0xd01dbc1b00000000, 0xe7870b3300000000, 0x366fec3d00000000,
+ 0x4556c42e00000000, 0x94be232000000000, 0x2b62ab7f00000000,
+ 0xfa8a4c7100000000, 0x89b3646200000000, 0x585b836c00000000,
+ 0x6fc1344400000000, 0xbe29d34a00000000, 0xcd10fb5900000000,
+ 0x1cf81c5700000000, 0xb3a9eae600000000, 0x62410de800000000,
+ 0x117825fb00000000, 0xc090c2f500000000, 0xf70a75dd00000000,
+ 0x26e292d300000000, 0x55dbbac000000000, 0x84335dce00000000,
+ 0x3befd59100000000, 0xea07329f00000000, 0x993e1a8c00000000,
+ 0x48d6fd8200000000, 0x7f4c4aaa00000000, 0xaea4ada400000000,
+ 0xdd9d85b700000000, 0x0c7562b900000000, 0x8471301e00000000,
+ 0x5599d71000000000, 0x26a0ff0300000000, 0xf748180d00000000,
+ 0xc0d2af2500000000, 0x113a482b00000000, 0x6203603800000000,
+ 0xb3eb873600000000, 0x0c370f6900000000, 0xdddfe86700000000,
+ 0xaee6c07400000000, 0x7f0e277a00000000, 0x4894905200000000,
+ 0x997c775c00000000, 0xea455f4f00000000, 0x3badb84100000000,
+ 0x94fc4ef000000000, 0x4514a9fe00000000, 0x362d81ed00000000,
+ 0xe7c566e300000000, 0xd05fd1cb00000000, 0x01b736c500000000,
+ 0x728e1ed600000000, 0xa366f9d800000000, 0x1cba718700000000,
+ 0xcd52968900000000, 0xbe6bbe9a00000000, 0x6f83599400000000,
+ 0x5819eebc00000000, 0x89f109b200000000, 0xfac821a100000000,
+ 0x2b20c6af00000000, 0xe56dbc1900000000, 0x34855b1700000000,
+ 0x47bc730400000000, 0x9654940a00000000, 0xa1ce232200000000,
+ 0x7026c42c00000000, 0x031fec3f00000000, 0xd2f70b3100000000,
+ 0x6d2b836e00000000, 0xbcc3646000000000, 0xcffa4c7300000000,
+ 0x1e12ab7d00000000, 0x29881c5500000000, 0xf860fb5b00000000,
+ 0x8b59d34800000000, 0x5ab1344600000000, 0xf5e0c2f700000000,
+ 0x240825f900000000, 0x57310dea00000000, 0x86d9eae400000000,
+ 0xb1435dcc00000000, 0x60abbac200000000, 0x139292d100000000,
+ 0xc27a75df00000000, 0x7da6fd8000000000, 0xac4e1a8e00000000,
+ 0xdf77329d00000000, 0x0e9fd59300000000, 0x390562bb00000000,
+ 0xe8ed85b500000000, 0x9bd4ada600000000, 0x4a3c4aa800000000,
+ 0x4649281100000000, 0x97a1cf1f00000000, 0xe498e70c00000000,
+ 0x3570000200000000, 0x02eab72a00000000, 0xd302502400000000,
+ 0xa03b783700000000, 0x71d39f3900000000, 0xce0f176600000000,
+ 0x1fe7f06800000000, 0x6cded87b00000000, 0xbd363f7500000000,
+ 0x8aac885d00000000, 0x5b446f5300000000, 0x287d474000000000,
+ 0xf995a04e00000000, 0x56c456ff00000000, 0x872cb1f100000000,
+ 0xf41599e200000000, 0x25fd7eec00000000, 0x1267c9c400000000,
+ 0xc38f2eca00000000, 0xb0b606d900000000, 0x615ee1d700000000,
+ 0xde82698800000000, 0x0f6a8e8600000000, 0x7c53a69500000000,
+ 0xadbb419b00000000, 0x9a21f6b300000000, 0x4bc911bd00000000,
+ 0x38f039ae00000000, 0xe918dea000000000, 0x2755a41600000000,
+ 0xf6bd431800000000, 0x85846b0b00000000, 0x546c8c0500000000,
+ 0x63f63b2d00000000, 0xb21edc2300000000, 0xc127f43000000000,
+ 0x10cf133e00000000, 0xaf139b6100000000, 0x7efb7c6f00000000,
+ 0x0dc2547c00000000, 0xdc2ab37200000000, 0xebb0045a00000000,
+ 0x3a58e35400000000, 0x4961cb4700000000, 0x98892c4900000000,
+ 0x37d8daf800000000, 0xe6303df600000000, 0x950915e500000000,
+ 0x44e1f2eb00000000, 0x737b45c300000000, 0xa293a2cd00000000,
+ 0xd1aa8ade00000000, 0x00426dd000000000, 0xbf9ee58f00000000,
+ 0x6e76028100000000, 0x1d4f2a9200000000, 0xcca7cd9c00000000,
+ 0xfb3d7ab400000000, 0x2ad59dba00000000, 0x59ecb5a900000000,
+ 0x880452a700000000},
+ {0x0000000000000000, 0xaa05daf100000000, 0x150dc53800000000,
+ 0xbf081fc900000000, 0x2a1a8a7100000000, 0x801f508000000000,
+ 0x3f174f4900000000, 0x951295b800000000, 0x543414e300000000,
+ 0xfe31ce1200000000, 0x4139d1db00000000, 0xeb3c0b2a00000000,
+ 0x7e2e9e9200000000, 0xd42b446300000000, 0x6b235baa00000000,
+ 0xc126815b00000000, 0xe96e591d00000000, 0x436b83ec00000000,
+ 0xfc639c2500000000, 0x566646d400000000, 0xc374d36c00000000,
+ 0x6971099d00000000, 0xd679165400000000, 0x7c7ccca500000000,
+ 0xbd5a4dfe00000000, 0x175f970f00000000, 0xa85788c600000000,
+ 0x0252523700000000, 0x9740c78f00000000, 0x3d451d7e00000000,
+ 0x824d02b700000000, 0x2848d84600000000, 0xd2ddb23a00000000,
+ 0x78d868cb00000000, 0xc7d0770200000000, 0x6dd5adf300000000,
+ 0xf8c7384b00000000, 0x52c2e2ba00000000, 0xedcafd7300000000,
+ 0x47cf278200000000, 0x86e9a6d900000000, 0x2cec7c2800000000,
+ 0x93e463e100000000, 0x39e1b91000000000, 0xacf32ca800000000,
+ 0x06f6f65900000000, 0xb9fee99000000000, 0x13fb336100000000,
+ 0x3bb3eb2700000000, 0x91b631d600000000, 0x2ebe2e1f00000000,
+ 0x84bbf4ee00000000, 0x11a9615600000000, 0xbbacbba700000000,
+ 0x04a4a46e00000000, 0xaea17e9f00000000, 0x6f87ffc400000000,
+ 0xc582253500000000, 0x7a8a3afc00000000, 0xd08fe00d00000000,
+ 0x459d75b500000000, 0xef98af4400000000, 0x5090b08d00000000,
+ 0xfa956a7c00000000, 0xa4bb657500000000, 0x0ebebf8400000000,
+ 0xb1b6a04d00000000, 0x1bb37abc00000000, 0x8ea1ef0400000000,
+ 0x24a435f500000000, 0x9bac2a3c00000000, 0x31a9f0cd00000000,
+ 0xf08f719600000000, 0x5a8aab6700000000, 0xe582b4ae00000000,
+ 0x4f876e5f00000000, 0xda95fbe700000000, 0x7090211600000000,
+ 0xcf983edf00000000, 0x659de42e00000000, 0x4dd53c6800000000,
+ 0xe7d0e69900000000, 0x58d8f95000000000, 0xf2dd23a100000000,
+ 0x67cfb61900000000, 0xcdca6ce800000000, 0x72c2732100000000,
+ 0xd8c7a9d000000000, 0x19e1288b00000000, 0xb3e4f27a00000000,
+ 0x0cecedb300000000, 0xa6e9374200000000, 0x33fba2fa00000000,
+ 0x99fe780b00000000, 0x26f667c200000000, 0x8cf3bd3300000000,
+ 0x7666d74f00000000, 0xdc630dbe00000000, 0x636b127700000000,
+ 0xc96ec88600000000, 0x5c7c5d3e00000000, 0xf67987cf00000000,
+ 0x4971980600000000, 0xe37442f700000000, 0x2252c3ac00000000,
+ 0x8857195d00000000, 0x375f069400000000, 0x9d5adc6500000000,
+ 0x084849dd00000000, 0xa24d932c00000000, 0x1d458ce500000000,
+ 0xb740561400000000, 0x9f088e5200000000, 0x350d54a300000000,
+ 0x8a054b6a00000000, 0x2000919b00000000, 0xb512042300000000,
+ 0x1f17ded200000000, 0xa01fc11b00000000, 0x0a1a1bea00000000,
+ 0xcb3c9ab100000000, 0x6139404000000000, 0xde315f8900000000,
+ 0x7434857800000000, 0xe12610c000000000, 0x4b23ca3100000000,
+ 0xf42bd5f800000000, 0x5e2e0f0900000000, 0x4877cbea00000000,
+ 0xe272111b00000000, 0x5d7a0ed200000000, 0xf77fd42300000000,
+ 0x626d419b00000000, 0xc8689b6a00000000, 0x776084a300000000,
+ 0xdd655e5200000000, 0x1c43df0900000000, 0xb64605f800000000,
+ 0x094e1a3100000000, 0xa34bc0c000000000, 0x3659557800000000,
+ 0x9c5c8f8900000000, 0x2354904000000000, 0x89514ab100000000,
+ 0xa11992f700000000, 0x0b1c480600000000, 0xb41457cf00000000,
+ 0x1e118d3e00000000, 0x8b03188600000000, 0x2106c27700000000,
+ 0x9e0eddbe00000000, 0x340b074f00000000, 0xf52d861400000000,
+ 0x5f285ce500000000, 0xe020432c00000000, 0x4a2599dd00000000,
+ 0xdf370c6500000000, 0x7532d69400000000, 0xca3ac95d00000000,
+ 0x603f13ac00000000, 0x9aaa79d000000000, 0x30afa32100000000,
+ 0x8fa7bce800000000, 0x25a2661900000000, 0xb0b0f3a100000000,
+ 0x1ab5295000000000, 0xa5bd369900000000, 0x0fb8ec6800000000,
+ 0xce9e6d3300000000, 0x649bb7c200000000, 0xdb93a80b00000000,
+ 0x719672fa00000000, 0xe484e74200000000, 0x4e813db300000000,
+ 0xf189227a00000000, 0x5b8cf88b00000000, 0x73c420cd00000000,
+ 0xd9c1fa3c00000000, 0x66c9e5f500000000, 0xcccc3f0400000000,
+ 0x59deaabc00000000, 0xf3db704d00000000, 0x4cd36f8400000000,
+ 0xe6d6b57500000000, 0x27f0342e00000000, 0x8df5eedf00000000,
+ 0x32fdf11600000000, 0x98f82be700000000, 0x0deabe5f00000000,
+ 0xa7ef64ae00000000, 0x18e77b6700000000, 0xb2e2a19600000000,
+ 0xecccae9f00000000, 0x46c9746e00000000, 0xf9c16ba700000000,
+ 0x53c4b15600000000, 0xc6d624ee00000000, 0x6cd3fe1f00000000,
+ 0xd3dbe1d600000000, 0x79de3b2700000000, 0xb8f8ba7c00000000,
+ 0x12fd608d00000000, 0xadf57f4400000000, 0x07f0a5b500000000,
+ 0x92e2300d00000000, 0x38e7eafc00000000, 0x87eff53500000000,
+ 0x2dea2fc400000000, 0x05a2f78200000000, 0xafa72d7300000000,
+ 0x10af32ba00000000, 0xbaaae84b00000000, 0x2fb87df300000000,
+ 0x85bda70200000000, 0x3ab5b8cb00000000, 0x90b0623a00000000,
+ 0x5196e36100000000, 0xfb93399000000000, 0x449b265900000000,
+ 0xee9efca800000000, 0x7b8c691000000000, 0xd189b3e100000000,
+ 0x6e81ac2800000000, 0xc48476d900000000, 0x3e111ca500000000,
+ 0x9414c65400000000, 0x2b1cd99d00000000, 0x8119036c00000000,
+ 0x140b96d400000000, 0xbe0e4c2500000000, 0x010653ec00000000,
+ 0xab03891d00000000, 0x6a25084600000000, 0xc020d2b700000000,
+ 0x7f28cd7e00000000, 0xd52d178f00000000, 0x403f823700000000,
+ 0xea3a58c600000000, 0x5532470f00000000, 0xff379dfe00000000,
+ 0xd77f45b800000000, 0x7d7a9f4900000000, 0xc272808000000000,
+ 0x68775a7100000000, 0xfd65cfc900000000, 0x5760153800000000,
+ 0xe8680af100000000, 0x426dd00000000000, 0x834b515b00000000,
+ 0x294e8baa00000000, 0x9646946300000000, 0x3c434e9200000000,
+ 0xa951db2a00000000, 0x035401db00000000, 0xbc5c1e1200000000,
+ 0x1659c4e300000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87,
+ 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede,
+ 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab,
+ 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c,
+ 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1,
+ 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7,
+ 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e,
+ 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308,
+ 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5,
+ 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472,
+ 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07,
+ 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e,
+ 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa,
+ 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec,
+ 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6,
+ 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0,
+ 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3,
+ 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba,
+ 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf,
+ 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975,
+ 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8,
+ 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde,
+ 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a,
+ 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c,
+ 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1,
+ 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65,
+ 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410,
+ 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649,
+ 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a,
+ 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c,
+ 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946,
+ 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450,
+ 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e,
+ 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857,
+ 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022,
+ 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5,
+ 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758,
+ 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e,
+ 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d,
+ 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b,
+ 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6,
+ 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401,
+ 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74,
+ 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d,
+ 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073,
+ 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65,
+ 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f,
+ 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749,
+ 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a,
+ 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033,
+ 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846,
+ 0x0d7139d7},
+ {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563,
+ 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f,
+ 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875,
+ 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536,
+ 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8,
+ 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43,
+ 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f,
+ 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184,
+ 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a,
+ 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39,
+ 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523,
+ 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f,
+ 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d,
+ 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6,
+ 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b,
+ 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0,
+ 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151,
+ 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d,
+ 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47,
+ 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a,
+ 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964,
+ 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef,
+ 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d,
+ 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6,
+ 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348,
+ 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53,
+ 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449,
+ 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645,
+ 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4,
+ 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f,
+ 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2,
+ 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69,
+ 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46,
+ 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a,
+ 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650,
+ 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13,
+ 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded,
+ 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366,
+ 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57,
+ 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc,
+ 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222,
+ 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61,
+ 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b,
+ 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277,
+ 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558,
+ 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3,
+ 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e,
+ 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5,
+ 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74,
+ 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78,
+ 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262,
+ 0x1c53e98a},
+ {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b,
+ 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40,
+ 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580,
+ 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7,
+ 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a,
+ 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37,
+ 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75,
+ 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218,
+ 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5,
+ 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2,
+ 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02,
+ 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59,
+ 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1,
+ 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c,
+ 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a,
+ 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307,
+ 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486,
+ 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd,
+ 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d,
+ 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2,
+ 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f,
+ 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72,
+ 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8,
+ 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985,
+ 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268,
+ 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94,
+ 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454,
+ 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f,
+ 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e,
+ 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3,
+ 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915,
+ 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778,
+ 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821,
+ 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a,
+ 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba,
+ 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d,
+ 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560,
+ 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d,
+ 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe,
+ 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3,
+ 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e,
+ 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509,
+ 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9,
+ 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92,
+ 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb,
+ 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6,
+ 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50,
+ 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d,
+ 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc,
+ 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7,
+ 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927,
+ 0x3f88e851},
+ {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96,
+ 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8,
+ 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0,
+ 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14,
+ 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7,
+ 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4,
+ 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe,
+ 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad,
+ 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e,
+ 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa,
+ 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2,
+ 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c,
+ 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab,
+ 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8,
+ 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d,
+ 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e,
+ 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7,
+ 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99,
+ 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1,
+ 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690,
+ 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933,
+ 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20,
+ 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf,
+ 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc,
+ 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f,
+ 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92,
+ 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca,
+ 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4,
+ 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd,
+ 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de,
+ 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb,
+ 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8,
+ 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474,
+ 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a,
+ 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252,
+ 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6,
+ 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55,
+ 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846,
+ 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7,
+ 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4,
+ 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47,
+ 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3,
+ 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb,
+ 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5,
+ 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49,
+ 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a,
+ 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f,
+ 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c,
+ 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305,
+ 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b,
+ 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523,
+ 0x3dee8ca6}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x85d996dd, 0x4bb55c60, 0xce6ccabd, 0x966ab9c0,
+ 0x13b32f1d, 0xdddfe5a0, 0x5806737d, 0x6dd3035a, 0xe80a9587,
+ 0x26665f3a, 0xa3bfc9e7, 0xfbb9ba9a, 0x7e602c47, 0xb00ce6fa,
+ 0x35d57027, 0xdaa607b4, 0x5f7f9169, 0x91135bd4, 0x14cacd09,
+ 0x4cccbe74, 0xc91528a9, 0x0779e214, 0x82a074c9, 0xb77504ee,
+ 0x32ac9233, 0xfcc0588e, 0x7919ce53, 0x211fbd2e, 0xa4c62bf3,
+ 0x6aaae14e, 0xef737793, 0xf54b7eb3, 0x7092e86e, 0xbefe22d3,
+ 0x3b27b40e, 0x6321c773, 0xe6f851ae, 0x28949b13, 0xad4d0dce,
+ 0x98987de9, 0x1d41eb34, 0xd32d2189, 0x56f4b754, 0x0ef2c429,
+ 0x8b2b52f4, 0x45479849, 0xc09e0e94, 0x2fed7907, 0xaa34efda,
+ 0x64582567, 0xe181b3ba, 0xb987c0c7, 0x3c5e561a, 0xf2329ca7,
+ 0x77eb0a7a, 0x423e7a5d, 0xc7e7ec80, 0x098b263d, 0x8c52b0e0,
+ 0xd454c39d, 0x518d5540, 0x9fe19ffd, 0x1a380920, 0xab918dbd,
+ 0x2e481b60, 0xe024d1dd, 0x65fd4700, 0x3dfb347d, 0xb822a2a0,
+ 0x764e681d, 0xf397fec0, 0xc6428ee7, 0x439b183a, 0x8df7d287,
+ 0x082e445a, 0x50283727, 0xd5f1a1fa, 0x1b9d6b47, 0x9e44fd9a,
+ 0x71378a09, 0xf4ee1cd4, 0x3a82d669, 0xbf5b40b4, 0xe75d33c9,
+ 0x6284a514, 0xace86fa9, 0x2931f974, 0x1ce48953, 0x993d1f8e,
+ 0x5751d533, 0xd28843ee, 0x8a8e3093, 0x0f57a64e, 0xc13b6cf3,
+ 0x44e2fa2e, 0x5edaf30e, 0xdb0365d3, 0x156faf6e, 0x90b639b3,
+ 0xc8b04ace, 0x4d69dc13, 0x830516ae, 0x06dc8073, 0x3309f054,
+ 0xb6d06689, 0x78bcac34, 0xfd653ae9, 0xa5634994, 0x20badf49,
+ 0xeed615f4, 0x6b0f8329, 0x847cf4ba, 0x01a56267, 0xcfc9a8da,
+ 0x4a103e07, 0x12164d7a, 0x97cfdba7, 0x59a3111a, 0xdc7a87c7,
+ 0xe9aff7e0, 0x6c76613d, 0xa21aab80, 0x27c33d5d, 0x7fc54e20,
+ 0xfa1cd8fd, 0x34701240, 0xb1a9849d, 0x17256aa0, 0x92fcfc7d,
+ 0x5c9036c0, 0xd949a01d, 0x814fd360, 0x049645bd, 0xcafa8f00,
+ 0x4f2319dd, 0x7af669fa, 0xff2fff27, 0x3143359a, 0xb49aa347,
+ 0xec9cd03a, 0x694546e7, 0xa7298c5a, 0x22f01a87, 0xcd836d14,
+ 0x485afbc9, 0x86363174, 0x03efa7a9, 0x5be9d4d4, 0xde304209,
+ 0x105c88b4, 0x95851e69, 0xa0506e4e, 0x2589f893, 0xebe5322e,
+ 0x6e3ca4f3, 0x363ad78e, 0xb3e34153, 0x7d8f8bee, 0xf8561d33,
+ 0xe26e1413, 0x67b782ce, 0xa9db4873, 0x2c02deae, 0x7404add3,
+ 0xf1dd3b0e, 0x3fb1f1b3, 0xba68676e, 0x8fbd1749, 0x0a648194,
+ 0xc4084b29, 0x41d1ddf4, 0x19d7ae89, 0x9c0e3854, 0x5262f2e9,
+ 0xd7bb6434, 0x38c813a7, 0xbd11857a, 0x737d4fc7, 0xf6a4d91a,
+ 0xaea2aa67, 0x2b7b3cba, 0xe517f607, 0x60ce60da, 0x551b10fd,
+ 0xd0c28620, 0x1eae4c9d, 0x9b77da40, 0xc371a93d, 0x46a83fe0,
+ 0x88c4f55d, 0x0d1d6380, 0xbcb4e71d, 0x396d71c0, 0xf701bb7d,
+ 0x72d82da0, 0x2ade5edd, 0xaf07c800, 0x616b02bd, 0xe4b29460,
+ 0xd167e447, 0x54be729a, 0x9ad2b827, 0x1f0b2efa, 0x470d5d87,
+ 0xc2d4cb5a, 0x0cb801e7, 0x8961973a, 0x6612e0a9, 0xe3cb7674,
+ 0x2da7bcc9, 0xa87e2a14, 0xf0785969, 0x75a1cfb4, 0xbbcd0509,
+ 0x3e1493d4, 0x0bc1e3f3, 0x8e18752e, 0x4074bf93, 0xc5ad294e,
+ 0x9dab5a33, 0x1872ccee, 0xd61e0653, 0x53c7908e, 0x49ff99ae,
+ 0xcc260f73, 0x024ac5ce, 0x87935313, 0xdf95206e, 0x5a4cb6b3,
+ 0x94207c0e, 0x11f9ead3, 0x242c9af4, 0xa1f50c29, 0x6f99c694,
+ 0xea405049, 0xb2462334, 0x379fb5e9, 0xf9f37f54, 0x7c2ae989,
+ 0x93599e1a, 0x168008c7, 0xd8ecc27a, 0x5d3554a7, 0x053327da,
+ 0x80eab107, 0x4e867bba, 0xcb5fed67, 0xfe8a9d40, 0x7b530b9d,
+ 0xb53fc120, 0x30e657fd, 0x68e02480, 0xed39b25d, 0x235578e0,
+ 0xa68cee3d},
+ {0x00000000, 0x76e10f9d, 0xadc46ee1, 0xdb25617c, 0x1b8fac19,
+ 0x6d6ea384, 0xb64bc2f8, 0xc0aacd65, 0x361e5933, 0x40ff56ae,
+ 0x9bda37d2, 0xed3b384f, 0x2d91f52a, 0x5b70fab7, 0x80559bcb,
+ 0xf6b49456, 0x6c3cb266, 0x1addbdfb, 0xc1f8dc87, 0xb719d31a,
+ 0x77b31e7f, 0x015211e2, 0xda77709e, 0xac967f03, 0x5a22eb55,
+ 0x2cc3e4c8, 0xf7e685b4, 0x81078a29, 0x41ad474c, 0x374c48d1,
+ 0xec6929ad, 0x9a882630, 0xd87864cd, 0xae996b50, 0x75bc0a2c,
+ 0x035d05b1, 0xc3f7c8d4, 0xb516c749, 0x6e33a635, 0x18d2a9a8,
+ 0xee663dfe, 0x98873263, 0x43a2531f, 0x35435c82, 0xf5e991e7,
+ 0x83089e7a, 0x582dff06, 0x2eccf09b, 0xb444d6ab, 0xc2a5d936,
+ 0x1980b84a, 0x6f61b7d7, 0xafcb7ab2, 0xd92a752f, 0x020f1453,
+ 0x74ee1bce, 0x825a8f98, 0xf4bb8005, 0x2f9ee179, 0x597feee4,
+ 0x99d52381, 0xef342c1c, 0x34114d60, 0x42f042fd, 0xf1f7b941,
+ 0x8716b6dc, 0x5c33d7a0, 0x2ad2d83d, 0xea781558, 0x9c991ac5,
+ 0x47bc7bb9, 0x315d7424, 0xc7e9e072, 0xb108efef, 0x6a2d8e93,
+ 0x1ccc810e, 0xdc664c6b, 0xaa8743f6, 0x71a2228a, 0x07432d17,
+ 0x9dcb0b27, 0xeb2a04ba, 0x300f65c6, 0x46ee6a5b, 0x8644a73e,
+ 0xf0a5a8a3, 0x2b80c9df, 0x5d61c642, 0xabd55214, 0xdd345d89,
+ 0x06113cf5, 0x70f03368, 0xb05afe0d, 0xc6bbf190, 0x1d9e90ec,
+ 0x6b7f9f71, 0x298fdd8c, 0x5f6ed211, 0x844bb36d, 0xf2aabcf0,
+ 0x32007195, 0x44e17e08, 0x9fc41f74, 0xe92510e9, 0x1f9184bf,
+ 0x69708b22, 0xb255ea5e, 0xc4b4e5c3, 0x041e28a6, 0x72ff273b,
+ 0xa9da4647, 0xdf3b49da, 0x45b36fea, 0x33526077, 0xe877010b,
+ 0x9e960e96, 0x5e3cc3f3, 0x28ddcc6e, 0xf3f8ad12, 0x8519a28f,
+ 0x73ad36d9, 0x054c3944, 0xde695838, 0xa88857a5, 0x68229ac0,
+ 0x1ec3955d, 0xc5e6f421, 0xb307fbbc, 0xe2ef7383, 0x940e7c1e,
+ 0x4f2b1d62, 0x39ca12ff, 0xf960df9a, 0x8f81d007, 0x54a4b17b,
+ 0x2245bee6, 0xd4f12ab0, 0xa210252d, 0x79354451, 0x0fd44bcc,
+ 0xcf7e86a9, 0xb99f8934, 0x62bae848, 0x145be7d5, 0x8ed3c1e5,
+ 0xf832ce78, 0x2317af04, 0x55f6a099, 0x955c6dfc, 0xe3bd6261,
+ 0x3898031d, 0x4e790c80, 0xb8cd98d6, 0xce2c974b, 0x1509f637,
+ 0x63e8f9aa, 0xa34234cf, 0xd5a33b52, 0x0e865a2e, 0x786755b3,
+ 0x3a97174e, 0x4c7618d3, 0x975379af, 0xe1b27632, 0x2118bb57,
+ 0x57f9b4ca, 0x8cdcd5b6, 0xfa3dda2b, 0x0c894e7d, 0x7a6841e0,
+ 0xa14d209c, 0xd7ac2f01, 0x1706e264, 0x61e7edf9, 0xbac28c85,
+ 0xcc238318, 0x56aba528, 0x204aaab5, 0xfb6fcbc9, 0x8d8ec454,
+ 0x4d240931, 0x3bc506ac, 0xe0e067d0, 0x9601684d, 0x60b5fc1b,
+ 0x1654f386, 0xcd7192fa, 0xbb909d67, 0x7b3a5002, 0x0ddb5f9f,
+ 0xd6fe3ee3, 0xa01f317e, 0x1318cac2, 0x65f9c55f, 0xbedca423,
+ 0xc83dabbe, 0x089766db, 0x7e766946, 0xa553083a, 0xd3b207a7,
+ 0x250693f1, 0x53e79c6c, 0x88c2fd10, 0xfe23f28d, 0x3e893fe8,
+ 0x48683075, 0x934d5109, 0xe5ac5e94, 0x7f2478a4, 0x09c57739,
+ 0xd2e01645, 0xa40119d8, 0x64abd4bd, 0x124adb20, 0xc96fba5c,
+ 0xbf8eb5c1, 0x493a2197, 0x3fdb2e0a, 0xe4fe4f76, 0x921f40eb,
+ 0x52b58d8e, 0x24548213, 0xff71e36f, 0x8990ecf2, 0xcb60ae0f,
+ 0xbd81a192, 0x66a4c0ee, 0x1045cf73, 0xd0ef0216, 0xa60e0d8b,
+ 0x7d2b6cf7, 0x0bca636a, 0xfd7ef73c, 0x8b9ff8a1, 0x50ba99dd,
+ 0x265b9640, 0xe6f15b25, 0x901054b8, 0x4b3535c4, 0x3dd43a59,
+ 0xa75c1c69, 0xd1bd13f4, 0x0a987288, 0x7c797d15, 0xbcd3b070,
+ 0xca32bfed, 0x1117de91, 0x67f6d10c, 0x9142455a, 0xe7a34ac7,
+ 0x3c862bbb, 0x4a672426, 0x8acde943, 0xfc2ce6de, 0x270987a2,
+ 0x51e8883f},
+ {0x00000000, 0xe8dbfbb9, 0x91b186a8, 0x796a7d11, 0x63657c8a,
+ 0x8bbe8733, 0xf2d4fa22, 0x1a0f019b, 0x87cc89cf, 0x6f177276,
+ 0x167d0f67, 0xfea6f4de, 0xe4a9f545, 0x0c720efc, 0x751873ed,
+ 0x9dc38854, 0x4f9f6244, 0xa74499fd, 0xde2ee4ec, 0x36f51f55,
+ 0x2cfa1ece, 0xc421e577, 0xbd4b9866, 0x559063df, 0xc853eb8b,
+ 0x20881032, 0x59e26d23, 0xb139969a, 0xab369701, 0x43ed6cb8,
+ 0x3a8711a9, 0xd25cea10, 0x9e3ec588, 0x76e53e31, 0x0f8f4320,
+ 0xe754b899, 0xfd5bb902, 0x158042bb, 0x6cea3faa, 0x8431c413,
+ 0x19f24c47, 0xf129b7fe, 0x8843caef, 0x60983156, 0x7a9730cd,
+ 0x924ccb74, 0xeb26b665, 0x03fd4ddc, 0xd1a1a7cc, 0x397a5c75,
+ 0x40102164, 0xa8cbdadd, 0xb2c4db46, 0x5a1f20ff, 0x23755dee,
+ 0xcbaea657, 0x566d2e03, 0xbeb6d5ba, 0xc7dca8ab, 0x2f075312,
+ 0x35085289, 0xddd3a930, 0xa4b9d421, 0x4c622f98, 0x7d7bfbca,
+ 0x95a00073, 0xecca7d62, 0x041186db, 0x1e1e8740, 0xf6c57cf9,
+ 0x8faf01e8, 0x6774fa51, 0xfab77205, 0x126c89bc, 0x6b06f4ad,
+ 0x83dd0f14, 0x99d20e8f, 0x7109f536, 0x08638827, 0xe0b8739e,
+ 0x32e4998e, 0xda3f6237, 0xa3551f26, 0x4b8ee49f, 0x5181e504,
+ 0xb95a1ebd, 0xc03063ac, 0x28eb9815, 0xb5281041, 0x5df3ebf8,
+ 0x249996e9, 0xcc426d50, 0xd64d6ccb, 0x3e969772, 0x47fcea63,
+ 0xaf2711da, 0xe3453e42, 0x0b9ec5fb, 0x72f4b8ea, 0x9a2f4353,
+ 0x802042c8, 0x68fbb971, 0x1191c460, 0xf94a3fd9, 0x6489b78d,
+ 0x8c524c34, 0xf5383125, 0x1de3ca9c, 0x07eccb07, 0xef3730be,
+ 0x965d4daf, 0x7e86b616, 0xacda5c06, 0x4401a7bf, 0x3d6bdaae,
+ 0xd5b02117, 0xcfbf208c, 0x2764db35, 0x5e0ea624, 0xb6d55d9d,
+ 0x2b16d5c9, 0xc3cd2e70, 0xbaa75361, 0x527ca8d8, 0x4873a943,
+ 0xa0a852fa, 0xd9c22feb, 0x3119d452, 0xbbf0874e, 0x532b7cf7,
+ 0x2a4101e6, 0xc29afa5f, 0xd895fbc4, 0x304e007d, 0x49247d6c,
+ 0xa1ff86d5, 0x3c3c0e81, 0xd4e7f538, 0xad8d8829, 0x45567390,
+ 0x5f59720b, 0xb78289b2, 0xcee8f4a3, 0x26330f1a, 0xf46fe50a,
+ 0x1cb41eb3, 0x65de63a2, 0x8d05981b, 0x970a9980, 0x7fd16239,
+ 0x06bb1f28, 0xee60e491, 0x73a36cc5, 0x9b78977c, 0xe212ea6d,
+ 0x0ac911d4, 0x10c6104f, 0xf81debf6, 0x817796e7, 0x69ac6d5e,
+ 0x25ce42c6, 0xcd15b97f, 0xb47fc46e, 0x5ca43fd7, 0x46ab3e4c,
+ 0xae70c5f5, 0xd71ab8e4, 0x3fc1435d, 0xa202cb09, 0x4ad930b0,
+ 0x33b34da1, 0xdb68b618, 0xc167b783, 0x29bc4c3a, 0x50d6312b,
+ 0xb80dca92, 0x6a512082, 0x828adb3b, 0xfbe0a62a, 0x133b5d93,
+ 0x09345c08, 0xe1efa7b1, 0x9885daa0, 0x705e2119, 0xed9da94d,
+ 0x054652f4, 0x7c2c2fe5, 0x94f7d45c, 0x8ef8d5c7, 0x66232e7e,
+ 0x1f49536f, 0xf792a8d6, 0xc68b7c84, 0x2e50873d, 0x573afa2c,
+ 0xbfe10195, 0xa5ee000e, 0x4d35fbb7, 0x345f86a6, 0xdc847d1f,
+ 0x4147f54b, 0xa99c0ef2, 0xd0f673e3, 0x382d885a, 0x222289c1,
+ 0xcaf97278, 0xb3930f69, 0x5b48f4d0, 0x89141ec0, 0x61cfe579,
+ 0x18a59868, 0xf07e63d1, 0xea71624a, 0x02aa99f3, 0x7bc0e4e2,
+ 0x931b1f5b, 0x0ed8970f, 0xe6036cb6, 0x9f6911a7, 0x77b2ea1e,
+ 0x6dbdeb85, 0x8566103c, 0xfc0c6d2d, 0x14d79694, 0x58b5b90c,
+ 0xb06e42b5, 0xc9043fa4, 0x21dfc41d, 0x3bd0c586, 0xd30b3e3f,
+ 0xaa61432e, 0x42bab897, 0xdf7930c3, 0x37a2cb7a, 0x4ec8b66b,
+ 0xa6134dd2, 0xbc1c4c49, 0x54c7b7f0, 0x2dadcae1, 0xc5763158,
+ 0x172adb48, 0xfff120f1, 0x869b5de0, 0x6e40a659, 0x744fa7c2,
+ 0x9c945c7b, 0xe5fe216a, 0x0d25dad3, 0x90e65287, 0x783da93e,
+ 0x0157d42f, 0xe98c2f96, 0xf3832e0d, 0x1b58d5b4, 0x6232a8a5,
+ 0x8ae9531c},
+ {0x00000000, 0x919168ae, 0x6325a087, 0xf2b4c829, 0x874c31d4,
+ 0x16dd597a, 0xe4699153, 0x75f8f9fd, 0x4f9f1373, 0xde0e7bdd,
+ 0x2cbab3f4, 0xbd2bdb5a, 0xc8d322a7, 0x59424a09, 0xabf68220,
+ 0x3a67ea8e, 0x9e3e27e6, 0x0faf4f48, 0xfd1b8761, 0x6c8aefcf,
+ 0x19721632, 0x88e37e9c, 0x7a57b6b5, 0xebc6de1b, 0xd1a13495,
+ 0x40305c3b, 0xb2849412, 0x2315fcbc, 0x56ed0541, 0xc77c6def,
+ 0x35c8a5c6, 0xa459cd68, 0x7d7b3f17, 0xecea57b9, 0x1e5e9f90,
+ 0x8fcff73e, 0xfa370ec3, 0x6ba6666d, 0x9912ae44, 0x0883c6ea,
+ 0x32e42c64, 0xa37544ca, 0x51c18ce3, 0xc050e44d, 0xb5a81db0,
+ 0x2439751e, 0xd68dbd37, 0x471cd599, 0xe34518f1, 0x72d4705f,
+ 0x8060b876, 0x11f1d0d8, 0x64092925, 0xf598418b, 0x072c89a2,
+ 0x96bde10c, 0xacda0b82, 0x3d4b632c, 0xcfffab05, 0x5e6ec3ab,
+ 0x2b963a56, 0xba0752f8, 0x48b39ad1, 0xd922f27f, 0xfaf67e2e,
+ 0x6b671680, 0x99d3dea9, 0x0842b607, 0x7dba4ffa, 0xec2b2754,
+ 0x1e9fef7d, 0x8f0e87d3, 0xb5696d5d, 0x24f805f3, 0xd64ccdda,
+ 0x47dda574, 0x32255c89, 0xa3b43427, 0x5100fc0e, 0xc09194a0,
+ 0x64c859c8, 0xf5593166, 0x07edf94f, 0x967c91e1, 0xe384681c,
+ 0x721500b2, 0x80a1c89b, 0x1130a035, 0x2b574abb, 0xbac62215,
+ 0x4872ea3c, 0xd9e38292, 0xac1b7b6f, 0x3d8a13c1, 0xcf3edbe8,
+ 0x5eafb346, 0x878d4139, 0x161c2997, 0xe4a8e1be, 0x75398910,
+ 0x00c170ed, 0x91501843, 0x63e4d06a, 0xf275b8c4, 0xc812524a,
+ 0x59833ae4, 0xab37f2cd, 0x3aa69a63, 0x4f5e639e, 0xdecf0b30,
+ 0x2c7bc319, 0xbdeaabb7, 0x19b366df, 0x88220e71, 0x7a96c658,
+ 0xeb07aef6, 0x9eff570b, 0x0f6e3fa5, 0xfddaf78c, 0x6c4b9f22,
+ 0x562c75ac, 0xc7bd1d02, 0x3509d52b, 0xa498bd85, 0xd1604478,
+ 0x40f12cd6, 0xb245e4ff, 0x23d48c51, 0xf4edfd5c, 0x657c95f2,
+ 0x97c85ddb, 0x06593575, 0x73a1cc88, 0xe230a426, 0x10846c0f,
+ 0x811504a1, 0xbb72ee2f, 0x2ae38681, 0xd8574ea8, 0x49c62606,
+ 0x3c3edffb, 0xadafb755, 0x5f1b7f7c, 0xce8a17d2, 0x6ad3daba,
+ 0xfb42b214, 0x09f67a3d, 0x98671293, 0xed9feb6e, 0x7c0e83c0,
+ 0x8eba4be9, 0x1f2b2347, 0x254cc9c9, 0xb4dda167, 0x4669694e,
+ 0xd7f801e0, 0xa200f81d, 0x339190b3, 0xc125589a, 0x50b43034,
+ 0x8996c24b, 0x1807aae5, 0xeab362cc, 0x7b220a62, 0x0edaf39f,
+ 0x9f4b9b31, 0x6dff5318, 0xfc6e3bb6, 0xc609d138, 0x5798b996,
+ 0xa52c71bf, 0x34bd1911, 0x4145e0ec, 0xd0d48842, 0x2260406b,
+ 0xb3f128c5, 0x17a8e5ad, 0x86398d03, 0x748d452a, 0xe51c2d84,
+ 0x90e4d479, 0x0175bcd7, 0xf3c174fe, 0x62501c50, 0x5837f6de,
+ 0xc9a69e70, 0x3b125659, 0xaa833ef7, 0xdf7bc70a, 0x4eeaafa4,
+ 0xbc5e678d, 0x2dcf0f23, 0x0e1b8372, 0x9f8aebdc, 0x6d3e23f5,
+ 0xfcaf4b5b, 0x8957b2a6, 0x18c6da08, 0xea721221, 0x7be37a8f,
+ 0x41849001, 0xd015f8af, 0x22a13086, 0xb3305828, 0xc6c8a1d5,
+ 0x5759c97b, 0xa5ed0152, 0x347c69fc, 0x9025a494, 0x01b4cc3a,
+ 0xf3000413, 0x62916cbd, 0x17699540, 0x86f8fdee, 0x744c35c7,
+ 0xe5dd5d69, 0xdfbab7e7, 0x4e2bdf49, 0xbc9f1760, 0x2d0e7fce,
+ 0x58f68633, 0xc967ee9d, 0x3bd326b4, 0xaa424e1a, 0x7360bc65,
+ 0xe2f1d4cb, 0x10451ce2, 0x81d4744c, 0xf42c8db1, 0x65bde51f,
+ 0x97092d36, 0x06984598, 0x3cffaf16, 0xad6ec7b8, 0x5fda0f91,
+ 0xce4b673f, 0xbbb39ec2, 0x2a22f66c, 0xd8963e45, 0x490756eb,
+ 0xed5e9b83, 0x7ccff32d, 0x8e7b3b04, 0x1fea53aa, 0x6a12aa57,
+ 0xfb83c2f9, 0x09370ad0, 0x98a6627e, 0xa2c188f0, 0x3350e05e,
+ 0xc1e42877, 0x507540d9, 0x258db924, 0xb41cd18a, 0x46a819a3,
+ 0xd739710d}};
+
+#endif
+
+#endif
+
+#if N == 5
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xaf449247, 0x85f822cf, 0x2abcb088, 0xd08143df,
+ 0x7fc5d198, 0x55796110, 0xfa3df357, 0x7a7381ff, 0xd53713b8,
+ 0xff8ba330, 0x50cf3177, 0xaaf2c220, 0x05b65067, 0x2f0ae0ef,
+ 0x804e72a8, 0xf4e703fe, 0x5ba391b9, 0x711f2131, 0xde5bb376,
+ 0x24664021, 0x8b22d266, 0xa19e62ee, 0x0edaf0a9, 0x8e948201,
+ 0x21d01046, 0x0b6ca0ce, 0xa4283289, 0x5e15c1de, 0xf1515399,
+ 0xdbede311, 0x74a97156, 0x32bf01bd, 0x9dfb93fa, 0xb7472372,
+ 0x1803b135, 0xe23e4262, 0x4d7ad025, 0x67c660ad, 0xc882f2ea,
+ 0x48cc8042, 0xe7881205, 0xcd34a28d, 0x627030ca, 0x984dc39d,
+ 0x370951da, 0x1db5e152, 0xb2f17315, 0xc6580243, 0x691c9004,
+ 0x43a0208c, 0xece4b2cb, 0x16d9419c, 0xb99dd3db, 0x93216353,
+ 0x3c65f114, 0xbc2b83bc, 0x136f11fb, 0x39d3a173, 0x96973334,
+ 0x6caac063, 0xc3ee5224, 0xe952e2ac, 0x461670eb, 0x657e037a,
+ 0xca3a913d, 0xe08621b5, 0x4fc2b3f2, 0xb5ff40a5, 0x1abbd2e2,
+ 0x3007626a, 0x9f43f02d, 0x1f0d8285, 0xb04910c2, 0x9af5a04a,
+ 0x35b1320d, 0xcf8cc15a, 0x60c8531d, 0x4a74e395, 0xe53071d2,
+ 0x91990084, 0x3edd92c3, 0x1461224b, 0xbb25b00c, 0x4118435b,
+ 0xee5cd11c, 0xc4e06194, 0x6ba4f3d3, 0xebea817b, 0x44ae133c,
+ 0x6e12a3b4, 0xc15631f3, 0x3b6bc2a4, 0x942f50e3, 0xbe93e06b,
+ 0x11d7722c, 0x57c102c7, 0xf8859080, 0xd2392008, 0x7d7db24f,
+ 0x87404118, 0x2804d35f, 0x02b863d7, 0xadfcf190, 0x2db28338,
+ 0x82f6117f, 0xa84aa1f7, 0x070e33b0, 0xfd33c0e7, 0x527752a0,
+ 0x78cbe228, 0xd78f706f, 0xa3260139, 0x0c62937e, 0x26de23f6,
+ 0x899ab1b1, 0x73a742e6, 0xdce3d0a1, 0xf65f6029, 0x591bf26e,
+ 0xd95580c6, 0x76111281, 0x5cada209, 0xf3e9304e, 0x09d4c319,
+ 0xa690515e, 0x8c2ce1d6, 0x23687391, 0xcafc06f4, 0x65b894b3,
+ 0x4f04243b, 0xe040b67c, 0x1a7d452b, 0xb539d76c, 0x9f8567e4,
+ 0x30c1f5a3, 0xb08f870b, 0x1fcb154c, 0x3577a5c4, 0x9a333783,
+ 0x600ec4d4, 0xcf4a5693, 0xe5f6e61b, 0x4ab2745c, 0x3e1b050a,
+ 0x915f974d, 0xbbe327c5, 0x14a7b582, 0xee9a46d5, 0x41ded492,
+ 0x6b62641a, 0xc426f65d, 0x446884f5, 0xeb2c16b2, 0xc190a63a,
+ 0x6ed4347d, 0x94e9c72a, 0x3bad556d, 0x1111e5e5, 0xbe5577a2,
+ 0xf8430749, 0x5707950e, 0x7dbb2586, 0xd2ffb7c1, 0x28c24496,
+ 0x8786d6d1, 0xad3a6659, 0x027ef41e, 0x823086b6, 0x2d7414f1,
+ 0x07c8a479, 0xa88c363e, 0x52b1c569, 0xfdf5572e, 0xd749e7a6,
+ 0x780d75e1, 0x0ca404b7, 0xa3e096f0, 0x895c2678, 0x2618b43f,
+ 0xdc254768, 0x7361d52f, 0x59dd65a7, 0xf699f7e0, 0x76d78548,
+ 0xd993170f, 0xf32fa787, 0x5c6b35c0, 0xa656c697, 0x091254d0,
+ 0x23aee458, 0x8cea761f, 0xaf82058e, 0x00c697c9, 0x2a7a2741,
+ 0x853eb506, 0x7f034651, 0xd047d416, 0xfafb649e, 0x55bff6d9,
+ 0xd5f18471, 0x7ab51636, 0x5009a6be, 0xff4d34f9, 0x0570c7ae,
+ 0xaa3455e9, 0x8088e561, 0x2fcc7726, 0x5b650670, 0xf4219437,
+ 0xde9d24bf, 0x71d9b6f8, 0x8be445af, 0x24a0d7e8, 0x0e1c6760,
+ 0xa158f527, 0x2116878f, 0x8e5215c8, 0xa4eea540, 0x0baa3707,
+ 0xf197c450, 0x5ed35617, 0x746fe69f, 0xdb2b74d8, 0x9d3d0433,
+ 0x32799674, 0x18c526fc, 0xb781b4bb, 0x4dbc47ec, 0xe2f8d5ab,
+ 0xc8446523, 0x6700f764, 0xe74e85cc, 0x480a178b, 0x62b6a703,
+ 0xcdf23544, 0x37cfc613, 0x988b5454, 0xb237e4dc, 0x1d73769b,
+ 0x69da07cd, 0xc69e958a, 0xec222502, 0x4366b745, 0xb95b4412,
+ 0x161fd655, 0x3ca366dd, 0x93e7f49a, 0x13a98632, 0xbced1475,
+ 0x9651a4fd, 0x391536ba, 0xc328c5ed, 0x6c6c57aa, 0x46d0e722,
+ 0xe9947565},
+ {0x00000000, 0x4e890ba9, 0x9d121752, 0xd39b1cfb, 0xe15528e5,
+ 0xafdc234c, 0x7c473fb7, 0x32ce341e, 0x19db578b, 0x57525c22,
+ 0x84c940d9, 0xca404b70, 0xf88e7f6e, 0xb60774c7, 0x659c683c,
+ 0x2b156395, 0x33b6af16, 0x7d3fa4bf, 0xaea4b844, 0xe02db3ed,
+ 0xd2e387f3, 0x9c6a8c5a, 0x4ff190a1, 0x01789b08, 0x2a6df89d,
+ 0x64e4f334, 0xb77fefcf, 0xf9f6e466, 0xcb38d078, 0x85b1dbd1,
+ 0x562ac72a, 0x18a3cc83, 0x676d5e2c, 0x29e45585, 0xfa7f497e,
+ 0xb4f642d7, 0x863876c9, 0xc8b17d60, 0x1b2a619b, 0x55a36a32,
+ 0x7eb609a7, 0x303f020e, 0xe3a41ef5, 0xad2d155c, 0x9fe32142,
+ 0xd16a2aeb, 0x02f13610, 0x4c783db9, 0x54dbf13a, 0x1a52fa93,
+ 0xc9c9e668, 0x8740edc1, 0xb58ed9df, 0xfb07d276, 0x289cce8d,
+ 0x6615c524, 0x4d00a6b1, 0x0389ad18, 0xd012b1e3, 0x9e9bba4a,
+ 0xac558e54, 0xe2dc85fd, 0x31479906, 0x7fce92af, 0xcedabc58,
+ 0x8053b7f1, 0x53c8ab0a, 0x1d41a0a3, 0x2f8f94bd, 0x61069f14,
+ 0xb29d83ef, 0xfc148846, 0xd701ebd3, 0x9988e07a, 0x4a13fc81,
+ 0x049af728, 0x3654c336, 0x78ddc89f, 0xab46d464, 0xe5cfdfcd,
+ 0xfd6c134e, 0xb3e518e7, 0x607e041c, 0x2ef70fb5, 0x1c393bab,
+ 0x52b03002, 0x812b2cf9, 0xcfa22750, 0xe4b744c5, 0xaa3e4f6c,
+ 0x79a55397, 0x372c583e, 0x05e26c20, 0x4b6b6789, 0x98f07b72,
+ 0xd67970db, 0xa9b7e274, 0xe73ee9dd, 0x34a5f526, 0x7a2cfe8f,
+ 0x48e2ca91, 0x066bc138, 0xd5f0ddc3, 0x9b79d66a, 0xb06cb5ff,
+ 0xfee5be56, 0x2d7ea2ad, 0x63f7a904, 0x51399d1a, 0x1fb096b3,
+ 0xcc2b8a48, 0x82a281e1, 0x9a014d62, 0xd48846cb, 0x07135a30,
+ 0x499a5199, 0x7b546587, 0x35dd6e2e, 0xe64672d5, 0xa8cf797c,
+ 0x83da1ae9, 0xcd531140, 0x1ec80dbb, 0x50410612, 0x628f320c,
+ 0x2c0639a5, 0xff9d255e, 0xb1142ef7, 0x46c47ef1, 0x084d7558,
+ 0xdbd669a3, 0x955f620a, 0xa7915614, 0xe9185dbd, 0x3a834146,
+ 0x740a4aef, 0x5f1f297a, 0x119622d3, 0xc20d3e28, 0x8c843581,
+ 0xbe4a019f, 0xf0c30a36, 0x235816cd, 0x6dd11d64, 0x7572d1e7,
+ 0x3bfbda4e, 0xe860c6b5, 0xa6e9cd1c, 0x9427f902, 0xdaaef2ab,
+ 0x0935ee50, 0x47bce5f9, 0x6ca9866c, 0x22208dc5, 0xf1bb913e,
+ 0xbf329a97, 0x8dfcae89, 0xc375a520, 0x10eeb9db, 0x5e67b272,
+ 0x21a920dd, 0x6f202b74, 0xbcbb378f, 0xf2323c26, 0xc0fc0838,
+ 0x8e750391, 0x5dee1f6a, 0x136714c3, 0x38727756, 0x76fb7cff,
+ 0xa5606004, 0xebe96bad, 0xd9275fb3, 0x97ae541a, 0x443548e1,
+ 0x0abc4348, 0x121f8fcb, 0x5c968462, 0x8f0d9899, 0xc1849330,
+ 0xf34aa72e, 0xbdc3ac87, 0x6e58b07c, 0x20d1bbd5, 0x0bc4d840,
+ 0x454dd3e9, 0x96d6cf12, 0xd85fc4bb, 0xea91f0a5, 0xa418fb0c,
+ 0x7783e7f7, 0x390aec5e, 0x881ec2a9, 0xc697c900, 0x150cd5fb,
+ 0x5b85de52, 0x694bea4c, 0x27c2e1e5, 0xf459fd1e, 0xbad0f6b7,
+ 0x91c59522, 0xdf4c9e8b, 0x0cd78270, 0x425e89d9, 0x7090bdc7,
+ 0x3e19b66e, 0xed82aa95, 0xa30ba13c, 0xbba86dbf, 0xf5216616,
+ 0x26ba7aed, 0x68337144, 0x5afd455a, 0x14744ef3, 0xc7ef5208,
+ 0x896659a1, 0xa2733a34, 0xecfa319d, 0x3f612d66, 0x71e826cf,
+ 0x432612d1, 0x0daf1978, 0xde340583, 0x90bd0e2a, 0xef739c85,
+ 0xa1fa972c, 0x72618bd7, 0x3ce8807e, 0x0e26b460, 0x40afbfc9,
+ 0x9334a332, 0xddbda89b, 0xf6a8cb0e, 0xb821c0a7, 0x6bbadc5c,
+ 0x2533d7f5, 0x17fde3eb, 0x5974e842, 0x8aeff4b9, 0xc466ff10,
+ 0xdcc53393, 0x924c383a, 0x41d724c1, 0x0f5e2f68, 0x3d901b76,
+ 0x731910df, 0xa0820c24, 0xee0b078d, 0xc51e6418, 0x8b976fb1,
+ 0x580c734a, 0x168578e3, 0x244b4cfd, 0x6ac24754, 0xb9595baf,
+ 0xf7d05006},
+ {0x00000000, 0x8d88fde2, 0xc060fd85, 0x4de80067, 0x5bb0fd4b,
+ 0xd63800a9, 0x9bd000ce, 0x1658fd2c, 0xb761fa96, 0x3ae90774,
+ 0x77010713, 0xfa89faf1, 0xecd107dd, 0x6159fa3f, 0x2cb1fa58,
+ 0xa13907ba, 0xb5b2f36d, 0x383a0e8f, 0x75d20ee8, 0xf85af30a,
+ 0xee020e26, 0x638af3c4, 0x2e62f3a3, 0xa3ea0e41, 0x02d309fb,
+ 0x8f5bf419, 0xc2b3f47e, 0x4f3b099c, 0x5963f4b0, 0xd4eb0952,
+ 0x99030935, 0x148bf4d7, 0xb014e09b, 0x3d9c1d79, 0x70741d1e,
+ 0xfdfce0fc, 0xeba41dd0, 0x662ce032, 0x2bc4e055, 0xa64c1db7,
+ 0x07751a0d, 0x8afde7ef, 0xc715e788, 0x4a9d1a6a, 0x5cc5e746,
+ 0xd14d1aa4, 0x9ca51ac3, 0x112de721, 0x05a613f6, 0x882eee14,
+ 0xc5c6ee73, 0x484e1391, 0x5e16eebd, 0xd39e135f, 0x9e761338,
+ 0x13feeeda, 0xb2c7e960, 0x3f4f1482, 0x72a714e5, 0xff2fe907,
+ 0xe977142b, 0x64ffe9c9, 0x2917e9ae, 0xa49f144c, 0xbb58c777,
+ 0x36d03a95, 0x7b383af2, 0xf6b0c710, 0xe0e83a3c, 0x6d60c7de,
+ 0x2088c7b9, 0xad003a5b, 0x0c393de1, 0x81b1c003, 0xcc59c064,
+ 0x41d13d86, 0x5789c0aa, 0xda013d48, 0x97e93d2f, 0x1a61c0cd,
+ 0x0eea341a, 0x8362c9f8, 0xce8ac99f, 0x4302347d, 0x555ac951,
+ 0xd8d234b3, 0x953a34d4, 0x18b2c936, 0xb98bce8c, 0x3403336e,
+ 0x79eb3309, 0xf463ceeb, 0xe23b33c7, 0x6fb3ce25, 0x225bce42,
+ 0xafd333a0, 0x0b4c27ec, 0x86c4da0e, 0xcb2cda69, 0x46a4278b,
+ 0x50fcdaa7, 0xdd742745, 0x909c2722, 0x1d14dac0, 0xbc2ddd7a,
+ 0x31a52098, 0x7c4d20ff, 0xf1c5dd1d, 0xe79d2031, 0x6a15ddd3,
+ 0x27fdddb4, 0xaa752056, 0xbefed481, 0x33762963, 0x7e9e2904,
+ 0xf316d4e6, 0xe54e29ca, 0x68c6d428, 0x252ed44f, 0xa8a629ad,
+ 0x099f2e17, 0x8417d3f5, 0xc9ffd392, 0x44772e70, 0x522fd35c,
+ 0xdfa72ebe, 0x924f2ed9, 0x1fc7d33b, 0xadc088af, 0x2048754d,
+ 0x6da0752a, 0xe02888c8, 0xf67075e4, 0x7bf88806, 0x36108861,
+ 0xbb987583, 0x1aa17239, 0x97298fdb, 0xdac18fbc, 0x5749725e,
+ 0x41118f72, 0xcc997290, 0x817172f7, 0x0cf98f15, 0x18727bc2,
+ 0x95fa8620, 0xd8128647, 0x559a7ba5, 0x43c28689, 0xce4a7b6b,
+ 0x83a27b0c, 0x0e2a86ee, 0xaf138154, 0x229b7cb6, 0x6f737cd1,
+ 0xe2fb8133, 0xf4a37c1f, 0x792b81fd, 0x34c3819a, 0xb94b7c78,
+ 0x1dd46834, 0x905c95d6, 0xddb495b1, 0x503c6853, 0x4664957f,
+ 0xcbec689d, 0x860468fa, 0x0b8c9518, 0xaab592a2, 0x273d6f40,
+ 0x6ad56f27, 0xe75d92c5, 0xf1056fe9, 0x7c8d920b, 0x3165926c,
+ 0xbced6f8e, 0xa8669b59, 0x25ee66bb, 0x680666dc, 0xe58e9b3e,
+ 0xf3d66612, 0x7e5e9bf0, 0x33b69b97, 0xbe3e6675, 0x1f0761cf,
+ 0x928f9c2d, 0xdf679c4a, 0x52ef61a8, 0x44b79c84, 0xc93f6166,
+ 0x84d76101, 0x095f9ce3, 0x16984fd8, 0x9b10b23a, 0xd6f8b25d,
+ 0x5b704fbf, 0x4d28b293, 0xc0a04f71, 0x8d484f16, 0x00c0b2f4,
+ 0xa1f9b54e, 0x2c7148ac, 0x619948cb, 0xec11b529, 0xfa494805,
+ 0x77c1b5e7, 0x3a29b580, 0xb7a14862, 0xa32abcb5, 0x2ea24157,
+ 0x634a4130, 0xeec2bcd2, 0xf89a41fe, 0x7512bc1c, 0x38fabc7b,
+ 0xb5724199, 0x144b4623, 0x99c3bbc1, 0xd42bbba6, 0x59a34644,
+ 0x4ffbbb68, 0xc273468a, 0x8f9b46ed, 0x0213bb0f, 0xa68caf43,
+ 0x2b0452a1, 0x66ec52c6, 0xeb64af24, 0xfd3c5208, 0x70b4afea,
+ 0x3d5caf8d, 0xb0d4526f, 0x11ed55d5, 0x9c65a837, 0xd18da850,
+ 0x5c0555b2, 0x4a5da89e, 0xc7d5557c, 0x8a3d551b, 0x07b5a8f9,
+ 0x133e5c2e, 0x9eb6a1cc, 0xd35ea1ab, 0x5ed65c49, 0x488ea165,
+ 0xc5065c87, 0x88ee5ce0, 0x0566a102, 0xa45fa6b8, 0x29d75b5a,
+ 0x643f5b3d, 0xe9b7a6df, 0xffef5bf3, 0x7267a611, 0x3f8fa676,
+ 0xb2075b94},
+ {0x00000000, 0x80f0171f, 0xda91287f, 0x5a613f60, 0x6e5356bf,
+ 0xeea341a0, 0xb4c27ec0, 0x343269df, 0xdca6ad7e, 0x5c56ba61,
+ 0x06378501, 0x86c7921e, 0xb2f5fbc1, 0x3205ecde, 0x6864d3be,
+ 0xe894c4a1, 0x623c5cbd, 0xe2cc4ba2, 0xb8ad74c2, 0x385d63dd,
+ 0x0c6f0a02, 0x8c9f1d1d, 0xd6fe227d, 0x560e3562, 0xbe9af1c3,
+ 0x3e6ae6dc, 0x640bd9bc, 0xe4fbcea3, 0xd0c9a77c, 0x5039b063,
+ 0x0a588f03, 0x8aa8981c, 0xc478b97a, 0x4488ae65, 0x1ee99105,
+ 0x9e19861a, 0xaa2befc5, 0x2adbf8da, 0x70bac7ba, 0xf04ad0a5,
+ 0x18de1404, 0x982e031b, 0xc24f3c7b, 0x42bf2b64, 0x768d42bb,
+ 0xf67d55a4, 0xac1c6ac4, 0x2cec7ddb, 0xa644e5c7, 0x26b4f2d8,
+ 0x7cd5cdb8, 0xfc25daa7, 0xc817b378, 0x48e7a467, 0x12869b07,
+ 0x92768c18, 0x7ae248b9, 0xfa125fa6, 0xa07360c6, 0x208377d9,
+ 0x14b11e06, 0x94410919, 0xce203679, 0x4ed02166, 0x538074b5,
+ 0xd37063aa, 0x89115cca, 0x09e14bd5, 0x3dd3220a, 0xbd233515,
+ 0xe7420a75, 0x67b21d6a, 0x8f26d9cb, 0x0fd6ced4, 0x55b7f1b4,
+ 0xd547e6ab, 0xe1758f74, 0x6185986b, 0x3be4a70b, 0xbb14b014,
+ 0x31bc2808, 0xb14c3f17, 0xeb2d0077, 0x6bdd1768, 0x5fef7eb7,
+ 0xdf1f69a8, 0x857e56c8, 0x058e41d7, 0xed1a8576, 0x6dea9269,
+ 0x378bad09, 0xb77bba16, 0x8349d3c9, 0x03b9c4d6, 0x59d8fbb6,
+ 0xd928eca9, 0x97f8cdcf, 0x1708dad0, 0x4d69e5b0, 0xcd99f2af,
+ 0xf9ab9b70, 0x795b8c6f, 0x233ab30f, 0xa3caa410, 0x4b5e60b1,
+ 0xcbae77ae, 0x91cf48ce, 0x113f5fd1, 0x250d360e, 0xa5fd2111,
+ 0xff9c1e71, 0x7f6c096e, 0xf5c49172, 0x7534866d, 0x2f55b90d,
+ 0xafa5ae12, 0x9b97c7cd, 0x1b67d0d2, 0x4106efb2, 0xc1f6f8ad,
+ 0x29623c0c, 0xa9922b13, 0xf3f31473, 0x7303036c, 0x47316ab3,
+ 0xc7c17dac, 0x9da042cc, 0x1d5055d3, 0xa700e96a, 0x27f0fe75,
+ 0x7d91c115, 0xfd61d60a, 0xc953bfd5, 0x49a3a8ca, 0x13c297aa,
+ 0x933280b5, 0x7ba64414, 0xfb56530b, 0xa1376c6b, 0x21c77b74,
+ 0x15f512ab, 0x950505b4, 0xcf643ad4, 0x4f942dcb, 0xc53cb5d7,
+ 0x45cca2c8, 0x1fad9da8, 0x9f5d8ab7, 0xab6fe368, 0x2b9ff477,
+ 0x71fecb17, 0xf10edc08, 0x199a18a9, 0x996a0fb6, 0xc30b30d6,
+ 0x43fb27c9, 0x77c94e16, 0xf7395909, 0xad586669, 0x2da87176,
+ 0x63785010, 0xe388470f, 0xb9e9786f, 0x39196f70, 0x0d2b06af,
+ 0x8ddb11b0, 0xd7ba2ed0, 0x574a39cf, 0xbfdefd6e, 0x3f2eea71,
+ 0x654fd511, 0xe5bfc20e, 0xd18dabd1, 0x517dbcce, 0x0b1c83ae,
+ 0x8bec94b1, 0x01440cad, 0x81b41bb2, 0xdbd524d2, 0x5b2533cd,
+ 0x6f175a12, 0xefe74d0d, 0xb586726d, 0x35766572, 0xdde2a1d3,
+ 0x5d12b6cc, 0x077389ac, 0x87839eb3, 0xb3b1f76c, 0x3341e073,
+ 0x6920df13, 0xe9d0c80c, 0xf4809ddf, 0x74708ac0, 0x2e11b5a0,
+ 0xaee1a2bf, 0x9ad3cb60, 0x1a23dc7f, 0x4042e31f, 0xc0b2f400,
+ 0x282630a1, 0xa8d627be, 0xf2b718de, 0x72470fc1, 0x4675661e,
+ 0xc6857101, 0x9ce44e61, 0x1c14597e, 0x96bcc162, 0x164cd67d,
+ 0x4c2de91d, 0xccddfe02, 0xf8ef97dd, 0x781f80c2, 0x227ebfa2,
+ 0xa28ea8bd, 0x4a1a6c1c, 0xcaea7b03, 0x908b4463, 0x107b537c,
+ 0x24493aa3, 0xa4b92dbc, 0xfed812dc, 0x7e2805c3, 0x30f824a5,
+ 0xb00833ba, 0xea690cda, 0x6a991bc5, 0x5eab721a, 0xde5b6505,
+ 0x843a5a65, 0x04ca4d7a, 0xec5e89db, 0x6cae9ec4, 0x36cfa1a4,
+ 0xb63fb6bb, 0x820ddf64, 0x02fdc87b, 0x589cf71b, 0xd86ce004,
+ 0x52c47818, 0xd2346f07, 0x88555067, 0x08a54778, 0x3c972ea7,
+ 0xbc6739b8, 0xe60606d8, 0x66f611c7, 0x8e62d566, 0x0e92c279,
+ 0x54f3fd19, 0xd403ea06, 0xe03183d9, 0x60c194c6, 0x3aa0aba6,
+ 0xba50bcb9},
+ {0x00000000, 0x9570d495, 0xf190af6b, 0x64e07bfe, 0x38505897,
+ 0xad208c02, 0xc9c0f7fc, 0x5cb02369, 0x70a0b12e, 0xe5d065bb,
+ 0x81301e45, 0x1440cad0, 0x48f0e9b9, 0xdd803d2c, 0xb96046d2,
+ 0x2c109247, 0xe141625c, 0x7431b6c9, 0x10d1cd37, 0x85a119a2,
+ 0xd9113acb, 0x4c61ee5e, 0x288195a0, 0xbdf14135, 0x91e1d372,
+ 0x049107e7, 0x60717c19, 0xf501a88c, 0xa9b18be5, 0x3cc15f70,
+ 0x5821248e, 0xcd51f01b, 0x19f3c2f9, 0x8c83166c, 0xe8636d92,
+ 0x7d13b907, 0x21a39a6e, 0xb4d34efb, 0xd0333505, 0x4543e190,
+ 0x695373d7, 0xfc23a742, 0x98c3dcbc, 0x0db30829, 0x51032b40,
+ 0xc473ffd5, 0xa093842b, 0x35e350be, 0xf8b2a0a5, 0x6dc27430,
+ 0x09220fce, 0x9c52db5b, 0xc0e2f832, 0x55922ca7, 0x31725759,
+ 0xa40283cc, 0x8812118b, 0x1d62c51e, 0x7982bee0, 0xecf26a75,
+ 0xb042491c, 0x25329d89, 0x41d2e677, 0xd4a232e2, 0x33e785f2,
+ 0xa6975167, 0xc2772a99, 0x5707fe0c, 0x0bb7dd65, 0x9ec709f0,
+ 0xfa27720e, 0x6f57a69b, 0x434734dc, 0xd637e049, 0xb2d79bb7,
+ 0x27a74f22, 0x7b176c4b, 0xee67b8de, 0x8a87c320, 0x1ff717b5,
+ 0xd2a6e7ae, 0x47d6333b, 0x233648c5, 0xb6469c50, 0xeaf6bf39,
+ 0x7f866bac, 0x1b661052, 0x8e16c4c7, 0xa2065680, 0x37768215,
+ 0x5396f9eb, 0xc6e62d7e, 0x9a560e17, 0x0f26da82, 0x6bc6a17c,
+ 0xfeb675e9, 0x2a14470b, 0xbf64939e, 0xdb84e860, 0x4ef43cf5,
+ 0x12441f9c, 0x8734cb09, 0xe3d4b0f7, 0x76a46462, 0x5ab4f625,
+ 0xcfc422b0, 0xab24594e, 0x3e548ddb, 0x62e4aeb2, 0xf7947a27,
+ 0x937401d9, 0x0604d54c, 0xcb552557, 0x5e25f1c2, 0x3ac58a3c,
+ 0xafb55ea9, 0xf3057dc0, 0x6675a955, 0x0295d2ab, 0x97e5063e,
+ 0xbbf59479, 0x2e8540ec, 0x4a653b12, 0xdf15ef87, 0x83a5ccee,
+ 0x16d5187b, 0x72356385, 0xe745b710, 0x67cf0be4, 0xf2bfdf71,
+ 0x965fa48f, 0x032f701a, 0x5f9f5373, 0xcaef87e6, 0xae0ffc18,
+ 0x3b7f288d, 0x176fbaca, 0x821f6e5f, 0xe6ff15a1, 0x738fc134,
+ 0x2f3fe25d, 0xba4f36c8, 0xdeaf4d36, 0x4bdf99a3, 0x868e69b8,
+ 0x13febd2d, 0x771ec6d3, 0xe26e1246, 0xbede312f, 0x2baee5ba,
+ 0x4f4e9e44, 0xda3e4ad1, 0xf62ed896, 0x635e0c03, 0x07be77fd,
+ 0x92cea368, 0xce7e8001, 0x5b0e5494, 0x3fee2f6a, 0xaa9efbff,
+ 0x7e3cc91d, 0xeb4c1d88, 0x8fac6676, 0x1adcb2e3, 0x466c918a,
+ 0xd31c451f, 0xb7fc3ee1, 0x228cea74, 0x0e9c7833, 0x9becaca6,
+ 0xff0cd758, 0x6a7c03cd, 0x36cc20a4, 0xa3bcf431, 0xc75c8fcf,
+ 0x522c5b5a, 0x9f7dab41, 0x0a0d7fd4, 0x6eed042a, 0xfb9dd0bf,
+ 0xa72df3d6, 0x325d2743, 0x56bd5cbd, 0xc3cd8828, 0xefdd1a6f,
+ 0x7aadcefa, 0x1e4db504, 0x8b3d6191, 0xd78d42f8, 0x42fd966d,
+ 0x261ded93, 0xb36d3906, 0x54288e16, 0xc1585a83, 0xa5b8217d,
+ 0x30c8f5e8, 0x6c78d681, 0xf9080214, 0x9de879ea, 0x0898ad7f,
+ 0x24883f38, 0xb1f8ebad, 0xd5189053, 0x406844c6, 0x1cd867af,
+ 0x89a8b33a, 0xed48c8c4, 0x78381c51, 0xb569ec4a, 0x201938df,
+ 0x44f94321, 0xd18997b4, 0x8d39b4dd, 0x18496048, 0x7ca91bb6,
+ 0xe9d9cf23, 0xc5c95d64, 0x50b989f1, 0x3459f20f, 0xa129269a,
+ 0xfd9905f3, 0x68e9d166, 0x0c09aa98, 0x99797e0d, 0x4ddb4cef,
+ 0xd8ab987a, 0xbc4be384, 0x293b3711, 0x758b1478, 0xe0fbc0ed,
+ 0x841bbb13, 0x116b6f86, 0x3d7bfdc1, 0xa80b2954, 0xcceb52aa,
+ 0x599b863f, 0x052ba556, 0x905b71c3, 0xf4bb0a3d, 0x61cbdea8,
+ 0xac9a2eb3, 0x39eafa26, 0x5d0a81d8, 0xc87a554d, 0x94ca7624,
+ 0x01baa2b1, 0x655ad94f, 0xf02a0dda, 0xdc3a9f9d, 0x494a4b08,
+ 0x2daa30f6, 0xb8dae463, 0xe46ac70a, 0x711a139f, 0x15fa6861,
+ 0x808abcf4},
+ {0x00000000, 0xcf9e17c8, 0x444d29d1, 0x8bd33e19, 0x889a53a2,
+ 0x4704446a, 0xccd77a73, 0x03496dbb, 0xca45a105, 0x05dbb6cd,
+ 0x8e0888d4, 0x41969f1c, 0x42dff2a7, 0x8d41e56f, 0x0692db76,
+ 0xc90cccbe, 0x4ffa444b, 0x80645383, 0x0bb76d9a, 0xc4297a52,
+ 0xc76017e9, 0x08fe0021, 0x832d3e38, 0x4cb329f0, 0x85bfe54e,
+ 0x4a21f286, 0xc1f2cc9f, 0x0e6cdb57, 0x0d25b6ec, 0xc2bba124,
+ 0x49689f3d, 0x86f688f5, 0x9ff48896, 0x506a9f5e, 0xdbb9a147,
+ 0x1427b68f, 0x176edb34, 0xd8f0ccfc, 0x5323f2e5, 0x9cbde52d,
+ 0x55b12993, 0x9a2f3e5b, 0x11fc0042, 0xde62178a, 0xdd2b7a31,
+ 0x12b56df9, 0x996653e0, 0x56f84428, 0xd00eccdd, 0x1f90db15,
+ 0x9443e50c, 0x5bddf2c4, 0x58949f7f, 0x970a88b7, 0x1cd9b6ae,
+ 0xd347a166, 0x1a4b6dd8, 0xd5d57a10, 0x5e064409, 0x919853c1,
+ 0x92d13e7a, 0x5d4f29b2, 0xd69c17ab, 0x19020063, 0xe498176d,
+ 0x2b0600a5, 0xa0d53ebc, 0x6f4b2974, 0x6c0244cf, 0xa39c5307,
+ 0x284f6d1e, 0xe7d17ad6, 0x2eddb668, 0xe143a1a0, 0x6a909fb9,
+ 0xa50e8871, 0xa647e5ca, 0x69d9f202, 0xe20acc1b, 0x2d94dbd3,
+ 0xab625326, 0x64fc44ee, 0xef2f7af7, 0x20b16d3f, 0x23f80084,
+ 0xec66174c, 0x67b52955, 0xa82b3e9d, 0x6127f223, 0xaeb9e5eb,
+ 0x256adbf2, 0xeaf4cc3a, 0xe9bda181, 0x2623b649, 0xadf08850,
+ 0x626e9f98, 0x7b6c9ffb, 0xb4f28833, 0x3f21b62a, 0xf0bfa1e2,
+ 0xf3f6cc59, 0x3c68db91, 0xb7bbe588, 0x7825f240, 0xb1293efe,
+ 0x7eb72936, 0xf564172f, 0x3afa00e7, 0x39b36d5c, 0xf62d7a94,
+ 0x7dfe448d, 0xb2605345, 0x3496dbb0, 0xfb08cc78, 0x70dbf261,
+ 0xbf45e5a9, 0xbc0c8812, 0x73929fda, 0xf841a1c3, 0x37dfb60b,
+ 0xfed37ab5, 0x314d6d7d, 0xba9e5364, 0x750044ac, 0x76492917,
+ 0xb9d73edf, 0x320400c6, 0xfd9a170e, 0x1241289b, 0xdddf3f53,
+ 0x560c014a, 0x99921682, 0x9adb7b39, 0x55456cf1, 0xde9652e8,
+ 0x11084520, 0xd804899e, 0x179a9e56, 0x9c49a04f, 0x53d7b787,
+ 0x509eda3c, 0x9f00cdf4, 0x14d3f3ed, 0xdb4de425, 0x5dbb6cd0,
+ 0x92257b18, 0x19f64501, 0xd66852c9, 0xd5213f72, 0x1abf28ba,
+ 0x916c16a3, 0x5ef2016b, 0x97fecdd5, 0x5860da1d, 0xd3b3e404,
+ 0x1c2df3cc, 0x1f649e77, 0xd0fa89bf, 0x5b29b7a6, 0x94b7a06e,
+ 0x8db5a00d, 0x422bb7c5, 0xc9f889dc, 0x06669e14, 0x052ff3af,
+ 0xcab1e467, 0x4162da7e, 0x8efccdb6, 0x47f00108, 0x886e16c0,
+ 0x03bd28d9, 0xcc233f11, 0xcf6a52aa, 0x00f44562, 0x8b277b7b,
+ 0x44b96cb3, 0xc24fe446, 0x0dd1f38e, 0x8602cd97, 0x499cda5f,
+ 0x4ad5b7e4, 0x854ba02c, 0x0e989e35, 0xc10689fd, 0x080a4543,
+ 0xc794528b, 0x4c476c92, 0x83d97b5a, 0x809016e1, 0x4f0e0129,
+ 0xc4dd3f30, 0x0b4328f8, 0xf6d93ff6, 0x3947283e, 0xb2941627,
+ 0x7d0a01ef, 0x7e436c54, 0xb1dd7b9c, 0x3a0e4585, 0xf590524d,
+ 0x3c9c9ef3, 0xf302893b, 0x78d1b722, 0xb74fa0ea, 0xb406cd51,
+ 0x7b98da99, 0xf04be480, 0x3fd5f348, 0xb9237bbd, 0x76bd6c75,
+ 0xfd6e526c, 0x32f045a4, 0x31b9281f, 0xfe273fd7, 0x75f401ce,
+ 0xba6a1606, 0x7366dab8, 0xbcf8cd70, 0x372bf369, 0xf8b5e4a1,
+ 0xfbfc891a, 0x34629ed2, 0xbfb1a0cb, 0x702fb703, 0x692db760,
+ 0xa6b3a0a8, 0x2d609eb1, 0xe2fe8979, 0xe1b7e4c2, 0x2e29f30a,
+ 0xa5facd13, 0x6a64dadb, 0xa3681665, 0x6cf601ad, 0xe7253fb4,
+ 0x28bb287c, 0x2bf245c7, 0xe46c520f, 0x6fbf6c16, 0xa0217bde,
+ 0x26d7f32b, 0xe949e4e3, 0x629adafa, 0xad04cd32, 0xae4da089,
+ 0x61d3b741, 0xea008958, 0x259e9e90, 0xec92522e, 0x230c45e6,
+ 0xa8df7bff, 0x67416c37, 0x6408018c, 0xab961644, 0x2045285d,
+ 0xefdb3f95},
+ {0x00000000, 0x24825136, 0x4904a26c, 0x6d86f35a, 0x920944d8,
+ 0xb68b15ee, 0xdb0de6b4, 0xff8fb782, 0xff638ff1, 0xdbe1dec7,
+ 0xb6672d9d, 0x92e57cab, 0x6d6acb29, 0x49e89a1f, 0x246e6945,
+ 0x00ec3873, 0x25b619a3, 0x01344895, 0x6cb2bbcf, 0x4830eaf9,
+ 0xb7bf5d7b, 0x933d0c4d, 0xfebbff17, 0xda39ae21, 0xdad59652,
+ 0xfe57c764, 0x93d1343e, 0xb7536508, 0x48dcd28a, 0x6c5e83bc,
+ 0x01d870e6, 0x255a21d0, 0x4b6c3346, 0x6fee6270, 0x0268912a,
+ 0x26eac01c, 0xd965779e, 0xfde726a8, 0x9061d5f2, 0xb4e384c4,
+ 0xb40fbcb7, 0x908ded81, 0xfd0b1edb, 0xd9894fed, 0x2606f86f,
+ 0x0284a959, 0x6f025a03, 0x4b800b35, 0x6eda2ae5, 0x4a587bd3,
+ 0x27de8889, 0x035cd9bf, 0xfcd36e3d, 0xd8513f0b, 0xb5d7cc51,
+ 0x91559d67, 0x91b9a514, 0xb53bf422, 0xd8bd0778, 0xfc3f564e,
+ 0x03b0e1cc, 0x2732b0fa, 0x4ab443a0, 0x6e361296, 0x96d8668c,
+ 0xb25a37ba, 0xdfdcc4e0, 0xfb5e95d6, 0x04d12254, 0x20537362,
+ 0x4dd58038, 0x6957d10e, 0x69bbe97d, 0x4d39b84b, 0x20bf4b11,
+ 0x043d1a27, 0xfbb2ada5, 0xdf30fc93, 0xb2b60fc9, 0x96345eff,
+ 0xb36e7f2f, 0x97ec2e19, 0xfa6add43, 0xdee88c75, 0x21673bf7,
+ 0x05e56ac1, 0x6863999b, 0x4ce1c8ad, 0x4c0df0de, 0x688fa1e8,
+ 0x050952b2, 0x218b0384, 0xde04b406, 0xfa86e530, 0x9700166a,
+ 0xb382475c, 0xddb455ca, 0xf93604fc, 0x94b0f7a6, 0xb032a690,
+ 0x4fbd1112, 0x6b3f4024, 0x06b9b37e, 0x223be248, 0x22d7da3b,
+ 0x06558b0d, 0x6bd37857, 0x4f512961, 0xb0de9ee3, 0x945ccfd5,
+ 0xf9da3c8f, 0xdd586db9, 0xf8024c69, 0xdc801d5f, 0xb106ee05,
+ 0x9584bf33, 0x6a0b08b1, 0x4e895987, 0x230faadd, 0x078dfbeb,
+ 0x0761c398, 0x23e392ae, 0x4e6561f4, 0x6ae730c2, 0x95688740,
+ 0xb1ead676, 0xdc6c252c, 0xf8ee741a, 0xf6c1cb59, 0xd2439a6f,
+ 0xbfc56935, 0x9b473803, 0x64c88f81, 0x404adeb7, 0x2dcc2ded,
+ 0x094e7cdb, 0x09a244a8, 0x2d20159e, 0x40a6e6c4, 0x6424b7f2,
+ 0x9bab0070, 0xbf295146, 0xd2afa21c, 0xf62df32a, 0xd377d2fa,
+ 0xf7f583cc, 0x9a737096, 0xbef121a0, 0x417e9622, 0x65fcc714,
+ 0x087a344e, 0x2cf86578, 0x2c145d0b, 0x08960c3d, 0x6510ff67,
+ 0x4192ae51, 0xbe1d19d3, 0x9a9f48e5, 0xf719bbbf, 0xd39bea89,
+ 0xbdadf81f, 0x992fa929, 0xf4a95a73, 0xd02b0b45, 0x2fa4bcc7,
+ 0x0b26edf1, 0x66a01eab, 0x42224f9d, 0x42ce77ee, 0x664c26d8,
+ 0x0bcad582, 0x2f4884b4, 0xd0c73336, 0xf4456200, 0x99c3915a,
+ 0xbd41c06c, 0x981be1bc, 0xbc99b08a, 0xd11f43d0, 0xf59d12e6,
+ 0x0a12a564, 0x2e90f452, 0x43160708, 0x6794563e, 0x67786e4d,
+ 0x43fa3f7b, 0x2e7ccc21, 0x0afe9d17, 0xf5712a95, 0xd1f37ba3,
+ 0xbc7588f9, 0x98f7d9cf, 0x6019add5, 0x449bfce3, 0x291d0fb9,
+ 0x0d9f5e8f, 0xf210e90d, 0xd692b83b, 0xbb144b61, 0x9f961a57,
+ 0x9f7a2224, 0xbbf87312, 0xd67e8048, 0xf2fcd17e, 0x0d7366fc,
+ 0x29f137ca, 0x4477c490, 0x60f595a6, 0x45afb476, 0x612de540,
+ 0x0cab161a, 0x2829472c, 0xd7a6f0ae, 0xf324a198, 0x9ea252c2,
+ 0xba2003f4, 0xbacc3b87, 0x9e4e6ab1, 0xf3c899eb, 0xd74ac8dd,
+ 0x28c57f5f, 0x0c472e69, 0x61c1dd33, 0x45438c05, 0x2b759e93,
+ 0x0ff7cfa5, 0x62713cff, 0x46f36dc9, 0xb97cda4b, 0x9dfe8b7d,
+ 0xf0787827, 0xd4fa2911, 0xd4161162, 0xf0944054, 0x9d12b30e,
+ 0xb990e238, 0x461f55ba, 0x629d048c, 0x0f1bf7d6, 0x2b99a6e0,
+ 0x0ec38730, 0x2a41d606, 0x47c7255c, 0x6345746a, 0x9ccac3e8,
+ 0xb84892de, 0xd5ce6184, 0xf14c30b2, 0xf1a008c1, 0xd52259f7,
+ 0xb8a4aaad, 0x9c26fb9b, 0x63a94c19, 0x472b1d2f, 0x2aadee75,
+ 0x0e2fbf43},
+ {0x00000000, 0x36f290f3, 0x6de521e6, 0x5b17b115, 0xdbca43cc,
+ 0xed38d33f, 0xb62f622a, 0x80ddf2d9, 0x6ce581d9, 0x5a17112a,
+ 0x0100a03f, 0x37f230cc, 0xb72fc215, 0x81dd52e6, 0xdacae3f3,
+ 0xec387300, 0xd9cb03b2, 0xef399341, 0xb42e2254, 0x82dcb2a7,
+ 0x0201407e, 0x34f3d08d, 0x6fe46198, 0x5916f16b, 0xb52e826b,
+ 0x83dc1298, 0xd8cba38d, 0xee39337e, 0x6ee4c1a7, 0x58165154,
+ 0x0301e041, 0x35f370b2, 0x68e70125, 0x5e1591d6, 0x050220c3,
+ 0x33f0b030, 0xb32d42e9, 0x85dfd21a, 0xdec8630f, 0xe83af3fc,
+ 0x040280fc, 0x32f0100f, 0x69e7a11a, 0x5f1531e9, 0xdfc8c330,
+ 0xe93a53c3, 0xb22de2d6, 0x84df7225, 0xb12c0297, 0x87de9264,
+ 0xdcc92371, 0xea3bb382, 0x6ae6415b, 0x5c14d1a8, 0x070360bd,
+ 0x31f1f04e, 0xddc9834e, 0xeb3b13bd, 0xb02ca2a8, 0x86de325b,
+ 0x0603c082, 0x30f15071, 0x6be6e164, 0x5d147197, 0xd1ce024a,
+ 0xe73c92b9, 0xbc2b23ac, 0x8ad9b35f, 0x0a044186, 0x3cf6d175,
+ 0x67e16060, 0x5113f093, 0xbd2b8393, 0x8bd91360, 0xd0cea275,
+ 0xe63c3286, 0x66e1c05f, 0x501350ac, 0x0b04e1b9, 0x3df6714a,
+ 0x080501f8, 0x3ef7910b, 0x65e0201e, 0x5312b0ed, 0xd3cf4234,
+ 0xe53dd2c7, 0xbe2a63d2, 0x88d8f321, 0x64e08021, 0x521210d2,
+ 0x0905a1c7, 0x3ff73134, 0xbf2ac3ed, 0x89d8531e, 0xd2cfe20b,
+ 0xe43d72f8, 0xb929036f, 0x8fdb939c, 0xd4cc2289, 0xe23eb27a,
+ 0x62e340a3, 0x5411d050, 0x0f066145, 0x39f4f1b6, 0xd5cc82b6,
+ 0xe33e1245, 0xb829a350, 0x8edb33a3, 0x0e06c17a, 0x38f45189,
+ 0x63e3e09c, 0x5511706f, 0x60e200dd, 0x5610902e, 0x0d07213b,
+ 0x3bf5b1c8, 0xbb284311, 0x8ddad3e2, 0xd6cd62f7, 0xe03ff204,
+ 0x0c078104, 0x3af511f7, 0x61e2a0e2, 0x57103011, 0xd7cdc2c8,
+ 0xe13f523b, 0xba28e32e, 0x8cda73dd, 0x78ed02d5, 0x4e1f9226,
+ 0x15082333, 0x23fab3c0, 0xa3274119, 0x95d5d1ea, 0xcec260ff,
+ 0xf830f00c, 0x1408830c, 0x22fa13ff, 0x79eda2ea, 0x4f1f3219,
+ 0xcfc2c0c0, 0xf9305033, 0xa227e126, 0x94d571d5, 0xa1260167,
+ 0x97d49194, 0xccc32081, 0xfa31b072, 0x7aec42ab, 0x4c1ed258,
+ 0x1709634d, 0x21fbf3be, 0xcdc380be, 0xfb31104d, 0xa026a158,
+ 0x96d431ab, 0x1609c372, 0x20fb5381, 0x7bece294, 0x4d1e7267,
+ 0x100a03f0, 0x26f89303, 0x7def2216, 0x4b1db2e5, 0xcbc0403c,
+ 0xfd32d0cf, 0xa62561da, 0x90d7f129, 0x7cef8229, 0x4a1d12da,
+ 0x110aa3cf, 0x27f8333c, 0xa725c1e5, 0x91d75116, 0xcac0e003,
+ 0xfc3270f0, 0xc9c10042, 0xff3390b1, 0xa42421a4, 0x92d6b157,
+ 0x120b438e, 0x24f9d37d, 0x7fee6268, 0x491cf29b, 0xa524819b,
+ 0x93d61168, 0xc8c1a07d, 0xfe33308e, 0x7eeec257, 0x481c52a4,
+ 0x130be3b1, 0x25f97342, 0xa923009f, 0x9fd1906c, 0xc4c62179,
+ 0xf234b18a, 0x72e94353, 0x441bd3a0, 0x1f0c62b5, 0x29fef246,
+ 0xc5c68146, 0xf33411b5, 0xa823a0a0, 0x9ed13053, 0x1e0cc28a,
+ 0x28fe5279, 0x73e9e36c, 0x451b739f, 0x70e8032d, 0x461a93de,
+ 0x1d0d22cb, 0x2bffb238, 0xab2240e1, 0x9dd0d012, 0xc6c76107,
+ 0xf035f1f4, 0x1c0d82f4, 0x2aff1207, 0x71e8a312, 0x471a33e1,
+ 0xc7c7c138, 0xf13551cb, 0xaa22e0de, 0x9cd0702d, 0xc1c401ba,
+ 0xf7369149, 0xac21205c, 0x9ad3b0af, 0x1a0e4276, 0x2cfcd285,
+ 0x77eb6390, 0x4119f363, 0xad218063, 0x9bd31090, 0xc0c4a185,
+ 0xf6363176, 0x76ebc3af, 0x4019535c, 0x1b0ee249, 0x2dfc72ba,
+ 0x180f0208, 0x2efd92fb, 0x75ea23ee, 0x4318b31d, 0xc3c541c4,
+ 0xf537d137, 0xae206022, 0x98d2f0d1, 0x74ea83d1, 0x42181322,
+ 0x190fa237, 0x2ffd32c4, 0xaf20c01d, 0x99d250ee, 0xc2c5e1fb,
+ 0xf4377108}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0xf390f23600000000, 0xe621e56d00000000,
+ 0x15b1175b00000000, 0xcc43cadb00000000, 0x3fd338ed00000000,
+ 0x2a622fb600000000, 0xd9f2dd8000000000, 0xd981e56c00000000,
+ 0x2a11175a00000000, 0x3fa0000100000000, 0xcc30f23700000000,
+ 0x15c22fb700000000, 0xe652dd8100000000, 0xf3e3cada00000000,
+ 0x007338ec00000000, 0xb203cbd900000000, 0x419339ef00000000,
+ 0x54222eb400000000, 0xa7b2dc8200000000, 0x7e40010200000000,
+ 0x8dd0f33400000000, 0x9861e46f00000000, 0x6bf1165900000000,
+ 0x6b822eb500000000, 0x9812dc8300000000, 0x8da3cbd800000000,
+ 0x7e3339ee00000000, 0xa7c1e46e00000000, 0x5451165800000000,
+ 0x41e0010300000000, 0xb270f33500000000, 0x2501e76800000000,
+ 0xd691155e00000000, 0xc320020500000000, 0x30b0f03300000000,
+ 0xe9422db300000000, 0x1ad2df8500000000, 0x0f63c8de00000000,
+ 0xfcf33ae800000000, 0xfc80020400000000, 0x0f10f03200000000,
+ 0x1aa1e76900000000, 0xe931155f00000000, 0x30c3c8df00000000,
+ 0xc3533ae900000000, 0xd6e22db200000000, 0x2572df8400000000,
+ 0x97022cb100000000, 0x6492de8700000000, 0x7123c9dc00000000,
+ 0x82b33bea00000000, 0x5b41e66a00000000, 0xa8d1145c00000000,
+ 0xbd60030700000000, 0x4ef0f13100000000, 0x4e83c9dd00000000,
+ 0xbd133beb00000000, 0xa8a22cb000000000, 0x5b32de8600000000,
+ 0x82c0030600000000, 0x7150f13000000000, 0x64e1e66b00000000,
+ 0x9771145d00000000, 0x4a02ced100000000, 0xb9923ce700000000,
+ 0xac232bbc00000000, 0x5fb3d98a00000000, 0x8641040a00000000,
+ 0x75d1f63c00000000, 0x6060e16700000000, 0x93f0135100000000,
+ 0x93832bbd00000000, 0x6013d98b00000000, 0x75a2ced000000000,
+ 0x86323ce600000000, 0x5fc0e16600000000, 0xac50135000000000,
+ 0xb9e1040b00000000, 0x4a71f63d00000000, 0xf801050800000000,
+ 0x0b91f73e00000000, 0x1e20e06500000000, 0xedb0125300000000,
+ 0x3442cfd300000000, 0xc7d23de500000000, 0xd2632abe00000000,
+ 0x21f3d88800000000, 0x2180e06400000000, 0xd210125200000000,
+ 0xc7a1050900000000, 0x3431f73f00000000, 0xedc32abf00000000,
+ 0x1e53d88900000000, 0x0be2cfd200000000, 0xf8723de400000000,
+ 0x6f0329b900000000, 0x9c93db8f00000000, 0x8922ccd400000000,
+ 0x7ab23ee200000000, 0xa340e36200000000, 0x50d0115400000000,
+ 0x4561060f00000000, 0xb6f1f43900000000, 0xb682ccd500000000,
+ 0x45123ee300000000, 0x50a329b800000000, 0xa333db8e00000000,
+ 0x7ac1060e00000000, 0x8951f43800000000, 0x9ce0e36300000000,
+ 0x6f70115500000000, 0xdd00e26000000000, 0x2e90105600000000,
+ 0x3b21070d00000000, 0xc8b1f53b00000000, 0x114328bb00000000,
+ 0xe2d3da8d00000000, 0xf762cdd600000000, 0x04f23fe000000000,
+ 0x0481070c00000000, 0xf711f53a00000000, 0xe2a0e26100000000,
+ 0x1130105700000000, 0xc8c2cdd700000000, 0x3b523fe100000000,
+ 0x2ee328ba00000000, 0xdd73da8c00000000, 0xd502ed7800000000,
+ 0x26921f4e00000000, 0x3323081500000000, 0xc0b3fa2300000000,
+ 0x194127a300000000, 0xead1d59500000000, 0xff60c2ce00000000,
+ 0x0cf030f800000000, 0x0c83081400000000, 0xff13fa2200000000,
+ 0xeaa2ed7900000000, 0x19321f4f00000000, 0xc0c0c2cf00000000,
+ 0x335030f900000000, 0x26e127a200000000, 0xd571d59400000000,
+ 0x670126a100000000, 0x9491d49700000000, 0x8120c3cc00000000,
+ 0x72b031fa00000000, 0xab42ec7a00000000, 0x58d21e4c00000000,
+ 0x4d63091700000000, 0xbef3fb2100000000, 0xbe80c3cd00000000,
+ 0x4d1031fb00000000, 0x58a126a000000000, 0xab31d49600000000,
+ 0x72c3091600000000, 0x8153fb2000000000, 0x94e2ec7b00000000,
+ 0x67721e4d00000000, 0xf0030a1000000000, 0x0393f82600000000,
+ 0x1622ef7d00000000, 0xe5b21d4b00000000, 0x3c40c0cb00000000,
+ 0xcfd032fd00000000, 0xda6125a600000000, 0x29f1d79000000000,
+ 0x2982ef7c00000000, 0xda121d4a00000000, 0xcfa30a1100000000,
+ 0x3c33f82700000000, 0xe5c125a700000000, 0x1651d79100000000,
+ 0x03e0c0ca00000000, 0xf07032fc00000000, 0x4200c1c900000000,
+ 0xb19033ff00000000, 0xa42124a400000000, 0x57b1d69200000000,
+ 0x8e430b1200000000, 0x7dd3f92400000000, 0x6862ee7f00000000,
+ 0x9bf21c4900000000, 0x9b8124a500000000, 0x6811d69300000000,
+ 0x7da0c1c800000000, 0x8e3033fe00000000, 0x57c2ee7e00000000,
+ 0xa4521c4800000000, 0xb1e30b1300000000, 0x4273f92500000000,
+ 0x9f0023a900000000, 0x6c90d19f00000000, 0x7921c6c400000000,
+ 0x8ab134f200000000, 0x5343e97200000000, 0xa0d31b4400000000,
+ 0xb5620c1f00000000, 0x46f2fe2900000000, 0x4681c6c500000000,
+ 0xb51134f300000000, 0xa0a023a800000000, 0x5330d19e00000000,
+ 0x8ac20c1e00000000, 0x7952fe2800000000, 0x6ce3e97300000000,
+ 0x9f731b4500000000, 0x2d03e87000000000, 0xde931a4600000000,
+ 0xcb220d1d00000000, 0x38b2ff2b00000000, 0xe14022ab00000000,
+ 0x12d0d09d00000000, 0x0761c7c600000000, 0xf4f135f000000000,
+ 0xf4820d1c00000000, 0x0712ff2a00000000, 0x12a3e87100000000,
+ 0xe1331a4700000000, 0x38c1c7c700000000, 0xcb5135f100000000,
+ 0xdee022aa00000000, 0x2d70d09c00000000, 0xba01c4c100000000,
+ 0x499136f700000000, 0x5c2021ac00000000, 0xafb0d39a00000000,
+ 0x76420e1a00000000, 0x85d2fc2c00000000, 0x9063eb7700000000,
+ 0x63f3194100000000, 0x638021ad00000000, 0x9010d39b00000000,
+ 0x85a1c4c000000000, 0x763136f600000000, 0xafc3eb7600000000,
+ 0x5c53194000000000, 0x49e20e1b00000000, 0xba72fc2d00000000,
+ 0x08020f1800000000, 0xfb92fd2e00000000, 0xee23ea7500000000,
+ 0x1db3184300000000, 0xc441c5c300000000, 0x37d137f500000000,
+ 0x226020ae00000000, 0xd1f0d29800000000, 0xd183ea7400000000,
+ 0x2213184200000000, 0x37a20f1900000000, 0xc432fd2f00000000,
+ 0x1dc020af00000000, 0xee50d29900000000, 0xfbe1c5c200000000,
+ 0x087137f400000000},
+ {0x0000000000000000, 0x3651822400000000, 0x6ca2044900000000,
+ 0x5af3866d00000000, 0xd844099200000000, 0xee158bb600000000,
+ 0xb4e60ddb00000000, 0x82b78fff00000000, 0xf18f63ff00000000,
+ 0xc7dee1db00000000, 0x9d2d67b600000000, 0xab7ce59200000000,
+ 0x29cb6a6d00000000, 0x1f9ae84900000000, 0x45696e2400000000,
+ 0x7338ec0000000000, 0xa319b62500000000, 0x9548340100000000,
+ 0xcfbbb26c00000000, 0xf9ea304800000000, 0x7b5dbfb700000000,
+ 0x4d0c3d9300000000, 0x17ffbbfe00000000, 0x21ae39da00000000,
+ 0x5296d5da00000000, 0x64c757fe00000000, 0x3e34d19300000000,
+ 0x086553b700000000, 0x8ad2dc4800000000, 0xbc835e6c00000000,
+ 0xe670d80100000000, 0xd0215a2500000000, 0x46336c4b00000000,
+ 0x7062ee6f00000000, 0x2a91680200000000, 0x1cc0ea2600000000,
+ 0x9e7765d900000000, 0xa826e7fd00000000, 0xf2d5619000000000,
+ 0xc484e3b400000000, 0xb7bc0fb400000000, 0x81ed8d9000000000,
+ 0xdb1e0bfd00000000, 0xed4f89d900000000, 0x6ff8062600000000,
+ 0x59a9840200000000, 0x035a026f00000000, 0x350b804b00000000,
+ 0xe52ada6e00000000, 0xd37b584a00000000, 0x8988de2700000000,
+ 0xbfd95c0300000000, 0x3d6ed3fc00000000, 0x0b3f51d800000000,
+ 0x51ccd7b500000000, 0x679d559100000000, 0x14a5b99100000000,
+ 0x22f43bb500000000, 0x7807bdd800000000, 0x4e563ffc00000000,
+ 0xcce1b00300000000, 0xfab0322700000000, 0xa043b44a00000000,
+ 0x9612366e00000000, 0x8c66d89600000000, 0xba375ab200000000,
+ 0xe0c4dcdf00000000, 0xd6955efb00000000, 0x5422d10400000000,
+ 0x6273532000000000, 0x3880d54d00000000, 0x0ed1576900000000,
+ 0x7de9bb6900000000, 0x4bb8394d00000000, 0x114bbf2000000000,
+ 0x271a3d0400000000, 0xa5adb2fb00000000, 0x93fc30df00000000,
+ 0xc90fb6b200000000, 0xff5e349600000000, 0x2f7f6eb300000000,
+ 0x192eec9700000000, 0x43dd6afa00000000, 0x758ce8de00000000,
+ 0xf73b672100000000, 0xc16ae50500000000, 0x9b99636800000000,
+ 0xadc8e14c00000000, 0xdef00d4c00000000, 0xe8a18f6800000000,
+ 0xb252090500000000, 0x84038b2100000000, 0x06b404de00000000,
+ 0x30e586fa00000000, 0x6a16009700000000, 0x5c4782b300000000,
+ 0xca55b4dd00000000, 0xfc0436f900000000, 0xa6f7b09400000000,
+ 0x90a632b000000000, 0x1211bd4f00000000, 0x24403f6b00000000,
+ 0x7eb3b90600000000, 0x48e23b2200000000, 0x3bdad72200000000,
+ 0x0d8b550600000000, 0x5778d36b00000000, 0x6129514f00000000,
+ 0xe39edeb000000000, 0xd5cf5c9400000000, 0x8f3cdaf900000000,
+ 0xb96d58dd00000000, 0x694c02f800000000, 0x5f1d80dc00000000,
+ 0x05ee06b100000000, 0x33bf849500000000, 0xb1080b6a00000000,
+ 0x8759894e00000000, 0xddaa0f2300000000, 0xebfb8d0700000000,
+ 0x98c3610700000000, 0xae92e32300000000, 0xf461654e00000000,
+ 0xc230e76a00000000, 0x4087689500000000, 0x76d6eab100000000,
+ 0x2c256cdc00000000, 0x1a74eef800000000, 0x59cbc1f600000000,
+ 0x6f9a43d200000000, 0x3569c5bf00000000, 0x0338479b00000000,
+ 0x818fc86400000000, 0xb7de4a4000000000, 0xed2dcc2d00000000,
+ 0xdb7c4e0900000000, 0xa844a20900000000, 0x9e15202d00000000,
+ 0xc4e6a64000000000, 0xf2b7246400000000, 0x7000ab9b00000000,
+ 0x465129bf00000000, 0x1ca2afd200000000, 0x2af32df600000000,
+ 0xfad277d300000000, 0xcc83f5f700000000, 0x9670739a00000000,
+ 0xa021f1be00000000, 0x22967e4100000000, 0x14c7fc6500000000,
+ 0x4e347a0800000000, 0x7865f82c00000000, 0x0b5d142c00000000,
+ 0x3d0c960800000000, 0x67ff106500000000, 0x51ae924100000000,
+ 0xd3191dbe00000000, 0xe5489f9a00000000, 0xbfbb19f700000000,
+ 0x89ea9bd300000000, 0x1ff8adbd00000000, 0x29a92f9900000000,
+ 0x735aa9f400000000, 0x450b2bd000000000, 0xc7bca42f00000000,
+ 0xf1ed260b00000000, 0xab1ea06600000000, 0x9d4f224200000000,
+ 0xee77ce4200000000, 0xd8264c6600000000, 0x82d5ca0b00000000,
+ 0xb484482f00000000, 0x3633c7d000000000, 0x006245f400000000,
+ 0x5a91c39900000000, 0x6cc041bd00000000, 0xbce11b9800000000,
+ 0x8ab099bc00000000, 0xd0431fd100000000, 0xe6129df500000000,
+ 0x64a5120a00000000, 0x52f4902e00000000, 0x0807164300000000,
+ 0x3e56946700000000, 0x4d6e786700000000, 0x7b3ffa4300000000,
+ 0x21cc7c2e00000000, 0x179dfe0a00000000, 0x952a71f500000000,
+ 0xa37bf3d100000000, 0xf98875bc00000000, 0xcfd9f79800000000,
+ 0xd5ad196000000000, 0xe3fc9b4400000000, 0xb90f1d2900000000,
+ 0x8f5e9f0d00000000, 0x0de910f200000000, 0x3bb892d600000000,
+ 0x614b14bb00000000, 0x571a969f00000000, 0x24227a9f00000000,
+ 0x1273f8bb00000000, 0x48807ed600000000, 0x7ed1fcf200000000,
+ 0xfc66730d00000000, 0xca37f12900000000, 0x90c4774400000000,
+ 0xa695f56000000000, 0x76b4af4500000000, 0x40e52d6100000000,
+ 0x1a16ab0c00000000, 0x2c47292800000000, 0xaef0a6d700000000,
+ 0x98a124f300000000, 0xc252a29e00000000, 0xf40320ba00000000,
+ 0x873bccba00000000, 0xb16a4e9e00000000, 0xeb99c8f300000000,
+ 0xddc84ad700000000, 0x5f7fc52800000000, 0x692e470c00000000,
+ 0x33ddc16100000000, 0x058c434500000000, 0x939e752b00000000,
+ 0xa5cff70f00000000, 0xff3c716200000000, 0xc96df34600000000,
+ 0x4bda7cb900000000, 0x7d8bfe9d00000000, 0x277878f000000000,
+ 0x1129fad400000000, 0x621116d400000000, 0x544094f000000000,
+ 0x0eb3129d00000000, 0x38e290b900000000, 0xba551f4600000000,
+ 0x8c049d6200000000, 0xd6f71b0f00000000, 0xe0a6992b00000000,
+ 0x3087c30e00000000, 0x06d6412a00000000, 0x5c25c74700000000,
+ 0x6a74456300000000, 0xe8c3ca9c00000000, 0xde9248b800000000,
+ 0x8461ced500000000, 0xb2304cf100000000, 0xc108a0f100000000,
+ 0xf75922d500000000, 0xadaaa4b800000000, 0x9bfb269c00000000,
+ 0x194ca96300000000, 0x2f1d2b4700000000, 0x75eead2a00000000,
+ 0x43bf2f0e00000000},
+ {0x0000000000000000, 0xc8179ecf00000000, 0xd1294d4400000000,
+ 0x193ed38b00000000, 0xa2539a8800000000, 0x6a44044700000000,
+ 0x737ad7cc00000000, 0xbb6d490300000000, 0x05a145ca00000000,
+ 0xcdb6db0500000000, 0xd488088e00000000, 0x1c9f964100000000,
+ 0xa7f2df4200000000, 0x6fe5418d00000000, 0x76db920600000000,
+ 0xbecc0cc900000000, 0x4b44fa4f00000000, 0x8353648000000000,
+ 0x9a6db70b00000000, 0x527a29c400000000, 0xe91760c700000000,
+ 0x2100fe0800000000, 0x383e2d8300000000, 0xf029b34c00000000,
+ 0x4ee5bf8500000000, 0x86f2214a00000000, 0x9fccf2c100000000,
+ 0x57db6c0e00000000, 0xecb6250d00000000, 0x24a1bbc200000000,
+ 0x3d9f684900000000, 0xf588f68600000000, 0x9688f49f00000000,
+ 0x5e9f6a5000000000, 0x47a1b9db00000000, 0x8fb6271400000000,
+ 0x34db6e1700000000, 0xfcccf0d800000000, 0xe5f2235300000000,
+ 0x2de5bd9c00000000, 0x9329b15500000000, 0x5b3e2f9a00000000,
+ 0x4200fc1100000000, 0x8a1762de00000000, 0x317a2bdd00000000,
+ 0xf96db51200000000, 0xe053669900000000, 0x2844f85600000000,
+ 0xddcc0ed000000000, 0x15db901f00000000, 0x0ce5439400000000,
+ 0xc4f2dd5b00000000, 0x7f9f945800000000, 0xb7880a9700000000,
+ 0xaeb6d91c00000000, 0x66a147d300000000, 0xd86d4b1a00000000,
+ 0x107ad5d500000000, 0x0944065e00000000, 0xc153989100000000,
+ 0x7a3ed19200000000, 0xb2294f5d00000000, 0xab179cd600000000,
+ 0x6300021900000000, 0x6d1798e400000000, 0xa500062b00000000,
+ 0xbc3ed5a000000000, 0x74294b6f00000000, 0xcf44026c00000000,
+ 0x07539ca300000000, 0x1e6d4f2800000000, 0xd67ad1e700000000,
+ 0x68b6dd2e00000000, 0xa0a143e100000000, 0xb99f906a00000000,
+ 0x71880ea500000000, 0xcae547a600000000, 0x02f2d96900000000,
+ 0x1bcc0ae200000000, 0xd3db942d00000000, 0x265362ab00000000,
+ 0xee44fc6400000000, 0xf77a2fef00000000, 0x3f6db12000000000,
+ 0x8400f82300000000, 0x4c1766ec00000000, 0x5529b56700000000,
+ 0x9d3e2ba800000000, 0x23f2276100000000, 0xebe5b9ae00000000,
+ 0xf2db6a2500000000, 0x3accf4ea00000000, 0x81a1bde900000000,
+ 0x49b6232600000000, 0x5088f0ad00000000, 0x989f6e6200000000,
+ 0xfb9f6c7b00000000, 0x3388f2b400000000, 0x2ab6213f00000000,
+ 0xe2a1bff000000000, 0x59ccf6f300000000, 0x91db683c00000000,
+ 0x88e5bbb700000000, 0x40f2257800000000, 0xfe3e29b100000000,
+ 0x3629b77e00000000, 0x2f1764f500000000, 0xe700fa3a00000000,
+ 0x5c6db33900000000, 0x947a2df600000000, 0x8d44fe7d00000000,
+ 0x455360b200000000, 0xb0db963400000000, 0x78cc08fb00000000,
+ 0x61f2db7000000000, 0xa9e545bf00000000, 0x12880cbc00000000,
+ 0xda9f927300000000, 0xc3a141f800000000, 0x0bb6df3700000000,
+ 0xb57ad3fe00000000, 0x7d6d4d3100000000, 0x64539eba00000000,
+ 0xac44007500000000, 0x1729497600000000, 0xdf3ed7b900000000,
+ 0xc600043200000000, 0x0e179afd00000000, 0x9b28411200000000,
+ 0x533fdfdd00000000, 0x4a010c5600000000, 0x8216929900000000,
+ 0x397bdb9a00000000, 0xf16c455500000000, 0xe85296de00000000,
+ 0x2045081100000000, 0x9e8904d800000000, 0x569e9a1700000000,
+ 0x4fa0499c00000000, 0x87b7d75300000000, 0x3cda9e5000000000,
+ 0xf4cd009f00000000, 0xedf3d31400000000, 0x25e44ddb00000000,
+ 0xd06cbb5d00000000, 0x187b259200000000, 0x0145f61900000000,
+ 0xc95268d600000000, 0x723f21d500000000, 0xba28bf1a00000000,
+ 0xa3166c9100000000, 0x6b01f25e00000000, 0xd5cdfe9700000000,
+ 0x1dda605800000000, 0x04e4b3d300000000, 0xccf32d1c00000000,
+ 0x779e641f00000000, 0xbf89fad000000000, 0xa6b7295b00000000,
+ 0x6ea0b79400000000, 0x0da0b58d00000000, 0xc5b72b4200000000,
+ 0xdc89f8c900000000, 0x149e660600000000, 0xaff32f0500000000,
+ 0x67e4b1ca00000000, 0x7eda624100000000, 0xb6cdfc8e00000000,
+ 0x0801f04700000000, 0xc0166e8800000000, 0xd928bd0300000000,
+ 0x113f23cc00000000, 0xaa526acf00000000, 0x6245f40000000000,
+ 0x7b7b278b00000000, 0xb36cb94400000000, 0x46e44fc200000000,
+ 0x8ef3d10d00000000, 0x97cd028600000000, 0x5fda9c4900000000,
+ 0xe4b7d54a00000000, 0x2ca04b8500000000, 0x359e980e00000000,
+ 0xfd8906c100000000, 0x43450a0800000000, 0x8b5294c700000000,
+ 0x926c474c00000000, 0x5a7bd98300000000, 0xe116908000000000,
+ 0x29010e4f00000000, 0x303fddc400000000, 0xf828430b00000000,
+ 0xf63fd9f600000000, 0x3e28473900000000, 0x271694b200000000,
+ 0xef010a7d00000000, 0x546c437e00000000, 0x9c7bddb100000000,
+ 0x85450e3a00000000, 0x4d5290f500000000, 0xf39e9c3c00000000,
+ 0x3b8902f300000000, 0x22b7d17800000000, 0xeaa04fb700000000,
+ 0x51cd06b400000000, 0x99da987b00000000, 0x80e44bf000000000,
+ 0x48f3d53f00000000, 0xbd7b23b900000000, 0x756cbd7600000000,
+ 0x6c526efd00000000, 0xa445f03200000000, 0x1f28b93100000000,
+ 0xd73f27fe00000000, 0xce01f47500000000, 0x06166aba00000000,
+ 0xb8da667300000000, 0x70cdf8bc00000000, 0x69f32b3700000000,
+ 0xa1e4b5f800000000, 0x1a89fcfb00000000, 0xd29e623400000000,
+ 0xcba0b1bf00000000, 0x03b72f7000000000, 0x60b72d6900000000,
+ 0xa8a0b3a600000000, 0xb19e602d00000000, 0x7989fee200000000,
+ 0xc2e4b7e100000000, 0x0af3292e00000000, 0x13cdfaa500000000,
+ 0xdbda646a00000000, 0x651668a300000000, 0xad01f66c00000000,
+ 0xb43f25e700000000, 0x7c28bb2800000000, 0xc745f22b00000000,
+ 0x0f526ce400000000, 0x166cbf6f00000000, 0xde7b21a000000000,
+ 0x2bf3d72600000000, 0xe3e449e900000000, 0xfada9a6200000000,
+ 0x32cd04ad00000000, 0x89a04dae00000000, 0x41b7d36100000000,
+ 0x588900ea00000000, 0x909e9e2500000000, 0x2e5292ec00000000,
+ 0xe6450c2300000000, 0xff7bdfa800000000, 0x376c416700000000,
+ 0x8c01086400000000, 0x441696ab00000000, 0x5d28452000000000,
+ 0x953fdbef00000000},
+ {0x0000000000000000, 0x95d4709500000000, 0x6baf90f100000000,
+ 0xfe7be06400000000, 0x9758503800000000, 0x028c20ad00000000,
+ 0xfcf7c0c900000000, 0x6923b05c00000000, 0x2eb1a07000000000,
+ 0xbb65d0e500000000, 0x451e308100000000, 0xd0ca401400000000,
+ 0xb9e9f04800000000, 0x2c3d80dd00000000, 0xd24660b900000000,
+ 0x4792102c00000000, 0x5c6241e100000000, 0xc9b6317400000000,
+ 0x37cdd11000000000, 0xa219a18500000000, 0xcb3a11d900000000,
+ 0x5eee614c00000000, 0xa095812800000000, 0x3541f1bd00000000,
+ 0x72d3e19100000000, 0xe707910400000000, 0x197c716000000000,
+ 0x8ca801f500000000, 0xe58bb1a900000000, 0x705fc13c00000000,
+ 0x8e24215800000000, 0x1bf051cd00000000, 0xf9c2f31900000000,
+ 0x6c16838c00000000, 0x926d63e800000000, 0x07b9137d00000000,
+ 0x6e9aa32100000000, 0xfb4ed3b400000000, 0x053533d000000000,
+ 0x90e1434500000000, 0xd773536900000000, 0x42a723fc00000000,
+ 0xbcdcc39800000000, 0x2908b30d00000000, 0x402b035100000000,
+ 0xd5ff73c400000000, 0x2b8493a000000000, 0xbe50e33500000000,
+ 0xa5a0b2f800000000, 0x3074c26d00000000, 0xce0f220900000000,
+ 0x5bdb529c00000000, 0x32f8e2c000000000, 0xa72c925500000000,
+ 0x5957723100000000, 0xcc8302a400000000, 0x8b11128800000000,
+ 0x1ec5621d00000000, 0xe0be827900000000, 0x756af2ec00000000,
+ 0x1c4942b000000000, 0x899d322500000000, 0x77e6d24100000000,
+ 0xe232a2d400000000, 0xf285e73300000000, 0x675197a600000000,
+ 0x992a77c200000000, 0x0cfe075700000000, 0x65ddb70b00000000,
+ 0xf009c79e00000000, 0x0e7227fa00000000, 0x9ba6576f00000000,
+ 0xdc34474300000000, 0x49e037d600000000, 0xb79bd7b200000000,
+ 0x224fa72700000000, 0x4b6c177b00000000, 0xdeb867ee00000000,
+ 0x20c3878a00000000, 0xb517f71f00000000, 0xaee7a6d200000000,
+ 0x3b33d64700000000, 0xc548362300000000, 0x509c46b600000000,
+ 0x39bff6ea00000000, 0xac6b867f00000000, 0x5210661b00000000,
+ 0xc7c4168e00000000, 0x805606a200000000, 0x1582763700000000,
+ 0xebf9965300000000, 0x7e2de6c600000000, 0x170e569a00000000,
+ 0x82da260f00000000, 0x7ca1c66b00000000, 0xe975b6fe00000000,
+ 0x0b47142a00000000, 0x9e9364bf00000000, 0x60e884db00000000,
+ 0xf53cf44e00000000, 0x9c1f441200000000, 0x09cb348700000000,
+ 0xf7b0d4e300000000, 0x6264a47600000000, 0x25f6b45a00000000,
+ 0xb022c4cf00000000, 0x4e5924ab00000000, 0xdb8d543e00000000,
+ 0xb2aee46200000000, 0x277a94f700000000, 0xd901749300000000,
+ 0x4cd5040600000000, 0x572555cb00000000, 0xc2f1255e00000000,
+ 0x3c8ac53a00000000, 0xa95eb5af00000000, 0xc07d05f300000000,
+ 0x55a9756600000000, 0xabd2950200000000, 0x3e06e59700000000,
+ 0x7994f5bb00000000, 0xec40852e00000000, 0x123b654a00000000,
+ 0x87ef15df00000000, 0xeecca58300000000, 0x7b18d51600000000,
+ 0x8563357200000000, 0x10b745e700000000, 0xe40bcf6700000000,
+ 0x71dfbff200000000, 0x8fa45f9600000000, 0x1a702f0300000000,
+ 0x73539f5f00000000, 0xe687efca00000000, 0x18fc0fae00000000,
+ 0x8d287f3b00000000, 0xcaba6f1700000000, 0x5f6e1f8200000000,
+ 0xa115ffe600000000, 0x34c18f7300000000, 0x5de23f2f00000000,
+ 0xc8364fba00000000, 0x364dafde00000000, 0xa399df4b00000000,
+ 0xb8698e8600000000, 0x2dbdfe1300000000, 0xd3c61e7700000000,
+ 0x46126ee200000000, 0x2f31debe00000000, 0xbae5ae2b00000000,
+ 0x449e4e4f00000000, 0xd14a3eda00000000, 0x96d82ef600000000,
+ 0x030c5e6300000000, 0xfd77be0700000000, 0x68a3ce9200000000,
+ 0x01807ece00000000, 0x94540e5b00000000, 0x6a2fee3f00000000,
+ 0xfffb9eaa00000000, 0x1dc93c7e00000000, 0x881d4ceb00000000,
+ 0x7666ac8f00000000, 0xe3b2dc1a00000000, 0x8a916c4600000000,
+ 0x1f451cd300000000, 0xe13efcb700000000, 0x74ea8c2200000000,
+ 0x33789c0e00000000, 0xa6acec9b00000000, 0x58d70cff00000000,
+ 0xcd037c6a00000000, 0xa420cc3600000000, 0x31f4bca300000000,
+ 0xcf8f5cc700000000, 0x5a5b2c5200000000, 0x41ab7d9f00000000,
+ 0xd47f0d0a00000000, 0x2a04ed6e00000000, 0xbfd09dfb00000000,
+ 0xd6f32da700000000, 0x43275d3200000000, 0xbd5cbd5600000000,
+ 0x2888cdc300000000, 0x6f1addef00000000, 0xfacead7a00000000,
+ 0x04b54d1e00000000, 0x91613d8b00000000, 0xf8428dd700000000,
+ 0x6d96fd4200000000, 0x93ed1d2600000000, 0x06396db300000000,
+ 0x168e285400000000, 0x835a58c100000000, 0x7d21b8a500000000,
+ 0xe8f5c83000000000, 0x81d6786c00000000, 0x140208f900000000,
+ 0xea79e89d00000000, 0x7fad980800000000, 0x383f882400000000,
+ 0xadebf8b100000000, 0x539018d500000000, 0xc644684000000000,
+ 0xaf67d81c00000000, 0x3ab3a88900000000, 0xc4c848ed00000000,
+ 0x511c387800000000, 0x4aec69b500000000, 0xdf38192000000000,
+ 0x2143f94400000000, 0xb49789d100000000, 0xddb4398d00000000,
+ 0x4860491800000000, 0xb61ba97c00000000, 0x23cfd9e900000000,
+ 0x645dc9c500000000, 0xf189b95000000000, 0x0ff2593400000000,
+ 0x9a2629a100000000, 0xf30599fd00000000, 0x66d1e96800000000,
+ 0x98aa090c00000000, 0x0d7e799900000000, 0xef4cdb4d00000000,
+ 0x7a98abd800000000, 0x84e34bbc00000000, 0x11373b2900000000,
+ 0x78148b7500000000, 0xedc0fbe000000000, 0x13bb1b8400000000,
+ 0x866f6b1100000000, 0xc1fd7b3d00000000, 0x54290ba800000000,
+ 0xaa52ebcc00000000, 0x3f869b5900000000, 0x56a52b0500000000,
+ 0xc3715b9000000000, 0x3d0abbf400000000, 0xa8decb6100000000,
+ 0xb32e9aac00000000, 0x26faea3900000000, 0xd8810a5d00000000,
+ 0x4d557ac800000000, 0x2476ca9400000000, 0xb1a2ba0100000000,
+ 0x4fd95a6500000000, 0xda0d2af000000000, 0x9d9f3adc00000000,
+ 0x084b4a4900000000, 0xf630aa2d00000000, 0x63e4dab800000000,
+ 0x0ac76ae400000000, 0x9f131a7100000000, 0x6168fa1500000000,
+ 0xf4bc8a8000000000},
+ {0x0000000000000000, 0x1f17f08000000000, 0x7f2891da00000000,
+ 0x603f615a00000000, 0xbf56536e00000000, 0xa041a3ee00000000,
+ 0xc07ec2b400000000, 0xdf69323400000000, 0x7eada6dc00000000,
+ 0x61ba565c00000000, 0x0185370600000000, 0x1e92c78600000000,
+ 0xc1fbf5b200000000, 0xdeec053200000000, 0xbed3646800000000,
+ 0xa1c494e800000000, 0xbd5c3c6200000000, 0xa24bcce200000000,
+ 0xc274adb800000000, 0xdd635d3800000000, 0x020a6f0c00000000,
+ 0x1d1d9f8c00000000, 0x7d22fed600000000, 0x62350e5600000000,
+ 0xc3f19abe00000000, 0xdce66a3e00000000, 0xbcd90b6400000000,
+ 0xa3cefbe400000000, 0x7ca7c9d000000000, 0x63b0395000000000,
+ 0x038f580a00000000, 0x1c98a88a00000000, 0x7ab978c400000000,
+ 0x65ae884400000000, 0x0591e91e00000000, 0x1a86199e00000000,
+ 0xc5ef2baa00000000, 0xdaf8db2a00000000, 0xbac7ba7000000000,
+ 0xa5d04af000000000, 0x0414de1800000000, 0x1b032e9800000000,
+ 0x7b3c4fc200000000, 0x642bbf4200000000, 0xbb428d7600000000,
+ 0xa4557df600000000, 0xc46a1cac00000000, 0xdb7dec2c00000000,
+ 0xc7e544a600000000, 0xd8f2b42600000000, 0xb8cdd57c00000000,
+ 0xa7da25fc00000000, 0x78b317c800000000, 0x67a4e74800000000,
+ 0x079b861200000000, 0x188c769200000000, 0xb948e27a00000000,
+ 0xa65f12fa00000000, 0xc66073a000000000, 0xd977832000000000,
+ 0x061eb11400000000, 0x1909419400000000, 0x793620ce00000000,
+ 0x6621d04e00000000, 0xb574805300000000, 0xaa6370d300000000,
+ 0xca5c118900000000, 0xd54be10900000000, 0x0a22d33d00000000,
+ 0x153523bd00000000, 0x750a42e700000000, 0x6a1db26700000000,
+ 0xcbd9268f00000000, 0xd4ced60f00000000, 0xb4f1b75500000000,
+ 0xabe647d500000000, 0x748f75e100000000, 0x6b98856100000000,
+ 0x0ba7e43b00000000, 0x14b014bb00000000, 0x0828bc3100000000,
+ 0x173f4cb100000000, 0x77002deb00000000, 0x6817dd6b00000000,
+ 0xb77eef5f00000000, 0xa8691fdf00000000, 0xc8567e8500000000,
+ 0xd7418e0500000000, 0x76851aed00000000, 0x6992ea6d00000000,
+ 0x09ad8b3700000000, 0x16ba7bb700000000, 0xc9d3498300000000,
+ 0xd6c4b90300000000, 0xb6fbd85900000000, 0xa9ec28d900000000,
+ 0xcfcdf89700000000, 0xd0da081700000000, 0xb0e5694d00000000,
+ 0xaff299cd00000000, 0x709babf900000000, 0x6f8c5b7900000000,
+ 0x0fb33a2300000000, 0x10a4caa300000000, 0xb1605e4b00000000,
+ 0xae77aecb00000000, 0xce48cf9100000000, 0xd15f3f1100000000,
+ 0x0e360d2500000000, 0x1121fda500000000, 0x711e9cff00000000,
+ 0x6e096c7f00000000, 0x7291c4f500000000, 0x6d86347500000000,
+ 0x0db9552f00000000, 0x12aea5af00000000, 0xcdc7979b00000000,
+ 0xd2d0671b00000000, 0xb2ef064100000000, 0xadf8f6c100000000,
+ 0x0c3c622900000000, 0x132b92a900000000, 0x7314f3f300000000,
+ 0x6c03037300000000, 0xb36a314700000000, 0xac7dc1c700000000,
+ 0xcc42a09d00000000, 0xd355501d00000000, 0x6ae900a700000000,
+ 0x75fef02700000000, 0x15c1917d00000000, 0x0ad661fd00000000,
+ 0xd5bf53c900000000, 0xcaa8a34900000000, 0xaa97c21300000000,
+ 0xb580329300000000, 0x1444a67b00000000, 0x0b5356fb00000000,
+ 0x6b6c37a100000000, 0x747bc72100000000, 0xab12f51500000000,
+ 0xb405059500000000, 0xd43a64cf00000000, 0xcb2d944f00000000,
+ 0xd7b53cc500000000, 0xc8a2cc4500000000, 0xa89dad1f00000000,
+ 0xb78a5d9f00000000, 0x68e36fab00000000, 0x77f49f2b00000000,
+ 0x17cbfe7100000000, 0x08dc0ef100000000, 0xa9189a1900000000,
+ 0xb60f6a9900000000, 0xd6300bc300000000, 0xc927fb4300000000,
+ 0x164ec97700000000, 0x095939f700000000, 0x696658ad00000000,
+ 0x7671a82d00000000, 0x1050786300000000, 0x0f4788e300000000,
+ 0x6f78e9b900000000, 0x706f193900000000, 0xaf062b0d00000000,
+ 0xb011db8d00000000, 0xd02ebad700000000, 0xcf394a5700000000,
+ 0x6efddebf00000000, 0x71ea2e3f00000000, 0x11d54f6500000000,
+ 0x0ec2bfe500000000, 0xd1ab8dd100000000, 0xcebc7d5100000000,
+ 0xae831c0b00000000, 0xb194ec8b00000000, 0xad0c440100000000,
+ 0xb21bb48100000000, 0xd224d5db00000000, 0xcd33255b00000000,
+ 0x125a176f00000000, 0x0d4de7ef00000000, 0x6d7286b500000000,
+ 0x7265763500000000, 0xd3a1e2dd00000000, 0xccb6125d00000000,
+ 0xac89730700000000, 0xb39e838700000000, 0x6cf7b1b300000000,
+ 0x73e0413300000000, 0x13df206900000000, 0x0cc8d0e900000000,
+ 0xdf9d80f400000000, 0xc08a707400000000, 0xa0b5112e00000000,
+ 0xbfa2e1ae00000000, 0x60cbd39a00000000, 0x7fdc231a00000000,
+ 0x1fe3424000000000, 0x00f4b2c000000000, 0xa130262800000000,
+ 0xbe27d6a800000000, 0xde18b7f200000000, 0xc10f477200000000,
+ 0x1e66754600000000, 0x017185c600000000, 0x614ee49c00000000,
+ 0x7e59141c00000000, 0x62c1bc9600000000, 0x7dd64c1600000000,
+ 0x1de92d4c00000000, 0x02feddcc00000000, 0xdd97eff800000000,
+ 0xc2801f7800000000, 0xa2bf7e2200000000, 0xbda88ea200000000,
+ 0x1c6c1a4a00000000, 0x037beaca00000000, 0x63448b9000000000,
+ 0x7c537b1000000000, 0xa33a492400000000, 0xbc2db9a400000000,
+ 0xdc12d8fe00000000, 0xc305287e00000000, 0xa524f83000000000,
+ 0xba3308b000000000, 0xda0c69ea00000000, 0xc51b996a00000000,
+ 0x1a72ab5e00000000, 0x05655bde00000000, 0x655a3a8400000000,
+ 0x7a4dca0400000000, 0xdb895eec00000000, 0xc49eae6c00000000,
+ 0xa4a1cf3600000000, 0xbbb63fb600000000, 0x64df0d8200000000,
+ 0x7bc8fd0200000000, 0x1bf79c5800000000, 0x04e06cd800000000,
+ 0x1878c45200000000, 0x076f34d200000000, 0x6750558800000000,
+ 0x7847a50800000000, 0xa72e973c00000000, 0xb83967bc00000000,
+ 0xd80606e600000000, 0xc711f66600000000, 0x66d5628e00000000,
+ 0x79c2920e00000000, 0x19fdf35400000000, 0x06ea03d400000000,
+ 0xd98331e000000000, 0xc694c16000000000, 0xa6aba03a00000000,
+ 0xb9bc50ba00000000},
+ {0x0000000000000000, 0xe2fd888d00000000, 0x85fd60c000000000,
+ 0x6700e84d00000000, 0x4bfdb05b00000000, 0xa90038d600000000,
+ 0xce00d09b00000000, 0x2cfd581600000000, 0x96fa61b700000000,
+ 0x7407e93a00000000, 0x1307017700000000, 0xf1fa89fa00000000,
+ 0xdd07d1ec00000000, 0x3ffa596100000000, 0x58fab12c00000000,
+ 0xba0739a100000000, 0x6df3b2b500000000, 0x8f0e3a3800000000,
+ 0xe80ed27500000000, 0x0af35af800000000, 0x260e02ee00000000,
+ 0xc4f38a6300000000, 0xa3f3622e00000000, 0x410eeaa300000000,
+ 0xfb09d30200000000, 0x19f45b8f00000000, 0x7ef4b3c200000000,
+ 0x9c093b4f00000000, 0xb0f4635900000000, 0x5209ebd400000000,
+ 0x3509039900000000, 0xd7f48b1400000000, 0x9be014b000000000,
+ 0x791d9c3d00000000, 0x1e1d747000000000, 0xfce0fcfd00000000,
+ 0xd01da4eb00000000, 0x32e02c6600000000, 0x55e0c42b00000000,
+ 0xb71d4ca600000000, 0x0d1a750700000000, 0xefe7fd8a00000000,
+ 0x88e715c700000000, 0x6a1a9d4a00000000, 0x46e7c55c00000000,
+ 0xa41a4dd100000000, 0xc31aa59c00000000, 0x21e72d1100000000,
+ 0xf613a60500000000, 0x14ee2e8800000000, 0x73eec6c500000000,
+ 0x91134e4800000000, 0xbdee165e00000000, 0x5f139ed300000000,
+ 0x3813769e00000000, 0xdaeefe1300000000, 0x60e9c7b200000000,
+ 0x82144f3f00000000, 0xe514a77200000000, 0x07e92fff00000000,
+ 0x2b1477e900000000, 0xc9e9ff6400000000, 0xaee9172900000000,
+ 0x4c149fa400000000, 0x77c758bb00000000, 0x953ad03600000000,
+ 0xf23a387b00000000, 0x10c7b0f600000000, 0x3c3ae8e000000000,
+ 0xdec7606d00000000, 0xb9c7882000000000, 0x5b3a00ad00000000,
+ 0xe13d390c00000000, 0x03c0b18100000000, 0x64c059cc00000000,
+ 0x863dd14100000000, 0xaac0895700000000, 0x483d01da00000000,
+ 0x2f3de99700000000, 0xcdc0611a00000000, 0x1a34ea0e00000000,
+ 0xf8c9628300000000, 0x9fc98ace00000000, 0x7d34024300000000,
+ 0x51c95a5500000000, 0xb334d2d800000000, 0xd4343a9500000000,
+ 0x36c9b21800000000, 0x8cce8bb900000000, 0x6e33033400000000,
+ 0x0933eb7900000000, 0xebce63f400000000, 0xc7333be200000000,
+ 0x25ceb36f00000000, 0x42ce5b2200000000, 0xa033d3af00000000,
+ 0xec274c0b00000000, 0x0edac48600000000, 0x69da2ccb00000000,
+ 0x8b27a44600000000, 0xa7dafc5000000000, 0x452774dd00000000,
+ 0x22279c9000000000, 0xc0da141d00000000, 0x7add2dbc00000000,
+ 0x9820a53100000000, 0xff204d7c00000000, 0x1dddc5f100000000,
+ 0x31209de700000000, 0xd3dd156a00000000, 0xb4ddfd2700000000,
+ 0x562075aa00000000, 0x81d4febe00000000, 0x6329763300000000,
+ 0x04299e7e00000000, 0xe6d416f300000000, 0xca294ee500000000,
+ 0x28d4c66800000000, 0x4fd42e2500000000, 0xad29a6a800000000,
+ 0x172e9f0900000000, 0xf5d3178400000000, 0x92d3ffc900000000,
+ 0x702e774400000000, 0x5cd32f5200000000, 0xbe2ea7df00000000,
+ 0xd92e4f9200000000, 0x3bd3c71f00000000, 0xaf88c0ad00000000,
+ 0x4d75482000000000, 0x2a75a06d00000000, 0xc88828e000000000,
+ 0xe47570f600000000, 0x0688f87b00000000, 0x6188103600000000,
+ 0x837598bb00000000, 0x3972a11a00000000, 0xdb8f299700000000,
+ 0xbc8fc1da00000000, 0x5e72495700000000, 0x728f114100000000,
+ 0x907299cc00000000, 0xf772718100000000, 0x158ff90c00000000,
+ 0xc27b721800000000, 0x2086fa9500000000, 0x478612d800000000,
+ 0xa57b9a5500000000, 0x8986c24300000000, 0x6b7b4ace00000000,
+ 0x0c7ba28300000000, 0xee862a0e00000000, 0x548113af00000000,
+ 0xb67c9b2200000000, 0xd17c736f00000000, 0x3381fbe200000000,
+ 0x1f7ca3f400000000, 0xfd812b7900000000, 0x9a81c33400000000,
+ 0x787c4bb900000000, 0x3468d41d00000000, 0xd6955c9000000000,
+ 0xb195b4dd00000000, 0x53683c5000000000, 0x7f95644600000000,
+ 0x9d68eccb00000000, 0xfa68048600000000, 0x18958c0b00000000,
+ 0xa292b5aa00000000, 0x406f3d2700000000, 0x276fd56a00000000,
+ 0xc5925de700000000, 0xe96f05f100000000, 0x0b928d7c00000000,
+ 0x6c92653100000000, 0x8e6fedbc00000000, 0x599b66a800000000,
+ 0xbb66ee2500000000, 0xdc66066800000000, 0x3e9b8ee500000000,
+ 0x1266d6f300000000, 0xf09b5e7e00000000, 0x979bb63300000000,
+ 0x75663ebe00000000, 0xcf61071f00000000, 0x2d9c8f9200000000,
+ 0x4a9c67df00000000, 0xa861ef5200000000, 0x849cb74400000000,
+ 0x66613fc900000000, 0x0161d78400000000, 0xe39c5f0900000000,
+ 0xd84f981600000000, 0x3ab2109b00000000, 0x5db2f8d600000000,
+ 0xbf4f705b00000000, 0x93b2284d00000000, 0x714fa0c000000000,
+ 0x164f488d00000000, 0xf4b2c00000000000, 0x4eb5f9a100000000,
+ 0xac48712c00000000, 0xcb48996100000000, 0x29b511ec00000000,
+ 0x054849fa00000000, 0xe7b5c17700000000, 0x80b5293a00000000,
+ 0x6248a1b700000000, 0xb5bc2aa300000000, 0x5741a22e00000000,
+ 0x30414a6300000000, 0xd2bcc2ee00000000, 0xfe419af800000000,
+ 0x1cbc127500000000, 0x7bbcfa3800000000, 0x994172b500000000,
+ 0x23464b1400000000, 0xc1bbc39900000000, 0xa6bb2bd400000000,
+ 0x4446a35900000000, 0x68bbfb4f00000000, 0x8a4673c200000000,
+ 0xed469b8f00000000, 0x0fbb130200000000, 0x43af8ca600000000,
+ 0xa152042b00000000, 0xc652ec6600000000, 0x24af64eb00000000,
+ 0x08523cfd00000000, 0xeaafb47000000000, 0x8daf5c3d00000000,
+ 0x6f52d4b000000000, 0xd555ed1100000000, 0x37a8659c00000000,
+ 0x50a88dd100000000, 0xb255055c00000000, 0x9ea85d4a00000000,
+ 0x7c55d5c700000000, 0x1b553d8a00000000, 0xf9a8b50700000000,
+ 0x2e5c3e1300000000, 0xcca1b69e00000000, 0xaba15ed300000000,
+ 0x495cd65e00000000, 0x65a18e4800000000, 0x875c06c500000000,
+ 0xe05cee8800000000, 0x02a1660500000000, 0xb8a65fa400000000,
+ 0x5a5bd72900000000, 0x3d5b3f6400000000, 0xdfa6b7e900000000,
+ 0xf35befff00000000, 0x11a6677200000000, 0x76a68f3f00000000,
+ 0x945b07b200000000},
+ {0x0000000000000000, 0xa90b894e00000000, 0x5217129d00000000,
+ 0xfb1c9bd300000000, 0xe52855e100000000, 0x4c23dcaf00000000,
+ 0xb73f477c00000000, 0x1e34ce3200000000, 0x8b57db1900000000,
+ 0x225c525700000000, 0xd940c98400000000, 0x704b40ca00000000,
+ 0x6e7f8ef800000000, 0xc77407b600000000, 0x3c689c6500000000,
+ 0x9563152b00000000, 0x16afb63300000000, 0xbfa43f7d00000000,
+ 0x44b8a4ae00000000, 0xedb32de000000000, 0xf387e3d200000000,
+ 0x5a8c6a9c00000000, 0xa190f14f00000000, 0x089b780100000000,
+ 0x9df86d2a00000000, 0x34f3e46400000000, 0xcfef7fb700000000,
+ 0x66e4f6f900000000, 0x78d038cb00000000, 0xd1dbb18500000000,
+ 0x2ac72a5600000000, 0x83cca31800000000, 0x2c5e6d6700000000,
+ 0x8555e42900000000, 0x7e497ffa00000000, 0xd742f6b400000000,
+ 0xc976388600000000, 0x607db1c800000000, 0x9b612a1b00000000,
+ 0x326aa35500000000, 0xa709b67e00000000, 0x0e023f3000000000,
+ 0xf51ea4e300000000, 0x5c152dad00000000, 0x4221e39f00000000,
+ 0xeb2a6ad100000000, 0x1036f10200000000, 0xb93d784c00000000,
+ 0x3af1db5400000000, 0x93fa521a00000000, 0x68e6c9c900000000,
+ 0xc1ed408700000000, 0xdfd98eb500000000, 0x76d207fb00000000,
+ 0x8dce9c2800000000, 0x24c5156600000000, 0xb1a6004d00000000,
+ 0x18ad890300000000, 0xe3b112d000000000, 0x4aba9b9e00000000,
+ 0x548e55ac00000000, 0xfd85dce200000000, 0x0699473100000000,
+ 0xaf92ce7f00000000, 0x58bcdace00000000, 0xf1b7538000000000,
+ 0x0aabc85300000000, 0xa3a0411d00000000, 0xbd948f2f00000000,
+ 0x149f066100000000, 0xef839db200000000, 0x468814fc00000000,
+ 0xd3eb01d700000000, 0x7ae0889900000000, 0x81fc134a00000000,
+ 0x28f79a0400000000, 0x36c3543600000000, 0x9fc8dd7800000000,
+ 0x64d446ab00000000, 0xcddfcfe500000000, 0x4e136cfd00000000,
+ 0xe718e5b300000000, 0x1c047e6000000000, 0xb50ff72e00000000,
+ 0xab3b391c00000000, 0x0230b05200000000, 0xf92c2b8100000000,
+ 0x5027a2cf00000000, 0xc544b7e400000000, 0x6c4f3eaa00000000,
+ 0x9753a57900000000, 0x3e582c3700000000, 0x206ce20500000000,
+ 0x89676b4b00000000, 0x727bf09800000000, 0xdb7079d600000000,
+ 0x74e2b7a900000000, 0xdde93ee700000000, 0x26f5a53400000000,
+ 0x8ffe2c7a00000000, 0x91cae24800000000, 0x38c16b0600000000,
+ 0xc3ddf0d500000000, 0x6ad6799b00000000, 0xffb56cb000000000,
+ 0x56bee5fe00000000, 0xada27e2d00000000, 0x04a9f76300000000,
+ 0x1a9d395100000000, 0xb396b01f00000000, 0x488a2bcc00000000,
+ 0xe181a28200000000, 0x624d019a00000000, 0xcb4688d400000000,
+ 0x305a130700000000, 0x99519a4900000000, 0x8765547b00000000,
+ 0x2e6edd3500000000, 0xd57246e600000000, 0x7c79cfa800000000,
+ 0xe91ada8300000000, 0x401153cd00000000, 0xbb0dc81e00000000,
+ 0x1206415000000000, 0x0c328f6200000000, 0xa539062c00000000,
+ 0x5e259dff00000000, 0xf72e14b100000000, 0xf17ec44600000000,
+ 0x58754d0800000000, 0xa369d6db00000000, 0x0a625f9500000000,
+ 0x145691a700000000, 0xbd5d18e900000000, 0x4641833a00000000,
+ 0xef4a0a7400000000, 0x7a291f5f00000000, 0xd322961100000000,
+ 0x283e0dc200000000, 0x8135848c00000000, 0x9f014abe00000000,
+ 0x360ac3f000000000, 0xcd16582300000000, 0x641dd16d00000000,
+ 0xe7d1727500000000, 0x4edafb3b00000000, 0xb5c660e800000000,
+ 0x1ccde9a600000000, 0x02f9279400000000, 0xabf2aeda00000000,
+ 0x50ee350900000000, 0xf9e5bc4700000000, 0x6c86a96c00000000,
+ 0xc58d202200000000, 0x3e91bbf100000000, 0x979a32bf00000000,
+ 0x89aefc8d00000000, 0x20a575c300000000, 0xdbb9ee1000000000,
+ 0x72b2675e00000000, 0xdd20a92100000000, 0x742b206f00000000,
+ 0x8f37bbbc00000000, 0x263c32f200000000, 0x3808fcc000000000,
+ 0x9103758e00000000, 0x6a1fee5d00000000, 0xc314671300000000,
+ 0x5677723800000000, 0xff7cfb7600000000, 0x046060a500000000,
+ 0xad6be9eb00000000, 0xb35f27d900000000, 0x1a54ae9700000000,
+ 0xe148354400000000, 0x4843bc0a00000000, 0xcb8f1f1200000000,
+ 0x6284965c00000000, 0x99980d8f00000000, 0x309384c100000000,
+ 0x2ea74af300000000, 0x87acc3bd00000000, 0x7cb0586e00000000,
+ 0xd5bbd12000000000, 0x40d8c40b00000000, 0xe9d34d4500000000,
+ 0x12cfd69600000000, 0xbbc45fd800000000, 0xa5f091ea00000000,
+ 0x0cfb18a400000000, 0xf7e7837700000000, 0x5eec0a3900000000,
+ 0xa9c21e8800000000, 0x00c997c600000000, 0xfbd50c1500000000,
+ 0x52de855b00000000, 0x4cea4b6900000000, 0xe5e1c22700000000,
+ 0x1efd59f400000000, 0xb7f6d0ba00000000, 0x2295c59100000000,
+ 0x8b9e4cdf00000000, 0x7082d70c00000000, 0xd9895e4200000000,
+ 0xc7bd907000000000, 0x6eb6193e00000000, 0x95aa82ed00000000,
+ 0x3ca10ba300000000, 0xbf6da8bb00000000, 0x166621f500000000,
+ 0xed7aba2600000000, 0x4471336800000000, 0x5a45fd5a00000000,
+ 0xf34e741400000000, 0x0852efc700000000, 0xa159668900000000,
+ 0x343a73a200000000, 0x9d31faec00000000, 0x662d613f00000000,
+ 0xcf26e87100000000, 0xd112264300000000, 0x7819af0d00000000,
+ 0x830534de00000000, 0x2a0ebd9000000000, 0x859c73ef00000000,
+ 0x2c97faa100000000, 0xd78b617200000000, 0x7e80e83c00000000,
+ 0x60b4260e00000000, 0xc9bfaf4000000000, 0x32a3349300000000,
+ 0x9ba8bddd00000000, 0x0ecba8f600000000, 0xa7c021b800000000,
+ 0x5cdcba6b00000000, 0xf5d7332500000000, 0xebe3fd1700000000,
+ 0x42e8745900000000, 0xb9f4ef8a00000000, 0x10ff66c400000000,
+ 0x9333c5dc00000000, 0x3a384c9200000000, 0xc124d74100000000,
+ 0x682f5e0f00000000, 0x761b903d00000000, 0xdf10197300000000,
+ 0x240c82a000000000, 0x8d070bee00000000, 0x18641ec500000000,
+ 0xb16f978b00000000, 0x4a730c5800000000, 0xe378851600000000,
+ 0xfd4c4b2400000000, 0x5447c26a00000000, 0xaf5b59b900000000,
+ 0x0650d0f700000000},
+ {0x0000000000000000, 0x479244af00000000, 0xcf22f88500000000,
+ 0x88b0bc2a00000000, 0xdf4381d000000000, 0x98d1c57f00000000,
+ 0x1061795500000000, 0x57f33dfa00000000, 0xff81737a00000000,
+ 0xb81337d500000000, 0x30a38bff00000000, 0x7731cf5000000000,
+ 0x20c2f2aa00000000, 0x6750b60500000000, 0xefe00a2f00000000,
+ 0xa8724e8000000000, 0xfe03e7f400000000, 0xb991a35b00000000,
+ 0x31211f7100000000, 0x76b35bde00000000, 0x2140662400000000,
+ 0x66d2228b00000000, 0xee629ea100000000, 0xa9f0da0e00000000,
+ 0x0182948e00000000, 0x4610d02100000000, 0xcea06c0b00000000,
+ 0x893228a400000000, 0xdec1155e00000000, 0x995351f100000000,
+ 0x11e3eddb00000000, 0x5671a97400000000, 0xbd01bf3200000000,
+ 0xfa93fb9d00000000, 0x722347b700000000, 0x35b1031800000000,
+ 0x62423ee200000000, 0x25d07a4d00000000, 0xad60c66700000000,
+ 0xeaf282c800000000, 0x4280cc4800000000, 0x051288e700000000,
+ 0x8da234cd00000000, 0xca30706200000000, 0x9dc34d9800000000,
+ 0xda51093700000000, 0x52e1b51d00000000, 0x1573f1b200000000,
+ 0x430258c600000000, 0x04901c6900000000, 0x8c20a04300000000,
+ 0xcbb2e4ec00000000, 0x9c41d91600000000, 0xdbd39db900000000,
+ 0x5363219300000000, 0x14f1653c00000000, 0xbc832bbc00000000,
+ 0xfb116f1300000000, 0x73a1d33900000000, 0x3433979600000000,
+ 0x63c0aa6c00000000, 0x2452eec300000000, 0xace252e900000000,
+ 0xeb70164600000000, 0x7a037e6500000000, 0x3d913aca00000000,
+ 0xb52186e000000000, 0xf2b3c24f00000000, 0xa540ffb500000000,
+ 0xe2d2bb1a00000000, 0x6a62073000000000, 0x2df0439f00000000,
+ 0x85820d1f00000000, 0xc21049b000000000, 0x4aa0f59a00000000,
+ 0x0d32b13500000000, 0x5ac18ccf00000000, 0x1d53c86000000000,
+ 0x95e3744a00000000, 0xd27130e500000000, 0x8400999100000000,
+ 0xc392dd3e00000000, 0x4b22611400000000, 0x0cb025bb00000000,
+ 0x5b43184100000000, 0x1cd15cee00000000, 0x9461e0c400000000,
+ 0xd3f3a46b00000000, 0x7b81eaeb00000000, 0x3c13ae4400000000,
+ 0xb4a3126e00000000, 0xf33156c100000000, 0xa4c26b3b00000000,
+ 0xe3502f9400000000, 0x6be093be00000000, 0x2c72d71100000000,
+ 0xc702c15700000000, 0x809085f800000000, 0x082039d200000000,
+ 0x4fb27d7d00000000, 0x1841408700000000, 0x5fd3042800000000,
+ 0xd763b80200000000, 0x90f1fcad00000000, 0x3883b22d00000000,
+ 0x7f11f68200000000, 0xf7a14aa800000000, 0xb0330e0700000000,
+ 0xe7c033fd00000000, 0xa052775200000000, 0x28e2cb7800000000,
+ 0x6f708fd700000000, 0x390126a300000000, 0x7e93620c00000000,
+ 0xf623de2600000000, 0xb1b19a8900000000, 0xe642a77300000000,
+ 0xa1d0e3dc00000000, 0x29605ff600000000, 0x6ef21b5900000000,
+ 0xc68055d900000000, 0x8112117600000000, 0x09a2ad5c00000000,
+ 0x4e30e9f300000000, 0x19c3d40900000000, 0x5e5190a600000000,
+ 0xd6e12c8c00000000, 0x9173682300000000, 0xf406fcca00000000,
+ 0xb394b86500000000, 0x3b24044f00000000, 0x7cb640e000000000,
+ 0x2b457d1a00000000, 0x6cd739b500000000, 0xe467859f00000000,
+ 0xa3f5c13000000000, 0x0b878fb000000000, 0x4c15cb1f00000000,
+ 0xc4a5773500000000, 0x8337339a00000000, 0xd4c40e6000000000,
+ 0x93564acf00000000, 0x1be6f6e500000000, 0x5c74b24a00000000,
+ 0x0a051b3e00000000, 0x4d975f9100000000, 0xc527e3bb00000000,
+ 0x82b5a71400000000, 0xd5469aee00000000, 0x92d4de4100000000,
+ 0x1a64626b00000000, 0x5df626c400000000, 0xf584684400000000,
+ 0xb2162ceb00000000, 0x3aa690c100000000, 0x7d34d46e00000000,
+ 0x2ac7e99400000000, 0x6d55ad3b00000000, 0xe5e5111100000000,
+ 0xa27755be00000000, 0x490743f800000000, 0x0e95075700000000,
+ 0x8625bb7d00000000, 0xc1b7ffd200000000, 0x9644c22800000000,
+ 0xd1d6868700000000, 0x59663aad00000000, 0x1ef47e0200000000,
+ 0xb686308200000000, 0xf114742d00000000, 0x79a4c80700000000,
+ 0x3e368ca800000000, 0x69c5b15200000000, 0x2e57f5fd00000000,
+ 0xa6e749d700000000, 0xe1750d7800000000, 0xb704a40c00000000,
+ 0xf096e0a300000000, 0x78265c8900000000, 0x3fb4182600000000,
+ 0x684725dc00000000, 0x2fd5617300000000, 0xa765dd5900000000,
+ 0xe0f799f600000000, 0x4885d77600000000, 0x0f1793d900000000,
+ 0x87a72ff300000000, 0xc0356b5c00000000, 0x97c656a600000000,
+ 0xd054120900000000, 0x58e4ae2300000000, 0x1f76ea8c00000000,
+ 0x8e0582af00000000, 0xc997c60000000000, 0x41277a2a00000000,
+ 0x06b53e8500000000, 0x5146037f00000000, 0x16d447d000000000,
+ 0x9e64fbfa00000000, 0xd9f6bf5500000000, 0x7184f1d500000000,
+ 0x3616b57a00000000, 0xbea6095000000000, 0xf9344dff00000000,
+ 0xaec7700500000000, 0xe95534aa00000000, 0x61e5888000000000,
+ 0x2677cc2f00000000, 0x7006655b00000000, 0x379421f400000000,
+ 0xbf249dde00000000, 0xf8b6d97100000000, 0xaf45e48b00000000,
+ 0xe8d7a02400000000, 0x60671c0e00000000, 0x27f558a100000000,
+ 0x8f87162100000000, 0xc815528e00000000, 0x40a5eea400000000,
+ 0x0737aa0b00000000, 0x50c497f100000000, 0x1756d35e00000000,
+ 0x9fe66f7400000000, 0xd8742bdb00000000, 0x33043d9d00000000,
+ 0x7496793200000000, 0xfc26c51800000000, 0xbbb481b700000000,
+ 0xec47bc4d00000000, 0xabd5f8e200000000, 0x236544c800000000,
+ 0x64f7006700000000, 0xcc854ee700000000, 0x8b170a4800000000,
+ 0x03a7b66200000000, 0x4435f2cd00000000, 0x13c6cf3700000000,
+ 0x54548b9800000000, 0xdce437b200000000, 0x9b76731d00000000,
+ 0xcd07da6900000000, 0x8a959ec600000000, 0x022522ec00000000,
+ 0x45b7664300000000, 0x12445bb900000000, 0x55d61f1600000000,
+ 0xdd66a33c00000000, 0x9af4e79300000000, 0x3286a91300000000,
+ 0x7514edbc00000000, 0xfda4519600000000, 0xba36153900000000,
+ 0xedc528c300000000, 0xaa576c6c00000000, 0x22e7d04600000000,
+ 0x657594e900000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59,
+ 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4,
+ 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67,
+ 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef,
+ 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97,
+ 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88,
+ 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687,
+ 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698,
+ 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0,
+ 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068,
+ 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb,
+ 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056,
+ 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016,
+ 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009,
+ 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028,
+ 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037,
+ 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a,
+ 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7,
+ 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054,
+ 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7,
+ 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af,
+ 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0,
+ 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4,
+ 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab,
+ 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3,
+ 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a,
+ 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9,
+ 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54,
+ 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09,
+ 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16,
+ 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37,
+ 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28,
+ 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e,
+ 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3,
+ 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40,
+ 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8,
+ 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0,
+ 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf,
+ 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6,
+ 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9,
+ 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1,
+ 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059,
+ 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca,
+ 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067,
+ 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031,
+ 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e,
+ 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f,
+ 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010,
+ 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d,
+ 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0,
+ 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073,
+ 0xd8ac6b35},
+ {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2,
+ 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd,
+ 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696,
+ 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3,
+ 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f,
+ 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35,
+ 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5,
+ 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f,
+ 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673,
+ 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46,
+ 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d,
+ 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632,
+ 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28,
+ 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192,
+ 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c,
+ 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6,
+ 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0,
+ 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff,
+ 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4,
+ 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95,
+ 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9,
+ 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03,
+ 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7,
+ 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d,
+ 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151,
+ 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808,
+ 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343,
+ 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c,
+ 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a,
+ 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0,
+ 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e,
+ 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594,
+ 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6,
+ 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399,
+ 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2,
+ 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7,
+ 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb,
+ 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571,
+ 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289,
+ 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33,
+ 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f,
+ 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a,
+ 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461,
+ 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e,
+ 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c,
+ 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6,
+ 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918,
+ 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2,
+ 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484,
+ 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb,
+ 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0,
+ 0xa140efa8},
+ {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706,
+ 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed,
+ 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289,
+ 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a,
+ 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214,
+ 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3,
+ 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3,
+ 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254,
+ 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a,
+ 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9,
+ 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad,
+ 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746,
+ 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060,
+ 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187,
+ 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef,
+ 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408,
+ 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e,
+ 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495,
+ 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1,
+ 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532,
+ 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c,
+ 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb,
+ 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb,
+ 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c,
+ 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42,
+ 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060,
+ 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04,
+ 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef,
+ 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99,
+ 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e,
+ 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16,
+ 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1,
+ 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7,
+ 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c,
+ 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38,
+ 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb,
+ 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5,
+ 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42,
+ 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62,
+ 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85,
+ 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb,
+ 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18,
+ 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c,
+ 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997,
+ 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1,
+ 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36,
+ 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e,
+ 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9,
+ 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf,
+ 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24,
+ 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040,
+ 0x917cd6a1},
+ {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf,
+ 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd,
+ 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896,
+ 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9,
+ 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3,
+ 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f,
+ 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d,
+ 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1,
+ 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab,
+ 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4,
+ 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f,
+ 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d,
+ 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4,
+ 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978,
+ 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad,
+ 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621,
+ 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46,
+ 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854,
+ 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f,
+ 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a,
+ 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890,
+ 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c,
+ 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4,
+ 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238,
+ 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622,
+ 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab,
+ 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0,
+ 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2,
+ 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295,
+ 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19,
+ 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc,
+ 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140,
+ 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd,
+ 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf,
+ 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184,
+ 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb,
+ 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1,
+ 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d,
+ 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb,
+ 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257,
+ 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d,
+ 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22,
+ 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069,
+ 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b,
+ 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6,
+ 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a,
+ 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf,
+ 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33,
+ 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254,
+ 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146,
+ 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d,
+ 0x18ba364e}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x43cba687, 0xc7903cd4, 0x845b9a53, 0xcf270873,
+ 0x8cecaef4, 0x08b734a7, 0x4b7c9220, 0x9e4f10e6, 0xdd84b661,
+ 0x59df2c32, 0x1a148ab5, 0x51681895, 0x12a3be12, 0x96f82441,
+ 0xd53382c6, 0x7d995117, 0x3e52f790, 0xba096dc3, 0xf9c2cb44,
+ 0xb2be5964, 0xf175ffe3, 0x752e65b0, 0x36e5c337, 0xe3d641f1,
+ 0xa01de776, 0x24467d25, 0x678ddba2, 0x2cf14982, 0x6f3aef05,
+ 0xeb617556, 0xa8aad3d1, 0xfa32a32e, 0xb9f905a9, 0x3da29ffa,
+ 0x7e69397d, 0x3515ab5d, 0x76de0dda, 0xf2859789, 0xb14e310e,
+ 0x647db3c8, 0x27b6154f, 0xa3ed8f1c, 0xe026299b, 0xab5abbbb,
+ 0xe8911d3c, 0x6cca876f, 0x2f0121e8, 0x87abf239, 0xc46054be,
+ 0x403bceed, 0x03f0686a, 0x488cfa4a, 0x0b475ccd, 0x8f1cc69e,
+ 0xccd76019, 0x19e4e2df, 0x5a2f4458, 0xde74de0b, 0x9dbf788c,
+ 0xd6c3eaac, 0x95084c2b, 0x1153d678, 0x529870ff, 0xf465465d,
+ 0xb7aee0da, 0x33f57a89, 0x703edc0e, 0x3b424e2e, 0x7889e8a9,
+ 0xfcd272fa, 0xbf19d47d, 0x6a2a56bb, 0x29e1f03c, 0xadba6a6f,
+ 0xee71cce8, 0xa50d5ec8, 0xe6c6f84f, 0x629d621c, 0x2156c49b,
+ 0x89fc174a, 0xca37b1cd, 0x4e6c2b9e, 0x0da78d19, 0x46db1f39,
+ 0x0510b9be, 0x814b23ed, 0xc280856a, 0x17b307ac, 0x5478a12b,
+ 0xd0233b78, 0x93e89dff, 0xd8940fdf, 0x9b5fa958, 0x1f04330b,
+ 0x5ccf958c, 0x0e57e573, 0x4d9c43f4, 0xc9c7d9a7, 0x8a0c7f20,
+ 0xc170ed00, 0x82bb4b87, 0x06e0d1d4, 0x452b7753, 0x9018f595,
+ 0xd3d35312, 0x5788c941, 0x14436fc6, 0x5f3ffde6, 0x1cf45b61,
+ 0x98afc132, 0xdb6467b5, 0x73ceb464, 0x300512e3, 0xb45e88b0,
+ 0xf7952e37, 0xbce9bc17, 0xff221a90, 0x7b7980c3, 0x38b22644,
+ 0xed81a482, 0xae4a0205, 0x2a119856, 0x69da3ed1, 0x22a6acf1,
+ 0x616d0a76, 0xe5369025, 0xa6fd36a2, 0xe8cb8cba, 0xab002a3d,
+ 0x2f5bb06e, 0x6c9016e9, 0x27ec84c9, 0x6427224e, 0xe07cb81d,
+ 0xa3b71e9a, 0x76849c5c, 0x354f3adb, 0xb114a088, 0xf2df060f,
+ 0xb9a3942f, 0xfa6832a8, 0x7e33a8fb, 0x3df80e7c, 0x9552ddad,
+ 0xd6997b2a, 0x52c2e179, 0x110947fe, 0x5a75d5de, 0x19be7359,
+ 0x9de5e90a, 0xde2e4f8d, 0x0b1dcd4b, 0x48d66bcc, 0xcc8df19f,
+ 0x8f465718, 0xc43ac538, 0x87f163bf, 0x03aaf9ec, 0x40615f6b,
+ 0x12f92f94, 0x51328913, 0xd5691340, 0x96a2b5c7, 0xddde27e7,
+ 0x9e158160, 0x1a4e1b33, 0x5985bdb4, 0x8cb63f72, 0xcf7d99f5,
+ 0x4b2603a6, 0x08eda521, 0x43913701, 0x005a9186, 0x84010bd5,
+ 0xc7caad52, 0x6f607e83, 0x2cabd804, 0xa8f04257, 0xeb3be4d0,
+ 0xa04776f0, 0xe38cd077, 0x67d74a24, 0x241ceca3, 0xf12f6e65,
+ 0xb2e4c8e2, 0x36bf52b1, 0x7574f436, 0x3e086616, 0x7dc3c091,
+ 0xf9985ac2, 0xba53fc45, 0x1caecae7, 0x5f656c60, 0xdb3ef633,
+ 0x98f550b4, 0xd389c294, 0x90426413, 0x1419fe40, 0x57d258c7,
+ 0x82e1da01, 0xc12a7c86, 0x4571e6d5, 0x06ba4052, 0x4dc6d272,
+ 0x0e0d74f5, 0x8a56eea6, 0xc99d4821, 0x61379bf0, 0x22fc3d77,
+ 0xa6a7a724, 0xe56c01a3, 0xae109383, 0xeddb3504, 0x6980af57,
+ 0x2a4b09d0, 0xff788b16, 0xbcb32d91, 0x38e8b7c2, 0x7b231145,
+ 0x305f8365, 0x739425e2, 0xf7cfbfb1, 0xb4041936, 0xe69c69c9,
+ 0xa557cf4e, 0x210c551d, 0x62c7f39a, 0x29bb61ba, 0x6a70c73d,
+ 0xee2b5d6e, 0xade0fbe9, 0x78d3792f, 0x3b18dfa8, 0xbf4345fb,
+ 0xfc88e37c, 0xb7f4715c, 0xf43fd7db, 0x70644d88, 0x33afeb0f,
+ 0x9b0538de, 0xd8ce9e59, 0x5c95040a, 0x1f5ea28d, 0x542230ad,
+ 0x17e9962a, 0x93b20c79, 0xd079aafe, 0x054a2838, 0x46818ebf,
+ 0xc2da14ec, 0x8111b26b, 0xca6d204b, 0x89a686cc, 0x0dfd1c9f,
+ 0x4e36ba18},
+ {0x00000000, 0xe1b652ef, 0x836bd405, 0x62dd86ea, 0x06d7a80b,
+ 0xe761fae4, 0x85bc7c0e, 0x640a2ee1, 0x0cae5117, 0xed1803f8,
+ 0x8fc58512, 0x6e73d7fd, 0x0a79f91c, 0xebcfabf3, 0x89122d19,
+ 0x68a47ff6, 0x185ca32e, 0xf9eaf1c1, 0x9b37772b, 0x7a8125c4,
+ 0x1e8b0b25, 0xff3d59ca, 0x9de0df20, 0x7c568dcf, 0x14f2f239,
+ 0xf544a0d6, 0x9799263c, 0x762f74d3, 0x12255a32, 0xf39308dd,
+ 0x914e8e37, 0x70f8dcd8, 0x30b8465d, 0xd10e14b2, 0xb3d39258,
+ 0x5265c0b7, 0x366fee56, 0xd7d9bcb9, 0xb5043a53, 0x54b268bc,
+ 0x3c16174a, 0xdda045a5, 0xbf7dc34f, 0x5ecb91a0, 0x3ac1bf41,
+ 0xdb77edae, 0xb9aa6b44, 0x581c39ab, 0x28e4e573, 0xc952b79c,
+ 0xab8f3176, 0x4a396399, 0x2e334d78, 0xcf851f97, 0xad58997d,
+ 0x4ceecb92, 0x244ab464, 0xc5fce68b, 0xa7216061, 0x4697328e,
+ 0x229d1c6f, 0xc32b4e80, 0xa1f6c86a, 0x40409a85, 0x60708dba,
+ 0x81c6df55, 0xe31b59bf, 0x02ad0b50, 0x66a725b1, 0x8711775e,
+ 0xe5ccf1b4, 0x047aa35b, 0x6cdedcad, 0x8d688e42, 0xefb508a8,
+ 0x0e035a47, 0x6a0974a6, 0x8bbf2649, 0xe962a0a3, 0x08d4f24c,
+ 0x782c2e94, 0x999a7c7b, 0xfb47fa91, 0x1af1a87e, 0x7efb869f,
+ 0x9f4dd470, 0xfd90529a, 0x1c260075, 0x74827f83, 0x95342d6c,
+ 0xf7e9ab86, 0x165ff969, 0x7255d788, 0x93e38567, 0xf13e038d,
+ 0x10885162, 0x50c8cbe7, 0xb17e9908, 0xd3a31fe2, 0x32154d0d,
+ 0x561f63ec, 0xb7a93103, 0xd574b7e9, 0x34c2e506, 0x5c669af0,
+ 0xbdd0c81f, 0xdf0d4ef5, 0x3ebb1c1a, 0x5ab132fb, 0xbb076014,
+ 0xd9dae6fe, 0x386cb411, 0x489468c9, 0xa9223a26, 0xcbffbccc,
+ 0x2a49ee23, 0x4e43c0c2, 0xaff5922d, 0xcd2814c7, 0x2c9e4628,
+ 0x443a39de, 0xa58c6b31, 0xc751eddb, 0x26e7bf34, 0x42ed91d5,
+ 0xa35bc33a, 0xc18645d0, 0x2030173f, 0x81e66bae, 0x60503941,
+ 0x028dbfab, 0xe33bed44, 0x8731c3a5, 0x6687914a, 0x045a17a0,
+ 0xe5ec454f, 0x8d483ab9, 0x6cfe6856, 0x0e23eebc, 0xef95bc53,
+ 0x8b9f92b2, 0x6a29c05d, 0x08f446b7, 0xe9421458, 0x99bac880,
+ 0x780c9a6f, 0x1ad11c85, 0xfb674e6a, 0x9f6d608b, 0x7edb3264,
+ 0x1c06b48e, 0xfdb0e661, 0x95149997, 0x74a2cb78, 0x167f4d92,
+ 0xf7c91f7d, 0x93c3319c, 0x72756373, 0x10a8e599, 0xf11eb776,
+ 0xb15e2df3, 0x50e87f1c, 0x3235f9f6, 0xd383ab19, 0xb78985f8,
+ 0x563fd717, 0x34e251fd, 0xd5540312, 0xbdf07ce4, 0x5c462e0b,
+ 0x3e9ba8e1, 0xdf2dfa0e, 0xbb27d4ef, 0x5a918600, 0x384c00ea,
+ 0xd9fa5205, 0xa9028edd, 0x48b4dc32, 0x2a695ad8, 0xcbdf0837,
+ 0xafd526d6, 0x4e637439, 0x2cbef2d3, 0xcd08a03c, 0xa5acdfca,
+ 0x441a8d25, 0x26c70bcf, 0xc7715920, 0xa37b77c1, 0x42cd252e,
+ 0x2010a3c4, 0xc1a6f12b, 0xe196e614, 0x0020b4fb, 0x62fd3211,
+ 0x834b60fe, 0xe7414e1f, 0x06f71cf0, 0x642a9a1a, 0x859cc8f5,
+ 0xed38b703, 0x0c8ee5ec, 0x6e536306, 0x8fe531e9, 0xebef1f08,
+ 0x0a594de7, 0x6884cb0d, 0x893299e2, 0xf9ca453a, 0x187c17d5,
+ 0x7aa1913f, 0x9b17c3d0, 0xff1ded31, 0x1eabbfde, 0x7c763934,
+ 0x9dc06bdb, 0xf564142d, 0x14d246c2, 0x760fc028, 0x97b992c7,
+ 0xf3b3bc26, 0x1205eec9, 0x70d86823, 0x916e3acc, 0xd12ea049,
+ 0x3098f2a6, 0x5245744c, 0xb3f326a3, 0xd7f90842, 0x364f5aad,
+ 0x5492dc47, 0xb5248ea8, 0xdd80f15e, 0x3c36a3b1, 0x5eeb255b,
+ 0xbf5d77b4, 0xdb575955, 0x3ae10bba, 0x583c8d50, 0xb98adfbf,
+ 0xc9720367, 0x28c45188, 0x4a19d762, 0xabaf858d, 0xcfa5ab6c,
+ 0x2e13f983, 0x4cce7f69, 0xad782d86, 0xc5dc5270, 0x246a009f,
+ 0x46b78675, 0xa701d49a, 0xc30bfa7b, 0x22bda894, 0x40602e7e,
+ 0xa1d67c91},
+ {0x00000000, 0x5880e2d7, 0xf106b474, 0xa98656a3, 0xe20d68e9,
+ 0xba8d8a3e, 0x130bdc9d, 0x4b8b3e4a, 0x851da109, 0xdd9d43de,
+ 0x741b157d, 0x2c9bf7aa, 0x6710c9e0, 0x3f902b37, 0x96167d94,
+ 0xce969f43, 0x0a3b4213, 0x52bba0c4, 0xfb3df667, 0xa3bd14b0,
+ 0xe8362afa, 0xb0b6c82d, 0x19309e8e, 0x41b07c59, 0x8f26e31a,
+ 0xd7a601cd, 0x7e20576e, 0x26a0b5b9, 0x6d2b8bf3, 0x35ab6924,
+ 0x9c2d3f87, 0xc4addd50, 0x14768426, 0x4cf666f1, 0xe5703052,
+ 0xbdf0d285, 0xf67beccf, 0xaefb0e18, 0x077d58bb, 0x5ffdba6c,
+ 0x916b252f, 0xc9ebc7f8, 0x606d915b, 0x38ed738c, 0x73664dc6,
+ 0x2be6af11, 0x8260f9b2, 0xdae01b65, 0x1e4dc635, 0x46cd24e2,
+ 0xef4b7241, 0xb7cb9096, 0xfc40aedc, 0xa4c04c0b, 0x0d461aa8,
+ 0x55c6f87f, 0x9b50673c, 0xc3d085eb, 0x6a56d348, 0x32d6319f,
+ 0x795d0fd5, 0x21dded02, 0x885bbba1, 0xd0db5976, 0x28ec084d,
+ 0x706cea9a, 0xd9eabc39, 0x816a5eee, 0xcae160a4, 0x92618273,
+ 0x3be7d4d0, 0x63673607, 0xadf1a944, 0xf5714b93, 0x5cf71d30,
+ 0x0477ffe7, 0x4ffcc1ad, 0x177c237a, 0xbefa75d9, 0xe67a970e,
+ 0x22d74a5e, 0x7a57a889, 0xd3d1fe2a, 0x8b511cfd, 0xc0da22b7,
+ 0x985ac060, 0x31dc96c3, 0x695c7414, 0xa7caeb57, 0xff4a0980,
+ 0x56cc5f23, 0x0e4cbdf4, 0x45c783be, 0x1d476169, 0xb4c137ca,
+ 0xec41d51d, 0x3c9a8c6b, 0x641a6ebc, 0xcd9c381f, 0x951cdac8,
+ 0xde97e482, 0x86170655, 0x2f9150f6, 0x7711b221, 0xb9872d62,
+ 0xe107cfb5, 0x48819916, 0x10017bc1, 0x5b8a458b, 0x030aa75c,
+ 0xaa8cf1ff, 0xf20c1328, 0x36a1ce78, 0x6e212caf, 0xc7a77a0c,
+ 0x9f2798db, 0xd4aca691, 0x8c2c4446, 0x25aa12e5, 0x7d2af032,
+ 0xb3bc6f71, 0xeb3c8da6, 0x42badb05, 0x1a3a39d2, 0x51b10798,
+ 0x0931e54f, 0xa0b7b3ec, 0xf837513b, 0x50d8119a, 0x0858f34d,
+ 0xa1dea5ee, 0xf95e4739, 0xb2d57973, 0xea559ba4, 0x43d3cd07,
+ 0x1b532fd0, 0xd5c5b093, 0x8d455244, 0x24c304e7, 0x7c43e630,
+ 0x37c8d87a, 0x6f483aad, 0xc6ce6c0e, 0x9e4e8ed9, 0x5ae35389,
+ 0x0263b15e, 0xabe5e7fd, 0xf365052a, 0xb8ee3b60, 0xe06ed9b7,
+ 0x49e88f14, 0x11686dc3, 0xdffef280, 0x877e1057, 0x2ef846f4,
+ 0x7678a423, 0x3df39a69, 0x657378be, 0xccf52e1d, 0x9475ccca,
+ 0x44ae95bc, 0x1c2e776b, 0xb5a821c8, 0xed28c31f, 0xa6a3fd55,
+ 0xfe231f82, 0x57a54921, 0x0f25abf6, 0xc1b334b5, 0x9933d662,
+ 0x30b580c1, 0x68356216, 0x23be5c5c, 0x7b3ebe8b, 0xd2b8e828,
+ 0x8a380aff, 0x4e95d7af, 0x16153578, 0xbf9363db, 0xe713810c,
+ 0xac98bf46, 0xf4185d91, 0x5d9e0b32, 0x051ee9e5, 0xcb8876a6,
+ 0x93089471, 0x3a8ec2d2, 0x620e2005, 0x29851e4f, 0x7105fc98,
+ 0xd883aa3b, 0x800348ec, 0x783419d7, 0x20b4fb00, 0x8932ada3,
+ 0xd1b24f74, 0x9a39713e, 0xc2b993e9, 0x6b3fc54a, 0x33bf279d,
+ 0xfd29b8de, 0xa5a95a09, 0x0c2f0caa, 0x54afee7d, 0x1f24d037,
+ 0x47a432e0, 0xee226443, 0xb6a28694, 0x720f5bc4, 0x2a8fb913,
+ 0x8309efb0, 0xdb890d67, 0x9002332d, 0xc882d1fa, 0x61048759,
+ 0x3984658e, 0xf712facd, 0xaf92181a, 0x06144eb9, 0x5e94ac6e,
+ 0x151f9224, 0x4d9f70f3, 0xe4192650, 0xbc99c487, 0x6c429df1,
+ 0x34c27f26, 0x9d442985, 0xc5c4cb52, 0x8e4ff518, 0xd6cf17cf,
+ 0x7f49416c, 0x27c9a3bb, 0xe95f3cf8, 0xb1dfde2f, 0x1859888c,
+ 0x40d96a5b, 0x0b525411, 0x53d2b6c6, 0xfa54e065, 0xa2d402b2,
+ 0x6679dfe2, 0x3ef93d35, 0x977f6b96, 0xcfff8941, 0x8474b70b,
+ 0xdcf455dc, 0x7572037f, 0x2df2e1a8, 0xe3647eeb, 0xbbe49c3c,
+ 0x1262ca9f, 0x4ae22848, 0x01691602, 0x59e9f4d5, 0xf06fa276,
+ 0xa8ef40a1},
+ {0x00000000, 0x463b6765, 0x8c76ceca, 0xca4da9af, 0x59ebed4e,
+ 0x1fd08a2b, 0xd59d2384, 0x93a644e1, 0xb2d6db9d, 0xf4edbcf8,
+ 0x3ea01557, 0x789b7232, 0xeb3d36d3, 0xad0651b6, 0x674bf819,
+ 0x21709f7c, 0x25abc6e0, 0x6390a185, 0xa9dd082a, 0xefe66f4f,
+ 0x7c402bae, 0x3a7b4ccb, 0xf036e564, 0xb60d8201, 0x977d1d7d,
+ 0xd1467a18, 0x1b0bd3b7, 0x5d30b4d2, 0xce96f033, 0x88ad9756,
+ 0x42e03ef9, 0x04db599c, 0x0b50fc1a, 0x4d6b9b7f, 0x872632d0,
+ 0xc11d55b5, 0x52bb1154, 0x14807631, 0xdecddf9e, 0x98f6b8fb,
+ 0xb9862787, 0xffbd40e2, 0x35f0e94d, 0x73cb8e28, 0xe06dcac9,
+ 0xa656adac, 0x6c1b0403, 0x2a206366, 0x2efb3afa, 0x68c05d9f,
+ 0xa28df430, 0xe4b69355, 0x7710d7b4, 0x312bb0d1, 0xfb66197e,
+ 0xbd5d7e1b, 0x9c2de167, 0xda168602, 0x105b2fad, 0x566048c8,
+ 0xc5c60c29, 0x83fd6b4c, 0x49b0c2e3, 0x0f8ba586, 0x16a0f835,
+ 0x509b9f50, 0x9ad636ff, 0xdced519a, 0x4f4b157b, 0x0970721e,
+ 0xc33ddbb1, 0x8506bcd4, 0xa47623a8, 0xe24d44cd, 0x2800ed62,
+ 0x6e3b8a07, 0xfd9dcee6, 0xbba6a983, 0x71eb002c, 0x37d06749,
+ 0x330b3ed5, 0x753059b0, 0xbf7df01f, 0xf946977a, 0x6ae0d39b,
+ 0x2cdbb4fe, 0xe6961d51, 0xa0ad7a34, 0x81dde548, 0xc7e6822d,
+ 0x0dab2b82, 0x4b904ce7, 0xd8360806, 0x9e0d6f63, 0x5440c6cc,
+ 0x127ba1a9, 0x1df0042f, 0x5bcb634a, 0x9186cae5, 0xd7bdad80,
+ 0x441be961, 0x02208e04, 0xc86d27ab, 0x8e5640ce, 0xaf26dfb2,
+ 0xe91db8d7, 0x23501178, 0x656b761d, 0xf6cd32fc, 0xb0f65599,
+ 0x7abbfc36, 0x3c809b53, 0x385bc2cf, 0x7e60a5aa, 0xb42d0c05,
+ 0xf2166b60, 0x61b02f81, 0x278b48e4, 0xedc6e14b, 0xabfd862e,
+ 0x8a8d1952, 0xccb67e37, 0x06fbd798, 0x40c0b0fd, 0xd366f41c,
+ 0x955d9379, 0x5f103ad6, 0x192b5db3, 0x2c40f16b, 0x6a7b960e,
+ 0xa0363fa1, 0xe60d58c4, 0x75ab1c25, 0x33907b40, 0xf9ddd2ef,
+ 0xbfe6b58a, 0x9e962af6, 0xd8ad4d93, 0x12e0e43c, 0x54db8359,
+ 0xc77dc7b8, 0x8146a0dd, 0x4b0b0972, 0x0d306e17, 0x09eb378b,
+ 0x4fd050ee, 0x859df941, 0xc3a69e24, 0x5000dac5, 0x163bbda0,
+ 0xdc76140f, 0x9a4d736a, 0xbb3dec16, 0xfd068b73, 0x374b22dc,
+ 0x717045b9, 0xe2d60158, 0xa4ed663d, 0x6ea0cf92, 0x289ba8f7,
+ 0x27100d71, 0x612b6a14, 0xab66c3bb, 0xed5da4de, 0x7efbe03f,
+ 0x38c0875a, 0xf28d2ef5, 0xb4b64990, 0x95c6d6ec, 0xd3fdb189,
+ 0x19b01826, 0x5f8b7f43, 0xcc2d3ba2, 0x8a165cc7, 0x405bf568,
+ 0x0660920d, 0x02bbcb91, 0x4480acf4, 0x8ecd055b, 0xc8f6623e,
+ 0x5b5026df, 0x1d6b41ba, 0xd726e815, 0x911d8f70, 0xb06d100c,
+ 0xf6567769, 0x3c1bdec6, 0x7a20b9a3, 0xe986fd42, 0xafbd9a27,
+ 0x65f03388, 0x23cb54ed, 0x3ae0095e, 0x7cdb6e3b, 0xb696c794,
+ 0xf0ada0f1, 0x630be410, 0x25308375, 0xef7d2ada, 0xa9464dbf,
+ 0x8836d2c3, 0xce0db5a6, 0x04401c09, 0x427b7b6c, 0xd1dd3f8d,
+ 0x97e658e8, 0x5dabf147, 0x1b909622, 0x1f4bcfbe, 0x5970a8db,
+ 0x933d0174, 0xd5066611, 0x46a022f0, 0x009b4595, 0xcad6ec3a,
+ 0x8ced8b5f, 0xad9d1423, 0xeba67346, 0x21ebdae9, 0x67d0bd8c,
+ 0xf476f96d, 0xb24d9e08, 0x780037a7, 0x3e3b50c2, 0x31b0f544,
+ 0x778b9221, 0xbdc63b8e, 0xfbfd5ceb, 0x685b180a, 0x2e607f6f,
+ 0xe42dd6c0, 0xa216b1a5, 0x83662ed9, 0xc55d49bc, 0x0f10e013,
+ 0x492b8776, 0xda8dc397, 0x9cb6a4f2, 0x56fb0d5d, 0x10c06a38,
+ 0x141b33a4, 0x522054c1, 0x986dfd6e, 0xde569a0b, 0x4df0deea,
+ 0x0bcbb98f, 0xc1861020, 0x87bd7745, 0xa6cde839, 0xe0f68f5c,
+ 0x2abb26f3, 0x6c804196, 0xff260577, 0xb91d6212, 0x7350cbbd,
+ 0x356bacd8}};
+
+#endif
+
+#endif
+
+#if N == 6
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x3db1ecdc, 0x7b63d9b8, 0x46d23564, 0xf6c7b370,
+ 0xcb765fac, 0x8da46ac8, 0xb0158614, 0x36fe60a1, 0x0b4f8c7d,
+ 0x4d9db919, 0x702c55c5, 0xc039d3d1, 0xfd883f0d, 0xbb5a0a69,
+ 0x86ebe6b5, 0x6dfcc142, 0x504d2d9e, 0x169f18fa, 0x2b2ef426,
+ 0x9b3b7232, 0xa68a9eee, 0xe058ab8a, 0xdde94756, 0x5b02a1e3,
+ 0x66b34d3f, 0x2061785b, 0x1dd09487, 0xadc51293, 0x9074fe4f,
+ 0xd6a6cb2b, 0xeb1727f7, 0xdbf98284, 0xe6486e58, 0xa09a5b3c,
+ 0x9d2bb7e0, 0x2d3e31f4, 0x108fdd28, 0x565de84c, 0x6bec0490,
+ 0xed07e225, 0xd0b60ef9, 0x96643b9d, 0xabd5d741, 0x1bc05155,
+ 0x2671bd89, 0x60a388ed, 0x5d126431, 0xb60543c6, 0x8bb4af1a,
+ 0xcd669a7e, 0xf0d776a2, 0x40c2f0b6, 0x7d731c6a, 0x3ba1290e,
+ 0x0610c5d2, 0x80fb2367, 0xbd4acfbb, 0xfb98fadf, 0xc6291603,
+ 0x763c9017, 0x4b8d7ccb, 0x0d5f49af, 0x30eea573, 0x6c820349,
+ 0x5133ef95, 0x17e1daf1, 0x2a50362d, 0x9a45b039, 0xa7f45ce5,
+ 0xe1266981, 0xdc97855d, 0x5a7c63e8, 0x67cd8f34, 0x211fba50,
+ 0x1cae568c, 0xacbbd098, 0x910a3c44, 0xd7d80920, 0xea69e5fc,
+ 0x017ec20b, 0x3ccf2ed7, 0x7a1d1bb3, 0x47acf76f, 0xf7b9717b,
+ 0xca089da7, 0x8cdaa8c3, 0xb16b441f, 0x3780a2aa, 0x0a314e76,
+ 0x4ce37b12, 0x715297ce, 0xc14711da, 0xfcf6fd06, 0xba24c862,
+ 0x879524be, 0xb77b81cd, 0x8aca6d11, 0xcc185875, 0xf1a9b4a9,
+ 0x41bc32bd, 0x7c0dde61, 0x3adfeb05, 0x076e07d9, 0x8185e16c,
+ 0xbc340db0, 0xfae638d4, 0xc757d408, 0x7742521c, 0x4af3bec0,
+ 0x0c218ba4, 0x31906778, 0xda87408f, 0xe736ac53, 0xa1e49937,
+ 0x9c5575eb, 0x2c40f3ff, 0x11f11f23, 0x57232a47, 0x6a92c69b,
+ 0xec79202e, 0xd1c8ccf2, 0x971af996, 0xaaab154a, 0x1abe935e,
+ 0x270f7f82, 0x61dd4ae6, 0x5c6ca63a, 0xd9040692, 0xe4b5ea4e,
+ 0xa267df2a, 0x9fd633f6, 0x2fc3b5e2, 0x1272593e, 0x54a06c5a,
+ 0x69118086, 0xeffa6633, 0xd24b8aef, 0x9499bf8b, 0xa9285357,
+ 0x193dd543, 0x248c399f, 0x625e0cfb, 0x5fefe027, 0xb4f8c7d0,
+ 0x89492b0c, 0xcf9b1e68, 0xf22af2b4, 0x423f74a0, 0x7f8e987c,
+ 0x395cad18, 0x04ed41c4, 0x8206a771, 0xbfb74bad, 0xf9657ec9,
+ 0xc4d49215, 0x74c11401, 0x4970f8dd, 0x0fa2cdb9, 0x32132165,
+ 0x02fd8416, 0x3f4c68ca, 0x799e5dae, 0x442fb172, 0xf43a3766,
+ 0xc98bdbba, 0x8f59eede, 0xb2e80202, 0x3403e4b7, 0x09b2086b,
+ 0x4f603d0f, 0x72d1d1d3, 0xc2c457c7, 0xff75bb1b, 0xb9a78e7f,
+ 0x841662a3, 0x6f014554, 0x52b0a988, 0x14629cec, 0x29d37030,
+ 0x99c6f624, 0xa4771af8, 0xe2a52f9c, 0xdf14c340, 0x59ff25f5,
+ 0x644ec929, 0x229cfc4d, 0x1f2d1091, 0xaf389685, 0x92897a59,
+ 0xd45b4f3d, 0xe9eaa3e1, 0xb58605db, 0x8837e907, 0xcee5dc63,
+ 0xf35430bf, 0x4341b6ab, 0x7ef05a77, 0x38226f13, 0x059383cf,
+ 0x8378657a, 0xbec989a6, 0xf81bbcc2, 0xc5aa501e, 0x75bfd60a,
+ 0x480e3ad6, 0x0edc0fb2, 0x336de36e, 0xd87ac499, 0xe5cb2845,
+ 0xa3191d21, 0x9ea8f1fd, 0x2ebd77e9, 0x130c9b35, 0x55deae51,
+ 0x686f428d, 0xee84a438, 0xd33548e4, 0x95e77d80, 0xa856915c,
+ 0x18431748, 0x25f2fb94, 0x6320cef0, 0x5e91222c, 0x6e7f875f,
+ 0x53ce6b83, 0x151c5ee7, 0x28adb23b, 0x98b8342f, 0xa509d8f3,
+ 0xe3dbed97, 0xde6a014b, 0x5881e7fe, 0x65300b22, 0x23e23e46,
+ 0x1e53d29a, 0xae46548e, 0x93f7b852, 0xd5258d36, 0xe89461ea,
+ 0x0383461d, 0x3e32aac1, 0x78e09fa5, 0x45517379, 0xf544f56d,
+ 0xc8f519b1, 0x8e272cd5, 0xb396c009, 0x357d26bc, 0x08ccca60,
+ 0x4e1eff04, 0x73af13d8, 0xc3ba95cc, 0xfe0b7910, 0xb8d94c74,
+ 0x8568a0a8},
+ {0x00000000, 0x69790b65, 0xd2f216ca, 0xbb8b1daf, 0x7e952bd5,
+ 0x17ec20b0, 0xac673d1f, 0xc51e367a, 0xfd2a57aa, 0x94535ccf,
+ 0x2fd84160, 0x46a14a05, 0x83bf7c7f, 0xeac6771a, 0x514d6ab5,
+ 0x383461d0, 0x2125a915, 0x485ca270, 0xf3d7bfdf, 0x9aaeb4ba,
+ 0x5fb082c0, 0x36c989a5, 0x8d42940a, 0xe43b9f6f, 0xdc0ffebf,
+ 0xb576f5da, 0x0efde875, 0x6784e310, 0xa29ad56a, 0xcbe3de0f,
+ 0x7068c3a0, 0x1911c8c5, 0x424b522a, 0x2b32594f, 0x90b944e0,
+ 0xf9c04f85, 0x3cde79ff, 0x55a7729a, 0xee2c6f35, 0x87556450,
+ 0xbf610580, 0xd6180ee5, 0x6d93134a, 0x04ea182f, 0xc1f42e55,
+ 0xa88d2530, 0x1306389f, 0x7a7f33fa, 0x636efb3f, 0x0a17f05a,
+ 0xb19cedf5, 0xd8e5e690, 0x1dfbd0ea, 0x7482db8f, 0xcf09c620,
+ 0xa670cd45, 0x9e44ac95, 0xf73da7f0, 0x4cb6ba5f, 0x25cfb13a,
+ 0xe0d18740, 0x89a88c25, 0x3223918a, 0x5b5a9aef, 0x8496a454,
+ 0xedefaf31, 0x5664b29e, 0x3f1db9fb, 0xfa038f81, 0x937a84e4,
+ 0x28f1994b, 0x4188922e, 0x79bcf3fe, 0x10c5f89b, 0xab4ee534,
+ 0xc237ee51, 0x0729d82b, 0x6e50d34e, 0xd5dbcee1, 0xbca2c584,
+ 0xa5b30d41, 0xccca0624, 0x77411b8b, 0x1e3810ee, 0xdb262694,
+ 0xb25f2df1, 0x09d4305e, 0x60ad3b3b, 0x58995aeb, 0x31e0518e,
+ 0x8a6b4c21, 0xe3124744, 0x260c713e, 0x4f757a5b, 0xf4fe67f4,
+ 0x9d876c91, 0xc6ddf67e, 0xafa4fd1b, 0x142fe0b4, 0x7d56ebd1,
+ 0xb848ddab, 0xd131d6ce, 0x6abacb61, 0x03c3c004, 0x3bf7a1d4,
+ 0x528eaab1, 0xe905b71e, 0x807cbc7b, 0x45628a01, 0x2c1b8164,
+ 0x97909ccb, 0xfee997ae, 0xe7f85f6b, 0x8e81540e, 0x350a49a1,
+ 0x5c7342c4, 0x996d74be, 0xf0147fdb, 0x4b9f6274, 0x22e66911,
+ 0x1ad208c1, 0x73ab03a4, 0xc8201e0b, 0xa159156e, 0x64472314,
+ 0x0d3e2871, 0xb6b535de, 0xdfcc3ebb, 0xd25c4ee9, 0xbb25458c,
+ 0x00ae5823, 0x69d75346, 0xacc9653c, 0xc5b06e59, 0x7e3b73f6,
+ 0x17427893, 0x2f761943, 0x460f1226, 0xfd840f89, 0x94fd04ec,
+ 0x51e33296, 0x389a39f3, 0x8311245c, 0xea682f39, 0xf379e7fc,
+ 0x9a00ec99, 0x218bf136, 0x48f2fa53, 0x8deccc29, 0xe495c74c,
+ 0x5f1edae3, 0x3667d186, 0x0e53b056, 0x672abb33, 0xdca1a69c,
+ 0xb5d8adf9, 0x70c69b83, 0x19bf90e6, 0xa2348d49, 0xcb4d862c,
+ 0x90171cc3, 0xf96e17a6, 0x42e50a09, 0x2b9c016c, 0xee823716,
+ 0x87fb3c73, 0x3c7021dc, 0x55092ab9, 0x6d3d4b69, 0x0444400c,
+ 0xbfcf5da3, 0xd6b656c6, 0x13a860bc, 0x7ad16bd9, 0xc15a7676,
+ 0xa8237d13, 0xb132b5d6, 0xd84bbeb3, 0x63c0a31c, 0x0ab9a879,
+ 0xcfa79e03, 0xa6de9566, 0x1d5588c9, 0x742c83ac, 0x4c18e27c,
+ 0x2561e919, 0x9eeaf4b6, 0xf793ffd3, 0x328dc9a9, 0x5bf4c2cc,
+ 0xe07fdf63, 0x8906d406, 0x56caeabd, 0x3fb3e1d8, 0x8438fc77,
+ 0xed41f712, 0x285fc168, 0x4126ca0d, 0xfaadd7a2, 0x93d4dcc7,
+ 0xabe0bd17, 0xc299b672, 0x7912abdd, 0x106ba0b8, 0xd57596c2,
+ 0xbc0c9da7, 0x07878008, 0x6efe8b6d, 0x77ef43a8, 0x1e9648cd,
+ 0xa51d5562, 0xcc645e07, 0x097a687d, 0x60036318, 0xdb887eb7,
+ 0xb2f175d2, 0x8ac51402, 0xe3bc1f67, 0x583702c8, 0x314e09ad,
+ 0xf4503fd7, 0x9d2934b2, 0x26a2291d, 0x4fdb2278, 0x1481b897,
+ 0x7df8b3f2, 0xc673ae5d, 0xaf0aa538, 0x6a149342, 0x036d9827,
+ 0xb8e68588, 0xd19f8eed, 0xe9abef3d, 0x80d2e458, 0x3b59f9f7,
+ 0x5220f292, 0x973ec4e8, 0xfe47cf8d, 0x45ccd222, 0x2cb5d947,
+ 0x35a41182, 0x5cdd1ae7, 0xe7560748, 0x8e2f0c2d, 0x4b313a57,
+ 0x22483132, 0x99c32c9d, 0xf0ba27f8, 0xc88e4628, 0xa1f74d4d,
+ 0x1a7c50e2, 0x73055b87, 0xb61b6dfd, 0xdf626698, 0x64e97b37,
+ 0x0d907052},
+ {0x00000000, 0x7fc99b93, 0xff933726, 0x805aacb5, 0x2457680d,
+ 0x5b9ef39e, 0xdbc45f2b, 0xa40dc4b8, 0x48aed01a, 0x37674b89,
+ 0xb73de73c, 0xc8f47caf, 0x6cf9b817, 0x13302384, 0x936a8f31,
+ 0xeca314a2, 0x915da034, 0xee943ba7, 0x6ece9712, 0x11070c81,
+ 0xb50ac839, 0xcac353aa, 0x4a99ff1f, 0x3550648c, 0xd9f3702e,
+ 0xa63aebbd, 0x26604708, 0x59a9dc9b, 0xfda41823, 0x826d83b0,
+ 0x02372f05, 0x7dfeb496, 0xf9ca4629, 0x8603ddba, 0x0659710f,
+ 0x7990ea9c, 0xdd9d2e24, 0xa254b5b7, 0x220e1902, 0x5dc78291,
+ 0xb1649633, 0xcead0da0, 0x4ef7a115, 0x313e3a86, 0x9533fe3e,
+ 0xeafa65ad, 0x6aa0c918, 0x1569528b, 0x6897e61d, 0x175e7d8e,
+ 0x9704d13b, 0xe8cd4aa8, 0x4cc08e10, 0x33091583, 0xb353b936,
+ 0xcc9a22a5, 0x20393607, 0x5ff0ad94, 0xdfaa0121, 0xa0639ab2,
+ 0x046e5e0a, 0x7ba7c599, 0xfbfd692c, 0x8434f2bf, 0x28e58a13,
+ 0x572c1180, 0xd776bd35, 0xa8bf26a6, 0x0cb2e21e, 0x737b798d,
+ 0xf321d538, 0x8ce84eab, 0x604b5a09, 0x1f82c19a, 0x9fd86d2f,
+ 0xe011f6bc, 0x441c3204, 0x3bd5a997, 0xbb8f0522, 0xc4469eb1,
+ 0xb9b82a27, 0xc671b1b4, 0x462b1d01, 0x39e28692, 0x9def422a,
+ 0xe226d9b9, 0x627c750c, 0x1db5ee9f, 0xf116fa3d, 0x8edf61ae,
+ 0x0e85cd1b, 0x714c5688, 0xd5419230, 0xaa8809a3, 0x2ad2a516,
+ 0x551b3e85, 0xd12fcc3a, 0xaee657a9, 0x2ebcfb1c, 0x5175608f,
+ 0xf578a437, 0x8ab13fa4, 0x0aeb9311, 0x75220882, 0x99811c20,
+ 0xe64887b3, 0x66122b06, 0x19dbb095, 0xbdd6742d, 0xc21fefbe,
+ 0x4245430b, 0x3d8cd898, 0x40726c0e, 0x3fbbf79d, 0xbfe15b28,
+ 0xc028c0bb, 0x64250403, 0x1bec9f90, 0x9bb63325, 0xe47fa8b6,
+ 0x08dcbc14, 0x77152787, 0xf74f8b32, 0x888610a1, 0x2c8bd419,
+ 0x53424f8a, 0xd318e33f, 0xacd178ac, 0x51cb1426, 0x2e028fb5,
+ 0xae582300, 0xd191b893, 0x759c7c2b, 0x0a55e7b8, 0x8a0f4b0d,
+ 0xf5c6d09e, 0x1965c43c, 0x66ac5faf, 0xe6f6f31a, 0x993f6889,
+ 0x3d32ac31, 0x42fb37a2, 0xc2a19b17, 0xbd680084, 0xc096b412,
+ 0xbf5f2f81, 0x3f058334, 0x40cc18a7, 0xe4c1dc1f, 0x9b08478c,
+ 0x1b52eb39, 0x649b70aa, 0x88386408, 0xf7f1ff9b, 0x77ab532e,
+ 0x0862c8bd, 0xac6f0c05, 0xd3a69796, 0x53fc3b23, 0x2c35a0b0,
+ 0xa801520f, 0xd7c8c99c, 0x57926529, 0x285bfeba, 0x8c563a02,
+ 0xf39fa191, 0x73c50d24, 0x0c0c96b7, 0xe0af8215, 0x9f661986,
+ 0x1f3cb533, 0x60f52ea0, 0xc4f8ea18, 0xbb31718b, 0x3b6bdd3e,
+ 0x44a246ad, 0x395cf23b, 0x469569a8, 0xc6cfc51d, 0xb9065e8e,
+ 0x1d0b9a36, 0x62c201a5, 0xe298ad10, 0x9d513683, 0x71f22221,
+ 0x0e3bb9b2, 0x8e611507, 0xf1a88e94, 0x55a54a2c, 0x2a6cd1bf,
+ 0xaa367d0a, 0xd5ffe699, 0x792e9e35, 0x06e705a6, 0x86bda913,
+ 0xf9743280, 0x5d79f638, 0x22b06dab, 0xa2eac11e, 0xdd235a8d,
+ 0x31804e2f, 0x4e49d5bc, 0xce137909, 0xb1dae29a, 0x15d72622,
+ 0x6a1ebdb1, 0xea441104, 0x958d8a97, 0xe8733e01, 0x97baa592,
+ 0x17e00927, 0x682992b4, 0xcc24560c, 0xb3edcd9f, 0x33b7612a,
+ 0x4c7efab9, 0xa0ddee1b, 0xdf147588, 0x5f4ed93d, 0x208742ae,
+ 0x848a8616, 0xfb431d85, 0x7b19b130, 0x04d02aa3, 0x80e4d81c,
+ 0xff2d438f, 0x7f77ef3a, 0x00be74a9, 0xa4b3b011, 0xdb7a2b82,
+ 0x5b208737, 0x24e91ca4, 0xc84a0806, 0xb7839395, 0x37d93f20,
+ 0x4810a4b3, 0xec1d600b, 0x93d4fb98, 0x138e572d, 0x6c47ccbe,
+ 0x11b97828, 0x6e70e3bb, 0xee2a4f0e, 0x91e3d49d, 0x35ee1025,
+ 0x4a278bb6, 0xca7d2703, 0xb5b4bc90, 0x5917a832, 0x26de33a1,
+ 0xa6849f14, 0xd94d0487, 0x7d40c03f, 0x02895bac, 0x82d3f719,
+ 0xfd1a6c8a},
+ {0x00000000, 0xa396284c, 0x9c5d56d9, 0x3fcb7e95, 0xe3cbabf3,
+ 0x405d83bf, 0x7f96fd2a, 0xdc00d566, 0x1ce651a7, 0xbf7079eb,
+ 0x80bb077e, 0x232d2f32, 0xff2dfa54, 0x5cbbd218, 0x6370ac8d,
+ 0xc0e684c1, 0x39cca34e, 0x9a5a8b02, 0xa591f597, 0x0607dddb,
+ 0xda0708bd, 0x799120f1, 0x465a5e64, 0xe5cc7628, 0x252af2e9,
+ 0x86bcdaa5, 0xb977a430, 0x1ae18c7c, 0xc6e1591a, 0x65777156,
+ 0x5abc0fc3, 0xf92a278f, 0x7399469c, 0xd00f6ed0, 0xefc41045,
+ 0x4c523809, 0x9052ed6f, 0x33c4c523, 0x0c0fbbb6, 0xaf9993fa,
+ 0x6f7f173b, 0xcce93f77, 0xf32241e2, 0x50b469ae, 0x8cb4bcc8,
+ 0x2f229484, 0x10e9ea11, 0xb37fc25d, 0x4a55e5d2, 0xe9c3cd9e,
+ 0xd608b30b, 0x759e9b47, 0xa99e4e21, 0x0a08666d, 0x35c318f8,
+ 0x965530b4, 0x56b3b475, 0xf5259c39, 0xcaeee2ac, 0x6978cae0,
+ 0xb5781f86, 0x16ee37ca, 0x2925495f, 0x8ab36113, 0xe7328d38,
+ 0x44a4a574, 0x7b6fdbe1, 0xd8f9f3ad, 0x04f926cb, 0xa76f0e87,
+ 0x98a47012, 0x3b32585e, 0xfbd4dc9f, 0x5842f4d3, 0x67898a46,
+ 0xc41fa20a, 0x181f776c, 0xbb895f20, 0x844221b5, 0x27d409f9,
+ 0xdefe2e76, 0x7d68063a, 0x42a378af, 0xe13550e3, 0x3d358585,
+ 0x9ea3adc9, 0xa168d35c, 0x02fefb10, 0xc2187fd1, 0x618e579d,
+ 0x5e452908, 0xfdd30144, 0x21d3d422, 0x8245fc6e, 0xbd8e82fb,
+ 0x1e18aab7, 0x94abcba4, 0x373de3e8, 0x08f69d7d, 0xab60b531,
+ 0x77606057, 0xd4f6481b, 0xeb3d368e, 0x48ab1ec2, 0x884d9a03,
+ 0x2bdbb24f, 0x1410ccda, 0xb786e496, 0x6b8631f0, 0xc81019bc,
+ 0xf7db6729, 0x544d4f65, 0xad6768ea, 0x0ef140a6, 0x313a3e33,
+ 0x92ac167f, 0x4eacc319, 0xed3aeb55, 0xd2f195c0, 0x7167bd8c,
+ 0xb181394d, 0x12171101, 0x2ddc6f94, 0x8e4a47d8, 0x524a92be,
+ 0xf1dcbaf2, 0xce17c467, 0x6d81ec2b, 0x15141c31, 0xb682347d,
+ 0x89494ae8, 0x2adf62a4, 0xf6dfb7c2, 0x55499f8e, 0x6a82e11b,
+ 0xc914c957, 0x09f24d96, 0xaa6465da, 0x95af1b4f, 0x36393303,
+ 0xea39e665, 0x49afce29, 0x7664b0bc, 0xd5f298f0, 0x2cd8bf7f,
+ 0x8f4e9733, 0xb085e9a6, 0x1313c1ea, 0xcf13148c, 0x6c853cc0,
+ 0x534e4255, 0xf0d86a19, 0x303eeed8, 0x93a8c694, 0xac63b801,
+ 0x0ff5904d, 0xd3f5452b, 0x70636d67, 0x4fa813f2, 0xec3e3bbe,
+ 0x668d5aad, 0xc51b72e1, 0xfad00c74, 0x59462438, 0x8546f15e,
+ 0x26d0d912, 0x191ba787, 0xba8d8fcb, 0x7a6b0b0a, 0xd9fd2346,
+ 0xe6365dd3, 0x45a0759f, 0x99a0a0f9, 0x3a3688b5, 0x05fdf620,
+ 0xa66bde6c, 0x5f41f9e3, 0xfcd7d1af, 0xc31caf3a, 0x608a8776,
+ 0xbc8a5210, 0x1f1c7a5c, 0x20d704c9, 0x83412c85, 0x43a7a844,
+ 0xe0318008, 0xdffafe9d, 0x7c6cd6d1, 0xa06c03b7, 0x03fa2bfb,
+ 0x3c31556e, 0x9fa77d22, 0xf2269109, 0x51b0b945, 0x6e7bc7d0,
+ 0xcdedef9c, 0x11ed3afa, 0xb27b12b6, 0x8db06c23, 0x2e26446f,
+ 0xeec0c0ae, 0x4d56e8e2, 0x729d9677, 0xd10bbe3b, 0x0d0b6b5d,
+ 0xae9d4311, 0x91563d84, 0x32c015c8, 0xcbea3247, 0x687c1a0b,
+ 0x57b7649e, 0xf4214cd2, 0x282199b4, 0x8bb7b1f8, 0xb47ccf6d,
+ 0x17eae721, 0xd70c63e0, 0x749a4bac, 0x4b513539, 0xe8c71d75,
+ 0x34c7c813, 0x9751e05f, 0xa89a9eca, 0x0b0cb686, 0x81bfd795,
+ 0x2229ffd9, 0x1de2814c, 0xbe74a900, 0x62747c66, 0xc1e2542a,
+ 0xfe292abf, 0x5dbf02f3, 0x9d598632, 0x3ecfae7e, 0x0104d0eb,
+ 0xa292f8a7, 0x7e922dc1, 0xdd04058d, 0xe2cf7b18, 0x41595354,
+ 0xb87374db, 0x1be55c97, 0x242e2202, 0x87b80a4e, 0x5bb8df28,
+ 0xf82ef764, 0xc7e589f1, 0x6473a1bd, 0xa495257c, 0x07030d30,
+ 0x38c873a5, 0x9b5e5be9, 0x475e8e8f, 0xe4c8a6c3, 0xdb03d856,
+ 0x7895f01a},
+ {0x00000000, 0x2a283862, 0x545070c4, 0x7e7848a6, 0xa8a0e188,
+ 0x8288d9ea, 0xfcf0914c, 0xd6d8a92e, 0x8a30c551, 0xa018fd33,
+ 0xde60b595, 0xf4488df7, 0x229024d9, 0x08b81cbb, 0x76c0541d,
+ 0x5ce86c7f, 0xcf108ce3, 0xe538b481, 0x9b40fc27, 0xb168c445,
+ 0x67b06d6b, 0x4d985509, 0x33e01daf, 0x19c825cd, 0x452049b2,
+ 0x6f0871d0, 0x11703976, 0x3b580114, 0xed80a83a, 0xc7a89058,
+ 0xb9d0d8fe, 0x93f8e09c, 0x45501f87, 0x6f7827e5, 0x11006f43,
+ 0x3b285721, 0xedf0fe0f, 0xc7d8c66d, 0xb9a08ecb, 0x9388b6a9,
+ 0xcf60dad6, 0xe548e2b4, 0x9b30aa12, 0xb1189270, 0x67c03b5e,
+ 0x4de8033c, 0x33904b9a, 0x19b873f8, 0x8a409364, 0xa068ab06,
+ 0xde10e3a0, 0xf438dbc2, 0x22e072ec, 0x08c84a8e, 0x76b00228,
+ 0x5c983a4a, 0x00705635, 0x2a586e57, 0x542026f1, 0x7e081e93,
+ 0xa8d0b7bd, 0x82f88fdf, 0xfc80c779, 0xd6a8ff1b, 0x8aa03f0e,
+ 0xa088076c, 0xdef04fca, 0xf4d877a8, 0x2200de86, 0x0828e6e4,
+ 0x7650ae42, 0x5c789620, 0x0090fa5f, 0x2ab8c23d, 0x54c08a9b,
+ 0x7ee8b2f9, 0xa8301bd7, 0x821823b5, 0xfc606b13, 0xd6485371,
+ 0x45b0b3ed, 0x6f988b8f, 0x11e0c329, 0x3bc8fb4b, 0xed105265,
+ 0xc7386a07, 0xb94022a1, 0x93681ac3, 0xcf8076bc, 0xe5a84ede,
+ 0x9bd00678, 0xb1f83e1a, 0x67209734, 0x4d08af56, 0x3370e7f0,
+ 0x1958df92, 0xcff02089, 0xe5d818eb, 0x9ba0504d, 0xb188682f,
+ 0x6750c101, 0x4d78f963, 0x3300b1c5, 0x192889a7, 0x45c0e5d8,
+ 0x6fe8ddba, 0x1190951c, 0x3bb8ad7e, 0xed600450, 0xc7483c32,
+ 0xb9307494, 0x93184cf6, 0x00e0ac6a, 0x2ac89408, 0x54b0dcae,
+ 0x7e98e4cc, 0xa8404de2, 0x82687580, 0xfc103d26, 0xd6380544,
+ 0x8ad0693b, 0xa0f85159, 0xde8019ff, 0xf4a8219d, 0x227088b3,
+ 0x0858b0d1, 0x7620f877, 0x5c08c015, 0xce31785d, 0xe419403f,
+ 0x9a610899, 0xb04930fb, 0x669199d5, 0x4cb9a1b7, 0x32c1e911,
+ 0x18e9d173, 0x4401bd0c, 0x6e29856e, 0x1051cdc8, 0x3a79f5aa,
+ 0xeca15c84, 0xc68964e6, 0xb8f12c40, 0x92d91422, 0x0121f4be,
+ 0x2b09ccdc, 0x5571847a, 0x7f59bc18, 0xa9811536, 0x83a92d54,
+ 0xfdd165f2, 0xd7f95d90, 0x8b1131ef, 0xa139098d, 0xdf41412b,
+ 0xf5697949, 0x23b1d067, 0x0999e805, 0x77e1a0a3, 0x5dc998c1,
+ 0x8b6167da, 0xa1495fb8, 0xdf31171e, 0xf5192f7c, 0x23c18652,
+ 0x09e9be30, 0x7791f696, 0x5db9cef4, 0x0151a28b, 0x2b799ae9,
+ 0x5501d24f, 0x7f29ea2d, 0xa9f14303, 0x83d97b61, 0xfda133c7,
+ 0xd7890ba5, 0x4471eb39, 0x6e59d35b, 0x10219bfd, 0x3a09a39f,
+ 0xecd10ab1, 0xc6f932d3, 0xb8817a75, 0x92a94217, 0xce412e68,
+ 0xe469160a, 0x9a115eac, 0xb03966ce, 0x66e1cfe0, 0x4cc9f782,
+ 0x32b1bf24, 0x18998746, 0x44914753, 0x6eb97f31, 0x10c13797,
+ 0x3ae90ff5, 0xec31a6db, 0xc6199eb9, 0xb861d61f, 0x9249ee7d,
+ 0xcea18202, 0xe489ba60, 0x9af1f2c6, 0xb0d9caa4, 0x6601638a,
+ 0x4c295be8, 0x3251134e, 0x18792b2c, 0x8b81cbb0, 0xa1a9f3d2,
+ 0xdfd1bb74, 0xf5f98316, 0x23212a38, 0x0909125a, 0x77715afc,
+ 0x5d59629e, 0x01b10ee1, 0x2b993683, 0x55e17e25, 0x7fc94647,
+ 0xa911ef69, 0x8339d70b, 0xfd419fad, 0xd769a7cf, 0x01c158d4,
+ 0x2be960b6, 0x55912810, 0x7fb91072, 0xa961b95c, 0x8349813e,
+ 0xfd31c998, 0xd719f1fa, 0x8bf19d85, 0xa1d9a5e7, 0xdfa1ed41,
+ 0xf589d523, 0x23517c0d, 0x0979446f, 0x77010cc9, 0x5d2934ab,
+ 0xced1d437, 0xe4f9ec55, 0x9a81a4f3, 0xb0a99c91, 0x667135bf,
+ 0x4c590ddd, 0x3221457b, 0x18097d19, 0x44e11166, 0x6ec92904,
+ 0x10b161a2, 0x3a9959c0, 0xec41f0ee, 0xc669c88c, 0xb811802a,
+ 0x9239b848},
+ {0x00000000, 0x4713f6fb, 0x8e27edf6, 0xc9341b0d, 0xc73eddad,
+ 0x802d2b56, 0x4919305b, 0x0e0ac6a0, 0x550cbd1b, 0x121f4be0,
+ 0xdb2b50ed, 0x9c38a616, 0x923260b6, 0xd521964d, 0x1c158d40,
+ 0x5b067bbb, 0xaa197a36, 0xed0a8ccd, 0x243e97c0, 0x632d613b,
+ 0x6d27a79b, 0x2a345160, 0xe3004a6d, 0xa413bc96, 0xff15c72d,
+ 0xb80631d6, 0x71322adb, 0x3621dc20, 0x382b1a80, 0x7f38ec7b,
+ 0xb60cf776, 0xf11f018d, 0x8f43f22d, 0xc85004d6, 0x01641fdb,
+ 0x4677e920, 0x487d2f80, 0x0f6ed97b, 0xc65ac276, 0x8149348d,
+ 0xda4f4f36, 0x9d5cb9cd, 0x5468a2c0, 0x137b543b, 0x1d71929b,
+ 0x5a626460, 0x93567f6d, 0xd4458996, 0x255a881b, 0x62497ee0,
+ 0xab7d65ed, 0xec6e9316, 0xe26455b6, 0xa577a34d, 0x6c43b840,
+ 0x2b504ebb, 0x70563500, 0x3745c3fb, 0xfe71d8f6, 0xb9622e0d,
+ 0xb768e8ad, 0xf07b1e56, 0x394f055b, 0x7e5cf3a0, 0xc5f6e21b,
+ 0x82e514e0, 0x4bd10fed, 0x0cc2f916, 0x02c83fb6, 0x45dbc94d,
+ 0x8cefd240, 0xcbfc24bb, 0x90fa5f00, 0xd7e9a9fb, 0x1eddb2f6,
+ 0x59ce440d, 0x57c482ad, 0x10d77456, 0xd9e36f5b, 0x9ef099a0,
+ 0x6fef982d, 0x28fc6ed6, 0xe1c875db, 0xa6db8320, 0xa8d14580,
+ 0xefc2b37b, 0x26f6a876, 0x61e55e8d, 0x3ae32536, 0x7df0d3cd,
+ 0xb4c4c8c0, 0xf3d73e3b, 0xfdddf89b, 0xbace0e60, 0x73fa156d,
+ 0x34e9e396, 0x4ab51036, 0x0da6e6cd, 0xc492fdc0, 0x83810b3b,
+ 0x8d8bcd9b, 0xca983b60, 0x03ac206d, 0x44bfd696, 0x1fb9ad2d,
+ 0x58aa5bd6, 0x919e40db, 0xd68db620, 0xd8877080, 0x9f94867b,
+ 0x56a09d76, 0x11b36b8d, 0xe0ac6a00, 0xa7bf9cfb, 0x6e8b87f6,
+ 0x2998710d, 0x2792b7ad, 0x60814156, 0xa9b55a5b, 0xeea6aca0,
+ 0xb5a0d71b, 0xf2b321e0, 0x3b873aed, 0x7c94cc16, 0x729e0ab6,
+ 0x358dfc4d, 0xfcb9e740, 0xbbaa11bb, 0x509cc277, 0x178f348c,
+ 0xdebb2f81, 0x99a8d97a, 0x97a21fda, 0xd0b1e921, 0x1985f22c,
+ 0x5e9604d7, 0x05907f6c, 0x42838997, 0x8bb7929a, 0xcca46461,
+ 0xc2aea2c1, 0x85bd543a, 0x4c894f37, 0x0b9ab9cc, 0xfa85b841,
+ 0xbd964eba, 0x74a255b7, 0x33b1a34c, 0x3dbb65ec, 0x7aa89317,
+ 0xb39c881a, 0xf48f7ee1, 0xaf89055a, 0xe89af3a1, 0x21aee8ac,
+ 0x66bd1e57, 0x68b7d8f7, 0x2fa42e0c, 0xe6903501, 0xa183c3fa,
+ 0xdfdf305a, 0x98ccc6a1, 0x51f8ddac, 0x16eb2b57, 0x18e1edf7,
+ 0x5ff21b0c, 0x96c60001, 0xd1d5f6fa, 0x8ad38d41, 0xcdc07bba,
+ 0x04f460b7, 0x43e7964c, 0x4ded50ec, 0x0afea617, 0xc3cabd1a,
+ 0x84d94be1, 0x75c64a6c, 0x32d5bc97, 0xfbe1a79a, 0xbcf25161,
+ 0xb2f897c1, 0xf5eb613a, 0x3cdf7a37, 0x7bcc8ccc, 0x20caf777,
+ 0x67d9018c, 0xaeed1a81, 0xe9feec7a, 0xe7f42ada, 0xa0e7dc21,
+ 0x69d3c72c, 0x2ec031d7, 0x956a206c, 0xd279d697, 0x1b4dcd9a,
+ 0x5c5e3b61, 0x5254fdc1, 0x15470b3a, 0xdc731037, 0x9b60e6cc,
+ 0xc0669d77, 0x87756b8c, 0x4e417081, 0x0952867a, 0x075840da,
+ 0x404bb621, 0x897fad2c, 0xce6c5bd7, 0x3f735a5a, 0x7860aca1,
+ 0xb154b7ac, 0xf6474157, 0xf84d87f7, 0xbf5e710c, 0x766a6a01,
+ 0x31799cfa, 0x6a7fe741, 0x2d6c11ba, 0xe4580ab7, 0xa34bfc4c,
+ 0xad413aec, 0xea52cc17, 0x2366d71a, 0x647521e1, 0x1a29d241,
+ 0x5d3a24ba, 0x940e3fb7, 0xd31dc94c, 0xdd170fec, 0x9a04f917,
+ 0x5330e21a, 0x142314e1, 0x4f256f5a, 0x083699a1, 0xc10282ac,
+ 0x86117457, 0x881bb2f7, 0xcf08440c, 0x063c5f01, 0x412fa9fa,
+ 0xb030a877, 0xf7235e8c, 0x3e174581, 0x7904b37a, 0x770e75da,
+ 0x301d8321, 0xf929982c, 0xbe3a6ed7, 0xe53c156c, 0xa22fe397,
+ 0x6b1bf89a, 0x2c080e61, 0x2202c8c1, 0x65113e3a, 0xac252537,
+ 0xeb36d3cc},
+ {0x00000000, 0xa13984ee, 0x99020f9d, 0x383b8b73, 0xe975197b,
+ 0x484c9d95, 0x707716e6, 0xd14e9208, 0x099b34b7, 0xa8a2b059,
+ 0x90993b2a, 0x31a0bfc4, 0xe0ee2dcc, 0x41d7a922, 0x79ec2251,
+ 0xd8d5a6bf, 0x1336696e, 0xb20fed80, 0x8a3466f3, 0x2b0de21d,
+ 0xfa437015, 0x5b7af4fb, 0x63417f88, 0xc278fb66, 0x1aad5dd9,
+ 0xbb94d937, 0x83af5244, 0x2296d6aa, 0xf3d844a2, 0x52e1c04c,
+ 0x6ada4b3f, 0xcbe3cfd1, 0x266cd2dc, 0x87555632, 0xbf6edd41,
+ 0x1e5759af, 0xcf19cba7, 0x6e204f49, 0x561bc43a, 0xf72240d4,
+ 0x2ff7e66b, 0x8ece6285, 0xb6f5e9f6, 0x17cc6d18, 0xc682ff10,
+ 0x67bb7bfe, 0x5f80f08d, 0xfeb97463, 0x355abbb2, 0x94633f5c,
+ 0xac58b42f, 0x0d6130c1, 0xdc2fa2c9, 0x7d162627, 0x452dad54,
+ 0xe41429ba, 0x3cc18f05, 0x9df80beb, 0xa5c38098, 0x04fa0476,
+ 0xd5b4967e, 0x748d1290, 0x4cb699e3, 0xed8f1d0d, 0x4cd9a5b8,
+ 0xede02156, 0xd5dbaa25, 0x74e22ecb, 0xa5acbcc3, 0x0495382d,
+ 0x3caeb35e, 0x9d9737b0, 0x4542910f, 0xe47b15e1, 0xdc409e92,
+ 0x7d791a7c, 0xac378874, 0x0d0e0c9a, 0x353587e9, 0x940c0307,
+ 0x5fefccd6, 0xfed64838, 0xc6edc34b, 0x67d447a5, 0xb69ad5ad,
+ 0x17a35143, 0x2f98da30, 0x8ea15ede, 0x5674f861, 0xf74d7c8f,
+ 0xcf76f7fc, 0x6e4f7312, 0xbf01e11a, 0x1e3865f4, 0x2603ee87,
+ 0x873a6a69, 0x6ab57764, 0xcb8cf38a, 0xf3b778f9, 0x528efc17,
+ 0x83c06e1f, 0x22f9eaf1, 0x1ac26182, 0xbbfbe56c, 0x632e43d3,
+ 0xc217c73d, 0xfa2c4c4e, 0x5b15c8a0, 0x8a5b5aa8, 0x2b62de46,
+ 0x13595535, 0xb260d1db, 0x79831e0a, 0xd8ba9ae4, 0xe0811197,
+ 0x41b89579, 0x90f60771, 0x31cf839f, 0x09f408ec, 0xa8cd8c02,
+ 0x70182abd, 0xd121ae53, 0xe91a2520, 0x4823a1ce, 0x996d33c6,
+ 0x3854b728, 0x006f3c5b, 0xa156b8b5, 0x99b34b70, 0x388acf9e,
+ 0x00b144ed, 0xa188c003, 0x70c6520b, 0xd1ffd6e5, 0xe9c45d96,
+ 0x48fdd978, 0x90287fc7, 0x3111fb29, 0x092a705a, 0xa813f4b4,
+ 0x795d66bc, 0xd864e252, 0xe05f6921, 0x4166edcf, 0x8a85221e,
+ 0x2bbca6f0, 0x13872d83, 0xb2bea96d, 0x63f03b65, 0xc2c9bf8b,
+ 0xfaf234f8, 0x5bcbb016, 0x831e16a9, 0x22279247, 0x1a1c1934,
+ 0xbb259dda, 0x6a6b0fd2, 0xcb528b3c, 0xf369004f, 0x525084a1,
+ 0xbfdf99ac, 0x1ee61d42, 0x26dd9631, 0x87e412df, 0x56aa80d7,
+ 0xf7930439, 0xcfa88f4a, 0x6e910ba4, 0xb644ad1b, 0x177d29f5,
+ 0x2f46a286, 0x8e7f2668, 0x5f31b460, 0xfe08308e, 0xc633bbfd,
+ 0x670a3f13, 0xace9f0c2, 0x0dd0742c, 0x35ebff5f, 0x94d27bb1,
+ 0x459ce9b9, 0xe4a56d57, 0xdc9ee624, 0x7da762ca, 0xa572c475,
+ 0x044b409b, 0x3c70cbe8, 0x9d494f06, 0x4c07dd0e, 0xed3e59e0,
+ 0xd505d293, 0x743c567d, 0xd56aeec8, 0x74536a26, 0x4c68e155,
+ 0xed5165bb, 0x3c1ff7b3, 0x9d26735d, 0xa51df82e, 0x04247cc0,
+ 0xdcf1da7f, 0x7dc85e91, 0x45f3d5e2, 0xe4ca510c, 0x3584c304,
+ 0x94bd47ea, 0xac86cc99, 0x0dbf4877, 0xc65c87a6, 0x67650348,
+ 0x5f5e883b, 0xfe670cd5, 0x2f299edd, 0x8e101a33, 0xb62b9140,
+ 0x171215ae, 0xcfc7b311, 0x6efe37ff, 0x56c5bc8c, 0xf7fc3862,
+ 0x26b2aa6a, 0x878b2e84, 0xbfb0a5f7, 0x1e892119, 0xf3063c14,
+ 0x523fb8fa, 0x6a043389, 0xcb3db767, 0x1a73256f, 0xbb4aa181,
+ 0x83712af2, 0x2248ae1c, 0xfa9d08a3, 0x5ba48c4d, 0x639f073e,
+ 0xc2a683d0, 0x13e811d8, 0xb2d19536, 0x8aea1e45, 0x2bd39aab,
+ 0xe030557a, 0x4109d194, 0x79325ae7, 0xd80bde09, 0x09454c01,
+ 0xa87cc8ef, 0x9047439c, 0x317ec772, 0xe9ab61cd, 0x4892e523,
+ 0x70a96e50, 0xd190eabe, 0x00de78b6, 0xa1e7fc58, 0x99dc772b,
+ 0x38e5f3c5},
+ {0x00000000, 0xe81790a1, 0x0b5e2703, 0xe349b7a2, 0x16bc4e06,
+ 0xfeabdea7, 0x1de26905, 0xf5f5f9a4, 0x2d789c0c, 0xc56f0cad,
+ 0x2626bb0f, 0xce312bae, 0x3bc4d20a, 0xd3d342ab, 0x309af509,
+ 0xd88d65a8, 0x5af13818, 0xb2e6a8b9, 0x51af1f1b, 0xb9b88fba,
+ 0x4c4d761e, 0xa45ae6bf, 0x4713511d, 0xaf04c1bc, 0x7789a414,
+ 0x9f9e34b5, 0x7cd78317, 0x94c013b6, 0x6135ea12, 0x89227ab3,
+ 0x6a6bcd11, 0x827c5db0, 0xb5e27030, 0x5df5e091, 0xbebc5733,
+ 0x56abc792, 0xa35e3e36, 0x4b49ae97, 0xa8001935, 0x40178994,
+ 0x989aec3c, 0x708d7c9d, 0x93c4cb3f, 0x7bd35b9e, 0x8e26a23a,
+ 0x6631329b, 0x85788539, 0x6d6f1598, 0xef134828, 0x0704d889,
+ 0xe44d6f2b, 0x0c5aff8a, 0xf9af062e, 0x11b8968f, 0xf2f1212d,
+ 0x1ae6b18c, 0xc26bd424, 0x2a7c4485, 0xc935f327, 0x21226386,
+ 0xd4d79a22, 0x3cc00a83, 0xdf89bd21, 0x379e2d80, 0xb0b5e621,
+ 0x58a27680, 0xbbebc122, 0x53fc5183, 0xa609a827, 0x4e1e3886,
+ 0xad578f24, 0x45401f85, 0x9dcd7a2d, 0x75daea8c, 0x96935d2e,
+ 0x7e84cd8f, 0x8b71342b, 0x6366a48a, 0x802f1328, 0x68388389,
+ 0xea44de39, 0x02534e98, 0xe11af93a, 0x090d699b, 0xfcf8903f,
+ 0x14ef009e, 0xf7a6b73c, 0x1fb1279d, 0xc73c4235, 0x2f2bd294,
+ 0xcc626536, 0x2475f597, 0xd1800c33, 0x39979c92, 0xdade2b30,
+ 0x32c9bb91, 0x05579611, 0xed4006b0, 0x0e09b112, 0xe61e21b3,
+ 0x13ebd817, 0xfbfc48b6, 0x18b5ff14, 0xf0a26fb5, 0x282f0a1d,
+ 0xc0389abc, 0x23712d1e, 0xcb66bdbf, 0x3e93441b, 0xd684d4ba,
+ 0x35cd6318, 0xdddaf3b9, 0x5fa6ae09, 0xb7b13ea8, 0x54f8890a,
+ 0xbcef19ab, 0x491ae00f, 0xa10d70ae, 0x4244c70c, 0xaa5357ad,
+ 0x72de3205, 0x9ac9a2a4, 0x79801506, 0x919785a7, 0x64627c03,
+ 0x8c75eca2, 0x6f3c5b00, 0x872bcba1, 0xba1aca03, 0x520d5aa2,
+ 0xb144ed00, 0x59537da1, 0xaca68405, 0x44b114a4, 0xa7f8a306,
+ 0x4fef33a7, 0x9762560f, 0x7f75c6ae, 0x9c3c710c, 0x742be1ad,
+ 0x81de1809, 0x69c988a8, 0x8a803f0a, 0x6297afab, 0xe0ebf21b,
+ 0x08fc62ba, 0xebb5d518, 0x03a245b9, 0xf657bc1d, 0x1e402cbc,
+ 0xfd099b1e, 0x151e0bbf, 0xcd936e17, 0x2584feb6, 0xc6cd4914,
+ 0x2edad9b5, 0xdb2f2011, 0x3338b0b0, 0xd0710712, 0x386697b3,
+ 0x0ff8ba33, 0xe7ef2a92, 0x04a69d30, 0xecb10d91, 0x1944f435,
+ 0xf1536494, 0x121ad336, 0xfa0d4397, 0x2280263f, 0xca97b69e,
+ 0x29de013c, 0xc1c9919d, 0x343c6839, 0xdc2bf898, 0x3f624f3a,
+ 0xd775df9b, 0x5509822b, 0xbd1e128a, 0x5e57a528, 0xb6403589,
+ 0x43b5cc2d, 0xaba25c8c, 0x48ebeb2e, 0xa0fc7b8f, 0x78711e27,
+ 0x90668e86, 0x732f3924, 0x9b38a985, 0x6ecd5021, 0x86dac080,
+ 0x65937722, 0x8d84e783, 0x0aaf2c22, 0xe2b8bc83, 0x01f10b21,
+ 0xe9e69b80, 0x1c136224, 0xf404f285, 0x174d4527, 0xff5ad586,
+ 0x27d7b02e, 0xcfc0208f, 0x2c89972d, 0xc49e078c, 0x316bfe28,
+ 0xd97c6e89, 0x3a35d92b, 0xd222498a, 0x505e143a, 0xb849849b,
+ 0x5b003339, 0xb317a398, 0x46e25a3c, 0xaef5ca9d, 0x4dbc7d3f,
+ 0xa5abed9e, 0x7d268836, 0x95311897, 0x7678af35, 0x9e6f3f94,
+ 0x6b9ac630, 0x838d5691, 0x60c4e133, 0x88d37192, 0xbf4d5c12,
+ 0x575accb3, 0xb4137b11, 0x5c04ebb0, 0xa9f11214, 0x41e682b5,
+ 0xa2af3517, 0x4ab8a5b6, 0x9235c01e, 0x7a2250bf, 0x996be71d,
+ 0x717c77bc, 0x84898e18, 0x6c9e1eb9, 0x8fd7a91b, 0x67c039ba,
+ 0xe5bc640a, 0x0dabf4ab, 0xeee24309, 0x06f5d3a8, 0xf3002a0c,
+ 0x1b17baad, 0xf85e0d0f, 0x10499dae, 0xc8c4f806, 0x20d368a7,
+ 0xc39adf05, 0x2b8d4fa4, 0xde78b600, 0x366f26a1, 0xd5269103,
+ 0x3d3101a2}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0xa19017e800000000, 0x03275e0b00000000,
+ 0xa2b749e300000000, 0x064ebc1600000000, 0xa7deabfe00000000,
+ 0x0569e21d00000000, 0xa4f9f5f500000000, 0x0c9c782d00000000,
+ 0xad0c6fc500000000, 0x0fbb262600000000, 0xae2b31ce00000000,
+ 0x0ad2c43b00000000, 0xab42d3d300000000, 0x09f59a3000000000,
+ 0xa8658dd800000000, 0x1838f15a00000000, 0xb9a8e6b200000000,
+ 0x1b1faf5100000000, 0xba8fb8b900000000, 0x1e764d4c00000000,
+ 0xbfe65aa400000000, 0x1d51134700000000, 0xbcc104af00000000,
+ 0x14a4897700000000, 0xb5349e9f00000000, 0x1783d77c00000000,
+ 0xb613c09400000000, 0x12ea356100000000, 0xb37a228900000000,
+ 0x11cd6b6a00000000, 0xb05d7c8200000000, 0x3070e2b500000000,
+ 0x91e0f55d00000000, 0x3357bcbe00000000, 0x92c7ab5600000000,
+ 0x363e5ea300000000, 0x97ae494b00000000, 0x351900a800000000,
+ 0x9489174000000000, 0x3cec9a9800000000, 0x9d7c8d7000000000,
+ 0x3fcbc49300000000, 0x9e5bd37b00000000, 0x3aa2268e00000000,
+ 0x9b32316600000000, 0x3985788500000000, 0x98156f6d00000000,
+ 0x284813ef00000000, 0x89d8040700000000, 0x2b6f4de400000000,
+ 0x8aff5a0c00000000, 0x2e06aff900000000, 0x8f96b81100000000,
+ 0x2d21f1f200000000, 0x8cb1e61a00000000, 0x24d46bc200000000,
+ 0x85447c2a00000000, 0x27f335c900000000, 0x8663222100000000,
+ 0x229ad7d400000000, 0x830ac03c00000000, 0x21bd89df00000000,
+ 0x802d9e3700000000, 0x21e6b5b000000000, 0x8076a25800000000,
+ 0x22c1ebbb00000000, 0x8351fc5300000000, 0x27a809a600000000,
+ 0x86381e4e00000000, 0x248f57ad00000000, 0x851f404500000000,
+ 0x2d7acd9d00000000, 0x8ceada7500000000, 0x2e5d939600000000,
+ 0x8fcd847e00000000, 0x2b34718b00000000, 0x8aa4666300000000,
+ 0x28132f8000000000, 0x8983386800000000, 0x39de44ea00000000,
+ 0x984e530200000000, 0x3af91ae100000000, 0x9b690d0900000000,
+ 0x3f90f8fc00000000, 0x9e00ef1400000000, 0x3cb7a6f700000000,
+ 0x9d27b11f00000000, 0x35423cc700000000, 0x94d22b2f00000000,
+ 0x366562cc00000000, 0x97f5752400000000, 0x330c80d100000000,
+ 0x929c973900000000, 0x302bdeda00000000, 0x91bbc93200000000,
+ 0x1196570500000000, 0xb00640ed00000000, 0x12b1090e00000000,
+ 0xb3211ee600000000, 0x17d8eb1300000000, 0xb648fcfb00000000,
+ 0x14ffb51800000000, 0xb56fa2f000000000, 0x1d0a2f2800000000,
+ 0xbc9a38c000000000, 0x1e2d712300000000, 0xbfbd66cb00000000,
+ 0x1b44933e00000000, 0xbad484d600000000, 0x1863cd3500000000,
+ 0xb9f3dadd00000000, 0x09aea65f00000000, 0xa83eb1b700000000,
+ 0x0a89f85400000000, 0xab19efbc00000000, 0x0fe01a4900000000,
+ 0xae700da100000000, 0x0cc7444200000000, 0xad5753aa00000000,
+ 0x0532de7200000000, 0xa4a2c99a00000000, 0x0615807900000000,
+ 0xa785979100000000, 0x037c626400000000, 0xa2ec758c00000000,
+ 0x005b3c6f00000000, 0xa1cb2b8700000000, 0x03ca1aba00000000,
+ 0xa25a0d5200000000, 0x00ed44b100000000, 0xa17d535900000000,
+ 0x0584a6ac00000000, 0xa414b14400000000, 0x06a3f8a700000000,
+ 0xa733ef4f00000000, 0x0f56629700000000, 0xaec6757f00000000,
+ 0x0c713c9c00000000, 0xade12b7400000000, 0x0918de8100000000,
+ 0xa888c96900000000, 0x0a3f808a00000000, 0xabaf976200000000,
+ 0x1bf2ebe000000000, 0xba62fc0800000000, 0x18d5b5eb00000000,
+ 0xb945a20300000000, 0x1dbc57f600000000, 0xbc2c401e00000000,
+ 0x1e9b09fd00000000, 0xbf0b1e1500000000, 0x176e93cd00000000,
+ 0xb6fe842500000000, 0x1449cdc600000000, 0xb5d9da2e00000000,
+ 0x11202fdb00000000, 0xb0b0383300000000, 0x120771d000000000,
+ 0xb397663800000000, 0x33baf80f00000000, 0x922aefe700000000,
+ 0x309da60400000000, 0x910db1ec00000000, 0x35f4441900000000,
+ 0x946453f100000000, 0x36d31a1200000000, 0x97430dfa00000000,
+ 0x3f26802200000000, 0x9eb697ca00000000, 0x3c01de2900000000,
+ 0x9d91c9c100000000, 0x39683c3400000000, 0x98f82bdc00000000,
+ 0x3a4f623f00000000, 0x9bdf75d700000000, 0x2b82095500000000,
+ 0x8a121ebd00000000, 0x28a5575e00000000, 0x893540b600000000,
+ 0x2dccb54300000000, 0x8c5ca2ab00000000, 0x2eebeb4800000000,
+ 0x8f7bfca000000000, 0x271e717800000000, 0x868e669000000000,
+ 0x24392f7300000000, 0x85a9389b00000000, 0x2150cd6e00000000,
+ 0x80c0da8600000000, 0x2277936500000000, 0x83e7848d00000000,
+ 0x222caf0a00000000, 0x83bcb8e200000000, 0x210bf10100000000,
+ 0x809be6e900000000, 0x2462131c00000000, 0x85f204f400000000,
+ 0x27454d1700000000, 0x86d55aff00000000, 0x2eb0d72700000000,
+ 0x8f20c0cf00000000, 0x2d97892c00000000, 0x8c079ec400000000,
+ 0x28fe6b3100000000, 0x896e7cd900000000, 0x2bd9353a00000000,
+ 0x8a4922d200000000, 0x3a145e5000000000, 0x9b8449b800000000,
+ 0x3933005b00000000, 0x98a317b300000000, 0x3c5ae24600000000,
+ 0x9dcaf5ae00000000, 0x3f7dbc4d00000000, 0x9eedaba500000000,
+ 0x3688267d00000000, 0x9718319500000000, 0x35af787600000000,
+ 0x943f6f9e00000000, 0x30c69a6b00000000, 0x91568d8300000000,
+ 0x33e1c46000000000, 0x9271d38800000000, 0x125c4dbf00000000,
+ 0xb3cc5a5700000000, 0x117b13b400000000, 0xb0eb045c00000000,
+ 0x1412f1a900000000, 0xb582e64100000000, 0x1735afa200000000,
+ 0xb6a5b84a00000000, 0x1ec0359200000000, 0xbf50227a00000000,
+ 0x1de76b9900000000, 0xbc777c7100000000, 0x188e898400000000,
+ 0xb91e9e6c00000000, 0x1ba9d78f00000000, 0xba39c06700000000,
+ 0x0a64bce500000000, 0xabf4ab0d00000000, 0x0943e2ee00000000,
+ 0xa8d3f50600000000, 0x0c2a00f300000000, 0xadba171b00000000,
+ 0x0f0d5ef800000000, 0xae9d491000000000, 0x06f8c4c800000000,
+ 0xa768d32000000000, 0x05df9ac300000000, 0xa44f8d2b00000000,
+ 0x00b678de00000000, 0xa1266f3600000000, 0x039126d500000000,
+ 0xa201313d00000000},
+ {0x0000000000000000, 0xee8439a100000000, 0x9d0f029900000000,
+ 0x738b3b3800000000, 0x7b1975e900000000, 0x959d4c4800000000,
+ 0xe616777000000000, 0x08924ed100000000, 0xb7349b0900000000,
+ 0x59b0a2a800000000, 0x2a3b999000000000, 0xc4bfa03100000000,
+ 0xcc2deee000000000, 0x22a9d74100000000, 0x5122ec7900000000,
+ 0xbfa6d5d800000000, 0x6e69361300000000, 0x80ed0fb200000000,
+ 0xf366348a00000000, 0x1de20d2b00000000, 0x157043fa00000000,
+ 0xfbf47a5b00000000, 0x887f416300000000, 0x66fb78c200000000,
+ 0xd95dad1a00000000, 0x37d994bb00000000, 0x4452af8300000000,
+ 0xaad6962200000000, 0xa244d8f300000000, 0x4cc0e15200000000,
+ 0x3f4bda6a00000000, 0xd1cfe3cb00000000, 0xdcd26c2600000000,
+ 0x3256558700000000, 0x41dd6ebf00000000, 0xaf59571e00000000,
+ 0xa7cb19cf00000000, 0x494f206e00000000, 0x3ac41b5600000000,
+ 0xd44022f700000000, 0x6be6f72f00000000, 0x8562ce8e00000000,
+ 0xf6e9f5b600000000, 0x186dcc1700000000, 0x10ff82c600000000,
+ 0xfe7bbb6700000000, 0x8df0805f00000000, 0x6374b9fe00000000,
+ 0xb2bb5a3500000000, 0x5c3f639400000000, 0x2fb458ac00000000,
+ 0xc130610d00000000, 0xc9a22fdc00000000, 0x2726167d00000000,
+ 0x54ad2d4500000000, 0xba2914e400000000, 0x058fc13c00000000,
+ 0xeb0bf89d00000000, 0x9880c3a500000000, 0x7604fa0400000000,
+ 0x7e96b4d500000000, 0x90128d7400000000, 0xe399b64c00000000,
+ 0x0d1d8fed00000000, 0xb8a5d94c00000000, 0x5621e0ed00000000,
+ 0x25aadbd500000000, 0xcb2ee27400000000, 0xc3bcaca500000000,
+ 0x2d38950400000000, 0x5eb3ae3c00000000, 0xb037979d00000000,
+ 0x0f91424500000000, 0xe1157be400000000, 0x929e40dc00000000,
+ 0x7c1a797d00000000, 0x748837ac00000000, 0x9a0c0e0d00000000,
+ 0xe987353500000000, 0x07030c9400000000, 0xd6ccef5f00000000,
+ 0x3848d6fe00000000, 0x4bc3edc600000000, 0xa547d46700000000,
+ 0xadd59ab600000000, 0x4351a31700000000, 0x30da982f00000000,
+ 0xde5ea18e00000000, 0x61f8745600000000, 0x8f7c4df700000000,
+ 0xfcf776cf00000000, 0x12734f6e00000000, 0x1ae101bf00000000,
+ 0xf465381e00000000, 0x87ee032600000000, 0x696a3a8700000000,
+ 0x6477b56a00000000, 0x8af38ccb00000000, 0xf978b7f300000000,
+ 0x17fc8e5200000000, 0x1f6ec08300000000, 0xf1eaf92200000000,
+ 0x8261c21a00000000, 0x6ce5fbbb00000000, 0xd3432e6300000000,
+ 0x3dc717c200000000, 0x4e4c2cfa00000000, 0xa0c8155b00000000,
+ 0xa85a5b8a00000000, 0x46de622b00000000, 0x3555591300000000,
+ 0xdbd160b200000000, 0x0a1e837900000000, 0xe49abad800000000,
+ 0x971181e000000000, 0x7995b84100000000, 0x7107f69000000000,
+ 0x9f83cf3100000000, 0xec08f40900000000, 0x028ccda800000000,
+ 0xbd2a187000000000, 0x53ae21d100000000, 0x20251ae900000000,
+ 0xcea1234800000000, 0xc6336d9900000000, 0x28b7543800000000,
+ 0x5b3c6f0000000000, 0xb5b856a100000000, 0x704bb39900000000,
+ 0x9ecf8a3800000000, 0xed44b10000000000, 0x03c088a100000000,
+ 0x0b52c67000000000, 0xe5d6ffd100000000, 0x965dc4e900000000,
+ 0x78d9fd4800000000, 0xc77f289000000000, 0x29fb113100000000,
+ 0x5a702a0900000000, 0xb4f413a800000000, 0xbc665d7900000000,
+ 0x52e264d800000000, 0x21695fe000000000, 0xcfed664100000000,
+ 0x1e22858a00000000, 0xf0a6bc2b00000000, 0x832d871300000000,
+ 0x6da9beb200000000, 0x653bf06300000000, 0x8bbfc9c200000000,
+ 0xf834f2fa00000000, 0x16b0cb5b00000000, 0xa9161e8300000000,
+ 0x4792272200000000, 0x34191c1a00000000, 0xda9d25bb00000000,
+ 0xd20f6b6a00000000, 0x3c8b52cb00000000, 0x4f0069f300000000,
+ 0xa184505200000000, 0xac99dfbf00000000, 0x421de61e00000000,
+ 0x3196dd2600000000, 0xdf12e48700000000, 0xd780aa5600000000,
+ 0x390493f700000000, 0x4a8fa8cf00000000, 0xa40b916e00000000,
+ 0x1bad44b600000000, 0xf5297d1700000000, 0x86a2462f00000000,
+ 0x68267f8e00000000, 0x60b4315f00000000, 0x8e3008fe00000000,
+ 0xfdbb33c600000000, 0x133f0a6700000000, 0xc2f0e9ac00000000,
+ 0x2c74d00d00000000, 0x5fffeb3500000000, 0xb17bd29400000000,
+ 0xb9e99c4500000000, 0x576da5e400000000, 0x24e69edc00000000,
+ 0xca62a77d00000000, 0x75c472a500000000, 0x9b404b0400000000,
+ 0xe8cb703c00000000, 0x064f499d00000000, 0x0edd074c00000000,
+ 0xe0593eed00000000, 0x93d205d500000000, 0x7d563c7400000000,
+ 0xc8ee6ad500000000, 0x266a537400000000, 0x55e1684c00000000,
+ 0xbb6551ed00000000, 0xb3f71f3c00000000, 0x5d73269d00000000,
+ 0x2ef81da500000000, 0xc07c240400000000, 0x7fdaf1dc00000000,
+ 0x915ec87d00000000, 0xe2d5f34500000000, 0x0c51cae400000000,
+ 0x04c3843500000000, 0xea47bd9400000000, 0x99cc86ac00000000,
+ 0x7748bf0d00000000, 0xa6875cc600000000, 0x4803656700000000,
+ 0x3b885e5f00000000, 0xd50c67fe00000000, 0xdd9e292f00000000,
+ 0x331a108e00000000, 0x40912bb600000000, 0xae15121700000000,
+ 0x11b3c7cf00000000, 0xff37fe6e00000000, 0x8cbcc55600000000,
+ 0x6238fcf700000000, 0x6aaab22600000000, 0x842e8b8700000000,
+ 0xf7a5b0bf00000000, 0x1921891e00000000, 0x143c06f300000000,
+ 0xfab83f5200000000, 0x8933046a00000000, 0x67b73dcb00000000,
+ 0x6f25731a00000000, 0x81a14abb00000000, 0xf22a718300000000,
+ 0x1cae482200000000, 0xa3089dfa00000000, 0x4d8ca45b00000000,
+ 0x3e079f6300000000, 0xd083a6c200000000, 0xd811e81300000000,
+ 0x3695d1b200000000, 0x451eea8a00000000, 0xab9ad32b00000000,
+ 0x7a5530e000000000, 0x94d1094100000000, 0xe75a327900000000,
+ 0x09de0bd800000000, 0x014c450900000000, 0xefc87ca800000000,
+ 0x9c43479000000000, 0x72c77e3100000000, 0xcd61abe900000000,
+ 0x23e5924800000000, 0x506ea97000000000, 0xbeea90d100000000,
+ 0xb678de0000000000, 0x58fce7a100000000, 0x2b77dc9900000000,
+ 0xc5f3e53800000000},
+ {0x0000000000000000, 0xfbf6134700000000, 0xf6ed278e00000000,
+ 0x0d1b34c900000000, 0xaddd3ec700000000, 0x562b2d8000000000,
+ 0x5b30194900000000, 0xa0c60a0e00000000, 0x1bbd0c5500000000,
+ 0xe04b1f1200000000, 0xed502bdb00000000, 0x16a6389c00000000,
+ 0xb660329200000000, 0x4d9621d500000000, 0x408d151c00000000,
+ 0xbb7b065b00000000, 0x367a19aa00000000, 0xcd8c0aed00000000,
+ 0xc0973e2400000000, 0x3b612d6300000000, 0x9ba7276d00000000,
+ 0x6051342a00000000, 0x6d4a00e300000000, 0x96bc13a400000000,
+ 0x2dc715ff00000000, 0xd63106b800000000, 0xdb2a327100000000,
+ 0x20dc213600000000, 0x801a2b3800000000, 0x7bec387f00000000,
+ 0x76f70cb600000000, 0x8d011ff100000000, 0x2df2438f00000000,
+ 0xd60450c800000000, 0xdb1f640100000000, 0x20e9774600000000,
+ 0x802f7d4800000000, 0x7bd96e0f00000000, 0x76c25ac600000000,
+ 0x8d34498100000000, 0x364f4fda00000000, 0xcdb95c9d00000000,
+ 0xc0a2685400000000, 0x3b547b1300000000, 0x9b92711d00000000,
+ 0x6064625a00000000, 0x6d7f569300000000, 0x968945d400000000,
+ 0x1b885a2500000000, 0xe07e496200000000, 0xed657dab00000000,
+ 0x16936eec00000000, 0xb65564e200000000, 0x4da377a500000000,
+ 0x40b8436c00000000, 0xbb4e502b00000000, 0x0035567000000000,
+ 0xfbc3453700000000, 0xf6d871fe00000000, 0x0d2e62b900000000,
+ 0xade868b700000000, 0x561e7bf000000000, 0x5b054f3900000000,
+ 0xa0f35c7e00000000, 0x1be2f6c500000000, 0xe014e58200000000,
+ 0xed0fd14b00000000, 0x16f9c20c00000000, 0xb63fc80200000000,
+ 0x4dc9db4500000000, 0x40d2ef8c00000000, 0xbb24fccb00000000,
+ 0x005ffa9000000000, 0xfba9e9d700000000, 0xf6b2dd1e00000000,
+ 0x0d44ce5900000000, 0xad82c45700000000, 0x5674d71000000000,
+ 0x5b6fe3d900000000, 0xa099f09e00000000, 0x2d98ef6f00000000,
+ 0xd66efc2800000000, 0xdb75c8e100000000, 0x2083dba600000000,
+ 0x8045d1a800000000, 0x7bb3c2ef00000000, 0x76a8f62600000000,
+ 0x8d5ee56100000000, 0x3625e33a00000000, 0xcdd3f07d00000000,
+ 0xc0c8c4b400000000, 0x3b3ed7f300000000, 0x9bf8ddfd00000000,
+ 0x600eceba00000000, 0x6d15fa7300000000, 0x96e3e93400000000,
+ 0x3610b54a00000000, 0xcde6a60d00000000, 0xc0fd92c400000000,
+ 0x3b0b818300000000, 0x9bcd8b8d00000000, 0x603b98ca00000000,
+ 0x6d20ac0300000000, 0x96d6bf4400000000, 0x2dadb91f00000000,
+ 0xd65baa5800000000, 0xdb409e9100000000, 0x20b68dd600000000,
+ 0x807087d800000000, 0x7b86949f00000000, 0x769da05600000000,
+ 0x8d6bb31100000000, 0x006aace000000000, 0xfb9cbfa700000000,
+ 0xf6878b6e00000000, 0x0d71982900000000, 0xadb7922700000000,
+ 0x5641816000000000, 0x5b5ab5a900000000, 0xa0aca6ee00000000,
+ 0x1bd7a0b500000000, 0xe021b3f200000000, 0xed3a873b00000000,
+ 0x16cc947c00000000, 0xb60a9e7200000000, 0x4dfc8d3500000000,
+ 0x40e7b9fc00000000, 0xbb11aabb00000000, 0x77c29c5000000000,
+ 0x8c348f1700000000, 0x812fbbde00000000, 0x7ad9a89900000000,
+ 0xda1fa29700000000, 0x21e9b1d000000000, 0x2cf2851900000000,
+ 0xd704965e00000000, 0x6c7f900500000000, 0x9789834200000000,
+ 0x9a92b78b00000000, 0x6164a4cc00000000, 0xc1a2aec200000000,
+ 0x3a54bd8500000000, 0x374f894c00000000, 0xccb99a0b00000000,
+ 0x41b885fa00000000, 0xba4e96bd00000000, 0xb755a27400000000,
+ 0x4ca3b13300000000, 0xec65bb3d00000000, 0x1793a87a00000000,
+ 0x1a889cb300000000, 0xe17e8ff400000000, 0x5a0589af00000000,
+ 0xa1f39ae800000000, 0xace8ae2100000000, 0x571ebd6600000000,
+ 0xf7d8b76800000000, 0x0c2ea42f00000000, 0x013590e600000000,
+ 0xfac383a100000000, 0x5a30dfdf00000000, 0xa1c6cc9800000000,
+ 0xacddf85100000000, 0x572beb1600000000, 0xf7ede11800000000,
+ 0x0c1bf25f00000000, 0x0100c69600000000, 0xfaf6d5d100000000,
+ 0x418dd38a00000000, 0xba7bc0cd00000000, 0xb760f40400000000,
+ 0x4c96e74300000000, 0xec50ed4d00000000, 0x17a6fe0a00000000,
+ 0x1abdcac300000000, 0xe14bd98400000000, 0x6c4ac67500000000,
+ 0x97bcd53200000000, 0x9aa7e1fb00000000, 0x6151f2bc00000000,
+ 0xc197f8b200000000, 0x3a61ebf500000000, 0x377adf3c00000000,
+ 0xcc8ccc7b00000000, 0x77f7ca2000000000, 0x8c01d96700000000,
+ 0x811aedae00000000, 0x7aecfee900000000, 0xda2af4e700000000,
+ 0x21dce7a000000000, 0x2cc7d36900000000, 0xd731c02e00000000,
+ 0x6c206a9500000000, 0x97d679d200000000, 0x9acd4d1b00000000,
+ 0x613b5e5c00000000, 0xc1fd545200000000, 0x3a0b471500000000,
+ 0x371073dc00000000, 0xcce6609b00000000, 0x779d66c000000000,
+ 0x8c6b758700000000, 0x8170414e00000000, 0x7a86520900000000,
+ 0xda40580700000000, 0x21b64b4000000000, 0x2cad7f8900000000,
+ 0xd75b6cce00000000, 0x5a5a733f00000000, 0xa1ac607800000000,
+ 0xacb754b100000000, 0x574147f600000000, 0xf7874df800000000,
+ 0x0c715ebf00000000, 0x016a6a7600000000, 0xfa9c793100000000,
+ 0x41e77f6a00000000, 0xba116c2d00000000, 0xb70a58e400000000,
+ 0x4cfc4ba300000000, 0xec3a41ad00000000, 0x17cc52ea00000000,
+ 0x1ad7662300000000, 0xe121756400000000, 0x41d2291a00000000,
+ 0xba243a5d00000000, 0xb73f0e9400000000, 0x4cc91dd300000000,
+ 0xec0f17dd00000000, 0x17f9049a00000000, 0x1ae2305300000000,
+ 0xe114231400000000, 0x5a6f254f00000000, 0xa199360800000000,
+ 0xac8202c100000000, 0x5774118600000000, 0xf7b21b8800000000,
+ 0x0c4408cf00000000, 0x015f3c0600000000, 0xfaa92f4100000000,
+ 0x77a830b000000000, 0x8c5e23f700000000, 0x8145173e00000000,
+ 0x7ab3047900000000, 0xda750e7700000000, 0x21831d3000000000,
+ 0x2c9829f900000000, 0xd76e3abe00000000, 0x6c153ce500000000,
+ 0x97e32fa200000000, 0x9af81b6b00000000, 0x610e082c00000000,
+ 0xc1c8022200000000, 0x3a3e116500000000, 0x372525ac00000000,
+ 0xccd336eb00000000},
+ {0x0000000000000000, 0x6238282a00000000, 0xc470505400000000,
+ 0xa648787e00000000, 0x88e1a0a800000000, 0xead9888200000000,
+ 0x4c91f0fc00000000, 0x2ea9d8d600000000, 0x51c5308a00000000,
+ 0x33fd18a000000000, 0x95b560de00000000, 0xf78d48f400000000,
+ 0xd924902200000000, 0xbb1cb80800000000, 0x1d54c07600000000,
+ 0x7f6ce85c00000000, 0xe38c10cf00000000, 0x81b438e500000000,
+ 0x27fc409b00000000, 0x45c468b100000000, 0x6b6db06700000000,
+ 0x0955984d00000000, 0xaf1de03300000000, 0xcd25c81900000000,
+ 0xb249204500000000, 0xd071086f00000000, 0x7639701100000000,
+ 0x1401583b00000000, 0x3aa880ed00000000, 0x5890a8c700000000,
+ 0xfed8d0b900000000, 0x9ce0f89300000000, 0x871f504500000000,
+ 0xe527786f00000000, 0x436f001100000000, 0x2157283b00000000,
+ 0x0ffef0ed00000000, 0x6dc6d8c700000000, 0xcb8ea0b900000000,
+ 0xa9b6889300000000, 0xd6da60cf00000000, 0xb4e248e500000000,
+ 0x12aa309b00000000, 0x709218b100000000, 0x5e3bc06700000000,
+ 0x3c03e84d00000000, 0x9a4b903300000000, 0xf873b81900000000,
+ 0x6493408a00000000, 0x06ab68a000000000, 0xa0e310de00000000,
+ 0xc2db38f400000000, 0xec72e02200000000, 0x8e4ac80800000000,
+ 0x2802b07600000000, 0x4a3a985c00000000, 0x3556700000000000,
+ 0x576e582a00000000, 0xf126205400000000, 0x931e087e00000000,
+ 0xbdb7d0a800000000, 0xdf8ff88200000000, 0x79c780fc00000000,
+ 0x1bffa8d600000000, 0x0e3fa08a00000000, 0x6c0788a000000000,
+ 0xca4ff0de00000000, 0xa877d8f400000000, 0x86de002200000000,
+ 0xe4e6280800000000, 0x42ae507600000000, 0x2096785c00000000,
+ 0x5ffa900000000000, 0x3dc2b82a00000000, 0x9b8ac05400000000,
+ 0xf9b2e87e00000000, 0xd71b30a800000000, 0xb523188200000000,
+ 0x136b60fc00000000, 0x715348d600000000, 0xedb3b04500000000,
+ 0x8f8b986f00000000, 0x29c3e01100000000, 0x4bfbc83b00000000,
+ 0x655210ed00000000, 0x076a38c700000000, 0xa12240b900000000,
+ 0xc31a689300000000, 0xbc7680cf00000000, 0xde4ea8e500000000,
+ 0x7806d09b00000000, 0x1a3ef8b100000000, 0x3497206700000000,
+ 0x56af084d00000000, 0xf0e7703300000000, 0x92df581900000000,
+ 0x8920f0cf00000000, 0xeb18d8e500000000, 0x4d50a09b00000000,
+ 0x2f6888b100000000, 0x01c1506700000000, 0x63f9784d00000000,
+ 0xc5b1003300000000, 0xa789281900000000, 0xd8e5c04500000000,
+ 0xbadde86f00000000, 0x1c95901100000000, 0x7eadb83b00000000,
+ 0x500460ed00000000, 0x323c48c700000000, 0x947430b900000000,
+ 0xf64c189300000000, 0x6aace00000000000, 0x0894c82a00000000,
+ 0xaedcb05400000000, 0xcce4987e00000000, 0xe24d40a800000000,
+ 0x8075688200000000, 0x263d10fc00000000, 0x440538d600000000,
+ 0x3b69d08a00000000, 0x5951f8a000000000, 0xff1980de00000000,
+ 0x9d21a8f400000000, 0xb388702200000000, 0xd1b0580800000000,
+ 0x77f8207600000000, 0x15c0085c00000000, 0x5d7831ce00000000,
+ 0x3f4019e400000000, 0x9908619a00000000, 0xfb3049b000000000,
+ 0xd599916600000000, 0xb7a1b94c00000000, 0x11e9c13200000000,
+ 0x73d1e91800000000, 0x0cbd014400000000, 0x6e85296e00000000,
+ 0xc8cd511000000000, 0xaaf5793a00000000, 0x845ca1ec00000000,
+ 0xe66489c600000000, 0x402cf1b800000000, 0x2214d99200000000,
+ 0xbef4210100000000, 0xdccc092b00000000, 0x7a84715500000000,
+ 0x18bc597f00000000, 0x361581a900000000, 0x542da98300000000,
+ 0xf265d1fd00000000, 0x905df9d700000000, 0xef31118b00000000,
+ 0x8d0939a100000000, 0x2b4141df00000000, 0x497969f500000000,
+ 0x67d0b12300000000, 0x05e8990900000000, 0xa3a0e17700000000,
+ 0xc198c95d00000000, 0xda67618b00000000, 0xb85f49a100000000,
+ 0x1e1731df00000000, 0x7c2f19f500000000, 0x5286c12300000000,
+ 0x30bee90900000000, 0x96f6917700000000, 0xf4ceb95d00000000,
+ 0x8ba2510100000000, 0xe99a792b00000000, 0x4fd2015500000000,
+ 0x2dea297f00000000, 0x0343f1a900000000, 0x617bd98300000000,
+ 0xc733a1fd00000000, 0xa50b89d700000000, 0x39eb714400000000,
+ 0x5bd3596e00000000, 0xfd9b211000000000, 0x9fa3093a00000000,
+ 0xb10ad1ec00000000, 0xd332f9c600000000, 0x757a81b800000000,
+ 0x1742a99200000000, 0x682e41ce00000000, 0x0a1669e400000000,
+ 0xac5e119a00000000, 0xce6639b000000000, 0xe0cfe16600000000,
+ 0x82f7c94c00000000, 0x24bfb13200000000, 0x4687991800000000,
+ 0x5347914400000000, 0x317fb96e00000000, 0x9737c11000000000,
+ 0xf50fe93a00000000, 0xdba631ec00000000, 0xb99e19c600000000,
+ 0x1fd661b800000000, 0x7dee499200000000, 0x0282a1ce00000000,
+ 0x60ba89e400000000, 0xc6f2f19a00000000, 0xa4cad9b000000000,
+ 0x8a63016600000000, 0xe85b294c00000000, 0x4e13513200000000,
+ 0x2c2b791800000000, 0xb0cb818b00000000, 0xd2f3a9a100000000,
+ 0x74bbd1df00000000, 0x1683f9f500000000, 0x382a212300000000,
+ 0x5a12090900000000, 0xfc5a717700000000, 0x9e62595d00000000,
+ 0xe10eb10100000000, 0x8336992b00000000, 0x257ee15500000000,
+ 0x4746c97f00000000, 0x69ef11a900000000, 0x0bd7398300000000,
+ 0xad9f41fd00000000, 0xcfa769d700000000, 0xd458c10100000000,
+ 0xb660e92b00000000, 0x1028915500000000, 0x7210b97f00000000,
+ 0x5cb961a900000000, 0x3e81498300000000, 0x98c931fd00000000,
+ 0xfaf119d700000000, 0x859df18b00000000, 0xe7a5d9a100000000,
+ 0x41eda1df00000000, 0x23d589f500000000, 0x0d7c512300000000,
+ 0x6f44790900000000, 0xc90c017700000000, 0xab34295d00000000,
+ 0x37d4d1ce00000000, 0x55ecf9e400000000, 0xf3a4819a00000000,
+ 0x919ca9b000000000, 0xbf35716600000000, 0xdd0d594c00000000,
+ 0x7b45213200000000, 0x197d091800000000, 0x6611e14400000000,
+ 0x0429c96e00000000, 0xa261b11000000000, 0xc059993a00000000,
+ 0xeef041ec00000000, 0x8cc869c600000000, 0x2a8011b800000000,
+ 0x48b8399200000000},
+ {0x0000000000000000, 0x4c2896a300000000, 0xd9565d9c00000000,
+ 0x957ecb3f00000000, 0xf3abcbe300000000, 0xbf835d4000000000,
+ 0x2afd967f00000000, 0x66d500dc00000000, 0xa751e61c00000000,
+ 0xeb7970bf00000000, 0x7e07bb8000000000, 0x322f2d2300000000,
+ 0x54fa2dff00000000, 0x18d2bb5c00000000, 0x8dac706300000000,
+ 0xc184e6c000000000, 0x4ea3cc3900000000, 0x028b5a9a00000000,
+ 0x97f591a500000000, 0xdbdd070600000000, 0xbd0807da00000000,
+ 0xf120917900000000, 0x645e5a4600000000, 0x2876cce500000000,
+ 0xe9f22a2500000000, 0xa5dabc8600000000, 0x30a477b900000000,
+ 0x7c8ce11a00000000, 0x1a59e1c600000000, 0x5671776500000000,
+ 0xc30fbc5a00000000, 0x8f272af900000000, 0x9c46997300000000,
+ 0xd06e0fd000000000, 0x4510c4ef00000000, 0x0938524c00000000,
+ 0x6fed529000000000, 0x23c5c43300000000, 0xb6bb0f0c00000000,
+ 0xfa9399af00000000, 0x3b177f6f00000000, 0x773fe9cc00000000,
+ 0xe24122f300000000, 0xae69b45000000000, 0xc8bcb48c00000000,
+ 0x8494222f00000000, 0x11eae91000000000, 0x5dc27fb300000000,
+ 0xd2e5554a00000000, 0x9ecdc3e900000000, 0x0bb308d600000000,
+ 0x479b9e7500000000, 0x214e9ea900000000, 0x6d66080a00000000,
+ 0xf818c33500000000, 0xb430559600000000, 0x75b4b35600000000,
+ 0x399c25f500000000, 0xace2eeca00000000, 0xe0ca786900000000,
+ 0x861f78b500000000, 0xca37ee1600000000, 0x5f49252900000000,
+ 0x1361b38a00000000, 0x388d32e700000000, 0x74a5a44400000000,
+ 0xe1db6f7b00000000, 0xadf3f9d800000000, 0xcb26f90400000000,
+ 0x870e6fa700000000, 0x1270a49800000000, 0x5e58323b00000000,
+ 0x9fdcd4fb00000000, 0xd3f4425800000000, 0x468a896700000000,
+ 0x0aa21fc400000000, 0x6c771f1800000000, 0x205f89bb00000000,
+ 0xb521428400000000, 0xf909d42700000000, 0x762efede00000000,
+ 0x3a06687d00000000, 0xaf78a34200000000, 0xe35035e100000000,
+ 0x8585353d00000000, 0xc9ada39e00000000, 0x5cd368a100000000,
+ 0x10fbfe0200000000, 0xd17f18c200000000, 0x9d578e6100000000,
+ 0x0829455e00000000, 0x4401d3fd00000000, 0x22d4d32100000000,
+ 0x6efc458200000000, 0xfb828ebd00000000, 0xb7aa181e00000000,
+ 0xa4cbab9400000000, 0xe8e33d3700000000, 0x7d9df60800000000,
+ 0x31b560ab00000000, 0x5760607700000000, 0x1b48f6d400000000,
+ 0x8e363deb00000000, 0xc21eab4800000000, 0x039a4d8800000000,
+ 0x4fb2db2b00000000, 0xdacc101400000000, 0x96e486b700000000,
+ 0xf031866b00000000, 0xbc1910c800000000, 0x2967dbf700000000,
+ 0x654f4d5400000000, 0xea6867ad00000000, 0xa640f10e00000000,
+ 0x333e3a3100000000, 0x7f16ac9200000000, 0x19c3ac4e00000000,
+ 0x55eb3aed00000000, 0xc095f1d200000000, 0x8cbd677100000000,
+ 0x4d3981b100000000, 0x0111171200000000, 0x946fdc2d00000000,
+ 0xd8474a8e00000000, 0xbe924a5200000000, 0xf2badcf100000000,
+ 0x67c417ce00000000, 0x2bec816d00000000, 0x311c141500000000,
+ 0x7d3482b600000000, 0xe84a498900000000, 0xa462df2a00000000,
+ 0xc2b7dff600000000, 0x8e9f495500000000, 0x1be1826a00000000,
+ 0x57c914c900000000, 0x964df20900000000, 0xda6564aa00000000,
+ 0x4f1baf9500000000, 0x0333393600000000, 0x65e639ea00000000,
+ 0x29ceaf4900000000, 0xbcb0647600000000, 0xf098f2d500000000,
+ 0x7fbfd82c00000000, 0x33974e8f00000000, 0xa6e985b000000000,
+ 0xeac1131300000000, 0x8c1413cf00000000, 0xc03c856c00000000,
+ 0x55424e5300000000, 0x196ad8f000000000, 0xd8ee3e3000000000,
+ 0x94c6a89300000000, 0x01b863ac00000000, 0x4d90f50f00000000,
+ 0x2b45f5d300000000, 0x676d637000000000, 0xf213a84f00000000,
+ 0xbe3b3eec00000000, 0xad5a8d6600000000, 0xe1721bc500000000,
+ 0x740cd0fa00000000, 0x3824465900000000, 0x5ef1468500000000,
+ 0x12d9d02600000000, 0x87a71b1900000000, 0xcb8f8dba00000000,
+ 0x0a0b6b7a00000000, 0x4623fdd900000000, 0xd35d36e600000000,
+ 0x9f75a04500000000, 0xf9a0a09900000000, 0xb588363a00000000,
+ 0x20f6fd0500000000, 0x6cde6ba600000000, 0xe3f9415f00000000,
+ 0xafd1d7fc00000000, 0x3aaf1cc300000000, 0x76878a6000000000,
+ 0x10528abc00000000, 0x5c7a1c1f00000000, 0xc904d72000000000,
+ 0x852c418300000000, 0x44a8a74300000000, 0x088031e000000000,
+ 0x9dfefadf00000000, 0xd1d66c7c00000000, 0xb7036ca000000000,
+ 0xfb2bfa0300000000, 0x6e55313c00000000, 0x227da79f00000000,
+ 0x099126f200000000, 0x45b9b05100000000, 0xd0c77b6e00000000,
+ 0x9cefedcd00000000, 0xfa3aed1100000000, 0xb6127bb200000000,
+ 0x236cb08d00000000, 0x6f44262e00000000, 0xaec0c0ee00000000,
+ 0xe2e8564d00000000, 0x77969d7200000000, 0x3bbe0bd100000000,
+ 0x5d6b0b0d00000000, 0x11439dae00000000, 0x843d569100000000,
+ 0xc815c03200000000, 0x4732eacb00000000, 0x0b1a7c6800000000,
+ 0x9e64b75700000000, 0xd24c21f400000000, 0xb499212800000000,
+ 0xf8b1b78b00000000, 0x6dcf7cb400000000, 0x21e7ea1700000000,
+ 0xe0630cd700000000, 0xac4b9a7400000000, 0x3935514b00000000,
+ 0x751dc7e800000000, 0x13c8c73400000000, 0x5fe0519700000000,
+ 0xca9e9aa800000000, 0x86b60c0b00000000, 0x95d7bf8100000000,
+ 0xd9ff292200000000, 0x4c81e21d00000000, 0x00a974be00000000,
+ 0x667c746200000000, 0x2a54e2c100000000, 0xbf2a29fe00000000,
+ 0xf302bf5d00000000, 0x3286599d00000000, 0x7eaecf3e00000000,
+ 0xebd0040100000000, 0xa7f892a200000000, 0xc12d927e00000000,
+ 0x8d0504dd00000000, 0x187bcfe200000000, 0x5453594100000000,
+ 0xdb7473b800000000, 0x975ce51b00000000, 0x02222e2400000000,
+ 0x4e0ab88700000000, 0x28dfb85b00000000, 0x64f72ef800000000,
+ 0xf189e5c700000000, 0xbda1736400000000, 0x7c2595a400000000,
+ 0x300d030700000000, 0xa573c83800000000, 0xe95b5e9b00000000,
+ 0x8f8e5e4700000000, 0xc3a6c8e400000000, 0x56d803db00000000,
+ 0x1af0957800000000},
+ {0x0000000000000000, 0x939bc97f00000000, 0x263793ff00000000,
+ 0xb5ac5a8000000000, 0x0d68572400000000, 0x9ef39e5b00000000,
+ 0x2b5fc4db00000000, 0xb8c40da400000000, 0x1ad0ae4800000000,
+ 0x894b673700000000, 0x3ce73db700000000, 0xaf7cf4c800000000,
+ 0x17b8f96c00000000, 0x8423301300000000, 0x318f6a9300000000,
+ 0xa214a3ec00000000, 0x34a05d9100000000, 0xa73b94ee00000000,
+ 0x1297ce6e00000000, 0x810c071100000000, 0x39c80ab500000000,
+ 0xaa53c3ca00000000, 0x1fff994a00000000, 0x8c64503500000000,
+ 0x2e70f3d900000000, 0xbdeb3aa600000000, 0x0847602600000000,
+ 0x9bdca95900000000, 0x2318a4fd00000000, 0xb0836d8200000000,
+ 0x052f370200000000, 0x96b4fe7d00000000, 0x2946caf900000000,
+ 0xbadd038600000000, 0x0f71590600000000, 0x9cea907900000000,
+ 0x242e9ddd00000000, 0xb7b554a200000000, 0x02190e2200000000,
+ 0x9182c75d00000000, 0x339664b100000000, 0xa00dadce00000000,
+ 0x15a1f74e00000000, 0x863a3e3100000000, 0x3efe339500000000,
+ 0xad65faea00000000, 0x18c9a06a00000000, 0x8b52691500000000,
+ 0x1de6976800000000, 0x8e7d5e1700000000, 0x3bd1049700000000,
+ 0xa84acde800000000, 0x108ec04c00000000, 0x8315093300000000,
+ 0x36b953b300000000, 0xa5229acc00000000, 0x0736392000000000,
+ 0x94adf05f00000000, 0x2101aadf00000000, 0xb29a63a000000000,
+ 0x0a5e6e0400000000, 0x99c5a77b00000000, 0x2c69fdfb00000000,
+ 0xbff2348400000000, 0x138ae52800000000, 0x80112c5700000000,
+ 0x35bd76d700000000, 0xa626bfa800000000, 0x1ee2b20c00000000,
+ 0x8d797b7300000000, 0x38d521f300000000, 0xab4ee88c00000000,
+ 0x095a4b6000000000, 0x9ac1821f00000000, 0x2f6dd89f00000000,
+ 0xbcf611e000000000, 0x04321c4400000000, 0x97a9d53b00000000,
+ 0x22058fbb00000000, 0xb19e46c400000000, 0x272ab8b900000000,
+ 0xb4b171c600000000, 0x011d2b4600000000, 0x9286e23900000000,
+ 0x2a42ef9d00000000, 0xb9d926e200000000, 0x0c757c6200000000,
+ 0x9feeb51d00000000, 0x3dfa16f100000000, 0xae61df8e00000000,
+ 0x1bcd850e00000000, 0x88564c7100000000, 0x309241d500000000,
+ 0xa30988aa00000000, 0x16a5d22a00000000, 0x853e1b5500000000,
+ 0x3acc2fd100000000, 0xa957e6ae00000000, 0x1cfbbc2e00000000,
+ 0x8f60755100000000, 0x37a478f500000000, 0xa43fb18a00000000,
+ 0x1193eb0a00000000, 0x8208227500000000, 0x201c819900000000,
+ 0xb38748e600000000, 0x062b126600000000, 0x95b0db1900000000,
+ 0x2d74d6bd00000000, 0xbeef1fc200000000, 0x0b43454200000000,
+ 0x98d88c3d00000000, 0x0e6c724000000000, 0x9df7bb3f00000000,
+ 0x285be1bf00000000, 0xbbc028c000000000, 0x0304256400000000,
+ 0x909fec1b00000000, 0x2533b69b00000000, 0xb6a87fe400000000,
+ 0x14bcdc0800000000, 0x8727157700000000, 0x328b4ff700000000,
+ 0xa110868800000000, 0x19d48b2c00000000, 0x8a4f425300000000,
+ 0x3fe318d300000000, 0xac78d1ac00000000, 0x2614cb5100000000,
+ 0xb58f022e00000000, 0x002358ae00000000, 0x93b891d100000000,
+ 0x2b7c9c7500000000, 0xb8e7550a00000000, 0x0d4b0f8a00000000,
+ 0x9ed0c6f500000000, 0x3cc4651900000000, 0xaf5fac6600000000,
+ 0x1af3f6e600000000, 0x89683f9900000000, 0x31ac323d00000000,
+ 0xa237fb4200000000, 0x179ba1c200000000, 0x840068bd00000000,
+ 0x12b496c000000000, 0x812f5fbf00000000, 0x3483053f00000000,
+ 0xa718cc4000000000, 0x1fdcc1e400000000, 0x8c47089b00000000,
+ 0x39eb521b00000000, 0xaa709b6400000000, 0x0864388800000000,
+ 0x9bfff1f700000000, 0x2e53ab7700000000, 0xbdc8620800000000,
+ 0x050c6fac00000000, 0x9697a6d300000000, 0x233bfc5300000000,
+ 0xb0a0352c00000000, 0x0f5201a800000000, 0x9cc9c8d700000000,
+ 0x2965925700000000, 0xbafe5b2800000000, 0x023a568c00000000,
+ 0x91a19ff300000000, 0x240dc57300000000, 0xb7960c0c00000000,
+ 0x1582afe000000000, 0x8619669f00000000, 0x33b53c1f00000000,
+ 0xa02ef56000000000, 0x18eaf8c400000000, 0x8b7131bb00000000,
+ 0x3edd6b3b00000000, 0xad46a24400000000, 0x3bf25c3900000000,
+ 0xa869954600000000, 0x1dc5cfc600000000, 0x8e5e06b900000000,
+ 0x369a0b1d00000000, 0xa501c26200000000, 0x10ad98e200000000,
+ 0x8336519d00000000, 0x2122f27100000000, 0xb2b93b0e00000000,
+ 0x0715618e00000000, 0x948ea8f100000000, 0x2c4aa55500000000,
+ 0xbfd16c2a00000000, 0x0a7d36aa00000000, 0x99e6ffd500000000,
+ 0x359e2e7900000000, 0xa605e70600000000, 0x13a9bd8600000000,
+ 0x803274f900000000, 0x38f6795d00000000, 0xab6db02200000000,
+ 0x1ec1eaa200000000, 0x8d5a23dd00000000, 0x2f4e803100000000,
+ 0xbcd5494e00000000, 0x097913ce00000000, 0x9ae2dab100000000,
+ 0x2226d71500000000, 0xb1bd1e6a00000000, 0x041144ea00000000,
+ 0x978a8d9500000000, 0x013e73e800000000, 0x92a5ba9700000000,
+ 0x2709e01700000000, 0xb492296800000000, 0x0c5624cc00000000,
+ 0x9fcdedb300000000, 0x2a61b73300000000, 0xb9fa7e4c00000000,
+ 0x1beedda000000000, 0x887514df00000000, 0x3dd94e5f00000000,
+ 0xae42872000000000, 0x16868a8400000000, 0x851d43fb00000000,
+ 0x30b1197b00000000, 0xa32ad00400000000, 0x1cd8e48000000000,
+ 0x8f432dff00000000, 0x3aef777f00000000, 0xa974be0000000000,
+ 0x11b0b3a400000000, 0x822b7adb00000000, 0x3787205b00000000,
+ 0xa41ce92400000000, 0x06084ac800000000, 0x959383b700000000,
+ 0x203fd93700000000, 0xb3a4104800000000, 0x0b601dec00000000,
+ 0x98fbd49300000000, 0x2d578e1300000000, 0xbecc476c00000000,
+ 0x2878b91100000000, 0xbbe3706e00000000, 0x0e4f2aee00000000,
+ 0x9dd4e39100000000, 0x2510ee3500000000, 0xb68b274a00000000,
+ 0x03277dca00000000, 0x90bcb4b500000000, 0x32a8175900000000,
+ 0xa133de2600000000, 0x149f84a600000000, 0x87044dd900000000,
+ 0x3fc0407d00000000, 0xac5b890200000000, 0x19f7d38200000000,
+ 0x8a6c1afd00000000},
+ {0x0000000000000000, 0x650b796900000000, 0xca16f2d200000000,
+ 0xaf1d8bbb00000000, 0xd52b957e00000000, 0xb020ec1700000000,
+ 0x1f3d67ac00000000, 0x7a361ec500000000, 0xaa572afd00000000,
+ 0xcf5c539400000000, 0x6041d82f00000000, 0x054aa14600000000,
+ 0x7f7cbf8300000000, 0x1a77c6ea00000000, 0xb56a4d5100000000,
+ 0xd061343800000000, 0x15a9252100000000, 0x70a25c4800000000,
+ 0xdfbfd7f300000000, 0xbab4ae9a00000000, 0xc082b05f00000000,
+ 0xa589c93600000000, 0x0a94428d00000000, 0x6f9f3be400000000,
+ 0xbffe0fdc00000000, 0xdaf576b500000000, 0x75e8fd0e00000000,
+ 0x10e3846700000000, 0x6ad59aa200000000, 0x0fdee3cb00000000,
+ 0xa0c3687000000000, 0xc5c8111900000000, 0x2a524b4200000000,
+ 0x4f59322b00000000, 0xe044b99000000000, 0x854fc0f900000000,
+ 0xff79de3c00000000, 0x9a72a75500000000, 0x356f2cee00000000,
+ 0x5064558700000000, 0x800561bf00000000, 0xe50e18d600000000,
+ 0x4a13936d00000000, 0x2f18ea0400000000, 0x552ef4c100000000,
+ 0x30258da800000000, 0x9f38061300000000, 0xfa337f7a00000000,
+ 0x3ffb6e6300000000, 0x5af0170a00000000, 0xf5ed9cb100000000,
+ 0x90e6e5d800000000, 0xead0fb1d00000000, 0x8fdb827400000000,
+ 0x20c609cf00000000, 0x45cd70a600000000, 0x95ac449e00000000,
+ 0xf0a73df700000000, 0x5fbab64c00000000, 0x3ab1cf2500000000,
+ 0x4087d1e000000000, 0x258ca88900000000, 0x8a91233200000000,
+ 0xef9a5a5b00000000, 0x54a4968400000000, 0x31afefed00000000,
+ 0x9eb2645600000000, 0xfbb91d3f00000000, 0x818f03fa00000000,
+ 0xe4847a9300000000, 0x4b99f12800000000, 0x2e92884100000000,
+ 0xfef3bc7900000000, 0x9bf8c51000000000, 0x34e54eab00000000,
+ 0x51ee37c200000000, 0x2bd8290700000000, 0x4ed3506e00000000,
+ 0xe1cedbd500000000, 0x84c5a2bc00000000, 0x410db3a500000000,
+ 0x2406cacc00000000, 0x8b1b417700000000, 0xee10381e00000000,
+ 0x942626db00000000, 0xf12d5fb200000000, 0x5e30d40900000000,
+ 0x3b3bad6000000000, 0xeb5a995800000000, 0x8e51e03100000000,
+ 0x214c6b8a00000000, 0x444712e300000000, 0x3e710c2600000000,
+ 0x5b7a754f00000000, 0xf467fef400000000, 0x916c879d00000000,
+ 0x7ef6ddc600000000, 0x1bfda4af00000000, 0xb4e02f1400000000,
+ 0xd1eb567d00000000, 0xabdd48b800000000, 0xced631d100000000,
+ 0x61cbba6a00000000, 0x04c0c30300000000, 0xd4a1f73b00000000,
+ 0xb1aa8e5200000000, 0x1eb705e900000000, 0x7bbc7c8000000000,
+ 0x018a624500000000, 0x64811b2c00000000, 0xcb9c909700000000,
+ 0xae97e9fe00000000, 0x6b5ff8e700000000, 0x0e54818e00000000,
+ 0xa1490a3500000000, 0xc442735c00000000, 0xbe746d9900000000,
+ 0xdb7f14f000000000, 0x74629f4b00000000, 0x1169e62200000000,
+ 0xc108d21a00000000, 0xa403ab7300000000, 0x0b1e20c800000000,
+ 0x6e1559a100000000, 0x1423476400000000, 0x71283e0d00000000,
+ 0xde35b5b600000000, 0xbb3eccdf00000000, 0xe94e5cd200000000,
+ 0x8c4525bb00000000, 0x2358ae0000000000, 0x4653d76900000000,
+ 0x3c65c9ac00000000, 0x596eb0c500000000, 0xf6733b7e00000000,
+ 0x9378421700000000, 0x4319762f00000000, 0x26120f4600000000,
+ 0x890f84fd00000000, 0xec04fd9400000000, 0x9632e35100000000,
+ 0xf3399a3800000000, 0x5c24118300000000, 0x392f68ea00000000,
+ 0xfce779f300000000, 0x99ec009a00000000, 0x36f18b2100000000,
+ 0x53faf24800000000, 0x29ccec8d00000000, 0x4cc795e400000000,
+ 0xe3da1e5f00000000, 0x86d1673600000000, 0x56b0530e00000000,
+ 0x33bb2a6700000000, 0x9ca6a1dc00000000, 0xf9add8b500000000,
+ 0x839bc67000000000, 0xe690bf1900000000, 0x498d34a200000000,
+ 0x2c864dcb00000000, 0xc31c179000000000, 0xa6176ef900000000,
+ 0x090ae54200000000, 0x6c019c2b00000000, 0x163782ee00000000,
+ 0x733cfb8700000000, 0xdc21703c00000000, 0xb92a095500000000,
+ 0x694b3d6d00000000, 0x0c40440400000000, 0xa35dcfbf00000000,
+ 0xc656b6d600000000, 0xbc60a81300000000, 0xd96bd17a00000000,
+ 0x76765ac100000000, 0x137d23a800000000, 0xd6b532b100000000,
+ 0xb3be4bd800000000, 0x1ca3c06300000000, 0x79a8b90a00000000,
+ 0x039ea7cf00000000, 0x6695dea600000000, 0xc988551d00000000,
+ 0xac832c7400000000, 0x7ce2184c00000000, 0x19e9612500000000,
+ 0xb6f4ea9e00000000, 0xd3ff93f700000000, 0xa9c98d3200000000,
+ 0xccc2f45b00000000, 0x63df7fe000000000, 0x06d4068900000000,
+ 0xbdeaca5600000000, 0xd8e1b33f00000000, 0x77fc388400000000,
+ 0x12f741ed00000000, 0x68c15f2800000000, 0x0dca264100000000,
+ 0xa2d7adfa00000000, 0xc7dcd49300000000, 0x17bde0ab00000000,
+ 0x72b699c200000000, 0xddab127900000000, 0xb8a06b1000000000,
+ 0xc29675d500000000, 0xa79d0cbc00000000, 0x0880870700000000,
+ 0x6d8bfe6e00000000, 0xa843ef7700000000, 0xcd48961e00000000,
+ 0x62551da500000000, 0x075e64cc00000000, 0x7d687a0900000000,
+ 0x1863036000000000, 0xb77e88db00000000, 0xd275f1b200000000,
+ 0x0214c58a00000000, 0x671fbce300000000, 0xc802375800000000,
+ 0xad094e3100000000, 0xd73f50f400000000, 0xb234299d00000000,
+ 0x1d29a22600000000, 0x7822db4f00000000, 0x97b8811400000000,
+ 0xf2b3f87d00000000, 0x5dae73c600000000, 0x38a50aaf00000000,
+ 0x4293146a00000000, 0x27986d0300000000, 0x8885e6b800000000,
+ 0xed8e9fd100000000, 0x3defabe900000000, 0x58e4d28000000000,
+ 0xf7f9593b00000000, 0x92f2205200000000, 0xe8c43e9700000000,
+ 0x8dcf47fe00000000, 0x22d2cc4500000000, 0x47d9b52c00000000,
+ 0x8211a43500000000, 0xe71add5c00000000, 0x480756e700000000,
+ 0x2d0c2f8e00000000, 0x573a314b00000000, 0x3231482200000000,
+ 0x9d2cc39900000000, 0xf827baf000000000, 0x28468ec800000000,
+ 0x4d4df7a100000000, 0xe2507c1a00000000, 0x875b057300000000,
+ 0xfd6d1bb600000000, 0x986662df00000000, 0x377be96400000000,
+ 0x5270900d00000000},
+ {0x0000000000000000, 0xdcecb13d00000000, 0xb8d9637b00000000,
+ 0x6435d24600000000, 0x70b3c7f600000000, 0xac5f76cb00000000,
+ 0xc86aa48d00000000, 0x148615b000000000, 0xa160fe3600000000,
+ 0x7d8c4f0b00000000, 0x19b99d4d00000000, 0xc5552c7000000000,
+ 0xd1d339c000000000, 0x0d3f88fd00000000, 0x690a5abb00000000,
+ 0xb5e6eb8600000000, 0x42c1fc6d00000000, 0x9e2d4d5000000000,
+ 0xfa189f1600000000, 0x26f42e2b00000000, 0x32723b9b00000000,
+ 0xee9e8aa600000000, 0x8aab58e000000000, 0x5647e9dd00000000,
+ 0xe3a1025b00000000, 0x3f4db36600000000, 0x5b78612000000000,
+ 0x8794d01d00000000, 0x9312c5ad00000000, 0x4ffe749000000000,
+ 0x2bcba6d600000000, 0xf72717eb00000000, 0x8482f9db00000000,
+ 0x586e48e600000000, 0x3c5b9aa000000000, 0xe0b72b9d00000000,
+ 0xf4313e2d00000000, 0x28dd8f1000000000, 0x4ce85d5600000000,
+ 0x9004ec6b00000000, 0x25e207ed00000000, 0xf90eb6d000000000,
+ 0x9d3b649600000000, 0x41d7d5ab00000000, 0x5551c01b00000000,
+ 0x89bd712600000000, 0xed88a36000000000, 0x3164125d00000000,
+ 0xc64305b600000000, 0x1aafb48b00000000, 0x7e9a66cd00000000,
+ 0xa276d7f000000000, 0xb6f0c24000000000, 0x6a1c737d00000000,
+ 0x0e29a13b00000000, 0xd2c5100600000000, 0x6723fb8000000000,
+ 0xbbcf4abd00000000, 0xdffa98fb00000000, 0x031629c600000000,
+ 0x17903c7600000000, 0xcb7c8d4b00000000, 0xaf495f0d00000000,
+ 0x73a5ee3000000000, 0x4903826c00000000, 0x95ef335100000000,
+ 0xf1dae11700000000, 0x2d36502a00000000, 0x39b0459a00000000,
+ 0xe55cf4a700000000, 0x816926e100000000, 0x5d8597dc00000000,
+ 0xe8637c5a00000000, 0x348fcd6700000000, 0x50ba1f2100000000,
+ 0x8c56ae1c00000000, 0x98d0bbac00000000, 0x443c0a9100000000,
+ 0x2009d8d700000000, 0xfce569ea00000000, 0x0bc27e0100000000,
+ 0xd72ecf3c00000000, 0xb31b1d7a00000000, 0x6ff7ac4700000000,
+ 0x7b71b9f700000000, 0xa79d08ca00000000, 0xc3a8da8c00000000,
+ 0x1f446bb100000000, 0xaaa2803700000000, 0x764e310a00000000,
+ 0x127be34c00000000, 0xce97527100000000, 0xda1147c100000000,
+ 0x06fdf6fc00000000, 0x62c824ba00000000, 0xbe24958700000000,
+ 0xcd817bb700000000, 0x116dca8a00000000, 0x755818cc00000000,
+ 0xa9b4a9f100000000, 0xbd32bc4100000000, 0x61de0d7c00000000,
+ 0x05ebdf3a00000000, 0xd9076e0700000000, 0x6ce1858100000000,
+ 0xb00d34bc00000000, 0xd438e6fa00000000, 0x08d457c700000000,
+ 0x1c52427700000000, 0xc0bef34a00000000, 0xa48b210c00000000,
+ 0x7867903100000000, 0x8f4087da00000000, 0x53ac36e700000000,
+ 0x3799e4a100000000, 0xeb75559c00000000, 0xfff3402c00000000,
+ 0x231ff11100000000, 0x472a235700000000, 0x9bc6926a00000000,
+ 0x2e2079ec00000000, 0xf2ccc8d100000000, 0x96f91a9700000000,
+ 0x4a15abaa00000000, 0x5e93be1a00000000, 0x827f0f2700000000,
+ 0xe64add6100000000, 0x3aa66c5c00000000, 0x920604d900000000,
+ 0x4eeab5e400000000, 0x2adf67a200000000, 0xf633d69f00000000,
+ 0xe2b5c32f00000000, 0x3e59721200000000, 0x5a6ca05400000000,
+ 0x8680116900000000, 0x3366faef00000000, 0xef8a4bd200000000,
+ 0x8bbf999400000000, 0x575328a900000000, 0x43d53d1900000000,
+ 0x9f398c2400000000, 0xfb0c5e6200000000, 0x27e0ef5f00000000,
+ 0xd0c7f8b400000000, 0x0c2b498900000000, 0x681e9bcf00000000,
+ 0xb4f22af200000000, 0xa0743f4200000000, 0x7c988e7f00000000,
+ 0x18ad5c3900000000, 0xc441ed0400000000, 0x71a7068200000000,
+ 0xad4bb7bf00000000, 0xc97e65f900000000, 0x1592d4c400000000,
+ 0x0114c17400000000, 0xddf8704900000000, 0xb9cda20f00000000,
+ 0x6521133200000000, 0x1684fd0200000000, 0xca684c3f00000000,
+ 0xae5d9e7900000000, 0x72b12f4400000000, 0x66373af400000000,
+ 0xbadb8bc900000000, 0xdeee598f00000000, 0x0202e8b200000000,
+ 0xb7e4033400000000, 0x6b08b20900000000, 0x0f3d604f00000000,
+ 0xd3d1d17200000000, 0xc757c4c200000000, 0x1bbb75ff00000000,
+ 0x7f8ea7b900000000, 0xa362168400000000, 0x5445016f00000000,
+ 0x88a9b05200000000, 0xec9c621400000000, 0x3070d32900000000,
+ 0x24f6c69900000000, 0xf81a77a400000000, 0x9c2fa5e200000000,
+ 0x40c314df00000000, 0xf525ff5900000000, 0x29c94e6400000000,
+ 0x4dfc9c2200000000, 0x91102d1f00000000, 0x859638af00000000,
+ 0x597a899200000000, 0x3d4f5bd400000000, 0xe1a3eae900000000,
+ 0xdb0586b500000000, 0x07e9378800000000, 0x63dce5ce00000000,
+ 0xbf3054f300000000, 0xabb6414300000000, 0x775af07e00000000,
+ 0x136f223800000000, 0xcf83930500000000, 0x7a65788300000000,
+ 0xa689c9be00000000, 0xc2bc1bf800000000, 0x1e50aac500000000,
+ 0x0ad6bf7500000000, 0xd63a0e4800000000, 0xb20fdc0e00000000,
+ 0x6ee36d3300000000, 0x99c47ad800000000, 0x4528cbe500000000,
+ 0x211d19a300000000, 0xfdf1a89e00000000, 0xe977bd2e00000000,
+ 0x359b0c1300000000, 0x51aede5500000000, 0x8d426f6800000000,
+ 0x38a484ee00000000, 0xe44835d300000000, 0x807de79500000000,
+ 0x5c9156a800000000, 0x4817431800000000, 0x94fbf22500000000,
+ 0xf0ce206300000000, 0x2c22915e00000000, 0x5f877f6e00000000,
+ 0x836bce5300000000, 0xe75e1c1500000000, 0x3bb2ad2800000000,
+ 0x2f34b89800000000, 0xf3d809a500000000, 0x97eddbe300000000,
+ 0x4b016ade00000000, 0xfee7815800000000, 0x220b306500000000,
+ 0x463ee22300000000, 0x9ad2531e00000000, 0x8e5446ae00000000,
+ 0x52b8f79300000000, 0x368d25d500000000, 0xea6194e800000000,
+ 0x1d46830300000000, 0xc1aa323e00000000, 0xa59fe07800000000,
+ 0x7973514500000000, 0x6df544f500000000, 0xb119f5c800000000,
+ 0xd52c278e00000000, 0x09c096b300000000, 0xbc267d3500000000,
+ 0x60cacc0800000000, 0x04ff1e4e00000000, 0xd813af7300000000,
+ 0xcc95bac300000000, 0x10790bfe00000000, 0x744cd9b800000000,
+ 0xa8a0688500000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f,
+ 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999,
+ 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee,
+ 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615,
+ 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383,
+ 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb,
+ 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275,
+ 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d,
+ 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b,
+ 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460,
+ 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317,
+ 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1,
+ 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5,
+ 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd,
+ 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04,
+ 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c,
+ 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7,
+ 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11,
+ 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66,
+ 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7,
+ 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871,
+ 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309,
+ 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd,
+ 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85,
+ 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913,
+ 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d,
+ 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a,
+ 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc,
+ 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57,
+ 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f,
+ 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6,
+ 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e,
+ 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f,
+ 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289,
+ 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe,
+ 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05,
+ 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893,
+ 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb,
+ 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0,
+ 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8,
+ 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e,
+ 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5,
+ 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2,
+ 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574,
+ 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5,
+ 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add,
+ 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114,
+ 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c,
+ 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7,
+ 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701,
+ 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076,
+ 0x09cd8551},
+ {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193,
+ 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2,
+ 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c,
+ 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71,
+ 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a,
+ 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d,
+ 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71,
+ 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436,
+ 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d,
+ 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000,
+ 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae,
+ 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf,
+ 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930,
+ 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277,
+ 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff,
+ 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8,
+ 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef,
+ 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e,
+ 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20,
+ 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95,
+ 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e,
+ 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9,
+ 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d,
+ 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a,
+ 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151,
+ 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4,
+ 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a,
+ 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b,
+ 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c,
+ 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b,
+ 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3,
+ 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4,
+ 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b,
+ 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a,
+ 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4,
+ 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189,
+ 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92,
+ 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5,
+ 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9,
+ 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe,
+ 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5,
+ 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8,
+ 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66,
+ 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707,
+ 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8,
+ 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f,
+ 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707,
+ 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40,
+ 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017,
+ 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876,
+ 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8,
+ 0x7bc97a0c},
+ {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300,
+ 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0,
+ 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80,
+ 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701,
+ 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41,
+ 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81,
+ 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43,
+ 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83,
+ 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3,
+ 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42,
+ 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202,
+ 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2,
+ 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7,
+ 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407,
+ 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47,
+ 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87,
+ 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86,
+ 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46,
+ 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506,
+ 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44,
+ 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704,
+ 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4,
+ 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5,
+ 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505,
+ 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45,
+ 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f,
+ 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f,
+ 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f,
+ 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e,
+ 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e,
+ 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e,
+ 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce,
+ 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c,
+ 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc,
+ 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c,
+ 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d,
+ 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d,
+ 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d,
+ 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88,
+ 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48,
+ 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708,
+ 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89,
+ 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9,
+ 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309,
+ 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb,
+ 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b,
+ 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b,
+ 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b,
+ 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a,
+ 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a,
+ 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a,
+ 0x7851a2ca},
+ {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb,
+ 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8,
+ 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0,
+ 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f,
+ 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a,
+ 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf,
+ 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5,
+ 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380,
+ 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815,
+ 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa,
+ 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2,
+ 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1,
+ 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1,
+ 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4,
+ 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa,
+ 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df,
+ 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6,
+ 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5,
+ 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad,
+ 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca,
+ 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f,
+ 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a,
+ 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8,
+ 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d,
+ 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708,
+ 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d,
+ 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865,
+ 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636,
+ 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f,
+ 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a,
+ 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744,
+ 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061,
+ 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0,
+ 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293,
+ 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb,
+ 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874,
+ 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1,
+ 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4,
+ 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f,
+ 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a,
+ 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f,
+ 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120,
+ 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778,
+ 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b,
+ 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a,
+ 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af,
+ 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81,
+ 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4,
+ 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd,
+ 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e,
+ 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6,
+ 0x566b6848}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x9e83da9f, 0x7d01c4e4, 0xe3821e7b, 0xbb04f912,
+ 0x2587238d, 0xc6053df6, 0x5886e769, 0x7609f225, 0xe88a28ba,
+ 0x0b0836c1, 0x958bec5e, 0xcd0d0b37, 0x538ed1a8, 0xb00ccfd3,
+ 0x2e8f154c, 0xec12e44b, 0x72913ed4, 0x911320af, 0x0f90fa30,
+ 0x57161d59, 0xc995c7c6, 0x2a17d9bd, 0xb4940322, 0x9a1b166e,
+ 0x0498ccf1, 0xe71ad28a, 0x79990815, 0x211fef7c, 0xbf9c35e3,
+ 0x5c1e2b98, 0xc29df107, 0xd825c897, 0x46a61208, 0xa5240c73,
+ 0x3ba7d6ec, 0x63213185, 0xfda2eb1a, 0x1e20f561, 0x80a32ffe,
+ 0xae2c3ab2, 0x30afe02d, 0xd32dfe56, 0x4dae24c9, 0x1528c3a0,
+ 0x8bab193f, 0x68290744, 0xf6aadddb, 0x34372cdc, 0xaab4f643,
+ 0x4936e838, 0xd7b532a7, 0x8f33d5ce, 0x11b00f51, 0xf232112a,
+ 0x6cb1cbb5, 0x423edef9, 0xdcbd0466, 0x3f3f1a1d, 0xa1bcc082,
+ 0xf93a27eb, 0x67b9fd74, 0x843be30f, 0x1ab83990, 0xf14de1f4,
+ 0x6fce3b6b, 0x8c4c2510, 0x12cfff8f, 0x4a4918e6, 0xd4cac279,
+ 0x3748dc02, 0xa9cb069d, 0x874413d1, 0x19c7c94e, 0xfa45d735,
+ 0x64c60daa, 0x3c40eac3, 0xa2c3305c, 0x41412e27, 0xdfc2f4b8,
+ 0x1d5f05bf, 0x83dcdf20, 0x605ec15b, 0xfedd1bc4, 0xa65bfcad,
+ 0x38d82632, 0xdb5a3849, 0x45d9e2d6, 0x6b56f79a, 0xf5d52d05,
+ 0x1657337e, 0x88d4e9e1, 0xd0520e88, 0x4ed1d417, 0xad53ca6c,
+ 0x33d010f3, 0x29682963, 0xb7ebf3fc, 0x5469ed87, 0xcaea3718,
+ 0x926cd071, 0x0cef0aee, 0xef6d1495, 0x71eece0a, 0x5f61db46,
+ 0xc1e201d9, 0x22601fa2, 0xbce3c53d, 0xe4652254, 0x7ae6f8cb,
+ 0x9964e6b0, 0x07e73c2f, 0xc57acd28, 0x5bf917b7, 0xb87b09cc,
+ 0x26f8d353, 0x7e7e343a, 0xe0fdeea5, 0x037ff0de, 0x9dfc2a41,
+ 0xb3733f0d, 0x2df0e592, 0xce72fbe9, 0x50f12176, 0x0877c61f,
+ 0x96f41c80, 0x757602fb, 0xebf5d864, 0xa39db332, 0x3d1e69ad,
+ 0xde9c77d6, 0x401fad49, 0x18994a20, 0x861a90bf, 0x65988ec4,
+ 0xfb1b545b, 0xd5944117, 0x4b179b88, 0xa89585f3, 0x36165f6c,
+ 0x6e90b805, 0xf013629a, 0x13917ce1, 0x8d12a67e, 0x4f8f5779,
+ 0xd10c8de6, 0x328e939d, 0xac0d4902, 0xf48bae6b, 0x6a0874f4,
+ 0x898a6a8f, 0x1709b010, 0x3986a55c, 0xa7057fc3, 0x448761b8,
+ 0xda04bb27, 0x82825c4e, 0x1c0186d1, 0xff8398aa, 0x61004235,
+ 0x7bb87ba5, 0xe53ba13a, 0x06b9bf41, 0x983a65de, 0xc0bc82b7,
+ 0x5e3f5828, 0xbdbd4653, 0x233e9ccc, 0x0db18980, 0x9332531f,
+ 0x70b04d64, 0xee3397fb, 0xb6b57092, 0x2836aa0d, 0xcbb4b476,
+ 0x55376ee9, 0x97aa9fee, 0x09294571, 0xeaab5b0a, 0x74288195,
+ 0x2cae66fc, 0xb22dbc63, 0x51afa218, 0xcf2c7887, 0xe1a36dcb,
+ 0x7f20b754, 0x9ca2a92f, 0x022173b0, 0x5aa794d9, 0xc4244e46,
+ 0x27a6503d, 0xb9258aa2, 0x52d052c6, 0xcc538859, 0x2fd19622,
+ 0xb1524cbd, 0xe9d4abd4, 0x7757714b, 0x94d56f30, 0x0a56b5af,
+ 0x24d9a0e3, 0xba5a7a7c, 0x59d86407, 0xc75bbe98, 0x9fdd59f1,
+ 0x015e836e, 0xe2dc9d15, 0x7c5f478a, 0xbec2b68d, 0x20416c12,
+ 0xc3c37269, 0x5d40a8f6, 0x05c64f9f, 0x9b459500, 0x78c78b7b,
+ 0xe64451e4, 0xc8cb44a8, 0x56489e37, 0xb5ca804c, 0x2b495ad3,
+ 0x73cfbdba, 0xed4c6725, 0x0ece795e, 0x904da3c1, 0x8af59a51,
+ 0x147640ce, 0xf7f45eb5, 0x6977842a, 0x31f16343, 0xaf72b9dc,
+ 0x4cf0a7a7, 0xd2737d38, 0xfcfc6874, 0x627fb2eb, 0x81fdac90,
+ 0x1f7e760f, 0x47f89166, 0xd97b4bf9, 0x3af95582, 0xa47a8f1d,
+ 0x66e77e1a, 0xf864a485, 0x1be6bafe, 0x85656061, 0xdde38708,
+ 0x43605d97, 0xa0e243ec, 0x3e619973, 0x10ee8c3f, 0x8e6d56a0,
+ 0x6def48db, 0xf36c9244, 0xabea752d, 0x3569afb2, 0xd6ebb1c9,
+ 0x48686b56},
+ {0x00000000, 0xc0642817, 0x80c9502e, 0x40ad7839, 0x0093a15c,
+ 0xc0f7894b, 0x805af172, 0x403ed965, 0x002643b9, 0xc0426bae,
+ 0x80ef1397, 0x408b3b80, 0x00b5e2e5, 0xc0d1caf2, 0x807cb2cb,
+ 0x40189adc, 0x414af7a9, 0x812edfbe, 0xc183a787, 0x01e78f90,
+ 0x41d956f5, 0x81bd7ee2, 0xc11006db, 0x01742ecc, 0x416cb410,
+ 0x81089c07, 0xc1a5e43e, 0x01c1cc29, 0x41ff154c, 0x819b3d5b,
+ 0xc1364562, 0x01526d75, 0xc3929f88, 0x03f6b79f, 0x435bcfa6,
+ 0x833fe7b1, 0xc3013ed4, 0x036516c3, 0x43c86efa, 0x83ac46ed,
+ 0xc3b4dc31, 0x03d0f426, 0x437d8c1f, 0x8319a408, 0xc3277d6d,
+ 0x0343557a, 0x43ee2d43, 0x838a0554, 0x82d86821, 0x42bc4036,
+ 0x0211380f, 0xc2751018, 0x824bc97d, 0x422fe16a, 0x02829953,
+ 0xc2e6b144, 0x82fe2b98, 0x429a038f, 0x02377bb6, 0xc25353a1,
+ 0x826d8ac4, 0x4209a2d3, 0x02a4daea, 0xc2c0f2fd, 0xc7234eca,
+ 0x074766dd, 0x47ea1ee4, 0x878e36f3, 0xc7b0ef96, 0x07d4c781,
+ 0x4779bfb8, 0x871d97af, 0xc7050d73, 0x07612564, 0x47cc5d5d,
+ 0x87a8754a, 0xc796ac2f, 0x07f28438, 0x475ffc01, 0x873bd416,
+ 0x8669b963, 0x460d9174, 0x06a0e94d, 0xc6c4c15a, 0x86fa183f,
+ 0x469e3028, 0x06334811, 0xc6576006, 0x864ffada, 0x462bd2cd,
+ 0x0686aaf4, 0xc6e282e3, 0x86dc5b86, 0x46b87391, 0x06150ba8,
+ 0xc67123bf, 0x04b1d142, 0xc4d5f955, 0x8478816c, 0x441ca97b,
+ 0x0422701e, 0xc4465809, 0x84eb2030, 0x448f0827, 0x049792fb,
+ 0xc4f3baec, 0x845ec2d5, 0x443aeac2, 0x040433a7, 0xc4601bb0,
+ 0x84cd6389, 0x44a94b9e, 0x45fb26eb, 0x859f0efc, 0xc53276c5,
+ 0x05565ed2, 0x456887b7, 0x850cafa0, 0xc5a1d799, 0x05c5ff8e,
+ 0x45dd6552, 0x85b94d45, 0xc514357c, 0x05701d6b, 0x454ec40e,
+ 0x852aec19, 0xc5879420, 0x05e3bc37, 0xcf41ed4f, 0x0f25c558,
+ 0x4f88bd61, 0x8fec9576, 0xcfd24c13, 0x0fb66404, 0x4f1b1c3d,
+ 0x8f7f342a, 0xcf67aef6, 0x0f0386e1, 0x4faefed8, 0x8fcad6cf,
+ 0xcff40faa, 0x0f9027bd, 0x4f3d5f84, 0x8f597793, 0x8e0b1ae6,
+ 0x4e6f32f1, 0x0ec24ac8, 0xcea662df, 0x8e98bbba, 0x4efc93ad,
+ 0x0e51eb94, 0xce35c383, 0x8e2d595f, 0x4e497148, 0x0ee40971,
+ 0xce802166, 0x8ebef803, 0x4edad014, 0x0e77a82d, 0xce13803a,
+ 0x0cd372c7, 0xccb75ad0, 0x8c1a22e9, 0x4c7e0afe, 0x0c40d39b,
+ 0xcc24fb8c, 0x8c8983b5, 0x4cedaba2, 0x0cf5317e, 0xcc911969,
+ 0x8c3c6150, 0x4c584947, 0x0c669022, 0xcc02b835, 0x8cafc00c,
+ 0x4ccbe81b, 0x4d99856e, 0x8dfdad79, 0xcd50d540, 0x0d34fd57,
+ 0x4d0a2432, 0x8d6e0c25, 0xcdc3741c, 0x0da75c0b, 0x4dbfc6d7,
+ 0x8ddbeec0, 0xcd7696f9, 0x0d12beee, 0x4d2c678b, 0x8d484f9c,
+ 0xcde537a5, 0x0d811fb2, 0x0862a385, 0xc8068b92, 0x88abf3ab,
+ 0x48cfdbbc, 0x08f102d9, 0xc8952ace, 0x883852f7, 0x485c7ae0,
+ 0x0844e03c, 0xc820c82b, 0x888db012, 0x48e99805, 0x08d74160,
+ 0xc8b36977, 0x881e114e, 0x487a3959, 0x4928542c, 0x894c7c3b,
+ 0xc9e10402, 0x09852c15, 0x49bbf570, 0x89dfdd67, 0xc972a55e,
+ 0x09168d49, 0x490e1795, 0x896a3f82, 0xc9c747bb, 0x09a36fac,
+ 0x499db6c9, 0x89f99ede, 0xc954e6e7, 0x0930cef0, 0xcbf03c0d,
+ 0x0b94141a, 0x4b396c23, 0x8b5d4434, 0xcb639d51, 0x0b07b546,
+ 0x4baacd7f, 0x8bcee568, 0xcbd67fb4, 0x0bb257a3, 0x4b1f2f9a,
+ 0x8b7b078d, 0xcb45dee8, 0x0b21f6ff, 0x4b8c8ec6, 0x8be8a6d1,
+ 0x8abacba4, 0x4adee3b3, 0x0a739b8a, 0xca17b39d, 0x8a296af8,
+ 0x4a4d42ef, 0x0ae03ad6, 0xca8412c1, 0x8a9c881d, 0x4af8a00a,
+ 0x0a55d833, 0xca31f024, 0x8a0f2941, 0x4a6b0156, 0x0ac6796f,
+ 0xcaa25178},
+ {0x00000000, 0xd4ea739b, 0xe9d396ed, 0x3d39e576, 0x93a15c00,
+ 0x474b2f9b, 0x7a72caed, 0xae98b976, 0x2643b900, 0xf2a9ca9b,
+ 0xcf902fed, 0x1b7a5c76, 0xb5e2e500, 0x6108969b, 0x5c3173ed,
+ 0x88db0076, 0x4c867201, 0x986c019a, 0xa555e4ec, 0x71bf9777,
+ 0xdf272e01, 0x0bcd5d9a, 0x36f4b8ec, 0xe21ecb77, 0x6ac5cb01,
+ 0xbe2fb89a, 0x83165dec, 0x57fc2e77, 0xf9649701, 0x2d8ee49a,
+ 0x10b701ec, 0xc45d7277, 0x980ce502, 0x4ce69699, 0x71df73ef,
+ 0xa5350074, 0x0badb902, 0xdf47ca99, 0xe27e2fef, 0x36945c74,
+ 0xbe4f5c02, 0x6aa52f99, 0x579ccaef, 0x8376b974, 0x2dee0002,
+ 0xf9047399, 0xc43d96ef, 0x10d7e574, 0xd48a9703, 0x0060e498,
+ 0x3d5901ee, 0xe9b37275, 0x472bcb03, 0x93c1b898, 0xaef85dee,
+ 0x7a122e75, 0xf2c92e03, 0x26235d98, 0x1b1ab8ee, 0xcff0cb75,
+ 0x61687203, 0xb5820198, 0x88bbe4ee, 0x5c519775, 0x3019ca05,
+ 0xe4f3b99e, 0xd9ca5ce8, 0x0d202f73, 0xa3b89605, 0x7752e59e,
+ 0x4a6b00e8, 0x9e817373, 0x165a7305, 0xc2b0009e, 0xff89e5e8,
+ 0x2b639673, 0x85fb2f05, 0x51115c9e, 0x6c28b9e8, 0xb8c2ca73,
+ 0x7c9fb804, 0xa875cb9f, 0x954c2ee9, 0x41a65d72, 0xef3ee404,
+ 0x3bd4979f, 0x06ed72e9, 0xd2070172, 0x5adc0104, 0x8e36729f,
+ 0xb30f97e9, 0x67e5e472, 0xc97d5d04, 0x1d972e9f, 0x20aecbe9,
+ 0xf444b872, 0xa8152f07, 0x7cff5c9c, 0x41c6b9ea, 0x952cca71,
+ 0x3bb47307, 0xef5e009c, 0xd267e5ea, 0x068d9671, 0x8e569607,
+ 0x5abce59c, 0x678500ea, 0xb36f7371, 0x1df7ca07, 0xc91db99c,
+ 0xf4245cea, 0x20ce2f71, 0xe4935d06, 0x30792e9d, 0x0d40cbeb,
+ 0xd9aab870, 0x77320106, 0xa3d8729d, 0x9ee197eb, 0x4a0be470,
+ 0xc2d0e406, 0x163a979d, 0x2b0372eb, 0xffe90170, 0x5171b806,
+ 0x859bcb9d, 0xb8a22eeb, 0x6c485d70, 0x6032940b, 0xb4d8e790,
+ 0x89e102e6, 0x5d0b717d, 0xf393c80b, 0x2779bb90, 0x1a405ee6,
+ 0xceaa2d7d, 0x46712d0b, 0x929b5e90, 0xafa2bbe6, 0x7b48c87d,
+ 0xd5d0710b, 0x013a0290, 0x3c03e7e6, 0xe8e9947d, 0x2cb4e60a,
+ 0xf85e9591, 0xc56770e7, 0x118d037c, 0xbf15ba0a, 0x6bffc991,
+ 0x56c62ce7, 0x822c5f7c, 0x0af75f0a, 0xde1d2c91, 0xe324c9e7,
+ 0x37ceba7c, 0x9956030a, 0x4dbc7091, 0x708595e7, 0xa46fe67c,
+ 0xf83e7109, 0x2cd40292, 0x11ede7e4, 0xc507947f, 0x6b9f2d09,
+ 0xbf755e92, 0x824cbbe4, 0x56a6c87f, 0xde7dc809, 0x0a97bb92,
+ 0x37ae5ee4, 0xe3442d7f, 0x4ddc9409, 0x9936e792, 0xa40f02e4,
+ 0x70e5717f, 0xb4b80308, 0x60527093, 0x5d6b95e5, 0x8981e67e,
+ 0x27195f08, 0xf3f32c93, 0xcecac9e5, 0x1a20ba7e, 0x92fbba08,
+ 0x4611c993, 0x7b282ce5, 0xafc25f7e, 0x015ae608, 0xd5b09593,
+ 0xe88970e5, 0x3c63037e, 0x502b5e0e, 0x84c12d95, 0xb9f8c8e3,
+ 0x6d12bb78, 0xc38a020e, 0x17607195, 0x2a5994e3, 0xfeb3e778,
+ 0x7668e70e, 0xa2829495, 0x9fbb71e3, 0x4b510278, 0xe5c9bb0e,
+ 0x3123c895, 0x0c1a2de3, 0xd8f05e78, 0x1cad2c0f, 0xc8475f94,
+ 0xf57ebae2, 0x2194c979, 0x8f0c700f, 0x5be60394, 0x66dfe6e2,
+ 0xb2359579, 0x3aee950f, 0xee04e694, 0xd33d03e2, 0x07d77079,
+ 0xa94fc90f, 0x7da5ba94, 0x409c5fe2, 0x94762c79, 0xc827bb0c,
+ 0x1ccdc897, 0x21f42de1, 0xf51e5e7a, 0x5b86e70c, 0x8f6c9497,
+ 0xb25571e1, 0x66bf027a, 0xee64020c, 0x3a8e7197, 0x07b794e1,
+ 0xd35de77a, 0x7dc55e0c, 0xa92f2d97, 0x9416c8e1, 0x40fcbb7a,
+ 0x84a1c90d, 0x504bba96, 0x6d725fe0, 0xb9982c7b, 0x1700950d,
+ 0xc3eae696, 0xfed303e0, 0x2a39707b, 0xa2e2700d, 0x76080396,
+ 0x4b31e6e0, 0x9fdb957b, 0x31432c0d, 0xe5a95f96, 0xd890bae0,
+ 0x0c7ac97b},
+ {0x00000000, 0x27652581, 0x0fcc3bd9, 0x28a91e58, 0x5f9e0669,
+ 0x78fb23e8, 0x50523db0, 0x77371831, 0xbe3c0dd2, 0x99592853,
+ 0xb1f0360b, 0x9695138a, 0xe1a20bbb, 0xc6c72e3a, 0xee6e3062,
+ 0xc90b15e3, 0x3d7f6b7f, 0x1a1a4efe, 0x32b350a6, 0x15d67527,
+ 0x62e16d16, 0x45844897, 0x6d2d56cf, 0x4a48734e, 0x834366ad,
+ 0xa426432c, 0x8c8f5d74, 0xabea78f5, 0xdcdd60c4, 0xfbb84545,
+ 0xd3115b1d, 0xf4747e9c, 0x7afed6fe, 0x5d9bf37f, 0x7532ed27,
+ 0x5257c8a6, 0x2560d097, 0x0205f516, 0x2aaceb4e, 0x0dc9cecf,
+ 0xc4c2db2c, 0xe3a7fead, 0xcb0ee0f5, 0xec6bc574, 0x9b5cdd45,
+ 0xbc39f8c4, 0x9490e69c, 0xb3f5c31d, 0x4781bd81, 0x60e49800,
+ 0x484d8658, 0x6f28a3d9, 0x181fbbe8, 0x3f7a9e69, 0x17d38031,
+ 0x30b6a5b0, 0xf9bdb053, 0xded895d2, 0xf6718b8a, 0xd114ae0b,
+ 0xa623b63a, 0x814693bb, 0xa9ef8de3, 0x8e8aa862, 0xb5fadc26,
+ 0x929ff9a7, 0xba36e7ff, 0x9d53c27e, 0xea64da4f, 0xcd01ffce,
+ 0xe5a8e196, 0xc2cdc417, 0x0bc6d1f4, 0x2ca3f475, 0x040aea2d,
+ 0x236fcfac, 0x5458d79d, 0x733df21c, 0x5b94ec44, 0x7cf1c9c5,
+ 0x8885b759, 0xafe092d8, 0x87498c80, 0xa02ca901, 0xd71bb130,
+ 0xf07e94b1, 0xd8d78ae9, 0xffb2af68, 0x36b9ba8b, 0x11dc9f0a,
+ 0x39758152, 0x1e10a4d3, 0x6927bce2, 0x4e429963, 0x66eb873b,
+ 0x418ea2ba, 0xcf040ad8, 0xe8612f59, 0xc0c83101, 0xe7ad1480,
+ 0x909a0cb1, 0xb7ff2930, 0x9f563768, 0xb83312e9, 0x7138070a,
+ 0x565d228b, 0x7ef43cd3, 0x59911952, 0x2ea60163, 0x09c324e2,
+ 0x216a3aba, 0x060f1f3b, 0xf27b61a7, 0xd51e4426, 0xfdb75a7e,
+ 0xdad27fff, 0xade567ce, 0x8a80424f, 0xa2295c17, 0x854c7996,
+ 0x4c476c75, 0x6b2249f4, 0x438b57ac, 0x64ee722d, 0x13d96a1c,
+ 0x34bc4f9d, 0x1c1551c5, 0x3b707444, 0x6af5b94d, 0x4d909ccc,
+ 0x65398294, 0x425ca715, 0x356bbf24, 0x120e9aa5, 0x3aa784fd,
+ 0x1dc2a17c, 0xd4c9b49f, 0xf3ac911e, 0xdb058f46, 0xfc60aac7,
+ 0x8b57b2f6, 0xac329777, 0x849b892f, 0xa3feacae, 0x578ad232,
+ 0x70eff7b3, 0x5846e9eb, 0x7f23cc6a, 0x0814d45b, 0x2f71f1da,
+ 0x07d8ef82, 0x20bdca03, 0xe9b6dfe0, 0xced3fa61, 0xe67ae439,
+ 0xc11fc1b8, 0xb628d989, 0x914dfc08, 0xb9e4e250, 0x9e81c7d1,
+ 0x100b6fb3, 0x376e4a32, 0x1fc7546a, 0x38a271eb, 0x4f9569da,
+ 0x68f04c5b, 0x40595203, 0x673c7782, 0xae376261, 0x895247e0,
+ 0xa1fb59b8, 0x869e7c39, 0xf1a96408, 0xd6cc4189, 0xfe655fd1,
+ 0xd9007a50, 0x2d7404cc, 0x0a11214d, 0x22b83f15, 0x05dd1a94,
+ 0x72ea02a5, 0x558f2724, 0x7d26397c, 0x5a431cfd, 0x9348091e,
+ 0xb42d2c9f, 0x9c8432c7, 0xbbe11746, 0xccd60f77, 0xebb32af6,
+ 0xc31a34ae, 0xe47f112f, 0xdf0f656b, 0xf86a40ea, 0xd0c35eb2,
+ 0xf7a67b33, 0x80916302, 0xa7f44683, 0x8f5d58db, 0xa8387d5a,
+ 0x613368b9, 0x46564d38, 0x6eff5360, 0x499a76e1, 0x3ead6ed0,
+ 0x19c84b51, 0x31615509, 0x16047088, 0xe2700e14, 0xc5152b95,
+ 0xedbc35cd, 0xcad9104c, 0xbdee087d, 0x9a8b2dfc, 0xb22233a4,
+ 0x95471625, 0x5c4c03c6, 0x7b292647, 0x5380381f, 0x74e51d9e,
+ 0x03d205af, 0x24b7202e, 0x0c1e3e76, 0x2b7b1bf7, 0xa5f1b395,
+ 0x82949614, 0xaa3d884c, 0x8d58adcd, 0xfa6fb5fc, 0xdd0a907d,
+ 0xf5a38e25, 0xd2c6aba4, 0x1bcdbe47, 0x3ca89bc6, 0x1401859e,
+ 0x3364a01f, 0x4453b82e, 0x63369daf, 0x4b9f83f7, 0x6cfaa676,
+ 0x988ed8ea, 0xbfebfd6b, 0x9742e333, 0xb027c6b2, 0xc710de83,
+ 0xe075fb02, 0xc8dce55a, 0xefb9c0db, 0x26b2d538, 0x01d7f0b9,
+ 0x297eeee1, 0x0e1bcb60, 0x792cd351, 0x5e49f6d0, 0x76e0e888,
+ 0x5185cd09}};
+
+#endif
+
+#endif
+
+#endif
+
+local const z_crc_t FAR x2n_table[] = {
+ 0x40000000, 0x20000000, 0x08000000, 0x00800000, 0x00008000,
+ 0xedb88320, 0xb1e6b092, 0xa06a2517, 0xed627dae, 0x88d14467,
+ 0xd7bbfe6a, 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0,
+ 0x09fe548f, 0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 0x31fec169,
+ 0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, 0xbad90e37,
+ 0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a,
+ 0xc40ba6d0, 0xc4e22c3c};
diff --git a/lib/zlib/deflate.c b/lib/zlib/deflate.c
new file mode 100644
index 0000000..2b67bc3
--- /dev/null
+++ b/lib/zlib/deflate.c
@@ -0,0 +1,2116 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process depends on being able to identify portions
+ * of the input text which are identical to earlier input (within a
+ * sliding window trailing behind the input currently being processed).
+ *
+ * The most straightforward technique turns out to be the fastest for
+ * most input files: try all possible matches and select the longest.
+ * The key feature of this algorithm is that insertions into the string
+ * dictionary are very simple and thus fast, and deletions are avoided
+ * completely. Insertions are performed at each input character, whereas
+ * string matches are performed only when the previous match ends. So it
+ * is preferable to spend more time in matches to allow very fast string
+ * insertions and avoid deletions. The matching algorithm for small
+ * strings is inspired from that of Rabin & Karp. A brute force approach
+ * is used to find longer strings when a small match has been found.
+ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ * (by Leonid Broukhis).
+ * A previous version of this file used a more sophisticated algorithm
+ * (by Fiala and Greene) which is guaranteed to run in linear amortized
+ * time, but has a larger average cost, uses more memory and is patented.
+ * However the F&G algorithm may be faster for some highly redundant
+ * files if the parameter max_chain_length (described below) is too large.
+ *
+ * ACKNOWLEDGEMENTS
+ *
+ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ * I found it in 'freeze' written by Leonid Broukhis.
+ * Thanks to many people for bug reports and testing.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ * Available in http://tools.ietf.org/html/rfc1951
+ *
+ * A description of the Rabin and Karp algorithm is given in the book
+ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ * Fiala,E.R., and Greene,D.H.
+ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id$ */
+
+#include "deflate.h"
+
+const char deflate_copyright[] =
+ " deflate 1.3 Copyright 1995-2023 Jean-loup Gailly and Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+typedef enum {
+ need_more, /* block not completed, need more input or more output */
+ block_done, /* block flush performed */
+ finish_started, /* finish started, need only more output at next deflate */
+ finish_done /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func)(deflate_state *s, int flush);
+/* Compression function. Returns the block state after the call. */
+
+local block_state deflate_stored(deflate_state *s, int flush);
+local block_state deflate_fast(deflate_state *s, int flush);
+#ifndef FASTEST
+local block_state deflate_slow(deflate_state *s, int flush);
+#endif
+local block_state deflate_rle(deflate_state *s, int flush);
+local block_state deflate_huff(deflate_state *s, int flush);
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+# define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+ ush good_length; /* reduce lazy search above this match length */
+ ush max_lazy; /* do not perform lazy search above this match length */
+ ush nice_length; /* quit search above this match length */
+ ush max_chain;
+ compress_func func;
+} config;
+
+#ifdef FASTEST
+local const config configuration_table[2] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */
+#else
+local const config configuration_table[10] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */
+/* 2 */ {4, 5, 16, 8, deflate_fast},
+/* 3 */ {4, 6, 32, 32, deflate_fast},
+
+/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */
+/* 5 */ {8, 16, 32, 32, deflate_slow},
+/* 6 */ {8, 16, 128, 128, deflate_slow},
+/* 7 */ {8, 32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
+#endif
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */
+#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0))
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN assertion: all calls to UPDATE_HASH are made with consecutive input
+ * characters, so that a running hash key can be computed from the previous
+ * key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h) << s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN assertion: all calls to INSERT_STRING are made with consecutive input
+ * characters and the first MIN_MATCH bytes of str are valid (except for
+ * the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+ do { \
+ s->head[s->hash_size - 1] = NIL; \
+ zmemzero((Bytef *)s->head, \
+ (unsigned)(s->hash_size - 1)*sizeof(*s->head)); \
+ } while (0)
+
+/* ===========================================================================
+ * Slide the hash table when sliding the window down (could be avoided with 32
+ * bit values at the expense of memory usage). We slide even when level == 0 to
+ * keep the hash table consistent if we switch back to level > 0 later.
+ */
+#if defined(__has_feature)
+# if __has_feature(memory_sanitizer)
+ __attribute__((no_sanitize("memory")))
+# endif
+#endif
+local void slide_hash(deflate_state *s) {
+ unsigned n, m;
+ Posf *p;
+ uInt wsize = s->w_size;
+
+ n = s->hash_size;
+ p = &s->head[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m - wsize : NIL);
+ } while (--n);
+ n = wsize;
+#ifndef FASTEST
+ p = &s->prev[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m - wsize : NIL);
+ /* If n is not on any hash chain, prev[n] is garbage but
+ * its value will never be used.
+ */
+ } while (--n);
+#endif
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read. All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local unsigned read_buf(z_streamp strm, Bytef *buf, unsigned size) {
+ unsigned len = strm->avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ strm->avail_in -= len;
+
+ zmemcpy(buf, strm->next_in, len);
+ if (strm->state->wrap == 1) {
+ strm->adler = adler32(strm->adler, buf, len);
+ }
+#ifdef GZIP
+ else if (strm->state->wrap == 2) {
+ strm->adler = crc32(strm->adler, buf, len);
+ }
+#endif
+ strm->next_in += len;
+ strm->total_in += len;
+
+ return len;
+}
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ * At least one byte has been read, or avail_in == 0; reads are
+ * performed for at least two bytes (required for the zip translate_eol
+ * option -- not supported here).
+ */
+local void fill_window(deflate_state *s) {
+ unsigned n;
+ unsigned more; /* Amount of free space at the end of the window. */
+ uInt wsize = s->w_size;
+
+ Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
+
+ do {
+ more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+ /* Deal with !@#$% 64K limit: */
+ if (sizeof(int) <= 2) {
+ if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+ more = wsize;
+
+ } else if (more == (unsigned)(-1)) {
+ /* Very unlikely, but possible on 16 bit machine if
+ * strstart == 0 && lookahead == 1 (input done a byte at time)
+ */
+ more--;
+ }
+ }
+
+ /* If the window is almost full and there is insufficient lookahead,
+ * move the upper half to the lower one to make room in the upper half.
+ */
+ if (s->strstart >= wsize + MAX_DIST(s)) {
+
+ zmemcpy(s->window, s->window + wsize, (unsigned)wsize - more);
+ s->match_start -= wsize;
+ s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
+ s->block_start -= (long) wsize;
+ if (s->insert > s->strstart)
+ s->insert = s->strstart;
+ slide_hash(s);
+ more += wsize;
+ }
+ if (s->strm->avail_in == 0) break;
+
+ /* If there was no sliding:
+ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ * more == window_size - lookahead - strstart
+ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ * => more >= window_size - 2*WSIZE + 2
+ * In the BIG_MEM or MMAP case (not yet supported),
+ * window_size == input_size + MIN_LOOKAHEAD &&
+ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ * Otherwise, window_size == 2*WSIZE so more >= 2.
+ * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+ */
+ Assert(more >= 2, "more < 2");
+
+ n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+ s->lookahead += n;
+
+ /* Initialize the hash value now that we have some input: */
+ if (s->lookahead + s->insert >= MIN_MATCH) {
+ uInt str = s->strstart - s->insert;
+ s->ins_h = s->window[str];
+ UPDATE_HASH(s, s->ins_h, s->window[str + 1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ while (s->insert) {
+ UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
+#ifndef FASTEST
+ s->prev[str & s->w_mask] = s->head[s->ins_h];
+#endif
+ s->head[s->ins_h] = (Pos)str;
+ str++;
+ s->insert--;
+ if (s->lookahead + s->insert < MIN_MATCH)
+ break;
+ }
+ }
+ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ * but this is not important since only literal bytes will be emitted.
+ */
+
+ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+
+ /* If the WIN_INIT bytes after the end of the current data have never been
+ * written, then zero those bytes in order to avoid memory check reports of
+ * the use of uninitialized (or uninitialised as Julian writes) bytes by
+ * the longest match routines. Update the high water mark for the next
+ * time through here. WIN_INIT is set to MAX_MATCH since the longest match
+ * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
+ */
+ if (s->high_water < s->window_size) {
+ ulg curr = s->strstart + (ulg)(s->lookahead);
+ ulg init;
+
+ if (s->high_water < curr) {
+ /* Previous high water mark below current data -- zero WIN_INIT
+ * bytes or up to end of window, whichever is less.
+ */
+ init = s->window_size - curr;
+ if (init > WIN_INIT)
+ init = WIN_INIT;
+ zmemzero(s->window + curr, (unsigned)init);
+ s->high_water = curr + init;
+ }
+ else if (s->high_water < (ulg)curr + WIN_INIT) {
+ /* High water mark at or above current data, but below current data
+ * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
+ * to end of window, whichever is less.
+ */
+ init = (ulg)curr + WIN_INIT - s->high_water;
+ if (init > s->window_size - s->high_water)
+ init = s->window_size - s->high_water;
+ zmemzero(s->window + s->high_water, (unsigned)init);
+ s->high_water += init;
+ }
+ }
+
+ Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
+ "not enough room for search");
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version,
+ int stream_size) {
+ return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY, version, stream_size);
+ /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(z_streamp strm, int level, int method,
+ int windowBits, int memLevel, int strategy,
+ const char *version, int stream_size) {
+ deflate_state *s;
+ int wrap = 1;
+ static const char my_version[] = ZLIB_VERSION;
+
+ if (version == Z_NULL || version[0] != my_version[0] ||
+ stream_size != sizeof(z_stream)) {
+ return Z_VERSION_ERROR;
+ }
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+ strm->msg = Z_NULL;
+ if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+#endif
+ }
+ if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zfree = zcfree;
+#endif
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+
+ if (windowBits < 0) { /* suppress zlib wrapper */
+ wrap = 0;
+ if (windowBits < -15)
+ return Z_STREAM_ERROR;
+ windowBits = -windowBits;
+ }
+#ifdef GZIP
+ else if (windowBits > 15) {
+ wrap = 2; /* write gzip wrapper instead */
+ windowBits -= 16;
+ }
+#endif
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+ windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+ strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) {
+ return Z_STREAM_ERROR;
+ }
+ if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */
+ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+ if (s == Z_NULL) return Z_MEM_ERROR;
+ strm->state = (struct internal_state FAR *)s;
+ s->strm = strm;
+ s->status = INIT_STATE; /* to pass state test in deflateReset() */
+
+ s->wrap = wrap;
+ s->gzhead = Z_NULL;
+ s->w_bits = (uInt)windowBits;
+ s->w_size = 1 << s->w_bits;
+ s->w_mask = s->w_size - 1;
+
+ s->hash_bits = (uInt)memLevel + 7;
+ s->hash_size = 1 << s->hash_bits;
+ s->hash_mask = s->hash_size - 1;
+ s->hash_shift = ((s->hash_bits + MIN_MATCH-1) / MIN_MATCH);
+
+ s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+ s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
+ s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+ s->high_water = 0; /* nothing written to s->window yet */
+
+ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+ /* We overlay pending_buf and sym_buf. This works since the average size
+ * for length/distance pairs over any compressed block is assured to be 31
+ * bits or less.
+ *
+ * Analysis: The longest fixed codes are a length code of 8 bits plus 5
+ * extra bits, for lengths 131 to 257. The longest fixed distance codes are
+ * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest
+ * possible fixed-codes length/distance pair is then 31 bits total.
+ *
+ * sym_buf starts one-fourth of the way into pending_buf. So there are
+ * three bytes in sym_buf for every four bytes in pending_buf. Each symbol
+ * in sym_buf is three bytes -- two for the distance and one for the
+ * literal/length. As each symbol is consumed, the pointer to the next
+ * sym_buf value to read moves forward three bytes. From that symbol, up to
+ * 31 bits are written to pending_buf. The closest the written pending_buf
+ * bits gets to the next sym_buf symbol to read is just before the last
+ * code is written. At that time, 31*(n - 2) bits have been written, just
+ * after 24*(n - 2) bits have been consumed from sym_buf. sym_buf starts at
+ * 8*n bits into pending_buf. (Note that the symbol buffer fills when n - 1
+ * symbols are written.) The closest the writing gets to what is unread is
+ * then n + 14 bits. Here n is lit_bufsize, which is 16384 by default, and
+ * can range from 128 to 32768.
+ *
+ * Therefore, at a minimum, there are 142 bits of space between what is
+ * written and what is read in the overlain buffers, so the symbols cannot
+ * be overwritten by the compressed data. That space is actually 139 bits,
+ * due to the three-bit fixed-code block header.
+ *
+ * That covers the case where either Z_FIXED is specified, forcing fixed
+ * codes, or when the use of fixed codes is chosen, because that choice
+ * results in a smaller compressed block than dynamic codes. That latter
+ * condition then assures that the above analysis also covers all dynamic
+ * blocks. A dynamic-code block will only be chosen to be emitted if it has
+ * fewer bits than a fixed-code block would for the same set of symbols.
+ * Therefore its average symbol length is assured to be less than 31. So
+ * the compressed data for a dynamic block also cannot overwrite the
+ * symbols from which it is being constructed.
+ */
+
+ s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4);
+ s->pending_buf_size = (ulg)s->lit_bufsize * 4;
+
+ if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+ s->pending_buf == Z_NULL) {
+ s->status = FINISH_STATE;
+ strm->msg = ERR_MSG(Z_MEM_ERROR);
+ deflateEnd (strm);
+ return Z_MEM_ERROR;
+ }
+ s->sym_buf = s->pending_buf + s->lit_bufsize;
+ s->sym_end = (s->lit_bufsize - 1) * 3;
+ /* We avoid equality with lit_bufsize*3 because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
+
+ s->level = level;
+ s->strategy = strategy;
+ s->method = (Byte)method;
+
+ return deflateReset(strm);
+}
+
+/* =========================================================================
+ * Check for a valid deflate stream state. Return 0 if ok, 1 if not.
+ */
+local int deflateStateCheck(z_streamp strm) {
+ deflate_state *s;
+ if (strm == Z_NULL ||
+ strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
+ return 1;
+ s = strm->state;
+ if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE &&
+#ifdef GZIP
+ s->status != GZIP_STATE &&
+#endif
+ s->status != EXTRA_STATE &&
+ s->status != NAME_STATE &&
+ s->status != COMMENT_STATE &&
+ s->status != HCRC_STATE &&
+ s->status != BUSY_STATE &&
+ s->status != FINISH_STATE))
+ return 1;
+ return 0;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary(z_streamp strm, const Bytef *dictionary,
+ uInt dictLength) {
+ deflate_state *s;
+ uInt str, n;
+ int wrap;
+ unsigned avail;
+ z_const unsigned char *next;
+
+ if (deflateStateCheck(strm) || dictionary == Z_NULL)
+ return Z_STREAM_ERROR;
+ s = strm->state;
+ wrap = s->wrap;
+ if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead)
+ return Z_STREAM_ERROR;
+
+ /* when using zlib wrappers, compute Adler-32 for provided dictionary */
+ if (wrap == 1)
+ strm->adler = adler32(strm->adler, dictionary, dictLength);
+ s->wrap = 0; /* avoid computing Adler-32 in read_buf */
+
+ /* if dictionary would fill window, just replace the history */
+ if (dictLength >= s->w_size) {
+ if (wrap == 0) { /* already empty otherwise */
+ CLEAR_HASH(s);
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->insert = 0;
+ }
+ dictionary += dictLength - s->w_size; /* use the tail */
+ dictLength = s->w_size;
+ }
+
+ /* insert dictionary into window and hash */
+ avail = strm->avail_in;
+ next = strm->next_in;
+ strm->avail_in = dictLength;
+ strm->next_in = (z_const Bytef *)dictionary;
+ fill_window(s);
+ while (s->lookahead >= MIN_MATCH) {
+ str = s->strstart;
+ n = s->lookahead - (MIN_MATCH-1);
+ do {
+ UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
+#ifndef FASTEST
+ s->prev[str & s->w_mask] = s->head[s->ins_h];
+#endif
+ s->head[s->ins_h] = (Pos)str;
+ str++;
+ } while (--n);
+ s->strstart = str;
+ s->lookahead = MIN_MATCH-1;
+ fill_window(s);
+ }
+ s->strstart += s->lookahead;
+ s->block_start = (long)s->strstart;
+ s->insert = s->lookahead;
+ s->lookahead = 0;
+ s->match_length = s->prev_length = MIN_MATCH-1;
+ s->match_available = 0;
+ strm->next_in = next;
+ strm->avail_in = avail;
+ s->wrap = wrap;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateGetDictionary(z_streamp strm, Bytef *dictionary,
+ uInt *dictLength) {
+ deflate_state *s;
+ uInt len;
+
+ if (deflateStateCheck(strm))
+ return Z_STREAM_ERROR;
+ s = strm->state;
+ len = s->strstart + s->lookahead;
+ if (len > s->w_size)
+ len = s->w_size;
+ if (dictionary != Z_NULL && len)
+ zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len);
+ if (dictLength != Z_NULL)
+ *dictLength = len;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateResetKeep(z_streamp strm) {
+ deflate_state *s;
+
+ if (deflateStateCheck(strm)) {
+ return Z_STREAM_ERROR;
+ }
+
+ strm->total_in = strm->total_out = 0;
+ strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+ strm->data_type = Z_UNKNOWN;
+
+ s = (deflate_state *)strm->state;
+ s->pending = 0;
+ s->pending_out = s->pending_buf;
+
+ if (s->wrap < 0) {
+ s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
+ }
+ s->status =
+#ifdef GZIP
+ s->wrap == 2 ? GZIP_STATE :
+#endif
+ INIT_STATE;
+ strm->adler =
+#ifdef GZIP
+ s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
+#endif
+ adler32(0L, Z_NULL, 0);
+ s->last_flush = -2;
+
+ _tr_init(s);
+
+ return Z_OK;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init(deflate_state *s) {
+ s->window_size = (ulg)2L*s->w_size;
+
+ CLEAR_HASH(s);
+
+ /* Set the default configuration parameters:
+ */
+ s->max_lazy_match = configuration_table[s->level].max_lazy;
+ s->good_match = configuration_table[s->level].good_length;
+ s->nice_match = configuration_table[s->level].nice_length;
+ s->max_chain_length = configuration_table[s->level].max_chain;
+
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->lookahead = 0;
+ s->insert = 0;
+ s->match_length = s->prev_length = MIN_MATCH-1;
+ s->match_available = 0;
+ s->ins_h = 0;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset(z_streamp strm) {
+ int ret;
+
+ ret = deflateResetKeep(strm);
+ if (ret == Z_OK)
+ lm_init(strm->state);
+ return ret;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetHeader(z_streamp strm, gz_headerp head) {
+ if (deflateStateCheck(strm) || strm->state->wrap != 2)
+ return Z_STREAM_ERROR;
+ strm->state->gzhead = head;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePending(z_streamp strm, unsigned *pending, int *bits) {
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+ if (pending != Z_NULL)
+ *pending = strm->state->pending;
+ if (bits != Z_NULL)
+ *bits = strm->state->bi_valid;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePrime(z_streamp strm, int bits, int value) {
+ deflate_state *s;
+ int put;
+
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+ s = strm->state;
+ if (bits < 0 || bits > 16 ||
+ s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
+ return Z_BUF_ERROR;
+ do {
+ put = Buf_size - s->bi_valid;
+ if (put > bits)
+ put = bits;
+ s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);
+ s->bi_valid += put;
+ _tr_flush_bits(s);
+ value >>= put;
+ bits -= put;
+ } while (bits);
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(z_streamp strm, int level, int strategy) {
+ deflate_state *s;
+ compress_func func;
+
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+ s = strm->state;
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+ if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
+ return Z_STREAM_ERROR;
+ }
+ func = configuration_table[s->level].func;
+
+ if ((strategy != s->strategy || func != configuration_table[level].func) &&
+ s->last_flush != -2) {
+ /* Flush the last buffer: */
+ int err = deflate(strm, Z_BLOCK);
+ if (err == Z_STREAM_ERROR)
+ return err;
+ if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead)
+ return Z_BUF_ERROR;
+ }
+ if (s->level != level) {
+ if (s->level == 0 && s->matches != 0) {
+ if (s->matches == 1)
+ slide_hash(s);
+ else
+ CLEAR_HASH(s);
+ s->matches = 0;
+ }
+ s->level = level;
+ s->max_lazy_match = configuration_table[level].max_lazy;
+ s->good_match = configuration_table[level].good_length;
+ s->nice_match = configuration_table[level].nice_length;
+ s->max_chain_length = configuration_table[level].max_chain;
+ }
+ s->strategy = strategy;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy,
+ int nice_length, int max_chain) {
+ deflate_state *s;
+
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+ s = strm->state;
+ s->good_match = (uInt)good_length;
+ s->max_lazy_match = (uInt)max_lazy;
+ s->nice_match = nice_length;
+ s->max_chain_length = (uInt)max_chain;
+ return Z_OK;
+}
+
+/* =========================================================================
+ * For the default windowBits of 15 and memLevel of 8, this function returns a
+ * close to exact, as well as small, upper bound on the compressed size. This
+ * is an expansion of ~0.03%, plus a small constant.
+ *
+ * For any setting other than those defaults for windowBits and memLevel, one
+ * of two worst case bounds is returned. This is at most an expansion of ~4% or
+ * ~13%, plus a small constant.
+ *
+ * Both the 0.03% and 4% derive from the overhead of stored blocks. The first
+ * one is for stored blocks of 16383 bytes (memLevel == 8), whereas the second
+ * is for stored blocks of 127 bytes (the worst case memLevel == 1). The
+ * expansion results from five bytes of header for each stored block.
+ *
+ * The larger expansion of 13% results from a window size less than or equal to
+ * the symbols buffer size (windowBits <= memLevel + 7). In that case some of
+ * the data being compressed may have slid out of the sliding window, impeding
+ * a stored block from being emitted. Then the only choice is a fixed or
+ * dynamic block, where a fixed block limits the maximum expansion to 9 bits
+ * per 8-bit byte, plus 10 bits for every block. The smallest block size for
+ * which this can occur is 255 (memLevel == 2).
+ *
+ * Shifts are used to approximate divisions, for speed.
+ */
+uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) {
+ deflate_state *s;
+ uLong fixedlen, storelen, wraplen;
+
+ /* upper bound for fixed blocks with 9-bit literals and length 255
+ (memLevel == 2, which is the lowest that may not use stored blocks) --
+ ~13% overhead plus a small constant */
+ fixedlen = sourceLen + (sourceLen >> 3) + (sourceLen >> 8) +
+ (sourceLen >> 9) + 4;
+
+ /* upper bound for stored blocks with length 127 (memLevel == 1) --
+ ~4% overhead plus a small constant */
+ storelen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) +
+ (sourceLen >> 11) + 7;
+
+ /* if can't get parameters, return larger bound plus a zlib wrapper */
+ if (deflateStateCheck(strm))
+ return (fixedlen > storelen ? fixedlen : storelen) + 6;
+
+ /* compute wrapper length */
+ s = strm->state;
+ switch (s->wrap) {
+ case 0: /* raw deflate */
+ wraplen = 0;
+ break;
+ case 1: /* zlib wrapper */
+ wraplen = 6 + (s->strstart ? 4 : 0);
+ break;
+#ifdef GZIP
+ case 2: /* gzip wrapper */
+ wraplen = 18;
+ if (s->gzhead != Z_NULL) { /* user-supplied gzip header */
+ Bytef *str;
+ if (s->gzhead->extra != Z_NULL)
+ wraplen += 2 + s->gzhead->extra_len;
+ str = s->gzhead->name;
+ if (str != Z_NULL)
+ do {
+ wraplen++;
+ } while (*str++);
+ str = s->gzhead->comment;
+ if (str != Z_NULL)
+ do {
+ wraplen++;
+ } while (*str++);
+ if (s->gzhead->hcrc)
+ wraplen += 2;
+ }
+ break;
+#endif
+ default: /* for compiler happiness */
+ wraplen = 6;
+ }
+
+ /* if not default parameters, return one of the conservative bounds */
+ if (s->w_bits != 15 || s->hash_bits != 8 + 7)
+ return (s->w_bits <= s->hash_bits && s->level ? fixedlen : storelen) +
+ wraplen;
+
+ /* default settings: return tight bound for that case -- ~0.03% overhead
+ plus a small constant */
+ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
+ (sourceLen >> 25) + 13 - 6 + wraplen;
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB(deflate_state *s, uInt b) {
+ put_byte(s, (Byte)(b >> 8));
+ put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output, except for
+ * some deflate_stored() output, goes through this function so some
+ * applications may wish to modify it to avoid allocating a large
+ * strm->next_out buffer and copying into it. (See also read_buf()).
+ */
+local void flush_pending(z_streamp strm) {
+ unsigned len;
+ deflate_state *s = strm->state;
+
+ _tr_flush_bits(s);
+ len = s->pending;
+ if (len > strm->avail_out) len = strm->avail_out;
+ if (len == 0) return;
+
+ zmemcpy(strm->next_out, s->pending_out, len);
+ strm->next_out += len;
+ s->pending_out += len;
+ strm->total_out += len;
+ strm->avail_out -= len;
+ s->pending -= len;
+ if (s->pending == 0) {
+ s->pending_out = s->pending_buf;
+ }
+}
+
+/* ===========================================================================
+ * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1].
+ */
+#define HCRC_UPDATE(beg) \
+ do { \
+ if (s->gzhead->hcrc && s->pending > (beg)) \
+ strm->adler = crc32(strm->adler, s->pending_buf + (beg), \
+ s->pending - (beg)); \
+ } while (0)
+
+/* ========================================================================= */
+int ZEXPORT deflate(z_streamp strm, int flush) {
+ int old_flush; /* value of flush param for previous deflate call */
+ deflate_state *s;
+
+ if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) {
+ return Z_STREAM_ERROR;
+ }
+ s = strm->state;
+
+ if (strm->next_out == Z_NULL ||
+ (strm->avail_in != 0 && strm->next_in == Z_NULL) ||
+ (s->status == FINISH_STATE && flush != Z_FINISH)) {
+ ERR_RETURN(strm, Z_STREAM_ERROR);
+ }
+ if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+ old_flush = s->last_flush;
+ s->last_flush = flush;
+
+ /* Flush as much pending output as possible */
+ if (s->pending != 0) {
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ /* Since avail_out is 0, deflate will be called again with
+ * more output space, but possibly with both pending and
+ * avail_in equal to zero. There won't be anything to do,
+ * but this is not an error situation so make sure we
+ * return OK instead of BUF_ERROR at next call of deflate:
+ */
+ s->last_flush = -1;
+ return Z_OK;
+ }
+
+ /* Make sure there is something to do and avoid duplicate consecutive
+ * flushes. For repeated and useless calls with Z_FINISH, we keep
+ * returning Z_STREAM_END instead of Z_BUF_ERROR.
+ */
+ } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) &&
+ flush != Z_FINISH) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* User must not provide more input after the first FINISH: */
+ if (s->status == FINISH_STATE && strm->avail_in != 0) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* Write the header */
+ if (s->status == INIT_STATE && s->wrap == 0)
+ s->status = BUSY_STATE;
+ if (s->status == INIT_STATE) {
+ /* zlib header */
+ uInt header = (Z_DEFLATED + ((s->w_bits - 8) << 4)) << 8;
+ uInt level_flags;
+
+ if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
+ level_flags = 0;
+ else if (s->level < 6)
+ level_flags = 1;
+ else if (s->level == 6)
+ level_flags = 2;
+ else
+ level_flags = 3;
+ header |= (level_flags << 6);
+ if (s->strstart != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ putShortMSB(s, header);
+
+ /* Save the adler32 of the preset dictionary: */
+ if (s->strstart != 0) {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ strm->adler = adler32(0L, Z_NULL, 0);
+ s->status = BUSY_STATE;
+
+ /* Compression must start with an empty pending buffer */
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ }
+#ifdef GZIP
+ if (s->status == GZIP_STATE) {
+ /* gzip header */
+ strm->adler = crc32(0L, Z_NULL, 0);
+ put_byte(s, 31);
+ put_byte(s, 139);
+ put_byte(s, 8);
+ if (s->gzhead == Z_NULL) {
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, OS_CODE);
+ s->status = BUSY_STATE;
+
+ /* Compression must start with an empty pending buffer */
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ }
+ else {
+ put_byte(s, (s->gzhead->text ? 1 : 0) +
+ (s->gzhead->hcrc ? 2 : 0) +
+ (s->gzhead->extra == Z_NULL ? 0 : 4) +
+ (s->gzhead->name == Z_NULL ? 0 : 8) +
+ (s->gzhead->comment == Z_NULL ? 0 : 16)
+ );
+ put_byte(s, (Byte)(s->gzhead->time & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, s->gzhead->os & 0xff);
+ if (s->gzhead->extra != Z_NULL) {
+ put_byte(s, s->gzhead->extra_len & 0xff);
+ put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
+ }
+ if (s->gzhead->hcrc)
+ strm->adler = crc32(strm->adler, s->pending_buf,
+ s->pending);
+ s->gzindex = 0;
+ s->status = EXTRA_STATE;
+ }
+ }
+ if (s->status == EXTRA_STATE) {
+ if (s->gzhead->extra != Z_NULL) {
+ ulg beg = s->pending; /* start of bytes to update crc */
+ uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex;
+ while (s->pending + left > s->pending_buf_size) {
+ uInt copy = s->pending_buf_size - s->pending;
+ zmemcpy(s->pending_buf + s->pending,
+ s->gzhead->extra + s->gzindex, copy);
+ s->pending = s->pending_buf_size;
+ HCRC_UPDATE(beg);
+ s->gzindex += copy;
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ beg = 0;
+ left -= copy;
+ }
+ zmemcpy(s->pending_buf + s->pending,
+ s->gzhead->extra + s->gzindex, left);
+ s->pending += left;
+ HCRC_UPDATE(beg);
+ s->gzindex = 0;
+ }
+ s->status = NAME_STATE;
+ }
+ if (s->status == NAME_STATE) {
+ if (s->gzhead->name != Z_NULL) {
+ ulg beg = s->pending; /* start of bytes to update crc */
+ int val;
+ do {
+ if (s->pending == s->pending_buf_size) {
+ HCRC_UPDATE(beg);
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ beg = 0;
+ }
+ val = s->gzhead->name[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ HCRC_UPDATE(beg);
+ s->gzindex = 0;
+ }
+ s->status = COMMENT_STATE;
+ }
+ if (s->status == COMMENT_STATE) {
+ if (s->gzhead->comment != Z_NULL) {
+ ulg beg = s->pending; /* start of bytes to update crc */
+ int val;
+ do {
+ if (s->pending == s->pending_buf_size) {
+ HCRC_UPDATE(beg);
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ beg = 0;
+ }
+ val = s->gzhead->comment[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ HCRC_UPDATE(beg);
+ }
+ s->status = HCRC_STATE;
+ }
+ if (s->status == HCRC_STATE) {
+ if (s->gzhead->hcrc) {
+ if (s->pending + 2 > s->pending_buf_size) {
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ }
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ strm->adler = crc32(0L, Z_NULL, 0);
+ }
+ s->status = BUSY_STATE;
+
+ /* Compression must start with an empty pending buffer */
+ flush_pending(strm);
+ if (s->pending != 0) {
+ s->last_flush = -1;
+ return Z_OK;
+ }
+ }
+#endif
+
+ /* Start a new block or continue the current one.
+ */
+ if (strm->avail_in != 0 || s->lookahead != 0 ||
+ (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+ block_state bstate;
+
+ bstate = s->level == 0 ? deflate_stored(s, flush) :
+ s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
+ s->strategy == Z_RLE ? deflate_rle(s, flush) :
+ (*(configuration_table[s->level].func))(s, flush);
+
+ if (bstate == finish_started || bstate == finish_done) {
+ s->status = FINISH_STATE;
+ }
+ if (bstate == need_more || bstate == finish_started) {
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+ }
+ return Z_OK;
+ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ * of deflate should use the same flush parameter to make sure
+ * that the flush is complete. So we don't have to output an
+ * empty block here, this will be done at next call. This also
+ * ensures that for a very small output buffer, we emit at most
+ * one empty block.
+ */
+ }
+ if (bstate == block_done) {
+ if (flush == Z_PARTIAL_FLUSH) {
+ _tr_align(s);
+ } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
+ _tr_stored_block(s, (char*)0, 0L, 0);
+ /* For a full flush, this empty block will be recognized
+ * as a special marker by inflate_sync().
+ */
+ if (flush == Z_FULL_FLUSH) {
+ CLEAR_HASH(s); /* forget history */
+ if (s->lookahead == 0) {
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->insert = 0;
+ }
+ }
+ }
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+ return Z_OK;
+ }
+ }
+ }
+
+ if (flush != Z_FINISH) return Z_OK;
+ if (s->wrap <= 0) return Z_STREAM_END;
+
+ /* Write the trailer */
+#ifdef GZIP
+ if (s->wrap == 2) {
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
+ put_byte(s, (Byte)(strm->total_in & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
+ }
+ else
+#endif
+ {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ flush_pending(strm);
+ /* If avail_out is zero, the application will call deflate again
+ * to flush the rest.
+ */
+ if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
+ return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd(z_streamp strm) {
+ int status;
+
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
+
+ status = strm->state->status;
+
+ /* Deallocate in reverse order of allocations: */
+ TRY_FREE(strm, strm->state->pending_buf);
+ TRY_FREE(strm, strm->state->head);
+ TRY_FREE(strm, strm->state->prev);
+ TRY_FREE(strm, strm->state->window);
+
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+
+ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy(z_streamp dest, z_streamp source) {
+#ifdef MAXSEG_64K
+ (void)dest;
+ (void)source;
+ return Z_STREAM_ERROR;
+#else
+ deflate_state *ds;
+ deflate_state *ss;
+
+
+ if (deflateStateCheck(source) || dest == Z_NULL) {
+ return Z_STREAM_ERROR;
+ }
+
+ ss = source->state;
+
+ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
+
+ ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+ if (ds == Z_NULL) return Z_MEM_ERROR;
+ dest->state = (struct internal_state FAR *) ds;
+ zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state));
+ ds->strm = dest;
+
+ ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+ ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
+ ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
+ ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);
+
+ if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+ ds->pending_buf == Z_NULL) {
+ deflateEnd (dest);
+ return Z_MEM_ERROR;
+ }
+ /* following zmemcpy do not work for 16-bit MSDOS */
+ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+ zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
+ zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
+ zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+ ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+ ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
+
+ ds->l_desc.dyn_tree = ds->dyn_ltree;
+ ds->d_desc.dyn_tree = ds->dyn_dtree;
+ ds->bl_desc.dyn_tree = ds->bl_tree;
+
+ return Z_OK;
+#endif /* MAXSEG_64K */
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+local uInt longest_match(deflate_state *s, IPos cur_match) {
+ unsigned chain_length = s->max_chain_length;/* max hash chain length */
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ int best_len = (int)s->prev_length; /* best match length so far */
+ int nice_match = s->nice_match; /* stop if match long enough */
+ IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+ s->strstart - (IPos)MAX_DIST(s) : NIL;
+ /* Stop when cur_match becomes <= limit. To simplify the code,
+ * we prevent matches with the string of window index 0.
+ */
+ Posf *prev = s->prev;
+ uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+ /* Compare two bytes at a time. Note: this is not always beneficial.
+ * Try with and without -DUNALIGNED_OK to check.
+ */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+ register ush scan_start = *(ushf*)scan;
+ register ush scan_end = *(ushf*)(scan + best_len - 1);
+#else
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+ register Byte scan_end1 = scan[best_len - 1];
+ register Byte scan_end = scan[best_len];
+#endif
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ /* Do not waste too much time if we already have a good match: */
+ if (s->prev_length >= s->good_match) {
+ chain_length >>= 2;
+ }
+ /* Do not look for matches beyond the end of the input. This is necessary
+ * to make deflate deterministic.
+ */
+ if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead;
+
+ Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
+ "need lookahead");
+
+ do {
+ Assert(cur_match < s->strstart, "no future");
+ match = s->window + cur_match;
+
+ /* Skip to next match if the match length cannot increase
+ * or if the match length is less than 2. Note that the checks below
+ * for insufficient lookahead only occur occasionally for performance
+ * reasons. Therefore uninitialized memory will be accessed, and
+ * conditional jumps will be made that depend on those values.
+ * However the length of the match is limited to the lookahead, so
+ * the output of deflate is not affected by the uninitialized values.
+ */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+ /* This code assumes sizeof(unsigned short) == 2. Do not use
+ * UNALIGNED_OK if your compiler uses a different size.
+ */
+ if (*(ushf*)(match + best_len - 1) != scan_end ||
+ *(ushf*)match != scan_start) continue;
+
+ /* It is not necessary to compare scan[2] and match[2] since they are
+ * always equal when the other bytes match, given that the hash keys
+ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+ * strstart + 3, + 5, up to strstart + 257. We check for insufficient
+ * lookahead only every 4th comparison; the 128th check will be made
+ * at strstart + 257. If MAX_MATCH-2 is not a multiple of 8, it is
+ * necessary to put more guard bytes at the end of the window, or
+ * to check more often for insufficient lookahead.
+ */
+ Assert(scan[2] == match[2], "scan[2]?");
+ scan++, match++;
+ do {
+ } while (*(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
+ *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
+ *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
+ *(ushf*)(scan += 2) == *(ushf*)(match += 2) &&
+ scan < strend);
+ /* The funny "do {}" generates better code on most compilers */
+
+ /* Here, scan <= window + strstart + 257 */
+ Assert(scan <= s->window + (unsigned)(s->window_size - 1),
+ "wild scan");
+ if (*scan == *match) scan++;
+
+ len = (MAX_MATCH - 1) - (int)(strend - scan);
+ scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+ if (match[best_len] != scan_end ||
+ match[best_len - 1] != scan_end1 ||
+ *match != *scan ||
+ *++match != scan[1]) continue;
+
+ /* The check at best_len - 1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match++;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart + 258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window + (unsigned)(s->window_size - 1),
+ "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+ if (len > best_len) {
+ s->match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+ scan_end = *(ushf*)(scan + best_len - 1);
+#else
+ scan_end1 = scan[best_len - 1];
+ scan_end = scan[best_len];
+#endif
+ }
+ } while ((cur_match = prev[cur_match & wmask]) > limit
+ && --chain_length != 0);
+
+ if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+ return s->lookahead;
+}
+
+#else /* FASTEST */
+
+/* ---------------------------------------------------------------------------
+ * Optimized version for FASTEST only
+ */
+local uInt longest_match(deflate_state *s, IPos cur_match) {
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
+ "need lookahead");
+
+ Assert(cur_match < s->strstart, "no future");
+
+ match = s->window + cur_match;
+
+ /* Return failure if the match length is less than 2:
+ */
+ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+ /* The check at best_len - 1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match += 2;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart + 258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window + (unsigned)(s->window_size - 1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+
+ if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+ s->match_start = cur_match;
+ return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
+}
+
+#endif /* FASTEST */
+
+#ifdef ZLIB_DEBUG
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(deflate_state *s, IPos start, IPos match, int length) {
+ /* check that the match is indeed a match */
+ if (zmemcmp(s->window + match,
+ s->window + start, length) != EQUAL) {
+ fprintf(stderr, " start %u, match %u, length %d\n",
+ start, match, length);
+ do {
+ fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+ } while (--length != 0);
+ z_error("invalid match");
+ }
+ if (z_verbose > 1) {
+ fprintf(stderr,"\\[%d,%d]", start - match, length);
+ do { putc(s->window[start++], stderr); } while (--length != 0);
+ }
+}
+#else
+# define check_match(s, start, match, length)
+#endif /* ZLIB_DEBUG */
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, last) { \
+ _tr_flush_block(s, (s->block_start >= 0L ? \
+ (charf *)&s->window[(unsigned)s->block_start] : \
+ (charf *)Z_NULL), \
+ (ulg)((long)s->strstart - s->block_start), \
+ (last)); \
+ s->block_start = s->strstart; \
+ flush_pending(s->strm); \
+ Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, last) { \
+ FLUSH_BLOCK_ONLY(s, last); \
+ if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \
+}
+
+/* Maximum stored block length in deflate format (not including header). */
+#define MAX_STORED 65535
+
+/* Minimum of a and b. */
+#ifndef MIN
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+#endif
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ *
+ * In case deflateParams() is used to later switch to a non-zero compression
+ * level, s->matches (otherwise unused when storing) keeps track of the number
+ * of hash table slides to perform. If s->matches is 1, then one hash table
+ * slide will be done when switching. If s->matches is 2, the maximum value
+ * allowed here, then the hash table will be cleared, since two or more slides
+ * is the same as a clear.
+ *
+ * deflate_stored() is written to minimize the number of times an input byte is
+ * copied. It is most efficient with large input and output buffers, which
+ * maximizes the opportunities to have a single copy from next_in to next_out.
+ */
+local block_state deflate_stored(deflate_state *s, int flush) {
+ /* Smallest worthy block size when not flushing or finishing. By default
+ * this is 32K. This can be as small as 507 bytes for memLevel == 1. For
+ * large input and output buffers, the stored block size will be larger.
+ */
+ unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size);
+
+ /* Copy as many min_block or larger stored blocks directly to next_out as
+ * possible. If flushing, copy the remaining available input to next_out as
+ * stored blocks, if there is enough space.
+ */
+ unsigned len, left, have, last = 0;
+ unsigned used = s->strm->avail_in;
+ do {
+ /* Set len to the maximum size block that we can copy directly with the
+ * available input data and output space. Set left to how much of that
+ * would be copied from what's left in the window.
+ */
+ len = MAX_STORED; /* maximum deflate stored block length */
+ have = (s->bi_valid + 42) >> 3; /* number of header bytes */
+ if (s->strm->avail_out < have) /* need room for header */
+ break;
+ /* maximum stored block length that will fit in avail_out: */
+ have = s->strm->avail_out - have;
+ left = s->strstart - s->block_start; /* bytes left in window */
+ if (len > (ulg)left + s->strm->avail_in)
+ len = left + s->strm->avail_in; /* limit len to the input */
+ if (len > have)
+ len = have; /* limit len to the output */
+
+ /* If the stored block would be less than min_block in length, or if
+ * unable to copy all of the available input when flushing, then try
+ * copying to the window and the pending buffer instead. Also don't
+ * write an empty block when flushing -- deflate() does that.
+ */
+ if (len < min_block && ((len == 0 && flush != Z_FINISH) ||
+ flush == Z_NO_FLUSH ||
+ len != left + s->strm->avail_in))
+ break;
+
+ /* Make a dummy stored block in pending to get the header bytes,
+ * including any pending bits. This also updates the debugging counts.
+ */
+ last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0;
+ _tr_stored_block(s, (char *)0, 0L, last);
+
+ /* Replace the lengths in the dummy stored block with len. */
+ s->pending_buf[s->pending - 4] = len;
+ s->pending_buf[s->pending - 3] = len >> 8;
+ s->pending_buf[s->pending - 2] = ~len;
+ s->pending_buf[s->pending - 1] = ~len >> 8;
+
+ /* Write the stored block header bytes. */
+ flush_pending(s->strm);
+
+#ifdef ZLIB_DEBUG
+ /* Update debugging counts for the data about to be copied. */
+ s->compressed_len += len << 3;
+ s->bits_sent += len << 3;
+#endif
+
+ /* Copy uncompressed bytes from the window to next_out. */
+ if (left) {
+ if (left > len)
+ left = len;
+ zmemcpy(s->strm->next_out, s->window + s->block_start, left);
+ s->strm->next_out += left;
+ s->strm->avail_out -= left;
+ s->strm->total_out += left;
+ s->block_start += left;
+ len -= left;
+ }
+
+ /* Copy uncompressed bytes directly from next_in to next_out, updating
+ * the check value.
+ */
+ if (len) {
+ read_buf(s->strm, s->strm->next_out, len);
+ s->strm->next_out += len;
+ s->strm->avail_out -= len;
+ s->strm->total_out += len;
+ }
+ } while (last == 0);
+
+ /* Update the sliding window with the last s->w_size bytes of the copied
+ * data, or append all of the copied data to the existing window if less
+ * than s->w_size bytes were copied. Also update the number of bytes to
+ * insert in the hash tables, in the event that deflateParams() switches to
+ * a non-zero compression level.
+ */
+ used -= s->strm->avail_in; /* number of input bytes directly copied */
+ if (used) {
+ /* If any input was used, then no unused input remains in the window,
+ * therefore s->block_start == s->strstart.
+ */
+ if (used >= s->w_size) { /* supplant the previous history */
+ s->matches = 2; /* clear hash */
+ zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size);
+ s->strstart = s->w_size;
+ s->insert = s->strstart;
+ }
+ else {
+ if (s->window_size - s->strstart <= used) {
+ /* Slide the window down. */
+ s->strstart -= s->w_size;
+ zmemcpy(s->window, s->window + s->w_size, s->strstart);
+ if (s->matches < 2)
+ s->matches++; /* add a pending slide_hash() */
+ if (s->insert > s->strstart)
+ s->insert = s->strstart;
+ }
+ zmemcpy(s->window + s->strstart, s->strm->next_in - used, used);
+ s->strstart += used;
+ s->insert += MIN(used, s->w_size - s->insert);
+ }
+ s->block_start = s->strstart;
+ }
+ if (s->high_water < s->strstart)
+ s->high_water = s->strstart;
+
+ /* If the last block was written to next_out, then done. */
+ if (last)
+ return finish_done;
+
+ /* If flushing and all input has been consumed, then done. */
+ if (flush != Z_NO_FLUSH && flush != Z_FINISH &&
+ s->strm->avail_in == 0 && (long)s->strstart == s->block_start)
+ return block_done;
+
+ /* Fill the window with any remaining input. */
+ have = s->window_size - s->strstart;
+ if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) {
+ /* Slide the window down. */
+ s->block_start -= s->w_size;
+ s->strstart -= s->w_size;
+ zmemcpy(s->window, s->window + s->w_size, s->strstart);
+ if (s->matches < 2)
+ s->matches++; /* add a pending slide_hash() */
+ have += s->w_size; /* more space now */
+ if (s->insert > s->strstart)
+ s->insert = s->strstart;
+ }
+ if (have > s->strm->avail_in)
+ have = s->strm->avail_in;
+ if (have) {
+ read_buf(s->strm, s->window + s->strstart, have);
+ s->strstart += have;
+ s->insert += MIN(have, s->w_size - s->insert);
+ }
+ if (s->high_water < s->strstart)
+ s->high_water = s->strstart;
+
+ /* There was not enough avail_out to write a complete worthy or flushed
+ * stored block to next_out. Write a stored block to pending instead, if we
+ * have enough input for a worthy block, or if flushing and there is enough
+ * room for the remaining input as a stored block in the pending buffer.
+ */
+ have = (s->bi_valid + 42) >> 3; /* number of header bytes */
+ /* maximum stored block length that will fit in pending: */
+ have = MIN(s->pending_buf_size - have, MAX_STORED);
+ min_block = MIN(have, s->w_size);
+ left = s->strstart - s->block_start;
+ if (left >= min_block ||
+ ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH &&
+ s->strm->avail_in == 0 && left <= have)) {
+ len = MIN(left, have);
+ last = flush == Z_FINISH && s->strm->avail_in == 0 &&
+ len == left ? 1 : 0;
+ _tr_stored_block(s, (charf *)s->window + s->block_start, len, last);
+ s->block_start += len;
+ flush_pending(s->strm);
+ }
+
+ /* We've done all we can with the available input and output. */
+ return last ? finish_started : need_more;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(deflate_state *s, int flush) {
+ IPos hash_head; /* head of the hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart + 2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ hash_head = NIL;
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ * At this point we have always match_length < MIN_MATCH
+ */
+ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ s->match_length = longest_match (s, hash_head);
+ /* longest_match() sets match_start */
+ }
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->match_start, s->match_length);
+
+ _tr_tally_dist(s, s->strstart - s->match_start,
+ s->match_length - MIN_MATCH, bflush);
+
+ s->lookahead -= s->match_length;
+
+ /* Insert new strings in the hash table only if the match length
+ * is not too large. This saves time but degrades compression.
+ */
+#ifndef FASTEST
+ if (s->match_length <= s->max_insert_length &&
+ s->lookahead >= MIN_MATCH) {
+ s->match_length--; /* string at strstart already in table */
+ do {
+ s->strstart++;
+ INSERT_STRING(s, s->strstart, hash_head);
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead.
+ */
+ } while (--s->match_length != 0);
+ s->strstart++;
+ } else
+#endif
+ {
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart + 1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ * matter since it will be recomputed at next deflate call.
+ */
+ }
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit(s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
+ if (flush == Z_FINISH) {
+ FLUSH_BLOCK(s, 1);
+ return finish_done;
+ }
+ if (s->sym_next)
+ FLUSH_BLOCK(s, 0);
+ return block_done;
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(deflate_state *s, int flush) {
+ IPos hash_head; /* head of hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ /* Process the input block. */
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart + 2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ hash_head = NIL;
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ */
+ s->prev_length = s->match_length, s->prev_match = s->match_start;
+ s->match_length = MIN_MATCH-1;
+
+ if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+ s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ s->match_length = longest_match (s, hash_head);
+ /* longest_match() sets match_start */
+
+ if (s->match_length <= 5 && (s->strategy == Z_FILTERED
+#if TOO_FAR <= 32767
+ || (s->match_length == MIN_MATCH &&
+ s->strstart - s->match_start > TOO_FAR)
+#endif
+ )) {
+
+ /* If prev_match is also MIN_MATCH, match_start is garbage
+ * but we will ignore the current match anyway.
+ */
+ s->match_length = MIN_MATCH-1;
+ }
+ }
+ /* If there was a match at the previous step and the current
+ * match is not better, output the previous match:
+ */
+ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+ uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+ /* Do not insert strings in hash table beyond this. */
+
+ check_match(s, s->strstart - 1, s->prev_match, s->prev_length);
+
+ _tr_tally_dist(s, s->strstart - 1 - s->prev_match,
+ s->prev_length - MIN_MATCH, bflush);
+
+ /* Insert in hash table all strings up to the end of the match.
+ * strstart - 1 and strstart are already inserted. If there is not
+ * enough lookahead, the last two strings are not inserted in
+ * the hash table.
+ */
+ s->lookahead -= s->prev_length - 1;
+ s->prev_length -= 2;
+ do {
+ if (++s->strstart <= max_insert) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+ } while (--s->prev_length != 0);
+ s->match_available = 0;
+ s->match_length = MIN_MATCH-1;
+ s->strstart++;
+
+ if (bflush) FLUSH_BLOCK(s, 0);
+
+ } else if (s->match_available) {
+ /* If there was no match at the previous position, output a
+ * single literal. If there was a match but the current match
+ * is longer, truncate the previous match to a single literal.
+ */
+ Tracevv((stderr,"%c", s->window[s->strstart - 1]));
+ _tr_tally_lit(s, s->window[s->strstart - 1], bflush);
+ if (bflush) {
+ FLUSH_BLOCK_ONLY(s, 0);
+ }
+ s->strstart++;
+ s->lookahead--;
+ if (s->strm->avail_out == 0) return need_more;
+ } else {
+ /* There is no previous match to compare with, wait for
+ * the next step to decide.
+ */
+ s->match_available = 1;
+ s->strstart++;
+ s->lookahead--;
+ }
+ }
+ Assert (flush != Z_NO_FLUSH, "no flush?");
+ if (s->match_available) {
+ Tracevv((stderr,"%c", s->window[s->strstart - 1]));
+ _tr_tally_lit(s, s->window[s->strstart - 1], bflush);
+ s->match_available = 0;
+ }
+ s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
+ if (flush == Z_FINISH) {
+ FLUSH_BLOCK(s, 1);
+ return finish_done;
+ }
+ if (s->sym_next)
+ FLUSH_BLOCK(s, 0);
+ return block_done;
+}
+#endif /* FASTEST */
+
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one. Do not maintain a hash table. (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+local block_state deflate_rle(deflate_state *s, int flush) {
+ int bflush; /* set if current block must be flushed */
+ uInt prev; /* byte at distance one to match */
+ Bytef *scan, *strend; /* scan goes up to strend for length of run */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the longest run, plus one for the unrolled loop.
+ */
+ if (s->lookahead <= MAX_MATCH) {
+ fill_window(s);
+ if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* See how many times the previous byte repeats */
+ s->match_length = 0;
+ if (s->lookahead >= MIN_MATCH && s->strstart > 0) {
+ scan = s->window + s->strstart - 1;
+ prev = *scan;
+ if (prev == *++scan && prev == *++scan && prev == *++scan) {
+ strend = s->window + s->strstart + MAX_MATCH;
+ do {
+ } while (prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ scan < strend);
+ s->match_length = MAX_MATCH - (uInt)(strend - scan);
+ if (s->match_length > s->lookahead)
+ s->match_length = s->lookahead;
+ }
+ Assert(scan <= s->window + (uInt)(s->window_size - 1),
+ "wild scan");
+ }
+
+ /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->strstart - 1, s->match_length);
+
+ _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);
+
+ s->lookahead -= s->match_length;
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit(s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ s->insert = 0;
+ if (flush == Z_FINISH) {
+ FLUSH_BLOCK(s, 1);
+ return finish_done;
+ }
+ if (s->sym_next)
+ FLUSH_BLOCK(s, 0);
+ return block_done;
+}
+
+/* ===========================================================================
+ * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table.
+ * (It will be regenerated if this run of deflate switches away from Huffman.)
+ */
+local block_state deflate_huff(deflate_state *s, int flush) {
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we have a literal to write. */
+ if (s->lookahead == 0) {
+ fill_window(s);
+ if (s->lookahead == 0) {
+ if (flush == Z_NO_FLUSH)
+ return need_more;
+ break; /* flush the current block */
+ }
+ }
+
+ /* Output a literal byte */
+ s->match_length = 0;
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit(s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ s->insert = 0;
+ if (flush == Z_FINISH) {
+ FLUSH_BLOCK(s, 1);
+ return finish_done;
+ }
+ if (s->sym_next)
+ FLUSH_BLOCK(s, 0);
+ return block_done;
+}
diff --git a/lib/zlib/deflate.h b/lib/zlib/deflate.h
new file mode 100644
index 0000000..8696791
--- /dev/null
+++ b/lib/zlib/deflate.h
@@ -0,0 +1,346 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-2018 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef DEFLATE_H
+#define DEFLATE_H
+
+#include "zutil.h"
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer creation by deflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip encoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GZIP
+#endif
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS 256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES 30
+/* number of distance codes */
+
+#define BL_CODES 19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define Buf_size 16
+/* size of bit buffer in bi_buf */
+
+#define INIT_STATE 42 /* zlib header -> BUSY_STATE */
+#ifdef GZIP
+# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */
+#endif
+#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */
+#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */
+#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */
+#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */
+#define BUSY_STATE 113 /* deflate -> FINISH_STATE */
+#define FINISH_STATE 666 /* stream complete */
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+ union {
+ ush freq; /* frequency count */
+ ush code; /* bit string */
+ } fc;
+ union {
+ ush dad; /* father node in Huffman tree */
+ ush len; /* length of bit string */
+ } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad dl.dad
+#define Len dl.len
+
+typedef struct static_tree_desc_s static_tree_desc;
+
+typedef struct tree_desc_s {
+ ct_data *dyn_tree; /* the dynamic tree */
+ int max_code; /* largest code with non zero frequency */
+ const static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ int status; /* as the name implies */
+ Bytef *pending_buf; /* output still pending */
+ ulg pending_buf_size; /* size of pending_buf */
+ Bytef *pending_out; /* next pending byte to output to the stream */
+ ulg pending; /* nb of bytes in the pending buffer */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ gz_headerp gzhead; /* gzip header information to write */
+ ulg gzindex; /* where in extra, name, or comment */
+ Byte method; /* can only be DEFLATED */
+ int last_flush; /* value of flush param for previous deflate call */
+
+ /* used by deflate.c: */
+
+ uInt w_size; /* LZ77 window size (32K by default) */
+ uInt w_bits; /* log2(w_size) (8..16) */
+ uInt w_mask; /* w_size - 1 */
+
+ Bytef *window;
+ /* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least wSize
+ * bytes. With this organization, matches are limited to a distance of
+ * wSize-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: use the user input buffer as sliding window.
+ */
+
+ ulg window_size;
+ /* Actual size of window: 2*wSize, except when the user input buffer
+ * is directly used as sliding window.
+ */
+
+ Posf *prev;
+ /* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+ Posf *head; /* Heads of the hash chains or NIL. */
+
+ uInt ins_h; /* hash index of string to be inserted */
+ uInt hash_size; /* number of elements in hash table */
+ uInt hash_bits; /* log2(hash_size) */
+ uInt hash_mask; /* hash_size-1 */
+
+ uInt hash_shift;
+ /* Number of bits by which ins_h must be shifted at each input
+ * step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * hash_shift * MIN_MATCH >= hash_bits
+ */
+
+ long block_start;
+ /* Window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+ uInt match_length; /* length of best match */
+ IPos prev_match; /* previous match */
+ int match_available; /* set if previous match exists */
+ uInt strstart; /* start of string to insert */
+ uInt match_start; /* start of matching string */
+ uInt lookahead; /* number of valid bytes ahead in window */
+
+ uInt prev_length;
+ /* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ uInt max_chain_length;
+ /* To speed up deflation, hash chains are never searched beyond this
+ * length. A higher limit improves compression ratio but degrades the
+ * speed.
+ */
+
+ uInt max_lazy_match;
+ /* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+# define max_insert_length max_lazy_match
+ /* Insert new strings in the hash table only if the match length is not
+ * greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+ int level; /* compression level (1..9) */
+ int strategy; /* favor or force Huffman coding*/
+
+ uInt good_match;
+ /* Use a faster search when the previous match is longer than this */
+
+ int nice_match; /* Stop searching when current match exceeds this */
+
+ /* used by trees.c: */
+ /* Didn't use ct_data typedef below to suppress compiler warning */
+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
+
+ struct tree_desc_s l_desc; /* desc. for literal tree */
+ struct tree_desc_s d_desc; /* desc. for distance tree */
+ struct tree_desc_s bl_desc; /* desc. for bit length tree */
+
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+ int heap_len; /* number of elements in the heap */
+ int heap_max; /* element of largest frequency */
+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+ uch depth[2*L_CODES+1];
+ /* Depth of each subtree used as tie breaker for trees of equal frequency
+ */
+
+ uchf *sym_buf; /* buffer for distances and literals/lengths */
+
+ uInt lit_bufsize;
+ /* Size of match buffer for literals/lengths. There are 4 reasons for
+ * limiting lit_bufsize to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input
+ * data is still in the window so we can still emit a stored block even
+ * when input comes from standard input. (This can also be done for
+ * all blocks if lit_bufsize is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * This is applicable only for zip (not gzip or zlib).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting
+ * trees more frequently.
+ * - I can't count above 4
+ */
+
+ uInt sym_next; /* running index in sym_buf */
+ uInt sym_end; /* symbol table full when sym_next reaches this */
+
+ ulg opt_len; /* bit length of current block with optimal trees */
+ ulg static_len; /* bit length of current block with static trees */
+ uInt matches; /* number of string matches in current block */
+ uInt insert; /* bytes at end of window left to insert */
+
+#ifdef ZLIB_DEBUG
+ ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
+#endif
+
+ ush bi_buf;
+ /* Output buffer. bits are inserted starting at the bottom (least
+ * significant bits).
+ */
+ int bi_valid;
+ /* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+ ulg high_water;
+ /* High water mark offset in window for initialized bytes -- bytes above
+ * this are set to zero in order to avoid memory check warnings when
+ * longest match routines access bytes past the input. This is then
+ * updated to the new high water mark.
+ */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+#define WIN_INIT MAX_MATCH
+/* Number of bytes after end of data in window to initialize in order to avoid
+ memory checker errors from longest match routines */
+
+ /* in trees.c */
+void ZLIB_INTERNAL _tr_init(deflate_state *s);
+int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc);
+void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf,
+ ulg stored_len, int last);
+void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s);
+void ZLIB_INTERNAL _tr_align(deflate_state *s);
+void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf,
+ ulg stored_len, int last);
+
+#define d_code(dist) \
+ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef ZLIB_DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+ extern uch ZLIB_INTERNAL _length_code[];
+ extern uch ZLIB_INTERNAL _dist_code[];
+#else
+ extern const uch ZLIB_INTERNAL _length_code[];
+ extern const uch ZLIB_INTERNAL _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+ { uch cc = (c); \
+ s->sym_buf[s->sym_next++] = 0; \
+ s->sym_buf[s->sym_next++] = 0; \
+ s->sym_buf[s->sym_next++] = cc; \
+ s->dyn_ltree[cc].Freq++; \
+ flush = (s->sym_next == s->sym_end); \
+ }
+# define _tr_tally_dist(s, distance, length, flush) \
+ { uch len = (uch)(length); \
+ ush dist = (ush)(distance); \
+ s->sym_buf[s->sym_next++] = (uch)dist; \
+ s->sym_buf[s->sym_next++] = (uch)(dist >> 8); \
+ s->sym_buf[s->sym_next++] = len; \
+ dist--; \
+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+ s->dyn_dtree[d_code(dist)].Freq++; \
+ flush = (s->sym_next == s->sym_end); \
+ }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+ flush = _tr_tally(s, distance, length)
+#endif
+
+#endif /* DEFLATE_H */
diff --git a/lib/zlib/gzclose.c b/lib/zlib/gzclose.c
new file mode 100644
index 0000000..48d6a86
--- /dev/null
+++ b/lib/zlib/gzclose.c
@@ -0,0 +1,23 @@
+/* gzclose.c -- zlib gzclose() function
+ * Copyright (C) 2004, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+/* gzclose() is in a separate file so that it is linked in only if it is used.
+ That way the other gzclose functions can be used instead to avoid linking in
+ unneeded compression or decompression routines. */
+int ZEXPORT gzclose(gzFile file) {
+#ifndef NO_GZCOMPRESS
+ gz_statep state;
+
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+
+ return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file);
+#else
+ return gzclose_r(file);
+#endif
+}
diff --git a/lib/zlib/gzguts.h b/lib/zlib/gzguts.h
new file mode 100644
index 0000000..4448a09
--- /dev/null
+++ b/lib/zlib/gzguts.h
@@ -0,0 +1,218 @@
+/* gzguts.h -- zlib internal header definitions for gz* operations
+ * Copyright (C) 2004-2019 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#ifdef _LARGEFILE64_SOURCE
+# ifndef _LARGEFILE_SOURCE
+# define _LARGEFILE_SOURCE 1
+# endif
+# undef _FILE_OFFSET_BITS
+# undef _TIME_BITS
+#endif
+
+#ifdef HAVE_HIDDEN
+# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+#else
+# define ZLIB_INTERNAL
+#endif
+
+#include "zlib.h"
+#include <stdio.h>
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+# include <limits.h>
+#endif
+
+#ifndef _POSIX_SOURCE
+# define _POSIX_SOURCE
+#endif
+#include <fcntl.h>
+
+#ifdef _WIN32
+# include <stddef.h>
+#endif
+
+#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
+# include <io.h>
+#endif
+
+#if defined(_WIN32)
+# define WIDECHAR
+#endif
+
+#ifdef WINAPI_FAMILY
+# define open _open
+# define read _read
+# define write _write
+# define close _close
+#endif
+
+#ifdef NO_DEFLATE /* for compatibility with old definition */
+# define NO_GZCOMPRESS
+#endif
+
+#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+
+#if defined(__CYGWIN__)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+
+#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+
+#ifndef HAVE_VSNPRINTF
+# ifdef MSDOS
+/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+ but for now we just assume it doesn't. */
+# define NO_vsnprintf
+# endif
+# ifdef __TURBOC__
+# define NO_vsnprintf
+# endif
+# ifdef WIN32
+/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+# if !defined(vsnprintf) && !defined(NO_vsnprintf)
+# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
+# define vsnprintf _vsnprintf
+# endif
+# endif
+# endif
+# ifdef __SASC
+# define NO_vsnprintf
+# endif
+# ifdef VMS
+# define NO_vsnprintf
+# endif
+# ifdef __OS400__
+# define NO_vsnprintf
+# endif
+# ifdef __MVS__
+# define NO_vsnprintf
+# endif
+#endif
+
+/* unlike snprintf (which is required in C99), _snprintf does not guarantee
+ null termination of the result -- however this is only used in gzlib.c where
+ the result is assured to fit in the space provided */
+#if defined(_MSC_VER) && _MSC_VER < 1900
+# define snprintf _snprintf
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* since "static" is used to mean two completely different things in C, we
+ define "local" for the non-static meaning of "static", for readability
+ (compile with -Dlocal if your debugger can't find static symbols) */
+
+/* gz* functions always use library allocation functions */
+#ifndef STDC
+ extern voidp malloc(uInt size);
+ extern void free(voidpf ptr);
+#endif
+
+/* get errno and strerror definition */
+#if defined UNDER_CE
+# include <windows.h>
+# define zstrerror() gz_strwinerror((DWORD)GetLastError())
+#else
+# ifndef NO_STRERROR
+# include <errno.h>
+# define zstrerror() strerror(errno)
+# else
+# define zstrerror() "stdio error (consult errno)"
+# endif
+#endif
+
+/* provide prototypes for these when building zlib without LFS */
+#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
+ ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
+ ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int);
+ ZEXTERN z_off64_t ZEXPORT gztell64(gzFile);
+ ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile);
+#endif
+
+/* default memLevel */
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+
+/* default i/o buffer size -- double this for output when reading (this and
+ twice this must be able to fit in an unsigned type) */
+#define GZBUFSIZE 8192
+
+/* gzip modes, also provide a little integrity check on the passed structure */
+#define GZ_NONE 0
+#define GZ_READ 7247
+#define GZ_WRITE 31153
+#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */
+
+/* values for gz_state how */
+#define LOOK 0 /* look for a gzip header */
+#define COPY 1 /* copy input directly */
+#define GZIP 2 /* decompress a gzip stream */
+
+/* internal gzip file state data structure */
+typedef struct {
+ /* exposed contents for gzgetc() macro */
+ struct gzFile_s x; /* "x" for exposed */
+ /* x.have: number of bytes available at x.next */
+ /* x.next: next output data to deliver or write */
+ /* x.pos: current position in uncompressed data */
+ /* used for both reading and writing */
+ int mode; /* see gzip modes above */
+ int fd; /* file descriptor */
+ char *path; /* path or fd for error messages */
+ unsigned size; /* buffer size, zero if not allocated yet */
+ unsigned want; /* requested buffer size, default is GZBUFSIZE */
+ unsigned char *in; /* input buffer (double-sized when writing) */
+ unsigned char *out; /* output buffer (double-sized when reading) */
+ int direct; /* 0 if processing gzip, 1 if transparent */
+ /* just for reading */
+ int how; /* 0: get header, 1: copy, 2: decompress */
+ z_off64_t start; /* where the gzip data started, for rewinding */
+ int eof; /* true if end of input file reached */
+ int past; /* true if read requested past end */
+ /* just for writing */
+ int level; /* compression level */
+ int strategy; /* compression strategy */
+ int reset; /* true if a reset is pending after a Z_FINISH */
+ /* seek request */
+ z_off64_t skip; /* amount to skip (already rewound if backwards) */
+ int seek; /* true if seek request pending */
+ /* error information */
+ int err; /* error code */
+ char *msg; /* error message */
+ /* zlib inflate or deflate stream */
+ z_stream strm; /* stream structure in-place (not a pointer) */
+} gz_state;
+typedef gz_state FAR *gz_statep;
+
+/* shared functions */
+void ZLIB_INTERNAL gz_error(gz_statep, int, const char *);
+#if defined UNDER_CE
+char ZLIB_INTERNAL *gz_strwinerror(DWORD error);
+#endif
+
+/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
+ value -- needed when comparing unsigned to z_off64_t, which is signed
+ (possible z_off64_t types off_t, off64_t, and long are all signed) */
+#ifdef INT_MAX
+# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
+#else
+unsigned ZLIB_INTERNAL gz_intmax(void);
+# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
+#endif
diff --git a/lib/zlib/gzlib.c b/lib/zlib/gzlib.c
new file mode 100644
index 0000000..29fc448
--- /dev/null
+++ b/lib/zlib/gzlib.c
@@ -0,0 +1,582 @@
+/* gzlib.c -- zlib functions common to reading and writing gzip files
+ * Copyright (C) 2004-2019 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+#if defined(_WIN32) && !defined(__BORLANDC__)
+# define LSEEK _lseeki64
+#else
+#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
+# define LSEEK lseek64
+#else
+# define LSEEK lseek
+#endif
+#endif
+
+#if defined UNDER_CE
+
+/* Map the Windows error number in ERROR to a locale-dependent error message
+ string and return a pointer to it. Typically, the values for ERROR come
+ from GetLastError.
+
+ The string pointed to shall not be modified by the application, but may be
+ overwritten by a subsequent call to gz_strwinerror
+
+ The gz_strwinerror function does not change the current setting of
+ GetLastError. */
+char ZLIB_INTERNAL *gz_strwinerror(DWORD error) {
+ static char buf[1024];
+
+ wchar_t *msgbuf;
+ DWORD lasterr = GetLastError();
+ DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ NULL,
+ error,
+ 0, /* Default language */
+ (LPVOID)&msgbuf,
+ 0,
+ NULL);
+ if (chars != 0) {
+ /* If there is an \r\n appended, zap it. */
+ if (chars >= 2
+ && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
+ chars -= 2;
+ msgbuf[chars] = 0;
+ }
+
+ if (chars > sizeof (buf) - 1) {
+ chars = sizeof (buf) - 1;
+ msgbuf[chars] = 0;
+ }
+
+ wcstombs(buf, msgbuf, chars + 1);
+ LocalFree(msgbuf);
+ }
+ else {
+ sprintf(buf, "unknown win32 error (%ld)", error);
+ }
+
+ SetLastError(lasterr);
+ return buf;
+}
+
+#endif /* UNDER_CE */
+
+/* Reset gzip file state */
+local void gz_reset(gz_statep state) {
+ state->x.have = 0; /* no output data available */
+ if (state->mode == GZ_READ) { /* for reading ... */
+ state->eof = 0; /* not at end of file */
+ state->past = 0; /* have not read past end yet */
+ state->how = LOOK; /* look for gzip header */
+ }
+ else /* for writing ... */
+ state->reset = 0; /* no deflateReset pending */
+ state->seek = 0; /* no seek request pending */
+ gz_error(state, Z_OK, NULL); /* clear error */
+ state->x.pos = 0; /* no uncompressed data yet */
+ state->strm.avail_in = 0; /* no input data yet */
+}
+
+/* Open a gzip file either by name or file descriptor. */
+local gzFile gz_open(const void *path, int fd, const char *mode) {
+ gz_statep state;
+ z_size_t len;
+ int oflag;
+#ifdef O_CLOEXEC
+ int cloexec = 0;
+#endif
+#ifdef O_EXCL
+ int exclusive = 0;
+#endif
+
+ /* check input */
+ if (path == NULL)
+ return NULL;
+
+ /* allocate gzFile structure to return */
+ state = (gz_statep)malloc(sizeof(gz_state));
+ if (state == NULL)
+ return NULL;
+ state->size = 0; /* no buffers allocated yet */
+ state->want = GZBUFSIZE; /* requested buffer size */
+ state->msg = NULL; /* no error message yet */
+
+ /* interpret mode */
+ state->mode = GZ_NONE;
+ state->level = Z_DEFAULT_COMPRESSION;
+ state->strategy = Z_DEFAULT_STRATEGY;
+ state->direct = 0;
+ while (*mode) {
+ if (*mode >= '0' && *mode <= '9')
+ state->level = *mode - '0';
+ else
+ switch (*mode) {
+ case 'r':
+ state->mode = GZ_READ;
+ break;
+#ifndef NO_GZCOMPRESS
+ case 'w':
+ state->mode = GZ_WRITE;
+ break;
+ case 'a':
+ state->mode = GZ_APPEND;
+ break;
+#endif
+ case '+': /* can't read and write at the same time */
+ free(state);
+ return NULL;
+ case 'b': /* ignore -- will request binary anyway */
+ break;
+#ifdef O_CLOEXEC
+ case 'e':
+ cloexec = 1;
+ break;
+#endif
+#ifdef O_EXCL
+ case 'x':
+ exclusive = 1;
+ break;
+#endif
+ case 'f':
+ state->strategy = Z_FILTERED;
+ break;
+ case 'h':
+ state->strategy = Z_HUFFMAN_ONLY;
+ break;
+ case 'R':
+ state->strategy = Z_RLE;
+ break;
+ case 'F':
+ state->strategy = Z_FIXED;
+ break;
+ case 'T':
+ state->direct = 1;
+ break;
+ default: /* could consider as an error, but just ignore */
+ ;
+ }
+ mode++;
+ }
+
+ /* must provide an "r", "w", or "a" */
+ if (state->mode == GZ_NONE) {
+ free(state);
+ return NULL;
+ }
+
+ /* can't force transparent read */
+ if (state->mode == GZ_READ) {
+ if (state->direct) {
+ free(state);
+ return NULL;
+ }
+ state->direct = 1; /* for empty file */
+ }
+
+ /* save the path name for error messages */
+#ifdef WIDECHAR
+ if (fd == -2) {
+ len = wcstombs(NULL, path, 0);
+ if (len == (z_size_t)-1)
+ len = 0;
+ }
+ else
+#endif
+ len = strlen((const char *)path);
+ state->path = (char *)malloc(len + 1);
+ if (state->path == NULL) {
+ free(state);
+ return NULL;
+ }
+#ifdef WIDECHAR
+ if (fd == -2)
+ if (len)
+ wcstombs(state->path, path, len + 1);
+ else
+ *(state->path) = 0;
+ else
+#endif
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+ (void)snprintf(state->path, len + 1, "%s", (const char *)path);
+#else
+ strcpy(state->path, path);
+#endif
+
+ /* compute the flags for open() */
+ oflag =
+#ifdef O_LARGEFILE
+ O_LARGEFILE |
+#endif
+#ifdef O_BINARY
+ O_BINARY |
+#endif
+#ifdef O_CLOEXEC
+ (cloexec ? O_CLOEXEC : 0) |
+#endif
+ (state->mode == GZ_READ ?
+ O_RDONLY :
+ (O_WRONLY | O_CREAT |
+#ifdef O_EXCL
+ (exclusive ? O_EXCL : 0) |
+#endif
+ (state->mode == GZ_WRITE ?
+ O_TRUNC :
+ O_APPEND)));
+
+ /* open the file with the appropriate flags (or just use fd) */
+ state->fd = fd > -1 ? fd : (
+#ifdef WIDECHAR
+ fd == -2 ? _wopen(path, oflag, 0666) :
+#endif
+ open((const char *)path, oflag, 0666));
+ if (state->fd == -1) {
+ free(state->path);
+ free(state);
+ return NULL;
+ }
+ if (state->mode == GZ_APPEND) {
+ LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */
+ state->mode = GZ_WRITE; /* simplify later checks */
+ }
+
+ /* save the current position for rewinding (only if reading) */
+ if (state->mode == GZ_READ) {
+ state->start = LSEEK(state->fd, 0, SEEK_CUR);
+ if (state->start == -1) state->start = 0;
+ }
+
+ /* initialize stream */
+ gz_reset(state);
+
+ /* return stream */
+ return (gzFile)state;
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzopen(const char *path, const char *mode) {
+ return gz_open(path, -1, mode);
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzopen64(const char *path, const char *mode) {
+ return gz_open(path, -1, mode);
+}
+
+/* -- see zlib.h -- */
+gzFile ZEXPORT gzdopen(int fd, const char *mode) {
+ char *path; /* identifier for error messages */
+ gzFile gz;
+
+ if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
+ return NULL;
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+ (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
+#else
+ sprintf(path, "<fd:%d>", fd); /* for debugging */
+#endif
+ gz = gz_open(path, fd, mode);
+ free(path);
+ return gz;
+}
+
+/* -- see zlib.h -- */
+#ifdef WIDECHAR
+gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) {
+ return gz_open(path, -2, mode);
+}
+#endif
+
+/* -- see zlib.h -- */
+int ZEXPORT gzbuffer(gzFile file, unsigned size) {
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return -1;
+
+ /* make sure we haven't already allocated memory */
+ if (state->size != 0)
+ return -1;
+
+ /* check and set requested size */
+ if ((size << 1) < size)
+ return -1; /* need to be able to double it */
+ if (size < 8)
+ size = 8; /* needed to behave well with flushing */
+ state->want = size;
+ return 0;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzrewind(gzFile file) {
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return -1;
+
+ /* back up and start over */
+ if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
+ return -1;
+ gz_reset(state);
+ return 0;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {
+ unsigned n;
+ z_off64_t ret;
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return -1;
+
+ /* check that there's no error */
+ if (state->err != Z_OK && state->err != Z_BUF_ERROR)
+ return -1;
+
+ /* can only seek from start or relative to current position */
+ if (whence != SEEK_SET && whence != SEEK_CUR)
+ return -1;
+
+ /* normalize offset to a SEEK_CUR specification */
+ if (whence == SEEK_SET)
+ offset -= state->x.pos;
+ else if (state->seek)
+ offset += state->skip;
+ state->seek = 0;
+
+ /* if within raw area while reading, just go there */
+ if (state->mode == GZ_READ && state->how == COPY &&
+ state->x.pos + offset >= 0) {
+ ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR);
+ if (ret == -1)
+ return -1;
+ state->x.have = 0;
+ state->eof = 0;
+ state->past = 0;
+ state->seek = 0;
+ gz_error(state, Z_OK, NULL);
+ state->strm.avail_in = 0;
+ state->x.pos += offset;
+ return state->x.pos;
+ }
+
+ /* calculate skip amount, rewinding if needed for back seek when reading */
+ if (offset < 0) {
+ if (state->mode != GZ_READ) /* writing -- can't go backwards */
+ return -1;
+ offset += state->x.pos;
+ if (offset < 0) /* before start of file! */
+ return -1;
+ if (gzrewind(file) == -1) /* rewind, then skip to offset */
+ return -1;
+ }
+
+ /* if reading, skip what's in output buffer (one less gzgetc() check) */
+ if (state->mode == GZ_READ) {
+ n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
+ (unsigned)offset : state->x.have;
+ state->x.have -= n;
+ state->x.next += n;
+ state->x.pos += n;
+ offset -= n;
+ }
+
+ /* request skip (if not zero) */
+ if (offset) {
+ state->seek = 1;
+ state->skip = offset;
+ }
+ return state->x.pos + offset;
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) {
+ z_off64_t ret;
+
+ ret = gzseek64(file, (z_off64_t)offset, whence);
+ return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gztell64(gzFile file) {
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return -1;
+
+ /* return position */
+ return state->x.pos + (state->seek ? state->skip : 0);
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gztell(gzFile file) {
+ z_off64_t ret;
+
+ ret = gztell64(file);
+ return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+z_off64_t ZEXPORT gzoffset64(gzFile file) {
+ z_off64_t offset;
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return -1;
+
+ /* compute and return effective offset in file */
+ offset = LSEEK(state->fd, 0, SEEK_CUR);
+ if (offset == -1)
+ return -1;
+ if (state->mode == GZ_READ) /* reading */
+ offset -= state->strm.avail_in; /* don't count buffered input */
+ return offset;
+}
+
+/* -- see zlib.h -- */
+z_off_t ZEXPORT gzoffset(gzFile file) {
+ z_off64_t ret;
+
+ ret = gzoffset64(file);
+ return ret == (z_off_t)ret ? (z_off_t)ret : -1;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzeof(gzFile file) {
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return 0;
+
+ /* return end-of-file state */
+ return state->mode == GZ_READ ? state->past : 0;
+}
+
+/* -- see zlib.h -- */
+const char * ZEXPORT gzerror(gzFile file, int *errnum) {
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return NULL;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return NULL;
+
+ /* return error information */
+ if (errnum != NULL)
+ *errnum = state->err;
+ return state->err == Z_MEM_ERROR ? "out of memory" :
+ (state->msg == NULL ? "" : state->msg);
+}
+
+/* -- see zlib.h -- */
+void ZEXPORT gzclearerr(gzFile file) {
+ gz_statep state;
+
+ /* get internal structure and check integrity */
+ if (file == NULL)
+ return;
+ state = (gz_statep)file;
+ if (state->mode != GZ_READ && state->mode != GZ_WRITE)
+ return;
+
+ /* clear error and end-of-file */
+ if (state->mode == GZ_READ) {
+ state->eof = 0;
+ state->past = 0;
+ }
+ gz_error(state, Z_OK, NULL);
+}
+
+/* Create an error message in allocated memory and set state->err and
+ state->msg accordingly. Free any previous error message already there. Do
+ not try to free or allocate space if the error is Z_MEM_ERROR (out of
+ memory). Simply save the error message as a static string. If there is an
+ allocation failure constructing the error message, then convert the error to
+ out of memory. */
+void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {
+ /* free previously allocated message and clear */
+ if (state->msg != NULL) {
+ if (state->err != Z_MEM_ERROR)
+ free(state->msg);
+ state->msg = NULL;
+ }
+
+ /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
+ if (err != Z_OK && err != Z_BUF_ERROR)
+ state->x.have = 0;
+
+ /* set error code, and if no message, then done */
+ state->err = err;
+ if (msg == NULL)
+ return;
+
+ /* for an out of memory error, return literal string when requested */
+ if (err == Z_MEM_ERROR)
+ return;
+
+ /* construct error message with path */
+ if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
+ NULL) {
+ state->err = Z_MEM_ERROR;
+ return;
+ }
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+ (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
+ "%s%s%s", state->path, ": ", msg);
+#else
+ strcpy(state->msg, state->path);
+ strcat(state->msg, ": ");
+ strcat(state->msg, msg);
+#endif
+}
+
+#ifndef INT_MAX
+/* portably return maximum value for an int (when limits.h presumed not
+ available) -- we need to do this to cover cases where 2's complement not
+ used, since C standard permits 1's complement and sign-bit representations,
+ otherwise we could just use ((unsigned)-1) >> 1 */
+unsigned ZLIB_INTERNAL gz_intmax(void) {
+ unsigned p, q;
+
+ p = 1;
+ do {
+ q = p;
+ p <<= 1;
+ p++;
+ } while (p > q);
+ return q >> 1;
+}
+#endif
diff --git a/lib/zlib/gzread.c b/lib/zlib/gzread.c
new file mode 100644
index 0000000..4168cbc
--- /dev/null
+++ b/lib/zlib/gzread.c
@@ -0,0 +1,602 @@
+/* gzread.c -- zlib functions for reading gzip files
+ * Copyright (C) 2004-2017 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
+ state->fd, and update state->eof, state->err, and state->msg as appropriate.
+ This function needs to loop on read(), since read() is not guaranteed to
+ read the number of bytes requested, depending on the type of descriptor. */
+local int gz_load(gz_statep state, unsigned char *buf, unsigned len,
+ unsigned *have) {
+ int ret;
+ unsigned get, max = ((unsigned)-1 >> 2) + 1;
+
+ *have = 0;
+ do {
+ get = len - *have;
+ if (get > max)
+ get = max;
+ ret = read(state->fd, buf + *have, get);
+ if (ret <= 0)
+ break;
+ *have += (unsigned)ret;
+ } while (*have < len);
+ if (ret < 0) {
+ gz_error(state, Z_ERRNO, zstrerror());
+ return -1;
+ }
+ if (ret == 0)
+ state->eof = 1;
+ return 0;
+}
+
+/* Load up input buffer and set eof flag if last data loaded -- return -1 on
+ error, 0 otherwise. Note that the eof flag is set when the end of the input
+ file is reached, even though there may be unused data in the buffer. Once
+ that data has been used, no more attempts will be made to read the file.
+ If strm->avail_in != 0, then the current data is moved to the beginning of
+ the input buffer, and then the remainder of the buffer is loaded with the
+ available data from the input file. */
+local int gz_avail(gz_statep state) {
+ unsigned got;
+ z_streamp strm = &(state->strm);
+
+ if (state->err != Z_OK && state->err != Z_BUF_ERROR)
+ return -1;
+ if (state->eof == 0) {
+ if (strm->avail_in) { /* copy what's there to the start */
+ unsigned char *p = state->in;
+ unsigned const char *q = strm->next_in;
+ unsigned n = strm->avail_in;
+ do {
+ *p++ = *q++;
+ } while (--n);
+ }
+ if (gz_load(state, state->in + strm->avail_in,
+ state->size - strm->avail_in, &got) == -1)
+ return -1;
+ strm->avail_in += got;
+ strm->next_in = state->in;
+ }
+ return 0;
+}
+
+/* Look for gzip header, set up for inflate or copy. state->x.have must be 0.
+ If this is the first time in, allocate required memory. state->how will be
+ left unchanged if there is no more input data available, will be set to COPY
+ if there is no gzip header and direct copying will be performed, or it will
+ be set to GZIP for decompression. If direct copying, then leftover input
+ data from the input buffer will be copied to the output buffer. In that
+ case, all further file reads will be directly to either the output buffer or
+ a user buffer. If decompressing, the inflate state will be initialized.
+ gz_look() will return 0 on success or -1 on failure. */
+local int gz_look(gz_statep state) {
+ z_streamp strm = &(state->strm);
+
+ /* allocate read buffers and inflate memory */
+ if (state->size == 0) {
+ /* allocate buffers */
+ state->in = (unsigned char *)malloc(state->want);
+ state->out = (unsigned char *)malloc(state->want << 1);
+ if (state->in == NULL || state->out == NULL) {
+ free(state->out);
+ free(state->in);
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+ state->size = state->want;
+
+ /* allocate inflate memory */
+ state->strm.zalloc = Z_NULL;
+ state->strm.zfree = Z_NULL;
+ state->strm.opaque = Z_NULL;
+ state->strm.avail_in = 0;
+ state->strm.next_in = Z_NULL;
+ if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */
+ free(state->out);
+ free(state->in);
+ state->size = 0;
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+ }
+
+ /* get at least the magic bytes in the input buffer */
+ if (strm->avail_in < 2) {
+ if (gz_avail(state) == -1)
+ return -1;
+ if (strm->avail_in == 0)
+ return 0;
+ }
+
+ /* look for gzip magic bytes -- if there, do gzip decoding (note: there is
+ a logical dilemma here when considering the case of a partially written
+ gzip file, to wit, if a single 31 byte is written, then we cannot tell
+ whether this is a single-byte file, or just a partially written gzip
+ file -- for here we assume that if a gzip file is being written, then
+ the header will be written in a single operation, so that reading a
+ single byte is sufficient indication that it is not a gzip file) */
+ if (strm->avail_in > 1 &&
+ strm->next_in[0] == 31 && strm->next_in[1] == 139) {
+ inflateReset(strm);
+ state->how = GZIP;
+ state->direct = 0;
+ return 0;
+ }
+
+ /* no gzip header -- if we were decoding gzip before, then this is trailing
+ garbage. Ignore the trailing garbage and finish. */
+ if (state->direct == 0) {
+ strm->avail_in = 0;
+ state->eof = 1;
+ state->x.have = 0;
+ return 0;
+ }
+
+ /* doing raw i/o, copy any leftover input to output -- this assumes that
+ the output buffer is larger than the input buffer, which also assures
+ space for gzungetc() */
+ state->x.next = state->out;
+ memcpy(state->x.next, strm->next_in, strm->avail_in);
+ state->x.have = strm->avail_in;
+ strm->avail_in = 0;
+ state->how = COPY;
+ state->direct = 1;
+ return 0;
+}
+
+/* Decompress from input to the provided next_out and avail_out in the state.
+ On return, state->x.have and state->x.next point to the just decompressed
+ data. If the gzip stream completes, state->how is reset to LOOK to look for
+ the next gzip stream or raw data, once state->x.have is depleted. Returns 0
+ on success, -1 on failure. */
+local int gz_decomp(gz_statep state) {
+ int ret = Z_OK;
+ unsigned had;
+ z_streamp strm = &(state->strm);
+
+ /* fill output buffer up to end of deflate stream */
+ had = strm->avail_out;
+ do {
+ /* get more input for inflate() */
+ if (strm->avail_in == 0 && gz_avail(state) == -1)
+ return -1;
+ if (strm->avail_in == 0) {
+ gz_error(state, Z_BUF_ERROR, "unexpected end of file");
+ break;
+ }
+
+ /* decompress and handle errors */
+ ret = inflate(strm, Z_NO_FLUSH);
+ if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
+ gz_error(state, Z_STREAM_ERROR,
+ "internal error: inflate stream corrupt");
+ return -1;
+ }
+ if (ret == Z_MEM_ERROR) {
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+ if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
+ gz_error(state, Z_DATA_ERROR,
+ strm->msg == NULL ? "compressed data error" : strm->msg);
+ return -1;
+ }
+ } while (strm->avail_out && ret != Z_STREAM_END);
+
+ /* update available output */
+ state->x.have = had - strm->avail_out;
+ state->x.next = strm->next_out - state->x.have;
+
+ /* if the gzip stream completed successfully, look for another */
+ if (ret == Z_STREAM_END)
+ state->how = LOOK;
+
+ /* good decompression */
+ return 0;
+}
+
+/* Fetch data and put it in the output buffer. Assumes state->x.have is 0.
+ Data is either copied from the input file or decompressed from the input
+ file depending on state->how. If state->how is LOOK, then a gzip header is
+ looked for to determine whether to copy or decompress. Returns -1 on error,
+ otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the
+ end of the input file has been reached and all data has been processed. */
+local int gz_fetch(gz_statep state) {
+ z_streamp strm = &(state->strm);
+
+ do {
+ switch(state->how) {
+ case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */
+ if (gz_look(state) == -1)
+ return -1;
+ if (state->how == LOOK)
+ return 0;
+ break;
+ case COPY: /* -> COPY */
+ if (gz_load(state, state->out, state->size << 1, &(state->x.have))
+ == -1)
+ return -1;
+ state->x.next = state->out;
+ return 0;
+ case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */
+ strm->avail_out = state->size << 1;
+ strm->next_out = state->out;
+ if (gz_decomp(state) == -1)
+ return -1;
+ }
+ } while (state->x.have == 0 && (!state->eof || strm->avail_in));
+ return 0;
+}
+
+/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
+local int gz_skip(gz_statep state, z_off64_t len) {
+ unsigned n;
+
+ /* skip over len bytes or reach end-of-file, whichever comes first */
+ while (len)
+ /* skip over whatever is in output buffer */
+ if (state->x.have) {
+ n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
+ (unsigned)len : state->x.have;
+ state->x.have -= n;
+ state->x.next += n;
+ state->x.pos += n;
+ len -= n;
+ }
+
+ /* output buffer empty -- return if we're at the end of the input */
+ else if (state->eof && state->strm.avail_in == 0)
+ break;
+
+ /* need more data to skip -- load up output buffer */
+ else {
+ /* get more output, looking for header if required */
+ if (gz_fetch(state) == -1)
+ return -1;
+ }
+ return 0;
+}
+
+/* Read len bytes into buf from file, or less than len up to the end of the
+ input. Return the number of bytes read. If zero is returned, either the
+ end of file was reached, or there was an error. state->err must be
+ consulted in that case to determine which. */
+local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) {
+ z_size_t got;
+ unsigned n;
+
+ /* if len is zero, avoid unnecessary operations */
+ if (len == 0)
+ return 0;
+
+ /* process a skip request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_skip(state, state->skip) == -1)
+ return 0;
+ }
+
+ /* get len bytes to buf, or less than len if at the end */
+ got = 0;
+ do {
+ /* set n to the maximum amount of len that fits in an unsigned int */
+ n = (unsigned)-1;
+ if (n > len)
+ n = (unsigned)len;
+
+ /* first just try copying data from the output buffer */
+ if (state->x.have) {
+ if (state->x.have < n)
+ n = state->x.have;
+ memcpy(buf, state->x.next, n);
+ state->x.next += n;
+ state->x.have -= n;
+ }
+
+ /* output buffer empty -- return if we're at the end of the input */
+ else if (state->eof && state->strm.avail_in == 0) {
+ state->past = 1; /* tried to read past end */
+ break;
+ }
+
+ /* need output data -- for small len or new stream load up our output
+ buffer */
+ else if (state->how == LOOK || n < (state->size << 1)) {
+ /* get more output, looking for header if required */
+ if (gz_fetch(state) == -1)
+ return 0;
+ continue; /* no progress yet -- go back to copy above */
+ /* the copy above assures that we will leave with space in the
+ output buffer, allowing at least one gzungetc() to succeed */
+ }
+
+ /* large len -- read directly into user buffer */
+ else if (state->how == COPY) { /* read directly */
+ if (gz_load(state, (unsigned char *)buf, n, &n) == -1)
+ return 0;
+ }
+
+ /* large len -- decompress directly into user buffer */
+ else { /* state->how == GZIP */
+ state->strm.avail_out = n;
+ state->strm.next_out = (unsigned char *)buf;
+ if (gz_decomp(state) == -1)
+ return 0;
+ n = state->x.have;
+ state->x.have = 0;
+ }
+
+ /* update progress */
+ len -= n;
+ buf = (char *)buf + n;
+ got += n;
+ state->x.pos += n;
+ } while (len);
+
+ /* return number of bytes read into user buffer */
+ return got;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) {
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return -1;
+
+ /* since an int is returned, make sure len fits in one, otherwise return
+ with an error (this avoids a flaw in the interface) */
+ if ((int)len < 0) {
+ gz_error(state, Z_STREAM_ERROR, "request does not fit in an int");
+ return -1;
+ }
+
+ /* read len or fewer bytes to buf */
+ len = (unsigned)gz_read(state, buf, len);
+
+ /* check for an error */
+ if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
+ return -1;
+
+ /* return the number of bytes read (this is assured to fit in an int) */
+ return (int)len;
+}
+
+/* -- see zlib.h -- */
+z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file) {
+ z_size_t len;
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return 0;
+
+ /* compute bytes to read -- error on overflow */
+ len = nitems * size;
+ if (size && len / size != nitems) {
+ gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
+ return 0;
+ }
+
+ /* read len or fewer bytes to buf, return the number of full items read */
+ return len ? gz_read(state, buf, len) / size : 0;
+}
+
+/* -- see zlib.h -- */
+#ifdef Z_PREFIX_SET
+# undef z_gzgetc
+#else
+# undef gzgetc
+#endif
+int ZEXPORT gzgetc(gzFile file) {
+ unsigned char buf[1];
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return -1;
+
+ /* try output buffer (no need to check for skip request) */
+ if (state->x.have) {
+ state->x.have--;
+ state->x.pos++;
+ return *(state->x.next)++;
+ }
+
+ /* nothing there -- try gz_read() */
+ return gz_read(state, buf, 1) < 1 ? -1 : buf[0];
+}
+
+int ZEXPORT gzgetc_(gzFile file) {
+ return gzgetc(file);
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzungetc(int c, gzFile file) {
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* in case this was just opened, set up the input buffer */
+ if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
+ (void)gz_look(state);
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return -1;
+
+ /* process a skip request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_skip(state, state->skip) == -1)
+ return -1;
+ }
+
+ /* can't push EOF */
+ if (c < 0)
+ return -1;
+
+ /* if output buffer empty, put byte at end (allows more pushing) */
+ if (state->x.have == 0) {
+ state->x.have = 1;
+ state->x.next = state->out + (state->size << 1) - 1;
+ state->x.next[0] = (unsigned char)c;
+ state->x.pos--;
+ state->past = 0;
+ return c;
+ }
+
+ /* if no room, give up (must have already done a gzungetc()) */
+ if (state->x.have == (state->size << 1)) {
+ gz_error(state, Z_DATA_ERROR, "out of room to push characters");
+ return -1;
+ }
+
+ /* slide output data if needed and insert byte before existing data */
+ if (state->x.next == state->out) {
+ unsigned char *src = state->out + state->x.have;
+ unsigned char *dest = state->out + (state->size << 1);
+ while (src > state->out)
+ *--dest = *--src;
+ state->x.next = dest;
+ }
+ state->x.have++;
+ state->x.next--;
+ state->x.next[0] = (unsigned char)c;
+ state->x.pos--;
+ state->past = 0;
+ return c;
+}
+
+/* -- see zlib.h -- */
+char * ZEXPORT gzgets(gzFile file, char *buf, int len) {
+ unsigned left, n;
+ char *str;
+ unsigned char *eol;
+ gz_statep state;
+
+ /* check parameters and get internal structure */
+ if (file == NULL || buf == NULL || len < 1)
+ return NULL;
+ state = (gz_statep)file;
+
+ /* check that we're reading and that there's no (serious) error */
+ if (state->mode != GZ_READ ||
+ (state->err != Z_OK && state->err != Z_BUF_ERROR))
+ return NULL;
+
+ /* process a skip request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_skip(state, state->skip) == -1)
+ return NULL;
+ }
+
+ /* copy output bytes up to new line or len - 1, whichever comes first --
+ append a terminating zero to the string (we don't check for a zero in
+ the contents, let the user worry about that) */
+ str = buf;
+ left = (unsigned)len - 1;
+ if (left) do {
+ /* assure that something is in the output buffer */
+ if (state->x.have == 0 && gz_fetch(state) == -1)
+ return NULL; /* error */
+ if (state->x.have == 0) { /* end of file */
+ state->past = 1; /* read past end */
+ break; /* return what we have */
+ }
+
+ /* look for end-of-line in current output buffer */
+ n = state->x.have > left ? left : state->x.have;
+ eol = (unsigned char *)memchr(state->x.next, '\n', n);
+ if (eol != NULL)
+ n = (unsigned)(eol - state->x.next) + 1;
+
+ /* copy through end-of-line, or remainder if not found */
+ memcpy(buf, state->x.next, n);
+ state->x.have -= n;
+ state->x.next += n;
+ state->x.pos += n;
+ left -= n;
+ buf += n;
+ } while (left && eol == NULL);
+
+ /* return terminated string, or if nothing, end of file */
+ if (buf == str)
+ return NULL;
+ buf[0] = 0;
+ return str;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzdirect(gzFile file) {
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+
+ /* if the state is not known, but we can find out, then do so (this is
+ mainly for right after a gzopen() or gzdopen()) */
+ if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
+ (void)gz_look(state);
+
+ /* return 1 if transparent, 0 if processing a gzip stream */
+ return state->direct;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzclose_r(gzFile file) {
+ int ret, err;
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+
+ /* check that we're reading */
+ if (state->mode != GZ_READ)
+ return Z_STREAM_ERROR;
+
+ /* free memory and close file */
+ if (state->size) {
+ inflateEnd(&(state->strm));
+ free(state->out);
+ free(state->in);
+ }
+ err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
+ gz_error(state, Z_OK, NULL);
+ free(state->path);
+ ret = close(state->fd);
+ free(state);
+ return ret ? Z_ERRNO : err;
+}
diff --git a/lib/zlib/gzwrite.c b/lib/zlib/gzwrite.c
new file mode 100644
index 0000000..435b462
--- /dev/null
+++ b/lib/zlib/gzwrite.c
@@ -0,0 +1,631 @@
+/* gzwrite.c -- zlib functions for writing gzip files
+ * Copyright (C) 2004-2019 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "gzguts.h"
+
+/* Initialize state for writing a gzip file. Mark initialization by setting
+ state->size to non-zero. Return -1 on a memory allocation failure, or 0 on
+ success. */
+local int gz_init(gz_statep state) {
+ int ret;
+ z_streamp strm = &(state->strm);
+
+ /* allocate input buffer (double size for gzprintf) */
+ state->in = (unsigned char *)malloc(state->want << 1);
+ if (state->in == NULL) {
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+
+ /* only need output buffer and deflate state if compressing */
+ if (!state->direct) {
+ /* allocate output buffer */
+ state->out = (unsigned char *)malloc(state->want);
+ if (state->out == NULL) {
+ free(state->in);
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+
+ /* allocate deflate memory, set up for gzip compression */
+ strm->zalloc = Z_NULL;
+ strm->zfree = Z_NULL;
+ strm->opaque = Z_NULL;
+ ret = deflateInit2(strm, state->level, Z_DEFLATED,
+ MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
+ if (ret != Z_OK) {
+ free(state->out);
+ free(state->in);
+ gz_error(state, Z_MEM_ERROR, "out of memory");
+ return -1;
+ }
+ strm->next_in = NULL;
+ }
+
+ /* mark state as initialized */
+ state->size = state->want;
+
+ /* initialize write buffer if compressing */
+ if (!state->direct) {
+ strm->avail_out = state->size;
+ strm->next_out = state->out;
+ state->x.next = strm->next_out;
+ }
+ return 0;
+}
+
+/* Compress whatever is at avail_in and next_in and write to the output file.
+ Return -1 if there is an error writing to the output file or if gz_init()
+ fails to allocate memory, otherwise 0. flush is assumed to be a valid
+ deflate() flush value. If flush is Z_FINISH, then the deflate() state is
+ reset to start a new gzip stream. If gz->direct is true, then simply write
+ to the output file without compressing, and ignore flush. */
+local int gz_comp(gz_statep state, int flush) {
+ int ret, writ;
+ unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
+ z_streamp strm = &(state->strm);
+
+ /* allocate memory if this is the first time through */
+ if (state->size == 0 && gz_init(state) == -1)
+ return -1;
+
+ /* write directly if requested */
+ if (state->direct) {
+ while (strm->avail_in) {
+ put = strm->avail_in > max ? max : strm->avail_in;
+ writ = write(state->fd, strm->next_in, put);
+ if (writ < 0) {
+ gz_error(state, Z_ERRNO, zstrerror());
+ return -1;
+ }
+ strm->avail_in -= (unsigned)writ;
+ strm->next_in += writ;
+ }
+ return 0;
+ }
+
+ /* check for a pending reset */
+ if (state->reset) {
+ /* don't start a new gzip member unless there is data to write */
+ if (strm->avail_in == 0)
+ return 0;
+ deflateReset(strm);
+ state->reset = 0;
+ }
+
+ /* run deflate() on provided input until it produces no more output */
+ ret = Z_OK;
+ do {
+ /* write out current buffer contents if full, or if flushing, but if
+ doing Z_FINISH then don't write until we get to Z_STREAM_END */
+ if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
+ (flush != Z_FINISH || ret == Z_STREAM_END))) {
+ while (strm->next_out > state->x.next) {
+ put = strm->next_out - state->x.next > (int)max ? max :
+ (unsigned)(strm->next_out - state->x.next);
+ writ = write(state->fd, state->x.next, put);
+ if (writ < 0) {
+ gz_error(state, Z_ERRNO, zstrerror());
+ return -1;
+ }
+ state->x.next += writ;
+ }
+ if (strm->avail_out == 0) {
+ strm->avail_out = state->size;
+ strm->next_out = state->out;
+ state->x.next = state->out;
+ }
+ }
+
+ /* compress */
+ have = strm->avail_out;
+ ret = deflate(strm, flush);
+ if (ret == Z_STREAM_ERROR) {
+ gz_error(state, Z_STREAM_ERROR,
+ "internal error: deflate stream corrupt");
+ return -1;
+ }
+ have -= strm->avail_out;
+ } while (have);
+
+ /* if that completed a deflate stream, allow another to start */
+ if (flush == Z_FINISH)
+ state->reset = 1;
+
+ /* all done, no errors */
+ return 0;
+}
+
+/* Compress len zeros to output. Return -1 on a write error or memory
+ allocation failure by gz_comp(), or 0 on success. */
+local int gz_zero(gz_statep state, z_off64_t len) {
+ int first;
+ unsigned n;
+ z_streamp strm = &(state->strm);
+
+ /* consume whatever's left in the input buffer */
+ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
+ return -1;
+
+ /* compress len zeros (len guaranteed > 0) */
+ first = 1;
+ while (len) {
+ n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
+ (unsigned)len : state->size;
+ if (first) {
+ memset(state->in, 0, n);
+ first = 0;
+ }
+ strm->avail_in = n;
+ strm->next_in = state->in;
+ state->x.pos += n;
+ if (gz_comp(state, Z_NO_FLUSH) == -1)
+ return -1;
+ len -= n;
+ }
+ return 0;
+}
+
+/* Write len bytes from buf to file. Return the number of bytes written. If
+ the returned value is less than len, then there was an error. */
+local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
+ z_size_t put = len;
+
+ /* if len is zero, avoid unnecessary operations */
+ if (len == 0)
+ return 0;
+
+ /* allocate memory if this is the first time through */
+ if (state->size == 0 && gz_init(state) == -1)
+ return 0;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return 0;
+ }
+
+ /* for small len, copy to input buffer, otherwise compress directly */
+ if (len < state->size) {
+ /* copy to input buffer, compress when full */
+ do {
+ unsigned have, copy;
+
+ if (state->strm.avail_in == 0)
+ state->strm.next_in = state->in;
+ have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
+ state->in);
+ copy = state->size - have;
+ if (copy > len)
+ copy = (unsigned)len;
+ memcpy(state->in + have, buf, copy);
+ state->strm.avail_in += copy;
+ state->x.pos += copy;
+ buf = (const char *)buf + copy;
+ len -= copy;
+ if (len && gz_comp(state, Z_NO_FLUSH) == -1)
+ return 0;
+ } while (len);
+ }
+ else {
+ /* consume whatever's left in the input buffer */
+ if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
+ return 0;
+
+ /* directly compress user buffer to file */
+ state->strm.next_in = (z_const Bytef *)buf;
+ do {
+ unsigned n = (unsigned)-1;
+ if (n > len)
+ n = (unsigned)len;
+ state->strm.avail_in = n;
+ state->x.pos += n;
+ if (gz_comp(state, Z_NO_FLUSH) == -1)
+ return 0;
+ len -= n;
+ } while (len);
+ }
+
+ /* input was all buffered or compressed */
+ return put;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return 0;
+
+ /* since an int is returned, make sure len fits in one, otherwise return
+ with an error (this avoids a flaw in the interface) */
+ if ((int)len < 0) {
+ gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
+ return 0;
+ }
+
+ /* write len bytes from buf (the return value will fit in an int) */
+ return (int)gz_write(state, buf, len);
+}
+
+/* -- see zlib.h -- */
+z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems,
+ gzFile file) {
+ z_size_t len;
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return 0;
+ state = (gz_statep)file;
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return 0;
+
+ /* compute bytes to read -- error on overflow */
+ len = nitems * size;
+ if (size && len / size != nitems) {
+ gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
+ return 0;
+ }
+
+ /* write len bytes to buf, return the number of full items written */
+ return len ? gz_write(state, buf, len) / size : 0;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzputc(gzFile file, int c) {
+ unsigned have;
+ unsigned char buf[1];
+ gz_statep state;
+ z_streamp strm;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return -1;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return -1;
+ }
+
+ /* try writing to input buffer for speed (state->size == 0 if buffer not
+ initialized) */
+ if (state->size) {
+ if (strm->avail_in == 0)
+ strm->next_in = state->in;
+ have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
+ if (have < state->size) {
+ state->in[have] = (unsigned char)c;
+ strm->avail_in++;
+ state->x.pos++;
+ return c & 0xff;
+ }
+ }
+
+ /* no room in buffer or not initialized, use gz_write() */
+ buf[0] = (unsigned char)c;
+ if (gz_write(state, buf, 1) != 1)
+ return -1;
+ return c & 0xff;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzputs(gzFile file, const char *s) {
+ z_size_t len, put;
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return -1;
+ state = (gz_statep)file;
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return -1;
+
+ /* write string */
+ len = strlen(s);
+ if ((int)len < 0 || (unsigned)len != len) {
+ gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
+ return -1;
+ }
+ put = gz_write(state, s, len);
+ return put < len ? -1 : (int)len;
+}
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#include <stdarg.h>
+
+/* -- see zlib.h -- */
+int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
+ int len;
+ unsigned left;
+ char *next;
+ gz_statep state;
+ z_streamp strm;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return Z_STREAM_ERROR;
+
+ /* make sure we have some buffer space */
+ if (state->size == 0 && gz_init(state) == -1)
+ return state->err;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return state->err;
+ }
+
+ /* do the printf() into the input buffer, put length in len -- the input
+ buffer is double-sized just for this function, so there is guaranteed to
+ be state->size bytes available after the current contents */
+ if (strm->avail_in == 0)
+ strm->next_in = state->in;
+ next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
+ next[state->size - 1] = 0;
+#ifdef NO_vsnprintf
+# ifdef HAS_vsprintf_void
+ (void)vsprintf(next, format, va);
+ for (len = 0; len < state->size; len++)
+ if (next[len] == 0) break;
+# else
+ len = vsprintf(next, format, va);
+# endif
+#else
+# ifdef HAS_vsnprintf_void
+ (void)vsnprintf(next, state->size, format, va);
+ len = strlen(next);
+# else
+ len = vsnprintf(next, state->size, format, va);
+# endif
+#endif
+
+ /* check that printf() results fit in buffer */
+ if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
+ return 0;
+
+ /* update buffer and position, compress first half if past that */
+ strm->avail_in += (unsigned)len;
+ state->x.pos += len;
+ if (strm->avail_in >= state->size) {
+ left = strm->avail_in - state->size;
+ strm->avail_in = state->size;
+ if (gz_comp(state, Z_NO_FLUSH) == -1)
+ return state->err;
+ memmove(state->in, state->in + state->size, left);
+ strm->next_in = state->in;
+ strm->avail_in = left;
+ }
+ return len;
+}
+
+int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
+ va_list va;
+ int ret;
+
+ va_start(va, format);
+ ret = gzvprintf(file, format, va);
+ va_end(va);
+ return ret;
+}
+
+#else /* !STDC && !Z_HAVE_STDARG_H */
+
+/* -- see zlib.h -- */
+int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,
+ int a4, int a5, int a6, int a7, int a8, int a9, int a10,
+ int a11, int a12, int a13, int a14, int a15, int a16,
+ int a17, int a18, int a19, int a20) {
+ unsigned len, left;
+ char *next;
+ gz_statep state;
+ z_streamp strm;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that can really pass pointer in ints */
+ if (sizeof(int) != sizeof(void *))
+ return Z_STREAM_ERROR;
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return Z_STREAM_ERROR;
+
+ /* make sure we have some buffer space */
+ if (state->size == 0 && gz_init(state) == -1)
+ return state->error;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return state->error;
+ }
+
+ /* do the printf() into the input buffer, put length in len -- the input
+ buffer is double-sized just for this function, so there is guaranteed to
+ be state->size bytes available after the current contents */
+ if (strm->avail_in == 0)
+ strm->next_in = state->in;
+ next = (char *)(strm->next_in + strm->avail_in);
+ next[state->size - 1] = 0;
+#ifdef NO_snprintf
+# ifdef HAS_sprintf_void
+ sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
+ a13, a14, a15, a16, a17, a18, a19, a20);
+ for (len = 0; len < size; len++)
+ if (next[len] == 0)
+ break;
+# else
+ len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
+ a12, a13, a14, a15, a16, a17, a18, a19, a20);
+# endif
+#else
+# ifdef HAS_snprintf_void
+ snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+ len = strlen(next);
+# else
+ len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
+ a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+# endif
+#endif
+
+ /* check that printf() results fit in buffer */
+ if (len == 0 || len >= state->size || next[state->size - 1] != 0)
+ return 0;
+
+ /* update buffer and position, compress first half if past that */
+ strm->avail_in += len;
+ state->x.pos += len;
+ if (strm->avail_in >= state->size) {
+ left = strm->avail_in - state->size;
+ strm->avail_in = state->size;
+ if (gz_comp(state, Z_NO_FLUSH) == -1)
+ return state->err;
+ memmove(state->in, state->in + state->size, left);
+ strm->next_in = state->in;
+ strm->avail_in = left;
+ }
+ return (int)len;
+}
+
+#endif
+
+/* -- see zlib.h -- */
+int ZEXPORT gzflush(gzFile file, int flush) {
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK)
+ return Z_STREAM_ERROR;
+
+ /* check flush parameter */
+ if (flush < 0 || flush > Z_FINISH)
+ return Z_STREAM_ERROR;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return state->err;
+ }
+
+ /* compress remaining data with requested flush */
+ (void)gz_comp(state, flush);
+ return state->err;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
+ gz_statep state;
+ z_streamp strm;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+ strm = &(state->strm);
+
+ /* check that we're writing and that there's no error */
+ if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct)
+ return Z_STREAM_ERROR;
+
+ /* if no change is requested, then do nothing */
+ if (level == state->level && strategy == state->strategy)
+ return Z_OK;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ return state->err;
+ }
+
+ /* change compression parameters for subsequent input */
+ if (state->size) {
+ /* flush previous input with previous parameters before changing */
+ if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
+ return state->err;
+ deflateParams(strm, level, strategy);
+ }
+ state->level = level;
+ state->strategy = strategy;
+ return Z_OK;
+}
+
+/* -- see zlib.h -- */
+int ZEXPORT gzclose_w(gzFile file) {
+ int ret = Z_OK;
+ gz_statep state;
+
+ /* get internal structure */
+ if (file == NULL)
+ return Z_STREAM_ERROR;
+ state = (gz_statep)file;
+
+ /* check that we're writing */
+ if (state->mode != GZ_WRITE)
+ return Z_STREAM_ERROR;
+
+ /* check for seek request */
+ if (state->seek) {
+ state->seek = 0;
+ if (gz_zero(state, state->skip) == -1)
+ ret = state->err;
+ }
+
+ /* flush, free memory, and close file */
+ if (gz_comp(state, Z_FINISH) == -1)
+ ret = state->err;
+ if (state->size) {
+ if (!state->direct) {
+ (void)deflateEnd(&(state->strm));
+ free(state->out);
+ }
+ free(state->in);
+ }
+ gz_error(state, Z_OK, NULL);
+ free(state->path);
+ if (close(state->fd) == -1)
+ ret = Z_ERRNO;
+ free(state);
+ return ret;
+}
diff --git a/lib/zlib/infback.c b/lib/zlib/infback.c
new file mode 100644
index 0000000..c68ef76
--- /dev/null
+++ b/lib/zlib/infback.c
@@ -0,0 +1,628 @@
+/* infback.c -- inflate using a call-back interface
+ * Copyright (C) 1995-2022 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ This code is largely copied from inflate.c. Normally either infback.o or
+ inflate.o would be linked into an application--not both. The interface
+ with inffast.c is retained so that optimized assembler-coded versions of
+ inflate_fast() can be used with either inflate.c or infback.c.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+/*
+ strm provides memory allocation functions in zalloc and zfree, or
+ Z_NULL to use the library memory allocation functions.
+
+ windowBits is in the range 8..15, and window is a user-supplied
+ window and output buffer that is 2**windowBits bytes.
+ */
+int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits,
+ unsigned char FAR *window, const char *version,
+ int stream_size) {
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL || window == Z_NULL ||
+ windowBits < 8 || windowBits > 15)
+ return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+#endif
+ }
+ if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zfree = zcfree;
+#endif
+ state = (struct inflate_state FAR *)ZALLOC(strm, 1,
+ sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ state->dmax = 32768U;
+ state->wbits = (uInt)windowBits;
+ state->wsize = 1U << windowBits;
+ state->window = window;
+ state->wnext = 0;
+ state->whave = 0;
+ state->sane = 1;
+ return Z_OK;
+}
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables(struct inflate_state FAR *state) {
+#ifdef BUILDFIXED
+ static int virgin = 1;
+ static code *lenfix, *distfix;
+ static code fixed[544];
+
+ /* build fixed huffman tables if first call (may not be thread safe) */
+ if (virgin) {
+ unsigned sym, bits;
+ static code *next;
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) state->lens[sym++] = 8;
+ while (sym < 256) state->lens[sym++] = 9;
+ while (sym < 280) state->lens[sym++] = 7;
+ while (sym < 288) state->lens[sym++] = 8;
+ next = fixed;
+ lenfix = next;
+ bits = 9;
+ inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) state->lens[sym++] = 5;
+ distfix = next;
+ bits = 5;
+ inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+ /* do this just once */
+ virgin = 0;
+ }
+#else /* !BUILDFIXED */
+# include "inffixed.h"
+#endif /* BUILDFIXED */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+/* Macros for inflateBack(): */
+
+/* Load returned state from inflate_fast() */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Set state from registers for inflate_fast() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Assure that some input is available. If input is requested, but denied,
+ then return a Z_BUF_ERROR from inflateBack(). */
+#define PULL() \
+ do { \
+ if (have == 0) { \
+ have = in(in_desc, &next); \
+ if (have == 0) { \
+ next = Z_NULL; \
+ ret = Z_BUF_ERROR; \
+ goto inf_leave; \
+ } \
+ } \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflateBack()
+ with an error if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ PULL(); \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflateBack() with
+ an error. */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/* Assure that some output space is available, by writing out the window
+ if it's full. If the write fails, return from inflateBack() with a
+ Z_BUF_ERROR. */
+#define ROOM() \
+ do { \
+ if (left == 0) { \
+ put = state->window; \
+ left = state->wsize; \
+ state->whave = left; \
+ if (out(out_desc, put, left)) { \
+ ret = Z_BUF_ERROR; \
+ goto inf_leave; \
+ } \
+ } \
+ } while (0)
+
+/*
+ strm provides the memory allocation functions and window buffer on input,
+ and provides information on the unused input on return. For Z_DATA_ERROR
+ returns, strm will also provide an error message.
+
+ in() and out() are the call-back input and output functions. When
+ inflateBack() needs more input, it calls in(). When inflateBack() has
+ filled the window with output, or when it completes with data in the
+ window, it calls out() to write out the data. The application must not
+ change the provided input until in() is called again or inflateBack()
+ returns. The application must not change the window/output buffer until
+ inflateBack() returns.
+
+ in() and out() are called with a descriptor parameter provided in the
+ inflateBack() call. This parameter can be a structure that provides the
+ information required to do the read or write, as well as accumulated
+ information on the input and output such as totals and check values.
+
+ in() should return zero on failure. out() should return non-zero on
+ failure. If either in() or out() fails, than inflateBack() returns a
+ Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
+ was in() or out() that caused in the error. Otherwise, inflateBack()
+ returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
+ error, or Z_MEM_ERROR if it could not allocate memory for the state.
+ inflateBack() can also return Z_STREAM_ERROR if the input parameters
+ are not correct, i.e. strm is Z_NULL or the state was not initialized.
+ */
+int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc) {
+ struct inflate_state FAR *state;
+ z_const unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code here; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ /* Check that the strm exists and that the state was initialized */
+ if (strm == Z_NULL || strm->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* Reset the state */
+ strm->msg = Z_NULL;
+ state->mode = TYPE;
+ state->last = 0;
+ state->whave = 0;
+ next = strm->next_in;
+ have = next != Z_NULL ? strm->avail_in : 0;
+ hold = 0;
+ bits = 0;
+ put = state->window;
+ left = state->wsize;
+
+ /* Inflate until end of block marked as last */
+ for (;;)
+ switch (state->mode) {
+ case TYPE:
+ /* determine and dispatch block type */
+ if (state->last) {
+ BYTEBITS();
+ state->mode = DONE;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN; /* decode codes */
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+
+ case STORED:
+ /* get and verify stored block length */
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+
+ /* copy stored block from input to output */
+ while (state->length != 0) {
+ copy = state->length;
+ PULL();
+ ROOM();
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+
+ case TABLE:
+ /* get dynamic table entries descriptor */
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+
+ /* get code length code lengths (not a typo) */
+ state->have = 0;
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+
+ /* get length and distance code code lengths */
+ state->have = 0;
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.val < 16) {
+ DROPBITS(here.bits);
+ state->lens[state->have++] = here.val;
+ }
+ else {
+ if (here.val == 16) {
+ NEEDBITS(here.bits + 2);
+ DROPBITS(here.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = (unsigned)(state->lens[state->have - 1]);
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (here.val == 17) {
+ NEEDBITS(here.bits + 3);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(here.bits + 7);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* check for end-of-block code (better have one) */
+ if (state->lens[256] == 0) {
+ strm->msg = (char *)"invalid code -- missing end-of-block";
+ state->mode = BAD;
+ break;
+ }
+
+ /* build code tables -- note: do not change the lenbits or distbits
+ values here (9 and 6) without reading the comments in inftrees.h
+ concerning the ENOUGH constants, which depend on those values */
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (code const FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN;
+ ZFALLTHROUGH;
+
+ case LEN:
+ /* use inflate_fast() if we have enough input and output */
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ if (state->whave < state->wsize)
+ state->whave = state->wsize - left;
+ inflate_fast(strm, state->wsize);
+ LOAD();
+ break;
+ }
+
+ /* get a literal, length, or end-of-block code */
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.op && (here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(here.bits);
+ state->length = (unsigned)here.val;
+
+ /* process literal */
+ if (here.op == 0) {
+ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", here.val));
+ ROOM();
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ }
+
+ /* process end of block */
+ if (here.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+
+ /* invalid code */
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+
+ /* length code -- get extra bits, if any */
+ state->extra = (unsigned)(here.op) & 15;
+ if (state->extra != 0) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+
+ /* get distance code */
+ for (;;) {
+ here = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(here.bits);
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)here.val;
+
+ /* get distance extra bits, if any */
+ state->extra = (unsigned)(here.op) & 15;
+ if (state->extra != 0) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ if (state->offset > state->wsize - (state->whave < state->wsize ?
+ left : 0)) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+
+ /* copy match from window to output */
+ do {
+ ROOM();
+ copy = state->wsize - state->offset;
+ if (copy < left) {
+ from = put + copy;
+ copy = left - copy;
+ }
+ else {
+ from = put - state->offset;
+ copy = left;
+ }
+ if (copy > state->length) copy = state->length;
+ state->length -= copy;
+ left -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ } while (state->length != 0);
+ break;
+
+ case DONE:
+ /* inflate stream terminated properly */
+ ret = Z_STREAM_END;
+ goto inf_leave;
+
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+
+ default:
+ /* can't happen, but makes compilers happy */
+ ret = Z_STREAM_ERROR;
+ goto inf_leave;
+ }
+
+ /* Write leftover output and return unused input */
+ inf_leave:
+ if (left < state->wsize) {
+ if (out(out_desc, state->window, state->wsize - left) &&
+ ret == Z_STREAM_END)
+ ret = Z_BUF_ERROR;
+ }
+ strm->next_in = next;
+ strm->avail_in = have;
+ return ret;
+}
+
+int ZEXPORT inflateBackEnd(z_streamp strm) {
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
diff --git a/lib/zlib/inffast.c b/lib/zlib/inffast.c
new file mode 100644
index 0000000..9354676
--- /dev/null
+++ b/lib/zlib/inffast.c
@@ -0,0 +1,320 @@
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2017 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef ASMINF
+# pragma message("Assembler code may have bugs -- use at your own risk")
+#else
+
+/*
+ Decode literal, length, and distance codes and write out the resulting
+ literal and match bytes until either not enough input or output is
+ available, an end-of-block is encountered, or a data error is encountered.
+ When large enough input and output buffers are supplied to inflate(), for
+ example, a 16K input buffer and a 64K output buffer, more than 95% of the
+ inflate execution time is spent in this routine.
+
+ Entry assumptions:
+
+ state->mode == LEN
+ strm->avail_in >= 6
+ strm->avail_out >= 258
+ start >= strm->avail_out
+ state->bits < 8
+
+ On return, state->mode is one of:
+
+ LEN -- ran out of enough output space or enough available input
+ TYPE -- reached end of block code, inflate() to interpret next block
+ BAD -- error in block data
+
+ Notes:
+
+ - The maximum input bits used by a length/distance pair is 15 bits for the
+ length code, 5 bits for the length extra, 15 bits for the distance code,
+ and 13 bits for the distance extra. This totals 48 bits, or six bytes.
+ Therefore if strm->avail_in >= 6, then there is enough input to avoid
+ checking for available input while decoding.
+
+ - The maximum bytes that a single length/distance pair can output is 258
+ bytes, which is the maximum length that can be coded. inflate_fast()
+ requires strm->avail_out >= 258 for each loop to avoid checking for
+ output space.
+ */
+void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
+ struct inflate_state FAR *state;
+ z_const unsigned char FAR *in; /* local strm->next_in */
+ z_const unsigned char FAR *last; /* have enough input while in < last */
+ unsigned char FAR *out; /* local strm->next_out */
+ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
+ unsigned char FAR *end; /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+ unsigned dmax; /* maximum distance from zlib header */
+#endif
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned wnext; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
+ unsigned long hold; /* local strm->hold */
+ unsigned bits; /* local strm->bits */
+ code const FAR *lcode; /* local strm->lencode */
+ code const FAR *dcode; /* local strm->distcode */
+ unsigned lmask; /* mask for first level of length codes */
+ unsigned dmask; /* mask for first level of distance codes */
+ code const *here; /* retrieved table entry */
+ unsigned op; /* code bits, operation, extra bits, or */
+ /* window position, window bytes to copy */
+ unsigned len; /* match length, unused bytes */
+ unsigned dist; /* match distance */
+ unsigned char FAR *from; /* where to copy match from */
+
+ /* copy state to local variables */
+ state = (struct inflate_state FAR *)strm->state;
+ in = strm->next_in;
+ last = in + (strm->avail_in - 5);
+ out = strm->next_out;
+ beg = out - (start - strm->avail_out);
+ end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+ dmax = state->dmax;
+#endif
+ wsize = state->wsize;
+ whave = state->whave;
+ wnext = state->wnext;
+ window = state->window;
+ hold = state->hold;
+ bits = state->bits;
+ lcode = state->lencode;
+ dcode = state->distcode;
+ lmask = (1U << state->lenbits) - 1;
+ dmask = (1U << state->distbits) - 1;
+
+ /* decode literals and length/distances until end-of-block or not enough
+ input data or output space */
+ do {
+ if (bits < 15) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ }
+ here = lcode + (hold & lmask);
+ dolen:
+ op = (unsigned)(here->bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(here->op);
+ if (op == 0) { /* literal */
+ Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", here->val));
+ *out++ = (unsigned char)(here->val);
+ }
+ else if (op & 16) { /* length base */
+ len = (unsigned)(here->val);
+ op &= 15; /* number of extra bits */
+ if (op) {
+ if (bits < op) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ }
+ len += (unsigned)hold & ((1U << op) - 1);
+ hold >>= op;
+ bits -= op;
+ }
+ Tracevv((stderr, "inflate: length %u\n", len));
+ if (bits < 15) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ }
+ here = dcode + (hold & dmask);
+ dodist:
+ op = (unsigned)(here->bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(here->op);
+ if (op & 16) { /* distance base */
+ dist = (unsigned)(here->val);
+ op &= 15; /* number of extra bits */
+ if (bits < op) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ if (bits < op) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ }
+ }
+ dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+ if (dist > dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ hold >>= op;
+ bits -= op;
+ Tracevv((stderr, "inflate: distance %u\n", dist));
+ op = (unsigned)(out - beg); /* max distance in output */
+ if (dist > op) { /* see if copy from window */
+ op = dist - op; /* distance back in window */
+ if (op > whave) {
+ if (state->sane) {
+ strm->msg =
+ (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ if (len <= op - whave) {
+ do {
+ *out++ = 0;
+ } while (--len);
+ continue;
+ }
+ len -= op - whave;
+ do {
+ *out++ = 0;
+ } while (--op > whave);
+ if (op == 0) {
+ from = out - dist;
+ do {
+ *out++ = *from++;
+ } while (--len);
+ continue;
+ }
+#endif
+ }
+ from = window;
+ if (wnext == 0) { /* very common case */
+ from += wsize - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ *out++ = *from++;
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ else if (wnext < op) { /* wrap around window */
+ from += wsize + wnext - op;
+ op -= wnext;
+ if (op < len) { /* some from end of window */
+ len -= op;
+ do {
+ *out++ = *from++;
+ } while (--op);
+ from = window;
+ if (wnext < len) { /* some from start of window */
+ op = wnext;
+ len -= op;
+ do {
+ *out++ = *from++;
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ }
+ else { /* contiguous in window */
+ from += wnext - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ *out++ = *from++;
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ while (len > 2) {
+ *out++ = *from++;
+ *out++ = *from++;
+ *out++ = *from++;
+ len -= 3;
+ }
+ if (len) {
+ *out++ = *from++;
+ if (len > 1)
+ *out++ = *from++;
+ }
+ }
+ else {
+ from = out - dist; /* copy direct from output */
+ do { /* minimum length is three */
+ *out++ = *from++;
+ *out++ = *from++;
+ *out++ = *from++;
+ len -= 3;
+ } while (len > 2);
+ if (len) {
+ *out++ = *from++;
+ if (len > 1)
+ *out++ = *from++;
+ }
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level distance code */
+ here = dcode + here->val + (hold & ((1U << op) - 1));
+ goto dodist;
+ }
+ else {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level length code */
+ here = lcode + here->val + (hold & ((1U << op) - 1));
+ goto dolen;
+ }
+ else if (op & 32) { /* end-of-block */
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ else {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ } while (in < last && out < end);
+
+ /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+ len = bits >> 3;
+ in -= len;
+ bits -= len << 3;
+ hold &= (1U << bits) - 1;
+
+ /* update state and return */
+ strm->next_in = in;
+ strm->next_out = out;
+ strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+ strm->avail_out = (unsigned)(out < end ?
+ 257 + (end - out) : 257 - (out - end));
+ state->hold = hold;
+ state->bits = bits;
+ return;
+}
+
+/*
+ inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+ - Using bit fields for code structure
+ - Different op definition to avoid & for extra bits (do & for table bits)
+ - Three separate decoding do-loops for direct, window, and wnext == 0
+ - Special case for distance > 1 copies to do overlapped load and store copy
+ - Explicit branch predictions (based on measured branch probabilities)
+ - Deferring match copy and interspersed it with decoding subsequent codes
+ - Swapping literal/length else
+ - Swapping window/direct else
+ - Larger unrolled copy loops (three is about right)
+ - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
diff --git a/lib/zlib/inffast.h b/lib/zlib/inffast.h
new file mode 100644
index 0000000..49c6d15
--- /dev/null
+++ b/lib/zlib/inffast.h
@@ -0,0 +1,11 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-2003, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start);
diff --git a/lib/zlib/inffixed.h b/lib/zlib/inffixed.h
new file mode 100644
index 0000000..d628327
--- /dev/null
+++ b/lib/zlib/inffixed.h
@@ -0,0 +1,94 @@
+ /* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by makefixed().
+ */
+
+ /* WARNING: this file should *not* be used by applications.
+ It is part of the implementation of this library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+ static const code lenfix[512] = {
+ {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+ {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+ {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+ {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+ {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+ {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+ {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+ {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+ {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+ {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+ {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+ {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+ {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+ {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+ {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+ {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+ {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+ {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+ {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+ {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+ {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+ {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+ {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+ {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+ {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+ {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+ {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+ {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+ {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+ {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+ {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+ {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+ {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+ {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+ {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+ {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+ {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+ {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+ {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+ {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+ {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+ {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+ {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+ {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+ {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+ {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+ {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+ {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+ {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+ {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+ {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+ {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+ {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+ {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+ {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+ {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+ {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+ {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+ {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+ {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+ {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+ {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+ {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+ {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+ {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+ {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+ {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+ {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+ {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+ {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+ {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+ {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+ {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+ {0,9,255}
+ };
+
+ static const code distfix[32] = {
+ {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+ {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+ {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+ {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+ {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+ {22,5,193},{64,5,0}
+ };
diff --git a/lib/zlib/inflate.c b/lib/zlib/inflate.c
new file mode 100644
index 0000000..ec11a97
--- /dev/null
+++ b/lib/zlib/inflate.c
@@ -0,0 +1,1525 @@
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2022 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * Change history:
+ *
+ * 1.2.beta0 24 Nov 2002
+ * - First version -- complete rewrite of inflate to simplify code, avoid
+ * creation of window when not needed, minimize use of window when it is
+ * needed, make inffast.c even faster, implement gzip decoding, and to
+ * improve code readability and style over the previous zlib inflate code
+ *
+ * 1.2.beta1 25 Nov 2002
+ * - Use pointers for available input and output checking in inffast.c
+ * - Remove input and output counters in inffast.c
+ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
+ * - Remove unnecessary second byte pull from length extra in inffast.c
+ * - Unroll direct copy to three copies per loop in inffast.c
+ *
+ * 1.2.beta2 4 Dec 2002
+ * - Change external routine names to reduce potential conflicts
+ * - Correct filename to inffixed.h for fixed tables in inflate.c
+ * - Make hbuf[] unsigned char to match parameter type in inflate.c
+ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
+ * to avoid negation problem on Alphas (64 bit) in inflate.c
+ *
+ * 1.2.beta3 22 Dec 2002
+ * - Add comments on state->bits assertion in inffast.c
+ * - Add comments on op field in inftrees.h
+ * - Fix bug in reuse of allocated window after inflateReset()
+ * - Remove bit fields--back to byte structure for speed
+ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
+ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
+ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
+ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
+ * - Use local copies of stream next and avail values, as well as local bit
+ * buffer and bit count in inflate()--for speed when inflate_fast() not used
+ *
+ * 1.2.beta4 1 Jan 2003
+ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
+ * - Move a comment on output buffer sizes from inffast.c to inflate.c
+ * - Add comments in inffast.c to introduce the inflate_fast() routine
+ * - Rearrange window copies in inflate_fast() for speed and simplification
+ * - Unroll last copy for window match in inflate_fast()
+ * - Use local copies of window variables in inflate_fast() for speed
+ * - Pull out common wnext == 0 case for speed in inflate_fast()
+ * - Make op and len in inflate_fast() unsigned for consistency
+ * - Add FAR to lcode and dcode declarations in inflate_fast()
+ * - Simplified bad distance check in inflate_fast()
+ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
+ * source file infback.c to provide a call-back interface to inflate for
+ * programs like gzip and unzip -- uses window as output buffer to avoid
+ * window copying
+ *
+ * 1.2.beta5 1 Jan 2003
+ * - Improved inflateBack() interface to allow the caller to provide initial
+ * input in strm.
+ * - Fixed stored blocks bug in inflateBack()
+ *
+ * 1.2.beta6 4 Jan 2003
+ * - Added comments in inffast.c on effectiveness of POSTINC
+ * - Typecasting all around to reduce compiler warnings
+ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
+ * make compilers happy
+ * - Changed type of window in inflateBackInit() to unsigned char *
+ *
+ * 1.2.beta7 27 Jan 2003
+ * - Changed many types to unsigned or unsigned short to avoid warnings
+ * - Added inflateCopy() function
+ *
+ * 1.2.0 9 Mar 2003
+ * - Changed inflateBack() interface to provide separate opaque descriptors
+ * for the in() and out() functions
+ * - Changed inflateBack() argument and in_func typedef to swap the length
+ * and buffer address return values for the input function
+ * - Check next_in and next_out for Z_NULL on entry to inflate()
+ *
+ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef MAKEFIXED
+# ifndef BUILDFIXED
+# define BUILDFIXED
+# endif
+#endif
+
+local int inflateStateCheck(z_streamp strm) {
+ struct inflate_state FAR *state;
+ if (strm == Z_NULL ||
+ strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
+ return 1;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state == Z_NULL || state->strm != strm ||
+ state->mode < HEAD || state->mode > SYNC)
+ return 1;
+ return 0;
+}
+
+int ZEXPORT inflateResetKeep(z_streamp strm) {
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ strm->total_in = strm->total_out = state->total = 0;
+ strm->msg = Z_NULL;
+ if (state->wrap) /* to support ill-conceived Java test suite */
+ strm->adler = state->wrap & 1;
+ state->mode = HEAD;
+ state->last = 0;
+ state->havedict = 0;
+ state->flags = -1;
+ state->dmax = 32768U;
+ state->head = Z_NULL;
+ state->hold = 0;
+ state->bits = 0;
+ state->lencode = state->distcode = state->next = state->codes;
+ state->sane = 1;
+ state->back = -1;
+ Tracev((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateReset(z_streamp strm) {
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ state->wsize = 0;
+ state->whave = 0;
+ state->wnext = 0;
+ return inflateResetKeep(strm);
+}
+
+int ZEXPORT inflateReset2(z_streamp strm, int windowBits) {
+ int wrap;
+ struct inflate_state FAR *state;
+
+ /* get the state */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* extract wrap request from windowBits parameter */
+ if (windowBits < 0) {
+ if (windowBits < -15)
+ return Z_STREAM_ERROR;
+ wrap = 0;
+ windowBits = -windowBits;
+ }
+ else {
+ wrap = (windowBits >> 4) + 5;
+#ifdef GUNZIP
+ if (windowBits < 48)
+ windowBits &= 15;
+#endif
+ }
+
+ /* set number of window bits, free window if different */
+ if (windowBits && (windowBits < 8 || windowBits > 15))
+ return Z_STREAM_ERROR;
+ if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
+ ZFREE(strm, state->window);
+ state->window = Z_NULL;
+ }
+
+ /* update state and reset the rest of it */
+ state->wrap = wrap;
+ state->wbits = (unsigned)windowBits;
+ return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit2_(z_streamp strm, int windowBits,
+ const char *version, int stream_size) {
+ int ret;
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+#endif
+ }
+ if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zfree = zcfree;
+#endif
+ state = (struct inflate_state FAR *)
+ ZALLOC(strm, 1, sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ state->strm = strm;
+ state->window = Z_NULL;
+ state->mode = HEAD; /* to pass state test in inflateReset2() */
+ ret = inflateReset2(strm, windowBits);
+ if (ret != Z_OK) {
+ ZFREE(strm, state);
+ strm->state = Z_NULL;
+ }
+ return ret;
+}
+
+int ZEXPORT inflateInit_(z_streamp strm, const char *version,
+ int stream_size) {
+ return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) {
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ if (bits == 0)
+ return Z_OK;
+ state = (struct inflate_state FAR *)strm->state;
+ if (bits < 0) {
+ state->hold = 0;
+ state->bits = 0;
+ return Z_OK;
+ }
+ if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;
+ value &= (1L << bits) - 1;
+ state->hold += (unsigned)value << state->bits;
+ state->bits += (uInt)bits;
+ return Z_OK;
+}
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables(struct inflate_state FAR *state) {
+#ifdef BUILDFIXED
+ static int virgin = 1;
+ static code *lenfix, *distfix;
+ static code fixed[544];
+
+ /* build fixed huffman tables if first call (may not be thread safe) */
+ if (virgin) {
+ unsigned sym, bits;
+ static code *next;
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) state->lens[sym++] = 8;
+ while (sym < 256) state->lens[sym++] = 9;
+ while (sym < 280) state->lens[sym++] = 7;
+ while (sym < 288) state->lens[sym++] = 8;
+ next = fixed;
+ lenfix = next;
+ bits = 9;
+ inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) state->lens[sym++] = 5;
+ distfix = next;
+ bits = 5;
+ inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+ /* do this just once */
+ virgin = 0;
+ }
+#else /* !BUILDFIXED */
+# include "inffixed.h"
+#endif /* BUILDFIXED */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include <stdio.h>
+
+/*
+ Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also
+ defines BUILDFIXED, so the tables are built on the fly. makefixed() writes
+ those tables to stdout, which would be piped to inffixed.h. A small program
+ can simply call makefixed to do this:
+
+ void makefixed(void);
+
+ int main(void)
+ {
+ makefixed();
+ return 0;
+ }
+
+ Then that can be linked with zlib built with MAKEFIXED defined and run:
+
+ a.out > inffixed.h
+ */
+void makefixed(void)
+{
+ unsigned low, size;
+ struct inflate_state state;
+
+ fixedtables(&state);
+ puts(" /* inffixed.h -- table for decoding fixed codes");
+ puts(" * Generated automatically by makefixed().");
+ puts(" */");
+ puts("");
+ puts(" /* WARNING: this file should *not* be used by applications.");
+ puts(" It is part of the implementation of this library and is");
+ puts(" subject to change. Applications should only use zlib.h.");
+ puts(" */");
+ puts("");
+ size = 1U << 9;
+ printf(" static const code lenfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 7) == 0) printf("\n ");
+ printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
+ state.lencode[low].bits, state.lencode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+ size = 1U << 5;
+ printf("\n static const code distfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 6) == 0) printf("\n ");
+ printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+ state.distcode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+}
+#endif /* MAKEFIXED */
+
+/*
+ Update the window with the last wsize (normally 32K) bytes written before
+ returning. If window does not exist yet, create it. This is only called
+ when a window is already in use, or when output has been written during this
+ inflate call, but the end of the deflate stream has not been reached yet.
+ It is also called to create a window for dictionary data when a dictionary
+ is loaded.
+
+ Providing output buffers larger than 32K to inflate() should provide a speed
+ advantage, since only the last 32K of output is copied to the sliding window
+ upon return from inflate(), and since all distances after the first 32K of
+ output will fall in the output data, making match copies simpler and faster.
+ The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(z_streamp strm, const Bytef *end, unsigned copy) {
+ struct inflate_state FAR *state;
+ unsigned dist;
+
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* if it hasn't been done already, allocate space for the window */
+ if (state->window == Z_NULL) {
+ state->window = (unsigned char FAR *)
+ ZALLOC(strm, 1U << state->wbits,
+ sizeof(unsigned char));
+ if (state->window == Z_NULL) return 1;
+ }
+
+ /* if window not in use yet, initialize */
+ if (state->wsize == 0) {
+ state->wsize = 1U << state->wbits;
+ state->wnext = 0;
+ state->whave = 0;
+ }
+
+ /* copy state->wsize or less output bytes into the circular window */
+ if (copy >= state->wsize) {
+ zmemcpy(state->window, end - state->wsize, state->wsize);
+ state->wnext = 0;
+ state->whave = state->wsize;
+ }
+ else {
+ dist = state->wsize - state->wnext;
+ if (dist > copy) dist = copy;
+ zmemcpy(state->window + state->wnext, end - copy, dist);
+ copy -= dist;
+ if (copy) {
+ zmemcpy(state->window, end - copy, copy);
+ state->wnext = copy;
+ state->whave = state->wsize;
+ }
+ else {
+ state->wnext += dist;
+ if (state->wnext == state->wsize) state->wnext = 0;
+ if (state->whave < state->wsize) state->whave += dist;
+ }
+ }
+ return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+# define UPDATE_CHECK(check, buf, len) \
+ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+# define CRC2(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ check = crc32(check, hbuf, 2); \
+ } while (0)
+
+# define CRC4(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ hbuf[2] = (unsigned char)((word) >> 16); \
+ hbuf[3] = (unsigned char)((word) >> 24); \
+ check = crc32(check, hbuf, 4); \
+ } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+ if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ if (have == 0) goto inf_leave; \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/*
+ inflate() uses a state machine to process as much input data and generate as
+ much output data as possible before returning. The state machine is
+ structured roughly as follows:
+
+ for (;;) switch (state) {
+ ...
+ case STATEn:
+ if (not enough input data or output space to make progress)
+ return;
+ ... make progress ...
+ state = STATEm;
+ break;
+ ...
+ }
+
+ so when inflate() is called again, the same case is attempted again, and
+ if the appropriate resources are provided, the machine proceeds to the
+ next state. The NEEDBITS() macro is usually the way the state evaluates
+ whether it can proceed or should return. NEEDBITS() does the return if
+ the requested bits are not available. The typical use of the BITS macros
+ is:
+
+ NEEDBITS(n);
+ ... do something with BITS(n) ...
+ DROPBITS(n);
+
+ where NEEDBITS(n) either returns from inflate() if there isn't enough
+ input left to load n bits into the accumulator, or it continues. BITS(n)
+ gives the low n bits in the accumulator. When done, DROPBITS(n) drops
+ the low n bits off the accumulator. INITBITS() clears the accumulator
+ and sets the number of available bits to zero. BYTEBITS() discards just
+ enough bits to put the accumulator on a byte boundary. After BYTEBITS()
+ and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+ NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+ if there is no input available. The decoding of variable length codes uses
+ PULLBYTE() directly in order to pull just enough bytes to decode the next
+ code, and no more.
+
+ Some states loop until they get enough input, making sure that enough
+ state information is maintained to continue the loop where it left off
+ if NEEDBITS() returns in the loop. For example, want, need, and keep
+ would all have to actually be part of the saved state in case NEEDBITS()
+ returns:
+
+ case STATEw:
+ while (want < need) {
+ NEEDBITS(n);
+ keep[want++] = BITS(n);
+ DROPBITS(n);
+ }
+ state = STATEx;
+ case STATEx:
+
+ As shown above, if the next state is also the next case, then the break
+ is omitted.
+
+ A state may also return if there is not enough output space available to
+ complete that state. Those states are copying stored data, writing a
+ literal byte, and copying a matching string.
+
+ When returning, a "goto inf_leave" is used to update the total counters,
+ update the check value, and determine whether any progress has been made
+ during that inflate() call in order to return the proper return code.
+ Progress is defined as a change in either strm->avail_in or strm->avail_out.
+ When there is a window, goto inf_leave will update the window with the last
+ output written. If a goto inf_leave occurs in the middle of decompression
+ and there is no window currently, goto inf_leave will create one and copy
+ output to the window for the next call of inflate().
+
+ In this implementation, the flush parameter of inflate() only affects the
+ return code (per zlib.h). inflate() always writes as much as possible to
+ strm->next_out, given the space available and the provided input--the effect
+ documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
+ the allocation of and copying into a sliding window until necessary, which
+ provides the effect documented in zlib.h for Z_FINISH when the entire input
+ stream available. So the only thing the flush parameter actually does is:
+ when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
+ will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(z_streamp strm, int flush) {
+ struct inflate_state FAR *state;
+ z_const unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned in, out; /* save starting available input and output */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code here; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+#ifdef GUNZIP
+ unsigned char hbuf[4]; /* buffer for gzip header crc calculation */
+#endif
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ if (inflateStateCheck(strm) || strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0))
+ return Z_STREAM_ERROR;
+
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */
+ LOAD();
+ in = have;
+ out = left;
+ ret = Z_OK;
+ for (;;)
+ switch (state->mode) {
+ case HEAD:
+ if (state->wrap == 0) {
+ state->mode = TYPEDO;
+ break;
+ }
+ NEEDBITS(16);
+#ifdef GUNZIP
+ if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */
+ if (state->wbits == 0)
+ state->wbits = 15;
+ state->check = crc32(0L, Z_NULL, 0);
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = FLAGS;
+ break;
+ }
+ if (state->head != Z_NULL)
+ state->head->done = -1;
+ if (!(state->wrap & 1) || /* check if zlib header allowed */
+#else
+ if (
+#endif
+ ((BITS(8) << 8) + (hold >> 8)) % 31) {
+ strm->msg = (char *)"incorrect header check";
+ state->mode = BAD;
+ break;
+ }
+ if (BITS(4) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ DROPBITS(4);
+ len = BITS(4) + 8;
+ if (state->wbits == 0)
+ state->wbits = len;
+ if (len > 15 || len > state->wbits) {
+ strm->msg = (char *)"invalid window size";
+ state->mode = BAD;
+ break;
+ }
+ state->dmax = 1U << len;
+ state->flags = 0; /* indicate zlib header */
+ Tracev((stderr, "inflate: zlib header ok\n"));
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = hold & 0x200 ? DICTID : TYPE;
+ INITBITS();
+ break;
+#ifdef GUNZIP
+ case FLAGS:
+ NEEDBITS(16);
+ state->flags = (int)(hold);
+ if ((state->flags & 0xff) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ if (state->flags & 0xe000) {
+ strm->msg = (char *)"unknown header flags set";
+ state->mode = BAD;
+ break;
+ }
+ if (state->head != Z_NULL)
+ state->head->text = (int)((hold >> 8) & 1);
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = TIME;
+ ZFALLTHROUGH;
+ case TIME:
+ NEEDBITS(32);
+ if (state->head != Z_NULL)
+ state->head->time = hold;
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ CRC4(state->check, hold);
+ INITBITS();
+ state->mode = OS;
+ ZFALLTHROUGH;
+ case OS:
+ NEEDBITS(16);
+ if (state->head != Z_NULL) {
+ state->head->xflags = (int)(hold & 0xff);
+ state->head->os = (int)(hold >> 8);
+ }
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = EXLEN;
+ ZFALLTHROUGH;
+ case EXLEN:
+ if (state->flags & 0x0400) {
+ NEEDBITS(16);
+ state->length = (unsigned)(hold);
+ if (state->head != Z_NULL)
+ state->head->extra_len = (unsigned)hold;
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ CRC2(state->check, hold);
+ INITBITS();
+ }
+ else if (state->head != Z_NULL)
+ state->head->extra = Z_NULL;
+ state->mode = EXTRA;
+ ZFALLTHROUGH;
+ case EXTRA:
+ if (state->flags & 0x0400) {
+ copy = state->length;
+ if (copy > have) copy = have;
+ if (copy) {
+ if (state->head != Z_NULL &&
+ state->head->extra != Z_NULL &&
+ (len = state->head->extra_len - state->length) <
+ state->head->extra_max) {
+ zmemcpy(state->head->extra + len, next,
+ len + copy > state->head->extra_max ?
+ state->head->extra_max - len : copy);
+ }
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ state->length -= copy;
+ }
+ if (state->length) goto inf_leave;
+ }
+ state->length = 0;
+ state->mode = NAME;
+ ZFALLTHROUGH;
+ case NAME:
+ if (state->flags & 0x0800) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->name != Z_NULL &&
+ state->length < state->head->name_max)
+ state->head->name[state->length++] = (Bytef)len;
+ } while (len && copy < have);
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->name = Z_NULL;
+ state->length = 0;
+ state->mode = COMMENT;
+ ZFALLTHROUGH;
+ case COMMENT:
+ if (state->flags & 0x1000) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->comment != Z_NULL &&
+ state->length < state->head->comm_max)
+ state->head->comment[state->length++] = (Bytef)len;
+ } while (len && copy < have);
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->comment = Z_NULL;
+ state->mode = HCRC;
+ ZFALLTHROUGH;
+ case HCRC:
+ if (state->flags & 0x0200) {
+ NEEDBITS(16);
+ if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
+ strm->msg = (char *)"header crc mismatch";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ }
+ if (state->head != Z_NULL) {
+ state->head->hcrc = (int)((state->flags >> 9) & 1);
+ state->head->done = 1;
+ }
+ strm->adler = state->check = crc32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ break;
+#endif
+ case DICTID:
+ NEEDBITS(32);
+ strm->adler = state->check = ZSWAP32(hold);
+ INITBITS();
+ state->mode = DICT;
+ ZFALLTHROUGH;
+ case DICT:
+ if (state->havedict == 0) {
+ RESTORE();
+ return Z_NEED_DICT;
+ }
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ ZFALLTHROUGH;
+ case TYPE:
+ if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
+ ZFALLTHROUGH;
+ case TYPEDO:
+ if (state->last) {
+ BYTEBITS();
+ state->mode = CHECK;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN_; /* decode codes */
+ if (flush == Z_TREES) {
+ DROPBITS(2);
+ goto inf_leave;
+ }
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+ case STORED:
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+ state->mode = COPY_;
+ if (flush == Z_TREES) goto inf_leave;
+ ZFALLTHROUGH;
+ case COPY_:
+ state->mode = COPY;
+ ZFALLTHROUGH;
+ case COPY:
+ copy = state->length;
+ if (copy) {
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ if (copy == 0) goto inf_leave;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ break;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ state->have = 0;
+ state->mode = LENLENS;
+ ZFALLTHROUGH;
+ case LENLENS:
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (const code FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+ state->have = 0;
+ state->mode = CODELENS;
+ ZFALLTHROUGH;
+ case CODELENS:
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.val < 16) {
+ DROPBITS(here.bits);
+ state->lens[state->have++] = here.val;
+ }
+ else {
+ if (here.val == 16) {
+ NEEDBITS(here.bits + 2);
+ DROPBITS(here.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = state->lens[state->have - 1];
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (here.val == 17) {
+ NEEDBITS(here.bits + 3);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(here.bits + 7);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* check for end-of-block code (better have one) */
+ if (state->lens[256] == 0) {
+ strm->msg = (char *)"invalid code -- missing end-of-block";
+ state->mode = BAD;
+ break;
+ }
+
+ /* build code tables -- note: do not change the lenbits or distbits
+ values here (9 and 6) without reading the comments in inftrees.h
+ concerning the ENOUGH constants, which depend on those values */
+ state->next = state->codes;
+ state->lencode = (const code FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (const code FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN_;
+ if (flush == Z_TREES) goto inf_leave;
+ ZFALLTHROUGH;
+ case LEN_:
+ state->mode = LEN;
+ ZFALLTHROUGH;
+ case LEN:
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ inflate_fast(strm, out);
+ LOAD();
+ if (state->mode == TYPE)
+ state->back = -1;
+ break;
+ }
+ state->back = 0;
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.op && (here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ state->back += last.bits;
+ }
+ DROPBITS(here.bits);
+ state->back += here.bits;
+ state->length = (unsigned)here.val;
+ if ((int)(here.op) == 0) {
+ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", here.val));
+ state->mode = LIT;
+ break;
+ }
+ if (here.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->back = -1;
+ state->mode = TYPE;
+ break;
+ }
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ state->extra = (unsigned)(here.op) & 15;
+ state->mode = LENEXT;
+ ZFALLTHROUGH;
+ case LENEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ state->back += state->extra;
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+ state->was = state->length;
+ state->mode = DIST;
+ ZFALLTHROUGH;
+ case DIST:
+ for (;;) {
+ here = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ state->back += last.bits;
+ }
+ DROPBITS(here.bits);
+ state->back += here.bits;
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)here.val;
+ state->extra = (unsigned)(here.op) & 15;
+ state->mode = DISTEXT;
+ ZFALLTHROUGH;
+ case DISTEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ state->back += state->extra;
+ }
+#ifdef INFLATE_STRICT
+ if (state->offset > state->dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+ state->mode = MATCH;
+ ZFALLTHROUGH;
+ case MATCH:
+ if (left == 0) goto inf_leave;
+ copy = out - left;
+ if (state->offset > copy) { /* copy from window */
+ copy = state->offset - copy;
+ if (copy > state->whave) {
+ if (state->sane) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ Trace((stderr, "inflate.c too far\n"));
+ copy -= state->whave;
+ if (copy > state->length) copy = state->length;
+ if (copy > left) copy = left;
+ left -= copy;
+ state->length -= copy;
+ do {
+ *put++ = 0;
+ } while (--copy);
+ if (state->length == 0) state->mode = LEN;
+ break;
+#endif
+ }
+ if (copy > state->wnext) {
+ copy -= state->wnext;
+ from = state->window + (state->wsize - copy);
+ }
+ else
+ from = state->window + (state->wnext - copy);
+ if (copy > state->length) copy = state->length;
+ }
+ else { /* copy from output */
+ from = put - state->offset;
+ copy = state->length;
+ }
+ if (copy > left) copy = left;
+ left -= copy;
+ state->length -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ if (state->length == 0) state->mode = LEN;
+ break;
+ case LIT:
+ if (left == 0) goto inf_leave;
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ case CHECK:
+ if (state->wrap) {
+ NEEDBITS(32);
+ out -= left;
+ strm->total_out += out;
+ state->total += out;
+ if ((state->wrap & 4) && out)
+ strm->adler = state->check =
+ UPDATE_CHECK(state->check, put - out, out);
+ out = left;
+ if ((state->wrap & 4) && (
+#ifdef GUNZIP
+ state->flags ? hold :
+#endif
+ ZSWAP32(hold)) != state->check) {
+ strm->msg = (char *)"incorrect data check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: check matches trailer\n"));
+ }
+#ifdef GUNZIP
+ state->mode = LENGTH;
+ ZFALLTHROUGH;
+ case LENGTH:
+ if (state->wrap && state->flags) {
+ NEEDBITS(32);
+ if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) {
+ strm->msg = (char *)"incorrect length check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: length matches trailer\n"));
+ }
+#endif
+ state->mode = DONE;
+ ZFALLTHROUGH;
+ case DONE:
+ ret = Z_STREAM_END;
+ goto inf_leave;
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+ case MEM:
+ return Z_MEM_ERROR;
+ case SYNC:
+ default:
+ return Z_STREAM_ERROR;
+ }
+
+ /*
+ Return from inflate(), updating the total counts and the check value.
+ If there was no progress during the inflate() call, return a buffer
+ error. Call updatewindow() to create and/or update the window state.
+ Note: a memory error from inflate() is non-recoverable.
+ */
+ inf_leave:
+ RESTORE();
+ if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
+ (state->mode < CHECK || flush != Z_FINISH)))
+ if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ in -= strm->avail_in;
+ out -= strm->avail_out;
+ strm->total_in += in;
+ strm->total_out += out;
+ state->total += out;
+ if ((state->wrap & 4) && out)
+ strm->adler = state->check =
+ UPDATE_CHECK(state->check, strm->next_out - out, out);
+ strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
+ (state->mode == TYPE ? 128 : 0) +
+ (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
+ if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+ ret = Z_BUF_ERROR;
+ return ret;
+}
+
+int ZEXPORT inflateEnd(z_streamp strm) {
+ struct inflate_state FAR *state;
+ if (inflateStateCheck(strm))
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->window != Z_NULL) ZFREE(strm, state->window);
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary,
+ uInt *dictLength) {
+ struct inflate_state FAR *state;
+
+ /* check state */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* copy dictionary */
+ if (state->whave && dictionary != Z_NULL) {
+ zmemcpy(dictionary, state->window + state->wnext,
+ state->whave - state->wnext);
+ zmemcpy(dictionary + state->whave - state->wnext,
+ state->window, state->wnext);
+ }
+ if (dictLength != Z_NULL)
+ *dictLength = state->whave;
+ return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary,
+ uInt dictLength) {
+ struct inflate_state FAR *state;
+ unsigned long dictid;
+ int ret;
+
+ /* check state */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->wrap != 0 && state->mode != DICT)
+ return Z_STREAM_ERROR;
+
+ /* check for correct dictionary identifier */
+ if (state->mode == DICT) {
+ dictid = adler32(0L, Z_NULL, 0);
+ dictid = adler32(dictid, dictionary, dictLength);
+ if (dictid != state->check)
+ return Z_DATA_ERROR;
+ }
+
+ /* copy dictionary to window using updatewindow(), which will amend the
+ existing dictionary if appropriate */
+ ret = updatewindow(strm, dictionary + dictLength, dictLength);
+ if (ret) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ state->havedict = 1;
+ Tracev((stderr, "inflate: dictionary set\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) {
+ struct inflate_state FAR *state;
+
+ /* check state */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+ /* save header structure */
+ state->head = head;
+ head->done = 0;
+ return Z_OK;
+}
+
+/*
+ Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found
+ or when out of input. When called, *have is the number of pattern bytes
+ found in order so far, in 0..3. On return *have is updated to the new
+ state. If on return *have equals four, then the pattern was found and the
+ return value is how many bytes were read including the last byte of the
+ pattern. If *have is less than four, then the pattern has not been found
+ yet and the return value is len. In the latter case, syncsearch() can be
+ called again with more data and the *have state. *have is initialized to
+ zero for the first call.
+ */
+local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf,
+ unsigned len) {
+ unsigned got;
+ unsigned next;
+
+ got = *have;
+ next = 0;
+ while (next < len && got < 4) {
+ if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+ got++;
+ else if (buf[next])
+ got = 0;
+ else
+ got = 4 - got;
+ next++;
+ }
+ *have = got;
+ return next;
+}
+
+int ZEXPORT inflateSync(z_streamp strm) {
+ unsigned len; /* number of bytes to look at or looked at */
+ int flags; /* temporary to save header status */
+ unsigned long in, out; /* temporary to save total_in and total_out */
+ unsigned char buf[4]; /* to restore bit buffer to byte string */
+ struct inflate_state FAR *state;
+
+ /* check parameters */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+ /* if first time, start search in bit buffer */
+ if (state->mode != SYNC) {
+ state->mode = SYNC;
+ state->hold <<= state->bits & 7;
+ state->bits -= state->bits & 7;
+ len = 0;
+ while (state->bits >= 8) {
+ buf[len++] = (unsigned char)(state->hold);
+ state->hold >>= 8;
+ state->bits -= 8;
+ }
+ state->have = 0;
+ syncsearch(&(state->have), buf, len);
+ }
+
+ /* search available input */
+ len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+ strm->avail_in -= len;
+ strm->next_in += len;
+ strm->total_in += len;
+
+ /* return no joy or set up to restart inflate() on a new block */
+ if (state->have != 4) return Z_DATA_ERROR;
+ if (state->flags == -1)
+ state->wrap = 0; /* if no header yet, treat as raw */
+ else
+ state->wrap &= ~4; /* no point in computing a check value now */
+ flags = state->flags;
+ in = strm->total_in; out = strm->total_out;
+ inflateReset(strm);
+ strm->total_in = in; strm->total_out = out;
+ state->flags = flags;
+ state->mode = TYPE;
+ return Z_OK;
+}
+
+/*
+ Returns true if inflate is currently at the end of a block generated by
+ Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ implementation to provide an additional safety check. PPP uses
+ Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+ block. When decompressing, PPP checks that at the end of input packet,
+ inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(z_streamp strm) {
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) {
+ struct inflate_state FAR *state;
+ struct inflate_state FAR *copy;
+ unsigned char FAR *window;
+ unsigned wsize;
+
+ /* check input */
+ if (inflateStateCheck(source) || dest == Z_NULL)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)source->state;
+
+ /* allocate space */
+ copy = (struct inflate_state FAR *)
+ ZALLOC(source, 1, sizeof(struct inflate_state));
+ if (copy == Z_NULL) return Z_MEM_ERROR;
+ window = Z_NULL;
+ if (state->window != Z_NULL) {
+ window = (unsigned char FAR *)
+ ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+ if (window == Z_NULL) {
+ ZFREE(source, copy);
+ return Z_MEM_ERROR;
+ }
+ }
+
+ /* copy state */
+ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
+ zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
+ copy->strm = dest;
+ if (state->lencode >= state->codes &&
+ state->lencode <= state->codes + ENOUGH - 1) {
+ copy->lencode = copy->codes + (state->lencode - state->codes);
+ copy->distcode = copy->codes + (state->distcode - state->codes);
+ }
+ copy->next = copy->codes + (state->next - state->codes);
+ if (window != Z_NULL) {
+ wsize = 1U << state->wbits;
+ zmemcpy(window, state->window, wsize);
+ }
+ copy->window = window;
+ dest->state = (struct internal_state FAR *)copy;
+ return Z_OK;
+}
+
+int ZEXPORT inflateUndermine(z_streamp strm, int subvert) {
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ state->sane = !subvert;
+ return Z_OK;
+#else
+ (void)subvert;
+ state->sane = 1;
+ return Z_DATA_ERROR;
+#endif
+}
+
+int ZEXPORT inflateValidate(z_streamp strm, int check) {
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (check && state->wrap)
+ state->wrap |= 4;
+ else
+ state->wrap &= ~4;
+ return Z_OK;
+}
+
+long ZEXPORT inflateMark(z_streamp strm) {
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm))
+ return -(1L << 16);
+ state = (struct inflate_state FAR *)strm->state;
+ return (long)(((unsigned long)((long)state->back)) << 16) +
+ (state->mode == COPY ? state->length :
+ (state->mode == MATCH ? state->was - state->length : 0));
+}
+
+unsigned long ZEXPORT inflateCodesUsed(z_streamp strm) {
+ struct inflate_state FAR *state;
+ if (inflateStateCheck(strm)) return (unsigned long)-1;
+ state = (struct inflate_state FAR *)strm->state;
+ return (unsigned long)(state->next - state->codes);
+}
diff --git a/lib/zlib/inflate.h b/lib/zlib/inflate.h
new file mode 100644
index 0000000..f127b6b
--- /dev/null
+++ b/lib/zlib/inflate.h
@@ -0,0 +1,126 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2019 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip decoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GUNZIP
+#endif
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+ HEAD = 16180, /* i: waiting for magic header */
+ FLAGS, /* i: waiting for method and flags (gzip) */
+ TIME, /* i: waiting for modification time (gzip) */
+ OS, /* i: waiting for extra flags and operating system (gzip) */
+ EXLEN, /* i: waiting for extra length (gzip) */
+ EXTRA, /* i: waiting for extra bytes (gzip) */
+ NAME, /* i: waiting for end of file name (gzip) */
+ COMMENT, /* i: waiting for end of comment (gzip) */
+ HCRC, /* i: waiting for header crc (gzip) */
+ DICTID, /* i: waiting for dictionary check value */
+ DICT, /* waiting for inflateSetDictionary() call */
+ TYPE, /* i: waiting for type bits, including last-flag bit */
+ TYPEDO, /* i: same, but skip check to exit inflate on new block */
+ STORED, /* i: waiting for stored size (length and complement) */
+ COPY_, /* i/o: same as COPY below, but only first time in */
+ COPY, /* i/o: waiting for input or output to copy stored block */
+ TABLE, /* i: waiting for dynamic block table lengths */
+ LENLENS, /* i: waiting for code length code lengths */
+ CODELENS, /* i: waiting for length/lit and distance code lengths */
+ LEN_, /* i: same as LEN below, but only first time in */
+ LEN, /* i: waiting for length/lit/eob code */
+ LENEXT, /* i: waiting for length extra bits */
+ DIST, /* i: waiting for distance code */
+ DISTEXT, /* i: waiting for distance extra bits */
+ MATCH, /* o: waiting for output space to copy string */
+ LIT, /* o: waiting for output space to write literal */
+ CHECK, /* i: waiting for 32-bit check value */
+ LENGTH, /* i: waiting for 32-bit length (gzip) */
+ DONE, /* finished check, done -- remain here until reset */
+ BAD, /* got a data error -- remain here until reset */
+ MEM, /* got an inflate() memory error -- remain here until reset */
+ SYNC /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+ State transitions between above modes -
+
+ (most modes can go to BAD or MEM on error -- not shown for clarity)
+
+ Process header:
+ HEAD -> (gzip) or (zlib) or (raw)
+ (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
+ HCRC -> TYPE
+ (zlib) -> DICTID or TYPE
+ DICTID -> DICT -> TYPE
+ (raw) -> TYPEDO
+ Read deflate blocks:
+ TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
+ STORED -> COPY_ -> COPY -> TYPE
+ TABLE -> LENLENS -> CODELENS -> LEN_
+ LEN_ -> LEN
+ Read deflate codes in fixed or dynamic block:
+ LEN -> LENEXT or LIT or TYPE
+ LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+ LIT -> LEN
+ Process trailer:
+ CHECK -> LENGTH -> DONE
+ */
+
+/* State maintained between inflate() calls -- approximately 7K bytes, not
+ including the allocated sliding window, which is up to 32K bytes. */
+struct inflate_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ inflate_mode mode; /* current inflate mode */
+ int last; /* true if processing last block */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip,
+ bit 2 true to validate check value */
+ int havedict; /* true if dictionary provided */
+ int flags; /* gzip header method and flags, 0 if zlib, or
+ -1 if raw or no header yet */
+ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
+ unsigned long check; /* protected copy of check value */
+ unsigned long total; /* protected copy of output count */
+ gz_headerp head; /* where to save gzip header information */
+ /* sliding window */
+ unsigned wbits; /* log base 2 of requested window size */
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned wnext; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if needed */
+ /* bit accumulator */
+ unsigned long hold; /* input bit accumulator */
+ unsigned bits; /* number of bits in "in" */
+ /* for string and stored block copying */
+ unsigned length; /* literal or length of data to copy */
+ unsigned offset; /* distance back to copy string from */
+ /* for table and code decoding */
+ unsigned extra; /* extra bits needed */
+ /* fixed and dynamic code tables */
+ code const FAR *lencode; /* starting table for length/literal codes */
+ code const FAR *distcode; /* starting table for distance codes */
+ unsigned lenbits; /* index bits for lencode */
+ unsigned distbits; /* index bits for distcode */
+ /* dynamic table building */
+ unsigned ncode; /* number of code length code lengths */
+ unsigned nlen; /* number of length code lengths */
+ unsigned ndist; /* number of distance code lengths */
+ unsigned have; /* number of code lengths in lens[] */
+ code FAR *next; /* next available space in codes[] */
+ unsigned short lens[320]; /* temporary storage for code lengths */
+ unsigned short work[288]; /* work area for code table building */
+ code codes[ENOUGH]; /* space for code tables */
+ int sane; /* if false, allow invalid distance too far */
+ int back; /* bits back of last unprocessed length/lit */
+ unsigned was; /* initial length of match */
+};
diff --git a/lib/zlib/inftrees.c b/lib/zlib/inftrees.c
new file mode 100644
index 0000000..8a208c2
--- /dev/null
+++ b/lib/zlib/inftrees.c
@@ -0,0 +1,299 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2023 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#define MAXBITS 15
+
+const char inflate_copyright[] =
+ " inflate 1.3 Copyright 1995-2023 Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/*
+ Build a set of tables to decode the provided canonical Huffman code.
+ The code lengths are lens[0..codes-1]. The result starts at *table,
+ whose indices are 0..2^bits-1. work is a writable array of at least
+ lens shorts, which is used as a work area. type is the type of code
+ to be generated, CODES, LENS, or DISTS. On return, zero is success,
+ -1 is an invalid code, and +1 means that ENOUGH isn't enough. table
+ on return points to the next available entry's address. bits is the
+ requested root table index bits, and on return it is the actual root
+ table index bits. It will differ if the request is greater than the
+ longest code or if it is less than the shortest code.
+ */
+int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
+ unsigned codes, code FAR * FAR *table,
+ unsigned FAR *bits, unsigned short FAR *work) {
+ unsigned len; /* a code's length in bits */
+ unsigned sym; /* index of code symbols */
+ unsigned min, max; /* minimum and maximum code lengths */
+ unsigned root; /* number of index bits for root table */
+ unsigned curr; /* number of index bits for current table */
+ unsigned drop; /* code bits to drop for sub-table */
+ int left; /* number of prefix codes available */
+ unsigned used; /* code entries in table used */
+ unsigned huff; /* Huffman code */
+ unsigned incr; /* for incrementing code, index */
+ unsigned fill; /* index for replicating entries */
+ unsigned low; /* low bits for current root entry */
+ unsigned mask; /* mask for low root bits */
+ code here; /* table entry for duplication */
+ code FAR *next; /* next available space in table */
+ const unsigned short FAR *base; /* base value table to use */
+ const unsigned short FAR *extra; /* extra bits table to use */
+ unsigned match; /* use base and extra for symbol >= match */
+ unsigned short count[MAXBITS+1]; /* number of codes of each length */
+ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
+ static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 198, 203};
+ static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577, 0, 0};
+ static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+ 28, 28, 29, 29, 64, 64};
+
+ /*
+ Process a set of code lengths to create a canonical Huffman code. The
+ code lengths are lens[0..codes-1]. Each length corresponds to the
+ symbols 0..codes-1. The Huffman code is generated by first sorting the
+ symbols by length from short to long, and retaining the symbol order
+ for codes with equal lengths. Then the code starts with all zero bits
+ for the first code of the shortest length, and the codes are integer
+ increments for the same length, and zeros are appended as the length
+ increases. For the deflate format, these bits are stored backwards
+ from their more natural integer increment ordering, and so when the
+ decoding tables are built in the large loop below, the integer codes
+ are incremented backwards.
+
+ This routine assumes, but does not check, that all of the entries in
+ lens[] are in the range 0..MAXBITS. The caller must assure this.
+ 1..MAXBITS is interpreted as that code length. zero means that that
+ symbol does not occur in this code.
+
+ The codes are sorted by computing a count of codes for each length,
+ creating from that a table of starting indices for each length in the
+ sorted table, and then entering the symbols in order in the sorted
+ table. The sorted table is work[], with that space being provided by
+ the caller.
+
+ The length counts are used for other purposes as well, i.e. finding
+ the minimum and maximum length codes, determining if there are any
+ codes at all, checking for a valid set of lengths, and looking ahead
+ at length counts to determine sub-table sizes when building the
+ decoding tables.
+ */
+
+ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+ for (len = 0; len <= MAXBITS; len++)
+ count[len] = 0;
+ for (sym = 0; sym < codes; sym++)
+ count[lens[sym]]++;
+
+ /* bound code lengths, force root to be within code lengths */
+ root = *bits;
+ for (max = MAXBITS; max >= 1; max--)
+ if (count[max] != 0) break;
+ if (root > max) root = max;
+ if (max == 0) { /* no symbols to code at all */
+ here.op = (unsigned char)64; /* invalid code marker */
+ here.bits = (unsigned char)1;
+ here.val = (unsigned short)0;
+ *(*table)++ = here; /* make a table to force an error */
+ *(*table)++ = here;
+ *bits = 1;
+ return 0; /* no symbols, but wait for decoding to report error */
+ }
+ for (min = 1; min < max; min++)
+ if (count[min] != 0) break;
+ if (root < min) root = min;
+
+ /* check for an over-subscribed or incomplete set of lengths */
+ left = 1;
+ for (len = 1; len <= MAXBITS; len++) {
+ left <<= 1;
+ left -= count[len];
+ if (left < 0) return -1; /* over-subscribed */
+ }
+ if (left > 0 && (type == CODES || max != 1))
+ return -1; /* incomplete set */
+
+ /* generate offsets into symbol table for each length for sorting */
+ offs[1] = 0;
+ for (len = 1; len < MAXBITS; len++)
+ offs[len + 1] = offs[len] + count[len];
+
+ /* sort symbols by length, by symbol order within each length */
+ for (sym = 0; sym < codes; sym++)
+ if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+ /*
+ Create and fill in decoding tables. In this loop, the table being
+ filled is at next and has curr index bits. The code being used is huff
+ with length len. That code is converted to an index by dropping drop
+ bits off of the bottom. For codes where len is less than drop + curr,
+ those top drop + curr - len bits are incremented through all values to
+ fill the table with replicated entries.
+
+ root is the number of index bits for the root table. When len exceeds
+ root, sub-tables are created pointed to by the root entry with an index
+ of the low root bits of huff. This is saved in low to check for when a
+ new sub-table should be started. drop is zero when the root table is
+ being filled, and drop is root when sub-tables are being filled.
+
+ When a new sub-table is needed, it is necessary to look ahead in the
+ code lengths to determine what size sub-table is needed. The length
+ counts are used for this, and so count[] is decremented as codes are
+ entered in the tables.
+
+ used keeps track of how many table entries have been allocated from the
+ provided *table space. It is checked for LENS and DIST tables against
+ the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
+ the initial root table size constants. See the comments in inftrees.h
+ for more information.
+
+ sym increments through all symbols, and the loop terminates when
+ all codes of length max, i.e. all codes, have been processed. This
+ routine permits incomplete codes, so another loop after this one fills
+ in the rest of the decoding tables with invalid code markers.
+ */
+
+ /* set up for code type */
+ switch (type) {
+ case CODES:
+ base = extra = work; /* dummy value--not used */
+ match = 20;
+ break;
+ case LENS:
+ base = lbase;
+ extra = lext;
+ match = 257;
+ break;
+ default: /* DISTS */
+ base = dbase;
+ extra = dext;
+ match = 0;
+ }
+
+ /* initialize state for loop */
+ huff = 0; /* starting code */
+ sym = 0; /* starting code symbol */
+ len = min; /* starting code length */
+ next = *table; /* current table to fill in */
+ curr = root; /* current table index bits */
+ drop = 0; /* current bits to drop from code for index */
+ low = (unsigned)(-1); /* trigger new sub-table when len > root */
+ used = 1U << root; /* use root table entries */
+ mask = used - 1; /* mask for comparing low */
+
+ /* check available table space */
+ if ((type == LENS && used > ENOUGH_LENS) ||
+ (type == DISTS && used > ENOUGH_DISTS))
+ return 1;
+
+ /* process all codes and make table entries */
+ for (;;) {
+ /* create table entry */
+ here.bits = (unsigned char)(len - drop);
+ if (work[sym] + 1U < match) {
+ here.op = (unsigned char)0;
+ here.val = work[sym];
+ }
+ else if (work[sym] >= match) {
+ here.op = (unsigned char)(extra[work[sym] - match]);
+ here.val = base[work[sym] - match];
+ }
+ else {
+ here.op = (unsigned char)(32 + 64); /* end of block */
+ here.val = 0;
+ }
+
+ /* replicate for those indices with low len bits equal to huff */
+ incr = 1U << (len - drop);
+ fill = 1U << curr;
+ min = fill; /* save offset to next table */
+ do {
+ fill -= incr;
+ next[(huff >> drop) + fill] = here;
+ } while (fill != 0);
+
+ /* backwards increment the len-bit code huff */
+ incr = 1U << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+
+ /* go to next symbol, update count, len */
+ sym++;
+ if (--(count[len]) == 0) {
+ if (len == max) break;
+ len = lens[work[sym]];
+ }
+
+ /* create new sub-table if needed */
+ if (len > root && (huff & mask) != low) {
+ /* if first time, transition to sub-tables */
+ if (drop == 0)
+ drop = root;
+
+ /* increment past last table */
+ next += min; /* here min is 1 << curr */
+
+ /* determine length of next table */
+ curr = len - drop;
+ left = (int)(1 << curr);
+ while (curr + drop < max) {
+ left -= count[curr + drop];
+ if (left <= 0) break;
+ curr++;
+ left <<= 1;
+ }
+
+ /* check for enough space */
+ used += 1U << curr;
+ if ((type == LENS && used > ENOUGH_LENS) ||
+ (type == DISTS && used > ENOUGH_DISTS))
+ return 1;
+
+ /* point entry in root table to sub-table */
+ low = huff & mask;
+ (*table)[low].op = (unsigned char)curr;
+ (*table)[low].bits = (unsigned char)root;
+ (*table)[low].val = (unsigned short)(next - *table);
+ }
+ }
+
+ /* fill in remaining table entry if code is incomplete (guaranteed to have
+ at most one remaining entry, since if the code is incomplete, the
+ maximum code length that was allowed to get this far is one bit) */
+ if (huff != 0) {
+ here.op = (unsigned char)64; /* invalid code marker */
+ here.bits = (unsigned char)(len - drop);
+ here.val = (unsigned short)0;
+ next[huff] = here;
+ }
+
+ /* set return parameters */
+ *table += used;
+ *bits = root;
+ return 0;
+}
diff --git a/lib/zlib/inftrees.h b/lib/zlib/inftrees.h
new file mode 100644
index 0000000..a10712d
--- /dev/null
+++ b/lib/zlib/inftrees.h
@@ -0,0 +1,62 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2005, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* Structure for decoding tables. Each entry provides either the
+ information needed to do the operation requested by the code that
+ indexed that table entry, or it provides a pointer to another
+ table that indexes more bits of the code. op indicates whether
+ the entry is a pointer to another table, a literal, a length or
+ distance, an end-of-block, or an invalid code. For a table
+ pointer, the low four bits of op is the number of index bits of
+ that table. For a length or distance, the low four bits of op
+ is the number of extra bits to get after the code. bits is
+ the number of bits in this code or part of the code to drop off
+ of the bit buffer. val is the actual byte to output in the case
+ of a literal, the base length or distance, or the offset from
+ the current table to the next table. Each entry is four bytes. */
+typedef struct {
+ unsigned char op; /* operation, extra bits, table bits */
+ unsigned char bits; /* bits in this part of the code */
+ unsigned short val; /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+ 00000000 - literal
+ 0000tttt - table link, tttt != 0 is the number of table index bits
+ 0001eeee - length or distance, eeee is the number of extra bits
+ 01100000 - end of block
+ 01000000 - invalid code
+ */
+
+/* Maximum size of the dynamic table. The maximum number of code structures is
+ 1444, which is the sum of 852 for literal/length codes and 592 for distance
+ codes. These values were found by exhaustive searches using the program
+ examples/enough.c found in the zlib distribution. The arguments to that
+ program are the number of symbols, the initial root table size, and the
+ maximum bit length of a code. "enough 286 9 15" for literal/length codes
+ returns returns 852, and "enough 30 6 15" for distance codes returns 592.
+ The initial root table size (9 or 6) is found in the fifth argument of the
+ inflate_table() calls in inflate.c and infback.c. If the root table size is
+ changed, then these maximum sizes would be need to be recalculated and
+ updated. */
+#define ENOUGH_LENS 852
+#define ENOUGH_DISTS 592
+#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
+
+/* Type of code to build for inflate_table() */
+typedef enum {
+ CODES,
+ LENS,
+ DISTS
+} codetype;
+
+int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
+ unsigned codes, code FAR * FAR *table,
+ unsigned FAR *bits, unsigned short FAR *work);
diff --git a/lib/zlib/trees.c b/lib/zlib/trees.c
new file mode 100644
index 0000000..8dbdc40
--- /dev/null
+++ b/lib/zlib/trees.c
@@ -0,0 +1,1103 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-2021 Jean-loup Gailly
+ * detect_data_type() function provided freely by Cosmin Truta, 2006
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process uses several Huffman trees. The more
+ * common source values are represented by shorter bit sequences.
+ *
+ * Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values). The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ * Storer, James A.
+ * Data Compression: Methods and Theory, pp. 49-50.
+ * Computer Science Press, 1988. ISBN 0-7167-8156-5.
+ *
+ * Sedgewick, R.
+ * Algorithms, p290.
+ * Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* @(#) $Id$ */
+
+/* #define GEN_TREES_H */
+
+#include "deflate.h"
+
+#ifdef ZLIB_DEBUG
+# include <ctype.h>
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6 16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10 17
+/* repeat a zero length 3-10 times (3 bits of repeat count) */
+
+#define REPZ_11_138 18
+/* repeat a zero length 11-138 times (7 bits of repeat count) */
+
+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local const int extra_dbits[D_CODES] /* extra bits for each distance code */
+ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local const uch bl_order[BL_CODES]
+ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+#define DIST_CODE_LEN 512 /* see definition of array dist_code below */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+/* non ANSI compilers may not accept trees.h */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+uch _dist_code[DIST_CODE_LEN];
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+uch _length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#else
+# include "trees.h"
+#endif /* GEN_TREES_H */
+
+struct static_tree_desc_s {
+ const ct_data *static_tree; /* static tree or NULL */
+ const intf *extra_bits; /* extra bits for each code or NULL */
+ int extra_base; /* base index for extra_bits */
+ int elems; /* max number of elements in the tree */
+ int max_length; /* max bit length for the codes */
+};
+
+#ifdef NO_INIT_GLOBAL_POINTERS
+# define TCONST
+#else
+# define TCONST const
+#endif
+
+local TCONST static_tree_desc static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local TCONST static_tree_desc static_d_desc =
+{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
+
+local TCONST static_tree_desc static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+ put_byte(s, (uch)((w) & 0xff)); \
+ put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(unsigned code, int len) {
+ register unsigned res = 0;
+ do {
+ res |= code & 1;
+ code >>= 1, res <<= 1;
+ } while (--len > 0);
+ return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(deflate_state *s) {
+ if (s->bi_valid == 16) {
+ put_short(s, s->bi_buf);
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ } else if (s->bi_valid >= 8) {
+ put_byte(s, (Byte)s->bi_buf);
+ s->bi_buf >>= 8;
+ s->bi_valid -= 8;
+ }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(deflate_state *s) {
+ if (s->bi_valid > 8) {
+ put_short(s, s->bi_buf);
+ } else if (s->bi_valid > 0) {
+ put_byte(s, (Byte)s->bi_buf);
+ }
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+#ifdef ZLIB_DEBUG
+ s->bits_sent = (s->bits_sent + 7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ * zero code length.
+ */
+local void gen_codes(ct_data *tree, int max_code, ushf *bl_count) {
+ ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+ unsigned code = 0; /* running code value */
+ int bits; /* bit index */
+ int n; /* code index */
+
+ /* The distribution counts are first used to generate the code values
+ * without bit reversal.
+ */
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ code = (code + bl_count[bits - 1]) << 1;
+ next_code[bits] = (ush)code;
+ }
+ /* Check that the bit counts in bl_count are consistent. The last code
+ * must be all ones.
+ */
+ Assert (code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1,
+ "inconsistent bit counts");
+ Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+ for (n = 0; n <= max_code; n++) {
+ int len = tree[n].Len;
+ if (len == 0) continue;
+ /* Now reverse the bits */
+ tree[n].Code = (ush)bi_reverse(next_code[len]++, len);
+
+ Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+ n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len] - 1));
+ }
+}
+
+#ifdef GEN_TREES_H
+local void gen_trees_header(void);
+#endif
+
+#ifndef ZLIB_DEBUG
+# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+ /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* !ZLIB_DEBUG */
+# define send_code(s, c, tree) \
+ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+ send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef ZLIB_DEBUG
+local void send_bits(deflate_state *s, int value, int length) {
+ Tracevv((stderr," l %2d v %4x ", length, value));
+ Assert(length > 0 && length <= 15, "invalid length");
+ s->bits_sent += (ulg)length;
+
+ /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+ * (16 - bi_valid) bits from value, leaving (width - (16 - bi_valid))
+ * unused bits in value.
+ */
+ if (s->bi_valid > (int)Buf_size - length) {
+ s->bi_buf |= (ush)value << s->bi_valid;
+ put_short(s, s->bi_buf);
+ s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+ s->bi_valid += length - Buf_size;
+ } else {
+ s->bi_buf |= (ush)value << s->bi_valid;
+ s->bi_valid += length;
+ }
+}
+#else /* !ZLIB_DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+ if (s->bi_valid > (int)Buf_size - len) {\
+ int val = (int)value;\
+ s->bi_buf |= (ush)val << s->bi_valid;\
+ put_short(s, s->bi_buf);\
+ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+ s->bi_valid += len - Buf_size;\
+ } else {\
+ s->bi_buf |= (ush)(value) << s->bi_valid;\
+ s->bi_valid += len;\
+ }\
+}
+#endif /* ZLIB_DEBUG */
+
+
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+local void tr_static_init(void) {
+#if defined(GEN_TREES_H) || !defined(STDC)
+ static int static_init_done = 0;
+ int n; /* iterates over tree elements */
+ int bits; /* bit counter */
+ int length; /* length value */
+ int code; /* code value */
+ int dist; /* distance index */
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ if (static_init_done) return;
+
+ /* For some embedded targets, global variables are not initialized: */
+#ifdef NO_INIT_GLOBAL_POINTERS
+ static_l_desc.static_tree = static_ltree;
+ static_l_desc.extra_bits = extra_lbits;
+ static_d_desc.static_tree = static_dtree;
+ static_d_desc.extra_bits = extra_dbits;
+ static_bl_desc.extra_bits = extra_blbits;
+#endif
+
+ /* Initialize the mapping length (0..255) -> length code (0..28) */
+ length = 0;
+ for (code = 0; code < LENGTH_CODES-1; code++) {
+ base_length[code] = length;
+ for (n = 0; n < (1 << extra_lbits[code]); n++) {
+ _length_code[length++] = (uch)code;
+ }
+ }
+ Assert (length == 256, "tr_static_init: length != 256");
+ /* Note that the length 255 (match length 258) can be represented
+ * in two different ways: code 284 + 5 bits or code 285, so we
+ * overwrite length_code[255] to use the best encoding:
+ */
+ _length_code[length - 1] = (uch)code;
+
+ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+ dist = 0;
+ for (code = 0 ; code < 16; code++) {
+ base_dist[code] = dist;
+ for (n = 0; n < (1 << extra_dbits[code]); n++) {
+ _dist_code[dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: dist != 256");
+ dist >>= 7; /* from now on, all distances are divided by 128 */
+ for ( ; code < D_CODES; code++) {
+ base_dist[code] = dist << 7;
+ for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
+ _dist_code[256 + dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: 256 + dist != 512");
+
+ /* Construct the codes of the static literal tree */
+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+ n = 0;
+ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+ /* Codes 286 and 287 do not exist, but we must include them in the
+ * tree construction to get a canonical Huffman tree (longest code
+ * all ones)
+ */
+ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+ /* The static distance tree is trivial: */
+ for (n = 0; n < D_CODES; n++) {
+ static_dtree[n].Len = 5;
+ static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+ }
+ static_init_done = 1;
+
+# ifdef GEN_TREES_H
+ gen_trees_header();
+# endif
+#endif /* defined(GEN_TREES_H) || !defined(STDC) */
+}
+
+/* ===========================================================================
+ * Generate the file trees.h describing the static trees.
+ */
+#ifdef GEN_TREES_H
+# ifndef ZLIB_DEBUG
+# include <stdio.h>
+# endif
+
+# define SEPARATOR(i, last, width) \
+ ((i) == (last)? "\n};\n\n" : \
+ ((i) % (width) == (width) - 1 ? ",\n" : ", "))
+
+void gen_trees_header(void) {
+ FILE *header = fopen("trees.h", "w");
+ int i;
+
+ Assert (header != NULL, "Can't open trees.h");
+ fprintf(header,
+ "/* header created automatically with -DGEN_TREES_H */\n\n");
+
+ fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
+ for (i = 0; i < L_CODES+2; i++) {
+ fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
+ static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
+ }
+
+ fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+ static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
+ }
+
+ fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n");
+ for (i = 0; i < DIST_CODE_LEN; i++) {
+ fprintf(header, "%2u%s", _dist_code[i],
+ SEPARATOR(i, DIST_CODE_LEN-1, 20));
+ }
+
+ fprintf(header,
+ "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+ for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
+ fprintf(header, "%2u%s", _length_code[i],
+ SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
+ }
+
+ fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
+ for (i = 0; i < LENGTH_CODES; i++) {
+ fprintf(header, "%1u%s", base_length[i],
+ SEPARATOR(i, LENGTH_CODES-1, 20));
+ }
+
+ fprintf(header, "local const int base_dist[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "%5u%s", base_dist[i],
+ SEPARATOR(i, D_CODES-1, 10));
+ }
+
+ fclose(header);
+}
+#endif /* GEN_TREES_H */
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(deflate_state *s) {
+ int n; /* iterates over tree elements */
+
+ /* Initialize the trees. */
+ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
+ for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
+ for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+ s->dyn_ltree[END_BLOCK].Freq = 1;
+ s->opt_len = s->static_len = 0L;
+ s->sym_next = s->matches = 0;
+}
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void ZLIB_INTERNAL _tr_init(deflate_state *s) {
+ tr_static_init();
+
+ s->l_desc.dyn_tree = s->dyn_ltree;
+ s->l_desc.stat_desc = &static_l_desc;
+
+ s->d_desc.dyn_tree = s->dyn_dtree;
+ s->d_desc.stat_desc = &static_d_desc;
+
+ s->bl_desc.dyn_tree = s->bl_tree;
+ s->bl_desc.stat_desc = &static_bl_desc;
+
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+#ifdef ZLIB_DEBUG
+ s->compressed_len = 0L;
+ s->bits_sent = 0L;
+#endif
+
+ /* Initialize the first block of the first file: */
+ init_block(s);
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+ top = s->heap[SMALLEST]; \
+ s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+ pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+ (tree[n].Freq < tree[m].Freq || \
+ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(deflate_state *s, ct_data *tree, int k) {
+ int v = s->heap[k];
+ int j = k << 1; /* left son of k */
+ while (j <= s->heap_len) {
+ /* Set j to the smallest of the two sons: */
+ if (j < s->heap_len &&
+ smaller(tree, s->heap[j + 1], s->heap[j], s->depth)) {
+ j++;
+ }
+ /* Exit if v is smaller than both sons */
+ if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+ /* Exchange v with the smallest son */
+ s->heap[k] = s->heap[j]; k = j;
+
+ /* And continue down the tree, setting j to the left son of k */
+ j <<= 1;
+ }
+ s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ * above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ * array bl_count contains the frequencies for each bit length.
+ * The length opt_len is updated; static_len is also updated if stree is
+ * not null.
+ */
+local void gen_bitlen(deflate_state *s, tree_desc *desc) {
+ ct_data *tree = desc->dyn_tree;
+ int max_code = desc->max_code;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ const intf *extra = desc->stat_desc->extra_bits;
+ int base = desc->stat_desc->extra_base;
+ int max_length = desc->stat_desc->max_length;
+ int h; /* heap index */
+ int n, m; /* iterate over the tree elements */
+ int bits; /* bit length */
+ int xbits; /* extra bits */
+ ush f; /* frequency */
+ int overflow = 0; /* number of elements with bit length too large */
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+ /* In a first pass, compute the optimal bit lengths (which may
+ * overflow in the case of the bit length tree).
+ */
+ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+ for (h = s->heap_max + 1; h < HEAP_SIZE; h++) {
+ n = s->heap[h];
+ bits = tree[tree[n].Dad].Len + 1;
+ if (bits > max_length) bits = max_length, overflow++;
+ tree[n].Len = (ush)bits;
+ /* We overwrite tree[n].Dad which is no longer needed */
+
+ if (n > max_code) continue; /* not a leaf node */
+
+ s->bl_count[bits]++;
+ xbits = 0;
+ if (n >= base) xbits = extra[n - base];
+ f = tree[n].Freq;
+ s->opt_len += (ulg)f * (unsigned)(bits + xbits);
+ if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits);
+ }
+ if (overflow == 0) return;
+
+ Tracev((stderr,"\nbit length overflow\n"));
+ /* This happens for example on obj2 and pic of the Calgary corpus */
+
+ /* Find the first bit length which could increase: */
+ do {
+ bits = max_length - 1;
+ while (s->bl_count[bits] == 0) bits--;
+ s->bl_count[bits]--; /* move one leaf down the tree */
+ s->bl_count[bits + 1] += 2; /* move one overflow item as its brother */
+ s->bl_count[max_length]--;
+ /* The brother of the overflow item also moves one step up,
+ * but this does not affect bl_count[max_length]
+ */
+ overflow -= 2;
+ } while (overflow > 0);
+
+ /* Now recompute all bit lengths, scanning in increasing frequency.
+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+ * lengths instead of fixing only the wrong ones. This idea is taken
+ * from 'ar' written by Haruhiko Okumura.)
+ */
+ for (bits = max_length; bits != 0; bits--) {
+ n = s->bl_count[bits];
+ while (n != 0) {
+ m = s->heap[--h];
+ if (m > max_code) continue;
+ if ((unsigned) tree[m].Len != (unsigned) bits) {
+ Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+ s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq;
+ tree[m].Len = (ush)bits;
+ }
+ n--;
+ }
+ }
+}
+
+#ifdef DUMP_BL_TREE
+# include <stdio.h>
+#endif
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ * and corresponding code. The length opt_len is updated; static_len is
+ * also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(deflate_state *s, tree_desc *desc) {
+ ct_data *tree = desc->dyn_tree;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ int elems = desc->stat_desc->elems;
+ int n, m; /* iterate over heap elements */
+ int max_code = -1; /* largest code with non zero frequency */
+ int node; /* new node being created */
+
+ /* Construct the initial heap, with least frequent element in
+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n + 1].
+ * heap[0] is not used.
+ */
+ s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++) {
+ if (tree[n].Freq != 0) {
+ s->heap[++(s->heap_len)] = max_code = n;
+ s->depth[n] = 0;
+ } else {
+ tree[n].Len = 0;
+ }
+ }
+
+ /* The pkzip format requires that at least one distance code exists,
+ * and that at least one bit should be sent even if there is only one
+ * possible code. So to avoid special checks later on we force at least
+ * two codes of non zero frequency.
+ */
+ while (s->heap_len < 2) {
+ node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+ tree[node].Freq = 1;
+ s->depth[node] = 0;
+ s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+ /* node is 0 or 1 so it does not have extra bits */
+ }
+ desc->max_code = max_code;
+
+ /* The elements heap[heap_len/2 + 1 .. heap_len] are leaves of the tree,
+ * establish sub-heaps of increasing lengths:
+ */
+ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+ /* Construct the Huffman tree by repeatedly combining the least two
+ * frequent nodes.
+ */
+ node = elems; /* next internal node of the tree */
+ do {
+ pqremove(s, tree, n); /* n = node of least frequency */
+ m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+ s->heap[--(s->heap_max)] = m;
+
+ /* Create a new node father of n and m */
+ tree[node].Freq = tree[n].Freq + tree[m].Freq;
+ s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
+ s->depth[n] : s->depth[m]) + 1);
+ tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+ if (tree == s->bl_tree) {
+ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+ }
+#endif
+ /* and insert the new node in the heap */
+ s->heap[SMALLEST] = node++;
+ pqdownheap(s, tree, SMALLEST);
+
+ } while (s->heap_len >= 2);
+
+ s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+ /* At this point, the fields freq and dad are set. We can now
+ * generate the bit lengths.
+ */
+ gen_bitlen(s, (tree_desc *)desc);
+
+ /* The field len is now set, we can generate the bit codes */
+ gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree(deflate_state *s, ct_data *tree, int max_code) {
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ if (nextlen == 0) max_count = 138, min_count = 3;
+ tree[max_code + 1].Len = (ush)0xffff; /* guard */
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n + 1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ s->bl_tree[curlen].Freq += count;
+ } else if (curlen != 0) {
+ if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+ s->bl_tree[REP_3_6].Freq++;
+ } else if (count <= 10) {
+ s->bl_tree[REPZ_3_10].Freq++;
+ } else {
+ s->bl_tree[REPZ_11_138].Freq++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree(deflate_state *s, ct_data *tree, int max_code) {
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ /* tree[max_code + 1].Len = -1; */ /* guard already set */
+ if (nextlen == 0) max_count = 138, min_count = 3;
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n + 1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+ } else if (curlen != 0) {
+ if (curlen != prevlen) {
+ send_code(s, curlen, s->bl_tree); count--;
+ }
+ Assert(count >= 3 && count <= 6, " 3_6?");
+ send_code(s, REP_3_6, s->bl_tree); send_bits(s, count - 3, 2);
+
+ } else if (count <= 10) {
+ send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count - 3, 3);
+
+ } else {
+ send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count - 11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(deflate_state *s) {
+ int max_blindex; /* index of last bit length code of non zero freq */
+
+ /* Determine the bit length frequencies for literal and distance trees */
+ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+ scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+ /* Build the bit length tree: */
+ build_tree(s, (tree_desc *)(&(s->bl_desc)));
+ /* opt_len now includes the length of the tree representations, except the
+ * lengths of the bit lengths codes and the 5 + 5 + 4 bits for the counts.
+ */
+
+ /* Determine the number of bit length codes to send. The pkzip format
+ * requires that at least 4 bit length codes be sent. (appnote.txt says
+ * 3 but the actual value used is 4.)
+ */
+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+ if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+ }
+ /* Update opt_len to include the bit length tree and counts */
+ s->opt_len += 3*((ulg)max_blindex + 1) + 5 + 5 + 4;
+ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+ s->opt_len, s->static_len));
+
+ return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(deflate_state *s, int lcodes, int dcodes,
+ int blcodes) {
+ int rank; /* index in bl_order */
+
+ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+ "too many codes");
+ Tracev((stderr, "\nbl counts: "));
+ send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */
+ send_bits(s, dcodes - 1, 5);
+ send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */
+ for (rank = 0; rank < blcodes; rank++) {
+ Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+ send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+ }
+ Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_ltree, lcodes - 1); /* literal tree */
+ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_dtree, dcodes - 1); /* distance tree */
+ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf,
+ ulg stored_len, int last) {
+ send_bits(s, (STORED_BLOCK<<1) + last, 3); /* send block type */
+ bi_windup(s); /* align on byte boundary */
+ put_short(s, (ush)stored_len);
+ put_short(s, (ush)~stored_len);
+ if (stored_len)
+ zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
+ s->pending += stored_len;
+#ifdef ZLIB_DEBUG
+ s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+ s->compressed_len += (stored_len + 4) << 3;
+ s->bits_sent += 2*16;
+ s->bits_sent += stored_len << 3;
+#endif
+}
+
+/* ===========================================================================
+ * Flush the bits in the bit buffer to pending output (leaves at most 7 bits)
+ */
+void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s) {
+ bi_flush(s);
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ */
+void ZLIB_INTERNAL _tr_align(deflate_state *s) {
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+#ifdef ZLIB_DEBUG
+ s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+#endif
+ bi_flush(s);
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(deflate_state *s, const ct_data *ltree,
+ const ct_data *dtree) {
+ unsigned dist; /* distance of matched string */
+ int lc; /* match length or unmatched char (if dist == 0) */
+ unsigned sx = 0; /* running index in sym_buf */
+ unsigned code; /* the code to send */
+ int extra; /* number of extra bits to send */
+
+ if (s->sym_next != 0) do {
+ dist = s->sym_buf[sx++] & 0xff;
+ dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
+ lc = s->sym_buf[sx++];
+ if (dist == 0) {
+ send_code(s, lc, ltree); /* send a literal byte */
+ Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ code = _length_code[lc];
+ send_code(s, code + LITERALS + 1, ltree); /* send length code */
+ extra = extra_lbits[code];
+ if (extra != 0) {
+ lc -= base_length[code];
+ send_bits(s, lc, extra); /* send the extra length bits */
+ }
+ dist--; /* dist is now the match distance - 1 */
+ code = d_code(dist);
+ Assert (code < D_CODES, "bad d_code");
+
+ send_code(s, code, dtree); /* send the distance code */
+ extra = extra_dbits[code];
+ if (extra != 0) {
+ dist -= (unsigned)base_dist[code];
+ send_bits(s, dist, extra); /* send the extra distance bits */
+ }
+ } /* literal or match pair ? */
+
+ /* Check that the overlay between pending_buf and sym_buf is ok: */
+ Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
+
+ } while (sx < s->sym_next);
+
+ send_code(s, END_BLOCK, ltree);
+}
+
+/* ===========================================================================
+ * Check if the data type is TEXT or BINARY, using the following algorithm:
+ * - TEXT if the two conditions below are satisfied:
+ * a) There are no non-portable control characters belonging to the
+ * "block list" (0..6, 14..25, 28..31).
+ * b) There is at least one printable character belonging to the
+ * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
+ * - BINARY otherwise.
+ * - The following partially-portable control characters form a
+ * "gray list" that is ignored in this detection algorithm:
+ * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
+ * IN assertion: the fields Freq of dyn_ltree are set.
+ */
+local int detect_data_type(deflate_state *s) {
+ /* block_mask is the bit mask of block-listed bytes
+ * set bits 0..6, 14..25, and 28..31
+ * 0xf3ffc07f = binary 11110011111111111100000001111111
+ */
+ unsigned long block_mask = 0xf3ffc07fUL;
+ int n;
+
+ /* Check for non-textual ("block-listed") bytes. */
+ for (n = 0; n <= 31; n++, block_mask >>= 1)
+ if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0))
+ return Z_BINARY;
+
+ /* Check for textual ("allow-listed") bytes. */
+ if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
+ || s->dyn_ltree[13].Freq != 0)
+ return Z_TEXT;
+ for (n = 32; n < LITERALS; n++)
+ if (s->dyn_ltree[n].Freq != 0)
+ return Z_TEXT;
+
+ /* There are no "block-listed" or "allow-listed" bytes:
+ * this stream either is empty or has tolerated ("gray-listed") bytes only.
+ */
+ return Z_BINARY;
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and write out the encoded block.
+ */
+void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf,
+ ulg stored_len, int last) {
+ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+ int max_blindex = 0; /* index of last bit length code of non zero freq */
+
+ /* Build the Huffman trees unless a stored block is forced */
+ if (s->level > 0) {
+
+ /* Check if the file is binary or text */
+ if (s->strm->data_type == Z_UNKNOWN)
+ s->strm->data_type = detect_data_type(s);
+
+ /* Construct the literal and distance trees */
+ build_tree(s, (tree_desc *)(&(s->l_desc)));
+ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+
+ build_tree(s, (tree_desc *)(&(s->d_desc)));
+ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+ /* At this point, opt_len and static_len are the total bit lengths of
+ * the compressed block data, excluding the tree representations.
+ */
+
+ /* Build the bit length tree for the above two trees, and get the index
+ * in bl_order of the last bit length code to send.
+ */
+ max_blindex = build_bl_tree(s);
+
+ /* Determine the best encoding. Compute the block lengths in bytes. */
+ opt_lenb = (s->opt_len + 3 + 7) >> 3;
+ static_lenb = (s->static_len + 3 + 7) >> 3;
+
+ Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+ opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+ s->sym_next / 3));
+
+#ifndef FORCE_STATIC
+ if (static_lenb <= opt_lenb || s->strategy == Z_FIXED)
+#endif
+ opt_lenb = static_lenb;
+
+ } else {
+ Assert(buf != (char*)0, "lost buf");
+ opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+ }
+
+#ifdef FORCE_STORED
+ if (buf != (char*)0) { /* force stored block */
+#else
+ if (stored_len + 4 <= opt_lenb && buf != (char*)0) {
+ /* 4: two words for the lengths */
+#endif
+ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ * Otherwise we can't have processed more than WSIZE input bytes since
+ * the last block flush, because compression would have been
+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ * transform a block into a stored block.
+ */
+ _tr_stored_block(s, buf, stored_len, last);
+
+ } else if (static_lenb == opt_lenb) {
+ send_bits(s, (STATIC_TREES<<1) + last, 3);
+ compress_block(s, (const ct_data *)static_ltree,
+ (const ct_data *)static_dtree);
+#ifdef ZLIB_DEBUG
+ s->compressed_len += 3 + s->static_len;
+#endif
+ } else {
+ send_bits(s, (DYN_TREES<<1) + last, 3);
+ send_all_trees(s, s->l_desc.max_code + 1, s->d_desc.max_code + 1,
+ max_blindex + 1);
+ compress_block(s, (const ct_data *)s->dyn_ltree,
+ (const ct_data *)s->dyn_dtree);
+#ifdef ZLIB_DEBUG
+ s->compressed_len += 3 + s->opt_len;
+#endif
+ }
+ Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+ /* The above check is made mod 2^32, for files larger than 512 MB
+ * and uLong implemented on 32 bits.
+ */
+ init_block(s);
+
+ if (last) {
+ bi_windup(s);
+#ifdef ZLIB_DEBUG
+ s->compressed_len += 7; /* align on byte boundary */
+#endif
+ }
+ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len >> 3,
+ s->compressed_len - 7*last));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) {
+ s->sym_buf[s->sym_next++] = (uch)dist;
+ s->sym_buf[s->sym_next++] = (uch)(dist >> 8);
+ s->sym_buf[s->sym_next++] = (uch)lc;
+ if (dist == 0) {
+ /* lc is the unmatched char */
+ s->dyn_ltree[lc].Freq++;
+ } else {
+ s->matches++;
+ /* Here, lc is the match length - MIN_MATCH */
+ dist--; /* dist = match distance - 1 */
+ Assert((ush)dist < (ush)MAX_DIST(s) &&
+ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+ (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
+
+ s->dyn_ltree[_length_code[lc] + LITERALS + 1].Freq++;
+ s->dyn_dtree[d_code(dist)].Freq++;
+ }
+ return (s->sym_next == s->sym_end);
+}
diff --git a/lib/zlib/trees.h b/lib/zlib/trees.h
new file mode 100644
index 0000000..d35639d
--- /dev/null
+++ b/lib/zlib/trees.h
@@ -0,0 +1,128 @@
+/* header created automatically with -DGEN_TREES_H */
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
+{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
+{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
+{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
+{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
+{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
+{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
+{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
+{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
+{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
+{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
+{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
+{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
+{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
+{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
+{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
+{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
+{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
+{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
+{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
+{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
+{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
+{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
+{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
+{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
+{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
+{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
+{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
+{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
+{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
+{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
+{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
+{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
+{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
+{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
+{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
+{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
+{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
+{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
+{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
+{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
+{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
+{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
+{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
+{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
+{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
+{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
+{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
+{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
+{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
+{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
+{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
+{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
+{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
+{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
+{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
+{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
+{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+};
+
diff --git a/lib/zlib/uncompr.c b/lib/zlib/uncompr.c
new file mode 100644
index 0000000..5e25666
--- /dev/null
+++ b/lib/zlib/uncompr.c
@@ -0,0 +1,85 @@
+/* uncompr.c -- decompress a memory buffer
+ * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+ Decompresses the source buffer into the destination buffer. *sourceLen is
+ the byte length of the source buffer. Upon entry, *destLen is the total size
+ of the destination buffer, which must be large enough to hold the entire
+ uncompressed data. (The size of the uncompressed data must have been saved
+ previously by the compressor and transmitted to the decompressor by some
+ mechanism outside the scope of this compression library.) Upon exit,
+ *destLen is the size of the decompressed data and *sourceLen is the number
+ of source bytes consumed. Upon return, source + *sourceLen points to the
+ first unused input byte.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer, or
+ Z_DATA_ERROR if the input data was corrupted, including if the input data is
+ an incomplete zlib stream.
+*/
+int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, const Bytef *source,
+ uLong *sourceLen) {
+ z_stream stream;
+ int err;
+ const uInt max = (uInt)-1;
+ uLong len, left;
+ Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */
+
+ len = *sourceLen;
+ if (*destLen) {
+ left = *destLen;
+ *destLen = 0;
+ }
+ else {
+ left = 1;
+ dest = buf;
+ }
+
+ stream.next_in = (z_const Bytef *)source;
+ stream.avail_in = 0;
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ err = inflateInit(&stream);
+ if (err != Z_OK) return err;
+
+ stream.next_out = dest;
+ stream.avail_out = 0;
+
+ do {
+ if (stream.avail_out == 0) {
+ stream.avail_out = left > (uLong)max ? max : (uInt)left;
+ left -= stream.avail_out;
+ }
+ if (stream.avail_in == 0) {
+ stream.avail_in = len > (uLong)max ? max : (uInt)len;
+ len -= stream.avail_in;
+ }
+ err = inflate(&stream, Z_NO_FLUSH);
+ } while (err == Z_OK);
+
+ *sourceLen -= len + stream.avail_in;
+ if (dest != buf)
+ *destLen = stream.total_out;
+ else if (stream.total_out && err == Z_BUF_ERROR)
+ left = 1;
+
+ inflateEnd(&stream);
+ return err == Z_STREAM_END ? Z_OK :
+ err == Z_NEED_DICT ? Z_DATA_ERROR :
+ err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR :
+ err;
+}
+
+int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, const Bytef *source,
+ uLong sourceLen) {
+ return uncompress2(dest, destLen, source, &sourceLen);
+}
diff --git a/lib/zlib/zconf.h.in b/lib/zlib/zconf.h.in
new file mode 100644
index 0000000..ae34fee
--- /dev/null
+++ b/lib/zlib/zconf.h.in
@@ -0,0 +1,580 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/* The following four defines are enabled by sudo's configure script. */
+#undef HAVE_FALLTHROUGH_ATTRIBUTE
+#undef HAVE_DSO_VISIBILITY
+#undef HAVE_MEMCPY
+#undef HAVE_UNISTD_H
+#undef HAVE_VSNPRINTF
+#undef _FILE_OFFSET_BITS
+#undef _LARGE_FILES
+#undef const
+
+/* We build sudo and its libs with -fvisibility=hidden where supported. */
+#ifdef HAVE_DSO_VISIBILITY
+# if defined(__GNUC__)
+# define ZEXTERN extern __attribute__((__visibility__("default")))
+# elif defined(__SUNPRO_C)
+# define ZEXTERN extern __global
+# elif defined(ZLIB_INTERNAL)
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+#endif
+
+#ifdef HAVE_FALLTHROUGH_ATTRIBUTE
+# define ZFALLTHROUGH __attribute__((__fallthrough__))
+#else
+# define ZFALLTHROUGH do { } while (0)
+#endif
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
+ */
+#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
+# define Z_PREFIX_SET
+
+/* all linked symbols and init macros */
+# define _dist_code z__dist_code
+# define _length_code z__length_code
+# define _tr_align z__tr_align
+# define _tr_flush_bits z__tr_flush_bits
+# define _tr_flush_block z__tr_flush_block
+# define _tr_init z__tr_init
+# define _tr_stored_block z__tr_stored_block
+# define _tr_tally z__tr_tally
+# define adler32 z_adler32
+# define adler32_combine z_adler32_combine
+# define adler32_combine64 z_adler32_combine64
+# define adler32_z z_adler32_z
+# ifndef Z_SOLO
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# endif
+# define crc32 z_crc32
+# define crc32_combine z_crc32_combine
+# define crc32_combine64 z_crc32_combine64
+# define crc32_combine_gen z_crc32_combine_gen
+# define crc32_combine_gen64 z_crc32_combine_gen64
+# define crc32_combine_op z_crc32_combine_op
+# define crc32_z z_crc32_z
+# define deflate z_deflate
+# define deflateBound z_deflateBound
+# define deflateCopy z_deflateCopy
+# define deflateEnd z_deflateEnd
+# define deflateGetDictionary z_deflateGetDictionary
+# define deflateInit z_deflateInit
+# define deflateInit2 z_deflateInit2
+# define deflateInit2_ z_deflateInit2_
+# define deflateInit_ z_deflateInit_
+# define deflateParams z_deflateParams
+# define deflatePending z_deflatePending
+# define deflatePrime z_deflatePrime
+# define deflateReset z_deflateReset
+# define deflateResetKeep z_deflateResetKeep
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateSetHeader z_deflateSetHeader
+# define deflateTune z_deflateTune
+# define deflate_copyright z_deflate_copyright
+# define get_crc_table z_get_crc_table
+# ifndef Z_SOLO
+# define gz_error z_gz_error
+# define gz_intmax z_gz_intmax
+# define gz_strwinerror z_gz_strwinerror
+# define gzbuffer z_gzbuffer
+# define gzclearerr z_gzclearerr
+# define gzclose z_gzclose
+# define gzclose_r z_gzclose_r
+# define gzclose_w z_gzclose_w
+# define gzdirect z_gzdirect
+# define gzdopen z_gzdopen
+# define gzeof z_gzeof
+# define gzerror z_gzerror
+# define gzflush z_gzflush
+# define gzfread z_gzfread
+# define gzfwrite z_gzfwrite
+# define gzgetc z_gzgetc
+# define gzgetc_ z_gzgetc_
+# define gzgets z_gzgets
+# define gzoffset z_gzoffset
+# define gzoffset64 z_gzoffset64
+# define gzopen z_gzopen
+# define gzopen64 z_gzopen64
+# ifdef _WIN32
+# define gzopen_w z_gzopen_w
+# endif
+# define gzprintf z_gzprintf
+# define gzputc z_gzputc
+# define gzputs z_gzputs
+# define gzread z_gzread
+# define gzrewind z_gzrewind
+# define gzseek z_gzseek
+# define gzseek64 z_gzseek64
+# define gzsetparams z_gzsetparams
+# define gztell z_gztell
+# define gztell64 z_gztell64
+# define gzungetc z_gzungetc
+# define gzvprintf z_gzvprintf
+# define gzwrite z_gzwrite
+# endif
+# define inflate z_inflate
+# define inflateBack z_inflateBack
+# define inflateBackEnd z_inflateBackEnd
+# define inflateBackInit z_inflateBackInit
+# define inflateBackInit_ z_inflateBackInit_
+# define inflateCodesUsed z_inflateCodesUsed
+# define inflateCopy z_inflateCopy
+# define inflateEnd z_inflateEnd
+# define inflateGetDictionary z_inflateGetDictionary
+# define inflateGetHeader z_inflateGetHeader
+# define inflateInit z_inflateInit
+# define inflateInit2 z_inflateInit2
+# define inflateInit2_ z_inflateInit2_
+# define inflateInit_ z_inflateInit_
+# define inflateMark z_inflateMark
+# define inflatePrime z_inflatePrime
+# define inflateReset z_inflateReset
+# define inflateReset2 z_inflateReset2
+# define inflateResetKeep z_inflateResetKeep
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateUndermine z_inflateUndermine
+# define inflateValidate z_inflateValidate
+# define inflate_copyright z_inflate_copyright
+# define inflate_fast z_inflate_fast
+# define inflate_table z_inflate_table
+# ifndef Z_SOLO
+# define uncompress z_uncompress
+# define uncompress2 z_uncompress2
+# endif
+# define zError z_zError
+# ifndef Z_SOLO
+# define zcalloc z_zcalloc
+# define zcfree z_zcfree
+# endif
+# define zlibCompileFlags z_zlibCompileFlags
+# define zlibVersion z_zlibVersion
+
+/* all zlib typedefs in zlib.h and zconf.h */
+# define Byte z_Byte
+# define Bytef z_Bytef
+# define alloc_func z_alloc_func
+# define charf z_charf
+# define free_func z_free_func
+# ifndef Z_SOLO
+# define gzFile z_gzFile
+# endif
+# define gz_header z_gz_header
+# define gz_headerp z_gz_headerp
+# define in_func z_in_func
+# define intf z_intf
+# define out_func z_out_func
+# define uInt z_uInt
+# define uIntf z_uIntf
+# define uLong z_uLong
+# define uLongf z_uLongf
+# define voidp z_voidp
+# define voidpc z_voidpc
+# define voidpf z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+# define gz_header_s z_gz_header_s
+# define internal_state z_internal_state
+
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+#if defined(ZLIB_CONST) && !defined(z_const)
+# define z_const const
+#else
+# define z_const
+#endif
+
+#ifdef Z_SOLO
+# ifdef _WIN64
+ typedef unsigned long long z_size_t;
+# else
+ typedef unsigned long z_size_t;
+# endif
+#else
+# define z_longlong long long
+# if defined(NO_SIZE_T)
+ typedef unsigned NO_SIZE_T z_size_t;
+# elif defined(STDC)
+# include <stddef.h>
+ typedef size_t z_size_t;
+# else
+ typedef unsigned long z_size_t;
+# endif
+# undef z_longlong
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus about 7 kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+#ifndef Z_ARG /* function prototypes for stdarg */
+# if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# define Z_ARG(args) args
+# else
+# define Z_ARG(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+# include <limits.h>
+# if (UINT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned
+# elif (ULONG_MAX == 0xffffffffUL)
+# define Z_U4 unsigned long
+# elif (USHRT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned short
+# endif
+#endif
+
+#ifdef Z_U4
+ typedef Z_U4 z_crc_t;
+#else
+ typedef unsigned long z_crc_t;
+#endif
+
+#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
+# define Z_HAVE_UNISTD_H
+#endif
+
+#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */
+# define Z_HAVE_STDARG_H
+#endif
+
+#ifdef STDC
+# ifndef Z_SOLO
+# include <sys/types.h> /* for off_t */
+# endif
+#endif
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifndef Z_SOLO
+# include <stdarg.h> /* for va_list */
+# endif
+#endif
+
+#ifdef _WIN32
+# ifndef Z_SOLO
+# include <stddef.h> /* for wchar_t */
+# endif
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+# undef _LARGEFILE64_SOURCE
+#endif
+
+#ifndef Z_HAVE_UNISTD_H
+# ifdef __WATCOMC__
+# define Z_HAVE_UNISTD_H
+# endif
+#endif
+#ifndef Z_HAVE_UNISTD_H
+# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)
+# define Z_HAVE_UNISTD_H
+# endif
+#endif
+#ifndef Z_SOLO
+# if defined(Z_HAVE_UNISTD_H)
+# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
+# ifdef VMS
+# include <unixio.h> /* for off_t */
+# endif
+# ifndef z_off_t
+# define z_off_t off_t
+# endif
+# endif
+#endif
+
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
+# define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+# define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
+# define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if !defined(_WIN32) && defined(Z_LARGE64)
+# define z_off64_t off64_t
+#else
+# if defined(_WIN32) && !defined(__GNUC__)
+# define z_off64_t __int64
+# else
+# define z_off64_t z_off_t
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+ #pragma map(deflateInit_,"DEIN")
+ #pragma map(deflateInit2_,"DEIN2")
+ #pragma map(deflateEnd,"DEEND")
+ #pragma map(deflateBound,"DEBND")
+ #pragma map(inflateInit_,"ININ")
+ #pragma map(inflateInit2_,"ININ2")
+ #pragma map(inflateEnd,"INEND")
+ #pragma map(inflateSync,"INSY")
+ #pragma map(inflateSetDictionary,"INSEDI")
+ #pragma map(compressBound,"CMBND")
+ #pragma map(inflate_table,"INTABL")
+ #pragma map(inflate_fast,"INFA")
+ #pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/lib/zlib/zlib.exp b/lib/zlib/zlib.exp
new file mode 100644
index 0000000..8f43859
--- /dev/null
+++ b/lib/zlib/zlib.exp
@@ -0,0 +1,88 @@
+adler32
+adler32_combine
+adler32_combine64
+adler32_z
+compress
+compress2
+compressBound
+crc32
+crc32_combine
+crc32_combine64
+crc32_combine_gen
+crc32_combine_gen64
+crc32_combine_op
+crc32_z
+deflate
+deflateBound
+deflateCopy
+deflateEnd
+deflateGetDictionary
+deflateInit2_
+deflateInit_
+deflateParams
+deflatePending
+deflatePrime
+deflateReset
+deflateResetKeep
+deflateSetDictionary
+deflateSetHeader
+deflateTune
+get_crc_table
+gzbuffer
+gzclearerr
+gzclose
+gzclose_r
+gzclose_w
+gzdirect
+gzdopen
+gzeof
+gzerror
+gzflush
+gzfread
+gzfwrite
+gzgetc
+gzgetc_
+gzgets
+gzoffset
+gzoffset64
+gzopen
+gzopen64
+gzprintf
+gzputc
+gzputs
+gzread
+gzrewind
+gzseek
+gzseek64
+gzsetparams
+gztell
+gztell64
+gzungetc
+gzvprintf
+gzwrite
+inflate
+inflateBack
+inflateBackEnd
+inflateBackInit_
+inflateCodesUsed
+inflateCopy
+inflateEnd
+inflateGetDictionary
+inflateGetHeader
+inflateInit2_
+inflateInit_
+inflateMark
+inflatePrime
+inflateReset
+inflateReset2
+inflateResetKeep
+inflateSetDictionary
+inflateSync
+inflateSyncPoint
+inflateUndermine
+inflateValidate
+uncompress
+uncompress2
+zError
+zlibCompileFlags
+zlibVersion
diff --git a/lib/zlib/zlib.h b/lib/zlib/zlib.h
new file mode 100644
index 0000000..6b7244f
--- /dev/null
+++ b/lib/zlib/zlib.h
@@ -0,0 +1,1938 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.3, August 18th, 2023
+
+ Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
+ (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.3"
+#define ZLIB_VERNUM 0x1300
+#define ZLIB_VER_MAJOR 1
+#define ZLIB_VER_MINOR 3
+#define ZLIB_VER_REVISION 0
+#define ZLIB_VER_SUBREVISION 0
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed data.
+ This version of the library supports only one compression method (deflation)
+ but other algorithms will be added later and will have the same stream
+ interface.
+
+ Compression can be done in a single step if the buffers are large enough,
+ or can be done by repeated calls of the compression function. In the latter
+ case, the application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The compressed data format used by default by the in-memory functions is
+ the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+ around a deflate stream, which is itself documented in RFC 1951.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio using the functions that start
+ with "gz". The gzip format is different from the zlib format. gzip is a
+ gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+ This library can optionally read and write gzip and raw deflate streams in
+ memory as well.
+
+ The zlib format was designed to be compact and fast for use in memory
+ and on communications channels. The gzip format was designed for single-
+ file compression on file systems, has a larger header than zlib to maintain
+ directory information, and uses a different, slower check method than zlib.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never crash
+ even in the case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func)(voidpf opaque, uInt items, uInt size);
+typedef void (*free_func)(voidpf opaque, voidpf address);
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ z_const Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total number of input bytes read so far */
+
+ Bytef *next_out; /* next output byte will go here */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total number of bytes output so far */
+
+ z_const char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: binary or text
+ for deflate, or the decoding state for inflate */
+ uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ gzip header information passed to and from zlib routines. See RFC 1952
+ for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+ int text; /* true if compressed data believed to be text */
+ uLong time; /* modification time */
+ int xflags; /* extra flags (not used when writing a gzip file) */
+ int os; /* operating system */
+ Bytef *extra; /* pointer to extra field or Z_NULL if none */
+ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */
+ uInt extra_max; /* space at extra (only when reading header) */
+ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */
+ uInt name_max; /* space at name (only when reading header) */
+ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */
+ uInt comm_max; /* space at comment (only when reading header) */
+ int hcrc; /* true if there was or will be a header crc */
+ int done; /* true when done reading gzip header (not used
+ when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+ The application must update next_in and avail_in when avail_in has dropped
+ to zero. It must update next_out and avail_out when avail_out has dropped
+ to zero. The application must initialize zalloc, zfree and opaque before
+ calling the init function. All other fields are set by the compression
+ library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe. In that case, zlib is thread-safe. When zalloc and zfree are
+ Z_NULL on entry to the initialization function, they are set to internal
+ routines that use the standard library functions malloc() and free().
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this if
+ the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers
+ returned by zalloc for objects of exactly 65536 bytes *must* have their
+ offset normalized to zero. The default allocation function provided by this
+ library ensures this (see zutil.c). To reduce memory requirements and avoid
+ any allocation of 64K objects, at the expense of compression ratio, compile
+ the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or progress
+ reports. After compression, total_in holds the total size of the
+ uncompressed data and may be saved for use by the decompressor (particularly
+ if the decompressor wants to decompress everything in a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+#define Z_BLOCK 5
+#define Z_TREES 6
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_RLE 3
+#define Z_FIXED 4
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_TEXT 1
+#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field for deflate() */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+
+ /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion(void);
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is not
+ compatible with the zlib.h header file used by the application. This check
+ is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit(z_streamp strm, int level);
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller. If
+ zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
+ allocation functions. total_in, total_out, adler, and msg are initialized.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at all
+ (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION
+ requests a default compromise between speed and compression (currently
+ equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if level is not a valid compression level, or
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION). msg is set to null
+ if there is no error message. deflateInit does not perform any compression:
+ this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate(z_streamp strm, int flush);
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Generate more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary. Some output may be provided even if
+ flush is zero.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming more
+ output, and updating avail_in or avail_out accordingly; avail_out should
+ never be zero before the call. The application can consume the compressed
+ output when it wants, for example when the output buffer is full (avail_out
+ == 0), or after each call of deflate(). If deflate returns Z_OK and with
+ zero avail_out, it must be called again after making room in the output
+ buffer because there might be more output pending. See deflatePending(),
+ which can be used if desired to determine whether or not there is more output
+ in that case.
+
+ Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+ decide how much data to accumulate before producing output, in order to
+ maximize compression.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In
+ particular avail_in is zero after the call if enough output space has been
+ provided before the call.) Flushing may degrade compression for some
+ compression algorithms and so it should be used only when necessary. This
+ completes the current deflate block and follows it with an empty stored block
+ that is three bits plus filler bits to the next byte, followed by four bytes
+ (00 00 ff ff).
+
+ If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
+ output buffer, but the output is not aligned to a byte boundary. All of the
+ input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
+ This completes the current deflate block and follows it with an empty fixed
+ codes block that is 10 bits long. This assures that enough bytes are output
+ in order for the decompressor to finish the block before the empty fixed
+ codes block.
+
+ If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
+ for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
+ seven bits of the current block are held to be written as the next byte after
+ the next deflate block is completed. In this case, the decompressor may not
+ be provided enough bits at this point in order to complete decompression of
+ the data provided so far to the compressor. It may need to wait for the next
+ block to be emitted. This is for advanced applications that need to control
+ the emission of deflate blocks.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+ avail_out is greater than six when the flush marker begins, in order to avoid
+ repeated flush markers upon calling deflate() again when avail_out == 0.
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there was
+ enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this
+ function must be called again with Z_FINISH and more output space (updated
+ avail_out) but no more input data, until it returns with Z_STREAM_END or an
+ error. After deflate has returned Z_STREAM_END, the only possible operations
+ on the stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used in the first deflate call after deflateInit if all the
+ compression is to be done in a single step. In order to complete in one
+ call, avail_out must be at least the value returned by deflateBound (see
+ below). Then deflate is guaranteed to return Z_STREAM_END. If not enough
+ output space is provided, deflate will not return Z_STREAM_END, and it must
+ be called again as described above.
+
+ deflate() sets strm->adler to the Adler-32 checksum of all input read
+ so far (that is, total_in bytes). If a gzip stream is being generated, then
+ strm->adler will be the CRC-32 checksum of the input read so far. (See
+ deflateInit2 below.)
+
+ deflate() may update strm->data_type if it can make a good guess about
+ the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is
+ considered binary. This field is only for information purposes and does not
+ affect the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was Z_NULL or the state was inadvertently written over
+ by the application), or Z_BUF_ERROR if no progress is possible (for example
+ avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and
+ deflate() can be called again with more input and more output space to
+ continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd(z_streamp strm);
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any pending
+ output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case, msg
+ may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit(z_streamp strm);
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. In the current version of inflate, the provided input is not
+ read or consumed. The allocation of a sliding window will be deferred to
+ the first call of inflate (if the decompression does not complete on the
+ first call). If zalloc and zfree are set to Z_NULL, inflateInit updates
+ them to use default allocation functions. total_in, total_out, adler, and
+ msg are initialized.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+ invalid, such as a null pointer to the structure. msg is set to null if
+ there is no error message. inflateInit does not perform any decompression.
+ Actual decompression will be done by inflate(). So next_in, and avail_in,
+ next_out, and avail_out are unused and unchanged. The current
+ implementation of inflateInit() does not process any header information --
+ that is deferred until inflate() is called.
+*/
+
+
+ZEXTERN int ZEXPORT inflate(z_streamp strm, int flush);
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), then next_in and avail_in are updated
+ accordingly, and processing will resume at this point for the next call of
+ inflate().
+
+ - Generate more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there is
+ no more input data or no more space in the output buffer (see below about
+ the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming more
+ output, and updating the next_* and avail_* values accordingly. If the
+ caller of inflate() does not provide both available input and available
+ output space, it is possible that there will be no progress made. The
+ application can consume the uncompressed output when it wants, for example
+ when the output buffer is full (avail_out == 0), or after each call of
+ inflate(). If inflate returns Z_OK and with zero avail_out, it must be
+ called again after making room in the output buffer because there might be
+ more output pending.
+
+ The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
+ Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much
+ output as possible to the output buffer. Z_BLOCK requests that inflate()
+ stop if and when it gets to the next deflate block boundary. When decoding
+ the zlib or gzip format, this will cause inflate() to return immediately
+ after the header and before the first block. When doing a raw inflate,
+ inflate() will go ahead and process the first block, and will return when it
+ gets to the end of that block, or when it runs out of data.
+
+ The Z_BLOCK option assists in appending to or combining deflate streams.
+ To assist in this, on return inflate() always sets strm->data_type to the
+ number of unused bits in the last byte taken from strm->next_in, plus 64 if
+ inflate() is currently decoding the last block in the deflate stream, plus
+ 128 if inflate() returned immediately after decoding an end-of-block code or
+ decoding the complete header up to just before the first byte of the deflate
+ stream. The end-of-block will not be indicated until all of the uncompressed
+ data from that block has been written to strm->next_out. The number of
+ unused bits may in general be greater than seven, except when bit 7 of
+ data_type is set, in which case the number of unused bits will be less than
+ eight. data_type is set as noted here every time inflate() returns for all
+ flush options, and so can be used to determine the amount of currently
+ consumed input in bits.
+
+ The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
+ end of each deflate block header is reached, before any actual data in that
+ block is decoded. This allows the caller to determine the length of the
+ deflate block header for later use in random access within a deflate block.
+ 256 is added to the value of strm->data_type when inflate() returns
+ immediately after reaching the end of the deflate block header.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step (a
+ single call of inflate), the parameter flush should be set to Z_FINISH. In
+ this case all pending input is processed and all pending output is flushed;
+ avail_out must be large enough to hold all of the uncompressed data for the
+ operation to complete. (The size of the uncompressed data may have been
+ saved by the compressor for this purpose.) The use of Z_FINISH is not
+ required to perform an inflation in one step. However it may be used to
+ inform inflate that a faster approach can be used for the single inflate()
+ call. Z_FINISH also informs inflate to not maintain a sliding window if the
+ stream completes, which reduces inflate's memory footprint. If the stream
+ does not complete, either because not all of the stream is provided or not
+ enough output space is provided, then a sliding window will be allocated and
+ inflate() can be called again to continue the operation as if Z_NO_FLUSH had
+ been used.
+
+ In this implementation, inflate() always flushes as much output as
+ possible to the output buffer, and always uses the faster approach on the
+ first call. So the effects of the flush parameter in this implementation are
+ on the return value of inflate() as noted below, when inflate() returns early
+ when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
+ memory for a sliding window when Z_FINISH is used.
+
+ If a preset dictionary is needed after this call (see inflateSetDictionary
+ below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
+ chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+ strm->adler to the Adler-32 checksum of all output produced so far (that is,
+ total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+ below. At the end of the stream, inflate() checks that its computed Adler-32
+ checksum is equal to that saved by the compressor and returns Z_STREAM_END
+ only if the checksum is correct.
+
+ inflate() can decompress and check either zlib-wrapped or gzip-wrapped
+ deflate data. The header type is detected automatically, if requested when
+ initializing with inflateInit2(). Any information contained in the gzip
+ header is not retained unless inflateGetHeader() is used. When processing
+ gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
+ produced so far. The CRC-32 is checked against the gzip trailer, as is the
+ uncompressed length, modulo 2^32.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect check
+ value, in which case strm->msg points to a string with a more specific
+ error), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+ next_in or next_out was Z_NULL, or the state was inadvertently written over
+ by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR
+ if no progress was possible or if there was not enough room in the output
+ buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+ inflate() can be called again with more input and more output space to
+ continue decompressing. If Z_DATA_ERROR is returned, the application may
+ then call inflateSync() to look for a good compression block if a partial
+ recovery of the data is to be attempted.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd(z_streamp strm);
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any pending
+ output.
+
+ inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state
+ was inconsistent.
+*/
+
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2(z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy);
+
+ This is another version of deflateInit with more compression options. The
+ fields zalloc, zfree and opaque must be initialized before by the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ For the current implementation of deflate(), a windowBits value of 8 (a
+ window size of 256 bytes) is not supported. As a result, a request for 8
+ will result in 9 (a 512-byte window). In that case, providing 8 to
+ inflateInit2() will result in an error when the zlib header with 9 is
+ checked against the initialization of inflate(). The remedy is to not use 8
+ with deflateInit2() with this initialization, or at least in that case use 9
+ with inflateInit2().
+
+ windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+ determines the window size. deflate() will then generate raw deflate data
+ with no zlib header or trailer, and will not compute a check value.
+
+ windowBits can also be greater than 15 for optional gzip encoding. Add
+ 16 to windowBits to write a simple gzip header and trailer around the
+ compressed data instead of a zlib wrapper. The gzip header will have no
+ file name, no extra data, no comment, no modification time (set to zero), no
+ header crc, and the operating system will be set to the appropriate value,
+ if the operating system was determined at compile time. If a gzip stream is
+ being written, strm->adler is a CRC-32 instead of an Adler-32.
+
+ For raw deflate or gzip encoding, a request for a 256-byte window is
+ rejected as invalid, since only the zlib header provides a means of
+ transmitting the window size to the decompressor.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but is
+ slow and reduces compression ratio; memLevel=9 uses maximum memory for
+ optimal speed. The default value is 8. See zconf.h for total memory usage
+ as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match), or Z_RLE to limit match distances to one (run-length
+ encoding). Filtered data consists mostly of small values with a somewhat
+ random distribution. In this case, the compression algorithm is tuned to
+ compress them better. The effect of Z_FILTERED is to force more Huffman
+ coding and less string matching; it is somewhat intermediate between
+ Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as
+ fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The
+ strategy parameter only affects the compression ratio but not the
+ correctness of the compressed output even if it is not set appropriately.
+ Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
+ decoder for special applications.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
+ method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
+ incompatible with the version assumed by the caller (ZLIB_VERSION). msg is
+ set to null if there is no error message. deflateInit2 does not perform any
+ compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary(z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength);
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. When using the zlib format, this
+ function must be called immediately after deflateInit, deflateInit2 or
+ deflateReset, and before any call of deflate. When doing raw deflate, this
+ function must be called either before any call of deflate, or immediately
+ after the completion of a deflate block, i.e. after all input has been
+ consumed and all output has been delivered when using any of the flush
+ options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The
+ compressor and decompressor must use exactly the same dictionary (see
+ inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size
+ provided in deflateInit or deflateInit2. Thus the strings most likely to be
+ useful should be put at the end of the dictionary, not at the front. In
+ addition, the current implementation of deflate will use at most the window
+ size minus 262 bytes of the provided dictionary.
+
+ Upon return of this function, strm->adler is set to the Adler-32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The Adler-32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.) If a raw deflate was requested, then the
+ Adler-32 value is not computed and strm->adler is not set.
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if not at a block boundary for raw deflate). deflateSetDictionary does
+ not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateGetDictionary(z_streamp strm,
+ Bytef *dictionary,
+ uInt *dictLength);
+/*
+ Returns the sliding dictionary being maintained by deflate. dictLength is
+ set to the number of bytes in the dictionary, and that many bytes are copied
+ to dictionary. dictionary must have enough space, where 32768 bytes is
+ always enough. If deflateGetDictionary() is called with dictionary equal to
+ Z_NULL, then only the dictionary length is returned, and nothing is copied.
+ Similarly, if dictLength is Z_NULL, then it is not set.
+
+ deflateGetDictionary() may return a length less than the window size, even
+ when more than the window size in input has been provided. It may return up
+ to 258 bytes less in that case, due to how zlib's implementation of deflate
+ manages the sliding window and lookahead for matches, where matches can be
+ up to 258 bytes long. If the application needs the last window-size bytes of
+ input, then that would need to be saved by the application outside of zlib.
+
+ deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+ stream state is inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateCopy(z_streamp dest,
+ z_streamp source);
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and can
+ consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being Z_NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset(z_streamp strm);
+/*
+ This function is equivalent to deflateEnd followed by deflateInit, but
+ does not free and reallocate the internal compression state. The stream
+ will leave the compression level and any other attributes that may have been
+ set unchanged. total_in, total_out, adler, and msg are initialized.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams(z_streamp strm,
+ int level,
+ int strategy);
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2(). This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different strategy.
+ If the compression approach (which is a function of the level) or the
+ strategy is changed, and if there have been any deflate() calls since the
+ state was initialized or reset, then the input available so far is
+ compressed with the old level and strategy using deflate(strm, Z_BLOCK).
+ There are three approaches for the compression levels 0, 1..3, and 4..9
+ respectively. The new level and strategy will take effect at the next call
+ of deflate().
+
+ If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does
+ not have enough output space to complete, then the parameter change will not
+ take effect. In this case, deflateParams() can be called again with the
+ same parameters and more output space to try again.
+
+ In order to assure a change in the parameters on the first try, the
+ deflate stream should be flushed using deflate() with Z_BLOCK or other flush
+ request until strm.avail_out is not zero, before calling deflateParams().
+ Then no more input data should be provided before the deflateParams() call.
+ If this is done, the old level and strategy will be applied to the data
+ compressed before deflateParams(), and the new level and strategy will be
+ applied to the data compressed after deflateParams().
+
+ deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream
+ state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if
+ there was not enough output space to complete the compression of the
+ available input data before a change in the strategy or approach. Note that
+ in the case of a Z_BUF_ERROR, the parameters are not changed. A return
+ value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be
+ retried with more output space.
+*/
+
+ZEXTERN int ZEXPORT deflateTune(z_streamp strm,
+ int good_length,
+ int max_lazy,
+ int nice_length,
+ int max_chain);
+/*
+ Fine tune deflate's internal compression parameters. This should only be
+ used by someone who understands the algorithm used by zlib's deflate for
+ searching for the best matching string, and even then only by the most
+ fanatic optimizer trying to squeeze out the last compressed bit for their
+ specific input data. Read the deflate.c source code for the meaning of the
+ max_lazy, good_length, nice_length, and max_chain parameters.
+
+ deflateTune() can be called after deflateInit() or deflateInit2(), and
+ returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm,
+ uLong sourceLen);
+/*
+ deflateBound() returns an upper bound on the compressed size after
+ deflation of sourceLen bytes. It must be called after deflateInit() or
+ deflateInit2(), and after deflateSetHeader(), if used. This would be used
+ to allocate an output buffer for deflation in a single pass, and so would be
+ called before deflate(). If that first deflate() call is provided the
+ sourceLen input bytes, an output buffer allocated to the size returned by
+ deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
+ to return Z_STREAM_END. Note that it is possible for the compressed size to
+ be larger than the value returned by deflateBound() if flush options other
+ than Z_FINISH or Z_NO_FLUSH are used.
+*/
+
+ZEXTERN int ZEXPORT deflatePending(z_streamp strm,
+ unsigned *pending,
+ int *bits);
+/*
+ deflatePending() returns the number of bytes and bits of output that have
+ been generated, but not yet provided in the available output. The bytes not
+ provided would be due to the available output space having being consumed.
+ The number of bits of output not provided are between 0 and 7, where they
+ await more bits to join them in order to fill out a full byte. If pending
+ or bits are Z_NULL, then those values are not set.
+
+ deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+ */
+
+ZEXTERN int ZEXPORT deflatePrime(z_streamp strm,
+ int bits,
+ int value);
+/*
+ deflatePrime() inserts bits in the deflate output stream. The intent
+ is that this function is used to start off the deflate output with the bits
+ leftover from a previous deflate stream when appending to it. As such, this
+ function can only be used for raw deflate, and must be used before the first
+ deflate() call after a deflateInit2() or deflateReset(). bits must be less
+ than or equal to 16, and that many of the least significant bits of value
+ will be inserted in the output.
+
+ deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
+ room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
+ source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader(z_streamp strm,
+ gz_headerp head);
+/*
+ deflateSetHeader() provides gzip header information for when a gzip
+ stream is requested by deflateInit2(). deflateSetHeader() may be called
+ after deflateInit2() or deflateReset() and before the first call of
+ deflate(). The text, time, os, extra field, name, and comment information
+ in the provided gz_header structure are written to the gzip header (xflag is
+ ignored -- the extra flags are set according to the compression level). The
+ caller must assure that, if not Z_NULL, name and comment are terminated with
+ a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+ available there. If hcrc is true, a gzip header crc is included. Note that
+ the current versions of the command-line version of gzip (up through version
+ 1.3.x) do not support header crc's, and will report that it is a "multi-part
+ gzip file" and give up.
+
+ If deflateSetHeader is not used, the default gzip header has text false,
+ the time set to zero, and os set to the current operating system, with no
+ extra, name, or comment fields. The gzip header is returned to the default
+ state by deflateReset().
+
+ deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2(z_streamp strm,
+ int windowBits);
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. windowBits must be greater than or equal to the windowBits value
+ provided to deflateInit2() while compressing, or it must be equal to 15 if
+ deflateInit2() was not used. If a compressed stream with a larger window
+ size is given as input, inflate() will return with the error code
+ Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ windowBits can also be zero to request that inflate use the window size in
+ the zlib header of the compressed stream.
+
+ windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+ determines the window size. inflate() will then process raw deflate data,
+ not looking for a zlib or gzip header, not generating a check value, and not
+ looking for any check values for comparison at the end of the stream. This
+ is for use with other formats that use the deflate compressed data format
+ such as zip. Those formats provide their own check values. If a custom
+ format is developed using the raw deflate format for compressed data, it is
+ recommended that a check value such as an Adler-32 or a CRC-32 be applied to
+ the uncompressed data as is done in the zlib, gzip, and zip formats. For
+ most applications, the zlib format should be used as is. Note that comments
+ above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+ windowBits can also be greater than 15 for optional gzip decoding. Add
+ 32 to windowBits to enable zlib and gzip decoding with automatic header
+ detection, or add 16 to decode only the gzip format (the zlib format will
+ return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a
+ CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see
+ below), inflate() will *not* automatically decode concatenated gzip members.
+ inflate() will return Z_STREAM_END at the end of the gzip member. The state
+ would need to be reset to continue decoding a subsequent gzip member. This
+ *must* be done if there is more data after a gzip member, in order for the
+ decompression to be compliant with the gzip standard (RFC 1952).
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+ invalid, such as a null pointer to the structure. msg is set to null if
+ there is no error message. inflateInit2 does not perform any decompression
+ apart from possibly reading the zlib header if present: actual decompression
+ will be done by inflate(). (So next_in and avail_in may be modified, but
+ next_out and avail_out are unused and unchanged.) The current implementation
+ of inflateInit2() does not process any header information -- that is
+ deferred until inflate() is called.
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary(z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength);
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate,
+ if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the Adler-32 value returned by that call of inflate.
+ The compressor and decompressor must use exactly the same dictionary (see
+ deflateSetDictionary). For raw inflate, this function can be called at any
+ time to set the dictionary. If the provided dictionary is smaller than the
+ window and there is already data in the window, then the provided dictionary
+ will amend what's there. The application must insure that the dictionary
+ that was used for compression is provided.
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect Adler-32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateGetDictionary(z_streamp strm,
+ Bytef *dictionary,
+ uInt *dictLength);
+/*
+ Returns the sliding dictionary being maintained by inflate. dictLength is
+ set to the number of bytes in the dictionary, and that many bytes are copied
+ to dictionary. dictionary must have enough space, where 32768 bytes is
+ always enough. If inflateGetDictionary() is called with dictionary equal to
+ Z_NULL, then only the dictionary length is returned, and nothing is copied.
+ Similarly, if dictLength is Z_NULL, then it is not set.
+
+ inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+ stream state is inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateSync(z_streamp strm);
+/*
+ Skips invalid compressed data until a possible full flush point (see above
+ for the description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync searches for a 00 00 FF FF pattern in the compressed data.
+ All full flush points have this pattern, but not all occurrences of this
+ pattern are full flush points.
+
+ inflateSync returns Z_OK if a possible full flush point has been found,
+ Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
+ has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
+ In the success case, the application may save the current current value of
+ total_in which indicates where valid compressed data was found. In the
+ error case, the application may repeatedly call inflateSync, providing more
+ input each time, until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy(z_streamp dest,
+ z_streamp source);
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when randomly accessing a large stream. The
+ first pass through the stream can periodically record the inflate state,
+ allowing restarting inflate at those points when randomly accessing the
+ stream.
+
+ inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being Z_NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset(z_streamp strm);
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate the internal decompression state. The
+ stream will keep attributes that may have been set by inflateInit2.
+ total_in, total_out, adler, and msg are initialized.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT inflateReset2(z_streamp strm,
+ int windowBits);
+/*
+ This function is the same as inflateReset, but it also permits changing
+ the wrap and window size requests. The windowBits parameter is interpreted
+ the same as it is for inflateInit2. If the window size is changed, then the
+ memory allocated for the window is freed, and the window will be reallocated
+ by inflate() if needed.
+
+ inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL), or if
+ the windowBits parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT inflatePrime(z_streamp strm,
+ int bits,
+ int value);
+/*
+ This function inserts bits in the inflate input stream. The intent is
+ that this function is used to start inflating at a bit position in the
+ middle of a byte. The provided bits will be used before any bytes are used
+ from next_in. This function should only be used with raw inflate, and
+ should be used before the first inflate() call after inflateInit2() or
+ inflateReset(). bits must be less than or equal to 16, and that many of the
+ least significant bits of value will be inserted in the input.
+
+ If bits is negative, then the input stream bit buffer is emptied. Then
+ inflatePrime() can be called again to put bits in the buffer. This is used
+ to clear out bits leftover after feeding inflate a block description prior
+ to feeding inflate codes.
+
+ inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN long ZEXPORT inflateMark(z_streamp strm);
+/*
+ This function returns two values, one in the lower 16 bits of the return
+ value, and the other in the remaining upper bits, obtained by shifting the
+ return value down 16 bits. If the upper value is -1 and the lower value is
+ zero, then inflate() is currently decoding information outside of a block.
+ If the upper value is -1 and the lower value is non-zero, then inflate is in
+ the middle of a stored block, with the lower value equaling the number of
+ bytes from the input remaining to copy. If the upper value is not -1, then
+ it is the number of bits back from the current bit position in the input of
+ the code (literal or length/distance pair) currently being processed. In
+ that case the lower value is the number of bytes already emitted for that
+ code.
+
+ A code is being processed if inflate is waiting for more input to complete
+ decoding of the code, or if it has completed decoding but is waiting for
+ more output space to write the literal or match data.
+
+ inflateMark() is used to mark locations in the input data for random
+ access, which may be at bit positions, and to note those cases where the
+ output of a code may span boundaries of random access blocks. The current
+ location in the input stream can be determined from avail_in and data_type
+ as noted in the description for the Z_BLOCK flush parameter for inflate.
+
+ inflateMark returns the value noted above, or -65536 if the provided
+ source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader(z_streamp strm,
+ gz_headerp head);
+/*
+ inflateGetHeader() requests that gzip header information be stored in the
+ provided gz_header structure. inflateGetHeader() may be called after
+ inflateInit2() or inflateReset(), and before the first call of inflate().
+ As inflate() processes the gzip stream, head->done is zero until the header
+ is completed, at which time head->done is set to one. If a zlib stream is
+ being decoded, then head->done is set to -1 to indicate that there will be
+ no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be
+ used to force inflate() to return immediately after header processing is
+ complete and before any actual data is decompressed.
+
+ The text, time, xflags, and os fields are filled in with the gzip header
+ contents. hcrc is set to true if there is a header CRC. (The header CRC
+ was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+ contains the maximum number of bytes to write to extra. Once done is true,
+ extra_len contains the actual extra field length, and extra contains the
+ extra field, or that field truncated if extra_max is less than extra_len.
+ If name is not Z_NULL, then up to name_max characters are written there,
+ terminated with a zero unless the length is greater than name_max. If
+ comment is not Z_NULL, then up to comm_max characters are written there,
+ terminated with a zero unless the length is greater than comm_max. When any
+ of extra, name, or comment are not Z_NULL and the respective field is not
+ present in the header, then that field is set to Z_NULL to signal its
+ absence. This allows the use of deflateSetHeader() with the returned
+ structure to duplicate the header. However if those fields are set to
+ allocated memory, then the application will need to save those pointers
+ elsewhere so that they can be eventually freed.
+
+ If inflateGetHeader is not used, then the header information is simply
+ discarded. The header is always checked for validity, including the header
+ CRC if present. inflateReset() will reset the process to discard the header
+ information. The application would need to call inflateGetHeader() again to
+ retrieve the header from the next gzip stream.
+
+ inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit(z_streamp strm, int windowBits,
+ unsigned char FAR *window);
+
+ Initialize the internal stream state for decompression using inflateBack()
+ calls. The fields zalloc, zfree and opaque in strm must be initialized
+ before the call. If zalloc and zfree are Z_NULL, then the default library-
+ derived memory allocation routines are used. windowBits is the base two
+ logarithm of the window size, in the range 8..15. window is a caller
+ supplied buffer of that size. Except for special applications where it is
+ assured that deflate was used with small window sizes, windowBits must be 15
+ and a 32K byte window must be supplied to be able to decompress general
+ deflate streams.
+
+ See inflateBack() for the usage of these routines.
+
+ inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+ the parameters are invalid, Z_MEM_ERROR if the internal state could not be
+ allocated, or Z_VERSION_ERROR if the version of the library does not match
+ the version of the header file.
+*/
+
+typedef unsigned (*in_func)(void FAR *,
+ z_const unsigned char FAR * FAR *);
+typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned);
+
+ZEXTERN int ZEXPORT inflateBack(z_streamp strm,
+ in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc);
+/*
+ inflateBack() does a raw inflate with a single call using a call-back
+ interface for input and output. This is potentially more efficient than
+ inflate() for file i/o applications, in that it avoids copying between the
+ output and the sliding window by simply making the window itself the output
+ buffer. inflate() can be faster on modern CPUs when used with large
+ buffers. inflateBack() trusts the application to not change the output
+ buffer passed by the output function, at least until inflateBack() returns.
+
+ inflateBackInit() must be called first to allocate the internal state
+ and to initialize the state with the user-provided window buffer.
+ inflateBack() may then be used multiple times to inflate a complete, raw
+ deflate stream with each call. inflateBackEnd() is then called to free the
+ allocated state.
+
+ A raw deflate stream is one with no zlib or gzip header or trailer.
+ This routine would normally be used in a utility that reads zip or gzip
+ files and writes out uncompressed files. The utility would decode the
+ header and process the trailer on its own, hence this routine expects only
+ the raw deflate stream to decompress. This is different from the default
+ behavior of inflate(), which expects a zlib header and trailer around the
+ deflate stream.
+
+ inflateBack() uses two subroutines supplied by the caller that are then
+ called by inflateBack() for input and output. inflateBack() calls those
+ routines until it reads a complete deflate stream and writes out all of the
+ uncompressed data, or until it encounters an error. The function's
+ parameters and return types are defined above in the in_func and out_func
+ typedefs. inflateBack() will call in(in_desc, &buf) which should return the
+ number of bytes of provided input, and a pointer to that input in buf. If
+ there is no input available, in() must return zero -- buf is ignored in that
+ case -- and inflateBack() will return a buffer error. inflateBack() will
+ call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].
+ out() should return zero on success, or non-zero on failure. If out()
+ returns non-zero, inflateBack() will return with an error. Neither in() nor
+ out() are permitted to change the contents of the window provided to
+ inflateBackInit(), which is also the buffer that out() uses to write from.
+ The length written by out() will be at most the window size. Any non-zero
+ amount of input may be provided by in().
+
+ For convenience, inflateBack() can be provided input on the first call by
+ setting strm->next_in and strm->avail_in. If that input is exhausted, then
+ in() will be called. Therefore strm->next_in must be initialized before
+ calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called
+ immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in
+ must also be initialized, and then if strm->avail_in is not zero, input will
+ initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+ The in_desc and out_desc parameters of inflateBack() is passed as the
+ first parameter of in() and out() respectively when they are called. These
+ descriptors can be optionally used to pass any information that the caller-
+ supplied in() and out() functions need to do their job.
+
+ On return, inflateBack() will set strm->next_in and strm->avail_in to
+ pass back any unused input that was provided by the last in() call. The
+ return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+ if in() or out() returned an error, Z_DATA_ERROR if there was a format error
+ in the deflate stream (in which case strm->msg is set to indicate the nature
+ of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
+ In the case of Z_BUF_ERROR, an input or output error can be distinguished
+ using strm->next_in which will be Z_NULL only if in() returned an error. If
+ strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
+ non-zero. (in() will always be called before out(), so strm->next_in is
+ assured to be defined if out() returns non-zero.) Note that inflateBack()
+ cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd(z_streamp strm);
+/*
+ All memory allocated by inflateBackInit() is freed.
+
+ inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+ state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags(void);
+/* Return flags indicating compile-time options.
+
+ Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+ 1.0: size of uInt
+ 3.2: size of uLong
+ 5.4: size of voidpf (pointer)
+ 7.6: size of z_off_t
+
+ Compiler, assembler, and debug options:
+ 8: ZLIB_DEBUG
+ 9: ASMV or ASMINF -- use ASM code
+ 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+ 11: 0 (reserved)
+
+ One-time table building (smaller code, but not thread-safe if true):
+ 12: BUILDFIXED -- build static block decoding tables when needed
+ 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+ 14,15: 0 (reserved)
+
+ Library content (indicates missing functionality):
+ 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+ deflate code when not needed)
+ 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+ and decode gzip streams (to avoid linking crc code)
+ 18-19: 0 (reserved)
+
+ Operation variations (changes in library functionality):
+ 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+ 21: FASTEST -- deflate algorithm with only one, lowest compression level
+ 22,23: 0 (reserved)
+
+ The sprintf variant used by gzprintf (zero is best):
+ 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+ 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+ 26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+ Remainder:
+ 27-31: 0 (reserved)
+ */
+
+#ifndef Z_SOLO
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the basic
+ stream-oriented functions. To simplify the interface, some default options
+ are assumed (compression level and memory usage, standard memory allocation
+ functions). The source code of these utility functions can be modified if
+ you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress(Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen);
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total size
+ of the destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed data. compress() is equivalent to compress2() with a level
+ parameter of Z_DEFAULT_COMPRESSION.
+
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2(Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level);
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed data.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound(uLong sourceLen);
+/*
+ compressBound() returns an upper bound on the compressed size after
+ compress() or compress2() on sourceLen bytes. It would be used before a
+ compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress(Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen);
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total size
+ of the destination buffer, which must be large enough to hold the entire
+ uncompressed data. (The size of the uncompressed data must have been saved
+ previously by the compressor and transmitted to the decompressor by some
+ mechanism outside the scope of this compression library.) Upon exit, destLen
+ is the actual size of the uncompressed data.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In
+ the case where there is not enough room, uncompress() will fill the output
+ buffer with the uncompressed data up to that point.
+*/
+
+ZEXTERN int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong *sourceLen);
+/*
+ Same as uncompress, except that sourceLen is a pointer, where the
+ length of the source is *sourceLen. On return, *sourceLen is the number of
+ source bytes consumed.
+*/
+
+ /* gzip file access functions */
+
+/*
+ This library supports reading and writing files in gzip (.gz) format with
+ an interface similar to that of stdio, using the functions that start with
+ "gz". The gzip format is different from the zlib format. gzip is a gzip
+ wrapper, documented in RFC 1952, wrapped around a deflate stream.
+*/
+
+typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */
+
+/*
+ZEXTERN gzFile ZEXPORT gzopen(const char *path, const char *mode);
+
+ Open the gzip (.gz) file at path for reading and decompressing, or
+ compressing and writing. The mode parameter is as in fopen ("rb" or "wb")
+ but can also include a compression level ("wb9") or a strategy: 'f' for
+ filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h",
+ 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression
+ as in "wb9F". (See the description of deflateInit2 for more information
+ about the strategy parameter.) 'T' will request transparent writing or
+ appending with no compression and not using the gzip format.
+
+ "a" can be used instead of "w" to request that the gzip stream that will
+ be written be appended to the file. "+" will result in an error, since
+ reading and writing to the same gzip file is not supported. The addition of
+ "x" when writing will create the file exclusively, which fails if the file
+ already exists. On systems that support it, the addition of "e" when
+ reading or writing will set the flag to close the file on an execve() call.
+
+ These functions, as well as gzip, will read and decode a sequence of gzip
+ streams in a file. The append function of gzopen() can be used to create
+ such a file. (Also see gzflush() for another way to do this.) When
+ appending, gzopen does not test whether the file begins with a gzip stream,
+ nor does it look for the end of the gzip streams to begin appending. gzopen
+ will simply append a gzip stream to the existing file.
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression. When
+ reading, this will be detected automatically by looking for the magic two-
+ byte gzip header.
+
+ gzopen returns NULL if the file could not be opened, if there was
+ insufficient memory to allocate the gzFile state, or if an invalid mode was
+ specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
+ errno can be checked to determine if the reason gzopen failed was that the
+ file could not be opened.
+*/
+
+ZEXTERN gzFile ZEXPORT gzdopen(int fd, const char *mode);
+/*
+ Associate a gzFile with the file descriptor fd. File descriptors are
+ obtained from calls like open, dup, creat, pipe or fileno (if the file has
+ been previously opened with fopen). The mode parameter is as in gzopen.
+
+ The next call of gzclose on the returned gzFile will also close the file
+ descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
+ fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
+ mode);. The duplicated descriptor should be saved to avoid a leak, since
+ gzdopen does not close fd if it fails. If you are using fileno() to get the
+ file descriptor from a FILE *, then you will have to use dup() to avoid
+ double-close()ing the file descriptor. Both gzclose() and fclose() will
+ close the associated file descriptor, so they need to have different file
+ descriptors.
+
+ gzdopen returns NULL if there was insufficient memory to allocate the
+ gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
+ provided, or '+' was provided), or if fd is -1. The file descriptor is not
+ used until the next gz* read, write, seek, or close operation, so gzdopen
+ will not detect if fd is invalid (unless fd is -1).
+*/
+
+ZEXTERN int ZEXPORT gzbuffer(gzFile file, unsigned size);
+/*
+ Set the internal buffer size used by this library's functions for file to
+ size. The default buffer size is 8192 bytes. This function must be called
+ after gzopen() or gzdopen(), and before any other calls that read or write
+ the file. The buffer memory allocation is always deferred to the first read
+ or write. Three times that size in buffer space is allocated. A larger
+ buffer size of, for example, 64K or 128K bytes will noticeably increase the
+ speed of decompression (reading).
+
+ The new buffer size also affects the maximum length for gzprintf().
+
+ gzbuffer() returns 0 on success, or -1 on failure, such as being called
+ too late.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams(gzFile file, int level, int strategy);
+/*
+ Dynamically update the compression level and strategy for file. See the
+ description of deflateInit2 for the meaning of these parameters. Previously
+ provided data is flushed before applying the parameter changes.
+
+ gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not
+ opened for writing, Z_ERRNO if there is an error writing the flushed data,
+ or Z_MEM_ERROR if there is a memory allocation error.
+*/
+
+ZEXTERN int ZEXPORT gzread(gzFile file, voidp buf, unsigned len);
+/*
+ Read and decompress up to len uncompressed bytes from file into buf. If
+ the input file is not in gzip format, gzread copies the given number of
+ bytes into the buffer directly from the file.
+
+ After reaching the end of a gzip stream in the input, gzread will continue
+ to read, looking for another gzip stream. Any number of gzip streams may be
+ concatenated in the input file, and will all be decompressed by gzread().
+ If something other than a gzip stream is encountered after a gzip stream,
+ that remaining trailing garbage is ignored (and no error is returned).
+
+ gzread can be used to read a gzip file that is being concurrently written.
+ Upon reaching the end of the input, gzread will return with the available
+ data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
+ gzclearerr can be used to clear the end of file indicator in order to permit
+ gzread to be tried again. Z_OK indicates that a gzip stream was completed
+ on the last gzread. Z_BUF_ERROR indicates that the input file ended in the
+ middle of a gzip stream. Note that gzread does not return -1 in the event
+ of an incomplete gzip stream. This error is deferred until gzclose(), which
+ will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
+ stream. Alternatively, gzerror can be used before gzclose to detect this
+ case.
+
+ gzread returns the number of uncompressed bytes actually read, less than
+ len for end of file, or -1 for error. If len is too large to fit in an int,
+ then nothing is read, -1 is returned, and the error state is set to
+ Z_STREAM_ERROR.
+*/
+
+ZEXTERN z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems,
+ gzFile file);
+/*
+ Read and decompress up to nitems items of size size from file into buf,
+ otherwise operating as gzread() does. This duplicates the interface of
+ stdio's fread(), with size_t request and return types. If the library
+ defines size_t, then z_size_t is identical to size_t. If not, then z_size_t
+ is an unsigned integer type that can contain a pointer.
+
+ gzfread() returns the number of full items read of size size, or zero if
+ the end of the file was reached and a full item could not be read, or if
+ there was an error. gzerror() must be consulted if zero is returned in
+ order to determine if there was an error. If the multiplication of size and
+ nitems overflows, i.e. the product does not fit in a z_size_t, then nothing
+ is read, zero is returned, and the error state is set to Z_STREAM_ERROR.
+
+ In the event that the end of file is reached and only a partial item is
+ available at the end, i.e. the remaining uncompressed data length is not a
+ multiple of size, then the final partial item is nevertheless read into buf
+ and the end-of-file flag is set. The length of the partial item read is not
+ provided, but could be inferred from the result of gztell(). This behavior
+ is the same as the behavior of fread() implementations in common libraries,
+ but it prevents the direct use of gzfread() to read a concurrently written
+ file, resetting and retrying on end-of-file, when size is not 1.
+*/
+
+ZEXTERN int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len);
+/*
+ Compress and write the len uncompressed bytes at buf to file. gzwrite
+ returns the number of uncompressed bytes written or 0 in case of error.
+*/
+
+ZEXTERN z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size,
+ z_size_t nitems, gzFile file);
+/*
+ Compress and write nitems items of size size from buf to file, duplicating
+ the interface of stdio's fwrite(), with size_t request and return types. If
+ the library defines size_t, then z_size_t is identical to size_t. If not,
+ then z_size_t is an unsigned integer type that can contain a pointer.
+
+ gzfwrite() returns the number of full items written of size size, or zero
+ if there was an error. If the multiplication of size and nitems overflows,
+ i.e. the product does not fit in a z_size_t, then nothing is written, zero
+ is returned, and the error state is set to Z_STREAM_ERROR.
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf(gzFile file, const char *format, ...);
+/*
+ Convert, format, compress, and write the arguments (...) to file under
+ control of the string format, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written, or a negative zlib error code in case
+ of error. The number of uncompressed bytes written is limited to 8191, or
+ one less than the buffer size given to gzbuffer(). The caller should assure
+ that this limit is not exceeded. If it is exceeded, then gzprintf() will
+ return an error (0) with nothing written. In this case, there may also be a
+ buffer overflow with unpredictable consequences, which is possible only if
+ zlib was compiled with the insecure functions sprintf() or vsprintf(),
+ because the secure snprintf() or vsnprintf() functions were not available.
+ This can be determined using zlibCompileFlags().
+*/
+
+ZEXTERN int ZEXPORT gzputs(gzFile file, const char *s);
+/*
+ Compress and write the given null-terminated string s to file, excluding
+ the terminating null character.
+
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets(gzFile file, char *buf, int len);
+/*
+ Read and decompress bytes from file into buf, until len-1 characters are
+ read, or until a newline character is read and transferred to buf, or an
+ end-of-file condition is encountered. If any characters are read or if len
+ is one, the string is terminated with a null character. If no characters
+ are read due to an end-of-file or len is less than one, then the buffer is
+ left untouched.
+
+ gzgets returns buf which is a null-terminated string, or it returns NULL
+ for end-of-file or in case of error. If there was an error, the contents at
+ buf are indeterminate.
+*/
+
+ZEXTERN int ZEXPORT gzputc(gzFile file, int c);
+/*
+ Compress and write c, converted to an unsigned char, into file. gzputc
+ returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc(gzFile file);
+/*
+ Read and decompress one byte from file. gzgetc returns this byte or -1
+ in case of end of file or error. This is implemented as a macro for speed.
+ As such, it does not do all of the checking the other functions do. I.e.
+ it does not check to see if file is NULL, nor whether the structure file
+ points to has been clobbered or not.
+*/
+
+ZEXTERN int ZEXPORT gzungetc(int c, gzFile file);
+/*
+ Push c back onto the stream for file to be read as the first character on
+ the next read. At least one character of push-back is always allowed.
+ gzungetc() returns the character pushed, or -1 on failure. gzungetc() will
+ fail if c is -1, and may fail if a character has been pushed but not read
+ yet. If gzungetc is used immediately after gzopen or gzdopen, at least the
+ output buffer size of pushed characters is allowed. (See gzbuffer above.)
+ The pushed character will be discarded if the stream is repositioned with
+ gzseek() or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush(gzFile file, int flush);
+/*
+ Flush all pending output to file. The parameter flush is as in the
+ deflate() function. The return value is the zlib error number (see function
+ gzerror below). gzflush is only permitted when writing.
+
+ If the flush parameter is Z_FINISH, the remaining data is written and the
+ gzip stream is completed in the output. If gzwrite() is called again, a new
+ gzip stream will be started in the output. gzread() is able to read such
+ concatenated gzip streams.
+
+ gzflush should be called only when strictly necessary because it will
+ degrade compression if called too often.
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzseek(gzFile file,
+ z_off_t offset, int whence);
+
+ Set the starting position to offset relative to whence for the next gzread
+ or gzwrite on file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT gzrewind(gzFile file);
+/*
+ Rewind file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET).
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gztell(gzFile file);
+
+ Return the starting position for the next gzread or gzwrite on file.
+ This position represents a number of bytes in the uncompressed data stream,
+ and is zero when starting, even if appending or reading a gzip stream from
+ the middle of a file using gzdopen().
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzoffset(gzFile file);
+
+ Return the current compressed (actual) read or write offset of file. This
+ offset includes the count of bytes that precede the gzip stream, for example
+ when appending or when using gzdopen() for reading. When reading, the
+ offset does not include as yet unused buffered input. This information can
+ be used for a progress indicator. On error, gzoffset() returns -1.
+*/
+
+ZEXTERN int ZEXPORT gzeof(gzFile file);
+/*
+ Return true (1) if the end-of-file indicator for file has been set while
+ reading, false (0) otherwise. Note that the end-of-file indicator is set
+ only if the read tried to go past the end of the input, but came up short.
+ Therefore, just like feof(), gzeof() may return false even if there is no
+ more data to read, in the event that the last read request was for the exact
+ number of bytes remaining in the input file. This will happen if the input
+ file size is an exact multiple of the buffer size.
+
+ If gzeof() returns true, then the read functions will return no more data,
+ unless the end-of-file indicator is reset by gzclearerr() and the input file
+ has grown since the previous end of file was detected.
+*/
+
+ZEXTERN int ZEXPORT gzdirect(gzFile file);
+/*
+ Return true (1) if file is being copied directly while reading, or false
+ (0) if file is a gzip stream being decompressed.
+
+ If the input file is empty, gzdirect() will return true, since the input
+ does not contain a gzip stream.
+
+ If gzdirect() is used immediately after gzopen() or gzdopen() it will
+ cause buffers to be allocated to allow reading the file to determine if it
+ is a gzip file. Therefore if gzbuffer() is used, it should be called before
+ gzdirect().
+
+ When writing, gzdirect() returns true (1) if transparent writing was
+ requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note:
+ gzdirect() is not needed when writing. Transparent writing must be
+ explicitly requested, so the application already knows the answer. When
+ linking statically, using gzdirect() will include all of the zlib code for
+ gzip file reading and decompression, which may not be desired.)
+*/
+
+ZEXTERN int ZEXPORT gzclose(gzFile file);
+/*
+ Flush all pending output for file, if necessary, close file and
+ deallocate the (de)compression state. Note that once file is closed, you
+ cannot call gzerror with file, since its structures have been deallocated.
+ gzclose must not be called more than once on the same file, just as free
+ must not be called more than once on the same allocation.
+
+ gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
+ file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
+ last read ended in the middle of a gzip stream, or Z_OK on success.
+*/
+
+ZEXTERN int ZEXPORT gzclose_r(gzFile file);
+ZEXTERN int ZEXPORT gzclose_w(gzFile file);
+/*
+ Same as gzclose(), but gzclose_r() is only for use when reading, and
+ gzclose_w() is only for use when writing or appending. The advantage to
+ using these instead of gzclose() is that they avoid linking in zlib
+ compression or decompression code that is not used when only reading or only
+ writing respectively. If gzclose() is used, then both compression and
+ decompression code will be included the application when linking to a static
+ zlib library.
+*/
+
+ZEXTERN const char * ZEXPORT gzerror(gzFile file, int *errnum);
+/*
+ Return the error message for the last error which occurred on file.
+ errnum is set to zlib error number. If an error occurred in the file system
+ and not in the compression library, errnum is set to Z_ERRNO and the
+ application may consult errno to get the exact error code.
+
+ The application must not modify the returned string. Future calls to
+ this function may invalidate the previously returned string. If file is
+ closed, then the string previously returned by gzerror will no longer be
+ available.
+
+ gzerror() should be used to distinguish errors from end-of-file for those
+ functions above that do not distinguish those cases in their return values.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr(gzFile file);
+/*
+ Clear the error and end-of-file flags for file. This is analogous to the
+ clearerr() function in stdio. This is useful for continuing to read a gzip
+ file that is being written concurrently.
+*/
+
+#endif /* !Z_SOLO */
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the compression
+ library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len);
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. An Adler-32 value is in the range of a 32-bit
+ unsigned integer. If buf is Z_NULL, this function returns the required
+ initial value for the checksum.
+
+ An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed
+ much faster.
+
+ Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf,
+ z_size_t len);
+/*
+ Same as adler32(), but with a size_t length.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2,
+ z_off_t len2);
+
+ Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
+ and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+ each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
+ seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note
+ that the z_off_t type (like off_t) is a signed integer. If len2 is
+ negative, the result has no meaning or utility.
+*/
+
+ZEXTERN uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len);
+/*
+ Update a running CRC-32 with the bytes buf[0..len-1] and return the
+ updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer.
+ If buf is Z_NULL, this function returns the required initial value for the
+ crc. Pre- and post-conditioning (one's complement) is performed within this
+ function so it shouldn't be done by the application.
+
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32_z(uLong crc, const Bytef *buf,
+ z_size_t len);
+/*
+ Same as crc32(), but with a size_t length.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2);
+
+ Combine two CRC-32 check values into one. For two sequences of bytes,
+ seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+ calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
+ check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+ len2.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2);
+
+ Return the operator corresponding to length len2, to be used with
+ crc32_combine_op().
+*/
+
+ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op);
+/*
+ Give the same result as crc32_combine(), using op in place of len2. op is
+ is generated from len2 by crc32_combine_gen(). This will be faster than
+ crc32_combine() if the generated op is used more than once.
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_(z_streamp strm, int level,
+ const char *version, int stream_size);
+ZEXTERN int ZEXPORT inflateInit_(z_streamp strm,
+ const char *version, int stream_size);
+ZEXTERN int ZEXPORT deflateInit2_(z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size);
+ZEXTERN int ZEXPORT inflateInit2_(z_streamp strm, int windowBits,
+ const char *version, int stream_size);
+ZEXTERN int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits,
+ unsigned char FAR *window,
+ const char *version,
+ int stream_size);
+#ifdef Z_PREFIX_SET
+# define z_deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+# define z_inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+# define z_inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+ (int)sizeof(z_stream))
+# define z_inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, (int)sizeof(z_stream))
+#else
+# define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+# define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+# define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+ (int)sizeof(z_stream))
+# define inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, (int)sizeof(z_stream))
+#endif
+
+#ifndef Z_SOLO
+
+/* gzgetc() macro and its supporting function and exposed data structure. Note
+ * that the real internal state is much larger than the exposed structure.
+ * This abbreviated structure exposes just enough for the gzgetc() macro. The
+ * user should not mess with these exposed elements, since their names or
+ * behavior could change in the future, perhaps even capriciously. They can
+ * only be used by the gzgetc() macro. You have been warned.
+ */
+struct gzFile_s {
+ unsigned have;
+ unsigned char *next;
+ z_off64_t pos;
+};
+ZEXTERN int ZEXPORT gzgetc_(gzFile file); /* backward compatibility */
+#ifdef Z_PREFIX_SET
+# undef z_gzgetc
+# define z_gzgetc(g) \
+ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
+#else
+# define gzgetc(g) \
+ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
+#endif
+
+/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
+ * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
+ * both are true, the application gets the *64 functions, and the regular
+ * functions are changed to 64 bits) -- in case these are set on systems
+ * without large file support, _LFS64_LARGEFILE must also be true
+ */
+#ifdef Z_LARGE64
+ ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
+ ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int);
+ ZEXTERN z_off64_t ZEXPORT gztell64(gzFile);
+ ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile);
+ ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off64_t);
+ ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off64_t);
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off64_t);
+#endif
+
+#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
+# ifdef Z_PREFIX_SET
+# define z_gzopen z_gzopen64
+# define z_gzseek z_gzseek64
+# define z_gztell z_gztell64
+# define z_gzoffset z_gzoffset64
+# define z_adler32_combine z_adler32_combine64
+# define z_crc32_combine z_crc32_combine64
+# define z_crc32_combine_gen z_crc32_combine_gen64
+# else
+# define gzopen gzopen64
+# define gzseek gzseek64
+# define gztell gztell64
+# define gzoffset gzoffset64
+# define adler32_combine adler32_combine64
+# define crc32_combine crc32_combine64
+# define crc32_combine_gen crc32_combine_gen64
+# endif
+# ifndef Z_LARGE64
+ ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
+ ZEXTERN z_off_t ZEXPORT gzseek64(gzFile, z_off_t, int);
+ ZEXTERN z_off_t ZEXPORT gztell64(gzFile);
+ ZEXTERN z_off_t ZEXPORT gzoffset64(gzFile);
+ ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t);
+# endif
+#else
+ ZEXTERN gzFile ZEXPORT gzopen(const char *, const char *);
+ ZEXTERN z_off_t ZEXPORT gzseek(gzFile, z_off_t, int);
+ ZEXTERN z_off_t ZEXPORT gztell(gzFile);
+ ZEXTERN z_off_t ZEXPORT gzoffset(gzFile);
+ ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t);
+#endif
+
+#else /* Z_SOLO */
+
+ ZEXTERN uLong ZEXPORT adler32_combine(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t);
+
+#endif /* !Z_SOLO */
+
+/* undocumented functions */
+ZEXTERN const char * ZEXPORT zError(int);
+ZEXTERN int ZEXPORT inflateSyncPoint(z_streamp);
+ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table(void);
+ZEXTERN int ZEXPORT inflateUndermine(z_streamp, int);
+ZEXTERN int ZEXPORT inflateValidate(z_streamp, int);
+ZEXTERN unsigned long ZEXPORT inflateCodesUsed(z_streamp);
+ZEXTERN int ZEXPORT inflateResetKeep(z_streamp);
+ZEXTERN int ZEXPORT deflateResetKeep(z_streamp);
+#if defined(_WIN32) && !defined(Z_SOLO)
+ZEXTERN gzFile ZEXPORT gzopen_w(const wchar_t *path,
+ const char *mode);
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifndef Z_SOLO
+ZEXTERN int ZEXPORTVA gzvprintf(gzFile file,
+ const char *format,
+ va_list va);
+# endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/lib/zlib/zutil.c b/lib/zlib/zutil.c
new file mode 100644
index 0000000..b1c5d2d
--- /dev/null
+++ b/lib/zlib/zutil.c
@@ -0,0 +1,299 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2017 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zutil.h"
+#ifndef Z_SOLO
+# include "gzguts.h"
+#endif
+
+z_const char * const z_errmsg[10] = {
+ (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */
+ (z_const char *)"stream end", /* Z_STREAM_END 1 */
+ (z_const char *)"", /* Z_OK 0 */
+ (z_const char *)"file error", /* Z_ERRNO (-1) */
+ (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */
+ (z_const char *)"data error", /* Z_DATA_ERROR (-3) */
+ (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */
+ (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */
+ (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */
+ (z_const char *)""
+};
+
+
+const char * ZEXPORT zlibVersion(void) {
+ return ZLIB_VERSION;
+}
+
+uLong ZEXPORT zlibCompileFlags(void) {
+ uLong flags;
+
+ flags = 0;
+ switch ((int)(sizeof(uInt))) {
+ case 2: break;
+ case 4: flags += 1; break;
+ case 8: flags += 2; break;
+ default: flags += 3;
+ }
+ switch ((int)(sizeof(uLong))) {
+ case 2: break;
+ case 4: flags += 1 << 2; break;
+ case 8: flags += 2 << 2; break;
+ default: flags += 3 << 2;
+ }
+ switch ((int)(sizeof(voidpf))) {
+ case 2: break;
+ case 4: flags += 1 << 4; break;
+ case 8: flags += 2 << 4; break;
+ default: flags += 3 << 4;
+ }
+ switch ((int)(sizeof(z_off_t))) {
+ case 2: break;
+ case 4: flags += 1 << 6; break;
+ case 8: flags += 2 << 6; break;
+ default: flags += 3 << 6;
+ }
+#ifdef ZLIB_DEBUG
+ flags += 1 << 8;
+#endif
+ /*
+#if defined(ASMV) || defined(ASMINF)
+ flags += 1 << 9;
+#endif
+ */
+#ifdef ZLIB_WINAPI
+ flags += 1 << 10;
+#endif
+#ifdef BUILDFIXED
+ flags += 1 << 12;
+#endif
+#ifdef DYNAMIC_CRC_TABLE
+ flags += 1 << 13;
+#endif
+#ifdef NO_GZCOMPRESS
+ flags += 1L << 16;
+#endif
+#ifdef NO_GZIP
+ flags += 1L << 17;
+#endif
+#ifdef PKZIP_BUG_WORKAROUND
+ flags += 1L << 20;
+#endif
+#ifdef FASTEST
+ flags += 1L << 21;
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifdef NO_vsnprintf
+ flags += 1L << 25;
+# ifdef HAS_vsprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_vsnprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#else
+ flags += 1L << 24;
+# ifdef NO_snprintf
+ flags += 1L << 25;
+# ifdef HAS_sprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_snprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#endif
+ return flags;
+}
+
+#ifdef ZLIB_DEBUG
+#include <stdlib.h>
+# ifndef verbose
+# define verbose 0
+# endif
+int ZLIB_INTERNAL z_verbose = verbose;
+
+void ZLIB_INTERNAL z_error(char *m) {
+ fprintf(stderr, "%s\n", m);
+ exit(1);
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(int err) {
+ return ERR_MSG(err);
+}
+
+#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
+ /* The older Microsoft C Run-Time Library for Windows CE doesn't have
+ * errno. We define it as a global variable to simplify porting.
+ * Its value is always 0 and should not be used.
+ */
+ int errno = 0;
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len) {
+ if (len == 0) return;
+ do {
+ *dest++ = *source++; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+
+int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len) {
+ uInt j;
+
+ for (j = 0; j < len; j++) {
+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+ }
+ return 0;
+}
+
+void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len) {
+ if (len == 0) return;
+ do {
+ *dest++ = 0; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+#endif
+
+#ifndef Z_SOLO
+
+#ifdef SYS16BIT
+
+#ifdef __TURBOC__
+/* Turbo C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+ voidpf org_ptr;
+ voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) {
+ voidpf buf;
+ ulg bsize = (ulg)items*size;
+
+ (void)opaque;
+
+ /* If we allocate less than 65520 bytes, we assume that farmalloc
+ * will return a usable pointer which doesn't have to be normalized.
+ */
+ if (bsize < 65520L) {
+ buf = farmalloc(bsize);
+ if (*(ush*)&buf != 0) return buf;
+ } else {
+ buf = farmalloc(bsize + 16L);
+ }
+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+ table[next_ptr].org_ptr = buf;
+
+ /* Normalize the pointer to seg:0 */
+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+ *(ush*)&buf = 0;
+ table[next_ptr++].new_ptr = buf;
+ return buf;
+}
+
+void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
+ int n;
+
+ (void)opaque;
+
+ if (*(ush*)&ptr != 0) { /* object < 64K */
+ farfree(ptr);
+ return;
+ }
+ /* Find the original pointer */
+ for (n = 0; n < next_ptr; n++) {
+ if (ptr != table[n].new_ptr) continue;
+
+ farfree(table[n].org_ptr);
+ while (++n < next_ptr) {
+ table[n-1] = table[n];
+ }
+ next_ptr--;
+ return;
+ }
+ Assert(0, "zcfree: ptr not found");
+}
+
+#endif /* __TURBOC__ */
+
+
+#ifdef M_I86
+/* Microsoft C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+# define _halloc halloc
+# define _hfree hfree
+#endif
+
+voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) {
+ (void)opaque;
+ return _halloc((long)items, size);
+}
+
+void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
+ (void)opaque;
+ _hfree(ptr);
+}
+
+#endif /* M_I86 */
+
+#endif /* SYS16BIT */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp malloc(uInt size);
+extern voidp calloc(uInt items, uInt size);
+extern void free(voidpf ptr);
+#endif
+
+voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) {
+ (void)opaque;
+ return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+ (voidpf)calloc(items, size);
+}
+
+void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
+ (void)opaque;
+ free(ptr);
+}
+
+#endif /* MY_ZCALLOC */
+
+#endif /* !Z_SOLO */
diff --git a/lib/zlib/zutil.h b/lib/zlib/zutil.h
new file mode 100644
index 0000000..902a304
--- /dev/null
+++ b/lib/zlib/zutil.h
@@ -0,0 +1,275 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZUTIL_H
+#define ZUTIL_H
+
+#ifdef HAVE_HIDDEN
+# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+#else
+# define ZLIB_INTERNAL
+#endif
+
+#include "zlib.h"
+
+#if defined(STDC) && !defined(Z_SOLO)
+# if !(defined(_WIN32_WCE) && defined(_MSC_VER))
+# include <stddef.h>
+# endif
+# include <string.h>
+# include <stdlib.h>
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* since "static" is used to mean two completely different things in C, we
+ define "local" for the non-static meaning of "static", for readability
+ (compile with -Dlocal if your debugger can't find static symbols) */
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC)
+# include <limits.h>
+# if (ULONG_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned long
+# elif (ULLONG_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned long long
+# elif (UINT_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned
+# endif
+#endif
+
+extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+ return (strm->msg = ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+ /* target dependencies */
+
+#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
+# define OS_CODE 0x00
+# ifndef Z_SOLO
+# if defined(__TURBOC__) || defined(__BORLANDC__)
+# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+ /* Allow compilation with ANSI keywords only enabled */
+ void _Cdecl farfree( void *block );
+ void *_Cdecl farmalloc( unsigned long nbytes );
+# else
+# include <alloc.h>
+# endif
+# else /* MSC or DJGPP */
+# include <malloc.h>
+# endif
+# endif
+#endif
+
+#ifdef AMIGA
+# define OS_CODE 1
+#endif
+
+#if defined(VAXC) || defined(VMS)
+# define OS_CODE 2
+# define F_OPEN(name, mode) \
+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#ifdef __370__
+# if __TARGET_LIB__ < 0x20000000
+# define OS_CODE 4
+# elif __TARGET_LIB__ < 0x40000000
+# define OS_CODE 11
+# else
+# define OS_CODE 8
+# endif
+#endif
+
+#if defined(ATARI) || defined(atarist)
+# define OS_CODE 5
+#endif
+
+#ifdef OS2
+# define OS_CODE 6
+# if defined(M_I86) && !defined(Z_SOLO)
+# include <malloc.h>
+# endif
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+# define OS_CODE 7
+# ifndef Z_SOLO
+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+# include <unix.h> /* for fdopen */
+# else
+# ifndef fdopen
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __acorn
+# define OS_CODE 13
+#endif
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+# define OS_CODE 10
+#endif
+
+#ifdef _BEOS_
+# define OS_CODE 16
+#endif
+
+#ifdef __TOS_OS400__
+# define OS_CODE 18
+#endif
+
+#ifdef __APPLE__
+# define OS_CODE 19
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
+# if defined(_WIN32_WCE)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# else
+# define fdopen(fd,type) _fdopen(fd,type)
+# endif
+#endif
+
+#if defined(__BORLANDC__) && !defined(MSDOS)
+ #pragma warn -8004
+ #pragma warn -8008
+ #pragma warn -8066
+#endif
+
+/* provide prototypes for these when building zlib without LFS */
+#if !defined(_WIN32) && \
+ (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
+ ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t);
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t);
+#endif
+
+ /* common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 3 /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+# define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+ /* functions */
+
+#if defined(pyr) || defined(Z_SOLO)
+# define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+ * You may have to use the same strategy for Borland C (untested).
+ * The __SC__ check is for Symantec.
+ */
+# define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+# define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+# define zmemcpy _fmemcpy
+# define zmemcmp _fmemcmp
+# define zmemzero(dest, len) _fmemset(dest, 0, len)
+# else
+# define zmemcpy memcpy
+# define zmemcmp memcmp
+# define zmemzero(dest, len) memset(dest, 0, len)
+# endif
+#else
+ void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len);
+ int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len);
+ void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len);
+#endif
+
+/* Diagnostic functions */
+#ifdef ZLIB_DEBUG
+# include <stdio.h>
+ extern int ZLIB_INTERNAL z_verbose;
+ extern void ZLIB_INTERNAL z_error(char *m);
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) {if (z_verbose>=0) fprintf x ;}
+# define Tracev(x) {if (z_verbose>0) fprintf x ;}
+# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+#ifndef Z_SOLO
+ voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items,
+ unsigned size);
+ void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr);
+#endif
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+/* Reverse the bytes in a 32-bit value */
+#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+#endif /* ZUTIL_H */
diff --git a/logsrvd/Makefile.in b/logsrvd/Makefile.in
new file mode 100644
index 0000000..1c7e3ee
--- /dev/null
+++ b/logsrvd/Makefile.in
@@ -0,0 +1,610 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2019-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+devdir = @devdir@
+scriptdir = $(top_srcdir)/scripts
+incdir = $(top_srcdir)/include
+rundir = @rundir@
+cross_compiling = @CROSS_COMPILING@
+
+# Compiler & tools to use
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+SHA1SUM = @SHA1SUM@
+EGREP = @EGREP@
+SED = @SED@
+
+# Our install program supports extra flags...
+INSTALL = $(SHELL) $(scriptdir)/install-sh -c
+INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
+INSTALL_BACKUP = @INSTALL_BACKUP@
+
+# Libraries
+LT_LIBS = $(top_builddir)/lib/iolog/libsudo_iolog.la \
+ $(top_builddir)/lib/eventlog/libsudo_eventlog.la \
+ $(top_builddir)/lib/logsrv/liblogsrv.la \
+ $(top_builddir)/lib/protobuf-c/libprotobuf-c.la
+LIBS = $(LT_LIBS) @LIBTLS@
+
+# C preprocessor defines
+CPPDEFS = -D_PATH_SUDO_LOGSRVD_CONF=\"@sudo_logsrvd_conf@\" \
+ -DLOCALEDIR=\"$(localedir)\"
+
+# C preprocessor flags
+CPPFLAGS = -I$(incdir) -I$(top_builddir) -I$(devdir) -I$(srcdir) \
+ $(CPPDEFS) @CPPFLAGS@
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+
+# Flags to pass to the link stage
+LDFLAGS = @LDFLAGS@
+LT_LDFLAGS = @LT_LDFLAGS@
+
+# Flags to pass to libtool
+LTFLAGS = --tag=disable-static
+
+# Address sanitizer flags
+ASAN_CFLAGS = @ASAN_CFLAGS@
+ASAN_LDFLAGS = @ASAN_LDFLAGS@
+
+# PIE flags
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+
+# Stack smashing protection flags
+HARDENING_CFLAGS = @HARDENING_CFLAGS@
+HARDENING_LDFLAGS = @HARDENING_LDFLAGS@
+
+# cppcheck options, usually set in the top-level Makefile
+CPPCHECK_OPTS = -q --enable=warning,performance,portability --suppress=constStatement --suppress=compareBoolExpressionWithInt --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
+
+# splint options, usually set in the top-level Makefile
+SPLINT_OPTS = -D__restrict= -checks
+
+# PVS-studio options
+PVS_CFG = $(top_srcdir)/PVS-Studio.cfg
+PVS_IGNORE = 'V707,V011,V002,V536'
+PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
+
+# Where to install things...
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+sysconfdir = @sysconfdir@
+adminconfdir = @adminconfdir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+
+# Fuzzers
+LIBFUZZSTUB = $(top_builddir)/lib/fuzzstub/libsudo_fuzzstub.la
+LIB_FUZZING_ENGINE = @FUZZ_ENGINE@
+FUZZ_PROGS = fuzz_logsrvd_conf
+FUZZ_SEED_CORPUS = ${FUZZ_PROGS:=_seed_corpus.zip}
+FUZZ_LIBS = $(LIB_FUZZING_ENGINE) $(LIBS)
+FUZZ_LDFLAGS = $(LDFLAGS)
+FUZZ_MAX_LEN = 4096
+FUZZ_RUNS = 8192
+FUZZ_VERBOSE =
+
+TEST_PROGS = logsrvd_conf_test
+TEST_LIBS = $(LIBS)
+TEST_LDFLAGS = $(LDFLAGS)
+TEST_VERBOSE =
+
+# User and group IDs the installed files should be "owned" by
+install_uid = 0
+install_gid = 0
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+PROGS = sudo_logsrvd sudo_sendlog
+
+LOGSRVD_OBJS = logsrv_util.o iolog_writer.o logsrvd.o logsrvd_conf.o \
+ logsrvd_journal.o logsrvd_local.o logsrvd_relay.o \
+ logsrvd_queue.o tls_client.o tls_init.o
+
+SENDLOG_OBJS = logsrv_util.o sendlog.o tls_client.o tls_init.o
+
+IOBJS = $(LOGSRVD_OBJS:.o=.i) $(SENDLOG_OBJS:.o=.i)
+
+POBJS = $(IOBJS:.i=.plog)
+
+LIBOBJDIR = $(top_builddir)/@ac_config_libobj_dir@/
+
+VERSION = @PACKAGE_VERSION@
+
+FUZZ_LOGSRVD_CONF_OBJS = fuzz_logsrvd_conf.o logsrvd_conf.o tls_init.o
+
+FUZZ_LOGSRVD_CONF_CORPUS = $(srcdir)/regress/corpus/seed/logsrvd_conf/logsrvd.conf.*
+
+CONF_TEST_OBJS = logsrvd_conf_test.o logsrvd_conf.o tls_init.o
+
+all: $(PROGS)
+
+depend:
+ $(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
+ --builddir=$(abs_top_builddir) logsrvd/Makefile.in
+ cd $(top_builddir) && ./config.status --file logsrvd/Makefile
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file logsrvd/Makefile
+
+.SUFFIXES: .c .h .i .lo .o .plog
+
+.c.o:
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.lo:
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.i:
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+
+.i.plog:
+ ifile=$<; rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $${ifile%i}c --i-file $< --output-file $@
+
+sudo_logsrvd: $(LOGSRVD_OBJS) $(LT_LIBS)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LOGSRVD_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS)
+
+sudo_sendlog: $(SENDLOG_OBJS) $(LT_LIBS)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(SENDLOG_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS)
+
+fuzz_logsrvd_conf: $(FUZZ_LOGSRVD_CONF_OBJS) $(LIBFUZZSTUB) $(LT_LIBS)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(FUZZ_LOGSRVD_CONF_OBJS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(FUZZ_LDFLAGS) $(FUZZ_LIBS)
+
+logsrvd_conf_test: $(CONF_TEST_OBJS) $(LT_LIBS)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CONF_TEST_OBJS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
+
+fuzz_logsrvd_conf_seed_corpus.zip:
+ tdir=fuzz_logsrvd_conf.$$$$; \
+ mkdir $$tdir; \
+ for f in $(FUZZ_LOGSRVD_CONF_CORPUS); do \
+ cp $$f $$tdir/`$(SHA1SUM) $$f | $(SED) -e 's/^.*= *//' -e 's/ .*//'`; \
+ done; \
+ zip -j $@ $$tdir/*; \
+ rm -rf $$tdir
+
+run-fuzz_logsrvd_conf: fuzz_logsrvd_conf
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ umask 022; \
+ corpus=regress/corpus/logsrvd_conf; \
+ mkdir -p $$corpus; \
+ for f in $(FUZZ_LOGSRVD_CONF_CORPUS); do \
+ cp $$f $$corpus; \
+ done; \
+ ./fuzz_logsrvd_conf -dict=$(srcdir)/regress/fuzz/fuzz_logsrvd_conf.dict -max_len=$(FUZZ_MAX_LEN) -runs=$(FUZZ_RUNS) $(FUZZ_VERBOSE) $$corpus
+
+pre-install:
+
+install: install-binaries
+
+install-dirs:
+ $(SHELL) $(scriptdir)/mkinstalldirs $(DESTDIR)$(sbindir)
+
+install-binaries: install-dirs $(PROGS)
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) $(INSTALL_OWNER) -m 0755 sudo_logsrvd $(DESTDIR)$(sbindir)/sudo_logsrvd
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) $(INSTALL_OWNER) -m 0755 sudo_sendlog $(DESTDIR)$(sbindir)/sudo_sendlog
+
+install-doc:
+
+install-includes:
+
+install-plugin:
+
+install-fuzzer: $(FUZZ_PROGS) $(FUZZ_SEED_CORPUS)
+ @if test X"$(FUZZ_DESTDIR)" = X""; then \
+ echo "must set FUZZ_DESTDIR for install-fuzzer target"; \
+ else \
+ cp $(FUZZ_PROGS) $(FUZZ_SEED_CORPUS) $(FUZZ_DESTDIR); \
+ fi
+
+uninstall:
+ -rm -f $(DESTDIR)$(sbindir)/sudo_logsrvd \
+ $(DESTDIR)$(sbindir)/sudo_sendlog
+ -test -z "$(INSTALL_BACKUP)" || \
+ rm -f $(DESTDIR)$(sbindir)/sudo_logsrvd$(INSTALL_BACKUP) \
+ $(DESTDIR)$(sbindir)/sudo_sendlog$(INSTALL_BACKUP)
+
+splint:
+ splint $(SPLINT_OPTS) -I$(incdir) -I$(top_builddir) -I. -I$(srcdir) $(srcdir)/*.c
+
+cppcheck:
+ cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) -I. -I$(srcdir) $(srcdir)/*.c
+
+pvs-log-files: $(POBJS)
+
+pvs-studio: $(POBJS)
+ plog-converter $(PVS_LOG_OPTS) $(POBJS)
+
+fuzz: run-fuzz_logsrvd_conf
+
+check-fuzzer: $(FUZZ_PROGS)
+ @if test X"$(cross_compiling)" != X"yes"; then \
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ echo "fuzz_logsrvd_conf: verifying corpus"; \
+ ./fuzz_logsrvd_conf $(FUZZ_VERBOSE) $(FUZZ_LOGSRVD_CONF_CORPUS); \
+ fi
+
+check: $(TEST_PROGS) check-fuzzer
+ @if test X"$(cross_compiling)" != X"yes"; then \
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ builddir=$(abs_top_builddir)/logsrvd; \
+ cd $(srcdir) || exit 1; \
+ if test -n "@LIBTLS@"; then \
+ $$builddir/logsrvd_conf_test $(TEST_VERBOSE) \
+ regress/logsrvd_conf/tls/*.in; \
+ else \
+ $$builddir/logsrvd_conf_test $(TEST_VERBOSE) \
+ regress/logsrvd_conf/*.in; \
+ fi; \
+ fi
+
+check-verbose: check
+
+clean:
+ -$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f $(PROGS) $(FUZZ_PROGS) \
+ $(TEST_PROGS) *.lo *.o *.la
+ -rm -f *.i *.plog stamp-* core *.core core.*
+ -rm -rf regress/corpus/logsrvd_conf
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile .libs
+
+clobber: distclean
+
+realclean: distclean
+ rm -f TAGS tags
+
+cleandir: realclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean \
+ $(FUZZ_SEED_CORPUS) run-fuzz_logsrvd_conf
+
+# Autogenerated dependencies, do not modify
+fuzz_logsrvd_conf.o: $(srcdir)/regress/fuzz/fuzz_logsrvd_conf.c \
+ $(incdir)/compat/stdbool.h $(incdir)/log_server.pb-c.h \
+ $(incdir)/protobuf-c/protobuf-c.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_ssl_compat.h \
+ $(incdir)/sudo_util.h $(srcdir)/logsrv_util.h \
+ $(srcdir)/logsrvd.h $(srcdir)/tls_common.h \
+ $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/fuzz/fuzz_logsrvd_conf.c
+fuzz_logsrvd_conf.i: $(srcdir)/regress/fuzz/fuzz_logsrvd_conf.c \
+ $(incdir)/compat/stdbool.h $(incdir)/log_server.pb-c.h \
+ $(incdir)/protobuf-c/protobuf-c.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_ssl_compat.h \
+ $(incdir)/sudo_util.h $(srcdir)/logsrv_util.h \
+ $(srcdir)/logsrvd.h $(srcdir)/tls_common.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fuzz_logsrvd_conf.plog: fuzz_logsrvd_conf.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/fuzz/fuzz_logsrvd_conf.c --i-file $< --output-file $@
+iolog_writer.o: $(srcdir)/iolog_writer.c $(incdir)/compat/stdbool.h \
+ $(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/logsrv_util.h $(srcdir)/logsrvd.h \
+ $(srcdir)/tls_common.h $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_writer.c
+iolog_writer.i: $(srcdir)/iolog_writer.c $(incdir)/compat/stdbool.h \
+ $(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/logsrv_util.h $(srcdir)/logsrvd.h \
+ $(srcdir)/tls_common.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_writer.plog: iolog_writer.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_writer.c --i-file $< --output-file $@
+logsrv_util.o: $(srcdir)/logsrv_util.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/logsrv_util.h $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/logsrv_util.c
+logsrv_util.i: $(srcdir)/logsrv_util.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/logsrv_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+logsrv_util.plog: logsrv_util.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/logsrv_util.c --i-file $< --output-file $@
+logsrvd.o: $(srcdir)/logsrvd.c $(incdir)/compat/getopt.h \
+ $(incdir)/compat/stdbool.h $(incdir)/hostcheck.h \
+ $(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_json.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_rand.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/logsrv_util.h $(srcdir)/logsrvd.h $(srcdir)/tls_common.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/logsrvd.c
+logsrvd.i: $(srcdir)/logsrvd.c $(incdir)/compat/getopt.h \
+ $(incdir)/compat/stdbool.h $(incdir)/hostcheck.h \
+ $(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_json.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_rand.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/logsrv_util.h $(srcdir)/logsrvd.h $(srcdir)/tls_common.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+logsrvd.plog: logsrvd.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/logsrvd.c --i-file $< --output-file $@
+logsrvd_conf.o: $(srcdir)/logsrvd_conf.c $(incdir)/compat/getaddrinfo.h \
+ $(incdir)/compat/stdbool.h $(incdir)/log_server.pb-c.h \
+ $(incdir)/protobuf-c/protobuf-c.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_ssl_compat.h \
+ $(incdir)/sudo_util.h $(srcdir)/logsrv_util.h \
+ $(srcdir)/logsrvd.h $(srcdir)/tls_common.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/logsrvd_conf.c
+logsrvd_conf.i: $(srcdir)/logsrvd_conf.c $(incdir)/compat/getaddrinfo.h \
+ $(incdir)/compat/stdbool.h $(incdir)/log_server.pb-c.h \
+ $(incdir)/protobuf-c/protobuf-c.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_ssl_compat.h \
+ $(incdir)/sudo_util.h $(srcdir)/logsrv_util.h \
+ $(srcdir)/logsrvd.h $(srcdir)/tls_common.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+logsrvd_conf.plog: logsrvd_conf.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/logsrvd_conf.c --i-file $< --output-file $@
+logsrvd_conf_test.o: $(srcdir)/regress/logsrvd_conf/logsrvd_conf_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/log_server.pb-c.h \
+ $(incdir)/protobuf-c/protobuf-c.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/logsrv_util.h $(srcdir)/logsrvd.h \
+ $(srcdir)/tls_common.h $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/logsrvd_conf/logsrvd_conf_test.c
+logsrvd_conf_test.i: $(srcdir)/regress/logsrvd_conf/logsrvd_conf_test.c \
+ $(incdir)/compat/stdbool.h $(incdir)/log_server.pb-c.h \
+ $(incdir)/protobuf-c/protobuf-c.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/logsrv_util.h $(srcdir)/logsrvd.h \
+ $(srcdir)/tls_common.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+logsrvd_conf_test.plog: logsrvd_conf_test.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/logsrvd_conf/logsrvd_conf_test.c --i-file $< --output-file $@
+logsrvd_journal.o: $(srcdir)/logsrvd_journal.c $(incdir)/compat/stdbool.h \
+ $(incdir)/log_server.pb-c.h \
+ $(incdir)/protobuf-c/protobuf-c.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_ssl_compat.h \
+ $(incdir)/sudo_util.h $(srcdir)/logsrv_util.h \
+ $(srcdir)/logsrvd.h $(srcdir)/tls_common.h \
+ $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/logsrvd_journal.c
+logsrvd_journal.i: $(srcdir)/logsrvd_journal.c $(incdir)/compat/stdbool.h \
+ $(incdir)/log_server.pb-c.h \
+ $(incdir)/protobuf-c/protobuf-c.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_ssl_compat.h \
+ $(incdir)/sudo_util.h $(srcdir)/logsrv_util.h \
+ $(srcdir)/logsrvd.h $(srcdir)/tls_common.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+logsrvd_journal.plog: logsrvd_journal.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/logsrvd_journal.c --i-file $< --output-file $@
+logsrvd_local.o: $(srcdir)/logsrvd_local.c $(incdir)/compat/stdbool.h \
+ $(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_json.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_rand.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/logsrv_util.h $(srcdir)/logsrvd.h \
+ $(srcdir)/tls_common.h $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/logsrvd_local.c
+logsrvd_local.i: $(srcdir)/logsrvd_local.c $(incdir)/compat/stdbool.h \
+ $(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_json.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_rand.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/logsrv_util.h $(srcdir)/logsrvd.h \
+ $(srcdir)/tls_common.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+logsrvd_local.plog: logsrvd_local.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/logsrvd_local.c --i-file $< --output-file $@
+logsrvd_queue.o: $(srcdir)/logsrvd_queue.c $(incdir)/compat/stdbool.h \
+ $(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/logsrv_util.h $(srcdir)/logsrvd.h \
+ $(srcdir)/tls_common.h $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/logsrvd_queue.c
+logsrvd_queue.i: $(srcdir)/logsrvd_queue.c $(incdir)/compat/stdbool.h \
+ $(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/logsrv_util.h $(srcdir)/logsrvd.h \
+ $(srcdir)/tls_common.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+logsrvd_queue.plog: logsrvd_queue.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/logsrvd_queue.c --i-file $< --output-file $@
+logsrvd_relay.o: $(srcdir)/logsrvd_relay.c $(incdir)/compat/stdbool.h \
+ $(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_ssl_compat.h \
+ $(incdir)/sudo_util.h $(srcdir)/logsrv_util.h \
+ $(srcdir)/logsrvd.h $(srcdir)/tls_common.h \
+ $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/logsrvd_relay.c
+logsrvd_relay.i: $(srcdir)/logsrvd_relay.c $(incdir)/compat/stdbool.h \
+ $(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_ssl_compat.h \
+ $(incdir)/sudo_util.h $(srcdir)/logsrv_util.h \
+ $(srcdir)/logsrvd.h $(srcdir)/tls_common.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+logsrvd_relay.plog: logsrvd_relay.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/logsrvd_relay.c --i-file $< --output-file $@
+sendlog.o: $(srcdir)/sendlog.c $(incdir)/compat/getaddrinfo.h \
+ $(incdir)/compat/getopt.h $(incdir)/compat/stdbool.h \
+ $(incdir)/hostcheck.h $(incdir)/log_server.pb-c.h \
+ $(incdir)/protobuf-c/protobuf-c.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/logsrv_util.h $(srcdir)/sendlog.h $(srcdir)/tls_common.h \
+ $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sendlog.c
+sendlog.i: $(srcdir)/sendlog.c $(incdir)/compat/getaddrinfo.h \
+ $(incdir)/compat/getopt.h $(incdir)/compat/stdbool.h \
+ $(incdir)/hostcheck.h $(incdir)/log_server.pb-c.h \
+ $(incdir)/protobuf-c/protobuf-c.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/logsrv_util.h $(srcdir)/sendlog.h $(srcdir)/tls_common.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sendlog.plog: sendlog.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sendlog.c --i-file $< --output-file $@
+tls_client.o: $(srcdir)/tls_client.c $(incdir)/compat/stdbool.h \
+ $(incdir)/hostcheck.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/logsrv_util.h $(srcdir)/tls_common.h \
+ $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/tls_client.c
+tls_client.i: $(srcdir)/tls_client.c $(incdir)/compat/stdbool.h \
+ $(incdir)/hostcheck.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/logsrv_util.h $(srcdir)/tls_common.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+tls_client.plog: tls_client.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/tls_client.c --i-file $< --output-file $@
+tls_init.o: $(srcdir)/tls_init.c $(incdir)/compat/stdbool.h \
+ $(incdir)/hostcheck.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_ssl_compat.h $(srcdir)/tls_common.h \
+ $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/tls_init.c
+tls_init.i: $(srcdir)/tls_init.c $(incdir)/compat/stdbool.h \
+ $(incdir)/hostcheck.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_ssl_compat.h $(srcdir)/tls_common.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+tls_init.plog: tls_init.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/tls_init.c --i-file $< --output-file $@
diff --git a/logsrvd/iolog_writer.c b/logsrvd/iolog_writer.c
new file mode 100644
index 0000000..940bd48
--- /dev/null
+++ b/logsrvd/iolog_writer.c
@@ -0,0 +1,914 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_eventlog.h>
+#include <sudo_gettext.h>
+#include <sudo_iolog.h>
+#include <sudo_fatal.h>
+#include <sudo_queue.h>
+#include <sudo_util.h>
+
+#include <logsrvd.h>
+
+static bool
+type_matches(InfoMessage *info, const char *source,
+ InfoMessage__ValueCase value_case)
+{
+ const void *val = info->u.strval; /* same for strlistval */
+ debug_decl(type_matches, SUDO_DEBUG_UTIL);
+
+ if (info->key == NULL) {
+ sudo_warnx(U_("%s: protocol error: NULL key"), source);
+ debug_return_bool(false);
+ }
+ if (info->value_case != value_case) {
+ sudo_warnx(U_("%s: protocol error: wrong type for %s"),
+ source, info->key);
+ debug_return_bool(false);
+ }
+ if (value_case != INFO_MESSAGE__VALUE_NUMVAL && val == NULL) {
+ sudo_warnx(U_("%s: protocol error: NULL value found in %s"),
+ source, info->key);
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+/*
+ * Copy the specified string list.
+ * The input string list need not be NULL-terminated.
+ * Returns a NULL-terminated string vector.
+ */
+static char **
+strlist_copy(InfoMessage__StringList *strlist)
+{
+ char **dst, **src = strlist->strings;
+ size_t i, len = strlist->n_strings;
+ debug_decl(strlist_copy, SUDO_DEBUG_UTIL);
+
+ dst = reallocarray(NULL, len + 1, sizeof(char *));
+ if (dst == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ for (i = 0; i < len; i++) {
+ if ((dst[i] = strdup(src[i])) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ dst[i] = NULL;
+ debug_return_ptr(dst);
+
+bad:
+ if (dst != NULL) {
+ while (i)
+ free(dst[--i]);
+ free(dst);
+ }
+ debug_return_ptr(NULL);
+}
+
+/*
+ * Fill in eventlog details from an AcceptMessage
+ * Caller is responsible for freeing strings in struct eventlog.
+ * Returns true on success and false on failure.
+ */
+struct eventlog *
+evlog_new(TimeSpec *submit_time, InfoMessage **info_msgs, size_t infolen,
+ struct connection_closure *closure)
+{
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ struct eventlog *evlog;
+ unsigned char uuid[16];
+ size_t idx;
+ debug_decl(evlog_new, SUDO_DEBUG_UTIL);
+
+ evlog = calloc(1, sizeof(*evlog));
+ if (evlog == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+
+ /* Create a UUID to store in the event log. */
+ sudo_uuid_create(uuid);
+ if (sudo_uuid_to_string(uuid, evlog->uuid_str, sizeof(evlog->uuid_str)) == NULL) {
+ sudo_warnx("%s", U_("unable to generate UUID"));
+ goto bad;
+ }
+
+ /* Client/peer IP address. */
+ if ((evlog->peeraddr = strdup(closure->ipaddr)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+
+ /* Submit time. */
+ if (submit_time != NULL) {
+ evlog->submit_time.tv_sec = (time_t)submit_time->tv_sec;
+ evlog->submit_time.tv_nsec = (long)submit_time->tv_nsec;
+ }
+
+ /* Default values */
+ evlog->lines = 24;
+ evlog->columns = 80;
+ evlog->runuid = (uid_t)-1;
+ evlog->rungid = (gid_t)-1;
+ evlog->exit_value = -1;
+
+ /* Pull out values by key from info array. */
+ for (idx = 0; idx < infolen; idx++) {
+ InfoMessage *info = info_msgs[idx];
+ const char *key = info->key;
+ switch (key[0]) {
+ case 'c':
+ if (strcmp(key, "columns") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_NUMVAL)) {
+ if (info->u.numval <= 0 || info->u.numval > INT_MAX) {
+ errno = ERANGE;
+ sudo_warn(U_("%s: %s"), source, "columns");
+ } else {
+ evlog->columns = (int)info->u.numval;
+ }
+ }
+ continue;
+ }
+ if (strcmp(key, "command") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_STRVAL)) {
+ if ((evlog->command = strdup(info->u.strval)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ continue;
+ }
+ break;
+ case 'l':
+ if (strcmp(key, "lines") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_NUMVAL)) {
+ if (info->u.numval <= 0 || info->u.numval > INT_MAX) {
+ errno = ERANGE;
+ sudo_warn(U_("%s: %s"), source, "lines");
+ } else {
+ evlog->lines = (int)info->u.numval;
+ }
+ }
+ continue;
+ }
+ break;
+ case 'r':
+ if (strcmp(key, "runargv") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_STRLISTVAL)) {
+ evlog->runargv = strlist_copy(info->u.strlistval);
+ if (evlog->runargv == NULL)
+ goto bad;
+ }
+ continue;
+ }
+ if (strcmp(key, "runchroot") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_STRVAL)) {
+ if ((evlog->runchroot = strdup(info->u.strval)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ continue;
+ }
+ if (strcmp(key, "runcwd") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_STRVAL)) {
+ if ((evlog->runcwd = strdup(info->u.strval)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ continue;
+ }
+ if (strcmp(key, "runenv") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_STRLISTVAL)) {
+ evlog->runenv = strlist_copy(info->u.strlistval);
+ if (evlog->runenv == NULL)
+ goto bad;
+ }
+ continue;
+ }
+ if (strcmp(key, "rungid") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_NUMVAL)) {
+ if (info->u.numval < 0 || info->u.numval > UINT_MAX) {
+ errno = ERANGE;
+ sudo_warn(U_("%s: %s"), source, "rungid");
+ } else {
+ evlog->rungid = (gid_t)info->u.numval;
+ }
+ }
+ continue;
+ }
+ if (strcmp(key, "rungroup") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_STRVAL)) {
+ if ((evlog->rungroup = strdup(info->u.strval)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ continue;
+ }
+ if (strcmp(key, "runuid") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_NUMVAL)) {
+ if (info->u.numval < 0 || info->u.numval > UINT_MAX) {
+ errno = ERANGE;
+ sudo_warn(U_("%s: %s"), source, "runuid");
+ } else {
+ evlog->runuid = (uid_t)info->u.numval;
+ }
+ }
+ continue;
+ }
+ if (strcmp(key, "runuser") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_STRVAL)) {
+ if ((evlog->runuser = strdup(info->u.strval)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ continue;
+ }
+ break;
+ case 's':
+ if (strcmp(key, "source") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_STRVAL)) {
+ if ((evlog->source = strdup(info->u.strval)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ continue;
+ }
+ if (strcmp(key, "submitcwd") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_STRVAL)) {
+ if ((evlog->cwd = strdup(info->u.strval)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ continue;
+ }
+ if (strcmp(key, "submitenv") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_STRLISTVAL)) {
+ evlog->submitenv = strlist_copy(info->u.strlistval);
+ if (evlog->submitenv == NULL)
+ goto bad;
+ }
+ continue;
+ }
+ if (strcmp(key, "submitgroup") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_STRVAL)) {
+ if ((evlog->submitgroup = strdup(info->u.strval)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ continue;
+ }
+ if (strcmp(key, "submithost") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_STRVAL)) {
+ if ((evlog->submithost = strdup(info->u.strval)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ continue;
+ }
+ if (strcmp(key, "submituser") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_STRVAL)) {
+ if ((evlog->submituser = strdup(info->u.strval)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ continue;
+ }
+ break;
+ case 't':
+ if (strcmp(key, "ttyname") == 0) {
+ if (type_matches(info, source, INFO_MESSAGE__VALUE_STRVAL)) {
+ if ((evlog->ttyname = strdup(info->u.strval)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ continue;
+ }
+ break;
+ }
+ }
+
+ /* Check for required settings */
+ if (evlog->submituser == NULL) {
+ sudo_warnx(U_("%s: protocol error: %s missing from AcceptMessage"),
+ source, "submituser");
+ goto bad;
+ }
+ if (evlog->submithost == NULL) {
+ sudo_warnx(U_("%s: protocol error: %s missing from AcceptMessage"),
+ source, "submithost");
+ goto bad;
+ }
+ if (evlog->runuser == NULL) {
+ sudo_warnx(U_("%s: protocol error: %s missing from AcceptMessage"),
+ source, "runuser");
+ goto bad;
+ }
+ if (evlog->command == NULL) {
+ sudo_warnx(U_("%s: protocol error: %s missing from AcceptMessage"),
+ source, "command");
+ goto bad;
+ }
+
+ /* Other settings that must exist for event logging. */
+ if (evlog->cwd == NULL) {
+ if ((evlog->cwd = strdup("unknown")) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ if (evlog->runcwd == NULL) {
+ if ((evlog->runcwd = strdup(evlog->cwd)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ if (evlog->submitgroup == NULL) {
+ /* TODO: make submitgroup required */
+ if ((evlog->submitgroup = strdup("unknown")) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ if (evlog->ttyname == NULL) {
+ if ((evlog->ttyname = strdup("unknown")) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+
+ debug_return_ptr(evlog);
+
+bad:
+ eventlog_free(evlog);
+ debug_return_ptr(NULL);
+}
+
+struct iolog_path_closure {
+ char *iolog_dir;
+ struct eventlog *evlog;
+};
+
+static size_t
+fill_seq(char *str, size_t strsize, void *v)
+{
+ struct iolog_path_closure *closure = v;
+ char *sessid = closure->evlog->sessid;
+ int len;
+ debug_decl(fill_seq, SUDO_DEBUG_UTIL);
+
+ if (sessid[0] == '\0') {
+ if (!iolog_nextid(closure->iolog_dir, sessid))
+ debug_return_size_t((size_t)-1);
+ }
+
+ /* Path is of the form /var/log/sudo-io/00/00/01. */
+ len = snprintf(str, strsize, "%c%c/%c%c/%c%c", sessid[0],
+ sessid[1], sessid[2], sessid[3], sessid[4], sessid[5]);
+ if (len < 0 || len >= (ssize_t)strsize) {
+ sudo_warnx(U_("%s: unable to format session id"), __func__);
+ debug_return_size_t(strsize); /* handle non-standard snprintf() */
+ }
+ debug_return_size_t((size_t)len);
+}
+
+static size_t
+fill_user(char * restrict str, size_t strsize, void * restrict v)
+{
+ struct iolog_path_closure *closure = v;
+ const struct eventlog *evlog = closure->evlog;
+ debug_decl(fill_user, SUDO_DEBUG_UTIL);
+
+ if (evlog->submituser == NULL) {
+ sudo_warnx(U_("%s: %s is not set"), __func__, "submituser");
+ debug_return_size_t(strsize);
+ }
+ debug_return_size_t(strlcpy(str, evlog->submituser, strsize));
+}
+
+static size_t
+fill_group(char * restrict str, size_t strsize, void * restrict v)
+{
+ struct iolog_path_closure *closure = v;
+ const struct eventlog *evlog = closure->evlog;
+ debug_decl(fill_group, SUDO_DEBUG_UTIL);
+
+ if (evlog->submitgroup == NULL) {
+ sudo_warnx(U_("%s: %s is not set"), __func__, "submitgroup");
+ debug_return_size_t(strsize);
+ }
+ debug_return_size_t(strlcpy(str, evlog->submitgroup, strsize));
+}
+
+static size_t
+fill_runas_user(char * restrict str, size_t strsize, void * restrict v)
+{
+ struct iolog_path_closure *closure = v;
+ const struct eventlog *evlog = closure->evlog;
+ debug_decl(fill_runas_user, SUDO_DEBUG_UTIL);
+
+ if (evlog->runuser == NULL) {
+ sudo_warnx(U_("%s: %s is not set"), __func__, "runuser");
+ debug_return_size_t(strsize);
+ }
+ debug_return_size_t(strlcpy(str, evlog->runuser, strsize));
+}
+
+static size_t
+fill_runas_group(char * restrict str, size_t strsize, void * restrict v)
+{
+ struct iolog_path_closure *closure = v;
+ const struct eventlog *evlog = closure->evlog;
+ debug_decl(fill_runas_group, SUDO_DEBUG_UTIL);
+
+ /* FIXME: rungroup not guaranteed to be set */
+ if (evlog->rungroup == NULL) {
+ sudo_warnx(U_("%s: %s is not set"), __func__, "rungroup");
+ debug_return_size_t(strsize);
+ }
+ debug_return_size_t(strlcpy(str, evlog->rungroup, strsize));
+}
+
+static size_t
+fill_hostname(char * restrict str, size_t strsize, void * restrict v)
+{
+ struct iolog_path_closure *closure = v;
+ const struct eventlog *evlog = closure->evlog;
+ debug_decl(fill_hostname, SUDO_DEBUG_UTIL);
+
+ if (evlog->submithost == NULL) {
+ sudo_warnx(U_("%s: %s is not set"), __func__, "submithost");
+ debug_return_size_t(strsize);
+ }
+ debug_return_size_t(strlcpy(str, evlog->submithost, strsize));
+}
+
+static size_t
+fill_command(char * restrict str, size_t strsize, void * restrict v)
+{
+ struct iolog_path_closure *closure = v;
+ const struct eventlog *evlog = closure->evlog;
+ debug_decl(fill_command, SUDO_DEBUG_UTIL);
+
+ if (evlog->command == NULL) {
+ sudo_warnx(U_("%s: %s is not set"), __func__, "command");
+ debug_return_size_t(strsize);
+ }
+ debug_return_size_t(strlcpy(str, evlog->command, strsize));
+}
+
+/* Note: "seq" must be first in the list. */
+static const struct iolog_path_escape path_escapes[] = {
+ { "seq", fill_seq },
+ { "user", fill_user },
+ { "group", fill_group },
+ { "runas_user", fill_runas_user },
+ { "runas_group", fill_runas_group },
+ { "hostname", fill_hostname },
+ { "command", fill_command },
+ { NULL, NULL }
+};
+
+/*
+ * Create I/O log path
+ * Sets iolog_path, iolog_file and iolog_dir_fd in the closure
+ */
+static bool
+create_iolog_path(struct connection_closure *closure)
+{
+ struct eventlog *evlog = closure->evlog;
+ struct iolog_path_closure path_closure;
+ char expanded_dir[PATH_MAX], expanded_file[PATH_MAX], pathbuf[PATH_MAX];
+ int len;
+ debug_decl(create_iolog_path, SUDO_DEBUG_UTIL);
+
+ path_closure.evlog = evlog;
+ path_closure.iolog_dir = expanded_dir;
+
+ if (!expand_iolog_path(logsrvd_conf_iolog_dir(), expanded_dir,
+ sizeof(expanded_dir), &path_escapes[1], &path_closure)) {
+ sudo_warnx(U_("unable to expand iolog path %s"),
+ logsrvd_conf_iolog_dir());
+ goto bad;
+ }
+
+ if (!expand_iolog_path(logsrvd_conf_iolog_file(), expanded_file,
+ sizeof(expanded_file), &path_escapes[0], &path_closure)) {
+ sudo_warnx(U_("unable to expand iolog path %s"),
+ logsrvd_conf_iolog_file());
+ goto bad;
+ }
+
+ len = snprintf(pathbuf, sizeof(pathbuf), "%s/%s", expanded_dir,
+ expanded_file);
+ if (len < 0 || len >= ssizeof(pathbuf)) {
+ errno = ENAMETOOLONG;
+ sudo_warn("%s/%s", expanded_dir, expanded_file);
+ goto bad;
+ }
+
+ /*
+ * Create log path, along with any intermediate subdirs.
+ * Calls mkdtemp() if pathbuf ends in XXXXXX.
+ */
+ if (!iolog_mkpath(pathbuf)) {
+ sudo_warn(U_("unable to create iolog path %s"), pathbuf);
+ goto bad;
+ }
+ if ((evlog->iolog_path = strdup(pathbuf)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ evlog->iolog_file = evlog->iolog_path + strlen(expanded_dir) + 1;
+
+ /* We use iolog_dir_fd in calls to openat(2) */
+ closure->iolog_dir_fd =
+ iolog_openat(AT_FDCWD, evlog->iolog_path, O_RDONLY);
+ if (closure->iolog_dir_fd == -1) {
+ sudo_warn("%s", evlog->iolog_path);
+ goto bad;
+ }
+
+ debug_return_bool(true);
+bad:
+ free(evlog->iolog_path);
+ evlog->iolog_path = NULL;
+ debug_return_bool(false);
+}
+
+bool
+iolog_create(int iofd, struct connection_closure *closure)
+{
+ debug_decl(iolog_create, SUDO_DEBUG_UTIL);
+
+ if (iofd < 0 || iofd >= IOFD_MAX) {
+ sudo_warnx(U_("invalid iofd %d"), iofd);
+ debug_return_bool(false);
+ }
+
+ closure->iolog_files[iofd].enabled = true;
+ debug_return_bool(iolog_open(&closure->iolog_files[iofd],
+ closure->iolog_dir_fd, iofd, "w"));
+}
+
+void
+iolog_close_all(struct connection_closure *closure)
+{
+ const char *errstr;
+ unsigned int i;
+ debug_decl(iolog_close_all, SUDO_DEBUG_UTIL);
+
+ for (i = 0; i < IOFD_MAX; i++) {
+ if (!closure->iolog_files[i].enabled)
+ continue;
+ if (!iolog_close(&closure->iolog_files[i], &errstr)) {
+ sudo_warnx(U_("error closing iofd %u: %s"), i, errstr);
+ }
+ }
+ if (closure->iolog_dir_fd != -1)
+ close(closure->iolog_dir_fd);
+
+ debug_return;
+}
+
+bool
+iolog_flush_all(struct connection_closure *closure)
+{
+ const char *errstr;
+ bool ret = true;
+ unsigned int i;
+ debug_decl(iolog_flush_all, SUDO_DEBUG_UTIL);
+
+ for (i = 0; i < IOFD_MAX; i++) {
+ if (!closure->iolog_files[i].enabled)
+ continue;
+ if (!iolog_flush(&closure->iolog_files[i], &errstr)) {
+ sudo_warnx(U_("error flushing iofd %u: %s"), i, errstr);
+ ret = false;
+ }
+ }
+
+ debug_return_bool(ret);
+}
+
+bool
+iolog_init(AcceptMessage *msg, struct connection_closure *closure)
+{
+ struct eventlog *evlog = closure->evlog;
+ debug_decl(iolog_init, SUDO_DEBUG_UTIL);
+
+ /* Create I/O log path */
+ if (!create_iolog_path(closure))
+ debug_return_bool(false);
+
+ /* Write sudo I/O log info file */
+ if (!iolog_write_info_file(closure->iolog_dir_fd, evlog))
+ debug_return_bool(false);
+
+ /*
+ * Create timing, stdout, stderr and ttyout files for sudoreplay.
+ * Others will be created on demand.
+ */
+ if (!iolog_create(IOFD_TIMING, closure) ||
+ !iolog_create(IOFD_STDOUT, closure) ||
+ !iolog_create(IOFD_STDERR, closure) ||
+ !iolog_create(IOFD_TTYOUT, closure))
+ debug_return_bool(false);
+
+ /* Ready to log I/O buffers. */
+ debug_return_bool(true);
+}
+
+/*
+ * Copy len bytes from src to dst.
+ */
+static bool
+iolog_copy(struct iolog_file *src, struct iolog_file *dst, off_t remainder,
+ const char **errstr)
+{
+ char buf[64 * 1024];
+ ssize_t nread;
+ debug_decl(iolog_copy, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "copying %lld bytes", (long long)remainder);
+ while (remainder > 0) {
+ const size_t toread = MIN((size_t)remainder, sizeof(buf));
+ nread = iolog_read(src, buf, toread, errstr);
+ if (nread == -1)
+ debug_return_bool(false);
+ remainder -= nread;
+
+ do {
+ ssize_t nwritten = iolog_write(dst, buf, (size_t)nread, errstr);
+ if (nwritten == -1)
+ debug_return_bool(false);
+ nread -= nwritten;
+ } while (nread > 0);
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Like rename(2) but changes UID as needed.
+ */
+static bool
+iolog_rename(const char *from, const char *to)
+{
+ bool ok, uid_changed = false;
+ debug_decl(iolog_rename, SUDO_DEBUG_UTIL);
+
+ ok = rename(from, to) == 0;
+ if (!ok && errno == EACCES) {
+ uid_changed = iolog_swapids(false);
+ if (uid_changed)
+ ok = rename(from, to) == 0;
+ }
+
+ if (uid_changed) {
+ if (!iolog_swapids(true))
+ ok = false;
+ }
+ debug_return_bool(ok);
+}
+
+/* Compressed logs don't support random access, need to rewrite them. */
+bool
+iolog_rewrite(const struct timespec *target, struct connection_closure *closure)
+{
+ const struct eventlog *evlog = closure->evlog;
+ struct iolog_file new_iolog_files[IOFD_MAX];
+ off_t iolog_file_sizes[IOFD_MAX] = { 0 };
+ struct timing_closure timing;
+ int iofd, len, tmpdir_fd = -1;
+ const char *name, *errstr;
+ char tmpdir[PATH_MAX];
+ bool ret = false;
+ debug_decl(iolog_rewrite, SUDO_DEBUG_UTIL);
+
+ memset(&timing, 0, sizeof(timing));
+ timing.decimal = ".";
+
+ /* Parse timing file until we reach the target point. */
+ /* TODO: use iolog_seekto with a callback? */
+ for (;;) {
+ /* Read next record from timing file. */
+ if (iolog_read_timing_record(&closure->iolog_files[IOFD_TIMING], &timing) != 0)
+ goto done;
+ sudo_timespecadd(&timing.delay, &closure->elapsed_time,
+ &closure->elapsed_time);
+ if (timing.event < IOFD_TIMING) {
+ if (!closure->iolog_files[timing.event].enabled) {
+ /* Missing log file. */
+ sudo_warnx(U_("invalid I/O log %s: %s referenced but not present"),
+ evlog->iolog_path, iolog_fd_to_name(timing.event));
+ goto done;
+ }
+ iolog_file_sizes[timing.event] += (off_t)timing.u.nbytes;
+ }
+
+ if (sudo_timespeccmp(&closure->elapsed_time, target, >=)) {
+ if (sudo_timespeccmp(&closure->elapsed_time, target, ==))
+ break;
+
+ /* Mismatch between resume point and stored log. */
+ sudo_warnx(U_("%s: unable to find resume point [%lld, %ld]"),
+ evlog->iolog_path, (long long)target->tv_sec, target->tv_nsec);
+ goto done;
+ }
+ }
+ iolog_file_sizes[IOFD_TIMING] =
+ iolog_seek(&closure->iolog_files[IOFD_TIMING], 0, SEEK_CUR);
+ iolog_rewind(&closure->iolog_files[IOFD_TIMING]);
+
+ /* Create new I/O log files in a temporary directory. */
+ len = snprintf(tmpdir, sizeof(tmpdir), "%s/restart.XXXXXX",
+ evlog->iolog_path);
+ if (len < 0 || len >= ssizeof(tmpdir)) {
+ errno = ENAMETOOLONG;
+ sudo_warn("%s/restart.XXXXXX", evlog->iolog_path);
+ goto done;
+ }
+ if (!iolog_mkdtemp(tmpdir)) {
+ sudo_warn(U_("unable to mkdir %s"), tmpdir);
+ goto done;
+ }
+ if ((tmpdir_fd = iolog_openat(AT_FDCWD, tmpdir, O_RDONLY)) == -1) {
+ sudo_warn(U_("unable to open %s"), tmpdir);
+ goto done;
+ }
+
+ /* Create new copies of the existing iologs */
+ memset(new_iolog_files, 0, sizeof(new_iolog_files));
+ for (iofd = 0; iofd < IOFD_MAX; iofd++) {
+ if (!closure->iolog_files[iofd].enabled)
+ continue;
+ new_iolog_files[iofd].enabled = true;
+ if (!iolog_open(&new_iolog_files[iofd], tmpdir_fd, iofd, "w")) {
+ if (errno != ENOENT) {
+ sudo_warn(U_("unable to open %s/%s"),
+ tmpdir, iolog_fd_to_name(iofd));
+ goto done;
+ }
+ }
+ }
+
+ for (iofd = 0; iofd < IOFD_MAX; iofd++) {
+ if (!closure->iolog_files[iofd].enabled)
+ continue;
+ if (!iolog_copy(&closure->iolog_files[iofd], &new_iolog_files[iofd],
+ iolog_file_sizes[iofd], &errstr)) {
+ name = iolog_fd_to_name(iofd);
+ sudo_warnx(U_("unable to copy %s/%s to %s/%s: %s"),
+ evlog->iolog_path, name, tmpdir, name, errstr);
+ goto done;
+ }
+ }
+
+ /* Move copied log files into place. */
+ for (iofd = 0; iofd < IOFD_MAX; iofd++) {
+ char from[PATH_MAX], to[PATH_MAX];
+
+ if (!closure->iolog_files[iofd].enabled)
+ continue;
+
+ /* This would be easier with renameat(2), old systems are annoying. */
+ name = iolog_fd_to_name(iofd);
+ len = snprintf(from, sizeof(from), "%s/%s", tmpdir, name);
+ if (len < 0 || len >= ssizeof(from)) {
+ errno = ENAMETOOLONG;
+ sudo_warn("%s/%s", tmpdir, name);
+ goto done;
+ }
+ len = snprintf(to, sizeof(to), "%s/%s", evlog->iolog_path,
+ name);
+ if (len < 0 || len >= ssizeof(from)) {
+ errno = ENAMETOOLONG;
+ sudo_warn("%s/%s", evlog->iolog_path, name);
+ goto done;
+ }
+ if (!iolog_rename(from, to)) {
+ sudo_warn(U_("unable to rename %s to %s"), from, to);
+ goto done;
+ }
+ }
+
+ for (iofd = 0; iofd < IOFD_MAX; iofd++) {
+ if (!closure->iolog_files[iofd].enabled)
+ continue;
+ (void)iolog_close(&closure->iolog_files[iofd], &errstr);
+ closure->iolog_files[iofd] = new_iolog_files[iofd];
+ new_iolog_files[iofd].enabled = false;
+ }
+
+ /* Ready to log I/O buffers. */
+ ret = true;
+done:
+ if (tmpdir_fd != -1) {
+ if (!ret) {
+ for (iofd = 0; iofd < IOFD_MAX; iofd++) {
+ if (!new_iolog_files[iofd].enabled)
+ continue;
+ (void)iolog_close(&new_iolog_files[iofd], &errstr);
+ (void)unlinkat(tmpdir_fd, iolog_fd_to_name(iofd), 0);
+ }
+ }
+ close(tmpdir_fd);
+ (void)rmdir(tmpdir);
+ }
+ debug_return_bool(ret);
+}
+
+/*
+ * Add given delta to elapsed time.
+ * We cannot use timespecadd here since delta is not struct timespec.
+ */
+void
+update_elapsed_time(TimeSpec *delta, struct timespec *elapsed)
+{
+ debug_decl(update_elapsed_time, SUDO_DEBUG_UTIL);
+
+ /* Cannot use timespecadd since msg doesn't use struct timespec. */
+ elapsed->tv_sec += (time_t)delta->tv_sec;
+ elapsed->tv_nsec += (long)delta->tv_nsec;
+ while (elapsed->tv_nsec >= 1000000000) {
+ elapsed->tv_sec++;
+ elapsed->tv_nsec -= 1000000000;
+ }
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "%s: delta [%lld, %d], elapsed time now [%lld, %ld]",
+ __func__, (long long)delta->tv_sec, delta->tv_nsec,
+ (long long)elapsed->tv_sec, elapsed->tv_nsec);
+
+ debug_return;
+}
diff --git a/logsrvd/logsrv_util.c b/logsrvd/logsrv_util.c
new file mode 100644
index 0000000..fd972f6
--- /dev/null
+++ b/logsrvd/logsrv_util.c
@@ -0,0 +1,191 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+
+#include <errno.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_iolog.h>
+#include <sudo_util.h>
+
+#include "logsrv_util.h"
+
+/*
+ * Expand buf as needed or just reset it.
+ */
+bool
+expand_buf(struct connection_buffer *buf, size_t needed)
+{
+ void *newdata;
+ debug_decl(expand_buf, SUDO_DEBUG_UTIL);
+
+ if (buf->size < needed) {
+ /* Expand buffer. */
+ const size_t newsize = sudo_pow2_roundup(needed);
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "expanding buffer from %zu to %zu", buf->size, newsize);
+ if (newsize < needed) {
+ /* overflow */
+ errno = ENOMEM;
+ goto oom;
+ }
+ if ((newdata = malloc(newsize)) == NULL)
+ goto oom;
+ if (buf->len != buf->off)
+ memcpy(newdata, buf->data + buf->off, buf->len - buf->off);
+ free(buf->data);
+ buf->data = newdata;
+ buf->size = newsize;
+ } else {
+ /* Just reset existing buffer. */
+ if (buf->len != buf->off) {
+ memmove(buf->data, buf->data + buf->off,
+ buf->len - buf->off);
+ }
+ }
+ buf->len -= buf->off;
+ buf->off = 0;
+
+ debug_return_bool(true);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+}
+
+/*
+ * Open any I/O log files that are present.
+ * The timing file must always exist.
+ */
+bool
+iolog_open_all(int dfd, const char *iolog_dir, struct iolog_file *iolog_files,
+ const char *mode)
+{
+ int iofd;
+ debug_decl(iolog_open_all, SUDO_DEBUG_UTIL);
+
+ for (iofd = 0; iofd < IOFD_MAX; iofd++) {
+ iolog_files[iofd].enabled = true;
+ if (!iolog_open(&iolog_files[iofd], dfd, iofd, mode)) {
+ if (errno != ENOENT) {
+ sudo_warn(U_("unable to open %s/%s"), iolog_dir,
+ iolog_fd_to_name(iofd));
+ debug_return_bool(false);
+ }
+ }
+ }
+ if (!iolog_files[IOFD_TIMING].enabled) {
+ sudo_warn(U_("unable to open %s/%s"), iolog_dir,
+ iolog_fd_to_name(IOFD_TIMING));
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+/*
+ * Seek to the specified point in time in the I/O logs.
+ */
+bool
+iolog_seekto(int iolog_dir_fd, const char *iolog_path,
+ struct iolog_file *iolog_files, struct timespec *elapsed_time,
+ const struct timespec *target)
+{
+ struct timing_closure timing;
+ off_t pos;
+ debug_decl(iolog_seekto, SUDO_DEBUG_UTIL);
+
+ if (!sudo_timespecisset(target)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "resuming at start of file [0, 0]");
+ debug_return_bool(true);
+ }
+
+ memset(&timing, 0, sizeof(timing));
+ timing.decimal = ".";
+
+ /* Parse timing file until we reach the target point. */
+ for (;;) {
+ switch (iolog_read_timing_record(&iolog_files[IOFD_TIMING], &timing)) {
+ case 0:
+ break;
+ case 1:
+ /* EOF reading timing file. */
+ sudo_warnx(U_("%s/%s: unable to find resume point [%lld, %ld]"),
+ iolog_path, "timing", (long long)target->tv_sec,
+ target->tv_nsec);
+ goto bad;
+ default:
+ /* Error printed by iolog_read_timing_record(). */
+ goto bad;
+ }
+ sudo_timespecadd(elapsed_time, &timing.delay, elapsed_time);
+ if (timing.event < IOFD_TIMING) {
+ if (!iolog_files[timing.event].enabled) {
+ /* Missing log file. */
+ sudo_warn(U_("missing I/O log file %s/%s"), iolog_path,
+ iolog_fd_to_name(timing.event));
+ goto bad;
+ }
+ pos = iolog_seek(&iolog_files[timing.event], (off_t)timing.u.nbytes,
+ SEEK_CUR);
+ if (pos == -1) {
+ sudo_warn(U_("%s/%s: unable to seek forward %zu"), iolog_path,
+ iolog_fd_to_name(timing.event), timing.u.nbytes);
+ goto bad;
+ }
+ }
+ if (sudo_timespeccmp(elapsed_time, target, >=)) {
+ if (sudo_timespeccmp(elapsed_time, target, ==))
+ break;
+
+ /* Mismatch between resume point and stored log. */
+ sudo_warnx(U_("%s/%s: unable to find resume point [%lld, %ld]"),
+ iolog_path, "timing", (long long)target->tv_sec,
+ target->tv_nsec);
+ goto bad;
+ }
+ }
+ debug_return_bool(true);
+bad:
+ debug_return_bool(false);
+}
diff --git a/logsrvd/logsrv_util.h b/logsrvd/logsrv_util.h
new file mode 100644
index 0000000..cbf3655
--- /dev/null
+++ b/logsrvd/logsrv_util.h
@@ -0,0 +1,63 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_LOGSRV_UTIL_H
+#define SUDO_LOGSRV_UTIL_H
+
+#include <netinet/in.h> /* for INET_ADDRSTRLEN and INET6_ADDRSTRLEN */
+
+#ifndef INET_ADDRSTRLEN
+# define INET_ADDRSTRLEN 16
+#endif
+#ifndef INET6_ADDRSTRLEN
+# define INET6_ADDRSTRLEN 46
+#endif
+
+/* Default ports to listen on */
+#define DEFAULT_PORT "30343"
+#define DEFAULT_PORT_TLS "30344"
+
+/* Maximum message size (2Mb) */
+#define MESSAGE_SIZE_MAX (2 * 1024 * 1024)
+
+struct peer_info {
+ const char *name;
+#if defined(HAVE_STRUCT_IN6_ADDR)
+ char ipaddr[INET6_ADDRSTRLEN];
+#else
+ char ipaddr[INET_ADDRSTRLEN];
+#endif
+};
+
+struct connection_buffer {
+ TAILQ_ENTRY(connection_buffer) entries;
+ uint8_t *data;
+ size_t size;
+ size_t len;
+ size_t off;
+};
+TAILQ_HEAD(connection_buffer_list, connection_buffer);
+
+/* logsrv_util.c */
+struct iolog_file;
+bool expand_buf(struct connection_buffer *buf, size_t needed);
+bool iolog_open_all(int dfd, const char *iolog_dir, struct iolog_file *iolog_files, const char *mode);
+bool iolog_seekto(int iolog_dir_fd, const char *iolog_path, struct iolog_file *iolog_files, struct timespec *elapsed_time, const struct timespec *target);
+
+
+#endif /* SUDO_LOGSRV_UTIL_H */
diff --git a/logsrvd/logsrvd.c b/logsrvd/logsrvd.c
new file mode 100644
index 0000000..a3c3af3
--- /dev/null
+++ b/logsrvd/logsrvd.c
@@ -0,0 +1,2059 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#ifdef HAVE_GETOPT_LONG
+# include <getopt.h>
+# else
+# include <compat/getopt.h>
+#endif /* HAVE_GETOPT_LONG */
+
+#define NEED_INET_NTOP /* to expose sudo_inet_ntop in sudo_compat.h */
+
+#include <pathnames.h>
+#include <sudo_compat.h>
+#include <sudo_conf.h>
+#include <sudo_debug.h>
+#include <sudo_event.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_json.h>
+#include <sudo_iolog.h>
+#include <sudo_queue.h>
+#include <sudo_rand.h>
+#include <sudo_util.h>
+
+#include <logsrvd.h>
+#include <hostcheck.h>
+
+#ifndef O_NOFOLLOW
+# define O_NOFOLLOW 0
+#endif
+
+/*
+ * Sudo I/O audit server.
+ */
+static int logsrvd_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
+TAILQ_HEAD(connection_list, connection_closure);
+static struct connection_list connections = TAILQ_HEAD_INITIALIZER(connections);
+static struct listener_list listeners = TAILQ_HEAD_INITIALIZER(listeners);
+static const char server_id[] = "Sudo Audit Server " PACKAGE_VERSION;
+static const char *conf_file = NULL;
+
+/* Event loop callbacks. */
+static void client_msg_cb(int fd, int what, void *v);
+static void server_msg_cb(int fd, int what, void *v);
+static void server_commit_cb(int fd, int what, void *v);
+#if defined(HAVE_OPENSSL)
+static void tls_handshake_cb(int fd, int what, void *v);
+#endif
+
+/*
+ * Free a struct connection_closure container and its contents.
+ */
+static void
+connection_closure_free(struct connection_closure *closure)
+{
+ debug_decl(connection_closure_free, SUDO_DEBUG_UTIL);
+
+ if (closure != NULL) {
+ bool shutting_down = closure->state == SHUTDOWN;
+ struct sudo_event_base *evbase = closure->evbase;
+ struct connection_buffer *buf;
+
+ TAILQ_REMOVE(&connections, closure, entries);
+
+ if (closure->state == CONNECTING && closure->journal != NULL) {
+ /* Failed to relay journal file, retry later. */
+ logsrvd_queue_insert(closure);
+ }
+ if (closure->relay_closure != NULL)
+ relay_closure_free(closure->relay_closure);
+#if defined(HAVE_OPENSSL)
+ if (closure->ssl != NULL) {
+ /* Must call SSL_shutdown() before closing closure->sock. */
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "closing down TLS connection from %s", closure->ipaddr);
+ if (SSL_shutdown(closure->ssl) == 0)
+ SSL_shutdown(closure->ssl);
+ SSL_free(closure->ssl);
+ }
+#endif
+ if (closure->sock != -1) {
+ shutdown(closure->sock, SHUT_RDWR);
+ close(closure->sock);
+ }
+ iolog_close_all(closure);
+ sudo_ev_free(closure->commit_ev);
+ sudo_ev_free(closure->read_ev);
+ sudo_ev_free(closure->write_ev);
+#if defined(HAVE_OPENSSL)
+ sudo_ev_free(closure->ssl_accept_ev);
+#endif
+ eventlog_free(closure->evlog);
+ free(closure->read_buf.data);
+ while ((buf = TAILQ_FIRST(&closure->write_bufs)) != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "discarding write buffer %p, len %zu", buf, buf->len - buf->off);
+ TAILQ_REMOVE(&closure->write_bufs, buf, entries);
+ free(buf->data);
+ free(buf);
+ }
+ while ((buf = TAILQ_FIRST(&closure->free_bufs)) != NULL) {
+ TAILQ_REMOVE(&closure->free_bufs, buf, entries);
+ free(buf->data);
+ free(buf);
+ }
+ free(closure->journal_path);
+ if (closure->journal != NULL)
+ fclose(closure->journal);
+ free(closure);
+
+ if (shutting_down && TAILQ_EMPTY(&connections))
+ sudo_ev_loopbreak(evbase);
+ }
+
+ debug_return;
+}
+
+/*
+ * Allocate a new connection closure.
+ */
+struct connection_closure *
+connection_closure_alloc(int fd, bool tls, bool relay_only,
+ struct sudo_event_base *base)
+{
+ struct connection_closure *closure;
+ debug_decl(connection_closure_alloc, SUDO_DEBUG_UTIL);
+
+ if ((closure = calloc(1, sizeof(*closure))) == NULL)
+ debug_return_ptr(NULL);
+
+ closure->iolog_dir_fd = -1;
+ closure->sock = relay_only ? -1 : fd;
+ closure->evbase = base;
+ TAILQ_INIT(&closure->write_bufs);
+ TAILQ_INIT(&closure->free_bufs);
+
+ /* Use different message handlers depending on the operating mode. */
+ if (relay_only) {
+ closure->cms = &cms_relay;
+ } else if (logsrvd_conf_relay_store_first()) {
+ closure->store_first = true;
+ closure->cms = &cms_journal;
+ } else {
+ closure->cms = &cms_local;
+ }
+
+ TAILQ_INSERT_TAIL(&connections, closure, entries);
+
+ closure->read_buf.size = 64 * 1024;
+ closure->read_buf.data = malloc(closure->read_buf.size);
+ if (closure->read_buf.data == NULL)
+ goto bad;
+
+ closure->read_ev = sudo_ev_alloc(fd, SUDO_EV_READ|SUDO_EV_PERSIST,
+ client_msg_cb, closure);
+ if (closure->read_ev == NULL)
+ goto bad;
+
+ if (!relay_only) {
+ closure->write_ev = sudo_ev_alloc(fd, SUDO_EV_WRITE|SUDO_EV_PERSIST,
+ server_msg_cb, closure);
+ if (closure->write_ev == NULL)
+ goto bad;
+
+ closure->commit_ev = sudo_ev_alloc(-1, SUDO_EV_TIMEOUT,
+ server_commit_cb, closure);
+ if (closure->commit_ev == NULL)
+ goto bad;
+ }
+#if defined(HAVE_OPENSSL)
+ if (tls) {
+ closure->ssl_accept_ev = sudo_ev_alloc(fd, SUDO_EV_READ,
+ tls_handshake_cb, closure);
+ if (closure->ssl_accept_ev == NULL)
+ goto bad;
+ }
+#endif
+
+ debug_return_ptr(closure);
+bad:
+ connection_closure_free(closure);
+ debug_return_ptr(NULL);
+}
+
+/*
+ * Close the client connection when finished.
+ * If in store-and-forward mode, initiate a relay connection.
+ * Otherwise, free the connection closure, removing any events.
+ */
+void
+connection_close(struct connection_closure *closure)
+{
+ struct connection_closure *new_closure;
+ debug_decl(connection_close, SUDO_DEBUG_UTIL);
+
+ if (closure == NULL)
+ debug_return;
+
+ /* Final state should be FINISHED except on error. */
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "%s: closure %p, final state %d, relay_closure %p, "
+ "journal file %p, journal path %s", __func__, closure,
+ closure->state, closure->relay_closure, closure->journal,
+ closure->journal_path ? closure->journal_path : "");
+
+ /*
+ * If we finished a client connection in store-and-forward mode,
+ * create a new connection for the relay and replay the journal.
+ */
+ if (closure->store_first && closure->state == FINISHED &&
+ closure->relay_closure == NULL && closure->journal != NULL) {
+ new_closure = connection_closure_alloc(fileno(closure->journal), false,
+ true, closure->evbase);
+ if (new_closure != NULL) {
+ /* Re-parent journal settings. */
+ new_closure->journal = closure->journal;
+ closure->journal = NULL;
+ new_closure->journal_path = closure->journal_path;
+ closure->journal_path = NULL;
+
+ /* Connect to the first relay available asynchronously. */
+ if (!connect_relay(new_closure)) {
+ sudo_warnx("%s", U_("unable to connect to relay"));
+ connection_closure_free(new_closure);
+ }
+ }
+ }
+ if (closure->state == FINISHED && closure->journal_path != NULL) {
+ /* Journal relayed successfully, remove backing file. */
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "removing journal file %s", closure->journal_path);
+ unlink(closure->journal_path);
+
+ /* Process the next outgoing file (if any). */
+ logsrvd_queue_enable(0, closure->evbase);
+ }
+ connection_closure_free(closure);
+
+ debug_return;
+}
+
+struct connection_buffer *
+get_free_buf(size_t len, struct connection_closure *closure)
+{
+ struct connection_buffer *buf;
+ debug_decl(get_free_buf, SUDO_DEBUG_UTIL);
+
+ buf = TAILQ_FIRST(&closure->free_bufs);
+ if (buf != NULL) {
+ TAILQ_REMOVE(&closure->free_bufs, buf, entries);
+ } else {
+ if ((buf = calloc(1, sizeof(*buf))) == NULL)
+ goto oom;
+ }
+
+ if (len > buf->size) {
+ const size_t new_size = sudo_pow2_roundup(len);
+ if (new_size < len) {
+ /* overflow */
+ errno = ENOMEM;
+ goto oom;
+ }
+ free(buf->data);
+ if ((buf->data = malloc(new_size)) == NULL)
+ goto oom;
+ buf->size = new_size;
+ }
+
+ debug_return_ptr(buf);
+oom:
+ if (buf != NULL) {
+ free(buf->data);
+ free(buf);
+ }
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_ptr(NULL);
+}
+
+static bool
+fmt_server_message(struct connection_closure *closure, ServerMessage *msg)
+{
+ struct connection_buffer *buf = NULL;
+ uint32_t msg_len;
+ bool ret = false;
+ size_t len;
+ debug_decl(fmt_server_message, SUDO_DEBUG_UTIL);
+
+ len = server_message__get_packed_size(msg);
+ if (len > MESSAGE_SIZE_MAX) {
+ sudo_warnx(U_("server message too large: %zu"), len);
+ goto done;
+ }
+
+ /* Wire message size is used for length encoding, precedes message. */
+ msg_len = htonl((uint32_t)len);
+ len += sizeof(msg_len);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "size + server message %zu bytes", len);
+
+ if ((buf = get_free_buf(len, closure)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate connection_buffer");
+ goto done;
+ }
+ memcpy(buf->data, &msg_len, sizeof(msg_len));
+ server_message__pack(msg, buf->data + sizeof(msg_len));
+ buf->len = len;
+ TAILQ_INSERT_TAIL(&closure->write_bufs, buf, entries);
+
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+static bool
+fmt_hello_message(struct connection_closure *closure)
+{
+ ServerMessage msg = SERVER_MESSAGE__INIT;
+ ServerHello hello = SERVER_HELLO__INIT;
+ debug_decl(fmt_hello_message, SUDO_DEBUG_UTIL);
+
+ /* TODO: implement redirect and servers array. */
+ hello.server_id = (char *)server_id;
+ hello.subcommands = true;
+ msg.u.hello = &hello;
+ msg.type_case = SERVER_MESSAGE__TYPE_HELLO;
+
+ debug_return_bool(fmt_server_message(closure, &msg));
+}
+
+bool
+fmt_log_id_message(const char *id, struct connection_closure *closure)
+{
+ ServerMessage msg = SERVER_MESSAGE__INIT;
+ debug_decl(fmt_log_id_message, SUDO_DEBUG_UTIL);
+
+ msg.u.log_id = (char *)id;
+ msg.type_case = SERVER_MESSAGE__TYPE_LOG_ID;
+
+ debug_return_bool(fmt_server_message(closure, &msg));
+}
+
+static bool
+fmt_error_message(const char *errstr, struct connection_closure *closure)
+{
+ ServerMessage msg = SERVER_MESSAGE__INIT;
+ debug_decl(fmt_error_message, SUDO_DEBUG_UTIL);
+
+ msg.u.error = (char *)errstr;
+ msg.type_case = SERVER_MESSAGE__TYPE_ERROR;
+
+ debug_return_bool(fmt_server_message(closure, &msg));
+}
+
+/*
+ * Format a ServerMessage with the error string and add it to the write queue.
+ * Also sets the error flag state to true.
+ * Returns true if successfully scheduled, else false.
+ */
+bool
+schedule_error_message(const char *errstr, struct connection_closure *closure)
+{
+ bool ret = false;
+ debug_decl(schedule_error_message, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "send error to client: %s", errstr ? errstr : "none");
+
+ /* Prevent further reads from the client, just write the error. */
+ sudo_ev_del(closure->evbase, closure->read_ev);
+
+ if (errstr == NULL || closure->error || closure->write_ev == NULL)
+ goto done;
+
+ /* Format error message and add to the write queue. */
+ if (!fmt_error_message(errstr, closure))
+ goto done;
+ if (sudo_ev_add(closure->evbase, closure->write_ev,
+ logsrvd_conf_server_timeout(), true) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto done;
+ }
+ ret = true;
+
+done:
+ closure->error = true;
+ debug_return_bool(ret);
+}
+
+/*
+ * AcceptMessage handler.
+ */
+static bool
+handle_accept(AcceptMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ bool ret;
+ debug_decl(handle_accept, SUDO_DEBUG_UTIL);
+
+ /* We can get an AcceptMessage for a sub-command during a session. */
+ if (closure->state == EXITED || closure->state == FINISHED) {
+ sudo_warnx(U_("unexpected state %d for %s"), closure->state, source);
+ closure->errstr = _("state machine error");
+ debug_return_bool(false);
+ }
+
+ /* Check that message is valid. */
+ if (msg->submit_time == NULL || msg->n_info_msgs == 0) {
+ sudo_warnx(U_("%s: %s"), source, U_("invalid AcceptMessage"));
+ closure->errstr = _("invalid AcceptMessage");
+ debug_return_bool(false);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: received AcceptMessage from %s",
+ __func__, source);
+
+ ret = closure->cms->accept(msg, buf, len, closure);
+ if (ret && closure->state == INITIAL) {
+ if (msg->expect_iobufs)
+ closure->log_io = true;
+ closure->state = RUNNING;
+ }
+ debug_return_bool(ret);
+}
+
+/*
+ * RejectMessage handler.
+ */
+static bool
+handle_reject(RejectMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ bool ret;
+ debug_decl(handle_reject, SUDO_DEBUG_UTIL);
+
+ /* We can get a RejectMessage for a sub-command during a session. */
+ if (closure->state == EXITED || closure->state == FINISHED) {
+ sudo_warnx(U_("unexpected state %d for %s"), closure->state, source);
+ closure->errstr = _("state machine error");
+ debug_return_bool(false);
+ }
+
+ /* Check that message is valid. */
+ if (msg->submit_time == NULL || msg->n_info_msgs == 0) {
+ sudo_warnx(U_("%s: %s"), source, U_("invalid RejectMessage"));
+ closure->errstr = _("invalid RejectMessage");
+ debug_return_bool(false);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: received RejectMessage from %s",
+ __func__, source);
+
+ ret = closure->cms->reject(msg, buf, len, closure);
+ if (ret && closure->state == INITIAL) {
+ closure->state = FINISHED;
+ }
+
+ debug_return_bool(ret);
+}
+
+static bool
+handle_exit(ExitMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ bool ret;
+ debug_decl(handle_exit, SUDO_DEBUG_UTIL);
+
+ if (closure->state != RUNNING) {
+ sudo_warnx(U_("unexpected state %d for %s"), closure->state, source);
+ closure->errstr = _("state machine error");
+ debug_return_bool(false);
+ }
+
+ /* Check that message is valid. */
+ if (msg->run_time == NULL) {
+ sudo_warnx(U_("%s: %s"), source, U_("invalid ExitMessage"));
+ closure->errstr = _("invalid ExitMessage");
+ debug_return_bool(false);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: received ExitMessage from %s",
+ source, __func__);
+
+ ret = closure->cms->exit(msg, buf, len, closure);
+ if (ret) {
+ if (sudo_timespecisset(&closure->elapsed_time)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: elapsed time: [%lld, %ld]",
+ __func__, (long long)closure->elapsed_time.tv_sec,
+ closure->elapsed_time.tv_nsec);
+ }
+
+ if (closure->log_io) {
+ /* Command exited, client waiting for final commit point. */
+ closure->state = EXITED;
+
+ /* Relay host will send the final commit point. */
+ if (closure->relay_closure == NULL) {
+ struct timespec tv = { 0, 0 };
+ if (sudo_ev_add(closure->evbase, closure->commit_ev, &tv, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ ret = false;
+ }
+ }
+ } else {
+ /* No commit point to send to client, we are finished. */
+ closure->state = FINISHED;
+ }
+ }
+ sudo_ev_del(closure->evbase, closure->read_ev);
+
+ debug_return_bool(ret);
+}
+
+static bool
+handle_restart(RestartMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ bool ret = true;
+ debug_decl(handle_restart, SUDO_DEBUG_UTIL);
+
+ if (closure->state != INITIAL) {
+ sudo_warnx(U_("unexpected state %d for %s"), closure->state, source);
+ closure->errstr = _("state machine error");
+ debug_return_bool(false);
+ }
+
+ /* Check that message is valid. */
+ if (msg->log_id == NULL || msg->resume_point == NULL) {
+ sudo_warnx(U_("%s: %s"), source, U_("invalid RestartMessage"));
+ closure->errstr = _("invalid RestartMessage");
+ debug_return_bool(false);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: received RestartMessage for %s from %s", __func__, msg->log_id,
+ source);
+
+ /* Only I/O logs are restartable. */
+ closure->log_io = true;
+
+ if (closure->cms->restart(msg, buf, len, closure)) {
+ /* Successfully restarted. */
+ closure->state = RUNNING;
+ } else {
+ /* Report error to client before closing the connection. */
+ sudo_debug_printf(SUDO_DEBUG_WARN, "%s: unable to restart I/O log",
+ __func__);
+ if (!schedule_error_message(closure->errstr, closure))
+ ret = false;
+ }
+
+ debug_return_bool(ret);
+}
+
+static bool
+handle_alert(AlertMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ debug_decl(handle_alert, SUDO_DEBUG_UTIL);
+
+ /* Check that message is valid. */
+ if (msg->alert_time == NULL || msg->reason == NULL) {
+ sudo_warnx(U_("%s: %s"), source, U_("invalid AlertMessage"));
+ closure->errstr = _("invalid AlertMessage");
+ debug_return_bool(false);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: received AlertMessage from %s",
+ source, __func__);
+
+ debug_return_bool(closure->cms->alert(msg, buf, len, closure));
+}
+
+/* Enable a commit event if not relaying and it is not already pending. */
+static bool
+enable_commit(struct connection_closure *closure)
+{
+ debug_decl(enable_commit, SUDO_DEBUG_UTIL);
+
+ if (closure->relay_closure == NULL) {
+ if (!ISSET(closure->commit_ev->flags, SUDO_EVQ_INSERTED)) {
+ struct timespec tv = { ACK_FREQUENCY, 0 };
+ if (sudo_ev_add(closure->evbase, closure->commit_ev, &tv, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ debug_return_bool(false);
+ }
+ }
+ }
+ debug_return_bool(true);
+}
+
+static bool
+handle_iobuf(int iofd, IoBuffer *iobuf, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ debug_decl(handle_iobuf, SUDO_DEBUG_UTIL);
+
+ if (closure->state != RUNNING) {
+ sudo_warnx(U_("unexpected state %d for %s"), closure->state, source);
+ closure->errstr = _("state machine error");
+ debug_return_bool(false);
+ }
+ if (!closure->log_io) {
+ sudo_warnx(U_("%s: unexpected IoBuffer"), source);
+ closure->errstr = _("protocol error");
+ debug_return_bool(false);
+ }
+
+ /* Check that message is valid. */
+ if (iobuf->delay == NULL) {
+ sudo_warnx(U_("%s: %s"), source, U_("invalid IoBuffer"));
+ closure->errstr = _("invalid IoBuffer");
+ debug_return_bool(false);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: received IoBuffer from %s",
+ source, __func__);
+
+ if (!closure->cms->iobuf(iofd, iobuf, buf, len, closure))
+ debug_return_bool(false);
+ if (!enable_commit(closure))
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+static bool
+handle_winsize(ChangeWindowSize *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ debug_decl(handle_winsize, SUDO_DEBUG_UTIL);
+
+ if (closure->state != RUNNING) {
+ sudo_warnx(U_("unexpected state %d for %s"), closure->state, source);
+ closure->errstr = _("state machine error");
+ debug_return_bool(false);
+ }
+ if (!closure->log_io) {
+ sudo_warnx(U_("%s: unexpected IoBuffer"), source);
+ closure->errstr = _("protocol error");
+ debug_return_bool(false);
+ }
+
+ /* Check that message is valid. */
+ if (msg->delay == NULL) {
+ sudo_warnx(U_("%s: %s"), source, U_("invalid ChangeWindowSize"));
+ closure->errstr = _("invalid ChangeWindowSize");
+ debug_return_bool(false);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: received ChangeWindowSize from %s",
+ source, __func__);
+
+ if (!closure->cms->winsize(msg, buf, len, closure))
+ debug_return_bool(false);
+ if (!enable_commit(closure))
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+static bool
+handle_suspend(CommandSuspend *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ debug_decl(handle_syspend, SUDO_DEBUG_UTIL);
+
+ if (closure->state != RUNNING) {
+ sudo_warnx(U_("unexpected state %d for %s"), closure->state, source);
+ closure->errstr = _("state machine error");
+ debug_return_bool(false);
+ }
+ if (!closure->log_io) {
+ sudo_warnx(U_("%s: unexpected IoBuffer"), source);
+ closure->errstr = _("protocol error");
+ debug_return_bool(false);
+ }
+
+ /* Check that message is valid. */
+ if (msg->delay == NULL || msg->signal == NULL) {
+ sudo_warnx(U_("%s: %s"), source, U_("invalid CommandSuspend"));
+ closure->errstr = _("invalid CommandSuspend");
+ debug_return_bool(false);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: received CommandSuspend from %s",
+ source, __func__);
+
+ if (!closure->cms->suspend(msg, buf, len, closure))
+ debug_return_bool(false);
+ if (!enable_commit(closure))
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+static bool
+handle_client_hello(ClientHello *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ debug_decl(handle_client_hello, SUDO_DEBUG_UTIL);
+
+ if (closure->state != INITIAL) {
+ sudo_warnx(U_("unexpected state %d for %s"), closure->state, source);
+ closure->errstr = _("state machine error");
+ debug_return_bool(false);
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: received ClientHello",
+ __func__);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: client ID %s",
+ __func__, msg->client_id ? msg->client_id : "unknown");
+
+ debug_return_bool(true);
+}
+
+static bool
+handle_client_message(uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ ClientMessage *msg;
+ bool ret = false;
+ debug_decl(handle_client_message, SUDO_DEBUG_UTIL);
+
+ /* TODO: can we extract type_case without unpacking for relay case? */
+ msg = client_message__unpack(NULL, len, buf);
+ if (msg == NULL) {
+ sudo_warnx(U_("unable to unpack %s size %zu"), "ClientMessage", len);
+ debug_return_bool(false);
+ }
+
+ switch (msg->type_case) {
+ case CLIENT_MESSAGE__TYPE_ACCEPT_MSG:
+ ret = handle_accept(msg->u.accept_msg, buf, len, closure);
+ break;
+ case CLIENT_MESSAGE__TYPE_REJECT_MSG:
+ ret = handle_reject(msg->u.reject_msg, buf, len, closure);
+ break;
+ case CLIENT_MESSAGE__TYPE_EXIT_MSG:
+ ret = handle_exit(msg->u.exit_msg, buf, len, closure);
+ break;
+ case CLIENT_MESSAGE__TYPE_RESTART_MSG:
+ ret = handle_restart(msg->u.restart_msg, buf, len, closure);
+ break;
+ case CLIENT_MESSAGE__TYPE_ALERT_MSG:
+ ret = handle_alert(msg->u.alert_msg, buf, len, closure);
+ break;
+ case CLIENT_MESSAGE__TYPE_TTYIN_BUF:
+ ret = handle_iobuf(IOFD_TTYIN, msg->u.ttyin_buf, buf, len, closure);
+ break;
+ case CLIENT_MESSAGE__TYPE_TTYOUT_BUF:
+ ret = handle_iobuf(IOFD_TTYOUT, msg->u.ttyout_buf, buf, len, closure);
+ break;
+ case CLIENT_MESSAGE__TYPE_STDIN_BUF:
+ ret = handle_iobuf(IOFD_STDIN, msg->u.stdin_buf, buf, len, closure);
+ break;
+ case CLIENT_MESSAGE__TYPE_STDOUT_BUF:
+ ret = handle_iobuf(IOFD_STDOUT, msg->u.stdout_buf, buf, len, closure);
+ break;
+ case CLIENT_MESSAGE__TYPE_STDERR_BUF:
+ ret = handle_iobuf(IOFD_STDERR, msg->u.stderr_buf, buf, len, closure);
+ break;
+ case CLIENT_MESSAGE__TYPE_WINSIZE_EVENT:
+ ret = handle_winsize(msg->u.winsize_event, buf, len, closure);
+ break;
+ case CLIENT_MESSAGE__TYPE_SUSPEND_EVENT:
+ ret = handle_suspend(msg->u.suspend_event, buf, len, closure);
+ break;
+ case CLIENT_MESSAGE__TYPE_HELLO_MSG:
+ ret = handle_client_hello(msg->u.hello_msg, buf, len, closure);
+ break;
+ default:
+ sudo_warnx(U_("unexpected type_case value %d in %s from %s"),
+ msg->type_case, "ClientMessage", source);
+ closure->errstr = _("unrecognized ClientMessage type");
+ break;
+ }
+ client_message__free_unpacked(msg, NULL);
+
+ debug_return_bool(ret);
+}
+
+static void
+shutdown_cb(int unused, int what, void *v)
+{
+ struct sudo_event_base *base = v;
+ debug_decl(shutdown_cb, SUDO_DEBUG_UTIL);
+
+ sudo_ev_loopbreak(base);
+
+ debug_return;
+}
+
+/*
+ * Shut down active client connections if any, or exit immediately.
+ */
+static void
+server_shutdown(struct sudo_event_base *base)
+{
+ struct connection_closure *closure, *next;
+ struct sudo_event *ev;
+ struct timespec tv = { 0, 0 };
+ debug_decl(server_shutdown, SUDO_DEBUG_UTIL);
+
+ if (TAILQ_EMPTY(&connections)) {
+ sudo_ev_loopbreak(base);
+ debug_return;
+ }
+
+ TAILQ_FOREACH_SAFE(closure, &connections, entries, next) {
+ closure->state = SHUTDOWN;
+ sudo_ev_del(base, closure->read_ev);
+ if (closure->relay_closure != NULL) {
+ /* Connection being relayed, check for pending I/O. */
+ relay_shutdown(closure);
+ } else if (closure->log_io) {
+ /* Schedule final commit point for the connection. */
+ if (sudo_ev_add(base, closure->commit_ev, &tv, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ }
+ } else {
+ /* No commit point, close connection immediately. */
+ connection_close(closure);
+ }
+ }
+
+ if (!TAILQ_EMPTY(&connections)) {
+ /* We need a timed event to exit even if clients time out. */
+ ev = sudo_ev_alloc(-1, SUDO_EV_TIMEOUT, shutdown_cb, base);
+ if (ev != NULL) {
+ tv.tv_sec = SHUTDOWN_TIMEO;
+ if (sudo_ev_add(base, ev, &tv, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ }
+ }
+ }
+
+ debug_return;
+}
+
+/*
+ * Send a server message to the client.
+ */
+static void
+server_msg_cb(int fd, int what, void *v)
+{
+ struct connection_closure *closure = v;
+ struct connection_buffer *buf;
+ size_t nwritten;
+ debug_decl(server_msg_cb, SUDO_DEBUG_UTIL);
+
+ /* For TLS we may need to write as part of SSL_read_ex(). */
+ if (closure->read_instead_of_write) {
+ closure->read_instead_of_write = false;
+ /* Delete write event if it was only due to SSL_read_ex(). */
+ if (closure->temporary_write_event) {
+ closure->temporary_write_event = false;
+ sudo_ev_del(closure->evbase, closure->write_ev);
+ }
+ client_msg_cb(fd, what, v);
+ debug_return;
+ }
+
+ if (what == SUDO_EV_TIMEOUT) {
+ sudo_warnx(U_("timed out writing to client %s"), closure->ipaddr);
+ goto finished;
+ }
+
+ if ((buf = TAILQ_FIRST(&closure->write_bufs)) == NULL) {
+ sudo_warnx(U_("missing write buffer for client %s"), closure->ipaddr);
+ goto finished;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: sending %zu bytes to client (%s)",
+ __func__, buf->len - buf->off, closure->ipaddr);
+
+#if defined(HAVE_OPENSSL)
+ if (closure->ssl != NULL) {
+ const int result = SSL_write_ex(closure->ssl, buf->data + buf->off,
+ buf->len - buf->off, &nwritten);
+ if (result <= 0) {
+ const char *errstr;
+ switch (SSL_get_error(closure->ssl, result)) {
+ case SSL_ERROR_WANT_READ:
+ /* ssl wants to read, read event always active */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_write_ex returns SSL_ERROR_WANT_READ");
+ /* Redirect persistent read event to finish SSL_write_ex() */
+ closure->write_instead_of_read = true;
+ debug_return;
+ case SSL_ERROR_WANT_WRITE:
+ /* ssl wants to write more, write event remains active */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_write_ex returns SSL_ERROR_WANT_WRITE");
+ debug_return;
+ case SSL_ERROR_SYSCALL:
+ sudo_warn("%s: SSL_write_ex", closure->ipaddr);
+ goto finished;
+ default:
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx("%s: SSL_write_ex: %s", closure->ipaddr,
+ errstr ? errstr : strerror(errno));
+ goto finished;
+ }
+ }
+ } else
+#endif
+ {
+ nwritten = (size_t)write(fd, buf->data + buf->off, buf->len - buf->off);
+ }
+
+ if (nwritten == (size_t)-1) {
+ if (errno == EAGAIN || errno == EINTR)
+ debug_return;
+ sudo_warn("%s: write", closure->ipaddr);
+ goto finished;
+ }
+ buf->off += nwritten;
+
+ if (buf->off == buf->len) {
+ /* sent entire message, move buf to free list */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: finished sending %zu bytes to client", __func__, buf->len);
+ buf->off = 0;
+ buf->len = 0;
+ TAILQ_REMOVE(&closure->write_bufs, buf, entries);
+ TAILQ_INSERT_TAIL(&closure->free_bufs, buf, entries);
+ if (TAILQ_EMPTY(&closure->write_bufs)) {
+ /* Write queue empty, check state. */
+ sudo_ev_del(closure->evbase, closure->write_ev);
+ if (closure->error || closure->state == FINISHED ||
+ closure->state == SHUTDOWN)
+ goto finished;
+ }
+ }
+ debug_return;
+
+finished:
+ connection_close(closure);
+ debug_return;
+}
+
+/*
+ * Receive client message(s).
+ */
+static void
+client_msg_cb(int fd, int what, void *v)
+{
+ struct connection_closure *closure = v;
+ struct connection_buffer *buf = &closure->read_buf;
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ uint32_t msg_len;
+ size_t nread;
+ debug_decl(client_msg_cb, SUDO_DEBUG_UTIL);
+
+ /* For TLS we may need to read as part of SSL_write_ex(). */
+ if (closure->write_instead_of_read) {
+ closure->write_instead_of_read = false;
+ server_msg_cb(fd, what, v);
+ debug_return;
+ }
+
+ if (what == SUDO_EV_TIMEOUT) {
+ sudo_warnx(U_("timed out reading from client %s"), closure->ipaddr);
+ goto close_connection;
+ }
+
+#if defined(HAVE_OPENSSL)
+ if (closure->ssl != NULL) {
+ const int result = SSL_read_ex(closure->ssl, buf->data + buf->len,
+ buf->size, &nread);
+ if (result <= 0) {
+ const char *errstr;
+ switch (SSL_get_error(closure->ssl, result)) {
+ case SSL_ERROR_ZERO_RETURN:
+ /* ssl connection shutdown cleanly */
+ nread = 0;
+ break;
+ case SSL_ERROR_WANT_READ:
+ /* ssl wants to read more, read event is always active */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_read_ex returns SSL_ERROR_WANT_READ");
+ /* Read event is always active. */
+ debug_return;
+ case SSL_ERROR_WANT_WRITE:
+ /* ssl wants to write, schedule a write if not pending */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_read_ex returns SSL_ERROR_WANT_WRITE");
+ if (!sudo_ev_pending(closure->write_ev, SUDO_EV_WRITE, NULL)) {
+ /* Enable a temporary write event. */
+ if (sudo_ev_add(closure->evbase, closure->write_ev,
+ logsrvd_conf_server_timeout(), false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ closure->errstr = _("unable to allocate memory");
+ goto send_error;
+ }
+ closure->temporary_write_event = true;
+ }
+ /* Redirect write event to finish SSL_read_ex() */
+ closure->read_instead_of_write = true;
+ debug_return;
+ case SSL_ERROR_SYSCALL:
+ if (nread == 0) {
+ /* EOF, handled below */
+ sudo_warnx(U_("EOF from %s without proper TLS shutdown"),
+ closure->ipaddr);
+ break;
+ }
+ sudo_warn("%s: SSL_read_ex", closure->ipaddr);
+ goto close_connection;
+ default:
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx("%s: SSL_read_ex: %s", closure->ipaddr,
+ errstr ? errstr : strerror(errno));
+ goto close_connection;
+ }
+ }
+ } else
+#endif
+ {
+ nread = (size_t)read(fd, buf->data + buf->len, buf->size - buf->len);
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: received %zd bytes from client %s",
+ __func__, nread, closure->ipaddr);
+ switch (nread) {
+ case (size_t)-1:
+ if (errno == EAGAIN || errno == EINTR)
+ debug_return;
+ sudo_warn("%s: read", closure->ipaddr);
+ goto close_connection;
+ case 0:
+ if (closure->state != FINISHED) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "unexpected EOF");
+ }
+ goto close_connection;
+ default:
+ break;
+ }
+ buf->len += nread;
+
+ while (buf->len - buf->off >= sizeof(msg_len)) {
+ /* Read wire message size (uint32_t in network byte order). */
+ memcpy(&msg_len, buf->data + buf->off, sizeof(msg_len));
+ msg_len = ntohl(msg_len);
+
+ if (msg_len > MESSAGE_SIZE_MAX) {
+ sudo_warnx(U_("client message too large: %zu"), (size_t)msg_len);
+ closure->errstr = _("client message too large");
+ goto send_error;
+ }
+
+ if (msg_len + sizeof(msg_len) > buf->len - buf->off) {
+ /* Incomplete message, we'll read the rest next time. */
+ if (!expand_buf(buf, msg_len + sizeof(msg_len))) {
+ closure->errstr = _("unable to allocate memory");
+ goto send_error;
+ }
+ debug_return;
+ }
+
+ /* Parse ClientMessage (could be zero bytes). */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: parsing ClientMessage, size %u", __func__, msg_len);
+ buf->off += sizeof(msg_len);
+ if (!handle_client_message(buf->data + buf->off, msg_len, closure)) {
+ sudo_warnx(U_("%s: %s"), source, U_("invalid ClientMessage"));
+ closure->errstr = _("invalid ClientMessage");
+ goto send_error;
+ }
+ buf->off += msg_len;
+ }
+ buf->len -= buf->off;
+ buf->off = 0;
+
+ if (closure->state == FINISHED)
+ goto close_connection;
+
+ debug_return;
+
+send_error:
+ /*
+ * Try to send client an error message before closing the connection.
+ */
+ if (!schedule_error_message(closure->errstr, closure))
+ goto close_connection;
+ debug_return;
+
+close_connection:
+ connection_close(closure);
+ debug_return;
+}
+
+/*
+ * Format and schedule a commit_point message.
+ */
+bool
+schedule_commit_point(TimeSpec *commit_point,
+ struct connection_closure *closure)
+{
+ debug_decl(schedule_commit_point, SUDO_DEBUG_UTIL);
+
+ if (closure->write_ev != NULL) {
+ /* Send an acknowledgement of what we've committed to disk. */
+ ServerMessage msg = SERVER_MESSAGE__INIT;
+ msg.u.commit_point = commit_point;
+ msg.type_case = SERVER_MESSAGE__TYPE_COMMIT_POINT;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sending commit point [%lld, %ld]", __func__,
+ (long long)commit_point->tv_sec, (long)commit_point->tv_nsec);
+
+ if (!fmt_server_message(closure, &msg))
+ goto bad;
+ if (sudo_ev_add(closure->evbase, closure->write_ev,
+ logsrvd_conf_server_timeout(), false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto bad;
+ }
+ }
+
+ if (closure->state == EXITED)
+ closure->state = FINISHED;
+ debug_return_bool(true);
+bad:
+ debug_return_bool(false);
+}
+
+/*
+ * Time-based event that fires periodically to report to the client
+ * what has been committed to disk.
+ */
+static void
+server_commit_cb(int unused, int what, void *v)
+{
+ struct connection_closure *closure = v;
+ TimeSpec commit_point = TIME_SPEC__INIT;
+ debug_decl(server_commit_cb, SUDO_DEBUG_UTIL);
+
+ /* Flush I/O logs before sending commit point if needed. */
+ if (!iolog_get_flush())
+ iolog_flush_all(closure);
+
+ commit_point.tv_sec = closure->elapsed_time.tv_sec;
+ commit_point.tv_nsec = (int32_t)closure->elapsed_time.tv_nsec;
+ if (!schedule_commit_point(&commit_point, closure))
+ connection_close(closure);
+
+ debug_return;
+}
+
+/*
+ * Begin the sudo logserver protocol.
+ * When we enter the event loop the ServerHello message will be written
+ * and any pending ClientMessage will be read.
+ */
+bool
+start_protocol(struct connection_closure *closure)
+{
+ const struct timespec *timeout = logsrvd_conf_server_timeout();
+ debug_decl(start_protocol, SUDO_DEBUG_UTIL);
+
+ if (closure->relay_closure != NULL && closure->relay_closure->relays != NULL) {
+ /* No longer need the stashed relays list. */
+ address_list_delref(closure->relay_closure->relays);
+ closure->relay_closure->relays = NULL;
+ closure->relay_closure->relay_addr = NULL;
+ }
+
+ /* When replaying a journal there is no write event. */
+ if (closure->write_ev != NULL) {
+ if (!fmt_hello_message(closure))
+ debug_return_bool(false);
+
+ if (sudo_ev_add(closure->evbase, closure->write_ev, timeout, false) == -1)
+ debug_return_bool(false);
+ }
+
+ /* No read timeout, client messages may happen at arbitrary times. */
+ if (sudo_ev_add(closure->evbase, closure->read_ev, NULL, false) == -1)
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+#if defined(HAVE_OPENSSL)
+static int
+verify_peer_identity(int preverify_ok, X509_STORE_CTX *ctx)
+{
+ HostnameValidationResult result;
+ struct connection_closure *closure;
+ SSL *ssl;
+ X509 *current_cert;
+ X509 *peer_cert;
+ debug_decl(verify_peer_identity, SUDO_DEBUG_UTIL);
+
+ /* if pre-verification of the cert failed, just propagate that result back */
+ if (preverify_ok != 1) {
+ debug_return_int(0);
+ }
+
+ /* since this callback is called for each cert in the chain,
+ * check that current cert is the peer's certificate
+ */
+ current_cert = X509_STORE_CTX_get_current_cert(ctx);
+ peer_cert = X509_STORE_CTX_get0_cert(ctx);
+
+ if (current_cert != peer_cert) {
+ debug_return_int(1);
+ }
+
+ /* read out the attached object (closure) from the ssl connection object */
+ ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
+ closure = (struct connection_closure *)SSL_get_ex_data(ssl, 1);
+
+ result = validate_hostname(peer_cert, closure->ipaddr, closure->ipaddr, 1);
+
+ switch(result)
+ {
+ case MatchFound:
+ debug_return_int(1);
+ default:
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "hostname validation failed");
+ debug_return_int(0);
+ }
+}
+
+/*
+ * Set the TLS verify callback to verify_peer_identity().
+ */
+static void
+set_tls_verify_peer(void)
+{
+ SSL_CTX *server_ctx = logsrvd_server_tls_ctx();
+ SSL_CTX *relay_ctx = logsrvd_relay_tls_ctx();
+ debug_decl(set_tls_verify_peer, SUDO_DEBUG_UTIL);
+
+ if (server_ctx != NULL && logsrvd_conf_server_tls_check_peer()) {
+ /* Verify server cert during the handshake. */
+ SSL_CTX_set_verify(server_ctx,
+ SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+ verify_peer_identity);
+ }
+ if (relay_ctx != NULL && logsrvd_conf_relay_tls_check_peer()) {
+ /* Verify relay cert during the handshake. */
+ SSL_CTX_set_verify(relay_ctx,
+ SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+ verify_peer_identity);
+ }
+
+ debug_return;
+}
+
+static void
+tls_handshake_cb(int fd, int what, void *v)
+{
+ struct connection_closure *closure = v;
+ const char *errstr;
+ int err, handshake_status;
+ debug_decl(tls_handshake_cb, SUDO_DEBUG_UTIL);
+
+ if (what == SUDO_EV_TIMEOUT) {
+ sudo_warnx("TLS handshake with %s timed out", closure->ipaddr);
+ goto bad;
+ }
+
+ handshake_status = SSL_accept(closure->ssl);
+ err = SSL_get_error(closure->ssl, handshake_status);
+ switch (err) {
+ case SSL_ERROR_NONE:
+ /* ssl handshake was successful */
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "TLS handshake successful");
+ break;
+ case SSL_ERROR_WANT_READ:
+ /* ssl handshake is ongoing, re-schedule the SSL_accept() call */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_accept returns SSL_ERROR_WANT_READ");
+ if (what != SUDO_EV_READ) {
+ if (sudo_ev_set(closure->ssl_accept_ev, closure->sock,
+ SUDO_EV_READ, tls_handshake_cb, closure) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to set ssl_accept_ev to SUDO_EV_READ");
+ goto bad;
+ }
+ }
+ if (sudo_ev_add(closure->evbase, closure->ssl_accept_ev,
+ logsrvd_conf_server_timeout(), false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto bad;
+ }
+ debug_return;
+ case SSL_ERROR_WANT_WRITE:
+ /* ssl handshake is ongoing, re-schedule the SSL_accept() call */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_accept returns SSL_ERROR_WANT_WRITE");
+ if (what != SUDO_EV_WRITE) {
+ if (sudo_ev_set(closure->ssl_accept_ev, closure->sock,
+ SUDO_EV_WRITE, tls_handshake_cb, closure) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to set ssl_accept_ev to SUDO_EV_WRITE");
+ goto bad;
+ }
+ }
+ if (sudo_ev_add(closure->evbase, closure->ssl_accept_ev,
+ logsrvd_conf_server_timeout(), false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto bad;
+ }
+ debug_return;
+ case SSL_ERROR_SYSCALL:
+ sudo_warn("%s: SSL_accept", closure->ipaddr);
+ goto bad;
+ default:
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx("%s: SSL_accept: %s", closure->ipaddr,
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "TLS version: %s, negotiated cipher suite: %s",
+ SSL_get_version(closure->ssl),
+ SSL_get_cipher(closure->ssl));
+
+ /* Start the actual protocol now that the TLS handshake is complete. */
+ if (!TAILQ_EMPTY(logsrvd_conf_relay_address()) && !closure->store_first) {
+ if (!connect_relay(closure))
+ goto bad;
+ } else {
+ if (!start_protocol(closure))
+ goto bad;
+ }
+
+ debug_return;
+bad:
+ connection_close(closure);
+ debug_return;
+}
+#endif /* HAVE_OPENSSL */
+
+/*
+ * New connection.
+ * Allocate a connection closure and optionally perform TLS handshake.
+ */
+static bool
+new_connection(int sock, bool tls, const union sockaddr_union *sa_un,
+ struct sudo_event_base *evbase)
+{
+ struct connection_closure *closure;
+ debug_decl(new_connection, SUDO_DEBUG_UTIL);
+
+ if ((closure = connection_closure_alloc(sock, tls, false, evbase)) == NULL)
+ goto bad;
+
+ /* store the peer's IP address in the closure object */
+ if (sa_un->sa.sa_family == AF_INET) {
+ inet_ntop(AF_INET, &sa_un->sin.sin_addr, closure->ipaddr,
+ sizeof(closure->ipaddr));
+#ifdef HAVE_STRUCT_IN6_ADDR
+ } else if (sa_un->sa.sa_family == AF_INET6) {
+ inet_ntop(AF_INET6, &sa_un->sin6.sin6_addr, closure->ipaddr,
+ sizeof(closure->ipaddr));
+#endif /* HAVE_STRUCT_IN6_ADDR */
+ } else {
+ errno = EAFNOSUPPORT;
+ sudo_warn("%s", U_("unable to get remote IP addr"));
+ goto bad;
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "connection from %s", closure->ipaddr);
+
+#if defined(HAVE_OPENSSL)
+ /* If TLS is enabled, perform the TLS handshake first. */
+ if (tls) {
+ const char *errstr;
+
+ /* Create the SSL object for the closure and attach it to the socket */
+ if ((closure->ssl = SSL_new(logsrvd_server_tls_ctx())) == NULL) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("%s: %s"), "SSL_new",
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+
+ if (SSL_set_fd(closure->ssl, closure->sock) != 1) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("%s: %s"), "SSL_set_fd",
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+
+ /* attach the closure object to the ssl connection object to make it
+ available during hostname matching
+ */
+ if (SSL_set_ex_data(closure->ssl, 1, closure) <= 0) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("Unable to attach user data to the ssl object: %s"),
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+
+ /* Enable SSL_accept to begin handshake with client. */
+ if (sudo_ev_add(evbase, closure->ssl_accept_ev,
+ logsrvd_conf_server_timeout(), false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto bad;
+ }
+ }
+#endif
+ /* If no TLS handshake, start the protocol immediately. */
+ if (!tls) {
+ if (!TAILQ_EMPTY(logsrvd_conf_relay_address()) && !closure->store_first) {
+ if (!connect_relay(closure))
+ goto bad;
+ } else {
+ if (!start_protocol(closure))
+ goto bad;
+ }
+ }
+
+ debug_return_bool(true);
+bad:
+ connection_close(closure);
+ debug_return_bool(false);
+}
+
+static int
+create_listener(struct server_address *addr)
+{
+ int flags, on, sock;
+ const char *family = "inet4";
+ debug_decl(create_listener, SUDO_DEBUG_UTIL);
+
+ if ((sock = socket(addr->sa_un.sa.sa_family, SOCK_STREAM, 0)) == -1) {
+ sudo_warn("socket");
+ goto bad;
+ }
+ on = 1;
+#ifdef HAVE_STRUCT_IN6_ADDR
+ if (addr->sa_un.sa.sa_family == AF_INET6) {
+ family = "inet6";
+# ifdef IPV6_V6ONLY
+ /* Disable IPv4-mapped IPv6 addresses. */
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1)
+ sudo_warn("IPV6_V6ONLY");
+# endif
+ }
+#endif
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
+ sudo_warn("SO_REUSEADDR");
+ if (bind(sock, &addr->sa_un.sa, addr->sa_size) == -1) {
+ /* TODO: only warn once for IPv4 and IPv6 or disambiguate */
+ sudo_warn("%s (%s)", addr->sa_str, family);
+ goto bad;
+ }
+ if (listen(sock, SOMAXCONN) == -1) {
+ sudo_warn("listen");
+ goto bad;
+ }
+ flags = fcntl(sock, F_GETFL, 0);
+ if (flags == -1 || fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) {
+ sudo_warn("fcntl(O_NONBLOCK)");
+ goto bad;
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "listening on %s (%s)", addr->sa_str,
+ family);
+
+ debug_return_int(sock);
+bad:
+ if (sock != -1)
+ close(sock);
+ debug_return_int(-1);
+}
+
+static void
+listener_cb(int fd, int what, void *v)
+{
+ struct listener *l = v;
+ struct sudo_event_base *evbase = sudo_ev_get_base(l->ev);
+ union sockaddr_union sa_un;
+ socklen_t salen = sizeof(sa_un);
+ int sock;
+ debug_decl(listener_cb, SUDO_DEBUG_UTIL);
+
+ memset(&sa_un, 0, sizeof(sa_un));
+ sock = accept(fd, &sa_un.sa, &salen);
+ if (sock != -1) {
+ if (logsrvd_conf_server_tcp_keepalive()) {
+ int keepalive = 1;
+ if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
+ sizeof(keepalive)) == -1) {
+ sudo_warn("SO_KEEPALIVE");
+ }
+ }
+ if (!new_connection(sock, l->tls, &sa_un, evbase)) {
+ /* TODO: pause accepting on ENOMEM */
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to start new connection");
+ }
+ } else {
+ if (errno == EAGAIN || errno == EINTR)
+ debug_return;
+ /* TODO: pause accepting on ENFILE and EMFILE */
+ sudo_warn("accept");
+ }
+
+ debug_return;
+}
+
+static bool
+register_listener(struct server_address *addr, struct sudo_event_base *evbase)
+{
+ struct listener *l;
+ int sock;
+ debug_decl(register_listener, SUDO_DEBUG_UTIL);
+
+ sock = create_listener(addr);
+ if (sock == -1)
+ debug_return_bool(false);
+
+ /* TODO: make non-fatal */
+ if ((l = malloc(sizeof(*l))) == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ l->sock = sock;
+ l->tls = addr->tls;
+ l->ev = sudo_ev_alloc(sock, SUDO_EV_READ|SUDO_EV_PERSIST, listener_cb, l);
+ if (l->ev == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(evbase, l->ev, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+ TAILQ_INSERT_TAIL(&listeners, l, entries);
+
+ debug_return_bool(true);
+}
+
+/*
+ * Register listeners and set the TLS verify callback.
+ */
+static bool
+server_setup(struct sudo_event_base *base)
+{
+ struct server_address *addr;
+ struct listener *l;
+ int nlisteners = 0;
+ bool ret;
+ debug_decl(server_setup, SUDO_DEBUG_UTIL);
+
+ /* Free old listeners (if any) and register new ones. */
+ while ((l = TAILQ_FIRST(&listeners)) != NULL) {
+ TAILQ_REMOVE(&listeners, l, entries);
+ sudo_ev_free(l->ev);
+ close(l->sock);
+ free(l);
+ }
+ TAILQ_FOREACH(addr, logsrvd_conf_server_listen_address(), entries) {
+ nlisteners += register_listener(addr, base);
+ }
+ ret = nlisteners > 0;
+
+#if defined(HAVE_OPENSSL)
+ if (ret)
+ set_tls_verify_peer();
+#endif
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Reload config and re-initialize listeners.
+ */
+static void
+server_reload(struct sudo_event_base *evbase)
+{
+ debug_decl(server_reload, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "reloading server config");
+ if (logsrvd_conf_read(conf_file)) {
+ /* Re-initialize listeners. */
+ if (!server_setup(evbase))
+ sudo_fatalx("%s", U_("unable to setup listen socket"));
+
+ /* Re-read sudo.conf and re-initialize debugging. */
+ sudo_debug_deregister(logsrvd_debug_instance);
+ logsrvd_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
+ if (sudo_conf_read(NULL, SUDO_CONF_DEBUG) != -1) {
+ logsrvd_debug_instance = sudo_debug_register(getprogname(),
+ NULL, NULL, sudo_conf_debug_files(getprogname()), -1);
+ }
+ }
+
+ debug_return;
+}
+
+/*
+ * Dump server information to the debug file.
+ * Includes information about listeners and client connections.
+ */
+static void
+server_dump_stats(void)
+{
+ struct server_address *addr;
+ struct connection_closure *closure;
+ int n;
+ debug_decl(server_dump_stats, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s", server_id);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "configuration file: %s",
+ conf_file ? conf_file : _PATH_SUDO_LOGSRVD_CONF);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "listen addresses:");
+ n = 0;
+ TAILQ_FOREACH(addr, logsrvd_conf_server_listen_address(), entries) {
+ union sockaddr_union *sa_un = &addr->sa_un;
+ char ipaddr[INET6_ADDRSTRLEN];
+
+ switch (sa_un->sa.sa_family) {
+ case AF_INET:
+ inet_ntop(AF_INET, &sa_un->sin.sin_addr, ipaddr, sizeof(ipaddr));
+ break;
+#ifdef HAVE_STRUCT_IN6_ADDR
+ case AF_INET6:
+ inet_ntop(AF_INET6, &sa_un->sin6.sin6_addr, ipaddr, sizeof(ipaddr));
+ break;
+#endif /* HAVE_STRUCT_IN6_ADDR */
+ default:
+ (void)strlcpy(ipaddr, "[unknown]", sizeof(ipaddr));
+ break;
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, " %d: %s [%s]", ++n,
+ addr->sa_str, ipaddr);
+ }
+
+ if (!TAILQ_EMPTY(&connections)) {
+ n = 0;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "client connections:");
+ TAILQ_FOREACH(closure, &connections, entries) {
+ struct relay_closure *relay_closure = closure->relay_closure;
+
+ n++;
+ if (closure->sock == -1) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, " %2d: journal %s", n,
+ closure->journal_path ? closure->journal_path : "none");
+ sudo_debug_printf(SUDO_DEBUG_INFO, " %2d: fd %d", n,
+ closure->journal ? fileno(closure->journal) : -1);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO, " %2d: addr %s%s", n,
+ closure->ipaddr, closure->tls ? " (TLS)" : "");
+ sudo_debug_printf(SUDO_DEBUG_INFO, " %2d: sock %d", n,
+ closure->sock);
+ }
+ if (relay_closure != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, " relay: %s (%s)",
+ relay_closure->relay_name.name,
+ relay_closure->relay_name.ipaddr);
+ sudo_debug_printf(SUDO_DEBUG_INFO, " relay sock: %d",
+ relay_closure->sock);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, " state: %d", closure->state);
+ if (closure->errstr != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, " error: %s",
+ closure->errstr);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, " log I/O: %s",
+ closure->log_io ? "true" : "false");
+ sudo_debug_printf(SUDO_DEBUG_INFO, " store first: %s",
+ closure->store_first ? "true" : "false");
+ if (sudo_timespecisset(&closure->elapsed_time)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ " elapsed time: [%lld, %ld]",
+ (long long)closure->elapsed_time.tv_sec,
+ (long)closure->elapsed_time.tv_nsec);
+ }
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%d client connection(s)\n", n);
+ }
+ logsrvd_queue_dump();
+
+ debug_return;
+}
+
+static void
+signal_cb(int signo, int what, void *v)
+{
+ struct sudo_event_base *base = v;
+ debug_decl(signal_cb, SUDO_DEBUG_UTIL);
+
+ switch (signo) {
+ case SIGHUP:
+ server_reload(base);
+ break;
+ case SIGINT:
+ case SIGTERM:
+ /* Shut down active connections. */
+ server_shutdown(base);
+ break;
+ case SIGUSR1:
+ server_dump_stats();
+ break;
+ default:
+ sudo_warnx(U_("unexpected signal %d"), signo);
+ break;
+ }
+
+ debug_return;
+}
+
+static void
+register_signal(int signo, struct sudo_event_base *base)
+{
+ struct sudo_event *ev;
+ debug_decl(register_signal, SUDO_DEBUG_UTIL);
+
+ ev = sudo_ev_alloc(signo, SUDO_EV_SIGNAL, signal_cb, base);
+ if (ev == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(base, ev, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ debug_return;
+}
+
+static void
+logsrvd_cleanup(void)
+{
+ /* TODO: cleanup like on signal */
+ return;
+}
+
+/*
+ * Write the process ID into a file, typically /var/run/sudo/sudo_logsrvd.pid.
+ * If the parent directory doesn't exist, it will be created.
+ */
+static void
+write_pidfile(void)
+{
+ FILE *fp;
+ int dfd, fd;
+ mode_t oldmask;
+ const char *pid_file = logsrvd_conf_pid_file();
+ debug_decl(write_pidfile, SUDO_DEBUG_UTIL);
+
+ if (pid_file == NULL)
+ debug_return;
+
+ /* Default logsrvd umask is more restrictive (077). */
+ oldmask = umask(S_IWGRP|S_IWOTH);
+
+ dfd = sudo_open_parent_dir(pid_file, ROOT_UID, ROOT_GID,
+ S_IRWXU|S_IXGRP|S_IXOTH, false);
+ if (dfd != -1) {
+ const char *base = sudo_basename(pid_file);
+ fd = openat(dfd, base, O_WRONLY|O_CREAT|O_NOFOLLOW, 0644);
+ if (fd == -1 || (fp = fdopen(fd, "w")) == NULL) {
+ sudo_warn("%s", pid_file);
+ if (fd != -1)
+ close(fd);
+ } else {
+ fprintf(fp, "%u\n", (unsigned int)getpid());
+ fflush(fp);
+ if (ferror(fp))
+ sudo_warn("%s", pid_file);
+ fclose(fp);
+ }
+ close(dfd);
+ }
+ umask(oldmask);
+
+ debug_return;
+}
+
+/*
+ * Increase the number of open files to the maximum value.
+ */
+static void
+unlimit_nofile(void)
+{
+ struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
+ struct rlimit nofilelimit;
+ debug_decl(unlimit_nofile, SUDO_DEBUG_UTIL);
+
+ if (getrlimit(RLIMIT_NOFILE, &nofilelimit) != 0) {
+ sudo_warn("getrlimit(RLIMIT_NOFILE)");
+ debug_return;
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "RLIMIT_NOFILE [%lld, %lld] -> [inf, inf]",
+ (long long)nofilelimit.rlim_cur, (long long)nofilelimit.rlim_max);
+ if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
+ /* Unable to set to infinity, set to max instead. */
+ rl.rlim_cur = rl.rlim_max = nofilelimit.rlim_max;
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "RLIMIT_NOFILE [%lld, %lld] -> [%lld, %lld]",
+ (long long)nofilelimit.rlim_cur, (long long)nofilelimit.rlim_max,
+ (long long)rl.rlim_cur, (long long)rl.rlim_max);
+ if (setrlimit(RLIMIT_NOFILE, &rl) != 0)
+ sudo_warn("setrlimit(RLIMIT_NOFILE)");
+ }
+ debug_return;
+}
+
+/*
+ * Fork, detach from the terminal and write pid file unless nofork set.
+ */
+static void
+daemonize(bool nofork)
+{
+ int fd;
+ debug_decl(daemonize, SUDO_DEBUG_UTIL);
+
+ if (chdir("/") == -1)
+ sudo_warn("chdir(\"/\")");
+
+ if (!nofork) {
+ switch (sudo_debug_fork()) {
+ case -1:
+ sudo_fatal("fork");
+ case 0:
+ /* child */
+ break;
+ default:
+ /* parent, exit */
+ _exit(EXIT_SUCCESS);
+ }
+
+ /* detach from terminal and write pid file. */
+ if (setsid() == -1)
+ sudo_fatal("setsid");
+ write_pidfile();
+
+ if ((fd = open(_PATH_DEVNULL, O_RDWR)) != -1) {
+ (void) dup2(fd, STDIN_FILENO);
+ (void) dup2(fd, STDOUT_FILENO);
+ (void) dup2(fd, STDERR_FILENO);
+ if (fd > STDERR_FILENO)
+ (void) close(fd);
+ }
+ } else {
+ if ((fd = open(_PATH_DEVNULL, O_RDWR)) != -1) {
+ /* Preserve stdout/stderr in nofork mode (if open). */
+ (void) dup2(fd, STDIN_FILENO);
+ if (fcntl(STDOUT_FILENO, F_GETFL) == -1)
+ (void) dup2(fd, STDOUT_FILENO);
+ if (fcntl(STDERR_FILENO, F_GETFL) == -1)
+ (void) dup2(fd, STDERR_FILENO);
+ if (fd > STDERR_FILENO)
+ (void) close(fd);
+ }
+ }
+
+ /* Disable logging to stderr after we become a daemon. */
+ logsrvd_warn_stderr(false);
+
+ debug_return;
+}
+
+static void
+display_usage(FILE *fp)
+{
+ fprintf(fp, "usage: %s [-n] [-f conf_file] [-R percentage]\n",
+ getprogname());
+}
+
+sudo_noreturn static void
+usage(void)
+{
+ display_usage(stderr);
+ exit(EXIT_FAILURE);
+}
+
+sudo_noreturn static void
+help(void)
+{
+ printf("%s - %s\n\n", getprogname(), _("sudo log server"));
+ display_usage(stdout);
+ printf("\n%s\n", _("Options:"));
+ printf(" -f, --file %s\n",
+ _("path to configuration file"));
+ printf(" -h, --help %s\n",
+ _("display help message and exit"));
+ printf(" -n, --no-fork %s\n",
+ _("do not fork, run in the foreground"));
+ printf(" -R, --random-drop %s\n",
+ _("percent chance connections will drop"));
+ printf(" -V, --version %s\n",
+ _("display version information and exit"));
+ putchar('\n');
+ exit(EXIT_SUCCESS);
+}
+
+static const char short_opts[] = "f:hnR:V";
+static struct option long_opts[] = {
+ { "file", required_argument, NULL, 'f' },
+ { "help", no_argument, NULL, 'h' },
+ { "no-fork", no_argument, NULL, 'n' },
+ { "random-drop", required_argument, NULL, 'R' },
+ { "version", no_argument, NULL, 'V' },
+ { NULL, no_argument, NULL, 0 },
+};
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+int
+main(int argc, char *argv[])
+{
+ struct sudo_event_base *evbase;
+ bool nofork = false;
+ int ch;
+ debug_decl_vars(main, SUDO_DEBUG_MAIN);
+
+#if defined(SUDO_DEVEL) && defined(__OpenBSD__)
+ {
+ extern char *malloc_options;
+ malloc_options = "S";
+ }
+#endif
+
+ initprogname(argc > 0 ? argv[0] : "sudo_logsrvd");
+ setlocale(LC_ALL, "");
+ bindtextdomain("sudo", LOCALEDIR); /* XXX - add logsrvd domain */
+ textdomain("sudo");
+
+ /* Create files readable/writable only by owner. */
+ umask(S_IRWXG|S_IRWXO);
+
+ /* Register fatal/fatalx callback. */
+ sudo_fatal_callback_register(logsrvd_cleanup);
+
+ /* Read sudo.conf and initialize the debug subsystem. */
+ if (sudo_conf_read(NULL, SUDO_CONF_DEBUG) == -1)
+ return EXIT_FAILURE;
+ logsrvd_debug_instance = sudo_debug_register(getprogname(), NULL, NULL,
+ sudo_conf_debug_files(getprogname()), -1);
+
+ if (protobuf_c_version_number() < 1003000)
+ sudo_fatalx("%s", U_("Protobuf-C version 1.3 or higher required"));
+
+ while ((ch = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
+ switch (ch) {
+ case 'f':
+ conf_file = optarg;
+ break;
+ case 'h':
+ help();
+ /* NOTREACHED */
+ case 'n':
+ nofork = true;
+ break;
+ case 'R':
+ /* random connection drop probability as a percentage (debug) */
+ if (!set_random_drop(optarg))
+ sudo_fatalx(U_("invalid random drop value: %s"), optarg);
+ break;
+ case 'V':
+ (void)printf(_("%s version %s\n"), getprogname(),
+ PACKAGE_VERSION);
+ return 0;
+ default:
+ usage();
+ }
+ }
+
+ /* Read sudo_logsrvd.conf */
+ if (!logsrvd_conf_read(conf_file))
+ return EXIT_FAILURE;
+
+ /* Crank the open file limit to the maximum value allowed. */
+ unlimit_nofile();
+
+ if ((evbase = sudo_ev_base_alloc()) == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ /* Initialize listeners. */
+ if (!server_setup(evbase))
+ sudo_fatalx("%s", U_("unable to setup listen socket"));
+
+ register_signal(SIGHUP, evbase);
+ register_signal(SIGINT, evbase);
+ register_signal(SIGTERM, evbase);
+ register_signal(SIGUSR1, evbase);
+
+ /* Point of no return. */
+ daemonize(nofork);
+ signal(SIGPIPE, SIG_IGN);
+
+ logsrvd_queue_scan(evbase);
+ sudo_ev_dispatch(evbase);
+ if (!nofork && logsrvd_conf_pid_file() != NULL)
+ unlink(logsrvd_conf_pid_file());
+ logsrvd_conf_cleanup();
+
+ debug_return_int(0);
+}
diff --git a/logsrvd/logsrvd.h b/logsrvd/logsrvd.h
new file mode 100644
index 0000000..ec4f6ba
--- /dev/null
+++ b/logsrvd/logsrvd.h
@@ -0,0 +1,266 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_LOGSRVD_H
+#define SUDO_LOGSRVD_H
+
+#include <log_server.pb-c.h>
+#if PROTOBUF_C_VERSION_NUMBER < 1003000
+# error protobuf-c version 1.30 or higher required
+#endif
+
+#include <config.h>
+
+#if defined(HAVE_OPENSSL)
+# if defined(HAVE_WOLFSSL)
+# include <wolfssl/options.h>
+# endif
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+#endif
+
+#include "logsrv_util.h"
+#include <tls_common.h>
+
+/* Default timeout value for server socket */
+#define DEFAULT_SOCKET_TIMEOUT_SEC 30
+
+/* How often to send an ACK to the client (commit point) in seconds */
+#define ACK_FREQUENCY 10
+
+/* Shutdown timeout (in seconds) in case client connections time out. */
+#define SHUTDOWN_TIMEO 10
+
+/* Template for mkstemp(3) when creating temporary files. */
+#define RELAY_TEMPLATE "relay.XXXXXXXX"
+
+/*
+ * Connection status.
+ * In the RUNNING state we expect I/O log buffers.
+ */
+enum connection_status {
+ INITIAL,
+ CONNECTING,
+ RUNNING,
+ EXITED,
+ SHUTDOWN,
+ FINISHED
+};
+
+/*
+ * Per-connection relay state.
+ */
+struct relay_closure {
+ struct server_address_list *relays;
+ struct server_address *relay_addr;
+ struct sudo_event *read_ev;
+ struct sudo_event *write_ev;
+ struct sudo_event *connect_ev;
+ struct connection_buffer read_buf;
+ struct connection_buffer_list write_bufs;
+ struct peer_info relay_name;
+#if defined(HAVE_OPENSSL)
+ struct tls_client_closure tls_client;
+#endif
+ int sock;
+ bool read_instead_of_write;
+ bool write_instead_of_read;
+ bool temporary_write_event;
+};
+
+/*
+ * Per-connection state.
+ */
+struct connection_closure {
+ TAILQ_ENTRY(connection_closure) entries;
+ struct client_message_switch *cms;
+ struct relay_closure *relay_closure;
+ struct eventlog *evlog;
+ struct timespec elapsed_time;
+ struct connection_buffer read_buf;
+ struct connection_buffer_list write_bufs;
+ struct connection_buffer_list free_bufs;
+ struct sudo_event_base *evbase;
+ struct sudo_event *commit_ev;
+ struct sudo_event *read_ev;
+ struct sudo_event *write_ev;
+#if defined(HAVE_OPENSSL)
+ struct sudo_event *ssl_accept_ev;
+ SSL *ssl;
+#endif
+ const char *errstr;
+ FILE *journal;
+ char *journal_path;
+ struct iolog_file iolog_files[IOFD_MAX];
+ int iolog_dir_fd;
+ int sock;
+ enum connection_status state;
+ bool error;
+ bool tls;
+ bool log_io;
+ bool store_first;
+ bool read_instead_of_write;
+ bool write_instead_of_read;
+ bool temporary_write_event;
+#ifdef HAVE_STRUCT_IN6_ADDR
+ char ipaddr[INET6_ADDRSTRLEN];
+#else
+ char ipaddr[INET_ADDRSTRLEN];
+#endif
+};
+
+/* Client message switch. */
+struct client_message_switch {
+ bool (*accept)(AcceptMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure);
+ bool (*reject)(RejectMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure);
+ bool (*exit)(ExitMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure);
+ bool (*restart)(RestartMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure);
+ bool (*alert)(AlertMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure);
+ bool (*iobuf)(int iofd, IoBuffer *iobuf, uint8_t *buf, size_t len,
+ struct connection_closure *closure);
+ bool (*suspend)(CommandSuspend *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure);
+ bool (*winsize)(ChangeWindowSize *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure);
+};
+
+union sockaddr_union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+#ifdef HAVE_STRUCT_IN6_ADDR
+ struct sockaddr_in6 sin6;
+#endif
+};
+
+/*
+ * List of server addresses.
+ */
+struct server_address {
+ TAILQ_ENTRY(server_address) entries;
+ char *sa_host;
+ char *sa_str;
+ union sockaddr_union sa_un;
+ socklen_t sa_size;
+ bool tls;
+};
+TAILQ_HEAD(server_address_list, server_address);
+
+/*
+ * List of active network listeners.
+ */
+struct listener {
+ TAILQ_ENTRY(listener) entries;
+ struct sudo_event *ev;
+ int sock;
+ bool tls;
+};
+TAILQ_HEAD(listener_list, listener);
+
+/*
+ * Queue of finished journal files to be relayed.
+ */
+struct outgoing_journal {
+ TAILQ_ENTRY(outgoing_journal) entries;
+ char *journal_path;
+};
+TAILQ_HEAD(outgoing_journal_queue, outgoing_journal);
+
+/* iolog_writer.c */
+struct eventlog *evlog_new(TimeSpec *submit_time, InfoMessage **info_msgs, size_t infolen, struct connection_closure *closure);
+bool iolog_init(AcceptMessage *msg, struct connection_closure *closure);
+bool iolog_create(int iofd, struct connection_closure *closure);
+void iolog_close_all(struct connection_closure *closure);
+bool iolog_flush_all(struct connection_closure *closure);
+bool iolog_rewrite(const struct timespec *target, struct connection_closure *closure);
+void update_elapsed_time(TimeSpec *delta, struct timespec *elapsed);
+
+/* logsrvd.c */
+extern struct client_message_switch cms_local;
+bool start_protocol(struct connection_closure *closure);
+void connection_close(struct connection_closure *closure);
+bool schedule_commit_point(TimeSpec *commit_point, struct connection_closure *closure);
+bool fmt_log_id_message(const char *id, struct connection_closure *closure);
+bool schedule_error_message(const char *errstr, struct connection_closure *closure);
+struct connection_buffer *get_free_buf(size_t, struct connection_closure *closure);
+struct connection_closure *connection_closure_alloc(int fd, bool tls, bool relay_only, struct sudo_event_base *base);
+
+/* logsrvd_conf.c */
+bool logsrvd_conf_read(const char *path);
+const char *logsrvd_conf_iolog_dir(void);
+const char *logsrvd_conf_iolog_file(void);
+bool logsrvd_conf_iolog_log_passwords(void);
+void *logsrvd_conf_iolog_passprompt_regex(void);
+struct server_address_list *logsrvd_conf_server_listen_address(void);
+struct server_address_list *logsrvd_conf_relay_address(void);
+const char *logsrvd_conf_relay_dir(void);
+bool logsrvd_conf_relay_store_first(void);
+bool logsrvd_conf_relay_tcp_keepalive(void);
+bool logsrvd_conf_server_tcp_keepalive(void);
+const char *logsrvd_conf_pid_file(void);
+struct timespec *logsrvd_conf_server_timeout(void);
+struct timespec *logsrvd_conf_relay_connect_timeout(void);
+struct timespec *logsrvd_conf_relay_timeout(void);
+time_t logsrvd_conf_relay_retry_interval(void);
+#if defined(HAVE_OPENSSL)
+bool logsrvd_conf_server_tls_check_peer(void);
+SSL_CTX *logsrvd_server_tls_ctx(void);
+bool logsrvd_conf_relay_tls_check_peer(void);
+SSL_CTX *logsrvd_relay_tls_ctx(void);
+#endif
+bool logsrvd_conf_log_exit(void);
+uid_t logsrvd_conf_iolog_uid(void);
+gid_t logsrvd_conf_iolog_gid(void);
+mode_t logsrvd_conf_iolog_mode(void);
+void address_list_addref(struct server_address_list *);
+void address_list_delref(struct server_address_list *);
+void logsrvd_conf_cleanup(void);
+void logsrvd_warn_stderr(bool enabled);
+
+/* logsrvd_journal.c */
+extern struct client_message_switch cms_journal;
+
+/* logsrvd_local.c */
+extern struct client_message_switch cms_local;
+bool set_random_drop(const char *dropstr);
+bool store_accept_local(AcceptMessage *msg, uint8_t *buf, size_t len, struct connection_closure *closure);
+bool store_reject_local(RejectMessage *msg, uint8_t *buf, size_t len, struct connection_closure *closure);
+bool store_exit_local(ExitMessage *msg, uint8_t *buf, size_t len, struct connection_closure *closure);
+bool store_restart_local(RestartMessage *msg, uint8_t *buf, size_t len, struct connection_closure *closure);
+bool store_alert_local(AlertMessage *msg, uint8_t *buf, size_t len, struct connection_closure *closure);
+bool store_iobuf_local(int iofd, IoBuffer *iobuf, uint8_t *buf, size_t len, struct connection_closure *closure);
+bool store_winsize_local(ChangeWindowSize *msg, uint8_t *buf, size_t len, struct connection_closure *closure);
+bool store_suspend_local(CommandSuspend *msg, uint8_t *buf, size_t len, struct connection_closure *closure);
+
+/* logsrvd_queue.c */
+bool logsrvd_queue_enable(time_t timeout, struct sudo_event_base *evbase);
+bool logsrvd_queue_insert(struct connection_closure *closure);
+bool logsrvd_queue_scan(struct sudo_event_base *evbase);
+void logsrvd_queue_dump(void);
+
+/* logsrvd_relay.c */
+extern struct client_message_switch cms_relay;
+void relay_closure_free(struct relay_closure *relay_closure);
+bool connect_relay(struct connection_closure *closure);
+bool relay_shutdown(struct connection_closure *closure);
+
+#endif /* SUDO_LOGSRVD_H */
diff --git a/logsrvd/logsrvd_conf.c b/logsrvd/logsrvd_conf.c
new file mode 100644
index 0000000..ed125cd
--- /dev/null
+++ b/logsrvd/logsrvd_conf.c
@@ -0,0 +1,1918 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <netdb.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+#include <grp.h>
+#include <pwd.h>
+#ifndef HAVE_GETADDRINFO
+# include <compat/getaddrinfo.h>
+#endif
+
+#include <pathnames.h>
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_iolog.h>
+#include <sudo_util.h>
+
+#include <logsrvd.h>
+
+#if defined(HAVE_OPENSSL)
+# define DEFAULT_CA_CERT_PATH "/etc/ssl/sudo/cacert.pem"
+# define DEFAULT_SERVER_CERT_PATH "/etc/ssl/sudo/certs/logsrvd_cert.pem"
+# define DEFAULT_SERVER_KEY_PATH "/etc/ssl/sudo/private/logsrvd_key.pem"
+
+/* Evaluates to true if at least one TLS field is set, else false. */
+# define TLS_CONFIGURED(_s) \
+ ((_s).tls_key_path != NULL || (_s).tls_cert_path != NULL || \
+ (_s).tls_cacert_path != NULL || (_s).tls_dhparams_path != NULL || \
+ (_s).tls_ciphers_v12 != NULL || (_s).tls_ciphers_v13 != NULL || \
+ (_s).tls_verify != -1)
+
+/* Evaluates to the relay-specific TLS setting, falling back to server. */
+# define TLS_RELAY_STR(_c, _f) \
+ ((_c)->relay._f != NULL ? (_c)->relay._f : (_c)->server._f)
+
+# define TLS_RELAY_INT(_c, _f) \
+ ((_c)->relay._f != -1 ? (_c)->relay._f : (_c)->server._f)
+#endif
+
+enum server_log_type {
+ SERVER_LOG_NONE,
+ SERVER_LOG_STDERR,
+ SERVER_LOG_SYSLOG,
+ SERVER_LOG_FILE
+};
+
+struct logsrvd_config;
+typedef bool (*logsrvd_conf_cb_t)(struct logsrvd_config *, const char *, size_t);
+
+struct logsrvd_config_entry {
+ const char *conf_str;
+ logsrvd_conf_cb_t setter;
+ size_t offset;
+};
+
+struct logsrvd_config_section {
+ const char *name;
+ struct logsrvd_config_entry *entries;
+};
+
+struct address_list_container {
+ unsigned int refcnt;
+ struct server_address_list addrs;
+};
+
+static struct logsrvd_config {
+ struct logsrvd_config_server {
+ struct address_list_container addresses;
+ struct timespec timeout;
+ bool tcp_keepalive;
+ enum server_log_type log_type;
+ FILE *log_stream;
+ char *log_file;
+ char *pid_file;
+#if defined(HAVE_OPENSSL)
+ char *tls_key_path;
+ char *tls_cert_path;
+ char *tls_cacert_path;
+ char *tls_dhparams_path;
+ char *tls_ciphers_v12;
+ char *tls_ciphers_v13;
+ int tls_check_peer;
+ int tls_verify;
+ SSL_CTX *ssl_ctx;
+#endif
+ } server;
+ struct logsrvd_config_relay {
+ struct address_list_container relays;
+ struct timespec connect_timeout;
+ struct timespec timeout;
+ time_t retry_interval;
+ char *relay_dir;
+ bool tcp_keepalive;
+ bool store_first;
+#if defined(HAVE_OPENSSL)
+ char *tls_key_path;
+ char *tls_cert_path;
+ char *tls_cacert_path;
+ char *tls_dhparams_path;
+ char *tls_ciphers_v12;
+ char *tls_ciphers_v13;
+ int tls_check_peer;
+ int tls_verify;
+ SSL_CTX *ssl_ctx;
+#endif
+ } relay;
+ struct logsrvd_config_iolog {
+ bool compress;
+ bool flush;
+ bool gid_set;
+ bool log_passwords;
+ uid_t uid;
+ gid_t gid;
+ mode_t mode;
+ unsigned int maxseq;
+ char *iolog_dir;
+ char *iolog_file;
+ void *passprompt_regex;
+ } iolog;
+ struct logsrvd_config_eventlog {
+ int log_type;
+ bool log_exit;
+ enum eventlog_format log_format;
+ } eventlog;
+ struct logsrvd_config_syslog {
+ unsigned int maxlen;
+ int server_facility;
+ int facility;
+ int acceptpri;
+ int rejectpri;
+ int alertpri;
+ } syslog;
+ struct logsrvd_config_logfile {
+ char *path;
+ char *time_format;
+ FILE *stream;
+ } logfile;
+} *logsrvd_config;
+
+static bool logsrvd_warn_enable_stderr = true;
+
+/* eventlog getters */
+bool
+logsrvd_conf_log_exit(void)
+{
+ return logsrvd_config->eventlog.log_exit;
+}
+
+/* iolog getters */
+uid_t
+logsrvd_conf_iolog_uid(void)
+{
+ return logsrvd_config->iolog.uid;
+}
+
+gid_t
+logsrvd_conf_iolog_gid(void)
+{
+ return logsrvd_config->iolog.gid;
+}
+
+mode_t
+logsrvd_conf_iolog_mode(void)
+{
+ return logsrvd_config->iolog.mode;
+}
+
+const char *
+logsrvd_conf_iolog_dir(void)
+{
+ return logsrvd_config->iolog.iolog_dir;
+}
+
+const char *
+logsrvd_conf_iolog_file(void)
+{
+ return logsrvd_config->iolog.iolog_file;
+}
+
+bool
+logsrvd_conf_iolog_log_passwords(void)
+{
+ return logsrvd_config->iolog.log_passwords;
+}
+
+void *
+logsrvd_conf_iolog_passprompt_regex(void)
+{
+ return logsrvd_config->iolog.passprompt_regex;
+}
+
+/* server getters */
+struct server_address_list *
+logsrvd_conf_server_listen_address(void)
+{
+ return &logsrvd_config->server.addresses.addrs;
+}
+
+bool
+logsrvd_conf_server_tcp_keepalive(void)
+{
+ return logsrvd_config->server.tcp_keepalive;
+}
+
+const char *
+logsrvd_conf_pid_file(void)
+{
+ return logsrvd_config->server.pid_file;
+}
+
+struct timespec *
+logsrvd_conf_server_timeout(void)
+{
+ if (sudo_timespecisset(&logsrvd_config->server.timeout)) {
+ return &logsrvd_config->server.timeout;
+ }
+
+ return NULL;
+}
+
+#if defined(HAVE_OPENSSL)
+SSL_CTX *
+logsrvd_server_tls_ctx(void)
+{
+ return logsrvd_config->server.ssl_ctx;
+}
+
+bool
+logsrvd_conf_server_tls_check_peer(void)
+{
+ return logsrvd_config->server.tls_check_peer;
+}
+#endif
+
+/* relay getters */
+struct server_address_list *
+logsrvd_conf_relay_address(void)
+{
+ return &logsrvd_config->relay.relays.addrs;
+}
+
+const char *
+logsrvd_conf_relay_dir(void)
+{
+ return logsrvd_config->relay.relay_dir;
+}
+
+bool
+logsrvd_conf_relay_store_first(void)
+{
+ return logsrvd_config->relay.store_first;
+}
+
+bool
+logsrvd_conf_relay_tcp_keepalive(void)
+{
+ return logsrvd_config->relay.tcp_keepalive;
+}
+
+struct timespec *
+logsrvd_conf_relay_timeout(void)
+{
+ if (sudo_timespecisset(&logsrvd_config->relay.timeout)) {
+ return &logsrvd_config->relay.timeout;
+ }
+
+ return NULL;
+}
+
+struct timespec *
+logsrvd_conf_relay_connect_timeout(void)
+{
+ if (sudo_timespecisset(&logsrvd_config->relay.connect_timeout)) {
+ return &logsrvd_config->relay.connect_timeout;
+ }
+
+ return NULL;
+}
+
+time_t
+logsrvd_conf_relay_retry_interval(void)
+{
+ return logsrvd_config->relay.retry_interval;
+}
+
+#if defined(HAVE_OPENSSL)
+SSL_CTX *
+logsrvd_relay_tls_ctx(void)
+{
+ if (logsrvd_config->relay.ssl_ctx != NULL)
+ return logsrvd_config->relay.ssl_ctx;
+ return logsrvd_config->server.ssl_ctx;
+}
+
+bool
+logsrvd_conf_relay_tls_check_peer(void)
+{
+ if (logsrvd_config->relay.tls_check_peer != -1)
+ return logsrvd_config->relay.tls_check_peer;
+ return logsrvd_config->server.tls_check_peer;
+}
+#endif
+
+/* I/O log callbacks */
+static bool
+cb_iolog_dir(struct logsrvd_config *config, const char *path, size_t offset)
+{
+ debug_decl(cb_iolog_dir, SUDO_DEBUG_UTIL);
+
+ free(config->iolog.iolog_dir);
+ if ((config->iolog.iolog_dir = strdup(path)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+static bool
+cb_iolog_file(struct logsrvd_config *config, const char *path, size_t offset)
+{
+ debug_decl(cb_iolog_file, SUDO_DEBUG_UTIL);
+
+ free(config->iolog.iolog_file);
+ if ((config->iolog.iolog_file = strdup(path)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+static bool
+cb_iolog_compress(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ int val;
+ debug_decl(cb_iolog_compress, SUDO_DEBUG_UTIL);
+
+ if ((val = sudo_strtobool(str)) == -1)
+ debug_return_bool(false);
+
+ config->iolog.compress = val;
+ debug_return_bool(true);
+}
+
+static bool
+cb_iolog_log_passwords(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ int val;
+ debug_decl(cb_iolog_log_passwords, SUDO_DEBUG_UTIL);
+
+ if ((val = sudo_strtobool(str)) == -1)
+ debug_return_bool(false);
+
+ config->iolog.log_passwords = val;
+ debug_return_bool(true);
+}
+
+static bool
+cb_iolog_flush(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ int val;
+ debug_decl(cb_iolog_flush, SUDO_DEBUG_UTIL);
+
+ if ((val = sudo_strtobool(str)) == -1)
+ debug_return_bool(false);
+
+ config->iolog.flush = val;
+ debug_return_bool(true);
+}
+
+static bool
+cb_iolog_user(struct logsrvd_config *config, const char *user, size_t offset)
+{
+ struct passwd *pw;
+ debug_decl(cb_iolog_user, SUDO_DEBUG_UTIL);
+
+ if ((pw = getpwnam(user)) == NULL) {
+ sudo_warnx(U_("unknown user %s"), user);
+ debug_return_bool(false);
+ }
+ config->iolog.uid = pw->pw_uid;
+ if (!config->iolog.gid_set)
+ config->iolog.gid = pw->pw_gid;
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_iolog_group(struct logsrvd_config *config, const char *group, size_t offset)
+{
+ struct group *gr;
+ debug_decl(cb_iolog_group, SUDO_DEBUG_UTIL);
+
+ if ((gr = getgrnam(group)) == NULL) {
+ sudo_warnx(U_("unknown group %s"), group);
+ debug_return_bool(false);
+ }
+ config->iolog.gid = gr->gr_gid;
+ config->iolog.gid_set = true;
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_iolog_mode(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ const char *errstr;
+ mode_t mode;
+ debug_decl(cb_iolog_mode, SUDO_DEBUG_UTIL);
+
+ mode = sudo_strtomode(str, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("unable to parse iolog mode %s"), str);
+ debug_return_bool(false);
+ }
+ config->iolog.mode = mode;
+ debug_return_bool(true);
+}
+
+static bool
+cb_iolog_maxseq(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ const char *errstr;
+ unsigned int value;
+ debug_decl(cb_iolog_maxseq, SUDO_DEBUG_UTIL);
+
+ value = (unsigned int)sudo_strtonum(str, 0, SESSID_MAX, &errstr);
+ if (errstr != NULL) {
+ if (errno != ERANGE) {
+ sudo_warnx(U_("invalid value for %s: %s"), "maxseq", errstr);
+ debug_return_bool(false);
+ }
+ /* Out of range, clamp to SESSID_MAX as documented. */
+ value = SESSID_MAX;
+ }
+ config->iolog.maxseq = value;
+ debug_return_bool(true);
+}
+
+static bool
+cb_iolog_passprompt_regex(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ debug_decl(cb_iolog_passprompt_regex, SUDO_DEBUG_UTIL);
+
+ if (config->iolog.passprompt_regex == NULL) {
+ /* Lazy alloc of the passprompt regex handle. */
+ config->iolog.passprompt_regex = iolog_pwfilt_alloc();
+ if (config->iolog.passprompt_regex == NULL)
+ debug_return_bool(false);
+ }
+ debug_return_bool(iolog_pwfilt_add(config->iolog.passprompt_regex, str));
+}
+
+/* Server callbacks */
+static bool
+append_address(struct server_address_list *addresses, const char *str,
+ bool allow_wildcard)
+{
+ struct addrinfo hints, *res, *res0 = NULL;
+ char *sa_str = NULL, *sa_host = NULL;
+ char *copy, *host, *port;
+ bool tls, ret = false;
+ int error;
+ debug_decl(append_address, SUDO_DEBUG_UTIL);
+
+ if ((copy = strdup(str)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+
+ /* Parse host[:port] */
+ if (!iolog_parse_host_port(copy, &host, &port, &tls, DEFAULT_PORT,
+ DEFAULT_PORT_TLS))
+ goto done;
+ if (host[0] == '*' && host[1] == '\0') {
+ if (!allow_wildcard)
+ goto done;
+ host = NULL;
+ }
+
+#if !defined(HAVE_OPENSSL)
+ if (tls) {
+ sudo_warnx("%s", U_("TLS not supported"));
+ goto done;
+ }
+#endif
+
+ /* Only make a single copy of the string + host for all addresses. */
+ if ((sa_str = sudo_rcstr_dup(str)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ if (host != NULL && (sa_host = sudo_rcstr_dup(host)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+
+ /* Resolve host (and port if it is a service). */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE;
+ error = getaddrinfo(host, port, &hints, &res0);
+ if (error != 0) {
+ sudo_gai_warn(error, U_("%s:%s"), host ? host : "*", port);
+ goto done;
+ }
+ for (res = res0; res != NULL; res = res->ai_next) {
+ struct server_address *addr;
+
+ if ((addr = malloc(sizeof(*addr))) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ addr->sa_str = sudo_rcstr_addref(sa_str);
+ addr->sa_host = sudo_rcstr_addref(sa_host);
+
+ memcpy(&addr->sa_un, res->ai_addr, res->ai_addrlen);
+ addr->sa_size = res->ai_addrlen;
+ addr->tls = tls;
+ TAILQ_INSERT_TAIL(addresses, addr, entries);
+ }
+
+ ret = true;
+done:
+ sudo_rcstr_delref(sa_str);
+ sudo_rcstr_delref(sa_host);
+ if (res0 != NULL)
+ freeaddrinfo(res0);
+ free(copy);
+ debug_return_bool(ret);
+}
+
+static bool
+cb_server_listen_address(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ return append_address(&config->server.addresses.addrs, str, true);
+}
+
+static bool
+cb_server_timeout(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ time_t timeout;
+ const char *errstr;
+ debug_decl(cb_server_timeout, SUDO_DEBUG_UTIL);
+
+ timeout = (time_t)sudo_strtonum(str, 0, TIME_T_MAX, &errstr);
+ if (errstr != NULL)
+ debug_return_bool(false);
+
+ config->server.timeout.tv_sec = timeout;
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_server_keepalive(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ int val;
+ debug_decl(cb_server_keepalive, SUDO_DEBUG_UTIL);
+
+ if ((val = sudo_strtobool(str)) == -1)
+ debug_return_bool(false);
+
+ config->server.tcp_keepalive = val;
+ debug_return_bool(true);
+}
+
+static bool
+cb_server_pid_file(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ char *copy = NULL;
+ debug_decl(cb_server_pid_file, SUDO_DEBUG_UTIL);
+
+ /* An empty value means to disable the pid file. */
+ if (*str != '\0') {
+ if (*str != '/') {
+ sudo_warnx(U_("%s: not a fully qualified path"), str);
+ debug_return_bool(false);
+ }
+ if ((copy = strdup(str)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ }
+
+ free(config->server.pid_file);
+ config->server.pid_file = copy;
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_server_log(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ char *copy = NULL;
+ enum server_log_type log_type = SERVER_LOG_NONE;
+ debug_decl(cb_server_log, SUDO_DEBUG_UTIL);
+
+ /* An empty value means to disable the server log. */
+ if (*str != '\0') {
+ if (*str == '/') {
+ log_type = SERVER_LOG_FILE;
+ if ((copy = strdup(str)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ } else if (strcmp(str, "stderr") == 0) {
+ log_type = SERVER_LOG_STDERR;
+ } else if (strcmp(str, "syslog") == 0) {
+ log_type = SERVER_LOG_SYSLOG;
+ } else {
+ debug_return_bool(false);
+ }
+ }
+
+ free(config->server.log_file);
+ config->server.log_file = copy;
+ config->server.log_type = log_type;
+
+ debug_return_bool(true);
+}
+
+#if defined(HAVE_OPENSSL)
+static bool
+cb_tls_key(struct logsrvd_config *config, const char *path, size_t offset)
+{
+ char **p = (char **)((char *)config + offset);
+ debug_decl(cb_tls_key, SUDO_DEBUG_UTIL);
+
+ free(*p);
+ if ((*p = strdup(path)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+static bool
+cb_tls_cacert(struct logsrvd_config *config, const char *path, size_t offset)
+{
+ char **p = (char **)((char *)config + offset);
+ debug_decl(cb_tls_cacert, SUDO_DEBUG_UTIL);
+
+ free(*p);
+ if ((*p = strdup(path)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+static bool
+cb_tls_cert(struct logsrvd_config *config, const char *path, size_t offset)
+{
+ char **p = (char **)((char *)config + offset);
+ debug_decl(cb_tls_cert, SUDO_DEBUG_UTIL);
+
+ free(*p);
+ if ((*p = strdup(path)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+static bool
+cb_tls_dhparams(struct logsrvd_config *config, const char *path, size_t offset)
+{
+ char **p = (char **)((char *)config + offset);
+ debug_decl(cb_tls_dhparams, SUDO_DEBUG_UTIL);
+
+ free(*p);
+ if ((*p = strdup(path)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+static bool
+cb_tls_ciphers12(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ char **p = (char **)((char *)config + offset);
+ debug_decl(cb_tls_ciphers12, SUDO_DEBUG_UTIL);
+
+ free(*p);
+ if ((*p = strdup(str)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+static bool
+cb_tls_ciphers13(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ char **p = (char **)((char *)config + offset);
+ debug_decl(cb_tls_ciphers13, SUDO_DEBUG_UTIL);
+
+ free(*p);
+ if ((*p = strdup(str)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+static bool
+cb_tls_verify(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ int *p = (int *)((char *)config + offset);
+ int val;
+ debug_decl(cb_tls_verify, SUDO_DEBUG_UTIL);
+
+ if ((val = sudo_strtobool(str)) == -1)
+ debug_return_bool(false);
+
+ *p = val;
+ debug_return_bool(true);
+}
+
+static bool
+cb_tls_checkpeer(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ int *p = (int *)((char *)config + offset);
+ int val;
+ debug_decl(cb_tls_checkpeer, SUDO_DEBUG_UTIL);
+
+ if ((val = sudo_strtobool(str)) == -1)
+ debug_return_bool(false);
+
+ *p = val;
+ debug_return_bool(true);
+}
+#endif
+
+/* relay callbacks */
+static bool
+cb_relay_host(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ return append_address(&config->relay.relays.addrs, str, false);
+}
+
+static bool
+cb_relay_timeout(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ time_t timeout;
+ const char *errstr;
+ debug_decl(cb_relay_timeout, SUDO_DEBUG_UTIL);
+
+ timeout = (time_t)sudo_strtonum(str, 0, TIME_T_MAX, &errstr);
+ if (errstr != NULL)
+ debug_return_bool(false);
+
+ config->server.timeout.tv_sec = timeout;
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_relay_connect_timeout(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ time_t timeout;
+ const char *errstr;
+ debug_decl(cb_relay_connect_timeout, SUDO_DEBUG_UTIL);
+
+ timeout = (time_t)sudo_strtonum(str, 0, TIME_T_MAX, &errstr);
+ if (errstr != NULL)
+ debug_return_bool(false);
+
+ config->relay.connect_timeout.tv_sec = timeout;
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_relay_dir(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ char *copy = NULL;
+ debug_decl(cb_relay_dir, SUDO_DEBUG_UTIL);
+
+ if ((copy = strdup(str)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+
+ free(config->relay.relay_dir);
+ config->relay.relay_dir = copy;
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_retry_interval(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ time_t interval;
+ const char *errstr;
+ debug_decl(cb_retry_interval, SUDO_DEBUG_UTIL);
+
+ interval = (time_t)sudo_strtonum(str, 0, TIME_T_MAX, &errstr);
+ if (errstr != NULL)
+ debug_return_bool(false);
+
+ config->relay.retry_interval = interval;
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_relay_store_first(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ int val;
+ debug_decl(cb_relay_store_first, SUDO_DEBUG_UTIL);
+
+ if ((val = sudo_strtobool(str)) == -1)
+ debug_return_bool(false);
+
+ config->relay.store_first = val;
+ debug_return_bool(true);
+}
+
+static bool
+cb_relay_keepalive(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ int val;
+ debug_decl(cb_relay_keepalive, SUDO_DEBUG_UTIL);
+
+ if ((val = sudo_strtobool(str)) == -1)
+ debug_return_bool(false);
+
+ config->relay.tcp_keepalive = val;
+ debug_return_bool(true);
+}
+
+/* eventlog callbacks */
+static bool
+cb_eventlog_type(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ debug_decl(cb_eventlog_type, SUDO_DEBUG_UTIL);
+
+ if (strcmp(str, "none") == 0)
+ config->eventlog.log_type = EVLOG_NONE;
+ else if (strcmp(str, "syslog") == 0)
+ config->eventlog.log_type = EVLOG_SYSLOG;
+ else if (strcmp(str, "logfile") == 0)
+ config->eventlog.log_type = EVLOG_FILE;
+ else
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_eventlog_format(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ debug_decl(cb_eventlog_format, SUDO_DEBUG_UTIL);
+
+ if (strcmp(str, "json") == 0)
+ config->eventlog.log_format = EVLOG_JSON;
+ else if (strcmp(str, "sudo") == 0)
+ config->eventlog.log_format = EVLOG_SUDO;
+ else
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_eventlog_exit(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ int val;
+ debug_decl(cb_eventlog_exit, SUDO_DEBUG_UTIL);
+
+ if ((val = sudo_strtobool(str)) == -1)
+ debug_return_bool(false);
+
+ config->eventlog.log_exit = val;
+ debug_return_bool(true);
+}
+
+/* syslog callbacks */
+static bool
+cb_syslog_maxlen(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ unsigned int maxlen;
+ const char *errstr;
+ debug_decl(cb_syslog_maxlen, SUDO_DEBUG_UTIL);
+
+ maxlen = (unsigned int)sudo_strtonum(str, 1, UINT_MAX, &errstr);
+ if (errstr != NULL)
+ debug_return_bool(false);
+
+ config->syslog.maxlen = maxlen;
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_syslog_server_facility(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ int logfac;
+ debug_decl(cb_syslog_server_facility, SUDO_DEBUG_UTIL);
+
+ if (!sudo_str2logfac(str, &logfac)) {
+ sudo_warnx(U_("unknown syslog facility %s"), str);
+ debug_return_bool(false);
+ }
+
+ config->syslog.server_facility = logfac;
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_syslog_facility(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ int logfac;
+ debug_decl(cb_syslog_facility, SUDO_DEBUG_UTIL);
+
+ if (!sudo_str2logfac(str, &logfac)) {
+ sudo_warnx(U_("unknown syslog facility %s"), str);
+ debug_return_bool(false);
+ }
+
+ config->syslog.facility = logfac;
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_syslog_acceptpri(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ int logpri;
+ debug_decl(cb_syslog_acceptpri, SUDO_DEBUG_UTIL);
+
+ if (!sudo_str2logpri(str, &logpri)) {
+ sudo_warnx(U_("unknown syslog priority %s"), str);
+ debug_return_bool(false);
+ }
+
+ config->syslog.acceptpri = logpri;
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_syslog_rejectpri(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ int logpri;
+ debug_decl(cb_syslog_rejectpri, SUDO_DEBUG_UTIL);
+
+ if (!sudo_str2logpri(str, &logpri)) {
+ sudo_warnx(U_("unknown syslog priority %s"), str);
+ debug_return_bool(false);
+ }
+
+ config->syslog.rejectpri = logpri;
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_syslog_alertpri(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ int logpri;
+ debug_decl(cb_syslog_alertpri, SUDO_DEBUG_UTIL);
+
+ if (!sudo_str2logpri(str, &logpri)) {
+ sudo_warnx(U_("unknown syslog priority %s"), str);
+ debug_return_bool(false);
+ }
+
+ config->syslog.alertpri = logpri;
+
+ debug_return_bool(true);
+}
+
+/* logfile callbacks */
+static bool
+cb_logfile_path(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ char *copy = NULL;
+ debug_decl(cb_logfile_path, SUDO_DEBUG_UTIL);
+
+ if (*str != '/') {
+ sudo_warnx(U_("%s: not a fully qualified path"), str);
+ debug_return_bool(false);
+ }
+ if ((copy = strdup(str)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+
+ free(config->logfile.path);
+ config->logfile.path = copy;
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_logfile_time_format(struct logsrvd_config *config, const char *str, size_t offset)
+{
+ char *copy = NULL;
+ debug_decl(cb_logfile_time_format, SUDO_DEBUG_UTIL);
+
+ if ((copy = strdup(str)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+
+ free(config->logfile.time_format);
+ config->logfile.time_format = copy;
+
+ debug_return_bool(true);
+}
+
+void
+address_list_addref(struct server_address_list *al)
+{
+ struct address_list_container *container =
+ __containerof(al, struct address_list_container, addrs);
+ container->refcnt++;
+}
+
+void
+address_list_delref(struct server_address_list *al)
+{
+ struct address_list_container *container =
+ __containerof(al, struct address_list_container, addrs);
+ if (--container->refcnt == 0) {
+ struct server_address *addr;
+ while ((addr = TAILQ_FIRST(al))) {
+ TAILQ_REMOVE(al, addr, entries);
+ sudo_rcstr_delref(addr->sa_str);
+ sudo_rcstr_delref(addr->sa_host);
+ free(addr);
+ }
+ }
+}
+
+static struct logsrvd_config_entry server_conf_entries[] = {
+ { "listen_address", cb_server_listen_address },
+ { "timeout", cb_server_timeout },
+ { "tcp_keepalive", cb_server_keepalive },
+ { "pid_file", cb_server_pid_file },
+ { "server_log", cb_server_log },
+#if defined(HAVE_OPENSSL)
+ { "tls_key", cb_tls_key, offsetof(struct logsrvd_config, server.tls_key_path) },
+ { "tls_cacert", cb_tls_cacert, offsetof(struct logsrvd_config, server.tls_cacert_path) },
+ { "tls_cert", cb_tls_cert, offsetof(struct logsrvd_config, server.tls_cert_path) },
+ { "tls_dhparams", cb_tls_dhparams, offsetof(struct logsrvd_config, server.tls_dhparams_path) },
+ { "tls_ciphers_v12", cb_tls_ciphers12, offsetof(struct logsrvd_config, server.tls_ciphers_v12) },
+ { "tls_ciphers_v13", cb_tls_ciphers13, offsetof(struct logsrvd_config, server.tls_ciphers_v13) },
+ { "tls_checkpeer", cb_tls_checkpeer, offsetof(struct logsrvd_config, server.tls_check_peer) },
+ { "tls_verify", cb_tls_verify, offsetof(struct logsrvd_config, server.tls_verify) },
+#endif
+ { NULL }
+};
+
+static struct logsrvd_config_entry relay_conf_entries[] = {
+ { "relay_host", cb_relay_host },
+ { "timeout", cb_relay_timeout },
+ { "connect_timeout", cb_relay_connect_timeout },
+ { "relay_dir", cb_relay_dir },
+ { "retry_interval", cb_retry_interval },
+ { "store_first", cb_relay_store_first },
+ { "tcp_keepalive", cb_relay_keepalive },
+#if defined(HAVE_OPENSSL)
+ { "tls_key", cb_tls_key, offsetof(struct logsrvd_config, relay.tls_key_path) },
+ { "tls_cacert", cb_tls_cacert, offsetof(struct logsrvd_config, relay.tls_cacert_path) },
+ { "tls_cert", cb_tls_cert, offsetof(struct logsrvd_config, relay.tls_cert_path) },
+ { "tls_dhparams", cb_tls_dhparams, offsetof(struct logsrvd_config, relay.tls_dhparams_path) },
+ { "tls_ciphers_v12", cb_tls_ciphers12, offsetof(struct logsrvd_config, relay.tls_ciphers_v12) },
+ { "tls_ciphers_v13", cb_tls_ciphers13, offsetof(struct logsrvd_config, relay.tls_ciphers_v13) },
+ { "tls_checkpeer", cb_tls_checkpeer, offsetof(struct logsrvd_config, relay.tls_check_peer) },
+ { "tls_verify", cb_tls_verify, offsetof(struct logsrvd_config, relay.tls_verify) },
+#endif
+ { NULL }
+};
+
+static struct logsrvd_config_entry iolog_conf_entries[] = {
+ { "iolog_dir", cb_iolog_dir },
+ { "iolog_file", cb_iolog_file },
+ { "iolog_flush", cb_iolog_flush },
+ { "iolog_compress", cb_iolog_compress },
+ { "iolog_user", cb_iolog_user },
+ { "iolog_group", cb_iolog_group },
+ { "iolog_mode", cb_iolog_mode },
+ { "log_passwords", cb_iolog_log_passwords },
+ { "maxseq", cb_iolog_maxseq },
+ { "passprompt_regex", cb_iolog_passprompt_regex },
+ { NULL }
+};
+
+static struct logsrvd_config_entry eventlog_conf_entries[] = {
+ { "log_type", cb_eventlog_type },
+ { "log_format", cb_eventlog_format },
+ { "log_exit", cb_eventlog_exit },
+ { NULL }
+};
+
+static struct logsrvd_config_entry syslog_conf_entries[] = {
+ { "maxlen", cb_syslog_maxlen },
+ { "server_facility", cb_syslog_server_facility },
+ { "facility", cb_syslog_facility },
+ { "reject_priority", cb_syslog_rejectpri },
+ { "accept_priority", cb_syslog_acceptpri },
+ { "alert_priority", cb_syslog_alertpri },
+ { NULL }
+};
+
+static struct logsrvd_config_entry logfile_conf_entries[] = {
+ { "path", cb_logfile_path },
+ { "time_format", cb_logfile_time_format },
+ { NULL }
+};
+
+static struct logsrvd_config_section logsrvd_config_sections[] = {
+ { "server", server_conf_entries },
+ { "relay", relay_conf_entries },
+ { "iolog", iolog_conf_entries },
+ { "eventlog", eventlog_conf_entries },
+ { "syslog", syslog_conf_entries },
+ { "logfile", logfile_conf_entries },
+ { NULL }
+};
+
+static bool
+logsrvd_conf_parse(struct logsrvd_config *config, FILE *fp, const char *path)
+{
+ struct logsrvd_config_section *conf_section = NULL;
+ unsigned int lineno = 0;
+ size_t linesize = 0;
+ char *line = NULL;
+ bool ret = false;
+ debug_decl(logsrvd_conf_parse, SUDO_DEBUG_UTIL);
+
+ while (sudo_parseln(&line, &linesize, &lineno, fp, 0) != -1) {
+ struct logsrvd_config_entry *entry;
+ char *ep, *val;
+
+ /* Skip blank, comment or invalid lines. */
+ if (*line == '\0' || *line == ';')
+ continue;
+
+ /* New section */
+ if (line[0] == '[') {
+ char *cp, *section_name = line + 1;
+
+ if ((ep = strchr(section_name, ']')) == NULL) {
+ sudo_warnx(U_("%s:%d unmatched '[': %s"),
+ path, lineno, line);
+ goto done;
+ }
+ for (cp = ep + 1; *cp != '\0'; cp++) {
+ if (!isspace((unsigned char)*cp)) {
+ sudo_warnx(U_("%s:%d garbage after ']': %s"),
+ path, lineno, line);
+ goto done;
+ }
+ }
+ *ep = '\0';
+ for (conf_section = logsrvd_config_sections; conf_section->name != NULL;
+ conf_section++) {
+ if (strcasecmp(section_name, conf_section->name) == 0)
+ break;
+ }
+ if (conf_section->name == NULL) {
+ sudo_warnx(U_("%s:%d invalid config section: %s"),
+ path, lineno, section_name);
+ goto done;
+ }
+ continue;
+ }
+
+ if ((ep = strchr(line, '=')) == NULL) {
+ sudo_warnx(U_("%s:%d invalid configuration line: %s"),
+ path, lineno, line);
+ goto done;
+ }
+
+ if (conf_section == NULL) {
+ sudo_warnx(U_("%s:%d expected section name: %s"),
+ path, lineno, line);
+ goto done;
+ }
+
+ val = ep + 1;
+ while (isspace((unsigned char)*val))
+ val++;
+ while (ep > line && isspace((unsigned char)ep[-1]))
+ ep--;
+ *ep = '\0';
+ for (entry = conf_section->entries; entry->conf_str != NULL; entry++) {
+ if (strcasecmp(line, entry->conf_str) == 0) {
+ if (!entry->setter(config, val, entry->offset)) {
+ sudo_warnx(U_("invalid value for %s: %s"),
+ entry->conf_str, val);
+ goto done;
+ }
+ break;
+ }
+ }
+ if (entry->conf_str == NULL) {
+ sudo_warnx(U_("%s:%d [%s] illegal key: %s"), path, lineno,
+ conf_section->name, line);
+ goto done;
+ }
+ }
+ ret = true;
+
+done:
+ free(line);
+ debug_return_bool(ret);
+}
+
+static FILE *
+logsrvd_open_log_file(const char *path, int flags)
+{
+ mode_t oldmask;
+ FILE *fp = NULL;
+ const char *omode;
+ int fd;
+ debug_decl(logsrvd_open_log_file, SUDO_DEBUG_UTIL);
+
+ if (ISSET(flags, O_APPEND)) {
+ omode = "a";
+ } else {
+ omode = "w";
+ }
+ oldmask = umask(S_IRWXG|S_IRWXO);
+ fd = open(path, flags, S_IRUSR|S_IWUSR);
+ (void)umask(oldmask);
+ if (fd == -1 || (fp = fdopen(fd, omode)) == NULL) {
+ sudo_warn(U_("unable to open log file %s"), path);
+ if (fd != -1)
+ close(fd);
+ }
+
+ debug_return_ptr(fp);
+}
+
+static FILE *
+logsrvd_open_eventlog(struct logsrvd_config *config)
+{
+ int flags;
+ debug_decl(logsrvd_open_eventlog, SUDO_DEBUG_UTIL);
+
+ /* Cannot append to a JSON file. */
+ if (config->eventlog.log_format == EVLOG_JSON) {
+ flags = O_RDWR|O_CREAT;
+ } else {
+ flags = O_WRONLY|O_APPEND|O_CREAT;
+ }
+ debug_return_ptr(logsrvd_open_log_file(config->logfile.path, flags));
+}
+
+static FILE *
+logsrvd_stub_open_log(int type, const char *logfile)
+{
+ /* Actual open already done by logsrvd_open_eventlog() */
+ return logsrvd_config->logfile.stream;
+}
+
+static void
+logsrvd_stub_close_log(int type, FILE *fp)
+{
+ return;
+}
+
+/* Set eventlog configuration settings from logsrvd config. */
+static void
+logsrvd_conf_eventlog_setconf(struct logsrvd_config *config)
+{
+ debug_decl(logsrvd_conf_eventlog_setconf, SUDO_DEBUG_UTIL);
+
+ eventlog_set_type(config->eventlog.log_type);
+ eventlog_set_format(config->eventlog.log_format);
+ eventlog_set_syslog_acceptpri(config->syslog.acceptpri);
+ eventlog_set_syslog_rejectpri(config->syslog.rejectpri);
+ eventlog_set_syslog_alertpri(config->syslog.alertpri);
+ eventlog_set_syslog_maxlen(config->syslog.maxlen);
+ eventlog_set_logpath(config->logfile.path);
+ eventlog_set_time_fmt(config->logfile.time_format);
+ eventlog_set_open_log(logsrvd_stub_open_log);
+ eventlog_set_close_log(logsrvd_stub_close_log);
+
+ debug_return;
+}
+
+/* Set I/O log configuration settings from logsrvd config. */
+static void
+logsrvd_conf_iolog_setconf(struct logsrvd_config *config)
+{
+ debug_decl(logsrvd_conf_iolog_setconf, SUDO_DEBUG_UTIL);
+
+ iolog_set_defaults();
+ iolog_set_compress(config->iolog.compress);
+ iolog_set_flush(config->iolog.flush);
+ iolog_set_owner(config->iolog.uid, config->iolog.gid);
+ iolog_set_mode(config->iolog.mode);
+ iolog_set_maxseq(config->iolog.maxseq);
+
+ debug_return;
+}
+
+/*
+ * Conversation function for use by sudo_warn/sudo_fatal.
+ * Logs to stdout/stderr.
+ */
+static int
+logsrvd_conv_stderr(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
+{
+ int i;
+ debug_decl(logsrvd_conv_stderr, SUDO_DEBUG_UTIL);
+
+ for (i = 0; i < num_msgs; i++) {
+ if (fputs(msgs[i].msg, stderr) == EOF)
+ debug_return_int(-1);
+ }
+
+ debug_return_int(0);
+}
+
+/*
+ * Conversation function for use by sudo_warn/sudo_fatal.
+ * Acts as a no-op log sink.
+ */
+static int
+logsrvd_conv_none(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
+{
+ /* Also write to stderr if still in the foreground. */
+ if (logsrvd_warn_enable_stderr) {
+ (void)logsrvd_conv_stderr(num_msgs, msgs, replies, callback);
+ }
+
+ return 0;
+}
+
+/*
+ * Conversation function for use by sudo_warn/sudo_fatal.
+ * Logs to syslog.
+ */
+static int
+logsrvd_conv_syslog(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
+{
+ char *buf = NULL, *cp = NULL;
+ const char *progname;
+ size_t proglen, bufsize = 0;
+ int i;
+ debug_decl(logsrvd_conv_syslog, SUDO_DEBUG_UTIL);
+
+ if (logsrvd_config == NULL) {
+ debug_return_int(logsrvd_conv_stderr(num_msgs, msgs, replies, callback));
+ }
+
+ /* Also write to stderr if still in the foreground. */
+ if (logsrvd_warn_enable_stderr) {
+ (void)logsrvd_conv_stderr(num_msgs, msgs, replies, callback);
+ }
+
+ /*
+ * Concat messages into a flag string that we can syslog.
+ */
+ progname = getprogname();
+ proglen = strlen(progname);
+ for (i = 0; i < num_msgs; i++) {
+ const char *msg = msgs[i].msg;
+ size_t len = strlen(msg);
+ size_t used = (size_t)(cp - buf);
+
+ /* Strip leading "sudo_logsrvd: " prefix. */
+ if (strncmp(msg, progname, proglen) == 0) {
+ msg += proglen;
+ len -= proglen;
+ if (len == 0) {
+ /* Skip over ": " string that follows program name. */
+ if (i + 1 < num_msgs && strcmp(msgs[i + 1].msg, ": ") == 0) {
+ i++;
+ continue;
+ }
+ } else if (msg[0] == ':' && msg[1] == ' ') {
+ /* Handle "progname: " */
+ msg += 2;
+ len -= 2;
+ }
+ }
+
+ /* Strip off trailing newlines. */
+ while (len > 1 && msg[len - 1] == '\n')
+ len--;
+ if (len == 0)
+ continue;
+
+ if (len >= bufsize - used) {
+ bufsize += 1024;
+ char *tmp = realloc(buf, bufsize);
+ if (tmp == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ free(buf);
+ debug_return_int(-1);
+ }
+ buf = tmp;
+ cp = tmp + used;
+ }
+ memcpy(cp, msg, len);
+ cp[len] = '\0';
+ cp += len;
+ }
+ if (buf != NULL) {
+ openlog(progname, 0, logsrvd_config->syslog.server_facility);
+ syslog(LOG_ERR, "%s", buf);
+ free(buf);
+
+ /* Restore old syslog settings. */
+ if (logsrvd_config->eventlog.log_type == EVLOG_SYSLOG)
+ openlog("sudo", 0, logsrvd_config->syslog.facility);
+ }
+
+ debug_return_int(0);
+}
+
+/*
+ * Conversation function for use by sudo_warn/sudo_fatal.
+ * Logs to an already-open log file.
+ */
+static int
+logsrvd_conv_logfile(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
+{
+ const char *progname;
+ size_t proglen;
+ int i;
+ debug_decl(logsrvd_conv_logfile, SUDO_DEBUG_UTIL);
+
+ if (logsrvd_config == NULL) {
+ debug_return_int(logsrvd_conv_stderr(num_msgs, msgs, replies, callback));
+ }
+
+ /* Also write to stderr if still in the foreground. */
+ if (logsrvd_warn_enable_stderr) {
+ (void)logsrvd_conv_stderr(num_msgs, msgs, replies, callback);
+ }
+
+ if (logsrvd_config->server.log_stream == NULL) {
+ errno = EBADF;
+ debug_return_int(-1);
+ }
+
+ progname = getprogname();
+ proglen = strlen(progname);
+ for (i = 0; i < num_msgs; i++) {
+ const char *msg = msgs[i].msg;
+ size_t len = strlen(msg);
+
+ /* Strip leading "sudo_logsrvd: " prefix. */
+ if (strncmp(msg, progname, proglen) == 0) {
+ msg += proglen;
+ len -= proglen;
+ if (len == 0) {
+ /* Skip over ": " string that follows program name. */
+ if (i + 1 < num_msgs && strcmp(msgs[i + 1].msg, ": ") == 0) {
+ i++;
+ continue;
+ }
+ } else if (msg[0] == ':' && msg[1] == ' ') {
+ /* Handle "progname: " */
+ msg += 2;
+ len -= 2;
+ }
+ }
+
+ if (fwrite(msg, len, 1, logsrvd_config->server.log_stream) != 1)
+ debug_return_int(-1);
+ }
+
+ debug_return_int(0);
+}
+
+/* Free the specified struct logsrvd_config and its contents. */
+static void
+logsrvd_conf_free(struct logsrvd_config *config)
+{
+ debug_decl(logsrvd_conf_free, SUDO_DEBUG_UTIL);
+
+ if (config == NULL)
+ debug_return;
+
+ /* struct logsrvd_config_server */
+ address_list_delref(&config->server.addresses.addrs);
+ free(config->server.pid_file);
+ free(config->server.log_file);
+ if (config->server.log_stream != NULL)
+ fclose(config->server.log_stream);
+#if defined(HAVE_OPENSSL)
+ free(config->server.tls_key_path);
+ free(config->server.tls_cert_path);
+ free(config->server.tls_cacert_path);
+ free(config->server.tls_dhparams_path);
+ free(config->server.tls_ciphers_v12);
+ free(config->server.tls_ciphers_v13);
+
+ if (config->server.ssl_ctx != NULL)
+ SSL_CTX_free(config->server.ssl_ctx);
+#endif
+
+ /* struct logsrvd_config_relay */
+ address_list_delref(&config->relay.relays.addrs);
+ free(config->relay.relay_dir);
+#if defined(HAVE_OPENSSL)
+ free(config->relay.tls_key_path);
+ free(config->relay.tls_cert_path);
+ free(config->relay.tls_cacert_path);
+ free(config->relay.tls_dhparams_path);
+ free(config->relay.tls_ciphers_v12);
+ free(config->relay.tls_ciphers_v13);
+
+ if (config->relay.ssl_ctx != NULL)
+ SSL_CTX_free(config->relay.ssl_ctx);
+#endif
+
+ /* struct logsrvd_config_iolog */
+ free(config->iolog.iolog_dir);
+ free(config->iolog.iolog_file);
+ iolog_pwfilt_free(config->iolog.passprompt_regex);
+
+ /* struct logsrvd_config_logfile */
+ free(config->logfile.path);
+ free(config->logfile.time_format);
+ if (config->logfile.stream != NULL)
+ fclose(config->logfile.stream);
+
+ free(config);
+
+ debug_return;
+}
+
+/* Allocate a new struct logsrvd_config and set default values. */
+static struct logsrvd_config *
+logsrvd_conf_alloc(void)
+{
+ struct logsrvd_config *config;
+ debug_decl(logsrvd_conf_alloc, SUDO_DEBUG_UTIL);
+
+ if ((config = calloc(1, sizeof(*config))) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_ptr(NULL);
+ }
+
+ /* Relay defaults */
+ TAILQ_INIT(&config->relay.relays.addrs);
+ config->relay.relays.refcnt = 1;
+ config->relay.timeout.tv_sec = DEFAULT_SOCKET_TIMEOUT_SEC;
+ config->relay.connect_timeout.tv_sec = DEFAULT_SOCKET_TIMEOUT_SEC;
+ config->relay.tcp_keepalive = true;
+ config->relay.retry_interval = 30;
+ if (!cb_relay_dir(config, _PATH_SUDO_RELAY_DIR, 0))
+ goto bad;
+#if defined(HAVE_OPENSSL)
+ config->relay.tls_verify = -1;
+ config->relay.tls_check_peer = -1;
+#endif
+
+ /* Server defaults */
+ TAILQ_INIT(&config->server.addresses.addrs);
+ config->server.addresses.refcnt = 1;
+ config->server.timeout.tv_sec = DEFAULT_SOCKET_TIMEOUT_SEC;
+ config->server.tcp_keepalive = true;
+ config->server.log_type = SERVER_LOG_SYSLOG;
+ config->server.pid_file = strdup(_PATH_SUDO_LOGSRVD_PID);
+ if (config->server.pid_file == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+
+#if defined(HAVE_OPENSSL)
+ /*
+ * Only set default CA and cert paths if the files actually exist.
+ * This ensures we don't enable TLS by default when it is not configured.
+ */
+ if (access(DEFAULT_CA_CERT_PATH, R_OK) == 0) {
+ config->server.tls_cacert_path = strdup(DEFAULT_CA_CERT_PATH);
+ if (config->server.tls_cacert_path == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ if (access(DEFAULT_SERVER_CERT_PATH, R_OK) == 0) {
+ config->server.tls_cert_path = strdup(DEFAULT_SERVER_CERT_PATH);
+ if (config->server.tls_cert_path == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ }
+ config->server.tls_key_path = strdup(DEFAULT_SERVER_KEY_PATH);
+ if (config->server.tls_key_path == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ config->server.tls_verify = true;
+ config->server.tls_check_peer = false;
+#endif
+
+ /* I/O log defaults */
+ config->iolog.compress = false;
+ config->iolog.flush = true;
+ config->iolog.mode = S_IRUSR|S_IWUSR;
+ config->iolog.maxseq = SESSID_MAX;
+ if (!cb_iolog_dir(config, _PATH_SUDO_IO_LOGDIR, 0))
+ goto bad;
+ if (!cb_iolog_file(config, "%{seq}", 0))
+ goto bad;
+ config->iolog.uid = ROOT_UID;
+ config->iolog.gid = ROOT_GID;
+ config->iolog.gid_set = false;
+ config->iolog.log_passwords = true;
+
+ /* Event log defaults */
+ config->eventlog.log_type = EVLOG_SYSLOG;
+ config->eventlog.log_format = EVLOG_SUDO;
+ config->eventlog.log_exit = false;
+
+ /* Syslog defaults */
+ config->syslog.maxlen = 960;
+ config->syslog.server_facility = LOG_DAEMON;
+ if (!cb_syslog_facility(config, LOGFAC, 0)) {
+ sudo_warnx(U_("unknown syslog facility %s"), LOGFAC);
+ goto bad;
+ }
+ if (!cb_syslog_acceptpri(config, PRI_SUCCESS, 0)) {
+ sudo_warnx(U_("unknown syslog priority %s"), PRI_SUCCESS);
+ goto bad;
+ }
+ if (!cb_syslog_rejectpri(config, PRI_FAILURE, 0)) {
+ sudo_warnx(U_("unknown syslog priority %s"), PRI_FAILURE);
+ goto bad;
+ }
+ if (!cb_syslog_alertpri(config, PRI_FAILURE, 0)) {
+ sudo_warnx(U_("unknown syslog priority %s"), PRI_FAILURE);
+ goto bad;
+ }
+
+ /* Log file defaults */
+ if (!cb_logfile_time_format(config, "%h %e %T", 0))
+ goto bad;
+ if (!cb_logfile_path(config, _PATH_SUDO_LOGFILE, 0))
+ goto bad;
+
+ debug_return_ptr(config);
+bad:
+ logsrvd_conf_free(config);
+ debug_return_ptr(NULL);
+}
+
+static bool
+logsrvd_conf_apply(struct logsrvd_config *config)
+{
+#if defined(HAVE_OPENSSL)
+ struct server_address *addr;
+#endif
+ debug_decl(logsrvd_conf_apply, SUDO_DEBUG_UTIL);
+
+ /* There can be multiple passprompt regular expressions. */
+ if (config->iolog.passprompt_regex == NULL) {
+ if (!cb_iolog_passprompt_regex(config, PASSPROMPT_REGEX, 0))
+ debug_return_bool(false);
+ }
+
+ /* There can be multiple addresses so we can't set a default earlier. */
+ if (TAILQ_EMPTY(&config->server.addresses.addrs)) {
+ /* Enable plaintext listender. */
+ if (!cb_server_listen_address(config, "*:" DEFAULT_PORT, 0))
+ debug_return_bool(false);
+#if defined(HAVE_OPENSSL)
+ /* If a certificate was specified, enable the TLS listener too. */
+ if (config->server.tls_cert_path != NULL) {
+ if (!cb_server_listen_address(config, "*:" DEFAULT_PORT_TLS "(tls)", 0))
+ debug_return_bool(false);
+ }
+ } else {
+ /* Check that TLS configuration is valid. */
+ TAILQ_FOREACH(addr, &config->server.addresses.addrs, entries) {
+ if (!addr->tls)
+ continue;
+ /*
+ * If a TLS listener was explicitly enabled but the cert path
+ * was not, use the default.
+ */
+ if (config->server.tls_cert_path == NULL) {
+ config->server.tls_cert_path =
+ strdup(DEFAULT_SERVER_CERT_PATH);
+ if (config->server.tls_cert_path == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ }
+ break;
+ }
+#endif /* HAVE_OPENSSL */
+ }
+
+#if defined(HAVE_OPENSSL)
+ TAILQ_FOREACH(addr, &config->server.addresses.addrs, entries) {
+ if (!addr->tls)
+ continue;
+ /* Create a TLS context for the server. */
+ config->server.ssl_ctx = init_tls_context(
+ config->server.tls_cacert_path, config->server.tls_cert_path,
+ config->server.tls_key_path, config->server.tls_dhparams_path,
+ config->server.tls_ciphers_v12, config->server.tls_ciphers_v13,
+ config->server.tls_verify);
+ if (config->server.ssl_ctx == NULL) {
+ sudo_warnx("%s", U_("unable to initialize server TLS context"));
+ debug_return_bool(false);
+ }
+ break;
+ }
+
+ if (TLS_CONFIGURED(config->relay)) {
+ TAILQ_FOREACH(addr, &config->relay.relays.addrs, entries) {
+ if (!addr->tls)
+ continue;
+ /* Create a TLS context for the relay. */
+ config->relay.ssl_ctx = init_tls_context(
+ TLS_RELAY_STR(config, tls_cacert_path),
+ TLS_RELAY_STR(config, tls_cert_path),
+ TLS_RELAY_STR(config, tls_key_path),
+ TLS_RELAY_STR(config, tls_dhparams_path),
+ TLS_RELAY_STR(config, tls_ciphers_v12),
+ TLS_RELAY_STR(config, tls_ciphers_v13),
+ TLS_RELAY_INT(config, tls_verify));
+ if (config->relay.ssl_ctx == NULL) {
+ sudo_warnx("%s", U_("unable to initialize relay TLS context"));
+ debug_return_bool(false);
+ }
+ break;
+ }
+ }
+#endif /* HAVE_OPENSSL */
+
+ /* Clear store_first if not relaying. */
+ if (TAILQ_EMPTY(&config->relay.relays.addrs))
+ config->relay.store_first = false;
+
+ /* Open server log if specified. */
+ switch (config->server.log_type) {
+ case SERVER_LOG_SYSLOG:
+ sudo_warn_set_conversation(logsrvd_conv_syslog);
+ break;
+ case SERVER_LOG_FILE:
+ config->server.log_stream =
+ logsrvd_open_log_file(config->server.log_file, O_WRONLY|O_APPEND|O_CREAT);
+ if (config->server.log_stream == NULL)
+ debug_return_bool(false);
+ sudo_warn_set_conversation(logsrvd_conv_logfile);
+ break;
+ case SERVER_LOG_NONE:
+ sudo_warn_set_conversation(logsrvd_conv_none);
+ break;
+ case SERVER_LOG_STDERR:
+ /* Default is stderr. */
+ sudo_warn_set_conversation(NULL);
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "cannot open unknown log type %d", config->eventlog.log_type);
+ break;
+ }
+
+ /* Open event log if specified. */
+ switch (config->eventlog.log_type) {
+ case EVLOG_SYSLOG:
+ openlog("sudo", 0, config->syslog.facility);
+ break;
+ case EVLOG_FILE:
+ config->logfile.stream = logsrvd_open_eventlog(config);
+ if (config->logfile.stream == NULL)
+ debug_return_bool(false);
+ break;
+ case EVLOG_NONE:
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "cannot open unknown log type %d", config->eventlog.log_type);
+ break;
+ }
+
+ /*
+ * Update event and I/O log library config and install the new
+ * logsrvd config. We must not fail past this point or the event
+ * and I/O log config will be inconsistent with the logsrvd config.
+ */
+ logsrvd_conf_iolog_setconf(config);
+ logsrvd_conf_eventlog_setconf(config);
+
+ logsrvd_conf_free(logsrvd_config);
+ logsrvd_config = config;
+
+ debug_return_bool(true);
+}
+
+/*
+ * Read .ini style logsrvd.conf file.
+ * If path is NULL, use _PATH_SUDO_LOGSRVD_CONF.
+ * Note that we use '#' not ';' for the comment character.
+ */
+bool
+logsrvd_conf_read(const char *path)
+{
+ struct logsrvd_config *config;
+ char conf_file[PATH_MAX];
+ bool ret = false;
+ FILE *fp = NULL;
+ int fd = -1;
+ debug_decl(logsrvd_conf_read, SUDO_DEBUG_UTIL);
+
+ config = logsrvd_conf_alloc();
+
+ if (path != NULL) {
+ if (strlcpy(conf_file, path, sizeof(conf_file)) >= sizeof(conf_file))
+ errno = ENAMETOOLONG;
+ else
+ fd = open(conf_file, O_RDONLY);
+ } else {
+ fd = sudo_open_conf_path(_PATH_SUDO_LOGSRVD_CONF, conf_file,
+ sizeof(conf_file), NULL);
+ }
+ if (fd != -1)
+ fp = fdopen(fd, "r");
+ if (fp == NULL) {
+ if (path != NULL || errno != ENOENT) {
+ sudo_warn("%s", conf_file);
+ goto done;
+ }
+ } else {
+ if (!logsrvd_conf_parse(config, fp, conf_file))
+ goto done;
+ }
+
+ /* Install new config */
+ if (logsrvd_conf_apply(config)) {
+ config = NULL;
+ ret = true;
+ }
+
+done:
+ logsrvd_conf_free(config);
+ if (fp != NULL)
+ fclose(fp);
+ debug_return_bool(ret);
+}
+
+void
+logsrvd_conf_cleanup(void)
+{
+ debug_decl(logsrvd_conf_cleanup, SUDO_DEBUG_UTIL);
+
+ logsrvd_conf_free(logsrvd_config);
+ logsrvd_config = NULL;
+
+ debug_return;
+}
+
+void
+logsrvd_warn_stderr(bool enabled)
+{
+ logsrvd_warn_enable_stderr = enabled;
+}
diff --git a/logsrvd/logsrvd_journal.c b/logsrvd/logsrvd_journal.c
new file mode 100644
index 0000000..e4d2083
--- /dev/null
+++ b/logsrvd/logsrvd_journal.c
@@ -0,0 +1,622 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_conf.h>
+#include <sudo_debug.h>
+#include <sudo_event.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_iolog.h>
+#include <sudo_util.h>
+
+#include <logsrvd.h>
+
+/*
+ * Helper function to set closure->journal and closure->journal_path.
+ */
+static bool
+journal_fdopen(int fd, const char *journal_path,
+ struct connection_closure *closure)
+{
+ debug_decl(journal_fdopen, SUDO_DEBUG_UTIL);
+
+ free(closure->journal_path);
+ closure->journal_path = strdup(journal_path);
+ if (closure->journal_path == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+
+ /* Defer fdopen() until last--it cannot be undone. */
+ if (closure->journal != NULL)
+ fclose(closure->journal);
+ if ((closure->journal = fdopen(fd, "r+")) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to fdopen journal file %s", journal_path);
+ debug_return_bool(false);
+ }
+
+ debug_return_bool(true);
+}
+
+static int
+journal_mkstemp(const char *parent_dir, char *pathbuf, size_t pathsize)
+{
+ int len, dfd = -1, fd = -1;
+ mode_t dirmode, oldmask;
+ char *template;
+ debug_decl(journal_mkstemp, SUDO_DEBUG_UTIL);
+
+ /* umask must not be more restrictive than the file modes. */
+ dirmode = logsrvd_conf_iolog_mode() | S_IXUSR;
+ if (dirmode & (S_IRGRP|S_IWGRP))
+ dirmode |= S_IXGRP;
+ if (dirmode & (S_IROTH|S_IWOTH))
+ dirmode |= S_IXOTH;
+ oldmask = umask(ACCESSPERMS & ~dirmode);
+
+ len = snprintf(pathbuf, pathsize, "%s/%s/%s",
+ logsrvd_conf_relay_dir(), parent_dir, RELAY_TEMPLATE);
+ if ((size_t)len >= pathsize) {
+ errno = ENAMETOOLONG;
+ sudo_warn("%s/%s/%s", logsrvd_conf_relay_dir(), parent_dir,
+ RELAY_TEMPLATE);
+ goto done;
+ }
+ dfd = sudo_open_parent_dir(pathbuf, logsrvd_conf_iolog_uid(),
+ logsrvd_conf_iolog_gid(), S_IRWXU|S_IXGRP|S_IXOTH, false);
+ if (dfd == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to create parent dir for %s", pathbuf);
+ goto done;
+ }
+ template = &pathbuf[(size_t)len - (sizeof(RELAY_TEMPLATE) - 1)];
+ if ((fd = mkostempsat(dfd, template, 0, 0)) == -1) {
+ sudo_warn(U_("%s: %s"), "mkstemp", pathbuf);
+ goto done;
+ }
+
+done:
+ umask(oldmask);
+ if (dfd != -1)
+ close(dfd);
+
+ debug_return_int(fd);
+}
+
+/*
+ * Create a temporary file in the relay dir and store it in the closure.
+ */
+static bool
+journal_create(struct connection_closure *closure)
+{
+ char journal_path[PATH_MAX];
+ int fd;
+ debug_decl(journal_create, SUDO_DEBUG_UTIL);
+
+ fd = journal_mkstemp("incoming", journal_path, sizeof(journal_path));
+ if (fd == -1) {
+ closure->errstr = _("unable to create journal file");
+ debug_return_bool(false);
+ }
+ if (!sudo_lock_file(fd, SUDO_TLOCK)) {
+ sudo_warn(U_("unable to lock %s"), journal_path);
+ unlink(journal_path);
+ close(fd);
+ closure->errstr = _("unable to lock journal file");
+ debug_return_bool(false);
+ }
+ if (!journal_fdopen(fd, journal_path, closure)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to fdopen journal file %s", journal_path);
+ unlink(journal_path);
+ close(fd);
+ closure->errstr = _("unable to open journal file");
+ debug_return_bool(false);
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Flush any buffered data, rewind journal to the beginning and
+ * move to the outgoing directory.
+ * The actual open file is closed in connection_closure_free().
+ */
+static bool
+journal_finish(struct connection_closure *closure)
+{
+ char outgoing_path[PATH_MAX];
+ size_t len;
+ int fd;
+ debug_decl(journal_finish, SUDO_DEBUG_UTIL);
+
+ if (fflush(closure->journal) != 0) {
+ closure->errstr = _("unable to write journal file");
+ debug_return_bool(false);
+ }
+ rewind(closure->journal);
+
+ /* Move journal to the outgoing directory. */
+ fd = journal_mkstemp("outgoing", outgoing_path, sizeof(outgoing_path));
+ if (fd == -1) {
+ closure->errstr = _("unable to rename journal file");
+ debug_return_bool(false);
+ }
+ close(fd);
+ if (rename(closure->journal_path, outgoing_path) == -1) {
+ sudo_warn(U_("unable to rename %s to %s"), closure->journal_path,
+ outgoing_path);
+ closure->errstr = _("unable to rename journal file");
+ unlink(outgoing_path);
+ debug_return_bool(false);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "renamed %s -> %s", closure->journal_path, outgoing_path);
+ len = strlen(outgoing_path);
+ if (strlen(closure->journal_path) == len) {
+ /* This should always be true. */
+ memcpy(closure->journal_path, outgoing_path, len);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "length mismatch %zu != %zu", strlen(closure->journal_path), len);
+ free(closure->journal_path);
+ closure->journal_path = strdup(outgoing_path);
+ if (closure->journal_path == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ closure->errstr = _("unable to allocate memory");
+ debug_return_bool(false);
+ }
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Seek ahead in the journal to the specified target time.
+ * Returns true if we reached the target time exactly, else false.
+ */
+static bool
+journal_seek(struct timespec *target, struct connection_closure *closure)
+{
+ ClientMessage *msg = NULL;
+ size_t nread, bufsize = 0;
+ uint8_t *buf = NULL;
+ uint32_t msg_len;
+ bool ret = false;
+ debug_decl(journal_seek, SUDO_DEBUG_UTIL);
+
+ for (;;) {
+ TimeSpec *delay = NULL;
+
+ /* Read message size (uint32_t in network byte order). */
+ nread = fread(&msg_len, sizeof(msg_len), 1, closure->journal);
+ if (nread != 1) {
+ if (feof(closure->journal)) {
+ sudo_warnx(U_("%s: %s"), closure->journal_path,
+ U_("unexpected EOF reading journal file"));
+ closure->errstr = _("unexpected EOF reading journal file");
+ } else {
+ sudo_warn(U_("%s: %s"), closure->journal_path,
+ U_("error reading journal file"));
+ closure->errstr = _("error reading journal file");
+ }
+ break;
+ }
+ msg_len = ntohl(msg_len);
+ if (msg_len > MESSAGE_SIZE_MAX) {
+ sudo_warnx(U_("%s: %s"), closure->journal_path,
+ U_("client message too large"));
+ closure->errstr = _("client message too large");
+ break;
+ }
+
+ /* Read actual message now that we know the size. */
+ if (msg_len != 0) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "%s: reading message %u bytes", closure->journal_path, msg_len);
+
+ if (msg_len > bufsize) {
+ bufsize = sudo_pow2_roundup(msg_len);
+ if (bufsize < msg_len) {
+ /* overflow */
+ errno = ENOMEM;
+ closure->errstr = _("unable to allocate memory");
+ break;
+ }
+ free(buf);
+ if ((buf = malloc(bufsize)) == NULL) {
+ closure->errstr = _("unable to allocate memory");
+ break;
+ }
+ }
+
+ nread = fread(buf, msg_len, 1, closure->journal);
+ if (nread != 1) {
+ if (feof(closure->journal)) {
+ sudo_warnx(U_("%s: %s"), closure->journal_path,
+ U_("unexpected EOF reading journal file"));
+ closure->errstr = _("unexpected EOF reading journal file");
+ } else {
+ sudo_warn(U_("%s: %s"), closure->journal_path,
+ U_("error reading journal file"));
+ closure->errstr = _("error reading journal file");
+ }
+ break;
+ }
+ }
+
+ client_message__free_unpacked(msg, NULL);
+ msg = client_message__unpack(NULL, msg_len, buf);
+ if (msg == NULL) {
+ sudo_warnx(U_("unable to unpack %s size %zu"), "ClientMessage",
+ (size_t)msg_len);
+ closure->errstr = _("invalid journal file, unable to restart");
+ break;
+ }
+
+ switch (msg->type_case) {
+ case CLIENT_MESSAGE__TYPE_HELLO_MSG:
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "seeking past ClientHello (%d)", msg->type_case);
+ break;
+ case CLIENT_MESSAGE__TYPE_ACCEPT_MSG:
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "seeking past AcceptMessage (%d)", msg->type_case);
+ break;
+ case CLIENT_MESSAGE__TYPE_REJECT_MSG:
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "seeking past RejectMessage (%d)", msg->type_case);
+ break;
+ case CLIENT_MESSAGE__TYPE_EXIT_MSG:
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "seeking past ExitMessage (%d)", msg->type_case);
+ break;
+ case CLIENT_MESSAGE__TYPE_RESTART_MSG:
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "seeking past RestartMessage (%d)", msg->type_case);
+ break;
+ case CLIENT_MESSAGE__TYPE_ALERT_MSG:
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "seeking past AlertMessage (%d)", msg->type_case);
+ break;
+ case CLIENT_MESSAGE__TYPE_TTYIN_BUF:
+ delay = msg->u.ttyin_buf->delay;
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "read IoBuffer (%d), delay [%lld, %ld]", msg->type_case,
+ (long long)delay->tv_sec, (long)delay->tv_nsec);
+ break;
+ case CLIENT_MESSAGE__TYPE_TTYOUT_BUF:
+ delay = msg->u.ttyout_buf->delay;
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "read IoBuffer (%d), delay [%lld, %ld]", msg->type_case,
+ (long long)delay->tv_sec, (long)delay->tv_nsec);
+ break;
+ case CLIENT_MESSAGE__TYPE_STDIN_BUF:
+ delay = msg->u.stdin_buf->delay;
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "read IoBuffer (%d), delay [%lld, %ld]", msg->type_case,
+ (long long)delay->tv_sec, (long)delay->tv_nsec);
+ break;
+ case CLIENT_MESSAGE__TYPE_STDOUT_BUF:
+ delay = msg->u.stdout_buf->delay;
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "read stdout_buf (%d), delay [%lld, %ld]", msg->type_case,
+ (long long)delay->tv_sec, (long)delay->tv_nsec);
+ break;
+ case CLIENT_MESSAGE__TYPE_STDERR_BUF:
+ delay = msg->u.stderr_buf->delay;
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "read stderr_buf (%d), delay [%lld, %ld]", msg->type_case,
+ (long long)delay->tv_sec, (long)delay->tv_nsec);
+ break;
+ case CLIENT_MESSAGE__TYPE_WINSIZE_EVENT:
+ delay = msg->u.winsize_event->delay;
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "read ChangeWindowSize (%d), delay [%lld, %ld]", msg->type_case,
+ (long long)delay->tv_sec, (long)delay->tv_nsec);
+ break;
+ case CLIENT_MESSAGE__TYPE_SUSPEND_EVENT:
+ delay = msg->u.suspend_event->delay;
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "read CommandSuspend (%d), delay [%lld, %ld]", msg->type_case,
+ (long long)delay->tv_sec, (long)delay->tv_nsec);
+ break;
+ default:
+ sudo_warnx(U_("unexpected type_case value %d in %s from %s"),
+ msg->type_case, "ClientMessage", closure->journal_path);
+ break;
+ }
+ if (delay != NULL)
+ update_elapsed_time(delay, &closure->elapsed_time);
+
+ if (sudo_timespeccmp(&closure->elapsed_time, target, >=)) {
+ if (sudo_timespeccmp(&closure->elapsed_time, target, ==)) {
+ ret = true;
+ break;
+ }
+
+ /* Mismatch between resume point and stored log. */
+ closure->errstr = _("invalid journal file, unable to restart");
+ sudo_warnx(U_("%s: unable to find resume point [%lld, %ld]"),
+ closure->journal_path, (long long)target->tv_sec,
+ target->tv_nsec);
+ break;
+ }
+ }
+
+ client_message__free_unpacked(msg, NULL);
+ free(buf);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Restart an existing journal.
+ * Seeks to the resume_point in RestartMessage before continuing.
+ * Returns true if we reached the target time exactly, else false.
+ */
+static bool
+journal_restart(RestartMessage *msg, uint8_t *buf, size_t buflen,
+ struct connection_closure *closure)
+{
+ struct timespec target;
+ int fd, len;
+ char *cp, journal_path[PATH_MAX];
+ debug_decl(journal_restart, SUDO_DEBUG_UTIL);
+
+ /* Strip off leading hostname from log_id. */
+ if ((cp = strchr(msg->log_id, '/')) != NULL) {
+ if (cp != msg->log_id)
+ cp++;
+ } else {
+ cp = msg->log_id;
+ }
+ len = snprintf(journal_path, sizeof(journal_path), "%s/incoming/%s",
+ logsrvd_conf_relay_dir(), cp);
+ if (len >= ssizeof(journal_path)) {
+ errno = ENAMETOOLONG;
+ sudo_warn("%s/incoming/%s", logsrvd_conf_relay_dir(), cp);
+ closure->errstr = _("unable to create journal file");
+ debug_return_bool(false);
+ }
+ if ((fd = open(journal_path, O_RDWR)) == -1) {
+ sudo_warn(U_("unable to open %s"), journal_path);
+ closure->errstr = _("unable to create journal file");
+ debug_return_bool(false);
+ }
+ if (!journal_fdopen(fd, journal_path, closure)) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ close(fd);
+ closure->errstr = _("unable to allocate memory");
+ debug_return_bool(false);
+ }
+
+ /* Seek forward to resume point. */
+ target.tv_sec = (time_t)msg->resume_point->tv_sec;
+ target.tv_nsec = (long)msg->resume_point->tv_nsec;
+ if (!journal_seek(&target, closure)) {
+ sudo_warn(U_("unable to seek to [%lld, %ld] in journal file %s"),
+ (long long)target.tv_sec, target.tv_nsec, journal_path);
+ debug_return_bool(false);
+ }
+
+ debug_return_bool(true);
+}
+
+static bool
+journal_write(uint8_t * restrict buf, size_t len, struct connection_closure * restrict closure)
+{
+ uint32_t msg_len;
+ debug_decl(journal_write, SUDO_DEBUG_UTIL);
+
+ /* 32-bit message length in network byte order. */
+ msg_len = htonl((uint32_t)len);
+ if (fwrite(&msg_len, 1, sizeof(msg_len), closure->journal) != sizeof(msg_len)) {
+ closure->errstr = _("unable to write journal file");
+ debug_return_bool(false);
+ }
+ /* message payload */
+ if (fwrite(buf, 1, len, closure->journal) != len) {
+ closure->errstr = _("unable to write journal file");
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+/*
+ * Store an AcceptMessage from the client in the journal.
+ */
+static bool
+journal_accept(AcceptMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ debug_decl(journal_accept, SUDO_DEBUG_UTIL);
+
+ if (closure->journal_path != NULL) {
+ /* Re-use existing journal file. */
+ debug_return_bool(journal_write(buf, len, closure));
+ }
+
+ /* Store message in a journal for later relaying. */
+ if (!journal_create(closure))
+ debug_return_bool(false);
+ if (!journal_write(buf, len, closure))
+ debug_return_bool(false);
+
+ if (msg->expect_iobufs) {
+ /* Send log ID to client for restarting connections. */
+ if (!fmt_log_id_message(closure->journal_path, closure))
+ debug_return_bool(false);
+ if (sudo_ev_add(closure->evbase, closure->write_ev,
+ logsrvd_conf_server_timeout(), false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ debug_return_bool(false);
+ }
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Store a RejectMessage from the client in the journal.
+ */
+static bool
+journal_reject(RejectMessage *msg, uint8_t * restrict buf, size_t len,
+ struct connection_closure * restrict closure)
+{
+ debug_decl(journal_reject, SUDO_DEBUG_UTIL);
+
+ /* Store message in a journal for later relaying. */
+ if (closure->journal_path == NULL) {
+ if (!journal_create(closure))
+ debug_return_bool(false);
+ }
+ if (!journal_write(buf, len, closure))
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+/*
+ * Store an ExitMessage from the client in the journal.
+ */
+static bool
+journal_exit(ExitMessage *msg, uint8_t * restrict buf, size_t len,
+ struct connection_closure * restrict closure)
+{
+ debug_decl(journal_exit, SUDO_DEBUG_UTIL);
+
+ /* Store exit message in journal. */
+ if (!journal_write(buf, len, closure))
+ debug_return_bool(false);
+ if (!journal_finish(closure))
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+/*
+ * Store an AlertMessage from the client in the journal.
+ */
+static bool
+journal_alert(AlertMessage *msg, uint8_t * restrict buf, size_t len,
+ struct connection_closure * restrict closure)
+{
+ debug_decl(journal_alert, SUDO_DEBUG_UTIL);
+
+ /* Store message in a journal for later relaying. */
+ if (closure->journal_path == NULL) {
+ if (!journal_create(closure))
+ debug_return_bool(false);
+ }
+ if (!journal_write(buf, len, closure))
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+/*
+ * Store an IoBuffer from the client in the journal.
+ */
+static bool
+journal_iobuf(int iofd, IoBuffer *iobuf, uint8_t * restrict buf, size_t len,
+ struct connection_closure * restrict closure)
+{
+ debug_decl(journal_iobuf, SUDO_DEBUG_UTIL);
+
+ if (!journal_write(buf, len, closure))
+ debug_return_bool(false);
+ update_elapsed_time(iobuf->delay, &closure->elapsed_time);
+
+ debug_return_bool(true);
+}
+
+/*
+ * Store a CommandSuspend message from the client in the journal.
+ */
+static bool
+journal_suspend(CommandSuspend *msg, uint8_t * restrict buf, size_t len,
+ struct connection_closure * restrict closure)
+{
+ debug_decl(journal_suspend, SUDO_DEBUG_UTIL);
+
+ update_elapsed_time(msg->delay, &closure->elapsed_time);
+
+ debug_return_bool(journal_write(buf, len, closure));
+}
+
+/*
+ * Store a ChangeWindowSize message from the client in the journal.
+ */
+static bool
+journal_winsize(ChangeWindowSize *msg, uint8_t * restrict buf, size_t len,
+ struct connection_closure * restrict closure)
+{
+ debug_decl(journal_winsize, SUDO_DEBUG_UTIL);
+
+ update_elapsed_time(msg->delay, &closure->elapsed_time);
+
+ debug_return_bool(journal_write(buf, len, closure));
+}
+
+struct client_message_switch cms_journal = {
+ journal_accept,
+ journal_reject,
+ journal_exit,
+ journal_restart,
+ journal_alert,
+ journal_iobuf,
+ journal_suspend,
+ journal_winsize
+};
diff --git a/logsrvd/logsrvd_local.c b/logsrvd/logsrvd_local.c
new file mode 100644
index 0000000..8096d97
--- /dev/null
+++ b/logsrvd/logsrvd_local.c
@@ -0,0 +1,715 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_conf.h>
+#include <sudo_debug.h>
+#include <sudo_event.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_json.h>
+#include <sudo_iolog.h>
+#include <sudo_rand.h>
+#include <sudo_util.h>
+
+#include <logsrvd.h>
+
+struct logsrvd_info_closure {
+ InfoMessage **info_msgs;
+ size_t infolen;
+};
+
+static double random_drop;
+
+bool
+set_random_drop(const char *dropstr)
+{
+ char *ep;
+ debug_decl(set_random_drop, SUDO_DEBUG_UTIL);
+
+ errno = 0;
+ random_drop = strtod(dropstr, &ep);
+ if (*ep != '\0' || errno != 0)
+ debug_return_bool(false);
+ random_drop /= 100.0; /* convert from percentage */
+
+ debug_return_bool(true);
+}
+
+static bool
+logsrvd_json_log_cb(struct json_container *jsonc, void *v)
+{
+ struct logsrvd_info_closure *closure = v;
+ struct json_value json_value;
+ size_t idx;
+ debug_decl(logsrvd_json_log_cb, SUDO_DEBUG_UTIL);
+
+ for (idx = 0; idx < closure->infolen; idx++) {
+ InfoMessage *info = closure->info_msgs[idx];
+
+ switch (info->value_case) {
+ case INFO_MESSAGE__VALUE_NUMVAL:
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = info->u.numval;
+ if (!sudo_json_add_value(jsonc, info->key, &json_value))
+ goto bad;
+ break;
+ case INFO_MESSAGE__VALUE_STRVAL:
+ if (info->u.strval == NULL) {
+ sudo_warnx(U_("%s: protocol error: NULL value found in %s"),
+ "local", info->key);
+ break;
+ }
+ json_value.type = JSON_STRING;
+ json_value.u.string = info->u.strval;
+ if (!sudo_json_add_value(jsonc, info->key, &json_value))
+ goto bad;
+ break;
+ case INFO_MESSAGE__VALUE_STRLISTVAL: {
+ InfoMessage__StringList *strlist = info->u.strlistval;
+ size_t n;
+
+ if (strlist == NULL) {
+ sudo_warnx(U_("%s: protocol error: NULL value found in %s"),
+ "local", info->key);
+ break;
+ }
+ if (!sudo_json_open_array(jsonc, info->key))
+ goto bad;
+ for (n = 0; n < strlist->n_strings; n++) {
+ if (strlist->strings[n] == NULL) {
+ sudo_warnx(U_("%s: protocol error: NULL value found in %s"),
+ "local", info->key);
+ break;
+ }
+ json_value.type = JSON_STRING;
+ json_value.u.string = strlist->strings[n];
+ if (!sudo_json_add_value(jsonc, NULL, &json_value))
+ goto bad;
+ }
+ if (!sudo_json_close_array(jsonc))
+ goto bad;
+ break;
+ }
+ case INFO_MESSAGE__VALUE_NUMLISTVAL: {
+ InfoMessage__NumberList *numlist = info->u.numlistval;
+ size_t n;
+
+ if (numlist == NULL) {
+ sudo_warnx(U_("%s: protocol error: NULL value found in %s"),
+ "local", info->key);
+ break;
+ }
+ if (!sudo_json_open_array(jsonc, info->key))
+ goto bad;
+ for (n = 0; n < numlist->n_numbers; n++) {
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = numlist->numbers[n];
+ if (!sudo_json_add_value(jsonc, NULL, &json_value))
+ goto bad;
+ }
+ if (!sudo_json_close_array(jsonc))
+ goto bad;
+ break;
+ }
+ default:
+ sudo_warnx(U_("unexpected value_case %d in %s from %s"),
+ info->value_case, "InfoMessage", "local");
+ break;
+ }
+ }
+ debug_return_bool(true);
+bad:
+ debug_return_bool(false);
+}
+
+/*
+ * Parse and store an AcceptMessage locally.
+ */
+bool
+store_accept_local(AcceptMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ struct logsrvd_info_closure info = { msg->info_msgs, msg->n_info_msgs };
+ bool new_session = closure->evlog == NULL;
+ struct eventlog *evlog = NULL;
+ char *log_id = NULL;
+ bool ret = false;
+ debug_decl(store_accept_local, SUDO_DEBUG_UTIL);
+
+ /* Store sudo-style event and I/O logs. */
+ evlog = evlog_new(msg->submit_time, msg->info_msgs, msg->n_info_msgs,
+ closure);
+ if (evlog == NULL) {
+ closure->errstr = _("error parsing AcceptMessage");
+ goto done;
+ }
+
+ /* Additional setup for the initial command in the session. */
+ if (new_session) {
+ closure->evlog = evlog;
+
+ /* Create I/O log info file and parent directories. */
+ if (msg->expect_iobufs) {
+ if (!iolog_init(msg, closure)) {
+ closure->errstr = _("error creating I/O log");
+ goto done;
+ }
+ closure->log_io = true;
+ log_id = closure->evlog->iolog_path;
+ }
+ } else if (closure->log_io) {
+ /* Sub-command from an existing session, set iolog and offset. */
+ evlog->iolog_path = strdup(closure->evlog->iolog_path);
+ if (evlog->iolog_path == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ closure->errstr = _("unable to allocate memory");
+ goto done;
+ }
+ if (closure->evlog->iolog_file != NULL) {
+ evlog->iolog_file = evlog->iolog_path +
+ (closure->evlog->iolog_file - closure->evlog->iolog_path);
+ }
+ sudo_timespecsub(&evlog->submit_time, &closure->evlog->submit_time,
+ &evlog->iolog_offset);
+ }
+
+ if (!eventlog_accept(evlog, 0, logsrvd_json_log_cb, &info)) {
+ closure->errstr = _("error logging accept event");
+ goto done;
+ }
+
+ if (new_session && log_id != NULL) {
+ /* Send log ID to client for restarting connections. */
+ if (!fmt_log_id_message(log_id, closure))
+ goto done;
+ if (sudo_ev_add(closure->evbase, closure->write_ev,
+ logsrvd_conf_server_timeout(), false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto done;
+ }
+ }
+
+ ret = true;
+
+done:
+ if (closure->evlog != evlog)
+ eventlog_free(evlog);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Parse and store a RejectMessage locally.
+ */
+bool
+store_reject_local(RejectMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ struct logsrvd_info_closure info = { msg->info_msgs, msg->n_info_msgs };
+ struct eventlog *evlog = NULL;
+ bool ret = false;
+ debug_decl(store_reject_local, SUDO_DEBUG_UTIL);
+
+ evlog = evlog_new(msg->submit_time, msg->info_msgs, msg->n_info_msgs,
+ closure);
+ if (evlog == NULL) {
+ closure->errstr = _("error parsing RejectMessage");
+ goto done;
+ }
+
+ if (closure->evlog == NULL) {
+ /* Initial command in session. */
+ closure->evlog = evlog;
+ } else if (closure->log_io) {
+ /* Sub-command from an existing session, set iolog and offset. */
+ evlog->iolog_path = strdup(closure->evlog->iolog_path);
+ if (evlog->iolog_path == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ closure->errstr = _("unable to allocate memory");
+ goto done;
+ }
+ if (closure->evlog->iolog_file != NULL) {
+ evlog->iolog_file = evlog->iolog_path +
+ (closure->evlog->iolog_file - closure->evlog->iolog_path);
+ }
+ sudo_timespecsub(&evlog->submit_time, &closure->evlog->submit_time,
+ &evlog->iolog_offset);
+ }
+
+ if (!eventlog_reject(evlog, 0, msg->reason, logsrvd_json_log_cb, &info)) {
+ closure->errstr = _("error logging reject event");
+ goto done;
+ }
+
+ ret = true;
+
+done:
+ if (closure->evlog != evlog)
+ eventlog_free(evlog);
+
+ debug_return_bool(ret);
+}
+
+static bool
+store_exit_info_json(int dfd, struct eventlog *evlog)
+{
+ struct json_container jsonc = { 0 };
+ struct json_value json_value;
+ struct iovec iov[3];
+ bool ret = false;
+ int fd = -1;
+ off_t pos;
+ debug_decl(store_exit_info_json, SUDO_DEBUG_UTIL);
+
+ if (!sudo_json_init(&jsonc, 4, false, false, false))
+ goto done;
+
+ fd = iolog_openat(dfd, "log.json", O_RDWR);
+ if (fd == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to open to %s/log.json", evlog->iolog_path);
+ if (errno == ENOENT) {
+ /* Ignore missing log.json file. */
+ ret = true;
+ }
+ goto done;
+ }
+
+ if (sudo_timespecisset(&evlog->run_time)) {
+ if (!sudo_json_open_object(&jsonc, "run_time"))
+ goto done;
+
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = evlog->run_time.tv_sec;
+ if (!sudo_json_add_value(&jsonc, "seconds", &json_value))
+ goto done;
+
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = evlog->run_time.tv_nsec;
+ if (!sudo_json_add_value(&jsonc, "nanoseconds", &json_value))
+ goto done;
+
+ if (!sudo_json_close_object(&jsonc))
+ goto done;
+ }
+
+ if (evlog->signal_name != NULL) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = evlog->signal_name;
+ if (!sudo_json_add_value(&jsonc, "signal", &json_value))
+ goto done;
+
+ json_value.type = JSON_BOOL;
+ json_value.u.boolean = evlog->dumped_core;
+ if (!sudo_json_add_value(&jsonc, "dumped_core", &json_value))
+ goto done;
+ }
+
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = evlog->exit_value;
+ if (!sudo_json_add_value(&jsonc, "exit_value", &json_value))
+ goto done;
+
+ /* Back up to overwrite the final "\n}\n" */
+ pos = lseek(fd, -3, SEEK_END);
+ if (pos == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to rewind %s/log.json 3 bytes", evlog->iolog_path);
+ goto done;
+ }
+
+ /* Append the exit data and close the object. */
+ iov[0].iov_base = (char *)",";
+ iov[0].iov_len = 1;
+ iov[1].iov_base = sudo_json_get_buf(&jsonc);
+ iov[1].iov_len = sudo_json_get_len(&jsonc);
+ iov[2].iov_base = (char *)"\n}\n";
+ iov[2].iov_len = 3;
+ if (writev(fd, iov, 3) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to write %s/log.json", evlog->iolog_path);
+ /* Back up and try to restore to original state. */
+ if (lseek(fd, pos, SEEK_SET) != -1) {
+ ignore_result(write(fd, "\n}\n", 3));
+ }
+ goto done;
+ }
+
+ ret = true;
+
+done:
+ if (fd != -1)
+ close(fd);
+ sudo_json_free(&jsonc);
+ debug_return_bool(ret);
+}
+
+bool
+store_exit_local(ExitMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ struct eventlog *evlog = closure->evlog;
+ int flags = 0;
+ debug_decl(store_exit_local, SUDO_DEBUG_UTIL);
+
+ if (msg->run_time != NULL) {
+ evlog->run_time.tv_sec = (time_t)msg->run_time->tv_sec;
+ evlog->run_time.tv_nsec = (long)msg->run_time->tv_nsec;
+ }
+ evlog->exit_value = msg->exit_value;
+ if (msg->signal != NULL && msg->signal[0] != '\0') {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "command was killed by SIG%s%s", msg->signal,
+ msg->dumped_core ? " (core dumped)" : "");
+ evlog->signal_name = strdup(msg->signal);
+ if (evlog->signal_name == NULL) {
+ closure->errstr = _("unable to allocate memory");
+ debug_return_bool(false);
+ }
+ evlog->dumped_core = msg->dumped_core;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "command exited with %d", msg->exit_value);
+ }
+ if (logsrvd_conf_log_exit()) {
+ if (!eventlog_exit(closure->evlog, flags)) {
+ closure->errstr = _("error logging exit event");
+ debug_return_bool(false);
+ }
+ }
+
+ if (closure->log_io) {
+ mode_t mode;
+
+ /* Store the run time and exit status in log.json. */
+ if (!store_exit_info_json(closure->iolog_dir_fd, evlog)) {
+ closure->errstr = _("error logging exit event");
+ debug_return_bool(false);
+ }
+
+ /* Clear write bits from I/O timing file to indicate completion. */
+ mode = logsrvd_conf_iolog_mode();
+ CLR(mode, S_IWUSR|S_IWGRP|S_IWOTH);
+ if (fchmodat(closure->iolog_dir_fd, "timing", mode, 0) == -1) {
+ sudo_warn("chmod 0%o %s/%s", (unsigned int)mode, "timing",
+ logsrvd_conf_iolog_dir());
+ }
+ }
+
+ debug_return_bool(true);
+}
+
+bool
+store_restart_local(RestartMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ struct timespec target;
+ struct stat sb;
+ int iofd;
+ debug_decl(store_restart_local, SUDO_DEBUG_UTIL);
+
+ target.tv_sec = (time_t)msg->resume_point->tv_sec;
+ target.tv_nsec = (long)msg->resume_point->tv_nsec;
+
+ /* We must allocate closure->evlog for iolog_path. */
+ closure->evlog = calloc(1, sizeof(*closure->evlog));
+ if (closure->evlog == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ closure->errstr = _("unable to allocate memory");
+ goto bad;
+ }
+ closure->evlog->iolog_path = strdup(msg->log_id);
+ if (closure->evlog->iolog_path == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ closure->errstr = _("unable to allocate memory");
+ goto bad;
+ }
+
+ /* We use iolog_dir_fd in calls to openat(2) */
+ closure->iolog_dir_fd =
+ iolog_openat(AT_FDCWD, closure->evlog->iolog_path, O_RDONLY);
+ if (closure->iolog_dir_fd == -1) {
+ sudo_warn("%s", closure->evlog->iolog_path);
+ goto bad;
+ }
+
+ /* If the timing file write bit is clear, log is already complete. */
+ if (fstatat(closure->iolog_dir_fd, "timing", &sb, 0) == -1) {
+ sudo_warn("%s/timing", closure->evlog->iolog_path);
+ goto bad;
+ }
+ if (!ISSET(sb.st_mode, S_IWUSR)) {
+ sudo_warn(U_("%s: %s"), closure->evlog->iolog_path,
+ U_("log is already complete, cannot be restarted"));
+ closure->errstr = _("log is already complete, cannot be restarted");
+ goto bad;
+ }
+
+ /* Open existing I/O log files. */
+ if (!iolog_open_all(closure->iolog_dir_fd, closure->evlog->iolog_path,
+ closure->iolog_files, "r+"))
+ goto bad;
+
+ /* Compressed logs don't support random access, so rewrite them. */
+ for (iofd = 0; iofd < IOFD_MAX; iofd++) {
+ if (closure->iolog_files[iofd].compressed)
+ debug_return_bool(iolog_rewrite(&target, closure));
+ }
+
+ /* Parse timing file until we reach the target point. */
+ if (!iolog_seekto(closure->iolog_dir_fd, closure->evlog->iolog_path,
+ closure->iolog_files, &closure->elapsed_time, &target))
+ goto bad;
+
+ /* Must seek or flush before switching from read -> write. */
+ if (iolog_seek(&closure->iolog_files[IOFD_TIMING], 0, SEEK_CUR) == -1) {
+ sudo_warn("%s/timing", closure->evlog->iolog_path);
+ goto bad;
+ }
+
+ /* Ready to log I/O buffers. */
+ debug_return_bool(true);
+bad:
+ if (closure->errstr == NULL)
+ closure->errstr = _("unable to restart log");
+ debug_return_bool(false);
+}
+
+bool
+store_alert_local(AlertMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ struct eventlog *evlog = NULL;
+ struct timespec alert_time;
+ bool ret = false;
+ debug_decl(store_alert_local, SUDO_DEBUG_UTIL);
+
+ if (msg->info_msgs != NULL && msg->n_info_msgs != 0) {
+ evlog = evlog_new(NULL, msg->info_msgs, msg->n_info_msgs, closure);
+ if (evlog == NULL) {
+ closure->errstr = _("error parsing AlertMessage");
+ goto done;
+ }
+ if (closure->evlog == NULL)
+ closure->evlog = evlog;
+ }
+ alert_time.tv_sec = (time_t)msg->alert_time->tv_sec;
+ alert_time.tv_nsec = (long)msg->alert_time->tv_nsec;
+
+ if (!eventlog_alert(evlog, 0, &alert_time, msg->reason, NULL)) {
+ closure->errstr = _("error logging alert event");
+ goto done;
+ }
+
+ ret = true;
+
+done:
+ if (closure->evlog != evlog)
+ eventlog_free(evlog);
+
+ debug_return_bool(ret);
+}
+
+bool
+store_iobuf_local(int iofd, IoBuffer *iobuf, uint8_t *buf, size_t buflen,
+ struct connection_closure *closure)
+{
+ const struct eventlog *evlog = closure->evlog;
+ struct ProtobufCBinaryData data = iobuf->data;
+ char tbuf[1024], *newbuf = NULL;
+ const char *errstr;
+ int len;
+ debug_decl(store_iobuf_local, SUDO_DEBUG_UTIL);
+
+ /* Open log file as needed. */
+ if (!closure->iolog_files[iofd].enabled) {
+ if (!iolog_create(iofd, closure))
+ goto bad;
+ }
+
+ /* Format timing data. */
+ /* FIXME - assumes IOFD_* matches IO_EVENT_* */
+ len = snprintf(tbuf, sizeof(tbuf), "%d %lld.%09d %zu\n",
+ iofd, (long long)iobuf->delay->tv_sec, (int)iobuf->delay->tv_nsec,
+ data.len);
+ if (len < 0 || len >= ssizeof(tbuf)) {
+ sudo_warnx(U_("unable to format timing buffer, length %d"), len);
+ goto bad;
+ }
+
+ if (!logsrvd_conf_iolog_log_passwords()) {
+ if (!iolog_pwfilt_run(logsrvd_conf_iolog_passprompt_regex(), iofd,
+ (char *)data.data, data.len, &newbuf))
+ goto bad;
+ if (newbuf != NULL)
+ data.data = (uint8_t *)newbuf;
+ }
+
+ /* Write to specified I/O log file. */
+ if (!iolog_write(&closure->iolog_files[iofd], data.data, data.len, &errstr)) {
+ sudo_warnx(U_("%s/%s: %s"), evlog->iolog_path, iolog_fd_to_name(iofd),
+ errstr);
+ goto bad;
+ }
+
+ /* Write timing data. */
+ if (!iolog_write(&closure->iolog_files[IOFD_TIMING], tbuf,
+ (size_t)len, &errstr)) {
+ sudo_warnx(U_("%s/%s: %s"), evlog->iolog_path,
+ iolog_fd_to_name(IOFD_TIMING), errstr);
+ goto bad;
+ }
+
+ update_elapsed_time(iobuf->delay, &closure->elapsed_time);
+
+ /* Random drop is a debugging tool to test client restart. */
+ if (random_drop > 0.0) {
+ double randval = arc4random() / (double)UINT32_MAX;
+ if (randval < random_drop) {
+ closure->errstr = _("randomly dropping connection");
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "randomly dropping connection (%f < %f)", randval, random_drop);
+ goto bad;
+ }
+ }
+
+ free(newbuf);
+ debug_return_bool(true);
+bad:
+ free(newbuf);
+ if (closure->errstr == NULL)
+ closure->errstr = _("error writing IoBuffer");
+ debug_return_bool(false);
+}
+
+bool
+store_winsize_local(ChangeWindowSize *msg, uint8_t *buf, size_t buflen,
+ struct connection_closure *closure)
+{
+ const char *errstr;
+ char tbuf[1024];
+ int len;
+ debug_decl(store_winsize_local, SUDO_DEBUG_UTIL);
+
+ /* Format timing data including new window size. */
+ len = snprintf(tbuf, sizeof(tbuf), "%d %lld.%09d %d %d\n", IO_EVENT_WINSIZE,
+ (long long)msg->delay->tv_sec, (int)msg->delay->tv_nsec,
+ msg->rows, msg->cols);
+ if (len < 0 || len >= ssizeof(tbuf)) {
+ sudo_warnx(U_("unable to format timing buffer, length %d"), len);
+ goto bad;
+ }
+
+ /* Write timing data. */
+ if (!iolog_write(&closure->iolog_files[IOFD_TIMING], tbuf,
+ (size_t)len, &errstr)) {
+ sudo_warnx(U_("%s/%s: %s"), closure->evlog->iolog_path,
+ iolog_fd_to_name(IOFD_TIMING), errstr);
+ goto bad;
+ }
+
+ update_elapsed_time(msg->delay, &closure->elapsed_time);
+
+ debug_return_bool(true);
+bad:
+ if (closure->errstr == NULL)
+ closure->errstr = _("error writing ChangeWindowSize");
+ debug_return_bool(false);
+}
+
+bool
+store_suspend_local(CommandSuspend *msg, uint8_t *buf, size_t buflen,
+ struct connection_closure *closure)
+{
+ const char *errstr;
+ char tbuf[1024];
+ int len;
+ debug_decl(store_suspend_local, SUDO_DEBUG_UTIL);
+
+ /* Format timing data including suspend signal. */
+ len = snprintf(tbuf, sizeof(tbuf), "%d %lld.%09d %s\n", IO_EVENT_SUSPEND,
+ (long long)msg->delay->tv_sec, (int)msg->delay->tv_nsec,
+ msg->signal);
+ if (len < 0 || len >= ssizeof(tbuf)) {
+ sudo_warnx(U_("unable to format timing buffer, length %d"), len);
+ goto bad;
+ }
+
+ /* Write timing data. */
+ if (!iolog_write(&closure->iolog_files[IOFD_TIMING], tbuf,
+ (size_t)len, &errstr)) {
+ sudo_warnx(U_("%s/%s: %s"), closure->evlog->iolog_path,
+ iolog_fd_to_name(IOFD_TIMING), errstr);
+ goto bad;
+ }
+
+ update_elapsed_time(msg->delay, &closure->elapsed_time);
+
+ debug_return_bool(true);
+bad:
+ if (closure->errstr == NULL)
+ closure->errstr = _("error writing CommandSuspend");
+ debug_return_bool(false);
+}
+
+struct client_message_switch cms_local = {
+ store_accept_local,
+ store_reject_local,
+ store_exit_local,
+ store_restart_local,
+ store_alert_local,
+ store_iobuf_local,
+ store_suspend_local,
+ store_winsize_local
+};
diff --git a/logsrvd/logsrvd_queue.c b/logsrvd/logsrvd_queue.c
new file mode 100644
index 0000000..cf48656
--- /dev/null
+++ b/logsrvd/logsrvd_queue.c
@@ -0,0 +1,287 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_conf.h>
+#include <sudo_debug.h>
+#include <sudo_event.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_iolog.h>
+#include <sudo_queue.h>
+#include <sudo_util.h>
+
+#include <logsrvd.h>
+
+#if defined(HAVE_STRUCT_DIRENT_D_NAMLEN) && HAVE_STRUCT_DIRENT_D_NAMLEN
+# define NAMLEN(dirent) (dirent)->d_namlen
+#else
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#endif
+
+static struct outgoing_journal_queue outgoing_journal_queue =
+ TAILQ_HEAD_INITIALIZER(outgoing_journal_queue);
+
+static struct sudo_event *outgoing_queue_event;
+
+/*
+ * Callback that runs when the outgoing queue retry timer fires.
+ * Tries to relay the first entry in the outgoing queue.
+ */
+static void
+outgoing_queue_cb(int unused, int what, void *v)
+{
+ struct connection_closure *closure;
+ struct outgoing_journal *oj, *next;
+ struct sudo_event_base *evbase = v;
+ bool success = false;
+ debug_decl(outgoing_queue_cb, SUDO_DEBUG_UTIL);
+
+ /* Must have at least one relay server. */
+ if (TAILQ_EMPTY(logsrvd_conf_relay_address()))
+ debug_return;
+
+ /* Process first journal. */
+ TAILQ_FOREACH_SAFE(oj, &outgoing_journal_queue, entries, next) {
+ FILE *fp;
+ int fd;
+
+ fd = open(oj->journal_path, O_RDWR);
+ if (fd == -1) {
+ if (errno == ENOENT) {
+ TAILQ_REMOVE(&outgoing_journal_queue, oj, entries);
+ free(oj->journal_path);
+ free(oj);
+ }
+ continue;
+ }
+ if (!sudo_lock_file(fd, SUDO_TLOCK)) {
+ sudo_warn(U_("unable to lock %s"), oj->journal_path);
+ close(fd);
+ continue;
+ }
+ fp = fdopen(fd, "r");
+ if (fp == NULL) {
+ sudo_warn(U_("unable to open %s"), oj->journal_path);
+ close(fd);
+ break;
+ }
+
+ /* Allocate a connection closure and fill in journal vars. */
+ closure = connection_closure_alloc(fd, false, true, evbase);
+ if (closure == NULL) {
+ fclose(fp);
+ break;
+ }
+ closure->journal = fp;
+ closure->journal_path = oj->journal_path;
+
+ /* Done with oj now, closure owns journal_path. */
+ TAILQ_REMOVE(&outgoing_journal_queue, oj, entries);
+ free(oj);
+
+ success = connect_relay(closure);
+ if (!success) {
+ sudo_warnx("%s", U_("unable to connect to relay"));
+ connection_close(closure);
+ }
+ break;
+ }
+}
+
+/*
+ * Schedule the outgoing_queue_event, creating it as necessary.
+ * The event will fire after the specified timeout elapses.
+ */
+bool
+logsrvd_queue_enable(time_t timeout, struct sudo_event_base *evbase)
+{
+ debug_decl(logsrvd_queue_enable, SUDO_DEBUG_UTIL);
+
+ if (!TAILQ_EMPTY(&outgoing_journal_queue)) {
+ struct timespec tv = { timeout, 0 };
+
+ if (outgoing_queue_event == NULL) {
+ outgoing_queue_event = sudo_ev_alloc(-1, SUDO_EV_TIMEOUT,
+ outgoing_queue_cb, evbase);
+ if (outgoing_queue_event == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ }
+ if (sudo_ev_add(evbase, outgoing_queue_event, &tv, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ debug_return_bool(false);
+ }
+ }
+ debug_return_bool(true);
+}
+
+/*
+ * Allocate a queue item based on the connection and push it on
+ * the outgoing queue.
+ * Consumes journal_path from the closure.
+ */
+bool
+logsrvd_queue_insert(struct connection_closure *closure)
+{
+ struct outgoing_journal *oj;
+ debug_decl(logsrvd_queue_insert, SUDO_DEBUG_UTIL);
+
+ if (closure->journal_path == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "missing journal_path for closure %p", closure);
+ debug_return_bool(false);
+ }
+
+ if ((oj = malloc(sizeof(*oj))) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ oj->journal_path = closure->journal_path;
+ closure->journal_path = NULL;
+ TAILQ_INSERT_TAIL(&outgoing_journal_queue, oj, entries);
+
+ if (!logsrvd_queue_enable(logsrvd_conf_relay_retry_interval(),
+ closure->evbase))
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+/*
+ * Scan the outgoing queue at startup and populate the
+ * outgoing_journal_queue.
+ */
+bool
+logsrvd_queue_scan(struct sudo_event_base *evbase)
+{
+ char path[PATH_MAX];
+ struct dirent *dent;
+ size_t prefix_len;
+ int dirlen;
+ DIR *dirp;
+ debug_decl(logsrvd_queue_scan, SUDO_DEBUG_UTIL);
+
+ /* Must have at least one relay server. */
+ if (TAILQ_EMPTY(logsrvd_conf_relay_address()))
+ debug_return_bool(true);
+
+ dirlen = snprintf(path, sizeof(path), "%s/outgoing/%s",
+ logsrvd_conf_relay_dir(), RELAY_TEMPLATE);
+ if (dirlen >= ssizeof(path)) {
+ errno = ENAMETOOLONG;
+ sudo_warn("%s/outgoing/%s", logsrvd_conf_relay_dir(), RELAY_TEMPLATE);
+ debug_return_bool(false);
+ }
+ dirlen -= (int)sizeof(RELAY_TEMPLATE) - 1;
+ path[dirlen] = '\0';
+
+ dirp = opendir(path);
+ if (dirp == NULL) {
+ sudo_warn("opendir %s", path);
+ debug_return_bool(false);
+ }
+ prefix_len = strcspn(RELAY_TEMPLATE, "X");
+ while ((dent = readdir(dirp)) != NULL) {
+ struct outgoing_journal *oj;
+
+ /* Skip anything that is not a relay temp file. */
+ if (NAMLEN(dent) != sizeof(RELAY_TEMPLATE) - 1)
+ continue;
+ if (strncmp(dent->d_name, RELAY_TEMPLATE, prefix_len) != 0)
+ continue;
+
+ /* Add to queue. */
+ path[dirlen] = '\0';
+ if (strlcat(path, dent->d_name, sizeof(path)) >= sizeof(path))
+ continue;
+ if ((oj = malloc(sizeof(*oj))) == NULL)
+ goto oom;
+ if ((oj->journal_path = strdup(path)) == NULL) {
+ free(oj);
+ goto oom;
+ }
+ TAILQ_INSERT_TAIL(&outgoing_journal_queue, oj, entries);
+ }
+ closedir(dirp);
+
+ /* Process the queue immediately. */
+ if (!logsrvd_queue_enable(0, evbase))
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ closedir(dirp);
+ debug_return_bool(false);
+}
+
+/*
+ * Dump outgoing queue in response to SIGUSR1.
+ */
+void
+logsrvd_queue_dump(void)
+{
+ struct outgoing_journal *oj;
+ debug_decl(logsrvd_queue_dump, SUDO_DEBUG_UTIL);
+
+ if (TAILQ_EMPTY(&outgoing_journal_queue))
+ debug_return;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "outgoing journal queue:");
+ TAILQ_FOREACH(oj, &outgoing_journal_queue, entries) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, " %s", oj->journal_path);
+ }
+}
diff --git a/logsrvd/logsrvd_relay.c b/logsrvd/logsrvd_relay.c
new file mode 100644
index 0000000..5ee01b1
--- /dev/null
+++ b/logsrvd/logsrvd_relay.c
@@ -0,0 +1,1261 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#define NEED_INET_NTOP /* to expose sudo_inet_ntop in sudo_compat.h */
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_event.h>
+#include <sudo_eventlog.h>
+#include <sudo_gettext.h>
+#include <sudo_iolog.h>
+#include <sudo_fatal.h>
+#include <sudo_queue.h>
+#include <sudo_util.h>
+
+#include <logsrvd.h>
+
+static void relay_client_msg_cb(int fd, int what, void *v);
+static void relay_server_msg_cb(int fd, int what, void *v);
+static void connect_cb(int sock, int what, void *v);
+static bool start_relay(int sock, struct connection_closure *closure);
+
+/*
+ * Free a struct relay_closure container and its contents.
+ */
+void
+relay_closure_free(struct relay_closure *relay_closure)
+{
+ struct connection_buffer *buf;
+ debug_decl(relay_closure_free, SUDO_DEBUG_UTIL);
+
+#if defined(HAVE_OPENSSL)
+ if (relay_closure->tls_client.ssl != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "closing down TLS connection to %s",
+ relay_closure->relay_name.name);
+ if (SSL_shutdown(relay_closure->tls_client.ssl) == 0)
+ SSL_shutdown(relay_closure->tls_client.ssl);
+ SSL_free(relay_closure->tls_client.ssl);
+ }
+#endif
+ if (relay_closure->relays != NULL)
+ address_list_delref(relay_closure->relays);
+ sudo_rcstr_delref(relay_closure->relay_name.name);
+ sudo_ev_free(relay_closure->read_ev);
+ sudo_ev_free(relay_closure->write_ev);
+ sudo_ev_free(relay_closure->connect_ev);
+ free(relay_closure->read_buf.data);
+ while ((buf = TAILQ_FIRST(&relay_closure->write_bufs)) != NULL) {
+ TAILQ_REMOVE(&relay_closure->write_bufs, buf, entries);
+ free(buf->data);
+ free(buf);
+ }
+ if (relay_closure->sock != -1) {
+ shutdown(relay_closure->sock, SHUT_RDWR);
+ close(relay_closure->sock);
+ }
+ free(relay_closure);
+
+ debug_return;
+}
+
+/*
+ * Allocate a relay closure.
+ * Note that allocation of the events is deferred until we know the socket.
+ */
+static struct relay_closure *
+relay_closure_alloc(void)
+{
+ struct relay_closure *relay_closure;
+ debug_decl(relay_closure_alloc, SUDO_DEBUG_UTIL);
+
+ if ((relay_closure = calloc(1, sizeof(*relay_closure))) == NULL)
+ debug_return_ptr(NULL);
+
+ /* We take a reference to relays so it doesn't change while connecting. */
+ relay_closure->sock = -1;
+ relay_closure->relays = logsrvd_conf_relay_address();
+ address_list_addref(relay_closure->relays);
+ TAILQ_INIT(&relay_closure->write_bufs);
+
+ relay_closure->read_buf.size = 8 * 1024;
+ relay_closure->read_buf.data = malloc(relay_closure->read_buf.size);
+ if (relay_closure->read_buf.data == NULL)
+ goto bad;
+
+ debug_return_ptr(relay_closure);
+bad:
+ relay_closure_free(relay_closure);
+ debug_return_ptr(NULL);
+}
+
+/*
+ * Allocate a new buffer, copy buf to it and insert on the write queue.
+ * On success the relay write event is enabled.
+ * The length parameter does not include space for the message's wire size.
+ */
+static bool
+relay_enqueue_write(uint8_t *msgbuf, size_t len,
+ struct connection_closure *closure)
+{
+ struct relay_closure *relay_closure = closure->relay_closure;
+ struct connection_buffer *buf;
+ uint32_t msg_len;
+ bool ret = false;
+ debug_decl(relay_enqueue_write, SUDO_DEBUG_UTIL);
+
+ /* Wire message size is used for length encoding, precedes message. */
+ msg_len = htonl((uint32_t)len);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "size + client message %zu bytes", len);
+
+ if ((buf = get_free_buf(sizeof(msg_len) + len, closure)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate connection_buffer");
+ goto done;
+ }
+ memcpy(buf->data, &msg_len, sizeof(msg_len));
+ memcpy(buf->data + sizeof(msg_len), msgbuf, len);
+ buf->len = sizeof(msg_len) + len;
+
+ if (sudo_ev_add(closure->evbase, relay_closure->write_ev, NULL, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto done;
+ }
+
+ TAILQ_INSERT_TAIL(&relay_closure->write_bufs, buf, entries);
+ buf = NULL;
+
+ ret = true;
+
+done:
+ if (buf != NULL) {
+ free(buf->data);
+ free(buf);
+ }
+ debug_return_bool(ret);
+}
+
+/*
+ * Format a ClientMessage and store the wire format message in buf.
+ * Returns true on success, false on failure.
+ */
+static bool
+fmt_client_message(struct connection_closure *closure, ClientMessage *msg)
+{
+ struct relay_closure *relay_closure = closure->relay_closure;
+ struct connection_buffer *buf = NULL;
+ uint32_t msg_len;
+ bool ret = false;
+ size_t len;
+ debug_decl(fmt_client_message, SUDO_DEBUG_UTIL);
+
+ len = client_message__get_packed_size(msg);
+ if (len > MESSAGE_SIZE_MAX) {
+ sudo_warnx(U_("client message too large: %zu"), len);
+ goto done;
+ }
+
+ /* Wire message size is used for length encoding, precedes message. */
+ msg_len = htonl((uint32_t)len);
+ len += sizeof(msg_len);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "size + client message %zu bytes", len);
+
+ if ((buf = get_free_buf(len, closure)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate connection_buffer");
+ goto done;
+ }
+ memcpy(buf->data, &msg_len, sizeof(msg_len));
+ client_message__pack(msg, buf->data + sizeof(msg_len));
+ buf->len = len;
+ TAILQ_INSERT_TAIL(&relay_closure->write_bufs, buf, entries);
+
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+static bool
+fmt_client_hello(struct connection_closure *closure)
+{
+ struct relay_closure *relay_closure = closure->relay_closure;
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ ClientHello hello_msg = CLIENT_HELLO__INIT;
+ bool ret;
+ debug_decl(fmt_client_hello, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: sending ClientHello", __func__);
+ hello_msg.client_id = (char *)"Sudo Logsrvd " PACKAGE_VERSION;
+
+ client_msg.u.hello_msg = &hello_msg;
+ client_msg.type_case = CLIENT_MESSAGE__TYPE_HELLO_MSG;
+ ret = fmt_client_message(closure, &client_msg);
+ if (ret) {
+ if (sudo_ev_add(closure->evbase, relay_closure->read_ev, NULL, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ ret = false;
+ }
+ if (sudo_ev_add(closure->evbase, relay_closure->write_ev, NULL, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ ret = false;
+ }
+ }
+
+ debug_return_bool(ret);
+}
+
+#if defined(HAVE_OPENSSL)
+/* Wrapper for start_relay() called via tls_connect_cb() */
+static bool
+tls_client_start_fn(struct tls_client_closure *tls_client)
+{
+ sudo_ev_free(tls_client->tls_connect_ev);
+ tls_client->tls_connect_ev = NULL;
+ return start_relay(SSL_get_fd(tls_client->ssl), tls_client->parent_closure);
+}
+
+/* Perform TLS connection to the relay host. */
+static bool
+connect_relay_tls(struct connection_closure *closure)
+{
+ struct tls_client_closure *tls_client = &closure->relay_closure->tls_client;
+ SSL_CTX *ssl_ctx = logsrvd_relay_tls_ctx();
+ debug_decl(connect_relay_tls, SUDO_DEBUG_UTIL);
+
+ /* Populate struct tls_client_closure. */
+ tls_client->parent_closure = closure;
+ tls_client->evbase = closure->evbase;
+ tls_client->tls_connect_ev = sudo_ev_alloc(closure->relay_closure->sock,
+ SUDO_EV_WRITE, tls_connect_cb, tls_client);
+ if (tls_client->tls_connect_ev == NULL)
+ goto bad;
+ tls_client->peer_name = &closure->relay_closure->relay_name;
+ tls_client->connect_timeout = *logsrvd_conf_relay_connect_timeout();
+ tls_client->start_fn = tls_client_start_fn;
+ if (!tls_ctx_client_setup(ssl_ctx, closure->relay_closure->sock, tls_client))
+ goto bad;
+
+ debug_return_bool(true);
+bad:
+ debug_return_bool(false);
+}
+#endif /* HAVE_OPENSSL */
+
+/*
+ * Try to connect to the next relay host.
+ * Returns 0 on success, -1 on error, setting errno.
+ * If there is no next relay, errno is set to ENOENT.
+ */
+static int
+connect_relay_next(struct connection_closure *closure)
+{
+ struct relay_closure *relay_closure = closure->relay_closure;
+ struct server_address *relay;
+ int ret, sock = -1;
+ char *addr;
+ debug_decl(connect_relay_next, SUDO_DEBUG_UTIL);
+
+ /* Get next relay or return ENOENT none are left. */
+ if (relay_closure->relay_addr != NULL) {
+ relay = TAILQ_NEXT(relay_closure->relay_addr, entries);
+ } else {
+ relay = TAILQ_FIRST(relay_closure->relays);
+ }
+ if (relay == NULL) {
+ errno = ENOENT;
+ goto bad;
+ }
+ relay_closure->relay_addr = relay;
+
+ sock = socket(relay->sa_un.sa.sa_family, SOCK_STREAM, 0);
+ if (sock == -1) {
+ sudo_warn("socket");
+ goto bad;
+ }
+ if (logsrvd_conf_relay_tcp_keepalive()) {
+ int keepalive = 1;
+ if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
+ sizeof(keepalive)) == -1) {
+ sudo_warn("SO_KEEPALIVE");
+ }
+ }
+ ret = fcntl(sock, F_GETFL, 0);
+ if (ret == -1 || fcntl(sock, F_SETFL, ret | O_NONBLOCK) == -1) {
+ sudo_warn("fcntl(O_NONBLOCK)");
+ goto bad;
+ }
+
+ ret = connect(sock, &relay->sa_un.sa, relay->sa_size);
+ if (ret == -1 && errno != EINPROGRESS)
+ goto bad;
+
+ switch (relay->sa_un.sa.sa_family) {
+ case AF_INET:
+ addr = (char *)&relay->sa_un.sin.sin_addr;
+ break;
+#ifdef HAVE_STRUCT_IN6_ADDR
+ case AF_INET6:
+ addr = (char *)&relay->sa_un.sin6.sin6_addr;
+ break;
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ sudo_warn("connect");
+ goto bad;
+ }
+ inet_ntop(relay->sa_un.sa.sa_family, addr,
+ relay_closure->relay_name.ipaddr,
+ sizeof(relay_closure->relay_name.ipaddr));
+ relay_closure->relay_name.name = sudo_rcstr_addref(relay->sa_host);
+
+ if (ret == 0) {
+ if (relay_closure->sock != -1) {
+ shutdown(relay_closure->sock, SHUT_RDWR);
+ close(relay_closure->sock);
+ }
+ relay_closure->sock = sock;
+#if defined(HAVE_OPENSSL)
+ /* Relay connection succeeded, start TLS handshake. */
+ if (relay_closure->relay_addr->tls) {
+ if (!connect_relay_tls(closure))
+ goto bad;
+ } else
+#endif
+ {
+ /* Connection succeeded without blocking. */
+ if (!start_relay(sock, closure))
+ goto bad;
+ }
+ } else {
+ /* Connection will be completed in connect_cb(). */
+ relay_closure->connect_ev = sudo_ev_alloc(sock, SUDO_EV_WRITE,
+ connect_cb, closure);
+ if (relay_closure->connect_ev == NULL)
+ goto bad;
+ if (sudo_ev_add(closure->evbase, relay_closure->connect_ev,
+ logsrvd_conf_relay_connect_timeout(), false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto bad;
+ }
+ if (relay_closure->sock != -1) {
+ shutdown(relay_closure->sock, SHUT_RDWR);
+ close(relay_closure->sock);
+ }
+ relay_closure->sock = sock;
+ closure->state = CONNECTING;
+ }
+ debug_return_int(ret);
+
+bad:
+ /* Connection or system error. */
+ if (sock != -1) {
+ shutdown(sock, SHUT_RDWR);
+ close(sock);
+ }
+ sudo_rcstr_delref(relay_closure->relay_name.name);
+ relay_closure->relay_name.name = NULL;
+ sudo_ev_free(relay_closure->connect_ev);
+ relay_closure->connect_ev = NULL;
+ debug_return_int(-1);
+}
+
+static void
+connect_cb(int sock, int what, void *v)
+{
+ struct connection_closure *closure = v;
+ struct relay_closure *relay_closure = closure->relay_closure;
+ int errnum, optval, ret;
+ socklen_t optlen = sizeof(optval);
+ debug_decl(connect_cb, SUDO_DEBUG_UTIL);
+
+ if (what == SUDO_EV_TIMEOUT) {
+ errnum = ETIMEDOUT;
+ } else {
+ ret = getsockopt(sock, SOL_SOCKET, SO_ERROR, &optval, &optlen);
+ errnum = ret == 0 ? optval : errno;
+ }
+ if (errnum == 0) {
+ closure->state = INITIAL;
+#if defined(HAVE_OPENSSL)
+ /* Relay connection succeeded, start TLS handshake. */
+ if (relay_closure->relay_addr->tls) {
+ if (!connect_relay_tls(closure)) {
+ closure->errstr = _("TLS handshake with relay host failed");
+ if (!schedule_error_message(closure->errstr, closure))
+ connection_close(closure);
+ }
+ } else
+#endif
+ {
+ /* Relay connection succeeded, start talking to the client. */
+ if (!start_relay(sock, closure)) {
+ closure->errstr = _("unable to allocate memory");
+ if (!schedule_error_message(closure->errstr, closure))
+ connection_close(closure);
+ }
+ }
+ } else {
+ /* Connection failed, try next relay (if any). */
+ int res;
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "unable to connect to relay %s (%s): %s",
+ relay_closure->relay_name.name, relay_closure->relay_name.ipaddr,
+ strerror(errnum));
+ while ((res = connect_relay_next(closure)) == -1) {
+ if (errno == ENOENT || errno == EINPROGRESS) {
+ /* Out of relays or connecting asynchronously. */
+ break;
+ }
+ }
+ if (res == -1 && errno != EINPROGRESS) {
+ closure->errstr = _("unable to connect to relay host");
+ if (!schedule_error_message(closure->errstr, closure))
+ connection_close(closure);
+ }
+ }
+
+ debug_return;
+}
+
+/* Connect to the first available relay host. */
+bool
+connect_relay(struct connection_closure *closure)
+{
+ struct relay_closure *relay_closure;
+ int res;
+ debug_decl(connect_relay, SUDO_DEBUG_UTIL);
+
+ relay_closure = closure->relay_closure = relay_closure_alloc();
+ if (relay_closure == NULL)
+ debug_return_bool(false);
+
+ while ((res = connect_relay_next(closure)) == -1) {
+ if (errno == ENOENT || errno == EINPROGRESS) {
+ /* Out of relays or connecting asynchronously. */
+ break;
+ }
+ }
+
+ if (res == -1 && errno != EINPROGRESS)
+ debug_return_bool(false);
+
+ /* Switch to relay client message handlers. */
+ closure->cms = &cms_relay;
+ debug_return_bool(true);
+}
+
+/*
+ * Respond to a ServerHello message from the relay.
+ * Returns true on success, false on error.
+ */
+static bool
+handle_server_hello(ServerHello *msg, struct connection_closure *closure)
+{
+ struct relay_closure *relay_closure = closure->relay_closure;
+ debug_decl(handle_server_hello, SUDO_DEBUG_UTIL);
+
+ if (closure->state != INITIAL) {
+ sudo_warnx(U_("unexpected state %d for %s"), closure->state,
+ relay_closure->relay_name.ipaddr);
+ closure->errstr = _("state machine error");
+ debug_return_bool(false);
+ }
+
+ /* Check that ServerHello is valid. */
+ if (msg->server_id == NULL || msg->server_id[0] == '\0') {
+ sudo_warnx(U_("%s: invalid ServerHello, missing server_id"),
+ relay_closure->relay_name.ipaddr);
+ closure->errstr = _("invalid ServerHello");
+ debug_return_bool(false);
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "relay server %s (%s) ID %s", relay_closure->relay_name.name,
+ relay_closure->relay_name.ipaddr, msg->server_id);
+
+ /* TODO: handle redirect */
+
+ debug_return_bool(true);
+}
+
+/*
+ * Respond to a CommitPoint message from the relay.
+ * Returns true on success, false on error.
+ */
+static bool
+handle_commit_point(TimeSpec *commit_point, struct connection_closure *closure)
+{
+ debug_decl(handle_commit_point, SUDO_DEBUG_UTIL);
+
+ if (closure->state < RUNNING) {
+ sudo_warnx(U_("unexpected state %d for %s"), closure->state,
+ closure->relay_closure->relay_name.ipaddr);
+ closure->errstr = _("state machine error");
+ debug_return_bool(false);
+ }
+
+ /* Pass commit point from relay to client. */
+ debug_return_bool(schedule_commit_point(commit_point, closure));
+}
+
+/*
+ * Respond to a LogId message from the relay.
+ * Always returns true.
+ */
+static bool
+handle_log_id(char *id, struct connection_closure *closure)
+{
+ char *new_id;
+ bool ret = false;
+ int len;
+ debug_decl(handle_log_id, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "log ID %s from relay %s (%s)", id,
+ closure->relay_closure->relay_name.name,
+ closure->relay_closure->relay_name.ipaddr);
+
+ /* No client connection when replaying a journaled entry. */
+ if (closure->write_ev == NULL)
+ debug_return_bool(true);
+
+ /* Generate a new log ID that includes the relay host. */
+ len = asprintf(&new_id, "%s/%s", id,
+ closure->relay_closure->relay_name.name);
+ if (len != -1) {
+ if (fmt_log_id_message(id, closure)) {
+ if (sudo_ev_add(closure->evbase, closure->write_ev,
+ logsrvd_conf_relay_timeout(), false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ } else {
+ ret = true;
+ }
+ }
+ free(new_id);
+ }
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Respond to a ServerError message from the relay.
+ * Always returns false.
+ */
+static bool
+handle_server_error(char *errmsg, struct connection_closure *closure)
+{
+ struct relay_closure *relay_closure = closure->relay_closure;
+ debug_decl(handle_server_error, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "error message received from relay %s (%s): %s",
+ relay_closure->relay_name.name, relay_closure->relay_name.ipaddr,
+ errmsg);
+
+ /* Server will drop connection after the error message. */
+ sudo_ev_del(closure->evbase, closure->relay_closure->read_ev);
+ sudo_ev_del(closure->evbase, closure->relay_closure->write_ev);
+
+ if (!schedule_error_message(errmsg, closure))
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+/*
+ * Respond to a ServerAbort message from the server.
+ * Always returns false.
+ */
+static bool
+handle_server_abort(char *errmsg, struct connection_closure *closure)
+{
+ struct relay_closure *relay_closure = closure->relay_closure;
+ debug_decl(handle_server_abort, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "abort message received from relay %s (%s): %s",
+ relay_closure->relay_name.name, relay_closure->relay_name.ipaddr,
+ errmsg);
+
+ if (!schedule_error_message(errmsg, closure))
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+/*
+ * Respond to a ServerMessage from the relay.
+ * Returns true on success, false on error.
+ */
+static bool
+handle_server_message(uint8_t *buf, size_t len, struct connection_closure *closure)
+{
+ ServerMessage *msg;
+ bool ret = false;
+ debug_decl(handle_server_message, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: unpacking ServerMessage", __func__);
+ msg = server_message__unpack(NULL, len, buf);
+ if (msg == NULL) {
+ sudo_warnx(U_("unable to unpack %s size %zu"), "ServerMessage", len);
+ debug_return_bool(false);
+ }
+
+ switch (msg->type_case) {
+ case SERVER_MESSAGE__TYPE_HELLO:
+ if ((ret = handle_server_hello(msg->u.hello, closure))) {
+ /* Relay server said hello, start talking to client. */
+ ret = start_protocol(closure);
+ }
+ break;
+ case SERVER_MESSAGE__TYPE_COMMIT_POINT:
+ ret = handle_commit_point(msg->u.commit_point, closure);
+ break;
+ case SERVER_MESSAGE__TYPE_LOG_ID:
+ ret = handle_log_id(msg->u.log_id, closure);
+ break;
+ case SERVER_MESSAGE__TYPE_ERROR:
+ ret = handle_server_error(msg->u.error, closure);
+ break;
+ case SERVER_MESSAGE__TYPE_ABORT:
+ ret = handle_server_abort(msg->u.abort, closure);
+ break;
+ default:
+ sudo_warnx(U_("unexpected type_case value %d in %s from %s"),
+ msg->type_case, "ServerMessage",
+ closure->relay_closure->relay_name.ipaddr);
+ closure->errstr = _("unrecognized ServerMessage type");
+ break;
+ }
+
+ server_message__free_unpacked(msg, NULL);
+ debug_return_bool(ret);
+}
+
+/*
+ * Read and unpack a ServerMessage from the relay (read callback).
+ */
+static void
+relay_server_msg_cb(int fd, int what, void *v)
+{
+ struct connection_closure *closure = v;
+ struct relay_closure *relay_closure = closure->relay_closure;
+ struct connection_buffer *buf = &relay_closure->read_buf;
+ size_t nread;
+ uint32_t msg_len;
+ debug_decl(relay_server_msg_cb, SUDO_DEBUG_UTIL);
+
+ /* For TLS we may need to read as part of SSL_write_ex(). */
+ if (relay_closure->write_instead_of_read) {
+ relay_closure->write_instead_of_read = false;
+ relay_client_msg_cb(fd, what, v);
+ debug_return;
+ }
+
+ if (what == SUDO_EV_TIMEOUT) {
+ sudo_warnx(U_("timed out reading from relay %s (%s)"),
+ relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
+ closure->errstr = _("timeout reading from relay");
+ goto send_error;
+ }
+
+#if defined(HAVE_OPENSSL)
+ if (relay_closure->tls_client.ssl != NULL) {
+ SSL *ssl = relay_closure->tls_client.ssl;
+ int result;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: ServerMessage from relay %s (%s) [TLS]", __func__,
+ relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
+ result = SSL_read_ex(ssl, buf->data + buf->len, buf->size - buf->len,
+ &nread);
+ if (result <= 0) {
+ unsigned long errcode;
+ const char *errstr;
+
+ switch (SSL_get_error(ssl, result)) {
+ case SSL_ERROR_ZERO_RETURN:
+ /* ssl connection shutdown cleanly */
+ nread = 0;
+ break;
+ case SSL_ERROR_WANT_READ:
+ /* ssl wants to read more, read event is always active */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_read_ex returns SSL_ERROR_WANT_READ");
+ debug_return;
+ case SSL_ERROR_WANT_WRITE:
+ /* ssl wants to write, schedule a write if not pending */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_read_ex returns SSL_ERROR_WANT_WRITE");
+ if (!sudo_ev_pending(relay_closure->write_ev, SUDO_EV_WRITE, NULL)) {
+ /* Enable a temporary write event. */
+ if (sudo_ev_add(closure->evbase, relay_closure->write_ev, NULL, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ closure->errstr = _("unable to allocate memory");
+ goto send_error;
+ }
+ relay_closure->temporary_write_event = true;
+ }
+ /* Redirect write event to finish SSL_read_ex() */
+ relay_closure->read_instead_of_write = true;
+ debug_return;
+ case SSL_ERROR_SSL:
+ /*
+ * For TLS 1.3, if the cert verify function on the server
+ * returns an error, OpenSSL will send an internal error
+ * alert when we read ServerHello. Convert to a more useful
+ * message and hope that no actual internal error occurs.
+ */
+ errcode = ERR_get_error();
+#if !defined(HAVE_WOLFSSL)
+ if (closure->state == INITIAL &&
+ ERR_GET_REASON(errcode) == SSL_R_TLSV1_ALERT_INTERNAL_ERROR) {
+ errstr = _("relay host name does not match certificate");
+ closure->errstr = errstr;
+ } else
+#endif
+ {
+ errstr = ERR_reason_error_string(errcode);
+ closure->errstr = _("error reading from relay");
+ }
+ sudo_warnx("%s: SSL_read_ex: %s",
+ relay_closure->relay_name.ipaddr,
+ errstr ? errstr : strerror(errno));
+ goto send_error;
+ case SSL_ERROR_SYSCALL:
+ if (nread == 0) {
+ /* EOF, handled below */
+ sudo_warnx(U_("EOF from %s without proper TLS shutdown"),
+ relay_closure->relay_name.ipaddr);
+ break;
+ }
+ sudo_warn("%s: SSL_read_ex", relay_closure->relay_name.ipaddr);
+ closure->errstr = _("error reading from relay");
+ goto send_error;
+ default:
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx("%s: SSL_read_ex: %s",
+ relay_closure->relay_name.ipaddr,
+ errstr ? errstr : strerror(errno));
+ closure->errstr = _("error reading from relay");
+ goto send_error;
+ }
+ }
+ } else
+#endif
+ {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: ServerMessage from relay %s (%s)", __func__,
+ relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
+ nread = (size_t)read(fd, buf->data + buf->len, buf->size - buf->len);
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: received %zd bytes from relay %s (%s)", __func__, nread,
+ relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
+ switch (nread) {
+ case (size_t)-1:
+ if (errno == EAGAIN || errno == EINTR)
+ debug_return;
+ sudo_warn("%s: read", relay_closure->relay_name.ipaddr);
+ closure->errstr = _("unable to read from relay");
+ goto send_error;
+ case 0:
+ /* EOF from relay server, close the socket. */
+ shutdown(relay_closure->sock, SHUT_RDWR);
+ close(relay_closure->sock);
+ relay_closure->sock = -1;
+ sudo_ev_del(closure->evbase, relay_closure->read_ev);
+ sudo_ev_del(closure->evbase, relay_closure->write_ev);
+
+ if (closure->state != FINISHED) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "premature EOF from %s (%s) [state %d]",
+ relay_closure->relay_name.name,
+ relay_closure->relay_name.ipaddr, closure->state);
+ closure->errstr = _("relay server closed connection");
+ goto send_error;
+ }
+ if (closure->sock == -1)
+ connection_close(closure);
+ debug_return;
+ default:
+ break;
+ }
+ buf->len += nread;
+
+ while (buf->len - buf->off >= sizeof(msg_len)) {
+ /* Read wire message size (uint32_t in network byte order). */
+ memcpy(&msg_len, buf->data + buf->off, sizeof(msg_len));
+ msg_len = ntohl(msg_len);
+
+ if (msg_len > MESSAGE_SIZE_MAX) {
+ sudo_warnx(U_("server message too large: %zu"), (size_t)msg_len);
+ closure->errstr = _("server message too large");
+ goto send_error;
+ }
+
+ if (msg_len + sizeof(msg_len) > buf->len - buf->off) {
+ /* Incomplete message, we'll read the rest next time. */
+ if (!expand_buf(buf, msg_len + sizeof(msg_len))) {
+ closure->errstr = _("unable to allocate memory");
+ goto send_error;
+ }
+ debug_return;
+ }
+
+ /* Parse ServerMessage (could be zero bytes). */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: parsing ServerMessage, size %u", __func__, msg_len);
+ buf->off += sizeof(msg_len);
+ if (!handle_server_message(buf->data + buf->off, msg_len, closure))
+ goto send_error;
+ buf->off += msg_len;
+ }
+ buf->len -= buf->off;
+ buf->off = 0;
+ debug_return;
+
+send_error:
+ /*
+ * Try to send client an error message before closing connection.
+ * If we are already in an error state, just give up.
+ */
+ if (!schedule_error_message(closure->errstr, closure))
+ goto close_connection;
+ debug_return;
+
+close_connection:
+ connection_close(closure);
+ debug_return;
+}
+
+/*
+ * Forward a ClientMessage to the relay (write callback).
+ */
+static void
+relay_client_msg_cb(int fd, int what, void *v)
+{
+ struct connection_closure *closure = v;
+ struct relay_closure *relay_closure = closure->relay_closure;
+ struct connection_buffer *buf;
+ size_t nwritten;
+ debug_decl(relay_client_msg_cb, SUDO_DEBUG_UTIL);
+
+ /* For TLS we may need to write as part of SSL_read_ex(). */
+ if (relay_closure->read_instead_of_write) {
+ relay_closure->read_instead_of_write = false;
+ /* Delete write event if it was only due to SSL_read_ex(). */
+ if (relay_closure->temporary_write_event) {
+ relay_closure->temporary_write_event = false;
+ sudo_ev_del(closure->evbase, relay_closure->write_ev);
+ }
+ relay_server_msg_cb(fd, what, v);
+ debug_return;
+ }
+
+ if (what == SUDO_EV_TIMEOUT) {
+ sudo_warnx(U_("timed out writing to relay %s (%s)"),
+ relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
+ closure->errstr = _("timeout writing to relay");
+ goto send_error;
+ }
+
+ if ((buf = TAILQ_FIRST(&relay_closure->write_bufs)) == NULL) {
+ sudo_warnx(U_("missing write buffer for client %s"),
+ relay_closure->relay_name.ipaddr);
+ goto close_connection;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: sending %zu bytes to server %s (%s)",
+ __func__, buf->len - buf->off, relay_closure->relay_name.name,
+ relay_closure->relay_name.ipaddr);
+
+#if defined(HAVE_OPENSSL)
+ if (relay_closure->tls_client.ssl != NULL) {
+ SSL *ssl = relay_closure->tls_client.ssl;
+ const int result = SSL_write_ex(ssl, buf->data + buf->off,
+ buf->len - buf->off, &nwritten);
+ if (result <= 0) {
+ const char *errstr;
+
+ switch (SSL_get_error(ssl, result)) {
+ case SSL_ERROR_ZERO_RETURN:
+ /* ssl connection shutdown cleanly */
+ shutdown(relay_closure->sock, SHUT_RDWR);
+ close(relay_closure->sock);
+ relay_closure->sock = -1;
+ sudo_ev_del(closure->evbase, relay_closure->read_ev);
+ sudo_ev_del(closure->evbase, relay_closure->write_ev);
+
+ if (closure->state != FINISHED) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "premature EOF from %s (state %d)",
+ relay_closure->relay_name.ipaddr, closure->state);
+ closure->errstr = _("relay server closed connection");
+ goto send_error;
+ }
+ debug_return;
+ case SSL_ERROR_WANT_READ:
+ /* ssl wants to read, read event always active */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_write_ex returns SSL_ERROR_WANT_READ");
+ /* Redirect read event to finish SSL_write_ex() */
+ relay_closure->write_instead_of_read = true;
+ debug_return;
+ case SSL_ERROR_WANT_WRITE:
+ /* ssl wants to write more, write event remains active */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_write_ex returns SSL_ERROR_WANT_WRITE");
+ debug_return;
+ case SSL_ERROR_SYSCALL:
+ sudo_warn("%s: SSL_write_ex",
+ relay_closure->relay_name.ipaddr);
+ closure->errstr = _("error writing to relay");
+ goto send_error;
+ default:
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx("%s: SSL_write_ex: %s",
+ relay_closure->relay_name.ipaddr,
+ errstr ? errstr : strerror(errno));
+ closure->errstr = _("error writing to relay");
+ goto send_error;
+ }
+ }
+ } else
+#endif
+ {
+ nwritten = (size_t)write(fd, buf->data + buf->off, buf->len - buf->off);
+ if (nwritten == (size_t)-1) {
+ if (errno == EAGAIN || errno == EINTR)
+ debug_return;
+ sudo_warn("%s: write", relay_closure->relay_name.ipaddr);
+ closure->errstr = _("error writing to relay");
+ goto send_error;
+ }
+ }
+ buf->off += nwritten;
+
+ if (buf->off == buf->len) {
+ /* sent entire message, move buf to free list */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: finished sending %zu bytes to server", __func__, buf->len);
+ buf->off = 0;
+ buf->len = 0;
+ TAILQ_REMOVE(&relay_closure->write_bufs, buf, entries);
+ TAILQ_INSERT_TAIL(&closure->free_bufs, buf, entries);
+ if (TAILQ_EMPTY(&relay_closure->write_bufs))
+ sudo_ev_del(closure->evbase, relay_closure->write_ev);
+ }
+ debug_return;
+
+send_error:
+ /*
+ * Try to send client an error message before closing connection.
+ * If we are already in an error state, just give up.
+ */
+ if (!schedule_error_message(closure->errstr, closure))
+ goto close_connection;
+ debug_return;
+
+close_connection:
+ connection_close(closure);
+ debug_return;
+}
+
+/* Begin the conversation with the relay host. */
+static bool
+start_relay(int sock, struct connection_closure *closure)
+{
+ struct relay_closure *relay_closure = closure->relay_closure;
+ debug_decl(start_relay, SUDO_DEBUG_UTIL);
+
+ /* No longer need the connect event. */
+ sudo_ev_free(relay_closure->connect_ev);
+ relay_closure->connect_ev = NULL;
+
+ /* Allocate relay read/write events now that we know the socket. */
+ relay_closure->read_ev = sudo_ev_alloc(sock, SUDO_EV_READ|SUDO_EV_PERSIST,
+ relay_server_msg_cb, closure);
+ relay_closure->write_ev = sudo_ev_alloc(sock, SUDO_EV_WRITE|SUDO_EV_PERSIST,
+ relay_client_msg_cb, closure);
+ if (relay_closure->read_ev == NULL || relay_closure->write_ev == NULL)
+ debug_return_bool(false);
+
+ /* Start communication with the relay server by saying hello. */
+ debug_return_bool(fmt_client_hello(closure));
+}
+
+/*
+ * Relay an AcceptMessage from the client to the relay server.
+ */
+static bool
+relay_accept(AcceptMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ struct relay_closure *relay_closure = closure->relay_closure;
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ debug_decl(relay_accept, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: relaying AcceptMessage from %s to %s (%s)", __func__, source,
+ relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
+
+ debug_return_bool(relay_enqueue_write(buf, len, closure));
+}
+
+/*
+ * Relay a RejectMessage from the client to the relay server.
+ */
+static bool
+relay_reject(RejectMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ struct relay_closure *relay_closure = closure->relay_closure;
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ debug_decl(relay_reject, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: relaying RejectMessage from %s to %s (%s)", __func__, source,
+ relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
+
+ debug_return_bool(relay_enqueue_write(buf, len, closure));
+}
+
+/*
+ * Relay an ExitMessage from the client to the relay server.
+ */
+static bool
+relay_exit(ExitMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ struct relay_closure *relay_closure = closure->relay_closure;
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ debug_decl(relay_exit, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: relaying ExitMessage from %s to %s (%s)", __func__, source,
+ relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
+
+ debug_return_bool(relay_enqueue_write(buf, len, closure));
+}
+
+/*
+ * Relay a RestartMessage from the client to the relay server.
+ * We must rebuild the packed message because the log_id is modified.
+ */
+static bool
+relay_restart(RestartMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ struct relay_closure *relay_closure = closure->relay_closure;
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ struct sudo_event_base *evbase = closure->evbase;
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ RestartMessage restart_msg = *msg;
+ char *cp;
+ bool ret;
+ debug_decl(relay_restart, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: relaying RestartMessage from %s to %s (%s)", __func__, source,
+ relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
+
+ /*
+ * We prepend "relayhost/" to the log ID before relaying it to
+ * the client. Perform the reverse operation before passing the
+ * log ID to the relay host.
+ */
+ if ((cp = strchr(restart_msg.log_id, '/')) != NULL) {
+ if (cp != restart_msg.log_id)
+ restart_msg.log_id = cp + 1;
+ }
+
+ client_msg.u.restart_msg = &restart_msg;
+ client_msg.type_case = CLIENT_MESSAGE__TYPE_RESTART_MSG;
+ ret = fmt_client_message(closure, &client_msg);
+ if (ret) {
+ if (sudo_ev_add(evbase, relay_closure->write_ev, NULL, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ ret = false;
+ }
+ }
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Relay an AlertMessage from the client to the relay server.
+ */
+static bool
+relay_alert(AlertMessage *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ struct relay_closure *relay_closure = closure->relay_closure;
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ bool ret;
+ debug_decl(relay_alert, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: relaying AlertMessage from %s to %s (%s)", __func__, source,
+ relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
+
+ ret = relay_enqueue_write(buf, len, closure);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Relay a CommandSuspend from the client to the relay server.
+ */
+static bool
+relay_suspend(CommandSuspend *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ struct relay_closure *relay_closure = closure->relay_closure;
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ bool ret;
+ debug_decl(relay_suspend, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: relaying CommandSuspend from %s to %s (%s)", __func__, source,
+ relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
+
+ ret = relay_enqueue_write(buf, len, closure);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Relay a ChangeWindowSize from the client to the relay server.
+ */
+static bool
+relay_winsize(ChangeWindowSize *msg, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ struct relay_closure *relay_closure = closure->relay_closure;
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ bool ret;
+ debug_decl(relay_winsize, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: relaying ChangeWindowSize from %s to %s (%s)", __func__, source,
+ relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
+
+ ret = relay_enqueue_write(buf, len, closure);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Relay an IoBuffer from the client to the relay server.
+ */
+static bool
+relay_iobuf(int iofd, IoBuffer *iobuf, uint8_t *buf, size_t len,
+ struct connection_closure *closure)
+{
+ struct relay_closure *relay_closure = closure->relay_closure;
+ const char *source = closure->journal_path ? closure->journal_path :
+ closure->ipaddr;
+ bool ret;
+ debug_decl(relay_iobuf, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: relaying IoBuffer from %s to %s (%s)", __func__, source,
+ relay_closure->relay_name.name, relay_closure->relay_name.ipaddr);
+
+ ret = relay_enqueue_write(buf, len, closure);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Shutdown relay connection when server is exiting.
+ */
+bool
+relay_shutdown(struct connection_closure *closure)
+{
+ struct relay_closure *relay_closure = closure->relay_closure;
+ debug_decl(relay_shutdown, SUDO_DEBUG_UTIL);
+
+ /* Close connection unless relay events are pending. */
+ if (!sudo_ev_pending(relay_closure->read_ev, SUDO_EV_READ, NULL) &&
+ !sudo_ev_pending(relay_closure->write_ev, SUDO_EV_WRITE, NULL) &&
+ TAILQ_EMPTY(&relay_closure->write_bufs)) {
+ connection_close(closure);
+ }
+
+ debug_return_bool(true);
+}
+
+struct client_message_switch cms_relay = {
+ relay_accept,
+ relay_reject,
+ relay_exit,
+ relay_restart,
+ relay_alert,
+ relay_iobuf,
+ relay_suspend,
+ relay_winsize
+};
diff --git a/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.1 b/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.1
new file mode 100644
index 0000000..5fd7d3f
--- /dev/null
+++ b/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.1
@@ -0,0 +1,253 @@
+#
+# sudo logsrv daemon configuration
+#
+
+[server]
+# The host name or IP address and port to listen on with an optional TLS
+# flag. If no port is specified, port 30343 will be used for plaintext
+# connections and port 30344 will be used to TLS connections.
+# The following forms are accepted:
+# listen_address = hostname(tls)
+# listen_address = hostname:port(tls)
+# listen_address = IPv4_address(tls)
+# listen_address = IPv4_address:port(tls)
+# listen_address = [IPv6_address](tls)
+# listen_address = [IPv6_address]:port(tls)
+#
+# The (tls) suffix should be omitted for plaintext connections.
+#
+# Multiple listen_address settings may be specified.
+# The default is to listen on all addresses.
+#listen_address = *:30343
+#listen_address = *:30344(tls)
+
+# The file containing the ID of the running sudo_logsrvd process.
+#pid_file = /var/run/sudo/sudo_logsrvd.pid
+
+# Where to log server warnings: none, stderr, syslog, or a path name.
+#server_log = syslog
+
+# If true, enable the SO_KEEPALIVE socket option on client connections.
+# Defaults to true.
+#tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the client to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+#timeout = 30
+
+# If true, the server will validate its own certificate at startup.
+# Defaults to true.
+#tls_verify = true
+
+# If true, client certificates will be validated by the server;
+# clients without a valid certificate will be unable to connect.
+# By default, client certs are not checked.
+#tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+#tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# Required for TLS connections.
+#tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# Required for TLS connections.
+#tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# NOTE that this setting is only effective if the negotiated protocol
+# is TLS version 1.2.
+# The default cipher list is HIGH:!aNULL.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default cipher list is TLS_AES_256_GCM_SHA384.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# If not set, the server will use the OpenSSL defaults.
+#tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[relay]
+# The host name or IP address and port to send logs to in relay mode.
+# The syntax is identical to listen_address with the exception of
+# the wild card ('*') syntax. When this setting is enabled, logs will
+# be relayed to the specified host instead of being stored locally.
+# This setting is not enabled by default.
+#relay_host = relayhost.dom.ain
+#relay_host = relayhost.dom.ain(tls)
+
+# The amount of time, in seconds, the server will wait for a connection
+# to the relay server to complete. A value of 0 will disable the timeout.
+# The default value is 30.
+#connect_timeout = 30
+
+# The directory to store messages in before they are sent to the relay.
+# Messages are stored in wire format.
+# The default value is /var/log/sudo_logsrvd.
+#relay_dir = /var/log/sudo_logsrvd
+
+# The number of seconds to wait after a connection error before
+# making a new attempt to forward a message to a relay host.
+# The default value is 30.
+#retry_interval = 30
+
+# Whether to store the log before relaying it. If true, enable store
+# and forward mode. If false, the client connection is immediately
+# relayed. Defaults to false.
+#store_first = true
+
+# If true, enable the SO_KEEPALIVE socket option on relay connections.
+# Defaults to true.
+#tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the relay to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+#timeout = 30
+
+# If true, the server's relay certificate will be verified at startup.
+# The default is to use the value in the [server] section.
+#tls_verify = true
+
+# Whether to verify the relay's certificate for TLS connections.
+# The default is to use the value in the [server] section.
+#tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+# The default is to use the value in the [server] section.
+#tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# The default is to use the certificate in the [server] section.
+#tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# The default is to use the key in the [server] section.
+#tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# NOTE that this setting is only effective if the negotiated protocol
+# is TLS version 1.2.
+# The default is to use the value in the [server] section.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default is to use the value in the [server] section.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# The default is to use the value in the [server] section.
+#tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[iolog]
+# The top-level directory to use when constructing the path name for the
+# I/O log directory. The session sequence number, if any, is stored here.
+#iolog_dir = /var/log/sudo-io
+
+# The path name, relative to iolog_dir, in which to store I/O logs.
+# Note that iolog_file may contain directory components.
+#iolog_file = %{seq}
+
+# If set, I/O logs will be compressed using zlib. Enabling compression can
+# make it harder to view the logs in real-time as the program is executing.
+#iolog_compress = false
+
+# If set, I/O log data is flushed to disk after each write instead of
+# buffering it. This makes it possible to view the logs in real-time
+# as the program is executing but reduces the effectiveness of compression.
+#iolog_flush = true
+
+# The group to use when creating new I/O log files and directories.
+# If iolog_group is not set, the primary group-ID of the user specified
+# by iolog_user is used. If neither iolog_group nor iolog_user
+# are set, I/O log files and directories are created with group-ID 0.
+#iolog_group = wheel
+
+# The user to use when setting the user-ID and group-ID of new I/O
+# log files and directories. If iolog_group is set, it will be used
+# instead of the user's primary group-ID. By default, I/O log files
+# and directories are created with user and group-ID 0.
+#iolog_user = root
+
+# The file mode to use when creating I/O log files. The file permissions
+# will always include the owner read and write bits, even if they are
+# not present in the specified mode. When creating I/O log directories,
+# search (execute) bits are added to match the read and write bits
+# specified by iolog_mode.
+#iolog_mode = 0600
+
+# If disabled, sudo_logsrvd will attempt to avoid logging plaintext
+# password in the terminal input using passprompt_regex.
+#log_passwords = true
+
+# The maximum sequence number that will be substituted for the "%{seq}"
+# escape in the I/O log file. While the value substituted for "%{seq}"
+# is in base 36, maxseq itself should be expressed in decimal. Values
+# larger than 2176782336 (which corresponds to the base 36 sequence
+# number "ZZZZZZ") will be silently truncated to 2176782336.
+#maxseq = 2176782336
+
+# One or more POSIX extended regular expressions used to match
+# password prompts in the terminal output when log_passwords is
+# disabled. Multiple passprompt_regex settings may be specified.
+#passprompt_regex = [Pp]assword[: ]*
+#passprompt_regex = [Pp]assword for [a-z0-9]+: *
+
+[eventlog]
+# Where to log accept, reject, exit, and alert events.
+# Accepted values are syslog, logfile, or none.
+# Defaults to syslog
+#log_type = syslog
+
+# Whether to log an event when a command exits or is terminated by a signal.
+# Defaults to false
+#log_exit = true
+
+# Event log format.
+# Supported log formats are "sudo" and "json"
+# Defaults to sudo
+#log_format = sudo
+
+[syslog]
+# The maximum length of a syslog payload.
+# On many systems, syslog(3) has a relatively small log buffer.
+# IETF RFC 5424 states that syslog servers must support messages
+# of at least 480 bytes and should support messages up to 2048 bytes.
+# Messages larger than this value will be split into multiple messages.
+#maxlen = 960
+
+# The syslog facility to use for event log messages.
+# The following syslog facilities are supported: authpriv (if your OS
+# supports it), auth, daemon, user, local0, local1, local2, local3,
+# local4, local5, local6, and local7.
+#facility = authpriv
+
+# Syslog priority to use for event log accept messages, when the command
+# is allowed by the security policy. The following syslog priorities are
+# supported: alert, crit, debug, emerg, err, info, notice, warning, none.
+#accept_priority = notice
+
+# Syslog priority to use for event log reject messages, when the command
+# is not allowed by the security policy.
+#reject_priority = alert
+
+# Syslog priority to use for event log alert messages reported by the
+# client.
+#alert_priority = alert
+
+# The syslog facility to use for server warning messages.
+# Defaults to daemon.
+#server_facility = daemon
+
+[logfile]
+# The path to the file-based event log.
+# This path must be fully-qualified and start with a '/' character.
+#path = /var/log/sudo
+
+# The format string used when formatting the date and time for
+# file-based event logs. Formatting is performed via strftime(3) so
+# any format string supported by that function is allowed.
+#time_format = %h %e %T
diff --git a/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.2 b/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.2
new file mode 100644
index 0000000..a860082
--- /dev/null
+++ b/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.2
@@ -0,0 +1,255 @@
+#
+# sudo logsrv daemon configuration
+#
+
+[server]
+# The host name or IP address and port to listen on with an optional TLS
+# flag. If no port is specified, port 30343 will be used for plaintext
+# connections and port 30344 will be used to TLS connections.
+# The following forms are accepted:
+# listen_address = hostname(tls)
+# listen_address = hostname:port(tls)
+# listen_address = IPv4_address(tls)
+# listen_address = IPv4_address:port(tls)
+# listen_address = [IPv6_address](tls)
+# listen_address = [IPv6_address]:port(tls)
+#
+# The (tls) suffix should be omitted for plaintext connections.
+#
+# Multiple listen_address settings may be specified.
+# The default is to listen on all addresses.
+#listen_address = *:30343
+listen_address = *:30344(tls)
+
+# The file containing the ID of the running sudo_logsrvd process.
+pid_file = /var/run/sudo/sudo_logsrvd.pid
+
+# Where to log server warnings: none, stderr, syslog, or a path name.
+server_log = syslog
+
+# If true, enable the SO_KEEPALIVE socket option on client connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the client to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server will validate its own certificate at startup.
+# Defaults to true.
+tls_verify = true
+
+# If true, client certificates will be validated by the server;
+# clients without a valid certificate will be unable to connect.
+# By default, client certs are not checked.
+tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# Required for TLS connections.
+tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# Required for TLS connections.
+tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# NOTE that this setting is only effective if the negotiated protocol
+# is TLS version 1.2.
+# The default cipher list is HIGH:!aNULL.
+tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default cipher list is TLS_AES_256_GCM_SHA384.
+tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# If not set, the server will use the OpenSSL defaults.
+tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[relay]
+# The host name or IP address and port to send logs to in relay mode.
+# The syntax is identical to listen_address with the exception of
+# the wild card ('*') syntax. When this setting is enabled, logs will
+# be relayed to the specified host instead of being stored locally.
+# This setting is not enabled by default.
+#relay_host = relayhost.dom.ain
+#relay_host = relayhost.dom.ain(tls)
+relay_host = localhost(tls)
+
+# The amount of time, in seconds, the server will wait for a connection
+# to the relay server to complete. A value of 0 will disable the timeout.
+# The default value is 30.
+connect_timeout = 30
+
+# The directory to store messages in before they are sent to the relay.
+# Messages are stored in wire format.
+# The default value is /var/log/sudo_logsrvd.
+relay_dir = /var/log/sudo_logsrvd
+
+# The number of seconds to wait after a connection error before
+# making a new attempt to forward a message to a relay host.
+# The default value is 30.
+retry_interval = 30
+
+# Whether to store the log before relaying it. If true, enable store
+# and forward mode. If false, the client connection is immediately
+# relayed. Defaults to false.
+#store_first = true
+
+# If true, enable the SO_KEEPALIVE socket option on relay connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the relay to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server's relay certificate will be verified at startup.
+# The default is to use the value in the [server] section.
+#tls_verify = true
+
+# Whether to verify the relay's certificate for TLS connections.
+# The default is to use the value in the [server] section.
+#tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+# The default is to use the value in the [server] section.
+#tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# The default is to use the certificate in the [server] section.
+#tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# The default is to use the key in the [server] section.
+#tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# NOTE that this setting is only effective if the negotiated protocol
+# is TLS version 1.2.
+# The default is to use the value in the [server] section.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default is to use the value in the [server] section.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# The default is to use the value in the [server] section.
+#tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[iolog]
+# The top-level directory to use when constructing the path name for the
+# I/O log directory. The session sequence number, if any, is stored here.
+iolog_dir = /var/log/sudo-io
+
+# The path name, relative to iolog_dir, in which to store I/O logs.
+# Note that iolog_file may contain directory components.
+iolog_file = %{seq}
+
+# If set, I/O logs will be compressed using zlib. Enabling compression can
+# make it harder to view the logs in real-time as the program is executing.
+iolog_compress = false
+
+# If set, I/O log data is flushed to disk after each write instead of
+# buffering it. This makes it possible to view the logs in real-time
+# as the program is executing but reduces the effectiveness of compression.
+iolog_flush = true
+
+# The group to use when creating new I/O log files and directories.
+# If iolog_group is not set, the primary group-ID of the user specified
+# by iolog_user is used. If neither iolog_group nor iolog_user
+# are set, I/O log files and directories are created with group-ID 0.
+iolog_group = wheel
+
+# The user to use when setting the user-ID and group-ID of new I/O
+# log files and directories. If iolog_group is set, it will be used
+# instead of the user's primary group-ID. By default, I/O log files
+# and directories are created with user and group-ID 0.
+iolog_user = root
+
+# The file mode to use when creating I/O log files. The file permissions
+# will always include the owner read and write bits, even if they are
+# not present in the specified mode. When creating I/O log directories,
+# search (execute) bits are added to match the read and write bits
+# specified by iolog_mode.
+iolog_mode = 0600
+
+# If disabled, sudo_logsrvd will attempt to avoid logging plaintext
+# password in the terminal input using passprompt_regex.
+log_passwords = true
+
+# The maximum sequence number that will be substituted for the "%{seq}"
+# escape in the I/O log file. While the value substituted for "%{seq}"
+# is in base 36, maxseq itself should be expressed in decimal. Values
+# larger than 2176782336 (which corresponds to the base 36 sequence
+# number "ZZZZZZ") will be silently truncated to 2176782336.
+maxseq = 2176782336
+
+# One or more POSIX extended regular expressions used to match
+# password prompts in the terminal output when log_passwords is
+# disabled. Multiple passprompt_regex settings may be specified.
+#passprompt_regex = [Pp]assword[: ]*
+#passprompt_regex = [Pp]assword for [a-z0-9]+: *
+passprompt_regex = [Pp]assword[: ]*
+
+[eventlog]
+# Where to log accept, reject, exit, and alert events.
+# Accepted values are syslog, logfile, or none.
+# Defaults to syslog
+log_type = syslog
+
+# Whether to log an event when a command exits or is terminated by a signal.
+# Defaults to false
+log_exit = true
+
+# Event log format.
+# Supported log formats are "sudo" and "json"
+# Defaults to sudo
+log_format = sudo
+
+[syslog]
+# The maximum length of a syslog payload.
+# On many systems, syslog(3) has a relatively small log buffer.
+# IETF RFC 5424 states that syslog servers must support messages
+# of at least 480 bytes and should support messages up to 2048 bytes.
+# Messages larger than this value will be split into multiple messages.
+maxlen = 960
+
+# The syslog facility to use for event log messages.
+# The following syslog facilities are supported: authpriv (if your OS
+# supports it), auth, daemon, user, local0, local1, local2, local3,
+# local4, local5, local6, and local7.
+facility = authpriv
+
+# Syslog priority to use for event log accept messages, when the command
+# is allowed by the security policy. The following syslog priorities are
+# supported: alert, crit, debug, emerg, err, info, notice, warning, none.
+accept_priority = notice
+
+# Syslog priority to use for event log reject messages, when the command
+# is not allowed by the security policy.
+reject_priority = alert
+
+# Syslog priority to use for event log alert messages reported by the
+# client.
+alert_priority = alert
+
+# The syslog facility to use for server warning messages.
+# Defaults to daemon.
+server_facility = daemon
+
+[logfile]
+# The path to the file-based event log.
+# This path must be fully-qualified and start with a '/' character.
+path = /var/log/sudo
+
+# The format string used when formatting the date and time for
+# file-based event logs. Formatting is performed via strftime(3) so
+# any format string supported by that function is allowed.
+time_format = %h %e %T
diff --git a/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.3 b/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.3
new file mode 100644
index 0000000..b0fba8a
--- /dev/null
+++ b/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.3
@@ -0,0 +1,253 @@
+#
+# sudo logsrv daemon configuration
+#
+
+[server]
+# The host name or IP address and port to listen on with an optional TLS
+# flag. If no port is specified, port 30343 will be used for plaintext
+# connections and port 30344 will be used to TLS connections.
+# The following forms are accepted:
+# listen_address = hostname(tls)
+# listen_address = hostname:port(tls)
+# listen_address = IPv4_address(tls)
+# listen_address = IPv4_address:port(tls)
+# listen_address = [IPv6_address](tls)
+# listen_address = [IPv6_address]:port(tls)
+#
+# The (tls) suffix should be omitted for plaintext connections.
+#
+# Multiple listen_address settings may be specified.
+# The default is to listen on all addresses.
+listen_address = *:30343
+#listen_address = *:30344(tls)
+
+# The file containing the ID of the running sudo_logsrvd process.
+pid_file = /var/run/sudo/sudo_logsrvd.pid
+
+# Where to log server warnings: none, stderr, syslog, or a path name.
+#server_log = syslog
+
+# If true, enable the SO_KEEPALIVE socket option on client connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the client to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 0
+
+# If true, the server will validate its own certificate at startup.
+# Defaults to true.
+#tls_verify = true
+
+# If true, client certificates will be validated by the server;
+# clients without a valid certificate will be unable to connect.
+# By default, client certs are not checked.
+#tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+#tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# Required for TLS connections.
+#tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# Required for TLS connections.
+#tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# NOTE that this setting is only effective if the negotiated protocol
+# is TLS version 1.2.
+# The default cipher list is HIGH:!aNULL.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default cipher list is TLS_AES_256_GCM_SHA384.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# If not set, the server will use the OpenSSL defaults.
+#tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[relay]
+# The host name or IP address and port to send logs to in relay mode.
+# The syntax is identical to listen_address with the exception of
+# the wild card ('*') syntax. When this setting is enabled, logs will
+# be relayed to the specified host instead of being stored locally.
+# This setting is not enabled by default.
+#relay_host = relayhost.dom.ain
+#relay_host = relayhost.dom.ain(tls)
+
+# The amount of time, in seconds, the server will wait for a connection
+# to the relay server to complete. A value of 0 will disable the timeout.
+# The default value is 30.
+#connect_timeout = 30
+
+# The directory to store messages in before they are sent to the relay.
+# Messages are stored in wire format.
+# The default value is /var/log/sudo_logsrvd.
+#relay_dir = /var/log/sudo_logsrvd
+
+# The number of seconds to wait after a connection error before
+# making a new attempt to forward a message to a relay host.
+# The default value is 30.
+#retry_interval = 30
+
+# Whether to store the log before relaying it. If true, enable store
+# and forward mode. If false, the client connection is immediately
+# relayed. Defaults to false.
+#store_first = true
+
+# If true, enable the SO_KEEPALIVE socket option on relay connections.
+# Defaults to true.
+#tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the relay to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+#timeout = 30
+
+# If true, the server's relay certificate will be verified at startup.
+# The default is to use the value in the [server] section.
+#tls_verify = true
+
+# Whether to verify the relay's certificate for TLS connections.
+# The default is to use the value in the [server] section.
+#tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+# The default is to use the value in the [server] section.
+#tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# The default is to use the certificate in the [server] section.
+#tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# The default is to use the key in the [server] section.
+#tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# NOTE that this setting is only effective if the negotiated protocol
+# is TLS version 1.2.
+# The default is to use the value in the [server] section.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default is to use the value in the [server] section.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# The default is to use the value in the [server] section.
+#tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[iolog]
+# The top-level directory to use when constructing the path name for the
+# I/O log directory. The session sequence number, if any, is stored here.
+iolog_dir = /var/log/sudo-io/%{hostname}/%{user}
+
+# The path name, relative to iolog_dir, in which to store I/O logs.
+# Note that iolog_file may contain directory components.
+iolog_file = %{seq}
+
+# If set, I/O logs will be compressed using zlib. Enabling compression can
+# make it harder to view the logs in real-time as the program is executing.
+iolog_compress = true
+
+# If set, I/O log data is flushed to disk after each write instead of
+# buffering it. This makes it possible to view the logs in real-time
+# as the program is executing but reduces the effectiveness of compression.
+iolog_flush = false
+
+# The group to use when creating new I/O log files and directories.
+# If iolog_group is not set, the primary group-ID of the user specified
+# by iolog_user is used. If neither iolog_group nor iolog_user
+# are set, I/O log files and directories are created with group-ID 0.
+iolog_group = sudo
+
+# The user to use when setting the user-ID and group-ID of new I/O
+# log files and directories. If iolog_group is set, it will be used
+# instead of the user's primary group-ID. By default, I/O log files
+# and directories are created with user and group-ID 0.
+iolog_user = sudo
+
+# The file mode to use when creating I/O log files. The file permissions
+# will always include the owner read and write bits, even if they are
+# not present in the specified mode. When creating I/O log directories,
+# search (execute) bits are added to match the read and write bits
+# specified by iolog_mode.
+iolog_mode = 0640
+
+# If disabled, sudo_logsrvd will attempt to avoid logging plaintext
+# password in the terminal input using passprompt_regex.
+#log_passwords = true
+
+# The maximum sequence number that will be substituted for the "%{seq}"
+# escape in the I/O log file. While the value substituted for "%{seq}"
+# is in base 36, maxseq itself should be expressed in decimal. Values
+# larger than 2176782336 (which corresponds to the base 36 sequence
+# number "ZZZZZZ") will be silently truncated to 2176782336.
+maxseq = 999999999
+
+# One or more POSIX extended regular expressions used to match
+# password prompts in the terminal output when log_passwords is
+# disabled. Multiple passprompt_regex settings may be specified.
+#passprompt_regex = [Pp]assword[: ]*
+#passprompt_regex = [Pp]assword for [a-z0-9]+: *
+
+[eventlog]
+# Where to log accept, reject, exit, and alert events.
+# Accepted values are syslog, logfile, or none.
+# Defaults to syslog
+log_type = logfile
+
+# Whether to log an event when a command exits or is terminated by a signal.
+# Defaults to false
+log_exit = false
+
+# Event log format.
+# Supported log formats are "sudo" and "json"
+# Defaults to sudo
+log_format = json
+
+[syslog]
+# The maximum length of a syslog payload.
+# On many systems, syslog(3) has a relatively small log buffer.
+# IETF RFC 5424 states that syslog servers must support messages
+# of at least 480 bytes and should support messages up to 2048 bytes.
+# Messages larger than this value will be split into multiple messages.
+#maxlen = 960
+
+# The syslog facility to use for event log messages.
+# The following syslog facilities are supported: authpriv (if your OS
+# supports it), auth, daemon, user, local0, local1, local2, local3,
+# local4, local5, local6, and local7.
+#facility = authpriv
+
+# Syslog priority to use for event log accept messages, when the command
+# is allowed by the security policy. The following syslog priorities are
+# supported: alert, crit, debug, emerg, err, info, notice, warning, none.
+#accept_priority = notice
+
+# Syslog priority to use for event log reject messages, when the command
+# is not allowed by the security policy.
+#reject_priority = alert
+
+# Syslog priority to use for event log alert messages reported by the
+# client.
+#alert_priority = alert
+
+# The syslog facility to use for server warning messages.
+# Defaults to daemon.
+#server_facility = daemon
+
+[logfile]
+# The path to the file-based event log.
+# This path must be fully-qualified and start with a '/' character.
+path = /var/log/sudo.log
+
+# The format string used when formatting the date and time for
+# file-based event logs. Formatting is performed via strftime(3) so
+# any format string supported by that function is allowed.
+time_format = %a %b %e %H:%M:%S %Z
diff --git a/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.4 b/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.4
new file mode 100644
index 0000000..7d6ec4e
--- /dev/null
+++ b/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.4
@@ -0,0 +1,255 @@
+#
+# sudo logsrv daemon configuration
+#
+
+[server]
+# The host name or IP address and port to listen on with an optional TLS
+# flag. If no port is specified, port 30343 will be used for plaintext
+# connections and port 30344 will be used to TLS connections.
+# The following forms are accepted:
+# listen_address = hostname(tls)
+# listen_address = hostname:port(tls)
+# listen_address = IPv4_address(tls)
+# listen_address = IPv4_address:port(tls)
+# listen_address = [IPv6_address](tls)
+# listen_address = [IPv6_address]:port(tls)
+#
+# The (tls) suffix should be omitted for plaintext connections.
+#
+# Multiple listen_address settings may be specified.
+# The default is to listen on all addresses.
+#listen_address = *:30343
+listen_address = *:30344(tls)
+
+# The file containing the ID of the running sudo_logsrvd process.
+pid_file = /var/run/sudo/sudo_logsrvd.pid
+
+# Where to log server warnings: none, stderr, syslog, or a path name.
+server_log = syslog
+
+# If true, enable the SO_KEEPALIVE socket option on client connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the client to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server will validate its own certificate at startup.
+# Defaults to true.
+tls_verify = true
+
+# If true, client certificates will be validated by the server;
+# clients without a valid certificate will be unable to connect.
+# By default, client certs are not checked.
+tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# Required for TLS connections.
+tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# Required for TLS connections.
+tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# NOTE that this setting is only effective if the negotiated protocol
+# is TLS version 1.2.
+# The default cipher list is HIGH:!aNULL.
+tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default cipher list is TLS_AES_256_GCM_SHA384.
+tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# If not set, the server will use the OpenSSL defaults.
+tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[relay]
+# The host name or IP address and port to send logs to in relay mode.
+# The syntax is identical to listen_address with the exception of
+# the wild card ('*') syntax. When this setting is enabled, logs will
+# be relayed to the specified host instead of being stored locally.
+# This setting is not enabled by default.
+#relay_host = relayhost.dom.ain
+#relay_host = relayhost.dom.ain(tls)
+relay_host = localhost(tls)
+
+# The amount of time, in seconds, the server will wait for a connection
+# to the relay server to complete. A value of 0 will disable the timeout.
+# The default value is 30.
+connect_timeout = 30
+
+# The directory to store messages in before they are sent to the relay.
+# Messages are stored in wire format.
+# The default value is /var/log/sudo_logsrvd.
+relay_dir = /var/log/sudo_logsrvd
+
+# The number of seconds to wait after a connection error before
+# making a new attempt to forward a message to a relay host.
+# The default value is 30.
+retry_interval = 30
+
+# Whether to store the log before relaying it. If true, enable store
+# and forward mode. If false, the client connection is immediately
+# relayed. Defaults to false.
+#store_first = true
+
+# If true, enable the SO_KEEPALIVE socket option on relay connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the relay to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server's relay certificate will be verified at startup.
+# The default is to use the value in the [server] section.
+tls_verify = true
+
+# Whether to verify the relay's certificate for TLS connections.
+# The default is to use the value in the [server] section.
+tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+# The default is to use the value in the [server] section.
+tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# The default is to use the certificate in the [server] section.
+tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# The default is to use the key in the [server] section.
+tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# NOTE that this setting is only effective if the negotiated protocol
+# is TLS version 1.2.
+# The default is to use the value in the [server] section.
+tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default is to use the value in the [server] section.
+tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# The default is to use the value in the [server] section.
+tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[iolog]
+# The top-level directory to use when constructing the path name for the
+# I/O log directory. The session sequence number, if any, is stored here.
+iolog_dir = /var/log/sudo-io
+
+# The path name, relative to iolog_dir, in which to store I/O logs.
+# Note that iolog_file may contain directory components.
+iolog_file = %{seq}
+
+# If set, I/O logs will be compressed using zlib. Enabling compression can
+# make it harder to view the logs in real-time as the program is executing.
+iolog_compress = false
+
+# If set, I/O log data is flushed to disk after each write instead of
+# buffering it. This makes it possible to view the logs in real-time
+# as the program is executing but reduces the effectiveness of compression.
+iolog_flush = true
+
+# The group to use when creating new I/O log files and directories.
+# If iolog_group is not set, the primary group-ID of the user specified
+# by iolog_user is used. If neither iolog_group nor iolog_user
+# are set, I/O log files and directories are created with group-ID 0.
+#iolog_group = wheel
+
+# The user to use when setting the user-ID and group-ID of new I/O
+# log files and directories. If iolog_group is set, it will be used
+# instead of the user's primary group-ID. By default, I/O log files
+# and directories are created with user and group-ID 0.
+iolog_user = root
+
+# The file mode to use when creating I/O log files. The file permissions
+# will always include the owner read and write bits, even if they are
+# not present in the specified mode. When creating I/O log directories,
+# search (execute) bits are added to match the read and write bits
+# specified by iolog_mode.
+iolog_mode = 0600
+
+# If disabled, sudo_logsrvd will attempt to avoid logging plaintext
+# password in the terminal input using passprompt_regex.
+log_passwords = true
+
+# The maximum sequence number that will be substituted for the "%{seq}"
+# escape in the I/O log file. While the value substituted for "%{seq}"
+# is in base 36, maxseq itself should be expressed in decimal. Values
+# larger than 2176782336 (which corresponds to the base 36 sequence
+# number "ZZZZZZ") will be silently truncated to 2176782336.
+maxseq = 2176782336
+
+# One or more POSIX extended regular expressions used to match
+# password prompts in the terminal output when log_passwords is
+# disabled. Multiple passprompt_regex settings may be specified.
+#passprompt_regex = [Pp]assword[: ]*
+#passprompt_regex = [Pp]assword for [a-z0-9]+: *
+passprompt_regex = [Pp]assword[: ]*
+
+[eventlog]
+# Where to log accept, reject, exit, and alert events.
+# Accepted values are syslog, logfile, or none.
+# Defaults to syslog
+log_type = syslog
+
+# Whether to log an event when a command exits or is terminated by a signal.
+# Defaults to false
+log_exit = true
+
+# Event log format.
+# Supported log formats are "sudo" and "json"
+# Defaults to sudo
+log_format = sudo
+
+[syslog]
+# The maximum length of a syslog payload.
+# On many systems, syslog(3) has a relatively small log buffer.
+# IETF RFC 5424 states that syslog servers must support messages
+# of at least 480 bytes and should support messages up to 2048 bytes.
+# Messages larger than this value will be split into multiple messages.
+maxlen = 960
+
+# The syslog facility to use for event log messages.
+# The following syslog facilities are supported: authpriv (if your OS
+# supports it), auth, daemon, user, local0, local1, local2, local3,
+# local4, local5, local6, and local7.
+facility = unknown
+
+# Syslog priority to use for event log accept messages, when the command
+# is allowed by the security policy. The following syslog priorities are
+# supported: alert, crit, debug, emerg, err, info, notice, warning, none.
+accept_priority = notice
+
+# Syslog priority to use for event log reject messages, when the command
+# is not allowed by the security policy.
+reject_priority = alert
+
+# Syslog priority to use for event log alert messages reported by the
+# client.
+alert_priority = alert
+
+# The syslog facility to use for server warning messages.
+# Defaults to daemon.
+server_facility = daemon
+
+[logfile]
+# The path to the file-based event log.
+# This path must be fully-qualified and start with a '/' character.
+path = /var/log/sudo
+
+# The format string used when formatting the date and time for
+# file-based event logs. Formatting is performed via strftime(3) so
+# any format string supported by that function is allowed.
+time_format = %h %e %T
diff --git a/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.5 b/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.5
new file mode 100644
index 0000000..5a4019f
--- /dev/null
+++ b/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.5
@@ -0,0 +1,255 @@
+#
+# sudo logsrv daemon configuration
+#
+
+[server]
+# The host name or IP address and port to listen on with an optional TLS
+# flag. If no port is specified, port 30343 will be used for plaintext
+# connections and port 30344 will be used to TLS connections.
+# The following forms are accepted:
+# listen_address = hostname(tls)
+# listen_address = hostname:port(tls)
+# listen_address = IPv4_address(tls)
+# listen_address = IPv4_address:port(tls)
+# listen_address = [IPv6_address](tls)
+# listen_address = [IPv6_address]:port(tls)
+#
+# The (tls) suffix should be omitted for plaintext connections.
+#
+# Multiple listen_address settings may be specified.
+# The default is to listen on all addresses.
+#listen_address = *:30343
+listen_address = *:30344(tls)
+
+# The file containing the ID of the running sudo_logsrvd process.
+pid_file = /var/run/sudo/sudo_logsrvd.pid
+
+# Where to log server warnings: none, stderr, syslog, or a path name.
+server_log = syslog
+
+# If true, enable the SO_KEEPALIVE socket option on client connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the client to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server will validate its own certificate at startup.
+# Defaults to true.
+tls_verify = true
+
+# If true, client certificates will be validated by the server;
+# clients without a valid certificate will be unable to connect.
+# By default, client certs are not checked.
+tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# Required for TLS connections.
+tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# Required for TLS connections.
+tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# NOTE that this setting is only effective if the negotiated protocol
+# is TLS version 1.2.
+# The default cipher list is HIGH:!aNULL.
+tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default cipher list is TLS_AES_256_GCM_SHA384.
+tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# If not set, the server will use the OpenSSL defaults.
+tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[relay]
+# The host name or IP address and port to send logs to in relay mode.
+# The syntax is identical to listen_address with the exception of
+# the wild card ('*') syntax. When this setting is enabled, logs will
+# be relayed to the specified host instead of being stored locally.
+# This setting is not enabled by default.
+#relay_host = relayhost.dom.ain
+#relay_host = relayhost.dom.ain(tls)
+relay_host = localhost(tls)
+
+# The amount of time, in seconds, the server will wait for a connection
+# to the relay server to complete. A value of 0 will disable the timeout.
+# The default value is 30.
+connect_timeout = 30
+
+# The directory to store messages in before they are sent to the relay.
+# Messages are stored in wire format.
+# The default value is /var/log/sudo_logsrvd.
+relay_dir = /var/log/sudo_logsrvd
+
+# The number of seconds to wait after a connection error before
+# making a new attempt to forward a message to a relay host.
+# The default value is 30.
+retry_interval = 30
+
+# Whether to store the log before relaying it. If true, enable store
+# and forward mode. If false, the client connection is immediately
+# relayed. Defaults to false.
+#store_first = true
+
+# If true, enable the SO_KEEPALIVE socket option on relay connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the relay to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server's relay certificate will be verified at startup.
+# The default is to use the value in the [server] section.
+tls_verify = true
+
+# Whether to verify the relay's certificate for TLS connections.
+# The default is to use the value in the [server] section.
+tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+# The default is to use the value in the [server] section.
+tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# The default is to use the certificate in the [server] section.
+tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# The default is to use the key in the [server] section.
+tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# NOTE that this setting is only effective if the negotiated protocol
+# is TLS version 1.2.
+# The default is to use the value in the [server] section.
+tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default is to use the value in the [server] section.
+tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# The default is to use the value in the [server] section.
+tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[iolog]
+# The top-level directory to use when constructing the path name for the
+# I/O log directory. The session sequence number, if any, is stored here.
+iolog_dir = /var/log/sudo-io
+
+# The path name, relative to iolog_dir, in which to store I/O logs.
+# Note that iolog_file may contain directory components.
+iolog_file = %{seq}
+
+# If set, I/O logs will be compressed using zlib. Enabling compression can
+# make it harder to view the logs in real-time as the program is executing.
+iolog_compress = false
+
+# If set, I/O log data is flushed to disk after each write instead of
+# buffering it. This makes it possible to view the logs in real-time
+# as the program is executing but reduces the effectiveness of compression.
+iolog_flush = true
+
+# The group to use when creating new I/O log files and directories.
+# If iolog_group is not set, the primary group-ID of the user specified
+# by iolog_user is used. If neither iolog_group nor iolog_user
+# are set, I/O log files and directories are created with group-ID 0.
+#iolog_group = wheel
+
+# The user to use when setting the user-ID and group-ID of new I/O
+# log files and directories. If iolog_group is set, it will be used
+# instead of the user's primary group-ID. By default, I/O log files
+# and directories are created with user and group-ID 0.
+iolog_user = root
+
+# The file mode to use when creating I/O log files. The file permissions
+# will always include the owner read and write bits, even if they are
+# not present in the specified mode. When creating I/O log directories,
+# search (execute) bits are added to match the read and write bits
+# specified by iolog_mode.
+iolog_mode = 0600
+
+# If disabled, sudo_logsrvd will attempt to avoid logging plaintext
+# password in the terminal input using passprompt_regex.
+log_passwords = true
+
+# The maximum sequence number that will be substituted for the "%{seq}"
+# escape in the I/O log file. While the value substituted for "%{seq}"
+# is in base 36, maxseq itself should be expressed in decimal. Values
+# larger than 2176782336 (which corresponds to the base 36 sequence
+# number "ZZZZZZ") will be silently truncated to 2176782336.
+maxseq = 2176782336
+
+# One or more POSIX extended regular expressions used to match
+# password prompts in the terminal output when log_passwords is
+# disabled. Multiple passprompt_regex settings may be specified.
+#passprompt_regex = [Pp]assword[: ]*
+#passprompt_regex = [Pp]assword for [a-z0-9]+: *
+passprompt_regex = [Pp]assword[: ]*
+
+[eventlog]
+# Where to log accept, reject, exit, and alert events.
+# Accepted values are syslog, logfile, or none.
+# Defaults to syslog
+log_type = syslog
+
+# Whether to log an event when a command exits or is terminated by a signal.
+# Defaults to false
+log_exit = true
+
+# Event log format.
+# Supported log formats are "sudo" and "json"
+# Defaults to sudo
+log_format = sudo
+
+[syslog]
+# The maximum length of a syslog payload.
+# On many systems, syslog(3) has a relatively small log buffer.
+# IETF RFC 5424 states that syslog servers must support messages
+# of at least 480 bytes and should support messages up to 2048 bytes.
+# Messages larger than this value will be split into multiple messages.
+maxlen = 960
+
+# The syslog facility to use for event log messages.
+# The following syslog facilities are supported: authpriv (if your OS
+# supports it), auth, daemon, user, local0, local1, local2, local3,
+# local4, local5, local6, and local7.
+facility = authpriv
+
+# Syslog priority to use for event log accept messages, when the command
+# is allowed by the security policy. The following syslog priorities are
+# supported: alert, crit, debug, emerg, err, info, notice, warning, none.
+accept_priority = low
+
+# Syslog priority to use for event log reject messages, when the command
+# is not allowed by the security policy.
+reject_priority = alert
+
+# Syslog priority to use for event log alert messages reported by the
+# client.
+alert_priority = alert
+
+# The syslog facility to use for server warning messages.
+# Defaults to daemon.
+server_facility = daemon
+
+[logfile]
+# The path to the file-based event log.
+# This path must be fully-qualified and start with a '/' character.
+path = /var/log/sudo
+
+# The format string used when formatting the date and time for
+# file-based event logs. Formatting is performed via strftime(3) so
+# any format string supported by that function is allowed.
+time_format = %h %e %T
diff --git a/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.6 b/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.6
new file mode 100644
index 0000000..33f1cf2
--- /dev/null
+++ b/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.6
@@ -0,0 +1,255 @@
+#
+# sudo logsrv daemon configuration
+#
+
+[server]
+# The host name or IP address and port to listen on with an optional TLS
+# flag. If no port is specified, port 30343 will be used for plaintext
+# connections and port 30344 will be used to TLS connections.
+# The following forms are accepted:
+# listen_address = hostname(tls)
+# listen_address = hostname:port(tls)
+# listen_address = IPv4_address(tls)
+# listen_address = IPv4_address:port(tls)
+# listen_address = [IPv6_address](tls)
+# listen_address = [IPv6_address]:port(tls)
+#
+# The (tls) suffix should be omitted for plaintext connections.
+#
+# Multiple listen_address settings may be specified.
+# The default is to listen on all addresses.
+#listen_address = *:30343
+listen_address = *:30344(tls)
+
+# The file containing the ID of the running sudo_logsrvd process.
+pid_file = /var/run/sudo/sudo_logsrvd.pid
+
+# Where to log server warnings: none, stderr, syslog, or a path name.
+server_log = syslog
+
+# If true, enable the SO_KEEPALIVE socket option on client connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the client to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server will validate its own certificate at startup.
+# Defaults to true.
+tls_verify = true
+
+# If true, client certificates will be validated by the server;
+# clients without a valid certificate will be unable to connect.
+# By default, client certs are not checked.
+tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# Required for TLS connections.
+tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# Required for TLS connections.
+tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# NOTE that this setting is only effective if the negotiated protocol
+# is TLS version 1.2.
+# The default cipher list is HIGH:!aNULL.
+tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default cipher list is TLS_AES_256_GCM_SHA384.
+tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# If not set, the server will use the OpenSSL defaults.
+tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[relay]
+# The host name or IP address and port to send logs to in relay mode.
+# The syntax is identical to listen_address with the exception of
+# the wild card ('*') syntax. When this setting is enabled, logs will
+# be relayed to the specified host instead of being stored locally.
+# This setting is not enabled by default.
+#relay_host = relayhost.dom.ain
+#relay_host = relayhost.dom.ain(tls)
+relay_host = localhost(tls)
+
+# The amount of time, in seconds, the server will wait for a connection
+# to the relay server to complete. A value of 0 will disable the timeout.
+# The default value is 30.
+connect_timeout = 30
+
+# The directory to store messages in before they are sent to the relay.
+# Messages are stored in wire format.
+# The default value is /var/log/sudo_logsrvd.
+relay_dir = /var/log/sudo_logsrvd
+
+# The number of seconds to wait after a connection error before
+# making a new attempt to forward a message to a relay host.
+# The default value is 30.
+retry_interval = 30
+
+# Whether to store the log before relaying it. If true, enable store
+# and forward mode. If false, the client connection is immediately
+# relayed. Defaults to false.
+#store_first = true
+
+# If true, enable the SO_KEEPALIVE socket option on relay connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the relay to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server's relay certificate will be verified at startup.
+# The default is to use the value in the [server] section.
+tls_verify = true
+
+# Whether to verify the relay's certificate for TLS connections.
+# The default is to use the value in the [server] section.
+tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+# The default is to use the value in the [server] section.
+tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# The default is to use the certificate in the [server] section.
+tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# The default is to use the key in the [server] section.
+tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# NOTE that this setting is only effective if the negotiated protocol
+# is TLS version 1.2.
+# The default is to use the value in the [server] section.
+tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default is to use the value in the [server] section.
+tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# The default is to use the value in the [server] section.
+tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[iolog]
+# The top-level directory to use when constructing the path name for the
+# I/O log directory. The session sequence number, if any, is stored here.
+iolog_dir = /var/log/sudo-io
+
+# The path name, relative to iolog_dir, in which to store I/O logs.
+# Note that iolog_file may contain directory components.
+iolog_file = %{seq}
+
+# If set, I/O logs will be compressed using zlib. Enabling compression can
+# make it harder to view the logs in real-time as the program is executing.
+iolog_compress = false
+
+# If set, I/O log data is flushed to disk after each write instead of
+# buffering it. This makes it possible to view the logs in real-time
+# as the program is executing but reduces the effectiveness of compression.
+iolog_flush = true
+
+# The group to use when creating new I/O log files and directories.
+# If iolog_group is not set, the primary group-ID of the user specified
+# by iolog_user is used. If neither iolog_group nor iolog_user
+# are set, I/O log files and directories are created with group-ID 0.
+#iolog_group = wheel
+
+# The user to use when setting the user-ID and group-ID of new I/O
+# log files and directories. If iolog_group is set, it will be used
+# instead of the user's primary group-ID. By default, I/O log files
+# and directories are created with user and group-ID 0.
+iolog_user = root
+
+# The file mode to use when creating I/O log files. The file permissions
+# will always include the owner read and write bits, even if they are
+# not present in the specified mode. When creating I/O log directories,
+# search (execute) bits are added to match the read and write bits
+# specified by iolog_mode.
+iolog_mode = 0600
+
+# If disabled, sudo_logsrvd will attempt to avoid logging plaintext
+# password in the terminal input using passprompt_regex.
+log_passwords = true
+
+# The maximum sequence number that will be substituted for the "%{seq}"
+# escape in the I/O log file. While the value substituted for "%{seq}"
+# is in base 36, maxseq itself should be expressed in decimal. Values
+# larger than 2176782336 (which corresponds to the base 36 sequence
+# number "ZZZZZZ") will be silently truncated to 2176782336.
+maxseq = 2176782336
+
+# One or more POSIX extended regular expressions used to match
+# password prompts in the terminal output when log_passwords is
+# disabled. Multiple passprompt_regex settings may be specified.
+#passprompt_regex = [Pp]assword[: ]*
+#passprompt_regex = [Pp]assword for [a-z0-9]+: *
+passprompt_regex = [Pp]assword[: ]*
+
+[eventlog]
+# Where to log accept, reject, exit, and alert events.
+# Accepted values are syslog, logfile, or none.
+# Defaults to syslog
+log_type = syslog
+
+# Whether to log an event when a command exits or is terminated by a signal.
+# Defaults to false
+log_exit = true
+
+# Event log format.
+# Supported log formats are "sudo" and "json"
+# Defaults to sudo
+log_format = sudo
+
+[syslog]
+# The maximum length of a syslog payload.
+# On many systems, syslog(3) has a relatively small log buffer.
+# IETF RFC 5424 states that syslog servers must support messages
+# of at least 480 bytes and should support messages up to 2048 bytes.
+# Messages larger than this value will be split into multiple messages.
+maxlen = 960
+
+# The syslog facility to use for event log messages.
+# The following syslog facilities are supported: authpriv (if your OS
+# supports it), auth, daemon, user, local0, local1, local2, local3,
+# local4, local5, local6, and local7.
+facility = authpriv
+
+# Syslog priority to use for event log accept messages, when the command
+# is allowed by the security policy. The following syslog priorities are
+# supported: alert, crit, debug, emerg, err, info, notice, warning, none.
+accept_priority = notice
+
+# Syslog priority to use for event log reject messages, when the command
+# is not allowed by the security policy.
+reject_priority = alert
+
+# Syslog priority to use for event log alert messages reported by the
+# client.
+alert_priority = high
+
+# The syslog facility to use for server warning messages.
+# Defaults to daemon.
+server_facility = daemon
+
+[logfile]
+# The path to the file-based event log.
+# This path must be fully-qualified and start with a '/' character.
+path = /var/log/sudo
+
+# The format string used when formatting the date and time for
+# file-based event logs. Formatting is performed via strftime(3) so
+# any format string supported by that function is allowed.
+time_format = %h %e %T
diff --git a/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.7 b/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.7
new file mode 100644
index 0000000..65a2551
--- /dev/null
+++ b/logsrvd/regress/corpus/seed/logsrvd_conf/logsrvd.conf.7
@@ -0,0 +1,255 @@
+#
+# sudo logsrv daemon configuration
+#
+
+[server]
+# The host name or IP address and port to listen on with an optional TLS
+# flag. If no port is specified, port 30343 will be used for plaintext
+# connections and port 30344 will be used to TLS connections.
+# The following forms are accepted:
+# listen_address = hostname(tls)
+# listen_address = hostname:port(tls)
+# listen_address = IPv4_address(tls)
+# listen_address = IPv4_address:port(tls)
+# listen_address = [IPv6_address](tls)
+# listen_address = [IPv6_address]:port(tls)
+#
+# The (tls) suffix should be omitted for plaintext connections.
+#
+# Multiple listen_address settings may be specified.
+# The default is to listen on all addresses.
+#listen_address = *:30343
+listen_address = *:30344(tls)
+
+# The file containing the ID of the running sudo_logsrvd process.
+pid_file = /var/run/sudo/sudo_logsrvd.pid
+
+# Where to log server warnings: none, stderr, syslog, or a path name.
+server_log = syslog
+
+# If true, enable the SO_KEEPALIVE socket option on client connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the client to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server will validate its own certificate at startup.
+# Defaults to true.
+tls_verify = true
+
+# If true, client certificates will be validated by the server;
+# clients without a valid certificate will be unable to connect.
+# By default, client certs are not checked.
+tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# Required for TLS connections.
+tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# Required for TLS connections.
+tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# NOTE that this setting is only effective if the negotiated protocol
+# is TLS version 1.2.
+# The default cipher list is HIGH:!aNULL.
+tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default cipher list is TLS_AES_256_GCM_SHA384.
+tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# If not set, the server will use the OpenSSL defaults.
+tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[relay]
+# The host name or IP address and port to send logs to in relay mode.
+# The syntax is identical to listen_address with the exception of
+# the wild card ('*') syntax. When this setting is enabled, logs will
+# be relayed to the specified host instead of being stored locally.
+# This setting is not enabled by default.
+#relay_host = relayhost.dom.ain
+#relay_host = relayhost.dom.ain(tls)
+relay_host = localhost(tls)
+
+# The amount of time, in seconds, the server will wait for a connection
+# to the relay server to complete. A value of 0 will disable the timeout.
+# The default value is 30.
+connect_timeout = 30
+
+# The directory to store messages in before they are sent to the relay.
+# Messages are stored in wire format.
+# The default value is /var/log/sudo_logsrvd.
+relay_dir = /var/log/sudo_logsrvd
+
+# The number of seconds to wait after a connection error before
+# making a new attempt to forward a message to a relay host.
+# The default value is 30.
+retry_interval = 30
+
+# Whether to store the log before relaying it. If true, enable store
+# and forward mode. If false, the client connection is immediately
+# relayed. Defaults to false.
+#store_first = true
+
+# If true, enable the SO_KEEPALIVE socket option on relay connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the relay to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server's relay certificate will be verified at startup.
+# The default is to use the value in the [server] section.
+#tls_verify = true
+
+# Whether to verify the relay's certificate for TLS connections.
+# The default is to use the value in the [server] section.
+#tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+# The default is to use the value in the [server] section.
+#tls_cacert = /etc/ssl/sudo/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# The default is to use the certificate in the [server] section.
+#tls_cert = /etc/ssl/sudo/certs/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# The default is to use the key in the [server] section.
+#tls_key = /etc/ssl/sudo/private/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# NOTE that this setting is only effective if the negotiated protocol
+# is TLS version 1.2.
+# The default is to use the value in the [server] section.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default is to use the value in the [server] section.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# The default is to use the value in the [server] section.
+#tls_dhparams = /etc/ssl/sudo/logsrvd_dhparams.pem
+
+[iolog]
+# The top-level directory to use when constructing the path name for the
+# I/O log directory. The session sequence number, if any, is stored here.
+iolog_dir = /var/log/sudo-io
+
+# The path name, relative to iolog_dir, in which to store I/O logs.
+# Note that iolog_file may contain directory components.
+iolog_file = %{seq}
+
+# If set, I/O logs will be compressed using zlib. Enabling compression can
+# make it harder to view the logs in real-time as the program is executing.
+iolog_compress = false
+
+# If set, I/O log data is flushed to disk after each write instead of
+# buffering it. This makes it possible to view the logs in real-time
+# as the program is executing but reduces the effectiveness of compression.
+iolog_flush = true
+
+# The group to use when creating new I/O log files and directories.
+# If iolog_group is not set, the primary group-ID of the user specified
+# by iolog_user is used. If neither iolog_group nor iolog_user
+# are set, I/O log files and directories are created with group-ID 0.
+iolog_group = wheel
+
+# The user to use when setting the user-ID and group-ID of new I/O
+# log files and directories. If iolog_group is set, it will be used
+# instead of the user's primary group-ID. By default, I/O log files
+# and directories are created with user and group-ID 0.
+iolog_user = root
+
+# The file mode to use when creating I/O log files. The file permissions
+# will always include the owner read and write bits, even if they are
+# not present in the specified mode. When creating I/O log directories,
+# search (execute) bits are added to match the read and write bits
+# specified by iolog_mode.
+iolog_mode = 0600
+
+# If disabled, sudo_logsrvd will attempt to avoid logging plaintext
+# password in the terminal input using passprompt_regex.
+log_passwords = false
+
+# The maximum sequence number that will be substituted for the "%{seq}"
+# escape in the I/O log file. While the value substituted for "%{seq}"
+# is in base 36, maxseq itself should be expressed in decimal. Values
+# larger than 2176782336 (which corresponds to the base 36 sequence
+# number "ZZZZZZ") will be silently truncated to 2176782336.
+maxseq = 2176782336
+
+# One or more POSIX extended regular expressions used to match
+# password prompts in the terminal output when log_passwords is
+# disabled. Multiple passprompt_regex settings may be specified.
+#passprompt_regex = [Pp]assword[: ]*
+#passprompt_regex = [Pp]assword for [a-z0-9]+: *
+passprompt_regex = [Pp]assword[: ]\+++++++++++
+
+[eventlog]
+# Where to log accept, reject, exit, and alert events.
+# Accepted values are syslog, logfile, or none.
+# Defaults to syslog
+log_type = syslog
+
+# Whether to log an event when a command exits or is terminated by a signal.
+# Defaults to false
+log_exit = true
+
+# Event log format.
+# Supported log formats are "sudo" and "json"
+# Defaults to sudo
+log_format = sudo
+
+[syslog]
+# The maximum length of a syslog payload.
+# On many systems, syslog(3) has a relatively small log buffer.
+# IETF RFC 5424 states that syslog servers must support messages
+# of at least 480 bytes and should support messages up to 2048 bytes.
+# Messages larger than this value will be split into multiple messages.
+maxlen = 960
+
+# The syslog facility to use for event log messages.
+# The following syslog facilities are supported: authpriv (if your OS
+# supports it), auth, daemon, user, local0, local1, local2, local3,
+# local4, local5, local6, and local7.
+facility = authpriv
+
+# Syslog priority to use for event log accept messages, when the command
+# is allowed by the security policy. The following syslog priorities are
+# supported: alert, crit, debug, emerg, err, info, notice, warning, none.
+accept_priority = notice
+
+# Syslog priority to use for event log reject messages, when the command
+# is not allowed by the security policy.
+reject_priority = alert
+
+# Syslog priority to use for event log alert messages reported by the
+# client.
+alert_priority = alert
+
+# The syslog facility to use for server warning messages.
+# Defaults to daemon.
+server_facility = daemon
+
+[logfile]
+# The path to the file-based event log.
+# This path must be fully-qualified and start with a '/' character.
+path = /var/log/sudo
+
+# The format string used when formatting the date and time for
+# file-based event logs. Formatting is performed via strftime(3) so
+# any format string supported by that function is allowed.
+time_format = %h %e %T
diff --git a/logsrvd/regress/fuzz/fuzz_logsrvd_conf.c b/logsrvd/regress/fuzz/fuzz_logsrvd_conf.c
new file mode 100644
index 0000000..dc012be
--- /dev/null
+++ b/logsrvd/regress/fuzz/fuzz_logsrvd_conf.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2021-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <netdb.h>
+#include <regex.h>
+#include <time.h>
+#include <unistd.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_conf.h>
+#include <sudo_debug.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_iolog.h>
+#include <sudo_plugin.h>
+#include <sudo_util.h>
+
+#include <logsrvd.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+/*
+ * Stub version that always succeeds for small inputs and fails for large.
+ * We want to fuzz our parser, not libc's regular expression code.
+ */
+bool
+sudo_regex_compile_v1(void *v, const char *pattern, const char **errstr)
+{
+ regex_t *preg = v;
+
+ if (strlen(pattern) > 32) {
+ *errstr = "invalid regular expression";
+ return false;
+ }
+
+ /* hopefully avoid regfree() crashes */
+ memset(preg, 0, sizeof(*preg));
+ return true;
+}
+
+/*
+ * The fuzzing environment may not have DNS available, this may result
+ * in long delays that cause a timeout when fuzzing.
+ * This getaddrinfo() resolves every name as "localhost" (127.0.0.1).
+ */
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+/* Avoid compilation errors if getaddrinfo() or freeaddrinfo() are macros. */
+# undef getaddrinfo
+# undef freeaddrinfo
+
+int
+# ifdef HAVE_GETADDRINFO
+getaddrinfo(
+# else
+sudo_getaddrinfo(
+# endif
+ const char *nodename, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res)
+{
+ struct addrinfo *ai;
+ struct in_addr addr;
+ unsigned short port = 0;
+
+ /* Stub getaddrinfo(3) to avoid a DNS timeout in CIfuzz. */
+ if (servname == NULL) {
+ /* Must have either nodename or servname. */
+ if (nodename == NULL)
+ return EAI_NONAME;
+ } else {
+ struct servent *servent;
+ const char *errstr;
+
+ /* Parse servname as a port number or IPv4 TCP service name. */
+ port = sudo_strtonum(servname, 0, USHRT_MAX, &errstr);
+ if (errstr != NULL && errno == ERANGE)
+ return EAI_SERVICE;
+ if (hints != NULL && ISSET(hints->ai_flags, AI_NUMERICSERV))
+ return EAI_NONAME;
+ servent = getservbyname(servname, "tcp");
+ if (servent == NULL)
+ return EAI_NONAME;
+ port = htons(servent->s_port);
+ }
+
+ /* Hard-code IPv4 localhost for fuzzing. */
+ ai = calloc(1, sizeof(*ai) + sizeof(struct sockaddr_in));
+ if (ai == NULL)
+ return EAI_MEMORY;
+ ai->ai_canonname = strdup("localhost");
+ if (ai == NULL) {
+ free(ai);
+ return EAI_MEMORY;
+ }
+ ai->ai_family = AF_INET;
+ ai->ai_protocol = IPPROTO_TCP;
+ ai->ai_addrlen = sizeof(struct sockaddr_in);
+ ai->ai_addr = (struct sockaddr *)(ai + 1);
+ inet_pton(AF_INET, "127.0.0.1", &addr);
+ ((struct sockaddr_in *)ai->ai_addr)->sin_family = AF_INET;
+ ((struct sockaddr_in *)ai->ai_addr)->sin_addr = addr;
+ ((struct sockaddr_in *)ai->ai_addr)->sin_port = htons(port);
+ *res = ai;
+ return 0;
+}
+
+void
+# ifdef HAVE_GETADDRINFO
+freeaddrinfo(struct addrinfo *ai)
+# else
+sudo_freeaddrinfo(struct addrinfo *ai)
+# endif
+{
+ struct addrinfo *next;
+
+ while (ai != NULL) {
+ next = ai->ai_next;
+ free(ai->ai_canonname);
+ free(ai);
+ ai = next;
+ }
+}
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
+
+static int
+fuzz_conversation(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
+{
+ int n;
+
+ for (n = 0; n < num_msgs; n++) {
+ const struct sudo_conv_message *msg = &msgs[n];
+
+ switch (msg->msg_type & 0xff) {
+ case SUDO_CONV_PROMPT_ECHO_ON:
+ case SUDO_CONV_PROMPT_MASK:
+ case SUDO_CONV_PROMPT_ECHO_OFF:
+ /* input not supported */
+ return -1;
+ case SUDO_CONV_ERROR_MSG:
+ case SUDO_CONV_INFO_MSG:
+ /* no output for fuzzers */
+ break;
+ default:
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ char tempfile[] = "/tmp/logsrvd_conf.XXXXXX";
+ ssize_t nwritten;
+ int fd;
+
+ initprogname("fuzz_logsrvd_conf");
+ if (getenv("SUDO_FUZZ_VERBOSE") == NULL)
+ sudo_warn_set_conversation(fuzz_conversation);
+
+ /* logsrvd_conf_read() uses a conf file path, not an open file. */
+ fd = mkstemp(tempfile);
+ if (fd == -1)
+ return 0;
+ nwritten = write(fd, data, size);
+ if (nwritten == -1) {
+ close(fd);
+ return 0;
+ }
+ close(fd);
+
+ if (logsrvd_conf_read(tempfile)) {
+ /* public config getters */
+ logsrvd_conf_iolog_dir();
+ logsrvd_conf_iolog_file();
+ logsrvd_conf_iolog_mode();
+ logsrvd_conf_pid_file();
+ logsrvd_conf_relay_address();
+ logsrvd_conf_relay_connect_timeout();
+ logsrvd_conf_relay_tcp_keepalive();
+ logsrvd_conf_relay_timeout();
+ logsrvd_conf_server_listen_address();
+ logsrvd_conf_server_tcp_keepalive();
+ logsrvd_conf_server_timeout();
+
+ /* free config */
+ logsrvd_conf_cleanup();
+ }
+
+ unlink(tempfile);
+
+ fflush(stdout);
+
+ return 0;
+}
diff --git a/logsrvd/regress/fuzz/fuzz_logsrvd_conf.dict b/logsrvd/regress/fuzz/fuzz_logsrvd_conf.dict
new file mode 100644
index 0000000..d9f5d10
--- /dev/null
+++ b/logsrvd/regress/fuzz/fuzz_logsrvd_conf.dict
@@ -0,0 +1,44 @@
+"[server]"
+"listen_address"
+"pid_file"
+"tcp_keepalive"
+"timeout"
+"tls_verify"
+"tls_checkpeer"
+"tls_cacert"
+"tls_cert"
+"tls_key"
+"tls_ciphers_v12"
+"tls_ciphers_v13"
+"tls_dhparams"
+
+"[relay]"
+"relay_host"
+"connect_timeout"
+
+"[iolog]"
+"iolog_dir"
+"iolog_file"
+"iolog_compress"
+"iolog_flush"
+"iolog_group"
+"iolog_user"
+"iolog_mode"
+"log_passwords"
+"maxseq"
+"passprompt_regex"
+
+"[eventlog]"
+"log_type"
+"log_format"
+
+"[syslog]"
+"maxlen"
+"facility"
+"accept_priority"
+"reject_priority"
+"alert_priority"
+
+"[logfile]"
+"path"
+"time_format"
diff --git a/logsrvd/regress/logsrvd_conf/cacert.pem b/logsrvd/regress/logsrvd_conf/cacert.pem
new file mode 100644
index 0000000..f74402d
--- /dev/null
+++ b/logsrvd/regress/logsrvd_conf/cacert.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF/DCCA+SgAwIBAgIUOEgkFv51VLpqhnSlwmvTCjeq81kwDQYJKoZIhvcNAQEL
+BQAwgYUxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhDb2xvcmFkbzEQMA4GA1UEBwwH
+Qm91bGRlcjEVMBMGA1UECgwMU3VkbyBQcm9qZWN0MSMwIQYDVQQLDBpTdWRvIENl
+cnRpZmljYXRlIEF1dGhvcml0eTEVMBMGA1UEAwwMU3VkbyBSb290IENBMCAXDTIy
+MDYwMjE2NDQxMVoYDzIxMjIwNTA5MTY0NDExWjCBhTELMAkGA1UEBhMCVVMxETAP
+BgNVBAgMCENvbG9yYWRvMRAwDgYDVQQHDAdCb3VsZGVyMRUwEwYDVQQKDAxTdWRv
+IFByb2plY3QxIzAhBgNVBAsMGlN1ZG8gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MRUw
+EwYDVQQDDAxTdWRvIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQC8DASzPZlyg51mWLAJYPZDgHZL1gXQ9Nb+iYYfePz+9LPJ/ObPrDIWNC6j
+wDIPPOlB6+UzVKDR7JtqVo4kzea1C+cZilCo5nX3uIvzsn484vtmUMTPCIBZ3mYq
+zz4jIgkHxZwZlEhGRhf12sY+XeVwOvm73/iaODvodqjoQlvwwdZokov5HN1N8rCT
++uMH1TOPgz8pE365FjDmfZzizoslbxmoQLLmewFYsKQBpXMMurYkoXlSezoe+LWI
+lm9HEZjo6/YtMjypA1S02CXmB9Y2wSMOCzLfrLsqJe8x3yZ/clOdAIGFmPBNbAE5
+mpLT3tCf1n1xBRXQoQ33fNcWgyR3hPdI5EcKmhR5RS5fO7KOaBdOInmqvIOlr+yT
+jQVIk0jyEpW8Hf5vJypCsItgHtG2dz7XCoDVXKF7b270N+gSMhIa9XZLFiSsIgoM
+uJfDe+URHL0+UMohcwkRknTnU1DR+uGZi29oIe8eYdvraV9XpOTySVa4HM9ZG8Yv
+24EjzCJYGvSL1VFIK+q1NLt8uxXDPUAW4J8R9Teka5Hhkv6+iXGpYUqgy+jPW1yo
+shLBKn+/T+CkjStAyRwezm9pCUdJOMGRuQIEOAYBJwbzY+Qwe8va//r+K44ORG6N
+6Rq9QDApOxCn9lGuWiQM/jhOyN5vuMMPMKct8KatFw7d1hx5fwIDAQABo2AwXjAd
+BgNVHQ4EFgQU/nKxgas9kLS2L7jmi1A+lowSMiAwHwYDVR0jBBgwFoAU/nKxgas9
+kLS2L7jmi1A+lowSMiAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJ
+KoZIhvcNAQELBQADggIBAIaABzzebiw6xi9PFhBlfK+KYVJqTdwgLqOzLsL4qgPc
+J1XK+aQSC/WDleBVzMXeZdwKoRaU3Wcy+By6HWV52gjqOyhBlI2VgSDLGOYbXucM
+eCTlrlRoap6ut1PVMuuVoSjQi0DMbhkz3ZGx/a0STefGADu0R9JTaJJN36JfTjSH
+RBRDnhsEgZU5FVmTZqkZgATjRd7NwgmGAt17FvBuwBSAkt3NZmJTt7TzsCvtVBK2
+lkT4H+8m59lAp8Rk8RthRcAPQtMKsuvORBtwhbpLHbo9ilMRMc5rNc8IY9pzcQ0N
+sMzyk8SIRov/PBnC1SPK+/jRhzLA/1gyzg5dt2jQIE5GhNqDQxi+f5HTMKklO8C9
+KHSeu9DZ32pBaNZPPvECkSZoTIsKroVvzuL/4drg4qxQFT/az4Z/rwnfVK8MYhDP
+jKK19diEt36cQiDEr7WRCdhy8QmI49EBqE57LjOju5cuBXJnBFI05gbC4bQCzqZm
+G2fHeHDX+QeBSfgzOP1aerd8mLiRymoJuBYDY50UzkGgg0gPoSVQKqE5YnYxP/Sz
+HYoLv7N6COWqbtY9nmJTHwGGWoH40bIqSY8mGe34AZ7a/zVtvlcAgThlOH82dnPJ
+vfUOIbVoOOliY2O7J0TZJGQVgsH5qNd4rdyKoL7kl59sU+wl/5UVME8pA+B/LFNF
+-----END CERTIFICATE-----
diff --git a/logsrvd/regress/logsrvd_conf/logsrvd_cert.pem b/logsrvd/regress/logsrvd_conf/logsrvd_cert.pem
new file mode 100644
index 0000000..52ef5b6
--- /dev/null
+++ b/logsrvd/regress/logsrvd_conf/logsrvd_cert.pem
@@ -0,0 +1,28 @@
+-----BEGIN CERTIFICATE-----
+MIIEwzCCAqugAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgYUxCzAJBgNVBAYTAlVT
+MREwDwYDVQQIDAhDb2xvcmFkbzEQMA4GA1UEBwwHQm91bGRlcjEVMBMGA1UECgwM
+U3VkbyBQcm9qZWN0MSMwIQYDVQQLDBpTdWRvIENlcnRpZmljYXRlIEF1dGhvcml0
+eTEVMBMGA1UEAwwMU3VkbyBSb290IENBMCAXDTIyMDYwMjE2NDUzM1oYDzIxMjIw
+NTA5MTY0NTMzWjBlMQswCQYDVQQGEwJVUzERMA8GA1UECAwIQ29sb3JhZG8xFTAT
+BgNVBAoMDFN1ZG8gUHJvamVjdDEYMBYGA1UECwwPU3VkbyBMb2cgU2VydmVyMRIw
+EAYDVQQDDAkxMjcuMC4wLjEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQC7/TKl0yMsu+65gomOkJN+LlVAqVHuONQXCC2zBpSNsP7mXaxx0uhDDxg6kope
+J5f1diNX/Y5F60AlQn1a8cKOM1Cwvz7seTEZ1mCJay82Q3oyCCcSTjAa4ZDZbiag
+n4e4WYqIOw5EE0DPk37UTdsqUfy90JxCUxSBMY5FQUJbc86ZadsWPb5SzsHTXfi2
+a5vyqHMm7dJ/C30cyJ8jDkChReO78DrQIZHpuj0T7otKxwQu0tkQ1bKEto7hEeOl
+TblxrUZRkpumSUhFaZYt1DL6mrFinLtU9fYEFxE8f530D9mUtsZuPwYdqkantk7J
+GqnpjwP0ypWFP0ckwJcn5FJHAgMBAAGjWjBYMAkGA1UdEwQCMAAwCwYDVR0PBAQD
+AgXgMB0GA1UdDgQWBBTvAo8XDnHpwGZEAyUTSmiialQzSDAfBgNVHSMEGDAWgBT+
+crGBqz2QtLYvuOaLUD6WjBIyIDANBgkqhkiG9w0BAQsFAAOCAgEAHgUddk7bMYU5
+hdJiToCp0w32LQpHt8EepG4pWEzNdlnxBEb2D2f57JS3gVDoAyTAWxYipEdtCYx5
+2hMR4qrZ7G7G0D8XLj1A22nVlFUOqaUUIJRG1fFBGMM/T9CP1WLN2V2rYNoMFUdB
+3aahuVKYK4TawWBhEA0cnZJeHwpg/0/B7jxYWtKF2ys8CdqBd9rgPoKZF/QfxKmz
+otR7oZZuEaY9/kIkDtFaNb81JMbc/9RyBgB+5rQ8RmPcXDJ5aow5XvTWbx0LAwZZ
+u1c104UxwEy062WLnpluqZ3obyJsA8G3X4kI/CffCGCjIIdnRPYQiBngKL4hvAUs
+g/sD7Y1TrSWnEPJebpQwwYS4Y1HMPioDYJiGiehzZzUWWAC4itrj8mnycrTlvnev
+wMh5XGHqAXd5iF+Ztw1thj2dRiVpLkyKEiPLEpTI3QL1xwnyK28fPZJyMeJ/WNJ3
+Yb51qlZw2pH8kfXoOaIINUC9ZsJujm+SBbO0JX9BK95w+23WGd8cSHRNEytsLESP
+rvwljeCwQ7OqTmxT9iUBS8QZUM0ov3bF/oKpmcJe3xCAQCr2H41Fa1/CPrrco0Ar
+Te0qU+Qy1ir5Qfu13qiU6Ea0d7PcOdYEe6sjHUQ4Z/o+/uQ1NJS26ahPNKOChcDe
++r8pnbtZ9uW6dQjdU6Yk6Gl6Z/vOxvU=
+-----END CERTIFICATE-----
diff --git a/logsrvd/regress/logsrvd_conf/logsrvd_conf_test.c b/logsrvd/regress/logsrvd_conf/logsrvd_conf_test.c
new file mode 100644
index 0000000..cf286bd
--- /dev/null
+++ b/logsrvd/regress/logsrvd_conf/logsrvd_conf_test.c
@@ -0,0 +1,90 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <sys/socket.h>
+
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_iolog.h>
+#include <sudo_queue.h>
+#include <logsrvd.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+sudo_noreturn static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-v] conf_file\n", getprogname());
+ exit(EXIT_FAILURE);
+}
+
+/*
+ * Simple test driver for logsrvd_conf_read().
+ * Just pases the file, errors to standard error.
+ */
+int
+main(int argc, char *argv[])
+{
+ bool verbose = false;
+ int ch, ntests, errors = 0;
+
+ initprogname(argc > 0 ? argv[0] : "conf_test");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ verbose = true;
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1)
+ usage();
+
+ for (ntests = 0; ntests < argc; ntests++) {
+ const char *path = argv[ntests];
+ if (verbose)
+ printf("reading %s\n", path);
+ if (!logsrvd_conf_read(path))
+ errors++;
+ }
+ logsrvd_conf_cleanup();
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+ return errors;
+}
diff --git a/logsrvd/regress/logsrvd_conf/logsrvd_dhparams.pem b/logsrvd/regress/logsrvd_conf/logsrvd_dhparams.pem
new file mode 100644
index 0000000..508846e
--- /dev/null
+++ b/logsrvd/regress/logsrvd_conf/logsrvd_dhparams.pem
@@ -0,0 +1,8 @@
+-----BEGIN DH PARAMETERS-----
+MIIBCAKCAQEA/QJRAmmGCZw79LyKinHUA0fEEzDiUkhuILieN0LLruznj4RBebQi
+0sEa7YrFPG7z/eLU/aoBaJmWiX3ZOGReM1NoMJgZJezkY3HBiHombb9lBJHOSaHK
+rT6viG3tBiu3DiByC+hdcp9xWfXkxgC944tIiTdFJtgYWw1KUBRHnSMob+ulZ2VE
+COZE8HX7Nbp26fsfOKgcb/AX0fMLOetG0aaSgYAtyOGx1toRAFhEcdq/lusdkbzy
+SUWwXfMXZorZoPudn31w7IN2wvDtP7v5fGqx6e9c91Orhy96sC7jmwedK/BGnkRi
+XwnI6LNXwg30g4vLuinegqcNzmqcFY0wIwIBAg==
+-----END DH PARAMETERS-----
diff --git a/logsrvd/regress/logsrvd_conf/logsrvd_key.pem b/logsrvd/regress/logsrvd_conf/logsrvd_key.pem
new file mode 100644
index 0000000..e586169
--- /dev/null
+++ b/logsrvd/regress/logsrvd_conf/logsrvd_key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7/TKl0yMsu+65
+gomOkJN+LlVAqVHuONQXCC2zBpSNsP7mXaxx0uhDDxg6kopeJ5f1diNX/Y5F60Al
+Qn1a8cKOM1Cwvz7seTEZ1mCJay82Q3oyCCcSTjAa4ZDZbiagn4e4WYqIOw5EE0DP
+k37UTdsqUfy90JxCUxSBMY5FQUJbc86ZadsWPb5SzsHTXfi2a5vyqHMm7dJ/C30c
+yJ8jDkChReO78DrQIZHpuj0T7otKxwQu0tkQ1bKEto7hEeOlTblxrUZRkpumSUhF
+aZYt1DL6mrFinLtU9fYEFxE8f530D9mUtsZuPwYdqkantk7JGqnpjwP0ypWFP0ck
+wJcn5FJHAgMBAAECggEAA4H+N7l3v6t/ZmyKslU2EnXLUB3KfOrPb6hc90WOmy49
+pSuuTLz7adh6CbTeTeE96/wuWYqjq+AaVvszvrg+Xj3MqhiHd9Rdwmgbp0MBakyv
+ls72zXRrJycIk8mfgR5x1MRYvaGTlXWa9KgsIzw+Anftnyw3yOJf+1oNmAE7ENzf
+c3IBeQF040ahQleUoF6msNvjVrcKSiOpM8x+ectrx6S1vJP9rJFRp2g5Vlroskcs
+ztPF4P9MFgsAzDd3HPtzBHXzoDNAlTwBbT6Ins6CeWENJY2KjRqntfQUJZfa12cQ
+XE4v4HIBm2u8MxxjW4B3dNXcy4JY5yQu0RULJnGzYQKBgQDIuT2cVmdRDa9jyBUq
+XWpMOwo4jHm1qTr750dvq93z2fSSKjmee67xq1hYER+elhm9dSyRBFBwpabv5eNH
+4cZuvhlv4kJiIkXqohmhU1iQg4L5sKgXY9M8+MDsOr9SyCnAb7P/VyL2WsNgCB8l
+40We9feeCFQFyZi24IsusGCIGQKBgQDvwjAljmzBaTrjZlWhAEGoxCZ9yql+U7VJ
+6qu9hiSqetRDTAlo/ozFNvb5o0BCkOIg23zS48Fd99B082eYpXOpECK6rVOwdWwV
+aOQyoXIEFm4ihK/okELKaI9vsZjA7gAbIyzLMPPnXL3zGYk+yQbOBEuOBBa8o478
+lFhvgW55XwKBgH9wJK7CqNvsLWPTn6SDJL77aRTYE1oD9OAESfWbj9KHmeDHEEgP
+zNXA7NkVHhcow3TnFQGJVK0Ab0m2kiOMM9kRtsKzS2RU0EEU4+LqMLun05tFzqLz
+DSWT5aDV96zOSrvT79r47sisfYjV/zil4Aj5r1nVfcsi4GOTkqp07wTZAoGBAOFH
+Wkv/nkrBYJbI0g6cmhVEcVJi+Y18g+w3NzW2dH9HOGkfafwgqg6ojbmU3k1tqzvq
+YEgbvtZXgqRRDPdOBvZE9gznzaoROwSG8VxtfB9BIC0I9eyUmF1tj9EIU5p8Rtc4
+3t7xWUv8RXLFfMLkyqMLQB7p0p9fI3xKuynSuQYLAoGAPK8qQvaR91sZLAvfkEYT
+jeIAwr7ExN6W+lIO9FW9ctfCu/aePTsGSmH6TX0JIZN/6lZcTamaY45IRxJh7TgD
+ZHBSRxkYIGQcsH2Eb6MwouQYuFWWicf3dY+oI0wejLZ+1TsBRJSsegV/36KgWVw3
+gAbhy0D+TKSGwK1tBLgKnB8=
+-----END PRIVATE KEY-----
diff --git a/logsrvd/regress/logsrvd_conf/sudo_logsrvd.conf.1.in b/logsrvd/regress/logsrvd_conf/sudo_logsrvd.conf.1.in
new file mode 100644
index 0000000..ab92b8b
--- /dev/null
+++ b/logsrvd/regress/logsrvd_conf/sudo_logsrvd.conf.1.in
@@ -0,0 +1,252 @@
+#
+# sudo logsrv daemon configuration
+#
+
+[server]
+# The host name or IP address and port to listen on with an optional TLS
+# flag. If no port is specified, port 30343 will be used for plaintext
+# connections and port 30344 will be used to TLS connections.
+# The following forms are accepted:
+# listen_address = hostname(tls)
+# listen_address = hostname:port(tls)
+# listen_address = IPv4_address(tls)
+# listen_address = IPv4_address:port(tls)
+# listen_address = [IPv6_address](tls)
+# listen_address = [IPv6_address]:port(tls)
+#
+# The (tls) suffix should be omitted for plaintext connections.
+#
+# Multiple listen_address settings may be specified.
+# The default is to listen on all addresses.
+listen_address = *:30343
+#listen_address = *:30344(tls)
+
+# The file containing the ID of the running sudo_logsrvd process.
+pid_file = /var/run/sudo/sudo_logsrvd.pid
+
+# Where to log server warnings: none, stderr, syslog, or a path name.
+server_log = syslog
+
+# If true, enable the SO_KEEPALIVE socket option on client connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the client to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server will validate its own certificate at startup.
+# Defaults to true.
+#tls_verify = true
+
+# If true, client certificates will be validated by the server;
+# clients without a valid certificate will be unable to connect.
+# By default, client certs are not checked.
+#tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+#tls_cacert = regress/logsrvd_conf/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# Required for TLS connections.
+#tls_cert = regress/logsrvd_conf/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# Required for TLS connections.
+#tls_key = regress/logsrvd_conf/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# This setting is only effective if the negotiated protocol is TLS version
+# 1.2. The default cipher list is HIGH:!aNULL.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default cipher list is TLS_AES_256_GCM_SHA384.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# If not set, the server will use the OpenSSL defaults.
+#tls_dhparams = regress/logsrvd_conf/logsrvd_dhparams.pem
+
+[relay]
+# The host name or IP address and port to send logs to in relay mode.
+# The syntax is identical to listen_address with the exception of
+# the wild card ('*') syntax. When this setting is enabled, logs will
+# be relayed to the specified host instead of being stored locally.
+# This setting is not enabled by default.
+#relay_host = relayhost.dom.ain
+relay_host = 127.0.0.1
+
+# The amount of time, in seconds, the server will wait for a connection
+# to the relay server to complete. A value of 0 will disable the timeout.
+# The default value is 30.
+connect_timeout = 30
+
+# The directory to store messages in before they are sent to the relay.
+# Messages are stored in wire format.
+# The default value is /var/log/sudo_logsrvd.
+relay_dir = /var/log/sudo_logsrvd
+
+# The number of seconds to wait after a connection error before
+# making a new attempt to forward a message to a relay host.
+# The default value is 30.
+retry_interval = 30
+
+# Whether to store the log before relaying it. If true, enable store
+# and forward mode. If false, the client connection is immediately
+# relayed. Defaults to false.
+store_first = true
+
+# If true, enable the SO_KEEPALIVE socket option on relay connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the relay to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server's relay certificate will be verified at startup.
+# The default is to use the value in the [server] section.
+#tls_verify = true
+
+# Whether to verify the relay's certificate for TLS connections.
+# The default is to use the value in the [server] section.
+#tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+# The default is to use the value in the [server] section.
+#tls_cacert = regress/logsrvd_conf/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# The default is to use the certificate in the [server] section.
+#tls_cert = regress/logsrvd_conf/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# The default is to use the key in the [server] section.
+#tls_key = regress/logsrvd_conf/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# this setting is only effective if the negotiated protocol is TLS version
+# 1.2. The default is to use the value in the [server] section.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default is to use the value in the [server] section.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# The default is to use the value in the [server] section.
+#tls_dhparams = regress/logsrvd_conf/logsrvd_dhparams.pem
+
+[iolog]
+# The top-level directory to use when constructing the path name for the
+# I/O log directory. The session sequence number, if any, is stored here.
+iolog_dir = /var/log/sudo-io
+
+# The path name, relative to iolog_dir, in which to store I/O logs.
+# It is possible for iolog_file to contain directory components.
+iolog_file = %{seq}
+
+# If set, I/O logs will be compressed using zlib. Enabling compression can
+# make it harder to view the logs in real-time as the program is executing.
+iolog_compress = false
+
+# If set, I/O log data is flushed to disk after each write instead of
+# buffering it. This makes it possible to view the logs in real-time
+# as the program is executing but reduces the effectiveness of compression.
+iolog_flush = true
+
+# The group to use when creating new I/O log files and directories.
+# If iolog_group is not set, the primary group-ID of the user specified
+# by iolog_user is used. If neither iolog_group nor iolog_user
+# are set, I/O log files and directories are created with group-ID 0.
+#iolog_group = wheel
+
+# The user to use when setting the user-ID and group-ID of new I/O
+# log files and directories. If iolog_group is set, it will be used
+# instead of the user's primary group-ID. By default, I/O log files
+# and directories are created with user and group-ID 0.
+#iolog_user = root
+
+# The file mode to use when creating I/O log files. The file permissions
+# will always include the owner read and write bits, even if they are
+# not present in the specified mode. When creating I/O log directories,
+# search (execute) bits are added to match the read and write bits
+# specified by iolog_mode.
+iolog_mode = 0600
+
+# If disabled, sudo_logsrvd will attempt to avoid logging plaintext
+# password in the terminal input using passprompt_regex.
+log_passwords = true
+
+# The maximum sequence number that will be substituted for the "%{seq}"
+# escape in the I/O log file. While the value substituted for "%{seq}"
+# is in base 36, maxseq itself should be expressed in decimal. Values
+# larger than 2176782336 (which corresponds to the base 36 sequence
+# number "ZZZZZZ") will be silently truncated to 2176782336.
+maxseq = 2176782336
+
+# One or more POSIX extended regular expressions used to match
+# password prompts in the terminal output when log_passwords is
+# disabled. Multiple passprompt_regex settings may be specified.
+#passprompt_regex = [Pp]assword[: ]*
+passprompt_regex = [Pp]assword for [a-z0-9]+: *
+
+[eventlog]
+# Where to log accept, reject, exit, and alert events.
+# Accepted values are syslog, logfile, or none.
+# Defaults to syslog
+log_type = syslog
+
+# Whether to log an event when a command exits or is terminated by a signal.
+# Defaults to false
+log_exit = true
+
+# Event log format.
+# Supported log formats are "sudo" and "json"
+# Defaults to sudo
+log_format = sudo
+
+[syslog]
+# The maximum length of a syslog payload.
+# On many systems, syslog(3) has a relatively small log buffer.
+# IETF RFC 5424 states that syslog servers must support messages
+# of at least 480 bytes and should support messages up to 2048 bytes.
+# Messages larger than this value will be split into multiple messages.
+maxlen = 960
+
+# The syslog facility to use for event log messages.
+# The following syslog facilities are supported: authpriv (if your OS
+# supports it), auth, daemon, user, local0, local1, local2, local3,
+# local4, local5, local6, and local7.
+#facility = authpriv
+facility = auth
+
+# Syslog priority to use for event log accept messages, when the command
+# is allowed by the security policy. The following syslog priorities are
+# supported: alert, crit, debug, emerg, err, info, notice, warning, none.
+accept_priority = notice
+
+# Syslog priority to use for event log reject messages, when the command
+# is not allowed by the security policy.
+reject_priority = alert
+
+# Syslog priority to use for event log alert messages reported by the
+# client.
+alert_priority = alert
+
+# The syslog facility to use for server warning messages.
+# Defaults to daemon.
+server_facility = daemon
+
+[logfile]
+# The path to the file-based event log.
+# This path must be fully-qualified and start with a '/' character.
+path = /var/log/sudo.log
+
+# The format string used when formatting the date and time for
+# file-based event logs. Formatting is performed via strftime(3) so
+# any format string supported by that function is allowed.
+time_format = %h %e %T
diff --git a/logsrvd/regress/logsrvd_conf/sudo_logsrvd.conf.2.in b/logsrvd/regress/logsrvd_conf/sudo_logsrvd.conf.2.in
new file mode 100644
index 0000000..01b91ff
--- /dev/null
+++ b/logsrvd/regress/logsrvd_conf/sudo_logsrvd.conf.2.in
@@ -0,0 +1,252 @@
+#
+# sudo logsrv daemon configuration
+#
+
+[server]
+# The host name or IP address and port to listen on with an optional TLS
+# flag. If no port is specified, port 30343 will be used for plaintext
+# connections and port 30344 will be used to TLS connections.
+# The following forms are accepted:
+# listen_address = hostname(tls)
+# listen_address = hostname:port(tls)
+# listen_address = IPv4_address(tls)
+# listen_address = IPv4_address:port(tls)
+# listen_address = [IPv6_address](tls)
+# listen_address = [IPv6_address]:port(tls)
+#
+# The (tls) suffix should be omitted for plaintext connections.
+#
+# Multiple listen_address settings may be specified.
+# The default is to listen on all addresses.
+listen_address = 172.0.0.1:30343
+#listen_address = 172.0.0.1:30344(tls)
+
+# The file containing the ID of the running sudo_logsrvd process.
+pid_file = /var/run/sudo/sudo_logsrvd.pid
+
+# Where to log server warnings: none, stderr, syslog, or a path name.
+server_log = stderr
+
+# If true, enable the SO_KEEPALIVE socket option on client connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the client to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server will validate its own certificate at startup.
+# Defaults to true.
+#tls_verify = false
+
+# If true, client certificates will be validated by the server;
+# clients without a valid certificate will be unable to connect.
+# By default, client certs are not checked.
+#tls_checkpeer = true
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+#tls_cacert = regress/logsrvd_conf/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# Required for TLS connections.
+#tls_cert = regress/logsrvd_conf/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# Required for TLS connections.
+#tls_key = regress/logsrvd_conf/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# This setting is only effective if the negotiated protocol is TLS version
+# 1.2. The default cipher list is HIGH:!aNULL.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default cipher list is TLS_AES_256_GCM_SHA384.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# If not set, the server will use the OpenSSL defaults.
+#tls_dhparams = regress/logsrvd_conf/logsrvd_dhparams.pem
+
+[relay]
+# The host name or IP address and port to send logs to in relay mode.
+# The syntax is identical to listen_address with the exception of
+# the wild card ('*') syntax. When this setting is enabled, logs will
+# be relayed to the specified host instead of being stored locally.
+# This setting is not enabled by default.
+#relay_host = relayhost.dom.ain
+relay_host = 127.0.0.1
+
+# The amount of time, in seconds, the server will wait for a connection
+# to the relay server to complete. A value of 0 will disable the timeout.
+# The default value is 30.
+connect_timeout = 30
+
+# The directory to store messages in before they are sent to the relay.
+# Messages are stored in wire format.
+# The default value is /var/log/sudo_logsrvd.
+relay_dir = /var/log/sudo_logsrvd
+
+# The number of seconds to wait after a connection error before
+# making a new attempt to forward a message to a relay host.
+# The default value is 30.
+retry_interval = 30
+
+# Whether to store the log before relaying it. If true, enable store
+# and forward mode. If false, the client connection is immediately
+# relayed. Defaults to false.
+store_first = true
+
+# If true, enable the SO_KEEPALIVE socket option on relay connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the relay to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server's relay certificate will be verified at startup.
+# The default is to use the value in the [server] section.
+#tls_verify = true
+
+# Whether to verify the relay's certificate for TLS connections.
+# The default is to use the value in the [server] section.
+#tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+# The default is to use the value in the [server] section.
+#tls_cacert = regress/logsrvd_conf/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# The default is to use the certificate in the [server] section.
+#tls_cert = regress/logsrvd_conf/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# The default is to use the key in the [server] section.
+#tls_key = regress/logsrvd_conf/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# this setting is only effective if the negotiated protocol is TLS version
+# 1.2. The default is to use the value in the [server] section.
+#tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default is to use the value in the [server] section.
+#tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# The default is to use the value in the [server] section.
+#tls_dhparams = regress/logsrvd_conf/logsrvd_dhparams.pem
+
+[iolog]
+# The top-level directory to use when constructing the path name for the
+# I/O log directory. The session sequence number, if any, is stored here.
+iolog_dir = /var/log/sudo-io
+
+# The path name, relative to iolog_dir, in which to store I/O logs.
+# It is possible for iolog_file to contain directory components.
+iolog_file = %{seq}
+
+# If set, I/O logs will be compressed using zlib. Enabling compression can
+# make it harder to view the logs in real-time as the program is executing.
+iolog_compress = false
+
+# If set, I/O log data is flushed to disk after each write instead of
+# buffering it. This makes it possible to view the logs in real-time
+# as the program is executing but reduces the effectiveness of compression.
+iolog_flush = true
+
+# The group to use when creating new I/O log files and directories.
+# If iolog_group is not set, the primary group-ID of the user specified
+# by iolog_user is used. If neither iolog_group nor iolog_user
+# are set, I/O log files and directories are created with group-ID 0.
+#iolog_group = wheel
+
+# The user to use when setting the user-ID and group-ID of new I/O
+# log files and directories. If iolog_group is set, it will be used
+# instead of the user's primary group-ID. By default, I/O log files
+# and directories are created with user and group-ID 0.
+#iolog_user = root
+
+# The file mode to use when creating I/O log files. The file permissions
+# will always include the owner read and write bits, even if they are
+# not present in the specified mode. When creating I/O log directories,
+# search (execute) bits are added to match the read and write bits
+# specified by iolog_mode.
+iolog_mode = 0600
+
+# If disabled, sudo_logsrvd will attempt to avoid logging plaintext
+# password in the terminal input using passprompt_regex.
+log_passwords = true
+
+# The maximum sequence number that will be substituted for the "%{seq}"
+# escape in the I/O log file. While the value substituted for "%{seq}"
+# is in base 36, maxseq itself should be expressed in decimal. Values
+# larger than 2176782336 (which corresponds to the base 36 sequence
+# number "ZZZZZZ") will be silently truncated to 2176782336.
+maxseq = 2176782336
+
+# One or more POSIX extended regular expressions used to match
+# password prompts in the terminal output when log_passwords is
+# disabled. Multiple passprompt_regex settings may be specified.
+#passprompt_regex = [Pp]assword[: ]*
+passprompt_regex = [Pp]assword for [a-z0-9]+: *
+
+[eventlog]
+# Where to log accept, reject, exit, and alert events.
+# Accepted values are syslog, logfile, or none.
+# Defaults to syslog
+log_type = none
+
+# Whether to log an event when a command exits or is terminated by a signal.
+# Defaults to false
+log_exit = true
+
+# Event log format.
+# Supported log formats are "sudo" and "json"
+# Defaults to sudo
+log_format = json
+
+[syslog]
+# The maximum length of a syslog payload.
+# On many systems, syslog(3) has a relatively small log buffer.
+# IETF RFC 5424 states that syslog servers must support messages
+# of at least 480 bytes and should support messages up to 2048 bytes.
+# Messages larger than this value will be split into multiple messages.
+maxlen = 960
+
+# The syslog facility to use for event log messages.
+# The following syslog facilities are supported: authpriv (if your OS
+# supports it), auth, daemon, user, local0, local1, local2, local3,
+# local4, local5, local6, and local7.
+#facility = authpriv
+facility = daemon
+
+# Syslog priority to use for event log accept messages, when the command
+# is allowed by the security policy. The following syslog priorities are
+# supported: alert, crit, debug, emerg, err, info, notice, warning, none.
+accept_priority = notice
+
+# Syslog priority to use for event log reject messages, when the command
+# is not allowed by the security policy.
+reject_priority = alert
+
+# Syslog priority to use for event log alert messages reported by the
+# client.
+alert_priority = alert
+
+# The syslog facility to use for server warning messages.
+# Defaults to daemon.
+server_facility = daemon
+
+[logfile]
+# The path to the file-based event log.
+# This path must be fully-qualified and start with a '/' character.
+path = /var/log/sudo.log
+
+# The format string used when formatting the date and time for
+# file-based event logs. Formatting is performed via strftime(3) so
+# any format string supported by that function is allowed.
+time_format = %h %e %T
diff --git a/logsrvd/regress/logsrvd_conf/tls/sudo_logsrvd.conf.1.in b/logsrvd/regress/logsrvd_conf/tls/sudo_logsrvd.conf.1.in
new file mode 100644
index 0000000..6d97f44
--- /dev/null
+++ b/logsrvd/regress/logsrvd_conf/tls/sudo_logsrvd.conf.1.in
@@ -0,0 +1,252 @@
+#
+# sudo logsrv daemon configuration
+#
+
+[server]
+# The host name or IP address and port to listen on with an optional TLS
+# flag. If no port is specified, port 30343 will be used for plaintext
+# connections and port 30344 will be used to TLS connections.
+# The following forms are accepted:
+# listen_address = hostname(tls)
+# listen_address = hostname:port(tls)
+# listen_address = IPv4_address(tls)
+# listen_address = IPv4_address:port(tls)
+# listen_address = [IPv6_address](tls)
+# listen_address = [IPv6_address]:port(tls)
+#
+# The (tls) suffix should be omitted for plaintext connections.
+#
+# Multiple listen_address settings may be specified.
+# The default is to listen on all addresses.
+listen_address = *:30343
+listen_address = *:30344(tls)
+
+# The file containing the ID of the running sudo_logsrvd process.
+pid_file = /var/run/sudo/sudo_logsrvd.pid
+
+# Where to log server warnings: none, stderr, syslog, or a path name.
+server_log = syslog
+
+# If true, enable the SO_KEEPALIVE socket option on client connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the client to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server will validate its own certificate at startup.
+# Defaults to true.
+tls_verify = true
+
+# If true, client certificates will be validated by the server;
+# clients without a valid certificate will be unable to connect.
+# By default, client certs are not checked.
+tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+tls_cacert = regress/logsrvd_conf/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# Required for TLS connections.
+tls_cert = regress/logsrvd_conf/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# Required for TLS connections.
+tls_key = regress/logsrvd_conf/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# This setting is only effective if the negotiated protocol is TLS version
+# 1.2. The default cipher list is HIGH:!aNULL.
+tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default cipher list is TLS_AES_256_GCM_SHA384.
+tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# If not set, the server will use the OpenSSL defaults.
+tls_dhparams = regress/logsrvd_conf/logsrvd_dhparams.pem
+
+[relay]
+# The host name or IP address and port to send logs to in relay mode.
+# The syntax is identical to listen_address with the exception of
+# the wild card ('*') syntax. When this setting is enabled, logs will
+# be relayed to the specified host instead of being stored locally.
+# This setting is not enabled by default.
+#relay_host = relayhost.dom.ain
+relay_host = 127.0.0.1(tls)
+
+# The amount of time, in seconds, the server will wait for a connection
+# to the relay server to complete. A value of 0 will disable the timeout.
+# The default value is 30.
+connect_timeout = 30
+
+# The directory to store messages in before they are sent to the relay.
+# Messages are stored in wire format.
+# The default value is /var/log/sudo_logsrvd.
+relay_dir = /var/log/sudo_logsrvd
+
+# The number of seconds to wait after a connection error before
+# making a new attempt to forward a message to a relay host.
+# The default value is 30.
+retry_interval = 30
+
+# Whether to store the log before relaying it. If true, enable store
+# and forward mode. If false, the client connection is immediately
+# relayed. Defaults to false.
+store_first = true
+
+# If true, enable the SO_KEEPALIVE socket option on relay connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the relay to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server's relay certificate will be verified at startup.
+# The default is to use the value in the [server] section.
+tls_verify = true
+
+# Whether to verify the relay's certificate for TLS connections.
+# The default is to use the value in the [server] section.
+tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+# The default is to use the value in the [server] section.
+tls_cacert = regress/logsrvd_conf/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# The default is to use the certificate in the [server] section.
+tls_cert = regress/logsrvd_conf/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# The default is to use the key in the [server] section.
+tls_key = regress/logsrvd_conf/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# this setting is only effective if the negotiated protocol is TLS version
+# 1.2. The default is to use the value in the [server] section.
+tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default is to use the value in the [server] section.
+tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# The default is to use the value in the [server] section.
+tls_dhparams = regress/logsrvd_conf/logsrvd_dhparams.pem
+
+[iolog]
+# The top-level directory to use when constructing the path name for the
+# I/O log directory. The session sequence number, if any, is stored here.
+iolog_dir = /var/log/sudo-io
+
+# The path name, relative to iolog_dir, in which to store I/O logs.
+# It is possible for iolog_file to contain directory components.
+iolog_file = %{seq}
+
+# If set, I/O logs will be compressed using zlib. Enabling compression can
+# make it harder to view the logs in real-time as the program is executing.
+iolog_compress = false
+
+# If set, I/O log data is flushed to disk after each write instead of
+# buffering it. This makes it possible to view the logs in real-time
+# as the program is executing but reduces the effectiveness of compression.
+iolog_flush = true
+
+# The group to use when creating new I/O log files and directories.
+# If iolog_group is not set, the primary group-ID of the user specified
+# by iolog_user is used. If neither iolog_group nor iolog_user
+# are set, I/O log files and directories are created with group-ID 0.
+#iolog_group = wheel
+
+# The user to use when setting the user-ID and group-ID of new I/O
+# log files and directories. If iolog_group is set, it will be used
+# instead of the user's primary group-ID. By default, I/O log files
+# and directories are created with user and group-ID 0.
+#iolog_user = root
+
+# The file mode to use when creating I/O log files. The file permissions
+# will always include the owner read and write bits, even if they are
+# not present in the specified mode. When creating I/O log directories,
+# search (execute) bits are added to match the read and write bits
+# specified by iolog_mode.
+iolog_mode = 0600
+
+# If disabled, sudo_logsrvd will attempt to avoid logging plaintext
+# password in the terminal input using passprompt_regex.
+log_passwords = true
+
+# The maximum sequence number that will be substituted for the "%{seq}"
+# escape in the I/O log file. While the value substituted for "%{seq}"
+# is in base 36, maxseq itself should be expressed in decimal. Values
+# larger than 2176782336 (which corresponds to the base 36 sequence
+# number "ZZZZZZ") will be silently truncated to 2176782336.
+maxseq = 2176782336
+
+# One or more POSIX extended regular expressions used to match
+# password prompts in the terminal output when log_passwords is
+# disabled. Multiple passprompt_regex settings may be specified.
+#passprompt_regex = [Pp]assword[: ]*
+passprompt_regex = [Pp]assword for [a-z0-9]+: *
+
+[eventlog]
+# Where to log accept, reject, exit, and alert events.
+# Accepted values are syslog, logfile, or none.
+# Defaults to syslog
+log_type = syslog
+
+# Whether to log an event when a command exits or is terminated by a signal.
+# Defaults to false
+log_exit = true
+
+# Event log format.
+# Supported log formats are "sudo" and "json"
+# Defaults to sudo
+log_format = sudo
+
+[syslog]
+# The maximum length of a syslog payload.
+# On many systems, syslog(3) has a relatively small log buffer.
+# IETF RFC 5424 states that syslog servers must support messages
+# of at least 480 bytes and should support messages up to 2048 bytes.
+# Messages larger than this value will be split into multiple messages.
+maxlen = 960
+
+# The syslog facility to use for event log messages.
+# The following syslog facilities are supported: authpriv (if your OS
+# supports it), auth, daemon, user, local0, local1, local2, local3,
+# local4, local5, local6, and local7.
+#facility = authpriv
+facility = auth
+
+# Syslog priority to use for event log accept messages, when the command
+# is allowed by the security policy. The following syslog priorities are
+# supported: alert, crit, debug, emerg, err, info, notice, warning, none.
+accept_priority = notice
+
+# Syslog priority to use for event log reject messages, when the command
+# is not allowed by the security policy.
+reject_priority = alert
+
+# Syslog priority to use for event log alert messages reported by the
+# client.
+alert_priority = alert
+
+# The syslog facility to use for server warning messages.
+# Defaults to daemon.
+server_facility = daemon
+
+[logfile]
+# The path to the file-based event log.
+# This path must be fully-qualified and start with a '/' character.
+path = /var/log/sudo.log
+
+# The format string used when formatting the date and time for
+# file-based event logs. Formatting is performed via strftime(3) so
+# any format string supported by that function is allowed.
+time_format = %h %e %T
diff --git a/logsrvd/regress/logsrvd_conf/tls/sudo_logsrvd.conf.2.in b/logsrvd/regress/logsrvd_conf/tls/sudo_logsrvd.conf.2.in
new file mode 100644
index 0000000..0e71f67
--- /dev/null
+++ b/logsrvd/regress/logsrvd_conf/tls/sudo_logsrvd.conf.2.in
@@ -0,0 +1,252 @@
+#
+# sudo logsrv daemon configuration
+#
+
+[server]
+# The host name or IP address and port to listen on with an optional TLS
+# flag. If no port is specified, port 30343 will be used for plaintext
+# connections and port 30344 will be used to TLS connections.
+# The following forms are accepted:
+# listen_address = hostname(tls)
+# listen_address = hostname:port(tls)
+# listen_address = IPv4_address(tls)
+# listen_address = IPv4_address:port(tls)
+# listen_address = [IPv6_address](tls)
+# listen_address = [IPv6_address]:port(tls)
+#
+# The (tls) suffix should be omitted for plaintext connections.
+#
+# Multiple listen_address settings may be specified.
+# The default is to listen on all addresses.
+listen_address = 172.0.0.1:30343
+listen_address = 172.0.0.1:30344(tls)
+
+# The file containing the ID of the running sudo_logsrvd process.
+pid_file = /var/run/sudo/sudo_logsrvd.pid
+
+# Where to log server warnings: none, stderr, syslog, or a path name.
+server_log = stderr
+
+# If true, enable the SO_KEEPALIVE socket option on client connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the client to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server will validate its own certificate at startup.
+# Defaults to true.
+tls_verify = false
+
+# If true, client certificates will be validated by the server;
+# clients without a valid certificate will be unable to connect.
+# By default, client certs are not checked.
+tls_checkpeer = true
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+tls_cacert = regress/logsrvd_conf/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# Required for TLS connections.
+tls_cert = regress/logsrvd_conf/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# Required for TLS connections.
+tls_key = regress/logsrvd_conf/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# This setting is only effective if the negotiated protocol is TLS version
+# 1.2. The default cipher list is HIGH:!aNULL.
+tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default cipher list is TLS_AES_256_GCM_SHA384.
+tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# If not set, the server will use the OpenSSL defaults.
+tls_dhparams = regress/logsrvd_conf/logsrvd_dhparams.pem
+
+[relay]
+# The host name or IP address and port to send logs to in relay mode.
+# The syntax is identical to listen_address with the exception of
+# the wild card ('*') syntax. When this setting is enabled, logs will
+# be relayed to the specified host instead of being stored locally.
+# This setting is not enabled by default.
+#relay_host = relayhost.dom.ain
+relay_host = 127.0.0.1(tls)
+
+# The amount of time, in seconds, the server will wait for a connection
+# to the relay server to complete. A value of 0 will disable the timeout.
+# The default value is 30.
+connect_timeout = 30
+
+# The directory to store messages in before they are sent to the relay.
+# Messages are stored in wire format.
+# The default value is /var/log/sudo_logsrvd.
+relay_dir = /var/log/sudo_logsrvd
+
+# The number of seconds to wait after a connection error before
+# making a new attempt to forward a message to a relay host.
+# The default value is 30.
+retry_interval = 30
+
+# Whether to store the log before relaying it. If true, enable store
+# and forward mode. If false, the client connection is immediately
+# relayed. Defaults to false.
+store_first = true
+
+# If true, enable the SO_KEEPALIVE socket option on relay connections.
+# Defaults to true.
+tcp_keepalive = true
+
+# The amount of time, in seconds, the server will wait for the relay to
+# respond. A value of 0 will disable the timeout. The default value is 30.
+timeout = 30
+
+# If true, the server's relay certificate will be verified at startup.
+# The default is to use the value in the [server] section.
+tls_verify = true
+
+# Whether to verify the relay's certificate for TLS connections.
+# The default is to use the value in the [server] section.
+tls_checkpeer = false
+
+# Path to a certificate authority bundle file in PEM format to use
+# instead of the system's default certificate authority database.
+# The default is to use the value in the [server] section.
+tls_cacert = regress/logsrvd_conf/cacert.pem
+
+# Path to the server's certificate file in PEM format.
+# The default is to use the certificate in the [server] section.
+tls_cert = regress/logsrvd_conf/logsrvd_cert.pem
+
+# Path to the server's private key file in PEM format.
+# The default is to use the key in the [server] section.
+tls_key = regress/logsrvd_conf/logsrvd_key.pem
+
+# TLS cipher list (see "CIPHER LIST FORMAT" in the openssl-ciphers manual).
+# this setting is only effective if the negotiated protocol is TLS version
+# 1.2. The default is to use the value in the [server] section.
+tls_ciphers_v12 = HIGH:!aNULL
+
+# TLS cipher list if the negotiated protocol is TLS version 1.3.
+# The default is to use the value in the [server] section.
+tls_ciphers_v13 = TLS_AES_256_GCM_SHA384
+
+# Path to the Diffie-Hellman parameter file in PEM format.
+# The default is to use the value in the [server] section.
+tls_dhparams = regress/logsrvd_conf/logsrvd_dhparams.pem
+
+[iolog]
+# The top-level directory to use when constructing the path name for the
+# I/O log directory. The session sequence number, if any, is stored here.
+iolog_dir = /var/log/sudo-io
+
+# The path name, relative to iolog_dir, in which to store I/O logs.
+# It is possible for iolog_file to contain directory components.
+iolog_file = %{seq}
+
+# If set, I/O logs will be compressed using zlib. Enabling compression can
+# make it harder to view the logs in real-time as the program is executing.
+iolog_compress = false
+
+# If set, I/O log data is flushed to disk after each write instead of
+# buffering it. This makes it possible to view the logs in real-time
+# as the program is executing but reduces the effectiveness of compression.
+iolog_flush = true
+
+# The group to use when creating new I/O log files and directories.
+# If iolog_group is not set, the primary group-ID of the user specified
+# by iolog_user is used. If neither iolog_group nor iolog_user
+# are set, I/O log files and directories are created with group-ID 0.
+#iolog_group = wheel
+
+# The user to use when setting the user-ID and group-ID of new I/O
+# log files and directories. If iolog_group is set, it will be used
+# instead of the user's primary group-ID. By default, I/O log files
+# and directories are created with user and group-ID 0.
+#iolog_user = root
+
+# The file mode to use when creating I/O log files. The file permissions
+# will always include the owner read and write bits, even if they are
+# not present in the specified mode. When creating I/O log directories,
+# search (execute) bits are added to match the read and write bits
+# specified by iolog_mode.
+iolog_mode = 0600
+
+# If disabled, sudo_logsrvd will attempt to avoid logging plaintext
+# password in the terminal input using passprompt_regex.
+log_passwords = true
+
+# The maximum sequence number that will be substituted for the "%{seq}"
+# escape in the I/O log file. While the value substituted for "%{seq}"
+# is in base 36, maxseq itself should be expressed in decimal. Values
+# larger than 2176782336 (which corresponds to the base 36 sequence
+# number "ZZZZZZ") will be silently truncated to 2176782336.
+maxseq = 2176782336
+
+# One or more POSIX extended regular expressions used to match
+# password prompts in the terminal output when log_passwords is
+# disabled. Multiple passprompt_regex settings may be specified.
+#passprompt_regex = [Pp]assword[: ]*
+passprompt_regex = [Pp]assword for [a-z0-9]+: *
+
+[eventlog]
+# Where to log accept, reject, exit, and alert events.
+# Accepted values are syslog, logfile, or none.
+# Defaults to syslog
+log_type = none
+
+# Whether to log an event when a command exits or is terminated by a signal.
+# Defaults to false
+log_exit = true
+
+# Event log format.
+# Supported log formats are "sudo" and "json"
+# Defaults to sudo
+log_format = json
+
+[syslog]
+# The maximum length of a syslog payload.
+# On many systems, syslog(3) has a relatively small log buffer.
+# IETF RFC 5424 states that syslog servers must support messages
+# of at least 480 bytes and should support messages up to 2048 bytes.
+# Messages larger than this value will be split into multiple messages.
+maxlen = 960
+
+# The syslog facility to use for event log messages.
+# The following syslog facilities are supported: authpriv (if your OS
+# supports it), auth, daemon, user, local0, local1, local2, local3,
+# local4, local5, local6, and local7.
+#facility = authpriv
+facility = daemon
+
+# Syslog priority to use for event log accept messages, when the command
+# is allowed by the security policy. The following syslog priorities are
+# supported: alert, crit, debug, emerg, err, info, notice, warning, none.
+accept_priority = notice
+
+# Syslog priority to use for event log reject messages, when the command
+# is not allowed by the security policy.
+reject_priority = alert
+
+# Syslog priority to use for event log alert messages reported by the
+# client.
+alert_priority = alert
+
+# The syslog facility to use for server warning messages.
+# Defaults to daemon.
+server_facility = daemon
+
+[logfile]
+# The path to the file-based event log.
+# This path must be fully-qualified and start with a '/' character.
+path = /var/log/sudo.log
+
+# The format string used when formatting the date and time for
+# file-based event logs. Formatting is performed via strftime(3) so
+# any format string supported by that function is allowed.
+time_format = %h %e %T
diff --git a/logsrvd/sendlog.c b/logsrvd/sendlog.c
new file mode 100644
index 0000000..0ebc2ad
--- /dev/null
+++ b/logsrvd/sendlog.c
@@ -0,0 +1,1927 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <netdb.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#ifndef HAVE_GETADDRINFO
+# include <compat/getaddrinfo.h>
+#endif
+#ifdef HAVE_GETOPT_LONG
+# include <getopt.h>
+# else
+# include <compat/getopt.h>
+#endif /* HAVE_GETOPT_LONG */
+
+#include <sudo_compat.h>
+#include <sudo_conf.h>
+#include <sudo_debug.h>
+#include <sudo_event.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_iolog.h>
+#include <sudo_util.h>
+
+#include "sendlog.h"
+#include <hostcheck.h>
+
+#if defined(HAVE_OPENSSL)
+# define TLS_HANDSHAKE_TIMEO_SEC 10
+#endif
+
+TAILQ_HEAD(connection_list, client_closure);
+static struct connection_list connections = TAILQ_HEAD_INITIALIZER(connections);
+
+static struct peer_info server_info = { "localhost" };
+static char *iolog_dir;
+static bool testrun = false;
+static int nr_of_conns = 1;
+static int finished_transmissions = 0;
+
+#if defined(HAVE_OPENSSL)
+static SSL_CTX *ssl_ctx = NULL;
+static const char *ca_bundle = NULL;
+static const char *cert = NULL;
+static const char *key = NULL;
+static bool verify_server = true;
+#endif
+
+/* Server callback may redirect to client callback for TLS. */
+static void client_msg_cb(int fd, int what, void *v);
+static void server_msg_cb(int fd, int what, void *v);
+
+static void
+display_usage(FILE *fp)
+{
+#if defined(HAVE_OPENSSL)
+ fprintf(fp, "usage: %s [-AnV] [-b ca_bundle] [-c cert_file] [-h host] "
+ "[-i iolog-id] [-k key_file] [-p port] "
+#else
+ fprintf(fp, "usage: %s [-AnV] [-h host] [-i iolog-id] [-p port] "
+#endif
+ "[-r restart-point] [-R reject-reason] [-s stop-point] [-t number] /path/to/iolog\n",
+ getprogname());
+}
+
+sudo_noreturn static void
+usage(void)
+{
+ display_usage(stderr);
+ exit(EXIT_FAILURE);
+}
+
+sudo_noreturn static void
+help(void)
+{
+ printf("%s - %s\n\n", getprogname(),
+ _("send sudo I/O log to remote server"));
+ display_usage(stdout);
+ printf("\n%s\n", _("Options:"));
+ printf(" --help %s\n",
+ _("display help message and exit"));
+ printf(" -A, --accept %s\n",
+ _("only send an accept event (no I/O)"));
+#if defined(HAVE_OPENSSL)
+ printf(" -b, --ca-bundle %s\n",
+ _("certificate bundle file to verify server's cert against"));
+ printf(" -c, --cert %s\n",
+ _("certificate file for TLS handshake"));
+#endif
+ printf(" -h, --host %s\n",
+ _("host to send logs to"));
+ printf(" -i, --iolog_id %s\n",
+ _("remote ID of I/O log to be resumed"));
+#if defined(HAVE_OPENSSL)
+ printf(" -k, --key %s\n",
+ _("private key file"));
+ printf(" -n, --no-verify %s\n",
+ _("do not verify server certificate"));
+#endif
+ printf(" -p, --port %s\n",
+ _("port to use when connecting to host"));
+ printf(" -r, --restart %s\n",
+ _("restart previous I/O log transfer"));
+ printf(" -R, --reject %s\n",
+ _("reject the command with the given reason"));
+ printf(" -s, --stop-after %s\n",
+ _("stop transfer after reaching this time"));
+ printf(" -t, --test %s\n",
+ _("test audit server by sending selected I/O log n times in parallel"));
+ printf(" -V, --version %s\n",
+ _("display version information and exit"));
+ putchar('\n');
+ exit(EXIT_SUCCESS);
+}
+
+/*
+ * Connect to specified host:port
+ * If host has multiple addresses, the first one that connects is used.
+ * Returns open socket or -1 on error.
+ */
+static int
+connect_server(struct peer_info *server, const char *port)
+{
+ struct addrinfo hints, *res, *res0;
+ const char *addr, *cause = "getaddrinfo";
+ int error, sock, save_errno;
+ debug_decl(connect_server, SUDO_DEBUG_UTIL);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ error = getaddrinfo(server->name, port, &hints, &res0);
+ if (error != 0) {
+ sudo_warnx(U_("unable to look up %s:%s: %s"), server->name, port,
+ gai_strerror(error));
+ debug_return_int(-1);
+ }
+
+ sock = -1;
+ for (res = res0; res; res = res->ai_next) {
+ sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (sock == -1) {
+ cause = "socket";
+ continue;
+ }
+ if (connect(sock, res->ai_addr, res->ai_addrlen) == -1) {
+ cause = "connect";
+ save_errno = errno;
+ close(sock);
+ errno = save_errno;
+ sock = -1;
+ continue;
+ }
+ if (server->ipaddr[0] == '\0') {
+ switch (res->ai_family) {
+ case AF_INET:
+ addr = (char *)&((struct sockaddr_in *)res->ai_addr)->sin_addr;
+ break;
+ case AF_INET6:
+ addr = (char *)&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
+ break;
+ default:
+ cause = "ai_family";
+ save_errno = EAFNOSUPPORT;
+ close(sock);
+ errno = save_errno;
+ sock = -1;
+ continue;
+ }
+ if (inet_ntop(res->ai_family, addr, server->ipaddr,
+ sizeof(server->ipaddr)) == NULL) {
+ sudo_warnx("%s", U_("unable to get server IP addr"));
+ }
+ }
+ break; /* success */
+ }
+ freeaddrinfo(res0);
+
+ if (sock != -1) {
+ int flags = fcntl(sock, F_GETFL, 0);
+ if (flags == -1 || fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) {
+ cause = "fcntl(O_NONBLOCK)";
+ save_errno = errno;
+ close(sock);
+ errno = save_errno;
+ sock = -1;
+ }
+ }
+ if (sock == -1)
+ sudo_warn("%s", cause);
+
+ debug_return_int(sock);
+}
+
+/*
+ * Get a buffer from the free list if possible, else allocate a new one.
+ */
+static struct connection_buffer *
+get_free_buf(size_t len, struct client_closure *closure)
+{
+ struct connection_buffer *buf;
+ debug_decl(get_free_buf, SUDO_DEBUG_UTIL);
+
+ buf = TAILQ_FIRST(&closure->free_bufs);
+ if (buf != NULL) {
+ TAILQ_REMOVE(&closure->free_bufs, buf, entries);
+ } else {
+ if ((buf = calloc(1, sizeof(*buf))) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_ptr(NULL);
+ }
+ }
+
+ if (len > buf->size) {
+ free(buf->data);
+ buf->size = sudo_pow2_roundup(len);
+ if (buf->size < len || (buf->data = malloc(buf->size)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ free(buf);
+ buf = NULL;
+ }
+ }
+
+ debug_return_ptr(buf);
+}
+
+/*
+ * Read the next I/O buffer as described by closure->timing.
+ */
+static bool
+read_io_buf(struct client_closure *closure)
+{
+ struct timing_closure *timing = &closure->timing;
+ const char *errstr = NULL;
+ size_t nread;
+ debug_decl(read_io_buf, SUDO_DEBUG_UTIL);
+
+ if (!closure->iolog_files[timing->event].enabled) {
+ errno = ENOENT;
+ sudo_warn("%s/%s", iolog_dir, iolog_fd_to_name(timing->event));
+ debug_return_bool(false);
+ }
+
+ /* Expand buf as needed. */
+ if (timing->u.nbytes > closure->bufsize) {
+ const size_t new_size = sudo_pow2_roundup(timing->u.nbytes);
+ if (new_size < timing->u.nbytes) {
+ /* overflow */
+ errno = ENOMEM;
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ timing->u.nbytes = 0;
+ debug_return_bool(false);
+ }
+ free(closure->buf);
+ if ((closure->buf = malloc(new_size)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ closure->bufsize = 0;
+ timing->u.nbytes = 0;
+ debug_return_bool(false);
+ }
+ closure->bufsize = new_size;
+ }
+
+ nread = (size_t)iolog_read(&closure->iolog_files[timing->event],
+ closure->buf, timing->u.nbytes, &errstr);
+ if (nread == (size_t)-1) {
+ sudo_warnx(U_("unable to read %s/%s: %s"), iolog_dir,
+ iolog_fd_to_name(timing->event), errstr);
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+/*
+ * Format a ClientMessage and store the wire format message in buf.
+ * Returns true on success, false on failure.
+ */
+static bool
+fmt_client_message(struct client_closure *closure, ClientMessage *msg)
+{
+ struct connection_buffer *buf = NULL;
+ uint32_t msg_len;
+ bool ret = false;
+ size_t len;
+ debug_decl(fmt_client_message, SUDO_DEBUG_UTIL);
+
+ len = client_message__get_packed_size(msg);
+ if (len > MESSAGE_SIZE_MAX) {
+ sudo_warnx(U_("client message too large: %zu"), len);
+ goto done;
+ }
+ /* Wire message size is used for length encoding, precedes message. */
+ msg_len = htonl((uint32_t)len);
+ len += sizeof(msg_len);
+
+ if (!TAILQ_EMPTY(&closure->write_bufs)) {
+ buf = TAILQ_FIRST(&closure->write_bufs);
+ if (len > buf->size - buf->len) {
+ /* Too small. */
+ buf = NULL;
+ }
+ }
+ if (buf == NULL) {
+ if ((buf = get_free_buf(len, closure)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ TAILQ_INSERT_TAIL(&closure->write_bufs, buf, entries);
+ }
+
+ memcpy(buf->data + buf->len, &msg_len, sizeof(msg_len));
+ client_message__pack(msg, buf->data + buf->len + sizeof(msg_len));
+ buf->len += len;
+
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+static bool
+fmt_client_hello(struct client_closure *closure)
+{
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ ClientHello hello_msg = CLIENT_HELLO__INIT;
+ bool ret = false;
+ debug_decl(fmt_client_hello, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: sending ClientHello", __func__);
+ hello_msg.client_id = (char *)"Sudo Sendlog " PACKAGE_VERSION;
+
+ /* Schedule ClientMessage */
+ client_msg.u.hello_msg = &hello_msg;
+ client_msg.type_case = CLIENT_MESSAGE__TYPE_HELLO_MSG;
+ ret = fmt_client_message(closure, &client_msg);
+ if (ret) {
+ if (sudo_ev_add(closure->evbase, closure->read_ev, NULL, false) == -1)
+ ret = false;
+ if (sudo_ev_add(closure->evbase, closure->write_ev, NULL, false) == -1)
+ ret = false;
+ }
+
+ debug_return_bool(ret);
+}
+
+#if defined(HAVE_OPENSSL)
+/* Wrapper for fmt_client_hello() called via tls_connect_cb() */
+static bool
+tls_start_fn(struct tls_client_closure *tls_client)
+{
+ return fmt_client_hello(tls_client->parent_closure);
+}
+#endif /* HAVE_OPENSSL */
+
+static void
+free_info_messages(InfoMessage **info_msgs, size_t n_info_msgs)
+{
+ debug_decl(free_info_messages, SUDO_DEBUG_UTIL);
+
+ if (info_msgs != NULL) {
+ while (n_info_msgs) {
+ if (info_msgs[--n_info_msgs]->value_case == INFO_MESSAGE__VALUE_STRLISTVAL) {
+ /* Only strlistval was dynamically allocated */
+ free(info_msgs[n_info_msgs]->u.strlistval->strings);
+ free(info_msgs[n_info_msgs]->u.strlistval);
+ }
+ free(info_msgs[n_info_msgs]);
+ }
+ free(info_msgs);
+ }
+
+ debug_return;
+}
+
+/*
+ * Convert a NULL-terminated string vector (argv, envp) to a
+ * StringList with an associated size.
+ * Performs a shallow copy of the strings (copies pointers).
+ */
+static InfoMessage__StringList *
+vec_to_stringlist(char * const *vec)
+{
+ InfoMessage__StringList *strlist;
+ size_t len;
+ debug_decl(vec_to_stringlist, SUDO_DEBUG_UTIL);
+
+ strlist = malloc(sizeof(*strlist));
+ if (strlist == NULL)
+ goto done;
+ info_message__string_list__init(strlist);
+
+ /* Convert vec into a StringList. */
+ for (len = 0; vec[len] != NULL; len++) {
+ continue;
+ }
+ strlist->strings = reallocarray(NULL, len, sizeof(char *));
+ if (strlist->strings == NULL) {
+ free(strlist);
+ strlist = NULL;
+ goto done;
+ }
+ strlist->n_strings = len;
+ for (len = 0; vec[len] != NULL; len++) {
+ strlist->strings[len] = vec[len];
+ }
+
+done:
+ debug_return_ptr(strlist);
+}
+
+/*
+ * Split command + args separated by whitespace into a StringList.
+ * Returns a StringList containing command and args, reusing the contents
+ * of "command", which is modified.
+ */
+static InfoMessage__StringList *
+command_to_stringlist(char *command)
+{
+ InfoMessage__StringList *strlist;
+ char *cp;
+ size_t len;
+ debug_decl(command_to_stringlist, SUDO_DEBUG_UTIL);
+
+ strlist = malloc(sizeof(*strlist));
+ if (strlist == NULL)
+ debug_return_ptr(NULL);
+ info_message__string_list__init(strlist);
+
+ for (cp = command, len = 0;;) {
+ len++;
+ if ((cp = strchr(cp, ' ')) == NULL)
+ break;
+ cp++;
+ }
+ strlist->strings = reallocarray(NULL, len, sizeof(char *));
+ if (strlist->strings == NULL) {
+ free(strlist);
+ debug_return_ptr(NULL);
+ }
+ strlist->n_strings = len;
+
+ for (cp = command, len = 0;;) {
+ strlist->strings[len++] = cp;
+ if ((cp = strchr(cp, ' ')) == NULL)
+ break;
+ *cp++ = '\0';
+ }
+
+ debug_return_ptr(strlist);
+}
+
+/*
+ * Build runargv StringList using either argv or command in evlog.
+ * Truncated command in evlog after first space as a side effect.
+ */
+static InfoMessage__StringList *
+fmt_runargv(const struct eventlog *evlog)
+{
+ InfoMessage__StringList *runargv;
+ debug_decl(fmt_runargv, SUDO_DEBUG_UTIL);
+
+ /* We may have runargv from the log.json file. */
+ if (evlog->runargv != NULL && evlog->runargv[0] != NULL) {
+ /* Convert evlog->runargv into a StringList. */
+ runargv = vec_to_stringlist(evlog->runargv);
+ if (runargv != NULL) {
+ /* Make sure command doesn't include arguments. */
+ char *cp = strchr(evlog->command, ' ');
+ if (cp != NULL)
+ *cp = '\0';
+ }
+ } else {
+ /* No log.json file, split command into a StringList. */
+ runargv = command_to_stringlist(evlog->command);
+ }
+
+ debug_return_ptr(runargv);
+}
+
+/*
+ * Build runenv StringList from env in evlog, if present.
+ */
+static InfoMessage__StringList *
+fmt_runenv(const struct eventlog *evlog)
+{
+ debug_decl(fmt_runenv, SUDO_DEBUG_UTIL);
+
+ /* Only present in log.json. */
+ if (evlog->runenv == NULL || evlog->runenv[0] == NULL)
+ debug_return_ptr(NULL);
+
+ debug_return_ptr(vec_to_stringlist(evlog->runenv));
+}
+
+/*
+ * Build submitenv StringList from env in evlog, if present.
+ */
+static InfoMessage__StringList *
+fmt_submitenv(const struct eventlog *evlog)
+{
+ debug_decl(fmt_submitenv, SUDO_DEBUG_UTIL);
+
+ /* Only present in log.json. */
+ if (evlog->submitenv == NULL || evlog->submitenv[0] == NULL)
+ debug_return_ptr(NULL);
+
+ debug_return_ptr(vec_to_stringlist(evlog->submitenv));
+}
+
+static InfoMessage **
+fmt_info_messages(const struct eventlog *evlog, char *hostname,
+ size_t *n_info_msgs)
+{
+ InfoMessage **info_msgs = NULL;
+ InfoMessage__StringList *runargv = NULL;
+ InfoMessage__StringList *runenv = NULL;
+ InfoMessage__StringList *submitenv = NULL;
+ size_t info_msgs_size, n = 0;
+ debug_decl(fmt_info_messages, SUDO_DEBUG_UTIL);
+
+ runargv = fmt_runargv(evlog);
+ if (runargv == NULL)
+ goto oom;
+
+ /* runenv and submitenv are only present in log.json */
+ runenv = fmt_runenv(evlog);
+ submitenv = fmt_submitenv(evlog);
+
+ /* The sudo I/O log info file has limited info. */
+ info_msgs_size = 15;
+ info_msgs = calloc(info_msgs_size, sizeof(InfoMessage *));
+ if (info_msgs == NULL)
+ goto oom;
+ for (n = 0; n < info_msgs_size; n++) {
+ info_msgs[n] = malloc(sizeof(InfoMessage));
+ if (info_msgs[n] == NULL)
+ goto oom;
+ info_message__init(info_msgs[n]);
+ }
+
+#define fill_str(_n, _v) do { \
+ info_msgs[n]->key = (char *)(_n); \
+ info_msgs[n]->u.strval = (_v); \
+ info_msgs[n]->value_case = INFO_MESSAGE__VALUE_STRVAL; \
+ n++; \
+} while (0)
+
+#define fill_strlist(_n, _v) do { \
+ info_msgs[n]->key = (char *)(_n); \
+ info_msgs[n]->u.strlistval = (_v); \
+ info_msgs[n]->value_case = INFO_MESSAGE__VALUE_STRLISTVAL; \
+ n++; \
+} while (0)
+
+#define fill_num(_n, _v) do { \
+ info_msgs[n]->key = (char *)(_n); \
+ info_msgs[n]->u.numval = (_v); \
+ info_msgs[n]->value_case = INFO_MESSAGE__VALUE_NUMVAL; \
+ n++; \
+} while (0)
+
+ /* Fill in info_msgs */
+ n = 0;
+ fill_num("columns", evlog->columns);
+ fill_str("command", evlog->command);
+ fill_num("lines", evlog->lines);
+ fill_strlist("runargv", runargv);
+ runargv = NULL;
+ if (submitenv != NULL) {
+ fill_strlist("submitenv", submitenv);
+ submitenv = NULL;
+ }
+ if (runenv != NULL) {
+ fill_strlist("runenv", runenv);
+ runenv = NULL;
+ }
+ if (evlog->rungid != (gid_t)-1) {
+ fill_num("rungid", evlog->rungid);
+ }
+ if (evlog->rungroup != NULL) {
+ fill_str("rungroup", evlog->rungroup);
+ }
+ if (evlog->runuid != (uid_t)-1) {
+ fill_num("runuid", evlog->runuid);
+ }
+ fill_str("runuser", evlog->runuser);
+ fill_str("source", evlog->source);
+ fill_str("submitcwd", evlog->cwd);
+ fill_str("submithost", hostname);
+ fill_str("submituser", evlog->submituser);
+ fill_str("ttyname", evlog->ttyname);
+
+ /* Update n_info_msgs. */
+ *n_info_msgs = n;
+
+ /* Avoid leaking unused info_msg structs. */
+ while (n < info_msgs_size) {
+ free(info_msgs[n++]);
+ }
+
+ debug_return_ptr(info_msgs);
+
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ free_info_messages(info_msgs, n);
+ if (runargv != NULL) {
+ free(runargv->strings);
+ free(runargv);
+ }
+ if (runenv != NULL) {
+ free(runenv->strings);
+ free(runenv);
+ }
+ if (submitenv != NULL) {
+ free(submitenv->strings);
+ free(submitenv);
+ }
+ *n_info_msgs = 0;
+ debug_return_ptr(NULL);
+}
+
+/*
+ * Build and format a RejectMessage wrapped in a ClientMessage.
+ * Stores the wire format message in the closure's write buffer.
+ * Returns true on success, false on failure.
+ */
+static bool
+fmt_reject_message(struct client_closure *closure)
+{
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ RejectMessage reject_msg = REJECT_MESSAGE__INIT;
+ TimeSpec tv = TIME_SPEC__INIT;
+ size_t n_info_msgs;
+ bool ret = false;
+ char *hostname;
+ debug_decl(fmt_reject_message, SUDO_DEBUG_UTIL);
+
+ /*
+ * Fill in RejectMessage and add it to ClientMessage.
+ */
+ if ((hostname = sudo_gethostname()) == NULL) {
+ sudo_warn("gethostname");
+ debug_return_bool(false);
+ }
+
+ /* Sudo I/O logs only store start time in seconds. */
+ tv.tv_sec = (int64_t)closure->evlog->submit_time.tv_sec;
+ tv.tv_nsec = (int32_t)closure->evlog->submit_time.tv_nsec;
+ reject_msg.submit_time = &tv;
+
+ /* Why the command was rejected. */
+ reject_msg.reason = closure->reject_reason;
+
+ reject_msg.info_msgs = fmt_info_messages(closure->evlog, hostname,
+ &n_info_msgs);
+ if (reject_msg.info_msgs == NULL)
+ goto done;
+
+ /* Update n_info_msgs. */
+ reject_msg.n_info_msgs = n_info_msgs;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sending RejectMessage, array length %zu", __func__, n_info_msgs);
+
+ /* Schedule ClientMessage */
+ client_msg.u.reject_msg = &reject_msg;
+ client_msg.type_case = CLIENT_MESSAGE__TYPE_REJECT_MSG;
+ ret = fmt_client_message(closure, &client_msg);
+ if (ret) {
+ if (sudo_ev_add(closure->evbase, closure->write_ev, NULL, false) == -1)
+ ret = false;
+ }
+
+done:
+ free_info_messages(reject_msg.info_msgs, n_info_msgs);
+ free(hostname);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Build and format an AcceptMessage wrapped in a ClientMessage.
+ * Stores the wire format message in the closure's write buffer.
+ * Returns true on success, false on failure.
+ */
+static bool
+fmt_accept_message(struct client_closure *closure)
+{
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ AcceptMessage accept_msg = ACCEPT_MESSAGE__INIT;
+ TimeSpec tv = TIME_SPEC__INIT;
+ size_t n_info_msgs;
+ bool ret = false;
+ char *hostname;
+ debug_decl(fmt_accept_message, SUDO_DEBUG_UTIL);
+
+ /*
+ * Fill in AcceptMessage and add it to ClientMessage.
+ */
+ if ((hostname = sudo_gethostname()) == NULL) {
+ sudo_warn("gethostname");
+ debug_return_bool(false);
+ }
+
+ /* Sudo I/O logs only store start time in seconds. */
+ tv.tv_sec = (int64_t)closure->evlog->submit_time.tv_sec;
+ tv.tv_nsec = (int32_t)closure->evlog->submit_time.tv_nsec;
+ accept_msg.submit_time = &tv;
+
+ /* Client will send IoBuffer messages. */
+ accept_msg.expect_iobufs = !closure->accept_only;
+
+ accept_msg.info_msgs = fmt_info_messages(closure->evlog, hostname,
+ &n_info_msgs);
+ if (accept_msg.info_msgs == NULL)
+ goto done;
+
+ /* Update n_info_msgs. */
+ accept_msg.n_info_msgs = n_info_msgs;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sending AcceptMessage, array length %zu", __func__, n_info_msgs);
+
+ /* Schedule ClientMessage */
+ client_msg.u.accept_msg = &accept_msg;
+ client_msg.type_case = CLIENT_MESSAGE__TYPE_ACCEPT_MSG;
+ ret = fmt_client_message(closure, &client_msg);
+ if (ret) {
+ if (sudo_ev_add(closure->evbase, closure->write_ev, NULL, false) == -1)
+ ret = false;
+ }
+
+done:
+ free_info_messages(accept_msg.info_msgs, n_info_msgs);
+ free(hostname);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Build and format a RestartMessage wrapped in a ClientMessage.
+ * Stores the wire format message in the closure's write buffer.
+ * Returns true on success, false on failure.
+ */
+static bool
+fmt_restart_message(struct client_closure *closure)
+{
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ RestartMessage restart_msg = RESTART_MESSAGE__INIT;
+ TimeSpec tv = TIME_SPEC__INIT;
+ bool ret = false;
+ debug_decl(fmt_restart_message, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sending RestartMessage, [%lld, %ld]", __func__,
+ (long long)closure->restart.tv_sec, closure->restart.tv_nsec);
+
+ tv.tv_sec = (int64_t)closure->restart.tv_sec;
+ tv.tv_nsec = (int32_t)closure->restart.tv_nsec;
+ restart_msg.resume_point = &tv;
+ restart_msg.log_id = (char *)closure->iolog_id;
+
+ /* Schedule ClientMessage */
+ client_msg.u.restart_msg = &restart_msg;
+ client_msg.type_case = CLIENT_MESSAGE__TYPE_RESTART_MSG;
+ ret = fmt_client_message(closure, &client_msg);
+ if (ret) {
+ if (sudo_ev_add(closure->evbase, closure->write_ev, NULL, false) == -1)
+ ret = false;
+ }
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Build and format an ExitMessage wrapped in a ClientMessage.
+ * Stores the wire format message in the closure's write buffer list.
+ * Returns true on success, false on failure.
+ */
+static bool
+fmt_exit_message(struct client_closure *closure)
+{
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ ExitMessage exit_msg = EXIT_MESSAGE__INIT;
+ TimeSpec run_time = TIME_SPEC__INIT;
+ struct eventlog *evlog = closure->evlog;
+ bool ret = false;
+ debug_decl(fmt_exit_message, SUDO_DEBUG_UTIL);
+
+ if (evlog->exit_value != -1)
+ exit_msg.exit_value = evlog->exit_value;
+ if (sudo_timespecisset(&evlog->run_time)) {
+ run_time.tv_sec = (int64_t)evlog->run_time.tv_sec;
+ run_time.tv_nsec = (int32_t)evlog->run_time.tv_nsec;
+ exit_msg.run_time = &run_time;
+ }
+ if (evlog->signal_name != NULL) {
+ exit_msg.signal = evlog->signal_name;
+ exit_msg.dumped_core = evlog->dumped_core;
+ }
+
+ if (evlog->signal_name != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sending ExitMessage, signal %s, run_time [%lld, %ld]",
+ __func__, evlog->signal_name, (long long)evlog->run_time.tv_sec,
+ evlog->run_time.tv_nsec);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sending ExitMessage, exit value %d, run_time [%lld, %ld]",
+ __func__, evlog->exit_value, (long long)evlog->run_time.tv_sec,
+ evlog->run_time.tv_nsec);
+ }
+
+ /* Send ClientMessage */
+ client_msg.u.exit_msg = &exit_msg;
+ client_msg.type_case = CLIENT_MESSAGE__TYPE_EXIT_MSG;
+ if (!fmt_client_message(closure, &client_msg))
+ goto done;
+
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+/*
+ * Build and format an IoBuffer wrapped in a ClientMessage.
+ * Stores the wire format message in the closure's write buffer list.
+ * Returns true on success, false on failure.
+ */
+static bool
+fmt_io_buf(int type, struct client_closure *closure)
+{
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ IoBuffer iobuf_msg = IO_BUFFER__INIT;
+ TimeSpec delay = TIME_SPEC__INIT;
+ bool ret = false;
+ debug_decl(fmt_io_buf, SUDO_DEBUG_UTIL);
+
+ if (!read_io_buf(closure))
+ goto done;
+
+ /* Fill in IoBuffer. */
+ /* TODO: split buffer if it is too large */
+ delay.tv_sec = (int64_t)closure->timing.delay.tv_sec;
+ delay.tv_nsec = (int32_t)closure->timing.delay.tv_nsec;
+ iobuf_msg.delay = &delay;
+ iobuf_msg.data.data = (void *)closure->buf;
+ iobuf_msg.data.len = closure->timing.u.nbytes;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sending IoBuffer length %zu, type %d, size %zu", __func__,
+ iobuf_msg.data.len, type, io_buffer__get_packed_size(&iobuf_msg));
+
+ /* Send ClientMessage, it doesn't matter which IoBuffer we set. */
+ client_msg.u.ttyout_buf = &iobuf_msg;
+ client_msg.type_case = type;
+ if (!fmt_client_message(closure, &client_msg))
+ goto done;
+
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+/*
+ * Build and format a ChangeWindowSize message wrapped in a ClientMessage.
+ * Stores the wire format message in the closure's write buffer list.
+ * Returns true on success, false on failure.
+ */
+static bool
+fmt_winsize(struct client_closure *closure)
+{
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ ChangeWindowSize winsize_msg = CHANGE_WINDOW_SIZE__INIT;
+ TimeSpec delay = TIME_SPEC__INIT;
+ struct timing_closure *timing = &closure->timing;
+ bool ret = false;
+ debug_decl(fmt_winsize, SUDO_DEBUG_UTIL);
+
+ /* Fill in ChangeWindowSize message. */
+ delay.tv_sec = (int64_t)timing->delay.tv_sec;
+ delay.tv_nsec = (int32_t)timing->delay.tv_nsec;
+ winsize_msg.delay = &delay;
+ winsize_msg.rows = timing->u.winsize.lines;
+ winsize_msg.cols = timing->u.winsize.cols;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: sending ChangeWindowSize, %dx%d",
+ __func__, winsize_msg.rows, winsize_msg.cols);
+
+ /* Send ClientMessage */
+ client_msg.u.winsize_event = &winsize_msg;
+ client_msg.type_case = CLIENT_MESSAGE__TYPE_WINSIZE_EVENT;
+ if (!fmt_client_message(closure, &client_msg))
+ goto done;
+
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+/*
+ * Build and format a CommandSuspend message wrapped in a ClientMessage.
+ * Stores the wire format message in the closure's write buffer list.
+ * Returns true on success, false on failure.
+ */
+static bool
+fmt_suspend(struct client_closure *closure)
+{
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ CommandSuspend suspend_msg = COMMAND_SUSPEND__INIT;
+ TimeSpec delay = TIME_SPEC__INIT;
+ struct timing_closure *timing = &closure->timing;
+ bool ret = false;
+ debug_decl(fmt_suspend, SUDO_DEBUG_UTIL);
+
+ /* Fill in CommandSuspend message. */
+ delay.tv_sec = (int64_t)timing->delay.tv_sec;
+ delay.tv_nsec = (int32_t)timing->delay.tv_nsec;
+ suspend_msg.delay = &delay;
+ if (sig2str(timing->u.signo, closure->buf) == -1)
+ goto done;
+ suspend_msg.signal = closure->buf;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sending CommandSuspend, SIG%s", __func__, suspend_msg.signal);
+
+ /* Send ClientMessage */
+ client_msg.u.suspend_event = &suspend_msg;
+ client_msg.type_case = CLIENT_MESSAGE__TYPE_SUSPEND_EVENT;
+ if (!fmt_client_message(closure, &client_msg))
+ goto done;
+
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+/*
+ * Read the next entry for the I/O log timing file and format a ClientMessage.
+ * Stores the wire format message in the closure's write buffer list.
+ * Returns true on success, false on failure.
+ */
+static bool
+fmt_next_iolog(struct client_closure *closure)
+{
+ struct timing_closure *timing = &closure->timing;
+ bool ret = false;
+ debug_decl(fmt_next_iolog, SUDO_DEBUG_UTIL);
+
+ for (;;) {
+ const int timing_status = iolog_read_timing_record(
+ &closure->iolog_files[IOFD_TIMING], timing);
+ switch (timing_status) {
+ case 0:
+ /* OK */
+ break;
+ case 1:
+ /* no more IO buffers */
+ closure->state = SEND_EXIT;
+ debug_return_bool(fmt_exit_message(closure));
+ case -1:
+ default:
+ debug_return_bool(false);
+ }
+
+ /* Track elapsed time for comparison with commit points. */
+ sudo_timespecadd(&closure->elapsed, &timing->delay, &closure->elapsed);
+
+ /* If there is a stopping point, make sure we haven't reached it. */
+ if (sudo_timespecisset(&closure->stop_after)) {
+ if (sudo_timespeccmp(&closure->elapsed, &closure->stop_after, >)) {
+ /* Reached limit, force premature end. */
+ sudo_timespecsub(&closure->elapsed, &timing->delay,
+ &closure->elapsed);
+ debug_return_bool(false);
+ }
+ }
+
+ /* If we have a restart point, ignore records until we hit it. */
+ if (sudo_timespecisset(&closure->restart)) {
+ if (sudo_timespeccmp(&closure->restart, &closure->elapsed, >=))
+ continue;
+ sudo_timespecclear(&closure->restart); /* caught up */
+ }
+
+ switch (timing->event) {
+ case IO_EVENT_STDIN:
+ ret = fmt_io_buf(CLIENT_MESSAGE__TYPE_STDIN_BUF, closure);
+ break;
+ case IO_EVENT_STDOUT:
+ ret = fmt_io_buf(CLIENT_MESSAGE__TYPE_STDOUT_BUF, closure);
+ break;
+ case IO_EVENT_STDERR:
+ ret = fmt_io_buf(CLIENT_MESSAGE__TYPE_STDERR_BUF, closure);
+ break;
+ case IO_EVENT_TTYIN:
+ ret = fmt_io_buf(CLIENT_MESSAGE__TYPE_TTYIN_BUF, closure);
+ break;
+ case IO_EVENT_TTYOUT:
+ ret = fmt_io_buf(CLIENT_MESSAGE__TYPE_TTYOUT_BUF, closure);
+ break;
+ case IO_EVENT_WINSIZE:
+ ret = fmt_winsize(closure);
+ break;
+ case IO_EVENT_SUSPEND:
+ ret = fmt_suspend(closure);
+ break;
+ default:
+ sudo_warnx(U_("unexpected I/O event %d"), timing->event);
+ break;
+ }
+
+ /* Keep filling write buffer as long as we only have one of them. */
+ if (!ret)
+ break;
+ if (TAILQ_NEXT(TAILQ_FIRST(&closure->write_bufs), entries) != NULL)
+ break;
+ }
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Additional work to do after a ClientMessage was sent to the server.
+ * Advances state and formats the next ClientMessage (if any).
+ */
+static bool
+client_message_completion(struct client_closure *closure)
+{
+ debug_decl(client_message_completion, SUDO_DEBUG_UTIL);
+
+ switch (closure->state) {
+ case RECV_HELLO:
+ /* Wait for ServerHello, nothing to write until then. */
+ sudo_ev_del(closure->evbase, closure->write_ev);
+ break;
+ case SEND_ACCEPT:
+ if (closure->accept_only) {
+ closure->state = SEND_EXIT;
+ debug_return_bool(fmt_exit_message(closure));
+ }
+ FALLTHROUGH;
+ case SEND_RESTART:
+ closure->state = SEND_IO;
+ FALLTHROUGH;
+ case SEND_IO:
+ /* fmt_next_iolog() will advance state on EOF. */
+ if (!fmt_next_iolog(closure))
+ debug_return_bool(false);
+ break;
+ case SEND_REJECT:
+ /* Done writing, wait for server to close connection. */
+ sudo_ev_del(closure->evbase, closure->write_ev);
+ closure->state = FINISHED;
+ break;
+ case SEND_EXIT:
+ /* Done writing, wait for final commit point if sending I/O. */
+ sudo_ev_del(closure->evbase, closure->write_ev);
+ closure->state = closure->accept_only ? FINISHED : CLOSING;
+ break;
+ default:
+ sudo_warnx(U_("%s: unexpected state %d"), __func__, closure->state);
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+/*
+ * Respond to a ServerHello message from the server.
+ * Returns true on success, false on error.
+ */
+static bool
+handle_server_hello(ServerHello *msg, struct client_closure *closure)
+{
+ size_t n;
+ debug_decl(handle_server_hello, SUDO_DEBUG_UTIL);
+
+ if (closure->state != RECV_HELLO) {
+ sudo_warnx(U_("%s: unexpected state %d"), __func__, closure->state);
+ debug_return_bool(false);
+ }
+
+ /* Check that ServerHello is valid. */
+ if (msg->server_id == NULL || msg->server_id[0] == '\0') {
+ sudo_warnx("%s", U_("invalid ServerHello"));
+ debug_return_bool(false);
+ }
+
+ if (!testrun) {
+ printf("Server ID: %s\n", msg->server_id);
+ /* TODO: handle redirect */
+ if (msg->redirect != NULL && msg->redirect[0] != '\0')
+ printf("Redirect: %s\n", msg->redirect);
+ for (n = 0; n < msg->n_servers; n++) {
+ printf("Server %u: %s\n", (unsigned int)n + 1, msg->servers[n]);
+ }
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Respond to a CommitPoint message from the server.
+ * Returns true on success, false on error.
+ */
+static bool
+handle_commit_point(TimeSpec *commit_point, struct client_closure *closure)
+{
+ debug_decl(handle_commit_point, SUDO_DEBUG_UTIL);
+
+ /* Only valid after we have sent an IO buffer. */
+ if (closure->state < SEND_IO) {
+ sudo_warnx(U_("%s: unexpected state %d"), __func__, closure->state);
+ debug_return_bool(false);
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: commit point: [%lld, %d]",
+ __func__, (long long)commit_point->tv_sec, commit_point->tv_nsec);
+ closure->committed.tv_sec = (time_t)commit_point->tv_sec;
+ closure->committed.tv_nsec = (long)commit_point->tv_nsec;
+
+ debug_return_bool(true);
+}
+
+/*
+ * Respond to a LogId message from the server.
+ * Always returns true.
+ */
+static bool
+handle_log_id(char *id, struct client_closure *closure)
+{
+ debug_decl(handle_log_id, SUDO_DEBUG_UTIL);
+
+ if (!testrun)
+ printf("Remote log ID: %s\n", id);
+
+ debug_return_bool(true);
+}
+
+/*
+ * Respond to a ServerError message from the server.
+ * Always returns false.
+ */
+static bool
+handle_server_error(char *errmsg, struct client_closure *closure)
+{
+ debug_decl(handle_server_error, SUDO_DEBUG_UTIL);
+
+ sudo_warnx(U_("error message received from server: %s"), errmsg);
+ debug_return_bool(false);
+}
+
+/*
+ * Respond to a ServerAbort message from the server.
+ * Always returns false.
+ */
+static bool
+handle_server_abort(char *errmsg, struct client_closure *closure)
+{
+ debug_decl(handle_server_abort, SUDO_DEBUG_UTIL);
+
+ sudo_warnx(U_("abort message received from server: %s"), errmsg);
+ debug_return_bool(false);
+}
+
+/*
+ * Respond to a ServerMessage from the server.
+ * Returns true on success, false on error.
+ */
+static bool
+handle_server_message(uint8_t *buf, size_t len,
+ struct client_closure *closure)
+{
+ ServerMessage *msg;
+ bool ret = false;
+ debug_decl(handle_server_message, SUDO_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: unpacking ServerMessage", __func__);
+ msg = server_message__unpack(NULL, len, buf);
+ if (msg == NULL) {
+ sudo_warnx(U_("unable to unpack %s size %zu"), "ServerMessage", len);
+ debug_return_bool(false);
+ }
+
+ switch (msg->type_case) {
+ case SERVER_MESSAGE__TYPE_HELLO:
+ if ((ret = handle_server_hello(msg->u.hello, closure))) {
+ if (sudo_timespecisset(&closure->restart)) {
+ closure->state = SEND_RESTART;
+ ret = fmt_restart_message(closure);
+ } else if (closure->reject_reason != NULL) {
+ closure->state = SEND_REJECT;
+ ret = fmt_reject_message(closure);
+ } else {
+ closure->state = SEND_ACCEPT;
+ ret = fmt_accept_message(closure);
+ }
+ }
+ break;
+ case SERVER_MESSAGE__TYPE_COMMIT_POINT:
+ ret = handle_commit_point(msg->u.commit_point, closure);
+ if (sudo_timespeccmp(&closure->elapsed, &closure->committed, ==)) {
+ sudo_ev_del(closure->evbase, closure->read_ev);
+ closure->state = FINISHED;
+ if (++finished_transmissions == nr_of_conns)
+ sudo_ev_loopexit(closure->evbase);
+ }
+ break;
+ case SERVER_MESSAGE__TYPE_LOG_ID:
+ ret = handle_log_id(msg->u.log_id, closure);
+ break;
+ case SERVER_MESSAGE__TYPE_ERROR:
+ ret = handle_server_error(msg->u.error, closure);
+ closure->state = ERROR;
+ break;
+ case SERVER_MESSAGE__TYPE_ABORT:
+ ret = handle_server_abort(msg->u.abort, closure);
+ closure->state = ERROR;
+ break;
+ default:
+ sudo_warnx(U_("%s: unexpected type_case value %d"),
+ __func__, msg->type_case);
+ break;
+ }
+
+ server_message__free_unpacked(msg, NULL);
+ debug_return_bool(ret);
+}
+
+/*
+ * Read and unpack a ServerMessage (read callback).
+ */
+static void
+server_msg_cb(int fd, int what, void *v)
+{
+ struct client_closure *closure = v;
+ struct connection_buffer *buf = &closure->read_buf;
+ size_t nread;
+ uint32_t msg_len;
+ debug_decl(server_msg_cb, SUDO_DEBUG_UTIL);
+
+ /* For TLS we may need to read as part of SSL_write_ex(). */
+ if (closure->write_instead_of_read) {
+ closure->write_instead_of_read = false;
+ client_msg_cb(fd, what, v);
+ debug_return;
+ }
+
+ if (what == SUDO_EV_TIMEOUT) {
+ sudo_warnx("%s", U_("timeout reading from server"));
+ goto bad;
+ }
+
+#if defined(HAVE_OPENSSL)
+ if (cert != NULL) {
+ SSL *ssl = closure->tls_client.ssl;
+ int result;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: reading ServerMessage (TLS)", __func__);
+ result = SSL_read_ex(ssl, buf->data + buf->len, buf->size - buf->len,
+ &nread);
+ if (result <= 0) {
+ unsigned long errcode;
+ const char *errstr;
+
+ switch (SSL_get_error(ssl, result)) {
+ case SSL_ERROR_ZERO_RETURN:
+ /* ssl connection shutdown cleanly */
+ nread = 0;
+ break;
+ case SSL_ERROR_WANT_READ:
+ /* ssl wants to read more, read event is always active */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_read_ex returns SSL_ERROR_WANT_READ");
+ debug_return;
+ case SSL_ERROR_WANT_WRITE:
+ /* ssl wants to write, schedule a write if not pending */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_read_ex returns SSL_ERROR_WANT_WRITE");
+ if (!sudo_ev_pending(closure->write_ev, SUDO_EV_WRITE, NULL)) {
+ /* Enable a temporary write event. */
+ if (sudo_ev_add(closure->evbase, closure->write_ev, NULL, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto bad;
+ }
+ closure->temporary_write_event = true;
+ }
+ /* Redirect write event to finish SSL_read_ex() */
+ closure->read_instead_of_write = true;
+ debug_return;
+ case SSL_ERROR_SSL:
+ /*
+ * For TLS 1.3, if the cert verify function on the server
+ * returns an error, OpenSSL will send an internal error
+ * alert when we read ServerHello. Convert to a more useful
+ * message and hope that no actual internal error occurs.
+ */
+ errcode = ERR_get_error();
+#if !defined(HAVE_WOLFSSL)
+ if (closure->state == RECV_HELLO &&
+ ERR_GET_REASON(errcode) == SSL_R_TLSV1_ALERT_INTERNAL_ERROR) {
+ errstr = U_("host name does not match certificate");
+ } else
+#endif
+ {
+ errstr = ERR_reason_error_string(errcode);
+ }
+ sudo_warnx("%s", errstr ? errstr : strerror(errno));
+ goto bad;
+ case SSL_ERROR_SYSCALL:
+ sudo_warn("SSL_read_ex");
+ goto bad;
+ default:
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx("SSL_read_ex: %s",
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+ }
+ } else
+#endif
+ {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: reading ServerMessage", __func__);
+ nread = (size_t)read(fd, buf->data + buf->len, buf->size - buf->len);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: received %zd bytes from server",
+ __func__, nread);
+ switch (nread) {
+ case (size_t)-1:
+ if (errno == EAGAIN || errno == EINTR)
+ debug_return;
+ sudo_warn("read");
+ goto bad;
+ case 0:
+ if (closure->state != FINISHED)
+ sudo_warnx("%s", U_("premature EOF"));
+ goto bad;
+ default:
+ break;
+ }
+ buf->len += nread;
+
+ while (buf->len - buf->off >= sizeof(msg_len)) {
+ /* Read wire message size (uint32_t in network byte order). */
+ memcpy(&msg_len, buf->data + buf->off, sizeof(msg_len));
+ msg_len = ntohl(msg_len);
+
+ if (msg_len > MESSAGE_SIZE_MAX) {
+ sudo_warnx(U_("server message too large: %u"), msg_len);
+ goto bad;
+ }
+
+ if (msg_len + sizeof(msg_len) > buf->len - buf->off) {
+ /* Incomplete message, we'll read the rest next time. */
+ if (!expand_buf(buf, msg_len + sizeof(msg_len)))
+ goto bad;
+ debug_return;
+ }
+
+ /* Parse ServerMessage, could be zero bytes. */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: parsing ServerMessage, size %u", __func__, msg_len);
+ buf->off += sizeof(msg_len);
+ if (!handle_server_message(buf->data + buf->off, msg_len, closure))
+ goto bad;
+ buf->off += msg_len;
+ }
+ buf->len -= buf->off;
+ buf->off = 0;
+ debug_return;
+bad:
+ sudo_ev_del(closure->evbase, closure->read_ev);
+ debug_return;
+}
+
+/*
+ * Send a ClientMessage to the server (write callback).
+ */
+static void
+client_msg_cb(int fd, int what, void *v)
+{
+ struct client_closure *closure = v;
+ struct connection_buffer *buf;
+ size_t nwritten;
+ debug_decl(client_msg_cb, SUDO_DEBUG_UTIL);
+
+ if ((buf = TAILQ_FIRST(&closure->write_bufs)) == NULL) {
+ sudo_warnx(U_("missing write buffer for client %s"), "localhost");
+ goto bad;
+ }
+
+ /* For TLS we may need to write as part of SSL_read_ex(). */
+ if (closure->read_instead_of_write) {
+ closure->read_instead_of_write = false;
+ /* Delete write event if it was only due to SSL_read_ex(). */
+ if (closure->temporary_write_event) {
+ closure->temporary_write_event = false;
+ sudo_ev_del(closure->evbase, closure->write_ev);
+ }
+ server_msg_cb(fd, what, v);
+ debug_return;
+ }
+
+ if (what == SUDO_EV_TIMEOUT) {
+ sudo_warnx("%s", U_("timeout writing to server"));
+ goto bad;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sending %zu bytes to server", __func__, buf->len - buf->off);
+
+#if defined(HAVE_OPENSSL)
+ if (cert != NULL) {
+ SSL *ssl = closure->tls_client.ssl;
+ const int result = SSL_write_ex(ssl, buf->data + buf->off,
+ buf->len - buf->off, &nwritten);
+ if (result <= 0) {
+ const char *errstr;
+
+ switch (SSL_get_error(ssl, result)) {
+ case SSL_ERROR_ZERO_RETURN:
+ /* ssl connection shutdown */
+ goto bad;
+ case SSL_ERROR_WANT_READ:
+ /* ssl wants to read, read event always active */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_write_ex returns SSL_ERROR_WANT_READ");
+ /* Redirect read event to finish SSL_write_ex() */
+ closure->write_instead_of_read = true;
+ debug_return;
+ case SSL_ERROR_WANT_WRITE:
+ /* ssl wants to write more, write event remains active */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_write_ex returns SSL_ERROR_WANT_WRITE");
+ debug_return;
+ case SSL_ERROR_SYSCALL:
+ sudo_warn("SSL_write_ex");
+ goto bad;
+ default:
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx("SSL_write_ex: %s",
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+ }
+ } else
+#endif
+ {
+ nwritten = (size_t)write(fd, buf->data + buf->off, buf->len - buf->off);
+ }
+ if (nwritten == (size_t)-1) {
+ if (errno == EAGAIN || errno == EINTR)
+ debug_return;
+ sudo_warn("write");
+ goto bad;
+ }
+ buf->off += nwritten;
+
+ if (buf->off == buf->len) {
+ /* sent entire message */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: finished sending %zu bytes to server", __func__, buf->len);
+ buf->off = 0;
+ buf->len = 0;
+ TAILQ_REMOVE(&closure->write_bufs, buf, entries);
+ TAILQ_INSERT_TAIL(&closure->free_bufs, buf, entries);
+ if (TAILQ_EMPTY(&closure->write_bufs)) {
+ /* Write queue empty, check state. */
+ if (!client_message_completion(closure))
+ goto bad;
+ }
+ }
+ debug_return;
+
+bad:
+ sudo_ev_del(closure->evbase, closure->read_ev);
+ sudo_ev_del(closure->evbase, closure->write_ev);
+ debug_return;
+}
+
+/*
+ * Parse a timespec on the command line of the form
+ * seconds[,nanoseconds]
+ */
+static bool
+parse_timespec(struct timespec *ts, char *strval)
+{
+ const char *errstr;
+ char *nsecstr;
+ debug_decl(parse_timespec, SUDO_DEBUG_UTIL);
+
+ if ((nsecstr = strchr(strval, ',')) != NULL)
+ *nsecstr++ = '\0';
+
+ ts->tv_nsec = 0;
+ ts->tv_sec = (time_t)sudo_strtonum(strval, 0, TIME_T_MAX, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), strval, U_(errstr));
+ debug_return_bool(false);
+ }
+
+ if (nsecstr != NULL) {
+ ts->tv_nsec = (long)sudo_strtonum(nsecstr, 0, LONG_MAX, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), nsecstr, U_(errstr));
+ debug_return_bool(false);
+ }
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: parsed timespec [%lld, %ld]",
+ __func__, (long long)ts->tv_sec, ts->tv_nsec);
+ debug_return_bool(true);
+}
+
+/*
+ * Free client closure contents.
+ */
+static void
+client_closure_free(struct client_closure *closure)
+{
+ struct connection_buffer *buf;
+ debug_decl(connection_closure_free, SUDO_DEBUG_UTIL);
+
+ if (closure != NULL) {
+ TAILQ_REMOVE(&connections, closure, entries);
+#if defined(HAVE_OPENSSL)
+ if (closure->tls_client.ssl != NULL) {
+ if (SSL_shutdown(closure->tls_client.ssl) == 0)
+ SSL_shutdown(closure->tls_client.ssl);
+ SSL_free(closure->tls_client.ssl);
+ }
+ sudo_ev_free(closure->tls_client.tls_connect_ev);
+#endif
+ sudo_ev_free(closure->read_ev);
+ sudo_ev_free(closure->write_ev);
+ free(closure->read_buf.data);
+ free(closure->buf);
+ while ((buf = TAILQ_FIRST(&closure->write_bufs)) != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "discarding write buffer %p, len %zu", buf, buf->len - buf->off);
+ TAILQ_REMOVE(&closure->write_bufs, buf, entries);
+ free(buf->data);
+ free(buf);
+ }
+ while ((buf = TAILQ_FIRST(&closure->free_bufs)) != NULL) {
+ TAILQ_REMOVE(&closure->free_bufs, buf, entries);
+ free(buf->data);
+ free(buf);
+ }
+ shutdown(closure->sock, SHUT_RDWR);
+ close(closure->sock);
+ free(closure);
+ }
+
+ debug_return;
+}
+
+/*
+ * Initialize a new client closure
+ */
+static struct client_closure *
+client_closure_alloc(int sock, struct sudo_event_base *base,
+ struct timespec *restart, struct timespec *stop_after, const char *iolog_id,
+ char *reject_reason, bool accept_only, struct eventlog *evlog)
+{
+ struct connection_buffer *buf;
+ struct client_closure *closure;
+ debug_decl(client_closure_alloc, SUDO_DEBUG_UTIL);
+
+ if ((closure = calloc(1, sizeof(*closure))) == NULL)
+ debug_return_ptr(NULL);
+
+ closure->sock = sock;
+ closure->evbase = base;
+ TAILQ_INIT(&closure->write_bufs);
+ TAILQ_INIT(&closure->free_bufs);
+
+ TAILQ_INSERT_TAIL(&connections, closure, entries);
+
+ closure->state = RECV_HELLO;
+ closure->accept_only = accept_only;
+ closure->reject_reason = reject_reason;
+ closure->evlog = evlog;
+
+ closure->restart.tv_sec = restart->tv_sec;
+ closure->restart.tv_nsec = restart->tv_nsec;
+ closure->stop_after.tv_sec = stop_after->tv_sec;
+ closure->stop_after.tv_nsec = stop_after->tv_nsec;
+
+ closure->iolog_id = iolog_id;
+
+ closure->read_buf.size = 8 * 1024;
+ closure->read_buf.data = malloc(closure->read_buf.size);
+ if (closure->read_buf.data == NULL)
+ goto bad;
+
+ closure->read_ev = sudo_ev_alloc(sock, SUDO_EV_READ|SUDO_EV_PERSIST,
+ server_msg_cb, closure);
+ if (closure->read_ev == NULL)
+ goto bad;
+
+ buf = get_free_buf(64 * 1024, closure);
+ if (buf == NULL)
+ goto bad;
+ TAILQ_INSERT_TAIL(&closure->free_bufs, buf, entries);
+
+ closure->write_ev = sudo_ev_alloc(sock, SUDO_EV_WRITE|SUDO_EV_PERSIST,
+ client_msg_cb, closure);
+ if (closure->write_ev == NULL)
+ goto bad;
+
+#if defined(HAVE_OPENSSL)
+ if (cert != NULL) {
+ closure->tls_client.tls_connect_ev = sudo_ev_alloc(sock, SUDO_EV_WRITE,
+ tls_connect_cb, &closure->tls_client);
+ if (closure->tls_client.tls_connect_ev == NULL)
+ goto bad;
+ closure->tls_client.evbase = base;
+ closure->tls_client.parent_closure = closure;
+ closure->tls_client.peer_name = &server_info;
+ closure->tls_client.connect_timeout.tv_sec = TLS_HANDSHAKE_TIMEO_SEC;
+ closure->tls_client.start_fn = tls_start_fn;
+ }
+#endif
+
+ debug_return_ptr(closure);
+bad:
+ client_closure_free(closure);
+ debug_return_ptr(NULL);
+}
+
+#if defined(HAVE_OPENSSL)
+static const char short_opts[] = "Ah:i:np:r:R:s:t:b:c:k:V";
+#else
+static const char short_opts[] = "Ah:i:Ip:r:R:t:s:V";
+#endif
+static struct option long_opts[] = {
+ { "accept", no_argument, NULL, 'A' },
+ { "help", no_argument, NULL, 1 },
+ { "host", required_argument, NULL, 'h' },
+ { "iolog-id", required_argument, NULL, 'i' },
+ { "port", required_argument, NULL, 'p' },
+ { "restart", required_argument, NULL, 'r' },
+ { "reject", required_argument, NULL, 'R' },
+ { "stop-after", required_argument, NULL, 's' },
+ { "test", optional_argument, NULL, 't' },
+#if defined(HAVE_OPENSSL)
+ { "ca-bundle", required_argument, NULL, 'b' },
+ { "cert", required_argument, NULL, 'c' },
+ { "key", required_argument, NULL, 'k' },
+ { "no-verify", no_argument, NULL, 'n' },
+#endif
+ { "version", no_argument, NULL, 'V' },
+ { NULL, no_argument, NULL, 0 },
+};
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+int
+main(int argc, char *argv[])
+{
+ struct client_closure *closure = NULL;
+ struct sudo_event_base *evbase;
+ struct eventlog *evlog;
+ const char *port = NULL;
+ struct timespec restart = { 0, 0 };
+ struct timespec stop_after = { 0, 0 };
+ bool accept_only = false;
+ char *reject_reason = NULL;
+ const char *iolog_id = NULL;
+ const char *open_mode = "r";
+ const char *errstr;
+ int ch, sock, iolog_dir_fd, finished;
+ debug_decl_vars(main, SUDO_DEBUG_MAIN);
+
+#if defined(SUDO_DEVEL) && defined(__OpenBSD__)
+ {
+ extern char *malloc_options;
+ malloc_options = "S";
+ }
+#endif
+
+ signal(SIGPIPE, SIG_IGN);
+
+ initprogname(argc > 0 ? argv[0] : "sudo_sendlog");
+ setlocale(LC_ALL, "");
+ bindtextdomain("sudo", LOCALEDIR); /* XXX - add logsrvd domain */
+ textdomain("sudo");
+
+ /* Read sudo.conf and initialize the debug subsystem. */
+ if (sudo_conf_read(NULL, SUDO_CONF_DEBUG) == -1)
+ return EXIT_FAILURE;
+ sudo_debug_register(getprogname(), NULL, NULL,
+ sudo_conf_debug_files(getprogname()), -1);
+
+ if (protobuf_c_version_number() < 1003000)
+ sudo_fatalx("%s", U_("Protobuf-C version 1.3 or higher required"));
+
+ while ((ch = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
+ switch (ch) {
+ case 'A':
+ accept_only = true;
+ break;
+ case 'h':
+ server_info.name = optarg;
+ break;
+ case 'i':
+ iolog_id = optarg;
+ break;
+ case 'p':
+ port = optarg;
+ break;
+ case 'R':
+ reject_reason = optarg;
+ break;
+ case 'r':
+ if (!parse_timespec(&restart, optarg))
+ goto bad;
+ open_mode = "r+";
+ break;
+ case 's':
+ if (!parse_timespec(&stop_after, optarg))
+ goto bad;
+ break;
+ case 't':
+ nr_of_conns = (int)sudo_strtonum(optarg, 1, INT_MAX, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), optarg, U_(errstr));
+ goto bad;
+ }
+ testrun = true;
+ break;
+ case 1:
+ help();
+ /* NOTREACHED */
+#if defined(HAVE_OPENSSL)
+ case 'b':
+ ca_bundle = optarg;
+ break;
+ case 'c':
+ cert = optarg;
+ break;
+ case 'k':
+ key = optarg;
+ break;
+ case 'n':
+ verify_server = false;
+ break;
+#endif
+ case 'V':
+ (void)printf(_("%s version %s\n"), getprogname(),
+ PACKAGE_VERSION);
+ return 0;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+#if defined(HAVE_OPENSSL)
+ /* if no key file is given explicitly, try to load the key from the cert */
+ if (cert != NULL) {
+ if (key == NULL)
+ key = cert;
+ if (port == NULL)
+ port = DEFAULT_PORT_TLS;
+ }
+#endif
+ if (port == NULL)
+ port = DEFAULT_PORT;
+
+ if (sudo_timespecisset(&restart) != (iolog_id != NULL)) {
+ sudo_warnx("%s", U_("both restart point and iolog ID must be specified"));
+ usage();
+ }
+ if (sudo_timespecisset(&restart) && (accept_only || reject_reason)) {
+ sudo_warnx("%s", U_("a restart point may not be set when no I/O is sent"));
+ usage();
+ }
+
+ /* Remaining arg should be to I/O log dir to send. */
+ if (argc != 1)
+ usage();
+ iolog_dir = argv[0];
+ if ((iolog_dir_fd = open(iolog_dir, O_RDONLY)) == -1) {
+ sudo_warn("%s", iolog_dir);
+ goto bad;
+ }
+
+ /* Parse I/O log info file. */
+ if ((evlog = iolog_parse_loginfo(iolog_dir_fd, iolog_dir)) == NULL)
+ goto bad;
+
+ if ((evbase = sudo_ev_base_alloc()) == NULL)
+ sudo_fatal(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ if (testrun)
+ printf("connecting clients...\n");
+
+ for (int i = 0; i < nr_of_conns; i++) {
+ sock = connect_server(&server_info, port);
+ if (sock == -1)
+ goto bad;
+
+ if (!testrun)
+ printf("Connected to %s:%s\n", server_info.name, port);
+
+ closure = client_closure_alloc(sock, evbase, &restart, &stop_after,
+ iolog_id, reject_reason, accept_only, evlog);
+ if (closure == NULL)
+ goto bad;
+
+ /* Open the I/O log files and seek to restart point if there is one. */
+ if (!iolog_open_all(iolog_dir_fd, iolog_dir, closure->iolog_files, open_mode))
+ goto bad;
+ if (sudo_timespecisset(&closure->restart)) {
+ if (!iolog_seekto(iolog_dir_fd, iolog_dir, closure->iolog_files,
+ &closure->elapsed, &closure->restart))
+ goto bad;
+ }
+
+#if defined(HAVE_OPENSSL)
+ if (cert != NULL) {
+ if (!tls_client_setup(closure->sock, ca_bundle, cert, key, NULL,
+ NULL, NULL, verify_server, false, &closure->tls_client))
+ goto bad;
+ } else
+#endif
+ {
+ /* No TLS, send ClientHello */
+ if (!fmt_client_hello(closure))
+ goto bad;
+ }
+ }
+
+ if (testrun)
+ puts("sending logs...");
+
+ struct timespec t_start, t_end, t_result;
+ sudo_gettime_real(&t_start);
+
+ sudo_ev_dispatch(evbase);
+ sudo_ev_base_free(evbase);
+
+ sudo_gettime_real(&t_end);
+ sudo_timespecsub(&t_end, &t_start, &t_result);
+
+ finished = 0;
+ while ((closure = TAILQ_FIRST(&connections)) != NULL) {
+ if (closure->state == FINISHED) {
+ finished++;
+ } else {
+ sudo_warnx(U_("exited prematurely with state %d"), closure->state);
+ sudo_warnx(U_("elapsed time sent to server [%lld, %ld]"),
+ (long long)closure->elapsed.tv_sec, closure->elapsed.tv_nsec);
+ sudo_warnx(U_("commit point received from server [%lld, %ld]"),
+ (long long)closure->committed.tv_sec, closure->committed.tv_nsec);
+ }
+ client_closure_free(closure);
+ }
+ eventlog_free(evlog);
+#if defined(HAVE_OPENSSL)
+ SSL_CTX_free(ssl_ctx);
+#endif
+
+ if (finished != 0) {
+ printf("%d I/O log%s transmitted successfully in %lld.%.9ld seconds\n",
+ finished, nr_of_conns > 1 ? "s" : "",
+ (long long)t_result.tv_sec, t_result.tv_nsec);
+ debug_return_int(EXIT_SUCCESS);
+ }
+
+bad:
+ debug_return_int(EXIT_FAILURE);
+}
diff --git a/logsrvd/sendlog.h b/logsrvd/sendlog.h
new file mode 100644
index 0000000..ba40b3b
--- /dev/null
+++ b/logsrvd/sendlog.h
@@ -0,0 +1,82 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_SENDLOG_H
+#define SUDO_SENDLOG_H
+
+#include <log_server.pb-c.h>
+#if PROTOBUF_C_VERSION_NUMBER < 1003000
+# error protobuf-c version 1.30 or higher required
+#endif
+
+#include <config.h>
+
+#if defined(HAVE_OPENSSL)
+# if defined(HAVE_WOLFSSL)
+# include <wolfssl/options.h>
+# endif
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+#endif
+
+#include "logsrv_util.h"
+#include <tls_common.h>
+
+enum client_state {
+ ERROR,
+ RECV_HELLO,
+ SEND_RESTART,
+ SEND_ACCEPT,
+ SEND_REJECT,
+ SEND_IO,
+ SEND_EXIT,
+ CLOSING,
+ FINISHED
+};
+
+struct client_closure {
+ TAILQ_ENTRY(client_closure) entries;
+ int sock;
+ bool accept_only;
+ bool read_instead_of_write;
+ bool write_instead_of_read;
+ bool temporary_write_event;
+ struct timespec restart;
+ struct timespec stop_after;
+ struct timespec elapsed;
+ struct timespec committed;
+ struct timing_closure timing;
+ struct sudo_event_base *evbase;
+ struct connection_buffer read_buf;
+ struct connection_buffer_list write_bufs;
+ struct connection_buffer_list free_bufs;
+#if defined(HAVE_OPENSSL)
+ struct tls_client_closure tls_client;
+#endif
+ struct sudo_event *read_ev;
+ struct sudo_event *write_ev;
+ struct eventlog *evlog;
+ struct iolog_file iolog_files[IOFD_MAX];
+ const char *iolog_id;
+ char *reject_reason;
+ char *buf; /* XXX */
+ size_t bufsize; /* XXX */
+ enum client_state state;
+};
+
+#endif /* SUDO_SENDLOG_H */
diff --git a/logsrvd/tls_client.c b/logsrvd/tls_client.c
new file mode 100644
index 0000000..0cb0aa2
--- /dev/null
+++ b/logsrvd/tls_client.c
@@ -0,0 +1,251 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_event.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_util.h>
+
+#include "logsrv_util.h"
+#include <tls_common.h>
+#include <hostcheck.h>
+
+#if defined(HAVE_OPENSSL)
+
+/*
+ * Check that the server's certificate is valid that it contains the
+ * server name or IP address.
+ * Returns 0 if the cert is invalid, else 1.
+ */
+static int
+verify_peer_identity(int preverify_ok, X509_STORE_CTX *ctx)
+{
+ HostnameValidationResult result;
+ struct peer_info *peer_info;
+ SSL *ssl;
+ X509 *current_cert;
+ X509 *peer_cert;
+ debug_decl(verify_peer_identity, SUDO_DEBUG_UTIL);
+
+ /* if pre-verification of the cert failed, just propagate that result back */
+ if (preverify_ok != 1) {
+ debug_return_int(0);
+ }
+
+ /*
+ * Since this callback is called for each cert in the chain,
+ * check that current cert is the peer's certificate
+ */
+ current_cert = X509_STORE_CTX_get_current_cert(ctx);
+ peer_cert = X509_STORE_CTX_get0_cert(ctx);
+ if (current_cert != peer_cert) {
+ debug_return_int(1);
+ }
+
+ /* Fetch the attached peer_info from the ssl connection object. */
+ ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
+ peer_info = SSL_get_ex_data(ssl, 1);
+
+ /*
+ * Validate the cert based on the host name and IP address.
+ * If host name is not known, validate_hostname() can resolve it.
+ */
+ result = validate_hostname(peer_cert,
+ peer_info->name ? peer_info->name : peer_info->ipaddr,
+ peer_info->ipaddr, peer_info->name ? 0 : 1);
+
+ debug_return_int(result == MatchFound);
+}
+
+void
+tls_connect_cb(int sock, int what, void *v)
+{
+ struct tls_client_closure *tls_client = v;
+ struct sudo_event_base *evbase = tls_client->evbase;
+ const struct timespec *timeout = &tls_client->connect_timeout;
+ const char *errstr;
+ int con_stat;
+ debug_decl(tls_connect_cb, SUDO_DEBUG_UTIL);
+
+ if (what == SUDO_EV_TIMEOUT) {
+ sudo_warnx("%s", U_("TLS handshake timeout occurred"));
+ goto bad;
+ }
+
+ con_stat = SSL_connect(tls_client->ssl);
+
+ if (con_stat == 1) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "SSL_connect successful");
+ tls_client->tls_connect_state = true;
+ } else {
+ switch (SSL_get_error(tls_client->ssl, con_stat)) {
+ /* TLS handshake is not finished, reschedule event */
+ case SSL_ERROR_WANT_READ:
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_connect returns SSL_ERROR_WANT_READ");
+ if (what != SUDO_EV_READ) {
+ if (sudo_ev_set(tls_client->tls_connect_ev,
+ SSL_get_fd(tls_client->ssl), SUDO_EV_READ,
+ tls_connect_cb, tls_client) == -1) {
+ sudo_warnx("%s", U_("unable to set event"));
+ goto bad;
+ }
+ }
+ if (sudo_ev_add(evbase, tls_client->tls_connect_ev, timeout, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto bad;
+ }
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_connect returns SSL_ERROR_WANT_WRITE");
+ if (what != SUDO_EV_WRITE) {
+ if (sudo_ev_set(tls_client->tls_connect_ev,
+ SSL_get_fd(tls_client->ssl), SUDO_EV_WRITE,
+ tls_connect_cb, tls_client) == -1) {
+ sudo_warnx("%s", U_("unable to set event"));
+ goto bad;
+ }
+ }
+ if (sudo_ev_add(evbase, tls_client->tls_connect_ev, timeout, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto bad;
+ }
+ break;
+ case SSL_ERROR_SYSCALL:
+ sudo_warnx(U_("TLS connection failed: %s"), strerror(errno));
+ goto bad;
+ default:
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("TLS connection failed: %s"),
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+ }
+
+ if (tls_client->tls_connect_state) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "TLS version: %s, negotiated cipher suite: %s",
+ SSL_get_version(tls_client->ssl), SSL_get_cipher(tls_client->ssl));
+
+ /* Done with TLS connect, send ClientHello */
+ sudo_ev_free(tls_client->tls_connect_ev);
+ tls_client->tls_connect_ev = NULL;
+ if (!tls_client->start_fn(tls_client))
+ goto bad;
+ }
+
+ debug_return;
+
+bad:
+ sudo_ev_loopbreak(evbase);
+ debug_return;
+}
+
+bool
+tls_ctx_client_setup(SSL_CTX *ssl_ctx, int sock,
+ struct tls_client_closure *closure)
+{
+ const char *errstr;
+ bool ret = false;
+ debug_decl(tls_ctx_client_setup, SUDO_DEBUG_UTIL);
+
+ if ((closure->ssl = SSL_new(ssl_ctx)) == NULL) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("unable to allocate ssl object: %s"),
+ errstr ? errstr : strerror(errno));
+ goto done;
+ }
+
+ if (SSL_set_ex_data(closure->ssl, 1, closure->peer_name) <= 0) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("Unable to attach user data to the ssl object: %s"),
+ errstr ? errstr : strerror(errno));
+ goto done;
+ }
+
+ if (SSL_set_fd(closure->ssl, sock) <= 0) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("Unable to attach socket to the ssl object: %s"),
+ errstr ? errstr : strerror(errno));
+ goto done;
+ }
+
+ if (sudo_ev_add(closure->evbase, closure->tls_connect_ev, NULL, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto done;
+ }
+
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+bool
+tls_client_setup(int sock, const char *ca_bundle_file, const char *cert_file,
+ const char *key_file, const char *dhparam_file, const char *ciphers_v12,
+ const char *ciphers_v13, bool verify_server, bool check_peer,
+ struct tls_client_closure *closure)
+{
+ SSL_CTX *ssl_ctx;
+ debug_decl(tls_client_setup, SUDO_DEBUG_UTIL);
+
+ ssl_ctx = init_tls_context(ca_bundle_file, cert_file, key_file,
+ dhparam_file, ciphers_v12, ciphers_v13, verify_server);
+ if (ssl_ctx == NULL) {
+ sudo_warnx("%s", U_("unable to initialize TLS context"));
+ debug_return_bool(false);
+ }
+
+ if (check_peer) {
+ /* Verify server cert during the handshake. */
+ SSL_CTX_set_verify(ssl_ctx,
+ SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+ verify_peer_identity);
+ }
+
+ debug_return_bool(tls_ctx_client_setup(ssl_ctx, sock, closure));
+}
+#endif /* HAVE_OPENSSL */
diff --git a/logsrvd/tls_common.h b/logsrvd/tls_common.h
new file mode 100644
index 0000000..2222118
--- /dev/null
+++ b/logsrvd/tls_common.h
@@ -0,0 +1,53 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_TLS_COMMON_H
+#define SUDO_TLS_COMMON_H
+
+#include <config.h>
+
+#if defined(HAVE_OPENSSL)
+# if defined(HAVE_WOLFSSL)
+# include <wolfssl/options.h>
+# endif
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+# include <sudo_ssl_compat.h>
+
+struct tls_client_closure {
+ SSL *ssl;
+ void *parent_closure;
+ struct sudo_event_base *evbase; /* duplicated */
+ struct sudo_event *tls_connect_ev;
+ struct peer_info *peer_name;
+ struct timespec connect_timeout;
+ bool (*start_fn)(struct tls_client_closure *);
+ bool tls_connect_state;
+};
+
+/* tls_client.c */
+void tls_connect_cb(int sock, int what, void *v);
+bool tls_client_setup(int sock, const char *ca_bundle_file, const char *cert_file, const char *key_file, const char *dhparam_file, const char *ciphers_v12, const char *ciphers_v13, bool verify_server, bool check_peer, struct tls_client_closure *closure);
+bool tls_ctx_client_setup(SSL_CTX *ssl_ctx, int sock, struct tls_client_closure *closure);
+
+/* tls_init.c */
+SSL_CTX *init_tls_context(const char *ca_bundle_file, const char *cert_file, const char *key_file, const char *dhparam_file, const char *ciphers_v12, const char *ciphers_v13, bool verify_cert);
+
+#endif /* HAVE_OPENSSL */
+
+#endif /* SUDO_TLS_COMMON_H */
diff --git a/logsrvd/tls_init.c b/logsrvd/tls_init.c
new file mode 100644
index 0000000..c8c623e
--- /dev/null
+++ b/logsrvd/tls_init.c
@@ -0,0 +1,383 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_event.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+
+#include <tls_common.h>
+#include <hostcheck.h>
+
+#define DEFAULT_CIPHER_LST12 "HIGH:!aNULL"
+#define DEFAULT_CIPHER_LST13 "TLS_AES_256_GCM_SHA384"
+
+#if defined(HAVE_OPENSSL)
+# include <openssl/bio.h>
+# include <openssl/dh.h>
+
+static bool
+verify_cert_chain(SSL_CTX *ctx, const char *cert_file)
+{
+#ifdef HAVE_SSL_CTX_GET0_CERTIFICATE
+ const char *errstr;
+ bool ret = false;
+ X509_STORE_CTX *store_ctx = NULL;
+ X509_STORE *ca_store;
+ STACK_OF(X509) *chain_certs;
+ X509 *x509;
+ debug_decl(verify_cert_chain, SUDO_DEBUG_UTIL);
+
+ if ((x509 = SSL_CTX_get0_certificate(ctx)) == NULL) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx("SSL_CTX_get0_certificate: %s",
+ errstr ? errstr : strerror(errno));
+ goto done;
+ }
+
+ if ((store_ctx = X509_STORE_CTX_new()) == NULL) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx("X509_STORE_CTX_new: %s",
+ errstr ? errstr : strerror(errno));
+ goto done;
+ }
+
+ if (!SSL_CTX_get0_chain_certs(ctx, &chain_certs)) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx("SSL_CTX_get0_chain_certs: %s: %s", cert_file,
+ errstr ? errstr : strerror(errno));
+ goto done;
+ }
+
+ ca_store = SSL_CTX_get_cert_store(ctx);
+#ifdef X509_V_FLAG_X509_STRICT
+ if (ca_store != NULL)
+ X509_STORE_set_flags(ca_store, X509_V_FLAG_X509_STRICT);
+#endif
+
+ if (!X509_STORE_CTX_init(store_ctx, ca_store, x509, chain_certs)) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx("X509_STORE_CTX_init: %s",
+ errstr ? errstr : strerror(errno));
+ goto done;
+ }
+
+ if (X509_verify_cert(store_ctx) <= 0) {
+ errstr =
+ X509_verify_cert_error_string(X509_STORE_CTX_get_error(store_ctx));
+ sudo_warnx("X509_verify_cert: %s: %s", cert_file, errstr);
+ goto done;
+ }
+
+ ret = true;
+done:
+ X509_STORE_CTX_free(store_ctx);
+
+ debug_return_bool(ret);
+#else
+ /* TODO: verify server cert with old OpenSSL */
+ return true;
+#endif /* HAVE_SSL_CTX_GET0_CERTIFICATE */
+}
+
+static bool
+init_tls_ciphersuites(SSL_CTX *ctx, const char *ciphers_v12,
+ const char *ciphers_v13)
+{
+ const char *errstr;
+ int success = 0;
+ debug_decl(init_tls_ciphersuites, SUDO_DEBUG_UTIL);
+
+ if (ciphers_v12 != NULL) {
+ /* try to set TLS v1.2 ciphersuite list from config if given */
+ success = SSL_CTX_set_cipher_list(ctx, ciphers_v12);
+ if (success) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "TLS 1.2 ciphersuite list set to %s", ciphers_v12);
+ } else {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("unable to set TLS 1.2 ciphersuite to %s: %s"),
+ ciphers_v12, errstr ? errstr : strerror(errno));
+ }
+ }
+ if (!success) {
+ /* fallback to default ciphersuites for TLS v1.2 */
+ if (SSL_CTX_set_cipher_list(ctx, DEFAULT_CIPHER_LST12) <= 0) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("unable to set TLS 1.2 ciphersuite to %s: %s"),
+ DEFAULT_CIPHER_LST12, errstr ? errstr : strerror(errno));
+ debug_return_bool(false);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "TLS v1.2 ciphersuite list set to %s (default)",
+ DEFAULT_CIPHER_LST12);
+ }
+ }
+
+# if defined(HAVE_SSL_CTX_SET_CIPHERSUITES)
+ success = 0;
+ if (ciphers_v13 != NULL) {
+ /* try to set TLSv1.3 ciphersuite list from config */
+ success = SSL_CTX_set_ciphersuites(ctx, ciphers_v13);
+ if (success) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "TLS v1.3 ciphersuite list set to %s", ciphers_v13);
+ } else {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("unable to set TLS 1.3 ciphersuite to %s: %s"),
+ ciphers_v13, errstr ? errstr : strerror(errno));
+ }
+ }
+ if (!success) {
+ /* fallback to default ciphersuites for TLS v1.3 */
+ if (SSL_CTX_set_ciphersuites(ctx, DEFAULT_CIPHER_LST13) <= 0) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("unable to set TLS 1.3 ciphersuite to %s: %s"),
+ DEFAULT_CIPHER_LST13, errstr ? errstr : strerror(errno));
+ debug_return_bool(false);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "TLS v1.3 ciphersuite list set to %s (default)",
+ DEFAULT_CIPHER_LST13);
+ }
+ }
+# endif
+
+ debug_return_bool(true);
+}
+
+/*
+ * Load diffie-hellman parameters from bio and store in ctx.
+ * Returns true on success, else false.
+ */
+#ifdef HAVE_SSL_CTX_SET0_TMP_DH_PKEY
+static bool
+set_dhparams_bio(SSL_CTX *ctx, BIO *bio)
+{
+ EVP_PKEY *dhparams;
+ bool ret = false;
+ debug_decl(set_dhparams_bio, SUDO_DEBUG_UTIL);
+
+ dhparams = PEM_read_bio_Parameters(bio, NULL);
+ if (dhparams != NULL) {
+ /* dhparams is owned by ctx on success. */
+ ret = SSL_CTX_set0_tmp_dh_pkey(ctx, dhparams);
+ if (!ret) {
+ const char *errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("unable to set diffie-hellman parameters: %s"),
+ errstr ? errstr : strerror(errno));
+ EVP_PKEY_free(dhparams);
+ }
+ }
+ debug_return_bool(ret);
+}
+#else
+static bool
+set_dhparams_bio(SSL_CTX *ctx, BIO *bio)
+{
+ DH *dhparams;
+ bool ret = false;
+ debug_decl(set_dhparams_bio, SUDO_DEBUG_UTIL);
+
+ dhparams = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
+ if (dhparams != NULL) {
+ /* LEAK: dhparams leaked on config reload */
+ ret = SSL_CTX_set_tmp_dh(ctx, dhparams);
+ if (!ret) {
+ const char *errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("unable to set diffie-hellman parameters: %s"),
+ errstr ? errstr : strerror(errno));
+ DH_free(dhparams);
+ }
+ }
+ debug_return_bool(ret);
+}
+#endif /* HAVE_SSL_CTX_SET0_TMP_DH_PKEY */
+
+/*
+ * Load diffie-hellman parameters from the specified file and store in ctx.
+ * Returns true on success, else false.
+ */
+static bool
+set_dhparams(SSL_CTX *ctx, const char *dhparam_file)
+{
+ BIO *bio;
+ bool ret = false;
+ debug_decl(set_dhparams, SUDO_DEBUG_UTIL);
+
+ bio = BIO_new_file(dhparam_file, "r");
+ if (bio != NULL) {
+ if (set_dhparams_bio(ctx, bio)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "loaded diffie-hellman parameters from %s", dhparam_file);
+ ret = true;
+ }
+ BIO_free(bio);
+ } else {
+ sudo_warn(U_("unable to open %s"), dhparam_file);
+ }
+
+ debug_return_bool(ret);
+}
+
+SSL_CTX *
+init_tls_context(const char *ca_bundle_file, const char *cert_file,
+ const char *key_file, const char *dhparam_file, const char *ciphers_v12,
+ const char *ciphers_v13, bool verify_cert)
+{
+ SSL_CTX *ctx = NULL;
+ const char *errstr;
+ static bool initialized;
+ debug_decl(init_tls_context, SUDO_DEBUG_UTIL);
+
+ /* Only initialize the SSL library once. */
+ if (!initialized) {
+ SSL_library_init();
+ OpenSSL_add_all_algorithms();
+ SSL_load_error_strings();
+ initialized = true;
+ }
+
+ /* Create the ssl context and enforce TLS 1.2 or higher. */
+ if ((ctx = SSL_CTX_new(TLS_method())) == NULL) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("unable to create TLS context: %s"),
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
+ if (!SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION)) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("unable to set minimum protocol version to TLS 1.2: %s"),
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+#else
+ SSL_CTX_set_options(ctx,
+ SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1);
+#endif
+
+ if (ca_bundle_file != NULL) {
+ STACK_OF(X509_NAME) *cacerts =
+ SSL_load_client_CA_file(ca_bundle_file);
+
+ if (cacerts == NULL) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("%s: %s"), ca_bundle_file,
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+ SSL_CTX_set_client_CA_list(ctx, cacerts);
+
+ if (SSL_CTX_load_verify_locations(ctx, ca_bundle_file, NULL) <= 0) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx("SSL_CTX_load_verify_locations: %s: %s", ca_bundle_file,
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+ } else {
+ if (!SSL_CTX_set_default_verify_paths(ctx)) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx("SSL_CTX_set_default_verify_paths: %s",
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+ }
+
+ if (cert_file != NULL) {
+ if (!SSL_CTX_use_certificate_chain_file(ctx, cert_file)) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("%s: %s"), cert_file,
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+ if (key_file == NULL) {
+ /* No explicit key file set, try to use the cert file. */
+ key_file = cert_file;
+ }
+ if (!SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) ||
+ !SSL_CTX_check_private_key(ctx)) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("%s: %s"), key_file,
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+
+ /* Optionally verify the certificate we are using. */
+ if (verify_cert) {
+ if (!verify_cert_chain(ctx, cert_file))
+ goto bad;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "skipping local cert check");
+ }
+ }
+
+ /* Initialize TLS 1.2 1.3 ciphersuites. */
+ if (!init_tls_ciphersuites(ctx, ciphers_v12, ciphers_v13)) {
+ goto bad;
+ }
+
+ /*
+ * Load diffie-hellman parameters from a file if specified.
+ * Failure to open the file is not a fatal error.
+ */
+ if (dhparam_file != NULL) {
+ if (!set_dhparams(ctx, dhparam_file)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "unable to load dhparam file, using default parameters");
+ }
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "dhparam file not specified, using default parameters");
+ }
+
+ goto done;
+
+bad:
+ SSL_CTX_free(ctx);
+ ctx = NULL;
+
+done:
+ debug_return_ptr(ctx);
+}
+#endif /* HAVE_OPENSSL */
diff --git a/m4/ax_append_flag.m4 b/m4/ax_append_flag.m4
new file mode 100644
index 0000000..dd6d8b6
--- /dev/null
+++ b/m4/ax_append_flag.m4
@@ -0,0 +1,50 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_append_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE])
+#
+# DESCRIPTION
+#
+# FLAG is appended to the FLAGS-VARIABLE shell variable, with a space
+# added in between.
+#
+# If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
+# CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains
+# FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly
+# FLAG.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 8
+
+AC_DEFUN([AX_APPEND_FLAG],
+[dnl
+AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF
+AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])
+AS_VAR_SET_IF(FLAGS,[
+ AS_CASE([" AS_VAR_GET(FLAGS) "],
+ [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])],
+ [
+ AS_VAR_APPEND(FLAGS,[" $1"])
+ AC_RUN_LOG([: FLAGS="$FLAGS"])
+ ])
+ ],
+ [
+ AS_VAR_SET(FLAGS,[$1])
+ AC_RUN_LOG([: FLAGS="$FLAGS"])
+ ])
+AS_VAR_POPDEF([FLAGS])dnl
+])dnl AX_APPEND_FLAG
diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4
new file mode 100644
index 0000000..bd753b3
--- /dev/null
+++ b/m4/ax_check_compile_flag.m4
@@ -0,0 +1,53 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+# Check whether the given FLAG works with the current language's compiler
+# or gives an error. (Warnings, however, are ignored)
+#
+# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+# success/failure.
+#
+# If EXTRA-FLAGS is defined, it is added to the current language's default
+# flags (e.g. CFLAGS) when the check is done. The check is thus made with
+# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
+# force the compiler to issue an error when a bad flag is given.
+#
+# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 6
+
+AC_DEFUN([AX_CHECK_COMPILE_FLAG],
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
+AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
+ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
+ _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
+ AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+ [AS_VAR_SET(CACHEVAR,[yes])],
+ [AS_VAR_SET(CACHEVAR,[no])])
+ _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
+AS_VAR_IF(CACHEVAR,yes,
+ [m4_default([$2], :)],
+ [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_COMPILE_FLAGS
diff --git a/m4/ax_check_link_flag.m4 b/m4/ax_check_link_flag.m4
new file mode 100644
index 0000000..e2d0d36
--- /dev/null
+++ b/m4/ax_check_link_flag.m4
@@ -0,0 +1,71 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS])
+#
+# DESCRIPTION
+#
+# Check whether the given FLAG works with the linker or gives an error.
+# (Warnings, however, are ignored)
+#
+# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+# success/failure.
+#
+# If EXTRA-FLAGS is defined, it is added to the linker's default flags
+# when the check is done. The check is thus made with the flags: "LDFLAGS
+# EXTRA-FLAGS FLAG". This can for example be used to force the linker to
+# issue an error when a bad flag is given.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 2
+
+AC_DEFUN([AX_CHECK_LINK_FLAG],
+[AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
+AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS $4 $1"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM()],
+ [AS_VAR_SET(CACHEVAR,[yes])],
+ [AS_VAR_SET(CACHEVAR,[no])])
+ LDFLAGS=$ax_check_save_flags])
+AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
+ [m4_default([$2], :)],
+ [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_LINK_FLAGS
diff --git a/m4/ax_func_getaddrinfo.m4 b/m4/ax_func_getaddrinfo.m4
new file mode 100644
index 0000000..7cde7b9
--- /dev/null
+++ b/m4/ax_func_getaddrinfo.m4
@@ -0,0 +1,70 @@
+#
+# SYNOPSIS
+#
+# AX_FUNC_GETADDRINFO
+#
+# DESCRIPTION
+#
+# Checks for the getaddrinfo function in the standard C library,
+# as well as the socket and inet libraries, if they are present.
+# If extra libraries are required, they are added to LIBS.
+# If no getaddrinfo function is found, it is added to LIBOBJS.
+# Note: Tru64 UNIX contains two versions of getaddrinfo and we must
+# include netdb.h to get the proper definition.
+#
+# LICENSE
+#
+# Placed in the public domain by Todd C. Miller on November 20, 2013.
+#
+
+AC_DEFUN([AX_FUNC_GETADDRINFO],
+[AC_MSG_CHECKING(for getaddrinfo)
+AC_CACHE_VAL(ax_cv_func_getaddrinfo,
+[AC_LINK_IFELSE([AC_LANG_SOURCE([[#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+int main() { return getaddrinfo(0, 0, 0, 0); }]])], [ax_cv_func_getaddrinfo=yes], [ax_cv_func_getaddrinfo=no])])
+AC_MSG_RESULT([$ax_cv_func_getaddrinfo])
+if test X"$ax_cv_func_getaddrinfo" = X"yes"; then
+ AC_DEFINE(HAVE_GETADDRINFO, 1, [Define to 1 if you have the 'getaddrinfo' function.])
+else
+ # Not found in libc, check libsocket and libinet
+ _found=no
+ for _libs in "-lsocket" "-linet" "-lsocket -lnsl"; do
+ _cv="ax_cv_lib_getaddrinfo`echo \"$_libs\"|sed -e 's/-l/_/g' -e 's/ *//g'`"
+ AC_MSG_CHECKING([for getaddrinfo in $_libs])
+ AC_CACHE_VAL([$_cv], [
+ _nlibs=
+ for _l in $_libs; do
+ case "$LIBS" in
+ *"$_l"*) ;;
+ *) _nlibs="$_nlibs $_l";;
+ esac
+ done
+ _libs="${_nlibs# }"
+ if test -z "$_libs"; then
+ # No new libs to check
+ eval $_cv=no
+ else
+ AX_FUNC_GETADDRINFO_OLIBS="$LIBS"
+ LIBS="$LIBS $_libs"
+ AC_LINK_IFELSE([AC_LANG_SOURCE([[#include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ int main() { return getaddrinfo(0, 0, 0, 0); }]])], [eval $_cv=yes], [eval $_cv=no])
+ LIBS="$AX_FUNC_GETADDRINFO_OLIBS"
+ fi
+ ])
+ if eval test \$$_cv = "yes"; then
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_GETADDRINFO)
+ test -n "$_libs" && LIBS="$LIBS $_libs"
+ break
+ fi
+ AC_MSG_RESULT([no])
+ done
+ if eval test \$$_cv != "yes"; then
+ AC_LIBOBJ(getaddrinfo)
+ fi
+fi
+])
diff --git a/m4/ax_func_snprintf.m4 b/m4/ax_func_snprintf.m4
new file mode 100644
index 0000000..dfaa03d
--- /dev/null
+++ b/m4/ax_func_snprintf.m4
@@ -0,0 +1,85 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_func_snprintf.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_FUNC_SNPRINTF
+#
+# DESCRIPTION
+#
+# Checks for a fully C99 compliant snprintf, in particular checks whether
+# it does bounds checking and returns the correct string length; does the
+# same check for vsnprintf. If no working snprintf or vsnprintf is found,
+# request a replacement and warn the user about it. Note: the mentioned
+# replacement is freely available and may be used in any project
+# regardless of it's license.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Ruediger Kuhlmann <info@ruediger-kuhlmann.de>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 7
+
+AU_ALIAS([AC_FUNC_SNPRINTF], [AX_FUNC_SNPRINTF])
+AC_DEFUN([AX_FUNC_SNPRINTF],
+[AC_CHECK_FUNCS(snprintf vsnprintf)
+AC_MSG_CHECKING(for working snprintf)
+AC_CACHE_VAL(ac_cv_have_working_snprintf,
+[AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <stdio.h>
+#include <string.h>
+
+int main(void)
+{
+ char bufs[5] = { 'x', 'x', 'x', '\0', '\0' };
+ char bufd[5] = { 'x', 'x', 'x', '\0', '\0' };
+ int i;
+ i = snprintf (bufs, 2, "%s", "111");
+ if (strcmp (bufs, "1")) return (1);
+ if (i != 3) return (1);
+ i = snprintf (bufd, 2, "%d", 111);
+ if (strcmp (bufd, "1")) return (1);
+ if (i != 3) return (1);
+ return(0);
+}]])],[ac_cv_have_working_snprintf=yes],[ac_cv_have_working_snprintf=no],[ac_cv_have_working_snprintf=cross])])
+AC_MSG_RESULT([$ac_cv_have_working_snprintf])
+AC_MSG_CHECKING(for working vsnprintf)
+AC_CACHE_VAL(ac_cv_have_working_vsnprintf,
+[AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+int my_vsnprintf (char *buf, const char *tmpl, ...)
+{
+ int i;
+ va_list args;
+ va_start (args, tmpl);
+ i = vsnprintf (buf, 2, tmpl, args);
+ va_end (args);
+ return i;
+}
+
+int main(void)
+{
+ char bufs[5] = { 'x', 'x', 'x', '\0', '\0' };
+ char bufd[5] = { 'x', 'x', 'x', '\0', '\0' };
+ int i;
+ i = my_vsnprintf (bufs, "%s", "111");
+ if (strcmp (bufs, "1")) return (1);
+ if (i != 3) return (1);
+ i = my_vsnprintf (bufd, "%d", 111);
+ if (strcmp (bufd, "1")) return (1);
+ if (i != 3) return (1);
+ return(0);
+}]])],[ac_cv_have_working_vsnprintf=yes],[ac_cv_have_working_vsnprintf=no],[ac_cv_have_working_vsnprintf=cross])])
+AC_MSG_RESULT([$ac_cv_have_working_vsnprintf])
+if test x$ac_cv_have_working_snprintf$ac_cv_have_working_vsnprintf != "xyesyes"; then
+ AC_LIBOBJ(snprintf)
+ AC_MSG_WARN([Replacing missing/broken (v)snprintf() with sudo's version.])
+ AC_DEFINE(PREFER_PORTABLE_SNPRINTF, 1, [Enable replacement (v)snprintf if system (v)snprintf is broken.])
+fi])
diff --git a/m4/ax_gcc_builtin.m4 b/m4/ax_gcc_builtin.m4
new file mode 100644
index 0000000..02e6147
--- /dev/null
+++ b/m4/ax_gcc_builtin.m4
@@ -0,0 +1,176 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_gcc_builtin.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_GCC_BUILTIN(BUILTIN)
+#
+# DESCRIPTION
+#
+# This macro checks if the compiler supports one of GCC's built-in
+# functions; many other compilers also provide those same built-ins.
+#
+# The BUILTIN parameter is the name of the built-in function.
+#
+# If BUILTIN is supported define HAVE_<BUILTIN>. Keep in mind that since
+# builtins usually start with two underscores they will be copied over
+# into the HAVE_<BUILTIN> definition (e.g. HAVE___BUILTIN_EXPECT for
+# __builtin_expect()).
+#
+# The macro caches its result in the ax_cv_have_<BUILTIN> variable (e.g.
+# ax_cv_have___builtin_expect).
+#
+# The macro currently supports the following built-in functions:
+#
+# __builtin_assume_aligned
+# __builtin_bswap16
+# __builtin_bswap32
+# __builtin_bswap64
+# __builtin_choose_expr
+# __builtin___clear_cache
+# __builtin_clrsb
+# __builtin_clrsbl
+# __builtin_clrsbll
+# __builtin_clz
+# __builtin_clzl
+# __builtin_clzll
+# __builtin_complex
+# __builtin_constant_p
+# __builtin_cpu_init
+# __builtin_cpu_is
+# __builtin_cpu_supports
+# __builtin_ctz
+# __builtin_ctzl
+# __builtin_ctzll
+# __builtin_expect
+# __builtin_ffs
+# __builtin_ffsl
+# __builtin_ffsll
+# __builtin_fpclassify
+# __builtin_huge_val
+# __builtin_huge_valf
+# __builtin_huge_vall
+# __builtin_inf
+# __builtin_infd128
+# __builtin_infd32
+# __builtin_infd64
+# __builtin_inff
+# __builtin_infl
+# __builtin_isinf_sign
+# __builtin_nan
+# __builtin_nand128
+# __builtin_nand32
+# __builtin_nand64
+# __builtin_nanf
+# __builtin_nanl
+# __builtin_nans
+# __builtin_nansf
+# __builtin_nansl
+# __builtin_object_size
+# __builtin_parity
+# __builtin_parityl
+# __builtin_parityll
+# __builtin_popcount
+# __builtin_popcountl
+# __builtin_popcountll
+# __builtin_powi
+# __builtin_powif
+# __builtin_powil
+# __builtin_prefetch
+# __builtin_trap
+# __builtin_types_compatible_p
+# __builtin_unreachable
+#
+# Unsupported built-ins will be tested with an empty parameter set and the
+# result of the check might be wrong or meaningless so use with care.
+#
+# LICENSE
+#
+# Copyright (c) 2013 Gabriele Svelto <gabriele.svelto@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 7
+
+AC_DEFUN([AX_GCC_BUILTIN], [
+ AS_VAR_PUSHDEF([ac_var], [ax_cv_have_$1])
+
+ AC_CACHE_CHECK([for $1], [ac_var], [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([], [
+ m4_case([$1],
+ [__builtin_assume_aligned], [$1("", 0)],
+ [__builtin_bswap16], [$1(0)],
+ [__builtin_bswap32], [$1(0)],
+ [__builtin_bswap64], [$1(0)],
+ [__builtin_choose_expr], [$1(0, 0, 0)],
+ [__builtin___clear_cache], [$1("", "")],
+ [__builtin_clrsb], [$1(0)],
+ [__builtin_clrsbl], [$1(0)],
+ [__builtin_clrsbll], [$1(0)],
+ [__builtin_clz], [$1(0)],
+ [__builtin_clzl], [$1(0)],
+ [__builtin_clzll], [$1(0)],
+ [__builtin_complex], [$1(0.0, 0.0)],
+ [__builtin_constant_p], [$1(0)],
+ [__builtin_cpu_init], [$1()],
+ [__builtin_cpu_is], [$1("intel")],
+ [__builtin_cpu_supports], [$1("sse")],
+ [__builtin_ctz], [$1(0)],
+ [__builtin_ctzl], [$1(0)],
+ [__builtin_ctzll], [$1(0)],
+ [__builtin_expect], [$1(0, 0)],
+ [__builtin_ffs], [$1(0)],
+ [__builtin_ffsl], [$1(0)],
+ [__builtin_ffsll], [$1(0)],
+ [__builtin_fpclassify], [$1(0, 1, 2, 3, 4, 0.0)],
+ [__builtin_huge_val], [$1()],
+ [__builtin_huge_valf], [$1()],
+ [__builtin_huge_vall], [$1()],
+ [__builtin_inf], [$1()],
+ [__builtin_infd128], [$1()],
+ [__builtin_infd32], [$1()],
+ [__builtin_infd64], [$1()],
+ [__builtin_inff], [$1()],
+ [__builtin_infl], [$1()],
+ [__builtin_isinf_sign], [$1(0.0)],
+ [__builtin_nan], [$1("")],
+ [__builtin_nand128], [$1("")],
+ [__builtin_nand32], [$1("")],
+ [__builtin_nand64], [$1("")],
+ [__builtin_nanf], [$1("")],
+ [__builtin_nanl], [$1("")],
+ [__builtin_nans], [$1("")],
+ [__builtin_nansf], [$1("")],
+ [__builtin_nansl], [$1("")],
+ [__builtin_object_size], [$1("", 0)],
+ [__builtin_parity], [$1(0)],
+ [__builtin_parityl], [$1(0)],
+ [__builtin_parityll], [$1(0)],
+ [__builtin_popcount], [$1(0)],
+ [__builtin_popcountl], [$1(0)],
+ [__builtin_popcountll], [$1(0)],
+ [__builtin_powi], [$1(0, 0)],
+ [__builtin_powif], [$1(0, 0)],
+ [__builtin_powil], [$1(0, 0)],
+ [__builtin_prefetch], [$1("")],
+ [__builtin_trap], [$1()],
+ [__builtin_types_compatible_p], [$1(int, int)],
+ [__builtin_unreachable], [$1()],
+ [m4_warn([syntax], [Unsupported built-in $1, the test may fail])
+ $1()]
+ )
+ ])],
+ [AS_VAR_SET([ac_var], [yes])],
+ [AS_VAR_SET([ac_var], [no])])
+ ])
+
+ AS_IF([test yes = AS_VAR_GET([ac_var])],
+ [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$1), 1,
+ [Define to 1 if you have the '$1' built-in function])], [])
+
+ AS_VAR_POPDEF([ac_var])
+])
diff --git a/m4/ax_prog_cc_for_build.m4 b/m4/ax_prog_cc_for_build.m4
new file mode 100644
index 0000000..33eaa38
--- /dev/null
+++ b/m4/ax_prog_cc_for_build.m4
@@ -0,0 +1,155 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PROG_CC_FOR_BUILD
+#
+# DESCRIPTION
+#
+# This macro searches for a C compiler that generates native executables,
+# that is a C compiler that surely is not a cross-compiler. This can be
+# useful if you have to generate source code at compile-time like for
+# example GCC does.
+#
+# The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything
+# needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD).
+# The value of these variables can be overridden by the user by specifying
+# a compiler with an environment variable (like you do for standard CC).
+#
+# It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object
+# file extensions for the build platform, and GCC_FOR_BUILD to `yes' if
+# the compiler we found is GCC. All these variables but GCC_FOR_BUILD are
+# substituted in the Makefile.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Paolo Bonzini <bonzini@gnu.org>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 21
+
+AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD])
+AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_CPP])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+
+dnl Use the standard macros, but make them use other variable names
+dnl
+pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl
+pushdef([ac_cv_prog_cc_c89], ac_cv_build_prog_cc_c89)dnl
+pushdef([ac_cv_prog_cc_c99], ac_cv_build_prog_cc_c99)dnl
+pushdef([ac_cv_prog_cc_c11], ac_cv_build_prog_cc_c11)dnl
+pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl
+pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl
+pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl
+pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl
+pushdef([ac_cv_c_compiler_gnu], ac_cv_build_c_compiler_gnu)dnl
+pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl
+pushdef([ac_cv_objext], ac_cv_build_objext)dnl
+pushdef([ac_exeext], ac_build_exeext)dnl
+pushdef([ac_objext], ac_build_objext)dnl
+pushdef([CC], CC_FOR_BUILD)dnl
+pushdef([CPP], CPP_FOR_BUILD)dnl
+pushdef([GCC], GCC_FOR_BUILD)dnl
+pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl
+pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl
+pushdef([EXEEXT], BUILD_EXEEXT)dnl
+pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl
+pushdef([OBJEXT], BUILD_OBJEXT)dnl
+pushdef([host], build)dnl
+pushdef([host_alias], build_alias)dnl
+pushdef([host_cpu], build_cpu)dnl
+pushdef([host_vendor], build_vendor)dnl
+pushdef([host_os], build_os)dnl
+pushdef([ac_cv_host], ac_cv_build)dnl
+pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl
+pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl
+pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl
+pushdef([ac_cv_host_os], ac_cv_build_os)dnl
+pushdef([ac_tool_prefix], ac_build_tool_prefix)dnl
+pushdef([am_cv_CC_dependencies_compiler_type], am_cv_build_CC_dependencies_compiler_type)dnl
+pushdef([am_cv_prog_cc_c_o], am_cv_build_prog_cc_c_o)dnl
+pushdef([cross_compiling], cross_compiling_build)dnl
+
+cross_compiling_build=no
+
+ac_build_tool_prefix=
+AS_IF([test -n "$build"], [ac_build_tool_prefix="$build-"],
+ [test -n "$build_alias"],[ac_build_tool_prefix="$build_alias-"])
+
+AC_LANG_PUSH([C])
+
+dnl The pushdef([ac_cv_c_compiler_gnu], ...) currently does not cover
+dnl the use of this variable in _AC_LANG_COMPILER_GNU called by
+dnl AC_PROG_CC. Unset this cache variable temporarily as a workaround.
+was_set_c_compiler_gnu=${[ac_cv_c_compiler_gnu]+y}
+AS_IF([test ${was_set_c_compiler_gnu}],
+ [saved_c_compiler_gnu=$[ac_cv_c_compiler_gnu]
+ AS_UNSET([[ac_cv_c_compiler_gnu]])])
+
+AC_PROG_CC
+
+dnl Restore ac_cv_c_compiler_gnu
+AS_IF([test ${was_set_c_compiler_gnu}],
+ [[ac_cv_c_compiler_gnu]=$[saved_c_compiler_gnu]])
+
+_AC_COMPILER_EXEEXT
+_AC_COMPILER_OBJEXT
+AC_PROG_CPP
+
+dnl Restore the old definitions
+dnl
+popdef([cross_compiling])dnl
+popdef([am_cv_prog_cc_c_o])dnl
+popdef([am_cv_CC_dependencies_compiler_type])dnl
+popdef([ac_tool_prefix])dnl
+popdef([ac_cv_host_os])dnl
+popdef([ac_cv_host_vendor])dnl
+popdef([ac_cv_host_cpu])dnl
+popdef([ac_cv_host_alias])dnl
+popdef([ac_cv_host])dnl
+popdef([host_os])dnl
+popdef([host_vendor])dnl
+popdef([host_cpu])dnl
+popdef([host_alias])dnl
+popdef([host])dnl
+popdef([OBJEXT])dnl
+popdef([LDFLAGS])dnl
+popdef([EXEEXT])dnl
+popdef([CPPFLAGS])dnl
+popdef([CFLAGS])dnl
+popdef([GCC])dnl
+popdef([CPP])dnl
+popdef([CC])dnl
+popdef([ac_objext])dnl
+popdef([ac_exeext])dnl
+popdef([ac_cv_objext])dnl
+popdef([ac_cv_exeext])dnl
+popdef([ac_cv_c_compiler_gnu])dnl
+popdef([ac_cv_prog_cc_g])dnl
+popdef([ac_cv_prog_cc_cross])dnl
+popdef([ac_cv_prog_cc_works])dnl
+popdef([ac_cv_prog_cc_c89])dnl
+popdef([ac_cv_prog_gcc])dnl
+popdef([ac_cv_prog_CPP])dnl
+
+dnl restore global variables ac_ext, ac_cpp, ac_compile,
+dnl ac_link, ac_compiler_gnu (dependent on the current
+dnl language after popping):
+AC_LANG_POP([C])
+
+dnl Finally, set Makefile variables
+dnl
+AC_SUBST(BUILD_EXEEXT)dnl
+AC_SUBST(BUILD_OBJEXT)dnl
+AC_SUBST([CFLAGS_FOR_BUILD])dnl
+AC_SUBST([CPPFLAGS_FOR_BUILD])dnl
+AC_SUBST([LDFLAGS_FOR_BUILD])dnl
+])
diff --git a/m4/gettext.m4 b/m4/gettext.m4
new file mode 100644
index 0000000..f25bf7b
--- /dev/null
+++ b/m4/gettext.m4
@@ -0,0 +1,61 @@
+AC_DEFUN([SUDO_CHECK_GETTEXT], [
+ # gettext() and friends may be located in libc (Linux and Solaris)
+ # or in libintl. However, it is possible to have libintl installed
+ # even when gettext() is present in libc. In the case of GNU libintl,
+ # gettext() will be defined to gettext_libintl in libintl.h.
+ # Since gcc prefers /usr/local/include to /usr/include, we need to
+ # make sure we use the gettext() that matches the include file.
+ if test "$enable_nls" != "no"; then
+ if test "$enable_nls" != "yes"; then
+ AX_APPEND_FLAG([-I${enable_nls}/include], [CPPFLAGS])
+ SUDO_APPEND_LIBPATH(LDFLAGS, [$enable_nls/lib])
+ fi
+ OLIBS="$LIBS"
+ for l in "libc" "-lintl" "-lintl -liconv"; do
+ if test "$l" = "libc"; then
+ # If user specified a dir for libintl ignore libc
+ if test "$enable_nls" != "yes"; then
+ continue
+ fi
+ gettext_name=sudo_cv_gettext
+ AC_MSG_CHECKING([for gettext])
+ else
+ LIBS="$OLIBS $l"
+ gettext_name=sudo_cv_gettext"`echo $l|sed -e 's/ //g' -e 's/-/_/g'`"
+ AC_MSG_CHECKING([for gettext in $l])
+ fi
+ AC_CACHE_VAL($gettext_name, [
+ AC_LINK_IFELSE(
+ [
+ AC_LANG_PROGRAM([[#include <libintl.h>]], [(void)gettext((char *)0);])
+ ], [eval $gettext_name=yes], [eval $gettext_name=no]
+ )
+ ])
+ eval gettext_result="\$$gettext_name"
+ AC_MSG_RESULT($gettext_result)
+ if test "$gettext_result" = "yes"; then
+ AC_CHECK_FUNCS([ngettext])
+ break
+ fi
+ done
+ LIBS="$OLIBS"
+
+ if test "$sudo_cv_gettext" = "yes"; then
+ SUDO_NLS=enabled
+ # For Solaris we need links from lang to lang.UTF-8 in localedir
+ case "$host_os" in
+ solaris2*) LOCALEDIR_SUFFIX=".UTF-8";;
+ esac
+ elif test "$sudo_cv_gettext_lintl" = "yes"; then
+ SUDO_NLS=enabled
+ LIBINTL="-lintl"
+ elif test "$sudo_cv_gettext_lintl_liconv" = "yes"; then
+ SUDO_NLS=enabled
+ LIBINTL="-lintl -liconv"
+ fi
+ if test X"$SUDO_NLS" = X"enabled"; then
+ AC_DEFINE(HAVE_LIBINTL_H)
+ SUDO_APPEND_COMPAT_EXP(sudo_warn_gettext_v1)
+ fi
+ fi
+])
diff --git a/m4/hardening.m4 b/m4/hardening.m4
new file mode 100644
index 0000000..45c501f
--- /dev/null
+++ b/m4/hardening.m4
@@ -0,0 +1,119 @@
+AC_DEFUN([SUDO_CHECK_HARDENING], [
+ if test "$enable_hardening" != "no"; then
+ #
+ # Attempt to use _FORTIFY_SOURCE with sprintf. If the headers support
+ # it but libc does not, __sprintf_chk should be an undefined symbol.
+ #
+ O_CPPFLAGS="$CPPFLAGS"
+ AX_APPEND_FLAG([-D_FORTIFY_SOURCE=2], [CPPFLAGS])
+ AC_CACHE_CHECK([whether _FORTIFY_SOURCE may be specified],
+ [sudo_cv_use_fortify_source],
+ [AC_LINK_IFELSE([
+ AC_LANG_PROGRAM(
+ [[#include <stdio.h>]],
+ [[char buf[4]; sprintf(buf, "%s", "foo"); return buf[0];]]
+ )],
+ [sudo_cv_use_fortify_source=yes],
+ [sudo_cv_use_fortify_source=no]
+ )
+ ]
+ )
+ if test "$sudo_cv_use_fortify_source" != yes; then
+ CPPFLAGS="$O_CPPFLAGS"
+ fi
+
+ dnl
+ dnl The following tests rely on AC_LANG_WERROR.
+ dnl
+ if test -n "$GCC" -a "$enable_ssp" != "no"; then
+ AC_CACHE_CHECK([for compiler stack protector support],
+ [sudo_cv_var_stack_protector],
+ [
+ # Avoid CFLAGS since the compiler might optimize away our
+ # test. We don't want CPPFLAGS or LIBS to interfere with
+ # the test but keep LDFLAGS as it may have an rpath needed
+ # to find the ssp lib.
+ _CPPFLAGS="$CPPFLAGS"
+ _CFLAGS="$CFLAGS"
+ _LDFLAGS="$LDFLAGS"
+ _LIBS="$LIBS"
+ CPPFLAGS=
+ LIBS=
+
+ sudo_cv_var_stack_protector="-fstack-protector-strong"
+ CFLAGS="$sudo_cv_var_stack_protector"
+ LDFLAGS="$_LDFLAGS $sudo_cv_var_stack_protector"
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
+ [[char buf[1024]; buf[1023] = '\0';]])
+ ], [], [
+ sudo_cv_var_stack_protector="-fstack-protector-all"
+ CFLAGS="$sudo_cv_var_stack_protector"
+ LDFLAGS="$_LDFLAGS $sudo_cv_var_stack_protector"
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
+ [[char buf[1024]; buf[1023] = '\0';]])
+ ], [], [
+ sudo_cv_var_stack_protector="-fstack-protector"
+ CFLAGS="$sudo_cv_var_stack_protector"
+ LDFLAGS="$_LDFLAGS $sudo_cv_var_stack_protector"
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
+ [[char buf[1024]; buf[1023] = '\0';]])
+ ], [], [
+ sudo_cv_var_stack_protector=no
+ ])
+ ])
+ ])
+ CPPFLAGS="$_CPPFLAGS"
+ CFLAGS="$_CFLAGS"
+ LDFLAGS="$_LDFLAGS"
+ LIBS="$_LIBS"
+ ]
+ )
+ if test X"$sudo_cv_var_stack_protector" != X"no"; then
+ HARDENING_CFLAGS="$sudo_cv_var_stack_protector"
+ HARDENING_LDFLAGS="-Wc,$sudo_cv_var_stack_protector"
+ fi
+ fi
+
+ # The gcc front-end may accept -fstack-clash-protection even if the
+ # machine-specific code does not support it. We use a test program
+ # with a large stack allocation to try to cause the compiler to
+ # insert the stack clash protection code, or fail if not supported.
+ if test -n "$GCC"; then
+ AC_CACHE_CHECK([whether C compiler supports -fstack-clash-protection],
+ [sudo_cv_check_cflags___fstack_clash_protection],
+ [
+ _CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fstack-clash-protection"
+ AC_COMPILE_IFELSE([
+ AC_LANG_SOURCE([[int main(int argc, char *argv[]) { char buf[16384], *src = argv[0], *dst = buf; while ((*dst++ = *src++) != '\0') { continue; } return buf[argc]; }]])
+ ], [sudo_cv_check_cflags___fstack_clash_protection=yes], [sudo_cv_check_cflags___fstack_clash_protection=no])
+ CFLAGS="$_CFLAGS"
+ ]
+ )
+ if test X"$sudo_cv_check_cflags___fstack_clash_protection" = X"yes"; then
+ AX_CHECK_LINK_FLAG([-fstack-clash-protection], [
+ AX_APPEND_FLAG([-fstack-clash-protection], [HARDENING_CFLAGS])
+ AX_APPEND_FLAG([-Wc,-fstack-clash-protection], [HARDENING_LDFLAGS])
+ ])
+ fi
+
+ # Check for control-flow transfer instrumentation (Intel CET).
+ AX_CHECK_COMPILE_FLAG([-fcf-protection], [
+ AX_CHECK_LINK_FLAG([-fcf-protection], [
+ AX_APPEND_FLAG([-fcf-protection], [HARDENING_CFLAGS])
+ AX_APPEND_FLAG([-Wc,-fcf-protection], [HARDENING_LDFLAGS])
+ ])
+ ])
+ fi
+
+ # Linker-specific hardening flags.
+ if test X"$with_gnu_ld" = X"yes"; then
+ # GNU ld, and similar (gold, lld, etc).
+ AX_CHECK_LINK_FLAG([-Wl,-z,relro], [AX_APPEND_FLAG([-Wl,-z,relro], [HARDENING_LDFLAGS])])
+ AX_CHECK_LINK_FLAG([-Wl,-z,now], [AX_APPEND_FLAG([-Wl,-z,now], [HARDENING_LDFLAGS])])
+ AX_CHECK_LINK_FLAG([-Wl,-z,noexecstack], [AX_APPEND_FLAG([-Wl,-z,noexecstack], [HARDENING_LDFLAGS])])
+ fi
+ fi])
diff --git a/m4/ldap.m4 b/m4/ldap.m4
new file mode 100644
index 0000000..39f2e35
--- /dev/null
+++ b/m4/ldap.m4
@@ -0,0 +1,130 @@
+AC_DEFUN([SUDO_CHECK_LDAP], [
+ if test ${with_ldap-'no'} != "no"; then
+ O_LDFLAGS="$LDFLAGS"
+ if test "$with_ldap" != "yes"; then
+ SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${with_ldap}/lib])
+ LDFLAGS="$LDFLAGS -L${with_ldap}/lib"
+ if test -d "${with_ldap}/lib64"; then
+ SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${with_ldap}/lib64])
+ LDFLAGS="$LDFLAGS -L${with_ldap}/lib64"
+ fi
+ AX_APPEND_FLAG([-I${with_ldap}/include], [CPPFLAGS])
+ with_ldap=yes
+ fi
+ SUDOERS_OBJS="${SUDOERS_OBJS} ldap.lo ldap_conf.lo ldap_innetgr.lo"
+ case "$SUDOERS_OBJS" in
+ *ldap_util.lo*) ;;
+ *) SUDOERS_OBJS="${SUDOERS_OBJS} ldap_util.lo";;
+ esac
+ LDAP=""
+
+ _LIBS="$LIBS"
+ LDAP_LIBS=""
+ IBMLDAP_EXTRA=""
+ found=no
+ # On HP-UX, libibmldap has a hidden dependency on libCsup
+ case "$host_os" in
+ hpux*) AC_CHECK_LIB([Csup], [main], [IBMLDAP_EXTRA=" -lCsup"]);;
+ esac
+ AC_SEARCH_LIBS([ldap_init], ["ibmldap${IBMLDAP_EXTRA}" "ibmldap -lidsldif${IBMLDAP_EXTRA}" "ldap" "ldap -llber" "ldap -llber -lssl -lcrypto" "ibmldap${IBMLDAP_EXTRA}]", [
+ test "${ac_cv_search_ldap_init}" != "none required" && LDAP_LIBS="${ac_cv_search_ldap_init}"
+ found=yes
+ ])
+ # If nothing linked, try -lldap and hope for the best
+ if test "$found" = "no"; then
+ LDAP_LIBS="-lldap"
+ fi
+ LIBS="${_LIBS} ${LDAP_LIBS}"
+
+ AC_CHECK_DECL([LBER_OPT_DEBUG_LEVEL], [
+ case "$LDAP_LIBS" in
+ *-llber*)
+ # Already linking with -llber
+ ;;
+ *) # Link with -llber for ber_set_option() if it exists
+ AC_CHECK_LIB([lber], [ber_set_option], [found=yes], [found=no])
+ if test X"$found" = X"yes"; then
+ LDAP_LIBS="$LDAP_LIBS -llber"
+ fi
+ ;;
+ esac
+ ], [], [AC_INCLUDES_DEFAULT
+#include <lber.h>])
+ AC_CACHE_CHECK([whether lber.h is needed when including ldap.h], [sudo_cv_header_lber_h], [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
+#include <ldap.h>]], [[return ldap_msgfree(NULL)]])], [
+ # No need to explicitly include lber.h when including ldap.h.
+ sudo_cv_header_lber_h=no
+ ], [
+ sudo_cv_header_lber_h=yes
+ ])
+ ])
+ if test X"$sudo_cv_header_lber_h" = X"yes"; then
+ AC_DEFINE(HAVE_LBER_H)
+ fi
+
+ if test ${enable_sasl-'yes'} = "yes"; then
+ found_sasl_h=no
+ AC_CHECK_HEADERS([sasl/sasl.h] [sasl.h], [
+ found_sasl_h=yes
+ AC_CHECK_FUNCS([ldap_sasl_interactive_bind_s])
+ break
+ ])
+ if test X${enable_sasl} = X"yes"; then
+ if test X"$found_sasl_h" != X"yes"; then
+ AC_MSG_ERROR([--enable-sasl specified but unable to locate SASL development headers.])
+ fi
+ if test X"$ac_cv_func_ldap_sasl_interactive_bind_s" != X"yes"; then :
+ AC_MSG_ERROR([--enable-sasl specified but SASL support is missing in your LDAP library])
+ fi
+ fi
+ fi
+ AC_CHECK_HEADERS([ldapssl.h] [ldap_ssl.h] [mps/ldap_ssl.h], [break], [], [#include <ldap.h>])
+ AC_CHECK_FUNCS([ldap_initialize ldap_start_tls_s ldapssl_init ldapssl_set_strength ldap_unbind_ext_s ldap_str2dn ldap_create ldap_sasl_bind_s ldap_ssl_init ldap_ssl_client_init ldap_start_tls_s_np])
+ AC_CHECK_FUNCS([ldap_search_ext_s ldap_search_st], [break])
+
+ if test X"$check_gss_krb5_ccache_name" = X"yes"; then
+ AC_CHECK_LIB([gssapi], [gss_krb5_ccache_name], [
+ AC_DEFINE(HAVE_GSS_KRB5_CCACHE_NAME)
+ LDAP_LIBS="${LDAP_LIBS} -lgssapi"
+ ], [
+ AC_CHECK_LIB(gssapi_krb5, gss_krb5_ccache_name, [
+ AC_DEFINE(HAVE_GSS_KRB5_CCACHE_NAME)
+ LDAP_LIBS="${LDAP_LIBS} -lgssapi_krb5"
+ ])
+ ])
+
+ # gssapi headers may be separate or part of Kerberos V
+ found=no
+ O_CPPFLAGS="$CPPFLAGS"
+ for dir in "" "kerberosV" "krb5" "kerberos5" "kerberosv5"; do
+ test X"$dir" != X"" && CPPFLAGS="$O_CPPFLAGS -I/usr/include/${dir}"
+ # Use AC_PREPROC_IFELSE to check existence to avoid caching
+ # since we test with multiple values of CPPFLAGS
+ AC_PREPROC_IFELSE([
+ AC_LANG_PROGRAM([[#include <gssapi/gssapi.h>]])
+ ], [
+ AC_CHECK_HEADERS([gssapi/gssapi.h])
+ break
+ ], [
+ AC_PREPROC_IFELSE([
+ AC_LANG_PROGRAM([[#include <gssapi.h>]])
+ ], [
+ AC_CHECK_HEADERS([gssapi.h])
+ break
+ ])
+ ])
+ done
+ if test X"$ac_cv_header_gssapi_gssapi_h" != X"no"; then
+ AC_CHECK_HEADERS([gssapi/gssapi_krb5.h])
+ elif test X"$ac_cv_header_gssapi_h" = X"no"; then
+ CPPFLAGS="$O_CPPFLAGS"
+ AC_MSG_WARN([unable to locate gssapi.h, you will have to edit the Makefile and add -I/path/to/gssapi/includes to CPPFLAGS])
+ fi
+ fi
+
+ SUDOERS_LIBS="${SUDOERS_LIBS} ${LDAP_LIBS}"
+ LIBS="$_LIBS"
+ LDFLAGS="$O_LDFLAGS"
+ fi
+])
diff --git a/m4/libtool.m4 b/m4/libtool.m4
new file mode 100644
index 0000000..afdadd8
--- /dev/null
+++ b/m4/libtool.m4
@@ -0,0 +1,8459 @@
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+#
+# Copyright (C) 1996-2001, 2003-2019, 2021-2022 Free Software
+# Foundation, Inc.
+# Written by Gordon Matzigkeit, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+m4_define([_LT_COPYING], [dnl
+# Copyright (C) 2014 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions. There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program or library that is built
+# using GNU Libtool, you may include this file under the same
+# distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+])
+
+# serial 59 LT_INIT
+
+
+# LT_PREREQ(VERSION)
+# ------------------
+# Complain and exit if this libtool version is less that VERSION.
+m4_defun([LT_PREREQ],
+[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
+ [m4_default([$3],
+ [m4_fatal([Libtool version $1 or higher is required],
+ 63)])],
+ [$2])])
+
+
+# _LT_CHECK_BUILDDIR
+# ------------------
+# Complain if the absolute build directory name contains unusual characters
+m4_defun([_LT_CHECK_BUILDDIR],
+[case `pwd` in
+ *\ * | *\ *)
+ AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
+esac
+])
+
+
+# LT_INIT([OPTIONS])
+# ------------------
+AC_DEFUN([LT_INIT],
+[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK
+AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+AC_BEFORE([$0], [LT_LANG])dnl
+AC_BEFORE([$0], [LT_OUTPUT])dnl
+AC_BEFORE([$0], [LTDL_INIT])dnl
+m4_require([_LT_CHECK_BUILDDIR])dnl
+
+dnl Autoconf doesn't catch unexpanded LT_ macros by default:
+m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
+m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
+dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
+dnl unless we require an AC_DEFUNed macro:
+AC_REQUIRE([LTOPTIONS_VERSION])dnl
+AC_REQUIRE([LTSUGAR_VERSION])dnl
+AC_REQUIRE([LTVERSION_VERSION])dnl
+AC_REQUIRE([LTOBSOLETE_VERSION])dnl
+m4_require([_LT_PROG_LTMAIN])dnl
+
+_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])
+
+dnl Parse OPTIONS
+_LT_SET_OPTIONS([$0], [$1])
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS=$ltmain
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+_LT_SETUP
+
+# Only expand once:
+m4_define([LT_INIT])
+])# LT_INIT
+
+# Old names:
+AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
+AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
+dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
+
+
+# _LT_PREPARE_CC_BASENAME
+# -----------------------
+m4_defun([_LT_PREPARE_CC_BASENAME], [
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+ for cc_temp in @S|@*""; do
+ case $cc_temp in
+ compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+ distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+ done
+ func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+])# _LT_PREPARE_CC_BASENAME
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME,
+# but that macro is also expanded into generated libtool script, which
+# arranges for $SED and $ECHO to be set by different means.
+m4_defun([_LT_CC_BASENAME],
+[m4_require([_LT_PREPARE_CC_BASENAME])dnl
+AC_REQUIRE([_LT_DECL_SED])dnl
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+func_cc_basename $1
+cc_basename=$func_cc_basename_result
+])
+
+
+# _LT_FILEUTILS_DEFAULTS
+# ----------------------
+# It is okay to use these file commands and assume they have been set
+# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'.
+m4_defun([_LT_FILEUTILS_DEFAULTS],
+[: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+])# _LT_FILEUTILS_DEFAULTS
+
+
+# _LT_SETUP
+# ---------
+m4_defun([_LT_SETUP],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+
+_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl
+dnl
+_LT_DECL([], [host_alias], [0], [The host system])dnl
+_LT_DECL([], [host], [0])dnl
+_LT_DECL([], [host_os], [0])dnl
+dnl
+_LT_DECL([], [build_alias], [0], [The build system])dnl
+_LT_DECL([], [build], [0])dnl
+_LT_DECL([], [build_os], [0])dnl
+dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+test -z "$LN_S" && LN_S="ln -s"
+_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
+dnl
+AC_REQUIRE([LT_CMD_MAX_LEN])dnl
+_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
+_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
+dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
+m4_require([_LT_CMD_RELOAD])dnl
+m4_require([_LT_DECL_FILECMD])dnl
+m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
+m4_require([_LT_CMD_OLD_ARCHIVE])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_WITH_SYSROOT])dnl
+m4_require([_LT_CMD_TRUNCATE])dnl
+
+_LT_CONFIG_LIBTOOL_INIT([
+# See if we are running on zsh, and set the options that allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+fi
+])
+if test -n "${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+fi
+
+_LT_CHECK_OBJDIR
+
+m4_require([_LT_TAG_COMPILER])dnl
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test set != "${COLLECT_NAMES+set}"; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a '.a' archive for static linking (except MSVC and
+# ICC, which need '.lib').
+libext=a
+
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+old_CC=$CC
+old_CFLAGS=$CFLAGS
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ _LT_PATH_MAGIC
+ fi
+ ;;
+esac
+
+# Use C for the default configuration in the libtool script
+LT_SUPPORTED_TAG([CC])
+_LT_LANG_C_CONFIG
+_LT_LANG_DEFAULT_CONFIG
+_LT_CONFIG_COMMANDS
+])# _LT_SETUP
+
+
+# _LT_PREPARE_SED_QUOTE_VARS
+# --------------------------
+# Define a few sed substitution that help us do robust quoting.
+m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
+[# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([["`\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+])
+
+# _LT_PROG_LTMAIN
+# ---------------
+# Note that this code is called both from 'configure', and 'config.status'
+# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably,
+# 'config.status' has no value for ac_aux_dir unless we are using Automake,
+# so we pass a copy along to make sure it has a sensible value anyway.
+m4_defun([_LT_PROG_LTMAIN],
+[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
+_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
+ltmain=$ac_aux_dir/ltmain.sh
+])# _LT_PROG_LTMAIN
+
+
+## ------------------------------------- ##
+## Accumulate code for creating libtool. ##
+## ------------------------------------- ##
+
+# So that we can recreate a full libtool script including additional
+# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
+# in macros and then make a single call at the end using the 'libtool'
+# label.
+
+
+# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
+# ----------------------------------------
+# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL_INIT],
+[m4_ifval([$1],
+ [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
+ [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_INIT])
+
+
+# _LT_CONFIG_LIBTOOL([COMMANDS])
+# ------------------------------
+# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL],
+[m4_ifval([$1],
+ [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
+ [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
+
+
+# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
+# -----------------------------------------------------
+m4_defun([_LT_CONFIG_SAVE_COMMANDS],
+[_LT_CONFIG_LIBTOOL([$1])
+_LT_CONFIG_LIBTOOL_INIT([$2])
+])
+
+
+# _LT_FORMAT_COMMENT([COMMENT])
+# -----------------------------
+# Add leading comment marks to the start of each line, and a trailing
+# full-stop to the whole comment if one is not present already.
+m4_define([_LT_FORMAT_COMMENT],
+[m4_ifval([$1], [
+m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
+ [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
+)])
+
+
+
+## ------------------------ ##
+## FIXME: Eliminate VARNAME ##
+## ------------------------ ##
+
+
+# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
+# -------------------------------------------------------------------
+# CONFIGNAME is the name given to the value in the libtool script.
+# VARNAME is the (base) name used in the configure script.
+# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
+# VARNAME. Any other value will be used directly.
+m4_define([_LT_DECL],
+[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
+ [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
+ [m4_ifval([$1], [$1], [$2])])
+ lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
+ m4_ifval([$4],
+ [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
+ lt_dict_add_subkey([lt_decl_dict], [$2],
+ [tagged?], [m4_ifval([$5], [yes], [no])])])
+])
+
+
+# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
+# --------------------------------------------------------
+m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
+
+
+# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_tag_varnames],
+[_lt_decl_filter([tagged?], [yes], $@)])
+
+
+# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
+# ---------------------------------------------------------
+m4_define([_lt_decl_filter],
+[m4_case([$#],
+ [0], [m4_fatal([$0: too few arguments: $#])],
+ [1], [m4_fatal([$0: too few arguments: $#: $1])],
+ [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
+ [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
+ [lt_dict_filter([lt_decl_dict], $@)])[]dnl
+])
+
+
+# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
+# --------------------------------------------------
+m4_define([lt_decl_quote_varnames],
+[_lt_decl_filter([value], [1], $@)])
+
+
+# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_dquote_varnames],
+[_lt_decl_filter([value], [2], $@)])
+
+
+# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_varnames_tagged],
+[m4_assert([$# <= 2])dnl
+_$0(m4_quote(m4_default([$1], [[, ]])),
+ m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
+ m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
+m4_define([_lt_decl_varnames_tagged],
+[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
+
+
+# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_all_varnames],
+[_$0(m4_quote(m4_default([$1], [[, ]])),
+ m4_if([$2], [],
+ m4_quote(lt_decl_varnames),
+ m4_quote(m4_shift($@))))[]dnl
+])
+m4_define([_lt_decl_all_varnames],
+[lt_join($@, lt_decl_varnames_tagged([$1],
+ lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
+])
+
+
+# _LT_CONFIG_STATUS_DECLARE([VARNAME])
+# ------------------------------------
+# Quote a variable value, and forward it to 'config.status' so that its
+# declaration there will have the same value as in 'configure'. VARNAME
+# must have a single quote delimited value for this to work.
+m4_define([_LT_CONFIG_STATUS_DECLARE],
+[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])
+
+
+# _LT_CONFIG_STATUS_DECLARATIONS
+# ------------------------------
+# We delimit libtool config variables with single quotes, so when
+# we write them to config.status, we have to be sure to quote all
+# embedded single quotes properly. In configure, this macro expands
+# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
+#
+# <var>='`$ECHO "$<var>" | $SED "$delay_single_quote_subst"`'
+m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
+ [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAGS
+# ----------------
+# Output comment and list of tags supported by the script
+m4_defun([_LT_LIBTOOL_TAGS],
+[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
+available_tags='_LT_TAGS'dnl
+])
+
+
+# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
+# -----------------------------------
+# Extract the dictionary values for VARNAME (optionally with TAG) and
+# expand to a commented shell variable setting:
+#
+# # Some comment about what VAR is for.
+# visible_name=$lt_internal_name
+m4_define([_LT_LIBTOOL_DECLARE],
+[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
+ [description])))[]dnl
+m4_pushdef([_libtool_name],
+ m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
+m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
+ [0], [_libtool_name=[$]$1],
+ [1], [_libtool_name=$lt_[]$1],
+ [2], [_libtool_name=$lt_[]$1],
+ [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
+m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
+])
+
+
+# _LT_LIBTOOL_CONFIG_VARS
+# -----------------------
+# Produce commented declarations of non-tagged libtool config variables
+# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool'
+# script. Tagged libtool config variables (even for the LIBTOOL CONFIG
+# section) are produced by _LT_LIBTOOL_TAG_VARS.
+m4_defun([_LT_LIBTOOL_CONFIG_VARS],
+[m4_foreach([_lt_var],
+ m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
+ [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAG_VARS(TAG)
+# -------------------------
+m4_define([_LT_LIBTOOL_TAG_VARS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
+ [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
+
+
+# _LT_TAGVAR(VARNAME, [TAGNAME])
+# ------------------------------
+m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
+
+
+# _LT_CONFIG_COMMANDS
+# -------------------
+# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of
+# variables for single and double quote escaping we saved from calls
+# to _LT_DECL, we can put quote escaped variables declarations
+# into 'config.status', and then the shell code to quote escape them in
+# for loops in 'config.status'. Finally, any additional code accumulated
+# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
+m4_defun([_LT_CONFIG_COMMANDS],
+[AC_PROVIDE_IFELSE([LT_OUTPUT],
+ dnl If the libtool generation code has been placed in $CONFIG_LT,
+ dnl instead of duplicating it all over again into config.status,
+ dnl then we will have config.status run $CONFIG_LT later, so it
+ dnl needs to know what name is stored there:
+ [AC_CONFIG_COMMANDS([libtool],
+ [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
+ dnl If the libtool generation code is destined for config.status,
+ dnl expand the accumulated commands and init code now:
+ [AC_CONFIG_COMMANDS([libtool],
+ [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
+])#_LT_CONFIG_COMMANDS
+
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
+[
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+_LT_CONFIG_STATUS_DECLARATIONS
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+\$[]1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_quote_varnames); do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[[\\\\\\\`\\"\\\$]]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+# Double-quote double-evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_dquote_varnames); do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[[\\\\\\\`\\"\\\$]]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+_LT_OUTPUT_LIBTOOL_INIT
+])
+
+# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
+# ------------------------------------
+# Generate a child script FILE with all initialization necessary to
+# reuse the environment learned by the parent script, and make the
+# file executable. If COMMENT is supplied, it is inserted after the
+# '#!' sequence but before initialization text begins. After this
+# macro, additional text can be appended to FILE to form the body of
+# the child script. The macro ends with non-zero status if the
+# file could not be fully written (such as if the disk is full).
+m4_ifdef([AS_INIT_GENERATED],
+[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
+[m4_defun([_LT_GENERATED_FILE_INIT],
+[m4_require([AS_PREPARE])]dnl
+[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
+[lt_write_fail=0
+cat >$1 <<_ASEOF || lt_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+$2
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$1 <<\_ASEOF || lt_write_fail=1
+AS_SHELL_SANITIZE
+_AS_PREPARE
+exec AS_MESSAGE_FD>&1
+_ASEOF
+test 0 = "$lt_write_fail" && chmod +x $1[]dnl
+m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT
+
+# LT_OUTPUT
+# ---------
+# This macro allows early generation of the libtool script (before
+# AC_OUTPUT is called), incase it is used in configure for compilation
+# tests.
+AC_DEFUN([LT_OUTPUT],
+[: ${CONFIG_LT=./config.lt}
+AC_MSG_NOTICE([creating $CONFIG_LT])
+_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
+[# Run this file to recreate a libtool stub with the current configuration.])
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+lt_cl_silent=false
+exec AS_MESSAGE_LOG_FD>>config.log
+{
+ echo
+ AS_BOX([Running $as_me.])
+} >&AS_MESSAGE_LOG_FD
+
+lt_cl_help="\
+'$as_me' creates a local libtool stub from the current configuration,
+for use in further configure time tests before the real libtool is
+generated.
+
+Usage: $[0] [[OPTIONS]]
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+
+Report bugs to <bug-libtool@gnu.org>."
+
+lt_cl_version="\
+m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
+m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
+configured by $[0], generated by m4_PACKAGE_STRING.
+
+Copyright (C) 2011 Free Software Foundation, Inc.
+This config.lt script is free software; the Free Software Foundation
+gives unlimited permision to copy, distribute and modify it."
+
+while test 0 != $[#]
+do
+ case $[1] in
+ --version | --v* | -V )
+ echo "$lt_cl_version"; exit 0 ;;
+ --help | --h* | -h )
+ echo "$lt_cl_help"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --quiet | --q* | --silent | --s* | -q )
+ lt_cl_silent=: ;;
+
+ -*) AC_MSG_ERROR([unrecognized option: $[1]
+Try '$[0] --help' for more information.]) ;;
+
+ *) AC_MSG_ERROR([unrecognized argument: $[1]
+Try '$[0] --help' for more information.]) ;;
+ esac
+ shift
+done
+
+if $lt_cl_silent; then
+ exec AS_MESSAGE_FD>/dev/null
+fi
+_LTEOF
+
+cat >>"$CONFIG_LT" <<_LTEOF
+_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AC_MSG_NOTICE([creating $ofile])
+_LT_OUTPUT_LIBTOOL_COMMANDS
+AS_EXIT(0)
+_LTEOF
+chmod +x "$CONFIG_LT"
+
+# configure is writing to config.log, but config.lt does its own redirection,
+# appending to config.log, which fails on DOS, as config.log is still kept
+# open by configure. Here we exec the FD to /dev/null, effectively closing
+# config.log, so it can be properly (re)opened and appended to by config.lt.
+lt_cl_success=:
+test yes = "$silent" &&
+ lt_config_lt_args="$lt_config_lt_args --quiet"
+exec AS_MESSAGE_LOG_FD>/dev/null
+$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
+exec AS_MESSAGE_LOG_FD>>config.log
+$lt_cl_success || AS_EXIT(1)
+])# LT_OUTPUT
+
+
+# _LT_CONFIG(TAG)
+# ---------------
+# If TAG is the built-in tag, create an initial libtool script with a
+# default configuration from the untagged config vars. Otherwise add code
+# to config.status for appending the configuration named by TAG from the
+# matching tagged config vars.
+m4_defun([_LT_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_CONFIG_SAVE_COMMANDS([
+ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
+ m4_if(_LT_TAG, [C], [
+ # See if we are running on zsh, and set the options that allow our
+ # commands through without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+ fi
+
+ cfgfile=${ofile}T
+ trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+ $RM "$cfgfile"
+
+ cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+# Generated automatically by $as_me ($PACKAGE) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit, 1996
+
+_LT_COPYING
+_LT_LIBTOOL_TAGS
+
+# Configured defaults for sys_lib_dlsearch_path munging.
+: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
+
+# ### BEGIN LIBTOOL CONFIG
+_LT_LIBTOOL_CONFIG_VARS
+_LT_LIBTOOL_TAG_VARS
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+ cat <<'_LT_EOF' >> "$cfgfile"
+
+# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
+
+_LT_PREPARE_MUNGE_PATH_LIST
+_LT_PREPARE_CC_BASENAME
+
+# ### END FUNCTIONS SHARED WITH CONFIGURE
+
+_LT_EOF
+
+ case $host_os in
+ aix3*)
+ cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test set != "${COLLECT_NAMES+set}"; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+_LT_EOF
+ ;;
+ esac
+
+ _LT_PROG_LTMAIN
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ $SED '$q' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" ||
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+],
+[cat <<_LT_EOF >> "$ofile"
+
+dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
+dnl in a comment (ie after a #).
+# ### BEGIN LIBTOOL TAG CONFIG: $1
+_LT_LIBTOOL_TAG_VARS(_LT_TAG)
+# ### END LIBTOOL TAG CONFIG: $1
+_LT_EOF
+])dnl /m4_if
+],
+[m4_if([$1], [], [
+ PACKAGE='$PACKAGE'
+ VERSION='$VERSION'
+ RM='$RM'
+ ofile='$ofile'], [])
+])dnl /_LT_CONFIG_SAVE_COMMANDS
+])# _LT_CONFIG
+
+
+# LT_SUPPORTED_TAG(TAG)
+# ---------------------
+# Trace this macro to discover what tags are supported by the libtool
+# --tag option, using:
+# autoconf --trace 'LT_SUPPORTED_TAG:$1'
+AC_DEFUN([LT_SUPPORTED_TAG], [])
+
+
+# C support is built-in for now
+m4_define([_LT_LANG_C_enabled], [])
+m4_define([_LT_TAGS], [])
+
+
+# LT_LANG(LANG)
+# -------------
+# Enable libtool support for the given language if not already enabled.
+AC_DEFUN([LT_LANG],
+[AC_BEFORE([$0], [LT_OUTPUT])dnl
+m4_case([$1],
+ [C], [_LT_LANG(C)],
+ [C++], [_LT_LANG(CXX)],
+ [Go], [_LT_LANG(GO)],
+ [Java], [_LT_LANG(GCJ)],
+ [Fortran 77], [_LT_LANG(F77)],
+ [Fortran], [_LT_LANG(FC)],
+ [Windows Resource], [_LT_LANG(RC)],
+ [m4_ifdef([_LT_LANG_]$1[_CONFIG],
+ [_LT_LANG($1)],
+ [m4_fatal([$0: unsupported language: "$1"])])])dnl
+])# LT_LANG
+
+
+# _LT_LANG(LANGNAME)
+# ------------------
+m4_defun([_LT_LANG],
+[m4_ifdef([_LT_LANG_]$1[_enabled], [],
+ [LT_SUPPORTED_TAG([$1])dnl
+ m4_append([_LT_TAGS], [$1 ])dnl
+ m4_define([_LT_LANG_]$1[_enabled], [])dnl
+ _LT_LANG_$1_CONFIG($1)])dnl
+])# _LT_LANG
+
+
+m4_ifndef([AC_PROG_GO], [
+############################################################
+# NOTE: This macro has been submitted for inclusion into #
+# GNU Autoconf as AC_PROG_GO. When it is available in #
+# a released version of Autoconf we should remove this #
+# macro and use it instead. #
+############################################################
+m4_defun([AC_PROG_GO],
+[AC_LANG_PUSH(Go)dnl
+AC_ARG_VAR([GOC], [Go compiler command])dnl
+AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl
+_AC_ARG_VAR_LDFLAGS()dnl
+AC_CHECK_TOOL(GOC, gccgo)
+if test -z "$GOC"; then
+ if test -n "$ac_tool_prefix"; then
+ AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo])
+ fi
+fi
+if test -z "$GOC"; then
+ AC_CHECK_PROG(GOC, gccgo, gccgo, false)
+fi
+])#m4_defun
+])#m4_ifndef
+
+
+# _LT_LANG_DEFAULT_CONFIG
+# -----------------------
+m4_defun([_LT_LANG_DEFAULT_CONFIG],
+[AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [LT_LANG(CXX)],
+ [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_F77],
+ [LT_LANG(F77)],
+ [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_FC],
+ [LT_LANG(FC)],
+ [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
+
+dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
+dnl pulling things in needlessly.
+AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [m4_ifdef([AC_PROG_GCJ],
+ [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
+ m4_ifdef([A][M_PROG_GCJ],
+ [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
+ m4_ifdef([LT_PROG_GCJ],
+ [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
+
+AC_PROVIDE_IFELSE([AC_PROG_GO],
+ [LT_LANG(GO)],
+ [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])])
+
+AC_PROVIDE_IFELSE([LT_PROG_RC],
+ [LT_LANG(RC)],
+ [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
+])# _LT_LANG_DEFAULT_CONFIG
+
+# Obsolete macros:
+AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
+AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
+AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
+AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
+AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
+dnl AC_DEFUN([AC_LIBTOOL_F77], [])
+dnl AC_DEFUN([AC_LIBTOOL_FC], [])
+dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
+dnl AC_DEFUN([AC_LIBTOOL_RC], [])
+
+
+# _LT_TAG_COMPILER
+# ----------------
+m4_defun([_LT_TAG_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
+_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
+_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
+_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_TAG_COMPILER
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+m4_defun([_LT_COMPILER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+m4_defun([_LT_LINKER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+])# _LT_LINKER_BOILERPLATE
+
+# _LT_REQUIRED_DARWIN_CHECKS
+# -------------------------
+m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
+ case $host_os in
+ rhapsody* | darwin*)
+ AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
+ AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
+ AC_CHECK_TOOL([LIPO], [lipo], [:])
+ AC_CHECK_TOOL([OTOOL], [otool], [:])
+ AC_CHECK_TOOL([OTOOL64], [otool64], [:])
+ _LT_DECL([], [DSYMUTIL], [1],
+ [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
+ _LT_DECL([], [NMEDIT], [1],
+ [Tool to change global to local symbols on Mac OS X])
+ _LT_DECL([], [LIPO], [1],
+ [Tool to manipulate fat objects and archives on Mac OS X])
+ _LT_DECL([], [OTOOL], [1],
+ [ldd/readelf like tool for Mach-O binaries on Mac OS X])
+ _LT_DECL([], [OTOOL64], [1],
+ [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
+
+ AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
+ [lt_cv_apple_cc_single_mod=no
+ if test -z "$LT_MULTI_MODULE"; then
+ # By default we will add the -single_module flag. You can override
+ # by either setting the environment variable LT_MULTI_MODULE
+ # non-empty at configure time, or by adding -multi_module to the
+ # link flags.
+ rm -rf libconftest.dylib*
+ echo "int foo(void){return 1;}" > conftest.c
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
+ $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+ _lt_result=$?
+ # If there is a non-empty error log, and "single_module"
+ # appears in it, assume the flag caused a linker warning
+ if test -s conftest.err && $GREP single_module conftest.err; then
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ # Otherwise, if the output was created with a 0 exit code from
+ # the compiler, it worked.
+ elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
+ lt_cv_apple_cc_single_mod=yes
+ else
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ fi
+ rm -rf libconftest.dylib*
+ rm -f conftest.*
+ fi])
+
+ AC_CACHE_CHECK([for -exported_symbols_list linker flag],
+ [lt_cv_ld_exported_symbols_list],
+ [lt_cv_ld_exported_symbols_list=no
+ save_LDFLAGS=$LDFLAGS
+ echo "_main" > conftest.sym
+ LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+ [lt_cv_ld_exported_symbols_list=yes],
+ [lt_cv_ld_exported_symbols_list=no])
+ LDFLAGS=$save_LDFLAGS
+ ])
+
+ AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
+ [lt_cv_ld_force_load=no
+ cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+ echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
+ $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
+ echo "$AR $AR_FLAGS libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
+ $AR $AR_FLAGS libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
+ echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
+ $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
+ cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD
+ $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+ _lt_result=$?
+ if test -s conftest.err && $GREP force_load conftest.err; then
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
+ lt_cv_ld_force_load=yes
+ else
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ fi
+ rm -f conftest.err libconftest.a conftest conftest.c
+ rm -rf conftest.dSYM
+ ])
+ case $host_os in
+ rhapsody* | darwin1.[[012]])
+ _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
+ darwin1.*)
+ _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+ darwin*)
+ case $MACOSX_DEPLOYMENT_TARGET,$host in
+ 10.[[012]],*|,*powerpc*-darwin[[5-8]]*)
+ _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+ *)
+ _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+ esac
+ ;;
+ esac
+ if test yes = "$lt_cv_apple_cc_single_mod"; then
+ _lt_dar_single_mod='$single_module'
+ fi
+ if test yes = "$lt_cv_ld_exported_symbols_list"; then
+ _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
+ else
+ _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
+ fi
+ if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
+ _lt_dsymutil='~$DSYMUTIL $lib || :'
+ else
+ _lt_dsymutil=
+ fi
+ ;;
+ esac
+])
+
+
+# _LT_DARWIN_LINKER_FEATURES([TAG])
+# ---------------------------------
+# Checks for linker and compiler features on darwin
+m4_defun([_LT_DARWIN_LINKER_FEATURES],
+[
+ m4_require([_LT_REQUIRED_DARWIN_CHECKS])
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_automatic, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ if test yes = "$lt_cv_ld_force_load"; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+ m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes],
+ [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes])
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+ fi
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined
+ case $cc_basename in
+ ifort*|nagfor*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test yes = "$_lt_dar_can_shared"; then
+ output_verbose_link_cmd=func_echo_all
+ _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
+ _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
+ _LT_TAGVAR(module_expsym_cmds, $1)="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
+ m4_if([$1], [CXX],
+[ if test yes != "$lt_cv_apple_cc_single_mod"; then
+ _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
+ fi
+],[])
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+])
+
+# _LT_SYS_MODULE_PATH_AIX([TAGNAME])
+# ----------------------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+# Store the results from the different compilers for each TAGNAME.
+# Allow to override them for all tags through lt_cv_aix_libpath.
+m4_defun([_LT_SYS_MODULE_PATH_AIX],
+[m4_require([_LT_DECL_SED])dnl
+if test set = "${lt_cv_aix_libpath+set}"; then
+ aix_libpath=$lt_cv_aix_libpath
+else
+ AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])],
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM],[
+ lt_aix_libpath_sed='[
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\([^ ]*\) *$/\1/
+ p
+ }
+ }]'
+ _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ # Check for a 64-bit object if we didn't find anything.
+ if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+ _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ fi],[])
+ if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+ _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib
+ fi
+ ])
+ aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])
+fi
+])# _LT_SYS_MODULE_PATH_AIX
+
+
+# _LT_SHELL_INIT(ARG)
+# -------------------
+m4_define([_LT_SHELL_INIT],
+[m4_divert_text([M4SH-INIT], [$1
+])])# _LT_SHELL_INIT
+
+
+
+# _LT_PROG_ECHO_BACKSLASH
+# -----------------------
+# Find how we can fake an echo command that does not interpret backslash.
+# In particular, with Autoconf 2.60 or later we add some code to the start
+# of the generated configure script that will find a shell with a builtin
+# printf (that we can use as an echo command).
+m4_defun([_LT_PROG_ECHO_BACKSLASH],
+[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+AC_MSG_CHECKING([how to print strings])
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='printf %s\n'
+else
+ # Use this function as a fallback that always works.
+ func_fallback_echo ()
+ {
+ eval 'cat <<_LTECHO_EOF
+$[]1
+_LTECHO_EOF'
+ }
+ ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+ $ECHO "$*"
+}
+
+case $ECHO in
+ printf*) AC_MSG_RESULT([printf]) ;;
+ print*) AC_MSG_RESULT([print -r]) ;;
+ *) AC_MSG_RESULT([cat]) ;;
+esac
+
+m4_ifdef([_AS_DETECT_SUGGESTED],
+[_AS_DETECT_SUGGESTED([
+ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || (
+ ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+ PATH=/empty FPATH=/empty; export PATH FPATH
+ test "X`printf %s $ECHO`" = "X$ECHO" \
+ || test "X`print -r -- $ECHO`" = "X$ECHO" )])])
+
+_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
+_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
+])# _LT_PROG_ECHO_BACKSLASH
+
+
+# _LT_WITH_SYSROOT
+# ----------------
+AC_DEFUN([_LT_WITH_SYSROOT],
+[m4_require([_LT_DECL_SED])dnl
+AC_MSG_CHECKING([for sysroot])
+AC_ARG_WITH([sysroot],
+[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@],
+ [Search for dependent libraries within DIR (or the compiler's sysroot
+ if not specified).])],
+[], [with_sysroot=no])
+
+dnl lt_sysroot will always be passed unquoted. We quote it here
+dnl in case the user passed a directory name.
+lt_sysroot=
+case $with_sysroot in #(
+ yes)
+ if test yes = "$GCC"; then
+ lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+ fi
+ ;; #(
+ /*)
+ lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
+ ;; #(
+ no|'')
+ ;; #(
+ *)
+ AC_MSG_RESULT([$with_sysroot])
+ AC_MSG_ERROR([The sysroot must be an absolute path.])
+ ;;
+esac
+
+ AC_MSG_RESULT([${lt_sysroot:-no}])
+_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl
+[dependent libraries, and where our libraries should be installed.])])
+
+# _LT_ENABLE_LOCK
+# ---------------
+m4_defun([_LT_ENABLE_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+ [AS_HELP_STRING([--disable-libtool-lock],
+ [avoid locking (might break parallel builds)])])
+test no = "$enable_libtool_lock" || enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out what ABI is being produced by ac_compile, and set mode
+ # options accordingly.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `$FILECMD conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE=32
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE=64
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ if test yes = "$lt_cv_prog_gnu_ld"; then
+ case `$FILECMD conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `$FILECMD conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+mips64*-*linux*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ emul=elf
+ case `$FILECMD conftest.$ac_objext` in
+ *32-bit*)
+ emul="${emul}32"
+ ;;
+ *64-bit*)
+ emul="${emul}64"
+ ;;
+ esac
+ case `$FILECMD conftest.$ac_objext` in
+ *MSB*)
+ emul="${emul}btsmip"
+ ;;
+ *LSB*)
+ emul="${emul}ltsmip"
+ ;;
+ esac
+ case `$FILECMD conftest.$ac_objext` in
+ *N32*)
+ emul="${emul}n32"
+ ;;
+ esac
+ LD="${LD-ld} -m $emul"
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly. Note that the listed cases only cover the
+ # situations where additional linker options are needed (such as when
+ # doing 32-bit compilation for a host where ld defaults to 64-bit, or
+ # vice versa); the common cases where no linker options are needed do
+ # not appear in the list.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `$FILECMD conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_i386_fbsd"
+ ;;
+ x86_64-*linux*)
+ case `$FILECMD conftest.o` in
+ *x86-64*)
+ LD="${LD-ld} -m elf32_x86_64"
+ ;;
+ *)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ esac
+ ;;
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_x86_64_fbsd"
+ ;;
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*|s390*-*tpf*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS -belf"
+ AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+ [AC_LANG_PUSH(C)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+ AC_LANG_POP])
+ if test yes != "$lt_cv_cc_needs_belf"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS=$SAVE_CFLAGS
+ fi
+ ;;
+*-*solaris*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `$FILECMD conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*)
+ case $host in
+ i?86-*-solaris*|x86_64-*-solaris*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ sparc*-*-solaris*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ # GNU ld 2.21 introduced _sol2 emulations. Use them if available.
+ if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+ LD=${LD-ld}_sol2
+ fi
+ ;;
+ *)
+ if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+ LD="${LD-ld} -64"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+esac
+
+need_locks=$enable_libtool_lock
+])# _LT_ENABLE_LOCK
+
+
+# _LT_PROG_AR
+# -----------
+m4_defun([_LT_PROG_AR],
+[AC_CHECK_TOOLS(AR, [ar], false)
+: ${AR=ar}
+_LT_DECL([], [AR], [1], [The archiver])
+
+# Use ARFLAGS variable as AR's operation code to sync the variable naming with
+# Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
+# higher priority because thats what people were doing historically (setting
+# ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS
+# variable obsoleted/removed.
+
+test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
+lt_ar_flags=$AR_FLAGS
+_LT_DECL([], [lt_ar_flags], [0], [Flags to create an archive (by configure)])
+
+# Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override
+# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
+_LT_DECL([], [AR_FLAGS], [\@S|@{ARFLAGS-"\@S|@lt_ar_flags"}],
+ [Flags to create an archive])
+
+AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
+ [lt_cv_ar_at_file=no
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
+ [echo conftest.$ac_objext > conftest.lst
+ lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD'
+ AC_TRY_EVAL([lt_ar_try])
+ if test 0 -eq "$ac_status"; then
+ # Ensure the archiver fails upon bogus file names.
+ rm -f conftest.$ac_objext libconftest.a
+ AC_TRY_EVAL([lt_ar_try])
+ if test 0 -ne "$ac_status"; then
+ lt_cv_ar_at_file=@
+ fi
+ fi
+ rm -f conftest.* libconftest.a
+ ])
+ ])
+
+if test no = "$lt_cv_ar_at_file"; then
+ archiver_list_spec=
+else
+ archiver_list_spec=$lt_cv_ar_at_file
+fi
+_LT_DECL([], [archiver_list_spec], [1],
+ [How to feed a file listing to the archiver])
+])# _LT_PROG_AR
+
+
+# _LT_CMD_OLD_ARCHIVE
+# -------------------
+m4_defun([_LT_CMD_OLD_ARCHIVE],
+[_LT_PROG_AR
+
+AC_CHECK_TOOL(STRIP, strip, :)
+test -z "$STRIP" && STRIP=:
+_LT_DECL([], [STRIP], [1], [A symbol stripping program])
+
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+test -z "$RANLIB" && RANLIB=:
+_LT_DECL([], [RANLIB], [1],
+ [Commands used to install an old-style archive])
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ bitrig* | openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
+fi
+
+case $host_os in
+ darwin*)
+ lock_old_archive_extraction=yes ;;
+ *)
+ lock_old_archive_extraction=no ;;
+esac
+_LT_DECL([], [old_postinstall_cmds], [2])
+_LT_DECL([], [old_postuninstall_cmds], [2])
+_LT_TAGDECL([], [old_archive_cmds], [2],
+ [Commands used to build an old-style archive])
+_LT_DECL([], [lock_old_archive_extraction], [0],
+ [Whether to use a lock for old archive extraction])
+])# _LT_CMD_OLD_ARCHIVE
+
+
+# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([_LT_COMPILER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ fi
+ $RM conftest*
+])
+
+if test yes = "[$]$2"; then
+ m4_if([$5], , :, [$5])
+else
+ m4_if([$6], , :, [$6])
+fi
+])# _LT_COMPILER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
+
+
+# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------
+# Check whether the given linker option works
+AC_DEFUN([_LT_LINKER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS $3"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&AS_MESSAGE_LOG_FD
+ $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ else
+ $2=yes
+ fi
+ fi
+ $RM -r conftest*
+ LDFLAGS=$save_LDFLAGS
+])
+
+if test yes = "[$]$2"; then
+ m4_if([$4], , :, [$4])
+else
+ m4_if([$5], , :, [$5])
+fi
+])# _LT_LINKER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
+
+
+# LT_CMD_MAX_LEN
+#---------------
+AC_DEFUN([LT_CMD_MAX_LEN],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+ i=0
+ teststring=ABCD
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw* | cegcc*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ mint*)
+ # On MiNT this can take a long time and run out of memory.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ os2*)
+ # The test takes a long time on OS/2.
+ lt_cv_sys_max_cmd_len=8192
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[[ ]]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+ if test -n "$lt_cv_sys_max_cmd_len" && \
+ test undefined != "$lt_cv_sys_max_cmd_len"; then
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ else
+ # Make teststring a little bigger before we do anything with it.
+ # a 1K string should be a reasonable start.
+ for i in 1 2 3 4 5 6 7 8; do
+ teststring=$teststring$teststring
+ done
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ while { test X`env echo "$teststring$teststring" 2>/dev/null` \
+ = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+ test 17 != "$i" # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ # Only check the string length outside the loop.
+ lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on
+ # massive amounts of additional arguments before passing them to the
+ # linker. It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ fi
+ ;;
+ esac
+])
+if test -n "$lt_cv_sys_max_cmd_len"; then
+ AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+ AC_MSG_RESULT(none)
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+_LT_DECL([], [max_cmd_len], [0],
+ [What is the maximum length of a command?])
+])# LT_CMD_MAX_LEN
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
+
+
+# _LT_HEADER_DLFCN
+# ----------------
+m4_defun([_LT_HEADER_DLFCN],
+[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
+])# _LT_HEADER_DLFCN
+
+
+# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ----------------------------------------------------------------
+m4_defun([_LT_TRY_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test yes = "$cross_compiling"; then :
+ [$4]
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+[#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+/* When -fvisibility=hidden is used, assume the code has been annotated
+ correspondingly for the symbols needed. */
+#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else
+ {
+ if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ else puts (dlerror ());
+ }
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ return status;
+}]
+_LT_EOF
+ if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then
+ (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) $1 ;;
+ x$lt_dlneed_uscore) $2 ;;
+ x$lt_dlunknown|x*) $3 ;;
+ esac
+ else :
+ # compilation failed
+ $3
+ fi
+fi
+rm -fr conftest*
+])# _LT_TRY_DLOPEN_SELF
+
+
+# LT_SYS_DLOPEN_SELF
+# ------------------
+AC_DEFUN([LT_SYS_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test yes != "$enable_dlopen"; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen=load_add_on
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32* | cegcc*)
+ lt_cv_dlopen=LoadLibrary
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen=dlopen
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[
+ lt_cv_dlopen=dyld
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ])
+ ;;
+
+ tpf*)
+ # Don't try to run any link tests for TPF. We know it's impossible
+ # because TPF is a cross-compiler, and we know how we open DSOs.
+ lt_cv_dlopen=dlopen
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=no
+ ;;
+
+ *)
+ AC_CHECK_FUNC([shl_load],
+ [lt_cv_dlopen=shl_load],
+ [AC_CHECK_LIB([dld], [shl_load],
+ [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld],
+ [AC_CHECK_FUNC([dlopen],
+ [lt_cv_dlopen=dlopen],
+ [AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],
+ [AC_CHECK_LIB([svld], [dlopen],
+ [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld],
+ [AC_CHECK_LIB([dld], [dld_link],
+ [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld])
+ ])
+ ])
+ ])
+ ])
+ ])
+ ;;
+ esac
+
+ if test no = "$lt_cv_dlopen"; then
+ enable_dlopen=no
+ else
+ enable_dlopen=yes
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS=$CPPFLAGS
+ test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS=$LDFLAGS
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS=$LIBS
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ AC_CACHE_CHECK([whether a program can dlopen itself],
+ lt_cv_dlopen_self, [dnl
+ _LT_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+ lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+ ])
+
+ if test yes = "$lt_cv_dlopen_self"; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+ lt_cv_dlopen_self_static, [dnl
+ _LT_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+ lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
+ ])
+ fi
+
+ CPPFLAGS=$save_CPPFLAGS
+ LDFLAGS=$save_LDFLAGS
+ LIBS=$save_LIBS
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+_LT_DECL([dlopen_support], [enable_dlopen], [0],
+ [Whether dlopen is supported])
+_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
+ [Whether dlopen of programs is supported])
+_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
+ [Whether dlopen of statically linked programs is supported])
+])# LT_SYS_DLOPEN_SELF
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
+
+
+# _LT_COMPILER_C_O([TAGNAME])
+# ---------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler.
+# This macro does not hard code the compiler like AC_PROG_CC_C_O.
+m4_defun([_LT_COMPILER_C_O],
+[m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+ [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+ [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+ fi
+ fi
+ chmod u+w . 2>&AS_MESSAGE_LOG_FD
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+])
+_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
+ [Does compiler simultaneously support -c and -o options?])
+])# _LT_COMPILER_C_O
+
+
+# _LT_COMPILER_FILE_LOCKS([TAGNAME])
+# ----------------------------------
+# Check to see if we can do hard links to lock some files if needed
+m4_defun([_LT_COMPILER_FILE_LOCKS],
+[m4_require([_LT_ENABLE_LOCK])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_COMPILER_C_O([$1])
+
+hard_links=nottested
+if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then
+ # do not overwrite the value of need_locks provided by the user
+ AC_MSG_CHECKING([if we can lock with hard links])
+ hard_links=yes
+ $RM conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ AC_MSG_RESULT([$hard_links])
+ if test no = "$hard_links"; then
+ AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe])
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
+])# _LT_COMPILER_FILE_LOCKS
+
+
+# _LT_CHECK_OBJDIR
+# ----------------
+m4_defun([_LT_CHECK_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+_LT_DECL([], [objdir], [0],
+ [The name of the directory that contains temporary libtool files])dnl
+m4_pattern_allow([LT_OBJDIR])dnl
+AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/",
+ [Define to the sub-directory where libtool stores uninstalled libraries.])
+])# _LT_CHECK_OBJDIR
+
+
+# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
+# --------------------------------------
+# Check hardcoding attributes.
+m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
+ test -n "$_LT_TAGVAR(runpath_var, $1)" ||
+ test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then
+
+ # We can hardcode non-existent directories.
+ if test no != "$_LT_TAGVAR(hardcode_direct, $1)" &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" &&
+ test -z "$_LT_TAGVAR(fix_hardcoded_libdir_flag_spec, $1)" &&
+ test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then
+ # Linking always hardcodes the temporary library directory.
+ _LT_TAGVAR(hardcode_action, $1)=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ _LT_TAGVAR(hardcode_action, $1)=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ _LT_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
+
+if test relink = "$_LT_TAGVAR(hardcode_action, $1)" ||
+ test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test yes = "$shlibpath_overrides_runpath" ||
+ test no = "$enable_shared"; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+_LT_TAGDECL([], [hardcode_action], [0],
+ [How to hardcode a shared library path into an executable])
+])# _LT_LINKER_HARDCODE_LIBPATH
+
+
+# _LT_CMD_STRIPLIB
+# ----------------
+m4_defun([_LT_CMD_STRIPLIB],
+[m4_require([_LT_DECL_EGREP])
+striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -z "$STRIP"; then
+ AC_MSG_RESULT([no])
+else
+ if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+ old_striplib="$STRIP --strip-debug"
+ striplib="$STRIP --strip-unneeded"
+ AC_MSG_RESULT([yes])
+ else
+ case $host_os in
+ darwin*)
+ # FIXME - insert some real tests, host_os isn't really good enough
+ striplib="$STRIP -x"
+ old_striplib="$STRIP -S"
+ AC_MSG_RESULT([yes])
+ ;;
+ freebsd*)
+ if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
+ old_striplib="$STRIP --strip-debug"
+ striplib="$STRIP --strip-unneeded"
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ ;;
+ *)
+ AC_MSG_RESULT([no])
+ ;;
+ esac
+ fi
+fi
+_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
+_LT_DECL([], [striplib], [1])
+])# _LT_CMD_STRIPLIB
+
+
+# _LT_PREPARE_MUNGE_PATH_LIST
+# ---------------------------
+# Make sure func_munge_path_list() is defined correctly.
+m4_defun([_LT_PREPARE_MUNGE_PATH_LIST],
+[[# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+# string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+# string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+# "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+# VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+ case x@S|@2 in
+ x)
+ ;;
+ *:)
+ eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\"
+ ;;
+ x:*)
+ eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\"
+ ;;
+ *::*)
+ eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+ eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\"
+ ;;
+ *)
+ eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\"
+ ;;
+ esac
+}
+]])# _LT_PREPARE_PATH_LIST
+
+
+# _LT_SYS_DYNAMIC_LINKER([TAG])
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+m4_defun([_LT_SYS_DYNAMIC_LINKER],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_OBJDUMP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+m4_if([$1],
+ [], [
+if test yes = "$GCC"; then
+ case $host_os in
+ darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
+ *) lt_awk_arg='/^libraries:/' ;;
+ esac
+ case $host_os in
+ mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;;
+ *) lt_sed_strip_eq='s|=/|/|g' ;;
+ esac
+ lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+ case $lt_search_path_spec in
+ *\;*)
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+ ;;
+ *)
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+ ;;
+ esac
+ # Ok, now we have the path, separated by spaces, we can step through it
+ # and add multilib dir if necessary...
+ lt_tmp_lt_search_path_spec=
+ lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+ # ...but if some path component already ends with the multilib dir we assume
+ # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
+ case "$lt_multi_os_dir; $lt_search_path_spec " in
+ "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
+ lt_multi_os_dir=
+ ;;
+ esac
+ for lt_sys_path in $lt_search_path_spec; do
+ if test -d "$lt_sys_path$lt_multi_os_dir"; then
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
+ elif test -n "$lt_multi_os_dir"; then
+ test -d "$lt_sys_path" && \
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+ fi
+ done
+ lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS = " "; FS = "/|\n";} {
+ lt_foo = "";
+ lt_count = 0;
+ for (lt_i = NF; lt_i > 0; lt_i--) {
+ if ($lt_i != "" && $lt_i != ".") {
+ if ($lt_i == "..") {
+ lt_count++;
+ } else {
+ if (lt_count == 0) {
+ lt_foo = "/" $lt_i lt_foo;
+ } else {
+ lt_count--;
+ }
+ }
+ }
+ }
+ if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+ if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+}'`
+ # AWK program above erroneously prepends '/' to C:/dos/paths
+ # for these hosts.
+ case $host_os in
+ mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;;
+ esac
+ sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=.so
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+AC_ARG_VAR([LT_SYS_LIBRARY_PATH],
+[User-defined run-time library search path.])
+
+case $host_os in
+aix3*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+
+aix[[4-9]]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 supports IA64
+ library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line '#! .'. This would cause the generated library to
+ # depend on '.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[[01]] | aix4.[[01]].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # Using Import Files as archive members, it is possible to support
+ # filename-based versioning of shared library archives on AIX. While
+ # this would work for both with and without runtime linking, it will
+ # prevent static linking of such archives. So we do filename-based
+ # shared library versioning with .so extension only, which is used
+ # when both runtime linking and shared linking is enabled.
+ # Unfortunately, runtime linking may impact performance, so we do
+ # not want this to be the default eventually. Also, we use the
+ # versioned .so libs for executables only if there is the -brtl
+ # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
+ # To allow for filename-based versioning support, we need to create
+ # libNAME.so.V as an archive file, containing:
+ # *) an Import File, referring to the versioned filename of the
+ # archive as well as the shared archive member, telling the
+ # bitwidth (32 or 64) of that shared object, and providing the
+ # list of exported symbols of that shared object, eventually
+ # decorated with the 'weak' keyword
+ # *) the shared object with the F_LOADONLY flag set, to really avoid
+ # it being seen by the linker.
+ # At run time we better use the real file rather than another symlink,
+ # but for link time we create the symlink libNAME.so -> libNAME.so.V
+
+ case $with_aix_soname,$aix_use_runtimelinking in
+ # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ aix,yes) # traditional libtool
+ dynamic_linker='AIX unversionable lib.so'
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ ;;
+ aix,no) # traditional AIX only
+ dynamic_linker='AIX lib.a[(]lib.so.V[)]'
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='$libname$release.a $libname.a'
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+ svr4,*) # full svr4 only
+ dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]"
+ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+ # We do not specify a path in Import Files, so LIBPATH fires.
+ shlibpath_overrides_runpath=yes
+ ;;
+ *,yes) # both, prefer svr4
+ dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]"
+ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+ # unpreferred sharedlib libNAME.a needs extra handling
+ postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
+ postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
+ # We do not specify a path in Import Files, so LIBPATH fires.
+ shlibpath_overrides_runpath=yes
+ ;;
+ *,no) # both, prefer aix
+ dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]"
+ library_names_spec='$libname$release.a $libname.a'
+ soname_spec='$libname$release$shared_ext$major'
+ # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
+ postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
+ postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
+ ;;
+ esac
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ case $host_cpu in
+ powerpc)
+ # Since July 2007 AmigaOS4 officially supports .so libraries.
+ # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ ;;
+ m68k)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+ esac
+ ;;
+
+beos*)
+ library_names_spec='$libname$shared_ext'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[[45]]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+ version_type=windows
+ shrext_cmds=.dll
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$cc_basename in
+ yes,*)
+ # gcc
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+m4_if([$1], [],[
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
+ ;;
+ mingw* | cegcc*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ ;;
+
+ *,cl* | *,icl*)
+ # Native MSVC or ICC
+ libname_spec='$name'
+ soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+ library_names_spec='$libname.dll.lib'
+
+ case $build_os in
+ mingw*)
+ sys_lib_search_path_spec=
+ lt_save_ifs=$IFS
+ IFS=';'
+ for lt_path in $LIB
+ do
+ IFS=$lt_save_ifs
+ # Let DOS variable expansion print the short 8.3 style file name.
+ lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+ sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+ done
+ IFS=$lt_save_ifs
+ # Convert to MSYS style.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
+ ;;
+ cygwin*)
+ # Convert to unix form, then to dos form, then back to unix form
+ # but this time dos style (no spaces!) so that the unix form looks
+ # like /cygdrive/c/PROGRA~1:/cygdr...
+ sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+ sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+ sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ ;;
+ *)
+ sys_lib_search_path_spec=$LIB
+ if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
+ # It is most probably a Windows format PATH.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ # FIXME: find the short name or the path components, as spaces are
+ # common. (e.g. "Program Files" -> "PROGRA~1")
+ ;;
+ esac
+
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+ dynamic_linker='Win32 link.exe'
+ ;;
+
+ *)
+ # Assume MSVC and ICC wrapper
+ library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib'
+ dynamic_linker='Win32 ld.exe'
+ ;;
+ esac
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
+ soname_spec='$libname$release$major$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+m4_if([$1], [],[
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd* | dragonfly* | midnightbsd*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[[23]].*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2.*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ *) # from 4.6 on, and DragonFly
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+haiku*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ dynamic_linker="$host_os runtime_loader"
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ if test 32 = "$HPUX_IA64_MODE"; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ sys_lib_dlsearch_path_spec=/usr/lib/hpux32
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ sys_lib_dlsearch_path_spec=/usr/lib/hpux64
+ fi
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+ postinstall_cmds='chmod 555 $lib'
+ # or fails outright, so override atomically:
+ install_override_mode=555
+ ;;
+
+interix[[3-9]]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test yes = "$lt_cv_prog_gnu_ld"; then
+ version_type=linux # correct to gnu/linux during the next big refactor
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='$libname$release$shared_ext$major'
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
+ sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+linux*android*)
+ version_type=none # Android doesn't support versioned libraries.
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext'
+ soname_spec='$libname$release$shared_ext'
+ finish_cmds=
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ dynamic_linker='Android linker'
+ # Don't embed -rpath directories since the linker doesn't support them.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+
+ # Some binutils ld are patched to set DT_RUNPATH
+ AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
+ [lt_cv_shlibpath_overrides_runpath=no
+ save_LDFLAGS=$LDFLAGS
+ save_libdir=$libdir
+ eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
+ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+ [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
+ [lt_cv_shlibpath_overrides_runpath=yes])])
+ LDFLAGS=$save_LDFLAGS
+ libdir=$save_libdir
+ ])
+ shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Ideally, we could use ldconfig to report *all* directores which are
+ # searched for libraries, however this is still not possible. Aside from not
+ # being certain /sbin/ldconfig is available, command
+ # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
+ # even though it is searched at run-time. Try to do the best guess by
+ # appending ld.so.conf contents (and includes) to the search path.
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+*nto* | *qnx*)
+ version_type=qnx
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='ldqnx.so'
+ ;;
+
+openbsd* | bitrig*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec=/usr/lib
+ need_lib_prefix=no
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ need_version=no
+ else
+ need_version=yes
+ fi
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+os2*)
+ libname_spec='$name'
+ version_type=windows
+ shrext_cmds=.dll
+ need_version=no
+ need_lib_prefix=no
+ # OS/2 can only load a DLL with a base name of 8 characters or less.
+ soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
+ v=$($ECHO $release$versuffix | tr -d .-);
+ n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
+ $ECHO $n$v`$shared_ext'
+ library_names_spec='${libname}_dll.$libext'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=BEGINLIBPATH
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='$libname$release$shared_ext$major'
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+
+rdos*)
+ dynamic_linker=no
+ ;;
+
+solaris*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test yes = "$with_gnu_ld"; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec; then
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
+ soname_spec='$libname$shared_ext.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=sco
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ if test yes = "$with_gnu_ld"; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+tpf*)
+ # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+uts4*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test no = "$dynamic_linker" && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test yes = "$GCC"; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
+ sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
+fi
+
+if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
+ sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
+fi
+
+# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
+configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
+
+# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
+func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
+
+# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
+configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+
+_LT_DECL([], [variables_saved_for_relink], [1],
+ [Variables whose values should be saved in libtool wrapper scripts and
+ restored at link time])
+_LT_DECL([], [need_lib_prefix], [0],
+ [Do we need the "lib" prefix for modules?])
+_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
+_LT_DECL([], [version_type], [0], [Library versioning type])
+_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable])
+_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
+_LT_DECL([], [shlibpath_overrides_runpath], [0],
+ [Is shlibpath searched before the hard-coded library search path?])
+_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
+_LT_DECL([], [library_names_spec], [1],
+ [[List of archive names. First name is the real one, the rest are links.
+ The last name is the one that the linker finds with -lNAME]])
+_LT_DECL([], [soname_spec], [1],
+ [[The coded name of the library, if different from the real name]])
+_LT_DECL([], [install_override_mode], [1],
+ [Permission mode override for installation of shared libraries])
+_LT_DECL([], [postinstall_cmds], [2],
+ [Command to use after installation of a shared archive])
+_LT_DECL([], [postuninstall_cmds], [2],
+ [Command to use after uninstallation of a shared archive])
+_LT_DECL([], [finish_cmds], [2],
+ [Commands used to finish a libtool library installation in a directory])
+_LT_DECL([], [finish_eval], [1],
+ [[As "finish_cmds", except a single script fragment to be evaled but
+ not shown]])
+_LT_DECL([], [hardcode_into_libs], [0],
+ [Whether we should hardcode library paths into libraries])
+_LT_DECL([], [sys_lib_search_path_spec], [2],
+ [Compile-time system search path for libraries])
+_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2],
+ [Detected run-time system search path for libraries])
+_LT_DECL([], [configure_time_lt_sys_library_path], [2],
+ [Explicit LT_SYS_LIBRARY_PATH set during ./configure time])
+])# _LT_SYS_DYNAMIC_LINKER
+
+
+# _LT_PATH_TOOL_PREFIX(TOOL)
+# --------------------------
+# find a file program that can recognize shared library
+AC_DEFUN([_LT_PATH_TOOL_PREFIX],
+[m4_require([_LT_DECL_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] | ?:[\\/]*])
+ lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD=$MAGIC_CMD
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word. This closes a longstanding sh security hole.
+ ac_dummy="m4_if([$2], , $PATH, [$2])"
+ for ac_dir in $ac_dummy; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$1"; then
+ lt_cv_path_MAGIC_CMD=$ac_dir/"$1"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS=$lt_save_ifs
+ MAGIC_CMD=$lt_save_MAGIC_CMD
+ ;;
+esac])
+MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+if test -n "$MAGIC_CMD"; then
+ AC_MSG_RESULT($MAGIC_CMD)
+else
+ AC_MSG_RESULT(no)
+fi
+_LT_DECL([], [MAGIC_CMD], [0],
+ [Used to examine libraries when file_magic_cmd begins with "file"])dnl
+])# _LT_PATH_TOOL_PREFIX
+
+# Old name:
+AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
+
+
+# _LT_PATH_MAGIC
+# --------------
+# find a file program that can recognize a shared library
+m4_defun([_LT_PATH_MAGIC],
+[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+ else
+ MAGIC_CMD=:
+ fi
+fi
+])# _LT_PATH_MAGIC
+
+
+# LT_PATH_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([LT_PATH_LD],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PROG_ECHO_BACKSLASH])dnl
+
+AC_ARG_WITH([gnu-ld],
+ [AS_HELP_STRING([--with-gnu-ld],
+ [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+ [test no = "$withval" || with_gnu_ld=yes],
+ [with_gnu_ld=no])dnl
+
+ac_prog=ld
+if test yes = "$GCC"; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by $CC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return, which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]]* | ?:[[\\/]]*)
+ re_direlt='/[[^/]][[^/]]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+ while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD=$ac_prog
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test yes = "$with_gnu_ld"; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD=$ac_dir/$ac_prog
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test no != "$with_gnu_ld" && break
+ ;;
+ *)
+ test yes != "$with_gnu_ld" && break
+ ;;
+ esac
+ fi
+ done
+ IFS=$lt_save_ifs
+else
+ lt_cv_path_LD=$LD # Let the user override the test with a path.
+fi])
+LD=$lt_cv_path_LD
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+_LT_PATH_LD_GNU
+AC_SUBST([LD])
+
+_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
+])# LT_PATH_LD
+
+# Old names:
+AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
+AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_LD], [])
+dnl AC_DEFUN([AC_PROG_LD], [])
+
+
+# _LT_PATH_LD_GNU
+#- --------------
+m4_defun([_LT_PATH_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# _LT_PATH_LD_GNU
+
+
+# _LT_CMD_RELOAD
+# --------------
+# find reload flag for linker
+# -- PORTME Some linkers may need a different reload flag.
+m4_defun([_LT_CMD_RELOAD],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+ lt_cv_ld_reload_flag,
+ [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ if test yes != "$GCC"; then
+ reload_cmds=false
+ fi
+ ;;
+ darwin*)
+ if test yes = "$GCC"; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+_LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl
+_LT_TAGDECL([], [reload_cmds], [2])dnl
+])# _LT_CMD_RELOAD
+
+
+# _LT_PATH_DD
+# -----------
+# find a working dd
+m4_defun([_LT_PATH_DD],
+[AC_CACHE_CHECK([for a working dd], [ac_cv_path_lt_DD],
+[printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+: ${lt_DD:=$DD}
+AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd],
+[if "$ac_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+ cmp -s conftest.i conftest.out \
+ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
+fi])
+rm -f conftest.i conftest2.i conftest.out])
+])# _LT_PATH_DD
+
+
+# _LT_CMD_TRUNCATE
+# ----------------
+# find command to truncate a binary pipe
+m4_defun([_LT_CMD_TRUNCATE],
+[m4_require([_LT_PATH_DD])
+AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin],
+[printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+lt_cv_truncate_bin=
+if "$ac_cv_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+ cmp -s conftest.i conftest.out \
+ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
+fi
+rm -f conftest.i conftest2.i conftest.out
+test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"])
+_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1],
+ [Command to truncate a binary pipe])
+])# _LT_CMD_TRUNCATE
+
+
+# _LT_CHECK_MAGIC_METHOD
+# ----------------------
+# how to check for library dependencies
+# -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_MAGIC_METHOD],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+AC_CACHE_CHECK([how to recognize dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# 'unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# that responds to the $file_magic_cmd with a given extended regex.
+# If you have 'file' or equivalent on your system and you're not sure
+# whether 'pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[[4-9]]*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[[45]]*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='$FILECMD -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump',
+ # unless we find 'file', for example because we are cross-compiling.
+ if ( file / ) >/dev/null 2>&1; then
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ else
+ # Keep this pattern in sync with the one in func_win32_libid.
+ lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ fi
+ ;;
+
+cegcc*)
+ # use the weaker test based on 'objdump'. See mingw*.
+ lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | dragonfly* | midnightbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=$FILECMD
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+haiku*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+interix[[3-9]]*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=$FILECMD
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+*nto* | *qnx*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+openbsd* | bitrig*)
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+rdos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+tpf*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+os2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+])
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+ case $host_os in
+ mingw* | pw32*)
+ if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+ want_nocaseglob=yes
+ else
+ file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"`
+ fi
+ ;;
+ esac
+fi
+
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+_LT_DECL([], [deplibs_check_method], [1],
+ [Method to check whether dependent libraries are shared objects])
+_LT_DECL([], [file_magic_cmd], [1],
+ [Command to use when deplibs_check_method = "file_magic"])
+_LT_DECL([], [file_magic_glob], [1],
+ [How to find potential files when deplibs_check_method = "file_magic"])
+_LT_DECL([], [want_nocaseglob], [1],
+ [Find potential files using nocaseglob when deplibs_check_method = "file_magic"])
+])# _LT_CHECK_MAGIC_METHOD
+
+
+# LT_PATH_NM
+# ----------
+# find the pathname to a BSD- or MS-compatible name lister
+AC_DEFUN([LT_PATH_NM],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
+[if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM=$NM
+else
+ lt_nm_to_check=${ac_tool_prefix}nm
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm=$ac_dir/$lt_tmp_nm
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the 'sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
+ case $build_os in
+ mingw*) lt_bad_file=conftest.nm/nofile ;;
+ *) lt_bad_file=/dev/null ;;
+ esac
+ case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
+ *$lt_bad_file* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break 2
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break 2
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS=$lt_save_ifs
+ done
+ : ${lt_cv_path_NM=no}
+fi])
+if test no != "$lt_cv_path_NM"; then
+ NM=$lt_cv_path_NM
+else
+ # Didn't find any BSD compatible name lister, look for dumpbin.
+ if test -n "$DUMPBIN"; then :
+ # Let the user override the test.
+ else
+ AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
+ case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
+ *COFF*)
+ DUMPBIN="$DUMPBIN -symbols -headers"
+ ;;
+ *)
+ DUMPBIN=:
+ ;;
+ esac
+ fi
+ AC_SUBST([DUMPBIN])
+ if test : != "$DUMPBIN"; then
+ NM=$DUMPBIN
+ fi
+fi
+test -z "$NM" && NM=nm
+AC_SUBST([NM])
+_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
+
+AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
+ [lt_cv_nm_interface="BSD nm"
+ echo "int some_variable = 0;" > conftest.$ac_ext
+ (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$ac_compile" 2>conftest.err)
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
+ cat conftest.out >&AS_MESSAGE_LOG_FD
+ if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+ lt_cv_nm_interface="MS dumpbin"
+ fi
+ rm -f conftest*])
+])# LT_PATH_NM
+
+# Old names:
+AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
+AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_NM], [])
+dnl AC_DEFUN([AC_PROG_NM], [])
+
+# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+# --------------------------------
+# how to determine the name of the shared library
+# associated with a specific link library.
+# -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+m4_require([_LT_DECL_DLLTOOL])
+AC_CACHE_CHECK([how to associate runtime and link libraries],
+lt_cv_sharedlib_from_linklib_cmd,
+[lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+ # two different shell functions defined in ltmain.sh;
+ # decide which one to use based on capabilities of $DLLTOOL
+ case `$DLLTOOL --help 2>&1` in
+ *--identify-strict*)
+ lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+ ;;
+ *)
+ lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+ ;;
+ esac
+ ;;
+*)
+ # fallback: assume linklib IS sharedlib
+ lt_cv_sharedlib_from_linklib_cmd=$ECHO
+ ;;
+esac
+])
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
+ [Command to associate shared and link libraries])
+])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+
+
+# _LT_PATH_MANIFEST_TOOL
+# ----------------------
+# locate the manifest tool
+m4_defun([_LT_PATH_MANIFEST_TOOL],
+[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :)
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool],
+ [lt_cv_path_mainfest_tool=no
+ echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD
+ $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+ lt_cv_path_mainfest_tool=yes
+ fi
+ rm -f conftest*])
+if test yes != "$lt_cv_path_mainfest_tool"; then
+ MANIFEST_TOOL=:
+fi
+_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
+])# _LT_PATH_MANIFEST_TOOL
+
+
+# _LT_DLL_DEF_P([FILE])
+# ---------------------
+# True iff FILE is a Windows DLL '.def' file.
+# Keep in sync with func_dll_def_p in the libtool script
+AC_DEFUN([_LT_DLL_DEF_P],
+[dnl
+ test DEF = "`$SED -n dnl
+ -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace
+ -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments
+ -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl
+ -e q dnl Only consider the first "real" line
+ $1`" dnl
+])# _LT_DLL_DEF_P
+
+
+# LT_LIB_M
+# --------
+# check for math library
+AC_DEFUN([LT_LIB_M],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
+ # These system don't have libm, or don't need it
+ ;;
+*-ncr-sysv4.3*)
+ AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw)
+ AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+ ;;
+*)
+ AC_CHECK_LIB(m, cos, LIBM=-lm)
+ ;;
+esac
+AC_SUBST([LIBM])
+])# LT_LIB_M
+
+# Old name:
+AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_CHECK_LIBM], [])
+
+
+# _LT_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------
+m4_defun([_LT_COMPILER_NO_RTTI],
+[m4_require([_LT_TAG_COMPILER])dnl
+
+_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test yes = "$GCC"; then
+ case $cc_basename in
+ nvcc*)
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
+ esac
+
+ _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+ lt_cv_prog_compiler_rtti_exceptions,
+ [-fno-rtti -fno-exceptions], [],
+ [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
+ [Compiler flag to turn off builtin functions])
+])# _LT_COMPILER_NO_RTTI
+
+
+# _LT_CMD_GLOBAL_SYMBOLS
+# ----------------------
+m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[[BCDT]]'
+ ;;
+cygwin* | mingw* | pw32* | cegcc*)
+ symcode='[[ABCDGISTW]]'
+ ;;
+hpux*)
+ if test ia64 = "$host_cpu"; then
+ symcode='[[ABCDEGRST]]'
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[[BCDEGRST]]'
+ ;;
+osf*)
+ symcode='[[BCDEGQRST]]'
+ ;;
+solaris*)
+ symcode='[[BDRT]]'
+ ;;
+sco3.2v5*)
+ symcode='[[DT]]'
+ ;;
+sysv4.2uw2*)
+ symcode='[[DT]]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[[ABDT]]'
+ ;;
+sysv4)
+ symcode='[[DFNSTU]]'
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Gets list of data symbols to import.
+ lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'"
+ # Adjust the below global symbol transforms to fixup imported variables.
+ lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
+ lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'"
+ lt_c_name_lib_hook="\
+ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\
+ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'"
+else
+ # Disable hooks by default.
+ lt_cv_sys_global_symbol_to_import=
+ lt_cdecl_hook=
+ lt_c_name_hook=
+ lt_c_name_lib_hook=
+fi
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
+$lt_cdecl_hook\
+" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
+$lt_c_name_hook\
+" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'"
+
+# Transform an extracted symbol line into symbol name with lib prefix and
+# symbol address.
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
+$lt_c_name_lib_hook\
+" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Fake it for dumpbin and say T for any non-static function,
+ # D for any global variable and I for any imported variable.
+ # Also find C++ and __fastcall symbols from MSVC++ or ICC,
+ # which start with @ or ?.
+ lt_cv_sys_global_symbol_pipe="$AWK ['"\
+" {last_section=section; section=\$ 3};"\
+" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
+" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
+" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
+" \$ 0!~/External *\|/{next};"\
+" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+" {if(hide[section]) next};"\
+" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
+" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
+" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
+" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
+" ' prfx=^$ac_symprfx]"
+ else
+ lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+ fi
+ lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+ if AC_TRY_EVAL(ac_compile); then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+ if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */
+#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
+/* DATA imports from DLLs on WIN32 can't be const, because runtime
+ relocations are performed -- see ld's documentation on pseudo-relocs. */
+# define LT@&t@_DLSYM_CONST
+#elif defined __osf__
+/* This system does not cope well with relocations in const data. */
+# define LT@&t@_DLSYM_CONST
+#else
+# define LT@&t@_DLSYM_CONST const
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+ cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols. */
+LT@&t@_DLSYM_CONST struct {
+ const char *name;
+ void *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[[]] =
+{
+ { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+ $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+ cat <<\_LT_EOF >> conftest.$ac_ext
+ {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_globsym_save_LIBS=$LIBS
+ lt_globsym_save_CFLAGS=$CFLAGS
+ LIBS=conftstm.$ac_objext
+ CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+ if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then
+ pipe_works=yes
+ fi
+ LIBS=$lt_globsym_save_LIBS
+ CFLAGS=$lt_globsym_save_CFLAGS
+ else
+ echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+ cat conftest.$ac_ext >&5
+ fi
+ rm -rf conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test yes = "$pipe_works"; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ AC_MSG_RESULT(failed)
+else
+ AC_MSG_RESULT(ok)
+fi
+
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then
+ nm_file_list_spec='@'
+fi
+
+_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
+ [Take the output of nm and produce a listing of raw symbols and C names])
+_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
+ [Transform the output of nm in a proper C declaration])
+_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1],
+ [Transform the output of nm into a list of symbols to manually relocate])
+_LT_DECL([global_symbol_to_c_name_address],
+ [lt_cv_sys_global_symbol_to_c_name_address], [1],
+ [Transform the output of nm in a C name address pair])
+_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
+ [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
+ [Transform the output of nm in a C name address pair when lib prefix is needed])
+_LT_DECL([nm_interface], [lt_cv_nm_interface], [1],
+ [The name lister interface])
+_LT_DECL([], [nm_file_list_spec], [1],
+ [Specify filename containing input files for $NM])
+]) # _LT_CMD_GLOBAL_SYMBOLS
+
+
+# _LT_COMPILER_PIC([TAGNAME])
+# ---------------------------
+m4_defun([_LT_COMPILER_PIC],
+[m4_require([_LT_TAG_COMPILER])dnl
+_LT_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_TAGVAR(lt_prog_compiler_static, $1)=
+
+m4_if([$1], [CXX], [
+ # C++ specific cases for pic, static, wl, etc.
+ if test yes = "$GXX"; then
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the '-m68020' flag to GCC prevents building anything better,
+ # like '-m68040'.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | cygwin* | os2* | pw32* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ case $host_os in
+ os2*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+ ;;
+ esac
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ haiku*)
+ # PIC is the default for Haiku.
+ # The "-static" flag exists, but is broken.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)=
+ ;;
+ interix[[3-9]]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+ *qnx* | *nto*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix[[4-9]]*)
+ # All AIX code is PIC.
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68*)
+ # Green Hills C++ Compiler
+ # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ mingw* | cygwin* | os2* | pw32* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | dragonfly* | midnightbsd*)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+ if test ia64 != "$host_cpu"; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ fi
+ ;;
+ aCC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ interix*)
+ # This is c89, which is MS Visual C++ (no shared libs)
+ # Anyone wants to do a port?
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ case $cc_basename in
+ KCC*)
+ # KAI C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ ecpc* )
+ # old Intel C++ for x86_64, which still supported -KPIC.
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ icpc* )
+ # Intel C++, used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ cxx*)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
+ # IBM XL 8.0, 9.0 on PPC and BlueGene
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | $SED 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd*)
+ ;;
+ *qnx* | *nto*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ cxx*)
+ # Digital/Compaq C++
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC* | sunCC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ lcc*)
+ # Lucid
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ vxworks*)
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+],
+[
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the '-m68020' flag to GCC prevents building anything better,
+ # like '-m68040'.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ case $host_os in
+ os2*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+ ;;
+ esac
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+
+ haiku*)
+ # PIC is the default for Haiku.
+ # The "-static" flag exists, but is broken.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)=
+ ;;
+
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+
+ interix[[3-9]]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ enable_shared=no
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+
+ case $cc_basename in
+ nvcc*) # Cuda Compiler Driver 2.2
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
+ if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)"
+ fi
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ case $cc_basename in
+ nagfor*)
+ # NAG Fortran compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ esac
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ case $host_os in
+ os2*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+ ;;
+ esac
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC (with -KPIC) is the default.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ case $cc_basename in
+ # old Intel for x86_64, which still supported -KPIC.
+ ecc*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ # icc used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ icc* | ifort*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ # Lahey Fortran 8.1.
+ lf95*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
+ ;;
+ nagfor*)
+ # NAG Fortran compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ tcc*)
+ # Fabrice Bellard et al's Tiny C Compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ ccc*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All Alpha code is PIC.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ xl* | bgxl* | bgf* | mpixl*)
+ # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | $SED 5q` in
+ *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*)
+ # Sun Fortran 8.3 passes all unrecognized flags to the linker
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
+ ;;
+ *Sun\ F* | *Sun*Fortran*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ *Sun\ C*)
+ # Sun C 5.9
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ ;;
+ *Intel*\ [[CF]]*Compiler*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ *Portland\ Group*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ newsos6)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+
+ osf3* | osf4* | osf5*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All OSF/1 code is PIC.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ rdos*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ solaris*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ unicos*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+
+ uts4*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ *)
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+])
+case $host_os in
+ # For platforms that do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
+ ;;
+esac
+
+AC_CACHE_CHECK([for $compiler option to produce PIC],
+ [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)],
+ [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+ _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
+ [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
+ [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
+ [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
+ "" | " "*) ;;
+ *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+ esac],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
+ [Additional compiler flags for building library objects])
+
+_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
+ [How to pass a linker flag through the compiler])
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
+_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+ _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
+ $lt_tmp_static_flag,
+ [],
+ [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
+_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
+ [Compiler flag to prevent dynamic linking])
+])# _LT_COMPILER_PIC
+
+
+# _LT_LINKER_SHLIBS([TAGNAME])
+# ----------------------------
+# See if the linker supports building shared libraries.
+m4_defun([_LT_LINKER_SHLIBS],
+[AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+m4_if([$1], [CXX], [
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+ case $host_os in
+ aix[[4-9]]*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to GNU nm, but means don't demangle to AIX nm.
+ # Without the "-l" option, or with the "-B" option, AIX nm treats
+ # weak defined symbols like other global defined symbols, whereas
+ # GNU nm marks them as "W".
+ # While the 'weak' keyword is ignored in the Export File, we need
+ # it in the Import File for the 'aix-soname' feature, so we have
+ # to replace the "-B" option with "-P" for AIX nm.
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds
+ ;;
+ cygwin* | mingw* | cegcc*)
+ case $cc_basename in
+ cl* | icl*)
+ _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+ ;;
+ *)
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+ ;;
+ esac
+ ;;
+ *)
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+], [
+ runpath_var=
+ _LT_TAGVAR(allow_undefined_flag, $1)=
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(archive_cmds, $1)=
+ _LT_TAGVAR(archive_expsym_cmds, $1)=
+ _LT_TAGVAR(compiler_needs_object, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(hardcode_automatic, $1)=no
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ _LT_TAGVAR(hardcode_minus_L, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_TAGVAR(fix_hardcoded_libdir_flag_spec, $1)=
+ _LT_TAGVAR(fix_hardcoded_libdir_flag_spec_ld, $1)=
+ _LT_TAGVAR(inherit_rpath, $1)=no
+ _LT_TAGVAR(link_all_deplibs, $1)=unknown
+ _LT_TAGVAR(module_cmds, $1)=
+ _LT_TAGVAR(module_expsym_cmds, $1)=
+ _LT_TAGVAR(old_archive_from_new_cmds, $1)=
+ _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+ _LT_TAGVAR(thread_safe_flag_spec, $1)=
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ _LT_TAGVAR(include_expsyms, $1)=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ' (' and ')$', so one must not match beginning or
+ # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
+ # as well as any symbol that contains 'd'.
+ _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ # Exclude shared library initialization/finalization symbols.
+dnl Note also adjust exclude_expsyms for C++ above.
+ extract_expsyms_cmds=
+
+ case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++ or Intel C++ Compiler.
+ if test yes != "$GCC"; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
+ with_gnu_ld=yes
+ ;;
+ openbsd* | bitrig*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+
+ # On some targets, GNU ld is compatible enough with the native linker
+ # that we're better off using the native interface for both.
+ lt_use_gnu_ld_interface=no
+ if test yes = "$with_gnu_ld"; then
+ case $host_os in
+ aix*)
+ # The AIX port of GNU ld has always aspired to compatibility
+ # with the native linker. However, as the warning in the GNU ld
+ # block says, versions before 2.19.5* couldn't really create working
+ # shared libraries, regardless of the interface used.
+ case `$LD -v 2>&1` in
+ *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+ *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;;
+ *\ \(GNU\ Binutils\)\ [[3-9]]*) ;;
+ *)
+ lt_use_gnu_ld_interface=yes
+ ;;
+ esac
+ ;;
+ *)
+ lt_use_gnu_ld_interface=yes
+ ;;
+ esac
+ fi
+
+ if test yes = "$lt_use_gnu_ld_interface"; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='$wl'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v | $SED -e 's/([[^)]]\+)\s\+//' 2>&1` in
+ *GNU\ gold*) supports_anon_versioning=yes ;;
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix[[3-9]]*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test ia64 != "$host_cpu"; then
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)=''
+ ;;
+ m68k)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file, use it as
+ # is; otherwise, prepend EXPORTS...
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ haiku*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ os2*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ shrext_cmds=.dll
+ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='@'
+ ;;
+
+ interix[[3-9]]*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+ tmp_diet=no
+ if test linux-dietlibc = "$host_os"; then
+ case $cc_basename in
+ diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
+ esac
+ fi
+ if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+ && test no = "$tmp_diet"
+ then
+ tmp_addflag=' $pic_flag'
+ tmp_sharedflag='-shared'
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95* | pgfortran*)
+ # Portland Group f77 and f90 compilers
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ lf95*) # Lahey Fortran 8.1
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ tmp_sharedflag='--shared' ;;
+ nagfor*) # NAGFOR 5.3
+ tmp_sharedflag='-Wl,-shared' ;;
+ xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+ tmp_sharedflag='-qmkshrobj'
+ tmp_addflag= ;;
+ nvcc*) # Cuda Compiler Driver 2.2
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ _LT_TAGVAR(compiler_needs_object, $1)=yes
+ ;;
+ esac
+ case `$CC -V 2>&1 | $SED 5q` in
+ *Sun\ C*) # Sun C 5.9
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ _LT_TAGVAR(compiler_needs_object, $1)=yes
+ tmp_sharedflag='-G' ;;
+ *Sun\ F*) # Sun Fortran 8.3
+ tmp_sharedflag='-G' ;;
+ esac
+ _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+
+ if test yes = "$supports_anon_versioning"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
+ fi
+
+ case $cc_basename in
+ tcc*)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic'
+ ;;
+ xlf* | bgf* | bgxlf* | mpixlf*)
+ # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+ if test yes = "$supports_anon_versioning"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ esac
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+
+ if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then
+ runpath_var=
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ fi
+ ;;
+
+ aix[[4-9]]*)
+ if test ia64 = "$host_cpu"; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to GNU nm, but means don't demangle to AIX nm.
+ # Without the "-l" option, or with the "-B" option, AIX nm treats
+ # weak defined symbols like other global defined symbols, whereas
+ # GNU nm marks them as "W".
+ # While the 'weak' keyword is ignored in the Export File, we need
+ # it in the Import File for the 'aix-soname' feature, so we have
+ # to replace the "-B" option with "-P" for AIX nm.
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # have runtime linking enabled, and use it for executables.
+ # For shared libraries, we enable/disable runtime linking
+ # depending on the kind of the shared library created -
+ # when "with_aix_soname,aix_use_runtimelinking" is:
+ # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
+ # "aix,yes" lib.so shared, rtl:yes, for executables
+ # lib.a static archive
+ # "both,no" lib.so.V(shr.o) shared, rtl:yes
+ # lib.a(lib.so.V) shared, rtl:no, for executables
+ # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a(lib.so.V) shared, rtl:no
+ # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a static archive
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+ for ld_flag in $LDFLAGS; do
+ if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # With aix-soname=svr4, we create the lib.so.V shared archives only,
+ # so we don't have lib.a shared libs to link our executables.
+ # We have to force runtime linking in this case.
+ aix_use_runtimelinking=yes
+ LDFLAGS="$LDFLAGS -Wl,-brtl"
+ fi
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_TAGVAR(archive_cmds, $1)=''
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
+ case $with_aix_soname,$aix_use_runtimelinking in
+ aix,*) ;; # traditional, no import file
+ svr4,* | *,yes) # use import file
+ # The Import File defines what to hardcode.
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+ ;;
+ esac
+
+ if test yes = "$GCC"; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`$CC -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag="$shared_flag "'$wl-G'
+ fi
+ # Need to ensure runtime linking is disabled for the traditional
+ # shared library, or the linker may eventually find shared libraries
+ # /with/ Import File - we do not want to mix them.
+ shared_flag_aix='-shared'
+ shared_flag_svr4='-shared $wl-G'
+ else
+ # not using gcc
+ if test ia64 = "$host_cpu"; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag='$wl-G'
+ else
+ shared_flag='$wl-bM:SRE'
+ fi
+ shared_flag_aix='$wl-bM:SRE'
+ shared_flag_svr4='$wl-G'
+ fi
+ fi
+
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX([$1])
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+ else
+ if test ia64 = "$host_cpu"; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
+ _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX([$1])
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
+ if test yes = "$with_gnu_ld"; then
+ # We only use this code for GNU lds that support --whole-archive.
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+ else
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+ # -brtl affects multiple linker settings, -berok does not and is overridden later
+ compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
+ if test svr4 != "$with_aix_soname"; then
+ # This is similar to how AIX traditionally builds its shared libraries.
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+ fi
+ if test aix != "$with_aix_soname"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+ else
+ # used by -dlpreopen to get the symbols
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
+ fi
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)=''
+ ;;
+ m68k)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ ;;
+
+ bsdi[[45]]*)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++ or Intel C++ Compiler.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ case $cc_basename in
+ cl* | icl*)
+ # Native MSVC or ICC
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='@'
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=.dll
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+ cp "$export_symbols" "$output_objdir/$soname.def";
+ echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+ else
+ $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+ fi~
+ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+ linknames='
+ # The linker will not automatically build a static lib if we build a DLL.
+ # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+ # Don't use ranlib
+ _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+ _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+ lt_tool_outputfile="@TOOL_OUTPUT@"~
+ case $lt_outputfile in
+ *.exe|*.EXE) ;;
+ *)
+ lt_outputfile=$lt_outputfile.exe
+ lt_tool_outputfile=$lt_tool_outputfile.exe
+ ;;
+ esac~
+ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+ $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+ $RM "$lt_outputfile.manifest";
+ fi'
+ ;;
+ *)
+ # Assume MSVC and ICC wrapper
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=.dll
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+ # FIXME: Should let the user specify the lib program.
+ _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+ esac
+ ;;
+
+ darwin* | rhapsody*)
+ _LT_DARWIN_LINKER_FEATURES($1)
+ ;;
+
+ dgux*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2.*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | dragonfly* | midnightbsd*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ hpux9*)
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ ;;
+
+ hpux10*)
+ if test yes,no = "$GCC,$with_gnu_ld"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags $fix_hardcoded_libdir_flag'
+ _LT_TAGVAR(module_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $fix_hardcoded_libdir_flag'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags $fix_hardcoded_libdir_flag_ld'
+ _LT_TAGVAR(module_cmds, $1)='$LD -b -o $lib $libobjs $deplibs $linker_flags $fix_hardcoded_libdir_flag_ld'
+ fi
+ if test no = "$with_gnu_ld"; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir $fix_hardcoded_libdir_flag'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ # gcc-3.0.1 (collect2) breaks on -Wl,+cdp.
+ # HP-cc ignores -Wl,+cdp, and we test the linker for +cdp support.
+ AC_CACHE_CHECK([if +cdp linker flag works],
+ [_LT_TAGVAR(lt_cv_ldflag_cdp_works, $1)],
+ [_LT_TAGVAR(lt_cv_ldflag_cdp_works, $1)=no
+ save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,+cdp -Wl,/usr/lib/libc.1:/nonexistent -Wl,+cdp -Wl,/lib/libc.1:/nonexistent"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+ [_LT_TAGVAR(lt_cv_ldflag_cdp_works, $1)=yes],
+ [_LT_TAGVAR(lt_cv_ldflag_cdp_works, $1)=no])
+ LDFLAGS="$save_LDFLAGS"
+ ])
+ if test "$_LT_TAGVAR(lt_cv_ldflag_cdp_works, $1)" = yes; then
+ _LT_TAGVAR(fix_hardcoded_libdir_flag_spec, $1)='${wl}+cdp ${wl}${linkdir}/${dlname}:${libdir}/${dlname}'
+ _LT_TAGVAR(fix_hardcoded_libdir_flag_spec_ld, $1)='+cdp ${linkdir}/${dlname}:${libdir}/${dlname}'
+ fi
+ fi
+ ;;
+
+ hpux11*)
+ if test yes,no = "$GCC,$with_gnu_ld"; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(module_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(module_cmds, $1)='$CC -shared $pic_flag $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags $fix_hardcoded_libdir_flag'
+ _LT_TAGVAR(module_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $fix_hardcoded_libdir_flag'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(module_cmds, $1)='$CC -b -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(module_cmds, $1)='$CC -b $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ m4_if($1, [], [
+ # Older versions of the 11.00 compiler do not understand -b yet
+ # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+ _LT_LINKER_OPTION([if $CC understands -b],
+ _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
+ [
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags $fix_hardcoded_libdir_flag'
+ _LT_TAGVAR(module_cmds, $1)='$CC -b -o $lib $libobjs $deplibs $compiler_flags $fix_hardcoded_libdir_flag'
+ ], [
+ _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags $fix_hardcoded_libdir_flag_ld'
+ _LT_TAGVAR(module_cmds, $1)='$LD -b -o $lib $libobjs $deplibs $linker_flags $fix_hardcoded_libdir_flag_ld'
+ ])],
+ [
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags $fix_hardcoded_libdir_flag'
+ _LT_TAGVAR(module_cmds, $1)='$CC -b -o $lib $libobjs $deplibs $compiler_flags $fix_hardcoded_libdir_flag'
+ ])
+ ;;
+ esac
+ fi
+ if test no = "$with_gnu_ld"; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir $fix_hardcoded_libdir_flag'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ # gcc-3.0.1 (collect2) breaks on -Wl,+cdp.
+ # HP-cc ignores -Wl,+cdp, and we test the linker for +cdp support.
+ AC_CACHE_CHECK([if +cdp linker flag works],
+ [_LT_TAGVAR(lt_cv_ldflag_cdp_works, $1)],
+ [_LT_TAGVAR(lt_cv_ldflag_cdp_works, $1)=no
+ save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,+cdp -Wl,/usr/lib/libc.1:/nonexistent -Wl,+cdp -Wl,/lib/libc.1:/nonexistent"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+ [_LT_TAGVAR(lt_cv_ldflag_cdp_works, $1)=yes],
+ [_LT_TAGVAR(lt_cv_ldflag_cdp_works, $1)=no])
+ LDFLAGS="$save_LDFLAGS"
+ ])
+ if test "$_LT_TAGVAR(lt_cv_ldflag_cdp_works, $1)" = yes; then
+ _LT_TAGVAR(fix_hardcoded_libdir_flag_spec, $1)='${wl}+cdp ${wl}${linkdir}/${dlname}:${libdir}/${dlname}'
+ _LT_TAGVAR(fix_hardcoded_libdir_flag_spec_ld, $1)='+cdp ${linkdir}/${dlname}:${libdir}/${dlname}'
+ fi
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ # Try to use the -exported_symbol ld option, if it does not
+ # work, assume that -exports_file does not work either and
+ # implicitly export all symbols.
+ # This should be the same for all languages, so no per-tag cache variable.
+ AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol],
+ [lt_cv_irix_exported_symbol],
+ [save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
+ AC_LINK_IFELSE(
+ [AC_LANG_SOURCE(
+ [AC_LANG_CASE([C], [[int foo (void) { return 0; }]],
+ [C++], [[int foo (void) { return 0; }]],
+ [Fortran 77], [[
+ subroutine foo
+ end]],
+ [Fortran], [[
+ subroutine foo
+ end]])])],
+ [lt_cv_irix_exported_symbol=yes],
+ [lt_cv_irix_exported_symbol=no])
+ LDFLAGS=$save_LDFLAGS])
+ if test yes = "$lt_cv_irix_exported_symbol"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
+ fi
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(inherit_rpath, $1)=yes
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ linux*)
+ case $cc_basename in
+ tcc*)
+ # Fabrice Bellard et al's Tiny C Compiler
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ newsos6)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *nto* | *qnx*)
+ ;;
+
+ openbsd* | bitrig*)
+ if test -f /usr/libexec/ld.so; then
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ fi
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ os2*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ shrext_cmds=.dll
+ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='@'
+ ;;
+
+ osf3*)
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ else
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ else
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ solaris*)
+ _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
+ if test yes = "$GCC"; then
+ wlarc='$wl'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ else
+ case `$CC -V 2>&1` in
+ *"Compilers 5.0"*)
+ wlarc=''
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+ ;;
+ *)
+ wlarc='$wl'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ ;;
+ esac
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands '-z linker_flag'. GCC discards it without '$wl',
+ # but is careful enough not to reorder.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+ fi
+ ;;
+ esac
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ sunos4*)
+ if test sequent = "$host_vendor"; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ ;;
+ motorola)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4.3*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+ _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We CANNOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+ _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+
+ if test sni = "$host_vendor"; then
+ case $host in
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym'
+ ;;
+ esac
+ fi
+ fi
+])
+AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
+
+_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
+
+_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
+_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
+_LT_DECL([], [extract_expsyms_cmds], [2],
+ [The commands to extract the exported symbol list from a shared archive])
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+ # Assume -lc should be added
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+ if test yes,yes = "$GCC,$enable_shared"; then
+ case $_LT_TAGVAR(archive_cmds, $1) in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ AC_CACHE_CHECK([whether -lc should be explicitly linked in],
+ [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
+ [$RM conftest*
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
+ pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
+ _LT_TAGVAR(allow_undefined_flag, $1)=
+ if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
+ then
+ lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ else
+ lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ fi
+ _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $RM conftest*
+ ])
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
+ [Whether or not to add -lc for building shared libraries])
+_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
+ [enable_shared_with_static_runtimes], [0],
+ [Whether or not to disallow shared libs when runtime libs are static])
+_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
+ [Compiler flag to allow reflexive dlopens])
+_LT_TAGDECL([], [whole_archive_flag_spec], [1],
+ [Compiler flag to generate shared objects directly from archives])
+_LT_TAGDECL([], [compiler_needs_object], [1],
+ [Whether the compiler copes with passing no objects directly])
+_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
+ [Create an old-style archive from a shared archive])
+_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
+ [Create a temporary old-style archive to link instead of a shared archive])
+_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
+_LT_TAGDECL([], [archive_expsym_cmds], [2])
+_LT_TAGDECL([], [module_cmds], [2],
+ [Commands used to build a loadable module if different from building
+ a shared archive.])
+_LT_TAGDECL([], [module_expsym_cmds], [2])
+_LT_TAGDECL([], [with_gnu_ld], [1],
+ [Whether we are building with GNU ld or not])
+_LT_TAGDECL([], [allow_undefined_flag], [1],
+ [Flag that allows shared libraries with undefined symbols to be built])
+_LT_TAGDECL([], [no_undefined_flag], [1],
+ [Flag that enforces no undefined symbols])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
+ [Flag to hardcode $libdir into a binary during linking.
+ This must work even if $libdir does not exist])
+_LT_TAGDECL([], [hardcode_libdir_separator], [1],
+ [Whether we need a single "-rpath" flag with a separated argument])
+_LT_TAGDECL([], [hardcode_direct], [0],
+ [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
+ DIR into the resulting binary])
+_LT_TAGDECL([], [hardcode_direct_absolute], [0],
+ [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
+ DIR into the resulting binary and the resulting library dependency is
+ "absolute", i.e impossible to change by setting $shlibpath_var if the
+ library is relocated])
+_LT_TAGDECL([], [hardcode_minus_L], [0],
+ [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+ into the resulting binary])
+_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
+ [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+ into the resulting binary])
+_LT_TAGDECL([], [hardcode_automatic], [0],
+ [Set to "yes" if building a shared library automatically hardcodes DIR
+ into the library and all subsequent libraries and executables linked
+ against it])
+_LT_TAGDECL([], [fix_hardcoded_libdir_flag_spec], [1],
+ [Flag to modify a path being hardcoded into the resulting binary])
+_LT_TAGDECL([], [fix_hardcoded_libdir_flag_spec_ld], [1],
+ [If ld is used when linking, flag to modify a path being hardcoded into the resulting binary])
+_LT_TAGDECL([], [inherit_rpath], [0],
+ [Set to yes if linker adds runtime paths of dependent libraries
+ to runtime path list])
+_LT_TAGDECL([], [link_all_deplibs], [0],
+ [Whether libtool must link a program against all its dependency libraries])
+_LT_TAGDECL([], [always_export_symbols], [0],
+ [Set to "yes" if exported symbols are required])
+_LT_TAGDECL([], [export_symbols_cmds], [2],
+ [The commands to list exported symbols])
+_LT_TAGDECL([], [exclude_expsyms], [1],
+ [Symbols that should not be listed in the preloaded symbols])
+_LT_TAGDECL([], [include_expsyms], [1],
+ [Symbols that must always be exported])
+_LT_TAGDECL([], [prelink_cmds], [2],
+ [Commands necessary for linking programs (against libraries) with templates])
+_LT_TAGDECL([], [postlink_cmds], [2],
+ [Commands necessary for finishing linking programs])
+_LT_TAGDECL([], [file_list_spec], [1],
+ [Specify filename containing input files])
+dnl FIXME: Not yet implemented
+dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
+dnl [Compiler flag to generate thread safe objects])
+])# _LT_LINKER_SHLIBS
+
+
+# _LT_LANG_C_CONFIG([TAG])
+# ------------------------
+# Ensure that the configuration variables for a C compiler are suitably
+# defined. These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_C_CONFIG],
+[m4_require([_LT_DECL_EGREP])dnl
+lt_save_CC=$CC
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+_LT_TAG_COMPILER
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+ _LT_COMPILER_NO_RTTI($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+ LT_SYS_DLOPEN_SELF
+ _LT_CMD_STRIPLIB
+
+ # Report what library types will actually be built
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test no = "$can_build_shared" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test yes = "$enable_shared" && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+ aix[[4-9]]*)
+ if test ia64 != "$host_cpu"; then
+ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+ yes,aix,yes) ;; # shared object as lib.so file only
+ yes,svr4,*) ;; # shared object as lib.so archive member only
+ yes,*) enable_static=no ;; # shared object in lib.a archive as well
+ esac
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test yes = "$enable_shared" || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_CONFIG($1)
+fi
+AC_LANG_POP
+CC=$lt_save_CC
+])# _LT_LANG_C_CONFIG
+
+
+# _LT_LANG_CXX_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a C++ compiler are suitably
+# defined. These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_CXX_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+if test -n "$CXX" && ( test no != "$CXX" &&
+ ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) ||
+ (test g++ != "$CXX"))); then
+ AC_PROG_CXXCPP
+else
+ _lt_caught_CXX_error=yes
+fi
+
+AC_LANG_PUSH(C++)
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(compiler_needs_object, $1)=no
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(fix_hardcoded_libdir_flag_spec, $1)=
+_LT_TAGVAR(fix_hardcoded_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test yes != "$_lt_caught_CXX_error"; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="int some_variable = 0;"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC=$CC
+ lt_save_CFLAGS=$CFLAGS
+ lt_save_LD=$LD
+ lt_save_GCC=$GCC
+ GCC=$GXX
+ lt_save_with_gnu_ld=$with_gnu_ld
+ lt_save_path_LD=$lt_cv_path_LD
+ if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+ else
+ $as_unset lt_cv_prog_gnu_ld
+ fi
+ if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+ else
+ $as_unset lt_cv_path_LD
+ fi
+ test -z "${LDCXX+set}" || LD=$LDCXX
+ CC=${CXX-"c++"}
+ CFLAGS=$CXXFLAGS
+ compiler=$CC
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+
+ if test -n "$compiler"; then
+ # We don't want -fno-exception when compiling C++ code, so set the
+ # no_builtin_flag separately
+ if test yes = "$GXX"; then
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+ else
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+ fi
+
+ if test yes = "$GXX"; then
+ # Set up default GNU C++ configuration
+
+ LT_PATH_LD
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test yes = "$with_gnu_ld"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='$wl'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+ $GREP 'no-whole-archive' > /dev/null; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+
+ else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+ fi
+
+ # PORTME: fill in a description of your system's C++ link characteristics
+ AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aix[[4-9]]*)
+ if test ia64 = "$host_cpu"; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # have runtime linking enabled, and use it for executables.
+ # For shared libraries, we enable/disable runtime linking
+ # depending on the kind of the shared library created -
+ # when "with_aix_soname,aix_use_runtimelinking" is:
+ # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
+ # "aix,yes" lib.so shared, rtl:yes, for executables
+ # lib.a static archive
+ # "both,no" lib.so.V(shr.o) shared, rtl:yes
+ # lib.a(lib.so.V) shared, rtl:no, for executables
+ # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a(lib.so.V) shared, rtl:no
+ # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a static archive
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # With aix-soname=svr4, we create the lib.so.V shared archives only,
+ # so we don't have lib.a shared libs to link our executables.
+ # We have to force runtime linking in this case.
+ aix_use_runtimelinking=yes
+ LDFLAGS="$LDFLAGS -Wl,-brtl"
+ fi
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_TAGVAR(archive_cmds, $1)=''
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
+ case $with_aix_soname,$aix_use_runtimelinking in
+ aix,*) ;; # no import file
+ svr4,* | *,yes) # use import file
+ # The Import File defines what to hardcode.
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+ ;;
+ esac
+
+ if test yes = "$GXX"; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`$CC -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ esac
+ shared_flag='-shared'
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag=$shared_flag' $wl-G'
+ fi
+ # Need to ensure runtime linking is disabled for the traditional
+ # shared library, or the linker may eventually find shared libraries
+ # /with/ Import File - we do not want to mix them.
+ shared_flag_aix='-shared'
+ shared_flag_svr4='-shared $wl-G'
+ else
+ # not using gcc
+ if test ia64 = "$host_cpu"; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag='$wl-G'
+ else
+ shared_flag='$wl-bM:SRE'
+ fi
+ shared_flag_aix='$wl-bM:SRE'
+ shared_flag_svr4='$wl-G'
+ fi
+ fi
+
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to
+ # export.
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ # The "-G" linker flag allows undefined symbols.
+ _LT_TAGVAR(no_undefined_flag, $1)='-bernotok'
+ # Determine the default libpath from the value encoded in an empty
+ # executable.
+ _LT_SYS_MODULE_PATH_AIX([$1])
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+ else
+ if test ia64 = "$host_cpu"; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
+ _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX([$1])
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
+ if test yes = "$with_gnu_ld"; then
+ # We only use this code for GNU lds that support --whole-archive.
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+ else
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+ # -brtl affects multiple linker settings, -berok does not and is overridden later
+ compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
+ if test svr4 != "$with_aix_soname"; then
+ # This is similar to how AIX traditionally builds its shared
+ # libraries. Need -bnortl late, we may have -brtl in LDFLAGS.
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+ fi
+ if test aix != "$with_aix_soname"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+ else
+ # used by -dlpreopen to get the symbols
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
+ fi
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ case $GXX,$cc_basename in
+ ,cl* | no,cl* | ,icl* | no,icl*)
+ # Native MSVC or ICC
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='@'
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=.dll
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+ cp "$export_symbols" "$output_objdir/$soname.def";
+ echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+ else
+ $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+ fi~
+ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+ linknames='
+ # The linker will not automatically build a static lib if we build a DLL.
+ # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ # Don't use ranlib
+ _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+ _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+ lt_tool_outputfile="@TOOL_OUTPUT@"~
+ case $lt_outputfile in
+ *.exe|*.EXE) ;;
+ *)
+ lt_outputfile=$lt_outputfile.exe
+ lt_tool_outputfile=$lt_tool_outputfile.exe
+ ;;
+ esac~
+ func_to_tool_file "$lt_outputfile"~
+ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+ $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+ $RM "$lt_outputfile.manifest";
+ fi'
+ ;;
+ *)
+ # g++
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file, use it as
+ # is; otherwise, prepend EXPORTS...
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ darwin* | rhapsody*)
+ _LT_DARWIN_LINKER_FEATURES($1)
+ ;;
+
+ os2*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ shrext_cmds=.dll
+ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='@'
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ freebsd2.*)
+ # C++ shared libraries reported to be fairly broken before
+ # switch to ELF
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ freebsd-elf*)
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ ;;
+
+ freebsd* | dragonfly* | midnightbsd*)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ ;;
+
+ haiku*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ hpux9*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ ;;
+ *)
+ if test yes = "$GXX"; then
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ hpux10*|hpux11*)
+ if test no = "$with_gnu_ld"; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir $fix_hardcoded_libdir_flag'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ ;;
+ esac
+ fi
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ # gcc-3.0.1 (collect2) breaks on -Wl,+cdp.
+ # HP-aCC ignores -Wl,+cdp, and we test the linker for +cdp support.
+ AC_CACHE_CHECK([if +cdp linker flag works],
+ [_LT_TAGVAR(lt_cv_ldflag_cdp_works, $1)],
+ [_LT_TAGVAR(lt_cv_ldflag_cdp_works, $1)=no
+ save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,+cdp -Wl,/usr/lib/libc.1:/nonexistent -Wl,+cdp -Wl,/lib/libc.1:/nonexistent"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+ [_LT_TAGVAR(lt_cv_ldflag_cdp_works, $1)=yes],
+ [_LT_TAGVAR(lt_cv_ldflag_cdp_works, $1)=no])
+ LDFLAGS="$save_LDFLAGS"
+ ])
+ if test "$_LT_TAGVAR(lt_cv_ldflag_cdp_works, $1)" = yes; then
+ _LT_TAGVAR(fix_hardcoded_libdir_flag_spec, $1)='${wl}+cdp ${wl}${linkdir}/${dlname}:${libdir}/${dlname}'
+ fi
+ ;;
+ esac
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $fix_hardcoded_libdir_flag'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ ;;
+ *)
+ if test yes = "$GXX"; then
+ if test no = "$with_gnu_ld"; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $fix_hardcoded_libdir_flag'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ interix[[3-9]]*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC*)
+ # SGI C++
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test yes = "$GXX"; then
+ if test no = "$with_gnu_ld"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib'
+ fi
+ fi
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+ esac
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(inherit_rpath, $1)=yes
+ ;;
+
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc* | ecpc* )
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ tmp_idyn=
+ case $host_cpu in
+ ia64*) tmp_idyn=' -i_dynamic';;
+ esac
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler
+ case `$CC -V` in
+ *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
+ _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
+ _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
+ $RANLIB $oldlib'
+ _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 6 and above use weak symbols
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ ;;
+ cxx*)
+ # Compaq C++
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
+ ;;
+ xl* | mpixl* | bgxl*)
+ # IBM XL 8.0 on PPC, with GNU ld
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ if test yes = "$supports_anon_versioning"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ *)
+ case `$CC -V 2>&1 | $SED 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ _LT_TAGVAR(compiler_needs_object, $1)=yes
+
+ # Not sure whether something based on
+ # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+ # would be better.
+ output_verbose_link_cmd='func_echo_all'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ m88k*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+
+ *nto* | *qnx*)
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ ;;
+
+ openbsd* | bitrig*)
+ if test -f /usr/libexec/ld.so; then
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+ fi
+ output_verbose_link_cmd=func_echo_all
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ case $host in
+ osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
+ *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
+ esac
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ cxx*)
+ case $host in
+ osf3*)
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ ;;
+ *)
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~
+ $RM $lib.exp'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ ;;
+ *)
+ if test yes,no = "$GXX,$with_gnu_ld"; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+ case $host in
+ osf3*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ psos*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ lcc*)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ solaris*)
+ case $cc_basename in
+ CC* | sunCC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
+ _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands '-z linker_flag'.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+ ;;
+ esac
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+
+ output_verbose_link_cmd='func_echo_all'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test yes,no = "$GXX,$with_gnu_ld"; then
+ _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs'
+ if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+ else
+ # g++ 2.7 appears to require '-G' NOT '-shared' on this
+ # platform.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+ fi
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir'
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+ _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We CANNOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+ _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
+ '"$_LT_TAGVAR(old_archive_cmds, $1)"
+ _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
+ '"$_LT_TAGVAR(reload_cmds, $1)"
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+
+ AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+ test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
+
+ _LT_TAGVAR(GCC, $1)=$GXX
+ _LT_TAGVAR(LD, $1)=$LD
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_SYS_HIDDEN_LIBDEPS($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ CC=$lt_save_CC
+ CFLAGS=$lt_save_CFLAGS
+ LDCXX=$LD
+ LD=$lt_save_LD
+ GCC=$lt_save_GCC
+ with_gnu_ld=$lt_save_with_gnu_ld
+ lt_cv_path_LDCXX=$lt_cv_path_LD
+ lt_cv_path_LD=$lt_save_path_LD
+ lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+ lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test yes != "$_lt_caught_CXX_error"
+
+AC_LANG_POP
+])# _LT_LANG_CXX_CONFIG
+
+
+# _LT_FUNC_STRIPNAME_CNF
+# ----------------------
+# func_stripname_cnf prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+#
+# This function is identical to the (non-XSI) version of func_stripname,
+# except this one can be used by m4 code that may be executed by configure,
+# rather than the libtool script.
+m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl
+AC_REQUIRE([_LT_DECL_SED])
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])
+func_stripname_cnf ()
+{
+ case @S|@2 in
+ .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;;
+ *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;;
+ esac
+} # func_stripname_cnf
+])# _LT_FUNC_STRIPNAME_CNF
+
+
+# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
+# ---------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl
+# Dependencies to place before and after the object being linked:
+_LT_TAGVAR(predep_objects, $1)=
+_LT_TAGVAR(postdep_objects, $1)=
+_LT_TAGVAR(predeps, $1)=
+_LT_TAGVAR(postdeps, $1)=
+_LT_TAGVAR(compiler_lib_search_path, $1)=
+
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library. It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
+int a;
+void foo (void) { a = 0; }
+_LT_EOF
+], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+_LT_EOF
+], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
+ subroutine foo
+ implicit none
+ integer*4 a
+ a=0
+ return
+ end
+_LT_EOF
+], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
+ subroutine foo
+ implicit none
+ integer a
+ a=0
+ return
+ end
+_LT_EOF
+], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
+public class foo {
+ private int a;
+ public void bar (void) {
+ a = 0;
+ }
+};
+_LT_EOF
+], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF
+package foo
+func foo() {
+}
+_LT_EOF
+])
+
+_lt_libdeps_save_CFLAGS=$CFLAGS
+case "$CC $CFLAGS " in #(
+*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
+*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
+*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
+esac
+
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ for p in `eval "$output_verbose_link_cmd"`; do
+ case $prev$p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test x-L = "$p" ||
+ test x-R = "$p"; then
+ prev=$p
+ continue
+ fi
+
+ # Expand the sysroot to ease extracting the directories later.
+ if test -z "$prev"; then
+ case $p in
+ -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
+ -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
+ -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
+ esac
+ fi
+ case $p in
+ =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
+ esac
+ if test no = "$pre_test_object_deps_done"; then
+ case $prev in
+ -L | -R)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
+ _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p
+ else
+ _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$_LT_TAGVAR(postdeps, $1)"; then
+ _LT_TAGVAR(postdeps, $1)=$prev$p
+ else
+ _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p"
+ fi
+ fi
+ prev=
+ ;;
+
+ *.lto.$objext) ;; # Ignore GCC LTO objects
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test no = "$pre_test_object_deps_done"; then
+ if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
+ _LT_TAGVAR(predep_objects, $1)=$p
+ else
+ _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
+ fi
+ else
+ if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
+ _LT_TAGVAR(postdep_objects, $1)=$p
+ else
+ _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$RM -f confest.$objext
+CFLAGS=$_lt_libdeps_save_CFLAGS
+
+# PORTME: override above test on systems where it is broken
+m4_if([$1], [CXX],
+[case $host_os in
+interix[[3-9]]*)
+ # Interix 3.5 installs completely hosed .la files for C++, so rather than
+ # hack all around it, let's just trust "g++" to DTRT.
+ _LT_TAGVAR(predep_objects,$1)=
+ _LT_TAGVAR(postdep_objects,$1)=
+ _LT_TAGVAR(postdeps,$1)=
+ ;;
+esac
+])
+
+case " $_LT_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=
+if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'`
+fi
+_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
+ [The directories searched by this compiler when creating a shared library])
+_LT_TAGDECL([], [predep_objects], [1],
+ [Dependencies to place before and after the objects being linked to
+ create a shared library])
+_LT_TAGDECL([], [postdep_objects], [1])
+_LT_TAGDECL([], [predeps], [1])
+_LT_TAGDECL([], [postdeps], [1])
+_LT_TAGDECL([], [compiler_lib_search_path], [1],
+ [The library search path used internally by the compiler when linking
+ a shared library])
+])# _LT_SYS_HIDDEN_LIBDEPS
+
+
+# _LT_LANG_F77_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a Fortran 77 compiler are
+# suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_F77_CONFIG],
+[AC_LANG_PUSH(Fortran 77)
+if test -z "$F77" || test no = "$F77"; then
+ _lt_disable_F77=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(fix_hardcoded_libdir_flag_spec, $1)=
+_LT_TAGVAR(fix_hardcoded_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the F77 compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test yes != "$_lt_disable_F77"; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="\
+ subroutine t
+ return
+ end
+"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code="\
+ program t
+ end
+"
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC=$CC
+ lt_save_GCC=$GCC
+ lt_save_CFLAGS=$CFLAGS
+ CC=${F77-"f77"}
+ CFLAGS=$FFLAGS
+ compiler=$CC
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+ GCC=$G77
+ if test -n "$compiler"; then
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test no = "$can_build_shared" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test yes = "$enable_shared" && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+ aix[[4-9]]*)
+ if test ia64 != "$host_cpu"; then
+ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+ yes,aix,yes) ;; # shared object as lib.so file only
+ yes,svr4,*) ;; # shared object as lib.so archive member only
+ yes,*) enable_static=no ;; # shared object in lib.a archive as well
+ esac
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test yes = "$enable_shared" || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_TAGVAR(GCC, $1)=$G77
+ _LT_TAGVAR(LD, $1)=$LD
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ GCC=$lt_save_GCC
+ CC=$lt_save_CC
+ CFLAGS=$lt_save_CFLAGS
+fi # test yes != "$_lt_disable_F77"
+
+AC_LANG_POP
+])# _LT_LANG_F77_CONFIG
+
+
+# _LT_LANG_FC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for a Fortran compiler are
+# suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_FC_CONFIG],
+[AC_LANG_PUSH(Fortran)
+
+if test -z "$FC" || test no = "$FC"; then
+ _lt_disable_FC=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for fc test sources.
+ac_ext=${ac_fc_srcext-f}
+
+# Object file extension for compiled fc test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the FC compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test yes != "$_lt_disable_FC"; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="\
+ subroutine t
+ return
+ end
+"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code="\
+ program t
+ end
+"
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC=$CC
+ lt_save_GCC=$GCC
+ lt_save_CFLAGS=$CFLAGS
+ CC=${FC-"f95"}
+ CFLAGS=$FCFLAGS
+ compiler=$CC
+ GCC=$ac_cv_fc_compiler_gnu
+
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+
+ if test -n "$compiler"; then
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test no = "$can_build_shared" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test yes = "$enable_shared" && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+ aix[[4-9]]*)
+ if test ia64 != "$host_cpu"; then
+ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+ yes,aix,yes) ;; # shared object as lib.so file only
+ yes,svr4,*) ;; # shared object as lib.so archive member only
+ yes,*) enable_static=no ;; # shared object in lib.a archive as well
+ esac
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test yes = "$enable_shared" || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu
+ _LT_TAGVAR(LD, $1)=$LD
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_SYS_HIDDEN_LIBDEPS($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ GCC=$lt_save_GCC
+ CC=$lt_save_CC
+ CFLAGS=$lt_save_CFLAGS
+fi # test yes != "$_lt_disable_FC"
+
+AC_LANG_POP
+])# _LT_LANG_FC_CONFIG
+
+
+# _LT_LANG_GCJ_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Java Compiler compiler
+# are suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_GCJ_CONFIG],
+[AC_REQUIRE([LT_PROG_GCJ])dnl
+AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GCJ-"gcj"}
+CFLAGS=$GCJFLAGS
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)=$LD
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+ _LT_COMPILER_NO_RTTI($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_GCJ_CONFIG
+
+
+# _LT_LANG_GO_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Go compiler
+# are suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_GO_CONFIG],
+[AC_REQUIRE([LT_PROG_GO])dnl
+AC_LANG_SAVE
+
+# Source file extension for Go test sources.
+ac_ext=go
+
+# Object file extension for compiled Go test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="package main; func main() { }"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='package main; func main() { }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GOC-"gccgo"}
+CFLAGS=$GOFLAGS
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)=$LD
+_LT_CC_BASENAME([$compiler])
+
+# Go did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+ _LT_COMPILER_NO_RTTI($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_GO_CONFIG
+
+
+# _LT_LANG_RC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for the Windows resource compiler
+# are suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_RC_CONFIG],
+[AC_REQUIRE([LT_PROG_RC])dnl
+AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code=$lt_simple_compile_test_code
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=
+CC=${RC-"windres"}
+CFLAGS=
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+if test -n "$compiler"; then
+ :
+ _LT_CONFIG($1)
+fi
+
+GCC=$lt_save_GCC
+AC_LANG_RESTORE
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_RC_CONFIG
+
+
+# LT_PROG_GCJ
+# -----------
+AC_DEFUN([LT_PROG_GCJ],
+[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
+ [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
+ [AC_CHECK_TOOL(GCJ, gcj,)
+ test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2"
+ AC_SUBST(GCJFLAGS)])])[]dnl
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
+
+
+# LT_PROG_GO
+# ----------
+AC_DEFUN([LT_PROG_GO],
+[AC_CHECK_TOOL(GOC, gccgo,)
+])
+
+
+# LT_PROG_RC
+# ----------
+AC_DEFUN([LT_PROG_RC],
+[AC_CHECK_TOOL(RC, windres,)
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_RC], [])
+
+
+# _LT_DECL_EGREP
+# --------------
+# If we don't have a new enough Autoconf to choose the best grep
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_EGREP],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_REQUIRE([AC_PROG_FGREP])dnl
+test -z "$GREP" && GREP=grep
+_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
+_LT_DECL([], [EGREP], [1], [An ERE matcher])
+_LT_DECL([], [FGREP], [1], [A literal string matcher])
+dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
+AC_SUBST([GREP])
+])
+
+
+# _LT_DECL_OBJDUMP
+# --------------
+# If we don't have a new enough Autoconf to choose the best objdump
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_OBJDUMP],
+[AC_CHECK_TOOL(OBJDUMP, objdump, false)
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
+AC_SUBST([OBJDUMP])
+])
+
+# _LT_DECL_DLLTOOL
+# ----------------
+# Ensure DLLTOOL variable is set.
+m4_defun([_LT_DECL_DLLTOOL],
+[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
+AC_SUBST([DLLTOOL])
+])
+
+# _LT_DECL_FILECMD
+# ----------------
+# Check for a file(cmd) program that can be used to detect file type and magic
+m4_defun([_LT_DECL_FILECMD],
+[AC_CHECK_TOOL([FILECMD], [file], [:])
+_LT_DECL([], [FILECMD], [1], [A file(cmd) program that detects file types])
+])# _LD_DECL_FILECMD
+
+# _LT_DECL_SED
+# ------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible. Prefer GNU sed if found.
+m4_defun([_LT_DECL_SED],
+[AC_PROG_SED
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
+_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
+ [Sed that helps us avoid accidentally triggering echo(1) options like -n])
+])# _LT_DECL_SED
+
+m4_ifndef([AC_PROG_SED], [
+############################################################
+# NOTE: This macro has been submitted for inclusion into #
+# GNU Autoconf as AC_PROG_SED. When it is available in #
+# a released version of Autoconf we should remove this #
+# macro and use it instead. #
+############################################################
+
+m4_defun([AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for lt_ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+ fi
+ done
+ done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+ test ! -f "$lt_ac_sed" && continue
+ cat /dev/null > conftest.in
+ lt_ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+ # Check for GNU sed and select it if it is found.
+ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+ lt_cv_path_SED=$lt_ac_sed
+ break
+ fi
+ while true; do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo >>conftest.nl
+ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+ cmp -s conftest.out conftest.nl || break
+ # 10000 chars as input seems more than enough
+ test 10 -lt "$lt_ac_count" && break
+ lt_ac_count=`expr $lt_ac_count + 1`
+ if test "$lt_ac_count" -gt "$lt_ac_max"; then
+ lt_ac_max=$lt_ac_count
+ lt_cv_path_SED=$lt_ac_sed
+ fi
+ done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])#AC_PROG_SED
+])#m4_ifndef
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_SED], [])
+
+
+# _LT_CHECK_SHELL_FEATURES
+# ------------------------
+# Find out whether the shell is Bourne or XSI compatible,
+# or has some other useful features.
+m4_defun([_LT_CHECK_SHELL_FEATURES],
+[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ lt_unset=unset
+else
+ lt_unset=false
+fi
+_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+ lt_SP2NL='tr \040 \012'
+ lt_NL2SP='tr \015\012 \040\040'
+ ;;
+ *) # EBCDIC based system
+ lt_SP2NL='tr \100 \n'
+ lt_NL2SP='tr \r\n \100\100'
+ ;;
+esac
+_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
+_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
+])# _LT_CHECK_SHELL_FEATURES
+
+
+# _LT_PATH_CONVERSION_FUNCTIONS
+# -----------------------------
+# Determine what file name conversion functions should be used by
+# func_to_host_file (and, implicitly, by func_to_host_path). These are needed
+# for certain cross-compile configurations and native mingw.
+m4_defun([_LT_PATH_CONVERSION_FUNCTIONS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_MSG_CHECKING([how to convert $build file names to $host format])
+AC_CACHE_VAL(lt_cv_to_host_file_cmd,
+[case $host in
+ *-*-mingw* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+ ;;
+ *-*-cygwin* )
+ lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+ ;;
+ * ) # otherwise, assume *nix
+ lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+ ;;
+ esac
+ ;;
+ *-*-cygwin* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+ ;;
+ *-*-cygwin* )
+ lt_cv_to_host_file_cmd=func_convert_file_noop
+ ;;
+ * ) # otherwise, assume *nix
+ lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+ ;;
+ esac
+ ;;
+ * ) # unhandled hosts (and "normal" native builds)
+ lt_cv_to_host_file_cmd=func_convert_file_noop
+ ;;
+esac
+])
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+AC_MSG_RESULT([$lt_cv_to_host_file_cmd])
+_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd],
+ [0], [convert $build file names to $host format])dnl
+
+AC_MSG_CHECKING([how to convert $build file names to toolchain format])
+AC_CACHE_VAL(lt_cv_to_tool_file_cmd,
+[#assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+ *-*-mingw* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+ ;;
+ esac
+ ;;
+esac
+])
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+AC_MSG_RESULT([$lt_cv_to_tool_file_cmd])
+_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
+ [0], [convert $build files to toolchain format])dnl
+])# _LT_PATH_CONVERSION_FUNCTIONS
diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4
new file mode 100644
index 0000000..b0b5e9c
--- /dev/null
+++ b/m4/ltoptions.m4
@@ -0,0 +1,437 @@
+# Helper functions for option handling. -*- Autoconf -*-
+#
+# Copyright (C) 2004-2005, 2007-2009, 2011-2019, 2021-2022 Free
+# Software Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 8 ltoptions.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
+
+
+# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
+# ------------------------------------------
+m4_define([_LT_MANGLE_OPTION],
+[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
+
+
+# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
+# ---------------------------------------
+# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
+# matching handler defined, dispatch to it. Other OPTION-NAMEs are
+# saved as a flag.
+m4_define([_LT_SET_OPTION],
+[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
+m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
+ _LT_MANGLE_DEFUN([$1], [$2]),
+ [m4_warning([Unknown $1 option '$2'])])[]dnl
+])
+
+
+# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
+# ------------------------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+m4_define([_LT_IF_OPTION],
+[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
+
+
+# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
+# -------------------------------------------------------
+# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
+# are set.
+m4_define([_LT_UNLESS_OPTIONS],
+[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+ [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
+ [m4_define([$0_found])])])[]dnl
+m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
+])[]dnl
+])
+
+
+# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
+# ----------------------------------------
+# OPTION-LIST is a space-separated list of Libtool options associated
+# with MACRO-NAME. If any OPTION has a matching handler declared with
+# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
+# the unknown option and exit.
+m4_defun([_LT_SET_OPTIONS],
+[# Set options
+m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+ [_LT_SET_OPTION([$1], _LT_Option)])
+
+m4_if([$1],[LT_INIT],[
+ dnl
+ dnl Simply set some default values (i.e off) if boolean options were not
+ dnl specified:
+ _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
+ ])
+ _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
+ ])
+ dnl
+ dnl If no reference was made to various pairs of opposing options, then
+ dnl we run the default mode handler for the pair. For example, if neither
+ dnl 'shared' nor 'disable-shared' was passed, we enable building of shared
+ dnl archives by default:
+ _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
+ _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
+ _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
+ _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
+ [_LT_ENABLE_FAST_INSTALL])
+ _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
+ [_LT_WITH_AIX_SONAME([aix])])
+ ])
+])# _LT_SET_OPTIONS
+
+
+## --------------------------------- ##
+## Macros to handle LT_INIT options. ##
+## --------------------------------- ##
+
+# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
+# -----------------------------------------
+m4_define([_LT_MANGLE_DEFUN],
+[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
+
+
+# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
+# -----------------------------------------------
+m4_define([LT_OPTION_DEFINE],
+[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
+])# LT_OPTION_DEFINE
+
+
+# dlopen
+# ------
+LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
+])
+
+AU_DEFUN([AC_LIBTOOL_DLOPEN],
+[_LT_SET_OPTION([LT_INIT], [dlopen])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the 'dlopen' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
+
+
+# win32-dll
+# ---------
+# Declare package support for building win32 dll's.
+LT_OPTION_DEFINE([LT_INIT], [win32-dll],
+[enable_win32_dll=yes
+
+case $host in
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
+ AC_CHECK_TOOL(AS, as, false)
+ AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+ AC_CHECK_TOOL(OBJDUMP, objdump, false)
+ ;;
+esac
+
+test -z "$AS" && AS=as
+_LT_DECL([], [AS], [1], [Assembler program])dnl
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
+])# win32-dll
+
+AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+_LT_SET_OPTION([LT_INIT], [win32-dll])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the 'win32-dll' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
+
+
+# _LT_ENABLE_SHARED([DEFAULT])
+# ----------------------------
+# implement the --enable-shared flag, and supports the 'shared' and
+# 'disable-shared' LT_INIT options.
+# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
+m4_define([_LT_ENABLE_SHARED],
+[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([shared],
+ [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+ [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac],
+ [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
+
+ _LT_DECL([build_libtool_libs], [enable_shared], [0],
+ [Whether or not to build shared libraries])
+])# _LT_ENABLE_SHARED
+
+LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
+])
+
+AC_DEFUN([AC_DISABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], [disable-shared])
+])
+
+AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_SHARED], [])
+dnl AC_DEFUN([AM_DISABLE_SHARED], [])
+
+
+
+# _LT_ENABLE_STATIC([DEFAULT])
+# ----------------------------
+# implement the --enable-static flag, and support the 'static' and
+# 'disable-static' LT_INIT options.
+# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
+m4_define([_LT_ENABLE_STATIC],
+[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([static],
+ [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+ [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac],
+ [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
+
+ _LT_DECL([build_old_libs], [enable_static], [0],
+ [Whether or not to build static libraries])
+])# _LT_ENABLE_STATIC
+
+LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
+])
+
+AC_DEFUN([AC_DISABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], [disable-static])
+])
+
+AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_STATIC], [])
+dnl AC_DEFUN([AM_DISABLE_STATIC], [])
+
+
+
+# _LT_ENABLE_FAST_INSTALL([DEFAULT])
+# ----------------------------------
+# implement the --enable-fast-install flag, and support the 'fast-install'
+# and 'disable-fast-install' LT_INIT options.
+# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
+m4_define([_LT_ENABLE_FAST_INSTALL],
+[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([fast-install],
+ [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+ [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac],
+ [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
+
+_LT_DECL([fast_install], [enable_fast_install], [0],
+ [Whether or not to optimize for fast installation])dnl
+])# _LT_ENABLE_FAST_INSTALL
+
+LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
+
+# Old names:
+AU_DEFUN([AC_ENABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the 'fast-install' option into LT_INIT's first parameter.])
+])
+
+AU_DEFUN([AC_DISABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the 'disable-fast-install' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
+dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
+
+
+# _LT_WITH_AIX_SONAME([DEFAULT])
+# ----------------------------------
+# implement the --with-aix-soname flag, and support the `aix-soname=aix'
+# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT
+# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'.
+m4_define([_LT_WITH_AIX_SONAME],
+[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
+shared_archive_member_spec=
+case $host,$enable_shared in
+power*-*-aix[[5-9]]*,yes)
+ AC_MSG_CHECKING([which variant of shared library versioning to provide])
+ AC_ARG_WITH([aix-soname],
+ [AS_HELP_STRING([--with-aix-soname=aix|svr4|both],
+ [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
+ [case $withval in
+ aix|svr4|both)
+ ;;
+ *)
+ AC_MSG_ERROR([Unknown argument to --with-aix-soname])
+ ;;
+ esac
+ lt_cv_with_aix_soname=$with_aix_soname],
+ [AC_CACHE_VAL([lt_cv_with_aix_soname],
+ [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)
+ with_aix_soname=$lt_cv_with_aix_soname])
+ AC_MSG_RESULT([$with_aix_soname])
+ if test aix != "$with_aix_soname"; then
+ # For the AIX way of multilib, we name the shared archive member
+ # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
+ # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
+ # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
+ # the AIX toolchain works better with OBJECT_MODE set (default 32).
+ if test 64 = "${OBJECT_MODE-32}"; then
+ shared_archive_member_spec=shr_64
+ else
+ shared_archive_member_spec=shr
+ fi
+ fi
+ ;;
+*)
+ with_aix_soname=aix
+ ;;
+esac
+
+_LT_DECL([], [shared_archive_member_spec], [0],
+ [Shared archive member basename, for filename based shared library versioning on AIX])dnl
+])# _LT_WITH_AIX_SONAME
+
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])
+
+
+# _LT_WITH_PIC([MODE])
+# --------------------
+# implement the --with-pic flag, and support the 'pic-only' and 'no-pic'
+# LT_INIT options.
+# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'.
+m4_define([_LT_WITH_PIC],
+[AC_ARG_WITH([pic],
+ [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
+ [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+ [lt_p=${PACKAGE-default}
+ case $withval in
+ yes|no) pic_mode=$withval ;;
+ *)
+ pic_mode=default
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for lt_pkg in $withval; do
+ IFS=$lt_save_ifs
+ if test "X$lt_pkg" = "X$lt_p"; then
+ pic_mode=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac],
+ [pic_mode=m4_default([$1], [default])])
+
+_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
+])# _LT_WITH_PIC
+
+LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
+
+# Old name:
+AU_DEFUN([AC_LIBTOOL_PICMODE],
+[_LT_SET_OPTION([LT_INIT], [pic-only])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the 'pic-only' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
+
+## ----------------- ##
+## LTDL_INIT Options ##
+## ----------------- ##
+
+m4_define([_LTDL_MODE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
+ [m4_define([_LTDL_MODE], [nonrecursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [recursive],
+ [m4_define([_LTDL_MODE], [recursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [subproject],
+ [m4_define([_LTDL_MODE], [subproject])])
+
+m4_define([_LTDL_TYPE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [installable],
+ [m4_define([_LTDL_TYPE], [installable])])
+LT_OPTION_DEFINE([LTDL_INIT], [convenience],
+ [m4_define([_LTDL_TYPE], [convenience])])
diff --git a/m4/ltsugar.m4 b/m4/ltsugar.m4
new file mode 100644
index 0000000..902508b
--- /dev/null
+++ b/m4/ltsugar.m4
@@ -0,0 +1,124 @@
+# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
+#
+# Copyright (C) 2004-2005, 2007-2008, 2011-2019, 2021-2022 Free Software
+# Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltsugar.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
+
+
+# lt_join(SEP, ARG1, [ARG2...])
+# -----------------------------
+# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
+# associated separator.
+# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
+# versions in m4sugar had bugs.
+m4_define([lt_join],
+[m4_if([$#], [1], [],
+ [$#], [2], [[$2]],
+ [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
+m4_define([_lt_join],
+[m4_if([$#$2], [2], [],
+ [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
+
+
+# lt_car(LIST)
+# lt_cdr(LIST)
+# ------------
+# Manipulate m4 lists.
+# These macros are necessary as long as will still need to support
+# Autoconf-2.59, which quotes differently.
+m4_define([lt_car], [[$1]])
+m4_define([lt_cdr],
+[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
+ [$#], 1, [],
+ [m4_dquote(m4_shift($@))])])
+m4_define([lt_unquote], $1)
+
+
+# lt_append(MACRO-NAME, STRING, [SEPARATOR])
+# ------------------------------------------
+# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'.
+# Note that neither SEPARATOR nor STRING are expanded; they are appended
+# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
+# No SEPARATOR is output if MACRO-NAME was previously undefined (different
+# than defined and empty).
+#
+# This macro is needed until we can rely on Autoconf 2.62, since earlier
+# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
+m4_define([lt_append],
+[m4_define([$1],
+ m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
+
+
+
+# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
+# ----------------------------------------------------------
+# Produce a SEP delimited list of all paired combinations of elements of
+# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
+# has the form PREFIXmINFIXSUFFIXn.
+# Needed until we can rely on m4_combine added in Autoconf 2.62.
+m4_define([lt_combine],
+[m4_if(m4_eval([$# > 3]), [1],
+ [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
+[[m4_foreach([_Lt_prefix], [$2],
+ [m4_foreach([_Lt_suffix],
+ ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
+ [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
+
+
+# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
+# -----------------------------------------------------------------------
+# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
+# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
+m4_define([lt_if_append_uniq],
+[m4_ifdef([$1],
+ [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
+ [lt_append([$1], [$2], [$3])$4],
+ [$5])],
+ [lt_append([$1], [$2], [$3])$4])])
+
+
+# lt_dict_add(DICT, KEY, VALUE)
+# -----------------------------
+m4_define([lt_dict_add],
+[m4_define([$1($2)], [$3])])
+
+
+# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
+# --------------------------------------------
+m4_define([lt_dict_add_subkey],
+[m4_define([$1($2:$3)], [$4])])
+
+
+# lt_dict_fetch(DICT, KEY, [SUBKEY])
+# ----------------------------------
+m4_define([lt_dict_fetch],
+[m4_ifval([$3],
+ m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
+ m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
+
+
+# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
+# -----------------------------------------------------------------
+m4_define([lt_if_dict_fetch],
+[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
+ [$5],
+ [$6])])
+
+
+# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
+# --------------------------------------------------------------
+m4_define([lt_dict_filter],
+[m4_if([$5], [], [],
+ [lt_join(m4_quote(m4_default([$4], [[, ]])),
+ lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
+ [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
+])
diff --git a/m4/ltversion.m4 b/m4/ltversion.m4
new file mode 100644
index 0000000..b155d0a
--- /dev/null
+++ b/m4/ltversion.m4
@@ -0,0 +1,24 @@
+# ltversion.m4 -- version numbers -*- Autoconf -*-
+#
+# Copyright (C) 2004, 2011-2019, 2021-2022 Free Software Foundation,
+# Inc.
+# Written by Scott James Remnant, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# @configure_input@
+
+# serial 4245 ltversion.m4
+# This file is part of GNU Libtool
+
+m4_define([LT_PACKAGE_VERSION], [2.4.7])
+m4_define([LT_PACKAGE_REVISION], [2.4.7])
+
+AC_DEFUN([LTVERSION_VERSION],
+[macro_version='2.4.7'
+macro_revision='2.4.7'
+_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
+_LT_DECL(, macro_revision, 0)
+])
diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4
new file mode 100644
index 0000000..0f7a875
--- /dev/null
+++ b/m4/lt~obsolete.m4
@@ -0,0 +1,99 @@
+# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
+#
+# Copyright (C) 2004-2005, 2007, 2009, 2011-2019, 2021-2022 Free
+# Software Foundation, Inc.
+# Written by Scott James Remnant, 2004.
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 5 lt~obsolete.m4
+
+# These exist entirely to fool aclocal when bootstrapping libtool.
+#
+# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN),
+# which have later been changed to m4_define as they aren't part of the
+# exported API, or moved to Autoconf or Automake where they belong.
+#
+# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
+# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
+# using a macro with the same name in our local m4/libtool.m4 it'll
+# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
+# and doesn't know about Autoconf macros at all.)
+#
+# So we provide this file, which has a silly filename so it's always
+# included after everything else. This provides aclocal with the
+# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
+# because those macros already exist, or will be overwritten later.
+# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
+#
+# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
+# Yes, that means every name once taken will need to remain here until
+# we give up compatibility with versions before 1.7, at which point
+# we need to keep only those names which we still refer to.
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
+
+m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
+m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
+m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
+m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
+m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
+m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
+m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
+m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
+m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
+m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
+m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
+m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
+m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
+m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
+m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
+m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
+m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
+m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
+m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
+m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
+m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
+m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
+m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
+m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
+m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
+m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
+m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
+m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
+m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
+m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
+m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
+m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
+m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
+m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
+m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
+m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
+m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
+m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
+m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
+m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
+m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
+m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
+m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
+m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
+m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
+m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
+m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
+m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
+m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
+m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
+m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
diff --git a/m4/openssl.m4 b/m4/openssl.m4
new file mode 100644
index 0000000..6c2d6a6
--- /dev/null
+++ b/m4/openssl.m4
@@ -0,0 +1,309 @@
+AC_DEFUN([SUDO_CHECK_OPENSSL], [
+ openssl_missing=no
+ if test "${enable_openssl-no}" != no; then
+ # Use pkg-config to find the openssl cflags and libs if possible.
+ if test "$enable_openssl" != "yes" -a "$enable_openssl" != "maybe"; then
+ PKG_CONFIG_LIBDIR=
+ for d in ${enable_openssl}/*/pkgconfig; do
+ if test -d "$d"; then
+ PKG_CONFIG_LIBDIR="$PKG_CONFIG_LIBDIR:$d"
+ fi
+ done
+ if test -n "$PKG_CONFIG_LIBDIR"; then
+ PKG_CONFIG_LIBDIR=${PKG_CONFIG_LIBDIR#:}
+ export PKG_CONFIG_LIBDIR
+ fi
+ elif test "$cross_compiling" = "yes" -a -z "$PKG_CONFIG"; then
+ # Cannot use pkg-config when cross-compiling
+ PKG_CONFIG=false
+ fi
+ : ${PKG_CONFIG='pkg-config'}
+ pkg_openssl=`printf $enable_openssl_pkgconfig_template "openssl"`
+ pkg_libcrypto=lib`printf $enable_openssl_pkgconfig_template "crypto"`
+ if $PKG_CONFIG --exists "$pkg_openssl >= 1.0.1" >/dev/null 2>&1; then
+ AC_DEFINE(HAVE_OPENSSL)
+ if test "$enable_openssl" = "maybe"; then
+ enable_openssl=yes
+ fi
+
+ # Check whether --static is needed (don't assume name of ssl lib)
+ # There may be dependent libraries or -pthread.
+ O_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS `$PKG_CONFIG --libs-only-L $pkg_openssl`"
+ libssl="`$PKG_CONFIG --libs-only-l $pkg_openssl | sed 's/^ *-l//'`"
+ libssl_extra="`echo $libssl | sed 's/^[[^ ]]* *//'`"
+ libssl="`echo $libssl | sed 's/ .*//'`"
+ AC_CHECK_LIB([$libssl], [SSL_new], [STATIC=""], [STATIC="--static"], [$libssl_extra])
+ LDFLAGS="$O_LDFLAGS"
+
+ # Use pkg-config to determine OpenSSL libs and cflags
+ for f in `$PKG_CONFIG $STATIC --libs $pkg_openssl`; do
+ case "$f" in
+ -L*)
+ f="${f#-L}"
+ SUDO_APPEND_LIBPATH([LIBTLS], [$f])
+ ;;
+ *)
+ # Do not use AX_APPEND_FLAG as it will break static builds by removing
+ # duplicates such as -lz or -latomic which are needed by -lssl and -lcrypto
+ LIBTLS="$LIBTLS $f"
+ ;;
+ esac
+ done
+ if $PKG_CONFIG --exists $pkg_libcrypto >/dev/null 2>&1; then
+ # Use OpenSSL's sha2 functions if possible (don't assume name of crypto)
+ O_LDFLAGS="$LDFLAGS"
+ libcrypto=
+ libcrypto_extra=
+ for f in `$PKG_CONFIG $STATIC --libs $pkg_libcrypto`; do
+ case "$f" in
+ -l*)
+ if test -z "$libcrypto"; then
+ libcrypto="${f#-l}"
+ else
+ libcrypto_extra="$libcrypto_extra $f"
+ fi
+ ;;
+ *)
+ AX_APPEND_FLAG([$f], [LDFLAGS])
+ ;;
+ esac
+ done
+ AC_CHECK_LIB([$libcrypto], [EVP_MD_CTX_new], [DIGEST=digest_openssl.lo], [], [$libcrypto_extra])
+ LDFLAGS="$O_LDFLAGS"
+
+ # Use pkg-config to determine libcrypto libs and cflags
+ for f in `$PKG_CONFIG $STATIC --libs $pkg_libcrypto`; do
+ case "$f" in
+ -L*)
+ f="${f#-L}"
+ SUDO_APPEND_LIBPATH([LIBCRYPTO], [$f])
+ ;;
+ *)
+ AX_APPEND_FLAG([$f], [LIBCRYPTO])
+ ;;
+ esac
+ done
+ else
+ # No separate pkg config for libcrypto
+ LIBCRYPTO="$LIBTLS"
+ LIBCRYPTO_R="$LIBTLS_R"
+ fi
+ for f in `$PKG_CONFIG --cflags-only-I $pkg_openssl`; do
+ AX_APPEND_FLAG([$f], [CPPFLAGS])
+ done
+ else
+ # No pkg-config file present, try to do it manually
+ O_LDFLAGS="$LDFLAGS"
+ if test "$enable_openssl" != "yes" -a "$enable_openssl" != "maybe"; then
+ SUDO_APPEND_LIBPATH(LDFLAGS, [${enable_openssl}/lib])
+ fi
+ AC_CHECK_LIB([ssl], [SSL_new], [
+ # Check OPENSSL_VERSION_NUMBER in headers
+ O_CPPFLAGS="$CPPFLAGS"
+ if test "$enable_openssl" != "yes" -a "$enable_openssl" != "maybe"; then
+ # Note: we only reset CPPFLAGS on failure
+ AX_APPEND_FLAG([-I${enable_openssl}/include], [CPPFLAGS])
+ fi
+ AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[#include <openssl/opensslv.h>
+#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x1000100fL
+#error "OpenSSL too old"
+#endif
+ ]])], [
+ # OpenSSL >= 1.0.1 detected, use it.
+ AC_DEFINE(HAVE_OPENSSL)
+ if test "$enable_openssl" != "yes" -a "$enable_openssl" != "maybe"; then
+ SUDO_APPEND_LIBPATH(LIBCRYPTO, [${enable_openssl}/lib])
+ SUDO_APPEND_LIBPATH(LIBTLS, [${enable_openssl}/lib])
+ else
+ enable_openssl=yes
+ fi
+ LIBCRYPTO="${LIBCRYPTO} -lcrypto"
+ LIBTLS="${LIBTLS} -lssl -lcrypto"
+
+ # Use OpenSSL's sha2 functions if possible
+ AC_CHECK_LIB([crypto], [EVP_MD_CTX_new], [
+ DIGEST=digest_openssl.lo
+ ])
+ ], [
+ # OpenSSL < 1.0.1 detected, ignore it.
+ if test "$enable_openssl" = "maybe"; then
+ AC_MSG_WARN([OpenSSL too old (1.0.1 or higher required), Sudo logsrv connections will not be encrypted.])
+ openssl_missing=yes
+ enable_openssl=no
+ else
+ AC_MSG_ERROR([OpenSSL too old (1.0.1 or higher required).])
+ fi
+ CPPFLAGS="$O_CPPFLAGS"
+ ])
+ ], [
+ if test "$enable_openssl" = "maybe"; then
+ openssl_missing=yes
+ enable_openssl=no
+ else
+ AC_MSG_ERROR([OpenSSL development libraries not found.])
+ fi
+ ], [-lcrypto])
+ LDFLAGS="$O_LDFLAGS"
+ fi
+ if test "$enable_openssl" != "yes" -a "$enable_openssl" != "maybe"; then
+ unset PKG_CONFIG_LIBDIR
+ fi
+ fi
+ #
+ # Note that enable_openssl may be reset above.
+ #
+ if test "${enable_openssl-no}" != no; then
+ OLIBS="$LIBS"
+ LIBS="$LIBS $LIBTLS"
+ AC_CHECK_FUNCS([X509_STORE_CTX_get0_cert ASN1_STRING_get0_data SSL_CTX_get0_certificate SSL_CTX_set0_tmp_dh_pkey TLS_method])
+ # SSL_CTX_set_min_proto_version may be a macro
+ AC_CHECK_DECL([SSL_CTX_set_min_proto_version], [AC_DEFINE(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION)], [], [
+ AC_INCLUDES_DEFAULT
+ #include <openssl/ssl.h>
+ ])
+ AC_CHECK_FUNCS([SSL_read_ex], [], [
+ SSL_COMPAT_SRC=lib/ssl_compat
+ ])
+ # LibreSSL TLS 1.3 support may not be enabled, check for declaration too.
+ AC_CHECK_FUNC([SSL_CTX_set_ciphersuites], [
+ AC_CHECK_DECL([SSL_CTX_set_ciphersuites], [AC_DEFINE(HAVE_SSL_CTX_SET_CIPHERSUITES)], [], [
+ AC_INCLUDES_DEFAULT
+ #include <openssl/ssl.h>
+ ])
+ ])
+ LIBS="$OLIBS"
+ elif test "${enable_wolfssl-no}" != no; then
+ # Check for OpenSSL compatibility functions in wolfSSL.
+ # Use pkg-config to find the wolfssl cflags and libs if possible.
+ if test "$enable_wolfssl" != "yes"; then
+ PKG_CONFIG_LIBDIR="${enable_wolfssl}/lib/pkgconfig:${enable_wolfssl}/lib64/pkgconfig:${enable_wolfssl}/share/pkgconfig"
+ export PKG_CONFIG_LIBDIR
+ elif test "$cross_compiling" = "yes" -a -z "$PKG_CONFIG"; then
+ # Cannot use pkg-config when cross-compiling
+ PKG_CONFIG=false
+ fi
+ : ${PKG_CONFIG='pkg-config'}
+ if $PKG_CONFIG --exists wolfssl >/dev/null 2>&1; then
+ AC_DEFINE(HAVE_OPENSSL)
+ AC_DEFINE(HAVE_WOLFSSL)
+
+ O_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS `$PKG_CONFIG --cflags-only-I wolfssl`"
+ O_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS `$PKG_CONFIG --libs-only-L wolfssl`"
+
+ # Check whether --static is needed
+ libssl="`$PKG_CONFIG --libs-only-l wolfssl | sed 's/^ *-l//'`"
+ libssl_extra=`echo $libssl | sed 's/^[[^ ]]* *//'`
+ libssl=`echo $libssl | sed 's/ .*//'`
+ AC_CHECK_LIB([$libssl], [wolfSSL_new], [STATIC=""], [STATIC="--static"], [$libssl_extra])
+
+ # Use wolfSSL's sha2 functions if possible
+ AC_CHECK_DECL([EVP_MD_CTX_new], [DIGEST=digest_openssl.lo], [], [
+ AC_INCLUDES_DEFAULT
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/evp.h>
+ ])
+ CPPFLAGS="$O_CPPFLAGS"
+ LDFLAGS="$O_LDFLAGS"
+
+ # Use pkg-config to determine wolfSSL libs and cflags
+ for f in `$PKG_CONFIG $STATIC --libs wolfssl`; do
+ case "$f" in
+ -L*)
+ f="${f#-L}"
+ SUDO_APPEND_LIBPATH([LIBTLS], [$f])
+ ;;
+ *)
+ AX_APPEND_FLAG([$f], [LIBTLS])
+ ;;
+ esac
+ done
+ # No separate pkg config for libcrypto
+ LIBCRYPTO="$LIBTLS"
+ LIBCRYPTO_R="$LIBTLS_R"
+ for f in `$PKG_CONFIG --cflags-only-I wolfssl`; do
+ AX_APPEND_FLAG([$f], [CPPFLAGS])
+ # So we find the openssl compat headers under wolfssl
+ AX_APPEND_FLAG([$f/wolfssl], [CPPFLAGS])
+ done
+ if test "$CPPFLAGS" = "$O_CPPFLAGS"; then
+ # So we find the openssl compat headers under wolfssl (XXX)
+ AX_APPEND_FLAG([-I/usr/include/wolfssl], [CPPFLAGS])
+ fi
+ else
+ AC_DEFINE(HAVE_OPENSSL)
+ AC_DEFINE(HAVE_WOLFSSL)
+
+ # No pkg-config file present, try to do it manually
+ if test "$enable_wolfssl" != "yes"; then
+ SUDO_APPEND_LIBPATH(LIBCRYPTO, [${enable_wolfssl}/lib])
+ SUDO_APPEND_LIBPATH(LIBTLS, [${enable_wolfssl}/lib])
+ AX_APPEND_FLAG([-I${enable_wolfssl}/include], [CPPFLAGS])
+ # So we find the openssl compat headers under wolfssl
+ AX_APPEND_FLAG([-I${enable_wolfssl}/include/wolfssl], [CPPFLAGS])
+ else
+ # So we find the openssl compat headers under wolfssl (XXX)
+ AX_APPEND_FLAG([-I/usr/include/wolfssl], [CPPFLAGS])
+ fi
+ LIBTLS="${LIBTLS} -lwolfssl"
+ LIBCRYPTO="${LIBCRYPTO} -lwolfssl"
+
+ # Use wolfSSL's sha2 functions if possible
+ AC_CHECK_DECL([EVP_MD_CTX_new], [DIGEST=digest_openssl.lo], [], [
+ AC_INCLUDES_DEFAULT
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/evp.h>
+ ])
+ fi
+ dnl
+ dnl Check for specific OpenSSL API compatibility macros
+ dnl
+ AC_CHECK_DECL([X509_STORE_CTX_get0_cert], [AC_DEFINE(HAVE_X509_STORE_CTX_GET0_CERT)], [], [
+ AC_INCLUDES_DEFAULT
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/x509.h>
+ ])
+ AC_CHECK_DECL([ASN1_STRING_get0_data], [AC_DEFINE(HAVE_ASN1_STRING_GET0_DATA)], [], [
+ AC_INCLUDES_DEFAULT
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/asn1.h>
+ ])
+ AC_CHECK_DECL([SSL_CTX_get0_certificate], [AC_DEFINE(HAVE_SSL_CTX_GET0_CERTIFICATE)], [], [
+ AC_INCLUDES_DEFAULT
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/ssl.h>
+ ])
+ AC_CHECK_DECL([SSL_CTX_set0_tmp_dh_pkey], [AC_DEFINE(HAVE_SSL_CTX_SET0_TMP_DH_PKEY)], [], [
+ AC_INCLUDES_DEFAULT
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/ssl.h>
+ ])
+ AC_CHECK_DECL([TLS_method], [AC_DEFINE(HAVE_TLS_METHOD)], [], [
+ AC_INCLUDES_DEFAULT
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/ssl.h>
+ ])
+ AC_CHECK_DECL([SSL_CTX_set_min_proto_version], [AC_DEFINE(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION)], [], [
+ AC_INCLUDES_DEFAULT
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/ssl.h>
+ ])
+ AC_CHECK_DECL([SSL_CTX_set_ciphersuites], [AC_DEFINE(HAVE_SSL_CTX_SET_CIPHERSUITES)], [], [
+ AC_INCLUDES_DEFAULT
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/ssl.h>
+ ])
+ AC_CHECK_DECL([SSL_read_ex], [AC_DEFINE(HAVE_SSL_READ_EX)], [
+ SSL_COMPAT_SRC=lib/ssl_compat
+ ], [
+ AC_INCLUDES_DEFAULT
+ #include <wolfssl/options.h>
+ #include <wolfssl/openssl/ssl.h>
+ ])
+ fi
+ if test -n "$SSL_COMPAT_SRC"; then
+ LIBTLS='$(top_builddir)/lib/ssl_compat/libssl_compat.la '"${LIBTLS}"
+ fi
+])
diff --git a/m4/pie.m4 b/m4/pie.m4
new file mode 100644
index 0000000..f2eb470
--- /dev/null
+++ b/m4/pie.m4
@@ -0,0 +1,86 @@
+AC_DEFUN([SUDO_CHECK_PIE_SUPPORT], [
+ dnl
+ dnl Check for PIE executable support if using gcc.
+ dnl This test relies on AC_LANG_WERROR
+ dnl
+ if test -n "$GCC"; then
+ if test X"$enable_pie" = X""; then
+ case "$host_os" in
+ linux*)
+ # Attempt to build with PIE support
+ enable_pie="maybe"
+ ;;
+ esac
+ fi
+ if test X"$enable_pie" != X""; then
+ if test "$enable_pie" = "no"; then
+ AX_CHECK_COMPILE_FLAG([-fno-pie], [
+ _CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fno-pie"
+ AX_CHECK_LINK_FLAG([-nopie], [
+ PIE_CFLAGS="-fno-pie"
+ PIE_LDFLAGS="-nopie"
+ ])
+ CFLAGS="$_CFLAGS"
+ ])
+ else
+ AX_CHECK_COMPILE_FLAG([-fPIE], [
+ _CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fPIE"
+ _LDFLAGS="$LDFLAGS"
+ AX_CHECK_LINK_FLAG([-pie], [
+ if test "$enable_pie" = "maybe"; then
+ LDFLAGS="$LDFLAGS -pie"
+ SUDO_WORKING_PIE([enable_pie=yes], [])
+ fi
+ if test "$enable_pie" = "yes"; then
+ PIE_CFLAGS="-fPIE"
+ PIE_LDFLAGS="-Wc,-fPIE -pie"
+ fi
+ ])
+ CFLAGS="$_CFLAGS"
+ LDFLAGS="$_LDFLAGS"
+ ])
+ fi
+ fi
+ fi
+ if test X"$enable_pie" != X"no" -a X"$with_gnu_ld" = X"no"; then
+ # Solaris 11.1 and higher ld supports PIE executables, ASLR,
+ # non-executable stack and non-executable heap.
+ case "$host_os" in
+ solaris2.1[[1-9]]|solaris2.[[2-9]][[0-9]])
+ # This assumes lt_prog_compiler_pic is a single flag,
+ # which is the case on Solaris.
+ if test -n "$lt_prog_compiler_pic"; then
+ _CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $lt_prog_compiler_pic"
+ _LDFLAGS="$LDFLAGS"
+ AX_CHECK_LINK_FLAG([-Wl,-ztype=pie], [
+ # Try building PIE if not disabled.
+ if test X"$enable_pie" = X""; then
+ LDFLAGS="$LDFLAGS -Wl,-ztype=pie"
+ SUDO_WORKING_PIE([enable_pie=yes], [])
+ fi
+ if test "$enable_pie" = "yes"; then
+ PIE_CFLAGS="$lt_prog_compiler_pic"
+ PIE_LDFLAGS="-Wc,$lt_prog_compiler_pic -Wl,-ztype=pie"
+ fi
+ ])
+ CFLAGS="$_CFLAGS"
+ LDFLAGS="$_LDFLAGS"
+ fi
+ # These flags are only valid when linking an executable
+ # so we cannot add them to HARDENING_LDFLAGS.
+ AX_CHECK_LINK_FLAG([-Wl,-zaslr], [
+ AX_APPEND_FLAG([-Wl,-zaslr], [PIE_LDFLAGS])
+ ])
+ AX_CHECK_LINK_FLAG([-Wl,-znxheap], [
+ AX_APPEND_FLAG([-Wl,-znxheap], [PIE_LDFLAGS])
+ ])
+ AX_CHECK_LINK_FLAG([-Wl,-znxstack], [
+ AX_APPEND_FLAG([-Wl,-znxstack], [PIE_LDFLAGS])
+ ])
+ ;;
+ esac
+ fi
+])
diff --git a/m4/python.m4 b/m4/python.m4
new file mode 100644
index 0000000..b2302ba
--- /dev/null
+++ b/m4/python.m4
@@ -0,0 +1,244 @@
+## ------------------------ -*- Autoconf -*-
+## Python file handling
+## From Andrew Dalke
+## Updated by James Henstridge and other contributors.
+## ------------------------
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# ---------------------------------------------------------------------------
+# Adds support for distributing Python modules and packages. To
+# install modules, copy them to $(pythondir), using the python_PYTHON
+# automake variable. To install a package with the same name as the
+# automake package, install to $(pkgpythondir), or use the
+# pkgpython_PYTHON automake variable.
+#
+# The variables $(pyexecdir) and $(pkgpyexecdir) are provided as
+# locations to install python extension modules (shared libraries).
+# Another macro is required to find the appropriate flags to compile
+# extension modules.
+#
+# If your package is configured with a different prefix to python,
+# users will have to add the install directory to the PYTHONPATH
+# environment variable, or create a .pth file (see the python
+# documentation for details).
+#
+# If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will
+# cause an error if the version of python installed on the system
+# doesn't meet the requirement. MINIMUM-VERSION should consist of
+# numbers and dots only.
+AC_DEFUN([AM_PATH_PYTHON],
+ [
+ dnl Find a Python interpreter. Python versions prior to 2.0 are not
+ dnl supported. (2.0 was released on October 16, 2000).
+ m4_define_default([_AM_PYTHON_INTERPRETER_LIST],
+[python python2 python3 dnl
+ python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 dnl
+ python3.2 python3.1 python3.0 dnl
+ python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 dnl
+ python2.0])
+
+ AC_ARG_VAR([PYTHON], [the Python interpreter])
+
+ m4_if([$1],[],[
+ dnl No version check is needed.
+ # Find any Python interpreter.
+ if test -z "$PYTHON"; then
+ AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :)
+ fi
+ am_display_PYTHON=python
+ ], [
+ dnl A version check is needed.
+ if test -n "$PYTHON"; then
+ # If the user set $PYTHON, use it and don't search something else.
+ AC_MSG_CHECKING([whether $PYTHON version is >= $1])
+ AM_PYTHON_CHECK_VERSION([$PYTHON], [$1],
+ [AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])
+ AC_MSG_ERROR([Python interpreter is too old])])
+ am_display_PYTHON=$PYTHON
+ else
+ # Otherwise, try each interpreter until we find one that satisfies
+ # VERSION.
+ AC_CACHE_CHECK([for a Python interpreter with version >= $1],
+ [am_cv_pathless_PYTHON],[
+ for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do
+ test "$am_cv_pathless_PYTHON" = none && break
+ AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break])
+ done])
+ # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON.
+ if test "$am_cv_pathless_PYTHON" = none; then
+ PYTHON=:
+ else
+ AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON])
+ fi
+ am_display_PYTHON=$am_cv_pathless_PYTHON
+ fi
+ ])
+
+ if test "$PYTHON" = :; then
+ dnl Run any user-specified action, or abort.
+ m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])])
+ else
+
+ dnl Query Python for its version number. Although site.py simply uses
+ dnl sys.version[:3], printing that failed with Python 3.10, since the
+ dnl trailing zero was eliminated. So now we output just the major
+ dnl and minor version numbers, as numbers. Apparently the tertiary
+ dnl version is not of interest.
+
+ AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version],
+ [am_cv_python_version=`$PYTHON -c "import sys; print('%u.%u' % sys.version_info[[:2]])"`])
+ AC_SUBST([PYTHON_VERSION], [$am_cv_python_version])
+
+ dnl Use the values of $prefix and $exec_prefix for the corresponding
+ dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made
+ dnl distinct variables so they can be overridden if need be. However,
+ dnl general consensus is that you shouldn't need this ability.
+
+ AC_SUBST([PYTHON_PREFIX], ['${prefix}'])
+ AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}'])
+
+ dnl At times (like when building shared libraries) you may want
+ dnl to know which OS platform Python thinks this is.
+
+ AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform],
+ [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`])
+ AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform])
+
+ # Just factor out some code duplication.
+ am_python_setup_sysconfig="\
+import sys
+# Prefer sysconfig over distutils.sysconfig, for better compatibility
+# with python 3.x. See automake bug#10227.
+try:
+ import sysconfig
+except ImportError:
+ can_use_sysconfig = 0
+else:
+ can_use_sysconfig = 1
+# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs:
+# <https://github.com/pypa/virtualenv/issues/118>
+try:
+ from platform import python_implementation
+ if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7':
+ can_use_sysconfig = 0
+except ImportError:
+ pass"
+
+ dnl Set up 4 directories:
+
+ dnl pythondir -- where to install python scripts. This is the
+ dnl site-packages directory, not the python standard library
+ dnl directory like in previous automake betas. This behavior
+ dnl is more consistent with lispdir.m4 for example.
+ dnl Query distutils for this directory.
+ AC_CACHE_CHECK([for $am_display_PYTHON script directory],
+ [am_cv_python_pythondir],
+ [if test "x$prefix" = xNONE
+ then
+ am_py_prefix=$ac_default_prefix
+ else
+ am_py_prefix=$prefix
+ fi
+ am_cv_python_pythondir=`$PYTHON -c "
+$am_python_setup_sysconfig
+if can_use_sysconfig:
+ sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
+else:
+ from distutils import sysconfig
+ sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
+sys.stdout.write(sitedir)"`
+ case $am_cv_python_pythondir in
+ $am_py_prefix*)
+ am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'`
+ am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"`
+ ;;
+ *)
+ case $am_py_prefix in
+ /usr|/System*) ;;
+ *)
+ am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages
+ ;;
+ esac
+ ;;
+ esac
+ ])
+ AC_SUBST([pythondir], [$am_cv_python_pythondir])
+
+ dnl pkgpythondir -- $PACKAGE directory under pythondir. Was
+ dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is
+ dnl more consistent with the rest of automake.
+
+ AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE])
+
+ dnl pyexecdir -- directory for installing python extension modules
+ dnl (shared libraries)
+ dnl Query distutils for this directory.
+ AC_CACHE_CHECK([for $am_display_PYTHON extension module directory],
+ [am_cv_python_pyexecdir],
+ [if test "x$exec_prefix" = xNONE
+ then
+ am_py_exec_prefix=$am_py_prefix
+ else
+ am_py_exec_prefix=$exec_prefix
+ fi
+ am_cv_python_pyexecdir=`$PYTHON -c "
+$am_python_setup_sysconfig
+if can_use_sysconfig:
+ sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'})
+else:
+ from distutils import sysconfig
+ sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix')
+sys.stdout.write(sitedir)"`
+ case $am_cv_python_pyexecdir in
+ $am_py_exec_prefix*)
+ am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'`
+ am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"`
+ ;;
+ *)
+ case $am_py_exec_prefix in
+ /usr|/System*) ;;
+ *)
+ am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages
+ ;;
+ esac
+ ;;
+ esac
+ ])
+ AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir])
+
+ dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE)
+
+ AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE])
+
+ dnl Run any user-specified action.
+ $2
+ fi
+
+])
+
+
+# AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
+# ---------------------------------------------------------------------------
+# Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION.
+# Run ACTION-IF-FALSE otherwise.
+# This test uses sys.hexversion instead of the string equivalent (first
+# word of sys.version), in order to cope with versions such as 2.2c1.
+# This supports Python 2.0 or higher. (2.0 was released on October 16, 2000).
+AC_DEFUN([AM_PYTHON_CHECK_VERSION],
+ [prog="import sys
+# split strings by '.' and convert to numeric. Append some zeros
+# because we need at least 4 digits for the hex conversion.
+# map returns an iterator in Python 3.0 and a list in 2.x
+minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]]
+minverhex = 0
+# xrange is not present in Python 3.0 and range returns an iterator
+for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]]
+sys.exit(sys.hexversion < minverhex)"
+ AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])])
diff --git a/m4/runlog.m4 b/m4/runlog.m4
new file mode 100644
index 0000000..42408cc
--- /dev/null
+++ b/m4/runlog.m4
@@ -0,0 +1,17 @@
+## -*- Autoconf -*-
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_RUN_LOG(COMMAND)
+# -------------------
+# Run COMMAND, save the exit status in ac_status, and log it.
+# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
+AC_DEFUN([AM_RUN_LOG],
+[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
+ ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ (exit $ac_status); }])
diff --git a/m4/sanitizer.m4 b/m4/sanitizer.m4
new file mode 100644
index 0000000..57917a7
--- /dev/null
+++ b/m4/sanitizer.m4
@@ -0,0 +1,63 @@
+AC_DEFUN([SUDO_CHECK_SANITIZER], [
+ if test X"${enable_sanitizer}{enable_fuzzer}" != X"nono"; then
+ dnl
+ dnl For fuzz_policy we redefine getaddrinfo() and freeaddrinfo(), but
+ dnl this can cause problems with ld.lld when sanitizers are enabled.
+ dnl
+ AX_CHECK_LINK_FLAG([-Wl,--allow-multiple-definition], [AX_APPEND_FLAG([-Wl,--allow-multiple-definition], [ASAN_LDFLAGS])])
+ fi
+
+ dnl
+ dnl Check for -fsanitize support
+ dnl This test relies on AC_LANG_WERROR
+ dnl
+ if test X"$enable_sanitizer" != X"no"; then
+ AX_CHECK_COMPILE_FLAG([$enable_sanitizer], [
+ AX_APPEND_FLAG([$enable_sanitizer], [ASAN_CFLAGS])
+ AX_APPEND_FLAG([-XCClinker], [ASAN_LDFLAGS])
+ AX_APPEND_FLAG([$enable_sanitizer], [ASAN_LDFLAGS])
+ AX_CHECK_COMPILE_FLAG([-fno-omit-frame-pointer], [
+ AX_APPEND_FLAG([-fno-omit-frame-pointer], [CFLAGS])
+ ])
+ AC_DEFINE(NO_LEAKS)
+ dnl
+ dnl Check for libasan.so to preload it before sudo_intercept.so.
+ dnl gcc links asan dynamically, clang links it statically.
+ dnl
+ case `$CC --version 2>&1` in
+ *gcc*)
+ libasan=`$CC -print-file-name=libasan.so 2>/dev/null`
+ if test -n "$libasan" -a X"$libasan" != X"libasan.so"; then
+ # libasan.so may be a linker script
+ libasan="`awk 'BEGIN {lib=ARGV[[1]]} /^INPUT/ {lib=$[3]} END {print lib}' \"$libasan\"`"
+ SUDO_DEFINE_UNQUOTED(_PATH_ASAN_LIB, "$libasan", [Path to the libasan.so shared library])
+ fi
+ ;;
+ esac
+ ], [
+ AC_MSG_ERROR([$CC does not support the $enable_sanitizer flag])
+ ])
+ fi
+
+ if test X"$enable_fuzzer" = X"yes"; then
+ AX_CHECK_COMPILE_FLAG([-fsanitize=fuzzer-no-link], [
+ AX_APPEND_FLAG([-fsanitize=fuzzer-no-link], [ASAN_CFLAGS])
+ AX_APPEND_FLAG([-XCClinker], [ASAN_LDFLAGS])
+ AX_APPEND_FLAG([-fsanitize=fuzzer-no-link], [ASAN_LDFLAGS])
+ if test -z "$FUZZ_ENGINE"; then
+ FUZZ_ENGINE="-fsanitize=fuzzer"
+ fi
+ AX_CHECK_COMPILE_FLAG([-fno-omit-frame-pointer], [
+ AX_APPEND_FLAG([-fno-omit-frame-pointer], [CFLAGS])
+ ])
+ # Use CFLAGS, not CPPFLAGS to match oss-fuzz behavior
+ AX_APPEND_FLAG([-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION], [CFLAGS])
+ AC_DEFINE(NO_LEAKS)
+ ], [
+ AC_MSG_ERROR([$CC does not support the -fsanitize=fuzzer-no-link flag])
+ ])
+ else
+ # Not using compiler fuzzing support, link with stub library.
+ FUZZ_ENGINE='$(top_builddir)/lib/fuzzstub/libsudo_fuzzstub.la'
+ fi
+])
diff --git a/m4/sudo.m4 b/m4/sudo.m4
new file mode 100644
index 0000000..08eba76
--- /dev/null
+++ b/m4/sudo.m4
@@ -0,0 +1,713 @@
+dnl Local m4 macros for autoconf (used by sudo)
+dnl
+dnl SPDX-License-Identifier: ISC
+dnl
+dnl Copyright (c) 1994-1996, 1998-2005, 2007-2023
+dnl Todd C. Miller <Todd.Miller@sudo.ws>
+dnl
+dnl Permission to use, copy, modify, and distribute this software for any
+dnl purpose with or without fee is hereby granted, provided that the above
+dnl copyright notice and this permission notice appear in all copies.
+dnl
+dnl THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+dnl WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+dnl MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+dnl ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+dnl WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+dnl ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+dnl OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+dnl
+
+dnl
+dnl check for sendmail in well-known locations
+dnl
+AC_ARG_VAR([SENDMAILPROG], [The fully-qualified path to the sendmail program to use.])
+AC_DEFUN([SUDO_PROG_SENDMAIL], [
+ AC_PATH_PROG([SENDMAILPROG], [sendmail], [], [/usr/sbin$PATH_SEPARATOR/usr/lib$PATH_SEPARATOR/usr/etc$PATH_SEPARATOR/usr/ucblib$PATH_SEPARATOR/usr/local/lib$PATH_SEPARATOR/usr/local/bin])
+ test -n "${ac_cv_path_SENDMAILPROG}" && SUDO_DEFINE_UNQUOTED(_PATH_SUDO_SENDMAIL, "${ac_cv_path_SENDMAILPROG}")
+])dnl
+
+dnl
+dnl check for vi in well-known locations
+dnl
+AC_ARG_VAR([VIPROG], [The fully-qualified path to the vi program to use.])
+AC_DEFUN([SUDO_PROG_VI], [
+ AC_PATH_PROG([VIPROG], [vi], [], [/usr/bin$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/ucb$PATH_SEPARATOR/usr/bsd$PATH_SEPARATOR/usr/local/bin])
+ test -n "${ac_cv_path_VIPROG}" && SUDO_DEFINE_UNQUOTED(_PATH_VI, "${ac_cv_path_VIPROG}")
+])dnl
+
+dnl
+dnl check for mv in well-known locations
+dnl
+AC_ARG_VAR([MVPROG], [The fully-qualified path to the mv program to use.])
+AC_DEFUN([SUDO_PROG_MV], [
+ AC_PATH_PROG([MVPROG], [mv], [], [/usr/bin$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/ucb$PATH_SEPARATOR/usr/local/bin])
+ test -n "${ac_cv_path_MVPROG}" && SUDO_DEFINE_UNQUOTED(_PATH_MV, "${ac_cv_path_MVPROG}")
+])dnl
+
+dnl
+dnl check for bourne shell in well-known locations
+dnl
+AC_ARG_VAR([BSHELLPROG], [The fully-qualified path to the Bourne shell to use.])
+AC_DEFUN([SUDO_PROG_BSHELL], [
+ AC_PATH_PROG([BSHELLPROG], [sh], [/usr/bin$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/sbin])
+ test -n "${ac_cv_path_BSHELLPROG}" && SUDO_DEFINE_UNQUOTED(_PATH_BSHELL, "${ac_cv_path_BSHELLPROG}")
+])dnl
+
+dnl
+dnl Check for path to utmp file if not using getutid(), etc.
+dnl
+AC_DEFUN([SUDO_PATH_UTMP], [
+ AC_CACHE_CHECK([for utmp file path], [sudo_cv_path_UTMP], [
+ sudo_cv_path_UTMP=no
+ for p in "/var/run/utmp" "/var/adm/utmp" "/etc/utmp"; do
+ if test -r "$p"; then
+ sudo_cv_path_UTMP="$p"
+ break
+ fi
+ done
+ ])
+ if test X"$sudo_cv_path_UTMP" != X"no"; then
+ SUDO_DEFINE_UNQUOTED(_PATH_UTMP, "$sudo_cv_path_UTMP")
+ fi
+])
+
+dnl
+dnl Where the log file goes, use /var/log if it exists, else /{var,usr}/adm
+dnl
+AC_DEFUN([SUDO_LOGFILE], [
+ if test -n "$with_logpath"; then
+ logpath="$with_logpath"
+ else
+ AC_CACHE_CHECK([for log file location], [sudo_cv_log_path], [
+ # Default value of logpath set in configure.ac
+ sudo_cv_log_path="$logpath"
+ for d in /var/log /var/adm /usr/adm; do
+ if test -d "$d"; then
+ sudo_cv_log_path="$d/sudo.log"
+ break
+ fi
+ done
+ ])
+ logpath="$sudo_cv_log_path"
+ fi
+ SUDO_DEFINE_UNQUOTED(_PATH_SUDO_LOGFILE, "$logpath")
+])
+
+dnl
+dnl Detect time zone file directory, if any.
+dnl
+AC_DEFUN([SUDO_TZDIR], [
+ if test -n "$with_tzdir"; then
+ tzdir="$with_tzdir"
+ else
+ AC_CACHE_CHECK([time zone data directory], [sudo_cv_tz_dir], [
+ sudo_cv_tz_dir=no
+ for d in /usr/share /usr/share/lib /usr/lib /etc; do
+ if test -d "$d/zoneinfo"; then
+ sudo_cv_tz_dir="$d/zoneinfo"
+ break
+ fi
+ done
+ ])
+ tzdir="$sudo_cv_tz_dir"
+ fi
+ if test X"$tzdir" != X"no"; then
+ SUDO_DEFINE_UNQUOTED(_PATH_ZONEINFO, "$tzdir")
+ fi
+])
+
+dnl
+dnl Parent directory for time stamp dir.
+dnl
+AC_DEFUN([SUDO_RUNDIR], [
+ if test -n "$with_rundir"; then
+ rundir="$with_rundir"
+ elif test -n "$runstatedir" && test "$runstatedir" != '${localstatedir}/run'; then
+ rundir="$runstatedir/sudo"
+ else
+ # No --with-rundir or --runstatedir specified
+ AC_CACHE_CHECK([for sudo run dir location], [sudo_cv_run_dir], [
+ sudo_cv_run_dir=no
+ for d in /run /var/run /var/db /var/lib /var/adm /usr/adm; do
+ if test -d "$d"; then
+ sudo_cv_run_dir="$d/sudo"
+ break
+ fi
+ done
+ ])
+ rundir="$sudo_cv_run_dir"
+ fi
+ if test X"$rundir" != X"no"; then
+ SUDO_DEFINE_UNQUOTED(_PATH_SUDO_TIMEDIR, "$rundir/ts")
+ SUDO_DEFINE_UNQUOTED(_PATH_SUDO_LOGSRVD_PID, "$rundir/sudo_logsrvd.pid")
+ fi
+])
+
+dnl
+dnl Parent directory for the lecture status dir.
+dnl
+AC_DEFUN([SUDO_VARDIR], [
+ if test -n "$with_vardir"; then
+ vardir="$with_vardir"
+ else
+ AC_CACHE_CHECK([for sudo var dir location], [sudo_cv_var_dir], [
+ sudo_cv_var_dir=no
+ for d in /var/db /var/lib /var/adm /usr/adm; do
+ if test -d "$d"; then
+ sudo_cv_var_dir="$d/sudo"
+ break
+ fi
+ done
+ ])
+ vardir="$sudo_cv_var_dir"
+ fi
+ if test X"$vardir" != X"no"; then
+ SUDO_DEFINE_UNQUOTED(_PATH_SUDO_LECTURE_DIR, "$vardir/lectured")
+ fi
+])
+
+dnl
+dnl Where the sudo_logsrvd relay temporary log files go, use
+dnl /var/log/sudo_logsrvd if /var/log exists, else
+dnl /{var,usr}/adm/sudo_logsrvd
+dnl
+AC_DEFUN([SUDO_RELAY_DIR], [
+ if test "${with_relaydir-yes}" != "yes"; then
+ relay_dir="$with_relaydir"
+ else
+ AC_CACHE_CHECK([for sudo_logsrvd relay dir location], [sudo_cv_relay_dir], [
+ # Default value of relay_dir set in configure.ac
+ sudo_cv_relay_dir="$relay_dir"
+ for d in /var/log /var/adm /usr/adm; do
+ if test -d "$d"; then
+ sudo_cv_relay_dir="$d/sudo_logsrvd"
+ break
+ fi
+ done
+ ])
+ relay_dir="$sudo_cv_relay_dir"
+ fi
+ SUDO_DEFINE_UNQUOTED(_PATH_SUDO_RELAY_DIR, "$relay_dir")
+])
+
+dnl
+dnl Where the I/O log files go, use /var/log/sudo-io if
+dnl /var/log exists, else /{var,usr}/adm/sudo-io
+dnl
+AC_DEFUN([SUDO_IO_LOGDIR], [
+ if test "${with_iologdir-yes}" != "yes"; then
+ iolog_dir="$with_iologdir"
+ else
+ AC_CACHE_CHECK([for I/O log dir location], [sudo_cv_iolog_dir], [
+ # Default value of iolog_dir set in configure.ac
+ sudo_cv_iolog_dir="$iolog_dir"
+ for d in /var/log /var/adm /usr/adm; do
+ if test -d "$d"; then
+ sudo_cv_iolog_dir="$d/sudo-io"
+ break
+ fi
+ done
+ ])
+ iolog_dir="$sudo_cv_iolog_dir"
+ fi
+ SUDO_DEFINE_UNQUOTED(_PATH_SUDO_IO_LOGDIR, "$iolog_dir")
+])
+
+dnl
+dnl Where the log files go, use /var/log if it exists, else /{var,usr}/adm
+dnl
+AC_DEFUN([SUDO_LOGDIR], [
+ if test "${with_logdir-yes}" != "yes"; then
+ log_dir="$with_logdir"
+ else
+ AC_CACHE_CHECK([for log dir location], [sudo_cv_log_dir], [
+ # Default value of log_dir set in configure.ac
+ sudo_cv_log_dir="$log_dir"
+ for d in /var/log /var/adm /usr/adm; do
+ if test -d "$d"; then
+ sudo_cv_log_dir="$d"
+ break
+ fi
+ done
+ ])
+ log_dir="$sudo_cv_log_dir"
+ fi
+ SUDO_DEFINE_UNQUOTED(_PATH_SUDO_LOGDIR, "$log_dir")
+])
+
+dnl
+dnl check for working fnmatch(3)
+dnl
+AC_DEFUN([SUDO_FUNC_FNMATCH], [
+ AC_CACHE_CHECK([for working fnmatch with FNM_CASEFOLD],
+ sudo_cv_func_fnmatch, [
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <fnmatch.h>
+int main() { return(fnmatch("/*/bin/echo *", "/usr/bin/echo just a test", FNM_CASEFOLD)); }]])], [sudo_cv_func_fnmatch=yes], [sudo_cv_func_fnmatch=no], [sudo_cv_func_fnmatch=no])
+ ])
+ AS_IF([test $sudo_cv_func_fnmatch = yes], [$1], [$2])
+])
+
+dnl
+dnl Attempt to check for working PIE support.
+dnl This is a bit of a hack but on Solaris 10 with GNU ld and GNU as
+dnl we can end up with strange values from malloc().
+dnl A better check would be to verify that ASLR works with PIE.
+dnl
+AC_DEFUN([SUDO_WORKING_PIE], [
+ AC_CACHE_CHECK([for working PIE support], sudo_cv_working_pie, [
+ AC_RUN_IFELSE([AC_LANG_SOURCE([AC_INCLUDES_DEFAULT
+int main() { char *p = malloc(1024); if (p == NULL) return 1; memset(p, 0, 1024); return 0; }])], [sudo_cv_working_pie=yes], [sudo_cv_working_pie=no], [sudo_cv_working_pie=no])
+ ])
+ AS_IF([test $sudo_cv_working_pie = yes], [$1], [$2])
+])
+
+dnl
+dnl check for isblank(3)
+dnl
+AC_DEFUN([SUDO_FUNC_ISBLANK],
+ [AC_CACHE_CHECK([for isblank], [sudo_cv_func_isblank],
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <ctype.h>]], [[return (isblank('a'));]])],
+ [sudo_cv_func_isblank=yes], [sudo_cv_func_isblank=no])])
+] [
+ if test "$sudo_cv_func_isblank" = "yes"; then
+ AC_DEFINE(HAVE_ISBLANK, 1, [Define if you have isblank(3).])
+ else
+ AC_LIBOBJ(isblank)
+ SUDO_APPEND_COMPAT_EXP(isblank)
+ fi
+])
+
+AC_DEFUN([SUDO_CHECK_LIB], [
+ _sudo_check_lib_extras=`echo "$5"|sed -e 's/[ ]*//g' -e 's/-l/_/g'`
+ AC_MSG_CHECKING([for $2 in -l$1${5+ }$5])
+ AC_CACHE_VAL([sudo_cv_lib_$1''_$2$_sudo_check_lib_extras], [
+ SUDO_CHECK_LIB_OLIBS="$LIBS"
+ LIBS="$LIBS -l$1${5+ }$5"
+ AC_LINK_IFELSE(
+ [AC_LANG_CALL([], [$2])],
+ [eval sudo_cv_lib_$1''_$2$_sudo_check_lib_extras=yes],
+ [eval sudo_cv_lib_$1''_$2$_sudo_check_lib_extras=no]
+ )
+ LIBS="$SUDO_CHECK_LIB_OLIBS"
+ ])
+ if eval test \$sudo_cv_lib_$1''_$2$_sudo_check_lib_extras = "yes"; then
+ AC_MSG_RESULT([yes])
+ $3
+ else
+ AC_MSG_RESULT([no])
+ $4
+ fi
+])
+
+AC_DEFUN([SUDO_CHECK_NET_FUNC], [
+ _LIBS="$LIBS"
+ LIBS="${LIBS} ${NET_LIBS}"
+ found=true
+ AC_CHECK_FUNC([$1], [$2], [
+ # Look for $1 in network libraries appending to NET_LIBS as needed.
+ # May need to link with -lnsl and -lsocket due to unresolved symbols
+ found=false
+ for libs in "-lsocket" "-linet" "-lsocket -lnsl" "-lresolv"; do
+ _libs=
+ for lib in $libs; do
+ case "$NET_LIBS" in
+ *"$lib"*) ;;
+ *) _libs="$_libs $lib";;
+ esac
+ done
+ libs="${_libs# }"
+ test -z "$libs" && continue
+ lib="`echo \"$libs\"|sed -e 's/^-l//' -e 's/ .*$//'`"
+ extralibs="`echo \"$libs\"|sed 's/^-l[[^ ]]*//'`"
+ SUDO_CHECK_LIB($lib, $1, [
+ found=true
+ NET_LIBS="${NET_LIBS}${NET_LIBS+ }$libs"
+ INET_PTON_LIBS="$libs"
+ case "$libs" in
+ *-lresolv*)
+ AC_DEFINE(NEED_RESOLV_H)
+ ;;
+ esac
+ break
+ ], [], [$extralibs])
+ done
+ ])
+ LIBS="$_LIBS"
+ AS_IF([test $found = true], [$2], [$3])
+])
+
+dnl
+dnl check unsetenv() return value
+dnl
+AC_DEFUN([SUDO_FUNC_UNSETENV_VOID],
+ [AC_CACHE_CHECK([whether unsetenv returns void], [sudo_cv_func_unsetenv_void],
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT], [
+ [return unsetenv("FOO");]
+ ])
+ ],
+ [sudo_cv_func_unsetenv_void=no],
+ [sudo_cv_func_unsetenv_void=yes])])
+ if test $sudo_cv_func_unsetenv_void = yes; then
+ AC_DEFINE(UNSETENV_VOID, 1,
+ [Define to 1 if the 'unsetenv' function returns void instead of 'int'.])
+ fi
+ ])
+
+dnl
+dnl check putenv() argument for const
+dnl
+AC_DEFUN([SUDO_FUNC_PUTENV_CONST],
+ [AC_CACHE_CHECK([whether putenv takes a const argument], [sudo_cv_func_putenv_const],
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
+ int putenv(const char *string) {return 0;}
+ ], [])],
+ [sudo_cv_func_putenv_const=yes],
+ [sudo_cv_func_putenv_const=no])
+ ])
+ if test $sudo_cv_func_putenv_const = yes; then
+ AC_DEFINE(PUTENV_CONST, const, [Define to const if the 'putenv' function takes a const argument.])
+ else
+ AC_DEFINE(PUTENV_CONST, [])
+ fi
+])
+
+dnl
+dnl check if ioctl() request argument is int.
+dnl
+AC_DEFUN([SUDO_FUNC_IOCTL_REQ_INT],
+ [AC_CACHE_CHECK([whether ioctl() takes an int request argument], [sudo_cv_func_ioctl_req_int],
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+ int ioctl(int fd, int req, ...) {return 0;}
+ ], [])],
+ [sudo_cv_func_ioctl_req_int=yes],
+ [sudo_cv_func_ioctl_req_int=no])
+ ])
+ if test $sudo_cv_func_ioctl_req_int = yes; then
+ AC_DEFINE(IOCTL_REQ_CAST, [(int)], [Define to (int) if the 'ioctl' function request takes an int request argument.])
+ else
+ AC_DEFINE(IOCTL_REQ_CAST, [])
+ fi
+])
+
+dnl
+dnl check whether au_close() takes 3 or 4 arguments
+dnl
+AC_DEFUN([SUDO_FUNC_AU_CLOSE_SOLARIS11],
+[AC_CACHE_CHECK([whether au_close() takes 4 arguments],
+sudo_cv_func_au_close_solaris11,
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
+#include <bsm/audit.h>
+#include <bsm/libbsm.h>
+#include <bsm/audit_uevents.h>
+
+int au_close(int d, int keep, au_event_t event, au_emod_t emod) {return 0;}], [])],
+ [sudo_cv_func_au_close_solaris11=yes],
+ [sudo_cv_func_au_close_solaris11=no])
+ ])
+ if test $sudo_cv_func_au_close_solaris11 = yes; then
+ AC_DEFINE(HAVE_AU_CLOSE_SOLARIS11, 1, [Define to 1 if the 'au_close' functions takes 4 arguments like Solaris 11.])
+ fi
+])
+
+dnl
+dnl Check if the data argument for the sha2 functions is void * or u_char *
+dnl
+AC_DEFUN([SUDO_FUNC_SHA2_VOID_PTR],
+[AC_CACHE_CHECK([whether the data argument of SHA224Update() is void *],
+sudo_cv_func_sha2_void_ptr,
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
+#include <sha2.h>
+void SHA224Update(SHA2_CTX *context, const void *data, size_t len) {return;}], [])],
+ [sudo_cv_func_sha2_void_ptr=yes],
+ [sudo_cv_func_sha2_void_ptr=no])
+ ])
+ if test $sudo_cv_func_sha2_void_ptr = yes; then
+ AC_DEFINE(SHA2_VOID_PTR, 1,
+ [Define to 1 if the sha2 functions use 'const void *' instead of 'const unsigned char'.])
+ fi
+])
+
+dnl
+dnl check for sa_len field in struct sockaddr
+dnl
+AC_DEFUN([SUDO_SOCK_SA_LEN], [
+ AC_CHECK_MEMBER([struct sockaddr.sa_len],
+ [AC_DEFINE(HAVE_STRUCT_SOCKADDR_SA_LEN, 1, [Define if your struct sockaddr has an sa_len field.])],
+ [], [
+# include <sys/types.h>
+# include <sys/socket.h>]
+ )]
+)
+
+dnl
+dnl check for sin_len field in struct sockaddr_in
+dnl
+AC_DEFUN([SUDO_SOCK_SIN_LEN], [
+ AC_CHECK_MEMBER([struct sockaddr_in.sin_len],
+ [AC_DEFINE(HAVE_STRUCT_SOCKADDR_IN_SIN_LEN, 1, [Define if your struct sockaddr_in has a sin_len field.])],
+ [], [
+# include <sys/types.h>
+# include <sys/socket.h>]
+ )]
+)
+
+dnl
+dnl There are three different utmp variants we need to check for.
+dnl SUDO_CHECK_UTMP_MEMBERS(utmp_type)
+dnl
+AC_DEFUN([SUDO_CHECK_UTMP_MEMBERS], [
+ dnl
+ dnl Check for utmp/utmpx/utmps struct members.
+ dnl
+ AC_CHECK_MEMBER([struct $1.ut_id], [
+ AC_DEFINE(HAVE_STRUCT_UTMP_UT_ID, 1, [Define to 1 if 'ut_id' is a member of 'struct utmp'.])
+ ], [], [
+# include <sys/types.h>
+# include <$1.h>
+ ])
+ AC_CHECK_MEMBER([struct $1.ut_pid], [
+ AC_DEFINE(HAVE_STRUCT_UTMP_UT_PID, 1, [Define to 1 if 'ut_pid' is a member of 'struct utmp'.])
+ ], [], [
+# include <sys/types.h>
+# include <$1.h>
+ ])
+ AC_CHECK_MEMBER([struct $1.ut_tv], [
+ AC_DEFINE(HAVE_STRUCT_UTMP_UT_TV, 1, [Define to 1 if 'ut_tv' is a member of 'struct utmp'.])
+ ], [], [
+# include <sys/types.h>
+# include <$1.h>
+ ])
+ AC_CHECK_MEMBER([struct $1.ut_type], [
+ AC_DEFINE(HAVE_STRUCT_UTMP_UT_TYPE, 1, [Define to 1 if 'ut_type' is a member of 'struct utmp'.])
+ ], [], [
+# include <sys/types.h>
+# include <$1.h>
+ ])
+ dnl
+ dnl Older struct utmp has ut_name instead of ut_user
+ dnl
+ if test "$1" = "utmp"; then
+ AC_CHECK_MEMBERS([struct utmp.ut_user], [], [], [
+# include <sys/types.h>
+# include <$1.h>
+ ])
+ fi
+ dnl
+ dnl Check for ut_exit.__e_termination first, then ut_exit.e_termination
+ dnl We need to have already defined _GNU_SOURCE on glibc which only has
+ dnl __e_termination visible when _GNU_SOURCE is *not* defined.
+ dnl
+ AC_CHECK_MEMBER([struct $1.ut_exit.__e_termination], [
+ AC_DEFINE(HAVE_STRUCT_UTMP_UT_EXIT, 1, [Define to 1 if 'ut_exit' is a member of 'struct utmp'.])
+ AC_DEFINE(HAVE_STRUCT_UTMP_UT_EXIT___E_TERMINATION, 1, [Define to 1 if 'ut_exit.__e_termination' is a member of 'struct utmp'.])
+ ], [
+ AC_CHECK_MEMBER([struct $1.ut_exit.e_termination], [
+ AC_DEFINE(HAVE_STRUCT_UTMP_UT_EXIT, 1, [Define to 1 if 'ut_exit' is a member of 'struct utmp'.])
+ AC_DEFINE(HAVE_STRUCT_UTMP_UT_EXIT_E_TERMINATION, 1, [Define to 1 if 'ut_exit.e_termination' is a member of 'struct utmp'.])
+ ], [], [
+# include <sys/types.h>
+# include <$1.h>
+ ])
+ ], [
+# include <sys/types.h>
+# include <$1.h>
+ ])
+])
+
+dnl
+dnl Append a libpath to an LDFLAGS style variable if not already present.
+dnl Also appends to the _R version unless rpath is disabled.
+dnl
+AC_DEFUN([SUDO_APPEND_LIBPATH], [
+ AX_APPEND_FLAG([-L$2], [$1])
+ if test X"$enable_rpath" = X"yes"; then
+ AX_APPEND_FLAG([-R$2], [$1_R])
+ fi
+])
+
+dnl
+dnl Append one or more symbols to COMPAT_EXP
+dnl
+AC_DEFUN([SUDO_APPEND_COMPAT_EXP], [
+ for _sym in $1; do
+ COMPAT_EXP="${COMPAT_EXP}${_sym}
+"
+ done
+])
+
+dnl
+dnl Append one or more symbols to INTERCEPT_EXP
+dnl
+AC_DEFUN([SUDO_APPEND_INTERCEPT_EXP], [
+ for _sym in $1; do
+ INTERCEPT_EXP="${INTERCEPT_EXP}${_sym}
+"
+ done
+])
+
+dnl
+dnl Determine the mail spool location
+dnl NOTE: must be run *after* check for paths.h
+dnl
+AC_DEFUN([SUDO_MAILDIR], [
+ AC_CACHE_CHECK([for the user mail spool directory], [sudo_cv_mail_dir], [
+ sudo_cv_mail_dir=no
+ if test X"$ac_cv_header_paths_h" = X"yes"; then
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
+#include <paths.h>],
+ [char *p = _PATH_MAILDIR;])], [sudo_cv_mail_dir="paths.h"], [])
+ fi
+ if test $sudo_cv_mail_dir = no; then
+ # Solaris has maillock.h which defines MAILDIR
+ AC_CHECK_HEADERS(maillock.h, [
+ sudo_cv_mail_dir=maillock.h
+ ], [
+ sudo_cv_mail_dir=/var/mail
+ for d in /var/mail /var/spool/mail /usr/spool/mail; do
+ if test -d "$d"; then
+ sudo_cv_mail_dir="$d"
+ break
+ fi
+ done
+ ])
+ fi
+ ])
+ case "$sudo_cv_mail_dir" in
+ paths.h)
+ # _PATH_MAILDIR already present in paths.h.
+ ;;
+ maillock.h)
+ # Use MAILDIR from maillock.h
+ SUDO_DEFINE(_PATH_MAILDIR, MAILDIR)
+ AC_DEFINE(HAVE_MAILLOCK_H)
+ ;;
+ *)
+ SUDO_DEFINE_UNQUOTED(_PATH_MAILDIR, "$sudo_cv_mail_dir")
+ ;;
+ esac
+])
+
+dnl
+dnl Create PVS-Studio.cfg for supported platforms or throw an error.
+dnl
+AC_DEFUN([SUDO_PVS_STUDIO_CFG], [
+ if test X"$enable_pvs_studio" = X"yes"; then
+ # Determine preprocessor type
+ case "$CC" in
+ *clang*) preprocessor=clang;;
+ *gcc*) preprocessor=gcc;;
+ *) case `$CC --version 2>&1` in
+ *clang*) preprocessor=clang;;
+ *gcc*) preprocessor=gcc;;
+ *) AC_MSG_ERROR([Compiler must be gcc or clang for PVS-Studio.]);;
+ esac
+ ;;
+ esac
+
+ # Determine platform (currently linux or macos)
+ case "$host" in
+ x86_64-*-linux*) pvs_platform=linux64;;
+ *86-*-linux*) pvs_platform=linux32;;
+ *-*-darwin*) pvs_platform=macos;;
+ *) AC_MSG_ERROR([PVS-Studio does not support $host.]);;
+ esac
+
+ # Create a basic PVS-Studio.cfg file
+ cat > PVS-Studio.cfg <<-EOF
+ preprocessor = $preprocessor
+ platform = $pvs_platform
+ analysis-mode = 4
+ language = C
+ EOF
+
+ # Check for a license file in the default location
+ if test -f "$HOME/.config/PVS-Studio/PVS-Studio.lic"; then
+ echo "lic-file = $HOME/.config/PVS-Studio/PVS-Studio.lic" >> PVS-Studio.cfg
+ fi
+ fi
+])
+
+AC_DEFUN([SUDO_CPP_VARIADIC_MACROS],
+[AC_CACHE_CHECK([for variadic macro support in cpp],
+[sudo_cv_cpp_variadic_macros], [
+ sudo_cv_cpp_variadic_macros=yes
+ if test X"$ac_cv_prog_cc_c99" = X"no"; then
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
+#if defined(__GNUC__) && __GNUC__ == 2
+# define sudo_fprintf(fp, fmt...) fprintf((fp), (fmt))
+#else
+# define sudo_fprintf(fp, ...) fprintf((fp), __VA_ARGS__)
+#endif], [sudo_fprintf(stderr, "a %s", "test");
+ ])], [], [sudo_cv_cpp_variadic_macros=no])
+ fi
+ ])
+ if test X"$sudo_cv_cpp_variadic_macros" = X"no"; then
+ AC_DEFINE([NO_VARIADIC_MACROS], [1], [Define if your C preprocessor does not support variadic macros.])
+ AC_MSG_WARN([your C preprocessor doesn't support variadic macros, debugging support will be limited])
+ SUDO_APPEND_COMPAT_EXP(sudo_debug_printf_nvm_v1)
+ fi
+])
+
+dnl
+dnl private versions of AC_DEFINE and AC_DEFINE_UNQUOTED that don't support
+dnl tracing that we use to define paths for pathnames.h so autoheader doesn't
+dnl put them in config.h.in. An awful hack.
+dnl
+m4_define([SUDO_DEFINE],
+[cat >>confdefs.h <<\EOF
+[@%:@define] $1 m4_if($#, 2, [$2], $#, 3, [$2], 1)
+EOF
+])
+
+m4_define([SUDO_DEFINE_UNQUOTED],
+[cat >>confdefs.h <<EOF
+[@%:@define] $1 m4_if($#, 2, [$2], $#, 3, [$2], 1)
+EOF
+])
+
+dnl
+dnl Expand Makefile-style variables in $1 and store the result in $2.
+dnl Used to expand file paths for use in man pages and pathnames.h.
+dnl
+AC_DEFUN([SUDO_EXPAND_PATH], [
+ $2="$1"
+ while :; do
+ $2="`echo \"$$2\" | sed -e 's/(/{/g' -e 's/)/}/g'`"
+ case "$$2" in
+ *\${[[A-Za-z]]*}*)
+ eval $2="$$2"
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+case "$$2" in
+ NONE/*)
+ $2="${ac_default_prefix}${$2#NONE}"
+ ;;
+esac
+])
+
+dnl
+dnl Expand Makefile-style variables in $1, a colon-separated list of paths,
+dnl and define the result as a string using the name $2.
+dnl
+AC_DEFUN([SUDO_DEFINE_PATH], [
+ as_save_IFS=$IFS
+ IFS=:
+ _sudo_define_path_res=
+ for as_dir in $1; do
+ SUDO_EXPAND_PATH([$as_dir], [_sudo_define_path_exp])
+ if test -z "${_sudo_define_path_res}"; then
+ _sudo_define_path_res="${_sudo_define_path_exp}"
+ else
+ _sudo_define_path_res="${_sudo_define_path_res}:${_sudo_define_path_exp}"
+ fi
+ done
+ IFS=$as_save_IFS
+ SUDO_DEFINE_UNQUOTED($2, "${_sudo_define_path_res}")
+])
diff --git a/m4/visibility.m4 b/m4/visibility.m4
new file mode 100644
index 0000000..48188cd
--- /dev/null
+++ b/m4/visibility.m4
@@ -0,0 +1,140 @@
+AC_DEFUN([SUDO_SYMBOL_VISIBILITY], [
+ dnl
+ dnl Check for symbol visibility support.
+ dnl This test relies on AC_LANG_WERROR
+ dnl
+ if test -n "$GCC"; then
+ AX_CHECK_COMPILE_FLAG([-fvisibility=hidden], [
+ AC_DEFINE(HAVE_DSO_VISIBILITY)
+ AX_APPEND_FLAG([-fvisibility=hidden], [CFLAGS])
+ LT_LDEXPORTS=
+ LT_LDDEP=
+ ])
+ else
+ case "$host_os" in
+ hpux*)
+ AX_CHECK_COMPILE_FLAG([-Bhidden_def], [
+ # HP-UX cc may not allow __declspec(dllexport) to be
+ # used in conjunction with #pragma HP_DEFINED_EXTERNAL
+ # when redefining standard libc functions.
+ AC_CACHE_CHECK([whether __declspec(dllexport) can be used when overriding libc functions],
+ [sudo_cv_var_hpux_declspec_libc_function],
+ [
+ _CFLAGS="$CFLAGS"
+ CFLAGS="${CFLAGS} -Bhidden_def"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <stdlib.h>
+ __declspec(dllexport) char * getenv(const char *n) { return NULL; }]])], [
+ sudo_cv_var_hpux_declspec_libc_function=yes
+ ], [
+ sudo_cv_var_hpux_declspec_libc_function=no
+ ])
+ CFLAGS="$_CFLAGS"
+ ]
+ )
+ if test "$sudo_cv_var_hpux_declspec_libc_function" = "yes"; then
+ AC_DEFINE(HAVE_DSO_VISIBILITY)
+ AX_APPEND_FLAG([-Bhidden_def], [CFLAGS])
+ LT_LDEXPORTS=
+ LT_LDDEP=
+ fi
+ ])
+ ;;
+ solaris2*)
+ AX_CHECK_COMPILE_FLAG([-xldscope=hidden], [
+ AC_DEFINE(HAVE_DSO_VISIBILITY)
+ AX_APPEND_FLAG([-xldscope=hidden], [CFLAGS])
+ LT_LDEXPORTS=
+ LT_LDDEP=
+ ])
+ ;;
+ esac
+ fi
+
+ dnl
+ dnl Check whether ld supports version scripts (most ELF linkers).
+ dnl If possible, we use this even if the compiler has symbol visibility
+ dnl support so we will notice mismatches between the exports file and
+ dnl sudo_dso_public annotations in the source code.
+ dnl This test relies on AC_LANG_WERROR
+ dnl
+ if test "$lt_cv_prog_gnu_ld" = "yes"; then
+ AC_CACHE_CHECK([whether ld supports anonymous map files],
+ [sudo_cv_var_gnu_ld_anon_map],
+ [
+ sudo_cv_var_gnu_ld_anon_map=no
+ cat > conftest.map <<-EOF
+ {
+ global: foo;
+ local: *;
+ };
+ EOF
+ _CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $lt_prog_compiler_pic"
+ _LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_prog_compiler_pic -shared -Wl,--version-script,./conftest.map"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[int foo;]], [[]])],
+ [sudo_cv_var_gnu_ld_anon_map=yes])
+ CFLAGS="$_CFLAGS"
+ LDFLAGS="$_LDFLAGS"
+ rm -f conftest.map
+ ]
+ )
+ if test "$sudo_cv_var_gnu_ld_anon_map" = "yes"; then
+ LT_LDDEP="\$(shlib_map)"; LT_LDEXPORTS="-Wl,--version-script,\$(shlib_map)"
+ fi
+ else
+ case "$host_os" in
+ solaris2*)
+ AC_CACHE_CHECK([whether ld supports anonymous map files],
+ [sudo_cv_var_solaris_ld_anon_map],
+ [
+ sudo_cv_var_solaris_ld_anon_map=no
+ cat > conftest.map <<-EOF
+ {
+ global: foo;
+ local: *;
+ };
+ EOF
+ _CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $lt_prog_compiler_pic"
+ _LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS -shared -Wl,-M,./conftest.map"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[int foo;]], [[]])],
+ [sudo_cv_var_solaris_ld_anon_map=yes])
+ CFLAGS="$_CFLAGS"
+ LDFLAGS="$_LDFLAGS"
+ rm -f conftest.map
+ ]
+ )
+ if test "$sudo_cv_var_solaris_ld_anon_map" = "yes"; then
+ LT_LDDEP="\$(shlib_map)"; LT_LDEXPORTS="-Wl,-M,\$(shlib_map)"
+ fi
+ ;;
+ hpux*)
+ AC_CACHE_CHECK([whether ld supports controlling exported symbols],
+ [sudo_cv_var_hpux_ld_symbol_export],
+ [
+ sudo_cv_var_hpux_ld_symbol_export=no
+ echo "+e foo" > conftest.opt
+ _CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $lt_prog_compiler_pic"
+ _LDFLAGS="$LDFLAGS"
+ if test -n "$GCC"; then
+ LDFLAGS="$LDFLAGS -shared -Wl,-c,./conftest.opt"
+ else
+ LDFLAGS="$LDFLAGS -b -Wl,-c,./conftest.opt"
+ fi
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[int foo;]], [[]])],
+ [sudo_cv_var_hpux_ld_symbol_export=yes])
+ CFLAGS="$_CFLAGS"
+ LDFLAGS="$_LDFLAGS"
+ rm -f conftest.opt
+ ]
+ )
+ if test "$sudo_cv_var_hpux_ld_symbol_export" = "yes"; then
+ LT_LDDEP="\$(shlib_opt)"; LT_LDEXPORTS="-Wl,-c,\$(shlib_opt)"
+ fi
+ ;;
+ esac
+ fi
+])
diff --git a/pathnames.h.in b/pathnames.h.in
new file mode 100644
index 0000000..d27fcf3
--- /dev/null
+++ b/pathnames.h.in
@@ -0,0 +1,265 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998, 1999, 2001, 2004, 2005, 2007-2021
+ * Todd C. Miller <Todd.Miller@sudo.ws>.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * Pathnames to programs and files used by sudo.
+ */
+
+#ifdef HAVE_PATHS_H
+# include <paths.h>
+#endif /* HAVE_PATHS_H */
+
+#ifdef HAVE_MAILLOCK_H
+# include <maillock.h>
+#endif /* HAVE_MAILLOCK_H */
+
+#ifndef _PATH_DEV
+# define _PATH_DEV "/dev/"
+#endif /* _PATH_DEV */
+
+#ifndef _PATH_TTY
+# define _PATH_TTY _PATH_DEV "tty"
+#endif /* _PATH_TTY */
+
+#ifndef _PATH_DEVNULL
+# define _PATH_DEVNULL _PATH_DEV "null"
+#endif /* _PATH_DEVNULL */
+
+#ifndef _PATH_DEFPATH
+# define _PATH_DEFPATH "/usr/bin:/bin"
+#endif /* _PATH_DEFPATH */
+
+#ifndef _PATH_STDPATH
+# define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin"
+#endif /* _PATH_STDPATH */
+
+/* Use /etc/environment on AIX or Linux w/o PAM (where pam_env handles it). */
+#if defined(_AIX) || (defined(__linux__) && !defined(HAVE_PAM))
+# define _PATH_ENVIRONMENT "/etc/environment"
+#endif /* _PATH_ENVIRONMENT */
+
+/*
+ * The following paths are controlled via the configure script.
+ */
+
+/*
+ * NOTE: _PATH_SUDO_CONF is usually overridden by the Makefile.
+ */
+#ifndef _PATH_SUDO_CONF
+# undef _PATH_SUDO_CONF
+#endif /* _PATH_SUDO_CONF */
+
+/*
+ * NOTE: _PATH_SUDOERS is usually overridden by the Makefile.
+ */
+#ifndef _PATH_SUDOERS
+# undef _PATH_SUDOERS
+#endif /* _PATH_SUDOERS */
+
+/*
+ * NOTE: _PATH_CVTSUDOERS_CONF is usually overridden by the Makefile.
+ */
+#ifndef _PATH_CVTSUDOERS_CONF
+# undef _PATH_CVTSUDOERS_CONF
+#endif /* _PATH_CVTSUDOERS_CONF */
+
+/*
+ * NOTE: _PATH_SUDO_LOGSRVD_CONF is usually overridden by the Makefile.
+ */
+#ifndef _PATH_SUDO_LOGSRVD_CONF
+# undef _PATH_SUDO_LOGSRVD_CONF
+#endif /* _PATH_SUDO_LOGSRVD_CONF */
+
+/*
+ * Where sudo_logsrvd stores its pid file files. Defaults to
+ * /var/run/sudo/sudo_logsrvd.pid, /var/db/sudo/sudo_logsrvd.pid,
+ * /var/lib/sudo/sudo_logsrvd.pid, /var/adm/sudo/sudo_logsrvd.pid or
+ * /usr/adm/sudo/sudo_logsrvd.pid depending on what exists on the system.
+ */
+#ifndef _PATH_SUDO_LOGSRVD_PID
+# undef _PATH_SUDO_LOGSRVD_PID
+#endif /* _PATH_SUDO_LOGSRVD_PID */
+
+/*
+ * Where to store the time stamp files. Defaults to /var/run/sudo/ts,
+ * /var/db/sudo/ts, /var/lib/sudo/ts, /var/adm/sudo/ts or /usr/adm/sudo/ts
+ * depending on what exists on the system.
+ */
+#ifndef _PATH_SUDO_TIMEDIR
+# undef _PATH_SUDO_TIMEDIR
+#endif /* _PATH_SUDO_TIMEDIR */
+
+/*
+ * Where to store the lecture status files. Defaults to /var/db/sudo/lectured,
+ * /var/lib/sudo/lectured, /var/adm/sudo/lectured or /usr/adm/sudo/lectured
+ * depending on what exists on the system.
+ */
+#ifndef _PATH_SUDO_LECTURE_DIR
+# undef _PATH_SUDO_LECTURE_DIR
+#endif /* _PATH_SUDO_LECTURE_DIR */
+
+/*
+ * Where to put the I/O log files. Defaults to /var/log/sudo-io,
+ * /var/adm/sudo-io or /usr/adm/sudo-io depending on what exists.
+ */
+#ifndef _PATH_SUDO_IO_LOGDIR
+# undef _PATH_SUDO_IO_LOGDIR
+#endif /* _PATH_SUDO_IO_LOGDIR */
+
+/*
+ * Where to put the audit and other log files. Defaults to /var/log,
+ * /var/adm or /usr/adm depending on what exists.
+ */
+#ifndef _PATH_SUDO_LOGDIR
+# undef _PATH_SUDO_LOGDIR
+#endif /* _PATH_SUDO_LOGDIR */
+
+/*
+ * Where to store sudo_logsrvd relay temporary files. Defaults to
+ * /var/log/sudo_logsrvd, /var/adm/sudo_logsrvd or /usr/adm/sudo_logsrvd
+ * depending on what exists.
+ */
+#ifndef _PATH_SUDO_RELAY_DIR
+# undef _PATH_SUDO_RELAY_DIR
+#endif /* _PATH_SUDO_RELAY_DIR */
+
+/*
+ * Where to put the sudo log file when logging to a file. Defaults to
+ * /var/log/sudo.log if /var/log exists, else /var/adm/sudo.log.
+ */
+#ifndef _PATH_SUDO_LOGFILE
+# undef _PATH_SUDO_LOGFILE
+#endif /* _PATH_SUDO_LOGFILE */
+
+/*
+ * The path to an Ubuntu-style admin flag file that is created the
+ * first time a user runs sudo.
+ */
+#ifndef _PATH_SUDO_ADMIN_FLAG
+# undef _PATH_SUDO_ADMIN_FLAG
+#endif /* _PATH_SUDO_ADMIN_FLAG */
+
+#ifndef _PATH_SUDO_SENDMAIL
+# undef _PATH_SUDO_SENDMAIL
+#endif /* _PATH_SUDO_SENDMAIL */
+
+#ifndef _PATH_SUDO_INTERCEPT
+# undef _PATH_SUDO_INTERCEPT
+#endif /* _PATH_SUDO_INTERCEPT */
+
+#ifndef _PATH_SUDO_NOEXEC
+# undef _PATH_SUDO_NOEXEC
+#endif /* _PATH_SUDO_NOEXEC */
+
+#ifndef _PATH_SUDO_ASKPASS
+# undef _PATH_SUDO_ASKPASS
+#endif /* _PATH_SUDO_ASKPASS */
+
+#ifndef _PATH_SUDO_PLUGIN_DIR
+# undef _PATH_SUDO_PLUGIN_DIR
+#endif /* _PATH_SUDO_PLUGIN_DIR */
+
+#ifndef _PATH_SUDO_DEVSEARCH
+# undef _PATH_SUDO_DEVSEARCH
+#endif /* _PATH_SUDO_DEVSEARCH */
+
+#ifndef _PATH_SUDOERS_PLUGIN
+# undef _PATH_SUDOERS_PLUGIN
+#endif /* _PATH_SUDOERS_PLUGIN */
+
+#ifndef _PATH_ASAN_LIB
+# undef _PATH_ASAN_LIB
+#endif /* _PATH_ASAN_LIB */
+
+#ifndef _PATH_VI
+# undef _PATH_VI
+#endif /* _PATH_VI */
+
+#ifndef _PATH_MV
+# undef _PATH_MV
+#endif /* _PATH_MV */
+
+#ifndef _PATH_BSHELL
+# undef _PATH_BSHELL
+#endif /* _PATH_BSHELL */
+
+#ifndef _PATH_TMP
+# define _PATH_TMP "/tmp/"
+#endif /* _PATH_TMP */
+
+#ifndef _PATH_VARTMP
+# define _PATH_VARTMP "/var/tmp/"
+#endif /* _PATH_VARTMP */
+
+#ifndef _PATH_USRTMP
+# define _PATH_USRTMP "/usr/tmp/"
+#endif /* _PATH_USRTMP */
+
+#ifndef _PATH_MAILDIR
+# undef _PATH_MAILDIR
+#endif /* _PATH_MAILDIR */
+
+#ifndef _PATH_UTMP
+# undef _PATH_UTMP
+#endif /* _PATH_UTMP */
+
+#ifndef _PATH_SUDO_SESH
+# undef _PATH_SUDO_SESH
+#endif /* _PATH_SUDO_SESH */
+
+#ifndef _PATH_LDAP_CONF
+# undef _PATH_LDAP_CONF
+#endif /* _PATH_LDAP_CONF */
+
+#ifndef _PATH_LDAP_SECRET
+# undef _PATH_LDAP_SECRET
+#endif /* _PATH_LDAP_SECRET */
+
+#ifndef _PATH_SSSD_CONF
+# undef _PATH_SSSD_CONF
+#endif /* _PATH_SSSD_CONF */
+
+#ifndef _PATH_SSSD_LIB
+# undef _PATH_SSSD_LIB
+#endif /* _PATH_SSSD_LIB */
+
+#ifndef _PATH_NSSWITCH_CONF
+# undef _PATH_NSSWITCH_CONF
+#endif /* _PATH_NSSWITCH_CONF */
+
+#ifndef _PATH_NETSVC_CONF
+# undef _PATH_NETSVC_CONF
+#endif /* _PATH_NETSVC_CONF */
+
+#ifndef _PATH_ZONEINFO
+# undef _PATH_ZONEINFO
+#endif /* _PATH_ZONEINFO */
+
+/* On AIX, _PATH_BSHELL in paths.h is /usr/bin/bsh but we want /usr/bin/sh */
+#ifndef _PATH_SUDO_BSHELL
+# if defined(_AIX) && defined(HAVE_PATHS_H)
+# define _PATH_SUDO_BSHELL "/usr/bin/sh"
+# else
+# define _PATH_SUDO_BSHELL _PATH_BSHELL
+# endif
+#endif /* _PATH_SUDO_BSHELL */
diff --git a/plugins/audit_json/Makefile.in b/plugins/audit_json/Makefile.in
new file mode 100644
index 0000000..e885a39
--- /dev/null
+++ b/plugins/audit_json/Makefile.in
@@ -0,0 +1,232 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2020-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+devdir = @devdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+top_srcdir = @top_srcdir@
+scriptdir = $(top_srcdir)/scripts
+incdir = $(top_srcdir)/include
+cross_compiling = @CROSS_COMPILING@
+
+# Compiler & tools to use
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+SED = @SED@
+AWK = @AWK@
+
+# Our install program supports extra flags...
+INSTALL = $(SHELL) $(scriptdir)/install-sh -c
+INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
+INSTALL_BACKUP = @INSTALL_BACKUP@
+
+# Libraries
+LT_LIBS = $(top_builddir)/lib/util/libsudo_util.la
+LIBS = $(LT_LIBS)
+
+# C preprocessor flags
+CPPFLAGS = -I$(incdir) -I$(top_builddir) @CPPFLAGS@
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+
+# Flags to pass to the link stage
+LDFLAGS = @LDFLAGS@
+LT_LDFLAGS = @LT_LDFLAGS@ @LT_LDEXPORTS@
+
+# Flags to pass to libtool
+LTFLAGS = --tag=disable-static
+
+# Address sanitizer flags
+ASAN_CFLAGS = @ASAN_CFLAGS@
+ASAN_LDFLAGS = @ASAN_LDFLAGS@
+
+# PIE flags
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+
+# Stack smashing protection flags
+HARDENING_CFLAGS = @HARDENING_CFLAGS@
+HARDENING_LDFLAGS = @HARDENING_LDFLAGS@
+
+# cppcheck options, usually set in the top-level Makefile
+CPPCHECK_OPTS = -q --enable=warning,performance,portability --suppress=constStatement --suppress=compareBoolExpressionWithInt --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
+
+# splint options, usually set in the top-level Makefile
+SPLINT_OPTS = -D__restrict= -checks
+
+# PVS-studio options
+PVS_CFG = $(top_srcdir)/PVS-Studio.cfg
+PVS_IGNORE = 'V707,V011,V002,V536'
+PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
+
+# Where to install things...
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+sysconfdir = @sysconfdir@
+adminconfdir = @adminconfdir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+localstatedir = @localstatedir@
+plugindir = @plugindir@
+
+# File mode and map file to use for shared libraries/objects
+shlib_enable = @SHLIB_ENABLE@
+shlib_mode = @SHLIB_MODE@
+shlib_exp = $(srcdir)/audit_json.exp
+shlib_map = audit_json.map
+shlib_opt = audit_json.opt
+
+# User and group ids the installed files should be "owned" by
+install_uid = 0
+install_gid = 0
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+OBJS = audit_json.lo
+
+IOBJS = $(OBJS:.lo=.i)
+
+POBJS = $(IOBJS:.i=.plog)
+
+LIBOBJDIR = $(top_builddir)/@ac_config_libobj_dir@/
+
+VERSION = @PACKAGE_VERSION@
+
+all: audit_json.la
+
+depend:
+ $(scriptdir)/mkdep.pl --srcdir=$(top_srcdir) \
+ --builddir=$(abs_top_builddir) plugins/audit_json/Makefile.in
+ cd $(top_builddir) && ./config.status --file plugins/audit_json/Makefile
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file plugins/audit_json/Makefile
+
+.SUFFIXES: .c .h .i .lo .plog
+
+.c.lo:
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.i:
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+
+.i.plog:
+ ifile=$<; rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $${ifile%i}c --i-file $< --output-file $@
+
+$(shlib_map): $(shlib_exp)
+ @$(AWK) 'BEGIN { print "{\n\tglobal:" } { print "\t\t"$$0";" } END { print "\tlocal:\n\t\t*;\n};" }' $(shlib_exp) > $@
+
+$(shlib_opt): $(shlib_exp)
+ @$(SED) 's/^/+e /' $(shlib_exp) > $@
+
+audit_json.la: $(OBJS) $(LT_LIBS) @LT_LDDEP@
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) $(ASAN_LDFLAGS) $(HARDENING_LDFLAGS) $(LT_LDFLAGS) -o $@ $(OBJS) $(LIBS) -module -avoid-version -rpath $(plugindir) -shrext .so
+
+pre-install:
+
+install: install-plugin
+
+install-dirs:
+ $(SHELL) $(scriptdir)/mkinstalldirs $(DESTDIR)$(plugindir)
+
+install-binaries:
+
+install-includes:
+
+install-doc:
+
+install-plugin: install-dirs audit_json.la
+ if [ X"$(shlib_enable)" = X"yes" ]; then \
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) $(INSTALL_OWNER) -m $(shlib_mode) audit_json.la $(DESTDIR)$(plugindir); \
+ fi
+
+install-fuzzer:
+
+uninstall:
+ -$(LIBTOOL) $(LTFLAGS) --mode=uninstall rm -f $(DESTDIR)$(plugindir)/audit_json.la
+ -test -z "$(INSTALL_BACKUP)" || \
+ rm -f $(DESTDIR)$(plugindir)/audit_json.so$(INSTALL_BACKUP)
+
+splint:
+ splint $(SPLINT_OPTS) -I$(incdir) -I$(top_builddir) $(srcdir)/*.c
+
+cppcheck:
+ cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) $(srcdir)/*.c
+
+pvs-log-files: $(POBJS)
+
+pvs-studio: $(POBJS)
+ plog-converter $(PVS_LOG_OPTS) $(POBJS)
+
+fuzz:
+
+check-fuzzer:
+
+check: check-fuzzer
+
+check-verbose: check
+
+clean:
+ -$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f *.lo *.o *.la *.a
+ -rm -f *.i *.plog stamp-* core *.core core.*
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile .libs $(shlib_map) $(shlib_opt)
+
+clobber: distclean
+
+realclean: distclean
+ rm -f TAGS tags
+
+cleandir: realclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean
+
+# Autogenerated dependencies, do not modify
+getgrent.lo: $(srcdir)/getgrent.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/getgrent.c
+getgrent.i: $(srcdir)/getgrent.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+getgrent.plog: getgrent.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/getgrent.c --i-file $< --output-file $@
+audit_json.lo: $(srcdir)/audit_json.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_plugin.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/audit_json.c
+audit_json.i: $(srcdir)/audit_json.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_plugin.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+audit_json.plog: audit_json.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/audit_json.c --i-file $< --output-file $@
diff --git a/plugins/audit_json/audit_json.c b/plugins/audit_json/audit_json.c
new file mode 100644
index 0000000..c19c29b
--- /dev/null
+++ b/plugins/audit_json/audit_json.c
@@ -0,0 +1,737 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <time.h>
+
+#include <pathnames.h>
+#include <sudo_compat.h>
+#include <sudo_conf.h>
+#include <sudo_debug.h>
+#include <sudo_dso.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_json.h>
+#include <sudo_plugin.h>
+#include <sudo_util.h>
+
+static int audit_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
+static sudo_conv_t audit_conv;
+static sudo_printf_t audit_printf;
+
+static struct audit_state {
+ int submit_optind;
+ char uuid_str[37];
+ bool accepted;
+ FILE *log_fp;
+ char *logfile;
+ char * const * settings;
+ char * const * user_info;
+ char * const * submit_argv;
+ char * const * submit_envp;
+} state = { -1 };
+
+/* Filter out entries in settings[] that are not really options. */
+const char * const settings_filter[] = {
+ "debug_flags",
+ "max_groups",
+ "network_addrs",
+ "plugin_dir",
+ "plugin_path",
+ "progname",
+ NULL
+};
+
+static int
+audit_json_open(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t plugin_printf, char * const settings[],
+ char * const user_info[], int submit_optind, char * const submit_argv[],
+ char * const submit_envp[], char * const plugin_options[],
+ const char **errstr)
+{
+ struct sudo_conf_debug_file_list debug_files =
+ TAILQ_HEAD_INITIALIZER(debug_files);
+ struct sudo_debug_file *debug_file;
+ const char *cp, *plugin_path = NULL;
+ unsigned char uuid[16];
+ char * const *cur;
+ mode_t oldmask;
+ int fd, ret = -1;
+ debug_decl_vars(audit_json_open, SUDO_DEBUG_PLUGIN);
+
+ audit_conv = conversation;
+ audit_printf = plugin_printf;
+
+ /*
+ * Stash initial values.
+ */
+ state.submit_optind = submit_optind;
+ state.settings = settings;
+ state.user_info = user_info;
+ state.submit_argv = submit_argv;
+ state.submit_envp = submit_envp;
+
+ /* Initialize the debug subsystem. */
+ for (cur = settings; (cp = *cur) != NULL; cur++) {
+ if (strncmp(cp, "debug_flags=", sizeof("debug_flags=") - 1) == 0) {
+ cp += sizeof("debug_flags=") - 1;
+ if (sudo_debug_parse_flags(&debug_files, cp) == -1)
+ goto oom;
+ continue;
+ }
+ if (strncmp(cp, "plugin_path=", sizeof("plugin_path=") - 1) == 0) {
+ plugin_path = cp + sizeof("plugin_path=") - 1;
+ continue;
+ }
+ }
+ if (plugin_path != NULL && !TAILQ_EMPTY(&debug_files)) {
+ audit_debug_instance =
+ sudo_debug_register(plugin_path, NULL, NULL, &debug_files, -1);
+ if (audit_debug_instance == SUDO_DEBUG_INSTANCE_ERROR) {
+ *errstr = U_("unable to initialize debugging");
+ goto bad;
+ }
+ sudo_debug_enter(__func__, __FILE__, __LINE__, sudo_debug_subsys);
+ }
+
+ /* Create a UUID for this command for use with audit records. */
+ sudo_uuid_create(uuid);
+ if (sudo_uuid_to_string(uuid, state.uuid_str, sizeof(state.uuid_str)) == NULL) {
+ *errstr = U_("unable to generate UUID");
+ goto bad;
+ }
+
+ /* Parse plugin_options to check for logfile option. */
+ if (plugin_options != NULL) {
+ for (cur = plugin_options; (cp = *cur) != NULL; cur++) {
+ if (strncmp(cp, "logfile=", sizeof("logfile=") - 1) == 0) {
+ state.logfile = strdup(cp + sizeof("logfile=") - 1);
+ if (state.logfile == NULL)
+ goto oom;
+ }
+ }
+ }
+ if (state.logfile == NULL) {
+ if (asprintf(&state.logfile, "%s/sudo_audit.json", _PATH_SUDO_LOGDIR) == -1)
+ goto oom;
+ }
+
+ /* open log file */
+ /* TODO: support pipe */
+ oldmask = umask(S_IRWXG|S_IRWXO);
+ fd = open(state.logfile, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
+ (void)umask(oldmask);
+ if (fd == -1 || (state.log_fp = fdopen(fd, "w")) == NULL) {
+ *errstr = U_("unable to open audit system");
+ if (fd != -1)
+ close(fd);
+ goto bad;
+ }
+
+ ret = 1;
+ goto done;
+
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ *errstr = U_("unable to allocate memory");
+
+bad:
+ if (state.log_fp != NULL) {
+ fclose(state.log_fp);
+ state.log_fp = NULL;
+ }
+
+done:
+ while ((debug_file = TAILQ_FIRST(&debug_files))) {
+ TAILQ_REMOVE(&debug_files, debug_file, entries);
+ free(debug_file->debug_file);
+ free(debug_file->debug_flags);
+ free(debug_file);
+ }
+
+ debug_return_int(ret);
+}
+
+static bool
+add_key_value(struct json_container *jsonc, const char *str)
+{
+ struct json_value json_value;
+ const char *cp, *errstr;
+ char name[256];
+ size_t len;
+ debug_decl(add_key_value, SUDO_DEBUG_PLUGIN);
+
+ if ((cp = strchr(str, '=')) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring bad command info string \"%s\"", str);
+ debug_return_bool(false);
+ }
+ len = (size_t)(cp - str);
+ cp++;
+
+ /* Variable name currently limited to 256 chars */
+ if (len >= sizeof(name)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring long command info name \"%.*s\"", (int)len, str);
+ debug_return_bool(false);
+ }
+ memcpy(name, str, len);
+ name[len] = '\0';
+
+ /* Check for bool or number. */
+ json_value.type = JSON_NULL;
+ switch (cp[0]) {
+ case '0':
+ if (cp[1] == '\0') {
+ /* Only treat a plain "0" as number 0. */
+ json_value.u.number = 0;
+ json_value.type = JSON_NUMBER;
+ }
+ break;
+ case '+': case '-':
+ if (cp[1] == '0') {
+ /* Encode octal numbers as strings. */
+ break;
+ }
+ FALLTHROUGH;
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ json_value.u.number = sudo_strtonum(cp, INT_MIN, INT_MAX, &errstr);
+ if (errstr == NULL)
+ json_value.type = JSON_NUMBER;
+ break;
+ case 't':
+ if (strcmp(cp, "true") == 0) {
+ json_value.type = JSON_BOOL;
+ json_value.u.boolean = true;
+ }
+ break;
+ case 'f':
+ if (strcmp(cp, "false") == 0) {
+ json_value.type = JSON_BOOL;
+ json_value.u.boolean = false;
+ }
+ break;
+ }
+
+ /* Default to string type. */
+ if (json_value.type == JSON_NULL) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = cp;
+ }
+
+ debug_return_bool(sudo_json_add_value(jsonc, name, &json_value));
+}
+
+static bool
+add_array(struct json_container *jsonc, const char *name, char * const * array)
+{
+ const char *cp;
+ struct json_value json_value;
+ debug_decl(add_array, SUDO_DEBUG_PLUGIN);
+
+ if (!sudo_json_open_array(jsonc, name))
+ debug_return_bool(false);
+ while ((cp = *array) != NULL) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = cp;
+ if (!sudo_json_add_value(jsonc, name, &json_value))
+ debug_return_bool(false);
+ array++;
+ }
+ if (!sudo_json_close_array(jsonc))
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+static bool
+filter_key_value(const char *kv, const char * const * filter)
+{
+ const char * const *cur;
+ const char *cp;
+ size_t namelen;
+
+ if (filter != NULL) {
+ namelen = strcspn(kv, "=");
+ for (cur = filter; (cp = *cur) != NULL; cur++) {
+ if (strncmp(kv, cp, namelen) == 0 && cp[namelen] == '\0')
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool
+add_key_value_object(struct json_container *jsonc, const char *name,
+ char * const * array, const char * const * filter)
+{
+ char * const *cur;
+ const char *cp;
+ bool empty = false;
+ debug_decl(add_key_value_object, SUDO_DEBUG_PLUGIN);
+
+ if (filter != NULL) {
+ /* Avoid printing an empty object if everything is filtered. */
+ empty = true;
+ for (cur = array; (cp = *cur) != NULL; cur++) {
+ if (!filter_key_value(cp, filter)) {
+ empty = false;
+ break;
+ }
+ }
+ }
+ if (!empty) {
+ if (!sudo_json_open_object(jsonc, name))
+ goto bad;
+ for (cur = array; (cp = *cur) != NULL; cur++) {
+ if (filter_key_value(cp, filter))
+ continue;
+ if (!add_key_value(jsonc, cp))
+ goto bad;
+ }
+ if (!sudo_json_close_object(jsonc))
+ goto bad;
+ }
+
+ debug_return_bool(true);
+bad:
+ debug_return_bool(false);
+}
+
+static bool
+add_timestamp(struct json_container *jsonc, struct timespec *ts)
+{
+ struct json_value json_value;
+ time_t secs = ts->tv_sec;
+ char timebuf[1024];
+ struct tm gmt;
+ size_t len;
+ debug_decl(add_timestamp, SUDO_DEBUG_PLUGIN);
+
+ if (gmtime_r(&secs, &gmt) == NULL)
+ debug_return_bool(false);
+
+ sudo_json_open_object(jsonc, "timestamp");
+
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = ts->tv_sec;
+ sudo_json_add_value(jsonc, "seconds", &json_value);
+
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = ts->tv_nsec;
+ sudo_json_add_value(jsonc, "nanoseconds", &json_value);
+
+ timebuf[sizeof(timebuf) - 1] = '\0';
+ len = strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", &gmt);
+ if (len != 0 && timebuf[sizeof(timebuf) - 1] == '\0'){
+ json_value.type = JSON_STRING;
+ json_value.u.string = timebuf;
+ sudo_json_add_value(jsonc, "iso8601", &json_value);
+ }
+
+ timebuf[sizeof(timebuf) - 1] = '\0';
+ len = strftime(timebuf, sizeof(timebuf), "%a %b %e %H:%M:%S %Z %Y", &gmt);
+ if (len != 0 && timebuf[sizeof(timebuf) - 1] == '\0'){
+ json_value.type = JSON_STRING;
+ json_value.u.string = timebuf;
+ sudo_json_add_value(jsonc, "localtime", &json_value);
+ }
+
+ sudo_json_close_object(jsonc);
+
+ debug_return_bool(true);
+}
+
+static int
+audit_write_json(struct json_container * restrict jsonc)
+{
+ struct stat sb;
+ int ret = -1;
+ debug_decl(audit_write_json, SUDO_DEBUG_PLUGIN);
+
+ if (!sudo_lock_file(fileno(state.log_fp), SUDO_LOCK)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "unable to lock %s", state.logfile);
+ goto done;
+ }
+
+ /* Note: assumes file ends in "\n}\n" */
+ if (fstat(fileno(state.log_fp), &sb) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "unable to stat %s", state.logfile);
+ goto done;
+ }
+ if (sb.st_size == 0) {
+ /* New file */
+ putc('{', state.log_fp);
+ } else if (fseeko(state.log_fp, -3, SEEK_END) == 0) {
+ /* Continue file, overwrite the final "\n}\n" */
+ putc(',', state.log_fp);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "unable to seek %s", state.logfile);
+ goto done;
+ }
+
+ fputs(sudo_json_get_buf(jsonc), state.log_fp);
+ fputs("\n}\n", state.log_fp);
+ fflush(state.log_fp);
+ (void)sudo_lock_file(fileno(state.log_fp), SUDO_UNLOCK);
+
+ /* TODO: undo partial record on error */
+ if (!ferror(state.log_fp))
+ ret = true;
+
+done:
+ debug_return_int(ret);
+}
+
+static int
+audit_write_exit_record(int exit_status, int error)
+{
+ struct json_container jsonc;
+ struct json_value json_value;
+ struct timespec now;
+ int ret = -1;
+ debug_decl(audit_write_exit_record, SUDO_DEBUG_PLUGIN);
+
+ if (sudo_gettime_real(&now) == -1) {
+ sudo_warn("%s", U_("unable to read the clock"));
+ goto done;
+ }
+
+ if (!sudo_json_init(&jsonc, 4, false, false, false))
+ goto oom;
+ if (!sudo_json_open_object(&jsonc, "exit"))
+ goto oom;
+
+ /* Write UUID */
+ json_value.type = JSON_STRING;
+ json_value.u.string = state.uuid_str;
+ if (!sudo_json_add_value(&jsonc, "uuid", &json_value))
+ goto oom;
+
+ /* Write time stamp */
+ if (!add_timestamp(&jsonc, &now))
+ goto oom;
+
+ if (error != 0) {
+ /* Error executing command */
+ json_value.type = JSON_STRING;
+ json_value.u.string = strerror(error);
+ if (!sudo_json_add_value(&jsonc, "error", &json_value))
+ goto oom;
+ } else {
+ if (WIFEXITED(exit_status)) {
+ /* Command exited normally. */
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = WEXITSTATUS(exit_status);
+ if (!sudo_json_add_value(&jsonc, "exit_value", &json_value))
+ goto oom;
+ } else if (WIFSIGNALED(exit_status)) {
+ /* Command killed by signal. */
+ char signame[SIG2STR_MAX];
+ int signo = WTERMSIG(exit_status);
+ if (signo <= 0 || sig2str(signo, signame) == -1) {
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = signo;
+ if (!sudo_json_add_value(&jsonc, "signal", &json_value))
+ goto oom;
+ } else {
+ json_value.type = JSON_STRING;
+ json_value.u.string = signame; // -V507
+ if (!sudo_json_add_value(&jsonc, "signal", &json_value))
+ goto oom;
+ }
+ /* Core dump? */
+ json_value.type = JSON_BOOL;
+ json_value.u.boolean = WCOREDUMP(exit_status);
+ if (!sudo_json_add_value(&jsonc, "dumped_core", &json_value))
+ goto oom;
+ /* Exit value */
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = WTERMSIG(exit_status) | 128;
+ if (!sudo_json_add_value(&jsonc, "exit_value", &json_value))
+ goto oom;
+ }
+ }
+
+ if (!sudo_json_close_object(&jsonc))
+ goto oom;
+
+ ret = audit_write_json(&jsonc);
+ sudo_json_free(&jsonc);
+done:
+ debug_return_int(ret);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ sudo_json_free(&jsonc);
+ debug_return_int(-1);
+}
+
+static int
+audit_write_record(const char *audit_str, const char *plugin_name,
+ unsigned int plugin_type, const char *reason, char * const command_info[],
+ char * const run_argv[], char * const run_envp[])
+{
+ struct json_container jsonc;
+ struct json_value json_value;
+ struct timespec now;
+ int ret = -1;
+ debug_decl(audit_write_record, SUDO_DEBUG_PLUGIN);
+
+ if (sudo_gettime_real(&now) == -1) {
+ sudo_warn("%s", U_("unable to read the clock"));
+ goto done;
+ }
+
+ if (!sudo_json_init(&jsonc, 4, false, false, false))
+ goto oom;
+ if (!sudo_json_open_object(&jsonc, audit_str))
+ goto oom;
+
+ json_value.type = JSON_STRING;
+ json_value.u.string = plugin_name;
+ if (!sudo_json_add_value(&jsonc, "plugin_name", &json_value))
+ goto oom;
+
+ switch (plugin_type) {
+ case SUDO_FRONT_END:
+ json_value.u.string = "front-end";
+ break;
+ case SUDO_POLICY_PLUGIN:
+ json_value.u.string = "policy";
+ break;
+ case SUDO_IO_PLUGIN:
+ json_value.u.string = "io";
+ break;
+ case SUDO_APPROVAL_PLUGIN:
+ json_value.u.string = "approval";
+ break;
+ case SUDO_AUDIT_PLUGIN:
+ json_value.u.string = "audit";
+ break;
+ default:
+ json_value.u.string = "unknown";
+ break;
+ }
+ json_value.type = JSON_STRING;
+ if (!sudo_json_add_value(&jsonc, "plugin_type", &json_value))
+ goto oom;
+
+ /* error and reject audit events usually contain a reason. */
+ if (reason != NULL) {
+ json_value.type = JSON_STRING;
+ json_value.u.string = reason;
+ if (!sudo_json_add_value(&jsonc, "reason", &json_value))
+ goto oom;
+ }
+
+ json_value.type = JSON_STRING;
+ json_value.u.string = state.uuid_str;
+ if (!sudo_json_add_value(&jsonc, "uuid", &json_value))
+ goto oom;
+
+ if (!add_timestamp(&jsonc, &now))
+ goto oom;
+
+ /* Write key=value objects. */
+ if (state.settings != NULL) {
+ if (!add_key_value_object(&jsonc, "options", state.settings, settings_filter))
+ goto oom;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "missing settings list");
+ }
+ if (state.user_info != NULL) {
+ if (!add_key_value_object(&jsonc, "user_info", state.user_info, NULL))
+ goto oom;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "missing user_info list");
+ }
+ if (command_info != NULL) {
+ if (!add_key_value_object(&jsonc, "command_info", command_info, NULL))
+ goto oom;
+ }
+
+ /* Write submit_optind before submit_argv */
+ json_value.type = JSON_NUMBER;
+ json_value.u.number = state.submit_optind;
+ if (!sudo_json_add_value(&jsonc, "submit_optind", &json_value))
+ goto oom;
+
+ if (state.submit_argv != NULL) {
+ if (!add_array(&jsonc, "submit_argv", state.submit_argv))
+ goto oom;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "missing submit_argv array");
+ }
+ if (state.submit_envp != NULL) {
+ if (!add_array(&jsonc, "submit_envp", state.submit_envp))
+ goto oom;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "missing submit_envp array");
+ }
+ if (run_argv != NULL) {
+ if (!add_array(&jsonc, "run_argv", run_argv))
+ goto oom;
+ }
+ if (run_envp != NULL) {
+ if (!add_array(&jsonc, "run_envp", run_envp))
+ goto oom;
+ }
+
+ if (!sudo_json_close_object(&jsonc))
+ goto oom;
+
+ ret = audit_write_json(&jsonc);
+ sudo_json_free(&jsonc);
+
+done:
+ debug_return_int(ret);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ sudo_json_free(&jsonc);
+ debug_return_int(-1);
+}
+
+static int
+audit_json_accept(const char *plugin_name, unsigned int plugin_type,
+ char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr)
+{
+ int ret;
+ debug_decl(audit_json_accept, SUDO_DEBUG_PLUGIN);
+
+ /* Ignore the extra accept event from the sudo front-end. */
+ if (plugin_type == SUDO_FRONT_END)
+ debug_return_int(true);
+
+ state.accepted = true;
+
+ ret = audit_write_record("accept", plugin_name, plugin_type, NULL,
+ command_info, run_argv, run_envp);
+
+ debug_return_int(ret);
+}
+
+static int
+audit_json_reject(const char *plugin_name, unsigned int plugin_type,
+ const char *reason, char * const command_info[], const char **errstr)
+{
+ int ret;
+ debug_decl(audit_json_reject, SUDO_DEBUG_PLUGIN);
+
+ ret = audit_write_record("reject", plugin_name, plugin_type,
+ reason, command_info, NULL, NULL);
+
+ debug_return_int(ret);
+}
+
+static int
+audit_json_error(const char *plugin_name, unsigned int plugin_type,
+ const char *reason, char * const command_info[], const char **errstr)
+{
+ int ret;
+ debug_decl(audit_json_error, SUDO_DEBUG_PLUGIN);
+
+ ret = audit_write_record("error", plugin_name, plugin_type,
+ reason, command_info, NULL, NULL);
+
+ debug_return_int(ret);
+}
+
+static void
+audit_json_close(int status_type, int status)
+{
+ debug_decl(audit_json_close, SUDO_DEBUG_PLUGIN);
+
+ switch (status_type) {
+ case SUDO_PLUGIN_NO_STATUS:
+ break;
+ case SUDO_PLUGIN_WAIT_STATUS:
+ audit_write_exit_record(status, 0);
+ break;
+ case SUDO_PLUGIN_EXEC_ERROR:
+ audit_write_exit_record(0, status);
+ break;
+ case SUDO_PLUGIN_SUDO_ERROR:
+ audit_write_record("error", "sudo", 0, strerror(status),
+ NULL, NULL, NULL);
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unexpected status type %d, value %d", status_type, status);
+ break;
+ }
+
+ free(state.logfile);
+ if (state.log_fp != NULL)
+ fclose(state.log_fp);
+
+ debug_return;
+}
+
+static int
+audit_json_show_version(int verbose)
+{
+ debug_decl(audit_json_show_version, SUDO_DEBUG_PLUGIN);
+
+ audit_printf(SUDO_CONV_INFO_MSG, "JSON audit plugin version %s\n",
+ PACKAGE_VERSION);
+
+ debug_return_int(true);
+}
+
+sudo_dso_public struct audit_plugin audit_json = {
+ SUDO_AUDIT_PLUGIN,
+ SUDO_API_VERSION,
+ audit_json_open,
+ audit_json_close,
+ audit_json_accept,
+ audit_json_reject,
+ audit_json_error,
+ audit_json_show_version,
+ NULL, /* register_hooks */
+ NULL /* deregister_hooks */
+};
diff --git a/plugins/audit_json/audit_json.exp b/plugins/audit_json/audit_json.exp
new file mode 100644
index 0000000..9015117
--- /dev/null
+++ b/plugins/audit_json/audit_json.exp
@@ -0,0 +1 @@
+audit_json
diff --git a/plugins/group_file/Makefile.in b/plugins/group_file/Makefile.in
new file mode 100644
index 0000000..3223292
--- /dev/null
+++ b/plugins/group_file/Makefile.in
@@ -0,0 +1,234 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2010-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+devdir = @devdir@
+scriptdir = $(top_srcdir)/scripts
+incdir = $(top_srcdir)/include
+cross_compiling = @CROSS_COMPILING@
+
+# Compiler & tools to use
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+SED = @SED@
+AWK = @AWK@
+
+# Our install program supports extra flags...
+INSTALL = $(SHELL) $(scriptdir)/install-sh -c
+INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
+INSTALL_BACKUP = @INSTALL_BACKUP@
+
+# Libraries
+LT_LIBS = $(top_builddir)/lib/util/libsudo_util.la
+LIBS = $(LT_LIBS)
+
+# C preprocessor flags
+CPPFLAGS = -I$(incdir) -I$(top_builddir) @CPPFLAGS@
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+
+# Flags to pass to the link stage
+LDFLAGS = @LDFLAGS@
+LT_LDFLAGS = @LT_LDFLAGS@ @LT_LDEXPORTS@
+
+# Flags to pass to libtool
+LTFLAGS = --tag=disable-static
+
+# Address sanitizer flags
+ASAN_CFLAGS = @ASAN_CFLAGS@
+ASAN_LDFLAGS = @ASAN_LDFLAGS@
+
+# PIE flags
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+
+# Stack smashing protection flags
+HARDENING_CFLAGS = @HARDENING_CFLAGS@
+HARDENING_LDFLAGS = @HARDENING_LDFLAGS@
+
+# cppcheck options, usually set in the top-level Makefile
+CPPCHECK_OPTS = -q --enable=warning,performance,portability --suppress=constStatement --suppress=compareBoolExpressionWithInt --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
+
+# splint options, usually set in the top-level Makefile
+SPLINT_OPTS = -D__restrict= -checks
+
+# PVS-studio options
+PVS_CFG = $(top_srcdir)/PVS-Studio.cfg
+PVS_IGNORE = 'V707,V011,V002,V536'
+PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
+
+# Where to install things...
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+sysconfdir = @sysconfdir@
+adminconfdir = @adminconfdir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+localstatedir = @localstatedir@
+plugindir = @plugindir@
+
+# File mode and map file to use for shared libraries/objects
+shlib_enable = @SHLIB_ENABLE@
+shlib_mode = @SHLIB_MODE@
+shlib_exp = $(srcdir)/group_file.exp
+shlib_map = group_file.map
+shlib_opt = group_file.opt
+
+# User and group ids the installed files should be "owned" by
+install_uid = 0
+install_gid = 0
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+OBJS = group_file.lo getgrent.lo
+
+IOBJS = $(OBJS:.lo=.i)
+
+POBJS = $(IOBJS:.i=.plog)
+
+LIBOBJDIR = $(top_builddir)/@ac_config_libobj_dir@/
+
+VERSION = @PACKAGE_VERSION@
+
+all: group_file.la
+
+depend:
+ $(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
+ --builddir=$(abs_top_builddir) plugins/group_file/Makefile.in
+ cd $(top_builddir) && ./config.status --file plugins/group_file/Makefile
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file plugins/group_file/Makefile
+
+.SUFFIXES: .c .h .i .lo .plog
+
+.c.lo:
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.i:
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+
+.i.plog:
+ ifile=$<; rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $${ifile%i}c --i-file $< --output-file $@
+
+$(shlib_map): $(shlib_exp)
+ @$(AWK) 'BEGIN { print "{\n\tglobal:" } { print "\t\t"$$0";" } END { print "\tlocal:\n\t\t*;\n};" }' $(shlib_exp) > $@
+
+$(shlib_opt): $(shlib_exp)
+ @$(SED) 's/^/+e /' $(shlib_exp) > $@
+
+group_file.la: $(OBJS) $(LT_LIBS) @LT_LDDEP@
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) $(ASAN_LDFLAGS) $(HARDENING_LDFLAGS) $(LT_LDFLAGS) -o $@ $(OBJS) $(LIBS) -module -avoid-version -rpath $(plugindir) -shrext .so
+
+pre-install:
+
+install: install-plugin
+
+install-dirs:
+ $(SHELL) $(scriptdir)/mkinstalldirs $(DESTDIR)$(plugindir)
+
+install-binaries:
+
+install-includes:
+
+install-doc:
+
+install-plugin: install-dirs group_file.la
+ if [ X"$(shlib_enable)" = X"yes" ]; then \
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) $(INSTALL_OWNER) -m $(shlib_mode) group_file.la $(DESTDIR)$(plugindir); \
+ fi
+
+install-fuzzer:
+
+uninstall:
+ -$(LIBTOOL) $(LTFLAGS) --mode=uninstall rm -f $(DESTDIR)$(plugindir)/group_file.la
+ -test -z "$(INSTALL_BACKUP)" || \
+ rm -f $(DESTDIR)$(plugindir)/group_file.so$(INSTALL_BACKUP)
+
+splint:
+ splint $(SPLINT_OPTS) -I$(incdir) -I$(top_builddir) $(srcdir)/*.c
+
+cppcheck:
+ cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) $(srcdir)/*.c
+
+pvs-log-files: $(POBJS)
+
+pvs-studio: $(POBJS)
+ plog-converter $(PVS_LOG_OPTS) $(POBJS)
+
+fuzz:
+
+check-fuzzer:
+
+check: check-fuzzer
+
+check-verbose: check
+
+clean:
+ -$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f *.lo *.o *.la
+ -rm -f *.i *.plog stamp-* core *.core core.*
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile .libs $(shlib_map) $(shlib_opt)
+
+clobber: distclean
+
+realclean: distclean
+ rm -f TAGS tags
+
+cleandir: realclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean
+
+# Autogenerated dependencies, do not modify
+getgrent.lo: $(srcdir)/getgrent.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/getgrent.c
+getgrent.i: $(srcdir)/getgrent.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+getgrent.plog: getgrent.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/getgrent.c --i-file $< --output-file $@
+group_file.lo: $(srcdir)/group_file.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_plugin.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/group_file.c
+group_file.i: $(srcdir)/group_file.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_plugin.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+group_file.plog: group_file.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/group_file.c --i-file $< --output-file $@
diff --git a/plugins/group_file/getgrent.c b/plugins/group_file/getgrent.c
new file mode 100644
index 0000000..031aed5
--- /dev/null
+++ b/plugins/group_file/getgrent.c
@@ -0,0 +1,193 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2005,2008,2010-2015,2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+/*
+ * Trivial replacements for the libc getgrent() family of functions.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <grp.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+#undef GRMEM_MAX
+#define GRMEM_MAX 200
+
+static FILE *grf;
+static const char *grfile = "/etc/group";
+static int gr_stayopen;
+
+void mysetgrfile(const char *);
+void mysetgrent(void);
+void myendgrent(void);
+int mysetgroupent(int);
+struct group *mygetgrent(void);
+struct group *mygetgrnam(const char *);
+struct group *mygetgrgid(gid_t);
+
+void
+mysetgrfile(const char *file)
+{
+ grfile = file;
+ if (grf != NULL)
+ myendgrent();
+}
+
+static int
+open_group(int reset)
+{
+ if (grf == NULL) {
+ grf = fopen(grfile, "r");
+ if (grf != NULL) {
+ if (fcntl(fileno(grf), F_SETFD, FD_CLOEXEC) == -1) {
+ fclose(grf);
+ grf = NULL;
+ }
+ }
+ if (grf == NULL)
+ return 0;
+ } else if (reset) {
+ rewind(grf);
+ }
+ return 1;
+}
+
+int
+mysetgroupent(int stayopen)
+{
+ if (!open_group(1))
+ return 0;
+ gr_stayopen = stayopen;
+ return 1;
+}
+
+void
+mysetgrent(void)
+{
+ mysetgroupent(0);
+}
+
+void
+myendgrent(void)
+{
+ if (grf != NULL) {
+ fclose(grf);
+ grf = NULL;
+ }
+ gr_stayopen = 0;
+}
+
+struct group *
+mygetgrent(void)
+{
+ static struct group gr;
+ static char grbuf[LINE_MAX], *gr_mem[GRMEM_MAX+1];
+ size_t len;
+ id_t id;
+ char *cp, *colon;
+ const char *errstr;
+ int n;
+
+ if (!open_group(0))
+ return NULL;
+
+next_entry:
+ if ((colon = fgets(grbuf, sizeof(grbuf), grf)) == NULL)
+ return NULL;
+
+ memset(&gr, 0, sizeof(gr));
+ if ((colon = strchr(cp = colon, ':')) == NULL)
+ goto next_entry;
+ *colon++ = '\0';
+ gr.gr_name = cp;
+ if ((colon = strchr(cp = colon, ':')) == NULL)
+ goto next_entry;
+ *colon++ = '\0';
+ gr.gr_passwd = cp;
+ if ((colon = strchr(cp = colon, ':')) == NULL)
+ goto next_entry;
+ *colon++ = '\0';
+ id = sudo_strtoid(cp, &errstr);
+ if (errstr != NULL)
+ goto next_entry;
+ gr.gr_gid = (gid_t)id;
+ len = strlen(colon);
+ if (len > 0 && colon[len - 1] == '\n')
+ colon[len - 1] = '\0';
+ if (*colon != '\0') {
+ char *last;
+
+ gr.gr_mem = gr_mem;
+ cp = strtok_r(colon, ",", &last);
+ for (n = 0; cp != NULL && n < GRMEM_MAX; n++) {
+ gr.gr_mem[n] = cp;
+ cp = strtok_r(NULL, ",", &last);
+ }
+ gr.gr_mem[n] = NULL;
+ } else
+ gr.gr_mem = NULL;
+ return &gr;
+}
+
+struct group *
+mygetgrnam(const char *name)
+{
+ struct group *gr;
+
+ if (!open_group(1))
+ return NULL;
+ while ((gr = mygetgrent()) != NULL) {
+ if (strcmp(gr->gr_name, name) == 0)
+ break;
+ }
+ if (!gr_stayopen) {
+ fclose(grf);
+ grf = NULL;
+ }
+ return gr;
+}
+
+struct group *
+mygetgrgid(gid_t gid)
+{
+ struct group *gr;
+
+ if (!open_group(1))
+ return NULL;
+ while ((gr = mygetgrent()) != NULL) {
+ if (gr->gr_gid == gid)
+ break;
+ }
+ if (!gr_stayopen) {
+ fclose(grf);
+ grf = NULL;
+ }
+ return gr;
+}
diff --git a/plugins/group_file/group_file.c b/plugins/group_file/group_file.c
new file mode 100644
index 0000000..de9a491
--- /dev/null
+++ b/plugins/group_file/group_file.c
@@ -0,0 +1,129 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2014 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+
+#include <sudo_plugin.h>
+#include <sudo_compat.h>
+
+/*
+ * Sample sudoers group plugin that uses an extra group file with the
+ * same format as /etc/group.
+ */
+
+static sudo_printf_t sudo_log;
+
+extern void mysetgrfile(const char *);
+extern int mysetgroupent(int);
+extern void myendgrent(void);
+extern struct group *mygetgrnam(const char *);
+
+static int
+sample_init(int version, sudo_printf_t sudo_printf, char *const argv[])
+{
+ struct stat sb;
+
+ sudo_log = sudo_printf;
+
+ if (SUDO_API_VERSION_GET_MAJOR(version) != GROUP_API_VERSION_MAJOR) {
+ sudo_log(SUDO_CONV_ERROR_MSG,
+ "group_file: incompatible major version %d, expected %d\n",
+ SUDO_API_VERSION_GET_MAJOR(version),
+ GROUP_API_VERSION_MAJOR);
+ return -1;
+ }
+
+ /* Check that the group file exists and has a safe mode. */
+ if (argv == NULL || argv[0] == NULL) {
+ sudo_log(SUDO_CONV_ERROR_MSG,
+ "group_file: path to group file not specified\n");
+ return -1;
+ }
+ if (stat(argv[0], &sb) != 0) {
+ sudo_log(SUDO_CONV_ERROR_MSG,
+ "group_file: %s: %s\n", argv[0], strerror(errno));
+ return -1;
+ }
+ if ((sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+ sudo_log(SUDO_CONV_ERROR_MSG,
+ "%s must be only be writable by owner\n", argv[0]);
+ return -1;
+ }
+
+ mysetgrfile(argv[0]);
+ if (!mysetgroupent(1))
+ return false;
+
+ return true;
+}
+
+static void
+sample_cleanup(void)
+{
+ myendgrent();
+}
+
+/*
+ * Returns true if "user" is a member of "group", else false.
+ */
+static int
+sample_query(const char *user, const char *group, const struct passwd *pwd)
+{
+ struct group *grp;
+ char **member;
+
+ grp = mygetgrnam(group);
+ if (grp != NULL && grp->gr_mem != NULL) {
+ for (member = grp->gr_mem; *member != NULL; member++) {
+ if (strcasecmp(user, *member) == 0)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+sudo_dso_public struct sudoers_group_plugin group_plugin = {
+ GROUP_API_VERSION,
+ sample_init,
+ sample_cleanup,
+ sample_query
+};
diff --git a/plugins/group_file/group_file.exp b/plugins/group_file/group_file.exp
new file mode 100644
index 0000000..a859d6c
--- /dev/null
+++ b/plugins/group_file/group_file.exp
@@ -0,0 +1 @@
+group_plugin
diff --git a/plugins/group_file/plugin_test.c b/plugins/group_file/plugin_test.c
new file mode 100644
index 0000000..ec47f73
--- /dev/null
+++ b/plugins/group_file/plugin_test.c
@@ -0,0 +1,222 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2013 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+#include <ctype.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sudo_plugin.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/*
+ * Simple driver to test sudoer group plugins.
+ * usage: plugin_test [-p "plugin.so plugin_args ..."] user:group ...
+ */
+
+static void *group_handle;
+static struct sudoers_group_plugin *group_plugin;
+
+static int
+plugin_printf(int msg_type, const char * restrict fmt, ...)
+{
+ va_list ap;
+ FILE *fp;
+
+ switch (msg_type) {
+ case SUDO_CONV_INFO_MSG:
+ fp = stdout;
+ break;
+ case SUDO_CONV_ERROR_MSG:
+ fp = stderr;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ va_start(ap, fmt);
+ vfprintf(fp, fmt, ap);
+ va_end(ap);
+
+ return 0;
+}
+
+/*
+ * Load the specified plugin and run its init function.
+ * Returns -1 if unable to open the plugin, else it returns
+ * the value from the plugin's init function.
+ */
+static int
+group_plugin_load(char *plugin_info)
+{
+ char *args, path[PATH_MAX], savedch;
+ char **argv = NULL;
+ int rc;
+
+ /*
+ * Fill in .so path and split out args (if any).
+ */
+ if ((args = strpbrk(plugin_info, " \t")) != NULL) {
+ savedch = *args;
+ *args = '\0';
+ }
+ if (strlcpy(path, plugin_info, sizeof(path)) >= sizeof(path)) {
+ fprintf(stderr, "path too long: %s\n", plugin_info);
+ return -1;
+ }
+ if (args != NULL)
+ *args++ = savedch;
+
+ /* Open plugin and map in symbol. */
+ group_handle = dlopen(path, RTLD_LAZY);
+ if (!group_handle) {
+ fprintf(stderr, "unable to dlopen %s: %s\n", path, dlerror());
+ return -1;
+ }
+ group_plugin = dlsym(group_handle, "group_plugin");
+ if (group_plugin == NULL) {
+ fprintf(stderr, "unable to find symbol \"group_plugin\" in %s\n", path);
+ return -1;
+ }
+
+ if (SUDO_API_VERSION_GET_MAJOR(group_plugin->version) != GROUP_API_VERSION_MAJOR) {
+ fprintf(stderr,
+ "%s: incompatible group plugin major version %u, expected %u\n",
+ path, SUDO_API_VERSION_GET_MAJOR(group_plugin->version),
+ GROUP_API_VERSION_MAJOR);
+ return -1;
+ }
+
+ /*
+ * Split args into a vector if specified.
+ */
+ if (args != NULL) {
+ int ac = 0, wasblank = 1;
+ char *cp, *last;
+
+ for (cp = args; *cp != '\0'; cp++) {
+ if (isblank((unsigned char)*cp)) {
+ wasblank = 1;
+ } else if (wasblank) {
+ wasblank = 0;
+ ac++;
+ }
+ }
+ if (ac != 0) {
+ argv = malloc((ac + 1) * sizeof(char *));
+ if (argv == NULL) {
+ perror(NULL);
+ return -1;
+ }
+ ac = 0;
+ cp = strtok_r(args, " \t", &last);
+ while (cp != NULL) {
+ argv[ac++] = cp;
+ cp = strtok_r(NULL, " \t", &last);
+ }
+ argv[ac] = NULL;
+ }
+ }
+
+ rc = (group_plugin->init)(GROUP_API_VERSION, plugin_printf, argv);
+
+ free(argv);
+
+ return rc;
+}
+
+static void
+group_plugin_unload(void)
+{
+ (group_plugin->cleanup)();
+ dlclose(group_handle);
+ group_handle = NULL;
+}
+
+static int
+group_plugin_query(const char *user, const char *group,
+ const struct passwd *pwd)
+{
+ return (group_plugin->query)(user, group, pwd);
+}
+
+static void
+usage(void)
+{
+ fputs("usage: plugin_test [-p \"plugin.so plugin_args ...\"] user:group ...\n",
+ stderr);
+ exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch, found;
+ size_t i;
+ char *plugin = "group_file.so";
+ char *user, *group;
+ struct passwd *pwd;
+
+ while ((ch = getopt(argc, argv, "p:")) != -1) {
+ switch (ch) {
+ case 'p':
+ plugin = optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1)
+ usage();
+
+ if (group_plugin_load(plugin) != 1) {
+ fprintf(stderr, "unable to load plugin: %s\n", plugin);
+ return EXIT_FAILURE;
+ }
+
+ for (i = 0; argv[i] != NULL; i++) {
+ user = argv[i];
+ group = strchr(argv[i], ':');
+ if (group == NULL)
+ continue;
+ *group++ = '\0';
+ pwd = getpwnam(user);
+ found = group_plugin_query(user, group, pwd);
+ printf("user %s %s in group %s\n", user, found ? "is" : "NOT ", group);
+ }
+ group_plugin_unload();
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/plugins/python/Makefile.in b/plugins/python/Makefile.in
new file mode 100644
index 0000000..423aed4
--- /dev/null
+++ b/plugins/python/Makefile.in
@@ -0,0 +1,540 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2019-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+devdir = @devdir@
+scriptdir = $(top_srcdir)/scripts
+incdir = $(top_srcdir)/include
+cross_compiling = @CROSS_COMPILING@
+
+# Compiler & tools to use
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+EGREP = @EGREP@
+SED = @SED@
+AWK = @AWK@
+
+# Our install program supports extra flags...
+INSTALL = $(SHELL) $(scriptdir)/install-sh -c
+INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
+INSTALL_BACKUP = @INSTALL_BACKUP@
+
+# Libraries
+LT_LIBS = $(top_builddir)/lib/util/libsudo_util.la
+LIBS = $(LT_LIBS)
+
+LIBPYTHONPLUGIN = python_plugin.la
+
+# C preprocessor flags
+CPPFLAGS = -I$(incdir) -I$(top_builddir) -I$(top_srcdir) -DPLUGIN_DIR=\"$(plugindir)\" -DSRC_DIR=\"$(abs_srcdir)\" @CPPFLAGS@ @PYTHON_INCLUDE@
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+
+# Flags to pass to the link stage
+LDFLAGS = @LDFLAGS@ @PYTHON_LIBS@
+LT_LDFLAGS = @LT_LDFLAGS@ @LT_LDEXPORTS@
+
+# Flags to pass to libtool
+LTFLAGS = --tag=disable-static
+
+# Address sanitizer flags
+ASAN_CFLAGS = @ASAN_CFLAGS@
+ASAN_LDFLAGS = @ASAN_LDFLAGS@
+
+# PIE flags
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+
+# Stack smashing protection flags
+HARDENING_CFLAGS = @HARDENING_CFLAGS@
+HARDENING_LDFLAGS = @HARDENING_LDFLAGS@
+
+# cppcheck options, usually set in the top-level Makefile
+CPPCHECK_OPTS = -q --enable=warning,performance,portability --suppress=constStatement --suppress=compareBoolExpressionWithInt --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
+
+# splint options, usually set in the top-level Makefile
+SPLINT_OPTS = -D__restrict= -checks
+
+# PVS-studio options
+PVS_CFG = $(top_srcdir)/PVS-Studio.cfg
+PVS_IGNORE = 'V707,V011,V002,V536'
+PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
+
+# Where to install things...
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+sysconfdir = @sysconfdir@
+adminconfdir = @adminconfdir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+localstatedir = @localstatedir@
+plugindir = @plugindir@
+docdir = @docdir@
+exampledir = @exampledir@
+
+# File mode and map file to use for shared libraries/objects
+shlib_enable = @SHLIB_ENABLE@
+shlib_mode = @SHLIB_MODE@
+shlib_exp = $(srcdir)/python_plugin.exp
+shlib_map = python_plugin.map
+shlib_opt = python_plugin.opt
+
+# User and group ids the installed files should be "owned" by
+install_uid = 0
+install_gid = 0
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+EXAMPLES = example_approval_plugin.py example_audit_plugin.py \
+ example_conversation.py example_debugging.py \
+ example_group_plugin.py example_io_plugin.py example_policy_plugin.py
+
+OBJS = python_plugin_common.lo python_plugin_policy.lo python_plugin_io.lo \
+ python_plugin_group.lo pyhelpers.lo python_loghandler.lo \
+ python_convmessage.lo sudo_python_module.lo sudo_python_debug.lo \
+ python_baseplugin.lo python_plugin_audit.lo python_plugin_approval.lo
+
+IOBJS = $(OBJS:.lo=.i)
+
+POBJS = $(IOBJS:.i=.plog)
+
+LIBOBJDIR = $(top_builddir)/@ac_config_libobj_dir@/
+
+VERSION = @PACKAGE_VERSION@
+
+TEST_PROGS = check_python_examples
+TEST_VERBOSE =
+
+CHECK_PYTHON_EXAMPLES_OBJS = check_python_examples.o iohelpers.o testhelpers.o pyhelpers.o sudo_python_debug.o
+
+all: python_plugin.la
+
+depend:
+ $(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
+ --builddir=$(abs_top_builddir) plugins/python/Makefile.in
+ cd $(top_builddir) && ./config.status --file plugins/python/Makefile
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file plugins/python/Makefile
+
+.SUFFIXES: .c .h .i .lo .plog .o
+
+.c.o:
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.lo:
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.i:
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+
+.i.plog:
+ ifile=$<; rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $${ifile%i}c --i-file $< --output-file $@
+
+$(shlib_map): $(shlib_exp)
+ @$(AWK) 'BEGIN { print "{\n\tglobal:" } { print "\t\t"$$0";" } END { print "\tlocal:\n\t\t*;\n};" }' $(shlib_exp) > $@
+
+$(shlib_opt): $(shlib_exp)
+ @$(SED) 's/^/+e /' $(shlib_exp) > $@
+
+python_plugin.la: $(OBJS) $(LT_LIBS) @LT_LDDEP@
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) $(ASAN_LDFLAGS) $(HARDENING_LDFLAGS) $(LT_LDFLAGS) -o $@ $(OBJS) $(LIBS) -module -avoid-version -rpath $(plugindir) -shrext .so
+
+pre-install:
+
+install: install-plugin install-doc
+
+install-dirs:
+ $(SHELL) $(scriptdir)/mkinstalldirs $(DESTDIR)$(plugindir) $(DESTDIR)$(exampledir)
+
+install-binaries:
+
+install-includes:
+
+install-doc: install-dirs
+ for f in $(EXAMPLES); do $(INSTALL) $(INSTALL_OWNER) -m 0644 $(srcdir)/$$f $(DESTDIR)$(exampledir); done
+
+install-plugin: install-dirs python_plugin.la
+ if [ X"$(shlib_enable)" = X"yes" ]; then \
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) $(INSTALL_OWNER) -m $(shlib_mode) python_plugin.la $(DESTDIR)$(plugindir); \
+ fi
+
+install-fuzzer:
+
+uninstall:
+ -$(LIBTOOL) $(LTFLAGS) --mode=uninstall rm -f $(DESTDIR)$(plugindir)/python_plugin.la
+ -test -z "$(INSTALL_BACKUP)" || \
+ rm -f $(DESTDIR)$(plugindir)/python_plugin.so$(INSTALL_BACKUP)
+
+splint:
+ splint $(SPLINT_OPTS) -I$(incdir) -I$(top_builddir) -I$(top_srcdir) $(srcdir)/*.c
+
+cppcheck:
+ cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) -I$(top_srcdir) $(srcdir)/*.c
+
+pvs-log-files: $(POBJS)
+
+pvs-studio: $(POBJS)
+ plog-converter $(PVS_LOG_OPTS) $(POBJS)
+
+clean:
+ -$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f *.lo *.o *.la
+ -rm -f *.i *.plog stamp-* core *.core core.* $(TEST_PROGS)
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile .libs $(shlib_map) $(shlib_opt)
+
+clobber: distclean
+
+realclean: distclean
+ rm -f TAGS tags
+
+cleandir: realclean
+
+fuzz:
+
+check-fuzzer:
+
+check: $(TEST_PROGS) check-fuzzer
+ @if test X"$(cross_compiling)" != X"yes"; then \
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ LSAN_OPTIONS=suppressions=$(srcdir)/lsan_suppr.txt \
+ ./check_python_examples $(TEST_VERBOSE) \
+ ".libs/python_plugin.so"; \
+ fi
+
+check-verbose:
+ exec $(MAKE) $(MFLAGS) TEST_VERBOSE=-v FUZZ_VERBOSE=-verbosity=1 check
+
+update_test_data: $(TEST_PROGS)
+ @if test X"$(cross_compiling)" != X"yes"; then \
+ UPDATE_TESTDATA=1 ./check_python_examples ".libs/python_plugin.so"; \
+ fi
+
+check_python_examples: $(CHECK_PYTHON_EXAMPLES_OBJS) $(LIBPYTHONPLUGIN)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_PYTHON_EXAMPLES_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS)
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean
+
+# Autogenerated dependencies, do not modify
+check_python_examples.o: $(srcdir)/regress/check_python_examples.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_dso.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/regress/iohelpers.h \
+ $(srcdir)/regress/testhelpers.h \
+ $(srcdir)/sudo_python_debug.h $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/check_python_examples.c
+check_python_examples.i: $(srcdir)/regress/check_python_examples.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_dso.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/regress/iohelpers.h \
+ $(srcdir)/regress/testhelpers.h \
+ $(srcdir)/sudo_python_debug.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_python_examples.plog: check_python_examples.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/check_python_examples.c --i-file $< --output-file $@
+iohelpers.o: $(srcdir)/regress/iohelpers.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(srcdir)/regress/iohelpers.h \
+ $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/iohelpers.c
+iohelpers.i: $(srcdir)/regress/iohelpers.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(srcdir)/regress/iohelpers.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iohelpers.plog: iohelpers.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/iohelpers.c --i-file $< --output-file $@
+pyhelpers.lo: $(srcdir)/pyhelpers.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(srcdir)/pyhelpers.h $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/sudo_python_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/pyhelpers.c
+pyhelpers.i: $(srcdir)/pyhelpers.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(srcdir)/pyhelpers.h $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/sudo_python_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+pyhelpers.plog: pyhelpers.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/pyhelpers.c --i-file $< --output-file $@
+pyhelpers.o: $(srcdir)/pyhelpers.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(srcdir)/pyhelpers.h $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/sudo_python_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/pyhelpers.c
+python_baseplugin.lo: $(srcdir)/python_baseplugin.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(srcdir)/pyhelpers.h $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/sudo_python_debug.h \
+ $(srcdir)/sudo_python_module.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/python_baseplugin.c
+python_baseplugin.i: $(srcdir)/python_baseplugin.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(srcdir)/pyhelpers.h $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/sudo_python_debug.h \
+ $(srcdir)/sudo_python_module.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+python_baseplugin.plog: python_baseplugin.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/python_baseplugin.c --i-file $< --output-file $@
+python_convmessage.lo: $(srcdir)/python_convmessage.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/sudo_python_debug.h \
+ $(srcdir)/sudo_python_module.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/python_convmessage.c
+python_convmessage.i: $(srcdir)/python_convmessage.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/sudo_python_debug.h \
+ $(srcdir)/sudo_python_module.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+python_convmessage.plog: python_convmessage.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/python_convmessage.c --i-file $< --output-file $@
+python_loghandler.lo: $(srcdir)/python_loghandler.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(srcdir)/pyhelpers.h $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/sudo_python_debug.h \
+ $(srcdir)/sudo_python_module.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/python_loghandler.c
+python_loghandler.i: $(srcdir)/python_loghandler.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(srcdir)/pyhelpers.h $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/sudo_python_debug.h \
+ $(srcdir)/sudo_python_module.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+python_loghandler.plog: python_loghandler.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/python_loghandler.c --i-file $< --output-file $@
+python_plugin_approval.lo: $(srcdir)/python_plugin_approval.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/python_plugin_approval_multi.inc \
+ $(srcdir)/python_plugin_common.h \
+ $(srcdir)/sudo_python_debug.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/python_plugin_approval.c
+python_plugin_approval.i: $(srcdir)/python_plugin_approval.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/python_plugin_approval_multi.inc \
+ $(srcdir)/python_plugin_common.h \
+ $(srcdir)/sudo_python_debug.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+python_plugin_approval.plog: python_plugin_approval.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/python_plugin_approval.c --i-file $< --output-file $@
+python_plugin_audit.lo: $(srcdir)/python_plugin_audit.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/python_plugin_audit_multi.inc \
+ $(srcdir)/python_plugin_common.h \
+ $(srcdir)/sudo_python_debug.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/python_plugin_audit.c
+python_plugin_audit.i: $(srcdir)/python_plugin_audit.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/python_plugin_audit_multi.inc \
+ $(srcdir)/python_plugin_common.h \
+ $(srcdir)/sudo_python_debug.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+python_plugin_audit.plog: python_plugin_audit.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/python_plugin_audit.c --i-file $< --output-file $@
+python_plugin_common.lo: $(srcdir)/python_plugin_common.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/python_plugin_common.h \
+ $(srcdir)/sudo_python_debug.h \
+ $(srcdir)/sudo_python_module.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/python_plugin_common.c
+python_plugin_common.i: $(srcdir)/python_plugin_common.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/python_plugin_common.h \
+ $(srcdir)/sudo_python_debug.h \
+ $(srcdir)/sudo_python_module.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+python_plugin_common.plog: python_plugin_common.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/python_plugin_common.c --i-file $< --output-file $@
+python_plugin_group.lo: $(srcdir)/python_plugin_group.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/python_plugin_common.h \
+ $(srcdir)/sudo_python_debug.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/python_plugin_group.c
+python_plugin_group.i: $(srcdir)/python_plugin_group.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/python_plugin_common.h \
+ $(srcdir)/sudo_python_debug.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+python_plugin_group.plog: python_plugin_group.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/python_plugin_group.c --i-file $< --output-file $@
+python_plugin_io.lo: $(srcdir)/python_plugin_io.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(srcdir)/pyhelpers.h $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/python_plugin_common.h \
+ $(srcdir)/python_plugin_io_multi.inc \
+ $(srcdir)/sudo_python_debug.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/python_plugin_io.c
+python_plugin_io.i: $(srcdir)/python_plugin_io.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(srcdir)/pyhelpers.h $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/python_plugin_common.h \
+ $(srcdir)/python_plugin_io_multi.inc \
+ $(srcdir)/sudo_python_debug.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+python_plugin_io.plog: python_plugin_io.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/python_plugin_io.c --i-file $< --output-file $@
+python_plugin_policy.lo: $(srcdir)/python_plugin_policy.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/python_plugin_common.h \
+ $(srcdir)/sudo_python_debug.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/python_plugin_policy.c
+python_plugin_policy.i: $(srcdir)/python_plugin_policy.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/python_plugin_common.h \
+ $(srcdir)/sudo_python_debug.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+python_plugin_policy.plog: python_plugin_policy.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/python_plugin_policy.c --i-file $< --output-file $@
+sudo_python_debug.lo: $(srcdir)/sudo_python_debug.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/sudo_python_debug.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudo_python_debug.c
+sudo_python_debug.i: $(srcdir)/sudo_python_debug.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/sudo_python_debug.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudo_python_debug.plog: sudo_python_debug.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_python_debug.c --i-file $< --output-file $@
+sudo_python_debug.o: $(srcdir)/sudo_python_debug.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/sudo_python_debug.h \
+ $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudo_python_debug.c
+sudo_python_module.lo: $(srcdir)/sudo_python_module.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/sudo_python_debug.h \
+ $(srcdir)/sudo_python_module.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudo_python_module.c
+sudo_python_module.i: $(srcdir)/sudo_python_module.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h \
+ $(srcdir)/sudo_python_debug.h \
+ $(srcdir)/sudo_python_module.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudo_python_module.plog: sudo_python_module.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_python_module.c --i-file $< --output-file $@
+testhelpers.o: $(srcdir)/regress/testhelpers.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h $(srcdir)/regress/iohelpers.h \
+ $(srcdir)/regress/testhelpers.h $(srcdir)/sudo_python_debug.h \
+ $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/testhelpers.c
+testhelpers.i: $(srcdir)/regress/testhelpers.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/pyhelpers.h \
+ $(srcdir)/pyhelpers_cpychecker.h $(srcdir)/regress/iohelpers.h \
+ $(srcdir)/regress/testhelpers.h $(srcdir)/sudo_python_debug.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+testhelpers.plog: testhelpers.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/testhelpers.c --i-file $< --output-file $@
diff --git a/plugins/python/example_approval_plugin.py b/plugins/python/example_approval_plugin.py
new file mode 100644
index 0000000..56ac865
--- /dev/null
+++ b/plugins/python/example_approval_plugin.py
@@ -0,0 +1,18 @@
+import sudo
+
+from datetime import datetime
+
+
+class BusinessHoursApprovalPlugin(sudo.Plugin):
+ def check(self, command_info: tuple, run_argv: tuple,
+ run_env: tuple) -> int:
+ error_msg = ""
+ now = datetime.now()
+ if now.weekday() >= 5:
+ error_msg = "That is not allowed on the weekend!"
+ if now.hour < 8 or now.hour > 17:
+ error_msg = "That is not allowed outside the business hours!"
+
+ if error_msg:
+ sudo.log_info(error_msg)
+ raise sudo.PluginReject(error_msg)
diff --git a/plugins/python/example_audit_plugin.py b/plugins/python/example_audit_plugin.py
new file mode 100644
index 0000000..ede69c9
--- /dev/null
+++ b/plugins/python/example_audit_plugin.py
@@ -0,0 +1,84 @@
+import sudo
+
+import os
+
+
+VERSION = 1.0
+
+
+class SudoAuditPlugin(sudo.Plugin):
+ def __init__(self, plugin_options, user_info, **kwargs):
+ # For loading multiple times, an optional "Id" can be specified
+ # as argument to identify the log lines
+ plugin_id = sudo.options_as_dict(plugin_options).get("Id", "")
+ self._log_line_prefix = "(AUDIT{}) ".format(plugin_id)
+
+ user_info_dict = sudo.options_as_dict(user_info)
+ user = user_info_dict.get("user", "???")
+ uid = user_info_dict.get("uid", "???")
+ self._log("-- Started by user {} ({}) --".format(user, uid))
+
+ def __del__(self):
+ self._log("-- Finished --")
+
+ def open(self, submit_optind: int, submit_argv: tuple) -> int:
+ # To cut out the sudo options, use "submit_optind":
+ program_args = submit_argv[submit_optind:]
+ if program_args:
+ self._log("Requested command: " + " ".join(program_args))
+
+ def accept(self, plugin_name, plugin_type,
+ command_info, run_argv, run_envp) -> int:
+ info = sudo.options_as_dict(command_info)
+ cmd = list(run_argv)
+ cmd[0] = info.get("command")
+ self._log("Accepted command: {}".format(" ".join(cmd)))
+ self._log(" By the plugin: {} (type={})".format(
+ plugin_name, self.__plugin_type_str(plugin_type)))
+
+ self._log(" Environment: " + " ".join(run_envp))
+
+ def reject(self, plugin_name, plugin_type, audit_msg, command_info) -> int:
+ self._log("Rejected by plugin {} (type={}): {}".format(
+ plugin_name, self.__plugin_type_str(plugin_type), audit_msg))
+
+ def error(self, plugin_name, plugin_type, audit_msg, command_info) -> int:
+ self._log("Plugin {} (type={}) got an error: {}".format(
+ plugin_name, self.__plugin_type_str(plugin_type), audit_msg))
+
+ def close(self, status_kind: int, status: int) -> None:
+ if status_kind == sudo.EXIT_REASON.NO_STATUS:
+ self._log("The command was not executed")
+
+ elif status_kind == sudo.EXIT_REASON.WAIT_STATUS:
+ if os.WIFEXITED(status):
+ self._log("Command returned with exit code "
+ "{}".format(os.WEXITSTATUS(status)))
+ elif os.WIFSIGNALED(status):
+ self._log("Command exited due to signal "
+ "{}".format(os.WTERMSIG(status)))
+ else:
+ raise sudo.PluginError("Failed to understand wait exit status")
+
+ elif status_kind == sudo.EXIT_REASON.EXEC_ERROR:
+ self._log("Sudo has failed to execute the command, "
+ "execve returned {}".format(status))
+
+ elif status_kind == sudo.EXIT_REASON.SUDO_ERROR:
+ self._log("Sudo has run into an error: {}".format(status))
+
+ else:
+ raise Exception("Command returned unknown status kind {}".format(
+ status_kind))
+
+ def show_version(self, is_verbose: bool) -> int:
+ version_str = " (version=1.0)" if is_verbose else ""
+ sudo.log_info("Python Example Audit Plugin" + version_str)
+
+ def _log(self, string):
+ # For the example, we just log to output (this could be a file)
+ sudo.log_info(self._log_line_prefix, string)
+
+ @staticmethod
+ def __plugin_type_str(plugin_type):
+ return sudo.PLUGIN_TYPE(plugin_type).name
diff --git a/plugins/python/example_conversation.py b/plugins/python/example_conversation.py
new file mode 100644
index 0000000..8e68d36
--- /dev/null
+++ b/plugins/python/example_conversation.py
@@ -0,0 +1,98 @@
+import sudo
+import signal
+from os import path
+
+
+class ReasonLoggerIOPlugin(sudo.Plugin):
+ """
+ An example sudo plugin demonstrating how to use the sudo conversation API.
+
+ From the python plugin, you can ask something from the user using the
+ "sudo.conv" function. It expects one or more "sudo.ConvMessage" instances
+ which specifies how the interaction has to look like.
+
+ sudo.ConvMessage has the following fields (see help(sudo.ConvMessage)):
+ msg_type: int Specifies the type of the conversation.
+ See sudo.CONV.* constants below.
+ timeout: int The maximum amount of time for the conversation
+ in seconds. After the timeout exceeds, the "sudo.conv"
+ function will raise sudo.ConversationInterrupted
+ exception.
+ msg: str The message to display for the user.
+
+ To specify the conversion type you can use the following constants:
+ sudo.CONV.PROMPT_ECHO_OFF
+ sudo.CONV.PROMPT_ECHO_ON
+ sudo.CONV.ERROR_MSG
+ sudo.CONV.INFO_MSG
+ sudo.CONV.PROMPT_MASK
+ sudo.CONV.PROMPT_ECHO_OK
+ sudo.CONV.PREFER_TTY
+ """
+
+ def open(self, argv, command_info):
+ try:
+ conv_timeout = 120 # in seconds
+ sudo.log_info("Please provide your reason "
+ "for executing {}".format(argv))
+
+ # We ask two questions, the second is not visible on screen,
+ # so the user can hide a hidden message in case of criminals are
+ # forcing him for running the command.
+ # You can either specify the arguments in strict order (timeout
+ # being optional), or use named arguments.
+ message1 = sudo.ConvMessage(sudo.CONV.PROMPT_ECHO_ON,
+ "Reason: ",
+ conv_timeout)
+ message2 = sudo.ConvMessage(msg="Secret reason: ",
+ timeout=conv_timeout,
+ msg_type=sudo.CONV.PROMPT_MASK)
+ reply1, reply2 = sudo.conv(message1, message2,
+ on_suspend=self.on_conversation_suspend,
+ on_resume=self.on_conversation_resume)
+
+ with open(self._log_file_path(), "a") as file:
+ print("Executed", ' '.join(argv), file=file)
+ print("Reason:", reply1, file=file)
+ print("Hidden reason:", reply2, file=file)
+
+ except sudo.ConversationInterrupted:
+ sudo.log_error("You did not answer in time")
+ return sudo.RC.REJECT
+
+ def on_conversation_suspend(self, signum):
+ # This is just an example of how to do something on conversation
+ # suspend. You can skip specifying 'on_suspend' argument if there
+ # is no need
+ sudo.log_info("conversation suspend: signal",
+ self._signal_name(signum))
+
+ def on_conversation_resume(self, signum):
+ # This is just an example of how to do something on conversation
+ # resume. You can skip specifying 'on_resume' argument if there
+ # is no need
+ sudo.log_info("conversation resume: signal was",
+ self._signal_name(signum))
+
+ # helper functions:
+ if hasattr(signal, "Signals"):
+ @classmethod
+ def _signal_name(cls, signum: int):
+ try:
+ return signal.Signals(signum).name
+ except Exception:
+ return "{}".format(signum)
+ else:
+ @classmethod
+ def _signal_name(cls, signum: int):
+ for n, v in sorted(signal.__dict__.items()):
+ if v != signum:
+ continue
+ if n.startswith("SIG") and not n.startswith("SIG_"):
+ return n
+ return "{}".format(signum)
+
+ def _log_file_path(self):
+ options_dict = sudo.options_as_dict(self.plugin_options)
+ log_path = options_dict.get("LogPath", "/tmp")
+ return path.join(log_path, "sudo_reasons.txt")
diff --git a/plugins/python/example_debugging.py b/plugins/python/example_debugging.py
new file mode 100644
index 0000000..01310c6
--- /dev/null
+++ b/plugins/python/example_debugging.py
@@ -0,0 +1,85 @@
+import sudo
+
+import logging
+
+
+class DebugDemoPlugin(sudo.Plugin):
+ """
+ An example sudo plugin demonstrating the debugging capabilities.
+
+ You can install it as an extra IO plugin for example by adding the
+ following line to sudo.conf:
+ Plugin python_io python_plugin.so \
+ ModulePath=<path>/example_debugging.py \
+ ClassName=DebugDemoPlugin
+
+ To see the plugin's debug output, use the following line in sudo.conf:
+ Debug python_plugin.so \
+ /var/log/sudo_python_debug plugin@trace,c_calls@trace
+ ^ ^-- the options for the logging
+ ^----- the output will be placed here
+
+ The options for the logging is in format of multiple "subsystem@level"
+ separated by commas (",").
+ The most interesting subsystems are:
+ plugin Shows each call of sudo.debug API in the log
+ - py_calls Logs whenever a C function calls into the python module.
+ (For example calling this __init__ function.)
+ c_calls Logs whenever python calls into a C sudo API function
+
+ You can also specify "all" as subsystem name to get the debug messages of
+ all subsystems.
+
+ Other subsystems available:
+ internal logs internal functions of the python language wrapper
+ sudo_cb logs when sudo calls into its plugin API
+ load logs python plugin loading / unloading
+
+ Log levels
+ crit sudo.DEBUG.CRIT --> only critical messages
+ err sudo.DEBUG.ERROR
+ warn sudo.DEBUG.WARN
+ notice sudo.DEBUG.NOTICE
+ diag sudo.DEBUG.DIAG
+ info sudo.DEBUG.INFO
+ trace sudo.DEBUG.TRACE
+ debug sudo.DEBUG.DEBUG --> very extreme verbose debugging
+
+ See the sudo.conf manual for more details ("man sudo.conf").
+
+ """
+
+ def __init__(self, plugin_options, **kwargs):
+ # Specify: "py_calls@info" debug option to show the call to this
+ # constructor and the arguments passed in
+
+ # Specifying "plugin@err" debug option will show this message
+ # (or any more verbose level)
+ sudo.debug(sudo.DEBUG.ERROR, "My demo purpose plugin shows "
+ "this ERROR level debug message")
+
+ # Specifying "plugin@info" debug option will show this message
+ # (or any more verbose level)
+ sudo.debug(sudo.DEBUG.INFO, "My demo purpose plugin shows "
+ "this INFO level debug message")
+
+ # You can also use python log system, because sudo sets its log handler
+ # on the root logger.
+ # Note that the level of python logging is separate than the one set in
+ # sudo.conf. If using the python logger, each will have effect.
+ logger = logging.getLogger()
+ logger.setLevel(logging.INFO)
+ logger.error("Python log system shows this ERROR level debug message")
+ logger.info("Python log system shows this INFO level debug message")
+
+ # If you raise the level to info or below, the call of the debug
+ # will also be logged.
+ # An example output you will see in the debug log file:
+ # Dec 5 15:19:19 sudo[123040] __init__ @ /.../example_debugging.py:54 debugs:
+ # Dec 5 15:19:19 sudo[123040] My demo purpose plugin shows this ERROR level debug message
+
+ # Specify: "c_calls@diag" debug option to show this call and its
+ # arguments. If you specify info debug level instead ("c_calls@info"),
+ # you will also see the python function and line from which you called
+ # the 'options_as_dict' function.
+ self.plugin_options = sudo.options_as_dict(plugin_options)
diff --git a/plugins/python/example_group_plugin.py b/plugins/python/example_group_plugin.py
new file mode 100644
index 0000000..bb53fdb
--- /dev/null
+++ b/plugins/python/example_group_plugin.py
@@ -0,0 +1,45 @@
+import sudo
+
+
+class SudoGroupPlugin(sudo.Plugin):
+ """Example sudo input/output plugin
+
+ Demonstrates how to use the sudo group plugin API. Typing annotations are
+ just here for the help on the syntax (requires python >= 3.5).
+
+ On detailed description of the functions refer to sudo_plugin manual (man
+ sudo_plugin).
+
+ Most functions can express error or reject through their "int" return value
+ as documented in the manual. The sudo module also has constants for these:
+ sudo.RC.ACCEPT / sudo.RC.OK 1
+ sudo.RC.REJECT 0
+ sudo.RC.ERROR -1
+ sudo.RC.USAGE_ERROR -2
+
+ If the plugin encounters an error, instead of just returning sudo.RC.ERROR
+ result code it can also add a message describing the problem.
+ This can be done by raising the special exception:
+ raise sudo.PluginError("Message")
+ This added message will be used by the audit plugins.
+
+ If the function returns "None" (for example does not call return), it will
+ be considered sudo.RC.OK. If an exception other than sudo.PluginError is
+ raised, its backtrace will be shown to the user and the plugin function
+ returns sudo.RC.ERROR. If that is not acceptable, catch it.
+ """
+
+ # -- Plugin API functions --
+ def query(self, user: str, group: str, user_pwd: tuple):
+ """Query if user is part of the specified group.
+
+ Beware that user_pwd can be None if user is not present in the password
+ database. Otherwise it is a tuple convertible to pwd.struct_passwd.
+ """
+ hardcoded_user_groups = {
+ "testgroup": ["testuser1", "testuser2"],
+ "mygroup": ["test"]
+ }
+
+ group_has_user = user in hardcoded_user_groups.get(group, [])
+ return sudo.RC.ACCEPT if group_has_user else sudo.RC.REJECT
diff --git a/plugins/python/example_io_plugin.py b/plugins/python/example_io_plugin.py
new file mode 100644
index 0000000..dc4c6a7
--- /dev/null
+++ b/plugins/python/example_io_plugin.py
@@ -0,0 +1,153 @@
+import sudo
+
+from os import path
+import errno
+import signal
+import sys
+import json
+
+
+VERSION = 1.0
+
+
+class SudoIOPlugin(sudo.Plugin):
+ """Example sudo input/output plugin
+
+ Demonstrates how to use the sudo IO plugin API. All functions are added as
+ an example on their syntax, but note that all of them are optional.
+
+ On detailed description of the functions refer to sudo_plugin manual (man
+ sudo_plugin).
+
+ Most functions can express error or reject through their "int" return value
+ as documented in the manual. The sudo module also has constants for these:
+ sudo.RC.ACCEPT / sudo.RC.OK 1
+ sudo.RC.REJECT 0
+ sudo.RC.ERROR -1
+ sudo.RC.USAGE_ERROR -2
+
+ If the plugin encounters an error, instead of just returning sudo.RC.ERROR
+ result code it can also add a message describing the problem.
+ This can be done by raising the special exception:
+ raise sudo.PluginError("Message")
+ This added message will be used by the audit plugins.
+
+ If the function returns "None" (for example does not call return), it will
+ be considered sudo.RC.OK. If an exception other than sudo.PluginError is
+ raised, its backtrace will be shown to the user and the plugin function
+ returns sudo.RC.ERROR. If that is not acceptable, catch it.
+ """
+
+ # -- Plugin API functions --
+
+ def __init__(self, version: str,
+ plugin_options: tuple, **kwargs):
+ """The constructor of the IO plugin.
+
+ Other variables you can currently use as arguments are:
+ user_env: tuple
+ settings: tuple
+ user_info: tuple
+
+ For their detailed description, see the open() call of the C plugin API
+ in the sudo manual ("man sudo").
+ """
+ if not version.startswith("1."):
+ raise sudo.SudoException(
+ "This plugin plugin is not compatible with python plugin"
+ "API version {}".format(version))
+
+ # convert tuple of "key=value"s to dict
+ plugin_options = sudo.options_as_dict(plugin_options)
+
+ log_path = plugin_options.get("LogPath", "/tmp")
+ self._open_log_file(path.join(log_path, "sudo.log"))
+ self._log("", "-- Plugin STARTED --")
+
+ def __del__(self):
+ if hasattr(self, "_log_file"):
+ self._log("", "-- Plugin DESTROYED --")
+ self._log_file.close()
+
+ def open(self, argv: tuple,
+ command_info: tuple) -> int:
+ """Receives the command the user wishes to run.
+
+ This function works the same as open() call of the C IO plugin API (see
+ sudo manual), except that:
+ - It only gets called before the user would execute some command (and
+ not for a version query for example).
+ - Other arguments of the C open() call are received through the
+ constructor.
+ """
+ self._log("EXEC", " ".join(argv))
+ self._log("EXEC info", json.dumps(command_info, indent=4))
+
+ return sudo.RC.ACCEPT
+
+ def log_ttyout(self, buf: str) -> int:
+ return self._log("TTY OUT", buf.strip())
+
+ def log_ttyin(self, buf: str) -> int:
+ return self._log("TTY IN", buf.strip())
+
+ def log_stdin(self, buf: str) -> int:
+ return self._log("STD IN", buf.strip())
+
+ def log_stdout(self, buf: str) -> int:
+ return self._log("STD OUT", buf.strip())
+
+ def log_stderr(self, buf: str) -> int:
+ return self._log("STD ERR", buf.strip())
+
+ def change_winsize(self, line: int, cols: int) -> int:
+ self._log("WINSIZE", "{}x{}".format(line, cols))
+
+ def log_suspend(self, signo: int) -> int:
+ signal_description = self._signal_name(signo)
+
+ self._log("SUSPEND", signal_description)
+
+ def show_version(self, is_verbose: int) -> int:
+ sudo.log_info("Python Example IO Plugin version: {}".format(VERSION))
+ if is_verbose:
+ sudo.log_info("Python interpreter version:", sys.version)
+
+ def close(self, exit_status: int, error: int) -> None:
+ """Called when a command execution finished.
+
+ Works the same as close() from C API (see sudo_plugin manual), except
+ that it only gets called if there was a command execution trial (open()
+ returned with sudo.RC.ACCEPT).
+ """
+ if error == 0:
+ self._log("CLOSE", "Command returned {}".format(exit_status))
+ else:
+ error_name = errno.errorcode.get(error, "???")
+ self._log("CLOSE", "Failed to execute, execve returned {} ({})"
+ .format(error, error_name))
+
+ # -- Helper functions --
+
+ def _open_log_file(self, log_path):
+ sudo.log_info("Example sudo python plugin will log to", log_path)
+ self._log_file = open(log_path, "a")
+
+ def _log(self, type, message):
+ print(type, message, file=self._log_file)
+ return sudo.RC.ACCEPT
+
+ if hasattr(signal, "Signals"):
+ def _signal_name(cls, signo: int):
+ try:
+ return signal.Signals(signo).name
+ except ValueError:
+ return "signal {}".format(signo)
+ else:
+ def _signal_name(cls, signo: int):
+ for n, v in sorted(signal.__dict__.items()):
+ if v != signo:
+ continue;
+ if n.startswith("SIG") and not n.startswith("SIG_"):
+ return n
+ return "signal {}".format(signo)
diff --git a/plugins/python/example_policy_plugin.py b/plugins/python/example_policy_plugin.py
new file mode 100644
index 0000000..dfb15ca
--- /dev/null
+++ b/plugins/python/example_policy_plugin.py
@@ -0,0 +1,172 @@
+import sudo
+
+import errno
+import sys
+import os
+import pwd
+import grp
+import shutil
+
+
+VERSION = 1.0
+
+
+class SudoPolicyPlugin(sudo.Plugin):
+ """Example sudo policy plugin
+
+ Demonstrates how to use the sudo policy plugin API. All functions are added
+ as an example on their syntax, but note that most of them are optional
+ (except check_policy).
+
+ On detailed description of the functions refer to sudo_plugin manual (man
+ sudo_plugin).
+
+ Most functions can express error or reject through their "int" return value
+ as documented in the manual. The sudo module also has constants for these:
+ sudo.RC.ACCEPT / sudo.RC.OK 1
+ sudo.RC.REJECT 0
+ sudo.RC.ERROR -1
+ sudo.RC.USAGE_ERROR -2
+
+ If the plugin encounters an error, instead of just returning sudo.RC.ERROR
+ result code it can also add a message describing the problem.
+ This can be done by raising the special exception:
+ raise sudo.PluginError("Message")
+ This added message will be used by the audit plugins.
+
+ If the function returns "None" (for example does not call return), it will
+ be considered sudo.RC.OK. If an exception other than sudo.PluginError is
+ raised, its backtrace will be shown to the user and the plugin function
+ returns sudo.RC.ERROR. If that is not acceptable, catch it.
+ """
+
+ _allowed_commands = ("id", "whoami")
+ _safe_password = "12345"
+
+ # -- Plugin API functions --
+
+ def __init__(self, user_env: tuple, settings: tuple,
+ version: str, **kwargs):
+ """The constructor matches the C sudo plugin API open() call
+
+ Other variables you can currently use as arguments are:
+ user_info: tuple
+ plugin_options: tuple
+
+ For their detailed description, see the open() call of the C plugin API
+ in the sudo manual ("man sudo").
+ """
+ if not version.startswith("1."):
+ raise sudo.PluginError(
+ "This plugin plugin is not compatible with python plugin"
+ "API version {}".format(version))
+
+ self.user_env = sudo.options_as_dict(user_env)
+ self.settings = sudo.options_as_dict(settings)
+
+ def check_policy(self, argv: tuple, env_add: tuple):
+ cmd = argv[0]
+ # Example for a simple reject:
+ if not self._is_command_allowed(cmd):
+ sudo.log_error("You are not allowed to run this command!")
+ return sudo.RC.REJECT
+
+ raise sudo.PluginError("You are not allowed to run this command!")
+
+ # The environment the command will be executed with (we allow any here)
+ user_env_out = sudo.options_from_dict(self.user_env) + env_add
+
+ command_info_out = sudo.options_from_dict({
+ "command": self._find_on_path(cmd), # Absolute path of command
+ "runas_uid": self._runas_uid(), # The user id
+ "runas_gid": self._runas_gid(), # The group id
+ })
+
+ return (sudo.RC.ACCEPT, command_info_out, argv, user_env_out)
+
+ def init_session(self, user_pwd: tuple, user_env: tuple):
+ """Perform session setup
+
+ Beware that user_pwd can be None if user is not present in the password
+ database. Otherwise it is a tuple convertible to pwd.struct_passwd.
+ """
+ # conversion example:
+ user_pwd = pwd.struct_passwd(user_pwd) if user_pwd else None
+
+ # This is how you change the user_env:
+ return (sudo.RC.OK, user_env + ("PLUGIN_EXAMPLE_ENV=1",))
+
+ # If you do not want to change user_env, you can just return (or None):
+ # return sudo.RC.OK
+
+ def list(self, argv: tuple, is_verbose: int, user: str):
+ cmd = argv[0] if argv else None
+ as_user_text = "as user '{}'".format(user) if user else ""
+
+ if cmd:
+ allowed_text = "" if self._is_command_allowed(cmd) else "NOT "
+ sudo.log_info("You are {}allowed to execute command '{}'{}"
+ .format(allowed_text, cmd, as_user_text))
+
+ if not cmd or is_verbose:
+ sudo.log_info("Only the following commands are allowed:",
+ ", ".join(self._allowed_commands), as_user_text)
+
+ def validate(self):
+ pass # we have no cache
+
+ def invalidate(self, remove: int):
+ pass # we have no cache
+
+ def show_version(self, is_verbose: int):
+ sudo.log_info("Python Example Policy Plugin "
+ "version: {}".format(VERSION))
+ if is_verbose:
+ sudo.log_info("Python interpreter version:", sys.version)
+
+ def close(self, exit_status: int, error: int) -> None:
+ if error == 0:
+ sudo.log_info("The command returned with exit_status {}".format(
+ exit_status))
+ else:
+ error_name = errno.errorcode.get(error, "???")
+ sudo.log_error(
+ "Failed to execute command, execve syscall returned "
+ "{} ({})".format(error, error_name))
+
+ # -- Helper functions --
+
+ def _is_command_allowed(self, cmd):
+ return os.path.basename(cmd) in self._allowed_commands
+
+ def _find_on_path(self, cmd):
+ if os.path.isabs(cmd):
+ return cmd
+
+ path = self.user_env.get("PATH", "/usr/bin:/bin")
+ absolute_cmd = shutil.which(cmd, path=path)
+ if not absolute_cmd:
+ raise sudo.PluginError("Can not find cmd '{}' on PATH".format(cmd))
+ return absolute_cmd
+
+ def _runas_pwd(self):
+ runas_user = self.settings.get("runas_user") or "root"
+ try:
+ return pwd.getpwnam(runas_user)
+ except KeyError:
+ raise sudo.PluginError("Could not find user "
+ "'{}'".format(runas_user))
+
+ def _runas_uid(self):
+ return self._runas_pwd().pw_uid
+
+ def _runas_gid(self):
+ runas_group = self.settings.get("runas_group")
+ if runas_group is None:
+ return self._runas_pwd().pw_gid
+
+ try:
+ return grp.getgrnam(runas_group).gr_gid
+ except KeyError:
+ raise sudo.PluginError(
+ "Could not find group '{}'".format(runas_group))
diff --git a/plugins/python/lsan_suppr.txt b/plugins/python/lsan_suppr.txt
new file mode 100644
index 0000000..094ffd5
--- /dev/null
+++ b/plugins/python/lsan_suppr.txt
@@ -0,0 +1 @@
+leak:libpython
diff --git a/plugins/python/pyhelpers.c b/plugins/python/pyhelpers.c
new file mode 100644
index 0000000..2eac8e3
--- /dev/null
+++ b/plugins/python/pyhelpers.c
@@ -0,0 +1,587 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include "pyhelpers.h"
+
+#include <pwd.h>
+#include <signal.h>
+#include <pathnames.h>
+
+static int
+_sudo_printf_default(int msg_type, const char * restrict fmt, ...)
+{
+ FILE *fp = stdout;
+ FILE *ttyfp = NULL;
+ va_list ap;
+ int len;
+
+ if (ISSET(msg_type, SUDO_CONV_PREFER_TTY)) {
+ /* Try writing to /dev/tty first. */
+ ttyfp = fopen(_PATH_TTY, "w");
+ }
+
+ switch (msg_type & 0xff) {
+ case SUDO_CONV_ERROR_MSG:
+ fp = stderr;
+ FALLTHROUGH;
+ case SUDO_CONV_INFO_MSG:
+ va_start(ap, fmt);
+ len = vfprintf(ttyfp ? ttyfp : fp, fmt, ap);
+ va_end(ap);
+ break;
+ default:
+ len = -1;
+ errno = EINVAL;
+ break;
+ }
+
+ if (ttyfp != NULL)
+ fclose(ttyfp);
+
+ return len;
+}
+
+
+struct PythonContext py_ctx = {
+ .sudo_log = &_sudo_printf_default,
+};
+
+
+char *
+py_join_str_list(PyObject *py_str_list, const char *separator)
+{
+ debug_decl(py_join_str_list, PYTHON_DEBUG_INTERNAL);
+
+ char *result = NULL;
+ PyObject *py_separator = NULL;
+ PyObject *py_str = NULL;
+
+ py_separator = PyUnicode_FromString(separator);
+ if (py_separator == NULL)
+ goto cleanup;
+
+ py_str = PyObject_CallMethod(py_separator, "join", "(O)", py_str_list);
+ if (py_str == NULL) {
+ goto cleanup;
+ }
+
+ const char *str = PyUnicode_AsUTF8(py_str);
+ if (str != NULL) {
+ result = strdup(str);
+ }
+
+cleanup:
+ Py_XDECREF(py_str);
+ Py_XDECREF(py_separator);
+
+ debug_return_str(result);
+}
+
+static char *
+py_create_traceback_string(PyObject *py_traceback)
+{
+ debug_decl(py_create_traceback_string, PYTHON_DEBUG_INTERNAL);
+ if (py_traceback == NULL)
+ debug_return_str(strdup(""));
+
+ char* traceback = NULL;
+
+
+ PyObject *py_traceback_module = PyImport_ImportModule("traceback");
+ if (py_traceback_module == NULL) {
+ PyErr_Clear(); // do not care, we just won't show backtrace
+ } else {
+ PyObject *py_traceback_str_list = PyObject_CallMethod(py_traceback_module, "format_tb", "(O)", py_traceback);
+
+ if (py_traceback_str_list != NULL) {
+ traceback = py_join_str_list(py_traceback_str_list, "");
+ Py_DECREF(py_traceback_str_list);
+ }
+
+ Py_CLEAR(py_traceback_module);
+ }
+
+ debug_return_str(traceback ? traceback : strdup(""));
+}
+
+void
+py_log_last_error(const char *context_message)
+{
+ debug_decl(py_log_last_error, PYTHON_DEBUG_INTERNAL);
+ if (!PyErr_Occurred()) {
+ py_sudo_log(SUDO_CONV_ERROR_MSG, "%s\n", context_message);
+ debug_return;
+ }
+
+ PyObject *py_type = NULL, *py_message = NULL, *py_traceback = NULL;
+ PyErr_Fetch(&py_type, &py_message, &py_traceback);
+
+ char *message = py_message ? py_create_string_rep(py_message) : NULL;
+
+ py_sudo_log(SUDO_CONV_ERROR_MSG, "%s%s%s\n",
+ context_message ? context_message : "",
+ context_message && *context_message ? ": " : "",
+ message ? message : "(NULL)");
+ free(message);
+
+ if (py_traceback != NULL) {
+ char *traceback = py_create_traceback_string(py_traceback);
+ py_sudo_log(SUDO_CONV_INFO_MSG, "Traceback:\n%s\n", traceback);
+ free(traceback);
+ }
+
+ Py_XDECREF(py_type);
+ Py_XDECREF(py_message);
+ Py_XDECREF(py_traceback);
+ debug_return;
+}
+
+PyObject *
+py_str_array_to_tuple_with_count(Py_ssize_t count, char * const strings[])
+{
+ debug_decl(py_str_array_to_tuple_with_count, PYTHON_DEBUG_INTERNAL);
+
+ PyObject *py_argv = PyTuple_New(count);
+ if (py_argv == NULL)
+ debug_return_ptr(NULL);
+
+ for (int i = 0; i < count; ++i) {
+ PyObject *py_arg = PyUnicode_FromString(strings[i]);
+ if (py_arg == NULL || PyTuple_SetItem(py_argv, i, py_arg) != 0) {
+ Py_CLEAR(py_argv);
+ break;
+ }
+ }
+
+ debug_return_ptr(py_argv);
+}
+
+PyObject *
+py_str_array_to_tuple(char * const strings[])
+{
+ debug_decl(py_str_array_to_tuple, PYTHON_DEBUG_INTERNAL);
+
+ // find the item count ("strings" ends with NULL terminator):
+ Py_ssize_t count = 0;
+ if (strings != NULL) {
+ while (strings[count] != NULL)
+ ++count;
+ }
+
+ debug_return_ptr(py_str_array_to_tuple_with_count(count, strings));
+}
+
+char **
+py_str_array_from_tuple(PyObject *py_tuple)
+{
+ debug_decl(py_str_array_from_tuple, PYTHON_DEBUG_INTERNAL);
+
+ if (!PyTuple_Check(py_tuple)) {
+ PyErr_Format(PyExc_ValueError, "%s: value error, argument should be a tuple but it is '%s'",
+ __func__, Py_TYPENAME(py_tuple));
+ debug_return_ptr(NULL);
+ }
+
+ Py_ssize_t tuple_size = PyTuple_Size(py_tuple);
+
+ // we need an extra 0 at the end
+ char **result = calloc((size_t)tuple_size + 1, sizeof(char *));
+ if (result == NULL) {
+ debug_return_ptr(NULL);
+ }
+
+ for (int i = 0; i < tuple_size; ++i) {
+ PyObject *py_value = PyTuple_GetItem(py_tuple, i);
+ if (py_value == NULL) {
+ str_array_free(&result);
+ debug_return_ptr(NULL);
+ }
+
+ // Note that it can be an "int" or something else as well
+ char *value = py_create_string_rep(py_value);
+ if (value == NULL) {
+ // conversion error is already set
+ str_array_free(&result);
+ debug_return_ptr(NULL);
+ }
+ result[i] = value;
+ }
+
+ debug_return_ptr(result);
+}
+
+PyObject *
+py_tuple_get(PyObject *py_tuple, Py_ssize_t idx, PyTypeObject *expected_type)
+{
+ debug_decl(py_tuple_get, PYTHON_DEBUG_INTERNAL);
+
+ PyObject *py_item = PyTuple_GetItem(py_tuple, idx);
+ if (py_item == NULL) {
+ debug_return_ptr(NULL);
+ }
+
+ if (!PyObject_TypeCheck(py_item, expected_type)) {
+ PyErr_Format(PyExc_ValueError, "Value error: tuple element %d should "
+ "be a '%s' (but it is '%s')",
+ idx, expected_type->tp_name, Py_TYPENAME(py_item));
+ debug_return_ptr(NULL);
+ }
+
+ debug_return_ptr(py_item);
+}
+
+PyObject *
+py_create_version(unsigned int version)
+{
+ debug_decl(py_create_version, PYTHON_DEBUG_INTERNAL);
+ debug_return_ptr(PyUnicode_FromFormat("%d.%d", SUDO_API_VERSION_GET_MAJOR(version),
+ SUDO_API_VERSION_GET_MINOR(version)));
+}
+
+PyObject *
+py_from_passwd(const struct passwd *pwd)
+{
+ debug_decl(py_from_passwd, PYTHON_DEBUG_INTERNAL);
+
+ if (pwd == NULL) {
+ debug_return_ptr_pynone;
+ }
+
+ // Create a tuple similar and convertible to python "struct_passwd" of "pwd" module
+ debug_return_ptr(
+ Py_BuildValue("(zziizzz)", pwd->pw_name, pwd->pw_passwd,
+ pwd->pw_uid, pwd->pw_gid, pwd->pw_gecos,
+ pwd->pw_dir, pwd->pw_shell)
+ );
+}
+
+char *
+py_create_string_rep(PyObject *py_object)
+{
+ debug_decl(py_create_string_rep, PYTHON_DEBUG_INTERNAL);
+ char *result = NULL;
+
+ if (py_object == NULL)
+ debug_return_ptr(NULL);
+
+ PyObject *py_string = PyObject_Str(py_object);
+ if (py_string != NULL) {
+ const char *bytes = PyUnicode_AsUTF8(py_string);
+ if (bytes != NULL) {
+ /*
+ * Convert from old format w/ numeric value to new without it.
+ * Old: (<DEBUG.ERROR: 2>, 'ERROR level debug message')
+ * New: (DEBUG.ERROR, 'ERROR level debug message')
+ */
+ if (bytes[0] == '(' && bytes[1] == '<') {
+ const char *colon = strchr(bytes + 2, ':');
+ if (colon != NULL && colon[1] == ' ') {
+ const char *cp = colon + 2;
+ while (isdigit((unsigned char)*cp))
+ cp++;
+ if (cp[0] == '>' && (cp[1] == ',' || cp[1] == '\0')) {
+ bytes += 2;
+ if (asprintf(&result, "(%.*s%s", (int)(colon - bytes),
+ bytes, cp + 1) == -1) {
+ result = NULL;
+ goto done;
+ }
+ }
+ }
+ }
+ if (result == NULL)
+ result = strdup(bytes);
+ }
+ }
+
+done:
+ Py_XDECREF(py_string);
+ debug_return_ptr(result);
+}
+
+static void
+_py_debug_python_function(const char *class_name, const char *function_name, const char *message,
+ PyObject *py_args, PyObject *py_kwargs, unsigned int subsystem_id)
+{
+ debug_decl_vars(_py_debug_python_function, subsystem_id);
+
+ if (sudo_debug_needed(SUDO_DEBUG_DIAG)) {
+ char *args_str = NULL;
+ char *kwargs_str = NULL;
+ if (py_args != NULL) {
+ /* Sort by key for consistent output on Python < 3.6 */
+ PyObject *py_args_sorted = NULL;
+ if (PyDict_Check(py_args)) {
+ py_args_sorted = PyDict_Items(py_args);
+ if (py_args_sorted != NULL) {
+ if (PyList_Sort(py_args_sorted) == 0) {
+ py_args = py_args_sorted;
+ }
+ }
+ }
+ args_str = py_create_string_rep(py_args);
+ if (args_str != NULL && strncmp(args_str, "RC.", 3) == 0) {
+ /* Strip leading RC. to match python 3.10 behavior. */
+ memmove(args_str, args_str + 3, strlen(args_str + 3) + 1);
+ }
+ Py_XDECREF(py_args_sorted);
+ }
+ if (py_kwargs != NULL) {
+ /* Sort by key for consistent output on Python < 3.6 */
+ PyObject *py_kwargs_sorted = NULL;
+ if (PyDict_Check(py_kwargs)) {
+ py_kwargs_sorted = PyDict_Items(py_kwargs);
+ if (py_kwargs_sorted != NULL) {
+ if (PyList_Sort(py_kwargs_sorted) == 0) {
+ py_kwargs = py_kwargs_sorted;
+ }
+ }
+ }
+ kwargs_str = py_create_string_rep(py_kwargs);
+ Py_XDECREF(py_kwargs_sorted);
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "%s.%s %s: %s%s%s\n", class_name,
+ function_name, message, args_str ? args_str : "()",
+ kwargs_str ? " " : "", kwargs_str ? kwargs_str : "");
+ free(args_str);
+ free(kwargs_str);
+ }
+}
+
+void
+py_debug_python_call(const char *class_name, const char *function_name,
+ PyObject *py_args, PyObject *py_kwargs,
+ unsigned int subsystem_id)
+{
+ debug_decl_vars(py_debug_python_call, subsystem_id);
+
+ if (subsystem_id == PYTHON_DEBUG_C_CALLS && sudo_debug_needed(SUDO_DEBUG_INFO)) {
+ // at this level we also output the callee python script
+ char *callee_func_name = NULL, *callee_file_name = NULL;
+ long callee_line_number = -1;
+
+ if (py_get_current_execution_frame(&callee_file_name, &callee_line_number, &callee_func_name) == SUDO_RC_OK) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s @ %s:%ld calls C function:\n",
+ callee_func_name, callee_file_name, callee_line_number);
+ }
+
+ free(callee_func_name);
+ free(callee_file_name);
+ }
+
+ _py_debug_python_function(class_name, function_name, "was called with arguments",
+ py_args, py_kwargs, subsystem_id);
+}
+
+void
+py_debug_python_result(const char *class_name, const char *function_name,
+ PyObject *py_result, unsigned int subsystem_id)
+{
+ if (py_result == NULL) {
+ debug_decl_vars(py_debug_python_result, subsystem_id);
+ sudo_debug_printf(SUDO_CONV_ERROR_MSG, "%s.%s call failed\n",
+ class_name, function_name);
+ } else {
+ _py_debug_python_function(class_name, function_name, "returned result",
+ py_result, NULL, subsystem_id);
+ }
+}
+
+void
+str_array_free(char ***array)
+{
+ debug_decl(str_array_free, PYTHON_DEBUG_INTERNAL);
+
+ if (*array == NULL)
+ debug_return;
+
+ for (char **item_ptr = *array; *item_ptr != NULL; ++item_ptr)
+ free(*item_ptr);
+
+ free(*array);
+ *array = NULL;
+
+ debug_return;
+}
+
+int
+py_get_current_execution_frame(char **file_name, long *line_number, char **function_name)
+{
+ *file_name = NULL;
+ *line_number = (long)-1;
+ *function_name = NULL;
+
+ PyObject *py_err_type = NULL, *py_err_value = NULL, *py_err_traceback = NULL;
+ PyErr_Fetch(&py_err_type, &py_err_value, &py_err_traceback);
+
+ PyObject *py_frame = NULL, *py_f_code = NULL,
+ *py_filename = NULL, *py_function_name = NULL;
+
+ PyObject *py_getframe = PySys_GetObject("_getframe");
+ if (py_getframe == NULL)
+ goto cleanup;
+
+ py_frame = PyObject_CallFunction(py_getframe, "i", 0);
+ if (py_frame == NULL)
+ goto cleanup;
+
+ *line_number = py_object_get_optional_attr_number(py_frame, "f_lineno");
+
+ py_f_code = py_object_get_optional_attr(py_frame, "f_code", NULL);
+ if (py_f_code != NULL) {
+ py_filename = py_object_get_optional_attr(py_f_code, "co_filename", NULL);
+ if (py_filename != NULL)
+ *file_name = strdup(PyUnicode_AsUTF8(py_filename));
+
+ py_function_name = py_object_get_optional_attr(py_f_code, "co_name", NULL);
+ if (py_function_name != NULL)
+ *function_name = strdup(PyUnicode_AsUTF8(py_function_name));
+ }
+
+cleanup:
+ Py_CLEAR(py_frame);
+ Py_CLEAR(py_f_code);
+ Py_CLEAR(py_filename);
+ Py_CLEAR(py_function_name);
+
+ // we hide every error happening inside this function
+ PyErr_Restore(py_err_type, py_err_value, py_err_traceback);
+
+ return (*file_name && *function_name && (*line_number >= 0)) ?
+ SUDO_RC_OK : SUDO_RC_ERROR;
+}
+
+void
+py_ctx_reset()
+{
+ memset(&py_ctx, 0, sizeof(py_ctx));
+ py_ctx.sudo_log = &_sudo_printf_default;
+}
+
+int
+py_sudo_conv(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
+{
+ /* Enable suspend during password entry. */
+ struct sigaction sa, saved_sigtstp;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = SIG_DFL;
+ (void) sigaction(SIGTSTP, &sa, &saved_sigtstp);
+
+ int rc = SUDO_RC_ERROR;
+ if (py_ctx.sudo_conv != NULL)
+ rc = py_ctx.sudo_conv((int)num_msgs, msgs, replies, callback);
+
+ /* Restore signal handlers and signal mask. */
+ (void) sigaction(SIGTSTP, &saved_sigtstp, NULL);
+
+ return rc;
+}
+
+PyObject *
+py_object_get_optional_attr(PyObject *py_object, const char *attr, PyObject *py_default)
+{
+ if (PyObject_HasAttrString(py_object, attr)) {
+ return PyObject_GetAttrString(py_object, attr);
+ }
+ Py_XINCREF(py_default); // whatever we return will have its refcount incremented
+ return py_default;
+}
+
+const char *
+py_object_get_optional_attr_string(PyObject *py_object, const char *attr_name)
+{
+ PyObject *py_value = py_object_get_optional_attr(py_object, attr_name, NULL);
+ if (py_value == NULL)
+ return NULL;
+
+ const char *value = PyUnicode_AsUTF8(py_value);
+ Py_CLEAR(py_value); // Note, the object still has reference to the attribute
+ return value;
+}
+
+long
+py_object_get_optional_attr_number(PyObject *py_object, const char *attr_name)
+{
+ PyObject *py_value = py_object_get_optional_attr(py_object, attr_name, NULL);
+ if (py_value == NULL)
+ return -1;
+
+ long value = PyLong_AsLong(py_value);
+ Py_CLEAR(py_value);
+ return value;
+}
+
+void
+py_object_set_attr_number(PyObject *py_object, const char *attr_name, long number)
+{
+ PyObject *py_number = PyLong_FromLong(number);
+ if (py_number == NULL)
+ return;
+
+ PyObject_SetAttrString(py_object, attr_name, py_number);
+ Py_CLEAR(py_number);
+}
+
+void
+py_object_set_attr_string(PyObject *py_object, const char *attr_name, const char *value)
+{
+ PyObject *py_value = PyUnicode_FromString(value);
+ if (py_value == NULL)
+ return;
+
+ PyObject_SetAttrString(py_object, attr_name, py_value);
+ Py_CLEAR(py_value);
+}
+
+PyObject *
+py_dict_create_string_int(size_t count, struct key_value_str_int *key_values)
+{
+ debug_decl(py_dict_create_string_int, PYTHON_DEBUG_INTERNAL);
+
+ PyObject *py_value = NULL;
+ PyObject *py_dict = PyDict_New();
+ if (py_dict == NULL)
+ goto cleanup;
+
+ for (size_t i = 0; i < count; ++i) {
+ py_value = PyLong_FromLong(key_values[i].value);
+ if (py_value == NULL)
+ goto cleanup;
+
+ if (PyDict_SetItemString(py_dict, key_values[i].key, py_value) < 0)
+ goto cleanup;
+
+ Py_CLEAR(py_value);
+ }
+
+cleanup:
+ if (PyErr_Occurred()) {
+ Py_CLEAR(py_dict);
+ }
+ Py_CLEAR(py_value);
+
+ debug_return_ptr(py_dict);
+}
diff --git a/plugins/python/pyhelpers.h b/plugins/python/pyhelpers.h
new file mode 100644
index 0000000..1350a2a
--- /dev/null
+++ b/plugins/python/pyhelpers.h
@@ -0,0 +1,108 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_PLUGIN_PYHELPERS_H
+#define SUDO_PLUGIN_PYHELPERS_H
+
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
+
+/* Python may be built with 32-bit time_t support on some platforms. */
+#undef SIZEOF_TIME_T
+
+#include <config.h>
+#include <sudo_compat.h>
+#include <sudo_plugin.h>
+
+#include "pyhelpers_cpychecker.h"
+
+#include "sudo_python_debug.h"
+
+enum SudoPluginFunctionReturnCode {
+ SUDO_RC_OK = 1,
+ SUDO_RC_ACCEPT = 1,
+ SUDO_RC_REJECT = 0,
+ SUDO_RC_ERROR = -1,
+ SUDO_RC_USAGE_ERROR = -2,
+};
+
+#define INTERPRETER_MAX 32
+
+struct PythonContext
+{
+ sudo_printf_t sudo_log;
+ sudo_conv_t sudo_conv;
+ PyThreadState *py_main_interpreter;
+ size_t interpreter_count;
+ PyThreadState *py_subinterpreters[INTERPRETER_MAX];
+};
+
+extern struct PythonContext py_ctx;
+
+#define Py_TYPENAME(object) (object ? Py_TYPE(object)->tp_name : "NULL")
+
+#define py_sudo_log(...) py_ctx.sudo_log(__VA_ARGS__)
+
+int py_sudo_conv(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback);
+
+void py_log_last_error(const char *context_message);
+
+char *py_create_string_rep(PyObject *py_object);
+
+char *py_join_str_list(PyObject *py_str_list, const char *separator);
+
+struct key_value_str_int
+{
+ const char *key;
+ int value;
+};
+
+PyObject *py_dict_create_string_int(size_t count, struct key_value_str_int *key_values);
+
+PyObject *py_from_passwd(const struct passwd *pwd);
+
+PyObject *py_str_array_to_tuple_with_count(Py_ssize_t count, char * const strings[]);
+PyObject *py_str_array_to_tuple(char * const strings[]);
+char **py_str_array_from_tuple(PyObject *py_tuple);
+
+CPYCHECKER_RETURNS_BORROWED_REF
+PyObject *py_tuple_get(PyObject *py_tuple, Py_ssize_t index, PyTypeObject *expected_type);
+
+PyObject *py_object_get_optional_attr(PyObject *py_object, const char *attr, PyObject *py_default);
+long py_object_get_optional_attr_number(PyObject *py_object, const char *attr_name);
+const char *py_object_get_optional_attr_string(PyObject *py_object, const char *attr_name);
+
+void py_object_set_attr_number(PyObject *py_object, const char *attr_name, long number);
+void py_object_set_attr_string(PyObject *py_object, const char *attr_name, const char *value);
+
+PyObject *py_create_version(unsigned int version);
+
+void py_debug_python_call(const char *class_name, const char *function_name,
+ PyObject *py_args, PyObject *py_kwargs,
+ unsigned int subsystem_id);
+void py_debug_python_result(const char *class_name, const char *function_name,
+ PyObject *py_args, unsigned int subsystem_id);
+
+void str_array_free(char ***array);
+
+int py_get_current_execution_frame(char **file_name, long *line_number, char **function_name);
+
+void py_ctx_reset(void);
+
+#endif // SUDO_PLUGIN_PYHELPERS_H
diff --git a/plugins/python/pyhelpers_cpychecker.h b/plugins/python/pyhelpers_cpychecker.h
new file mode 100644
index 0000000..dc048c3
--- /dev/null
+++ b/plugins/python/pyhelpers_cpychecker.h
@@ -0,0 +1,45 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_PLUGIN_PYHELPERS_CPYCHECKER_H
+#define SUDO_PLUGIN_PYHELPERS_CPYCHECKER_H
+
+/* Helper macros for cpychecker */
+
+#if defined(WITH_CPYCHECKER_RETURNS_BORROWED_REF_ATTRIBUTE)
+ #define CPYCHECKER_RETURNS_BORROWED_REF \
+ __attribute__((cpychecker_returns_borrowed_ref))
+#else
+ #define CPYCHECKER_RETURNS_BORROWED_REF
+#endif
+
+#ifdef WITH_CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION_ATTRIBUTE
+ #define CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION \
+ __attribute__ ((cpychecker_negative_result_sets_exception))
+#else
+ #define CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
+#endif
+
+#if defined(WITH_CPYCHECKER_STEALS_REFERENCE_TO_ARG_ATTRIBUTE)
+ #define CPYCHECKER_STEALS_REFERENCE_TO_ARG(n) \
+ __attribute__((cpychecker_steals_reference_to_arg(n)))
+#else
+ #define CPYCHECKER_STEALS_REFERENCE_TO_ARG(n)
+#endif
+
+#endif // SUDO_PLUGIN_PYHELPERS_CPYCHECKER_H
diff --git a/plugins/python/python_baseplugin.c b/plugins/python/python_baseplugin.c
new file mode 100644
index 0000000..80af9b4
--- /dev/null
+++ b/plugins/python/python_baseplugin.c
@@ -0,0 +1,88 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include "sudo_python_module.h"
+
+PyTypeObject *sudo_type_Plugin = NULL;
+
+static PyObject *
+_sudo_Plugin__Init(PyObject *py_self, PyObject *py_args, PyObject *py_kwargs)
+{
+ debug_decl(_sudo_Plugin__Init, PYTHON_DEBUG_C_CALLS);
+
+ py_debug_python_call("Plugin", "__init__", py_args, NULL, PYTHON_DEBUG_C_CALLS);
+
+ if (!PyArg_UnpackTuple(py_args, "sudo.Plugin.__init__", 1, 1, &py_self))
+ goto cleanup;
+
+ Py_ssize_t pos = 0;
+ PyObject *py_key = NULL, *py_value = NULL; // -> borrowed references
+
+ while (PyDict_Next(py_kwargs, &pos, &py_key, &py_value)) {
+ if (PyObject_SetAttr(py_self, py_key, py_value) != 0)
+ goto cleanup;
+ }
+
+cleanup:
+ if (PyErr_Occurred())
+ debug_return_ptr(NULL);
+
+ debug_return_ptr_pynone;
+}
+
+
+static PyMethodDef _sudo_Plugin_class_methods[] = {
+ {"__init__", (PyCFunction)_sudo_Plugin__Init,
+ METH_VARARGS | METH_KEYWORDS,
+ "Base sudo plugin constructor"},
+ {NULL, NULL, 0, NULL}
+};
+
+
+int
+sudo_module_register_baseplugin(PyObject *py_module)
+{
+ debug_decl(sudo_module_register_baseplugin, PYTHON_DEBUG_INTERNAL);
+ int rc = SUDO_RC_ERROR;
+ PyObject *py_class = NULL;
+
+ py_class = sudo_module_create_class("sudo.Plugin", _sudo_Plugin_class_methods, NULL);
+ if (py_class == NULL)
+ goto cleanup;
+
+ if (PyModule_AddObject(py_module, "Plugin", py_class) < 0) {
+ goto cleanup;
+ }
+
+ // PyModule_AddObject steals a reference to py_class on success
+ Py_INCREF(py_class);
+ rc = SUDO_RC_OK;
+
+ Py_CLEAR(sudo_type_Plugin);
+ sudo_type_Plugin = (PyTypeObject *)py_class;
+ Py_INCREF(sudo_type_Plugin);
+
+cleanup:
+ Py_CLEAR(py_class);
+ debug_return_int(rc);
+}
diff --git a/plugins/python/python_convmessage.c b/plugins/python/python_convmessage.c
new file mode 100644
index 0000000..b49e1fa
--- /dev/null
+++ b/plugins/python/python_convmessage.c
@@ -0,0 +1,155 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include "sudo_python_module.h"
+
+PyTypeObject *sudo_type_ConvMessage;
+
+static PyObject *
+_sudo_ConvMessage__Init(PyObject *py_self, PyObject *py_args, PyObject *py_kwargs)
+{
+ debug_decl(_sudo_ConvMessage__Init, PYTHON_DEBUG_C_CALLS);
+
+ py_debug_python_call("ConvMessage", "__init__", py_args, py_kwargs, PYTHON_DEBUG_C_CALLS);
+
+ PyObject *py_empty = PyTuple_New(0);
+
+ struct sudo_conv_message conv_message = { 0, 0, NULL };
+
+ static const char *keywords[] = { "self", "msg_type", "msg", "timeout", NULL };
+ if (!PyArg_ParseTupleAndKeywords(py_args ? py_args : py_empty, py_kwargs, "Ois|i:sudo.ConvMessage", (char **)keywords,
+ &py_self, &(conv_message.msg_type), &(conv_message.msg),
+ &(conv_message.timeout)))
+ goto cleanup;
+
+ sudo_debug_printf(SUDO_DEBUG_TRACE, "Parsed arguments: self='%p' msg_type='%d' timeout='%d' msg='%s'",
+ (void *)py_self, conv_message.msg_type, conv_message.timeout, conv_message.msg);
+
+ py_object_set_attr_number(py_self, "msg_type", conv_message.msg_type);
+ if (PyErr_Occurred())
+ goto cleanup;
+
+ py_object_set_attr_number(py_self, "timeout", conv_message.timeout);
+ if (PyErr_Occurred()) // -V547
+ goto cleanup;
+
+ py_object_set_attr_string(py_self, "msg", conv_message.msg);
+ if (PyErr_Occurred()) // -V547
+ goto cleanup;
+
+cleanup:
+ Py_CLEAR(py_empty);
+
+ if (PyErr_Occurred())
+ debug_return_ptr(NULL);
+
+ debug_return_ptr_pynone;
+}
+
+
+static PyMethodDef _sudo_ConvMessage_class_methods[] =
+{
+ {"__init__", (PyCFunction)_sudo_ConvMessage__Init,
+ METH_VARARGS | METH_KEYWORDS,
+ "Conversation message (same as C type sudo_conv_message)"},
+ {NULL, NULL, 0, NULL}
+};
+
+
+int
+sudo_module_register_conv_message(PyObject *py_module)
+{
+ debug_decl(sudo_module_register_conv_message, PYTHON_DEBUG_INTERNAL);
+ int rc = SUDO_RC_ERROR;
+ PyObject *py_class = NULL;
+
+ py_class = sudo_module_create_class("sudo.ConvMessage", _sudo_ConvMessage_class_methods, NULL);
+ if (py_class == NULL)
+ goto cleanup;
+
+ if (PyModule_AddObject(py_module, "ConvMessage", py_class) < 0) {
+ goto cleanup;
+ }
+
+ // PyModule_AddObject steals the reference to py_class on success
+ Py_INCREF(py_class);
+ rc = SUDO_RC_OK;
+
+ Py_CLEAR(sudo_type_ConvMessage);
+ sudo_type_ConvMessage = (PyTypeObject *)py_class;
+ Py_INCREF(sudo_type_ConvMessage);
+
+cleanup:
+ Py_CLEAR(py_class);
+ debug_return_int(rc);
+}
+
+int
+sudo_module_ConvMessage_to_c(PyObject *py_conv_message, struct sudo_conv_message *conv_message)
+{
+ debug_decl(sudo_module_ConvMessage_to_c, PYTHON_DEBUG_C_CALLS);
+
+ conv_message->msg_type = (int)py_object_get_optional_attr_number(py_conv_message, "msg_type");
+ if (PyErr_Occurred())
+ debug_return_int(SUDO_RC_ERROR);
+
+ conv_message->timeout = (int)py_object_get_optional_attr_number(py_conv_message, "timeout");
+ if (PyErr_Occurred()) // -V547
+ debug_return_int(SUDO_RC_ERROR);
+
+ conv_message->msg = py_object_get_optional_attr_string(py_conv_message, "msg");
+ if (PyErr_Occurred()) // -V547
+ debug_return_int(SUDO_RC_ERROR);
+
+ debug_return_int(SUDO_RC_OK);
+}
+
+int
+sudo_module_ConvMessages_to_c(PyObject *py_tuple, Py_ssize_t *num_msgs, struct sudo_conv_message **msgs)
+{
+ debug_decl(sudo_module_ConvMessages_to_c, PYTHON_DEBUG_C_CALLS);
+
+ *num_msgs = PyTuple_Size(py_tuple);
+ *msgs = NULL;
+
+ if (*num_msgs <= 0) {
+ *num_msgs = 0;
+ PyErr_Format(sudo_exc_SudoException, "Expected at least one ConvMessage");
+ debug_return_int(SUDO_RC_ERROR);
+ }
+
+ *msgs = calloc((size_t)*num_msgs, sizeof(struct sudo_conv_message));
+ if (*msgs == NULL) {
+ debug_return_int(SUDO_RC_ERROR);
+ }
+
+ for (Py_ssize_t i = 0; i < *num_msgs; ++i) {
+ PyObject *py_msg = py_tuple_get(py_tuple, i, sudo_type_ConvMessage);
+ if (py_msg == NULL || sudo_module_ConvMessage_to_c(py_msg, &(*msgs)[i]) < 0) {
+ debug_return_int(SUDO_RC_ERROR);
+ }
+ }
+
+ debug_return_int(SUDO_RC_OK);
+}
+
diff --git a/plugins/python/python_loghandler.c b/plugins/python/python_loghandler.c
new file mode 100644
index 0000000..c5991e1
--- /dev/null
+++ b/plugins/python/python_loghandler.c
@@ -0,0 +1,182 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include "sudo_python_module.h"
+
+#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9
+# define PyObject_CallNoArgs(_o) PyObject_CallObject((_o), NULL)
+#endif
+
+static void
+_debug_plugin(unsigned int log_level, const char *log_message)
+{
+ debug_decl_vars(python_sudo_debug, PYTHON_DEBUG_PLUGIN);
+
+ if (sudo_debug_needed(SUDO_DEBUG_INFO)) {
+ // at trace level we output the position for the python log as well
+ char *func_name = NULL, *file_name = NULL;
+ long line_number = -1;
+
+ if (py_get_current_execution_frame(&file_name, &line_number, &func_name) == SUDO_RC_OK) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s @ %s:%ld debugs:\n",
+ func_name, file_name, line_number);
+ }
+
+ free(func_name);
+ free(file_name);
+ }
+
+ sudo_debug_printf(log_level, "%s\n", log_message);
+}
+
+PyObject *
+python_sudo_debug(PyObject *Py_UNUSED(py_self), PyObject *py_args)
+{
+ debug_decl(python_sudo_debug, PYTHON_DEBUG_C_CALLS);
+ py_debug_python_call("sudo", "debug", py_args, NULL, PYTHON_DEBUG_C_CALLS);
+
+ unsigned int log_level = SUDO_DEBUG_DEBUG;
+ const char *log_message = NULL;
+ if (!PyArg_ParseTuple(py_args, "is:sudo.debug", &log_level, &log_message)) {
+ debug_return_ptr(NULL);
+ }
+
+ _debug_plugin(log_level, log_message);
+
+ debug_return_ptr_pynone;
+}
+
+static unsigned int
+_sudo_log_level_from_python(long level)
+{
+ if (level >= 50)
+ return SUDO_DEBUG_CRIT;
+ if (level >= 40)
+ return SUDO_DEBUG_ERROR;
+ if (level >= 30)
+ return SUDO_DEBUG_WARN;
+ if (level >= 20)
+ return SUDO_DEBUG_INFO;
+
+ return SUDO_DEBUG_TRACE;
+}
+
+static PyObject *
+_sudo_LogHandler__emit(PyObject *py_self, PyObject *py_args)
+{
+ debug_decl(_sudo_LogHandler__emit, PYTHON_DEBUG_C_CALLS);
+
+ PyObject *py_record = NULL; // borrowed
+ PyObject *py_message = NULL;
+
+ py_debug_python_call("LogHandler", "emit", py_args, NULL, PYTHON_DEBUG_C_CALLS);
+
+ if (!PyArg_UnpackTuple(py_args, "sudo.LogHandler.emit", 2, 2, &py_self, &py_record))
+ goto cleanup;
+
+ long python_loglevel = py_object_get_optional_attr_number(py_record, "levelno");
+ if (PyErr_Occurred()) {
+ PyErr_Format(sudo_exc_SudoException, "sudo.LogHandler: Failed to determine log level");
+ goto cleanup;
+ }
+
+ unsigned int sudo_loglevel = _sudo_log_level_from_python(python_loglevel);
+
+ py_message = PyObject_CallMethod(py_self, "format", "O", py_record);
+ if (py_message == NULL)
+ goto cleanup;
+
+ _debug_plugin(sudo_loglevel, PyUnicode_AsUTF8(py_message));
+
+cleanup:
+ Py_CLEAR(py_message);
+ if (PyErr_Occurred()) {
+ debug_return_ptr(NULL);
+ }
+
+ debug_return_ptr_pynone;
+}
+
+/* The sudo.LogHandler class can be used to make the default python logger
+ * use sudo's built in log system. */
+static PyMethodDef _sudo_LogHandler_class_methods[] =
+{
+ {"emit", _sudo_LogHandler__emit, METH_VARARGS, ""},
+ {NULL, NULL, 0, NULL}
+};
+
+// This function creates the sudo.LogHandler class and adds it
+// to the root logger.
+int
+sudo_module_set_default_loghandler()
+{
+ debug_decl(sudo_module_set_default_loghandler, PYTHON_DEBUG_INTERNAL);
+
+ PyObject *py_sudo, *py_logging_module = NULL, *py_logger = NULL,
+ *py_streamhandler = NULL, *py_class = NULL,
+ *py_loghandler = NULL, *py_result = NULL;
+
+ py_sudo = PyImport_ImportModule("sudo");
+ if (py_sudo == NULL)
+ goto cleanup;
+
+ py_logging_module = PyImport_ImportModule("logging");
+ if (py_logging_module == NULL)
+ goto cleanup;
+
+ // Get the root logger which all loggers descend from.
+ py_logger = PyObject_CallMethod(py_logging_module, "getLogger", NULL);
+ if (py_logger == NULL)
+ goto cleanup;
+
+ py_streamhandler = PyObject_GetAttrString(py_logging_module, "StreamHandler");
+ if (py_streamhandler == NULL)
+ goto cleanup;
+
+ // Create our own handler that is a sub-class of StreamHandler
+ py_class = sudo_module_create_class("sudo.LogHandler",
+ _sudo_LogHandler_class_methods, py_streamhandler);
+ if (py_class == NULL)
+ goto cleanup;
+
+ // PyModule_AddObject steals a reference to py_class on success
+ if (PyModule_AddObject(py_sudo, "LogHandler", py_class) < 0)
+ goto cleanup;
+ Py_INCREF(py_class);
+
+ py_loghandler = PyObject_CallNoArgs(py_class);
+ if (py_loghandler == NULL)
+ goto cleanup;
+
+ py_result = PyObject_CallMethod(py_logger, "addHandler", "O", py_loghandler);
+
+cleanup:
+ Py_CLEAR(py_result);
+ Py_CLEAR(py_loghandler);
+ Py_CLEAR(py_class);
+ Py_CLEAR(py_streamhandler);
+ Py_CLEAR(py_logger);
+ Py_CLEAR(py_logging_module);
+ Py_CLEAR(py_sudo);
+ debug_return_int(PyErr_Occurred() ? SUDO_RC_ERROR : SUDO_RC_OK);
+}
diff --git a/plugins/python/python_plugin.exp b/plugins/python/python_plugin.exp
new file mode 100644
index 0000000..1261a58
--- /dev/null
+++ b/plugins/python/python_plugin.exp
@@ -0,0 +1,8 @@
+group_plugin
+python_approval
+python_approval_clone
+python_audit
+python_audit_clone
+python_io
+python_io_clone
+python_policy
diff --git a/plugins/python/python_plugin_approval.c b/plugins/python/python_plugin_approval.c
new file mode 100644
index 0000000..b9c746e
--- /dev/null
+++ b/plugins/python/python_plugin_approval.c
@@ -0,0 +1,196 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include "python_plugin_common.h"
+
+struct ApprovalPluginContext
+{
+ struct PluginContext base_ctx;
+ struct approval_plugin *plugin;
+};
+
+#define BASE_CTX(approval_ctx) (&(approval_ctx->base_ctx))
+
+#define PY_APPROVAL_PLUGIN_VERSION SUDO_API_MKVERSION(1, 0)
+
+#define CALLBACK_PLUGINFUNC(func_name) approval_ctx->plugin->func_name
+
+// This also verifies compile time that the name matches the sudo plugin API.
+#define CALLBACK_PYNAME(func_name) ((void)CALLBACK_PLUGINFUNC(func_name), #func_name)
+
+sudo_dso_public struct approval_plugin *python_approval_clone(void);
+
+static int
+python_plugin_approval_open(struct ApprovalPluginContext *approval_ctx,
+ unsigned int version, sudo_conv_t conversation, sudo_printf_t sudo_printf,
+ char * const settings[], char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr)
+{
+ debug_decl(python_plugin_approval_open, PYTHON_DEBUG_CALLBACKS);
+ (void) version;
+
+ int rc = python_plugin_register_logging(conversation, sudo_printf, settings);
+ if (rc != SUDO_RC_OK) {
+ debug_return_int(rc);
+ }
+
+ struct PluginContext *plugin_ctx = BASE_CTX(approval_ctx);
+
+ rc = python_plugin_init(plugin_ctx, plugin_options, version);
+ if (rc != SUDO_RC_OK) {
+ debug_return_int(rc);
+ }
+
+ PyObject *py_kwargs = NULL, *py_submit_optind = NULL,
+ *py_submit_argv = NULL;
+
+ if ((py_kwargs = python_plugin_construct_args(version, settings, user_info,
+ submit_envp, plugin_options)) == NULL ||
+ (py_submit_optind = PyLong_FromLong(submit_optind)) == NULL ||
+ (py_submit_argv = py_str_array_to_tuple(submit_argv)) == NULL)
+ {
+ py_log_last_error("Failed to construct plugin instance");
+ rc = SUDO_RC_ERROR;
+ } else {
+ PyDict_SetItemString(py_kwargs, "submit_optind", py_submit_optind);
+ PyDict_SetItemString(py_kwargs, "submit_argv", py_submit_argv);
+
+ rc = python_plugin_construct_custom(plugin_ctx, py_kwargs);
+ CALLBACK_SET_ERROR(plugin_ctx, errstr);
+ }
+
+ Py_CLEAR(py_kwargs);
+ Py_CLEAR(py_submit_argv);
+ Py_CLEAR(py_submit_optind);
+
+ if (rc != SUDO_RC_OK) {
+ debug_return_int(rc);
+ }
+
+ debug_return_int(rc);
+}
+
+static void
+python_plugin_approval_close(struct ApprovalPluginContext *approval_ctx)
+{
+ debug_decl(python_plugin_approval_close, PYTHON_DEBUG_CALLBACKS);
+
+ struct PluginContext *plugin_ctx = BASE_CTX(approval_ctx);
+ PyThreadState_Swap(plugin_ctx->py_interpreter);
+ python_plugin_deinit(plugin_ctx);
+
+ debug_return;
+}
+
+static int
+python_plugin_approval_check(struct ApprovalPluginContext *approval_ctx,
+ char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr)
+{
+ debug_decl(python_plugin_approval_check, PYTHON_DEBUG_CALLBACKS);
+
+ struct PluginContext *plugin_ctx = BASE_CTX(approval_ctx);
+
+ PyObject *py_command_info = NULL, *py_run_argv = NULL, *py_run_envp = NULL,
+ *py_args = NULL;
+
+ int rc = SUDO_RC_ERROR;
+ if ((py_command_info = py_str_array_to_tuple(command_info)) != NULL &&
+ (py_run_argv = py_str_array_to_tuple(run_argv)) != NULL &&
+ (py_run_envp = py_str_array_to_tuple(run_envp)) != NULL)
+ {
+ py_args = Py_BuildValue("(OOO)", py_command_info, py_run_argv, py_run_envp);
+ }
+
+ // Note, py_args gets cleared by api_rc_call
+ rc = python_plugin_api_rc_call(plugin_ctx, CALLBACK_PYNAME(check), py_args);
+ CALLBACK_SET_ERROR(plugin_ctx, errstr);
+
+ Py_CLEAR(py_command_info);
+ Py_CLEAR(py_run_argv);
+ Py_CLEAR(py_run_envp);
+
+ debug_return_int(rc);
+}
+
+static int
+python_plugin_approval_show_version(struct ApprovalPluginContext *approval_ctx, int verbose)
+{
+ debug_decl(python_plugin_approval_show_version, PYTHON_DEBUG_CALLBACKS);
+
+ struct PluginContext *plugin_ctx = BASE_CTX(approval_ctx);
+ PyThreadState_Swap(plugin_ctx->py_interpreter);
+
+ debug_return_int(python_plugin_show_version(plugin_ctx,
+ CALLBACK_PYNAME(show_version), verbose, PY_APPROVAL_PLUGIN_VERSION, "approval"));
+}
+
+sudo_dso_public struct approval_plugin python_approval;
+
+// generate symbols for loading multiple approval plugins:
+#define APPROVAL_SYMBOL_NAME(symbol) symbol
+#include "python_plugin_approval_multi.inc"
+#define APPROVAL_SYMBOL_NAME(symbol) symbol##1
+#include "python_plugin_approval_multi.inc"
+#define APPROVAL_SYMBOL_NAME(symbol) symbol##2
+#include "python_plugin_approval_multi.inc"
+#define APPROVAL_SYMBOL_NAME(symbol) symbol##3
+#include "python_plugin_approval_multi.inc"
+#define APPROVAL_SYMBOL_NAME(symbol) symbol##4
+#include "python_plugin_approval_multi.inc"
+#define APPROVAL_SYMBOL_NAME(symbol) symbol##5
+#include "python_plugin_approval_multi.inc"
+#define APPROVAL_SYMBOL_NAME(symbol) symbol##6
+#include "python_plugin_approval_multi.inc"
+#define APPROVAL_SYMBOL_NAME(symbol) symbol##7
+#include "python_plugin_approval_multi.inc"
+
+static struct approval_plugin *extra_approval_plugins[] = {
+ &python_approval1,
+ &python_approval2,
+ &python_approval3,
+ &python_approval4,
+ &python_approval5,
+ &python_approval6,
+ &python_approval7
+};
+
+struct approval_plugin *
+python_approval_clone(void)
+{
+ static size_t counter = 0;
+ struct approval_plugin *next_plugin = NULL;
+
+ size_t max = sizeof(extra_approval_plugins) / sizeof(*extra_approval_plugins);
+ if (counter < max) {
+ next_plugin = extra_approval_plugins[counter];
+ ++counter;
+ } else if (counter == max) {
+ ++counter;
+ py_sudo_log(SUDO_CONV_ERROR_MSG,
+ "sudo: loading more than %d sudo python approval plugins is not supported\n", counter);
+ }
+
+ return next_plugin;
+}
diff --git a/plugins/python/python_plugin_approval_multi.inc b/plugins/python/python_plugin_approval_multi.inc
new file mode 100644
index 0000000..d5b15ff
--- /dev/null
+++ b/plugins/python/python_plugin_approval_multi.inc
@@ -0,0 +1,57 @@
+/* The purpose of this file is to generate a approval_plugin symbols,
+ * with an I/O plugin context which is unique to it and its functions.
+ * The callbacks inside are just wrappers around the real functions in python_plugin_approval.c,
+ * their only purpose is to add the unique context to each separate approval_plugin call.
+ */
+
+#define PLUGIN_CTX APPROVAL_SYMBOL_NAME(plugin_ctx)
+#define CALLBACK_CFUNC(func_name) APPROVAL_SYMBOL_NAME(_python_plugin_approval_ ## func_name)
+
+extern struct approval_plugin APPROVAL_SYMBOL_NAME(python_approval);
+static struct ApprovalPluginContext PLUGIN_CTX = { { NULL }, &APPROVAL_SYMBOL_NAME(python_approval) };
+
+
+static int
+CALLBACK_CFUNC(open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_printf, char * const settings[],
+ char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr)
+{
+ return python_plugin_approval_open(&PLUGIN_CTX, version, conversation,
+ sudo_printf, settings, user_info, submit_optind, submit_argv,
+ submit_envp, plugin_options, errstr);
+}
+
+static void
+CALLBACK_CFUNC(close)(void)
+{
+ python_plugin_approval_close(&PLUGIN_CTX);
+}
+
+static int
+CALLBACK_CFUNC(check)(char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr)
+{
+ return python_plugin_approval_check(&PLUGIN_CTX, command_info, run_argv,
+ run_envp, errstr);
+}
+
+static int
+CALLBACK_CFUNC(show_version)(int verbose)
+{
+ return python_plugin_approval_show_version(&PLUGIN_CTX, verbose);
+}
+
+struct approval_plugin APPROVAL_SYMBOL_NAME(python_approval) = {
+ SUDO_APPROVAL_PLUGIN,
+ SUDO_API_VERSION,
+ CALLBACK_CFUNC(open),
+ CALLBACK_CFUNC(close),
+ CALLBACK_CFUNC(check),
+ CALLBACK_CFUNC(show_version)
+};
+
+#undef PLUGIN_CTX
+#undef CALLBACK_CFUNC
+#undef APPROVAL_SYMBOL_NAME
diff --git a/plugins/python/python_plugin_audit.c b/plugins/python/python_plugin_audit.c
new file mode 100644
index 0000000..58d59f7
--- /dev/null
+++ b/plugins/python/python_plugin_audit.c
@@ -0,0 +1,281 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include "python_plugin_common.h"
+
+struct AuditPluginContext
+{
+ struct PluginContext base_ctx;
+ struct audit_plugin *plugin;
+};
+
+#define BASE_CTX(audit_ctx) (&(audit_ctx->base_ctx))
+
+#define PY_AUDIT_PLUGIN_VERSION SUDO_API_MKVERSION(1, 0)
+
+#define CALLBACK_PLUGINFUNC(func_name) audit_ctx->plugin->func_name
+
+// This also verifies compile time that the name matches the sudo plugin API.
+#define CALLBACK_PYNAME(func_name) ((void)CALLBACK_PLUGINFUNC(func_name), #func_name)
+
+#define MARK_CALLBACK_OPTIONAL(function_name) \
+ do { \
+ python_plugin_mark_callback_optional(plugin_ctx, CALLBACK_PYNAME(function_name), \
+ (void **)&CALLBACK_PLUGINFUNC(function_name)); \
+ } while(0)
+
+sudo_dso_public struct audit_plugin *python_audit_clone(void);
+
+static int
+_call_plugin_open(struct AuditPluginContext *audit_ctx, int submit_optind, char * const submit_argv[])
+{
+ debug_decl(_call_plugin_open, PYTHON_DEBUG_CALLBACKS);
+
+ struct PluginContext *plugin_ctx = BASE_CTX(audit_ctx);
+ if (!PyObject_HasAttrString(plugin_ctx->py_instance, CALLBACK_PYNAME(open))) {
+ debug_return_int(SUDO_RC_OK);
+ }
+
+ int rc = SUDO_RC_ERROR;
+ PyObject *py_submit_argv = py_str_array_to_tuple(submit_argv);
+
+ if (py_submit_argv != NULL) {
+ rc = python_plugin_api_rc_call(plugin_ctx, CALLBACK_PYNAME(open),
+ Py_BuildValue("(iO)", submit_optind, py_submit_argv));
+ }
+
+ Py_XDECREF(py_submit_argv);
+ debug_return_int(rc);
+}
+
+static int
+python_plugin_audit_open(struct AuditPluginContext *audit_ctx,
+ unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_printf, char * const settings[],
+ char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr)
+{
+ debug_decl(python_plugin_audit_open, PYTHON_DEBUG_CALLBACKS);
+ (void) version;
+
+ int rc = python_plugin_register_logging(conversation, sudo_printf, settings);
+ if (rc != SUDO_RC_OK) {
+ debug_return_int(rc);
+ }
+
+ struct PluginContext *plugin_ctx = BASE_CTX(audit_ctx);
+
+ rc = python_plugin_init(plugin_ctx, plugin_options, version);
+ if (rc != SUDO_RC_OK) {
+ debug_return_int(rc);
+ }
+
+ rc = python_plugin_construct(plugin_ctx, PY_AUDIT_PLUGIN_VERSION, settings,
+ user_info, submit_envp, plugin_options);
+ CALLBACK_SET_ERROR(plugin_ctx, errstr);
+ if (rc != SUDO_RC_OK) {
+ debug_return_int(rc);
+ }
+
+ // skip plugin callbacks which are not mandatory
+ MARK_CALLBACK_OPTIONAL(accept);
+ MARK_CALLBACK_OPTIONAL(reject);
+ MARK_CALLBACK_OPTIONAL(error);
+
+ plugin_ctx->call_close = 1;
+ rc = _call_plugin_open(audit_ctx, submit_optind, submit_argv);
+ CALLBACK_SET_ERROR(plugin_ctx, errstr);
+
+ if (PyErr_Occurred()) {
+ py_log_last_error("Error during calling audit open");
+ }
+
+ debug_return_int(rc);
+}
+
+static void
+python_plugin_audit_close(struct AuditPluginContext *audit_ctx, int status_type, int status)
+{
+ debug_decl(python_plugin_audit_close, PYTHON_DEBUG_CALLBACKS);
+
+ python_plugin_close(BASE_CTX(audit_ctx), CALLBACK_PYNAME(close),
+ Py_BuildValue("(ii)", status_type, status));
+
+ debug_return;
+}
+
+static int
+python_plugin_audit_accept(struct AuditPluginContext *audit_ctx,
+ const char *plugin_name, unsigned int plugin_type,
+ char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr)
+{
+ debug_decl(python_plugin_audit_accept, PYTHON_DEBUG_CALLBACKS);
+
+ struct PluginContext *plugin_ctx = BASE_CTX(audit_ctx);
+ PyThreadState_Swap(plugin_ctx->py_interpreter);
+
+ PyObject *py_command_info = NULL, *py_run_argv = NULL, *py_run_envp = NULL;
+ int rc = SUDO_RC_ERROR;
+
+ py_run_argv = py_str_array_to_tuple(run_argv);
+ if (py_run_argv == NULL)
+ goto cleanup;
+
+ py_command_info = py_str_array_to_tuple(command_info);
+ if (py_command_info == NULL)
+ goto cleanup;
+
+ py_run_envp = py_str_array_to_tuple(run_envp);
+ if (py_run_envp == NULL)
+ goto cleanup;
+
+ PyObject *py_args = Py_BuildValue("(ziOOO)", plugin_name, plugin_type, py_command_info, py_run_argv, py_run_envp);
+ rc = python_plugin_api_rc_call(plugin_ctx, CALLBACK_PYNAME(accept), py_args);
+ CALLBACK_SET_ERROR(plugin_ctx, errstr);
+
+cleanup:
+ Py_CLEAR(py_command_info);
+ Py_CLEAR(py_run_argv);
+ Py_CLEAR(py_run_envp);
+
+ debug_return_int(rc);
+}
+
+static int
+python_plugin_audit_reject(struct AuditPluginContext *audit_ctx,
+ const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[], const char **errstr)
+{
+ debug_decl(python_plugin_audit_reject, PYTHON_DEBUG_CALLBACKS);
+
+ struct PluginContext *plugin_ctx = BASE_CTX(audit_ctx);
+ PyThreadState_Swap(plugin_ctx->py_interpreter);
+
+ PyObject *py_command_info = NULL;
+ int rc = SUDO_RC_ERROR;
+
+ py_command_info = py_str_array_to_tuple(command_info);
+ if (PyErr_Occurred())
+ goto cleanup;
+
+ PyObject *py_args = Py_BuildValue("(zizO)", plugin_name, plugin_type, audit_msg, py_command_info);
+ rc = python_plugin_api_rc_call(plugin_ctx, CALLBACK_PYNAME(reject), py_args);
+
+ CALLBACK_SET_ERROR(plugin_ctx, errstr);
+
+cleanup:
+ Py_CLEAR(py_command_info);
+ if (PyErr_Occurred())
+ py_log_last_error("Error during calling audit reject");
+
+ debug_return_int(rc);
+}
+
+static int
+python_plugin_audit_error(struct AuditPluginContext *audit_ctx,
+ const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[], const char **errstr)
+{
+ debug_decl(python_plugin_audit_error, PYTHON_DEBUG_CALLBACKS);
+
+ struct PluginContext *plugin_ctx = BASE_CTX(audit_ctx);
+ PyThreadState_Swap(plugin_ctx->py_interpreter);
+
+ PyObject *py_command_info = NULL;
+ int rc = SUDO_RC_ERROR;
+
+ py_command_info = py_str_array_to_tuple(command_info);
+ if (PyErr_Occurred())
+ goto cleanup;
+
+ PyObject *py_args = Py_BuildValue("(zizO)", plugin_name, plugin_type, audit_msg, py_command_info);
+ rc = python_plugin_api_rc_call(plugin_ctx, CALLBACK_PYNAME(error), py_args);
+ CALLBACK_SET_ERROR(plugin_ctx, errstr);
+
+cleanup:
+ Py_CLEAR(py_command_info);
+
+ debug_return_int(rc);
+}
+
+static int
+python_plugin_audit_show_version(struct AuditPluginContext *audit_ctx, int verbose)
+{
+ debug_decl(python_plugin_audit_show_version, PYTHON_DEBUG_CALLBACKS);
+
+ struct PluginContext *plugin_ctx = BASE_CTX(audit_ctx);
+ PyThreadState_Swap(plugin_ctx->py_interpreter);
+
+ debug_return_int(python_plugin_show_version(plugin_ctx,
+ CALLBACK_PYNAME(show_version), verbose, PY_AUDIT_PLUGIN_VERSION, "audit"));
+}
+
+sudo_dso_public struct audit_plugin python_audit;
+
+// generate symbols for loading multiple audit plugins:
+#define AUDIT_SYMBOL_NAME(symbol) symbol
+#include "python_plugin_audit_multi.inc"
+#define AUDIT_SYMBOL_NAME(symbol) symbol##1
+#include "python_plugin_audit_multi.inc"
+#define AUDIT_SYMBOL_NAME(symbol) symbol##2
+#include "python_plugin_audit_multi.inc"
+#define AUDIT_SYMBOL_NAME(symbol) symbol##3
+#include "python_plugin_audit_multi.inc"
+#define AUDIT_SYMBOL_NAME(symbol) symbol##4
+#include "python_plugin_audit_multi.inc"
+#define AUDIT_SYMBOL_NAME(symbol) symbol##5
+#include "python_plugin_audit_multi.inc"
+#define AUDIT_SYMBOL_NAME(symbol) symbol##6
+#include "python_plugin_audit_multi.inc"
+#define AUDIT_SYMBOL_NAME(symbol) symbol##7
+#include "python_plugin_audit_multi.inc"
+
+static struct audit_plugin *extra_audit_plugins[] = {
+ &python_audit1,
+ &python_audit2,
+ &python_audit3,
+ &python_audit4,
+ &python_audit5,
+ &python_audit6,
+ &python_audit7
+};
+
+struct audit_plugin *
+python_audit_clone(void)
+{
+ static size_t counter = 0;
+ struct audit_plugin *next_plugin = NULL;
+
+ size_t max = sizeof(extra_audit_plugins) / sizeof(*extra_audit_plugins);
+ if (counter < max) {
+ next_plugin = extra_audit_plugins[counter];
+ ++counter;
+ } else if (counter == max) {
+ ++counter;
+ py_sudo_log(SUDO_CONV_ERROR_MSG, "sudo: loading more than %d sudo python audit plugins is not supported\n", counter);
+ }
+
+ return next_plugin;
+}
diff --git a/plugins/python/python_plugin_audit_multi.inc b/plugins/python/python_plugin_audit_multi.inc
new file mode 100644
index 0000000..015b4d1
--- /dev/null
+++ b/plugins/python/python_plugin_audit_multi.inc
@@ -0,0 +1,78 @@
+/* The purpose of this file is to generate a audit_plugin symbols,
+ * with an I/O plugin context which is unique to it and its functions.
+ * The callbacks inside are just wrappers around the real functions in python_plugin_audit.c,
+ * their only purpose is to add the unique context to each separate audit_plugin call.
+ */
+
+#define PLUGIN_CTX AUDIT_SYMBOL_NAME(plugin_ctx)
+#define CALLBACK_CFUNC(func_name) AUDIT_SYMBOL_NAME(_python_plugin_audit_ ## func_name)
+
+extern struct audit_plugin AUDIT_SYMBOL_NAME(python_audit);
+static struct AuditPluginContext PLUGIN_CTX = { { NULL }, &AUDIT_SYMBOL_NAME(python_audit) };
+
+
+static int
+CALLBACK_CFUNC(open)(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_printf, char * const settings[],
+ char * const user_info[], int submit_optind,
+ char * const submit_argv[], char * const submit_envp[],
+ char * const plugin_options[], const char **errstr)
+{
+ return python_plugin_audit_open(&PLUGIN_CTX, version, conversation, sudo_printf,
+ settings, user_info, submit_optind, submit_argv, submit_envp,
+ plugin_options, errstr);
+}
+
+static void
+CALLBACK_CFUNC(close)(int status_type, int status)
+{
+ python_plugin_audit_close(&PLUGIN_CTX, status_type, status);
+}
+
+static int
+CALLBACK_CFUNC(accept)(const char *plugin_name, unsigned int plugin_type,
+ char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr)
+{
+ return python_plugin_audit_accept(&PLUGIN_CTX, plugin_name, plugin_type,
+ command_info, run_argv, run_envp, errstr);
+}
+
+static int
+CALLBACK_CFUNC(reject)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[], const char **errstr)
+{
+ return python_plugin_audit_reject(&PLUGIN_CTX, plugin_name, plugin_type,
+ audit_msg, command_info, errstr);
+}
+
+static int
+CALLBACK_CFUNC(error)(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[], const char **errstr)
+{
+ return python_plugin_audit_error(&PLUGIN_CTX, plugin_name, plugin_type,
+ audit_msg, command_info, errstr);
+}
+
+static int
+CALLBACK_CFUNC(show_version)(int verbose)
+{
+ return python_plugin_audit_show_version(&PLUGIN_CTX, verbose);
+}
+
+struct audit_plugin AUDIT_SYMBOL_NAME(python_audit) = {
+ SUDO_AUDIT_PLUGIN,
+ SUDO_API_VERSION,
+ CALLBACK_CFUNC(open),
+ CALLBACK_CFUNC(close),
+ CALLBACK_CFUNC(accept),
+ CALLBACK_CFUNC(reject),
+ CALLBACK_CFUNC(error),
+ CALLBACK_CFUNC(show_version),
+ NULL, /* register_hooks */
+ NULL /* deregister_hooks */
+};
+
+#undef PLUGIN_CTX
+#undef CALLBACK_CFUNC
+#undef AUDIT_SYMBOL_NAME
diff --git a/plugins/python/python_plugin_common.c b/plugins/python/python_plugin_common.c
new file mode 100644
index 0000000..6afceac
--- /dev/null
+++ b/plugins/python/python_plugin_common.c
@@ -0,0 +1,781 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include "python_plugin_common.h"
+#include "sudo_python_module.h"
+
+#include <sudo_queue.h>
+#include <sudo_conf.h>
+
+#include <limits.h>
+#include <string.h>
+
+static struct _inittab * python_inittab_copy = NULL;
+static size_t python_inittab_copy_len = 0;
+
+#ifndef PLUGIN_DIR
+#define PLUGIN_DIR ""
+#endif
+
+/* Py_FinalizeEx is new in version 3.6 */
+#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 6
+# define Py_FinalizeEx() (Py_Finalize(), 0)
+#endif
+
+static const char *
+_lookup_value(char * const keyvalues[], const char *key)
+{
+ debug_decl(_lookup_value, PYTHON_DEBUG_INTERNAL);
+ if (keyvalues == NULL)
+ debug_return_const_str(NULL);
+
+ size_t keylen = strlen(key);
+ for (; *keyvalues != NULL; ++keyvalues) {
+ const char *keyvalue = *keyvalues;
+ if (strncmp(keyvalue, key, keylen) == 0 && keyvalue[keylen] == '=')
+ debug_return_const_str(keyvalue + keylen + 1);
+ }
+ debug_return_const_str(NULL);
+}
+
+CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
+static int
+_append_python_path(const char *module_dir)
+{
+ debug_decl(_append_python_path, PYTHON_DEBUG_PLUGIN_LOAD);
+ int rc = -1;
+ PyObject *py_sys_path = PySys_GetObject("path"); // borrowed
+ if (py_sys_path == NULL) {
+ PyErr_Format(sudo_exc_SudoException, "Failed to get python 'path'");
+ debug_return_int(rc);
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "Extending python 'path' with '%s'\n", module_dir);
+
+ PyObject *py_module_dir = PyUnicode_FromString(module_dir);
+ if (py_module_dir == NULL || PyList_Append(py_sys_path, py_module_dir) != 0) {
+ Py_XDECREF(py_module_dir);
+ debug_return_int(rc);
+ }
+ Py_DECREF(py_module_dir);
+
+ if (sudo_debug_needed(SUDO_DEBUG_INFO)) {
+ char *path = py_join_str_list(py_sys_path, ":");
+ sudo_debug_printf(SUDO_DEBUG_INFO, "Python path became: %s\n", path);
+ free(path);
+ }
+
+ rc = 0;
+ debug_return_int(rc);
+}
+
+static PyObject *
+_import_module(const char *path)
+{
+ PyObject *module;
+ debug_decl(_import_module, PYTHON_DEBUG_PLUGIN_LOAD);
+
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "importing module: %s\n", path);
+
+ char path_copy[PATH_MAX];
+ if (strlcpy(path_copy, path, sizeof(path_copy)) >= sizeof(path_copy))
+ debug_return_ptr(NULL);
+
+ const char *module_dir = path_copy;
+ char *module_name = strrchr(path_copy, '/');
+ if (module_name == NULL) {
+ module_name = path_copy;
+ module_dir = "";
+ } else {
+ *module_name++ = '\0';
+ }
+
+ size_t len = strlen(module_name);
+ if (len >= 3 && strcmp(".py", module_name + len - 3) == 0)
+ module_name[len - 3] = '\0';
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "module_name: '%s', module_dir: '%s'\n", module_name, module_dir);
+
+ if (_append_python_path(module_dir) < 0)
+ debug_return_ptr(NULL);
+
+ module = PyImport_ImportModule(module_name);
+ if (module != NULL) {
+ PyObject *py_loaded_path = PyObject_GetAttrString(module, "__file__");
+ if (py_loaded_path != NULL) {
+ const char *loaded_path = PyUnicode_AsUTF8(py_loaded_path);
+ /* If path is a directory, loaded_path may be a file inside it. */
+ if (strncmp(loaded_path, path, strlen(path)) != 0) {
+ PyErr_Format(PyExc_Exception,
+ "module name conflict, tried to load %s, got %s",
+ path, loaded_path);
+ Py_CLEAR(module);
+ }
+ Py_DECREF(py_loaded_path);
+ }
+ }
+ debug_return_ptr(module);
+}
+
+// Create a new sub-interpreter and switch to it.
+static PyThreadState *
+_python_plugin_new_interpreter(void)
+{
+ debug_decl(_python_plugin_new_interpreter, PYTHON_DEBUG_INTERNAL);
+ if (py_ctx.interpreter_count >= INTERPRETER_MAX) {
+ PyErr_Format(PyExc_Exception, "Too many interpreters");
+ debug_return_ptr(NULL);
+ }
+
+ PyThreadState *py_interpreter = Py_NewInterpreter();
+ if (py_interpreter != NULL) {
+ py_ctx.py_subinterpreters[py_ctx.interpreter_count] = py_interpreter;
+ ++py_ctx.interpreter_count;
+ }
+
+ debug_return_ptr(py_interpreter);
+}
+
+static int
+_save_inittab(void)
+{
+ debug_decl(_save_inittab, PYTHON_DEBUG_INTERNAL);
+ free(python_inittab_copy); // just to be sure (it is always NULL)
+
+ for (python_inittab_copy_len = 0;
+ PyImport_Inittab[python_inittab_copy_len].name != NULL;
+ ++python_inittab_copy_len) {
+ }
+ ++python_inittab_copy_len; // for the null mark
+
+ python_inittab_copy = malloc(sizeof(struct _inittab) * python_inittab_copy_len);
+ if (python_inittab_copy == NULL) {
+ debug_return_int(SUDO_RC_ERROR);
+ }
+
+ memcpy(python_inittab_copy, PyImport_Inittab, python_inittab_copy_len * sizeof(struct _inittab));
+ debug_return_int(SUDO_RC_OK);
+}
+
+static void
+_restore_inittab(void)
+{
+ debug_decl(_restore_inittab, PYTHON_DEBUG_INTERNAL);
+
+ if (python_inittab_copy != NULL)
+ memcpy(PyImport_Inittab, python_inittab_copy, python_inittab_copy_len * sizeof(struct _inittab));
+
+ free(python_inittab_copy);
+ python_inittab_copy = NULL;
+ python_inittab_copy_len = 0;
+ debug_return;
+}
+
+static void
+python_plugin_handle_plugin_error_exception(PyObject **py_result, struct PluginContext *plugin_ctx)
+{
+ debug_decl(python_plugin_handle_plugin_error_exception, PYTHON_DEBUG_INTERNAL);
+
+ free(plugin_ctx->callback_error);
+ plugin_ctx->callback_error = NULL;
+
+ if (PyErr_Occurred()) {
+ int rc = SUDO_RC_ERROR;
+ if (PyErr_ExceptionMatches(sudo_exc_PluginReject)) {
+ rc = SUDO_RC_REJECT;
+ } else if (!PyErr_ExceptionMatches(sudo_exc_PluginError)) {
+ debug_return;
+ }
+
+ if (py_result != NULL) {
+ Py_CLEAR(*py_result);
+ *py_result = PyLong_FromLong(rc);
+ }
+
+ PyObject *py_type = NULL, *py_message = NULL, *py_traceback = NULL;
+ PyErr_Fetch(&py_type, &py_message, &py_traceback);
+
+ char *message = py_message ? py_create_string_rep(py_message) : NULL;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "received sudo.PluginError exception with message '%s'",
+ message == NULL ? "(null)" : message);
+
+ plugin_ctx->callback_error = message;
+
+ Py_CLEAR(py_type);
+ Py_CLEAR(py_message);
+ Py_CLEAR(py_traceback);
+ }
+
+ debug_return;
+}
+
+int
+python_plugin_construct_custom(struct PluginContext *plugin_ctx, PyObject *py_kwargs)
+{
+ debug_decl(python_plugin_construct_custom, PYTHON_DEBUG_PLUGIN_LOAD);
+ int rc = SUDO_RC_ERROR;
+ PyObject *py_args = PyTuple_New(0);
+
+ if (py_args == NULL)
+ goto cleanup;
+
+ py_debug_python_call(python_plugin_name(plugin_ctx), "__init__",
+ py_args, py_kwargs, PYTHON_DEBUG_PY_CALLS);
+
+ plugin_ctx->py_instance = PyObject_Call(plugin_ctx->py_class, py_args, py_kwargs);
+ python_plugin_handle_plugin_error_exception(NULL, plugin_ctx);
+
+ py_debug_python_result(python_plugin_name(plugin_ctx), "__init__",
+ plugin_ctx->py_instance, PYTHON_DEBUG_PY_CALLS);
+
+ if (plugin_ctx->py_instance)
+ rc = SUDO_RC_OK;
+
+cleanup:
+ if (PyErr_Occurred()) {
+ py_log_last_error("Failed to construct plugin instance");
+ Py_CLEAR(plugin_ctx->py_instance);
+ rc = SUDO_RC_ERROR;
+ }
+
+ Py_XDECREF(py_args);
+ debug_return_int(rc);
+}
+
+PyObject *
+python_plugin_construct_args(unsigned int version,
+ char *const settings[], char *const user_info[],
+ char *const user_env[], char *const plugin_options[])
+{
+ PyObject *py_settings = NULL;
+ PyObject *py_user_info = NULL;
+ PyObject *py_user_env = NULL;
+ PyObject *py_plugin_options = NULL;
+ PyObject *py_version = NULL;
+ PyObject *py_kwargs = NULL;
+
+ if ((py_settings = py_str_array_to_tuple(settings)) == NULL ||
+ (py_user_info = py_str_array_to_tuple(user_info)) == NULL ||
+ (py_user_env = py_str_array_to_tuple(user_env)) == NULL ||
+ (py_plugin_options = py_str_array_to_tuple(plugin_options)) == NULL ||
+ (py_version = py_create_version(version)) == NULL ||
+ (py_kwargs = PyDict_New()) == NULL ||
+ PyDict_SetItemString(py_kwargs, "version", py_version) != 0 ||
+ PyDict_SetItemString(py_kwargs, "settings", py_settings) != 0 ||
+ PyDict_SetItemString(py_kwargs, "user_env", py_user_env) != 0 ||
+ PyDict_SetItemString(py_kwargs, "user_info", py_user_info) != 0 ||
+ PyDict_SetItemString(py_kwargs, "plugin_options", py_plugin_options) != 0)
+ {
+ Py_CLEAR(py_kwargs);
+ }
+
+ Py_CLEAR(py_settings);
+ Py_CLEAR(py_user_info);
+ Py_CLEAR(py_user_env);
+ Py_CLEAR(py_plugin_options);
+ Py_CLEAR(py_version);
+ return py_kwargs;
+}
+
+int
+python_plugin_construct(struct PluginContext *plugin_ctx, unsigned int version,
+ char *const settings[], char *const user_info[],
+ char *const user_env[], char *const plugin_options[])
+{
+ debug_decl(python_plugin_construct, PYTHON_DEBUG_PLUGIN_LOAD);
+
+ int rc = SUDO_RC_ERROR;
+ PyObject *py_kwargs = python_plugin_construct_args(
+ version, settings, user_info, user_env, plugin_options);
+
+ if (py_kwargs == NULL) {
+ py_log_last_error("Failed to construct plugin instance");
+ } else {
+ rc = python_plugin_construct_custom(plugin_ctx, py_kwargs);
+ }
+
+ Py_CLEAR(py_kwargs);
+
+ debug_return_int(rc);
+}
+
+int
+python_plugin_register_logging(sudo_conv_t conversation,
+ sudo_printf_t sudo_printf,
+ char * const settings[])
+{
+ debug_decl(python_plugin_register_logging, PYTHON_DEBUG_INTERNAL);
+
+ int rc = SUDO_RC_ERROR;
+ if (conversation != NULL)
+ py_ctx.sudo_conv = conversation;
+
+ if (sudo_printf)
+ py_ctx.sudo_log = sudo_printf;
+
+ struct sudo_conf_debug_file_list debug_files = TAILQ_HEAD_INITIALIZER(debug_files);
+ struct sudo_conf_debug_file_list *debug_files_ptr = &debug_files;
+
+ const char *plugin_path = _lookup_value(settings, "plugin_path");
+ if (plugin_path == NULL)
+ plugin_path = "python_plugin.so";
+
+ const char *debug_flags = _lookup_value(settings, "debug_flags");
+
+ if (debug_flags == NULL) { // the group plugin does not have this information, so try to look it up
+ debug_files_ptr = sudo_conf_debug_files(plugin_path);
+ } else {
+ if (!python_debug_parse_flags(&debug_files, debug_flags))
+ goto cleanup;
+ }
+
+ if (debug_files_ptr != NULL) {
+ if (!python_debug_register(plugin_path, debug_files_ptr))
+ goto cleanup;
+ }
+
+ rc = SUDO_RC_OK;
+
+cleanup:
+ debug_return_int(rc);
+}
+
+CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
+static int
+_python_plugin_register_plugin_in_py_ctx(void)
+{
+ debug_decl(_python_plugin_register_plugin_in_py_ctx, PYTHON_DEBUG_PLUGIN_LOAD);
+
+ if (!Py_IsInitialized()) {
+ // Disable environment variables effecting the python interpreter
+ // This is important since we are running code here as root, the
+ // user should not be able to alter what is running any how.
+#if (PY_MAJOR_VERSION > 3) || (PY_MINOR_VERSION >= 8)
+ PyStatus status;
+ PyPreConfig preconfig;
+ PyConfig config;
+
+ PyPreConfig_InitPythonConfig(&preconfig);
+ preconfig.isolated = 1;
+ preconfig.use_environment = 0;
+ status = Py_PreInitialize(&preconfig);
+ if (PyStatus_Exception(status))
+ debug_return_int(SUDO_RC_ERROR);
+
+ /* Inittab changes happen after pre-init but before init. */
+ if (_save_inittab() != SUDO_RC_OK)
+ debug_return_int(SUDO_RC_ERROR);
+ PyImport_AppendInittab("sudo", sudo_module_init);
+
+ PyConfig_InitPythonConfig(&config);
+ config.isolated = 1;
+ status = Py_InitializeFromConfig(&config);
+ PyConfig_Clear(&config);
+ if (PyStatus_Exception(status))
+ debug_return_int(SUDO_RC_ERROR);
+#else
+ Py_IgnoreEnvironmentFlag = 1;
+ Py_IsolatedFlag = 1;
+ Py_NoUserSiteDirectory = 1;
+
+ if (_save_inittab() != SUDO_RC_OK)
+ debug_return_int(SUDO_RC_ERROR);
+ PyImport_AppendInittab("sudo", sudo_module_init);
+ Py_InitializeEx(0);
+#endif
+ py_ctx.py_main_interpreter = PyThreadState_Get();
+
+ // This ensures we import "sudo" module in the main interpreter,
+ // each subinterpreter will have a shallow copy.
+ // (This makes the C sudo module able to eg. import other modules.)
+ PyObject *py_sudo = NULL;
+ if ((py_sudo = PyImport_ImportModule("sudo")) == NULL) {
+ debug_return_int(SUDO_RC_ERROR);
+ }
+ Py_CLEAR(py_sudo);
+ } else {
+ PyThreadState_Swap(py_ctx.py_main_interpreter);
+ }
+
+ debug_return_int(SUDO_RC_OK);
+}
+
+static int
+_python_plugin_set_path(struct PluginContext *plugin_ctx, const char *path)
+{
+ if (path == NULL) {
+ py_sudo_log(SUDO_CONV_ERROR_MSG, "No python module path is specified. "
+ "Use 'ModulePath' plugin config option in 'sudo.conf'\n");
+ return SUDO_RC_ERROR;
+ }
+
+ if (*path == '/') { // absolute path
+ plugin_ctx->plugin_path = strdup(path);
+ } else {
+ if (asprintf(&plugin_ctx->plugin_path, PLUGIN_DIR "/python/%s", path) < 0)
+ plugin_ctx->plugin_path = NULL;
+ }
+
+ if (plugin_ctx->plugin_path == NULL) {
+ py_sudo_log(SUDO_CONV_ERROR_MSG, "Failed to allocate memory");
+ return SUDO_RC_ERROR;
+ }
+
+ return SUDO_RC_OK;
+}
+
+/* Returns the list of sudo.Plugins in a module */
+static PyObject *
+_python_plugin_class_list(PyObject *py_module) {
+ PyObject *py_module_dict = PyModule_GetDict(py_module); // Note: borrowed
+ PyObject *key, *value; // Note: borrowed
+ Py_ssize_t pos = 0;
+ PyObject *py_plugin_list = PyList_New(0);
+
+ while (PyDict_Next(py_module_dict, &pos, &key, &value)) {
+ if (PyObject_IsSubclass(value, (PyObject *)sudo_type_Plugin) == 1) {
+ if (PyList_Append(py_plugin_list, key) != 0)
+ goto cleanup;
+ } else {
+ PyErr_Clear();
+ }
+ }
+
+cleanup:
+ if (PyErr_Occurred()) {
+ Py_CLEAR(py_plugin_list);
+ }
+ return py_plugin_list;
+}
+
+/* Gets a sudo.Plugin class from the specified module. The argument "plugin_class"
+ * can be NULL in which case it loads the one and only "sudo.Plugin" present
+ * in the module (if so), or displays helpful error message. */
+static PyObject *
+_python_plugin_get_class(const char *plugin_path, PyObject *py_module, const char *plugin_class)
+{
+ debug_decl(_python_plugin_get_class, PYTHON_DEBUG_PLUGIN_LOAD);
+ PyObject *py_plugin_list = NULL, *py_class = NULL;
+
+ if (plugin_class == NULL) {
+ py_plugin_list = _python_plugin_class_list(py_module);
+ if (py_plugin_list == NULL) {
+ goto cleanup;
+ }
+
+ if (PyList_Size(py_plugin_list) == 1) {
+ PyObject *py_plugin_name = PyList_GetItem(py_plugin_list, 0); // Note: borrowed
+ plugin_class = PyUnicode_AsUTF8(py_plugin_name);
+ }
+ }
+
+ if (plugin_class == NULL) {
+ py_sudo_log(SUDO_CONV_ERROR_MSG, "No plugin class is specified for python module '%s'. "
+ "Use 'ClassName' configuration option in 'sudo.conf'\n", plugin_path);
+ if (py_plugin_list != NULL) {
+ /* Sorting the plugin list makes regress test output consistent. */
+ PyObject *py_obj = PyObject_CallMethod(py_plugin_list, "sort", "");
+ Py_CLEAR(py_obj);
+ char *possible_plugins = py_join_str_list(py_plugin_list, ", ");
+ if (possible_plugins != NULL) {
+ py_sudo_log(SUDO_CONV_ERROR_MSG, "Possible plugins: %s\n", possible_plugins);
+ free(possible_plugins);
+ }
+ }
+ goto cleanup;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "Using plugin class '%s'", plugin_class);
+ py_class = PyObject_GetAttrString(py_module, plugin_class);
+ if (py_class == NULL) {
+ py_sudo_log(SUDO_CONV_ERROR_MSG, "Failed to find plugin class '%s'\n", plugin_class);
+ PyErr_Clear();
+ goto cleanup;
+ }
+
+ if (!PyObject_IsSubclass(py_class, (PyObject *)sudo_type_Plugin)) {
+ py_sudo_log(SUDO_CONV_ERROR_MSG, "Plugin class '%s' does not inherit from 'sudo.Plugin'\n", plugin_class);
+ Py_CLEAR(py_class);
+ goto cleanup;
+ }
+
+cleanup:
+ Py_CLEAR(py_plugin_list);
+ debug_return_ptr(py_class);
+}
+
+int
+python_plugin_init(struct PluginContext *plugin_ctx, char * const plugin_options[],
+ unsigned int version)
+{
+ debug_decl(python_plugin_init, PYTHON_DEBUG_PLUGIN_LOAD);
+
+ int rc = SUDO_RC_ERROR;
+
+ if (_python_plugin_register_plugin_in_py_ctx() != SUDO_RC_OK)
+ goto cleanup;
+
+ plugin_ctx->sudo_api_version = version;
+
+ plugin_ctx->py_interpreter = _python_plugin_new_interpreter();
+ if (plugin_ctx->py_interpreter == NULL) {
+ goto cleanup;
+ }
+
+ if (sudo_module_set_default_loghandler() != SUDO_RC_OK) {
+ goto cleanup;
+ }
+
+ if (_python_plugin_set_path(plugin_ctx, _lookup_value(plugin_options, "ModulePath")) != SUDO_RC_OK) {
+ goto cleanup;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "Loading python module from path '%s'", plugin_ctx->plugin_path);
+ plugin_ctx->py_module = _import_module(plugin_ctx->plugin_path);
+ if (plugin_ctx->py_module == NULL) {
+ goto cleanup;
+ }
+
+ plugin_ctx->py_class = _python_plugin_get_class(plugin_ctx->plugin_path, plugin_ctx->py_module,
+ _lookup_value(plugin_options, "ClassName"));
+ if (plugin_ctx->py_class == NULL) {
+ goto cleanup;
+ }
+
+ rc = SUDO_RC_OK;
+
+cleanup:
+ if (plugin_ctx->py_class == NULL) {
+ py_log_last_error("Failed during loading plugin class");
+ rc = SUDO_RC_ERROR;
+ }
+
+ debug_return_int(rc);
+}
+
+void
+python_plugin_deinit(struct PluginContext *plugin_ctx)
+{
+ debug_decl(python_plugin_deinit, PYTHON_DEBUG_PLUGIN_LOAD);
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "Deinit was called for a python plugin\n");
+
+ Py_CLEAR(plugin_ctx->py_instance);
+ Py_CLEAR(plugin_ctx->py_class);
+ Py_CLEAR(plugin_ctx->py_module);
+
+ // Note: we are preserving the interpreters here until the unlink because
+ // of bugs like (strptime does not work after python interpreter reinit):
+ // https://bugs.python.org/issue27400
+ // These potentially effect a lot more python functions, simply because
+ // it is a rare tested scenario.
+
+ free(plugin_ctx->callback_error);
+ free(plugin_ctx->plugin_path);
+ memset(plugin_ctx, 0, sizeof(*plugin_ctx));
+
+ python_debug_deregister();
+ debug_return;
+}
+
+PyObject *
+python_plugin_api_call(struct PluginContext *plugin_ctx, const char *func_name, PyObject *py_args)
+{
+ debug_decl(python_plugin_api_call, PYTHON_DEBUG_PY_CALLS);
+
+ // Note: call fails if py_args is an empty tuple. Passing no arguments works passing NULL
+ // instead. So having such must be handled as valid. (See policy_plugin.validate())
+ if (py_args == NULL && PyErr_Occurred()) {
+ py_sudo_log(SUDO_CONV_ERROR_MSG, "Failed to build arguments for python plugin API call '%s'\n", func_name);
+ py_log_last_error(NULL);
+ debug_return_ptr(NULL);
+ }
+
+ PyObject *py_callable = NULL;
+ py_callable = PyObject_GetAttrString(plugin_ctx->py_instance, func_name);
+
+ if (py_callable == NULL) {
+ Py_CLEAR(py_args);
+ debug_return_ptr(NULL);
+ }
+
+ py_debug_python_call(python_plugin_name(plugin_ctx), func_name,
+ py_args, NULL, PYTHON_DEBUG_PY_CALLS);
+
+ PyObject *py_result = PyObject_CallObject(py_callable, py_args);
+ Py_CLEAR(py_args);
+ Py_CLEAR(py_callable);
+
+ py_debug_python_result(python_plugin_name(plugin_ctx), func_name,
+ py_result, PYTHON_DEBUG_PY_CALLS);
+
+ python_plugin_handle_plugin_error_exception(&py_result, plugin_ctx);
+
+ if (PyErr_Occurred()) {
+ py_log_last_error(NULL);
+ }
+
+ debug_return_ptr(py_result);
+}
+
+int
+python_plugin_rc_to_int(PyObject *py_result)
+{
+ debug_decl(python_plugin_rc_to_int, PYTHON_DEBUG_PY_CALLS);
+ if (py_result == NULL)
+ debug_return_int(SUDO_RC_ERROR);
+
+ if (py_result == Py_None)
+ debug_return_int(SUDO_RC_OK);
+
+ debug_return_int((int)PyLong_AsLong(py_result));
+}
+
+int
+python_plugin_api_rc_call(struct PluginContext *plugin_ctx, const char *func_name, PyObject *py_args)
+{
+ debug_decl(python_plugin_api_rc_call, PYTHON_DEBUG_PY_CALLS);
+
+ PyObject *py_result = python_plugin_api_call(plugin_ctx, func_name, py_args);
+ int rc = python_plugin_rc_to_int(py_result);
+ Py_XDECREF(py_result);
+ debug_return_int(rc);
+}
+
+int
+python_plugin_show_version(struct PluginContext *plugin_ctx, const char *python_callback_name,
+ int is_verbose, unsigned int plugin_api_version, const char *plugin_api_name)
+{
+ debug_decl(python_plugin_show_version, PYTHON_DEBUG_CALLBACKS);
+
+ if (is_verbose) {
+ py_sudo_log(SUDO_CONV_INFO_MSG, "Python %s plugin (API %d.%d): %s (loaded from '%s')\n",
+ plugin_api_name,
+ SUDO_API_VERSION_GET_MAJOR(plugin_api_version),
+ SUDO_API_VERSION_GET_MINOR(plugin_api_version),
+ python_plugin_name(plugin_ctx),
+ plugin_ctx->plugin_path);
+ }
+
+ int rc = SUDO_RC_OK;
+ if (PyObject_HasAttrString(plugin_ctx->py_instance, python_callback_name)) {
+ rc = python_plugin_api_rc_call(plugin_ctx, python_callback_name,
+ Py_BuildValue("(i)", is_verbose));
+ }
+
+ debug_return_int(rc);
+}
+
+void
+python_plugin_close(struct PluginContext *plugin_ctx, const char *callback_name,
+ PyObject *py_args)
+{
+ debug_decl(python_plugin_close, PYTHON_DEBUG_CALLBACKS);
+
+ PyThreadState_Swap(plugin_ctx->py_interpreter);
+
+ // Note, this should handle the case when init has failed
+ if (plugin_ctx->py_instance != NULL) {
+ if (!plugin_ctx->call_close) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "Skipping close call, because there was no command run\n");
+
+ } else if (!PyObject_HasAttrString(plugin_ctx->py_instance, callback_name)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "Python plugin function 'close' is skipped (not present)\n");
+ } else {
+ PyObject *py_result = python_plugin_api_call(plugin_ctx, callback_name, py_args);
+ py_args = NULL; // api call already freed it
+ Py_XDECREF(py_result);
+ }
+ }
+
+ Py_CLEAR(py_args);
+
+ if (PyErr_Occurred()) {
+ py_log_last_error(NULL);
+ }
+
+ python_plugin_deinit(plugin_ctx);
+ PyThreadState_Swap(py_ctx.py_main_interpreter);
+
+ debug_return;
+}
+
+void
+python_plugin_mark_callback_optional(struct PluginContext *plugin_ctx,
+ const char *function_name, void **function)
+{
+ if (!PyObject_HasAttrString(plugin_ctx->py_instance, function_name)) {
+ debug_decl_vars(python_plugin_mark_callback_optional, PYTHON_DEBUG_PY_CALLS);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s function '%s' is not implemented\n",
+ Py_TYPENAME(plugin_ctx->py_instance), function_name);
+ *function = NULL;
+ }
+}
+
+const char *
+python_plugin_name(struct PluginContext *plugin_ctx)
+{
+ debug_decl(python_plugin_name, PYTHON_DEBUG_INTERNAL);
+
+ const char *name = "(NULL)";
+
+ if (plugin_ctx == NULL || !PyType_Check(plugin_ctx->py_class))
+ debug_return_const_str(name);
+
+ debug_return_const_str(((PyTypeObject *)(plugin_ctx->py_class))->tp_name);
+}
+
+void python_plugin_unlink(void) __attribute__((destructor));
+
+// this gets run only when sudo unlinks the python_plugin.so
+void
+python_plugin_unlink(void)
+{
+ debug_decl(python_plugin_unlink, PYTHON_DEBUG_INTERNAL);
+ if (py_ctx.py_main_interpreter == NULL)
+ return;
+
+ if (Py_IsInitialized()) {
+ sudo_debug_printf(SUDO_DEBUG_NOTICE, "Closing: deinit python %zu subinterpreters\n",
+ py_ctx.interpreter_count);
+ while (py_ctx.interpreter_count != 0) {
+ PyThreadState *py_interpreter =
+ py_ctx.py_subinterpreters[--py_ctx.interpreter_count];
+ PyThreadState_Swap(py_interpreter);
+ Py_EndInterpreter(py_interpreter);
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_NOTICE, "Closing: deinit main interpreter\n");
+
+ // we need to call finalize from the main interpreter
+ PyThreadState_Swap(py_ctx.py_main_interpreter);
+
+ if (Py_FinalizeEx() != 0) {
+ sudo_debug_printf(SUDO_DEBUG_WARN, "Closing: failed to deinit python interpreter\n");
+ }
+
+ // Restore inittab so "sudo" module does not remain there (as garbage)
+ _restore_inittab();
+ }
+ py_ctx_reset();
+ debug_return;
+}
diff --git a/plugins/python/python_plugin_common.h b/plugins/python/python_plugin_common.h
new file mode 100644
index 0000000..c0fdce6
--- /dev/null
+++ b/plugins/python/python_plugin_common.h
@@ -0,0 +1,85 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_PYTHON_PLUGIN_COMMON_H
+#define SUDO_PYTHON_PLUGIN_COMMON_H
+
+#include "pyhelpers.h"
+
+struct PluginContext {
+ PyThreadState *py_interpreter;
+ PyObject *py_module;
+ PyObject *py_class;
+ PyObject *py_instance;
+ int call_close;
+ unsigned int sudo_api_version;
+ char *plugin_path;
+
+ // We use this to let the error string live until sudo and the audit plugins
+ // are using it.
+ char *callback_error;
+};
+
+int python_plugin_register_logging(sudo_conv_t conversation, sudo_printf_t sudo_printf, char * const settings[]);
+
+int python_plugin_init(struct PluginContext *plugin_ctx, char * const plugin_options[], unsigned int version);
+
+int python_plugin_construct_custom(struct PluginContext *plugin_ctx, PyObject *py_kwargs);
+
+PyObject *python_plugin_construct_args(unsigned int version, char *const settings[],
+ char *const user_info[], char *const user_env[], char *const plugin_options[]);
+
+int python_plugin_construct(struct PluginContext *plugin_ctx, unsigned int version,
+ char *const settings[], char *const user_info[],
+ char *const user_env[], char *const plugin_options[]);
+
+void python_plugin_deinit(struct PluginContext *plugin_ctx);
+
+int python_plugin_show_version(struct PluginContext *plugin_ctx,
+ const char *python_callback_name, int isVerbose, unsigned int plugin_api_version, const char *plugin_api_name);
+
+CPYCHECKER_STEALS_REFERENCE_TO_ARG(3)
+void python_plugin_close(struct PluginContext *plugin_ctx, const char *callback_name,
+ PyObject *py_args);
+
+CPYCHECKER_STEALS_REFERENCE_TO_ARG(3)
+PyObject *python_plugin_api_call(struct PluginContext *plugin_ctx,
+ const char *func_name, PyObject *py_args);
+
+CPYCHECKER_STEALS_REFERENCE_TO_ARG(3)
+int python_plugin_api_rc_call(struct PluginContext *plugin_ctx,
+ const char *func_name, PyObject *py_args);
+
+int python_plugin_rc_to_int(PyObject *py_result);
+
+void python_plugin_mark_callback_optional(struct PluginContext *plugin_ctx,
+ const char *function_name, void **function);
+
+const char *python_plugin_name(struct PluginContext *plugin_ctx);
+
+// sets the callback error stored in plugin_ctx into "errstr" but only if API
+// version is enough and "errstr" is valid
+#define CALLBACK_SET_ERROR(plugin_ctx, errstr) \
+ do { \
+ if ((plugin_ctx)->sudo_api_version >= SUDO_API_MKVERSION(1, 15)) { \
+ if (errstr != NULL) \
+ *errstr = (plugin_ctx)->callback_error; \
+ } \
+ } while(0)
+
+#endif // SUDO_PYTHON_PLUGIN_COMMON_H
diff --git a/plugins/python/python_plugin_group.c b/plugins/python/python_plugin_group.c
new file mode 100644
index 0000000..b1514c7
--- /dev/null
+++ b/plugins/python/python_plugin_group.c
@@ -0,0 +1,114 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include "python_plugin_common.h"
+
+static struct PluginContext plugin_ctx;
+
+extern struct sudoers_group_plugin group_plugin;
+
+#define PY_GROUP_PLUGIN_VERSION SUDO_API_MKVERSION(1, 0)
+
+#define CALLBACK_PLUGINFUNC(func_name) group_plugin.func_name
+#define CALLBACK_CFUNC(func_name) python_plugin_group_ ## func_name
+
+// This also verifies compile time that the name matches the sudo plugin API.
+#define CALLBACK_PYNAME(func_name) ((void)CALLBACK_PLUGINFUNC(func_name), #func_name)
+
+
+static int
+python_plugin_group_init(int version, sudo_printf_t sudo_printf, char *const plugin_options[])
+{
+ debug_decl(python_plugin_group_init, PYTHON_DEBUG_CALLBACKS);
+
+ if (version < SUDO_API_MKVERSION(1, 0)) {
+ sudo_printf(SUDO_CONV_ERROR_MSG,
+ "Error: Python group plugin requires at least plugin API version 1.0\n");
+ debug_return_int(SUDO_RC_ERROR);
+ }
+
+ int rc = SUDO_RC_ERROR;
+
+ rc = python_plugin_register_logging(NULL, sudo_printf, NULL);
+ if (rc != SUDO_RC_OK)
+ debug_return_int(rc);
+
+ rc = python_plugin_init(&plugin_ctx, plugin_options, (unsigned int)version);
+ if (rc != SUDO_RC_OK)
+ debug_return_int(rc);
+
+ PyObject *py_version = NULL,
+ *py_plugin_options = NULL,
+ *py_kwargs = NULL;
+
+ if ((py_kwargs = PyDict_New()) == NULL ||
+ (py_version = py_create_version(PY_GROUP_PLUGIN_VERSION)) == NULL ||
+ (py_plugin_options = py_str_array_to_tuple(plugin_options)) == NULL ||
+ PyDict_SetItemString(py_kwargs, "args", py_plugin_options) != 0 ||
+ PyDict_SetItemString(py_kwargs, "version", py_version))
+ {
+ py_log_last_error("Failed to construct arguments for plugin constructor call.");
+ rc = SUDO_RC_ERROR;
+ } else {
+ rc = python_plugin_construct_custom(&plugin_ctx, py_kwargs);
+ }
+
+ Py_XDECREF(py_version);
+ Py_XDECREF(py_plugin_options);
+ Py_XDECREF(py_kwargs);
+ debug_return_int(rc);
+}
+
+static void
+python_plugin_group_cleanup(void)
+{
+ debug_decl(python_plugin_group_cleanup, PYTHON_DEBUG_CALLBACKS);
+ PyThreadState_Swap(plugin_ctx.py_interpreter);
+ python_plugin_deinit(&plugin_ctx);
+}
+
+static int
+python_plugin_group_query(const char *user, const char *group, const struct passwd *pwd)
+{
+ debug_decl(python_plugin_group_query, PYTHON_DEBUG_CALLBACKS);
+
+ PyThreadState_Swap(plugin_ctx.py_interpreter);
+
+ PyObject *py_pwd = py_from_passwd(pwd);
+ if (py_pwd == NULL) {
+ debug_return_int(SUDO_RC_ERROR);
+ }
+
+ int rc = python_plugin_api_rc_call(&plugin_ctx, CALLBACK_PYNAME(query),
+ Py_BuildValue("(zzO)", user, group, py_pwd));
+ Py_XDECREF(py_pwd);
+
+ debug_return_int(rc);
+}
+
+sudo_dso_public struct sudoers_group_plugin group_plugin = {
+ GROUP_API_VERSION,
+ CALLBACK_CFUNC(init),
+ CALLBACK_CFUNC(cleanup),
+ CALLBACK_CFUNC(query)
+};
diff --git a/plugins/python/python_plugin_io.c b/plugins/python/python_plugin_io.c
new file mode 100644
index 0000000..d554cb5
--- /dev/null
+++ b/plugins/python/python_plugin_io.c
@@ -0,0 +1,276 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include "python_plugin_common.h"
+
+struct IOPluginContext
+{
+ struct PluginContext base_ctx;
+ struct io_plugin *io_plugin;
+};
+
+#define BASE_CTX(io_ctx) (&(io_ctx->base_ctx))
+
+#define PY_IO_PLUGIN_VERSION SUDO_API_MKVERSION(1, 0)
+
+#define CALLBACK_PLUGINFUNC(func_name) io_ctx->io_plugin->func_name
+
+// This also verifies compile time that the name matches the sudo plugin API.
+#define CALLBACK_PYNAME(func_name) ((void)CALLBACK_PLUGINFUNC(func_name), #func_name)
+
+#define MARK_CALLBACK_OPTIONAL(function_name) \
+ do { \
+ python_plugin_mark_callback_optional(plugin_ctx, CALLBACK_PYNAME(function_name), \
+ (void **)&CALLBACK_PLUGINFUNC(function_name)); \
+ } while(0)
+
+sudo_dso_public struct io_plugin *python_io_clone(void);
+
+static int
+_call_plugin_open(struct IOPluginContext *io_ctx, int argc, char * const argv[], char * const command_info[])
+{
+ debug_decl(_call_plugin_open, PYTHON_DEBUG_CALLBACKS);
+ struct PluginContext *plugin_ctx = BASE_CTX(io_ctx);
+ plugin_ctx->call_close = 1;
+
+ if (!PyObject_HasAttrString(plugin_ctx->py_instance, CALLBACK_PYNAME(open))) {
+ debug_return_int(SUDO_RC_OK);
+ }
+
+ int rc = SUDO_RC_ERROR;
+ PyObject *py_argv = py_str_array_to_tuple_with_count(argc, argv);
+ PyObject *py_command_info = py_str_array_to_tuple(command_info);
+
+ if (py_argv != NULL && py_command_info != NULL) {
+ rc = python_plugin_api_rc_call(plugin_ctx, CALLBACK_PYNAME(open),
+ Py_BuildValue("(OO)", py_argv, py_command_info));
+ }
+
+ if (rc != SUDO_RC_OK)
+ plugin_ctx->call_close = 0;
+
+ Py_XDECREF(py_argv);
+ Py_XDECREF(py_command_info);
+ debug_return_int(rc);
+}
+
+static int
+python_plugin_io_open(struct IOPluginContext *io_ctx,
+ unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_printf, char * const settings[],
+ char * const user_info[], char * const command_info[],
+ int argc, char * const argv[], char * const user_env[],
+ char * const plugin_options[], const char **errstr)
+{
+ debug_decl(python_plugin_io_open, PYTHON_DEBUG_CALLBACKS);
+
+ if (version < SUDO_API_MKVERSION(1, 2)) {
+ sudo_printf(SUDO_CONV_ERROR_MSG,
+ "Error: Python IO plugin requires at least plugin API version 1.2\n");
+ debug_return_int(SUDO_RC_ERROR);
+ }
+
+ int rc = python_plugin_register_logging(conversation, sudo_printf, settings);
+ if (rc != SUDO_RC_OK)
+ debug_return_int(rc);
+
+ struct PluginContext *plugin_ctx = BASE_CTX(io_ctx);
+ rc = python_plugin_init(plugin_ctx, plugin_options, version);
+
+ if (rc != SUDO_RC_OK)
+ debug_return_int(rc);
+
+ rc = python_plugin_construct(plugin_ctx, PY_IO_PLUGIN_VERSION,
+ settings, user_info, user_env, plugin_options);
+ CALLBACK_SET_ERROR(plugin_ctx, errstr);
+ if (rc != SUDO_RC_OK) {
+ debug_return_int(rc);
+ }
+
+ // skip plugin callbacks which are not mandatory
+ MARK_CALLBACK_OPTIONAL(log_ttyin);
+ MARK_CALLBACK_OPTIONAL(log_ttyout);
+ MARK_CALLBACK_OPTIONAL(log_stdin);
+ MARK_CALLBACK_OPTIONAL(log_stdout);
+ MARK_CALLBACK_OPTIONAL(log_stderr);
+ MARK_CALLBACK_OPTIONAL(change_winsize);
+ MARK_CALLBACK_OPTIONAL(log_suspend);
+ // open and close are mandatory
+
+ if (argc > 0) // we only call open if there is request for running sg
+ rc = _call_plugin_open(io_ctx, argc, argv, command_info);
+
+ CALLBACK_SET_ERROR(plugin_ctx, errstr);
+ debug_return_int(rc);
+}
+
+static void
+python_plugin_io_close(struct IOPluginContext *io_ctx, int exit_status, int error)
+{
+ debug_decl(python_plugin_io_close, PYTHON_DEBUG_CALLBACKS);
+ python_plugin_close(BASE_CTX(io_ctx), CALLBACK_PYNAME(close),
+ Py_BuildValue("(ii)", error == 0 ? exit_status : -1, error));
+ debug_return;
+}
+
+static int
+python_plugin_io_show_version(struct IOPluginContext *io_ctx, int verbose)
+{
+ debug_decl(python_plugin_io_show_version, PYTHON_DEBUG_CALLBACKS);
+
+ PyThreadState_Swap(BASE_CTX(io_ctx)->py_interpreter);
+
+ debug_return_int(python_plugin_show_version(BASE_CTX(io_ctx), CALLBACK_PYNAME(show_version),
+ verbose, PY_IO_PLUGIN_VERSION, "io"));
+}
+
+static int
+python_plugin_io_log_ttyin(struct IOPluginContext *io_ctx, const char *buf, unsigned int len, const char **errstr)
+{
+ debug_decl(python_plugin_io_log_ttyin, PYTHON_DEBUG_CALLBACKS);
+ struct PluginContext *plugin_ctx = BASE_CTX(io_ctx);
+ PyThreadState_Swap(plugin_ctx->py_interpreter);
+ int rc = python_plugin_api_rc_call(plugin_ctx, CALLBACK_PYNAME(log_ttyin),
+ Py_BuildValue("(s#)", buf, len));
+ CALLBACK_SET_ERROR(plugin_ctx, errstr);
+ debug_return_int(rc);
+}
+
+static int
+python_plugin_io_log_ttyout(struct IOPluginContext *io_ctx, const char *buf, unsigned int len, const char **errstr)
+{
+ debug_decl(python_plugin_io_log_ttyout, PYTHON_DEBUG_CALLBACKS);
+ struct PluginContext *plugin_ctx = BASE_CTX(io_ctx);
+ PyThreadState_Swap(plugin_ctx->py_interpreter);
+ int rc = python_plugin_api_rc_call(plugin_ctx, CALLBACK_PYNAME(log_ttyout),
+ Py_BuildValue("(s#)", buf, len));
+ CALLBACK_SET_ERROR(plugin_ctx, errstr);
+ debug_return_int(rc);
+}
+
+static int
+python_plugin_io_log_stdin(struct IOPluginContext *io_ctx, const char *buf, unsigned int len, const char **errstr)
+{
+ debug_decl(python_plugin_io_log_stdin, PYTHON_DEBUG_CALLBACKS);
+ struct PluginContext *plugin_ctx = BASE_CTX(io_ctx);
+ PyThreadState_Swap(plugin_ctx->py_interpreter);
+ int rc = python_plugin_api_rc_call(plugin_ctx, CALLBACK_PYNAME(log_stdin),
+ Py_BuildValue("(s#)", buf, len));
+ CALLBACK_SET_ERROR(plugin_ctx, errstr);
+ debug_return_int(rc);
+}
+
+static int
+python_plugin_io_log_stdout(struct IOPluginContext *io_ctx, const char *buf, unsigned int len, const char **errstr)
+{
+ debug_decl(python_plugin_io_log_stdout, PYTHON_DEBUG_CALLBACKS);
+ struct PluginContext *plugin_ctx = BASE_CTX(io_ctx);
+ PyThreadState_Swap(plugin_ctx->py_interpreter);
+ int rc = python_plugin_api_rc_call(plugin_ctx, CALLBACK_PYNAME(log_stdout),
+ Py_BuildValue("(s#)", buf, len));
+ CALLBACK_SET_ERROR(plugin_ctx, errstr);
+ debug_return_int(rc);
+}
+
+static int
+python_plugin_io_log_stderr(struct IOPluginContext *io_ctx, const char *buf, unsigned int len, const char **errstr)
+{
+ debug_decl(python_plugin_io_log_stderr, PYTHON_DEBUG_CALLBACKS);
+ struct PluginContext *plugin_ctx = BASE_CTX(io_ctx);
+ PyThreadState_Swap(plugin_ctx->py_interpreter);
+ int rc = python_plugin_api_rc_call(plugin_ctx, CALLBACK_PYNAME(log_stderr),
+ Py_BuildValue("(s#)", buf, len));
+ CALLBACK_SET_ERROR(plugin_ctx, errstr);
+ debug_return_int(rc);
+}
+
+static int
+python_plugin_io_change_winsize(struct IOPluginContext *io_ctx, unsigned int line, unsigned int cols, const char **errstr)
+{
+ debug_decl(python_plugin_io_change_winsize, PYTHON_DEBUG_CALLBACKS);
+ struct PluginContext *plugin_ctx = BASE_CTX(io_ctx);
+ PyThreadState_Swap(plugin_ctx->py_interpreter);
+ int rc = python_plugin_api_rc_call(plugin_ctx, CALLBACK_PYNAME(change_winsize),
+ Py_BuildValue("(ii)", line, cols));
+ CALLBACK_SET_ERROR(plugin_ctx, errstr);
+ debug_return_int(rc);
+}
+
+static int
+python_plugin_io_log_suspend(struct IOPluginContext *io_ctx, int signo, const char **errstr)
+{
+ debug_decl(python_plugin_io_log_suspend, PYTHON_DEBUG_CALLBACKS);
+ struct PluginContext *plugin_ctx = BASE_CTX(io_ctx);
+ PyThreadState_Swap(plugin_ctx->py_interpreter);
+ int rc = python_plugin_api_rc_call(plugin_ctx, CALLBACK_PYNAME(log_suspend),
+ Py_BuildValue("(i)", signo));
+ CALLBACK_SET_ERROR(plugin_ctx, errstr);
+ debug_return_int(rc);
+}
+
+// generate symbols for loading multiple io plugins:
+sudo_dso_public struct io_plugin python_io;
+#define IO_SYMBOL_NAME(symbol) symbol
+#include "python_plugin_io_multi.inc"
+#define IO_SYMBOL_NAME(symbol) symbol##1
+#include "python_plugin_io_multi.inc"
+#define IO_SYMBOL_NAME(symbol) symbol##2
+#include "python_plugin_io_multi.inc"
+#define IO_SYMBOL_NAME(symbol) symbol##3
+#include "python_plugin_io_multi.inc"
+#define IO_SYMBOL_NAME(symbol) symbol##4
+#include "python_plugin_io_multi.inc"
+#define IO_SYMBOL_NAME(symbol) symbol##5
+#include "python_plugin_io_multi.inc"
+#define IO_SYMBOL_NAME(symbol) symbol##6
+#include "python_plugin_io_multi.inc"
+#define IO_SYMBOL_NAME(symbol) symbol##7
+#include "python_plugin_io_multi.inc"
+
+static struct io_plugin *extra_io_plugins[] = {
+ &python_io1,
+ &python_io2,
+ &python_io3,
+ &python_io4,
+ &python_io5,
+ &python_io6,
+ &python_io7
+};
+
+struct io_plugin *
+python_io_clone(void)
+{
+ static size_t counter = 0;
+ struct io_plugin *next_plugin = NULL;
+
+ size_t max = sizeof(extra_io_plugins) / sizeof(*extra_io_plugins);
+ if (counter < max) {
+ next_plugin = extra_io_plugins[counter];
+ ++counter;
+ } else if (counter == max) {
+ ++counter;
+ py_sudo_log(SUDO_CONV_ERROR_MSG, "sudo: loading more than %d sudo python IO plugins is not supported\n", counter);
+ }
+
+ return next_plugin;
+}
diff --git a/plugins/python/python_plugin_io_multi.inc b/plugins/python/python_plugin_io_multi.inc
new file mode 100644
index 0000000..d5d58d2
--- /dev/null
+++ b/plugins/python/python_plugin_io_multi.inc
@@ -0,0 +1,99 @@
+/* The purpose of this file is to generate a io_plugin symbols,
+ * with an I/O plugin context which is unique to it and its functions.
+ * The callbacks inside are just wrappers around the real functions in python_plugin_io.c,
+ * their only purpose is to add the unique context to each separate io_plugin call.
+ */
+
+#define PLUGIN_CTX IO_SYMBOL_NAME(plugin_ctx)
+#define CALLBACK_CFUNC(func_name) IO_SYMBOL_NAME(_python_plugin_io_ ## func_name)
+
+extern struct io_plugin IO_SYMBOL_NAME(python_io);
+static struct IOPluginContext PLUGIN_CTX = { { NULL }, &IO_SYMBOL_NAME(python_io) };
+
+static int
+CALLBACK_CFUNC(open)(
+ unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_printf, char * const settings[],
+ char * const user_info[], char * const command_info[],
+ int argc, char * const argv[], char * const user_env[],
+ char * const plugin_options[], const char **errstr)
+{
+ return python_plugin_io_open(&PLUGIN_CTX, version, conversation,
+ sudo_printf, settings, user_info, command_info, argc, argv, user_env, plugin_options, errstr);
+}
+
+static void
+CALLBACK_CFUNC(close)(int exit_status, int error)
+{
+ python_plugin_io_close(&PLUGIN_CTX, exit_status, error);
+}
+
+static int
+CALLBACK_CFUNC(show_version)(int verbose)
+{
+ return python_plugin_io_show_version(&PLUGIN_CTX, verbose);
+}
+
+static int
+CALLBACK_CFUNC(log_ttyin)(const char *buf, unsigned int len, const char **errstr)
+{
+ return python_plugin_io_log_ttyin(&PLUGIN_CTX, buf, len, errstr);
+}
+
+static int
+CALLBACK_CFUNC(log_ttyout)(const char *buf, unsigned int len, const char **errstr)
+{
+ return python_plugin_io_log_ttyout(&PLUGIN_CTX, buf, len, errstr);
+}
+
+static int
+CALLBACK_CFUNC(log_stdin)(const char *buf, unsigned int len, const char **errstr)
+{
+ return python_plugin_io_log_stdin(&PLUGIN_CTX, buf, len, errstr);
+}
+
+static int
+CALLBACK_CFUNC(log_stdout)(const char *buf, unsigned int len, const char **errstr)
+{
+ return python_plugin_io_log_stdout(&PLUGIN_CTX, buf, len, errstr);
+}
+
+static int
+CALLBACK_CFUNC(log_stderr)(const char *buf, unsigned int len, const char **errstr)
+{
+ return python_plugin_io_log_stderr(&PLUGIN_CTX, buf, len, errstr);
+}
+
+static int
+CALLBACK_CFUNC(change_winsize)(unsigned int line, unsigned int cols, const char **errstr)
+{
+ return python_plugin_io_change_winsize(&PLUGIN_CTX, line, cols, errstr);
+}
+
+static int
+CALLBACK_CFUNC(log_suspend)(int signo, const char **errstr)
+{
+ return python_plugin_io_log_suspend(&PLUGIN_CTX, signo, errstr);
+}
+
+struct io_plugin IO_SYMBOL_NAME(python_io) = {
+ SUDO_IO_PLUGIN,
+ SUDO_API_VERSION,
+ CALLBACK_CFUNC(open),
+ CALLBACK_CFUNC(close),
+ CALLBACK_CFUNC(show_version),
+ CALLBACK_CFUNC(log_ttyin),
+ CALLBACK_CFUNC(log_ttyout),
+ CALLBACK_CFUNC(log_stdin),
+ CALLBACK_CFUNC(log_stdout),
+ CALLBACK_CFUNC(log_stderr),
+ NULL, // register_hooks,
+ NULL, // deregister_hooks,
+ CALLBACK_CFUNC(change_winsize),
+ CALLBACK_CFUNC(log_suspend),
+ NULL // event_alloc
+};
+
+#undef PLUGIN_CTX
+#undef CALLBACK_CFUNC
+#undef IO_SYMBOL_NAME
diff --git a/plugins/python/python_plugin_policy.c b/plugins/python/python_plugin_policy.c
new file mode 100644
index 0000000..5f356c2
--- /dev/null
+++ b/plugins/python/python_plugin_policy.c
@@ -0,0 +1,289 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include "python_plugin_common.h"
+
+
+static struct PluginContext plugin_ctx;
+
+extern struct policy_plugin python_policy;
+
+#define PY_POLICY_PLUGIN_VERSION SUDO_API_MKVERSION(1, 0)
+
+#define CALLBACK_PLUGINFUNC(func_name) python_policy.func_name
+#define CALLBACK_CFUNC(func_name) python_plugin_policy_ ## func_name
+
+// This also verifies compile time that the name matches the sudo plugin API.
+#define CALLBACK_PYNAME(func_name) ((void)CALLBACK_PLUGINFUNC(func_name), #func_name)
+
+#define MARK_CALLBACK_OPTIONAL(function_name) \
+ do { \
+ python_plugin_mark_callback_optional(&plugin_ctx, CALLBACK_PYNAME(function_name), \
+ (void **)&CALLBACK_PLUGINFUNC(function_name)); \
+ } while(0)
+
+
+static int
+python_plugin_policy_open(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_printf, char * const settings[],
+ char * const user_info[], char * const user_env[],
+ char * const plugin_options[], const char **errstr)
+{
+ debug_decl(python_plugin_policy_open, PYTHON_DEBUG_CALLBACKS);
+
+ if (version < SUDO_API_MKVERSION(1, 2)) {
+ sudo_printf(SUDO_CONV_ERROR_MSG,
+ "Error: Python policy plugin requires at least plugin API version 1.2\n");
+ debug_return_int(SUDO_RC_ERROR);
+ }
+
+ int rc = python_plugin_register_logging(conversation, sudo_printf, settings);
+ if (rc != SUDO_RC_OK)
+ debug_return_int(rc);
+
+ rc = python_plugin_init(&plugin_ctx, plugin_options, version);
+ if (rc != SUDO_RC_OK)
+ debug_return_int(rc);
+
+ rc = python_plugin_construct(&plugin_ctx, PY_POLICY_PLUGIN_VERSION, settings,
+ user_info, user_env, plugin_options);
+ CALLBACK_SET_ERROR(&plugin_ctx, errstr);
+ if (rc != SUDO_RC_OK) {
+ debug_return_int(rc);
+ }
+
+ // skip plugin callbacks which are not mandatory
+ MARK_CALLBACK_OPTIONAL(list);
+ MARK_CALLBACK_OPTIONAL(validate);
+ MARK_CALLBACK_OPTIONAL(invalidate);
+ MARK_CALLBACK_OPTIONAL(init_session);
+ // check_policy, open and close are mandatory
+
+ debug_return_int(rc);
+}
+
+static void
+python_plugin_policy_close(int exit_status, int error)
+{
+ debug_decl(python_plugin_policy_close, PYTHON_DEBUG_CALLBACKS);
+ python_plugin_close(&plugin_ctx, CALLBACK_PYNAME(close),
+ Py_BuildValue("(ii)", error == 0 ? exit_status : -1, error));
+ debug_return;
+}
+
+static int
+python_plugin_policy_check(int argc, char * const argv[],
+ char *env_add[], char **command_info_out[],
+ char **argv_out[], char **user_env_out[], const char **errstr)
+{
+ debug_decl(python_plugin_policy_check, PYTHON_DEBUG_CALLBACKS);
+ int rc = SUDO_RC_ERROR;
+
+ PyThreadState_Swap(plugin_ctx.py_interpreter);
+
+ *command_info_out = *argv_out = *user_env_out = NULL;
+
+ PyObject *py_argv = py_str_array_to_tuple_with_count(argc, argv);
+
+ PyObject *py_env_add = py_str_array_to_tuple(env_add);
+ PyObject *py_result = NULL;
+
+ if (py_argv == NULL || py_env_add == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "Failed to create some of the arguments for the python call "
+ "(py_argv=%p py_env_add=%p)\n", (void *)py_argv, (void *)py_env_add);
+ goto cleanup;
+ }
+
+ py_result = python_plugin_api_call(&plugin_ctx, CALLBACK_PYNAME(check_policy),
+ Py_BuildValue("(OO)", py_argv, py_env_add));
+ CALLBACK_SET_ERROR(&plugin_ctx, errstr);
+ if (py_result == NULL)
+ goto cleanup;
+
+ PyObject *py_rc = NULL,
+ *py_command_info_out = NULL,
+ *py_argv_out = NULL,
+ *py_user_env_out = NULL;
+ if (PyTuple_Check(py_result))
+ {
+ if (!PyArg_ParseTuple(py_result, "O!|O!O!O!:python_plugin.check_policy",
+ &PyLong_Type, &py_rc,
+ &PyTuple_Type, &py_command_info_out,
+ &PyTuple_Type, &py_argv_out,
+ &PyTuple_Type, &py_user_env_out))
+ {
+ goto cleanup;
+ }
+ } else {
+ py_rc = py_result;
+ }
+
+ if (py_command_info_out != NULL)
+ *command_info_out = py_str_array_from_tuple(py_command_info_out);
+
+ if (py_argv_out != NULL)
+ *argv_out = py_str_array_from_tuple(py_argv_out);
+
+ if (py_user_env_out != NULL)
+ *user_env_out = py_str_array_from_tuple(py_user_env_out);
+
+ rc = python_plugin_rc_to_int(py_rc);
+
+cleanup:
+ if (PyErr_Occurred()) {
+ py_log_last_error(NULL);
+ rc = SUDO_RC_ERROR;
+ free(*command_info_out);
+ free(*argv_out);
+ free(*user_env_out);
+ *command_info_out = *argv_out = *user_env_out = NULL;
+ }
+
+ Py_XDECREF(py_argv);
+ Py_XDECREF(py_env_add);
+ Py_XDECREF(py_result);
+
+ if (rc == SUDO_RC_ACCEPT)
+ plugin_ctx.call_close = 1;
+
+ debug_return_int(rc);
+}
+
+static int
+python_plugin_policy_list(int argc, char * const argv[], int verbose, const char *list_user, const char **errstr)
+{
+ debug_decl(python_plugin_policy_list, PYTHON_DEBUG_CALLBACKS);
+
+ PyThreadState_Swap(plugin_ctx.py_interpreter);
+
+ PyObject *py_argv = py_str_array_to_tuple_with_count(argc, argv);
+ if (py_argv == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "%s: Failed to create argv argument for the python call\n", __func__);
+ debug_return_int(SUDO_RC_ERROR);
+ }
+
+ int rc = python_plugin_api_rc_call(&plugin_ctx, CALLBACK_PYNAME(list),
+ Py_BuildValue("(Oiz)", py_argv, verbose, list_user));
+
+ Py_XDECREF(py_argv);
+
+ CALLBACK_SET_ERROR(&plugin_ctx, errstr);
+ debug_return_int(rc);
+}
+
+static int
+python_plugin_policy_version(int verbose)
+{
+ debug_decl(python_plugin_policy_version, PYTHON_DEBUG_CALLBACKS);
+
+ PyThreadState_Swap(plugin_ctx.py_interpreter);
+
+ debug_return_int(python_plugin_show_version(&plugin_ctx, CALLBACK_PYNAME(show_version),
+ verbose, PY_POLICY_PLUGIN_VERSION, "policy"));
+}
+
+static int
+python_plugin_policy_validate(const char **errstr)
+{
+ debug_decl(python_plugin_policy_validate, PYTHON_DEBUG_CALLBACKS);
+ PyThreadState_Swap(plugin_ctx.py_interpreter);
+ int rc = python_plugin_api_rc_call(&plugin_ctx, CALLBACK_PYNAME(validate), NULL);
+ CALLBACK_SET_ERROR(&plugin_ctx, errstr);
+ debug_return_int(rc);
+}
+
+static void
+python_plugin_policy_invalidate(int unlinkit)
+{
+ debug_decl(python_plugin_policy_invalidate, PYTHON_DEBUG_CALLBACKS);
+ PyThreadState_Swap(plugin_ctx.py_interpreter);
+ python_plugin_api_rc_call(&plugin_ctx, CALLBACK_PYNAME(invalidate),
+ Py_BuildValue("(i)", unlinkit));
+ debug_return;
+}
+
+static int
+python_plugin_policy_init_session(struct passwd *pwd, char **user_env[], const char **errstr)
+{
+ debug_decl(python_plugin_policy_init_session, PYTHON_DEBUG_CALLBACKS);
+ int rc = SUDO_RC_ERROR;
+ PyThreadState_Swap(plugin_ctx.py_interpreter);
+ PyObject *py_pwd = NULL, *py_user_env = NULL, *py_result = NULL;
+
+ py_pwd = py_from_passwd(pwd);
+ if (py_pwd == NULL)
+ goto cleanup;
+
+ py_user_env = py_str_array_to_tuple(*user_env);
+ if (py_user_env == NULL)
+ goto cleanup;
+
+ py_result = python_plugin_api_call(&plugin_ctx, CALLBACK_PYNAME(init_session),
+ Py_BuildValue("(OO)", py_pwd, py_user_env));
+ CALLBACK_SET_ERROR(&plugin_ctx, errstr);
+ if (py_result == NULL)
+ goto cleanup;
+
+ PyObject *py_user_env_out = NULL, *py_rc = NULL;
+ if (PyTuple_Check(py_result)) {
+ if (!PyArg_ParseTuple(py_result, "O!|O!:python_plugin.init_session",
+ &PyLong_Type, &py_rc,
+ &PyTuple_Type, &py_user_env_out)) {
+ goto cleanup;
+ }
+ } else {
+ py_rc = py_result;
+ }
+
+ if (py_user_env_out != NULL) {
+ str_array_free(user_env);
+ *user_env = py_str_array_from_tuple(py_user_env_out);
+ if (*user_env == NULL)
+ goto cleanup;
+ }
+
+ rc = python_plugin_rc_to_int(py_rc);
+
+cleanup:
+ Py_XDECREF(py_pwd);
+ Py_XDECREF(py_user_env);
+ Py_XDECREF(py_result);
+
+ debug_return_int(rc);
+}
+
+sudo_dso_public struct policy_plugin python_policy = {
+ SUDO_POLICY_PLUGIN,
+ SUDO_API_VERSION,
+ CALLBACK_CFUNC(open),
+ CALLBACK_CFUNC(close),
+ CALLBACK_CFUNC(version),
+ CALLBACK_CFUNC(check),
+ CALLBACK_CFUNC(list),
+ CALLBACK_CFUNC(validate),
+ CALLBACK_CFUNC(invalidate),
+ CALLBACK_CFUNC(init_session),
+ NULL, /* register_hooks */
+ NULL, /* deregister_hooks */
+ NULL /* event_alloc */
+};
diff --git a/plugins/python/regress/check_python_examples.c b/plugins/python/regress/check_python_examples.c
new file mode 100644
index 0000000..108d85d
--- /dev/null
+++ b/plugins/python/regress/check_python_examples.c
@@ -0,0 +1,1619 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include "testhelpers.h"
+#include <unistd.h>
+
+#include <sudo_dso.h>
+
+#define DECL_PLUGIN(type, variable_name) \
+ static struct type *variable_name = NULL; \
+ static struct type variable_name ## _original
+
+#define RESTORE_PYTHON_PLUGIN(variable_name) \
+ memcpy(variable_name, &(variable_name ## _original), sizeof(variable_name ## _original))
+
+#define SAVE_PYTHON_PLUGIN(variable_name) \
+ memcpy(&(variable_name ## _original), variable_name, sizeof(variable_name ## _original))
+
+static const char *python_plugin_so_path = NULL;
+static void *python_plugin_handle = NULL;
+DECL_PLUGIN(io_plugin, python_io);
+DECL_PLUGIN(policy_plugin, python_policy);
+DECL_PLUGIN(approval_plugin, python_approval);
+DECL_PLUGIN(audit_plugin, python_audit);
+DECL_PLUGIN(sudoers_group_plugin, group_plugin);
+
+static struct passwd example_pwd;
+static bool verbose;
+
+static int _init_symbols(void);
+static int _unlink_symbols(void);
+
+static void
+create_plugin_options(const char *module_name, const char *class_name, const char *extra_option)
+{
+ char opt_module_path[PATH_MAX + 256];
+ char opt_classname[PATH_MAX + 256];
+ snprintf(opt_module_path, sizeof(opt_module_path),
+ "ModulePath=" SRC_DIR "/%s.py", module_name);
+
+ snprintf(opt_classname, sizeof(opt_classname), "ClassName=%s", class_name);
+
+ str_array_free(&data.plugin_options);
+ size_t count = 3 + (extra_option != NULL);
+ data.plugin_options = create_str_array(count, opt_module_path,
+ opt_classname, extra_option, NULL);
+}
+
+static void
+create_io_plugin_options(const char *log_path)
+{
+ char opt_logpath[PATH_MAX + 16];
+ snprintf(opt_logpath, sizeof(opt_logpath), "LogPath=%s", log_path);
+ create_plugin_options("example_io_plugin", "SudoIOPlugin", opt_logpath);
+}
+
+static void
+create_debugging_plugin_options(void)
+{
+ create_plugin_options("example_debugging", "DebugDemoPlugin", NULL);
+}
+
+static void
+create_audit_plugin_options(const char *extra_argument)
+{
+ create_plugin_options("example_audit_plugin", "SudoAuditPlugin", extra_argument);
+}
+
+static void
+create_conversation_plugin_options(void)
+{
+ char opt_logpath[PATH_MAX + 16];
+ snprintf(opt_logpath, sizeof(opt_logpath), "LogPath=%s", data.tmp_dir);
+ create_plugin_options("example_conversation", "ReasonLoggerIOPlugin", opt_logpath);
+}
+
+static void
+create_policy_plugin_options(void)
+{
+ create_plugin_options("example_policy_plugin", "SudoPolicyPlugin", NULL);
+}
+
+static int
+init(void)
+{
+ // always start each test from clean state
+ memset(&data, 0, sizeof(data));
+
+ memset(&example_pwd, 0, sizeof(example_pwd));
+ example_pwd.pw_name = (char *)"pw_name";
+ example_pwd.pw_passwd = (char *)"pw_passwd";
+ example_pwd.pw_gecos = (char *)"pw_gecos";
+ example_pwd.pw_shell = (char *)"pw_shell";
+ example_pwd.pw_dir = (char *)"pw_dir";
+ example_pwd.pw_uid = (uid_t)1001;
+ example_pwd.pw_gid = (gid_t)101;
+
+ VERIFY_TRUE(asprintf(&data.tmp_dir, TEMP_PATH_TEMPLATE) >= 0);
+ VERIFY_NOT_NULL(mkdtemp(data.tmp_dir));
+
+ sudo_conf_clear_paths();
+
+ // some default values for the plugin open:
+ data.settings = create_str_array(1, NULL);
+ data.user_info = create_str_array(1, NULL);
+ data.command_info = create_str_array(1, NULL);
+ data.plugin_argc = 0;
+ data.plugin_argv = create_str_array(1, NULL);
+ data.user_env = create_str_array(1, NULL);
+
+ VERIFY_TRUE(_init_symbols());
+ return true;
+}
+
+static int
+cleanup(int success)
+{
+ if (!success) {
+ printf("\nThe output of the plugin:\n%s", data.stdout_str);
+ printf("\nThe error output of the plugin:\n%s", data.stderr_str);
+ }
+
+ VERIFY_TRUE(rmdir_recursive(data.tmp_dir));
+ if (data.tmp_dir2) {
+ VERIFY_TRUE(rmdir_recursive(data.tmp_dir2));
+ }
+
+ free(data.tmp_dir);
+ free(data.tmp_dir2);
+
+ str_array_free(&data.settings);
+ str_array_free(&data.user_info);
+ str_array_free(&data.command_info);
+ str_array_free(&data.plugin_argv);
+ str_array_free(&data.user_env);
+ str_array_free(&data.plugin_options);
+
+ return true;
+}
+
+static int
+check_example_io_plugin_version_display(int is_verbose)
+{
+ const char *errstr = NULL;
+ create_io_plugin_options(data.tmp_dir);
+
+ VERIFY_INT(python_io->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.command_info, data.plugin_argc, data.plugin_argv, data.user_env,
+ data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_INT(python_io->show_version(is_verbose), SUDO_RC_OK);
+
+ python_io->close(0, 0); // this should not call the python plugin close as there was no command run invocation
+
+ if (is_verbose) {
+ // Note: the exact python version is environment dependent
+ VERIFY_STR_CONTAINS(data.stdout_str, "Python interpreter version:");
+ *strstr(data.stdout_str, "Python interpreter version:") = '\0';
+ VERIFY_STDOUT(expected_path("check_example_io_plugin_version_display_full.stdout"));
+ } else {
+ VERIFY_STDOUT(expected_path("check_example_io_plugin_version_display.stdout"));
+ }
+
+ VERIFY_STDERR(expected_path("check_example_io_plugin_version_display.stderr"));
+ VERIFY_FILE("sudo.log", expected_path("check_example_io_plugin_version_display.stored"));
+
+ return true;
+}
+
+static int
+check_example_io_plugin_command_log(void)
+{
+ const char *errstr = NULL;
+ create_io_plugin_options(data.tmp_dir);
+
+ str_array_free(&data.plugin_argv);
+ data.plugin_argc = 2;
+ data.plugin_argv = create_str_array(3, "id", "--help", NULL);
+
+ str_array_free(&data.command_info);
+ data.command_info = create_str_array(3, "command=/bin/id", "runas_uid=0", NULL);
+
+ VERIFY_INT(python_io->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.command_info, data.plugin_argc, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io->log_stdin("some standard input", strlen("some standard input"), &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io->log_stdout("some standard output", strlen("some standard output"), &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io->log_stderr("some standard error", strlen("some standard error"), &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io->log_suspend(SIGTSTP, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io->log_suspend(SIGCONT, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io->change_winsize(200, 100, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io->log_ttyin("some tty input", strlen("some tty input"), &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io->log_ttyout("some tty output", strlen("some tty output"), &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ python_io->close(1, 0); // successful execution, command returned 1
+
+ VERIFY_STDOUT(expected_path("check_example_io_plugin_command_log.stdout"));
+ VERIFY_STDERR(expected_path("check_example_io_plugin_command_log.stderr"));
+ VERIFY_FILE("sudo.log", expected_path("check_example_io_plugin_command_log.stored"));
+
+ return true;
+}
+
+typedef struct io_plugin * (io_clone_func)(void);
+
+static int
+check_example_io_plugin_command_log_multiple(void)
+{
+ const char *errstr = NULL;
+
+ // verify multiple python io plugin symbols are available
+ io_clone_func *python_io_clone = (io_clone_func *)sudo_dso_findsym(python_plugin_handle, "python_io_clone");
+ VERIFY_PTR_NE(python_io_clone, NULL);
+
+ struct io_plugin *python_io2 = NULL;
+
+ for (int i = 0; i < 7; ++i) {
+ python_io2 = (*python_io_clone)();
+ VERIFY_PTR_NE(python_io2, NULL);
+ VERIFY_PTR_NE(python_io2, python_io);
+ }
+
+ // open the first plugin and let it log to tmp_dir
+ create_io_plugin_options(data.tmp_dir);
+
+ str_array_free(&data.plugin_argv);
+ data.plugin_argc = 2;
+ data.plugin_argv = create_str_array(3, "id", "--help", NULL);
+
+ str_array_free(&data.command_info);
+ data.command_info = create_str_array(3, "command=/bin/id", "runas_uid=0", NULL);
+
+ VERIFY_INT(python_io->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.command_info, data.plugin_argc, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ // For verifying the error message of no more plugin. It should be displayed only once.
+ VERIFY_PTR((*python_io_clone)(), NULL);
+ VERIFY_PTR((*python_io_clone)(), NULL);
+
+ // open the second plugin with another log directory
+ VERIFY_TRUE(asprintf(&data.tmp_dir2, TEMP_PATH_TEMPLATE) >= 0);
+ VERIFY_NOT_NULL(mkdtemp(data.tmp_dir2));
+ create_io_plugin_options(data.tmp_dir2);
+
+ str_array_free(&data.plugin_argv);
+ data.plugin_argc = 1;
+ data.plugin_argv = create_str_array(2, "whoami", NULL);
+
+ str_array_free(&data.command_info);
+ data.command_info = create_str_array(3, "command=/bin/whoami", "runas_uid=1", NULL);
+
+ VERIFY_INT(python_io2->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.command_info, data.plugin_argc, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ VERIFY_INT(python_io->log_stdin("stdin for plugin 1", strlen("stdin for plugin 1"), &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io2->log_stdin("stdin for plugin 2", strlen("stdin for plugin 2"), &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io->log_stdout("stdout for plugin 1", strlen("stdout for plugin 1"), &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io2->log_stdout("stdout for plugin 2", strlen("stdout for plugin 2"), &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io->log_stderr("stderr for plugin 1", strlen("stderr for plugin 1"), &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io2->log_stderr("stderr for plugin 2", strlen("stderr for plugin 2"), &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io->log_suspend(SIGTSTP, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io2->log_suspend(SIGSTOP, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io->log_suspend(SIGCONT, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io2->log_suspend(SIGCONT, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io->change_winsize(20, 10, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io2->change_winsize(30, 40, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io->log_ttyin("tty input for plugin 1", strlen("tty input for plugin 1"), &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io2->log_ttyin("tty input for plugin 2", strlen("tty input for plugin 2"), &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io->log_ttyout("tty output for plugin 1", strlen("tty output for plugin 1"), &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io2->log_ttyout("tty output for plugin 2", strlen("tty output for plugin 2"), &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ python_io->close(1, 0); // successful execution, command returned 1
+ python_io2->close(2, 0); // command returned 2
+
+ VERIFY_STDOUT(expected_path("check_example_io_plugin_command_log_multiple.stdout"));
+ VERIFY_STDERR(expected_path("check_example_io_plugin_command_log_multiple.stderr"));
+ VERIFY_FILE("sudo.log", expected_path("check_example_io_plugin_command_log_multiple1.stored"));
+ VERIFY_TRUE(verify_file(data.tmp_dir2, "sudo.log", expected_path("check_example_io_plugin_command_log_multiple2.stored")));
+
+ return true;
+}
+
+static int
+check_example_io_plugin_failed_to_start_command(void)
+{
+ const char *errstr = NULL;
+
+ create_io_plugin_options(data.tmp_dir);
+
+ str_array_free(&data.plugin_argv);
+ data.plugin_argc = 1;
+ data.plugin_argv = create_str_array(2, "cmd", NULL);
+
+ str_array_free(&data.command_info);
+ data.command_info = create_str_array(3, "command=/usr/share/cmd", "runas_uid=0", NULL);
+
+ VERIFY_INT(python_io->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.command_info, data.plugin_argc, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ python_io->close(0, EPERM); // execve returned with error
+
+ VERIFY_STDOUT(expected_path("check_example_io_plugin_failed_to_start_command.stdout"));
+ VERIFY_STDERR(expected_path("check_example_io_plugin_failed_to_start_command.stderr"));
+ VERIFY_FILE("sudo.log", expected_path("check_example_io_plugin_failed_to_start_command.stored"));
+
+ return true;
+}
+
+static int
+check_example_io_plugin_fails_with_python_backtrace(void)
+{
+ const char *errstr = NULL;
+
+ create_io_plugin_options("/some/not/writable/directory");
+
+ VERIFY_INT(python_io->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.command_info, data.plugin_argc, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_ERROR);
+ VERIFY_PTR(errstr, NULL);
+
+ VERIFY_STDOUT(expected_path("check_example_io_plugin_fails_with_python_backtrace.stdout"));
+ VERIFY_STDERR(expected_path("check_example_io_plugin_fails_with_python_backtrace.stderr"));
+
+ python_io->close(0, 0);
+ return true;
+}
+
+static int
+check_io_plugin_reports_error(void)
+{
+ const char *errstr = NULL;
+ str_array_free(&data.plugin_options);
+ data.plugin_options = create_str_array(
+ 3,
+ "ModulePath=" SRC_DIR "/regress/plugin_errorstr.py",
+ "ClassName=ConstructErrorPlugin",
+ NULL
+ );
+
+ VERIFY_INT(python_io->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.command_info, data.plugin_argc, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_ERROR);
+
+ VERIFY_STR(errstr, "Something wrong in plugin constructor");
+ errstr = NULL;
+
+ python_io->close(0, 0);
+
+ str_array_free(&data.plugin_options);
+ data.plugin_options = create_str_array(
+ 3,
+ "ModulePath=" SRC_DIR "/regress/plugin_errorstr.py",
+ "ClassName=ErrorMsgPlugin",
+ NULL
+ );
+
+ VERIFY_INT(python_io->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.command_info, data.plugin_argc, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ VERIFY_INT(python_io->log_stdin("", 0, &errstr), SUDO_RC_ERROR);
+ VERIFY_STR(errstr, "Something wrong in log_stdin");
+
+ errstr = (void *)13;
+ VERIFY_INT(python_io->log_stdout("", 0, &errstr), SUDO_RC_ERROR);
+ VERIFY_STR(errstr, "Something wrong in log_stdout");
+
+ errstr = NULL;
+ VERIFY_INT(python_io->log_stderr("", 0, &errstr), SUDO_RC_ERROR);
+ VERIFY_STR(errstr, "Something wrong in log_stderr");
+
+ errstr = NULL;
+ VERIFY_INT(python_io->log_ttyin("", 0, &errstr), SUDO_RC_ERROR);
+ VERIFY_STR(errstr, "Something wrong in log_ttyin");
+
+ errstr = NULL;
+ VERIFY_INT(python_io->log_ttyout("", 0, &errstr), SUDO_RC_ERROR);
+ VERIFY_STR(errstr, "Something wrong in log_ttyout");
+
+ errstr = NULL;
+ VERIFY_INT(python_io->log_suspend(SIGTSTP, &errstr), SUDO_RC_ERROR);
+ VERIFY_STR(errstr, "Something wrong in log_suspend");
+
+ errstr = NULL;
+ VERIFY_INT(python_io->change_winsize(200, 100, &errstr), SUDO_RC_ERROR);
+ VERIFY_STR(errstr, "Something wrong in change_winsize");
+
+ python_io->close(0, 0);
+
+ VERIFY_STR(data.stderr_str, "");
+ VERIFY_STR(data.stdout_str, "");
+ return true;
+}
+
+static int
+check_example_group_plugin(void)
+{
+ create_plugin_options("example_group_plugin", "SudoGroupPlugin", NULL);
+
+ VERIFY_INT(group_plugin->init(GROUP_API_VERSION, fake_printf, data.plugin_options), SUDO_RC_OK);
+
+ VERIFY_INT(group_plugin->query("test", "mygroup", NULL), SUDO_RC_OK);
+ VERIFY_INT(group_plugin->query("testuser2", "testgroup", NULL), SUDO_RC_OK);
+ VERIFY_INT(group_plugin->query("testuser2", "mygroup", NULL), SUDO_RC_REJECT);
+ VERIFY_INT(group_plugin->query("test", "testgroup", NULL), SUDO_RC_REJECT);
+
+ group_plugin->cleanup();
+ VERIFY_STR(data.stderr_str, "");
+ VERIFY_STR(data.stdout_str, "");
+ return true;
+}
+
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+static const char *
+create_debug_config(const char *debug_spec)
+{
+ char *result = NULL;
+
+ static char config_path[PATH_MAX] = "/";
+ snprintf(config_path, sizeof(config_path), "%s/sudo.conf", data.tmp_dir);
+
+ char *content = NULL;
+ if (asprintf(&content, "Debug %s %s/debug.log %s\n",
+ "python_plugin.so", data.tmp_dir, debug_spec) < 0)
+ {
+ puts("Failed to allocate string");
+ goto cleanup;
+ }
+
+ if (fwriteall(config_path, content) != true) {
+ printf("Failed to write '%s'\n", config_path);
+ goto cleanup;
+ }
+
+ result = config_path;
+
+cleanup:
+ free(content);
+
+ return result;
+}
+
+static int
+check_example_group_plugin_is_able_to_debug(void)
+{
+ const char *config_path = create_debug_config("py_calls@diag");
+ VERIFY_NOT_NULL(config_path);
+ VERIFY_INT(sudo_conf_read(config_path, SUDO_CONF_ALL), true);
+
+ create_plugin_options("example_group_plugin", "SudoGroupPlugin", NULL);
+
+ group_plugin->init(GROUP_API_VERSION, fake_printf, data.plugin_options);
+
+ group_plugin->query("user", "group", &example_pwd);
+
+ group_plugin->cleanup();
+
+ VERIFY_STR(data.stderr_str, "");
+ VERIFY_STR(data.stdout_str, "");
+
+ VERIFY_LOG_LINES(expected_path("check_example_group_plugin_is_able_to_debug.log"));
+
+ return true;
+}
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
+
+static int
+check_plugin_unload(void)
+{
+ // You can call this test to avoid having a lot of subinterpreters
+ // (each plugin->open starts one, and only plugin unlink closes)
+ // It only verifies that python was shut down correctly.
+ VERIFY_TRUE(Py_IsInitialized());
+ VERIFY_TRUE(_unlink_symbols());
+ VERIFY_FALSE(Py_IsInitialized()); // python interpreter could be stopped
+ return true;
+}
+
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+static int
+check_example_debugging(const char *debug_spec)
+{
+ const char *errstr = NULL;
+ const char *config_path = create_debug_config(debug_spec);
+ VERIFY_NOT_NULL(config_path);
+ VERIFY_INT(sudo_conf_read(config_path, SUDO_CONF_ALL), true);
+
+ create_debugging_plugin_options();
+
+ str_array_free(&data.settings);
+ char *debug_flags_setting = NULL;
+ VERIFY_TRUE(asprintf(&debug_flags_setting, "debug_flags=%s/debug.log %s", data.tmp_dir, debug_spec) >= 0);
+
+ data.settings = create_str_array(3, debug_flags_setting, "plugin_path=python_plugin.so", NULL);
+
+ VERIFY_INT(python_io->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.command_info, data.plugin_argc, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ python_io->close(0, 0);
+
+ VERIFY_STR(data.stderr_str, "");
+ VERIFY_STR(data.stdout_str, "");
+
+ VERIFY_LOG_LINES(expected_path("check_example_debugging_%s.log", debug_spec));
+
+ free(debug_flags_setting);
+ return true;
+}
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
+
+static int
+check_loading_fails(const char *name)
+{
+ const char *errstr = NULL;
+
+ VERIFY_INT(python_io->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.command_info, data.plugin_argc, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_ERROR);
+ VERIFY_PTR(errstr, NULL);
+ python_io->close(0, 0);
+
+ VERIFY_STDOUT(expected_path("check_loading_fails_%s.stdout", name));
+ VERIFY_STDERR(expected_path("check_loading_fails_%s.stderr", name));
+
+ return true;
+}
+
+static int
+check_loading_fails_with_missing_path(void)
+{
+ str_array_free(&data.plugin_options);
+ data.plugin_options = create_str_array(2, "ClassName=DebugDemoPlugin", NULL);
+ return check_loading_fails("missing_path");
+}
+
+static int
+check_loading_succeeds_with_missing_classname(void)
+{
+ str_array_free(&data.plugin_options);
+ data.plugin_options = create_str_array(2, "ModulePath=" SRC_DIR "/example_debugging.py", NULL);
+
+ const char *errstr = NULL;
+
+ VERIFY_INT(python_io->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.command_info, data.plugin_argc, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_io->show_version(1), SUDO_RC_OK);
+ python_io->close(0, 0);
+
+ VERIFY_STDOUT(expected_path("check_loading_succeeds_with_missing_classname.stdout"));
+ VERIFY_STR(data.stderr_str, "");
+
+ return true;
+}
+
+static int
+check_loading_fails_with_missing_classname(void)
+{
+ str_array_free(&data.plugin_options);
+ data.plugin_options = create_str_array(2, "ModulePath=" SRC_DIR "/regress/plugin_errorstr.py", NULL);
+ return check_loading_fails("missing_classname");
+}
+
+static int
+check_loading_fails_with_wrong_classname(void)
+{
+ create_plugin_options("example_debugging", "MispelledPluginName", NULL);
+ return check_loading_fails("wrong_classname");
+}
+
+static int
+check_loading_fails_with_wrong_path(void)
+{
+ str_array_free(&data.plugin_options);
+ data.plugin_options = create_str_array(3, "ModulePath=/wrong_path.py", "ClassName=PluginName", NULL);
+ return check_loading_fails("wrong_path");
+}
+
+static int
+check_example_conversation_plugin_reason_log(int simulate_suspend, const char *description)
+{
+ const char *errstr = NULL;
+
+ create_conversation_plugin_options();
+
+ str_array_free(&data.plugin_argv); // have a command run
+ data.plugin_argc = 1;
+ data.plugin_argv = create_str_array(2, "/bin/whoami", NULL);
+
+ data.conv_replies[0] = "my fake reason";
+ data.conv_replies[1] = "my real secret reason";
+
+ sudo_conv_t conversation = simulate_suspend ? fake_conversation_with_suspend : fake_conversation;
+
+ VERIFY_INT(python_io->open(SUDO_API_VERSION, conversation, fake_printf, data.settings,
+ data.user_info, data.command_info, data.plugin_argc, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ python_io->close(0, 0);
+
+ VERIFY_STDOUT(expected_path("check_example_conversation_plugin_reason_log_%s.stdout", description));
+ VERIFY_STDERR(expected_path("check_example_conversation_plugin_reason_log_%s.stderr", description));
+ VERIFY_CONV(expected_path("check_example_conversation_plugin_reason_log_%s.conversation", description));
+ VERIFY_FILE("sudo_reasons.txt", expected_path("check_example_conversation_plugin_reason_log_%s.stored", description));
+ return true;
+}
+
+static int
+check_example_conversation_plugin_user_interrupts(void)
+{
+ const char *errstr = NULL;
+
+ create_conversation_plugin_options();
+
+ str_array_free(&data.plugin_argv); // have a command run
+ data.plugin_argc = 1;
+ data.plugin_argv = create_str_array(2, "/bin/whoami", NULL);
+
+ data.conv_replies[0] = NULL; // this simulates user interrupt for the first question
+
+ VERIFY_INT(python_io->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.command_info, data.plugin_argc, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_REJECT);
+ VERIFY_PTR(errstr, NULL);
+ python_io->close(0, 0);
+
+ VERIFY_STDOUT(expected_path("check_example_conversation_plugin_user_interrupts.stdout"));
+ VERIFY_STDERR(expected_path("check_example_conversation_plugin_user_interrupts.stderr"));
+ VERIFY_CONV(expected_path("check_example_conversation_plugin_user_interrupts.conversation"));
+ return true;
+}
+
+static int
+check_example_policy_plugin_version_display(int is_verbose)
+{
+ const char *errstr = NULL;
+
+ create_policy_plugin_options();
+
+ VERIFY_INT(python_policy->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.user_env, data.plugin_options, &errstr),
+ SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_INT(python_policy->show_version(is_verbose), SUDO_RC_OK);
+
+ python_policy->close(0, 0); // this should not call the python plugin close as there was no command run invocation
+
+ if (is_verbose) {
+ // Note: the exact python version is environment dependent
+ VERIFY_STR_CONTAINS(data.stdout_str, "Python interpreter version:");
+ *strstr(data.stdout_str, "Python interpreter version:") = '\0';
+ VERIFY_STDOUT(expected_path("check_example_policy_plugin_version_display_full.stdout"));
+ } else {
+ VERIFY_STDOUT(expected_path("check_example_policy_plugin_version_display.stdout"));
+ }
+
+ VERIFY_STDERR(expected_path("check_example_policy_plugin_version_display.stderr"));
+
+ return true;
+}
+
+static int
+check_example_policy_plugin_accepted_execution(void)
+{
+ const char *errstr = NULL;
+
+ create_policy_plugin_options();
+
+ str_array_free(&data.plugin_argv);
+ data.plugin_argc = 2;
+ data.plugin_argv = create_str_array(3, "/bin/whoami", "--help", NULL);
+
+ str_array_free(&data.user_env);
+ data.user_env = create_str_array(3, "USER_ENV1=VALUE1", "USER_ENV2=value2", NULL);
+
+ VERIFY_INT(python_policy->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.user_env, data.plugin_options, &errstr),
+ SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ char **env_add = create_str_array(3, "REQUESTED_ENV1=VALUE1", "REQUESTED_ENV2=value2", NULL);
+
+ char **argv_out, **user_env_out, **command_info_out; // free to contain garbage
+
+ VERIFY_INT(python_policy->check_policy(data.plugin_argc, data.plugin_argv, env_add,
+ &command_info_out, &argv_out, &user_env_out, &errstr),
+ SUDO_RC_ACCEPT);
+ VERIFY_PTR(errstr, NULL);
+
+ VERIFY_STR_SET(command_info_out, 4, "command=/bin/whoami", "runas_uid=0", "runas_gid=0", NULL);
+ VERIFY_STR_SET(user_env_out, 5, "USER_ENV1=VALUE1", "USER_ENV2=value2",
+ "REQUESTED_ENV1=VALUE1", "REQUESTED_ENV2=value2", NULL);
+ VERIFY_STR_SET(argv_out, 3, "/bin/whoami", "--help", NULL);
+
+ VERIFY_INT(python_policy->init_session(&example_pwd, &user_env_out, &errstr), SUDO_RC_ACCEPT);
+ VERIFY_PTR(errstr, NULL);
+
+ // init session is able to modify the user env:
+ VERIFY_STR_SET(user_env_out, 6, "USER_ENV1=VALUE1", "USER_ENV2=value2",
+ "REQUESTED_ENV1=VALUE1", "REQUESTED_ENV2=value2", "PLUGIN_EXAMPLE_ENV=1", NULL);
+
+ python_policy->close(3, 0); // successful execution returned exit code 3
+
+ VERIFY_STDOUT(expected_path("check_example_policy_plugin_accepted_execution.stdout"));
+ VERIFY_STDERR(expected_path("check_example_policy_plugin_accepted_execution.stderr"));
+
+ str_array_free(&env_add);
+ str_array_free(&user_env_out);
+ str_array_free(&command_info_out);
+ str_array_free(&argv_out);
+ return true;
+}
+
+static int
+check_example_policy_plugin_failed_execution(void)
+{
+ const char *errstr = NULL;
+
+ create_policy_plugin_options();
+
+ str_array_free(&data.plugin_argv);
+ data.plugin_argc = 2;
+ data.plugin_argv = create_str_array(3, "/bin/id", "--help", NULL);
+
+ VERIFY_INT(python_policy->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.user_env, data.plugin_options, &errstr),
+ SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ char **argv_out, **user_env_out, **command_info_out; // free to contain garbage
+
+ VERIFY_INT(python_policy->check_policy(data.plugin_argc, data.plugin_argv, NULL,
+ &command_info_out, &argv_out, &user_env_out, &errstr),
+ SUDO_RC_ACCEPT);
+ VERIFY_PTR(errstr, NULL);
+
+ // pwd is unset (user is not part of /etc/passwd)
+ VERIFY_INT(python_policy->init_session(NULL, &user_env_out, &errstr), SUDO_RC_ACCEPT);
+ VERIFY_PTR(errstr, NULL);
+
+ python_policy->close(12345, ENOENT); // failed to execute
+
+ VERIFY_STDOUT(expected_path("check_example_policy_plugin_failed_execution.stdout"));
+ VERIFY_STDERR(expected_path("check_example_policy_plugin_failed_execution.stderr"));
+
+ str_array_free(&user_env_out);
+ str_array_free(&command_info_out);
+ str_array_free(&argv_out);
+ return true;
+}
+
+static int
+check_example_policy_plugin_denied_execution(void)
+{
+ const char *errstr = NULL;
+
+ create_policy_plugin_options();
+
+ str_array_free(&data.plugin_argv);
+ data.plugin_argc = 1;
+ data.plugin_argv = create_str_array(2, "/bin/passwd", NULL);
+
+ VERIFY_INT(python_policy->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.user_env, data.plugin_options, &errstr),
+ SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ char **argv_out, **user_env_out, **command_info_out; // free to contain garbage
+
+ VERIFY_INT(python_policy->check_policy(data.plugin_argc, data.plugin_argv, NULL,
+ &command_info_out, &argv_out, &user_env_out, &errstr),
+ SUDO_RC_REJECT);
+ VERIFY_PTR(errstr, NULL);
+
+ VERIFY_PTR(command_info_out, NULL);
+ VERIFY_PTR(argv_out, NULL);
+ VERIFY_PTR(user_env_out, NULL);
+
+ python_policy->close(0, 0); // there was no execution
+
+ VERIFY_STDOUT(expected_path("check_example_policy_plugin_denied_execution.stdout"));
+ VERIFY_STDERR(expected_path("check_example_policy_plugin_denied_execution.stderr"));
+
+ return true;
+}
+
+static int
+check_example_policy_plugin_list(void)
+{
+ const char *errstr = NULL;
+
+ create_policy_plugin_options();
+
+ VERIFY_INT(python_policy->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.user_env, data.plugin_options, &errstr),
+ SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ snprintf_append(data.stdout_str, MAX_OUTPUT, "-- minimal --\n");
+ VERIFY_INT(python_policy->list(data.plugin_argc, data.plugin_argv, false, NULL, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ snprintf_append(data.stdout_str, MAX_OUTPUT, "\n-- minimal (verbose) --\n");
+ VERIFY_INT(python_policy->list(data.plugin_argc, data.plugin_argv, true, NULL, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ snprintf_append(data.stdout_str, MAX_OUTPUT, "\n-- with user --\n");
+ VERIFY_INT(python_policy->list(data.plugin_argc, data.plugin_argv, false, "testuser", &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ snprintf_append(data.stdout_str, MAX_OUTPUT, "\n-- with user (verbose) --\n");
+ VERIFY_INT(python_policy->list(data.plugin_argc, data.plugin_argv, true, "testuser", &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ snprintf_append(data.stdout_str, MAX_OUTPUT, "\n-- with allowed program --\n");
+ str_array_free(&data.plugin_argv);
+ data.plugin_argc = 3;
+ data.plugin_argv = create_str_array(4, "/bin/id", "some", "arguments", NULL);
+ VERIFY_INT(python_policy->list(data.plugin_argc, data.plugin_argv, false, NULL, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ snprintf_append(data.stdout_str, MAX_OUTPUT, "\n-- with allowed program (verbose) --\n");
+ VERIFY_INT(python_policy->list(data.plugin_argc, data.plugin_argv, true, NULL, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ snprintf_append(data.stdout_str, MAX_OUTPUT, "\n-- with denied program --\n");
+ str_array_free(&data.plugin_argv);
+ data.plugin_argc = 1;
+ data.plugin_argv = create_str_array(2, "/bin/passwd", NULL);
+ VERIFY_INT(python_policy->list(data.plugin_argc, data.plugin_argv, false, NULL, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ snprintf_append(data.stdout_str, MAX_OUTPUT, "\n-- with denied program (verbose) --\n");
+ VERIFY_INT(python_policy->list(data.plugin_argc, data.plugin_argv, true, NULL, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ python_policy->close(0, 0); // there was no execution
+
+ VERIFY_STDOUT(expected_path("check_example_policy_plugin_list.stdout"));
+ VERIFY_STDERR(expected_path("check_example_policy_plugin_list.stderr"));
+
+ return true;
+}
+
+static int
+check_example_policy_plugin_validate_invalidate(void)
+{
+ const char *errstr = NULL;
+
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ // the plugin does not do any meaningful for these, so using log to validate instead
+ const char *config_path = create_debug_config("py_calls@diag");
+ VERIFY_NOT_NULL(config_path);
+ VERIFY_INT(sudo_conf_read(config_path, SUDO_CONF_ALL), true);
+#endif
+
+ create_policy_plugin_options();
+
+ VERIFY_INT(python_policy->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.user_env, data.plugin_options, &errstr),
+ SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ VERIFY_INT(python_policy->validate(&errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ python_policy->invalidate(true);
+ python_policy->invalidate(false);
+
+ python_policy->close(0, 0); // no command execution
+
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ VERIFY_LOG_LINES(expected_path("check_example_policy_plugin_validate_invalidate.log"));
+#endif
+ VERIFY_STR(data.stderr_str, "");
+ VERIFY_STR(data.stdout_str, "");
+ return true;
+}
+
+static int
+check_policy_plugin_callbacks_are_optional(void)
+{
+ const char *errstr = NULL;
+
+ create_debugging_plugin_options();
+
+ VERIFY_INT(python_policy->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.user_env, data.plugin_options, &errstr),
+ SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ VERIFY_PTR(python_policy->list, NULL);
+ VERIFY_PTR(python_policy->validate, NULL);
+ VERIFY_PTR(python_policy->invalidate, NULL);
+ VERIFY_PTR_NE(python_policy->check_policy, NULL); // (not optional)
+ VERIFY_PTR(python_policy->init_session, NULL);
+
+ // show_version always displays the plugin, but it is optional in the python layer
+ VERIFY_PTR_NE(python_policy->show_version, NULL);
+ VERIFY_INT(python_policy->show_version(1), SUDO_RC_OK);
+
+ python_policy->close(0, 0);
+ return true;
+}
+
+static int
+check_policy_plugin_reports_error(void)
+{
+ const char *errstr = NULL;
+ str_array_free(&data.plugin_options);
+ data.plugin_options = create_str_array(
+ 3,
+ "ModulePath=" SRC_DIR "/regress/plugin_errorstr.py",
+ "ClassName=ConstructErrorPlugin",
+ NULL
+ );
+
+ VERIFY_INT(python_policy->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.user_env, data.plugin_options, &errstr), SUDO_RC_ERROR);
+ VERIFY_STR(errstr, "Something wrong in plugin constructor");
+ errstr = NULL;
+
+ python_policy->close(0, 0);
+
+ str_array_free(&data.plugin_options);
+ data.plugin_options = create_str_array(
+ 3,
+ "ModulePath=" SRC_DIR "/regress/plugin_errorstr.py",
+ "ClassName=ErrorMsgPlugin",
+ NULL
+ );
+
+ data.plugin_argc = 1;
+ str_array_free(&data.plugin_argv);
+ data.plugin_argv = create_str_array(2, "id", NULL);
+
+ VERIFY_INT(python_policy->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ char **command_info_out = NULL;
+ char **argv_out = NULL;
+ char **user_env_out = NULL;
+
+ VERIFY_INT(python_policy->list(data.plugin_argc, data.plugin_argv, true, NULL, &errstr), SUDO_RC_ERROR);
+ VERIFY_STR(errstr, "Something wrong in list");
+
+ errstr = NULL;
+ VERIFY_INT(python_policy->validate(&errstr), SUDO_RC_ERROR);
+ VERIFY_STR(errstr, "Something wrong in validate");
+
+ errstr = NULL;
+ VERIFY_INT(python_policy->check_policy(data.plugin_argc, data.plugin_argv, data.user_env,
+ &command_info_out, &argv_out, &user_env_out, &errstr),
+ SUDO_RC_ERROR);
+ VERIFY_STR(errstr, "Something wrong in check_policy");
+
+ errstr = NULL;
+ VERIFY_INT(python_policy->init_session(&example_pwd, &user_env_out, &errstr), SUDO_RC_ERROR);
+ VERIFY_STR(errstr, "Something wrong in init_session");
+
+ python_policy->close(0, 0);
+
+ VERIFY_STR(data.stderr_str, "");
+ VERIFY_STR(data.stdout_str, "");
+ return true;
+}
+
+static int
+check_io_plugin_callbacks_are_optional(void)
+{
+ const char *errstr = NULL;
+
+ create_debugging_plugin_options();
+
+ VERIFY_INT(python_io->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.command_info, data.plugin_argc, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ VERIFY_PTR(python_io->log_stdin, NULL);
+ VERIFY_PTR(python_io->log_stdout, NULL);
+ VERIFY_PTR(python_io->log_stderr, NULL);
+ VERIFY_PTR(python_io->log_ttyin, NULL);
+ VERIFY_PTR(python_io->log_ttyout, NULL);
+ VERIFY_PTR(python_io->change_winsize, NULL);
+
+ // show_version always displays the plugin, but it is optional in the python layer
+ VERIFY_PTR_NE(python_io->show_version, NULL);
+ VERIFY_INT(python_io->show_version(1), SUDO_RC_OK);
+
+ python_io->close(0, 0);
+ return true;
+}
+
+static int
+check_python_plugins_do_not_affect_each_other(void)
+{
+ const char *errstr = NULL;
+
+ // We test here that one plugin is not able to effect the environment of another
+ // This is important so they do not ruin or depend on each other's state.
+ create_plugin_options("regress/plugin_conflict", "ConflictPlugin", "Path=path_for_first_plugin");
+
+ VERIFY_INT(python_io->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.command_info, data.plugin_argc, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ create_plugin_options("regress/plugin_conflict", "ConflictPlugin", "Path=path_for_second_plugin");
+ VERIFY_INT(python_policy->open(SUDO_API_VERSION, fake_conversation, fake_printf, data.settings,
+ data.user_info, data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ python_io->close(0, 0);
+ python_policy->close(0, 0);
+
+ VERIFY_STDOUT(expected_path("check_python_plugins_do_not_affect_each_other.stdout"));
+ VERIFY_STR(data.stderr_str, "");
+ return true;
+}
+
+static int
+check_example_audit_plugin_receives_accept(void)
+{
+ create_audit_plugin_options("");
+ const char *errstr = NULL;
+
+ str_array_free(&data.plugin_argv);
+ data.plugin_argv = create_str_array(6, "sudo", "-u", "user", "id", "--help", NULL);
+
+ str_array_free(&data.user_env);
+ data.user_env = create_str_array(3, "KEY1=VALUE1", "KEY2=VALUE2", NULL);
+
+ str_array_free(&data.user_info);
+ data.user_info = create_str_array(3, "user=testuser1", "uid=123", NULL);
+
+ VERIFY_INT(python_audit->open(SUDO_API_VERSION, fake_conversation, fake_printf,
+ data.settings, data.user_info, 3, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ str_array_free(&data.command_info);
+ data.command_info = create_str_array(2, "command=/sbin/id", NULL);
+
+ str_array_free(&data.plugin_argv);
+ data.plugin_argv = create_str_array(3, "id", "--help", NULL);
+
+ VERIFY_INT(python_audit->accept("accepter plugin name", SUDO_POLICY_PLUGIN,
+ data.command_info, data.plugin_argv,
+ data.user_env, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ python_audit->close(SUDO_PLUGIN_WAIT_STATUS, W_EXITCODE(2, 0)); // process exited with 2
+
+ VERIFY_STDOUT(expected_path("check_example_audit_plugin_receives_accept.stdout"));
+ VERIFY_STR(data.stderr_str, "");
+
+ return true;
+}
+
+static int
+check_example_audit_plugin_receives_reject(void)
+{
+ create_audit_plugin_options(NULL);
+ const char *errstr = NULL;
+
+ str_array_free(&data.plugin_argv);
+ data.plugin_argv = create_str_array(3, "sudo", "passwd", NULL);
+
+ str_array_free(&data.user_info);
+ data.user_info = create_str_array(3, "user=root", "uid=0", NULL);
+
+ VERIFY_INT(python_audit->open(SUDO_API_VERSION, fake_conversation, fake_printf,
+ data.settings, data.user_info, 1, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ VERIFY_INT(python_audit->reject("rejecter plugin name", SUDO_IO_PLUGIN,
+ "Rejected just because!", data.command_info,
+ &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ python_audit->close(SUDO_PLUGIN_NO_STATUS, 0); // program was not run
+
+ VERIFY_STDOUT(expected_path("check_example_audit_plugin_receives_reject.stdout"));
+ VERIFY_STR(data.stderr_str, "");
+
+ return true;
+}
+
+static int
+check_example_audit_plugin_receives_error(void)
+{
+ create_audit_plugin_options("");
+ const char *errstr = NULL;
+
+ str_array_free(&data.plugin_argv);
+ data.plugin_argv = create_str_array(5, "sudo", "-u", "user", "id", NULL);
+
+ VERIFY_INT(python_audit->open(SUDO_API_VERSION, fake_conversation, fake_printf,
+ data.settings, data.user_info, 3, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ str_array_free(&data.command_info);
+ data.command_info = create_str_array(2, "command=/sbin/id", NULL);
+
+ VERIFY_INT(python_audit->error("errorer plugin name", SUDO_AUDIT_PLUGIN,
+ "Some error has happened", data.command_info,
+ &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ python_audit->close(SUDO_PLUGIN_SUDO_ERROR, 222);
+
+ VERIFY_STDOUT(expected_path("check_example_audit_plugin_receives_error.stdout"));
+ VERIFY_STR(data.stderr_str, "");
+
+ return true;
+}
+
+typedef struct audit_plugin * (audit_clone_func)(void);
+
+static int
+check_example_audit_plugin_workflow_multiple(void)
+{
+ // verify multiple python audit plugins are available
+ audit_clone_func *python_audit_clone = (audit_clone_func *)sudo_dso_findsym(
+ python_plugin_handle, "python_audit_clone");
+ VERIFY_PTR_NE(python_audit_clone, NULL);
+
+ struct audit_plugin *python_audit2 = NULL;
+
+ for (int i = 0; i < 7; ++i) {
+ python_audit2 = (*python_audit_clone)();
+ VERIFY_PTR_NE(python_audit2, NULL);
+ VERIFY_PTR_NE(python_audit2, python_audit);
+ }
+
+ const char *errstr = NULL;
+
+ str_array_free(&data.plugin_argv);
+ data.plugin_argv = create_str_array(6, "sudo", "-u", "user", "id", "--help", NULL);
+
+ str_array_free(&data.user_env);
+ data.user_env = create_str_array(3, "KEY1=VALUE1", "KEY2=VALUE2", NULL);
+
+ str_array_free(&data.user_info);
+ data.user_info = create_str_array(3, "user=default", "uid=1000", NULL);
+
+ create_audit_plugin_options("Id=1");
+ VERIFY_INT(python_audit->open(SUDO_API_VERSION, fake_conversation, fake_printf,
+ data.settings, data.user_info, 3, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ // For verifying the error message of no more plugin. It should be displayed only once.
+ VERIFY_PTR((*python_audit_clone)(), NULL);
+ VERIFY_PTR((*python_audit_clone)(), NULL);
+
+ create_audit_plugin_options("Id=2");
+ VERIFY_INT(python_audit2->open(SUDO_API_VERSION, fake_conversation, fake_printf,
+ data.settings, data.user_info, 3, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ str_array_free(&data.command_info);
+ data.command_info = create_str_array(2, "command=/sbin/id", NULL);
+
+ str_array_free(&data.plugin_argv);
+ data.plugin_argv = create_str_array(3, "id", "--help", NULL);
+
+ VERIFY_INT(python_audit->accept("accepter plugin name", SUDO_POLICY_PLUGIN,
+ data.command_info, data.plugin_argv,
+ data.user_env, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ VERIFY_INT(python_audit2->accept("accepter plugin name", SUDO_POLICY_PLUGIN,
+ data.command_info, data.plugin_argv,
+ data.user_env, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ python_audit->close(SUDO_PLUGIN_WAIT_STATUS, W_EXITCODE(0, 11)); // process got signal 11
+ python_audit2->close(SUDO_PLUGIN_WAIT_STATUS, W_EXITCODE(0, 11));
+
+ VERIFY_STDOUT(expected_path("check_example_audit_plugin_workflow_multiple.stdout"));
+ VERIFY_STDERR(expected_path("check_example_audit_plugin_workflow_multiple.stderr"));
+
+ return true;
+}
+
+static int
+check_example_audit_plugin_version_display(void)
+{
+ create_audit_plugin_options(NULL);
+ const char *errstr = NULL;
+
+ str_array_free(&data.user_info);
+ data.user_info = create_str_array(3, "user=root", "uid=0", NULL);
+
+ str_array_free(&data.plugin_argv);
+ data.plugin_argv = create_str_array(3, "sudo", "-V", NULL);
+
+ VERIFY_INT(python_audit->open(SUDO_API_VERSION, fake_conversation, fake_printf,
+ data.settings, data.user_info, 2, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ VERIFY_INT(python_audit->show_version(false), SUDO_RC_OK);
+ VERIFY_INT(python_audit->show_version(true), SUDO_RC_OK);
+
+ python_audit->close(SUDO_PLUGIN_SUDO_ERROR, 222);
+
+ VERIFY_STDOUT(expected_path("check_example_audit_plugin_version_display.stdout"));
+ VERIFY_STR(data.stderr_str, "");
+
+ return true;
+}
+
+static int
+check_audit_plugin_callbacks_are_optional(void)
+{
+ const char *errstr = NULL;
+
+ create_debugging_plugin_options();
+
+ VERIFY_INT(python_audit->open(SUDO_API_VERSION, fake_conversation, fake_printf,
+ data.settings, data.user_info, 2, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr),
+ SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ VERIFY_PTR(python_audit->accept, NULL);
+ VERIFY_PTR(python_audit->reject, NULL);
+ VERIFY_PTR(python_audit->error, NULL);
+
+ // show_version always displays the plugin, but it is optional in the python layer
+ VERIFY_PTR_NE(python_audit->show_version, NULL);
+ VERIFY_INT(python_audit->show_version(1), SUDO_RC_OK);
+
+ python_audit->close(SUDO_PLUGIN_NO_STATUS, 0);
+ return true;
+}
+
+static int
+check_audit_plugin_reports_error(void)
+{
+ const char *errstr = NULL;
+ create_plugin_options("regress/plugin_errorstr", "ConstructErrorPlugin", NULL);
+
+ VERIFY_INT(python_audit->open(SUDO_API_VERSION, fake_conversation, fake_printf,
+ data.settings, data.user_info, 0, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_ERROR);
+
+ VERIFY_STR(errstr, "Something wrong in plugin constructor");
+ errstr = NULL;
+
+ python_audit->close(SUDO_PLUGIN_NO_STATUS, 0);
+
+ create_plugin_options("regress/plugin_errorstr", "ErrorMsgPlugin", NULL);
+
+ VERIFY_INT(python_audit->open(SUDO_API_VERSION, fake_conversation, fake_printf,
+ data.settings, data.user_info, 0, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_ERROR);
+ VERIFY_STR(errstr, "Something wrong in open");
+
+ errstr = NULL;
+ VERIFY_INT(python_audit->accept("plugin name", SUDO_POLICY_PLUGIN,
+ data.command_info, data.plugin_argv,
+ data.user_env, &errstr), SUDO_RC_ERROR);
+ VERIFY_STR(errstr, "Something wrong in accept");
+
+ errstr = NULL;
+ VERIFY_INT(python_audit->reject("plugin name", SUDO_POLICY_PLUGIN,
+ "audit message", data.command_info,
+ &errstr), SUDO_RC_ERROR);
+ VERIFY_STR(errstr, "Something wrong in reject");
+
+ errstr = NULL;
+ VERIFY_INT(python_audit->error("plugin name", SUDO_POLICY_PLUGIN,
+ "audit message", data.command_info,
+ &errstr), SUDO_RC_ERROR);
+ VERIFY_STR(errstr, "Something wrong in error");
+
+ python_audit->close(SUDO_PLUGIN_NO_STATUS, 0);
+
+ VERIFY_STR(data.stderr_str, "");
+ VERIFY_STR(data.stdout_str, "");
+ return true;
+}
+
+static int
+check_example_approval_plugin(const char *date_str, const char *expected_error)
+{
+ const char *errstr = NULL;
+
+ create_plugin_options("example_approval_plugin", "BusinessHoursApprovalPlugin", NULL);
+
+ VERIFY_INT(python_approval->open(SUDO_API_VERSION, fake_conversation, fake_printf,
+ data.settings, data.user_info, 0, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+
+ VERIFY_TRUE(mock_python_datetime_now("example_approval_plugin", date_str));
+
+ int expected_rc = (expected_error == NULL) ? SUDO_RC_ACCEPT : SUDO_RC_REJECT;
+
+ VERIFY_INT(python_approval->check(data.command_info, data.plugin_argv, data.user_env, &errstr),
+ expected_rc);
+
+ if (expected_error == NULL) {
+ VERIFY_PTR(errstr, NULL);
+ VERIFY_STR(data.stdout_str, "");
+ } else {
+ VERIFY_STR(errstr, expected_error);
+ VERIFY_STR_CONTAINS(data.stdout_str, expected_error); // (ends with \n)
+ }
+ VERIFY_STR(data.stderr_str, "");
+
+ python_approval->close();
+
+ return true;
+}
+
+typedef struct approval_plugin * (approval_clone_func)(void);
+
+static int
+check_multiple_approval_plugin_and_arguments(void)
+{
+ // verify multiple python approval plugins are available
+ approval_clone_func *python_approval_clone = (approval_clone_func *)sudo_dso_findsym(
+ python_plugin_handle, "python_approval_clone");
+ VERIFY_PTR_NE(python_approval_clone, NULL);
+
+ struct approval_plugin *python_approval2 = NULL;
+
+ for (int i = 0; i < 7; ++i) {
+ python_approval2 = (*python_approval_clone)();
+ VERIFY_PTR_NE(python_approval2, NULL);
+ VERIFY_PTR_NE(python_approval2, python_approval);
+ }
+
+ const char *errstr = NULL;
+ create_plugin_options("regress/plugin_approval_test", "ApprovalTestPlugin", "Id=1");
+
+ str_array_free(&data.plugin_argv);
+ data.plugin_argv = create_str_array(6, "sudo", "-u", "user", "whoami", "--help", NULL);
+
+ str_array_free(&data.user_env);
+ data.user_env = create_str_array(3, "USER_ENV1=VALUE1", "USER_ENV2=value2", NULL);
+
+ str_array_free(&data.user_info);
+ data.user_info = create_str_array(3, "INFO1=VALUE1", "info2=value2", NULL);
+
+ str_array_free(&data.settings);
+ data.settings = create_str_array(3, "SETTING1=VALUE1", "setting2=value2", NULL);
+
+ VERIFY_INT(python_approval->open(SUDO_API_VERSION, fake_conversation, fake_printf,
+ data.settings, data.user_info, 3, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ // For verifying the error message of no more plugin. It should be displayed only once.
+ VERIFY_PTR((*python_approval_clone)(), NULL);
+ VERIFY_PTR((*python_approval_clone)(), NULL);
+
+ create_plugin_options("regress/plugin_approval_test", "ApprovalTestPlugin", "Id=2");
+ VERIFY_INT(python_approval2->open(SUDO_API_VERSION, fake_conversation, fake_printf,
+ data.settings, data.user_info, 3, data.plugin_argv,
+ data.user_env, data.plugin_options, &errstr), SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ VERIFY_INT(python_approval->show_version(false), SUDO_RC_OK);
+ VERIFY_INT(python_approval2->show_version(true), SUDO_RC_OK);
+
+ str_array_free(&data.command_info);
+ data.command_info = create_str_array(3, "CMDINFO1=value1", "CMDINFO2=VALUE2", NULL);
+
+ str_array_free(&data.plugin_argv);
+ data.plugin_argv = create_str_array(3, "whoami", "--help", NULL);
+
+ VERIFY_INT(python_approval->check(data.command_info, data.plugin_argv, data.user_env, &errstr),
+ SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ VERIFY_INT(python_approval2->check(data.command_info, data.plugin_argv, data.user_env, &errstr),
+ SUDO_RC_OK);
+ VERIFY_PTR(errstr, NULL);
+
+ python_approval->close();
+ python_approval2->close();
+
+ VERIFY_STDOUT(expected_path("check_multiple_approval_plugin_and_arguments.stdout"));
+ VERIFY_STDERR(expected_path("check_multiple_approval_plugin_and_arguments.stderr"));
+
+ return true;
+}
+
+
+static int
+_init_symbols(void)
+{
+ if (python_plugin_handle != NULL) {
+ // symbols are already loaded, we just restore
+ RESTORE_PYTHON_PLUGIN(python_io);
+ RESTORE_PYTHON_PLUGIN(python_policy);
+ RESTORE_PYTHON_PLUGIN(python_approval);
+ RESTORE_PYTHON_PLUGIN(python_audit);
+ RESTORE_PYTHON_PLUGIN(group_plugin);
+ return true;
+ }
+
+ // we load the symbols
+ python_plugin_handle = sudo_dso_load(python_plugin_so_path, SUDO_DSO_LAZY|SUDO_DSO_GLOBAL);
+ VERIFY_PTR_NE(python_plugin_handle, NULL);
+
+ python_io = sudo_dso_findsym(python_plugin_handle, "python_io");
+ VERIFY_PTR_NE(python_io, NULL);
+
+ group_plugin = sudo_dso_findsym(python_plugin_handle, "group_plugin");
+ VERIFY_PTR_NE(group_plugin, NULL);
+
+ python_policy = sudo_dso_findsym(python_plugin_handle, "python_policy");
+ VERIFY_PTR_NE(python_policy, NULL);
+
+ python_audit = sudo_dso_findsym(python_plugin_handle, "python_audit");
+ VERIFY_PTR_NE(python_audit, NULL);
+
+ python_approval = sudo_dso_findsym(python_plugin_handle, "python_approval");
+ VERIFY_PTR_NE(python_approval, NULL);
+
+ SAVE_PYTHON_PLUGIN(python_io);
+ SAVE_PYTHON_PLUGIN(python_policy);
+ SAVE_PYTHON_PLUGIN(python_approval);
+ SAVE_PYTHON_PLUGIN(python_audit);
+ SAVE_PYTHON_PLUGIN(group_plugin);
+
+ return true;
+}
+
+static int
+_unlink_symbols(void)
+{
+ python_io = NULL;
+ group_plugin = NULL;
+ python_policy = NULL;
+ python_approval = NULL;
+ python_audit = NULL;
+ VERIFY_INT(sudo_dso_unload(python_plugin_handle), 0);
+ python_plugin_handle = NULL;
+ VERIFY_FALSE(Py_IsInitialized());
+ return true;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch, errors = 0, ntests = 0;
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ verbose = true;
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1) {
+ printf("Please specify the python_plugin.so as argument!\n");
+ return EXIT_FAILURE;
+ }
+ python_plugin_so_path = argv[0];
+
+ // Unbuffer stdout so we don't miss output during a crash.
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ RUN_TEST(check_example_io_plugin_version_display(true));
+ RUN_TEST(check_example_io_plugin_version_display(false));
+ RUN_TEST(check_example_io_plugin_command_log());
+ RUN_TEST(check_example_io_plugin_command_log_multiple());
+ RUN_TEST(check_example_io_plugin_failed_to_start_command());
+ RUN_TEST(check_example_io_plugin_fails_with_python_backtrace());
+ RUN_TEST(check_io_plugin_callbacks_are_optional());
+ RUN_TEST(check_io_plugin_reports_error());
+ RUN_TEST(check_plugin_unload());
+
+ RUN_TEST(check_example_group_plugin());
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ RUN_TEST(check_example_group_plugin_is_able_to_debug());
+#endif
+ RUN_TEST(check_plugin_unload());
+
+ RUN_TEST(check_loading_fails_with_missing_path());
+ RUN_TEST(check_loading_succeeds_with_missing_classname());
+ RUN_TEST(check_loading_fails_with_missing_classname());
+ RUN_TEST(check_loading_fails_with_wrong_classname());
+ RUN_TEST(check_loading_fails_with_wrong_path());
+ RUN_TEST(check_plugin_unload());
+
+ RUN_TEST(check_example_conversation_plugin_reason_log(false, "without_suspend"));
+ RUN_TEST(check_example_conversation_plugin_reason_log(true, "with_suspend"));
+ RUN_TEST(check_example_conversation_plugin_user_interrupts());
+ RUN_TEST(check_plugin_unload());
+
+ RUN_TEST(check_example_policy_plugin_version_display(true));
+ RUN_TEST(check_example_policy_plugin_version_display(false));
+ RUN_TEST(check_example_policy_plugin_accepted_execution());
+ RUN_TEST(check_example_policy_plugin_failed_execution());
+ RUN_TEST(check_example_policy_plugin_denied_execution());
+ RUN_TEST(check_example_policy_plugin_list());
+ RUN_TEST(check_example_policy_plugin_validate_invalidate());
+ RUN_TEST(check_policy_plugin_callbacks_are_optional());
+ RUN_TEST(check_policy_plugin_reports_error());
+ RUN_TEST(check_plugin_unload());
+
+ RUN_TEST(check_example_audit_plugin_receives_accept());
+ RUN_TEST(check_example_audit_plugin_receives_reject());
+ RUN_TEST(check_example_audit_plugin_receives_error());
+ RUN_TEST(check_example_audit_plugin_workflow_multiple());
+ RUN_TEST(check_example_audit_plugin_version_display());
+ RUN_TEST(check_audit_plugin_callbacks_are_optional());
+ RUN_TEST(check_audit_plugin_reports_error());
+ RUN_TEST(check_plugin_unload());
+
+ // Monday, too early
+ RUN_TEST(check_example_approval_plugin(
+ "2020-02-10T07:55:23", "That is not allowed outside the business hours!"));
+ // Monday, good time
+ RUN_TEST(check_example_approval_plugin("2020-02-10T08:05:23", NULL));
+ // Friday, good time
+ RUN_TEST(check_example_approval_plugin("2020-02-14T17:59:23", NULL));
+ // Friday, too late
+ RUN_TEST(check_example_approval_plugin(
+ "2020-02-10T18:05:23", "That is not allowed outside the business hours!"));
+ // Saturday
+ RUN_TEST(check_example_approval_plugin(
+ "2020-02-15T08:05:23", "That is not allowed on the weekend!"));
+ RUN_TEST(check_multiple_approval_plugin_and_arguments());
+
+ RUN_TEST(check_python_plugins_do_not_affect_each_other());
+ RUN_TEST(check_plugin_unload());
+
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ RUN_TEST(check_example_debugging("plugin@err"));
+ RUN_TEST(check_example_debugging("plugin@info"));
+ RUN_TEST(check_example_debugging("load@diag"));
+ RUN_TEST(check_example_debugging("sudo_cb@info"));
+ RUN_TEST(check_example_debugging("c_calls@diag"));
+ RUN_TEST(check_example_debugging("c_calls@info"));
+ RUN_TEST(check_example_debugging("py_calls@diag"));
+ RUN_TEST(check_example_debugging("py_calls@info"));
+ RUN_TEST(check_example_debugging("plugin@err"));
+ RUN_TEST(check_plugin_unload());
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
diff --git a/plugins/python/regress/iohelpers.c b/plugins/python/regress/iohelpers.c
new file mode 100644
index 0000000..7b85814
--- /dev/null
+++ b/plugins/python/regress/iohelpers.c
@@ -0,0 +1,182 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include "iohelpers.h"
+#include <sudo_fatal.h>
+
+int
+rmdir_recursive(const char *path)
+{
+ char *cmd = NULL;
+ int success = false;
+
+ if (asprintf(&cmd, "rm -rf \"%s\"", path) < 0)
+ return false;
+
+ if (system(cmd) == 0)
+ success = true;
+
+ free(cmd);
+
+ return success;
+}
+
+int
+fwriteall(const char *file_path, const char *string)
+{
+ int success = false;
+
+ FILE *file = fopen(file_path, "w+");
+ if (file == NULL)
+ goto cleanup;
+
+ size_t size = strlen(string);
+ if (fwrite(string, 1, size, file) < size) {
+ goto cleanup;
+ }
+
+ success = true;
+
+cleanup:
+ if (file)
+ fclose(file);
+
+ return success;
+}
+
+int
+freadall(const char *file_path, char *output, size_t max_len)
+{
+ int rc = false;
+ FILE *file = fopen(file_path, "rb");
+ if (file == NULL) {
+ sudo_warn_nodebug("failed to open file '%s'", file_path);
+ goto cleanup;
+ }
+
+ size_t len = fread(output, 1, max_len - 1, file);
+ output[len] = '\0';
+
+ if (ferror(file) != 0) {
+ sudo_warn_nodebug("failed to read file '%s'", file_path);
+ goto cleanup;
+ }
+
+ if (!feof(file)) {
+ sudo_warn_nodebug("file '%s' was bigger than allocated buffer %zu",
+ file_path, max_len);
+ goto cleanup;
+ }
+
+ rc = true;
+
+cleanup:
+ if (file)
+ fclose(file);
+
+ return rc;
+}
+
+int
+vsnprintf_append(char * restrict output, size_t max_output_len, const char * restrict fmt, va_list args)
+{
+ va_list args2;
+ va_copy(args2, args);
+
+ size_t output_len = strlen(output);
+ int rc = vsnprintf(output + output_len, max_output_len - output_len, fmt, args2);
+
+ va_end(args2);
+ return rc;
+}
+
+int
+snprintf_append(char * restrict output, size_t max_output_len, const char * restrict fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ int rc = vsnprintf_append(output, max_output_len, fmt, args);
+ va_end(args);
+ return rc;
+}
+
+int
+str_array_count(char **str_array)
+{
+ int result = 0;
+ for (; str_array[result] != NULL; ++result) {}
+ return result;
+}
+
+void
+str_array_snprint(char *out_str, size_t max_len, char **str_array, int array_len)
+{
+ if (array_len < 0)
+ array_len = str_array_count(str_array);
+
+ for (int pos = 0; pos < array_len; ++pos) {
+ snprintf_append(out_str, max_len, "%s%s", pos > 0 ? ", " : "", str_array[pos]);
+ }
+}
+
+char *
+str_replaced(const char *source, size_t dest_len, const char *old, const char *new)
+{
+ char *result = malloc(dest_len);
+ char *dest = result;
+ char *pos = NULL;
+ size_t old_len = strlen(old);
+
+ if (result == NULL)
+ return NULL;
+
+ while ((pos = strstr(source, old)) != NULL) {
+ size_t len = (size_t)snprintf(dest, dest_len,
+ "%.*s%s", (int)(pos - source), source, new);
+ if (len >= dest_len)
+ goto fail;
+
+ dest_len -= len;
+ dest += len;
+ source = pos + old_len;
+ }
+
+ if (strlcpy(dest, source, dest_len) >= dest_len)
+ goto fail;
+
+ return result;
+
+fail:
+ free(result);
+ return strdup("str_replace_all failed, string too long");
+}
+
+void
+str_replace_in_place(char *string, size_t max_length, const char *old, const char *new)
+{
+ char *replaced = str_replaced(string, max_length, old, new);
+ if (replaced != NULL) {
+ strlcpy(string, replaced, max_length);
+ free(replaced);
+ }
+}
diff --git a/plugins/python/regress/iohelpers.h b/plugins/python/regress/iohelpers.h
new file mode 100644
index 0000000..b0fc5ab
--- /dev/null
+++ b/plugins/python/regress/iohelpers.h
@@ -0,0 +1,58 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef PYTHON_IO_HELPERS
+#define PYTHON_IO_HELPERS
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <pwd.h>
+
+#include <sudo_compat.h>
+
+#define MAX_OUTPUT (2 << 16)
+
+int rmdir_recursive(const char *path);
+
+int fwriteall(const char *file_path, const char *string);
+int freadall(const char *file_path, char *output, size_t max_len);
+
+// allocates new string with the content of 'string' but 'old' replaced to 'new'
+// The allocated array will be dest_length size and null terminated correctly.
+char *str_replaced(const char *string, size_t dest_length, const char *old, const char *new);
+
+// same, but "string" must be able to store 'max_length' number of characters including the null terminator
+void str_replace_in_place(char *string, size_t max_length, const char *old, const char *new);
+
+int vsnprintf_append(char * restrict output, size_t max_output_len, const char * restrict fmt, va_list args);
+int snprintf_append(char * restrict output, size_t max_output_len, const char * restrict fmt, ...);
+
+int str_array_count(char **str_array);
+void str_array_snprint(char *out_str, size_t max_len, char **str_array, int array_len);
+
+#endif
diff --git a/plugins/python/regress/plugin_approval_test.py b/plugins/python/regress/plugin_approval_test.py
new file mode 100644
index 0000000..69ea668
--- /dev/null
+++ b/plugins/python/regress/plugin_approval_test.py
@@ -0,0 +1,22 @@
+import sudo
+import json
+
+
+class ApprovalTestPlugin(sudo.Plugin):
+ def __init__(self, plugin_options, **kwargs):
+ id = sudo.options_as_dict(plugin_options).get("Id", "")
+ super().__init__(plugin_options=plugin_options, **kwargs)
+ self._id = "(APPROVAL {})".format(id)
+ sudo.log_info("{} Constructed:".format(self._id))
+ sudo.log_info(json.dumps(self.__dict__, indent=4, sort_keys=True))
+
+ def __del__(self):
+ sudo.log_info("{} Destructed successfully".format(self._id))
+
+ def check(self, *args):
+ sudo.log_info("{} Check was called with arguments: "
+ "{}".format(self._id, args))
+
+ def show_version(self, *args):
+ sudo.log_info("{} Show version was called with arguments: "
+ "{}".format(self._id, args))
diff --git a/plugins/python/regress/plugin_conflict.py b/plugins/python/regress/plugin_conflict.py
new file mode 100644
index 0000000..3632193
--- /dev/null
+++ b/plugins/python/regress/plugin_conflict.py
@@ -0,0 +1,11 @@
+import sudo
+
+import sys
+
+sys.path = []
+
+class ConflictPlugin(sudo.Plugin):
+ def __init__(self, plugin_options, **kwargs):
+ sudo.log_info("PATH before: {} (should be empty)".format(sys.path))
+ sys.path = [sudo.options_as_dict(plugin_options).get("Path")]
+ sudo.log_info("PATH set: {}".format(sys.path))
diff --git a/plugins/python/regress/plugin_errorstr.py b/plugins/python/regress/plugin_errorstr.py
new file mode 100644
index 0000000..fcbd71d
--- /dev/null
+++ b/plugins/python/regress/plugin_errorstr.py
@@ -0,0 +1,18 @@
+import sudo
+
+
+# The purpose of this class is that all methods you call on its object
+# raises a PluginError with a message containing the name of the called method.
+# Eg. if you call "ErrorMsgPlugin().some_method()" it will raise
+# "Something wrong in some_method"
+class ErrorMsgPlugin(sudo.Plugin):
+ def __getattr__(self, name):
+ def raiser_func(*args):
+ raise sudo.PluginError("Something wrong in " + name)
+
+ return raiser_func
+
+
+class ConstructErrorPlugin(sudo.Plugin):
+ def __init__(self, **kwargs):
+ raise sudo.PluginError("Something wrong in plugin constructor")
diff --git a/plugins/python/regress/testdata/check_example_audit_plugin_receives_accept.stdout b/plugins/python/regress/testdata/check_example_audit_plugin_receives_accept.stdout
new file mode 100644
index 0000000..352f421
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_audit_plugin_receives_accept.stdout
@@ -0,0 +1,7 @@
+(AUDIT) -- Started by user testuser1 (123) --
+(AUDIT) Requested command: id --help
+(AUDIT) Accepted command: /sbin/id --help
+(AUDIT) By the plugin: accepter plugin name (type=POLICY)
+(AUDIT) Environment: KEY1=VALUE1 KEY2=VALUE2
+(AUDIT) Command returned with exit code 2
+(AUDIT) -- Finished --
diff --git a/plugins/python/regress/testdata/check_example_audit_plugin_receives_error.stdout b/plugins/python/regress/testdata/check_example_audit_plugin_receives_error.stdout
new file mode 100644
index 0000000..d569291
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_audit_plugin_receives_error.stdout
@@ -0,0 +1,5 @@
+(AUDIT) -- Started by user ??? (???) --
+(AUDIT) Requested command: id
+(AUDIT) Plugin errorer plugin name (type=AUDIT) got an error: Some error has happened
+(AUDIT) Sudo has run into an error: 222
+(AUDIT) -- Finished --
diff --git a/plugins/python/regress/testdata/check_example_audit_plugin_receives_reject.stdout b/plugins/python/regress/testdata/check_example_audit_plugin_receives_reject.stdout
new file mode 100644
index 0000000..574b058
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_audit_plugin_receives_reject.stdout
@@ -0,0 +1,5 @@
+(AUDIT) -- Started by user root (0) --
+(AUDIT) Requested command: passwd
+(AUDIT) Rejected by plugin rejecter plugin name (type=IO): Rejected just because!
+(AUDIT) The command was not executed
+(AUDIT) -- Finished --
diff --git a/plugins/python/regress/testdata/check_example_audit_plugin_version_display.stdout b/plugins/python/regress/testdata/check_example_audit_plugin_version_display.stdout
new file mode 100644
index 0000000..9c0ba9e
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_audit_plugin_version_display.stdout
@@ -0,0 +1,6 @@
+(AUDIT) -- Started by user root (0) --
+Python Example Audit Plugin
+Python audit plugin (API 1.0): SudoAuditPlugin (loaded from 'SRC_DIR/example_audit_plugin.py')
+Python Example Audit Plugin (version=1.0)
+(AUDIT) Sudo has run into an error: 222
+(AUDIT) -- Finished --
diff --git a/plugins/python/regress/testdata/check_example_audit_plugin_workflow_multiple.stderr b/plugins/python/regress/testdata/check_example_audit_plugin_workflow_multiple.stderr
new file mode 100644
index 0000000..1d7d4a1
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_audit_plugin_workflow_multiple.stderr
@@ -0,0 +1 @@
+sudo: loading more than 8 sudo python audit plugins is not supported
diff --git a/plugins/python/regress/testdata/check_example_audit_plugin_workflow_multiple.stdout b/plugins/python/regress/testdata/check_example_audit_plugin_workflow_multiple.stdout
new file mode 100644
index 0000000..b80c5e6
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_audit_plugin_workflow_multiple.stdout
@@ -0,0 +1,14 @@
+(AUDIT1) -- Started by user default (1000) --
+(AUDIT1) Requested command: id --help
+(AUDIT2) -- Started by user default (1000) --
+(AUDIT2) Requested command: id --help
+(AUDIT1) Accepted command: /sbin/id --help
+(AUDIT1) By the plugin: accepter plugin name (type=POLICY)
+(AUDIT1) Environment: KEY1=VALUE1 KEY2=VALUE2
+(AUDIT2) Accepted command: /sbin/id --help
+(AUDIT2) By the plugin: accepter plugin name (type=POLICY)
+(AUDIT2) Environment: KEY1=VALUE1 KEY2=VALUE2
+(AUDIT1) Command exited due to signal 11
+(AUDIT1) -- Finished --
+(AUDIT2) Command exited due to signal 11
+(AUDIT2) -- Finished --
diff --git a/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.conversation b/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.conversation
new file mode 100644
index 0000000..43bd2e7
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.conversation
@@ -0,0 +1,3 @@
+Question count: 2
+Question 0: <<Reason: >> (timeout: 120, msg_type=2)
+Question 1: <<Secret reason: >> (timeout: 120, msg_type=5)
diff --git a/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.stderr b/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.stderr
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.stderr
diff --git a/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.stdout b/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.stdout
new file mode 100644
index 0000000..9d515c9
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.stdout
@@ -0,0 +1,3 @@
+Please provide your reason for executing ('/bin/whoami',)
+conversation suspend: signal SIGTSTP
+conversation resume: signal was SIGCONT
diff --git a/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.stored b/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.stored
new file mode 100644
index 0000000..c0ab857
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_with_suspend.stored
@@ -0,0 +1,3 @@
+Executed /bin/whoami
+Reason: my fake reason
+Hidden reason: my real secret reason
diff --git a/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.conversation b/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.conversation
new file mode 100644
index 0000000..43bd2e7
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.conversation
@@ -0,0 +1,3 @@
+Question count: 2
+Question 0: <<Reason: >> (timeout: 120, msg_type=2)
+Question 1: <<Secret reason: >> (timeout: 120, msg_type=5)
diff --git a/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.stderr b/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.stderr
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.stderr
diff --git a/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.stdout b/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.stdout
new file mode 100644
index 0000000..7bbfa3f
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.stdout
@@ -0,0 +1 @@
+Please provide your reason for executing ('/bin/whoami',)
diff --git a/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.stored b/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.stored
new file mode 100644
index 0000000..c0ab857
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_conversation_plugin_reason_log_without_suspend.stored
@@ -0,0 +1,3 @@
+Executed /bin/whoami
+Reason: my fake reason
+Hidden reason: my real secret reason
diff --git a/plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.conv b/plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.conv
new file mode 100644
index 0000000..59d7202
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.conv
@@ -0,0 +1,2 @@
+Question count: 2
+Question 0: <<Reason: >> (timeout: 120, msg_type=2)
diff --git a/plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.conversation b/plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.conversation
new file mode 100644
index 0000000..59d7202
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.conversation
@@ -0,0 +1,2 @@
+Question count: 2
+Question 0: <<Reason: >> (timeout: 120, msg_type=2)
diff --git a/plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.stderr b/plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.stderr
new file mode 100644
index 0000000..8a4a528
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.stderr
@@ -0,0 +1 @@
+You did not answer in time
diff --git a/plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.stdout b/plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.stdout
new file mode 100644
index 0000000..7bbfa3f
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_conversation_plugin_user_interrupts.stdout
@@ -0,0 +1 @@
+Please provide your reason for executing ('/bin/whoami',)
diff --git a/plugins/python/regress/testdata/check_example_debugging_c_calls@diag.log b/plugins/python/regress/testdata/check_example_debugging_c_calls@diag.log
new file mode 100644
index 0000000..1a73a59
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_debugging_c_calls@diag.log
@@ -0,0 +1,6 @@
+sudo.debug was called with arguments: (DEBUG.ERROR, 'My demo purpose plugin shows this ERROR level debug message')
+sudo.debug was called with arguments: (DEBUG.INFO, 'My demo purpose plugin shows this INFO level debug message')
+LogHandler.emit was called
+LogHandler.emit was called
+sudo.options_as_dict was called with arguments: (('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin'),)
+sudo.options_as_dict returned result: [('ClassName', 'DebugDemoPlugin'), ('ModulePath', 'SRC_DIR/example_debugging.py')]
diff --git a/plugins/python/regress/testdata/check_example_debugging_c_calls@info.log b/plugins/python/regress/testdata/check_example_debugging_c_calls@info.log
new file mode 100644
index 0000000..b7bbe76
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_debugging_c_calls@info.log
@@ -0,0 +1,11 @@
+__init__ @ SRC_DIR/example_debugging.py:58 calls C function:
+sudo.debug was called with arguments: (DEBUG.ERROR, 'My demo purpose plugin shows this ERROR level debug message')
+__init__ @ SRC_DIR/example_debugging.py:63 calls C function:
+sudo.debug was called with arguments: (DEBUG.INFO, 'My demo purpose plugin shows this INFO level debug message')
+handle @ logging/__init__.py calls C function:
+LogHandler.emit was called
+handle @ logging/__init__.py calls C function:
+LogHandler.emit was called
+__init__ @ SRC_DIR/example_debugging.py:85 calls C function:
+sudo.options_as_dict was called with arguments: (('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin'),)
+sudo.options_as_dict returned result: [('ClassName', 'DebugDemoPlugin'), ('ModulePath', 'SRC_DIR/example_debugging.py')]
diff --git a/plugins/python/regress/testdata/check_example_debugging_load@diag.log b/plugins/python/regress/testdata/check_example_debugging_load@diag.log
new file mode 100644
index 0000000..15b4bbe
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_debugging_load@diag.log
@@ -0,0 +1,3 @@
+importing module: SRC_DIR/example_debugging.py
+Extending python 'path' with 'SRC_DIR'
+Deinit was called for a python plugin
diff --git a/plugins/python/regress/testdata/check_example_debugging_plugin@err.log b/plugins/python/regress/testdata/check_example_debugging_plugin@err.log
new file mode 100644
index 0000000..aec31ec
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_debugging_plugin@err.log
@@ -0,0 +1,2 @@
+My demo purpose plugin shows this ERROR level debug message
+Python log system shows this ERROR level debug message
diff --git a/plugins/python/regress/testdata/check_example_debugging_plugin@info.log b/plugins/python/regress/testdata/check_example_debugging_plugin@info.log
new file mode 100644
index 0000000..ed72f35
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_debugging_plugin@info.log
@@ -0,0 +1,8 @@
+__init__ @ SRC_DIR/example_debugging.py:58 debugs:
+My demo purpose plugin shows this ERROR level debug message
+__init__ @ SRC_DIR/example_debugging.py:63 debugs:
+My demo purpose plugin shows this INFO level debug message
+handle @ logging/__init__.py debugs:
+Python log system shows this ERROR level debug message
+handle @ logging/__init__.py debugs:
+Python log system shows this INFO level debug message
diff --git a/plugins/python/regress/testdata/check_example_debugging_py_calls@diag.log b/plugins/python/regress/testdata/check_example_debugging_py_calls@diag.log
new file mode 100644
index 0000000..97a89ef
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_debugging_py_calls@diag.log
@@ -0,0 +1,2 @@
+DebugDemoPlugin.__init__ was called with arguments: () [('plugin_options', ('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin')), ('settings', ('debug_flags=/tmp/sudo_check_python_exampleXXXXXX/debug.log py_calls@diag', 'plugin_path=python_plugin.so')), ('user_env', ()), ('user_info', ()), ('version', '1.0')]
+DebugDemoPlugin.__init__ returned result: <example_debugging.DebugDemoPlugin object>
diff --git a/plugins/python/regress/testdata/check_example_debugging_py_calls@info.log b/plugins/python/regress/testdata/check_example_debugging_py_calls@info.log
new file mode 100644
index 0000000..ae39daf
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_debugging_py_calls@info.log
@@ -0,0 +1,9 @@
+DebugDemoPlugin.__init__ was called with arguments: () [('plugin_options', ('ModulePath=SRC_DIR/example_debugging.py', 'ClassName=DebugDemoPlugin')), ('settings', ('debug_flags=/tmp/sudo_check_python_exampleXXXXXX/debug.log py_calls@info', 'plugin_path=python_plugin.so')), ('user_env', ()), ('user_info', ()), ('version', '1.0')]
+DebugDemoPlugin.__init__ returned result: <example_debugging.DebugDemoPlugin object>
+DebugDemoPlugin function 'log_ttyin' is not implemented
+DebugDemoPlugin function 'log_ttyout' is not implemented
+DebugDemoPlugin function 'log_stdin' is not implemented
+DebugDemoPlugin function 'log_stdout' is not implemented
+DebugDemoPlugin function 'log_stderr' is not implemented
+DebugDemoPlugin function 'change_winsize' is not implemented
+DebugDemoPlugin function 'log_suspend' is not implemented
diff --git a/plugins/python/regress/testdata/check_example_debugging_sudo_cb@info.log b/plugins/python/regress/testdata/check_example_debugging_sudo_cb@info.log
new file mode 100644
index 0000000..908066b
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_debugging_sudo_cb@info.log
@@ -0,0 +1 @@
+Skipping close call, because there was no command run
diff --git a/plugins/python/regress/testdata/check_example_group_plugin_is_able_to_debug.log b/plugins/python/regress/testdata/check_example_group_plugin_is_able_to_debug.log
new file mode 100644
index 0000000..b25007a
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_group_plugin_is_able_to_debug.log
@@ -0,0 +1,4 @@
+SudoGroupPlugin.__init__ was called with arguments: () [('args', ('ModulePath=SRC_DIR/example_group_plugin.py', 'ClassName=SudoGroupPlugin')), ('version', '1.0')]
+SudoGroupPlugin.__init__ returned result: <example_group_plugin.SudoGroupPlugin object>
+SudoGroupPlugin.query was called with arguments: ('user', 'group', ('pw_name', 'pw_passwd', 1001, 101, 'pw_gecos', 'pw_dir', 'pw_shell'))
+SudoGroupPlugin.query returned result: 0
diff --git a/plugins/python/regress/testdata/check_example_io_plugin_command_log.stderr b/plugins/python/regress/testdata/check_example_io_plugin_command_log.stderr
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_io_plugin_command_log.stderr
diff --git a/plugins/python/regress/testdata/check_example_io_plugin_command_log.stdout b/plugins/python/regress/testdata/check_example_io_plugin_command_log.stdout
new file mode 100644
index 0000000..7e94c91
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_io_plugin_command_log.stdout
@@ -0,0 +1 @@
+Example sudo python plugin will log to /tmp/sudo_check_python_exampleXXXXXX/sudo.log
diff --git a/plugins/python/regress/testdata/check_example_io_plugin_command_log.stored b/plugins/python/regress/testdata/check_example_io_plugin_command_log.stored
new file mode 100644
index 0000000..73fdc5d
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_io_plugin_command_log.stored
@@ -0,0 +1,16 @@
+ -- Plugin STARTED --
+EXEC id --help
+EXEC info [
+ "command=/bin/id",
+ "runas_uid=0"
+]
+STD IN some standard input
+STD OUT some standard output
+STD ERR some standard error
+SUSPEND SIGTSTP
+SUSPEND SIGCONT
+WINSIZE 200x100
+TTY IN some tty input
+TTY OUT some tty output
+CLOSE Command returned 1
+ -- Plugin DESTROYED --
diff --git a/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stderr b/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stderr
new file mode 100644
index 0000000..f519805
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stderr
@@ -0,0 +1 @@
+sudo: loading more than 8 sudo python IO plugins is not supported
diff --git a/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stdout b/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stdout
new file mode 100644
index 0000000..e9dbd67
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple.stdout
@@ -0,0 +1,2 @@
+Example sudo python plugin will log to /tmp/sudo_check_python_exampleXXXXXX/sudo.log
+Example sudo python plugin will log to /tmp/sudo_check_python_exampleXXXXXX2/sudo.log
diff --git a/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple1.stored b/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple1.stored
new file mode 100644
index 0000000..bc60c38
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple1.stored
@@ -0,0 +1,16 @@
+ -- Plugin STARTED --
+EXEC id --help
+EXEC info [
+ "command=/bin/id",
+ "runas_uid=0"
+]
+STD IN stdin for plugin 1
+STD OUT stdout for plugin 1
+STD ERR stderr for plugin 1
+SUSPEND SIGTSTP
+SUSPEND SIGCONT
+WINSIZE 20x10
+TTY IN tty input for plugin 1
+TTY OUT tty output for plugin 1
+CLOSE Command returned 1
+ -- Plugin DESTROYED --
diff --git a/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple2.stored b/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple2.stored
new file mode 100644
index 0000000..ed3fdc8
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_io_plugin_command_log_multiple2.stored
@@ -0,0 +1,16 @@
+ -- Plugin STARTED --
+EXEC whoami
+EXEC info [
+ "command=/bin/whoami",
+ "runas_uid=1"
+]
+STD IN stdin for plugin 2
+STD OUT stdout for plugin 2
+STD ERR stderr for plugin 2
+SUSPEND SIGSTOP
+SUSPEND SIGCONT
+WINSIZE 30x40
+TTY IN tty input for plugin 2
+TTY OUT tty output for plugin 2
+CLOSE Command returned 2
+ -- Plugin DESTROYED --
diff --git a/plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stderr b/plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stderr
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stderr
diff --git a/plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stdout b/plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stdout
new file mode 100644
index 0000000..7e94c91
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stdout
@@ -0,0 +1 @@
+Example sudo python plugin will log to /tmp/sudo_check_python_exampleXXXXXX/sudo.log
diff --git a/plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stored b/plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stored
new file mode 100644
index 0000000..1b99398
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_io_plugin_failed_to_start_command.stored
@@ -0,0 +1,8 @@
+ -- Plugin STARTED --
+EXEC cmd
+EXEC info [
+ "command=/usr/share/cmd",
+ "runas_uid=0"
+]
+CLOSE Failed to execute, execve returned 1 (EPERM)
+ -- Plugin DESTROYED --
diff --git a/plugins/python/regress/testdata/check_example_io_plugin_fails_with_python_backtrace.stderr b/plugins/python/regress/testdata/check_example_io_plugin_fails_with_python_backtrace.stderr
new file mode 100644
index 0000000..1dd42a6
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_io_plugin_fails_with_python_backtrace.stderr
@@ -0,0 +1 @@
+Failed to construct plugin instance: [Errno 2] No such file or directory: '/some/not/writable/directory/sudo.log'
diff --git a/plugins/python/regress/testdata/check_example_io_plugin_fails_with_python_backtrace.stdout b/plugins/python/regress/testdata/check_example_io_plugin_fails_with_python_backtrace.stdout
new file mode 100644
index 0000000..10b0e23
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_io_plugin_fails_with_python_backtrace.stdout
@@ -0,0 +1,7 @@
+Example sudo python plugin will log to /some/not/writable/directory/sudo.log
+Traceback:
+ File "SRC_DIR/example_io_plugin.py", line 64, in __init__
+ self._open_log_file(path.join(log_path, "sudo.log"))
+ File "SRC_DIR/example_io_plugin.py", line 134, in _open_log_file
+ self._log_file = open(log_path, "a")
+
diff --git a/plugins/python/regress/testdata/check_example_io_plugin_version_display.stderr b/plugins/python/regress/testdata/check_example_io_plugin_version_display.stderr
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_io_plugin_version_display.stderr
diff --git a/plugins/python/regress/testdata/check_example_io_plugin_version_display.stdout b/plugins/python/regress/testdata/check_example_io_plugin_version_display.stdout
new file mode 100644
index 0000000..07e998a
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_io_plugin_version_display.stdout
@@ -0,0 +1,2 @@
+Example sudo python plugin will log to /tmp/sudo_check_python_exampleXXXXXX/sudo.log
+Python Example IO Plugin version: 1.0
diff --git a/plugins/python/regress/testdata/check_example_io_plugin_version_display.stored b/plugins/python/regress/testdata/check_example_io_plugin_version_display.stored
new file mode 100644
index 0000000..45f9b9e
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_io_plugin_version_display.stored
@@ -0,0 +1,2 @@
+ -- Plugin STARTED --
+ -- Plugin DESTROYED --
diff --git a/plugins/python/regress/testdata/check_example_io_plugin_version_display_full.stdout b/plugins/python/regress/testdata/check_example_io_plugin_version_display_full.stdout
new file mode 100644
index 0000000..cfb3921
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_io_plugin_version_display_full.stdout
@@ -0,0 +1,3 @@
+Example sudo python plugin will log to /tmp/sudo_check_python_exampleXXXXXX/sudo.log
+Python io plugin (API 1.0): SudoIOPlugin (loaded from 'SRC_DIR/example_io_plugin.py')
+Python Example IO Plugin version: 1.0
diff --git a/plugins/python/regress/testdata/check_example_policy_plugin_accepted_execution.stderr b/plugins/python/regress/testdata/check_example_policy_plugin_accepted_execution.stderr
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_policy_plugin_accepted_execution.stderr
diff --git a/plugins/python/regress/testdata/check_example_policy_plugin_accepted_execution.stdout b/plugins/python/regress/testdata/check_example_policy_plugin_accepted_execution.stdout
new file mode 100644
index 0000000..c63a26e
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_policy_plugin_accepted_execution.stdout
@@ -0,0 +1 @@
+The command returned with exit_status 3
diff --git a/plugins/python/regress/testdata/check_example_policy_plugin_denied_execution.stderr b/plugins/python/regress/testdata/check_example_policy_plugin_denied_execution.stderr
new file mode 100644
index 0000000..6db9b2c
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_policy_plugin_denied_execution.stderr
@@ -0,0 +1 @@
+You are not allowed to run this command!
diff --git a/plugins/python/regress/testdata/check_example_policy_plugin_denied_execution.stdout b/plugins/python/regress/testdata/check_example_policy_plugin_denied_execution.stdout
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_policy_plugin_denied_execution.stdout
diff --git a/plugins/python/regress/testdata/check_example_policy_plugin_failed_execution.stderr b/plugins/python/regress/testdata/check_example_policy_plugin_failed_execution.stderr
new file mode 100644
index 0000000..e8d7034
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_policy_plugin_failed_execution.stderr
@@ -0,0 +1 @@
+Failed to execute command, execve syscall returned 2 (ENOENT)
diff --git a/plugins/python/regress/testdata/check_example_policy_plugin_failed_execution.stdout b/plugins/python/regress/testdata/check_example_policy_plugin_failed_execution.stdout
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_policy_plugin_failed_execution.stdout
diff --git a/plugins/python/regress/testdata/check_example_policy_plugin_list.stderr b/plugins/python/regress/testdata/check_example_policy_plugin_list.stderr
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_policy_plugin_list.stderr
diff --git a/plugins/python/regress/testdata/check_example_policy_plugin_list.stdout b/plugins/python/regress/testdata/check_example_policy_plugin_list.stdout
new file mode 100644
index 0000000..48c5baf
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_policy_plugin_list.stdout
@@ -0,0 +1,25 @@
+-- minimal --
+Only the following commands are allowed: id, whoami
+
+-- minimal (verbose) --
+Only the following commands are allowed: id, whoami
+
+-- with user --
+Only the following commands are allowed: id, whoami as user 'testuser'
+
+-- with user (verbose) --
+Only the following commands are allowed: id, whoami as user 'testuser'
+
+-- with allowed program --
+You are allowed to execute command '/bin/id'
+
+-- with allowed program (verbose) --
+You are allowed to execute command '/bin/id'
+Only the following commands are allowed: id, whoami
+
+-- with denied program --
+You are NOT allowed to execute command '/bin/passwd'
+
+-- with denied program (verbose) --
+You are NOT allowed to execute command '/bin/passwd'
+Only the following commands are allowed: id, whoami
diff --git a/plugins/python/regress/testdata/check_example_policy_plugin_validate_invalidate.log b/plugins/python/regress/testdata/check_example_policy_plugin_validate_invalidate.log
new file mode 100644
index 0000000..db4ac27
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_policy_plugin_validate_invalidate.log
@@ -0,0 +1,8 @@
+SudoPolicyPlugin.__init__ was called with arguments: () [('plugin_options', ('ModulePath=SRC_DIR/example_policy_plugin.py', 'ClassName=SudoPolicyPlugin')), ('settings', ()), ('user_env', ()), ('user_info', ()), ('version', '1.0')]
+SudoPolicyPlugin.__init__ returned result: <example_policy_plugin.SudoPolicyPlugin object>
+SudoPolicyPlugin.validate was called with arguments: ()
+SudoPolicyPlugin.validate returned result: None
+SudoPolicyPlugin.invalidate was called with arguments: (1,)
+SudoPolicyPlugin.invalidate returned result: None
+SudoPolicyPlugin.invalidate was called with arguments: (0,)
+SudoPolicyPlugin.invalidate returned result: None
diff --git a/plugins/python/regress/testdata/check_example_policy_plugin_version_display.stderr b/plugins/python/regress/testdata/check_example_policy_plugin_version_display.stderr
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_policy_plugin_version_display.stderr
diff --git a/plugins/python/regress/testdata/check_example_policy_plugin_version_display.stdout b/plugins/python/regress/testdata/check_example_policy_plugin_version_display.stdout
new file mode 100644
index 0000000..1cc1edd
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_policy_plugin_version_display.stdout
@@ -0,0 +1 @@
+Python Example Policy Plugin version: 1.0
diff --git a/plugins/python/regress/testdata/check_example_policy_plugin_version_display_full.stdout b/plugins/python/regress/testdata/check_example_policy_plugin_version_display_full.stdout
new file mode 100644
index 0000000..a23cf12
--- /dev/null
+++ b/plugins/python/regress/testdata/check_example_policy_plugin_version_display_full.stdout
@@ -0,0 +1,2 @@
+Python policy plugin (API 1.0): SudoPolicyPlugin (loaded from 'SRC_DIR/example_policy_plugin.py')
+Python Example Policy Plugin version: 1.0
diff --git a/plugins/python/regress/testdata/check_loading_fails_missing_classname.stderr b/plugins/python/regress/testdata/check_loading_fails_missing_classname.stderr
new file mode 100644
index 0000000..c207e2f
--- /dev/null
+++ b/plugins/python/regress/testdata/check_loading_fails_missing_classname.stderr
@@ -0,0 +1,3 @@
+No plugin class is specified for python module 'SRC_DIR/regress/plugin_errorstr.py'. Use 'ClassName' configuration option in 'sudo.conf'
+Possible plugins: ConstructErrorPlugin, ErrorMsgPlugin
+Failed during loading plugin class
diff --git a/plugins/python/regress/testdata/check_loading_fails_missing_classname.stdout b/plugins/python/regress/testdata/check_loading_fails_missing_classname.stdout
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/python/regress/testdata/check_loading_fails_missing_classname.stdout
diff --git a/plugins/python/regress/testdata/check_loading_fails_missing_path.stderr b/plugins/python/regress/testdata/check_loading_fails_missing_path.stderr
new file mode 100644
index 0000000..05bc634
--- /dev/null
+++ b/plugins/python/regress/testdata/check_loading_fails_missing_path.stderr
@@ -0,0 +1,2 @@
+No python module path is specified. Use 'ModulePath' plugin config option in 'sudo.conf'
+Failed during loading plugin class
diff --git a/plugins/python/regress/testdata/check_loading_fails_missing_path.stdout b/plugins/python/regress/testdata/check_loading_fails_missing_path.stdout
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/python/regress/testdata/check_loading_fails_missing_path.stdout
diff --git a/plugins/python/regress/testdata/check_loading_fails_not_owned_by_root.stderr b/plugins/python/regress/testdata/check_loading_fails_not_owned_by_root.stderr
new file mode 100644
index 0000000..7ba1bc9
--- /dev/null
+++ b/plugins/python/regress/testdata/check_loading_fails_not_owned_by_root.stderr
@@ -0,0 +1 @@
+Failed during loading plugin class: File 'SRC_DIR/example_debugging.py' must be owned by uid 0
diff --git a/plugins/python/regress/testdata/check_loading_fails_not_owned_by_root.stdout b/plugins/python/regress/testdata/check_loading_fails_not_owned_by_root.stdout
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/python/regress/testdata/check_loading_fails_not_owned_by_root.stdout
diff --git a/plugins/python/regress/testdata/check_loading_fails_wrong_classname.stderr b/plugins/python/regress/testdata/check_loading_fails_wrong_classname.stderr
new file mode 100644
index 0000000..a4c519a
--- /dev/null
+++ b/plugins/python/regress/testdata/check_loading_fails_wrong_classname.stderr
@@ -0,0 +1,2 @@
+Failed to find plugin class 'MispelledPluginName'
+Failed during loading plugin class
diff --git a/plugins/python/regress/testdata/check_loading_fails_wrong_classname.stdout b/plugins/python/regress/testdata/check_loading_fails_wrong_classname.stdout
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/python/regress/testdata/check_loading_fails_wrong_classname.stdout
diff --git a/plugins/python/regress/testdata/check_loading_fails_wrong_path.stderr b/plugins/python/regress/testdata/check_loading_fails_wrong_path.stderr
new file mode 100644
index 0000000..3087ba8
--- /dev/null
+++ b/plugins/python/regress/testdata/check_loading_fails_wrong_path.stderr
@@ -0,0 +1 @@
+Failed during loading plugin class: No module named 'wrong_path'
diff --git a/plugins/python/regress/testdata/check_loading_fails_wrong_path.stdout b/plugins/python/regress/testdata/check_loading_fails_wrong_path.stdout
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/python/regress/testdata/check_loading_fails_wrong_path.stdout
diff --git a/plugins/python/regress/testdata/check_loading_succeeds_with_missing_classname.stdout b/plugins/python/regress/testdata/check_loading_succeeds_with_missing_classname.stdout
new file mode 100644
index 0000000..f7a1a6f
--- /dev/null
+++ b/plugins/python/regress/testdata/check_loading_succeeds_with_missing_classname.stdout
@@ -0,0 +1 @@
+Python io plugin (API 1.0): DebugDemoPlugin (loaded from 'SRC_DIR/example_debugging.py')
diff --git a/plugins/python/regress/testdata/check_multiple_approval_plugin_and_arguments.stderr b/plugins/python/regress/testdata/check_multiple_approval_plugin_and_arguments.stderr
new file mode 100644
index 0000000..6dfb141
--- /dev/null
+++ b/plugins/python/regress/testdata/check_multiple_approval_plugin_and_arguments.stderr
@@ -0,0 +1 @@
+sudo: loading more than 8 sudo python approval plugins is not supported
diff --git a/plugins/python/regress/testdata/check_multiple_approval_plugin_and_arguments.stdout b/plugins/python/regress/testdata/check_multiple_approval_plugin_and_arguments.stdout
new file mode 100644
index 0000000..2589025
--- /dev/null
+++ b/plugins/python/regress/testdata/check_multiple_approval_plugin_and_arguments.stdout
@@ -0,0 +1,67 @@
+(APPROVAL 1) Constructed:
+{
+ "_id": "(APPROVAL 1)",
+ "plugin_options": [
+ "ModulePath=SRC_DIR/regress/plugin_approval_test.py",
+ "ClassName=ApprovalTestPlugin",
+ "Id=1"
+ ],
+ "settings": [
+ "SETTING1=VALUE1",
+ "setting2=value2"
+ ],
+ "submit_argv": [
+ "sudo",
+ "-u",
+ "user",
+ "whoami",
+ "--help"
+ ],
+ "submit_optind": 3,
+ "user_env": [
+ "USER_ENV1=VALUE1",
+ "USER_ENV2=value2"
+ ],
+ "user_info": [
+ "INFO1=VALUE1",
+ "info2=value2"
+ ],
+ "version": "1.21"
+}
+(APPROVAL 2) Constructed:
+{
+ "_id": "(APPROVAL 2)",
+ "plugin_options": [
+ "ModulePath=SRC_DIR/regress/plugin_approval_test.py",
+ "ClassName=ApprovalTestPlugin",
+ "Id=2"
+ ],
+ "settings": [
+ "SETTING1=VALUE1",
+ "setting2=value2"
+ ],
+ "submit_argv": [
+ "sudo",
+ "-u",
+ "user",
+ "whoami",
+ "--help"
+ ],
+ "submit_optind": 3,
+ "user_env": [
+ "USER_ENV1=VALUE1",
+ "USER_ENV2=value2"
+ ],
+ "user_info": [
+ "INFO1=VALUE1",
+ "info2=value2"
+ ],
+ "version": "1.21"
+}
+(APPROVAL 1) Show version was called with arguments: (0,)
+Python approval plugin (API 1.0): ApprovalTestPlugin (loaded from 'SRC_DIR/regress/plugin_approval_test.py')
+(APPROVAL 2) Show version was called with arguments: (1,)
+(APPROVAL 1) Check was called with arguments: (('CMDINFO1=value1', 'CMDINFO2=VALUE2'), ('whoami', '--help'), ('USER_ENV1=VALUE1', 'USER_ENV2=value2'))
+(APPROVAL 2) Check was called with arguments: (('CMDINFO1=value1', 'CMDINFO2=VALUE2'), ('whoami', '--help'), ('USER_ENV1=VALUE1', 'USER_ENV2=value2'))
+(APPROVAL 1) Destructed successfully
+(APPROVAL 2) Destructed successfully
diff --git a/plugins/python/regress/testdata/check_python_plugins_do_not_affect_each_other.stdout b/plugins/python/regress/testdata/check_python_plugins_do_not_affect_each_other.stdout
new file mode 100644
index 0000000..cd5bef9
--- /dev/null
+++ b/plugins/python/regress/testdata/check_python_plugins_do_not_affect_each_other.stdout
@@ -0,0 +1,4 @@
+PATH before: [] (should be empty)
+PATH set: ['path_for_first_plugin']
+PATH before: [] (should be empty)
+PATH set: ['path_for_second_plugin']
diff --git a/plugins/python/regress/testhelpers.c b/plugins/python/regress/testhelpers.c
new file mode 100644
index 0000000..ee55fb9
--- /dev/null
+++ b/plugins/python/regress/testhelpers.c
@@ -0,0 +1,356 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include "testhelpers.h"
+
+struct TestData data;
+
+/*
+ * Starting with Python 3.11, backtraces may contain a line with
+ * '^' characters to bring attention to the important part of the
+ * line.
+ */
+static void
+remove_underline(char *output)
+{
+ char *cp, *ep;
+
+ // Remove lines that only consist of '^' and white space.
+ cp = output;
+ ep = output + strlen(output);
+ for (;;) {
+ size_t len = strspn(cp, "^ \t");
+ if (len > 0 && cp[len] == '\n') {
+ /* Prune out lines that are "underlining". */
+ memmove(cp, cp + len + 1, (size_t)(ep - cp));
+ if (*cp == '\0')
+ break;
+ } else {
+ /* No match, move to the next line. */
+ cp = strchr(cp, '\n');
+ if (cp == NULL)
+ break;
+ cp++;
+ }
+ }
+}
+
+static void
+clean_output(char *output)
+{
+ // we replace some output which otherwise would be test run dependent
+ str_replace_in_place(output, MAX_OUTPUT, data.tmp_dir, TEMP_PATH_TEMPLATE);
+
+ if (data.tmp_dir2)
+ str_replace_in_place(output, MAX_OUTPUT, data.tmp_dir2, TEMP_PATH_TEMPLATE "2");
+
+ str_replace_in_place(output, MAX_OUTPUT, SRC_DIR, "SRC_DIR");
+
+ remove_underline(output);
+}
+
+const char *
+expected_path(const char *format, ...)
+{
+ static char expected_output_file[PATH_MAX];
+ size_t dirlen = strlcpy(expected_output_file, TESTDATA_DIR, sizeof(expected_output_file));
+
+ va_list args;
+ va_start(args, format);
+ vsnprintf(expected_output_file + dirlen, PATH_MAX - dirlen, format, args);
+ va_end(args);
+
+ return expected_output_file;
+}
+
+char **
+create_str_array(size_t count, ...)
+{
+ va_list args;
+
+ va_start(args, count);
+
+ char **result = calloc(count, sizeof(char *));
+ if (result != NULL) {
+ for (size_t i = 0; i < count; ++i) {
+ const char *str = va_arg(args, char *);
+ if (str != NULL) {
+ result[i] = strdup(str);
+ if (result[i] == NULL) {
+ while (i > 0) {
+ free(result[--i]);
+ }
+ free(result);
+ result = NULL;
+ break;
+ }
+ }
+ }
+ }
+
+ va_end(args);
+ return result;
+}
+
+int
+is_update(void)
+{
+ static int result = -1;
+ if (result < 0) {
+ const char *update = getenv("UPDATE_TESTDATA");
+ result = (update && strcmp(update, "1") == 0) ? 1 : 0;
+ }
+ return result;
+}
+
+int
+verify_content(char *actual_content, const char *reference_path)
+{
+ clean_output(actual_content);
+
+ if (is_update()) {
+ VERIFY_TRUE(fwriteall(reference_path, actual_content));
+ } else {
+ char expected_output[MAX_OUTPUT] = "";
+ if (!freadall(reference_path, expected_output, sizeof(expected_output))) {
+ printf("Error: Missing test data at '%s'\n", reference_path);
+ return false;
+ }
+ VERIFY_STR(actual_content, expected_output);
+ }
+
+ return true;
+}
+
+int
+verify_file(const char *actual_dir, const char *actual_file_name, const char *reference_path)
+{
+ char actual_path[PATH_MAX];
+ snprintf(actual_path, sizeof(actual_path), "%s/%s", actual_dir, actual_file_name);
+
+ char actual_str[MAX_OUTPUT];
+ if (!freadall(actual_path, actual_str, sizeof(actual_str))) {
+ printf("Expected that file '%s' gets created, but it was not\n", actual_path);
+ return false;
+ }
+
+ int rc = verify_content(actual_str, reference_path);
+ return rc;
+}
+
+int
+fake_conversation(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
+{
+ (void) callback;
+ snprintf_append(data.conv_str, MAX_OUTPUT, "Question count: %d\n", num_msgs);
+ for (int i = 0; i < num_msgs; ++i) {
+ const struct sudo_conv_message *msg = &msgs[i];
+ snprintf_append(data.conv_str, MAX_OUTPUT, "Question %d: <<%s>> (timeout: %d, msg_type=%d)\n",
+ i, msg->msg, msg->timeout, msg->msg_type);
+
+ if (data.conv_replies[i] == NULL)
+ return 1; // simulates user interruption (conversation error)
+
+ replies[i].reply = strdup(data.conv_replies[i]);
+ if (replies[i].reply == NULL)
+ return 1; // memory allocation error
+ }
+
+ return 0; // simulate user answered just fine
+}
+
+int
+fake_conversation_with_suspend(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
+{
+ if (callback != NULL) {
+ callback->on_suspend(SIGTSTP, callback->closure);
+ callback->on_resume(SIGCONT, callback->closure);
+ }
+
+ return fake_conversation(num_msgs, msgs, replies, callback);
+}
+
+int
+fake_printf(int msg_type, const char * restrict fmt, ...)
+{
+ int rc = -1;
+ va_list args;
+ va_start(args, fmt);
+
+ char *output = NULL;
+ switch(msg_type) {
+ case SUDO_CONV_INFO_MSG:
+ output = data.stdout_str;
+ break;
+ case SUDO_CONV_ERROR_MSG:
+ output = data.stderr_str;
+ break;
+ default:
+ break;
+ }
+
+ if (output)
+ rc = vsnprintf_append(output, MAX_OUTPUT, fmt, args);
+
+ va_end(args);
+ return rc;
+}
+
+int
+verify_log_lines(const char *reference_path)
+{
+ char stored_path[PATH_MAX];
+ snprintf(stored_path, sizeof(stored_path), "%s/%s", data.tmp_dir, "debug.log");
+
+ FILE *file = fopen(stored_path, "rb");
+ if (file == NULL) {
+ printf("Failed to open file '%s'\n", stored_path);
+ return false;
+ }
+
+ char line[1024] = "";
+ char stored_str[MAX_OUTPUT] = "";
+ while (fgets(line, sizeof(line), file) != NULL) {
+ char *line_data = strstr(line, "] "); // this skips the timestamp and pid at the beginning
+ VERIFY_NOT_NULL(line_data); // malformed log line
+ line_data += 2;
+
+ char *line_end = strstr(line_data, " object at "); // this skips checking the pointer hex
+ if (line_end) {
+ snprintf(line_end, sizeof(line) - (size_t)(line_end - line),
+ " object>\n");
+ }
+
+ if (strncmp(line_data, "handle @ /", sizeof("handle @ /") - 1) == 0) {
+ char *start = line_data + sizeof("handle @ ") - 1;
+
+ // normalize path to logging/__init__.py
+ char *logging = strstr(start, "logging/");
+ if (logging != NULL) {
+ memmove(start, logging, strlen(logging) + 1);
+ }
+
+ // remove line number
+ char *colon = strchr(start, ':');
+ if (colon != NULL) {
+ size_t len = strspn(colon + 1, "0123456789");
+ if (len != 0)
+ memmove(colon, colon + len + 1, strlen(colon + len + 1) + 1);
+ }
+ } else if (strncmp(line_data, "LogHandler.emit was called ", 27) == 0) {
+ // LogHandler.emit argument details vary based on python version
+ line_data[26] = '\n';
+ line_data[27] = '\0';
+ } else {
+ // Python 3.11 uses 0 instead of the symbolic REJECT in backtraces
+ char *cp = strstr(line_data, ": REJECT");
+ if (cp != NULL) {
+ // Convert ": REJECT" to ": 0" + rest of line
+ memcpy(cp, ": 0", 3);
+ memmove(cp + 3, cp + 8, strlen(cp + 8) + 1);
+ } else {
+ // Python 3.12 may use <RC.REJECT: 0> instead of 0
+ cp = strstr(line_data, "<RC.REJECT: 0>");
+ if (cp != NULL) {
+ *cp = '0';
+ memmove(cp + 1, cp + 14, strlen(cp + 14) + 1);
+ }
+ }
+
+ }
+
+ VERIFY_TRUE(strlcat(stored_str, line_data, sizeof(stored_str)) < sizeof(stored_str)); // we have enough space in buffer
+ }
+
+ clean_output(stored_str);
+
+ VERIFY_TRUE(verify_content(stored_str, reference_path));
+ return true;
+}
+
+int
+verify_str_set(char **actual_set, char **expected_set, const char *actual_variable_name)
+{
+ VERIFY_NOT_NULL(actual_set);
+ VERIFY_NOT_NULL(expected_set);
+
+ int actual_len = str_array_count(actual_set);
+ int expected_len = str_array_count(expected_set);
+
+ int matches = false;
+ if (actual_len == expected_len) {
+ int actual_pos = 0;
+ for (; actual_pos < actual_len; ++actual_pos) {
+ char *actual_item = actual_set[actual_pos];
+
+ int expected_pos = 0;
+ for (; expected_pos < expected_len; ++expected_pos) {
+ if (strcmp(actual_item, expected_set[expected_pos]) == 0)
+ break;
+ }
+
+ if (expected_pos == expected_len) {
+ // matching item was not found
+ break;
+ }
+ }
+
+ matches = (actual_pos == actual_len);
+ }
+
+ if (!matches) {
+ char actual_set_str[MAX_OUTPUT] = "";
+ char expected_set_str[MAX_OUTPUT] = "";
+ str_array_snprint(actual_set_str, MAX_OUTPUT, actual_set, actual_len);
+ str_array_snprint(expected_set_str, MAX_OUTPUT, expected_set, expected_len);
+
+ VERIFY_PRINT_MSG("%s", actual_variable_name, actual_set_str, "expected",
+ expected_set_str, "expected to contain the same elements as");
+ return false;
+ }
+
+ return true;
+}
+
+int
+mock_python_datetime_now(const char *plugin_name, const char *date_str)
+{
+ char *cmd = NULL;
+ int len;
+ len = asprintf(&cmd,
+ "import %s\n" // the plugin has its own submodule
+ "from datetime import datetime\n" // store the real datetime
+ "import time\n"
+ "from unittest.mock import Mock\n"
+ "%s.datetime = Mock()\n" // replace plugin's datetime
+ "%s.datetime.now = lambda: datetime.strptime('%s', '%%Y-%%m-%%dT%%H:%%M:%%S')\n",
+ plugin_name, plugin_name, plugin_name, date_str);
+ if (len == -1)
+ return false;
+ VERIFY_PTR_NE(cmd, NULL);
+ VERIFY_INT(PyRun_SimpleString(cmd), 0);
+ free(cmd);
+ return true;
+}
diff --git a/plugins/python/regress/testhelpers.h b/plugins/python/regress/testhelpers.h
new file mode 100644
index 0000000..8f78d9f
--- /dev/null
+++ b/plugins/python/regress/testhelpers.h
@@ -0,0 +1,175 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef PYTHON_TESTHELPERS
+#define PYTHON_TESTHELPERS
+
+#include "iohelpers.h"
+
+#include "../pyhelpers.h"
+
+#include <sudo_conf.h>
+
+// just for the IDE
+#ifndef SRC_DIR
+#define SRC_DIR ""
+#endif
+#define TESTDATA_DIR SRC_DIR "/regress/testdata/"
+
+#define TEMP_PATH_TEMPLATE "/tmp/sudo_check_python_exampleXXXXXX"
+
+extern struct TestData {
+ char *tmp_dir;
+ char *tmp_dir2;
+ char stdout_str[MAX_OUTPUT];
+ char stderr_str[MAX_OUTPUT];
+
+ char conv_str[MAX_OUTPUT];
+ const char *conv_replies[8];
+
+ // some example test data used by multiple test cases:
+ char ** settings;
+ char ** user_info;
+ char ** command_info;
+ char ** plugin_argv;
+ int plugin_argc;
+ char ** user_env;
+ char ** plugin_options;
+} data;
+
+const char * expected_path(const char *format, ...);
+
+char ** create_str_array(size_t count, ...);
+
+#define RUN_TEST(testcase) \
+ do { \
+ int success = 1; \
+ ntests++; \
+ if (verbose) { \
+ printf("Running test " #testcase " ... \n"); \
+ } \
+ if (!init()) { \
+ printf("FAILED: initialization of testcase %s at %s:%d\n", #testcase, __FILE__, __LINE__); \
+ success = 0; \
+ } else \
+ if (!testcase) { \
+ printf("FAILED: testcase %s at %s:%d\n", #testcase, __FILE__, __LINE__); \
+ success = 0; \
+ } \
+ if (!cleanup(success)) { \
+ printf("FAILED: deinitialization of testcase %s at %s:%d\n", #testcase, __FILE__, __LINE__); \
+ success = 0; \
+ } \
+ if (!success) { \
+ errors++; \
+ } \
+ } while(false)
+
+#define VERIFY_PRINT_MSG(fmt, actual_str, actual, expected_str, expected, expected_to_be_message) \
+ printf("Expectation failed at %s:%d:\n actual is <<" fmt ">>: %s\n %s <<" fmt ">>: %s\n", \
+ __FILE__, __LINE__, actual, actual_str, expected_to_be_message, expected, expected_str)
+
+#define VERIFY_CUSTOM(fmt, type, actual, expected, invert) \
+ do { \
+ type actual_value = (type)(actual); \
+ int failed = (actual_value != expected); \
+ if (invert) \
+ failed = !failed; \
+ if (failed) { \
+ VERIFY_PRINT_MSG(fmt, #actual, actual_value, #expected, expected, invert ? "not expected to be" : "expected to be"); \
+ return false; \
+ } \
+ } while(false)
+
+#define VERIFY_EQ(fmt, type, actual, expected) VERIFY_CUSTOM(fmt, type, actual, expected, false)
+#define VERIFY_NE(fmt, type, actual, not_expected) VERIFY_CUSTOM(fmt, type, actual, not_expected, true)
+
+#define VERIFY_INT(actual, expected) VERIFY_EQ("%d", int, actual, expected)
+
+#define VERIFY_PTR(actual, expected) VERIFY_EQ("%p", const void *, (const void *)actual, (const void *)expected)
+#define VERIFY_PTR_NE(actual, not_expected) VERIFY_NE("%p", const void *, (const void *)actual, (const void *)not_expected)
+
+#define VERIFY_TRUE(actual) VERIFY_NE("%d", int, actual, 0)
+#define VERIFY_FALSE(actual) VERIFY_INT(actual, false)
+
+#define VERIFY_NOT_NULL(actual) VERIFY_NE("%p", const void *, actual, NULL)
+
+#define VERIFY_STR(actual, expected) \
+ do { \
+ const char *actual_str = actual; \
+ if (!actual_str || strcmp(actual_str, expected) != 0) { \
+ VERIFY_PRINT_MSG("%s", #actual, actual_str ? actual_str : "(null)", #expected, expected, "expected to be"); \
+ return false; \
+ } \
+ } while(false)
+
+#define VERIFY_STR_CONTAINS(actual, expected) \
+ do { \
+ const char *actual_str = actual; \
+ if (!actual_str || strstr(actual_str, expected) == NULL) { \
+ VERIFY_PRINT_MSG("%s", #actual, actual_str ? actual_str : "(null)", #expected, expected, "expected to contain the string"); \
+ return false; \
+ } \
+ } while(false)
+
+int is_update(void);
+
+int verify_content(char *actual_content, const char *reference_path);
+
+#define VERIFY_CONTENT(actual_output, reference_path) \
+ VERIFY_TRUE(verify_content(actual_output, reference_path))
+
+#define VERIFY_STDOUT(reference_path) \
+ VERIFY_CONTENT(data.stdout_str, reference_path)
+
+#define VERIFY_STDERR(reference_path) \
+ VERIFY_CONTENT(data.stderr_str, reference_path)
+
+#define VERIFY_CONV(reference_name) \
+ VERIFY_CONTENT(data.conv_str, reference_name)
+
+int verify_file(const char *actual_dir, const char *actual_file_name, const char *reference_path);
+
+#define VERIFY_FILE(actual_file_name, reference_path) \
+ VERIFY_TRUE(verify_file(data.tmp_dir, actual_file_name, reference_path))
+
+int fake_conversation(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback);
+
+int fake_conversation_with_suspend(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback);
+
+int fake_printf(int msg_type, const char * restrict fmt, ...);
+
+int verify_log_lines(const char *reference_path);
+
+int mock_python_datetime_now(const char *plugin_name, const char *date_str);
+
+#define VERIFY_LOG_LINES(reference_path) \
+ VERIFY_TRUE(verify_log_lines(reference_path))
+
+int verify_str_set(char **actual_set, char **expected_set, const char *actual_variable_name);
+
+#define VERIFY_STR_SET(actual_set, ...) \
+ do { \
+ char **expected_set = create_str_array(__VA_ARGS__); \
+ VERIFY_TRUE(verify_str_set(actual_set, expected_set, #actual_set)); \
+ str_array_free(&expected_set); \
+ } while(false)
+
+#endif // PYTHON_TESTHELPERS
diff --git a/plugins/python/sudo_python_debug.c b/plugins/python/sudo_python_debug.c
new file mode 100644
index 0000000..e036282
--- /dev/null
+++ b/plugins/python/sudo_python_debug.c
@@ -0,0 +1,129 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <sudo_gettext.h>
+#include <sudo_compat.h>
+#include "sudo_python_debug.h"
+#include <sudo_queue.h>
+#include <sudo_conf.h>
+#include <sudo_fatal.h>
+
+
+static int python_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
+static unsigned int python_debug_refcnt;
+
+static const char *const python_subsystem_names[] = {
+ "py_calls", // logs c -> py calls
+ "c_calls", // logs py -> c calls
+ "load", // logs python plugin loading / unloading
+ "sudo_cb", // logs sudo callback calls
+ "internal", // logs internal functions of the language wrapper plugin
+ "plugin", // logs whatever log the python module would like to log through sudo.debug API
+ NULL
+};
+
+#define NUM_SUBSYSTEMS sizeof(python_subsystem_names) / sizeof(*python_subsystem_names) - 1
+
+/* Subsystem IDs assigned at registration time. */
+unsigned int python_subsystem_ids[NUM_SUBSYSTEMS];
+
+/*
+ * Parse the "filename flags,..." debug_flags entry and insert a new
+ * sudo_debug_file struct into debug_files.
+ */
+bool
+python_debug_parse_flags(struct sudo_conf_debug_file_list *debug_files,
+ const char *entry)
+{
+ /* Already initialized? */
+ if (python_debug_instance != SUDO_DEBUG_INSTANCE_INITIALIZER)
+ return true;
+
+ return sudo_debug_parse_flags(debug_files, entry) != -1;
+}
+
+/*
+ * Register the specified debug files and program with the
+ * debug subsystem, freeing the debug list when done.
+ * Sets the active debug instance as a side effect.
+ */
+bool
+python_debug_register(const char *program,
+ struct sudo_conf_debug_file_list *debug_files)
+{
+ int instance = python_debug_instance;
+ struct sudo_debug_file *debug_file, *debug_next;
+
+ /* Setup debugging if indicated. */
+ if (debug_files != NULL && !TAILQ_EMPTY(debug_files)) {
+ if (program != NULL) {
+ instance = sudo_debug_register(program, python_subsystem_names,
+ python_subsystem_ids, debug_files, -1);
+ }
+ TAILQ_FOREACH_SAFE(debug_file, debug_files, entries, debug_next) {
+ TAILQ_REMOVE(debug_files, debug_file, entries);
+ free(debug_file->debug_file);
+ free(debug_file->debug_flags);
+ free(debug_file);
+ }
+ }
+
+ switch (instance) {
+ case SUDO_DEBUG_INSTANCE_ERROR:
+ return false;
+ case SUDO_DEBUG_INSTANCE_INITIALIZER:
+ /* Nothing to do */
+ break;
+ default:
+ /* New debug instance or additional reference on existing one. */
+ python_debug_instance = instance;
+ sudo_debug_set_active_instance(python_debug_instance);
+ python_debug_refcnt++;
+ break;
+ }
+
+ return true;
+}
+
+/*
+ * Deregister python_debug_instance if it is registered.
+ */
+void
+python_debug_deregister(void)
+{
+ debug_decl(python_debug_deregister, PYTHON_DEBUG_INTERNAL);
+
+ if (python_debug_refcnt != 0) {
+ sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
+ if (--python_debug_refcnt == 0) {
+ if (sudo_debug_deregister(python_debug_instance) < 1)
+ python_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
+ }
+ }
+}
diff --git a/plugins/python/sudo_python_debug.h b/plugins/python/sudo_python_debug.h
new file mode 100644
index 0000000..dcd024d
--- /dev/null
+++ b/plugins/python/sudo_python_debug.h
@@ -0,0 +1,46 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2014 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_PYTHON_DEBUG_H
+#define SUDO_PYTHON_DEBUG_H
+
+#include <sudo_debug.h>
+
+/*
+ * Sudo python plugin debug subsystems.
+ * Note that python_subsystem_ids[] is filled in at debug registration time.
+ */
+extern unsigned int python_subsystem_ids[];
+#define PYTHON_DEBUG_PY_CALLS (python_subsystem_ids[0])
+#define PYTHON_DEBUG_C_CALLS (python_subsystem_ids[1])
+#define PYTHON_DEBUG_PLUGIN_LOAD (python_subsystem_ids[2])
+#define PYTHON_DEBUG_CALLBACKS (python_subsystem_ids[3])
+#define PYTHON_DEBUG_INTERNAL (python_subsystem_ids[4])
+#define PYTHON_DEBUG_PLUGIN (python_subsystem_ids[5])
+
+bool python_debug_parse_flags(struct sudo_conf_debug_file_list *debug_files, const char *entry);
+bool python_debug_register(const char *program, struct sudo_conf_debug_file_list *debug_files);
+void python_debug_deregister(void);
+
+#define debug_return_ptr_pynone \
+ do { \
+ Py_INCREF(Py_None); \
+ debug_return_ptr(Py_None); \
+ } while(0)
+
+#endif /* SUDO_PYTHON_DEBUG_H */
diff --git a/plugins/python/sudo_python_module.c b/plugins/python/sudo_python_module.c
new file mode 100644
index 0000000..e9bc6b9
--- /dev/null
+++ b/plugins/python/sudo_python_module.c
@@ -0,0 +1,631 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include "sudo_python_module.h"
+
+#define EXC_VAR(exception_name) sudo_exc_ ## exception_name
+#define TYPE_VAR(type_name) &sudo_type_ ## type_name
+
+// exceptions:
+PyObject *sudo_exc_SudoException;
+PyObject *sudo_exc_PluginException;
+PyObject *sudo_exc_PluginError;
+PyObject *sudo_exc_PluginReject;
+static PyObject *sudo_exc_ConversationInterrupted;
+
+// the methods exposed in the "sudo" python module
+// "args" is a tuple (~= const list) containing all the unnamed arguments
+// "kwargs" is a dict of the keyword arguments or NULL if there are none
+static PyObject *python_sudo_log_info(PyObject *py_self, PyObject *py_args, PyObject *py_kwargs);
+static PyObject *python_sudo_log_error(PyObject *py_self, PyObject *py_args, PyObject *py_kwargs);
+static PyObject *python_sudo_conversation(PyObject *py_self, PyObject *py_args, PyObject *py_kwargs);
+static PyObject *python_sudo_options_as_dict(PyObject *py_self, PyObject *py_args);
+static PyObject *python_sudo_options_from_dict(PyObject *py_self, PyObject *py_args);
+
+// Called on module teardown.
+static void sudo_module_free(void *self);
+
+static PyMethodDef sudo_methods[] = {
+ {"debug", (PyCFunction)python_sudo_debug, METH_VARARGS, "Debug messages which can be saved to file in sudo.conf."},
+ {"log_info", (PyCFunction)python_sudo_log_info, METH_VARARGS | METH_KEYWORDS, "Display informational messages."},
+ {"log_error", (PyCFunction)python_sudo_log_error, METH_VARARGS | METH_KEYWORDS, "Display error messages."},
+ {"conv", (PyCFunction)python_sudo_conversation, METH_VARARGS | METH_KEYWORDS, "Interact with the user"},
+ {"options_as_dict", python_sudo_options_as_dict, METH_VARARGS, "Convert a string tuple in key=value format to a dictionary."},
+ {"options_from_dict", python_sudo_options_from_dict, METH_VARARGS, "Convert a dictionary to a tuple of strings in key=value format."},
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+static struct PyModuleDef sudo_module = {
+ PyModuleDef_HEAD_INIT,
+ "sudo", /* name of module */
+ NULL, /* module documentation, may be NULL */
+ -1, /* size of per-interpreter state of the module,
+ or -1 if the module keeps state in global variables. */
+ sudo_methods,
+ NULL, /* slots */
+ NULL, /* traverse */
+ NULL, /* clear */
+ sudo_module_free
+};
+
+CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
+static int
+_parse_log_function_args(PyObject *py_args, PyObject *py_kwargs, char **args_joined, const char ** end)
+{
+ debug_decl(python_sudo_log, PYTHON_DEBUG_INTERNAL);
+
+ int rc = SUDO_RC_ERROR;
+ PyObject *py_empty = NULL;
+
+ const char *sep = NULL;
+ py_empty = PyTuple_New(0);
+ if (py_empty == NULL)
+ goto cleanup;
+
+ static const char *keywords[] = { "sep", "end", NULL };
+ if (py_kwargs != NULL && !PyArg_ParseTupleAndKeywords(py_empty, py_kwargs, "|zz:sudo.log", (char **)keywords, &sep, end))
+ goto cleanup;
+
+ if (sep == NULL)
+ sep = " ";
+
+ if (*end == NULL)
+ *end = "\n";
+
+ // this is to mimic the behaviour of python "print" / "log"
+ *args_joined = py_join_str_list(py_args, sep);
+ if (!PyErr_Occurred()) // == (*args_joined != NULL), but cpychecker does not understand that
+ rc = SUDO_RC_OK;
+
+cleanup:
+ Py_CLEAR(py_empty);
+ debug_return_int(rc);
+}
+
+static PyObject *
+python_sudo_log(int msg_type, PyObject *Py_UNUSED(py_self), PyObject *py_args, PyObject *py_kwargs)
+{
+ debug_decl(python_sudo_log, PYTHON_DEBUG_C_CALLS);
+ py_debug_python_call("sudo", "log", py_args, py_kwargs, PYTHON_DEBUG_C_CALLS);
+
+ int rc = SUDO_RC_ERROR;
+
+ char *args_joined = NULL;
+ const char *end = NULL;
+ if (_parse_log_function_args(py_args, py_kwargs, &args_joined, &end) != SUDO_RC_OK)
+ goto cleanup;
+
+ rc = py_ctx.sudo_log(msg_type, "%s%s", args_joined, end);
+ if (rc < 0) {
+ PyErr_Format(sudo_exc_SudoException, "sudo.log: Error displaying message");
+ goto cleanup;
+ }
+
+cleanup:
+ free(args_joined);
+
+ PyObject *py_result = PyErr_Occurred() ? NULL : PyLong_FromLong(rc);
+
+ py_debug_python_result("sudo", "log", py_result, PYTHON_DEBUG_C_CALLS);
+ debug_return_ptr(py_result);
+}
+
+static PyObject *
+python_sudo_options_as_dict(PyObject *py_self, PyObject *py_args)
+{
+ (void) py_self;
+
+ debug_decl(python_sudo_options_as_dict, PYTHON_DEBUG_C_CALLS);
+ py_debug_python_call("sudo", "options_as_dict", py_args, NULL, PYTHON_DEBUG_C_CALLS);
+
+ PyObject *py_config_tuple = NULL,
+ *py_result = NULL,
+ *py_config_tuple_iterator = NULL,
+ *py_config = NULL,
+ *py_splitted = NULL,
+ *py_separator = NULL;
+
+ if (!PyArg_ParseTuple(py_args, "O:sudo.options_as_dict", &py_config_tuple))
+ goto cleanup;
+
+ py_config_tuple_iterator = PyObject_GetIter(py_config_tuple);
+ if (py_config_tuple_iterator == NULL)
+ goto cleanup;
+
+ py_result = PyDict_New();
+ if (py_result == NULL)
+ goto cleanup;
+
+ py_separator = PyUnicode_FromString("=");
+ if (py_separator == NULL)
+ goto cleanup;
+
+ while ((py_config = PyIter_Next(py_config_tuple_iterator)) != NULL) {
+ py_splitted = PyUnicode_Split(py_config, py_separator, 1);
+ if (py_splitted == NULL)
+ goto cleanup;
+
+ PyObject *py_key = PyList_GetItem(py_splitted, 0); // borrowed ref
+ if (py_key == NULL)
+ goto cleanup;
+
+ PyObject *py_value = PyList_GetItem(py_splitted, 1);
+ if (py_value == NULL) { // skip values without a key
+ Py_CLEAR(py_config);
+ Py_CLEAR(py_splitted);
+ PyErr_Clear();
+ continue;
+ }
+
+ if (PyDict_SetItem(py_result, py_key, py_value) != 0) {
+ goto cleanup;
+ }
+
+ Py_CLEAR(py_config);
+ Py_CLEAR(py_splitted);
+ }
+
+cleanup:
+ Py_CLEAR(py_config_tuple_iterator);
+ Py_CLEAR(py_config);
+ Py_CLEAR(py_splitted);
+ Py_CLEAR(py_separator);
+
+ if (PyErr_Occurred()) {
+ Py_CLEAR(py_result);
+ }
+
+ py_debug_python_result("sudo", "options_as_dict", py_result, PYTHON_DEBUG_C_CALLS);
+ debug_return_ptr(py_result);
+}
+
+static PyObject *
+python_sudo_options_from_dict(PyObject *py_self, PyObject *py_args)
+{
+ (void) py_self;
+ debug_decl(python_sudo_options_from_dict, PYTHON_DEBUG_C_CALLS);
+ py_debug_python_call("sudo", "options_from_dict", py_args, NULL, PYTHON_DEBUG_C_CALLS);
+
+ PyObject *py_config_dict = NULL,
+ *py_result = NULL;
+
+ if (!PyArg_ParseTuple(py_args, "O!:sudo.options_from_dict", &PyDict_Type, &py_config_dict))
+ goto cleanup;
+
+ Py_ssize_t dict_size = PyDict_Size(py_config_dict);
+ py_result = PyTuple_New(dict_size);
+ if (py_result == NULL)
+ goto cleanup;
+
+ PyObject *py_key = NULL, *py_value = NULL; // -> borrowed references
+ Py_ssize_t i, pos = 0;
+ for (i = 0; PyDict_Next(py_config_dict, &pos, &py_key, &py_value); i++) {
+ PyObject *py_config = PyUnicode_FromFormat("%S%s%S", py_key, "=", py_value);
+ if (py_config == NULL)
+ goto cleanup;
+
+ /* Dictionaries are sparse so we cannot use pos as an index. */
+ if (PyTuple_SetItem(py_result, i, py_config) != 0) { // this steals a reference, even on error
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ if (PyErr_Occurred()) {
+ Py_CLEAR(py_result);
+ }
+
+ py_debug_python_result("sudo", "options_from_dict", py_result, PYTHON_DEBUG_C_CALLS);
+ debug_return_ptr(py_result);
+}
+
+static PyObject *
+python_sudo_log_info(PyObject *py_self, PyObject *py_args, PyObject *py_kwargs)
+{
+ return python_sudo_log(SUDO_CONV_INFO_MSG, py_self, py_args, py_kwargs);
+}
+
+static PyObject *
+python_sudo_log_error(PyObject *py_self, PyObject *py_args, PyObject *py_kwargs)
+{
+ return python_sudo_log(SUDO_CONV_ERROR_MSG, py_self, py_args, py_kwargs);
+}
+
+CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
+static int py_expect_arg_callable(PyObject *py_callable,
+ const char *func_name, const char *arg_name)
+{
+ debug_decl(py_expect_arg_callable, PYTHON_DEBUG_INTERNAL);
+
+ if (!PyCallable_Check(py_callable)) {
+ PyErr_Format(PyExc_ValueError, "%s: %s argument must be python callable (got %s) ",
+ func_name, arg_name, Py_TYPENAME(py_callable));
+ debug_return_int(-1);
+ }
+
+ debug_return_int(0);
+}
+
+struct py_conv_callback_closure
+{
+ PyObject *py_on_suspend;
+ PyObject *py_on_resume;
+};
+
+static int
+_call_conversation_callback(PyObject *py_callback, int signo)
+{
+ debug_decl(_call_conversation_callback, PYTHON_DEBUG_INTERNAL);
+
+ if (py_callback == NULL || py_callback == Py_None)
+ debug_return_int(0); // nothing to do
+
+ PyObject *py_result = PyObject_CallFunction(py_callback, "(i)", signo);
+
+ int rc = -1;
+
+ // We treat sudo.RC_OK (1) and None (no exception occurred) as success as well to avoid confusion
+ if (py_result && (py_result == Py_None || PyLong_AsLong(py_result) >= 0))
+ rc = 0;
+
+ Py_CLEAR(py_result);
+
+ if (rc != 0)
+ py_log_last_error("Error during conversation callback");
+
+ debug_return_int(rc);
+}
+
+static int
+python_sudo_conversation_suspend_cb(int signo, struct py_conv_callback_closure *closure)
+{
+ return _call_conversation_callback(closure->py_on_suspend, signo);
+}
+
+static int
+python_sudo_conversation_resume_cb(int signo, struct py_conv_callback_closure *closure)
+{
+ return _call_conversation_callback(closure->py_on_resume, signo);
+}
+
+static PyObject *
+python_sudo_conversation(PyObject *Py_UNUSED(self), PyObject *py_args, PyObject *py_kwargs)
+{
+ debug_decl(python_sudo_conversation, PYTHON_DEBUG_C_CALLS);
+ py_debug_python_call("sudo", "conv", py_args, py_kwargs, PYTHON_DEBUG_C_CALLS);
+
+ PyObject *py_result = NULL, *py_empty = NULL;
+ Py_ssize_t num_msgs = 0;
+ struct sudo_conv_message *msgs = NULL;
+ struct sudo_conv_reply *replies = NULL;
+
+ // Note, they are both borrowed references of py_kwargs
+ struct py_conv_callback_closure callback_closure = { NULL, NULL };
+
+ struct sudo_conv_callback callback = {
+ SUDO_CONV_CALLBACK_VERSION,
+ &callback_closure,
+ (sudo_conv_callback_fn_t)python_sudo_conversation_suspend_cb,
+ (sudo_conv_callback_fn_t)python_sudo_conversation_resume_cb
+ };
+
+ py_empty = PyTuple_New(0);
+ if (py_empty == NULL)
+ goto cleanup;
+
+ static const char *keywords[] = { "on_suspend", "on_resume", NULL };
+ if (py_kwargs != NULL && !PyArg_ParseTupleAndKeywords(py_empty, py_kwargs, "|OO:sudo.conv", (char **)keywords,
+ &callback_closure.py_on_suspend,
+ &callback_closure.py_on_resume))
+ goto cleanup;
+
+ if (callback_closure.py_on_suspend != NULL &&
+ py_expect_arg_callable(callback_closure.py_on_suspend, "sudo.conv", "on_suspend") < 0) {
+ goto cleanup;
+ }
+
+ if (callback_closure.py_on_resume != NULL &&
+ py_expect_arg_callable(callback_closure.py_on_resume, "sudo.conv", "on_resume") < 0) {
+ goto cleanup;
+ }
+
+ /* sudo_module_ConvMessages_to_c() returns error if no messages. */
+ if (sudo_module_ConvMessages_to_c(py_args, &num_msgs, &msgs) < 0) {
+ goto cleanup;
+ }
+
+ replies = calloc((size_t)num_msgs, sizeof(struct sudo_conv_reply));
+ if (replies == NULL)
+ goto cleanup;
+ py_result = PyTuple_New(num_msgs);
+ if (py_result == NULL)
+ goto cleanup;
+
+ if (py_ctx.sudo_conv == NULL) {
+ PyErr_Format(sudo_exc_SudoException, "%s: conversation is unavailable",
+ __func__);
+ goto cleanup;
+ }
+
+ int rc = py_sudo_conv((int)num_msgs, msgs, replies, &callback);
+ if (rc != 0) {
+ PyErr_Format(sudo_exc_ConversationInterrupted,
+ "%s: conversation was interrupted", __func__, rc);
+ goto cleanup;
+ }
+
+ for (Py_ssize_t i = 0; i < num_msgs; ++i) {
+ char *reply = replies[i].reply;
+ if (reply != NULL) {
+ PyObject *py_reply = PyUnicode_FromString(reply);
+ if (py_reply == NULL) {
+ goto cleanup;
+ }
+
+ if (PyTuple_SetItem(py_result, i, py_reply) != 0) { // this steals a reference even on error
+ PyErr_Format(sudo_exc_SudoException, "%s: failed to set tuple item", __func__);
+ goto cleanup;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "user reply for conversation: '%s'\n", reply);
+ }
+ }
+
+cleanup:
+ Py_CLEAR(py_empty);
+ if (replies != NULL) {
+ for (int i = 0; i < num_msgs; ++i)
+ free(replies[i].reply);
+ }
+ free(msgs);
+ free(replies);
+
+ if (PyErr_Occurred()) {
+ Py_CLEAR(py_result); // we return NULL
+ }
+
+ py_debug_python_result("sudo", "conv", py_result, PYTHON_DEBUG_C_CALLS);
+
+ debug_return_ptr(py_result);
+}
+
+/*
+ * Create a python class.
+ * Class name must be a full name including module, eg. "sudo.MyFavouriteClass".
+ * The resulting class object can be added to a module using PyModule_AddObject.
+ */
+PyObject *
+sudo_module_create_class(const char *class_name, PyMethodDef *class_methods,
+ PyObject *base_class)
+{
+ debug_decl(sudo_module_create_class, PYTHON_DEBUG_INTERNAL);
+
+ PyObject *py_base_classes = NULL, *py_class = NULL, *py_member_dict = NULL;
+
+ if (base_class == NULL) {
+ py_base_classes = PyTuple_New(0);
+ } else {
+ py_base_classes = Py_BuildValue("(O)", base_class);
+ }
+
+ if (py_base_classes == NULL)
+ goto cleanup;
+
+ py_member_dict = PyDict_New();
+ if (py_member_dict == NULL)
+ goto cleanup;
+
+ for (PyMethodDef *py_def = class_methods; py_def->ml_name != NULL; ++py_def) {
+ PyObject *py_func = PyCFunction_New(py_def, NULL);
+ if (py_func == NULL) {
+ goto cleanup;
+ }
+
+ // this wrapping makes the function get the 'self' as argument
+ PyObject *py_method = PyInstanceMethod_New(py_func);
+ if (py_method == NULL) {
+ Py_DECREF(py_func);
+ goto cleanup;
+ }
+
+ int rc = PyDict_SetItemString(py_member_dict, py_def->ml_name, py_method);
+
+ Py_XDECREF(py_func);
+ Py_XDECREF(py_method);
+
+ if (rc != 0)
+ goto cleanup;
+ }
+
+ py_class = PyObject_CallFunction((PyObject *)&PyType_Type, "(sOO)",
+ class_name,
+ py_base_classes,
+ py_member_dict);
+
+cleanup:
+ Py_CLEAR(py_base_classes);
+ Py_CLEAR(py_member_dict);
+
+ debug_return_ptr(py_class);
+}
+
+CPYCHECKER_STEALS_REFERENCE_TO_ARG(3)
+static void
+sudo_module_register_enum(PyObject *py_module, const char *enum_name, PyObject *py_constants_dict)
+{
+ // pseudo code:
+ // return enum.IntEnum('MyEnum', {'DEFINITION_NAME': DEFINITION_VALUE, ...})
+
+ debug_decl(sudo_module_register_enum, PYTHON_DEBUG_INTERNAL);
+
+ if (py_constants_dict == NULL)
+ return;
+
+ PyObject *py_enum_class = NULL;
+ PyObject *py_enum_module = PyImport_ImportModule("enum");
+ if (py_enum_module == NULL) {
+ Py_CLEAR(py_constants_dict);
+ debug_return;
+ }
+
+ py_enum_class = PyObject_CallMethod(py_enum_module,
+ "IntEnum", "sO", enum_name,
+ py_constants_dict);
+
+ Py_CLEAR(py_constants_dict);
+ Py_CLEAR(py_enum_module);
+
+ if (py_enum_class == NULL) {
+ debug_return;
+ }
+
+ // PyModule_AddObject steals the reference to py_enum_class on success
+ if (PyModule_AddObject(py_module, enum_name, py_enum_class) < 0) {
+ Py_CLEAR(py_enum_class);
+ }
+
+ debug_return;
+}
+
+PyMODINIT_FUNC
+sudo_module_init(void)
+{
+ debug_decl(sudo_module_init, PYTHON_DEBUG_C_CALLS);
+
+ PyObject *py_module = PyModule_Create(&sudo_module);
+
+ if (py_module == NULL)
+ debug_return_ptr(NULL);
+
+ // Note: "PyModule_AddObject()" decrements the refcount only on success
+
+ // exceptions
+ #define MODULE_ADD_EXCEPTION(exception_name, base_exception) \
+ do { \
+ EXC_VAR(exception_name) = PyErr_NewException("sudo." # exception_name, base_exception, NULL); \
+ if (EXC_VAR(exception_name) == NULL || PyModule_AddObject(py_module, # exception_name, EXC_VAR(exception_name)) < 0) { \
+ Py_CLEAR(EXC_VAR(exception_name)); \
+ goto cleanup; \
+ } \
+ Py_INCREF(EXC_VAR(exception_name)); \
+ } while(0);
+
+ MODULE_ADD_EXCEPTION(SudoException, NULL);
+
+ MODULE_ADD_EXCEPTION(PluginException, NULL);
+ MODULE_ADD_EXCEPTION(PluginError, EXC_VAR(PluginException));
+ MODULE_ADD_EXCEPTION(PluginReject, EXC_VAR(PluginException));
+
+ MODULE_ADD_EXCEPTION(ConversationInterrupted, EXC_VAR(SudoException));
+
+ #define MODULE_REGISTER_ENUM(name, key_values) \
+ sudo_module_register_enum(py_module, name, py_dict_create_string_int(\
+ sizeof(key_values) / sizeof(struct key_value_str_int), key_values))
+
+ // constants
+ struct key_value_str_int constants_rc[] = {
+ {"OK", SUDO_RC_OK},
+ {"ACCEPT", SUDO_RC_ACCEPT},
+ {"REJECT", SUDO_RC_REJECT},
+ {"ERROR", SUDO_RC_ERROR},
+ {"USAGE_ERROR", SUDO_RC_USAGE_ERROR}
+ };
+ MODULE_REGISTER_ENUM("RC", constants_rc);
+
+ struct key_value_str_int constants_conv[] = {
+ {"PROMPT_ECHO_OFF", SUDO_CONV_PROMPT_ECHO_OFF},
+ {"PROMPT_ECHO_ON", SUDO_CONV_PROMPT_ECHO_ON},
+ {"INFO_MSG", SUDO_CONV_INFO_MSG},
+ {"PROMPT_MASK", SUDO_CONV_PROMPT_MASK},
+ {"PROMPT_ECHO_OK", SUDO_CONV_PROMPT_ECHO_OK},
+ {"PREFER_TTY", SUDO_CONV_PREFER_TTY}
+ };
+ MODULE_REGISTER_ENUM("CONV", constants_conv);
+
+ struct key_value_str_int constants_debug[] = {
+ {"CRIT", SUDO_DEBUG_CRIT},
+ {"ERROR", SUDO_DEBUG_ERROR},
+ {"WARN", SUDO_DEBUG_WARN},
+ {"NOTICE", SUDO_DEBUG_NOTICE},
+ {"DIAG", SUDO_DEBUG_DIAG},
+ {"INFO", SUDO_DEBUG_INFO},
+ {"TRACE", SUDO_DEBUG_TRACE},
+ {"DEBUG", SUDO_DEBUG_DEBUG}
+ };
+ MODULE_REGISTER_ENUM("DEBUG", constants_debug);
+
+ struct key_value_str_int constants_exit_reason[] = {
+ {"NO_STATUS", SUDO_PLUGIN_NO_STATUS},
+ {"WAIT_STATUS", SUDO_PLUGIN_WAIT_STATUS},
+ {"EXEC_ERROR", SUDO_PLUGIN_EXEC_ERROR},
+ {"SUDO_ERROR", SUDO_PLUGIN_SUDO_ERROR}
+ };
+ MODULE_REGISTER_ENUM("EXIT_REASON", constants_exit_reason);
+
+ struct key_value_str_int constants_plugin_types[] = {
+ {"POLICY", SUDO_POLICY_PLUGIN},
+ {"AUDIT", SUDO_AUDIT_PLUGIN},
+ {"IO", SUDO_IO_PLUGIN},
+ {"APPROVAL", SUDO_APPROVAL_PLUGIN},
+ {"SUDO", SUDO_FRONT_END}
+ };
+ MODULE_REGISTER_ENUM("PLUGIN_TYPE", constants_plugin_types);
+
+ // classes
+ if (sudo_module_register_conv_message(py_module) != SUDO_RC_OK)
+ goto cleanup;
+
+ if (sudo_module_register_baseplugin(py_module) != SUDO_RC_OK)
+ goto cleanup;
+
+cleanup:
+ if (PyErr_Occurred()) {
+ Py_CLEAR(py_module);
+ Py_CLEAR(sudo_exc_SudoException);
+ Py_CLEAR(sudo_exc_PluginError);
+ Py_CLEAR(sudo_exc_PluginReject);
+ Py_CLEAR(sudo_exc_ConversationInterrupted);
+ }
+
+ debug_return_ptr(py_module);
+}
+
+static void
+sudo_module_free(void *self)
+{
+ debug_decl(sudo_module_free, PYTHON_DEBUG_C_CALLS);
+
+ // Free exceptions
+ Py_CLEAR(sudo_exc_SudoException);
+ Py_CLEAR(sudo_exc_PluginError);
+ Py_CLEAR(sudo_exc_PluginReject);
+ Py_CLEAR(sudo_exc_ConversationInterrupted);
+
+ // Free base plugin
+ Py_CLEAR(sudo_type_Plugin);
+
+ // Free conversation message type
+ Py_CLEAR(sudo_type_ConvMessage);
+
+ debug_return;
+}
diff --git a/plugins/python/sudo_python_module.h b/plugins/python/sudo_python_module.h
new file mode 100644
index 0000000..c18ec00
--- /dev/null
+++ b/plugins/python/sudo_python_module.h
@@ -0,0 +1,56 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Robert Manner <robert.manner@oneidentity.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_PYTHON_MODULE_H
+#define SUDO_PYTHON_MODULE_H
+
+#include "pyhelpers.h"
+
+extern PyObject *sudo_exc_SudoException; // Base exception for the sudo module problems
+
+// This is for the python plugins to report error messages for us
+extern PyObject *sudo_exc_PluginException; // base exception of the following:
+extern PyObject *sudo_exc_PluginReject; // a reject with message
+extern PyObject *sudo_exc_PluginError; // an error with message
+
+extern PyTypeObject *sudo_type_Plugin;
+extern PyTypeObject *sudo_type_ConvMessage;
+
+PyObject *sudo_module_create_class(const char *class_name, PyMethodDef *class_methods,
+ PyObject *base_class);
+
+CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
+int sudo_module_register_conv_message(PyObject *py_module);
+
+CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
+int sudo_module_ConvMessage_to_c(PyObject *py_conv_message, struct sudo_conv_message *conv_message);
+
+CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
+int sudo_module_ConvMessages_to_c(PyObject *py_tuple, Py_ssize_t *num_msgs, struct sudo_conv_message **msgs);
+
+CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
+int sudo_module_register_baseplugin(PyObject *py_module);
+
+CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
+int sudo_module_set_default_loghandler(void);
+
+PyObject *python_sudo_debug(PyObject *py_self, PyObject *py_args);
+
+PyMODINIT_FUNC sudo_module_init(void);
+
+#endif // SUDO_PYTHON_MODULE_H
diff --git a/plugins/sample/Makefile.in b/plugins/sample/Makefile.in
new file mode 100644
index 0000000..a20cdd4
--- /dev/null
+++ b/plugins/sample/Makefile.in
@@ -0,0 +1,221 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2011-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+devdir = @devdir@
+scriptdir = $(top_srcdir)/scripts
+incdir = $(top_srcdir)/include
+cross_compiling = @CROSS_COMPILING@
+
+# Compiler & tools to use
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+SED = @SED@
+AWK = @AWK@
+
+# Our install program supports extra flags...
+INSTALL = $(SHELL) $(scriptdir)/install-sh -c
+INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
+INSTALL_BACKUP = @INSTALL_BACKUP@
+
+# Libraries
+LIBS = $(top_builddir)/lib/util/libsudo_util.la
+
+# C preprocessor flags
+CPPFLAGS = -I$(incdir) -I$(top_builddir) @CPPFLAGS@
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+
+# Flags to pass to the link stage
+LDFLAGS = @LDFLAGS@
+LT_LDFLAGS = @LT_LDFLAGS@ @LT_LDEXPORTS@
+
+# Flags to pass to libtool
+LTFLAGS = --tag=disable-static
+
+# Address sanitizer flags
+ASAN_CFLAGS = @ASAN_CFLAGS@
+ASAN_LDFLAGS = @ASAN_LDFLAGS@
+
+# PIE flags
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+
+# Stack smashing protection flags
+HARDENING_CFLAGS = @HARDENING_CFLAGS@
+HARDENING_LDFLAGS = @HARDENING_LDFLAGS@
+
+# cppcheck options, usually set in the top-level Makefile
+CPPCHECK_OPTS = -q --enable=warning,performance,portability --suppress=constStatement --suppress=compareBoolExpressionWithInt --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
+
+# splint options, usually set in the top-level Makefile
+SPLINT_OPTS = -D__restrict= -checks
+
+# PVS-studio options
+PVS_CFG = $(top_srcdir)/PVS-Studio.cfg
+PVS_IGNORE = 'V707,V011,V002,V536'
+PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
+
+# Where to install things...
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+sysconfdir = @sysconfdir@
+adminconfdir = @adminconfdir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+localstatedir = @localstatedir@
+plugindir = @plugindir@
+
+# File mode and map file to use for shared libraries/objects
+shlib_enable = @SHLIB_ENABLE@
+shlib_mode = @SHLIB_MODE@
+shlib_exp = $(srcdir)/sample_plugin.exp
+shlib_map = sample_plugin.map
+shlib_opt = sample_plugin.opt
+
+# User and group ids the installed files should be "owned" by
+install_uid = 0
+install_gid = 0
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+OBJS = sample_plugin.lo
+
+LIBOBJDIR = $(top_builddir)/@ac_config_libobj_dir@/
+
+VERSION = @PACKAGE_VERSION@
+
+all: sample_plugin.la
+
+depend:
+ $(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
+ --builddir=$(abs_top_builddir) plugins/sample/Makefile.in
+ cd $(top_builddir) && ./config.status --file plugins/sample/Makefile
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file plugins/sample/Makefile
+
+.SUFFIXES: .c .h .i .lo .plog
+
+.c.lo:
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.i:
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+
+.i.plog:
+ ifile=$<; rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $${ifile%i}c --i-file $< --output-file $@
+
+$(shlib_map): $(shlib_exp)
+ @$(AWK) 'BEGIN { print "{\n\tglobal:" } { print "\t\t"$$0";" } END { print "\tlocal:\n\t\t*;\n};" }' $(shlib_exp) > $@
+
+$(shlib_opt): $(shlib_exp)
+ @$(SED) 's/^/+e /' $(shlib_exp) > $@
+
+sample_plugin.la: $(OBJS) @LT_LDDEP@
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) $(ASAN_LDFLAGS) $(HARDENING_LDFLAGS) $(LT_LDFLAGS) -o $@ $(OBJS) $(LIBS) -module -avoid-version -rpath $(plugindir) -shrext .so
+
+pre-install:
+
+install: install-plugin
+
+install-dirs:
+ $(SHELL) $(scriptdir)/mkinstalldirs $(DESTDIR)$(plugindir)
+
+install-binaries:
+
+install-includes:
+
+install-doc:
+
+install-plugin: install-dirs sample_plugin.la
+ if [ X"$(shlib_enable)" = X"yes" ]; then \
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) $(INSTALL_OWNER) -m $(shlib_mode) sample_plugin.la $(DESTDIR)$(plugindir); \
+ fi
+
+install-fuzzer:
+
+uninstall:
+ -$(LIBTOOL) $(LTFLAGS) --mode=uninstall rm -f $(DESTDIR)$(plugindir)/sample_plugin.la
+ -test -z "$(INSTALL_BACKUP)" || \
+ rm -f $(DESTDIR)$(plugindir)/sample_plugin.so$(INSTALL_BACKUP)
+
+splint:
+ splint $(SPLINT_OPTS) -I$(incdir) -I$(top_builddir) $(srcdir)/*.c
+
+cppcheck:
+ cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) $(srcdir)/*.c
+
+pvs-log-files: $(POBJS)
+
+pvs-studio: $(POBJS)
+ plog-converter $(PVS_LOG_OPTS) $(POBJS)
+
+fuzz:
+
+check-fuzzer:
+
+check: check-fuzzer
+
+check-verbose: check
+
+clean:
+ -$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f *.lo *.o *.la
+ -rm -f *.i *.plog stamp-* core *.core core.*
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile .libs $(shlib_map) $(shlib_opt)
+
+clobber: distclean
+
+realclean: distclean
+ rm -f TAGS tags
+
+cleandir: realclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean
+
+# Autogenerated dependencies, do not modify
+sample_plugin.lo: $(srcdir)/sample_plugin.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sample_plugin.c
+sample_plugin.i: $(srcdir)/sample_plugin.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sample_plugin.plog: sample_plugin.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sample_plugin.c --i-file $< --output-file $@
diff --git a/plugins/sample/README b/plugins/sample/README
new file mode 100644
index 0000000..dbd92cd
--- /dev/null
+++ b/plugins/sample/README
@@ -0,0 +1,22 @@
+This is a sample sudo policy plugin. See the sudo_plugin manual for
+information on writing your own plugin.
+
+The sample policy plugin is not installed by default. It can be installed
+by running "make install" as the superuser from the plugins/sample
+directory.
+
+To actually use the sample plugin, you'll need to modify the
+/etc/sudo.conf file. Caution: you should not make changes to
+/etc/sudo.conf without also having a root shell open repair things
+in case of an error. To enable the plugin, first comment out any
+existing policy Plugin line in /etc/sudo.conf, for example:
+
+ Plugin sudoers_policy sudoers.so
+
+Then add a line for the sample plugin:
+
+ Plugin sample_policy sample_plugin.so
+
+You may need to create /etc/sudo.conf if it does not already exist.
+
+Note that you may only have a single policy plugin defined.
diff --git a/plugins/sample/sample_plugin.c b/plugins/sample/sample_plugin.c
new file mode 100644
index 0000000..a529208
--- /dev/null
+++ b/plugins/sample/sample_plugin.c
@@ -0,0 +1,517 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2016, 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <grp.h>
+#include <pwd.h>
+
+#include <pathnames.h>
+#include <sudo_compat.h>
+#include <sudo_plugin.h>
+#include <sudo_util.h>
+
+/*
+ * Sample plugin module that allows any user who knows the password
+ * ("test") to run any command as root. Since there is no credential
+ * caching the validate and invalidate functions are NULL.
+ */
+
+static struct plugin_state {
+ char **envp;
+ char * const *settings;
+ char * const *user_info;
+} plugin_state;
+static sudo_conv_t sudo_conv;
+static sudo_printf_t sudo_log;
+static FILE *input, *output;
+static uid_t runas_uid = ROOT_UID;
+static gid_t runas_gid = (gid_t)-1;
+static int use_sudoedit = false;
+
+/*
+ * Plugin policy open function.
+ */
+static int
+policy_open(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], char * const user_env[], char * const args[],
+ const char **errstr)
+{
+ char * const *ui;
+ struct passwd *pw;
+ const char *runas_user = NULL;
+ struct group *gr;
+ const char *runas_group = NULL;
+
+ if (!sudo_conv)
+ sudo_conv = conversation;
+ if (!sudo_log)
+ sudo_log = sudo_plugin_printf;
+
+ if (SUDO_API_VERSION_GET_MAJOR(version) != SUDO_API_VERSION_MAJOR) {
+ sudo_log(SUDO_CONV_ERROR_MSG,
+ "the sample plugin requires API version %d.x\n",
+ SUDO_API_VERSION_MAJOR);
+ return -1;
+ }
+
+ /* Only allow commands to be run as root. */
+ for (ui = settings; *ui != NULL; ui++) {
+ if (strncmp(*ui, "runas_user=", sizeof("runas_user=") - 1) == 0) {
+ runas_user = *ui + sizeof("runas_user=") - 1;
+ }
+ if (strncmp(*ui, "runas_group=", sizeof("runas_group=") - 1) == 0) {
+ runas_group = *ui + sizeof("runas_group=") - 1;
+ }
+ if (strncmp(*ui, "progname=", sizeof("progname=") - 1) == 0) {
+ initprogname(*ui + sizeof("progname=") - 1);
+ }
+ /* Check to see if sudo was called as sudoedit or with -e flag. */
+ if (strncmp(*ui, "sudoedit=", sizeof("sudoedit=") - 1) == 0) {
+ if (strcasecmp(*ui + sizeof("sudoedit=") - 1, "true") == 0)
+ use_sudoedit = true;
+ }
+ /* This plugin doesn't support running sudo with no arguments. */
+ if (strncmp(*ui, "implied_shell=", sizeof("implied_shell=") - 1) == 0) {
+ if (strcasecmp(*ui + sizeof("implied_shell=") - 1, "true") == 0)
+ return -2; /* usage error */
+ }
+ }
+ if (runas_user != NULL) {
+ if ((pw = getpwnam(runas_user)) == NULL) {
+ sudo_log(SUDO_CONV_ERROR_MSG, "unknown user %s\n", runas_user);
+ return 0;
+ }
+ runas_uid = pw->pw_uid;
+ }
+ if (runas_group != NULL) {
+ if ((gr = getgrnam(runas_group)) == NULL) {
+ sudo_log(SUDO_CONV_ERROR_MSG, "unknown group %s\n", runas_group);
+ return 0;
+ }
+ runas_gid = gr->gr_gid;
+ }
+
+ /* Plugin state. */
+ plugin_state.envp = (char **)user_env;
+ plugin_state.settings = settings;
+ plugin_state.user_info = user_info;
+
+ return 1;
+}
+
+static char *
+find_in_path(char *command, char **envp)
+{
+ struct stat sb;
+ char *path = NULL;
+ char *path0, **ep, *cp;
+ char pathbuf[PATH_MAX], *qualified = NULL;
+
+ if (strchr(command, '/') != NULL)
+ return command;
+
+ for (ep = plugin_state.envp; *ep != NULL; ep++) {
+ if (strncmp(*ep, "PATH=", 5) == 0) {
+ path = *ep + 5;
+ break;
+ }
+ }
+ path = path0 = strdup(path ? path : _PATH_DEFPATH);
+ do {
+ if ((cp = strchr(path, ':')))
+ *cp = '\0';
+ snprintf(pathbuf, sizeof(pathbuf), "%s/%s", *path ? path : ".",
+ command);
+ if (stat(pathbuf, &sb) == 0) {
+ if (S_ISREG(sb.st_mode) && (sb.st_mode & 0000111)) {
+ qualified = pathbuf;
+ break;
+ }
+ }
+ path = cp + 1;
+ } while (cp != NULL);
+ free(path0);
+ return qualified ? strdup(qualified) : NULL;
+}
+
+static int
+check_passwd(void)
+{
+ struct sudo_conv_message msg;
+ struct sudo_conv_reply repl;
+
+ /* Prompt user for password via conversation function. */
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_type = SUDO_CONV_PROMPT_ECHO_OFF;
+ msg.msg = "Password: ";
+ memset(&repl, 0, sizeof(repl));
+ sudo_conv(1, &msg, &repl, NULL);
+ if (repl.reply == NULL) {
+ sudo_log(SUDO_CONV_ERROR_MSG, "missing password\n");
+ return false;
+ }
+ if (strcmp(repl.reply, "test") != 0) {
+ sudo_log(SUDO_CONV_ERROR_MSG, "incorrect password\n");
+ return false;
+ }
+ return true;
+}
+
+static char **
+build_command_info(const char *command)
+{
+ char **command_info;
+ int i = 0;
+
+ /* Setup command info. */
+ command_info = calloc(32, sizeof(char *));
+ if (command_info == NULL)
+ goto oom;
+ if ((command_info[i] = sudo_new_key_val("command", command)) == NULL)
+ goto oom;
+ i++;
+ if (asprintf(&command_info[i], "runas_euid=%ld", (long)runas_uid) == -1)
+ goto oom;
+ i++;
+ if (asprintf(&command_info[i++], "runas_uid=%ld", (long)runas_uid) == -1)
+ goto oom;
+ i++;
+ if (runas_gid != (gid_t)-1) {
+ if (asprintf(&command_info[i++], "runas_gid=%ld", (long)runas_gid) == -1)
+ goto oom;
+ i++;
+ if (asprintf(&command_info[i++], "runas_egid=%ld", (long)runas_gid) == -1)
+ goto oom;
+ i++;
+ }
+#ifdef USE_TIMEOUT
+ if ((command_info[i] = strdup("timeout=30")) == NULL)
+ goto oom;
+ i++;
+#endif
+ if (use_sudoedit) {
+ if ((command_info[i] = strdup("sudoedit=true")) == NULL)
+ goto oom;
+ }
+ return command_info;
+oom:
+ while (i > 0) {
+ free(command_info[i--]);
+ }
+ free(command_info);
+ return NULL;
+}
+
+static char *
+find_editor(int nfiles, char * const files[], char **argv_out[])
+{
+ char *cp, *last, **ep, **nargv, *editor_path;
+ char *editor = NULL;
+ int ac, i, nargc, wasblank;
+
+ /* Lookup EDITOR in user's environment. */
+ for (ep = plugin_state.envp; *ep != NULL; ep++) {
+ if (strncmp(*ep, "EDITOR=", 7) == 0) {
+ editor = *ep + 7;
+ break;
+ }
+ }
+ editor = strdup(editor ? editor : _PATH_VI);
+ if (editor == NULL) {
+ sudo_log(SUDO_CONV_ERROR_MSG, "unable to allocate memory\n");
+ return NULL;
+ }
+
+ /*
+ * Split editor into an argument vector; editor is reused (do not free).
+ * The EDITOR environment variables may contain command
+ * line args so look for those and alloc space for them too.
+ */
+ nargc = 1;
+ for (wasblank = 0, cp = editor; *cp != '\0'; cp++) {
+ if (isblank((unsigned char) *cp))
+ wasblank = 1;
+ else if (wasblank) {
+ wasblank = 0;
+ nargc++;
+ }
+ }
+ /* If we can't find the editor in the user's PATH, give up. */
+ cp = strtok_r(editor, " \t", &last);
+ if (cp == NULL ||
+ (editor_path = find_in_path(editor, plugin_state.envp)) == NULL) {
+ free(editor);
+ return NULL;
+ }
+ if (editor_path != editor)
+ free(editor);
+ nargv = reallocarray(NULL, (size_t)nargc + 1 + (size_t)nfiles + 1,
+ sizeof(char *));
+ if (nargv == NULL) {
+ sudo_log(SUDO_CONV_ERROR_MSG, "unable to allocate memory\n");
+ free(editor_path);
+ return NULL;
+ }
+ for (ac = 0; cp != NULL && ac < nargc; ac++) {
+ nargv[ac] = cp;
+ cp = strtok_r(NULL, " \t", &last);
+ }
+ nargv[ac++] = (char *)"--";
+ for (i = 0; i < nfiles; )
+ nargv[ac++] = files[i++];
+ nargv[ac] = NULL;
+
+ *argv_out = nargv;
+ return editor_path;
+}
+
+/*
+ * Plugin policy check function.
+ * Simple example that prompts for a password, hard-coded to "test".
+ */
+static int
+policy_check(int argc, char * const argv[],
+ char *env_add[], char **command_info_out[],
+ char **argv_out[], char **user_env_out[], const char **errstr)
+{
+ char *command;
+
+ if (!argc || argv[0] == NULL) {
+ sudo_log(SUDO_CONV_ERROR_MSG, "no command specified\n");
+ return false;
+ }
+
+ if (!check_passwd())
+ return false;
+
+ command = find_in_path(argv[0], plugin_state.envp);
+ if (command == NULL) {
+ sudo_log(SUDO_CONV_ERROR_MSG, "%s: command not found\n", argv[0]);
+ return false;
+ }
+
+ /* If "sudo vi" is run, auto-convert to sudoedit. */
+ if (strcmp(command, _PATH_VI) == 0)
+ use_sudoedit = true;
+
+ if (use_sudoedit) {
+ /* Rebuild argv using editor */
+ free(command);
+ command = find_editor(argc - 1, argv + 1, argv_out);
+ if (command == NULL) {
+ sudo_log(SUDO_CONV_ERROR_MSG, "unable to find valid editor\n");
+ return -1;
+ }
+ use_sudoedit = true;
+ } else {
+ /* No changes needd to argv */
+ *argv_out = (char **)argv;
+ }
+
+ /* No changes to envp */
+ *user_env_out = plugin_state.envp;
+
+ /* Setup command info. */
+ *command_info_out = build_command_info(command);
+ free(command);
+ if (*command_info_out == NULL) {
+ sudo_log(SUDO_CONV_ERROR_MSG, "out of memory\n");
+ return -1;
+ }
+
+ return true;
+}
+
+static int
+policy_list(int argc, char * const argv[], int verbose, const char *list_user,
+ const char **errstr)
+{
+ /*
+ * List user's capabilities.
+ */
+ sudo_log(SUDO_CONV_INFO_MSG, "Validated users may run any command\n");
+ return true;
+}
+
+static int
+policy_version(int verbose)
+{
+ sudo_log(SUDO_CONV_INFO_MSG, "Sample policy plugin version %s\n",
+ PACKAGE_VERSION);
+ return true;
+}
+
+static void
+policy_close(int exit_status, int error)
+{
+ /*
+ * The policy might log the command exit status here.
+ * In this example, we just print a message.
+ */
+ if (error) {
+ sudo_log(SUDO_CONV_ERROR_MSG, "Command error: %s\n", strerror(error));
+ } else {
+ if (WIFEXITED(exit_status)) {
+ sudo_log(SUDO_CONV_INFO_MSG, "Command exited with status %d\n",
+ WEXITSTATUS(exit_status));
+ } else if (WIFSIGNALED(exit_status)) {
+ sudo_log(SUDO_CONV_INFO_MSG, "Command killed by signal %d\n",
+ WTERMSIG(exit_status));
+ }
+ }
+}
+
+static int
+io_open(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], char * const command_info[],
+ int argc, char * const argv[], char * const user_env[], char * const args[],
+ const char **errstr)
+{
+ int fd;
+ char path[PATH_MAX];
+
+ if (!sudo_conv)
+ sudo_conv = conversation;
+ if (!sudo_log)
+ sudo_log = sudo_plugin_printf;
+
+ /* Open input and output files. */
+ snprintf(path, sizeof(path), "/var/tmp/sample-%u.output",
+ (unsigned int)getpid());
+ fd = open(path, O_WRONLY|O_CREAT|O_EXCL, 0644);
+ if (fd == -1)
+ return false;
+ output = fdopen(fd, "w");
+
+ snprintf(path, sizeof(path), "/var/tmp/sample-%u.input",
+ (unsigned int)getpid());
+ fd = open(path, O_WRONLY|O_CREAT|O_EXCL, 0644);
+ if (fd == -1)
+ return false;
+ input = fdopen(fd, "w");
+
+ return true;
+}
+
+static void
+io_close(int exit_status, int error)
+{
+ fclose(input);
+ fclose(output);
+}
+
+static int
+io_version(int verbose)
+{
+ sudo_log(SUDO_CONV_INFO_MSG, "Sample I/O plugin version %s\n",
+ PACKAGE_VERSION);
+ return true;
+}
+
+static int
+io_log_input(const char *buf, unsigned int len, const char **errstr)
+{
+ ignore_result(fwrite(buf, len, 1, input));
+ return true;
+}
+
+static int
+io_log_output(const char *buf, unsigned int len, const char **errstr)
+{
+ const char *cp, *ep;
+ bool ret = true;
+
+ ignore_result(fwrite(buf, len, 1, output));
+ /*
+ * If we find the string "honk!" in the buffer, reject it.
+ * In practice we'd want to be able to detect the word
+ * broken across two buffers.
+ */
+ for (cp = buf, ep = buf + len; cp < ep; cp++) {
+ if (cp + 5 < ep && memcmp(cp, "honk!", 5) == 0) {
+ ret = false;
+ break;
+ }
+ }
+ return ret;
+}
+
+sudo_dso_public struct policy_plugin sample_policy = {
+ SUDO_POLICY_PLUGIN,
+ SUDO_API_VERSION,
+ policy_open,
+ policy_close,
+ policy_version,
+ policy_check,
+ policy_list,
+ NULL, /* validate */
+ NULL, /* invalidate */
+ NULL, /* init_session */
+ NULL, /* register_hooks */
+ NULL, /* deregister_hooks */
+ NULL /* event_alloc() filled in by sudo */
+};
+
+/*
+ * Note: This plugin does not differentiate between tty and pipe I/O.
+ * It all gets logged to the same file.
+ */
+sudo_dso_public struct io_plugin sample_io = {
+ SUDO_IO_PLUGIN,
+ SUDO_API_VERSION,
+ io_open,
+ io_close,
+ io_version,
+ io_log_input, /* tty input */
+ io_log_output, /* tty output */
+ io_log_input, /* command stdin if not tty */
+ io_log_output, /* command stdout if not tty */
+ io_log_output, /* command stderr if not tty */
+ NULL, /* register_hooks */
+ NULL, /* deregister_hooks */
+ NULL, /* change_winsize */
+ NULL, /* log_suspend */
+ NULL /* event_alloc() filled in by sudo */
+};
diff --git a/plugins/sample/sample_plugin.exp b/plugins/sample/sample_plugin.exp
new file mode 100644
index 0000000..9f85094
--- /dev/null
+++ b/plugins/sample/sample_plugin.exp
@@ -0,0 +1,2 @@
+sample_policy
+sample_io
diff --git a/plugins/sample_approval/Makefile.in b/plugins/sample_approval/Makefile.in
new file mode 100644
index 0000000..3ffe465
--- /dev/null
+++ b/plugins/sample_approval/Makefile.in
@@ -0,0 +1,232 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2020-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+devdir = @devdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+top_srcdir = @top_srcdir@
+scriptdir = $(top_srcdir)/scripts
+incdir = $(top_srcdir)/include
+cross_compiling = @CROSS_COMPILING@
+
+# Compiler & tools to use
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+SED = @SED@
+AWK = @AWK@
+
+# Our install program supports extra flags...
+INSTALL = $(SHELL) $(scriptdir)/install-sh -c
+INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
+INSTALL_BACKUP = @INSTALL_BACKUP@
+
+# Libraries
+LT_LIBS = $(top_builddir)/lib/util/libsudo_util.la
+LIBS = $(LT_LIBS)
+
+# C preprocessor flags
+CPPFLAGS = -I$(incdir) -I$(top_builddir) @CPPFLAGS@
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+
+# Flags to pass to the link stage
+LDFLAGS = @LDFLAGS@
+LT_LDFLAGS = @LT_LDFLAGS@ @LT_LDEXPORTS@
+
+# Flags to pass to libtool
+LTFLAGS = --tag=disable-static
+
+# Address sanitizer flags
+ASAN_CFLAGS = @ASAN_CFLAGS@
+ASAN_LDFLAGS = @ASAN_LDFLAGS@
+
+# PIE flags
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+
+# Stack smashing protection flags
+HARDENING_CFLAGS = @HARDENING_CFLAGS@
+HARDENING_LDFLAGS = @HARDENING_LDFLAGS@
+
+# cppcheck options, usually set in the top-level Makefile
+CPPCHECK_OPTS = -q --enable=warning,performance,portability --suppress=constStatement --suppress=compareBoolExpressionWithInt --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
+
+# splint options, usually set in the top-level Makefile
+SPLINT_OPTS = -D__restrict= -checks
+
+# PVS-studio options
+PVS_CFG = $(top_srcdir)/PVS-Studio.cfg
+PVS_IGNORE = 'V707,V011,V002,V536'
+PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
+
+# Where to install things...
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+sysconfdir = @sysconfdir@
+adminconfdir = @adminconfdir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+localstatedir = @localstatedir@
+plugindir = @plugindir@
+
+# File mode and map file to use for shared libraries/objects
+shlib_enable = @SHLIB_ENABLE@
+shlib_mode = @SHLIB_MODE@
+shlib_exp = $(srcdir)/sample_approval.exp
+shlib_map = sample_approval.map
+shlib_opt = sample_approval.opt
+
+# User and group ids the installed files should be "owned" by
+install_uid = 0
+install_gid = 0
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+OBJS = sample_approval.lo
+
+IOBJS = $(OBJS:.lo=.i)
+
+POBJS = $(IOBJS:.i=.plog)
+
+LIBOBJDIR = $(top_builddir)/@ac_config_libobj_dir@/
+
+VERSION = @PACKAGE_VERSION@
+
+all: sample_approval.la
+
+depend:
+ $(scriptdir)/mkdep.pl --srcdir=$(top_srcdir) \
+ --builddir=$(abs_top_builddir) plugins/sample_approval/Makefile.in
+ cd $(top_builddir) && ./config.status --file plugins/sample_approval/Makefile
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file plugins/sample_approval/Makefile
+
+.SUFFIXES: .c .h .i .lo .plog
+
+.c.lo:
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.i:
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+
+.i.plog:
+ ifile=$<; rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $${ifile%i}c --i-file $< --output-file $@
+
+$(shlib_map): $(shlib_exp)
+ @$(AWK) 'BEGIN { print "{\n\tglobal:" } { print "\t\t"$$0";" } END { print "\tlocal:\n\t\t*;\n};" }' $(shlib_exp) > $@
+
+$(shlib_opt): $(shlib_exp)
+ @$(SED) 's/^/+e /' $(shlib_exp) > $@
+
+sample_approval.la: $(OBJS) $(LT_LIBS) @LT_LDDEP@
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) $(ASAN_LDFLAGS) $(HARDENING_LDFLAGS) $(LT_LDFLAGS) -o $@ $(OBJS) $(LIBS) -module -avoid-version -rpath $(plugindir) -shrext .so
+
+pre-install:
+
+install: install-plugin
+
+install-dirs:
+ $(SHELL) $(scriptdir)/mkinstalldirs $(DESTDIR)$(plugindir)
+
+install-binaries:
+
+install-includes:
+
+install-doc:
+
+install-plugin: install-dirs sample_approval.la
+ if [ X"$(shlib_enable)" = X"yes" ]; then \
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) $(INSTALL_OWNER) -m $(shlib_mode) sample_approval.la $(DESTDIR)$(plugindir); \
+ fi
+
+install-fuzzer:
+
+uninstall:
+ -$(LIBTOOL) $(LTFLAGS) --mode=uninstall rm -f $(DESTDIR)$(plugindir)/sample_approval.la
+ -test -z "$(INSTALL_BACKUP)" || \
+ rm -f $(DESTDIR)$(plugindir)/sample_approval.so$(INSTALL_BACKUP)
+
+splint:
+ splint $(SPLINT_OPTS) -I$(incdir) -I$(top_builddir) $(srcdir)/*.c
+
+cppcheck:
+ cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) $(srcdir)/*.c
+
+pvs-log-files: $(POBJS)
+
+pvs-studio: $(POBJS)
+ plog-converter $(PVS_LOG_OPTS) $(POBJS)
+
+fuzz:
+
+check-fuzzer:
+
+check: check-fuzzer
+
+check-verbose: check
+
+clean:
+ -$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f *.lo *.o *.la *.a
+ -rm -f *.i *.plog stamp-* core *.core core.*
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile .libs $(shlib_map) $(shlib_opt)
+
+clobber: distclean
+
+realclean: distclean
+ rm -f TAGS tags
+
+cleandir: realclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean
+
+# Autogenerated dependencies, do not modify
+getgrent.lo: $(srcdir)/getgrent.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/getgrent.c
+getgrent.i: $(srcdir)/getgrent.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+getgrent.plog: getgrent.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/getgrent.c --i-file $< --output-file $@
+sample_approval.lo: $(srcdir)/sample_approval.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_plugin.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sample_approval.c
+sample_approval.i: $(srcdir)/sample_approval.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_plugin.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sample_approval.plog: sample_approval.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sample_approval.c --i-file $< --output-file $@
diff --git a/plugins/sample_approval/sample_approval.c b/plugins/sample_approval/sample_approval.c
new file mode 100644
index 0000000..eb08f9c
--- /dev/null
+++ b/plugins/sample_approval/sample_approval.c
@@ -0,0 +1,169 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudo_conf.h>
+#include <sudo_debug.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_plugin.h>
+#include <sudo_util.h>
+
+static int approval_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
+sudo_printf_t sudo_printf;
+
+static int
+sample_approval_open(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t plugin_printf, char * const settings[],
+ char * const user_info[], int submit_optind, char * const submit_argv[],
+ char * const submit_envp[], char * const plugin_options[],
+ const char **errstr)
+{
+ struct sudo_conf_debug_file_list debug_files =
+ TAILQ_HEAD_INITIALIZER(debug_files);
+ struct sudo_debug_file *debug_file;
+ const char *cp, *plugin_path = NULL;
+ char * const *cur;
+ int ret = -1;
+ debug_decl_vars(sample_approval_open, SUDO_DEBUG_PLUGIN);
+
+ sudo_printf = plugin_printf;
+
+ /* Initialize the debug subsystem. */
+ for (cur = settings; (cp = *cur) != NULL; cur++) {
+ if (strncmp(cp, "debug_flags=", sizeof("debug_flags=") - 1) == 0) {
+ cp += sizeof("debug_flags=") - 1;
+ if (sudo_debug_parse_flags(&debug_files, cp) == -1)
+ goto oom;
+ continue;
+ }
+ if (strncmp(cp, "plugin_path=", sizeof("plugin_path=") - 1) == 0) {
+ plugin_path = cp + sizeof("plugin_path=") - 1;
+ continue;
+ }
+ }
+ if (plugin_path != NULL && !TAILQ_EMPTY(&debug_files)) {
+ approval_debug_instance =
+ sudo_debug_register(plugin_path, NULL, NULL, &debug_files, -1);
+ if (approval_debug_instance == SUDO_DEBUG_INSTANCE_ERROR) {
+ *errstr = U_("unable to initialize debugging");
+ goto done;
+ }
+ sudo_debug_enter(__func__, __FILE__, __LINE__, sudo_debug_subsys);
+ }
+
+ ret = 1;
+ goto done;
+
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ *errstr = U_("unable to allocate memory");
+
+done:
+ while ((debug_file = TAILQ_FIRST(&debug_files)) != NULL) {
+ TAILQ_REMOVE(&debug_files, debug_file, entries);
+ free(debug_file->debug_file);
+ free(debug_file->debug_flags);
+ free(debug_file);
+ }
+
+ debug_return_int(ret);
+}
+
+static void
+sample_approval_close(void)
+{
+ debug_decl(sample_approval_close, SUDO_DEBUG_PLUGIN);
+
+ /* Nothing here, we could store a NULL pointer instead. */
+
+ debug_return;
+}
+
+static int
+sample_approval_check(char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr)
+{
+ struct tm tm;
+ time_t now;
+ int ret = 0;
+ debug_decl(sample_approval_check, SUDO_DEBUG_PLUGIN);
+
+ /*
+ * Only approve requests that are within business hours,
+ * which are 9am - 5pm local time. Does not check holidays.
+ */
+ if (time(&now) == -1 || localtime_r(&now, &tm) == NULL)
+ goto done;
+ if (tm.tm_wday < 1 || tm.tm_wday > 5) {
+ /* bad weekday */
+ goto done;
+ }
+ if (tm.tm_hour < 9 || tm.tm_hour > 17 ||
+ (tm.tm_hour == 17 && tm.tm_min > 0)) {
+ /* bad hour */
+ goto done;
+ }
+ ret = 1;
+
+done:
+ if (ret == 0) {
+ *errstr = U_("You are not allowed to use sudo outside business hours");
+ sudo_printf(SUDO_CONV_ERROR_MSG, "%s\n", *errstr);
+ }
+
+ debug_return_int(ret);
+}
+
+static int
+sample_approval_show_version(int verbose)
+{
+ debug_decl(approval_show_version, SUDO_DEBUG_PLUGIN);
+
+ sudo_printf(SUDO_CONV_INFO_MSG, "sample approval plugin version %s\n",
+ PACKAGE_VERSION);
+
+ debug_return_int(true);
+}
+
+sudo_dso_public struct approval_plugin sample_approval = {
+ SUDO_APPROVAL_PLUGIN,
+ SUDO_API_VERSION,
+ sample_approval_open,
+ sample_approval_close,
+ sample_approval_check,
+ sample_approval_show_version
+};
diff --git a/plugins/sample_approval/sample_approval.exp b/plugins/sample_approval/sample_approval.exp
new file mode 100644
index 0000000..ea9cd65
--- /dev/null
+++ b/plugins/sample_approval/sample_approval.exp
@@ -0,0 +1 @@
+sample_approval
diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in
new file mode 100644
index 0000000..71218db
--- /dev/null
+++ b/plugins/sudoers/Makefile.in
@@ -0,0 +1,3546 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 1996, 1998-2005, 2007-2023
+# Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# Sponsored in part by the Defense Advanced Research Projects
+# Agency (DARPA) and Air Force Research Laboratory, Air Force
+# Materiel Command, USAF, under agreement number F39502-99-1-0512.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+devdir = @devdir@
+scriptdir = $(top_srcdir)/scripts
+authdir = $(srcdir)/auth
+incdir = $(top_srcdir)/include
+docdir = @docdir@
+libdir = @libdir@
+rundir = @rundir@
+vardir = @vardir@
+cross_compiling = @CROSS_COMPILING@
+
+# Compiler & tools to use
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+SHA1SUM = @SHA1SUM@
+FLEX = @FLEX@
+YACC = @YACC@
+EGREP = @EGREP@
+SED = @SED@
+AWK = @AWK@
+
+# Our install program supports extra flags...
+INSTALL = $(SHELL) $(scriptdir)/install-sh -c
+INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
+INSTALL_BACKUP = @INSTALL_BACKUP@
+
+# Libraries
+LIBFUZZSTUB = $(top_builddir)/lib/fuzzstub/libsudo_fuzzstub.la
+LIBEVENTLOG = $(top_builddir)/lib/eventlog/libsudo_eventlog.la
+LIBIOLOG = $(top_builddir)/lib/iolog/libsudo_iolog.la $(LIBEVENTLOG)
+LIBLOGSRV = @LIBLOGSRV@
+LIBUTIL = $(top_builddir)/lib/util/libsudo_util.la
+LIBS = $(LIBUTIL)
+NET_LIBS = @NET_LIBS@
+SUDOERS_LIBS = @SUDOERS_LIBS@ @AFS_LIBS@ @GETGROUPS_LIB@ @LIBTLS@ $(NET_LIBS) $(LIBIOLOG) $(LIBLOGSRV)
+REPLAY_LIBS = @REPLAY_LIBS@ $(LIBIOLOG)
+VISUDO_LIBS = $(NET_LIBS)
+CVTSUDOERS_LIBS = $(NET_LIBS)
+TESTSUDOERS_LIBS = $(NET_LIBS)
+
+# C preprocessor defines
+CPPDEFS = -DLIBDIR=\"$(libdir)\" -DLOCALEDIR=\"$(localedir)\" \
+ -D_PATH_SUDOERS=\"@sudoers_path@\" \
+ -D_PATH_CVTSUDOERS_CONF=\"@cvtsudoers_conf@\" \
+ -DSUDOERS_UID=$(sudoers_uid) -DSUDOERS_GID=$(sudoers_gid) \
+ -DSUDOERS_MODE=$(sudoers_mode)
+
+# C preprocessor flags
+CPPFLAGS = -I$(incdir) -I$(top_builddir) -I$(devdir) -I$(srcdir) \
+ $(CPPDEFS) @CPPFLAGS@
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+
+# Flags to pass to the link stage
+LDFLAGS = @LDFLAGS@
+LT_LDFLAGS = @SUDOERS_LDFLAGS@ @LT_LDFLAGS@ @LT_LDEXPORTS@
+
+# Flags to pass to libtool
+LTFLAGS =
+
+# Address sanitizer flags
+ASAN_CFLAGS = @ASAN_CFLAGS@
+ASAN_LDFLAGS = @ASAN_LDFLAGS@
+
+# PIE flags
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+
+# Stack smashing protection flags
+HARDENING_CFLAGS = @HARDENING_CFLAGS@
+HARDENING_LDFLAGS = @HARDENING_LDFLAGS@
+
+# cppcheck options, usually set in the top-level Makefile
+CPPCHECK_OPTS = -q --enable=warning,performance,portability --suppress=constStatement --suppress=compareBoolExpressionWithInt --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
+
+# splint options, usually set in the top-level Makefile
+SPLINT_OPTS = -D__restrict= -checks
+
+# PVS-studio options
+PVS_CFG = $(top_srcdir)/PVS-Studio.cfg
+PVS_IGNORE = 'V707,V011,V002,V536'
+PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
+
+# Where to install things...
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+sysconfdir = @sysconfdir@
+adminconfdir = @adminconfdir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+
+# File mode and map file to use for shared libraries/objects
+shlib_enable = @SHLIB_ENABLE@
+shlib_mode = @SHLIB_MODE@
+shlib_exp = $(srcdir)/sudoers.exp
+shlib_map = sudoers.map
+shlib_opt = sudoers.opt
+
+# Directory in which to install the sudoers plugin
+plugindir = @plugindir@
+
+# User and group ids the installed files should be "owned" by
+install_uid = 0
+install_gid = 0
+
+# User, group, and mode the sudoers file should be "owned" by (configure)
+sudoers_uid = @SUDOERS_UID@
+sudoers_gid = @SUDOERS_GID@
+sudoers_mode = @SUDOERS_MODE@
+
+# Set to non-empty for development mode
+DEVEL = @DEVEL@
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+PROGS = sudoers.la visudo sudoreplay cvtsudoers testsudoers
+
+# Regression tests
+TEST_PROGS = check_addr check_base64 check_digest check_editor \
+ check_env_pattern check_exptilde check_fill check_gentime \
+ check_iolog_plugin check_serialize_list \
+ check_starttime check_unesc @SUDOERS_TEST_PROGS@
+TEST_VERBOSE =
+HARNESS = $(SHELL) regress/harness $(TEST_VERBOSE)
+
+# Fuzzers
+LIB_FUZZING_ENGINE = @FUZZ_ENGINE@
+FUZZ_PROGS = fuzz_policy fuzz_sudoers fuzz_sudoers_ldif
+FUZZ_SEED_CORPUS = ${FUZZ_PROGS:=_seed_corpus.zip}
+FUZZ_LIBS = libparsesudoers.la @SUDOERS_LIBS@ $(LIB_FUZZING_ENGINE)
+FUZZ_LDFLAGS = @SUDOERS_LDFLAGS@
+FUZZ_MAX_LEN = 4096
+FUZZ_RUNS = 8192
+FUZZ_VERBOSE =
+
+AUTH_OBJS = sudo_auth.lo @AUTH_OBJS@
+
+LIBPARSESUDOERS_OBJS = alias.lo b64_decode.lo canon_path.lo defaults.lo \
+ digestname.lo exptilde.lo filedigest.lo \
+ gentime.lo gram.lo match.lo match_addr.lo \
+ match_command.lo match_digest.lo parser_warnx.lo \
+ pwutil.lo pwutil_impl.lo redblack.lo \
+ resolve_cmnd.lo strlist.lo sudoers_debug.lo \
+ timeout.lo timestr.lo toke.lo toke_util.lo
+
+LIBPARSESUDOERS_IOBJS = $(LIBPARSESUDOERS_OBJS:.lo=.i) passwd.i
+
+SUDOERS_OBJS = $(AUTH_OBJS) audit.lo boottime.lo check.lo check_util.lo \
+ display.lo editor.lo env.lo sudoers_hooks.lo env_pattern.lo \
+ file.lo find_path.lo fmtsudoers.lo gc.lo goodpath.lo \
+ group_plugin.lo interfaces.lo iolog.lo iolog_path_escapes.lo \
+ locale.lo log_client.lo logging.lo lookup.lo pivot.lo \
+ policy.lo prompt.lo serialize_list.lo set_perms.lo \
+ sethost.lo starttime.lo strlcpy_unesc.lo strvec_join.lo \
+ sudo_nss.lo sudoers.lo sudoers_cb.lo sudoers_ctx_free.lo \
+ timestamp.lo unesc_str.lo @SUDOERS_OBJS@
+
+SUDOERS_IOBJS = $(SUDOERS_OBJS:.lo=.i)
+
+VISUDO_OBJS = check_aliases.o editor.lo find_path.lo gc.lo goodpath.lo \
+ locale.lo sethost.lo stubs.o sudo_printf.o sudoers_ctx_free.lo \
+ visudo.o visudo_cb.o
+
+VISUDO_IOBJS = sudo_printf.i visudo.i
+
+CVTSUDOERS_OBJS = b64_encode.o cvtsudoers.o cvtsudoers_csv.o \
+ cvtsudoers_json.o cvtsudoers_ldif.o cvtsudoers_merge.o \
+ cvtsudoers_pwutil.o fmtsudoers.lo fmtsudoers_cvt.lo \
+ ldap_util.lo locale.lo parse_ldif.o sethost.lo \
+ stubs.o sudo_printf.o sudoers_ctx_free.lo \
+ testsudoers_pwutil.o tsgetgrpw.o tsgetusershell.o
+
+CVTSUDOERS_IOBJS = cvtsudoers.i cvtsudoers_csv.i cvtsudoers_json.i \
+ cvtsudoers_ldif.i cvtsudoers_merge.i cvtsudoers_pwutil.i
+
+REPLAY_OBJS = getdate.o sudoreplay.o
+
+REPLAY_IOBJS = $(REPLAY_OBJS:.o=.i)
+
+TEST_OBJS = check_util.lo fmtsudoers.lo fmtsudoers_cvt.lo group_plugin.lo \
+ interfaces.lo ldap_util.lo locale.lo lookup.lo net_ifs.o \
+ parse_ldif.o sethost.lo sudo_printf.o sudoers_ctx_free.lo \
+ testsudoers.o testsudoers_pwutil.o tsgetgrpw.o tsgetusershell.o
+
+IOBJS = $(LIBPARSESUDOERS_IOBJS) $(SUDOERS_IOBJS) $(VISUDO_IOBJS) \
+ $(CVTSUDOERS_IOBJS) $(REPLAY_IOBJS)
+
+POBJS = $(IOBJS:.i=.plog)
+
+TSDUMP_OBJS = tsdump.o sudoers_debug.lo locale.lo
+
+CHECK_ADDR_OBJS = check_addr.o interfaces.lo match_addr.lo sudoers_debug.lo \
+ sudo_printf.o
+
+CHECK_BASE64_OBJS = check_base64.o b64_decode.lo b64_encode.o sudoers_debug.lo
+
+CHECK_DIGEST_OBJS = check_digest.o filedigest.lo digestname.lo sudoers_debug.lo
+
+CHECK_EDITOR_OBJS = check_editor.o gc.lo editor.lo sudoers_debug.lo
+
+CHECK_ENV_MATCH_OBJS = check_env_pattern.o env_pattern.lo sudoers_debug.lo
+
+CHECK_EXPTILDE_OBJS = check_exptilde.o exptilde.lo pwutil.lo pwutil_impl.lo redblack.lo sudoers_debug.lo
+
+CHECK_FILL_OBJS = check_fill.o toke_util.lo sudoers_debug.lo
+
+CHECK_GENTIME_OBJS = check_gentime.o gentime.lo sudoers_debug.lo
+
+CHECK_IOLOG_PLUGIN_OBJS = check_iolog_plugin.o iolog.lo log_client.lo \
+ locale.lo pwutil.lo pwutil_impl.lo redblack.lo \
+ strlist.lo sudoers_debug.lo unesc_str.lo
+
+CHECK_SYMBOLS_OBJS = check_symbols.o
+
+CHECK_STARTTIME_OBJS = check_starttime.o starttime.lo sudoers_debug.lo
+
+CHECK_UNESC_OBJS = check_unesc.o strlcpy_unesc.lo strvec_join.lo \
+ sudoers_debug.lo unesc_str.lo
+
+CHECK_SERIALIZE_LIST_OBJS = check_serialize_list.lo serialize_list.lo \
+ sudoers_debug.lo
+
+FUZZ_POLICY_OBJS = editor.lo env.lo env_pattern.lo fuzz_policy.o \
+ fuzz_stubs.o gc.lo iolog_path_escapes.lo locale.lo \
+ policy.lo sethost.lo serialize_list.lo \
+ strlcpy_unesc.lo strvec_join.lo sudoers.lo \
+ sudoers_cb.lo sudoers_ctx_free.lo sudoers_hooks.lo
+
+FUZZ_POLICY_CORPUS = $(srcdir)/regress/corpus/seed/policy/policy.*
+
+FUZZ_SUDOERS_OBJS = check_aliases.o display.lo fuzz_stubs.o fuzz_sudoers.o \
+ fmtsudoers.lo locale.lo lookup.lo sudoers_ctx_free.lo
+
+FUZZ_SUDOERS_CORPUS = $(top_builddir)/examples/sudoers \
+ $(srcdir)/regress/sudoers/test1.in \
+ $(srcdir)/regress/sudoers/test2.in \
+ $(srcdir)/regress/sudoers/test3.in \
+ $(srcdir)/regress/sudoers/test4.in \
+ $(srcdir)/regress/sudoers/test5.in \
+ $(srcdir)/regress/sudoers/test6.in \
+ $(srcdir)/regress/sudoers/test7.in \
+ $(srcdir)/regress/sudoers/test8.in \
+ $(srcdir)/regress/sudoers/test9.in \
+ $(srcdir)/regress/sudoers/test10.in \
+ $(srcdir)/regress/sudoers/test11.in \
+ $(srcdir)/regress/sudoers/test12.in \
+ $(srcdir)/regress/sudoers/test13.in \
+ $(srcdir)/regress/sudoers/test14.in \
+ $(srcdir)/regress/sudoers/test15.in \
+ $(srcdir)/regress/sudoers/test16.in \
+ $(srcdir)/regress/sudoers/test17.in \
+ $(srcdir)/regress/sudoers/test18.in \
+ $(srcdir)/regress/sudoers/test19.in \
+ $(srcdir)/regress/sudoers/test20.in \
+ $(srcdir)/regress/sudoers/test21.in \
+ $(srcdir)/regress/sudoers/test22.in \
+ $(srcdir)/regress/sudoers/test23.in \
+ $(srcdir)/regress/sudoers/test24.in \
+ $(srcdir)/regress/sudoers/test25.in
+
+FUZZ_SUDOERS_LDIF_OBJS = fuzz_stubs.o fuzz_sudoers_ldif.o parse_ldif.o \
+ ldap_util.lo fmtsudoers.lo locale.lo
+
+FUZZ_SUDOERS_LDIF_CORPUS = $(srcdir)/regress/sudoers/*.ldif.ok \
+ $(srcdir)/regress/corpus/seed/ldif/*.ldif
+
+VERSION = @PACKAGE_VERSION@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+
+all: $(PROGS)
+
+.SUFFIXES: .c .h .i .l .lo .o .plog .y
+
+.c.o:
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.lo:
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.i:
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+
+.i.plog:
+ ifile=$<; rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $${ifile%i}c --i-file $< --output-file $@
+
+$(shlib_map): $(shlib_exp)
+ @$(AWK) 'BEGIN { print "{\n\tglobal:" } { print "\t\t"$$0";" } END { print "\tlocal:\n\t\t*;\n};" }' $(shlib_exp) > $@
+
+$(shlib_opt): $(shlib_exp)
+ @$(SED) 's/^/+e /' $(shlib_exp) > $@
+
+# Prevent default rules from building .c files from .l and .y files
+.l.c:
+ @true
+
+.y.c:
+ @true
+
+depend: tsgetusershell.c
+ $(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
+ --builddir=$(abs_top_builddir) plugins/sudoers/Makefile.in
+ cd $(top_builddir) && ./config.status --file plugins/sudoers/Makefile
+
+harness: $(srcdir)/regress/harness.in
+ cd $(top_builddir) && ./config.status --file plugins/sudoers/regress/harness && chmod +x plugins/sudoers/regress/harness
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file plugins/sudoers/Makefile
+
+libparsesudoers.la: $(LIBPARSESUDOERS_OBJS)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LIBPARSESUDOERS_OBJS) -no-install
+
+sudoers.la: $(SUDOERS_OBJS) $(LIBIOLOG) $(LIBLOGSRV) libparsesudoers.la @LT_LDDEP@
+ case "$(LT_LDFLAGS)" in \
+ *-no-install*) \
+ $(LIBTOOL) $(LTFLAGS) @SUDOERS_LT_STATIC@ --mode=link $(CC) $(LDFLAGS) $(LT_LDFLAGS) -o $@ $(SUDOERS_OBJS) libparsesudoers.la $(SUDOERS_LIBS) -module;; \
+ *) \
+ $(LIBTOOL) $(LTFLAGS) @SUDOERS_LT_STATIC@ --mode=link $(CC) $(LDFLAGS) $(ASAN_LDFLAGS) $(HARDENING_LDFLAGS) $(LT_LDFLAGS) -o $@ $(SUDOERS_OBJS) libparsesudoers.la $(SUDOERS_LIBS) -module -avoid-version -rpath $(plugindir) -shrext .so;; \
+ esac
+
+visudo: libparsesudoers.la $(VISUDO_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(VISUDO_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) libparsesudoers.la $(LIBS) $(VISUDO_LIBS)
+
+cvtsudoers: libparsesudoers.la $(CVTSUDOERS_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CVTSUDOERS_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) libparsesudoers.la $(LIBS) $(CVTSUDOERS_LIBS)
+
+sudoreplay: timestr.lo $(REPLAY_OBJS) $(LIBIOLOG)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(REPLAY_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) timestr.lo $(REPLAY_LIBS)
+
+testsudoers: libparsesudoers.la $(TEST_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(TEST_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) libparsesudoers.la $(LIBS) $(TESTSUDOERS_LIBS)
+
+tsdump: $(TSDUMP_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(TSDUMP_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS)
+
+check_addr: $(CHECK_ADDR_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_ADDR_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS) $(NET_LIBS)
+
+check_base64: $(CHECK_BASE64_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_BASE64_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS)
+
+check_digest: $(CHECK_DIGEST_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_DIGEST_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS)
+
+check_editor: $(CHECK_EDITOR_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_EDITOR_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS)
+
+check_env_pattern: $(CHECK_ENV_MATCH_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_ENV_MATCH_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS)
+
+check_exptilde: $(CHECK_EXPTILDE_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_EXPTILDE_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS)
+
+check_fill: $(CHECK_FILL_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_FILL_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS)
+
+check_gentime: $(CHECK_GENTIME_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_GENTIME_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS)
+
+check_iolog_plugin: $(CHECK_IOLOG_PLUGIN_OBJS) $(LIBUTIL) $(LIBIOLOG) $(LIBLOGSRV)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_PLUGIN_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBIOLOG) $(LIBLOGSRV) @LIBTLS@
+
+check_serialize_list: $(CHECK_SERIALIZE_LIST_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_SERIALIZE_LIST_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS)
+
+check_starttime: $(CHECK_STARTTIME_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_STARTTIME_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS)
+
+check_unesc: $(CHECK_UNESC_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_UNESC_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS)
+
+# We need to link check_symbols with -lpthread on HP-UX since LDAP uses threads
+check_symbols: $(CHECK_SYMBOLS_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_SYMBOLS_OBJS) $(CHECK_SYMBOLS_LDFLAGS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS) @SUDO_LIBS@
+
+fuzz_policy: $(FUZZ_POLICY_OBJS) libparsesudoers.la $(LIBEVENTLOG) $(LIBUTIL) $(LIBFUZZSTUB)
+ $(LIBTOOL) $(LTFLAGS) --mode=link @FUZZ_LD@ -o $@ $(FUZZ_POLICY_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(FUZZ_LDFLAGS) $(FUZZ_LIBS) $(LIBEVENTLOG)
+
+fuzz_sudoers: $(FUZZ_SUDOERS_OBJS) libparsesudoers.la $(LIBUTIL) $(LIBFUZZSTUB)
+ $(LIBTOOL) $(LTFLAGS) --mode=link @FUZZ_LD@ -o $@ $(FUZZ_SUDOERS_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(FUZZ_LDFLAGS) $(FUZZ_LIBS) $(LIBUTIL)
+
+fuzz_sudoers_ldif: $(FUZZ_SUDOERS_LDIF_OBJS) libparsesudoers.la $(LIBUTIL) $(LIBFUZZSTUB)
+ $(LIBTOOL) $(LTFLAGS) --mode=link @FUZZ_LD@ -o $@ $(FUZZ_SUDOERS_LDIF_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(FUZZ_LDFLAGS) $(FUZZ_LIBS) $(LIBUTIL)
+
+fuzz_policy_seed_corpus.zip:
+ tdir=fuzz_policy.$$$$; \
+ mkdir $$tdir; \
+ for f in $(FUZZ_POLICY_CORPUS); do \
+ cp $$f $$tdir/`$(SHA1SUM) $$f | $(SED) -e 's/^.*= *//' -e 's/ .*//'`; \
+ done; \
+ zip -j $@ $$tdir/*; \
+ rm -rf $$tdir
+
+run-fuzz_policy: fuzz_policy
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ umask 022; \
+ corpus=regress/corpus/policy; \
+ mkdir -p $$corpus; \
+ for f in $(FUZZ_POLICY_CORPUS); do \
+ cp $$f $$corpus; \
+ done; \
+ ./fuzz_policy -dict=$(srcdir)/regress/fuzz/fuzz_policy.dict -max_len=$(FUZZ_MAX_LEN) -runs=$(FUZZ_RUNS) $(FUZZ_VERBOSE) $$corpus
+
+fuzz_sudoers_seed_corpus.zip:
+ tdir=fuzz_sudoers.$$$$; \
+ mkdir $$tdir; \
+ for f in $(FUZZ_SUDOERS_CORPUS); do \
+ cp $$f $$tdir/`$(SHA1SUM) $$f | $(SED) -e 's/^.*= *//' -e 's/ .*//'`; \
+ done; \
+ zip -j $@ $$tdir/*; \
+ rm -rf $$tdir
+
+run-fuzz_sudoers: fuzz_sudoers
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ umask 022; \
+ corpus=regress/corpus/sudoers; \
+ mkdir -p $$corpus; \
+ for f in $(FUZZ_SUDOERS_CORPUS); do \
+ cp $$f $$corpus; \
+ done; \
+ ./fuzz_sudoers -dict=$(srcdir)/regress/fuzz/fuzz_sudoers.dict -max_len=$(FUZZ_MAX_LEN) -runs=$(FUZZ_RUNS) $(FUZZ_VERBOSE) $$corpus
+
+fuzz_sudoers_ldif_seed_corpus.zip:
+ tdir=fuzz_sudoers_ldif.$$$$; \
+ mkdir $$tdir; \
+ for f in $(FUZZ_SUDOERS_LDIF_CORPUS); do \
+ cp $$f $$tdir/`$(SHA1SUM) $$f | $(SED) -e 's/^.*= *//' -e 's/ .*//'`; \
+ done; \
+ zip -j $@ $$tdir/*; \
+ rm -rf $$tdir
+
+run-fuzz_sudoers_ldif: fuzz_sudoers_ldif
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ umask 022; \
+ corpus=regress/corpus/sudoers_ldif; \
+ mkdir -p $$corpus; \
+ for f in $(FUZZ_SUDOERS_LDIF_CORPUS); do \
+ cp $$f $$corpus; \
+ done; \
+ ./fuzz_sudoers_ldif -dict=$(srcdir)/regress/fuzz/fuzz_sudoers_ldif.dict -max_len=$(FUZZ_MAX_LEN) -runs=$(FUZZ_RUNS) $(FUZZ_VERBOSE) $$corpus
+
+GENERATED = gram.h gram.c toke.c def_data.c def_data.h getdate.c
+
+prologue:
+ echo "/*" > $@
+ echo " * This is an open source non-commercial project. Dear PVS-Studio, please check it." >> $@
+ echo " * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com" >> $@
+ echo " */" >> $@
+ echo "" >> $@
+ echo "#include <config.h>" >> $@
+
+$(devdir)/gram.c $(devdir)/gram.h: $(srcdir)/gram.y prologue
+ @if [ -n "$(DEVEL)" ]; then \
+ if test "$(srcdir)" = "."; then \
+ gram_y="gram.y"; \
+ else \
+ gram_y="$(srcdir)/gram.y"; \
+ fi; \
+ cmd='$(YACC) -d -p sudoers '"$$gram_y"'; cp prologue $(devdir)/gram.c; $(SED) -e "s/^\\(#line .*\\) \"y\\.tab\\.c\"/\1 \"gram.c\"/" -e "/^# *include <limits.h>/{N;s/__STDC_VERSION__ && 199901 <= __STDC_VERSION__/HAVE_STDINT_H/;}" y.tab.c >> $(devdir)/gram.c; sed -e "s/^\\(#line .*\\) \"y\\.tab\\.h\"/\1 \"gram.h\"/" y.tab.h > $(devdir)/gram.h; rm -f y.tab.[ch]'; \
+ echo "$$cmd"; eval $$cmd; \
+ fi
+
+$(devdir)/toke.c: $(srcdir)/toke.l prologue
+ @if [ -n "$(DEVEL)" ]; then \
+ if test "$(srcdir)" = "."; then \
+ toke_l="toke.l"; \
+ else \
+ toke_l="$(srcdir)/toke.l"; \
+ fi; \
+ cmd='$(FLEX) '"$$toke_l"'; cp prologue $(devdir)/toke.c; $(SED) -e "s/^\\(#line .*\\) \"lex\\.sudoers\\.c\"/\1 \"toke.c\"/" -e "s:/\* *FALLTHROUGH *\*/:FALLTHROUGH;:" lex.sudoers.c >> $(devdir)/toke.c; rm -f lex.sudoers.c'; \
+ echo "$$cmd"; eval $$cmd; \
+ fi
+
+$(devdir)/getdate.c: $(srcdir)/getdate.y prologue
+ @if [ -n "$(DEVEL)" ]; then \
+ echo "expect 10 shift/reduce conflicts"; \
+ if test "$(srcdir)" = "."; then \
+ getdate_y="getdate.y"; \
+ else \
+ getdate_y="$(srcdir)/getdate.y"; \
+ fi; \
+ cmd='$(YACC) '"$$getdate_y"'; cp prologue $(devdir)/getdate.c; $(SED) -e "s/^\\(#line .*\\) \"y\\.tab\\.c\"/\1 \"getdate.c\"/" -e "/^# *include <limits.h>/{N;s/__STDC_VERSION__ && 199901 <= __STDC_VERSION__/HAVE_STDINT_H/;}" y.tab.c >> $(devdir)/getdate.c; rm -f y.tab.c'; \
+ echo "$$cmd"; eval $$cmd; \
+ fi
+
+$(devdir)/def_data.c $(devdir)/def_data.h: $(srcdir)/def_data.in
+ @if [ -n "$(DEVEL)" ]; then \
+ cmd='AWK=$(AWK) $(SHELL) $(srcdir)/mkdefaults -o $(devdir)/def_data $(srcdir)/def_data.in'; \
+ echo "$$cmd"; eval $$cmd; \
+ fi
+
+tsgetusershell.c: $(top_srcdir)/lib/util/getusershell.c
+ printf '#define TESTSUDOERS\n\n' > $@
+ $(SED) 's/^sudo_/testsudoers_/' $(top_srcdir)/lib/util/getusershell.c >> $@
+
+sudoers: $(srcdir)/sudoers.in
+ cd $(top_builddir) && $(SHELL) config.status --file=plugins/sudoers/$@
+
+pre-install: visudo
+ @if test X"$(cross_compiling)" != X"yes" -a X"$(DESTDIR)" = X""; then \
+ if test -r $(sysconfdir)/sudoers; then \
+ echo "Checking existing sudoers file for syntax errors."; \
+ ./visudo -c -f $(sysconfdir)/sudoers; \
+ fi; \
+ fi
+
+install: install-plugin install-binaries install-sudoers install-doc
+
+install-dirs:
+ $(SHELL) $(scriptdir)/mkinstalldirs $(DESTDIR)$(plugindir) \
+ $(DESTDIR)$(sbindir) $(DESTDIR)$(bindir) \
+ $(DESTDIR)$(sysconfdir) $(DESTDIR)$(docdir) \
+ `echo $(DESTDIR)$(rundir)|$(SED) 's,/[^/]*$$,,'` \
+ `echo $(DESTDIR)$(vardir)|$(SED) 's,/[^/]*$$,,'`
+ $(INSTALL) -d $(INSTALL_OWNER) -m 0711 $(DESTDIR)$(rundir)
+ $(INSTALL) -d $(INSTALL_OWNER) -m 0711 $(DESTDIR)$(vardir)
+ $(INSTALL) -d $(INSTALL_OWNER) -m 0700 $(DESTDIR)$(vardir)/lectured
+
+install-binaries: cvtsudoers sudoreplay visudo install-dirs
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) $(INSTALL_OWNER) -m 0755 cvtsudoers $(DESTDIR)$(bindir)/cvtsudoers
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) $(INSTALL_OWNER) -m 0755 sudoreplay $(DESTDIR)$(bindir)/sudoreplay
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) $(INSTALL_OWNER) -m 0755 visudo $(DESTDIR)$(sbindir)/visudo
+
+install-includes:
+
+install-doc:
+
+install-plugin: sudoers.la install-dirs
+ case "$(LT_LDFLAGS)" in \
+ *-no-install*) ;; \
+ *) if [ X"$(shlib_enable)" = X"yes" ]; then \
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) $(INSTALL_OWNER) -m $(shlib_mode) sudoers.la $(DESTDIR)$(plugindir); \
+ fi;; \
+ esac
+
+install-sudoers: install-dirs
+ $(INSTALL) -d $(INSTALL_OWNER) -m 0750 $(DESTDIR)$(sysconfdir)/sudoers.d
+ $(INSTALL) $(INSTALL_OWNER) -m $(sudoers_mode) sudoers $(DESTDIR)$(sysconfdir)/sudoers.dist
+ test -r $(DESTDIR)$(sysconfdir)/sudoers || \
+ cp -p $(DESTDIR)$(sysconfdir)/sudoers.dist $(DESTDIR)$(sysconfdir)/sudoers
+
+install-fuzzer: $(FUZZ_PROGS) $(FUZZ_SEED_CORPUS)
+ @if test X"$(FUZZ_DESTDIR)" = X""; then \
+ echo "must set FUZZ_DESTDIR for install-fuzzer target"; \
+ else \
+ cp $(FUZZ_PROGS) $(FUZZ_SEED_CORPUS) $(FUZZ_DESTDIR); \
+ cp $(srcdir)/regress/fuzz/*.dict $(FUZZ_DESTDIR); \
+ fi
+
+uninstall:
+ -$(LIBTOOL) $(LTFLAGS) --mode=uninstall rm -f $(DESTDIR)$(plugindir)/sudoers.la
+ -rm -f $(DESTDIR)$(bindir)/cvtsudoers \
+ $(DESTDIR)$(bindir)/sudoreplay \
+ $(DESTDIR)$(sbindir)/visudo
+ -test -z "$(INSTALL_BACKUP)" || \
+ $(DESTDIR)$(bindir)/cvtsudoers$(INSTALL_BACKUP) \
+ $(DESTDIR)$(bindir)/sudoreplay$(INSTALL_BACKUP) \
+ $(DESTDIR)$(sbindir)/visudo$(INSTALL_BACKUP) \
+ $(DESTDIR)$(plugindir)/sudoers.so$(INSTALL_BACKUP)
+ -cmp $(DESTDIR)$(sysconfdir)/sudoers $(DESTDIR)$(sysconfdir)/sudoers.dist >/dev/null && \
+ rm -f $(DESTDIR)$(sysconfdir)/sudoers
+ -rm -f $(DESTDIR)$(sysconfdir)/sudoers.dist
+
+splint:
+ splint $(SPLINT_OPTS) -I$(incdir) -I$(top_builddir) -I$(devdir) -I$(srcdir) $(srcdir)/*.c $(srcdir)/auth/*.c
+
+cppcheck:
+ cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) -I$(devdir) -I$(srcdir) $(srcdir)/*.c $(srcdir)/auth/*.c
+
+pvs-log-files: $(POBJS)
+
+pvs-studio: $(POBJS)
+ plog-converter $(PVS_LOG_OPTS) $(POBJS)
+
+fuzz: run-fuzz_policy run-fuzz_sudoers run-fuzz_sudoers_ldif
+
+check-fuzzer: $(FUZZ_PROGS)
+ @if test X"$(cross_compiling)" != X"yes"; then \
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ echo "fuzz_sudoers: verifying corpus"; \
+ ./fuzz_sudoers $(FUZZ_VERBOSE) $(FUZZ_SUDOERS_CORPUS); \
+ echo "fuzz_sudoers-ldif: verifying corpus"; \
+ ./fuzz_sudoers_ldif $(FUZZ_VERBOSE) $(FUZZ_SUDOERS_LDIF_CORPUS); \
+ echo "fuzz_policy: verifying corpus"; \
+ ./fuzz_policy $(FUZZ_VERBOSE) $(FUZZ_POLICY_CORPUS); \
+ fi
+
+check: $(TEST_PROGS) visudo testsudoers cvtsudoers check-fuzzer
+ @if test X"$(cross_compiling)" != X"yes"; then \
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ umask 022; \
+ rval=0; \
+ mkdir -p regress/parser; \
+ ./check_addr $(TEST_VERBOSE) $(srcdir)/regress/parser/check_addr.in || rval=`expr $$rval + $$?`; \
+ ./check_base64 $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ if test -f check_digest; then \
+ ./check_digest $(TEST_VERBOSE) > regress/parser/check_digest.out; \
+ diff regress/parser/check_digest.out $(srcdir)/regress/parser/check_digest.out.ok || rval=`expr $$rval + $$?`; \
+ fi; \
+ ./check_editor $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./check_env_pattern $(TEST_VERBOSE) $(srcdir)/regress/env_match/data || rval=`expr $$rval + $$?`; \
+ ./check_exptilde $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./check_fill $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./check_gentime $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ mkdir -p regress/iolog_plugin; \
+ ./check_iolog_plugin $(TEST_VERBOSE) regress/iolog_plugin/iolog || rval=`expr $$rval + $$?`; \
+ ./check_serialize_list $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./check_starttime $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ ./check_unesc $(TEST_VERBOSE) || rval=`expr $$rval + $$?`; \
+ if test -f check_symbols; then \
+ ./check_symbols $(TEST_VERBOSE) .libs/sudoers.so $(shlib_exp) || rval=`expr $$rval + $$?`; \
+ fi; \
+ AWK=$(AWK) $(HARNESS) sudoers || rval=`expr $$rval + $$?`; \
+ AWK=$(AWK) $(HARNESS) testsudoers || rval=`expr $$rval + $$?`; \
+ AWK=$(AWK) $(HARNESS) visudo || rval=`expr $$rval + $$?`; \
+ AWK=$(AWK) $(HARNESS) cvtsudoers || rval=`expr $$rval + $$?`; \
+ exit $$rval; \
+ fi
+
+check-verbose:
+ exec $(MAKE) $(MFLAGS) TEST_VERBOSE=-v FUZZ_VERBOSE=-verbosity=1 check
+
+clean:
+ -$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f $(PROGS) $(TEST_PROGS) \
+ $(FUZZ_PROGS) *.lo *.o *.la
+ -rm -f *.i *.plog stamp-* core *.core core.* prologue regress/*/*.out \
+ regress/*/*.toke regress/*/*.err regress/*/*.json \
+ regress/*/*.ldif regress/*/*.ldif2sudo regress/*/*.sudo
+ -rm -rf regress/iolog_plugin/iolog regress/corpus/policy \
+ regress/corpus/sudoers regress/corpus/sudoers_ldif
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile sudoers sudoers.lo tsgetusershell.c regress/harness \
+ .libs $(shlib_map) $(shlib_opt)
+ @if [ -n "$(DEVEL)" -a "$(devdir)" != "$(srcdir)" ]; then \
+ cmd='rm -rf $(GENERATED)'; \
+ echo "$$cmd"; eval $$cmd; \
+ fi
+
+clobber: distclean
+
+realclean: distclean
+ rm -f TAGS tags
+
+cleandir: realclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean \
+ harness $(FUZZ_SEED_CORPUS) run-fuzz_policy run-fuzz_sudoers \
+ run-fuzz_sudoers_ldif
+
+# Autogenerated dependencies, do not modify
+afs.lo: $(authdir)/afs.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(authdir)/afs.c
+afs.i: $(authdir)/afs.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+afs.plog: afs.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(authdir)/afs.c --i-file $< --output-file $@
+aix_auth.lo: $(authdir)/aix_auth.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(authdir)/aix_auth.c
+aix_auth.i: $(authdir)/aix_auth.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+aix_auth.plog: aix_auth.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(authdir)/aix_auth.c --i-file $< --output-file $@
+alias.lo: $(srcdir)/alias.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/redblack.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/alias.c
+alias.i: $(srcdir)/alias.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/redblack.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+alias.plog: alias.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/alias.c --i-file $< --output-file $@
+audit.lo: $(srcdir)/audit.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_ssl_compat.h \
+ $(incdir)/sudo_util.h $(srcdir)/bsm_audit.h $(srcdir)/defaults.h \
+ $(srcdir)/linux_audit.h $(srcdir)/log_client.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/solaris_audit.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/audit.c
+audit.i: $(srcdir)/audit.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_ssl_compat.h \
+ $(incdir)/sudo_util.h $(srcdir)/bsm_audit.h $(srcdir)/defaults.h \
+ $(srcdir)/linux_audit.h $(srcdir)/log_client.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/solaris_audit.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+audit.plog: audit.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/audit.c --i-file $< --output-file $@
+b64_decode.lo: $(srcdir)/b64_decode.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/b64_decode.c
+b64_decode.i: $(srcdir)/b64_decode.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+b64_decode.plog: b64_decode.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/b64_decode.c --i-file $< --output-file $@
+b64_encode.o: $(srcdir)/b64_encode.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/b64_encode.c
+b64_encode.i: $(srcdir)/b64_encode.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+b64_encode.plog: b64_encode.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/b64_encode.c --i-file $< --output-file $@
+boottime.lo: $(srcdir)/boottime.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/boottime.c
+boottime.i: $(srcdir)/boottime.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+boottime.plog: boottime.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/boottime.c --i-file $< --output-file $@
+bsdauth.lo: $(authdir)/bsdauth.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(authdir)/bsdauth.c
+bsdauth.i: $(authdir)/bsdauth.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+bsdauth.plog: bsdauth.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(authdir)/bsdauth.c --i-file $< --output-file $@
+bsm_audit.lo: $(srcdir)/bsm_audit.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/bsm_audit.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/bsm_audit.c
+bsm_audit.i: $(srcdir)/bsm_audit.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/bsm_audit.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+bsm_audit.plog: bsm_audit.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/bsm_audit.c --i-file $< --output-file $@
+canon_path.lo: $(srcdir)/canon_path.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/redblack.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/canon_path.c
+canon_path.i: $(srcdir)/canon_path.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/redblack.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+canon_path.plog: canon_path.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/canon_path.c --i-file $< --output-file $@
+check.lo: $(srcdir)/check.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(srcdir)/timestamp.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/check.c
+check.i: $(srcdir)/check.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(srcdir)/timestamp.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check.plog: check.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/check.c --i-file $< --output-file $@
+check_addr.o: $(srcdir)/regress/parser/check_addr.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/interfaces.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/parser/check_addr.c
+check_addr.i: $(srcdir)/regress/parser/check_addr.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/interfaces.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_addr.plog: check_addr.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/parser/check_addr.c --i-file $< --output-file $@
+check_aliases.o: $(srcdir)/check_aliases.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/check_aliases.c
+check_aliases.i: $(srcdir)/check_aliases.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_aliases.plog: check_aliases.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/check_aliases.c --i-file $< --output-file $@
+check_base64.o: $(srcdir)/regress/parser/check_base64.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/parser/check_base64.c
+check_base64.i: $(srcdir)/regress/parser/check_base64.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_base64.plog: check_base64.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/parser/check_base64.c --i-file $< --output-file $@
+check_digest.o: $(srcdir)/regress/parser/check_digest.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/parse.h $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/parser/check_digest.c
+check_digest.i: $(srcdir)/regress/parser/check_digest.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/parse.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_digest.plog: check_digest.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/parser/check_digest.c --i-file $< --output-file $@
+check_editor.o: $(srcdir)/regress/editor/check_editor.c $(devdir)/def_data.c \
+ $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/editor/check_editor.c
+check_editor.i: $(srcdir)/regress/editor/check_editor.c $(devdir)/def_data.c \
+ $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_editor.plog: check_editor.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/editor/check_editor.c --i-file $< --output-file $@
+check_env_pattern.o: $(srcdir)/regress/env_match/check_env_pattern.c \
+ $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/env_match/check_env_pattern.c
+check_env_pattern.i: $(srcdir)/regress/env_match/check_env_pattern.c \
+ $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_env_pattern.plog: check_env_pattern.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/env_match/check_env_pattern.c --i-file $< --output-file $@
+check_exptilde.o: $(srcdir)/regress/exptilde/check_exptilde.c \
+ $(devdir)/def_data.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/exptilde/check_exptilde.c
+check_exptilde.i: $(srcdir)/regress/exptilde/check_exptilde.c \
+ $(devdir)/def_data.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_exptilde.plog: check_exptilde.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/exptilde/check_exptilde.c --i-file $< --output-file $@
+check_fill.o: $(srcdir)/regress/parser/check_fill.c $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/parse.h $(srcdir)/toke.h \
+ $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/parser/check_fill.c
+check_fill.i: $(srcdir)/regress/parser/check_fill.c $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/parse.h $(srcdir)/toke.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_fill.plog: check_fill.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/parser/check_fill.c --i-file $< --output-file $@
+check_gentime.o: $(srcdir)/regress/parser/check_gentime.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/parse.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/parser/check_gentime.c
+check_gentime.i: $(srcdir)/regress/parser/check_gentime.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/parse.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_gentime.plog: check_gentime.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/parser/check_gentime.c --i-file $< --output-file $@
+check_iolog_plugin.o: $(srcdir)/regress/iolog_plugin/check_iolog_plugin.c \
+ $(devdir)/def_data.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/iolog_plugin/check_iolog_plugin.c
+check_iolog_plugin.i: $(srcdir)/regress/iolog_plugin/check_iolog_plugin.c \
+ $(devdir)/def_data.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_iolog_plugin.plog: check_iolog_plugin.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/iolog_plugin/check_iolog_plugin.c --i-file $< --output-file $@
+check_serialize_list.lo: \
+ $(srcdir)/regress/serialize_list/check_serialize_list.c \
+ $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/serialize_list/check_serialize_list.c
+check_serialize_list.i: \
+ $(srcdir)/regress/serialize_list/check_serialize_list.c \
+ $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_serialize_list.plog: check_serialize_list.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/serialize_list/check_serialize_list.c --i-file $< --output-file $@
+check_starttime.o: $(srcdir)/regress/starttime/check_starttime.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/starttime/check_starttime.c
+check_starttime.i: $(srcdir)/regress/starttime/check_starttime.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_util.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_starttime.plog: check_starttime.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/starttime/check_starttime.c --i-file $< --output-file $@
+check_symbols.o: $(srcdir)/regress/check_symbols/check_symbols.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_dso.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/check_symbols/check_symbols.c
+check_symbols.i: $(srcdir)/regress/check_symbols/check_symbols.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_dso.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_symbols.plog: check_symbols.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/check_symbols/check_symbols.c --i-file $< --output-file $@
+check_unesc.o: $(srcdir)/regress/unescape/check_unesc.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/unescape/check_unesc.c
+check_unesc.i: $(srcdir)/regress/unescape/check_unesc.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_unesc.plog: check_unesc.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/unescape/check_unesc.c --i-file $< --output-file $@
+check_util.lo: $(srcdir)/check_util.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/check_util.c
+check_util.i: $(srcdir)/check_util.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_util.plog: check_util.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/check_util.c --i-file $< --output-file $@
+cvtsudoers.o: $(srcdir)/cvtsudoers.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/getopt.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_lbuf.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/cvtsudoers.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/redblack.h \
+ $(srcdir)/strlist.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/sudoers_version.h \
+ $(srcdir)/testsudoers_pwutil.h $(srcdir)/tsgetgrpw.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/cvtsudoers.c
+cvtsudoers.i: $(srcdir)/cvtsudoers.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/getopt.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_lbuf.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/cvtsudoers.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/redblack.h \
+ $(srcdir)/strlist.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/sudoers_version.h \
+ $(srcdir)/testsudoers_pwutil.h $(srcdir)/tsgetgrpw.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+cvtsudoers.plog: cvtsudoers.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/cvtsudoers.c --i-file $< --output-file $@
+cvtsudoers_csv.o: $(srcdir)/cvtsudoers_csv.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/cvtsudoers.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/strlist.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/cvtsudoers_csv.c
+cvtsudoers_csv.i: $(srcdir)/cvtsudoers_csv.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/cvtsudoers.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/strlist.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+cvtsudoers_csv.plog: cvtsudoers_csv.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/cvtsudoers_csv.c --i-file $< --output-file $@
+cvtsudoers_json.o: $(srcdir)/cvtsudoers_json.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_json.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/cvtsudoers.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/strlist.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/cvtsudoers_json.c
+cvtsudoers_json.i: $(srcdir)/cvtsudoers_json.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_json.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/cvtsudoers.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/strlist.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+cvtsudoers_json.plog: cvtsudoers_json.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/cvtsudoers_json.c --i-file $< --output-file $@
+cvtsudoers_ldif.o: $(srcdir)/cvtsudoers_ldif.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_lbuf.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/cvtsudoers.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/redblack.h $(srcdir)/strlist.h \
+ $(srcdir)/sudo_ldap.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/cvtsudoers_ldif.c
+cvtsudoers_ldif.i: $(srcdir)/cvtsudoers_ldif.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_lbuf.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/cvtsudoers.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/redblack.h $(srcdir)/strlist.h \
+ $(srcdir)/sudo_ldap.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+cvtsudoers_ldif.plog: cvtsudoers_ldif.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/cvtsudoers_ldif.c --i-file $< --output-file $@
+cvtsudoers_merge.o: $(srcdir)/cvtsudoers_merge.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/cvtsudoers.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/redblack.h $(srcdir)/strlist.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/cvtsudoers_merge.c
+cvtsudoers_merge.i: $(srcdir)/cvtsudoers_merge.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/cvtsudoers.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/redblack.h $(srcdir)/strlist.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+cvtsudoers_merge.plog: cvtsudoers_merge.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/cvtsudoers_merge.c --i-file $< --output-file $@
+cvtsudoers_pwutil.o: $(srcdir)/cvtsudoers_pwutil.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/cvtsudoers.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/pwutil.h $(srcdir)/strlist.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/cvtsudoers_pwutil.c
+cvtsudoers_pwutil.i: $(srcdir)/cvtsudoers_pwutil.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/cvtsudoers.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/pwutil.h $(srcdir)/strlist.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+cvtsudoers_pwutil.plog: cvtsudoers_pwutil.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/cvtsudoers_pwutil.c --i-file $< --output-file $@
+dce.lo: $(authdir)/dce.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(authdir)/dce.c
+dce.i: $(authdir)/dce.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+dce.plog: dce.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(authdir)/dce.c --i-file $< --output-file $@
+defaults.lo: $(srcdir)/defaults.c $(devdir)/def_data.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/defaults.c
+defaults.i: $(srcdir)/defaults.c $(devdir)/def_data.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+defaults.plog: defaults.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/defaults.c --i-file $< --output-file $@
+digestname.lo: $(srcdir)/digestname.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_queue.h \
+ $(srcdir)/parse.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/digestname.c
+digestname.i: $(srcdir)/digestname.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_queue.h \
+ $(srcdir)/parse.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+digestname.plog: digestname.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/digestname.c --i-file $< --output-file $@
+display.lo: $(srcdir)/display.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/display.c
+display.i: $(srcdir)/display.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+display.plog: display.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/display.c --i-file $< --output-file $@
+editor.lo: $(srcdir)/editor.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/editor.c
+editor.i: $(srcdir)/editor.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+editor.plog: editor.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/editor.c --i-file $< --output-file $@
+env.lo: $(srcdir)/env.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/env.c
+env.i: $(srcdir)/env.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+env.plog: env.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/env.c --i-file $< --output-file $@
+env_pattern.lo: $(srcdir)/env_pattern.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/env_pattern.c
+env_pattern.i: $(srcdir)/env_pattern.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+env_pattern.plog: env_pattern.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/env_pattern.c --i-file $< --output-file $@
+exptilde.lo: $(srcdir)/exptilde.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/pwutil.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/exptilde.c
+exptilde.i: $(srcdir)/exptilde.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/pwutil.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+exptilde.plog: exptilde.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/exptilde.c --i-file $< --output-file $@
+file.lo: $(srcdir)/file.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/file.c
+file.i: $(srcdir)/file.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+file.plog: file.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/file.c --i-file $< --output-file $@
+filedigest.lo: $(srcdir)/filedigest.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/filedigest.c
+filedigest.i: $(srcdir)/filedigest.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+filedigest.plog: filedigest.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/filedigest.c --i-file $< --output-file $@
+find_path.lo: $(srcdir)/find_path.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/find_path.c
+find_path.i: $(srcdir)/find_path.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+find_path.plog: find_path.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/find_path.c --i-file $< --output-file $@
+fmtsudoers.lo: $(srcdir)/fmtsudoers.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/fmtsudoers.c
+fmtsudoers.i: $(srcdir)/fmtsudoers.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fmtsudoers.plog: fmtsudoers.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/fmtsudoers.c --i-file $< --output-file $@
+fmtsudoers_cvt.lo: $(srcdir)/fmtsudoers_cvt.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_lbuf.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/fmtsudoers_cvt.c
+fmtsudoers_cvt.i: $(srcdir)/fmtsudoers_cvt.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_lbuf.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fmtsudoers_cvt.plog: fmtsudoers_cvt.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/fmtsudoers_cvt.c --i-file $< --output-file $@
+fuzz_policy.o: $(srcdir)/regress/fuzz/fuzz_policy.c $(devdir)/def_data.h \
+ $(incdir)/compat/getaddrinfo.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/auth/sudo_auth.h $(srcdir)/defaults.h \
+ $(srcdir)/interfaces.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/fuzz/fuzz_policy.c
+fuzz_policy.i: $(srcdir)/regress/fuzz/fuzz_policy.c $(devdir)/def_data.h \
+ $(incdir)/compat/getaddrinfo.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/auth/sudo_auth.h $(srcdir)/defaults.h \
+ $(srcdir)/interfaces.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fuzz_policy.plog: fuzz_policy.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/fuzz/fuzz_policy.c --i-file $< --output-file $@
+fuzz_stubs.o: $(srcdir)/regress/fuzz/fuzz_stubs.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/interfaces.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(srcdir)/timestamp.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/fuzz/fuzz_stubs.c
+fuzz_stubs.i: $(srcdir)/regress/fuzz/fuzz_stubs.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/interfaces.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(srcdir)/timestamp.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fuzz_stubs.plog: fuzz_stubs.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/fuzz/fuzz_stubs.c --i-file $< --output-file $@
+fuzz_sudoers.o: $(srcdir)/regress/fuzz/fuzz_sudoers.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/interfaces.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/fuzz/fuzz_sudoers.c
+fuzz_sudoers.i: $(srcdir)/regress/fuzz/fuzz_sudoers.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/interfaces.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fuzz_sudoers.plog: fuzz_sudoers.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/fuzz/fuzz_sudoers.c --i-file $< --output-file $@
+fuzz_sudoers_ldif.o: $(srcdir)/regress/fuzz/fuzz_sudoers_ldif.c \
+ $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/fuzz/fuzz_sudoers_ldif.c
+fuzz_sudoers_ldif.i: $(srcdir)/regress/fuzz/fuzz_sudoers_ldif.c \
+ $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fuzz_sudoers_ldif.plog: fuzz_sudoers_ldif.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/fuzz/fuzz_sudoers_ldif.c --i-file $< --output-file $@
+fwtk.lo: $(authdir)/fwtk.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(authdir)/fwtk.c
+fwtk.i: $(authdir)/fwtk.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+fwtk.plog: fwtk.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(authdir)/fwtk.c --i-file $< --output-file $@
+gc.lo: $(srcdir)/gc.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/gc.c
+gc.i: $(srcdir)/gc.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+gc.plog: gc.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/gc.c --i-file $< --output-file $@
+gentime.lo: $(srcdir)/gentime.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(srcdir)/parse.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/gentime.c
+gentime.i: $(srcdir)/gentime.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(srcdir)/parse.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+gentime.plog: gentime.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/gentime.c --i-file $< --output-file $@
+getdate.o: $(devdir)/getdate.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(devdir)/getdate.c
+getdate.i: $(devdir)/getdate.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+getdate.plog: getdate.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(devdir)/getdate.c --i-file $< --output-file $@
+getspwuid.lo: $(srcdir)/getspwuid.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/getspwuid.c
+getspwuid.i: $(srcdir)/getspwuid.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+getspwuid.plog: getspwuid.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/getspwuid.c --i-file $< --output-file $@
+goodpath.lo: $(srcdir)/goodpath.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/goodpath.c
+goodpath.i: $(srcdir)/goodpath.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+goodpath.plog: goodpath.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/goodpath.c --i-file $< --output-file $@
+gram.lo: $(devdir)/gram.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/toke.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(devdir)/gram.c
+gram.i: $(devdir)/gram.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/toke.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+gram.plog: gram.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(devdir)/gram.c --i-file $< --output-file $@
+group_plugin.lo: $(srcdir)/group_plugin.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_dso.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/group_plugin.c
+group_plugin.i: $(srcdir)/group_plugin.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_dso.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+group_plugin.plog: group_plugin.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/group_plugin.c --i-file $< --output-file $@
+interfaces.lo: $(srcdir)/interfaces.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/interfaces.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/interfaces.c
+interfaces.i: $(srcdir)/interfaces.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/interfaces.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+interfaces.plog: interfaces.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/interfaces.c --i-file $< --output-file $@
+iolog.lo: $(srcdir)/iolog.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/log_client.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/strlist.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog.c
+iolog.i: $(srcdir)/iolog.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/log_client.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/strlist.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog.plog: iolog.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog.c --i-file $< --output-file $@
+iolog_path_escapes.lo: $(srcdir)/iolog_path_escapes.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/iolog_path_escapes.c
+iolog_path_escapes.i: $(srcdir)/iolog_path_escapes.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+iolog_path_escapes.plog: iolog_path_escapes.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_path_escapes.c --i-file $< --output-file $@
+kerb5.lo: $(authdir)/kerb5.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(authdir)/kerb5.c
+kerb5.i: $(authdir)/kerb5.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+kerb5.plog: kerb5.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(authdir)/kerb5.c --i-file $< --output-file $@
+ldap.lo: $(srcdir)/ldap.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_dso.h $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_ldap.h $(srcdir)/sudo_ldap_conf.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/ldap.c
+ldap.i: $(srcdir)/ldap.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_dso.h $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_ldap.h $(srcdir)/sudo_ldap_conf.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+ldap.plog: ldap.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/ldap.c --i-file $< --output-file $@
+ldap_conf.lo: $(srcdir)/ldap_conf.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_ldap.h \
+ $(srcdir)/sudo_ldap_conf.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/ldap_conf.c
+ldap_conf.i: $(srcdir)/ldap_conf.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_ldap.h \
+ $(srcdir)/sudo_ldap_conf.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+ldap_conf.plog: ldap_conf.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/ldap_conf.c --i-file $< --output-file $@
+ldap_innetgr.lo: $(srcdir)/ldap_innetgr.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_ldap.h \
+ $(srcdir)/sudo_ldap_conf.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/ldap_innetgr.c
+ldap_innetgr.i: $(srcdir)/ldap_innetgr.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_ldap.h \
+ $(srcdir)/sudo_ldap_conf.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+ldap_innetgr.plog: ldap_innetgr.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/ldap_innetgr.c --i-file $< --output-file $@
+ldap_util.lo: $(srcdir)/ldap_util.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_lbuf.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/interfaces.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_ldap.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/ldap_util.c
+ldap_util.i: $(srcdir)/ldap_util.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_digest.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_lbuf.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/interfaces.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_ldap.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+ldap_util.plog: ldap_util.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/ldap_util.c --i-file $< --output-file $@
+linux_audit.lo: $(srcdir)/linux_audit.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/linux_audit.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/linux_audit.c
+linux_audit.i: $(srcdir)/linux_audit.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/linux_audit.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+linux_audit.plog: linux_audit.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/linux_audit.c --i-file $< --output-file $@
+locale.lo: $(srcdir)/locale.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/locale.c
+locale.i: $(srcdir)/locale.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+locale.plog: locale.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/locale.c --i-file $< --output-file $@
+log_client.lo: $(srcdir)/log_client.c $(devdir)/def_data.h \
+ $(incdir)/compat/getaddrinfo.h $(incdir)/compat/stdbool.h \
+ $(incdir)/hostcheck.h $(incdir)/log_server.pb-c.h \
+ $(incdir)/protobuf-c/protobuf-c.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_ssl_compat.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/log_client.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/strlist.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/log_client.c
+log_client.i: $(srcdir)/log_client.c $(devdir)/def_data.h \
+ $(incdir)/compat/getaddrinfo.h $(incdir)/compat/stdbool.h \
+ $(incdir)/hostcheck.h $(incdir)/log_server.pb-c.h \
+ $(incdir)/protobuf-c/protobuf-c.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_ssl_compat.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/log_client.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/strlist.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+log_client.plog: log_client.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/log_client.c --i-file $< --output-file $@
+logging.lo: $(srcdir)/logging.c $(devdir)/def_data.h \
+ $(incdir)/compat/getaddrinfo.h $(incdir)/compat/stdbool.h \
+ $(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/log_client.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/strlist.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/logging.c
+logging.i: $(srcdir)/logging.c $(devdir)/def_data.h \
+ $(incdir)/compat/getaddrinfo.h $(incdir)/compat/stdbool.h \
+ $(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_ssl_compat.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/log_client.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/strlist.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+logging.plog: logging.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/logging.c --i-file $< --output-file $@
+lookup.lo: $(srcdir)/lookup.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/lookup.c
+lookup.i: $(srcdir)/lookup.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+lookup.plog: lookup.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/lookup.c --i-file $< --output-file $@
+match.lo: $(srcdir)/match.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/fnmatch.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/match.c
+match.i: $(srcdir)/match.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/fnmatch.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+match.plog: match.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/match.c --i-file $< --output-file $@
+match_addr.lo: $(srcdir)/match_addr.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/interfaces.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/match_addr.c
+match_addr.i: $(srcdir)/match_addr.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/interfaces.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+match_addr.plog: match_addr.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/match_addr.c --i-file $< --output-file $@
+match_command.lo: $(srcdir)/match_command.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/fnmatch.h \
+ $(incdir)/compat/glob.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/match_command.c
+match_command.i: $(srcdir)/match_command.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/fnmatch.h \
+ $(incdir)/compat/glob.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+match_command.plog: match_command.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/match_command.c --i-file $< --output-file $@
+match_digest.lo: $(srcdir)/match_digest.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_digest.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/match_digest.c
+match_digest.i: $(srcdir)/match_digest.c $(devdir)/def_data.h \
+ $(devdir)/gram.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_digest.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+match_digest.plog: match_digest.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/match_digest.c --i-file $< --output-file $@
+net_ifs.o: $(top_srcdir)/src/net_ifs.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h $(top_srcdir)/src/sudo.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(top_srcdir)/src/net_ifs.c
+net_ifs.i: $(top_srcdir)/src/net_ifs.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h $(top_srcdir)/src/sudo.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+net_ifs.plog: net_ifs.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(top_srcdir)/src/net_ifs.c --i-file $< --output-file $@
+pam.lo: $(authdir)/pam.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(authdir)/pam.c
+pam.i: $(authdir)/pam.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+pam.plog: pam.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(authdir)/pam.c --i-file $< --output-file $@
+parse_ldif.o: $(srcdir)/parse_ldif.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/redblack.h $(srcdir)/strlist.h \
+ $(srcdir)/sudo_ldap.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/parse_ldif.c
+parse_ldif.i: $(srcdir)/parse_ldif.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/redblack.h $(srcdir)/strlist.h \
+ $(srcdir)/sudo_ldap.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+parse_ldif.plog: parse_ldif.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/parse_ldif.c --i-file $< --output-file $@
+parser_warnx.lo: $(srcdir)/parser_warnx.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/parser_warnx.c
+parser_warnx.i: $(srcdir)/parser_warnx.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+parser_warnx.plog: parser_warnx.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/parser_warnx.c --i-file $< --output-file $@
+passwd.lo: $(authdir)/passwd.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(authdir)/passwd.c
+passwd.i: $(authdir)/passwd.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+passwd.plog: passwd.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(authdir)/passwd.c --i-file $< --output-file $@
+pivot.lo: $(srcdir)/pivot.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/pivot.c
+pivot.i: $(srcdir)/pivot.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+pivot.plog: pivot.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/pivot.c --i-file $< --output-file $@
+policy.lo: $(srcdir)/policy.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/auth/sudo_auth.h \
+ $(srcdir)/defaults.h $(srcdir)/interfaces.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(srcdir)/sudoers_version.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/policy.c
+policy.i: $(srcdir)/policy.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/auth/sudo_auth.h \
+ $(srcdir)/defaults.h $(srcdir)/interfaces.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(srcdir)/sudoers_version.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+policy.plog: policy.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/policy.c --i-file $< --output-file $@
+prompt.lo: $(srcdir)/prompt.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/prompt.c
+prompt.i: $(srcdir)/prompt.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+prompt.plog: prompt.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/prompt.c --i-file $< --output-file $@
+pwutil.lo: $(srcdir)/pwutil.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/pwutil.h \
+ $(srcdir)/redblack.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/pwutil.c
+pwutil.i: $(srcdir)/pwutil.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/pwutil.h \
+ $(srcdir)/redblack.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+pwutil.plog: pwutil.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/pwutil.c --i-file $< --output-file $@
+pwutil_impl.lo: $(srcdir)/pwutil_impl.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/pwutil.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/pwutil_impl.c
+pwutil_impl.i: $(srcdir)/pwutil_impl.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/pwutil.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+pwutil_impl.plog: pwutil_impl.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/pwutil_impl.c --i-file $< --output-file $@
+redblack.lo: $(srcdir)/redblack.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/redblack.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/redblack.c
+redblack.i: $(srcdir)/redblack.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/redblack.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+redblack.plog: redblack.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/redblack.c --i-file $< --output-file $@
+resolve_cmnd.lo: $(srcdir)/resolve_cmnd.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/resolve_cmnd.c
+resolve_cmnd.i: $(srcdir)/resolve_cmnd.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+resolve_cmnd.plog: resolve_cmnd.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/resolve_cmnd.c --i-file $< --output-file $@
+rfc1938.lo: $(authdir)/rfc1938.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(authdir)/rfc1938.c
+rfc1938.i: $(authdir)/rfc1938.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+rfc1938.plog: rfc1938.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(authdir)/rfc1938.c --i-file $< --output-file $@
+secureware.lo: $(authdir)/secureware.c $(authdir)/sudo_auth.h \
+ $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(authdir)/secureware.c
+secureware.i: $(authdir)/secureware.c $(authdir)/sudo_auth.h \
+ $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+secureware.plog: secureware.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(authdir)/secureware.c --i-file $< --output-file $@
+securid5.lo: $(authdir)/securid5.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(authdir)/securid5.c
+securid5.i: $(authdir)/securid5.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+securid5.plog: securid5.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(authdir)/securid5.c --i-file $< --output-file $@
+serialize_list.lo: $(srcdir)/serialize_list.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/serialize_list.c
+serialize_list.i: $(srcdir)/serialize_list.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+serialize_list.plog: serialize_list.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/serialize_list.c --i-file $< --output-file $@
+set_perms.lo: $(srcdir)/set_perms.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/set_perms.c
+set_perms.i: $(srcdir)/set_perms.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+set_perms.plog: set_perms.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/set_perms.c --i-file $< --output-file $@
+sethost.lo: $(srcdir)/sethost.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sethost.c
+sethost.i: $(srcdir)/sethost.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sethost.plog: sethost.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sethost.c --i-file $< --output-file $@
+sia.lo: $(authdir)/sia.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(authdir)/sia.c
+sia.i: $(authdir)/sia.c $(authdir)/sudo_auth.h $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sia.plog: sia.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(authdir)/sia.c --i-file $< --output-file $@
+solaris_audit.lo: $(srcdir)/solaris_audit.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/solaris_audit.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/solaris_audit.c
+solaris_audit.i: $(srcdir)/solaris_audit.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/solaris_audit.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+solaris_audit.plog: solaris_audit.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/solaris_audit.c --i-file $< --output-file $@
+sssd.lo: $(srcdir)/sssd.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_dso.h $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_ldap.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sssd.c
+sssd.i: $(srcdir)/sssd.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_dso.h $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_ldap.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sssd.plog: sssd.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sssd.c --i-file $< --output-file $@
+starttime.lo: $(srcdir)/starttime.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/starttime.c
+starttime.i: $(srcdir)/starttime.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+starttime.plog: starttime.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/starttime.c --i-file $< --output-file $@
+strlcpy_unesc.lo: $(srcdir)/strlcpy_unesc.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/strlcpy_unesc.c
+strlcpy_unesc.i: $(srcdir)/strlcpy_unesc.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strlcpy_unesc.plog: strlcpy_unesc.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/strlcpy_unesc.c --i-file $< --output-file $@
+strlist.lo: $(srcdir)/strlist.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/strlist.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/strlist.c
+strlist.i: $(srcdir)/strlist.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/strlist.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strlist.plog: strlist.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/strlist.c --i-file $< --output-file $@
+strvec_join.lo: $(srcdir)/strvec_join.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/strvec_join.c
+strvec_join.i: $(srcdir)/strvec_join.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+strvec_join.plog: strvec_join.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/strvec_join.c --i-file $< --output-file $@
+stubs.o: $(srcdir)/stubs.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/interfaces.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/stubs.c
+stubs.i: $(srcdir)/stubs.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/interfaces.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+stubs.plog: stubs.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/stubs.c --i-file $< --output-file $@
+sudo_auth.lo: $(authdir)/sudo_auth.c $(authdir)/sudo_auth.h \
+ $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_rand.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/ins_2001.h $(srcdir)/ins_classic.h \
+ $(srcdir)/ins_csops.h $(srcdir)/ins_goons.h \
+ $(srcdir)/ins_python.h $(srcdir)/insults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(srcdir)/timestamp.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(authdir)/sudo_auth.c
+sudo_auth.i: $(authdir)/sudo_auth.c $(authdir)/sudo_auth.h \
+ $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_rand.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/ins_2001.h $(srcdir)/ins_classic.h \
+ $(srcdir)/ins_csops.h $(srcdir)/ins_goons.h \
+ $(srcdir)/ins_python.h $(srcdir)/insults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(srcdir)/timestamp.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudo_auth.plog: sudo_auth.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(authdir)/sudo_auth.c --i-file $< --output-file $@
+sudo_nss.lo: $(srcdir)/sudo_nss.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudo_nss.c
+sudo_nss.i: $(srcdir)/sudo_nss.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudo_nss.plog: sudo_nss.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_nss.c --i-file $< --output-file $@
+sudo_printf.o: $(srcdir)/sudo_printf.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudo_printf.c
+sudo_printf.i: $(srcdir)/sudo_printf.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudo_printf.plog: sudo_printf.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_printf.c --i-file $< --output-file $@
+sudoers.lo: $(srcdir)/sudoers.c $(devdir)/def_data.h \
+ $(incdir)/compat/getaddrinfo.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(srcdir)/timestamp.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudoers.c
+sudoers.i: $(srcdir)/sudoers.c $(devdir)/def_data.h \
+ $(incdir)/compat/getaddrinfo.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(srcdir)/timestamp.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudoers.plog: sudoers.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudoers.c --i-file $< --output-file $@
+sudoers_cb.lo: $(srcdir)/sudoers_cb.c $(devdir)/def_data.h \
+ $(incdir)/compat/getaddrinfo.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudoers_cb.c
+sudoers_cb.i: $(srcdir)/sudoers_cb.c $(devdir)/def_data.h \
+ $(incdir)/compat/getaddrinfo.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudoers_cb.plog: sudoers_cb.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudoers_cb.c --i-file $< --output-file $@
+sudoers_ctx_free.lo: $(srcdir)/sudoers_ctx_free.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudoers_ctx_free.c
+sudoers_ctx_free.i: $(srcdir)/sudoers_ctx_free.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudoers_ctx_free.plog: sudoers_ctx_free.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudoers_ctx_free.c --i-file $< --output-file $@
+sudoers_debug.lo: $(srcdir)/sudoers_debug.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudoers_debug.c
+sudoers_debug.i: $(srcdir)/sudoers_debug.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudoers_debug.plog: sudoers_debug.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudoers_debug.c --i-file $< --output-file $@
+sudoers_hooks.lo: $(srcdir)/sudoers_hooks.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudoers_hooks.c
+sudoers_hooks.i: $(srcdir)/sudoers_hooks.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudoers_hooks.plog: sudoers_hooks.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudoers_hooks.c --i-file $< --output-file $@
+sudoreplay.o: $(srcdir)/sudoreplay.c $(incdir)/compat/getopt.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/logging.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudoreplay.c
+sudoreplay.i: $(srcdir)/sudoreplay.c $(incdir)/compat/getopt.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_eventlog.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_iolog.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/logging.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudoreplay.plog: sudoreplay.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudoreplay.c --i-file $< --output-file $@
+testsudoers.o: $(srcdir)/testsudoers.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/interfaces.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/testsudoers_pwutil.h \
+ $(srcdir)/toke.h $(srcdir)/tsgetgrpw.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/testsudoers.c
+testsudoers.i: $(srcdir)/testsudoers.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/interfaces.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/testsudoers_pwutil.h \
+ $(srcdir)/toke.h $(srcdir)/tsgetgrpw.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+testsudoers.plog: testsudoers.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/testsudoers.c --i-file $< --output-file $@
+testsudoers_pwutil.o: $(srcdir)/testsudoers_pwutil.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/pwutil.h \
+ $(srcdir)/pwutil_impl.c $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(srcdir)/testsudoers_pwutil.h $(srcdir)/tsgetgrpw.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/testsudoers_pwutil.c
+testsudoers_pwutil.i: $(srcdir)/testsudoers_pwutil.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h \
+ $(srcdir)/parse.h $(srcdir)/pivot.h $(srcdir)/pwutil.h \
+ $(srcdir)/pwutil_impl.c $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(srcdir)/testsudoers_pwutil.h $(srcdir)/tsgetgrpw.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+testsudoers_pwutil.plog: testsudoers_pwutil.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/testsudoers_pwutil.c --i-file $< --output-file $@
+timeout.lo: $(srcdir)/timeout.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(srcdir)/parse.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/timeout.c
+timeout.i: $(srcdir)/timeout.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(srcdir)/parse.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+timeout.plog: timeout.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/timeout.c --i-file $< --output-file $@
+timestamp.lo: $(srcdir)/timestamp.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/timestamp.c
+timestamp.i: $(srcdir)/timestamp.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/timestamp.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+timestamp.plog: timestamp.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/timestamp.c --i-file $< --output-file $@
+timestr.lo: $(srcdir)/timestr.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/timestr.c
+timestr.i: $(srcdir)/timestr.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+timestr.plog: timestr.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/timestr.c --i-file $< --output-file $@
+toke.lo: $(devdir)/toke.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_digest.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/toke.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(devdir)/toke.c
+toke.i: $(devdir)/toke.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_digest.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/toke.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+toke.plog: toke.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(devdir)/toke.c --i-file $< --output-file $@
+toke_util.lo: $(srcdir)/toke_util.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/toke.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/toke_util.c
+toke_util.i: $(srcdir)/toke_util.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/toke.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+toke_util.plog: toke_util.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/toke_util.c --i-file $< --output-file $@
+tsdump.o: $(srcdir)/tsdump.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(srcdir)/timestamp.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/tsdump.c
+tsdump.i: $(srcdir)/tsdump.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(srcdir)/timestamp.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+tsdump.plog: tsdump.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/tsdump.c --i-file $< --output-file $@
+tsgetgrpw.o: $(srcdir)/tsgetgrpw.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/tsgetgrpw.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/tsgetgrpw.c
+tsgetgrpw.i: $(srcdir)/tsgetgrpw.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(srcdir)/tsgetgrpw.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+tsgetgrpw.plog: tsgetgrpw.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/tsgetgrpw.c --i-file $< --output-file $@
+tsgetusershell.o: tsgetusershell.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/tsgetgrpw.h $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) tsgetusershell.c
+tsgetusershell.i: tsgetusershell.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/tsgetgrpw.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+tsgetusershell.plog: tsgetusershell.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file tsgetusershell.c --i-file $< --output-file $@
+unesc_str.lo: $(srcdir)/unesc_str.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/unesc_str.c
+unesc_str.i: $(srcdir)/unesc_str.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/defaults.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+unesc_str.plog: unesc_str.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/unesc_str.c --i-file $< --output-file $@
+visudo.o: $(srcdir)/visudo.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/getopt.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/interfaces.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/redblack.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(srcdir)/sudoers_version.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/visudo.c
+visudo.i: $(srcdir)/visudo.c $(devdir)/def_data.h $(devdir)/gram.h \
+ $(incdir)/compat/getopt.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/interfaces.h $(srcdir)/logging.h $(srcdir)/parse.h \
+ $(srcdir)/pivot.h $(srcdir)/redblack.h $(srcdir)/sudo_nss.h \
+ $(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
+ $(srcdir)/sudoers_version.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+visudo.plog: visudo.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/visudo.c --i-file $< --output-file $@
+visudo_cb.o: $(srcdir)/visudo_cb.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/visudo_cb.c
+visudo_cb.i: $(srcdir)/visudo_cb.c $(devdir)/def_data.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_eventlog.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
+ $(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/pivot.h \
+ $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
+ $(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+visudo_cb.plog: visudo_cb.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/visudo_cb.c --i-file $< --output-file $@
diff --git a/plugins/sudoers/alias.c b/plugins/sudoers/alias.c
new file mode 100644
index 0000000..ab01d4d
--- /dev/null
+++ b/plugins/sudoers/alias.c
@@ -0,0 +1,380 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2004-2005, 2007-2021, 2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sudoers.h>
+#include <redblack.h>
+#include <gram.h>
+
+/*
+ * Comparison function for the red-black tree.
+ * Aliases are sorted by name with the type used as a tie-breaker.
+ */
+static int
+alias_compare(const void *v1, const void *v2)
+{
+ const struct alias *a1 = (const struct alias *)v1;
+ const struct alias *a2 = (const struct alias *)v2;
+ int res;
+ debug_decl(alias_compare, SUDOERS_DEBUG_ALIAS);
+
+ if (a1 == NULL)
+ res = -1;
+ else if (a2 == NULL)
+ res = 1;
+ else if ((res = strcmp(a1->name, a2->name)) == 0)
+ res = a1->type - a2->type;
+ debug_return_int(res);
+}
+
+/*
+ * Search the tree for an alias with the specified name and type.
+ * Returns a pointer to the alias structure or NULL if not found.
+ * Caller is responsible for calling alias_put() on the returned
+ * alias to mark it as unused.
+ */
+struct alias *
+alias_get(const struct sudoers_parse_tree *parse_tree, const char *name,
+ short type)
+{
+ struct alias key;
+ struct rbnode *node;
+ struct alias *a = NULL;
+ debug_decl(alias_get, SUDOERS_DEBUG_ALIAS);
+
+ if (parse_tree->aliases == NULL)
+ debug_return_ptr(NULL);
+
+ key.name = (char *)name;
+ key.type = type;
+ if ((node = rbfind(parse_tree->aliases, &key)) != NULL) {
+ /*
+ * Check whether this alias is already in use.
+ * If so, we've detected a loop. If not, set the flag,
+ * which the caller should clear with a call to alias_put().
+ */
+ a = node->data;
+ if (a->used) {
+ errno = ELOOP;
+ debug_return_ptr(NULL);
+ }
+ a->used = true;
+ } else {
+ errno = ENOENT;
+ }
+ debug_return_ptr(a);
+}
+
+/*
+ * Clear the "used" flag in an alias once the caller is done with it.
+ */
+void
+alias_put(struct alias *a)
+{
+ debug_decl(alias_put, SUDOERS_DEBUG_ALIAS);
+ a->used = false;
+ debug_return;
+}
+
+/*
+ * Add an alias to the aliases redblack tree.
+ * Note that "file" must be a reference-counted string.
+ * Returns true on success and false on failure, setting errno.
+ */
+bool
+alias_add(struct sudoers_parse_tree *parse_tree, char *name,
+ short type, char *file, int line, int column,
+ struct member *members)
+{
+ struct alias *a;
+ debug_decl(alias_add, SUDOERS_DEBUG_ALIAS);
+
+ if (parse_tree->aliases == NULL) {
+ if ((parse_tree->aliases = alloc_aliases()) == NULL)
+ debug_return_bool(false);
+ }
+
+ a = calloc(1, sizeof(*a));
+ if (a == NULL)
+ debug_return_bool(false);
+
+ /* Only set elements used by alias_compare() in case there is a dupe. */
+ a->name = name;
+ a->type = type;
+ switch (rbinsert(parse_tree->aliases, a, NULL)) {
+ case 1:
+ free(a);
+ errno = EEXIST;
+ debug_return_bool(false);
+ case -1:
+ free(a);
+ debug_return_bool(false);
+ }
+
+ /*
+ * It is now safe to fill in the rest of the alias. We do this last
+ * since it modifies "file" (adds a ref) and "members" (tailq conversion).
+ */
+ /* a->used = false; */
+ a->file = sudo_rcstr_addref(file);
+ a->line = line;
+ a->column = column;
+ HLTQ_TO_TAILQ(&a->members, members, entries);
+ debug_return_bool(true);
+}
+
+/*
+ * Closure to adapt 2-arg rbapply() to 3-arg alias_apply().
+ */
+struct alias_apply_closure {
+ struct sudoers_parse_tree *parse_tree;
+ int (*func)(struct sudoers_parse_tree *, struct alias *, void *);
+ void *cookie;
+};
+
+/* Adapt rbapply() to alias_apply() calling convention. */
+static int
+alias_apply_func(void *v1, void *v2)
+{
+ struct alias *a = v1;
+ struct alias_apply_closure *closure = v2;
+
+ return closure->func(closure->parse_tree, a, closure->cookie);
+}
+
+/*
+ * Apply a function to each alias entry and pass in a cookie.
+ */
+void
+alias_apply(struct sudoers_parse_tree *parse_tree,
+ int (*func)(struct sudoers_parse_tree *, struct alias *, void *),
+ void *cookie)
+{
+ struct alias_apply_closure closure;
+ debug_decl(alias_apply, SUDOERS_DEBUG_ALIAS);
+
+ if (parse_tree->aliases != NULL) {
+ closure.parse_tree = parse_tree;
+ closure.func = func;
+ closure.cookie = cookie;
+ rbapply(parse_tree->aliases, alias_apply_func, &closure, inorder);
+ }
+
+ debug_return;
+}
+
+/*
+ * Returns true if there are no aliases in the parse_tree, else false.
+ */
+bool
+no_aliases(const struct sudoers_parse_tree *parse_tree)
+{
+ debug_decl(no_aliases, SUDOERS_DEBUG_ALIAS);
+ debug_return_bool(parse_tree->aliases == NULL ||
+ rbisempty(parse_tree->aliases));
+}
+
+/*
+ * Free memory used by an alias struct and its members.
+ */
+void
+alias_free(void *v)
+{
+ struct alias *a = (struct alias *)v;
+ debug_decl(alias_free, SUDOERS_DEBUG_ALIAS);
+
+ if (a != NULL) {
+ free(a->name);
+ sudo_rcstr_delref(a->file);
+ free_members(&a->members);
+ free(a);
+ }
+
+ debug_return;
+}
+
+/*
+ * Find the named alias, remove it from the tree and return it.
+ */
+struct alias *
+alias_remove(struct sudoers_parse_tree *parse_tree, const char *name,
+ short type)
+{
+ struct rbnode *node;
+ struct alias key;
+ debug_decl(alias_remove, SUDOERS_DEBUG_ALIAS);
+
+ if (parse_tree->aliases != NULL) {
+ key.name = (char *)name;
+ key.type = type;
+ if ((node = rbfind(parse_tree->aliases, &key)) != NULL)
+ debug_return_ptr(rbdelete(parse_tree->aliases, node));
+ }
+ errno = ENOENT;
+ debug_return_ptr(NULL);
+}
+
+struct rbtree *
+alloc_aliases(void)
+{
+ debug_decl(alloc_aliases, SUDOERS_DEBUG_ALIAS);
+
+ debug_return_ptr(rbcreate(alias_compare));
+}
+
+void
+free_aliases(struct rbtree *aliases)
+{
+ debug_decl(free_aliases, SUDOERS_DEBUG_ALIAS);
+
+ if (aliases != NULL)
+ rbdestroy(aliases, alias_free);
+}
+
+const char *
+alias_type_to_string(short alias_type)
+{
+ return alias_type == HOSTALIAS ? "Host_Alias" :
+ alias_type == CMNDALIAS ? "Cmnd_Alias" :
+ alias_type == USERALIAS ? "User_Alias" :
+ alias_type == RUNASALIAS ? "Runas_Alias" :
+ "Invalid_Alias";
+}
+
+/*
+ * Remove the alias of the specified type as well as any other aliases
+ * referenced by that alias. Stores removed aliases in a freelist.
+ */
+static bool
+alias_remove_recursive(struct sudoers_parse_tree *parse_tree, char *name,
+ short type, struct rbtree *freelist)
+{
+ struct member *m;
+ struct alias *a;
+ bool ret = true;
+ debug_decl(alias_remove_recursive, SUDOERS_DEBUG_ALIAS);
+
+ if ((a = alias_remove(parse_tree, name, type)) != NULL) {
+ TAILQ_FOREACH(m, &a->members, entries) {
+ if (m->type == ALIAS) {
+ if (!alias_remove_recursive(parse_tree, m->name, type, freelist))
+ ret = false;
+ }
+ }
+ if (rbinsert(freelist, a, NULL) != 0)
+ ret = false;
+ }
+ debug_return_bool(ret);
+}
+
+static int
+alias_find_used_members(struct sudoers_parse_tree *parse_tree,
+ struct member_list *members, short atype, struct rbtree *used_aliases)
+{
+ struct member *m;
+ int errors = 0;
+ debug_decl(alias_find_used_members, SUDOERS_DEBUG_ALIAS);
+
+ if (members != NULL) {
+ TAILQ_FOREACH(m, members, entries) {
+ if (m->type != ALIAS)
+ continue;
+ if (!alias_remove_recursive(parse_tree, m->name, atype, used_aliases))
+ errors++;
+ }
+ }
+
+ debug_return_int(errors);
+}
+
+/*
+ * Move all aliases referenced by userspecs to used_aliases.
+ */
+bool
+alias_find_used(struct sudoers_parse_tree *parse_tree, struct rbtree *used_aliases)
+{
+ struct privilege *priv;
+ struct userspec *us;
+ struct cmndspec *cs;
+ struct defaults *d;
+ struct member *m;
+ int errors = 0;
+ debug_decl(alias_find_used, SUDOERS_DEBUG_ALIAS);
+
+ /* Move referenced aliases to used_aliases. */
+ TAILQ_FOREACH(us, &parse_tree->userspecs, entries) {
+ errors += alias_find_used_members(parse_tree, &us->users,
+ USERALIAS, used_aliases);
+ TAILQ_FOREACH(priv, &us->privileges, entries) {
+ errors += alias_find_used_members(parse_tree, &priv->hostlist,
+ HOSTALIAS, used_aliases);
+ TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
+ errors += alias_find_used_members(parse_tree, cs->runasuserlist,
+ RUNASALIAS, used_aliases);
+ errors += alias_find_used_members(parse_tree, cs->runasgrouplist,
+ RUNASALIAS, used_aliases);
+ if ((m = cs->cmnd)->type == ALIAS) {
+ if (!alias_remove_recursive(parse_tree, m->name, CMNDALIAS,
+ used_aliases))
+ errors++;
+ }
+ }
+ }
+ }
+ TAILQ_FOREACH(d, &parse_tree->defaults, entries) {
+ switch (d->type) {
+ case DEFAULTS_HOST:
+ errors += alias_find_used_members(parse_tree,
+ &d->binding->members, HOSTALIAS, used_aliases);
+ break;
+ case DEFAULTS_USER:
+ errors += alias_find_used_members(parse_tree,
+ &d->binding->members, USERALIAS, used_aliases);
+ break;
+ case DEFAULTS_RUNAS:
+ errors += alias_find_used_members(parse_tree,
+ &d->binding->members, RUNASALIAS, used_aliases);
+ break;
+ case DEFAULTS_CMND:
+ errors += alias_find_used_members(parse_tree,
+ &d->binding->members, CMNDALIAS, used_aliases);
+ break;
+ default:
+ break;
+ }
+ }
+
+ debug_return_bool(errors ? false : true);
+}
diff --git a/plugins/sudoers/audit.c b/plugins/sudoers/audit.c
new file mode 100644
index 0000000..a469514
--- /dev/null
+++ b/plugins/sudoers/audit.c
@@ -0,0 +1,494 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2015, 2019-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/wait.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudoers.h>
+#ifdef SUDOERS_LOG_CLIENT
+# include <log_client.h>
+#endif
+
+#ifdef HAVE_BSM_AUDIT
+# include <bsm_audit.h>
+#endif
+#ifdef HAVE_LINUX_AUDIT
+# include <linux_audit.h>
+#endif
+#ifdef HAVE_SOLARIS_AUDIT
+# include <solaris_audit.h>
+#endif
+
+#ifdef SUDOERS_LOG_CLIENT
+static struct log_details audit_details;
+#endif
+char *audit_msg = NULL;
+
+/* sudoers_audit is declared at the end of this file. */
+extern sudo_dso_public struct audit_plugin sudoers_audit;
+
+static int
+audit_success(const struct sudoers_context *ctx, char *const argv[])
+{
+ int rc = 0;
+ debug_decl(audit_success, SUDOERS_DEBUG_AUDIT);
+
+ if (argv != NULL) {
+#ifdef HAVE_BSM_AUDIT
+ if (bsm_audit_success(ctx, argv) == -1)
+ rc = -1;
+#endif
+#ifdef HAVE_LINUX_AUDIT
+ if (linux_audit_command(argv, 1) == -1)
+ rc = -1;
+#endif
+#ifdef HAVE_SOLARIS_AUDIT
+ if (solaris_audit_success(ctx, argv) == -1)
+ rc = -1;
+#endif
+ }
+
+ debug_return_int(rc);
+}
+
+static int
+audit_failure_int(const struct sudoers_context *ctx, char *const argv[],
+ const char *message)
+{
+ int ret = 0;
+ debug_decl(audit_failure_int, SUDOERS_DEBUG_AUDIT);
+
+#if defined(HAVE_BSM_AUDIT) || defined(HAVE_LINUX_AUDIT)
+ if (def_log_denied && argv != NULL) {
+#ifdef HAVE_BSM_AUDIT
+ if (bsm_audit_failure(ctx, argv, message) == -1)
+ ret = -1;
+#endif
+#ifdef HAVE_LINUX_AUDIT
+ if (linux_audit_command(argv, 0) == -1)
+ ret = -1;
+#endif
+#ifdef HAVE_SOLARIS_AUDIT
+ if (solaris_audit_failure(ctx, argv, message) == -1)
+ ret = -1;
+#endif
+ }
+#endif /* HAVE_BSM_AUDIT || HAVE_LINUX_AUDIT */
+
+ debug_return_int(ret);
+}
+
+int
+vaudit_failure(const struct sudoers_context *ctx, char *const argv[],
+ char const * restrict const fmt, va_list ap)
+{
+ int oldlocale, ret;
+ char *message;
+ debug_decl(vaudit_failure, SUDOERS_DEBUG_AUDIT);
+
+ /* Audit messages should be in the sudoers locale. */
+ sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
+
+ if ((ret = vasprintf(&message, _(fmt), ap)) == -1)
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ if (ret != -1) {
+ /* Set audit_msg for audit plugins. */
+ free(audit_msg);
+ audit_msg = message;
+
+ ret = audit_failure_int(ctx, argv, audit_msg);
+ }
+
+ sudoers_setlocale(oldlocale, NULL);
+
+ debug_return_int(ret);
+}
+
+int
+audit_failure(const struct sudoers_context *ctx, char *const argv[],
+ char const * restrict const fmt, ...)
+{
+ va_list ap;
+ int ret;
+ debug_decl(audit_failure, SUDOERS_DEBUG_AUDIT);
+
+ va_start(ap, fmt);
+ ret = vaudit_failure(ctx, argv, fmt, ap);
+ va_end(ap);
+
+ debug_return_int(ret);
+}
+
+static int
+sudoers_audit_open(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t plugin_printf, char * const settings[],
+ char * const user_info[], int submit_optind, char * const submit_argv[],
+ char * const submit_envp[], char * const plugin_options[],
+ const char **errstr)
+{
+ struct sudo_conf_debug_file_list debug_files = TAILQ_HEAD_INITIALIZER(debug_files);
+ struct sudoers_open_info info;
+ const char *cp, *plugin_path = NULL;
+ char * const *cur;
+ int ret;
+ debug_decl(sudoers_audit_open, SUDOERS_DEBUG_PLUGIN);
+
+ sudo_conv = conversation;
+ sudo_printf = plugin_printf;
+ if (sudoers_audit.event_alloc != NULL)
+ plugin_event_alloc = sudoers_audit.event_alloc;
+
+ bindtextdomain("sudoers", LOCALEDIR);
+
+ /* Initialize the debug subsystem. */
+ for (cur = settings; (cp = *cur) != NULL; cur++) {
+ if (strncmp(cp, "debug_flags=", sizeof("debug_flags=") - 1) == 0) {
+ cp += sizeof("debug_flags=") - 1;
+ if (!sudoers_debug_parse_flags(&debug_files, cp))
+ debug_return_int(-1);
+ continue;
+ }
+ if (strncmp(cp, "plugin_path=", sizeof("plugin_path=") - 1) == 0) {
+ plugin_path = cp + sizeof("plugin_path=") - 1;
+ continue;
+ }
+ }
+ if (!sudoers_debug_register(plugin_path, &debug_files))
+ debug_return_int(-1);
+
+ /* Call the sudoers init function. */
+ info.settings = settings;
+ info.user_info = user_info;
+ info.plugin_args = plugin_options;
+ ret = sudoers_init(&info, log_parse_error, submit_envp);
+
+ if (ret == true) {
+ /* Unset close function if we don't need it to avoid extra process. */
+#ifdef SUDOERS_LOG_CLIENT
+ if (client_closure == NULL)
+#endif
+ sudoers_audit.close = NULL;
+ } else {
+ /* The audit functions set audit_msg on failure. */
+ if (audit_msg != NULL)
+ *errstr = audit_msg;
+ }
+
+ debug_return_int(ret);
+}
+
+static void
+audit_to_eventlog(const struct sudoers_context *ctx, struct eventlog *evlog,
+ char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char *uuid_str)
+{
+ char * const *cur;
+ debug_decl(audit_to_eventlog, SUDOERS_DEBUG_PLUGIN);
+
+ /* Fill in evlog from sudoers Defaults, run_argv and run_envp. */
+ sudoers_to_eventlog(ctx, evlog, NULL, run_argv, run_envp, uuid_str);
+
+ /* Update iolog and execution environment from command_info[]. */
+ if (command_info != NULL) {
+ for (cur = command_info; *cur != NULL; cur++) {
+ switch (**cur) {
+ case 'c':
+ if (strncmp(*cur, "command=", sizeof("command=") - 1) == 0) {
+ evlog->command = *cur + sizeof("command=") - 1;
+ continue;
+ }
+ if (strncmp(*cur, "chroot=", sizeof("chroot=") - 1) == 0) {
+ evlog->runchroot = *cur + sizeof("chroot=") - 1;
+ continue;
+ }
+ break;
+ case 'i':
+ if (strncmp(*cur, "iolog_path=", sizeof("iolog_path=") - 1) == 0) {
+ evlog->iolog_path = *cur + sizeof("iolog_path=") - 1;
+ continue;
+ }
+ break;
+ case 'r':
+ if (strncmp(*cur, "runcwd=", sizeof("runcwd=") - 1) == 0) {
+ evlog->runcwd = *cur + sizeof("runcwd=") - 1;
+ continue;
+ }
+ break;
+ }
+ }
+ }
+
+ debug_return;
+}
+
+#ifdef SUDOERS_LOG_CLIENT
+static bool
+log_server_accept(const struct sudoers_context *ctx, struct eventlog *evlog)
+{
+ struct timespec now;
+ bool ret = false;
+ debug_decl(log_server_accept, SUDOERS_DEBUG_PLUGIN);
+
+ if (SLIST_EMPTY(&def_log_servers))
+ debug_return_bool(true);
+
+ if (client_closure != NULL && ISSET(ctx->mode, MODE_POLICY_INTERCEPTED)) {
+ /* Older servers don't support multiple commands per session. */
+ if (!client_closure->subcommands)
+ debug_return_bool(true);
+ } else {
+ /* Only send accept event to log server if I/O log plugin did not. */
+ if (iolog_enabled)
+ debug_return_bool(true);
+ }
+
+ if (sudo_gettime_real(&now) == -1) {
+ sudo_warn("%s", U_("unable to get time of day"));
+ goto done;
+ }
+
+ if (client_closure != NULL) {
+ /* Use existing client closure. */
+ if (fmt_accept_message(client_closure, evlog)) {
+ if (client_closure->write_ev->add(client_closure->write_ev,
+ &client_closure->log_details->server_timeout) == -1) {
+ sudo_warn("%s", U_("unable to add event to queue"));
+ goto done;
+ }
+ ret = true;
+ }
+ } else {
+ if (!init_log_details(&audit_details, evlog))
+ goto done;
+
+ /* Open connection to log server, send hello and accept messages. */
+ client_closure = log_server_open(&audit_details, &now, false,
+ SEND_ACCEPT, NULL);
+ if (client_closure != NULL)
+ ret = true;
+ }
+
+done:
+ debug_return_bool(ret);
+}
+
+static void
+log_server_exit(int status_type, int status)
+{
+ debug_decl(log_server_exit, SUDOERS_DEBUG_PLUGIN);
+
+ if (client_closure != NULL) {
+ int exit_status = 0, error = 0;
+
+ if (status_type == SUDO_PLUGIN_WAIT_STATUS) {
+ if (WIFEXITED(status))
+ exit_status = WEXITSTATUS(status);
+ else
+ exit_status = WTERMSIG(status) | 128;
+ } else {
+ /* Must be errno. */
+ error = status;
+ }
+ log_server_close(client_closure, exit_status, error);
+ client_closure = NULL;
+ free(audit_details.evlog);
+ audit_details.evlog = NULL;
+ }
+
+ debug_return;
+}
+#else
+static bool
+log_server_accept(const struct sudoers_context *ctx, struct eventlog *evlog)
+{
+ return true;
+}
+
+static void
+log_server_exit(int status_type, int status)
+{
+ return;
+}
+#endif /* SUDOERS_LOG_CLIENT */
+
+static int
+sudoers_audit_accept(const char *plugin_name, unsigned int plugin_type,
+ char * const command_info[], char * const run_argv[],
+ char * const run_envp[], const char **errstr)
+{
+ const struct sudoers_context *ctx = sudoers_get_context();
+ const char *uuid_str = NULL;
+ struct eventlog evlog;
+ static bool first = true;
+ int ret = true;
+ debug_decl(sudoers_audit_accept, SUDOERS_DEBUG_PLUGIN);
+
+ /* Only log the accept event from the sudo front-end */
+ if (plugin_type != SUDO_FRONT_END)
+ debug_return_int(true);
+
+ /* Log sub-commands with the uuid of the original command. */
+ if (!ISSET(ctx->mode, MODE_POLICY_INTERCEPTED))
+ uuid_str = ctx->uuid_str;
+
+ /*
+ * We must always call log_allowed() even if def_log_allowed is disabled
+ * since it will send mail if def_mail_always or def_mail_all_cmnds are
+ * set (it has its own checks for def_log_allowed).
+ */
+ audit_to_eventlog(ctx, &evlog, command_info, run_argv, run_envp, uuid_str);
+ if (!log_allowed(ctx, &evlog) && !def_ignore_logfile_errors)
+ ret = false;
+
+ /*
+ * Skip auditing and log server logging if "log_allowed" is disabled.
+ */
+ if (!def_log_allowed)
+ goto done;
+
+ if (audit_success(ctx, run_argv) != 0) {
+ if (!def_ignore_logfile_errors)
+ ret = false;
+ }
+
+ if (!log_server_accept(ctx, &evlog)) {
+ if (!def_ignore_logfile_errors)
+ ret = false;
+ }
+
+ if (first) {
+ /* log_subcmds doesn't go through sudo_policy_main again to set this. */
+ if (def_log_subcmds) {
+ if (!sudoers_set_mode(MODE_POLICY_INTERCEPTED, UINT_MAX)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to set 0x%x in ctx->mode", MODE_POLICY_INTERCEPTED);
+ }
+ }
+ first = false;
+ }
+
+done:
+ debug_return_int(ret);
+}
+
+static int
+sudoers_audit_reject(const char *plugin_name, unsigned int plugin_type,
+ const char *message, char * const command_info[], const char **errstr)
+{
+ const struct sudoers_context *ctx = sudoers_get_context();
+ struct eventlog evlog;
+ int ret = true;
+ debug_decl(sudoers_audit_reject, SUDOERS_DEBUG_PLUGIN);
+
+ /* Skip reject events that sudoers generated itself. */
+ if (strncmp(plugin_name, "sudoers_", 8) == 0)
+ debug_return_int(true);
+
+ if (!def_log_denied)
+ debug_return_int(true);
+
+ if (audit_failure_int(ctx, ctx->runas.argv, message) != 0) {
+ if (!def_ignore_audit_errors)
+ ret = false;
+ }
+
+ audit_to_eventlog(ctx, &evlog, command_info, ctx->runas.argv, NULL, NULL);
+ if (!eventlog_reject(&evlog, 0, message, NULL, NULL))
+ ret = false;
+
+ if (!log_server_reject(ctx, &evlog, message))
+ ret = false;
+
+ debug_return_int(ret);
+}
+
+static int
+sudoers_audit_error(const char *plugin_name, unsigned int plugin_type,
+ const char *message, char * const command_info[], const char **errstr)
+{
+ const struct sudoers_context *ctx = sudoers_get_context();
+ struct eventlog evlog;
+ struct timespec now;
+ int ret = true;
+ debug_decl(sudoers_audit_error, SUDOERS_DEBUG_PLUGIN);
+
+ /* Skip error events that sudoers generated itself. */
+ if (strncmp(plugin_name, "sudoers_", 8) == 0)
+ debug_return_int(true);
+
+ if (audit_failure_int(ctx, ctx->runas.argv, message) != 0) {
+ if (!def_ignore_audit_errors)
+ ret = false;
+ }
+
+ if (sudo_gettime_real(&now)) {
+ sudo_warn("%s", U_("unable to get time of day"));
+ debug_return_bool(false);
+ }
+
+ audit_to_eventlog(ctx, &evlog, command_info, ctx->runas.argv, NULL, NULL);
+ if (!eventlog_alert(&evlog, 0, &now, message, NULL))
+ ret = false;
+
+ if (!log_server_alert(ctx, &evlog, &now, message, NULL))
+ ret = false;
+
+ debug_return_int(ret);
+}
+
+static void
+sudoers_audit_close(int status_type, int status)
+{
+ log_server_exit(status_type, status);
+}
+
+static int
+sudoers_audit_version(int verbose)
+{
+ debug_decl(sudoers_audit_version, SUDOERS_DEBUG_PLUGIN);
+
+ sudo_printf(SUDO_CONV_INFO_MSG, "Sudoers audit plugin version %s\n",
+ PACKAGE_VERSION);
+
+ debug_return_int(true);
+}
+
+sudo_dso_public struct audit_plugin sudoers_audit = {
+ SUDO_AUDIT_PLUGIN,
+ SUDO_API_VERSION,
+ sudoers_audit_open,
+ sudoers_audit_close,
+ sudoers_audit_accept,
+ sudoers_audit_reject,
+ sudoers_audit_error,
+ sudoers_audit_version,
+ NULL, /* register_hooks */
+ NULL, /* deregister_hooks */
+ NULL /* event_alloc() filled in by sudo */
+};
diff --git a/plugins/sudoers/auth/API b/plugins/sudoers/auth/API
new file mode 100644
index 0000000..b38a1c4
--- /dev/null
+++ b/plugins/sudoers/auth/API
@@ -0,0 +1,148 @@
+NOTE: the Sudo auth API is subject to change
+
+Purpose: to provide a simple API for authentication methods that
+ encapsulates things nicely without turning into a maze
+ of #ifdef's
+
+The sudo_auth struct looks like this:
+
+typedef struct sudo_auth {
+ unsigned int flags; /* various flags, see below */
+ int status; /* status from verify routine */
+ char *name; /* name of the method in string form */
+ void *data; /* method-specific data pointer */
+
+ int (*init)(struct passwd *pw, sudo_auth *auth);
+ int (*setup)(struct passwd *pw, char **prompt, sudo_auth *auth);
+ int (*verify)(struct passwd *pw, const char *p, sudo_auth *auth, struct sudo_conv_callback *callback);
+ int (*approval)(struct passwd *pw, sudo_auth *auth);
+ int (*cleanup)(struct passwd *pw, sudo_auth *auth, bool force);
+ int (*begin_session)(struct passwd *pw, char **user_env[], struct sudo_auth *auth);
+ int (*end_session)(struct passwd *pw, struct sudo_auth *auth);
+} sudo_auth;
+
+The variables in the struct are as follows:
+ flags Bitwise binary flags, see below.
+
+ status Contains the return value from the last run of
+ the "verify" function. Starts out as AUTH_FAILURE.
+
+ name The name of the authentication method as a C string.
+
+ data A pointer to method-specific data. This is passed to
+ all the functions of an auth method and is usually
+ initialized in the "init" or "setup" routines.
+
+Possible values of sudo_auth.flags:
+ FLAG_DISABLED Set if an "init" or "setup" function fails.
+
+ FLAG_STANDALONE If set, this indicates that the method must
+ be the only auth method configured, and that
+ it will prompt for the password itself.
+
+ FLAG_ONEANDONLY If set, this indicates that the method is the
+ only one in use. Can be used by auth functions
+ to determine whether to return a fatal or nonfatal
+ error.
+
+ FLAG_NONINTERACTIVE If set, this indicates that the user invoked
+ sudo with the -n option and no user interaction
+ is allowed.
+
+The member functions can return the following values:
+ AUTH_SUCCESS Function succeeded. For a ``verify'' function
+ this means the user correctly authenticated.
+
+ AUTH_FAILURE Function failed. If this is an ``init'' or
+ ``setup'' routine, the auth method will be
+ marked as !configured.
+
+ AUTH_ERROR A fatal error occurred. The routine should have
+ written an error message to stderr and optionally
+ sent mail to the administrator. When verify_user()
+ receives AUTH_ERROR from an auth function it stops
+ authenticating and returns an error.
+
+ AUTH_INTR An attempt to read the password read was interrupted.
+ Usually this means the user entered ^C at the
+ password prompt.
+
+ AUTH_NONINTERACTIVE Function failed because user interaction was
+ required but sudo was run in non-interactive
+ mode.
+
+The functions in the struct are as follows:
+
+ int init(struct passwd *pw, sudo_auth *auth)
+ Function to do any one-time initialization for the auth
+ method. All of the "init" functions are run before anything
+ else.
+
+ int setup(struct passwd *pw, char **prompt, sudo_auth *auth)
+ Function to do method-specific setup. All the "setup"
+ routines are run before any of the "verify" routines. A
+ pointer to the prompt string may be used to add method-specific
+ info to the prompt.
+
+ int verify(struct passwd *pw, char *p, sudo_auth *auth, struct sudo_conv_callback *callback)
+ Function to do user verification for this auth method. For
+ standalone auth methods ``p'' is the prompt string. For
+ normal auth methods, ``p'' is the password the user entered.
+ The callback should be passed to auth_getpass() to allow sudoers
+ to unlock the ticket file when sudo is suspended.
+ Note that standalone auth methods are responsible for
+ rerading the password themselves.
+
+ int approval(struct passwd *pw, struct sudo_auth *auth)
+ Function to perform account management and approval *after*
+ the user has authenticated successfully. This function may
+ check for expired accounts, perform time of day restrictions, etc.
+ For PAM, this calls pam_acct_mgmt(). For BSD auth, it calls
+ auth_approval().
+
+ int cleanup(struct passwd *pw, sudo_auth *auth, bool force)
+ Function to do per-auth method cleanup. This is only run
+ at the end of the authentication process, after the user
+ has completely failed or succeeded to authenticate.
+ The ``auth->status'' variable contains the result of the
+ last authentication attempt which may be interesting.
+ If the force flag is set, cleanup should happen immediately.
+
+ int begin_session(struct passwd *pw, char **user_env[], struct sudo_auth *auth)
+ Function to begin a user session. This is used for session handling
+ in PAM and SIA.
+
+ int end_session(struct passwd *pw, struct sudo_auth *auth)
+ Function to end a user session. This is used for session handling
+ in PAM and SIA.
+
+A note about standalone methods. Some authentication methods can't
+coexist with any others. This may be because they encapsulate other
+methods (pam, sia) or because they have a special way of interacting
+with the user (securid).
+
+Adding a new authentication method:
+
+Each method should live in its own file. Add prototypes for the functions
+in sudo_auth.h.
+
+Add the method to the ``auth_switch'' in sudo_auth.c. Note that
+standalone methods must go first. If ``fooauth'' is a normal auth
+method, its entry would look like:
+
+#ifdef HAVE_FOOAUTH
+AUTH_ENTRY("foo", 0, foo_init, foo_setup, foo_verify,
+ foo_cleanup, foo_begin_session, foo_end_session)
+#endif
+
+If this is a standalone method, it would be:
+
+#ifdef HAVE_FOOAUTH
+AUTH_ENTRY("foo", FLAG_STANDALONE, foo_init, foo_setup, foo_verify,
+ foo_cleanup, foo_begin_session, foo_end_session)
+#endif
+
+If the method needs to run as the user, not root, add FLAG_USER to
+the second argument in the AUTH_ENTRY line. If you don't have an
+init/setup/cleanup/begin/end routine, just use a NULL for that
+field.
diff --git a/plugins/sudoers/auth/afs.c b/plugins/sudoers/auth/afs.c
new file mode 100644
index 0000000..7fae207
--- /dev/null
+++ b/plugins/sudoers/auth/afs.c
@@ -0,0 +1,88 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999, 2001-2005, 2007, 2010-2012, 2014-2015
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_AFS
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#include <afs/stds.h>
+#include <afs/kautils.h>
+
+#include <sudoers.h>
+#include "sudo_auth.h"
+#include <timestamp.h>
+
+int
+sudo_afs_verify(const struct sudoers_context *ctx, struct passwd *pw,
+ const char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
+{
+ struct ktc_encryptionKey afs_key;
+ struct ktc_token afs_token;
+ debug_decl(sudo_afs_verify, SUDOERS_DEBUG_AUTH);
+
+ if (IS_NONINTERACTIVE(auth))
+ debug_return_int(AUTH_NONINTERACTIVE);
+
+ /* Display lecture if needed and we haven't already done so. */
+ display_lecture(callback);
+
+ /* Try to just check the password */
+ ka_StringToKey(pass, NULL, &afs_key);
+ if (ka_GetAdminToken(pw->pw_name, /* name */
+ NULL, /* instance */
+ NULL, /* realm */
+ &afs_key, /* key (contains password) */
+ 0, /* lifetime */
+ &afs_token, /* token */
+ 0) == 0) /* new */
+ debug_return_int(AUTH_SUCCESS);
+
+ /* Fall back on old method XXX - needed? */
+ setpag();
+ if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION+KA_USERAUTH_DOSETPAG,
+ pw->pw_name, /* name */
+ NULL, /* instance */
+ NULL, /* realm */
+ pass, /* password */
+ 0, /* lifetime */
+ NULL, /* expiration ptr (unused) */
+ 0, /* spare */
+ NULL) == 0) /* reason */
+ debug_return_int(AUTH_SUCCESS);
+
+ debug_return_int(AUTH_FAILURE);
+}
+
+#endif HAVE_AFS
diff --git a/plugins/sudoers/auth/aix_auth.c b/plugins/sudoers/auth/aix_auth.c
new file mode 100644
index 0000000..74a3bc9
--- /dev/null
+++ b/plugins/sudoers/auth/aix_auth.c
@@ -0,0 +1,314 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999-2005, 2007-2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_AIXAUTH
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <pwd.h>
+#include <signal.h>
+#include <usersec.h>
+
+#include <sudoers.h>
+#include "sudo_auth.h"
+
+/*
+ * For a description of the AIX authentication API, see
+ * http://publib16.boulder.ibm.com/doc_link/en_US/a_doc_lib/libs/basetrf1/authenticate.htm
+ */
+
+#ifdef HAVE_PAM
+# define AIX_AUTH_UNKNOWN 0
+# define AIX_AUTH_STD 1
+# define AIX_AUTH_PAM 2
+
+static int
+sudo_aix_authtype(void)
+{
+ size_t linesize = 0;
+ ssize_t len;
+ char *cp, *line = NULL;
+ bool in_stanza = false;
+ int authtype = AIX_AUTH_UNKNOWN;
+ FILE *fp;
+ debug_decl(sudo_aix_authtype, SUDOERS_DEBUG_AUTH);
+
+ if ((fp = fopen("/etc/security/login.cfg", "r")) == NULL)
+ debug_return_int(AIX_AUTH_UNKNOWN);
+
+ while ((len = getdelim(&line, &linesize, '\n', fp)) != -1) {
+ /* First remove comments. */
+ if ((cp = strchr(line, '#')) != NULL) {
+ *cp = '\0';
+ len = (ssize_t)(cp - line);
+ }
+
+ /* Next remove trailing newlines and whitespace. */
+ while (len > 0 && isspace((unsigned char)line[len - 1]))
+ line[--len] = '\0';
+
+ /* Skip blank lines. */
+ if (len == 0)
+ continue;
+
+ /* Match start of the usw stanza. */
+ if (!in_stanza) {
+ if (strncmp(line, "usw:", 4) == 0)
+ in_stanza = true;
+ continue;
+ }
+
+ /* Check for end of the usw stanza. */
+ if (!isblank((unsigned char)line[0])) {
+ in_stanza = false;
+ break;
+ }
+
+ /* Skip leading blanks. */
+ cp = line;
+ do {
+ cp++;
+ } while (isblank((unsigned char)*cp));
+
+ /* Match "auth_type = (PAM_AUTH|STD_AUTH)". */
+ if (strncmp(cp, "auth_type", 9) != 0)
+ continue;
+ cp += 9;
+ while (isblank((unsigned char)*cp))
+ cp++;
+ if (*cp++ != '=')
+ continue;
+ while (isblank((unsigned char)*cp))
+ cp++;
+ if (strcmp(cp, "PAM_AUTH") == 0) {
+ authtype = AIX_AUTH_PAM;
+ break;
+ }
+ if (strcmp(cp, "STD_AUTH") == 0) {
+ authtype = AIX_AUTH_STD;
+ break;
+ }
+ }
+ free(line);
+ fclose(fp);
+
+ debug_return_int(authtype);
+}
+#endif /* HAVE_PAM */
+
+int
+sudo_aix_init(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth)
+{
+ debug_decl(sudo_aix_init, SUDOERS_DEBUG_AUTH);
+
+#ifdef HAVE_PAM
+ /* Check auth_type in /etc/security/login.cfg. */
+ if (sudo_aix_authtype() == AIX_AUTH_PAM) {
+ if (sudo_pam_init_quiet(ctx, pw, auth) == AUTH_SUCCESS) {
+ /* Fail AIX authentication so we can use PAM instead. */
+ debug_return_int(AUTH_FAILURE);
+ }
+ }
+#endif
+ debug_return_int(AUTH_SUCCESS);
+}
+
+/* Ignore AIX password incorrect message */
+static bool
+sudo_aix_valid_message(const char *message)
+{
+ const char *cp;
+ const char badpass_msgid[] = "3004-300";
+ debug_decl(sudo_aix_valid_message, SUDOERS_DEBUG_AUTH);
+
+ if (message == NULL || message[0] == '\0')
+ debug_return_bool(false);
+
+ /* Match "3004-300: You entered an invalid login name or password" */
+ for (cp = message; *cp != '\0'; cp++) {
+ if (isdigit((unsigned char)*cp)) {
+ if (strncmp(cp, badpass_msgid, strlen(badpass_msgid)) == 0)
+ debug_return_bool(false);
+ break;
+ }
+ }
+ debug_return_bool(true);
+}
+
+/*
+ * Change the user's password. If root changes the user's password
+ * the ADMCHG flag is set on the account (and the user must change
+ * it again) so we run passwd(1) as the user. This does mean that
+ * the user will need to re-enter their original password again,
+ * unlike with su(1). We may consider using pwdadm(1) as root to
+ * change the password and then clear the flag in the future.
+ */
+static bool
+sudo_aix_change_password(const struct sudoers_context *ctx, const char *user)
+{
+ struct sigaction sa, savechld;
+ pid_t child, pid;
+ bool ret = false;
+ sigset_t mask;
+ int status;
+ debug_decl(sudo_aix_change_password, SUDOERS_DEBUG_AUTH);
+
+ /* Set SIGCHLD handler to default since we call waitpid() below. */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = SIG_DFL;
+ (void) sigaction(SIGCHLD, &sa, &savechld);
+
+ switch (child = sudo_debug_fork()) {
+ case -1:
+ /* error */
+ sudo_warn("%s", U_("unable to fork"));
+ break;
+ case 0:
+ /* child, run passwd(1) */
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGQUIT);
+ (void) sigprocmask(SIG_UNBLOCK, &mask, NULL);
+ set_perms(ctx, PERM_USER);
+ execl("/usr/bin/passwd", "passwd", user, (char *)NULL);
+ sudo_warn("passwd");
+ _exit(127);
+ /* NOTREACHED */
+ default:
+ /* parent */
+ break;
+ }
+
+ /* Wait for passwd(1) to complete. */
+ do {
+ pid = waitpid(child, &status, 0);
+ } while (pid == -1 && errno == EINTR);
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "child (%d) exit value %d", (int)child, status);
+ if (pid != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0)
+ ret = true;
+
+ /* Restore saved SIGCHLD handler. */
+ (void) sigaction(SIGCHLD, &savechld, NULL);
+
+ debug_return_bool(ret);
+}
+
+int
+sudo_aix_verify(const struct sudoers_context *ctx, struct passwd *pw,
+ const char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback)
+{
+ char *pass, *message = NULL;
+ int result = 1, reenter = 0;
+ int ret = AUTH_SUCCESS;
+ debug_decl(sudo_aix_verify, SUDOERS_DEBUG_AUTH);
+
+ if (IS_NONINTERACTIVE(auth))
+ debug_return_int(AUTH_NONINTERACTIVE);
+
+ do {
+ pass = auth_getpass(prompt, SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ if (pass == NULL)
+ break;
+ free(message);
+ message = NULL;
+ result = authenticate(pw->pw_name, pass, &reenter, &message);
+ freezero(pass, strlen(pass));
+ prompt = message;
+ } while (reenter);
+
+ if (result != 0) {
+ /* Display error message, if any. */
+ if (sudo_aix_valid_message(message))
+ sudo_printf(SUDO_CONV_ERROR_MSG|SUDO_CONV_PREFER_TTY,
+ "%s", message);
+ ret = pass ? AUTH_FAILURE : AUTH_INTR;
+ }
+ free(message);
+ message = NULL;
+
+ /* Check if password expired and allow user to change it if possible. */
+ if (ret == AUTH_SUCCESS) {
+ result = passwdexpired(pw->pw_name, &message);
+ if (message != NULL && message[0] != '\0') {
+ int msg_type = SUDO_CONV_PREFER_TTY;
+ msg_type |= result ? SUDO_CONV_ERROR_MSG : SUDO_CONV_INFO_MSG,
+ sudo_printf(msg_type, "%s", message);
+ free(message);
+ message = NULL;
+ }
+ switch (result) {
+ case 0:
+ /* password not expired. */
+ break;
+ case 1:
+ /* password expired, user must change it */
+ if (!sudo_aix_change_password(ctx, pw->pw_name)) {
+ sudo_warnx(U_("unable to change password for %s"), pw->pw_name);
+ ret = AUTH_ERROR;
+ }
+ break;
+ case 2:
+ /* password expired, only admin can change it */
+ ret = AUTH_ERROR;
+ break;
+ default:
+ /* error (-1) */
+ sudo_warn("passwdexpired");
+ ret = AUTH_ERROR;
+ break;
+ }
+ }
+
+ debug_return_int(ret);
+}
+
+int
+sudo_aix_cleanup(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth, bool force)
+{
+ debug_decl(sudo_aix_cleanup, SUDOERS_DEBUG_AUTH);
+
+ /* Unset AUTHSTATE as it may not be correct for the runas user. */
+ if (sudo_unsetenv("AUTHSTATE") == -1)
+ debug_return_int(AUTH_FAILURE);
+
+ debug_return_int(AUTH_SUCCESS);
+}
+
+#endif /* HAVE_AIXAUTH */
diff --git a/plugins/sudoers/auth/bsdauth.c b/plugins/sudoers/auth/bsdauth.c
new file mode 100644
index 0000000..d48148c
--- /dev/null
+++ b/plugins/sudoers/auth/bsdauth.c
@@ -0,0 +1,224 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2000-2005, 2007-2008, 2010-2015
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_BSD_AUTH_H
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <signal.h>
+
+#include <login_cap.h>
+#include <bsd_auth.h>
+
+#include <sudoers.h>
+#include "sudo_auth.h"
+
+# ifndef LOGIN_DEFROOTCLASS
+# define LOGIN_DEFROOTCLASS "daemon"
+# endif
+
+struct bsdauth_state {
+ auth_session_t *as;
+ login_cap_t *lc;
+};
+
+static char *login_style; /* user may set style via -a option */
+
+int
+bsdauth_init(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth)
+{
+ static struct bsdauth_state state;
+ debug_decl(bsdauth_init, SUDOERS_DEBUG_AUTH);
+
+ /* Only initialize once. */
+ if (auth->data != NULL)
+ debug_return_int(AUTH_SUCCESS);
+
+ /* Get login class based on auth user, which may not be invoking user. */
+ if (pw->pw_class && *pw->pw_class) {
+ state.lc = login_getclass(pw->pw_class);
+ } else {
+ state.lc = login_getclass(
+ pw->pw_uid ? (char *)LOGIN_DEFCLASS : (char *)LOGIN_DEFROOTCLASS);
+ }
+ if (state.lc == NULL) {
+ log_warning(ctx, 0, N_("unable to get login class for user %s"),
+ pw->pw_name);
+ goto bad;
+ }
+
+ login_style = login_getstyle(state.lc, login_style, (char *)"auth-sudo");
+ if (login_style == NULL) {
+ log_warningx(ctx, 0, N_("invalid authentication type"));
+ goto bad;
+ }
+
+ if ((state.as = auth_open()) == NULL) {
+ log_warning(ctx, 0, N_("unable to begin BSD authentication"));
+ goto bad;
+ }
+
+ if (auth_setitem(state.as, AUTHV_STYLE, login_style) < 0 ||
+ auth_setitem(state.as, AUTHV_NAME, pw->pw_name) < 0 ||
+ auth_setitem(state.as, AUTHV_CLASS, ctx->runas.class) < 0) {
+ log_warningx(ctx, 0, N_("unable to initialize BSD authentication"));
+ goto bad;
+ }
+
+ auth->data = (void *) &state;
+ debug_return_int(AUTH_SUCCESS);
+bad:
+ auth_close(state.as);
+ login_close(state.lc);
+ debug_return_int(AUTH_ERROR);
+}
+
+int
+bsdauth_verify(const struct sudoers_context *ctx, struct passwd *pw,
+ const char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback)
+{
+ char *pass;
+ char *s;
+ size_t len;
+ int authok = 0;
+ struct sigaction sa, osa;
+ auth_session_t *as = ((struct bsdauth_state *) auth->data)->as;
+ debug_decl(bsdauth_verify, SUDOERS_DEBUG_AUTH);
+
+ if (IS_NONINTERACTIVE(auth))
+ debug_return_int(AUTH_NONINTERACTIVE);
+
+ /* save old signal handler */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = SIG_DFL;
+ (void) sigaction(SIGCHLD, &sa, &osa);
+
+ /*
+ * If there is a challenge then print that instead of the normal
+ * prompt. If the user just hits return we prompt again with echo
+ * turned on, which is useful for challenge/response things like
+ * S/Key.
+ */
+ if ((s = auth_challenge(as)) == NULL) {
+ pass = auth_getpass(prompt, SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ } else {
+ pass = auth_getpass(s, SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ if (pass != NULL && *pass == '\0') {
+ if ((prompt = strrchr(s, '\n')))
+ prompt++;
+ else
+ prompt = s;
+
+ /*
+ * Append '[echo on]' to the last line of the challenge and
+ * re-prompt with echo turned on.
+ */
+ len = strlen(prompt);
+ while (len > 0 && (isspace((unsigned char)prompt[len - 1]) || prompt[len - 1] == ':'))
+ len--;
+ if (asprintf(&s, "%.*s [echo on]: ", (int)len, prompt) == -1) {
+ log_warningx(ctx, 0, N_("unable to allocate memory"));
+ debug_return_int(AUTH_ERROR);
+ }
+ free(pass);
+ pass = auth_getpass(s, SUDO_CONV_PROMPT_ECHO_ON, callback);
+ free(s);
+ }
+ }
+
+ if (pass != NULL) {
+ authok = auth_userresponse(as, pass, 1);
+ freezero(pass, strlen(pass));
+ }
+
+ /* restore old signal handler */
+ (void) sigaction(SIGCHLD, &osa, NULL);
+
+ if (authok)
+ debug_return_int(AUTH_SUCCESS);
+
+ if (pass == NULL)
+ debug_return_int(AUTH_INTR);
+
+ if ((s = auth_getvalue(as, (char *)"errormsg")) != NULL)
+ log_warningx(ctx, 0, "%s", s);
+ debug_return_int(AUTH_FAILURE);
+}
+
+int
+bsdauth_approval(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth, bool exempt)
+{
+ struct bsdauth_state *state = auth->data;
+ debug_decl(bsdauth_approval, SUDOERS_DEBUG_AUTH);
+
+ if (auth_approval(state->as, state->lc, pw->pw_name, (char *)"auth-sudo") == 0) {
+ if (auth_getstate(state->as) & AUTH_EXPIRED)
+ log_warningx(ctx, 0, "%s", N_("your account has expired"));
+ else
+ log_warningx(ctx, 0, "%s", N_("approval failed"));
+ debug_return_int(AUTH_FAILURE);
+ }
+ debug_return_int(AUTH_SUCCESS);
+}
+
+int
+bsdauth_cleanup(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth, bool force)
+{
+ struct bsdauth_state *state = auth->data;
+ debug_decl(bsdauth_cleanup, SUDOERS_DEBUG_AUTH);
+
+ if (state != NULL) {
+ auth_close(state->as);
+ state->as = NULL;
+ login_close(state->lc);
+ state->lc = NULL;
+ auth->data = NULL;
+ }
+ login_style = NULL;
+
+ debug_return_int(AUTH_SUCCESS);
+}
+
+void
+bsdauth_set_style(const char *style)
+{
+ login_style = (char *)style;
+}
+
+#endif /* HAVE_BSD_AUTH_H */
diff --git a/plugins/sudoers/auth/dce.c b/plugins/sudoers/auth/dce.c
new file mode 100644
index 0000000..aa7c47b
--- /dev/null
+++ b/plugins/sudoers/auth/dce.c
@@ -0,0 +1,202 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2010-2012, 2014-2015
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+/*
+ * The code below basically comes from the examples supplied on
+ * the OSF DCE 1.0.3 manpages for the sec_login routines, with
+ * enough additional polishing to make the routine work with the
+ * rest of sudo.
+ *
+ * This code is known to work on HP 700 and 800 series systems
+ * running HP-UX 9.X and 10.X, with either HP's version 1.2.1 of DCE.
+ * (aka, OSF DCE 1.0.3) or with HP's version 1.4 of DCE (aka, OSF
+ * DCE 1.1).
+ */
+
+#include <config.h>
+
+#ifdef HAVE_DCE
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#include <dce/rpc.h>
+#include <dce/sec_login.h>
+#include <dce/dce_error.h> /* required to call dce_error_inq_text routine */
+
+#include <sudoers.h>
+#include "sudo_auth.h"
+#include <timestamp.h>
+
+static int check_dce_status(error_status_t, char *);
+
+int
+sudo_dce_verify(const struct sudoers_context *ctx, struct passwd *pw,
+ const char *plain_pw, sudo_auth *auth, struct sudo_conv_callback *callback)
+{
+ struct passwd temp_pw;
+ sec_passwd_rec_t password_rec;
+ sec_login_handle_t login_context;
+ boolean32 reset_passwd;
+ sec_login_auth_src_t auth_src;
+ error_status_t status;
+ debug_decl(sudo_dce_verify, SUDOERS_DEBUG_AUTH);
+
+ if (IS_NONINTERACTIVE(auth))
+ debug_return_int(AUTH_NONINTERACTIVE);
+
+ /* Display lecture if needed and we haven't already done so. */
+ display_lecture(callback);
+
+ /*
+ * Create the local context of the DCE principal necessary
+ * to perform authenticated network operations. The network
+ * identity set up by this operation cannot be used until it
+ * is validated via sec_login_validate_identity().
+ */
+ if (sec_login_setup_identity((unsigned_char_p_t) pw->pw_name,
+ sec_login_no_flags, &login_context, &status)) {
+
+ if (check_dce_status(status, "sec_login_setup_identity(1):"))
+ debug_return_int(AUTH_FAILURE);
+
+ password_rec.key.key_type = sec_passwd_plain;
+ password_rec.key.tagged_union.plain = (idl_char *) plain_pw;
+ password_rec.pepper = NULL;
+ password_rec.version_number = sec_passwd_c_version_none;
+
+ /* Validate the login context with the password */
+ if (sec_login_validate_identity(login_context, &password_rec,
+ &reset_passwd, &auth_src, &status)) {
+
+ if (check_dce_status(status, "sec_login_validate_identity(1):"))
+ debug_return_int(AUTH_FAILURE);
+
+ /*
+ * Certify that the DCE Security Server used to set
+ * up and validate a login context is legitimate. Makes
+ * sure that we didn't get spoofed by another DCE server.
+ */
+ if (!sec_login_certify_identity(login_context, &status)) {
+ sudo_printf(SUDO_CONV_ERROR_MSG|SUDO_CONV_PREFER_TTY,
+ "Whoa! Bogus authentication server!\n");
+ (void) check_dce_status(status,"sec_login_certify_identity(1):");
+ debug_return_int(AUTH_FAILURE);
+ }
+ if (check_dce_status(status, "sec_login_certify_identity(2):"))
+ debug_return_int(AUTH_FAILURE);
+
+ /*
+ * Sets the network credentials to those specified
+ * by the now validated login context.
+ */
+ sec_login_set_context(login_context, &status);
+ if (check_dce_status(status, "sec_login_set_context:"))
+ debug_return_int(AUTH_FAILURE);
+
+ /*
+ * Oops, your credentials were no good. Possibly
+ * caused by clock times out of adjustment between
+ * DCE client and DCE security server...
+ */
+ if (auth_src != sec_login_auth_src_network) {
+ sudo_printf(SUDO_CONV_ERROR_MSG|SUDO_CONV_PREFER_TTY,
+ "You have no network credentials.\n");
+ debug_return_int(AUTH_FAILURE);
+ }
+ /* Check if the password has aged and is thus no good */
+ if (reset_passwd) {
+ sudo_printf(SUDO_CONV_ERROR_MSG|SUDO_CONV_PREFER_TTY,
+ "Your DCE password needs resetting.\n");
+ debug_return_int(AUTH_FAILURE);
+ }
+
+ /*
+ * We should be a valid user by this point. Pull the
+ * user's password structure from the DCE security
+ * server just to make sure. If we get it with no
+ * problems, then we really are legitimate...
+ */
+ sec_login_get_pwent(login_context, (sec_login_passwd_t) &temp_pw,
+ &status);
+ if (check_dce_status(status, "sec_login_get_pwent:"))
+ debug_return_int(AUTH_FAILURE);
+
+ /*
+ * If we get to here, then the pwent above properly fetched
+ * the password structure from the DCE registry, so the user
+ * must be valid. We don't really care what the user's
+ * registry password is, just that the user could be
+ * validated. In fact, if we tried to compare the local
+ * password to the DCE entry at this point, the operation
+ * would fail if the hidden password feature is turned on,
+ * because the password field would contain an asterisk.
+ * Also go ahead and destroy the user's DCE login context
+ * before we leave here (and don't bother checking the
+ * status), in order to clean up credentials files in
+ * /opt/dcelocal/var/security/creds. By doing this, we are
+ * assuming that the user will not need DCE authentication
+ * later in the program, only local authentication. If this
+ * is not true, then the login_context will have to be
+ * returned to the calling program, and the context purged
+ * somewhere later in the program.
+ */
+ sec_login_purge_context(&login_context, &status);
+ debug_return_int(AUTH_SUCCESS);
+ } else {
+ if(check_dce_status(status, "sec_login_validate_identity(2):"))
+ debug_return_int(AUTH_FAILURE);
+ sec_login_purge_context(&login_context, &status);
+ if(check_dce_status(status, "sec_login_purge_context:"))
+ debug_return_int(AUTH_FAILURE);
+ }
+ }
+ (void) check_dce_status(status, "sec_login_setup_identity(2):");
+ debug_return_int(AUTH_FAILURE);
+}
+
+/* Returns 0 for DCE "ok" status, 1 otherwise */
+static int
+check_dce_status(error_status_t input_status, char *comment)
+{
+ int error_stat;
+ unsigned char error_string[dce_c_error_string_len];
+ debug_decl(check_dce_status, SUDOERS_DEBUG_AUTH);
+
+ if (input_status == rpc_s_ok)
+ debug_return_int(0);
+ dce_error_inq_text(input_status, error_string, &error_stat);
+ sudo_printf(SUDO_CONV_ERROR_MSG|SUDO_CONV_PREFER_TTY,
+ "%s %s\n", comment, error_string);
+ debug_return_int(1);
+}
+
+#endif /* HAVE_DCE */
diff --git a/plugins/sudoers/auth/fwtk.c b/plugins/sudoers/auth/fwtk.c
new file mode 100644
index 0000000..ae62c97
--- /dev/null
+++ b/plugins/sudoers/auth/fwtk.c
@@ -0,0 +1,161 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999-2005, 2008, 2010-2015
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_FWTK
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#include <auth.h>
+#include <firewall.h>
+
+#include <sudoers.h>
+#include "sudo_auth.h"
+
+int
+sudo_fwtk_init(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth)
+{
+ static Cfg *confp; /* Configuration entry struct */
+ char resp[128]; /* Response from the server */
+ debug_decl(sudo_fwtk_init, SUDOERS_DEBUG_AUTH);
+
+ /* Only initialize once. */
+ if (auth->data != NULL)
+ debug_return_int(AUTH_SUCCESS);
+
+ if (IS_NONINTERACTIVE(auth))
+ debug_return_int(AUTH_NONINTERACTIVE);
+
+ if ((confp = cfg_read("sudo")) == (Cfg *)-1) {
+ sudo_warnx("%s", U_("unable to read fwtk config"));
+ debug_return_int(AUTH_ERROR);
+ }
+
+ if (auth_open(confp)) {
+ sudo_warnx("%s", U_("unable to connect to authentication server"));
+ debug_return_int(AUTH_ERROR);
+ }
+
+ /* Get welcome message from auth server */
+ if (auth_recv(resp, sizeof(resp))) {
+ sudo_warnx("%s", U_("lost connection to authentication server"));
+ debug_return_int(AUTH_ERROR);
+ }
+ if (strncmp(resp, "Authsrv ready", 13) != 0) {
+ sudo_warnx(U_("authentication server error:\n%s"), resp);
+ debug_return_int(AUTH_ERROR);
+ }
+ auth->data = (void *) confp;
+
+ debug_return_int(AUTH_SUCCESS);
+}
+
+int
+sudo_fwtk_verify(const struct sudoers_context *ctx, struct passwd *pw,
+ const char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback)
+{
+ char *pass; /* Password from the user */
+ char buf[SUDO_CONV_REPL_MAX + 12]; /* General prupose buffer */
+ char resp[128]; /* Response from the server */
+ int error;
+ debug_decl(sudo_fwtk_verify, SUDOERS_DEBUG_AUTH);
+
+ /* Send username to authentication server. */
+ (void) snprintf(buf, sizeof(buf), "authorize %s 'sudo'", pw->pw_name);
+restart:
+ if (auth_send(buf) || auth_recv(resp, sizeof(resp))) {
+ sudo_warnx("%s", U_("lost connection to authentication server"));
+ debug_return_int(AUTH_ERROR);
+ }
+
+ /* Get the password/response from the user. */
+ if (strncmp(resp, "challenge ", 10) == 0) {
+ (void) snprintf(buf, sizeof(buf), "%s\nResponse: ", &resp[10]);
+ pass = auth_getpass(buf, SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ if (pass && *pass == '\0') {
+ free(pass);
+ pass = auth_getpass("Response [echo on]: ",
+ SUDO_CONV_PROMPT_ECHO_ON, callback);
+ }
+ } else if (strncmp(resp, "chalnecho ", 10) == 0) {
+ pass = auth_getpass(&resp[10], SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ } else if (strncmp(resp, "password", 8) == 0) {
+ pass = auth_getpass(prompt, SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ } else if (strncmp(resp, "display ", 8) == 0) {
+ sudo_printf(SUDO_CONV_INFO_MSG|SUDO_CONV_PREFER_TTY, "%s\n", &resp[8]);
+ strlcpy(buf, "response noop", sizeof(buf));
+ goto restart;
+ } else {
+ sudo_warnx("%s", resp);
+ debug_return_int(AUTH_ERROR);
+ }
+ if (pass == NULL) { /* ^C or error */
+ debug_return_int(AUTH_INTR);
+ }
+
+ /* Send the user's response to the server */
+ (void) snprintf(buf, sizeof(buf), "response '%s'", pass);
+ if (auth_send(buf) || auth_recv(resp, sizeof(resp))) {
+ sudo_warnx("%s", U_("lost connection to authentication server"));
+ error = AUTH_ERROR;
+ goto done;
+ }
+
+ if (strncmp(resp, "ok", 2) == 0) {
+ error = AUTH_SUCCESS;
+ goto done;
+ }
+
+ /* Main loop prints "Permission Denied" or insult. */
+ if (strcmp(resp, "Permission Denied.") != 0)
+ sudo_warnx("%s", resp);
+ error = AUTH_FAILURE;
+done:
+ explicit_bzero(buf, sizeof(buf));
+ freezero(pass, strlen(pass));
+ debug_return_int(error);
+}
+
+int
+sudo_fwtk_cleanup(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth, bool force)
+{
+ debug_decl(sudo_fwtk_cleanup, SUDOERS_DEBUG_AUTH);
+
+ auth_close();
+ debug_return_int(AUTH_SUCCESS);
+}
+
+#endif /* HAVE_FWTK */
diff --git a/plugins/sudoers/auth/kerb5.c b/plugins/sudoers/auth/kerb5.c
new file mode 100644
index 0000000..f7bab93
--- /dev/null
+++ b/plugins/sudoers/auth/kerb5.c
@@ -0,0 +1,345 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999-2005, 2007-2008, 2010-2015
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_KERB5
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <krb5.h>
+#ifdef HAVE_HEIMDAL
+#include <com_err.h>
+#endif
+
+#include <sudoers.h>
+#include "sudo_auth.h"
+
+#ifdef HAVE_HEIMDAL
+# define extract_name(c, p) krb5_principal_get_comp_string(c, p, 1)
+# define krb5_free_data_contents(c, d) krb5_data_free(d)
+#else
+# define extract_name(c, p) (krb5_princ_component(c, p, 1)->data)
+#endif
+
+#ifndef HAVE_KRB5_VERIFY_USER
+static int verify_krb_v5_tgt(const struct sudoers_context *, krb5_context,
+ krb5_creds *, const char *);
+#endif
+static struct _sudo_krb5_data {
+ krb5_context sudo_context;
+ krb5_principal princ;
+ krb5_ccache ccache;
+} sudo_krb5_data = { NULL, NULL, NULL };
+typedef struct _sudo_krb5_data *sudo_krb5_datap;
+
+#ifdef SUDO_KRB5_INSTANCE
+static const char *sudo_krb5_instance = SUDO_KRB5_INSTANCE;
+#else
+static const char *sudo_krb5_instance = NULL;
+#endif
+
+#ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
+static krb5_error_code
+krb5_get_init_creds_opt_alloc(krb5_context context,
+ krb5_get_init_creds_opt **opts)
+{
+ *opts = malloc(sizeof(krb5_get_init_creds_opt));
+ if (*opts == NULL)
+ return KRB5_CC_NOMEM;
+ krb5_get_init_creds_opt_init(*opts);
+ return 0;
+}
+
+static void
+krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opts)
+{
+ free(opts);
+}
+#endif
+
+int
+sudo_krb5_setup(const struct sudoers_context *ctx, struct passwd *pw,
+ char **promptp, sudo_auth *auth)
+{
+ static char *krb5_prompt;
+ debug_decl(sudo_krb5_init, SUDOERS_DEBUG_AUTH);
+
+ /* Don't override the prompt if the user specified their own. */
+ if (strcmp(*promptp, PASSPROMPT) != 0) {
+ debug_return_int(AUTH_SUCCESS);
+ }
+
+ if (krb5_prompt == NULL) {
+ krb5_context sudo_context;
+ krb5_principal princ;
+ char *pname;
+ krb5_error_code error;
+
+ sudo_context = ((sudo_krb5_datap) auth->data)->sudo_context;
+ princ = ((sudo_krb5_datap) auth->data)->princ;
+
+ /*
+ * Really, we need to tell the caller not to prompt for password. The
+ * API does not currently provide this unless the auth is standalone.
+ */
+ if ((error = krb5_unparse_name(sudo_context, princ, &pname))) {
+ log_warningx(ctx, 0,
+ N_("%s: unable to convert principal to string ('%s'): %s"),
+ auth->name, pw->pw_name, error_message(error));
+ debug_return_int(AUTH_FAILURE);
+ }
+
+ if (asprintf(&krb5_prompt, "Password for %s: ", pname) == -1) {
+ log_warningx(ctx, 0, N_("unable to allocate memory"));
+ free(pname);
+ debug_return_int(AUTH_ERROR);
+ }
+ free(pname);
+ }
+ *promptp = krb5_prompt;
+
+ debug_return_int(AUTH_SUCCESS);
+}
+
+int
+sudo_krb5_init(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth)
+{
+ krb5_context sudo_context;
+ krb5_error_code error;
+ char cache_name[64], *pname = pw->pw_name;
+ debug_decl(sudo_krb5_init, SUDOERS_DEBUG_AUTH);
+
+ /* Only initialize once. */
+ if (auth->data != NULL)
+ debug_return_int(AUTH_SUCCESS);
+
+ if (sudo_krb5_instance != NULL) {
+ int len = asprintf(&pname, "%s%s%s", pw->pw_name,
+ sudo_krb5_instance[0] != '/' ? "/" : "", sudo_krb5_instance);
+ if (len == -1) {
+ log_warningx(ctx, 0, N_("unable to allocate memory"));
+ debug_return_int(AUTH_ERROR);
+ }
+ }
+
+#ifdef HAVE_KRB5_INIT_SECURE_CONTEXT
+ error = krb5_init_secure_context(&(sudo_krb5_data.sudo_context));
+#else
+ error = krb5_init_context(&(sudo_krb5_data.sudo_context));
+#endif
+ if (error)
+ goto done;
+ sudo_context = sudo_krb5_data.sudo_context;
+
+ error = krb5_parse_name(sudo_context, pname, &(sudo_krb5_data.princ));
+ if (error) {
+ log_warningx(ctx, 0, N_("%s: unable to parse '%s': %s"), auth->name,
+ pname, error_message(error));
+ goto done;
+ }
+
+ (void) snprintf(cache_name, sizeof(cache_name), "MEMORY:sudocc_%ld",
+ (long) getpid());
+ if ((error = krb5_cc_resolve(sudo_context, cache_name,
+ &(sudo_krb5_data.ccache)))) {
+ log_warningx(ctx, 0, N_("%s: unable to resolve credential cache: %s"),
+ auth->name, error_message(error));
+ goto done;
+ }
+
+ auth->data = (void *) &sudo_krb5_data; /* Stash all our data here */
+
+done:
+ if (sudo_krb5_instance != NULL)
+ free(pname);
+ debug_return_int(error ? AUTH_FAILURE : AUTH_SUCCESS);
+}
+
+#ifdef HAVE_KRB5_VERIFY_USER
+int
+sudo_krb5_verify(const struct sudoers_context *ctx, struct passwd *pw,
+ const char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
+{
+ krb5_context sudo_context;
+ krb5_principal princ;
+ krb5_ccache ccache;
+ krb5_error_code error;
+ debug_decl(sudo_krb5_verify, SUDOERS_DEBUG_AUTH);
+
+ sudo_context = ((sudo_krb5_datap) auth->data)->sudo_context;
+ princ = ((sudo_krb5_datap) auth->data)->princ;
+ ccache = ((sudo_krb5_datap) auth->data)->ccache;
+
+ error = krb5_verify_user(sudo_context, princ, ccache, pass, 1, NULL);
+ debug_return_int(error ? AUTH_FAILURE : AUTH_SUCCESS);
+}
+#else
+int
+sudo_krb5_verify(const struct sudoers_context *ctx, struct passwd *pw,
+ const char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
+{
+ krb5_context sudo_context;
+ krb5_principal princ;
+ krb5_creds credbuf, *creds = NULL;
+ krb5_ccache ccache;
+ krb5_error_code error;
+ krb5_get_init_creds_opt *opts = NULL;
+ debug_decl(sudo_krb5_verify, SUDOERS_DEBUG_AUTH);
+
+ sudo_context = ((sudo_krb5_datap) auth->data)->sudo_context;
+ princ = ((sudo_krb5_datap) auth->data)->princ;
+ ccache = ((sudo_krb5_datap) auth->data)->ccache;
+
+ /* Set default flags based on the local config file. */
+ error = krb5_get_init_creds_opt_alloc(sudo_context, &opts);
+ if (error) {
+ log_warningx(ctx, 0, N_("%s: unable to allocate options: %s"),
+ auth->name, error_message(error));
+ goto done;
+ }
+#ifdef HAVE_HEIMDAL
+ krb5_get_init_creds_opt_set_default_flags(sudo_context, NULL,
+ krb5_principal_get_realm(sudo_context, princ), opts);
+#endif
+
+ /* Note that we always obtain a new TGT to verify the user */
+ if ((error = krb5_get_init_creds_password(sudo_context, &credbuf, princ,
+ pass, krb5_prompter_posix,
+ NULL, 0, NULL, opts))) {
+ /* Don't print error if just a bad password */
+ if (error != KRB5KRB_AP_ERR_BAD_INTEGRITY) {
+ log_warningx(ctx, 0, N_("%s: unable to get credentials: %s"),
+ auth->name, error_message(error));
+ }
+ goto done;
+ }
+ creds = &credbuf;
+
+ /* Verify the TGT to prevent spoof attacks. */
+ if ((error = verify_krb_v5_tgt(ctx, sudo_context, creds, auth->name)))
+ goto done;
+
+ /* Store credential in cache. */
+ if ((error = krb5_cc_initialize(sudo_context, ccache, princ))) {
+ log_warningx(ctx, 0, N_("%s: unable to initialize credential cache: %s"),
+ auth->name, error_message(error));
+ } else if ((error = krb5_cc_store_cred(sudo_context, ccache, creds))) {
+ log_warningx(ctx, 0, N_("%s: unable to store credential in cache: %s"),
+ auth->name, error_message(error));
+ }
+
+done:
+ if (opts) {
+#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_TWO_ARGS
+ krb5_get_init_creds_opt_free(sudo_context, opts);
+#else
+ krb5_get_init_creds_opt_free(opts);
+#endif
+ }
+ if (creds)
+ krb5_free_cred_contents(sudo_context, creds);
+ debug_return_int(error ? AUTH_FAILURE : AUTH_SUCCESS);
+}
+#endif
+
+int
+sudo_krb5_cleanup(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth, bool force)
+{
+ krb5_context sudo_context;
+ krb5_principal princ;
+ krb5_ccache ccache;
+ debug_decl(sudo_krb5_cleanup, SUDOERS_DEBUG_AUTH);
+
+ sudo_context = ((sudo_krb5_datap) auth->data)->sudo_context;
+ princ = ((sudo_krb5_datap) auth->data)->princ;
+ ccache = ((sudo_krb5_datap) auth->data)->ccache;
+
+ if (sudo_context) {
+ if (ccache)
+ krb5_cc_destroy(sudo_context, ccache);
+ if (princ)
+ krb5_free_principal(sudo_context, princ);
+ krb5_free_context(sudo_context);
+ }
+
+ debug_return_int(AUTH_SUCCESS);
+}
+
+#ifndef HAVE_KRB5_VERIFY_USER
+/*
+ * Verify the Kerberos ticket-granting ticket just retrieved for the
+ * user. If the Kerberos server doesn't respond, assume the user is
+ * trying to fake us out (since we DID just get a TGT from what is
+ * supposedly our KDC).
+ *
+ * Returns 0 for successful authentication, non-zero for failure.
+ */
+static int
+verify_krb_v5_tgt(const struct sudoers_context *ctx, krb5_context sudo_context,
+ krb5_creds *cred, const char *auth_name)
+{
+ krb5_error_code error;
+ krb5_principal server;
+ krb5_verify_init_creds_opt vopt;
+ debug_decl(verify_krb_v5_tgt, SUDOERS_DEBUG_AUTH);
+
+ /*
+ * Get the server principal for the local host.
+ * (Use defaults of "host" and canonicalized local name.)
+ */
+ if ((error = krb5_sname_to_principal(sudo_context, NULL, NULL,
+ KRB5_NT_SRV_HST, &server))) {
+ log_warningx(ctx, 0, N_("%s: unable to get host principal: %s"),
+ auth_name, error_message(error));
+ debug_return_int(-1);
+ }
+
+ /* Initialize verify opts and set secure mode */
+ krb5_verify_init_creds_opt_init(&vopt);
+ krb5_verify_init_creds_opt_set_ap_req_nofail(&vopt, 1);
+
+ /* verify the Kerberos ticket-granting ticket we just retrieved */
+ error = krb5_verify_init_creds(sudo_context, cred, server, NULL,
+ NULL, &vopt);
+ krb5_free_principal(sudo_context, server);
+ if (error) {
+ log_warningx(ctx, 0, N_("%s: Cannot verify TGT! Possible attack!: %s"),
+ auth_name, error_message(error));
+ }
+ debug_return_int(error);
+}
+#endif
+
+#endif /* HAVE_KERB5 */
diff --git a/plugins/sudoers/auth/pam.c b/plugins/sudoers/auth/pam.c
new file mode 100644
index 0000000..e8d1785
--- /dev/null
+++ b/plugins/sudoers/auth/pam.c
@@ -0,0 +1,776 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999-2005, 2007-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_PAM
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <errno.h>
+
+#ifdef HAVE_PAM_PAM_APPL_H
+# include <pam/pam_appl.h>
+#else
+# include <security/pam_appl.h>
+#endif
+
+#ifdef __hpux
+# include <nl_types.h>
+#endif
+
+#ifdef HAVE_LIBINTL_H
+# if defined(__LINUX_PAM__)
+# define PAM_TEXT_DOMAIN "Linux-PAM"
+# elif defined(__sun__)
+# define PAM_TEXT_DOMAIN "SUNW_OST_SYSOSPAM"
+# endif
+#endif
+
+/* We don't want to translate the strings in the calls to dgt(). */
+#ifdef PAM_TEXT_DOMAIN
+# define dgt(d, t) dgettext(d, t)
+#endif
+
+#include <sudoers.h>
+#include "sudo_auth.h"
+
+/* Only OpenPAM and Linux PAM use const qualifiers. */
+#ifdef PAM_SUN_CODEBASE
+# define PAM_CONST
+#else
+# define PAM_CONST const
+#endif
+
+/* Ambiguity in spec: is it an array of pointers or a pointer to an array? */
+#ifdef PAM_SUN_CODEBASE
+# define PAM_MSG_GET(msg, n) (*(msg) + (n))
+#else
+# define PAM_MSG_GET(msg, n) ((msg)[(n)])
+#endif
+
+#ifndef PAM_DATA_SILENT
+#define PAM_DATA_SILENT 0
+#endif
+
+struct sudo_pam_closure {
+ const struct sudoers_context *ctx;
+ struct sudo_conv_callback *callback;
+};
+
+struct conv_filter {
+ char *msg;
+ size_t msglen;
+};
+
+static int converse(int, PAM_CONST struct pam_message **,
+ struct pam_response **, void *);
+static struct sudo_pam_closure pam_closure;
+static struct pam_conv pam_conv = { converse, &pam_closure };
+static const char *def_prompt = PASSPROMPT;
+static bool getpass_error;
+static bool noninteractive;
+static pam_handle_t *pamh;
+static struct conv_filter *conv_filter;
+
+static void
+conv_filter_init(const struct sudoers_context *ctx)
+{
+ debug_decl(conv_filter_init, SUDOERS_DEBUG_AUTH);
+
+#ifdef __hpux
+ /*
+ * HP-UX displays last login information as part of either account
+ * management (in trusted mode) or session management (regular mode).
+ * Filter those out in the conversation function unless running a shell.
+ */
+ if (!ISSET(ctx->mode, MODE_SHELL|MODE_LOGIN_SHELL)) {
+ int i, nfilt = 0, maxfilters = 0;
+ struct conv_filter *newfilt;
+ nl_catd catd;
+ char *msg;
+
+ /*
+ * Messages from PAM account management when trusted mode is enabled:
+ * 1 Last successful login for %s: %s
+ * 2 Last successful login for %s: %s on %s
+ * 3 Last unsuccessful login for %s: %s
+ * 4 Last unsuccessful login for %s: %s on %s
+ */
+ if ((catd = catopen("pam_comsec", NL_CAT_LOCALE)) != -1) {
+ maxfilters += 4;
+ newfilt = reallocarray(conv_filter, maxfilters + 1,
+ sizeof(*conv_filter));
+ if (newfilt != NULL) {
+ conv_filter = newfilt;
+ for (i = 1; i < 5; i++) {
+ if ((msg = catgets(catd, 1, i, NULL)) == NULL)
+ break;
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "adding \"%s\" to conversation filter", msg);
+ if ((conv_filter[nfilt].msg = strdup(msg)) == NULL)
+ break;
+ conv_filter[nfilt].msglen = strcspn(msg, "%");
+ nfilt++;
+ }
+ }
+ }
+ /*
+ * Messages from PAM session management when trusted mode is disabled:
+ * 3 Last successful login: %s %s %s %s
+ * 4 Last authentication failure: %s %s %s %s
+ */
+ if ((catd = catopen("pam_hpsec", NL_CAT_LOCALE)) != -1) {
+ maxfilters += 2;
+ newfilt = reallocarray(conv_filter, maxfilters + 1,
+ sizeof(*conv_filter));
+ if (newfilt != NULL) {
+ conv_filter = newfilt;
+ for (i = 3; i < 5; i++) {
+ if ((msg = catgets(catd, 1, i, NULL)) == NULL)
+ break;
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "adding \"%s\" to conversation filter", msg);
+ if ((conv_filter[nfilt].msg = strdup(msg)) == NULL)
+ break;
+ conv_filter[nfilt].msglen = strcspn(msg, "%");
+ nfilt++;
+ }
+ }
+ }
+ if (conv_filter != NULL) {
+ conv_filter[nfilt].msg = NULL;
+ conv_filter[nfilt].msglen = 0;
+ }
+ }
+#endif /* __hpux */
+ debug_return;
+}
+
+/*
+ * Like pam_strerror() but never returns NULL and uses strerror(errno)
+ * for PAM_SYSTEM_ERR.
+ */
+static const char *
+sudo_pam_strerror(pam_handle_t *handle, int errnum)
+{
+ const char *errstr;
+ static char errbuf[32];
+
+ if (errnum == PAM_SYSTEM_ERR)
+ return strerror(errno);
+ if ((errstr = pam_strerror(handle, errnum)) == NULL)
+ (void)snprintf(errbuf, sizeof(errbuf), "PAM error %d", errnum);
+ return errstr;
+}
+
+static int
+sudo_pam_init2(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth, bool quiet)
+{
+ static int pam_status = PAM_SUCCESS;
+ const char *ttypath = ctx->user.ttypath;
+ const char *errstr, *pam_service;
+ int rc;
+ debug_decl(sudo_pam_init, SUDOERS_DEBUG_AUTH);
+
+ /* Stash pointer to last pam status. */
+ auth->data = &pam_status;
+
+ if (pamh != NULL) {
+ /* Already initialized (may happen with AIX or with sub-commands). */
+ debug_return_int(AUTH_SUCCESS);
+ }
+
+ /* Stash value of noninteractive flag for conversation function. */
+ noninteractive = IS_NONINTERACTIVE(auth);
+
+ /* Store context in closure so converse() has access to it. */
+ pam_closure.ctx = ctx;
+
+ /* Initialize PAM. */
+ if (ISSET(ctx->mode, MODE_ASKPASS) && def_pam_askpass_service != NULL) {
+ pam_service = def_pam_askpass_service;
+ } else {
+ pam_service = ISSET(ctx->mode, MODE_LOGIN_SHELL) ?
+ def_pam_login_service : def_pam_service;
+ }
+ pam_status = pam_start(pam_service, pw->pw_name, &pam_conv, &pamh);
+ if (pam_status != PAM_SUCCESS) {
+ errstr = sudo_pam_strerror(NULL, pam_status);
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "pam_start(%s, %s, %p, %p): %s", pam_service, pw->pw_name,
+ &pam_conv, &pamh, errstr);
+ if (!quiet)
+ log_warningx(ctx, 0, N_("unable to initialize PAM: %s"), errstr);
+ debug_return_int(AUTH_ERROR);
+ }
+
+ /* Initialize conversation function message filter. */
+ conv_filter_init(ctx);
+
+ /*
+ * Set PAM_RUSER to the invoking user (the "from" user).
+ * Solaris 7 and below require PAM_RHOST to be set if PAM_RUSER is.
+ * Note: PAM_RHOST may cause a DNS lookup on Linux in libaudit.
+ */
+ if (def_pam_ruser) {
+ rc = pam_set_item(pamh, PAM_RUSER, ctx->user.name);
+ if (rc != PAM_SUCCESS) {
+ errstr = sudo_pam_strerror(pamh, rc);
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "pam_set_item(pamh, PAM_RUSER, %s): %s", ctx->user.name, errstr);
+ }
+ }
+ if (def_pam_rhost) {
+ rc = pam_set_item(pamh, PAM_RHOST, ctx->user.host);
+ if (rc != PAM_SUCCESS) {
+ errstr = sudo_pam_strerror(pamh, rc);
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "pam_set_item(pamh, PAM_RHOST, %s): %s", ctx->user.host, errstr);
+ }
+ }
+ if (ttypath != NULL) {
+ rc = pam_set_item(pamh, PAM_TTY, ttypath);
+ if (rc != PAM_SUCCESS) {
+ errstr = sudo_pam_strerror(pamh, rc);
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "pam_set_item(pamh, PAM_TTY, %s): %s", ttypath, errstr);
+ }
+ }
+
+ /*
+ * If PAM session and setcred support is disabled we don't
+ * need to keep a sudo process around to close the session.
+ */
+ if (!def_pam_session && !def_pam_setcred)
+ auth->end_session = NULL;
+
+ debug_return_int(AUTH_SUCCESS);
+}
+
+int
+sudo_pam_init(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth)
+{
+ return sudo_pam_init2(ctx, pw, auth, false);
+}
+
+#ifdef _AIX
+int
+sudo_pam_init_quiet(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth)
+{
+ return sudo_pam_init2(ctx, pw, auth, true);
+}
+#endif /* _AIX */
+
+int
+sudo_pam_verify(const struct sudoers_context *ctx, struct passwd *pw,
+ const char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback)
+{
+ const char *envccname;
+ const char *s;
+ int *pam_status = (int *)auth->data;
+ debug_decl(sudo_pam_verify, SUDOERS_DEBUG_AUTH);
+
+ def_prompt = prompt; /* for converse */
+ getpass_error = false; /* set by converse if user presses ^C */
+ pam_closure.callback = callback; /* passed to conversation function */
+
+ /* Set KRB5CCNAME from the user environment if not set to propagate this
+ * information to PAM modules that may use it to authentication. */
+ envccname = sudo_getenv("KRB5CCNAME");
+ if (envccname == NULL && ctx->user.ccname != NULL) {
+ if (sudo_setenv("KRB5CCNAME", ctx->user.ccname, true) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "unable to set KRB5CCNAME");
+ debug_return_int(AUTH_FAILURE);
+ }
+ }
+
+ /* PAM_SILENT prevents the authentication service from generating output. */
+ *pam_status = pam_authenticate(pamh, PAM_SILENT);
+
+ /* Restore def_prompt, the passed-in prompt may be freed later. */
+ def_prompt = PASSPROMPT;
+
+ /* Restore KRB5CCNAME to its original value. */
+ if (envccname == NULL && sudo_unsetenv("KRB5CCNAME") != 0) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "unable to restore KRB5CCNAME");
+ debug_return_int(AUTH_FAILURE);
+ }
+
+ if (getpass_error) {
+ /* error or ^C from tgetpass() or running non-interactive */
+ debug_return_int(noninteractive ? AUTH_NONINTERACTIVE : AUTH_INTR);
+ }
+ switch (*pam_status) {
+ case PAM_SUCCESS:
+ debug_return_int(AUTH_SUCCESS);
+ case PAM_AUTH_ERR:
+ case PAM_AUTHINFO_UNAVAIL:
+ case PAM_MAXTRIES:
+ case PAM_PERM_DENIED:
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "pam_authenticate: %d", *pam_status);
+ debug_return_int(AUTH_FAILURE);
+ default:
+ s = sudo_pam_strerror(pamh, *pam_status);
+ log_warningx(ctx, 0, N_("PAM authentication error: %s"), s);
+ debug_return_int(AUTH_ERROR);
+ }
+}
+
+int
+sudo_pam_approval(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth, bool exempt)
+{
+ const char *s;
+ int rc, status = AUTH_SUCCESS;
+ int *pam_status = (int *) auth->data;
+ debug_decl(sudo_pam_approval, SUDOERS_DEBUG_AUTH);
+
+ if (def_pam_acct_mgmt) {
+ rc = pam_acct_mgmt(pamh, PAM_SILENT);
+ switch (rc) {
+ case PAM_SUCCESS:
+ break;
+ case PAM_AUTH_ERR:
+ log_warningx(ctx, 0, N_("account validation failure, "
+ "is your account locked?"));
+ status = AUTH_ERROR;
+ break;
+ case PAM_NEW_AUTHTOK_REQD:
+ /* Ignore if user is exempt from password restrictions. */
+ if (exempt) {
+ rc = *pam_status;
+ break;
+ }
+ /* New password required, try to change it. */
+ log_warningx(ctx, 0, N_("Account or password is "
+ "expired, reset your password and try again"));
+ rc = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
+ if (rc == PAM_SUCCESS)
+ break;
+ s = pam_strerror(pamh, rc);
+ log_warningx(ctx, 0,
+ N_("unable to change expired password: %s"), s);
+ status = AUTH_FAILURE;
+ break;
+ case PAM_AUTHTOK_EXPIRED:
+ /* Ignore if user is exempt from password restrictions. */
+ if (exempt) {
+ rc = *pam_status;
+ break;
+ }
+ /* Password expired, cannot be updated by user. */
+ log_warningx(ctx, 0,
+ N_("Password expired, contact your system administrator"));
+ status = AUTH_ERROR;
+ break;
+ case PAM_ACCT_EXPIRED:
+ log_warningx(ctx, 0,
+ N_("Account expired or PAM config lacks an \"account\" "
+ "section for sudo, contact your system administrator"));
+ status = AUTH_ERROR;
+ break;
+ case PAM_AUTHINFO_UNAVAIL:
+ case PAM_MAXTRIES:
+ case PAM_PERM_DENIED:
+ s = sudo_pam_strerror(pamh, rc);
+ log_warningx(ctx, 0, N_("PAM account management error: %s"), s);
+ status = AUTH_FAILURE;
+ break;
+ default:
+ s = sudo_pam_strerror(pamh, rc);
+ log_warningx(ctx, 0, N_("PAM account management error: %s"), s);
+ status = AUTH_ERROR;
+ break;
+ }
+ *pam_status = rc;
+ }
+ debug_return_int(status);
+}
+
+int
+sudo_pam_cleanup(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth, bool force)
+{
+ int *pam_status = (int *) auth->data;
+ debug_decl(sudo_pam_cleanup, SUDOERS_DEBUG_AUTH);
+
+ /* If successful, we can't close the session until sudo_pam_end_session() */
+ if (force || *pam_status != PAM_SUCCESS || auth->end_session == NULL) {
+ *pam_status = pam_end(pamh, *pam_status | PAM_DATA_SILENT);
+ pamh = NULL;
+ }
+ debug_return_int(*pam_status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);
+}
+
+int
+sudo_pam_begin_session(const struct sudoers_context *ctx, struct passwd *pw,
+ char **user_envp[], sudo_auth *auth)
+{
+ int rc, status = AUTH_SUCCESS;
+ int *pam_status = (int *) auth->data;
+ const char *errstr;
+ debug_decl(sudo_pam_begin_session, SUDOERS_DEBUG_AUTH);
+
+ /*
+ * If there is no valid user we cannot open a PAM session.
+ * This is not an error as sudo can run commands with arbitrary
+ * uids, it just means we are done from a session management standpoint.
+ */
+ if (pw == NULL) {
+ if (pamh != NULL) {
+ rc = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
+ if (rc != PAM_SUCCESS) {
+ errstr = sudo_pam_strerror(pamh, rc);
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "pam_end: %s", errstr);
+ }
+ pamh = NULL;
+ }
+ goto done;
+ }
+
+ /*
+ * Update PAM_USER to reference the user we are running the command
+ * as, as opposed to the user we authenticated as.
+ */
+ rc = pam_set_item(pamh, PAM_USER, pw->pw_name);
+ if (rc != PAM_SUCCESS) {
+ errstr = sudo_pam_strerror(pamh, rc);
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "pam_set_item(pamh, PAM_USER, %s): %s", pw->pw_name, errstr);
+ }
+
+ /*
+ * Reinitialize credentials when changing the user.
+ * We don't worry about a failure from pam_setcred() since with
+ * stacked PAM auth modules a failure from one module may override
+ * PAM_SUCCESS from another. For example, given a non-local user,
+ * pam_unix will fail but pam_ldap or pam_sss may succeed, but if
+ * pam_unix is first in the stack, pam_setcred() will fail.
+ */
+ if (def_pam_setcred) {
+ rc = pam_setcred(pamh, PAM_REINITIALIZE_CRED);
+ if (rc != PAM_SUCCESS) {
+ errstr = sudo_pam_strerror(pamh, rc);
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "pam_setcred: %s", errstr);
+ def_pam_setcred = false;
+ }
+ }
+
+ if (def_pam_session) {
+ /*
+ * We use PAM_SILENT to prevent pam_lastlog from printing last login
+ * information except when explicitly running a shell.
+ */
+ const bool silent = !ISSET(ctx->mode, MODE_SHELL|MODE_LOGIN_SHELL);
+ rc = pam_open_session(pamh, silent ? PAM_SILENT : 0);
+ switch (rc) {
+ case PAM_SUCCESS:
+ break;
+ case PAM_SESSION_ERR:
+ /* Treat PAM_SESSION_ERR as a non-fatal error. */
+ errstr = sudo_pam_strerror(pamh, rc);
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "pam_open_session: %s", errstr);
+ /* Avoid closing session that was not opened. */
+ def_pam_session = false;
+ break;
+ default:
+ /* Unexpected session failure, treat as fatal error. */
+ *pam_status = rc;
+ errstr = sudo_pam_strerror(pamh, rc);
+ log_warningx(ctx, 0, N_("%s: %s"), "pam_open_session", errstr);
+ rc = pam_end(pamh, *pam_status | PAM_DATA_SILENT);
+ if (rc != PAM_SUCCESS) {
+ errstr = sudo_pam_strerror(pamh, rc);
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "pam_end: %s", errstr);
+ }
+ pamh = NULL;
+ status = AUTH_ERROR;
+ goto done;
+ }
+ }
+
+#ifdef HAVE_PAM_GETENVLIST
+ /*
+ * Update environment based on what is stored in pamh.
+ * If no authentication is done we will only have environment
+ * variables if pam_env is called via session.
+ */
+ if (user_envp != NULL) {
+ char **pam_envp = pam_getenvlist(pamh);
+ if (pam_envp != NULL) {
+ /* Merge pam env with user env. */
+ if (!env_init(*user_envp) || !env_merge(ctx, pam_envp))
+ status = AUTH_ERROR;
+ *user_envp = env_get();
+ free(pam_envp);
+ /* XXX - we leak any duplicates that were in pam_envp */
+ }
+ }
+#endif /* HAVE_PAM_GETENVLIST */
+
+done:
+ debug_return_int(status);
+}
+
+int
+sudo_pam_end_session(sudo_auth *auth)
+{
+ int rc, status = AUTH_SUCCESS;
+ const char *errstr;
+ debug_decl(sudo_pam_end_session, SUDOERS_DEBUG_AUTH);
+
+ if (pamh != NULL) {
+ if (def_pam_session) {
+ rc = pam_close_session(pamh, PAM_SILENT);
+ if (rc != PAM_SUCCESS) {
+ errstr = sudo_pam_strerror(pamh, rc);
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "pam_close_session: %s", errstr);
+ }
+ }
+ if (def_pam_setcred) {
+ rc = pam_setcred(pamh, PAM_DELETE_CRED | PAM_SILENT);
+ if (rc != PAM_SUCCESS) {
+ errstr = sudo_pam_strerror(pamh, rc);
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "pam_setcred: %s", errstr);
+ }
+ }
+ rc = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
+ if (rc != PAM_SUCCESS) {
+ errstr = sudo_pam_strerror(pamh, rc);
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "pam_end: %s", errstr);
+ status = AUTH_ERROR;
+ }
+ pamh = NULL;
+ }
+
+ debug_return_int(status);
+}
+
+#define PROMPT_IS_PASSWORD(_p) \
+ (strncmp((_p), "Password:", 9) == 0 && \
+ ((_p)[9] == '\0' || ((_p)[9] == ' ' && (_p)[10] == '\0')))
+
+#ifdef PAM_TEXT_DOMAIN
+# define PAM_PROMPT_IS_PASSWORD(_p) \
+ (strcmp((_p), dgt(PAM_TEXT_DOMAIN, "Password:")) == 0 || \
+ strcmp((_p), dgt(PAM_TEXT_DOMAIN, "Password: ")) == 0 || \
+ PROMPT_IS_PASSWORD(_p))
+#else
+# define PAM_PROMPT_IS_PASSWORD(_p) PROMPT_IS_PASSWORD(_p)
+#endif /* PAM_TEXT_DOMAIN */
+
+/*
+ * We use the PAM prompt in preference to sudo's as long
+ * as passprompt_override is not set and:
+ * a) the (translated) sudo prompt matches /^Password: ?/
+ * or:
+ * b) the PAM prompt itself *doesn't* match /^Password: ?/
+ * or /^username's Password: ?/
+ *
+ * The intent is to use the PAM prompt for things like
+ * challenge-response, otherwise use sudo's prompt.
+ * There may also be cases where a localized translation
+ * of "Password: " exists for PAM but not for sudo.
+ */
+static bool
+use_pam_prompt(const char *pam_prompt)
+{
+ size_t user_len;
+ debug_decl(use_pam_prompt, SUDOERS_DEBUG_AUTH);
+
+ /* Always use sudo prompt if passprompt_override is set. */
+ if (def_passprompt_override)
+ debug_return_bool(false);
+
+ /* If sudo prompt matches "^Password: ?$", use PAM prompt. */
+ if (PROMPT_IS_PASSWORD(def_prompt))
+ debug_return_bool(true);
+
+ /* If PAM prompt matches "^Password: ?$", use sudo prompt. */
+ if (PAM_PROMPT_IS_PASSWORD(pam_prompt))
+ debug_return_bool(false);
+
+ /*
+ * Some PAM modules use "^username's Password: ?$" instead of
+ * "^Password: ?" so check for that too.
+ */
+ if (pam_closure.ctx != NULL) {
+ const char *user_name = pam_closure.ctx->user.name;
+ user_len = strlen(user_name);
+ if (strncmp(pam_prompt, user_name, user_len) == 0) {
+ const char *cp = pam_prompt + user_len;
+ if (strncmp(cp, "'s Password:", 12) == 0 &&
+ (cp[12] == '\0' || (cp[12] == ' ' && cp[13] == '\0')))
+ debug_return_bool(false);
+ }
+ }
+
+ /* Otherwise, use the PAM prompt. */
+ debug_return_bool(true);
+}
+
+static bool
+is_filtered(const char *msg)
+{
+ bool filtered = false;
+
+ if (conv_filter != NULL) {
+ struct conv_filter *filt = conv_filter;
+ while (filt->msg != NULL) {
+ if (strncmp(msg, filt->msg, filt->msglen) == 0) {
+ filtered = true;
+ break;
+ }
+ filt++;
+ }
+ }
+ return filtered;
+}
+
+/*
+ * ``Conversation function'' for PAM <-> human interaction.
+ */
+static int
+converse(int num_msg, PAM_CONST struct pam_message **msg,
+ struct pam_response **reply_out, void *appdata_ptr)
+{
+ struct sudo_conv_callback *callback = NULL;
+ struct sudo_pam_closure *closure = appdata_ptr;
+ struct pam_response *reply;
+ const char *prompt;
+ char *pass;
+ int n, type;
+ debug_decl(converse, SUDOERS_DEBUG_AUTH);
+
+ if (num_msg <= 0 || num_msg > PAM_MAX_NUM_MSG) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "invalid number of PAM messages: %d", num_msg);
+ debug_return_int(PAM_CONV_ERR);
+ }
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "number of PAM messages: %d", num_msg);
+
+ reply = calloc((size_t)num_msg, sizeof(struct pam_response));
+ if (reply == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(PAM_BUF_ERR);
+ }
+
+ if (closure != NULL)
+ callback = closure->callback;
+
+ for (n = 0; n < num_msg; n++) {
+ PAM_CONST struct pam_message *pm = PAM_MSG_GET(msg, n);
+
+ type = SUDO_CONV_PROMPT_ECHO_OFF;
+ switch (pm->msg_style) {
+ case PAM_PROMPT_ECHO_ON:
+ type = SUDO_CONV_PROMPT_ECHO_ON;
+ FALLTHROUGH;
+ case PAM_PROMPT_ECHO_OFF:
+ /* Error out if the last password read was interrupted. */
+ if (getpass_error)
+ goto bad;
+
+ /* Treat non-interactive mode as a getpass error. */
+ if (noninteractive) {
+ getpass_error = true;
+ goto bad;
+ }
+
+ /* Choose either the sudo prompt or the PAM one. */
+ prompt = use_pam_prompt(pm->msg) ? pm->msg : def_prompt;
+
+ /* Read the password unless interrupted. */
+ pass = auth_getpass(prompt, type, callback);
+ if (pass == NULL) {
+ /* Error (or ^C) reading password, don't try again. */
+ getpass_error = true;
+ goto bad;
+ }
+ if (strlen(pass) >= PAM_MAX_RESP_SIZE) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "password longer than %d", PAM_MAX_RESP_SIZE);
+ freezero(pass, strlen(pass));
+ pass = NULL;
+ goto bad;
+ }
+ reply[n].resp = pass; /* auth_getpass() malloc's a copy */
+ break;
+ case PAM_TEXT_INFO:
+ if (pm->msg != NULL && !is_filtered(pm->msg))
+ sudo_printf(SUDO_CONV_INFO_MSG|SUDO_CONV_PREFER_TTY,
+ "%s\n", pm->msg);
+ break;
+ case PAM_ERROR_MSG:
+ if (pm->msg != NULL)
+ sudo_printf(SUDO_CONV_ERROR_MSG|SUDO_CONV_PREFER_TTY,
+ "%s\n", pm->msg);
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unsupported message style: %d", pm->msg_style);
+ goto bad;
+ }
+ }
+
+ *reply_out = reply;
+ debug_return_int(PAM_SUCCESS);
+
+bad:
+ /* Zero and free allocated memory and return an error. */
+ for (n = 0; n < num_msg; n++) {
+ struct pam_response *pr = &reply[n];
+
+ if (pr->resp != NULL) {
+ freezero(pr->resp, strlen(pr->resp));
+ pr->resp = NULL;
+ }
+ }
+ free(reply);
+ debug_return_int(PAM_CONV_ERR);
+}
+
+#endif /* HAVE_PAM */
diff --git a/plugins/sudoers/auth/passwd.c b/plugins/sudoers/auth/passwd.c
new file mode 100644
index 0000000..0b1fcde
--- /dev/null
+++ b/plugins/sudoers/auth/passwd.c
@@ -0,0 +1,141 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999-2005, 2010-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#include <sudoers.h>
+#include "sudo_auth.h"
+
+#define DESLEN 13
+#define HAS_AGEINFO(p, l) (l == 18 && p[DESLEN] == ',')
+
+int
+sudo_passwd_init(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth)
+{
+ debug_decl(sudo_passwd_init, SUDOERS_DEBUG_AUTH);
+
+ /* Only initialize once. */
+ if (auth->data != NULL)
+ debug_return_int(AUTH_SUCCESS);
+
+#ifdef HAVE_SKEYACCESS
+ if (skeyaccess(pw, ctx->user.tty, NULL, NULL) == 0)
+ debug_return_int(AUTH_FAILURE);
+#endif
+ sudo_setspent();
+ auth->data = sudo_getepw(pw);
+ sudo_endspent();
+ debug_return_int(auth->data ? AUTH_SUCCESS : AUTH_ERROR);
+}
+
+#ifdef HAVE_CRYPT
+int
+sudo_passwd_verify(const struct sudoers_context *ctx, struct passwd *pw,
+ const char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
+{
+ char des_pass[9], *epass;
+ char *pw_epasswd = auth->data;
+ size_t pw_len;
+ int ret;
+ debug_decl(sudo_passwd_verify, SUDOERS_DEBUG_AUTH);
+
+ /* An empty plain-text password must match an empty encrypted password. */
+ if (pass[0] == '\0')
+ debug_return_int(pw_epasswd[0] ? AUTH_FAILURE : AUTH_SUCCESS);
+
+ /*
+ * Truncate to 8 chars if standard DES since not all crypt()'s do this.
+ */
+ pw_len = strlen(pw_epasswd);
+ if (pw_len == DESLEN || HAS_AGEINFO(pw_epasswd, pw_len)) {
+ (void)strlcpy(des_pass, pass, sizeof(des_pass));
+ pass = des_pass;
+ }
+
+ /*
+ * Normal UN*X password check.
+ * HP-UX may add aging info (separated by a ',') at the end so
+ * only compare the first DESLEN characters in that case.
+ */
+ epass = (char *) crypt(pass, pw_epasswd);
+ ret = AUTH_FAILURE;
+ if (epass != NULL) {
+ if (HAS_AGEINFO(pw_epasswd, pw_len) && strlen(epass) == DESLEN) {
+ if (strncmp(pw_epasswd, epass, DESLEN) == 0)
+ ret = AUTH_SUCCESS;
+ } else {
+ if (strcmp(pw_epasswd, epass) == 0)
+ ret = AUTH_SUCCESS;
+ }
+ }
+
+ explicit_bzero(des_pass, sizeof(des_pass));
+
+ debug_return_int(ret);
+}
+#else
+int
+sudo_passwd_verify(const struct sudoers_context *ctx, struct passwd *pw,
+ const char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
+{
+ char *pw_passwd = auth->data;
+ int ret;
+ debug_decl(sudo_passwd_verify, SUDOERS_DEBUG_AUTH);
+
+ /* Simple string compare for systems without crypt(). */
+ if (strcmp(pass, pw_passwd) == 0)
+ ret = AUTH_SUCCESS;
+ else
+ ret = AUTH_FAILURE;
+
+ debug_return_int(ret);
+}
+#endif
+
+int
+sudo_passwd_cleanup(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth, bool force)
+{
+ debug_decl(sudo_passwd_cleanup, SUDOERS_DEBUG_AUTH);
+
+ if (auth->data != NULL) {
+ /* Zero out encrypted password before freeing. */
+ size_t len = strlen((char *)auth->data);
+ freezero(auth->data, len);
+ auth->data = NULL;
+ }
+
+ debug_return_int(AUTH_SUCCESS);
+}
diff --git a/plugins/sudoers/auth/rfc1938.c b/plugins/sudoers/auth/rfc1938.c
new file mode 100644
index 0000000..bde9e33
--- /dev/null
+++ b/plugins/sudoers/auth/rfc1938.c
@@ -0,0 +1,141 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1994-1996, 1998-2005, 2010-2012, 2014-2015
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#if defined(HAVE_SKEY) || defined(HAVE_OPIE)
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#if defined(HAVE_SKEY)
+# include <skey.h>
+# define RFC1938 skey
+# ifdef HAVE_RFC1938_SKEYCHALLENGE
+# define rfc1938challenge(a,b,c,d) skeychallenge((a),(b),(c),(d))
+# else
+# define rfc1938challenge(a,b,c,d) skeychallenge((a),(b),(c))
+# endif
+# define rfc1938verify(a,b) skeyverify((a),(b))
+#elif defined(HAVE_OPIE)
+# include <opie.h>
+# define RFC1938 opie
+# define rfc1938challenge(a,b,c,d) opiechallenge((a),(b),(c))
+# define rfc1938verify(a,b) opieverify((a),(b))
+#endif
+
+#include <sudoers.h>
+#include "sudo_auth.h"
+
+int
+sudo_rfc1938_setup(const struct sudoers_context *ctx, struct passwd *pw,
+ char **promptp, sudo_auth *auth)
+{
+ char challenge[256];
+ size_t challenge_len;
+ static char *orig_prompt = NULL, *new_prompt = NULL;
+ static size_t op_len, np_size;
+ static struct RFC1938 rfc1938;
+ debug_decl(sudo_rfc1938_setup, SUDOERS_DEBUG_AUTH);
+
+ /* Stash a pointer to the rfc1938 struct if we have not initialized */
+ if (!auth->data)
+ auth->data = &rfc1938;
+
+ /* Save the original prompt */
+ if (orig_prompt == NULL) {
+ orig_prompt = *promptp;
+ op_len = strlen(orig_prompt);
+
+ /* Ignore trailing colon (we will add our own) */
+ if (orig_prompt[op_len - 1] == ':')
+ op_len--;
+ else if (op_len >= 2 && orig_prompt[op_len - 1] == ' '
+ && orig_prompt[op_len - 2] == ':')
+ op_len -= 2;
+ }
+
+#ifdef HAVE_SKEY
+ /* Close old stream */
+ if (rfc1938.keyfile)
+ (void) fclose(rfc1938.keyfile);
+#endif
+
+ /*
+ * Look up the user and get the rfc1938 challenge.
+ * If the user is not in the OTP db, only post a fatal error if
+ * we are running alone (since they may just use a normal passwd).
+ */
+ if (rfc1938challenge(&rfc1938, pw->pw_name, challenge, sizeof(challenge))) {
+ if (IS_ONEANDONLY(auth)) {
+ sudo_warnx(U_("you do not exist in the %s database"), auth->name);
+ debug_return_int(AUTH_ERROR);
+ } else {
+ debug_return_int(AUTH_FAILURE);
+ }
+ }
+
+ /* Get space for new prompt with embedded challenge */
+ challenge_len = strlen(challenge);
+ if (np_size < op_len + challenge_len + 7) {
+ char *p = realloc(new_prompt, op_len + challenge_len + 7);
+ if (p == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(AUTH_ERROR);
+ }
+ np_size = op_len + challenge_len + 7;
+ new_prompt = p;
+ }
+
+ if (def_long_otp_prompt)
+ (void) snprintf(new_prompt, np_size, "%s\n%s", challenge, orig_prompt);
+ else
+ (void) snprintf(new_prompt, np_size, "%.*s [ %s ]:", (int)op_len,
+ orig_prompt, challenge);
+
+ *promptp = new_prompt;
+ debug_return_int(AUTH_SUCCESS);
+}
+
+int
+sudo_rfc1938_verify(const struct sudoers_context *ctx, struct passwd *pw,
+ const char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
+{
+ debug_decl(sudo_rfc1938_verify, SUDOERS_DEBUG_AUTH);
+
+ if (rfc1938verify((struct RFC1938 *) auth->data, (char *)pass) == 0)
+ debug_return_int(AUTH_SUCCESS);
+ else
+ debug_return_int(AUTH_FAILURE);
+}
+
+#endif /* HAVE_SKEY || HAVE_OPIE */
diff --git a/plugins/sudoers/auth/secureware.c b/plugins/sudoers/auth/secureware.c
new file mode 100644
index 0000000..a193e55
--- /dev/null
+++ b/plugins/sudoers/auth/secureware.c
@@ -0,0 +1,116 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1998-2005, 2010-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_GETPRPWNAM
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+#ifdef __hpux
+# undef MAXINT
+# include <hpsecurity.h>
+#else
+# include <sys/security.h>
+#endif /* __hpux */
+#include <prot.h>
+
+#include <sudoers.h>
+#include "sudo_auth.h"
+
+#ifdef __alpha
+extern int crypt_type;
+#endif
+
+int
+sudo_secureware_init(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth)
+{
+ debug_decl(sudo_secureware_init, SUDOERS_DEBUG_AUTH);
+
+ /* Only initialize once. */
+ if (auth->data != NULL)
+ debug_return_int(AUTH_SUCCESS);
+
+#ifdef __alpha
+ if (crypt_type == INT_MAX)
+ debug_return_int(AUTH_FAILURE); /* no shadow */
+#endif
+
+ sudo_setspent();
+ auth->data = sudo_getepw(pw);
+ sudo_endspent();
+ debug_return_int(auth->data ? AUTH_SUCCESS : AUTH_ERROR);
+}
+
+int
+sudo_secureware_verify(const struct sudoers_context *ctx, struct passwd *pw,
+ const char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
+{
+ char *pw_epasswd = auth->data;
+ char *epass = NULL;
+ debug_decl(sudo_secureware_verify, SUDOERS_DEBUG_AUTH);
+
+ /* An empty plain-text password must match an empty encrypted password. */
+ if (pass[0] == '\0')
+ debug_return_int(pw_epasswd[0] ? AUTH_FAILURE : AUTH_SUCCESS);
+
+#if defined(__alpha)
+# ifdef HAVE_DISPCRYPT
+ epass = dispcrypt(pass, pw_epasswd, crypt_type);
+# else
+ if (crypt_type == AUTH_CRYPT_BIGCRYPT)
+ epass = bigcrypt(pass, pw_epasswd);
+ else if (crypt_type == AUTH_CRYPT_CRYPT16)
+ epass = crypt(pass, pw_epasswd);
+# endif /* HAVE_DISPCRYPT */
+#elif defined(HAVE_BIGCRYPT)
+ epass = bigcrypt(pass, pw_epasswd);
+#endif /* __alpha */
+
+ if (epass != NULL && strcmp(pw_epasswd, epass) == 0)
+ debug_return_int(AUTH_SUCCESS);
+ debug_return_int(AUTH_FAILURE);
+}
+
+int
+sudo_secureware_cleanup(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth, bool force)
+{
+ char *pw_epasswd = auth->data;
+ debug_decl(sudo_secureware_cleanup, SUDOERS_DEBUG_AUTH);
+
+ if (pw_epasswd != NULL)
+ freezero(pw_epasswd, strlen(pw_epasswd));
+ debug_return_int(AUTH_SUCCESS);
+}
+
+#endif /* HAVE_GETPRPWNAM */
diff --git a/plugins/sudoers/auth/securid5.c b/plugins/sudoers/auth/securid5.c
new file mode 100644
index 0000000..6d3c636
--- /dev/null
+++ b/plugins/sudoers/auth/securid5.c
@@ -0,0 +1,237 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999-2005, 2007, 2010-2012, 2014-2016
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ * Copyright (c) 2002 Michael Stroucken <michael@stroucken.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_SECURID
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+
+/* Needed for SecurID v5.0 Authentication on UNIX */
+#define UNIX 1
+#include <acexport.h>
+#include <sdacmvls.h>
+
+#include <sudoers.h>
+#include "sudo_auth.h"
+
+/*
+ * securid_init - Initialises communications with ACE server
+ * Arguments in:
+ * pw - UNUSED
+ * auth - sudo authentication structure
+ *
+ * Results out:
+ * auth - auth->data contains pointer to new SecurID handle
+ * return code - Fatal if initialization unsuccessful, otherwise
+ * success.
+ */
+int
+sudo_securid_init(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth)
+{
+ static SDI_HANDLE sd_dat; /* SecurID handle */
+ debug_decl(sudo_securid_init, SUDOERS_DEBUG_AUTH);
+
+ /* Only initialize once. */
+ if (auth->data != NULL)
+ debug_return_int(AUTH_SUCCESS);
+
+ if (IS_NONINTERACTIVE(auth))
+ debug_return_int(AUTH_NONINTERACTIVE);
+
+ /* Start communications */
+ if (AceInitialize() == SD_FALSE) {
+ sudo_warnx("%s", U_("failed to initialise the ACE API library"));
+ debug_return_int(AUTH_ERROR);
+ }
+
+ auth->data = (void *) &sd_dat; /* For method-specific data */
+
+ debug_return_int(AUTH_SUCCESS);
+}
+
+/*
+ * securid_setup - Initialises a SecurID transaction and locks out other
+ * ACE servers
+ *
+ * Arguments in:
+ * pw - struct passwd for username
+ * promptp - UNUSED
+ * auth - sudo authentication structure for SecurID handle
+ *
+ * Results out:
+ * return code - Success if transaction started correctly, fatal
+ * otherwise
+ */
+int
+sudo_securid_setup(const struct sudoers_context *ctx, struct passwd *pw,
+ char **promptp, sudo_auth *auth)
+{
+ SDI_HANDLE *sd = (SDI_HANDLE *) auth->data;
+ int retval;
+ debug_decl(sudo_securid_setup, SUDOERS_DEBUG_AUTH);
+
+ /* Re-initialize SecurID every time. */
+ if (SD_Init(sd) != ACM_OK) {
+ sudo_warnx("%s", U_("unable to contact the SecurID server"));
+ debug_return_int(AUTH_ERROR);
+ }
+
+ /* Lock new PIN code */
+ retval = SD_Lock(*sd, pw->pw_name);
+
+ switch (retval) {
+ case ACM_OK:
+ sudo_warnx("%s", U_("User ID locked for SecurID Authentication"));
+ debug_return_int(AUTH_SUCCESS);
+
+ case ACE_UNDEFINED_USERNAME:
+ sudo_warnx("%s", U_("invalid username length for SecurID"));
+ debug_return_int(AUTH_ERROR);
+
+ case ACE_ERR_INVALID_HANDLE:
+ sudo_warnx("%s", U_("invalid Authentication Handle for SecurID"));
+ debug_return_int(AUTH_ERROR);
+
+ case ACM_ACCESS_DENIED:
+ sudo_warnx("%s", U_("SecurID communication failed"));
+ debug_return_int(AUTH_ERROR);
+
+ default:
+ sudo_warnx("%s", U_("unknown SecurID error"));
+ debug_return_int(AUTH_ERROR);
+ }
+}
+
+/*
+ * securid_verify - Authenticates user and handles ACE responses
+ *
+ * Arguments in:
+ * pw - struct passwd for username
+ * prompt - UNUSED
+ * auth - sudo authentication structure for SecurID handle
+ *
+ * Results out:
+ * return code - Success on successful authentication, failure on
+ * incorrect authentication, fatal on errors
+ */
+int
+sudo_securid_verify(const struct sudoers_context *ctx, struct passwd *pw,
+ const char *promp, sudo_auth *auth, struct sudo_conv_callback *callback)
+{
+ SDI_HANDLE *sd = (SDI_HANDLE *) auth->data;
+ char *pass;
+ int ret;
+ debug_decl(sudo_securid_verify, SUDOERS_DEBUG_AUTH);
+
+ pass = auth_getpass("Enter your PASSCODE: ", SUDO_CONV_PROMPT_ECHO_OFF,
+ callback);
+
+ /* Have ACE verify password */
+ switch (SD_Check(*sd, pass, pw->pw_name)) {
+ case ACM_OK:
+ ret = AUTH_SUCESS;
+ break;
+
+ case ACE_UNDEFINED_PASSCODE:
+ sudo_warnx("%s", U_("invalid passcode length for SecurID"));
+ ret = AUTH_ERROR;
+ break;
+
+ case ACE_UNDEFINED_USERNAME:
+ sudo_warnx("%s", U_("invalid username length for SecurID"));
+ ret = AUTH_ERROR;
+ break;
+
+ case ACE_ERR_INVALID_HANDLE:
+ sudo_warnx("%s", U_("invalid Authentication Handle for SecurID"));
+ ret = AUTH_ERROR;
+ break;
+
+ case ACM_ACCESS_DENIED:
+ ret = AUTH_FAILURE;
+ break;
+
+ case ACM_NEXT_CODE_REQUIRED:
+ /* Sometimes (when current token close to expire?)
+ ACE challenges for the next token displayed
+ (entered without the PIN) */
+ if (pass != NULL)
+ freezero(pass, strlen(pass));
+ pass = auth_getpass("\
+!!! ATTENTION !!!\n\
+Wait for the token code to change, \n\
+then enter the new token code.\n", \
+ SUDO_CONV_PROMPT_ECHO_OFF, callback);
+
+ if (SD_Next(*sd, pass) == ACM_OK) {
+ ret = AUTH_SUCCESS;
+ break;
+ }
+
+ ret = AUTH_FAILURE;
+ break;
+
+ case ACM_NEW_PIN_REQUIRED:
+ /*
+ * This user's SecurID has not been activated yet,
+ * or the pin has been reset
+ */
+ /* XXX - Is setting up a new PIN within sudo's scope? */
+ SD_Pin(*sd, "");
+ sudo_printf(SUDO_CONV_ERROR_MSG|SUDO_CONV_PREFER_TTY,
+ "Your SecurID access has not yet been set up.\n");
+ sudo_printf(SUDO_CONV_ERROR_MSG|SUDO_CONV_PREFER_TTY,
+ "Please set up a PIN before you try to authenticate.\n");
+ ret = AUTH_ERROR;
+ break;
+
+ default:
+ sudo_warnx("%s", U_("unknown SecurID error"));
+ ret = AUTH_ERROR;
+ break;
+ }
+
+ /* Free resources */
+ SD_Close(*sd);
+
+ if (pass != NULL)
+ freezero(pass, strlen(pass));
+
+ /* Return stored state to calling process */
+ debug_return_int(ret);
+}
+
+#endif /* HAVE_SECURID */
diff --git a/plugins/sudoers/auth/sia.c b/plugins/sudoers/auth/sia.c
new file mode 100644
index 0000000..9c55071
--- /dev/null
+++ b/plugins/sudoers/auth/sia.c
@@ -0,0 +1,160 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999-2005, 2007, 2010-2015
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_SIA_SES_INIT
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <signal.h>
+#include <siad.h>
+
+#include <sudoers.h>
+#include "sudo_auth.h"
+
+static int sudo_argc;
+static char **sudo_argv;
+static char *sudo_tty;
+
+int
+sudo_sia_setup(const struct sudoers_context *ctx, struct passwd *pw,
+ char **promptp, sudo_auth *auth)
+{
+ SIAENTITY *siah;
+ int i;
+ debug_decl(sudo_sia_setup, SUDOERS_DEBUG_AUTH);
+
+ /* Rebuild argv for sia_ses_init() */
+ sudo_argc = ctx->runas.argc + 1;
+ sudo_argv = reallocarray(NULL, sudo_argc + 1, sizeof(char *));
+ if (sudo_argv == NULL) {
+ log_warningx(ctx, 0, N_("unable to allocate memory"));
+ debug_return_int(AUTH_ERROR);
+ }
+ sudo_argv[0] = "sudo";
+ for (i = 0; i < ctx->runas.argc; i++)
+ sudo_argv[i + 1] = ctx->runas.argv[i];
+ sudo_argv[sudo_argc] = NULL;
+
+ /* We don't let SIA prompt the user for input. */
+ sudo_tty = ctx->user.ttypath;
+ if (sia_ses_init(&siah, sudo_argc, sudo_argv, NULL, pw->pw_name, sudo_tty, 0, NULL) != SIASUCCESS) {
+ log_warning(ctx, 0, N_("unable to initialize SIA session"));
+ debug_return_int(AUTH_ERROR);
+ }
+
+ auth->data = siah;
+ debug_return_int(AUTH_SUCCESS);
+}
+
+int
+sudo_sia_verify(const struct sudoers_context *ctx, struct passwd *pw,
+ const char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback)
+{
+ SIAENTITY *siah = auth->data;
+ char *pass;
+ int rc;
+ debug_decl(sudo_sia_verify, SUDOERS_DEBUG_AUTH);
+
+ if (IS_NONINTERACTIVE(auth))
+ debug_return_int(AUTH_NONINTERACTIVE);
+
+ /* Get password, return AUTH_INTR if we got ^C */
+ pass = auth_getpass(prompt, SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ if (pass == NULL)
+ debug_return_int(AUTH_INTR);
+
+ /* Check password and zero out plaintext copy. */
+ rc = sia_ses_authent(NULL, pass, siah);
+ freezero(pass, strlen(pass));
+
+ if (rc == SIASUCCESS)
+ debug_return_int(AUTH_SUCCESS);
+ if (ISSET(rc, SIASTOP))
+ debug_return_int(AUTH_ERROR);
+ debug_return_int(AUTH_FAILURE);
+}
+
+int
+sudo_sia_cleanup(const struct sudoers_context *ctx, struct passwd *pw,
+ sudo_auth *auth, bool force)
+{
+ SIAENTITY *siah = auth->data;
+ debug_decl(sudo_sia_cleanup, SUDOERS_DEBUG_AUTH);
+
+ (void) sia_ses_release(&siah);
+ auth->data = NULL;
+ free(sudo_argv);
+ debug_return_int(AUTH_SUCCESS);
+}
+
+int
+sudo_sia_begin_session(const struct sudoers_context *ctx, struct passwd *pw,
+ char **user_envp[], sudo_auth *auth)
+{
+ SIAENTITY *siah;
+ int status = AUTH_ERROR;
+ debug_decl(sudo_sia_begin_session, SUDOERS_DEBUG_AUTH);
+
+ /* Re-init sia for the target user's session. */
+ if (sia_ses_init(&siah, sudo_argc - 1, sudo_argv + 1, NULL, pw->pw_name, sudo_tty, 0, NULL) != SIASUCCESS) {
+ log_warning(ctx, 0, N_("unable to initialize SIA session"));
+ goto done;
+ }
+
+ if (sia_make_entity_pwd(pw, siah) != SIASUCCESS) {
+ sudo_warn("sia_make_entity_pwd");
+ goto done;
+ }
+
+ status = AUTH_FAILURE; /* no more fatal errors. */
+
+ siah->authtype = SIA_A_NONE;
+ if (sia_ses_estab(sia_collect_trm, siah) != SIASUCCESS) {
+ sudo_warn("sia_ses_estab");
+ goto done;
+ }
+
+ if (sia_ses_launch(sia_collect_trm, siah) != SIASUCCESS) {
+ sudo_warn("sia_ses_launch");
+ goto done;
+ }
+
+ status = AUTH_SUCCESS;
+
+done:
+ (void) sia_ses_release(&siah);
+ debug_return_int(status);
+}
+
+#endif /* HAVE_SIA_SES_INIT */
diff --git a/plugins/sudoers/auth/sudo_auth.c b/plugins/sudoers/auth/sudo_auth.c
new file mode 100644
index 0000000..b74ab34
--- /dev/null
+++ b/plugins/sudoers/auth/sudo_auth.c
@@ -0,0 +1,557 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999-2005, 2008-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <time.h>
+#include <signal.h>
+
+#include <sudoers.h>
+#include "sudo_auth.h"
+#include <insults.h>
+#include <timestamp.h>
+
+static sudo_auth auth_switch[] = {
+/* Standalone entries first */
+#ifdef HAVE_AIXAUTH
+ AUTH_ENTRY("aixauth", FLAG_STANDALONE, sudo_aix_init, NULL, sudo_aix_verify, NULL, sudo_aix_cleanup, NULL, NULL)
+#endif
+#ifdef HAVE_PAM
+ AUTH_ENTRY("pam", FLAG_STANDALONE, sudo_pam_init, NULL, sudo_pam_verify, sudo_pam_approval, sudo_pam_cleanup, sudo_pam_begin_session, sudo_pam_end_session)
+#endif
+#ifdef HAVE_SECURID
+ AUTH_ENTRY("SecurId", FLAG_STANDALONE, sudo_securid_init, sudo_securid_setup, sudo_securid_verify, NULL, NULL, NULL, NULL)
+#endif
+#ifdef HAVE_SIA_SES_INIT
+ AUTH_ENTRY("sia", FLAG_STANDALONE, NULL, sudo_sia_setup, sudo_sia_verify, NULL, sudo_sia_cleanup, sudo_sia_begin_session, NULL)
+#endif
+#ifdef HAVE_FWTK
+ AUTH_ENTRY("fwtk", FLAG_STANDALONE, sudo_fwtk_init, NULL, sudo_fwtk_verify, NULL, sudo_fwtk_cleanup, NULL, NULL)
+#endif
+#ifdef HAVE_BSD_AUTH_H
+ AUTH_ENTRY("bsdauth", FLAG_STANDALONE, bsdauth_init, NULL, bsdauth_verify, bsdauth_approval, bsdauth_cleanup, NULL, NULL)
+#endif
+
+/* Non-standalone entries */
+#ifndef WITHOUT_PASSWD
+ AUTH_ENTRY("passwd", 0, sudo_passwd_init, NULL, sudo_passwd_verify, NULL, sudo_passwd_cleanup, NULL, NULL)
+#endif
+#if defined(HAVE_GETPRPWNAM) && !defined(WITHOUT_PASSWD)
+ AUTH_ENTRY("secureware", 0, sudo_secureware_init, NULL, sudo_secureware_verify, NULL, sudo_secureware_cleanup, NULL, NULL)
+#endif
+#ifdef HAVE_AFS
+ AUTH_ENTRY("afs", 0, NULL, NULL, sudo_afs_verify, NULL, NULL, NULL, NULL)
+#endif
+#ifdef HAVE_DCE
+ AUTH_ENTRY("dce", 0, NULL, NULL, sudo_dce_verify, NULL, NULL, NULL, NULL)
+#endif
+#ifdef HAVE_KERB5
+ AUTH_ENTRY("kerb5", 0, sudo_krb5_init, sudo_krb5_setup, sudo_krb5_verify, NULL, sudo_krb5_cleanup, NULL, NULL)
+#endif
+#ifdef HAVE_SKEY
+ AUTH_ENTRY("S/Key", 0, NULL, sudo_rfc1938_setup, sudo_rfc1938_verify, NULL, NULL, NULL, NULL)
+#endif
+#ifdef HAVE_OPIE
+ AUTH_ENTRY("OPIE", 0, NULL, sudo_rfc1938_setup, sudo_rfc1938_verify, NULL, NULL, NULL, NULL)
+#endif
+ AUTH_ENTRY(NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
+};
+
+static bool standalone;
+
+/*
+ * Initialize sudoers authentication method(s).
+ * Returns AUTH_SUCCESS on success and AUTH_ERROR on error.
+ */
+int
+sudo_auth_init(const struct sudoers_context *ctx, struct passwd *pw,
+ unsigned int mode)
+{
+ sudo_auth *auth;
+ debug_decl(sudo_auth_init, SUDOERS_DEBUG_AUTH);
+
+ if (auth_switch[0].name == NULL)
+ debug_return_int(AUTH_SUCCESS);
+
+ /* Initialize auth methods and unconfigure the method if necessary. */
+ for (auth = auth_switch; auth->name; auth++) {
+ if (ISSET(mode, MODE_NONINTERACTIVE))
+ SET(auth->flags, FLAG_NONINTERACTIVE);
+ if (auth->init && !IS_DISABLED(auth)) {
+ /* Disable if it failed to init unless there was a fatal error. */
+ switch ((auth->init)(ctx, pw, auth)) {
+ case AUTH_SUCCESS:
+ break;
+ case AUTH_FAILURE:
+ SET(auth->flags, FLAG_DISABLED);
+ break;
+ default:
+ /* Assume error msg already printed. */
+ debug_return_int(AUTH_ERROR);
+ }
+ }
+ }
+
+ /*
+ * Make sure we haven't mixed standalone and shared auth methods.
+ * If there are multiple standalone methods, only use the first one.
+ */
+ if ((standalone = IS_STANDALONE(&auth_switch[0]))) {
+ bool found = false;
+ for (auth = auth_switch; auth->name; auth++) {
+ if (IS_DISABLED(auth))
+ continue;
+ if (!IS_STANDALONE(auth)) {
+ audit_failure(ctx, ctx->runas.argv,
+ N_("invalid authentication methods"));
+ log_warningx(ctx, SLOG_SEND_MAIL,
+ N_("Invalid authentication methods compiled into sudo! "
+ "You may not mix standalone and non-standalone authentication."));
+ debug_return_int(AUTH_ERROR);
+ }
+ if (!found) {
+ /* Found first standalone method. */
+ found = true;
+ continue;
+ }
+ /* Disable other standalone methods. */
+ SET(auth->flags, FLAG_DISABLED);
+ }
+ }
+
+ /* Set FLAG_ONEANDONLY if there is only one auth method. */
+ for (auth = auth_switch; auth->name; auth++) {
+ /* Find first enabled auth method. */
+ if (!IS_DISABLED(auth)) {
+ sudo_auth *first = auth;
+ /* Check for others. */
+ for (; auth->name; auth++) {
+ if (!IS_DISABLED(auth))
+ break;
+ }
+ if (auth->name == NULL)
+ SET(first->flags, FLAG_ONEANDONLY);
+ break;
+ }
+ }
+
+ debug_return_int(AUTH_SUCCESS);
+}
+
+/*
+ * Call all authentication approval methods, if any.
+ * Returns AUTH_SUCCESS, AUTH_FAILURE or AUTH_ERROR.
+ */
+int
+sudo_auth_approval(const struct sudoers_context *ctx, struct passwd *pw,
+ unsigned int validated, bool exempt)
+{
+ int ret = AUTH_SUCCESS;
+ sudo_auth *auth;
+ debug_decl(sudo_auth_approval, SUDOERS_DEBUG_AUTH);
+
+ /* Call approval routines. */
+ for (auth = auth_switch; auth->name; auth++) {
+ if (auth->approval && !IS_DISABLED(auth)) {
+ ret = (auth->approval)(ctx, pw, auth, exempt);
+ if (ret != AUTH_SUCCESS) {
+ /* Assume error msg already printed. */
+ log_auth_failure(ctx, validated, 0);
+ break;
+ }
+ }
+ }
+ debug_return_int(ret);
+}
+
+/*
+ * Cleanup all authentication methods.
+ * Returns AUTH_SUCCESS on success and AUTH_ERROR on error.
+ */
+int
+sudo_auth_cleanup(const struct sudoers_context *ctx, struct passwd *pw,
+ bool force)
+{
+ sudo_auth *auth;
+ debug_decl(sudo_auth_cleanup, SUDOERS_DEBUG_AUTH);
+
+ /* Call cleanup routines. */
+ for (auth = auth_switch; auth->name; auth++) {
+ if (auth->cleanup && !IS_DISABLED(auth)) {
+ int status = (auth->cleanup)(ctx, pw, auth, force);
+ if (status != AUTH_SUCCESS) {
+ /* Assume error msg already printed. */
+ debug_return_int(AUTH_ERROR);
+ }
+ }
+ }
+ debug_return_int(AUTH_SUCCESS);
+}
+
+static void
+pass_warn(void)
+{
+ const char *warning = def_badpass_message;
+ debug_decl(pass_warn, SUDOERS_DEBUG_AUTH);
+
+#ifdef INSULT
+ if (def_insults)
+ warning = INSULT;
+#endif
+ sudo_printf(SUDO_CONV_ERROR_MSG|SUDO_CONV_PREFER_TTY, "%s\n", warning);
+
+ debug_return;
+}
+
+static bool
+user_interrupted(void)
+{
+ sigset_t mask;
+
+ return (sigpending(&mask) == 0 &&
+ (sigismember(&mask, SIGINT) || sigismember(&mask, SIGQUIT)));
+}
+
+/*
+ * Called when getpass is suspended so we can drop the lock.
+ */
+static int
+getpass_suspend(int signo, void *vclosure)
+{
+ struct getpass_closure *closure = vclosure;
+
+ timestamp_close(closure->cookie);
+ closure->cookie = NULL;
+ return 0;
+}
+
+/*
+ * Called when getpass is resumed so we can reacquire the lock.
+ */
+static int
+getpass_resume(int signo, void *vclosure)
+{
+ struct getpass_closure *closure = vclosure;
+
+ closure->cookie = timestamp_open(closure->ctx);
+ if (closure->cookie == NULL)
+ return -1;
+ if (!timestamp_lock(closure->cookie, closure->auth_pw))
+ return -1;
+ return 0;
+}
+
+/*
+ * Verify the specified user.
+ * Returns AUTH_SUCCESS, AUTH_FAILURE or AUTH_ERROR.
+ */
+int
+verify_user(const struct sudoers_context *ctx, struct passwd *pw, char *prompt,
+ unsigned int validated, struct sudo_conv_callback *callback)
+{
+ struct sigaction sa, saved_sigtstp;
+ int ret = AUTH_FAILURE;
+ unsigned int ntries;
+ sigset_t mask, omask;
+ sudo_auth *auth;
+ debug_decl(verify_user, SUDOERS_DEBUG_AUTH);
+
+ /* Make sure we have at least one auth method. */
+ if (auth_switch[0].name == NULL) {
+ audit_failure(ctx, ctx->runas.argv, N_("no authentication methods"));
+ log_warningx(ctx, SLOG_SEND_MAIL,
+ N_("There are no authentication methods compiled into sudo! "
+ "If you want to turn off authentication, use the "
+ "--disable-authentication configure option."));
+ debug_return_int(AUTH_ERROR);
+ }
+
+ /* Enable suspend during password entry. */
+ callback->on_suspend = getpass_suspend;
+ callback->on_resume = getpass_resume;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = SIG_DFL;
+ (void) sigaction(SIGTSTP, &sa, &saved_sigtstp);
+
+ /*
+ * We treat authentication as a critical section and block
+ * keyboard-generated signals such as SIGINT and SIGQUIT
+ * which might otherwise interrupt a sleep(3).
+ * They are temporarily unblocked by auth_getpass().
+ */
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGQUIT);
+ (void) sigprocmask(SIG_BLOCK, &mask, &omask);
+
+ for (ntries = 0; ntries < def_passwd_tries; ntries++) {
+ int num_methods = 0;
+ char *pass = NULL;
+
+ /* If user attempted to interrupt password verify, quit now. */
+ if (user_interrupted())
+ goto done;
+
+ if (ntries != 0)
+ pass_warn();
+
+ /* Do any per-method setup and unconfigure the method if needed */
+ for (auth = auth_switch; auth->name; auth++) {
+ if (IS_DISABLED(auth))
+ continue;
+ num_methods++;
+ if (auth->setup != NULL) {
+ switch ((auth->setup)(ctx, pw, &prompt, auth)) {
+ case AUTH_SUCCESS:
+ if (user_interrupted())
+ goto done; /* assume error msg already printed */
+ break;
+ case AUTH_FAILURE:
+ SET(auth->flags, FLAG_DISABLED);
+ break;
+ case AUTH_NONINTERACTIVE:
+ /* Non-interactive mode, cannot prompt user. */
+ goto done;
+ default:
+ ret = AUTH_ERROR;
+ goto done;
+ }
+ }
+ }
+ if (num_methods == 0) {
+ audit_failure(ctx, ctx->runas.argv,
+ N_("no authentication methods"));
+ log_warningx(ctx, SLOG_SEND_MAIL,
+ N_("Unable to initialize authentication methods."));
+ debug_return_int(AUTH_ERROR);
+ }
+
+ /* Get the password unless the auth function will do it for us */
+ if (!standalone) {
+ if (IS_NONINTERACTIVE(&auth_switch[0])) {
+ ret = AUTH_NONINTERACTIVE;
+ goto done;
+ }
+ pass = auth_getpass(prompt, SUDO_CONV_PROMPT_ECHO_OFF, callback);
+ if (pass == NULL)
+ break;
+ }
+
+ /* Call authentication functions. */
+ for (auth = auth_switch; auth->name; auth++) {
+ if (IS_DISABLED(auth))
+ continue;
+
+ ret = auth->status = (auth->verify)(ctx, pw,
+ standalone ? prompt : pass, auth, callback);
+ if (ret != AUTH_FAILURE)
+ break;
+ }
+ if (pass != NULL)
+ freezero(pass, strlen(pass));
+
+ if (ret != AUTH_FAILURE)
+ goto done;
+ }
+
+done:
+ /* Restore signal handlers and signal mask. */
+ (void) sigaction(SIGTSTP, &saved_sigtstp, NULL);
+ (void) sigprocmask(SIG_SETMASK, &omask, NULL);
+
+ switch (ret) {
+ case AUTH_SUCCESS:
+ break;
+ case AUTH_INTR:
+ ret = AUTH_FAILURE;
+ FALLTHROUGH;
+ case AUTH_FAILURE:
+ if (ntries != 0)
+ SET(validated, FLAG_BAD_PASSWORD);
+ log_auth_failure(ctx, validated, ntries);
+ break;
+ case AUTH_NONINTERACTIVE:
+ SET(validated, FLAG_NO_USER_INPUT);
+ FALLTHROUGH;
+ default:
+ log_auth_failure(ctx, validated, 0);
+ ret = AUTH_ERROR;
+ break;
+ }
+
+ debug_return_int(ret);
+}
+
+/*
+ * Call authentication method begin session hooks.
+ * Returns true on success, false on failure and -1 on error.
+ */
+int
+sudo_auth_begin_session(const struct sudoers_context *ctx, struct passwd *pw,
+ char **user_env[])
+{
+ sudo_auth *auth;
+ int ret = true;
+ debug_decl(sudo_auth_begin_session, SUDOERS_DEBUG_AUTH);
+
+ for (auth = auth_switch; auth->name; auth++) {
+ if (auth->begin_session && !IS_DISABLED(auth)) {
+ int status = (auth->begin_session)(ctx, pw, user_env, auth);
+ switch (status) {
+ case AUTH_SUCCESS:
+ break;
+ case AUTH_FAILURE:
+ ret = false;
+ break;
+ default:
+ /* Assume error msg already printed. */
+ ret = -1;
+ break;
+ }
+ }
+ }
+ debug_return_int(ret);
+}
+
+bool
+sudo_auth_needs_end_session(void)
+{
+ sudo_auth *auth;
+ bool needed = false;
+ debug_decl(sudo_auth_needs_end_session, SUDOERS_DEBUG_AUTH);
+
+ for (auth = auth_switch; auth->name; auth++) {
+ if (auth->end_session && !IS_DISABLED(auth)) {
+ needed = true;
+ break;
+ }
+ }
+ debug_return_bool(needed);
+}
+
+/*
+ * Call authentication method end session hooks.
+ * Returns true on success, false on failure and -1 on error.
+ */
+int
+sudo_auth_end_session(void)
+{
+ sudo_auth *auth;
+ int ret = true;
+ int status;
+ debug_decl(sudo_auth_end_session, SUDOERS_DEBUG_AUTH);
+
+ for (auth = auth_switch; auth->name; auth++) {
+ if (auth->end_session && !IS_DISABLED(auth)) {
+ status = (auth->end_session)(auth);
+ switch (status) {
+ case AUTH_SUCCESS:
+ break;
+ case AUTH_FAILURE:
+ ret = false;
+ break;
+ default:
+ /* Assume error msg already printed. */
+ ret = -1;
+ break;
+ }
+ }
+ }
+ debug_return_int(ret);
+}
+
+/*
+ * Prompts the user for a password using the conversation function.
+ * Returns the plaintext password or NULL.
+ * The user is responsible for freeing the returned value.
+ */
+char *
+auth_getpass(const char *prompt, int type, struct sudo_conv_callback *callback)
+{
+ struct sudo_conv_message msg;
+ struct sudo_conv_reply repl;
+ sigset_t mask, omask;
+ debug_decl(auth_getpass, SUDOERS_DEBUG_AUTH);
+
+ /* Display lecture if needed and we haven't already done so. */
+ display_lecture(callback);
+
+ /* Mask user input if pwfeedback set and echo is off. */
+ if (type == SUDO_CONV_PROMPT_ECHO_OFF && def_pwfeedback)
+ type = SUDO_CONV_PROMPT_MASK;
+
+ /* If visiblepw set, do not error out if there is no tty. */
+ if (def_visiblepw)
+ type |= SUDO_CONV_PROMPT_ECHO_OK;
+
+ /* Unblock SIGINT and SIGQUIT during password entry. */
+ /* XXX - do in tgetpass() itself instead? */
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGQUIT);
+ (void) sigprocmask(SIG_UNBLOCK, &mask, &omask);
+
+ /* Call conversation function. */
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_type = type;
+ msg.timeout = (int)def_passwd_timeout.tv_sec;
+ msg.msg = prompt;
+ memset(&repl, 0, sizeof(repl));
+ sudo_conv(1, &msg, &repl, callback);
+ /* XXX - check for ENOTTY? */
+
+ /* Restore previous signal mask. */
+ (void) sigprocmask(SIG_SETMASK, &omask, NULL);
+
+ debug_return_str_masked(repl.reply);
+}
+
+void
+dump_auth_methods(void)
+{
+ sudo_auth *auth;
+ debug_decl(dump_auth_methods, SUDOERS_DEBUG_AUTH);
+
+ sudo_printf(SUDO_CONV_INFO_MSG, _("Authentication methods:"));
+ for (auth = auth_switch; auth->name; auth++)
+ sudo_printf(SUDO_CONV_INFO_MSG, " '%s'", auth->name);
+ sudo_printf(SUDO_CONV_INFO_MSG, "\n");
+
+ debug_return;
+}
diff --git a/plugins/sudoers/auth/sudo_auth.h b/plugins/sudoers/auth/sudo_auth.h
new file mode 100644
index 0000000..bcb248a
--- /dev/null
+++ b/plugins/sudoers/auth/sudo_auth.h
@@ -0,0 +1,106 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999-2005, 2007-2016, 2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_AUTH_H
+#define SUDO_AUTH_H
+
+/* Private auth function return values (rowhammer resistant). */
+#define AUTH_INTR 0x69d61fc8 /* 1101001110101100001111111001000 */
+#define AUTH_NONINTERACTIVE 0x1629e037 /* 0010110001010011110000000110111 */
+
+struct sudoers_context;
+typedef struct sudo_auth {
+ unsigned int flags; /* various flags, see below */
+ int status; /* status from verify routine */
+ const char *name; /* name of the method as a string */
+ void *data; /* method-specific data pointer */
+ int (*init)(const struct sudoers_context *ctx, struct passwd *pw, struct sudo_auth *auth);
+ int (*setup)(const struct sudoers_context *ctx, struct passwd *pw, char **prompt, struct sudo_auth *auth);
+ int (*verify)(const struct sudoers_context *ctx, struct passwd *pw, const char *p, struct sudo_auth *auth, struct sudo_conv_callback *callback);
+ int (*approval)(const struct sudoers_context *ctx, struct passwd *pw, struct sudo_auth *auth, bool exempt);
+ int (*cleanup)(const struct sudoers_context *ctx, struct passwd *pw, struct sudo_auth *auth, bool force);
+ int (*begin_session)(const struct sudoers_context *ctx, struct passwd *pw, char **user_env[], struct sudo_auth *auth);
+ int (*end_session)(struct sudo_auth *auth);
+} sudo_auth;
+
+/* Values for sudo_auth.flags. */
+#define FLAG_DISABLED 0x02U /* method disabled */
+#define FLAG_STANDALONE 0x04U /* standalone auth method */
+#define FLAG_ONEANDONLY 0x08U /* one and only auth method */
+#define FLAG_NONINTERACTIVE 0x10U /* no user input allowed */
+
+/* Shortcuts for using the flags above. */
+#define IS_DISABLED(x) ((x)->flags & FLAG_DISABLED)
+#define IS_STANDALONE(x) ((x)->flags & FLAG_STANDALONE)
+#define IS_ONEANDONLY(x) ((x)->flags & FLAG_ONEANDONLY)
+#define IS_NONINTERACTIVE(x) ((x)->flags & FLAG_NONINTERACTIVE)
+
+/* Like tgetpass() but uses conversation function */
+char *auth_getpass(const char *prompt, int type, struct sudo_conv_callback *callback);
+
+/* Pointer to conversation function to use with auth_getpass(). */
+extern sudo_conv_t sudo_conv;
+
+/* Prototypes for standalone methods */
+int bsdauth_init(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth);
+int bsdauth_verify(const struct sudoers_context *ctx, struct passwd *pw, const char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
+int bsdauth_approval(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth, bool exempt);
+int bsdauth_cleanup(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth, bool force);
+void bsdauth_set_style(const char *style);
+int sudo_aix_init(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth);
+int sudo_aix_verify(const struct sudoers_context *ctx, struct passwd *pw, const char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
+int sudo_aix_cleanup(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth, bool force);
+int sudo_fwtk_init(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth);
+int sudo_fwtk_verify(const struct sudoers_context *ctx, struct passwd *pw, const char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
+int sudo_fwtk_cleanup(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth, bool force);
+int sudo_pam_init(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth);
+int sudo_pam_init_quiet(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth);
+int sudo_pam_verify(const struct sudoers_context *ctx, struct passwd *pw, const char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
+int sudo_pam_approval(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth, bool exempt);
+int sudo_pam_cleanup(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth, bool force);
+int sudo_pam_begin_session(const struct sudoers_context *ctx, struct passwd *pw, char **user_env[], sudo_auth *auth);
+int sudo_pam_end_session(sudo_auth *auth);
+int sudo_securid_init(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth);
+int sudo_securid_setup(const struct sudoers_context *ctx, struct passwd *pw, char **prompt, sudo_auth *auth);
+int sudo_securid_verify(const struct sudoers_context *ctx, struct passwd *pw, const char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
+int sudo_sia_setup(const struct sudoers_context *ctx, struct passwd *pw, char **prompt, sudo_auth *auth);
+int sudo_sia_verify(const struct sudoers_context *ctx, struct passwd *pw, const char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
+int sudo_sia_cleanup(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth, bool force);
+int sudo_sia_begin_session(const struct sudoers_context *ctx, struct passwd *pw, char **user_env[], sudo_auth *auth);
+
+/* Prototypes for normal methods */
+int sudo_afs_verify(const struct sudoers_context *ctx, struct passwd *pw, const char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
+int sudo_dce_verify(const struct sudoers_context *ctx, struct passwd *pw, const char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
+int sudo_krb5_init(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth);
+int sudo_krb5_setup(const struct sudoers_context *ctx, struct passwd *pw, char **prompt, sudo_auth *auth);
+int sudo_krb5_verify(const struct sudoers_context *ctx, struct passwd *pw, const char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
+int sudo_krb5_cleanup(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth, bool force);
+int sudo_passwd_init(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth);
+int sudo_passwd_verify(const struct sudoers_context *ctx, struct passwd *pw, const char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
+int sudo_passwd_cleanup(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth, bool force);
+int sudo_rfc1938_setup(const struct sudoers_context *ctx, struct passwd *pw, char **prompt, sudo_auth *auth);
+int sudo_rfc1938_verify(const struct sudoers_context *ctx, struct passwd *pw, const char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
+int sudo_secureware_init(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth);
+int sudo_secureware_verify(const struct sudoers_context *ctx, struct passwd *pw, const char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
+int sudo_secureware_cleanup(const struct sudoers_context *ctx, struct passwd *pw, sudo_auth *auth, bool force);
+
+/* Fields: name, flags, init, setup, verify, approval, cleanup, begin_sess, end_sess */
+#define AUTH_ENTRY(n, f, i, s, v, a, c, b, e) \
+ { (f), AUTH_FAILURE, (n), NULL, (i), (s), (v), (a), (c) , (b), (e) },
+
+#endif /* SUDO_AUTH_H */
diff --git a/plugins/sudoers/b64_decode.c b/plugins/sudoers/b64_decode.c
new file mode 100644
index 0000000..6242888
--- /dev/null
+++ b/plugins/sudoers/b64_decode.c
@@ -0,0 +1,83 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sudoers.h>
+
+/*
+ * Derived from code with the following declaration:
+ * PUBLIC DOMAIN - Jon Mayo - November 13, 2003
+ */
+
+static const unsigned char base64dec_tab[256]= {
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255,
+ 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
+ 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+};
+
+/*
+ * Decode a NUL-terminated string in base64 format and store the
+ * result in dst.
+ */
+size_t
+base64_decode(const char *in, unsigned char *out, size_t out_size)
+{
+ unsigned char *out_end = out + out_size;
+ const unsigned char *out0 = out;
+ unsigned int rem, v;
+ debug_decl(base64_decode, SUDOERS_DEBUG_MATCH);
+
+ for (v = 0, rem = 0; *in != '\0' && *in != '='; in++) {
+ unsigned char ch = base64dec_tab[(unsigned char)*in];
+ if (ch == 255)
+ debug_return_size_t((size_t)-1);
+ v = (v << 6) | ch;
+ rem += 6;
+ if (rem >= 8) {
+ rem -= 8;
+ if (out >= out_end)
+ debug_return_size_t((size_t)-1);
+ *out++ = (v >> rem) & 0xff;
+ }
+ }
+ if (rem >= 8) {
+ if (out >= out_end)
+ debug_return_size_t((size_t)-1);
+ *out++ = (v >> rem) & 0xff;
+ }
+ debug_return_size_t((size_t)(out - out0));
+}
diff --git a/plugins/sudoers/b64_encode.c b/plugins/sudoers/b64_encode.c
new file mode 100644
index 0000000..1e1afa0
--- /dev/null
+++ b/plugins/sudoers/b64_encode.c
@@ -0,0 +1,64 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sudoers.h>
+
+static const unsigned char base64enc_tab[64] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+size_t
+base64_encode(const unsigned char *in, size_t in_len, char *out, size_t out_len)
+{
+ size_t ii, io;
+ unsigned int rem, v;
+ debug_decl(base64_encode, SUDOERS_DEBUG_MATCH);
+
+ for (io = 0, ii = 0, v = 0, rem = 0; ii < in_len; ii++) {
+ unsigned char ch = in[ii];
+ v = (v << 8) | ch;
+ rem += 8;
+ while (rem >= 6) {
+ rem -= 6;
+ if (io >= out_len)
+ debug_return_size_t((size_t)-1); /* truncation is failure */
+ out[io++] = (char)base64enc_tab[(v >> rem) & 63];
+ }
+ }
+ if (rem != 0) {
+ v <<= (6 - rem);
+ if (io >= out_len)
+ debug_return_size_t((size_t)-1); /* truncation is failure */
+ out[io++] = (char)base64enc_tab[v&63];
+ }
+ while (io & 3) {
+ if (io >= out_len)
+ debug_return_size_t((size_t)-1); /* truncation is failure */
+ out[io++] = '=';
+ }
+ if (io >= out_len)
+ debug_return_size_t((size_t)-1); /* no room for NUL terminator */
+ out[io] = '\0';
+ debug_return_size_t(io);
+}
diff --git a/plugins/sudoers/boottime.c b/plugins/sudoers/boottime.c
new file mode 100644
index 0000000..5e7ce5f
--- /dev/null
+++ b/plugins/sudoers/boottime.c
@@ -0,0 +1,167 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2015, 2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h> /* for size_t, ssize_t */
+#include <sys/time.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <time.h>
+#ifndef __linux__
+# if defined(HAVE_SYS_SYSCTL_H)
+# include <sys/sysctl.h>
+# elif defined(HAVE_GETUTXID)
+# include <utmpx.h>
+# elif defined(HAVE_GETUTID)
+# include <utmp.h>
+# endif
+#endif /* !__linux__ */
+
+#include <sudoers.h>
+
+/*
+ * Fill in a struct timespec with the time the system booted.
+ * Returns 1 on success and 0 on failure.
+ */
+
+#if defined(__linux__)
+bool
+get_boottime(struct timespec *ts)
+{
+ char *line = NULL;
+ size_t linesize = 0;
+ bool found = false;
+ long long llval;
+ ssize_t len;
+ FILE *fp;
+ debug_decl(get_boottime, SUDOERS_DEBUG_UTIL);
+
+ /* read btime from /proc/stat */
+ fp = fopen("/proc/stat", "r");
+ if (fp != NULL) {
+ while ((len = getdelim(&line, &linesize, '\n', fp)) != -1) {
+ if (strncmp(line, "btime ", 6) == 0) {
+ if (line[len - 1] == '\n')
+ line[len - 1] = '\0';
+ llval = sudo_strtonum(line + 6, 1, LLONG_MAX, NULL);
+ if (llval > 0) {
+ ts->tv_sec = (time_t)llval;
+ ts->tv_nsec = 0;
+ found = true;
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "found btime in /proc/stat: %lld", llval);
+ break;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "invalid btime in /proc/stat: %s", line);
+ }
+ }
+ }
+ fclose(fp);
+ free(line);
+ }
+
+ debug_return_bool(found);
+}
+
+#elif defined(HAVE_SYSCTL) && defined(KERN_BOOTTIME)
+
+bool
+get_boottime(struct timespec *ts)
+{
+ size_t size;
+ int mib[2];
+ struct timeval tv;
+ debug_decl(get_boottime, SUDOERS_DEBUG_UTIL);
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_BOOTTIME;
+ size = sizeof(tv);
+ if (sysctl(mib, 2, &tv, &size, NULL, 0) != -1) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "KERN_BOOTTIME: %lld, %ld", (long long)tv.tv_sec, (long)tv.tv_usec);
+ TIMEVAL_TO_TIMESPEC(&tv, ts);
+ debug_return_bool(true);
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "KERN_BOOTTIME: %s", strerror(errno));
+ debug_return_bool(false);
+}
+
+#elif defined(HAVE_GETUTXID)
+
+bool
+get_boottime(struct timespec *ts)
+{
+ struct utmpx *ut, key;
+ debug_decl(get_boottime, SUDOERS_DEBUG_UTIL);
+
+ memset(&key, 0, sizeof(key));
+ key.ut_type = BOOT_TIME;
+ setutxent();
+ if ((ut = getutxid(&key)) != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "BOOT_TIME: %lld, %ld", (long long)ut->ut_tv.tv_sec,
+ (long)ut->ut_tv.tv_usec);
+ TIMEVAL_TO_TIMESPEC(&ut->ut_tv, ts);
+ }
+ endutxent();
+ debug_return_bool(ut != NULL);
+}
+
+#elif defined(HAVE_GETUTID)
+
+bool
+get_boottime(struct timespec *ts)
+{
+ struct utmp *ut, key;
+ debug_decl(get_boottime, SUDOERS_DEBUG_UTIL);
+
+ memset(&key, 0, sizeof(key));
+ key.ut_type = BOOT_TIME;
+ setutent();
+ if ((ut = getutid(&key)) != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "BOOT_TIME: %lld", (long long)ut->ut_time);
+ ts->tv_sec = ut->ut_time;
+ ts->tv_nsec = 0;
+ }
+ endutent();
+ debug_return_bool(ut != NULL);
+}
+
+#else
+
+bool
+get_boottime(struct timespec *ts)
+{
+ debug_decl(get_boottime, SUDOERS_DEBUG_UTIL);
+ debug_return_bool(false);
+}
+#endif
diff --git a/plugins/sudoers/bsm_audit.c b/plugins/sudoers/bsm_audit.c
new file mode 100644
index 0000000..95bd2d1
--- /dev/null
+++ b/plugins/sudoers/bsm_audit.c
@@ -0,0 +1,284 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ * Copyright (c) 2009 Christian S.J. Peron
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_BSM_AUDIT
+
+#include <sys/types.h> /* for pid_t */
+
+#include <bsm/audit.h>
+#include <bsm/libbsm.h>
+#include <bsm/audit_uevents.h>
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sudoers.h>
+#include <bsm_audit.h>
+
+/*
+ * Solaris auditon() returns EINVAL if BSM audit not configured.
+ * OpenBSM returns ENOSYS for unimplemented options.
+ */
+#ifdef __sun
+# define AUDIT_NOT_CONFIGURED EINVAL
+#else
+# define AUDIT_NOT_CONFIGURED ENOSYS
+#endif
+
+#ifdef __FreeBSD__
+# define BSM_AUDIT_COMPAT
+#endif
+
+static au_event_t sudo_audit_event = AUE_sudo;
+
+static int
+audit_sudo_selected(int sorf)
+{
+ auditinfo_addr_t ainfo_addr;
+ struct au_mask *mask;
+ int rc;
+ debug_decl(audit_sudo_selected, SUDOERS_DEBUG_AUDIT);
+
+ if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0) {
+#ifdef BSM_AUDIT_COMPAT
+ if (errno == ENOSYS) {
+ auditinfo_t ainfo;
+
+ /* Fall back to older BSM API. */
+ if (getaudit(&ainfo) < 0) {
+ sudo_warn("getaudit");
+ debug_return_int(-1);
+ }
+ mask = &ainfo.ai_mask;
+ } else
+#endif /* BSM_AUDIT_COMPAT */
+ {
+ sudo_warn("getaudit_addr");
+ debug_return_int(-1);
+ }
+ } else {
+ mask = &ainfo_addr.ai_mask;
+ }
+ rc = au_preselect(sudo_audit_event, mask, sorf, AU_PRS_REREAD);
+ if (rc == -1) {
+#if defined(__APPLE__) && defined(AUE_DARWIN_sudo)
+ /*
+ * Mac OS X 10.10 au_preselect() only accepts AUE_DARWIN_sudo.
+ */
+ sudo_audit_event = AUE_DARWIN_sudo;
+ rc = au_preselect(sudo_audit_event, mask, sorf, AU_PRS_REREAD);
+ if (rc == -1)
+#endif
+
+ sudo_warn("au_preselect");
+ }
+ debug_return_int(rc);
+}
+
+/*
+ * Returns 0 on success or -1 on error.
+ */
+int
+bsm_audit_success(const struct sudoers_context *ctx, char *const exec_args[])
+{
+ auditinfo_addr_t ainfo_addr;
+ token_t *tok;
+ au_id_t auid;
+ long au_cond;
+ int aufd, selected;
+ debug_decl(bsm_audit_success, SUDOERS_DEBUG_AUDIT);
+
+ /*
+ * If we are not auditing, don't cut an audit record; just return.
+ */
+ if (auditon(A_GETCOND, (caddr_t)&au_cond, sizeof(long)) < 0) {
+ if (errno == AUDIT_NOT_CONFIGURED)
+ debug_return_int(0);
+ sudo_warn("%s", U_("Could not determine audit condition"));
+ debug_return_int(-1);
+ }
+ if (au_cond == AUC_NOAUDIT)
+ debug_return_int(0);
+ /*
+ * Check to see if the preselection masks are interested in seeing
+ * this event.
+ */
+ selected = audit_sudo_selected(AU_PRS_SUCCESS);
+ if (selected != 1)
+ debug_return_int(!selected ? 0 : -1);
+ if (getauid(&auid) < 0) {
+ sudo_warn("getauid");
+ debug_return_int(-1);
+ }
+ if ((aufd = au_open()) == -1) {
+ sudo_warn("au_open");
+ debug_return_int(-1);
+ }
+ if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) {
+ tok = au_to_subject_ex(auid, ctx->user.euid, ctx->user.egid,
+ ctx->user.uid, ctx->user.gid, ctx->user.pid, ctx->user.pid,
+ &ainfo_addr.ai_termid);
+#ifdef BSM_AUDIT_COMPAT
+ } else if (errno == ENOSYS) {
+ auditinfo_t ainfo;
+
+ /*
+ * NB: We should probably watch out for ERANGE here.
+ */
+ if (getaudit(&ainfo) < 0) {
+ sudo_warn("getaudit");
+ debug_return_int(-1);
+ }
+ tok = au_to_subject(auid, ctx->user.euid, ctx->user.egid,
+ ctx->user.uid, ctx->user.gid, ctx->user.pid, ctx->user.pid,
+ &ainfo.ai_termid);
+#endif /* BSM_AUDIT_COMPAT */
+ } else {
+ sudo_warn("getaudit_addr");
+ debug_return_int(-1);
+ }
+ if (tok == NULL) {
+ sudo_warn("au_to_subject");
+ debug_return_int(-1);
+ }
+ au_write(aufd, tok);
+ tok = au_to_exec_args((char **)exec_args);
+ if (tok == NULL) {
+ sudo_warn("au_to_exec_args");
+ debug_return_int(-1);
+ }
+ au_write(aufd, tok);
+ tok = au_to_return32(0, 0);
+ if (tok == NULL) {
+ sudo_warn("au_to_return32");
+ debug_return_int(-1);
+ }
+ au_write(aufd, tok);
+#ifdef HAVE_AU_CLOSE_SOLARIS11
+ if (au_close(aufd, 1, sudo_audit_event, 0) == -1)
+#else
+ if (au_close(aufd, 1, sudo_audit_event) == -1)
+#endif
+ {
+ sudo_warn("%s", U_("unable to commit audit record"));
+ debug_return_int(-1);
+ }
+ debug_return_int(0);
+}
+
+/*
+ * Returns 0 on success or -1 on error.
+ */
+int
+bsm_audit_failure(const struct sudoers_context *ctx, char *const exec_args[],
+ const char *errmsg)
+{
+ auditinfo_addr_t ainfo_addr;
+ token_t *tok;
+ long au_cond;
+ au_id_t auid;
+ int aufd;
+ debug_decl(bsm_audit_failure, SUDOERS_DEBUG_AUDIT);
+
+ /*
+ * If we are not auditing, don't cut an audit record; just return.
+ */
+ if (auditon(A_GETCOND, (caddr_t)&au_cond, sizeof(long)) < 0) {
+ if (errno == AUDIT_NOT_CONFIGURED)
+ debug_return_int(0);
+ sudo_warn("%s", U_("Could not determine audit condition"));
+ debug_return_int(-1);
+ }
+ if (au_cond == AUC_NOAUDIT)
+ debug_return_int(0);
+ if (!audit_sudo_selected(AU_PRS_FAILURE))
+ debug_return_int(0);
+ if (getauid(&auid) < 0) {
+ sudo_warn("getauid");
+ debug_return_int(-1);
+ }
+ if ((aufd = au_open()) == -1) {
+ sudo_warn("au_open");
+ debug_return_int(-1);
+ }
+ if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) {
+ tok = au_to_subject_ex(auid, ctx->user.euid, ctx->user.egid,
+ ctx->user.uid, ctx->user.gid, ctx->user.pid, ctx->user.pid,
+ &ainfo_addr.ai_termid);
+#ifdef BSM_AUDIT_COMPAT
+ } else if (errno == ENOSYS) {
+ auditinfo_t ainfo;
+
+ if (getaudit(&ainfo) < 0) {
+ sudo_warn("getaudit");
+ debug_return_int(-1);
+ }
+ tok = au_to_subject(auid, ctx->user.euid, ctx->user.egid,
+ ctx->user.uid, ctx->user.gid, ctx->user.pid, ctx->user.pid,
+ &ainfo.ai_termid);
+#endif /* BSM_AUDIT_COMPAT */
+ } else {
+ sudo_warn("getaudit_addr");
+ debug_return_int(-1);
+ }
+ if (tok == NULL) {
+ sudo_warn("au_to_subject");
+ debug_return_int(-1);
+ }
+ au_write(aufd, tok);
+ tok = au_to_exec_args((char **)exec_args);
+ if (tok == NULL) {
+ sudo_warn("au_to_exec_args");
+ debug_return_int(-1);
+ }
+ au_write(aufd, tok);
+ tok = au_to_text((char *)errmsg);
+ if (tok == NULL) {
+ sudo_warn("au_to_text");
+ debug_return_int(-1);
+ }
+ au_write(aufd, tok);
+ tok = au_to_return32(EPERM, 1);
+ if (tok == NULL) {
+ sudo_warn("au_to_return32");
+ debug_return_int(-1);
+ }
+ au_write(aufd, tok);
+#ifdef HAVE_AU_CLOSE_SOLARIS11
+ if (au_close(aufd, 1, sudo_audit_event, PAD_FAILURE) == -1)
+#else
+ if (au_close(aufd, 1, sudo_audit_event) == -1)
+#endif
+ {
+ sudo_warn("%s", U_("unable to commit audit record"));
+ debug_return_int(-1);
+ }
+ debug_return_int(0);
+}
+
+#endif /* HAVE_BSM_AUDIT */
diff --git a/plugins/sudoers/bsm_audit.h b/plugins/sudoers/bsm_audit.h
new file mode 100644
index 0000000..5128fa5
--- /dev/null
+++ b/plugins/sudoers/bsm_audit.h
@@ -0,0 +1,26 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2010, 2013-2014 Todd C. Miller <Todd.Miller@sudo.ws>
+ * Copyright (c) 2009 Christian S.J. Peron
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_BSM_AUDIT_H
+#define SUDOERS_BSM_AUDIT_H
+
+int bsm_audit_success(const struct sudoers_context *ctx, char *const argv[]);
+int bsm_audit_failure(const struct sudoers_context *ctx, char *const argv[], const char *errmsg);
+
+#endif /* SUDOERS_BSM_AUDIT_H */
diff --git a/plugins/sudoers/canon_path.c b/plugins/sudoers/canon_path.c
new file mode 100644
index 0000000..79f8eef
--- /dev/null
+++ b/plugins/sudoers/canon_path.c
@@ -0,0 +1,200 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sudoers.h>
+#include <redblack.h>
+
+static struct rbtree *canon_cache;
+
+/*
+ * A cache_item includes storage for both the original path and the
+ * resolved path. The resolved path is directly embedded into the
+ * struct so that we can find the start of the struct cache_item
+ * given the value of resolved. Storage for pathname is embedded
+ * at the end with resolved.
+ */
+struct cache_item {
+ unsigned int refcnt;
+ char *pathname;
+ char resolved[];
+};
+
+/*
+ * Compare function for canon_cache.
+ * v1 is the key to find or data to insert, v2 is in-tree data.
+ */
+static int
+compare(const void *v1, const void *v2)
+{
+ const struct cache_item *ci1 = (const struct cache_item *)v1;
+ const struct cache_item *ci2 = (const struct cache_item *)v2;
+ return strcmp(ci1->pathname, ci2->pathname);
+}
+
+/* Convert a pointer returned by canon_path() to a struct cache_item *. */
+#define resolved_to_item(_r) ((struct cache_item *)((_r) - offsetof(struct cache_item, resolved)))
+
+/*
+ * Delete a ref from item and free if the refcount reaches 0.
+ */
+static void
+canon_path_free_item(void *v)
+{
+ struct cache_item *item = v;
+ debug_decl(canon_path_free_item, SUDOERS_DEBUG_UTIL);
+
+ if (--item->refcnt == 0)
+ free(item);
+
+ debug_return;
+}
+
+/*
+ * Delete a ref from the item containing "resolved" and free if
+ * the refcount reaches 0.
+ */
+void
+canon_path_free(char *resolved)
+{
+ debug_decl(canon_path_free, SUDOERS_DEBUG_UTIL);
+ if (resolved != NULL)
+ canon_path_free_item(resolved_to_item(resolved));
+ debug_return;
+}
+
+/*
+ * Free canon_cache.
+ * This only removes the reference for that the cache owns.
+ * Other references remain valid until canon_path_free() is called.
+ */
+void
+canon_path_free_cache(void)
+{
+ debug_decl(canon_path_free_cache, SUDOERS_DEBUG_UTIL);
+
+ if (canon_cache != NULL) {
+ rbdestroy(canon_cache, canon_path_free_item);
+ canon_cache = NULL;
+ }
+
+ debug_return;
+}
+
+/*
+ * Like realpath(3) but caches the result. Returns an entry from the
+ * cache on success (with an added reference) or NULL on failure.
+ */
+char *
+canon_path(const char *inpath)
+{
+ size_t item_size, inlen, reslen = 0;
+ char *resolved, resbuf[PATH_MAX];
+ struct cache_item key, *item;
+ struct rbnode *node = NULL;
+ debug_decl(canon_path, SUDOERS_DEBUG_UTIL);
+
+ if (canon_cache == NULL) {
+ canon_cache = rbcreate(compare);
+ if (canon_cache == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_str(NULL);
+ }
+ } else {
+ /* Check cache. */
+ key.pathname = (char *)inpath;
+ if ((node = rbfind(canon_cache, &key)) != NULL) {
+ item = node->data;
+ goto done;
+ }
+ }
+
+ /*
+ * Not cached, call realpath(3).
+ * Older realpath() doesn't support passing a NULL buffer.
+ * We special-case the empty string to resolve to "/".
+ * XXX - warn on errors other than ENOENT?
+ */
+ if (*inpath == '\0')
+ resolved = (char *)"/";
+ else
+ resolved = realpath(inpath, resbuf);
+
+ inlen = strlen(inpath);
+ /* one for NULL terminator of resolved, one for NULL terminator of pathname */
+ item_size = sizeof(*item) + inlen + 2;
+ if (resolved != NULL) {
+ reslen = strlen(resolved);
+ item_size += reslen;
+ }
+ item = malloc(item_size);
+ if (item == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_str(NULL);
+ }
+ if (resolved != NULL)
+ memcpy(item->resolved, resolved, reslen);
+ item->resolved[reslen] = '\0';
+ item->pathname = item->resolved + reslen + 1;
+ memcpy(item->pathname, inpath, inlen);
+ item->pathname[inlen] = '\0';
+ item->refcnt = 1;
+ switch (rbinsert(canon_cache, item, NULL)) {
+ case 1:
+ /* should not happen */
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "path \"%s\" already exists in the cache", inpath);
+ item->refcnt = 0;
+ break;
+ case -1:
+ /* can't cache item, just return it */
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "can't cache path \"%s\"", inpath);
+ item->refcnt = 0;
+ break;
+ }
+done:
+ if (item->refcnt != 0) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s: path %s -> %s (%s)", __func__, inpath,
+ item->resolved[0] ? item->resolved : "NULL",
+ node ? "cache hit" : "cached");
+ }
+ if (item->resolved[0] == '\0') {
+ /* negative result, free item if not cached */
+ if (item->refcnt == 0)
+ free(item);
+ debug_return_str(NULL);
+ }
+ item->refcnt++;
+ debug_return_str(item->resolved);
+}
diff --git a/plugins/sudoers/check.c b/plugins/sudoers/check.c
new file mode 100644
index 0000000..4356dd1
--- /dev/null
+++ b/plugins/sudoers/check.c
@@ -0,0 +1,325 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1993-1996,1998-2005, 2007-2018
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h> /* for ssize_t */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <sudoers.h>
+#include <timestamp.h>
+
+/*
+ * Get passwd entry for the user we are going to authenticate as.
+ * By default, this is the user invoking sudo. In the most common
+ * case, this matches ctx->user.pw or ctx->runas.pw.
+ */
+static struct passwd *
+get_authpw(struct sudoers_context *ctx, unsigned int mode)
+{
+ struct passwd *pw = NULL;
+ debug_decl(get_authpw, SUDOERS_DEBUG_AUTH);
+
+ if (ISSET(mode, (MODE_CHECK|MODE_LIST))) {
+ /* In list mode we always prompt for the user's password. */
+ sudo_pw_addref(ctx->user.pw);
+ pw = ctx->user.pw;
+ } else {
+ if (def_rootpw) {
+ if ((pw = sudo_getpwuid(ROOT_UID)) == NULL) {
+ log_warningx(ctx, SLOG_SEND_MAIL, N_("unknown uid %u"),
+ ROOT_UID);
+ }
+ } else if (def_runaspw) {
+ if ((pw = sudo_getpwnam(def_runas_default)) == NULL) {
+ log_warningx(ctx, SLOG_SEND_MAIL,
+ N_("unknown user %s"), def_runas_default);
+ }
+ } else if (def_targetpw) {
+ if (ctx->runas.pw->pw_name == NULL) {
+ /* This should never be NULL as we fake up the passwd struct */
+ log_warningx(ctx, SLOG_RAW_MSG, N_("unknown uid %u"),
+ (unsigned int) ctx->runas.pw->pw_uid);
+ } else {
+ sudo_pw_addref(ctx->runas.pw);
+ pw = ctx->runas.pw;
+ }
+ } else {
+ sudo_pw_addref(ctx->user.pw);
+ pw = ctx->user.pw;
+ }
+ }
+
+ debug_return_ptr(pw);
+}
+
+/*
+ * Returns AUTH_SUCCESS if the user successfully authenticates,
+ * AUTH_FAILURE if not or AUTH_ERROR on error.
+ */
+int
+check_user(struct sudoers_context *ctx, unsigned int validated,
+ unsigned int mode)
+{
+ struct getpass_closure closure = { 0 };
+ struct sudo_conv_callback callback;
+ int status = TS_ERROR;
+ int ret = AUTH_ERROR;
+ bool exempt = false;
+ char *prompt;
+ debug_decl(check_user, SUDOERS_DEBUG_AUTH);
+
+ /*
+ * In intercept mode, only check the user if configured to do so.
+ * We already have a session so no need to init the auth subsystem.
+ */
+ if (ISSET(ctx->mode, MODE_POLICY_INTERCEPTED)) {
+ if (!def_intercept_authenticate) {
+ debug_return_int(AUTH_SUCCESS);
+ }
+ }
+
+ /*
+ * Init authentication system regardless of whether we need a password.
+ * Required for proper PAM session support.
+ */
+ if ((closure.auth_pw = get_authpw(ctx, mode)) == NULL)
+ debug_return_int(AUTH_ERROR);
+ if (sudo_auth_init(ctx, closure.auth_pw, mode) != AUTH_SUCCESS) {
+ sudo_pw_delref(closure.auth_pw);
+ debug_return_int(AUTH_ERROR);
+ }
+ closure.ctx = ctx;
+
+ /*
+ * Don't prompt for the root passwd or if the user is exempt.
+ * If the user is not changing uid/gid, no need for a password.
+ */
+ if (!def_authenticate || user_is_exempt(ctx)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: %s", __func__,
+ !def_authenticate ? "authentication disabled" :
+ "user exempt from authentication");
+ exempt = true;
+ ret = AUTH_SUCCESS;
+ goto done;
+ }
+ if (ctx->user.uid == 0 || (ctx->user.uid == ctx->runas.pw->pw_uid &&
+ (ctx->runas.gr == NULL ||
+ user_in_group(ctx->user.pw, ctx->runas.gr->gr_name)))) {
+#ifdef HAVE_SELINUX
+ if (ctx->runas.role == NULL && ctx->runas.type == NULL)
+#endif
+#ifdef HAVE_APPARMOR
+ if (ctx->runas.apparmor_profile == NULL)
+#endif
+#ifdef HAVE_PRIV_SET
+ if (ctx->runas.privs == NULL && ctx->runas.limitprivs == NULL)
+#endif
+ {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: user running command as self", __func__);
+ ret = AUTH_SUCCESS;
+ goto done;
+ }
+ }
+
+ /* Construct callback for getpass function. */
+ memset(&callback, 0, sizeof(callback));
+ callback.version = SUDO_CONV_CALLBACK_VERSION;
+ callback.closure = &closure;
+
+ /* Open, lock and read time stamp file if we are using it. */
+ if (!ISSET(mode, MODE_IGNORE_TICKET)) {
+ /* Open time stamp file and check its status. */
+ closure.cookie = timestamp_open(ctx);
+ if (closure.cookie != NULL) {
+ if (timestamp_lock(closure.cookie, closure.auth_pw)) {
+ status = timestamp_status(closure.cookie, closure.auth_pw);
+ }
+ }
+ }
+
+ switch (status) {
+ case TS_FATAL:
+ /* Fatal error (usually setuid failure), unsafe to proceed. */
+ goto done;
+
+ case TS_CURRENT:
+ /* Time stamp file is valid and current. */
+ if (!ISSET(validated, FLAG_CHECK_USER)) {
+ ret = AUTH_SUCCESS;
+ break;
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: check user flag overrides time stamp", __func__);
+ FALLTHROUGH;
+
+ default:
+ if (ISSET(mode, MODE_NONINTERACTIVE) && !def_noninteractive_auth) {
+ validated |= FLAG_NO_USER_INPUT;
+ log_auth_failure(ctx, validated, 0);
+ goto done;
+ }
+
+ /* Expand any escapes in the prompt. */
+ prompt = expand_prompt(ctx,
+ ctx->user.prompt ? ctx->user.prompt : def_passprompt,
+ closure.auth_pw->pw_name);
+ if (prompt == NULL)
+ goto done;
+
+ ret = verify_user(ctx, closure.auth_pw, prompt, validated, &callback);
+ if (ret == AUTH_SUCCESS && closure.lectured)
+ (void)set_lectured(ctx); /* lecture error not fatal */
+ free(prompt);
+ break;
+ }
+
+done:
+ if (ret == AUTH_SUCCESS) {
+ /* The approval function may disallow a user post-authentication. */
+ ret = sudo_auth_approval(ctx, closure.auth_pw, validated, exempt);
+
+ /*
+ * Only update time stamp if user validated and was approved.
+ * Failure to update the time stamp is not a fatal error.
+ */
+ if (ret == AUTH_SUCCESS && ISSET(validated, VALIDATE_SUCCESS)) {
+ if (ISSET(mode, MODE_UPDATE_TICKET) && status != TS_ERROR)
+ (void)timestamp_update(closure.cookie, closure.auth_pw);
+ }
+ }
+ timestamp_close(closure.cookie);
+ sudo_auth_cleanup(ctx, closure.auth_pw, !ISSET(validated, VALIDATE_SUCCESS));
+ sudo_pw_delref(closure.auth_pw);
+
+ debug_return_int(ret);
+}
+
+/*
+ * Display sudo lecture (standard or custom).
+ * Returns true if the user was lectured, else false.
+ */
+void
+display_lecture(struct sudo_conv_callback *callback)
+{
+ struct getpass_closure *closure;
+ struct sudo_conv_message msg[2];
+ struct sudo_conv_reply repl[2];
+ char buf[BUFSIZ];
+ struct stat sb;
+ ssize_t nread;
+ int fd, msgcount = 1;
+ debug_decl(lecture, SUDOERS_DEBUG_AUTH);
+
+ if (callback == NULL || (closure = callback->closure) == NULL)
+ debug_return;
+
+ if (closure->lectured)
+ debug_return;
+
+ if (def_lecture == never ||
+ (def_lecture == once && already_lectured(closure->ctx)))
+ debug_return;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&repl, 0, sizeof(repl));
+
+ if (def_lecture_file) {
+ fd = open(def_lecture_file, O_RDONLY|O_NONBLOCK);
+ if (fd != -1 && fstat(fd, &sb) == 0) {
+ if (S_ISREG(sb.st_mode)) {
+ (void) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
+ while ((nread = read(fd, buf, sizeof(buf) - 1)) > 0) {
+ buf[nread] = '\0';
+ msg[0].msg_type = SUDO_CONV_ERROR_MSG|SUDO_CONV_PREFER_TTY;
+ msg[0].msg = buf;
+ sudo_conv(1, msg, repl, NULL);
+ }
+ if (nread == 0) {
+ close(fd);
+ goto done;
+ }
+ log_warning(closure->ctx, SLOG_RAW_MSG,
+ N_("error reading lecture file %s"), def_lecture_file);
+ } else {
+ log_warningx(closure->ctx, SLOG_RAW_MSG,
+ N_("ignoring lecture file %s: not a regular file"),
+ def_lecture_file);
+ }
+ } else {
+ log_warning(closure->ctx, SLOG_RAW_MSG|SLOG_NO_STDERR,
+ N_("unable to open %s"), def_lecture_file);
+ }
+ if (fd != -1)
+ close(fd);
+ }
+
+ /* Default sudo lecture. */
+ msg[0].msg_type = SUDO_CONV_ERROR_MSG|SUDO_CONV_PREFER_TTY;
+ msg[0].msg = _("\n"
+ "We trust you have received the usual lecture from the local System\n"
+ "Administrator. It usually boils down to these three things:\n\n"
+ " #1) Respect the privacy of others.\n"
+ " #2) Think before you type.\n"
+ " #3) With great power comes great responsibility.\n\n");
+ if (!def_pwfeedback) {
+ msg[1].msg_type = SUDO_CONV_ERROR_MSG|SUDO_CONV_PREFER_TTY;
+ msg[1].msg = _("For security reasons, the password you type will not be visible.\n\n");
+ msgcount++;
+ }
+ sudo_conv(msgcount, msg, repl, NULL);
+
+done:
+ closure->lectured = true;
+ debug_return;
+}
+
+/*
+ * Checks if the user is exempt from supplying a password.
+ */
+bool
+user_is_exempt(const struct sudoers_context *ctx)
+{
+ bool ret = false;
+ debug_decl(user_is_exempt, SUDOERS_DEBUG_AUTH);
+
+ if (def_exempt_group) {
+ if (user_in_group(ctx->user.pw, def_exempt_group))
+ ret = true;
+ }
+ debug_return_bool(ret);
+}
diff --git a/plugins/sudoers/check_aliases.c b/plugins/sudoers/check_aliases.c
new file mode 100644
index 0000000..8719698
--- /dev/null
+++ b/plugins/sudoers/check_aliases.c
@@ -0,0 +1,186 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2004-2005, 2007-2018, 2021-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sudoers.h>
+#include <gram.h>
+
+struct alias_warned {
+ SLIST_ENTRY(alias_warned) entries;
+ const char *name;
+};
+SLIST_HEAD(alias_warned_list, alias_warned);
+
+static bool
+alias_warned(struct alias_warned_list *warned, char *name)
+{
+ struct alias_warned *w;
+ debug_decl(alias_warned, SUDOERS_DEBUG_ALIAS);
+
+ SLIST_FOREACH(w, warned, entries) {
+ if (strcmp(w->name, name) == 0)
+ debug_return_bool(true);
+ }
+
+ debug_return_bool(false);
+}
+
+static void
+alias_warned_add(struct alias_warned_list *warned, char *name)
+{
+ struct alias_warned *w;
+ debug_decl(alias_warned_add, SUDOERS_DEBUG_ALIAS);
+
+ w = malloc(sizeof(*w));
+ if (w != NULL) {
+ w->name = name;
+ SLIST_INSERT_HEAD(warned, w, entries);
+ }
+
+ debug_return;
+}
+
+static int
+check_alias(struct sudoers_parse_tree *parse_tree,
+ struct alias_warned_list *warned, char *name, short type,
+ char *file, int line, int column, bool strict, bool quiet)
+{
+ struct member *m;
+ struct alias *a;
+ int errors = 0;
+ debug_decl(check_alias, SUDOERS_DEBUG_ALIAS);
+
+ if ((a = alias_get(parse_tree, name, type)) != NULL) {
+ /* check alias contents */
+ TAILQ_FOREACH(m, &a->members, entries) {
+ if (m->type != ALIAS)
+ continue;
+ errors += check_alias(parse_tree, warned, m->name, type,
+ a->file, a->line, a->column, strict, quiet);
+ }
+ alias_put(a);
+ } else {
+ if (!alias_warned(warned, name)) {
+ if (errno == ELOOP) {
+ parser_warnx(parse_tree->ctx, file, line, column, strict, quiet,
+ N_("cycle in %s \"%s\""), alias_type_to_string(type), name);
+ } else {
+ parser_warnx(parse_tree->ctx, file, line, column, strict, quiet,
+ N_("%s \"%s\" referenced but not defined"),
+ alias_type_to_string(type), name);
+ }
+ alias_warned_add(warned, name);
+ }
+ errors++;
+ }
+
+ debug_return_int(errors);
+}
+
+/*
+ * Iterate through the sudoers datastructures looking for undefined
+ * aliases or unused aliases.
+ * In strict mode, returns the number of errors, else 0.
+ */
+int
+check_aliases(struct sudoers_parse_tree *parse_tree, bool strict, bool quiet,
+ int (*cb_unused)(struct sudoers_parse_tree *, struct alias *, void *))
+{
+ struct alias_warned_list warned = SLIST_HEAD_INITIALIZER(warned);
+ struct rbtree *used_aliases;
+ struct alias_warned *w;
+ struct cmndspec *cs;
+ struct member *m;
+ struct privilege *priv;
+ struct userspec *us;
+ int errors = 0;
+ debug_decl(check_aliases, SUDOERS_DEBUG_ALIAS);
+
+ used_aliases = alloc_aliases();
+ if (used_aliases == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(-1);
+ }
+
+ /* Forward check. */
+ TAILQ_FOREACH(us, &parse_tree->userspecs, entries) {
+ TAILQ_FOREACH(m, &us->users, entries) {
+ if (m->type == ALIAS) {
+ errors += check_alias(parse_tree, &warned, m->name, USERALIAS,
+ us->file, us->line, us->column, strict, quiet);
+ }
+ }
+ TAILQ_FOREACH(priv, &us->privileges, entries) {
+ TAILQ_FOREACH(m, &priv->hostlist, entries) {
+ if (m->type == ALIAS) {
+ errors += check_alias(parse_tree, &warned, m->name, HOSTALIAS,
+ us->file, us->line, us->column, strict, quiet);
+ }
+ }
+ TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
+ if (cs->runasuserlist != NULL) {
+ TAILQ_FOREACH(m, cs->runasuserlist, entries) {
+ if (m->type == ALIAS) {
+ errors += check_alias(parse_tree, &warned, m->name, RUNASALIAS,
+ us->file, us->line, us->column, strict, quiet);
+ }
+ }
+ }
+ if (cs->runasgrouplist != NULL) {
+ TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
+ if (m->type == ALIAS) {
+ errors += check_alias(parse_tree, &warned, m->name, RUNASALIAS,
+ us->file, us->line, us->column, strict, quiet);
+ }
+ }
+ }
+ if ((m = cs->cmnd)->type == ALIAS) {
+ errors += check_alias(parse_tree, &warned, m->name, CMNDALIAS,
+ us->file, us->line, us->column, strict, quiet);
+ }
+ }
+ }
+ }
+ while ((w = SLIST_FIRST(&warned)) != NULL) {
+ SLIST_REMOVE_HEAD(&warned, entries);
+ free(w);
+ }
+
+ /* Reverse check (destructive) */
+ if (!alias_find_used(parse_tree, used_aliases))
+ errors++;
+ free_aliases(used_aliases);
+
+ /* If all aliases were referenced we will have an empty tree. */
+ if (!no_aliases(parse_tree))
+ alias_apply(parse_tree, cb_unused, &quiet);
+
+ debug_return_int(strict ? errors : 0);
+}
diff --git a/plugins/sudoers/check_util.c b/plugins/sudoers/check_util.c
new file mode 100644
index 0000000..a676069
--- /dev/null
+++ b/plugins/sudoers/check_util.c
@@ -0,0 +1,88 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020, 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#include <sudoers.h>
+
+/*
+ * Check whether specified runchroot matches def_runchroot.
+ * Returns true if matched, false if not matched and -1 on error.
+ */
+int
+check_user_runchroot(const char *runchroot)
+{
+ debug_decl(check_user_runchroot, SUDOERS_DEBUG_AUTH);
+
+ if (runchroot == NULL)
+ debug_return_bool(true);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "def_runchroot %s, runchroot %s",
+ def_runchroot ? def_runchroot : "none", runchroot ? runchroot : "none");
+
+ /* User may only specify a root dir if runchroot is "*" */
+ if (def_runchroot == NULL || strcmp(def_runchroot, "*") != 0)
+ debug_return_bool(false);
+
+ free(def_runchroot);
+ if ((def_runchroot = strdup(runchroot)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(-1);
+ }
+ debug_return_bool(true);
+}
+
+/*
+ * Check whether specified runcwd matches def_runcwd.
+ * Returns true if matched, false if not matched and -1 on error.
+ */
+int
+check_user_runcwd(const char *runcwd)
+{
+ debug_decl(check_user_runcwd, SUDOERS_DEBUG_AUTH);
+
+ if (runcwd == NULL)
+ debug_return_bool(true);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "def_runcwd %s, runcwd %s", def_runcwd ? def_runcwd : "none",
+ runcwd ? runcwd : "none");
+
+ /* User may only specify a cwd if runcwd is "*" */
+ if (def_runcwd == NULL || strcmp(def_runcwd, "*") != 0)
+ debug_return_bool(false);
+
+ free(def_runcwd);
+ if ((def_runcwd = strdup(runcwd)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(-1);
+ }
+ debug_return_bool(true);
+}
diff --git a/plugins/sudoers/cvtsudoers.c b/plugins/sudoers/cvtsudoers.c
new file mode 100644
index 0000000..e1db214
--- /dev/null
+++ b/plugins/sudoers/cvtsudoers.c
@@ -0,0 +1,1556 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2018-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+/*
+ * Convert from the sudoers file format to LDIF or JSON format.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <unistd.h>
+#ifdef HAVE_GETOPT_LONG
+# include <getopt.h>
+# else
+# include <compat/getopt.h>
+#endif /* HAVE_GETOPT_LONG */
+
+#include <sudoers.h>
+#include <sudoers_version.h>
+#include <sudo_lbuf.h>
+#include <redblack.h>
+#include <cvtsudoers.h>
+#include <testsudoers_pwutil.h>
+#include <tsgetgrpw.h>
+#include <gram.h>
+
+/* Long-only options values. */
+#define OPT_GROUP_FILE 256
+#define OPT_PASSWD_FILE 257
+
+/*
+ * Globals
+ */
+struct cvtsudoers_filter *filters;
+static FILE *logfp;
+static const char short_opts[] = "b:c:d:ef:hi:I:l:m:Mo:O:pP:s:V";
+static struct option long_opts[] = {
+ { "base", required_argument, NULL, 'b' },
+ { "config", required_argument, NULL, 'c' },
+ { "defaults", required_argument, NULL, 'd' },
+ { "expand-aliases", no_argument, NULL, 'e' },
+ { "output-format", required_argument, NULL, 'f' },
+ { "help", no_argument, NULL, 'h' },
+ { "input-format", required_argument, NULL, 'i' },
+ { "increment", required_argument, NULL, 'I' },
+ { "logfile", required_argument, NULL, 'l' },
+ { "match", required_argument, NULL, 'm' },
+ { "match-local", no_argument, NULL, 'M' },
+ { "prune-matches", no_argument, NULL, 'p' },
+ { "padding", required_argument, NULL, 'P' },
+ { "order-start", required_argument, NULL, 'O' },
+ { "output", required_argument, NULL, 'o' },
+ { "suppress", required_argument, NULL, 's' },
+ { "version", no_argument, NULL, 'V' },
+ { "group-file", required_argument, NULL, OPT_GROUP_FILE },
+ { "passwd-file", required_argument, NULL, OPT_PASSWD_FILE },
+ { NULL, no_argument, NULL, 0 },
+};
+
+sudo_dso_public int main(int argc, char *argv[]);
+static bool convert_sudoers_sudoers(struct sudoers_parse_tree *parse_tree, const char *output_file, struct cvtsudoers_config *conf);
+static bool parse_sudoers(struct sudoers_context *ctx, const char *input_file, struct cvtsudoers_config *conf);
+static bool parse_ldif(struct sudoers_parse_tree *parse_tree, const char *input_file, struct cvtsudoers_config *conf);
+static bool cvtsudoers_parse_filter(char *expression);
+static struct cvtsudoers_config *cvtsudoers_conf_read(const char *conf_file);
+static void cvtsudoers_conf_free(struct cvtsudoers_config *conf);
+static unsigned int cvtsudoers_parse_defaults(char *expression);
+static unsigned int cvtsudoers_parse_suppression(char *expression);
+static void filter_userspecs(struct sudoers_parse_tree *parse_tree, struct cvtsudoers_config *conf);
+static void filter_defaults(struct sudoers_parse_tree *parse_tree, struct cvtsudoers_config *conf);
+static void alias_remove_unused(struct sudoers_parse_tree *parse_tree);
+static void alias_prune(struct sudoers_parse_tree *parse_tree, struct cvtsudoers_config *conf);
+sudo_noreturn static void help(void);
+sudo_noreturn static void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ struct sudoers_parse_tree_list parse_trees = TAILQ_HEAD_INITIALIZER(parse_trees);
+ struct sudoers_context ctx = SUDOERS_CONTEXT_INITIALIZER;
+ struct sudoers_parse_tree merged_tree, *parse_tree = NULL;
+ struct cvtsudoers_config *conf = NULL;
+ enum sudoers_formats output_format = format_ldif;
+ enum sudoers_formats input_format = format_sudoers;
+ const char *input_file = "-";
+ const char *output_file = "-";
+ const char *conf_file = NULL;
+ const char *grfile = NULL, *pwfile = NULL;
+ const char *cp, *errstr;
+ int ch, exitcode = EXIT_FAILURE;
+ bool match_local = false;
+ debug_decl(main, SUDOERS_DEBUG_MAIN);
+
+#if defined(SUDO_DEVEL) && defined(__OpenBSD__)
+ {
+ extern char *malloc_options;
+ malloc_options = "S";
+ }
+#endif
+
+ initprogname(argc > 0 ? argv[0] : "cvtsudoers");
+ if (!sudoers_initlocale(setlocale(LC_ALL, ""), def_sudoers_locale))
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ sudo_warn_set_locale_func(sudoers_warn_setlocale);
+ bindtextdomain("sudoers", LOCALEDIR);
+ textdomain("sudoers");
+
+ /* Initialize early, before any "goto done". */
+ init_parse_tree(&merged_tree, NULL, NULL, &ctx, NULL);
+
+ /* Read debug and plugin sections of sudo.conf. */
+ if (sudo_conf_read(NULL, SUDO_CONF_DEBUG|SUDO_CONF_PLUGINS) == -1)
+ goto done;
+
+ /* Initialize the debug subsystem. */
+ if (!sudoers_debug_register(getprogname(), sudo_conf_debug_files(getprogname())))
+ goto done;
+
+ /* Check for --config option first (no getopt warnings). */
+ opterr = 0;
+ while ((ch = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
+ switch (ch) {
+ case 'c':
+ conf_file = optarg;
+ break;
+ }
+ }
+
+ /* Read conf file. */
+ conf = cvtsudoers_conf_read(conf_file);
+
+ /*
+ * Reset getopt and handle the rest of the arguments.
+ */
+ opterr = 1;
+ optind = 1;
+#ifdef HAVE_OPTRESET
+ optreset = 1;
+#endif
+ while ((ch = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
+ switch (ch) {
+ case 'b':
+ free(conf->sudoers_base);
+ conf->sudoers_base = strdup(optarg);
+ if (conf->sudoers_base == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ break;
+ case 'c':
+ /* handled above */
+ break;
+ case 'd':
+ conf->defstr = optarg;
+ break;
+ case 'e':
+ conf->expand_aliases = true;
+ break;
+ case 'f':
+ free(conf->output_format);
+ conf->output_format = strdup(optarg);
+ if (conf->output_format == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ break;
+ case 'h':
+ help();
+ /* NOTREACHED */
+ case 'i':
+ free(conf->input_format);
+ conf->input_format = strdup(optarg);
+ if (conf->input_format == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ break;
+ case 'I':
+ conf->order_increment =
+ (unsigned int)sudo_strtonum(optarg, 1, UINT_MAX, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("order increment: %s: %s"), optarg, U_(errstr));
+ usage();
+ }
+ break;
+ case 'l':
+ conf->logfile = optarg;
+ break;
+ case 'm':
+ conf->filter = optarg;
+ break;
+ case 'M':
+ match_local = true;
+ break;
+ case 'o':
+ output_file = optarg;
+ break;
+ case 'O':
+ conf->sudo_order =
+ (unsigned int)sudo_strtonum(optarg, 0, UINT_MAX, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("starting order: %s: %s"), optarg, U_(errstr));
+ usage();
+ }
+ break;
+ case 'p':
+ conf->prune_matches = true;
+ break;
+ case 'P':
+ conf->order_padding =
+ (unsigned int)sudo_strtonum(optarg, 1, UINT_MAX, &errstr);
+ if (errstr != NULL ) {
+ sudo_warnx(U_("order padding: %s: %s"), optarg, U_(errstr));
+ usage();
+ }
+ break;
+ case 's':
+ conf->supstr = optarg;
+ break;
+ case 'V':
+ (void) printf(_("%s version %s\n"), getprogname(),
+ PACKAGE_VERSION);
+ (void) printf(_("%s grammar version %d\n"), getprogname(),
+ SUDOERS_GRAMMAR_VERSION);
+ exitcode = EXIT_SUCCESS;
+ goto done;
+ case OPT_GROUP_FILE:
+ grfile = optarg;
+ break;
+ case OPT_PASSWD_FILE:
+ pwfile = optarg;
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (conf->logfile != NULL) {
+ logfp = fopen(conf->logfile, "w");
+ if (logfp == NULL)
+ sudo_fatalx(U_("unable to open log file %s"), conf->logfile);
+ }
+
+ if (conf->input_format != NULL) {
+ if (strcasecmp(conf->input_format, "ldif") == 0) {
+ input_format = format_ldif;
+ } else if (strcasecmp(conf->input_format, "sudoers") == 0) {
+ input_format = format_sudoers; // -V1048
+ } else {
+ sudo_warnx(U_("unsupported input format %s"), conf->input_format);
+ usage();
+ }
+ }
+ if (conf->output_format != NULL) {
+ if (strcasecmp(conf->output_format, "csv") == 0) {
+ output_format = format_csv;
+ conf->store_options = true;
+ } else if (strcasecmp(conf->output_format, "json") == 0) {
+ output_format = format_json;
+ conf->store_options = true;
+ } else if (strcasecmp(conf->output_format, "ldif") == 0) {
+ output_format = format_ldif; // -V1048
+ conf->store_options = true;
+ } else if (strcasecmp(conf->output_format, "sudoers") == 0) {
+ output_format = format_sudoers;
+ conf->store_options = false;
+ } else {
+ sudo_warnx(U_("unsupported output format %s"), conf->output_format);
+ usage();
+ }
+ }
+ if (conf->filter != NULL) {
+ /* We always expand aliases when filtering (may change in future). */
+ if (!cvtsudoers_parse_filter(conf->filter))
+ usage();
+ }
+ if (conf->defstr != NULL) {
+ conf->defaults = cvtsudoers_parse_defaults(conf->defstr);
+ if (conf->defaults == (unsigned int)-1)
+ usage();
+ }
+ if (conf->supstr != NULL) {
+ conf->suppress = cvtsudoers_parse_suppression(conf->supstr);
+ if (conf->suppress == (unsigned int)-1)
+ usage();
+ }
+
+ /* Apply padding to sudo_order if present. */
+ if (conf->sudo_order != 0 && conf->order_padding != 0) {
+ unsigned int multiplier = 1;
+
+ do {
+ multiplier *= 10;
+ } while (--conf->order_padding != 0);
+ conf->sudo_order *= multiplier;
+ conf->order_max = conf->sudo_order + (multiplier - 1);
+ conf->order_padding = multiplier;
+ }
+
+ /* If no base DN specified, check SUDOERS_BASE. */
+ if (conf->sudoers_base == NULL) {
+ conf->sudoers_base = getenv("SUDOERS_BASE");
+ if (conf->sudoers_base != NULL && *conf->sudoers_base != '\0') {
+ if ((conf->sudoers_base = strdup(conf->sudoers_base)) == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ }
+ }
+
+ /* Set pwutil backend to use the filter data. */
+ if (conf->filter != NULL && !match_local) {
+ sudo_pwutil_set_backend(cvtsudoers_make_pwitem, cvtsudoers_make_gritem,
+ cvtsudoers_make_gidlist_item, cvtsudoers_make_grlist_item, NULL);
+ } else {
+ if (grfile != NULL)
+ testsudoers_setgrfile(grfile);
+ if (pwfile != NULL)
+ testsudoers_setpwfile(pwfile);
+ sudo_pwutil_set_backend(
+ pwfile ? testsudoers_make_pwitem : NULL,
+ grfile ? testsudoers_make_gritem : NULL,
+ grfile ? testsudoers_make_gidlist_item : NULL,
+ grfile ? testsudoers_make_grlist_item : NULL,
+ NULL);
+ }
+
+ /* We may need the hostname to resolve %h escapes in include files. */
+ if (!sudoers_sethost(&ctx, NULL, NULL))
+ goto done;
+
+ do {
+ char *lhost = NULL, *shost = NULL;
+
+ /* Input file (defaults to stdin). */
+ if (argc > 0)
+ input_file = argv[0];
+
+ /* Check for optional hostname prefix on the input file. */
+ cp = strchr(input_file, ':');
+ if (cp != NULL) {
+ struct stat sb;
+
+ if (strcmp(cp, ":-") == 0 || stat(input_file, &sb) == -1) {
+ lhost = strndup(input_file, (size_t)(cp - input_file));
+ if (lhost == NULL)
+ sudo_fatalx("%s", U_("unable to allocate memory"));
+ input_file = cp + 1;
+ cp = strchr(lhost, '.');
+ if (cp == NULL) {
+ shost = lhost;
+ } else {
+ shost = strndup(lhost, (size_t)(cp - lhost));
+ }
+ }
+ }
+
+ if (strcmp(input_file, "-") != 0) {
+ if (strcmp(input_file, output_file) == 0) {
+ sudo_fatalx(U_("%s: input and output files must be different"),
+ input_file);
+ }
+ }
+
+ parse_tree = malloc(sizeof(*parse_tree));
+ if (parse_tree == NULL)
+ sudo_fatalx("%s", U_("unable to allocate memory"));
+ init_parse_tree(parse_tree, lhost, shost, &ctx, NULL);
+ TAILQ_INSERT_TAIL(&parse_trees, parse_tree, entries);
+
+ /* Setup defaults data structures. */
+ if (!init_defaults()) {
+ sudo_fatalx("%s",
+ U_("unable to initialize sudoers default values"));
+ }
+
+ switch (input_format) {
+ case format_ldif:
+ if (!parse_ldif(parse_tree, input_file, conf))
+ goto done;
+ break;
+ case format_sudoers:
+ if (!parse_sudoers(&ctx, input_file, conf))
+ goto done;
+ reparent_parse_tree(parse_tree);
+ break;
+ default:
+ sudo_fatalx("error: unhandled input %d", input_format);
+ }
+
+ /* Apply filters. */
+ filter_userspecs(parse_tree, conf);
+ filter_defaults(parse_tree, conf);
+ if (filters != NULL) {
+ alias_remove_unused(parse_tree);
+ if (conf->prune_matches && conf->expand_aliases)
+ alias_prune(parse_tree, conf);
+ }
+
+ argc--;
+ argv++;
+ } while (argc > 0);
+
+ parse_tree = TAILQ_FIRST(&parse_trees);
+ if (TAILQ_NEXT(parse_tree, entries)) {
+ /* Multiple sudoers files, merge them all. */
+ parse_tree = merge_sudoers(&parse_trees, &merged_tree);
+ }
+
+ switch (output_format) {
+ case format_csv:
+ exitcode = !convert_sudoers_csv(parse_tree, output_file, conf);
+ break;
+ case format_json:
+ exitcode = !convert_sudoers_json(parse_tree, output_file, conf);
+ break;
+ case format_ldif:
+ exitcode = !convert_sudoers_ldif(parse_tree, output_file, conf);
+ break;
+ case format_sudoers:
+ exitcode = !convert_sudoers_sudoers(parse_tree, output_file, conf);
+ break;
+ default:
+ sudo_fatalx("error: unhandled output format %d", output_format);
+ }
+
+done:
+ sudoers_ctx_free(&ctx);
+ free_parse_tree(&merged_tree);
+ while ((parse_tree = TAILQ_FIRST(&parse_trees)) != NULL) {
+ TAILQ_REMOVE(&parse_trees, parse_tree, entries);
+ free_parse_tree(parse_tree);
+ free(parse_tree);
+ }
+ cvtsudoers_conf_free(conf);
+ sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, exitcode);
+ return exitcode;
+}
+
+void
+log_warnx(const char * restrict fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (logfp != NULL) {
+ vfprintf(logfp, fmt, ap);
+ fputc('\n', logfp);
+ } else {
+ sudo_vwarnx_nodebug(fmt, ap);
+ }
+ va_end(ap);
+}
+
+/*
+ * cvtsudoers configuration data.
+ */
+static struct cvtsudoers_config cvtsudoers_config = INITIAL_CONFIG;
+static struct cvtsudoers_conf_table cvtsudoers_conf_vars[] = {
+ { "order_start", CONF_UINT, &cvtsudoers_config.sudo_order },
+ { "order_increment", CONF_UINT, &cvtsudoers_config.order_increment },
+ { "order_padding", CONF_UINT, &cvtsudoers_config.order_padding },
+ { "sudoers_base", CONF_STR, &cvtsudoers_config.sudoers_base },
+ { "input_format", CONF_STR, &cvtsudoers_config.input_format },
+ { "output_format", CONF_STR, &cvtsudoers_config.output_format },
+ { "match", CONF_STR, &cvtsudoers_config.filter },
+ { "match_local", CONF_BOOL, &cvtsudoers_config.match_local },
+ { "logfile", CONF_STR, &cvtsudoers_config.logfile },
+ { "defaults", CONF_STR, &cvtsudoers_config.defstr },
+ { "suppress", CONF_STR, &cvtsudoers_config.supstr },
+ { "group_file", CONF_STR, &cvtsudoers_config.group_file },
+ { "passwd_file", CONF_STR, &cvtsudoers_config.passwd_file },
+ { "expand_aliases", CONF_BOOL, &cvtsudoers_config.expand_aliases },
+ { "prune_matches", CONF_BOOL, &cvtsudoers_config.prune_matches }
+};
+
+/*
+ * Look up keyword in config table.
+ * Returns true if found, else false.
+ */
+static bool
+cvtsudoers_parse_keyword(const char *conf_file, const char *keyword,
+ const char *value, struct cvtsudoers_conf_table *table)
+{
+ struct cvtsudoers_conf_table *cur;
+ const char *errstr;
+ debug_decl(sudo_ldap_parse_keyword, SUDOERS_DEBUG_UTIL);
+
+ /* Look up keyword in config tables */
+ for (cur = table; cur->conf_str != NULL; cur++) {
+ if (strcasecmp(keyword, cur->conf_str) == 0) {
+ switch (cur->type) {
+ case CONF_BOOL:
+ *(bool *)(cur->valp) = sudo_strtobool(value) == true;
+ break;
+ case CONF_UINT:
+ {
+ unsigned int uval =
+ (unsigned int)sudo_strtonum(value, 0, UINT_MAX, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s: %s: %s"),
+ conf_file, keyword, value, U_(errstr));
+ continue;
+ }
+ *(unsigned int *)(cur->valp) = uval;
+ }
+ break;
+ case CONF_STR:
+ {
+ char *cp = strdup(value);
+ if (cp == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ free(*(char **)(cur->valp));
+ *(char **)(cur->valp) = cp;
+ break;
+ }
+ }
+ debug_return_bool(true);
+ }
+ }
+ debug_return_bool(false);
+}
+
+static struct cvtsudoers_config *
+cvtsudoers_conf_read(const char *path)
+{
+ char conf_file[PATH_MAX], *line = NULL;
+ size_t linesize = 0;
+ FILE *fp = NULL;
+ int fd = -1;
+ debug_decl(cvtsudoers_conf_read, SUDOERS_DEBUG_UTIL);
+
+ if (path != NULL) {
+ /* Empty string means use the defaults. */
+ if (*path == '\0')
+ debug_return_ptr(&cvtsudoers_config);
+ if (strlcpy(conf_file, path, sizeof(conf_file)) >= sizeof(conf_file))
+ errno = ENAMETOOLONG;
+ else
+ fd = open(conf_file, O_RDONLY);
+ } else {
+ fd = sudo_open_conf_path(_PATH_CVTSUDOERS_CONF, conf_file,
+ sizeof(conf_file), NULL);
+ }
+ if (fd != -1)
+ fp = fdopen(fd, "r");
+ if (fp == NULL) {
+ if (path != NULL || errno != ENOENT)
+ sudo_warn("%s", conf_file);
+ debug_return_ptr(&cvtsudoers_config);
+ }
+
+ while (sudo_parseln(&line, &linesize, NULL, fp, 0) != -1) {
+ char *keyword, *value;
+ size_t len;
+
+ if (*line == '\0')
+ continue; /* skip empty line */
+
+ /* Parse keyword = value */
+ keyword = line;
+ if ((value = strchr(line, '=')) == NULL || value == line)
+ continue;
+ len = (size_t)(value - line);
+
+ /* Trim whitespace after keyword and NUL-terminate. */
+ while (len > 0 && isblank((unsigned char)line[len - 1]))
+ len--;
+ line[len] = '\0';
+
+ /* Trim whitespace before value. */
+ do {
+ value++;
+ } while (isblank((unsigned char)*value));
+
+ /* Look up keyword in config tables */
+ if (!cvtsudoers_parse_keyword(conf_file, keyword, value, cvtsudoers_conf_vars))
+ sudo_warnx(U_("%s: unknown key word %s"), conf_file, keyword);
+ }
+ free(line);
+ fclose(fp);
+
+ debug_return_ptr(&cvtsudoers_config);
+}
+
+static void
+cvtsudoers_conf_free(struct cvtsudoers_config *conf)
+{
+ debug_decl(cvtsudoers_conf_free, SUDOERS_DEBUG_UTIL);
+
+ if (conf != NULL) {
+ free(conf->sudoers_base);
+ free(conf->input_format);
+ free(conf->output_format);
+ conf->sudoers_base = NULL;
+ conf->input_format = NULL;
+ conf->output_format = NULL;
+ }
+
+ debug_return;
+}
+
+static unsigned int
+cvtsudoers_parse_defaults(char *expression)
+{
+ char *last, *cp = expression;
+ unsigned int flags = 0;
+ debug_decl(cvtsudoers_parse_defaults, SUDOERS_DEBUG_UTIL);
+
+ for ((cp = strtok_r(cp, ",", &last)); cp != NULL; (cp = strtok_r(NULL, ",", &last))) {
+ if (strcasecmp(cp, "all") == 0) {
+ SET(flags, CVT_DEFAULTS_ALL);
+ } else if (strcasecmp(cp, "global") == 0) {
+ SET(flags, CVT_DEFAULTS_GLOBAL);
+ } else if (strcasecmp(cp, "user") == 0) {
+ SET(flags, CVT_DEFAULTS_USER);
+ } else if (strcasecmp(cp, "runas") == 0) {
+ SET(flags, CVT_DEFAULTS_RUNAS);
+ } else if (strcasecmp(cp, "host") == 0) {
+ SET(flags, CVT_DEFAULTS_HOST);
+ } else if (strcasecmp(cp, "command") == 0) {
+ SET(flags, CVT_DEFAULTS_CMND);
+ } else {
+ sudo_warnx(U_("invalid defaults type: %s"), cp);
+ debug_return_uint((unsigned int)-1);
+ }
+ }
+
+ debug_return_uint(flags);
+}
+
+static unsigned int
+cvtsudoers_parse_suppression(char *expression)
+{
+ char *last, *cp = expression;
+ unsigned int flags = 0;
+ debug_decl(cvtsudoers_parse_suppression, SUDOERS_DEBUG_UTIL);
+
+ for ((cp = strtok_r(cp, ",", &last)); cp != NULL; (cp = strtok_r(NULL, ",", &last))) {
+ if (strcasecmp(cp, "defaults") == 0) {
+ SET(flags, SUPPRESS_DEFAULTS);
+ } else if (strcasecmp(cp, "aliases") == 0) {
+ SET(flags, SUPPRESS_ALIASES);
+ } else if (strcasecmp(cp, "privileges") == 0 || strcasecmp(cp, "privs") == 0) {
+ SET(flags, SUPPRESS_PRIVS);
+ } else {
+ sudo_warnx(U_("invalid suppression type: %s"), cp);
+ debug_return_uint((unsigned int)-1);
+ }
+ }
+
+ debug_return_uint(flags);
+}
+
+static bool
+cvtsudoers_parse_filter(char *expression)
+{
+ char *last, *cp = expression;
+ debug_decl(cvtsudoers_parse_filter, SUDOERS_DEBUG_UTIL);
+
+ if (filters == NULL) {
+ if ((filters = malloc(sizeof(*filters))) == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ STAILQ_INIT(&filters->users);
+ STAILQ_INIT(&filters->groups);
+ STAILQ_INIT(&filters->hosts);
+ STAILQ_INIT(&filters->cmnds);
+ }
+
+ for ((cp = strtok_r(cp, ",", &last)); cp != NULL; (cp = strtok_r(NULL, ",", &last))) {
+ /*
+ * Filter expression:
+ * user=foo,group=bar,host=baz
+ */
+ char *keyword;
+ struct sudoers_string *s;
+
+ if ((s = malloc(sizeof(*s))) == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+
+ /* Parse keyword = value */
+ keyword = cp;
+ if ((cp = strchr(cp, '=')) == NULL) {
+ sudo_warnx(U_("invalid filter: %s"), keyword);
+ free(s);
+ debug_return_bool(false);
+ }
+ *cp++ = '\0';
+ s->str = cp;
+
+ if (strcmp(keyword, "user") == 0) {
+ STAILQ_INSERT_TAIL(&filters->users, s, entries);
+ } else if (strcmp(keyword, "group") == 0) {
+ STAILQ_INSERT_TAIL(&filters->groups, s, entries);
+ } else if (strcmp(keyword, "host") == 0) {
+ STAILQ_INSERT_TAIL(&filters->hosts, s, entries);
+ } else if (strcmp(keyword, "cmnd") == 0 || strcmp(keyword, "cmd") == 0) {
+ STAILQ_INSERT_TAIL(&filters->cmnds, s, entries);
+ } else {
+ sudo_warnx(U_("invalid filter: %s"), keyword);
+ free(s);
+ debug_return_bool(false);
+ }
+ }
+
+ debug_return_bool(true);
+}
+
+static bool
+parse_ldif(struct sudoers_parse_tree *parse_tree, const char *input_file,
+ struct cvtsudoers_config *conf)
+{
+ FILE *fp = stdin;
+ bool ret = false;
+ debug_decl(parse_ldif, SUDOERS_DEBUG_UTIL);
+
+ /* Open LDIF file and parse it. */
+ if (strcmp(input_file, "-") != 0) {
+ if ((fp = fopen(input_file, "r")) == NULL)
+ sudo_warn(U_("unable to open %s"), input_file);
+ }
+ if (fp != NULL) {
+ ret = sudoers_parse_ldif(parse_tree, fp, conf->sudoers_base,
+ conf->store_options);
+ if (fp != stdin)
+ fclose(fp);
+ }
+ debug_return_bool(ret);
+}
+
+static bool
+parse_sudoers(struct sudoers_context *ctx, const char *input_file,
+ struct cvtsudoers_config *conf)
+{
+ debug_decl(parse_sudoers, SUDOERS_DEBUG_UTIL);
+
+ /* Open sudoers file and parse it. */
+ if (strcmp(input_file, "-") == 0) {
+ sudoersin = stdin;
+ input_file = "stdin";
+ } else if ((sudoersin = fopen(input_file, "r")) == NULL)
+ sudo_fatal(U_("unable to open %s"), input_file);
+ init_parser(ctx, input_file);
+ if (sudoersparse() && !parse_error) {
+ sudo_warnx(U_("failed to parse %s file, unknown error"), input_file);
+ parse_error = true;
+ }
+ debug_return_bool(!parse_error);
+}
+
+FILE *
+open_sudoers(const char *file, char **outfile, bool doedit, bool *keepopen)
+{
+ return fopen(file, "r");
+}
+
+static bool
+userlist_matches_filter(struct sudoers_parse_tree *parse_tree,
+ struct member_list *users, struct cvtsudoers_config *conf)
+{
+ struct sudoers_string *s;
+ struct member *m, *next;
+ bool ret = false;
+ debug_decl(userlist_matches_filter, SUDOERS_DEBUG_UTIL);
+
+ if (filters == NULL ||
+ (STAILQ_EMPTY(&filters->users) && STAILQ_EMPTY(&filters->groups)))
+ debug_return_bool(true);
+
+ TAILQ_FOREACH_REVERSE_SAFE(m, users, member_list, entries, next) {
+ bool matched = false;
+
+ if (STAILQ_EMPTY(&filters->users)) {
+ struct passwd pw;
+
+ /*
+ * Only groups in filter, make a fake user so userlist_matches()
+ * can do its thing.
+ */
+ memset(&pw, 0, sizeof(pw));
+ pw.pw_name = (char *)"_nobody";
+ pw.pw_uid = (uid_t)-1;
+ pw.pw_gid = (gid_t)-1;
+
+ if (user_matches(parse_tree, &pw, m) == ALLOW)
+ matched = true;
+ } else {
+ STAILQ_FOREACH(s, &filters->users, entries) {
+ struct passwd *pw = NULL;
+
+ /* An upper case filter entry may be a User_Alias */
+ /* XXX - doesn't handle nested aliases */
+ if (m->type == ALIAS && !conf->expand_aliases) {
+ if (strcmp(m->name, s->str) == 0) {
+ matched = true;
+ break;
+ }
+ }
+
+ if (s->str[0] == '#') {
+ const char *errstr;
+ uid_t uid = sudo_strtoid(s->str + 1, &errstr);
+ if (errstr == NULL)
+ pw = sudo_getpwuid(uid);
+ }
+ if (pw == NULL)
+ pw = sudo_getpwnam(s->str);
+ if (pw == NULL)
+ continue;
+
+ if (user_matches(parse_tree, pw, m) == ALLOW)
+ matched = true;
+ sudo_pw_delref(pw);
+
+ /* Only need one user in the filter to match. */
+ if (matched)
+ break;
+ }
+ }
+
+ if (matched) {
+ ret = true;
+ } else if (conf->prune_matches) {
+ TAILQ_REMOVE(users, m, entries);
+ free_member(m);
+ }
+ }
+
+ debug_return_bool(ret);
+}
+
+static bool
+hostlist_matches_filter(struct sudoers_parse_tree *parse_tree,
+ struct member_list *hostlist, struct cvtsudoers_config *conf)
+{
+ struct sudoers_string *s;
+ struct member *m, *next;
+ char *lhost, *shost;
+ bool ret = false;
+ char **shosts;
+ size_t n = 0;
+ debug_decl(hostlist_matches_filter, SUDOERS_DEBUG_UTIL);
+
+ if (filters == NULL || STAILQ_EMPTY(&filters->hosts))
+ debug_return_bool(true);
+
+ /* Create an array of short host names. */
+ STAILQ_FOREACH(s, &filters->hosts, entries) {
+ n++;
+ }
+ shosts = reallocarray(NULL, n, sizeof(char *));
+ if (shosts == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ n = 0;
+ STAILQ_FOREACH(s, &filters->hosts, entries) {
+ lhost = s->str;
+ if ((shost = strchr(lhost, '.')) != NULL) {
+ shost = strndup(lhost, (size_t)(shost - lhost));
+ if (shost == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ } else {
+ shost = lhost;
+ }
+ shosts[n++] = shost;
+ }
+
+ TAILQ_FOREACH_REVERSE_SAFE(m, hostlist, member_list, entries, next) {
+ bool matched = false;
+ n = 0;
+ STAILQ_FOREACH(s, &filters->hosts, entries) {
+ lhost = s->str;
+ shost = shosts[n++];
+
+ /* An upper case filter entry may be a Host_Alias */
+ /* XXX - doesn't handle nested aliases */
+ if (m->type == ALIAS && !conf->expand_aliases) {
+ if (strcmp(m->name, s->str) == 0) {
+ matched = true;
+ break;
+ }
+ }
+
+ /* Only need one host in the filter to match. */
+ /* XXX - can't use netgroup_tuple with NULL pw */
+ if (host_matches(parse_tree, NULL, lhost, shost, m) == ALLOW) {
+ matched = true;
+ break;
+ }
+ }
+
+ if (matched) {
+ ret = true;
+ } else if (conf->prune_matches) {
+ TAILQ_REMOVE(hostlist, m, entries);
+ free_member(m);
+ }
+ }
+
+ /* Free shosts array and its contents. */
+ n = 0;
+ STAILQ_FOREACH(s, &filters->hosts, entries) {
+ lhost = s->str;
+ shost = shosts[n++];
+ if (shost != lhost)
+ free(shost);
+ }
+ free(shosts);
+
+ debug_return_bool(ret);
+}
+
+static bool
+cmnd_matches_filter(struct sudoers_parse_tree *parse_tree,
+ struct member *m, struct cvtsudoers_config *conf)
+{
+ struct sudoers_context *ctx = parse_tree->ctx;
+ struct sudoers_string *s;
+ bool matched = false;
+ debug_decl(cmnd_matches_filter, SUDOERS_DEBUG_UTIL);
+
+ /* TODO: match on runasuserlist/runasgrouplist, notbefore/notafter etc */
+ STAILQ_FOREACH(s, &filters->cmnds, entries) {
+ /* An upper case filter entry may be a Cmnd_Alias */
+ /* XXX - doesn't handle nested aliases */
+ if (m->type == ALIAS && !conf->expand_aliases) {
+ if (strcmp(m->name, s->str) == 0) {
+ matched = true;
+ break;
+ }
+ }
+
+ /* Only need one command in the filter to match. */
+ ctx->user.cmnd = s->str;
+ ctx->user.cmnd_base = sudo_basename(ctx->user.cmnd);
+ if (cmnd_matches(parse_tree, m, NULL, NULL) == ALLOW) {
+ matched = true;
+ break;
+ }
+ }
+ ctx->user.cmnd_base = NULL;
+ ctx->user.cmnd = NULL;
+
+ debug_return_bool(matched);
+}
+
+static bool
+cmndlist_matches_filter(struct sudoers_parse_tree *parse_tree,
+ struct member_list *cmndlist, struct cvtsudoers_config *conf)
+{
+ struct member *m, *next;
+ bool ret = false;
+ debug_decl(cmndlist_matches_filter, SUDOERS_DEBUG_UTIL);
+
+ if (filters == NULL || STAILQ_EMPTY(&filters->cmnds))
+ debug_return_bool(true);
+
+ TAILQ_FOREACH_REVERSE_SAFE(m, cmndlist, member_list, entries, next) {
+ bool matched = cmnd_matches_filter(parse_tree, m, conf);
+ if (matched) {
+ ret = true;
+ } else if (conf->prune_matches) {
+ TAILQ_REMOVE(cmndlist, m, entries);
+ free_member(m);
+ }
+ }
+
+ debug_return_bool(ret);
+}
+
+static bool
+cmndspeclist_matches_filter(struct sudoers_parse_tree *parse_tree,
+ struct cmndspec_list *cmndspecs, struct cvtsudoers_config *conf)
+{
+ struct cmndspec *cs, *next;
+ bool ret = false;
+ debug_decl(cmndspeclist_matches_filter, SUDOERS_DEBUG_UTIL);
+
+ if (filters == NULL || STAILQ_EMPTY(&filters->cmnds))
+ debug_return_bool(true);
+
+ TAILQ_FOREACH_REVERSE_SAFE(cs, cmndspecs, cmndspec_list, entries, next) {
+ bool matched = cmnd_matches_filter(parse_tree, cs->cmnd, conf);
+ if (matched) {
+ ret = true;
+ } else if (conf->prune_matches) {
+ /* free_cmndspec() removes cs from the list itself. */
+ free_cmndspec(cs, cmndspecs);
+ }
+ }
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Display Defaults entries
+ */
+static bool
+print_defaults_sudoers(struct sudoers_parse_tree *parse_tree,
+ struct sudo_lbuf *lbuf, bool expand_aliases)
+{
+ struct defaults *def, *next;
+ debug_decl(print_defaults_sudoers, SUDOERS_DEBUG_UTIL);
+
+ TAILQ_FOREACH_SAFE(def, &parse_tree->defaults, entries, next) {
+ sudoers_format_default_line(lbuf, parse_tree, def, &next,
+ expand_aliases);
+ }
+
+ debug_return_bool(!sudo_lbuf_error(lbuf));
+}
+
+static int
+print_alias_sudoers(struct sudoers_parse_tree *parse_tree, struct alias *a,
+ void *v)
+{
+ struct sudo_lbuf *lbuf = v;
+ struct member *m;
+ debug_decl(print_alias_sudoers, SUDOERS_DEBUG_UTIL);
+
+ sudo_lbuf_append(lbuf, "%s %s = ", alias_type_to_string(a->type),
+ a->name);
+ TAILQ_FOREACH(m, &a->members, entries) {
+ if (m != TAILQ_FIRST(&a->members))
+ sudo_lbuf_append(lbuf, ", ");
+ sudoers_format_member(lbuf, parse_tree, m, NULL, UNSPEC);
+ }
+ sudo_lbuf_append(lbuf, "\n");
+
+ debug_return_int(sudo_lbuf_error(lbuf) ? -1 : 0);
+}
+
+/*
+ * Display aliases
+ */
+static bool
+print_aliases_sudoers(struct sudoers_parse_tree *parse_tree,
+ struct sudo_lbuf *lbuf)
+{
+ debug_decl(print_aliases_sudoers, SUDOERS_DEBUG_UTIL);
+
+ alias_apply(parse_tree, print_alias_sudoers, lbuf);
+
+ debug_return_bool(!sudo_lbuf_error(lbuf));
+}
+
+static FILE *output_fp; /* global for convert_sudoers_output */
+
+static int
+convert_sudoers_output(const char * restrict buf)
+{
+ return fputs(buf, output_fp);
+}
+
+/*
+ * Apply filters to userspecs, removing non-matching entries.
+ */
+static void
+filter_userspecs(struct sudoers_parse_tree *parse_tree,
+ struct cvtsudoers_config *conf)
+{
+ struct userspec *us, *next_us;
+ struct privilege *priv, *next_priv;
+ debug_decl(filter_userspecs, SUDOERS_DEBUG_UTIL);
+
+ if (filters == NULL)
+ debug_return;
+
+ /*
+ * Does not currently prune out non-matching entries in the user or
+ * host lists. It acts more like a grep than a true filter.
+ * In the future, we may want to add a prune option.
+ */
+ TAILQ_FOREACH_SAFE(us, &parse_tree->userspecs, entries, next_us) {
+ if (!userlist_matches_filter(parse_tree, &us->users, conf)) {
+ TAILQ_REMOVE(&parse_tree->userspecs, us, entries);
+ free_userspec(us);
+ continue;
+ }
+ TAILQ_FOREACH_SAFE(priv, &us->privileges, entries, next_priv) {
+ if (!hostlist_matches_filter(parse_tree, &priv->hostlist, conf) ||
+ !cmndspeclist_matches_filter(parse_tree, &priv->cmndlist, conf)) {
+ TAILQ_REMOVE(&us->privileges, priv, entries);
+ free_privilege(priv);
+ }
+ }
+ if (TAILQ_EMPTY(&us->privileges)) {
+ TAILQ_REMOVE(&parse_tree->userspecs, us, entries);
+ free_userspec(us);
+ continue;
+ }
+ }
+ debug_return;
+}
+
+/*
+ * Check whether the alias described by "alias_name" is the same
+ * as "name" or includes an alias called "name".
+ * Returns true if matched, else false.
+ */
+static bool
+alias_matches(struct sudoers_parse_tree *parse_tree, const char *name,
+ const char *alias_name, short alias_type)
+{
+ struct alias *a;
+ struct member *m;
+ bool ret = false;
+ debug_decl(alias_matches, SUDOERS_DEBUG_ALIAS);
+
+ if (strcmp(name, alias_name) == 0)
+ debug_return_bool(true);
+
+ a = alias_get(parse_tree, alias_name, alias_type);
+ if (a != NULL) {
+ TAILQ_FOREACH(m, &a->members, entries) {
+ if (m->type != ALIAS)
+ continue;
+ if (alias_matches(parse_tree, name, m->name, alias_type)) {
+ ret = true;
+ break;
+ }
+ }
+ alias_put(a);
+ }
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Check whether userspecs uses the aliases in the specified member lists.
+ * If used, they are removed (and freed) from the list.
+ * This does *not* check Defaults for used aliases, only userspecs.
+ */
+static void
+alias_used_by_userspecs(struct sudoers_parse_tree *parse_tree,
+ struct member_list *user_aliases, struct member_list *runas_aliases,
+ struct member_list *host_aliases, struct member_list *cmnd_aliases)
+{
+ struct privilege *priv, *priv_next;
+ struct userspec *us, *us_next;
+ struct cmndspec *cs, *cs_next;
+ struct member *m, *m_next;
+ struct member *am, *am_next;
+ debug_decl(alias_used_by_userspecs, SUDOERS_DEBUG_ALIAS);
+
+ /* Iterate over the policy, checking for aliases. */
+ TAILQ_FOREACH_SAFE(us, &parse_tree->userspecs, entries, us_next) {
+ TAILQ_FOREACH_SAFE(m, &us->users, entries, m_next) {
+ if (m->type == ALIAS) {
+ /* If alias is used, remove from user_aliases and free. */
+ TAILQ_FOREACH_SAFE(am, user_aliases, entries, am_next) {
+ if (alias_matches(parse_tree, am->name, m->name, USERALIAS)) {
+ TAILQ_REMOVE(user_aliases, am, entries);
+ free_member(am);
+ }
+ }
+ }
+ }
+ TAILQ_FOREACH_SAFE(priv, &us->privileges, entries, priv_next) {
+ TAILQ_FOREACH(m, &priv->hostlist, entries) {
+ if (m->type == ALIAS) {
+ /* If alias is used, remove from host_aliases and free. */
+ TAILQ_FOREACH_SAFE(am, host_aliases, entries, am_next) {
+ if (alias_matches(parse_tree, am->name, m->name, HOSTALIAS)) {
+ TAILQ_REMOVE(host_aliases, am, entries);
+ free_member(am);
+ }
+ }
+ }
+ }
+ TAILQ_FOREACH_SAFE(cs, &priv->cmndlist, entries, cs_next) {
+ if (cs->runasuserlist != NULL) {
+ TAILQ_FOREACH_SAFE(m, cs->runasuserlist, entries, m_next) {
+ if (m->type == ALIAS) {
+ /* If alias is used, remove from runas_aliases and free. */
+ TAILQ_FOREACH_SAFE(am, runas_aliases, entries, am_next) {
+ if (alias_matches(parse_tree, am->name, m->name, RUNASALIAS)) {
+ TAILQ_REMOVE(runas_aliases, am, entries);
+ free_member(am);
+ }
+ }
+ }
+ }
+ }
+ if (cs->runasgrouplist != NULL) {
+ TAILQ_FOREACH_SAFE(m, cs->runasgrouplist, entries, m_next) {
+ if (m->type == ALIAS) {
+ /* If alias is used, remove from runas_aliases and free. */
+ TAILQ_FOREACH_SAFE(am, runas_aliases, entries, am_next) {
+ if (alias_matches(parse_tree, am->name, m->name, RUNASALIAS)) {
+ TAILQ_REMOVE(runas_aliases, am, entries);
+ free_member(am);
+ }
+ }
+ }
+ }
+ }
+ if ((m = cs->cmnd)->type == ALIAS) {
+ /* If alias is used, remove from cmnd_aliases and free. */
+ TAILQ_FOREACH_SAFE(am, cmnd_aliases, entries, am_next) {
+ if (alias_matches(parse_tree, am->name, m->name, CMNDALIAS)) {
+ TAILQ_REMOVE(cmnd_aliases, am, entries);
+ free_member(am);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ debug_return;
+}
+
+/*
+ * For each alias listed in members, remove and free the alias.
+ * Frees the contents of members too.
+ */
+static void
+free_aliases_by_members(struct sudoers_parse_tree *parse_tree,
+ struct member_list *members, short type)
+{
+ struct member *m;
+ struct alias *a;
+ debug_decl(free_aliases_by_members, SUDOERS_DEBUG_ALIAS);
+
+ while ((m = TAILQ_FIRST(members)) != NULL) {
+ TAILQ_REMOVE(members, m, entries);
+ a = alias_remove(parse_tree, m->name, type);
+ alias_free(a);
+ free_member(m);
+ }
+ debug_return;
+}
+
+/*
+ * Apply filters to host/user-based Defaults, removing non-matching entries.
+ */
+static void
+filter_defaults(struct sudoers_parse_tree *parse_tree,
+ struct cvtsudoers_config *conf)
+{
+ struct member_list user_aliases = TAILQ_HEAD_INITIALIZER(user_aliases);
+ struct member_list runas_aliases = TAILQ_HEAD_INITIALIZER(runas_aliases);
+ struct member_list host_aliases = TAILQ_HEAD_INITIALIZER(host_aliases);
+ struct member_list cmnd_aliases = TAILQ_HEAD_INITIALIZER(cmnd_aliases);
+ struct defaults *def, *def_next;
+ struct member *m, *m_next;
+ short alias_type;
+ debug_decl(filter_defaults, SUDOERS_DEBUG_DEFAULTS);
+
+ if (filters == NULL && conf->defaults == CVT_DEFAULTS_ALL)
+ debug_return;
+
+ TAILQ_FOREACH_SAFE(def, &parse_tree->defaults, entries, def_next) {
+ bool keep = true;
+
+ switch (def->type) {
+ case DEFAULTS:
+ if (!ISSET(conf->defaults, CVT_DEFAULTS_GLOBAL))
+ keep = false;
+ alias_type = UNSPEC;
+ break;
+ case DEFAULTS_USER:
+ if (!ISSET(conf->defaults, CVT_DEFAULTS_USER) ||
+ !userlist_matches_filter(parse_tree, &def->binding->members,
+ conf)) {
+ keep = false;
+ }
+ alias_type = USERALIAS;
+ break;
+ case DEFAULTS_RUNAS:
+ if (!ISSET(conf->defaults, CVT_DEFAULTS_RUNAS))
+ keep = false;
+ alias_type = RUNASALIAS;
+ break;
+ case DEFAULTS_HOST:
+ if (!ISSET(conf->defaults, CVT_DEFAULTS_HOST) ||
+ !hostlist_matches_filter(parse_tree, &def->binding->members,
+ conf)) {
+ keep = false;
+ }
+ alias_type = HOSTALIAS;
+ break;
+ case DEFAULTS_CMND:
+ if (!ISSET(conf->defaults, CVT_DEFAULTS_CMND) ||
+ !cmndlist_matches_filter(parse_tree, &def->binding->members,
+ conf)) {
+ keep = false;
+ }
+ alias_type = CMNDALIAS;
+ break;
+ default:
+ sudo_fatalx_nodebug("unexpected defaults type %d", def->type);
+ break;
+ }
+
+ if (!keep) {
+ /*
+ * Look for aliases used by the binding.
+ * Consecutive Defaults can share the same binding.
+ */
+ /* XXX - move to function */
+ if (alias_type != UNSPEC &&
+ (def_next == NULL || def->binding != def_next->binding)) {
+ TAILQ_FOREACH_SAFE(m, &def->binding->members, entries, m_next) {
+ if (m->type == ALIAS) {
+ TAILQ_REMOVE(&def->binding->members, m, entries);
+ switch (alias_type) {
+ case USERALIAS:
+ TAILQ_INSERT_TAIL(&user_aliases, m, entries);
+ break;
+ case RUNASALIAS:
+ TAILQ_INSERT_TAIL(&runas_aliases, m, entries);
+ break;
+ case HOSTALIAS:
+ TAILQ_INSERT_TAIL(&host_aliases, m, entries);
+ break;
+ case CMNDALIAS:
+ TAILQ_INSERT_TAIL(&cmnd_aliases, m, entries);
+ break;
+ default:
+ sudo_fatalx_nodebug("unexpected alias type %d",
+ alias_type);
+ break;
+ }
+ }
+ }
+ }
+ TAILQ_REMOVE(&parse_tree->defaults, def, entries);
+ free_default(def);
+ }
+ }
+
+ /* Determine unreferenced aliases and remove/free them. */
+ alias_used_by_userspecs(parse_tree, &user_aliases, &runas_aliases,
+ &host_aliases, &cmnd_aliases);
+ free_aliases_by_members(parse_tree, &user_aliases, USERALIAS);
+ free_aliases_by_members(parse_tree, &runas_aliases, RUNASALIAS);
+ free_aliases_by_members(parse_tree, &host_aliases, HOSTALIAS);
+ free_aliases_by_members(parse_tree, &cmnd_aliases, CMNDALIAS);
+
+ debug_return;
+}
+
+/*
+ * Remove unreferenced aliases.
+ */
+static void
+alias_remove_unused(struct sudoers_parse_tree *parse_tree)
+{
+ struct rbtree *used_aliases;
+ debug_decl(alias_remove_unused, SUDOERS_DEBUG_ALIAS);
+
+ used_aliases = alloc_aliases();
+ if (used_aliases == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ /* Move all referenced aliases to used_aliases. */
+ if (!alias_find_used(parse_tree, used_aliases))
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ /* Only unreferenced aliases are left, swap and free the unused ones. */
+ free_aliases(parse_tree->aliases);
+ parse_tree->aliases = used_aliases;
+
+ debug_return;
+}
+
+/*
+ * Prune out non-matching entries from user and host aliases.
+ */
+static int
+alias_prune_helper(struct sudoers_parse_tree *parse_tree, struct alias *a,
+ void *v)
+{
+ struct cvtsudoers_config *conf = v;
+
+ /* XXX - misuse of these functions */
+ switch (a->type) {
+ case USERALIAS:
+ userlist_matches_filter(parse_tree, &a->members, conf);
+ break;
+ case HOSTALIAS:
+ hostlist_matches_filter(parse_tree, &a->members, conf);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Prune out non-matching entries from within aliases.
+ */
+static void
+alias_prune(struct sudoers_parse_tree *parse_tree,
+ struct cvtsudoers_config *conf)
+{
+ debug_decl(alias_prune, SUDOERS_DEBUG_ALIAS);
+
+ alias_apply(parse_tree, alias_prune_helper, conf);
+
+ debug_return;
+}
+
+/*
+ * Convert back to sudoers.
+ */
+static bool
+convert_sudoers_sudoers(struct sudoers_parse_tree *parse_tree,
+ const char *output_file, struct cvtsudoers_config *conf)
+{
+ bool ret = true;
+ struct sudo_lbuf lbuf;
+ debug_decl(convert_sudoers_sudoers, SUDOERS_DEBUG_UTIL);
+
+ if (strcmp(output_file, "-") == 0) {
+ output_fp = stdout;
+ } else {
+ if ((output_fp = fopen(output_file, "w")) == NULL)
+ sudo_fatal(U_("unable to open %s"), output_file);
+ }
+
+ /* Wrap lines at 80 columns with a 4 character indent. */
+ sudo_lbuf_init(&lbuf, convert_sudoers_output, 4, "\\", 80);
+
+ /* Print Defaults */
+ if (!ISSET(conf->suppress, SUPPRESS_DEFAULTS)) {
+ if (!print_defaults_sudoers(parse_tree, &lbuf, conf->expand_aliases))
+ goto done;
+ if (lbuf.len > 0) {
+ sudo_lbuf_print(&lbuf);
+ sudo_lbuf_append(&lbuf, "\n");
+ }
+ }
+
+ /* Print Aliases */
+ if (!conf->expand_aliases && !ISSET(conf->suppress, SUPPRESS_ALIASES)) {
+ if (!print_aliases_sudoers(parse_tree, &lbuf))
+ goto done;
+ if (lbuf.len > 1) {
+ sudo_lbuf_print(&lbuf);
+ sudo_lbuf_append(&lbuf, "\n");
+ }
+ }
+
+ /* Print User_Specs, separated by blank lines. */
+ if (!ISSET(conf->suppress, SUPPRESS_PRIVS)) {
+ if (!sudoers_format_userspecs(&lbuf, parse_tree, "\n",
+ conf->expand_aliases, true)) {
+ goto done;
+ }
+ if (lbuf.len > 1) {
+ sudo_lbuf_print(&lbuf);
+ }
+ }
+
+done:
+ if (sudo_lbuf_error(&lbuf)) {
+ if (errno == ENOMEM)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ ret = false;
+ }
+ sudo_lbuf_destroy(&lbuf);
+
+ (void)fflush(output_fp);
+ if (ferror(output_fp)) {
+ sudo_warn(U_("unable to write to %s"), output_file);
+ ret = false;
+ }
+ if (output_fp != stdout)
+ fclose(output_fp);
+
+ debug_return_bool(ret);
+}
+
+static void
+display_usage(FILE *fp)
+{
+ (void) fprintf(fp, "usage: %s [-ehMpV] [-b dn] "
+ "[-c conf_file ] [-d deftypes] [-f output_format] [-i input_format] "
+ "[-I increment] [-m filter] [-o output_file] [-O start_point] "
+ "[-P padding] [-s sections] [input_file]\n", getprogname());
+}
+
+sudo_noreturn static void
+usage(void)
+{
+ display_usage(stderr);
+ exit(EXIT_FAILURE);
+}
+
+sudo_noreturn static void
+help(void)
+{
+ (void) printf(_("%s - convert between sudoers file formats\n\n"), getprogname());
+ display_usage(stdout);
+ (void) puts(_("\nOptions:\n"
+ " -b, --base=dn the base DN for sudo LDAP queries\n"
+ " -c, --config=conf_file the path to the configuration file\n"
+ " -d, --defaults=deftypes only convert Defaults of the specified types\n"
+ " -e, --expand-aliases expand aliases when converting\n"
+ " -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+ " -i, --input-format=format set input format: LDIF or sudoers\n"
+ " -I, --increment=num amount to increase each sudoOrder by\n"
+ " -h, --help display help message and exit\n"
+ " -m, --match=filter only convert entries that match the filter\n"
+ " -M, --match-local match filter uses passwd and group databases\n"
+ " -o, --output=output_file write converted sudoers to output_file\n"
+ " -O, --order-start=num starting point for first sudoOrder\n"
+ " -p, --prune-matches prune non-matching users, groups and hosts\n"
+ " -P, --padding=num base padding for sudoOrder increment\n"
+ " -s, --suppress=sections suppress output of certain sections\n"
+ " -V, --version display version information and exit"));
+ exit(EXIT_SUCCESS);
+}
diff --git a/plugins/sudoers/cvtsudoers.h b/plugins/sudoers/cvtsudoers.h
new file mode 100644
index 0000000..09d0e9b
--- /dev/null
+++ b/plugins/sudoers/cvtsudoers.h
@@ -0,0 +1,110 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2018, 2021-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_CVTSUDOERS_H
+#define SUDOERS_CVTSUDOERS_H
+
+#include <strlist.h>
+
+/* Supported input/output formats. */
+enum sudoers_formats {
+ format_csv,
+ format_json,
+ format_ldif,
+ format_sudoers
+};
+
+/* Flags for cvtsudoers_config.defaults */
+#define CVT_DEFAULTS_GLOBAL 0x01U
+#define CVT_DEFAULTS_USER 0x02U
+#define CVT_DEFAULTS_RUNAS 0x04U
+#define CVT_DEFAULTS_HOST 0x08U
+#define CVT_DEFAULTS_CMND 0x10U
+#define CVT_DEFAULTS_ALL 0xffU
+
+/* Flags for cvtsudoers_config.suppress */
+#define SUPPRESS_DEFAULTS 0x01U
+#define SUPPRESS_ALIASES 0x02U
+#define SUPPRESS_PRIVS 0x04U
+
+/* cvtsudoers.conf settings */
+struct cvtsudoers_config {
+ unsigned int sudo_order;
+ unsigned int order_increment;
+ unsigned int order_padding;
+ unsigned int order_max;
+ unsigned int defaults;
+ unsigned int suppress;
+ bool store_options;
+ bool expand_aliases;
+ bool prune_matches;
+ bool match_local;
+ char *sudoers_base;
+ char *input_format;
+ char *output_format;
+ char *filter;
+ char *logfile;
+ char *defstr;
+ char *supstr;
+ char *group_file;
+ char *passwd_file;
+};
+
+/* Initial config settings for above. */
+#define INITIAL_CONFIG { 1, 1, 0, 0, CVT_DEFAULTS_ALL, 0, true }
+
+#define CONF_BOOL 0
+#define CONF_UINT 1
+#define CONF_STR 2
+
+struct cvtsudoers_conf_table {
+ const char *conf_str; /* config file string */
+ int type; /* CONF_BOOL, CONF_UINT, CONF_STR */
+ void *valp; /* pointer into cvtsudoers_config */
+};
+
+struct cvtsudoers_filter {
+ struct sudoers_str_list users;
+ struct sudoers_str_list groups;
+ struct sudoers_str_list hosts;
+ struct sudoers_str_list cmnds;
+};
+
+/* cvtsudoers.c */
+extern struct cvtsudoers_filter *filters;
+void log_warnx(const char * restrict fmt, ...) sudo_printflike(1, 2);
+
+/* cvtsudoers_csv.c */
+bool convert_sudoers_csv(const struct sudoers_parse_tree *parse_tree, const char *output_file, struct cvtsudoers_config *conf);
+
+/* cvtsudoers_json.c */
+bool convert_sudoers_json(const struct sudoers_parse_tree *parse_tree, const char *output_file, struct cvtsudoers_config *conf);
+
+/* cvtsudoers_ldif.c */
+bool convert_sudoers_ldif(const struct sudoers_parse_tree *parse_tree, const char *output_file, struct cvtsudoers_config *conf);
+
+/* cvtsudoers_merge.c */
+struct sudoers_parse_tree *merge_sudoers(struct sudoers_parse_tree_list *parse_trees, struct sudoers_parse_tree *merged_tree);
+
+/* cvtsudoers_pwutil.c */
+struct cache_item *cvtsudoers_make_pwitem(uid_t uid, const char *name);
+struct cache_item *cvtsudoers_make_gritem(gid_t gid, const char *name);
+struct cache_item *cvtsudoers_make_gidlist_item(const struct passwd *pw, int unusued1, GETGROUPS_T *unused2, char * const *unused3, unsigned int type);
+struct cache_item *cvtsudoers_make_grlist_item(const struct passwd *pw, char * const *unused1);
+
+#endif /* SUDOERS_CVTSUDOERS_H */
diff --git a/plugins/sudoers/cvtsudoers_csv.c b/plugins/sudoers/cvtsudoers_csv.c
new file mode 100644
index 0000000..d5cb6a5
--- /dev/null
+++ b/plugins/sudoers/cvtsudoers_csv.c
@@ -0,0 +1,720 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <unistd.h>
+#include <stdarg.h>
+
+#include <sudoers.h>
+#include <cvtsudoers.h>
+#include <gram.h>
+
+static void print_member_list_csv(FILE *fp, const struct sudoers_parse_tree *parse_tree, struct member_list *members, bool negated, short alias_type, bool expand_aliases);
+
+/*
+ * Print sudoOptions from a defaults_list.
+ */
+static bool
+print_options_csv(FILE *fp, struct defaults_list *options, bool need_comma)
+{
+ struct defaults *opt;
+ debug_decl(print_options_csv, SUDOERS_DEBUG_UTIL);
+
+ TAILQ_FOREACH(opt, options, entries) {
+ if (opt->val != NULL) {
+ /* There is no need to double quote values here. */
+ fprintf(fp, "%s%s%s%s", need_comma ? "," : "", opt->var,
+ opt->op == '+' ? "+=" : opt->op == '-' ? "-=" : "=", opt->val);
+ } else {
+ /* Boolean flag. */
+ fprintf(fp, "%s%s%s%s", need_comma ? "," : "", opt->var,
+ opt->op == false ? "!" : "", opt->var);
+ }
+ need_comma = true;
+ }
+
+ debug_return_bool(!ferror(fp));
+}
+
+/*
+ * Map a Defaults type to string.
+ */
+static const char *
+defaults_type_to_string(int defaults_type)
+{
+ switch (defaults_type) {
+ case DEFAULTS:
+ return "defaults";
+ case DEFAULTS_CMND:
+ return "defaults_command";
+ case DEFAULTS_HOST:
+ return "defaults_host";
+ case DEFAULTS_RUNAS:
+ return "defaults_runas";
+ case DEFAULTS_USER:
+ return "defaults_user";
+ default:
+ sudo_fatalx_nodebug("unexpected defaults type %d", defaults_type);
+ }
+}
+
+/*
+ * Map a Defaults type to an alias type.
+ */
+static short
+defaults_to_alias_type(int defaults_type)
+{
+ switch (defaults_type) {
+ case DEFAULTS_CMND:
+ return CMNDALIAS;
+ case DEFAULTS_HOST:
+ return HOSTALIAS;
+ case DEFAULTS_RUNAS:
+ return RUNASALIAS;
+ case DEFAULTS_USER:
+ return USERALIAS;
+ default:
+ sudo_fatalx_nodebug("unexpected defaults type %d", defaults_type);
+ }
+}
+
+/*
+ * Print a string, performing quoting as needed.
+ * If a field includes a comma it must be double-quoted.
+ * Double quotes are replaced by a pair of double-quotes.
+ * XXX - rewrite this
+ */
+static bool
+print_csv_string(FILE * restrict fp, const char * restrict str, bool quoted)
+{
+ const char *src = str;
+ char *dst, *newstr;
+ size_t len, newsize;
+ bool quote_it = false;
+ bool ret = true;
+ debug_decl(print_csv_string, SUDOERS_DEBUG_UTIL);
+
+ len = strcspn(str, quoted ? "\"" : "\",");
+ if (str[len] == '\0') {
+ /* nothing to escape */
+ debug_return_bool(fputs(str, fp) != EOF);
+ }
+
+ if (!quoted && strchr(str + len, ',') != NULL)
+ quote_it = true;
+
+ /* String includes characters we need to escape. */
+ newsize = len + 2 + (strlen(len + str) * 2) + 1;
+ if ((newstr = malloc(newsize)) == NULL)
+ debug_return_bool(false);
+ dst = newstr;
+
+ if (quote_it)
+ *dst++ = '"';
+ while (*src != '\0') {
+ if (*src == '"')
+ *dst++ = '"';
+ *dst++ = *src++;
+ }
+ if (quote_it)
+ *dst++ = '"';
+ *dst = '\0';
+
+ if (fputs(newstr, fp) == EOF)
+ ret = false;
+ free(newstr);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Format a sudo_command as a string.
+ * Returns the formatted, dynamically allocated string or dies on error.
+ */
+static char *
+format_cmnd(struct sudo_command *c, bool negated)
+{
+ struct command_digest *digest;
+ char *buf, *cp, *cmnd;
+ size_t bufsiz;
+ int len;
+ debug_decl(format_cmnd, SUDOERS_DEBUG_UTIL);
+
+ cmnd = c->cmnd ? c->cmnd : (char *)"ALL";
+ bufsiz = negated + strlen(cmnd) + 1;
+ if (c->args != NULL)
+ bufsiz += 1 + strlen(c->args);
+ TAILQ_FOREACH(digest, &c->digests, entries) {
+ bufsiz += strlen(digest_type_to_name(digest->digest_type)) + 1 +
+ strlen(digest->digest_str) + 1;
+ if (TAILQ_NEXT(digest, entries) != NULL)
+ bufsiz += 2;
+ }
+
+ if ((buf = malloc(bufsiz)) == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+
+ cp = buf;
+ TAILQ_FOREACH(digest, &c->digests, entries) {
+ len = snprintf(cp, bufsiz - (size_t)(cp - buf), "%s:%s%s ",
+ digest_type_to_name(digest->digest_type), digest->digest_str,
+ TAILQ_NEXT(digest, entries) ? "," : "");
+ if (len < 0 || len >= (int)bufsiz - (cp - buf))
+ sudo_fatalx(U_("internal error, %s overflow"), __func__);
+ cp += len;
+ }
+
+ len = snprintf(cp, bufsiz - (size_t)(cp - buf), "%s%s%s%s",
+ negated ? "!" : "", cmnd, c->args ? " " : "", c->args ? c->args : "");
+ if (len < 0 || len >= (int)bufsiz - (cp - buf))
+ sudo_fatalx(U_("internal error, %s overflow"), __func__);
+
+ debug_return_str(buf);
+}
+
+/*
+ * Print struct member in CSV format as the specified attribute.
+ * See print_member_int() in parse.c.
+ */
+static void
+print_member_csv(FILE *fp, const struct sudoers_parse_tree *parse_tree,
+ char *name, int type, bool negated, bool quoted, short alias_type,
+ bool expand_aliases)
+{
+ struct alias *a;
+ char *str;
+ int len;
+ debug_decl(print_member_csv, SUDOERS_DEBUG_UTIL);
+
+ switch (type) {
+ case MYSELF:
+ /* Only valid for sudoRunasUser */
+ break;
+ case ALL:
+ if (name == NULL) {
+ fputs(negated ? "!ALL" : "ALL", fp);
+ break;
+ }
+ FALLTHROUGH;
+ case COMMAND:
+ str = format_cmnd((struct sudo_command *)name, negated);
+ print_csv_string(fp, str, quoted);
+ free(str);
+ break;
+ case ALIAS:
+ if (expand_aliases) {
+ if ((a = alias_get(parse_tree, name, alias_type)) != NULL) {
+ print_member_list_csv(fp, parse_tree, &a->members, negated,
+ alias_type, expand_aliases);
+ alias_put(a);
+ break;
+ }
+ }
+ FALLTHROUGH;
+ default:
+ len = asprintf(&str, "%s%s", negated ? "!" : "", name);
+ if (len == -1) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ print_csv_string(fp, str, quoted);
+ free(str);
+ break;
+ }
+
+ debug_return;
+}
+
+/*
+ * Print list of struct member in CSV format as the specified attribute.
+ * See print_member_int() in parse.c.
+ */
+static void
+print_member_list_csv(FILE *fp, const struct sudoers_parse_tree *parse_tree,
+ struct member_list *members, bool negated, short alias_type,
+ bool expand_aliases)
+{
+ struct member *m, *next;
+ debug_decl(print_member_list_csv, SUDOERS_DEBUG_UTIL);
+
+ if (TAILQ_EMPTY(members))
+ debug_return;
+
+ if (TAILQ_FIRST(members) != TAILQ_LAST(members, member_list))
+ putc('"', fp);
+ TAILQ_FOREACH_SAFE(m, members, entries, next) {
+ print_member_csv(fp, parse_tree, m->name, m->type,
+ negated ? !m->negated : m->negated, true, alias_type,
+ expand_aliases);
+ if (next != NULL)
+ putc(',', fp);
+ }
+ if (TAILQ_FIRST(members) != TAILQ_LAST(members, member_list))
+ putc('"', fp);
+
+ debug_return;
+}
+
+/*
+ * Print the binding for a Defaults entry of the specified type.
+ */
+static void
+print_defaults_binding_csv(FILE *fp,
+ const struct sudoers_parse_tree *parse_tree,
+ struct defaults_binding *binding, int type, bool expand_aliases)
+{
+ short alias_type;
+ debug_decl(print_defaults_binding_csv, SUDOERS_DEBUG_UTIL);
+
+ if (type != DEFAULTS) {
+ /* Print each member object in binding. */
+ alias_type = defaults_to_alias_type(type);
+ print_member_list_csv(fp, parse_tree, &binding->members, false,
+ alias_type, expand_aliases);
+ }
+
+ debug_return;
+}
+
+/*
+ * Print all Defaults in CSV format:
+ *
+ * defaults,binding,name,operator,value
+ *
+ * where "operator" is one of +=, -=, or =
+ * and boolean flags use true/false for the value.
+ */
+static bool
+print_defaults_csv(FILE *fp, const struct sudoers_parse_tree *parse_tree,
+ bool expand_aliases)
+{
+ struct defaults *def;
+ debug_decl(print_defaults_csv, SUDOERS_DEBUG_UTIL);
+
+ if (TAILQ_EMPTY(&parse_tree->defaults))
+ debug_return_bool(true);
+
+ /* Heading line. */
+ fputs("defaults_type,binding,name,operator,value\n", fp);
+
+ TAILQ_FOREACH(def, &parse_tree->defaults, entries) {
+ const char *operator;
+
+ /* Print operator */
+ switch (def->op) {
+ case '+':
+ operator = "+=";
+ break;
+ case '-':
+ operator = "-=";
+ break;
+ case true:
+ case false:
+ operator = "=";
+ break;
+ default:
+ sudo_warnx("internal error: unexpected defaults op %d", def->op);
+ continue;
+ }
+
+ /*
+ * For CSV we use a separate entry for each Defaults setting,
+ * even if they were on the same line in sudoers.
+ */
+ fprintf(fp, "%s,", defaults_type_to_string(def->type));
+
+ /* Print binding (if any), which could be a list. */
+ print_defaults_binding_csv(fp, parse_tree, def->binding, def->type,
+ expand_aliases);
+
+ /* Print Defaults name + operator. */
+ fprintf(fp, ",%s,%s,", def->var, operator);
+
+ /* Print defaults value. */
+ /* XXX - differentiate between lists and single values? */
+ if (def->val == NULL) {
+ fputs(def->op == true ? "true" : "false", fp);
+ } else {
+ /* Does not handle lists specially. */
+ print_csv_string(fp, def->val, false);
+ }
+ putc('\n', fp);
+ }
+ putc('\n', fp);
+ fflush(fp);
+
+ debug_return_bool(!ferror(fp));
+}
+
+/*
+ * Callback for alias_apply() to print an alias entry.
+ */
+static int
+print_alias_csv(struct sudoers_parse_tree *parse_tree, struct alias *a, void *v)
+{
+ FILE *fp = v;
+ const char *title;
+ debug_decl(print_alias_csv, SUDOERS_DEBUG_UTIL);
+
+ title = alias_type_to_string(a->type);
+ if (title == NULL) {
+ sudo_warnx("unexpected alias type %d", a->type);
+ debug_return_int(0);
+ }
+
+ fprintf(fp, "%s,%s,", title, a->name);
+ print_member_list_csv(fp, parse_tree, &a->members, false, a->type, false);
+ putc('\n', fp);
+ debug_return_int(0);
+}
+
+/*
+ * Print all aliases in CSV format:
+ */
+static bool
+print_aliases_csv(FILE *fp, const struct sudoers_parse_tree *parse_tree)
+{
+ debug_decl(print_aliases_csv, SUDOERS_DEBUG_UTIL);
+
+ if (TAILQ_EMPTY(&parse_tree->defaults))
+ debug_return_bool(true);
+
+ /* Heading line. */
+ fputs("alias_type,alias_name,members\n", fp);
+
+ /* print_alias_csv() does not modify parse_tree. */
+ alias_apply((struct sudoers_parse_tree *)parse_tree, print_alias_csv, fp);
+ putc('\n', fp);
+
+ debug_return_bool(true);
+}
+
+/*
+ * Print a Cmnd_Spec in CSV format.
+ */
+static void
+print_cmndspec_csv(FILE *fp, const struct sudoers_parse_tree *parse_tree,
+ struct cmndspec *cs, struct cmndspec **nextp,
+ struct defaults_list *options, bool expand_aliases)
+{
+ char timebuf[sizeof("20120727121554Z")];
+ struct cmndspec *next = *nextp;
+ bool need_comma = false;
+ struct member *m;
+ struct tm gmt;
+ bool last_one, quoted = false;
+ size_t len;
+ debug_decl(print_cmndspec_csv, SUDOERS_DEBUG_UTIL);
+
+ if (cs->runasuserlist != NULL) {
+ print_member_list_csv(fp, parse_tree, cs->runasuserlist, false,
+ RUNASALIAS, expand_aliases);
+ }
+ putc(',', fp);
+
+ if (cs->runasgrouplist != NULL) {
+ print_member_list_csv(fp, parse_tree, cs->runasgrouplist, false,
+ RUNASALIAS, expand_aliases);
+ }
+ putc(',', fp);
+
+ /* We don't know how many options there will be so always quote it. */
+ putc('"', fp);
+ if (cs->notbefore != UNSPEC) {
+ if (gmtime_r(&cs->notbefore, &gmt) == NULL) {
+ sudo_warn("%s", U_("unable to get GMT time"));
+ } else {
+ timebuf[sizeof(timebuf) - 1] = '\0';
+ len = strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", &gmt);
+ if (len == 0 || timebuf[sizeof(timebuf) - 1] != '\0') {
+ sudo_warnx("%s", U_("unable to format timestamp"));
+ } else {
+ fprintf(fp, "%snotbefore=%s", need_comma ? "," : "", timebuf); // -V547
+ need_comma = true;
+ }
+ }
+ }
+ if (cs->notafter != UNSPEC) {
+ if (gmtime_r(&cs->notafter, &gmt) == NULL) {
+ sudo_warn("%s", U_("unable to get GMT time"));
+ } else {
+ timebuf[sizeof(timebuf) - 1] = '\0';
+ len = strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", &gmt);
+ if (len == 0 || timebuf[sizeof(timebuf) - 1] != '\0') {
+ sudo_warnx("%s", U_("unable to format timestamp"));
+ } else {
+ fprintf(fp, "%snotafter=%s", need_comma ? "," : "", timebuf);
+ need_comma = true;
+ }
+ }
+ }
+
+ if (cs->timeout > 0) {
+ fprintf(fp, "%scommand_timeout=%d", need_comma ? "," : "", cs->timeout);
+ need_comma = true;
+ }
+
+ /* Print tags as options */
+ if (TAGS_SET(cs->tags)) {
+ struct cmndtag tag = cs->tags;
+
+ if (tag.nopasswd != UNSPEC) {
+ fprintf(fp, "%s%s", need_comma ? "," : "",
+ tag.nopasswd ? "!authenticate" : "authenticate");
+ need_comma = true;
+ }
+ if (tag.noexec != UNSPEC) {
+ fprintf(fp, "%s%s", need_comma ? "," : "",
+ tag.noexec ? "noexec" : "!noexec");
+ need_comma = true;
+ }
+ if (tag.intercept != UNSPEC) {
+ fprintf(fp, "%s%s", need_comma ? "," : "",
+ tag.intercept ? "intercept" : "!intercept");
+ need_comma = true;
+ }
+ if (tag.send_mail != UNSPEC) {
+ if (tag.send_mail) {
+ fprintf(fp, "%smail_all_cmnds", need_comma ? "," : "");
+ } else {
+ fprintf(fp, "%s!mail_all_cmnds,!mail_always,!mail_no_perms",
+ need_comma ? "," : "");
+ }
+ need_comma = true;
+ }
+ if (tag.setenv != UNSPEC && tag.setenv != IMPLIED) {
+ fprintf(fp, "%s%s", need_comma ? "," : "",
+ tag.setenv ? "setenv" : "!setenv");
+ need_comma = true;
+ }
+ if (tag.follow != UNSPEC) {
+ fprintf(fp, "%s%s", need_comma ? "," : "",
+ tag.follow ? "sudoedit_follow" : "!sudoedit_follow");
+ need_comma = true;
+ }
+ if (tag.log_input != UNSPEC) {
+ fprintf(fp, "%s%s", need_comma ? "," : "",
+ tag.follow ? "log_input" : "!log_input");
+ need_comma = true;
+ }
+ if (tag.log_output != UNSPEC) {
+ fprintf(fp, "%s%s", need_comma ? "," : "",
+ tag.follow ? "log_output" : "!log_output");
+ need_comma = true;
+ }
+ }
+ print_options_csv(fp, options, need_comma);
+ if (!TAILQ_EMPTY(options))
+ need_comma = true;
+
+ /* Print runchroot and runcwd. */
+ if (cs->runchroot != NULL) {
+ fprintf(fp, "%srunchroot=%s", need_comma ? "," : "", cs->runchroot);
+ need_comma = true;
+ }
+ if (cs->runcwd != NULL) {
+ fprintf(fp, "%sruncwd=%s", need_comma ? "," : "", cs->runcwd);
+ need_comma = true;
+ }
+
+#ifdef HAVE_SELINUX
+ /* Print SELinux role/type */
+ if (cs->role != NULL && cs->type != NULL) {
+ fprintf(fp, "%srole=%s,type=%s", need_comma ? "," : "",
+ cs->role, cs->type);
+ need_comma = true;
+ }
+#endif /* HAVE_SELINUX */
+
+#ifdef HAVE_APPARMOR
+ if (cs->apparmor_profile != NULL) {
+ fprintf(fp, "%sapparmor_profile=%s,", need_comma ? "," : "",
+ cs->apparmor_profile);
+ need_comma = true;
+ }
+#endif /* HAVE_APPARMOR */
+
+#ifdef HAVE_PRIV_SET
+ /* Print Solaris privs/limitprivs */
+ if (cs->privs != NULL || cs->limitprivs != NULL) {
+ if (cs->privs != NULL) {
+ fprintf(fp, "%sprivs=%s", need_comma ? "," : "", cs->privs);
+ need_comma = true;
+ }
+ if (cs->limitprivs != NULL) {
+ fprintf(fp, "%slimitprivs=%s", need_comma ? "," : "", cs->limitprivs);
+ need_comma = true;
+ }
+ }
+#endif /* HAVE_PRIV_SET */
+#ifdef __clang_analyzer__
+ (void)&need_comma;
+#endif
+ putc('"', fp);
+ putc(',', fp);
+
+ /*
+ * Merge adjacent commands with matching tags, runas, SELinux
+ * role/type, AppArmor profiles and Solaris priv settings.
+ */
+ for (;;) {
+ /* Does the next entry differ only in the command itself? */
+ /* XXX - move into a function that returns bool */
+ /* XXX - TAG_SET does not account for implied SETENV */
+ last_one = next == NULL ||
+ RUNAS_CHANGED(cs, next) || TAGS_CHANGED(cs->tags, next->tags)
+#ifdef HAVE_PRIV_SET
+ || cs->privs != next->privs || cs->limitprivs != next->limitprivs
+#endif /* HAVE_PRIV_SET */
+#ifdef HAVE_SELINUX
+ || cs->role != next->role || cs->type != next->type
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_APPARMOR
+ || cs->apparmor_profile != next->apparmor_profile
+#endif /* HAVE_APPARMOR */
+ || cs->runchroot != next->runchroot || cs->runcwd != next->runcwd;
+
+ if (!quoted && !last_one) {
+ quoted = true;
+ putc('"', fp);
+ }
+ m = cs->cmnd;
+ print_member_csv(fp, parse_tree, m->name, m->type, m->negated, quoted,
+ CMNDALIAS, expand_aliases);
+ if (last_one)
+ break;
+ putc(',', fp);
+ cs = next;
+ next = TAILQ_NEXT(cs, entries);
+ }
+ if (quoted)
+ putc('"', fp);
+
+ *nextp = next;
+
+ debug_return;
+}
+
+/*
+ * Print a single User_Spec.
+ */
+static bool
+print_userspec_csv(FILE *fp, const struct sudoers_parse_tree *parse_tree,
+ struct userspec *us, bool expand_aliases)
+{
+ struct privilege *priv;
+ struct cmndspec *cs, *next;
+ debug_decl(print_userspec_csv, SUDOERS_DEBUG_UTIL);
+
+ /*
+ * Each userspec struct may contain multiple privileges for the user.
+ */
+ TAILQ_FOREACH(priv, &us->privileges, entries) {
+ TAILQ_FOREACH_SAFE(cs, &priv->cmndlist, entries, next) {
+ fputs("rule,", fp);
+ print_member_list_csv(fp, parse_tree, &us->users, false,
+ USERALIAS, expand_aliases);
+ putc(',', fp);
+
+ print_member_list_csv(fp, parse_tree, &priv->hostlist, false,
+ HOSTALIAS, expand_aliases);
+ putc(',', fp);
+
+ print_cmndspec_csv(fp, parse_tree, cs, &next, &priv->defaults,
+ expand_aliases);
+ putc('\n', fp);
+ }
+ }
+
+ debug_return_bool(!ferror(fp));
+}
+
+/*
+ * Print User_Specs.
+ */
+static bool
+print_userspecs_csv(FILE *fp, const struct sudoers_parse_tree *parse_tree,
+ bool expand_aliases)
+{
+ struct userspec *us;
+ debug_decl(print_userspecs_csv, SUDOERS_DEBUG_UTIL);
+
+ if (TAILQ_EMPTY(&parse_tree->userspecs))
+ debug_return_bool(true);
+
+ /* Heading line. */
+ fputs("rule,user,host,runusers,rungroups,options,command\n", fp);
+
+ TAILQ_FOREACH(us, &parse_tree->userspecs, entries) {
+ if (!print_userspec_csv(fp, parse_tree, us, expand_aliases))
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+/*
+ * Export the parsed sudoers file in CSV format.
+ */
+bool
+convert_sudoers_csv(const struct sudoers_parse_tree *parse_tree,
+ const char *output_file, struct cvtsudoers_config *conf)
+{
+ bool ret = true;
+ FILE *output_fp = stdout;
+ debug_decl(convert_sudoers_csv, SUDOERS_DEBUG_UTIL);
+
+ if (output_file != NULL && strcmp(output_file, "-") != 0) {
+ if ((output_fp = fopen(output_file, "w")) == NULL)
+ sudo_fatal(U_("unable to open %s"), output_file);
+ }
+
+ /* Dump Defaults in CSV format. */
+ if (!ISSET(conf->suppress, SUPPRESS_DEFAULTS))
+ print_defaults_csv(output_fp, parse_tree, conf->expand_aliases);
+
+ /* Dump Aliases in CSV format. */
+ if (!conf->expand_aliases && !ISSET(conf->suppress, SUPPRESS_ALIASES)) {
+ print_aliases_csv(output_fp, parse_tree);
+ }
+
+ /* Dump User_Specs in CSV format. */
+ if (!ISSET(conf->suppress, SUPPRESS_PRIVS))
+ print_userspecs_csv(output_fp, parse_tree, conf->expand_aliases);
+
+ (void)fflush(output_fp);
+ if (ferror(output_fp))
+ ret = false;
+ if (output_fp != stdout)
+ fclose(output_fp);
+
+ debug_return_bool(ret);
+}
diff --git a/plugins/sudoers/cvtsudoers_json.c b/plugins/sudoers/cvtsudoers_json.c
new file mode 100644
index 0000000..3ff543d
--- /dev/null
+++ b/plugins/sudoers/cvtsudoers_json.c
@@ -0,0 +1,937 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#include <sudoers.h>
+#include <sudo_json.h>
+#include <cvtsudoers.h>
+#include <gram.h>
+
+/*
+ * Closure used to store state when iterating over all aliases.
+ */
+struct json_alias_closure {
+ struct json_container *jsonc;
+ const char *title;
+ unsigned int count;
+ short alias_type;
+};
+
+/*
+ * Type values used to disambiguate the generic WORD and ALIAS types.
+ */
+enum word_type {
+ TYPE_COMMAND,
+ TYPE_HOSTNAME,
+ TYPE_RUNASGROUP,
+ TYPE_RUNASUSER,
+ TYPE_USERNAME
+};
+
+/*
+ * Print sudo command member in JSON format, with correct indentation.
+ */
+static void
+print_command_json(struct json_container *jsonc, const char *name, bool negated)
+{
+ struct sudo_command *c = (struct sudo_command *)name;
+ struct command_digest *digest;
+ struct json_value value;
+ char *cmnd = c->cmnd;
+ const char *digest_name;
+ debug_decl(print_command_json, SUDOERS_DEBUG_UTIL);
+
+ /* Print command with optional command line args. */
+ if (c->args != NULL) {
+ if (asprintf(&cmnd, "%s %s", c->cmnd, c->args) == -1) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ }
+ value.type = JSON_STRING;
+ value.u.string = cmnd ? cmnd : (char *)"ALL";
+
+ if (!negated && TAILQ_EMPTY(&c->digests)) {
+ /* Print as { "command": "command and args" } */
+ sudo_json_add_value_as_object(jsonc, "command", &value);
+ } else {
+ /* Print as multi-line object. */
+ sudo_json_open_object(jsonc, NULL);
+ sudo_json_add_value(jsonc, "command", &value);
+
+ /* Optional digest list. */
+ TAILQ_FOREACH(digest, &c->digests, entries) {
+ digest_name = digest_type_to_name(digest->digest_type);
+ value.type = JSON_STRING;
+ value.u.string = digest->digest_str;
+ sudo_json_add_value(jsonc, digest_name, &value);
+ }
+
+ /* Command may be negated. */
+ if (negated) {
+ value.type = JSON_BOOL;
+ value.u.boolean = true;
+ sudo_json_add_value(jsonc, "negated", &value);
+ }
+
+ sudo_json_close_object(jsonc);
+ }
+
+ if (cmnd != c->cmnd)
+ free(cmnd);
+
+ debug_return;
+}
+
+/*
+ * Map an alias type to enum word_type.
+ */
+static enum word_type
+alias_to_word_type(short alias_type)
+{
+ switch (alias_type) {
+ case CMNDALIAS:
+ return TYPE_COMMAND;
+ case HOSTALIAS:
+ return TYPE_HOSTNAME;
+ case RUNASALIAS:
+ return TYPE_RUNASUSER;
+ case USERALIAS:
+ return TYPE_USERNAME;
+ default:
+ sudo_fatalx_nodebug("unexpected alias type %d", alias_type);
+ }
+}
+
+/*
+ * Map a Defaults type to enum word_type.
+ */
+static enum word_type
+defaults_to_word_type(int defaults_type)
+{
+ switch (defaults_type) {
+ case DEFAULTS_CMND:
+ return TYPE_COMMAND;
+ case DEFAULTS_HOST:
+ return TYPE_HOSTNAME;
+ case DEFAULTS_RUNAS:
+ return TYPE_RUNASUSER;
+ case DEFAULTS_USER:
+ return TYPE_USERNAME;
+ default:
+ sudo_fatalx_nodebug("unexpected defaults type %d", defaults_type);
+ }
+}
+
+/*
+ * Print struct member in JSON format, with correct indentation.
+ */
+static void
+print_member_json_int(struct json_container *jsonc,
+ const struct sudoers_parse_tree *parse_tree, char *name, int type,
+ bool negated, enum word_type word_type, bool expand_aliases)
+{
+ struct json_value value;
+ const char *typestr = NULL;
+ const char *errstr;
+ short alias_type = UNSPEC;
+ id_t id;
+ debug_decl(print_member_json_int, SUDOERS_DEBUG_UTIL);
+
+ /* Most of the time we print a string. */
+ value.type = JSON_STRING;
+ switch (type) {
+ case ALL:
+ if (name == NULL) {
+ value.u.string = "ALL";
+ } else {
+ /* ALL used with digest, print as a command. */
+ type = COMMAND;
+ }
+ break;
+ case MYSELF:
+ value.u.string = "";
+ break;
+ default:
+ if (name == NULL)
+ sudo_fatalx("missing member name for type %d", type);
+ value.u.string = name;
+ }
+
+ switch (type) {
+ case USERGROUP:
+ value.u.string++; /* skip leading '%' */
+ if (*value.u.string == ':') {
+ value.u.string++;
+ typestr = "nonunixgroup";
+ if (*value.u.string == '#') {
+ id = sudo_strtoid(value.u.string + 1, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx("internal error: non-Unix group-ID %s: \"%s\"",
+ errstr, value.u.string + 1);
+ } else {
+ value.type = JSON_ID;
+ value.u.id = id;
+ typestr = "nonunixgid";
+ }
+ }
+ } else {
+ typestr = "usergroup";
+ if (*value.u.string == '#') {
+ id = sudo_strtoid(value.u.string + 1, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx("internal error: group-ID %s: \"%s\"",
+ errstr, value.u.string + 1);
+ } else {
+ value.type = JSON_ID;
+ value.u.id = id;
+ typestr = "usergid";
+ }
+ }
+ }
+ break;
+ case NETGROUP:
+ typestr = "netgroup";
+ value.u.string++; /* skip leading '+' */
+ break;
+ case NTWKADDR:
+ typestr = "networkaddr";
+ break;
+ case COMMAND:
+ print_command_json(jsonc, name, negated);
+ debug_return;
+ case ALL:
+ case MYSELF:
+ case WORD:
+ switch (word_type) {
+ case TYPE_COMMAND:
+ typestr = "command";
+ break;
+ case TYPE_HOSTNAME:
+ typestr = "hostname";
+ break;
+ case TYPE_RUNASGROUP:
+ typestr = "usergroup";
+ break;
+ case TYPE_RUNASUSER:
+ case TYPE_USERNAME:
+ typestr = "username";
+ if (*value.u.string == '#') {
+ id = sudo_strtoid(value.u.string + 1, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx("internal error: user-ID %s: \"%s\"",
+ errstr, name);
+ } else {
+ value.type = JSON_ID;
+ value.u.id = id;
+ typestr = "userid";
+ }
+ }
+ break;
+ default:
+ sudo_fatalx("unexpected word type %d", word_type);
+ }
+ break;
+ case ALIAS:
+ switch (word_type) {
+ case TYPE_COMMAND:
+ if (expand_aliases) {
+ alias_type = CMNDALIAS;
+ } else {
+ typestr = "cmndalias";
+ }
+ break;
+ case TYPE_HOSTNAME:
+ if (expand_aliases) {
+ alias_type = HOSTALIAS;
+ } else {
+ typestr = "hostalias";
+ }
+ break;
+ case TYPE_RUNASGROUP:
+ case TYPE_RUNASUSER:
+ if (expand_aliases) {
+ alias_type = RUNASALIAS;
+ } else {
+ typestr = "runasalias";
+ }
+ break;
+ case TYPE_USERNAME:
+ if (expand_aliases) {
+ alias_type = USERALIAS;
+ } else {
+ typestr = "useralias";
+ }
+ break;
+ default:
+ sudo_fatalx("unexpected word type %d", word_type);
+ }
+ break;
+ default:
+ sudo_fatalx("unexpected member type %d", type);
+ }
+
+ if (expand_aliases && type == ALIAS) {
+ struct alias *a;
+ struct member *m;
+
+ /* Print each member of the alias. */
+ if ((a = alias_get(parse_tree, value.u.string, alias_type)) != NULL) {
+ TAILQ_FOREACH(m, &a->members, entries) {
+ print_member_json_int(jsonc, parse_tree, m->name, m->type,
+ negated ? !m->negated : m->negated,
+ alias_to_word_type(alias_type), true);
+ }
+ alias_put(a);
+ }
+ } else {
+ if (negated) {
+ sudo_json_open_object(jsonc, NULL);
+ sudo_json_add_value(jsonc, typestr, &value);
+ value.type = JSON_BOOL;
+ value.u.boolean = true;
+ sudo_json_add_value(jsonc, "negated", &value);
+ sudo_json_close_object(jsonc);
+ } else {
+ sudo_json_add_value_as_object(jsonc, typestr, &value);
+ }
+ }
+
+ debug_return;
+}
+
+static void
+print_member_json(struct json_container *jsonc,
+ const struct sudoers_parse_tree *parse_tree, struct member *m,
+ enum word_type word_type, bool expand_aliases)
+{
+ print_member_json_int(jsonc, parse_tree, m->name, m->type, m->negated,
+ word_type, expand_aliases);
+}
+
+/*
+ * Callback for alias_apply() to print an alias entry if it matches
+ * the type specified in the closure.
+ */
+static int
+print_alias_json(struct sudoers_parse_tree *parse_tree, struct alias *a,
+ void *v)
+{
+ struct json_alias_closure *closure = v;
+ struct member *m;
+ debug_decl(print_alias_json, SUDOERS_DEBUG_UTIL);
+
+ if (a->type != closure->alias_type)
+ debug_return_int(0);
+
+ /* Open the aliases object or close the last entry, then open new one. */
+ if (closure->count++ == 0) {
+ sudo_json_open_object(closure->jsonc, closure->title);
+ } else {
+ sudo_json_close_array(closure->jsonc);
+ }
+ sudo_json_open_array(closure->jsonc, a->name);
+
+ TAILQ_FOREACH(m, &a->members, entries) {
+ print_member_json(closure->jsonc, parse_tree, m,
+ alias_to_word_type(closure->alias_type), false);
+ }
+ debug_return_int(0);
+}
+
+/*
+ * Print the binding for a Defaults entry of the specified type.
+ */
+static void
+print_binding_json(struct json_container *jsonc,
+ const struct sudoers_parse_tree *parse_tree,
+ struct defaults_binding *binding, int type, bool expand_aliases)
+{
+ struct member *m;
+ debug_decl(print_binding_json, SUDOERS_DEBUG_UTIL);
+
+ if (TAILQ_EMPTY(&binding->members))
+ debug_return;
+
+ /* Print each member object in binding. */
+ sudo_json_open_array(jsonc, "Binding");
+ TAILQ_FOREACH(m, &binding->members, entries) {
+ print_member_json(jsonc, parse_tree, m, defaults_to_word_type(type),
+ expand_aliases);
+ }
+ sudo_json_close_array(jsonc);
+
+ debug_return;
+}
+
+/*
+ * Print a Defaults list JSON format.
+ */
+static void
+print_defaults_list_json(struct json_container *jsonc, struct defaults *def)
+{
+ char savech, *start, *end = def->val;
+ struct json_value value;
+ debug_decl(print_defaults_list_json, SUDOERS_DEBUG_UTIL);
+
+ sudo_json_open_object(jsonc, NULL);
+ value.type = JSON_STRING;
+ switch (def->op) {
+ case '+':
+ value.u.string = "list_add";
+ break;
+ case '-':
+ value.u.string = "list_remove";
+ break;
+ case true:
+ value.u.string = "list_assign";
+ break;
+ default:
+ sudo_warnx("internal error: unexpected list op %d", def->op);
+ value.u.string = "unsupported";
+ break;
+ }
+ sudo_json_add_value(jsonc, "operation", &value);
+ sudo_json_open_array(jsonc, def->var);
+ /* Split value into multiple space-separated words. */
+ do {
+ /* Remove leading blanks, must have a non-empty string. */
+ for (start = end; isblank((unsigned char)*start); start++)
+ continue;
+ if (*start == '\0')
+ break;
+
+ /* Find the end and print it. */
+ for (end = start; *end && !isblank((unsigned char)*end); end++)
+ continue;
+ savech = *end;
+ *end = '\0';
+ value.type = JSON_STRING;
+ value.u.string = start;
+ sudo_json_add_value(jsonc, NULL, &value);
+ *end = savech;
+ } while (*end++ != '\0');
+ sudo_json_close_array(jsonc);
+ sudo_json_close_object(jsonc);
+
+ debug_return;
+}
+
+static int
+get_defaults_type(struct defaults *def)
+{
+ struct sudo_defs_types *cur;
+
+ /* Look up def in table to find its type. */
+ for (cur = sudo_defs_table; cur->name; cur++) {
+ if (strcmp(def->var, cur->name) == 0)
+ return cur->type;
+ }
+ return -1;
+}
+
+/*
+ * Export all Defaults in JSON format.
+ */
+static void
+print_defaults_json(struct json_container *jsonc,
+ const struct sudoers_parse_tree *parse_tree, bool expand_aliases)
+{
+ struct json_value value;
+ struct defaults *def, *next;
+ int type;
+ debug_decl(print_defaults_json, SUDOERS_DEBUG_UTIL);
+
+ if (TAILQ_EMPTY(&parse_tree->defaults))
+ debug_return;
+
+ sudo_json_open_array(jsonc, "Defaults");
+
+ TAILQ_FOREACH_SAFE(def, &parse_tree->defaults, entries, next) {
+ type = get_defaults_type(def);
+ if (type == -1) {
+ log_warnx(U_("%s:%d:%d: unknown defaults entry \"%s\""),
+ def->file, def->line, def->column, def->var);
+ /* XXX - just pass it through as a string anyway? */
+ continue;
+ }
+
+ /* Found it, print object container and binding (if any). */
+ sudo_json_open_object(jsonc, NULL);
+ print_binding_json(jsonc, parse_tree, def->binding, def->type,
+ expand_aliases);
+
+ /* Validation checks. */
+ /* XXX - validate values in addition to names? */
+
+ /* Print options, merging ones with the same binding. */
+ sudo_json_open_array(jsonc, "Options");
+ for (;;) {
+ next = TAILQ_NEXT(def, entries);
+ /* XXX - need to update cur too */
+ if ((type & T_MASK) == T_FLAG || def->val == NULL) {
+ value.type = JSON_BOOL;
+ value.u.boolean = def->op;
+ sudo_json_add_value_as_object(jsonc, def->var, &value);
+ } else if ((type & T_MASK) == T_LIST) {
+ print_defaults_list_json(jsonc, def);
+ } else {
+ value.type = JSON_STRING;
+ value.u.string = def->val;
+ sudo_json_add_value_as_object(jsonc, def->var, &value);
+ }
+ if (next == NULL || def->binding != next->binding)
+ break;
+ def = next;
+ type = get_defaults_type(def);
+ if (type == -1) {
+ log_warnx(U_("%s:%d:%d: unknown defaults entry \"%s\""),
+ def->file, def->line, def->column, def->var);
+ /* XXX - just pass it through as a string anyway? */
+ break;
+ }
+ }
+ sudo_json_close_array(jsonc);
+ sudo_json_close_object(jsonc);
+ }
+
+ /* Close Defaults array; comma (if any) & newline will be printer later. */
+ sudo_json_close_array(jsonc);
+
+ debug_return;
+}
+
+/*
+ * Export all aliases of the specified type in JSON format.
+ * Iterates through the entire aliases tree.
+ */
+static void
+print_aliases_by_type_json(struct json_container *jsonc,
+ const struct sudoers_parse_tree *parse_tree, short alias_type,
+ const char *title)
+{
+ struct json_alias_closure closure;
+ debug_decl(print_aliases_by_type_json, SUDOERS_DEBUG_UTIL);
+
+ /* print_alias_json() does not modify parse_tree. */
+ closure.jsonc = jsonc;
+ closure.count = 0;
+ closure.alias_type = alias_type;
+ closure.title = title;
+ alias_apply((struct sudoers_parse_tree *)parse_tree, print_alias_json,
+ &closure);
+ if (closure.count != 0) {
+ sudo_json_close_array(jsonc);
+ sudo_json_close_object(jsonc);
+ }
+
+ debug_return;
+}
+
+/*
+ * Export all aliases in JSON format.
+ */
+static void
+print_aliases_json(struct json_container *jsonc,
+ const struct sudoers_parse_tree *parse_tree)
+{
+ debug_decl(print_aliases_json, SUDOERS_DEBUG_UTIL);
+
+ print_aliases_by_type_json(jsonc, parse_tree, USERALIAS, "User_Aliases");
+ print_aliases_by_type_json(jsonc, parse_tree, RUNASALIAS, "Runas_Aliases");
+ print_aliases_by_type_json(jsonc, parse_tree, HOSTALIAS, "Host_Aliases");
+ print_aliases_by_type_json(jsonc, parse_tree, CMNDALIAS, "Command_Aliases");
+
+ debug_return;
+}
+
+/* Does the next entry differ only in the command itself? */
+static bool
+cmndspec_continues(struct cmndspec *cs, struct cmndspec *next)
+{
+ bool ret = next != NULL &&
+ !RUNAS_CHANGED(cs, next) && !TAGS_CHANGED(cs->tags, next->tags)
+#ifdef HAVE_PRIV_SET
+ && cs->privs == next->privs && cs->limitprivs == next->limitprivs
+#endif /* HAVE_PRIV_SET */
+#ifdef HAVE_SELINUX
+ && cs->role == next->role && cs->type == next->type
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_APPARMOR
+ && cs->apparmor_profile == next->apparmor_profile
+#endif /* HAVE_APPARMOR */
+ && cs->runchroot == next->runchroot && cs->runcwd == next->runcwd;
+ return ret;
+}
+
+/*
+ * Print a Cmnd_Spec in JSON format at the correct indent level.
+ * A pointer to the next Cmnd_Spec is passed in to make it possible to
+ * merge adjacent entries that are identical in all but the command.
+ */
+static void
+print_cmndspec_json(struct json_container *jsonc,
+ const struct sudoers_parse_tree *parse_tree, struct cmndspec *cs,
+ struct cmndspec **nextp, struct defaults_list *options, bool expand_aliases)
+{
+ char timebuf[sizeof("20120727121554Z")];
+ struct cmndspec *next = *nextp;
+ struct json_value value;
+ struct defaults *def;
+ struct member *m;
+ struct tm gmt;
+ size_t len;
+ debug_decl(print_cmndspec_json, SUDOERS_DEBUG_UTIL);
+
+ /* Open Cmnd_Spec object. */
+ sudo_json_open_object(jsonc, NULL);
+
+ /* Print runasuserlist */
+ if (cs->runasuserlist != NULL) {
+ sudo_json_open_array(jsonc, "runasusers");
+ TAILQ_FOREACH(m, cs->runasuserlist, entries) {
+ print_member_json(jsonc, parse_tree, m, TYPE_RUNASUSER,
+ expand_aliases);
+ }
+ sudo_json_close_array(jsonc);
+ }
+
+ /* Print runasgrouplist */
+ if (cs->runasgrouplist != NULL) {
+ sudo_json_open_array(jsonc, "runasgroups");
+ TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
+ print_member_json(jsonc, parse_tree, m, TYPE_RUNASGROUP,
+ expand_aliases);
+ }
+ sudo_json_close_array(jsonc);
+ }
+
+ /* Print options and tags */
+ if (cs->timeout > 0 || cs->notbefore != UNSPEC || cs->notafter != UNSPEC ||
+ cs->runchroot != NULL || cs->runcwd != NULL || TAGS_SET(cs->tags) ||
+ !TAILQ_EMPTY(options)) {
+ struct cmndtag tag = cs->tags;
+
+ sudo_json_open_array(jsonc, "Options");
+ if (cs->runchroot != NULL) {
+ value.type = JSON_STRING;
+ value.u.string = cs->runchroot;
+ sudo_json_add_value(jsonc, "runchroot", &value);
+ }
+ if (cs->runcwd != NULL) {
+ value.type = JSON_STRING;
+ value.u.string = cs->runcwd;
+ sudo_json_add_value(jsonc, "runcwd", &value);
+ }
+ if (cs->timeout > 0) {
+ value.type = JSON_NUMBER;
+ value.u.number = cs->timeout;
+ sudo_json_add_value_as_object(jsonc, "command_timeout", &value);
+ }
+ if (cs->notbefore != UNSPEC) {
+ if (gmtime_r(&cs->notbefore, &gmt) == NULL) {
+ sudo_warn("%s", U_("unable to get GMT time"));
+ } else {
+ timebuf[sizeof(timebuf) - 1] = '\0';
+ len = strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", &gmt);
+ if (len == 0 || timebuf[sizeof(timebuf) - 1] != '\0') {
+ sudo_warnx("%s", U_("unable to format timestamp"));
+ } else {
+ value.type = JSON_STRING;
+ value.u.string = timebuf;
+ sudo_json_add_value_as_object(jsonc, "notbefore", &value);
+ }
+ }
+ }
+ if (cs->notafter != UNSPEC) {
+ if (gmtime_r(&cs->notafter, &gmt) == NULL) {
+ sudo_warn("%s", U_("unable to get GMT time"));
+ } else {
+ timebuf[sizeof(timebuf) - 1] = '\0';
+ len = strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", &gmt);
+ if (len == 0 || timebuf[sizeof(timebuf) - 1] != '\0') {
+ sudo_warnx("%s", U_("unable to format timestamp"));
+ } else {
+ value.type = JSON_STRING;
+ value.u.string = timebuf;
+ sudo_json_add_value_as_object(jsonc, "notafter", &value);
+ }
+ }
+ }
+ if (tag.nopasswd != UNSPEC) {
+ value.type = JSON_BOOL;
+ value.u.boolean = !tag.nopasswd;
+ sudo_json_add_value_as_object(jsonc, "authenticate", &value);
+ }
+ if (tag.noexec != UNSPEC) {
+ value.type = JSON_BOOL;
+ value.u.boolean = tag.noexec;
+ sudo_json_add_value_as_object(jsonc, "noexec", &value);
+ }
+ if (tag.intercept != UNSPEC) {
+ value.type = JSON_BOOL;
+ value.u.boolean = tag.intercept;
+ sudo_json_add_value_as_object(jsonc, "intercept", &value);
+ }
+ if (tag.send_mail != UNSPEC) {
+ value.type = JSON_BOOL;
+ value.u.boolean = tag.send_mail;
+ sudo_json_add_value_as_object(jsonc, "send_mail", &value);
+ }
+ if (tag.setenv != UNSPEC) {
+ value.type = JSON_BOOL;
+ value.u.boolean = tag.setenv;
+ sudo_json_add_value_as_object(jsonc, "setenv", &value);
+ }
+ if (tag.follow != UNSPEC) {
+ value.type = JSON_BOOL;
+ value.u.boolean = tag.follow;
+ sudo_json_add_value_as_object(jsonc, "sudoedit_follow", &value);
+ }
+ if (tag.log_input != UNSPEC) {
+ value.type = JSON_BOOL;
+ value.u.boolean = tag.log_input;
+ sudo_json_add_value_as_object(jsonc, "log_input", &value);
+ }
+ if (tag.log_output != UNSPEC) {
+ value.type = JSON_BOOL;
+ value.u.boolean = tag.log_output;
+ sudo_json_add_value_as_object(jsonc, "log_output", &value);
+ }
+ TAILQ_FOREACH(def, options, entries) {
+ int type = get_defaults_type(def);
+ if (type == -1) {
+ log_warnx(U_("%s:%d:%d: unknown defaults entry \"%s\""),
+ def->file, def->line, def->column, def->var);
+ /* XXX - just pass it through as a string anyway? */
+ continue;
+ }
+ if ((type & T_MASK) == T_FLAG || def->val == NULL) {
+ value.type = JSON_BOOL;
+ value.u.boolean = def->op;
+ sudo_json_add_value_as_object(jsonc, def->var, &value);
+ } else if ((type & T_MASK) == T_LIST) {
+ print_defaults_list_json(jsonc, def);
+ } else {
+ value.type = JSON_STRING;
+ value.u.string = def->val;
+ sudo_json_add_value_as_object(jsonc, def->var, &value);
+ }
+ }
+ sudo_json_close_array(jsonc);
+ }
+
+#ifdef HAVE_SELINUX
+ /* Print SELinux role/type */
+ if (cs->role != NULL && cs->type != NULL) {
+ sudo_json_open_array(jsonc, "SELinux_Spec");
+ value.type = JSON_STRING;
+ value.u.string = cs->role;
+ sudo_json_add_value(jsonc, "role", &value);
+ value.u.string = cs->type;
+ sudo_json_add_value(jsonc, "type", &value);
+ sudo_json_close_array(jsonc);
+ }
+#endif /* HAVE_SELINUX */
+
+#ifdef HAVE_APPARMOR
+ if (cs->apparmor_profile != NULL) {
+ sudo_json_open_array(jsonc, "AppArmor_Spec");
+ value.type = JSON_STRING;
+ value.u.string = cs->apparmor_profile;
+ sudo_json_add_value(jsonc, "apparmor_profile", &value);
+ sudo_json_close_array(jsonc);
+ }
+#endif /* HAVE_APPARMOR */
+
+#ifdef HAVE_PRIV_SET
+ /* Print Solaris privs/limitprivs */
+ if (cs->privs != NULL || cs->limitprivs != NULL) {
+ sudo_json_open_array(jsonc, "Solaris_Priv_Spec");
+ value.type = JSON_STRING;
+ if (cs->privs != NULL) {
+ value.u.string = cs->privs;
+ sudo_json_add_value(jsonc, "privs", &value);
+ }
+ if (cs->limitprivs != NULL) {
+ value.u.string = cs->limitprivs;
+ sudo_json_add_value(jsonc, "limitprivs", &value);
+ }
+ sudo_json_close_array(jsonc);
+ }
+#endif /* HAVE_PRIV_SET */
+
+ /*
+ * Merge adjacent commands with matching tags, runas, SELinux
+ * role/type and Solaris priv settings.
+ */
+ sudo_json_open_array(jsonc, "Commands");
+ for (;;) {
+ print_member_json(jsonc, parse_tree, cs->cmnd, TYPE_COMMAND,
+ expand_aliases);
+ /* Does the next entry differ only in the command itself? */
+ if (!cmndspec_continues(cs, next))
+ break;
+ cs = next;
+ next = TAILQ_NEXT(cs, entries);
+ }
+ sudo_json_close_array(jsonc);
+
+ /* Close Cmnd_Spec object. */
+ sudo_json_close_object(jsonc);
+
+ *nextp = next;
+
+ debug_return;
+}
+
+/*
+ * Print a User_Spec in JSON format at the correct indent level.
+ */
+static void
+print_userspec_json(struct json_container *jsonc,
+ const struct sudoers_parse_tree *parse_tree, struct userspec *us,
+ bool expand_aliases)
+{
+ struct privilege *priv;
+ struct member *m;
+ struct cmndspec *cs, *next;
+ debug_decl(print_userspec_json, SUDOERS_DEBUG_UTIL);
+
+ /*
+ * Each userspec struct may contain multiple privileges for
+ * a user. We export each privilege as a separate User_Spec
+ * object for simplicity's sake.
+ */
+ TAILQ_FOREACH(priv, &us->privileges, entries) {
+ /* Open User_Spec object. */
+ sudo_json_open_object(jsonc, NULL);
+
+ /* Print users list. */
+ sudo_json_open_array(jsonc, "User_List");
+ TAILQ_FOREACH(m, &us->users, entries) {
+ print_member_json(jsonc, parse_tree, m, TYPE_USERNAME,
+ expand_aliases);
+ }
+ sudo_json_close_array(jsonc);
+
+ /* Print hosts list. */
+ sudo_json_open_array(jsonc, "Host_List");
+ TAILQ_FOREACH(m, &priv->hostlist, entries) {
+ print_member_json(jsonc, parse_tree, m, TYPE_HOSTNAME,
+ expand_aliases);
+ }
+ sudo_json_close_array(jsonc);
+
+ /* Print commands. */
+ sudo_json_open_array(jsonc, "Cmnd_Specs");
+ TAILQ_FOREACH_SAFE(cs, &priv->cmndlist, entries, next) {
+ print_cmndspec_json(jsonc, parse_tree, cs, &next, &priv->defaults,
+ expand_aliases);
+ }
+ sudo_json_close_array(jsonc);
+
+ /* Close User_Spec object. */
+ sudo_json_close_object(jsonc);
+ }
+
+ debug_return;
+}
+
+static void
+print_userspecs_json(struct json_container *jsonc,
+ const struct sudoers_parse_tree *parse_tree, bool expand_aliases)
+{
+ struct userspec *us;
+ debug_decl(print_userspecs_json, SUDOERS_DEBUG_UTIL);
+
+ if (TAILQ_EMPTY(&parse_tree->userspecs))
+ debug_return;
+
+ sudo_json_open_array(jsonc, "User_Specs");
+ TAILQ_FOREACH(us, &parse_tree->userspecs, entries) {
+ print_userspec_json(jsonc, parse_tree, us, expand_aliases);
+ }
+ sudo_json_close_array(jsonc);
+
+ debug_return;
+}
+
+/*
+ * Export the parsed sudoers file in JSON format.
+ */
+bool
+convert_sudoers_json(const struct sudoers_parse_tree *parse_tree,
+ const char *output_file, struct cvtsudoers_config *conf)
+{
+ struct json_container jsonc;
+ bool ret = true;
+ FILE *output_fp = stdout;
+ debug_decl(convert_sudoers_json, SUDOERS_DEBUG_UTIL);
+
+ if (strcmp(output_file, "-") != 0) {
+ if ((output_fp = fopen(output_file, "w")) == NULL)
+ sudo_fatal(U_("unable to open %s"), output_file);
+ }
+
+ /* 4 space indent, non-compact, exit on memory allocation failure. */
+ sudo_json_init(&jsonc, 4, false, true, false);
+
+ /* Dump Defaults in JSON format. */
+ if (!ISSET(conf->suppress, SUPPRESS_DEFAULTS)) {
+ print_defaults_json(&jsonc, parse_tree, conf->expand_aliases);
+ }
+
+ /* Dump Aliases in JSON format. */
+ if (!conf->expand_aliases && !ISSET(conf->suppress, SUPPRESS_ALIASES)) {
+ print_aliases_json(&jsonc, parse_tree);
+ }
+
+ /* Dump User_Specs in JSON format. */
+ if (!ISSET(conf->suppress, SUPPRESS_PRIVS)) {
+ print_userspecs_json(&jsonc, parse_tree, conf->expand_aliases);
+ }
+
+ /* Write JSON output. */
+ if (sudo_json_get_len(&jsonc) != 0) {
+ putc('{', output_fp);
+ fputs(sudo_json_get_buf(&jsonc), output_fp);
+ fputs("\n}\n", output_fp);
+ (void)fflush(output_fp);
+ if (ferror(output_fp))
+ ret = false;
+ }
+ sudo_json_free(&jsonc);
+ if (output_fp != stdout)
+ fclose(output_fp);
+
+ debug_return_bool(ret);
+}
diff --git a/plugins/sudoers/cvtsudoers_ldif.c b/plugins/sudoers/cvtsudoers_ldif.c
new file mode 100644
index 0000000..b967d47
--- /dev/null
+++ b/plugins/sudoers/cvtsudoers_ldif.c
@@ -0,0 +1,735 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2018-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <unistd.h>
+#include <stdarg.h>
+
+#include <sudoers.h>
+#include <sudo_ldap.h>
+#include <redblack.h>
+#include <cvtsudoers.h>
+#include <sudo_lbuf.h>
+#include <gram.h>
+
+struct seen_user {
+ const char *name;
+ unsigned long count;
+};
+
+static struct rbtree *seen_users;
+
+static int
+seen_user_compare(const void *aa, const void *bb)
+{
+ const struct seen_user *a = aa;
+ const struct seen_user *b = bb;
+
+ return strcasecmp(a->name, b->name);
+}
+
+static void
+seen_user_free(void *v)
+{
+ struct seen_user *su = v;
+
+ free((void *)su->name);
+ free(su);
+}
+
+static bool
+safe_string(const char *str)
+{
+ const unsigned char *ustr = (const unsigned char *)str;
+ unsigned char ch = *ustr++;
+ debug_decl(safe_string, SUDOERS_DEBUG_UTIL);
+
+ /* Initial char must be <= 127 and not LF, CR, SPACE, ':', '<' */
+ switch (ch) {
+ case '\0':
+ debug_return_bool(true);
+ case '\n':
+ case '\r':
+ case ' ':
+ case ':':
+ case '<':
+ debug_return_bool(false);
+ default:
+ if (ch > 127)
+ debug_return_bool(false);
+ }
+
+ /* Any value <= 127 decimal except NUL, LF, and CR is safe */
+ while ((ch = *ustr++) != '\0') {
+ if (ch > 127 || ch == '\n' || ch == '\r')
+ debug_return_bool(false);
+ }
+
+ debug_return_bool(true);
+}
+
+static bool
+print_attribute_ldif(FILE *fp, const char *name, const char *value)
+{
+ const unsigned char *uvalue = (unsigned char *)value;
+ char *encoded = NULL;
+ size_t esize;
+ debug_decl(print_attribute_ldif, SUDOERS_DEBUG_UTIL);
+
+ if (!safe_string(value)) {
+ const size_t vlen = strlen(value);
+ esize = ((vlen + 2) / 3 * 4) + 1;
+ if ((encoded = malloc(esize)) == NULL)
+ debug_return_bool(false);
+ if (base64_encode(uvalue, vlen, encoded, esize) == (size_t)-1) {
+ free(encoded);
+ debug_return_bool(false);
+ }
+ fprintf(fp, "%s:: %s\n", name, encoded);
+ free(encoded);
+ } else if (*value != '\0') {
+ fprintf(fp, "%s: %s\n", name, value);
+ } else {
+ fprintf(fp, "%s:\n", name);
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Print sudoOptions from a defaults_list.
+ */
+static bool
+print_options_ldif(FILE *fp, const struct defaults_list *options)
+{
+ struct defaults *opt;
+ char *attr_val;
+ int len;
+ debug_decl(print_options_ldif, SUDOERS_DEBUG_UTIL);
+
+ TAILQ_FOREACH(opt, options, entries) {
+ if (opt->type != DEFAULTS)
+ continue; /* don't support bound defaults */
+
+ if (opt->val != NULL) {
+ /* There is no need to double quote values here. */
+ len = asprintf(&attr_val, "%s%s%s", opt->var,
+ opt->op == '+' ? "+=" : opt->op == '-' ? "-=" : "=", opt->val);
+ } else {
+ /* Boolean flag. */
+ len = asprintf(&attr_val, "%s%s",
+ opt->op == false ? "!" : "", opt->var);
+ }
+ if (len == -1) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ print_attribute_ldif(fp, "sudoOption", attr_val);
+ free(attr_val);
+ }
+
+ debug_return_bool(!ferror(fp));
+}
+
+/*
+ * Print global Defaults in a single sudoRole object.
+ */
+static bool
+print_global_defaults_ldif(FILE *fp,
+ const struct sudoers_parse_tree *parse_tree, const char *base)
+{
+ unsigned int count = 0;
+ struct sudo_lbuf lbuf;
+ struct defaults *opt;
+ char *dn;
+ debug_decl(print_global_defaults_ldif, SUDOERS_DEBUG_UTIL);
+
+ sudo_lbuf_init(&lbuf, NULL, 0, NULL, 80);
+
+ TAILQ_FOREACH(opt, &parse_tree->defaults, entries) {
+ /* Skip bound Defaults (unsupported). */
+ if (opt->type == DEFAULTS) {
+ count++;
+ } else {
+ lbuf.len = 0;
+ sudo_lbuf_append(&lbuf, "# ");
+ sudoers_format_default_line(&lbuf, parse_tree, opt, false, true);
+ fprintf(fp, "# Unable to translate %s:%d:%d:\n%s\n",
+ opt->file, opt->line, opt->column, lbuf.buf);
+ }
+ }
+ sudo_lbuf_destroy(&lbuf);
+
+ if (count == 0)
+ debug_return_bool(true);
+
+ if (asprintf(&dn, "cn=defaults,%s", base) == -1) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ print_attribute_ldif(fp, "dn", dn);
+ free(dn);
+ print_attribute_ldif(fp, "objectClass", "top");
+ print_attribute_ldif(fp, "objectClass", "sudoRole");
+ print_attribute_ldif(fp, "cn", "defaults");
+ print_attribute_ldif(fp, "description", "Default sudoOption's go here");
+
+ print_options_ldif(fp, &parse_tree->defaults);
+ putc('\n', fp);
+
+ debug_return_bool(!ferror(fp));
+}
+
+/*
+ * Format a sudo_command as a string.
+ * Returns the formatted, dynamically allocated string or dies on error.
+ */
+static char *
+format_cmnd(struct sudo_command *c, bool negated)
+{
+ struct command_digest *digest;
+ char *buf, *cp, *cmnd;
+ size_t bufsiz;
+ int len;
+ debug_decl(format_cmnd, SUDOERS_DEBUG_UTIL);
+
+ cmnd = c->cmnd ? c->cmnd : (char *)"ALL";
+ bufsiz = negated + strlen(cmnd) + 1;
+ if (c->args != NULL)
+ bufsiz += 1 + strlen(c->args);
+ TAILQ_FOREACH(digest, &c->digests, entries) {
+ bufsiz += strlen(digest_type_to_name(digest->digest_type)) + 1 +
+ strlen(digest->digest_str) + 1;
+ if (TAILQ_NEXT(digest, entries) != NULL)
+ bufsiz += 2;
+ }
+
+ if ((buf = malloc(bufsiz)) == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+
+ cp = buf;
+ TAILQ_FOREACH(digest, &c->digests, entries) {
+ len = snprintf(cp, bufsiz - (size_t)(cp - buf), "%s:%s%s ",
+ digest_type_to_name(digest->digest_type), digest->digest_str,
+ TAILQ_NEXT(digest, entries) ? "," : "");
+ if (len < 0 || len >= (int)bufsiz - (cp - buf))
+ sudo_fatalx(U_("internal error, %s overflow"), __func__);
+ cp += len;
+ }
+
+ len = snprintf(cp, bufsiz - (size_t)(cp - buf), "%s%s%s%s",
+ negated ? "!" : "", cmnd, c->args ? " " : "", c->args ? c->args : "");
+ if (len < 0 || len >= (int)bufsiz - (cp - buf))
+ sudo_fatalx(U_("internal error, %s overflow"), __func__);
+
+ debug_return_str(buf);
+}
+
+/*
+ * Print struct member in LDIF format as the specified attribute.
+ * See print_member_int() in parse.c.
+ */
+static void
+print_member_ldif(FILE *fp, const struct sudoers_parse_tree *parse_tree,
+ char *name, int type, bool negated, short alias_type,
+ const char *attr_name)
+{
+ struct alias *a;
+ struct member *m;
+ char *attr_val;
+ int len;
+ debug_decl(print_member_ldif, SUDOERS_DEBUG_UTIL);
+
+ switch (type) {
+ case MYSELF:
+ /* Only valid for sudoRunasUser */
+ print_attribute_ldif(fp, attr_name, "");
+ break;
+ case ALL:
+ if (name == NULL) {
+ print_attribute_ldif(fp, attr_name, negated ? "!ALL" : "ALL");
+ break;
+ }
+ FALLTHROUGH;
+ case COMMAND:
+ attr_val = format_cmnd((struct sudo_command *)name, negated);
+ print_attribute_ldif(fp, attr_name, attr_val);
+ free(attr_val);
+ break;
+ case ALIAS:
+ if ((a = alias_get(parse_tree, name, alias_type)) != NULL) {
+ TAILQ_FOREACH(m, &a->members, entries) {
+ print_member_ldif(fp, parse_tree, m->name, m->type,
+ negated ? !m->negated : m->negated, alias_type, attr_name);
+ }
+ alias_put(a);
+ break;
+ }
+ FALLTHROUGH;
+ default:
+ len = asprintf(&attr_val, "%s%s", negated ? "!" : "", name);
+ if (len == -1) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ print_attribute_ldif(fp, attr_name, attr_val);
+ free(attr_val);
+ break;
+ }
+
+ debug_return;
+}
+
+/*
+ * Print a Cmnd_Spec in LDIF format.
+ * A pointer to the next Cmnd_Spec is passed in to make it possible to
+ * merge adjacent entries that are identical in all but the command.
+ */
+static void
+print_cmndspec_ldif(FILE *fp, const struct sudoers_parse_tree *parse_tree,
+ struct cmndspec *cs, struct cmndspec **nextp, struct defaults_list *options)
+{
+ char timebuf[sizeof("20120727121554Z")];
+ struct cmndspec *next = *nextp;
+ struct member *m;
+ struct tm gmt;
+ char *attr_val;
+ bool last_one;
+ size_t len;
+ debug_decl(print_cmndspec_ldif, SUDOERS_DEBUG_UTIL);
+
+ /* Print runasuserlist as sudoRunAsUser attributes */
+ if (cs->runasuserlist != NULL) {
+ TAILQ_FOREACH(m, cs->runasuserlist, entries) {
+ print_member_ldif(fp, parse_tree, m->name, m->type, m->negated,
+ RUNASALIAS, "sudoRunAsUser");
+ }
+ }
+
+ /* Print runasgrouplist as sudoRunAsGroup attributes */
+ if (cs->runasgrouplist != NULL) {
+ TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
+ print_member_ldif(fp, parse_tree, m->name, m->type, m->negated,
+ RUNASALIAS, "sudoRunAsGroup");
+ }
+ }
+
+ /* Print sudoNotBefore and sudoNotAfter attributes */
+ if (cs->notbefore != UNSPEC) {
+ if (gmtime_r(&cs->notbefore, &gmt) == NULL) {
+ sudo_warn("%s", U_("unable to get GMT time"));
+ } else {
+ timebuf[sizeof(timebuf) - 1] = '\0';
+ len = strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", &gmt);
+ if (len == 0 || timebuf[sizeof(timebuf) - 1] != '\0') {
+ sudo_warnx("%s", U_("unable to format timestamp"));
+ } else {
+ print_attribute_ldif(fp, "sudoNotBefore", timebuf);
+ }
+ }
+ }
+ if (cs->notafter != UNSPEC) {
+ if (gmtime_r(&cs->notafter, &gmt) == NULL) {
+ sudo_warn("%s", U_("unable to get GMT time"));
+ } else {
+ timebuf[sizeof(timebuf) - 1] = '\0';
+ len = strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%SZ", &gmt);
+ if (len == 0 || timebuf[sizeof(timebuf) - 1] != '\0') {
+ sudo_warnx("%s", U_("unable to format timestamp"));
+ } else {
+ print_attribute_ldif(fp, "sudoNotAfter", timebuf);
+ }
+ }
+ }
+
+ /* Print timeout as a sudoOption. */
+ if (cs->timeout > 0) {
+ if (asprintf(&attr_val, "command_timeout=%d", cs->timeout) == -1) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ print_attribute_ldif(fp, "sudoOption", attr_val);
+ free(attr_val);
+ }
+
+ /* Print tags as sudoOption attributes */
+ if (TAGS_SET(cs->tags)) {
+ struct cmndtag tag = cs->tags;
+
+ if (tag.nopasswd != UNSPEC) {
+ print_attribute_ldif(fp, "sudoOption",
+ tag.nopasswd ? "!authenticate" : "authenticate");
+ }
+ if (tag.noexec != UNSPEC) {
+ print_attribute_ldif(fp, "sudoOption",
+ tag.noexec ? "noexec" : "!noexec");
+ }
+ if (tag.intercept != UNSPEC) {
+ print_attribute_ldif(fp, "sudoOption",
+ tag.intercept ? "intercept" : "!intercept");
+ }
+ if (tag.send_mail != UNSPEC) {
+ if (tag.send_mail) {
+ print_attribute_ldif(fp, "sudoOption", "mail_all_cmnds");
+ } else {
+ print_attribute_ldif(fp, "sudoOption", "!mail_all_cmnds");
+ print_attribute_ldif(fp, "sudoOption", "!mail_always");
+ print_attribute_ldif(fp, "sudoOption", "!mail_no_perms");
+ }
+ }
+ if (tag.setenv != UNSPEC && tag.setenv != IMPLIED) {
+ print_attribute_ldif(fp, "sudoOption",
+ tag.setenv ? "setenv" : "!setenv");
+ }
+ if (tag.follow != UNSPEC) {
+ print_attribute_ldif(fp, "sudoOption",
+ tag.follow ? "sudoedit_follow" : "!sudoedit_follow");
+ }
+ if (tag.log_input != UNSPEC) {
+ print_attribute_ldif(fp, "sudoOption",
+ tag.log_input ? "log_input" : "!log_input");
+ }
+ if (tag.log_output != UNSPEC) {
+ print_attribute_ldif(fp, "sudoOption",
+ tag.log_output ? "log_output" : "!log_output");
+ }
+ }
+ print_options_ldif(fp, options);
+
+ /* Print runchroot and runcwd. */
+ if (cs->runchroot != NULL) {
+ if (asprintf(&attr_val, "runchroot=%s", cs->runchroot) == -1) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ print_attribute_ldif(fp, "sudoOption", attr_val);
+ free(attr_val);
+ }
+ if (cs->runcwd != NULL) {
+ if (asprintf(&attr_val, "runcwd=%s", cs->runcwd) == -1) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ print_attribute_ldif(fp, "sudoOption", attr_val);
+ free(attr_val);
+ }
+
+#ifdef HAVE_SELINUX
+ /* Print SELinux role/type */
+ if (cs->role != NULL && cs->type != NULL) {
+ if (asprintf(&attr_val, "role=%s", cs->role) == -1) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ print_attribute_ldif(fp, "sudoOption", attr_val);
+ free(attr_val);
+
+ if (asprintf(&attr_val, "type=%s", cs->type) == -1) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ print_attribute_ldif(fp, "sudoOption", attr_val);
+ free(attr_val);
+ }
+#endif /* HAVE_SELINUX */
+
+#ifdef HAVE_APPARMOR
+ /* Print AppArmor profile */
+ if (cs->apparmor_profile != NULL) {
+ if (asprintf(&attr_val, "apparmor_profile=%s", cs->apparmor_profile) == -1) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ print_attribute_ldif(fp, "sudoOption", attr_val);
+ free(attr_val);
+ }
+#endif /* HAVE_APPARMOR */
+
+#ifdef HAVE_PRIV_SET
+ /* Print Solaris privs/limitprivs */
+ if (cs->privs != NULL || cs->limitprivs != NULL) {
+ if (cs->privs != NULL) {
+ if (asprintf(&attr_val, "privs=%s", cs->privs) == -1) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ print_attribute_ldif(fp, "sudoOption", attr_val);
+ free(attr_val);
+ }
+ if (cs->limitprivs != NULL) {
+ if (asprintf(&attr_val, "limitprivs=%s", cs->limitprivs) == -1) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ print_attribute_ldif(fp, "sudoOption", attr_val);
+ free(attr_val);
+ }
+ }
+#endif /* HAVE_PRIV_SET */
+
+ /*
+ * Merge adjacent commands with matching tags, runas, SELinux
+ * role/type and Solaris priv settings.
+ */
+ for (;;) {
+ /* Does the next entry differ only in the command itself? */
+ /* XXX - move into a function that returns bool */
+ /* XXX - TAG_SET does not account for implied SETENV */
+ last_one = next == NULL ||
+ RUNAS_CHANGED(cs, next) || TAGS_CHANGED(cs->tags, next->tags)
+#ifdef HAVE_PRIV_SET
+ || cs->privs != next->privs || cs->limitprivs != next->limitprivs
+#endif /* HAVE_PRIV_SET */
+#ifdef HAVE_SELINUX
+ || cs->role != next->role || cs->type != next->type
+#endif /* HAVE_SELINUX */
+ || cs->runchroot != next->runchroot || cs->runcwd != next->runcwd;
+
+ print_member_ldif(fp, parse_tree, cs->cmnd->name, cs->cmnd->type,
+ cs->cmnd->negated, CMNDALIAS, "sudoCommand");
+ if (last_one)
+ break;
+ cs = next;
+ next = TAILQ_NEXT(cs, entries);
+ }
+
+ *nextp = next;
+
+ debug_return;
+}
+
+/*
+ * Convert user name to cn, avoiding duplicates and quoting as needed.
+ * See http://www.faqs.org/rfcs/rfc2253.html
+ */
+static char *
+user_to_cn(const char *user)
+{
+ struct seen_user key, *su = NULL;
+ struct rbnode *node;
+ const char *src;
+ char *cn, *dst;
+ size_t size;
+ debug_decl(user_to_cn, SUDOERS_DEBUG_UTIL);
+
+ /* Allocate as much as we could possibly need. */
+ size = (2 * strlen(user)) + 64 + 1;
+ if ((cn = malloc(size)) == NULL)
+ goto bad;
+
+ /*
+ * Increment the number of times we have seen this user.
+ */
+ key.name = user;
+ node = rbfind(seen_users, &key);
+ if (node != NULL) {
+ su = node->data;
+ } else {
+ if ((su = malloc(sizeof(*su))) == NULL)
+ goto bad;
+ su->count = 0;
+ if ((su->name = strdup(user)) == NULL)
+ goto bad;
+ if (rbinsert(seen_users, su, NULL) != 0)
+ goto bad;
+ }
+
+ /* Build cn, quoting special chars as needed (we allocated 2 x len). */
+ for (src = user, dst = cn; *src != '\0'; src++) {
+ switch (*src) {
+ case ',':
+ case '+':
+ case '"':
+ case '\\':
+ case '<':
+ case '>':
+ case '#':
+ case ';':
+ *dst++ = '\\'; /* always escape */
+ break;
+ case ' ':
+ if (src == user || src[1] == '\0')
+ *dst++ = '\\'; /* only escape at beginning or end of string */
+ break;
+ default:
+ break;
+ }
+ *dst++ = *src;
+ }
+ *dst = '\0';
+
+ /* Append count if there are duplicate users (cn must be unique). */
+ if (su->count != 0) {
+ size -= (size_t)(dst - cn);
+ if ((size_t)snprintf(dst, size, "_%lu", su->count) >= size) {
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ goto bad;
+ }
+ }
+ su->count++;
+
+ debug_return_str(cn);
+bad:
+ if (su != NULL && su->count == 0)
+ seen_user_free(su);
+ free(cn);
+ debug_return_str(NULL);
+}
+
+/*
+ * Print a single User_Spec.
+ */
+static bool
+print_userspec_ldif(FILE *fp, const struct sudoers_parse_tree *parse_tree,
+ struct userspec *us, struct cvtsudoers_config *conf)
+{
+ struct privilege *priv;
+ struct member *m;
+ struct cmndspec *cs, *next;
+ debug_decl(print_userspec_ldif, SUDOERS_DEBUG_UTIL);
+
+ /*
+ * Each userspec struct may contain multiple privileges for
+ * the user. We export each privilege as a separate sudoRole
+ * object for simplicity's sake.
+ */
+ TAILQ_FOREACH(priv, &us->privileges, entries) {
+ TAILQ_FOREACH_SAFE(cs, &priv->cmndlist, entries, next) {
+ const char *base = conf->sudoers_base;
+ char *cn, *dn;
+
+ /*
+ * Increment the number of times we have seen this user.
+ * If more than one user is listed, just use the first one.
+ */
+ m = TAILQ_FIRST(&us->users);
+ cn = user_to_cn(m->type == ALL ? "ALL" : m->name);
+ if (cn == NULL || asprintf(&dn, "cn=%s,%s", cn, base) == -1) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+
+ print_attribute_ldif(fp, "dn", dn);
+ print_attribute_ldif(fp, "objectClass", "top");
+ print_attribute_ldif(fp, "objectClass", "sudoRole");
+ print_attribute_ldif(fp, "cn", cn);
+ free(cn);
+ free(dn);
+
+ TAILQ_FOREACH(m, &us->users, entries) {
+ print_member_ldif(fp, parse_tree, m->name, m->type, m->negated,
+ USERALIAS, "sudoUser");
+ }
+
+ TAILQ_FOREACH(m, &priv->hostlist, entries) {
+ print_member_ldif(fp, parse_tree, m->name, m->type, m->negated,
+ HOSTALIAS, "sudoHost");
+ }
+
+ print_cmndspec_ldif(fp, parse_tree, cs, &next, &priv->defaults);
+
+ if (conf->sudo_order != 0) {
+ char numbuf[STRLEN_MAX_UNSIGNED(conf->sudo_order) + 1];
+ if (conf->order_max != 0 && conf->sudo_order > conf->order_max) {
+ sudo_fatalx(U_("too many sudoers entries, maximum %u"),
+ conf->order_padding);
+ }
+ (void)snprintf(numbuf, sizeof(numbuf), "%u", conf->sudo_order);
+ print_attribute_ldif(fp, "sudoOrder", numbuf);
+ putc('\n', fp);
+ conf->sudo_order += conf->order_increment;
+ }
+ }
+ }
+
+ debug_return_bool(!ferror(fp));
+}
+
+/*
+ * Print User_Specs.
+ */
+static bool
+print_userspecs_ldif(FILE *fp, const struct sudoers_parse_tree *parse_tree,
+ struct cvtsudoers_config *conf)
+{
+ struct userspec *us;
+ debug_decl(print_userspecs_ldif, SUDOERS_DEBUG_UTIL);
+
+ TAILQ_FOREACH(us, &parse_tree->userspecs, entries) {
+ if (!print_userspec_ldif(fp, parse_tree, us, conf))
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+/*
+ * Export the parsed sudoers file in LDIF format.
+ */
+bool
+convert_sudoers_ldif(const struct sudoers_parse_tree *parse_tree,
+ const char *output_file, struct cvtsudoers_config *conf)
+{
+ bool ret = true;
+ FILE *output_fp = stdout;
+ debug_decl(convert_sudoers_ldif, SUDOERS_DEBUG_UTIL);
+
+ if (conf->sudoers_base == NULL) {
+ sudo_fatalx("%s", U_("the SUDOERS_BASE environment variable is not set and the -b option was not specified."));
+ }
+
+ if (output_file != NULL && strcmp(output_file, "-") != 0) {
+ if ((output_fp = fopen(output_file, "w")) == NULL)
+ sudo_fatal(U_("unable to open %s"), output_file);
+ }
+
+ /* Create a dictionary of already-seen users. */
+ seen_users = rbcreate(seen_user_compare);
+
+ /* Dump global Defaults in LDIF format. */
+ if (!ISSET(conf->suppress, SUPPRESS_DEFAULTS))
+ print_global_defaults_ldif(output_fp, parse_tree, conf->sudoers_base);
+
+ /* Dump User_Specs in LDIF format, expanding Aliases. */
+ if (!ISSET(conf->suppress, SUPPRESS_PRIVS))
+ print_userspecs_ldif(output_fp, parse_tree, conf);
+
+ /* Clean up. */
+ rbdestroy(seen_users, seen_user_free);
+
+ (void)fflush(output_fp);
+ if (ferror(output_fp))
+ ret = false;
+ if (output_fp != stdout)
+ fclose(output_fp);
+
+ debug_return_bool(ret);
+}
diff --git a/plugins/sudoers/cvtsudoers_merge.c b/plugins/sudoers/cvtsudoers_merge.c
new file mode 100644
index 0000000..d5e5b08
--- /dev/null
+++ b/plugins/sudoers/cvtsudoers_merge.c
@@ -0,0 +1,1247 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <sudoers.h>
+#include <redblack.h>
+#include <cvtsudoers.h>
+#include <gram.h>
+
+static struct member *
+new_member(const char *name, short type)
+{
+ struct member *m;
+ debug_decl(digest_list_equivalent, SUDOERS_DEBUG_PARSER);
+
+ m = calloc(1, sizeof(struct member));
+ if (m == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (name != NULL) {
+ m->name = strdup(name);
+ if (m->name == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ }
+ m->type = type;
+
+ debug_return_ptr(m);
+}
+
+/*
+ * Compare two digest lists.
+ * Returns true if they are the same, else false.
+ * XXX - should not care about order
+ */
+static bool
+digest_list_equivalent(struct command_digest_list *cdl1,
+ struct command_digest_list *cdl2)
+{
+ struct command_digest *cd1 = TAILQ_FIRST(cdl1);
+ struct command_digest *cd2 = TAILQ_FIRST(cdl2);
+ debug_decl(digest_list_equivalent, SUDOERS_DEBUG_PARSER);
+
+ while (cd1 != NULL && cd2 != NULL) {
+ if (cd1->digest_type != cd2->digest_type)
+ debug_return_bool(false);
+ if (strcmp(cd1->digest_str, cd2->digest_str) != 0)
+ debug_return_bool(false);
+ cd1 = TAILQ_NEXT(cd1, entries);
+ cd2 = TAILQ_NEXT(cd2, entries);
+ }
+
+ if (cd1 != NULL || cd2 != NULL)
+ debug_return_bool(false);
+ debug_return_bool(true);
+}
+
+/*
+ * Compare two members.
+ * Returns true if they are the same, else false.
+ */
+static bool
+member_equivalent(struct member *m1, struct member *m2)
+{
+ debug_decl(member_equivalent, SUDOERS_DEBUG_PARSER);
+
+ if (m1->type != m2->type || m1->negated != m2->negated)
+ debug_return_bool(false);
+
+ if (m1->type == COMMAND) {
+ struct sudo_command *c1 = (struct sudo_command *)m1->name;
+ struct sudo_command *c2 = (struct sudo_command *)m2->name;
+ if (c1->cmnd != NULL && c2->cmnd != NULL) {
+ if (strcmp(c1->cmnd, c2->cmnd) != 0)
+ debug_return_bool(false);
+ } else if (c1->cmnd != c2->cmnd) {
+ debug_return_bool(false);
+ }
+
+ if (c1->args != NULL && c2->args != NULL) {
+ if (strcmp(c1->args, c2->args) != 0)
+ debug_return_bool(false);
+ } else if (c1->args != c2->args) {
+ debug_return_bool(false);
+ }
+
+ if (!digest_list_equivalent(&c1->digests, &c2->digests)) {
+ debug_return_bool(false);
+ }
+ } else {
+ if (m1->name != NULL && m2->name != NULL) {
+ if (strcmp(m1->name, m2->name) != 0)
+ debug_return_bool(false);
+ } else if (m1->name != m2->name) {
+ debug_return_bool(false);
+ }
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Compare two members, m1 and m2.
+ * Returns true if m2 overrides m1, else false.
+ */
+static bool
+member_overridden(struct member *m1, struct member *m2, bool check_negated)
+{
+ debug_decl(member_overridden, SUDOERS_DEBUG_PARSER);
+
+ if (check_negated && m1->negated != m2->negated)
+ debug_return_bool(false);
+
+ /* "ALL" always wins (modulo digest). */
+ if (m2->type == ALL) {
+ if (m2->name != NULL) {
+ struct sudo_command *c1 = (struct sudo_command *)m1->name;
+ struct sudo_command *c2 = (struct sudo_command *)m2->name;
+ debug_return_bool(digest_list_equivalent(&c1->digests, &c2->digests));
+ }
+ debug_return_bool(true);
+ }
+
+ if (m1->type != m2->type)
+ debug_return_bool(false);
+
+ if (m1->type == COMMAND) {
+ struct sudo_command *c1 = (struct sudo_command *)m1->name;
+ struct sudo_command *c2 = (struct sudo_command *)m2->name;
+ if (strcmp(c1->cmnd, c2->cmnd) != 0)
+ debug_return_bool(false);
+
+ if (c1->args != NULL && c2->args != NULL) {
+ if (strcmp(c1->args, c2->args) != 0)
+ debug_return_bool(false);
+ } else if (c1->args != c2->args) {
+ debug_return_bool(false);
+ }
+
+ if (!digest_list_equivalent(&c1->digests, &c2->digests)) {
+ debug_return_bool(false);
+ }
+ } else {
+ if (strcmp(m1->name, m2->name) != 0)
+ debug_return_bool(false);
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Given two member lists, ml1 and ml2.
+ * Returns true if the every element of ml1 is overridden by ml2, else false.
+ */
+static bool
+member_list_override(struct member_list *ml1, struct member_list *ml2,
+ bool check_negated)
+{
+ struct member *m1, *m2;
+ debug_decl(member_list_override, SUDOERS_DEBUG_PARSER);
+
+ /* An empty member_list only overrides another empty list. */
+ if (TAILQ_EMPTY(ml2)) {
+ debug_return_bool(TAILQ_EMPTY(ml1));
+ }
+
+ /* Check whether each element of ml1 is also covered by ml2. */
+ TAILQ_FOREACH_REVERSE(m1, ml1, member_list, entries) {
+ bool overridden = false;
+ TAILQ_FOREACH_REVERSE(m2, ml2, member_list, entries) {
+ if (member_overridden(m1, m2, check_negated)) {
+ overridden = true;
+ break;
+ }
+ }
+ if (!overridden)
+ debug_return_bool(false);
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Compare two member lists.
+ * Returns true if they are the same, else false.
+ * XXX - should not care about order if things are not negated.
+ */
+static bool
+member_list_equivalent(struct member_list *ml1, struct member_list *ml2)
+{
+ struct member *m1 = TAILQ_FIRST(ml1);
+ struct member *m2 = TAILQ_FIRST(ml2);
+ debug_decl(member_list_equivalent, SUDOERS_DEBUG_PARSER);
+
+ while (m1 != NULL && m2 != NULL) {
+ if (!member_equivalent(m1, m2))
+ debug_return_bool(false);
+ m1 = TAILQ_NEXT(m1, entries);
+ m2 = TAILQ_NEXT(m2, entries);
+ }
+
+ if (m1 != NULL || m2 != NULL)
+ debug_return_bool(false);
+ debug_return_bool(true);
+}
+
+/*
+ * Attempt to simplify a host list.
+ * If a host list contains all hosts in bound_hosts, replace them with
+ * "ALL". Also prune hosts on either side of "ALL" when possible.
+ */
+static void
+simplify_host_list(struct member_list *hosts, const char *file, int line,
+ int column, struct member_list *bound_hosts)
+{
+ struct member *m, *n, *next;
+ bool logged = false;
+ debug_decl(simplify_host_list, SUDOERS_DEBUG_PARSER);
+
+ /*
+ * If all sudoers sources have an associated host, replace a
+ * list of those hosts with "ALL".
+ */
+ if (!TAILQ_EMPTY(bound_hosts)) {
+ TAILQ_FOREACH_REVERSE(n, bound_hosts, member_list, entries) {
+ TAILQ_FOREACH_REVERSE(m, hosts, member_list, entries) {
+ if (m->negated) {
+ /* Don't try to handled negated entries. */
+ m = NULL;
+ break;
+ }
+ if (m->type == n->type && strcmp(m->name, n->name) == 0) {
+ /* match */
+ break;
+ }
+ }
+ if (m == NULL) {
+ /* no match */
+ break;
+ }
+ }
+ if (n == NULL) {
+ /* found all hosts */
+ log_warnx(U_("%s:%d:%d: converting host list to ALL"),
+ file, line, column);
+ logged = true;
+
+ TAILQ_FOREACH_REVERSE(n, bound_hosts, member_list, entries) {
+ TAILQ_FOREACH_REVERSE_SAFE(m, hosts, member_list, entries, next) {
+ if (m->negated) {
+ /* Don't try to handled negated entries. */
+ m = NULL;
+ break;
+ }
+ if (m->type == n->type && strcmp(m->name, n->name) == 0) {
+ /* remove matching host */
+ TAILQ_REMOVE(hosts, m, entries);
+ free_member(m);
+ break;
+ }
+ }
+ }
+ m = new_member(NULL, ALL);
+ TAILQ_INSERT_TAIL(hosts, m, entries);
+ }
+ }
+
+ /*
+ * A host list that contains ALL with no negated entries past it
+ * is equivalent to a list containing just "ALL".
+ */
+ TAILQ_FOREACH_REVERSE(m, hosts, member_list, entries) {
+ if (m->negated) {
+ /* Don't try to handled negated entries. */
+ break;
+ }
+ if (m->type == ALL) {
+ /* Replace member list with a single ALL entry. */
+ if (!logged) {
+ log_warnx(U_("%s:%d:%d: converting host list to ALL"),
+ file, line, column);
+ }
+ TAILQ_REMOVE(hosts, m, entries);
+ free_members(hosts);
+ TAILQ_INSERT_TAIL(hosts, m, entries);
+ break;
+ }
+ }
+
+ debug_return;
+}
+
+/*
+ * Generate a unique name from old_name that is not used in parse_tree,
+ * subsequent parse_trees or merged_tree.
+ */
+static char *
+alias_make_unique(const char *old_name, short type,
+ struct sudoers_parse_tree *parse_tree0,
+ struct sudoers_parse_tree *merged_tree)
+{
+ struct sudoers_parse_tree *parse_tree;
+ char *cp, *new_name = NULL;
+ struct alias *a;
+ long long suffix;
+ size_t namelen;
+ debug_decl(alias_make_unique, SUDOERS_DEBUG_ALIAS);
+
+ /* If old_name already has a suffix, increment it, else start with "_1". */
+ suffix = 0;
+ namelen = strlen(old_name);
+ cp = strrchr(old_name, '_');
+ if (cp != NULL && isdigit((unsigned char)cp[1])) {
+ suffix = sudo_strtonum(cp + 1, 0, LLONG_MAX, NULL);
+ if (suffix != 0) {
+ namelen = (size_t)(cp - old_name);
+ }
+ }
+
+ for (;;) {
+ suffix++;
+ free(new_name);
+ if (asprintf(&new_name, "%.*s_%lld", (int)namelen, old_name, suffix) == -1)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ /* Make sure new_name is not already in use. */
+ a = alias_get(merged_tree, new_name, type);
+ if (a != NULL) {
+ alias_put(a);
+ continue;
+ }
+ parse_tree = parse_tree0;
+ while ((parse_tree = TAILQ_NEXT(parse_tree, entries)) != NULL) {
+ a = alias_get(parse_tree, new_name, type);
+ if (a != NULL) {
+ alias_put(a);
+ break;
+ }
+ }
+ if (a == NULL) {
+ /* Must be unique. */
+ break;
+ }
+ }
+
+ debug_return_ptr(new_name);
+}
+
+struct alias_rename_closure {
+ const char *old_name;
+ const char *new_name;
+ int type;
+};
+
+static int
+alias_rename_members(struct sudoers_parse_tree *parse_tree, struct alias *a,
+ void *v)
+{
+ struct alias_rename_closure *closure = v;
+ struct member *m;
+ debug_decl(alias_rename_members, SUDOERS_DEBUG_ALIAS);
+
+ if (a->type != closure->type)
+ debug_return_int(0);
+
+ /* Replace old_name in member list, if present. */
+ TAILQ_FOREACH(m, &a->members, entries) {
+ if (m->type == ALIAS && strcmp(m->name, closure->old_name) == 0) {
+ char *copy = strdup(closure->new_name);
+ if (copy == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ free(m->name);
+ m->name = copy;
+ }
+ }
+
+ debug_return_int(0);
+}
+
+static void
+alias_rename_defaults(const char *old_name, const char *new_name,
+ short alias_type, struct defaults_list *defaults)
+{
+ struct defaults *def, *def_next;
+ struct member *m;
+ debug_decl(alias_rename_defaults, SUDOERS_DEBUG_ALIAS);
+
+ TAILQ_FOREACH_SAFE(def, defaults, entries, def_next) {
+ /* Consecutive Defaults can share the same binding. */
+ if (def_next != NULL && def->binding == def_next->binding)
+ continue;
+
+ switch (def->type) {
+ case DEFAULTS_USER:
+ if (alias_type != USERALIAS)
+ continue;
+ break;
+ case DEFAULTS_RUNAS:
+ if (alias_type != RUNASALIAS)
+ continue;
+ break;
+ case DEFAULTS_HOST:
+ if (alias_type != HOSTALIAS)
+ continue;
+ break;
+ default:
+ continue;
+ }
+
+ /* Rename matching aliases in the binding's member_list. */
+ TAILQ_FOREACH(m, &def->binding->members, entries) {
+ if (m->type != ALIAS)
+ continue;
+ if (strcmp(m->name, old_name) == 0) {
+ char *copy = strdup(new_name);
+ if (copy == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ free(m->name);
+ m->name = copy;
+ }
+ }
+ }
+
+ debug_return;
+}
+
+static void
+alias_rename_member(const char *old_name, const char *new_name,
+ struct member *m)
+{
+ debug_decl(alias_rename_member, SUDOERS_DEBUG_ALIAS);
+
+ if (m->type == ALIAS && strcmp(m->name, old_name) == 0) {
+ char *copy = strdup(new_name);
+ if (copy == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ free(m->name);
+ m->name = copy;
+ }
+
+ debug_return;
+}
+
+static void
+alias_rename_member_list(const char *old_name, const char *new_name,
+ struct member_list *members)
+{
+ struct member *m;
+ debug_decl(alias_rename_member_list, SUDOERS_DEBUG_ALIAS);
+
+ TAILQ_FOREACH(m, members, entries) {
+ alias_rename_member(old_name, new_name, m);
+ }
+
+ debug_return;
+}
+
+static bool
+alias_rename_userspecs(const char *old_name, const char *new_name,
+ short alias_type, struct userspec_list *userspecs)
+{
+ struct privilege *priv;
+ struct cmndspec *cs;
+ struct userspec *us;
+ bool ret = true;
+ debug_decl(alias_rename_userspecs, SUDOERS_DEBUG_ALIAS);
+
+ TAILQ_FOREACH(us, userspecs, entries) {
+ if (alias_type == USERALIAS) {
+ alias_rename_member_list(old_name, new_name, &us->users);
+ }
+ TAILQ_FOREACH(priv, &us->privileges, entries) {
+ alias_rename_defaults(old_name, new_name, alias_type, &priv->defaults);
+ if (alias_type == HOSTALIAS) {
+ alias_rename_member_list(old_name, new_name, &priv->hostlist);
+ continue;
+ }
+ TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
+ if (alias_type == CMNDALIAS) {
+ alias_rename_member(old_name, new_name, cs->cmnd);
+ continue;
+ }
+ if (alias_type == RUNASALIAS) {
+ if (cs->runasuserlist != NULL) {
+ alias_rename_member_list(old_name, new_name, cs->runasuserlist);
+ }
+ if (cs->runasgrouplist != NULL) {
+ alias_rename_member_list(old_name, new_name, cs->runasgrouplist);
+ }
+ }
+ }
+ }
+ }
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Rename an alias in parse_tree and all the places where it is used.
+ */
+static bool
+alias_rename(const char *old_name, const char *new_name,
+ short alias_type, struct sudoers_parse_tree *parse_tree)
+{
+ struct alias_rename_closure closure = { old_name, new_name, alias_type };
+ struct alias *a;
+ debug_decl(alias_rename, SUDOERS_DEBUG_ALIAS);
+
+ /* Remove under old name and add via new to maintain tree properties. */
+ a = alias_remove(parse_tree, old_name, alias_type);
+ if (a == NULL) {
+ /* Should not happen. */
+ sudo_warnx(U_("unable to find alias %s"), old_name);
+ debug_return_bool(false);
+ }
+ log_warnx(U_("%s:%d:%d: renaming alias %s to %s"),
+ a->file, a->line, a->column, a->name, new_name);
+ free(a->name);
+ a->name = strdup(new_name);
+ if (a->name == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ switch (rbinsert(parse_tree->aliases, a, NULL)) {
+ case 0:
+ /* success */
+ break;
+ case 1:
+ /* Already present, should not happen. */
+ errno = EEXIST;
+ sudo_warn(U_("%s: %s"), __func__, a->name);
+ break;
+ default:
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ }
+
+ /* Rename it in the aliases tree itself (aliases can be nested). */
+ alias_apply(parse_tree, alias_rename_members, &closure);
+
+ /* Rename it in the Defaults list. */
+ alias_rename_defaults(old_name, new_name, alias_type, &parse_tree->defaults);
+
+ /* Rename it in the userspecs list. */
+ alias_rename_userspecs(old_name, new_name, alias_type, &parse_tree->userspecs);
+
+ debug_return_bool(true);
+}
+
+static int
+alias_resolve_conflicts(struct sudoers_parse_tree *parse_tree0, struct alias *a,
+ void *v)
+{
+ struct sudoers_parse_tree *parse_tree = parse_tree0;
+ struct sudoers_parse_tree *merged_tree = v;
+ char *new_name;
+ int ret;
+ debug_decl(alias_resolve_conflicts, SUDOERS_DEBUG_ALIAS);
+
+ /*
+ * Check for conflicting alias names in the subsequent sudoers files.
+ * Duplicates are removed and conflicting aliases are renamed.
+ * We cannot modify the alias tree that we are traversing.
+ */
+ while ((parse_tree = TAILQ_NEXT(parse_tree, entries)) != NULL) {
+ struct alias *b = alias_get(parse_tree, a->name, a->type);
+ if (b == NULL)
+ continue;
+
+ /* If alias 'b' is equivalent, remove it. */
+ alias_put(b);
+ if (member_list_equivalent(&a->members, &b->members)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "removing duplicate alias %s from %p", a->name, parse_tree);
+ b = alias_remove(parse_tree, a->name, a->type);
+ log_warnx(U_("%s:%d:%d: removing duplicate alias %s"),
+ b->file, b->line, b->column, b->name);
+ alias_free(b);
+ continue;
+ }
+
+ /* Rename alias 'b' to avoid a naming conflict. */
+ new_name = alias_make_unique(a->name, a->type, parse_tree, merged_tree);
+ alias_rename(a->name, new_name, a->type, parse_tree);
+ free(new_name);
+ }
+
+ /*
+ * The alias will exist in both the original and merged trees.
+ * This is not a problem as the caller will delete the old trees
+ * (without freeing the data).
+ */
+ ret = rbinsert(merged_tree->aliases, a, NULL);
+ switch (ret) {
+ case 0:
+ /* success */
+ break;
+ case 1:
+ /* already present, should not happen. */
+ errno = EEXIST;
+ sudo_warn(U_("%s: %s"), __func__, a->name);
+ break;
+ default:
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ }
+
+ debug_return_int(0);
+}
+
+static bool
+merge_aliases(struct sudoers_parse_tree_list *parse_trees,
+ struct sudoers_parse_tree *merged_tree)
+{
+ struct sudoers_parse_tree *parse_tree;
+ debug_decl(merge_aliases, SUDOERS_DEBUG_ALIAS);
+
+ /*
+ * For each parse_tree, check for collisions with alias names
+ * in subsequent parse trees. On collision, add a numbered
+ * suffix (e.g. ALIAS_1) to make the name unique and rename
+ * any uses of that alias in the affected parse_tree.
+ */
+ TAILQ_FOREACH(parse_tree, parse_trees, entries) {
+ if (parse_tree->aliases == NULL)
+ continue;
+
+ /*
+ * Resolve any conflicts in alias names, renaming aliases as
+ * needed and eliminating duplicates.
+ */
+ alias_apply(parse_tree, alias_resolve_conflicts, merged_tree);
+
+ /*
+ * Destroy the old alias tree without freeing the alias data
+ * which has been copied to merged_tree.
+ */
+ rbdestroy(parse_tree->aliases, NULL);
+ parse_tree->aliases = NULL;
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Compare two defaults structs but not their actual value.
+ * Returns true if they refer to the same Defaults variable and binding.
+ * Also sets mergeable if they only differ in the binding.
+ */
+static bool
+defaults_var_matches(struct defaults *d1, struct defaults *d2,
+ bool *mergeable)
+{
+ debug_decl(defaults_var_matches, SUDOERS_DEBUG_DEFAULTS);
+
+ if (strcmp(d1->var, d2->var) != 0)
+ debug_return_bool(false);
+ if (d1->type != d2->type) {
+ if ((d1->type == DEFAULTS && d2->type == DEFAULTS_HOST) ||
+ (d1->type == DEFAULTS_HOST && d2->type == DEFAULTS)) {
+ /* We can merge host and global bindings. */
+ if (mergeable != NULL)
+ *mergeable = true;
+ }
+ debug_return_bool(false);
+ }
+ if (d1->type != DEFAULTS) {
+ if (!member_list_equivalent(&d1->binding->members, &d2->binding->members)) {
+ if (mergeable != NULL)
+ *mergeable = true;
+ debug_return_bool(false);
+ }
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Compare the values of two defaults structs, which must be of the same type.
+ * Returns true if the value and operator match, else false.
+ */
+static bool
+defaults_val_matches(struct defaults *d1, struct defaults *d2)
+{
+ debug_decl(defaults_val_matches, SUDOERS_DEBUG_DEFAULTS);
+
+ /* XXX - what about list operators? */
+ if (d1->op != d2->op)
+ debug_return_bool(false);
+
+ /* Either both must be NULL or both non-NULL _and_ matching. */
+ if (d1->val != NULL && d2->val != NULL) {
+ if (strcmp(d1->val, d2->val) != 0)
+ debug_return_bool(false);
+ } else {
+ if (d1->val != NULL || d2->val != NULL)
+ debug_return_bool(false);
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Returns true if d1 is equivalent to d2, else false.
+ */
+static bool
+defaults_equivalent(struct defaults *d1, struct defaults *d2)
+{
+ debug_decl(defaults_equivalent, SUDOERS_DEBUG_DEFAULTS);
+
+ if (!defaults_var_matches(d1, d2, NULL))
+ debug_return_bool(false);
+ debug_return_bool(defaults_val_matches(d1, d2));
+}
+
+/*
+ * Returns true if dl1 is equivalent to dl2, else false.
+ */
+static bool
+defaults_list_equivalent(struct defaults_list *dl1, struct defaults_list *dl2)
+{
+ struct defaults *d1 = TAILQ_FIRST(dl1);
+ struct defaults *d2 = TAILQ_FIRST(dl2);
+ debug_decl(defaults_list_equivalent, SUDOERS_DEBUG_DEFAULTS);
+
+ while (d1 != NULL && d2 != NULL) {
+ if (!defaults_equivalent(d1, d2))
+ debug_return_bool(false);
+ d1 = TAILQ_NEXT(d1, entries);
+ d2 = TAILQ_NEXT(d2, entries);
+ }
+
+ if (d1 != NULL || d2 != NULL)
+ debug_return_bool(false);
+ debug_return_bool(true);
+}
+
+enum cvtsudoers_conflict {
+ CONFLICT_NONE,
+ CONFLICT_RESOLVED,
+ CONFLICT_UNRESOLVED
+};
+
+/*
+ * Check for duplicate and conflicting Defaults entries in later sudoers files.
+ * Returns true if we find a conflict or duplicate, else false.
+ */
+static enum cvtsudoers_conflict
+defaults_check_conflict(struct defaults *def,
+ struct sudoers_parse_tree *parse_tree0)
+{
+ struct sudoers_parse_tree *parse_tree = parse_tree0;
+ struct defaults *d;
+ debug_decl(defaults_check_conflict, SUDOERS_DEBUG_DEFAULTS);
+
+ while ((parse_tree = TAILQ_NEXT(parse_tree, entries)) != NULL) {
+ TAILQ_FOREACH_REVERSE(d, &parse_tree->defaults, defaults_list, entries) {
+ bool mergeable = false;
+
+ /*
+ * We currently only merge host-based Defaults but could do
+ * others as well. Lists in Defaults entries can be harder
+ * to read, especially command lists.
+ */
+ if (!defaults_var_matches(def, d, &mergeable)) {
+ if (!mergeable || (def->type != DEFAULTS && def->type != DEFAULTS_HOST))
+ continue;
+ }
+ if (defaults_val_matches(def, d)) {
+ /* Duplicate Defaults entry (may need to merge binding). */
+ if (mergeable) {
+ if (d->type != def->type &&
+ (d->type == DEFAULTS || def->type == DEFAULTS)) {
+ /*
+ * To be able to merge two Defaults, they both must
+ * have the same binding type. Convert a global
+ * Defaults to one bound to single "ALL" member.
+ */
+ if (d->type == DEFAULTS) {
+ struct member *m = new_member(NULL, ALL);
+ TAILQ_INSERT_TAIL(&d->binding->members, m, entries);
+ d->type = def->type;
+ }
+ if (def->type == DEFAULTS) {
+ struct member *m = new_member(NULL, ALL);
+ TAILQ_INSERT_TAIL(&def->binding->members, m, entries);
+ def->type = d->type;
+ }
+ }
+
+ /* Prepend def binding to d (hence double concat). */
+ TAILQ_CONCAT(&def->binding->members, &d->binding->members, entries);
+ TAILQ_CONCAT(&d->binding->members, &def->binding->members, entries);
+ }
+ debug_return_int(CONFLICT_RESOLVED);
+ }
+ /*
+ * If the value doesn't match but the Defaults name did we don't
+ * consider that a conflict.
+ */
+ if (!mergeable) {
+ log_warnx(U_("%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"),
+ def->file, def->line, def->column, def->var,
+ d->file, d->line, d->column);
+ debug_return_int(CONFLICT_UNRESOLVED);
+ }
+ }
+ }
+
+ debug_return_int(CONFLICT_NONE);
+}
+
+/*
+ * Merge Defaults entries in parse_trees and store the result in
+ * merged_tree. If a hostname was specified with the sudoers source,
+ * create a host-specific Defaults entry where possible.
+ * Returns true on success, else false.
+ */
+static bool
+merge_defaults(struct sudoers_parse_tree_list *parse_trees,
+ struct sudoers_parse_tree *merged_tree, struct member_list *bound_hosts)
+{
+ struct sudoers_parse_tree *parse_tree;
+ struct defaults *def;
+ struct member *m;
+ debug_decl(merge_defaults, SUDOERS_DEBUG_DEFAULTS);
+
+ TAILQ_FOREACH(parse_tree, parse_trees, entries) {
+ /*
+ * If parse_tree has a host name associated with it,
+ * try to make the Defaults setting host-specific.
+ */
+ TAILQ_FOREACH(def, &parse_tree->defaults, entries) {
+ if (parse_tree->lhost != NULL && def->type == DEFAULTS) {
+ m = new_member(parse_tree->lhost, WORD);
+ log_warnx(U_("%s:%d:%d: made Defaults \"%s\" specific to host %s"),
+ def->file, def->line, def->column, def->var,
+ parse_tree->lhost);
+ TAILQ_INSERT_TAIL(&def->binding->members, m, entries);
+ def->type = DEFAULTS_HOST;
+ }
+ }
+ }
+
+ TAILQ_FOREACH(parse_tree, parse_trees, entries) {
+ while ((def = TAILQ_FIRST(&parse_tree->defaults)) != NULL) {
+ /*
+ * Only add Defaults entry if not overridden by subsequent sudoers.
+ */
+ TAILQ_REMOVE(&parse_tree->defaults, def, entries);
+ switch (defaults_check_conflict(def, parse_tree)) {
+ case CONFLICT_NONE:
+ if (def->type != DEFAULTS_HOST) {
+ log_warnx(U_("%s:%d:%d: unable to make Defaults \"%s\" host-specific"),
+ def->file, def->line, def->column, def->var);
+ }
+ TAILQ_INSERT_TAIL(&merged_tree->defaults, def, entries);
+ break;
+ case CONFLICT_RESOLVED:
+ /* Duplicate or merged into a subsequent Defaults setting. */
+ free_default(def);
+ break;
+ case CONFLICT_UNRESOLVED:
+ log_warnx(U_("%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"),
+ def->file, def->line, def->column, def->var);
+ free_default(def);
+ break;
+ }
+ }
+ }
+
+ /*
+ * Simplify host lists in the merged Defaults.
+ */
+ TAILQ_FOREACH(def, &merged_tree->defaults, entries) {
+ /* TODO: handle refcnt != 1 */
+ if (def->type == DEFAULTS_HOST && def->binding->refcnt == 1) {
+ simplify_host_list(&def->binding->members, def->file, def->line,
+ def->column, bound_hosts);
+ m = TAILQ_FIRST(&def->binding->members);
+ if (m->type == ALL && !m->negated) {
+ if (TAILQ_NEXT(m, entries) == NULL) {
+ /* Convert Defaults@ALL -> Defaults */
+ def->type = DEFAULTS;
+ free_members(&def->binding->members);
+ TAILQ_INIT(&def->binding->members);
+ }
+ }
+ }
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Returns true if cs1 is equivalent to cs2, else false.
+ */
+static bool
+cmndspec_equivalent(struct cmndspec *cs1, struct cmndspec *cs2, bool check_negated)
+{
+ debug_decl(cmndspec_equivalent, SUDOERS_DEBUG_PARSER);
+
+ if (cs1->runasuserlist != NULL && cs2->runasuserlist != NULL) {
+ if (!member_list_override(cs1->runasuserlist, cs2->runasuserlist, check_negated))
+ debug_return_bool(false);
+ } else if (cs1->runasuserlist != cs2->runasuserlist) {
+ debug_return_bool(false);
+ }
+ if (cs1->runasgrouplist != NULL && cs2->runasgrouplist != NULL) {
+ if (!member_list_override(cs1->runasgrouplist, cs2->runasgrouplist, check_negated))
+ debug_return_bool(false);
+ } else if (cs1->runasgrouplist != cs2->runasgrouplist) {
+ debug_return_bool(false);
+ }
+ if (!member_equivalent(cs1->cmnd, cs2->cmnd))
+ debug_return_bool(false);
+ if (TAGS_CHANGED(cs1->tags, cs2->tags))
+ debug_return_bool(false);
+ if (cs1->timeout != cs2->timeout)
+ debug_return_bool(false);
+ if (cs1->notbefore != cs2->notbefore)
+ debug_return_bool(false);
+ if (cs1->notafter != cs2->notafter)
+ debug_return_bool(false);
+ if (cs1->runcwd != NULL && cs2->runcwd != NULL) {
+ if (strcmp(cs1->runcwd, cs2->runcwd) != 0)
+ debug_return_bool(false);
+ } else if (cs1->runcwd != cs2->runcwd) {
+ debug_return_bool(false);
+ }
+ if (cs1->runchroot != NULL && cs2->runchroot != NULL) {
+ if (strcmp(cs1->runchroot, cs2->runchroot) != 0)
+ debug_return_bool(false);
+ } else if (cs1->runchroot != cs2->runchroot) {
+ debug_return_bool(false);
+ }
+#ifdef HAVE_SELINUX
+ if (cs1->role != NULL && cs2->role != NULL) {
+ if (strcmp(cs1->role, cs2->role) != 0)
+ debug_return_bool(false);
+ } else if (cs1->role != cs2->role) {
+ debug_return_bool(false);
+ }
+ if (cs1->type != NULL && cs2->type != NULL) {
+ if (strcmp(cs1->type, cs2->type) != 0)
+ debug_return_bool(false);
+ } else if (cs1->type != cs2->type) {
+ debug_return_bool(false);
+ }
+#endif
+#ifdef HAVE_APPARMOR
+ if (cs1->apparmor_profile != NULL && cs2->apparmor_profile != NULL) {
+ if (strcmp(cs1->apparmor_profile, cs2->apparmor_profile) != 0)
+ debug_return_bool(false);
+ } else if (cs1->apparmor_profile != cs2->apparmor_profile) {
+ debug_return_bool(false);
+ }
+#endif
+#ifdef HAVE_PRIV_SET
+ if (cs1->privs != NULL && cs2->privs != NULL) {
+ if (strcmp(cs1->privs, cs2->privs) != 0)
+ debug_return_bool(false);
+ } else if (cs1->privs != cs2->privs) {
+ debug_return_bool(false);
+ }
+ if (cs1->limitprivs != NULL && cs2->limitprivs != NULL) {
+ if (strcmp(cs1->limitprivs, cs2->limitprivs) != 0)
+ debug_return_bool(false);
+ } else if (cs1->limitprivs != cs2->limitprivs) {
+ debug_return_bool(false);
+ }
+#endif
+
+ debug_return_bool(true);
+}
+
+/*
+ * Returns true if csl1 is equivalent to csl2, else false.
+ */
+static bool
+cmndspec_list_equivalent(struct cmndspec_list *csl1, struct cmndspec_list *csl2,
+ bool check_negated)
+{
+ struct cmndspec *cs1 = TAILQ_FIRST(csl1);
+ struct cmndspec *cs2 = TAILQ_FIRST(csl2);
+ debug_decl(cmndspec_list_equivalent, SUDOERS_DEBUG_PARSER);
+
+ while (cs1 != NULL && cs2 != NULL) {
+ if (!cmndspec_equivalent(cs1, cs2, check_negated))
+ debug_return_bool(false);
+ cs1 = TAILQ_NEXT(cs1, entries);
+ cs2 = TAILQ_NEXT(cs2, entries);
+ }
+
+ if (cs1 != NULL || cs2 != NULL)
+ debug_return_bool(false);
+ debug_return_bool(true);
+}
+
+/*
+ * Check whether userspec us1 is overridden by another sudoers file entry.
+ * If us1 and another userspec differ only in their host lists, merges
+ * the hosts from us1 into that userspec.
+ * Returns true if overridden, else false.
+ * TODO: merge privs
+ */
+static enum cvtsudoers_conflict
+userspec_overridden(struct userspec *us1,
+ struct sudoers_parse_tree *parse_tree, bool check_negated)
+{
+ struct userspec *us2;
+ bool hosts_differ = false;
+ debug_decl(userspec_overridden, SUDOERS_DEBUG_PARSER);
+
+ if (TAILQ_EMPTY(&parse_tree->userspecs))
+ debug_return_int(CONFLICT_NONE);
+
+ /* Sudoers rules are applied in reverse order (last match wins). */
+ TAILQ_FOREACH_REVERSE(us2, &parse_tree->userspecs, userspec_list, entries) {
+ struct privilege *priv1, *priv2;
+
+ if (!member_list_override(&us1->users, &us2->users, check_negated))
+ continue;
+
+ /* XXX - order should not matter */
+ priv1 = TAILQ_LAST(&us1->privileges, privilege_list);
+ priv2 = TAILQ_LAST(&us2->privileges, privilege_list);
+ while (priv1 != NULL && priv2 != NULL) {
+ if (!defaults_list_equivalent(&priv1->defaults, &priv2->defaults))
+ break;
+ if (!cmndspec_list_equivalent(&priv1->cmndlist, &priv2->cmndlist, check_negated))
+ break;
+
+ if (!member_list_override(&priv1->hostlist, &priv2->hostlist, check_negated))
+ hosts_differ = true;
+
+ priv1 = TAILQ_PREV(priv1, privilege_list, entries);
+ priv2 = TAILQ_PREV(priv2, privilege_list, entries);
+ }
+ if (priv1 != NULL || priv2 != NULL) {
+ /* mismatch */
+ continue;
+ }
+
+ /*
+ * If we have a match of everything except the host list,
+ * merge the differing host lists.
+ */
+ if (hosts_differ) {
+ priv1 = TAILQ_LAST(&us1->privileges, privilege_list);
+ priv2 = TAILQ_LAST(&us2->privileges, privilege_list);
+ while (priv1 != NULL && priv2 != NULL) {
+ if (!member_list_override(&priv1->hostlist, &priv2->hostlist, check_negated)) {
+ /*
+ * Priv matches but hosts differ, prepend priv1 hostlist
+ * to into priv2 hostlist (hence the double concat).
+ */
+ TAILQ_CONCAT(&priv1->hostlist, &priv2->hostlist, entries);
+ TAILQ_CONCAT(&priv2->hostlist, &priv1->hostlist, entries);
+ log_warnx(U_("%s:%d:%d: merging userspec into %s:%d:%d"),
+ us1->file, us1->line, us1->column,
+ us2->file, us2->line, us2->column);
+ }
+ priv1 = TAILQ_PREV(priv1, privilege_list, entries);
+ priv2 = TAILQ_PREV(priv2, privilege_list, entries);
+ }
+ debug_return_int(CONFLICT_RESOLVED);
+ }
+ debug_return_int(CONFLICT_UNRESOLVED);
+ }
+
+ debug_return_int(CONFLICT_NONE);
+}
+
+/*
+ * Check whether userspec us1 is overridden by another sudoers file entry.
+ * If us1 and another userspec differ only in their host lists, merges
+ * the hosts from us1 into that userspec.
+ * Returns true if overridden, else false.
+ */
+static enum cvtsudoers_conflict
+userspec_check_conflict(struct userspec *us1,
+ struct sudoers_parse_tree *parse_tree0)
+{
+ struct sudoers_parse_tree *parse_tree = parse_tree0;
+ debug_decl(userspec_check_conflict, SUDOERS_DEBUG_PARSER);
+
+ while ((parse_tree = TAILQ_NEXT(parse_tree, entries)) != NULL) {
+ enum cvtsudoers_conflict ret =
+ userspec_overridden(us1, parse_tree, false);
+ if (ret != CONFLICT_NONE)
+ debug_return_int(ret);
+ }
+
+ debug_return_int(CONFLICT_NONE);
+}
+
+/*
+ * Merge userspecs in parse_trees and store the result in merged_tree.
+ * If a hostname was specified with the sudoers source, make the
+ * privilege host-specific where possible.
+ * Returns true on success, else false.
+ */
+static bool
+merge_userspecs(struct sudoers_parse_tree_list *parse_trees,
+ struct sudoers_parse_tree *merged_tree, struct member_list *bound_hosts)
+{
+ struct sudoers_parse_tree *parse_tree;
+ struct userspec *us;
+ struct privilege *priv;
+ struct member *m;
+ debug_decl(merge_userspecs, SUDOERS_DEBUG_DEFAULTS);
+
+ /*
+ * If parse_tree has a host name associated with it,
+ * try to make the privilege host-specific.
+ */
+ TAILQ_FOREACH(parse_tree, parse_trees, entries) {
+ if (parse_tree->lhost == NULL)
+ continue;
+ TAILQ_FOREACH(us, &parse_tree->userspecs, entries) {
+ TAILQ_FOREACH(priv, &us->privileges, entries) {
+ TAILQ_FOREACH(m, &priv->hostlist, entries) {
+ /* We don't alter !ALL in a hostlist (XXX - should we?). */
+ if (m->type == ALL && !m->negated) {
+ m->type = WORD;
+ m->name = strdup(parse_tree->lhost);
+ if (m->name == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Prune out duplicate userspecs after substituting hostname(s).
+ * Traverse the list in reverse order--in sudoers last match wins.
+ * XXX - do this at the privilege/cmndspec level instead.
+ */
+ TAILQ_FOREACH(parse_tree, parse_trees, entries) {
+ while ((us = TAILQ_LAST(&parse_tree->userspecs, userspec_list)) != NULL) {
+ TAILQ_REMOVE(&parse_tree->userspecs, us, entries);
+ switch (userspec_check_conflict(us, parse_tree)) {
+ case CONFLICT_NONE:
+ TAILQ_INSERT_HEAD(&merged_tree->userspecs, us, entries);
+ break;
+ case CONFLICT_RESOLVED:
+ free_userspec(us);
+ break;
+ case CONFLICT_UNRESOLVED:
+ log_warnx(U_("%s:%d:%d: removing userspec overridden by subsequent entries"),
+ us->file, us->line, us->column);
+ free_userspec(us);
+ break;
+ }
+ }
+ }
+
+ /*
+ * Simplify member lists in the merged tree.
+ * Convert host lists with all hosts listed to "ALL" and
+ * collapse other entries around "ALL".
+ */
+ TAILQ_FOREACH_REVERSE(us, &merged_tree->userspecs, userspec_list, entries) {
+ TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
+ /* TODO: simplify other lists? */
+ simplify_host_list(&priv->hostlist, us->file, us->line, us->column,
+ bound_hosts);
+ }
+ }
+
+ debug_return_bool(true);
+}
+
+struct sudoers_parse_tree *
+merge_sudoers(struct sudoers_parse_tree_list *parse_trees,
+ struct sudoers_parse_tree *merged_tree)
+{
+ struct member_list bound_hosts = TAILQ_HEAD_INITIALIZER(bound_hosts);
+ struct sudoers_parse_tree *parse_tree;
+ debug_decl(merge_sudoers, SUDOERS_DEBUG_UTIL);
+
+ /*
+ * If all sudoers sources have a host associated with them, we
+ * can replace a list of those hosts with "ALL" in Defaults
+ * and userspecs.
+ */
+ TAILQ_FOREACH(parse_tree, parse_trees, entries) {
+ if (parse_tree->lhost == NULL)
+ break;
+ }
+ if (parse_tree == NULL) {
+ TAILQ_FOREACH(parse_tree, parse_trees, entries) {
+ struct member *m = new_member(parse_tree->lhost, WORD);
+ TAILQ_INSERT_TAIL(&bound_hosts, m, entries);
+ }
+ }
+
+ if ((merged_tree->aliases = alloc_aliases()) == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ if (!merge_aliases(parse_trees, merged_tree))
+ goto bad;
+
+ if (!merge_defaults(parse_trees, merged_tree, &bound_hosts))
+ goto bad;
+
+ if (!merge_userspecs(parse_trees, merged_tree, &bound_hosts))
+ goto bad;
+
+ free_members(&bound_hosts);
+ debug_return_ptr(merged_tree);
+bad:
+ free_members(&bound_hosts);
+ debug_return_ptr(NULL);
+}
diff --git a/plugins/sudoers/cvtsudoers_pwutil.c b/plugins/sudoers/cvtsudoers_pwutil.c
new file mode 100644
index 0000000..35ccbdd
--- /dev/null
+++ b/plugins/sudoers/cvtsudoers_pwutil.c
@@ -0,0 +1,484 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2007-2019
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <sudoers.h>
+#include <cvtsudoers.h>
+#include <pwutil.h>
+
+#ifndef LOGIN_NAME_MAX
+# ifdef _POSIX_LOGIN_NAME_MAX
+# define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX
+# else
+# define LOGIN_NAME_MAX 9
+# endif
+#endif /* LOGIN_NAME_MAX */
+
+#define FIELD_SIZE(src, name, size) \
+do { \
+ if ((src)->name) { \
+ size = strlen((src)->name) + 1; \
+ total += size; \
+ } else { \
+ size = 0; \
+ } \
+} while (0)
+
+#define FIELD_COPY(src, dst, name, size) \
+do { \
+ if ((src)->name) { \
+ memcpy(cp, (src)->name, size); \
+ (dst)->name = cp; \
+ cp += size; \
+ } \
+} while (0)
+
+/*
+ * Dynamically allocate space for a struct item plus the key and data
+ * elements. If name is non-NULL it is used as the key, else the
+ * uid is the key. Fills in datum from the users filter.
+ * Returns NULL on calloc error or unknown name/id, setting errno
+ * to ENOMEM or ENOENT respectively.
+ */
+struct cache_item *
+cvtsudoers_make_pwitem(uid_t uid, const char *name)
+{
+ char *cp, uidstr[STRLEN_MAX_UNSIGNED(uid_t) + 2];
+ size_t nsize, psize, gsize, dsize, ssize, total;
+#ifdef HAVE_LOGIN_CAP_H
+ size_t csize;
+#endif
+ struct cache_item_pw *pwitem;
+ struct passwd pw, *newpw;
+ struct sudoers_string *s = NULL;
+ debug_decl(cvtsudoers_make_pwitem, SUDOERS_DEBUG_NSS);
+
+ /* Look up name or uid in filter list. */
+ if (name != NULL) {
+ STAILQ_FOREACH(s, &filters->users, entries) {
+ if (strcasecmp(name, s->str) == 0) {
+ uid = (uid_t)-1;
+ break;
+ }
+ }
+ } else {
+ STAILQ_FOREACH(s, &filters->users, entries) {
+ const char *errstr;
+ uid_t filter_uid;
+
+ if (s->str[0] != '#')
+ continue;
+
+ filter_uid = sudo_strtoid(s->str + 1, &errstr);
+ if (errstr == NULL) {
+ if (uid != filter_uid)
+ continue;
+ (void)snprintf(uidstr, sizeof(uidstr), "#%u",
+ (unsigned int)uid);
+ break;
+ }
+ }
+ }
+ if (s == NULL) {
+ errno = ENOENT;
+ debug_return_ptr(NULL);
+ }
+
+ /* Fake up a passwd struct. */
+ memset(&pw, 0, sizeof(pw));
+ pw.pw_name = name ? s->str : uidstr;
+ pw.pw_passwd = (char *)"*";
+ pw.pw_uid = uid;
+ pw.pw_gid = (gid_t)-1;
+ pw.pw_shell = (char *)_PATH_BSHELL;
+ pw.pw_dir = (char *)"/";
+
+ /* Allocate in one big chunk for easy freeing. */
+ total = sizeof(*pwitem);
+ FIELD_SIZE(&pw, pw_name, nsize);
+ FIELD_SIZE(&pw, pw_passwd, psize);
+#ifdef HAVE_LOGIN_CAP_H
+ FIELD_SIZE(&pw, pw_class, csize);
+#endif
+ FIELD_SIZE(&pw, pw_gecos, gsize);
+ FIELD_SIZE(&pw, pw_dir, dsize);
+ FIELD_SIZE(&pw, pw_shell, ssize);
+ if (name != NULL)
+ total += strlen(name) + 1;
+
+ /* Allocate space for struct item, struct passwd and the strings. */
+ if ((pwitem = calloc(1, total)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+ newpw = &pwitem->pw;
+
+ /*
+ * Copy in passwd contents and make strings relative to space
+ * at the end of the struct.
+ */
+ memcpy(newpw, &pw, sizeof(pw));
+ cp = (char *)(pwitem + 1);
+ FIELD_COPY(&pw, newpw, pw_name, nsize);
+ FIELD_COPY(&pw, newpw, pw_passwd, psize);
+#ifdef HAVE_LOGIN_CAP_H
+ FIELD_COPY(&pw, newpw, pw_class, csize);
+#endif
+ FIELD_COPY(&pw, newpw, pw_gecos, gsize);
+ FIELD_COPY(&pw, newpw, pw_dir, dsize);
+ FIELD_COPY(&pw, newpw, pw_shell, ssize);
+
+ /* Set key and datum. */
+ if (name != NULL) {
+ memcpy(cp, name, strlen(name) + 1);
+ pwitem->cache.k.name = cp;
+ } else {
+ pwitem->cache.k.uid = pw.pw_uid;
+ }
+ pwitem->cache.d.pw = newpw;
+ pwitem->cache.refcnt = 1;
+
+ debug_return_ptr(&pwitem->cache);
+}
+
+/*
+ * Dynamically allocate space for a struct item plus the key and data
+ * elements. If name is non-NULL it is used as the key, else the
+ * gid is the key. Fills in datum from the groups filter.
+ * Returns NULL on calloc error or unknown name/id, setting errno
+ * to ENOMEM or ENOENT respectively.
+ */
+struct cache_item *
+cvtsudoers_make_gritem(gid_t gid, const char *name)
+{
+ char *cp, gidstr[STRLEN_MAX_UNSIGNED(gid_t) + 2];
+ size_t nsize, psize, total, len, nmem = 0;
+ struct cache_item_gr *gritem;
+ struct group gr, *newgr;
+ struct sudoers_string *s = NULL;
+ debug_decl(cvtsudoers_make_gritem, SUDOERS_DEBUG_NSS);
+
+ /* Look up name or gid in filter list. */
+ if (name != NULL) {
+ STAILQ_FOREACH(s, &filters->groups, entries) {
+ if (strcasecmp(name, s->str) == 0) {
+ gid = (gid_t)-1;
+ break;
+ }
+ }
+ } else {
+ STAILQ_FOREACH(s, &filters->groups, entries) {
+ const char *errstr;
+ gid_t filter_gid;
+
+ if (s->str[0] != '#')
+ continue;
+
+ filter_gid = sudo_strtoid(s->str + 1, &errstr);
+ if (errstr == NULL) {
+ if (gid != filter_gid)
+ continue;
+ (void)snprintf(gidstr, sizeof(gidstr), "#%u",
+ (unsigned int)gid);
+ break;
+ }
+ }
+ }
+ if (s == NULL) {
+ errno = ENOENT;
+ debug_return_ptr(NULL);
+ }
+
+ /* Fake up a group struct with all filter users as members. */
+ memset(&gr, 0, sizeof(gr));
+ gr.gr_name = name ? s->str : gidstr;
+ gr.gr_gid = gid;
+
+ /* Allocate in one big chunk for easy freeing. */
+ total = sizeof(*gritem);
+ FIELD_SIZE(&gr, gr_name, nsize);
+ FIELD_SIZE(&gr, gr_passwd, psize);
+ if (!STAILQ_EMPTY(&filters->users)) {
+ STAILQ_FOREACH(s, &filters->users, entries) {
+ total += strlen(s->str) + 1;
+ nmem++;
+ }
+ total += sizeof(char *) * nmem;
+ }
+ if (name != NULL)
+ total += strlen(name) + 1;
+
+ if ((gritem = calloc(1, total)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+
+ /*
+ * Copy in group contents and make strings relative to space
+ * at the end of the buffer. Note that gr_mem must come
+ * immediately after struct group to guarantee proper alignment.
+ */
+ newgr = &gritem->gr;
+ memcpy(newgr, &gr, sizeof(gr));
+ cp = (char *)(gritem + 1);
+ if (nmem != 0) {
+ newgr->gr_mem = (char **)cp;
+ cp += sizeof(char *) * nmem;
+ nmem = 0;
+ STAILQ_FOREACH(s, &filters->users, entries) {
+ len = strlen(s->str) + 1;
+ memcpy(cp, s->str, len);
+ newgr->gr_mem[nmem++] = cp;
+ cp += len;
+ }
+ newgr->gr_mem[nmem] = NULL;
+ }
+ FIELD_COPY(&gr, newgr, gr_passwd, psize);
+ FIELD_COPY(&gr, newgr, gr_name, nsize);
+
+ /* Set key and datum. */
+ if (name != NULL) {
+ memcpy(cp, name, strlen(name) + 1);
+ gritem->cache.k.name = cp;
+ } else {
+ gritem->cache.k.gid = gr.gr_gid;
+ }
+ gritem->cache.d.gr = newgr;
+ gritem->cache.refcnt = 1;
+
+ debug_return_ptr(&gritem->cache);
+}
+
+static struct cache_item_gidlist *gidlist_item;
+
+/*
+ * Dynamically allocate space for a struct item plus the key and data
+ * elements. Fills in datum from the groups filter.
+ */
+struct cache_item *
+cvtsudoers_make_gidlist_item(const struct passwd *pw, int unused1,
+ GETGROUPS_T *unused2, char * const *unused3, unsigned int type)
+{
+ char *cp;
+ size_t nsize, total;
+ struct cache_item_gidlist *glitem;
+ struct sudoers_string *s;
+ struct gid_list *gidlist;
+ GETGROUPS_T *gids = NULL;
+ int i, ngids = 0;
+ debug_decl(cvtsudoers_make_gidlist_item, SUDOERS_DEBUG_NSS);
+
+ /*
+ * There's only a single gid list.
+ */
+ if (gidlist_item != NULL) {
+ gidlist_item->cache.refcnt++;
+ debug_return_ptr(&gidlist_item->cache);
+ }
+
+ /* Count number of possible gids in the filter. */
+ STAILQ_FOREACH(s, &filters->groups, entries) {
+ if (s->str[0] == '#')
+ ngids++;
+ }
+
+ /* Allocate gids[] array and fill it with parsed gids. */
+ if (ngids != 0) {
+ gids = reallocarray(NULL, (size_t)ngids, sizeof(GETGROUPS_T));
+ if (gids == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+ ngids = 0;
+ STAILQ_FOREACH(s, &filters->groups, entries) {
+ if (s->str[0] == '#') {
+ const char *errstr;
+ gid_t gid = sudo_strtoid(s->str + 1, &errstr);
+ if (errstr == NULL) {
+ /* Valid gid. */
+ gids[ngids++] = gid;
+ }
+ }
+ }
+ }
+ if (ngids == 0) {
+ free(gids);
+ errno = ENOENT;
+ debug_return_ptr(NULL);
+ }
+
+ /* Allocate in one big chunk for easy freeing. */
+ nsize = strlen(pw->pw_name) + 1;
+ total = sizeof(*glitem) + nsize;
+ total += sizeof(gid_t *) * (size_t)ngids;
+
+ if ((glitem = calloc(1, total)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ free(gids);
+ debug_return_ptr(NULL);
+ }
+
+ /*
+ * Copy in group list and make pointers relative to space
+ * at the end of the buffer. Note that the groups array must come
+ * immediately after struct group to guarantee proper alignment.
+ */
+ gidlist = &glitem->gidlist;
+ cp = (char *)(glitem + 1);
+ gidlist->gids = (gid_t *)cp;
+ cp += sizeof(gid_t) * (size_t)ngids;
+
+ /* Set key and datum. */
+ memcpy(cp, pw->pw_name, nsize);
+ glitem->cache.k.name = cp;
+ glitem->cache.d.gidlist = gidlist;
+ glitem->cache.refcnt = 1;
+ glitem->cache.type = type;
+
+ /*
+ * Store group IDs.
+ */
+ for (i = 0; i < ngids; i++)
+ gidlist->gids[i] = gids[i];
+ gidlist->ngids = ngids;
+ free(gids);
+
+ debug_return_ptr(&glitem->cache);
+}
+
+static struct cache_item_gidlist *grlist_item;
+
+/*
+ * Dynamically allocate space for a struct item plus the key and data
+ * elements. Fills in group names from the groups filter.
+ */
+struct cache_item *
+cvtsudoers_make_grlist_item(const struct passwd *pw, char * const *unused1)
+{
+ char *cp;
+ size_t nsize, ngroups, total, len;
+ struct cache_item_grlist *grlitem;
+ struct sudoers_string *s;
+ struct group_list *grlist;
+ size_t groupname_len;
+ debug_decl(cvtsudoers_make_grlist_item, SUDOERS_DEBUG_NSS);
+
+ /*
+ * There's only a single group list.
+ */
+ if (grlist_item != NULL) {
+ grlist_item->cache.refcnt++;
+ debug_return_ptr(&grlist_item->cache);
+ }
+
+ /* Count number of groups in the filter. */
+ ngroups = 0;
+ STAILQ_FOREACH(s, &filters->groups, entries) {
+ ngroups++;
+ }
+
+#ifdef _SC_LOGIN_NAME_MAX
+ groupname_len = (size_t)MAX(sysconf(_SC_LOGIN_NAME_MAX), 32);
+#else
+ groupname_len = MAX(LOGIN_NAME_MAX, 32);
+#endif
+
+ /* Allocate in one big chunk for easy freeing. */
+ nsize = strlen(pw->pw_name) + 1;
+ total = sizeof(*grlitem) + nsize;
+ total += groupname_len * ngroups;
+
+again:
+ if ((grlitem = calloc(1, total)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+
+ /*
+ * Copy in group list and make pointers relative to space
+ * at the end of the buffer. Note that the groups array must come
+ * immediately after struct group to guarantee proper alignment.
+ */
+ grlist = &grlitem->grlist;
+ cp = (char *)(grlitem + 1);
+ grlist->groups = (char **)cp;
+ cp += sizeof(char *) * ngroups;
+
+ /* Set key and datum. */
+ memcpy(cp, pw->pw_name, nsize);
+ grlitem->cache.k.name = cp;
+ grlitem->cache.d.grlist = grlist;
+ grlitem->cache.refcnt = 1;
+ cp += nsize;
+
+ /*
+ * Copy groups from filter.
+ */
+ ngroups = 0;
+ STAILQ_FOREACH(s, &filters->groups, entries) {
+ if (s->str[0] == '#') {
+ const char *errstr;
+ sudo_strtoid(s->str + 1, &errstr);
+ if (errstr == NULL) {
+ /* Group ID not name, ignore it. */
+ continue;
+ }
+ }
+ len = strlen(s->str) + 1;
+ if ((size_t)(cp - (char *)grlitem) + len > total) {
+ total += len + groupname_len;
+ free(grlitem);
+ goto again;
+ }
+ memcpy(cp, s->str, len);
+ grlist->groups[ngroups++] = cp;
+ cp += len;
+ }
+ grlist->ngroups = (int)ngroups;
+
+ debug_return_ptr(&grlitem->cache);
+}
diff --git a/plugins/sudoers/def_data.c b/plugins/sudoers/def_data.c
new file mode 100644
index 0000000..b8c1212
--- /dev/null
+++ b/plugins/sudoers/def_data.c
@@ -0,0 +1,701 @@
+/* generated file, do not edit */
+
+static struct def_values def_data_lecture[] = {
+ { "never", never },
+ { "once", once },
+ { "always", always },
+ { NULL, 0 },
+};
+
+static struct def_values def_data_listpw[] = {
+ { "never", never },
+ { "any", any },
+ { "all", all },
+ { "always", always },
+ { NULL, 0 },
+};
+
+static struct def_values def_data_verifypw[] = {
+ { "never", never },
+ { "all", all },
+ { "any", any },
+ { "always", always },
+ { NULL, 0 },
+};
+
+static struct def_values def_data_fdexec[] = {
+ { "never", never },
+ { "digest_only", digest_only },
+ { "always", always },
+ { NULL, 0 },
+};
+
+static struct def_values def_data_timestamp_type[] = {
+ { "global", global },
+ { "ppid", ppid },
+ { "tty", tty },
+ { "kernel", kernel },
+ { NULL, 0 },
+};
+
+static struct def_values def_data_log_format[] = {
+ { "sudo", sudo },
+ { "json", json },
+ { NULL, 0 },
+};
+
+static struct def_values def_data_intercept_type[] = {
+ { "dso", dso },
+ { "trace", trace },
+ { NULL, 0 },
+};
+
+struct sudo_defs_types sudo_defs_table[] = {
+ {
+ "syslog", T_LOGFAC|T_BOOL,
+ N_("Syslog facility if syslog is being used for logging: %s"),
+ NULL,
+ }, {
+ "syslog_goodpri", T_LOGPRI|T_BOOL,
+ N_("Syslog priority to use when user authenticates successfully: %s"),
+ NULL,
+ }, {
+ "syslog_badpri", T_LOGPRI|T_BOOL,
+ N_("Syslog priority to use when user authenticates unsuccessfully: %s"),
+ NULL,
+ }, {
+ "long_otp_prompt", T_FLAG,
+ N_("Put OTP prompt on its own line"),
+ NULL,
+ }, {
+ "ignore_dot", T_FLAG,
+ N_("Ignore '.' in $PATH"),
+ NULL,
+ }, {
+ "mail_always", T_FLAG,
+ N_("Always send mail when sudo is run"),
+ NULL,
+ }, {
+ "mail_badpass", T_FLAG,
+ N_("Send mail if user authentication fails"),
+ NULL,
+ }, {
+ "mail_no_user", T_FLAG,
+ N_("Send mail if the user is not in sudoers"),
+ NULL,
+ }, {
+ "mail_no_host", T_FLAG,
+ N_("Send mail if the user is not in sudoers for this host"),
+ NULL,
+ }, {
+ "mail_no_perms", T_FLAG,
+ N_("Send mail if the user is not allowed to run a command"),
+ NULL,
+ }, {
+ "mail_all_cmnds", T_FLAG,
+ N_("Send mail if the user tries to run a command"),
+ NULL,
+ }, {
+ "tty_tickets", T_FLAG,
+ N_("Use a separate timestamp for each user/tty combo"),
+ NULL,
+ }, {
+ "lecture", T_TUPLE|T_BOOL,
+ N_("Lecture user the first time they run sudo"),
+ def_data_lecture,
+ }, {
+ "lecture_file", T_STR|T_PATH|T_BOOL,
+ N_("File containing the sudo lecture: %s"),
+ NULL,
+ }, {
+ "authenticate", T_FLAG,
+ N_("Require users to authenticate by default"),
+ NULL,
+ }, {
+ "root_sudo", T_FLAG,
+ N_("Root may run sudo"),
+ NULL,
+ }, {
+ "log_host", T_FLAG,
+ N_("Log the hostname in the (non-syslog) log file"),
+ NULL,
+ }, {
+ "log_year", T_FLAG,
+ N_("Log the year in the (non-syslog) log file"),
+ NULL,
+ }, {
+ "shell_noargs", T_FLAG,
+ N_("If sudo is invoked with no arguments, start a shell"),
+ NULL,
+ }, {
+ "set_home", T_FLAG,
+ N_("Set $HOME to the target user when starting a shell with -s"),
+ NULL,
+ }, {
+ "always_set_home", T_FLAG,
+ N_("Always set $HOME to the target user's home directory"),
+ NULL,
+ }, {
+ "path_info", T_FLAG,
+ N_("Allow some information gathering to give useful error messages"),
+ NULL,
+ }, {
+ "fqdn", T_FLAG,
+ N_("Require fully-qualified hostnames in the sudoers file"),
+ NULL,
+ }, {
+ "insults", T_FLAG,
+ N_("Insult the user when they enter an incorrect password"),
+ NULL,
+ }, {
+ "requiretty", T_FLAG,
+ N_("Only allow the user to run sudo if they have a tty"),
+ NULL,
+ }, {
+ "env_editor", T_FLAG,
+ N_("Visudo will honor the EDITOR environment variable"),
+ NULL,
+ }, {
+ "rootpw", T_FLAG,
+ N_("Prompt for root's password, not the users's"),
+ NULL,
+ }, {
+ "runaspw", T_FLAG,
+ N_("Prompt for the runas_default user's password, not the users's"),
+ NULL,
+ }, {
+ "targetpw", T_FLAG,
+ N_("Prompt for the target user's password, not the users's"),
+ NULL,
+ }, {
+ "use_loginclass", T_FLAG,
+ N_("Apply defaults in the target user's login class if there is one"),
+ NULL,
+ }, {
+ "set_logname", T_FLAG,
+ N_("Set the LOGNAME and USER environment variables"),
+ NULL,
+ }, {
+ "stay_setuid", T_FLAG,
+ N_("Only set the effective uid to the target user, not the real uid"),
+ NULL,
+ }, {
+ "preserve_groups", T_FLAG,
+ N_("Don't initialize the group vector to that of the target user"),
+ NULL,
+ }, {
+ "loglinelen", T_UINT|T_BOOL,
+ N_("Length at which to wrap log file lines (0 for no wrap): %u"),
+ NULL,
+ }, {
+ "timestamp_timeout", T_TIMESPEC|T_BOOL,
+ N_("Authentication timestamp timeout: %.1f minutes"),
+ NULL,
+ }, {
+ "passwd_timeout", T_TIMESPEC|T_BOOL,
+ N_("Password prompt timeout: %.1f minutes"),
+ NULL,
+ }, {
+ "passwd_tries", T_UINT,
+ N_("Number of tries to enter a password: %u"),
+ NULL,
+ }, {
+ "umask", T_MODE|T_BOOL,
+ N_("Umask to use or 0777 to use user's: 0%o"),
+ NULL,
+ }, {
+ "logfile", T_STR|T_BOOL|T_PATH,
+ N_("Path to log file: %s"),
+ NULL,
+ }, {
+ "mailerpath", T_STR|T_BOOL|T_PATH,
+ N_("Path to mail program: %s"),
+ NULL,
+ }, {
+ "mailerflags", T_STR|T_BOOL,
+ N_("Flags for mail program: %s"),
+ NULL,
+ }, {
+ "mailto", T_STR|T_BOOL,
+ N_("Address to send mail to: %s"),
+ NULL,
+ }, {
+ "mailfrom", T_STR|T_BOOL,
+ N_("Address to send mail from: %s"),
+ NULL,
+ }, {
+ "mailsub", T_STR,
+ N_("Subject line for mail messages: %s"),
+ NULL,
+ }, {
+ "badpass_message", T_STR,
+ N_("Incorrect password message: %s"),
+ NULL,
+ }, {
+ "lecture_status_dir", T_STR|T_PATH,
+ N_("Path to lecture status dir: %s"),
+ NULL,
+ }, {
+ "timestampdir", T_STR|T_PATH,
+ N_("Path to authentication timestamp dir: %s"),
+ NULL,
+ }, {
+ "timestampowner", T_STR,
+ N_("Owner of the authentication timestamp dir: %s"),
+ NULL,
+ }, {
+ "exempt_group", T_STR|T_BOOL,
+ N_("Users in this group are exempt from password and PATH requirements: %s"),
+ NULL,
+ }, {
+ "passprompt", T_STR,
+ N_("Default password prompt: %s"),
+ NULL,
+ }, {
+ "passprompt_override", T_FLAG,
+ N_("If set, passprompt will override system prompt in all cases."),
+ NULL,
+ }, {
+ "runas_default", T_STR,
+ N_("Default user to run commands as: %s"),
+ NULL,
+ }, {
+ "secure_path", T_STR|T_BOOL,
+ N_("Value to override user's $PATH with: %s"),
+ NULL,
+ }, {
+ "editor", T_STR|T_PATH,
+ N_("Path to the editor for use by visudo: %s"),
+ NULL,
+ }, {
+ "listpw", T_TUPLE|T_BOOL,
+ N_("When to require a password for 'list' pseudocommand: %s"),
+ def_data_listpw,
+ }, {
+ "verifypw", T_TUPLE|T_BOOL,
+ N_("When to require a password for 'verify' pseudocommand: %s"),
+ def_data_verifypw,
+ }, {
+ "noexec", T_FLAG,
+ N_("Preload the sudo_noexec library which replaces the exec functions"),
+ NULL,
+ }, {
+ "ignore_local_sudoers", T_FLAG,
+ N_("If LDAP directory is up, do we ignore local sudoers file"),
+ NULL,
+ }, {
+ "closefrom", T_INT,
+ N_("File descriptors >= %d will be closed before executing a command"),
+ NULL,
+ }, {
+ "closefrom_override", T_FLAG,
+ N_("If set, users may override the value of \"closefrom\" with the -C option"),
+ NULL,
+ }, {
+ "setenv", T_FLAG,
+ N_("Allow users to set arbitrary environment variables"),
+ NULL,
+ }, {
+ "env_reset", T_FLAG,
+ N_("Reset the environment to a default set of variables"),
+ NULL,
+ }, {
+ "env_check", T_LIST|T_BOOL,
+ N_("Environment variables to check for safety:"),
+ NULL,
+ }, {
+ "env_delete", T_LIST|T_BOOL,
+ N_("Environment variables to remove:"),
+ NULL,
+ }, {
+ "env_keep", T_LIST|T_BOOL,
+ N_("Environment variables to preserve:"),
+ NULL,
+ }, {
+ "role", T_STR,
+ N_("SELinux role to use in the new security context: %s"),
+ NULL,
+ }, {
+ "type", T_STR,
+ N_("SELinux type to use in the new security context: %s"),
+ NULL,
+ }, {
+ "env_file", T_STR|T_PATH|T_BOOL,
+ N_("Path to the sudo-specific environment file: %s"),
+ NULL,
+ }, {
+ "restricted_env_file", T_STR|T_PATH|T_BOOL,
+ N_("Path to the restricted sudo-specific environment file: %s"),
+ NULL,
+ }, {
+ "sudoers_locale", T_STR,
+ N_("Locale to use while parsing sudoers: %s"),
+ NULL,
+ }, {
+ "visiblepw", T_FLAG,
+ N_("Allow sudo to prompt for a password even if it would be visible"),
+ NULL,
+ }, {
+ "pwfeedback", T_FLAG,
+ N_("Provide visual feedback at the password prompt when there is user input"),
+ NULL,
+ }, {
+ "fast_glob", T_FLAG,
+ N_("Use faster globbing that is less accurate but does not access the filesystem"),
+ NULL,
+ }, {
+ "umask_override", T_FLAG,
+ N_("The umask specified in sudoers will override the user's, even if it is more permissive"),
+ NULL,
+ }, {
+ "log_input", T_FLAG,
+ N_("Log user's input for the command being run"),
+ NULL,
+ }, {
+ "log_stdin", T_FLAG,
+ N_("Log the command's standard input if not connected to a terminal"),
+ NULL,
+ }, {
+ "log_ttyin", T_FLAG,
+ N_("Log the user's terminal input for the command being run"),
+ NULL,
+ }, {
+ "log_output", T_FLAG,
+ N_("Log the output of the command being run"),
+ NULL,
+ }, {
+ "log_stdout", T_FLAG,
+ N_("Log the command's standard output if not connected to a terminal"),
+ NULL,
+ }, {
+ "log_stderr", T_FLAG,
+ N_("Log the command's standard error if not connected to a terminal"),
+ NULL,
+ }, {
+ "log_ttyout", T_FLAG,
+ N_("Log the terminal output of the command being run"),
+ NULL,
+ }, {
+ "compress_io", T_FLAG,
+ N_("Compress I/O logs using zlib"),
+ NULL,
+ }, {
+ "use_pty", T_FLAG,
+ N_("Always run commands in a pseudo-tty"),
+ NULL,
+ }, {
+ "group_plugin", T_STR,
+ N_("Plugin for non-Unix group support: %s"),
+ NULL,
+ }, {
+ "iolog_dir", T_STR|T_PATH,
+ N_("Directory in which to store input/output logs: %s"),
+ NULL,
+ }, {
+ "iolog_file", T_STR,
+ N_("File in which to store the input/output log: %s"),
+ NULL,
+ }, {
+ "set_utmp", T_FLAG,
+ N_("Add an entry to the utmp/utmpx file when allocating a pty"),
+ NULL,
+ }, {
+ "utmp_runas", T_FLAG,
+ N_("Set the user in utmp to the runas user, not the invoking user"),
+ NULL,
+ }, {
+ "privs", T_STR,
+ N_("Set of permitted privileges: %s"),
+ NULL,
+ }, {
+ "limitprivs", T_STR,
+ N_("Set of limit privileges: %s"),
+ NULL,
+ }, {
+ "exec_background", T_FLAG,
+ N_("Run commands on a pty in the background"),
+ NULL,
+ }, {
+ "pam_service", T_STR,
+ N_("PAM service name to use: %s"),
+ NULL,
+ }, {
+ "pam_login_service", T_STR,
+ N_("PAM service name to use for login shells: %s"),
+ NULL,
+ }, {
+ "pam_askpass_service", T_STR,
+ N_("PAM service name to use when sudo is run with the -A option: %s"),
+ NULL,
+ }, {
+ "pam_setcred", T_FLAG,
+ N_("Attempt to establish PAM credentials for the target user"),
+ NULL,
+ }, {
+ "pam_session", T_FLAG,
+ N_("Create a new PAM session for the command to run in"),
+ NULL,
+ }, {
+ "pam_acct_mgmt", T_FLAG,
+ N_("Perform PAM account validation management"),
+ NULL,
+ }, {
+ "maxseq", T_STR,
+ N_("Maximum I/O log sequence number: %s"),
+ NULL,
+ }, {
+ "use_netgroups", T_FLAG,
+ N_("Enable sudoers netgroup support"),
+ NULL,
+ }, {
+ "sudoedit_checkdir", T_FLAG,
+ N_("Check parent directories for writability when editing files with sudoedit"),
+ NULL,
+ }, {
+ "sudoedit_follow", T_FLAG,
+ N_("Follow symbolic links when editing files with sudoedit"),
+ NULL,
+ }, {
+ "always_query_group_plugin", T_FLAG,
+ N_("Query the group plugin for unknown system groups"),
+ NULL,
+ }, {
+ "netgroup_tuple", T_FLAG,
+ N_("Match netgroups based on the entire tuple: user, host and domain"),
+ NULL,
+ }, {
+ "ignore_audit_errors", T_FLAG,
+ N_("Allow commands to be run even if sudo cannot write to the audit log"),
+ NULL,
+ }, {
+ "ignore_iolog_errors", T_FLAG,
+ N_("Allow commands to be run even if sudo cannot write to the I/O log"),
+ NULL,
+ }, {
+ "ignore_logfile_errors", T_FLAG,
+ N_("Allow commands to be run even if sudo cannot write to the log file"),
+ NULL,
+ }, {
+ "match_group_by_gid", T_FLAG,
+ N_("Resolve groups in sudoers and match on the group ID, not the name"),
+ NULL,
+ }, {
+ "syslog_maxlen", T_UINT,
+ N_("Log entries larger than this value will be split into multiple syslog messages: %u"),
+ NULL,
+ }, {
+ "iolog_user", T_STR|T_BOOL,
+ N_("User that will own the I/O log files: %s"),
+ NULL,
+ }, {
+ "iolog_group", T_STR|T_BOOL,
+ N_("Group that will own the I/O log files: %s"),
+ NULL,
+ }, {
+ "iolog_mode", T_MODE,
+ N_("File mode to use for the I/O log files: 0%o"),
+ NULL,
+ }, {
+ "fdexec", T_TUPLE|T_BOOL,
+ N_("Execute commands by file descriptor instead of by path: %s"),
+ def_data_fdexec,
+ }, {
+ "ignore_unknown_defaults", T_FLAG,
+ N_("Ignore unknown Defaults entries in sudoers instead of producing a warning"),
+ NULL,
+ }, {
+ "command_timeout", T_TIMEOUT|T_BOOL,
+ N_("Time in seconds after which the command will be terminated: %u"),
+ NULL,
+ }, {
+ "user_command_timeouts", T_FLAG,
+ N_("Allow the user to specify a timeout on the command line"),
+ NULL,
+ }, {
+ "iolog_flush", T_FLAG,
+ N_("Flush I/O log data to disk immediately instead of buffering it"),
+ NULL,
+ }, {
+ "syslog_pid", T_FLAG,
+ N_("Include the process ID when logging via syslog"),
+ NULL,
+ }, {
+ "timestamp_type", T_TUPLE,
+ N_("Type of authentication timestamp record: %s"),
+ def_data_timestamp_type,
+ }, {
+ "authfail_message", T_STR,
+ N_("Authentication failure message: %s"),
+ NULL,
+ }, {
+ "case_insensitive_user", T_FLAG,
+ N_("Ignore case when matching user names"),
+ NULL,
+ }, {
+ "case_insensitive_group", T_FLAG,
+ N_("Ignore case when matching group names"),
+ NULL,
+ }, {
+ "log_allowed", T_FLAG,
+ N_("Log when a command is allowed by sudoers"),
+ NULL,
+ }, {
+ "log_denied", T_FLAG,
+ N_("Log when a command is denied by sudoers"),
+ NULL,
+ }, {
+ "log_servers", T_LIST|T_BOOL,
+ N_("Sudo log server(s) to connect to with optional port"),
+ NULL,
+ }, {
+ "log_server_timeout", T_TIMEOUT|T_BOOL,
+ N_("Sudo log server timeout in seconds: %u"),
+ NULL,
+ }, {
+ "log_server_keepalive", T_FLAG,
+ N_("Enable SO_KEEPALIVE socket option on the socket connected to the logserver"),
+ NULL,
+ }, {
+ "log_server_cabundle", T_STR|T_BOOL|T_PATH,
+ N_("Path to the audit server's CA bundle file: %s"),
+ NULL,
+ }, {
+ "log_server_peer_cert", T_STR|T_BOOL|T_PATH,
+ N_("Path to the sudoers certificate file: %s"),
+ NULL,
+ }, {
+ "log_server_peer_key", T_STR|T_BOOL|T_PATH,
+ N_("Path to the sudoers private key file: %s"),
+ NULL,
+ }, {
+ "log_server_verify", T_FLAG,
+ N_("Verify that the log server's certificate is valid"),
+ NULL,
+ }, {
+ "runas_allow_unknown_id", T_FLAG,
+ N_("Allow the use of unknown runas user and/or group ID"),
+ NULL,
+ }, {
+ "runas_check_shell", T_FLAG,
+ N_("Only permit running commands as a user with a valid shell"),
+ NULL,
+ }, {
+ "pam_ruser", T_FLAG,
+ N_("Set the pam remote user to the user running sudo"),
+ NULL,
+ }, {
+ "pam_rhost", T_FLAG,
+ N_("Set the pam remote host to the local host name"),
+ NULL,
+ }, {
+ "runcwd", T_STR|T_BOOL|T_CHPATH,
+ N_("Working directory to change to before executing the command: %s"),
+ NULL,
+ }, {
+ "runchroot", T_STR|T_BOOL|T_CHPATH,
+ N_("Root directory to change to before executing the command: %s"),
+ NULL,
+ }, {
+ "log_format", T_TUPLE,
+ N_("The format of logs to produce: %s"),
+ def_data_log_format,
+ }, {
+ "selinux", T_FLAG,
+ N_("Enable SELinux RBAC support"),
+ NULL,
+ }, {
+ "admin_flag", T_STR|T_BOOL|T_CHPATH,
+ N_("Path to the file that is created the first time sudo is run: %s"),
+ NULL,
+ }, {
+ "intercept", T_FLAG,
+ N_("Intercept further commands and apply sudoers restrictions to them"),
+ NULL,
+ }, {
+ "log_subcmds", T_FLAG,
+ N_("Log sub-commands run by the original command"),
+ NULL,
+ }, {
+ "log_exit_status", T_FLAG,
+ N_("Log the exit status of commands"),
+ NULL,
+ }, {
+ "intercept_authenticate", T_FLAG,
+ N_("Subsequent commands in an intercepted session must be authenticated"),
+ NULL,
+ }, {
+ "intercept_allow_setid", T_FLAG,
+ N_("Allow an intercepted command to run set setuid or setgid programs"),
+ NULL,
+ }, {
+ "rlimit_as", T_RLIMIT|T_BOOL,
+ N_("The maximum size to which the process's address space may grow (in bytes): %s"),
+ NULL,
+ }, {
+ "rlimit_core", T_RLIMIT|T_BOOL,
+ N_("The largest size core dump file that may be created (in bytes): %s"),
+ NULL,
+ }, {
+ "rlimit_cpu", T_RLIMIT|T_BOOL,
+ N_("The maximum amount of CPU time that the process may use (in seconds): %s"),
+ NULL,
+ }, {
+ "rlimit_data", T_RLIMIT|T_BOOL,
+ N_("The maximum size of the data segment for the process (in bytes): %s"),
+ NULL,
+ }, {
+ "rlimit_fsize", T_RLIMIT|T_BOOL,
+ N_("The largest size file that the process may create (in bytes): %s"),
+ NULL,
+ }, {
+ "rlimit_locks", T_RLIMIT|T_BOOL,
+ N_("The maximum number of locks that the process may establish: %s"),
+ NULL,
+ }, {
+ "rlimit_memlock", T_RLIMIT|T_BOOL,
+ N_("The maximum size that the process may lock in memory (in bytes): %s"),
+ NULL,
+ }, {
+ "rlimit_nofile", T_RLIMIT|T_BOOL,
+ N_("The maximum number of files that the process may have open: %s"),
+ NULL,
+ }, {
+ "rlimit_nproc", T_RLIMIT|T_BOOL,
+ N_("The maximum number of processes that the user may run simultaneously: %s"),
+ NULL,
+ }, {
+ "rlimit_rss", T_RLIMIT|T_BOOL,
+ N_("The maximum size to which the process's resident set size may grow (in bytes): %s"),
+ NULL,
+ }, {
+ "rlimit_stack", T_RLIMIT|T_BOOL,
+ N_("The maximum size to which the process's stack may grow (in bytes): %s"),
+ NULL,
+ }, {
+ "noninteractive_auth", T_FLAG,
+ N_("Attempt authentication even when in non-interactive mode"),
+ NULL,
+ }, {
+ "log_passwords", T_FLAG,
+ N_("Store plaintext passwords in I/O log input"),
+ NULL,
+ }, {
+ "passprompt_regex", T_LIST|T_SPACE|T_BOOL,
+ N_("List of regular expressions to use when matching a password prompt"),
+ NULL,
+ }, {
+ "intercept_type", T_TUPLE,
+ N_("The mechanism used by the intercept and log_subcmds options: %s"),
+ def_data_intercept_type,
+ }, {
+ "intercept_verify", T_FLAG,
+ N_("Attempt to verify the command and arguments after execution"),
+ NULL,
+ }, {
+ "apparmor_profile", T_STR,
+ N_("AppArmor profile to use in the new security context: %s"),
+ NULL,
+ }, {
+ NULL, 0, NULL
+ }
+};
diff --git a/plugins/sudoers/def_data.h b/plugins/sudoers/def_data.h
new file mode 100644
index 0000000..5c244a4
--- /dev/null
+++ b/plugins/sudoers/def_data.h
@@ -0,0 +1,341 @@
+/* generated file, do not edit */
+
+#define I_SYSLOG 0
+#define def_syslog (sudo_defs_table[I_SYSLOG].sd_un.ival)
+#define I_SYSLOG_GOODPRI 1
+#define def_syslog_goodpri (sudo_defs_table[I_SYSLOG_GOODPRI].sd_un.ival)
+#define I_SYSLOG_BADPRI 2
+#define def_syslog_badpri (sudo_defs_table[I_SYSLOG_BADPRI].sd_un.ival)
+#define I_LONG_OTP_PROMPT 3
+#define def_long_otp_prompt (sudo_defs_table[I_LONG_OTP_PROMPT].sd_un.flag)
+#define I_IGNORE_DOT 4
+#define def_ignore_dot (sudo_defs_table[I_IGNORE_DOT].sd_un.flag)
+#define I_MAIL_ALWAYS 5
+#define def_mail_always (sudo_defs_table[I_MAIL_ALWAYS].sd_un.flag)
+#define I_MAIL_BADPASS 6
+#define def_mail_badpass (sudo_defs_table[I_MAIL_BADPASS].sd_un.flag)
+#define I_MAIL_NO_USER 7
+#define def_mail_no_user (sudo_defs_table[I_MAIL_NO_USER].sd_un.flag)
+#define I_MAIL_NO_HOST 8
+#define def_mail_no_host (sudo_defs_table[I_MAIL_NO_HOST].sd_un.flag)
+#define I_MAIL_NO_PERMS 9
+#define def_mail_no_perms (sudo_defs_table[I_MAIL_NO_PERMS].sd_un.flag)
+#define I_MAIL_ALL_CMNDS 10
+#define def_mail_all_cmnds (sudo_defs_table[I_MAIL_ALL_CMNDS].sd_un.flag)
+#define I_TTY_TICKETS 11
+#define def_tty_tickets (sudo_defs_table[I_TTY_TICKETS].sd_un.flag)
+#define I_LECTURE 12
+#define def_lecture (sudo_defs_table[I_LECTURE].sd_un.tuple)
+#define I_LECTURE_FILE 13
+#define def_lecture_file (sudo_defs_table[I_LECTURE_FILE].sd_un.str)
+#define I_AUTHENTICATE 14
+#define def_authenticate (sudo_defs_table[I_AUTHENTICATE].sd_un.flag)
+#define I_ROOT_SUDO 15
+#define def_root_sudo (sudo_defs_table[I_ROOT_SUDO].sd_un.flag)
+#define I_LOG_HOST 16
+#define def_log_host (sudo_defs_table[I_LOG_HOST].sd_un.flag)
+#define I_LOG_YEAR 17
+#define def_log_year (sudo_defs_table[I_LOG_YEAR].sd_un.flag)
+#define I_SHELL_NOARGS 18
+#define def_shell_noargs (sudo_defs_table[I_SHELL_NOARGS].sd_un.flag)
+#define I_SET_HOME 19
+#define def_set_home (sudo_defs_table[I_SET_HOME].sd_un.flag)
+#define I_ALWAYS_SET_HOME 20
+#define def_always_set_home (sudo_defs_table[I_ALWAYS_SET_HOME].sd_un.flag)
+#define I_PATH_INFO 21
+#define def_path_info (sudo_defs_table[I_PATH_INFO].sd_un.flag)
+#define I_FQDN 22
+#define def_fqdn (sudo_defs_table[I_FQDN].sd_un.flag)
+#define I_INSULTS 23
+#define def_insults (sudo_defs_table[I_INSULTS].sd_un.flag)
+#define I_REQUIRETTY 24
+#define def_requiretty (sudo_defs_table[I_REQUIRETTY].sd_un.flag)
+#define I_ENV_EDITOR 25
+#define def_env_editor (sudo_defs_table[I_ENV_EDITOR].sd_un.flag)
+#define I_ROOTPW 26
+#define def_rootpw (sudo_defs_table[I_ROOTPW].sd_un.flag)
+#define I_RUNASPW 27
+#define def_runaspw (sudo_defs_table[I_RUNASPW].sd_un.flag)
+#define I_TARGETPW 28
+#define def_targetpw (sudo_defs_table[I_TARGETPW].sd_un.flag)
+#define I_USE_LOGINCLASS 29
+#define def_use_loginclass (sudo_defs_table[I_USE_LOGINCLASS].sd_un.flag)
+#define I_SET_LOGNAME 30
+#define def_set_logname (sudo_defs_table[I_SET_LOGNAME].sd_un.flag)
+#define I_STAY_SETUID 31
+#define def_stay_setuid (sudo_defs_table[I_STAY_SETUID].sd_un.flag)
+#define I_PRESERVE_GROUPS 32
+#define def_preserve_groups (sudo_defs_table[I_PRESERVE_GROUPS].sd_un.flag)
+#define I_LOGLINELEN 33
+#define def_loglinelen (sudo_defs_table[I_LOGLINELEN].sd_un.uival)
+#define I_TIMESTAMP_TIMEOUT 34
+#define def_timestamp_timeout (sudo_defs_table[I_TIMESTAMP_TIMEOUT].sd_un.tspec)
+#define I_PASSWD_TIMEOUT 35
+#define def_passwd_timeout (sudo_defs_table[I_PASSWD_TIMEOUT].sd_un.tspec)
+#define I_PASSWD_TRIES 36
+#define def_passwd_tries (sudo_defs_table[I_PASSWD_TRIES].sd_un.uival)
+#define I_UMASK 37
+#define def_umask (sudo_defs_table[I_UMASK].sd_un.mode)
+#define I_LOGFILE 38
+#define def_logfile (sudo_defs_table[I_LOGFILE].sd_un.str)
+#define I_MAILERPATH 39
+#define def_mailerpath (sudo_defs_table[I_MAILERPATH].sd_un.str)
+#define I_MAILERFLAGS 40
+#define def_mailerflags (sudo_defs_table[I_MAILERFLAGS].sd_un.str)
+#define I_MAILTO 41
+#define def_mailto (sudo_defs_table[I_MAILTO].sd_un.str)
+#define I_MAILFROM 42
+#define def_mailfrom (sudo_defs_table[I_MAILFROM].sd_un.str)
+#define I_MAILSUB 43
+#define def_mailsub (sudo_defs_table[I_MAILSUB].sd_un.str)
+#define I_BADPASS_MESSAGE 44
+#define def_badpass_message (sudo_defs_table[I_BADPASS_MESSAGE].sd_un.str)
+#define I_LECTURE_STATUS_DIR 45
+#define def_lecture_status_dir (sudo_defs_table[I_LECTURE_STATUS_DIR].sd_un.str)
+#define I_TIMESTAMPDIR 46
+#define def_timestampdir (sudo_defs_table[I_TIMESTAMPDIR].sd_un.str)
+#define I_TIMESTAMPOWNER 47
+#define def_timestampowner (sudo_defs_table[I_TIMESTAMPOWNER].sd_un.str)
+#define I_EXEMPT_GROUP 48
+#define def_exempt_group (sudo_defs_table[I_EXEMPT_GROUP].sd_un.str)
+#define I_PASSPROMPT 49
+#define def_passprompt (sudo_defs_table[I_PASSPROMPT].sd_un.str)
+#define I_PASSPROMPT_OVERRIDE 50
+#define def_passprompt_override (sudo_defs_table[I_PASSPROMPT_OVERRIDE].sd_un.flag)
+#define I_RUNAS_DEFAULT 51
+#define def_runas_default (sudo_defs_table[I_RUNAS_DEFAULT].sd_un.str)
+#define I_SECURE_PATH 52
+#define def_secure_path (sudo_defs_table[I_SECURE_PATH].sd_un.str)
+#define I_EDITOR 53
+#define def_editor (sudo_defs_table[I_EDITOR].sd_un.str)
+#define I_LISTPW 54
+#define def_listpw (sudo_defs_table[I_LISTPW].sd_un.tuple)
+#define I_VERIFYPW 55
+#define def_verifypw (sudo_defs_table[I_VERIFYPW].sd_un.tuple)
+#define I_NOEXEC 56
+#define def_noexec (sudo_defs_table[I_NOEXEC].sd_un.flag)
+#define I_IGNORE_LOCAL_SUDOERS 57
+#define def_ignore_local_sudoers (sudo_defs_table[I_IGNORE_LOCAL_SUDOERS].sd_un.flag)
+#define I_CLOSEFROM 58
+#define def_closefrom (sudo_defs_table[I_CLOSEFROM].sd_un.ival)
+#define I_CLOSEFROM_OVERRIDE 59
+#define def_closefrom_override (sudo_defs_table[I_CLOSEFROM_OVERRIDE].sd_un.flag)
+#define I_SETENV 60
+#define def_setenv (sudo_defs_table[I_SETENV].sd_un.flag)
+#define I_ENV_RESET 61
+#define def_env_reset (sudo_defs_table[I_ENV_RESET].sd_un.flag)
+#define I_ENV_CHECK 62
+#define def_env_check (sudo_defs_table[I_ENV_CHECK].sd_un.list)
+#define I_ENV_DELETE 63
+#define def_env_delete (sudo_defs_table[I_ENV_DELETE].sd_un.list)
+#define I_ENV_KEEP 64
+#define def_env_keep (sudo_defs_table[I_ENV_KEEP].sd_un.list)
+#define I_ROLE 65
+#define def_role (sudo_defs_table[I_ROLE].sd_un.str)
+#define I_TYPE 66
+#define def_type (sudo_defs_table[I_TYPE].sd_un.str)
+#define I_ENV_FILE 67
+#define def_env_file (sudo_defs_table[I_ENV_FILE].sd_un.str)
+#define I_RESTRICTED_ENV_FILE 68
+#define def_restricted_env_file (sudo_defs_table[I_RESTRICTED_ENV_FILE].sd_un.str)
+#define I_SUDOERS_LOCALE 69
+#define def_sudoers_locale (sudo_defs_table[I_SUDOERS_LOCALE].sd_un.str)
+#define I_VISIBLEPW 70
+#define def_visiblepw (sudo_defs_table[I_VISIBLEPW].sd_un.flag)
+#define I_PWFEEDBACK 71
+#define def_pwfeedback (sudo_defs_table[I_PWFEEDBACK].sd_un.flag)
+#define I_FAST_GLOB 72
+#define def_fast_glob (sudo_defs_table[I_FAST_GLOB].sd_un.flag)
+#define I_UMASK_OVERRIDE 73
+#define def_umask_override (sudo_defs_table[I_UMASK_OVERRIDE].sd_un.flag)
+#define I_LOG_INPUT 74
+#define def_log_input (sudo_defs_table[I_LOG_INPUT].sd_un.flag)
+#define I_LOG_STDIN 75
+#define def_log_stdin (sudo_defs_table[I_LOG_STDIN].sd_un.flag)
+#define I_LOG_TTYIN 76
+#define def_log_ttyin (sudo_defs_table[I_LOG_TTYIN].sd_un.flag)
+#define I_LOG_OUTPUT 77
+#define def_log_output (sudo_defs_table[I_LOG_OUTPUT].sd_un.flag)
+#define I_LOG_STDOUT 78
+#define def_log_stdout (sudo_defs_table[I_LOG_STDOUT].sd_un.flag)
+#define I_LOG_STDERR 79
+#define def_log_stderr (sudo_defs_table[I_LOG_STDERR].sd_un.flag)
+#define I_LOG_TTYOUT 80
+#define def_log_ttyout (sudo_defs_table[I_LOG_TTYOUT].sd_un.flag)
+#define I_COMPRESS_IO 81
+#define def_compress_io (sudo_defs_table[I_COMPRESS_IO].sd_un.flag)
+#define I_USE_PTY 82
+#define def_use_pty (sudo_defs_table[I_USE_PTY].sd_un.flag)
+#define I_GROUP_PLUGIN 83
+#define def_group_plugin (sudo_defs_table[I_GROUP_PLUGIN].sd_un.str)
+#define I_IOLOG_DIR 84
+#define def_iolog_dir (sudo_defs_table[I_IOLOG_DIR].sd_un.str)
+#define I_IOLOG_FILE 85
+#define def_iolog_file (sudo_defs_table[I_IOLOG_FILE].sd_un.str)
+#define I_SET_UTMP 86
+#define def_set_utmp (sudo_defs_table[I_SET_UTMP].sd_un.flag)
+#define I_UTMP_RUNAS 87
+#define def_utmp_runas (sudo_defs_table[I_UTMP_RUNAS].sd_un.flag)
+#define I_PRIVS 88
+#define def_privs (sudo_defs_table[I_PRIVS].sd_un.str)
+#define I_LIMITPRIVS 89
+#define def_limitprivs (sudo_defs_table[I_LIMITPRIVS].sd_un.str)
+#define I_EXEC_BACKGROUND 90
+#define def_exec_background (sudo_defs_table[I_EXEC_BACKGROUND].sd_un.flag)
+#define I_PAM_SERVICE 91
+#define def_pam_service (sudo_defs_table[I_PAM_SERVICE].sd_un.str)
+#define I_PAM_LOGIN_SERVICE 92
+#define def_pam_login_service (sudo_defs_table[I_PAM_LOGIN_SERVICE].sd_un.str)
+#define I_PAM_ASKPASS_SERVICE 93
+#define def_pam_askpass_service (sudo_defs_table[I_PAM_ASKPASS_SERVICE].sd_un.str)
+#define I_PAM_SETCRED 94
+#define def_pam_setcred (sudo_defs_table[I_PAM_SETCRED].sd_un.flag)
+#define I_PAM_SESSION 95
+#define def_pam_session (sudo_defs_table[I_PAM_SESSION].sd_un.flag)
+#define I_PAM_ACCT_MGMT 96
+#define def_pam_acct_mgmt (sudo_defs_table[I_PAM_ACCT_MGMT].sd_un.flag)
+#define I_MAXSEQ 97
+#define def_maxseq (sudo_defs_table[I_MAXSEQ].sd_un.str)
+#define I_USE_NETGROUPS 98
+#define def_use_netgroups (sudo_defs_table[I_USE_NETGROUPS].sd_un.flag)
+#define I_SUDOEDIT_CHECKDIR 99
+#define def_sudoedit_checkdir (sudo_defs_table[I_SUDOEDIT_CHECKDIR].sd_un.flag)
+#define I_SUDOEDIT_FOLLOW 100
+#define def_sudoedit_follow (sudo_defs_table[I_SUDOEDIT_FOLLOW].sd_un.flag)
+#define I_ALWAYS_QUERY_GROUP_PLUGIN 101
+#define def_always_query_group_plugin (sudo_defs_table[I_ALWAYS_QUERY_GROUP_PLUGIN].sd_un.flag)
+#define I_NETGROUP_TUPLE 102
+#define def_netgroup_tuple (sudo_defs_table[I_NETGROUP_TUPLE].sd_un.flag)
+#define I_IGNORE_AUDIT_ERRORS 103
+#define def_ignore_audit_errors (sudo_defs_table[I_IGNORE_AUDIT_ERRORS].sd_un.flag)
+#define I_IGNORE_IOLOG_ERRORS 104
+#define def_ignore_iolog_errors (sudo_defs_table[I_IGNORE_IOLOG_ERRORS].sd_un.flag)
+#define I_IGNORE_LOGFILE_ERRORS 105
+#define def_ignore_logfile_errors (sudo_defs_table[I_IGNORE_LOGFILE_ERRORS].sd_un.flag)
+#define I_MATCH_GROUP_BY_GID 106
+#define def_match_group_by_gid (sudo_defs_table[I_MATCH_GROUP_BY_GID].sd_un.flag)
+#define I_SYSLOG_MAXLEN 107
+#define def_syslog_maxlen (sudo_defs_table[I_SYSLOG_MAXLEN].sd_un.uival)
+#define I_IOLOG_USER 108
+#define def_iolog_user (sudo_defs_table[I_IOLOG_USER].sd_un.str)
+#define I_IOLOG_GROUP 109
+#define def_iolog_group (sudo_defs_table[I_IOLOG_GROUP].sd_un.str)
+#define I_IOLOG_MODE 110
+#define def_iolog_mode (sudo_defs_table[I_IOLOG_MODE].sd_un.mode)
+#define I_FDEXEC 111
+#define def_fdexec (sudo_defs_table[I_FDEXEC].sd_un.tuple)
+#define I_IGNORE_UNKNOWN_DEFAULTS 112
+#define def_ignore_unknown_defaults (sudo_defs_table[I_IGNORE_UNKNOWN_DEFAULTS].sd_un.flag)
+#define I_COMMAND_TIMEOUT 113
+#define def_command_timeout (sudo_defs_table[I_COMMAND_TIMEOUT].sd_un.ival)
+#define I_USER_COMMAND_TIMEOUTS 114
+#define def_user_command_timeouts (sudo_defs_table[I_USER_COMMAND_TIMEOUTS].sd_un.flag)
+#define I_IOLOG_FLUSH 115
+#define def_iolog_flush (sudo_defs_table[I_IOLOG_FLUSH].sd_un.flag)
+#define I_SYSLOG_PID 116
+#define def_syslog_pid (sudo_defs_table[I_SYSLOG_PID].sd_un.flag)
+#define I_TIMESTAMP_TYPE 117
+#define def_timestamp_type (sudo_defs_table[I_TIMESTAMP_TYPE].sd_un.tuple)
+#define I_AUTHFAIL_MESSAGE 118
+#define def_authfail_message (sudo_defs_table[I_AUTHFAIL_MESSAGE].sd_un.str)
+#define I_CASE_INSENSITIVE_USER 119
+#define def_case_insensitive_user (sudo_defs_table[I_CASE_INSENSITIVE_USER].sd_un.flag)
+#define I_CASE_INSENSITIVE_GROUP 120
+#define def_case_insensitive_group (sudo_defs_table[I_CASE_INSENSITIVE_GROUP].sd_un.flag)
+#define I_LOG_ALLOWED 121
+#define def_log_allowed (sudo_defs_table[I_LOG_ALLOWED].sd_un.flag)
+#define I_LOG_DENIED 122
+#define def_log_denied (sudo_defs_table[I_LOG_DENIED].sd_un.flag)
+#define I_LOG_SERVERS 123
+#define def_log_servers (sudo_defs_table[I_LOG_SERVERS].sd_un.list)
+#define I_LOG_SERVER_TIMEOUT 124
+#define def_log_server_timeout (sudo_defs_table[I_LOG_SERVER_TIMEOUT].sd_un.ival)
+#define I_LOG_SERVER_KEEPALIVE 125
+#define def_log_server_keepalive (sudo_defs_table[I_LOG_SERVER_KEEPALIVE].sd_un.flag)
+#define I_LOG_SERVER_CABUNDLE 126
+#define def_log_server_cabundle (sudo_defs_table[I_LOG_SERVER_CABUNDLE].sd_un.str)
+#define I_LOG_SERVER_PEER_CERT 127
+#define def_log_server_peer_cert (sudo_defs_table[I_LOG_SERVER_PEER_CERT].sd_un.str)
+#define I_LOG_SERVER_PEER_KEY 128
+#define def_log_server_peer_key (sudo_defs_table[I_LOG_SERVER_PEER_KEY].sd_un.str)
+#define I_LOG_SERVER_VERIFY 129
+#define def_log_server_verify (sudo_defs_table[I_LOG_SERVER_VERIFY].sd_un.flag)
+#define I_RUNAS_ALLOW_UNKNOWN_ID 130
+#define def_runas_allow_unknown_id (sudo_defs_table[I_RUNAS_ALLOW_UNKNOWN_ID].sd_un.flag)
+#define I_RUNAS_CHECK_SHELL 131
+#define def_runas_check_shell (sudo_defs_table[I_RUNAS_CHECK_SHELL].sd_un.flag)
+#define I_PAM_RUSER 132
+#define def_pam_ruser (sudo_defs_table[I_PAM_RUSER].sd_un.flag)
+#define I_PAM_RHOST 133
+#define def_pam_rhost (sudo_defs_table[I_PAM_RHOST].sd_un.flag)
+#define I_RUNCWD 134
+#define def_runcwd (sudo_defs_table[I_RUNCWD].sd_un.str)
+#define I_RUNCHROOT 135
+#define def_runchroot (sudo_defs_table[I_RUNCHROOT].sd_un.str)
+#define I_LOG_FORMAT 136
+#define def_log_format (sudo_defs_table[I_LOG_FORMAT].sd_un.tuple)
+#define I_SELINUX 137
+#define def_selinux (sudo_defs_table[I_SELINUX].sd_un.flag)
+#define I_ADMIN_FLAG 138
+#define def_admin_flag (sudo_defs_table[I_ADMIN_FLAG].sd_un.str)
+#define I_INTERCEPT 139
+#define def_intercept (sudo_defs_table[I_INTERCEPT].sd_un.flag)
+#define I_LOG_SUBCMDS 140
+#define def_log_subcmds (sudo_defs_table[I_LOG_SUBCMDS].sd_un.flag)
+#define I_LOG_EXIT_STATUS 141
+#define def_log_exit_status (sudo_defs_table[I_LOG_EXIT_STATUS].sd_un.flag)
+#define I_INTERCEPT_AUTHENTICATE 142
+#define def_intercept_authenticate (sudo_defs_table[I_INTERCEPT_AUTHENTICATE].sd_un.flag)
+#define I_INTERCEPT_ALLOW_SETID 143
+#define def_intercept_allow_setid (sudo_defs_table[I_INTERCEPT_ALLOW_SETID].sd_un.flag)
+#define I_RLIMIT_AS 144
+#define def_rlimit_as (sudo_defs_table[I_RLIMIT_AS].sd_un.str)
+#define I_RLIMIT_CORE 145
+#define def_rlimit_core (sudo_defs_table[I_RLIMIT_CORE].sd_un.str)
+#define I_RLIMIT_CPU 146
+#define def_rlimit_cpu (sudo_defs_table[I_RLIMIT_CPU].sd_un.str)
+#define I_RLIMIT_DATA 147
+#define def_rlimit_data (sudo_defs_table[I_RLIMIT_DATA].sd_un.str)
+#define I_RLIMIT_FSIZE 148
+#define def_rlimit_fsize (sudo_defs_table[I_RLIMIT_FSIZE].sd_un.str)
+#define I_RLIMIT_LOCKS 149
+#define def_rlimit_locks (sudo_defs_table[I_RLIMIT_LOCKS].sd_un.str)
+#define I_RLIMIT_MEMLOCK 150
+#define def_rlimit_memlock (sudo_defs_table[I_RLIMIT_MEMLOCK].sd_un.str)
+#define I_RLIMIT_NOFILE 151
+#define def_rlimit_nofile (sudo_defs_table[I_RLIMIT_NOFILE].sd_un.str)
+#define I_RLIMIT_NPROC 152
+#define def_rlimit_nproc (sudo_defs_table[I_RLIMIT_NPROC].sd_un.str)
+#define I_RLIMIT_RSS 153
+#define def_rlimit_rss (sudo_defs_table[I_RLIMIT_RSS].sd_un.str)
+#define I_RLIMIT_STACK 154
+#define def_rlimit_stack (sudo_defs_table[I_RLIMIT_STACK].sd_un.str)
+#define I_NONINTERACTIVE_AUTH 155
+#define def_noninteractive_auth (sudo_defs_table[I_NONINTERACTIVE_AUTH].sd_un.flag)
+#define I_LOG_PASSWORDS 156
+#define def_log_passwords (sudo_defs_table[I_LOG_PASSWORDS].sd_un.flag)
+#define I_PASSPROMPT_REGEX 157
+#define def_passprompt_regex (sudo_defs_table[I_PASSPROMPT_REGEX].sd_un.list)
+#define I_INTERCEPT_TYPE 158
+#define def_intercept_type (sudo_defs_table[I_INTERCEPT_TYPE].sd_un.tuple)
+#define I_INTERCEPT_VERIFY 159
+#define def_intercept_verify (sudo_defs_table[I_INTERCEPT_VERIFY].sd_un.flag)
+#define I_APPARMOR_PROFILE 160
+#define def_apparmor_profile (sudo_defs_table[I_APPARMOR_PROFILE].sd_un.str)
+
+enum def_tuple {
+ never,
+ once,
+ always,
+ any,
+ all,
+ digest_only,
+ global,
+ ppid,
+ tty,
+ kernel,
+ sudo,
+ json,
+ dso,
+ trace
+};
diff --git a/plugins/sudoers/def_data.in b/plugins/sudoers/def_data.in
new file mode 100644
index 0000000..4d627e6
--- /dev/null
+++ b/plugins/sudoers/def_data.in
@@ -0,0 +1,502 @@
+#
+# Format:
+#
+# var_name
+# TYPE
+# description (or NULL)
+# array of struct def_values if TYPE == T_TUPLE
+#
+# NOTE: for tuples that can be used in a boolean context the first
+# value corresponds to boolean FALSE and the second to TRUE.
+#
+
+syslog
+ T_LOGFAC|T_BOOL
+ "Syslog facility if syslog is being used for logging: %s"
+syslog_goodpri
+ T_LOGPRI|T_BOOL
+ "Syslog priority to use when user authenticates successfully: %s"
+syslog_badpri
+ T_LOGPRI|T_BOOL
+ "Syslog priority to use when user authenticates unsuccessfully: %s"
+long_otp_prompt
+ T_FLAG
+ "Put OTP prompt on its own line"
+ignore_dot
+ T_FLAG
+ "Ignore '.' in $PATH"
+mail_always
+ T_FLAG
+ "Always send mail when sudo is run"
+mail_badpass
+ T_FLAG
+ "Send mail if user authentication fails"
+mail_no_user
+ T_FLAG
+ "Send mail if the user is not in sudoers"
+mail_no_host
+ T_FLAG
+ "Send mail if the user is not in sudoers for this host"
+mail_no_perms
+ T_FLAG
+ "Send mail if the user is not allowed to run a command"
+mail_all_cmnds
+ T_FLAG
+ "Send mail if the user tries to run a command"
+tty_tickets
+ T_FLAG
+ "Use a separate timestamp for each user/tty combo"
+lecture
+ T_TUPLE|T_BOOL
+ "Lecture user the first time they run sudo"
+ never once always
+lecture_file
+ T_STR|T_PATH|T_BOOL
+ "File containing the sudo lecture: %s"
+authenticate
+ T_FLAG
+ "Require users to authenticate by default"
+root_sudo
+ T_FLAG
+ "Root may run sudo"
+log_host
+ T_FLAG
+ "Log the hostname in the (non-syslog) log file"
+log_year
+ T_FLAG
+ "Log the year in the (non-syslog) log file"
+shell_noargs
+ T_FLAG
+ "If sudo is invoked with no arguments, start a shell"
+set_home
+ T_FLAG
+ "Set $HOME to the target user when starting a shell with -s"
+always_set_home
+ T_FLAG
+ "Always set $HOME to the target user's home directory"
+path_info
+ T_FLAG
+ "Allow some information gathering to give useful error messages"
+fqdn
+ T_FLAG
+ "Require fully-qualified hostnames in the sudoers file"
+insults
+ T_FLAG
+ "Insult the user when they enter an incorrect password"
+requiretty
+ T_FLAG
+ "Only allow the user to run sudo if they have a tty"
+env_editor
+ T_FLAG
+ "Visudo will honor the EDITOR environment variable"
+rootpw
+ T_FLAG
+ "Prompt for root's password, not the users's"
+runaspw
+ T_FLAG
+ "Prompt for the runas_default user's password, not the users's"
+targetpw
+ T_FLAG
+ "Prompt for the target user's password, not the users's"
+use_loginclass
+ T_FLAG
+ "Apply defaults in the target user's login class if there is one"
+set_logname
+ T_FLAG
+ "Set the LOGNAME and USER environment variables"
+stay_setuid
+ T_FLAG
+ "Only set the effective uid to the target user, not the real uid"
+preserve_groups
+ T_FLAG
+ "Don't initialize the group vector to that of the target user"
+loglinelen
+ T_UINT|T_BOOL
+ "Length at which to wrap log file lines (0 for no wrap): %u"
+timestamp_timeout
+ T_TIMESPEC|T_BOOL
+ "Authentication timestamp timeout: %.1f minutes"
+passwd_timeout
+ T_TIMESPEC|T_BOOL
+ "Password prompt timeout: %.1f minutes"
+passwd_tries
+ T_UINT
+ "Number of tries to enter a password: %u"
+umask
+ T_MODE|T_BOOL
+ "Umask to use or 0777 to use user's: 0%o"
+logfile
+ T_STR|T_BOOL|T_PATH
+ "Path to log file: %s"
+mailerpath
+ T_STR|T_BOOL|T_PATH
+ "Path to mail program: %s"
+mailerflags
+ T_STR|T_BOOL
+ "Flags for mail program: %s"
+mailto
+ T_STR|T_BOOL
+ "Address to send mail to: %s"
+mailfrom
+ T_STR|T_BOOL
+ "Address to send mail from: %s"
+mailsub
+ T_STR
+ "Subject line for mail messages: %s"
+badpass_message
+ T_STR
+ "Incorrect password message: %s"
+lecture_status_dir
+ T_STR|T_PATH
+ "Path to lecture status dir: %s"
+timestampdir
+ T_STR|T_PATH
+ "Path to authentication timestamp dir: %s"
+timestampowner
+ T_STR
+ "Owner of the authentication timestamp dir: %s"
+exempt_group
+ T_STR|T_BOOL
+ "Users in this group are exempt from password and PATH requirements: %s"
+passprompt
+ T_STR
+ "Default password prompt: %s"
+passprompt_override
+ T_FLAG
+ "If set, passprompt will override system prompt in all cases."
+runas_default
+ T_STR
+ "Default user to run commands as: %s"
+secure_path
+ T_STR|T_BOOL
+ "Value to override user's $PATH with: %s"
+editor
+ T_STR|T_PATH
+ "Path to the editor for use by visudo: %s"
+listpw
+ T_TUPLE|T_BOOL
+ "When to require a password for 'list' pseudocommand: %s"
+ never any all always
+verifypw
+ T_TUPLE|T_BOOL
+ "When to require a password for 'verify' pseudocommand: %s"
+ never all any always
+noexec
+ T_FLAG
+ "Preload the sudo_noexec library which replaces the exec functions"
+ignore_local_sudoers
+ T_FLAG
+ "If LDAP directory is up, do we ignore local sudoers file"
+closefrom
+ T_INT
+ "File descriptors >= %d will be closed before executing a command"
+closefrom_override
+ T_FLAG
+ "If set, users may override the value of "closefrom" with the -C option"
+setenv
+ T_FLAG
+ "Allow users to set arbitrary environment variables"
+env_reset
+ T_FLAG
+ "Reset the environment to a default set of variables"
+env_check
+ T_LIST|T_BOOL
+ "Environment variables to check for safety:"
+env_delete
+ T_LIST|T_BOOL
+ "Environment variables to remove:"
+env_keep
+ T_LIST|T_BOOL
+ "Environment variables to preserve:"
+role
+ T_STR
+ "SELinux role to use in the new security context: %s"
+type
+ T_STR
+ "SELinux type to use in the new security context: %s"
+env_file
+ T_STR|T_PATH|T_BOOL
+ "Path to the sudo-specific environment file: %s"
+restricted_env_file
+ T_STR|T_PATH|T_BOOL
+ "Path to the restricted sudo-specific environment file: %s"
+sudoers_locale
+ T_STR
+ "Locale to use while parsing sudoers: %s"
+visiblepw
+ T_FLAG
+ "Allow sudo to prompt for a password even if it would be visible"
+pwfeedback
+ T_FLAG
+ "Provide visual feedback at the password prompt when there is user input"
+fast_glob
+ T_FLAG
+ "Use faster globbing that is less accurate but does not access the filesystem"
+umask_override
+ T_FLAG
+ "The umask specified in sudoers will override the user's, even if it is more permissive"
+log_input
+ T_FLAG
+ "Log user's input for the command being run"
+log_stdin
+ T_FLAG
+ "Log the command's standard input if not connected to a terminal"
+log_ttyin
+ T_FLAG
+ "Log the user's terminal input for the command being run"
+log_output
+ T_FLAG
+ "Log the output of the command being run"
+log_stdout
+ T_FLAG
+ "Log the command's standard output if not connected to a terminal"
+log_stderr
+ T_FLAG
+ "Log the command's standard error if not connected to a terminal"
+log_ttyout
+ T_FLAG
+ "Log the terminal output of the command being run"
+compress_io
+ T_FLAG
+ "Compress I/O logs using zlib"
+use_pty
+ T_FLAG
+ "Always run commands in a pseudo-tty"
+group_plugin
+ T_STR
+ "Plugin for non-Unix group support: %s"
+iolog_dir
+ T_STR|T_PATH
+ "Directory in which to store input/output logs: %s"
+iolog_file
+ T_STR
+ "File in which to store the input/output log: %s"
+set_utmp
+ T_FLAG
+ "Add an entry to the utmp/utmpx file when allocating a pty"
+utmp_runas
+ T_FLAG
+ "Set the user in utmp to the runas user, not the invoking user"
+privs
+ T_STR
+ "Set of permitted privileges: %s"
+limitprivs
+ T_STR
+ "Set of limit privileges: %s"
+exec_background
+ T_FLAG
+ "Run commands on a pty in the background"
+pam_service
+ T_STR
+ "PAM service name to use: %s"
+pam_login_service
+ T_STR
+ "PAM service name to use for login shells: %s"
+pam_askpass_service
+ T_STR
+ "PAM service name to use when sudo is run with the -A option: %s"
+pam_setcred
+ T_FLAG
+ "Attempt to establish PAM credentials for the target user"
+pam_session
+ T_FLAG
+ "Create a new PAM session for the command to run in"
+pam_acct_mgmt
+ T_FLAG
+ "Perform PAM account validation management"
+maxseq
+ T_STR
+ "Maximum I/O log sequence number: %s"
+use_netgroups
+ T_FLAG
+ "Enable sudoers netgroup support"
+sudoedit_checkdir
+ T_FLAG
+ "Check parent directories for writability when editing files with sudoedit"
+sudoedit_follow
+ T_FLAG
+ "Follow symbolic links when editing files with sudoedit"
+always_query_group_plugin
+ T_FLAG
+ "Query the group plugin for unknown system groups"
+netgroup_tuple
+ T_FLAG
+ "Match netgroups based on the entire tuple: user, host and domain"
+ignore_audit_errors
+ T_FLAG
+ "Allow commands to be run even if sudo cannot write to the audit log"
+ignore_iolog_errors
+ T_FLAG
+ "Allow commands to be run even if sudo cannot write to the I/O log"
+ignore_logfile_errors
+ T_FLAG
+ "Allow commands to be run even if sudo cannot write to the log file"
+match_group_by_gid
+ T_FLAG
+ "Resolve groups in sudoers and match on the group ID, not the name"
+syslog_maxlen
+ T_UINT
+ "Log entries larger than this value will be split into multiple syslog messages: %u"
+iolog_user
+ T_STR|T_BOOL
+ "User that will own the I/O log files: %s"
+iolog_group
+ T_STR|T_BOOL
+ "Group that will own the I/O log files: %s"
+iolog_mode
+ T_MODE
+ "File mode to use for the I/O log files: 0%o"
+fdexec
+ T_TUPLE|T_BOOL
+ "Execute commands by file descriptor instead of by path: %s"
+ never digest_only always
+ignore_unknown_defaults
+ T_FLAG
+ "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+command_timeout
+ T_TIMEOUT|T_BOOL
+ "Time in seconds after which the command will be terminated: %u"
+user_command_timeouts
+ T_FLAG
+ "Allow the user to specify a timeout on the command line"
+iolog_flush
+ T_FLAG
+ "Flush I/O log data to disk immediately instead of buffering it"
+syslog_pid
+ T_FLAG
+ "Include the process ID when logging via syslog"
+timestamp_type
+ T_TUPLE
+ "Type of authentication timestamp record: %s"
+ global ppid tty kernel
+authfail_message
+ T_STR
+ "Authentication failure message: %s"
+case_insensitive_user
+ T_FLAG
+ "Ignore case when matching user names"
+case_insensitive_group
+ T_FLAG
+ "Ignore case when matching group names"
+log_allowed
+ T_FLAG
+ "Log when a command is allowed by sudoers"
+log_denied
+ T_FLAG
+ "Log when a command is denied by sudoers"
+log_servers
+ T_LIST|T_BOOL
+ "Sudo log server(s) to connect to with optional port"
+log_server_timeout
+ T_TIMEOUT|T_BOOL
+ "Sudo log server timeout in seconds: %u"
+log_server_keepalive
+ T_FLAG
+ "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+log_server_cabundle
+ T_STR|T_BOOL|T_PATH
+ "Path to the audit server's CA bundle file: %s"
+log_server_peer_cert
+ T_STR|T_BOOL|T_PATH
+ "Path to the sudoers certificate file: %s"
+log_server_peer_key
+ T_STR|T_BOOL|T_PATH
+ "Path to the sudoers private key file: %s"
+log_server_verify
+ T_FLAG
+ "Verify that the log server's certificate is valid"
+runas_allow_unknown_id
+ T_FLAG
+ "Allow the use of unknown runas user and/or group ID"
+runas_check_shell
+ T_FLAG
+ "Only permit running commands as a user with a valid shell"
+pam_ruser
+ T_FLAG
+ "Set the pam remote user to the user running sudo"
+pam_rhost
+ T_FLAG
+ "Set the pam remote host to the local host name"
+runcwd
+ T_STR|T_BOOL|T_CHPATH
+ "Working directory to change to before executing the command: %s"
+runchroot
+ T_STR|T_BOOL|T_CHPATH
+ "Root directory to change to before executing the command: %s"
+log_format
+ T_TUPLE
+ "The format of logs to produce: %s"
+ sudo json
+selinux
+ T_FLAG
+ "Enable SELinux RBAC support"
+admin_flag
+ T_STR|T_BOOL|T_CHPATH
+ "Path to the file that is created the first time sudo is run: %s"
+intercept
+ T_FLAG
+ "Intercept further commands and apply sudoers restrictions to them"
+log_subcmds
+ T_FLAG
+ "Log sub-commands run by the original command"
+log_exit_status
+ T_FLAG
+ "Log the exit status of commands"
+intercept_authenticate
+ T_FLAG
+ "Subsequent commands in an intercepted session must be authenticated"
+intercept_allow_setid
+ T_FLAG
+ "Allow an intercepted command to run set setuid or setgid programs"
+rlimit_as
+ T_RLIMIT|T_BOOL
+ "The maximum size to which the process's address space may grow (in bytes): %s"
+rlimit_core
+ T_RLIMIT|T_BOOL
+ "The largest size core dump file that may be created (in bytes): %s"
+rlimit_cpu
+ T_RLIMIT|T_BOOL
+ "The maximum amount of CPU time that the process may use (in seconds): %s"
+rlimit_data
+ T_RLIMIT|T_BOOL
+ "The maximum size of the data segment for the process (in bytes): %s"
+rlimit_fsize
+ T_RLIMIT|T_BOOL
+ "The largest size file that the process may create (in bytes): %s"
+rlimit_locks
+ T_RLIMIT|T_BOOL
+ "The maximum number of locks that the process may establish: %s"
+rlimit_memlock
+ T_RLIMIT|T_BOOL
+ "The maximum size that the process may lock in memory (in bytes): %s"
+rlimit_nofile
+ T_RLIMIT|T_BOOL
+ "The maximum number of files that the process may have open: %s"
+rlimit_nproc
+ T_RLIMIT|T_BOOL
+ "The maximum number of processes that the user may run simultaneously: %s"
+rlimit_rss
+ T_RLIMIT|T_BOOL
+ "The maximum size to which the process's resident set size may grow (in bytes): %s"
+rlimit_stack
+ T_RLIMIT|T_BOOL
+ "The maximum size to which the process's stack may grow (in bytes): %s"
+noninteractive_auth
+ T_FLAG
+ "Attempt authentication even when in non-interactive mode"
+log_passwords
+ T_FLAG
+ "Store plaintext passwords in I/O log input"
+passprompt_regex
+ T_LIST|T_SPACE|T_BOOL
+ "List of regular expressions to use when matching a password prompt"
+intercept_type
+ T_TUPLE
+ "The mechanism used by the intercept and log_subcmds options: %s"
+ dso trace
+intercept_verify
+ T_FLAG
+ "Attempt to verify the command and arguments after execution"
+apparmor_profile
+ T_STR
+ "AppArmor profile to use in the new security context: %s"
diff --git a/plugins/sudoers/defaults.c b/plugins/sudoers/defaults.c
new file mode 100644
index 0000000..34c5d1d
--- /dev/null
+++ b/plugins/sudoers/defaults.c
@@ -0,0 +1,1310 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999-2005, 2007-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <syslog.h>
+
+#include <sudoers.h>
+#include <sudo_eventlog.h>
+#include <sudo_iolog.h>
+#include <gram.h>
+
+static struct early_default early_defaults[] = {
+ { I_IGNORE_UNKNOWN_DEFAULTS },
+#ifdef FQDN
+ { I_FQDN, true },
+#else
+ { I_FQDN },
+#endif
+ { I_MATCH_GROUP_BY_GID },
+ { I_GROUP_PLUGIN },
+ { I_RUNAS_DEFAULT },
+ { I_SUDOERS_LOCALE },
+ { -1 }
+};
+
+/*
+ * Local prototypes.
+ */
+static bool store_int(const char *str, struct sudo_defs_types *def);
+static bool store_list(const char *str, struct sudo_defs_types *def, int op);
+static bool store_mode(const char *str, struct sudo_defs_types *def);
+static int store_str(const char *str, struct sudo_defs_types *def);
+static bool store_syslogfac(const char *str, struct sudo_defs_types *def);
+static bool store_syslogpri(const char *str, struct sudo_defs_types *def);
+static bool store_timeout(const char *str, struct sudo_defs_types *def);
+static bool store_tuple(const char *str, struct sudo_defs_types *def, int op);
+static bool store_uint(const char *str, struct sudo_defs_types *def);
+static bool store_timespec(const char *str, struct sudo_defs_types *def);
+static bool store_rlimit(const char *str, struct sudo_defs_types *def);
+static bool store_plugin(const char *str, struct sudo_defs_types *def, int op);
+static bool list_op(const char *str, size_t, struct list_members *list, enum list_ops op);
+static bool valid_path(const struct sudoers_context *ctx, struct sudo_defs_types *def, const char *val, const char *file, int line, int column, bool quiet);
+
+/*
+ * Table describing compile-time and run-time options.
+ */
+#include <def_data.c>
+
+/*
+ * Print version and configure info.
+ */
+void
+dump_defaults(void)
+{
+ struct sudo_defs_types *cur;
+ struct list_member *item;
+ struct def_values *def;
+ const char *desc;
+ debug_decl(dump_defaults, SUDOERS_DEBUG_DEFAULTS);
+
+ for (cur = sudo_defs_table; cur->name; cur++) {
+ if (cur->desc) {
+ desc = _(cur->desc);
+ switch (cur->type & T_MASK) {
+ case T_FLAG:
+ if (cur->sd_un.flag)
+ sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", desc);
+ break;
+ case T_STR:
+ case T_RLIMIT:
+ if (cur->sd_un.str) {
+ sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.str);
+ sudo_printf(SUDO_CONV_INFO_MSG, "\n");
+ }
+ break;
+ case T_LOGFAC:
+ if (cur->sd_un.ival) {
+ sudo_printf(SUDO_CONV_INFO_MSG, desc,
+ sudo_logfac2str(cur->sd_un.ival));
+ sudo_printf(SUDO_CONV_INFO_MSG, "\n");
+ }
+ break;
+ case T_LOGPRI:
+ if (cur->sd_un.ival) {
+ sudo_printf(SUDO_CONV_INFO_MSG, desc,
+ sudo_logpri2str(cur->sd_un.ival));
+ sudo_printf(SUDO_CONV_INFO_MSG, "\n");
+ }
+ break;
+ case T_INT:
+ sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.ival);
+ sudo_printf(SUDO_CONV_INFO_MSG, "\n");
+ break;
+ case T_UINT:
+ sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.uival);
+ sudo_printf(SUDO_CONV_INFO_MSG, "\n");
+ break;
+ case T_TIMESPEC: {
+ /* display timespec in minutes as a double */
+ double d = (double)cur->sd_un.tspec.tv_sec +
+ ((double)cur->sd_un.tspec.tv_nsec / 1000000000.0);
+ sudo_printf(SUDO_CONV_INFO_MSG, desc, d / 60.0);
+ sudo_printf(SUDO_CONV_INFO_MSG, "\n");
+ break;
+ }
+ case T_MODE:
+ sudo_printf(SUDO_CONV_INFO_MSG, desc, cur->sd_un.mode);
+ sudo_printf(SUDO_CONV_INFO_MSG, "\n");
+ break;
+ case T_LIST:
+ if (!SLIST_EMPTY(&cur->sd_un.list)) {
+ sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", desc);
+ SLIST_FOREACH(item, &cur->sd_un.list, entries) {
+ sudo_printf(SUDO_CONV_INFO_MSG,
+ "\t%s\n", item->value);
+ }
+ }
+ break;
+ case T_TIMEOUT:
+ if (cur->sd_un.ival) {
+ sudo_printf(SUDO_CONV_INFO_MSG, desc,
+ cur->sd_un.ival);
+ sudo_printf(SUDO_CONV_INFO_MSG, "\n");
+ }
+ break;
+ case T_TUPLE:
+ for (def = cur->values; def->sval; def++) {
+ if (cur->sd_un.tuple == def->nval) {
+ sudo_printf(SUDO_CONV_INFO_MSG, desc, def->sval);
+ break;
+ }
+ }
+ sudo_printf(SUDO_CONV_INFO_MSG, "\n");
+ break;
+ }
+ }
+ }
+ debug_return;
+}
+
+static bool
+defaults_warnx(const struct sudoers_context *ctx, const char *file, int line,
+ int column, bool quiet, const char * restrict fmt, ...)
+{
+ va_list ap;
+ bool ret;
+ debug_decl(defaults_warnx, SUDOERS_DEBUG_DEFAULTS);
+
+ va_start(ap, fmt);
+ ret = parser_vwarnx(ctx, file, line, column, true, quiet, fmt, ap);
+ va_end(ap);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Find the index of the specified Defaults name in sudo_defs_table[]
+ * On success, returns the matching index or -1 on failure.
+ */
+static int
+find_default(const struct sudoers_context *ctx, const char *name,
+ const char *file, int line, int column, bool quiet)
+{
+ int i;
+ debug_decl(find_default, SUDOERS_DEBUG_DEFAULTS);
+
+ for (i = 0; sudo_defs_table[i].name != NULL; i++) {
+ if (strcmp(name, sudo_defs_table[i].name) == 0)
+ debug_return_int(i);
+ }
+ if (!def_ignore_unknown_defaults) {
+ defaults_warnx(ctx, file, line, column, quiet,
+ N_("unknown defaults entry \"%s\""), name);
+ }
+ debug_return_int(-1);
+}
+
+/*
+ * Parse a defaults entry, storing the parsed entry in sd_un.
+ * Returns true on success or false on failure.
+ */
+static bool
+parse_default_entry(const struct sudoers_context *ctx,
+ struct sudo_defs_types *def, const char *val, int op,
+ const char *file, int line, int column, bool quiet)
+{
+ int rc;
+ debug_decl(parse_default_entry, SUDOERS_DEBUG_DEFAULTS);
+
+ if (file == NULL)
+ file = "front-end";
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: %s:%d:%d: %s=%s op=%d",
+ __func__, file, line, column, def->name, val ? val : "", op);
+
+ /*
+ * If no value specified, the boolean flag must be set for non-flags.
+ * Only flags and tuples support boolean "true".
+ */
+ if (val == NULL) {
+ switch (def->type & T_MASK) {
+ case T_LOGFAC:
+ if (op == true) {
+ /* Use default syslog facility if none specified. */
+ val = LOGFAC;
+ }
+ break;
+ case T_FLAG:
+ break;
+ case T_TUPLE:
+ if (ISSET(def->type, T_BOOL))
+ break;
+ FALLTHROUGH;
+ default:
+ if (!ISSET(def->type, T_BOOL) || op != false) {
+ defaults_warnx(ctx, file, line, column, quiet,
+ N_("no value specified for \"%s\""), def->name);
+ debug_return_bool(false);
+ }
+ }
+ }
+
+ /* Only lists support append/remove. */
+ if ((op == '+' || op == '-') && (def->type & T_MASK) != T_LIST) {
+ defaults_warnx(ctx, file, line, column, quiet,
+ N_("invalid operator \"%c=\" for \"%s\""), op, def->name);
+ debug_return_bool(false);
+ }
+
+ switch (def->type & T_MASK) {
+ case T_LOGFAC:
+ rc = store_syslogfac(val, def);
+ break;
+ case T_LOGPRI:
+ rc = store_syslogpri(val, def);
+ break;
+ case T_STR:
+ if (val != NULL && ISSET(def->type, T_PATH|T_CHPATH)) {
+ if (!valid_path(ctx, def, val, file, line, column, quiet)) {
+ rc = -1;
+ break;
+ }
+ }
+ rc = store_str(val, def);
+ break;
+ case T_INT:
+ rc = store_int(val, def);
+ break;
+ case T_UINT:
+ rc = store_uint(val, def);
+ break;
+ case T_MODE:
+ rc = store_mode(val, def);
+ break;
+ case T_FLAG:
+ if (val != NULL) {
+ defaults_warnx(ctx, file, line, column, quiet,
+ N_("option \"%s\" does not take a value"), def->name);
+ rc = -1;
+ break;
+ }
+ def->sd_un.flag = (bool)op;
+ rc = true;
+ break;
+ case T_LIST:
+ rc = store_list(val, def, op);
+ break;
+ case T_TIMEOUT:
+ rc = store_timeout(val, def);
+ break;
+ case T_TUPLE:
+ rc = store_tuple(val, def, op);
+ break;
+ case T_TIMESPEC:
+ rc = store_timespec(val, def);
+ break;
+ case T_PLUGIN:
+ rc = store_plugin(val, def, op);
+ break;
+ case T_RLIMIT:
+ rc = store_rlimit(val, def);
+ break;
+ default:
+ defaults_warnx(ctx, file, line, column, quiet,
+ N_("invalid Defaults type 0x%x for option \"%s\""),
+ def->type, def->name);
+ rc = -1;
+ break;
+ }
+ if (rc == false) {
+ defaults_warnx(ctx, file, line, column, quiet,
+ N_("value \"%s\" is invalid for option \"%s\""), val, def->name);
+ }
+
+ debug_return_bool(rc == true);
+}
+
+static struct early_default *
+is_early_default(const char *name)
+{
+ struct early_default *early;
+ debug_decl(is_early_default, SUDOERS_DEBUG_DEFAULTS);
+
+ for (early = early_defaults; early->idx != -1; early++) {
+ if (strcmp(name, sudo_defs_table[early->idx].name) == 0)
+ debug_return_ptr(early);
+ }
+ debug_return_ptr(NULL);
+}
+
+static bool
+run_callback(struct sudoers_context *ctx, const char *file, int line,
+ int column, struct sudo_defs_types *def, int op)
+{
+ debug_decl(run_callback, SUDOERS_DEBUG_DEFAULTS);
+
+ if (def->callback == NULL)
+ debug_return_bool(true);
+ debug_return_bool(def->callback(ctx, file, line, column, &def->sd_un, op));
+}
+
+/*
+ * Sets/clears an entry in the defaults structure.
+ * Runs the callback if present on success.
+ */
+bool
+set_default(struct sudoers_context *ctx, const char *var, const char *val,
+ int op, const char *file, int line, int column, bool quiet)
+{
+ int idx;
+ debug_decl(set_default, SUDOERS_DEBUG_DEFAULTS);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "%s: setting Defaults %s -> %s", __func__, var, val ? val : "false");
+
+ idx = find_default(ctx, var, file, line, column, quiet);
+ if (idx != -1) {
+ /* Set parsed value in sudo_defs_table and run callback (if any). */
+ struct sudo_defs_types *def = &sudo_defs_table[idx];
+ if (parse_default_entry(ctx, def, val, op, file, line, column, quiet))
+ debug_return_bool(run_callback(ctx, file, line, column, def, op));
+ }
+ debug_return_bool(false);
+}
+
+/*
+ * Like set_default() but stores the matching default value
+ * and does not run callbacks.
+ */
+static bool
+set_early_default(const struct sudoers_context *ctx, const char *var,
+ const char *val, int op, const char *file, int line, int column,
+ bool quiet, struct early_default *early)
+{
+ int idx;
+ debug_decl(set_early_default, SUDOERS_DEBUG_DEFAULTS);
+
+ idx = find_default(ctx, var, file, line, column, quiet);
+ if (idx != -1) {
+ /* Set parsed value in sudo_defs_table but defer callback (if any). */
+ struct sudo_defs_types *def = &sudo_defs_table[idx];
+ if (parse_default_entry(ctx, def, val, op, file, line, column, quiet)) {
+ if (early->file != NULL)
+ sudo_rcstr_delref(early->file);
+ early->file = sudo_rcstr_addref(file);
+ early->line = line;
+ early->column = column;
+ early->run_callback = true;
+ debug_return_bool(true);
+ }
+ }
+ debug_return_bool(false);
+}
+
+/*
+ * Run callbacks for early defaults.
+ */
+static bool
+run_early_defaults(struct sudoers_context *ctx)
+{
+ struct early_default *early;
+ bool ret = true;
+ debug_decl(run_early_defaults, SUDOERS_DEBUG_DEFAULTS);
+
+ for (early = early_defaults; early->idx != -1; early++) {
+ if (early->run_callback) {
+ if (!run_callback(ctx, early->file, early->line, early->column,
+ &sudo_defs_table[early->idx], true))
+ ret = false;
+ early->run_callback = false;
+ }
+ }
+ debug_return_bool(ret);
+}
+
+static void
+free_defs_val(int type, union sudo_defs_val *sd_un)
+{
+ switch (type & T_MASK) {
+ case T_STR:
+ case T_RLIMIT:
+ free(sd_un->str);
+ break;
+ case T_LIST:
+ (void)list_op(NULL, 0, &sd_un->list, freeall);
+ break;
+ }
+ memset(sd_un, 0, sizeof(*sd_un));
+}
+
+static bool
+init_passprompt_regex(void)
+{
+ struct list_member *lm;
+ debug_decl(init_passprompt_regex, SUDOERS_DEBUG_DEFAULTS);
+
+ /* Add initial defaults setting. */
+ lm = calloc(1, sizeof(struct list_member));
+ if (lm == NULL || (lm->value = strdup(PASSPROMPT_REGEX)) == NULL) {
+ free(lm);
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ SLIST_INSERT_HEAD(&def_passprompt_regex, lm, entries);
+
+ debug_return_bool(true);
+}
+
+/*
+ * Set default options to compiled-in values.
+ * Any of these may be overridden at runtime by a "Defaults" file.
+ */
+bool
+init_defaults(void)
+{
+ static bool firsttime = true;
+ struct sudo_defs_types *def;
+ debug_decl(init_defaults, SUDOERS_DEBUG_DEFAULTS);
+
+ /* Clear any old settings. */
+ if (!firsttime) {
+ for (def = sudo_defs_table; def->name != NULL; def++)
+ free_defs_val(def->type, &def->sd_un);
+ }
+
+ /* First initialize the flags. */
+#ifdef LONG_OTP_PROMPT
+ def_long_otp_prompt = true;
+#endif
+#ifdef IGNORE_DOT_PATH
+ def_ignore_dot = true;
+#endif
+#ifdef ALWAYS_SEND_MAIL
+ def_mail_always = true;
+#endif
+#ifdef SEND_MAIL_WHEN_NO_USER
+ def_mail_no_user = true;
+#endif
+#ifdef SEND_MAIL_WHEN_NO_HOST
+ def_mail_no_host = true;
+#endif
+#ifdef SEND_MAIL_WHEN_NOT_OK
+ def_mail_no_perms = true;
+#endif
+#ifndef NO_LECTURE
+ def_lecture = once;
+#endif
+#ifndef NO_AUTHENTICATION
+ def_authenticate = true;
+#endif
+#ifndef NO_ROOT_SUDO
+ def_root_sudo = true;
+#endif
+#ifdef HOST_IN_LOG
+ def_log_host = true;
+#endif
+#ifdef SHELL_IF_NO_ARGS
+ def_shell_noargs = true;
+#endif
+#ifdef SHELL_SETS_HOME
+ def_set_home = true;
+#endif
+#ifndef DONT_LEAK_PATH_INFO
+ def_path_info = true;
+#endif
+#ifdef USE_INSULTS
+ def_insults = true;
+#endif
+#ifdef FQDN
+ def_fqdn = true;
+#endif
+#ifdef ENV_EDITOR
+ def_env_editor = true;
+#endif
+#ifdef UMASK_OVERRIDE
+ def_umask_override = true;
+#endif
+#ifdef SUDOERS_NAME_MATCH
+ def_fast_glob = true;
+ def_fdexec = never;
+#else
+ def_fdexec = digest_only;
+#endif
+ def_timestamp_type = TIMESTAMP_TYPE;
+ if ((def_iolog_file = strdup(IOLOG_FILE)) == NULL)
+ goto oom;
+ if ((def_iolog_dir = strdup(_PATH_SUDO_IO_LOGDIR)) == NULL)
+ goto oom;
+ if ((def_sudoers_locale = strdup("C")) == NULL)
+ goto oom;
+ def_env_reset = ENV_RESET;
+ def_set_logname = true;
+ def_closefrom = STDERR_FILENO + 1;
+ def_pam_ruser = true;
+#ifdef __sun__
+ def_pam_rhost = true;
+#endif
+ if ((def_pam_service = strdup("sudo")) == NULL)
+ goto oom;
+#ifdef HAVE_PAM_LOGIN
+ if ((def_pam_login_service = strdup("sudo-i")) == NULL)
+ goto oom;
+#else
+ if ((def_pam_login_service = strdup("sudo")) == NULL)
+ goto oom;
+#endif
+#ifdef NO_PAM_SESSION
+ def_pam_session = false;
+#else
+ def_pam_session = true;
+#endif
+#ifdef HAVE_SELINUX
+ def_selinux = true;
+#endif
+#ifdef _PATH_SUDO_ADMIN_FLAG
+ if ((def_admin_flag = strdup(_PATH_SUDO_ADMIN_FLAG)) == NULL)
+ goto oom;
+#endif
+ if ((def_rlimit_core = strdup("0,0")) == NULL)
+ goto oom;
+ def_intercept_type = dso;
+ def_intercept_verify = true;
+ def_use_netgroups = true;
+ def_netgroup_tuple = false;
+ def_sudoedit_checkdir = true;
+ def_iolog_mode = S_IRUSR|S_IWUSR;
+ def_log_allowed = true;
+ def_log_denied = true;
+ def_log_format = sudo;
+ def_runas_allow_unknown_id = false;
+ def_noninteractive_auth = false;
+ def_use_pty = true;
+
+ /* Syslog options need special care since they both strings and ints */
+#if (LOGGING & SLOG_SYSLOG)
+ (void) store_syslogfac(LOGFAC, &sudo_defs_table[I_SYSLOG]);
+ (void) store_syslogpri(PRI_SUCCESS, &sudo_defs_table[I_SYSLOG_GOODPRI]);
+ (void) store_syslogpri(PRI_FAILURE, &sudo_defs_table[I_SYSLOG_BADPRI]);
+#endif
+
+ /* Password flags also have a string and integer component. */
+ (void) store_tuple("any", &sudo_defs_table[I_LISTPW], 0);
+ (void) store_tuple("all", &sudo_defs_table[I_VERIFYPW], 0);
+
+ /* Then initialize the int-like things. */
+#ifdef SUDO_UMASK
+ def_umask = SUDO_UMASK;
+#else
+ def_umask = ACCESSPERMS;
+#endif
+ def_loglinelen = MAXLOGFILELEN;
+ def_timestamp_timeout.tv_sec = TIMEOUT * 60;
+ def_passwd_timeout.tv_sec = PASSWORD_TIMEOUT * 60;
+ def_passwd_tries = TRIES_FOR_PASSWORD;
+#ifdef HAVE_ZLIB_H
+ def_compress_io = true;
+#endif
+ def_ignore_audit_errors = true;
+ def_ignore_iolog_errors = false;
+ def_ignore_logfile_errors = true;
+ def_log_passwords = true;
+#ifdef SUDOERS_LOG_CLIENT
+ def_log_server_timeout = 30;
+ def_log_server_verify = true;
+ def_log_server_keepalive = true;
+#endif
+
+ /* Now do the strings */
+ if ((def_mailto = strdup(MAILTO)) == NULL)
+ goto oom;
+ if ((def_mailsub = strdup(N_(MAILSUBJECT))) == NULL)
+ goto oom;
+ if ((def_badpass_message = strdup(_(INCORRECT_PASSWORD))) == NULL)
+ goto oom;
+#ifdef _PATH_SUDO_LECTURE_DIR
+ if ((def_lecture_status_dir = strdup(_PATH_SUDO_LECTURE_DIR)) == NULL)
+ goto oom;
+#endif
+#ifdef _PATH_SUDO_TIMEDIR
+ if ((def_timestampdir = strdup(_PATH_SUDO_TIMEDIR)) == NULL)
+ goto oom;
+#endif
+ if ((def_passprompt = strdup(_(PASSPROMPT))) == NULL)
+ goto oom;
+ if ((def_runas_default = strdup(RUNAS_DEFAULT)) == NULL)
+ goto oom;
+#ifdef _PATH_SUDO_SENDMAIL
+ if ((def_mailerpath = strdup(_PATH_SUDO_SENDMAIL)) == NULL)
+ goto oom;
+#endif
+ if ((def_mailerflags = strdup("-t")) == NULL)
+ goto oom;
+#if (LOGGING & SLOG_FILE)
+ if ((def_logfile = strdup(_PATH_SUDO_LOGFILE)) == NULL)
+ goto oom;
+#endif
+#ifdef EXEMPTGROUP
+ if ((def_exempt_group = strdup(EXEMPTGROUP)) == NULL)
+ goto oom;
+#endif
+#ifdef SECURE_PATH
+ if ((def_secure_path = strdup(SECURE_PATH)) == NULL)
+ goto oom;
+#endif
+ if ((def_editor = strdup(EDITOR)) == NULL)
+ goto oom;
+ def_set_utmp = true;
+ def_pam_acct_mgmt = true;
+ def_pam_setcred = true;
+ def_syslog_maxlen = MAXSYSLOGLEN;
+ def_case_insensitive_user = true;
+ def_case_insensitive_group = true;
+
+ /* Reset the locale. */
+ if (!firsttime) {
+ if (!sudoers_initlocale(NULL, def_sudoers_locale))
+ goto oom;
+ }
+
+ /* Finally do the lists (currently just environment tables). */
+ if (!init_envtables())
+ goto oom;
+
+ /* Init eventlog config. */
+ init_eventlog_config();
+
+ /* Initial iolog password prompt regex. */
+ if (!init_passprompt_regex())
+ debug_return_bool(false);
+
+ firsttime = false;
+
+ debug_return_bool(true);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+}
+
+/*
+ * Check whether a defaults entry matches the specified type.
+ * Returns true if it matches, else false.
+ */
+static bool
+default_type_matches(struct defaults *d, int what)
+{
+ debug_decl(default_type_matches, SUDOERS_DEBUG_DEFAULTS);
+
+ switch (d->type) {
+ case DEFAULTS:
+ if (ISSET(what, SETDEF_GENERIC))
+ debug_return_bool(true);
+ break;
+ case DEFAULTS_USER:
+ if (ISSET(what, SETDEF_USER))
+ debug_return_bool(true);
+ break;
+ case DEFAULTS_RUNAS:
+ if (ISSET(what, SETDEF_RUNAS))
+ debug_return_bool(true);
+ break;
+ case DEFAULTS_HOST:
+ if (ISSET(what, SETDEF_HOST))
+ debug_return_bool(true);
+ break;
+ case DEFAULTS_CMND:
+ if (ISSET(what, SETDEF_CMND))
+ debug_return_bool(true);
+ break;
+ }
+ debug_return_bool(false);
+}
+
+/*
+ * Check whether a defaults entry's binding matches.
+ * Returns true if it matches, else false.
+ */
+static bool
+default_binding_matches(const struct sudoers_context *ctx,
+ struct sudoers_parse_tree *parse_tree, struct defaults *d, int what)
+{
+ debug_decl(default_binding_matches, SUDOERS_DEBUG_DEFAULTS);
+
+ switch (d->type) {
+ case DEFAULTS:
+ debug_return_bool(true);
+ case DEFAULTS_USER:
+ if (userlist_matches(parse_tree, ctx->user.pw, &d->binding->members) == ALLOW)
+ debug_return_bool(true);
+ break;
+ case DEFAULTS_RUNAS:
+ if (runaslist_matches(parse_tree, &d->binding->members, NULL, NULL, NULL) == ALLOW)
+ debug_return_bool(true);
+ break;
+ case DEFAULTS_HOST:
+ if (hostlist_matches(parse_tree, ctx->user.pw, &d->binding->members) == ALLOW)
+ debug_return_bool(true);
+ break;
+ case DEFAULTS_CMND:
+ if (cmndlist_matches(parse_tree, &d->binding->members, NULL, NULL) == ALLOW)
+ debug_return_bool(true);
+ break;
+ }
+ debug_return_bool(false);
+}
+
+/*
+ * Update the global defaults based on the given defaults list.
+ * Pass in an OR'd list of which default types to update.
+ */
+bool
+update_defaults(struct sudoers_context *ctx,
+ struct sudoers_parse_tree *parse_tree,
+ struct defaults_list *defs, int what, bool quiet)
+{
+ struct defaults *d;
+ bool global_defaults = false;
+ bool ret = true;
+ debug_decl(update_defaults, SUDOERS_DEBUG_DEFAULTS);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "what: 0x%02x", what);
+
+ /* If no defaults list specified, use the global one in the parse tree. */
+ if (defs == NULL) {
+ defs = &parse_tree->defaults;
+ global_defaults = true;
+ }
+
+ /*
+ * If using the global defaults list, apply Defaults values marked as early.
+ */
+ if (global_defaults) {
+ TAILQ_FOREACH(d, defs, entries) {
+ struct early_default *early = is_early_default(d->var);
+ if (early == NULL)
+ continue;
+
+ /* Defaults type and binding must match. */
+ if (!default_type_matches(d, what) ||
+ !default_binding_matches(ctx, parse_tree, d, what))
+ continue;
+
+ /* Copy the value to sudo_defs_table and mark as early. */
+ if (!set_early_default(ctx, d->var, d->val, d->op, d->file, d->line,
+ d->column, quiet, early))
+ ret = false;
+ }
+
+ /* Run callbacks for early defaults (if any) */
+ if (!run_early_defaults(ctx))
+ ret = false;
+ }
+
+ /*
+ * Set the rest of the defaults and run their callbacks, if any.
+ */
+ TAILQ_FOREACH(d, defs, entries) {
+ if (global_defaults) {
+ /* Skip Defaults marked as early, we already did them. */
+ if (is_early_default(d->var))
+ continue;
+ }
+
+ /* Defaults type and binding must match. */
+ if (!default_type_matches(d, what) ||
+ !default_binding_matches(ctx, parse_tree, d, what))
+ continue;
+
+ /* Copy the value to sudo_defs_table and run callback (if any) */
+ if (!set_default(ctx, d->var, d->val, d->op, d->file, d->line, d->column, quiet))
+ ret = false;
+ }
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Check all defaults entries without actually setting them.
+ */
+bool
+check_defaults(const struct sudoers_parse_tree *parse_tree, bool quiet)
+{
+ struct defaults *d;
+ bool ret = true;
+ int idx;
+ debug_decl(check_defaults, SUDOERS_DEBUG_DEFAULTS);
+
+ TAILQ_FOREACH(d, &parse_tree->defaults, entries) {
+ idx = find_default(parse_tree->ctx, d->var, d->file, d->line,
+ d->column, quiet);
+ if (idx != -1) {
+ struct sudo_defs_types def = sudo_defs_table[idx];
+ memset(&def.sd_un, 0, sizeof(def.sd_un));
+ if (parse_default_entry(parse_tree->ctx, &def, d->val, d->op,
+ d->file, d->line, d->column, quiet)) {
+ free_defs_val(def.type, &def.sd_un);
+ continue;
+ }
+ }
+ /* There was an error in the entry. */
+ ret = false;
+ }
+ debug_return_bool(ret);
+}
+
+static bool
+store_int(const char *str, struct sudo_defs_types *def)
+{
+ const char *errstr;
+ int i;
+ debug_decl(store_int, SUDOERS_DEBUG_DEFAULTS);
+
+ if (str == NULL) {
+ def->sd_un.ival = 0;
+ } else {
+ i = (int)sudo_strtonum(str, INT_MIN, INT_MAX, &errstr);
+ if (errstr != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: %s", str, errstr);
+ debug_return_bool(false);
+ }
+ def->sd_un.ival = i;
+ }
+ debug_return_bool(true);
+}
+
+static bool
+store_uint(const char *str, struct sudo_defs_types *def)
+{
+ const char *errstr;
+ unsigned int u;
+ debug_decl(store_uint, SUDOERS_DEBUG_DEFAULTS);
+
+ if (str == NULL) {
+ def->sd_un.uival = 0;
+ } else {
+ u = (unsigned int)sudo_strtonum(str, 0, UINT_MAX, &errstr);
+ if (errstr != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: %s", str, errstr);
+ debug_return_bool(false);
+ }
+ def->sd_un.uival = u;
+ }
+ debug_return_bool(true);
+}
+
+/* Check resource limit syntax, does not save as rlim_t. */
+static bool
+check_rlimit(const char *str, bool soft)
+{
+ const size_t inflen = sizeof("infinity") - 1;
+ debug_decl(check_rlimit, SUDOERS_DEBUG_DEFAULTS);
+
+ if (isdigit((unsigned char)*str)) {
+ unsigned long long ullval;
+ char *ep;
+
+ errno = 0;
+#ifdef HAVE_STRTOULL
+ ullval = strtoull(str, &ep, 10);
+ if (str == ep || (errno == ERANGE && ullval == ULLONG_MAX))
+ debug_return_bool(false);
+#else
+ ullval = strtoul(str, &ep, 10);
+ if (str == ep || (errno == ERANGE && ullval == ULONG_MAX))
+ debug_return_bool(false);
+#endif
+ if (*ep == '\0' || (soft && *ep == ','))
+ debug_return_bool(true);
+ debug_return_bool(false);
+ }
+ if (strncmp(str, "infinity", inflen) == 0) {
+ if (str[inflen] == '\0' || (soft && str[inflen] == ','))
+ debug_return_bool(true);
+ }
+ debug_return_bool(false);
+}
+
+static bool
+store_rlimit(const char *str, struct sudo_defs_types *def)
+{
+ debug_decl(store_rlimit, SUDOERS_DEBUG_DEFAULTS);
+
+ /* The special values "user" and "default" are not compound. */
+ if (str != NULL && strcmp(str, "user") != 0 && strcmp(str, "default") != 0) {
+ const char *hard, *soft = str;
+ /*
+ * Expect a limit in the form "soft,hard" or "limit" (both soft+hard).
+ */
+ hard = strchr(str, ',');
+ if (hard != NULL)
+ hard++;
+ else
+ hard = soft;
+
+ if (!check_rlimit(soft, true))
+ debug_return_bool(false);
+ if (!check_rlimit(hard, false))
+ debug_return_bool(false);
+ }
+
+ /* Store as string, front-end will parse it as a limit. */
+ debug_return_bool(store_str(str, def));
+}
+
+static bool
+store_timespec(const char *str, struct sudo_defs_types *def)
+{
+ struct timespec ts;
+ char sign = '+';
+ long i;
+ debug_decl(store_timespec, SUDOERS_DEBUG_DEFAULTS);
+
+ sudo_timespecclear(&ts);
+ if (str != NULL) {
+ /* Convert from minutes to seconds. */
+ if (*str == '+' || *str == '-')
+ sign = *str++;
+ while (*str != '\0' && *str != '.') {
+ if (!isdigit((unsigned char)*str))
+ debug_return_bool(false); /* invalid number */
+
+ /* Verify (ts.tv_sec * 10) + (digit * 60) <= TIME_T_MAX. */
+ i = (*str++ - '0') * 60L;
+ if (ts.tv_sec > (TIME_T_MAX - i) / 10)
+ debug_return_bool(false); /* overflow */
+ ts.tv_sec *= 10;
+ ts.tv_sec += i;
+ }
+ if (*str++ == '.') {
+ long long nsec = 0;
+
+ /* Convert optional fractional component to seconds and nanosecs. */
+ for (i = 100000000; i > 0; i /= 10) {
+ if (*str == '\0')
+ break;
+ if (!isdigit((unsigned char)*str))
+ debug_return_bool(false); /* invalid number */
+ nsec += i * (*str++ - '0') * 60LL;
+ }
+ while (nsec >= 1000000000) {
+ if (ts.tv_sec == TIME_T_MAX)
+ debug_return_bool(false); /* overflow */
+ ts.tv_sec++;
+ nsec -= 1000000000;
+ }
+ ts.tv_nsec = (long)nsec;
+ }
+ }
+ if (sign == '-') {
+ def->sd_un.tspec.tv_sec = -ts.tv_sec;
+ def->sd_un.tspec.tv_nsec = -ts.tv_nsec;
+ } else {
+ def->sd_un.tspec.tv_sec = ts.tv_sec;
+ def->sd_un.tspec.tv_nsec = ts.tv_nsec;
+ }
+ debug_return_bool(true);
+}
+
+static bool
+store_tuple(const char *str, struct sudo_defs_types *def, int op)
+{
+ struct def_values *v;
+ debug_decl(store_tuple, SUDOERS_DEBUG_DEFAULTS);
+
+ /*
+ * Look up tuple value by name to find enum def_tuple value.
+ * A tuple must have at least two possible values.
+ */
+ if (str == NULL) {
+ /*
+ * Boolean context: true maps to values[1], false maps to values[0].
+ */
+ if (op == true) {
+ v = &def->values[1];
+ def->sd_un.ival = v->nval;
+ } else if (op == false) {
+ v = &def->values[0];
+ def->sd_un.ival = v->nval;
+ } else {
+ debug_return_bool(false);
+ }
+ } else {
+ for (v = def->values; v->sval != NULL; v++) {
+ if (strcmp(v->sval, str) == 0) {
+ def->sd_un.tuple = v->nval;
+ break;
+ }
+ }
+ if (v->sval == NULL)
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+static int
+store_str(const char *str, struct sudo_defs_types *def)
+{
+ debug_decl(store_str, SUDOERS_DEBUG_DEFAULTS);
+
+ free(def->sd_un.str);
+ if (str == NULL) {
+ def->sd_un.str = NULL;
+ } else {
+ if ((def->sd_un.str = strdup(str)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(-1);
+ }
+ }
+ debug_return_int(true);
+}
+
+static bool
+store_list(const char *str, struct sudo_defs_types *def, int op)
+{
+ debug_decl(store_list, SUDOERS_DEBUG_DEFAULTS);
+
+ /* Remove all old members. */
+ if (op == false || op == true)
+ (void)list_op(NULL, 0, &def->sd_un.list, freeall);
+
+ /* Split str into multiple space-separated words and act on each one. */
+ if (str != NULL) {
+ const char *cp, *ep;
+ const char *end = str + strlen(str);
+ const enum list_ops lop = op == '-' ? delete : add;
+
+ if (ISSET(def->type, T_SPACE)) {
+ if (!list_op(str, strlen(str), &def->sd_un.list, lop))
+ debug_return_bool(false);
+ } else {
+ for (cp = sudo_strsplit(str, end, " \t", &ep); cp != NULL;
+ cp = sudo_strsplit(NULL, end, " \t", &ep)) {
+ if (!list_op(cp, (size_t)(ep - cp), &def->sd_un.list, lop))
+ debug_return_bool(false);
+ }
+ }
+ }
+ debug_return_bool(true);
+}
+
+static bool
+store_plugin(const char *str, struct sudo_defs_types *def, int op)
+{
+ const enum list_ops lop = op == '-' ? delete : add;
+ debug_decl(store_plugin, SUDOERS_DEBUG_DEFAULTS);
+
+ /* Remove all old members. */
+ if (op == false || op == true)
+ (void)list_op(NULL, 0, &def->sd_un.list, freeall);
+
+ if (str != NULL) {
+ if (!list_op(str, strlen(str), &def->sd_un.list, lop))
+ debug_return_bool(false);
+ }
+
+ debug_return_bool(true);
+}
+
+static bool
+store_syslogfac(const char *str, struct sudo_defs_types *def)
+{
+ debug_decl(store_syslogfac, SUDOERS_DEBUG_DEFAULTS);
+
+ if (str == NULL) {
+ def->sd_un.ival = false;
+ debug_return_bool(true);
+ }
+ debug_return_bool(sudo_str2logfac(str, &def->sd_un.ival));
+}
+
+static bool
+store_syslogpri(const char *str, struct sudo_defs_types *def)
+{
+ debug_decl(store_syslogpri, SUDOERS_DEBUG_DEFAULTS);
+
+ if (str == NULL) {
+ def->sd_un.ival = -1;
+ debug_return_bool(true);
+ }
+ debug_return_bool(sudo_str2logpri(str, &def->sd_un.ival));
+}
+
+static bool
+store_mode(const char *str, struct sudo_defs_types *def)
+{
+ mode_t mode;
+ const char *errstr;
+ debug_decl(store_mode, SUDOERS_DEBUG_DEFAULTS);
+
+ if (str == NULL) {
+ def->sd_un.mode = ACCESSPERMS;
+ } else {
+ mode = sudo_strtomode(str, &errstr);
+ if (errstr != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s is %s", str, errstr);
+ debug_return_bool(false);
+ }
+ def->sd_un.mode = mode;
+ }
+ debug_return_bool(true);
+}
+
+static bool
+store_timeout(const char *str, struct sudo_defs_types *def)
+{
+ debug_decl(store_mode, SUDOERS_DEBUG_DEFAULTS);
+
+ if (str == NULL) {
+ def->sd_un.ival = 0;
+ } else {
+ int seconds = parse_timeout(str);
+ if (seconds == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "%s", str);
+ debug_return_bool(false);
+ }
+ def->sd_un.ival = seconds;
+ }
+ debug_return_bool(true);
+}
+
+static bool
+valid_path(const struct sudoers_context *ctx, struct sudo_defs_types *def,
+ const char *val, const char *file, int line, int column, bool quiet)
+{
+ bool ret = true;
+ debug_decl(valid_path, SUDOERS_DEBUG_DEFAULTS);
+
+ if (strlen(val) >= PATH_MAX) {
+ defaults_warnx(ctx, file, line, column, quiet,
+ N_("path name for \"%s\" too long"), def->name);
+ ret = false;
+ }
+ if (ISSET(def->type, T_CHPATH)) {
+ if (val[0] != '/' && val[0] != '~' && (val[0] != '*' || val[1] != '\0')) {
+ defaults_warnx(ctx, file, line, column, quiet,
+ N_("values for \"%s\" must start with a '/', '~', or '*'"),
+ def->name);
+ ret = false;
+ }
+ } else {
+ if (val[0] != '/') {
+ defaults_warnx(ctx, file, line, column, quiet,
+ N_("values for \"%s\" must start with a '/'"), def->name);
+ ret = false;
+ }
+
+ }
+ debug_return_bool(ret);
+}
+
+static bool
+list_op(const char *str, size_t len, struct list_members *list,
+ enum list_ops op)
+{
+ struct list_member *cur, *prev = NULL;
+ debug_decl(list_op, SUDOERS_DEBUG_DEFAULTS);
+
+ if (op == freeall) {
+ while ((cur = SLIST_FIRST(list)) != NULL) {
+ SLIST_REMOVE_HEAD(list, entries);
+ free(cur->value);
+ free(cur);
+ }
+ debug_return_bool(true);
+ }
+
+ SLIST_FOREACH(cur, list, entries) {
+ if ((strncmp(cur->value, str, len) == 0 && cur->value[len] == '\0')) {
+
+ if (op == add)
+ debug_return_bool(true); /* already exists */
+
+ /* Delete node */
+ if (prev == NULL)
+ SLIST_REMOVE_HEAD(list, entries);
+ else
+ SLIST_REMOVE_AFTER(prev, entries);
+ free(cur->value);
+ free(cur);
+ break;
+ }
+ prev = cur;
+ }
+
+ /* Add new node to the head of the list. */
+ if (op == add) {
+ cur = calloc(1, sizeof(struct list_member));
+ if (cur == NULL || (cur->value = strndup(str, len)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ free(cur);
+ debug_return_bool(false);
+ }
+ SLIST_INSERT_HEAD(list, cur, entries);
+ }
+ debug_return_bool(true);
+}
+
+bool
+append_default(const char *var, const char *val, int op,
+ char *source, struct defaults_list *defs)
+{
+ struct defaults *def;
+ debug_decl(append_default, SUDOERS_DEBUG_DEFAULTS);
+
+ if ((def = calloc(1, sizeof(*def))) == NULL)
+ goto oom;
+
+ def->type = DEFAULTS;
+ def->op = op;
+ if ((def->var = strdup(var)) == NULL) {
+ goto oom;
+ }
+ if (val != NULL) {
+ if ((def->val = strdup(val)) == NULL)
+ goto oom;
+ }
+ def->file = source;
+ sudo_rcstr_addref(source);
+ TAILQ_INSERT_TAIL(defs, def, entries);
+ debug_return_bool(true);
+
+oom:
+ if (def != NULL) {
+ free(def->var);
+ free(def->val);
+ free(def);
+ }
+ debug_return_bool(false);
+}
+
+bool
+cb_passprompt_regex(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ struct list_member *lm;
+ const char *errstr;
+ debug_decl(cb_passprompt_regex, SUDOERS_DEBUG_DEFAULTS);
+
+ /* If adding one or more regexps, make sure they are valid. */
+ if (op == '+' || op == true) {
+ SLIST_FOREACH(lm, &sd_un->list, entries) {
+ if (!sudo_regex_compile(NULL, lm->value, &errstr)) {
+ defaults_warnx(ctx, file, line, column, false,
+ U_("invalid regular expression \"%s\": %s"),
+ lm->value, U_(errstr));
+ debug_return_bool(false);
+ }
+ }
+ }
+
+ debug_return_bool(true);
+}
diff --git a/plugins/sudoers/defaults.h b/plugins/sudoers/defaults.h
new file mode 100644
index 0000000..9909024
--- /dev/null
+++ b/plugins/sudoers/defaults.h
@@ -0,0 +1,157 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999-2005, 2008-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#ifndef SUDOERS_DEFAULTS_H
+#define SUDOERS_DEFAULTS_H
+
+#include <time.h>
+#include <def_data.h>
+#include <sudo_queue.h>
+
+struct list_member {
+ SLIST_ENTRY(list_member) entries;
+ char *value;
+};
+
+SLIST_HEAD(list_members, list_member);
+
+enum list_ops {
+ add,
+ delete,
+ freeall
+};
+
+/* Mapping of tuple string value to enum def_tuple. */
+struct def_values {
+ const char *sval; /* string value */
+ enum def_tuple nval;/* numeric value */
+};
+
+union sudo_defs_val {
+ bool flag;
+ int ival;
+ unsigned int uival;
+ enum def_tuple tuple;
+ char *str;
+ mode_t mode;
+ struct timespec tspec;
+ struct list_members list;
+};
+
+/*
+ * Structure describing compile-time and run-time options.
+ */
+struct sudoers_context;
+struct sudo_defs_types {
+ const char *name;
+ int type;
+ const char *desc;
+ struct def_values *values;
+ bool (*callback)(struct sudoers_context *ctx, const char *file, int line, int column, const union sudo_defs_val *, int op);
+ union sudo_defs_val sd_un;
+};
+
+/*
+ * Defaults values to apply before others.
+ */
+struct early_default {
+ int idx;
+ int run_callback;
+ int line;
+ int column;
+ char *file;
+};
+
+/*
+ * Four types of defaults: strings, integers, and flags.
+ * Also, T_INT, T_TIMESPEC or T_STR may be ANDed with T_BOOL to indicate that
+ * a value is not required. Flags are boolean by nature...
+ */
+#undef T_INT
+#define T_INT 0x001
+#undef T_UINT
+#define T_UINT 0x002
+#undef T_STR
+#define T_STR 0x003
+#undef T_FLAG
+#define T_FLAG 0x004
+#undef T_MODE
+#define T_MODE 0x005
+#undef T_LIST
+#define T_LIST 0x006
+#undef T_LOGFAC
+#define T_LOGFAC 0x007
+#undef T_LOGPRI
+#define T_LOGPRI 0x008
+#undef T_TUPLE
+#define T_TUPLE 0x009
+#undef T_TIMESPEC
+#define T_TIMESPEC 0x010
+#undef T_TIMEOUT
+#define T_TIMEOUT 0x011
+#undef T_RLIMIT
+#define T_RLIMIT 0x012
+#undef T_PLUGIN
+#define T_PLUGIN 0x013
+#undef T_MASK
+#define T_MASK 0x0FF
+#undef T_BOOL
+#define T_BOOL 0x100
+#undef T_PATH
+#define T_PATH 0x200
+#undef T_CHPATH
+#define T_CHPATH 0x400
+#undef T_SPACE
+#define T_SPACE 0x800
+
+/*
+ * Argument to update_defaults()
+ */
+#define SETDEF_GENERIC 0x01
+#define SETDEF_HOST 0x02
+#define SETDEF_USER 0x04
+#define SETDEF_RUNAS 0x08
+#define SETDEF_CMND 0x10
+#define SETDEF_ALL (SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER|SETDEF_RUNAS|SETDEF_CMND)
+
+/*
+ * Convenience macros
+ */
+#define iolog_enabled (def_log_stdin || def_log_ttyin || def_log_stdout || def_log_stderr || def_log_ttyout)
+
+/*
+ * Prototypes
+ */
+struct defaults_list;
+struct sudoers_parse_tree;
+void dump_default(void);
+bool init_defaults(void);
+bool set_default(struct sudoers_context *ctx, const char *var, const char *val, int op, const char *file, int line, int column, bool quiet);
+bool update_defaults(struct sudoers_context *ctx, struct sudoers_parse_tree *parse_tree, struct defaults_list *defs, int what, bool quiet);
+bool check_defaults(const struct sudoers_parse_tree *parse_tree, bool quiet);
+bool append_default(const char *var, const char *val, int op, char *source, struct defaults_list *defs);
+bool cb_passprompt_regex(struct sudoers_context *ctx, const char *file, int line, int column, const union sudo_defs_val *sd_un, int op);
+
+extern struct sudo_defs_types sudo_defs_table[];
+
+#endif /* SUDOERS_DEFAULTS_H */
diff --git a/plugins/sudoers/digestname.c b/plugins/sudoers/digestname.c
new file mode 100644
index 0000000..9415220
--- /dev/null
+++ b/plugins/sudoers/digestname.c
@@ -0,0 +1,55 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2017 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sudo_compat.h>
+#include <sudo_digest.h>
+#include <sudoers_debug.h>
+#include <parse.h>
+
+const char *
+digest_type_to_name(unsigned int digest_type)
+{
+ const char *digest_name;
+ debug_decl(digest_type_to_name, SUDOERS_DEBUG_UTIL);
+
+ switch (digest_type) {
+ case SUDO_DIGEST_SHA224:
+ digest_name = "sha224";
+ break;
+ case SUDO_DIGEST_SHA256:
+ digest_name = "sha256";
+ break;
+ case SUDO_DIGEST_SHA384:
+ digest_name = "sha384";
+ break;
+ case SUDO_DIGEST_SHA512:
+ digest_name = "sha512";
+ break;
+ default:
+ digest_name = "unknown digest";
+ break;
+ }
+ debug_return_const_str(digest_name);
+}
diff --git a/plugins/sudoers/display.c b/plugins/sudoers/display.c
new file mode 100644
index 0000000..83b4e42
--- /dev/null
+++ b/plugins/sudoers/display.c
@@ -0,0 +1,661 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2004-2005, 2007-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <pwd.h>
+
+#include <sudoers.h>
+#include <sudo_lbuf.h>
+#include <gram.h>
+
+static int
+display_priv_short(const struct sudoers_parse_tree *parse_tree,
+ const struct passwd *pw, const struct userspec *us, struct sudo_lbuf *lbuf)
+{
+ struct privilege *priv;
+ int nfound = 0;
+ debug_decl(display_priv_short, SUDOERS_DEBUG_PARSER);
+
+ TAILQ_FOREACH(priv, &us->privileges, entries) {
+ struct cmndspec *cs;
+ struct cmndtag tags;
+
+ if (hostlist_matches(parse_tree, pw, &priv->hostlist) != ALLOW)
+ continue;
+
+ sudoers_defaults_list_to_tags(&priv->defaults, &tags);
+ TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
+ struct cmndspec *prev_cs = TAILQ_PREV(cs, cmndspec_list, entries);
+
+ if (prev_cs == NULL || RUNAS_CHANGED(cs, prev_cs)) {
+ struct member *m;
+
+ /* Start new line, first entry or RunAs changed. */
+ if (prev_cs != NULL)
+ sudo_lbuf_append(lbuf, "\n");
+ sudo_lbuf_append(lbuf, " (");
+ if (cs->runasuserlist != NULL) {
+ TAILQ_FOREACH(m, cs->runasuserlist, entries) {
+ if (m != TAILQ_FIRST(cs->runasuserlist))
+ sudo_lbuf_append(lbuf, ", ");
+ sudoers_format_member(lbuf, parse_tree, m, ", ",
+ RUNASALIAS);
+ }
+ } else if (cs->runasgrouplist == NULL) {
+ sudo_lbuf_append(lbuf, "%s", def_runas_default);
+ } else {
+ sudo_lbuf_append(lbuf, "%s", pw->pw_name);
+ }
+ if (cs->runasgrouplist != NULL) {
+ sudo_lbuf_append(lbuf, " : ");
+ TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
+ if (m != TAILQ_FIRST(cs->runasgrouplist))
+ sudo_lbuf_append(lbuf, ", ");
+ sudoers_format_member(lbuf, parse_tree, m, ", ",
+ RUNASALIAS);
+ }
+ }
+ sudo_lbuf_append(lbuf, ") ");
+ sudoers_format_cmndspec(lbuf, parse_tree, cs, NULL,
+ tags, true);
+ } else {
+ /* Continue existing line. */
+ sudo_lbuf_append(lbuf, ", ");
+ sudoers_format_cmndspec(lbuf, parse_tree, cs, prev_cs,
+ tags, true);
+ }
+ nfound++;
+ }
+ sudo_lbuf_append(lbuf, "\n");
+ }
+ debug_return_int(nfound);
+}
+
+/*
+ * Compare the current cmndspec with the previous one to determine
+ * whether we need to start a new long entry for "sudo -ll".
+ * Returns true if we should start a new long entry, else false.
+ */
+static bool
+new_long_entry(const struct cmndspec *cs, const struct cmndspec *prev_cs)
+{
+ debug_decl(new_long_entry, SUDOERS_DEBUG_PARSER);
+
+ if (prev_cs == NULL)
+ debug_return_bool(true);
+ if (RUNAS_CHANGED(cs, prev_cs) || TAGS_CHANGED(prev_cs->tags, cs->tags))
+ debug_return_bool(true);
+#ifdef HAVE_PRIV_SET
+ if (cs->privs && (!prev_cs->privs || strcmp(cs->privs, prev_cs->privs) != 0))
+ debug_return_bool(true);
+ if (cs->limitprivs && (!prev_cs->limitprivs || strcmp(cs->limitprivs, prev_cs->limitprivs) != 0))
+ debug_return_bool(true);
+#endif /* HAVE_PRIV_SET */
+#ifdef HAVE_SELINUX
+ if (cs->role && (!prev_cs->role || strcmp(cs->role, prev_cs->role) != 0))
+ debug_return_bool(true);
+ if (cs->type && (!prev_cs->type || strcmp(cs->type, prev_cs->type) != 0))
+ debug_return_bool(true);
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_APPARMOR
+ if (cs->apparmor_profile && (!prev_cs->apparmor_profile || strcmp(cs->apparmor_profile, prev_cs->apparmor_profile) != 0))
+ debug_return_bool(true);
+#endif /* HAVE_APPARMOR */
+ if (cs->runchroot && (!prev_cs->runchroot || strcmp(cs->runchroot, prev_cs->runchroot) != 0))
+ debug_return_bool(true);
+ if (cs->runcwd && (!prev_cs->runcwd || strcmp(cs->runcwd, prev_cs->runcwd) != 0))
+ debug_return_bool(true);
+ if (cs->timeout != prev_cs->timeout)
+ debug_return_bool(true);
+ if (cs->notbefore != prev_cs->notbefore)
+ debug_return_bool(true);
+ if (cs->notafter != prev_cs->notafter)
+ debug_return_bool(true);
+ debug_return_bool(false);
+}
+
+static void
+display_cmndspec_long(const struct sudoers_parse_tree *parse_tree,
+ const struct passwd *pw, const struct userspec *us,
+ const struct privilege *priv, const struct cmndspec *cs,
+ const struct cmndspec *prev_cs, struct sudo_lbuf *lbuf)
+{
+ const struct defaults *d;
+ const struct member *m;
+ debug_decl(display_cmndspec_long, SUDOERS_DEBUG_PARSER);
+
+ if (new_long_entry(cs, prev_cs)) {
+ unsigned int olen;
+
+ if (prev_cs != NULL)
+ sudo_lbuf_append(lbuf, "\n");
+ if (priv->ldap_role != NULL) {
+ sudo_lbuf_append(lbuf, _("LDAP Role: %s\n"),
+ priv->ldap_role);
+ } else {
+ sudo_lbuf_append(lbuf, _("Sudoers entry: %s\n"),
+ us->file);
+ }
+ sudo_lbuf_append(lbuf, "%s", _(" RunAsUsers: "));
+ if (cs->runasuserlist != NULL) {
+ TAILQ_FOREACH(m, cs->runasuserlist, entries) {
+ if (m != TAILQ_FIRST(cs->runasuserlist))
+ sudo_lbuf_append(lbuf, ", ");
+ sudoers_format_member(lbuf, parse_tree, m, ", ",
+ RUNASALIAS);
+ }
+ } else if (cs->runasgrouplist == NULL) {
+ sudo_lbuf_append(lbuf, "%s", def_runas_default);
+ } else {
+ sudo_lbuf_append(lbuf, "%s", pw->pw_name);
+ }
+ sudo_lbuf_append(lbuf, "\n");
+ if (cs->runasgrouplist != NULL) {
+ sudo_lbuf_append(lbuf, "%s", _(" RunAsGroups: "));
+ TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
+ if (m != TAILQ_FIRST(cs->runasgrouplist))
+ sudo_lbuf_append(lbuf, ", ");
+ sudoers_format_member(lbuf, parse_tree, m, ", ",
+ RUNASALIAS);
+ }
+ sudo_lbuf_append(lbuf, "\n");
+ }
+ olen = lbuf->len;
+ sudo_lbuf_append(lbuf, "%s", _(" Options: "));
+ TAILQ_FOREACH(d, &priv->defaults, entries) {
+ sudoers_format_default(lbuf, d);
+ sudo_lbuf_append(lbuf, ", ");
+ }
+ if (TAG_SET(cs->tags.setenv))
+ sudo_lbuf_append(lbuf, "%ssetenv, ", cs->tags.setenv ? "" : "!");
+ if (TAG_SET(cs->tags.noexec))
+ sudo_lbuf_append(lbuf, "%snoexec, ", cs->tags.noexec ? "" : "!");
+ if (TAG_SET(cs->tags.intercept))
+ sudo_lbuf_append(lbuf, "%sintercept, ", cs->tags.intercept ? "" : "!");
+ if (TAG_SET(cs->tags.nopasswd))
+ sudo_lbuf_append(lbuf, "%sauthenticate, ", cs->tags.nopasswd ? "!" : "");
+ if (TAG_SET(cs->tags.log_input))
+ sudo_lbuf_append(lbuf, "%slog_input, ", cs->tags.log_input ? "" : "!");
+ if (TAG_SET(cs->tags.log_output))
+ sudo_lbuf_append(lbuf, "%slog_output, ", cs->tags.log_output ? "" : "!");
+ if (lbuf->buf[lbuf->len - 2] == ',') {
+ lbuf->len -= 2; /* remove trailing ", " */
+ sudo_lbuf_append(lbuf, "\n");
+ } else {
+ lbuf->len = olen; /* no options */
+ }
+#ifdef HAVE_PRIV_SET
+ if (cs->privs)
+ sudo_lbuf_append(lbuf, " Privs: %s\n", cs->privs);
+ if (cs->limitprivs)
+ sudo_lbuf_append(lbuf, " Limitprivs: %s\n", cs->limitprivs);
+#endif /* HAVE_PRIV_SET */
+#ifdef HAVE_SELINUX
+ if (cs->role)
+ sudo_lbuf_append(lbuf, " Role: %s\n", cs->role);
+ if (cs->type)
+ sudo_lbuf_append(lbuf, " Type: %s\n", cs->type);
+#endif /* HAVE_SELINUX */
+ if (cs->runchroot != NULL)
+ sudo_lbuf_append(lbuf, " Chroot: %s\n", cs->runchroot);
+ if (cs->runcwd != NULL)
+ sudo_lbuf_append(lbuf, " Cwd: %s\n", cs->runcwd);
+ if (cs->timeout > 0) {
+ char numbuf[STRLEN_MAX_SIGNED(int) + 1];
+ (void)snprintf(numbuf, sizeof(numbuf), "%d", cs->timeout);
+ sudo_lbuf_append(lbuf, " Timeout: %s\n", numbuf);
+ }
+ if (cs->notbefore != UNSPEC) {
+ char buf[sizeof("CCYYMMDDHHMMSSZ")] = "";
+ struct tm gmt;
+ size_t len;
+ if (gmtime_r(&cs->notbefore, &gmt) != NULL) {
+ len = strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", &gmt);
+ if (len != 0 && buf[sizeof(buf) - 1] == '\0')
+ sudo_lbuf_append(lbuf, " NotBefore: %s\n", buf);
+ }
+ }
+ if (cs->notafter != UNSPEC) {
+ char buf[sizeof("CCYYMMDDHHMMSSZ")] = "";
+ struct tm gmt;
+ size_t len;
+ if (gmtime_r(&cs->notafter, &gmt) != NULL) {
+ len = strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", &gmt);
+ if (len != 0 && buf[sizeof(buf) - 1] == '\0')
+ sudo_lbuf_append(lbuf, " NotAfter: %s\n", buf);
+ }
+ }
+ sudo_lbuf_append(lbuf, "%s", _(" Commands:\n"));
+ }
+ sudo_lbuf_append(lbuf, "\t");
+ sudoers_format_member(lbuf, parse_tree, cs->cmnd, "\n\t",
+ CMNDALIAS);
+ sudo_lbuf_append(lbuf, "\n");
+
+ debug_return;
+}
+
+static int
+display_priv_long(const struct sudoers_parse_tree *parse_tree,
+ const struct passwd *pw, const struct userspec *us, struct sudo_lbuf *lbuf)
+{
+ const struct privilege *priv;
+ int nfound = 0;
+ debug_decl(display_priv_long, SUDOERS_DEBUG_PARSER);
+
+ TAILQ_FOREACH(priv, &us->privileges, entries) {
+ const struct cmndspec *cs, *prev_cs;
+
+ if (hostlist_matches(parse_tree, pw, &priv->hostlist) != ALLOW)
+ continue;
+ prev_cs = NULL;
+ sudo_lbuf_append(lbuf, "\n");
+ TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
+ display_cmndspec_long(parse_tree, pw, us, priv, cs, prev_cs,
+ lbuf);
+ prev_cs = cs;
+ nfound++;
+ }
+ }
+ debug_return_int(nfound);
+}
+
+static int
+sudo_display_userspecs(struct sudoers_parse_tree *parse_tree,
+ const struct passwd *pw, struct sudo_lbuf *lbuf, bool verbose)
+{
+ const struct userspec *us;
+ int nfound = 0;
+ debug_decl(sudo_display_userspecs, SUDOERS_DEBUG_PARSER);
+
+ TAILQ_FOREACH(us, &parse_tree->userspecs, entries) {
+ if (userlist_matches(parse_tree, pw, &us->users) != ALLOW)
+ continue;
+
+ if (verbose)
+ nfound += display_priv_long(parse_tree, pw, us, lbuf);
+ else
+ nfound += display_priv_short(parse_tree, pw, us, lbuf);
+ }
+ if (sudo_lbuf_error(lbuf))
+ debug_return_int(-1);
+ debug_return_int(nfound);
+}
+
+/*
+ * Display matching Defaults entries for the given user on this host.
+ */
+static int
+display_defaults(const struct sudoers_parse_tree *parse_tree,
+ const struct passwd *pw, struct sudo_lbuf *lbuf)
+{
+ const struct defaults *d;
+ const char *prefix;
+ int nfound = 0;
+ debug_decl(display_defaults, SUDOERS_DEBUG_PARSER);
+
+ if (lbuf->len == 0 || isspace((unsigned char)lbuf->buf[lbuf->len - 1]))
+ prefix = " ";
+ else
+ prefix = ", ";
+
+ TAILQ_FOREACH(d, &parse_tree->defaults, entries) {
+ switch (d->type) {
+ case DEFAULTS_HOST:
+ if (hostlist_matches(parse_tree, pw, &d->binding->members) != ALLOW)
+ continue;
+ break;
+ case DEFAULTS_USER:
+ if (userlist_matches(parse_tree, pw, &d->binding->members) != ALLOW)
+ continue;
+ break;
+ case DEFAULTS_RUNAS:
+ case DEFAULTS_CMND:
+ continue;
+ }
+ sudo_lbuf_append(lbuf, "%s", prefix);
+ sudoers_format_default(lbuf, d);
+ prefix = ", ";
+ nfound++;
+ }
+ if (sudo_lbuf_error(lbuf))
+ debug_return_int(-1);
+ debug_return_int(nfound);
+}
+
+/*
+ * Display Defaults entries of the given type.
+ */
+static int
+display_bound_defaults_by_type(const struct sudoers_parse_tree *parse_tree,
+ int deftype, struct sudo_lbuf *lbuf)
+{
+ const struct defaults *d;
+ const struct defaults_binding *binding = NULL;
+ const struct member *m;
+ const char *dsep;
+ short atype;
+ int nfound = 0;
+ debug_decl(display_bound_defaults_by_type, SUDOERS_DEBUG_PARSER);
+
+ switch (deftype) {
+ case DEFAULTS_HOST:
+ atype = HOSTALIAS;
+ dsep = "@";
+ break;
+ case DEFAULTS_USER:
+ atype = USERALIAS;
+ dsep = ":";
+ break;
+ case DEFAULTS_RUNAS:
+ atype = RUNASALIAS;
+ dsep = ">";
+ break;
+ case DEFAULTS_CMND:
+ atype = CMNDALIAS;
+ dsep = "!";
+ break;
+ default:
+ debug_return_int(-1);
+ }
+ TAILQ_FOREACH(d, &parse_tree->defaults, entries) {
+ if (d->type != deftype)
+ continue;
+
+ nfound++;
+ if (binding != d->binding) {
+ binding = d->binding;
+ if (nfound != 1)
+ sudo_lbuf_append(lbuf, "\n");
+ sudo_lbuf_append(lbuf, " Defaults%s", dsep);
+ TAILQ_FOREACH(m, &binding->members, entries) {
+ if (m != TAILQ_FIRST(&binding->members))
+ sudo_lbuf_append(lbuf, ", ");
+ sudoers_format_member(lbuf, parse_tree, m, ", ", atype);
+ }
+ sudo_lbuf_append(lbuf, " ");
+ } else
+ sudo_lbuf_append(lbuf, ", ");
+ sudoers_format_default(lbuf, d);
+ }
+
+ if (sudo_lbuf_error(lbuf))
+ debug_return_int(-1);
+ debug_return_int(nfound);
+}
+
+/*
+ * Display Defaults entries that are per-runas or per-command
+ */
+static int
+display_bound_defaults(const struct sudoers_parse_tree *parse_tree,
+ const struct passwd *pw, struct sudo_lbuf *lbuf)
+{
+ int nfound = 0;
+ debug_decl(display_bound_defaults, SUDOERS_DEBUG_PARSER);
+
+ /* XXX - should only print ones that match what the user can do. */
+ nfound += display_bound_defaults_by_type(parse_tree, DEFAULTS_RUNAS,
+ lbuf);
+ nfound += display_bound_defaults_by_type(parse_tree, DEFAULTS_CMND,
+ lbuf);
+
+ if (sudo_lbuf_error(lbuf))
+ debug_return_int(-1);
+ debug_return_int(nfound);
+}
+
+static int
+output(const char *buf)
+{
+ struct sudo_conv_message msg;
+ struct sudo_conv_reply repl;
+ debug_decl(output, SUDOERS_DEBUG_NSS);
+
+ /* Call conversation function */
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_type = SUDO_CONV_INFO_MSG;
+ msg.msg = buf;
+ memset(&repl, 0, sizeof(repl));
+ if (sudo_conv(1, &msg, &repl, NULL) == -1)
+ debug_return_int(0);
+ debug_return_int((int)strlen(buf));
+}
+
+/*
+ * Print out privileges for the specified user.
+ * Returns true on success or -1 on error.
+ */
+int
+display_privs(struct sudoers_context *ctx, const struct sudo_nss_list *snl,
+ struct passwd *pw, int verbose)
+{
+ const struct sudo_nss *nss;
+ struct sudo_lbuf def_buf, priv_buf;
+ int cols, count, n;
+ unsigned int olen;
+ struct stat sb;
+ debug_decl(display_privs, SUDOERS_DEBUG_PARSER);
+
+ if (verbose < 0) {
+ /* Nothing to display. */
+ debug_return_int(true);
+ }
+
+ cols = ctx->user.cols;
+ if (fstat(STDOUT_FILENO, &sb) == 0 && S_ISFIFO(sb.st_mode))
+ cols = 0;
+ sudo_lbuf_init(&def_buf, output, 4, NULL, cols);
+ sudo_lbuf_init(&priv_buf, output, 8, NULL, cols);
+
+ sudo_lbuf_append(&def_buf, _("Matching Defaults entries for %s on %s:\n"),
+ pw->pw_name, ctx->runas.shost);
+ count = 0;
+ TAILQ_FOREACH(nss, snl, entries) {
+ n = display_defaults(nss->parse_tree, pw, &def_buf);
+ if (n == -1)
+ goto bad;
+ count += n;
+ }
+ if (count != 0) {
+ sudo_lbuf_append(&def_buf, "\n\n");
+ } else {
+ /* Undo Defaults header. */
+ def_buf.len = 0;
+ }
+
+ /* Display Runas and Cmnd-specific defaults. */
+ olen = def_buf.len;
+ sudo_lbuf_append(&def_buf, _("Runas and Command-specific defaults for %s:\n"),
+ pw->pw_name);
+ count = 0;
+ TAILQ_FOREACH(nss, snl, entries) {
+ n = display_bound_defaults(nss->parse_tree, pw, &def_buf);
+ if (n == -1)
+ goto bad;
+ count += n;
+ }
+ if (count != 0) {
+ sudo_lbuf_append(&def_buf, "\n\n");
+ } else {
+ /* Undo Defaults header. */
+ def_buf.len = olen;
+ }
+
+ /* Display privileges from all sources. */
+ sudo_lbuf_append(&priv_buf,
+ _("User %s may run the following commands on %s:\n"),
+ pw->pw_name, ctx->runas.shost);
+ count = 0;
+ TAILQ_FOREACH(nss, snl, entries) {
+ if (nss->query(ctx, nss, pw) != -1) {
+ n = sudo_display_userspecs(nss->parse_tree, pw, &priv_buf,
+ verbose);
+ if (n == -1)
+ goto bad;
+ count += n;
+ }
+ }
+ if (count == 0) {
+ def_buf.len = 0;
+ priv_buf.len = 0;
+ sudo_lbuf_append(&priv_buf,
+ _("User %s is not allowed to run sudo on %s.\n"),
+ pw->pw_name, ctx->runas.shost);
+ }
+ if (sudo_lbuf_error(&def_buf) || sudo_lbuf_error(&priv_buf))
+ goto bad;
+
+ sudo_lbuf_print(&def_buf);
+ sudo_lbuf_print(&priv_buf);
+
+ sudo_lbuf_destroy(&def_buf);
+ sudo_lbuf_destroy(&priv_buf);
+
+ debug_return_int(true);
+bad:
+ sudo_lbuf_destroy(&def_buf);
+ sudo_lbuf_destroy(&priv_buf);
+
+ debug_return_int(-1);
+}
+
+static int
+display_cmnd_check(struct sudoers_context *ctx,
+ const struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
+ time_t now, struct sudoers_match_info *match_info)
+{
+ int host_match, runas_match, cmnd_match = UNSPEC;
+ char *saved_user_cmnd, *saved_user_base;
+ const struct privilege *priv;
+ const struct userspec *us;
+ const struct cmndspec *cs;
+ debug_decl(display_cmnd_check, SUDOERS_DEBUG_PARSER);
+
+ /*
+ * For "sudo -l command", ctx->user.cmnd is "list" and the actual
+ * command we are checking is in ctx->user.cmnd_list.
+ */
+ saved_user_cmnd = ctx->user.cmnd;
+ saved_user_base = ctx->user.cmnd_base;
+ ctx->user.cmnd = ctx->user.cmnd_list;
+ ctx->user.cmnd_base = sudo_basename(ctx->user.cmnd);
+
+ TAILQ_FOREACH_REVERSE(us, &parse_tree->userspecs, userspec_list, entries) {
+ if (userlist_matches(parse_tree, pw, &us->users) != ALLOW)
+ continue;
+ TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
+ host_match = hostlist_matches(parse_tree, pw, &priv->hostlist);
+ if (host_match != ALLOW)
+ continue;
+ TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) {
+ if (cs->notbefore != UNSPEC) {
+ if (now < cs->notbefore)
+ continue;
+ }
+ if (cs->notafter != UNSPEC) {
+ if (now > cs->notafter)
+ continue;
+ }
+ runas_match = runaslist_matches(parse_tree, cs->runasuserlist,
+ cs->runasgrouplist, NULL, NULL);
+ if (runas_match == ALLOW) {
+ cmnd_match = cmnd_matches(parse_tree, cs->cmnd,
+ cs->runchroot, NULL);
+ if (cmnd_match != UNSPEC) {
+ match_info->parse_tree = parse_tree;
+ match_info->us = us;
+ match_info->priv = priv;
+ match_info->cs = cs;
+ goto done;
+ }
+ }
+ }
+ }
+ }
+done:
+ ctx->user.cmnd = saved_user_cmnd;
+ ctx->user.cmnd_base = saved_user_base;
+ debug_return_int(cmnd_match);
+}
+
+/*
+ * Check ctx->user.cmnd against sudoers and print the matching entry if the
+ * command is allowed.
+ * Returns true if the command is allowed, false if not or -1 on error.
+ */
+int
+display_cmnd(struct sudoers_context *ctx, const struct sudo_nss_list *snl,
+ struct passwd *pw, int verbose)
+{
+ struct sudoers_match_info match_info = { NULL };
+ struct sudo_lbuf lbuf;
+ struct sudo_nss *nss;
+ int m, match = UNSPEC;
+ int ret = false;
+ time_t now;
+ debug_decl(display_cmnd, SUDOERS_DEBUG_PARSER);
+
+ /* Iterate over each source, checking for the command. */
+ time(&now);
+ sudo_lbuf_init(&lbuf, output, 0, NULL, 0);
+ TAILQ_FOREACH(nss, snl, entries) {
+ if (nss->query(ctx, nss, pw) == -1) {
+ /* The query function should have printed an error message. */
+ debug_return_int(-1);
+ }
+
+ m = display_cmnd_check(ctx, nss->parse_tree, pw, now, &match_info);
+ if (m != UNSPEC)
+ match = m;
+
+ if (!sudo_nss_can_continue(nss, m))
+ break;
+ }
+ if (match == ALLOW) {
+ if (verbose < 0) {
+ /* Nothing to display. */
+ debug_return_int(true);
+ }
+ if (verbose) {
+ /* Append matching sudoers rule (long form). */
+ display_cmndspec_long(match_info.parse_tree, pw, match_info.us,
+ match_info.priv, match_info.cs, NULL, &lbuf);
+ sudo_lbuf_append(&lbuf, " Matched: ");
+ }
+ sudo_lbuf_append(&lbuf, "%s%s%s\n", ctx->user.cmnd_list,
+ ctx->user.cmnd_args ? " " : "",
+ ctx->user.cmnd_args ? ctx->user.cmnd_args : "");
+ sudo_lbuf_print(&lbuf);
+ ret = sudo_lbuf_error(&lbuf) ? -1 : true;
+ sudo_lbuf_destroy(&lbuf);
+ }
+ debug_return_int(ret);
+}
diff --git a/plugins/sudoers/editor.c b/plugins/sudoers/editor.c
new file mode 100644
index 0000000..db1e3e0
--- /dev/null
+++ b/plugins/sudoers/editor.c
@@ -0,0 +1,275 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2015, 2020-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sudoers.h>
+
+/*
+ * Non-destructive word-split that handles single and double quotes and
+ * escaped white space. Quotes are only recognized at the start of a word.
+ * They are treated as normal characters inside a word.
+ */
+static const char *
+wordsplit(const char *str, const char *endstr, const char **last)
+{
+ const char *cp;
+ debug_decl(wordsplit, SUDOERS_DEBUG_UTIL);
+
+ /* If no str specified, use last ptr (if any). */
+ if (str == NULL) {
+ str = *last;
+ /* Consume end quote if present. */
+ if (*str == '"' || *str == '\'')
+ str++;
+ }
+
+ /* Skip leading white space characters. */
+ while (str < endstr && (*str == ' ' || *str == '\t'))
+ str++;
+
+ /* Empty string? */
+ if (str >= endstr) {
+ *last = endstr;
+ debug_return_ptr(NULL);
+ }
+
+ /* If word is quoted, skip to end quote and return. */
+ if (*str == '"' || *str == '\'') {
+ const char *endquote;
+ for (cp = str + 1; cp < endstr; cp = endquote + 1) {
+ endquote = memchr(cp, *str, (size_t)(endstr - cp));
+ if (endquote == NULL)
+ break;
+ /* ignore escaped quotes */
+ if (endquote[-1] != '\\') {
+ *last = endquote;
+ debug_return_const_ptr(str + 1);
+ }
+ }
+ }
+
+ /* Scan str until we encounter white space. */
+ for (cp = str; cp < endstr; cp++) {
+ if (cp[0] == '\\' && cp[1] != '\0') {
+ /* quoted char, do not interpret */
+ cp++;
+ continue;
+ }
+ if (*cp == ' ' || *cp == '\t') {
+ /* end of word */
+ break;
+ }
+ }
+ *last = cp;
+ debug_return_const_ptr(str);
+}
+
+/* Copy len chars from string, collapsing chars escaped with a backslash. */
+static char *
+copy_arg(const char *src, size_t len)
+{
+ const char *src_end = src + len;
+ char *copy, *dst;
+ debug_decl(copy_arg, SUDOERS_DEBUG_UTIL);
+
+ if ((copy = malloc(len + 1)) != NULL) {
+ sudoers_gc_add(GC_PTR, copy);
+ for (dst = copy; src < src_end; ) {
+ if (src[0] == '\\' && src[1] != '\0')
+ src++;
+ *dst++ = *src++;
+ }
+ *dst = '\0';
+ }
+
+ debug_return_ptr(copy);
+}
+
+/*
+ * Search for the specified editor in the user's PATH, checking
+ * the result against allowlist if non-NULL. An argument vector
+ * suitable for execve() is allocated and stored in argv_out.
+ * If nfiles is non-zero, files[] is added to the end of argv_out.
+ *
+ * Returns the path to be executed on success, else NULL.
+ * The caller is responsible for freeing the returned editor path
+ * as well as the argument vector.
+ */
+static char *
+resolve_editor(const char *ed, size_t edlen, int nfiles, char * const *files,
+ int *argc_out, char ***argv_out, char * const *allowlist)
+{
+ char **nargv = NULL, *editor = NULL, *editor_path = NULL;
+ const char *tmp, *cp, *ep = NULL;
+ const char *edend = ed + edlen;
+ struct stat user_editor_sb;
+ int nargc = 0;
+ debug_decl(resolve_editor, SUDOERS_DEBUG_UTIL);
+
+ /*
+ * Split editor into an argument vector, including files to edit.
+ * The EDITOR and VISUAL environment variables may contain command
+ * line args so look for those and alloc space for them too.
+ */
+ cp = wordsplit(ed, edend, &ep);
+ if (cp == NULL)
+ debug_return_str(NULL);
+ editor = copy_arg(cp, (size_t)(ep - cp));
+ if (editor == NULL)
+ goto oom;
+
+ /* If we can't find the editor in the user's PATH, give up. */
+ if (find_path(editor, &editor_path, &user_editor_sb, getenv("PATH"),
+ false, allowlist) != FOUND) {
+ errno = ENOENT;
+ goto bad;
+ }
+
+ /* Count rest of arguments and allocate editor argv. */
+ for (nargc = 1, tmp = ep; wordsplit(NULL, edend, &tmp) != NULL; )
+ nargc++;
+ if (nfiles != 0)
+ nargc += nfiles + 1;
+ nargv = reallocarray(NULL, (size_t)nargc + 1, sizeof(char *));
+ if (nargv == NULL)
+ goto oom;
+ sudoers_gc_add(GC_PTR, nargv);
+
+ /* Fill in editor argv (assumes files[] is NULL-terminated). */
+ nargv[0] = editor;
+ editor = NULL;
+ for (nargc = 1; (cp = wordsplit(NULL, edend, &ep)) != NULL; nargc++) {
+ /* Copy string, collapsing chars escaped with a backslash. */
+ nargv[nargc] = copy_arg(cp, (size_t)(ep - cp));
+ if (nargv[nargc] == NULL)
+ goto oom;
+
+ /*
+ * We use "--" to separate the editor and arguments from the files
+ * to edit. The editor arguments themselves may not contain "--".
+ */
+ if (strcmp(nargv[nargc], "--") == 0) {
+ sudo_warnx(U_("ignoring editor: %.*s"), (int)edlen, ed);
+ sudo_warnx("%s", U_("editor arguments may not contain \"--\""));
+ errno = EINVAL;
+ goto bad;
+ }
+ }
+ if (nfiles != 0) {
+ nargv[nargc++] = (char *)"--";
+ do
+ nargv[nargc++] = *files++;
+ while (--nfiles > 0);
+ }
+ nargv[nargc] = NULL;
+
+ *argc_out = nargc;
+ *argv_out = nargv;
+ debug_return_str(editor_path);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+bad:
+ sudoers_gc_remove(GC_PTR, editor);
+ free(editor);
+ free(editor_path);
+ if (nargv != NULL) {
+ while (nargc > 0) {
+ sudoers_gc_remove(GC_PTR, nargv[--nargc]);
+ free(nargv[nargc]);
+ }
+ sudoers_gc_remove(GC_PTR, nargv);
+ free(nargv);
+ }
+ debug_return_str(NULL);
+}
+
+/*
+ * Determine which editor to use based on the SUDO_EDITOR, VISUAL and
+ * EDITOR environment variables as well as the editor path in sudoers.
+ *
+ * Returns the path to be executed on success, else NULL.
+ * The caller is responsible for freeing the returned editor path
+ * as well as the argument vector.
+ */
+char *
+find_editor(int nfiles, char * const *files, int *argc_out, char ***argv_out,
+ char * const *allowlist, const char **env_editor)
+{
+ char *editor_path = NULL;
+ const char *ev[3];
+ size_t i;
+ debug_decl(find_editor, SUDOERS_DEBUG_UTIL);
+
+ /*
+ * If any of SUDO_EDITOR, VISUAL or EDITOR are set, choose the first one.
+ */
+ *env_editor = NULL;
+ ev[0] = "SUDO_EDITOR";
+ ev[1] = "VISUAL";
+ ev[2] = "EDITOR";
+ for (i = 0; i < nitems(ev); i++) {
+ char *editor = getenv(ev[i]);
+
+ if (editor != NULL && *editor != '\0') {
+ *env_editor = editor;
+ editor_path = resolve_editor(editor, strlen(editor),
+ nfiles, files, argc_out, argv_out, allowlist);
+ if (editor_path != NULL)
+ break;
+ if (errno != ENOENT)
+ debug_return_str(NULL);
+ }
+ }
+
+ /*
+ * If SUDO_EDITOR, VISUAL and EDITOR were either not set or not
+ * allowed (based on the values of def_editor and def_env_editor),
+ * choose the first one in def_editor that exists.
+ */
+ if (editor_path == NULL) {
+ const char *def_editor_end = def_editor + strlen(def_editor);
+ const char *cp, *ep;
+
+ /* def_editor could be a path, split it up, avoiding strtok() */
+ for (cp = sudo_strsplit(def_editor, def_editor_end, ":", &ep);
+ cp != NULL; cp = sudo_strsplit(NULL, def_editor_end, ":", &ep)) {
+ editor_path = resolve_editor(cp, (size_t)(ep - cp), nfiles,
+ files, argc_out, argv_out, allowlist);
+ if (editor_path != NULL)
+ break;
+ if (errno != ENOENT)
+ debug_return_str(NULL);
+ }
+ }
+
+ /* Caller is responsible for freeing editor_path, not g/c'd. */
+ debug_return_str(editor_path);
+}
diff --git a/plugins/sudoers/env.c b/plugins/sudoers/env.c
new file mode 100644
index 0000000..e3f28f1
--- /dev/null
+++ b/plugins/sudoers/env.c
@@ -0,0 +1,1444 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2000-2005, 2007-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#ifdef HAVE_LOGIN_CAP_H
+# include <login_cap.h>
+# ifndef LOGIN_SETENV
+# define LOGIN_SETENV 0
+# endif
+#endif /* HAVE_LOGIN_CAP_H */
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <pwd.h>
+
+#include <sudoers.h>
+
+/*
+ * Flags used in rebuild_env()
+ */
+#undef DID_TERM
+#define DID_TERM 0x00000001
+#undef DID_PATH
+#define DID_PATH 0x00000002
+#undef DID_HOME
+#define DID_HOME 0x00000004
+#undef DID_SHELL
+#define DID_SHELL 0x00000008
+#undef DID_LOGNAME
+#define DID_LOGNAME 0x00000010
+#undef DID_USER
+#define DID_USER 0x00000020
+#undef DID_LOGIN
+#define DID_LOGIN 0x00000040
+#undef DID_MAIL
+#define DID_MAIL 0x00000080
+#undef DID_MAX
+#define DID_MAX 0x0000ffff
+
+#undef KEPT_TERM
+#define KEPT_TERM 0x00010000
+#undef KEPT_PATH
+#define KEPT_PATH 0x00020000
+#undef KEPT_HOME
+#define KEPT_HOME 0x00040000
+#undef KEPT_SHELL
+#define KEPT_SHELL 0x00080000
+#undef KEPT_LOGNAME
+#define KEPT_LOGNAME 0x00100000
+#undef KEPT_USER
+#define KEPT_USER 0x00200000
+#undef KEPT_LOGIN
+#define KEPT_LOGIN 0x00400000
+#undef KEPT_MAIL
+#define KEPT_MAIL 0x00800000
+#undef KEPT_MAX
+#define KEPT_MAX 0xffff0000
+
+/*
+ * AIX sets the LOGIN environment variable too.
+ */
+#ifdef _AIX
+# define KEPT_USER_VARIABLES (KEPT_LOGIN|KEPT_LOGNAME|KEPT_USER)
+#else
+# define KEPT_USER_VARIABLES (KEPT_LOGNAME|KEPT_USER)
+#endif
+
+/*
+ * Functions to open, close and parse an environment file, either
+ * a system file such as /etc/environment or one specified in sudoers.
+ */
+struct sudoers_env_file {
+ void * (*open)(const char *);
+ void (*close)(void *);
+ char * (*next)(void *, int *);
+};
+
+/*
+ * State for a local environment file.
+ */
+struct env_file_local {
+ FILE *fp;
+ char *line;
+ size_t linesize;
+};
+
+struct environment {
+ char **envp; /* pointer to the new environment */
+ char **old_envp; /* pointer the old environment we allocated */
+ size_t env_size; /* size of new_environ in char **'s */
+ size_t env_len; /* number of slots used, not counting NULL */
+};
+
+/*
+ * Copy of the sudo-managed environment.
+ */
+static struct environment env;
+
+/*
+ * Default table of "bad" variables to remove from the environment.
+ * XXX - how to omit TERMCAP if it starts with '/'?
+ */
+static const char *initial_badenv_table[] = {
+ "IFS",
+ "CDPATH",
+ "LOCALDOMAIN",
+ "RES_OPTIONS",
+ "HOSTALIASES",
+ "NLSPATH",
+ "PATH_LOCALE",
+ "LD_*",
+ "_RLD*",
+#ifdef __hpux
+ "SHLIB_PATH",
+#endif /* __hpux */
+#ifdef _AIX
+ "LDR_*",
+ "LIBPATH",
+ "AUTHSTATE",
+#endif
+#ifdef __APPLE__
+ "DYLD_*",
+#endif
+#ifdef HAVE_KERB5
+ "KRB5_CONFIG*",
+ "KRB5_KTNAME",
+#endif /* HAVE_KERB5 */
+#ifdef HAVE_SECURID
+ "VAR_ACE",
+ "USR_ACE",
+ "DLC_ACE",
+#endif /* HAVE_SECURID */
+ "TERMINFO", /* terminfo, exclusive path to terminfo files */
+ "TERMINFO_DIRS", /* terminfo, path(s) to terminfo files */
+ "TERMPATH", /* termcap, path(s) to termcap files */
+ "TERMCAP", /* XXX - only if it starts with '/' */
+ "ENV", /* ksh, file to source before script runs */
+ "BASH_ENV", /* bash, file to source before script runs */
+ "PS4", /* bash, prefix for lines in xtrace mode */
+ "GLOBIGNORE", /* bash, globbing patterns to ignore */
+ "BASHOPTS", /* bash, initial "shopt -s" options */
+ "SHELLOPTS", /* bash, initial "set -o" options */
+ "JAVA_TOOL_OPTIONS", /* java, extra command line options */
+ "PERLIO_DEBUG", /* perl, debugging output file */
+ "PERLLIB", /* perl, search path for modules/includes */
+ "PERL5LIB", /* perl 5, search path for modules/includes */
+ "PERL5OPT", /* perl 5, extra command line options */
+ "PERL5DB", /* perl 5, command used to load debugger */
+ "FPATH", /* ksh, search path for functions */
+ "NULLCMD", /* zsh, command for null file redirection */
+ "READNULLCMD", /* zsh, command for null file redirection */
+ "ZDOTDIR", /* zsh, search path for dot files */
+ "TMPPREFIX", /* zsh, prefix for temporary files */
+ "PYTHONHOME", /* python, module search path */
+ "PYTHONPATH", /* python, search path */
+ "PYTHONINSPECT", /* python, allow inspection */
+ "PYTHONUSERBASE", /* python, per user site-packages directory */
+ "RUBYLIB", /* ruby, library load path */
+ "RUBYOPT", /* ruby, extra command line options */
+ "*=()*", /* bash functions */
+ NULL
+};
+
+/*
+ * Default table of variables to check for '%' and '/' characters.
+ */
+static const char *initial_checkenv_table[] = {
+ "COLORTERM",
+ "LANG",
+ "LANGUAGE",
+ "LC_*",
+ "LINGUAS",
+ "TERM",
+ "TZ",
+ NULL
+};
+
+/*
+ * Default table of variables to preserve in the environment.
+ */
+static const char *initial_keepenv_table[] = {
+ "COLORS",
+ "DISPLAY",
+ "HOSTNAME",
+ "KRB5CCNAME",
+ "LS_COLORS",
+ "PATH",
+ "PS1",
+ "PS2",
+ "XAUTHORITY",
+ "XAUTHORIZATION",
+ "XDG_CURRENT_DESKTOP",
+ NULL
+};
+
+/*
+ * Free our copy (or copies) of the environment.
+ * This function is only safe to call after the command has executed.
+ */
+void
+env_free(void)
+{
+ sudoers_gc_remove(GC_PTR, env.envp);
+ free(env.envp);
+ sudoers_gc_remove(GC_PTR, env.old_envp);
+ free(env.old_envp);
+ memset(&env, 0, sizeof(env));
+}
+
+/*
+ * Initialize env based on envp.
+ */
+bool
+env_init(char * const envp[])
+{
+ char * const *ep;
+ size_t len;
+ debug_decl(env_init, SUDOERS_DEBUG_ENV);
+
+ if (envp == NULL) {
+ /* Free the old envp we allocated, if any. */
+ sudoers_gc_remove(GC_PTR, env.old_envp);
+ free(env.old_envp);
+
+ /*
+ * Reset to initial state but keep a pointer to what we allocated
+ * since it will be passed to execve(2).
+ */
+ env.old_envp = env.envp;
+ env.envp = NULL;
+ env.env_size = 0;
+ env.env_len = 0;
+ } else {
+ /* Make private copy of envp. */
+ for (ep = envp; *ep != NULL; ep++)
+ continue;
+ len = (size_t)(ep - envp);
+
+ env.env_len = len;
+ env.env_size = len + 1 + 128;
+ env.envp = reallocarray(NULL, env.env_size, sizeof(char *));
+ if (env.envp == NULL) {
+ env.env_size = 0;
+ env.env_len = 0;
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ sudoers_gc_add(GC_PTR, env.envp);
+#ifdef ENV_DEBUG
+ memset(env.envp, 0, env.env_size * sizeof(char *));
+#endif
+ memcpy(env.envp, envp, len * sizeof(char *));
+ env.envp[len] = NULL;
+
+ /* Free the old envp we allocated, if any. */
+ sudoers_gc_remove(GC_PTR, env.old_envp);
+ free(env.old_envp);
+ env.old_envp = NULL;
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Getter for private copy of the environment.
+ */
+char **
+env_get(void)
+{
+ return env.envp;
+}
+
+/*
+ * Swap the old and new copies of the environment.
+ */
+bool
+env_swap_old(void)
+{
+ char **old_envp;
+
+ if (env.old_envp == NULL)
+ return false;
+ old_envp = env.old_envp;
+ env.old_envp = env.envp;
+ env.envp = old_envp;
+ return true;
+}
+
+/*
+ * Similar to putenv(3) but operates on sudo's private copy of the
+ * environment (not environ) and it always overwrites. The dupcheck param
+ * determines whether we need to verify that the variable is not already set.
+ * Will only overwrite an existing variable if overwrite is set.
+ * Does not include warnings or debugging to avoid recursive calls.
+ */
+int
+sudo_putenv_nodebug(char *str, bool dupcheck, bool overwrite)
+{
+ char **ep;
+ const char *equal;
+ bool found = false;
+
+ /* Some putenv(3) implementations check for NULL. */
+ if (str == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* The string must contain a '=' char but not start with one. */
+ equal = strchr(str, '=');
+ if (equal == NULL || equal == str) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Make sure there is room for the new entry plus a NULL. */
+ if (env.env_size > 2 && env.env_len > env.env_size - 2) {
+ char **nenvp;
+ size_t nsize;
+
+ if (env.env_size > SIZE_MAX - 128) {
+ sudo_warnx_nodebug(U_("internal error, %s overflow"),
+ "sudo_putenv_nodebug");
+ errno = EOVERFLOW;
+ return -1;
+ }
+ nsize = env.env_size + 128;
+ if (nsize > SIZE_MAX / sizeof(char *)) {
+ sudo_warnx_nodebug(U_("internal error, %s overflow"),
+ "sudo_putenv_nodebug");
+ errno = EOVERFLOW;
+ return -1;
+ }
+ sudoers_gc_remove(GC_PTR, env.envp);
+ nenvp = reallocarray(env.envp, nsize, sizeof(char *));
+ if (nenvp == NULL) {
+ sudoers_gc_add(GC_PTR, env.envp);
+ return -1;
+ }
+ sudoers_gc_add(GC_PTR, nenvp);
+ env.envp = nenvp;
+ env.env_size = nsize;
+#ifdef ENV_DEBUG
+ memset(env.envp + env.env_len, 0,
+ (env.env_size - env.env_len) * sizeof(char *));
+#endif
+ }
+
+#ifdef ENV_DEBUG
+ if (env.envp[env.env_len] != NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+#endif
+
+ if (dupcheck) {
+ size_t len = (size_t)(equal - str) + 1;
+ for (ep = env.envp; *ep != NULL; ep++) {
+ if (strncmp(str, *ep, len) == 0) {
+ if (overwrite)
+ *ep = str;
+ found = true;
+ break;
+ }
+ }
+ /* Prune out extra instances of the variable we just overwrote. */
+ if (found && overwrite) {
+ while (*++ep != NULL) {
+ if (strncmp(str, *ep, len) == 0) {
+ char **cur = ep;
+ while ((*cur = *(cur + 1)) != NULL)
+ cur++;
+ ep--;
+ }
+ }
+ env.env_len = (size_t)(ep - env.envp);
+ }
+ }
+
+ if (!found) {
+ ep = env.envp + env.env_len;
+ env.env_len++;
+ *ep++ = str;
+ *ep = NULL;
+ }
+ return 0;
+}
+
+/*
+ * Similar to putenv(3) but operates on sudo's private copy of the
+ * environment (not environ) and it always overwrites. The dupcheck param
+ * determines whether we need to verify that the variable is not already set.
+ * Will only overwrite an existing variable if overwrite is set.
+ */
+static int
+sudo_putenv(char *str, bool dupcheck, bool overwrite)
+{
+ int ret;
+ debug_decl(sudo_putenv, SUDOERS_DEBUG_ENV);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "sudo_putenv: %s", str);
+
+ ret = sudo_putenv_nodebug(str, dupcheck, overwrite);
+ if (ret == -1) {
+#ifdef ENV_DEBUG
+ if (env.envp[env.env_len] != NULL) {
+ sudo_warnx("%s",
+ U_("sudo_putenv: corrupted envp, length mismatch"));
+ }
+#endif
+ }
+ debug_return_int(ret);
+}
+
+/*
+ * Similar to setenv(3) but operates on a private copy of the environment.
+ * The dupcheck param determines whether we need to verify that the variable
+ * is not already set.
+ */
+static int
+sudo_setenv2(const char *var, const char *val, bool dupcheck, bool overwrite)
+{
+ char *estring;
+ size_t esize;
+ int ret = -1;
+ debug_decl(sudo_setenv2, SUDOERS_DEBUG_ENV);
+
+ esize = strlen(var) + 1 + strlen(val) + 1;
+ if ((estring = malloc(esize)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_int(-1);
+ }
+
+ /* Build environment string and insert it. */
+ if (strlcpy(estring, var, esize) >= esize ||
+ strlcat(estring, "=", esize) >= esize ||
+ strlcat(estring, val, esize) >= esize) {
+
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ errno = EOVERFLOW;
+ } else {
+ ret = sudo_putenv(estring, dupcheck, overwrite);
+ }
+ if (ret == -1)
+ free(estring);
+ else
+ sudoers_gc_add(GC_PTR, estring);
+ debug_return_int(ret);
+}
+
+/*
+ * Similar to setenv(3) but operates on a private copy of the environment.
+ */
+int
+sudo_setenv(const char *var, const char *val, int overwrite)
+{
+ return sudo_setenv2(var, val, true, (bool)overwrite);
+}
+
+/*
+ * Similar to unsetenv(3) but operates on a private copy of the environment.
+ * Does not include warnings or debugging to avoid recursive calls.
+ */
+int
+sudo_unsetenv_nodebug(const char *var)
+{
+ char **ep = env.envp;
+ size_t len;
+
+ if (ep == NULL || var == NULL || *var == '\0' || strchr(var, '=') != NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ len = strlen(var);
+ while (*ep != NULL) {
+ if (strncmp(var, *ep, len) == 0 && (*ep)[len] == '=') {
+ /* Found it; shift remainder + NULL over by one. */
+ char **cur = ep;
+ while ((*cur = *(cur + 1)) != NULL)
+ cur++;
+ env.env_len--;
+ /* Keep going, could be multiple instances of the var. */
+ } else {
+ ep++;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Similar to unsetenv(3) but operates on a private copy of the environment.
+ */
+int
+sudo_unsetenv(const char *name)
+{
+ int ret;
+ debug_decl(sudo_unsetenv, SUDOERS_DEBUG_ENV);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "sudo_unsetenv: %s", name);
+
+ ret = sudo_unsetenv_nodebug(name);
+
+ debug_return_int(ret);
+}
+
+/*
+ * Similar to getenv(3) but operates on a private copy of the environment.
+ * Does not include warnings or debugging to avoid recursive calls.
+ */
+char *
+sudo_getenv_nodebug(const char *name)
+{
+ char **ep, *val = NULL;
+ size_t namelen = 0;
+
+ if (env.env_len != 0) {
+ /* For BSD compatibility, treat '=' in name like end of string. */
+ while (name[namelen] != '\0' && name[namelen] != '=')
+ namelen++;
+ for (ep = env.envp; *ep != NULL; ep++) {
+ if (strncmp(*ep, name, namelen) == 0 && (*ep)[namelen] == '=') {
+ val = *ep + namelen + 1;
+ break;
+ }
+ }
+ }
+ return val;
+}
+
+/*
+ * Similar to getenv(3) but operates on a private copy of the environment.
+ */
+char *
+sudo_getenv(const char *name)
+{
+ char *val;
+ debug_decl(sudo_getenv, SUDOERS_DEBUG_ENV);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "sudo_getenv: %s", name);
+
+ val = sudo_getenv_nodebug(name);
+
+ debug_return_str(val);
+}
+
+/*
+ * Check for var against patterns in the specified environment list.
+ * Returns true if the variable was found, else false.
+ */
+static bool
+matches_env_list(const char *var, struct list_members *list, bool *full_match)
+{
+ struct list_member *cur;
+ bool is_logname = false;
+ debug_decl(matches_env_list, SUDOERS_DEBUG_ENV);
+
+ switch (*var) {
+ case 'L':
+ if (strncmp(var, "LOGNAME=", 8) == 0)
+ is_logname = true;
+#ifdef _AIX
+ else if (strncmp(var, "LOGIN=", 6) == 0)
+ is_logname = true;
+#endif
+ break;
+ case 'U':
+ if (strncmp(var, "USER=", 5) == 0)
+ is_logname = true;
+ break;
+ }
+
+ if (is_logname) {
+ /*
+ * We treat LOGIN, LOGNAME and USER specially.
+ * If one is preserved/deleted we want to preserve/delete them all.
+ */
+ SLIST_FOREACH(cur, list, entries) {
+ if (matches_env_pattern(cur->value, "LOGNAME", full_match) ||
+#ifdef _AIX
+ matches_env_pattern(cur->value, "LOGIN", full_match) ||
+#endif
+ matches_env_pattern(cur->value, "USER", full_match))
+ debug_return_bool(true);
+ }
+ } else {
+ SLIST_FOREACH(cur, list, entries) {
+ if (matches_env_pattern(cur->value, var, full_match))
+ debug_return_bool(true);
+ }
+ }
+ debug_return_bool(false);
+}
+
+/*
+ * Check the env_delete blocklist.
+ * Returns true if the variable was found, else false.
+ */
+static bool
+matches_env_delete(const char *var)
+{
+ bool full_match; /* unused */
+ debug_decl(matches_env_delete, SUDOERS_DEBUG_ENV);
+
+ /* Skip anything listed in env_delete. */
+ debug_return_bool(matches_env_list(var, &def_env_delete, &full_match));
+}
+
+/*
+ * Verify the TZ environment variable is safe.
+ * On many systems it is possible to set this to a pathname.
+ */
+static bool
+tz_is_safe(const char *tzval)
+{
+ const char *cp;
+ char lastch;
+ debug_decl(tz_is_safe, SUDOERS_DEBUG_ENV);
+
+ /* tzcode treats a value beginning with a ':' as a path. */
+ if (tzval[0] == ':')
+ tzval++;
+
+ /* Reject fully-qualified TZ that doesn't being with the zoneinfo dir. */
+ if (tzval[0] == '/') {
+#ifdef _PATH_ZONEINFO
+ if (strncmp(tzval, _PATH_ZONEINFO, sizeof(_PATH_ZONEINFO) - 1) != 0 ||
+ tzval[sizeof(_PATH_ZONEINFO) - 1] != '/')
+ debug_return_bool(false);
+#else
+ /* Assume the worst. */
+ debug_return_bool(false);
+#endif
+ }
+
+ /*
+ * Make sure TZ only contains printable non-space characters
+ * and does not contain a '..' path element.
+ */
+ lastch = '/';
+ for (cp = tzval; *cp != '\0'; cp++) {
+ if (isspace((unsigned char)*cp) || !isprint((unsigned char)*cp))
+ debug_return_bool(false);
+ if (lastch == '/' && cp[0] == '.' && cp[1] == '.' &&
+ (cp[2] == '/' || cp[2] == '\0'))
+ debug_return_bool(false);
+ lastch = *cp;
+ }
+
+ /* Reject extra long TZ values (even if not a path). */
+ if ((size_t)(cp - tzval) >= PATH_MAX)
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+/*
+ * Apply the env_check list.
+ * Returns true if the variable is allowed, false if denied
+ * or -1 if no match.
+ */
+static int
+matches_env_check(const char *var, bool *full_match)
+{
+ int keepit = -1;
+ debug_decl(matches_env_check, SUDOERS_DEBUG_ENV);
+
+ /* Skip anything listed in env_check that includes '/' or '%'. */
+ if (matches_env_list(var, &def_env_check, full_match)) {
+ if (strncmp(var, "TZ=", 3) == 0) {
+ /* Special case for TZ */
+ keepit = tz_is_safe(var + 3);
+ } else {
+ const char *val = strchr(var, '=');
+ if (val != NULL)
+ keepit = !strpbrk(val + 1, "/%");
+ }
+ }
+ debug_return_int(keepit);
+}
+
+/*
+ * Check the env_keep list.
+ * Returns true if the variable is allowed else false.
+ */
+static bool
+matches_env_keep(const struct sudoers_context *ctx, const char *var,
+ bool *full_match)
+{
+ bool keepit = false;
+ debug_decl(matches_env_keep, SUDOERS_DEBUG_ENV);
+
+ /* Preserve SHELL variable for "sudo -s". */
+ if (ISSET(ctx->mode, MODE_SHELL) && strncmp(var, "SHELL=", 6) == 0) {
+ keepit = true;
+ } else if (matches_env_list(var, &def_env_keep, full_match)) {
+ keepit = true;
+ }
+ debug_return_bool(keepit);
+}
+
+/*
+ * Look up var in the env_delete and env_check.
+ * Returns true if we should delete the variable, else false.
+ */
+static bool
+env_should_delete(const char *var)
+{
+ int delete_it;
+ bool full_match = false;
+ debug_decl(env_should_delete, SUDOERS_DEBUG_ENV);
+
+ delete_it = matches_env_delete(var);
+ if (!delete_it)
+ delete_it = matches_env_check(var, &full_match) == false;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "delete %s: %s",
+ var, delete_it ? "YES" : "NO");
+ debug_return_bool(delete_it);
+}
+
+/*
+ * Lookup var in the env_check and env_keep lists.
+ * Returns true if the variable is allowed else false.
+ */
+static bool
+env_should_keep(const struct sudoers_context *ctx, const char *var)
+{
+ int keepit;
+ bool full_match = false;
+ const char *cp;
+ debug_decl(env_should_keep, SUDOERS_DEBUG_ENV);
+
+ keepit = matches_env_check(var, &full_match);
+ if (keepit == -1)
+ keepit = matches_env_keep(ctx, var, &full_match);
+
+ /* Skip bash functions unless we matched on the value as well as name. */
+ if (keepit && !full_match) {
+ if ((cp = strchr(var, '=')) != NULL) {
+ if (strncmp(cp, "=() ", 4) == 0)
+ keepit = false;
+ }
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "keep %s: %s",
+ var, keepit == true ? "YES" : "NO");
+ debug_return_bool(keepit == true);
+}
+
+#ifdef HAVE_PAM
+/*
+ * Merge another environment with our private copy.
+ * Only overwrite an existing variable if it is not
+ * being preserved from the user's environment.
+ * Returns true on success or false on failure.
+ */
+bool
+env_merge(const struct sudoers_context *ctx, char * const envp[])
+{
+ char * const *ep;
+ bool ret = true;
+ debug_decl(env_merge, SUDOERS_DEBUG_ENV);
+
+ for (ep = envp; *ep != NULL; ep++) {
+ /* XXX - avoid checking value here, should only check name */
+ bool overwrite = def_env_reset ? !env_should_keep(ctx, *ep) : env_should_delete(*ep);
+ if (sudo_putenv(*ep, true, overwrite) == -1) {
+ /* XXX cannot undo on failure */
+ ret = false;
+ break;
+ }
+ }
+ debug_return_bool(ret);
+}
+#endif /* HAVE_PAM */
+
+static void
+env_update_didvar(const char *ep, unsigned int *didvar)
+{
+ switch (*ep) {
+ case 'H':
+ if (strncmp(ep, "HOME=", 5) == 0)
+ SET(*didvar, DID_HOME);
+ break;
+ case 'L':
+#ifdef _AIX
+ if (strncmp(ep, "LOGIN=", 8) == 0)
+ SET(*didvar, DID_LOGIN);
+#endif
+ if (strncmp(ep, "LOGNAME=", 8) == 0)
+ SET(*didvar, DID_LOGNAME);
+ break;
+ case 'M':
+ if (strncmp(ep, "MAIL=", 5) == 0)
+ SET(*didvar, DID_MAIL);
+ break;
+ case 'P':
+ if (strncmp(ep, "PATH=", 5) == 0)
+ SET(*didvar, DID_PATH);
+ break;
+ case 'S':
+ if (strncmp(ep, "SHELL=", 6) == 0)
+ SET(*didvar, DID_SHELL);
+ break;
+ case 'T':
+ if (strncmp(ep, "TERM=", 5) == 0)
+ SET(*didvar, DID_TERM);
+ break;
+ case 'U':
+ if (strncmp(ep, "USER=", 5) == 0)
+ SET(*didvar, DID_USER);
+ break;
+ }
+}
+
+#define CHECK_PUTENV(a, b, c) do { \
+ if (sudo_putenv((char *)(a), (b), (c)) == -1) { \
+ goto bad; \
+ } \
+} while (0)
+
+#define CHECK_SETENV2(a, b, c, d) do { \
+ if (sudo_setenv2((char *)(a), (b), (c), (d)) == -1) { \
+ goto bad; \
+ } \
+} while (0)
+
+/*
+ * Build a new environment and either clear potentially dangerous
+ * variables from the old one or start with a clean slate.
+ * Also adds sudo-specific variables (SUDO_*).
+ * Returns true on success or false on failure.
+ */
+bool
+rebuild_env(const struct sudoers_context *ctx)
+{
+ char **ep, *cp, *ps1;
+ char idbuf[STRLEN_MAX_UNSIGNED(uid_t) + 1];
+ unsigned int didvar;
+ bool reset_home = false;
+ int len;
+ debug_decl(rebuild_env, SUDOERS_DEBUG_ENV);
+
+ /*
+ * Either clean out the environment or reset to a safe default.
+ */
+ ps1 = NULL;
+ didvar = 0;
+ env.env_len = 0;
+ env.env_size = 128;
+ sudoers_gc_remove(GC_PTR, env.old_envp);
+ free(env.old_envp);
+ env.old_envp = env.envp;
+ env.envp = reallocarray(NULL, env.env_size, sizeof(char *));
+ if (env.envp == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ env.env_size = 0;
+ goto bad;
+ }
+ sudoers_gc_add(GC_PTR, env.envp);
+#ifdef ENV_DEBUG
+ memset(env.envp, 0, env.env_size * sizeof(char *));
+#else
+ env.envp[0] = NULL;
+#endif
+
+ /* Reset HOME based on target user if configured to. */
+ if (ISSET(ctx->mode, MODE_RUN)) {
+ if (def_always_set_home ||
+ ISSET(ctx->mode, MODE_RESET_HOME | MODE_LOGIN_SHELL) ||
+ (ISSET(ctx->mode, MODE_SHELL) && def_set_home))
+ reset_home = true;
+ }
+
+ if (def_env_reset || ISSET(ctx->mode, MODE_LOGIN_SHELL)) {
+ /*
+ * If starting with a fresh environment, initialize it based on
+ * /etc/environment or login.conf. For "sudo -i" we want those
+ * variables to override the invoking user's environment, so we
+ * defer reading them until later.
+ */
+ if (!ISSET(ctx->mode, MODE_LOGIN_SHELL)) {
+#ifdef HAVE_LOGIN_CAP_H
+ /* Insert login class environment variables. */
+ if (ctx->runas.class) {
+ login_cap_t *lc = login_getclass(ctx->runas.class);
+ if (lc != NULL) {
+ setusercontext(lc, ctx->runas.pw,
+ ctx->runas.pw->pw_uid, LOGIN_SETPATH|LOGIN_SETENV);
+ login_close(lc);
+ }
+ }
+#endif /* HAVE_LOGIN_CAP_H */
+#ifdef _PATH_ENVIRONMENT
+ /* Insert system-wide environment variables. */
+ if (!read_env_file(ctx, _PATH_ENVIRONMENT, true, false))
+ sudo_warn("%s", _PATH_ENVIRONMENT);
+#endif
+ for (ep = env.envp; *ep; ep++)
+ env_update_didvar(*ep, &didvar);
+ }
+
+ /* Pull in vars we want to keep from the old environment. */
+ if (env.old_envp != NULL) {
+ for (ep = env.old_envp; *ep; ep++) {
+ bool keepit;
+
+ /*
+ * Look up the variable in the env_check and env_keep lists.
+ */
+ keepit = env_should_keep(ctx, *ep);
+
+ /*
+ * Do SUDO_PS1 -> PS1 conversion.
+ * This must happen *after* env_should_keep() is called.
+ */
+ if (strncmp(*ep, "SUDO_PS1=", 9) == 0)
+ ps1 = *ep + 5;
+
+ if (keepit) {
+ /* Preserve variable. */
+ CHECK_PUTENV(*ep, true, false);
+ env_update_didvar(*ep, &didvar);
+ }
+ }
+ }
+ didvar |= didvar << 16; /* convert DID_* to KEPT_* */
+
+ /*
+ * Add in defaults. In -i mode these come from the runas user,
+ * otherwise they may be from the user's environment (depends
+ * on sudoers options).
+ */
+ if (ISSET(ctx->mode, MODE_LOGIN_SHELL)) {
+ CHECK_SETENV2("SHELL", ctx->runas.pw->pw_shell,
+ ISSET(didvar, DID_SHELL), true);
+#ifdef _AIX
+ CHECK_SETENV2("LOGIN", ctx->runas.pw->pw_name,
+ ISSET(didvar, DID_LOGIN), true);
+#endif
+ CHECK_SETENV2("LOGNAME", ctx->runas.pw->pw_name,
+ ISSET(didvar, DID_LOGNAME), true);
+ CHECK_SETENV2("USER", ctx->runas.pw->pw_name,
+ ISSET(didvar, DID_USER), true);
+ } else {
+ /* We will set LOGNAME later in the def_set_logname case. */
+ if (!def_set_logname) {
+#ifdef _AIX
+ if (!ISSET(didvar, DID_LOGIN))
+ CHECK_SETENV2("LOGIN", ctx->user.name, false, true);
+#endif
+ if (!ISSET(didvar, DID_LOGNAME))
+ CHECK_SETENV2("LOGNAME", ctx->user.name, false, true);
+ if (!ISSET(didvar, DID_USER))
+ CHECK_SETENV2("USER", ctx->user.name, false, true);
+ }
+ }
+
+ /* If we didn't keep HOME, reset it based on target user. */
+ if (!ISSET(didvar, KEPT_HOME))
+ reset_home = true;
+
+ /*
+ * Set MAIL to target user in -i mode or if MAIL is not preserved
+ * from user's environment.
+ */
+ if (ISSET(ctx->mode, MODE_LOGIN_SHELL) || !ISSET(didvar, KEPT_MAIL)) {
+ if (_PATH_MAILDIR[sizeof(_PATH_MAILDIR) - 2] == '/') {
+ len = asprintf(&cp, "MAIL=%s%s", _PATH_MAILDIR,
+ ctx->runas.pw->pw_name);
+ } else {
+ len = asprintf(&cp, "MAIL=%s/%s", _PATH_MAILDIR,
+ ctx->runas.pw->pw_name);
+ }
+ if (len == -1)
+ goto bad;
+ if (sudo_putenv(cp, ISSET(didvar, DID_MAIL), true) == -1) {
+ free(cp);
+ goto bad;
+ }
+ sudoers_gc_add(GC_PTR, cp);
+ }
+ } else {
+ /*
+ * Copy environ entries as long as they don't match env_delete or
+ * env_check.
+ */
+ if (env.old_envp != NULL) {
+ for (ep = env.old_envp; *ep; ep++) {
+ /* Add variable unless it matches a blocklist. */
+ if (!env_should_delete(*ep)) {
+ if (strncmp(*ep, "SUDO_PS1=", 9) == 0)
+ ps1 = *ep + 5;
+ else if (strncmp(*ep, "SHELL=", 6) == 0)
+ SET(didvar, DID_SHELL);
+ else if (strncmp(*ep, "PATH=", 5) == 0)
+ SET(didvar, DID_PATH);
+ else if (strncmp(*ep, "TERM=", 5) == 0)
+ SET(didvar, DID_TERM);
+ CHECK_PUTENV(*ep, true, false);
+ }
+ }
+ }
+ }
+ /* Replace the PATH envariable with a secure one? */
+ if (def_secure_path && !user_is_exempt(ctx)) {
+ CHECK_SETENV2("PATH", def_secure_path, true, true);
+ SET(didvar, DID_PATH);
+ }
+
+ /*
+ * Set LOGIN, LOGNAME, and USER to target if "set_logname" is not
+ * disabled. We skip this if we are running a login shell (because
+ * they have already been set).
+ */
+ if (def_set_logname && !ISSET(ctx->mode, MODE_LOGIN_SHELL)) {
+ if ((didvar & KEPT_USER_VARIABLES) == 0) {
+ /* Nothing preserved, set them all. */
+#ifdef _AIX
+ CHECK_SETENV2("LOGIN", ctx->runas.pw->pw_name, true, true);
+#endif
+ CHECK_SETENV2("LOGNAME", ctx->runas.pw->pw_name, true, true);
+ CHECK_SETENV2("USER", ctx->runas.pw->pw_name, true, true);
+ } else if ((didvar & KEPT_USER_VARIABLES) != KEPT_USER_VARIABLES) {
+ /*
+ * Preserved some of LOGIN, LOGNAME, USER but not all.
+ * Make the unset ones match so we don't end up with some
+ * set to the invoking user and others set to the runas user.
+ */
+ if (ISSET(didvar, KEPT_LOGNAME))
+ cp = sudo_getenv("LOGNAME");
+#ifdef _AIX
+ else if (ISSET(didvar, KEPT_LOGIN))
+ cp = sudo_getenv("LOGIN");
+#endif
+ else if (ISSET(didvar, KEPT_USER))
+ cp = sudo_getenv("USER");
+ else
+ cp = NULL;
+ if (cp != NULL) {
+#ifdef _AIX
+ if (!ISSET(didvar, KEPT_LOGIN))
+ CHECK_SETENV2("LOGIN", cp, true, true);
+#endif
+ if (!ISSET(didvar, KEPT_LOGNAME))
+ CHECK_SETENV2("LOGNAME", cp, true, true);
+ if (!ISSET(didvar, KEPT_USER))
+ CHECK_SETENV2("USER", cp, true, true);
+ }
+ }
+ }
+
+ /* Set $HOME to target user if not preserving user's value. */
+ if (reset_home)
+ CHECK_SETENV2("HOME", ctx->runas.pw->pw_dir, true, true);
+
+ /* Provide default values for $SHELL, $TERM and $PATH if not set. */
+ if (!ISSET(didvar, DID_SHELL))
+ CHECK_SETENV2("SHELL", ctx->runas.pw->pw_shell, false, false);
+ if (!ISSET(didvar, DID_TERM))
+ CHECK_PUTENV("TERM=unknown", false, false);
+ if (!ISSET(didvar, DID_PATH))
+ CHECK_SETENV2("PATH", _PATH_STDPATH, false, true);
+
+ /* Set PS1 if SUDO_PS1 is set. */
+ if (ps1 != NULL)
+ CHECK_PUTENV(ps1, true, true);
+
+ /* Add the SUDO_COMMAND envariable (cmnd + args). */
+ if (ctx->user.cmnd_args) {
+ /*
+ * We limit ctx->user.cmnd_args to 4096 bytes to avoid an execve(2)
+ * failure for very long argument vectors. The command's environment
+ * also counts against the ARG_MAX limit.
+ */
+ len = asprintf(&cp, "SUDO_COMMAND=%s %.*s", ctx->user.cmnd, 4096,
+ ctx->user.cmnd_args);
+ if (len == -1)
+ goto bad;
+ if (sudo_putenv(cp, true, true) == -1) {
+ free(cp);
+ goto bad;
+ }
+ sudoers_gc_add(GC_PTR, cp);
+ } else {
+ CHECK_SETENV2("SUDO_COMMAND", ctx->user.cmnd, true, true);
+ }
+
+ /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */
+ CHECK_SETENV2("SUDO_USER", ctx->user.name, true, true);
+ (void)snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) ctx->user.uid);
+ CHECK_SETENV2("SUDO_UID", idbuf, true, true);
+ (void)snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) ctx->user.gid);
+ CHECK_SETENV2("SUDO_GID", idbuf, true, true);
+
+ debug_return_bool(true);
+
+bad:
+ sudo_warn("%s", U_("unable to rebuild the environment"));
+ debug_return_bool(false);
+}
+
+/*
+ * Insert all environment variables in envp into the private copy
+ * of the environment.
+ * Returns true on success or false on failure.
+ */
+bool
+insert_env_vars(char * const envp[])
+{
+ char * const *ep;
+ bool ret = true;
+ debug_decl(insert_env_vars, SUDOERS_DEBUG_ENV);
+
+ /* Add user-specified environment variables. */
+ if (envp != NULL) {
+ for (ep = envp; *ep != NULL; ep++) {
+ /* XXX - no undo on failure */
+ if (sudo_putenv(*ep, true, true) == -1) {
+ ret = false;
+ break;
+ }
+ }
+ }
+ debug_return_bool(ret);
+}
+
+/*
+ * Validate the list of environment variables passed in on the command
+ * line against env_delete, env_check, and env_keep.
+ * Calls log_warning() if any specified variables are not allowed.
+ * Returns true if allowed, else false.
+ */
+bool
+validate_env_vars(const struct sudoers_context *ctx, char * const env_vars[])
+{
+ char * const *ep;
+ char errbuf[4096];
+ char *errpos = errbuf;
+ bool okvar, ret = true;
+ debug_decl(validate_env_vars, SUDOERS_DEBUG_ENV);
+
+ if (env_vars == NULL)
+ debug_return_bool(true); /* nothing to do */
+
+ /* Add user-specified environment variables. */
+ for (ep = env_vars; *ep != NULL; ep++) {
+ char *eq = strchr(*ep, '=');
+ if (eq == NULL || eq == *ep) {
+ /* Must be in the form var=val. */
+ okvar = false;
+ } else if (def_secure_path && !user_is_exempt(ctx) &&
+ strncmp(*ep, "PATH=", 5) == 0) {
+ okvar = false;
+ } else if (def_env_reset) {
+ okvar = env_should_keep(ctx, *ep);
+ } else {
+ okvar = !env_should_delete(*ep);
+ }
+ if (okvar == false) {
+ /* Not allowed, append to error buffer if space remains. */
+ if (errpos < &errbuf[sizeof(errbuf)]) {
+ const size_t varlen = strcspn(*ep, "=");
+ const size_t errsize = sizeof(errbuf) - (size_t)(errpos - errbuf);
+ int len = snprintf(errpos, errsize, "%s%.*s",
+ errpos != errbuf ? ", " : "", (int)varlen, *ep);
+ if (len >= ssizeof(errbuf) - (errpos - errbuf)) {
+ memcpy(&errbuf[sizeof(errbuf) - 4], "...", 4);
+ errpos = &errbuf[sizeof(errbuf)];
+ } else {
+ errpos += len;
+ }
+ }
+ }
+ }
+ if (errpos != errbuf) {
+ /* XXX - audit? */
+ log_warningx(ctx, 0,
+ N_("sorry, you are not allowed to set the following environment variables: %s"), errbuf);
+ ret = false;
+ }
+ debug_return_bool(ret);
+}
+
+static void *
+env_file_open_local(const char *path)
+{
+ struct env_file_local *efl;
+ debug_decl(env_file_open_local, SUDOERS_DEBUG_ENV);
+
+ efl = calloc(1, sizeof(*efl));
+ if (efl != NULL) {
+ if ((efl->fp = fopen(path, "r")) == NULL) {
+ if (errno != ENOENT) {
+ free(efl);
+ efl = NULL;
+ }
+ }
+ }
+ debug_return_ptr(efl);
+}
+
+static void
+env_file_close_local(void *cookie)
+{
+ struct env_file_local *efl = cookie;
+ debug_decl(env_file_close_local, SUDOERS_DEBUG_ENV);
+
+ if (efl != NULL) {
+ if (efl->fp != NULL)
+ fclose(efl->fp);
+ free(efl->line);
+ free(efl);
+ }
+ debug_return;
+}
+
+/*
+ * Parse /etc/environment lines ala AIX and Linux.
+ * Lines may be in either of three formats:
+ * NAME=VALUE
+ * NAME="VALUE"
+ * NAME='VALUE'
+ * with an optional "export" prefix so the shell can source the file.
+ * Invalid lines, blank lines, or lines consisting solely of a comment
+ * character are skipped.
+ */
+static char *
+env_file_next_local(void *cookie, int *errnum)
+{
+ struct env_file_local *efl = cookie;
+ char *var, *val, *ret = NULL;
+ size_t var_len, val_len;
+ debug_decl(env_file_next_local, SUDOERS_DEBUG_ENV);
+
+ *errnum = 0;
+ if (efl->fp == NULL)
+ debug_return_ptr(NULL);
+
+ for (;;) {
+ if (sudo_parseln(&efl->line, &efl->linesize, NULL, efl->fp, PARSELN_CONT_IGN) == -1) {
+ if (!feof(efl->fp))
+ *errnum = errno;
+ break;
+ }
+
+ /* Skip blank or comment lines */
+ if (*(var = efl->line) == '\0')
+ continue;
+
+ /* Skip optional "export " */
+ if (strncmp(var, "export", 6) == 0 && isspace((unsigned char) var[6])) {
+ var += 7;
+ while (isspace((unsigned char) *var)) {
+ var++;
+ }
+ }
+
+ /* Must be of the form name=["']value['"] */
+ for (val = var; *val != '\0' && *val != '='; val++)
+ continue;
+ if (var == val || *val != '=')
+ continue;
+ var_len = (size_t)(val - var);
+ val_len = strlen(++val);
+
+ /* Strip leading and trailing single/double quotes */
+ if ((val[0] == '\'' || val[0] == '\"') && val_len > 1 && val[0] == val[val_len - 1]) {
+ val[val_len - 1] = '\0';
+ val++;
+ val_len -= 2;
+ }
+
+ if ((ret = malloc(var_len + 1 + val_len + 1)) == NULL) {
+ *errnum = errno;
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ } else {
+ memcpy(ret, var, var_len + 1); /* includes '=' */
+ memcpy(ret + var_len + 1, val, val_len + 1); /* includes NUL */
+ sudoers_gc_add(GC_PTR, ret);
+ }
+ break;
+ }
+ debug_return_str(ret);
+}
+
+static struct sudoers_env_file env_file_sudoers = {
+ env_file_open_local,
+ env_file_close_local,
+ env_file_next_local
+};
+
+static struct sudoers_env_file env_file_system = {
+ env_file_open_local,
+ env_file_close_local,
+ env_file_next_local
+};
+
+void
+register_env_file(void * (*ef_open)(const char *), void (*ef_close)(void *),
+ char * (*ef_next)(void *, int *), bool sys)
+{
+ struct sudoers_env_file *ef = sys ? &env_file_system : &env_file_sudoers;
+
+ ef->open = ef_open;
+ ef->close = ef_close;
+ ef->next = ef_next;
+}
+
+bool
+read_env_file(const struct sudoers_context *ctx, const char *path,
+ bool overwrite, bool restricted)
+{
+ struct sudoers_env_file *ef;
+ bool ret = true;
+ char *envstr;
+ void *cookie;
+ int errnum;
+ debug_decl(read_env_file, SUDOERS_DEBUG_ENV);
+
+ /*
+ * The environment file may be handled differently depending on
+ * whether it is specified in sudoers or the system.
+ */
+ if (path == def_env_file || path == def_restricted_env_file)
+ ef = &env_file_sudoers;
+ else
+ ef = &env_file_system;
+
+ cookie = ef->open(path);
+ if (cookie == NULL)
+ debug_return_bool(false);
+
+ for (;;) {
+ /* Keep reading until EOF or error. */
+ if ((envstr = ef->next(cookie, &errnum)) == NULL) {
+ if (errnum != 0)
+ ret = false;
+ break;
+ }
+
+ /*
+ * If the env file is restricted, apply env_check and env_keep
+ * when env_reset is set or env_delete when it is not.
+ */
+ if (restricted) {
+ if (def_env_reset ? !env_should_keep(ctx, envstr) : env_should_delete(envstr)) {
+ free(envstr);
+ continue;
+ }
+ }
+ if (sudo_putenv(envstr, true, overwrite) == -1) {
+ /* XXX - no undo on failure */
+ ret = false;
+ break;
+ }
+ }
+ ef->close(cookie);
+
+ debug_return_bool(ret);
+}
+
+bool
+init_envtables(void)
+{
+ struct list_member *cur;
+ const char **p;
+ debug_decl(init_envtables, SUDOERS_DEBUG_ENV);
+
+ /* Fill in the "env_delete" list. */
+ for (p = initial_badenv_table; *p; p++) {
+ cur = calloc(1, sizeof(struct list_member));
+ if (cur == NULL || (cur->value = strdup(*p)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ free(cur);
+ debug_return_bool(false);
+ }
+ SLIST_INSERT_HEAD(&def_env_delete, cur, entries);
+ }
+
+ /* Fill in the "env_check" list. */
+ for (p = initial_checkenv_table; *p; p++) {
+ cur = calloc(1, sizeof(struct list_member));
+ if (cur == NULL || (cur->value = strdup(*p)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ free(cur);
+ debug_return_bool(false);
+ }
+ SLIST_INSERT_HEAD(&def_env_check, cur, entries);
+ }
+
+ /* Fill in the "env_keep" list. */
+ for (p = initial_keepenv_table; *p; p++) {
+ cur = calloc(1, sizeof(struct list_member));
+ if (cur == NULL || (cur->value = strdup(*p)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ free(cur);
+ debug_return_bool(false);
+ }
+ SLIST_INSERT_HEAD(&def_env_keep, cur, entries);
+ }
+ debug_return_bool(true);
+}
diff --git a/plugins/sudoers/env_pattern.c b/plugins/sudoers/env_pattern.c
new file mode 100644
index 0000000..502f56b
--- /dev/null
+++ b/plugins/sudoers/env_pattern.c
@@ -0,0 +1,93 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2017 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudoers.h>
+
+/* extern for regress tests */
+bool
+matches_env_pattern(const char *pattern, const char *var, bool *full_match)
+{
+ size_t len, sep_pos;
+ bool iswild = false, match = false;
+ bool saw_sep = false;
+ const char *cp;
+ debug_decl(matches_env_pattern, SUDOERS_DEBUG_ENV);
+
+ /* Locate position of the '=' separator in var=value. */
+ sep_pos = strcspn(var, "=");
+
+ /* Locate '*' wildcard and compute len. */
+ for (cp = pattern; *cp != '\0'; cp++) {
+ if (*cp == '*') {
+ iswild = true;
+ break;
+ }
+ }
+ len = (size_t)(cp - pattern);
+
+ if (iswild) {
+ /* Match up to the '*' wildcard. */
+ if (strncmp(pattern, var, len) == 0) {
+ while (*cp != '\0') {
+ if (*cp == '*') {
+ /* Collapse sequential '*'s */
+ do {
+ cp++;
+ } while (*cp == '*');
+ /* A '*' at the end of a pattern matches anything. */
+ if (*cp == '\0') {
+ match = true;
+ break;
+ }
+ /* Keep track of whether we matched an equal sign. */
+ if (*cp == '=')
+ saw_sep = true;
+ /* Look for first match of text after the '*' */
+ while ((saw_sep || len != sep_pos) &&
+ var[len] != '\0' && var[len] != *cp)
+ len++;
+ }
+ if (var[len] != *cp)
+ break;
+ cp++;
+ len++;
+ }
+ if (*cp == '\0' && (len == sep_pos || var[len] == '\0'))
+ match = true;
+ }
+ } else {
+ if (strncmp(pattern, var, len) == 0 &&
+ (len == sep_pos || var[len] == '\0')) {
+ match = true;
+ }
+ }
+ if (match)
+ *full_match = len > sep_pos + 1;
+ debug_return_bool(match);
+}
diff --git a/plugins/sudoers/exptilde.c b/plugins/sudoers/exptilde.c
new file mode 100644
index 0000000..03de3da
--- /dev/null
+++ b/plugins/sudoers/exptilde.c
@@ -0,0 +1,99 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <grp.h>
+#include <pwd.h>
+
+#include <sudoers.h>
+#include <pwutil.h>
+
+/*
+ * Expand leading tilde in *path, which must be dynamically allocated.
+ * Replaces path with the expanded version as needed, freeing the old one.
+ * Returns true on success, false on failure.
+ */
+bool
+expand_tilde(char **path, const char *user)
+{
+ char *npath, *opath = *path;
+ char *slash = NULL;
+ struct passwd *pw;
+ int len;
+ debug_decl(expand_tilde, SUDOERS_DEBUG_UTIL);
+
+ switch (*opath++) {
+ case '/':
+ /* A fully-qualified path, nothing to do. */
+ debug_return_bool(true);
+ case '~':
+ /* See below. */
+ break;
+ default:
+ /* Not a fully-qualified path or one that starts with a tilde. */
+ debug_return_bool(false);
+ }
+
+ switch (*opath) {
+ case '\0':
+ /* format: ~ */
+ break;
+ case '/':
+ /* format: ~/foo */
+ opath++;
+ break;
+ default:
+ /* format: ~user/foo */
+ user = opath;
+ slash = strchr(opath, '/');
+ if (slash != NULL) {
+ *slash = '\0';
+ opath = slash + 1;
+ } else {
+ opath = (char *)"";
+ }
+ }
+ pw = sudo_getpwnam(user);
+ if (slash != NULL)
+ *slash = '/';
+ if (pw == NULL) {
+ /* Unknown user. */
+ sudo_warnx(U_("unknown user %s"), user);
+ debug_return_bool(false);
+ }
+
+ len = asprintf(&npath, "%s%s%s", pw->pw_dir, *opath ? "/" : "", opath);
+ sudo_pw_delref(pw);
+ if (len == -1) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+
+ free(*path);
+ *path = npath;
+ debug_return_bool(true);
+}
diff --git a/plugins/sudoers/file.c b/plugins/sudoers/file.c
new file mode 100644
index 0000000..865350a
--- /dev/null
+++ b/plugins/sudoers/file.c
@@ -0,0 +1,153 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2004-2005, 2007-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sudoers.h>
+#include <sudo_lbuf.h>
+#include <gram.h>
+
+struct sudo_file_handle {
+ FILE *fp;
+ struct sudoers_parse_tree parse_tree;
+};
+
+static int
+sudo_file_close(struct sudoers_context *ctx, struct sudo_nss *nss)
+{
+ debug_decl(sudo_file_close, SUDOERS_DEBUG_NSS);
+ struct sudo_file_handle *handle = nss->handle;
+
+ if (handle != NULL) {
+ fclose(handle->fp);
+ sudoersin = NULL;
+
+ free_parse_tree(&handle->parse_tree);
+ free(handle);
+ nss->handle = NULL;
+ }
+
+ debug_return_int(0);
+}
+
+static int
+sudo_file_open(struct sudoers_context *ctx, struct sudo_nss *nss)
+{
+ debug_decl(sudo_file_open, SUDOERS_DEBUG_NSS);
+ struct sudo_file_handle *handle;
+ char *outfile = NULL;
+
+ /* Note: relies on defaults being initialized early. */
+ if (def_ignore_local_sudoers)
+ debug_return_int(-1);
+
+ if (nss->handle != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: called with non-NULL handle %p", __func__, nss->handle);
+ sudo_file_close(ctx, nss);
+ }
+
+ handle = malloc(sizeof(*handle));
+ if (handle != NULL) {
+ init_parser(ctx, NULL);
+ handle->fp = open_sudoers(ctx->parser_conf.sudoers_path, &outfile,
+ false, NULL);
+ if (handle->fp != NULL) {
+ init_parse_tree(&handle->parse_tree, NULL, NULL, ctx, nss);
+ if (outfile != NULL) {
+ /* Update path to open sudoers file. */
+ sudo_rcstr_delref(sudoers);
+ sudoers = outfile;
+ }
+ } else {
+ free(handle);
+ handle = NULL;
+ }
+ }
+ nss->handle = handle;
+ debug_return_int(nss->handle ? 0 : -1);
+}
+
+/*
+ * Parse and return the specified sudoers file.
+ */
+static struct sudoers_parse_tree *
+sudo_file_parse(struct sudoers_context *ctx, const struct sudo_nss *nss)
+{
+ debug_decl(sudo_file_close, SUDOERS_DEBUG_NSS);
+ struct sudo_file_handle *handle = nss->handle;
+ int error;
+
+ if (handle == NULL || handle->fp == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "%s: called with NULL %s",
+ __func__, handle ? "file pointer" : "handle");
+ debug_return_ptr(NULL);
+ }
+
+ sudoersin = handle->fp;
+ error = sudoersparse();
+ if (error || (parse_error && !sudoers_error_recovery())) {
+ /* unrecoverable error */
+ debug_return_ptr(NULL);
+ }
+
+ /* Move parsed sudoers policy to nss handle. */
+ reparent_parse_tree(&handle->parse_tree);
+
+ debug_return_ptr(&handle->parse_tree);
+}
+
+/*
+ * No need for explicit sudoers queries, the parse function handled it.
+ */
+static int
+sudo_file_query(struct sudoers_context *ctx, const struct sudo_nss *nss,
+ struct passwd *pw)
+{
+ debug_decl(sudo_file_query, SUDOERS_DEBUG_NSS);
+ debug_return_int(0);
+}
+
+/*
+ * No need to get defaults for sudoers file, the parse function handled it.
+ */
+static int
+sudo_file_getdefs(struct sudoers_context *ctx, const struct sudo_nss *nss)
+{
+ debug_decl(sudo_file_getdefs, SUDOERS_DEBUG_NSS);
+ debug_return_int(0);
+}
+
+/* sudo_nss implementation */
+struct sudo_nss sudo_nss_file = {
+ { NULL, NULL },
+ "sudoers",
+ sudo_file_open,
+ sudo_file_close,
+ sudo_file_parse,
+ sudo_file_query,
+ sudo_file_getdefs
+};
diff --git a/plugins/sudoers/filedigest.c b/plugins/sudoers/filedigest.c
new file mode 100644
index 0000000..36cc498
--- /dev/null
+++ b/plugins/sudoers/filedigest.c
@@ -0,0 +1,91 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sudoers.h>
+#include <sudo_digest.h>
+
+unsigned char *
+sudo_filedigest(int fd, const char *file, unsigned int digest_type,
+ size_t *digest_len)
+{
+ unsigned char *file_digest = NULL;
+ unsigned char buf[32 * 1024];
+ struct sudo_digest *dig = NULL;
+ FILE *fp = NULL;
+ size_t nread;
+ int fd2;
+ debug_decl(sudo_filedigest, SUDOERS_DEBUG_UTIL);
+
+ *digest_len = sudo_digest_getlen(digest_type);
+ if (*digest_len == 0) {
+ sudo_warnx(U_("unsupported digest type %u for %s"), digest_type, file);
+ debug_return_ptr(NULL);
+ }
+
+ if ((fd2 = dup(fd)) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "unable to dup %s: %s",
+ file, strerror(errno));
+ debug_return_ptr(NULL);
+ }
+ if ((fp = fdopen(fd2, "r")) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "unable to fdopen %s: %s",
+ file, strerror(errno));
+ close(fd2);
+ goto bad;
+ }
+ if ((file_digest = malloc(*digest_len)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ if ((dig = sudo_digest_alloc(digest_type)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ while ((nread = fread(buf, 1, sizeof(buf), fp)) != 0) {
+ sudo_digest_update(dig, buf, nread);
+ }
+ if (ferror(fp)) {
+ sudo_warnx(U_("%s: read error"), file);
+ goto bad;
+ }
+ sudo_digest_final(dig, file_digest);
+ sudo_digest_free(dig);
+ fclose(fp);
+
+ debug_return_ptr(file_digest);
+bad:
+ sudo_digest_free(dig);
+ free(file_digest);
+ if (fp != NULL)
+ fclose(fp);
+ debug_return_ptr(NULL);
+}
diff --git a/plugins/sudoers/find_path.c b/plugins/sudoers/find_path.c
new file mode 100644
index 0000000..9b96615
--- /dev/null
+++ b/plugins/sudoers/find_path.c
@@ -0,0 +1,168 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2010-2015, 2017-2019
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sudoers.h>
+
+/*
+ * Check the given command against the specified allowlist (NULL-terminated).
+ * On success, rewrites cmnd based on the allowlist and returns true.
+ * On failure, returns false.
+ */
+static bool
+cmnd_allowed(char *cmnd, size_t cmnd_size, struct stat *cmnd_sbp,
+ char * const *allowlist)
+{
+ const char *cmnd_base;
+ char * const *al;
+ debug_decl(cmnd_allowed, SUDOERS_DEBUG_UTIL);
+
+ if (!sudo_goodpath(cmnd, cmnd_sbp))
+ debug_return_bool(false);
+
+ if (allowlist == NULL)
+ debug_return_bool(true); /* nothing to check */
+
+ /* We compare the base names to avoid excessive stat()ing. */
+ cmnd_base = sudo_basename(cmnd);
+
+ for (al = allowlist; *al != NULL; al++) {
+ const char *base, *path = *al;
+ struct stat sb;
+
+ base = sudo_basename(path);
+ if (strcmp(cmnd_base, base) != 0)
+ continue;
+
+ if (sudo_goodpath(path, &sb) &&
+ sb.st_dev == cmnd_sbp->st_dev && sb.st_ino == cmnd_sbp->st_ino) {
+ /* Overwrite cmnd with safe version from allowlist. */
+ if (strlcpy(cmnd, path, cmnd_size) < cmnd_size)
+ debug_return_bool(true);
+ }
+ }
+ debug_return_bool(false);
+}
+
+/*
+ * This function finds the full pathname for a command and stores it
+ * in a statically allocated array, filling in a pointer to the array.
+ * Returns FOUND if the command was found, NOT_FOUND if it was not found,
+ * NOT_FOUND_DOT if it would have been found but it is in '.' and
+ * ignore_dot is set or NOT_FOUND_ERROR if an error occurred.
+ * The caller is responsible for freeing the output file.
+ */
+int
+find_path(const char *infile, char **outfile, struct stat *sbp,
+ const char *path, bool ignore_dot, char * const *allowlist)
+{
+ char command[PATH_MAX];
+ const char *cp, *ep, *pathend;
+ bool found = false;
+ bool checkdot = false;
+ int len;
+ debug_decl(find_path, SUDOERS_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "resolving %s", infile);
+
+ /*
+ * If we were given a fully qualified or relative path
+ * there is no need to look at $PATH.
+ */
+ if (strchr(infile, '/') != NULL) {
+ if (strlcpy(command, infile, sizeof(command)) >= sizeof(command)) {
+ errno = ENAMETOOLONG;
+ debug_return_int(NOT_FOUND_ERROR);
+ }
+ found = cmnd_allowed(command, sizeof(command), sbp, allowlist);
+ goto done;
+ }
+
+ if (path == NULL)
+ debug_return_int(NOT_FOUND);
+
+ pathend = path + strlen(path);
+ for (cp = sudo_strsplit(path, pathend, ":", &ep); cp != NULL;
+ cp = sudo_strsplit(NULL, pathend, ":", &ep)) {
+
+ /*
+ * Search current dir last if it is in PATH.
+ * This will miss sneaky things like using './' or './/' (XXX)
+ */
+ if (cp == ep || (*cp == '.' && cp + 1 == ep)) {
+ checkdot = 1;
+ continue;
+ }
+
+ /*
+ * Resolve the path and exit the loop if found.
+ */
+ len = snprintf(command, sizeof(command), "%.*s/%s",
+ (int)(ep - cp), cp, infile);
+ if (len < 0 || len >= ssizeof(command)) {
+ errno = ENAMETOOLONG;
+ debug_return_int(NOT_FOUND_ERROR);
+ }
+ found = cmnd_allowed(command, sizeof(command), sbp, allowlist);
+ if (found)
+ break;
+ }
+
+ /*
+ * Check current dir if dot was in the PATH
+ */
+ if (!found && checkdot) {
+ len = snprintf(command, sizeof(command), "./%s", infile);
+ if (len < 0 || len >= ssizeof(command)) {
+ errno = ENAMETOOLONG;
+ debug_return_int(NOT_FOUND_ERROR);
+ }
+ found = cmnd_allowed(command, sizeof(command), sbp, allowlist);
+ if (found && ignore_dot)
+ debug_return_int(NOT_FOUND_DOT);
+ }
+
+done:
+ if (found) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "found %s", command);
+ if ((*outfile = strdup(command)) == NULL)
+ debug_return_int(NOT_FOUND_ERROR);
+ debug_return_int(FOUND);
+ }
+ debug_return_int(NOT_FOUND);
+}
diff --git a/plugins/sudoers/fmtsudoers.c b/plugins/sudoers/fmtsudoers.c
new file mode 100644
index 0000000..7e6d45d
--- /dev/null
+++ b/plugins/sudoers/fmtsudoers.c
@@ -0,0 +1,322 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2004-2005, 2007-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <time.h>
+
+#include <sudoers.h>
+#include <sudo_lbuf.h>
+#include <gram.h>
+
+/*
+ * Write the contents of a struct member to the lbuf.
+ * If alias_type is not UNSPEC, expand aliases using that type with
+ * the specified separator (which must not be NULL in the UNSPEC case).
+ */
+static bool
+sudoers_format_member_int(struct sudo_lbuf *lbuf,
+ const struct sudoers_parse_tree *parse_tree, const char *name, int type,
+ bool negated, const char *separator, short alias_type)
+{
+ const struct sudoers_context *ctx = parse_tree->ctx;
+ struct alias *a;
+ const struct member *m;
+ const struct sudo_command *c;
+ const struct command_digest *digest;
+ debug_decl(sudoers_format_member_int, SUDOERS_DEBUG_UTIL);
+
+ switch (type) {
+ case MYSELF:
+ sudo_lbuf_append(lbuf, "%s%s", negated ? "!" : "",
+ ctx->runas.list_pw ? ctx->runas.list_pw->pw_name :
+ (ctx->user.name ? ctx->user.name : ""));
+ break;
+ case ALL:
+ if (name == NULL) {
+ sudo_lbuf_append(lbuf, "%sALL", negated ? "!" : "");
+ break;
+ }
+ FALLTHROUGH;
+ case COMMAND:
+ c = (struct sudo_command *) name;
+ TAILQ_FOREACH(digest, &c->digests, entries) {
+ sudo_lbuf_append(lbuf, "%s:%s%s ",
+ digest_type_to_name(digest->digest_type),
+ digest->digest_str, TAILQ_NEXT(digest, entries) ? "," : "");
+ }
+ if (negated)
+ sudo_lbuf_append(lbuf, "!");
+ if (c->cmnd == NULL || c->cmnd[0] == '^') {
+ /* No additional quoting of characters inside a regex. */
+ sudo_lbuf_append(lbuf, "%s", c->cmnd ? c->cmnd : "ALL");
+ } else {
+ sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED_CMD, "%s",
+ c->cmnd);
+ }
+ if (c->args != NULL) {
+ sudo_lbuf_append(lbuf, " ");
+ if (c->args[0] == '^') {
+ /* No additional quoting of characters inside a regex. */
+ sudo_lbuf_append(lbuf, "%s", c->args);
+ } else {
+ sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED_ARG, "%s",
+ c->args);
+ }
+ }
+ break;
+ case USERGROUP:
+ /* Special case for %#gid, %:non-unix-group, %:#non-unix-gid */
+ if (strpbrk(name, " \t") == NULL) {
+ if (*++name == ':') {
+ name++;
+ sudo_lbuf_append(lbuf, "%s", "%:");
+ } else {
+ sudo_lbuf_append(lbuf, "%s", "%");
+ }
+ }
+ goto print_word;
+ case ALIAS:
+ if (alias_type != UNSPEC) {
+ if ((a = alias_get(parse_tree, name, alias_type)) != NULL) {
+ TAILQ_FOREACH(m, &a->members, entries) {
+ if (m != TAILQ_FIRST(&a->members))
+ sudo_lbuf_append(lbuf, "%s", separator);
+ sudoers_format_member_int(lbuf, parse_tree,
+ m->name, m->type,
+ negated ? !m->negated : m->negated,
+ separator, alias_type);
+ }
+ alias_put(a);
+ break;
+ }
+ }
+ FALLTHROUGH;
+ default:
+ print_word:
+ /* Do not quote UID/GID, all others get quoted. */
+ if (name[0] == '#' &&
+ name[strspn(name + 1, "0123456789") + 1] == '\0') {
+ sudo_lbuf_append(lbuf, "%s%s", negated ? "!" : "", name);
+ } else {
+ if (strpbrk(name, " \t") != NULL) {
+ sudo_lbuf_append(lbuf, "%s\"", negated ? "!" : "");
+ sudo_lbuf_append_quoted(lbuf, "\"", "%s", name);
+ sudo_lbuf_append(lbuf, "\"");
+ } else {
+ sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s%s",
+ negated ? "!" : "", name);
+ }
+ }
+ break;
+ }
+ debug_return_bool(!sudo_lbuf_error(lbuf));
+}
+
+bool
+sudoers_format_member(struct sudo_lbuf *lbuf,
+ const struct sudoers_parse_tree *parse_tree, const struct member *m,
+ const char *separator, short alias_type)
+{
+ return sudoers_format_member_int(lbuf, parse_tree, m->name, m->type,
+ m->negated, separator, alias_type);
+}
+
+/*
+ * Store a defaults entry as a command tag.
+ */
+bool
+sudoers_defaults_to_tags(const char *var, const char *val, int op,
+ struct cmndtag *tags)
+{
+ bool ret = true;
+ debug_decl(sudoers_defaults_to_tags, SUDOERS_DEBUG_UTIL);
+
+ if (op == true || op == false) {
+ if (strcmp(var, "authenticate") == 0) {
+ tags->nopasswd = op == false;
+ } else if (strcmp(var, "sudoedit_follow") == 0) {
+ tags->follow = op == true;
+ } else if (strcmp(var, "log_input") == 0) {
+ tags->log_input = op == true;
+ } else if (strcmp(var, "log_output") == 0) {
+ tags->log_output = op == true;
+ } else if (strcmp(var, "noexec") == 0) {
+ tags->noexec = op == true;
+ } else if (strcmp(var, "intercept") == 0) {
+ tags->intercept = op == true;
+ } else if (strcmp(var, "setenv") == 0) {
+ tags->setenv = op == true;
+ } else if (strcmp(var, "mail_all_cmnds") == 0 ||
+ strcmp(var, "mail_always") == 0 ||
+ strcmp(var, "mail_no_perms") == 0) {
+ tags->send_mail = op == true;
+ } else {
+ ret = false;
+ }
+ } else {
+ ret = false;
+ }
+ debug_return_bool(ret);
+}
+
+/*
+ * Convert a defaults list to command tags.
+ */
+bool
+sudoers_defaults_list_to_tags(const struct defaults_list *defs,
+ struct cmndtag *tags)
+{
+ const struct defaults *d;
+ bool ret = true;
+ debug_decl(sudoers_defaults_list_to_tags, SUDOERS_DEBUG_UTIL);
+
+ TAGS_INIT(tags);
+ if (defs != NULL) {
+ TAILQ_FOREACH(d, defs, entries) {
+ if (!sudoers_defaults_to_tags(d->var, d->val, d->op, tags)) {
+ if (d->val != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_WARN,
+ "unable to convert defaults to tag: %s%s%s", d->var,
+ d->op == '+' ? "+=" : d->op == '-' ? "-=" : "=", d->val);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN,
+ "unable to convert defaults to tag: %s%s%s",
+ d->op == false ? "!" : "", d->var, "");
+ }
+ ret = false;
+ }
+ }
+ }
+ debug_return_bool(ret);
+}
+
+#define FIELD_CHANGED(ocs, ncs, fld) \
+ ((ocs) == NULL || (ncs)->fld != (ocs)->fld)
+
+#define TAG_CHANGED(ocs, ncs, t, tt) \
+ (TAG_SET((t).tt) && FIELD_CHANGED(ocs, ncs, tags.tt))
+
+/*
+ * Write a cmndspec to lbuf in sudoers format.
+ */
+bool
+sudoers_format_cmndspec(struct sudo_lbuf *lbuf,
+ const struct sudoers_parse_tree *parse_tree, const struct cmndspec *cs,
+ const struct cmndspec *prev_cs, struct cmndtag tags, bool expand_aliases)
+{
+ debug_decl(sudoers_format_cmndspec, SUDOERS_DEBUG_UTIL);
+
+ /* Merge privilege-level tags with cmndspec tags. */
+ TAGS_MERGE(tags, cs->tags);
+
+#ifdef HAVE_PRIV_SET
+ if (cs->privs != NULL && FIELD_CHANGED(prev_cs, cs, privs))
+ sudo_lbuf_append(lbuf, "PRIVS=\"%s\" ", cs->privs);
+ if (cs->limitprivs != NULL && FIELD_CHANGED(prev_cs, cs, limitprivs))
+ sudo_lbuf_append(lbuf, "LIMITPRIVS=\"%s\" ", cs->limitprivs);
+#endif /* HAVE_PRIV_SET */
+#ifdef HAVE_SELINUX
+ if (cs->role != NULL && FIELD_CHANGED(prev_cs, cs, role))
+ sudo_lbuf_append(lbuf, "ROLE=%s ", cs->role);
+ if (cs->type != NULL && FIELD_CHANGED(prev_cs, cs, type))
+ sudo_lbuf_append(lbuf, "TYPE=%s ", cs->type);
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_APPARMOR
+ if (cs->apparmor_profile != NULL && FIELD_CHANGED(prev_cs, cs, apparmor_profile))
+ sudo_lbuf_append(lbuf, "APPARMOR_PROFILE=%s ", cs->apparmor_profile);
+#endif /* HAVE_APPARMOR */
+ if (cs->runchroot != NULL && FIELD_CHANGED(prev_cs, cs, runchroot))
+ sudo_lbuf_append(lbuf, "CHROOT=%s ", cs->runchroot);
+ if (cs->runcwd != NULL && FIELD_CHANGED(prev_cs, cs, runcwd))
+ sudo_lbuf_append(lbuf, "CWD=%s ", cs->runcwd);
+ if (cs->timeout > 0 && FIELD_CHANGED(prev_cs, cs, timeout)) {
+ char numbuf[STRLEN_MAX_SIGNED(int) + 1];
+ (void)snprintf(numbuf, sizeof(numbuf), "%d", cs->timeout);
+ sudo_lbuf_append(lbuf, "TIMEOUT=%s ", numbuf);
+ }
+ if (cs->notbefore != UNSPEC && FIELD_CHANGED(prev_cs, cs, notbefore)) {
+ char buf[sizeof("CCYYMMDDHHMMSSZ")] = "";
+ struct tm gmt;
+ if (gmtime_r(&cs->notbefore, &gmt) != NULL) {
+ size_t len = strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", &gmt);
+ if (len != 0 && buf[sizeof(buf) - 1] == '\0')
+ sudo_lbuf_append(lbuf, "NOTBEFORE=%s ", buf);
+ }
+ }
+ if (cs->notafter != UNSPEC && FIELD_CHANGED(prev_cs, cs, notafter)) {
+ char buf[sizeof("CCYYMMDDHHMMSSZ")] = "";
+ struct tm gmt;
+ if (gmtime_r(&cs->notafter, &gmt) != NULL) {
+ size_t len = strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", &gmt);
+ if (len != 0 && buf[sizeof(buf) - 1] == '\0')
+ sudo_lbuf_append(lbuf, "NOTAFTER=%s ", buf);
+ }
+ }
+ if (TAG_CHANGED(prev_cs, cs, tags, setenv))
+ sudo_lbuf_append(lbuf, tags.setenv ? "SETENV: " : "NOSETENV: ");
+ if (TAG_CHANGED(prev_cs, cs, tags, intercept))
+ sudo_lbuf_append(lbuf, tags.intercept ? "INTERCEPT: " : "NOINTERCEPT: ");
+ if (TAG_CHANGED(prev_cs, cs, tags, noexec))
+ sudo_lbuf_append(lbuf, tags.noexec ? "NOEXEC: " : "EXEC: ");
+ if (TAG_CHANGED(prev_cs, cs, tags, nopasswd))
+ sudo_lbuf_append(lbuf, tags.nopasswd ? "NOPASSWD: " : "PASSWD: ");
+ if (TAG_CHANGED(prev_cs, cs, tags, log_input))
+ sudo_lbuf_append(lbuf, tags.log_input ? "LOG_INPUT: " : "NOLOG_INPUT: ");
+ if (TAG_CHANGED(prev_cs, cs, tags, log_output))
+ sudo_lbuf_append(lbuf, tags.log_output ? "LOG_OUTPUT: " : "NOLOG_OUTPUT: ");
+ if (TAG_CHANGED(prev_cs, cs, tags, send_mail))
+ sudo_lbuf_append(lbuf, tags.send_mail ? "MAIL: " : "NOMAIL: ");
+ if (TAG_CHANGED(prev_cs, cs, tags, follow))
+ sudo_lbuf_append(lbuf, tags.follow ? "FOLLOW: " : "NOFOLLOW: ");
+ sudoers_format_member(lbuf, parse_tree, cs->cmnd, ", ",
+ expand_aliases ? CMNDALIAS : UNSPEC);
+ debug_return_bool(!sudo_lbuf_error(lbuf));
+}
+
+/*
+ * Format and append a defaults entry to the specified lbuf.
+ */
+bool
+sudoers_format_default(struct sudo_lbuf *lbuf, const struct defaults *d)
+{
+ debug_decl(sudoers_format_default, SUDOERS_DEBUG_UTIL);
+
+ if (d->val != NULL) {
+ sudo_lbuf_append(lbuf, "%s%s", d->var,
+ d->op == '+' ? "+=" : d->op == '-' ? "-=" : "=");
+ if (strpbrk(d->val, " \t") != NULL) {
+ sudo_lbuf_append(lbuf, "\"");
+ sudo_lbuf_append_quoted(lbuf, "\"", "%s", d->val);
+ sudo_lbuf_append(lbuf, "\"");
+ } else
+ sudo_lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", d->val);
+ } else {
+ sudo_lbuf_append(lbuf, "%s%s", d->op == false ? "!" : "", d->var);
+ }
+ debug_return_bool(!sudo_lbuf_error(lbuf));
+}
diff --git a/plugins/sudoers/fmtsudoers_cvt.c b/plugins/sudoers/fmtsudoers_cvt.c
new file mode 100644
index 0000000..0f68fa0
--- /dev/null
+++ b/plugins/sudoers/fmtsudoers_cvt.c
@@ -0,0 +1,219 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2004-2005, 2007-2021, 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <sudoers.h>
+#include <sudo_lbuf.h>
+#include <gram.h>
+
+/*
+ * Write a privilege to lbuf in sudoers format.
+ */
+bool
+sudoers_format_privilege(struct sudo_lbuf *lbuf,
+ const struct sudoers_parse_tree *parse_tree, const struct privilege *priv,
+ bool expand_aliases)
+{
+ const struct cmndspec *cs, *prev_cs;
+ const struct member *m;
+ struct cmndtag tags;
+ debug_decl(sudoers_format_privilege, SUDOERS_DEBUG_UTIL);
+
+ /* Convert per-privilege defaults to tags. */
+ sudoers_defaults_list_to_tags(&priv->defaults, &tags);
+
+ /* Print hosts list. */
+ TAILQ_FOREACH(m, &priv->hostlist, entries) {
+ if (m != TAILQ_FIRST(&priv->hostlist))
+ sudo_lbuf_append(lbuf, ", ");
+ sudoers_format_member(lbuf, parse_tree, m, ", ",
+ expand_aliases ? HOSTALIAS : UNSPEC);
+ }
+
+ /* Print commands. */
+ sudo_lbuf_append(lbuf, " = ");
+ prev_cs = NULL;
+ TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
+ if (prev_cs == NULL || RUNAS_CHANGED(cs, prev_cs)) {
+ if (cs != TAILQ_FIRST(&priv->cmndlist))
+ sudo_lbuf_append(lbuf, ", ");
+ if (cs->runasuserlist != NULL || cs->runasgrouplist != NULL)
+ sudo_lbuf_append(lbuf, "(");
+ if (cs->runasuserlist != NULL) {
+ TAILQ_FOREACH(m, cs->runasuserlist, entries) {
+ if (m != TAILQ_FIRST(cs->runasuserlist))
+ sudo_lbuf_append(lbuf, ", ");
+ sudoers_format_member(lbuf, parse_tree, m, ", ",
+ expand_aliases ? RUNASALIAS : UNSPEC);
+ }
+ }
+ if (cs->runasgrouplist != NULL) {
+ sudo_lbuf_append(lbuf, " : ");
+ TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
+ if (m != TAILQ_FIRST(cs->runasgrouplist))
+ sudo_lbuf_append(lbuf, ", ");
+ sudoers_format_member(lbuf, parse_tree, m, ", ",
+ expand_aliases ? RUNASALIAS : UNSPEC);
+ }
+ }
+ if (cs->runasuserlist != NULL || cs->runasgrouplist != NULL)
+ sudo_lbuf_append(lbuf, ") ");
+ } else if (cs != TAILQ_FIRST(&priv->cmndlist)) {
+ sudo_lbuf_append(lbuf, ", ");
+ }
+ sudoers_format_cmndspec(lbuf, parse_tree, cs, prev_cs, tags,
+ expand_aliases);
+ prev_cs = cs;
+ }
+
+ debug_return_bool(!sudo_lbuf_error(lbuf));
+}
+
+/*
+ * Write a userspec to lbuf in sudoers format.
+ */
+bool
+sudoers_format_userspec(struct sudo_lbuf *lbuf,
+ const struct sudoers_parse_tree *parse_tree,
+ const struct userspec *us, bool expand_aliases)
+{
+ const struct sudoers_comment *comment;
+ const struct privilege *priv;
+ const struct member *m;
+ debug_decl(sudoers_format_userspec, SUDOERS_DEBUG_UTIL);
+
+ /* Print comments (if any). */
+ STAILQ_FOREACH(comment, &us->comments, entries) {
+ sudo_lbuf_append(lbuf, "# %s\n", comment->str);
+ }
+
+ /* Print users list. */
+ TAILQ_FOREACH(m, &us->users, entries) {
+ if (m != TAILQ_FIRST(&us->users))
+ sudo_lbuf_append(lbuf, ", ");
+ sudoers_format_member(lbuf, parse_tree, m, ", ",
+ expand_aliases ? USERALIAS : UNSPEC);
+ }
+
+ TAILQ_FOREACH(priv, &us->privileges, entries) {
+ if (priv != TAILQ_FIRST(&us->privileges))
+ sudo_lbuf_append(lbuf, " : ");
+ else
+ sudo_lbuf_append(lbuf, " ");
+ if (!sudoers_format_privilege(lbuf, parse_tree, priv, expand_aliases))
+ break;
+ }
+ sudo_lbuf_append(lbuf, "\n");
+
+ debug_return_bool(!sudo_lbuf_error(lbuf));
+}
+
+/*
+ * Write a userspec_list to lbuf in sudoers format.
+ */
+bool
+sudoers_format_userspecs(struct sudo_lbuf *lbuf,
+ const struct sudoers_parse_tree *parse_tree, const char *separator,
+ bool expand_aliases, bool flush)
+{
+ const struct userspec *us;
+ debug_decl(sudoers_format_userspecs, SUDOERS_DEBUG_UTIL);
+
+ TAILQ_FOREACH(us, &parse_tree->userspecs, entries) {
+ if (separator != NULL && us != TAILQ_FIRST(&parse_tree->userspecs))
+ sudo_lbuf_append(lbuf, "%s", separator);
+ if (!sudoers_format_userspec(lbuf, parse_tree, us, expand_aliases))
+ break;
+ sudo_lbuf_print(lbuf);
+ }
+
+ debug_return_bool(!sudo_lbuf_error(lbuf));
+}
+
+/*
+ * Format and append a defaults line to the specified lbuf.
+ * If next, is specified, it must point to the next defaults
+ * entry in the list; this is used to print multiple defaults
+ * entries with the same binding on a single line.
+ */
+bool
+sudoers_format_default_line(struct sudo_lbuf *lbuf,
+ const struct sudoers_parse_tree *parse_tree, const struct defaults *d,
+ struct defaults **next, bool expand_aliases)
+{
+ const struct member *m;
+ short alias_type;
+ debug_decl(sudoers_format_default_line, SUDOERS_DEBUG_UTIL);
+
+ /* Print Defaults type and binding (if present) */
+ switch (d->type) {
+ case DEFAULTS_HOST:
+ sudo_lbuf_append(lbuf, "Defaults@");
+ alias_type = expand_aliases ? HOSTALIAS : UNSPEC;
+ break;
+ case DEFAULTS_USER:
+ sudo_lbuf_append(lbuf, "Defaults:");
+ alias_type = expand_aliases ? USERALIAS : UNSPEC;
+ break;
+ case DEFAULTS_RUNAS:
+ sudo_lbuf_append(lbuf, "Defaults>");
+ alias_type = expand_aliases ? RUNASALIAS : UNSPEC;
+ break;
+ case DEFAULTS_CMND:
+ sudo_lbuf_append(lbuf, "Defaults!");
+ alias_type = expand_aliases ? CMNDALIAS : UNSPEC;
+ break;
+ default:
+ sudo_lbuf_append(lbuf, "Defaults");
+ alias_type = UNSPEC;
+ break;
+ }
+ TAILQ_FOREACH(m, &d->binding->members, entries) {
+ if (m != TAILQ_FIRST(&d->binding->members))
+ sudo_lbuf_append(lbuf, ", ");
+ sudoers_format_member(lbuf, parse_tree, m, ", ", alias_type);
+ }
+
+ sudo_lbuf_append(lbuf, " ");
+ sudoers_format_default(lbuf, d);
+
+ if (next != NULL) {
+ /* Merge Defaults with the same binding, there may be multiple. */
+ struct defaults *n;
+ while ((n = TAILQ_NEXT(d, entries)) && d->binding == n->binding) {
+ sudo_lbuf_append(lbuf, ", ");
+ sudoers_format_default(lbuf, n);
+ d = n;
+ }
+ *next = n;
+ }
+ sudo_lbuf_append(lbuf, "\n");
+
+ debug_return_bool(!sudo_lbuf_error(lbuf));
+}
diff --git a/plugins/sudoers/gc.c b/plugins/sudoers/gc.c
new file mode 100644
index 0000000..5bcb2dc
--- /dev/null
+++ b/plugins/sudoers/gc.c
@@ -0,0 +1,154 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2016 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudoers.h>
+
+struct sudoers_gc_entry {
+ SLIST_ENTRY(sudoers_gc_entry) entries;
+ enum sudoers_gc_types type;
+ union {
+ char **vec;
+ void *ptr;
+ } u;
+};
+SLIST_HEAD(sudoers_gc_list, sudoers_gc_entry);
+#ifdef NO_LEAKS
+static struct sudoers_gc_list sudoers_gc_list =
+ SLIST_HEAD_INITIALIZER(sudoers_gc_list);
+#endif
+
+bool
+sudoers_gc_add(enum sudoers_gc_types type, void *v)
+{
+#ifdef NO_LEAKS
+ struct sudoers_gc_entry *gc;
+ debug_decl(sudoers_gc_add, SUDOERS_DEBUG_UTIL);
+
+ if (v == NULL)
+ debug_return_bool(false);
+
+ gc = calloc(1, sizeof(*gc));
+ if (gc == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ switch (type) {
+ case GC_PTR:
+ gc->u.ptr = v;
+ break;
+ case GC_VECTOR:
+ gc->u.vec = v;
+ break;
+ default:
+ free(gc);
+ sudo_warnx("unexpected garbage type %d", type);
+ debug_return_bool(false);
+ }
+ gc->type = type;
+ SLIST_INSERT_HEAD(&sudoers_gc_list, gc, entries);
+ debug_return_bool(true);
+#else
+ return true;
+#endif /* NO_LEAKS */
+}
+
+bool
+sudoers_gc_remove(enum sudoers_gc_types type, void *v)
+{
+#ifdef NO_LEAKS
+ struct sudoers_gc_entry *gc, *prev = NULL;
+ debug_decl(sudoers_gc_remove, SUDOERS_DEBUG_UTIL);
+
+ if (v == NULL)
+ debug_return_bool(false);
+
+ SLIST_FOREACH(gc, &sudoers_gc_list, entries) {
+ switch (gc->type) {
+ case GC_PTR:
+ if (gc->u.ptr == v)
+ goto found;
+ break;
+ case GC_VECTOR:
+ if (gc->u.vec == v)
+ goto found;
+ break;
+ default:
+ sudo_warnx("unexpected garbage type %d in %p", gc->type, gc);
+ }
+ prev = gc;
+ }
+ /* If this happens, there is a bug in the g/c code. */
+ sudo_warnx("%s: unable to find %p, type %d", __func__, v, type);
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ abort();
+#else
+ debug_return_bool(false);
+#endif
+found:
+ if (prev == NULL)
+ SLIST_REMOVE_HEAD(&sudoers_gc_list, entries);
+ else
+ SLIST_REMOVE_AFTER(prev, entries);
+ free(gc);
+
+ debug_return_bool(true);
+#else
+ return true;
+#endif /* NO_LEAKS */
+}
+
+void
+sudoers_gc_run(void)
+{
+#ifdef NO_LEAKS
+ struct sudoers_gc_entry *gc;
+ char **cur;
+ debug_decl(sudoers_gc_run, SUDOERS_DEBUG_UTIL);
+
+ /* Collect garbage. */
+ while ((gc = SLIST_FIRST(&sudoers_gc_list)) != NULL) {
+ SLIST_REMOVE_HEAD(&sudoers_gc_list, entries);
+ switch (gc->type) {
+ case GC_PTR:
+ free(gc->u.ptr);
+ free(gc);
+ break;
+ case GC_VECTOR:
+ for (cur = gc->u.vec; *cur != NULL; cur++)
+ free(*cur);
+ free(gc->u.vec);
+ free(gc);
+ break;
+ default:
+ sudo_warnx("unexpected garbage type %d", gc->type);
+ }
+ }
+
+ debug_return;
+#endif /* NO_LEAKS */
+}
diff --git a/plugins/sudoers/gentime.c b/plugins/sudoers/gentime.c
new file mode 100644
index 0000000..7575c37
--- /dev/null
+++ b/plugins/sudoers/gentime.c
@@ -0,0 +1,171 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2017, 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+
+#include <sudo_compat.h>
+#include <sudoers_debug.h>
+#include <parse.h>
+
+/* Since timegm() is only used in one place we keep the macro local. */
+#ifndef HAVE_TIMEGM
+# define timegm(_t) sudo_timegm(_t)
+#endif
+
+/*
+ * Parse a timestamp in Generalized Time format as per RFC4517.
+ * E.g. yyyymmddHHMMSS.FZ or yyyymmddHHMMSS.F[+-]TZOFF
+ * where minutes, seconds and fraction are optional.
+ * Returns the time in Unix time format or -1 on error.
+ */
+time_t
+parse_gentime(const char *timestr)
+{
+ char tcopy[sizeof("yyyymmddHHMMSS")];
+ const char *cp;
+ time_t result;
+ struct tm tm;
+ size_t len;
+ int items, tzoff = 0;
+ bool islocal = false;
+ debug_decl(parse_gentime, SUDOERS_DEBUG_PARSER);
+
+ /* Make a copy of the non-fractional time without zone for easy parsing. */
+ len = strspn(timestr, "0123456789");
+ if (len >= sizeof(tcopy) || len < sizeof("yyyymmddHH") -1 || (len & 1)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to parse general time string %s", timestr);
+ debug_return_time_t(-1);
+ }
+ memcpy(tcopy, timestr, len);
+ tcopy[len] = '\0';
+
+ /* Parse general time, ignoring the timezone for now. */
+ memset(&tm, 0, sizeof(tm));
+ items = sscanf(tcopy, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon,
+ &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
+ if (items == EOF || items < 4) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "only parsed %d items in general time string %s", items, timestr);
+ debug_return_time_t(-1);
+ }
+
+ /* Parse optional fractional hours/minute/second if present. */
+ cp = timestr + len;
+ if ((cp[0] == '.' || cp[0] == ',') && isdigit((unsigned char)cp[1])) {
+ int frac = cp[1] - '0';
+ switch (items) {
+ case 4:
+ /* convert fractional hour -> minutes */
+ tm.tm_min += 60 / 10 * frac;
+ break;
+ case 5:
+ /* convert fractional minute -> seconds */
+ tm.tm_sec += 60 / 10 * frac;
+ break;
+ case 6:
+ /* ignore fractional second */
+ break;
+ }
+ cp += 2; /* skip over radix and fraction */
+ }
+
+ /* Parse optional time zone. */
+ switch (*cp) {
+ case '-':
+ case '+': {
+ int hour = 0, min = 0;
+
+ /* No DST */
+ tm.tm_isdst = 0;
+ /* time zone offset must be hh or hhmm */
+ len = strspn(cp + 1, "0123456789");
+ if (len != 2 && len != 4) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to parse time zone offset in %s, bad tz offset",
+ timestr);
+ debug_return_time_t(-1);
+ }
+ /* parse time zone offset */
+ items = sscanf(cp + 1, "%2d%2d", &hour, &min);
+ if (items == EOF || items < 1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to parse time zone offset in %s, items %d",
+ timestr, items);
+ debug_return_time_t(-1);
+ }
+ if (*cp == '-')
+ tzoff = -((hour * 60) + min) * 60;
+ else
+ tzoff = ((hour * 60) + min) * 60;
+ cp += 1 + (items * 2);
+ break;
+ }
+ case 'Z':
+ /* GMT/UTC, no DST */
+ tm.tm_isdst = 0;
+ cp++;
+ break;
+ case '\0':
+ /* no zone specified, use local time */
+ tm.tm_isdst = -1;
+ islocal = true;
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to parse general time string %s", timestr);
+ debug_return_time_t(-1);
+ }
+ if (*cp != '\0') {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "trailing garbage in general time string %s", timestr);
+ debug_return_time_t(-1);
+ }
+
+ /* Adjust from Generalized Time to struct tm */
+ tm.tm_year -= 1900;
+ tm.tm_mon--;
+
+ if (islocal) {
+ result = mktime(&tm);
+ } else {
+ result = timegm(&tm);
+ if (result != -1) {
+ /* Adjust time based on supplied GMT offset. */
+ result -= tzoff;
+ }
+ }
+
+ debug_return_time_t(result);
+}
diff --git a/plugins/sudoers/getdate.c b/plugins/sudoers/getdate.c
new file mode 100644
index 0000000..23a424b
--- /dev/null
+++ b/plugins/sudoers/getdate.c
@@ -0,0 +1,2455 @@
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+/* A Bison parser, made by GNU Bison 3.8.2. */
+
+/* Bison implementation for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
+ Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
+ especially those whose name start with YY_ or yy_. They are
+ private implementation details that can be changed or removed. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output, and Bison version. */
+#define YYBISON 30802
+
+/* Bison version string. */
+#define YYBISON_VERSION "3.8.2"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+
+
+
+/* First part of user prologue. */
+#line 1 "getdate.y"
+
+/*
+** Originally written by Steven M. Bellovin <smb@research.att.com> while
+** at the University of North Carolina at Chapel Hill. Later tweaked by
+** a couple of people on Usenet. Completely overhauled by Rich $alz
+** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
+**
+** This grammar has 10 shift/reduce conflicts.
+**
+** This code is in the public domain and has no copyright.
+*/
+/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
+/* SUPPRESS 288 on yyerrlab *//* Label unused */
+
+// PVS Studio suppression
+// -V::560, 592, 1037, 1042
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <time.h>
+#include <limits.h>
+#include <ctype.h>
+
+#include <sudo_compat.h>
+
+
+#define EPOCH 1970
+#define HOUR(x) ((time_t)(x) * 60)
+#define SECSPERDAY (24L * 60L * 60L)
+
+
+/*
+** An entry in the lexical lookup table.
+*/
+typedef struct _TABLE {
+ const char *name;
+ int type;
+ time_t value;
+} TABLE;
+
+
+/*
+** Daylight-savings mode: on, off, or not yet known.
+*/
+typedef enum _DSTMODE {
+ DSTon, DSToff, DSTmaybe
+} DSTMODE;
+
+/*
+** Meridian: am, pm, or 24-hour style.
+*/
+typedef enum _MERIDIAN {
+ MERam, MERpm, MER24
+} MERIDIAN;
+
+
+/*
+** Global variables. We could get rid of most of these by using a good
+** union as the yacc stack. (This routine was originally written before
+** yacc had the %union construct.) Maybe someday; right now we only use
+** the %union very rarely.
+*/
+static char *yyInput;
+static DSTMODE yyDSTmode;
+static time_t yyDayOrdinal;
+static time_t yyDayNumber;
+static int yyHaveDate;
+static int yyHaveDay;
+static int yyHaveRel;
+static int yyHaveTime;
+static int yyHaveZone;
+static time_t yyTimezone;
+static time_t yyDay;
+static time_t yyHour;
+static time_t yyMinutes;
+static time_t yyMonth;
+static time_t yySeconds;
+static time_t yyYear;
+static MERIDIAN yyMeridian;
+static time_t yyRelMonth;
+static time_t yyRelSeconds;
+
+static int yylex(void);
+ int yyparse(void);
+ void yyerror(const char *s);
+
+
+#line 167 "getdate.c"
+
+# ifndef YY_CAST
+# ifdef __cplusplus
+# define YY_CAST(Type, Val) static_cast<Type> (Val)
+# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast<Type> (Val)
+# else
+# define YY_CAST(Type, Val) ((Type) (Val))
+# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val))
+# endif
+# endif
+# ifndef YY_NULLPTR
+# if defined __cplusplus
+# if 201103L <= __cplusplus
+# define YY_NULLPTR nullptr
+# else
+# define YY_NULLPTR 0
+# endif
+# else
+# define YY_NULLPTR ((void*)0)
+# endif
+# endif
+
+
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+
+/* Token kinds. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ YYEMPTY = -2,
+ YYEOF = 0, /* "end of file" */
+ YYerror = 256, /* error */
+ YYUNDEF = 257, /* "invalid token" */
+ tAGO = 258, /* tAGO */
+ tID = 259, /* tID */
+ tDST = 260, /* tDST */
+ tDAY = 261, /* tDAY */
+ tDAYZONE = 262, /* tDAYZONE */
+ tMINUTE_UNIT = 263, /* tMINUTE_UNIT */
+ tMONTH = 264, /* tMONTH */
+ tMONTH_UNIT = 265, /* tMONTH_UNIT */
+ tSEC_UNIT = 266, /* tSEC_UNIT */
+ tSNUMBER = 267, /* tSNUMBER */
+ tUNUMBER = 268, /* tUNUMBER */
+ tZONE = 269, /* tZONE */
+ tMERIDIAN = 270 /* tMERIDIAN */
+ };
+ typedef enum yytokentype yytoken_kind_t;
+#endif
+/* Token kinds. */
+#define YYEMPTY -2
+#define YYEOF 0
+#define YYerror 256
+#define YYUNDEF 257
+#define tAGO 258
+#define tID 259
+#define tDST 260
+#define tDAY 261
+#define tDAYZONE 262
+#define tMINUTE_UNIT 263
+#define tMONTH 264
+#define tMONTH_UNIT 265
+#define tSEC_UNIT 266
+#define tSNUMBER 267
+#define tUNUMBER 268
+#define tZONE 269
+#define tMERIDIAN 270
+
+/* Value type. */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+union YYSTYPE
+{
+#line 97 "getdate.y"
+
+ time_t Number;
+ enum _MERIDIAN Meridian;
+
+#line 252 "getdate.c"
+
+};
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+extern YYSTYPE yylval;
+
+
+int yyparse (void);
+
+
+
+/* Symbol kind. */
+enum yysymbol_kind_t
+{
+ YYSYMBOL_YYEMPTY = -2,
+ YYSYMBOL_YYEOF = 0, /* "end of file" */
+ YYSYMBOL_YYerror = 1, /* error */
+ YYSYMBOL_YYUNDEF = 2, /* "invalid token" */
+ YYSYMBOL_tAGO = 3, /* tAGO */
+ YYSYMBOL_tID = 4, /* tID */
+ YYSYMBOL_tDST = 5, /* tDST */
+ YYSYMBOL_tDAY = 6, /* tDAY */
+ YYSYMBOL_tDAYZONE = 7, /* tDAYZONE */
+ YYSYMBOL_tMINUTE_UNIT = 8, /* tMINUTE_UNIT */
+ YYSYMBOL_tMONTH = 9, /* tMONTH */
+ YYSYMBOL_tMONTH_UNIT = 10, /* tMONTH_UNIT */
+ YYSYMBOL_tSEC_UNIT = 11, /* tSEC_UNIT */
+ YYSYMBOL_tSNUMBER = 12, /* tSNUMBER */
+ YYSYMBOL_tUNUMBER = 13, /* tUNUMBER */
+ YYSYMBOL_tZONE = 14, /* tZONE */
+ YYSYMBOL_tMERIDIAN = 15, /* tMERIDIAN */
+ YYSYMBOL_16_ = 16, /* ':' */
+ YYSYMBOL_17_ = 17, /* ',' */
+ YYSYMBOL_18_ = 18, /* '/' */
+ YYSYMBOL_YYACCEPT = 19, /* $accept */
+ YYSYMBOL_spec = 20, /* spec */
+ YYSYMBOL_item = 21, /* item */
+ YYSYMBOL_time = 22, /* time */
+ YYSYMBOL_zone = 23, /* zone */
+ YYSYMBOL_day = 24, /* day */
+ YYSYMBOL_date = 25, /* date */
+ YYSYMBOL_rel = 26, /* rel */
+ YYSYMBOL_relunit = 27, /* relunit */
+ YYSYMBOL_number = 28, /* number */
+ YYSYMBOL_o_merid = 29 /* o_merid */
+};
+typedef enum yysymbol_kind_t yysymbol_kind_t;
+
+
+
+
+#ifdef short
+# undef short
+#endif
+
+/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure
+ <limits.h> and (if available) <stdint.h> are included
+ so that the code can choose integer types of a good width. */
+
+#ifndef __PTRDIFF_MAX__
+# include <limits.h> /* INFRINGES ON USER NAME SPACE */
+# if defined HAVE_STDINT_H
+# include <stdint.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_STDINT_H
+# endif
+#endif
+
+/* Narrow types that promote to a signed type and that can represent a
+ signed or unsigned integer of at least N bits. In tables they can
+ save space and decrease cache pressure. Promoting to a signed type
+ helps avoid bugs in integer arithmetic. */
+
+#ifdef __INT_LEAST8_MAX__
+typedef __INT_LEAST8_TYPE__ yytype_int8;
+#elif defined YY_STDINT_H
+typedef int_least8_t yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef __INT_LEAST16_MAX__
+typedef __INT_LEAST16_TYPE__ yytype_int16;
+#elif defined YY_STDINT_H
+typedef int_least16_t yytype_int16;
+#else
+typedef short yytype_int16;
+#endif
+
+/* Work around bug in HP-UX 11.23, which defines these macros
+ incorrectly for preprocessor constants. This workaround can likely
+ be removed in 2023, as HPE has promised support for HP-UX 11.23
+ (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of
+ <https://h20195.www2.hpe.com/V2/getpdf.aspx/4AA4-7673ENW.pdf>. */
+#ifdef __hpux
+# undef UINT_LEAST8_MAX
+# undef UINT_LEAST16_MAX
+# define UINT_LEAST8_MAX 255
+# define UINT_LEAST16_MAX 65535
+#endif
+
+#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__
+typedef __UINT_LEAST8_TYPE__ yytype_uint8;
+#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \
+ && UINT_LEAST8_MAX <= INT_MAX)
+typedef uint_least8_t yytype_uint8;
+#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX
+typedef unsigned char yytype_uint8;
+#else
+typedef short yytype_uint8;
+#endif
+
+#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__
+typedef __UINT_LEAST16_TYPE__ yytype_uint16;
+#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \
+ && UINT_LEAST16_MAX <= INT_MAX)
+typedef uint_least16_t yytype_uint16;
+#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX
+typedef unsigned short yytype_uint16;
+#else
+typedef int yytype_uint16;
+#endif
+
+#ifndef YYPTRDIFF_T
+# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__
+# define YYPTRDIFF_T __PTRDIFF_TYPE__
+# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__
+# elif defined PTRDIFF_MAX
+# ifndef ptrdiff_t
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# endif
+# define YYPTRDIFF_T ptrdiff_t
+# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX
+# else
+# define YYPTRDIFF_T long
+# define YYPTRDIFF_MAXIMUM LONG_MAX
+# endif
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM \
+ YY_CAST (YYPTRDIFF_T, \
+ (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \
+ ? YYPTRDIFF_MAXIMUM \
+ : YY_CAST (YYSIZE_T, -1)))
+
+#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X))
+
+
+/* Stored state numbers (used for stacks). */
+typedef yytype_int8 yy_state_t;
+
+/* State numbers in computations. */
+typedef int yy_state_fast_t;
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(Msgid) Msgid
+# endif
+#endif
+
+
+#ifndef YY_ATTRIBUTE_PURE
+# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
+# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__))
+# else
+# define YY_ATTRIBUTE_PURE
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__)
+# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+# else
+# define YY_ATTRIBUTE_UNUSED
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YY_USE(E) ((void) (E))
+#else
+# define YY_USE(E) /* empty */
+#endif
+
+/* Suppress an incorrect diagnostic about yylval being uninitialized. */
+#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__
+# if __GNUC__ * 100 + __GNUC_MINOR__ < 407
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")
+# else
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \
+ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# endif
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+ _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__
+# define YY_IGNORE_USELESS_CAST_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"")
+# define YY_IGNORE_USELESS_CAST_END \
+ _Pragma ("GCC diagnostic pop")
+#endif
+#ifndef YY_IGNORE_USELESS_CAST_BEGIN
+# define YY_IGNORE_USELESS_CAST_BEGIN
+# define YY_IGNORE_USELESS_CAST_END
+#endif
+
+
+#define YY_ASSERT(E) ((void) (0 && (E)))
+
+#if !defined yyoverflow
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+ /* Use EXIT_SUCCESS as a witness for stdlib.h. */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's 'empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined EXIT_SUCCESS \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* !defined yyoverflow */
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yy_state_t yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYPTRDIFF_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / YYSIZEOF (*yyptr); \
+ } \
+ while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(Dst, Src, Count) \
+ __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src)))
+# else
+# define YYCOPY(Dst, Src, Count) \
+ do \
+ { \
+ YYPTRDIFF_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (Dst)[yyi] = (Src)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 2
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 41
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 19
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 11
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 42
+/* YYNSTATES -- Number of states. */
+#define YYNSTATES 52
+
+/* YYMAXUTOK -- Last valid token kind. */
+#define YYMAXUTOK 270
+
+
+/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, with out-of-bounds checking. */
+#define YYTRANSLATE(YYX) \
+ (0 <= (YYX) && (YYX) <= YYMAXUTOK \
+ ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \
+ : YYSYMBOL_YYUNDEF)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex. */
+static const yytype_int8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 17, 2, 2, 18, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 16, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15
+};
+
+#if YYDEBUG
+/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
+static const yytype_int16 yyrline[] =
+{
+ 0, 111, 111, 112, 115, 118, 121, 124, 127, 130,
+ 133, 139, 145, 152, 158, 168, 172, 177, 183, 187,
+ 191, 197, 201, 212, 218, 224, 228, 233, 237, 244,
+ 248, 251, 254, 257, 260, 263, 266, 269, 272, 275,
+ 280, 307, 310
+};
+#endif
+
+/** Accessing symbol of state STATE. */
+#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State])
+
+#if YYDEBUG || 0
+/* The user-facing name of the symbol whose (internal) number is
+ YYSYMBOL. No bounds checking. */
+static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED;
+
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "\"end of file\"", "error", "\"invalid token\"", "tAGO", "tID", "tDST",
+ "tDAY", "tDAYZONE", "tMINUTE_UNIT", "tMONTH", "tMONTH_UNIT", "tSEC_UNIT",
+ "tSNUMBER", "tUNUMBER", "tZONE", "tMERIDIAN", "':'", "','", "'/'",
+ "$accept", "spec", "item", "time", "zone", "day", "date", "rel",
+ "relunit", "number", "o_merid", YY_NULLPTR
+};
+
+static const char *
+yysymbol_name (yysymbol_kind_t yysymbol)
+{
+ return yytname[yysymbol];
+}
+#endif
+
+#define YYPACT_NINF (-12)
+
+#define yypact_value_is_default(Yyn) \
+ ((Yyn) == YYPACT_NINF)
+
+#define YYTABLE_NINF (-1)
+
+#define yytable_value_is_error(Yyn) \
+ 0
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+static const yytype_int8 yypact[] =
+{
+ -12, 0, -12, -1, -12, -12, 10, -12, -12, 18,
+ 9, 17, -12, -12, -12, -12, -12, -12, 27, -12,
+ -12, 15, -12, -12, -12, -12, -12, -10, -12, -12,
+ 21, -12, 22, 23, -12, -12, 24, -12, -12, -12,
+ -11, 20, -12, -12, -12, 26, -12, 28, 19, -12,
+ -12, -12
+};
+
+/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE does not specify something else to do. Zero
+ means the default is an error. */
+static const yytype_int8 yydefact[] =
+{
+ 2, 0, 1, 18, 16, 33, 0, 39, 36, 0,
+ 40, 15, 3, 4, 5, 7, 6, 8, 30, 9,
+ 19, 25, 32, 37, 34, 20, 31, 27, 38, 35,
+ 0, 10, 0, 0, 17, 29, 0, 24, 28, 23,
+ 41, 21, 26, 12, 42, 0, 11, 0, 41, 22,
+ 14, 13
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
+{
+ -12, -12, -12, -12, -12, -12, -12, -12, -12, -12,
+ -8
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int8 yydefgoto[] =
+{
+ 0, 1, 12, 13, 14, 15, 16, 17, 18, 19,
+ 46
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule whose
+ number is the opposite. If YYTABLE_NINF, syntax error. */
+static const yytype_int8 yytable[] =
+{
+ 2, 43, 37, 38, 44, 45, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 25, 20, 26, 27, 28,
+ 29, 30, 34, 21, 31, 32, 22, 33, 23, 24,
+ 35, 50, 36, 39, 44, 40, 41, 42, 47, 48,
+ 51, 49
+};
+
+static const yytype_int8 yycheck[] =
+{
+ 0, 12, 12, 13, 15, 16, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 6, 17, 8, 9, 10,
+ 11, 12, 5, 13, 15, 16, 8, 18, 10, 11,
+ 3, 12, 17, 12, 15, 13, 13, 13, 18, 13,
+ 48, 13
+};
+
+/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of
+ state STATE-NUM. */
+static const yytype_int8 yystos[] =
+{
+ 0, 20, 0, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 21, 22, 23, 24, 25, 26, 27, 28,
+ 17, 13, 8, 10, 11, 6, 8, 9, 10, 11,
+ 12, 15, 16, 18, 5, 3, 17, 12, 13, 12,
+ 13, 13, 13, 12, 15, 16, 29, 18, 13, 13,
+ 12, 29
+};
+
+/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */
+static const yytype_int8 yyr1[] =
+{
+ 0, 19, 20, 20, 21, 21, 21, 21, 21, 21,
+ 22, 22, 22, 22, 22, 23, 23, 23, 24, 24,
+ 24, 25, 25, 25, 25, 25, 25, 25, 25, 26,
+ 26, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 28, 29, 29
+};
+
+/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */
+static const yytype_int8 yyr2[] =
+{
+ 0, 2, 0, 2, 1, 1, 1, 1, 1, 1,
+ 2, 4, 4, 6, 6, 1, 1, 2, 1, 2,
+ 2, 3, 5, 3, 3, 2, 4, 2, 3, 2,
+ 1, 2, 2, 1, 2, 2, 1, 2, 2, 1,
+ 1, 0, 1
+};
+
+
+enum { YYENOMEM = -2 };
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+#define YYNOMEM goto yyexhaustedlab
+
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+ do \
+ if (yychar == YYEMPTY) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ YYPOPSTACK (yylen); \
+ yystate = *yyssp; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+ while (0)
+
+/* Backward compatibility with an undocumented macro.
+ Use YYerror or YYUNDEF. */
+#define YYERRCODE YYUNDEF
+
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+
+
+
+# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Kind, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
+
+
+/*-----------------------------------.
+| Print this symbol's value on YYO. |
+`-----------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyo,
+ yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep)
+{
+ FILE *yyoutput = yyo;
+ YY_USE (yyoutput);
+ if (!yyvaluep)
+ return;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ YY_USE (yykind);
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+/*---------------------------.
+| Print this symbol on YYO. |
+`---------------------------*/
+
+static void
+yy_symbol_print (FILE *yyo,
+ yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep)
+{
+ YYFPRINTF (yyo, "%s %s (",
+ yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind));
+
+ yy_symbol_value_print (yyo, yykind, yyvaluep);
+ YYFPRINTF (yyo, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop)
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp,
+ int yyrule)
+{
+ int yylno = yyrline[yyrule];
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr,
+ YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]),
+ &yyvsp[(yyi + 1) - (yynrhs)]);
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyssp, yyvsp, Rule); \
+} while (0)
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args) ((void) 0)
+# define YY_SYMBOL_PRINT(Title, Kind, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg,
+ yysymbol_kind_t yykind, YYSTYPE *yyvaluep)
+{
+ YY_USE (yyvaluep);
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp);
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ YY_USE (yykind);
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+/* Lookahead token kind. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+/* Number of syntax errors so far. */
+int yynerrs;
+
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+int
+yyparse (void)
+{
+ yy_state_fast_t yystate = 0;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus = 0;
+
+ /* Refer to the stacks through separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* Their size. */
+ YYPTRDIFF_T yystacksize = YYINITDEPTH;
+
+ /* The state stack: array, bottom, top. */
+ yy_state_t yyssa[YYINITDEPTH];
+ yy_state_t *yyss = yyssa;
+ yy_state_t *yyssp = yyss;
+
+ /* The semantic value stack: array, bottom, top. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ YYSTYPE *yyvsp = yyvs;
+
+ int yyn;
+ /* The return value of yyparse. */
+ int yyresult;
+ /* Lookahead symbol kind. */
+ yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ goto yysetstate;
+
+
+/*------------------------------------------------------------.
+| yynewstate -- push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+
+/*--------------------------------------------------------------------.
+| yysetstate -- set current state (the top of the stack) to yystate. |
+`--------------------------------------------------------------------*/
+yysetstate:
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+ YY_ASSERT (0 <= yystate && yystate < YYNSTATES);
+ YY_IGNORE_USELESS_CAST_BEGIN
+ *yyssp = YY_CAST (yy_state_t, yystate);
+ YY_IGNORE_USELESS_CAST_END
+ YY_STACK_PRINT (yyss, yyssp);
+
+ if (yyss + yystacksize - 1 <= yyssp)
+#if !defined yyoverflow && !defined YYSTACK_RELOCATE
+ YYNOMEM;
+#else
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYPTRDIFF_T yysize = yyssp - yyss + 1;
+
+# if defined yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ yy_state_t *yyss1 = yyss;
+ YYSTYPE *yyvs1 = yyvs;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * YYSIZEOF (*yyssp),
+ &yyvs1, yysize * YYSIZEOF (*yyvsp),
+ &yystacksize);
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+# else /* defined YYSTACK_RELOCATE */
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ YYNOMEM;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yy_state_t *yyss1 = yyss;
+ union yyalloc *yyptr =
+ YY_CAST (union yyalloc *,
+ YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
+ if (! yyptr)
+ YYNOMEM;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+ YY_IGNORE_USELESS_CAST_BEGIN
+ YYDPRINTF ((stderr, "Stack size increased to %ld\n",
+ YY_CAST (long, yystacksize)));
+ YY_IGNORE_USELESS_CAST_END
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
+
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yypact_value_is_default (yyn))
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token\n"));
+ yychar = yylex ();
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = YYEOF;
+ yytoken = YYSYMBOL_YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else if (yychar == YYerror)
+ {
+ /* The scanner already issued an error message, process directly
+ to error recovery. But do not keep the error token as
+ lookahead, it is too special and may lead us to an endless
+ loop in error recovery. */
+ yychar = YYUNDEF;
+ yytoken = YYSYMBOL_YYerror;
+ goto yyerrlab1;
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yytable_value_is_error (yyn))
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+ yystate = yyn;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ '$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 4: /* item: time */
+#line 115 "getdate.y"
+ {
+ yyHaveTime++;
+ }
+#line 1290 "getdate.c"
+ break;
+
+ case 5: /* item: zone */
+#line 118 "getdate.y"
+ {
+ yyHaveZone++;
+ }
+#line 1298 "getdate.c"
+ break;
+
+ case 6: /* item: date */
+#line 121 "getdate.y"
+ {
+ yyHaveDate++;
+ }
+#line 1306 "getdate.c"
+ break;
+
+ case 7: /* item: day */
+#line 124 "getdate.y"
+ {
+ yyHaveDay++;
+ }
+#line 1314 "getdate.c"
+ break;
+
+ case 8: /* item: rel */
+#line 127 "getdate.y"
+ {
+ yyHaveRel++;
+ }
+#line 1322 "getdate.c"
+ break;
+
+ case 10: /* time: tUNUMBER tMERIDIAN */
+#line 133 "getdate.y"
+ {
+ yyHour = (yyvsp[-1].Number);
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyMeridian = (yyvsp[0].Meridian);
+ }
+#line 1333 "getdate.c"
+ break;
+
+ case 11: /* time: tUNUMBER ':' tUNUMBER o_merid */
+#line 139 "getdate.y"
+ {
+ yyHour = (yyvsp[-3].Number);
+ yyMinutes = (yyvsp[-1].Number);
+ yySeconds = 0;
+ yyMeridian = (yyvsp[0].Meridian);
+ }
+#line 1344 "getdate.c"
+ break;
+
+ case 12: /* time: tUNUMBER ':' tUNUMBER tSNUMBER */
+#line 145 "getdate.y"
+ {
+ yyHour = (yyvsp[-3].Number);
+ yyMinutes = (yyvsp[-1].Number);
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = - ((yyvsp[0].Number) % 100 + ((yyvsp[0].Number) / 100) * 60);
+ }
+#line 1356 "getdate.c"
+ break;
+
+ case 13: /* time: tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid */
+#line 152 "getdate.y"
+ {
+ yyHour = (yyvsp[-5].Number);
+ yyMinutes = (yyvsp[-3].Number);
+ yySeconds = (yyvsp[-1].Number);
+ yyMeridian = (yyvsp[0].Meridian);
+ }
+#line 1367 "getdate.c"
+ break;
+
+ case 14: /* time: tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER */
+#line 158 "getdate.y"
+ {
+ yyHour = (yyvsp[-5].Number);
+ yyMinutes = (yyvsp[-3].Number);
+ yySeconds = (yyvsp[-1].Number);
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = - ((yyvsp[0].Number) % 100 + ((yyvsp[0].Number) / 100) * 60);
+ }
+#line 1380 "getdate.c"
+ break;
+
+ case 15: /* zone: tZONE */
+#line 168 "getdate.y"
+ {
+ yyTimezone = (yyvsp[0].Number);
+ yyDSTmode = DSToff;
+ }
+#line 1389 "getdate.c"
+ break;
+
+ case 16: /* zone: tDAYZONE */
+#line 172 "getdate.y"
+ {
+ yyTimezone = (yyvsp[0].Number);
+ yyDSTmode = DSTon;
+ }
+#line 1398 "getdate.c"
+ break;
+
+ case 17: /* zone: tZONE tDST */
+#line 177 "getdate.y"
+ {
+ yyTimezone = (yyvsp[-1].Number);
+ yyDSTmode = DSTon;
+ }
+#line 1407 "getdate.c"
+ break;
+
+ case 18: /* day: tDAY */
+#line 183 "getdate.y"
+ {
+ yyDayOrdinal = 1;
+ yyDayNumber = (yyvsp[0].Number);
+ }
+#line 1416 "getdate.c"
+ break;
+
+ case 19: /* day: tDAY ',' */
+#line 187 "getdate.y"
+ {
+ yyDayOrdinal = 1;
+ yyDayNumber = (yyvsp[-1].Number);
+ }
+#line 1425 "getdate.c"
+ break;
+
+ case 20: /* day: tUNUMBER tDAY */
+#line 191 "getdate.y"
+ {
+ yyDayOrdinal = (yyvsp[-1].Number);
+ yyDayNumber = (yyvsp[0].Number);
+ }
+#line 1434 "getdate.c"
+ break;
+
+ case 21: /* date: tUNUMBER '/' tUNUMBER */
+#line 197 "getdate.y"
+ {
+ yyMonth = (yyvsp[-2].Number);
+ yyDay = (yyvsp[0].Number);
+ }
+#line 1443 "getdate.c"
+ break;
+
+ case 22: /* date: tUNUMBER '/' tUNUMBER '/' tUNUMBER */
+#line 201 "getdate.y"
+ {
+ if ((yyvsp[-4].Number) >= 100) {
+ yyYear = (yyvsp[-4].Number);
+ yyMonth = (yyvsp[-2].Number);
+ yyDay = (yyvsp[0].Number);
+ } else {
+ yyMonth = (yyvsp[-4].Number);
+ yyDay = (yyvsp[-2].Number);
+ yyYear = (yyvsp[0].Number);
+ }
+ }
+#line 1459 "getdate.c"
+ break;
+
+ case 23: /* date: tUNUMBER tSNUMBER tSNUMBER */
+#line 212 "getdate.y"
+ {
+ /* ISO 8601 format. yyyy-mm-dd. */
+ yyYear = (yyvsp[-2].Number);
+ yyMonth = -(yyvsp[-1].Number);
+ yyDay = -(yyvsp[0].Number);
+ }
+#line 1470 "getdate.c"
+ break;
+
+ case 24: /* date: tUNUMBER tMONTH tSNUMBER */
+#line 218 "getdate.y"
+ {
+ /* e.g. 17-JUN-1992. */
+ yyDay = (yyvsp[-2].Number);
+ yyMonth = (yyvsp[-1].Number);
+ yyYear = -(yyvsp[0].Number);
+ }
+#line 1481 "getdate.c"
+ break;
+
+ case 25: /* date: tMONTH tUNUMBER */
+#line 224 "getdate.y"
+ {
+ yyMonth = (yyvsp[-1].Number);
+ yyDay = (yyvsp[0].Number);
+ }
+#line 1490 "getdate.c"
+ break;
+
+ case 26: /* date: tMONTH tUNUMBER ',' tUNUMBER */
+#line 228 "getdate.y"
+ {
+ yyMonth = (yyvsp[-3].Number);
+ yyDay = (yyvsp[-2].Number);
+ yyYear = (yyvsp[0].Number);
+ }
+#line 1500 "getdate.c"
+ break;
+
+ case 27: /* date: tUNUMBER tMONTH */
+#line 233 "getdate.y"
+ {
+ yyMonth = (yyvsp[0].Number);
+ yyDay = (yyvsp[-1].Number);
+ }
+#line 1509 "getdate.c"
+ break;
+
+ case 28: /* date: tUNUMBER tMONTH tUNUMBER */
+#line 237 "getdate.y"
+ {
+ yyMonth = (yyvsp[-1].Number);
+ yyDay = (yyvsp[-2].Number);
+ yyYear = (yyvsp[0].Number);
+ }
+#line 1519 "getdate.c"
+ break;
+
+ case 29: /* rel: relunit tAGO */
+#line 244 "getdate.y"
+ {
+ yyRelSeconds = -yyRelSeconds;
+ yyRelMonth = -yyRelMonth;
+ }
+#line 1528 "getdate.c"
+ break;
+
+ case 31: /* relunit: tUNUMBER tMINUTE_UNIT */
+#line 251 "getdate.y"
+ {
+ yyRelSeconds += (yyvsp[-1].Number) * (yyvsp[0].Number) * 60L;
+ }
+#line 1536 "getdate.c"
+ break;
+
+ case 32: /* relunit: tSNUMBER tMINUTE_UNIT */
+#line 254 "getdate.y"
+ {
+ yyRelSeconds += (yyvsp[-1].Number) * (yyvsp[0].Number) * 60L;
+ }
+#line 1544 "getdate.c"
+ break;
+
+ case 33: /* relunit: tMINUTE_UNIT */
+#line 257 "getdate.y"
+ {
+ yyRelSeconds += (yyvsp[0].Number) * 60L;
+ }
+#line 1552 "getdate.c"
+ break;
+
+ case 34: /* relunit: tSNUMBER tSEC_UNIT */
+#line 260 "getdate.y"
+ {
+ yyRelSeconds += (yyvsp[-1].Number);
+ }
+#line 1560 "getdate.c"
+ break;
+
+ case 35: /* relunit: tUNUMBER tSEC_UNIT */
+#line 263 "getdate.y"
+ {
+ yyRelSeconds += (yyvsp[-1].Number);
+ }
+#line 1568 "getdate.c"
+ break;
+
+ case 36: /* relunit: tSEC_UNIT */
+#line 266 "getdate.y"
+ {
+ yyRelSeconds++;
+ }
+#line 1576 "getdate.c"
+ break;
+
+ case 37: /* relunit: tSNUMBER tMONTH_UNIT */
+#line 269 "getdate.y"
+ {
+ yyRelMonth += (yyvsp[-1].Number) * (yyvsp[0].Number);
+ }
+#line 1584 "getdate.c"
+ break;
+
+ case 38: /* relunit: tUNUMBER tMONTH_UNIT */
+#line 272 "getdate.y"
+ {
+ yyRelMonth += (yyvsp[-1].Number) * (yyvsp[0].Number);
+ }
+#line 1592 "getdate.c"
+ break;
+
+ case 39: /* relunit: tMONTH_UNIT */
+#line 275 "getdate.y"
+ {
+ yyRelMonth += (yyvsp[0].Number);
+ }
+#line 1600 "getdate.c"
+ break;
+
+ case 40: /* number: tUNUMBER */
+#line 280 "getdate.y"
+ {
+ if (yyHaveTime && yyHaveDate && !yyHaveRel)
+ yyYear = (yyvsp[0].Number);
+ else {
+ if((yyvsp[0].Number)>10000) {
+ yyHaveDate++;
+ yyDay= ((yyvsp[0].Number))%100;
+ yyMonth= ((yyvsp[0].Number)/100)%100;
+ yyYear = (yyvsp[0].Number)/10000;
+ }
+ else {
+ yyHaveTime++;
+ if ((yyvsp[0].Number) < 100) {
+ yyHour = (yyvsp[0].Number);
+ yyMinutes = 0;
+ }
+ else {
+ yyHour = (yyvsp[0].Number) / 100;
+ yyMinutes = (yyvsp[0].Number) % 100;
+ }
+ yySeconds = 0;
+ yyMeridian = MER24;
+ }
+ }
+ }
+#line 1630 "getdate.c"
+ break;
+
+ case 41: /* o_merid: %empty */
+#line 307 "getdate.y"
+ {
+ (yyval.Meridian) = MER24;
+ }
+#line 1638 "getdate.c"
+ break;
+
+ case 42: /* o_merid: tMERIDIAN */
+#line 310 "getdate.y"
+ {
+ (yyval.Meridian) = (yyvsp[0].Meridian);
+ }
+#line 1646 "getdate.c"
+ break;
+
+
+#line 1650 "getdate.c"
+
+ default: break;
+ }
+ /* User semantic actions sometimes alter yychar, and that requires
+ that yytoken be updated with the new translation. We take the
+ approach of translating immediately before every use of yytoken.
+ One alternative is translating here after every semantic action,
+ but that translation would be missed if the semantic action invokes
+ YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+ if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
+ incorrect destructor might then be invoked immediately. In the
+ case of YYERROR or YYBACKUP, subsequent parser actions might lead
+ to an incorrect destructor call or verbose syntax error message
+ before the lookahead is translated. */
+ YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+
+ *++yyvsp = yyval;
+
+ /* Now 'shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+ {
+ const int yylhs = yyr1[yyn] - YYNTOKENS;
+ const int yyi = yypgoto[yylhs] + *yyssp;
+ yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp
+ ? yytable[yyi]
+ : yydefgoto[yylhs]);
+ }
+
+ goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error. |
+`--------------------------------------*/
+yyerrlab:
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar);
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+ yyerror (YY_("syntax error"));
+ }
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+ /* Pacify compilers when the user code never invokes YYERROR and the
+ label yyerrorlab therefore never appears in user code. */
+ if (0)
+ YYERROR;
+ ++yynerrs;
+
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ /* Pop stack until we find a state that shifts the error token. */
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (!yypact_value_is_default (yyn))
+ {
+ yyn += YYSYMBOL_YYerror;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ YY_ACCESSING_SYMBOL (yystate), yyvsp);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturnlab;
+
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturnlab;
+
+
+/*-----------------------------------------------------------.
+| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. |
+`-----------------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (YY_("memory exhausted"));
+ yyresult = 2;
+ goto yyreturnlab;
+
+
+/*----------------------------------------------------------.
+| yyreturnlab -- parsing is finished, clean up and return. |
+`----------------------------------------------------------*/
+yyreturnlab:
+ if (yychar != YYEMPTY)
+ {
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = YYTRANSLATE (yychar);
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval);
+ }
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ YY_ACCESSING_SYMBOL (+*yyssp), yyvsp);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+
+ return yyresult;
+}
+
+#line 315 "getdate.y"
+
+
+/* Month and day table. */
+static TABLE const MonthDayTable[] = {
+ { "january", tMONTH, 1 },
+ { "february", tMONTH, 2 },
+ { "march", tMONTH, 3 },
+ { "april", tMONTH, 4 },
+ { "may", tMONTH, 5 },
+ { "june", tMONTH, 6 },
+ { "july", tMONTH, 7 },
+ { "august", tMONTH, 8 },
+ { "september", tMONTH, 9 },
+ { "sept", tMONTH, 9 },
+ { "october", tMONTH, 10 },
+ { "november", tMONTH, 11 },
+ { "december", tMONTH, 12 },
+ { "sunday", tDAY, 0 },
+ { "monday", tDAY, 1 },
+ { "tuesday", tDAY, 2 },
+ { "tues", tDAY, 2 },
+ { "wednesday", tDAY, 3 },
+ { "wednes", tDAY, 3 },
+ { "thursday", tDAY, 4 },
+ { "thur", tDAY, 4 },
+ { "thurs", tDAY, 4 },
+ { "friday", tDAY, 5 },
+ { "saturday", tDAY, 6 },
+ { NULL }
+};
+
+/* Time units table. */
+static TABLE const UnitsTable[] = {
+ { "year", tMONTH_UNIT, 12 },
+ { "month", tMONTH_UNIT, 1 },
+ { "fortnight", tMINUTE_UNIT, 14 * 24 * 60 },
+ { "week", tMINUTE_UNIT, 7 * 24 * 60 },
+ { "day", tMINUTE_UNIT, 1 * 24 * 60 },
+ { "hour", tMINUTE_UNIT, 60 },
+ { "minute", tMINUTE_UNIT, 1 },
+ { "min", tMINUTE_UNIT, 1 },
+ { "second", tSEC_UNIT, 1 },
+ { "sec", tSEC_UNIT, 1 },
+ { NULL }
+};
+
+/* Assorted relative-time words. */
+static TABLE const OtherTable[] = {
+ { "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 },
+ { "yesterday", tMINUTE_UNIT, -1 * 24 * 60 },
+ { "today", tMINUTE_UNIT, 0 },
+ { "now", tMINUTE_UNIT, 0 },
+ { "last", tUNUMBER, -1 },
+ { "this", tUNUMBER, 0 },
+ { "next", tUNUMBER, 2 },
+ { "first", tUNUMBER, 1 },
+/* { "second", tUNUMBER, 2 }, */
+ { "third", tUNUMBER, 3 },
+ { "fourth", tUNUMBER, 4 },
+ { "fifth", tUNUMBER, 5 },
+ { "sixth", tUNUMBER, 6 },
+ { "seventh", tUNUMBER, 7 },
+ { "eighth", tUNUMBER, 8 },
+ { "ninth", tUNUMBER, 9 },
+ { "tenth", tUNUMBER, 10 },
+ { "eleventh", tUNUMBER, 11 },
+ { "twelfth", tUNUMBER, 12 },
+ { "ago", tAGO, 1 },
+ { NULL }
+};
+
+/* The timezone table. */
+/* Some of these are commented out because a time_t can't store a float. */
+static TABLE const TimezoneTable[] = {
+ { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
+ { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
+ { "utc", tZONE, HOUR( 0) },
+ { "wet", tZONE, HOUR( 0) }, /* Western European */
+ { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
+ { "wat", tZONE, HOUR( 1) }, /* West Africa */
+ { "at", tZONE, HOUR( 2) }, /* Azores */
+#if 0
+ /* For completeness. BST is also British Summer, and GST is
+ * also Guam Standard. */
+ { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
+ { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
+#endif
+#if 0
+ { "nft", tZONE, HOUR(3.5) }, /* Newfoundland */
+ { "nst", tZONE, HOUR(3.5) }, /* Newfoundland Standard */
+ { "ndt", tDAYZONE, HOUR(3.5) }, /* Newfoundland Daylight */
+#endif
+ { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
+ { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
+ { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
+ { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
+ { "cst", tZONE, HOUR( 6) }, /* Central Standard */
+ { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
+ { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
+ { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
+ { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
+ { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
+ { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
+ { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
+ { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
+ { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
+ { "cat", tZONE, HOUR(10) }, /* Central Alaska */
+ { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
+ { "nt", tZONE, HOUR(11) }, /* Nome */
+ { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
+ { "cet", tZONE, -HOUR(1) }, /* Central European */
+ { "met", tZONE, -HOUR(1) }, /* Middle European */
+ { "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
+ { "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
+ { "swt", tZONE, -HOUR(1) }, /* Swedish Winter */
+ { "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */
+ { "fwt", tZONE, -HOUR(1) }, /* French Winter */
+ { "fst", tDAYZONE, -HOUR(1) }, /* French Summer */
+ { "eet", tZONE, -HOUR(2) }, /* Eastern Europe, USSR Zone 1 */
+ { "bt", tZONE, -HOUR(3) }, /* Baghdad, USSR Zone 2 */
+#if 0
+ { "it", tZONE, -HOUR(3.5) },/* Iran */
+#endif
+ { "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */
+ { "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */
+#if 0
+ { "ist", tZONE, -HOUR(5.5) },/* Indian Standard */
+#endif
+ { "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */
+#if 0
+ /* For completeness. NST is also Newfoundland Standard, and SST is
+ * also Swedish Summer. */
+ { "nst", tZONE, -HOUR(6.5) },/* North Sumatra */
+ { "sst", tZONE, -HOUR(7) }, /* South Sumatra, USSR Zone 6 */
+#endif /* 0 */
+ { "wast", tZONE, -HOUR(7) }, /* West Australian Standard */
+ { "wadt", tDAYZONE, -HOUR(7) }, /* West Australian Daylight */
+#if 0
+ { "jt", tZONE, -HOUR(7.5) },/* Java (3pm in Cronusland!) */
+#endif
+ { "cct", tZONE, -HOUR(8) }, /* China Coast, USSR Zone 7 */
+ { "jst", tZONE, -HOUR(9) }, /* Japan Standard, USSR Zone 8 */
+#if 0
+ { "cast", tZONE, -HOUR(9.5) },/* Central Australian Standard */
+ { "cadt", tDAYZONE, -HOUR(9.5) },/* Central Australian Daylight */
+#endif
+ { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
+ { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
+ { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
+ { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
+ { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
+ { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
+ { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
+ { NULL }
+};
+
+/* Military timezone table. */
+static TABLE const MilitaryTable[] = {
+ { "a", tZONE, HOUR( 1) },
+ { "b", tZONE, HOUR( 2) },
+ { "c", tZONE, HOUR( 3) },
+ { "d", tZONE, HOUR( 4) },
+ { "e", tZONE, HOUR( 5) },
+ { "f", tZONE, HOUR( 6) },
+ { "g", tZONE, HOUR( 7) },
+ { "h", tZONE, HOUR( 8) },
+ { "i", tZONE, HOUR( 9) },
+ { "k", tZONE, HOUR( 10) },
+ { "l", tZONE, HOUR( 11) },
+ { "m", tZONE, HOUR( 12) },
+ { "n", tZONE, HOUR(- 1) },
+ { "o", tZONE, HOUR(- 2) },
+ { "p", tZONE, HOUR(- 3) },
+ { "q", tZONE, HOUR(- 4) },
+ { "r", tZONE, HOUR(- 5) },
+ { "s", tZONE, HOUR(- 6) },
+ { "t", tZONE, HOUR(- 7) },
+ { "u", tZONE, HOUR(- 8) },
+ { "v", tZONE, HOUR(- 9) },
+ { "w", tZONE, HOUR(-10) },
+ { "x", tZONE, HOUR(-11) },
+ { "y", tZONE, HOUR(-12) },
+ { "z", tZONE, HOUR( 0) },
+ { NULL }
+};
+
+
+
+
+/* ARGSUSED */
+void
+yyerror(const char *s)
+{
+ return;
+}
+
+
+static time_t
+ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian)
+{
+ if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
+ return -1;
+ switch (Meridian) {
+ case MER24:
+ if (Hours < 0 || Hours > 23)
+ return -1;
+ return (Hours * 60L + Minutes) * 60L + Seconds;
+ case MERam:
+ if (Hours < 1 || Hours > 12)
+ return -1;
+ if (Hours == 12)
+ Hours = 0;
+ return (Hours * 60L + Minutes) * 60L + Seconds;
+ case MERpm:
+ if (Hours < 1 || Hours > 12)
+ return -1;
+ if (Hours == 12)
+ Hours = 0;
+ return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
+ default:
+ abort ();
+ }
+ /* NOTREACHED */
+}
+
+
+/* Year is either
+ * A negative number, which means to use its absolute value (why?)
+ * A number from 0 to 99, which means a year from 1900 to 1999, or
+ * The actual year (>=100). */
+static time_t
+Convert(time_t Month, time_t Day, time_t Year, time_t Hours, time_t Minutes,
+ time_t Seconds, MERIDIAN Meridian, DSTMODE DSTmode)
+{
+ static int DaysInMonth[12] = {
+ 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ struct tm tm;
+ time_t tod;
+ time_t Julian;
+ int i;
+
+ if (Year < 0)
+ Year = -Year;
+ if (Year < 69)
+ Year += 2000;
+ else if (Year < 100) {
+ Year += 1900;
+ if (Year < EPOCH)
+ Year += 100;
+ }
+ DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
+ ? 29 : 28;
+ /* 32-bit time_t cannot represent years past 2038 */
+ if (Year < EPOCH || (sizeof(time_t) == sizeof(int) && Year > 2038)
+ || Month < 1 || Month > 12
+ /* Lint fluff: "conversion from long may lose accuracy" */
+ || Day < 1 || Day > DaysInMonth[--Month])
+ return -1;
+
+ for (Julian = Day - 1, i = 0; i < Month; i++)
+ Julian += DaysInMonth[i];
+ for (i = EPOCH; i < Year; i++)
+ Julian += 365 + (i % 4 == 0);
+ Julian *= SECSPERDAY;
+ Julian += yyTimezone * 60L;
+ if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
+ return -1;
+ Julian += tod;
+ if (DSTmode == DSTon
+ || (DSTmode == DSTmaybe && localtime_r(&Julian, &tm) && tm.tm_isdst))
+ Julian -= 60 * 60;
+ return Julian;
+}
+
+
+static time_t
+DSTcorrect(time_t Start, time_t Future)
+{
+ struct tm start_tm;
+ struct tm future_tm;
+ time_t StartDay;
+ time_t FutureDay;
+
+ if (!localtime_r(&Start, &start_tm) || !localtime_r(&Future, &future_tm))
+ return -1;
+
+ StartDay = (start_tm.tm_hour + 1) % 24;
+ FutureDay = (future_tm.tm_hour + 1) % 24;
+ return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
+}
+
+
+static time_t
+RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber)
+{
+ struct tm tm;
+ time_t now;
+
+ now = Start;
+ if (!localtime_r(&now, &tm))
+ return -1;
+ now += SECSPERDAY * ((DayNumber - tm.tm_wday + 7) % 7);
+ now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
+ return DSTcorrect(Start, now);
+}
+
+
+static time_t
+RelativeMonth(time_t Start, time_t RelMonth)
+{
+ struct tm tm;
+ time_t Month;
+ time_t Year;
+
+ if (RelMonth == 0)
+ return 0;
+ if (!localtime_r(&Start, &tm))
+ return -1;
+ Month = 12 * (tm.tm_year + 1900) + tm.tm_mon + RelMonth;
+ Year = Month / 12;
+ Month = Month % 12 + 1;
+ return DSTcorrect(Start,
+ Convert(Month, (time_t)tm.tm_mday, Year,
+ (time_t)tm.tm_hour, (time_t)tm.tm_min, (time_t)tm.tm_sec,
+ MER24, DSTmaybe));
+}
+
+
+static int
+LookupWord(char *buff)
+{
+ char *p;
+ char *q;
+ const TABLE *tp;
+ int i;
+ int abbrev;
+ int bufflen;
+
+ /* Make it lowercase. */
+ for (p = buff; *p; p++) {
+ if (isupper((unsigned char)*p))
+ *p = (char)tolower((unsigned char)*p);
+ }
+ if ((bufflen = (int)(p - buff)) == 0)
+ return '\0';
+
+ if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
+ yylval.Meridian = MERam;
+ return tMERIDIAN;
+ }
+ if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
+ yylval.Meridian = MERpm;
+ return tMERIDIAN;
+ }
+
+ /* See if we have an abbreviation for a month. */
+ if (bufflen == 3)
+ abbrev = 1;
+ else if (bufflen == 4 && buff[3] == '.') {
+ abbrev = 1;
+ buff[bufflen = 3] = '\0';
+ }
+ else
+ abbrev = 0;
+
+ for (tp = MonthDayTable; tp->name; tp++) {
+ if (abbrev) {
+ if (strncmp(buff, tp->name, 3) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+ else if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+
+ for (tp = TimezoneTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ if (strcmp(buff, "dst") == 0)
+ return tDST;
+
+ for (tp = UnitsTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ /* Strip off any plural and try the units table again. */
+ i = bufflen - 1;
+ if (buff[i] == 's') {
+ buff[i] = '\0';
+ for (tp = UnitsTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ buff[i] = 's'; /* Put back for "this" in OtherTable. */
+ }
+
+ for (tp = OtherTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ /* Military timezones. */
+ if (buff[1] == '\0' && isalpha((unsigned char)*buff)) {
+ for (tp = MilitaryTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+
+ /* Drop out any periods and try the timezone table again. */
+ for (i = 0, p = q = buff; *q; q++)
+ if (*q != '.')
+ *p++ = *q;
+ else
+ i++;
+ *p = '\0';
+ if (i)
+ for (tp = TimezoneTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ return tID;
+}
+
+
+static int
+yylex(void)
+{
+ char c;
+ char *p;
+ char buff[20];
+ int Count;
+ int sign;
+
+ for ( ; ; ) {
+ while (isspace((unsigned char)*yyInput))
+ yyInput++;
+
+ if (isdigit((unsigned char)(c = *yyInput)) || c == '-' || c == '+') {
+ if (c == '-' || c == '+') {
+ sign = c == '-' ? -1 : 1;
+ if (!isdigit((unsigned char)*++yyInput))
+ /* skip the '-' sign */
+ continue;
+ }
+ else
+ sign = 0;
+ for (yylval.Number = 0; isdigit((unsigned char)(c = *yyInput++)); )
+ yylval.Number = 10 * yylval.Number + c - '0';
+ yyInput--;
+ if (sign < 0)
+ yylval.Number = -yylval.Number;
+ return sign ? tSNUMBER : tUNUMBER;
+ }
+ if (isalpha((unsigned char)c)) {
+ for (p = buff; isalpha((unsigned char)(c = *yyInput++)) || c == '.'; )
+ if (p < &buff[sizeof buff - 1])
+ *p++ = c;
+ *p = '\0';
+ yyInput--;
+ return LookupWord(buff);
+ }
+ if (c != '(')
+ return *yyInput++;
+ Count = 0;
+ do {
+ c = *yyInput++;
+ if (c == '\0')
+ return c;
+ if (c == '(')
+ Count++;
+ else if (c == ')')
+ Count--;
+ } while (Count > 0);
+ }
+}
+
+#define TM_YEAR_ORIGIN 1900
+
+/* Yield A - B, measured in seconds. */
+static long
+difftm(struct tm *a, struct tm *b)
+{
+ int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
+ int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
+ long days = (
+ /* difference in day of year */
+ a->tm_yday - b->tm_yday
+ /* + intervening leap days */
+ + ((ay >> 2) - (by >> 2))
+ - (ay/100 - by/100)
+ + ((ay/100 >> 2) - (by/100 >> 2))
+ /* + difference in years * 365 */
+ + (long)(ay-by) * 365
+ );
+ return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
+ + (a->tm_min - b->tm_min))
+ + (a->tm_sec - b->tm_sec));
+}
+
+time_t get_date(char *p);
+
+time_t
+get_date(char *p)
+{
+ struct tm tm, gmt;
+ time_t Start;
+ time_t tod;
+ time_t now;
+ time_t tz;
+
+ yyInput = p;
+ (void)time (&now);
+
+ if (gmtime_r (&now, &gmt) == NULL)
+ return -1;
+
+ if (localtime_r (&now, &tm) == NULL)
+ return -1;
+
+ tz = difftm (&gmt, &tm) / 60;
+ if (tm.tm_isdst)
+ tz += 60;
+
+ yyYear = tm.tm_year + 1900;
+ yyMonth = tm.tm_mon + 1;
+ yyDay = tm.tm_mday;
+ yyTimezone = tz;
+ yyDSTmode = DSTmaybe;
+ yyHour = 0;
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyMeridian = MER24;
+ yyRelSeconds = 0;
+ yyRelMonth = 0;
+ yyHaveDate = 0;
+ yyHaveDay = 0;
+ yyHaveRel = 0;
+ yyHaveTime = 0;
+ yyHaveZone = 0;
+
+ if (yyparse()
+ || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
+ return -1;
+
+ if (yyHaveDate || yyHaveTime || yyHaveDay) {
+ Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
+ yyMeridian, yyDSTmode);
+ if (Start < 0)
+ return -1;
+ }
+ else {
+ Start = now;
+ if (!yyHaveRel)
+ Start -= ((tm.tm_hour * 60L + tm.tm_min) * 60L) + tm.tm_sec;
+ }
+
+ Start += yyRelSeconds;
+ Start += RelativeMonth(Start, yyRelMonth);
+
+ if (yyHaveDay && !yyHaveDate) {
+ tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
+ Start += tod;
+ }
+
+ /* Have to do *something* with a legitimate -1 so it's distinguishable
+ * from the error return value. (Alternately could set errno on error.) */
+ return Start == -1 ? 0 : Start;
+}
+
+
+#ifdef TEST
+
+/* ARGSUSED */
+int
+main(int argc, char *argv[])
+{
+ char buff[128];
+ time_t d;
+
+ (void)fputs("Enter date, or blank line to exit.\n\t> ", stdout);
+ (void)fflush(stdout);
+ while (fgets(buff, sizeof(buff), stdin) && buff[0]) {
+ d = get_date(buff);
+ if (d == -1)
+ (void)fputs("Bad format - couldn't convert.\n\t> ", stdout);
+ else
+ (void)printf("%s\t> ", ctime(&d));
+ (void)fflush(stdout);
+ }
+ return 0;
+}
+#endif /* TEST */
diff --git a/plugins/sudoers/getdate.y b/plugins/sudoers/getdate.y
new file mode 100644
index 0000000..b773763
--- /dev/null
+++ b/plugins/sudoers/getdate.y
@@ -0,0 +1,921 @@
+%{
+/*
+** Originally written by Steven M. Bellovin <smb@research.att.com> while
+** at the University of North Carolina at Chapel Hill. Later tweaked by
+** a couple of people on Usenet. Completely overhauled by Rich $alz
+** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
+**
+** This grammar has 10 shift/reduce conflicts.
+**
+** This code is in the public domain and has no copyright.
+*/
+/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
+/* SUPPRESS 288 on yyerrlab *//* Label unused */
+
+// PVS Studio suppression
+// -V::560, 592, 1037, 1042
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <time.h>
+#include <limits.h>
+#include <ctype.h>
+
+#include <sudo_compat.h>
+
+
+#define EPOCH 1970
+#define HOUR(x) ((time_t)(x) * 60)
+#define SECSPERDAY (24L * 60L * 60L)
+
+
+/*
+** An entry in the lexical lookup table.
+*/
+typedef struct _TABLE {
+ const char *name;
+ int type;
+ time_t value;
+} TABLE;
+
+
+/*
+** Daylight-savings mode: on, off, or not yet known.
+*/
+typedef enum _DSTMODE {
+ DSTon, DSToff, DSTmaybe
+} DSTMODE;
+
+/*
+** Meridian: am, pm, or 24-hour style.
+*/
+typedef enum _MERIDIAN {
+ MERam, MERpm, MER24
+} MERIDIAN;
+
+
+/*
+** Global variables. We could get rid of most of these by using a good
+** union as the yacc stack. (This routine was originally written before
+** yacc had the %union construct.) Maybe someday; right now we only use
+** the %union very rarely.
+*/
+static char *yyInput;
+static DSTMODE yyDSTmode;
+static time_t yyDayOrdinal;
+static time_t yyDayNumber;
+static int yyHaveDate;
+static int yyHaveDay;
+static int yyHaveRel;
+static int yyHaveTime;
+static int yyHaveZone;
+static time_t yyTimezone;
+static time_t yyDay;
+static time_t yyHour;
+static time_t yyMinutes;
+static time_t yyMonth;
+static time_t yySeconds;
+static time_t yyYear;
+static MERIDIAN yyMeridian;
+static time_t yyRelMonth;
+static time_t yyRelSeconds;
+
+static int yylex(void);
+ int yyparse(void);
+ void yyerror(const char *s);
+
+%}
+
+%union {
+ time_t Number;
+ enum _MERIDIAN Meridian;
+}
+
+%token tAGO tID tDST
+%token <Number> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
+%token <Number> tSEC_UNIT tSNUMBER tUNUMBER tZONE
+%token <Meridian> tMERIDIAN
+
+%type <Meridian> o_merid
+
+%%
+
+spec : /* NULL */
+ | spec item
+ ;
+
+item : time {
+ yyHaveTime++;
+ }
+ | zone {
+ yyHaveZone++;
+ }
+ | date {
+ yyHaveDate++;
+ }
+ | day {
+ yyHaveDay++;
+ }
+ | rel {
+ yyHaveRel++;
+ }
+ | number
+ ;
+
+time : tUNUMBER tMERIDIAN {
+ yyHour = $1;
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyMeridian = $2;
+ }
+ | tUNUMBER ':' tUNUMBER o_merid {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = 0;
+ yyMeridian = $4;
+ }
+ | tUNUMBER ':' tUNUMBER tSNUMBER {
+ yyHour = $1;
+ yyMinutes = $3;
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
+ }
+ | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = $5;
+ yyMeridian = $6;
+ }
+ | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = $5;
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
+ }
+ ;
+
+zone : tZONE {
+ yyTimezone = $1;
+ yyDSTmode = DSToff;
+ }
+ | tDAYZONE {
+ yyTimezone = $1;
+ yyDSTmode = DSTon;
+ }
+ |
+ tZONE tDST {
+ yyTimezone = $1;
+ yyDSTmode = DSTon;
+ }
+ ;
+
+day : tDAY {
+ yyDayOrdinal = 1;
+ yyDayNumber = $1;
+ }
+ | tDAY ',' {
+ yyDayOrdinal = 1;
+ yyDayNumber = $1;
+ }
+ | tUNUMBER tDAY {
+ yyDayOrdinal = $1;
+ yyDayNumber = $2;
+ }
+ ;
+
+date : tUNUMBER '/' tUNUMBER {
+ yyMonth = $1;
+ yyDay = $3;
+ }
+ | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
+ if ($1 >= 100) {
+ yyYear = $1;
+ yyMonth = $3;
+ yyDay = $5;
+ } else {
+ yyMonth = $1;
+ yyDay = $3;
+ yyYear = $5;
+ }
+ }
+ | tUNUMBER tSNUMBER tSNUMBER {
+ /* ISO 8601 format. yyyy-mm-dd. */
+ yyYear = $1;
+ yyMonth = -$2;
+ yyDay = -$3;
+ }
+ | tUNUMBER tMONTH tSNUMBER {
+ /* e.g. 17-JUN-1992. */
+ yyDay = $1;
+ yyMonth = $2;
+ yyYear = -$3;
+ }
+ | tMONTH tUNUMBER {
+ yyMonth = $1;
+ yyDay = $2;
+ }
+ | tMONTH tUNUMBER ',' tUNUMBER {
+ yyMonth = $1;
+ yyDay = $2;
+ yyYear = $4;
+ }
+ | tUNUMBER tMONTH {
+ yyMonth = $2;
+ yyDay = $1;
+ }
+ | tUNUMBER tMONTH tUNUMBER {
+ yyMonth = $2;
+ yyDay = $1;
+ yyYear = $3;
+ }
+ ;
+
+rel : relunit tAGO {
+ yyRelSeconds = -yyRelSeconds;
+ yyRelMonth = -yyRelMonth;
+ }
+ | relunit
+ ;
+
+relunit : tUNUMBER tMINUTE_UNIT {
+ yyRelSeconds += $1 * $2 * 60L;
+ }
+ | tSNUMBER tMINUTE_UNIT {
+ yyRelSeconds += $1 * $2 * 60L;
+ }
+ | tMINUTE_UNIT {
+ yyRelSeconds += $1 * 60L;
+ }
+ | tSNUMBER tSEC_UNIT {
+ yyRelSeconds += $1;
+ }
+ | tUNUMBER tSEC_UNIT {
+ yyRelSeconds += $1;
+ }
+ | tSEC_UNIT {
+ yyRelSeconds++;
+ }
+ | tSNUMBER tMONTH_UNIT {
+ yyRelMonth += $1 * $2;
+ }
+ | tUNUMBER tMONTH_UNIT {
+ yyRelMonth += $1 * $2;
+ }
+ | tMONTH_UNIT {
+ yyRelMonth += $1;
+ }
+ ;
+
+number : tUNUMBER {
+ if (yyHaveTime && yyHaveDate && !yyHaveRel)
+ yyYear = $1;
+ else {
+ if($1>10000) {
+ yyHaveDate++;
+ yyDay= ($1)%100;
+ yyMonth= ($1/100)%100;
+ yyYear = $1/10000;
+ }
+ else {
+ yyHaveTime++;
+ if ($1 < 100) {
+ yyHour = $1;
+ yyMinutes = 0;
+ }
+ else {
+ yyHour = $1 / 100;
+ yyMinutes = $1 % 100;
+ }
+ yySeconds = 0;
+ yyMeridian = MER24;
+ }
+ }
+ }
+ ;
+
+o_merid : /* NULL */ {
+ $$ = MER24;
+ }
+ | tMERIDIAN {
+ $$ = $1;
+ }
+ ;
+
+%%
+
+/* Month and day table. */
+static TABLE const MonthDayTable[] = {
+ { "january", tMONTH, 1 },
+ { "february", tMONTH, 2 },
+ { "march", tMONTH, 3 },
+ { "april", tMONTH, 4 },
+ { "may", tMONTH, 5 },
+ { "june", tMONTH, 6 },
+ { "july", tMONTH, 7 },
+ { "august", tMONTH, 8 },
+ { "september", tMONTH, 9 },
+ { "sept", tMONTH, 9 },
+ { "october", tMONTH, 10 },
+ { "november", tMONTH, 11 },
+ { "december", tMONTH, 12 },
+ { "sunday", tDAY, 0 },
+ { "monday", tDAY, 1 },
+ { "tuesday", tDAY, 2 },
+ { "tues", tDAY, 2 },
+ { "wednesday", tDAY, 3 },
+ { "wednes", tDAY, 3 },
+ { "thursday", tDAY, 4 },
+ { "thur", tDAY, 4 },
+ { "thurs", tDAY, 4 },
+ { "friday", tDAY, 5 },
+ { "saturday", tDAY, 6 },
+ { NULL }
+};
+
+/* Time units table. */
+static TABLE const UnitsTable[] = {
+ { "year", tMONTH_UNIT, 12 },
+ { "month", tMONTH_UNIT, 1 },
+ { "fortnight", tMINUTE_UNIT, 14 * 24 * 60 },
+ { "week", tMINUTE_UNIT, 7 * 24 * 60 },
+ { "day", tMINUTE_UNIT, 1 * 24 * 60 },
+ { "hour", tMINUTE_UNIT, 60 },
+ { "minute", tMINUTE_UNIT, 1 },
+ { "min", tMINUTE_UNIT, 1 },
+ { "second", tSEC_UNIT, 1 },
+ { "sec", tSEC_UNIT, 1 },
+ { NULL }
+};
+
+/* Assorted relative-time words. */
+static TABLE const OtherTable[] = {
+ { "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 },
+ { "yesterday", tMINUTE_UNIT, -1 * 24 * 60 },
+ { "today", tMINUTE_UNIT, 0 },
+ { "now", tMINUTE_UNIT, 0 },
+ { "last", tUNUMBER, -1 },
+ { "this", tUNUMBER, 0 },
+ { "next", tUNUMBER, 2 },
+ { "first", tUNUMBER, 1 },
+/* { "second", tUNUMBER, 2 }, */
+ { "third", tUNUMBER, 3 },
+ { "fourth", tUNUMBER, 4 },
+ { "fifth", tUNUMBER, 5 },
+ { "sixth", tUNUMBER, 6 },
+ { "seventh", tUNUMBER, 7 },
+ { "eighth", tUNUMBER, 8 },
+ { "ninth", tUNUMBER, 9 },
+ { "tenth", tUNUMBER, 10 },
+ { "eleventh", tUNUMBER, 11 },
+ { "twelfth", tUNUMBER, 12 },
+ { "ago", tAGO, 1 },
+ { NULL }
+};
+
+/* The timezone table. */
+/* Some of these are commented out because a time_t can't store a float. */
+static TABLE const TimezoneTable[] = {
+ { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
+ { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
+ { "utc", tZONE, HOUR( 0) },
+ { "wet", tZONE, HOUR( 0) }, /* Western European */
+ { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
+ { "wat", tZONE, HOUR( 1) }, /* West Africa */
+ { "at", tZONE, HOUR( 2) }, /* Azores */
+#if 0
+ /* For completeness. BST is also British Summer, and GST is
+ * also Guam Standard. */
+ { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
+ { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
+#endif
+#if 0
+ { "nft", tZONE, HOUR(3.5) }, /* Newfoundland */
+ { "nst", tZONE, HOUR(3.5) }, /* Newfoundland Standard */
+ { "ndt", tDAYZONE, HOUR(3.5) }, /* Newfoundland Daylight */
+#endif
+ { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
+ { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
+ { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
+ { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
+ { "cst", tZONE, HOUR( 6) }, /* Central Standard */
+ { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
+ { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
+ { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
+ { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
+ { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
+ { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
+ { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
+ { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
+ { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
+ { "cat", tZONE, HOUR(10) }, /* Central Alaska */
+ { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
+ { "nt", tZONE, HOUR(11) }, /* Nome */
+ { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
+ { "cet", tZONE, -HOUR(1) }, /* Central European */
+ { "met", tZONE, -HOUR(1) }, /* Middle European */
+ { "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
+ { "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
+ { "swt", tZONE, -HOUR(1) }, /* Swedish Winter */
+ { "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */
+ { "fwt", tZONE, -HOUR(1) }, /* French Winter */
+ { "fst", tDAYZONE, -HOUR(1) }, /* French Summer */
+ { "eet", tZONE, -HOUR(2) }, /* Eastern Europe, USSR Zone 1 */
+ { "bt", tZONE, -HOUR(3) }, /* Baghdad, USSR Zone 2 */
+#if 0
+ { "it", tZONE, -HOUR(3.5) },/* Iran */
+#endif
+ { "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */
+ { "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */
+#if 0
+ { "ist", tZONE, -HOUR(5.5) },/* Indian Standard */
+#endif
+ { "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */
+#if 0
+ /* For completeness. NST is also Newfoundland Standard, and SST is
+ * also Swedish Summer. */
+ { "nst", tZONE, -HOUR(6.5) },/* North Sumatra */
+ { "sst", tZONE, -HOUR(7) }, /* South Sumatra, USSR Zone 6 */
+#endif /* 0 */
+ { "wast", tZONE, -HOUR(7) }, /* West Australian Standard */
+ { "wadt", tDAYZONE, -HOUR(7) }, /* West Australian Daylight */
+#if 0
+ { "jt", tZONE, -HOUR(7.5) },/* Java (3pm in Cronusland!) */
+#endif
+ { "cct", tZONE, -HOUR(8) }, /* China Coast, USSR Zone 7 */
+ { "jst", tZONE, -HOUR(9) }, /* Japan Standard, USSR Zone 8 */
+#if 0
+ { "cast", tZONE, -HOUR(9.5) },/* Central Australian Standard */
+ { "cadt", tDAYZONE, -HOUR(9.5) },/* Central Australian Daylight */
+#endif
+ { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
+ { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
+ { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
+ { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
+ { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
+ { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
+ { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
+ { NULL }
+};
+
+/* Military timezone table. */
+static TABLE const MilitaryTable[] = {
+ { "a", tZONE, HOUR( 1) },
+ { "b", tZONE, HOUR( 2) },
+ { "c", tZONE, HOUR( 3) },
+ { "d", tZONE, HOUR( 4) },
+ { "e", tZONE, HOUR( 5) },
+ { "f", tZONE, HOUR( 6) },
+ { "g", tZONE, HOUR( 7) },
+ { "h", tZONE, HOUR( 8) },
+ { "i", tZONE, HOUR( 9) },
+ { "k", tZONE, HOUR( 10) },
+ { "l", tZONE, HOUR( 11) },
+ { "m", tZONE, HOUR( 12) },
+ { "n", tZONE, HOUR(- 1) },
+ { "o", tZONE, HOUR(- 2) },
+ { "p", tZONE, HOUR(- 3) },
+ { "q", tZONE, HOUR(- 4) },
+ { "r", tZONE, HOUR(- 5) },
+ { "s", tZONE, HOUR(- 6) },
+ { "t", tZONE, HOUR(- 7) },
+ { "u", tZONE, HOUR(- 8) },
+ { "v", tZONE, HOUR(- 9) },
+ { "w", tZONE, HOUR(-10) },
+ { "x", tZONE, HOUR(-11) },
+ { "y", tZONE, HOUR(-12) },
+ { "z", tZONE, HOUR( 0) },
+ { NULL }
+};
+
+
+
+
+/* ARGSUSED */
+void
+yyerror(const char *s)
+{
+ return;
+}
+
+
+static time_t
+ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian)
+{
+ if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
+ return -1;
+ switch (Meridian) {
+ case MER24:
+ if (Hours < 0 || Hours > 23)
+ return -1;
+ return (Hours * 60L + Minutes) * 60L + Seconds;
+ case MERam:
+ if (Hours < 1 || Hours > 12)
+ return -1;
+ if (Hours == 12)
+ Hours = 0;
+ return (Hours * 60L + Minutes) * 60L + Seconds;
+ case MERpm:
+ if (Hours < 1 || Hours > 12)
+ return -1;
+ if (Hours == 12)
+ Hours = 0;
+ return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
+ default:
+ abort ();
+ }
+ /* NOTREACHED */
+}
+
+
+/* Year is either
+ * A negative number, which means to use its absolute value (why?)
+ * A number from 0 to 99, which means a year from 1900 to 1999, or
+ * The actual year (>=100). */
+static time_t
+Convert(time_t Month, time_t Day, time_t Year, time_t Hours, time_t Minutes,
+ time_t Seconds, MERIDIAN Meridian, DSTMODE DSTmode)
+{
+ static int DaysInMonth[12] = {
+ 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ struct tm tm;
+ time_t tod;
+ time_t Julian;
+ int i;
+
+ if (Year < 0)
+ Year = -Year;
+ if (Year < 69)
+ Year += 2000;
+ else if (Year < 100) {
+ Year += 1900;
+ if (Year < EPOCH)
+ Year += 100;
+ }
+ DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
+ ? 29 : 28;
+ /* 32-bit time_t cannot represent years past 2038 */
+ if (Year < EPOCH || (sizeof(time_t) == sizeof(int) && Year > 2038)
+ || Month < 1 || Month > 12
+ /* Lint fluff: "conversion from long may lose accuracy" */
+ || Day < 1 || Day > DaysInMonth[--Month])
+ return -1;
+
+ for (Julian = Day - 1, i = 0; i < Month; i++)
+ Julian += DaysInMonth[i];
+ for (i = EPOCH; i < Year; i++)
+ Julian += 365 + (i % 4 == 0);
+ Julian *= SECSPERDAY;
+ Julian += yyTimezone * 60L;
+ if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
+ return -1;
+ Julian += tod;
+ if (DSTmode == DSTon
+ || (DSTmode == DSTmaybe && localtime_r(&Julian, &tm) && tm.tm_isdst))
+ Julian -= 60 * 60;
+ return Julian;
+}
+
+
+static time_t
+DSTcorrect(time_t Start, time_t Future)
+{
+ struct tm start_tm;
+ struct tm future_tm;
+ time_t StartDay;
+ time_t FutureDay;
+
+ if (!localtime_r(&Start, &start_tm) || !localtime_r(&Future, &future_tm))
+ return -1;
+
+ StartDay = (start_tm.tm_hour + 1) % 24;
+ FutureDay = (future_tm.tm_hour + 1) % 24;
+ return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
+}
+
+
+static time_t
+RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber)
+{
+ struct tm tm;
+ time_t now;
+
+ now = Start;
+ if (!localtime_r(&now, &tm))
+ return -1;
+ now += SECSPERDAY * ((DayNumber - tm.tm_wday + 7) % 7);
+ now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
+ return DSTcorrect(Start, now);
+}
+
+
+static time_t
+RelativeMonth(time_t Start, time_t RelMonth)
+{
+ struct tm tm;
+ time_t Month;
+ time_t Year;
+
+ if (RelMonth == 0)
+ return 0;
+ if (!localtime_r(&Start, &tm))
+ return -1;
+ Month = 12 * (tm.tm_year + 1900) + tm.tm_mon + RelMonth;
+ Year = Month / 12;
+ Month = Month % 12 + 1;
+ return DSTcorrect(Start,
+ Convert(Month, (time_t)tm.tm_mday, Year,
+ (time_t)tm.tm_hour, (time_t)tm.tm_min, (time_t)tm.tm_sec,
+ MER24, DSTmaybe));
+}
+
+
+static int
+LookupWord(char *buff)
+{
+ char *p;
+ char *q;
+ const TABLE *tp;
+ int i;
+ int abbrev;
+ int bufflen;
+
+ /* Make it lowercase. */
+ for (p = buff; *p; p++) {
+ if (isupper((unsigned char)*p))
+ *p = (char)tolower((unsigned char)*p);
+ }
+ if ((bufflen = (int)(p - buff)) == 0)
+ return '\0';
+
+ if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
+ yylval.Meridian = MERam;
+ return tMERIDIAN;
+ }
+ if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
+ yylval.Meridian = MERpm;
+ return tMERIDIAN;
+ }
+
+ /* See if we have an abbreviation for a month. */
+ if (bufflen == 3)
+ abbrev = 1;
+ else if (bufflen == 4 && buff[3] == '.') {
+ abbrev = 1;
+ buff[bufflen = 3] = '\0';
+ }
+ else
+ abbrev = 0;
+
+ for (tp = MonthDayTable; tp->name; tp++) {
+ if (abbrev) {
+ if (strncmp(buff, tp->name, 3) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+ else if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+
+ for (tp = TimezoneTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ if (strcmp(buff, "dst") == 0)
+ return tDST;
+
+ for (tp = UnitsTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ /* Strip off any plural and try the units table again. */
+ i = bufflen - 1;
+ if (buff[i] == 's') {
+ buff[i] = '\0';
+ for (tp = UnitsTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ buff[i] = 's'; /* Put back for "this" in OtherTable. */
+ }
+
+ for (tp = OtherTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ /* Military timezones. */
+ if (buff[1] == '\0' && isalpha((unsigned char)*buff)) {
+ for (tp = MilitaryTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+
+ /* Drop out any periods and try the timezone table again. */
+ for (i = 0, p = q = buff; *q; q++)
+ if (*q != '.')
+ *p++ = *q;
+ else
+ i++;
+ *p = '\0';
+ if (i)
+ for (tp = TimezoneTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ return tID;
+}
+
+
+static int
+yylex(void)
+{
+ char c;
+ char *p;
+ char buff[20];
+ int Count;
+ int sign;
+
+ for ( ; ; ) {
+ while (isspace((unsigned char)*yyInput))
+ yyInput++;
+
+ if (isdigit((unsigned char)(c = *yyInput)) || c == '-' || c == '+') {
+ if (c == '-' || c == '+') {
+ sign = c == '-' ? -1 : 1;
+ if (!isdigit((unsigned char)*++yyInput))
+ /* skip the '-' sign */
+ continue;
+ }
+ else
+ sign = 0;
+ for (yylval.Number = 0; isdigit((unsigned char)(c = *yyInput++)); )
+ yylval.Number = 10 * yylval.Number + c - '0';
+ yyInput--;
+ if (sign < 0)
+ yylval.Number = -yylval.Number;
+ return sign ? tSNUMBER : tUNUMBER;
+ }
+ if (isalpha((unsigned char)c)) {
+ for (p = buff; isalpha((unsigned char)(c = *yyInput++)) || c == '.'; )
+ if (p < &buff[sizeof buff - 1])
+ *p++ = c;
+ *p = '\0';
+ yyInput--;
+ return LookupWord(buff);
+ }
+ if (c != '(')
+ return *yyInput++;
+ Count = 0;
+ do {
+ c = *yyInput++;
+ if (c == '\0')
+ return c;
+ if (c == '(')
+ Count++;
+ else if (c == ')')
+ Count--;
+ } while (Count > 0);
+ }
+}
+
+#define TM_YEAR_ORIGIN 1900
+
+/* Yield A - B, measured in seconds. */
+static long
+difftm(struct tm *a, struct tm *b)
+{
+ int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
+ int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
+ long days = (
+ /* difference in day of year */
+ a->tm_yday - b->tm_yday
+ /* + intervening leap days */
+ + ((ay >> 2) - (by >> 2))
+ - (ay/100 - by/100)
+ + ((ay/100 >> 2) - (by/100 >> 2))
+ /* + difference in years * 365 */
+ + (long)(ay-by) * 365
+ );
+ return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
+ + (a->tm_min - b->tm_min))
+ + (a->tm_sec - b->tm_sec));
+}
+
+time_t get_date(char *p);
+
+time_t
+get_date(char *p)
+{
+ struct tm tm, gmt;
+ time_t Start;
+ time_t tod;
+ time_t now;
+ time_t tz;
+
+ yyInput = p;
+ (void)time (&now);
+
+ if (gmtime_r (&now, &gmt) == NULL)
+ return -1;
+
+ if (localtime_r (&now, &tm) == NULL)
+ return -1;
+
+ tz = difftm (&gmt, &tm) / 60;
+ if (tm.tm_isdst)
+ tz += 60;
+
+ yyYear = tm.tm_year + 1900;
+ yyMonth = tm.tm_mon + 1;
+ yyDay = tm.tm_mday;
+ yyTimezone = tz;
+ yyDSTmode = DSTmaybe;
+ yyHour = 0;
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyMeridian = MER24;
+ yyRelSeconds = 0;
+ yyRelMonth = 0;
+ yyHaveDate = 0;
+ yyHaveDay = 0;
+ yyHaveRel = 0;
+ yyHaveTime = 0;
+ yyHaveZone = 0;
+
+ if (yyparse()
+ || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
+ return -1;
+
+ if (yyHaveDate || yyHaveTime || yyHaveDay) {
+ Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
+ yyMeridian, yyDSTmode);
+ if (Start < 0)
+ return -1;
+ }
+ else {
+ Start = now;
+ if (!yyHaveRel)
+ Start -= ((tm.tm_hour * 60L + tm.tm_min) * 60L) + tm.tm_sec;
+ }
+
+ Start += yyRelSeconds;
+ Start += RelativeMonth(Start, yyRelMonth);
+
+ if (yyHaveDay && !yyHaveDate) {
+ tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
+ Start += tod;
+ }
+
+ /* Have to do *something* with a legitimate -1 so it's distinguishable
+ * from the error return value. (Alternately could set errno on error.) */
+ return Start == -1 ? 0 : Start;
+}
+
+
+#ifdef TEST
+
+/* ARGSUSED */
+int
+main(int argc, char *argv[])
+{
+ char buff[128];
+ time_t d;
+
+ (void)fputs("Enter date, or blank line to exit.\n\t> ", stdout);
+ (void)fflush(stdout);
+ while (fgets(buff, sizeof(buff), stdin) && buff[0]) {
+ d = get_date(buff);
+ if (d == -1)
+ (void)fputs("Bad format - couldn't convert.\n\t> ", stdout);
+ else
+ (void)printf("%s\t> ", ctime(&d));
+ (void)fflush(stdout);
+ }
+ return 0;
+}
+#endif /* TEST */
diff --git a/plugins/sudoers/getspwuid.c b/plugins/sudoers/getspwuid.c
new file mode 100644
index 0000000..dd5092d
--- /dev/null
+++ b/plugins/sudoers/getspwuid.c
@@ -0,0 +1,139 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2010-2012, 2014-2015
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+#ifdef HAVE_GETSPNAM
+# include <shadow.h>
+#endif /* HAVE_GETSPNAM */
+#ifdef HAVE_GETPRPWNAM
+# ifdef __hpux
+# undef MAXINT
+# include <hpsecurity.h>
+# else
+# include <sys/security.h>
+# endif /* __hpux */
+# include <prot.h>
+#endif /* HAVE_GETPRPWNAM */
+
+#include <sudoers.h>
+
+/*
+ * Exported for auth/secureware.c
+ */
+#if defined(HAVE_GETPRPWNAM) && defined(__alpha)
+int crypt_type = INT_MAX;
+#endif /* HAVE_GETPRPWNAM && __alpha */
+
+/*
+ * Return a copy of the encrypted password for the user described by pw.
+ * If shadow passwords are in use, look in the shadow file.
+ */
+char *
+sudo_getepw(const struct passwd *pw)
+{
+ char *epw = NULL;
+ debug_decl(sudo_getepw, SUDOERS_DEBUG_AUTH);
+
+ /* If there is a function to check for shadow enabled, use it... */
+#ifdef HAVE_ISCOMSEC
+ if (!iscomsec())
+ goto done;
+#endif /* HAVE_ISCOMSEC */
+
+#ifdef HAVE_GETPWNAM_SHADOW
+ {
+ struct passwd *spw;
+
+ /* On OpenBSD we need to closed the non-shadow passwd db first. */
+ endpwent();
+ if ((spw = getpwnam_shadow(pw->pw_name)) != NULL)
+ epw = spw->pw_passwd;
+ setpassent(1);
+ }
+#endif /* HAVE_GETPWNAM_SHADOW */
+#ifdef HAVE_GETPRPWNAM
+ {
+ struct pr_passwd *spw;
+
+ if ((spw = getprpwnam(pw->pw_name)) && spw->ufld.fd_encrypt) {
+# ifdef __alpha
+ crypt_type = spw->ufld.fd_oldcrypt;
+# endif /* __alpha */
+ epw = spw->ufld.fd_encrypt;
+ }
+ }
+#endif /* HAVE_GETPRPWNAM */
+#ifdef HAVE_GETSPNAM
+ {
+ struct spwd *spw;
+
+ if ((spw = getspnam(pw->pw_name)) && spw->sp_pwdp)
+ epw = spw->sp_pwdp;
+ }
+#endif /* HAVE_GETSPNAM */
+
+#if defined(HAVE_ISCOMSEC)
+done:
+#endif
+ /* If no shadow password, fall back on regular password. */
+ debug_return_str(strdup(epw ? epw : pw->pw_passwd));
+}
+
+void
+sudo_setspent(void)
+{
+ debug_decl(sudo_setspent, SUDOERS_DEBUG_AUTH);
+
+#ifdef HAVE_GETPRPWNAM
+ setprpwent();
+#endif
+#ifdef HAVE_GETSPNAM
+ setspent();
+#endif
+ debug_return;
+}
+
+void
+sudo_endspent(void)
+{
+ debug_decl(sudo_endspent, SUDOERS_DEBUG_AUTH);
+
+#ifdef HAVE_GETPRPWNAM
+ endprpwent();
+#endif
+#ifdef HAVE_GETSPNAM
+ endspent();
+#endif
+ debug_return;
+}
diff --git a/plugins/sudoers/goodpath.c b/plugins/sudoers/goodpath.c
new file mode 100644
index 0000000..b2d412d
--- /dev/null
+++ b/plugins/sudoers/goodpath.c
@@ -0,0 +1,61 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2010-2012, 2014-2016
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sudoers.h>
+
+/*
+ * Verify that path is a normal file and executable by root.
+ */
+bool
+sudo_goodpath(const char *path, struct stat *sbp)
+{
+ bool ret = false;
+ struct stat sb;
+ debug_decl(sudo_goodpath, SUDOERS_DEBUG_UTIL);
+
+ if (path != NULL) {
+ if (sbp == NULL)
+ sbp = &sb;
+
+ if (stat(path, sbp) == 0) {
+ /* Make sure path describes an executable regular file. */
+ if (S_ISREG(sbp->st_mode) && ISSET(sbp->st_mode, S_IXUSR|S_IXGRP|S_IXOTH))
+ ret = true;
+ else
+ errno = EACCES;
+ }
+ }
+ debug_return_bool(ret);
+}
diff --git a/plugins/sudoers/gram.c b/plugins/sudoers/gram.c
new file mode 100644
index 0000000..1106467
--- /dev/null
+++ b/plugins/sudoers/gram.c
@@ -0,0 +1,4308 @@
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+/* A Bison parser, made by GNU Bison 3.8.2. */
+
+/* Bison implementation for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
+ Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
+ especially those whose name start with YY_ or yy_. They are
+ private implementation details that can be changed or removed. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output, and Bison version. */
+#define YYBISON 30802
+
+/* Bison version string. */
+#define YYBISON_VERSION "3.8.2"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+
+/* Substitute the variable and function names. */
+#define yyparse sudoersparse
+#define yylex sudoerslex
+#define yyerror sudoerserror
+#define yydebug sudoersdebug
+#define yynerrs sudoersnerrs
+#define yylval sudoerslval
+#define yychar sudoerschar
+
+/* First part of user prologue. */
+#line 1 "gram.y"
+
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2007-2013, 2014-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sudoers.h>
+#include <sudo_digest.h>
+#include <toke.h>
+
+#ifdef YYBISON
+# define YYERROR_VERBOSE
+#endif
+
+/* If we last saw a newline the entry is on the preceding line. */
+#define this_lineno (sudoerschar == '\n' ? sudolineno - 1 : sudolineno)
+
+// PVS Studio suppression
+// -V::560, 592, 1037, 1042
+
+/*
+ * Globals
+ */
+bool parse_error = false;
+
+static struct sudoers_parser_config parser_conf =
+ SUDOERS_PARSER_CONFIG_INITIALIZER;
+
+/* Optional logging function for parse errors. */
+sudoers_logger_t sudoers_error_hook;
+
+static int alias_line, alias_column;
+
+#ifdef NO_LEAKS
+static struct parser_leak_list parser_leak_list =
+ SLIST_HEAD_INITIALIZER(parser_leak_list);
+#endif
+
+struct sudoers_parse_tree parsed_policy = {
+ { NULL, NULL }, /* entries */
+ TAILQ_HEAD_INITIALIZER(parsed_policy.userspecs),
+ TAILQ_HEAD_INITIALIZER(parsed_policy.defaults),
+ NULL, /* aliases */
+ NULL, /* lhost */
+ NULL, /* shost */
+ NULL, /* nss */
+ NULL /* ctx */
+};
+
+/*
+ * Local prototypes
+ */
+static void init_options(struct command_options *opts);
+static bool add_defaults(short, struct member *, struct defaults *);
+static bool add_userspec(struct member *, struct privilege *);
+static struct defaults *new_default(char *, char *, short);
+static struct member *new_member(char *, short);
+static struct sudo_command *new_command(char *, char *);
+static struct command_digest *new_digest(unsigned int, char *);
+static void alias_error(const char *name, int errnum);
+
+#line 167 "gram.c"
+
+# ifndef YY_CAST
+# ifdef __cplusplus
+# define YY_CAST(Type, Val) static_cast<Type> (Val)
+# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast<Type> (Val)
+# else
+# define YY_CAST(Type, Val) ((Type) (Val))
+# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val))
+# endif
+# endif
+# ifndef YY_NULLPTR
+# if defined __cplusplus
+# if 201103L <= __cplusplus
+# define YY_NULLPTR nullptr
+# else
+# define YY_NULLPTR 0
+# endif
+# else
+# define YY_NULLPTR ((void*)0)
+# endif
+# endif
+
+/* Use api.header.include to #include this header
+ instead of duplicating it here. */
+#ifndef YY_SUDOERS_Y_TAB_H_INCLUDED
+# define YY_SUDOERS_Y_TAB_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int sudoersdebug;
+#endif
+
+/* Token kinds. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ YYEMPTY = -2,
+ YYEOF = 0, /* "end of file" */
+ YYerror = 256, /* error */
+ YYUNDEF = 257, /* "invalid token" */
+ COMMAND = 258, /* COMMAND */
+ ALIAS = 259, /* ALIAS */
+ DEFVAR = 260, /* DEFVAR */
+ NTWKADDR = 261, /* NTWKADDR */
+ NETGROUP = 262, /* NETGROUP */
+ USERGROUP = 263, /* USERGROUP */
+ WORD = 264, /* WORD */
+ DIGEST = 265, /* DIGEST */
+ INCLUDE = 266, /* INCLUDE */
+ INCLUDEDIR = 267, /* INCLUDEDIR */
+ DEFAULTS = 268, /* DEFAULTS */
+ DEFAULTS_HOST = 269, /* DEFAULTS_HOST */
+ DEFAULTS_USER = 270, /* DEFAULTS_USER */
+ DEFAULTS_RUNAS = 271, /* DEFAULTS_RUNAS */
+ DEFAULTS_CMND = 272, /* DEFAULTS_CMND */
+ NOPASSWD = 273, /* NOPASSWD */
+ PASSWD = 274, /* PASSWD */
+ NOEXEC = 275, /* NOEXEC */
+ EXEC = 276, /* EXEC */
+ SETENV = 277, /* SETENV */
+ NOSETENV = 278, /* NOSETENV */
+ LOG_INPUT = 279, /* LOG_INPUT */
+ NOLOG_INPUT = 280, /* NOLOG_INPUT */
+ LOG_OUTPUT = 281, /* LOG_OUTPUT */
+ NOLOG_OUTPUT = 282, /* NOLOG_OUTPUT */
+ MAIL = 283, /* MAIL */
+ NOMAIL = 284, /* NOMAIL */
+ FOLLOWLNK = 285, /* FOLLOWLNK */
+ NOFOLLOWLNK = 286, /* NOFOLLOWLNK */
+ INTERCEPT = 287, /* INTERCEPT */
+ NOINTERCEPT = 288, /* NOINTERCEPT */
+ ALL = 289, /* ALL */
+ HOSTALIAS = 290, /* HOSTALIAS */
+ CMNDALIAS = 291, /* CMNDALIAS */
+ USERALIAS = 292, /* USERALIAS */
+ RUNASALIAS = 293, /* RUNASALIAS */
+ ERROR = 294, /* ERROR */
+ NOMATCH = 295, /* NOMATCH */
+ CHROOT = 296, /* CHROOT */
+ CWD = 297, /* CWD */
+ TYPE = 298, /* TYPE */
+ ROLE = 299, /* ROLE */
+ APPARMOR_PROFILE = 300, /* APPARMOR_PROFILE */
+ PRIVS = 301, /* PRIVS */
+ LIMITPRIVS = 302, /* LIMITPRIVS */
+ CMND_TIMEOUT = 303, /* CMND_TIMEOUT */
+ NOTBEFORE = 304, /* NOTBEFORE */
+ NOTAFTER = 305, /* NOTAFTER */
+ MYSELF = 306, /* MYSELF */
+ SHA224_TOK = 307, /* SHA224_TOK */
+ SHA256_TOK = 308, /* SHA256_TOK */
+ SHA384_TOK = 309, /* SHA384_TOK */
+ SHA512_TOK = 310 /* SHA512_TOK */
+ };
+ typedef enum yytokentype yytoken_kind_t;
+#endif
+/* Token kinds. */
+#define YYEMPTY -2
+#define YYEOF 0
+#define YYerror 256
+#define YYUNDEF 257
+#define COMMAND 258
+#define ALIAS 259
+#define DEFVAR 260
+#define NTWKADDR 261
+#define NETGROUP 262
+#define USERGROUP 263
+#define WORD 264
+#define DIGEST 265
+#define INCLUDE 266
+#define INCLUDEDIR 267
+#define DEFAULTS 268
+#define DEFAULTS_HOST 269
+#define DEFAULTS_USER 270
+#define DEFAULTS_RUNAS 271
+#define DEFAULTS_CMND 272
+#define NOPASSWD 273
+#define PASSWD 274
+#define NOEXEC 275
+#define EXEC 276
+#define SETENV 277
+#define NOSETENV 278
+#define LOG_INPUT 279
+#define NOLOG_INPUT 280
+#define LOG_OUTPUT 281
+#define NOLOG_OUTPUT 282
+#define MAIL 283
+#define NOMAIL 284
+#define FOLLOWLNK 285
+#define NOFOLLOWLNK 286
+#define INTERCEPT 287
+#define NOINTERCEPT 288
+#define ALL 289
+#define HOSTALIAS 290
+#define CMNDALIAS 291
+#define USERALIAS 292
+#define RUNASALIAS 293
+#define ERROR 294
+#define NOMATCH 295
+#define CHROOT 296
+#define CWD 297
+#define TYPE 298
+#define ROLE 299
+#define APPARMOR_PROFILE 300
+#define PRIVS 301
+#define LIMITPRIVS 302
+#define CMND_TIMEOUT 303
+#define NOTBEFORE 304
+#define NOTAFTER 305
+#define MYSELF 306
+#define SHA224_TOK 307
+#define SHA256_TOK 308
+#define SHA384_TOK 309
+#define SHA512_TOK 310
+
+/* Value type. */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+union YYSTYPE
+{
+#line 90 "gram.y"
+
+ struct cmndspec *cmndspec;
+ struct defaults *defaults;
+ struct member *member;
+ struct runascontainer *runas;
+ struct privilege *privilege;
+ struct command_digest *digest;
+ struct sudo_command command;
+ struct command_options options;
+ struct cmndtag tag;
+ char *string;
+ const char *cstring;
+ int tok;
+
+#line 345 "gram.c"
+
+};
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+extern YYSTYPE sudoerslval;
+
+
+int sudoersparse (void);
+
+
+#endif /* !YY_SUDOERS_Y_TAB_H_INCLUDED */
+/* Symbol kind. */
+enum yysymbol_kind_t
+{
+ YYSYMBOL_YYEMPTY = -2,
+ YYSYMBOL_YYEOF = 0, /* "end of file" */
+ YYSYMBOL_YYerror = 1, /* error */
+ YYSYMBOL_YYUNDEF = 2, /* "invalid token" */
+ YYSYMBOL_COMMAND = 3, /* COMMAND */
+ YYSYMBOL_ALIAS = 4, /* ALIAS */
+ YYSYMBOL_DEFVAR = 5, /* DEFVAR */
+ YYSYMBOL_NTWKADDR = 6, /* NTWKADDR */
+ YYSYMBOL_NETGROUP = 7, /* NETGROUP */
+ YYSYMBOL_USERGROUP = 8, /* USERGROUP */
+ YYSYMBOL_WORD = 9, /* WORD */
+ YYSYMBOL_DIGEST = 10, /* DIGEST */
+ YYSYMBOL_INCLUDE = 11, /* INCLUDE */
+ YYSYMBOL_INCLUDEDIR = 12, /* INCLUDEDIR */
+ YYSYMBOL_DEFAULTS = 13, /* DEFAULTS */
+ YYSYMBOL_DEFAULTS_HOST = 14, /* DEFAULTS_HOST */
+ YYSYMBOL_DEFAULTS_USER = 15, /* DEFAULTS_USER */
+ YYSYMBOL_DEFAULTS_RUNAS = 16, /* DEFAULTS_RUNAS */
+ YYSYMBOL_DEFAULTS_CMND = 17, /* DEFAULTS_CMND */
+ YYSYMBOL_NOPASSWD = 18, /* NOPASSWD */
+ YYSYMBOL_PASSWD = 19, /* PASSWD */
+ YYSYMBOL_NOEXEC = 20, /* NOEXEC */
+ YYSYMBOL_EXEC = 21, /* EXEC */
+ YYSYMBOL_SETENV = 22, /* SETENV */
+ YYSYMBOL_NOSETENV = 23, /* NOSETENV */
+ YYSYMBOL_LOG_INPUT = 24, /* LOG_INPUT */
+ YYSYMBOL_NOLOG_INPUT = 25, /* NOLOG_INPUT */
+ YYSYMBOL_LOG_OUTPUT = 26, /* LOG_OUTPUT */
+ YYSYMBOL_NOLOG_OUTPUT = 27, /* NOLOG_OUTPUT */
+ YYSYMBOL_MAIL = 28, /* MAIL */
+ YYSYMBOL_NOMAIL = 29, /* NOMAIL */
+ YYSYMBOL_FOLLOWLNK = 30, /* FOLLOWLNK */
+ YYSYMBOL_NOFOLLOWLNK = 31, /* NOFOLLOWLNK */
+ YYSYMBOL_INTERCEPT = 32, /* INTERCEPT */
+ YYSYMBOL_NOINTERCEPT = 33, /* NOINTERCEPT */
+ YYSYMBOL_ALL = 34, /* ALL */
+ YYSYMBOL_HOSTALIAS = 35, /* HOSTALIAS */
+ YYSYMBOL_CMNDALIAS = 36, /* CMNDALIAS */
+ YYSYMBOL_USERALIAS = 37, /* USERALIAS */
+ YYSYMBOL_RUNASALIAS = 38, /* RUNASALIAS */
+ YYSYMBOL_39_ = 39, /* ':' */
+ YYSYMBOL_40_ = 40, /* '=' */
+ YYSYMBOL_41_ = 41, /* ',' */
+ YYSYMBOL_42_ = 42, /* '!' */
+ YYSYMBOL_43_ = 43, /* '+' */
+ YYSYMBOL_44_ = 44, /* '-' */
+ YYSYMBOL_45_ = 45, /* '(' */
+ YYSYMBOL_46_ = 46, /* ')' */
+ YYSYMBOL_47_n_ = 47, /* '\n' */
+ YYSYMBOL_ERROR = 48, /* ERROR */
+ YYSYMBOL_NOMATCH = 49, /* NOMATCH */
+ YYSYMBOL_CHROOT = 50, /* CHROOT */
+ YYSYMBOL_CWD = 51, /* CWD */
+ YYSYMBOL_TYPE = 52, /* TYPE */
+ YYSYMBOL_ROLE = 53, /* ROLE */
+ YYSYMBOL_APPARMOR_PROFILE = 54, /* APPARMOR_PROFILE */
+ YYSYMBOL_PRIVS = 55, /* PRIVS */
+ YYSYMBOL_LIMITPRIVS = 56, /* LIMITPRIVS */
+ YYSYMBOL_CMND_TIMEOUT = 57, /* CMND_TIMEOUT */
+ YYSYMBOL_NOTBEFORE = 58, /* NOTBEFORE */
+ YYSYMBOL_NOTAFTER = 59, /* NOTAFTER */
+ YYSYMBOL_MYSELF = 60, /* MYSELF */
+ YYSYMBOL_SHA224_TOK = 61, /* SHA224_TOK */
+ YYSYMBOL_SHA256_TOK = 62, /* SHA256_TOK */
+ YYSYMBOL_SHA384_TOK = 63, /* SHA384_TOK */
+ YYSYMBOL_SHA512_TOK = 64, /* SHA512_TOK */
+ YYSYMBOL_YYACCEPT = 65, /* $accept */
+ YYSYMBOL_file = 66, /* file */
+ YYSYMBOL_line = 67, /* line */
+ YYSYMBOL_entry = 68, /* entry */
+ YYSYMBOL_include = 69, /* include */
+ YYSYMBOL_includedir = 70, /* includedir */
+ YYSYMBOL_defaults_list = 71, /* defaults_list */
+ YYSYMBOL_defaults_entry = 72, /* defaults_entry */
+ YYSYMBOL_privileges = 73, /* privileges */
+ YYSYMBOL_privilege = 74, /* privilege */
+ YYSYMBOL_ophost = 75, /* ophost */
+ YYSYMBOL_host = 76, /* host */
+ YYSYMBOL_cmndspeclist = 77, /* cmndspeclist */
+ YYSYMBOL_cmndspec = 78, /* cmndspec */
+ YYSYMBOL_digestspec = 79, /* digestspec */
+ YYSYMBOL_digestlist = 80, /* digestlist */
+ YYSYMBOL_digcmnd = 81, /* digcmnd */
+ YYSYMBOL_opcmnd = 82, /* opcmnd */
+ YYSYMBOL_chdirspec = 83, /* chdirspec */
+ YYSYMBOL_chrootspec = 84, /* chrootspec */
+ YYSYMBOL_timeoutspec = 85, /* timeoutspec */
+ YYSYMBOL_notbeforespec = 86, /* notbeforespec */
+ YYSYMBOL_notafterspec = 87, /* notafterspec */
+ YYSYMBOL_rolespec = 88, /* rolespec */
+ YYSYMBOL_typespec = 89, /* typespec */
+ YYSYMBOL_apparmor_profilespec = 90, /* apparmor_profilespec */
+ YYSYMBOL_privsspec = 91, /* privsspec */
+ YYSYMBOL_limitprivsspec = 92, /* limitprivsspec */
+ YYSYMBOL_runasspec = 93, /* runasspec */
+ YYSYMBOL_runaslist = 94, /* runaslist */
+ YYSYMBOL_reserved_word = 95, /* reserved_word */
+ YYSYMBOL_reserved_alias = 96, /* reserved_alias */
+ YYSYMBOL_options = 97, /* options */
+ YYSYMBOL_cmndtag = 98, /* cmndtag */
+ YYSYMBOL_cmnd = 99, /* cmnd */
+ YYSYMBOL_hostaliases = 100, /* hostaliases */
+ YYSYMBOL_hostalias = 101, /* hostalias */
+ YYSYMBOL_102_1 = 102, /* $@1 */
+ YYSYMBOL_hostlist = 103, /* hostlist */
+ YYSYMBOL_cmndaliases = 104, /* cmndaliases */
+ YYSYMBOL_cmndalias = 105, /* cmndalias */
+ YYSYMBOL_106_2 = 106, /* $@2 */
+ YYSYMBOL_cmndlist = 107, /* cmndlist */
+ YYSYMBOL_runasaliases = 108, /* runasaliases */
+ YYSYMBOL_runasalias = 109, /* runasalias */
+ YYSYMBOL_110_3 = 110, /* $@3 */
+ YYSYMBOL_useraliases = 111, /* useraliases */
+ YYSYMBOL_useralias = 112, /* useralias */
+ YYSYMBOL_113_4 = 113, /* $@4 */
+ YYSYMBOL_userlist = 114, /* userlist */
+ YYSYMBOL_opuser = 115, /* opuser */
+ YYSYMBOL_user = 116, /* user */
+ YYSYMBOL_grouplist = 117, /* grouplist */
+ YYSYMBOL_opgroup = 118, /* opgroup */
+ YYSYMBOL_group = 119 /* group */
+};
+typedef enum yysymbol_kind_t yysymbol_kind_t;
+
+
+
+
+#ifdef short
+# undef short
+#endif
+
+/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure
+ <limits.h> and (if available) <stdint.h> are included
+ so that the code can choose integer types of a good width. */
+
+#ifndef __PTRDIFF_MAX__
+# include <limits.h> /* INFRINGES ON USER NAME SPACE */
+# if defined HAVE_STDINT_H
+# include <stdint.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_STDINT_H
+# endif
+#endif
+
+/* Narrow types that promote to a signed type and that can represent a
+ signed or unsigned integer of at least N bits. In tables they can
+ save space and decrease cache pressure. Promoting to a signed type
+ helps avoid bugs in integer arithmetic. */
+
+#ifdef __INT_LEAST8_MAX__
+typedef __INT_LEAST8_TYPE__ yytype_int8;
+#elif defined YY_STDINT_H
+typedef int_least8_t yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef __INT_LEAST16_MAX__
+typedef __INT_LEAST16_TYPE__ yytype_int16;
+#elif defined YY_STDINT_H
+typedef int_least16_t yytype_int16;
+#else
+typedef short yytype_int16;
+#endif
+
+/* Work around bug in HP-UX 11.23, which defines these macros
+ incorrectly for preprocessor constants. This workaround can likely
+ be removed in 2023, as HPE has promised support for HP-UX 11.23
+ (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of
+ <https://h20195.www2.hpe.com/V2/getpdf.aspx/4AA4-7673ENW.pdf>. */
+#ifdef __hpux
+# undef UINT_LEAST8_MAX
+# undef UINT_LEAST16_MAX
+# define UINT_LEAST8_MAX 255
+# define UINT_LEAST16_MAX 65535
+#endif
+
+#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__
+typedef __UINT_LEAST8_TYPE__ yytype_uint8;
+#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \
+ && UINT_LEAST8_MAX <= INT_MAX)
+typedef uint_least8_t yytype_uint8;
+#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX
+typedef unsigned char yytype_uint8;
+#else
+typedef short yytype_uint8;
+#endif
+
+#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__
+typedef __UINT_LEAST16_TYPE__ yytype_uint16;
+#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \
+ && UINT_LEAST16_MAX <= INT_MAX)
+typedef uint_least16_t yytype_uint16;
+#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX
+typedef unsigned short yytype_uint16;
+#else
+typedef int yytype_uint16;
+#endif
+
+#ifndef YYPTRDIFF_T
+# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__
+# define YYPTRDIFF_T __PTRDIFF_TYPE__
+# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__
+# elif defined PTRDIFF_MAX
+# ifndef ptrdiff_t
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# endif
+# define YYPTRDIFF_T ptrdiff_t
+# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX
+# else
+# define YYPTRDIFF_T long
+# define YYPTRDIFF_MAXIMUM LONG_MAX
+# endif
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM \
+ YY_CAST (YYPTRDIFF_T, \
+ (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \
+ ? YYPTRDIFF_MAXIMUM \
+ : YY_CAST (YYSIZE_T, -1)))
+
+#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X))
+
+
+/* Stored state numbers (used for stacks). */
+typedef yytype_uint8 yy_state_t;
+
+/* State numbers in computations. */
+typedef int yy_state_fast_t;
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(Msgid) Msgid
+# endif
+#endif
+
+
+#ifndef YY_ATTRIBUTE_PURE
+# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
+# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__))
+# else
+# define YY_ATTRIBUTE_PURE
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__)
+# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+# else
+# define YY_ATTRIBUTE_UNUSED
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YY_USE(E) ((void) (E))
+#else
+# define YY_USE(E) /* empty */
+#endif
+
+/* Suppress an incorrect diagnostic about yylval being uninitialized. */
+#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__
+# if __GNUC__ * 100 + __GNUC_MINOR__ < 407
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")
+# else
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \
+ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# endif
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+ _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__
+# define YY_IGNORE_USELESS_CAST_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"")
+# define YY_IGNORE_USELESS_CAST_END \
+ _Pragma ("GCC diagnostic pop")
+#endif
+#ifndef YY_IGNORE_USELESS_CAST_BEGIN
+# define YY_IGNORE_USELESS_CAST_BEGIN
+# define YY_IGNORE_USELESS_CAST_END
+#endif
+
+
+#define YY_ASSERT(E) ((void) (0 && (E)))
+
+#if !defined yyoverflow
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+ /* Use EXIT_SUCCESS as a witness for stdlib.h. */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's 'empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined EXIT_SUCCESS \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* !defined yyoverflow */
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yy_state_t yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYPTRDIFF_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / YYSIZEOF (*yyptr); \
+ } \
+ while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(Dst, Src, Count) \
+ __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src)))
+# else
+# define YYCOPY(Dst, Src, Count) \
+ do \
+ { \
+ YYPTRDIFF_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (Dst)[yyi] = (Src)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 90
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 332
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 65
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 55
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 155
+/* YYNSTATES -- Number of states. */
+#define YYNSTATES 256
+
+/* YYMAXUTOK -- Last valid token kind. */
+#define YYMAXUTOK 310
+
+
+/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, with out-of-bounds checking. */
+#define YYTRANSLATE(YYX) \
+ (0 <= (YYX) && (YYX) <= YYMAXUTOK \
+ ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \
+ : YYSYMBOL_YYUNDEF)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex. */
+static const yytype_int8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 47, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 42, 2, 2, 2, 2, 2, 2,
+ 45, 46, 2, 43, 41, 44, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 39, 2,
+ 2, 40, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64
+};
+
+#if YYDEBUG
+/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
+static const yytype_int16 yyrline[] =
+{
+ 0, 204, 204, 207, 210, 211, 214, 217, 220, 228,
+ 236, 242, 245, 248, 251, 254, 258, 262, 266, 270,
+ 276, 279, 285, 288, 294, 295, 302, 311, 320, 330,
+ 340, 352, 353, 358, 364, 381, 385, 391, 400, 408,
+ 417, 426, 437, 438, 500, 570, 579, 588, 597, 608,
+ 609, 616, 619, 633, 637, 643, 659, 675, 680, 684,
+ 689, 694, 699, 704, 708, 713, 716, 721, 738, 750,
+ 766, 784, 803, 804, 805, 806, 807, 808, 809, 810,
+ 811, 812, 813, 816, 822, 825, 830, 835, 844, 853,
+ 865, 872, 879, 886, 893, 902, 905, 908, 911, 914,
+ 917, 920, 923, 926, 929, 932, 935, 938, 941, 944,
+ 947, 950, 955, 969, 978, 999, 1022, 1023, 1026, 1026,
+ 1038, 1041, 1042, 1049, 1050, 1053, 1053, 1065, 1068, 1069,
+ 1076, 1077, 1080, 1080, 1092, 1095, 1096, 1099, 1099, 1111,
+ 1114, 1115, 1122, 1126, 1132, 1141, 1149, 1158, 1167, 1178,
+ 1179, 1186, 1190, 1196, 1205, 1213
+};
+#endif
+
+/** Accessing symbol of state STATE. */
+#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State])
+
+#if YYDEBUG || 0
+/* The user-facing name of the symbol whose (internal) number is
+ YYSYMBOL. No bounds checking. */
+static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED;
+
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "\"end of file\"", "error", "\"invalid token\"", "COMMAND", "ALIAS",
+ "DEFVAR", "NTWKADDR", "NETGROUP", "USERGROUP", "WORD", "DIGEST",
+ "INCLUDE", "INCLUDEDIR", "DEFAULTS", "DEFAULTS_HOST", "DEFAULTS_USER",
+ "DEFAULTS_RUNAS", "DEFAULTS_CMND", "NOPASSWD", "PASSWD", "NOEXEC",
+ "EXEC", "SETENV", "NOSETENV", "LOG_INPUT", "NOLOG_INPUT", "LOG_OUTPUT",
+ "NOLOG_OUTPUT", "MAIL", "NOMAIL", "FOLLOWLNK", "NOFOLLOWLNK",
+ "INTERCEPT", "NOINTERCEPT", "ALL", "HOSTALIAS", "CMNDALIAS", "USERALIAS",
+ "RUNASALIAS", "':'", "'='", "','", "'!'", "'+'", "'-'", "'('", "')'",
+ "'\\n'", "ERROR", "NOMATCH", "CHROOT", "CWD", "TYPE", "ROLE",
+ "APPARMOR_PROFILE", "PRIVS", "LIMITPRIVS", "CMND_TIMEOUT", "NOTBEFORE",
+ "NOTAFTER", "MYSELF", "SHA224_TOK", "SHA256_TOK", "SHA384_TOK",
+ "SHA512_TOK", "$accept", "file", "line", "entry", "include",
+ "includedir", "defaults_list", "defaults_entry", "privileges",
+ "privilege", "ophost", "host", "cmndspeclist", "cmndspec", "digestspec",
+ "digestlist", "digcmnd", "opcmnd", "chdirspec", "chrootspec",
+ "timeoutspec", "notbeforespec", "notafterspec", "rolespec", "typespec",
+ "apparmor_profilespec", "privsspec", "limitprivsspec", "runasspec",
+ "runaslist", "reserved_word", "reserved_alias", "options", "cmndtag",
+ "cmnd", "hostaliases", "hostalias", "$@1", "hostlist", "cmndaliases",
+ "cmndalias", "$@2", "cmndlist", "runasaliases", "runasalias", "$@3",
+ "useraliases", "useralias", "$@4", "userlist", "opuser", "user",
+ "grouplist", "opgroup", "group", YY_NULLPTR
+};
+
+static const char *
+yysymbol_name (yysymbol_kind_t yysymbol)
+{
+ return yytname[yysymbol];
+}
+#endif
+
+#define YYPACT_NINF (-116)
+
+#define yypact_value_is_default(Yyn) \
+ ((Yyn) == YYPACT_NINF)
+
+#define YYTABLE_NINF (-4)
+
+#define yytable_value_is_error(Yyn) \
+ 0
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+static const yytype_int16 yypact[] =
+{
+ 174, -29, -116, -116, -116, -116, 35, 38, 11, 239,
+ 150, 150, 8, -116, 32, 76, 88, 114, 254, -116,
+ 58, 218, -116, -116, -116, 70, -116, -116, -116, 12,
+ 13, 136, 73, 14, -116, -116, -116, -116, -116, -116,
+ 276, -116, -116, 4, 10, 10, -116, -116, -116, -116,
+ 190, 42, 81, 85, 97, -116, 64, -116, -116, -116,
+ 52, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+ -116, -116, -116, -116, 57, 2, -116, -116, 111, 9,
+ -116, -116, 112, 56, -116, -116, 123, 61, -116, -116,
+ -116, -116, 150, 62, -116, 75, 90, -116, 130, -116,
+ 188, 204, 205, -116, 11, -116, -116, 239, 55, 66,
+ 108, -116, 207, 210, 213, 228, 143, -116, 8, 155,
+ 175, 239, 32, -116, 209, 8, 76, -116, 211, 150,
+ 88, -116, 217, 150, 114, -116, -116, 194, -116, 202,
+ -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+ -116, -116, -116, -116, -116, -116, -116, 239, 225, -116,
+ 8, 227, -116, 150, 229, -116, 150, 229, -116, -116,
+ -116, 233, 230, -116, -116, 225, 227, 229, 229, 235,
+ 232, 121, 202, 240, -116, -116, -116, 255, 238, -116,
+ -116, -116, 235, -116, 234, 236, 244, 246, 247, 260,
+ 261, 262, 263, 264, -116, -116, -116, -116, -116, -116,
+ -116, -116, -116, -116, 1, -116, 235, 238, 241, 296,
+ 297, 298, 299, 300, 302, 303, 304, 305, -116, -116,
+ -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+ -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+ -116, -116, -116, -116, -116, -116
+};
+
+/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE does not specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 0, 0, 144, 146, 147, 148, 0, 0, 0, 0,
+ 0, 0, 0, 145, 0, 0, 0, 0, 0, 6,
+ 0, 0, 4, 8, 9, 0, 140, 142, 7, 0,
+ 0, 26, 0, 0, 24, 37, 40, 39, 41, 38,
+ 0, 121, 35, 0, 0, 0, 114, 113, 115, 112,
+ 0, 0, 0, 0, 0, 49, 0, 128, 51, 53,
+ 0, 118, 72, 73, 74, 79, 78, 82, 80, 81,
+ 75, 76, 77, 83, 0, 0, 116, 125, 0, 0,
+ 123, 137, 0, 0, 135, 132, 0, 0, 130, 143,
+ 1, 5, 0, 0, 31, 0, 0, 20, 0, 22,
+ 0, 0, 0, 27, 0, 15, 36, 0, 0, 0,
+ 0, 54, 0, 0, 0, 0, 0, 52, 0, 0,
+ 0, 0, 0, 12, 0, 0, 0, 13, 0, 0,
+ 0, 11, 0, 0, 0, 14, 141, 0, 10, 65,
+ 21, 23, 28, 29, 30, 25, 122, 18, 16, 17,
+ 45, 46, 47, 48, 50, 129, 19, 0, 120, 117,
+ 0, 127, 124, 0, 139, 136, 0, 134, 131, 33,
+ 32, 67, 34, 42, 84, 119, 126, 138, 133, 71,
+ 0, 68, 65, 95, 153, 155, 154, 0, 70, 149,
+ 151, 66, 0, 43, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 85, 86, 89, 87, 88, 90,
+ 91, 92, 93, 94, 0, 152, 0, 69, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 96, 97,
+ 98, 99, 102, 103, 104, 105, 106, 107, 110, 111,
+ 108, 109, 100, 101, 44, 150, 56, 55, 61, 60,
+ 62, 63, 64, 57, 58, 59
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
+{
+ -116, -116, -116, 294, -116, -116, -6, 212, -116, 180,
+ 214, 278, -116, 137, 206, -116, -115, 267, -116, -116,
+ -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
+ -116, -9, -116, -116, 270, -116, 203, -116, -7, -116,
+ 198, -116, -85, -116, 192, -116, -116, 197, -116, -10,
+ 237, 310, 138, 115, 145
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_uint8 yydefgoto[] =
+{
+ 0, 20, 21, 22, 23, 24, 33, 34, 93, 94,
+ 41, 42, 172, 173, 55, 56, 57, 58, 204, 205,
+ 206, 207, 208, 209, 210, 211, 212, 213, 174, 180,
+ 73, 74, 183, 214, 59, 75, 76, 120, 95, 79,
+ 80, 124, 60, 87, 88, 132, 83, 84, 128, 25,
+ 26, 27, 188, 189, 190
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule whose
+ number is the opposite. If YYTABLE_NINF, syntax error. */
+static const yytype_int16 yytable[] =
+{
+ 44, 45, 43, 155, 46, 47, 78, 82, 86, 31,
+ 48, 46, 47, 96, 98, 31, 31, 48, 28, 228,
+ 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
+ 239, 240, 241, 242, 243, 49, 61, 108, 109, 110,
+ 161, 122, 49, 50, 29, 107, 32, 30, 126, 123,
+ 50, 92, 32, 32, 119, 104, 127, 31, 90, 97,
+ 99, 105, 51, 52, 53, 54, 62, 46, 47, 51,
+ 52, 53, 54, 48, 35, 176, 36, 37, 103, 38,
+ 77, 112, 63, 64, 65, 66, 67, 68, 69, 70,
+ 71, 72, 81, 118, 32, 130, 104, 121, 49, 244,
+ 134, 137, 147, 131, 39, 116, 50, 104, 135, 138,
+ 62, 92, 40, 148, 158, 139, 107, 78, 85, 164,
+ 113, 82, 62, 167, 114, 86, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 115, 140, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 62, 104,
+ 175, 125, 129, 177, 2, 149, 178, 3, 4, 5,
+ 192, 181, 92, 133, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, -2, 1, 100, 141, 2, 101,
+ 102, 3, 4, 5, 13, 6, 7, 8, 9, 10,
+ 11, 12, 18, 46, 47, 169, 104, 142, 35, 48,
+ 36, 37, 156, 38, 51, 52, 53, 54, 13, 14,
+ 15, 16, 17, 143, 144, 157, 18, 150, -3, 1,
+ 151, 19, 2, 152, 49, 3, 4, 5, 39, 6,
+ 7, 8, 9, 10, 11, 12, 40, 2, 153, 184,
+ 3, 4, 5, 35, 185, 36, 37, 171, 38, 160,
+ 246, 163, 13, 14, 15, 16, 17, 166, 2, 184,
+ 18, 3, 4, 5, 185, 19, 107, 13, 118, 186,
+ 92, 182, 179, 39, 218, 18, 219, 187, 191, 216,
+ 35, 40, 36, 37, 220, 38, 221, 222, 13, 186,
+ 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
+ 223, 224, 225, 226, 227, 247, 248, 249, 250, 251,
+ 39, 252, 253, 254, 255, 91, 145, 170, 106, 193,
+ 111, 146, 154, 117, 162, 159, 168, 165, 89, 136,
+ 217, 245, 215
+};
+
+static const yytype_uint8 yycheck[] =
+{
+ 10, 11, 9, 118, 3, 4, 15, 16, 17, 5,
+ 9, 3, 4, 1, 1, 5, 5, 9, 47, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 4, 43, 44, 45,
+ 125, 39, 34, 42, 9, 41, 42, 9, 39, 47,
+ 42, 41, 42, 42, 60, 41, 47, 5, 0, 47,
+ 47, 47, 61, 62, 63, 64, 34, 3, 4, 61,
+ 62, 63, 64, 9, 4, 160, 6, 7, 5, 9,
+ 4, 39, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 4, 41, 42, 39, 41, 40, 34, 214,
+ 39, 39, 47, 47, 34, 41, 42, 41, 47, 47,
+ 34, 41, 42, 47, 121, 40, 41, 126, 4, 129,
+ 39, 130, 34, 133, 39, 134, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 39, 47, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 34, 41,
+ 157, 40, 40, 163, 4, 47, 166, 7, 8, 9,
+ 39, 171, 41, 40, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 0, 1, 40, 47, 4, 43,
+ 44, 7, 8, 9, 34, 11, 12, 13, 14, 15,
+ 16, 17, 42, 3, 4, 1, 41, 9, 4, 9,
+ 6, 7, 47, 9, 61, 62, 63, 64, 34, 35,
+ 36, 37, 38, 9, 9, 40, 42, 10, 0, 1,
+ 10, 47, 4, 10, 34, 7, 8, 9, 34, 11,
+ 12, 13, 14, 15, 16, 17, 42, 4, 10, 4,
+ 7, 8, 9, 4, 9, 6, 7, 45, 9, 40,
+ 9, 40, 34, 35, 36, 37, 38, 40, 4, 4,
+ 42, 7, 8, 9, 9, 47, 41, 34, 41, 34,
+ 41, 41, 39, 34, 40, 42, 40, 42, 46, 41,
+ 4, 42, 6, 7, 40, 9, 40, 40, 34, 34,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 40, 40, 40, 40, 40, 9, 9, 9, 9, 9,
+ 34, 9, 9, 9, 9, 21, 104, 137, 40, 182,
+ 50, 107, 116, 56, 126, 122, 134, 130, 18, 92,
+ 192, 216, 187
+};
+
+/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of
+ state STATE-NUM. */
+static const yytype_int8 yystos[] =
+{
+ 0, 1, 4, 7, 8, 9, 11, 12, 13, 14,
+ 15, 16, 17, 34, 35, 36, 37, 38, 42, 47,
+ 66, 67, 68, 69, 70, 114, 115, 116, 47, 9,
+ 9, 5, 42, 71, 72, 4, 6, 7, 9, 34,
+ 42, 75, 76, 103, 114, 114, 3, 4, 9, 34,
+ 42, 61, 62, 63, 64, 79, 80, 81, 82, 99,
+ 107, 4, 34, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 95, 96, 100, 101, 4, 96, 104,
+ 105, 4, 96, 111, 112, 4, 96, 108, 109, 116,
+ 0, 68, 41, 73, 74, 103, 1, 47, 1, 47,
+ 40, 43, 44, 5, 41, 47, 76, 41, 71, 71,
+ 71, 99, 39, 39, 39, 39, 41, 82, 41, 71,
+ 102, 40, 39, 47, 106, 40, 39, 47, 113, 40,
+ 39, 47, 110, 40, 39, 47, 115, 39, 47, 40,
+ 47, 47, 9, 9, 9, 72, 75, 47, 47, 47,
+ 10, 10, 10, 10, 79, 81, 47, 40, 103, 101,
+ 40, 107, 105, 40, 114, 112, 40, 114, 109, 1,
+ 74, 45, 77, 78, 93, 103, 107, 114, 114, 39,
+ 94, 114, 41, 97, 4, 9, 34, 42, 117, 118,
+ 119, 46, 39, 78, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 98, 119, 41, 117, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 81, 118, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9
+};
+
+/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */
+static const yytype_int8 yyr1[] =
+{
+ 0, 65, 66, 66, 67, 67, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 69, 69, 70, 70, 71, 71, 72, 72, 72, 72,
+ 72, 73, 73, 73, 74, 75, 75, 76, 76, 76,
+ 76, 76, 77, 77, 78, 79, 79, 79, 79, 80,
+ 80, 81, 81, 82, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 93, 94, 94, 94,
+ 94, 94, 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 96, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 98, 98, 98, 98, 98,
+ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
+ 98, 98, 99, 99, 99, 99, 100, 100, 102, 101,
+ 101, 103, 103, 104, 104, 106, 105, 105, 107, 107,
+ 108, 108, 110, 109, 109, 111, 111, 113, 112, 112,
+ 114, 114, 115, 115, 116, 116, 116, 116, 116, 117,
+ 117, 118, 118, 119, 119, 119
+};
+
+/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */
+static const yytype_int8 yyr2[] =
+{
+ 0, 2, 0, 1, 1, 2, 1, 2, 1, 1,
+ 3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
+ 3, 4, 3, 4, 1, 3, 1, 2, 3, 3,
+ 3, 1, 3, 3, 3, 1, 2, 1, 1, 1,
+ 1, 1, 1, 3, 4, 3, 3, 3, 3, 1,
+ 3, 1, 2, 1, 2, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 0, 3, 0, 1, 3,
+ 2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 0, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 0, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 1, 1, 1, 1, 1, 3, 0, 4,
+ 3, 1, 3, 1, 3, 0, 4, 3, 1, 3,
+ 1, 3, 0, 4, 3, 1, 3, 0, 4, 3,
+ 1, 3, 1, 2, 1, 1, 1, 1, 1, 1,
+ 3, 1, 2, 1, 1, 1
+};
+
+
+enum { YYENOMEM = -2 };
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+#define YYNOMEM goto yyexhaustedlab
+
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+ do \
+ if (yychar == YYEMPTY) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ YYPOPSTACK (yylen); \
+ yystate = *yyssp; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+ while (0)
+
+/* Backward compatibility with an undocumented macro.
+ Use YYerror or YYUNDEF. */
+#define YYERRCODE YYUNDEF
+
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+
+
+
+# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Kind, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
+
+
+/*-----------------------------------.
+| Print this symbol's value on YYO. |
+`-----------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyo,
+ yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep)
+{
+ FILE *yyoutput = yyo;
+ YY_USE (yyoutput);
+ if (!yyvaluep)
+ return;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ YY_USE (yykind);
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+/*---------------------------.
+| Print this symbol on YYO. |
+`---------------------------*/
+
+static void
+yy_symbol_print (FILE *yyo,
+ yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep)
+{
+ YYFPRINTF (yyo, "%s %s (",
+ yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind));
+
+ yy_symbol_value_print (yyo, yykind, yyvaluep);
+ YYFPRINTF (yyo, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop)
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp,
+ int yyrule)
+{
+ int yylno = yyrline[yyrule];
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr,
+ YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]),
+ &yyvsp[(yyi + 1) - (yynrhs)]);
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyssp, yyvsp, Rule); \
+} while (0)
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args) ((void) 0)
+# define YY_SYMBOL_PRINT(Title, Kind, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg,
+ yysymbol_kind_t yykind, YYSTYPE *yyvaluep)
+{
+ YY_USE (yyvaluep);
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp);
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ YY_USE (yykind);
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+/* Lookahead token kind. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+/* Number of syntax errors so far. */
+int yynerrs;
+
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+int
+yyparse (void)
+{
+ yy_state_fast_t yystate = 0;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus = 0;
+
+ /* Refer to the stacks through separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* Their size. */
+ YYPTRDIFF_T yystacksize = YYINITDEPTH;
+
+ /* The state stack: array, bottom, top. */
+ yy_state_t yyssa[YYINITDEPTH];
+ yy_state_t *yyss = yyssa;
+ yy_state_t *yyssp = yyss;
+
+ /* The semantic value stack: array, bottom, top. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ YYSTYPE *yyvsp = yyvs;
+
+ int yyn;
+ /* The return value of yyparse. */
+ int yyresult;
+ /* Lookahead symbol kind. */
+ yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ goto yysetstate;
+
+
+/*------------------------------------------------------------.
+| yynewstate -- push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+
+/*--------------------------------------------------------------------.
+| yysetstate -- set current state (the top of the stack) to yystate. |
+`--------------------------------------------------------------------*/
+yysetstate:
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+ YY_ASSERT (0 <= yystate && yystate < YYNSTATES);
+ YY_IGNORE_USELESS_CAST_BEGIN
+ *yyssp = YY_CAST (yy_state_t, yystate);
+ YY_IGNORE_USELESS_CAST_END
+ YY_STACK_PRINT (yyss, yyssp);
+
+ if (yyss + yystacksize - 1 <= yyssp)
+#if !defined yyoverflow && !defined YYSTACK_RELOCATE
+ YYNOMEM;
+#else
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYPTRDIFF_T yysize = yyssp - yyss + 1;
+
+# if defined yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ yy_state_t *yyss1 = yyss;
+ YYSTYPE *yyvs1 = yyvs;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * YYSIZEOF (*yyssp),
+ &yyvs1, yysize * YYSIZEOF (*yyvsp),
+ &yystacksize);
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+# else /* defined YYSTACK_RELOCATE */
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ YYNOMEM;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yy_state_t *yyss1 = yyss;
+ union yyalloc *yyptr =
+ YY_CAST (union yyalloc *,
+ YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
+ if (! yyptr)
+ YYNOMEM;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+ YY_IGNORE_USELESS_CAST_BEGIN
+ YYDPRINTF ((stderr, "Stack size increased to %ld\n",
+ YY_CAST (long, yystacksize)));
+ YY_IGNORE_USELESS_CAST_END
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
+
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yypact_value_is_default (yyn))
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token\n"));
+ yychar = yylex ();
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = YYEOF;
+ yytoken = YYSYMBOL_YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else if (yychar == YYerror)
+ {
+ /* The scanner already issued an error message, process directly
+ to error recovery. But do not keep the error token as
+ lookahead, it is too special and may lead us to an endless
+ loop in error recovery. */
+ yychar = YYUNDEF;
+ yytoken = YYSYMBOL_YYerror;
+ goto yyerrlab1;
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yytable_value_is_error (yyn))
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+ yystate = yyn;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ '$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2: /* file: %empty */
+#line 204 "gram.y"
+ {
+ ; /* empty file */
+ }
+#line 1653 "gram.c"
+ break;
+
+ case 6: /* entry: '\n' */
+#line 214 "gram.y"
+ {
+ ; /* blank line */
+ }
+#line 1661 "gram.c"
+ break;
+
+ case 7: /* entry: error '\n' */
+#line 217 "gram.y"
+ {
+ yyerrok;
+ }
+#line 1669 "gram.c"
+ break;
+
+ case 8: /* entry: include */
+#line 220 "gram.y"
+ {
+ const bool success = push_include((yyvsp[0].string),
+ parsed_policy.ctx->user.shost, &parser_conf);
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ free((yyvsp[0].string));
+ if (!success && !parser_conf.recovery)
+ YYERROR;
+ }
+#line 1682 "gram.c"
+ break;
+
+ case 9: /* entry: includedir */
+#line 228 "gram.y"
+ {
+ const bool success = push_includedir((yyvsp[0].string),
+ parsed_policy.ctx->user.shost, &parser_conf);
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ free((yyvsp[0].string));
+ if (!success && !parser_conf.recovery)
+ YYERROR;
+ }
+#line 1695 "gram.c"
+ break;
+
+ case 10: /* entry: userlist privileges '\n' */
+#line 236 "gram.y"
+ {
+ if (!add_userspec((yyvsp[-2].member), (yyvsp[-1].privilege))) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ }
+#line 1706 "gram.c"
+ break;
+
+ case 11: /* entry: USERALIAS useraliases '\n' */
+#line 242 "gram.y"
+ {
+ ;
+ }
+#line 1714 "gram.c"
+ break;
+
+ case 12: /* entry: HOSTALIAS hostaliases '\n' */
+#line 245 "gram.y"
+ {
+ ;
+ }
+#line 1722 "gram.c"
+ break;
+
+ case 13: /* entry: CMNDALIAS cmndaliases '\n' */
+#line 248 "gram.y"
+ {
+ ;
+ }
+#line 1730 "gram.c"
+ break;
+
+ case 14: /* entry: RUNASALIAS runasaliases '\n' */
+#line 251 "gram.y"
+ {
+ ;
+ }
+#line 1738 "gram.c"
+ break;
+
+ case 15: /* entry: DEFAULTS defaults_list '\n' */
+#line 254 "gram.y"
+ {
+ if (!add_defaults(DEFAULTS, NULL, (yyvsp[-1].defaults)))
+ YYERROR;
+ }
+#line 1747 "gram.c"
+ break;
+
+ case 16: /* entry: DEFAULTS_USER userlist defaults_list '\n' */
+#line 258 "gram.y"
+ {
+ if (!add_defaults(DEFAULTS_USER, (yyvsp[-2].member), (yyvsp[-1].defaults)))
+ YYERROR;
+ }
+#line 1756 "gram.c"
+ break;
+
+ case 17: /* entry: DEFAULTS_RUNAS userlist defaults_list '\n' */
+#line 262 "gram.y"
+ {
+ if (!add_defaults(DEFAULTS_RUNAS, (yyvsp[-2].member), (yyvsp[-1].defaults)))
+ YYERROR;
+ }
+#line 1765 "gram.c"
+ break;
+
+ case 18: /* entry: DEFAULTS_HOST hostlist defaults_list '\n' */
+#line 266 "gram.y"
+ {
+ if (!add_defaults(DEFAULTS_HOST, (yyvsp[-2].member), (yyvsp[-1].defaults)))
+ YYERROR;
+ }
+#line 1774 "gram.c"
+ break;
+
+ case 19: /* entry: DEFAULTS_CMND cmndlist defaults_list '\n' */
+#line 270 "gram.y"
+ {
+ if (!add_defaults(DEFAULTS_CMND, (yyvsp[-2].member), (yyvsp[-1].defaults)))
+ YYERROR;
+ }
+#line 1783 "gram.c"
+ break;
+
+ case 20: /* include: INCLUDE WORD '\n' */
+#line 276 "gram.y"
+ {
+ (yyval.string) = (yyvsp[-1].string);
+ }
+#line 1791 "gram.c"
+ break;
+
+ case 21: /* include: INCLUDE WORD error '\n' */
+#line 279 "gram.y"
+ {
+ yyerrok;
+ (yyval.string) = (yyvsp[-2].string);
+ }
+#line 1800 "gram.c"
+ break;
+
+ case 22: /* includedir: INCLUDEDIR WORD '\n' */
+#line 285 "gram.y"
+ {
+ (yyval.string) = (yyvsp[-1].string);
+ }
+#line 1808 "gram.c"
+ break;
+
+ case 23: /* includedir: INCLUDEDIR WORD error '\n' */
+#line 288 "gram.y"
+ {
+ yyerrok;
+ (yyval.string) = (yyvsp[-2].string);
+ }
+#line 1817 "gram.c"
+ break;
+
+ case 25: /* defaults_list: defaults_list ',' defaults_entry */
+#line 295 "gram.y"
+ {
+ parser_leak_remove(LEAK_DEFAULTS, (yyvsp[0].defaults));
+ HLTQ_CONCAT((yyvsp[-2].defaults), (yyvsp[0].defaults), entries);
+ (yyval.defaults) = (yyvsp[-2].defaults);
+ }
+#line 1827 "gram.c"
+ break;
+
+ case 26: /* defaults_entry: DEFVAR */
+#line 302 "gram.y"
+ {
+ (yyval.defaults) = new_default((yyvsp[0].string), NULL, true);
+ if ((yyval.defaults) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_DEFAULTS, (yyval.defaults));
+ }
+#line 1841 "gram.c"
+ break;
+
+ case 27: /* defaults_entry: '!' DEFVAR */
+#line 311 "gram.y"
+ {
+ (yyval.defaults) = new_default((yyvsp[0].string), NULL, false);
+ if ((yyval.defaults) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_DEFAULTS, (yyval.defaults));
+ }
+#line 1855 "gram.c"
+ break;
+
+ case 28: /* defaults_entry: DEFVAR '=' WORD */
+#line 320 "gram.y"
+ {
+ (yyval.defaults) = new_default((yyvsp[-2].string), (yyvsp[0].string), true);
+ if ((yyval.defaults) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[-2].string));
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_DEFAULTS, (yyval.defaults));
+ }
+#line 1870 "gram.c"
+ break;
+
+ case 29: /* defaults_entry: DEFVAR '+' WORD */
+#line 330 "gram.y"
+ {
+ (yyval.defaults) = new_default((yyvsp[-2].string), (yyvsp[0].string), '+');
+ if ((yyval.defaults) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[-2].string));
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_DEFAULTS, (yyval.defaults));
+ }
+#line 1885 "gram.c"
+ break;
+
+ case 30: /* defaults_entry: DEFVAR '-' WORD */
+#line 340 "gram.y"
+ {
+ (yyval.defaults) = new_default((yyvsp[-2].string), (yyvsp[0].string), '-');
+ if ((yyval.defaults) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[-2].string));
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_DEFAULTS, (yyval.defaults));
+ }
+#line 1900 "gram.c"
+ break;
+
+ case 32: /* privileges: privileges ':' privilege */
+#line 353 "gram.y"
+ {
+ parser_leak_remove(LEAK_PRIVILEGE, (yyvsp[0].privilege));
+ HLTQ_CONCAT((yyvsp[-2].privilege), (yyvsp[0].privilege), entries);
+ (yyval.privilege) = (yyvsp[-2].privilege);
+ }
+#line 1910 "gram.c"
+ break;
+
+ case 33: /* privileges: privileges ':' error */
+#line 358 "gram.y"
+ {
+ yyerrok;
+ (yyval.privilege) = (yyvsp[-2].privilege);
+ }
+#line 1919 "gram.c"
+ break;
+
+ case 34: /* privilege: hostlist '=' cmndspeclist */
+#line 364 "gram.y"
+ {
+ struct privilege *p = calloc(1, sizeof(*p));
+ if (p == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_PRIVILEGE, p);
+ TAILQ_INIT(&p->defaults);
+ parser_leak_remove(LEAK_MEMBER, (yyvsp[-2].member));
+ HLTQ_TO_TAILQ(&p->hostlist, (yyvsp[-2].member), entries);
+ parser_leak_remove(LEAK_CMNDSPEC, (yyvsp[0].cmndspec));
+ HLTQ_TO_TAILQ(&p->cmndlist, (yyvsp[0].cmndspec), entries);
+ HLTQ_INIT(p, entries);
+ (yyval.privilege) = p;
+ }
+#line 1939 "gram.c"
+ break;
+
+ case 35: /* ophost: host */
+#line 381 "gram.y"
+ {
+ (yyval.member) = (yyvsp[0].member);
+ (yyval.member)->negated = false;
+ }
+#line 1948 "gram.c"
+ break;
+
+ case 36: /* ophost: '!' host */
+#line 385 "gram.y"
+ {
+ (yyval.member) = (yyvsp[0].member);
+ (yyval.member)->negated = true;
+ }
+#line 1957 "gram.c"
+ break;
+
+ case 37: /* host: ALIAS */
+#line 391 "gram.y"
+ {
+ (yyval.member) = new_member((yyvsp[0].string), ALIAS);
+ if ((yyval.member) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_MEMBER, (yyval.member));
+ }
+#line 1971 "gram.c"
+ break;
+
+ case 38: /* host: ALL */
+#line 400 "gram.y"
+ {
+ (yyval.member) = new_member(NULL, ALL);
+ if ((yyval.member) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_MEMBER, (yyval.member));
+ }
+#line 1984 "gram.c"
+ break;
+
+ case 39: /* host: NETGROUP */
+#line 408 "gram.y"
+ {
+ (yyval.member) = new_member((yyvsp[0].string), NETGROUP);
+ if ((yyval.member) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_MEMBER, (yyval.member));
+ }
+#line 1998 "gram.c"
+ break;
+
+ case 40: /* host: NTWKADDR */
+#line 417 "gram.y"
+ {
+ (yyval.member) = new_member((yyvsp[0].string), NTWKADDR);
+ if ((yyval.member) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_MEMBER, (yyval.member));
+ }
+#line 2012 "gram.c"
+ break;
+
+ case 41: /* host: WORD */
+#line 426 "gram.y"
+ {
+ (yyval.member) = new_member((yyvsp[0].string), WORD);
+ if ((yyval.member) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_MEMBER, (yyval.member));
+ }
+#line 2026 "gram.c"
+ break;
+
+ case 43: /* cmndspeclist: cmndspeclist ',' cmndspec */
+#line 438 "gram.y"
+ {
+ struct cmndspec *prev;
+ prev = HLTQ_LAST((yyvsp[-2].cmndspec), cmndspec, entries);
+ parser_leak_remove(LEAK_CMNDSPEC, (yyvsp[0].cmndspec));
+ HLTQ_CONCAT((yyvsp[-2].cmndspec), (yyvsp[0].cmndspec), entries);
+
+ /* propagate runcwd and runchroot */
+ if ((yyvsp[0].cmndspec)->runcwd == NULL)
+ (yyvsp[0].cmndspec)->runcwd = prev->runcwd;
+ if ((yyvsp[0].cmndspec)->runchroot == NULL)
+ (yyvsp[0].cmndspec)->runchroot = prev->runchroot;
+#ifdef HAVE_SELINUX
+ /* propagate role and type */
+ if ((yyvsp[0].cmndspec)->role == NULL && (yyvsp[0].cmndspec)->type == NULL) {
+ (yyvsp[0].cmndspec)->role = prev->role;
+ (yyvsp[0].cmndspec)->type = prev->type;
+ }
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_PRIV_SET
+ /* propagate privs & limitprivs */
+ if ((yyvsp[0].cmndspec)->privs == NULL && (yyvsp[0].cmndspec)->limitprivs == NULL) {
+ (yyvsp[0].cmndspec)->privs = prev->privs;
+ (yyvsp[0].cmndspec)->limitprivs = prev->limitprivs;
+ }
+#endif /* HAVE_PRIV_SET */
+ /* propagate command time restrictions */
+ if ((yyvsp[0].cmndspec)->notbefore == UNSPEC)
+ (yyvsp[0].cmndspec)->notbefore = prev->notbefore;
+ if ((yyvsp[0].cmndspec)->notafter == UNSPEC)
+ (yyvsp[0].cmndspec)->notafter = prev->notafter;
+ /* propagate command timeout */
+ if ((yyvsp[0].cmndspec)->timeout == UNSPEC)
+ (yyvsp[0].cmndspec)->timeout = prev->timeout;
+ /* propagate tags and runas list */
+ if ((yyvsp[0].cmndspec)->tags.nopasswd == UNSPEC)
+ (yyvsp[0].cmndspec)->tags.nopasswd = prev->tags.nopasswd;
+ if ((yyvsp[0].cmndspec)->tags.noexec == UNSPEC)
+ (yyvsp[0].cmndspec)->tags.noexec = prev->tags.noexec;
+ if ((yyvsp[0].cmndspec)->tags.intercept == UNSPEC)
+ (yyvsp[0].cmndspec)->tags.intercept = prev->tags.intercept;
+ if ((yyvsp[0].cmndspec)->tags.setenv == UNSPEC &&
+ prev->tags.setenv != IMPLIED)
+ (yyvsp[0].cmndspec)->tags.setenv = prev->tags.setenv;
+ if ((yyvsp[0].cmndspec)->tags.log_input == UNSPEC)
+ (yyvsp[0].cmndspec)->tags.log_input = prev->tags.log_input;
+ if ((yyvsp[0].cmndspec)->tags.log_output == UNSPEC)
+ (yyvsp[0].cmndspec)->tags.log_output = prev->tags.log_output;
+ if ((yyvsp[0].cmndspec)->tags.send_mail == UNSPEC)
+ (yyvsp[0].cmndspec)->tags.send_mail = prev->tags.send_mail;
+ if ((yyvsp[0].cmndspec)->tags.follow == UNSPEC)
+ (yyvsp[0].cmndspec)->tags.follow = prev->tags.follow;
+ if (((yyvsp[0].cmndspec)->runasuserlist == NULL &&
+ (yyvsp[0].cmndspec)->runasgrouplist == NULL) &&
+ (prev->runasuserlist != NULL ||
+ prev->runasgrouplist != NULL)) {
+ (yyvsp[0].cmndspec)->runasuserlist = prev->runasuserlist;
+ (yyvsp[0].cmndspec)->runasgrouplist = prev->runasgrouplist;
+ }
+ (yyval.cmndspec) = (yyvsp[-2].cmndspec);
+ }
+#line 2091 "gram.c"
+ break;
+
+ case 44: /* cmndspec: runasspec options cmndtag digcmnd */
+#line 500 "gram.y"
+ {
+ struct cmndspec *cs = calloc(1, sizeof(*cs));
+ if (cs == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_CMNDSPEC, cs);
+ if ((yyvsp[-3].runas) != NULL) {
+ if ((yyvsp[-3].runas)->runasusers != NULL) {
+ cs->runasuserlist =
+ malloc(sizeof(*cs->runasuserlist));
+ if (cs->runasuserlist == NULL) {
+ free(cs);
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ /* g/c done via runas container */
+ HLTQ_TO_TAILQ(cs->runasuserlist,
+ (yyvsp[-3].runas)->runasusers, entries);
+ }
+ if ((yyvsp[-3].runas)->runasgroups != NULL) {
+ cs->runasgrouplist =
+ malloc(sizeof(*cs->runasgrouplist));
+ if (cs->runasgrouplist == NULL) {
+ free(cs);
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ /* g/c done via runas container */
+ HLTQ_TO_TAILQ(cs->runasgrouplist,
+ (yyvsp[-3].runas)->runasgroups, entries);
+ }
+ parser_leak_remove(LEAK_RUNAS, (yyvsp[-3].runas));
+ free((yyvsp[-3].runas));
+ }
+#ifdef HAVE_SELINUX
+ cs->role = (yyvsp[-2].options).role;
+ parser_leak_remove(LEAK_PTR, (yyvsp[-2].options).role);
+ cs->type = (yyvsp[-2].options).type;
+ parser_leak_remove(LEAK_PTR, (yyvsp[-2].options).type);
+#endif
+#ifdef HAVE_APPARMOR
+ cs->apparmor_profile = (yyvsp[-2].options).apparmor_profile;
+ parser_leak_remove(LEAK_PTR, (yyvsp[-2].options).apparmor_profile);
+#endif
+#ifdef HAVE_PRIV_SET
+ cs->privs = (yyvsp[-2].options).privs;
+ parser_leak_remove(LEAK_PTR, (yyvsp[-2].options).privs);
+ cs->limitprivs = (yyvsp[-2].options).limitprivs;
+ parser_leak_remove(LEAK_PTR, (yyvsp[-2].options).limitprivs);
+#endif
+ cs->notbefore = (yyvsp[-2].options).notbefore;
+ cs->notafter = (yyvsp[-2].options).notafter;
+ cs->timeout = (yyvsp[-2].options).timeout;
+ cs->runcwd = (yyvsp[-2].options).runcwd;
+ parser_leak_remove(LEAK_PTR, (yyvsp[-2].options).runcwd);
+ cs->runchroot = (yyvsp[-2].options).runchroot;
+ parser_leak_remove(LEAK_PTR, (yyvsp[-2].options).runchroot);
+ cs->tags = (yyvsp[-1].tag);
+ cs->cmnd = (yyvsp[0].member);
+ parser_leak_remove(LEAK_MEMBER, (yyvsp[0].member));
+ HLTQ_INIT(cs, entries);
+ /* sudo "ALL" implies the SETENV tag */
+ if (cs->cmnd->type == ALL && !cs->cmnd->negated &&
+ cs->tags.setenv == UNSPEC)
+ cs->tags.setenv = IMPLIED;
+ (yyval.cmndspec) = cs;
+ }
+#line 2164 "gram.c"
+ break;
+
+ case 45: /* digestspec: SHA224_TOK ':' DIGEST */
+#line 570 "gram.y"
+ {
+ (yyval.digest) = new_digest(SUDO_DIGEST_SHA224, (yyvsp[0].string));
+ if ((yyval.digest) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_DIGEST, (yyval.digest));
+ }
+#line 2178 "gram.c"
+ break;
+
+ case 46: /* digestspec: SHA256_TOK ':' DIGEST */
+#line 579 "gram.y"
+ {
+ (yyval.digest) = new_digest(SUDO_DIGEST_SHA256, (yyvsp[0].string));
+ if ((yyval.digest) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_DIGEST, (yyval.digest));
+ }
+#line 2192 "gram.c"
+ break;
+
+ case 47: /* digestspec: SHA384_TOK ':' DIGEST */
+#line 588 "gram.y"
+ {
+ (yyval.digest) = new_digest(SUDO_DIGEST_SHA384, (yyvsp[0].string));
+ if ((yyval.digest) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_DIGEST, (yyval.digest));
+ }
+#line 2206 "gram.c"
+ break;
+
+ case 48: /* digestspec: SHA512_TOK ':' DIGEST */
+#line 597 "gram.y"
+ {
+ (yyval.digest) = new_digest(SUDO_DIGEST_SHA512, (yyvsp[0].string));
+ if ((yyval.digest) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_DIGEST, (yyval.digest));
+ }
+#line 2220 "gram.c"
+ break;
+
+ case 50: /* digestlist: digestlist ',' digestspec */
+#line 609 "gram.y"
+ {
+ parser_leak_remove(LEAK_DIGEST, (yyvsp[0].digest));
+ HLTQ_CONCAT((yyvsp[-2].digest), (yyvsp[0].digest), entries);
+ (yyval.digest) = (yyvsp[-2].digest);
+ }
+#line 2230 "gram.c"
+ break;
+
+ case 51: /* digcmnd: opcmnd */
+#line 616 "gram.y"
+ {
+ (yyval.member) = (yyvsp[0].member);
+ }
+#line 2238 "gram.c"
+ break;
+
+ case 52: /* digcmnd: digestlist opcmnd */
+#line 619 "gram.y"
+ {
+ struct sudo_command *c =
+ (struct sudo_command *) (yyvsp[0].member)->name;
+
+ if ((yyvsp[0].member)->type != COMMAND && (yyvsp[0].member)->type != ALL) {
+ sudoerserror(N_("a digest requires a path name"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_DIGEST, (yyvsp[-1].digest));
+ HLTQ_TO_TAILQ(&c->digests, (yyvsp[-1].digest), entries);
+ (yyval.member) = (yyvsp[0].member);
+ }
+#line 2255 "gram.c"
+ break;
+
+ case 53: /* opcmnd: cmnd */
+#line 633 "gram.y"
+ {
+ (yyval.member) = (yyvsp[0].member);
+ (yyval.member)->negated = false;
+ }
+#line 2264 "gram.c"
+ break;
+
+ case 54: /* opcmnd: '!' cmnd */
+#line 637 "gram.y"
+ {
+ (yyval.member) = (yyvsp[0].member);
+ (yyval.member)->negated = true;
+ }
+#line 2273 "gram.c"
+ break;
+
+ case 55: /* chdirspec: CWD '=' WORD */
+#line 643 "gram.y"
+ {
+ if ((yyvsp[0].string)[0] != '/' && (yyvsp[0].string)[0] != '~') {
+ if (strcmp((yyvsp[0].string), "*") != 0) {
+ sudoerserror(N_("values for \"CWD\" must"
+ " start with a '/', '~', or '*'"));
+ YYERROR;
+ }
+ }
+ if (strlen((yyvsp[0].string)) >= PATH_MAX) {
+ sudoerserror(N_("\"CWD\" path too long"));
+ YYERROR;
+ }
+ (yyval.string) = (yyvsp[0].string);
+ }
+#line 2292 "gram.c"
+ break;
+
+ case 56: /* chrootspec: CHROOT '=' WORD */
+#line 659 "gram.y"
+ {
+ if ((yyvsp[0].string)[0] != '/' && (yyvsp[0].string)[0] != '~') {
+ if (strcmp((yyvsp[0].string), "*") != 0) {
+ sudoerserror(N_("values for \"CHROOT\" must"
+ " start with a '/', '~', or '*'"));
+ YYERROR;
+ }
+ }
+ if (strlen((yyvsp[0].string)) >= PATH_MAX) {
+ sudoerserror(N_("\"CHROOT\" path too long"));
+ YYERROR;
+ }
+ (yyval.string) = (yyvsp[0].string);
+ }
+#line 2311 "gram.c"
+ break;
+
+ case 57: /* timeoutspec: CMND_TIMEOUT '=' WORD */
+#line 675 "gram.y"
+ {
+ (yyval.string) = (yyvsp[0].string);
+ }
+#line 2319 "gram.c"
+ break;
+
+ case 58: /* notbeforespec: NOTBEFORE '=' WORD */
+#line 680 "gram.y"
+ {
+ (yyval.string) = (yyvsp[0].string);
+ }
+#line 2327 "gram.c"
+ break;
+
+ case 59: /* notafterspec: NOTAFTER '=' WORD */
+#line 684 "gram.y"
+ {
+ (yyval.string) = (yyvsp[0].string);
+ }
+#line 2335 "gram.c"
+ break;
+
+ case 60: /* rolespec: ROLE '=' WORD */
+#line 689 "gram.y"
+ {
+ (yyval.string) = (yyvsp[0].string);
+ }
+#line 2343 "gram.c"
+ break;
+
+ case 61: /* typespec: TYPE '=' WORD */
+#line 694 "gram.y"
+ {
+ (yyval.string) = (yyvsp[0].string);
+ }
+#line 2351 "gram.c"
+ break;
+
+ case 62: /* apparmor_profilespec: APPARMOR_PROFILE '=' WORD */
+#line 699 "gram.y"
+ {
+ (yyval.string) = (yyvsp[0].string);
+ }
+#line 2359 "gram.c"
+ break;
+
+ case 63: /* privsspec: PRIVS '=' WORD */
+#line 704 "gram.y"
+ {
+ (yyval.string) = (yyvsp[0].string);
+ }
+#line 2367 "gram.c"
+ break;
+
+ case 64: /* limitprivsspec: LIMITPRIVS '=' WORD */
+#line 708 "gram.y"
+ {
+ (yyval.string) = (yyvsp[0].string);
+ }
+#line 2375 "gram.c"
+ break;
+
+ case 65: /* runasspec: %empty */
+#line 713 "gram.y"
+ {
+ (yyval.runas) = NULL;
+ }
+#line 2383 "gram.c"
+ break;
+
+ case 66: /* runasspec: '(' runaslist ')' */
+#line 716 "gram.y"
+ {
+ (yyval.runas) = (yyvsp[-1].runas);
+ }
+#line 2391 "gram.c"
+ break;
+
+ case 67: /* runaslist: %empty */
+#line 721 "gram.y"
+ {
+ /* User may run command as themselves. */
+ (yyval.runas) = calloc(1, sizeof(struct runascontainer));
+ if ((yyval.runas) != NULL) {
+ (yyval.runas)->runasusers = new_member(NULL, MYSELF);
+ /* $$->runasgroups = NULL; */
+ if ((yyval.runas)->runasusers == NULL) {
+ free((yyval.runas));
+ (yyval.runas) = NULL;
+ }
+ }
+ if ((yyval.runas) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_RUNAS, (yyval.runas));
+ }
+#line 2413 "gram.c"
+ break;
+
+ case 68: /* runaslist: userlist */
+#line 738 "gram.y"
+ {
+ /* User may run command as a user in userlist. */
+ (yyval.runas) = calloc(1, sizeof(struct runascontainer));
+ if ((yyval.runas) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_RUNAS, (yyval.runas));
+ parser_leak_remove(LEAK_MEMBER, (yyvsp[0].member));
+ (yyval.runas)->runasusers = (yyvsp[0].member);
+ /* $$->runasgroups = NULL; */
+ }
+#line 2430 "gram.c"
+ break;
+
+ case 69: /* runaslist: userlist ':' grouplist */
+#line 750 "gram.y"
+ {
+ /*
+ * User may run command as a user in userlist
+ * and optionally as a group in grouplist.
+ */
+ (yyval.runas) = calloc(1, sizeof(struct runascontainer));
+ if ((yyval.runas) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_RUNAS, (yyval.runas));
+ parser_leak_remove(LEAK_MEMBER, (yyvsp[-2].member));
+ parser_leak_remove(LEAK_MEMBER, (yyvsp[0].member));
+ (yyval.runas)->runasusers = (yyvsp[-2].member);
+ (yyval.runas)->runasgroups = (yyvsp[0].member);
+ }
+#line 2451 "gram.c"
+ break;
+
+ case 70: /* runaslist: ':' grouplist */
+#line 766 "gram.y"
+ {
+ /* User may run command as a group in grouplist. */
+ (yyval.runas) = calloc(1, sizeof(struct runascontainer));
+ if ((yyval.runas) != NULL) {
+ (yyval.runas)->runasusers = new_member(NULL, MYSELF);
+ if ((yyval.runas)->runasusers == NULL) {
+ free((yyval.runas));
+ (yyval.runas) = NULL;
+ }
+ }
+ if ((yyval.runas) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_RUNAS, (yyval.runas));
+ parser_leak_remove(LEAK_MEMBER, (yyvsp[0].member));
+ (yyval.runas)->runasgroups = (yyvsp[0].member);
+ }
+#line 2474 "gram.c"
+ break;
+
+ case 71: /* runaslist: ':' */
+#line 784 "gram.y"
+ {
+ /* User may run command as themselves. */
+ (yyval.runas) = calloc(1, sizeof(struct runascontainer));
+ if ((yyval.runas) != NULL) {
+ (yyval.runas)->runasusers = new_member(NULL, MYSELF);
+ /* $$->runasgroups = NULL; */
+ if ((yyval.runas)->runasusers == NULL) {
+ free((yyval.runas));
+ (yyval.runas) = NULL;
+ }
+ }
+ if ((yyval.runas) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_RUNAS, (yyval.runas));
+ }
+#line 2496 "gram.c"
+ break;
+
+ case 72: /* reserved_word: ALL */
+#line 803 "gram.y"
+ { (yyval.cstring) = "ALL"; }
+#line 2502 "gram.c"
+ break;
+
+ case 73: /* reserved_word: CHROOT */
+#line 804 "gram.y"
+ { (yyval.cstring) = "CHROOT"; }
+#line 2508 "gram.c"
+ break;
+
+ case 74: /* reserved_word: CWD */
+#line 805 "gram.y"
+ { (yyval.cstring) = "CWD"; }
+#line 2514 "gram.c"
+ break;
+
+ case 75: /* reserved_word: CMND_TIMEOUT */
+#line 806 "gram.y"
+ { (yyval.cstring) = "CMND_TIMEOUT"; }
+#line 2520 "gram.c"
+ break;
+
+ case 76: /* reserved_word: NOTBEFORE */
+#line 807 "gram.y"
+ { (yyval.cstring) = "NOTBEFORE"; }
+#line 2526 "gram.c"
+ break;
+
+ case 77: /* reserved_word: NOTAFTER */
+#line 808 "gram.y"
+ { (yyval.cstring) = "NOTAFTER"; }
+#line 2532 "gram.c"
+ break;
+
+ case 78: /* reserved_word: ROLE */
+#line 809 "gram.y"
+ { (yyval.cstring) = "ROLE"; }
+#line 2538 "gram.c"
+ break;
+
+ case 79: /* reserved_word: TYPE */
+#line 810 "gram.y"
+ { (yyval.cstring) = "TYPE"; }
+#line 2544 "gram.c"
+ break;
+
+ case 80: /* reserved_word: PRIVS */
+#line 811 "gram.y"
+ { (yyval.cstring) = "PRIVS"; }
+#line 2550 "gram.c"
+ break;
+
+ case 81: /* reserved_word: LIMITPRIVS */
+#line 812 "gram.y"
+ { (yyval.cstring) = "LIMITPRIVS"; }
+#line 2556 "gram.c"
+ break;
+
+ case 82: /* reserved_word: APPARMOR_PROFILE */
+#line 813 "gram.y"
+ { (yyval.cstring) = "APPARMOR_PROFILE"; }
+#line 2562 "gram.c"
+ break;
+
+ case 83: /* reserved_alias: reserved_word */
+#line 816 "gram.y"
+ {
+ sudoerserrorf(U_("syntax error, reserved word %s used as an alias name"), (yyvsp[0].cstring));
+ YYERROR;
+ }
+#line 2571 "gram.c"
+ break;
+
+ case 84: /* options: %empty */
+#line 822 "gram.y"
+ {
+ init_options(&(yyval.options));
+ }
+#line 2579 "gram.c"
+ break;
+
+ case 85: /* options: options chdirspec */
+#line 825 "gram.y"
+ {
+ parser_leak_remove(LEAK_PTR, (yyval.options).runcwd);
+ free((yyval.options).runcwd);
+ (yyval.options).runcwd = (yyvsp[0].string);
+ }
+#line 2589 "gram.c"
+ break;
+
+ case 86: /* options: options chrootspec */
+#line 830 "gram.y"
+ {
+ parser_leak_remove(LEAK_PTR, (yyval.options).runchroot);
+ free((yyval.options).runchroot);
+ (yyval.options).runchroot = (yyvsp[0].string);
+ }
+#line 2599 "gram.c"
+ break;
+
+ case 87: /* options: options notbeforespec */
+#line 835 "gram.y"
+ {
+ (yyval.options).notbefore = parse_gentime((yyvsp[0].string));
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ free((yyvsp[0].string));
+ if ((yyval.options).notbefore == -1) {
+ sudoerserror(N_("invalid notbefore value"));
+ YYERROR;
+ }
+ }
+#line 2613 "gram.c"
+ break;
+
+ case 88: /* options: options notafterspec */
+#line 844 "gram.y"
+ {
+ (yyval.options).notafter = parse_gentime((yyvsp[0].string));
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ free((yyvsp[0].string));
+ if ((yyval.options).notafter == -1) {
+ sudoerserror(N_("invalid notafter value"));
+ YYERROR;
+ }
+ }
+#line 2627 "gram.c"
+ break;
+
+ case 89: /* options: options timeoutspec */
+#line 853 "gram.y"
+ {
+ (yyval.options).timeout = parse_timeout((yyvsp[0].string));
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ free((yyvsp[0].string));
+ if ((yyval.options).timeout == -1) {
+ if (errno == ERANGE)
+ sudoerserror(N_("timeout value too large"));
+ else
+ sudoerserror(N_("invalid timeout value"));
+ YYERROR;
+ }
+ }
+#line 2644 "gram.c"
+ break;
+
+ case 90: /* options: options rolespec */
+#line 865 "gram.y"
+ {
+#ifdef HAVE_SELINUX
+ parser_leak_remove(LEAK_PTR, (yyval.options).role);
+ free((yyval.options).role);
+ (yyval.options).role = (yyvsp[0].string);
+#endif
+ }
+#line 2656 "gram.c"
+ break;
+
+ case 91: /* options: options typespec */
+#line 872 "gram.y"
+ {
+#ifdef HAVE_SELINUX
+ parser_leak_remove(LEAK_PTR, (yyval.options).type);
+ free((yyval.options).type);
+ (yyval.options).type = (yyvsp[0].string);
+#endif
+ }
+#line 2668 "gram.c"
+ break;
+
+ case 92: /* options: options apparmor_profilespec */
+#line 879 "gram.y"
+ {
+#ifdef HAVE_APPARMOR
+ parser_leak_remove(LEAK_PTR, (yyval.options).apparmor_profile);
+ free((yyval.options).apparmor_profile);
+ (yyval.options).apparmor_profile = (yyvsp[0].string);
+#endif
+ }
+#line 2680 "gram.c"
+ break;
+
+ case 93: /* options: options privsspec */
+#line 886 "gram.y"
+ {
+#ifdef HAVE_PRIV_SET
+ parser_leak_remove(LEAK_PTR, (yyval.options).privs);
+ free((yyval.options).privs);
+ (yyval.options).privs = (yyvsp[0].string);
+#endif
+ }
+#line 2692 "gram.c"
+ break;
+
+ case 94: /* options: options limitprivsspec */
+#line 893 "gram.y"
+ {
+#ifdef HAVE_PRIV_SET
+ parser_leak_remove(LEAK_PTR, (yyval.options).limitprivs);
+ free((yyval.options).limitprivs);
+ (yyval.options).limitprivs = (yyvsp[0].string);
+#endif
+ }
+#line 2704 "gram.c"
+ break;
+
+ case 95: /* cmndtag: %empty */
+#line 902 "gram.y"
+ {
+ TAGS_INIT(&(yyval.tag));
+ }
+#line 2712 "gram.c"
+ break;
+
+ case 96: /* cmndtag: cmndtag NOPASSWD */
+#line 905 "gram.y"
+ {
+ (yyval.tag).nopasswd = true;
+ }
+#line 2720 "gram.c"
+ break;
+
+ case 97: /* cmndtag: cmndtag PASSWD */
+#line 908 "gram.y"
+ {
+ (yyval.tag).nopasswd = false;
+ }
+#line 2728 "gram.c"
+ break;
+
+ case 98: /* cmndtag: cmndtag NOEXEC */
+#line 911 "gram.y"
+ {
+ (yyval.tag).noexec = true;
+ }
+#line 2736 "gram.c"
+ break;
+
+ case 99: /* cmndtag: cmndtag EXEC */
+#line 914 "gram.y"
+ {
+ (yyval.tag).noexec = false;
+ }
+#line 2744 "gram.c"
+ break;
+
+ case 100: /* cmndtag: cmndtag INTERCEPT */
+#line 917 "gram.y"
+ {
+ (yyval.tag).intercept = true;
+ }
+#line 2752 "gram.c"
+ break;
+
+ case 101: /* cmndtag: cmndtag NOINTERCEPT */
+#line 920 "gram.y"
+ {
+ (yyval.tag).intercept = false;
+ }
+#line 2760 "gram.c"
+ break;
+
+ case 102: /* cmndtag: cmndtag SETENV */
+#line 923 "gram.y"
+ {
+ (yyval.tag).setenv = true;
+ }
+#line 2768 "gram.c"
+ break;
+
+ case 103: /* cmndtag: cmndtag NOSETENV */
+#line 926 "gram.y"
+ {
+ (yyval.tag).setenv = false;
+ }
+#line 2776 "gram.c"
+ break;
+
+ case 104: /* cmndtag: cmndtag LOG_INPUT */
+#line 929 "gram.y"
+ {
+ (yyval.tag).log_input = true;
+ }
+#line 2784 "gram.c"
+ break;
+
+ case 105: /* cmndtag: cmndtag NOLOG_INPUT */
+#line 932 "gram.y"
+ {
+ (yyval.tag).log_input = false;
+ }
+#line 2792 "gram.c"
+ break;
+
+ case 106: /* cmndtag: cmndtag LOG_OUTPUT */
+#line 935 "gram.y"
+ {
+ (yyval.tag).log_output = true;
+ }
+#line 2800 "gram.c"
+ break;
+
+ case 107: /* cmndtag: cmndtag NOLOG_OUTPUT */
+#line 938 "gram.y"
+ {
+ (yyval.tag).log_output = false;
+ }
+#line 2808 "gram.c"
+ break;
+
+ case 108: /* cmndtag: cmndtag FOLLOWLNK */
+#line 941 "gram.y"
+ {
+ (yyval.tag).follow = true;
+ }
+#line 2816 "gram.c"
+ break;
+
+ case 109: /* cmndtag: cmndtag NOFOLLOWLNK */
+#line 944 "gram.y"
+ {
+ (yyval.tag).follow = false;
+ }
+#line 2824 "gram.c"
+ break;
+
+ case 110: /* cmndtag: cmndtag MAIL */
+#line 947 "gram.y"
+ {
+ (yyval.tag).send_mail = true;
+ }
+#line 2832 "gram.c"
+ break;
+
+ case 111: /* cmndtag: cmndtag NOMAIL */
+#line 950 "gram.y"
+ {
+ (yyval.tag).send_mail = false;
+ }
+#line 2840 "gram.c"
+ break;
+
+ case 112: /* cmnd: ALL */
+#line 955 "gram.y"
+ {
+ struct sudo_command *c;
+
+ if ((c = new_command(NULL, NULL)) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ (yyval.member) = new_member((char *)c, ALL);
+ if ((yyval.member) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_MEMBER, (yyval.member));
+ }
+#line 2859 "gram.c"
+ break;
+
+ case 113: /* cmnd: ALIAS */
+#line 969 "gram.y"
+ {
+ (yyval.member) = new_member((yyvsp[0].string), ALIAS);
+ if ((yyval.member) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_MEMBER, (yyval.member));
+ }
+#line 2873 "gram.c"
+ break;
+
+ case 114: /* cmnd: COMMAND */
+#line 978 "gram.y"
+ {
+ struct sudo_command *c;
+
+ if (strlen((yyvsp[0].command).cmnd) >= PATH_MAX) {
+ sudoerserror(N_("command too long"));
+ YYERROR;
+ }
+ if ((c = new_command((yyvsp[0].command).cmnd, (yyvsp[0].command).args)) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ (yyval.member) = new_member((char *)c, COMMAND);
+ if ((yyval.member) == NULL) {
+ free(c);
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].command).cmnd);
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].command).args);
+ parser_leak_add(LEAK_MEMBER, (yyval.member));
+ }
+#line 2899 "gram.c"
+ break;
+
+ case 115: /* cmnd: WORD */
+#line 999 "gram.y"
+ {
+ if (strcmp((yyvsp[0].string), "list") == 0) {
+ struct sudo_command *c;
+
+ if ((c = new_command((yyvsp[0].string), NULL)) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ (yyval.member) = new_member((char *)c, COMMAND);
+ if ((yyval.member) == NULL) {
+ free(c);
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_MEMBER, (yyval.member));
+ } else {
+ sudoerserror(N_("expected a fully-qualified path name"));
+ YYERROR;
+ }
+ }
+#line 2925 "gram.c"
+ break;
+
+ case 118: /* $@1: %empty */
+#line 1026 "gram.y"
+ {
+ alias_line = this_lineno;
+ alias_column = (int)sudolinebuf.toke_start + 1;
+ }
+#line 2934 "gram.c"
+ break;
+
+ case 119: /* hostalias: ALIAS $@1 '=' hostlist */
+#line 1029 "gram.y"
+ {
+ if (!alias_add(&parsed_policy, (yyvsp[-3].string), HOSTALIAS,
+ sudoers, alias_line, alias_column, (yyvsp[0].member))) {
+ alias_error((yyvsp[-3].string), errno);
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[-3].string));
+ parser_leak_remove(LEAK_MEMBER, (yyvsp[0].member));
+ }
+#line 2948 "gram.c"
+ break;
+
+ case 122: /* hostlist: hostlist ',' ophost */
+#line 1042 "gram.y"
+ {
+ parser_leak_remove(LEAK_MEMBER, (yyvsp[0].member));
+ HLTQ_CONCAT((yyvsp[-2].member), (yyvsp[0].member), entries);
+ (yyval.member) = (yyvsp[-2].member);
+ }
+#line 2958 "gram.c"
+ break;
+
+ case 125: /* $@2: %empty */
+#line 1053 "gram.y"
+ {
+ alias_line = this_lineno;
+ alias_column = (int)sudolinebuf.toke_start + 1;
+ }
+#line 2967 "gram.c"
+ break;
+
+ case 126: /* cmndalias: ALIAS $@2 '=' cmndlist */
+#line 1056 "gram.y"
+ {
+ if (!alias_add(&parsed_policy, (yyvsp[-3].string), CMNDALIAS,
+ sudoers, alias_line, alias_column, (yyvsp[0].member))) {
+ alias_error((yyvsp[-3].string), errno);
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[-3].string));
+ parser_leak_remove(LEAK_MEMBER, (yyvsp[0].member));
+ }
+#line 2981 "gram.c"
+ break;
+
+ case 129: /* cmndlist: cmndlist ',' digcmnd */
+#line 1069 "gram.y"
+ {
+ parser_leak_remove(LEAK_MEMBER, (yyvsp[0].member));
+ HLTQ_CONCAT((yyvsp[-2].member), (yyvsp[0].member), entries);
+ (yyval.member) = (yyvsp[-2].member);
+ }
+#line 2991 "gram.c"
+ break;
+
+ case 132: /* $@3: %empty */
+#line 1080 "gram.y"
+ {
+ alias_line = this_lineno;
+ alias_column = (int)sudolinebuf.toke_start + 1;
+ }
+#line 3000 "gram.c"
+ break;
+
+ case 133: /* runasalias: ALIAS $@3 '=' userlist */
+#line 1083 "gram.y"
+ {
+ if (!alias_add(&parsed_policy, (yyvsp[-3].string), RUNASALIAS,
+ sudoers, alias_line, alias_column, (yyvsp[0].member))) {
+ alias_error((yyvsp[-3].string), errno);
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[-3].string));
+ parser_leak_remove(LEAK_MEMBER, (yyvsp[0].member));
+ }
+#line 3014 "gram.c"
+ break;
+
+ case 137: /* $@4: %empty */
+#line 1099 "gram.y"
+ {
+ alias_line = this_lineno;
+ alias_column = (int)sudolinebuf.toke_start + 1;
+ }
+#line 3023 "gram.c"
+ break;
+
+ case 138: /* useralias: ALIAS $@4 '=' userlist */
+#line 1102 "gram.y"
+ {
+ if (!alias_add(&parsed_policy, (yyvsp[-3].string), USERALIAS,
+ sudoers, alias_line, alias_column, (yyvsp[0].member))) {
+ alias_error((yyvsp[-3].string), errno);
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[-3].string));
+ parser_leak_remove(LEAK_MEMBER, (yyvsp[0].member));
+ }
+#line 3037 "gram.c"
+ break;
+
+ case 141: /* userlist: userlist ',' opuser */
+#line 1115 "gram.y"
+ {
+ parser_leak_remove(LEAK_MEMBER, (yyvsp[0].member));
+ HLTQ_CONCAT((yyvsp[-2].member), (yyvsp[0].member), entries);
+ (yyval.member) = (yyvsp[-2].member);
+ }
+#line 3047 "gram.c"
+ break;
+
+ case 142: /* opuser: user */
+#line 1122 "gram.y"
+ {
+ (yyval.member) = (yyvsp[0].member);
+ (yyval.member)->negated = false;
+ }
+#line 3056 "gram.c"
+ break;
+
+ case 143: /* opuser: '!' user */
+#line 1126 "gram.y"
+ {
+ (yyval.member) = (yyvsp[0].member);
+ (yyval.member)->negated = true;
+ }
+#line 3065 "gram.c"
+ break;
+
+ case 144: /* user: ALIAS */
+#line 1132 "gram.y"
+ {
+ (yyval.member) = new_member((yyvsp[0].string), ALIAS);
+ if ((yyval.member) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_MEMBER, (yyval.member));
+ }
+#line 3079 "gram.c"
+ break;
+
+ case 145: /* user: ALL */
+#line 1141 "gram.y"
+ {
+ (yyval.member) = new_member(NULL, ALL);
+ if ((yyval.member) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_MEMBER, (yyval.member));
+ }
+#line 3092 "gram.c"
+ break;
+
+ case 146: /* user: NETGROUP */
+#line 1149 "gram.y"
+ {
+ (yyval.member) = new_member((yyvsp[0].string), NETGROUP);
+ if ((yyval.member) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_MEMBER, (yyval.member));
+ }
+#line 3106 "gram.c"
+ break;
+
+ case 147: /* user: USERGROUP */
+#line 1158 "gram.y"
+ {
+ (yyval.member) = new_member((yyvsp[0].string), USERGROUP);
+ if ((yyval.member) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_MEMBER, (yyval.member));
+ }
+#line 3120 "gram.c"
+ break;
+
+ case 148: /* user: WORD */
+#line 1167 "gram.y"
+ {
+ (yyval.member) = new_member((yyvsp[0].string), WORD);
+ if ((yyval.member) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_MEMBER, (yyval.member));
+ }
+#line 3134 "gram.c"
+ break;
+
+ case 150: /* grouplist: grouplist ',' opgroup */
+#line 1179 "gram.y"
+ {
+ parser_leak_remove(LEAK_MEMBER, (yyvsp[0].member));
+ HLTQ_CONCAT((yyvsp[-2].member), (yyvsp[0].member), entries);
+ (yyval.member) = (yyvsp[-2].member);
+ }
+#line 3144 "gram.c"
+ break;
+
+ case 151: /* opgroup: group */
+#line 1186 "gram.y"
+ {
+ (yyval.member) = (yyvsp[0].member);
+ (yyval.member)->negated = false;
+ }
+#line 3153 "gram.c"
+ break;
+
+ case 152: /* opgroup: '!' group */
+#line 1190 "gram.y"
+ {
+ (yyval.member) = (yyvsp[0].member);
+ (yyval.member)->negated = true;
+ }
+#line 3162 "gram.c"
+ break;
+
+ case 153: /* group: ALIAS */
+#line 1196 "gram.y"
+ {
+ (yyval.member) = new_member((yyvsp[0].string), ALIAS);
+ if ((yyval.member) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_MEMBER, (yyval.member));
+ }
+#line 3176 "gram.c"
+ break;
+
+ case 154: /* group: ALL */
+#line 1205 "gram.y"
+ {
+ (yyval.member) = new_member(NULL, ALL);
+ if ((yyval.member) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_MEMBER, (yyval.member));
+ }
+#line 3189 "gram.c"
+ break;
+
+ case 155: /* group: WORD */
+#line 1213 "gram.y"
+ {
+ (yyval.member) = new_member((yyvsp[0].string), WORD);
+ if ((yyval.member) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, (yyvsp[0].string));
+ parser_leak_add(LEAK_MEMBER, (yyval.member));
+ }
+#line 3203 "gram.c"
+ break;
+
+
+#line 3207 "gram.c"
+
+ default: break;
+ }
+ /* User semantic actions sometimes alter yychar, and that requires
+ that yytoken be updated with the new translation. We take the
+ approach of translating immediately before every use of yytoken.
+ One alternative is translating here after every semantic action,
+ but that translation would be missed if the semantic action invokes
+ YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+ if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
+ incorrect destructor might then be invoked immediately. In the
+ case of YYERROR or YYBACKUP, subsequent parser actions might lead
+ to an incorrect destructor call or verbose syntax error message
+ before the lookahead is translated. */
+ YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+
+ *++yyvsp = yyval;
+
+ /* Now 'shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+ {
+ const int yylhs = yyr1[yyn] - YYNTOKENS;
+ const int yyi = yypgoto[yylhs] + *yyssp;
+ yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp
+ ? yytable[yyi]
+ : yydefgoto[yylhs]);
+ }
+
+ goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error. |
+`--------------------------------------*/
+yyerrlab:
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar);
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+ yyerror (YY_("syntax error"));
+ }
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+ /* Pacify compilers when the user code never invokes YYERROR and the
+ label yyerrorlab therefore never appears in user code. */
+ if (0)
+ YYERROR;
+ ++yynerrs;
+
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ /* Pop stack until we find a state that shifts the error token. */
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (!yypact_value_is_default (yyn))
+ {
+ yyn += YYSYMBOL_YYerror;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ YY_ACCESSING_SYMBOL (yystate), yyvsp);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturnlab;
+
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturnlab;
+
+
+/*-----------------------------------------------------------.
+| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. |
+`-----------------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (YY_("memory exhausted"));
+ yyresult = 2;
+ goto yyreturnlab;
+
+
+/*----------------------------------------------------------.
+| yyreturnlab -- parsing is finished, clean up and return. |
+`----------------------------------------------------------*/
+yyreturnlab:
+ if (yychar != YYEMPTY)
+ {
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = YYTRANSLATE (yychar);
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval);
+ }
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ YY_ACCESSING_SYMBOL (+*yyssp), yyvsp);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+
+ return yyresult;
+}
+
+#line 1223 "gram.y"
+
+/* Like yyerror() but takes a printf-style format string. */
+void
+sudoerserrorf(const char * restrict fmt, ...)
+{
+ const int column = (int)(sudolinebuf.toke_start + 1);
+ va_list ap;
+ debug_decl(sudoerserrorf, SUDOERS_DEBUG_PARSER);
+
+ if (sudoers_error_hook != NULL) {
+ va_start(ap, fmt);
+ sudoers_error_hook(parsed_policy.ctx, sudoers, this_lineno, column,
+ fmt, ap);
+ va_end(ap);
+ }
+ if (parser_conf.verbose > 0 && fmt != NULL) {
+ LEXTRACE("<*> ");
+#ifndef TRACELEXER
+ if (trace_print == NULL || trace_print == sudoers_trace_print) {
+ char *tofree = NULL;
+ const char *s;
+ int oldlocale;
+
+ /* Warnings are displayed in the user's locale. */
+ sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale);
+
+ va_start(ap, fmt);
+ if (strcmp(fmt, "%s") == 0) {
+ /* Optimize common case, a single string. */
+ s = _(va_arg(ap, char *));
+ } else {
+ if (vasprintf(&tofree, _(fmt), ap) != -1) {
+ s = tofree;
+ } else {
+ s = _("syntax error");
+ tofree = NULL;
+ }
+ }
+ sudo_printf(SUDO_CONV_ERROR_MSG, _("%s:%d:%zu: %s\n"), sudoers,
+ this_lineno, sudolinebuf.toke_start + 1, s);
+ free(tofree);
+ va_end(ap);
+ sudoers_setlocale(oldlocale, NULL);
+
+ /* Display the offending line and token if possible. */
+ if (sudolinebuf.len != 0) {
+ char tildes[128];
+ size_t tlen = 0;
+
+ sudo_printf(SUDO_CONV_ERROR_MSG, "%s%s", sudolinebuf.buf,
+ sudolinebuf.buf[sudolinebuf.len - 1] == '\n' ? "" : "\n");
+ if (sudolinebuf.toke_end > sudolinebuf.toke_start) {
+ tlen = sudolinebuf.toke_end - sudolinebuf.toke_start - 1;
+ if (tlen >= sizeof(tildes))
+ tlen = sizeof(tildes) - 1;
+ memset(tildes, '~', tlen);
+ }
+ tildes[tlen] = '\0';
+ sudo_printf(SUDO_CONV_ERROR_MSG, "%*s^%s\n",
+ (int)sudolinebuf.toke_start, "", tildes);
+ }
+ }
+#endif
+ }
+ parse_error = true;
+ debug_return;
+}
+
+void
+sudoerserror(const char *s)
+{
+ if (sudoerschar == ERROR) {
+ /* Use error string from lexer. */
+ s = sudoers_errstr;
+ sudoers_errstr = NULL;
+ }
+
+#pragma pvs(push)
+#pragma pvs(disable: 575, 618)
+
+ if (s == NULL)
+ sudoerserrorf(NULL);
+ else
+ sudoerserrorf("%s", s);
+
+#pragma pvs(pop)
+}
+
+static void
+alias_error(const char *name, int errnum)
+{
+ if (errnum == EEXIST)
+ sudoerserrorf(U_("Alias \"%s\" already defined"), name);
+ else
+ sudoerserror(N_("unable to allocate memory"));
+}
+
+static struct defaults *
+new_default(char *var, char *val, short op)
+{
+ struct defaults *d;
+ debug_decl(new_default, SUDOERS_DEBUG_PARSER);
+
+ if ((d = calloc(1, sizeof(struct defaults))) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+
+ d->var = var;
+ d->val = val;
+ /* d->type = 0; */
+ d->op = op;
+ /* d->binding = NULL; */
+ d->line = this_lineno;
+ d->column = (int)(sudolinebuf.toke_start + 1);
+ d->file = sudo_rcstr_addref(sudoers);
+ HLTQ_INIT(d, entries);
+
+ debug_return_ptr(d);
+}
+
+static struct member *
+new_member(char *name, short type)
+{
+ struct member *m;
+ debug_decl(new_member, SUDOERS_DEBUG_PARSER);
+
+ if ((m = calloc(1, sizeof(struct member))) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+
+ m->name = name;
+ m->type = type;
+ HLTQ_INIT(m, entries);
+
+ debug_return_ptr(m);
+}
+
+static struct sudo_command *
+new_command(char *cmnd, char *args)
+{
+ struct sudo_command *c;
+ debug_decl(new_command, SUDOERS_DEBUG_PARSER);
+
+ if ((c = calloc(1, sizeof(*c))) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+ /* garbage collected as part of struct member */
+
+ c->cmnd = cmnd;
+ c->args = args;
+ TAILQ_INIT(&c->digests);
+
+ debug_return_ptr(c);
+}
+
+static struct command_digest *
+new_digest(unsigned int digest_type, char *digest_str)
+{
+ struct command_digest *digest;
+ debug_decl(new_digest, SUDOERS_DEBUG_PARSER);
+
+ if ((digest = malloc(sizeof(*digest))) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+
+ HLTQ_INIT(digest, entries);
+ digest->digest_type = digest_type;
+ digest->digest_str = digest_str;
+ if (digest->digest_str == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ free(digest);
+ digest = NULL;
+ }
+
+ debug_return_ptr(digest);
+}
+
+static void
+free_defaults_binding(struct defaults_binding *binding)
+{
+ debug_decl(free_defaults_binding, SUDOERS_DEBUG_PARSER);
+
+ /* Bindings may be shared among multiple Defaults entries. */
+ if (binding != NULL) {
+ if (--binding->refcnt == 0) {
+ free_members(&binding->members);
+ free(binding);
+ }
+ }
+
+ debug_return;
+}
+
+/*
+ * Add a list of defaults structures to the defaults list.
+ * The bmem argument, if non-NULL, specifies a list of hosts, users,
+ * or runas users the entries apply to (determined by the type).
+ */
+static bool
+add_defaults(short type, struct member *bmem, struct defaults *defs)
+{
+ struct defaults *d, *next;
+ struct defaults_binding *binding;
+ bool ret = true;
+ debug_decl(add_defaults, SUDOERS_DEBUG_PARSER);
+
+ if (defs == NULL)
+ debug_return_bool(false);
+
+ /*
+ * We use a single binding for each entry in defs.
+ */
+ if ((binding = malloc(sizeof(*binding))) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ sudoerserror(N_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ if (bmem != NULL) {
+ parser_leak_remove(LEAK_MEMBER, bmem);
+ HLTQ_TO_TAILQ(&binding->members, bmem, entries);
+ } else {
+ TAILQ_INIT(&binding->members);
+ }
+ binding->refcnt = 0;
+
+ /*
+ * Set type and binding (who it applies to) for new entries.
+ * Then add to the global defaults list.
+ */
+ parser_leak_remove(LEAK_DEFAULTS, defs);
+ HLTQ_FOREACH_SAFE(d, defs, entries, next) {
+ d->type = type;
+ d->binding = binding;
+ binding->refcnt++;
+ TAILQ_INSERT_TAIL(&parsed_policy.defaults, d, entries);
+ }
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Allocate a new struct userspec, populate it, and insert it at the
+ * end of the userspecs list.
+ */
+static bool
+add_userspec(struct member *members, struct privilege *privs)
+{
+ struct userspec *u;
+ debug_decl(add_userspec, SUDOERS_DEBUG_PARSER);
+
+ if ((u = calloc(1, sizeof(*u))) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_bool(false);
+ }
+ /* We already parsed the newline so sudolineno is off by one. */
+ u->line = sudolineno - 1;
+ u->column = (int)(sudolinebuf.toke_start + 1);
+ u->file = sudo_rcstr_addref(sudoers);
+ parser_leak_remove(LEAK_MEMBER, members);
+ HLTQ_TO_TAILQ(&u->users, members, entries);
+ parser_leak_remove(LEAK_PRIVILEGE, privs);
+ HLTQ_TO_TAILQ(&u->privileges, privs, entries);
+ STAILQ_INIT(&u->comments);
+ TAILQ_INSERT_TAIL(&parsed_policy.userspecs, u, entries);
+
+ debug_return_bool(true);
+}
+
+/*
+ * Free a member struct and its contents.
+ */
+void
+free_member(struct member *m)
+{
+ debug_decl(free_member, SUDOERS_DEBUG_PARSER);
+
+ if (m->type == COMMAND || (m->type == ALL && m->name != NULL)) {
+ struct command_digest *digest;
+ struct sudo_command *c = (struct sudo_command *)m->name;
+ free(c->cmnd);
+ free(c->args);
+ while ((digest = TAILQ_FIRST(&c->digests)) != NULL) {
+ TAILQ_REMOVE(&c->digests, digest, entries);
+ free(digest->digest_str);
+ free(digest);
+ }
+ }
+ free(m->name);
+ free(m);
+
+ debug_return;
+}
+
+/*
+ * Free a tailq of members but not the struct member_list container itself.
+ */
+void
+free_members(struct member_list *members)
+{
+ struct member *m;
+ debug_decl(free_members, SUDOERS_DEBUG_PARSER);
+
+ while ((m = TAILQ_FIRST(members)) != NULL) {
+ TAILQ_REMOVE(members, m, entries);
+ free_member(m);
+ }
+
+ debug_return;
+}
+
+void
+free_defaults(struct defaults_list *defs)
+{
+ struct defaults *def;
+ debug_decl(free_defaults, SUDOERS_DEBUG_PARSER);
+
+ while ((def = TAILQ_FIRST(defs)) != NULL) {
+ TAILQ_REMOVE(defs, def, entries);
+ free_default(def);
+ }
+
+ debug_return;
+}
+
+void
+free_default(struct defaults *def)
+{
+ debug_decl(free_default, SUDOERS_DEBUG_PARSER);
+
+ free_defaults_binding(def->binding);
+ sudo_rcstr_delref(def->file);
+ free(def->var);
+ free(def->val);
+ free(def);
+
+ debug_return;
+}
+
+void
+free_cmndspec(struct cmndspec *cs, struct cmndspec_list *csl)
+{
+ struct cmndspec *prev, *next;
+ debug_decl(free_cmndspec, SUDOERS_DEBUG_PARSER);
+
+ prev = TAILQ_PREV(cs, cmndspec_list, entries);
+ next = TAILQ_NEXT(cs, entries);
+ TAILQ_REMOVE(csl, cs, entries);
+
+ /* Don't free runcwd/runchroot that are in use by other entries. */
+ if ((prev == NULL || cs->runcwd != prev->runcwd) &&
+ (next == NULL || cs->runcwd != next->runcwd)) {
+ free(cs->runcwd);
+ }
+ if ((prev == NULL || cs->runchroot != prev->runchroot) &&
+ (next == NULL || cs->runchroot != next->runchroot)) {
+ free(cs->runchroot);
+ }
+#ifdef HAVE_SELINUX
+ /* Don't free root/type that are in use by other entries. */
+ if ((prev == NULL || cs->role != prev->role) &&
+ (next == NULL || cs->role != next->role)) {
+ free(cs->role);
+ }
+ if ((prev == NULL || cs->type != prev->type) &&
+ (next == NULL || cs->type != next->type)) {
+ free(cs->type);
+ }
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_PRIV_SET
+ /* Don't free privs/limitprivs that are in use by other entries. */
+ if ((prev == NULL || cs->privs != prev->privs) &&
+ (next == NULL || cs->privs != next->privs)) {
+ free(cs->privs);
+ }
+ if ((prev == NULL || cs->limitprivs != prev->limitprivs) &&
+ (next == NULL || cs->limitprivs != next->limitprivs)) {
+ free(cs->limitprivs);
+ }
+#endif /* HAVE_PRIV_SET */
+ /* Don't free user/group lists that are in use by other entries. */
+ if (cs->runasuserlist != NULL) {
+ if ((prev == NULL || cs->runasuserlist != prev->runasuserlist) &&
+ (next == NULL || cs->runasuserlist != next->runasuserlist)) {
+ free_members(cs->runasuserlist);
+ free(cs->runasuserlist);
+ }
+ }
+ if (cs->runasgrouplist != NULL) {
+ if ((prev == NULL || cs->runasgrouplist != prev->runasgrouplist) &&
+ (next == NULL || cs->runasgrouplist != next->runasgrouplist)) {
+ free_members(cs->runasgrouplist);
+ free(cs->runasgrouplist);
+ }
+ }
+ free_member(cs->cmnd);
+ free(cs);
+
+ debug_return;
+}
+
+void
+free_cmndspecs(struct cmndspec_list *csl)
+{
+ struct member_list *runasuserlist = NULL, *runasgrouplist = NULL;
+ char *runcwd = NULL, *runchroot = NULL;
+#ifdef HAVE_SELINUX
+ char *role = NULL, *type = NULL;
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_PRIV_SET
+ char *privs = NULL, *limitprivs = NULL;
+#endif /* HAVE_PRIV_SET */
+ struct cmndspec *cs;
+ debug_decl(free_cmndspecs, SUDOERS_DEBUG_PARSER);
+
+ while ((cs = TAILQ_FIRST(csl)) != NULL) {
+ TAILQ_REMOVE(csl, cs, entries);
+
+ /* Only free the first instance of runcwd/runchroot. */
+ if (cs->runcwd != runcwd) {
+ runcwd = cs->runcwd;
+ free(cs->runcwd);
+ }
+ if (cs->runchroot != runchroot) {
+ runchroot = cs->runchroot;
+ free(cs->runchroot);
+ }
+#ifdef HAVE_SELINUX
+ /* Only free the first instance of a role/type. */
+ if (cs->role != role) {
+ role = cs->role;
+ free(cs->role);
+ }
+ if (cs->type != type) {
+ type = cs->type;
+ free(cs->type);
+ }
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_PRIV_SET
+ /* Only free the first instance of privs/limitprivs. */
+ if (cs->privs != privs) {
+ privs = cs->privs;
+ free(cs->privs);
+ }
+ if (cs->limitprivs != limitprivs) {
+ limitprivs = cs->limitprivs;
+ free(cs->limitprivs);
+ }
+#endif /* HAVE_PRIV_SET */
+ /* Only free the first instance of runas user/group lists. */
+ if (cs->runasuserlist && cs->runasuserlist != runasuserlist) {
+ runasuserlist = cs->runasuserlist;
+ free_members(runasuserlist);
+ free(runasuserlist);
+ }
+ if (cs->runasgrouplist && cs->runasgrouplist != runasgrouplist) {
+ runasgrouplist = cs->runasgrouplist;
+ free_members(runasgrouplist);
+ free(runasgrouplist);
+ }
+ free_member(cs->cmnd);
+ free(cs);
+ }
+
+ debug_return;
+}
+
+void
+free_privilege(struct privilege *priv)
+{
+ struct defaults *def;
+ debug_decl(free_privilege, SUDOERS_DEBUG_PARSER);
+
+ free(priv->ldap_role);
+ free_members(&priv->hostlist);
+ free_cmndspecs(&priv->cmndlist);
+ while ((def = TAILQ_FIRST(&priv->defaults)) != NULL) {
+ TAILQ_REMOVE(&priv->defaults, def, entries);
+ free_default(def);
+ }
+ free(priv);
+
+ debug_return;
+}
+
+void
+free_userspecs(struct userspec_list *usl)
+{
+ struct userspec *us;
+ debug_decl(free_userspecs, SUDOERS_DEBUG_PARSER);
+
+ while ((us = TAILQ_FIRST(usl)) != NULL) {
+ TAILQ_REMOVE(usl, us, entries);
+ free_userspec(us);
+ }
+
+ debug_return;
+}
+
+void
+free_userspec(struct userspec *us)
+{
+ struct privilege *priv;
+ struct sudoers_comment *comment;
+ debug_decl(free_userspec, SUDOERS_DEBUG_PARSER);
+
+ free_members(&us->users);
+ while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) {
+ TAILQ_REMOVE(&us->privileges, priv, entries);
+ free_privilege(priv);
+ }
+ while ((comment = STAILQ_FIRST(&us->comments)) != NULL) {
+ STAILQ_REMOVE_HEAD(&us->comments, entries);
+ free(comment->str);
+ free(comment);
+ }
+ sudo_rcstr_delref(us->file);
+ free(us);
+
+ debug_return;
+}
+
+/*
+ * Initialized a sudoers parse tree.
+ * Takes ownership of lhost and shost.
+ */
+void
+init_parse_tree(struct sudoers_parse_tree *parse_tree, char *lhost, char *shost,
+ struct sudoers_context *ctx, struct sudo_nss *nss)
+{
+ TAILQ_INIT(&parse_tree->userspecs);
+ TAILQ_INIT(&parse_tree->defaults);
+ parse_tree->aliases = NULL;
+ parse_tree->shost = shost;
+ parse_tree->lhost = lhost;
+ parse_tree->ctx = ctx;
+ parse_tree->nss = nss;
+}
+
+/*
+ * Move the contents of parsed_policy to new_tree.
+ */
+void
+reparent_parse_tree(struct sudoers_parse_tree *new_tree)
+{
+ TAILQ_CONCAT(&new_tree->userspecs, &parsed_policy.userspecs, entries);
+ TAILQ_CONCAT(&new_tree->defaults, &parsed_policy.defaults, entries);
+ new_tree->aliases = parsed_policy.aliases;
+ parsed_policy.aliases = NULL;
+}
+
+/*
+ * Free the contents of a sudoers parse tree and initialize it.
+ */
+void
+free_parse_tree(struct sudoers_parse_tree *parse_tree)
+{
+ free_userspecs(&parse_tree->userspecs);
+ free_defaults(&parse_tree->defaults);
+ free_aliases(parse_tree->aliases);
+ parse_tree->aliases = NULL;
+ free(parse_tree->lhost);
+ if (parse_tree->shost != parse_tree->lhost)
+ free(parse_tree->shost);
+ parse_tree->lhost = parse_tree->shost = NULL;
+ parse_tree->nss = NULL;
+ parse_tree->ctx = NULL;
+}
+
+/*
+ * Free up space used by data structures from a previous parser run and sets
+ * the current sudoers file to path.
+ */
+bool
+init_parser(struct sudoers_context *ctx, const char *file)
+{
+ bool ret = true;
+ debug_decl(init_parser, SUDOERS_DEBUG_PARSER);
+
+ free_parse_tree(&parsed_policy);
+ parsed_policy.ctx = ctx;
+ parser_leak_init();
+ init_lexer();
+ parse_error = false;
+
+ if (ctx != NULL) {
+ parser_conf = ctx->parser_conf;
+ } else {
+ const struct sudoers_parser_config def_conf =
+ SUDOERS_PARSER_CONFIG_INITIALIZER;
+ parser_conf = def_conf;
+ }
+
+ sudo_rcstr_delref(sudoers);
+ if (file != NULL) {
+ if ((sudoers = sudo_rcstr_dup(file)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ ret = false;
+ }
+ } else {
+ sudoers = NULL;
+ }
+
+ sudo_rcstr_delref(sudoers_search_path);
+ if (parser_conf.sudoers_path != NULL) {
+ sudoers_search_path = sudo_rcstr_dup(parser_conf.sudoers_path);
+ if (sudoers_search_path == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ ret = false;
+ }
+ } else {
+ sudoers_search_path = NULL;
+ }
+
+ debug_return_bool(ret);
+}
+
+bool
+reset_parser(void)
+{
+ return init_parser(NULL, NULL);
+}
+
+/*
+ * Initialize all options in a cmndspec.
+ */
+static void
+init_options(struct command_options *opts)
+{
+ opts->notbefore = UNSPEC;
+ opts->notafter = UNSPEC;
+ opts->timeout = UNSPEC;
+ opts->runchroot = NULL;
+ opts->runcwd = NULL;
+#ifdef HAVE_SELINUX
+ opts->role = NULL;
+ opts->type = NULL;
+#endif
+#ifdef HAVE_PRIV_SET
+ opts->privs = NULL;
+ opts->limitprivs = NULL;
+#endif
+#ifdef HAVE_APPARMOR
+ opts->apparmor_profile = NULL;
+#endif
+}
+
+uid_t
+sudoers_file_uid(void)
+{
+ return parser_conf.sudoers_uid;
+}
+
+gid_t
+sudoers_file_gid(void)
+{
+ return parser_conf.sudoers_gid;
+}
+
+mode_t
+sudoers_file_mode(void)
+{
+ return parser_conf.sudoers_mode;
+}
+
+bool
+sudoers_error_recovery(void)
+{
+ return parser_conf.recovery;
+}
+
+bool
+sudoers_strict(void)
+{
+ return parser_conf.strict;
+}
+
+bool
+parser_leak_add(enum parser_leak_types type, void *v)
+{
+#ifdef NO_LEAKS
+ struct parser_leak_entry *entry;
+ debug_decl(parser_leak_add, SUDOERS_DEBUG_PARSER);
+
+ if (v == NULL)
+ debug_return_bool(false);
+
+ entry = calloc(1, sizeof(*entry));
+ if (entry == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ switch (type) {
+ case LEAK_PRIVILEGE:
+ entry->u.p = v;
+ break;
+ case LEAK_CMNDSPEC:
+ entry->u.cs = v;
+ break;
+ case LEAK_DEFAULTS:
+ entry->u.d = v;
+ break;
+ case LEAK_MEMBER:
+ entry->u.m = v;
+ break;
+ case LEAK_DIGEST:
+ entry->u.dig = v;
+ break;
+ case LEAK_RUNAS:
+ entry->u.rc = v;
+ break;
+ case LEAK_PTR:
+ entry->u.ptr = v;
+ break;
+ default:
+ free(entry);
+ sudo_warnx("unexpected leak type %d", type);
+ debug_return_bool(false);
+ }
+ entry->type = type;
+ SLIST_INSERT_HEAD(&parser_leak_list, entry, entries);
+ debug_return_bool(true);
+#else
+ return true;
+#endif /* NO_LEAKS */
+}
+
+bool
+parser_leak_remove(enum parser_leak_types type, void *v)
+{
+#ifdef NO_LEAKS
+ struct parser_leak_entry *entry, *prev = NULL;
+ debug_decl(parser_leak_remove, SUDOERS_DEBUG_PARSER);
+
+ if (v == NULL)
+ debug_return_bool(false);
+
+ SLIST_FOREACH(entry, &parser_leak_list, entries) {
+ switch (entry->type) {
+ case LEAK_PRIVILEGE:
+ if (entry->u.p == v)
+ goto found;
+ break;
+ case LEAK_CMNDSPEC:
+ if (entry->u.cs == v)
+ goto found;
+ break;
+ case LEAK_DEFAULTS:
+ if (entry->u.d == v)
+ goto found;
+ break;
+ case LEAK_MEMBER:
+ if (entry->u.m == v)
+ goto found;
+ break;
+ case LEAK_DIGEST:
+ if (entry->u.dig == v)
+ goto found;
+ break;
+ case LEAK_RUNAS:
+ if (entry->u.rc == v)
+ goto found;
+ break;
+ case LEAK_PTR:
+ if (entry->u.ptr == v)
+ goto found;
+ break;
+ default:
+ sudo_warnx("unexpected leak type %d in %p", entry->type, entry);
+ }
+ prev = entry;
+ }
+ /* If this happens, there is a bug in the leak tracking code. */
+ sudo_warnx("%s: unable to find %p, type %d", __func__, v, type);
+ debug_return_bool(false);
+found:
+ if (prev == NULL)
+ SLIST_REMOVE_HEAD(&parser_leak_list, entries);
+ else
+ SLIST_REMOVE_AFTER(prev, entries);
+ free(entry);
+ debug_return_bool(true);
+#else
+ return true;
+#endif /* NO_LEAKS */
+}
+
+#ifdef NO_LEAKS
+static void
+parser_leak_free(void)
+{
+ struct parser_leak_entry *entry;
+ void *next;
+ debug_decl(parser_leak_run, SUDOERS_DEBUG_PARSER);
+
+ /* Free the leaks. */
+ while ((entry = SLIST_FIRST(&parser_leak_list))) {
+ SLIST_REMOVE_HEAD(&parser_leak_list, entries);
+ switch (entry->type) {
+ case LEAK_PRIVILEGE:
+ {
+ struct privilege *priv;
+
+ HLTQ_FOREACH_SAFE(priv, entry->u.p, entries, next)
+ free_privilege(priv);
+ free(entry);
+ }
+ break;
+ case LEAK_CMNDSPEC:
+ {
+ struct cmndspec_list specs;
+
+ HLTQ_TO_TAILQ(&specs, entry->u.cs, entries);
+ free_cmndspecs(&specs);
+ free(entry);
+ }
+ break;
+ case LEAK_DEFAULTS:
+ {
+ struct defaults_list defs;
+
+ HLTQ_TO_TAILQ(&defs, entry->u.d, entries);
+ free_defaults(&defs);
+ free(entry);
+ }
+ break;
+ case LEAK_MEMBER:
+ {
+ struct member *m;
+
+ HLTQ_FOREACH_SAFE(m, entry->u.m, entries, next)
+ free_member(m);
+ free(entry);
+ }
+ break;
+ case LEAK_DIGEST:
+ {
+ struct command_digest *dig;
+
+ HLTQ_FOREACH_SAFE(dig, entry->u.dig, entries, next) {
+ free(dig->digest_str);
+ free(dig);
+ }
+ free(entry);
+ }
+ break;
+ case LEAK_RUNAS:
+ {
+ struct member *m;
+
+ if (entry->u.rc->runasusers != NULL) {
+ HLTQ_FOREACH_SAFE(m, entry->u.rc->runasusers, entries, next)
+ free_member(m);
+ }
+ if (entry->u.rc->runasgroups != NULL) {
+ HLTQ_FOREACH_SAFE(m, entry->u.rc->runasgroups, entries, next)
+ free_member(m);
+ }
+ free(entry->u.rc);
+ free(entry);
+ break;
+ }
+ case LEAK_PTR:
+ free(entry->u.ptr);
+ free(entry);
+ break;
+ default:
+ sudo_warnx("unexpected garbage type %d", entry->type);
+ }
+ }
+
+ debug_return;
+}
+#endif /* NO_LEAKS */
+
+void
+parser_leak_init(void)
+{
+#ifdef NO_LEAKS
+ static bool initialized;
+ debug_decl(parser_leak_init, SUDOERS_DEBUG_PARSER);
+
+ if (!initialized) {
+ atexit(parser_leak_free);
+ initialized = true;
+ debug_return;
+ }
+
+ /* Already initialized, free existing leaks. */
+ parser_leak_free();
+ debug_return;
+#endif /* NO_LEAKS */
+}
diff --git a/plugins/sudoers/gram.h b/plugins/sudoers/gram.h
new file mode 100644
index 0000000..23dd52a
--- /dev/null
+++ b/plugins/sudoers/gram.h
@@ -0,0 +1,206 @@
+/* A Bison parser, made by GNU Bison 3.8.2. */
+
+/* Bison interface for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
+ Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
+ especially those whose name start with YY_ or yy_. They are
+ private implementation details that can be changed or removed. */
+
+#ifndef YY_SUDOERS_Y_TAB_H_INCLUDED
+# define YY_SUDOERS_Y_TAB_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int sudoersdebug;
+#endif
+
+/* Token kinds. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ YYEMPTY = -2,
+ YYEOF = 0, /* "end of file" */
+ YYerror = 256, /* error */
+ YYUNDEF = 257, /* "invalid token" */
+ COMMAND = 258, /* COMMAND */
+ ALIAS = 259, /* ALIAS */
+ DEFVAR = 260, /* DEFVAR */
+ NTWKADDR = 261, /* NTWKADDR */
+ NETGROUP = 262, /* NETGROUP */
+ USERGROUP = 263, /* USERGROUP */
+ WORD = 264, /* WORD */
+ DIGEST = 265, /* DIGEST */
+ INCLUDE = 266, /* INCLUDE */
+ INCLUDEDIR = 267, /* INCLUDEDIR */
+ DEFAULTS = 268, /* DEFAULTS */
+ DEFAULTS_HOST = 269, /* DEFAULTS_HOST */
+ DEFAULTS_USER = 270, /* DEFAULTS_USER */
+ DEFAULTS_RUNAS = 271, /* DEFAULTS_RUNAS */
+ DEFAULTS_CMND = 272, /* DEFAULTS_CMND */
+ NOPASSWD = 273, /* NOPASSWD */
+ PASSWD = 274, /* PASSWD */
+ NOEXEC = 275, /* NOEXEC */
+ EXEC = 276, /* EXEC */
+ SETENV = 277, /* SETENV */
+ NOSETENV = 278, /* NOSETENV */
+ LOG_INPUT = 279, /* LOG_INPUT */
+ NOLOG_INPUT = 280, /* NOLOG_INPUT */
+ LOG_OUTPUT = 281, /* LOG_OUTPUT */
+ NOLOG_OUTPUT = 282, /* NOLOG_OUTPUT */
+ MAIL = 283, /* MAIL */
+ NOMAIL = 284, /* NOMAIL */
+ FOLLOWLNK = 285, /* FOLLOWLNK */
+ NOFOLLOWLNK = 286, /* NOFOLLOWLNK */
+ INTERCEPT = 287, /* INTERCEPT */
+ NOINTERCEPT = 288, /* NOINTERCEPT */
+ ALL = 289, /* ALL */
+ HOSTALIAS = 290, /* HOSTALIAS */
+ CMNDALIAS = 291, /* CMNDALIAS */
+ USERALIAS = 292, /* USERALIAS */
+ RUNASALIAS = 293, /* RUNASALIAS */
+ ERROR = 294, /* ERROR */
+ NOMATCH = 295, /* NOMATCH */
+ CHROOT = 296, /* CHROOT */
+ CWD = 297, /* CWD */
+ TYPE = 298, /* TYPE */
+ ROLE = 299, /* ROLE */
+ APPARMOR_PROFILE = 300, /* APPARMOR_PROFILE */
+ PRIVS = 301, /* PRIVS */
+ LIMITPRIVS = 302, /* LIMITPRIVS */
+ CMND_TIMEOUT = 303, /* CMND_TIMEOUT */
+ NOTBEFORE = 304, /* NOTBEFORE */
+ NOTAFTER = 305, /* NOTAFTER */
+ MYSELF = 306, /* MYSELF */
+ SHA224_TOK = 307, /* SHA224_TOK */
+ SHA256_TOK = 308, /* SHA256_TOK */
+ SHA384_TOK = 309, /* SHA384_TOK */
+ SHA512_TOK = 310 /* SHA512_TOK */
+ };
+ typedef enum yytokentype yytoken_kind_t;
+#endif
+/* Token kinds. */
+#define YYEMPTY -2
+#define YYEOF 0
+#define YYerror 256
+#define YYUNDEF 257
+#define COMMAND 258
+#define ALIAS 259
+#define DEFVAR 260
+#define NTWKADDR 261
+#define NETGROUP 262
+#define USERGROUP 263
+#define WORD 264
+#define DIGEST 265
+#define INCLUDE 266
+#define INCLUDEDIR 267
+#define DEFAULTS 268
+#define DEFAULTS_HOST 269
+#define DEFAULTS_USER 270
+#define DEFAULTS_RUNAS 271
+#define DEFAULTS_CMND 272
+#define NOPASSWD 273
+#define PASSWD 274
+#define NOEXEC 275
+#define EXEC 276
+#define SETENV 277
+#define NOSETENV 278
+#define LOG_INPUT 279
+#define NOLOG_INPUT 280
+#define LOG_OUTPUT 281
+#define NOLOG_OUTPUT 282
+#define MAIL 283
+#define NOMAIL 284
+#define FOLLOWLNK 285
+#define NOFOLLOWLNK 286
+#define INTERCEPT 287
+#define NOINTERCEPT 288
+#define ALL 289
+#define HOSTALIAS 290
+#define CMNDALIAS 291
+#define USERALIAS 292
+#define RUNASALIAS 293
+#define ERROR 294
+#define NOMATCH 295
+#define CHROOT 296
+#define CWD 297
+#define TYPE 298
+#define ROLE 299
+#define APPARMOR_PROFILE 300
+#define PRIVS 301
+#define LIMITPRIVS 302
+#define CMND_TIMEOUT 303
+#define NOTBEFORE 304
+#define NOTAFTER 305
+#define MYSELF 306
+#define SHA224_TOK 307
+#define SHA256_TOK 308
+#define SHA384_TOK 309
+#define SHA512_TOK 310
+
+/* Value type. */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+union YYSTYPE
+{
+#line 90 "gram.y"
+
+ struct cmndspec *cmndspec;
+ struct defaults *defaults;
+ struct member *member;
+ struct runascontainer *runas;
+ struct privilege *privilege;
+ struct command_digest *digest;
+ struct sudo_command command;
+ struct command_options options;
+ struct cmndtag tag;
+ char *string;
+ const char *cstring;
+ int tok;
+
+#line 192 "gram.h"
+
+};
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+extern YYSTYPE sudoerslval;
+
+
+int sudoersparse (void);
+
+
+#endif /* !YY_SUDOERS_Y_TAB_H_INCLUDED */
diff --git a/plugins/sudoers/gram.y b/plugins/sudoers/gram.y
new file mode 100644
index 0000000..85ad240
--- /dev/null
+++ b/plugins/sudoers/gram.y
@@ -0,0 +1,2125 @@
+%{
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2007-2013, 2014-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sudoers.h>
+#include <sudo_digest.h>
+#include <toke.h>
+
+#ifdef YYBISON
+# define YYERROR_VERBOSE
+#endif
+
+/* If we last saw a newline the entry is on the preceding line. */
+#define this_lineno (sudoerschar == '\n' ? sudolineno - 1 : sudolineno)
+
+// PVS Studio suppression
+// -V::560, 592, 1037, 1042
+
+/*
+ * Globals
+ */
+bool parse_error = false;
+
+static struct sudoers_parser_config parser_conf =
+ SUDOERS_PARSER_CONFIG_INITIALIZER;
+
+/* Optional logging function for parse errors. */
+sudoers_logger_t sudoers_error_hook;
+
+static int alias_line, alias_column;
+
+#ifdef NO_LEAKS
+static struct parser_leak_list parser_leak_list =
+ SLIST_HEAD_INITIALIZER(parser_leak_list);
+#endif
+
+struct sudoers_parse_tree parsed_policy = {
+ { NULL, NULL }, /* entries */
+ TAILQ_HEAD_INITIALIZER(parsed_policy.userspecs),
+ TAILQ_HEAD_INITIALIZER(parsed_policy.defaults),
+ NULL, /* aliases */
+ NULL, /* lhost */
+ NULL, /* shost */
+ NULL, /* nss */
+ NULL /* ctx */
+};
+
+/*
+ * Local prototypes
+ */
+static void init_options(struct command_options *opts);
+static bool add_defaults(short, struct member *, struct defaults *);
+static bool add_userspec(struct member *, struct privilege *);
+static struct defaults *new_default(char *, char *, short);
+static struct member *new_member(char *, short);
+static struct sudo_command *new_command(char *, char *);
+static struct command_digest *new_digest(unsigned int, char *);
+static void alias_error(const char *name, int errnum);
+%}
+
+%union {
+ struct cmndspec *cmndspec;
+ struct defaults *defaults;
+ struct member *member;
+ struct runascontainer *runas;
+ struct privilege *privilege;
+ struct command_digest *digest;
+ struct sudo_command command;
+ struct command_options options;
+ struct cmndtag tag;
+ char *string;
+ const char *cstring;
+ int tok;
+}
+
+%start file /* special start symbol */
+%token <command> COMMAND /* absolute pathname w/ optional args */
+%token <string> ALIAS /* an UPPERCASE alias name */
+%token <string> DEFVAR /* a Defaults variable name */
+%token <string> NTWKADDR /* ipv4 or ipv6 address */
+%token <string> NETGROUP /* a netgroup (+NAME) */
+%token <string> USERGROUP /* a usergroup (%NAME) */
+%token <string> WORD /* a word */
+%token <string> DIGEST /* a SHA-2 digest */
+%token <tok> INCLUDE /* @include */
+%token <tok> INCLUDEDIR /* @includedir */
+%token <tok> DEFAULTS /* Defaults entry */
+%token <tok> DEFAULTS_HOST /* Host-specific defaults entry */
+%token <tok> DEFAULTS_USER /* User-specific defaults entry */
+%token <tok> DEFAULTS_RUNAS /* Runas-specific defaults entry */
+%token <tok> DEFAULTS_CMND /* Command-specific defaults entry */
+%token <tok> NOPASSWD /* no passwd req for command */
+%token <tok> PASSWD /* passwd req for command (default) */
+%token <tok> NOEXEC /* preload fake execve() for cmnd */
+%token <tok> EXEC /* don't preload fake execve() */
+%token <tok> SETENV /* user may set environment for cmnd */
+%token <tok> NOSETENV /* user may not set environment */
+%token <tok> LOG_INPUT /* log user's cmnd input */
+%token <tok> NOLOG_INPUT /* don't log user's cmnd input */
+%token <tok> LOG_OUTPUT /* log cmnd output */
+%token <tok> NOLOG_OUTPUT /* don't log cmnd output */
+%token <tok> MAIL /* mail log message */
+%token <tok> NOMAIL /* don't mail log message */
+%token <tok> FOLLOWLNK /* follow symbolic links */
+%token <tok> NOFOLLOWLNK /* don't follow symbolic links */
+%token <tok> INTERCEPT /* intercept children of command */
+%token <tok> NOINTERCEPT /* disable intercepting of children */
+%token <tok> ALL /* ALL keyword */
+%token <tok> HOSTALIAS /* Host_Alias keyword */
+%token <tok> CMNDALIAS /* Cmnd_Alias keyword */
+%token <tok> USERALIAS /* User_Alias keyword */
+%token <tok> RUNASALIAS /* Runas_Alias keyword */
+%token <tok> ':' '=' ',' '!' '+' '-' /* union member tokens */
+%token <tok> '(' ')' /* runas tokens */
+%token <tok> '\n' /* newline (with optional comment) */
+%token <tok> ERROR /* error from lexer */
+%token <tok> NOMATCH /* no match from lexer */
+%token <tok> CHROOT /* root directory for command */
+%token <tok> CWD /* working directory for command */
+%token <tok> TYPE /* SELinux type */
+%token <tok> ROLE /* SELinux role */
+%token <tok> APPARMOR_PROFILE /* AppArmor profile */
+%token <tok> PRIVS /* Solaris privileges */
+%token <tok> LIMITPRIVS /* Solaris limit privileges */
+%token <tok> CMND_TIMEOUT /* command timeout */
+%token <tok> NOTBEFORE /* time restriction */
+%token <tok> NOTAFTER /* time restriction */
+%token <tok> MYSELF /* run as myself, not another user */
+%token <tok> SHA224_TOK /* sha224 token */
+%token <tok> SHA256_TOK /* sha256 token */
+%token <tok> SHA384_TOK /* sha384 token */
+%token <tok> SHA512_TOK /* sha512 token */
+
+%type <cmndspec> cmndspec
+%type <cmndspec> cmndspeclist
+%type <defaults> defaults_entry
+%type <defaults> defaults_list
+%type <member> cmnd
+%type <member> opcmnd
+%type <member> digcmnd
+%type <member> cmndlist
+%type <member> host
+%type <member> hostlist
+%type <member> ophost
+%type <member> opuser
+%type <member> user
+%type <member> userlist
+%type <member> opgroup
+%type <member> group
+%type <member> grouplist
+%type <runas> runasspec
+%type <runas> runaslist
+%type <privilege> privilege
+%type <privilege> privileges
+%type <tag> cmndtag
+%type <options> options
+%type <string> chdirspec
+%type <string> chrootspec
+%type <string> rolespec
+%type <string> typespec
+%type <string> apparmor_profilespec
+%type <string> privsspec
+%type <string> limitprivsspec
+%type <string> timeoutspec
+%type <string> notbeforespec
+%type <string> notafterspec
+%type <string> include
+%type <string> includedir
+%type <digest> digestspec
+%type <digest> digestlist
+%type <cstring> reserved_word
+
+%%
+
+file : {
+ ; /* empty file */
+ }
+ | line
+ ;
+
+line : entry
+ | line entry
+ ;
+
+entry : '\n' {
+ ; /* blank line */
+ }
+ | error '\n' {
+ yyerrok;
+ }
+ | include {
+ const bool success = push_include($1,
+ parsed_policy.ctx->user.shost, &parser_conf);
+ parser_leak_remove(LEAK_PTR, $1);
+ free($1);
+ if (!success && !parser_conf.recovery)
+ YYERROR;
+ }
+ | includedir {
+ const bool success = push_includedir($1,
+ parsed_policy.ctx->user.shost, &parser_conf);
+ parser_leak_remove(LEAK_PTR, $1);
+ free($1);
+ if (!success && !parser_conf.recovery)
+ YYERROR;
+ }
+ | userlist privileges '\n' {
+ if (!add_userspec($1, $2)) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ }
+ | USERALIAS useraliases '\n' {
+ ;
+ }
+ | HOSTALIAS hostaliases '\n' {
+ ;
+ }
+ | CMNDALIAS cmndaliases '\n' {
+ ;
+ }
+ | RUNASALIAS runasaliases '\n' {
+ ;
+ }
+ | DEFAULTS defaults_list '\n' {
+ if (!add_defaults(DEFAULTS, NULL, $2))
+ YYERROR;
+ }
+ | DEFAULTS_USER userlist defaults_list '\n' {
+ if (!add_defaults(DEFAULTS_USER, $2, $3))
+ YYERROR;
+ }
+ | DEFAULTS_RUNAS userlist defaults_list '\n' {
+ if (!add_defaults(DEFAULTS_RUNAS, $2, $3))
+ YYERROR;
+ }
+ | DEFAULTS_HOST hostlist defaults_list '\n' {
+ if (!add_defaults(DEFAULTS_HOST, $2, $3))
+ YYERROR;
+ }
+ | DEFAULTS_CMND cmndlist defaults_list '\n' {
+ if (!add_defaults(DEFAULTS_CMND, $2, $3))
+ YYERROR;
+ }
+ ;
+
+include : INCLUDE WORD '\n' {
+ $$ = $2;
+ }
+ | INCLUDE WORD error '\n' {
+ yyerrok;
+ $$ = $2;
+ }
+ ;
+
+includedir : INCLUDEDIR WORD '\n' {
+ $$ = $2;
+ }
+ | INCLUDEDIR WORD error '\n' {
+ yyerrok;
+ $$ = $2;
+ }
+ ;
+
+defaults_list : defaults_entry
+ | defaults_list ',' defaults_entry {
+ parser_leak_remove(LEAK_DEFAULTS, $3);
+ HLTQ_CONCAT($1, $3, entries);
+ $$ = $1;
+ }
+ ;
+
+defaults_entry : DEFVAR {
+ $$ = new_default($1, NULL, true);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_add(LEAK_DEFAULTS, $$);
+ }
+ | '!' DEFVAR {
+ $$ = new_default($2, NULL, false);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $2);
+ parser_leak_add(LEAK_DEFAULTS, $$);
+ }
+ | DEFVAR '=' WORD {
+ $$ = new_default($1, $3, true);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_remove(LEAK_PTR, $3);
+ parser_leak_add(LEAK_DEFAULTS, $$);
+ }
+ | DEFVAR '+' WORD {
+ $$ = new_default($1, $3, '+');
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_remove(LEAK_PTR, $3);
+ parser_leak_add(LEAK_DEFAULTS, $$);
+ }
+ | DEFVAR '-' WORD {
+ $$ = new_default($1, $3, '-');
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_remove(LEAK_PTR, $3);
+ parser_leak_add(LEAK_DEFAULTS, $$);
+ }
+ ;
+
+privileges : privilege
+ | privileges ':' privilege {
+ parser_leak_remove(LEAK_PRIVILEGE, $3);
+ HLTQ_CONCAT($1, $3, entries);
+ $$ = $1;
+ }
+ | privileges ':' error {
+ yyerrok;
+ $$ = $1;
+ }
+ ;
+
+privilege : hostlist '=' cmndspeclist {
+ struct privilege *p = calloc(1, sizeof(*p));
+ if (p == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_PRIVILEGE, p);
+ TAILQ_INIT(&p->defaults);
+ parser_leak_remove(LEAK_MEMBER, $1);
+ HLTQ_TO_TAILQ(&p->hostlist, $1, entries);
+ parser_leak_remove(LEAK_CMNDSPEC, $3);
+ HLTQ_TO_TAILQ(&p->cmndlist, $3, entries);
+ HLTQ_INIT(p, entries);
+ $$ = p;
+ }
+ ;
+
+ophost : host {
+ $$ = $1;
+ $$->negated = false;
+ }
+ | '!' host {
+ $$ = $2;
+ $$->negated = true;
+ }
+ ;
+
+host : ALIAS {
+ $$ = new_member($1, ALIAS);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_add(LEAK_MEMBER, $$);
+ }
+ | ALL {
+ $$ = new_member(NULL, ALL);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_MEMBER, $$);
+ }
+ | NETGROUP {
+ $$ = new_member($1, NETGROUP);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_add(LEAK_MEMBER, $$);
+ }
+ | NTWKADDR {
+ $$ = new_member($1, NTWKADDR);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_add(LEAK_MEMBER, $$);
+ }
+ | WORD {
+ $$ = new_member($1, WORD);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_add(LEAK_MEMBER, $$);
+ }
+ ;
+
+cmndspeclist : cmndspec
+ | cmndspeclist ',' cmndspec {
+ struct cmndspec *prev;
+ prev = HLTQ_LAST($1, cmndspec, entries);
+ parser_leak_remove(LEAK_CMNDSPEC, $3);
+ HLTQ_CONCAT($1, $3, entries);
+
+ /* propagate runcwd and runchroot */
+ if ($3->runcwd == NULL)
+ $3->runcwd = prev->runcwd;
+ if ($3->runchroot == NULL)
+ $3->runchroot = prev->runchroot;
+#ifdef HAVE_SELINUX
+ /* propagate role and type */
+ if ($3->role == NULL && $3->type == NULL) {
+ $3->role = prev->role;
+ $3->type = prev->type;
+ }
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_PRIV_SET
+ /* propagate privs & limitprivs */
+ if ($3->privs == NULL && $3->limitprivs == NULL) {
+ $3->privs = prev->privs;
+ $3->limitprivs = prev->limitprivs;
+ }
+#endif /* HAVE_PRIV_SET */
+ /* propagate command time restrictions */
+ if ($3->notbefore == UNSPEC)
+ $3->notbefore = prev->notbefore;
+ if ($3->notafter == UNSPEC)
+ $3->notafter = prev->notafter;
+ /* propagate command timeout */
+ if ($3->timeout == UNSPEC)
+ $3->timeout = prev->timeout;
+ /* propagate tags and runas list */
+ if ($3->tags.nopasswd == UNSPEC)
+ $3->tags.nopasswd = prev->tags.nopasswd;
+ if ($3->tags.noexec == UNSPEC)
+ $3->tags.noexec = prev->tags.noexec;
+ if ($3->tags.intercept == UNSPEC)
+ $3->tags.intercept = prev->tags.intercept;
+ if ($3->tags.setenv == UNSPEC &&
+ prev->tags.setenv != IMPLIED)
+ $3->tags.setenv = prev->tags.setenv;
+ if ($3->tags.log_input == UNSPEC)
+ $3->tags.log_input = prev->tags.log_input;
+ if ($3->tags.log_output == UNSPEC)
+ $3->tags.log_output = prev->tags.log_output;
+ if ($3->tags.send_mail == UNSPEC)
+ $3->tags.send_mail = prev->tags.send_mail;
+ if ($3->tags.follow == UNSPEC)
+ $3->tags.follow = prev->tags.follow;
+ if (($3->runasuserlist == NULL &&
+ $3->runasgrouplist == NULL) &&
+ (prev->runasuserlist != NULL ||
+ prev->runasgrouplist != NULL)) {
+ $3->runasuserlist = prev->runasuserlist;
+ $3->runasgrouplist = prev->runasgrouplist;
+ }
+ $$ = $1;
+ }
+ ;
+
+cmndspec : runasspec options cmndtag digcmnd {
+ struct cmndspec *cs = calloc(1, sizeof(*cs));
+ if (cs == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_CMNDSPEC, cs);
+ if ($1 != NULL) {
+ if ($1->runasusers != NULL) {
+ cs->runasuserlist =
+ malloc(sizeof(*cs->runasuserlist));
+ if (cs->runasuserlist == NULL) {
+ free(cs);
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ /* g/c done via runas container */
+ HLTQ_TO_TAILQ(cs->runasuserlist,
+ $1->runasusers, entries);
+ }
+ if ($1->runasgroups != NULL) {
+ cs->runasgrouplist =
+ malloc(sizeof(*cs->runasgrouplist));
+ if (cs->runasgrouplist == NULL) {
+ free(cs);
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ /* g/c done via runas container */
+ HLTQ_TO_TAILQ(cs->runasgrouplist,
+ $1->runasgroups, entries);
+ }
+ parser_leak_remove(LEAK_RUNAS, $1);
+ free($1);
+ }
+#ifdef HAVE_SELINUX
+ cs->role = $2.role;
+ parser_leak_remove(LEAK_PTR, $2.role);
+ cs->type = $2.type;
+ parser_leak_remove(LEAK_PTR, $2.type);
+#endif
+#ifdef HAVE_APPARMOR
+ cs->apparmor_profile = $2.apparmor_profile;
+ parser_leak_remove(LEAK_PTR, $2.apparmor_profile);
+#endif
+#ifdef HAVE_PRIV_SET
+ cs->privs = $2.privs;
+ parser_leak_remove(LEAK_PTR, $2.privs);
+ cs->limitprivs = $2.limitprivs;
+ parser_leak_remove(LEAK_PTR, $2.limitprivs);
+#endif
+ cs->notbefore = $2.notbefore;
+ cs->notafter = $2.notafter;
+ cs->timeout = $2.timeout;
+ cs->runcwd = $2.runcwd;
+ parser_leak_remove(LEAK_PTR, $2.runcwd);
+ cs->runchroot = $2.runchroot;
+ parser_leak_remove(LEAK_PTR, $2.runchroot);
+ cs->tags = $3;
+ cs->cmnd = $4;
+ parser_leak_remove(LEAK_MEMBER, $4);
+ HLTQ_INIT(cs, entries);
+ /* sudo "ALL" implies the SETENV tag */
+ if (cs->cmnd->type == ALL && !cs->cmnd->negated &&
+ cs->tags.setenv == UNSPEC)
+ cs->tags.setenv = IMPLIED;
+ $$ = cs;
+ }
+ ;
+
+digestspec : SHA224_TOK ':' DIGEST {
+ $$ = new_digest(SUDO_DIGEST_SHA224, $3);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $3);
+ parser_leak_add(LEAK_DIGEST, $$);
+ }
+ | SHA256_TOK ':' DIGEST {
+ $$ = new_digest(SUDO_DIGEST_SHA256, $3);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $3);
+ parser_leak_add(LEAK_DIGEST, $$);
+ }
+ | SHA384_TOK ':' DIGEST {
+ $$ = new_digest(SUDO_DIGEST_SHA384, $3);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $3);
+ parser_leak_add(LEAK_DIGEST, $$);
+ }
+ | SHA512_TOK ':' DIGEST {
+ $$ = new_digest(SUDO_DIGEST_SHA512, $3);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $3);
+ parser_leak_add(LEAK_DIGEST, $$);
+ }
+ ;
+
+digestlist : digestspec
+ | digestlist ',' digestspec {
+ parser_leak_remove(LEAK_DIGEST, $3);
+ HLTQ_CONCAT($1, $3, entries);
+ $$ = $1;
+ }
+ ;
+
+digcmnd : opcmnd {
+ $$ = $1;
+ }
+ | digestlist opcmnd {
+ struct sudo_command *c =
+ (struct sudo_command *) $2->name;
+
+ if ($2->type != COMMAND && $2->type != ALL) {
+ sudoerserror(N_("a digest requires a path name"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_DIGEST, $1);
+ HLTQ_TO_TAILQ(&c->digests, $1, entries);
+ $$ = $2;
+ }
+ ;
+
+opcmnd : cmnd {
+ $$ = $1;
+ $$->negated = false;
+ }
+ | '!' cmnd {
+ $$ = $2;
+ $$->negated = true;
+ }
+ ;
+
+chdirspec : CWD '=' WORD {
+ if ($3[0] != '/' && $3[0] != '~') {
+ if (strcmp($3, "*") != 0) {
+ sudoerserror(N_("values for \"CWD\" must"
+ " start with a '/', '~', or '*'"));
+ YYERROR;
+ }
+ }
+ if (strlen($3) >= PATH_MAX) {
+ sudoerserror(N_("\"CWD\" path too long"));
+ YYERROR;
+ }
+ $$ = $3;
+ }
+ ;
+
+chrootspec : CHROOT '=' WORD {
+ if ($3[0] != '/' && $3[0] != '~') {
+ if (strcmp($3, "*") != 0) {
+ sudoerserror(N_("values for \"CHROOT\" must"
+ " start with a '/', '~', or '*'"));
+ YYERROR;
+ }
+ }
+ if (strlen($3) >= PATH_MAX) {
+ sudoerserror(N_("\"CHROOT\" path too long"));
+ YYERROR;
+ }
+ $$ = $3;
+ }
+ ;
+
+timeoutspec : CMND_TIMEOUT '=' WORD {
+ $$ = $3;
+ }
+ ;
+
+notbeforespec : NOTBEFORE '=' WORD {
+ $$ = $3;
+ }
+
+notafterspec : NOTAFTER '=' WORD {
+ $$ = $3;
+ }
+ ;
+
+rolespec : ROLE '=' WORD {
+ $$ = $3;
+ }
+ ;
+
+typespec : TYPE '=' WORD {
+ $$ = $3;
+ }
+ ;
+
+apparmor_profilespec : APPARMOR_PROFILE '=' WORD {
+ $$ = $3;
+ }
+ ;
+
+privsspec : PRIVS '=' WORD {
+ $$ = $3;
+ }
+ ;
+limitprivsspec : LIMITPRIVS '=' WORD {
+ $$ = $3;
+ }
+ ;
+
+runasspec : /* empty */ {
+ $$ = NULL;
+ }
+ | '(' runaslist ')' {
+ $$ = $2;
+ }
+ ;
+
+runaslist : /* empty */ {
+ /* User may run command as themselves. */
+ $$ = calloc(1, sizeof(struct runascontainer));
+ if ($$ != NULL) {
+ $$->runasusers = new_member(NULL, MYSELF);
+ /* $$->runasgroups = NULL; */
+ if ($$->runasusers == NULL) {
+ free($$);
+ $$ = NULL;
+ }
+ }
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_RUNAS, $$);
+ }
+ | userlist {
+ /* User may run command as a user in userlist. */
+ $$ = calloc(1, sizeof(struct runascontainer));
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_RUNAS, $$);
+ parser_leak_remove(LEAK_MEMBER, $1);
+ $$->runasusers = $1;
+ /* $$->runasgroups = NULL; */
+ }
+ | userlist ':' grouplist {
+ /*
+ * User may run command as a user in userlist
+ * and optionally as a group in grouplist.
+ */
+ $$ = calloc(1, sizeof(struct runascontainer));
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_RUNAS, $$);
+ parser_leak_remove(LEAK_MEMBER, $1);
+ parser_leak_remove(LEAK_MEMBER, $3);
+ $$->runasusers = $1;
+ $$->runasgroups = $3;
+ }
+ | ':' grouplist {
+ /* User may run command as a group in grouplist. */
+ $$ = calloc(1, sizeof(struct runascontainer));
+ if ($$ != NULL) {
+ $$->runasusers = new_member(NULL, MYSELF);
+ if ($$->runasusers == NULL) {
+ free($$);
+ $$ = NULL;
+ }
+ }
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_RUNAS, $$);
+ parser_leak_remove(LEAK_MEMBER, $2);
+ $$->runasgroups = $2;
+ }
+ | ':' {
+ /* User may run command as themselves. */
+ $$ = calloc(1, sizeof(struct runascontainer));
+ if ($$ != NULL) {
+ $$->runasusers = new_member(NULL, MYSELF);
+ /* $$->runasgroups = NULL; */
+ if ($$->runasusers == NULL) {
+ free($$);
+ $$ = NULL;
+ }
+ }
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_RUNAS, $$);
+ }
+ ;
+
+reserved_word : ALL { $$ = "ALL"; }
+ | CHROOT { $$ = "CHROOT"; }
+ | CWD { $$ = "CWD"; }
+ | CMND_TIMEOUT { $$ = "CMND_TIMEOUT"; }
+ | NOTBEFORE { $$ = "NOTBEFORE"; }
+ | NOTAFTER { $$ = "NOTAFTER"; }
+ | ROLE { $$ = "ROLE"; }
+ | TYPE { $$ = "TYPE"; }
+ | PRIVS { $$ = "PRIVS"; }
+ | LIMITPRIVS { $$ = "LIMITPRIVS"; }
+ | APPARMOR_PROFILE { $$ = "APPARMOR_PROFILE"; }
+ ;
+
+reserved_alias : reserved_word {
+ sudoerserrorf(U_("syntax error, reserved word %s used as an alias name"), $1);
+ YYERROR;
+ }
+ ;
+
+options : /* empty */ {
+ init_options(&$$);
+ }
+ | options chdirspec {
+ parser_leak_remove(LEAK_PTR, $$.runcwd);
+ free($$.runcwd);
+ $$.runcwd = $2;
+ }
+ | options chrootspec {
+ parser_leak_remove(LEAK_PTR, $$.runchroot);
+ free($$.runchroot);
+ $$.runchroot = $2;
+ }
+ | options notbeforespec {
+ $$.notbefore = parse_gentime($2);
+ parser_leak_remove(LEAK_PTR, $2);
+ free($2);
+ if ($$.notbefore == -1) {
+ sudoerserror(N_("invalid notbefore value"));
+ YYERROR;
+ }
+ }
+ | options notafterspec {
+ $$.notafter = parse_gentime($2);
+ parser_leak_remove(LEAK_PTR, $2);
+ free($2);
+ if ($$.notafter == -1) {
+ sudoerserror(N_("invalid notafter value"));
+ YYERROR;
+ }
+ }
+ | options timeoutspec {
+ $$.timeout = parse_timeout($2);
+ parser_leak_remove(LEAK_PTR, $2);
+ free($2);
+ if ($$.timeout == -1) {
+ if (errno == ERANGE)
+ sudoerserror(N_("timeout value too large"));
+ else
+ sudoerserror(N_("invalid timeout value"));
+ YYERROR;
+ }
+ }
+ | options rolespec {
+#ifdef HAVE_SELINUX
+ parser_leak_remove(LEAK_PTR, $$.role);
+ free($$.role);
+ $$.role = $2;
+#endif
+ }
+ | options typespec {
+#ifdef HAVE_SELINUX
+ parser_leak_remove(LEAK_PTR, $$.type);
+ free($$.type);
+ $$.type = $2;
+#endif
+ }
+ | options apparmor_profilespec {
+#ifdef HAVE_APPARMOR
+ parser_leak_remove(LEAK_PTR, $$.apparmor_profile);
+ free($$.apparmor_profile);
+ $$.apparmor_profile = $2;
+#endif
+ }
+ | options privsspec {
+#ifdef HAVE_PRIV_SET
+ parser_leak_remove(LEAK_PTR, $$.privs);
+ free($$.privs);
+ $$.privs = $2;
+#endif
+ }
+ | options limitprivsspec {
+#ifdef HAVE_PRIV_SET
+ parser_leak_remove(LEAK_PTR, $$.limitprivs);
+ free($$.limitprivs);
+ $$.limitprivs = $2;
+#endif
+ }
+ ;
+
+cmndtag : /* empty */ {
+ TAGS_INIT(&$$);
+ }
+ | cmndtag NOPASSWD {
+ $$.nopasswd = true;
+ }
+ | cmndtag PASSWD {
+ $$.nopasswd = false;
+ }
+ | cmndtag NOEXEC {
+ $$.noexec = true;
+ }
+ | cmndtag EXEC {
+ $$.noexec = false;
+ }
+ | cmndtag INTERCEPT {
+ $$.intercept = true;
+ }
+ | cmndtag NOINTERCEPT {
+ $$.intercept = false;
+ }
+ | cmndtag SETENV {
+ $$.setenv = true;
+ }
+ | cmndtag NOSETENV {
+ $$.setenv = false;
+ }
+ | cmndtag LOG_INPUT {
+ $$.log_input = true;
+ }
+ | cmndtag NOLOG_INPUT {
+ $$.log_input = false;
+ }
+ | cmndtag LOG_OUTPUT {
+ $$.log_output = true;
+ }
+ | cmndtag NOLOG_OUTPUT {
+ $$.log_output = false;
+ }
+ | cmndtag FOLLOWLNK {
+ $$.follow = true;
+ }
+ | cmndtag NOFOLLOWLNK {
+ $$.follow = false;
+ }
+ | cmndtag MAIL {
+ $$.send_mail = true;
+ }
+ | cmndtag NOMAIL {
+ $$.send_mail = false;
+ }
+ ;
+
+cmnd : ALL {
+ struct sudo_command *c;
+
+ if ((c = new_command(NULL, NULL)) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ $$ = new_member((char *)c, ALL);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_MEMBER, $$);
+ }
+ | ALIAS {
+ $$ = new_member($1, ALIAS);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_add(LEAK_MEMBER, $$);
+ }
+ | COMMAND {
+ struct sudo_command *c;
+
+ if (strlen($1.cmnd) >= PATH_MAX) {
+ sudoerserror(N_("command too long"));
+ YYERROR;
+ }
+ if ((c = new_command($1.cmnd, $1.args)) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ $$ = new_member((char *)c, COMMAND);
+ if ($$ == NULL) {
+ free(c);
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1.cmnd);
+ parser_leak_remove(LEAK_PTR, $1.args);
+ parser_leak_add(LEAK_MEMBER, $$);
+ }
+ | WORD {
+ if (strcmp($1, "list") == 0) {
+ struct sudo_command *c;
+
+ if ((c = new_command($1, NULL)) == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ $$ = new_member((char *)c, COMMAND);
+ if ($$ == NULL) {
+ free(c);
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_add(LEAK_MEMBER, $$);
+ } else {
+ sudoerserror(N_("expected a fully-qualified path name"));
+ YYERROR;
+ }
+ }
+ ;
+
+hostaliases : hostalias
+ | hostaliases ':' hostalias
+ ;
+
+hostalias : ALIAS {
+ alias_line = this_lineno;
+ alias_column = (int)sudolinebuf.toke_start + 1;
+ } '=' hostlist {
+ if (!alias_add(&parsed_policy, $1, HOSTALIAS,
+ sudoers, alias_line, alias_column, $4)) {
+ alias_error($1, errno);
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_remove(LEAK_MEMBER, $4);
+ }
+ | reserved_alias '=' hostlist
+ ;
+
+hostlist : ophost
+ | hostlist ',' ophost {
+ parser_leak_remove(LEAK_MEMBER, $3);
+ HLTQ_CONCAT($1, $3, entries);
+ $$ = $1;
+ }
+ ;
+
+cmndaliases : cmndalias
+ | cmndaliases ':' cmndalias
+ ;
+
+cmndalias : ALIAS {
+ alias_line = this_lineno;
+ alias_column = (int)sudolinebuf.toke_start + 1;
+ } '=' cmndlist {
+ if (!alias_add(&parsed_policy, $1, CMNDALIAS,
+ sudoers, alias_line, alias_column, $4)) {
+ alias_error($1, errno);
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_remove(LEAK_MEMBER, $4);
+ }
+ | reserved_alias '=' cmndlist
+ ;
+
+cmndlist : digcmnd
+ | cmndlist ',' digcmnd {
+ parser_leak_remove(LEAK_MEMBER, $3);
+ HLTQ_CONCAT($1, $3, entries);
+ $$ = $1;
+ }
+ ;
+
+runasaliases : runasalias
+ | runasaliases ':' runasalias
+ ;
+
+runasalias : ALIAS {
+ alias_line = this_lineno;
+ alias_column = (int)sudolinebuf.toke_start + 1;
+ } '=' userlist {
+ if (!alias_add(&parsed_policy, $1, RUNASALIAS,
+ sudoers, alias_line, alias_column, $4)) {
+ alias_error($1, errno);
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_remove(LEAK_MEMBER, $4);
+ }
+ | reserved_alias '=' userlist
+ ;
+
+useraliases : useralias
+ | useraliases ':' useralias
+ ;
+
+useralias : ALIAS {
+ alias_line = this_lineno;
+ alias_column = (int)sudolinebuf.toke_start + 1;
+ } '=' userlist {
+ if (!alias_add(&parsed_policy, $1, USERALIAS,
+ sudoers, alias_line, alias_column, $4)) {
+ alias_error($1, errno);
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_remove(LEAK_MEMBER, $4);
+ }
+ | reserved_alias '=' userlist
+ ;
+
+userlist : opuser
+ | userlist ',' opuser {
+ parser_leak_remove(LEAK_MEMBER, $3);
+ HLTQ_CONCAT($1, $3, entries);
+ $$ = $1;
+ }
+ ;
+
+opuser : user {
+ $$ = $1;
+ $$->negated = false;
+ }
+ | '!' user {
+ $$ = $2;
+ $$->negated = true;
+ }
+ ;
+
+user : ALIAS {
+ $$ = new_member($1, ALIAS);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_add(LEAK_MEMBER, $$);
+ }
+ | ALL {
+ $$ = new_member(NULL, ALL);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_MEMBER, $$);
+ }
+ | NETGROUP {
+ $$ = new_member($1, NETGROUP);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_add(LEAK_MEMBER, $$);
+ }
+ | USERGROUP {
+ $$ = new_member($1, USERGROUP);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_add(LEAK_MEMBER, $$);
+ }
+ | WORD {
+ $$ = new_member($1, WORD);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_add(LEAK_MEMBER, $$);
+ }
+ ;
+
+grouplist : opgroup
+ | grouplist ',' opgroup {
+ parser_leak_remove(LEAK_MEMBER, $3);
+ HLTQ_CONCAT($1, $3, entries);
+ $$ = $1;
+ }
+ ;
+
+opgroup : group {
+ $$ = $1;
+ $$->negated = false;
+ }
+ | '!' group {
+ $$ = $2;
+ $$->negated = true;
+ }
+ ;
+
+group : ALIAS {
+ $$ = new_member($1, ALIAS);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_add(LEAK_MEMBER, $$);
+ }
+ | ALL {
+ $$ = new_member(NULL, ALL);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_add(LEAK_MEMBER, $$);
+ }
+ | WORD {
+ $$ = new_member($1, WORD);
+ if ($$ == NULL) {
+ sudoerserror(N_("unable to allocate memory"));
+ YYERROR;
+ }
+ parser_leak_remove(LEAK_PTR, $1);
+ parser_leak_add(LEAK_MEMBER, $$);
+ }
+ ;
+%%
+/* Like yyerror() but takes a printf-style format string. */
+void
+sudoerserrorf(const char * restrict fmt, ...)
+{
+ const int column = (int)(sudolinebuf.toke_start + 1);
+ va_list ap;
+ debug_decl(sudoerserrorf, SUDOERS_DEBUG_PARSER);
+
+ if (sudoers_error_hook != NULL) {
+ va_start(ap, fmt);
+ sudoers_error_hook(parsed_policy.ctx, sudoers, this_lineno, column,
+ fmt, ap);
+ va_end(ap);
+ }
+ if (parser_conf.verbose > 0 && fmt != NULL) {
+ LEXTRACE("<*> ");
+#ifndef TRACELEXER
+ if (trace_print == NULL || trace_print == sudoers_trace_print) {
+ char *tofree = NULL;
+ const char *s;
+ int oldlocale;
+
+ /* Warnings are displayed in the user's locale. */
+ sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale);
+
+ va_start(ap, fmt);
+ if (strcmp(fmt, "%s") == 0) {
+ /* Optimize common case, a single string. */
+ s = _(va_arg(ap, char *));
+ } else {
+ if (vasprintf(&tofree, _(fmt), ap) != -1) {
+ s = tofree;
+ } else {
+ s = _("syntax error");
+ tofree = NULL;
+ }
+ }
+ sudo_printf(SUDO_CONV_ERROR_MSG, _("%s:%d:%zu: %s\n"), sudoers,
+ this_lineno, sudolinebuf.toke_start + 1, s);
+ free(tofree);
+ va_end(ap);
+ sudoers_setlocale(oldlocale, NULL);
+
+ /* Display the offending line and token if possible. */
+ if (sudolinebuf.len != 0) {
+ char tildes[128];
+ size_t tlen = 0;
+
+ sudo_printf(SUDO_CONV_ERROR_MSG, "%s%s", sudolinebuf.buf,
+ sudolinebuf.buf[sudolinebuf.len - 1] == '\n' ? "" : "\n");
+ if (sudolinebuf.toke_end > sudolinebuf.toke_start) {
+ tlen = sudolinebuf.toke_end - sudolinebuf.toke_start - 1;
+ if (tlen >= sizeof(tildes))
+ tlen = sizeof(tildes) - 1;
+ memset(tildes, '~', tlen);
+ }
+ tildes[tlen] = '\0';
+ sudo_printf(SUDO_CONV_ERROR_MSG, "%*s^%s\n",
+ (int)sudolinebuf.toke_start, "", tildes);
+ }
+ }
+#endif
+ }
+ parse_error = true;
+ debug_return;
+}
+
+void
+sudoerserror(const char *s)
+{
+ if (sudoerschar == ERROR) {
+ /* Use error string from lexer. */
+ s = sudoers_errstr;
+ sudoers_errstr = NULL;
+ }
+
+#pragma pvs(push)
+#pragma pvs(disable: 575, 618)
+
+ if (s == NULL)
+ sudoerserrorf(NULL);
+ else
+ sudoerserrorf("%s", s);
+
+#pragma pvs(pop)
+}
+
+static void
+alias_error(const char *name, int errnum)
+{
+ if (errnum == EEXIST)
+ sudoerserrorf(U_("Alias \"%s\" already defined"), name);
+ else
+ sudoerserror(N_("unable to allocate memory"));
+}
+
+static struct defaults *
+new_default(char *var, char *val, short op)
+{
+ struct defaults *d;
+ debug_decl(new_default, SUDOERS_DEBUG_PARSER);
+
+ if ((d = calloc(1, sizeof(struct defaults))) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+
+ d->var = var;
+ d->val = val;
+ /* d->type = 0; */
+ d->op = op;
+ /* d->binding = NULL; */
+ d->line = this_lineno;
+ d->column = (int)(sudolinebuf.toke_start + 1);
+ d->file = sudo_rcstr_addref(sudoers);
+ HLTQ_INIT(d, entries);
+
+ debug_return_ptr(d);
+}
+
+static struct member *
+new_member(char *name, short type)
+{
+ struct member *m;
+ debug_decl(new_member, SUDOERS_DEBUG_PARSER);
+
+ if ((m = calloc(1, sizeof(struct member))) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+
+ m->name = name;
+ m->type = type;
+ HLTQ_INIT(m, entries);
+
+ debug_return_ptr(m);
+}
+
+static struct sudo_command *
+new_command(char *cmnd, char *args)
+{
+ struct sudo_command *c;
+ debug_decl(new_command, SUDOERS_DEBUG_PARSER);
+
+ if ((c = calloc(1, sizeof(*c))) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+ /* garbage collected as part of struct member */
+
+ c->cmnd = cmnd;
+ c->args = args;
+ TAILQ_INIT(&c->digests);
+
+ debug_return_ptr(c);
+}
+
+static struct command_digest *
+new_digest(unsigned int digest_type, char *digest_str)
+{
+ struct command_digest *digest;
+ debug_decl(new_digest, SUDOERS_DEBUG_PARSER);
+
+ if ((digest = malloc(sizeof(*digest))) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+
+ HLTQ_INIT(digest, entries);
+ digest->digest_type = digest_type;
+ digest->digest_str = digest_str;
+ if (digest->digest_str == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ free(digest);
+ digest = NULL;
+ }
+
+ debug_return_ptr(digest);
+}
+
+static void
+free_defaults_binding(struct defaults_binding *binding)
+{
+ debug_decl(free_defaults_binding, SUDOERS_DEBUG_PARSER);
+
+ /* Bindings may be shared among multiple Defaults entries. */
+ if (binding != NULL) {
+ if (--binding->refcnt == 0) {
+ free_members(&binding->members);
+ free(binding);
+ }
+ }
+
+ debug_return;
+}
+
+/*
+ * Add a list of defaults structures to the defaults list.
+ * The bmem argument, if non-NULL, specifies a list of hosts, users,
+ * or runas users the entries apply to (determined by the type).
+ */
+static bool
+add_defaults(short type, struct member *bmem, struct defaults *defs)
+{
+ struct defaults *d, *next;
+ struct defaults_binding *binding;
+ bool ret = true;
+ debug_decl(add_defaults, SUDOERS_DEBUG_PARSER);
+
+ if (defs == NULL)
+ debug_return_bool(false);
+
+ /*
+ * We use a single binding for each entry in defs.
+ */
+ if ((binding = malloc(sizeof(*binding))) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ sudoerserror(N_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ if (bmem != NULL) {
+ parser_leak_remove(LEAK_MEMBER, bmem);
+ HLTQ_TO_TAILQ(&binding->members, bmem, entries);
+ } else {
+ TAILQ_INIT(&binding->members);
+ }
+ binding->refcnt = 0;
+
+ /*
+ * Set type and binding (who it applies to) for new entries.
+ * Then add to the global defaults list.
+ */
+ parser_leak_remove(LEAK_DEFAULTS, defs);
+ HLTQ_FOREACH_SAFE(d, defs, entries, next) {
+ d->type = type;
+ d->binding = binding;
+ binding->refcnt++;
+ TAILQ_INSERT_TAIL(&parsed_policy.defaults, d, entries);
+ }
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Allocate a new struct userspec, populate it, and insert it at the
+ * end of the userspecs list.
+ */
+static bool
+add_userspec(struct member *members, struct privilege *privs)
+{
+ struct userspec *u;
+ debug_decl(add_userspec, SUDOERS_DEBUG_PARSER);
+
+ if ((u = calloc(1, sizeof(*u))) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_bool(false);
+ }
+ /* We already parsed the newline so sudolineno is off by one. */
+ u->line = sudolineno - 1;
+ u->column = (int)(sudolinebuf.toke_start + 1);
+ u->file = sudo_rcstr_addref(sudoers);
+ parser_leak_remove(LEAK_MEMBER, members);
+ HLTQ_TO_TAILQ(&u->users, members, entries);
+ parser_leak_remove(LEAK_PRIVILEGE, privs);
+ HLTQ_TO_TAILQ(&u->privileges, privs, entries);
+ STAILQ_INIT(&u->comments);
+ TAILQ_INSERT_TAIL(&parsed_policy.userspecs, u, entries);
+
+ debug_return_bool(true);
+}
+
+/*
+ * Free a member struct and its contents.
+ */
+void
+free_member(struct member *m)
+{
+ debug_decl(free_member, SUDOERS_DEBUG_PARSER);
+
+ if (m->type == COMMAND || (m->type == ALL && m->name != NULL)) {
+ struct command_digest *digest;
+ struct sudo_command *c = (struct sudo_command *)m->name;
+ free(c->cmnd);
+ free(c->args);
+ while ((digest = TAILQ_FIRST(&c->digests)) != NULL) {
+ TAILQ_REMOVE(&c->digests, digest, entries);
+ free(digest->digest_str);
+ free(digest);
+ }
+ }
+ free(m->name);
+ free(m);
+
+ debug_return;
+}
+
+/*
+ * Free a tailq of members but not the struct member_list container itself.
+ */
+void
+free_members(struct member_list *members)
+{
+ struct member *m;
+ debug_decl(free_members, SUDOERS_DEBUG_PARSER);
+
+ while ((m = TAILQ_FIRST(members)) != NULL) {
+ TAILQ_REMOVE(members, m, entries);
+ free_member(m);
+ }
+
+ debug_return;
+}
+
+void
+free_defaults(struct defaults_list *defs)
+{
+ struct defaults *def;
+ debug_decl(free_defaults, SUDOERS_DEBUG_PARSER);
+
+ while ((def = TAILQ_FIRST(defs)) != NULL) {
+ TAILQ_REMOVE(defs, def, entries);
+ free_default(def);
+ }
+
+ debug_return;
+}
+
+void
+free_default(struct defaults *def)
+{
+ debug_decl(free_default, SUDOERS_DEBUG_PARSER);
+
+ free_defaults_binding(def->binding);
+ sudo_rcstr_delref(def->file);
+ free(def->var);
+ free(def->val);
+ free(def);
+
+ debug_return;
+}
+
+void
+free_cmndspec(struct cmndspec *cs, struct cmndspec_list *csl)
+{
+ struct cmndspec *prev, *next;
+ debug_decl(free_cmndspec, SUDOERS_DEBUG_PARSER);
+
+ prev = TAILQ_PREV(cs, cmndspec_list, entries);
+ next = TAILQ_NEXT(cs, entries);
+ TAILQ_REMOVE(csl, cs, entries);
+
+ /* Don't free runcwd/runchroot that are in use by other entries. */
+ if ((prev == NULL || cs->runcwd != prev->runcwd) &&
+ (next == NULL || cs->runcwd != next->runcwd)) {
+ free(cs->runcwd);
+ }
+ if ((prev == NULL || cs->runchroot != prev->runchroot) &&
+ (next == NULL || cs->runchroot != next->runchroot)) {
+ free(cs->runchroot);
+ }
+#ifdef HAVE_SELINUX
+ /* Don't free root/type that are in use by other entries. */
+ if ((prev == NULL || cs->role != prev->role) &&
+ (next == NULL || cs->role != next->role)) {
+ free(cs->role);
+ }
+ if ((prev == NULL || cs->type != prev->type) &&
+ (next == NULL || cs->type != next->type)) {
+ free(cs->type);
+ }
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_PRIV_SET
+ /* Don't free privs/limitprivs that are in use by other entries. */
+ if ((prev == NULL || cs->privs != prev->privs) &&
+ (next == NULL || cs->privs != next->privs)) {
+ free(cs->privs);
+ }
+ if ((prev == NULL || cs->limitprivs != prev->limitprivs) &&
+ (next == NULL || cs->limitprivs != next->limitprivs)) {
+ free(cs->limitprivs);
+ }
+#endif /* HAVE_PRIV_SET */
+ /* Don't free user/group lists that are in use by other entries. */
+ if (cs->runasuserlist != NULL) {
+ if ((prev == NULL || cs->runasuserlist != prev->runasuserlist) &&
+ (next == NULL || cs->runasuserlist != next->runasuserlist)) {
+ free_members(cs->runasuserlist);
+ free(cs->runasuserlist);
+ }
+ }
+ if (cs->runasgrouplist != NULL) {
+ if ((prev == NULL || cs->runasgrouplist != prev->runasgrouplist) &&
+ (next == NULL || cs->runasgrouplist != next->runasgrouplist)) {
+ free_members(cs->runasgrouplist);
+ free(cs->runasgrouplist);
+ }
+ }
+ free_member(cs->cmnd);
+ free(cs);
+
+ debug_return;
+}
+
+void
+free_cmndspecs(struct cmndspec_list *csl)
+{
+ struct member_list *runasuserlist = NULL, *runasgrouplist = NULL;
+ char *runcwd = NULL, *runchroot = NULL;
+#ifdef HAVE_SELINUX
+ char *role = NULL, *type = NULL;
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_PRIV_SET
+ char *privs = NULL, *limitprivs = NULL;
+#endif /* HAVE_PRIV_SET */
+ struct cmndspec *cs;
+ debug_decl(free_cmndspecs, SUDOERS_DEBUG_PARSER);
+
+ while ((cs = TAILQ_FIRST(csl)) != NULL) {
+ TAILQ_REMOVE(csl, cs, entries);
+
+ /* Only free the first instance of runcwd/runchroot. */
+ if (cs->runcwd != runcwd) {
+ runcwd = cs->runcwd;
+ free(cs->runcwd);
+ }
+ if (cs->runchroot != runchroot) {
+ runchroot = cs->runchroot;
+ free(cs->runchroot);
+ }
+#ifdef HAVE_SELINUX
+ /* Only free the first instance of a role/type. */
+ if (cs->role != role) {
+ role = cs->role;
+ free(cs->role);
+ }
+ if (cs->type != type) {
+ type = cs->type;
+ free(cs->type);
+ }
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_PRIV_SET
+ /* Only free the first instance of privs/limitprivs. */
+ if (cs->privs != privs) {
+ privs = cs->privs;
+ free(cs->privs);
+ }
+ if (cs->limitprivs != limitprivs) {
+ limitprivs = cs->limitprivs;
+ free(cs->limitprivs);
+ }
+#endif /* HAVE_PRIV_SET */
+ /* Only free the first instance of runas user/group lists. */
+ if (cs->runasuserlist && cs->runasuserlist != runasuserlist) {
+ runasuserlist = cs->runasuserlist;
+ free_members(runasuserlist);
+ free(runasuserlist);
+ }
+ if (cs->runasgrouplist && cs->runasgrouplist != runasgrouplist) {
+ runasgrouplist = cs->runasgrouplist;
+ free_members(runasgrouplist);
+ free(runasgrouplist);
+ }
+ free_member(cs->cmnd);
+ free(cs);
+ }
+
+ debug_return;
+}
+
+void
+free_privilege(struct privilege *priv)
+{
+ struct defaults *def;
+ debug_decl(free_privilege, SUDOERS_DEBUG_PARSER);
+
+ free(priv->ldap_role);
+ free_members(&priv->hostlist);
+ free_cmndspecs(&priv->cmndlist);
+ while ((def = TAILQ_FIRST(&priv->defaults)) != NULL) {
+ TAILQ_REMOVE(&priv->defaults, def, entries);
+ free_default(def);
+ }
+ free(priv);
+
+ debug_return;
+}
+
+void
+free_userspecs(struct userspec_list *usl)
+{
+ struct userspec *us;
+ debug_decl(free_userspecs, SUDOERS_DEBUG_PARSER);
+
+ while ((us = TAILQ_FIRST(usl)) != NULL) {
+ TAILQ_REMOVE(usl, us, entries);
+ free_userspec(us);
+ }
+
+ debug_return;
+}
+
+void
+free_userspec(struct userspec *us)
+{
+ struct privilege *priv;
+ struct sudoers_comment *comment;
+ debug_decl(free_userspec, SUDOERS_DEBUG_PARSER);
+
+ free_members(&us->users);
+ while ((priv = TAILQ_FIRST(&us->privileges)) != NULL) {
+ TAILQ_REMOVE(&us->privileges, priv, entries);
+ free_privilege(priv);
+ }
+ while ((comment = STAILQ_FIRST(&us->comments)) != NULL) {
+ STAILQ_REMOVE_HEAD(&us->comments, entries);
+ free(comment->str);
+ free(comment);
+ }
+ sudo_rcstr_delref(us->file);
+ free(us);
+
+ debug_return;
+}
+
+/*
+ * Initialized a sudoers parse tree.
+ * Takes ownership of lhost and shost.
+ */
+void
+init_parse_tree(struct sudoers_parse_tree *parse_tree, char *lhost, char *shost,
+ struct sudoers_context *ctx, struct sudo_nss *nss)
+{
+ TAILQ_INIT(&parse_tree->userspecs);
+ TAILQ_INIT(&parse_tree->defaults);
+ parse_tree->aliases = NULL;
+ parse_tree->shost = shost;
+ parse_tree->lhost = lhost;
+ parse_tree->ctx = ctx;
+ parse_tree->nss = nss;
+}
+
+/*
+ * Move the contents of parsed_policy to new_tree.
+ */
+void
+reparent_parse_tree(struct sudoers_parse_tree *new_tree)
+{
+ TAILQ_CONCAT(&new_tree->userspecs, &parsed_policy.userspecs, entries);
+ TAILQ_CONCAT(&new_tree->defaults, &parsed_policy.defaults, entries);
+ new_tree->aliases = parsed_policy.aliases;
+ parsed_policy.aliases = NULL;
+}
+
+/*
+ * Free the contents of a sudoers parse tree and initialize it.
+ */
+void
+free_parse_tree(struct sudoers_parse_tree *parse_tree)
+{
+ free_userspecs(&parse_tree->userspecs);
+ free_defaults(&parse_tree->defaults);
+ free_aliases(parse_tree->aliases);
+ parse_tree->aliases = NULL;
+ free(parse_tree->lhost);
+ if (parse_tree->shost != parse_tree->lhost)
+ free(parse_tree->shost);
+ parse_tree->lhost = parse_tree->shost = NULL;
+ parse_tree->nss = NULL;
+ parse_tree->ctx = NULL;
+}
+
+/*
+ * Free up space used by data structures from a previous parser run and sets
+ * the current sudoers file to path.
+ */
+bool
+init_parser(struct sudoers_context *ctx, const char *file)
+{
+ bool ret = true;
+ debug_decl(init_parser, SUDOERS_DEBUG_PARSER);
+
+ free_parse_tree(&parsed_policy);
+ parsed_policy.ctx = ctx;
+ parser_leak_init();
+ init_lexer();
+ parse_error = false;
+
+ if (ctx != NULL) {
+ parser_conf = ctx->parser_conf;
+ } else {
+ const struct sudoers_parser_config def_conf =
+ SUDOERS_PARSER_CONFIG_INITIALIZER;
+ parser_conf = def_conf;
+ }
+
+ sudo_rcstr_delref(sudoers);
+ if (file != NULL) {
+ if ((sudoers = sudo_rcstr_dup(file)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ ret = false;
+ }
+ } else {
+ sudoers = NULL;
+ }
+
+ sudo_rcstr_delref(sudoers_search_path);
+ if (parser_conf.sudoers_path != NULL) {
+ sudoers_search_path = sudo_rcstr_dup(parser_conf.sudoers_path);
+ if (sudoers_search_path == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ ret = false;
+ }
+ } else {
+ sudoers_search_path = NULL;
+ }
+
+ debug_return_bool(ret);
+}
+
+bool
+reset_parser(void)
+{
+ return init_parser(NULL, NULL);
+}
+
+/*
+ * Initialize all options in a cmndspec.
+ */
+static void
+init_options(struct command_options *opts)
+{
+ opts->notbefore = UNSPEC;
+ opts->notafter = UNSPEC;
+ opts->timeout = UNSPEC;
+ opts->runchroot = NULL;
+ opts->runcwd = NULL;
+#ifdef HAVE_SELINUX
+ opts->role = NULL;
+ opts->type = NULL;
+#endif
+#ifdef HAVE_PRIV_SET
+ opts->privs = NULL;
+ opts->limitprivs = NULL;
+#endif
+#ifdef HAVE_APPARMOR
+ opts->apparmor_profile = NULL;
+#endif
+}
+
+uid_t
+sudoers_file_uid(void)
+{
+ return parser_conf.sudoers_uid;
+}
+
+gid_t
+sudoers_file_gid(void)
+{
+ return parser_conf.sudoers_gid;
+}
+
+mode_t
+sudoers_file_mode(void)
+{
+ return parser_conf.sudoers_mode;
+}
+
+bool
+sudoers_error_recovery(void)
+{
+ return parser_conf.recovery;
+}
+
+bool
+sudoers_strict(void)
+{
+ return parser_conf.strict;
+}
+
+bool
+parser_leak_add(enum parser_leak_types type, void *v)
+{
+#ifdef NO_LEAKS
+ struct parser_leak_entry *entry;
+ debug_decl(parser_leak_add, SUDOERS_DEBUG_PARSER);
+
+ if (v == NULL)
+ debug_return_bool(false);
+
+ entry = calloc(1, sizeof(*entry));
+ if (entry == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ switch (type) {
+ case LEAK_PRIVILEGE:
+ entry->u.p = v;
+ break;
+ case LEAK_CMNDSPEC:
+ entry->u.cs = v;
+ break;
+ case LEAK_DEFAULTS:
+ entry->u.d = v;
+ break;
+ case LEAK_MEMBER:
+ entry->u.m = v;
+ break;
+ case LEAK_DIGEST:
+ entry->u.dig = v;
+ break;
+ case LEAK_RUNAS:
+ entry->u.rc = v;
+ break;
+ case LEAK_PTR:
+ entry->u.ptr = v;
+ break;
+ default:
+ free(entry);
+ sudo_warnx("unexpected leak type %d", type);
+ debug_return_bool(false);
+ }
+ entry->type = type;
+ SLIST_INSERT_HEAD(&parser_leak_list, entry, entries);
+ debug_return_bool(true);
+#else
+ return true;
+#endif /* NO_LEAKS */
+}
+
+bool
+parser_leak_remove(enum parser_leak_types type, void *v)
+{
+#ifdef NO_LEAKS
+ struct parser_leak_entry *entry, *prev = NULL;
+ debug_decl(parser_leak_remove, SUDOERS_DEBUG_PARSER);
+
+ if (v == NULL)
+ debug_return_bool(false);
+
+ SLIST_FOREACH(entry, &parser_leak_list, entries) {
+ switch (entry->type) {
+ case LEAK_PRIVILEGE:
+ if (entry->u.p == v)
+ goto found;
+ break;
+ case LEAK_CMNDSPEC:
+ if (entry->u.cs == v)
+ goto found;
+ break;
+ case LEAK_DEFAULTS:
+ if (entry->u.d == v)
+ goto found;
+ break;
+ case LEAK_MEMBER:
+ if (entry->u.m == v)
+ goto found;
+ break;
+ case LEAK_DIGEST:
+ if (entry->u.dig == v)
+ goto found;
+ break;
+ case LEAK_RUNAS:
+ if (entry->u.rc == v)
+ goto found;
+ break;
+ case LEAK_PTR:
+ if (entry->u.ptr == v)
+ goto found;
+ break;
+ default:
+ sudo_warnx("unexpected leak type %d in %p", entry->type, entry);
+ }
+ prev = entry;
+ }
+ /* If this happens, there is a bug in the leak tracking code. */
+ sudo_warnx("%s: unable to find %p, type %d", __func__, v, type);
+ debug_return_bool(false);
+found:
+ if (prev == NULL)
+ SLIST_REMOVE_HEAD(&parser_leak_list, entries);
+ else
+ SLIST_REMOVE_AFTER(prev, entries);
+ free(entry);
+ debug_return_bool(true);
+#else
+ return true;
+#endif /* NO_LEAKS */
+}
+
+#ifdef NO_LEAKS
+static void
+parser_leak_free(void)
+{
+ struct parser_leak_entry *entry;
+ void *next;
+ debug_decl(parser_leak_run, SUDOERS_DEBUG_PARSER);
+
+ /* Free the leaks. */
+ while ((entry = SLIST_FIRST(&parser_leak_list))) {
+ SLIST_REMOVE_HEAD(&parser_leak_list, entries);
+ switch (entry->type) {
+ case LEAK_PRIVILEGE:
+ {
+ struct privilege *priv;
+
+ HLTQ_FOREACH_SAFE(priv, entry->u.p, entries, next)
+ free_privilege(priv);
+ free(entry);
+ }
+ break;
+ case LEAK_CMNDSPEC:
+ {
+ struct cmndspec_list specs;
+
+ HLTQ_TO_TAILQ(&specs, entry->u.cs, entries);
+ free_cmndspecs(&specs);
+ free(entry);
+ }
+ break;
+ case LEAK_DEFAULTS:
+ {
+ struct defaults_list defs;
+
+ HLTQ_TO_TAILQ(&defs, entry->u.d, entries);
+ free_defaults(&defs);
+ free(entry);
+ }
+ break;
+ case LEAK_MEMBER:
+ {
+ struct member *m;
+
+ HLTQ_FOREACH_SAFE(m, entry->u.m, entries, next)
+ free_member(m);
+ free(entry);
+ }
+ break;
+ case LEAK_DIGEST:
+ {
+ struct command_digest *dig;
+
+ HLTQ_FOREACH_SAFE(dig, entry->u.dig, entries, next) {
+ free(dig->digest_str);
+ free(dig);
+ }
+ free(entry);
+ }
+ break;
+ case LEAK_RUNAS:
+ {
+ struct member *m;
+
+ if (entry->u.rc->runasusers != NULL) {
+ HLTQ_FOREACH_SAFE(m, entry->u.rc->runasusers, entries, next)
+ free_member(m);
+ }
+ if (entry->u.rc->runasgroups != NULL) {
+ HLTQ_FOREACH_SAFE(m, entry->u.rc->runasgroups, entries, next)
+ free_member(m);
+ }
+ free(entry->u.rc);
+ free(entry);
+ break;
+ }
+ case LEAK_PTR:
+ free(entry->u.ptr);
+ free(entry);
+ break;
+ default:
+ sudo_warnx("unexpected garbage type %d", entry->type);
+ }
+ }
+
+ debug_return;
+}
+#endif /* NO_LEAKS */
+
+void
+parser_leak_init(void)
+{
+#ifdef NO_LEAKS
+ static bool initialized;
+ debug_decl(parser_leak_init, SUDOERS_DEBUG_PARSER);
+
+ if (!initialized) {
+ atexit(parser_leak_free);
+ initialized = true;
+ debug_return;
+ }
+
+ /* Already initialized, free existing leaks. */
+ parser_leak_free();
+ debug_return;
+#endif /* NO_LEAKS */
+}
diff --git a/plugins/sudoers/group_plugin.c b/plugins/sudoers/group_plugin.c
new file mode 100644
index 0000000..02e4b5f
--- /dev/null
+++ b/plugins/sudoers/group_plugin.c
@@ -0,0 +1,313 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2020, 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <sudoers.h>
+#include <sudo_dso.h>
+
+#if defined(HAVE_DLOPEN) || defined(HAVE_SHL_LOAD)
+
+static void *group_handle;
+static struct sudoers_group_plugin *group_plugin;
+
+/*
+ * Check for a fallback path when the original group plugin is not loadable.
+ * Returns true on success, rewriting path and filling in sb, else false.
+ */
+static bool
+group_plugin_fallback(char *path, size_t pathsize)
+{
+#if defined(__LP64__)
+ char newpath[PATH_MAX];
+ bool ret = false;
+ struct stat sb;
+ int len;
+ debug_decl(group_plugin_fallback, SUDOERS_DEBUG_UTIL);
+
+# if defined(__sun__) || defined(__linux__)
+ /*
+ * Solaris uses /lib/64 and /usr/lib/64 for 64-bit libraries.
+ * Linux may use /lib64 and /usr/lib64 for 64-bit libraries.
+ * If dirname(path) ends in /lib, try /lib/64 (Solaris) or /lib64 (Linux).
+ */
+# if defined(__sun__)
+ const char *lib64 = "lib/64";
+# else
+ const char *lib64 = "lib64";
+# endif
+ const char *base, *slash;
+ int dirlen;
+
+ slash = strrchr(path, '/');
+ if (slash == NULL) {
+ goto done;
+ }
+ base = slash + 1;
+
+ /* Collapse consecutive slashes. */
+ while (slash > path && slash[-1] == '/') {
+ slash--;
+ }
+
+ /* If directory ends in /lib/, try again with /lib/64/ or /lib64/. */
+ dirlen = (int)(slash - path);
+ if (dirlen < 4 || strncmp(slash - 4, "/lib", 4) != 0) {
+ goto done;
+ }
+ dirlen -= 4;
+ len = snprintf(newpath, sizeof(newpath), "%.*s/%s/%s", dirlen, path, lib64,
+ base);
+# else /* !__sun__ && !__linux__ */
+ /*
+ * Multilib not supported, check for a path of the form libfoo64.so.
+ */
+ const char *dot;
+ int plen;
+
+ dot = strrchr(path, '.');
+ if (dot == NULL) {
+ goto done;
+ }
+ plen = (int)(dot - path);
+
+ /* If basename(path) doesn't match libfoo64.so, try adding the 64. */
+ if (plen >= 2 && strncmp(dot - 2, "64", 2) == 0) {
+ goto done;
+ }
+ len = snprintf(newpath, sizeof(newpath), "%.*s64%s", plen, path, dot);
+# endif /* __sun__ || __linux__ */
+ if (len < 0 || len >= ssizeof(newpath)) {
+ errno = ENAMETOOLONG;
+ goto done;
+ }
+ if (stat(newpath, &sb) == -1) {
+ goto done;
+ }
+ if (strlcpy(path, newpath, pathsize) >= pathsize) {
+ errno = ENAMETOOLONG;
+ goto done;
+ }
+ ret = true;
+done:
+ debug_return_bool(ret);
+#else
+ return false;
+#endif /* __LP64__ */
+}
+
+/*
+ * Load the specified plugin and run its init function.
+ * Returns -1 if unable to open the plugin, else it returns
+ * the value from the plugin's init function.
+ */
+static int
+group_plugin_load(const struct sudoers_context *ctx, const char *plugin_info)
+{
+ const char *plugin_dir = ctx->settings.plugin_dir;
+ char *args, path[PATH_MAX];
+ char **argv = NULL;
+ int len, rc = -1;
+ bool retry = true;
+ debug_decl(group_plugin_load, SUDOERS_DEBUG_UTIL);
+
+ /*
+ * Fill in .so path and split out args (if any).
+ */
+ if ((args = strpbrk(plugin_info, " \t")) != NULL) {
+ len = snprintf(path, sizeof(path), "%s%.*s",
+ (*plugin_info != '/') ? plugin_dir : "",
+ (int)(args - plugin_info), plugin_info);
+ args++;
+ } else {
+ len = snprintf(path, sizeof(path), "%s%s",
+ (*plugin_info != '/') ? plugin_dir : "", plugin_info);
+ }
+ if (len < 0 || len >= ssizeof(path)) {
+ errno = ENAMETOOLONG;
+ sudo_warn("%s%s",
+ (*plugin_info != '/') ? plugin_dir : "", plugin_info);
+ goto done;
+ }
+
+ for (;;) {
+ group_handle = sudo_dso_load(path, SUDO_DSO_LAZY|SUDO_DSO_GLOBAL);
+ if (group_handle != NULL) {
+ break;
+ }
+
+ if (!retry || !group_plugin_fallback(path, sizeof(path))) {
+ const char *errstr = sudo_dso_strerror();
+ sudo_warnx(U_("unable to load %s: %s"), path,
+ errstr ? errstr : "unknown error");
+ goto done;
+ }
+
+ /* Retry once with the fallback path. */
+ retry = false;
+ }
+
+ /* Map in symbol from group plugin. */
+ group_plugin = sudo_dso_findsym(group_handle, "group_plugin");
+ if (group_plugin == NULL) {
+ sudo_warnx(U_("unable to find symbol \"group_plugin\" in %s"), path);
+ goto done;
+ }
+
+ if (SUDO_API_VERSION_GET_MAJOR(group_plugin->version) != GROUP_API_VERSION_MAJOR) {
+ sudo_warnx(U_("%s: incompatible group plugin major version %d, expected %d"),
+ path, SUDO_API_VERSION_GET_MAJOR(group_plugin->version),
+ GROUP_API_VERSION_MAJOR);
+ goto done;
+ }
+
+ /*
+ * Split args into a vector if specified.
+ */
+ if (args != NULL) {
+ int ac = 0;
+ bool wasblank = true;
+ char *cp, *last;
+
+ for (cp = args; *cp != '\0'; cp++) {
+ if (isblank((unsigned char)*cp)) {
+ wasblank = true;
+ } else if (wasblank) {
+ wasblank = false;
+ ac++;
+ }
+ }
+ if (ac != 0) {
+ argv = reallocarray(NULL, (size_t)ac + 1, sizeof(char *));
+ if (argv == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ goto done;
+ }
+ ac = 0;
+ cp = strtok_r(args, " \t", &last);
+ while (cp != NULL) {
+ argv[ac++] = cp;
+ cp = strtok_r(NULL, " \t", &last);
+ }
+ argv[ac] = NULL;
+ }
+ }
+
+ rc = (group_plugin->init)(GROUP_API_VERSION, sudo_printf, argv);
+
+done:
+ free(argv);
+
+ if (rc != true) {
+ if (group_handle != NULL) {
+ sudo_dso_unload(group_handle);
+ group_handle = NULL;
+ group_plugin = NULL;
+ }
+ }
+
+ debug_return_int(rc);
+}
+
+void
+group_plugin_unload(void)
+{
+ debug_decl(group_plugin_unload, SUDOERS_DEBUG_UTIL);
+
+ if (group_plugin != NULL) {
+ (group_plugin->cleanup)();
+ group_plugin = NULL;
+ }
+ if (group_handle != NULL) {
+ sudo_dso_unload(group_handle);
+ group_handle = NULL;
+ }
+ debug_return;
+}
+
+int
+group_plugin_query(const char *user, const char *group,
+ const struct passwd *pwd)
+{
+ debug_decl(group_plugin_query, SUDOERS_DEBUG_UTIL);
+
+ if (group_plugin == NULL)
+ debug_return_int(false);
+ debug_return_int((group_plugin->query)(user, group, pwd));
+}
+
+#else /* !HAVE_DLOPEN && !HAVE_SHL_LOAD */
+
+/*
+ * No loadable shared object support.
+ */
+
+static int
+group_plugin_load(const struct sudoers_context *ctx, const char *plugin_info)
+{
+ debug_decl(group_plugin_load, SUDOERS_DEBUG_UTIL);
+ debug_return_int(false);
+}
+
+void
+group_plugin_unload(void)
+{
+ debug_decl(group_plugin_unload, SUDOERS_DEBUG_UTIL);
+ debug_return;
+}
+
+int
+group_plugin_query(const char *user, const char *group,
+ const struct passwd *pwd)
+{
+ debug_decl(group_plugin_query, SUDOERS_DEBUG_UTIL);
+ debug_return_int(false);
+}
+
+#endif /* HAVE_DLOPEN || HAVE_SHL_LOAD */
+
+/*
+ * Group plugin sudoers callback.
+ */
+bool
+cb_group_plugin(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ bool rc = true;
+ debug_decl(cb_group_plugin, SUDOERS_DEBUG_PLUGIN);
+
+ /* Unload any existing group plugin before loading a new one. */
+ group_plugin_unload();
+ if (sd_un->str != NULL)
+ rc = group_plugin_load(ctx, sd_un->str);
+ debug_return_bool(rc);
+}
diff --git a/plugins/sudoers/ins_2001.h b/plugins/sudoers/ins_2001.h
new file mode 100644
index 0000000..d2ce989
--- /dev/null
+++ b/plugins/sudoers/ins_2001.h
@@ -0,0 +1,35 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998, 1999 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_INS_2001_H
+#define SUDOERS_INS_2001_H
+
+ /*
+ * HAL insults (paraphrased) from 2001.
+ */
+
+ "Just what do you think you're doing Dave?",
+ "It can only be attributed to human error.",
+ "That's something I cannot allow to happen.",
+ "My mind is going. I can feel it.",
+ "Sorry about this, I know it's a bit silly.",
+ "Take a stress pill and think things over.",
+ "This mission is too important for me to allow you to jeopardize it.",
+ "I feel much better now.",
+
+#endif /* SUDOERS_INS_2001_H */
diff --git a/plugins/sudoers/ins_classic.h b/plugins/sudoers/ins_classic.h
new file mode 100644
index 0000000..08d54d7
--- /dev/null
+++ b/plugins/sudoers/ins_classic.h
@@ -0,0 +1,39 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998, 1999 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_INS_CLASSIC_H
+#define SUDOERS_INS_CLASSIC_H
+
+ /*
+ * Insults from the original sudo(8).
+ */
+
+ "Wrong! You cheating scum!",
+#ifndef OFFENSIVE_INSULTS
+ "And you call yourself a Rocket Scientist!",
+#else
+ "No soap, honkie-lips.",
+#endif
+ "Where did you learn to type?",
+ "Are you on drugs?",
+ "My pet ferret can type better than you!",
+ "You type like i drive.",
+ "Do you think like you type?",
+ "Your mind just hasn't been the same since the electro-shock, has it?",
+
+#endif /* SUDOERS_INS_CLASSIC_H */
diff --git a/plugins/sudoers/ins_csops.h b/plugins/sudoers/ins_csops.h
new file mode 100644
index 0000000..fe66cfa
--- /dev/null
+++ b/plugins/sudoers/ins_csops.h
@@ -0,0 +1,41 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998, 1999, 2004
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_INS_CSOPS_H
+#define SUDOERS_INS_CSOPS_H
+
+ /*
+ * CSOps insults (may be site dependent).
+ */
+
+ "Maybe if you used more than just two fingers...",
+ "BOB says: You seem to have forgotten your passwd, enter another!",
+ "stty: unknown mode: doofus",
+ "I can't hear you -- I'm using the scrambler.",
+ "The more you drive -- the dumber you get.",
+#ifdef PC_INSULTS
+ "Listen, broccoli brains, I don't have time to listen to this trash.",
+#else
+ "Listen, burrito brains, I don't have time to listen to this trash.",
+#endif
+ "I've seen penguins that can type better than that.",
+ "Have you considered trying to match wits with a rutabaga?",
+ "You speak an infinite deal of nothing",
+
+#endif /* SUDOERS_INS_CSOPS_H */
diff --git a/plugins/sudoers/ins_goons.h b/plugins/sudoers/ins_goons.h
new file mode 100644
index 0000000..34df45b
--- /dev/null
+++ b/plugins/sudoers/ins_goons.h
@@ -0,0 +1,50 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998, 1999 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_INS_GOONS_H
+#define SUDOERS_INS_GOONS_H
+
+ /*
+ * Insults from the "Goon Show."
+ */
+
+ "You silly, twisted boy you.",
+ "He has fallen in the water!",
+ "We'll all be murdered in our beds!",
+ "You can't come in. Our tiger has got flu",
+ "I don't wish to know that.",
+ "What, what, what, what, what, what, what, what, what, what?",
+ "You can't get the wood, you know.",
+ "You'll starve!",
+ "... and it used to be so popular...",
+ "Pauses for audience applause, not a sausage",
+ "Hold it up to the light --- not a brain in sight!",
+ "Have a gorilla...",
+ "There must be cure for it!",
+ "There's a lot of it about, you know.",
+ "You do that again and see what happens...",
+ "Ying Tong Iddle I Po",
+ "Harm can come to a young lad like that!",
+ "And with that remarks folks, the case of the Crown vs yourself was proven.",
+ "Speak English you fool --- there are no subtitles in this scene.",
+ "You gotta go owwwww!",
+ "I have been called worse.",
+ "It's only your word against mine.",
+ "I think ... err ... I think ... I think I'll go home",
+
+#endif /* SUDOERS_INS_GOONS_H */
diff --git a/plugins/sudoers/ins_python.h b/plugins/sudoers/ins_python.h
new file mode 100644
index 0000000..16088f3
--- /dev/null
+++ b/plugins/sudoers/ins_python.h
@@ -0,0 +1,39 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_INS_PYTHON_H
+#define SUDOERS_INS_PYTHON_H
+
+ /*
+ * Insults from "Monty Python's Flying Circus" and family.
+ */
+
+ "That is no basis for supreme executive power!",
+ "You empty-headed animal food trough wiper!",
+ "I fart in your general direction!",
+ "Your mother was a hamster and your father smelt of elderberries!",
+ "You must cut down the mightiest tree in the forest... with... a herring!",
+ "I wave my private parts at your aunties!",
+ "He's not the Messiah, he's a very naughty boy!",
+ "I wish to make a complaint.",
+ "When you're walking home tonight, and some homicidal maniac comes after you with a bunch of loganberries, don't come crying to me!",
+ "This man, he doesn't know when he's beaten! He doesn't know when he's winning, either. He has no... sort of... sensory apparatus...",
+ "There's nothing wrong with you that an expensive operation can't prolong.",
+ "I'm very sorry, but I'm not allowed to argue unless you've paid.",
+
+#endif /* SUDOERS_INS_PYTHON_H */
diff --git a/plugins/sudoers/insults.h b/plugins/sudoers/insults.h
new file mode 100644
index 0000000..25ad46a
--- /dev/null
+++ b/plugins/sudoers/insults.h
@@ -0,0 +1,69 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1994-1996, 1998-1999, 2004
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_INSULTS_H
+#define SUDOERS_INSULTS_H
+
+#if defined(HAL_INSULTS) || defined(GOONS_INSULTS) || defined(CLASSIC_INSULTS) || defined(CSOPS_INSULTS) || defined(PYTHON_INSULTS)
+
+#include <sudo_rand.h>
+
+/*
+ * Use one or more set of insults as determined by configure
+ */
+
+const char *insults[] = {
+
+# ifdef HAL_INSULTS
+# include "ins_2001.h"
+# endif
+
+# ifdef GOONS_INSULTS
+# include "ins_goons.h"
+# endif
+
+# ifdef CLASSIC_INSULTS
+# include "ins_classic.h"
+# endif
+
+# ifdef CSOPS_INSULTS
+# include "ins_csops.h"
+# endif
+
+# ifdef PYTHON_INSULTS
+# include "ins_python.h"
+# endif
+
+ NULL
+
+};
+
+/*
+ * How may I insult you? Let me count the ways...
+ */
+#define NOFINSULTS (nitems(insults) - 1)
+
+/*
+ * return a pseudo-random insult.
+ */
+#define INSULT (insults[arc4random_uniform(NOFINSULTS)])
+
+#endif /* HAL_INSULTS || GOONS_INSULTS || CLASSIC_INSULTS || CSOPS_INSULTS || PYTHON_INSULTS */
+
+#endif /* SUDOERS_INSULTS_H */
diff --git a/plugins/sudoers/interfaces.c b/plugins/sudoers/interfaces.c
new file mode 100644
index 0000000..19c6767
--- /dev/null
+++ b/plugins/sudoers/interfaces.c
@@ -0,0 +1,134 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2016 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#ifdef NEED_RESOLV_H
+# include <arpa/nameser.h>
+# include <resolv.h>
+#endif /* NEED_RESOLV_H */
+#include <netdb.h>
+#include <errno.h>
+
+#include <sudoers.h>
+#include <interfaces.h>
+
+static struct interface_list interfaces = SLIST_HEAD_INITIALIZER(interfaces);
+
+/*
+ * Parse a space-delimited list of IP address/netmask pairs and
+ * store in a list of interface structures. Returns true on
+ * success and false on parse error or memory allocation error.
+ */
+bool
+set_interfaces(const char *ai)
+{
+ char *addrinfo, *addr, *mask, *last;
+ struct interface *ifp;
+ bool ret = false;
+ debug_decl(set_interfaces, SUDOERS_DEBUG_NETIF);
+
+ if ((addrinfo = strdup(ai)) == NULL)
+ debug_return_bool(false);
+ for (addr = strtok_r(addrinfo, " \t", &last); addr != NULL; addr = strtok_r(NULL, " \t", &last)) {
+ /* Separate addr and mask. */
+ if ((mask = strchr(addr, '/')) == NULL)
+ continue;
+ *mask++ = '\0';
+
+ /* Parse addr and store in list. */
+ if ((ifp = calloc(1, sizeof(*ifp))) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ if (strchr(addr, ':')) {
+ /* IPv6 */
+#ifdef HAVE_STRUCT_IN6_ADDR
+ ifp->family = AF_INET6;
+ if (inet_pton(AF_INET6, addr, &ifp->addr.ip6) != 1) {
+ sudo_warnx(U_("unable to parse IP address \"%s\""), addr);
+ free(ifp);
+ goto done;
+ }
+ if (inet_pton(AF_INET6, mask, &ifp->netmask.ip6) != 1) {
+ sudo_warnx(U_("unable to parse netmask \"%s\""), mask);
+ free(ifp);
+ goto done;
+ }
+#else
+ free(ifp);
+ continue;
+#endif
+ } else {
+ /* IPv4 */
+ ifp->family = AF_INET;
+ if (inet_pton(AF_INET, addr, &ifp->addr.ip4) != 1) {
+ sudo_warnx(U_("unable to parse IP address \"%s\""), addr);
+ free(ifp);
+ goto done;
+ }
+ if (inet_pton(AF_INET, mask, &ifp->netmask.ip4) != 1) {
+ sudo_warnx(U_("unable to parse netmask \"%s\""), mask);
+ free(ifp);
+ goto done;
+ }
+ }
+ SLIST_INSERT_HEAD(&interfaces, ifp, entries);
+ }
+ ret = true;
+
+done:
+ free(addrinfo);
+ debug_return_bool(ret);
+}
+
+struct interface_list *
+get_interfaces(void)
+{
+ return &interfaces;
+}
+
+void
+dump_interfaces(const char *ai)
+{
+ const char *cp, *ep;
+ const char *ai_end = ai + strlen(ai);
+ debug_decl(set_interfaces, SUDOERS_DEBUG_NETIF);
+
+ sudo_printf(SUDO_CONV_INFO_MSG,
+ _("Local IP address and netmask pairs:\n"));
+ cp = sudo_strsplit(ai, ai_end, " \t", &ep);
+ while (cp != NULL) {
+ sudo_printf(SUDO_CONV_INFO_MSG, "\t%.*s\n", (int)(ep - cp), cp);
+ cp = sudo_strsplit(NULL, ai_end, " \t", &ep);
+ }
+
+ debug_return;
+}
diff --git a/plugins/sudoers/interfaces.h b/plugins/sudoers/interfaces.h
new file mode 100644
index 0000000..49cca72
--- /dev/null
+++ b/plugins/sudoers/interfaces.h
@@ -0,0 +1,57 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2007, 2010-2013
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#ifndef SUDOERS_INTERFACES_H
+#define SUDOERS_INTERFACES_H
+
+/*
+ * Union to hold either strucr in_addr or in6_add
+ */
+union sudo_in_addr_un {
+ struct in_addr ip4;
+#ifdef HAVE_STRUCT_IN6_ADDR
+ struct in6_addr ip6;
+#endif
+};
+
+/*
+ * IP address and netmask pairs for checking against local interfaces.
+ */
+struct interface {
+ SLIST_ENTRY(interface) entries;
+ unsigned int family; /* AF_INET or AF_INET6 */
+ union sudo_in_addr_un addr;
+ union sudo_in_addr_un netmask;
+};
+
+SLIST_HEAD(interface_list, interface);
+
+/*
+ * Prototypes for external functions.
+ */
+int get_net_ifs(char **addrinfo);
+void dump_interfaces(const char *);
+bool set_interfaces(const char *);
+struct interface_list *get_interfaces(void);
+
+#endif /* SUDOERS_INTERFACES_H */
diff --git a/plugins/sudoers/iolog.c b/plugins/sudoers/iolog.c
new file mode 100644
index 0000000..51afd34
--- /dev/null
+++ b/plugins/sudoers/iolog.c
@@ -0,0 +1,1388 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <pwd.h>
+#include <grp.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <sudoers.h>
+#include <sudo_eventlog.h>
+#include <sudo_iolog.h>
+#include <strlist.h>
+#ifdef SUDOERS_LOG_CLIENT
+# include <log_client.h>
+#endif
+
+static struct iolog_file iolog_files[] = {
+ { false }, /* IOFD_STDIN */
+ { false }, /* IOFD_STDOUT */
+ { false }, /* IOFD_STDERR */
+ { false }, /* IOFD_TTYIN */
+ { false }, /* IOFD_TTYOUT */
+ { true, }, /* IOFD_TIMING */
+};
+
+static struct sudoers_io_operations {
+ int (*open)(struct timespec *now);
+ void (*close)(int exit_status, int error, const char **errstr);
+ int (*log)(int event, const char *buf, unsigned int len,
+ struct timespec *delay, const char **errstr);
+ int (*change_winsize)(unsigned int lines, unsigned int cols,
+ struct timespec *delay, const char **errstr);
+ int (*suspend)(const char *signame, struct timespec *delay,
+ const char **errstr);
+} io_operations;
+
+static struct log_details iolog_details;
+static bool warned = false;
+static bool log_passwords = true;
+static int iolog_dir_fd = -1;
+static struct timespec last_time;
+static void *passprompt_regex_handle;
+static void sudoers_io_setops(void);
+
+/* sudoers_io is declared at the end of this file. */
+extern sudo_dso_public struct io_plugin sudoers_io;
+
+/*
+ * Sudoers callback for maxseq Defaults setting.
+ */
+bool
+cb_maxseq(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ const char *errstr;
+ unsigned int value;
+ debug_decl(cb_maxseq, SUDOERS_DEBUG_UTIL);
+
+ value = (unsigned int)sudo_strtonum(sd_un->str, 0, SESSID_MAX, &errstr);
+ if (errstr != NULL) {
+ if (errno != ERANGE) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "bad maxseq: %s: %s", sd_un->str, errstr);
+ debug_return_bool(false);
+ }
+ /* Out of range, clamp to SESSID_MAX as documented. */
+ value = SESSID_MAX;
+ }
+ iolog_set_maxseq(value);
+ debug_return_bool(true);
+}
+
+/*
+ * Sudoers callback for iolog_user Defaults setting.
+ */
+bool
+cb_iolog_user(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ const char *name = sd_un->str;
+ struct passwd *pw;
+ debug_decl(cb_iolog_user, SUDOERS_DEBUG_UTIL);
+
+ /* NULL name means reset to default. */
+ if (name == NULL) {
+ iolog_set_owner(ROOT_UID, ROOT_GID);
+ } else {
+ if ((pw = sudo_getpwnam(name)) == NULL) {
+ log_warningx(ctx, SLOG_SEND_MAIL, N_("unknown user %s"), name);
+ debug_return_bool(false);
+ }
+ iolog_set_owner(pw->pw_uid, pw->pw_gid);
+ sudo_pw_delref(pw);
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Look up I/O log group-ID from group name.
+ */
+bool
+cb_iolog_group(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ const char *name = sd_un->str;
+ struct group *gr;
+ debug_decl(cb_iolog_group, SUDOERS_DEBUG_UTIL);
+
+ /* NULL name means reset to default. */
+ if (name == NULL) {
+ iolog_set_gid(ROOT_GID);
+ } else {
+ if ((gr = sudo_getgrnam(name)) == NULL) {
+ log_warningx(ctx, SLOG_SEND_MAIL, N_("unknown group %s"), name);
+ debug_return_bool(false);
+ }
+ iolog_set_gid(gr->gr_gid);
+ sudo_gr_delref(gr);
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Sudoers callback for iolog_mode Defaults setting.
+ */
+bool
+cb_iolog_mode(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ iolog_set_mode(sd_un->mode);
+ return true;
+}
+
+/*
+ * Make a shallow copy of a NULL-terminated argument or environment vector.
+ * Only the outer array is allocated, the pointers inside are copied.
+ * The caller is responsible for freeing the returned copy.
+ */
+static char **
+copy_vector_shallow(char * const *vec)
+{
+ char **copy;
+ size_t len;
+ debug_decl(copy_vector, SUDOERS_DEBUG_UTIL);
+
+ for (len = 0; vec[len] != NULL; len++)
+ continue;
+
+ if ((copy = reallocarray(NULL, len + 1, sizeof(char *))) != NULL) {
+ for (len = 0; vec[len] != NULL; len++)
+ copy[len] = vec[len];
+ copy[len] = NULL;
+ }
+
+ debug_return_ptr(copy);
+}
+
+static void
+free_iolog_details(void)
+{
+ debug_decl(free_iolog_details, SUDOERS_DEBUG_PLUGIN);
+
+ if (iolog_details.evlog != NULL) {
+ /* We only make a shallow copy of argv and envp. */
+ free(iolog_details.evlog->runargv);
+ iolog_details.evlog->runargv = NULL;
+ free(iolog_details.evlog->runenv);
+ iolog_details.evlog->runenv = NULL;
+ free(iolog_details.evlog->submitenv);
+ iolog_details.evlog->submitenv = NULL;
+ eventlog_free(iolog_details.evlog);
+ }
+ str_list_free(iolog_details.log_servers);
+#if defined(HAVE_OPENSSL)
+ free(iolog_details.ca_bundle);
+ free(iolog_details.cert_file);
+ free(iolog_details.key_file);
+#endif /* HAVE_OPENSSL */
+
+ debug_return;
+}
+
+/*
+ * Convert a comma-separated list to a string list.
+ */
+static struct sudoers_str_list *
+deserialize_stringlist(const char *s)
+{
+ struct sudoers_str_list *strlist;
+ struct sudoers_string *str;
+ const char *s_end = s + strlen(s);
+ const char *cp, *ep;
+ debug_decl(deserialize_stringlist, SUDOERS_DEBUG_UTIL);
+
+ if ((strlist = str_list_alloc()) == NULL)
+ debug_return_ptr(NULL);
+
+ for (cp = sudo_strsplit(s, s_end, ",", &ep); cp != NULL;
+ cp = sudo_strsplit(NULL, s_end, ",", &ep)) {
+ if (cp == ep)
+ continue;
+ if ((str = malloc(sizeof(*str))) == NULL)
+ goto bad;
+ if ((str->str = strndup(cp, (size_t)(ep - cp))) == NULL) {
+ free(str);
+ goto bad;
+ }
+ unescape_string(str->str);
+ STAILQ_INSERT_TAIL(strlist, str, entries);
+ }
+ if (STAILQ_EMPTY(strlist))
+ goto bad;
+
+ debug_return_ptr(strlist);
+
+bad:
+ str_list_free(strlist);
+ debug_return_ptr(NULL);
+}
+
+/*
+ * Set passprompt regex filter based on a comma-separated string.
+ * Returns a passprompt regex handle pointer.
+ */
+static void *
+set_passprompt_regex(const char *cstr)
+{
+ void *handle;
+ char *cp, *str, *last = NULL;
+ debug_decl(set_passprompt_regex, SUDOERS_DEBUG_UTIL);
+
+ handle = iolog_pwfilt_alloc();
+ str = strdup(cstr);
+ if (handle == NULL || str == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+
+ for ((cp = strtok_r(str, ",", &last)); cp != NULL;
+ (cp = strtok_r(NULL, ",", &last))) {
+ unescape_string(cp);
+ if (!iolog_pwfilt_add(handle, cp))
+ goto bad;
+ }
+
+ free(str);
+ debug_return_ptr(handle);
+bad:
+ free(str);
+ iolog_pwfilt_free(handle);
+ debug_return_ptr(NULL);
+}
+
+/*
+ * Pull out I/O log related data from user_info and command_info arrays.
+ * Returns true if I/O logging is enabled, false if not and -1 on error.
+ */
+static int
+iolog_deserialize_info(struct log_details *details, char * const user_info[],
+ char * const command_info[], char * const argv[], char * const user_env[])
+{
+ const struct sudoers_context *ctx = sudoers_get_context();
+ struct eventlog *evlog;
+ const char *runas_uid_str = "0", *runas_euid_str = NULL;
+ const char *runas_gid_str = "0", *runas_egid_str = NULL;
+ const char *errstr;
+ char idbuf[STRLEN_MAX_UNSIGNED(uid_t) + 2];
+ char * const *cur;
+ struct passwd *pw;
+ struct group *gr;
+ id_t id;
+ debug_decl(iolog_deserialize_info, SUDOERS_DEBUG_UTIL);
+
+ if ((evlog = calloc(1, sizeof(*evlog))) == NULL)
+ goto oom;
+ details->evlog = evlog;
+
+ evlog->lines = 24;
+ evlog->columns = 80;
+ evlog->runuid = ROOT_UID;
+ evlog->rungid = 0;
+ sudo_gettime_real(&evlog->submit_time);
+
+ for (cur = user_info; *cur != NULL; cur++) {
+ switch (**cur) {
+ case 'c':
+ if (strncmp(*cur, "cols=", sizeof("cols=") - 1) == 0) {
+ int n = (int)sudo_strtonum(*cur + sizeof("cols=") - 1, 1,
+ INT_MAX, NULL);
+ if (n > 0)
+ evlog->columns = n;
+ continue;
+ }
+ if (strncmp(*cur, "cwd=", sizeof("cwd=") - 1) == 0) {
+ free(evlog->cwd);
+ evlog->cwd = strdup(*cur + sizeof("cwd=") - 1);
+ if (evlog->cwd == NULL)
+ goto oom;
+ continue;
+ }
+ break;
+ case 'h':
+ if (strncmp(*cur, "host=", sizeof("host=") - 1) == 0) {
+ free(evlog->submithost);
+ evlog->submithost = strdup(*cur + sizeof("host=") - 1);
+ if (evlog->submithost == NULL)
+ goto oom;
+ continue;
+ }
+ break;
+ case 'l':
+ if (strncmp(*cur, "lines=", sizeof("lines=") - 1) == 0) {
+ int n = (int)sudo_strtonum(*cur + sizeof("lines=") - 1, 1,
+ INT_MAX, NULL);
+ if (n > 0)
+ evlog->lines = n;
+ continue;
+ }
+ break;
+ case 't':
+ if (strncmp(*cur, "tty=", sizeof("tty=") - 1) == 0) {
+ free(evlog->ttyname);
+ evlog->ttyname = strdup(*cur + sizeof("tty=") - 1);
+ if (evlog->ttyname == NULL)
+ goto oom;
+ continue;
+ }
+ break;
+ case 'u':
+ if (strncmp(*cur, "user=", sizeof("user=") - 1) == 0) {
+ free(evlog->submituser);
+ evlog->submituser = strdup(*cur + sizeof("user=") - 1);
+ if (evlog->submituser == NULL)
+ goto oom;
+ continue;
+ }
+ break;
+ }
+ }
+
+ for (cur = command_info; *cur != NULL; cur++) {
+ switch (**cur) {
+ case 'c':
+ if (strncmp(*cur, "command=", sizeof("command=") - 1) == 0) {
+ free(evlog->command);
+ evlog->command = strdup(*cur + sizeof("command=") - 1);
+ if (evlog->command == NULL)
+ goto oom;
+ continue;
+ }
+ if (strncmp(*cur, "chroot=", sizeof("chroot=") - 1) == 0) {
+ free(evlog->runchroot);
+ evlog->runchroot = strdup(*cur + sizeof("chroot=") - 1);
+ if (evlog->runchroot == NULL)
+ goto oom;
+ continue;
+ }
+ break;
+ case 'i':
+ if (strncmp(*cur, "ignore_iolog_errors=", sizeof("ignore_iolog_errors=") - 1) == 0) {
+ if (sudo_strtobool(*cur + sizeof("ignore_iolog_errors=") - 1) == true)
+ details->ignore_log_errors = true;
+ continue;
+ }
+ if (strncmp(*cur, "iolog_path=", sizeof("iolog_path=") - 1) == 0) {
+ free(evlog->iolog_path);
+ evlog->iolog_path = strdup(*cur + sizeof("iolog_path=") - 1);
+ if (evlog->iolog_path == NULL)
+ goto oom;
+ continue;
+ }
+ if (strncmp(*cur, "iolog_stdin=", sizeof("iolog_stdin=") - 1) == 0) {
+ if (sudo_strtobool(*cur + sizeof("iolog_stdin=") - 1) == true)
+ iolog_files[IOFD_STDIN].enabled = true;
+ continue;
+ }
+ if (strncmp(*cur, "iolog_stdout=", sizeof("iolog_stdout=") - 1) == 0) {
+ if (sudo_strtobool(*cur + sizeof("iolog_stdout=") - 1) == true)
+ iolog_files[IOFD_STDOUT].enabled = true;
+ continue;
+ }
+ if (strncmp(*cur, "iolog_stderr=", sizeof("iolog_stderr=") - 1) == 0) {
+ if (sudo_strtobool(*cur + sizeof("iolog_stderr=") - 1) == true)
+ iolog_files[IOFD_STDERR].enabled = true;
+ continue;
+ }
+ if (strncmp(*cur, "iolog_ttyin=", sizeof("iolog_ttyin=") - 1) == 0) {
+ if (sudo_strtobool(*cur + sizeof("iolog_ttyin=") - 1) == true)
+ iolog_files[IOFD_TTYIN].enabled = true;
+ continue;
+ }
+ if (strncmp(*cur, "iolog_ttyout=", sizeof("iolog_ttyout=") - 1) == 0) {
+ if (sudo_strtobool(*cur + sizeof("iolog_ttyout=") - 1) == true)
+ iolog_files[IOFD_TTYOUT].enabled = true;
+ continue;
+ }
+ if (strncmp(*cur, "iolog_compress=", sizeof("iolog_compress=") - 1) == 0) {
+ int val = sudo_strtobool(*cur + sizeof("iolog_compress=") - 1);
+ if (val != -1) {
+ iolog_set_compress(val);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN,
+ "%s: unable to parse %s", __func__, *cur);
+ }
+ continue;
+ }
+ if (strncmp(*cur, "iolog_flush=", sizeof("iolog_flush=") - 1) == 0) {
+ int val = sudo_strtobool(*cur + sizeof("iolog_flush=") - 1);
+ if (val != -1) {
+ iolog_set_flush(val);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN,
+ "%s: unable to parse %s", __func__, *cur);
+ }
+ continue;
+ }
+ if (strncmp(*cur, "iolog_mode=", sizeof("iolog_mode=") - 1) == 0) {
+ mode_t mode = sudo_strtomode(*cur + sizeof("iolog_mode=") - 1, &errstr);
+ if (errstr == NULL) {
+ iolog_set_mode(mode);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN,
+ "%s: unable to parse %s", __func__, *cur);
+ }
+ continue;
+ }
+ if (strncmp(*cur, "iolog_group=", sizeof("iolog_group=") - 1) == 0) {
+ gr = sudo_getgrnam(*cur + sizeof("iolog_group=") - 1);
+ if (gr == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_WARN, "%s: unknown group %s",
+ __func__, *cur + sizeof("iolog_group=") - 1);
+ } else {
+ iolog_set_gid(gr->gr_gid);
+ sudo_gr_delref(gr);
+ }
+ continue;
+ }
+ if (strncmp(*cur, "iolog_user=", sizeof("iolog_user=") - 1) == 0) {
+ pw = sudo_getpwnam(*cur + sizeof("iolog_user=") - 1);
+ if (pw == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_WARN, "%s: unknown user %s",
+ __func__, *cur + sizeof("iolog_user=") - 1);
+ } else {
+ iolog_set_owner(pw->pw_uid, pw->pw_gid);
+ sudo_pw_delref(pw);
+ }
+ continue;
+ }
+ break;
+ case 'l':
+ if (strncmp(*cur, "log_passwords=", sizeof("log_passwords=") - 1) == 0) {
+ int val = sudo_strtobool(*cur + sizeof("log_passwords=") - 1);
+ if (val != -1) {
+ log_passwords = val;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN,
+ "%s: unable to parse %s", __func__, *cur);
+ }
+ continue;
+ }
+ if (strncmp(*cur, "log_servers=", sizeof("log_servers=") - 1) == 0) {
+ details->log_servers =
+ deserialize_stringlist(*cur + sizeof("log_servers=") - 1);
+ if (!details->log_servers)
+ goto oom;
+ continue;
+ }
+ if (strncmp(*cur, "log_server_timeout=", sizeof("log_server_timeout=") - 1) == 0) {
+ details->server_timeout.tv_sec = (time_t)
+ sudo_strtonum(*cur + sizeof("log_server_timeout=") - 1, 1,
+ TIME_T_MAX, NULL);
+ continue;
+ }
+ if (strncmp(*cur, "log_server_keepalive=", sizeof("log_server_keepalive=") - 1) == 0) {
+ int val = sudo_strtobool(*cur + sizeof("log_server_keepalive=") - 1);
+ if (val != -1) {
+ details->keepalive = val;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN,
+ "%s: unable to parse %s", __func__, *cur);
+ }
+ continue;
+ }
+#if defined(HAVE_OPENSSL)
+ if (strncmp(*cur, "log_server_cabundle=", sizeof("log_server_cabundle=") - 1) == 0) {
+ free(details->ca_bundle);
+ details->ca_bundle = strdup(*cur + sizeof("log_server_cabundle=") - 1);
+ if (details->ca_bundle == NULL)
+ goto oom;
+ continue;
+ }
+ if (strncmp(*cur, "log_server_peer_cert=", sizeof("log_server_peer_cert=") - 1) == 0) {
+ free(details->cert_file);
+ details->cert_file = strdup(*cur + sizeof("log_server_peer_cert=") - 1);
+ if (details->cert_file == NULL)
+ goto oom;
+ continue;
+ }
+ if (strncmp(*cur, "log_server_peer_key=", sizeof("log_server_peer_key=") - 1) == 0) {
+ free(details->key_file);
+ details->key_file = strdup(*cur + sizeof("log_server_peer_key=") - 1);
+ if (details->key_file == NULL)
+ goto oom;
+ continue;
+ }
+ if (strncmp(*cur, "log_server_verify=", sizeof("log_server_verify=") - 1) == 0) {
+ int val = sudo_strtobool(*cur + sizeof("log_server_verify=") - 1);
+ if (val != -1) {
+ details->verify_server = val;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN,
+ "%s: unable to parse %s", __func__, *cur);
+ }
+ continue;
+ }
+#endif /* HAVE_OPENSSL */
+ break;
+ case 'm':
+ if (strncmp(*cur, "maxseq=", sizeof("maxseq=") - 1) == 0) {
+ union sudo_defs_val sd_un;
+ sd_un.str = *cur + sizeof("maxseq=") - 1;
+ cb_maxseq(NULL, "policy", -1, -1, &sd_un, true);
+ continue;
+ }
+ break;
+ case 'p':
+ if (strncmp(*cur, "passprompt_regex=", sizeof("passprompt_regex=") - 1) == 0) {
+ iolog_pwfilt_free(passprompt_regex_handle);
+ passprompt_regex_handle =
+ set_passprompt_regex(*cur + sizeof("passprompt_regex=") - 1);
+ if (passprompt_regex_handle == NULL)
+ debug_return_int(-1);
+ }
+ break;
+ case 'r':
+ if (strncmp(*cur, "runas_gid=", sizeof("runas_gid=") - 1) == 0) {
+ runas_gid_str = *cur + sizeof("runas_gid=") - 1;
+ continue;
+ }
+ if (strncmp(*cur, "runas_egid=", sizeof("runas_egid=") - 1) == 0) {
+ runas_egid_str = *cur + sizeof("runas_egid=") - 1;
+ continue;
+ }
+ if (strncmp(*cur, "runas_uid=", sizeof("runas_uid=") - 1) == 0) {
+ runas_uid_str = *cur + sizeof("runas_uid=") - 1;
+ continue;
+ }
+ if (strncmp(*cur, "runas_euid=", sizeof("runas_euid=") - 1) == 0) {
+ runas_euid_str = *cur + sizeof("runas_euid=") - 1;
+ continue;
+ }
+ if (strncmp(*cur, "runcwd=", sizeof("runcwd=") - 1) == 0) {
+ free(evlog->runcwd);
+ evlog->runcwd = strdup(*cur + sizeof("runcwd=") - 1);
+ if (evlog->runcwd == NULL)
+ goto oom;
+ continue;
+ }
+ break;
+ case 's':
+ if (strncmp(*cur, "source=", sizeof("source=") - 1) == 0) {
+ free(evlog->source);
+ evlog->source = strdup(*cur + sizeof("source=") - 1);
+ if (evlog->source == NULL)
+ goto oom;
+ continue;
+ }
+ }
+ }
+
+ if (argv != NULL) {
+ evlog->runargv = copy_vector_shallow(argv);
+ if (evlog->runargv == NULL)
+ goto oom;
+ }
+ if (user_env != NULL) {
+ evlog->runenv = copy_vector_shallow(user_env);
+ if (evlog->runenv == NULL)
+ goto oom;
+ }
+ if (ctx->user.envp != NULL) {
+ evlog->submitenv = copy_vector_shallow(ctx->user.envp);
+ if (evlog->submitenv == NULL)
+ goto oom;
+ }
+
+ /*
+ * Lookup runas user and group, preferring effective over real uid/gid.
+ */
+ if (runas_euid_str != NULL)
+ runas_uid_str = runas_euid_str;
+ if (runas_uid_str != NULL) {
+ id = sudo_strtoid(runas_uid_str, &errstr);
+ if (errstr != NULL)
+ sudo_warnx("runas uid %s: %s", runas_uid_str, U_(errstr));
+ else
+ evlog->runuid = (uid_t)id;
+ }
+ if (runas_egid_str != NULL)
+ runas_gid_str = runas_egid_str;
+ if (runas_gid_str != NULL) {
+ id = sudo_strtoid(runas_gid_str, &errstr);
+ if (errstr != NULL)
+ sudo_warnx("runas gid %s: %s", runas_gid_str, U_(errstr));
+ else
+ evlog->rungid = (gid_t)id;
+ }
+
+ pw = sudo_getpwuid(evlog->runuid);
+ if (pw != NULL) {
+ gid_t pw_gid = pw->pw_gid;
+ free(evlog->runuser);
+ evlog->runuser = strdup(pw->pw_name);
+ sudo_pw_delref(pw);
+ if (evlog->runuser == NULL)
+ goto oom;
+ if (evlog->rungid != pw_gid) {
+ gr = sudo_getgrgid(evlog->rungid);
+ if (gr != NULL) {
+ free(evlog->rungroup);
+ evlog->rungroup = strdup(gr->gr_name);
+ sudo_gr_delref(gr);
+ if (evlog->rungroup == NULL)
+ goto oom;
+ } else {
+ idbuf[0] = '#';
+ strlcpy(&idbuf[1], runas_gid_str, sizeof(idbuf) - 1);
+ free(evlog->rungroup);
+ evlog->rungroup = strdup(idbuf);
+ if (evlog->rungroup == NULL)
+ goto oom;
+ }
+ }
+ } else {
+ idbuf[0] = '#';
+ strlcpy(&idbuf[1], runas_uid_str, sizeof(idbuf) - 1);
+ free(evlog->runuser);
+ evlog->runuser = strdup(idbuf);
+ if (evlog->runuser == NULL)
+ goto oom;
+ }
+
+ debug_return_int(
+ iolog_files[IOFD_STDIN].enabled || iolog_files[IOFD_STDOUT].enabled ||
+ iolog_files[IOFD_STDERR].enabled || iolog_files[IOFD_TTYIN].enabled ||
+ iolog_files[IOFD_TTYOUT].enabled);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(-1);
+}
+
+static int
+sudoers_io_open_local(struct timespec *now)
+{
+ const struct sudoers_context *ctx = sudoers_get_context();
+ struct eventlog *evlog = iolog_details.evlog;
+ int i, ret = -1;
+ debug_decl(sudoers_io_open_local, SUDOERS_DEBUG_PLUGIN);
+
+ /* If no I/O log path defined we need to figure it out ourselves. */
+ if (evlog->iolog_path == NULL) {
+ int len;
+
+ /* Get next session ID and convert it into a path. */
+ if (!iolog_nextid(_PATH_SUDO_IO_LOGDIR, evlog->sessid)) {
+ log_warning(ctx, SLOG_SEND_MAIL,
+ N_("unable to update sequence file"));
+ warned = true;
+ goto done;
+ }
+ len = asprintf(&evlog->iolog_path, "%s/%c%c/%c%c/%c%c",
+ _PATH_SUDO_IO_LOGDIR,
+ evlog->sessid[0], evlog->sessid[1], evlog->sessid[2],
+ evlog->sessid[3], evlog->sessid[4], evlog->sessid[5]);
+ if (len == -1) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ }
+
+ /*
+ * Create I/O log path along with any intermediate subdirs.
+ * Calls mkdtemp() if iolog_path ends in XXXXXX.
+ */
+ if (!iolog_mkpath(evlog->iolog_path)) {
+ log_warning(ctx, SLOG_SEND_MAIL, "%s", evlog->iolog_path);
+ warned = true;
+ goto done;
+ }
+
+ iolog_dir_fd = iolog_openat(AT_FDCWD, evlog->iolog_path, O_RDONLY);
+ if (iolog_dir_fd == -1) {
+ log_warning(ctx, SLOG_SEND_MAIL, "%s", evlog->iolog_path);
+ warned = true;
+ goto done;
+ }
+
+ /* Write log file with user and command details. */
+ if (!iolog_write_info_file(iolog_dir_fd, iolog_details.evlog)) {
+ log_warningx(ctx, SLOG_SEND_MAIL,
+ N_("unable to write to I/O log file: %s"), strerror(errno));
+ warned = true;
+ goto done;
+ }
+
+ /* Create the timing and I/O log files. */
+ for (i = 0; i < IOFD_MAX; i++) {
+ if (!iolog_open(&iolog_files[i], iolog_dir_fd, i, "w")) {
+ log_warning(ctx, SLOG_SEND_MAIL, N_("unable to create %s/%s"),
+ evlog->iolog_path, iolog_fd_to_name(i));
+ warned = true;
+ goto done;
+ }
+ }
+
+ ret = true;
+
+done:
+ debug_return_int(ret);
+}
+
+#ifdef SUDOERS_LOG_CLIENT
+static int
+sudoers_io_open_remote(struct timespec *now)
+{
+ debug_decl(sudoers_io_open_remote, SUDOERS_DEBUG_PLUGIN);
+
+ /* Open connection to log server, send hello and accept messages. */
+ client_closure = log_server_open(&iolog_details, now, true, SEND_ACCEPT,
+ NULL);
+ if (client_closure != NULL)
+ debug_return_int(1);
+
+ debug_return_int(-1);
+}
+#endif /* SUDOERS_LOG_CLIENT */
+
+static int
+sudoers_io_open(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t plugin_printf, char * const settings[],
+ char * const user_info[], char * const command_info[],
+ int argc, char * const argv[], char * const user_env[], char * const args[],
+ const char **errstr)
+{
+ struct sudo_conf_debug_file_list debug_files = TAILQ_HEAD_INITIALIZER(debug_files);
+ char * const *cur;
+ const char *cp, *plugin_path = NULL;
+ int ret = -1;
+ debug_decl(sudoers_io_open, SUDOERS_DEBUG_PLUGIN);
+
+ sudo_conv = conversation;
+ sudo_printf = plugin_printf;
+ if (sudoers_io.event_alloc != NULL)
+ plugin_event_alloc = sudoers_io.event_alloc;
+
+ bindtextdomain("sudoers", LOCALEDIR);
+
+ /* Initialize the debug subsystem. */
+ for (cur = settings; (cp = *cur) != NULL; cur++) {
+ if (strncmp(cp, "debug_flags=", sizeof("debug_flags=") - 1) == 0) {
+ cp += sizeof("debug_flags=") - 1;
+ if (!sudoers_debug_parse_flags(&debug_files, cp))
+ debug_return_int(-1);
+ continue;
+ }
+ if (strncmp(cp, "plugin_path=", sizeof("plugin_path=") - 1) == 0) {
+ plugin_path = cp + sizeof("plugin_path=") - 1;
+ continue;
+ }
+ }
+
+ if (!sudoers_debug_register(plugin_path, &debug_files))
+ goto done;
+
+ /* If we have no command (because -V was specified) just return. */
+ if (argc == 0)
+ debug_return_int(true);
+
+ /*
+ * Pull iolog settings out of command_info.
+ */
+ ret = iolog_deserialize_info(&iolog_details, user_info, command_info,
+ argv, user_env);
+ if (ret != true)
+ goto done;
+
+ /* Initialize io_operations. */
+ sudoers_io_setops();
+
+ if (sudo_gettime_awake(&last_time) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to get time of day", __func__);
+ goto done;
+ }
+
+ /*
+ * Create local I/O log file or connect to remote log server.
+ */
+ if ((ret = io_operations.open(&last_time)) != true)
+ goto done;
+
+ /*
+ * Clear I/O log function pointers for disabled log functions.
+ */
+ if (!iolog_files[IOFD_STDIN].enabled)
+ sudoers_io.log_stdin = NULL;
+ if (!iolog_files[IOFD_STDOUT].enabled)
+ sudoers_io.log_stdout = NULL;
+ if (!iolog_files[IOFD_STDERR].enabled)
+ sudoers_io.log_stderr = NULL;
+ if (!iolog_files[IOFD_TTYIN].enabled)
+ sudoers_io.log_ttyin = NULL;
+ if (!iolog_files[IOFD_TTYOUT].enabled)
+ sudoers_io.log_ttyout = NULL;
+
+done:
+ if (ret != true) {
+ if (iolog_dir_fd != -1) {
+ close(iolog_dir_fd);
+ iolog_dir_fd = -1;
+ }
+ free_iolog_details();
+ sudo_freepwcache();
+ sudo_freegrcache();
+ }
+
+ /* Ignore errors if they occur if the policy says so. */
+ if (ret == -1 && iolog_details.ignore_log_errors)
+ ret = 0;
+
+ debug_return_int(ret);
+}
+
+static void
+sudoers_io_close_local(int exit_status, int error, const char **errstr)
+{
+ unsigned int i;
+ debug_decl(sudoers_io_close_local, SUDOERS_DEBUG_PLUGIN);
+
+ /* Close the files. */
+ for (i = 0; i < IOFD_MAX; i++) {
+ if (iolog_files[i].fd.v == NULL)
+ continue;
+ iolog_close(&iolog_files[i], errstr);
+ }
+
+ /* Clear write bits from I/O timing file to indicate completion. */
+ if (iolog_dir_fd != -1) {
+ struct stat sb;
+ if (fstatat(iolog_dir_fd, "timing", &sb, 0) != -1) {
+ CLR(sb.st_mode, S_IWUSR|S_IWGRP|S_IWOTH);
+ if (fchmodat(iolog_dir_fd, "timing", sb.st_mode, 0) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to fchmodat timing file", __func__);
+ }
+ }
+ close(iolog_dir_fd);
+ iolog_dir_fd = -1;
+ }
+
+ debug_return;
+}
+
+#ifdef SUDOERS_LOG_CLIENT
+static void
+sudoers_io_close_remote(int exit_status, int error, const char **errstr)
+{
+ debug_decl(sudoers_io_close_remote, SUDOERS_DEBUG_PLUGIN);
+
+ log_server_close(client_closure, exit_status, error);
+ client_closure = NULL;
+
+ debug_return;
+}
+#endif
+
+static void
+sudoers_io_close(int exit_status, int error)
+{
+ const struct sudoers_context *ctx = sudoers_get_context();
+ const char *errstr = NULL;
+ debug_decl(sudoers_io_close, SUDOERS_DEBUG_PLUGIN);
+
+ if (io_operations.close != NULL)
+ io_operations.close(exit_status, error, &errstr);
+
+ if (errstr != NULL && !warned) {
+ /* Only warn about I/O log file errors once. */
+ log_warningx(ctx, SLOG_SEND_MAIL,
+ N_("unable to write to I/O log file: %s"), errstr);
+ warned = true;
+ }
+
+ free_iolog_details();
+ sudo_freepwcache();
+ sudo_freegrcache();
+ iolog_pwfilt_free(passprompt_regex_handle);
+ passprompt_regex_handle = NULL;
+
+ /* sudoers_debug_deregister() calls sudo_debug_exit() for us. */
+ sudoers_debug_deregister();
+}
+
+static int
+sudoers_io_version(int verbose)
+{
+ debug_decl(sudoers_io_version, SUDOERS_DEBUG_PLUGIN);
+
+ sudo_printf(SUDO_CONV_INFO_MSG, "Sudoers I/O plugin version %s\n",
+ PACKAGE_VERSION);
+
+ debug_return_int(true);
+}
+
+/*
+ * Write an I/O log entry to the local file system.
+ * Returns 1 on success and -1 on error.
+ * Fills in errstr on error.
+ */
+static int
+sudoers_io_log_local(int event, const char *buf, unsigned int len,
+ struct timespec *delay, const char **errstr)
+{
+ struct iolog_file *iol;
+ char tbuf[1024];
+ char *newbuf = NULL;
+ int ret = -1;
+ debug_decl(sudoers_io_log_local, SUDOERS_DEBUG_PLUGIN);
+
+ if (event < 0 || event >= IOFD_MAX) {
+ *errstr = NULL;
+ sudo_warnx(U_("unexpected I/O event %d"), event);
+ debug_return_int(-1);
+ }
+ iol = &iolog_files[event];
+ if (!iol->enabled) {
+ *errstr = NULL;
+ sudo_warnx(U_("%s: internal error, I/O log file for event %d not open"),
+ __func__, event);
+ debug_return_int(-1);
+ }
+
+ if (!log_passwords && passprompt_regex_handle != NULL) {
+ if (!iolog_pwfilt_run(passprompt_regex_handle, event, buf, len, &newbuf))
+ debug_return_int(-1);
+ }
+
+ /* Write I/O log file entry. */
+ if (iolog_write(iol, newbuf ? newbuf : buf, len, errstr) == -1)
+ goto done;
+
+ /* Write timing file entry. */
+ len = (unsigned int)snprintf(tbuf, sizeof(tbuf), "%d %lld.%09ld %u\n",
+ event, (long long)delay->tv_sec, delay->tv_nsec, len);
+ if (len >= sizeof(tbuf)) {
+ /* Not actually possible due to the size of tbuf[]. */
+ *errstr = strerror(EOVERFLOW);
+ goto done;
+ }
+ if (iolog_write(&iolog_files[IOFD_TIMING], tbuf, len, errstr) == -1)
+ goto done;
+
+ /* Success. */
+ ret = 1;
+
+done:
+ free(newbuf);
+ debug_return_int(ret);
+}
+
+#ifdef SUDOERS_LOG_CLIENT
+/*
+ * Schedule an I/O log entry to be written to the log server.
+ * Returns 1 on success and -1 on error.
+ * Fills in errstr on error.
+ */
+static int
+sudoers_io_log_remote(int event, const char *buf, unsigned int len,
+ struct timespec *delay, const char **errstr)
+{
+ int type, ret = -1;
+ debug_decl(sudoers_io_log_remote, SUDOERS_DEBUG_PLUGIN);
+
+ if (client_closure->disabled)
+ debug_return_int(1);
+
+ /* Track elapsed time for comparison with commit points. */
+ sudo_timespecadd(delay, &client_closure->elapsed, &client_closure->elapsed);
+
+ switch (event) {
+ case IO_EVENT_STDIN:
+ type = CLIENT_MESSAGE__TYPE_STDIN_BUF;
+ break;
+ case IO_EVENT_STDOUT:
+ type = CLIENT_MESSAGE__TYPE_STDOUT_BUF;
+ break;
+ case IO_EVENT_STDERR:
+ type = CLIENT_MESSAGE__TYPE_STDERR_BUF;
+ break;
+ case IO_EVENT_TTYIN:
+ type = CLIENT_MESSAGE__TYPE_TTYIN_BUF;
+ break;
+ case IO_EVENT_TTYOUT:
+ type = CLIENT_MESSAGE__TYPE_TTYOUT_BUF;
+ break;
+ default:
+ sudo_warnx(U_("unexpected I/O event %d"), event);
+ goto done;
+ }
+ if (fmt_io_buf(client_closure, type, buf, len, delay)) {
+ ret = client_closure->write_ev->add(client_closure->write_ev,
+ &iolog_details.server_timeout);
+ if (ret == -1)
+ sudo_warn("%s", U_("unable to add event to queue"));
+ }
+
+done:
+ debug_return_int(ret);
+}
+#endif /* SUDOERS_LOG_CLIENT */
+
+/*
+ * Generic I/O logging function. Called by the I/O logging entry points.
+ * Returns 1 on success and -1 on error.
+ */
+static int
+sudoers_io_log(const char *buf, unsigned int len, int event, const char **errstr)
+{
+ const struct sudoers_context *ctx = sudoers_get_context();
+ struct timespec now, delay;
+ const char *ioerror = NULL;
+ int ret = -1;
+ debug_decl(sudoers_io_log, SUDOERS_DEBUG_PLUGIN);
+
+ if (sudo_gettime_awake(&now) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to get time of day", __func__);
+ ioerror = N_("unable to read the clock");
+ goto bad;
+ }
+ sudo_timespecsub(&now, &last_time, &delay);
+
+ ret = io_operations.log(event, buf, len, &delay, &ioerror);
+
+ last_time.tv_sec = now.tv_sec;
+ last_time.tv_nsec = now.tv_nsec;
+
+bad:
+ if (ret == -1) {
+ if (ioerror != NULL) {
+ char *cp;
+
+ if (asprintf(&cp, N_("unable to write to I/O log file: %s"),
+ ioerror) != -1) {
+ *errstr = cp;
+ }
+ if (!warned) {
+ /* Only warn about I/O log file errors once. */
+ log_warningx(ctx, SLOG_SEND_MAIL,
+ N_("unable to write to I/O log file: %s"), ioerror);
+ warned = true;
+ }
+ }
+
+ /* Ignore errors if they occur if the policy says so. */
+ if (iolog_details.ignore_log_errors)
+ ret = 1;
+ }
+
+ debug_return_int(ret);
+}
+
+static int
+sudoers_io_log_stdin(const char *buf, unsigned int len, const char **errstr)
+{
+ return sudoers_io_log(buf, len, IO_EVENT_STDIN, errstr);
+}
+
+static int
+sudoers_io_log_stdout(const char *buf, unsigned int len, const char **errstr)
+{
+ return sudoers_io_log(buf, len, IO_EVENT_STDOUT, errstr);
+}
+
+static int
+sudoers_io_log_stderr(const char *buf, unsigned int len, const char **errstr)
+{
+ return sudoers_io_log(buf, len, IO_EVENT_STDERR, errstr);
+}
+
+static int
+sudoers_io_log_ttyin(const char *buf, unsigned int len, const char **errstr)
+{
+ return sudoers_io_log(buf, len, IO_EVENT_TTYIN, errstr);
+}
+
+static int
+sudoers_io_log_ttyout(const char *buf, unsigned int len, const char **errstr)
+{
+ return sudoers_io_log(buf, len, IO_EVENT_TTYOUT, errstr);
+}
+
+static int
+sudoers_io_change_winsize_local(unsigned int lines, unsigned int cols,
+ struct timespec *delay, const char **errstr)
+{
+ char tbuf[1024];
+ int len, ret = -1;
+ debug_decl(sudoers_io_change_winsize_local, SUDOERS_DEBUG_PLUGIN);
+
+ /* Write window change event to the timing file. */
+ len = snprintf(tbuf, sizeof(tbuf), "%d %lld.%09ld %u %u\n",
+ IO_EVENT_WINSIZE, (long long)delay->tv_sec, delay->tv_nsec,
+ lines, cols);
+ if (len < 0 || len >= ssizeof(tbuf)) {
+ /* Not actually possible due to the size of tbuf[]. */
+ *errstr = strerror(EOVERFLOW);
+ goto done;
+ }
+ if (iolog_write(&iolog_files[IOFD_TIMING], tbuf, (size_t)len, errstr) == -1)
+ goto done;
+
+ /* Success. */
+ ret = 1;
+
+done:
+ debug_return_int(ret);
+}
+
+#ifdef SUDOERS_LOG_CLIENT
+static int
+sudoers_io_change_winsize_remote(unsigned int lines, unsigned int cols,
+ struct timespec *delay, const char **errstr)
+{
+ int ret = -1;
+ debug_decl(sudoers_io_change_winsize_remote, SUDOERS_DEBUG_PLUGIN);
+
+ if (client_closure->disabled)
+ debug_return_int(1);
+
+ /* Track elapsed time for comparison with commit points. */
+ sudo_timespecadd(delay, &client_closure->elapsed, &client_closure->elapsed);
+
+ if (fmt_winsize(client_closure, lines, cols, delay)) {
+ ret = client_closure->write_ev->add(client_closure->write_ev,
+ &iolog_details.server_timeout);
+ if (ret == -1)
+ sudo_warn("%s", U_("unable to add event to queue"));
+ }
+
+ debug_return_int(ret);
+}
+#endif /* SUDOERS_LOG_CLIENT */
+
+static int
+sudoers_io_change_winsize(unsigned int lines, unsigned int cols, const char **errstr)
+{
+ const struct sudoers_context *ctx = sudoers_get_context();
+ struct timespec now, delay;
+ const char *ioerror = NULL;
+ int ret = -1;
+ debug_decl(sudoers_io_change_winsize, SUDOERS_DEBUG_PLUGIN);
+
+ if (sudo_gettime_awake(&now) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to get time of day", __func__);
+ ioerror = N_("unable to read the clock");
+ goto bad;
+ }
+ sudo_timespecsub(&now, &last_time, &delay);
+
+ ret = io_operations.change_winsize(lines, cols, &delay, &ioerror);
+
+ last_time.tv_sec = now.tv_sec;
+ last_time.tv_nsec = now.tv_nsec;
+
+bad:
+ if (ret == -1) {
+ if (ioerror != NULL && !warned) {
+ char *cp;
+
+ if (asprintf(&cp, N_("unable to write to I/O log file: %s"),
+ ioerror) != -1) {
+ *errstr = cp;
+ }
+ if (!warned) {
+ /* Only warn about I/O log file errors once. */
+ log_warningx(ctx, SLOG_SEND_MAIL,
+ N_("unable to write to I/O log file: %s"), ioerror);
+ warned = true;
+ }
+ }
+
+ /* Ignore errors if they occur if the policy says so. */
+ if (iolog_details.ignore_log_errors)
+ ret = 1;
+ }
+
+ debug_return_int(ret);
+}
+
+static int
+sudoers_io_suspend_local(const char *signame, struct timespec *delay,
+ const char **errstr)
+{
+ unsigned int len;
+ char tbuf[1024];
+ int ret = -1;
+ debug_decl(sudoers_io_suspend_local, SUDOERS_DEBUG_PLUGIN);
+
+ /* Write suspend event to the timing file. */
+ len = (unsigned int)snprintf(tbuf, sizeof(tbuf), "%d %lld.%09ld %s\n",
+ IO_EVENT_SUSPEND, (long long)delay->tv_sec, delay->tv_nsec, signame);
+ if (len >= sizeof(tbuf)) {
+ /* Not actually possible due to the size of tbuf[]. */
+ *errstr = strerror(EOVERFLOW);
+ goto done;
+ }
+ if (iolog_write(&iolog_files[IOFD_TIMING], tbuf, len, errstr) == -1)
+ goto done;
+
+ /* Success. */
+ ret = 1;
+
+done:
+ debug_return_int(ret);
+}
+
+#ifdef SUDOERS_LOG_CLIENT
+static int
+sudoers_io_suspend_remote(const char *signame, struct timespec *delay,
+ const char **errstr)
+{
+ int ret = -1;
+ debug_decl(sudoers_io_suspend_remote, SUDOERS_DEBUG_PLUGIN);
+
+ if (client_closure->disabled)
+ debug_return_int(1);
+
+ /* Track elapsed time for comparison with commit points. */
+ sudo_timespecadd(delay, &client_closure->elapsed, &client_closure->elapsed);
+
+ if (fmt_suspend(client_closure, signame, delay)) {
+ ret = client_closure->write_ev->add(client_closure->write_ev,
+ &iolog_details.server_timeout);
+ if (ret == -1)
+ sudo_warn("%s", U_("unable to add event to queue"));
+ }
+
+ debug_return_int(ret);
+}
+#endif /* SUDOERS_LOG_CLIENT */
+
+static int
+sudoers_io_suspend(int signo, const char **errstr)
+{
+ const struct sudoers_context *ctx = sudoers_get_context();
+ struct timespec now, delay;
+ char signame[SIG2STR_MAX];
+ const char *ioerror = NULL;
+ int ret = -1;
+ debug_decl(sudoers_io_suspend, SUDOERS_DEBUG_PLUGIN);
+
+ if (signo <= 0 || sig2str(signo, signame) == -1) {
+ sudo_warnx(U_("%s: internal error, invalid signal %d"),
+ __func__, signo);
+ debug_return_int(-1);
+ }
+
+ if (sudo_gettime_awake(&now) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to get time of day", __func__);
+ ioerror = N_("unable to read the clock");
+ goto bad;
+ }
+ sudo_timespecsub(&now, &last_time, &delay);
+
+ /* Write suspend event to the timing file. */
+ ret = io_operations.suspend(signame, &delay, &ioerror);
+
+ last_time.tv_sec = now.tv_sec;
+ last_time.tv_nsec = now.tv_nsec;
+
+bad:
+ if (ret == -1) {
+ if (ioerror != NULL && !warned) {
+ char *cp;
+
+ if (asprintf(&cp, N_("unable to write to I/O log file: %s"),
+ ioerror) != -1) {
+ *errstr = cp;
+ }
+ if (!warned) {
+ /* Only warn about I/O log file errors once. */
+ log_warningx(ctx, SLOG_SEND_MAIL,
+ N_("unable to write to I/O log file: %s"), ioerror);
+ warned = true;
+ }
+ }
+
+ /* Ignore errors if they occur if the policy says so. */
+ if (iolog_details.ignore_log_errors)
+ ret = 1;
+ }
+
+ debug_return_int(ret);
+}
+
+/*
+ * Fill in the contents of io_operations, either local or remote.
+ */
+static void
+sudoers_io_setops(void)
+{
+ debug_decl(sudoers_io_setops, SUDOERS_DEBUG_PLUGIN);
+
+#ifdef SUDOERS_LOG_CLIENT
+ if (plugin_event_alloc != NULL && iolog_details.log_servers != NULL) {
+ io_operations.open = sudoers_io_open_remote;
+ io_operations.close = sudoers_io_close_remote;
+ io_operations.log = sudoers_io_log_remote;
+ io_operations.change_winsize = sudoers_io_change_winsize_remote;
+ io_operations.suspend = sudoers_io_suspend_remote;
+ } else
+#endif /* SUDOERS_LOG_CLIENT */
+ {
+ io_operations.open = sudoers_io_open_local;
+ io_operations.close = sudoers_io_close_local;
+ io_operations.log = sudoers_io_log_local;
+ io_operations.change_winsize = sudoers_io_change_winsize_local;
+ io_operations.suspend = sudoers_io_suspend_local;
+ }
+
+ debug_return;
+}
+
+sudo_dso_public struct io_plugin sudoers_io = {
+ SUDO_IO_PLUGIN,
+ SUDO_API_VERSION,
+ sudoers_io_open,
+ sudoers_io_close,
+ sudoers_io_version,
+ sudoers_io_log_ttyin,
+ sudoers_io_log_ttyout,
+ sudoers_io_log_stdin,
+ sudoers_io_log_stdout,
+ sudoers_io_log_stderr,
+ NULL, /* register_hooks */
+ NULL, /* deregister_hooks */
+ sudoers_io_change_winsize,
+ sudoers_io_suspend,
+ NULL /* event_alloc() filled in by sudo */
+};
diff --git a/plugins/sudoers/iolog_path_escapes.c b/plugins/sudoers/iolog_path_escapes.c
new file mode 100644
index 0000000..d234c55
--- /dev/null
+++ b/plugins/sudoers/iolog_path_escapes.c
@@ -0,0 +1,170 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+
+#include <sudoers.h>
+#include <sudo_iolog.h>
+
+/*
+ * Like strlcpy(3) but replaces '/' with '_'.
+ */
+static size_t
+strlcpy_no_slash(char *dst, const char *src, size_t size)
+{
+ size_t len = 0;
+ char ch;
+ debug_decl(strlcpy_no_slash, SUDOERS_DEBUG_UTIL);
+
+ while ((ch = *src++) != '\0') {
+ if (size > 1) {
+ /* Replace '/' with '_' */
+ if (ch == '/')
+ ch = '_';
+ *dst++ = ch;
+ size--;
+ }
+ len++;
+ }
+ if (size > 0)
+ *dst = '\0';
+
+ debug_return_size_t(len);
+}
+
+static size_t
+fill_seq(char *str, size_t strsize, void *v)
+{
+#ifdef SUDOERS_NO_SEQ
+ debug_decl(fill_seq, SUDOERS_DEBUG_UTIL);
+ debug_return_size_t(strlcpy(str, "%{seq}", strsize));
+#else
+ struct sudoers_context *ctx = v;
+ static char sessid[7];
+ int len;
+ debug_decl(fill_seq, SUDOERS_DEBUG_UTIL);
+
+ if (sessid[0] == '\0') {
+ if (!iolog_nextid(ctx->iolog_dir, sessid))
+ debug_return_size_t((size_t)-1);
+ }
+
+ /* Path is of the form /var/log/sudo-io/00/00/01. */
+ len = snprintf(str, strsize, "%c%c/%c%c/%c%c", sessid[0],
+ sessid[1], sessid[2], sessid[3], sessid[4], sessid[5]);
+ if (len < 0)
+ debug_return_size_t(strsize); /* handle non-standard snprintf() */
+ debug_return_size_t((size_t)len);
+#endif /* SUDOERS_NO_SEQ */
+}
+
+static size_t
+fill_user(char *str, size_t strsize, void *v)
+{
+ struct sudoers_context *ctx = v;
+ debug_decl(fill_user, SUDOERS_DEBUG_UTIL);
+ debug_return_size_t(strlcpy_no_slash(str, ctx->user.name, strsize));
+}
+
+static size_t
+fill_group(char *str, size_t strsize, void *v)
+{
+ struct sudoers_context *ctx = v;
+ struct group *grp;
+ size_t len;
+ debug_decl(fill_group, SUDOERS_DEBUG_UTIL);
+
+ if ((grp = sudo_getgrgid(ctx->user.gid)) != NULL) {
+ len = strlcpy_no_slash(str, grp->gr_name, strsize);
+ sudo_gr_delref(grp);
+ } else {
+ len = (size_t)snprintf(str, strsize, "#%u", (unsigned int)ctx->user.gid);
+ }
+ debug_return_size_t(len);
+}
+
+static size_t
+fill_runas_user(char *str, size_t strsize, void *v)
+{
+ struct sudoers_context *ctx = v;
+ debug_decl(fill_runas_user, SUDOERS_DEBUG_UTIL);
+ debug_return_size_t(strlcpy_no_slash(str, ctx->runas.pw->pw_name, strsize));
+}
+
+static size_t
+fill_runas_group(char *str, size_t strsize, void *v)
+{
+ struct sudoers_context *ctx = v;
+ struct group *grp;
+ size_t len;
+ debug_decl(fill_runas_group, SUDOERS_DEBUG_UTIL);
+
+ if (ctx->runas.gr != NULL) {
+ len = strlcpy_no_slash(str, ctx->runas.gr->gr_name, strsize);
+ } else {
+ if ((grp = sudo_getgrgid(ctx->runas.pw->pw_gid)) != NULL) {
+ len = strlcpy_no_slash(str, grp->gr_name, strsize);
+ sudo_gr_delref(grp);
+ } else {
+ len = (size_t)snprintf(str, strsize, "#%u",
+ (unsigned int)ctx->runas.pw->pw_gid);
+ }
+ }
+ debug_return_size_t(len);
+}
+
+static size_t
+fill_hostname(char *str, size_t strsize, void *v)
+{
+ struct sudoers_context *ctx = v;
+ debug_decl(fill_hostname, SUDOERS_DEBUG_UTIL);
+ debug_return_size_t(strlcpy_no_slash(str, ctx->user.shost, strsize));
+}
+
+static size_t
+fill_command(char *str, size_t strsize, void *v)
+{
+ struct sudoers_context *ctx = v;
+ debug_decl(fill_command, SUDOERS_DEBUG_UTIL);
+ debug_return_size_t(strlcpy_no_slash(str, ctx->user.cmnd_base, strsize));
+}
+
+/* Note: "seq" must be first in the list. */
+static const struct iolog_path_escape path_escapes[] = {
+ { "seq", fill_seq },
+ { "user", fill_user },
+ { "group", fill_group },
+ { "runas_user", fill_runas_user },
+ { "runas_group", fill_runas_group },
+ { "hostname", fill_hostname },
+ { "command", fill_command },
+ { NULL, NULL }
+};
+const struct iolog_path_escape *sudoers_iolog_path_escapes = path_escapes;
diff --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c
new file mode 100644
index 0000000..08ed3ec
--- /dev/null
+++ b/plugins/sudoers/ldap.c
@@ -0,0 +1,2045 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2003-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * This code is derived from software contributed by Aaron Spangler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <unistd.h>
+#include <time.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
+#ifdef HAVE_LBER_H
+# include <lber.h>
+#endif
+#include <ldap.h>
+#if defined(HAVE_LDAPSSL_H)
+# include <ldapssl.h>
+#elif defined(HAVE_LDAP_SSL_H)
+# include <ldap_ssl.h>
+#elif defined(HAVE_MPS_LDAP_SSL_H)
+# include <mps/ldap_ssl.h>
+#endif
+#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
+# ifdef HAVE_SASL_SASL_H
+# include <sasl/sasl.h>
+# else
+# include <sasl.h>
+# endif
+#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
+
+#include <sudoers.h>
+#include <sudo_lbuf.h>
+#include <sudo_ldap.h>
+#include <sudo_ldap_conf.h>
+#include <sudo_dso.h>
+
+#if defined(HAVE_LDAP_SASL_INTERACTIVE_BIND_S) && !defined(LDAP_SASL_QUIET)
+# define LDAP_SASL_QUIET 0
+#endif
+
+#ifndef HAVE_LDAP_UNBIND_EXT_S
+#define ldap_unbind_ext_s(a, b, c) ldap_unbind_s(a)
+#endif
+
+/* The TIMEFILTER_LENGTH is the length of the filter when timed entries
+ are used. The length is computed as follows:
+ 81 for the filter itself
+ + 2 * 17 for the now timestamp
+*/
+#define TIMEFILTER_LENGTH 115
+
+/*
+ * The ldap_search structure implements a linked list of ldap and
+ * search result pointers, which allows us to remove them after
+ * all search results have been combined in memory.
+ */
+struct ldap_search_result {
+ STAILQ_ENTRY(ldap_search_result) entries;
+ LDAP *ldap;
+ LDAPMessage *searchresult;
+};
+STAILQ_HEAD(ldap_search_list, ldap_search_result);
+
+/*
+ * The ldap_entry_wrapper structure is used to implement sorted result entries.
+ * A double is used for the order to allow for insertion of new entries
+ * without having to renumber everything.
+ * Note: there is no standard floating point type in LDAP.
+ * As a result, some LDAP servers will only allow an integer.
+ */
+struct ldap_entry_wrapper {
+ LDAPMessage *entry;
+ double order;
+};
+
+/*
+ * The ldap_result structure contains the list of matching searches as
+ * well as an array of all result entries sorted by the sudoOrder attribute.
+ */
+struct ldap_result {
+ struct ldap_search_list searches;
+ struct ldap_entry_wrapper *entries;
+ unsigned int allocated_entries;
+ unsigned int nentries;
+};
+#define ALLOCATION_INCREMENT 100
+
+/*
+ * The ldap_netgroup structure implements a singly-linked tail queue of
+ * netgroups a user is a member of when querying netgroups directly.
+ */
+struct ldap_netgroup {
+ STAILQ_ENTRY(ldap_netgroup) entries;
+ char *name;
+};
+STAILQ_HEAD(ldap_netgroup_list, ldap_netgroup);
+
+/*
+ * LDAP sudo_nss handle.
+ * We store the connection to the LDAP server and the passwd struct of the
+ * user the last query was performed for.
+ */
+struct sudo_ldap_handle {
+ LDAP *ld;
+ struct passwd *pw;
+ struct sudoers_parse_tree parse_tree;
+};
+
+#ifdef HAVE_LDAP_INITIALIZE
+static char *
+sudo_ldap_join_uri(struct ldap_config_str_list *uri_list)
+{
+ struct ldap_config_str *uri;
+ size_t len = 0;
+ char *buf = NULL;
+ debug_decl(sudo_ldap_join_uri, SUDOERS_DEBUG_LDAP);
+
+ STAILQ_FOREACH(uri, uri_list, entries) {
+ if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS) {
+ if (strncasecmp(uri->val, "ldaps://", 8) == 0) {
+ sudo_warnx("%s", U_("starttls not supported when using ldaps"));
+ ldap_conf.ssl_mode = SUDO_LDAP_SSL;
+ }
+ }
+ len += strlen(uri->val) + 1;
+ }
+ if (len == 0 || (buf = malloc(len)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ } else {
+ char *cp = buf;
+
+ STAILQ_FOREACH(uri, uri_list, entries) {
+ cp += strlcpy(cp, uri->val, len - (size_t)(cp - buf));
+ *cp++ = ' ';
+ }
+ cp[-1] = '\0';
+ }
+ debug_return_str(buf);
+}
+#endif /* HAVE_LDAP_INITIALIZE */
+
+/*
+ * Wrapper for ldap_create() or ldap_init() that handles
+ * SSL/TLS initialization as well.
+ * Returns LDAP_SUCCESS on success, else non-zero.
+ */
+static int
+sudo_ldap_init(const struct sudoers_context *ctx, LDAP **ldp, const char *host,
+ int port)
+{
+ LDAP *ld;
+ int ret;
+ debug_decl(sudo_ldap_init, SUDOERS_DEBUG_LDAP);
+
+#ifdef HAVE_LDAPSSL_INIT
+ if (ldap_conf.ssl_mode != SUDO_LDAP_CLEAR) {
+ const int defsecure = ldap_conf.ssl_mode == SUDO_LDAP_SSL;
+ DPRINTF2("ldapssl_clientauth_init(%s, %s)",
+ ldap_conf.tls_certfile ? ldap_conf.tls_certfile : "NULL",
+ ldap_conf.tls_keyfile ? ldap_conf.tls_keyfile : "NULL");
+ ret = ldapssl_clientauth_init(ldap_conf.tls_certfile, NULL,
+ ldap_conf.tls_keyfile != NULL, ldap_conf.tls_keyfile, NULL);
+ /*
+ * Starting with version 5.0, Mozilla-derived LDAP SDKs require
+ * the cert and key paths to be a directory, not a file.
+ * If the user specified a file and it fails, try the parent dir.
+ */
+ if (ret != LDAP_SUCCESS) {
+ bool retry = false;
+ if (ldap_conf.tls_certfile != NULL) {
+ char *cp = strrchr(ldap_conf.tls_certfile, '/');
+ if (cp != NULL && strncmp(cp + 1, "cert", 4) == 0) {
+ *cp = '\0';
+ retry = true;
+ }
+ }
+ if (ldap_conf.tls_keyfile != NULL) {
+ char *cp = strrchr(ldap_conf.tls_keyfile, '/');
+ if (cp != NULL && strncmp(cp + 1, "key", 3) == 0) {
+ *cp = '\0';
+ retry = true;
+ }
+ }
+ if (retry) {
+ DPRINTF2("retry ldapssl_clientauth_init(%s, %s)",
+ ldap_conf.tls_certfile ? ldap_conf.tls_certfile : "NULL",
+ ldap_conf.tls_keyfile ? ldap_conf.tls_keyfile : "NULL");
+ ret = ldapssl_clientauth_init(ldap_conf.tls_certfile, NULL,
+ ldap_conf.tls_keyfile != NULL, ldap_conf.tls_keyfile, NULL);
+ }
+ }
+ if (ret != LDAP_SUCCESS) {
+ sudo_warnx(U_("unable to initialize SSL cert and key db: %s"),
+ ldapssl_err2string(ret));
+ if (ldap_conf.tls_certfile == NULL)
+ sudo_warnx(U_("you must set TLS_CERT in %s to use SSL"),
+ ctx->settings.ldap_conf);
+ goto done;
+ }
+
+ DPRINTF2("ldapssl_init(%s, %d, %d)", host, port, defsecure);
+ if ((ld = ldapssl_init(host, port, defsecure)) != NULL)
+ ret = LDAP_SUCCESS;
+ } else
+#elif defined(HAVE_LDAP_SSL_INIT) && defined(HAVE_LDAP_SSL_CLIENT_INIT)
+ if (ldap_conf.ssl_mode == SUDO_LDAP_SSL) {
+ int sslrc;
+ ret = ldap_ssl_client_init(ldap_conf.tls_keyfile, ldap_conf.tls_keypw,
+ 0, &sslrc);
+ if (ret != LDAP_SUCCESS) {
+ sudo_warnx("ldap_ssl_client_init(): %s: %s",
+ ldap_err2string(ret), ssl_err2string(sslrc));
+ goto done;
+ }
+ DPRINTF2("ldap_ssl_init(%s, %d, NULL)", host, port);
+ if ((ld = ldap_ssl_init((char *)host, port, NULL)) != NULL)
+ ret = LDAP_SUCCESS;
+ } else
+#endif
+ {
+#ifdef HAVE_LDAP_CREATE
+ DPRINTF2("ldap_create()");
+ if ((ret = ldap_create(&ld)) != LDAP_SUCCESS)
+ goto done;
+ DPRINTF2("ldap_set_option(LDAP_OPT_HOST_NAME, %s)", host);
+ ret = ldap_set_option(ld, LDAP_OPT_HOST_NAME, host);
+#else
+ DPRINTF2("ldap_init(%s, %d)", host, port);
+ if ((ld = ldap_init((char *)host, port)) == NULL) {
+ ret = LDAP_LOCAL_ERROR;
+ goto done;
+ }
+ ret = LDAP_SUCCESS;
+#endif
+ }
+
+ *ldp = ld;
+done:
+ debug_return_int(ret);
+}
+
+/*
+ * Wrapper for ldap_get_values_len() that fills in the response code
+ * on error.
+ */
+static struct berval **
+sudo_ldap_get_values_len(LDAP *ld, LDAPMessage *entry, const char *attr, int *rc)
+{
+ struct berval **bval;
+
+ bval = ldap_get_values_len(ld, entry, attr);
+ if (bval == NULL) {
+ const int optrc = ldap_get_option(ld, LDAP_OPT_RESULT_CODE, rc);
+ if (optrc != LDAP_OPT_SUCCESS)
+ *rc = optrc;
+ } else {
+ *rc = LDAP_SUCCESS;
+ }
+ return bval;
+}
+
+/*
+ * Walk through search results and return true if we have a matching
+ * non-Unix group (including netgroups), else false.
+ * A matching entry that is negated will always return false.
+ */
+static int
+sudo_ldap_check_non_unix_group(struct sudoers_context *ctx,
+ const struct sudo_nss *nss, LDAPMessage *entry, struct passwd *pw)
+{
+ struct sudo_ldap_handle *handle = nss->handle;
+ LDAP *ld = handle->ld;
+ struct berval **bv, **p;
+ bool ret = false;
+ int rc;
+ debug_decl(sudo_ldap_check_non_unix_group, SUDOERS_DEBUG_LDAP);
+
+ if (!entry)
+ debug_return_bool(false);
+
+ /* get the values from the entry */
+ bv = sudo_ldap_get_values_len(ld, entry, "sudoUser", &rc);
+ if (bv == NULL) {
+ if (rc == LDAP_NO_MEMORY)
+ debug_return_int(-1);
+ debug_return_bool(false);
+ }
+
+ /* walk through values */
+ for (p = bv; *p != NULL && !ret; p++) {
+ bool negated = false;
+ const char *val = (*p)->bv_val;
+
+ if (*val == '!') {
+ val++;
+ negated = true;
+ }
+ if (*val == '+') {
+ if (netgr_matches(nss, val,
+ def_netgroup_tuple ? ctx->runas.host : NULL,
+ def_netgroup_tuple ? ctx->runas.shost : NULL, pw->pw_name) == ALLOW)
+ ret = true;
+ DPRINTF2("ldap sudoUser netgroup '%s%s' ... %s",
+ negated ? "!" : "", val, ret ? "MATCH!" : "not");
+ } else {
+ if (group_plugin_query(pw->pw_name, val + 2, pw))
+ ret = true;
+ DPRINTF2("ldap sudoUser non-Unix group '%s%s' ... %s",
+ negated ? "!" : "", val, ret ? "MATCH!" : "not");
+ }
+ /* A negated match overrides all other entries. */
+ if (ret && negated) {
+ ret = false;
+ break;
+ }
+ }
+
+ ldap_value_free_len(bv); /* cleanup */
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Extract the dn from an entry and return the first rdn from it.
+ */
+static char *
+sudo_ldap_get_first_rdn(LDAP *ld, LDAPMessage *entry, int *rc)
+{
+#ifdef HAVE_LDAP_STR2DN
+ char *dn, *rdn = NULL;
+ LDAPDN tmpDN;
+ debug_decl(sudo_ldap_get_first_rdn, SUDOERS_DEBUG_LDAP);
+
+ if ((dn = ldap_get_dn(ld, entry)) == NULL) {
+ int optrc = ldap_get_option(ld, LDAP_OPT_RESULT_CODE, rc);
+ if (optrc != LDAP_OPT_SUCCESS)
+ *rc = optrc;
+ debug_return_str(NULL);
+ }
+ *rc = ldap_str2dn(dn, &tmpDN, LDAP_DN_FORMAT_LDAP);
+ if (*rc == LDAP_SUCCESS) {
+ ldap_rdn2str(tmpDN[0], &rdn, LDAP_DN_FORMAT_UFN);
+ ldap_dnfree(tmpDN);
+ }
+ ldap_memfree(dn);
+ debug_return_str(rdn);
+#else
+ char *dn, **edn;
+ debug_decl(sudo_ldap_get_first_rdn, SUDOERS_DEBUG_LDAP);
+
+ if ((dn = ldap_get_dn(ld, entry)) == NULL) {
+ int optrc = ldap_get_option(ld, LDAP_OPT_RESULT_CODE, rc);
+ if (optrc != LDAP_OPT_SUCCESS)
+ *rc = optrc;
+ debug_return_str(NULL);
+ }
+ edn = ldap_explode_dn(dn, 1);
+ ldap_memfree(dn);
+ if (edn == NULL) {
+ *rc = LDAP_NO_MEMORY;
+ debug_return_str(NULL);
+ }
+ *rc = LDAP_SUCCESS;
+ debug_return_str(edn[0]);
+#endif
+}
+
+/*
+ * Read sudoOption and fill in the defaults list.
+ * This is used to parse the cn=defaults entry.
+ */
+static bool
+sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry, struct defaults_list *defs)
+{
+ struct berval **p, **bv = NULL;
+ char *cp, *cn = NULL, *source = NULL;
+ bool ret = false;
+ int rc;
+ debug_decl(sudo_ldap_parse_options, SUDOERS_DEBUG_LDAP);
+
+ bv = sudo_ldap_get_values_len(ld, entry, "sudoOption", &rc);
+ if (bv == NULL) {
+ if (rc == LDAP_NO_MEMORY)
+ goto oom;
+ debug_return_bool(true);
+ }
+
+ /* Use sudoRole in place of file name in defaults. */
+ cn = sudo_ldap_get_first_rdn(ld, entry, &rc);
+ if (cn == NULL) {
+ if (rc == LDAP_NO_MEMORY)
+ goto oom;
+ }
+ if (asprintf(&cp, "sudoRole %s", cn ? cn : "UNKNOWN") == -1)
+ goto oom;
+ source = sudo_rcstr_dup(cp);
+ free(cp);
+ if (source == NULL)
+ goto oom;
+
+ /* Walk through options, appending to defs. */
+ for (p = bv; *p != NULL; p++) {
+ char *var, *val;
+ int op;
+
+ op = sudo_ldap_parse_option((*p)->bv_val, &var, &val);
+ if (!append_default(var, val, op, source, defs))
+ goto oom;
+ }
+
+ ret = true;
+ goto done;
+
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+done:
+ sudo_rcstr_delref(source);
+ if (cn)
+ ldap_memfree(cn);
+ ldap_value_free_len(bv);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Build an LDAP timefilter.
+ *
+ * Stores a filter in the buffer that makes sure only entries
+ * are selected that have a sudoNotBefore in the past and a
+ * sudoNotAfter in the future, i.e. a filter of the following
+ * structure (spaced out a little more for better readability:
+ *
+ * (&
+ * (|
+ * (!(sudoNotAfter=*))
+ * (sudoNotAfter>__now__)
+ * )
+ * (|
+ * (!(sudoNotBefore=*))
+ * (sudoNotBefore<__now__)
+ * )
+ * )
+ *
+ * If either the sudoNotAfter or sudoNotBefore attributes are missing,
+ * no time restriction shall be imposed.
+ */
+static bool
+sudo_ldap_timefilter(char *buffer, size_t buffersize)
+{
+ char timebuffer[sizeof("20120727121554.0Z")];
+ bool ret = false;
+ struct tm gmt;
+ time_t now;
+ size_t tblen;
+ int buflen;
+ debug_decl(sudo_ldap_timefilter, SUDOERS_DEBUG_LDAP);
+
+ /* Make sure we have a formatted timestamp for __now__. */
+ time(&now);
+ if (gmtime_r(&now, &gmt) == NULL) {
+ sudo_warn("%s", U_("unable to get GMT time"));
+ goto done;
+ }
+
+ /* Format the timestamp according to the RFC. */
+ timebuffer[sizeof(timebuffer) - 1] = '\0';
+ tblen = strftime(timebuffer, sizeof(timebuffer), "%Y%m%d%H%M%S.0Z", &gmt);
+ if (tblen == 0 || timebuffer[sizeof(timebuffer) - 1] != '\0') {
+ sudo_warnx("%s", U_("unable to format timestamp"));
+ goto done;
+ }
+
+ /* Build filter. */
+ buflen = snprintf(buffer, buffersize, "(&(|(!(sudoNotAfter=*))(sudoNotAfter>=%s))(|(!(sudoNotBefore=*))(sudoNotBefore<=%s)))",
+ timebuffer, timebuffer);
+ if (buflen < 0 || (size_t)buflen >= buffersize) {
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ errno = EOVERFLOW;
+ goto done;
+ }
+
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+/*
+ * Builds up a filter to search for default settings
+ */
+static char *
+sudo_ldap_build_default_filter(void)
+{
+ char *filt;
+ debug_decl(sudo_ldap_build_default_filter, SUDOERS_DEBUG_LDAP);
+
+ if (!ldap_conf.search_filter)
+ debug_return_str(strdup("cn=defaults"));
+
+ if (asprintf(&filt, "(&%s(cn=defaults))", ldap_conf.search_filter) == -1)
+ debug_return_str(NULL);
+
+ debug_return_str(filt);
+}
+
+/*
+ * Check the netgroups list beginning at "start" for nesting.
+ * Parent nodes with a memberNisNetgroup that match one of the
+ * netgroups are added to the list and checked for further nesting.
+ * Return true on success or false if there was an internal overflow.
+ */
+static bool
+sudo_netgroup_lookup_nested(struct sudoers_context *ctx, LDAP *ld, char *base,
+ struct timeval *timeout, struct ldap_netgroup_list *netgroups,
+ struct ldap_netgroup *start)
+{
+ LDAPMessage *entry, *result;
+ size_t filt_len;
+ char *filt;
+ int rc;
+ debug_decl(sudo_netgroup_lookup_nested, SUDOERS_DEBUG_LDAP);
+
+ DPRINTF1("Checking for nested netgroups from netgroup_base '%s'", base);
+ do {
+ struct ldap_netgroup *ng, *old_tail;
+
+ result = NULL;
+ old_tail = STAILQ_LAST(netgroups, ldap_netgroup, entries);
+ filt_len = strlen(ldap_conf.netgroup_search_filter) + 7;
+ for (ng = start; ng != NULL; ng = STAILQ_NEXT(ng, entries)) {
+ filt_len += sudo_ldap_value_len(ng->name) + 20;
+ }
+ if ((filt = malloc(filt_len)) == NULL)
+ goto oom;
+ CHECK_STRLCPY(filt, "(&", filt_len);
+ CHECK_STRLCAT(filt, ldap_conf.netgroup_search_filter, filt_len);
+ CHECK_STRLCAT(filt, "(|", filt_len);
+ for (ng = start; ng != NULL; ng = STAILQ_NEXT(ng, entries)) {
+ CHECK_STRLCAT(filt, "(memberNisNetgroup=", filt_len);
+ CHECK_LDAP_VCAT(filt, ng->name, filt_len);
+ CHECK_STRLCAT(filt, ")", filt_len);
+ }
+ CHECK_STRLCAT(filt, "))", filt_len);
+ DPRINTF1("ldap netgroup search filter: '%s'", filt);
+ rc = ldap_search_ext_s(ld, base, LDAP_SCOPE_SUBTREE, filt,
+ NULL, 0, NULL, NULL, timeout, 0, &result);
+ free(filt);
+ if (rc == LDAP_SUCCESS) {
+ LDAP_FOREACH(entry, ld, result) {
+ struct berval **bv;
+
+ bv = sudo_ldap_get_values_len(ld, entry, "cn", &rc);
+ if (bv == NULL) {
+ if (rc == LDAP_NO_MEMORY)
+ goto oom;
+ } else {
+ /* Don't add a netgroup twice. */
+ STAILQ_FOREACH(ng, netgroups, entries) {
+ /* Assumes only one cn per entry. */
+ if (strcasecmp(ng->name, (*bv)->bv_val) == 0)
+ break;
+ }
+ if (ng == NULL) {
+ ng = malloc(sizeof(*ng));
+ if (ng == NULL ||
+ (ng->name = strdup((*bv)->bv_val)) == NULL) {
+ free(ng);
+ ldap_value_free_len(bv);
+ goto oom;
+ }
+#ifdef __clang_analyzer__
+ /* clang analyzer false positive */
+ if (__builtin_expect(netgroups->stqh_last == NULL, 0))
+ __builtin_trap();
+#endif
+ STAILQ_INSERT_TAIL(netgroups, ng, entries);
+ DPRINTF1("Found new netgroup %s for %s", ng->name, base);
+ }
+ ldap_value_free_len(bv);
+ }
+ }
+ }
+ ldap_msgfree(result);
+
+ /* Check for nested netgroups in what we added. */
+ start = old_tail ? STAILQ_NEXT(old_tail, entries) : STAILQ_FIRST(netgroups);
+ } while (start != NULL);
+
+ debug_return_bool(true);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ ldap_msgfree(result);
+ debug_return_bool(false);
+overflow:
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ free(filt);
+ debug_return_bool(false);
+}
+
+/*
+ * Look up netgroups that the specified user is a member of.
+ * Appends new entries to the netgroups list.
+ * Return true on success or false if there was an internal overflow.
+ */
+static bool
+sudo_netgroup_lookup(struct sudoers_context *ctx, LDAP *ld, struct passwd *pw,
+ struct ldap_netgroup_list *netgroups)
+{
+ struct ldap_config_str *base;
+ struct ldap_netgroup *ng, *old_tail;
+ struct timeval tv, *tvp = NULL;
+ LDAPMessage *entry, *result = NULL;
+ const char *domain;
+ char *escaped_domain = NULL, *escaped_user = NULL;
+ char *escaped_host = NULL, *escaped_shost = NULL, *filt = NULL;
+ int filt_len, rc;
+ bool ret = false;
+ debug_decl(sudo_netgroup_lookup, SUDOERS_DEBUG_LDAP);
+
+ if (ldap_conf.timeout > 0) {
+ tv.tv_sec = ldap_conf.timeout;
+ tv.tv_usec = 0;
+ tvp = &tv;
+ }
+
+ /* Use NIS domain if set, else wildcard match. */
+ domain = sudo_getdomainname();
+
+ /* Escape the domain, host names, and user name per RFC 4515. */
+ if (domain != NULL) {
+ if ((escaped_domain = sudo_ldap_value_dup(domain)) == NULL)
+ goto oom;
+ }
+ if ((escaped_user = sudo_ldap_value_dup(pw->pw_name)) == NULL)
+ goto oom;
+ if (def_netgroup_tuple) {
+ escaped_host = sudo_ldap_value_dup(ctx->runas.host);
+ if (ctx->runas.host == ctx->runas.shost)
+ escaped_shost = escaped_host;
+ else
+ escaped_shost = sudo_ldap_value_dup(ctx->runas.shost);
+ if (escaped_host == NULL || escaped_shost == NULL)
+ goto oom;
+ }
+
+ /* Build query, using NIS domain if it is set. */
+ if (domain != NULL) {
+ if (escaped_host != escaped_shost) {
+ filt_len = asprintf(&filt, "(&%s(|"
+ "(nisNetgroupTriple=\\28,%s,%s\\29)"
+ "(nisNetgroupTriple=\\28%s,%s,%s\\29)"
+ "(nisNetgroupTriple=\\28%s,%s,%s\\29)"
+ "(nisNetgroupTriple=\\28,%s,\\29)"
+ "(nisNetgroupTriple=\\28%s,%s,\\29)"
+ "(nisNetgroupTriple=\\28%s,%s,\\29)))",
+ ldap_conf.netgroup_search_filter, escaped_user, escaped_domain,
+ escaped_shost, escaped_user, escaped_domain,
+ escaped_host, escaped_user, escaped_domain, escaped_user,
+ escaped_shost, escaped_user, escaped_host, escaped_user);
+ } else if (escaped_shost != NULL) {
+ filt_len = asprintf(&filt, "(&%s(|"
+ "(nisNetgroupTriple=\\28,%s,%s\\29)"
+ "(nisNetgroupTriple=\\28%s,%s,%s\\29)"
+ "(nisNetgroupTriple=\\28,%s,\\29)"
+ "(nisNetgroupTriple=\\28%s,%s,\\29)))",
+ ldap_conf.netgroup_search_filter, escaped_user, escaped_domain,
+ escaped_shost, escaped_user, escaped_domain,
+ escaped_user, escaped_shost, escaped_user);
+ } else {
+ filt_len = asprintf(&filt, "(&%s(|"
+ "(nisNetgroupTriple=\\28*,%s,%s\\29)"
+ "(nisNetgroupTriple=\\28*,%s,\\29)))",
+ ldap_conf.netgroup_search_filter, escaped_user, escaped_domain,
+ escaped_user);
+ }
+ } else {
+ if (escaped_host != escaped_shost) {
+ filt_len = asprintf(&filt, "(&%s(|"
+ "(nisNetgroupTriple=\\28,%s,*\\29)"
+ "(nisNetgroupTriple=\\28%s,%s,*\\29)"
+ "(nisNetgroupTriple=\\28%s,%s,*\\29)))",
+ ldap_conf.netgroup_search_filter, escaped_user,
+ escaped_shost, escaped_user, escaped_host, escaped_user);
+ } else if (escaped_shost != NULL) {
+ filt_len = asprintf(&filt, "(&%s(|"
+ "(nisNetgroupTriple=\\28,%s,*\\29)"
+ "(nisNetgroupTriple=\\28%s,%s,*\\29)))",
+ ldap_conf.netgroup_search_filter, escaped_user,
+ escaped_shost, escaped_user);
+ } else {
+ filt_len = asprintf(&filt,
+ "(&%s(|(nisNetgroupTriple=\\28*,%s,*\\29)))",
+ ldap_conf.netgroup_search_filter, escaped_user);
+ }
+ }
+ if (filt_len == -1)
+ goto oom;
+ DPRINTF1("ldap netgroup search filter: '%s'", filt);
+
+ STAILQ_FOREACH(base, &ldap_conf.netgroup_base, entries) {
+ DPRINTF1("searching from netgroup_base '%s'", base->val);
+ rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, filt,
+ NULL, 0, NULL, NULL, tvp, 0, &result);
+ if (rc != LDAP_SUCCESS) {
+ DPRINTF1("ldap netgroup search failed: %s", ldap_err2string(rc));
+ ldap_msgfree(result);
+ result = NULL;
+ continue;
+ }
+
+ old_tail = STAILQ_LAST(netgroups, ldap_netgroup, entries);
+ LDAP_FOREACH(entry, ld, result) {
+ struct berval **bv;
+
+ bv = sudo_ldap_get_values_len(ld, entry, "cn", &rc);
+ if (bv == NULL) {
+ if (rc == LDAP_NO_MEMORY)
+ goto oom;
+ } else {
+ /* Don't add a netgroup twice. */
+ STAILQ_FOREACH(ng, netgroups, entries) {
+ /* Assumes only one cn per entry. */
+ if (strcasecmp(ng->name, (*bv)->bv_val) == 0)
+ break;
+ }
+ if (ng == NULL) {
+ ng = malloc(sizeof(*ng));
+ if (ng == NULL ||
+ (ng->name = strdup((*bv)->bv_val)) == NULL) {
+ free(ng);
+ ldap_value_free_len(bv);
+ goto oom;
+ }
+ STAILQ_INSERT_TAIL(netgroups, ng, entries);
+ DPRINTF1("Found new netgroup %s for %s", ng->name,
+ base->val);
+ }
+ ldap_value_free_len(bv);
+ }
+ }
+ ldap_msgfree(result);
+ result = NULL;
+
+ /* Check for nested netgroups in what we added. */
+ ng = old_tail ? STAILQ_NEXT(old_tail, entries) : STAILQ_FIRST(netgroups);
+ if (ng != NULL) {
+ if (!sudo_netgroup_lookup_nested(ctx, ld, base->val, tvp, netgroups, ng))
+ goto done;
+ }
+ }
+ ret = true;
+ goto done;
+
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+done:
+ free(escaped_domain);
+ free(escaped_user);
+ free(escaped_host);
+ if (escaped_host != escaped_shost)
+ free(escaped_shost);
+ free(filt);
+ ldap_msgfree(result);
+ debug_return_bool(ret);
+}
+
+/*
+ * Builds up a filter to check against LDAP.
+ */
+static char *
+sudo_ldap_build_pass1(struct sudoers_context *ctx, LDAP *ld, struct passwd *pw)
+{
+ char idbuf[STRLEN_MAX_UNSIGNED(uid_t) + 1];
+ char timebuffer[TIMEFILTER_LENGTH + 1];
+ char *buf, *notbuf;
+ struct ldap_netgroup_list netgroups;
+ struct ldap_netgroup *ng = NULL;
+ struct gid_list *gidlist;
+ struct group_list *grlist;
+ struct group *grp;
+ size_t sz = 0;
+ int i;
+ debug_decl(sudo_ldap_build_pass1, SUDOERS_DEBUG_LDAP);
+
+ STAILQ_INIT(&netgroups);
+
+ if (ldap_conf.timed || ldap_conf.search_filter) {
+ /* Allocate space for the global AND. */
+ sz += 3;
+
+ /* Add LDAP search filter if present. */
+ if (ldap_conf.search_filter)
+ sz += strlen(ldap_conf.search_filter);
+
+ /* If timed, add space for time limits. */
+ if (ldap_conf.timed)
+ sz += TIMEFILTER_LENGTH;
+ }
+
+ /* Add space for the global OR clause + (sudoUser=ALL) + NOT + NUL. */
+ sz += sizeof("(|(sudoUser=ALL)(!(|)))");
+
+ /* Add space for username and uid, including the negated versions. */
+ sz += ((sizeof("(sudoUser=)(sudoUser=#)") - 1 +
+ sudo_ldap_value_len(pw->pw_name) + sizeof(idbuf) - 1) * 2) + 2;
+
+ /* Add space for primary and supplementary groups and gids */
+ if ((grp = sudo_getgrgid(pw->pw_gid)) != NULL) {
+ sz += ((sizeof("(sudoUser=%)") - 1 +
+ sudo_ldap_value_len(grp->gr_name)) * 2) + 1;
+ }
+ sz += ((sizeof("(sudoUser=%#)") - 1 + sizeof(idbuf) - 1) * 2) + 1;
+ if ((grlist = sudo_get_grlist(pw)) != NULL) {
+ for (i = 0; i < grlist->ngroups; i++) {
+ if (grp != NULL && strcasecmp(grlist->groups[i], grp->gr_name) == 0)
+ continue;
+ sz += ((sizeof("(sudoUser=%)") - 1 +
+ sudo_ldap_value_len(grlist->groups[i])) * 2) + 1;
+ }
+ }
+ if ((gidlist = sudo_get_gidlist(pw, ENTRY_TYPE_ANY)) != NULL) {
+ for (i = 0; i < gidlist->ngids; i++) {
+ if (pw->pw_gid == gidlist->gids[i])
+ continue;
+ sz += ((sizeof("(sudoUser=%#)") - 1 + sizeof(idbuf) - 1) * 2) + 1;
+ }
+ }
+
+ /* Add space for user netgroups if netgroup_base specified. */
+ if (ldap_conf.netgroup_query) {
+ DPRINTF1("Looking up netgroups for %s", pw->pw_name);
+ if (sudo_netgroup_lookup(ctx, ld, pw, &netgroups)) {
+ STAILQ_FOREACH(ng, &netgroups, entries) {
+ sz += ((sizeof("(sudoUser=+)") - 1 + strlen(ng->name)) * 2) + 1;
+ }
+ } else {
+ /* sudo_netgroup_lookup() failed, clean up. */
+ while ((ng = STAILQ_FIRST(&netgroups)) != NULL) {
+ STAILQ_REMOVE_HEAD(&netgroups, entries);
+ free(ng->name);
+ free(ng);
+ }
+ }
+ }
+
+ buf = malloc(sz);
+ notbuf = malloc(sz);
+ if (buf == NULL || notbuf == NULL)
+ goto bad;
+ *buf = '\0';
+ *notbuf = '\0';
+
+ /*
+ * If timed or using a search filter, start a global AND clause to
+ * contain the search filter, search criteria, and time restriction.
+ */
+ if (ldap_conf.timed || ldap_conf.search_filter)
+ CHECK_STRLCPY(buf, "(&", sz);
+
+ if (ldap_conf.search_filter)
+ CHECK_STRLCAT(buf, ldap_conf.search_filter, sz);
+
+ /* Global OR + sudoUser=user_name filter */
+ CHECK_STRLCAT(buf, "(|(sudoUser=", sz);
+ CHECK_LDAP_VCAT(buf, pw->pw_name, sz);
+ CHECK_STRLCAT(buf, ")", sz);
+ CHECK_STRLCAT(notbuf, "(sudoUser=!", sz);
+ CHECK_LDAP_VCAT(notbuf, pw->pw_name, sz);
+ CHECK_STRLCAT(notbuf, ")", sz);
+
+ /* Append user-ID */
+ (void) snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int)pw->pw_uid);
+ CHECK_STRLCAT(buf, "(sudoUser=#", sz);
+ CHECK_STRLCAT(buf, idbuf, sz);
+ CHECK_STRLCAT(buf, ")", sz);
+ CHECK_STRLCAT(notbuf, "(sudoUser=!#", sz);
+ CHECK_STRLCAT(notbuf, idbuf, sz);
+ CHECK_STRLCAT(notbuf, ")", sz);
+
+ /* Append primary group and group-ID */
+ if (grp != NULL) {
+ CHECK_STRLCAT(buf, "(sudoUser=%", sz);
+ CHECK_LDAP_VCAT(buf, grp->gr_name, sz);
+ CHECK_STRLCAT(buf, ")", sz);
+ CHECK_STRLCAT(notbuf, "(sudoUser=!%", sz);
+ CHECK_LDAP_VCAT(notbuf, grp->gr_name, sz);
+ CHECK_STRLCAT(notbuf, ")", sz);
+ }
+ (void) snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int)pw->pw_gid);
+ CHECK_STRLCAT(buf, "(sudoUser=%#", sz);
+ CHECK_STRLCAT(buf, idbuf, sz);
+ CHECK_STRLCAT(buf, ")", sz);
+ CHECK_STRLCAT(notbuf, "(sudoUser=!%#", sz);
+ CHECK_STRLCAT(notbuf, idbuf, sz);
+ CHECK_STRLCAT(notbuf, ")", sz);
+
+ /* Append supplementary groups and group-IDs */
+ if (grlist != NULL) {
+ for (i = 0; i < grlist->ngroups; i++) {
+ if (grp != NULL && strcasecmp(grlist->groups[i], grp->gr_name) == 0)
+ continue;
+ CHECK_STRLCAT(buf, "(sudoUser=%", sz);
+ CHECK_LDAP_VCAT(buf, grlist->groups[i], sz);
+ CHECK_STRLCAT(buf, ")", sz);
+ CHECK_STRLCAT(notbuf, "(sudoUser=!%", sz);
+ CHECK_LDAP_VCAT(notbuf, grlist->groups[i], sz);
+ CHECK_STRLCAT(notbuf, ")", sz);
+ }
+ }
+ if (gidlist != NULL) {
+ for (i = 0; i < gidlist->ngids; i++) {
+ if (pw->pw_gid == gidlist->gids[i])
+ continue;
+ (void) snprintf(idbuf, sizeof(idbuf), "%u",
+ (unsigned int)gidlist->gids[i]);
+ CHECK_STRLCAT(buf, "(sudoUser=%#", sz);
+ CHECK_STRLCAT(buf, idbuf, sz);
+ CHECK_STRLCAT(buf, ")", sz);
+ CHECK_STRLCAT(notbuf, "(sudoUser=!%#", sz);
+ CHECK_STRLCAT(notbuf, idbuf, sz);
+ CHECK_STRLCAT(notbuf, ")", sz);
+ }
+ }
+
+ /* Done with groups. */
+ if (gidlist != NULL)
+ sudo_gidlist_delref(gidlist);
+ if (grlist != NULL)
+ sudo_grlist_delref(grlist);
+ if (grp != NULL)
+ sudo_gr_delref(grp);
+
+ /* Add netgroups (if any), freeing the list as we go. */
+ while ((ng = STAILQ_FIRST(&netgroups)) != NULL) {
+ STAILQ_REMOVE_HEAD(&netgroups, entries);
+ CHECK_STRLCAT(buf, "(sudoUser=+", sz);
+ CHECK_LDAP_VCAT(buf, ng->name, sz);
+ CHECK_STRLCAT(buf, ")", sz);
+ CHECK_STRLCAT(notbuf, "(sudoUser=!+", sz);
+ CHECK_LDAP_VCAT(notbuf, ng->name, sz);
+ CHECK_STRLCAT(notbuf, ")", sz);
+ free(ng->name);
+ free(ng);
+ }
+
+ /* Add ALL to list. */
+ CHECK_STRLCAT(buf, "(sudoUser=ALL))", sz);
+
+ /* Add filter for negated entries. */
+ CHECK_STRLCAT(buf, "(!(|", sz);
+ CHECK_STRLCAT(buf, notbuf, sz);
+ CHECK_STRLCAT(buf, ")", sz);
+
+ /* Add the time restriction, or simply end the global OR. */
+ if (ldap_conf.timed) {
+ CHECK_STRLCAT(buf, ")", sz); /* closes the global OR */
+ if (!sudo_ldap_timefilter(timebuffer, sizeof(timebuffer)))
+ goto bad;
+ CHECK_STRLCAT(buf, timebuffer, sz);
+ } else if (ldap_conf.search_filter) {
+ CHECK_STRLCAT(buf, ")", sz); /* closes the global OR */
+ }
+
+ CHECK_STRLCAT(buf, ")", sz); /* closes the global OR or the global AND */
+
+ free(notbuf);
+ debug_return_str(buf);
+overflow:
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ if (ng != NULL) {
+ /* Overflow while traversing netgroups. */
+ free(ng->name);
+ free(ng);
+ }
+ errno = EOVERFLOW;
+bad:
+ while ((ng = STAILQ_FIRST(&netgroups)) != NULL) {
+ STAILQ_REMOVE_HEAD(&netgroups, entries);
+ free(ng->name);
+ free(ng);
+ }
+ free(buf);
+ free(notbuf);
+ debug_return_str(NULL);
+}
+
+/*
+ * Builds up a filter to check against non-Unix group
+ * entries in LDAP, including netgroups.
+ */
+static char *
+sudo_ldap_build_pass2(void)
+{
+ char *filt, timebuffer[TIMEFILTER_LENGTH + 1];
+ bool query_netgroups = def_use_netgroups;
+ int len;
+ debug_decl(sudo_ldap_build_pass2, SUDOERS_DEBUG_LDAP);
+
+ /*
+ * If we can query nisNetgroupTriple using netgroup_base, there is
+ * no need to match all netgroups in pass 2. If netgroups are not
+ * natively supported, netgroup_base must be set.
+ */
+ if (ldap_conf.netgroup_query)
+ query_netgroups = false;
+#ifndef HAVE_INNETGR
+ else if (STAILQ_EMPTY(&ldap_conf.netgroup_base))
+ query_netgroups = false;
+#endif
+
+ /* Short circuit if no netgroups and no non-Unix groups. */
+ if (!query_netgroups && !def_group_plugin) {
+ errno = ENOENT;
+ debug_return_str(NULL);
+ }
+
+ if (ldap_conf.timed) {
+ if (!sudo_ldap_timefilter(timebuffer, sizeof(timebuffer)))
+ debug_return_str(NULL);
+ }
+
+ /*
+ * Match all sudoUsers beginning with '+' or '%:'.
+ * If a search filter or time restriction is specified,
+ * those get ANDed in to the expression.
+ */
+ if (query_netgroups && def_group_plugin) {
+ len = asprintf(&filt, "%s%s(|(sudoUser=+*)(sudoUser=!+*)(sudoUser=%%:*)(sudoUser=!%%:*))%s%s",
+ (ldap_conf.timed || ldap_conf.search_filter) ? "(&" : "",
+ ldap_conf.search_filter ? ldap_conf.search_filter : "",
+ ldap_conf.timed ? timebuffer : "",
+ (ldap_conf.timed || ldap_conf.search_filter) ? ")" : "");
+ } else {
+ len = asprintf(&filt, "%s%s(|(sudoUser=%s*)(sudoUser=!%s*))%s%s",
+ (ldap_conf.timed || ldap_conf.search_filter) ? "(&" : "",
+ ldap_conf.search_filter ? ldap_conf.search_filter : "",
+ query_netgroups ? "+" : "%:", query_netgroups ? "+" : "%:",
+ ldap_conf.timed ? timebuffer : "",
+ (ldap_conf.timed || ldap_conf.search_filter) ? ")" : "");
+ }
+ if (len == -1)
+ filt = NULL;
+
+ debug_return_str(filt);
+}
+
+static char *
+berval_iter(void **vp)
+{
+ struct berval **bv = *vp;
+
+ *vp = bv + 1;
+ return *bv ? (*bv)->bv_val : NULL;
+}
+
+/*
+ * Wrapper for sudo_ldap_role_to_priv() that takes an LDAPMessage.
+ * Returns a struct privilege on success or NULL on failure.
+ */
+static struct privilege *
+ldap_entry_to_priv(LDAP *ld, LDAPMessage *entry, int *rc_out)
+{
+ struct berval **cmnds = NULL, **hosts = NULL;
+ struct berval **runasusers = NULL, **runasgroups = NULL;
+ struct berval **opts = NULL, **notbefore = NULL, **notafter = NULL;
+ struct privilege *priv = NULL;
+ char *cn = NULL;
+ int rc;
+ debug_decl(ldap_entry_to_priv, SUDOERS_DEBUG_LDAP);
+
+ /* Ignore sudoRole without sudoCommand or sudoHost. */
+ cmnds = sudo_ldap_get_values_len(ld, entry, "sudoCommand", &rc);
+ if (cmnds == NULL)
+ goto cleanup;
+ hosts = sudo_ldap_get_values_len(ld, entry, "sudoHost", &rc);
+ if (hosts == NULL)
+ goto cleanup;
+
+ /* Get the entry's dn for long format printing. */
+ if ((cn = sudo_ldap_get_first_rdn(ld, entry, &rc)) == NULL)
+ goto cleanup;
+
+ /* Get sudoRunAsUser / sudoRunAsGroup */
+ runasusers = sudo_ldap_get_values_len(ld, entry, "sudoRunAsUser", &rc);
+ if (runasusers == NULL) {
+ if (rc != LDAP_NO_MEMORY)
+ runasusers = sudo_ldap_get_values_len(ld, entry, "sudoRunAs", &rc);
+ if (rc == LDAP_NO_MEMORY)
+ goto cleanup;
+ }
+ runasgroups = sudo_ldap_get_values_len(ld, entry, "sudoRunAsGroup", &rc);
+ if (rc == LDAP_NO_MEMORY)
+ goto cleanup;
+
+ /* Get sudoNotBefore / sudoNotAfter */
+ if (ldap_conf.timed) {
+ notbefore = sudo_ldap_get_values_len(ld, entry, "sudoNotBefore", &rc);
+ if (rc == LDAP_NO_MEMORY)
+ goto cleanup;
+ notafter = sudo_ldap_get_values_len(ld, entry, "sudoNotAfter", &rc);
+ if (rc == LDAP_NO_MEMORY)
+ goto cleanup;
+ }
+
+ /* Parse sudoOptions. */
+ opts = sudo_ldap_get_values_len(ld, entry, "sudoOption", &rc);
+ if (rc == LDAP_NO_MEMORY)
+ goto cleanup;
+
+ priv = sudo_ldap_role_to_priv(cn, hosts, runasusers, runasgroups,
+ cmnds, opts, notbefore ? notbefore[0]->bv_val : NULL,
+ notafter ? notafter[0]->bv_val : NULL, false, true, berval_iter);
+ if (priv == NULL) {
+ rc = LDAP_NO_MEMORY;
+ goto cleanup;
+ }
+
+cleanup:
+ if (cn != NULL)
+ ldap_memfree(cn);
+ if (cmnds != NULL)
+ ldap_value_free_len(cmnds);
+ if (hosts != NULL)
+ ldap_value_free_len(hosts);
+ if (runasusers != NULL)
+ ldap_value_free_len(runasusers);
+ if (runasgroups != NULL)
+ ldap_value_free_len(runasgroups);
+ if (opts != NULL)
+ ldap_value_free_len(opts);
+ if (notbefore != NULL)
+ ldap_value_free_len(notbefore);
+ if (notafter != NULL)
+ ldap_value_free_len(notafter);
+
+ *rc_out = rc;
+ debug_return_ptr(priv);
+}
+
+static bool
+ldap_to_sudoers(LDAP *ld, struct ldap_result *lres,
+ struct userspec_list *ldap_userspecs)
+{
+ struct userspec *us;
+ struct member *m;
+ unsigned int i;
+ int rc;
+ debug_decl(ldap_to_sudoers, SUDOERS_DEBUG_LDAP);
+
+ /* We only have a single userspec */
+ if ((us = calloc(1, sizeof(*us))) == NULL)
+ goto oom;
+ us->file = sudo_rcstr_dup("LDAP");
+ TAILQ_INIT(&us->users);
+ TAILQ_INIT(&us->privileges);
+ STAILQ_INIT(&us->comments);
+ TAILQ_INSERT_TAIL(ldap_userspecs, us, entries);
+
+ /* The user has already matched, use ALL as wildcard. */
+ if ((m = sudo_ldap_new_member_all()) == NULL)
+ goto oom;
+ TAILQ_INSERT_TAIL(&us->users, m, entries);
+
+ /* Treat each entry as a separate privilege. */
+ for (i = 0; i < lres->nentries; i++) {
+ struct privilege *priv;
+
+ priv = ldap_entry_to_priv(ld, lres->entries[i].entry, &rc);
+ if (priv == NULL) {
+ if (rc == LDAP_NO_MEMORY)
+ goto oom;
+ continue;
+ }
+ TAILQ_INSERT_TAIL(&us->privileges, priv, entries);
+ }
+
+ debug_return_bool(true);
+
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ free_userspecs(ldap_userspecs);
+ debug_return_bool(false);
+}
+
+#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
+typedef unsigned int (*sudo_gss_krb5_ccache_name_t)(unsigned int *minor_status, const char *name, const char **old_name);
+static sudo_gss_krb5_ccache_name_t sudo_gss_krb5_ccache_name;
+
+static int
+sudo_set_krb5_ccache_name(const char *name, const char **old_name)
+{
+ int ret = 0;
+ unsigned int junk;
+ static bool initialized;
+ debug_decl(sudo_set_krb5_ccache_name, SUDOERS_DEBUG_LDAP);
+
+ if (!initialized) {
+ sudo_gss_krb5_ccache_name = (sudo_gss_krb5_ccache_name_t)
+ sudo_dso_findsym(SUDO_DSO_DEFAULT, "gss_krb5_ccache_name");
+ initialized = true;
+ }
+
+ /*
+ * Try to use gss_krb5_ccache_name() if possible.
+ * We also need to set KRB5CCNAME since some LDAP libs may not use
+ * gss_krb5_ccache_name().
+ */
+ if (sudo_gss_krb5_ccache_name != NULL) {
+ ret = (int)sudo_gss_krb5_ccache_name(&junk, name, old_name);
+ } else {
+ /* No gss_krb5_ccache_name(), fall back on KRB5CCNAME. */
+ if (old_name != NULL)
+ *old_name = sudo_getenv("KRB5CCNAME");
+ }
+ if (name != NULL && *name != '\0') {
+ if (sudo_setenv("KRB5CCNAME", name, true) == -1)
+ ret = -1;
+ } else {
+ if (sudo_unsetenv("KRB5CCNAME") == -1)
+ ret = -1;
+ }
+
+ debug_return_int(ret);
+}
+
+/*
+ * Make a copy of the credential cache file specified by KRB5CCNAME
+ * which must be readable by the user. The resulting cache file
+ * is root-owned and will be removed after authenticating via SASL.
+ */
+static char *
+sudo_krb5_copy_cc_file(struct sudoers_context *ctx)
+{
+ static char new_ccname[] = _PATH_TMP "sudocc_XXXXXXXX";
+ const char *old_ccname = ctx->user.ccname;
+ ssize_t nread, nwritten = -1;
+ char buf[10240], *ret = NULL;
+ int nfd, ofd = -1;
+ debug_decl(sudo_krb5_copy_cc_file, SUDOERS_DEBUG_LDAP);
+
+ old_ccname = sudo_krb5_ccname_path(old_ccname);
+ if (old_ccname != NULL) {
+ /* Open credential cache as user to prevent stolen creds. */
+ if (!set_perms(ctx, PERM_USER))
+ goto done;
+ ofd = open(old_ccname, O_RDONLY|O_NONBLOCK);
+ if (!restore_perms())
+ goto done;
+
+ if (ofd != -1) {
+ (void) fcntl(ofd, F_SETFL, 0);
+ if (sudo_lock_file(ofd, SUDO_LOCK)) {
+ nfd = mkstemp(new_ccname);
+ if (nfd != -1) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "copy ccache %s -> %s", old_ccname, new_ccname);
+ while ((nread = read(ofd, buf, sizeof(buf))) > 0) {
+ ssize_t off = 0;
+ do {
+ nwritten = write(nfd, buf + off,
+ (size_t)(nread - off));
+ if (nwritten == -1) {
+ sudo_warn("error writing to %s", new_ccname);
+ goto write_error;
+ }
+ off += nwritten;
+ } while (off < nread);
+ }
+ if (nread == -1)
+ sudo_warn("unable to read %s", new_ccname);
+write_error:
+ close(nfd);
+ if (nread != -1 && nwritten != -1) {
+ ret = new_ccname; /* success! */
+ } else {
+ unlink(new_ccname); /* failed */
+ }
+ } else {
+ sudo_warn("unable to create temp file %s", new_ccname);
+ }
+ }
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to open %s", old_ccname);
+ }
+ }
+done:
+ if (ofd != -1)
+ close(ofd);
+ debug_return_str(ret);
+}
+
+static int
+sudo_ldap_sasl_interact(LDAP *ld, unsigned int flags, void *_auth_id,
+ void *_interact)
+{
+ char *auth_id = (char *)_auth_id;
+ sasl_interact_t *interact = (sasl_interact_t *)_interact;
+ int ret = LDAP_SUCCESS;
+ debug_decl(sudo_ldap_sasl_interact, SUDOERS_DEBUG_LDAP);
+
+ for (; interact->id != SASL_CB_LIST_END; interact++) {
+ if (interact->id != SASL_CB_USER) {
+ sudo_warnx("sudo_ldap_sasl_interact: unexpected interact id %lu",
+ interact->id);
+ ret = LDAP_PARAM_ERROR;
+ break;
+ }
+
+ if (auth_id != NULL)
+ interact->result = auth_id;
+ else if (interact->defresult != NULL)
+ interact->result = interact->defresult;
+ else
+ interact->result = "";
+
+ interact->len = (unsigned int)strlen(interact->result);
+#if SASL_VERSION_MAJOR < 2
+ interact->result = strdup(interact->result);
+ if (interact->result == NULL) {
+ ret = LDAP_NO_MEMORY;
+ break;
+ }
+#endif /* SASL_VERSION_MAJOR < 2 */
+ DPRINTF2("sudo_ldap_sasl_interact: SASL_CB_USER %s",
+ (const char *)interact->result);
+ }
+ debug_return_int(ret);
+}
+#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
+
+/*
+ * Create a new sudo_ldap_result structure.
+ */
+static struct ldap_result *
+sudo_ldap_result_alloc(void)
+{
+ struct ldap_result *result;
+ debug_decl(sudo_ldap_result_alloc, SUDOERS_DEBUG_LDAP);
+
+ result = calloc(1, sizeof(*result));
+ if (result != NULL)
+ STAILQ_INIT(&result->searches);
+
+ debug_return_ptr(result);
+}
+
+/*
+ * Free the ldap result structure
+ */
+static void
+sudo_ldap_result_free(struct ldap_result *lres)
+{
+ struct ldap_search_result *s;
+ debug_decl(sudo_ldap_result_free, SUDOERS_DEBUG_LDAP);
+
+ if (lres != NULL) {
+ if (lres->nentries) {
+ free(lres->entries);
+ lres->entries = NULL;
+ }
+ while ((s = STAILQ_FIRST(&lres->searches)) != NULL) {
+ STAILQ_REMOVE_HEAD(&lres->searches, entries);
+ ldap_msgfree(s->searchresult);
+ free(s);
+ }
+ free(lres);
+ }
+ debug_return;
+}
+
+/*
+ * Add a search result to the ldap_result structure.
+ */
+static struct ldap_search_result *
+sudo_ldap_result_add_search(struct ldap_result *lres, LDAP *ldap,
+ LDAPMessage *searchresult)
+{
+ struct ldap_search_result *news;
+ debug_decl(sudo_ldap_result_add_search, SUDOERS_DEBUG_LDAP);
+
+ /* Create new entry and add it to the end of the chain. */
+ news = calloc(1, sizeof(*news));
+ if (news != NULL) {
+ news->ldap = ldap;
+ news->searchresult = searchresult;
+ STAILQ_INSERT_TAIL(&lres->searches, news, entries);
+ }
+
+ debug_return_ptr(news);
+}
+
+/*
+ * Connect to the LDAP server specified by ld.
+ * Returns LDAP_SUCCESS on success, else non-zero.
+ */
+static int
+sudo_ldap_bind_s(struct sudoers_context *ctx, LDAP *ld)
+{
+ int ret;
+ debug_decl(sudo_ldap_bind_s, SUDOERS_DEBUG_LDAP);
+
+#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
+ if (ldap_conf.rootuse_sasl == true ||
+ (ldap_conf.rootuse_sasl != false && ldap_conf.use_sasl == true)) {
+ const char *old_ccname = NULL;
+ const char *new_ccname = ldap_conf.krb5_ccname;
+ const char *tmp_ccname = NULL;
+ void *auth_id = ldap_conf.rootsasl_auth_id ?
+ ldap_conf.rootsasl_auth_id : ldap_conf.sasl_auth_id;
+ int rc;
+
+ /* Make temp copy of the user's credential cache as needed. */
+ if (ldap_conf.krb5_ccname == NULL && ctx->user.ccname != NULL) {
+ new_ccname = tmp_ccname = sudo_krb5_copy_cc_file(ctx);
+ if (tmp_ccname == NULL) {
+ /* XXX - fatal error */
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "unable to copy user ccache %s", ctx->user.ccname);
+ }
+ }
+
+ if (new_ccname != NULL) {
+ rc = sudo_set_krb5_ccache_name(new_ccname, &old_ccname);
+ if (rc == 0) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "set ccache name %s -> %s",
+ old_ccname ? old_ccname : "(none)", new_ccname);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "sudo_set_krb5_ccache_name() failed: %d", rc);
+ }
+ }
+ ret = ldap_sasl_interactive_bind_s(ld, ldap_conf.binddn,
+ ldap_conf.sasl_mech, NULL, NULL, LDAP_SASL_QUIET,
+ sudo_ldap_sasl_interact, auth_id);
+ if (new_ccname != NULL) {
+ rc = sudo_set_krb5_ccache_name(old_ccname ? old_ccname : "", NULL);
+ if (rc == 0) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "restore ccache name %s -> %s", new_ccname,
+ old_ccname ? old_ccname : "(none)");
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "sudo_set_krb5_ccache_name() failed: %d", rc);
+ }
+ /* Remove temporary copy of user's credential cache. */
+ if (tmp_ccname != NULL)
+ unlink(tmp_ccname);
+ }
+ if (ret != LDAP_SUCCESS) {
+ sudo_warnx("ldap_sasl_interactive_bind_s(): %s",
+ ldap_err2string(ret));
+ goto done;
+ }
+ DPRINTF1("ldap_sasl_interactive_bind_s() ok");
+ } else
+#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
+#ifdef HAVE_LDAP_SASL_BIND_S
+ {
+ struct berval bv;
+
+ bv.bv_val = ldap_conf.bindpw ? ldap_conf.bindpw : (char *)"";
+ bv.bv_len = strlen(bv.bv_val);
+
+ ret = ldap_sasl_bind_s(ld, ldap_conf.binddn, LDAP_SASL_SIMPLE, &bv,
+ NULL, NULL, NULL);
+ if (ret != LDAP_SUCCESS) {
+ sudo_warnx("ldap_sasl_bind_s(): %s", ldap_err2string(ret));
+ goto done;
+ }
+ DPRINTF1("ldap_sasl_bind_s() ok");
+ }
+#else
+ {
+ ret = ldap_simple_bind_s(ld, ldap_conf.binddn, ldap_conf.bindpw);
+ if (ret != LDAP_SUCCESS) {
+ sudo_warnx("ldap_simple_bind_s(): %s", ldap_err2string(ret));
+ goto done;
+ }
+ DPRINTF1("ldap_simple_bind_s() ok");
+ }
+#endif
+done:
+ debug_return_int(ret);
+}
+
+/*
+ * Shut down the LDAP connection.
+ */
+static int
+sudo_ldap_close(struct sudoers_context *ctx, struct sudo_nss *nss)
+{
+ struct sudo_ldap_handle *handle = nss->handle;
+ debug_decl(sudo_ldap_close, SUDOERS_DEBUG_LDAP);
+
+ if (handle != NULL) {
+ /* Unbind and close the LDAP connection. */
+ if (handle->ld != NULL) {
+ ldap_unbind_ext_s(handle->ld, NULL, NULL);
+ handle->ld = NULL;
+ }
+
+ /* Free the handle container. */
+ if (handle->pw != NULL)
+ sudo_pw_delref(handle->pw);
+ free_parse_tree(&handle->parse_tree);
+ free(handle);
+ nss->handle = NULL;
+ }
+ debug_return_int(0);
+}
+
+/*
+ * Open a connection to the LDAP server.
+ * Returns 0 on success and non-zero on failure.
+ */
+static int
+sudo_ldap_open(struct sudoers_context *ctx, struct sudo_nss *nss)
+{
+ LDAP *ld;
+ int rc = -1;
+ bool ldapnoinit = false;
+ struct sudo_ldap_handle *handle;
+ debug_decl(sudo_ldap_open, SUDOERS_DEBUG_LDAP);
+
+ if (nss->handle != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: called with non-NULL handle %p", __func__, nss->handle);
+ sudo_ldap_close(ctx, nss);
+ }
+
+ if (!sudo_ldap_read_config(ctx))
+ goto done;
+
+ /* Prevent reading of user ldaprc and system defaults. */
+ if (sudo_getenv("LDAPNOINIT") == NULL) {
+ if (sudo_setenv("LDAPNOINIT", "1", true) == 0)
+ ldapnoinit = true;
+ }
+
+ /* Set global LDAP options */
+ if (sudo_ldap_set_options_global() != LDAP_SUCCESS)
+ goto done;
+
+ /* Connect to LDAP server */
+#ifdef HAVE_LDAP_INITIALIZE
+ if (!STAILQ_EMPTY(&ldap_conf.uri)) {
+ char *buf = sudo_ldap_join_uri(&ldap_conf.uri);
+ if (buf == NULL)
+ goto done;
+ DPRINTF2("ldap_initialize(ld, %s)", buf);
+ rc = ldap_initialize(&ld, buf);
+ free(buf);
+ } else
+#endif
+ rc = sudo_ldap_init(ctx, &ld, ldap_conf.host, ldap_conf.port);
+ if (rc != LDAP_SUCCESS) {
+ sudo_warnx(U_("unable to initialize LDAP: %s"), ldap_err2string(rc));
+ goto done;
+ }
+
+ /* Set LDAP per-connection options */
+ rc = sudo_ldap_set_options_conn(ld);
+ if (rc != LDAP_SUCCESS)
+ goto done;
+
+ if (ldapnoinit)
+ (void) sudo_unsetenv("LDAPNOINIT");
+
+ if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS) {
+#if defined(HAVE_LDAP_START_TLS_S)
+ rc = ldap_start_tls_s(ld, NULL, NULL);
+ if (rc != LDAP_SUCCESS) {
+ sudo_warnx("ldap_start_tls_s(): %s", ldap_err2string(rc));
+ goto done;
+ }
+ DPRINTF1("ldap_start_tls_s() ok");
+#elif defined(HAVE_LDAP_SSL_CLIENT_INIT) && defined(HAVE_LDAP_START_TLS_S_NP)
+ int sslrc;
+ rc = ldap_ssl_client_init(ldap_conf.tls_keyfile, ldap_conf.tls_keypw,
+ 0, &sslrc);
+ if (rc != LDAP_SUCCESS) {
+ sudo_warnx("ldap_ssl_client_init(): %s: %s",
+ ldap_err2string(rc), ssl_err2string(sslrc));
+ goto done;
+ }
+ rc = ldap_start_tls_s_np(ld, NULL);
+ if (rc != LDAP_SUCCESS) {
+ sudo_warnx("ldap_start_tls_s_np(): %s", ldap_err2string(rc));
+ goto done;
+ }
+ DPRINTF1("ldap_start_tls_s_np() ok");
+#else
+ sudo_warnx("%s",
+ U_("start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"));
+#endif /* !HAVE_LDAP_START_TLS_S && !HAVE_LDAP_START_TLS_S_NP */
+ }
+
+ /* Actually connect */
+ rc = sudo_ldap_bind_s(ctx, ld);
+ if (rc != LDAP_SUCCESS)
+ goto done;
+
+ /* Create a handle container. */
+ handle = calloc(1, sizeof(struct sudo_ldap_handle));
+ if (handle == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ rc = -1;
+ goto done;
+ }
+ handle->ld = ld;
+ /* handle->pw = NULL; */
+ init_parse_tree(&handle->parse_tree, NULL, NULL, ctx, nss);
+ nss->handle = handle;
+
+done:
+ debug_return_int(rc == LDAP_SUCCESS ? 0 : -1);
+}
+
+static int
+sudo_ldap_getdefs(struct sudoers_context *ctx, const struct sudo_nss *nss)
+{
+ struct sudo_ldap_handle *handle = nss->handle;
+ struct timeval tv, *tvp = NULL;
+ struct ldap_config_str *base;
+ LDAPMessage *entry, *result = NULL;
+ char *filt = NULL;
+ int rc, ret = -1;
+ static bool cached;
+ debug_decl(sudo_ldap_getdefs, SUDOERS_DEBUG_LDAP);
+
+ if (handle == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: called with NULL handle", __func__);
+ debug_return_int(-1);
+ }
+
+ /* Use cached result if present. */
+ if (cached)
+ debug_return_int(0);
+
+ filt = sudo_ldap_build_default_filter();
+ if (filt == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(-1);
+ }
+ DPRINTF1("Looking for cn=defaults: %s", filt);
+
+ STAILQ_FOREACH(base, &ldap_conf.base, entries) {
+ LDAP *ld = handle->ld;
+
+ if (ldap_conf.timeout > 0) {
+ tv.tv_sec = ldap_conf.timeout;
+ tv.tv_usec = 0;
+ tvp = &tv;
+ }
+ ldap_msgfree(result);
+ result = NULL;
+ rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE,
+ filt, NULL, 0, NULL, NULL, tvp, 0, &result);
+ if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) {
+ DPRINTF1("found:%s", ldap_get_dn(ld, entry));
+ if (!sudo_ldap_parse_options(ld, entry, &handle->parse_tree.defaults))
+ goto done;
+ } else {
+ DPRINTF1("no default options found in %s", base->val);
+ }
+ }
+ cached = true;
+ ret = 0;
+
+done:
+ ldap_msgfree(result);
+ free(filt);
+
+ debug_return_int(ret);
+}
+
+/*
+ * Comparison function for ldap_entry_wrapper structures, ascending order.
+ * This should match role_order_cmp() in parse_ldif.c.
+ */
+static int
+ldap_entry_compare(const void *a, const void *b)
+{
+ const struct ldap_entry_wrapper *aw = a;
+ const struct ldap_entry_wrapper *bw = b;
+ debug_decl(ldap_entry_compare, SUDOERS_DEBUG_LDAP);
+
+ debug_return_int(aw->order < bw->order ? -1 :
+ (aw->order > bw->order ? 1 : 0));
+}
+
+/*
+ * Return the last entry in the list of searches, usually the
+ * one currently being used to add entries.
+ */
+static struct ldap_search_result *
+sudo_ldap_result_last_search(struct ldap_result *lres)
+{
+ debug_decl(sudo_ldap_result_last_search, SUDOERS_DEBUG_LDAP);
+
+ debug_return_ptr(STAILQ_LAST(&lres->searches, ldap_search_result, entries));
+}
+
+/*
+ * Add an entry to the result structure.
+ */
+static struct ldap_entry_wrapper *
+sudo_ldap_result_add_entry(struct ldap_result *lres, LDAPMessage *entry)
+{
+ struct ldap_search_result *last;
+ struct berval **bv;
+ double order = 0.0;
+ char *ep;
+ int rc;
+ debug_decl(sudo_ldap_result_add_entry, SUDOERS_DEBUG_LDAP);
+
+ /* Determine whether the entry has the sudoOrder attribute. */
+ last = sudo_ldap_result_last_search(lres);
+ if (last != NULL) {
+ bv = sudo_ldap_get_values_len(last->ldap, entry, "sudoOrder", &rc);
+ if (bv == NULL) {
+ if (rc == LDAP_NO_MEMORY)
+ debug_return_ptr(NULL);
+ } else {
+ if (ldap_count_values_len(bv) > 0) {
+ /* Get the value of this attribute, 0 if not present. */
+ DPRINTF2("order attribute raw: %s", (*bv)->bv_val);
+ order = strtod((*bv)->bv_val, &ep);
+ if (ep == (*bv)->bv_val || *ep != '\0') {
+ sudo_warnx(U_("invalid sudoOrder attribute: %s"),
+ (*bv)->bv_val);
+ order = 0.0;
+ }
+ DPRINTF2("order attribute: %f", order);
+ }
+ ldap_value_free_len(bv);
+ }
+ }
+
+ /*
+ * Enlarge the array of entry wrappers as needed, preallocating blocks
+ * of 100 entries to save on allocation time.
+ */
+ if (++lres->nentries > lres->allocated_entries) {
+ unsigned int allocated_entries =
+ lres->allocated_entries + ALLOCATION_INCREMENT;
+ struct ldap_entry_wrapper *entries = reallocarray(lres->entries,
+ allocated_entries, sizeof(lres->entries[0]));
+ if (entries == NULL)
+ debug_return_ptr(NULL);
+ lres->allocated_entries = allocated_entries;
+ lres->entries = entries;
+ }
+
+ /* Fill in the new entry and return it. */
+ lres->entries[lres->nentries - 1].entry = entry;
+ lres->entries[lres->nentries - 1].order = order;
+
+ debug_return_ptr(&lres->entries[lres->nentries - 1]);
+}
+
+/*
+ * Perform the LDAP query for the user. The caller is responsible for
+ * freeing the result with sudo_ldap_result_free().
+ */
+static struct ldap_result *
+sudo_ldap_result_get(struct sudoers_context *ctx, const struct sudo_nss *nss,
+ struct passwd *pw)
+{
+ struct sudo_ldap_handle *handle = nss->handle;
+ struct ldap_config_str *base;
+ struct ldap_result *lres;
+ struct timeval tv, *tvp = NULL;
+ LDAPMessage *entry, *result;
+ LDAP *ld = handle->ld;
+ char *filt = NULL;
+ int pass, rc;
+ debug_decl(sudo_ldap_result_get, SUDOERS_DEBUG_LDAP);
+
+ /*
+ * Okay - time to search for anything that matches this user
+ * Lets limit it to only two queries of the LDAP server
+ *
+ * The first pass will look by the username, groups, and
+ * the keyword ALL. We will then inspect the results that
+ * came back from the query. We don't need to inspect the
+ * sudoUser in this pass since the LDAP server already scanned
+ * it for us.
+ *
+ * The second pass will return all the entries that contain non-
+ * Unix groups, including netgroups. Then we take the non-Unix
+ * groups returned and try to match them against the username.
+ *
+ * Since we have to sort the possible entries before we make a
+ * decision, we perform the queries and store all of the results in
+ * an ldap_result object. The results are then sorted by sudoOrder.
+ */
+ lres = sudo_ldap_result_alloc();
+ if (lres == NULL)
+ goto oom;
+ for (pass = 0; pass < 2; pass++) {
+ filt = pass ? sudo_ldap_build_pass2() : sudo_ldap_build_pass1(ctx, ld, pw);
+ if (filt != NULL) {
+ DPRINTF1("ldap search '%s'", filt);
+ STAILQ_FOREACH(base, &ldap_conf.base, entries) {
+ DPRINTF1("searching from base '%s'",
+ base->val);
+ if (ldap_conf.timeout > 0) {
+ tv.tv_sec = ldap_conf.timeout;
+ tv.tv_usec = 0;
+ tvp = &tv;
+ }
+ result = NULL;
+ rc = ldap_search_ext_s(ld, base->val, LDAP_SCOPE_SUBTREE, filt,
+ NULL, 0, NULL, NULL, tvp, 0, &result);
+ if (rc != LDAP_SUCCESS) {
+ DPRINTF1("ldap search pass %d failed: %s", pass + 1,
+ ldap_err2string(rc));
+ continue;
+ }
+
+ /* Add the search result to list of search results. */
+ DPRINTF1("adding search result");
+ if (sudo_ldap_result_add_search(lres, ld, result) == NULL)
+ goto oom;
+ LDAP_FOREACH(entry, ld, result) {
+ if (pass != 0) {
+ /* Check non-unix group in 2nd pass. */
+ switch (sudo_ldap_check_non_unix_group(ctx, nss, entry,
+ pw)) {
+ case -1:
+ goto oom;
+ case false:
+ continue;
+ default:
+ break;
+ }
+ }
+ if (sudo_ldap_result_add_entry(lres, entry) == NULL)
+ goto oom;
+ }
+ DPRINTF1("result now has %d entries", lres->nentries);
+ }
+ free(filt);
+ } else if (errno != ENOENT) {
+ /* Out of memory? */
+ goto oom;
+ }
+ }
+
+ /* Sort the entries by the sudoOrder attribute. */
+ if (lres->nentries != 0) {
+ DPRINTF1("sorting remaining %d entries", lres->nentries);
+ qsort(lres->entries, lres->nentries, sizeof(lres->entries[0]),
+ ldap_entry_compare);
+ }
+
+ debug_return_ptr(lres);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ free(filt);
+ sudo_ldap_result_free(lres);
+ debug_return_ptr(NULL);
+}
+
+/*
+ * Perform LDAP query for user and host and convert to sudoers
+ * parse tree.
+ */
+static int
+sudo_ldap_query(struct sudoers_context *ctx, const struct sudo_nss *nss,
+ struct passwd *pw)
+{
+ struct sudo_ldap_handle *handle = nss->handle;
+ struct ldap_result *lres = NULL;
+ int ret = -1;
+ debug_decl(sudo_ldap_query, SUDOERS_DEBUG_LDAP);
+
+ if (handle == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: called with NULL handle", __func__);
+ debug_return_int(-1);
+ }
+
+ /* Use cached result if it matches pw. */
+ if (handle->pw != NULL) {
+ if (pw == handle->pw) {
+ ret = 0;
+ goto done;
+ }
+ sudo_pw_delref(handle->pw);
+ handle->pw = NULL;
+ }
+
+ /* Free old userspecs, if any. */
+ free_userspecs(&handle->parse_tree.userspecs);
+
+ DPRINTF1("%s: ldap search user %s, host %s", __func__, pw->pw_name,
+ ctx->runas.host);
+ if ((lres = sudo_ldap_result_get(ctx, nss, pw)) == NULL)
+ goto done;
+
+ /* Convert to sudoers parse tree. */
+ if (!ldap_to_sudoers(handle->ld, lres, &handle->parse_tree.userspecs))
+ goto done;
+
+ /* Stash a ref to the passwd struct in the handle. */
+ sudo_pw_addref(pw);
+ handle->pw = pw;
+
+ ret = 0;
+
+done:
+ /* Cleanup. */
+ sudo_ldap_result_free(lres);
+ if (ret == -1)
+ free_userspecs(&handle->parse_tree.userspecs);
+ debug_return_int(ret);
+}
+
+/*
+ * Return the initialized (but empty) sudoers parse tree.
+ * The contents will be populated by the getdefs() and query() functions.
+ */
+static struct sudoers_parse_tree *
+sudo_ldap_parse(struct sudoers_context *ctx, const struct sudo_nss *nss)
+{
+ struct sudo_ldap_handle *handle = nss->handle;
+ debug_decl(sudo_ldap_parse, SUDOERS_DEBUG_LDAP);
+
+ if (handle == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: called with NULL handle", __func__);
+ debug_return_ptr(NULL);
+ }
+
+ debug_return_ptr(&handle->parse_tree);
+}
+
+static int
+sudo_ldap_innetgr(const struct sudo_nss *nss, const char *netgr,
+ const char *host, const char *user, const char *domain)
+{
+ const struct sudo_ldap_handle *handle = nss->handle;
+ return sudo_ldap_innetgr_int(handle->ld, netgr, host, user, domain);
+}
+
+#if 0
+/*
+ * Create an ldap_result from an LDAP search result.
+ *
+ * This function is currently not used anywhere, it is left here as
+ * an example of how to use the cached searches.
+ */
+static struct ldap_result *
+sudo_ldap_result_from_search(LDAP *ldap, LDAPMessage *searchresult)
+{
+ struct ldap_search_result *last;
+ struct ldap_result *result;
+ LDAPMessage *entry;
+
+ /*
+ * An ldap_result is built from several search results, which are
+ * organized in a list. The head of the list is maintained in the
+ * ldap_result structure, together with the wrappers that point
+ * to individual entries, this has to be initialized first.
+ */
+ result = sudo_ldap_result_alloc();
+ if (result == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_ptr(NULL);
+ }
+
+ /*
+ * Build a new list node for the search result, this creates the
+ * list node.
+ */
+ last = sudo_ldap_result_add_search(result, ldap, searchresult);
+
+ /*
+ * Now add each entry in the search result to the array of of entries
+ * in the ldap_result object.
+ */
+ LDAP_FOREACH(entry, last->ldap, last->searchresult) {
+ if (sudo_ldap_result_add_entry(result, entry) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ sudo_ldap_result_free(result);
+ result = NULL;
+ break;
+ }
+ }
+ DPRINTF1("sudo_ldap_result_from_search: %d entries found",
+ result ? result->nentries : -1);
+ return result;
+}
+#endif
+
+/* sudo_nss implementation */
+struct sudo_nss sudo_nss_ldap = {
+ { NULL, NULL },
+ "ldap",
+ sudo_ldap_open,
+ sudo_ldap_close,
+ sudo_ldap_parse,
+ sudo_ldap_query,
+ sudo_ldap_getdefs,
+ sudo_ldap_innetgr
+};
diff --git a/plugins/sudoers/ldap_conf.c b/plugins/sudoers/ldap_conf.c
new file mode 100644
index 0000000..10e2373
--- /dev/null
+++ b/plugins/sudoers/ldap_conf.c
@@ -0,0 +1,960 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2003-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * This code is derived from software contributed by Aaron Spangler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+#ifdef HAVE_LBER_H
+# include <lber.h>
+#endif
+#include <ldap.h>
+#if defined(HAVE_LDAP_SSL_H)
+# include <ldap_ssl.h>
+#elif defined(HAVE_MPS_LDAP_SSL_H)
+# include <mps/ldap_ssl.h>
+#endif
+
+#include <sudoers.h>
+#include <sudo_lbuf.h>
+#include <sudo_ldap.h>
+#include <sudo_ldap_conf.h>
+
+/* Older Netscape LDAP SDKs don't prototype ldapssl_set_strength() */
+#if defined(HAVE_LDAPSSL_SET_STRENGTH) && !defined(HAVE_LDAP_SSL_H) && !defined(HAVE_MPS_LDAP_SSL_H)
+extern int ldapssl_set_strength(LDAP *ldap, int strength);
+#endif
+
+#if !defined(LDAP_OPT_NETWORK_TIMEOUT) && defined(LDAP_OPT_CONNECT_TIMEOUT)
+# define LDAP_OPT_NETWORK_TIMEOUT LDAP_OPT_CONNECT_TIMEOUT
+#endif
+
+#ifndef LDAPS_PORT
+# define LDAPS_PORT 636
+#endif
+
+/* Default search filter. */
+#define DEFAULT_SEARCH_FILTER "(objectClass=sudoRole)"
+
+/* Default netgroup search filter. */
+#define DEFAULT_NETGROUP_SEARCH_FILTER "(objectClass=nisNetgroup)"
+
+/* LDAP configuration structure */
+struct ldap_config ldap_conf;
+
+static struct ldap_config_table ldap_conf_global[] = {
+ { "sudoers_debug", CONF_INT, -1, &ldap_conf.debug },
+ { "host", CONF_STR, -1, &ldap_conf.host },
+ { "port", CONF_INT, -1, &ldap_conf.port },
+ { "ssl", CONF_STR, -1, &ldap_conf.ssl },
+ { "sslpath", CONF_STR, -1, &ldap_conf.tls_certfile },
+ { "uri", CONF_LIST_STR, -1, &ldap_conf.uri },
+#ifdef LDAP_OPT_DEBUG_LEVEL
+ { "debug", CONF_INT, LDAP_OPT_DEBUG_LEVEL, &ldap_conf.ldap_debug },
+#endif
+#ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
+ { "tls_checkpeer", CONF_BOOL, LDAP_OPT_X_TLS_REQUIRE_CERT,
+ &ldap_conf.tls_checkpeer },
+ { "tls_reqcert", CONF_REQCERT_VAL, LDAP_OPT_X_TLS_REQUIRE_CERT,
+ &ldap_conf.tls_reqcert },
+#else
+ { "tls_checkpeer", CONF_BOOL, -1, &ldap_conf.tls_checkpeer },
+#endif
+#ifdef LDAP_OPT_X_TLS_CACERTFILE
+ { "tls_cacertfile", CONF_STR, LDAP_OPT_X_TLS_CACERTFILE,
+ &ldap_conf.tls_cacertfile },
+ { "tls_cacert", CONF_STR, LDAP_OPT_X_TLS_CACERTFILE,
+ &ldap_conf.tls_cacertfile },
+#endif
+#ifdef LDAP_OPT_X_TLS_CACERTDIR
+ { "tls_cacertdir", CONF_STR, LDAP_OPT_X_TLS_CACERTDIR,
+ &ldap_conf.tls_cacertdir },
+#endif
+#ifdef LDAP_OPT_X_TLS_RANDOM_FILE
+ { "tls_randfile", CONF_STR, LDAP_OPT_X_TLS_RANDOM_FILE,
+ &ldap_conf.tls_random_file },
+#endif
+#ifdef LDAP_OPT_X_TLS_CIPHER_SUITE
+ { "tls_ciphers", CONF_STR, LDAP_OPT_X_TLS_CIPHER_SUITE,
+ &ldap_conf.tls_cipher_suite },
+#elif defined(LDAP_OPT_SSL_CIPHER)
+ { "tls_ciphers", CONF_STR, LDAP_OPT_SSL_CIPHER,
+ &ldap_conf.tls_cipher_suite },
+#endif
+#ifdef LDAP_OPT_X_TLS_CERTFILE
+ { "tls_cert", CONF_STR, LDAP_OPT_X_TLS_CERTFILE,
+ &ldap_conf.tls_certfile },
+#else
+ { "tls_cert", CONF_STR, -1, &ldap_conf.tls_certfile },
+#endif
+#ifdef LDAP_OPT_X_TLS_KEYFILE
+ { "tls_key", CONF_STR, LDAP_OPT_X_TLS_KEYFILE,
+ &ldap_conf.tls_keyfile },
+#else
+ { "tls_key", CONF_STR, -1, &ldap_conf.tls_keyfile },
+#endif
+#ifdef HAVE_LDAP_SSL_CLIENT_INIT
+ { "tls_keypw", CONF_STR, -1, &ldap_conf.tls_keypw },
+#endif
+ { "binddn", CONF_STR, -1, &ldap_conf.binddn },
+ { "bindpw", CONF_STR, -1, &ldap_conf.bindpw },
+ { "rootbinddn", CONF_STR, -1, &ldap_conf.rootbinddn },
+ { "sudoers_base", CONF_LIST_STR, -1, &ldap_conf.base },
+ { "sudoers_timed", CONF_BOOL, -1, &ldap_conf.timed },
+ { "sudoers_search_filter", CONF_STR, -1, &ldap_conf.search_filter },
+ { "netgroup_base", CONF_LIST_STR, -1, &ldap_conf.netgroup_base },
+ { "netgroup_search_filter", CONF_STR, -1, &ldap_conf.netgroup_search_filter },
+ { "netgroup_query", CONF_BOOL, -1, &ldap_conf.netgroup_query },
+#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
+ { "use_sasl", CONF_BOOL, -1, &ldap_conf.use_sasl },
+ { "sasl_mech", CONF_STR, -1, &ldap_conf.sasl_mech },
+ { "sasl_auth_id", CONF_STR, -1, &ldap_conf.sasl_auth_id },
+ { "rootuse_sasl", CONF_BOOL, -1, &ldap_conf.rootuse_sasl },
+ { "rootsasl_auth_id", CONF_STR, -1, &ldap_conf.rootsasl_auth_id },
+ { "krb5_ccname", CONF_STR, -1, &ldap_conf.krb5_ccname },
+#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
+ { NULL }
+};
+
+static struct ldap_config_table ldap_conf_conn[] = {
+#ifdef LDAP_OPT_PROTOCOL_VERSION
+ { "ldap_version", CONF_INT, LDAP_OPT_PROTOCOL_VERSION,
+ &ldap_conf.version },
+#endif
+#ifdef LDAP_OPT_NETWORK_TIMEOUT
+ { "bind_timelimit", CONF_INT, -1 /* needs timeval, set manually */,
+ &ldap_conf.bind_timelimit },
+ { "network_timeout", CONF_INT, -1 /* needs timeval, set manually */,
+ &ldap_conf.bind_timelimit },
+#elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
+ { "bind_timelimit", CONF_INT, LDAP_X_OPT_CONNECT_TIMEOUT,
+ &ldap_conf.bind_timelimit },
+ { "network_timeout", CONF_INT, LDAP_X_OPT_CONNECT_TIMEOUT,
+ &ldap_conf.bind_timelimit },
+#endif
+ { "timelimit", CONF_INT, LDAP_OPT_TIMELIMIT, &ldap_conf.timelimit },
+#ifdef LDAP_OPT_TIMEOUT
+ { "timeout", CONF_INT, -1 /* needs timeval, set manually */,
+ &ldap_conf.timeout },
+#endif
+#ifdef LDAP_OPT_DEREF
+ { "deref", CONF_DEREF_VAL, LDAP_OPT_DEREF, &ldap_conf.deref },
+#endif
+#ifdef LDAP_OPT_X_SASL_SECPROPS
+ { "sasl_secprops", CONF_STR, LDAP_OPT_X_SASL_SECPROPS,
+ &ldap_conf.sasl_secprops },
+#endif
+ { NULL }
+};
+
+#ifdef HAVE_LDAP_CREATE
+/*
+ * Rebuild the hosts list and include a specific port for each host.
+ * ldap_create() does not take a default port parameter so we must
+ * append one if we want something other than LDAP_PORT.
+ */
+static bool
+sudo_ldap_conf_add_ports(void)
+{
+ char *host, *last, *port, defport[13];
+ char hostbuf[LINE_MAX * 2];
+ int len;
+ debug_decl(sudo_ldap_conf_add_ports, SUDOERS_DEBUG_LDAP);
+
+ hostbuf[0] = '\0';
+ len = snprintf(defport, sizeof(defport), ":%d", ldap_conf.port);
+ if (len < 0 || len >= ssizeof(defport)) {
+ sudo_warnx(U_("%s: port too large"), __func__);
+ debug_return_bool(false);
+ }
+
+ for ((host = strtok_r(ldap_conf.host, " \t", &last)); host; (host = strtok_r(NULL, " \t", &last))) {
+ if (hostbuf[0] != '\0')
+ CHECK_STRLCAT(hostbuf, " ", sizeof(hostbuf));
+ CHECK_STRLCAT(hostbuf, host, sizeof(hostbuf));
+
+ /* Append port if there is not one already. */
+ if ((port = strrchr(host, ':')) == NULL ||
+ !isdigit((unsigned char)port[1])) {
+ CHECK_STRLCAT(hostbuf, defport, sizeof(hostbuf));
+ }
+ }
+
+ free(ldap_conf.host);
+ if ((ldap_conf.host = strdup(hostbuf)) == NULL)
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(ldap_conf.host != NULL);
+
+overflow:
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ debug_return_bool(false);
+}
+#endif
+
+#ifndef HAVE_LDAP_INITIALIZE
+/*
+ * For each uri, convert to host:port pairs. For ldaps:// enable SSL
+ * Accepts: uris of the form ldap:/// or ldap://hostname:portnum/
+ * where the trailing slash is optional.
+ * Returns LDAP_SUCCESS on success, else non-zero.
+ */
+static int
+sudo_ldap_parse_uri(const struct ldap_config_str_list *uri_list)
+{
+ const struct ldap_config_str *entry;
+ char *buf, hostbuf[LINE_MAX];
+ int nldap = 0, nldaps = 0;
+ int ret = -1;
+ debug_decl(sudo_ldap_parse_uri, SUDOERS_DEBUG_LDAP);
+
+ hostbuf[0] = '\0';
+ STAILQ_FOREACH(entry, uri_list, entries) {
+ char *cp, *last, *uri;
+ const char *host, *port;
+
+ buf = strdup(entry->val);
+ if (buf == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ for ((uri = strtok_r(buf, " \t", &last)); uri != NULL; (uri = strtok_r(NULL, " \t", &last))) {
+ if (strncasecmp(uri, "ldap://", 7) == 0) {
+ nldap++;
+ host = uri + 7;
+ } else if (strncasecmp(uri, "ldaps://", 8) == 0) {
+ nldaps++;
+ host = uri + 8;
+ } else {
+ sudo_warnx(U_("unsupported LDAP uri type: %s"), uri);
+ goto done;
+ }
+
+ /* trim optional trailing slash */
+ if ((cp = strrchr(host, '/')) != NULL && cp[1] == '\0') {
+ *cp = '\0';
+ }
+
+ if (hostbuf[0] != '\0')
+ CHECK_STRLCAT(hostbuf, " ", sizeof(hostbuf));
+
+ if (*host == '\0')
+ host = "localhost"; /* no host specified, use localhost */
+
+ CHECK_STRLCAT(hostbuf, host, sizeof(hostbuf));
+
+ /* If using SSL and no port specified, add port 636 */
+ if (nldaps) {
+ if ((port = strrchr(host, ':')) == NULL ||
+ !isdigit((unsigned char)port[1]))
+ CHECK_STRLCAT(hostbuf, ":636", sizeof(hostbuf));
+ }
+ }
+
+ if (nldaps != 0) {
+ if (nldap != 0) {
+ sudo_warnx("%s", U_("unable to mix ldap and ldaps URIs"));
+ goto done;
+ }
+ if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS)
+ sudo_warnx("%s", U_("starttls not supported when using ldaps"));
+ ldap_conf.ssl_mode = SUDO_LDAP_SSL;
+ }
+ free(buf);
+ }
+ buf = NULL;
+
+ /* Store parsed URI(s) in host for ldap_create() or ldap_init(). */
+ free(ldap_conf.host);
+ if ((ldap_conf.host = strdup(hostbuf)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+
+ ret = LDAP_SUCCESS;
+
+done:
+ free(buf);
+ debug_return_int(ret);
+
+overflow:
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ free(buf);
+ debug_return_int(-1);
+}
+#endif /* HAVE_LDAP_INITIALIZE */
+
+/*
+ * Decode a secret if it is base64 encoded, else return NULL.
+ */
+static char *
+sudo_ldap_decode_secret(const char *secret)
+{
+ unsigned char *result = NULL;
+ size_t len, reslen;
+ debug_decl(sudo_ldap_decode_secret, SUDOERS_DEBUG_LDAP);
+
+ if (strncasecmp(secret, "base64:", sizeof("base64:") - 1) == 0) {
+ /*
+ * Decode a base64 secret. The decoded length is 3/4 the encoded
+ * length but padding may be missing so round up to a multiple of 4.
+ */
+ secret += sizeof("base64:") - 1;
+ reslen = ((strlen(secret) + 3) / 4 * 3);
+ result = malloc(reslen + 1);
+ if (result == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ } else {
+ len = base64_decode(secret, result, reslen);
+ if (len == (size_t)-1) {
+ free(result);
+ result = NULL;
+ } else {
+ result[len] = '\0';
+ }
+ }
+ }
+ debug_return_str((char *)result);
+}
+
+static void
+sudo_ldap_read_secret(const char *path)
+{
+ FILE *fp;
+ char *line = NULL;
+ size_t linesize = 0;
+ ssize_t len;
+ debug_decl(sudo_ldap_read_secret, SUDOERS_DEBUG_LDAP);
+
+ if ((fp = fopen(path, "r")) != NULL) {
+ len = getdelim(&line, &linesize, '\n', fp);
+ if (len != -1) {
+ /* trim newline */
+ while (len > 0 && line[len - 1] == '\n')
+ line[--len] = '\0';
+ /* copy to bindpw and binddn */
+ free(ldap_conf.bindpw);
+ ldap_conf.bindpw = sudo_ldap_decode_secret(line);
+ if (ldap_conf.bindpw == NULL) {
+ /* not base64 encoded, use directly */
+ ldap_conf.bindpw = line;
+ line = NULL;
+ }
+ free(ldap_conf.binddn);
+ ldap_conf.binddn = ldap_conf.rootbinddn;
+ ldap_conf.rootbinddn = NULL;
+ }
+ fclose(fp);
+ free(line);
+ }
+ debug_return;
+}
+
+/*
+ * Look up keyword in config tables.
+ * Returns true if found, else false.
+ */
+static bool
+sudo_ldap_parse_keyword(const struct sudoers_context *ctx, const char *keyword,
+ const char *value, struct ldap_config_table *table)
+{
+ struct ldap_config_table *cur;
+ const char *errstr;
+ debug_decl(sudo_ldap_parse_keyword, SUDOERS_DEBUG_LDAP);
+
+ /* Look up keyword in config tables */
+ for (cur = table; cur->conf_str != NULL; cur++) {
+ if (strcasecmp(keyword, cur->conf_str) == 0) {
+ switch (cur->type) {
+ case CONF_DEREF_VAL:
+#ifdef LDAP_OPT_DEREF
+ if (strcasecmp(value, "searching") == 0)
+ *(int *)(cur->valp) = LDAP_DEREF_SEARCHING;
+ else if (strcasecmp(value, "finding") == 0)
+ *(int *)(cur->valp) = LDAP_DEREF_FINDING;
+ else if (strcasecmp(value, "always") == 0)
+ *(int *)(cur->valp) = LDAP_DEREF_ALWAYS;
+ else
+ *(int *)(cur->valp) = LDAP_DEREF_NEVER;
+#endif /* LDAP_OPT_DEREF */
+ break;
+ case CONF_REQCERT_VAL:
+#ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
+ if (strcasecmp(value, "never") == 0)
+ *(int *)(cur->valp) = LDAP_OPT_X_TLS_NEVER;
+ else if (strcasecmp(value, "allow") == 0)
+ *(int *)(cur->valp) = LDAP_OPT_X_TLS_ALLOW;
+ else if (strcasecmp(value, "try") == 0)
+ *(int *)(cur->valp) = LDAP_OPT_X_TLS_TRY;
+ else if (strcasecmp(value, "hard") == 0)
+ *(int *)(cur->valp) = LDAP_OPT_X_TLS_HARD;
+ else if (strcasecmp(value, "demand") == 0)
+ *(int *)(cur->valp) = LDAP_OPT_X_TLS_DEMAND;
+#endif /* LDAP_OPT_X_TLS_REQUIRE_CERT */
+ break;
+ case CONF_BOOL:
+ *(int *)(cur->valp) = sudo_strtobool(value) == true;
+ break;
+ case CONF_INT:
+ *(int *)(cur->valp) = (int)sudo_strtonum(value, INT_MIN, INT_MAX,
+ &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s: %s: %s"), ctx->settings.ldap_conf,
+ keyword, value, U_(errstr));
+ }
+ break;
+ case CONF_STR:
+ {
+ char *cp = NULL;
+
+ free(*(char **)(cur->valp));
+ if (*value && (cp = strdup(value)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ *(char **)(cur->valp) = cp;
+ break;
+ }
+ case CONF_LIST_STR:
+ {
+ struct ldap_config_str_list *head;
+ struct ldap_config_str *str;
+ size_t len = strlen(value);
+
+ if (len > 0) {
+ head = (struct ldap_config_str_list *)cur->valp;
+ if ((str = malloc(sizeof(*str) + len + 1)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ memcpy(str->val, value, len + 1);
+ STAILQ_INSERT_TAIL(head, str, entries);
+ }
+ }
+ break;
+ default:
+ sudo_warnx(
+ "internal error: unhandled CONF_ value %d for option %s",
+ cur->type, cur->conf_str);
+ sudo_warnx(
+ "update %s to add missing support for CONF_ value %d",
+ __func__, cur->type);
+ break;
+ }
+ debug_return_bool(true);
+ }
+ }
+ debug_return_bool(false);
+}
+
+#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
+const char *
+sudo_krb5_ccname_path(const char *old_ccname)
+{
+ const char *ccname = old_ccname;
+ debug_decl(sudo_krb5_ccname_path, SUDOERS_DEBUG_LDAP);
+
+ if (ccname == NULL)
+ debug_return_const_str(NULL);
+
+ /* Strip off leading FILE: or WRFILE: prefix. */
+ switch (ccname[0]) {
+ case 'F':
+ case 'f':
+ if (strncasecmp(ccname, "FILE:", 5) == 0)
+ ccname += 5;
+ break;
+ case 'W':
+ case 'w':
+ if (strncasecmp(ccname, "WRFILE:", 7) == 0)
+ ccname += 7;
+ break;
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "ccache %s -> %s", old_ccname, ccname);
+
+ /* Credential cache must be a fully-qualified path name. */
+ debug_return_const_str(*ccname == '/' ? ccname : NULL);
+}
+
+static bool
+sudo_check_krb5_ccname(const char *ccname)
+{
+ int fd;
+ const char *ccname_path;
+ debug_decl(sudo_check_krb5_ccname, SUDOERS_DEBUG_LDAP);
+
+ /* Strip off prefix to get path name. */
+ ccname_path = sudo_krb5_ccname_path(ccname);
+ if (ccname_path == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "unsupported krb5 credential cache path: %s", ccname);
+ debug_return_bool(false);
+ }
+ /* Make sure credential cache is fully-qualified and exists. */
+ fd = open(ccname_path, O_RDONLY|O_NONBLOCK, 0);
+ if (fd == -1) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "unable to open krb5 credential cache: %s", ccname_path);
+ debug_return_bool(false);
+ }
+ close(fd);
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "using krb5 credential cache: %s", ccname_path);
+ debug_return_bool(true);
+}
+#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
+
+bool
+sudo_ldap_read_config(const struct sudoers_context *ctx)
+{
+ char *cp, *keyword, *value, *line = NULL;
+ struct ldap_config_str *conf_str;
+ size_t linesize = 0;
+ FILE *fp;
+ debug_decl(sudo_ldap_read_config, SUDOERS_DEBUG_LDAP);
+
+ /* defaults */
+ ldap_conf.version = 3;
+ ldap_conf.port = -1;
+ ldap_conf.tls_checkpeer = -1;
+ ldap_conf.tls_reqcert = -1;
+ ldap_conf.timelimit = -1;
+ ldap_conf.timeout = -1;
+ ldap_conf.bind_timelimit = -1;
+ ldap_conf.use_sasl = -1;
+ ldap_conf.rootuse_sasl = -1;
+ ldap_conf.deref = -1;
+ ldap_conf.search_filter = strdup(DEFAULT_SEARCH_FILTER);
+ ldap_conf.netgroup_search_filter = strdup(DEFAULT_NETGROUP_SEARCH_FILTER);
+ ldap_conf.netgroup_query = true;
+ STAILQ_INIT(&ldap_conf.uri);
+ STAILQ_INIT(&ldap_conf.base);
+ STAILQ_INIT(&ldap_conf.netgroup_base);
+
+ if (ldap_conf.search_filter == NULL || ldap_conf.netgroup_search_filter == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+
+ if ((fp = fopen(ctx->settings.ldap_conf, "r")) == NULL)
+ debug_return_bool(false);
+
+ while (sudo_parseln(&line, &linesize, NULL, fp, PARSELN_COMM_BOL|PARSELN_CONT_IGN) != -1) {
+ if (*line == '\0')
+ continue; /* skip empty line */
+
+ /* split into keyword and value */
+ keyword = cp = line;
+ while (*cp && !isblank((unsigned char) *cp))
+ cp++;
+ if (*cp)
+ *cp++ = '\0'; /* terminate keyword */
+
+ /* skip whitespace before value */
+ while (isblank((unsigned char) *cp))
+ cp++;
+ value = cp;
+
+ /* Look up keyword in config tables */
+ if (!sudo_ldap_parse_keyword(ctx, keyword, value, ldap_conf_global))
+ sudo_ldap_parse_keyword(ctx, keyword, value, ldap_conf_conn);
+ }
+ free(line);
+ fclose(fp);
+
+ if (!ldap_conf.host) {
+ ldap_conf.host = strdup("localhost");
+ if (ldap_conf.host == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ }
+ if (STAILQ_EMPTY(&ldap_conf.netgroup_base)) {
+ /* netgroup_query is only valid in conjunction with netgroup_base */
+ ldap_conf.netgroup_query = false;
+ }
+
+ DPRINTF1("LDAP Config Summary");
+ DPRINTF1("===================");
+ if (!STAILQ_EMPTY(&ldap_conf.uri)) {
+ STAILQ_FOREACH(conf_str, &ldap_conf.uri, entries) {
+ DPRINTF1("uri %s", conf_str->val);
+ }
+ } else {
+ DPRINTF1("host %s",
+ ldap_conf.host ? ldap_conf.host : "(NONE)");
+ DPRINTF1("port %d", ldap_conf.port);
+ }
+ DPRINTF1("ldap_version %d", ldap_conf.version);
+
+ if (!STAILQ_EMPTY(&ldap_conf.base)) {
+ STAILQ_FOREACH(conf_str, &ldap_conf.base, entries) {
+ DPRINTF1("sudoers_base %s", conf_str->val);
+ }
+ } else {
+ DPRINTF1("sudoers_base %s", "(NONE: LDAP disabled)");
+ }
+ if (ldap_conf.search_filter) {
+ DPRINTF1("search_filter %s", ldap_conf.search_filter);
+ }
+ if (!STAILQ_EMPTY(&ldap_conf.netgroup_base)) {
+ STAILQ_FOREACH(conf_str, &ldap_conf.netgroup_base, entries) {
+ DPRINTF1("netgroup_base %s", conf_str->val);
+ }
+ DPRINTF1("netgroup_query %s",
+ ldap_conf.netgroup_query ? "(yes)" : "(no)");
+ } else {
+ DPRINTF1("netgroup_base %s", "(NONE: will use nsswitch)");
+ }
+ if (ldap_conf.netgroup_search_filter) {
+ DPRINTF1("netgroup_search_filter %s", ldap_conf.netgroup_search_filter);
+ }
+ DPRINTF1("binddn %s",
+ ldap_conf.binddn ? ldap_conf.binddn : "(anonymous)");
+ DPRINTF1("bindpw %s",
+ ldap_conf.bindpw ? ldap_conf.bindpw : "(anonymous)");
+ if (ldap_conf.bind_timelimit > 0) {
+ DPRINTF1("bind_timelimit %d", ldap_conf.bind_timelimit);
+ }
+ if (ldap_conf.timelimit > 0) {
+ DPRINTF1("timelimit %d", ldap_conf.timelimit);
+ }
+ if (ldap_conf.deref != -1) {
+ DPRINTF1("deref %d", ldap_conf.deref);
+ }
+ DPRINTF1("ssl %s", ldap_conf.ssl ? ldap_conf.ssl : "(no)");
+ if (ldap_conf.tls_checkpeer != -1) {
+ DPRINTF1("tls_checkpeer %s",
+ ldap_conf.tls_checkpeer ? "(yes)" : "(no)");
+ }
+#ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
+ if (ldap_conf.tls_reqcert != -1) {
+ DPRINTF1("tls_reqcert %s",
+ ldap_conf.tls_reqcert == LDAP_OPT_X_TLS_NEVER ? "hard" :
+ ldap_conf.tls_reqcert == LDAP_OPT_X_TLS_ALLOW ? "allow" :
+ ldap_conf.tls_reqcert == LDAP_OPT_X_TLS_TRY ? "try" :
+ ldap_conf.tls_reqcert == LDAP_OPT_X_TLS_HARD ? "hard" :
+ ldap_conf.tls_reqcert == LDAP_OPT_X_TLS_DEMAND ? "demand" :
+ "unknown");
+ }
+#endif /* LDAP_OPT_X_TLS_REQUIRE_CERT */
+ if (ldap_conf.tls_cacertfile != NULL) {
+ DPRINTF1("tls_cacertfile %s", ldap_conf.tls_cacertfile);
+ }
+ if (ldap_conf.tls_cacertdir != NULL) {
+ DPRINTF1("tls_cacertdir %s", ldap_conf.tls_cacertdir);
+ }
+ if (ldap_conf.tls_random_file != NULL) {
+ DPRINTF1("tls_random_file %s", ldap_conf.tls_random_file);
+ }
+ if (ldap_conf.tls_cipher_suite != NULL) {
+ DPRINTF1("tls_cipher_suite %s", ldap_conf.tls_cipher_suite);
+ }
+ if (ldap_conf.tls_certfile != NULL) {
+ DPRINTF1("tls_certfile %s", ldap_conf.tls_certfile);
+ }
+ if (ldap_conf.tls_keyfile != NULL) {
+ DPRINTF1("tls_keyfile %s", ldap_conf.tls_keyfile);
+ }
+#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
+ if (ldap_conf.use_sasl != -1) {
+ if (ldap_conf.sasl_mech == NULL) {
+ /* Default mechanism is GSSAPI. */
+ ldap_conf.sasl_mech = strdup("GSSAPI");
+ if (ldap_conf.sasl_mech == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ }
+ DPRINTF1("use_sasl %s", ldap_conf.use_sasl ? "yes" : "no");
+ DPRINTF1("sasl_mech %s", ldap_conf.sasl_mech);
+ DPRINTF1("sasl_auth_id %s",
+ ldap_conf.sasl_auth_id ? ldap_conf.sasl_auth_id : "(NONE)");
+ DPRINTF1("rootuse_sasl %d",
+ ldap_conf.rootuse_sasl);
+ DPRINTF1("rootsasl_auth_id %s",
+ ldap_conf.rootsasl_auth_id ? ldap_conf.rootsasl_auth_id : "(NONE)");
+ DPRINTF1("sasl_secprops %s",
+ ldap_conf.sasl_secprops ? ldap_conf.sasl_secprops : "(NONE)");
+ DPRINTF1("krb5_ccname %s",
+ ldap_conf.krb5_ccname ? ldap_conf.krb5_ccname : "(NONE)");
+ }
+#endif
+ DPRINTF1("===================");
+
+ if (STAILQ_EMPTY(&ldap_conf.base))
+ debug_return_bool(false); /* if no base is defined, ignore LDAP */
+
+ if (ldap_conf.bind_timelimit > 0)
+ ldap_conf.bind_timelimit *= 1000; /* convert to ms */
+
+ /*
+ * Interpret SSL option
+ */
+ if (ldap_conf.ssl != NULL) {
+ if (strcasecmp(ldap_conf.ssl, "start_tls") == 0)
+ ldap_conf.ssl_mode = SUDO_LDAP_STARTTLS;
+ else if (sudo_strtobool(ldap_conf.ssl) == true)
+ ldap_conf.ssl_mode = SUDO_LDAP_SSL;
+ }
+
+#if defined(HAVE_LDAPSSL_SET_STRENGTH) && !defined(LDAP_OPT_X_TLS_REQUIRE_CERT)
+ if (ldap_conf.tls_checkpeer != -1) {
+ ldapssl_set_strength(NULL,
+ ldap_conf.tls_checkpeer ? LDAPSSL_AUTH_CERT : LDAPSSL_AUTH_WEAK);
+ }
+#endif
+
+#ifndef HAVE_LDAP_INITIALIZE
+ /* Convert uri list to host list if no ldap_initialize(). */
+ if (!STAILQ_EMPTY(&ldap_conf.uri)) {
+ struct ldap_config_str *uri;
+
+ if (sudo_ldap_parse_uri(&ldap_conf.uri) != LDAP_SUCCESS)
+ debug_return_bool(false);
+ while ((uri = STAILQ_FIRST(&ldap_conf.uri)) != NULL) {
+ STAILQ_REMOVE_HEAD(&ldap_conf.uri, entries);
+ free(uri);
+ }
+ ldap_conf.port = LDAP_PORT;
+ }
+#endif
+
+ if (STAILQ_EMPTY(&ldap_conf.uri)) {
+ /* Use port 389 for plaintext LDAP and port 636 for SSL LDAP */
+ if (ldap_conf.port < 0)
+ ldap_conf.port =
+ ldap_conf.ssl_mode == SUDO_LDAP_SSL ? LDAPS_PORT : LDAP_PORT;
+
+#ifdef HAVE_LDAP_CREATE
+ /*
+ * Cannot specify port directly to ldap_create(), each host must
+ * include :port to override the default.
+ */
+ if (ldap_conf.port != LDAP_PORT) {
+ if (!sudo_ldap_conf_add_ports())
+ debug_return_bool(false);
+ }
+#endif
+ }
+
+ /* If search filter is not parenthesized, make it so. */
+ if (ldap_conf.search_filter && ldap_conf.search_filter[0] != '(') {
+ size_t len = strlen(ldap_conf.search_filter);
+ cp = ldap_conf.search_filter;
+ ldap_conf.search_filter = malloc(len + 3);
+ if (ldap_conf.search_filter == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ ldap_conf.search_filter[0] = '(';
+ memcpy(ldap_conf.search_filter + 1, cp, len);
+ ldap_conf.search_filter[len + 1] = ')';
+ ldap_conf.search_filter[len + 2] = '\0';
+ free(cp);
+ }
+
+
+ /* If rootbinddn set, read in /etc/ldap.secret if it exists. */
+ if (ldap_conf.rootbinddn) {
+ sudo_ldap_read_secret(ctx->settings.ldap_secret);
+ } else if (ldap_conf.bindpw) {
+ cp = sudo_ldap_decode_secret(ldap_conf.bindpw);
+ if (cp != NULL) {
+ free(ldap_conf.bindpw);
+ ldap_conf.bindpw = cp;
+ }
+ }
+
+ if (ldap_conf.tls_keypw) {
+ cp = sudo_ldap_decode_secret(ldap_conf.tls_keypw);
+ if (cp != NULL) {
+ free(ldap_conf.tls_keypw);
+ ldap_conf.tls_keypw = cp;
+ }
+ }
+
+#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
+ /*
+ * Make sure we can open the file specified by krb5_ccname.
+ */
+ if (ldap_conf.krb5_ccname != NULL) {
+ if (!sudo_check_krb5_ccname(ldap_conf.krb5_ccname))
+ ldap_conf.krb5_ccname = NULL;
+ }
+#endif
+
+ debug_return_bool(true);
+}
+
+/*
+ * Set LDAP options from the specified options table
+ * Returns LDAP_SUCCESS on success, else non-zero.
+ */
+static int
+sudo_ldap_set_options_table(LDAP *ld, struct ldap_config_table *table)
+{
+ struct ldap_config_table *cur;
+ int ival, rc, errors = 0;
+ char *sval;
+ debug_decl(sudo_ldap_set_options_table, SUDOERS_DEBUG_LDAP);
+
+ for (cur = table; cur->conf_str != NULL; cur++) {
+ if (cur->opt_val == -1)
+ continue;
+
+ switch (cur->type) {
+ case CONF_DEREF_VAL:
+ case CONF_REQCERT_VAL:
+ case CONF_BOOL:
+ case CONF_INT:
+ ival = *(int *)(cur->valp);
+ if (ival >= 0) {
+ DPRINTF1("ldap_set_option: %s -> %d", cur->conf_str, ival);
+ rc = ldap_set_option(ld, cur->opt_val, &ival);
+ if (rc != LDAP_OPT_SUCCESS) {
+ sudo_warnx("ldap_set_option: %s -> %d: %s",
+ cur->conf_str, ival, ldap_err2string(rc));
+ errors++;
+ }
+ }
+ break;
+ case CONF_STR:
+ sval = *(char **)(cur->valp);
+ if (sval != NULL) {
+ DPRINTF1("ldap_set_option: %s -> %s", cur->conf_str, sval);
+ rc = ldap_set_option(ld, cur->opt_val, sval);
+ if (rc != LDAP_OPT_SUCCESS) {
+ sudo_warnx("ldap_set_option: %s -> %s: %s",
+ cur->conf_str, sval, ldap_err2string(rc));
+ errors++;
+ }
+ }
+ break;
+ case CONF_LIST_STR:
+ /* Lists are iterated over and don't set LDAP options directly. */
+ break;
+ default:
+ sudo_warnx("internal error: unhandled CONF_ value %d for option %s",
+ cur->type, cur->conf_str);
+ sudo_warnx("update %s to add missing support for CONF_ value %d",
+ __func__, cur->type);
+ }
+ }
+ debug_return_int(errors ? -1 : LDAP_SUCCESS);
+}
+
+/*
+ * Set LDAP options based on the global config table.
+ * Returns LDAP_SUCCESS on success, else non-zero.
+ */
+int
+sudo_ldap_set_options_global(void)
+{
+ int ret;
+ debug_decl(sudo_ldap_set_options_global, SUDOERS_DEBUG_LDAP);
+
+ /* Set ber options */
+#ifdef LBER_OPT_DEBUG_LEVEL
+ if (ldap_conf.ldap_debug)
+ ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &ldap_conf.ldap_debug);
+#endif
+
+ /* Parse global LDAP options table. */
+ ret = sudo_ldap_set_options_table(NULL, ldap_conf_global);
+ debug_return_int(ret);
+}
+
+/*
+ * Set LDAP options based on the per-connection config table.
+ * Returns LDAP_SUCCESS on success, else non-zero.
+ */
+int
+sudo_ldap_set_options_conn(LDAP *ld)
+{
+ int rc;
+ debug_decl(sudo_ldap_set_options_conn, SUDOERS_DEBUG_LDAP);
+
+ /* Parse per-connection LDAP options table. */
+ rc = sudo_ldap_set_options_table(ld, ldap_conf_conn);
+ if (rc == -1)
+ debug_return_int(-1);
+
+#ifdef LDAP_OPT_TIMEOUT
+ /* Convert timeout to a timeval */
+ if (ldap_conf.timeout > 0) {
+ struct timeval tv;
+ tv.tv_sec = ldap_conf.timeout;
+ tv.tv_usec = 0;
+ DPRINTF1("ldap_set_option(LDAP_OPT_TIMEOUT, %d)", ldap_conf.timeout);
+ rc = ldap_set_option(ld, LDAP_OPT_TIMEOUT, &tv);
+ if (rc != LDAP_OPT_SUCCESS) {
+ sudo_warnx("ldap_set_option(TIMEOUT, %d): %s",
+ ldap_conf.timeout, ldap_err2string(rc));
+ }
+ }
+#endif
+#ifdef LDAP_OPT_NETWORK_TIMEOUT
+ /* Convert bind_timelimit to a timeval */
+ if (ldap_conf.bind_timelimit > 0) {
+ struct timeval tv;
+ tv.tv_sec = ldap_conf.bind_timelimit / 1000;
+ tv.tv_usec = 0;
+ DPRINTF1("ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT, %d)",
+ ldap_conf.bind_timelimit / 1000);
+ rc = ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
+# if !defined(LDAP_OPT_CONNECT_TIMEOUT) || LDAP_VENDOR_VERSION != 510
+ /* Tivoli Directory Server 6.3 libs always return a (bogus) error. */
+ if (rc != LDAP_OPT_SUCCESS) {
+ sudo_warnx("ldap_set_option(NETWORK_TIMEOUT, %d): %s",
+ ldap_conf.bind_timelimit / 1000, ldap_err2string(rc));
+ }
+# endif
+ }
+#endif
+
+#if defined(LDAP_OPT_X_TLS) && !defined(HAVE_LDAPSSL_INIT)
+ if (ldap_conf.ssl_mode == SUDO_LDAP_SSL) {
+ int val = LDAP_OPT_X_TLS_HARD;
+ DPRINTF1("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD)");
+ rc = ldap_set_option(ld, LDAP_OPT_X_TLS, &val);
+ if (rc != LDAP_SUCCESS) {
+ sudo_warnx("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD): %s",
+ ldap_err2string(rc));
+ debug_return_int(-1);
+ }
+ }
+#endif
+ debug_return_int(LDAP_SUCCESS);
+}
diff --git a/plugins/sudoers/ldap_innetgr.c b/plugins/sudoers/ldap_innetgr.c
new file mode 100644
index 0000000..2309485
--- /dev/null
+++ b/plugins/sudoers/ldap_innetgr.c
@@ -0,0 +1,264 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <time.h>
+#include <ctype.h>
+#ifdef HAVE_LBER_H
+# include <lber.h>
+#endif
+#include <ldap.h>
+
+#include <sudoers.h>
+#include <sudo_ldap.h>
+#include <sudo_ldap_conf.h>
+
+/*
+ * Compare str to netgroup string ngstr of length nglen where str is a
+ * NUL-terminated string and ngstr is part of a netgroup triple string.
+ * Uses innetgr(3)-style matching rules.
+ * Returns true if the strings match, else false.
+ */
+static bool
+sudo_ldap_netgroup_match_str(const char *str, const char *ngstr, size_t nglen,
+ bool ignore_case)
+{
+ debug_decl(sudo_ldap_netgroup_match_str, SUDOERS_DEBUG_LDAP);
+
+ /* Skip leading whitespace. */
+ while (isspace((unsigned char)*ngstr) && nglen > 0) {
+ ngstr++;
+ nglen--;
+ }
+ /* Skip trailing whitespace. */
+ while (nglen > 0 && isspace((unsigned char)ngstr[nglen - 1])) {
+ nglen--;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: compare \"%s\" to \"%.*s\"",
+ __func__, str ? str : "", (int)nglen, ngstr);
+
+ if (nglen == 0 || str == NULL) {
+ /* An empty string is a wildcard. */
+ debug_return_bool(true);
+ }
+ if (*ngstr == '-' && nglen == 1) {
+ /* '-' means no valid value. */
+ debug_return_bool(false);
+ }
+ if (ignore_case) {
+ if (strncasecmp(str, ngstr, nglen) == 0 && str[nglen] == '\0')
+ debug_return_bool(true);
+ } else {
+ if (strncmp(str, ngstr, nglen) == 0 && str[nglen] == '\0')
+ debug_return_bool(true);
+ }
+ debug_return_bool(false);
+}
+
+/*
+ * Match the specified netgroup triple using the given host,
+ * user and domain. Matching rules as per innetgr(3).
+ * Returns 1 on match, else 0.
+ */
+static int
+sudo_ldap_match_netgroup(const char *triple, const char *host,
+ const char *user, const char *domain)
+{
+ const char *cp, *ep;
+ debug_decl(sudo_ldap_match_netgroup, SUDOERS_DEBUG_LDAP);
+
+ /* Trim leading space, check for opening paren. */
+ while (isspace((unsigned char)*triple))
+ triple++;
+ if (*triple != '(') {
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "%s: invalid triple: %s",
+ __func__, triple);
+ debug_return_int(0);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: matching (%s,%s,%s) against %s",
+ __func__, host ? host : "", user ? user : "", domain ? domain : "",
+ triple);
+
+ /* Parse host. */
+ cp = triple + 1;
+ ep = strchr(cp, ',');
+ if (ep == NULL || !sudo_ldap_netgroup_match_str(host, cp, (size_t)(ep - cp), true))
+ debug_return_int(0);
+
+ /* Parse user. */
+ cp = ep + 1;
+ ep = strchr(cp, ',');
+ if (ep == NULL || !sudo_ldap_netgroup_match_str(user, cp, (size_t)(ep - cp), def_case_insensitive_user))
+ debug_return_int(0);
+
+ /* Parse domain. */
+ cp = ep + 1;
+ ep = strchr(cp, ')');
+ if (ep == NULL || !sudo_ldap_netgroup_match_str(domain, cp, (size_t)(ep - cp), true))
+ debug_return_int(0);
+
+ debug_return_int(1);
+}
+
+#define MAX_NETGROUP_DEPTH 128
+struct netgroups_seen {
+ const char *groups[MAX_NETGROUP_DEPTH];
+ size_t len;
+};
+
+static int
+sudo_ldap_innetgr_base(LDAP *ld, const char *base,
+ struct timeval *timeout, const char *netgr, const char *host,
+ const char *user, const char *domain, struct netgroups_seen *seen)
+{
+ char *escaped_netgr = NULL, *filt = NULL;
+ LDAPMessage *entry, *result = NULL;
+ int rc, ret = 0;
+ size_t n;
+ debug_decl(sudo_ldap_innetgr_base, SUDOERS_DEBUG_LDAP);
+
+ /* Cycle detection. */
+ for (n = 0; n < seen->len; n++) {
+ if (strcmp(netgr, seen->groups[n]) == 0) {
+ DPRINTF1("%s: cycle in netgroups", netgr);
+ goto done;
+ }
+ }
+ if (seen->len + 1 > MAX_NETGROUP_DEPTH) {
+ DPRINTF1("%s: too many nested netgroups", netgr);
+ goto done;
+ }
+ seen->groups[seen->len++] = netgr;
+
+ /* Escape the netgroup name per RFC 4515. */
+ if ((escaped_netgr = sudo_ldap_value_dup(netgr)) == NULL)
+ goto done;
+
+ /* Build nisNetgroup query. */
+ rc = asprintf(&filt, "(&%s(cn=%s))",
+ ldap_conf.netgroup_search_filter, escaped_netgr);
+ if (rc == -1)
+ goto done;
+ DPRINTF1("ldap netgroup search filter: '%s'", filt);
+
+ /* Perform an LDAP query for nisNetgroup. */
+ DPRINTF1("searching from netgroup_base '%s'", base);
+ rc = ldap_search_ext_s(ld, base, LDAP_SCOPE_SUBTREE, filt,
+ NULL, 0, NULL, NULL, timeout, 0, &result);
+ free(filt);
+ if (rc != LDAP_SUCCESS) {
+ DPRINTF1("ldap netgroup search failed: %s", ldap_err2string(rc));
+ goto done;
+ }
+
+ LDAP_FOREACH(entry, ld, result) {
+ struct berval **bv, **p;
+
+ /* Check all nisNetgroupTriple entries. */
+ bv = ldap_get_values_len(ld, entry, "nisNetgroupTriple");
+ if (bv == NULL) {
+ const int optrc = ldap_get_option(ld, LDAP_OPT_RESULT_CODE, &rc);
+ if (optrc != LDAP_OPT_SUCCESS || rc == LDAP_NO_MEMORY)
+ goto done;
+ } else {
+ for (p = bv; *p != NULL && !ret; p++) {
+ char *val = (*p)->bv_val;
+ if (sudo_ldap_match_netgroup(val, host, user, domain)) {
+ ret = 1;
+ break;
+ }
+ }
+ ldap_value_free_len(bv);
+ if (ret == 1)
+ break;
+ }
+
+ /* Handle nested netgroups. */
+ bv = ldap_get_values_len(ld, entry, "memberNisNetgroup");
+ if (bv == NULL) {
+ const int optrc = ldap_get_option(ld, LDAP_OPT_RESULT_CODE, &rc);
+ if (optrc != LDAP_OPT_SUCCESS || rc == LDAP_NO_MEMORY)
+ goto done;
+ } else {
+ for (p = bv; *p != NULL && !ret; p++) {
+ const char *val = (*p)->bv_val;
+ const size_t saved_len = seen->len;
+ ret = sudo_ldap_innetgr_base(ld, base, timeout, val, host,
+ user, domain, seen);
+ /* Restore seen state to avoid use-after-free. */
+ seen->len = saved_len;
+ }
+ ldap_value_free_len(bv);
+ }
+ }
+
+done:
+ ldap_msgfree(result);
+ free(escaped_netgr);
+
+ debug_return_int(ret);
+}
+
+int
+sudo_ldap_innetgr_int(void *v, const char *netgr, const char *host,
+ const char *user, const char *domain)
+{
+ LDAP *ld = v;
+ struct timeval tv, *tvp = NULL;
+ struct ldap_config_str *base;
+ struct netgroups_seen seen;
+ int ret = 0;
+ debug_decl(sudo_ldap_innetgr, SUDOERS_DEBUG_LDAP);
+
+ if (STAILQ_EMPTY(&ldap_conf.netgroup_base)) {
+ /* LDAP netgroups not configured. */
+ debug_return_int(-1);
+ }
+
+ if (ldap_conf.timeout > 0) {
+ tv.tv_sec = ldap_conf.timeout;
+ tv.tv_usec = 0;
+ tvp = &tv;
+ }
+
+ /* Perform an LDAP query for nisNetgroup. */
+ STAILQ_FOREACH(base, &ldap_conf.netgroup_base, entries) {
+ seen.len = 0;
+ ret = sudo_ldap_innetgr_base(ld, base->val, tvp, netgr, host,
+ user, domain, &seen);
+ if (ret != 0)
+ break;
+ }
+
+ debug_return_int(ret);
+}
diff --git a/plugins/sudoers/ldap_util.c b/plugins/sudoers/ldap_util.c
new file mode 100644
index 0000000..3cfd3b0
--- /dev/null
+++ b/plugins/sudoers/ldap_util.c
@@ -0,0 +1,750 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013, 2016, 2018-2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * This code is derived from software contributed by Aaron Spangler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <sudoers.h>
+#include <interfaces.h>
+#include <sudo_lbuf.h>
+#include <sudo_ldap.h>
+#include <sudo_digest.h>
+#include <gram.h>
+
+/*
+ * Returns true if the string pointed to by valp begins with an
+ * odd number of '!' characters. Intervening blanks are ignored.
+ * Stores the address of the string after '!' removal in valp.
+ */
+bool
+sudo_ldap_is_negated(char **valp)
+{
+ char *val = *valp;
+ bool ret = false;
+ debug_decl(sudo_ldap_is_negated, SUDOERS_DEBUG_LDAP);
+
+ while (*val == '!') {
+ ret = !ret;
+ do {
+ val++;
+ } while (isblank((unsigned char)*val));
+ }
+ *valp = val;
+ debug_return_bool(ret);
+}
+
+/*
+ * Parse an option string into a defaults structure.
+ * The members of def are pointers into optstr (which is modified).
+ */
+int
+sudo_ldap_parse_option(char *optstr, char **varp, char **valp)
+{
+ char *cp, *val = NULL;
+ char *var = optstr;
+ int op;
+ debug_decl(sudo_ldap_parse_option, SUDOERS_DEBUG_LDAP);
+
+ /* check for equals sign past first char */
+ cp = strchr(var, '=');
+ if (cp != NULL && cp > var) {
+ val = cp + 1;
+ op = cp[-1]; /* peek for += or -= cases */
+ if (op == '+' || op == '-') {
+ /* case var+=val or var-=val */
+ cp--;
+ } else {
+ /* case var=val */
+ op = true;
+ }
+ /* Trim whitespace between var and operator. */
+ while (cp > var && isblank((unsigned char)cp[-1]))
+ cp--;
+ /* Truncate variable name. */
+ *cp = '\0';
+ /* Trim leading whitespace from val. */
+ while (isblank((unsigned char)*val))
+ val++;
+ /* Strip double quotes if present. */
+ if (*val == '"') {
+ char *ep = val + strlen(val);
+ if (ep != val && ep[-1] == '"') {
+ val++;
+ ep[-1] = '\0';
+ }
+ }
+ } else {
+ /* Boolean value, either true or false. */
+ op = sudo_ldap_is_negated(&var) ? false : true;
+ }
+ *varp = var;
+ *valp = val;
+
+ debug_return_int(op);
+}
+
+/*
+ * Convert an array of user/group names to a member list.
+ * The caller is responsible for freeing the returned struct member_list.
+ */
+static struct member_list *
+array_to_member_list(void *a, sudo_ldap_iter_t iter)
+{
+ struct member_list negated_members =
+ TAILQ_HEAD_INITIALIZER(negated_members);
+ struct member_list *members;
+ struct member *m;
+ char *val;
+ debug_decl(bv_to_member_list, SUDOERS_DEBUG_LDAP);
+
+ if ((members = calloc(1, sizeof(*members))) == NULL)
+ return NULL;
+ TAILQ_INIT(members);
+
+ while ((val = iter(&a)) != NULL) {
+ if ((m = calloc(1, sizeof(*m))) == NULL)
+ goto bad;
+ m->negated = sudo_ldap_is_negated(&val);
+
+ switch (val[0]) {
+ case '\0':
+ /* Empty RunAsUser means run as the invoking user. */
+ m->type = MYSELF;
+ break;
+ case '+':
+ m->type = NETGROUP;
+ break;
+ case '%':
+ m->type = USERGROUP;
+ break;
+ case 'A':
+ if (strcmp(val, "ALL") == 0) {
+ m->type = ALL;
+ break;
+ }
+ FALLTHROUGH;
+ default:
+ m->type = WORD;
+ break;
+ }
+ if (m->type != ALL && m->type != MYSELF) {
+ if ((m->name = strdup(val)) == NULL) {
+ free(m);
+ goto bad;
+ }
+ }
+ if (m->negated)
+ TAILQ_INSERT_TAIL(&negated_members, m, entries);
+ else
+ TAILQ_INSERT_TAIL(members, m, entries);
+ }
+
+ /* Negated members take precedence so we insert them at the end. */
+ TAILQ_CONCAT(members, &negated_members, entries);
+ debug_return_ptr(members);
+bad:
+ free_members(&negated_members);
+ free_members(members);
+ free(members);
+ debug_return_ptr(NULL);
+}
+
+static bool
+is_address(char *host)
+{
+ union sudo_in_addr_un addr;
+ bool ret = false;
+ char *slash;
+ debug_decl(is_address, SUDOERS_DEBUG_LDAP);
+
+ /* Check for mask, not currently parsed. */
+ if ((slash = strchr(host, '/')) != NULL)
+ *slash = '\0';
+
+ if (inet_pton(AF_INET, host, &addr.ip4) == 1)
+ ret = true;
+#ifdef HAVE_STRUCT_IN6_ADDR
+ else if (inet_pton(AF_INET6, host, &addr.ip6) == 1)
+ ret = true;
+#endif
+
+ if (slash != NULL)
+ *slash = '/';
+
+ debug_return_bool(ret);
+}
+
+static struct member *
+host_to_member(char *host)
+{
+ struct member *m;
+ debug_decl(host_to_member, SUDOERS_DEBUG_LDAP);
+
+ if ((m = calloc(1, sizeof(*m))) == NULL)
+ goto oom;
+ m->negated = sudo_ldap_is_negated(&host);
+ switch (*host) {
+ case '+':
+ m->type = NETGROUP;
+ break;
+ case 'A':
+ if (strcmp(host, "ALL") == 0) {
+ m->type = ALL;
+ break;
+ }
+ FALLTHROUGH;
+ default:
+ if (is_address(host)) {
+ m->type = NTWKADDR;
+ } else {
+ m->type = WORD;
+ }
+ break;
+ }
+ if (m->type != ALL) {
+ if ((m->name = strdup(host)) == NULL)
+ goto oom;
+ }
+
+ debug_return_ptr(m);
+oom:
+ free(m);
+ debug_return_ptr(NULL);
+}
+
+/*
+ * If a digest prefix is present, add it to struct command_digest_list
+ * and update cmnd to point to the command after the digest.
+ * Returns 1 if a digest was parsed, 0 if not and -1 on error.
+ */
+static int
+sudo_ldap_extract_digest(const char *cmnd, char **endptr,
+ struct command_digest_list *digests)
+{
+ const char *ep, *cp = cmnd;
+ struct command_digest *digest;
+ unsigned int digest_type = SUDO_DIGEST_INVALID;
+ debug_decl(sudo_ldap_extract_digest, SUDOERS_DEBUG_LDAP);
+
+ /*
+ * Check for and extract a digest prefix, e.g.
+ * sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1 /bin/ls
+ */
+ if (cp[0] == 's' && cp[1] == 'h' && cp[2] == 'a') {
+ switch (cp[3]) {
+ case '2':
+ if (cp[4] == '2' && cp[5] == '4')
+ digest_type = SUDO_DIGEST_SHA224;
+ else if (cp[4] == '5' && cp[5] == '6')
+ digest_type = SUDO_DIGEST_SHA256;
+ break;
+ case '3':
+ if (cp[4] == '8' && cp[5] == '4')
+ digest_type = SUDO_DIGEST_SHA384;
+ break;
+ case '5':
+ if (cp[4] == '1' && cp[5] == '2')
+ digest_type = SUDO_DIGEST_SHA512;
+ break;
+ }
+ if (digest_type != SUDO_DIGEST_INVALID) {
+ cp += 6;
+ while (isblank((unsigned char)*cp))
+ cp++;
+ if (*cp == ':') {
+ cp++;
+ while (isblank((unsigned char)*cp))
+ cp++;
+ ep = cp;
+ while (*ep != '\0' && !isblank((unsigned char)*ep) && *ep != ',')
+ ep++;
+ if (isblank((unsigned char)*ep) || *ep == ',') {
+ if ((digest = malloc(sizeof(*digest))) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ debug_return_int(-1);
+ }
+ digest->digest_type = digest_type;
+ digest->digest_str = strndup(cp, (size_t)(ep - cp));
+ if (digest->digest_str == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ free(digest);
+ debug_return_int(-1);
+ }
+ while (isblank((unsigned char)*ep))
+ ep++;
+ *endptr = (char *)ep;
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s digest %s for %s",
+ digest_type_to_name(digest_type),
+ digest->digest_str, cp);
+ TAILQ_INSERT_TAIL(digests, digest, entries);
+ debug_return_int(1);
+ }
+ }
+ }
+ }
+ debug_return_int(0);
+}
+
+/*
+ * If a digest list is present, fill in struct command_digest_list
+ * and update cmnd to point to the command after the digest.
+ * Returns false on error, else true.
+ */
+static bool
+sudo_ldap_extract_digests(char **cmnd, struct command_digest_list *digests)
+{
+ char *cp = *cmnd;
+ int rc;
+ debug_decl(sudo_ldap_extract_digests, SUDOERS_DEBUG_LDAP);
+
+ for (;;) {
+ rc = sudo_ldap_extract_digest(cp, &cp, digests);
+ if (rc != 1)
+ break;
+
+ /* Check for additional digestspecs, separated by a comma. */
+ if (*cp != ',')
+ break;
+ do {
+ cp++;
+ } while (isblank((unsigned char)*cp));
+ }
+ *cmnd = cp;
+
+ debug_return_bool(rc != -1);
+}
+
+/*
+ * Convert an LDAP sudoRole to a sudoers privilege.
+ * Pass in struct berval ** for LDAP or char *** for SSSD.
+ */
+struct privilege *
+sudo_ldap_role_to_priv(const char *cn, void *hosts, void *runasusers,
+ void *runasgroups, void *cmnds, void *opts, const char *notbefore,
+ const char *notafter, bool warnings, bool store_options,
+ sudo_ldap_iter_t iter)
+{
+ struct cmndspec_list negated_cmnds = TAILQ_HEAD_INITIALIZER(negated_cmnds);
+ struct member_list negated_hosts = TAILQ_HEAD_INITIALIZER(negated_hosts);
+ struct cmndspec *prev_cmndspec = NULL;
+ struct privilege *priv;
+ struct member *m;
+ char *cmnd;
+ debug_decl(sudo_ldap_role_to_priv, SUDOERS_DEBUG_LDAP);
+
+ if ((priv = calloc(1, sizeof(*priv))) == NULL)
+ goto oom;
+ TAILQ_INIT(&priv->hostlist);
+ TAILQ_INIT(&priv->cmndlist);
+ TAILQ_INIT(&priv->defaults);
+
+ priv->ldap_role = strdup(cn ? cn : "UNKNOWN");
+ if (priv->ldap_role == NULL)
+ goto oom;
+
+ if (hosts == NULL) {
+ /* The host has already matched, use ALL as wildcard. */
+ if ((m = sudo_ldap_new_member_all()) == NULL)
+ goto oom;
+ TAILQ_INSERT_TAIL(&priv->hostlist, m, entries);
+ } else {
+ char *host;
+ while ((host = iter(&hosts)) != NULL) {
+ if ((m = host_to_member(host)) == NULL)
+ goto oom;
+ if (m->negated)
+ TAILQ_INSERT_TAIL(&negated_hosts, m, entries);
+ else
+ TAILQ_INSERT_TAIL(&priv->hostlist, m, entries);
+ }
+ /* Negated hosts take precedence so we insert them at the end. */
+ TAILQ_CONCAT(&priv->hostlist, &negated_hosts, entries);
+ }
+
+ /*
+ * Parse sudoCommands and add to cmndlist.
+ */
+ while ((cmnd = iter(&cmnds)) != NULL) {
+ bool negated = sudo_ldap_is_negated(&cmnd);
+ struct sudo_command *c = NULL;
+ struct cmndspec *cmndspec;
+
+ /* Allocate storage upfront. */
+ if ((cmndspec = calloc(1, sizeof(*cmndspec))) == NULL)
+ goto oom;
+ if ((m = calloc(1, sizeof(*m))) == NULL) {
+ free(cmndspec);
+ goto oom;
+ }
+ if ((c = calloc(1, sizeof(*c))) == NULL) {
+ free(cmndspec);
+ free(m);
+ goto oom;
+ }
+ m->name = (char *)c;
+ TAILQ_INIT(&c->digests);
+
+ /* Negated commands have precedence so insert them at the end. */
+ if (negated)
+ TAILQ_INSERT_TAIL(&negated_cmnds, cmndspec, entries);
+ else
+ TAILQ_INSERT_TAIL(&priv->cmndlist, cmndspec, entries);
+
+ /* Initialize cmndspec */
+ TAGS_INIT(&cmndspec->tags);
+ cmndspec->notbefore = UNSPEC;
+ cmndspec->notafter = UNSPEC;
+ cmndspec->timeout = UNSPEC;
+ cmndspec->cmnd = m;
+
+ if (prev_cmndspec != NULL) {
+ /* Inherit values from prior cmndspec (common to the sudoRole). */
+ cmndspec->runasuserlist = prev_cmndspec->runasuserlist;
+ cmndspec->runasgrouplist = prev_cmndspec->runasgrouplist;
+ cmndspec->notbefore = prev_cmndspec->notbefore;
+ cmndspec->notafter = prev_cmndspec->notafter;
+ cmndspec->timeout = prev_cmndspec->timeout;
+ cmndspec->runchroot = prev_cmndspec->runchroot;
+ cmndspec->runcwd = prev_cmndspec->runcwd;
+#ifdef HAVE_SELINUX
+ cmndspec->role = prev_cmndspec->role;
+ cmndspec->type = prev_cmndspec->type;
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_PRIV_SET
+ cmndspec->privs = prev_cmndspec->privs;
+ cmndspec->limitprivs = prev_cmndspec->limitprivs;
+#endif /* HAVE_PRIV_SET */
+ cmndspec->tags = prev_cmndspec->tags;
+ if (cmndspec->tags.setenv == IMPLIED)
+ cmndspec->tags.setenv = UNSPEC;
+ } else {
+ /* Parse sudoRunAsUser / sudoRunAs */
+ if (runasusers != NULL) {
+ cmndspec->runasuserlist =
+ array_to_member_list(runasusers, iter);
+ if (cmndspec->runasuserlist == NULL)
+ goto oom;
+ }
+
+ /* Parse sudoRunAsGroup */
+ if (runasgroups != NULL) {
+ cmndspec->runasgrouplist =
+ array_to_member_list(runasgroups, iter);
+ if (cmndspec->runasgrouplist == NULL)
+ goto oom;
+ }
+
+ /* Parse sudoNotBefore / sudoNotAfter */
+ if (notbefore != NULL)
+ cmndspec->notbefore = parse_gentime(notbefore);
+ if (notafter != NULL)
+ cmndspec->notafter = parse_gentime(notafter);
+
+ /* Parse sudoOptions. */
+ if (opts != NULL) {
+ char *opt, *source = NULL;
+
+ if (store_options) {
+ /* Use sudoRole in place of file name in defaults. */
+ size_t slen = sizeof("sudoRole ") - 1 + strlen(priv->ldap_role);
+ if ((source = sudo_rcstr_alloc(slen)) == NULL)
+ goto oom;
+ if ((size_t)snprintf(source, slen + 1, "sudoRole %s", priv->ldap_role) != slen) {
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ sudo_rcstr_delref(source);
+ goto bad;
+ }
+ }
+
+ while ((opt = iter(&opts)) != NULL) {
+ char *var, *val;
+ int op;
+
+ op = sudo_ldap_parse_option(opt, &var, &val);
+ if (strcmp(var, "command_timeout") == 0 && val != NULL) {
+ if (cmndspec->timeout != UNSPEC) {
+ sudo_warnx(U_("duplicate sudoOption: %s%s%s"), var,
+ op == '+' ? "+=" : op == '-' ? "-=" : "=", val);
+ }
+ cmndspec->timeout = parse_timeout(val);
+ } else if (strcmp(var, "runchroot") == 0 && val != NULL) {
+ if (cmndspec->runchroot != NULL) {
+ free(cmndspec->runchroot);
+ sudo_warnx(U_("duplicate sudoOption: %s%s%s"), var,
+ op == '+' ? "+=" : op == '-' ? "-=" : "=", val);
+ }
+ if ((cmndspec->runchroot = strdup(val)) == NULL)
+ break;
+ } else if (strcmp(var, "runcwd") == 0 && val != NULL) {
+ if (cmndspec->runcwd != NULL) {
+ free(cmndspec->runcwd);
+ sudo_warnx(U_("duplicate sudoOption: %s%s%s"), var,
+ op == '+' ? "+=" : op == '-' ? "-=" : "=", val);
+ }
+ if ((cmndspec->runcwd = strdup(val)) == NULL)
+ break;
+#ifdef HAVE_SELINUX
+ } else if (strcmp(var, "role") == 0 && val != NULL) {
+ if (cmndspec->role != NULL) {
+ free(cmndspec->role);
+ sudo_warnx(U_("duplicate sudoOption: %s%s%s"), var,
+ op == '+' ? "+=" : op == '-' ? "-=" : "=", val);
+ }
+ if ((cmndspec->role = strdup(val)) == NULL)
+ break;
+ } else if (strcmp(var, "type") == 0 && val != NULL) {
+ if (cmndspec->type != NULL) {
+ free(cmndspec->type);
+ sudo_warnx(U_("duplicate sudoOption: %s%s%s"), var,
+ op == '+' ? "+=" : op == '-' ? "-=" : "=", val);
+ }
+ if ((cmndspec->type = strdup(val)) == NULL)
+ break;
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_PRIV_SET
+ } else if (strcmp(var, "privs") == 0 && val != NULL) {
+ if (cmndspec->privs != NULL) {
+ free(cmndspec->privs);
+ sudo_warnx(U_("duplicate sudoOption: %s%s%s"), var,
+ op == '+' ? "+=" : op == '-' ? "-=" : "=", val);
+ }
+ if ((cmndspec->privs = strdup(val)) == NULL)
+ break;
+ } else if (strcmp(var, "limitprivs") == 0 && val != NULL) {
+ if (cmndspec->limitprivs != NULL) {
+ free(cmndspec->limitprivs);
+ sudo_warnx(U_("duplicate sudoOption: %s%s%s"), var,
+ op == '+' ? "+=" : op == '-' ? "-=" : "=", val);
+ }
+ if ((cmndspec->limitprivs = strdup(val)) == NULL)
+ break;
+#endif /* HAVE_PRIV_SET */
+ } else if (store_options) {
+ if (!append_default(var, val, op, source,
+ &priv->defaults)) {
+ break;
+ }
+ } else {
+ /* Convert to tags. */
+ bool converted = sudoers_defaults_to_tags(var, val, op,
+ &cmndspec->tags);
+ if (!converted) {
+ if (warnings) {
+ /* XXX - callback to process unsupported options. */
+ if (val != NULL) {
+ sudo_warnx(U_("unable to convert sudoOption: %s%s%s"), var, op == '+' ? "+=" : op == '-' ? "-=" : "=", val);
+ } else {
+ sudo_warnx(U_("unable to convert sudoOption: %s%s%s"), op == false ? "!" : "", var, "");
+ }
+ }
+ continue;
+ }
+ }
+ }
+ sudo_rcstr_delref(source);
+ if (opt != NULL) {
+ /* Defer oom until we drop the ref on source. */
+ goto oom;
+ }
+ }
+
+ /* So we can inherit previous values. */
+ prev_cmndspec = cmndspec;
+ }
+
+ /* Fill in command member now that options have been processed. */
+ m->negated = negated;
+ if (!sudo_ldap_extract_digests(&cmnd, &c->digests))
+ goto oom;
+ if (strcmp(cmnd, "ALL") == 0) {
+ if (cmndspec->tags.setenv == UNSPEC)
+ cmndspec->tags.setenv = IMPLIED;
+ m->type = ALL;
+ } else {
+ char *args = strpbrk(cmnd, " \t");
+ if (args != NULL) {
+ *args++ = '\0';
+ if ((c->args = strdup(args)) == NULL)
+ goto oom;
+ }
+ if ((c->cmnd = strdup(cmnd)) == NULL)
+ goto oom;
+ m->type = COMMAND;
+ }
+ }
+ /* Negated commands take precedence so we insert them at the end. */
+ TAILQ_CONCAT(&priv->cmndlist, &negated_cmnds, entries);
+
+ debug_return_ptr(priv);
+
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+bad:
+ if (priv != NULL) {
+ TAILQ_CONCAT(&priv->hostlist, &negated_hosts, entries);
+ TAILQ_CONCAT(&priv->cmndlist, &negated_cmnds, entries);
+ free_privilege(priv);
+ }
+ debug_return_ptr(NULL);
+}
+
+/* So ldap.c and sssd.c don't need to include gram.h */
+struct member *
+sudo_ldap_new_member_all(void)
+{
+ struct member *m;
+ debug_decl(sudo_ldap_new_member_all, SUDOERS_DEBUG_LDAP);
+
+ if ((m = calloc(1, sizeof(*m))) != NULL)
+ m->type = ALL;
+ debug_return_ptr(m);
+}
+
+/*
+ * Determine length of query value after escaping characters
+ * as per RFC 4515.
+ */
+size_t
+sudo_ldap_value_len(const char *value)
+{
+ const char *s;
+ size_t len = 0;
+
+ for (s = value; *s != '\0'; s++) {
+ switch (*s) {
+ case '\\':
+ case '(':
+ case ')':
+ case '*':
+ len += 2;
+ break;
+ }
+ }
+ len += (size_t)(s - value);
+ return len;
+}
+
+/*
+ * Like strlcat() but escapes characters as per RFC 4515.
+ */
+size_t
+sudo_ldap_value_cat(char * restrict dst, const char * restrict src, size_t size)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = size;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ d++;
+ dlen = (size_t)(d - dst);
+ n = size - dlen;
+
+ if (n == 0)
+ return dlen + strlen(s);
+ while (*s != '\0') {
+ switch (*s) {
+ case '\\':
+ if (n < 3)
+ goto done;
+ *d++ = '\\';
+ *d++ = '5';
+ *d++ = 'c';
+ n -= 3;
+ break;
+ case '(':
+ if (n < 3)
+ goto done;
+ *d++ = '\\';
+ *d++ = '2';
+ *d++ = '8';
+ n -= 3;
+ break;
+ case ')':
+ if (n < 3)
+ goto done;
+ *d++ = '\\';
+ *d++ = '2';
+ *d++ = '9';
+ n -= 3;
+ break;
+ case '*':
+ if (n < 3)
+ goto done;
+ *d++ = '\\';
+ *d++ = '2';
+ *d++ = 'a';
+ n -= 3;
+ break;
+ default:
+ if (n < 1)
+ goto done;
+ *d++ = *s;
+ n--;
+ break;
+ }
+ s++;
+ }
+done:
+ *d = '\0';
+ while (*s != '\0')
+ s++;
+ return dlen + (size_t)(s - src); /* count does not include NUL */
+}
+
+/*
+ * Like strdup() but escapes characters as per RFC 4515.
+ */
+char *
+sudo_ldap_value_dup(const char *src)
+{
+ char *dst;
+ size_t size;
+
+ size = sudo_ldap_value_len(src) + 1;
+ dst = malloc(size);
+ if (dst == NULL)
+ return NULL;
+
+ *dst = '\0';
+ if (sudo_ldap_value_cat(dst, src, size) >= size) {
+ /* Should not be possible... */
+ free(dst);
+ dst = NULL;
+ }
+ return dst;
+}
diff --git a/plugins/sudoers/linux_audit.c b/plugins/sudoers/linux_audit.c
new file mode 100644
index 0000000..2b52dac
--- /dev/null
+++ b/plugins/sudoers/linux_audit.c
@@ -0,0 +1,117 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_LINUX_AUDIT
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <libaudit.h>
+
+#include <sudoers.h>
+#include <linux_audit.h>
+
+#define AUDIT_NOT_CONFIGURED -2
+
+/*
+ * Open audit connection if possible.
+ * Returns audit fd on success and -1 on failure.
+ */
+static int
+linux_audit_open(void)
+{
+ static int au_fd = -1;
+ debug_decl(linux_audit_open, SUDOERS_DEBUG_AUDIT);
+
+ if (au_fd != -1)
+ debug_return_int(au_fd);
+ au_fd = audit_open();
+ if (au_fd == -1) {
+ /* Kernel may not have audit support. */
+ if (errno == EINVAL || errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT)
+ au_fd = AUDIT_NOT_CONFIGURED;
+ else
+ sudo_warn("%s", U_("unable to open audit system"));
+ } else if (fcntl(au_fd, F_SETFD, FD_CLOEXEC) == -1) {
+ sudo_warn("%s", U_("unable to open audit system"));
+ audit_close(au_fd);
+ au_fd = -1;
+ }
+ debug_return_int(au_fd);
+}
+
+int
+linux_audit_command(char *const argv[], int result)
+{
+ int au_fd, rc = -1;
+ char *cp, *command = NULL;
+ char * const *av;
+ size_t size, n;
+ debug_decl(linux_audit_command, SUDOERS_DEBUG_AUDIT);
+
+ /* Don't return an error if auditing is not configured. */
+ if ((au_fd = linux_audit_open()) < 0)
+ debug_return_int(au_fd == AUDIT_NOT_CONFIGURED ? 0 : -1);
+
+ /* Convert argv to a flat string. */
+ for (size = 0, av = argv; *av != NULL; av++)
+ size += strlen(*av) + 1;
+ if (size != 0)
+ command = malloc(size);
+ if (command == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ for (av = argv, cp = command; *av != NULL; av++) {
+ const size_t rem = size - (size_t)(cp - command);
+ n = strlcpy(cp, *av, rem);
+ if (n >= rem) {
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ goto done;
+ }
+ cp += n;
+ *cp++ = ' ';
+ }
+ *--cp = '\0';
+
+ /* Log command, ignoring ECONNREFUSED on error. */
+ if (audit_log_user_command(au_fd, AUDIT_USER_CMD, command, NULL, result) <= 0) {
+ if (errno != ECONNREFUSED) {
+ sudo_warn("%s", U_("unable to send audit message"));
+ goto done;
+ }
+ }
+
+ rc = 0;
+
+done:
+ free(command);
+
+ debug_return_int(rc);
+}
+
+#endif /* HAVE_LINUX_AUDIT */
diff --git a/plugins/sudoers/linux_audit.h b/plugins/sudoers/linux_audit.h
new file mode 100644
index 0000000..89c468b
--- /dev/null
+++ b/plugins/sudoers/linux_audit.h
@@ -0,0 +1,24 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010, 2013 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_LINUX_AUDIT_H
+#define SUDOERS_LINUX_AUDIT_H
+
+int linux_audit_command(char *const argv[], int result);
+
+#endif /* SUDOERS_LINUX_AUDIT_H */
diff --git a/plugins/sudoers/locale.c b/plugins/sudoers/locale.c
new file mode 100644
index 0000000..40cee30
--- /dev/null
+++ b/plugins/sudoers/locale.c
@@ -0,0 +1,155 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2012-2016, 2020, 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+
+#define DEFAULT_TEXT_DOMAIN "sudoers"
+
+#include <sudo_compat.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudoers_debug.h>
+
+#include <defaults.h>
+#include <logging.h>
+
+static int current_locale = SUDOERS_LOCALE_USER;
+static char *user_locale;
+static char *sudoers_locale;
+
+int
+sudoers_getlocale(void)
+{
+ debug_decl(sudoers_getlocale, SUDOERS_DEBUG_UTIL);
+ debug_return_int(current_locale);
+}
+
+bool
+sudoers_initlocale(const char *ulocale, const char *slocale)
+{
+ debug_decl(sudoers_initlocale, SUDOERS_DEBUG_UTIL);
+
+ if (ulocale != NULL) {
+ free(user_locale);
+ if ((user_locale = strdup(ulocale)) == NULL)
+ debug_return_bool(false);
+ }
+ if (slocale != NULL) {
+ free(sudoers_locale);
+ if ((sudoers_locale = strdup(slocale)) == NULL)
+ debug_return_bool(false);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: user locale %s, sudoers locale %s",
+ __func__, user_locale, sudoers_locale);
+ debug_return_bool(true);
+}
+
+/*
+ * Set locale to user or sudoers value.
+ * Returns true on success and false on failure,
+ * If prev_locale is non-NULL it will be filled in with the
+ * old SUDOERS_LOCALE_* value.
+ */
+bool
+sudoers_setlocale(int locale_type, int *prev_locale)
+{
+ char *res = NULL;
+ debug_decl(sudoers_setlocale, SUDOERS_DEBUG_UTIL);
+
+ switch (locale_type) {
+ case SUDOERS_LOCALE_USER:
+ if (prev_locale)
+ *prev_locale = current_locale;
+ if (current_locale != SUDOERS_LOCALE_USER) {
+ current_locale = SUDOERS_LOCALE_USER;
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s: setting locale to %s (user)", __func__,
+ user_locale ? user_locale : "");
+ res = setlocale(LC_ALL, user_locale ? user_locale : "");
+ if (res != NULL && user_locale == NULL) {
+ user_locale = setlocale(LC_ALL, NULL);
+ if (user_locale != NULL)
+ user_locale = strdup(user_locale);
+ if (user_locale == NULL)
+ res = NULL;
+ }
+ }
+ break;
+ case SUDOERS_LOCALE_SUDOERS:
+ if (prev_locale)
+ *prev_locale = current_locale;
+ if (current_locale != SUDOERS_LOCALE_SUDOERS) {
+ current_locale = SUDOERS_LOCALE_SUDOERS;
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s: setting locale to %s (sudoers)", __func__,
+ sudoers_locale ? sudoers_locale : "C");
+ res = setlocale(LC_ALL, sudoers_locale ? sudoers_locale : "C");
+ if (res == NULL && sudoers_locale != NULL) {
+ if (strcmp(sudoers_locale, "C") != 0) {
+ free(sudoers_locale);
+ sudoers_locale = strdup("C");
+ if (sudoers_locale != NULL)
+ res = setlocale(LC_ALL, "C");
+ }
+ }
+ }
+ break;
+ }
+ debug_return_bool(res ? true : false);
+}
+
+bool
+sudoers_warn_setlocale(bool restore, int *cookie)
+{
+ debug_decl(sudoers_warn_setlocale, SUDOERS_DEBUG_UTIL);
+
+ if (restore)
+ debug_return_bool(sudoers_setlocale(*cookie, NULL));
+ debug_return_bool(sudoers_setlocale(SUDOERS_LOCALE_USER, cookie));
+}
+
+/*
+ * Callback for sudoers_locale sudoers setting.
+ */
+bool
+sudoers_locale_callback(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(sudoers_locale_callback, SUDOERS_DEBUG_UTIL);
+
+ if (sudoers_initlocale(NULL, sd_un->str)) {
+ if (setlocale(LC_ALL, sd_un->str) != NULL)
+ debug_return_bool(true);
+ }
+ debug_return_bool(false);
+}
diff --git a/plugins/sudoers/log_client.c b/plugins/sudoers/log_client.c
new file mode 100644
index 0000000..94f3b0b
--- /dev/null
+++ b/plugins/sudoers/log_client.c
@@ -0,0 +1,2102 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef SUDOERS_LOG_CLIENT
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <netdb.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#ifndef HAVE_GETADDRINFO
+# include <compat/getaddrinfo.h>
+#endif
+
+#if defined(HAVE_OPENSSL)
+# if defined(HAVE_WOLFSSL)
+# include <wolfssl/options.h>
+# endif
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+# include <openssl/x509v3.h>
+#endif /* HAVE_OPENSSL */
+
+#define NEED_INET_NTOP /* to expose sudo_inet_ntop in sudo_compat.h */
+
+#include <sudoers.h>
+#include <sudo_event.h>
+#include <sudo_eventlog.h>
+#include <sudo_iolog.h>
+#include <hostcheck.h>
+#include <log_client.h>
+#include <strlist.h>
+
+/* Shared between iolog.c and audit.c */
+struct client_closure *client_closure;
+
+/* Server callback may redirect to client callback for TLS. */
+static void client_msg_cb(int fd, int what, void *v);
+static void server_msg_cb(int fd, int what, void *v);
+
+static void
+connect_cb(int sock, int what, void *v)
+{
+ int optval, ret, *errnump = v;
+ socklen_t optlen = sizeof(optval);
+ debug_decl(connect_cb, SUDOERS_DEBUG_UTIL);
+
+ if (what == SUDO_PLUGIN_EV_TIMEOUT) {
+ *errnump = ETIMEDOUT;
+ } else {
+ ret = getsockopt(sock, SOL_SOCKET, SO_ERROR, &optval, &optlen);
+ *errnump = ret == 0 ? optval : errno;
+ }
+
+ debug_return;
+}
+
+/*
+ * Like connect(2) but with a timeout.
+ */
+static int
+timed_connect(int sock, const struct sockaddr *addr, socklen_t addrlen,
+ const struct timespec *timeout)
+{
+ struct sudo_event_base *evbase = NULL;
+ struct sudo_event *connect_event = NULL;
+ int ret, errnum = 0;
+ debug_decl(timed_connect, SUDOERS_DEBUG_UTIL);
+
+ ret = connect(sock, addr, addrlen);
+ if (ret == -1 && errno == EINPROGRESS) {
+ evbase = sudo_ev_base_alloc();
+ connect_event = sudo_ev_alloc(sock, SUDO_PLUGIN_EV_WRITE, connect_cb,
+ &errnum);
+ if (evbase == NULL || connect_event == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ if (sudo_ev_add(evbase, connect_event, timeout, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto done;
+ }
+ if (sudo_ev_dispatch(evbase) == -1) {
+ sudo_warn("%s", U_("error in event loop"));
+ goto done;
+ }
+ if (errnum == 0)
+ ret = 0;
+ else
+ errno = errnum;
+ }
+
+done:
+ sudo_ev_base_free(evbase);
+ sudo_ev_free(connect_event);
+
+ debug_return_int(ret);
+}
+
+#if defined(HAVE_OPENSSL)
+static int
+verify_peer_identity(int preverify_ok, X509_STORE_CTX *ctx)
+{
+ HostnameValidationResult result;
+ struct client_closure *closure;
+ SSL *ssl;
+ X509 *current_cert;
+ X509 *peer_cert;
+ debug_decl(verify_peer_identity, SUDOERS_DEBUG_UTIL);
+
+ /* if pre-verification of the cert failed, just propagate that result back */
+ if (preverify_ok != 1) {
+ debug_return_int(0);
+ }
+
+ /* since this callback is called for each cert in the chain,
+ * check that current cert is the peer's certificate
+ */
+ current_cert = X509_STORE_CTX_get_current_cert(ctx);
+ peer_cert = X509_STORE_CTX_get0_cert(ctx);
+
+ if (current_cert != peer_cert) {
+ debug_return_int(1);
+ }
+
+ /* read out the attached object (closure) from the ssl connection object */
+ ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
+ closure = SSL_get_ex_data(ssl, 1);
+
+ result = validate_hostname(peer_cert, closure->server_name,
+ closure->server_ip, 0);
+
+ switch(result)
+ {
+ case MatchFound:
+ debug_return_int(1);
+ default:
+ debug_return_int(0);
+ }
+}
+
+static bool
+tls_init(struct client_closure *closure)
+{
+ const char *errstr;
+ debug_decl(tls_init, SUDOERS_DEBUG_PLUGIN);
+
+ /* Only attempt to initialize TLS once, the parameters don't change. */
+ if (closure->ssl_initialized) {
+ if (closure->ssl == NULL)
+ debug_return_bool(false);
+ SSL_clear(closure->ssl);
+ debug_return_bool(true);
+ }
+
+ closure->ssl_initialized = true;
+ SSL_library_init();
+ OpenSSL_add_all_algorithms();
+ SSL_load_error_strings();
+
+ /* Create the ssl context and enforce TLS 1.2 or higher. */
+ if ((closure->ssl_ctx = SSL_CTX_new(TLS_method())) == NULL) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("Creation of new SSL_CTX object failed: %s"),
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
+ if (!SSL_CTX_set_min_proto_version(closure->ssl_ctx, TLS1_2_VERSION)) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to restrict min. protocol version: %s",
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+#else
+ SSL_CTX_set_options(closure->ssl_ctx,
+ SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1);
+#endif
+
+ /* Enable server cert verification if log_server_verify is set in sudoers */
+ if (closure->log_details->verify_server) {
+ if (closure->log_details->ca_bundle != NULL) {
+ if (SSL_CTX_load_verify_locations(closure->ssl_ctx,
+ closure->log_details->ca_bundle, NULL) <= 0) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("%s: %s"), closure->log_details->ca_bundle,
+ errstr ? errstr : strerror(errno));
+ sudo_warnx(U_("unable to load certificate authority bundle %s"),
+ closure->log_details->ca_bundle);
+ goto bad;
+ }
+ } else {
+ if (!SSL_CTX_set_default_verify_paths(closure->ssl_ctx)) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx("SSL_CTX_set_default_verify_paths: %s",
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+ }
+ SSL_CTX_set_verify(closure->ssl_ctx, SSL_VERIFY_PEER, verify_peer_identity);
+ }
+
+ /* Load the client certificate file if it is set in sudoers. */
+ if (closure->log_details->cert_file != NULL) {
+ if (!SSL_CTX_use_certificate_chain_file(closure->ssl_ctx,
+ closure->log_details->cert_file)) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("%s: %s"), closure->log_details->cert_file,
+ errstr ? errstr : strerror(errno));
+ sudo_warnx(U_("unable to load certificate %s"),
+ closure->log_details->cert_file);
+ goto bad;
+ }
+ if (closure->log_details->key_file == NULL) {
+ /* No explicit key file set, try to use the cert file. */
+ closure->log_details->key_file = closure->log_details->cert_file;
+ }
+ if (!SSL_CTX_use_PrivateKey_file(closure->ssl_ctx,
+ closure->log_details->key_file, SSL_FILETYPE_PEM) ||
+ !SSL_CTX_check_private_key(closure->ssl_ctx)) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("%s: %s"), closure->log_details->key_file,
+ errstr ? errstr : strerror(errno));
+ sudo_warnx(U_("unable to load private key %s"),
+ closure->log_details->key_file);
+ goto bad;
+ }
+ }
+
+ /* Create the SSL object and attach the closure. */
+ if ((closure->ssl = SSL_new(closure->ssl_ctx)) == NULL) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("Unable to allocate ssl object: %s"),
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+ if (SSL_set_ex_data(closure->ssl, 1, closure) <= 0) {
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("Unable to attach user data to the ssl object: %s"),
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+
+ debug_return_bool(true);
+
+bad:
+ SSL_free(closure->ssl);
+ closure->ssl = NULL;
+ SSL_CTX_free(closure->ssl_ctx);
+ closure->ssl_ctx = NULL;
+ debug_return_bool(false);
+}
+
+struct tls_connect_closure {
+ bool tls_conn_status;
+ SSL *ssl;
+ const char *host;
+ const char *port;
+ const struct timespec *timeout;
+ struct sudo_event_base *evbase;
+ struct sudo_event *tls_connect_ev;
+};
+
+static void
+tls_connect_cb(int sock, int what, void *v)
+{
+ struct tls_connect_closure *closure = v;
+ const struct timespec *timeout = closure->timeout;
+ int tls_con;
+ debug_decl(tls_connect_cb, SUDOERS_DEBUG_UTIL);
+
+ if (what == SUDO_PLUGIN_EV_TIMEOUT) {
+ sudo_warnx("%s", U_("TLS handshake timeout occurred"));
+ goto bad;
+ }
+
+ tls_con = SSL_connect(closure->ssl);
+
+ if (tls_con == 1) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "TLS version: %s, negotiated cipher suite: %s",
+ SSL_get_version(closure->ssl), SSL_get_cipher(closure->ssl));
+ closure->tls_conn_status = true;
+ } else {
+ const char *errstr;
+
+ switch (SSL_get_error(closure->ssl, tls_con)) {
+ /* TLS handshake is not finished, reschedule event */
+ case SSL_ERROR_WANT_READ:
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_connect returns SSL_ERROR_WANT_READ");
+ if (what != SUDO_EV_READ) {
+ if (sudo_ev_set(closure->tls_connect_ev, sock,
+ SUDO_EV_READ, tls_connect_cb, closure) == -1) {
+ sudo_warnx("%s", U_("unable to set event"));
+ goto bad;
+ }
+ }
+ if (sudo_ev_add(closure->evbase, closure->tls_connect_ev,
+ timeout, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto bad;
+ }
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_connect returns SSL_ERROR_WANT_WRITE");
+ if (what != SUDO_EV_WRITE) {
+ if (sudo_ev_set(closure->tls_connect_ev, sock,
+ SUDO_EV_WRITE, tls_connect_cb, closure) == -1) {
+ sudo_warnx("%s", U_("unable to set event"));
+ goto bad;
+ }
+ }
+ if (sudo_ev_add(closure->evbase, closure->tls_connect_ev,
+ timeout, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto bad;
+ }
+ break;
+ case SSL_ERROR_SYSCALL:
+ sudo_warnx(U_("TLS connection to %s:%s failed: %s"),
+ closure->host, closure->port, strerror(errno));
+ goto bad;
+ default:
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx(U_("TLS connection to %s:%s failed: %s"),
+ closure->host, closure->port,
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+ }
+
+ debug_return;
+
+bad:
+ /* Break out of tls connect event loop with an error. */
+ sudo_ev_loopbreak(closure->evbase);
+
+ debug_return;
+}
+
+static bool
+tls_timed_connect(SSL *ssl, const char *host, const char *port,
+ const struct timespec *timeout)
+{
+ struct tls_connect_closure closure;
+ debug_decl(tls_timed_connect, SUDOERS_DEBUG_UTIL);
+
+ memset(&closure, 0, sizeof(closure));
+ closure.ssl = ssl;
+ closure.host = host;
+ closure.port = port;
+ closure.timeout = timeout;
+ closure.evbase = sudo_ev_base_alloc();
+ closure.tls_connect_ev = sudo_ev_alloc(SSL_get_fd(ssl),
+ SUDO_PLUGIN_EV_WRITE, tls_connect_cb, &closure);
+
+ if (closure.evbase == NULL || closure.tls_connect_ev == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+
+ if (sudo_ev_add(closure.evbase, closure.tls_connect_ev, timeout, false) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto done;
+ }
+
+ if (sudo_ev_dispatch(closure.evbase) == -1) {
+ sudo_warnx("%s", U_("error in event loop"));
+ goto done;
+ }
+
+done:
+ if (closure.tls_connect_ev != NULL)
+ sudo_ev_free(closure.tls_connect_ev);
+ sudo_ev_base_free(closure.evbase);
+
+ debug_return_bool(closure.tls_conn_status);
+}
+#endif /* HAVE_OPENSSL */
+
+/*
+ * Connect to specified host:port
+ * If host has multiple addresses, the first one that connects is used.
+ * Returns open socket or -1 on error.
+ */
+static int
+connect_server(const char *host, const char *port, bool tls,
+ struct client_closure *closure, const char **reason)
+{
+ const struct timespec *timeout = &closure->log_details->server_timeout;
+ struct addrinfo hints, *res, *res0;
+ const char *addr, *cause = NULL;
+ int error, sock = -1;
+ debug_decl(connect_server, SUDOERS_DEBUG_UTIL);
+
+#if !defined(HAVE_OPENSSL)
+ if (tls) {
+ errno = EPROTONOSUPPORT;
+ sudo_warn("%s:%s(tls)", host, port);
+ debug_return_int(-1);
+ }
+#endif
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ error = getaddrinfo(host, port, &hints, &res0);
+ if (error != 0) {
+ sudo_warnx(U_("unable to look up %s:%s: %s"), host, port,
+ gai_strerror(error));
+ debug_return_int(-1);
+ }
+
+ for (res = res0; res; res = res->ai_next) {
+ int flags, save_errno;
+
+ sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (sock == -1) {
+ cause = "socket";
+ continue;
+ }
+ flags = fcntl(sock, F_GETFL, 0);
+ if (flags == -1 || fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) {
+ cause = "fcntl(O_NONBLOCK)";
+ save_errno = errno;
+ close(sock);
+ errno = save_errno;
+ sock = -1;
+ continue;
+ }
+ if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1) {
+ cause = "fcntl(FD_CLOEXEC)";
+ save_errno = errno;
+ close(sock);
+ errno = save_errno;
+ sock = -1;
+ continue;
+ }
+ if (closure->log_details->keepalive) {
+ flags = 1;
+ if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &flags,
+ sizeof(flags)) == -1) {
+ cause = "setsockopt(SO_KEEPALIVE)";
+ save_errno = errno;
+ close(sock);
+ errno = save_errno;
+ sock = -1;
+ continue;
+ }
+ }
+ if (timed_connect(sock, res->ai_addr, res->ai_addrlen, timeout) == -1) {
+ /* No need to set cause, caller's error message is sufficient. */
+ save_errno = errno;
+ close(sock);
+ errno = save_errno;
+ sock = -1;
+ continue;
+ }
+ switch (res->ai_family) {
+ case AF_INET:
+ addr = (char *)&((struct sockaddr_in *)res->ai_addr)->sin_addr;
+ break;
+#ifdef HAVE_STRUCT_IN6_ADDR
+ case AF_INET6:
+ addr = (char *)&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
+ break;
+#endif
+ default:
+ cause = "ai_family";
+ save_errno = EAFNOSUPPORT;
+ shutdown(sock, SHUT_RDWR);
+ close(sock);
+ errno = save_errno;
+ sock = -1;
+ continue;
+ }
+ if (inet_ntop(res->ai_family, addr, closure->server_ip,
+ sizeof(closure->server_ip)) == NULL) {
+ cause = "inet_ntop";
+ save_errno = errno;
+ shutdown(sock, SHUT_RDWR);
+ close(sock);
+ errno = save_errno;
+ sock = -1;
+ continue;
+ }
+ free(closure->server_name);
+ if ((closure->server_name = strdup(host)) == NULL) {
+ cause = "strdup";
+ save_errno = errno;
+ shutdown(sock, SHUT_RDWR);
+ close(sock);
+ errno = save_errno;
+ sock = -1;
+ continue;
+ }
+
+#if defined(HAVE_OPENSSL)
+ if (tls) {
+ if (!tls_init(closure) || !SSL_set_fd(closure->ssl, sock)) {
+ cause = U_("TLS initialization was unsuccessful");
+ save_errno = errno;
+ shutdown(sock, SHUT_RDWR);
+ close(sock);
+ errno = save_errno;
+ sock = -1;
+ continue;
+ }
+ /* Perform TLS handshake. */
+ if (!tls_timed_connect(closure->ssl, host, port, timeout)) {
+ cause = U_("TLS handshake was unsuccessful");
+ save_errno = errno;
+ shutdown(sock, SHUT_RDWR);
+ close(sock);
+ errno = save_errno;
+ sock = -1;
+ continue;
+ }
+ } else {
+ /* No TLS for this connection, make sure it is not initialized. */
+ SSL_free(closure->ssl);
+ closure->ssl = NULL;
+ SSL_CTX_free(closure->ssl_ctx);
+ closure->ssl_ctx = NULL;
+ }
+#endif /* HAVE_OPENSSL */
+ break; /* success */
+ }
+ freeaddrinfo(res0);
+
+ if (sock == -1)
+ *reason = cause;
+
+ debug_return_int(sock);
+}
+
+/*
+ * Connect to the first server in the list.
+ * Stores socket in closure with O_NONBLOCK and close-on-exec flags set.
+ * Returns true on success, else false.
+ */
+bool
+log_server_connect(struct client_closure *closure)
+{
+ struct sudoers_string *server;
+ char *host, *port, *copy = NULL;
+ const char *cause = NULL;
+ int sock;
+ bool tls, ret = false;
+ debug_decl(log_server_connect, SUDOERS_DEBUG_UTIL);
+
+ STAILQ_FOREACH(server, closure->log_details->log_servers, entries) {
+ free(copy);
+ if ((copy = strdup(server->str)) == NULL)
+ break;
+ if (!iolog_parse_host_port(copy, &host, &port, &tls, DEFAULT_PORT,
+ DEFAULT_PORT_TLS)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to parse %s", copy);
+ continue;
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "connecting to %s port %s%s", host, port, tls ? " (tls)" : "");
+ sock = connect_server(host, port, tls, closure, &cause);
+ if (sock != -1) {
+ if (closure->read_ev->set(closure->read_ev, sock,
+ SUDO_PLUGIN_EV_READ|SUDO_PLUGIN_EV_PERSIST,
+ server_msg_cb, closure) == -1) {
+ cause = (U_("unable to add event to queue"));
+ break;
+ }
+
+ if (closure->write_ev->set(closure->write_ev, sock,
+ SUDO_PLUGIN_EV_WRITE|SUDO_PLUGIN_EV_PERSIST,
+ client_msg_cb, closure) == -1) {
+ cause = (U_("unable to add event to queue"));
+ break;
+ }
+
+ /* success */
+ closure->sock = sock;
+ ret = true;
+ break;
+ }
+ }
+ free(copy);
+
+ if (!ret && cause != NULL)
+ sudo_warn("%s", cause);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Free client closure and contents, not including log details.
+ */
+void
+client_closure_free(struct client_closure *closure)
+{
+ struct connection_buffer *buf;
+ debug_decl(client_closure_free, SUDOERS_DEBUG_UTIL);
+
+ if (closure == NULL)
+ debug_return;
+
+#if defined(HAVE_OPENSSL)
+ /* Shut down the TLS connection cleanly and free SSL data. */
+ if (closure->ssl != NULL) {
+ if (SSL_shutdown(closure->ssl) == 0)
+ SSL_shutdown(closure->ssl);
+ SSL_free(closure->ssl);
+ }
+ SSL_CTX_free(closure->ssl_ctx);
+#endif
+
+ if (closure->sock != -1) {
+ shutdown(closure->sock, SHUT_RDWR);
+ close(closure->sock);
+ }
+ free(closure->server_name);
+ while ((buf = TAILQ_FIRST(&closure->write_bufs)) != NULL) {
+ TAILQ_REMOVE(&closure->write_bufs, buf, entries);
+ free(buf->data);
+ free(buf);
+ }
+ while ((buf = TAILQ_FIRST(&closure->free_bufs)) != NULL) {
+ TAILQ_REMOVE(&closure->free_bufs, buf, entries);
+ free(buf->data);
+ free(buf);
+ }
+ if (closure->read_ev != NULL)
+ closure->read_ev->free(closure->read_ev);
+ if (closure->write_ev != NULL)
+ closure->write_ev->free(closure->write_ev);
+ free(closure->read_buf.data);
+ free(closure->iolog_id);
+
+ free(closure);
+
+ debug_return;
+}
+
+static struct connection_buffer *
+get_free_buf(struct client_closure *closure)
+{
+ struct connection_buffer *buf;
+ debug_decl(get_free_buf, SUDOERS_DEBUG_UTIL);
+
+ buf = TAILQ_FIRST(&closure->free_bufs);
+ if (buf != NULL)
+ TAILQ_REMOVE(&closure->free_bufs, buf, entries);
+ else
+ buf = calloc(1, sizeof(*buf));
+
+ debug_return_ptr(buf);
+}
+
+/*
+ * Format a ClientMessage.
+ * Appends the wire format message to the closure's write queue.
+ * Returns true on success, false on failure.
+ */
+bool
+fmt_client_message(struct client_closure *closure, ClientMessage *msg)
+{
+ struct connection_buffer *buf;
+ uint32_t msg_len;
+ bool ret = false;
+ size_t len;
+ debug_decl(fmt_client_message, SUDOERS_DEBUG_UTIL);
+
+ if ((buf = get_free_buf(closure)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+
+ len = client_message__get_packed_size(msg);
+ if (len > MESSAGE_SIZE_MAX) {
+ sudo_warnx(U_("client message too large: %zu"), len);
+ goto done;
+ }
+ /* Wire message size is used for length encoding, precedes message. */
+ msg_len = htonl((uint32_t)len);
+ len += sizeof(msg_len);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: new ClientMessage, %zu bytes",
+ __func__, len);
+
+ /* Resize buffer as needed. */
+ if (len > buf->size) {
+ const size_t new_size = sudo_pow2_roundup(len);
+ if (new_size < len) {
+ /* overflow */
+ errno = ENOMEM;
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ free(buf->data);
+ if ((buf->data = malloc(new_size)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ buf->size = new_size;
+ }
+
+ memcpy(buf->data, &msg_len, sizeof(msg_len));
+ client_message__pack(msg, buf->data + sizeof(msg_len));
+ buf->len = len;
+ TAILQ_INSERT_TAIL(&closure->write_bufs, buf, entries);
+ buf = NULL;
+
+ ret = true;
+
+done:
+ if (buf != NULL) {
+ free(buf->data);
+ free(buf);
+ }
+ debug_return_bool(ret);
+}
+
+/*
+ * Build and format a ClientHello wrapped in a ClientMessage.
+ * Appends the wire format message to the closure's write queue.
+ * Returns true on success, false on failure.
+ */
+static bool
+fmt_client_hello(struct client_closure *closure)
+{
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ ClientHello hello_msg = CLIENT_HELLO__INIT;
+ bool ret = false;
+ debug_decl(fmt_client_hello, SUDOERS_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: sending ClientHello", __func__);
+
+ /* Client name + version */
+ hello_msg.client_id = (char *)"sudoers " PACKAGE_VERSION;
+
+ /* Schedule ClientMessage */
+ client_msg.u.hello_msg = &hello_msg;
+ client_msg.type_case = CLIENT_MESSAGE__TYPE_HELLO_MSG;
+ ret = fmt_client_message(closure, &client_msg);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Free an array of InfoMessage.
+ * Does not free the actual contents, other than strlistval arrays.
+ */
+static void
+free_info_messages(InfoMessage **info_msgs, size_t n)
+{
+ debug_decl(free_info_messages, SUDOERS_DEBUG_UTIL);
+
+ if (info_msgs != NULL) {
+ while (n-- != 0) {
+ /* A strlist array is dynamically allocated. */
+ if (info_msgs[n]->value_case == INFO_MESSAGE__VALUE_STRLISTVAL) {
+ free(info_msgs[n]->u.strlistval);
+ }
+ free(info_msgs[n]);
+ }
+ free(info_msgs);
+ }
+
+ debug_return;
+}
+
+static InfoMessage **
+fmt_info_messages(struct client_closure *closure, struct eventlog *evlog,
+ size_t *n_info_msgs)
+{
+ InfoMessage__StringList *runargv = NULL;
+ InfoMessage__StringList *runenv = NULL;
+ InfoMessage__StringList *submitenv = NULL;
+ InfoMessage **info_msgs = NULL;
+ size_t info_msgs_size, n = 0;
+ debug_decl(fmt_info_messages, SUDOERS_DEBUG_UTIL);
+
+ /* Convert NULL-terminated vectors to StringList. */
+ if (evlog->submitenv != NULL) {
+ if ((submitenv = malloc(sizeof(*submitenv))) == NULL)
+ goto bad;
+ info_message__string_list__init(submitenv);
+ submitenv->strings = evlog->submitenv;
+ while (submitenv->strings[submitenv->n_strings] != NULL)
+ submitenv->n_strings++;
+ }
+
+ if (evlog->runargv != NULL) {
+ if ((runargv = malloc(sizeof(*runargv))) == NULL)
+ goto bad;
+ info_message__string_list__init(runargv);
+ runargv->strings = evlog->runargv;
+ while (runargv->strings[runargv->n_strings] != NULL)
+ runargv->n_strings++;
+ }
+
+ if (evlog->runenv != NULL) {
+ if ((runenv = malloc(sizeof(*runenv))) == NULL)
+ goto bad;
+ info_message__string_list__init(runenv);
+ runenv->strings = evlog->runenv;
+ while (runenv->strings[runenv->n_strings] != NULL)
+ runenv->n_strings++;
+ }
+
+ /* XXX - realloc as needed instead of preallocating */
+ info_msgs_size = 24;
+ info_msgs = calloc(info_msgs_size, sizeof(InfoMessage *));
+ if (info_msgs == NULL)
+ goto bad;
+ for (n = 0; n < info_msgs_size; n++) {
+ info_msgs[n] = malloc(sizeof(InfoMessage));
+ if (info_msgs[n] == NULL)
+ goto bad;
+ info_message__init(info_msgs[n]);
+ }
+
+#define fill_str(_n, _v) do { \
+ info_msgs[n]->key = (char *)(_n); \
+ info_msgs[n]->u.strval = (_v); \
+ info_msgs[n]->value_case = INFO_MESSAGE__VALUE_STRVAL; \
+ n++; \
+} while (0)
+
+#define fill_strlist(_n, _v) do { \
+ info_msgs[n]->key = (char *)(_n); \
+ info_msgs[n]->u.strlistval = (_v); \
+ info_msgs[n]->value_case = INFO_MESSAGE__VALUE_STRLISTVAL; \
+ n++; \
+} while (0)
+
+#define fill_num(_n, _v) do { \
+ info_msgs[n]->key = (char *)(_n); \
+ info_msgs[n]->u.numval = (_v); \
+ info_msgs[n]->value_case = INFO_MESSAGE__VALUE_NUMVAL; \
+ n++; \
+} while (0)
+
+ /* Fill in info_msgs */
+ n = 0;
+
+ /* TODO: clientargv (not currently supported by API) */
+ /* TODO: clientpid */
+ /* TODO: clientppid */
+ /* TODO: clientsid */
+ fill_num("columns", evlog->columns);
+ fill_str("command", evlog->command);
+ fill_num("lines", evlog->lines);
+ if (runargv != NULL) {
+ fill_strlist("runargv", runargv);
+ runargv = NULL;
+ }
+ if (evlog->runchroot != NULL) {
+ fill_str("runchroot", evlog->runchroot);
+ }
+ if (evlog->runcwd != NULL) {
+ fill_str("runcwd", evlog->runcwd);
+ }
+ if (runenv != NULL) {
+ fill_strlist("runenv", runenv);
+ runenv = NULL;
+ }
+ if (evlog->rungroup != NULL) {
+ fill_num("rungid", evlog->rungid);
+ fill_str("rungroup", evlog->rungroup);
+ }
+ /* TODO - rungids */
+ /* TODO - rungroups */
+ fill_num("runuid", evlog->runuid);
+ fill_str("runuser", evlog->runuser);
+ if (evlog->source != NULL) {
+ fill_str("source", evlog->source);
+ }
+ if (evlog->cwd != NULL) {
+ fill_str("submitcwd", evlog->cwd);
+ }
+ if (submitenv != NULL) {
+ fill_strlist("submitenv", submitenv);
+ submitenv = NULL;
+ }
+ /* TODO - submitgid */
+ /* TODO - submitgids */
+ /* TODO - submitgroup */
+ /* TODO - submitgroups */
+ fill_str("submithost", evlog->submithost);
+ /* TODO - submituid */
+ fill_str("submituser", evlog->submituser);
+ if (evlog->ttyname != NULL) {
+ fill_str("ttyname", evlog->ttyname);
+ }
+
+ /* Free unused structs. */
+ while (info_msgs_size > n)
+ free(info_msgs[--info_msgs_size]);
+
+ *n_info_msgs = n;
+ debug_return_ptr(info_msgs);
+
+bad:
+ free_info_messages(info_msgs, n);
+ free(runargv);
+ free(runenv);
+ free(submitenv);
+
+ *n_info_msgs = 0;
+ debug_return_ptr(NULL);
+}
+
+/*
+ * Build and format an AcceptMessage wrapped in a ClientMessage.
+ * Appends the wire format message to the closure's write queue.
+ * Returns true on success, false on failure.
+ */
+bool
+fmt_accept_message(struct client_closure *closure, struct eventlog *evlog)
+{
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ AcceptMessage accept_msg = ACCEPT_MESSAGE__INIT;
+ TimeSpec ts = TIME_SPEC__INIT;
+ struct timespec now;
+ bool ret = false;
+ debug_decl(fmt_accept_message, SUDOERS_DEBUG_UTIL);
+
+ /*
+ * Fill in AcceptMessage and add it to ClientMessage.
+ */
+ if (sudo_gettime_real(&now)) {
+ sudo_warn("%s", U_("unable to get time of day"));
+ debug_return_bool(false);
+ }
+ ts.tv_sec = (int64_t)now.tv_sec;
+ ts.tv_nsec = (int32_t)now.tv_nsec;
+ accept_msg.submit_time = &ts;
+
+ /* Client will send IoBuffer messages. */
+ accept_msg.expect_iobufs = closure->log_io;
+
+ accept_msg.info_msgs = fmt_info_messages(closure, evlog,
+ &accept_msg.n_info_msgs);
+ if (accept_msg.info_msgs == NULL)
+ goto done;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sending AcceptMessage, array length %zu", __func__,
+ accept_msg.n_info_msgs);
+
+ /* Schedule ClientMessage */
+ client_msg.u.accept_msg = &accept_msg;
+ client_msg.type_case = CLIENT_MESSAGE__TYPE_ACCEPT_MSG;
+ ret = fmt_client_message(closure, &client_msg);
+
+done:
+ free_info_messages(accept_msg.info_msgs, accept_msg.n_info_msgs);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Build and format a RejectMessage wrapped in a ClientMessage.
+ * Appends the wire format message to the closure's write queue.
+ * Returns true on success, false on failure.
+ */
+bool
+fmt_reject_message(struct client_closure *closure, struct eventlog *evlog)
+{
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ RejectMessage reject_msg = REJECT_MESSAGE__INIT;
+ TimeSpec ts = TIME_SPEC__INIT;
+ struct timespec now;
+ bool ret = false;
+ debug_decl(fmt_reject_message, SUDOERS_DEBUG_UTIL);
+
+ /*
+ * Fill in RejectMessage and add it to ClientMessage.
+ */
+ if (sudo_gettime_real(&now)) {
+ sudo_warn("%s", U_("unable to get time of day"));
+ debug_return_bool(false);
+ }
+ ts.tv_sec = (int64_t)now.tv_sec;
+ ts.tv_nsec = (int32_t)now.tv_nsec;
+ reject_msg.submit_time = &ts;
+
+ /* Reason for rejecting the request. */
+ reject_msg.reason = (char *)closure->reason;
+
+ reject_msg.info_msgs = fmt_info_messages(closure, evlog,
+ &reject_msg.n_info_msgs);
+ if (reject_msg.info_msgs == NULL)
+ goto done;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sending RejectMessage, array length %zu", __func__,
+ reject_msg.n_info_msgs);
+
+ /* Schedule ClientMessage */
+ client_msg.u.reject_msg = &reject_msg;
+ client_msg.type_case = CLIENT_MESSAGE__TYPE_REJECT_MSG;
+ ret = fmt_client_message(closure, &client_msg);
+
+done:
+ free_info_messages(reject_msg.info_msgs, reject_msg.n_info_msgs);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Build and format an AlertMessage wrapped in a ClientMessage.
+ * Appends the wire format message to the closure's write queue.
+ * Returns true on success, false on failure.
+ */
+static bool
+fmt_alert_message(struct client_closure *closure, struct eventlog *evlog)
+{
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ AlertMessage alert_msg = ALERT_MESSAGE__INIT;
+ TimeSpec ts = TIME_SPEC__INIT;
+ struct timespec now;
+ bool ret = false;
+ debug_decl(fmt_alert_message, SUDOERS_DEBUG_UTIL);
+
+ /*
+ * Fill in AlertMessage and add it to ClientMessage.
+ */
+ if (sudo_gettime_real(&now)) {
+ sudo_warn("%s", U_("unable to get time of day"));
+ debug_return_bool(false);
+ }
+ ts.tv_sec = (int64_t)now.tv_sec;
+ ts.tv_nsec = (int32_t)now.tv_nsec;
+ alert_msg.alert_time = &ts;
+
+ /* Reason for the alert. */
+ alert_msg.reason = (char *)closure->reason;
+
+ alert_msg.info_msgs = fmt_info_messages(closure, evlog,
+ &alert_msg.n_info_msgs);
+ if (alert_msg.info_msgs == NULL)
+ goto done;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sending AlertMessage, array length %zu", __func__,
+ alert_msg.n_info_msgs);
+
+ /* Schedule ClientMessage */
+ client_msg.u.alert_msg = &alert_msg;
+ client_msg.type_case = CLIENT_MESSAGE__TYPE_ALERT_MSG;
+ ret = fmt_client_message(closure, &client_msg);
+
+done:
+ free_info_messages(alert_msg.info_msgs, alert_msg.n_info_msgs);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Build and format an AcceptMessage, RejectMessage or AlertMessage
+ * (depending on initial_state) wrapped in a ClientMessage.
+ * Appends the wire format message to the closure's write queue.
+ * Returns true on success, false on failure.
+ */
+static bool
+fmt_initial_message(struct client_closure *closure)
+{
+ bool ret = false;
+ debug_decl(fmt_initial_message, SUDOERS_DEBUG_UTIL);
+
+ closure->state = closure->initial_state;
+ switch (closure->state) {
+ case SEND_ACCEPT:
+ /* Format and schedule AcceptMessage. */
+ if ((ret = fmt_accept_message(closure, closure->log_details->evlog))) {
+ /*
+ * Move read/write events back to main sudo event loop.
+ * Server messages may occur at any time, so no timeout.
+ * Write event will be re-enabled later.
+ */
+ closure->read_ev->setbase(closure->read_ev, NULL);
+ if (closure->read_ev->add(closure->read_ev, NULL) == -1) {
+ sudo_warn("%s", U_("unable to add event to queue"));
+ ret = false;
+ }
+ closure->write_ev->setbase(closure->write_ev, NULL);
+ }
+ break;
+ case SEND_REJECT:
+ /* Format and schedule RejectMessage. */
+ ret = fmt_reject_message(closure, closure->log_details->evlog);
+ break;
+ case SEND_ALERT:
+ /* Format and schedule AlertMessage. */
+ ret = fmt_alert_message(closure, closure->log_details->evlog);
+ break;
+ default:
+ sudo_warnx(U_("%s: unexpected state %d"), __func__, closure->state);
+ break;
+ }
+ debug_return_bool(ret);
+}
+
+#ifdef notyet
+/*
+ * Build and format a RestartMessage wrapped in a ClientMessage.
+ * Appends the wire format message to the closure's write queue.
+ * Returns true on success, false on failure.
+ */
+bool
+fmt_restart_message(struct client_closure *closure)
+{
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ RestartMessage restart_msg = RESTART_MESSAGE__INIT;
+ TimeSpec tv = TIME_SPEC__INIT;
+ bool ret = false;
+ debug_decl(fmt_restart_message, SUDOERS_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sending RestartMessage, [%lld, %ld]", __func__,
+ (long long)closure->restart->tv_sec, closure->restart->tv_nsec);
+
+ tv.tv_sec = closure->restart->tv_sec;
+ tv.tv_nsec = closure->restart->tv_nsec;
+ restart_msg.resume_point = &tv;
+ restart_msg.log_id = closure->iolog_id;
+
+ /* Schedule ClientMessage */
+ client_msg.restart_msg = &restart_msg;
+ client_msg.type_case = CLIENT_MESSAGE__TYPE_RESTART_MSG;
+ ret = fmt_client_message(closure, &client_msg);
+
+ debug_return_bool(ret);
+}
+#endif
+
+/*
+ * Build and format an ExitMessage wrapped in a ClientMessage.
+ * Appends the wire format message to the closure's write queue.
+ * Returns true on success, false on failure.
+ */
+bool
+fmt_exit_message(struct client_closure *closure, int exit_status, int error)
+{
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ ExitMessage exit_msg = EXIT_MESSAGE__INIT;
+ TimeSpec ts = TIME_SPEC__INIT;
+ char signame[SIG2STR_MAX];
+ bool ret = false;
+ struct timespec run_time;
+ debug_decl(fmt_exit_message, SUDOERS_DEBUG_UTIL);
+
+ if (sudo_gettime_awake(&run_time) == -1) {
+ sudo_warn("%s", U_("unable to get time of day"));
+ goto done;
+ }
+ sudo_timespecsub(&run_time, &closure->start_time, &run_time);
+
+ ts.tv_sec = (int64_t)run_time.tv_sec;
+ ts.tv_nsec = (int32_t)run_time.tv_nsec;
+ exit_msg.run_time = &ts;
+
+ if (error != 0) {
+ /* Error executing the command. */
+ exit_msg.error = strerror(error);
+ } else {
+ if (WIFEXITED(exit_status)) {
+ exit_msg.exit_value = WEXITSTATUS(exit_status);
+ } else if (WIFSIGNALED(exit_status)) {
+ const int signo = WTERMSIG(exit_status);
+ if (signo <= 0 || sig2str(signo, signame) == -1) {
+ sudo_warnx(U_("%s: internal error, invalid signal %d"),
+ __func__, signo);
+ goto done;
+ }
+ exit_msg.signal = signame;
+ if (WCOREDUMP(exit_status))
+ exit_msg.dumped_core = true;
+ exit_msg.exit_value = WTERMSIG(exit_status) | 128;
+ } else if (WIFSTOPPED(exit_status)) {
+ const int signo = WSTOPSIG(exit_status);
+ sudo_warnx(U_("%s: internal error, invalid signal %d"),
+ __func__, signo);
+ goto done;
+ } else if (WIFCONTINUED(exit_status)) {
+ sudo_warnx(U_("%s: internal error, invalid signal %d"),
+ __func__, SIGCONT);
+ goto done;
+ } else {
+ sudo_warnx(U_("%s: internal error, invalid exit status %d"),
+ __func__, exit_status);
+ goto done;
+ }
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sending ExitMessage, exitval %d, error %s, signal %s, coredump %s",
+ __func__, exit_msg.exit_value, exit_msg.error ? exit_msg.error : "",
+ exit_msg.signal ? exit_msg.signal : "",
+ exit_msg.dumped_core ? "yes" : "no");
+
+ /* Send ClientMessage */
+ client_msg.u.exit_msg = &exit_msg;
+ client_msg.type_case = CLIENT_MESSAGE__TYPE_EXIT_MSG;
+ if (!fmt_client_message(closure, &client_msg))
+ goto done;
+
+ closure->state = SEND_EXIT;
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+/*
+ * Build and format an IoBuffer wrapped in a ClientMessage.
+ * Appends the wire format message to the closure's write queue.
+ * Returns true on success, false on failure.
+ */
+bool
+fmt_io_buf(struct client_closure *closure, int type, const char *buf,
+ unsigned int len, struct timespec *delay)
+{
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ IoBuffer iobuf_msg = IO_BUFFER__INIT;
+ TimeSpec ts = TIME_SPEC__INIT;
+ bool ret = false;
+ debug_decl(fmt_io_buf, SUDOERS_DEBUG_UTIL);
+
+ /* Fill in IoBuffer. */
+ ts.tv_sec = (int64_t)delay->tv_sec;
+ ts.tv_nsec = (int32_t)delay->tv_nsec;
+ iobuf_msg.delay = &ts;
+ iobuf_msg.data.data = (void *)buf;
+ iobuf_msg.data.len = len;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sending IoBuffer length %zu, type %d, size %zu", __func__,
+ iobuf_msg.data.len, type, io_buffer__get_packed_size(&iobuf_msg));
+
+ /* Schedule ClientMessage, it doesn't matter which IoBuffer we set. */
+ client_msg.u.ttyout_buf = &iobuf_msg;
+ client_msg.type_case = type;
+ if (!fmt_client_message(closure, &client_msg))
+ goto done;
+
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+/*
+ * Build and format a ChangeWindowSize message wrapped in a ClientMessage.
+ * Appends the wire format message to the closure's write queue.
+ * Returns true on success, false on failure.
+ */
+bool
+fmt_winsize(struct client_closure *closure, unsigned int lines,
+ unsigned int cols, struct timespec *delay)
+{
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ ChangeWindowSize winsize_msg = CHANGE_WINDOW_SIZE__INIT;
+ TimeSpec ts = TIME_SPEC__INIT;
+ bool ret = false;
+ debug_decl(fmt_winsize, SUDOERS_DEBUG_UTIL);
+
+ /* Fill in ChangeWindowSize message. */
+ ts.tv_sec = (int64_t)delay->tv_sec;
+ ts.tv_nsec = (int32_t)delay->tv_nsec;
+ winsize_msg.delay = &ts;
+ winsize_msg.rows = (int32_t)lines;
+ winsize_msg.cols = (int32_t)cols;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: sending ChangeWindowSize, %dx%d",
+ __func__, winsize_msg.rows, winsize_msg.cols);
+
+ /* Send ClientMessage */
+ client_msg.u.winsize_event = &winsize_msg;
+ client_msg.type_case = CLIENT_MESSAGE__TYPE_WINSIZE_EVENT;
+ if (!fmt_client_message(closure, &client_msg))
+ goto done;
+
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+/*
+ * Build and format a CommandSuspend message wrapped in a ClientMessage.
+ * Appends the wire format message to the closure's write queue.
+ * Returns true on success, false on failure.
+ */
+bool
+fmt_suspend(struct client_closure *closure, const char *signame, struct timespec *delay)
+{
+ ClientMessage client_msg = CLIENT_MESSAGE__INIT;
+ CommandSuspend suspend_msg = COMMAND_SUSPEND__INIT;
+ TimeSpec ts = TIME_SPEC__INIT;
+ bool ret = false;
+ debug_decl(fmt_suspend, SUDOERS_DEBUG_UTIL);
+
+ /* Fill in CommandSuspend message. */
+ ts.tv_sec = (int64_t)delay->tv_sec;
+ ts.tv_nsec = (int32_t)delay->tv_nsec;
+ suspend_msg.delay = &ts;
+ suspend_msg.signal = (char *)signame;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sending CommandSuspend, SIG%s", __func__, suspend_msg.signal);
+
+ /* Send ClientMessage */
+ client_msg.u.suspend_event = &suspend_msg;
+ client_msg.type_case = CLIENT_MESSAGE__TYPE_SUSPEND_EVENT;
+ if (!fmt_client_message(closure, &client_msg))
+ goto done;
+
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+/*
+ * Additional work to do after a ClientMessage was sent to the server.
+ * Advances state and formats the next ClientMessage (if any).
+ * XXX - better name
+ */
+static bool
+client_message_completion(struct client_closure *closure)
+{
+ debug_decl(client_message_completion, SUDOERS_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: state %d", __func__, closure->state);
+
+ switch (closure->state) {
+ case RECV_HELLO:
+ /* Waiting for ServerHello, nothing else to do. */
+ break;
+ case SEND_ALERT:
+ case SEND_REJECT:
+ /* Nothing else to send, we are done. */
+ closure->write_ev->del(closure->write_ev);
+ closure->read_ev->del(closure->read_ev);
+ closure->state = FINISHED;
+ break;
+ case SEND_ACCEPT:
+ case SEND_RESTART:
+ closure->state = SEND_IO;
+ break;
+ case SEND_IO:
+ /* Arbitrary number of I/O log buffers, no state change. */
+ break;
+ case SEND_EXIT:
+ if (closure->log_io) {
+ /* Done writing, just waiting for final commit point. */
+ closure->write_ev->del(closure->write_ev);
+ closure->state = CLOSING;
+
+ /* Enable timeout while waiting for final commit point. */
+ if (closure->read_ev->add(closure->read_ev,
+ &closure->log_details->server_timeout) == -1) {
+ sudo_warn("%s", U_("unable to add event to queue"));
+ debug_return_bool(false);
+ }
+ } else {
+ /* No commit point to wait for, we are done. */
+ closure->state = FINISHED;
+ closure->read_ev->del(closure->read_ev);
+ }
+ break;
+ default:
+ sudo_warnx(U_("%s: unexpected state %d"), __func__, closure->state);
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+/*
+ * Read the ServerHello message from the log server.
+ * We do this synchronously, since we don't want the command to run
+ * before the log server connection is completely established.
+ */
+bool
+read_server_hello(struct client_closure *closure)
+{
+ struct sudo_event_base *evbase = NULL;
+ bool ret = false;
+ debug_decl(read_server_hello, SUDOERS_DEBUG_UTIL);
+
+ /* Get new event base so we can read ServerHello synchronously. */
+ evbase = sudo_ev_base_alloc();
+ if (evbase == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+
+ /* Write ClientHello. */
+ if (!fmt_client_hello(closure))
+ goto done;
+ closure->write_ev->setbase(closure->write_ev, evbase);
+ if (closure->write_ev->add(closure->write_ev,
+ &closure->log_details->server_timeout) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto done;
+ }
+
+ /* Read ServerHello. */
+ closure->read_ev->setbase(closure->read_ev, evbase);
+ if (closure->read_ev->add(closure->read_ev,
+ &closure->log_details->server_timeout) == -1) {
+ sudo_warnx("%s", U_("unable to add event to queue"));
+ goto done;
+ }
+
+ /* Read/write hello messages synchronously. */
+ if (sudo_ev_dispatch(evbase) == -1) {
+ sudo_warnx("%s", U_("error in event loop"));
+ goto done;
+ }
+
+ if (!sudo_ev_got_break(evbase))
+ ret = true;
+
+done:
+ sudo_ev_base_free(evbase);
+ debug_return_bool(ret);
+}
+
+/*
+ * Respond to a ServerHello message from the server.
+ * Returns true on success, false on error.
+ */
+static bool
+handle_server_hello(ServerHello *msg, struct client_closure *closure)
+{
+ size_t n;
+ debug_decl(handle_server_hello, SUDOERS_DEBUG_UTIL);
+
+ if (closure->state != RECV_HELLO) {
+ sudo_warnx(U_("%s: unexpected state %d"), __func__, closure->state);
+ debug_return_bool(false);
+ }
+
+ /* Check that ServerHello is valid. */
+ if (msg->server_id == NULL || msg->server_id[0] == '\0') {
+ sudo_warnx("%s", U_("invalid ServerHello"));
+ debug_return_bool(false);
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: server ID: %s",
+ __func__, msg->server_id);
+ /* TODO: handle redirect */
+ if (msg->redirect != NULL && msg->redirect[0] != '\0') {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: redirect: %s",
+ __func__, msg->redirect);
+ }
+ for (n = 0; n < msg->n_servers; n++) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: server %zu: %s",
+ __func__, n + 1, msg->servers[n]);
+ }
+
+ /* Does the server support logging sub-commands in a session? */
+ closure->subcommands = msg->subcommands;
+
+ debug_return_bool(true);
+}
+
+/*
+ * Respond to a CommitPoint message from the server.
+ * Returns true on success, false on error.
+ */
+static bool
+handle_commit_point(TimeSpec *commit_point, struct client_closure *closure)
+{
+ debug_decl(handle_commit_point, SUDOERS_DEBUG_UTIL);
+
+ /* Only valid after we have sent an IO buffer. */
+ if (closure->state < SEND_IO) {
+ sudo_warnx(U_("%s: unexpected state %d"), __func__, closure->state);
+ debug_return_bool(false);
+ }
+
+ closure->committed.tv_sec = (time_t)commit_point->tv_sec;
+ closure->committed.tv_nsec = (long)commit_point->tv_nsec;
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: received [%lld, %d], elapsed [%lld, %ld], committed [%lld, %ld]",
+ __func__, (long long)commit_point->tv_sec, commit_point->tv_nsec,
+ (long long)closure->elapsed.tv_sec, closure->elapsed.tv_nsec,
+ (long long)closure->committed.tv_sec, closure->committed.tv_nsec);
+
+ if (closure->state == CLOSING) {
+ if (sudo_timespeccmp(&closure->elapsed, &closure->committed, ==)) {
+ /* Last commit point received, exit event loop. */
+ closure->state = FINISHED;
+ closure->read_ev->del(closure->read_ev);
+ }
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Respond to a LogId message from the server.
+ * Always returns true.
+ */
+static bool
+handle_log_id(char *id, struct client_closure *closure)
+{
+ debug_decl(handle_log_id, SUDOERS_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: remote log ID: %s", __func__, id);
+ if (closure->iolog_id != NULL) {
+ if ((closure->iolog_id = strdup(id)) == NULL)
+ sudo_fatal(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ }
+ debug_return_bool(true);
+}
+
+/*
+ * Respond to a ServerError message from the server.
+ * Always returns false.
+ */
+static bool
+handle_server_error(char *errmsg, struct client_closure *closure)
+{
+ debug_decl(handle_server_error, SUDOERS_DEBUG_UTIL);
+
+ sudo_warnx(U_("error message received from server: %s"), errmsg);
+ debug_return_bool(false);
+}
+
+/*
+ * Respond to a ServerAbort message from the server.
+ * Always returns false.
+ */
+static bool
+handle_server_abort(char *errmsg, struct client_closure *closure)
+{
+ debug_decl(handle_server_abort, SUDOERS_DEBUG_UTIL);
+
+ sudo_warnx(U_("abort message received from server: %s"), errmsg);
+ debug_return_bool(false);
+}
+
+/*
+ * Respond to a ServerMessage from the server.
+ * Returns true on success, false on error.
+ */
+static bool
+handle_server_message(uint8_t *buf, size_t len,
+ struct client_closure *closure)
+{
+ ServerMessage *msg;
+ bool ret = false;
+ debug_decl(handle_server_message, SUDOERS_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: unpacking ServerMessage", __func__);
+ msg = server_message__unpack(NULL, len, buf);
+ if (msg == NULL) {
+ sudo_warnx(U_("unable to unpack %s size %zu"), "ServerMessage", len);
+ debug_return_bool(false);
+ }
+
+ switch (msg->type_case) {
+ case SERVER_MESSAGE__TYPE_HELLO:
+ if (handle_server_hello(msg->u.hello, closure)) {
+ if ((ret = fmt_initial_message(closure))) {
+ if (closure->write_ev->add(closure->write_ev,
+ &closure->log_details->server_timeout) == -1) {
+ sudo_warn("%s", U_("unable to add event to queue"));
+ ret = false;
+ }
+ }
+ }
+ break;
+ case SERVER_MESSAGE__TYPE_COMMIT_POINT:
+ ret = handle_commit_point(msg->u.commit_point, closure);
+ break;
+ case SERVER_MESSAGE__TYPE_LOG_ID:
+ ret = handle_log_id(msg->u.log_id, closure);
+ break;
+ case SERVER_MESSAGE__TYPE_ERROR:
+ ret = handle_server_error(msg->u.error, closure);
+ closure->state = ERROR;
+ break;
+ case SERVER_MESSAGE__TYPE_ABORT:
+ ret = handle_server_abort(msg->u.abort, closure);
+ closure->state = ERROR;
+ break;
+ default:
+ sudo_warnx(U_("%s: unexpected type_case value %d"),
+ __func__, msg->type_case);
+ break;
+ }
+
+ server_message__free_unpacked(msg, NULL);
+ debug_return_bool(ret);
+}
+
+/*
+ * Expand buf as needed or just reset it.
+ * XXX - share with logsrvd/sendlog
+ */
+static bool
+expand_buf(struct connection_buffer *buf, size_t needed)
+{
+ void *newdata;
+ debug_decl(expand_buf, SUDOERS_DEBUG_UTIL);
+
+ if (buf->size < needed) {
+ /* Expand buffer. */
+ const size_t newsize = sudo_pow2_roundup(needed);
+ if (newsize < needed) {
+ /* overflow */
+ errno = ENOMEM;
+ goto oom;
+ }
+ if ((newdata = malloc(needed)) == NULL)
+ goto oom;
+ if (buf->off > 0)
+ memcpy(newdata, buf->data + buf->off, buf->len - buf->off);
+ free(buf->data);
+ buf->data = newdata;
+ buf->size = newsize;
+ } else {
+ /* Just reset existing buffer. */
+ if (buf->off > 0) {
+ memmove(buf->data, buf->data + buf->off,
+ buf->len - buf->off);
+ }
+ }
+ buf->len -= buf->off;
+ buf->off = 0;
+
+ debug_return_bool(true);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+}
+
+/*
+ * Read and unpack a ServerMessage (read callback).
+ */
+static void
+server_msg_cb(int fd, int what, void *v)
+{
+ struct client_closure *closure = v;
+ struct connection_buffer *buf = &closure->read_buf;
+ size_t nread;
+ uint32_t msg_len;
+ debug_decl(server_msg_cb, SUDOERS_DEBUG_UTIL);
+
+ /* For TLS we may need to read as part of SSL_write_ex(). */
+ if (closure->write_instead_of_read) {
+ closure->write_instead_of_read = false;
+ client_msg_cb(fd, what, v);
+ debug_return;
+ }
+
+ if (what == SUDO_PLUGIN_EV_TIMEOUT) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: timed out reading from server",
+ __func__);
+ goto bad;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: reading ServerMessage", __func__);
+#if defined(HAVE_OPENSSL)
+ if (closure->ssl != NULL) {
+ const int result = SSL_read_ex(closure->ssl, buf->data + buf->len,
+ buf->size - buf->len, &nread);
+ if (result <= 0) {
+ unsigned long errcode;
+ const char *errstr;
+
+ switch (SSL_get_error(closure->ssl, result)) {
+ case SSL_ERROR_ZERO_RETURN:
+ /* TLS connection shutdown cleanly */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "TLS connection shut down cleanly");
+ nread = 0;
+ break;
+ case SSL_ERROR_WANT_READ:
+ /* ssl wants to read more, read event is always active */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_read_ex returns SSL_ERROR_WANT_READ");
+ debug_return;
+ case SSL_ERROR_WANT_WRITE:
+ /* ssl wants to write, so schedule the write handler */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_read_ex returns SSL_ERROR_WANT_WRITE");
+ if (!closure->write_ev->pending(closure->write_ev,
+ SUDO_PLUGIN_EV_WRITE, NULL)) {
+ /* Enable a temporary write event. */
+ if (closure->write_ev->add(closure->write_ev, NULL) == -1) {
+ sudo_warn("%s", U_("unable to add event to queue"));
+ goto bad;
+ }
+ closure->temporary_write_event = true;
+ }
+ /* Redirect write event to finish SSL_read_ex() */
+ closure->read_instead_of_write = true;
+ debug_return;
+ case SSL_ERROR_SSL:
+ /*
+ * For TLS 1.3, if the cert verify function on the server
+ * returns an error, OpenSSL will send an internal error
+ * alert when we read ServerHello. Convert to a more useful
+ * message and hope that no actual internal error occurs.
+ */
+ errcode = ERR_get_error();
+#if !defined(HAVE_WOLFSSL)
+ if (closure->state == RECV_HELLO &&
+ ERR_GET_REASON(errcode) == SSL_R_TLSV1_ALERT_INTERNAL_ERROR) {
+ errstr = U_("host name does not match certificate");
+ } else
+#endif
+ {
+ errstr = ERR_reason_error_string(errcode);
+ }
+ sudo_warnx("%s", errstr ? errstr : strerror(errno));
+ goto bad;
+ case SSL_ERROR_SYSCALL:
+ if (nread == 0)
+ sudo_warnx("%s", U_("lost connection to log server"));
+ else
+ sudo_warn("SSL_read_ex");
+ goto bad;
+ default:
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx("SSL_read_ex: %s",
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+ }
+ } else
+#endif /* HAVE_OPENSSL */
+ {
+ nread = (size_t)read(fd, buf->data + buf->len, buf->size - buf->len);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: received %zd bytes from server",
+ __func__, nread);
+ switch (nread) {
+ case (size_t)-1:
+ if (errno == EAGAIN)
+ debug_return;
+ sudo_warn("read");
+ goto bad;
+ case 0:
+ sudo_warnx("%s", U_("lost connection to log server"));
+ goto bad;
+ default:
+ break;
+ }
+ buf->len += nread;
+
+ while (buf->len - buf->off >= sizeof(msg_len)) {
+ /* Read wire message size (uint32_t in network byte order). */
+ memcpy(&msg_len, buf->data + buf->off, sizeof(msg_len));
+ msg_len = ntohl(msg_len);
+
+ if (msg_len > MESSAGE_SIZE_MAX) {
+ sudo_warnx(U_("server message too large: %u"), msg_len);
+ goto bad;
+ }
+
+ if (msg_len + sizeof(msg_len) > buf->len - buf->off) {
+ /* Incomplete message, we'll read the rest next time. */
+ if (!expand_buf(buf, msg_len + sizeof(msg_len)))
+ goto bad;
+ debug_return;
+ }
+
+ /* Parse ServerMessage, could be zero bytes. */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: parsing ServerMessage, size %u", __func__, msg_len);
+ buf->off += sizeof(msg_len);
+ if (!handle_server_message(buf->data + buf->off, msg_len, closure))
+ goto bad;
+ buf->off += msg_len;
+ }
+ buf->len -= buf->off;
+ buf->off = 0;
+ debug_return;
+bad:
+ if (closure->log_details->ignore_log_errors) {
+ /* Disable plugin, the command continues. */
+ closure->disabled = true;
+ closure->read_ev->del(closure->read_ev);
+ } else {
+ /* Break out of sudo event loop and kill the command. */
+ closure->read_ev->loopbreak(closure->read_ev);
+ }
+ debug_return;
+}
+
+/*
+ * Send a ClientMessage to the server (write callback).
+ */
+static void
+client_msg_cb(int fd, int what, void *v)
+{
+ struct client_closure *closure = v;
+ struct connection_buffer *buf;
+ size_t nwritten;
+ debug_decl(client_msg_cb, SUDOERS_DEBUG_UTIL);
+
+ /* For TLS we may need to write as part of SSL_read_ex(). */
+ if (closure->read_instead_of_write) {
+ closure->read_instead_of_write = false;
+ /* Delete write event if it was only due to SSL_read_ex(). */
+ if (closure->temporary_write_event) {
+ closure->temporary_write_event = false;
+ closure->write_ev->del(closure->write_ev);
+ }
+ server_msg_cb(fd, what, v);
+ debug_return;
+ }
+
+ if (what == SUDO_PLUGIN_EV_TIMEOUT) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: timed out writing to server",
+ __func__);
+ goto bad;
+ }
+
+ if ((buf = TAILQ_FIRST(&closure->write_bufs)) == NULL) {
+ sudo_warnx("%s", U_("missing write buffer"));
+ goto bad;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sending %zu bytes to server", __func__, buf->len - buf->off);
+
+#if defined(HAVE_OPENSSL)
+ if (closure->ssl != NULL) {
+ const int result = SSL_write_ex(closure->ssl, buf->data + buf->off,
+ buf->len - buf->off, &nwritten);
+ if (result <= 0) {
+ const char *errstr;
+
+ switch (SSL_get_error(closure->ssl, result)) {
+ case SSL_ERROR_ZERO_RETURN:
+ /* TLS connection shutdown cleanly */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "TLS connection shut down cleanly");
+ goto bad;
+ case SSL_ERROR_WANT_READ:
+ /* ssl wants to read, read event always active */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_write_ex returns SSL_ERROR_WANT_READ");
+ /* Redirect read event to finish SSL_write_ex() */
+ closure->write_instead_of_read = true;
+ debug_return;
+ case SSL_ERROR_WANT_WRITE:
+ /* ssl wants to write more, write event remains active */
+ sudo_debug_printf(SUDO_DEBUG_NOTICE|SUDO_DEBUG_LINENO,
+ "SSL_write_ex returns SSL_ERROR_WANT_WRITE");
+ debug_return;
+ case SSL_ERROR_SSL:
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx("%s", errstr ? errstr : strerror(errno));
+ goto bad;
+ case SSL_ERROR_SYSCALL:
+ sudo_warn("SSL_write_ex");
+ goto bad;
+ default:
+ errstr = ERR_reason_error_string(ERR_get_error());
+ sudo_warnx("SSL_write_ex: %s",
+ errstr ? errstr : strerror(errno));
+ goto bad;
+ }
+ }
+ } else
+#endif /* HAVE_OPENSSL */
+ {
+ nwritten = (size_t)write(fd, buf->data + buf->off, buf->len - buf->off);
+ }
+
+ if (nwritten == (size_t)-1) {
+ sudo_warn("send");
+ goto bad;
+ }
+ buf->off += nwritten;
+
+ if (buf->off == buf->len) {
+ /* sent entire message, move buf to free list */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: finished sending %zu bytes to server", __func__, buf->len);
+ buf->off = 0;
+ buf->len = 0;
+ TAILQ_REMOVE(&closure->write_bufs, buf, entries);
+ TAILQ_INSERT_TAIL(&closure->free_bufs, buf, entries);
+ if (TAILQ_EMPTY(&closure->write_bufs)) {
+ /* Write queue empty, check for state change. */
+ closure->write_ev->del(closure->write_ev);
+ if (!client_message_completion(closure))
+ goto bad;
+ }
+ }
+ debug_return;
+
+bad:
+ if (closure->log_details->ignore_log_errors) {
+ /* Disable plugin, the command continues. */
+ closure->disabled = true;
+ closure->write_ev->del(closure->read_ev);
+ closure->write_ev->del(closure->write_ev);
+ } else {
+ /* Break out of sudo event loop and kill the command. */
+ closure->write_ev->loopbreak(closure->write_ev);
+ }
+ debug_return;
+}
+
+/*
+ * Allocate and initialize a new client closure
+ */
+static struct client_closure *
+client_closure_alloc(struct log_details *details, struct timespec *now,
+ bool log_io, enum client_state initial_state, const char *reason)
+{
+ struct client_closure *closure;
+ debug_decl(client_closure_alloc, SUDOERS_DEBUG_UTIL);
+
+ if (plugin_event_alloc == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "plugin_event_alloc is not set");
+ debug_return_ptr(NULL);
+ }
+
+ if ((closure = calloc(1, sizeof(*closure))) == NULL)
+ goto oom;
+
+ closure->sock = -1;
+ closure->log_io = log_io;
+ closure->reason = reason;
+ closure->state = RECV_HELLO;
+ closure->initial_state = initial_state;
+
+ closure->start_time.tv_sec = now->tv_sec;
+ closure->start_time.tv_nsec = now->tv_nsec;
+
+ TAILQ_INIT(&closure->write_bufs);
+ TAILQ_INIT(&closure->free_bufs);
+
+ closure->read_buf.size = 64 * 1024;
+ closure->read_buf.data = malloc(closure->read_buf.size);
+ if (closure->read_buf.data == NULL)
+ goto oom;
+
+ if ((closure->read_ev = plugin_event_alloc()) == NULL)
+ goto oom;
+
+ if ((closure->write_ev = plugin_event_alloc()) == NULL)
+ goto oom;
+
+ closure->log_details = details;
+
+ debug_return_ptr(closure);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ client_closure_free(closure);
+ debug_return_ptr(NULL);
+}
+
+struct client_closure *
+log_server_open(struct log_details *details, struct timespec *now,
+ bool log_io, enum client_state initial_state, const char *reason)
+{
+ struct client_closure *closure;
+ static bool warned = false;
+ debug_decl(log_server_open, SUDOERS_DEBUG_UTIL);
+
+ closure = client_closure_alloc(details, now, log_io, initial_state,
+ reason);
+ if (closure == NULL)
+ goto bad;
+
+ /* Connect to log first available log server. */
+ if (!log_server_connect(closure)) {
+ /* TODO: support offline logs if server unreachable */
+ if (!warned) {
+ sudo_warnx("%s", U_("unable to connect to log server"));
+ warned = true;
+ }
+ goto bad;
+ }
+
+ /* Read ServerHello synchronously or fail. */
+ if (read_server_hello(closure))
+ debug_return_ptr(closure);
+
+bad:
+ client_closure_free(closure);
+ debug_return_ptr(NULL);
+}
+
+/*
+ * Send ExitMessage, wait for final commit message and free closure.
+ */
+bool
+log_server_close(struct client_closure *closure, int exit_status, int error)
+{
+ struct sudo_event_base *evbase = NULL;
+ bool ret = false;
+ debug_decl(log_server_close, SUDOERS_DEBUG_UTIL);
+
+ if (closure->disabled)
+ goto done;
+
+ /* Format and append an ExitMessage to the write queue. */
+ if (!fmt_exit_message(closure, exit_status, error))
+ goto done;
+
+ /*
+ * Create private event base and reparent the read/write events.
+ * We cannot use the main sudo event loop as it has already exited.
+ */
+ if ((evbase = sudo_ev_base_alloc()) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+
+ /* Enable read event to receive server messages. */
+ closure->read_ev->setbase(closure->read_ev, evbase);
+ if (closure->read_ev->add(closure->read_ev,
+ &closure->log_details->server_timeout) == -1) {
+ sudo_warn("%s", U_("unable to add event to queue"));
+ goto done;
+ }
+
+ /* Enable the write event to write the ExitMessage. */
+ closure->write_ev->setbase(closure->write_ev, evbase);
+ if (closure->write_ev->add(closure->write_ev,
+ &closure->log_details->server_timeout) == -1) {
+ sudo_warn("%s", U_("unable to add event to queue"));
+ goto done;
+ }
+
+ /* Loop until queues are flushed and final commit point received. */
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "flushing buffers and waiting for final commit point");
+ if (sudo_ev_dispatch(evbase) == -1 || sudo_ev_got_break(evbase)) {
+ sudo_warnx("%s", U_("error in event loop"));
+ goto done;
+ }
+
+ ret = true;
+
+done:
+ sudo_ev_base_free(evbase);
+ client_closure_free(closure);
+ debug_return_bool(ret);
+}
+
+#endif /* SUDOERS_LOG_CLIENT */
diff --git a/plugins/sudoers/log_client.h b/plugins/sudoers/log_client.h
new file mode 100644
index 0000000..78508ef
--- /dev/null
+++ b/plugins/sudoers/log_client.h
@@ -0,0 +1,124 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_LOG_CLIENT_H
+#define SUDOERS_LOG_CLIENT_H
+
+#include <netinet/in.h> /* for INET6?_ADDRSTRLEN */
+#if defined(HAVE_OPENSSL)
+# if defined(HAVE_WOLFSSL)
+# include <wolfssl/options.h>
+# endif /* HAVE_WOLFSSL */
+# include <openssl/ssl.h>
+# include <sudo_ssl_compat.h>
+#endif /* HAVE_OPENSSL */
+
+#include <log_server.pb-c.h>
+
+#ifndef INET_ADDRSTRLEN
+# define INET_ADDRSTRLEN 16
+#endif
+#ifndef INET6_ADDRSTRLEN
+# define INET6_ADDRSTRLEN 46
+#endif
+
+#if PROTOBUF_C_VERSION_NUMBER < 1003000
+# error protobuf-c version 1.30 or higher required
+#endif
+
+/* Default ports to listen on */
+#define DEFAULT_PORT "30343"
+#define DEFAULT_PORT_TLS "30344"
+
+/* Maximum message size (2Mb) */
+#define MESSAGE_SIZE_MAX (2 * 1024 * 1024)
+
+/* TODO - share with logsrvd/sendlog */
+struct connection_buffer {
+ TAILQ_ENTRY(connection_buffer) entries;
+ uint8_t *data;
+ size_t size;
+ size_t len;
+ size_t off;
+};
+TAILQ_HEAD(connection_buffer_list, connection_buffer);
+
+enum client_state {
+ ERROR,
+ RECV_HELLO,
+ SEND_RESTART, /* TODO: currently unimplemented */
+ SEND_ACCEPT,
+ SEND_ALERT,
+ SEND_REJECT,
+ SEND_IO,
+ SEND_EXIT,
+ CLOSING,
+ FINISHED
+};
+
+/* Remote connection closure, non-zero fields must come first. */
+struct client_closure {
+ int sock;
+ bool read_instead_of_write;
+ bool write_instead_of_read;
+ bool temporary_write_event;
+ bool disabled;
+ bool log_io;
+ char *server_name;
+#if defined(HAVE_STRUCT_IN6_ADDR)
+ char server_ip[INET6_ADDRSTRLEN];
+#else
+ char server_ip[INET_ADDRSTRLEN];
+#endif
+#if defined(HAVE_OPENSSL)
+ SSL_CTX *ssl_ctx;
+ SSL *ssl;
+ bool ssl_initialized;
+#endif /* HAVE_OPENSSL */
+ bool subcommands;
+ enum client_state state;
+ enum client_state initial_state; /* XXX - bad name */
+ struct connection_buffer_list write_bufs;
+ struct connection_buffer_list free_bufs;
+ struct connection_buffer read_buf;
+ struct sudo_plugin_event *read_ev;
+ struct sudo_plugin_event *write_ev;
+ struct log_details *log_details;
+ struct timespec start_time;
+ struct timespec elapsed;
+ struct timespec committed;
+ char *iolog_id;
+ const char *reason;
+};
+
+/* iolog_client.c */
+struct client_closure *log_server_open(struct log_details *details, struct timespec *now, bool log_io, enum client_state initial_state, const char *reason);
+bool log_server_close(struct client_closure *closure, int exit_status, int error);
+bool fmt_client_message(struct client_closure *closure, ClientMessage *msg);
+bool fmt_accept_message(struct client_closure *closure, struct eventlog *evlog);
+bool fmt_reject_message(struct client_closure *closure, struct eventlog *evlog);
+bool fmt_exit_message(struct client_closure *closure, int exit_status, int error);
+bool fmt_io_buf(struct client_closure *closure, int type, const char *buf, unsigned int len, struct timespec *delay);
+bool fmt_suspend(struct client_closure *closure, const char *signame, struct timespec *delay);
+bool fmt_winsize(struct client_closure *closure, unsigned int lines, unsigned int cols, struct timespec *delay);
+bool log_server_connect(struct client_closure *closure);
+void client_closure_free(struct client_closure *closure);
+bool read_server_hello(struct client_closure *closure);
+extern struct client_closure *client_closure;
+
+#endif /* SUDOERS_LOG_CLIENT_H */
diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c
new file mode 100644
index 0000000..5b0c7a6
--- /dev/null
+++ b/plugins/sudoers/logging.c
@@ -0,0 +1,1158 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1994-1996, 1998-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#ifdef __TANDEM
+# include <floss.h>
+#endif
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_NL_LANGINFO
+# include <langinfo.h>
+#endif /* HAVE_NL_LANGINFO */
+#include <netdb.h>
+#include <pwd.h>
+#include <grp.h>
+#include <time.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <syslog.h>
+#ifndef HAVE_GETADDRINFO
+# include <compat/getaddrinfo.h>
+#endif
+
+#include <sudoers.h>
+#ifdef SUDOERS_LOG_CLIENT
+# include <log_client.h>
+# include <strlist.h>
+#endif
+
+struct parse_error {
+ STAILQ_ENTRY(parse_error) entries;
+ char *errstr;
+};
+STAILQ_HEAD(parse_error_list, parse_error);
+static struct parse_error_list parse_error_list =
+ STAILQ_HEAD_INITIALIZER(parse_error_list);
+
+static bool should_mail(const struct sudoers_context *ctx, unsigned int);
+static bool warned = false;
+
+#ifdef SUDOERS_LOG_CLIENT
+/*
+ * Convert a defaults-style list to a stringlist.
+ */
+static struct sudoers_str_list *
+list_to_strlist(struct list_members *list)
+{
+ struct sudoers_str_list *strlist;
+ struct sudoers_string *str;
+ struct list_member *item;
+ debug_decl(slist_to_strlist, SUDOERS_DEBUG_LOGGING);
+
+ if ((strlist = str_list_alloc()) == NULL)
+ goto oom;
+
+ SLIST_FOREACH(item, list, entries) {
+ if ((str = sudoers_string_alloc(item->value)) == NULL)
+ goto oom;
+ /* List is in reverse order, insert at head to fix that. */
+ STAILQ_INSERT_HEAD(strlist, str, entries);
+ }
+
+ debug_return_ptr(strlist);
+oom:
+ str_list_free(strlist);
+ debug_return_ptr(NULL);
+}
+
+bool
+init_log_details(struct log_details *details, struct eventlog *evlog)
+{
+ struct sudoers_str_list *log_servers = NULL;
+ debug_decl(init_log_details, SUDOERS_DEBUG_LOGGING);
+
+ memset(details, 0, sizeof(*details));
+
+ if ((log_servers = list_to_strlist(&def_log_servers)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+
+ details->evlog = evlog;
+ details->ignore_log_errors = def_ignore_logfile_errors;
+ details->log_servers = log_servers;
+ details->server_timeout.tv_sec = def_log_server_timeout;
+ details->keepalive = def_log_server_keepalive;
+#if defined(HAVE_OPENSSL)
+ details->ca_bundle = def_log_server_cabundle;
+ details->cert_file = def_log_server_peer_cert;
+ details->key_file = def_log_server_peer_key;
+ details->verify_server = def_log_server_verify;
+#endif /* HAVE_OPENSSL */
+
+ debug_return_bool(true);
+}
+
+bool
+log_server_reject(const struct sudoers_context *ctx, struct eventlog *evlog,
+ const char *message)
+{
+ bool ret = false;
+ debug_decl(log_server_reject, SUDOERS_DEBUG_LOGGING);
+
+ if (SLIST_EMPTY(&def_log_servers))
+ debug_return_bool(true);
+
+ if (ISSET(ctx->mode, MODE_POLICY_INTERCEPTED)) {
+ /* Older servers don't support multiple commands per session. */
+ if (!client_closure->subcommands)
+ debug_return_bool(true);
+
+ /* Use existing client closure. */
+ if (fmt_reject_message(client_closure, evlog)) {
+ if (client_closure->write_ev->add(client_closure->write_ev,
+ &client_closure->log_details->server_timeout) == -1) {
+ sudo_warn("%s", U_("unable to add event to queue"));
+ goto done;
+ }
+ ret = true;
+ }
+ } else {
+ struct log_details details;
+
+ if (!init_log_details(&details, evlog))
+ debug_return_bool(false);
+
+ /* Open connection to log server, send hello and reject messages. */
+ client_closure = log_server_open(&details, &evlog->submit_time,
+ false, SEND_REJECT, message);
+ if (client_closure != NULL) {
+ client_closure_free(client_closure);
+ client_closure = NULL;
+ ret = true;
+ }
+
+ /* Only the log_servers string list is dynamically allocated. */
+ str_list_free(details.log_servers);
+ }
+
+done:
+ debug_return_bool(ret);
+}
+
+bool
+log_server_alert(const struct sudoers_context *ctx, struct eventlog *evlog,
+ struct timespec *now, const char *message, const char *errstr)
+{
+ struct log_details details;
+ char *emessage = NULL;
+ bool ret = false;
+ debug_decl(log_server_alert, SUDOERS_DEBUG_LOGGING);
+
+ if (SLIST_EMPTY(&def_log_servers))
+ debug_return_bool(true);
+
+ if (errstr != NULL) {
+ if (asprintf(&emessage, _("%s: %s"), message, errstr) == -1) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ }
+
+ if (ISSET(ctx->mode, MODE_POLICY_INTERCEPTED)) {
+ /* Older servers don't support multiple commands per session. */
+ if (!client_closure->subcommands) {
+ ret = true;
+ goto done;
+ }
+
+ /* Use existing client closure. */
+ if (fmt_reject_message(client_closure, evlog)) {
+ if (client_closure->write_ev->add(client_closure->write_ev,
+ &client_closure->log_details->server_timeout) == -1) {
+ sudo_warn("%s", U_("unable to add event to queue"));
+ goto done;
+ }
+ ret = true;
+ }
+ } else {
+ if (!init_log_details(&details, evlog))
+ goto done;
+
+ /* Open connection to log server, send hello and alert messages. */
+ client_closure = log_server_open(&details, now, false,
+ SEND_ALERT, emessage ? emessage : message);
+ if (client_closure != NULL) {
+ client_closure_free(client_closure);
+ client_closure = NULL;
+ ret = true;
+ }
+
+ /* Only the log_servers string list is dynamically allocated. */
+ str_list_free(details.log_servers);
+ }
+
+done:
+ free(emessage);
+ debug_return_bool(ret);
+}
+#else
+bool
+log_server_reject(const struct sudoers_context *ctx, struct eventlog *evlog,
+ const char *message)
+{
+ return true;
+}
+
+bool
+log_server_alert(const struct sudoers_context *ctx, struct eventlog *evlog,
+ struct timespec *now, const char *message, const char *errstr)
+{
+ return true;
+}
+#endif /* SUDOERS_LOG_CLIENT */
+
+/*
+ * Log a reject event to syslog, a log file, sudo_logsrvd and/or email.
+ */
+static bool
+log_reject(const struct sudoers_context *ctx, const char *message,
+ bool logit, bool mailit)
+{
+ const char *uuid_str = NULL;
+ struct eventlog evlog;
+ int evl_flags = 0;
+ bool ret;
+ debug_decl(log_reject, SUDOERS_DEBUG_LOGGING);
+
+ if (!ISSET(ctx->mode, MODE_POLICY_INTERCEPTED))
+ uuid_str = ctx->uuid_str;
+
+ if (mailit) {
+ SET(evl_flags, EVLOG_MAIL);
+ if (!logit)
+ SET(evl_flags, EVLOG_MAIL_ONLY);
+ }
+ sudoers_to_eventlog(ctx, &evlog, ctx->runas.cmnd, ctx->runas.argv,
+ NULL, uuid_str);
+ ret = eventlog_reject(&evlog, evl_flags, message, NULL, NULL);
+ if (!log_server_reject(ctx, &evlog, message))
+ ret = false;
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Log, audit and mail the denial message, optionally informing the user.
+ */
+bool
+log_denial(const struct sudoers_context *ctx, unsigned int status,
+ bool inform_user)
+{
+ const char *message;
+ int oldlocale;
+ bool mailit, ret = true;
+ debug_decl(log_denial, SUDOERS_DEBUG_LOGGING);
+
+ /* Send mail based on status. */
+ mailit = should_mail(ctx, status);
+
+ /* Set error message. */
+ if (ISSET(status, FLAG_NO_USER))
+ message = N_("user NOT in sudoers");
+ else if (ISSET(status, FLAG_NO_HOST))
+ message = N_("user NOT authorized on host");
+ else if (ISSET(status, FLAG_INTERCEPT_SETID))
+ message = N_("setid command rejected in intercept mode");
+ else
+ message = N_("command not allowed");
+
+ /* Do auditing first (audit_failure() handles the locale itself). */
+ audit_failure(ctx, ctx->runas.argv, "%s", message);
+
+ if (def_log_denied || mailit) {
+ /* Log and mail messages should be in the sudoers locale. */
+ sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
+
+ if (!log_reject(ctx, message, def_log_denied, mailit))
+ ret = false;
+
+ /* Restore locale. */
+ sudoers_setlocale(oldlocale, NULL);
+ }
+
+ /* Inform the user of the failure (in their locale). */
+ if (inform_user) {
+ sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale);
+
+ if (ISSET(status, FLAG_NO_USER)) {
+ sudo_printf(SUDO_CONV_ERROR_MSG, _("%s is not in the sudoers "
+ "file.\n"), ctx->user.name);
+ } else if (ISSET(status, FLAG_NO_HOST)) {
+ sudo_printf(SUDO_CONV_ERROR_MSG, _("%s is not allowed to run sudo "
+ "on %s.\n"), ctx->user.name, ctx->runas.shost);
+ } else if (ISSET(status, FLAG_INTERCEPT_SETID)) {
+ sudo_printf(SUDO_CONV_ERROR_MSG, _("%s: %s\n"), getprogname(),
+ _("setid commands are not permitted in intercept mode"));
+ } else if (ISSET(status, FLAG_NO_CHECK)) {
+ sudo_printf(SUDO_CONV_ERROR_MSG, _("Sorry, user %s may not run "
+ "sudo on %s.\n"), ctx->user.name, ctx->runas.shost);
+ } else {
+ const struct passwd *runas_pw =
+ ctx->runas.list_pw ? ctx->runas.list_pw : ctx->runas.pw;
+ const char *cmnd1 = ctx->user.cmnd;
+ const char *cmnd2 = "";
+
+ if (ISSET(ctx->mode, MODE_CHECK)) {
+ /* For "sudo -l command" the command run is in runas.argv[1]. */
+ cmnd1 = "list ";
+ cmnd2 = ctx->runas.argv[1];
+ }
+ sudo_printf(SUDO_CONV_ERROR_MSG, _("Sorry, user %s is not allowed "
+ "to execute '%s%s%s%s' as %s%s%s on %s.\n"),
+ ctx->user.name, cmnd1, cmnd2, ctx->user.cmnd_args ? " " : "",
+ ctx->user.cmnd_args ? ctx->user.cmnd_args : "",
+ runas_pw ? runas_pw->pw_name : ctx->user.name,
+ ctx->runas.gr ? ":" : "",
+ ctx->runas.gr ? ctx->runas.gr->gr_name : "",
+ ctx->user.host);
+ }
+ if (mailit) {
+ sudo_printf(SUDO_CONV_ERROR_MSG, "%s",
+ _("This incident has been reported to the administrator.\n"));
+ }
+ sudoers_setlocale(oldlocale, NULL);
+ }
+ debug_return_bool(ret);
+}
+
+/*
+ * Log and audit that user was not allowed to run the command.
+ */
+bool
+log_failure(const struct sudoers_context *ctx, unsigned int status,
+ int cmnd_status)
+{
+ bool ret, inform_user = true;
+ debug_decl(log_failure, SUDOERS_DEBUG_LOGGING);
+
+ /* The user doesn't always get to see the log message (path info). */
+ if (!ISSET(status, FLAG_NO_USER | FLAG_NO_HOST) &&
+ ctx->runas.list_pw == NULL && def_path_info &&
+ (cmnd_status == NOT_FOUND_DOT || cmnd_status == NOT_FOUND))
+ inform_user = false;
+ ret = log_denial(ctx, status, inform_user);
+
+ if (!inform_user) {
+ const char *cmnd = ctx->user.cmnd;
+ if (ISSET(ctx->mode, MODE_CHECK))
+ cmnd = ctx->user.cmnd_list ? ctx->user.cmnd_list : ctx->runas.argv[1];
+
+ /*
+ * We'd like to not leak path info at all here, but that can
+ * *really* confuse the users. To really close the leak we'd
+ * have to say "not allowed to run foo" even when the problem
+ * is just "no foo in path" since the user can trivially set
+ * their path to just contain a single dir.
+ */
+ if (cmnd_status == NOT_FOUND)
+ sudo_warnx(U_("%s: command not found"), cmnd);
+ else if (cmnd_status == NOT_FOUND_DOT)
+ sudo_warnx(U_("ignoring \"%s\" found in '.'\nUse \"sudo ./%s\" if this is the \"%s\" you wish to run."), cmnd, cmnd, cmnd);
+ }
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Format an authentication failure message, using either
+ * authfail_message from sudoers or a locale-specific message.
+ */
+static char *
+fmt_authfail_message(unsigned int tries)
+{
+ char numbuf[STRLEN_MAX_UNSIGNED(unsigned int) + 1];
+ char *dst, *dst_end, *ret = NULL;
+ const char *src;
+ size_t len;
+ debug_decl(fmt_authfail_message, SUDOERS_DEBUG_LOGGING);
+
+ if (def_authfail_message == NULL) {
+ if (asprintf(&ret, ngettext("%u incorrect password attempt",
+ "%u incorrect password attempts", tries), tries) == -1)
+ goto oom;
+ debug_return_ptr(ret);
+ }
+
+ len = (size_t)snprintf(numbuf, sizeof(numbuf), "%u", tries);
+ if (len >= sizeof(numbuf))
+ goto overflow;
+
+ src = def_authfail_message;
+ len = strlen(src) + 1;
+ while (*src != '\0') {
+ if (src[0] == '%') {
+ switch (src[1]) {
+ case '%':
+ len--;
+ src++;
+ break;
+ case 'd':
+ len -= 2;
+ len += strlen(numbuf);
+ src++;
+ break;
+ default:
+ /* pass through as-is */
+ break;
+ }
+ }
+ src++;
+ }
+
+ if ((ret = malloc(len)) == NULL)
+ goto oom;
+ dst = ret;
+ dst_end = ret + len;
+
+ src = def_authfail_message;
+ while (*src != '\0') {
+ /* Always leave space for the terminating NUL. */
+ if (dst + 1 >= dst_end)
+ goto overflow;
+ if (src[0] == '%') {
+ switch (src[1]) {
+ case '%':
+ src++;
+ break;
+ case 'd':
+ len = strlcpy(dst, numbuf, (size_t)(dst_end - dst));
+ if (len >= (size_t)(dst_end - dst))
+ goto overflow;
+ dst += len;
+ src += 2;
+ continue;
+ default:
+ /* pass through as-is */
+ break;
+ }
+ }
+ *dst++ = *src++;
+ }
+ *dst = '\0';
+
+ debug_return_ptr(ret);
+
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_ptr(NULL);
+
+overflow:
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ free(ret);
+ errno = ERANGE;
+ debug_return_ptr(NULL);
+}
+
+/*
+ * Log and audit that user was not able to authenticate themselves.
+ */
+bool
+log_auth_failure(const struct sudoers_context *ctx, unsigned int status,
+ unsigned int tries)
+{
+ char *message = NULL;
+ int oldlocale;
+ bool ret = true;
+ bool mailit = false;
+ bool logit = true;
+ debug_decl(log_auth_failure, SUDOERS_DEBUG_LOGGING);
+
+ /* Do auditing first (audit_failure() handles the locale itself). */
+ audit_failure(ctx, ctx->runas.argv, "%s", N_("authentication failure"));
+
+ /* If sudoers denied the command we'll log that separately. */
+ if (!ISSET(status, FLAG_BAD_PASSWORD|FLAG_NO_USER_INPUT))
+ logit = false;
+
+ /*
+ * Do we need to send mail?
+ * We want to avoid sending multiple messages for the same command
+ * so if we are going to send an email about the denial, that takes
+ * precedence.
+ */
+ if (ISSET(status, VALIDATE_SUCCESS)) {
+ /* Command allowed, auth failed; do we need to send mail? */
+ if (def_mail_badpass || def_mail_always)
+ mailit = true;
+ if (!def_log_denied)
+ logit = false;
+ } else {
+ /* Command denied, auth failed; make sure we don't send mail twice. */
+ if (def_mail_badpass && !should_mail(ctx, status))
+ mailit = true;
+ /* Don't log the bad password message, we'll log a denial instead. */
+ logit = false;
+ }
+
+ if (logit || mailit) {
+ /* Log and mail messages should be in the sudoers locale. */
+ sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
+
+ if (ISSET(status, FLAG_BAD_PASSWORD)) {
+ message = fmt_authfail_message(tries);
+ if (message == NULL) {
+ ret = false;
+ } else {
+ ret = log_reject(ctx, message, logit, mailit);
+ free(message);
+ }
+ } else {
+ ret = log_reject(ctx, _("a password is required"), logit, mailit);
+ }
+
+ /* Restore locale. */
+ sudoers_setlocale(oldlocale, NULL);
+ }
+
+ /* Inform the user if they failed to authenticate (in their locale). */
+ sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale);
+
+ if (ISSET(status, FLAG_BAD_PASSWORD)) {
+ message = fmt_authfail_message(tries);
+ if (message == NULL) {
+ ret = false;
+ } else {
+ sudo_warnx("%s", message);
+ free(message);
+ }
+ } else {
+ sudo_warnx("%s", _("a password is required"));
+ }
+
+ sudoers_setlocale(oldlocale, NULL);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Log and potentially mail the allowed command.
+ */
+bool
+log_allowed(const struct sudoers_context *ctx, struct eventlog *evlog)
+{
+ int oldlocale;
+ int evl_flags = 0;
+ bool mailit, ret = true;
+ debug_decl(log_allowed, SUDOERS_DEBUG_LOGGING);
+
+ /* Send mail based on status. */
+ mailit = should_mail(ctx, VALIDATE_SUCCESS);
+
+ if (def_log_allowed || mailit) {
+ /* Log and mail messages should be in the sudoers locale. */
+ sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
+
+ if (mailit) {
+ SET(evl_flags, EVLOG_MAIL);
+ if (!def_log_allowed)
+ SET(evl_flags, EVLOG_MAIL_ONLY);
+ }
+ if (!eventlog_accept(evlog, evl_flags, NULL, NULL))
+ ret = false;
+
+ sudoers_setlocale(oldlocale, NULL);
+ }
+
+ debug_return_bool(ret);
+}
+
+bool
+log_exit_status(const struct sudoers_context *ctx, int status)
+{
+ struct eventlog evlog;
+ int evl_flags = 0;
+ int exit_value = 0;
+ int oldlocale;
+ struct timespec run_time;
+ char sigbuf[SIG2STR_MAX];
+ char *signal_name = NULL;
+ bool dumped_core = false;
+ bool ret = true;
+ debug_decl(log_exit_status, SUDOERS_DEBUG_LOGGING);
+
+ if (def_log_exit_status || def_mail_always) {
+ if (sudo_gettime_real(&run_time) == -1) {
+ sudo_warn("%s", U_("unable to get time of day"));
+ ret = false;
+ goto done;
+ }
+ sudo_timespecsub(&run_time, &ctx->submit_time, &run_time);
+
+ if (WIFEXITED(status)) {
+ exit_value = WEXITSTATUS(status);
+ } else if (WIFSIGNALED(status)) {
+ int signo = WTERMSIG(status);
+ if (signo <= 0 || sig2str(signo, sigbuf) == -1)
+ (void)snprintf(sigbuf, sizeof(sigbuf), "%d", signo);
+ signal_name = sigbuf;
+ exit_value = signo | 128;
+ dumped_core = WCOREDUMP(status);
+ } else {
+ sudo_warnx("invalid exit status 0x%x", status);
+ ret = false;
+ goto done;
+ }
+
+ /* Log and mail messages should be in the sudoers locale. */
+ sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
+
+ sudoers_to_eventlog(ctx, &evlog, ctx->runas.cmnd_saved,
+ ctx->runas.argv_saved, NULL, ctx->uuid_str);
+ if (def_mail_always) {
+ SET(evl_flags, EVLOG_MAIL);
+ if (!def_log_exit_status)
+ SET(evl_flags, EVLOG_MAIL_ONLY);
+ }
+ evlog.run_time = run_time;
+ evlog.exit_value = exit_value;
+ evlog.signal_name = signal_name;
+ evlog.dumped_core = dumped_core;
+ if (!eventlog_exit(&evlog, evl_flags))
+ ret = false;
+
+ sudoers_setlocale(oldlocale, NULL);
+ }
+
+done:
+ debug_return_bool(ret);
+}
+
+/*
+ * Add message to the parse error journal, which takes ownership of it.
+ * The message will be freed once the journal is processed.
+ * Returns true if message was journaled (and consumed), else false.
+ */
+static bool
+journal_parse_error(char *message)
+{
+ struct parse_error *pe;
+ debug_decl(journal_parse_error, SUDOERS_DEBUG_LOGGING);
+
+ pe = malloc(sizeof(*pe));
+ if (pe == NULL)
+ debug_return_bool(false);
+ pe->errstr = message;
+ STAILQ_INSERT_TAIL(&parse_error_list, pe, entries);
+ debug_return_bool(true);
+}
+
+/*
+ * Perform logging for log_warning()/log_warningx().
+ */
+static bool
+vlog_warning(const struct sudoers_context *ctx, unsigned int flags,
+ int errnum, const char * restrict fmt, va_list ap)
+{
+ struct eventlog evlog;
+ struct timespec now;
+ const char *errstr = NULL;
+ char *message;
+ bool ret = true;
+ int len, oldlocale;
+ int evl_flags = 0;
+ va_list ap2;
+ debug_decl(vlog_warning, SUDOERS_DEBUG_LOGGING);
+
+ /* Do auditing first (audit_failure() handles the locale itself). */
+ if (ISSET(flags, SLOG_AUDIT)) {
+ va_copy(ap2, ap);
+ vaudit_failure(ctx, ctx->runas.argv, fmt, ap2);
+ va_end(ap2);
+ }
+
+ /* Need extra copy of ap for sudo_vwarn()/sudo_vwarnx() below. */
+ va_copy(ap2, ap);
+
+ /* Log messages should be in the sudoers locale. */
+ sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
+
+ /* Expand printf-style format + args. */
+ len = vasprintf(&message, _(fmt), ap);
+ if (len == -1) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ ret = false;
+ goto done;
+ }
+
+ if (ISSET(flags, SLOG_USE_ERRNO))
+ errstr = strerror(errnum);
+ else if (ISSET(flags, SLOG_GAI_ERRNO))
+ errstr = gai_strerror(errnum);
+
+ /* Log to debug file. */
+ if (errstr != NULL) {
+ sudo_debug_printf2(NULL, NULL, 0,
+ SUDO_DEBUG_WARN|sudo_debug_subsys, "%s: %s", message, errstr);
+ } else {
+ sudo_debug_printf2(NULL, NULL, 0,
+ SUDO_DEBUG_WARN|sudo_debug_subsys, "%s", message);
+ }
+
+ if (ISSET(flags, SLOG_SEND_MAIL) || !ISSET(flags, SLOG_NO_LOG)) {
+ if (sudo_gettime_real(&now) == -1) {
+ sudo_warn("%s", U_("unable to get time of day"));
+ goto done;
+ }
+ if (ISSET(flags, SLOG_RAW_MSG))
+ SET(evl_flags, EVLOG_RAW);
+ if (ISSET(flags, SLOG_SEND_MAIL)) {
+ SET(evl_flags, EVLOG_MAIL);
+ if (ISSET(flags, SLOG_NO_LOG))
+ SET(evl_flags, EVLOG_MAIL_ONLY);
+ }
+ sudoers_to_eventlog(ctx, &evlog, ctx->runas.cmnd, ctx->runas.argv,
+ NULL, ctx->uuid_str);
+ if (!eventlog_alert(&evlog, evl_flags, &now, message, errstr))
+ ret = false;
+ if (!log_server_alert(ctx, &evlog, &now, message, errstr))
+ ret = false;
+ }
+
+ if (ISSET(flags, SLOG_PARSE_ERROR)) {
+ char *copy;
+
+ /* Journal parse error for later mailing. */
+ if (errstr != NULL) {
+ if (asprintf(&copy, U_("%s: %s"), message, errstr) == -1)
+ copy = NULL;
+ } else {
+ copy = strdup(message);
+ }
+ if (copy != NULL) {
+ /* journal_parse_error() takes ownership of copy on success. */
+ if (!journal_parse_error(copy)) {
+ free(copy);
+ ret = false;
+ }
+ }
+ }
+
+ /*
+ * Tell the user (in their locale).
+ */
+ if (!ISSET(flags, SLOG_NO_STDERR)) {
+ sudoers_setlocale(SUDOERS_LOCALE_USER, NULL);
+ if (ISSET(flags, SLOG_USE_ERRNO)) {
+ errno = errnum;
+ sudo_vwarn_nodebug(_(fmt), ap2);
+ } else if (ISSET(flags, SLOG_GAI_ERRNO)) {
+ sudo_gai_vwarn_nodebug(errnum, _(fmt), ap2);
+ } else {
+ sudo_vwarnx_nodebug(_(fmt), ap2);
+ }
+ }
+
+done:
+ va_end(ap2);
+ sudoers_setlocale(oldlocale, NULL);
+
+ debug_return_bool(ret);
+}
+
+bool
+log_warning(const struct sudoers_context *ctx, unsigned int flags,
+ const char * restrict fmt, ...)
+{
+ va_list ap;
+ bool ret;
+ debug_decl(log_warning, SUDOERS_DEBUG_LOGGING);
+
+ /* Log the error. */
+ va_start(ap, fmt);
+ ret = vlog_warning(ctx, flags|SLOG_USE_ERRNO, errno, fmt, ap);
+ va_end(ap);
+
+ debug_return_bool(ret);
+}
+
+bool
+log_warningx(const struct sudoers_context *ctx, unsigned int flags,
+ const char * restrict fmt, ...)
+{
+ va_list ap;
+ bool ret;
+ debug_decl(log_warningx, SUDOERS_DEBUG_LOGGING);
+
+ /* Log the error. */
+ va_start(ap, fmt);
+ ret = vlog_warning(ctx, flags, 0, fmt, ap);
+ va_end(ap);
+
+ debug_return_bool(ret);
+}
+
+bool
+gai_log_warning(const struct sudoers_context *ctx, unsigned int flags,
+ int errnum, const char * restrict fmt, ...)
+{
+ va_list ap;
+ bool ret;
+ debug_decl(gai_log_warning, SUDOERS_DEBUG_LOGGING);
+
+ /* Log the error. */
+ va_start(ap, fmt);
+ ret = vlog_warning(ctx, flags|SLOG_GAI_ERRNO, errnum, fmt, ap);
+ va_end(ap);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Send mail about accumulated parser errors.
+ * Frees the list of parse errors when done.
+ */
+bool
+mail_parse_errors(const struct sudoers_context *ctx)
+{
+ const int evl_flags = EVLOG_RAW;
+ struct parse_error *pe;
+ struct eventlog evlog;
+ char **errors = NULL;
+ struct timespec now;
+ bool ret = false;
+ size_t n;
+ debug_decl(mail_parse_errors, SUDOERS_DEBUG_LOGGING);
+
+ if (STAILQ_EMPTY(&parse_error_list))
+ debug_return_bool(true);
+
+ if (sudo_gettime_real(&now) == -1) {
+ sudo_warn("%s", U_("unable to get time of day"));
+ goto done;
+ }
+ sudoers_to_eventlog(ctx, &evlog, ctx->runas.cmnd, ctx->runas.argv,
+ NULL, ctx->uuid_str);
+
+ /* Convert parse_error_list to a string vector. */
+ n = 0;
+ STAILQ_FOREACH(pe, &parse_error_list, entries) {
+ n++;
+ }
+ errors = reallocarray(NULL, n + 1, sizeof(char *));
+ if (errors == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ n = 0;
+ STAILQ_FOREACH(pe, &parse_error_list, entries) {
+ errors[n++] = _(pe->errstr);
+ }
+ errors[n] = NULL;
+
+ ret = eventlog_mail(&evlog, evl_flags, &now, _("problem parsing sudoers"),
+ NULL, errors);
+
+done:
+ free(errors);
+ while ((pe = STAILQ_FIRST(&parse_error_list)) != NULL) {
+ STAILQ_REMOVE_HEAD(&parse_error_list, entries);
+ free(pe->errstr);
+ free(pe);
+ }
+ debug_return_bool(ret);
+}
+
+/*
+ * Log a parse error using log_warningx().
+ * Journals the message to be mailed after parsing is complete.
+ * Does not write the message to stderr.
+ */
+bool
+log_parse_error(const struct sudoers_context *ctx, const char *file,
+ int line, int column, const char * restrict fmt, va_list args)
+{
+ const unsigned int flags = SLOG_RAW_MSG|SLOG_NO_STDERR;
+ char *message, *tofree = NULL;
+ const char *errstr;
+ bool ret;
+ int len;
+ debug_decl(log_parse_error, SUDOERS_DEBUG_LOGGING);
+
+ if (fmt == NULL) {
+ errstr = _("syntax error");
+ } else if (strcmp(fmt, "%s") == 0) {
+ /* Optimize common case, a single string. */
+ errstr = _(va_arg(args, char *));
+ } else {
+ if (vasprintf(&tofree, _(fmt), args) == -1)
+ debug_return_bool(false);
+ errstr = tofree;
+ }
+
+ if (line > 0) {
+ ret = log_warningx(ctx, flags, N_("%s:%d:%d: %s"), file, line, column,
+ errstr);
+ } else {
+ ret = log_warningx(ctx, flags, N_("%s: %s"), file, errstr);
+ }
+
+ /* Journal parse error for later mailing. */
+ if (line > 0) {
+ len = asprintf(&message, _("%s:%d:%d: %s"), file, line, column, errstr);
+ } else {
+ len = asprintf(&message, _("%s: %s"), file, errstr);
+ }
+ if (len != -1) {
+ if (!journal_parse_error(message)) {
+ free(message);
+ ret = false;
+ }
+ } else {
+ ret = false;
+ }
+
+ free(tofree);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Determine whether we should send mail based on "status" and defaults options.
+ */
+static bool
+should_mail(const struct sudoers_context *ctx, unsigned int status)
+{
+ debug_decl(should_mail, SUDOERS_DEBUG_LOGGING);
+
+ if (!def_mailto || !def_mailerpath || access(def_mailerpath, X_OK) == -1)
+ debug_return_bool(false);
+
+ debug_return_bool(def_mail_always || ISSET(status, VALIDATE_ERROR) ||
+ (def_mail_all_cmnds && ISSET(ctx->mode, (MODE_RUN|MODE_EDIT))) ||
+ (def_mail_no_user && ISSET(status, FLAG_NO_USER)) ||
+ (def_mail_no_host && ISSET(status, FLAG_NO_HOST)) ||
+ (def_mail_no_perms && !ISSET(status, VALIDATE_SUCCESS)));
+}
+
+/*
+ * Build a struct eventlog from sudoers data.
+ * The values in the resulting eventlog struct should not be freed.
+ */
+void
+sudoers_to_eventlog(const struct sudoers_context *ctx, struct eventlog *evlog,
+ const char *cmnd, char * const runargv[], char * const runenv[],
+ const char *uuid_str)
+{
+ struct group *grp;
+ debug_decl(sudoers_to_eventlog, SUDOERS_DEBUG_LOGGING);
+
+ /* We rely on the reference held by the group cache. */
+ if ((grp = sudo_getgrgid(ctx->user.pw->pw_gid)) != NULL)
+ sudo_gr_delref(grp);
+
+ memset(evlog, 0, sizeof(*evlog));
+ evlog->iolog_file = ctx->iolog_file;
+ evlog->iolog_path = ctx->iolog_path;
+ evlog->command = cmnd ? (char *)cmnd : (runargv ? runargv[0] : NULL);
+ evlog->cwd = ctx->user.cwd;
+ if (def_runchroot != NULL && strcmp(def_runchroot, "*") != 0) {
+ evlog->runchroot = def_runchroot;
+ }
+ if (def_runcwd && strcmp(def_runcwd, "*") != 0) {
+ evlog->runcwd = def_runcwd;
+ } else if (ISSET(ctx->mode, MODE_LOGIN_SHELL) && ctx->runas.pw != NULL) {
+ evlog->runcwd = ctx->runas.pw->pw_dir;
+ } else {
+ evlog->runcwd = ctx->user.cwd;
+ }
+ evlog->rungroup = ctx->runas.gr ? ctx->runas.gr->gr_name : ctx->runas.group;
+ evlog->source = ctx->source;
+ evlog->submithost = ctx->user.host;
+ evlog->submituser = ctx->user.name;
+ if (grp != NULL)
+ evlog->submitgroup = grp->gr_name;
+ evlog->ttyname = ctx->user.ttypath;
+ evlog->runargv = (char **)runargv;
+ evlog->env_add = (char **)ctx->user.env_add;
+ evlog->runenv = (char **)runenv;
+ evlog->submitenv = (char **)ctx->user.envp;
+ evlog->submit_time = ctx->submit_time;
+ evlog->lines = ctx->user.lines;
+ evlog->columns = ctx->user.cols;
+ if (ctx->runas.pw != NULL) {
+ evlog->rungid = ctx->runas.pw->pw_gid;
+ evlog->runuid = ctx->runas.pw->pw_uid;
+ evlog->runuser = ctx->runas.pw->pw_name;
+ } else {
+ evlog->rungid = (gid_t)-1;
+ evlog->runuid = (uid_t)-1;
+ evlog->runuser = ctx->runas.user;
+ }
+ if (uuid_str == NULL) {
+ unsigned char uuid[16];
+
+ sudo_uuid_create(uuid);
+ if (sudo_uuid_to_string(uuid, evlog->uuid_str, sizeof(evlog->uuid_str)) == NULL)
+ sudo_warnx("%s", U_("unable to generate UUID"));
+ } else {
+ strlcpy(evlog->uuid_str, uuid_str, sizeof(evlog->uuid_str));
+ }
+ if (ISSET(ctx->mode, MODE_POLICY_INTERCEPTED)) {
+ struct timespec now;
+ if (sudo_gettime_real(&now) == -1) {
+ sudo_warn("%s", U_("unable to get time of day"));
+ } else {
+ sudo_timespecsub(&now, &ctx->submit_time, &evlog->iolog_offset);
+ }
+ }
+
+ debug_return;
+}
+
+static FILE *
+sudoers_log_open(int type, const char *log_file)
+{
+ const char *omode;
+ bool uid_changed;
+ FILE *fp = NULL;
+ mode_t oldmask;
+ int fd, flags;
+ debug_decl(sudoers_log_open, SUDOERS_DEBUG_LOGGING);
+
+ switch (type) {
+ case EVLOG_SYSLOG:
+ openlog("sudo", def_syslog_pid ? LOG_PID : 0, def_syslog);
+ break;
+ case EVLOG_FILE:
+ /* Open log file as root, mode 0600 (cannot append to JSON). */
+ if (def_log_format == json) {
+ flags = O_RDWR|O_CREAT;
+ omode = "w";
+ } else {
+ flags = O_WRONLY|O_APPEND|O_CREAT;
+ omode = "a";
+ }
+ oldmask = umask(S_IRWXG|S_IRWXO);
+ uid_changed = set_perms(NULL, PERM_ROOT);
+ fd = open(log_file, flags, S_IRUSR|S_IWUSR);
+ if (uid_changed && !restore_perms()) {
+ if (fd != -1) {
+ close(fd);
+ fd = -1;
+ }
+ }
+ (void) umask(oldmask);
+ if (fd == -1 || (fp = fdopen(fd, omode)) == NULL) {
+ if (!warned) {
+ warned = true;
+ sudo_warn(U_("unable to open log file %s"), log_file);
+ }
+ if (fd != -1)
+ close(fd);
+ }
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unsupported log type %d", type);
+ break;
+ }
+
+ debug_return_ptr(fp);
+}
+
+static void
+sudoers_log_close(int type, FILE *fp)
+{
+ debug_decl(sudoers_log_close, SUDOERS_DEBUG_LOGGING);
+
+ switch (type) {
+ case EVLOG_SYSLOG:
+ break;
+ case EVLOG_FILE:
+ if (fp == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "tried to close NULL log stream");
+ break;
+ }
+ (void)fflush(fp);
+ if (ferror(fp) && !warned) {
+ warned = true;
+ sudo_warn(U_("unable to write log file %s"), def_logfile);
+ }
+ fclose(fp);
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unsupported log type %d", type);
+ break;
+ }
+
+ debug_return;
+}
+
+void
+init_eventlog_config(void)
+{
+ int logtype = 0;
+ debug_decl(init_eventlog_config, SUDOERS_DEBUG_LOGGING);
+
+ if (def_syslog)
+ logtype |= EVLOG_SYSLOG;
+ if (def_logfile)
+ logtype |= EVLOG_FILE;
+
+ eventlog_set_type(logtype);
+ eventlog_set_format(def_log_format == sudo ? EVLOG_SUDO : EVLOG_JSON);
+ eventlog_set_syslog_acceptpri(def_syslog_goodpri);
+ eventlog_set_syslog_rejectpri(def_syslog_badpri);
+ eventlog_set_syslog_alertpri(def_syslog_badpri);
+ eventlog_set_syslog_maxlen(def_syslog_maxlen);
+ eventlog_set_file_maxlen(def_loglinelen);
+ eventlog_set_mailuid(ROOT_UID);
+ eventlog_set_omit_hostname(!def_log_host);
+ eventlog_set_logpath(def_logfile);
+ eventlog_set_time_fmt(def_log_year ? "%h %e %T %Y" : "%h %e %T");
+ eventlog_set_mailerpath(def_mailerpath);
+ eventlog_set_mailerflags(def_mailerflags);
+ eventlog_set_mailfrom(def_mailfrom);
+ eventlog_set_mailto(def_mailto);
+ eventlog_set_mailsub(def_mailsub);
+ eventlog_set_open_log(sudoers_log_open);
+ eventlog_set_close_log(sudoers_log_close);
+
+ debug_return;
+}
diff --git a/plugins/sudoers/logging.h b/plugins/sudoers/logging.h
new file mode 100644
index 0000000..647fd28
--- /dev/null
+++ b/plugins/sudoers/logging.h
@@ -0,0 +1,94 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999-2005, 2009-2022
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_LOGGING_H
+#define SUDOERS_LOGGING_H
+
+#include <stdarg.h>
+
+struct sudoers_str_list;
+struct log_details {
+ struct eventlog *evlog;
+ struct sudoers_str_list *log_servers;
+ struct timespec server_timeout;
+# if defined(HAVE_OPENSSL)
+ char *ca_bundle;
+ char *cert_file;
+ char *key_file;
+# endif /* HAVE_OPENSSL */
+ bool keepalive;
+ bool verify_server;
+ bool ignore_log_errors;
+};
+
+/*
+ * Values for sudoers_setlocale()
+ */
+#define SUDOERS_LOCALE_USER 0
+#define SUDOERS_LOCALE_SUDOERS 1
+
+/* Logging types */
+#define SLOG_SYSLOG 0x01
+#define SLOG_FILE 0x02
+#define SLOG_BOTH 0x03
+
+/* Flags for log_warning()/log_warningx() */
+#define SLOG_USE_ERRNO 0x01 /* internal use only */
+#define SLOG_GAI_ERRNO 0x02 /* internal use only */
+#define SLOG_RAW_MSG 0x04 /* do not format msg before logging */
+#define SLOG_SEND_MAIL 0x08 /* log via mail */
+#define SLOG_NO_STDERR 0x10 /* do not log via stderr */
+#define SLOG_NO_LOG 0x20 /* do not log via file or syslog */
+#define SLOG_AUDIT 0x40 /* send message to audit as well */
+#define SLOG_PARSE_ERROR 0x80 /* format as a parse error */
+
+struct sudoers_context;
+typedef bool (*sudoers_logger_t)(const struct sudoers_context *ctx, const char *file, int line, int column, const char * restrict fmt, va_list args);
+
+/* XXX - needed for auditing */
+extern char *audit_msg;
+
+union sudo_defs_val;
+struct sudo_plugin_event;
+struct log_details;
+
+bool sudoers_warn_setlocale(bool restore, int *cookie);
+bool sudoers_setlocale(int locale_type, int *prev_locale);
+int sudoers_getlocale(void);
+int audit_failure(const struct sudoers_context *ctx, char *const argv[], char const * restrict const fmt, ...) sudo_printflike(3, 4);
+int vaudit_failure(const struct sudoers_context *ctx, char *const argv[], char const * restrict const fmt, va_list ap) sudo_printflike(3, 0);
+bool log_allowed(const struct sudoers_context *ctx, struct eventlog *evlog);
+bool log_exit_status(const struct sudoers_context *ctx, int exit_status);
+bool log_auth_failure(const struct sudoers_context *ctx, unsigned int status, unsigned int tries);
+bool log_denial(const struct sudoers_context *ctx, unsigned int status, bool inform_user);
+bool log_failure(const struct sudoers_context *ctx, unsigned int status, int flags);
+bool log_server_alert(const struct sudoers_context *ctx, struct eventlog *evlog, struct timespec *now, const char *message, const char *errstr);
+bool log_server_reject(const struct sudoers_context *ctx, struct eventlog *evlog, const char *message);
+bool log_warning(const struct sudoers_context *ctx, unsigned int flags, const char * restrict fmt, ...) sudo_printflike(3, 4);
+bool log_warningx(const struct sudoers_context *ctx, unsigned int flags, const char * restrict fmt, ...) sudo_printflike(3, 4);
+bool gai_log_warning(const struct sudoers_context *ctx, unsigned int flags, int errnum, const char * restrict fmt, ...) sudo_printflike(4, 5);
+bool sudoers_initlocale(const char *ulocale, const char *slocale);
+bool sudoers_locale_callback(struct sudoers_context *ctx, const char *file, int line, int column, const union sudo_defs_val *sd_un, int op);
+void sudoers_to_eventlog(const struct sudoers_context *ctx, struct eventlog *evlog, const char *cmnd, char * const runargv[], char *const runenv[], const char *uuid_str);
+void init_eventlog_config(void);
+bool init_log_details(struct log_details *details, struct eventlog *evlog);
+bool log_parse_error(const struct sudoers_context *ctx, const char *file, int line, int column, const char * restrict fmt, va_list ap) sudo_printf0like(5, 0);
+bool mail_parse_errors(const struct sudoers_context *ctx);
+
+#endif /* SUDOERS_LOGGING_H */
diff --git a/plugins/sudoers/lookup.c b/plugins/sudoers/lookup.c
new file mode 100644
index 0000000..ffcb23c
--- /dev/null
+++ b/plugins/sudoers/lookup.c
@@ -0,0 +1,569 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2004-2005, 2007-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#include <sudoers.h>
+#include <gram.h>
+
+static int
+runas_matches_pw(struct sudoers_parse_tree *parse_tree,
+ const struct cmndspec *cs, const struct passwd *pw)
+{
+ debug_decl(runas_matches_pw, SUDOERS_DEBUG_PARSER);
+
+ if (cs->runasuserlist != NULL)
+ debug_return_int(userlist_matches(parse_tree, pw, cs->runasuserlist));
+
+ if (cs->runasgrouplist == NULL) {
+ /* No explicit runas user or group, use default. */
+ if (userpw_matches(def_runas_default, pw->pw_name, pw) == ALLOW)
+ debug_return_int(ALLOW);
+ }
+ debug_return_int(UNSPEC);
+}
+
+/*
+ * Look up the user in the sudoers parse tree for pseudo-commands like
+ * list, verify and kill.
+ */
+static unsigned int
+sudoers_lookup_pseudo(struct sudo_nss_list *snl, struct sudoers_context *ctx,
+ time_t now, sudoers_lookup_callback_fn_t callback, void *cb_data,
+ int pwflag)
+{
+ char *saved_runchroot;
+ struct passwd *root_pw = NULL;
+ struct sudo_nss *nss;
+ struct cmndspec *cs;
+ struct privilege *priv;
+ struct userspec *us;
+ struct defaults *def;
+ int nopass, match = UNSPEC;
+ unsigned int validated = 0;
+ enum def_tuple pwcheck;
+ debug_decl(sudoers_lookup_pseudo, SUDOERS_DEBUG_PARSER);
+
+ pwcheck = (pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple;
+ nopass = (pwcheck == never || pwcheck == all) ? true : false;
+
+ if (ctx->runas.list_pw != NULL) {
+ root_pw = sudo_getpwuid(ROOT_UID);
+ if (root_pw == NULL)
+ sudo_warnx(U_("unknown uid %u"), ROOT_UID);
+ } else {
+ SET(validated, FLAG_NO_CHECK);
+ }
+
+ /* Don't use chroot setting for pseudo-commands. */
+ saved_runchroot = def_runchroot;
+ def_runchroot = NULL;
+
+ TAILQ_FOREACH(nss, snl, entries) {
+ if (nss->query(ctx, nss, ctx->user.pw) == -1) {
+ /* The query function should have printed an error message. */
+ SET(validated, VALIDATE_ERROR);
+ break;
+ }
+
+ /*
+ * We have to traverse the policy forwards, not in reverse,
+ * to support the "pwcheck == all" case.
+ */
+ TAILQ_FOREACH(us, &nss->parse_tree->userspecs, entries) {
+ const int user_match = userlist_matches(nss->parse_tree,
+ ctx->user.pw, &us->users);
+ if (user_match != ALLOW) {
+ if (callback != NULL && user_match == DENY) {
+ callback(nss->parse_tree, us, user_match, NULL, UNSPEC,
+ NULL, UNSPEC, UNSPEC, UNSPEC, cb_data);
+ }
+ continue;
+ }
+ TAILQ_FOREACH(priv, &us->privileges, entries) {
+ int priv_nopass = UNSPEC;
+ const int host_match = hostlist_matches(nss->parse_tree,
+ ctx->user.pw, &priv->hostlist);
+ if (host_match != ALLOW) {
+ if (callback != NULL) {
+ callback(nss->parse_tree, us, user_match, priv,
+ host_match, NULL, UNSPEC, UNSPEC, UNSPEC, cb_data);
+ }
+ continue;
+ }
+ TAILQ_FOREACH(def, &priv->defaults, entries) {
+ if (strcmp(def->var, "authenticate") == 0) {
+ priv_nopass = !def->op;
+ break;
+ }
+ }
+ TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
+ int cmnd_match = UNSPEC;
+ int date_match = UNSPEC;
+ int runas_match = UNSPEC;
+
+ if (pwcheck == any) {
+ if (cs->tags.nopasswd == true || priv_nopass == true)
+ nopass = true;
+ } else if (pwcheck == all) {
+ if (cs->tags.nopasswd != true && priv_nopass != true)
+ nopass = false;
+ }
+
+ if (cs->notbefore != UNSPEC) {
+ date_match = now < cs->notbefore ? DENY : ALLOW;
+ }
+ if (cs->notafter != UNSPEC) {
+ date_match = now > cs->notafter ? DENY : ALLOW;
+ }
+ /*
+ * Root can list any user's privileges.
+ * A user may always list their own privileges.
+ */
+ if (ctx->user.uid == 0 || ctx->runas.list_pw == NULL ||
+ ctx->user.uid == ctx->runas.list_pw->pw_uid) {
+ cmnd_match = ALLOW;
+ runas_match = ALLOW;
+ } else if (date_match != DENY) {
+ /*
+ * To list another user's prilileges, the runas
+ * user must match the list user or root.
+ */
+ runas_match = runas_matches_pw(nss->parse_tree, cs,
+ ctx->runas.list_pw);
+ switch (runas_match) {
+ case DENY:
+ break;
+ case ALLOW:
+ /*
+ * RunAs user matches list user.
+ * Match on command "list" or ALL.
+ */
+ cmnd_match = cmnd_matches(nss->parse_tree,
+ cs->cmnd, cs->runchroot, NULL);
+ break;
+ default:
+ /*
+ * RunAs user doesn't match list user.
+ * Only allow listing if the user has
+ * "sudo ALL" for root.
+ */
+ if (root_pw != NULL &&
+ runas_matches_pw(nss->parse_tree, cs,
+ root_pw) == ALLOW) {
+ runas_match = ALLOW;
+ cmnd_match = cmnd_matches_all(nss->parse_tree,
+ cs->cmnd, cs->runchroot, NULL);
+ }
+ break;
+ }
+ }
+ if (callback != NULL) {
+ callback(nss->parse_tree, us, user_match, priv,
+ host_match, cs, date_match, runas_match,
+ cmnd_match, cb_data);
+ }
+ if (SPECIFIED(cmnd_match)) {
+ /*
+ * We take the last match but must process
+ * the entire policy for pwcheck == all.
+ */
+ match = cmnd_match;
+ }
+ }
+ }
+ }
+ if (!sudo_nss_can_continue(nss, match))
+ break;
+ }
+ if (root_pw != NULL)
+ sudo_pw_delref(root_pw);
+ if (match == ALLOW || ctx->user.uid == 0) {
+ /* User has an entry for this host. */
+ SET(validated, VALIDATE_SUCCESS);
+ } else {
+ /* No entry or user is not allowed to list other users. */
+ SET(validated, VALIDATE_FAILURE);
+ }
+ if (pwcheck == always && def_authenticate)
+ SET(validated, FLAG_CHECK_USER);
+ else if (nopass == true)
+ def_authenticate = false;
+
+ /* Restore original def_runchroot. */
+ def_runchroot = saved_runchroot;
+
+ debug_return_uint(validated);
+}
+
+static int
+sudoers_lookup_check(struct sudo_nss *nss, struct sudoers_context *ctx,
+ unsigned int *validated, struct cmnd_info *info, time_t now,
+ sudoers_lookup_callback_fn_t callback, void *cb_data,
+ struct cmndspec **matching_cs, struct defaults_list **defs)
+{
+ struct cmndspec *cs;
+ struct privilege *priv;
+ struct userspec *us;
+ struct member *matching_user;
+ debug_decl(sudoers_lookup_check, SUDOERS_DEBUG_PARSER);
+
+ memset(info, 0, sizeof(*info));
+
+ TAILQ_FOREACH_REVERSE(us, &nss->parse_tree->userspecs, userspec_list, entries) {
+ const int user_match = userlist_matches(nss->parse_tree, ctx->user.pw,
+ &us->users);
+ if (user_match != ALLOW) {
+ if (callback != NULL && user_match == DENY) {
+ callback(nss->parse_tree, us, user_match, NULL, UNSPEC, NULL,
+ UNSPEC, UNSPEC, UNSPEC, cb_data);
+ }
+ continue;
+ }
+ CLR(*validated, FLAG_NO_USER);
+ TAILQ_FOREACH_REVERSE(priv, &us->privileges, privilege_list, entries) {
+ const int host_match = hostlist_matches(nss->parse_tree,
+ ctx->user.pw, &priv->hostlist);
+ if (host_match == ALLOW) {
+ CLR(*validated, FLAG_NO_HOST);
+ } else {
+ if (callback != NULL) {
+ callback(nss->parse_tree, us, user_match, priv, host_match,
+ NULL, UNSPEC, UNSPEC, UNSPEC, cb_data);
+ }
+ continue;
+ }
+ TAILQ_FOREACH_REVERSE(cs, &priv->cmndlist, cmndspec_list, entries) {
+ int cmnd_match = UNSPEC;
+ int date_match = UNSPEC;
+ int runas_match = UNSPEC;
+
+ if (cs->notbefore != UNSPEC) {
+ date_match = now < cs->notbefore ? DENY : ALLOW;
+ }
+ if (cs->notafter != UNSPEC) {
+ date_match = now > cs->notafter ? DENY : ALLOW;
+ }
+ if (date_match != DENY) {
+ matching_user = NULL;
+ runas_match = runaslist_matches(nss->parse_tree,
+ cs->runasuserlist, cs->runasgrouplist, &matching_user,
+ NULL);
+ if (runas_match == ALLOW) {
+ cmnd_match = cmnd_matches(nss->parse_tree, cs->cmnd,
+ cs->runchroot, info);
+ }
+ }
+ if (callback != NULL) {
+ callback(nss->parse_tree, us, user_match, priv, host_match,
+ cs, date_match, runas_match, cmnd_match, cb_data);
+ }
+
+ if (SPECIFIED(cmnd_match)) {
+ /*
+ * If user is running command as themselves,
+ * set ctx->runas.pw = ctx->user.pw.
+ * XXX - hack, want more general solution
+ */
+ if (matching_user && matching_user->type == MYSELF) {
+ sudo_pw_delref(ctx->runas.pw);
+ sudo_pw_addref(ctx->user.pw);
+ ctx->runas.pw = ctx->user.pw;
+ }
+ *matching_cs = cs;
+ *defs = &priv->defaults;
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "userspec matched @ %s:%d:%d: %s",
+ us->file ? us->file : "???", us->line, us->column,
+ cmnd_match ? "allowed" : "denied");
+ debug_return_int(cmnd_match);
+ }
+ free(info->cmnd_path);
+ memset(info, 0, sizeof(*info));
+ }
+ }
+ }
+ debug_return_int(UNSPEC);
+}
+
+/*
+ * Apply cmndspec-specific settings including SELinux role/type,
+ * Solaris privs, and command tags.
+ */
+static bool
+apply_cmndspec(struct sudoers_context *ctx, struct cmndspec *cs)
+{
+ debug_decl(apply_cmndspec, SUDOERS_DEBUG_PARSER);
+
+ if (cs != NULL) {
+#ifdef HAVE_SELINUX
+ /* Set role and type if not specified on command line. */
+ if (ctx->runas.role == NULL) {
+ if (cs->role != NULL) {
+ ctx->runas.role = strdup(cs->role);
+ if (ctx->runas.role == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ } else {
+ ctx->runas.role = def_role;
+ def_role = NULL;
+ }
+ if (ctx->runas.role != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "ctx->runas.role -> %s", ctx->runas.role);
+ }
+ }
+ if (ctx->runas.type == NULL) {
+ if (cs->type != NULL) {
+ ctx->runas.type = strdup(cs->type);
+ if (ctx->runas.type == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ } else {
+ ctx->runas.type = def_type;
+ def_type = NULL;
+ }
+ if (ctx->runas.type != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "ctx->runas.type -> %s", ctx->runas.type);
+ }
+ }
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_APPARMOR
+ /* Set AppArmor profile, if specified */
+ if (cs->apparmor_profile != NULL) {
+ ctx->runas.apparmor_profile = strdup(cs->apparmor_profile);
+ if (ctx->runas.apparmor_profile == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ } else {
+ ctx->runas.apparmor_profile = def_apparmor_profile;
+ def_apparmor_profile = NULL;
+ }
+ if (ctx->runas.apparmor_profile != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "ctx->runas.apparmor_profile -> %s", ctx->runas.apparmor_profile);
+ }
+#endif
+#ifdef HAVE_PRIV_SET
+ /* Set Solaris privilege sets */
+ if (ctx->runas.privs == NULL) {
+ if (cs->privs != NULL) {
+ ctx->runas.privs = strdup(cs->privs);
+ if (ctx->runas.privs == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ } else {
+ ctx->runas.privs = def_privs;
+ def_privs = NULL;
+ }
+ if (ctx->runas.privs != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "ctx->runas.privs -> %s", ctx->runas.privs);
+ }
+ }
+ if (ctx->runas.limitprivs == NULL) {
+ if (cs->limitprivs != NULL) {
+ ctx->runas.limitprivs = strdup(cs->limitprivs);
+ if (ctx->runas.limitprivs == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ } else {
+ ctx->runas.limitprivs = def_limitprivs;
+ def_limitprivs = NULL;
+ }
+ if (ctx->runas.limitprivs != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "ctx->runas.limitprivs -> %s", ctx->runas.limitprivs);
+ }
+ }
+#endif /* HAVE_PRIV_SET */
+ if (cs->timeout > 0) {
+ def_command_timeout = cs->timeout;
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "def_command_timeout -> %d", def_command_timeout);
+ }
+ if (cs->runcwd != NULL) {
+ free(def_runcwd);
+ def_runcwd = strdup(cs->runcwd);
+ if (def_runcwd == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "def_runcwd -> %s", def_runcwd);
+ }
+ if (cs->runchroot != NULL) {
+ free(def_runchroot);
+ def_runchroot = strdup(cs->runchroot);
+ if (def_runchroot == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "def_runchroot -> %s", def_runchroot);
+ }
+ if (cs->tags.nopasswd != UNSPEC) {
+ def_authenticate = !cs->tags.nopasswd;
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "def_authenticate -> %s", def_authenticate ? "true" : "false");
+ }
+ if (cs->tags.noexec != UNSPEC) {
+ def_noexec = cs->tags.noexec;
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "def_noexec -> %s", def_noexec ? "true" : "false");
+ }
+ if (cs->tags.intercept != UNSPEC) {
+ def_intercept = cs->tags.intercept;
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "def_intercept -> %s", def_intercept ? "true" : "false");
+ }
+ if (cs->tags.setenv != UNSPEC) {
+ def_setenv = cs->tags.setenv;
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "def_setenv -> %s", def_setenv ? "true" : "false");
+ }
+ if (cs->tags.log_input != UNSPEC) {
+ def_log_input = cs->tags.log_input;
+ cb_log_input(ctx, NULL, 0, 0, NULL, cs->tags.log_input);
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "def_log_input -> %s", def_log_input ? "true" : "false");
+ }
+ if (cs->tags.log_output != UNSPEC) {
+ def_log_output = cs->tags.log_output;
+ cb_log_output(ctx, NULL, 0, 0, NULL, cs->tags.log_output);
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "def_log_output -> %s", def_log_output ? "true" : "false");
+ }
+ if (cs->tags.send_mail != UNSPEC) {
+ if (cs->tags.send_mail) {
+ def_mail_all_cmnds = true;
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "def_mail_all_cmnds -> true");
+ } else {
+ def_mail_all_cmnds = false;
+ def_mail_always = false;
+ def_mail_no_perms = false;
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "def_mail_all_cmnds -> false, def_mail_always -> false, "
+ "def_mail_no_perms -> false");
+ }
+ }
+ if (cs->tags.follow != UNSPEC) {
+ def_sudoedit_follow = cs->tags.follow;
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "def_sudoedit_follow -> %s", def_sudoedit_follow ? "true" : "false");
+ }
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Look up the user in the sudoers parse tree and check to see if they are
+ * allowed to run the specified command on this host as the target user.
+ */
+unsigned int
+sudoers_lookup(struct sudo_nss_list *snl, struct sudoers_context *ctx,
+ time_t now, sudoers_lookup_callback_fn_t callback, void *cb_data,
+ int *cmnd_status, int pwflag)
+{
+ struct defaults_list *defs = NULL;
+ struct sudoers_parse_tree *parse_tree = NULL;
+ struct cmndspec *cs = NULL;
+ struct sudo_nss *nss;
+ struct cmnd_info info;
+ unsigned int validated = FLAG_NO_USER | FLAG_NO_HOST;
+ int m, match = UNSPEC;
+ debug_decl(sudoers_lookup, SUDOERS_DEBUG_PARSER);
+
+ /*
+ * Special case checking the "validate", "list" and "kill" pseudo-commands.
+ */
+ if (pwflag) {
+ debug_return_uint(sudoers_lookup_pseudo(snl, ctx, now, callback,
+ cb_data, pwflag));
+ }
+
+ /* Need to be runas user while stat'ing things. */
+ if (!set_perms(ctx, PERM_RUNAS))
+ debug_return_uint(validated);
+
+ /* Query each sudoers source and check the user. */
+ TAILQ_FOREACH(nss, snl, entries) {
+ if (nss->query(ctx, nss, ctx->user.pw) == -1) {
+ /* The query function should have printed an error message. */
+ SET(validated, VALIDATE_ERROR);
+ break;
+ }
+
+ m = sudoers_lookup_check(nss, ctx, &validated, &info, now, callback,
+ cb_data, &cs, &defs);
+ if (SPECIFIED(m)) {
+ match = m;
+ parse_tree = nss->parse_tree;
+ }
+
+ if (!sudo_nss_can_continue(nss, m))
+ break;
+ }
+ if (SPECIFIED(match)) {
+ if (info.cmnd_path != NULL) {
+ /* Update cmnd, cmnd_stat, cmnd_status from matching entry. */
+ free(ctx->user.cmnd);
+ ctx->user.cmnd = info.cmnd_path;
+ if (ctx->user.cmnd_stat != NULL)
+ *ctx->user.cmnd_stat = info.cmnd_stat;
+ *cmnd_status = info.status;
+ }
+ if (defs != NULL)
+ (void)update_defaults(ctx, parse_tree, defs, SETDEF_GENERIC, false);
+ if (!apply_cmndspec(ctx, cs))
+ SET(validated, VALIDATE_ERROR);
+ else if (match == ALLOW)
+ SET(validated, VALIDATE_SUCCESS);
+ else
+ SET(validated, VALIDATE_FAILURE);
+ }
+ if (!restore_perms())
+ SET(validated, VALIDATE_ERROR);
+ debug_return_uint(validated);
+}
diff --git a/plugins/sudoers/match.c b/plugins/sudoers/match.c
new file mode 100644
index 0000000..30a4b10
--- /dev/null
+++ b/plugins/sudoers/match.c
@@ -0,0 +1,812 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2007-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#ifdef HAVE_SYS_SYSTEMINFO_H
+# include <sys/systeminfo.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <unistd.h>
+#ifdef HAVE_NETGROUP_H
+# include <netgroup.h>
+#else
+# include <netdb.h>
+#endif /* HAVE_NETGROUP_H */
+#include <dirent.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#ifdef HAVE_FNMATCH
+# include <fnmatch.h>
+#else
+# include <compat/fnmatch.h>
+#endif /* HAVE_FNMATCH */
+
+#include <sudoers.h>
+#include <gram.h>
+
+/*
+ * Check whether user described by pw matches member.
+ * Returns ALLOW, DENY or UNSPEC.
+ */
+int
+user_matches(const struct sudoers_parse_tree *parse_tree,
+ const struct passwd *pw, const struct member *m)
+{
+ const struct sudoers_context *ctx = parse_tree->ctx;
+ const char *lhost = parse_tree->lhost ? parse_tree->lhost : ctx->runas.host;
+ const char *shost = parse_tree->shost ? parse_tree->shost : ctx->runas.shost;
+ int matched = UNSPEC;
+ struct alias *a;
+ debug_decl(user_matches, SUDOERS_DEBUG_MATCH);
+
+ switch (m->type) {
+ case ALL:
+ matched = m->negated ? DENY : ALLOW;
+ break;
+ case NETGROUP:
+ if (netgr_matches(parse_tree->nss, m->name,
+ def_netgroup_tuple ? lhost : NULL,
+ def_netgroup_tuple ? shost : NULL, pw->pw_name) == ALLOW)
+ matched = m->negated ? DENY : ALLOW;
+ break;
+ case USERGROUP:
+ if (usergr_matches(m->name, pw->pw_name, pw) == ALLOW)
+ matched = m->negated ? DENY : ALLOW;
+ break;
+ case ALIAS:
+ if ((a = alias_get(parse_tree, m->name, USERALIAS)) != NULL) {
+ /* XXX */
+ const int rc = userlist_matches(parse_tree, pw, &a->members);
+ if (SPECIFIED(rc)) {
+ if (m->negated) {
+ matched = rc == ALLOW ? DENY : ALLOW;
+ } else {
+ matched = rc;
+ }
+ }
+ alias_put(a);
+ break;
+ }
+ FALLTHROUGH;
+ case WORD:
+ if (userpw_matches(m->name, pw->pw_name, pw) == ALLOW)
+ matched = m->negated ? DENY : ALLOW;
+ break;
+ }
+ debug_return_int(matched);
+}
+
+/*
+ * Check for user described by pw in a list of members.
+ * Returns ALLOW, DENY or UNSPEC.
+ */
+int
+userlist_matches(const struct sudoers_parse_tree *parse_tree,
+ const struct passwd *pw, const struct member_list *list)
+{
+ struct member *m;
+ int matched = UNSPEC;
+ debug_decl(userlist_matches, SUDOERS_DEBUG_MATCH);
+
+ TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
+ matched = user_matches(parse_tree, pw, m);
+ if (SPECIFIED(matched))
+ break;
+ }
+ debug_return_int(matched);
+}
+
+struct gid_list *
+runas_getgroups(const struct sudoers_context *ctx)
+{
+ const struct passwd *pw;
+ debug_decl(runas_getgroups, SUDOERS_DEBUG_MATCH);
+
+ if (def_preserve_groups) {
+ sudo_gidlist_addref(ctx->user.gid_list);
+ debug_return_ptr(ctx->user.gid_list);
+ }
+
+ /* Only use results from a group db query, not the front end. */
+ pw = ctx->runas.pw ? ctx->runas.pw : ctx->user.pw;
+ debug_return_ptr(sudo_get_gidlist(pw, ENTRY_TYPE_QUERIED));
+}
+
+/*
+ * Check whether the requested runas user matches user_list, the
+ * user portion of a sudoers runaslist. If user_list is NULL, a
+ * list containing runas_default is used.
+ * Returns ALLOW, DENY or UNSPEC.
+ */
+static int
+runas_userlist_matches(const struct sudoers_parse_tree *parse_tree,
+ const struct member_list *user_list, struct member **matching_user)
+{
+ const struct sudoers_context *ctx = parse_tree->ctx;
+ const char *lhost = parse_tree->lhost ? parse_tree->lhost : ctx->runas.host;
+ const char *shost = parse_tree->shost ? parse_tree->shost : ctx->runas.shost;
+ int user_matched = UNSPEC;
+ struct member *m;
+ struct alias *a;
+ debug_decl(runas_userlist_matches, SUDOERS_DEBUG_MATCH);
+
+ TAILQ_FOREACH_REVERSE(m, user_list, member_list, entries) {
+ switch (m->type) {
+ case ALL:
+ user_matched = m->negated ? DENY : ALLOW;
+ break;
+ case NETGROUP:
+ if (netgr_matches(parse_tree->nss, m->name,
+ def_netgroup_tuple ? lhost : NULL,
+ def_netgroup_tuple ? shost : NULL,
+ ctx->runas.pw->pw_name) == ALLOW)
+ user_matched = m->negated ? DENY : ALLOW;
+ break;
+ case USERGROUP:
+ if (usergr_matches(m->name, ctx->runas.pw->pw_name, ctx->runas.pw) == ALLOW)
+ user_matched = m->negated ? DENY : ALLOW;
+ break;
+ case ALIAS:
+ a = alias_get(parse_tree, m->name, RUNASALIAS);
+ if (a != NULL) {
+ const int rc = runas_userlist_matches(parse_tree,
+ &a->members, matching_user);
+ if (SPECIFIED(rc)) {
+ if (m->negated) {
+ user_matched = rc == ALLOW ? DENY : ALLOW;
+ } else {
+ user_matched = rc;
+ }
+ }
+ alias_put(a);
+ break;
+ }
+ FALLTHROUGH;
+ case WORD:
+ if (userpw_matches(m->name, ctx->runas.pw->pw_name, ctx->runas.pw) == ALLOW)
+ user_matched = m->negated ? DENY : ALLOW;
+ break;
+ case MYSELF:
+ /*
+ * Only match a rule with an empty runas user if a group
+ * was specified on the command line without a user _or_
+ * the user specified their own name on the command line.
+ */
+ if ((!ISSET(ctx->settings.flags, RUNAS_USER_SPECIFIED) &&
+ ISSET(ctx->settings.flags, RUNAS_GROUP_SPECIFIED)) ||
+ strcmp(ctx->user.name, ctx->runas.pw->pw_name) == 0)
+ user_matched = m->negated ? DENY : ALLOW;
+ break;
+ }
+ if (SPECIFIED(user_matched)) {
+ if (matching_user != NULL && m->type != ALIAS)
+ *matching_user = m;
+ break;
+ }
+ }
+ debug_return_int(user_matched);
+}
+
+/*
+ * Check whether the requested runas group matches group_list, the
+ * group portion of a sudoers runaslist, or the runas user's groups.
+ * Returns ALLOW, DENY or UNSPEC.
+ */
+static int
+runas_grouplist_matches(const struct sudoers_parse_tree *parse_tree,
+ const struct member_list *group_list, struct member **matching_group)
+{
+ const struct sudoers_context *ctx = parse_tree->ctx;
+ int group_matched = UNSPEC;
+ struct member *m;
+ struct alias *a;
+ debug_decl(runas_grouplist_matches, SUDOERS_DEBUG_MATCH);
+
+ if (group_list != NULL) {
+ TAILQ_FOREACH_REVERSE(m, group_list, member_list, entries) {
+ switch (m->type) {
+ case ALL:
+ group_matched = m->negated ? DENY : ALLOW;
+ break;
+ case ALIAS:
+ a = alias_get(parse_tree, m->name, RUNASALIAS);
+ if (a != NULL) {
+ const int rc = runas_grouplist_matches(parse_tree,
+ &a->members, matching_group);
+ if (SPECIFIED(rc)) {
+ if (m->negated) {
+ group_matched = rc == ALLOW ? DENY : ALLOW;
+ } else {
+ group_matched = rc;
+ }
+ }
+ alias_put(a);
+ break;
+ }
+ FALLTHROUGH;
+ case WORD:
+ if (group_matches(m->name, ctx->runas.gr) == ALLOW)
+ group_matched = m->negated ? DENY : ALLOW;
+ break;
+ }
+ if (SPECIFIED(group_matched)) {
+ if (matching_group != NULL && m->type != ALIAS)
+ *matching_group = m;
+ break;
+ }
+ }
+ }
+ if (!SPECIFIED(group_matched)) {
+ struct gid_list *runas_groups;
+ /*
+ * The runas group was not explicitly allowed by sudoers.
+ * Check whether it is one of the target user's groups.
+ */
+ if (ctx->runas.pw->pw_gid == ctx->runas.gr->gr_gid) {
+ group_matched = ALLOW; /* runas group matches passwd db */
+ } else if ((runas_groups = runas_getgroups(ctx)) != NULL) {
+ int i;
+
+ for (i = 0; i < runas_groups->ngids; i++) {
+ if (runas_groups->gids[i] == ctx->runas.gr->gr_gid) {
+ group_matched = ALLOW; /* matched aux group vector */
+ break;
+ }
+ }
+ sudo_gidlist_delref(runas_groups);
+ }
+ }
+
+ debug_return_int(group_matched);
+}
+
+/*
+ * Check whether the sudoers runaslist, composed of user_list and
+ * group_list, matches the runas user/group requested by the user.
+ * Either (or both) user_list and group_list may be NULL.
+ * If user_list is NULL, a list containing runas_default is used.
+ * Returns ALLOW, DENY or UNSPEC.
+ */
+int
+runaslist_matches(const struct sudoers_parse_tree *parse_tree,
+ const struct member_list *user_list, const struct member_list *group_list,
+ struct member **matching_user, struct member **matching_group)
+{
+ const struct sudoers_context *ctx = parse_tree->ctx;
+ struct member_list _user_list = TAILQ_HEAD_INITIALIZER(_user_list);
+ int user_matched, group_matched = UNSPEC;
+ struct member m_user;
+ debug_decl(runaslist_matches, SUDOERS_DEBUG_MATCH);
+
+ /* If no runas user listed in sudoers, use the default value. */
+ if (user_list == NULL) {
+ m_user.name = def_runas_default;
+ m_user.type = WORD;
+ m_user.negated = false;
+ TAILQ_INSERT_HEAD(&_user_list, &m_user, entries);
+ user_list = &_user_list;
+ matching_user = NULL;
+ }
+
+ user_matched = runas_userlist_matches(parse_tree, user_list, matching_user);
+ if (ISSET(ctx->settings.flags, RUNAS_GROUP_SPECIFIED)) {
+ group_matched = runas_grouplist_matches(parse_tree, group_list,
+ matching_group);
+ }
+
+ if (user_matched == DENY || group_matched == DENY)
+ debug_return_int(DENY);
+ if (user_matched == group_matched || ctx->runas.gr == NULL)
+ debug_return_int(user_matched);
+ debug_return_int(UNSPEC);
+}
+
+/*
+ * Check for lhost and shost in a list of members.
+ * Returns ALLOW, DENY or UNSPEC.
+ */
+static int
+hostlist_matches_int(const struct sudoers_parse_tree *parse_tree,
+ const struct passwd *pw, const char *lhost, const char *shost,
+ const struct member_list *list)
+{
+ struct member *m;
+ int matched = UNSPEC;
+ debug_decl(hostlist_matches, SUDOERS_DEBUG_MATCH);
+
+ TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
+ matched = host_matches(parse_tree, pw, lhost, shost, m);
+ if (SPECIFIED(matched))
+ break;
+ }
+ debug_return_int(matched);
+}
+
+/*
+ * Check for ctx->runas.host and ctx->runas.shost in a list of members.
+ * Returns ALLOW, DENY or UNSPEC.
+ */
+int
+hostlist_matches(const struct sudoers_parse_tree *parse_tree,
+ const struct passwd *pw, const struct member_list *list)
+{
+ const struct sudoers_context *ctx = parse_tree->ctx;
+ const char *lhost = parse_tree->lhost ? parse_tree->lhost : ctx->runas.host;
+ const char *shost = parse_tree->shost ? parse_tree->shost : ctx->runas.shost;
+
+ return hostlist_matches_int(parse_tree, pw, lhost, shost, list);
+}
+
+/*
+ * Check whether host or shost matches member.
+ * Returns ALLOW, DENY or UNSPEC.
+ */
+int
+host_matches(const struct sudoers_parse_tree *parse_tree,
+ const struct passwd *pw, const char *lhost, const char *shost,
+ const struct member *m)
+{
+ struct alias *a;
+ int ret = UNSPEC;
+ debug_decl(host_matches, SUDOERS_DEBUG_MATCH);
+
+ switch (m->type) {
+ case ALL:
+ ret = m->negated ? DENY : ALLOW;
+ break;
+ case NETGROUP:
+ if (netgr_matches(parse_tree->nss, m->name, lhost, shost,
+ def_netgroup_tuple ? pw->pw_name : NULL) == ALLOW)
+ ret = m->negated ? DENY : ALLOW;
+ break;
+ case NTWKADDR:
+ if (addr_matches(m->name) == ALLOW)
+ ret = m->negated ? DENY : ALLOW;
+ break;
+ case ALIAS:
+ a = alias_get(parse_tree, m->name, HOSTALIAS);
+ if (a != NULL) {
+ /* XXX */
+ const int rc = hostlist_matches_int(parse_tree, pw, lhost,
+ shost, &a->members);
+ if (SPECIFIED(rc)) {
+ if (m->negated) {
+ ret = rc == ALLOW ? DENY : ALLOW;
+ } else {
+ ret = rc;
+ }
+ }
+ alias_put(a);
+ break;
+ }
+ FALLTHROUGH;
+ case WORD:
+ if (hostname_matches(shost, lhost, m->name) == ALLOW)
+ ret = m->negated ? DENY : ALLOW;
+ break;
+ }
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "host %s (%s) matches sudoers host %s%s: %s", lhost, shost,
+ m->negated ? "!" : "", m->name ? m->name : "ALL",
+ ret == ALLOW ? "ALLOW" : "DENY");
+ debug_return_int(ret);
+}
+
+/*
+ * Check for cmnd and args in a list of members.
+ * Returns ALLOW, DENY or UNSPEC.
+ */
+int
+cmndlist_matches(const struct sudoers_parse_tree *parse_tree,
+ const struct member_list *list, const char *runchroot,
+ struct cmnd_info *info)
+{
+ struct member *m;
+ int matched;
+ debug_decl(cmndlist_matches, SUDOERS_DEBUG_MATCH);
+
+ TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
+ matched = cmnd_matches(parse_tree, m, runchroot, info);
+ if (SPECIFIED(matched))
+ debug_return_int(matched);
+ }
+ debug_return_int(UNSPEC);
+}
+
+/*
+ * Check cmnd and args.
+ * Returns ALLOW, DENY or UNSPEC.
+ */
+int
+cmnd_matches(const struct sudoers_parse_tree *parse_tree,
+ const struct member *m, const char *runchroot, struct cmnd_info *info)
+{
+ struct alias *a;
+ struct sudo_command *c;
+ int rc, matched = UNSPEC;
+ debug_decl(cmnd_matches, SUDOERS_DEBUG_MATCH);
+
+ switch (m->type) {
+ case ALL:
+ case COMMAND:
+ c = (struct sudo_command *)m->name;
+ if (command_matches(parse_tree->ctx, c->cmnd, c->args, runchroot,
+ info, &c->digests) == ALLOW)
+ matched = m->negated ? DENY : ALLOW;
+ break;
+ case ALIAS:
+ a = alias_get(parse_tree, m->name, CMNDALIAS);
+ if (a != NULL) {
+ rc = cmndlist_matches(parse_tree, &a->members, runchroot, info);
+ if (SPECIFIED(rc)) {
+ if (m->negated) {
+ matched = rc == ALLOW ? DENY : ALLOW;
+ } else {
+ matched = rc;
+ }
+ }
+ alias_put(a);
+ }
+ break;
+ }
+ debug_return_int(matched);
+}
+
+/*
+ * Like cmnd_matches() but only matches against the ALL command.
+ * Returns ALLOW, DENY or UNSPEC.
+ */
+int
+cmnd_matches_all(const struct sudoers_parse_tree *parse_tree,
+ const struct member *m, const char *runchroot, struct cmnd_info *info)
+{
+ const bool negated = m->negated;
+ struct sudo_command *c;
+ int matched = UNSPEC;
+ struct alias *a;
+ debug_decl(cmnd_matches_all, SUDOERS_DEBUG_MATCH);
+
+ switch (m->type) {
+ case ALL:
+ c = (struct sudo_command *)m->name;
+ if (command_matches(parse_tree->ctx, c->cmnd, c->args, runchroot,
+ info, &c->digests) == ALLOW)
+ matched = negated ? DENY : ALLOW;
+ break;
+ case ALIAS:
+ a = alias_get(parse_tree, m->name, CMNDALIAS);
+ if (a != NULL) {
+ TAILQ_FOREACH_REVERSE(m, &a->members, member_list, entries) {
+ matched = cmnd_matches_all(parse_tree, m, runchroot, info);
+ if (SPECIFIED(matched)) {
+ if (negated)
+ matched = matched == ALLOW ? DENY : ALLOW;
+ break;
+ }
+ }
+ alias_put(a);
+ }
+ break;
+ }
+ debug_return_int(matched);
+}
+
+/*
+ * Returns ALLOW if the hostname matches the pattern, else DENY
+ */
+int
+hostname_matches(const char *shost, const char *lhost, const char *pattern)
+{
+ const char *host;
+ int ret;
+ debug_decl(hostname_matches, SUDOERS_DEBUG_MATCH);
+
+ host = strchr(pattern, '.') != NULL ? lhost : shost;
+ ret = DENY;
+ if (has_meta(pattern)) {
+ if (fnmatch(pattern, host, FNM_CASEFOLD) == 0)
+ ret = ALLOW;
+ } else {
+ if (strcasecmp(host, pattern) == 0)
+ ret = ALLOW;
+ }
+ debug_return_int(ret);
+}
+
+/*
+ * Returns ALLOW if the user/uid from sudoers matches the specified user/uid,
+ * else returns DENY.
+ */
+int
+userpw_matches(const char *sudoers_user, const char *user, const struct passwd *pw)
+{
+ const char *errstr;
+ int ret = DENY;
+ uid_t uid;
+ debug_decl(userpw_matches, SUDOERS_DEBUG_MATCH);
+
+ if (pw != NULL && *sudoers_user == '#') {
+ uid = (uid_t) sudo_strtoid(sudoers_user + 1, &errstr);
+ if (errstr == NULL && uid == pw->pw_uid) {
+ ret = ALLOW;
+ goto done;
+ }
+ }
+ if (def_case_insensitive_user) {
+ if (strcasecmp(sudoers_user, user) == 0)
+ ret = ALLOW;
+ } else {
+ if (strcmp(sudoers_user, user) == 0)
+ ret = ALLOW;
+ }
+done:
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "user %s matches sudoers user %s: %s",
+ user, sudoers_user, ret == ALLOW ? "ALLOW" : "DENY");
+ debug_return_int(ret);
+}
+
+/*
+ * Returns ALLOW if the group/gid from sudoers matches the specified group/gid,
+ * else returns DENY.
+ */
+int
+group_matches(const char *sudoers_group, const struct group *gr)
+{
+ const char *errstr;
+ int ret = DENY;
+ gid_t gid;
+ debug_decl(group_matches, SUDOERS_DEBUG_MATCH);
+
+ if (*sudoers_group == '#') {
+ gid = (gid_t) sudo_strtoid(sudoers_group + 1, &errstr);
+ if (errstr == NULL && gid == gr->gr_gid) {
+ ret = ALLOW;
+ goto done;
+ }
+ }
+ if (def_case_insensitive_group) {
+ if (strcasecmp(sudoers_group, gr->gr_name) == 0)
+ ret = ALLOW;
+ } else {
+ if (strcmp(sudoers_group, gr->gr_name) == 0)
+ ret = ALLOW;
+ }
+done:
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "group %s matches sudoers group %s: %s",
+ gr->gr_name, sudoers_group, ret == ALLOW ? "ALLOW" : "DENY");
+ debug_return_int(ret);
+}
+
+/*
+ * Returns true if the given user belongs to the named group,
+ * else returns false.
+ */
+int
+usergr_matches(const char *group, const char *user, const struct passwd *pw)
+{
+ struct passwd *pw0 = NULL;
+ int ret = DENY;
+ debug_decl(usergr_matches, SUDOERS_DEBUG_MATCH);
+
+ /* Make sure we have a valid usergroup, sudo style */
+ if (*group++ != '%') {
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "user group %s has no leading '%%'",
+ group);
+ goto done;
+ }
+
+ /* Query group plugin for %:name groups. */
+ if (*group == ':' && def_group_plugin) {
+ if (group_plugin_query(user, group + 1, pw) == true)
+ ret = ALLOW;
+ goto done;
+ }
+
+ /* Look up user's primary gid in the passwd file. */
+ if (pw == NULL) {
+ if ((pw0 = sudo_getpwnam(user)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "unable to find %s in passwd db",
+ user);
+ goto done;
+ }
+ pw = pw0;
+ }
+
+ if (user_in_group(pw, group)) {
+ ret = ALLOW;
+ goto done;
+ }
+
+ /* Query the group plugin for Unix groups too? */
+ if (def_group_plugin && def_always_query_group_plugin) {
+ if (group_plugin_query(user, group, pw) == true) {
+ ret = ALLOW;
+ goto done;
+ }
+ }
+
+done:
+ if (pw0 != NULL)
+ sudo_pw_delref(pw0);
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "user %s matches group %s: %s", user, group,
+ ret == ALLOW ? "ALLOW" : "DENY");
+ debug_return_int(ret);
+}
+
+#if defined(HAVE_GETDOMAINNAME) || defined(SI_SRPC_DOMAIN)
+/*
+ * Check the domain for invalid characters.
+ * Linux getdomainname(2) returns (none) if no domain is set.
+ */
+static bool
+valid_domain(const char *domain)
+{
+ const char *cp;
+ debug_decl(valid_domain, SUDOERS_DEBUG_MATCH);
+
+ for (cp = domain; *cp != '\0'; cp++) {
+ /* Check for illegal characters, Linux may use "(none)". */
+ if (*cp == '(' || *cp == ')' || *cp == ',' || *cp == ' ')
+ break;
+ }
+ if (cp == domain || *cp != '\0')
+ debug_return_bool(false);
+ debug_return_bool(true);
+}
+
+/*
+ * Get NIS-style domain name and copy from static storage or NULL if none.
+ */
+const char *
+sudo_getdomainname(void)
+{
+ static char *domain;
+ static bool initialized;
+ debug_decl(sudo_getdomainname, SUDOERS_DEBUG_MATCH);
+
+ if (!initialized) {
+ size_t host_name_max;
+ int rc;
+
+# ifdef _SC_HOST_NAME_MAX
+ host_name_max = (size_t)sysconf(_SC_HOST_NAME_MAX);
+ if (host_name_max == (size_t)-1)
+# endif
+ host_name_max = 255; /* POSIX and historic BSD */
+
+ domain = malloc(host_name_max + 1);
+ if (domain != NULL) {
+ domain[0] = '\0';
+# ifdef SI_SRPC_DOMAIN
+ rc = sysinfo(SI_SRPC_DOMAIN, domain, host_name_max + 1);
+# else
+ rc = getdomainname(domain, host_name_max + 1);
+# endif
+ if (rc == -1 || !valid_domain(domain)) {
+ /* Error or invalid domain name. */
+ free(domain);
+ domain = NULL;
+ }
+ } else {
+ /* XXX - want to pass error back to caller */
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ }
+ initialized = true;
+ }
+ debug_return_str(domain);
+}
+#else
+const char *
+sudo_getdomainname(void)
+{
+ debug_decl(sudo_getdomainname, SUDOERS_DEBUG_MATCH);
+ debug_return_ptr(NULL);
+}
+#endif /* HAVE_GETDOMAINNAME || SI_SRPC_DOMAIN */
+
+/*
+ * Returns ALLOW if "host" and "user" belong to the netgroup "netgr",
+ * else return DENY. Either of "lhost", "shost" or "user" may be NULL
+ * in which case that argument is not checked...
+ */
+int
+netgr_matches(const struct sudo_nss *nss, const char *netgr,
+ const char *lhost, const char *shost, const char *user)
+{
+ const char *domain;
+ int ret = DENY;
+ debug_decl(netgr_matches, SUDOERS_DEBUG_MATCH);
+
+ if (!def_use_netgroups) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "netgroups are disabled");
+ debug_return_int(DENY);
+ }
+
+ /* make sure we have a valid netgroup, sudo style */
+ if (*netgr++ != '+') {
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "netgroup %s has no leading '+'",
+ netgr);
+ debug_return_int(DENY);
+ }
+
+ /* get the domain name (if any) */
+ domain = sudo_getdomainname();
+
+ /* Use nss-specific innetgr() function if available. */
+ if (nss != NULL && nss->innetgr != NULL) {
+ switch (nss->innetgr(nss, netgr, lhost, user, domain)) {
+ case 0:
+ if (lhost != shost) {
+ if (nss->innetgr(nss, netgr, shost, user, domain) == 1)
+ ret = ALLOW;
+ }
+ goto done;
+ case 1:
+ ret = ALLOW;
+ goto done;
+ default:
+ /* Not supported, use system innetgr(3). */
+ break;
+ }
+ }
+
+#ifdef HAVE_INNETGR
+ /* Use system innetgr() function. */
+ if (innetgr(netgr, lhost, user, domain) == 1) {
+ ret = ALLOW;
+ } else if (lhost != shost) {
+ if (innetgr(netgr, shost, user, domain) == 1)
+ ret = ALLOW;
+ }
+#else
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "%s: no system netgroup support", __func__);
+#endif /* HAVE_INNETGR */
+
+done:
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "netgroup %s matches (%s|%s, %s, %s): %s", netgr, lhost ? lhost : "",
+ shost ? shost : "", user ? user : "", domain ? domain : "",
+ ret == ALLOW ? "ALLOW" : "DENY");
+
+ debug_return_int(ret);
+}
diff --git a/plugins/sudoers/match_addr.c b/plugins/sudoers/match_addr.c
new file mode 100644
index 0000000..c77c873
--- /dev/null
+++ b/plugins/sudoers/match_addr.c
@@ -0,0 +1,209 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2007-2015
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#ifdef NEED_RESOLV_H
+# include <arpa/nameser.h>
+# include <resolv.h>
+#endif /* NEED_RESOLV_H */
+
+#include <sudoers.h>
+#include <interfaces.h>
+
+static int
+addr_matches_if(const char *n)
+{
+ union sudo_in_addr_un addr;
+ struct interface *ifp;
+#ifdef HAVE_STRUCT_IN6_ADDR
+ size_t j;
+#endif
+ unsigned int family;
+ debug_decl(addr_matches_if, SUDOERS_DEBUG_MATCH);
+
+#ifdef HAVE_STRUCT_IN6_ADDR
+ if (inet_pton(AF_INET6, n, &addr.ip6) == 1) {
+ family = AF_INET6;
+ } else
+#endif /* HAVE_STRUCT_IN6_ADDR */
+ if (inet_pton(AF_INET, n, &addr.ip4) == 1) {
+ family = AF_INET;
+ } else {
+ debug_return_int(DENY);
+ }
+
+ SLIST_FOREACH(ifp, get_interfaces(), entries) {
+ if (ifp->family != family)
+ continue;
+ switch (family) {
+ case AF_INET:
+ if (ifp->addr.ip4.s_addr == addr.ip4.s_addr ||
+ (ifp->addr.ip4.s_addr & ifp->netmask.ip4.s_addr)
+ == addr.ip4.s_addr)
+ debug_return_int(ALLOW);
+ break;
+#ifdef HAVE_STRUCT_IN6_ADDR
+ case AF_INET6:
+ if (memcmp(ifp->addr.ip6.s6_addr, addr.ip6.s6_addr,
+ sizeof(addr.ip6.s6_addr)) == 0)
+ debug_return_int(ALLOW);
+ for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) {
+ if ((ifp->addr.ip6.s6_addr[j] & ifp->netmask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j])
+ break;
+ }
+ if (j == sizeof(addr.ip6.s6_addr))
+ debug_return_int(ALLOW);
+ break;
+#endif /* HAVE_STRUCT_IN6_ADDR */
+ }
+ }
+
+ debug_return_int(DENY);
+}
+
+static int
+addr_matches_if_netmask(const char *n, const char *m)
+{
+ size_t i;
+ union sudo_in_addr_un addr, mask;
+ struct interface *ifp;
+#ifdef HAVE_STRUCT_IN6_ADDR
+ size_t j;
+#endif
+ unsigned int family;
+ const char *errstr;
+ debug_decl(addr_matches_if, SUDOERS_DEBUG_MATCH);
+
+#ifdef HAVE_STRUCT_IN6_ADDR
+ if (inet_pton(AF_INET6, n, &addr.ip6) == 1)
+ family = AF_INET6;
+ else
+#endif /* HAVE_STRUCT_IN6_ADDR */
+ if (inet_pton(AF_INET, n, &addr.ip4) == 1) {
+ family = AF_INET;
+ } else {
+ debug_return_int(DENY);
+ }
+
+ if (family == AF_INET) {
+ if (strchr(m, '.')) {
+ if (inet_pton(AF_INET, m, &mask.ip4) != 1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "IPv4 netmask %s: %s", m, "invalid value");
+ debug_return_int(DENY);
+ }
+ } else {
+ i = (size_t)sudo_strtonum(m, 1, 32, &errstr);
+ if (errstr != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "IPv4 netmask %s: %s", m, errstr);
+ debug_return_int(DENY);
+ }
+ mask.ip4.s_addr = htonl(0xffffffffU << (32 - i));
+ }
+ addr.ip4.s_addr &= mask.ip4.s_addr;
+ }
+#ifdef HAVE_STRUCT_IN6_ADDR
+ else {
+ if (inet_pton(AF_INET6, m, &mask.ip6) != 1) {
+ j = (size_t)sudo_strtonum(m, 1, 128, &errstr);
+ if (errstr != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "IPv6 netmask %s: %s", m, errstr);
+ debug_return_int(DENY);
+ }
+ for (i = 0; i < sizeof(addr.ip6.s6_addr); i++) {
+ if (j < i * 8)
+ mask.ip6.s6_addr[i] = 0;
+ else if (i * 8 + 8 <= j)
+ mask.ip6.s6_addr[i] = 0xff;
+ else
+ mask.ip6.s6_addr[i] = 0xff00 >> (j - i * 8);
+ addr.ip6.s6_addr[i] &= mask.ip6.s6_addr[i];
+ }
+ }
+ }
+#endif /* HAVE_STRUCT_IN6_ADDR */
+
+ SLIST_FOREACH(ifp, get_interfaces(), entries) {
+ if (ifp->family != family)
+ continue;
+ switch (family) {
+ case AF_INET:
+ if ((ifp->addr.ip4.s_addr & mask.ip4.s_addr) == addr.ip4.s_addr)
+ debug_return_int(ALLOW);
+ break;
+#ifdef HAVE_STRUCT_IN6_ADDR
+ case AF_INET6:
+ for (j = 0; j < sizeof(addr.ip6.s6_addr); j++) {
+ if ((ifp->addr.ip6.s6_addr[j] & mask.ip6.s6_addr[j]) != addr.ip6.s6_addr[j])
+ break;
+ }
+ if (j == sizeof(addr.ip6.s6_addr))
+ debug_return_int(ALLOW);
+ break;
+#endif /* HAVE_STRUCT_IN6_ADDR */
+ }
+ }
+
+ debug_return_int(DENY);
+}
+
+/*
+ * Returns ALLOW if "n" is one of our ip addresses or if
+ * "n" is a network that we are on, else returns DENY.
+ */
+int
+addr_matches(char *n)
+{
+ char *m;
+ int ret;
+ debug_decl(addr_matches, SUDOERS_DEBUG_MATCH);
+
+ /* If there's an explicit netmask, use it. */
+ if ((m = strchr(n, '/'))) {
+ *m++ = '\0';
+ ret = addr_matches_if_netmask(n, m);
+ *(m - 1) = '/';
+ } else
+ ret = addr_matches_if(n);
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "IP address %s matches local host: %s", n,
+ ret == ALLOW ? "ALLOW" : "DENY");
+ debug_return_int(ret);
+}
diff --git a/plugins/sudoers/match_command.c b/plugins/sudoers/match_command.c
new file mode 100644
index 0000000..4ac56ee
--- /dev/null
+++ b/plugins/sudoers/match_command.c
@@ -0,0 +1,898 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2007-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifndef SUDOERS_NAME_MATCH
+# ifdef HAVE_GLOB
+# include <glob.h>
+# else
+# include <compat/glob.h>
+# endif /* HAVE_GLOB */
+#endif /* SUDOERS_NAME_MATCH */
+#include <dirent.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifdef HAVE_FNMATCH
+# include <fnmatch.h>
+#else
+# include <compat/fnmatch.h>
+#endif /* HAVE_FNMATCH */
+#include <regex.h>
+
+#include <sudoers.h>
+#include <gram.h>
+
+#if !defined(O_EXEC) && defined(O_PATH)
+# define O_EXEC O_PATH
+#endif
+
+static int
+regex_matches(const char *pattern, const char *str)
+{
+ const char *errstr;
+ regex_t re;
+ int ret;
+ debug_decl(regex_matches, SUDOERS_DEBUG_MATCH);
+
+ if (!sudo_regex_compile(&re, pattern, &errstr)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to compile regular expression \"%s\": %s",
+ pattern, errstr);
+ debug_return_int(DENY);
+ }
+
+ if (regexec(&re, str, 0, NULL, 0) == 0)
+ ret = ALLOW;
+ else
+ ret = DENY;
+ regfree(&re);
+
+ debug_return_int(ret);
+}
+
+static int
+command_args_match(struct sudoers_context *ctx, const char *sudoers_cmnd,
+ const char *sudoers_args)
+{
+ const char *args = ctx->user.cmnd_args ? ctx->user.cmnd_args : "";
+ int flags = 0;
+ debug_decl(command_args_match, SUDOERS_DEBUG_MATCH);
+
+ /*
+ * If no args specified in sudoers, any user args are allowed.
+ * If the empty string is specified in sudoers, no user args are allowed.
+ */
+ if (sudoers_args == NULL)
+ debug_return_int(ALLOW);
+ if (strcmp("\"\"", sudoers_args) == 0)
+ debug_return_int(ctx->user.cmnd_args ? DENY : ALLOW);
+
+ /*
+ * If args are specified in sudoers, they must match the user args.
+ * Args are matched either as a regular expression or glob pattern.
+ */
+ if (sudoers_args[0] == '^') {
+ size_t len = strlen(sudoers_args);
+ if (len > 0 && sudoers_args[len - 1] == '$')
+ debug_return_int(regex_matches(sudoers_args, args));
+ }
+
+ /* If running as sudoedit, all args are assumed to be paths. */
+ if (strcmp(sudoers_cmnd, "sudoedit") == 0)
+ flags = FNM_PATHNAME;
+ if (fnmatch(sudoers_args, args, flags) == 0)
+ debug_return_int(ALLOW);
+ debug_return_int(DENY);
+}
+
+#ifndef SUDOERS_NAME_MATCH
+/*
+ * Stat file by fd is possible, else by path.
+ * Returns true on success, else false.
+ */
+static bool
+do_stat(int fd, const char *path, struct stat *sb)
+{
+ bool ret;
+ debug_decl(do_stat, SUDOERS_DEBUG_MATCH);
+
+ if (fd != -1) {
+ ret = fstat(fd, sb) == 0;
+ } else {
+ ret = stat(path, sb) == 0;
+ }
+ debug_return_bool(ret);
+}
+#endif /* SUDOERS_NAME_MATCH */
+
+/*
+ * Check whether the fd refers to a shell script with a "#!" shebang.
+ */
+static bool
+is_script(int fd)
+{
+ bool ret = false;
+ char magic[2];
+ debug_decl(is_script, SUDOERS_DEBUG_MATCH);
+
+ if (pread(fd, magic, 2, 0) == 2) {
+ if (magic[0] == '#' && magic[1] == '!')
+ ret = true;
+ }
+ debug_return_bool(ret);
+}
+
+/*
+ * Open path if fdexec is enabled or if a digest is present.
+ * Returns false on error, else true.
+ */
+static bool
+open_cmnd(const char *path, const struct command_digest_list *digests, int *fdp)
+{
+ int fd;
+ debug_decl(open_cmnd, SUDOERS_DEBUG_MATCH);
+
+ /* Only open the file for fdexec or for digest matching. */
+ if (def_fdexec != always && TAILQ_EMPTY(digests))
+ debug_return_bool(true);
+
+ fd = open(path, O_RDONLY|O_NONBLOCK);
+# ifdef O_EXEC
+ if (fd == -1 && errno == EACCES && TAILQ_EMPTY(digests)) {
+ /* Try again with O_EXEC if no digest is specified. */
+ const int saved_errno = errno;
+ if ((fd = open(path, O_EXEC)) == -1)
+ errno = saved_errno;
+ }
+# endif
+ if (fd == -1)
+ debug_return_bool(false);
+
+ (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
+ *fdp = fd;
+ debug_return_bool(true);
+}
+
+static void
+set_cmnd_fd(struct sudoers_context *ctx, int fd, int real_root)
+{
+ debug_decl(set_cmnd_fd, SUDOERS_DEBUG_MATCH);
+
+ if (ctx->runas.execfd != -1)
+ close(ctx->runas.execfd);
+
+ if (fd != -1) {
+ if (def_fdexec == never) {
+ /* Never use fexedcve() */
+ close(fd);
+ fd = -1;
+ } else if (is_script(fd)) {
+ char fdpath[PATH_MAX];
+ struct stat sb;
+ int error, flags;
+
+ /* We can only use fexecve() on a script if /dev/fd/N exists. */
+ if (real_root != -1) {
+ /* Path relative to old root directory. */
+ (void)snprintf(fdpath, sizeof(fdpath), "dev/fd/%d", fd);
+ error = fstatat(real_root, fdpath, &sb, 0);
+ } else {
+ /* Absolute path. */
+ (void)snprintf(fdpath, sizeof(fdpath), "/dev/fd/%d", fd);
+ error = stat(fdpath, &sb);
+ }
+ if (error != 0) {
+ /* Missing /dev/fd file, can't use fexecve(). */
+ close(fd);
+ fd = -1;
+ } else {
+ /*
+ * Shell scripts go through namei twice so we can't have the
+ * close on exec flag set on the fd for fexecve(2).
+ */
+ flags = fcntl(fd, F_GETFD) & ~FD_CLOEXEC;
+ (void)fcntl(fd, F_SETFD, flags);
+ }
+ }
+ }
+
+ ctx->runas.execfd = fd;
+
+ debug_return;
+}
+
+#ifndef SUDOERS_NAME_MATCH
+/*
+ * Return true if ctx->user.cmnd names one of the inodes in dir, else false.
+ */
+static int
+command_matches_dir(struct sudoers_context *ctx, const char *sudoers_dir,
+ size_t dlen, int real_root, const struct command_digest_list *digests)
+{
+ struct stat sudoers_stat;
+ char path[PATH_MAX];
+ int len, fd = -1;
+ int ret = DENY;
+ debug_decl(command_matches_dir, SUDOERS_DEBUG_MATCH);
+
+ /* Compare the canonicalized directories, if possible. */
+ if (ctx->user.cmnd_dir != NULL) {
+ char *resolved = canon_path(sudoers_dir);
+ if (resolved != NULL) {
+ if (strcmp(resolved, ctx->user.cmnd_dir) != 0) {
+ canon_path_free(resolved);
+ goto done;
+ }
+ canon_path_free(resolved);
+ }
+ }
+
+ /* Check for command in sudoers_dir. */
+ len = snprintf(path, sizeof(path), "%s/%s", sudoers_dir, ctx->user.cmnd_base);
+ if (len < 0 || len >= ssizeof(path))
+ goto done;
+
+ /* Open the file for fdexec or for digest matching. */
+ if (!open_cmnd(path, digests, &fd))
+ goto done;
+ if (!do_stat(fd, path, &sudoers_stat))
+ goto done;
+
+ if (ctx->user.cmnd_stat == NULL ||
+ (ctx->user.cmnd_stat->st_dev == sudoers_stat.st_dev &&
+ ctx->user.cmnd_stat->st_ino == sudoers_stat.st_ino)) {
+ if (digest_matches(fd, path, digests) != ALLOW)
+ goto done;
+ free(ctx->runas.cmnd);
+ if ((ctx->runas.cmnd = strdup(path)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ ret = ALLOW;
+ goto done;
+ }
+ ret = DENY;
+
+done:
+ if (fd != -1)
+ close(fd);
+ debug_return_int(ret);
+}
+#else /* SUDOERS_NAME_MATCH */
+/*
+ * Return true if ctx->user.cmnd names one of the inodes in dir, else false.
+ */
+static int
+command_matches_dir(struct sudoers_context *ctx, const char *sudoers_dir,
+ size_t dlen, int real_root, const struct command_digest_list *digests)
+{
+ int fd = -1;
+ debug_decl(command_matches_dir, SUDOERS_DEBUG_MATCH);
+
+ /* Match ctx->user.cmnd against sudoers_dir. */
+ if (strncmp(ctx->user.cmnd, sudoers_dir, dlen) != 0 || ctx->user.cmnd[dlen] != '/')
+ goto bad;
+
+ /* Make sure ctx->user.cmnd is not in a subdir of sudoers_dir. */
+ if (strchr(ctx->user.cmnd + dlen + 1, '\0') != NULL)
+ goto bad;
+
+ /* Open the file for fdexec or for digest matching. */
+ if (!open_cmnd(ctx->user.cmnd, digests, &fd))
+ goto bad;
+ if (digest_matches(fd, ctx->user.cmnd, digests) != ALLOW)
+ goto bad;
+ set_cmnd_fd(ctx, fd, real_root);
+
+ debug_return_int(ALLOW);
+bad:
+ if (fd != -1)
+ close(fd);
+ debug_return_int(DENY);
+}
+#endif /* SUDOERS_NAME_MATCH */
+
+static int
+command_matches_all(struct sudoers_context *ctx, int real_root,
+ const struct command_digest_list *digests)
+{
+#ifndef SUDOERS_NAME_MATCH
+ struct stat sb;
+#endif
+ int fd = -1;
+ debug_decl(command_matches_all, SUDOERS_DEBUG_MATCH);
+
+ if (strchr(ctx->user.cmnd, '/') != NULL) {
+#ifndef SUDOERS_NAME_MATCH
+ /* Open the file for fdexec or for digest matching. */
+ bool open_error = !open_cmnd(ctx->user.cmnd, digests, &fd);
+
+ /* A non-existent file is not an error for "sudo ALL". */
+ if (do_stat(fd, ctx->user.cmnd, &sb)) {
+ if (open_error) {
+ /* File exists but we couldn't open it above? */
+ goto bad;
+ }
+ }
+#else
+ /* Open the file for fdexec or for digest matching. */
+ (void)open_cmnd(ctx->user.cmnd, digests, &fd);
+#endif
+ }
+
+ /* Check digest of ctx->user.cmnd since we have no sudoers_cmnd for ALL. */
+ if (digest_matches(fd, ctx->user.cmnd, digests) != ALLOW)
+ goto bad;
+ set_cmnd_fd(ctx, fd, real_root);
+
+ /* No need to set ctx->runas.cmnd for ALL. */
+ debug_return_int(ALLOW);
+bad:
+ if (fd != -1)
+ close(fd);
+ debug_return_int(DENY);
+}
+
+static int
+command_matches_fnmatch(struct sudoers_context *ctx, const char *sudoers_cmnd,
+ const char *sudoers_args, int real_root,
+ const struct command_digest_list *digests)
+{
+ const char *cmnd = ctx->user.cmnd;
+ char buf[PATH_MAX];
+ int len, fd = -1;
+#ifndef SUDOERS_NAME_MATCH
+ struct stat sb;
+#endif
+ debug_decl(command_matches_fnmatch, SUDOERS_DEBUG_MATCH);
+
+ /* A relative ctx->user.cmnd will not match, try canonicalized version. */
+ if (ctx->user.cmnd[0] != '/') {
+ if (ctx->user.cmnd_dir == NULL)
+ debug_return_int(DENY);
+ len = snprintf(buf, sizeof(buf), "%s/%s", ctx->user.cmnd_dir,
+ ctx->user.cmnd_base);
+ if (len < 0 || len >= ssizeof(buf))
+ debug_return_int(DENY);
+ cmnd = buf;
+ }
+
+ /*
+ * Return ALLOW if fnmatch(3) succeeds AND
+ * a) there are no args in sudoers OR
+ * b) there are no args on command line and none required by sudoers OR
+ * c) there are args in sudoers and on command line and they match
+ * else return DENY.
+ */
+ if (fnmatch(sudoers_cmnd, cmnd, FNM_PATHNAME) != 0)
+ debug_return_int(DENY);
+
+ if (command_args_match(ctx, sudoers_cmnd, sudoers_args) == ALLOW) {
+ /* Open the file for fdexec or for digest matching. */
+ if (!open_cmnd(cmnd, digests, &fd))
+ goto bad;
+#ifndef SUDOERS_NAME_MATCH
+ if (!do_stat(fd, cmnd, &sb))
+ goto bad;
+#endif
+ /* Check digest of cmnd since sudoers_cmnd is a pattern. */
+ if (digest_matches(fd, cmnd, digests) != ALLOW)
+ goto bad;
+ set_cmnd_fd(ctx, fd, real_root);
+
+ /* No need to set ctx->runas.cmnd since cmnd matches sudoers_cmnd */
+ debug_return_int(ALLOW);
+bad:
+ if (fd != -1)
+ close(fd);
+ }
+ debug_return_int(DENY);
+}
+
+static int
+command_matches_regex(struct sudoers_context *ctx, const char *sudoers_cmnd,
+ const char *sudoers_args, int real_root,
+ const struct command_digest_list *digests)
+{
+ const char *cmnd = ctx->user.cmnd;
+ char buf[PATH_MAX];
+ int len, fd = -1;
+#ifndef SUDOERS_NAME_MATCH
+ struct stat sb;
+#endif
+ debug_decl(command_matches_regex, SUDOERS_DEBUG_MATCH);
+
+ /* A relative ctx->user.cmnd will not match, try canonicalized version. */
+ if (ctx->user.cmnd[0] != '/') {
+ if (ctx->user.cmnd_dir == NULL)
+ debug_return_int(DENY);
+ len = snprintf(buf, sizeof(buf), "%s/%s", ctx->user.cmnd_dir,
+ ctx->user.cmnd_base);
+ if (len < 0 || len >= ssizeof(buf))
+ debug_return_int(DENY);
+ cmnd = buf;
+ }
+
+ /*
+ * Return ALLOW if sudoers_cmnd regex matches cmnd AND
+ * a) there are no args in sudoers OR
+ * b) there are no args on command line and none required by sudoers OR
+ * c) there are args in sudoers and on command line and they match
+ * else return DENY.
+ */
+ if (regex_matches(sudoers_cmnd, cmnd) != ALLOW)
+ debug_return_int(DENY);
+
+ if (command_args_match(ctx, sudoers_cmnd, sudoers_args) == ALLOW) {
+ /* Open the file for fdexec or for digest matching. */
+ if (!open_cmnd(cmnd, digests, &fd))
+ goto bad;
+#ifndef SUDOERS_NAME_MATCH
+ if (!do_stat(fd, cmnd, &sb))
+ goto bad;
+#endif
+ /* Check digest of cmnd since sudoers_cmnd is a pattern. */
+ if (digest_matches(fd, cmnd, digests) != ALLOW)
+ goto bad;
+ set_cmnd_fd(ctx, fd, real_root);
+
+ /* No need to set ctx->runas.cmnd since cmnd matches sudoers_cmnd */
+ debug_return_int(ALLOW);
+bad:
+ if (fd != -1)
+ close(fd);
+ }
+ debug_return_int(DENY);
+}
+
+#ifndef SUDOERS_NAME_MATCH
+static int
+command_matches_glob(struct sudoers_context *ctx, const char *sudoers_cmnd,
+ const char *sudoers_args, int real_root,
+ const struct command_digest_list *digests)
+{
+ struct stat sudoers_stat;
+ bool bad_digest = false;
+ char **ap, *base, *cp;
+ int fd = -1;
+ size_t dlen;
+ glob_t gl;
+ debug_decl(command_matches_glob, SUDOERS_DEBUG_MATCH);
+
+ /*
+ * First check to see if we can avoid the call to glob(3).
+ * Short circuit if there are no meta chars in the command itself
+ * and ctx->user.cmnd_base and basename(sudoers_cmnd) don't match.
+ */
+ dlen = strlen(sudoers_cmnd);
+ if (sudoers_cmnd[dlen - 1] != '/') {
+ base = sudo_basename(sudoers_cmnd);
+ if (!has_meta(base) && strcmp(ctx->user.cmnd_base, base) != 0)
+ debug_return_int(DENY);
+ }
+
+ /*
+ * Return ALLOW if we find a match in the glob(3) results AND
+ * a) there are no args in sudoers OR
+ * b) there are no args on command line and none required by sudoers OR
+ * c) there are args in sudoers and on command line and they match
+ * else return DENY.
+ */
+ if (glob(sudoers_cmnd, GLOB_NOSORT, NULL, &gl) != 0 || gl.gl_pathc == 0) {
+ globfree(&gl);
+ debug_return_int(DENY);
+ }
+
+ /* If ctx->user.cmnd is fully-qualified, check for an exact match. */
+ if (ctx->user.cmnd[0] == '/') {
+ for (ap = gl.gl_pathv; (cp = *ap) != NULL; ap++) {
+ if (fd != -1) {
+ close(fd);
+ fd = -1;
+ }
+
+ if (strcmp(cp, ctx->user.cmnd) != 0)
+ continue;
+ /* Open the file for fdexec or for digest matching. */
+ if (!open_cmnd(cp, digests, &fd))
+ continue;
+ if (!do_stat(fd, cp, &sudoers_stat))
+ continue;
+ if (ctx->user.cmnd_stat == NULL ||
+ (ctx->user.cmnd_stat->st_dev == sudoers_stat.st_dev &&
+ ctx->user.cmnd_stat->st_ino == sudoers_stat.st_ino)) {
+ /* There could be multiple matches, check digest early. */
+ if (digest_matches(fd, cp, digests) != ALLOW) {
+ bad_digest = true;
+ continue;
+ }
+ free(ctx->runas.cmnd);
+ if ((ctx->runas.cmnd = strdup(cp)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ cp = NULL; /* fail closed */
+ }
+ } else {
+ /* Paths match, but st_dev and st_ino are different. */
+ cp = NULL; /* fail closed */
+ }
+ goto done;
+ }
+ }
+ /* No exact match, compare basename, cmnd_dir, st_dev and st_ino. */
+ if (!bad_digest) {
+ for (ap = gl.gl_pathv; (cp = *ap) != NULL; ap++) {
+ if (fd != -1) {
+ close(fd);
+ fd = -1;
+ }
+
+ /* If it ends in '/' it is a directory spec. */
+ dlen = strlen(cp);
+ if (cp[dlen - 1] == '/') {
+ if (command_matches_dir(ctx, cp, dlen, real_root, digests) == ALLOW) {
+ globfree(&gl);
+ debug_return_int(ALLOW);
+ }
+ continue;
+ }
+
+ /* Only proceed if ctx->user.cmnd_base and basename(cp) match */
+ base = sudo_basename(cp);
+ if (strcmp(ctx->user.cmnd_base, base) != 0)
+ continue;
+
+ /* Compare the canonicalized parent directories, if possible. */
+ if (ctx->user.cmnd_dir != NULL) {
+ char *slash = strrchr(cp, '/');
+ if (slash != NULL) {
+ char *resolved;
+ *slash = '\0';
+ resolved = canon_path(cp);
+ *slash = '/';
+ if (resolved != NULL) {
+ /* Canonicalized directories must match. */
+ int result = strcmp(resolved, ctx->user.cmnd_dir);
+ canon_path_free(resolved);
+ if (result != 0)
+ continue;
+ }
+ }
+ }
+
+ /* Open the file for fdexec or for digest matching. */
+ if (!open_cmnd(cp, digests, &fd))
+ continue;
+ if (!do_stat(fd, cp, &sudoers_stat))
+ continue;
+ if (ctx->user.cmnd_stat == NULL ||
+ (ctx->user.cmnd_stat->st_dev == sudoers_stat.st_dev &&
+ ctx->user.cmnd_stat->st_ino == sudoers_stat.st_ino)) {
+ if (digest_matches(fd, cp, digests) != ALLOW)
+ continue;
+ free(ctx->runas.cmnd);
+ if ((ctx->runas.cmnd = strdup(cp)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ cp = NULL; /* fail closed */
+ }
+ goto done;
+ }
+ }
+ }
+done:
+ globfree(&gl);
+ if (cp != NULL) {
+ if (command_args_match(ctx, sudoers_cmnd, sudoers_args) == ALLOW) {
+ /* ctx->runas.cmnd was set above. */
+ set_cmnd_fd(ctx, fd, real_root);
+ debug_return_int(ALLOW);
+ }
+ }
+ if (fd != -1)
+ close(fd);
+ debug_return_int(DENY);
+}
+
+static int
+command_matches_normal(struct sudoers_context *ctx, const char *sudoers_cmnd,
+ const char *sudoers_args, int real_root,
+ const struct command_digest_list *digests)
+{
+ struct stat sudoers_stat;
+ const char *base;
+ size_t dlen;
+ int fd = -1;
+ debug_decl(command_matches_normal, SUDOERS_DEBUG_MATCH);
+
+ /* If it ends in '/' it is a directory spec. */
+ dlen = strlen(sudoers_cmnd);
+ if (sudoers_cmnd[dlen - 1] == '/') {
+ debug_return_int(command_matches_dir(ctx, sudoers_cmnd, dlen,
+ real_root, digests));
+ }
+
+ /* Only proceed if ctx->user.cmnd_base and basename(sudoers_cmnd) match */
+ base = sudo_basename(sudoers_cmnd);
+ if (strcmp(ctx->user.cmnd_base, base) != 0)
+ debug_return_int(DENY);
+
+ /* Compare the canonicalized parent directories, if possible. */
+ if (ctx->user.cmnd_dir != NULL) {
+ const char *slash = strrchr(sudoers_cmnd, '/');
+ if (slash != NULL) {
+ char sudoers_cmnd_dir[PATH_MAX], *resolved;
+ const size_t len = (size_t)(slash - sudoers_cmnd);
+ if (len >= sizeof(sudoers_cmnd_dir))
+ goto bad;
+ if (len != 0)
+ memcpy(sudoers_cmnd_dir, sudoers_cmnd, len);
+ sudoers_cmnd_dir[len] = '\0';
+ resolved = canon_path(sudoers_cmnd_dir);
+ if (resolved != NULL) {
+ if (strcmp(resolved, ctx->user.cmnd_dir) != 0) {
+ canon_path_free(resolved);
+ goto bad;
+ }
+ canon_path_free(resolved);
+ }
+ }
+ }
+
+ /* Open the file for fdexec or for digest matching. */
+ if (!open_cmnd(sudoers_cmnd, digests, &fd))
+ goto bad;
+
+ /*
+ * Return true if command matches AND
+ * a) there are no args in sudoers OR
+ * b) there are no args on command line and none req by sudoers OR
+ * c) there are args in sudoers and on command line and they match
+ * d) there is a digest and it matches
+ */
+ if (ctx->user.cmnd_stat != NULL && do_stat(fd, sudoers_cmnd, &sudoers_stat)) {
+ if (ctx->user.cmnd_stat->st_dev != sudoers_stat.st_dev ||
+ ctx->user.cmnd_stat->st_ino != sudoers_stat.st_ino)
+ goto bad;
+ } else {
+ /* Either user or sudoers command does not exist, match by name. */
+ if (strcmp(ctx->user.cmnd, sudoers_cmnd) != 0)
+ goto bad;
+ }
+ if (command_args_match(ctx, sudoers_cmnd, sudoers_args) != ALLOW)
+ goto bad;
+ if (digest_matches(fd, sudoers_cmnd, digests) != ALLOW) {
+ /* XXX - log functions not available but we should log very loudly */
+ goto bad;
+ }
+ free(ctx->runas.cmnd);
+ if ((ctx->runas.cmnd = strdup(sudoers_cmnd)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ set_cmnd_fd(ctx, fd, real_root);
+ debug_return_int(ALLOW);
+bad:
+ if (fd != -1)
+ close(fd);
+ debug_return_int(DENY);
+}
+#else /* SUDOERS_NAME_MATCH */
+static int
+command_matches_glob(struct sudoers_context *ctx, const char *sudoers_cmnd,
+ const char *sudoers_args, int real_root,
+ const struct command_digest_list *digests)
+{
+ return command_matches_fnmatch(ctx, sudoers_cmnd, sudoers_args, real_root,
+ digests);
+}
+
+static int
+command_matches_normal(struct sudoers_context *ctx, const char *sudoers_cmnd,
+ const char *sudoers_args, int real_root,
+ const struct command_digest_list *digests)
+{
+ size_t dlen;
+ int fd = -1;
+ debug_decl(command_matches_normal, SUDOERS_DEBUG_MATCH);
+
+ /* If it ends in '/' it is a directory spec. */
+ dlen = strlen(sudoers_cmnd);
+ if (sudoers_cmnd[dlen - 1] == '/') {
+ debug_return_int(command_matches_dir(ctx, sudoers_cmnd, dlen, real_root,
+ digests));
+ }
+
+ if (strcmp(ctx->user.cmnd, sudoers_cmnd) == 0) {
+ if (command_args_match(ctx, sudoers_cmnd, sudoers_args) == ALLOW) {
+ /* Open the file for fdexec or for digest matching. */
+ if (!open_cmnd(ctx->user.cmnd, digests, &fd))
+ goto bad;
+ if (digest_matches(fd, ctx->user.cmnd, digests) != ALLOW)
+ goto bad;
+
+ /* Successful match. */
+ free(ctx->runas.cmnd);
+ if ((ctx->runas.cmnd = strdup(sudoers_cmnd)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ goto bad;
+ }
+ set_cmnd_fd(ctx, fd, real_root);
+ debug_return_int(ALLOW);
+ }
+ }
+bad:
+ if (fd != -1)
+ close(fd);
+ debug_return_int(DENY);
+}
+#endif /* SUDOERS_NAME_MATCH */
+
+/*
+ * If path doesn't end in /, return ALLOW iff cmnd & path name the same inode;
+ * otherwise, return ALLOW if ctx->user.cmnd names one of the inodes in path.
+ * Returns DENY on failure.
+ */
+int
+command_matches(struct sudoers_context *ctx, const char *sudoers_cmnd,
+ const char *sudoers_args, const char *runchroot, struct cmnd_info *info,
+ const struct command_digest_list *digests)
+{
+ struct sudoers_pivot pivot_state = SUDOERS_PIVOT_INITIALIZER;
+ char *saved_user_cmnd = NULL;
+ struct stat saved_user_stat;
+ bool reset_cmnd = false;
+ int real_root = -1;
+ int ret = DENY;
+ debug_decl(command_matches, SUDOERS_DEBUG_MATCH);
+
+ if (ctx->runas.chroot != NULL) {
+ if (runchroot != NULL && strcmp(runchroot, "*") != 0 &&
+ strcmp(runchroot, ctx->runas.chroot) != 0) {
+ /* CHROOT mismatch */
+ goto done;
+ }
+ /* User-specified runchroot (cmnd_stat already set appropriately). */
+ runchroot = ctx->runas.chroot;
+ } else if (runchroot == NULL) {
+ /* No rule-specific runchroot, use global (cmnd_stat already set). */
+ if (def_runchroot != NULL && strcmp(def_runchroot, "*") != '\0')
+ runchroot = def_runchroot;
+ } else {
+ /* Rule-specific runchroot, must reset cmnd and cmnd_stat. */
+ reset_cmnd = true;
+ }
+
+ /* Pivot root. */
+ if (runchroot != NULL) {
+ if (!pivot_root(runchroot, &pivot_state))
+ goto done;
+ real_root = pivot_state.saved_root;
+ }
+
+ if (reset_cmnd) {
+ /* Rule-specific runchroot, set cmnd and cmnd_stat after pivot. */
+ int status;
+
+ /* Save old ctx->user.cmnd first, set_cmnd_path() will free it. */
+ saved_user_cmnd = ctx->user.cmnd;
+ ctx->user.cmnd = NULL;
+ if (ctx->user.cmnd_stat != NULL)
+ saved_user_stat = *ctx->user.cmnd_stat;
+ status = set_cmnd_path(ctx, NULL);
+ if (status != FOUND) {
+ ctx->user.cmnd = saved_user_cmnd;
+ saved_user_cmnd = NULL;
+ }
+ if (info != NULL)
+ info->status = status;
+ }
+
+ if (sudoers_cmnd == NULL) {
+ sudoers_cmnd = "ALL";
+ ret = command_matches_all(ctx, real_root, digests);
+ goto done;
+ }
+
+ /* Check for regular expressions first. */
+ if (sudoers_cmnd[0] == '^') {
+ ret = command_matches_regex(ctx, sudoers_cmnd, sudoers_args, real_root,
+ digests);
+ goto done;
+ }
+
+ /* Check for pseudo-commands */
+ if (sudoers_cmnd[0] != '/') {
+ /*
+ * Return true if sudoers_cmnd and cmnd match a pseudo-command AND
+ * a) there are no args in sudoers OR
+ * b) there are no args on command line and none req by sudoers OR
+ * c) there are args in sudoers and on command line and they match
+ */
+ if (strcmp(sudoers_cmnd, "list") == 0 ||
+ strcmp(sudoers_cmnd, "sudoedit") == 0) {
+ if (strcmp(ctx->user.cmnd, sudoers_cmnd) == 0 &&
+ command_args_match(ctx, sudoers_cmnd, sudoers_args) == ALLOW) {
+ /* No need to set ctx->user.cmnd since cmnd == sudoers_cmnd */
+ ret = ALLOW;
+ }
+ }
+ goto done;
+ }
+
+ if (has_meta(sudoers_cmnd)) {
+ /*
+ * If sudoers_cmnd has meta characters in it, we need to
+ * use glob(3) and/or fnmatch(3) to do the matching.
+ */
+ if (def_fast_glob) {
+ ret = command_matches_fnmatch(ctx, sudoers_cmnd, sudoers_args,
+ real_root, digests);
+ } else {
+ ret = command_matches_glob(ctx, sudoers_cmnd, sudoers_args,
+ real_root, digests);
+ }
+ } else {
+ ret = command_matches_normal(ctx, sudoers_cmnd, sudoers_args,
+ real_root, digests);
+ }
+done:
+ /* Restore root. */
+ if (runchroot != NULL)
+ (void)unpivot_root(&pivot_state);
+
+ /* Restore ctx->user.cmnd and ctx->user.cmnd_stat. */
+ if (saved_user_cmnd != NULL) {
+ if (info != NULL) {
+ free(info->cmnd_path);
+ info->cmnd_path = ctx->user.cmnd;
+ if (ctx->user.cmnd_stat != NULL)
+ info->cmnd_stat = *ctx->user.cmnd_stat;
+ } else {
+ free(ctx->user.cmnd);
+ }
+ ctx->user.cmnd = saved_user_cmnd;
+ if (ctx->user.cmnd_stat != NULL)
+ *ctx->user.cmnd_stat = saved_user_stat;
+ }
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "user command \"%s%s%s\" matches sudoers command \"%s%s%s\"%s%s: %s",
+ ctx->user.cmnd, ctx->user.cmnd_args ? " " : "",
+ ctx->user.cmnd_args ? ctx->user.cmnd_args : "", sudoers_cmnd,
+ sudoers_args ? " " : "", sudoers_args ? sudoers_args : "",
+ runchroot ? ", chroot " : "", runchroot ? runchroot : "",
+ ret == ALLOW ? "ALLOW" : "DENY");
+ debug_return_int(ret);
+}
diff --git a/plugins/sudoers/match_digest.c b/plugins/sudoers/match_digest.c
new file mode 100644
index 0000000..09ea435
--- /dev/null
+++ b/plugins/sudoers/match_digest.c
@@ -0,0 +1,134 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2007-2020
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sudoers.h>
+#include <sudo_digest.h>
+#include <gram.h>
+
+int
+digest_matches(int fd, const char *path,
+ const struct command_digest_list *digests)
+{
+ unsigned int digest_type = SUDO_DIGEST_INVALID;
+ unsigned char *file_digest = NULL;
+ unsigned char *sudoers_digest = NULL;
+ struct command_digest *digest;
+ size_t digest_len = (size_t)-1;
+ int matched = DENY;
+ int fd2 = -1;
+ debug_decl(digest_matches, SUDOERS_DEBUG_MATCH);
+
+ if (TAILQ_EMPTY(digests)) {
+ /* No digest, no problem. */
+ debug_return_int(ALLOW);
+ }
+
+ if (fd == -1) {
+ fd2 = open(path, O_RDONLY|O_NONBLOCK);
+ if (fd2 == -1) {
+ /* No file, no match. */
+ goto done;
+ }
+ fd = fd2;
+ }
+
+ TAILQ_FOREACH(digest, digests, entries) {
+ /* Compute file digest if needed. */
+ if (digest->digest_type != digest_type) {
+ free(file_digest);
+ file_digest = sudo_filedigest(fd, path, digest->digest_type,
+ &digest_len);
+ if (lseek(fd, (off_t)0, SEEK_SET) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "unable to rewind digest fd");
+ }
+ digest_type = digest->digest_type;
+ }
+ if (file_digest == NULL) {
+ /* Warning (if any) printed by sudo_filedigest() */
+ goto done;
+ }
+
+ /* Convert the command digest from ascii to binary. */
+ if ((sudoers_digest = malloc(digest_len)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ if (strlen(digest->digest_str) == digest_len * 2) {
+ /* Convert ascii hex to binary. */
+ size_t i;
+ for (i = 0; i < digest_len; i++) {
+ const int h = sudo_hexchar(&digest->digest_str[2 * i]);
+ if (h == -1)
+ goto bad_format;
+ sudoers_digest[i] = (unsigned char)h;
+ }
+ } else {
+ /* Convert base64 to binary. */
+ size_t len = base64_decode(digest->digest_str, sudoers_digest, digest_len);
+ if (len == (size_t)-1)
+ goto bad_format;
+ if (len != digest_len) {
+ sudo_warnx(
+ U_("digest for %s (%s) bad length %zu, expected %zu"),
+ path, digest->digest_str, len, digest_len);
+ goto done;
+ }
+ }
+ if (memcmp(file_digest, sudoers_digest, digest_len) == 0) {
+ matched = ALLOW;
+ break;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_DIAG|SUDO_DEBUG_LINENO,
+ "%s digest mismatch for %s, expecting %s",
+ digest_type_to_name(digest->digest_type), path, digest->digest_str);
+ free(sudoers_digest);
+ sudoers_digest = NULL;
+ }
+ goto done;
+
+bad_format:
+ sudo_warnx(U_("digest for %s (%s) is not in %s form"), path,
+ digest->digest_str, digest_type_to_name(digest->digest_type));
+done:
+ if (fd2 != -1)
+ close(fd2);
+ free(sudoers_digest);
+ free(file_digest);
+ debug_return_int(matched);
+}
diff --git a/plugins/sudoers/mkdefaults b/plugins/sudoers/mkdefaults
new file mode 100755
index 0000000..89ddfb9
--- /dev/null
+++ b/plugins/sudoers/mkdefaults
@@ -0,0 +1,163 @@
+#!/bin/sh
+#
+# Generate sudo_defs_table and associated defines
+#
+# Input should be formatted thusly:
+#
+# var_name
+# TYPE
+# description (or NULL)
+# array of struct def_values if TYPE == T_TUPLE [optional]
+# *callback [optional]
+
+# Deal with optional -o (output) argument
+if [ "$1" = "-o" ]; then
+ if [ $# -lt 2 ]; then
+ echo "usage: $0 [-o output] [input_file ...]" 1>&2
+ exit 1
+ fi
+ OUTFILE="$2"
+ shift 2
+else
+ OUTFILE=def_data
+fi
+if [ $# -eq 0 ]; then
+ set -- def_data.in
+fi
+
+${AWK-awk} -v outfile=$OUTFILE '
+BEGIN {
+ tuple_values[0] = "never"
+ tuple_keys["never"] = 0
+ ntuples = 1
+ header = outfile ".h"
+ cfile = outfile ".c"
+
+ type_map["T_INT"] = "ival"
+ type_map["T_UINT"] = "uival"
+ type_map["T_STR"] = "str"
+ type_map["T_FLAG"] = "flag"
+ type_map["T_MODE"] = "mode"
+ type_map["T_LIST"] = "list"
+ type_map["T_LOGFAC"] = "ival"
+ type_map["T_LOGPRI"] = "ival"
+ type_map["T_TUPLE"] = "tuple"
+ type_map["T_TIMESPEC"] = "tspec"
+ type_map["T_TIMEOUT"] = "ival"
+ type_map["T_RLIMIT"] = "str"
+ type_map["T_PLUGIN"] = "list"
+}
+{
+ sub(/#.*/, "", $0)
+ if (/^[ \t]*$/) next
+ if (/^[a-zA-Z]/) {
+ # Store previous record and begin new one
+ if (var)
+ records[count++] = sprintf("%s\n%s\n%s\n%s\n%s\n", var, type, desc, values, callback)
+ var = $1
+ type = ""
+ desc = ""
+ values = ""
+ callback = ""
+ state = 0
+ } else {
+ state++
+ # Strip leading/trailing whitespace
+ gsub(/^[ \t]+|[ \t]+$/, "")
+ if (state == 1) {
+ # type
+ type = $1
+ } else if (state == 2) {
+ # description
+ if ($0 == "NULL") {
+ desc = "NULL"
+ } else {
+ # Strip leading and trailing double quote and escape the rest
+ gsub(/^"|"$/, "")
+ gsub(/"/, "\\\"")
+ desc = sprintf("N_(\"%s\")", $0)
+ }
+ } else if (state == 3 || state == 4) {
+ if (/^\*/) {
+ callback = substr($0, 2)
+ } else {
+ if (type ~ /^T_TUPLE/) {
+ values = $0
+ # Add to tuple_values as necessary
+ n = split(values, vals)
+ for (i = 1; i <= n; i++) {
+ if (!(vals[i] in tuple_keys)) {
+ tuple_keys[vals[i]] = ntuples
+ tuple_values[ntuples++] = vals[i]
+ }
+ }
+ }
+ }
+ } else {
+ die("syntax error in input near line " NR)
+ }
+ }
+}
+END {
+ if (var)
+ records[count++] = sprintf("%s\n%s\n%s\n%s\n%s\n", var, type, desc, values, callback)
+
+ print "/* generated file, do not edit */\n" > header
+ print "/* generated file, do not edit */\n" > cfile
+
+ # Print out value arrays
+ for (i = 0; i < count; i++) {
+ split(records[i], fields, "\n")
+ if (fields[4]) {
+ if (fields[2] !~ /^T_TUPLE/)
+ die("Values list specified for non-tuple " records[1])
+ printf "static struct def_values def_data_%s[] = {\n", fields[1] > cfile
+ n = split(fields[4], t)
+ for (j = 1; j <= n; j++) {
+ printf " { \"%s\", %s },\n", t[j], t[j] > cfile
+ }
+ print " { NULL, 0 }," > cfile
+ print "};\n" > cfile
+ }
+ }
+
+ # Print each record
+ print "struct sudo_defs_types sudo_defs_table[] = {\n {" > cfile
+ for (i = 0; i < count; i++) {
+ print_record(records[i], i)
+ }
+ print "\tNULL, 0, NULL\n }\n};" > cfile
+
+ # Print out def_tuple
+ print "\nenum def_tuple {" > header
+ for (i = 0; i < ntuples; i++)
+ printf "%s %s", i ? ",\n" : "", tuple_values[i] > header
+ print "\n};" > header
+}
+
+function die(msg) {
+ print msg > "/dev/stderr"
+ exit 1
+}
+
+function print_record(rec, recnum) {
+ split(rec, fields, "\n")
+ type = fields[2]
+ sub(/\|.*/, "", type)
+ if (!(type in type_map))
+ die("unknown defaults type " fields[2])
+
+ # each variable gets a macro to access its value
+ defname = "I_" toupper(fields[1])
+ printf "#define %-23s %d\n", defname, recnum > header
+ printf "#define def_%-19s (sudo_defs_table[%s].sd_un.%s)\n",
+ fields[1], defname, type_map[type] > header
+
+ printf "\t\"%s\", %s,\n\t%s,\n", fields[1], fields[2], fields[3] > cfile
+ printf "\t%s,\n", fields[4] ? "def_data_" fields[1] : "NULL" > cfile
+ if (fields[5]) {
+ printf "\t%s,\n", fields[5] > cfile
+ }
+ print " }, {" > cfile
+}
+' "$@"
diff --git a/plugins/sudoers/parse.h b/plugins/sudoers/parse.h
new file mode 100644
index 0000000..0764c54
--- /dev/null
+++ b/plugins/sudoers/parse.h
@@ -0,0 +1,505 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2000, 2004, 2007-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_PARSE_H
+#define SUDOERS_PARSE_H
+
+#include <sys/stat.h>
+#include <sudo_queue.h>
+
+/* Characters that must be quoted in sudoers. */
+#define SUDOERS_QUOTED ":,=#\""
+#define SUDOERS_QUOTED_CMD ":,= \t#"
+#define SUDOERS_QUOTED_ARG ":,=#"
+
+/* Returns true if string 's' contains meta characters. */
+#define has_meta(s) (strpbrk(s, "\\?*[]") != NULL)
+
+/* Match by name, not inode, when fuzzing. */
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+# define SUDOERS_NAME_MATCH
+#endif
+
+/* Allowed by policy (rowhammer resistant). */
+#undef ALLOW
+#define ALLOW 0x52a2925 /* 0101001010100010100100100101 */
+
+/* Denied by policy (rowhammer resistant). */
+#undef DENY
+#define DENY 0xad5d6da /* 1010110101011101011011011010 */
+
+/* Neither allowed, nor denied. */
+#undef UNSPEC
+#define UNSPEC -1
+
+/* Tag implied by root access (SETENV only). */
+#undef IMPLIED
+#define IMPLIED 2
+
+/*
+ * We must explicitly check against ALLOW and DENY instead testing
+ * that the value is not UNSPEC to avoid potential ROWHAMMER issues.
+ */
+#define SPECIFIED(_v) ((_v) == ALLOW || (_v) == DENY)
+
+/*
+ * Initialize all tags to UNSPEC.
+ */
+#define TAGS_INIT(t) do { \
+ (t)->follow = UNSPEC; \
+ (t)->intercept = UNSPEC; \
+ (t)->log_input = UNSPEC; \
+ (t)->log_output = UNSPEC; \
+ (t)->noexec = UNSPEC; \
+ (t)->nopasswd = UNSPEC; \
+ (t)->send_mail = UNSPEC; \
+ (t)->setenv = UNSPEC; \
+} while (0)
+
+/*
+ * Copy any tags set in t2 into t, overriding the value in t.
+ */
+#define TAGS_MERGE(t, t2) do { \
+ if ((t2).follow != UNSPEC) \
+ (t).follow = (t2).follow; \
+ if ((t2).intercept != UNSPEC) \
+ (t).intercept = (t2).intercept; \
+ if ((t2).log_input != UNSPEC) \
+ (t).log_input = (t2).log_input; \
+ if ((t2).log_output != UNSPEC) \
+ (t).log_output = (t2).log_output; \
+ if ((t2).noexec != UNSPEC) \
+ (t).noexec = (t2).noexec; \
+ if ((t2).nopasswd != UNSPEC) \
+ (t).nopasswd = (t2).nopasswd; \
+ if ((t2).send_mail != UNSPEC) \
+ (t).send_mail = (t2).send_mail; \
+ if ((t2).setenv != UNSPEC) \
+ (t).setenv = (t2).setenv; \
+} while (0)
+
+/*
+ * Returns true if any tag are not UNSPEC, else false.
+ */
+#define TAGS_SET(t) \
+ ((t).follow != UNSPEC || (t).intercept != UNSPEC || \
+ (t).log_input != UNSPEC || (t).log_output != UNSPEC || \
+ (t).noexec != UNSPEC || (t).nopasswd != UNSPEC || \
+ (t).send_mail != UNSPEC || (t).setenv != UNSPEC)
+
+/*
+ * Returns true if the specified tag is not UNSPEC or IMPLIED, else false.
+ */
+#define TAG_SET(tt) \
+ ((tt) == true || (tt) == false)
+
+/*
+ * Returns true if any tags set in nt differ between ot and nt, else false.
+ */
+#define TAGS_CHANGED(ot, nt) \
+ ((TAG_SET((nt).follow) && (nt).follow != (ot).follow) || \
+ (TAG_SET((nt).intercept) && (nt).intercept != (ot).intercept) || \
+ (TAG_SET((nt).log_input) && (nt).log_input != (ot).log_input) || \
+ (TAG_SET((nt).log_output) && (nt).log_output != (ot).log_output) || \
+ (TAG_SET((nt).noexec) && (nt).noexec != (ot).noexec) || \
+ (TAG_SET((nt).nopasswd) && (nt).nopasswd != (ot).nopasswd) || \
+ (TAG_SET((nt).setenv) && (nt).setenv != (ot).setenv) || \
+ (TAG_SET((nt).send_mail) && (nt).send_mail != (ot).send_mail))
+
+/*
+ * Returns true if the runas user and group lists match, else false.
+ */
+#define RUNAS_CHANGED(cs1, cs2) \
+ ((cs1)->runasuserlist != (cs2)->runasuserlist || \
+ (cs1)->runasgrouplist != (cs2)->runasgrouplist)
+
+struct command_digest {
+ TAILQ_ENTRY(command_digest) entries;
+ unsigned int digest_type;
+ char *digest_str;
+};
+
+/*
+ * Tags associated with a command.
+ * Possible values: true, false, IMPLIED, UNSPEC.
+ */
+struct cmndtag {
+ signed int follow: 3;
+ signed int intercept: 3;
+ signed int log_input: 3;
+ signed int log_output: 3;
+ signed int noexec: 3;
+ signed int nopasswd: 3;
+ signed int send_mail: 3;
+ signed int setenv: 3;
+};
+
+/*
+ * Per-command option container struct.
+ */
+struct command_options {
+ time_t notbefore; /* time restriction */
+ time_t notafter; /* time restriction */
+ int timeout; /* command timeout */
+ char *runcwd; /* working directory */
+ char *runchroot; /* root directory */
+#ifdef HAVE_SELINUX
+ char *role, *type; /* SELinux role and type */
+#endif
+#ifdef HAVE_APPARMOR
+ char *apparmor_profile; /* AppArmor profile */
+#endif
+#ifdef HAVE_PRIV_SET
+ char *privs, *limitprivs; /* Solaris privilege sets */
+#endif
+};
+
+/*
+ * The parsed sudoers file is stored as a collection of linked lists,
+ * modelled after the yacc grammar.
+ *
+ * Other than the alias struct, which is stored in a red-black tree,
+ * the data structure used is a doubly-linked tail queue. While sudoers
+ * is being parsed, a headless tail queue is used where the first entry
+ * acts as the head and the prev pointer does double duty as the tail pointer.
+ * This makes it possible to trivially append sub-lists. In addition, the prev
+ * pointer is always valid (even if it points to itself). Unlike a circle
+ * queue, the next pointer of the last entry is NULL and does not point back
+ * to the head. When the tail queue is finalized, it is converted to a
+ * normal BSD tail queue.
+ */
+
+/*
+ * Tail queue list head structures.
+ */
+TAILQ_HEAD(defaults_list, defaults);
+TAILQ_HEAD(userspec_list, userspec);
+TAILQ_HEAD(member_list, member);
+TAILQ_HEAD(privilege_list, privilege);
+TAILQ_HEAD(cmndspec_list, cmndspec);
+TAILQ_HEAD(command_digest_list, command_digest);
+STAILQ_HEAD(comment_list, sudoers_comment);
+TAILQ_HEAD(sudoers_parse_tree_list, sudoers_parse_tree);
+
+/*
+ * Structure describing a user specification and list thereof.
+ */
+struct userspec {
+ TAILQ_ENTRY(userspec) entries;
+ struct member_list users; /* list of users */
+ struct privilege_list privileges; /* list of privileges */
+ struct comment_list comments; /* optional comments */
+ int line; /* line number in sudoers */
+ int column; /* column number in sudoers */
+ char *file; /* name of sudoers file */
+};
+
+/*
+ * Structure describing a privilege specification.
+ */
+struct privilege {
+ TAILQ_ENTRY(privilege) entries;
+ char *ldap_role; /* LDAP sudoRole */
+ struct member_list hostlist; /* list of hosts */
+ struct cmndspec_list cmndlist; /* list of Cmnd_Specs */
+ struct defaults_list defaults; /* list of sudoOptions */
+};
+
+/*
+ * A command with option args and digest.
+ * XXX - merge into struct member
+ */
+struct sudo_command {
+ char *cmnd;
+ char *args;
+ struct command_digest_list digests;
+};
+
+/*
+ * Structure describing a linked list of Cmnd_Specs.
+ * XXX - include struct command_options instead of its contents inline
+ */
+struct cmndspec {
+ TAILQ_ENTRY(cmndspec) entries;
+ struct member_list *runasuserlist; /* list of runas users */
+ struct member_list *runasgrouplist; /* list of runas groups */
+ struct member *cmnd; /* command to allow/deny */
+ struct cmndtag tags; /* tag specificaion */
+ int timeout; /* command timeout */
+ time_t notbefore; /* time restriction */
+ time_t notafter; /* time restriction */
+ char *runcwd; /* working directory */
+ char *runchroot; /* root directory */
+#ifdef HAVE_SELINUX
+ char *role, *type; /* SELinux role and type */
+#endif
+#ifdef HAVE_APPARMOR
+ char *apparmor_profile; /* AppArmor profile */
+#endif
+#ifdef HAVE_PRIV_SET
+ char *privs, *limitprivs; /* Solaris privilege sets */
+#endif
+};
+
+/*
+ * Generic structure to hold users, hosts, commands.
+ */
+struct member {
+ TAILQ_ENTRY(member) entries;
+ char *name; /* member name */
+ short type; /* type (see gram.h) */
+ short negated; /* negated via '!'? */
+};
+
+struct runascontainer {
+ struct member *runasusers;
+ struct member *runasgroups;
+};
+
+struct defaults_binding {
+ struct member_list members;
+ unsigned int refcnt;
+};
+
+struct sudoers_comment {
+ STAILQ_ENTRY(sudoers_comment) entries;
+ char *str;
+};
+
+/*
+ * Generic structure to hold {User,Host,Runas,Cmnd}_Alias
+ * Aliases are stored in a red-black tree, sorted by name and type.
+ */
+struct alias {
+ char *name; /* alias name */
+ short type; /* {USER,HOST,RUNAS,CMND}ALIAS */
+ short used; /* "used" flag for cycle detection */
+ int line; /* line number of alias entry */
+ int column; /* column number of alias entry */
+ char *file; /* file the alias entry was in */
+ struct member_list members; /* list of alias members */
+};
+
+/*
+ * Structure describing a Defaults entry in sudoers.
+ */
+struct defaults {
+ TAILQ_ENTRY(defaults) entries;
+ char *var; /* variable name */
+ char *val; /* variable value */
+ struct defaults_binding *binding; /* user/host/runas binding */
+ char *file; /* file Defaults entry was in */
+ int type; /* DEFAULTS{,_USER,_RUNAS,_HOST} */
+ int op; /* true, false, '+', '-' */
+ int line; /* line number of Defaults entry */
+ int column; /* column number of Defaults entry */
+};
+
+struct sudoers_match_info {
+ const struct sudoers_parse_tree *parse_tree;
+ const struct userspec *us; /* matching userspec */
+ const struct privilege *priv; /* matching privilege */
+ const struct cmndspec *cs; /* matching cmndspec */
+};
+
+/*
+ * Parsed sudoers policy.
+ */
+struct sudo_nss;
+struct sudoers_parse_tree {
+ TAILQ_ENTRY(sudoers_parse_tree) entries;
+ struct userspec_list userspecs;
+ struct defaults_list defaults;
+ struct rbtree *aliases;
+ char *shost, *lhost;
+ struct sudo_nss *nss;
+ struct sudoers_context *ctx;
+};
+
+/*
+ * Info about the command being resolved.
+ */
+struct cmnd_info {
+ struct stat cmnd_stat;
+ char *cmnd_path;
+ int status;
+};
+
+/*
+ * Optional callback for sudoers_lookup().
+ */
+typedef void (*sudoers_lookup_callback_fn_t)(const struct sudoers_parse_tree *parse_tree, const struct userspec *us, int user_match, const struct privilege *priv, int host_match, const struct cmndspec *cs, int date_match, int runas_match, int cmnd_match, void *closure);
+
+/*
+ * The parser passes pointers to data structures that are not stored anywhere.
+ * We add them to the leak list at allocation time and remove them from
+ * the list when they are stored in another data structure.
+ * This makes it possible to free data on error that would otherwise be leaked.
+ */
+enum parser_leak_types {
+ LEAK_UNKNOWN,
+ LEAK_PRIVILEGE,
+ LEAK_CMNDSPEC,
+ LEAK_DEFAULTS,
+ LEAK_MEMBER,
+ LEAK_DIGEST,
+ LEAK_RUNAS,
+ LEAK_PTR
+};
+struct parser_leak_entry {
+ SLIST_ENTRY(parser_leak_entry) entries;
+ enum parser_leak_types type;
+ union {
+ struct command_digest *dig;
+ struct privilege *p;
+ struct cmndspec *cs;
+ struct defaults *d;
+ struct member *m;
+ struct runascontainer *rc;
+ void *ptr;
+ } u;
+};
+SLIST_HEAD(parser_leak_list, parser_leak_entry);
+
+#define YY_DECL int sudoerslex(void)
+
+/* alias.c */
+struct rbtree *alloc_aliases(void);
+void free_aliases(struct rbtree *aliases);
+bool no_aliases(const struct sudoers_parse_tree *parse_tree);
+bool alias_add(struct sudoers_parse_tree *parse_tree, char *name, short type, char *file, int line, int column, struct member *members);
+const char *alias_type_to_string(short alias_type);
+struct alias *alias_get(const struct sudoers_parse_tree *parse_tree, const char *name, short type);
+struct alias *alias_remove(struct sudoers_parse_tree *parse_tree, const char *name, short type);
+bool alias_find_used(struct sudoers_parse_tree *parse_tree, struct rbtree *used_aliases);
+void alias_apply(struct sudoers_parse_tree *parse_tree, int (*func)(struct sudoers_parse_tree *, struct alias *, void *), void *cookie);
+void alias_free(void *a);
+void alias_put(struct alias *a);
+
+/* check_aliases.c */
+int check_aliases(struct sudoers_parse_tree *parse_tree, bool strict, bool quiet, int (*cb_unused)(struct sudoers_parse_tree *, struct alias *, void *));
+
+/* gram.y */
+extern bool parse_error;
+extern struct sudoers_parse_tree parsed_policy;
+extern bool (*sudoers_error_hook)(const struct sudoers_context *ctx, const char *file, int line, int column, const char * restrict fmt, va_list args);
+bool reset_parser(void);
+void free_member(struct member *m);
+void free_members(struct member_list *members);
+void free_cmndspec(struct cmndspec *cs, struct cmndspec_list *csl);
+void free_cmndspecs(struct cmndspec_list *csl);
+void free_privilege(struct privilege *priv);
+void free_userspec(struct userspec *us);
+void free_userspecs(struct userspec_list *usl);
+void free_default(struct defaults *def);
+void free_defaults(struct defaults_list *defs);
+bool init_parser(struct sudoers_context *ctx, const char *file);
+void init_parse_tree(struct sudoers_parse_tree *parse_tree, char *lhost, char *shost, struct sudoers_context *ctx, struct sudo_nss *nss);
+void free_parse_tree(struct sudoers_parse_tree *parse_tree);
+bool parser_leak_add(enum parser_leak_types type, void *v);
+bool parser_leak_remove(enum parser_leak_types type, void *v);
+void parser_leak_init(void);
+void reparent_parse_tree(struct sudoers_parse_tree *new_tree);
+int sudoersparse(void);
+uid_t sudoers_file_uid(void);
+gid_t sudoers_file_gid(void);
+mode_t sudoers_file_mode(void);
+bool sudoers_error_recovery(void);
+bool sudoers_strict(void);
+
+/* match_addr.c */
+int addr_matches(char *n);
+
+/* match_command.c */
+int command_matches(struct sudoers_context *ctx, const char *sudoers_cmnd, const char *sudoers_args, const char *runchroot, struct cmnd_info *info, const struct command_digest_list *digests);
+
+/* match_digest.c */
+int digest_matches(int fd, const char *path, const struct command_digest_list *digests);
+
+/* match.c */
+struct group;
+struct passwd;
+int group_matches(const char *sudoers_group, const struct group *gr);
+int hostname_matches(const char *shost, const char *lhost, const char *pattern);
+int netgr_matches(const struct sudo_nss *nss, const char *netgr, const char *lhost, const char *shost, const char *user);
+int usergr_matches(const char *group, const char *user, const struct passwd *pw);
+int userpw_matches(const char *sudoers_user, const char *user, const struct passwd *pw);
+int cmnd_matches(const struct sudoers_parse_tree *parse_tree, const struct member *m, const char *runchroot, struct cmnd_info *info);
+int cmnd_matches_all(const struct sudoers_parse_tree *parse_tree, const struct member *m, const char *runchroot, struct cmnd_info *info);
+int cmndlist_matches(const struct sudoers_parse_tree *parse_tree, const struct member_list *list, const char *runchroot, struct cmnd_info *info);
+int host_matches(const struct sudoers_parse_tree *parse_tree, const struct passwd *pw, const char *host, const char *shost, const struct member *m);
+int hostlist_matches(const struct sudoers_parse_tree *parse_tree, const struct passwd *pw, const struct member_list *list);
+int runaslist_matches(const struct sudoers_parse_tree *parse_tree, const struct member_list *user_list, const struct member_list *group_list, struct member **matching_user, struct member **matching_group);
+int user_matches(const struct sudoers_parse_tree *parse_tree, const struct passwd *pw, const struct member *m);
+int userlist_matches(const struct sudoers_parse_tree *parse_tree, const struct passwd *pw, const struct member_list *list);
+const char *sudo_getdomainname(void);
+struct gid_list *runas_getgroups(const struct sudoers_context *ctx);
+
+/* toke.l */
+YY_DECL;
+void sudoersrestart(FILE *);
+extern FILE *sudoersin;
+extern char *sudoers;
+
+/* base64.c */
+size_t base64_decode(const char *str, unsigned char *dst, size_t dsize);
+size_t base64_encode(const unsigned char *in, size_t in_len, char *out, size_t out_len);
+
+/* timeout.c */
+int parse_timeout(const char *timestr);
+
+/* gentime.c */
+time_t parse_gentime(const char *expstr);
+
+/* filedigest.c */
+unsigned char *sudo_filedigest(int fd, const char *file, unsigned int digest_type, size_t *digest_len);
+
+/* digestname.c */
+const char *digest_type_to_name(unsigned int digest_type);
+
+/* parse.c */
+struct sudo_nss_list;
+unsigned int sudoers_lookup(struct sudo_nss_list *snl, struct sudoers_context *ctx, time_t now, sudoers_lookup_callback_fn_t callback, void *cb_data, int *cmnd_status, int pwflag);
+
+/* display.c */
+int display_privs(struct sudoers_context *ctx, const struct sudo_nss_list *snl, struct passwd *pw, int verbose);
+int display_cmnd(struct sudoers_context *ctx, const struct sudo_nss_list *snl, struct passwd *pw, int verbose);
+
+/* parse_ldif.c */
+bool sudoers_parse_ldif(struct sudoers_parse_tree *parse_tree, FILE *fp, const char *sudoers_base, bool store_options);
+
+/* fmtsudoers.c */
+struct sudo_lbuf;
+bool sudoers_format_cmndspec(struct sudo_lbuf *lbuf, const struct sudoers_parse_tree *parse_tree, const struct cmndspec *cs, const struct cmndspec *prev_cs, struct cmndtag tags, bool expand_aliases);
+bool sudoers_format_default(struct sudo_lbuf *lbuf, const struct defaults *d);
+bool sudoers_format_member(struct sudo_lbuf *lbuf, const struct sudoers_parse_tree *parse_tree, const struct member *m, const char *separator, short alias_type);
+bool sudoers_defaults_to_tags(const char *var, const char *val, int op, struct cmndtag *tags);
+bool sudoers_defaults_list_to_tags(const struct defaults_list *defs, struct cmndtag *tags);
+
+/* fmtsudoers_cvt.c */
+bool sudoers_format_privilege(struct sudo_lbuf *lbuf, const struct sudoers_parse_tree *parse_tree, const struct privilege *priv, bool expand_aliases);
+bool sudoers_format_userspec(struct sudo_lbuf *lbuf, const struct sudoers_parse_tree *parse_tree, const struct userspec *us, bool expand_aliases);
+bool sudoers_format_userspecs(struct sudo_lbuf *lbuf, const struct sudoers_parse_tree *parse_tree, const char *separator, bool expand_aliases, bool flush);
+bool sudoers_format_default_line(struct sudo_lbuf *lbuf, const struct sudoers_parse_tree *parse_tree, const struct defaults *d, struct defaults **next, bool expand_aliases);
+
+/* parser_warnx.c */
+bool parser_warnx(const struct sudoers_context *ctx, const char *file, int line, int column, bool strict, bool quiet, const char * restrict fmt, ...) sudo_printflike(7, 8);
+bool parser_vwarnx(const struct sudoers_context *ctx, const char *file, int line, int column, bool strict, bool quiet, const char * restrict fmt, va_list ap) sudo_printflike(7, 0);
+
+#endif /* SUDOERS_PARSE_H */
diff --git a/plugins/sudoers/parse_ldif.c b/plugins/sudoers/parse_ldif.c
new file mode 100644
index 0000000..180e7da
--- /dev/null
+++ b/plugins/sudoers/parse_ldif.c
@@ -0,0 +1,778 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2018-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <ctype.h>
+
+#include <sudoers.h>
+#include <sudo_ldap.h>
+#include <redblack.h>
+#include <strlist.h>
+#include <gram.h>
+
+struct sudo_role {
+ STAILQ_ENTRY(sudo_role) entries;
+ char *cn;
+ char *notbefore;
+ char *notafter;
+ double order;
+ struct sudoers_str_list *cmnds;
+ struct sudoers_str_list *hosts;
+ struct sudoers_str_list *users;
+ struct sudoers_str_list *runasusers;
+ struct sudoers_str_list *runasgroups;
+ struct sudoers_str_list *options;
+};
+STAILQ_HEAD(sudo_role_list, sudo_role);
+
+static void
+sudo_role_free(struct sudo_role *role)
+{
+ debug_decl(sudo_role_free, SUDOERS_DEBUG_UTIL);
+
+ if (role != NULL) {
+ free(role->cn);
+ free(role->notbefore);
+ free(role->notafter);
+ str_list_free(role->cmnds);
+ str_list_free(role->hosts);
+ str_list_free(role->users);
+ str_list_free(role->runasusers);
+ str_list_free(role->runasgroups);
+ str_list_free(role->options);
+ free(role);
+ }
+
+ debug_return;
+}
+
+static struct sudo_role *
+sudo_role_alloc(void)
+{
+ struct sudo_role *role;
+ debug_decl(sudo_role_alloc, SUDOERS_DEBUG_UTIL);
+
+ role = calloc(1, sizeof(*role));
+ if (role != NULL) {
+ role->cmnds = str_list_alloc();
+ role->hosts = str_list_alloc();
+ role->users = str_list_alloc();
+ role->runasusers = str_list_alloc();
+ role->runasgroups = str_list_alloc();
+ role->options = str_list_alloc();
+ if (role->cmnds == NULL || role->hosts == NULL ||
+ role->users == NULL || role->runasusers == NULL ||
+ role->runasgroups == NULL || role->options == NULL) {
+ sudo_role_free(role);
+ role = NULL;
+ }
+ }
+
+ debug_return_ptr(role);
+}
+
+/*
+ * Parse an LDIF line, filling in attribute name and value.
+ * Modifies line, decodes base64 attribute values if present.
+ * See http://www.faqs.org/rfcs/rfc2849.html
+ */
+static bool
+ldif_parse_attribute(char *line, char **name, char **value)
+{
+ bool encoded = false;
+ char *attr, *cp, *ep, *colon;
+ size_t len;
+ debug_decl(ldif_parse_attribute, SUDOERS_DEBUG_UTIL);
+
+ /* Parse attribute name: [a-zA-Z][a-zA-Z0-9-]*: */
+ if (!isalpha((unsigned char)*line))
+ debug_return_bool(false);
+ for (cp = line + 1; *cp != ':' && *cp != '\0'; cp++) {
+ if (!isalnum((unsigned char)*cp) && *cp != '-')
+ debug_return_bool(false);
+ }
+ if (*cp != ':')
+ debug_return_bool(false);
+ colon = cp++;
+
+ /* Check for foo:: base64str. */
+ if (*cp == ':') {
+ encoded = true;
+ cp++;
+ }
+
+ /* Trim leading and trailing space. */
+ while (*cp == ' ')
+ cp++;
+
+ ep = cp + strlen(cp);
+ while (ep > cp && ep[-1] == ' ') {
+ ep--;
+ /* Don't trim escaped trailing space if not base64. */
+ if (!encoded && ep != cp && ep[-1] == '\\')
+ break;
+ *ep = '\0';
+ }
+
+ attr = cp;
+ if (encoded) {
+ /*
+ * Decode base64 inline and add NUL-terminator.
+ * The copy allows us to provide a useful message on error.
+ */
+ char *copy = strdup(attr);
+ if (copy == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ len = base64_decode(attr, (unsigned char *)copy, strlen(copy));
+ if (len == (size_t)-1) {
+ free(copy);
+ debug_return_bool(false);
+ }
+ memcpy(attr, copy, len);
+ attr[len] = '\0';
+ free(copy);
+ }
+
+ *colon = '\0';
+ *name = line;
+ *value = attr;
+
+ debug_return_bool(true);
+}
+
+/*
+ * Allocate a struct sudoers_string, store str in it and
+ * insert into the specified strlist.
+ */
+static void
+ldif_store_string(const char *str, struct sudoers_str_list *strlist, bool sorted)
+{
+ struct sudoers_string *ls;
+ debug_decl(ldif_store_string, SUDOERS_DEBUG_UTIL);
+
+ if ((ls = sudoers_string_alloc(str)) == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ if (!sorted) {
+ STAILQ_INSERT_TAIL(strlist, ls, entries);
+ } else {
+ struct sudoers_string *prev, *next;
+
+ /* Insertion sort, list is small. */
+ prev = STAILQ_FIRST(strlist);
+ if (prev == NULL || strcasecmp(str, prev->str) <= 0) {
+ STAILQ_INSERT_HEAD(strlist, ls, entries);
+ } else {
+ while ((next = STAILQ_NEXT(prev, entries)) != NULL) {
+ if (strcasecmp(str, next->str) <= 0)
+ break;
+ prev = next;
+ }
+ STAILQ_INSERT_AFTER(strlist, prev, ls, entries);
+ }
+ }
+
+ debug_return;
+}
+
+/*
+ * Iterator for sudo_ldap_role_to_priv().
+ * Takes a pointer to a struct sudoers_string *.
+ * Returns the string or NULL if we've reached the end.
+ */
+static char *
+sudoers_string_iter(void **vp)
+{
+ struct sudoers_string *ls = *vp;
+
+ if (ls == NULL)
+ return NULL;
+
+ *vp = STAILQ_NEXT(ls, entries);
+
+ return ls->str;
+}
+
+static int
+role_order_cmp(const void *va, const void *vb)
+{
+ const struct sudo_role *a = *(const struct sudo_role **)va;
+ const struct sudo_role *b = *(const struct sudo_role **)vb;
+ debug_decl(role_order_cmp, SUDOERS_DEBUG_LDAP);
+
+ debug_return_int(a->order < b->order ? -1 :
+ (a->order > b->order ? 1 : 0));
+}
+
+/*
+ * Parse list of sudoOption and store in the parse tree's defaults list.
+ */
+static void
+ldif_store_options(struct sudoers_parse_tree *parse_tree,
+ struct sudoers_str_list *options)
+{
+ struct defaults *d;
+ struct sudoers_string *ls;
+ char *var, *val;
+ debug_decl(ldif_store_options, SUDOERS_DEBUG_UTIL);
+
+ STAILQ_FOREACH(ls, options, entries) {
+ if ((d = calloc(1, sizeof(*d))) == NULL ||
+ (d->binding = malloc(sizeof(*d->binding))) == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ TAILQ_INIT(&d->binding->members);
+ d->binding->refcnt = 1;
+ d->type = DEFAULTS;
+ d->op = sudo_ldap_parse_option(ls->str, &var, &val);
+ if ((d->var = strdup(var)) == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ if (val != NULL) {
+ if ((d->val = strdup(val)) == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ }
+ TAILQ_INSERT_TAIL(&parse_tree->defaults, d, entries);
+ }
+ debug_return;
+}
+
+static int
+str_list_cmp(const void *aa, const void *bb)
+{
+ const struct sudoers_str_list *a = aa;
+ const struct sudoers_str_list *b = bb;
+ const struct sudoers_string *lsa = STAILQ_FIRST(a);
+ const struct sudoers_string *lsb = STAILQ_FIRST(b);
+ int ret;
+
+ while (lsa != NULL && lsb != NULL) {
+ if ((ret = strcasecmp(lsa->str, lsb->str)) != 0)
+ return ret;
+ lsa = STAILQ_NEXT(lsa, entries);
+ lsb = STAILQ_NEXT(lsb, entries);
+ }
+ return lsa == lsb ? 0 : (lsa == NULL ? -1 : 1);
+}
+
+static int
+str_list_cache(struct rbtree *cache, struct sudoers_str_list **strlistp)
+{
+ struct sudoers_str_list *strlist = *strlistp;
+ struct rbnode *node;
+ int ret;
+ debug_decl(str_list_cache, SUDOERS_DEBUG_UTIL);
+
+ ret = rbinsert(cache, strlist, &node);
+ switch (ret) {
+ case 0:
+ /* new entry, take a ref for the cache */
+ strlist->refcnt++;
+ break;
+ case 1:
+ /* already exists, use existing and take a ref. */
+ str_list_free(strlist);
+ strlist = node->data;
+ strlist->refcnt++;
+ *strlistp = strlist;
+ break;
+ }
+ debug_return_int(ret);
+}
+
+/*
+ * Convert a sudoRole to sudoers format and store in the parse tree.
+ */
+static void
+role_to_sudoers(struct sudoers_parse_tree *parse_tree, struct sudo_role *role,
+ bool store_options, bool reuse_userspec, bool reuse_privilege,
+ bool reuse_runas)
+{
+ struct privilege *priv;
+ struct sudoers_string *ls;
+ struct userspec *us;
+ struct member *m;
+ debug_decl(role_to_sudoers, SUDOERS_DEBUG_UTIL);
+
+ /*
+ * TODO: use cn to create a UserAlias if multiple users in it?
+ */
+
+ if (reuse_userspec) {
+ /* Re-use the previous userspec */
+ us = TAILQ_LAST(&parse_tree->userspecs, userspec_list);
+ } else {
+ /* Allocate a new userspec and fill in the user list. */
+ if ((us = calloc(1, sizeof(*us))) == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ TAILQ_INIT(&us->privileges);
+ TAILQ_INIT(&us->users);
+ STAILQ_INIT(&us->comments);
+
+ STAILQ_FOREACH(ls, role->users, entries) {
+ char *user = ls->str;
+
+ if ((m = calloc(1, sizeof(*m))) == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ m->negated = sudo_ldap_is_negated(&user);
+ switch (*user) {
+ case '\0':
+ /* Empty RunAsUser means run as the invoking user. */
+ m->type = MYSELF;
+ break;
+ case '+':
+ m->type = NETGROUP;
+ break;
+ case '%':
+ m->type = USERGROUP;
+ break;
+ case 'A':
+ if (strcmp(user, "ALL") == 0) {
+ m->type = ALL;
+ break;
+ }
+ FALLTHROUGH;
+ default:
+ m->type = WORD;
+ break;
+ }
+ if (m->type != ALL && m->type != MYSELF) {
+ if ((m->name = strdup(user)) == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ }
+ TAILQ_INSERT_TAIL(&us->users, m, entries);
+ }
+ }
+
+ /* Add source role as a comment. */
+ if (role->cn != NULL) {
+ struct sudoers_comment *comment = NULL;
+ if (reuse_userspec) {
+ /* Try to re-use comment too. */
+ STAILQ_FOREACH(comment, &us->comments, entries) {
+ if (strncasecmp(comment->str, "sudoRole ", 9) == 0) {
+ char *tmpstr;
+ if (asprintf(&tmpstr, "%s, %s", comment->str, role->cn) == -1) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ free(comment->str);
+ comment->str = tmpstr;
+ break;
+ }
+ }
+ }
+ if (comment == NULL) {
+ /* Create a new comment. */
+ if ((comment = malloc(sizeof(*comment))) == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ if (asprintf(&comment->str, "sudoRole %s", role->cn) == -1) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ STAILQ_INSERT_TAIL(&us->comments, comment, entries);
+ }
+ }
+
+ /* Convert role to sudoers privilege. */
+ priv = sudo_ldap_role_to_priv(role->cn, STAILQ_FIRST(role->hosts),
+ STAILQ_FIRST(role->runasusers), STAILQ_FIRST(role->runasgroups),
+ STAILQ_FIRST(role->cmnds), STAILQ_FIRST(role->options),
+ role->notbefore, role->notafter, true, store_options,
+ sudoers_string_iter);
+ if (priv == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+
+ if (reuse_privilege && !TAILQ_EMPTY(&us->privileges)) {
+ /* Hostspec unchanged, append cmndlist to previous privilege. */
+ struct privilege *prev_priv = TAILQ_LAST(&us->privileges, privilege_list);
+ if (reuse_runas) {
+ /* Runas users and groups same if as in previous privilege. */
+ struct cmndspec *cmndspec = TAILQ_FIRST(&priv->cmndlist);
+ const struct cmndspec *prev_cmndspec =
+ TAILQ_LAST(&prev_priv->cmndlist, cmndspec_list);
+ struct member_list *runasuserlist = prev_cmndspec->runasuserlist;
+ struct member_list *runasgrouplist = prev_cmndspec->runasgrouplist;
+
+ /* Free duplicate runas lists. */
+ if (cmndspec->runasuserlist != NULL) {
+ free_members(cmndspec->runasuserlist);
+ free(cmndspec->runasuserlist);
+ }
+ if (cmndspec->runasgrouplist != NULL) {
+ free_members(cmndspec->runasgrouplist);
+ free(cmndspec->runasgrouplist);
+ }
+
+ /* Update cmndspec with previous runas lists. */
+ TAILQ_FOREACH(cmndspec, &priv->cmndlist, entries) {
+ cmndspec->runasuserlist = runasuserlist;
+ cmndspec->runasgrouplist = runasgrouplist;
+ }
+ }
+ TAILQ_CONCAT(&prev_priv->cmndlist, &priv->cmndlist, entries);
+ free_privilege(priv);
+ } else {
+ TAILQ_INSERT_TAIL(&us->privileges, priv, entries);
+ }
+
+ /* Add finished userspec to the list if new. */
+ if (!reuse_userspec)
+ TAILQ_INSERT_TAIL(&parse_tree->userspecs, us, entries);
+
+ debug_return;
+}
+
+/*
+ * Convert the list of sudoRoles to sudoers format and store in the parse tree.
+ */
+static void
+ldif_to_sudoers(struct sudoers_parse_tree *parse_tree,
+ struct sudo_role_list *roles, unsigned int numroles, bool store_options)
+{
+ struct sudo_role **role_array, *role = NULL;
+ unsigned int n;
+ debug_decl(ldif_to_sudoers, SUDOERS_DEBUG_UTIL);
+
+ /* Convert from list of roles to array and sort by order. */
+ role_array = reallocarray(NULL, numroles + 1, sizeof(*role_array));
+ if (role_array == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ for (n = 0; n < numroles; n++) {
+ if ((role = STAILQ_FIRST(roles)) == NULL)
+ break; /* cannot happen */
+ STAILQ_REMOVE_HEAD(roles, entries);
+ role_array[n] = role;
+ }
+ role_array[n] = NULL;
+ qsort(role_array, numroles, sizeof(*role_array), role_order_cmp);
+
+ /*
+ * Iterate over roles in sorted order, converting to sudoers.
+ */
+ for (n = 0, role = NULL; n < numroles; n++) {
+ bool reuse_userspec = false;
+ bool reuse_privilege = false;
+ bool reuse_runas = false;
+ struct sudo_role *prev_role = role;
+
+ role = role_array[n];
+
+ /* Check whether we can reuse the previous user and host specs */
+ if (prev_role != NULL && role->users == prev_role->users) {
+ reuse_userspec = true;
+
+ /*
+ * Since options are stored per-privilege we can't
+ * append to the previous privilege's cmndlist if
+ * we are storing options.
+ */
+ if (!store_options) {
+ if (role->hosts == prev_role->hosts) {
+ reuse_privilege = true;
+
+ /* Reuse runasusers and runasgroups if possible. */
+ if (role->runasusers == prev_role->runasusers &&
+ role->runasgroups == prev_role->runasgroups)
+ reuse_runas = true;
+ }
+ }
+ }
+
+ role_to_sudoers(parse_tree, role, store_options, reuse_userspec,
+ reuse_privilege, reuse_runas);
+ }
+
+ /* Clean up. */
+ for (n = 0; n < numroles; n++)
+ sudo_role_free(role_array[n]);
+ free(role_array);
+
+ debug_return;
+}
+
+/*
+ * Given a cn with possible quoted characters, return a copy of
+ * the cn with quote characters ('\\') removed.
+ * The caller is responsible for freeing the returned string.
+ */
+static
+char *unquote_cn(const char *src)
+{
+ char *dst, *new_cn;
+ size_t len;
+ debug_decl(unquote_cn, SUDOERS_DEBUG_UTIL);
+
+ len = strlen(src);
+ if ((new_cn = malloc(len + 1)) == NULL)
+ debug_return_str(NULL);
+
+ for (dst = new_cn; *src != '\0';) {
+ if (src[0] == '\\' && src[1] != '\0')
+ src++;
+ *dst++ = *src++;
+ }
+ *dst = '\0';
+
+ debug_return_str(new_cn);
+}
+
+/*
+ * Parse a sudoers file in LDIF format, https://tools.ietf.org/html/rfc2849
+ * Parsed sudoRole objects are stored in the specified parse_tree which
+ * must already be initialized.
+ */
+bool
+sudoers_parse_ldif(struct sudoers_parse_tree *parse_tree,
+ FILE *fp, const char *sudoers_base, bool store_options)
+{
+ struct sudo_role_list roles = STAILQ_HEAD_INITIALIZER(roles);
+ struct sudo_role *role = NULL;
+ struct rbtree *usercache, *groupcache, *hostcache;
+ unsigned numroles = 0;
+ bool in_role = false;
+ size_t linesize = 0;
+ char *attr, *name, *line = NULL, *savedline = NULL;
+ size_t savedlen = 0;
+ bool mismatch = false;
+ int errors = 0;
+ debug_decl(sudoers_parse_ldif, SUDOERS_DEBUG_UTIL);
+
+ /*
+ * We cache user, group and host lists to make it eay to detect when there
+ * are identical lists (simple pointer compare). This makes it possible
+ * to merge multiplpe sudoRole objects into a single UserSpec and/or
+ * Privilege. The lists are sorted since LDAP order is arbitrary.
+ */
+ usercache = rbcreate(str_list_cmp);
+ groupcache = rbcreate(str_list_cmp);
+ hostcache = rbcreate(str_list_cmp);
+ if (usercache == NULL || groupcache == NULL || hostcache == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ /* Read through input, parsing into sudo_roles and global defaults. */
+ for (;;) {
+ int ch;
+ ssize_t len = getdelim(&line, &linesize, '\n', fp);
+
+ /* Trim trailing return or newline. */
+ while (len > 0 && (line[len - 1] == '\r' || line[len - 1] == '\n'))
+ line[--len] = '\0';
+
+ /* Blank line or EOF terminates an entry. */
+ if (len <= 0) {
+ if (in_role) {
+ if (role->cn != NULL && strcasecmp(role->cn, "defaults") == 0) {
+ ldif_store_options(parse_tree, role->options);
+ sudo_role_free(role);
+ } else if (STAILQ_EMPTY(role->users) ||
+ STAILQ_EMPTY(role->hosts) || STAILQ_EMPTY(role->cmnds)) {
+ /* Incomplete role. */
+ sudo_warnx(U_("ignoring incomplete sudoRole: cn: %s"),
+ role->cn ? role->cn : "UNKNOWN");
+ sudo_role_free(role);
+ } else {
+ /* Cache users, hosts, runasusers and runasgroups. */
+ if (str_list_cache(usercache, &role->users) == -1 ||
+ str_list_cache(hostcache, &role->hosts) == -1 ||
+ str_list_cache(usercache, &role->runasusers) == -1 ||
+ str_list_cache(groupcache, &role->runasgroups) == -1) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+
+ /* Store finished role. */
+ STAILQ_INSERT_TAIL(&roles, role, entries);
+ numroles++;
+ }
+ role = NULL;
+ in_role = false;
+ }
+ if (len == -1) {
+ /* EOF */
+ break;
+ }
+ mismatch = false;
+ continue;
+ }
+
+ if (savedline != NULL) {
+ char *tmp;
+
+ /* Append to saved line. */
+ linesize = savedlen + (size_t)len + 1;
+ if ((tmp = realloc(savedline, linesize)) == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ memcpy(tmp + savedlen, line, (size_t)len + 1);
+ free(line);
+ line = tmp;
+ savedline = NULL;
+ }
+
+ /* Check for folded line */
+ if ((ch = getc(fp)) == ' ') {
+ /* folded line, append to the saved portion. */
+ savedlen = (size_t)len;
+ savedline = line;
+ line = NULL;
+ linesize = 0;
+ continue;
+ }
+ ungetc(ch, fp); /* not folded, push back ch */
+
+ /* Skip comment lines or records that don't match the base. */
+ if (*line == '#' || mismatch)
+ continue;
+
+ /* Reject invalid LDIF. */
+ if (!ldif_parse_attribute(line, &name, &attr)) {
+ sudo_warnx(U_("invalid LDIF attribute: %s"), line);
+ errors++;
+ continue;
+ }
+
+ /* Parse dn and objectClass. */
+ if (strcasecmp(name, "dn") == 0) {
+ /* Compare dn to base, if specified. */
+ if (sudoers_base != NULL) {
+ /* Skip over cn if present. */
+ if (strncasecmp(attr, "cn=", 3) == 0) {
+ for (attr += 3; *attr != '\0'; attr++) {
+ /* Handle escaped ',' chars. */
+ if (*attr == '\\' && attr[1] != '\0')
+ attr++;
+ if (*attr == ',') {
+ attr++;
+ break;
+ }
+ }
+ }
+ if (strcasecmp(attr, sudoers_base) != 0) {
+ /* Doesn't match base, skip the rest of it. */
+ mismatch = true;
+ continue;
+ }
+ }
+ } else if (strcasecmp(name, "objectClass") == 0) {
+ if (strcasecmp(attr, "sudoRole") == 0) {
+ /* Allocate new role as needed. */
+ if (role == NULL) {
+ if ((role = sudo_role_alloc()) == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ }
+ in_role = true;
+ }
+ }
+
+ /* Not in a sudoRole, keep reading. */
+ if (!in_role)
+ continue;
+
+ /* Part of a sudoRole, parse it. */
+ if (strcasecmp(name, "cn") == 0) {
+ free(role->cn);
+ role->cn = unquote_cn(attr);
+ if (role->cn == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ } else if (strcasecmp(name, "sudoUser") == 0) {
+ ldif_store_string(attr, role->users, true);
+ } else if (strcasecmp(name, "sudoHost") == 0) {
+ ldif_store_string(attr, role->hosts, true);
+ } else if (strcasecmp(name, "sudoRunAs") == 0) {
+ ldif_store_string(attr, role->runasusers, true);
+ } else if (strcasecmp(name, "sudoRunAsUser") == 0) {
+ ldif_store_string(attr, role->runasusers, true);
+ } else if (strcasecmp(name, "sudoRunAsGroup") == 0) {
+ ldif_store_string(attr, role->runasgroups, true);
+ } else if (strcasecmp(name, "sudoCommand") == 0) {
+ ldif_store_string(attr, role->cmnds, false);
+ } else if (strcasecmp(name, "sudoOption") == 0) {
+ ldif_store_string(attr, role->options, false);
+ } else if (strcasecmp(name, "sudoOrder") == 0) {
+ char *ep;
+ role->order = strtod(attr, &ep);
+ if (ep == attr || *ep != '\0') {
+ sudo_warnx(U_("invalid sudoOrder attribute: %s"), attr);
+ errors++;
+ }
+ } else if (strcasecmp(name, "sudoNotBefore") == 0) {
+ free(role->notbefore);
+ role->notbefore = strdup(attr);
+ if (role->notbefore == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ } else if (strcasecmp(name, "sudoNotAfter") == 0) {
+ free(role->notafter);
+ role->notafter = strdup(attr);
+ if (role->notafter == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ }
+ }
+ sudo_role_free(role);
+ free(line);
+ free(savedline);
+
+ /* Convert from roles to sudoers data structures. */
+ if (numroles > 0)
+ ldif_to_sudoers(parse_tree, &roles, numroles, store_options);
+
+ /* Clean up. */
+ rbdestroy(usercache, str_list_free);
+ rbdestroy(groupcache, str_list_free);
+ rbdestroy(hostcache, str_list_free);
+
+ debug_return_bool(errors == 0);
+}
diff --git a/plugins/sudoers/parser_warnx.c b/plugins/sudoers/parser_warnx.c
new file mode 100644
index 0000000..9b0bfdd
--- /dev/null
+++ b/plugins/sudoers/parser_warnx.c
@@ -0,0 +1,82 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2022-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sudoers.h>
+
+bool
+parser_vwarnx(const struct sudoers_context *ctx, const char *file, int line,
+ int column, bool strict, bool quiet, const char * restrict fmt, va_list ap)
+{
+ bool ret = true;
+ debug_decl(parser_warnx, SUDOERS_DEBUG_DEFAULTS);
+
+ if (strict && sudoers_error_hook != NULL) {
+ va_list ap2;
+
+ va_copy(ap2, ap);
+ ret = sudoers_error_hook(ctx, file, line, column, fmt, ap2);
+ va_end(ap2);
+ }
+
+ if (!quiet) {
+ int oldlocale;
+ char *errstr;
+
+ sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale);
+ if (vasprintf(&errstr, _(fmt), ap) == -1) {
+ errstr = NULL;
+ ret = false;
+ } else if (line > 0) {
+ sudo_printf(SUDO_CONV_ERROR_MSG, _("%s:%d:%d: %s\n"), file,
+ line, column, errstr);
+ } else {
+ sudo_printf(SUDO_CONV_ERROR_MSG, _("%s: %s\n"), file, errstr);
+ }
+ sudoers_setlocale(oldlocale, NULL);
+
+ free(errstr);
+ }
+
+ debug_return_bool(ret);
+}
+
+bool
+parser_warnx(const struct sudoers_context *ctx, const char *file, int line,
+ int column, bool strict, bool quiet, const char * restrict fmt, ...)
+{
+ va_list ap;
+ bool ret;
+ debug_decl(parser_warnx, SUDOERS_DEBUG_DEFAULTS);
+
+ va_start(ap, fmt);
+ ret = parser_vwarnx(ctx, file, line, column, strict, quiet, fmt, ap);
+ va_end(ap);
+
+ debug_return_bool(ret);
+}
diff --git a/plugins/sudoers/pivot.c b/plugins/sudoers/pivot.c
new file mode 100644
index 0000000..59423f9
--- /dev/null
+++ b/plugins/sudoers/pivot.c
@@ -0,0 +1,87 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sudoers.h>
+
+/*
+ * Pivot to a new root directory, storing the old root and old cwd
+ * in state. Changes current working directory to the new root.
+ * Returns true on success, else false.
+ */
+bool
+pivot_root(const char *new_root, struct sudoers_pivot *state)
+{
+ debug_decl(pivot_root, SUDOERS_DEBUG_UTIL);
+
+ state->saved_root = open("/", O_RDONLY);
+ state->saved_cwd = open(".", O_RDONLY);
+ if (state->saved_root == -1 || state->saved_cwd == -1 || chroot(new_root) == -1) {
+ if (state->saved_root != -1) {
+ close(state->saved_root);
+ state->saved_root = -1;
+ }
+ if (state->saved_cwd != -1) {
+ close(state->saved_cwd);
+ state->saved_cwd = -1;
+ }
+ debug_return_bool(false);
+ }
+ debug_return_bool(chdir("/") == 0);
+}
+
+/*
+ * Pivot back to the stored root directory and restore the old cwd.
+ * Returns true on success, else false.
+ */
+bool
+unpivot_root(struct sudoers_pivot *state)
+{
+ bool ret = true;
+ debug_decl(unpivot_root, SUDOERS_DEBUG_UTIL);
+
+ /* Order is important: restore old root, *then* change cwd. */
+ if (state->saved_root != -1) {
+ if (fchdir(state->saved_root) == -1 || chroot(".") == -1) {
+ sudo_warn("%s", U_("unable to restore root directory"));
+ ret = false;
+ }
+ close(state->saved_root);
+ state->saved_root = -1;
+ }
+ if (state->saved_cwd != -1) {
+ if (fchdir(state->saved_cwd) == -1) {
+ sudo_warn("%s", U_("unable to restore current working directory"));
+ ret = false;
+ }
+ close(state->saved_cwd);
+ state->saved_cwd = -1;
+ }
+
+ debug_return_bool(ret);
+}
diff --git a/plugins/sudoers/pivot.h b/plugins/sudoers/pivot.h
new file mode 100644
index 0000000..b03993e
--- /dev/null
+++ b/plugins/sudoers/pivot.h
@@ -0,0 +1,32 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_PIVOT_H
+#define SUDOERS_PIVOT_H
+
+#define SUDOERS_PIVOT_INITIALIZER { -1, -1 }
+
+struct sudoers_pivot {
+ int saved_root;
+ int saved_cwd;
+};
+
+bool pivot_root(const char *new_root, struct sudoers_pivot *state);
+bool unpivot_root(struct sudoers_pivot *state);
+
+#endif /* SUDOERS_PIVOT_H */
diff --git a/plugins/sudoers/po/README b/plugins/sudoers/po/README
new file mode 100644
index 0000000..cff4d29
--- /dev/null
+++ b/plugins/sudoers/po/README
@@ -0,0 +1,14 @@
+NLS Translations for sudo are coordinated through the Translation
+Project, at https://translationproject.org/
+
+If you would like to contribute a translation for sudo, please join
+a translation team at the Translation Project instead of contributing
+a po file directly. This will avoid duplicated work if there is
+already a translation in progress. If you would like to become a
+member of a translation team, please follow the instructions at
+https://translationproject.org/html/translators.html
+
+The messages in sudo are split into two domains: sudo and sudoers.
+The former is used by the sudo front-end and utility functions.
+The latter is used by the sudoers policy and I/O logging plug-ins
+as well as the sudoers-specific commands visudo and sudoreplay.
diff --git a/plugins/sudoers/po/ast.mo b/plugins/sudoers/po/ast.mo
new file mode 100644
index 0000000..05cd28b
--- /dev/null
+++ b/plugins/sudoers/po/ast.mo
Binary files differ
diff --git a/plugins/sudoers/po/ast.po b/plugins/sudoers/po/ast.po
new file mode 100644
index 0000000..0957204
--- /dev/null
+++ b/plugins/sudoers/po/ast.po
@@ -0,0 +1,2343 @@
+# Portable object template file for the sudoers plugin
+# This file is put in the public domain.
+#
+# Todd C. Miller <Todd.Miller@sudo.ws>, 2011-2016.
+# enolp <enolp@softastur.org>, 2018, 2019.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.8.28b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2019-07-19 10:39-0600\n"
+"PO-Revision-Date: 2019-08-03 14:37+0200\n"
+"Last-Translator: enolp <enolp@softastur.org>\n"
+"Language-Team: Asturian <alministradores@softastur.org>\n"
+"Language: ast\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Lokalize 19.04.3\n"
+
+#: confstr.sh:1
+msgid "syntax error"
+msgstr "fallu de sintaxis"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "Contraseña de %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] contraseña de %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Contraseña:"
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** Información de SEGURANZA pa %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Perdona pero volvi tentalo."
+
+#: gram.y:194 gram.y:242 gram.y:249 gram.y:256 gram.y:263 gram.y:270
+#: gram.y:286 gram.y:310 gram.y:317 gram.y:324 gram.y:331 gram.y:338
+#: gram.y:401 gram.y:409 gram.y:419 gram.y:452 gram.y:459 gram.y:466
+#: gram.y:473 gram.y:555 gram.y:562 gram.y:571 gram.y:580 gram.y:597
+#: gram.y:709 gram.y:716 gram.y:723 gram.y:731 gram.y:831 gram.y:838
+#: gram.y:845 gram.y:852 gram.y:859 gram.y:885 gram.y:892 gram.y:899
+#: gram.y:1022 gram.y:1296 plugins/sudoers/alias.c:132
+#: plugins/sudoers/alias.c:139 plugins/sudoers/alias.c:155
+#: plugins/sudoers/auth/bsdauth.c:148 plugins/sudoers/auth/kerb5.c:123
+#: plugins/sudoers/auth/kerb5.c:149 plugins/sudoers/auth/pam.c:656
+#: plugins/sudoers/auth/rfc1938.c:116 plugins/sudoers/auth/sia.c:64
+#: plugins/sudoers/cvtsudoers.c:124 plugins/sudoers/cvtsudoers.c:165
+#: plugins/sudoers/cvtsudoers.c:182 plugins/sudoers/cvtsudoers.c:193
+#: plugins/sudoers/cvtsudoers.c:305 plugins/sudoers/cvtsudoers.c:433
+#: plugins/sudoers/cvtsudoers.c:566 plugins/sudoers/cvtsudoers.c:583
+#: plugins/sudoers/cvtsudoers.c:646 plugins/sudoers/cvtsudoers.c:761
+#: plugins/sudoers/cvtsudoers.c:769 plugins/sudoers/cvtsudoers.c:1179
+#: plugins/sudoers/cvtsudoers.c:1183 plugins/sudoers/cvtsudoers.c:1285
+#: plugins/sudoers/cvtsudoers_ldif.c:154 plugins/sudoers/cvtsudoers_ldif.c:197
+#: plugins/sudoers/cvtsudoers_ldif.c:244 plugins/sudoers/cvtsudoers_ldif.c:263
+#: plugins/sudoers/cvtsudoers_ldif.c:334 plugins/sudoers/cvtsudoers_ldif.c:389
+#: plugins/sudoers/cvtsudoers_ldif.c:397 plugins/sudoers/cvtsudoers_ldif.c:414
+#: plugins/sudoers/cvtsudoers_ldif.c:423 plugins/sudoers/cvtsudoers_ldif.c:570
+#: plugins/sudoers/defaults.c:664 plugins/sudoers/defaults.c:957
+#: plugins/sudoers/defaults.c:1128 plugins/sudoers/editor.c:72
+#: plugins/sudoers/editor.c:90 plugins/sudoers/editor.c:101
+#: plugins/sudoers/env.c:268 plugins/sudoers/filedigest.c:66
+#: plugins/sudoers/filedigest.c:82 plugins/sudoers/gc.c:59
+#: plugins/sudoers/group_plugin.c:138 plugins/sudoers/interfaces.c:78
+#: plugins/sudoers/iolog.c:941 plugins/sudoers/iolog_path.c:174
+#: plugins/sudoers/iolog_util.c:85 plugins/sudoers/iolog_util.c:124
+#: plugins/sudoers/iolog_util.c:133 plugins/sudoers/iolog_util.c:143
+#: plugins/sudoers/iolog_util.c:151 plugins/sudoers/iolog_util.c:155
+#: plugins/sudoers/ldap.c:185 plugins/sudoers/ldap.c:416
+#: plugins/sudoers/ldap.c:420 plugins/sudoers/ldap.c:432
+#: plugins/sudoers/ldap.c:723 plugins/sudoers/ldap.c:887
+#: plugins/sudoers/ldap.c:1235 plugins/sudoers/ldap.c:1662
+#: plugins/sudoers/ldap.c:1699 plugins/sudoers/ldap.c:1780
+#: plugins/sudoers/ldap.c:1915 plugins/sudoers/ldap.c:2016
+#: plugins/sudoers/ldap.c:2032 plugins/sudoers/ldap_conf.c:223
+#: plugins/sudoers/ldap_conf.c:254 plugins/sudoers/ldap_conf.c:306
+#: plugins/sudoers/ldap_conf.c:342 plugins/sudoers/ldap_conf.c:445
+#: plugins/sudoers/ldap_conf.c:460 plugins/sudoers/ldap_conf.c:557
+#: plugins/sudoers/ldap_conf.c:590 plugins/sudoers/ldap_conf.c:682
+#: plugins/sudoers/ldap_conf.c:764 plugins/sudoers/ldap_util.c:510
+#: plugins/sudoers/ldap_util.c:566 plugins/sudoers/linux_audit.c:83
+#: plugins/sudoers/logging.c:202 plugins/sudoers/logging.c:519
+#: plugins/sudoers/logging.c:545 plugins/sudoers/logging.c:586
+#: plugins/sudoers/logging.c:727 plugins/sudoers/logging.c:1087
+#: plugins/sudoers/match_command.c:249 plugins/sudoers/match_command.c:367
+#: plugins/sudoers/match_command.c:414 plugins/sudoers/match_command.c:482
+#: plugins/sudoers/match_digest.c:67 plugins/sudoers/parse.c:200
+#: plugins/sudoers/parse.c:212 plugins/sudoers/parse.c:227
+#: plugins/sudoers/parse.c:239 plugins/sudoers/parse_ldif.c:143
+#: plugins/sudoers/parse_ldif.c:170 plugins/sudoers/parse_ldif.c:239
+#: plugins/sudoers/parse_ldif.c:246 plugins/sudoers/parse_ldif.c:251
+#: plugins/sudoers/parse_ldif.c:327 plugins/sudoers/parse_ldif.c:338
+#: plugins/sudoers/parse_ldif.c:344 plugins/sudoers/parse_ldif.c:369
+#: plugins/sudoers/parse_ldif.c:381 plugins/sudoers/parse_ldif.c:385
+#: plugins/sudoers/parse_ldif.c:399 plugins/sudoers/parse_ldif.c:566
+#: plugins/sudoers/parse_ldif.c:596 plugins/sudoers/parse_ldif.c:621
+#: plugins/sudoers/parse_ldif.c:681 plugins/sudoers/parse_ldif.c:700
+#: plugins/sudoers/parse_ldif.c:746 plugins/sudoers/parse_ldif.c:756
+#: plugins/sudoers/policy.c:504 plugins/sudoers/policy.c:746
+#: plugins/sudoers/prompt.c:100 plugins/sudoers/pwutil.c:199
+#: plugins/sudoers/pwutil.c:272 plugins/sudoers/pwutil.c:350
+#: plugins/sudoers/pwutil.c:524 plugins/sudoers/pwutil.c:590
+#: plugins/sudoers/pwutil.c:661 plugins/sudoers/pwutil.c:820
+#: plugins/sudoers/pwutil.c:878 plugins/sudoers/pwutil.c:923
+#: plugins/sudoers/pwutil.c:982 plugins/sudoers/sssd.c:154
+#: plugins/sudoers/sssd.c:400 plugins/sudoers/sssd.c:463
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:554
+#: plugins/sudoers/sssd.c:745 plugins/sudoers/stubs.c:103
+#: plugins/sudoers/stubs.c:111 plugins/sudoers/sudoers.c:271
+#: plugins/sudoers/sudoers.c:281 plugins/sudoers/sudoers.c:290
+#: plugins/sudoers/sudoers.c:332 plugins/sudoers/sudoers.c:655
+#: plugins/sudoers/sudoers.c:781 plugins/sudoers/sudoers.c:825
+#: plugins/sudoers/sudoers.c:1119 plugins/sudoers/sudoers_debug.c:114
+#: plugins/sudoers/sudoreplay.c:581 plugins/sudoers/sudoreplay.c:584
+#: plugins/sudoers/sudoreplay.c:1261 plugins/sudoers/sudoreplay.c:1461
+#: plugins/sudoers/sudoreplay.c:1465 plugins/sudoers/testsudoers.c:136
+#: plugins/sudoers/testsudoers.c:236 plugins/sudoers/testsudoers.c:253
+#: plugins/sudoers/testsudoers.c:587 plugins/sudoers/timestamp.c:439
+#: plugins/sudoers/timestamp.c:483 plugins/sudoers/timestamp.c:960
+#: plugins/sudoers/toke_util.c:59 plugins/sudoers/toke_util.c:112
+#: plugins/sudoers/toke_util.c:149 plugins/sudoers/tsdump.c:130
+#: plugins/sudoers/visudo.c:152 plugins/sudoers/visudo.c:328
+#: plugins/sudoers/visudo.c:334 plugins/sudoers/visudo.c:444
+#: plugins/sudoers/visudo.c:622 plugins/sudoers/visudo.c:942
+#: plugins/sudoers/visudo.c:1029 plugins/sudoers/visudo.c:1118 toke.l:846
+#: toke.l:947 toke.l:1104
+msgid "unable to allocate memory"
+msgstr "nun pue allugase memoria"
+
+#: gram.y:484
+msgid "a digest requires a path name"
+msgstr "un digest rique un nome de camín"
+
+#: gram.y:610
+msgid "invalid notbefore value"
+msgstr "el valor de notbefore nun ye válidu"
+
+#: gram.y:618
+msgid "invalid notafter value"
+msgstr "el valor de notafter nun ye válidu"
+
+#: gram.y:627 plugins/sudoers/policy.c:320
+msgid "timeout value too large"
+msgstr "el valor de la escosa del tiempu d'espera ye pergrande"
+
+#: gram.y:629 plugins/sudoers/policy.c:322
+msgid "invalid timeout value"
+msgstr "la escosa del tiempu d'espera nun ye válida"
+
+#: gram.y:1296 plugins/sudoers/auth/pam.c:468 plugins/sudoers/auth/pam.c:656
+#: plugins/sudoers/auth/rfc1938.c:116 plugins/sudoers/cvtsudoers.c:124
+#: plugins/sudoers/cvtsudoers.c:164 plugins/sudoers/cvtsudoers.c:181
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:304
+#: plugins/sudoers/cvtsudoers.c:432 plugins/sudoers/cvtsudoers.c:565
+#: plugins/sudoers/cvtsudoers.c:582 plugins/sudoers/cvtsudoers.c:646
+#: plugins/sudoers/cvtsudoers.c:761 plugins/sudoers/cvtsudoers.c:768
+#: plugins/sudoers/cvtsudoers.c:1179 plugins/sudoers/cvtsudoers.c:1183
+#: plugins/sudoers/cvtsudoers.c:1285 plugins/sudoers/cvtsudoers_ldif.c:153
+#: plugins/sudoers/cvtsudoers_ldif.c:196 plugins/sudoers/cvtsudoers_ldif.c:243
+#: plugins/sudoers/cvtsudoers_ldif.c:262 plugins/sudoers/cvtsudoers_ldif.c:333
+#: plugins/sudoers/cvtsudoers_ldif.c:388 plugins/sudoers/cvtsudoers_ldif.c:396
+#: plugins/sudoers/cvtsudoers_ldif.c:413 plugins/sudoers/cvtsudoers_ldif.c:422
+#: plugins/sudoers/cvtsudoers_ldif.c:569 plugins/sudoers/defaults.c:664
+#: plugins/sudoers/defaults.c:957 plugins/sudoers/defaults.c:1128
+#: plugins/sudoers/editor.c:72 plugins/sudoers/editor.c:90
+#: plugins/sudoers/editor.c:101 plugins/sudoers/env.c:268
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:82
+#: plugins/sudoers/gc.c:59 plugins/sudoers/group_plugin.c:138
+#: plugins/sudoers/interfaces.c:78 plugins/sudoers/iolog.c:941
+#: plugins/sudoers/iolog_path.c:174 plugins/sudoers/iolog_util.c:85
+#: plugins/sudoers/iolog_util.c:124 plugins/sudoers/iolog_util.c:133
+#: plugins/sudoers/iolog_util.c:143 plugins/sudoers/iolog_util.c:151
+#: plugins/sudoers/iolog_util.c:155 plugins/sudoers/ldap.c:185
+#: plugins/sudoers/ldap.c:416 plugins/sudoers/ldap.c:420
+#: plugins/sudoers/ldap.c:432 plugins/sudoers/ldap.c:723
+#: plugins/sudoers/ldap.c:887 plugins/sudoers/ldap.c:1235
+#: plugins/sudoers/ldap.c:1662 plugins/sudoers/ldap.c:1699
+#: plugins/sudoers/ldap.c:1780 plugins/sudoers/ldap.c:1915
+#: plugins/sudoers/ldap.c:2016 plugins/sudoers/ldap.c:2032
+#: plugins/sudoers/ldap_conf.c:223 plugins/sudoers/ldap_conf.c:254
+#: plugins/sudoers/ldap_conf.c:306 plugins/sudoers/ldap_conf.c:342
+#: plugins/sudoers/ldap_conf.c:445 plugins/sudoers/ldap_conf.c:460
+#: plugins/sudoers/ldap_conf.c:557 plugins/sudoers/ldap_conf.c:590
+#: plugins/sudoers/ldap_conf.c:681 plugins/sudoers/ldap_conf.c:764
+#: plugins/sudoers/ldap_util.c:510 plugins/sudoers/ldap_util.c:566
+#: plugins/sudoers/linux_audit.c:83 plugins/sudoers/logging.c:202
+#: plugins/sudoers/logging.c:519 plugins/sudoers/logging.c:545
+#: plugins/sudoers/logging.c:585 plugins/sudoers/logging.c:1087
+#: plugins/sudoers/match_command.c:248 plugins/sudoers/match_command.c:366
+#: plugins/sudoers/match_command.c:413 plugins/sudoers/match_command.c:482
+#: plugins/sudoers/match_digest.c:67 plugins/sudoers/parse.c:199
+#: plugins/sudoers/parse.c:211 plugins/sudoers/parse.c:226
+#: plugins/sudoers/parse.c:238 plugins/sudoers/parse_ldif.c:142
+#: plugins/sudoers/parse_ldif.c:169 plugins/sudoers/parse_ldif.c:238
+#: plugins/sudoers/parse_ldif.c:245 plugins/sudoers/parse_ldif.c:250
+#: plugins/sudoers/parse_ldif.c:326 plugins/sudoers/parse_ldif.c:337
+#: plugins/sudoers/parse_ldif.c:343 plugins/sudoers/parse_ldif.c:368
+#: plugins/sudoers/parse_ldif.c:380 plugins/sudoers/parse_ldif.c:384
+#: plugins/sudoers/parse_ldif.c:398 plugins/sudoers/parse_ldif.c:566
+#: plugins/sudoers/parse_ldif.c:595 plugins/sudoers/parse_ldif.c:620
+#: plugins/sudoers/parse_ldif.c:680 plugins/sudoers/parse_ldif.c:699
+#: plugins/sudoers/parse_ldif.c:745 plugins/sudoers/parse_ldif.c:755
+#: plugins/sudoers/policy.c:134 plugins/sudoers/policy.c:143
+#: plugins/sudoers/policy.c:152 plugins/sudoers/policy.c:178
+#: plugins/sudoers/policy.c:305 plugins/sudoers/policy.c:320
+#: plugins/sudoers/policy.c:322 plugins/sudoers/policy.c:348
+#: plugins/sudoers/policy.c:358 plugins/sudoers/policy.c:402
+#: plugins/sudoers/policy.c:412 plugins/sudoers/policy.c:421
+#: plugins/sudoers/policy.c:430 plugins/sudoers/policy.c:504
+#: plugins/sudoers/policy.c:746 plugins/sudoers/prompt.c:100
+#: plugins/sudoers/pwutil.c:199 plugins/sudoers/pwutil.c:272
+#: plugins/sudoers/pwutil.c:350 plugins/sudoers/pwutil.c:524
+#: plugins/sudoers/pwutil.c:590 plugins/sudoers/pwutil.c:661
+#: plugins/sudoers/pwutil.c:820 plugins/sudoers/pwutil.c:878
+#: plugins/sudoers/pwutil.c:923 plugins/sudoers/pwutil.c:982
+#: plugins/sudoers/set_perms.c:396 plugins/sudoers/set_perms.c:775
+#: plugins/sudoers/set_perms.c:1165 plugins/sudoers/set_perms.c:1493
+#: plugins/sudoers/set_perms.c:1659 plugins/sudoers/sssd.c:153
+#: plugins/sudoers/sssd.c:400 plugins/sudoers/sssd.c:463
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:554
+#: plugins/sudoers/sssd.c:745 plugins/sudoers/stubs.c:103
+#: plugins/sudoers/stubs.c:111 plugins/sudoers/sudoers.c:271
+#: plugins/sudoers/sudoers.c:281 plugins/sudoers/sudoers.c:290
+#: plugins/sudoers/sudoers.c:332 plugins/sudoers/sudoers.c:655
+#: plugins/sudoers/sudoers.c:781 plugins/sudoers/sudoers.c:825
+#: plugins/sudoers/sudoers.c:1119 plugins/sudoers/sudoers_debug.c:113
+#: plugins/sudoers/sudoreplay.c:581 plugins/sudoers/sudoreplay.c:584
+#: plugins/sudoers/sudoreplay.c:1261 plugins/sudoers/sudoreplay.c:1461
+#: plugins/sudoers/sudoreplay.c:1465 plugins/sudoers/testsudoers.c:136
+#: plugins/sudoers/testsudoers.c:236 plugins/sudoers/testsudoers.c:253
+#: plugins/sudoers/testsudoers.c:587 plugins/sudoers/timestamp.c:439
+#: plugins/sudoers/timestamp.c:483 plugins/sudoers/timestamp.c:960
+#: plugins/sudoers/toke_util.c:59 plugins/sudoers/toke_util.c:112
+#: plugins/sudoers/toke_util.c:149 plugins/sudoers/tsdump.c:130
+#: plugins/sudoers/visudo.c:152 plugins/sudoers/visudo.c:328
+#: plugins/sudoers/visudo.c:334 plugins/sudoers/visudo.c:444
+#: plugins/sudoers/visudo.c:622 plugins/sudoers/visudo.c:942
+#: plugins/sudoers/visudo.c:1029 plugins/sudoers/visudo.c:1118 toke.l:846
+#: toke.l:947 toke.l:1104
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: plugins/sudoers/alias.c:151
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Yá se definió l'alias «%s»"
+
+#: plugins/sudoers/auth/aix_auth.c:203 plugins/sudoers/logging.c:788
+msgid "unable to fork"
+msgstr "nun pue biforcase"
+
+#: plugins/sudoers/auth/aix_auth.c:281
+#, fuzzy, c-format
+#| msgid "unable to change expired password: %s"
+msgid "unable to change password for %s"
+msgstr "nun pue camudase la contraseña caducada: %s"
+
+#: plugins/sudoers/auth/bsdauth.c:75
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "nun pue consiguise la clas pal usuariu %s"
+
+#: plugins/sudoers/auth/bsdauth.c:80
+msgid "unable to begin bsd authentication"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:88
+msgid "invalid authentication type"
+msgstr "la triba d'autenticación nun ye válida"
+
+#: plugins/sudoers/auth/bsdauth.c:97
+msgid "unable to initialize BSD authentication"
+msgstr "nun pue aniciase l'autenticaciónde BSD"
+
+#: plugins/sudoers/auth/bsdauth.c:185
+msgid "your account has expired"
+msgstr "la to cuenta caducó"
+
+#: plugins/sudoers/auth/bsdauth.c:187
+msgid "approval failed"
+msgstr "fallu de l'aprobación"
+
+#: plugins/sudoers/auth/fwtk.c:59
+msgid "unable to read fwtk config"
+msgstr "nun pue lleese la configuración de fwtk"
+
+#: plugins/sudoers/auth/fwtk.c:64
+msgid "unable to connect to authentication server"
+msgstr "nun pue coneutase col sirvidor d'autenticación"
+
+#: plugins/sudoers/auth/fwtk.c:70 plugins/sudoers/auth/fwtk.c:94
+#: plugins/sudoers/auth/fwtk.c:126
+msgid "lost connection to authentication server"
+msgstr "perdióse la conexón col sirvidor d'autenticación"
+
+#: plugins/sudoers/auth/fwtk.c:74
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"fallu del sirvidor d'autenticación:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:115
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:165
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: nun pue analizase «%s»: %s"
+
+#: plugins/sudoers/auth/kerb5.c:174
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: nun pue resolvese la caché de credenciales: %s"
+
+#: plugins/sudoers/auth/kerb5.c:221
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: nun pue allugase les opciones: %s"
+
+#: plugins/sudoers/auth/kerb5.c:236
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: nun puen consiguise les credenciales: %s"
+
+#: plugins/sudoers/auth/kerb5.c:249
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: nun pue aniciase la caché de credenciales: %s"
+
+#: plugins/sudoers/auth/kerb5.c:252
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: nun pue atroxase la credencial na caché: %s"
+
+#: plugins/sudoers/auth/kerb5.c:316
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:330
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: Nun pue verificase'l TGT, ¡quiciabes tean atacándote! : %s"
+
+#: plugins/sudoers/auth/pam.c:200
+msgid "unable to initialize PAM"
+msgstr "nun pue aniciase PAM"
+
+#: plugins/sudoers/auth/pam.c:299
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Fallu d'autenticación PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:318
+msgid "account validation failure, is your account locked?"
+msgstr "fallu de la validación de la cuenta, ¿tienes la cuenta bloquiada?"
+
+#: plugins/sudoers/auth/pam.c:329
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Caducó la cuenta o la contraseña, reanicia la to contraseña y volvi tentalo"
+
+#: plugins/sudoers/auth/pam.c:337
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "nun pue camudase la contraseña caducada: %s"
+
+#: plugins/sudoers/auth/pam.c:348
+msgid "Password expired, contact your system administrator"
+msgstr "Caducó la contraseña, contauta col alministrador de sistemes"
+
+#: plugins/sudoers/auth/pam.c:353
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "La cuenta caducó o a la configuración de PAM fálta-y la seición «account» pa sudo, contauta col alministrador de sistemes"
+
+#: plugins/sudoers/auth/pam.c:361 plugins/sudoers/auth/pam.c:367
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "Fallu de la xesión de cuentes PAM: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:104 plugins/sudoers/visudo.c:248
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "nun esistes na base de datos %s"
+
+#: plugins/sudoers/auth/securid5.c:77
+msgid "failed to initialise the ACE API library"
+msgstr "fallu al aniciar la biblioteca ACE API"
+
+#: plugins/sudoers/auth/securid5.c:103
+msgid "unable to contact the SecurID server"
+msgstr "nun pue contautase col sirvidor de SecurID"
+
+#: plugins/sudoers/auth/securid5.c:112
+msgid "User ID locked for SecurID Authentication"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:116 plugins/sudoers/auth/securid5.c:167
+msgid "invalid username length for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:120 plugins/sudoers/auth/securid5.c:172
+msgid "invalid Authentication Handle for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:124
+msgid "SecurID communication failed"
+msgstr "Falló la comunicación de SecurID"
+
+#: plugins/sudoers/auth/securid5.c:128 plugins/sudoers/auth/securid5.c:217
+msgid "unknown SecurID error"
+msgstr "desconozse'l fallu de SecurID"
+
+#: plugins/sudoers/auth/securid5.c:162
+msgid "invalid passcode length for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/sia.c:74 plugins/sudoers/auth/sia.c:129
+msgid "unable to initialize SIA session"
+msgstr "nun pue aniciase la sesión SIA"
+
+#: plugins/sudoers/auth/sudo_auth.c:138
+msgid "invalid authentication methods"
+msgstr "métodos d'autenticación non válidos"
+
+#: plugins/sudoers/auth/sudo_auth.c:140
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "¡Compiláronse en sudo métodos d'autenticación non válidos! Nun podríes combinar l'autenticación independiente y non independiente."
+
+#: plugins/sudoers/auth/sudo_auth.c:261 plugins/sudoers/auth/sudo_auth.c:311
+msgid "no authentication methods"
+msgstr "nun hai métodos d'autenticación"
+
+#: plugins/sudoers/auth/sudo_auth.c:263
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "¡Nun se compilaron en sudo métodos d'autenticación! Si quies desactivar l'autenticación, usa la opción de configuración --disable-authentication ."
+
+#: plugins/sudoers/auth/sudo_auth.c:313
+msgid "Unable to initialize authentication methods."
+msgstr "Nun puen aniciase los métodos d'autenticación."
+
+#: plugins/sudoers/auth/sudo_auth.c:479
+msgid "Authentication methods:"
+msgstr "Métodos d'autenticación:"
+
+#: plugins/sudoers/bsm_audit.c:125 plugins/sudoers/bsm_audit.c:217
+msgid "Could not determine audit condition"
+msgstr "Nun pudo determinase la condición d'autoría"
+
+#: plugins/sudoers/bsm_audit.c:190 plugins/sudoers/bsm_audit.c:281
+msgid "unable to commit audit record"
+msgstr "nun pue unviase'l rexistru d'auditoría"
+
+#: plugins/sudoers/check.c:269
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/check.c:312 plugins/sudoers/check.c:322
+#: plugins/sudoers/sudoers.c:698 plugins/sudoers/sudoers.c:743
+#: plugins/sudoers/tsdump.c:126
+#, c-format
+msgid "unknown uid: %u"
+msgstr "desconozse l'UID: %u"
+
+#: plugins/sudoers/check.c:317 plugins/sudoers/iolog.c:255
+#: plugins/sudoers/policy.c:917 plugins/sudoers/sudoers.c:1158
+#: plugins/sudoers/testsudoers.c:227 plugins/sudoers/testsudoers.c:400
+#, c-format
+msgid "unknown user: %s"
+msgstr "desconozse l'usuariu: %s"
+
+#: plugins/sudoers/cvtsudoers.c:199
+#, c-format
+msgid "order increment: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:215
+#, c-format
+msgid "starting order: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:225
+#, c-format
+msgid "order padding: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:233 plugins/sudoers/sudoreplay.c:289
+#: plugins/sudoers/visudo.c:184
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s versión %s\n"
+
+#: plugins/sudoers/cvtsudoers.c:235 plugins/sudoers/visudo.c:186
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "Gramática de %s na versión %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:252 plugins/sudoers/testsudoers.c:175
+#, c-format
+msgid "unsupported input format %s"
+msgstr "nun se sofita'l formatu d'entrada %s"
+
+#: plugins/sudoers/cvtsudoers.c:267
+#, c-format
+msgid "unsupported output format %s"
+msgstr "nun se sofita'l formatu de salida %s"
+
+#: plugins/sudoers/cvtsudoers.c:319
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: los ficheros d'entrada y salida han ser diferentes"
+
+#: plugins/sudoers/cvtsudoers.c:335 plugins/sudoers/sudoers.c:174
+#: plugins/sudoers/testsudoers.c:266 plugins/sudoers/visudo.c:254
+#: plugins/sudoers/visudo.c:610 plugins/sudoers/visudo.c:933
+msgid "unable to initialize sudoers default values"
+msgstr "nun puen aniciase los valores predeterminaos de sudoers"
+
+#: plugins/sudoers/cvtsudoers.c:421 plugins/sudoers/ldap_conf.c:435
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:480
+#, c-format
+msgid "%s: unknown key word: %s"
+msgstr "%s: desconozse la pallabra clave: %s"
+
+#: plugins/sudoers/cvtsudoers.c:526
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:549
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:589 plugins/sudoers/cvtsudoers.c:603
+#, c-format
+msgid "invalid filter: %s"
+msgstr "la peñera nun ye válida: %s"
+
+#: plugins/sudoers/cvtsudoers.c:622 plugins/sudoers/cvtsudoers.c:639
+#: plugins/sudoers/cvtsudoers.c:1245 plugins/sudoers/cvtsudoers_json.c:1130
+#: plugins/sudoers/cvtsudoers_ldif.c:643 plugins/sudoers/iolog.c:413
+#: plugins/sudoers/iolog_util.c:74 plugins/sudoers/sudoers.c:909
+#: plugins/sudoers/sudoreplay.c:335 plugins/sudoers/sudoreplay.c:1427
+#: plugins/sudoers/timestamp.c:448 plugins/sudoers/tsdump.c:135
+#: plugins/sudoers/visudo.c:929
+#, c-format
+msgid "unable to open %s"
+msgstr "nun pue abrise %s"
+
+#: plugins/sudoers/cvtsudoers.c:642 plugins/sudoers/visudo.c:938
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "fallu al analizar el ficheru %s, fallu desconocíu"
+
+#: plugins/sudoers/cvtsudoers.c:650 plugins/sudoers/visudo.c:955
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr "fallu d'analís en %s cierca de la llinia %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:653 plugins/sudoers/visudo.c:958
+#, c-format
+msgid "parse error in %s\n"
+msgstr "fallu d'analís en %s\n"
+
+#: plugins/sudoers/cvtsudoers.c:1292 plugins/sudoers/iolog.c:500
+#: plugins/sudoers/sudoreplay.c:1131 plugins/sudoers/timestamp.c:332
+#: plugins/sudoers/timestamp.c:335
+#, c-format
+msgid "unable to write to %s"
+msgstr "nun pue escribise en %s"
+
+#: plugins/sudoers/cvtsudoers.c:1315
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:1317
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_json.c:684 plugins/sudoers/cvtsudoers_json.c:720
+#: plugins/sudoers/cvtsudoers_json.c:938
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "desconozse lo predeterminao de la entrada «%s»"
+
+#: plugins/sudoers/cvtsudoers_json.c:858 plugins/sudoers/cvtsudoers_json.c:873
+#: plugins/sudoers/cvtsudoers_ldif.c:308 plugins/sudoers/cvtsudoers_ldif.c:319
+#: plugins/sudoers/ldap.c:482
+msgid "unable to get GMT time"
+msgstr "nun pue consiguise la hora GMT"
+
+#: plugins/sudoers/cvtsudoers_json.c:861 plugins/sudoers/cvtsudoers_json.c:876
+#: plugins/sudoers/cvtsudoers_ldif.c:311 plugins/sudoers/cvtsudoers_ldif.c:322
+#: plugins/sudoers/ldap.c:488
+msgid "unable to format timestamp"
+msgstr "nun pue formatiase la marca de tiempu"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:526 plugins/sudoers/env.c:330
+#: plugins/sudoers/env.c:337 plugins/sudoers/env.c:442
+#: plugins/sudoers/ldap.c:496 plugins/sudoers/ldap.c:727
+#: plugins/sudoers/ldap.c:1054 plugins/sudoers/ldap_conf.c:227
+#: plugins/sudoers/ldap_conf.c:317 plugins/sudoers/linux_audit.c:89
+#: plugins/sudoers/logging.c:1092 plugins/sudoers/policy.c:625
+#: plugins/sudoers/policy.c:635 plugins/sudoers/prompt.c:168
+#: plugins/sudoers/sudoers.c:847 plugins/sudoers/testsudoers.c:257
+#: plugins/sudoers/toke_util.c:161
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "fallu internu, sobrecarga de %s"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:595
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_ldif.c:638
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "nun s'afitó la variable d'entornu SUDOERS_BASE y tampoco s'especificó la opción -b"
+
+#: plugins/sudoers/def_data.c:42
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:46
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "La prioridá a usar de syslog cuando un usuariu s'autentica con ésitu: %s"
+
+#: plugins/sudoers/def_data.c:50
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "La prioridá a usar de syslog cuando un usuariu nun s'autentica con ésitu: %s"
+
+#: plugins/sudoers/def_data.c:54
+msgid "Put OTP prompt on its own line"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:58
+msgid "Ignore '.' in $PATH"
+msgstr "Inora «.» en $PATH"
+
+#: plugins/sudoers/def_data.c:62
+msgid "Always send mail when sudo is run"
+msgstr "Unviar siempres un corréu cuando sudo ta n'execución"
+
+#: plugins/sudoers/def_data.c:66
+msgid "Send mail if user authentication fails"
+msgstr "Unvia un corréu si falla l'autenticación del usuariu"
+
+#: plugins/sudoers/def_data.c:70
+msgid "Send mail if the user is not in sudoers"
+msgstr "Unvia un corréu si l'usuariu nun ta en sudoers"
+
+#: plugins/sudoers/def_data.c:74
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Unvia un corréu si l'usuariu nun ta nel sudoers d'esti agospiu"
+
+#: plugins/sudoers/def_data.c:78
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Unvia un corréu si l'usuariu nun tien permisu pa executar un comandu"
+
+#: plugins/sudoers/def_data.c:82
+msgid "Send mail if the user tries to run a command"
+msgstr "Unvia un corréu si l'usuariu tenta d'executar un comandu"
+
+#: plugins/sudoers/def_data.c:86
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:90
+msgid "Lecture user the first time they run sudo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:94
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Ficheru que contién la llectura de sudo: %s"
+
+#: plugins/sudoers/def_data.c:98
+msgid "Require users to authenticate by default"
+msgstr "Rique que los usuarios s'autentiquen por defeutu"
+
+#: plugins/sudoers/def_data.c:102
+msgid "Root may run sudo"
+msgstr "Root podría executar sudo"
+
+#: plugins/sudoers/def_data.c:106
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:110
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Rexistra l'añu nel ficheru de rexistru (non syslog)"
+
+#: plugins/sudoers/def_data.c:114
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Si s'invoca sudo ensin argumentos, anicia una shell"
+
+#: plugins/sudoers/def_data.c:118
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Afita $HOME al usuariu de destín al aniciar una shell con -s"
+
+#: plugins/sudoers/def_data.c:122
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Siempres afita $HOME al direutoriu d'aniciu del usuariu de destín"
+
+#: plugins/sudoers/def_data.c:126
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Permite la recoyida de della información pa dar mensaxes de fallu útiles"
+
+#: plugins/sudoers/def_data.c:130
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:134
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Insulta al usuariu cuando introduza una contraseña incorreuta"
+
+#: plugins/sudoers/def_data.c:138
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Namái permite que l'usuariu execute sudo si tien una TTY"
+
+#: plugins/sudoers/def_data.c:142
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo va respetar la variable d'entornu EDITOR"
+
+#: plugins/sudoers/def_data.c:146
+msgid "Prompt for root's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:150
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:154
+msgid "Prompt for the target user's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:158
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:162
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Afita les variables d'entornu LOGNAME y USER"
+
+#: plugins/sudoers/def_data.c:166
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Namái afita l'UID efeutivu al usuariu de destín, non al UID real"
+
+#: plugins/sudoers/def_data.c:170
+msgid "Don't initialize the group vector to that of the target user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:174
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Llargor al que s'axusten les llinies del ficheru de rexistru (0 pa nun axustar): %u"
+
+#: plugins/sudoers/def_data.c:178
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Escosa del tiempu d'espera de la marca de tiempu de l'autenticación: %.1f minutes"
+
+#: plugins/sudoers/def_data.c:182
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Escosa del tiempu d'espera pa la introducción de contraseñes: %.1f minutes"
+
+#: plugins/sudoers/def_data.c:186
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Númberu d'intentos pa introducir una contraseña: %u"
+
+#: plugins/sudoers/def_data.c:190
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:194
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Camín al ficheru de rexistru: %s"
+
+#: plugins/sudoers/def_data.c:198
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Camín al programa de corréu: %s"
+
+#: plugins/sudoers/def_data.c:202
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Banderes pal programa de corréu: %s"
+
+#: plugins/sudoers/def_data.c:206
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Direición a la qu'unviar correos: %s"
+
+#: plugins/sudoers/def_data.c:210
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Direición dende la qu'unviar correos: %s"
+
+#: plugins/sudoers/def_data.c:214
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Asuntu de los mensaxes de corréu: %s"
+
+#: plugins/sudoers/def_data.c:218
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Mensaxe de contraseña incorreuta: %s"
+
+#: plugins/sudoers/def_data.c:222
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:226
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Camín al direutoriu de marques de tiempu de l'autenticación: %s"
+
+#: plugins/sudoers/def_data.c:230
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:234
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:238
+#, c-format
+msgid "Default password prompt: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:242
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr ""
+
+#: plugins/sudoers/def_data.c:246
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Usuariu predeterminái pa executar comandos como: %s"
+
+#: plugins/sudoers/def_data.c:250
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Valor col qu'anular el $PATH d'usuariu: %s"
+
+#: plugins/sudoers/def_data.c:254
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Camín al editor que va usar visudo: %s"
+
+#: plugins/sudoers/def_data.c:258
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:262
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:266
+msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:270
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Si'l direutoriu LDAP ta activu, inoramos el ficheru sudoers llocal"
+
+#: plugins/sudoers/def_data.c:274
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:278
+msgid "If set, users may override the value of `closefrom' with the -C option"
+msgstr "Si s'afita, los usuarios podríen anular el valor de «closefrom» cola opción -C"
+
+#: plugins/sudoers/def_data.c:282
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Permite que los usuarios afiten variables d'entornu arbitraries"
+
+#: plugins/sudoers/def_data.c:286
+msgid "Reset the environment to a default set of variables"
+msgstr "Reafita l'entornu al conxuntu de variables predetermináu"
+
+#: plugins/sudoers/def_data.c:290
+msgid "Environment variables to check for sanity:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:294
+msgid "Environment variables to remove:"
+msgstr "Variables d'entornu a desaniciar:"
+
+#: plugins/sudoers/def_data.c:298
+msgid "Environment variables to preserve:"
+msgstr "Variables d'entornu a caltener:"
+
+#: plugins/sudoers/def_data.c:302
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "El rol de SELinux a usar nel contestu de seguranza nuevu: %s"
+
+#: plugins/sudoers/def_data.c:306
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "La triba de SELinux a usar nel contestu de seguranza nuevu: %s"
+
+#: plugins/sudoers/def_data.c:310
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Camín al ficheru d'entornu específicu de sudo: %s"
+
+#: plugins/sudoers/def_data.c:314
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Camín al ficheru d'entornu restrinxíu y específicu de sudo: %s"
+
+#: plugins/sudoers/def_data.c:318
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "La locale a usar mentanto s'analiza sudoers: %s"
+
+#: plugins/sudoers/def_data.c:322
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Permite a sudo pidir una contraseña magar que seya visible"
+
+#: plugins/sudoers/def_data.c:326
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:330
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:334
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "El umask especificáu en sudoers va anular el del usuariu, magar que seya más permisivu"
+
+#: plugins/sudoers/def_data.c:338
+msgid "Log user's input for the command being run"
+msgstr "Rexistra la entrada d'usuariu pal comandu que ta n'execución"
+
+#: plugins/sudoers/def_data.c:342
+msgid "Log the output of the command being run"
+msgstr "Rexistra la salida del comandu que ta n'execución"
+
+#: plugins/sudoers/def_data.c:346
+msgid "Compress I/O logs using zlib"
+msgstr "Comprime los rexistros d'E/S usando zlib"
+
+#: plugins/sudoers/def_data.c:350
+msgid "Always run commands in a pseudo-tty"
+msgstr "Executa siempres los comandos nuna pseudoTTY"
+
+#: plugins/sudoers/def_data.c:354
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Complementu pal sofitu de grupos non Unix: %s"
+
+#: plugins/sudoers/def_data.c:358
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Direutoriu nel que s'atroxen los rexistros d'entrada/salida: %s"
+
+#: plugins/sudoers/def_data.c:362
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Ficheru nel que s'atroxen los rexistros d'entrada/salida: %s"
+
+#: plugins/sudoers/def_data.c:366
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Amiesta una entrada al ficheru utmp/utmpx al allugar una PTY"
+
+#: plugins/sudoers/def_data.c:370
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:374
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Conxuntu de privilexos permitíos: %s"
+
+#: plugins/sudoers/def_data.c:378
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Conxuntu de privilexos llendaos: %s"
+
+#: plugins/sudoers/def_data.c:382
+msgid "Run commands on a pty in the background"
+msgstr "Executa comandos nuna PTY en segundu planu"
+
+#: plugins/sudoers/def_data.c:386
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "Nome del serviciu PAM a usar: %s"
+
+#: plugins/sudoers/def_data.c:390
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "Nome del serviciu PAM a usar pa les shells d'aniciu de sesión: %s"
+
+#: plugins/sudoers/def_data.c:394
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Tenta d'afitar les credenciales de PAM pal usuariu de destín"
+
+#: plugins/sudoers/def_data.c:398
+msgid "Create a new PAM session for the command to run in"
+msgstr "Crea una sesión PAM nueva pal comandu que va executase nella"
+
+#: plugins/sudoers/def_data.c:402
+#, fuzzy
+#| msgid "PAM account management error: %s"
+msgid "Perform PAM account validation management"
+msgstr "Fallu de la xesión de cuentes PAM: %s"
+
+#: plugins/sudoers/def_data.c:406
+#, c-format
+msgid "Maximum I/O log sequence number: %u"
+msgstr "Númberu máximu de secuencies de rexistru d'E/S: %u"
+
+#: plugins/sudoers/def_data.c:410
+msgid "Enable sudoers netgroup support"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:414
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Comprueba'l permisu d'escritura nos direutorios parentales al editar ficheros con sudoedit"
+
+#: plugins/sudoers/def_data.c:418
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Sigue enllaces simbólicos cuando s'editen ficheros con sudoedit"
+
+#: plugins/sudoers/def_data.c:422
+msgid "Query the group plugin for unknown system groups"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:426
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:430
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Permite que los comandos s'executen magar que sudo nun puea escribir nel rexistru d'auditoría"
+
+#: plugins/sudoers/def_data.c:434
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Permite que los comandos s'executen magar que sudo nun puea escribir nel rexistru d'E/S"
+
+#: plugins/sudoers/def_data.c:438
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Permite que los comandos s'executen magar que sudo nun puea escribir nel ficheru de rexistru "
+
+#: plugins/sudoers/def_data.c:442
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:446
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Les entraes mayores qu'esti valor nun van dixebrase en mensaxes de syslog múltiples: %u"
+
+#: plugins/sudoers/def_data.c:450
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "L'usuariu que va ser propietariu de los ficheros de rexistru d'E/S: %s"
+
+#: plugins/sudoers/def_data.c:454
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "El grupu que va ser propietariu de los ficheros de rexistru d'E/S: %s"
+
+#: plugins/sudoers/def_data.c:458
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:462
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Executa comandos pol descriptor de ficheru en cuentes de pol camín: %s"
+
+#: plugins/sudoers/def_data.c:466
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:470
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "El tiempu en segundos tres el que'l comandu va terminar: %u"
+
+#: plugins/sudoers/def_data.c:474
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Permite que l'usuariu especifique na llinia de comandos una escosa del tiempu d'espera"
+
+#: plugins/sudoers/def_data.c:478
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:482
+msgid "Include the process ID when logging via syslog"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:486
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Rexistru de la marca de tiempu de la triba d'autentiación: %s"
+
+#: plugins/sudoers/def_data.c:490
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Mensaxe del fallu d'autenticación: %s"
+
+#: plugins/sudoers/def_data.c:494
+msgid "Ignore case when matching user names"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:498
+msgid "Ignore case when matching group names"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:231
+#, c-format
+msgid "%s:%d unknown defaults entry \"%s\""
+msgstr "%s:%d desconozse lo predeterminao de la entrada «%s»"
+
+#: plugins/sudoers/defaults.c:234
+#, c-format
+msgid "%s: unknown defaults entry \"%s\""
+msgstr "%s: desconozse lo predeterminao de la entrada «%s»"
+
+#: plugins/sudoers/defaults.c:277
+#, c-format
+msgid "%s:%d no value specified for \"%s\""
+msgstr "%s:%d nun s'especificó dengún valor pa «%s»"
+
+#: plugins/sudoers/defaults.c:280
+#, c-format
+msgid "%s: no value specified for \"%s\""
+msgstr "%s: nun s'especificó dengún valor pa «%s»"
+
+#: plugins/sudoers/defaults.c:300
+#, c-format
+msgid "%s:%d values for \"%s\" must start with a '/'"
+msgstr "%s:%d los valores pa «%s» han apenzar per «/»"
+
+#: plugins/sudoers/defaults.c:303
+#, c-format
+msgid "%s: values for \"%s\" must start with a '/'"
+msgstr "%s los valores pa «%s» han apenzar per «/»"
+
+#: plugins/sudoers/defaults.c:325
+#, c-format
+msgid "%s:%d option \"%s\" does not take a value"
+msgstr "%s:%d la opción «%s» nun garra dengún valor"
+
+#: plugins/sudoers/defaults.c:328
+#, c-format
+msgid "%s: option \"%s\" does not take a value"
+msgstr "%s: la opción «%s» nun garra dengún valor"
+
+#: plugins/sudoers/defaults.c:353
+#, c-format
+msgid "%s:%d invalid Defaults type 0x%x for option \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:356
+#, c-format
+msgid "%s: invalid Defaults type 0x%x for option \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:366
+#, c-format
+msgid "%s:%d value \"%s\" is invalid for option \"%s\""
+msgstr "%s:%d el valor «%s» nun ye válidu pa la opción «%s»"
+
+#: plugins/sudoers/defaults.c:369
+#, c-format
+msgid "%s: value \"%s\" is invalid for option \"%s\""
+msgstr "%s: el valor «%s» nun ye válidu pa la opción «%s»"
+
+#: plugins/sudoers/env.c:411
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr ""
+
+#: plugins/sudoers/env.c:1132
+msgid "unable to rebuild the environment"
+msgstr "nun pue construyise de nueves l'entornu"
+
+#: plugins/sudoers/env.c:1206
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "perdona pero nun tienes permisu p'afitar les variables d'entornu de darréu: %s"
+
+#: plugins/sudoers/file.c:116
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr "fallu d'analís en %s cierca de la llinia %d"
+
+#: plugins/sudoers/file.c:119
+#, c-format
+msgid "parse error in %s"
+msgstr "fallu d'analís en %s"
+
+#: plugins/sudoers/filedigest.c:61
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr "nun se sofita la triba de digest %d pa %s"
+
+#: plugins/sudoers/filedigest.c:90
+#, c-format
+msgid "%s: read error"
+msgstr "%s: fallu de llectura"
+
+#: plugins/sudoers/group_plugin.c:90
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s ha ser propiedá del UID %d"
+
+#: plugins/sudoers/group_plugin.c:94
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr "%s ha ser namái escribible pol dueñu"
+
+#: plugins/sudoers/group_plugin.c:102 plugins/sudoers/sssd.c:563
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "nun pue cargase %s: %s"
+
+#: plugins/sudoers/group_plugin.c:108
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "nun pue alcontrase'l símbolu «group_plugin» en %s"
+
+#: plugins/sudoers/group_plugin.c:113
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:86 plugins/sudoers/interfaces.c:103
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "nun pue analizase la direición IP «%s»"
+
+#: plugins/sudoers/interfaces.c:91 plugins/sudoers/interfaces.c:108
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "nun pue analizase la mázcara de rede «%s»"
+
+#: plugins/sudoers/interfaces.c:136
+msgid "Local IP address and netmask pairs:\n"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:117 plugins/sudoers/mkdir_parents.c:82
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s esiste pero nun ye un direutoriu (0%o)"
+
+#: plugins/sudoers/iolog.c:142 plugins/sudoers/iolog.c:182
+#: plugins/sudoers/mkdir_parents.c:71 plugins/sudoers/timestamp.c:212
+#, c-format
+msgid "unable to mkdir %s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:186 plugins/sudoers/visudo.c:739
+#: plugins/sudoers/visudo.c:750
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "nun pue camudse'l mou de %s a 0%o"
+
+#: plugins/sudoers/iolog.c:294 plugins/sudoers/sudoers.c:1189
+#: plugins/sudoers/testsudoers.c:424
+#, c-format
+msgid "unknown group: %s"
+msgstr "desconozse'l grupu: %s"
+
+#: plugins/sudoers/iolog.c:464 plugins/sudoers/sudoers.c:913
+#: plugins/sudoers/sudoreplay.c:842 plugins/sudoers/sudoreplay.c:1538
+#: plugins/sudoers/tsdump.c:145
+#, c-format
+msgid "unable to read %s"
+msgstr "nun pue lleese %s"
+
+#: plugins/sudoers/iolog.c:579 plugins/sudoers/iolog.c:799
+#, c-format
+msgid "unable to create %s"
+msgstr "nun pue crease %s"
+
+#: plugins/sudoers/iolog.c:822 plugins/sudoers/iolog.c:1037
+#: plugins/sudoers/iolog.c:1113 plugins/sudoers/iolog.c:1207
+#: plugins/sudoers/iolog.c:1267
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "nun pue escribise nel ficheru de rexistru d'E/S %s"
+
+#: plugins/sudoers/iolog.c:1071
+#, fuzzy, c-format
+#| msgid "%s: internal error, file index %d not open"
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: fallu internu, l'índiz de ficheros %d nun ta abiertu"
+
+#: plugins/sudoers/iolog.c:1230
+#, fuzzy, c-format
+#| msgid "%s: internal error, file index %d not open"
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: fallu internu, l'índiz de ficheros %d nun ta abiertu"
+
+#: plugins/sudoers/iolog_util.c:89
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: el ficheru de rexistru nun ye válidu"
+
+#: plugins/sudoers/iolog_util.c:107
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: falta'l ficheru de marques de tiempu"
+
+#: plugins/sudoers/iolog_util.c:113
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr ""
+
+#: plugins/sudoers/iolog_util.c:120
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: falta'l campu d'usuariu"
+
+#: plugins/sudoers/iolog_util.c:129
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr ""
+
+#: plugins/sudoers/iolog_util.c:138
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:178 plugins/sudoers/ldap_conf.c:296
+msgid "starttls not supported when using ldaps"
+msgstr "nun se sofita starttls cuando s'usa LDAPS"
+
+#: plugins/sudoers/ldap.c:249
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "nun pue aniciase la base de datos de claves y certificaos SSL: %s"
+
+#: plugins/sudoers/ldap.c:252
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "ha afitar TLS_CERT en %s pa usar SSL"
+
+#: plugins/sudoers/ldap.c:1614
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "nun pue aniciase LDAP: %s"
+
+#: plugins/sudoers/ldap.c:1650
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1787 plugins/sudoers/parse_ldif.c:737
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "atributu sudoOrder non válidu: %s"
+
+#: plugins/sudoers/ldap_conf.c:205
+msgid "sudo_ldap_conf_add_ports: port too large"
+msgstr "sudo_ldap_conf_add_ports: el puertu ye pergrande"
+
+#: plugins/sudoers/ldap_conf.c:265
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "nun se sofita la triba URI de LDAP: %s"
+
+#: plugins/sudoers/ldap_conf.c:292
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "nun puen mecese les URIs de LDAP y LDAPS"
+
+#: plugins/sudoers/ldap_util.c:456 plugins/sudoers/ldap_util.c:458
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "nun pue convertise sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:59
+msgid "unable to open audit system"
+msgstr "nun pue abrise'l sistema d'auditoría"
+
+#: plugins/sudoers/linux_audit.c:100
+msgid "unable to send audit message"
+msgstr "nun pue unviase'l mensaxe d'auditoría"
+
+#: plugins/sudoers/logging.c:120
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: plugins/sudoers/logging.c:148
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (el comandu siguió) %s"
+
+#: plugins/sudoers/logging.c:177
+#, c-format
+msgid "unable to open log file: %s"
+msgstr "nun pue abrise'l ficheru de rexistru: %s"
+
+#: plugins/sudoers/logging.c:185
+#, c-format
+msgid "unable to lock log file: %s"
+msgstr "nun pue bloquiase'l fiheru de rexistru: %s"
+
+#: plugins/sudoers/logging.c:218
+#, c-format
+msgid "unable to write log file: %s"
+msgstr "nun pue escribise nel ficheru de rexistru: %s"
+
+#: plugins/sudoers/logging.c:247
+msgid "No user or host"
+msgstr ""
+
+#: plugins/sudoers/logging.c:249
+msgid "validation failure"
+msgstr "fallu de validación"
+
+#: plugins/sudoers/logging.c:256
+msgid "user NOT in sudoers"
+msgstr "l'usuariu NUN ta en sudoers"
+
+#: plugins/sudoers/logging.c:258
+msgid "user NOT authorized on host"
+msgstr "l'usuariu NUN ta autorizáu nel agospiu"
+
+#: plugins/sudoers/logging.c:260
+msgid "command not allowed"
+msgstr "comandu non permitíu"
+
+#: plugins/sudoers/logging.c:295
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr "%s nun ta nel ficheru sudoers. Va informase d'esti incidente.\n"
+
+#: plugins/sudoers/logging.c:298
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr "%s nun tien permisu pa executar sudo en %s. Va informase d'esti accidente.\n"
+
+#: plugins/sudoers/logging.c:302
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Perdona pero l'usuariu %s podría nun executar sudo en %s.\n"
+
+#: plugins/sudoers/logging.c:305
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr "Perdona pero l'usuariu %s nun tien permisu pa executar «%s%s%s» como %s%s%s en %s.\n"
+
+#: plugins/sudoers/logging.c:342 plugins/sudoers/sudoers.c:440
+#: plugins/sudoers/sudoers.c:442 plugins/sudoers/sudoers.c:444
+#: plugins/sudoers/sudoers.c:446 plugins/sudoers/sudoers.c:601
+#: plugins/sudoers/sudoers.c:603
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: nun s'alcontró'l comandu"
+
+#: plugins/sudoers/logging.c:344 plugins/sudoers/sudoers.c:436
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+
+#: plugins/sudoers/logging.c:361
+msgid "authentication failure"
+msgstr "fallu d'autenticación"
+
+#: plugins/sudoers/logging.c:387
+msgid "a password is required"
+msgstr "ríquese una contraseña"
+
+#: plugins/sudoers/logging.c:450
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] ""
+msgstr[1] ""
+
+#: plugins/sudoers/logging.c:715
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "nun pue facese dup a stdin: %m"
+
+#: plugins/sudoers/logging.c:755
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "nun pue executase %s: %m"
+
+#: plugins/sudoers/logging.c:796 plugins/sudoers/logging.c:852
+#, c-format
+msgid "unable to fork: %m"
+msgstr "nun pue biforcase: %m"
+
+#: plugins/sudoers/logging.c:842
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "nun pue abrise la tubería: %m"
+
+#: plugins/sudoers/match_digest.c:100
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "el digest pa %s (%s) nun ta na forma %s"
+
+#: plugins/sudoers/mkdir_parents.c:77 plugins/sudoers/sudoers.c:938
+#: plugins/sudoers/visudo.c:437 plugins/sudoers/visudo.c:733
+#, c-format
+msgid "unable to stat %s"
+msgstr "nun pue facese stat a %s"
+
+#: plugins/sudoers/parse.c:449
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+"\n"
+"Rol LADAP: %s\n"
+
+#: plugins/sudoers/parse.c:452
+#, c-format
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+"\n"
+"entrada de sudoers:\n"
+
+#: plugins/sudoers/parse.c:454
+#, c-format
+msgid " RunAsUsers: "
+msgstr " RunAsUsers: "
+
+#: plugins/sudoers/parse.c:469
+#, c-format
+msgid " RunAsGroups: "
+msgstr " RunAsGroups: "
+
+#: plugins/sudoers/parse.c:479
+#, c-format
+msgid " Options: "
+msgstr " Opciones: "
+
+#: plugins/sudoers/parse.c:535
+#, c-format
+msgid " Commands:\n"
+msgstr " Comandos:\n"
+
+#: plugins/sudoers/parse.c:726
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr ""
+
+#: plugins/sudoers/parse.c:744
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr ""
+
+#: plugins/sudoers/parse.c:762
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "L'usuariu %s podría executar los comandos de darréu en %s:\n"
+
+#: plugins/sudoers/parse.c:777
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/parse_ldif.c:147
+#, fuzzy, c-format
+#| msgid "invalid timeout value"
+msgid "ignoring invalid attribute value: %s"
+msgstr "la escosa del tiempu d'espera nun ye válida"
+
+#: plugins/sudoers/parse_ldif.c:586
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr ""
+
+#: plugins/sudoers/policy.c:90 plugins/sudoers/policy.c:116
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:295 plugins/sudoers/testsudoers.c:280
+msgid "unable to parse network address list"
+msgstr "nun pue analizase la llista de direiciones de rede"
+
+#: plugins/sudoers/policy.c:439
+msgid "user name not set by sudo front-end"
+msgstr "el nome d'usuariu nun lu afitó'l frontal de sudo"
+
+#: plugins/sudoers/policy.c:443
+msgid "user ID not set by sudo front-end"
+msgstr "el fontal de sudo nun la afitó la ID d'usuariu"
+
+#: plugins/sudoers/policy.c:447
+msgid "group ID not set by sudo front-end"
+msgstr "el fontal de sudo nun la afitó la ID de grupu"
+
+#: plugins/sudoers/policy.c:451
+msgid "host name not set by sudo front-end"
+msgstr "el nome d'agospiu nun lu afitó'l frontal de sudo"
+
+#: plugins/sudoers/policy.c:804 plugins/sudoers/visudo.c:236
+#: plugins/sudoers/visudo.c:867
+#, c-format
+msgid "unable to execute %s"
+msgstr "nun pue executase %s"
+
+#: plugins/sudoers/policy.c:935
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Versión %s del complementu de polítiques de sudoers\n"
+
+#: plugins/sudoers/policy.c:937
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Versión %d de la gramática del ficheru sudoers\n"
+
+#: plugins/sudoers/policy.c:941
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Camín de sudoers: %s\n"
+
+#: plugins/sudoers/policy.c:944
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "camín de nsswitch: %s\n"
+
+#: plugins/sudoers/policy.c:946
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "camín de ldap.conf: %s\n"
+
+#: plugins/sudoers/policy.c:947
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "camín de ldap.secret: %s\n"
+
+#: plugins/sudoers/policy.c:980
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:222 plugins/sudoers/pwutil.c:241
+#, c-format
+msgid "unable to cache uid %u, out of memory"
+msgstr "nun pue atroxase na caché l'UID %u, nun hai memoria"
+
+#: plugins/sudoers/pwutil.c:235
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "nun pue atroxase na caché l'UID %u, yá esiste"
+
+#: plugins/sudoers/pwutil.c:296 plugins/sudoers/pwutil.c:314
+#: plugins/sudoers/pwutil.c:377 plugins/sudoers/pwutil.c:422
+#, c-format
+msgid "unable to cache user %s, out of memory"
+msgstr "nun pue atroxase na caché l'usuariu %s, nun hai memoria"
+
+#: plugins/sudoers/pwutil.c:309
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "nun pue atroxase na caché l'usuariu %s, yá esiste"
+
+#: plugins/sudoers/pwutil.c:541 plugins/sudoers/pwutil.c:560
+#, c-format
+msgid "unable to cache gid %u, out of memory"
+msgstr "nun pue atroxase na caché'l GID %u, nun hai memoria"
+
+#: plugins/sudoers/pwutil.c:554
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "nun pue atroxase na caché'l GID %u, yá esiste"
+
+#: plugins/sudoers/pwutil.c:608 plugins/sudoers/pwutil.c:626
+#: plugins/sudoers/pwutil.c:674 plugins/sudoers/pwutil.c:716
+#, c-format
+msgid "unable to cache group %s, out of memory"
+msgstr "nun pue atroxase na caché'l grupu %s, nun hai memoria"
+
+#: plugins/sudoers/pwutil.c:621
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "nun pue atroxase na caché'l grupu %s, yá esiste"
+
+#: plugins/sudoers/pwutil.c:843 plugins/sudoers/pwutil.c:896
+#: plugins/sudoers/pwutil.c:947 plugins/sudoers/pwutil.c:1001
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "nun pue atroxase na caché la llista de grupos pa %s, yá esiste"
+
+#: plugins/sudoers/pwutil.c:849 plugins/sudoers/pwutil.c:901
+#: plugins/sudoers/pwutil.c:953 plugins/sudoers/pwutil.c:1006
+#, c-format
+msgid "unable to cache group list for %s, out of memory"
+msgstr "nun pue atroxase na caché la llista de grupos pa %s, nun hai memoria"
+
+#: plugins/sudoers/pwutil.c:890
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:995
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:120 plugins/sudoers/set_perms.c:478
+#: plugins/sudoers/set_perms.c:921 plugins/sudoers/set_perms.c:1254
+#: plugins/sudoers/set_perms.c:1573
+msgid "perm stack overflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:128 plugins/sudoers/set_perms.c:409
+#: plugins/sudoers/set_perms.c:486 plugins/sudoers/set_perms.c:788
+#: plugins/sudoers/set_perms.c:929 plugins/sudoers/set_perms.c:1178
+#: plugins/sudoers/set_perms.c:1262 plugins/sudoers/set_perms.c:1506
+#: plugins/sudoers/set_perms.c:1581 plugins/sudoers/set_perms.c:1672
+msgid "perm stack underflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:187 plugins/sudoers/set_perms.c:532
+#: plugins/sudoers/set_perms.c:1315 plugins/sudoers/set_perms.c:1614
+msgid "unable to change to root gid"
+msgstr "nun pue camudase'l GID de root"
+
+#: plugins/sudoers/set_perms.c:278 plugins/sudoers/set_perms.c:629
+#: plugins/sudoers/set_perms.c:1060 plugins/sudoers/set_perms.c:1392
+msgid "unable to change to runas gid"
+msgstr "nun pue camudase'l GID de runas"
+
+#: plugins/sudoers/set_perms.c:283 plugins/sudoers/set_perms.c:634
+#: plugins/sudoers/set_perms.c:1065 plugins/sudoers/set_perms.c:1397
+msgid "unable to set runas group vector"
+msgstr "nun pue afitase'l vector de grupos de runas"
+
+#: plugins/sudoers/set_perms.c:294 plugins/sudoers/set_perms.c:645
+#: plugins/sudoers/set_perms.c:1074 plugins/sudoers/set_perms.c:1406
+msgid "unable to change to runas uid"
+msgstr "nun pue camudase l'UID de runas"
+
+#: plugins/sudoers/set_perms.c:312 plugins/sudoers/set_perms.c:663
+#: plugins/sudoers/set_perms.c:1090 plugins/sudoers/set_perms.c:1422
+msgid "unable to change to sudoers gid"
+msgstr "nun pue camudase'l GID de sudoers"
+
+#: plugins/sudoers/set_perms.c:396 plugins/sudoers/set_perms.c:775
+#: plugins/sudoers/set_perms.c:1165 plugins/sudoers/set_perms.c:1493
+#: plugins/sudoers/set_perms.c:1659
+msgid "too many processes"
+msgstr "milenta procesos"
+
+#: plugins/sudoers/solaris_audit.c:58
+msgid "unable to get current working directory"
+msgstr "nun pue consiguise'l direutoriu actual de trabayu"
+
+#: plugins/sudoers/solaris_audit.c:66
+#, c-format
+msgid "truncated audit path user_cmnd: %s"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:73
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:122
+msgid "audit_failure message too long"
+msgstr "el mensaxe d'audit_failure ye pergrande"
+
+#: plugins/sudoers/sssd.c:565
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "nun pue aniciase la fonte SSS. ¿Ta SSSD instaláu nel sistema?"
+
+#: plugins/sudoers/sssd.c:573 plugins/sudoers/sssd.c:582
+#: plugins/sudoers/sssd.c:591 plugins/sudoers/sssd.c:600
+#: plugins/sudoers/sssd.c:609
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "nun pue alcontrase'l símbolu «%s» en %s"
+
+#: plugins/sudoers/sudoers.c:210 plugins/sudoers/sudoers.c:866
+msgid "problem with defaults entries"
+msgstr "problema coles entraes predeterminaes"
+
+#: plugins/sudoers/sudoers.c:214
+msgid "no valid sudoers sources found, quitting"
+msgstr "nun s'alcontró denguna fonte de sudoers válida, colando"
+
+#: plugins/sudoers/sudoers.c:252
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers especifica que root nun tien permisu pa usar sudo"
+
+#: plugins/sudoers/sudoers.c:310
+msgid "you are not permitted to use the -C option"
+msgstr "nun tienes permisu pa usar la opción -C"
+
+#: plugins/sudoers/sudoers.c:357
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:372
+msgid "no tty"
+msgstr "nun hai denguna TTY"
+
+#: plugins/sudoers/sudoers.c:373
+msgid "sorry, you must have a tty to run sudo"
+msgstr "perdona pero has tener una tty pa executar sudo"
+
+#: plugins/sudoers/sudoers.c:435
+msgid "command in current directory"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:454
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "perdona pero nun tienes permisu p'afitar una escosa del tiempu d'espera de los comandos"
+
+#: plugins/sudoers/sudoers.c:462
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "perdona pero nun tienes permisu pa calternet l'entornu"
+
+#: plugins/sudoers/sudoers.c:810
+msgid "command too long"
+msgstr "el comandu ye perllargu"
+
+#: plugins/sudoers/sudoers.c:942
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s nun ye un ficheru regular"
+
+#: plugins/sudoers/sudoers.c:946 plugins/sudoers/timestamp.c:259 toke.l:967
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s ye propiedá del UID %u, debería ser %u"
+
+#: plugins/sudoers/sudoers.c:950 toke.l:972
+#, c-format
+msgid "%s is world writable"
+msgstr "%s ye escribible por tol mundu"
+
+#: plugins/sudoers/sudoers.c:954 toke.l:975
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s ye propiedá del GID %u, debería ser %u"
+
+#: plugins/sudoers/sudoers.c:987
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "namái root pue usar «-c %s»"
+
+#: plugins/sudoers/sudoers.c:1006
+#, c-format
+msgid "unknown login class: %s"
+msgstr "desconozse la clas d'aniciu de sesión: %s"
+
+#: plugins/sudoers/sudoers.c:1091 plugins/sudoers/sudoers.c:1105
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "nun pue resolvese l'agospiu %s"
+
+#: plugins/sudoers/sudoreplay.c:250
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "opción non válida de peñera: %s"
+
+#: plugins/sudoers/sudoreplay.c:263
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "tiempu máximu d'espera non válidu: %s"
+
+#: plugins/sudoers/sudoreplay.c:286
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "fautor de velocidá non válidu: %s"
+
+#: plugins/sudoers/sudoreplay.c:321
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s/timing: %s"
+msgstr "%s/%.2s/%.2s/%.2s/sincronía: %s"
+
+#: plugins/sudoers/sudoreplay.c:327
+#, c-format
+msgid "%s/%s/timing: %s"
+msgstr "%s/%s/sincronía: %s"
+
+#: plugins/sudoers/sudoreplay.c:343
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Reproduciendo la sesión de sudo: %s"
+
+#: plugins/sudoers/sudoreplay.c:541 plugins/sudoers/sudoreplay.c:588
+#: plugins/sudoers/sudoreplay.c:785 plugins/sudoers/sudoreplay.c:894
+#: plugins/sudoers/sudoreplay.c:979 plugins/sudoers/sudoreplay.c:994
+#: plugins/sudoers/sudoreplay.c:1001 plugins/sudoers/sudoreplay.c:1008
+#: plugins/sudoers/sudoreplay.c:1015 plugins/sudoers/sudoreplay.c:1022
+#: plugins/sudoers/sudoreplay.c:1170
+msgid "unable to add event to queue"
+msgstr "nun pue amestase l'eventu a la cola"
+
+#: plugins/sudoers/sudoreplay.c:656
+msgid "unable to set tty to raw mode"
+msgstr "nun pue afitase'l mou en bruto a la TTY"
+
+#: plugins/sudoers/sudoreplay.c:707
+#, c-format
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr "Alvertencia: la terminal ye mui pequeña como pa reproducir el rexistru afayadizamente.\n"
+
+#: plugins/sudoers/sudoreplay.c:708
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "La xeometría del rexistru ye %d x %d, la de la to terminal ye %d x %d"
+
+#: plugins/sudoers/sudoreplay.c:736
+msgid "Replay finished, press any key to restore the terminal."
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:768
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1204 plugins/sudoers/sudoreplay.c:1229
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "espresión ambigua «%s»"
+
+#: plugins/sudoers/sudoreplay.c:1251
+msgid "unmatched ')' in expression"
+msgstr "nun s'abrió «)» na espresión"
+
+#: plugins/sudoers/sudoreplay.c:1255
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "desconozse'l términu de gueta «%s»"
+
+#: plugins/sudoers/sudoreplay.c:1270
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s rique un argumentu"
+
+#: plugins/sudoers/sudoreplay.c:1273 plugins/sudoers/sudoreplay.c:1514
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr "espresión regular non válida: %s"
+
+#: plugins/sudoers/sudoreplay.c:1277
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "nun pudo analizase la data «%s»"
+
+#: plugins/sudoers/sudoreplay.c:1286
+msgid "unmatched '(' in expression"
+msgstr "nun se zarró «(» na espresión"
+
+#: plugins/sudoers/sudoreplay.c:1288
+msgid "illegal trailing \"or\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1290
+msgid "illegal trailing \"!\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1340
+#, c-format
+msgid "unknown search type %d"
+msgstr "desconozse la triba de gueta %d"
+
+#: plugins/sudoers/sudoreplay.c:1607
+#, fuzzy, c-format
+#| msgid "usage: %s [-hnR] [-d dir] [-m num] [-s num] ID\n"
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "usu: %s [-hnR] [-d direutoriu] [-m númberu] [-s númberu] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1610
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "usu: %s [-h] [-d direutoriu] -l [espresión de gueta]\n"
+
+#: plugins/sudoers/sudoreplay.c:1619
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - reproduz los rexistros de sesión de sudo\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1621
+#, fuzzy
+#| msgid ""
+#| "\n"
+#| "Options:\n"
+#| " -d, --directory=dir specify directory for session logs\n"
+#| " -f, --filter=filter specify which I/O type(s) to display\n"
+#| " -h, --help display help message and exit\n"
+#| " -l, --list list available session IDs, with optional expression\n"
+#| " -m, --max-wait=num max number of seconds to wait between events\n"
+#| " -s, --speed=num speed up or slow down output\n"
+#| " -V, --version display version information and exit"
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Opciones:\n"
+" -d, --directory=dir especifica'l direutoriu pa los rexistros de la sesión\n"
+" -f, --filter=filter especifica les tribes d'E/S que van amosase\n"
+" -h, --help amuesa esti mensaxe d'ayuda y cola\n"
+" -l, --list llista les IDs de sesión disponibles, con una espresión opcional\n"
+" -m, --max-wait=num númberu máximu de segundos a esperar ente eventos\n"
+" -s, --speed=num acelera o vuelve lenta la salida\n"
+" -V, --version amuesa la información de la versión y cola"
+
+#: plugins/sudoers/testsudoers.c:362
+msgid "\thost unmatched"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:365
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Comandu permitíu"
+
+#: plugins/sudoers/testsudoers.c:366
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Comandu ñegáu"
+
+#: plugins/sudoers/testsudoers.c:366
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Comandu ensin coincidencies"
+
+#: plugins/sudoers/timestamp.c:267
+#, c-format
+msgid "%s is group writable"
+msgstr "%s ye escribible pol grupu"
+
+#: plugins/sudoers/timestamp.c:343
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:829 plugins/sudoers/timestamp.c:921
+#: plugins/sudoers/visudo.c:498 plugins/sudoers/visudo.c:504
+msgid "unable to read the clock"
+msgstr "nun pue lleese'l reló"
+
+#: plugins/sudoers/timestamp.c:840
+msgid "ignoring time stamp from the future"
+msgstr "inorando la marca de tiempu del futuru"
+
+#: plugins/sudoers/timestamp.c:863
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:985
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "nun pue bloquiase'l ficheru de marque de tiempu %s"
+
+#: plugins/sudoers/timestamp.c:1029 plugins/sudoers/timestamp.c:1049
+#, c-format
+msgid "lecture status path too long: %s/%s"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:232
+msgid "the -x option will be removed in a future release"
+msgstr "la opción -x va desaniciase en llanzamientos futuros"
+
+#: plugins/sudoers/visudo.c:233
+msgid "please consider using the cvtsudoers utility instead"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:284 plugins/sudoers/visudo.c:666
+#, c-format
+msgid "press return to edit %s: "
+msgstr "primi retrocesu pa editar %s:"
+
+#: plugins/sudoers/visudo.c:345
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "l'editor especificáu (%s) nun esiste"
+
+#: plugins/sudoers/visudo.c:347
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "nun s'alcontró dengún editor (camín del editor = %s)"
+
+#: plugins/sudoers/visudo.c:457 plugins/sudoers/visudo.c:465
+msgid "write error"
+msgstr "fallu d'escritura"
+
+#: plugins/sudoers/visudo.c:511
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "nun pue facese stat al ficheru temporal (%s), %s nun camudó"
+
+#: plugins/sudoers/visudo.c:518
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:524
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "falló l'editor (%s), %s nun camudó"
+
+#: plugins/sudoers/visudo.c:546
+#, c-format
+msgid "%s unchanged"
+msgstr "%s nun camudó"
+
+#: plugins/sudoers/visudo.c:605
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "nun pue abrise de nueves el ficheru temporal (%s), %s nun camudó."
+
+#: plugins/sudoers/visudo.c:617
+#, c-format
+msgid "unabled to parse temporary file (%s), unknown error"
+msgstr "nun pudo analizase'l ficheru temporal (%s), fallu desconocíu"
+
+#: plugins/sudoers/visudo.c:655
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr "fallu internu, ¡nun pue alcontrase %s na llista!"
+
+#: plugins/sudoers/visudo.c:735 plugins/sudoers/visudo.c:744
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "nun pue afitase l'UID o GID de %s a (%u, %u)"
+
+#: plugins/sudoers/visudo.c:767
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s y %s nun tán nel mesmu sistema de ficheros, usando mv pa renomar"
+
+#: plugins/sudoers/visudo.c:781
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "falló'l comandu: «%s %s %s», %s nun camudó"
+
+#: plugins/sudoers/visudo.c:791
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "fallu al renomar %s, %s nun camudó"
+
+#: plugins/sudoers/visudo.c:812
+msgid "What now? "
+msgstr "¿Y agora qué?"
+
+#: plugins/sudoers/visudo.c:826
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:872
+#, c-format
+msgid "unable to run %s"
+msgstr "nun pue executase %s"
+
+#: plugins/sudoers/visudo.c:902
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:909
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:966 plugins/sudoers/visudo.c:973
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:992
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s ta ocupáu, volvi tentalo más sero"
+
+#: plugins/sudoers/visudo.c:995
+#, fuzzy, c-format
+#| msgid "unable to open %s"
+msgid "unable to lock %s"
+msgstr "nun pue abrise %s"
+
+#: plugins/sudoers/visudo.c:996
+msgid "Edit anyway? [y/N]"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1080
+#, c-format
+msgid "Error: %s:%d cycle in %s \"%s\""
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1081
+#, c-format
+msgid "Warning: %s:%d cycle in %s \"%s\""
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1085
+#, c-format
+msgid "Error: %s:%d %s \"%s\" referenced but not defined"
+msgstr "Fallu: %s:%d %s «%s» referencióse pero nun se definió"
+
+#: plugins/sudoers/visudo.c:1086
+#, c-format
+msgid "Warning: %s:%d %s \"%s\" referenced but not defined"
+msgstr "Alvertencia: %s:%d %s «%s» referencióse pero nun se definió"
+
+#: plugins/sudoers/visudo.c:1177
+#, c-format
+msgid "Warning: %s:%d unused %s \"%s\""
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1292
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - edita de mou seguru'l ficheru sudoers\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1294
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Opciones:\n"
+" -c, --check mou de namái comprobación\n"
+" -f, --file=sudoers especifica l'allugamientu del ficheru sudoers\n"
+" -h, --help amuesa esti mensaxe d'ayuda y cola\n"
+" -q, --quiet mensaxes menos detallaos (silenciosos) de los fallos de sintaxis\n"
+" -s, --strict comprobación estricta de la sintaxis\n"
+" -V, --version amuesa la información de la versión y cola\n"
+
+#: toke.l:941
+msgid "too many levels of includes"
+msgstr "milenta niveles d'inclusión"
diff --git a/plugins/sudoers/po/ca.mo b/plugins/sudoers/po/ca.mo
new file mode 100644
index 0000000..e6beade
--- /dev/null
+++ b/plugins/sudoers/po/ca.mo
Binary files differ
diff --git a/plugins/sudoers/po/ca.po b/plugins/sudoers/po/ca.po
new file mode 100644
index 0000000..1914e83
--- /dev/null
+++ b/plugins/sudoers/po/ca.po
@@ -0,0 +1,3260 @@
+# Portable object template file for the sudoers plugin
+# This file is put in the public domain.
+# Walter Garcia-Fontes <walter.garcia@upf.edu>, 2021.
+#
+# Glossari
+#
+# principal - Es refereix a "Principals may represent users, network hosts, or network services. A principal that corresponds to a network host is called a host principal", s'ha traduït com a "principal".
+# tty - el terminal, això prové de l'acrònim en anglès per a teletip (tty) i ara s'usa per a un terminal obert on es pot entrar informació
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.9.6b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2021-03-02 19:29-0700\n"
+"PO-Revision-Date: 2021-04-27 11:00+0200\n"
+"Last-Translator: Walter Garcia-Fontes <walter.garcia@upf.edu>\n"
+"Language-Team: Catalan <ca@dodds.net>\n"
+"Language: ca\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: confstr.sh:1 gram.y:1183
+msgid "syntax error"
+msgstr "error de sintaxi"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "contrasenya de %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] contrasenya per a %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Contrasenya: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** Informació de SEGURETAT per a %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Ho sentim, proveu un altre cop."
+
+#: gram.y:233 gram.y:300 gram.y:309 gram.y:318 gram.y:328 gram.y:338
+#: gram.y:362 gram.y:389 gram.y:398 gram.y:406 gram.y:415 gram.y:424
+#: gram.y:496 gram.y:506 gram.y:518 gram.y:562 gram.y:571 gram.y:580
+#: gram.y:589 gram.y:619 gram.y:716 gram.y:724 gram.y:735 gram.y:747
+#: gram.y:766 gram.y:914 gram.y:922 gram.y:932 gram.y:938 gram.y:1060
+#: gram.y:1069 gram.y:1077 gram.y:1086 gram.y:1095 gram.y:1124 gram.y:1133
+#: gram.y:1141 gram.y:1231 gram.y:1343 gram.y:1650 gram.y:1700
+#: lib/eventlog/eventlog.c:260 lib/eventlog/eventlog.c:333
+#: lib/eventlog/eventlog.c:733 lib/eventlog/eventlog.c:797
+#: lib/eventlog/eventlog.c:1053 lib/iolog/iolog_json.c:125
+#: lib/iolog/iolog_json.c:330 lib/iolog/iolog_json.c:360
+#: lib/iolog/iolog_json.c:503 lib/iolog/iolog_legacy.c:100
+#: lib/iolog/iolog_legacy.c:111 lib/iolog/iolog_legacy.c:123
+#: lib/iolog/iolog_legacy.c:133 lib/iolog/iolog_legacy.c:139
+#: lib/iolog/iolog_loginfo.c:76 lib/iolog/iolog_loginfo.c:210
+#: logsrvd/sendlog.c:496 plugins/sudoers/audit.c:115
+#: plugins/sudoers/audit.c:263 plugins/sudoers/auth/bsdauth.c:143
+#: plugins/sudoers/auth/kerb5.c:118 plugins/sudoers/auth/kerb5.c:144
+#: plugins/sudoers/auth/pam.c:689 plugins/sudoers/auth/rfc1938.c:111
+#: plugins/sudoers/auth/sia.c:59 plugins/sudoers/check_aliases.c:95
+#: plugins/sudoers/cvtsudoers.c:119 plugins/sudoers/cvtsudoers.c:160
+#: plugins/sudoers/cvtsudoers.c:177 plugins/sudoers/cvtsudoers.c:188
+#: plugins/sudoers/cvtsudoers.c:300 plugins/sudoers/cvtsudoers.c:428
+#: plugins/sudoers/cvtsudoers.c:561 plugins/sudoers/cvtsudoers.c:578
+#: plugins/sudoers/cvtsudoers.c:646 plugins/sudoers/cvtsudoers.c:761
+#: plugins/sudoers/cvtsudoers.c:769 plugins/sudoers/cvtsudoers.c:1183
+#: plugins/sudoers/cvtsudoers.c:1187 plugins/sudoers/cvtsudoers.c:1289
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:151
+#: plugins/sudoers/cvtsudoers_ldif.c:194 plugins/sudoers/cvtsudoers_ldif.c:235
+#: plugins/sudoers/cvtsudoers_ldif.c:300 plugins/sudoers/cvtsudoers_ldif.c:371
+#: plugins/sudoers/cvtsudoers_ldif.c:421 plugins/sudoers/cvtsudoers_ldif.c:429
+#: plugins/sudoers/cvtsudoers_ldif.c:440 plugins/sudoers/cvtsudoers_ldif.c:447
+#: plugins/sudoers/cvtsudoers_ldif.c:460 plugins/sudoers/cvtsudoers_ldif.c:468
+#: plugins/sudoers/cvtsudoers_ldif.c:615 plugins/sudoers/defaults.c:638
+#: plugins/sudoers/defaults.c:933 plugins/sudoers/defaults.c:1108
+#: plugins/sudoers/editor.c:181 plugins/sudoers/env.c:262
+#: plugins/sudoers/exptilde.c:92 plugins/sudoers/filedigest.c:54
+#: plugins/sudoers/filedigest.c:70 plugins/sudoers/gc.c:57
+#: plugins/sudoers/group_plugin.c:133 plugins/sudoers/interfaces.c:72
+#: plugins/sudoers/iolog.c:609 plugins/sudoers/iolog.c:626
+#: plugins/sudoers/ldap.c:184 plugins/sudoers/ldap.c:422
+#: plugins/sudoers/ldap.c:432 plugins/sudoers/ldap.c:437
+#: plugins/sudoers/ldap.c:441 plugins/sudoers/ldap.c:453
+#: plugins/sudoers/ldap.c:744 plugins/sudoers/ldap.c:908
+#: plugins/sudoers/ldap.c:1281 plugins/sudoers/ldap.c:1709
+#: plugins/sudoers/ldap.c:1746 plugins/sudoers/ldap.c:1827
+#: plugins/sudoers/ldap.c:1962 plugins/sudoers/ldap.c:2063
+#: plugins/sudoers/ldap.c:2079 plugins/sudoers/ldap_conf.c:218
+#: plugins/sudoers/ldap_conf.c:249 plugins/sudoers/ldap_conf.c:301
+#: plugins/sudoers/ldap_conf.c:337 plugins/sudoers/ldap_conf.c:441
+#: plugins/sudoers/ldap_conf.c:456 plugins/sudoers/ldap_conf.c:553
+#: plugins/sudoers/ldap_conf.c:586 plugins/sudoers/ldap_conf.c:678
+#: plugins/sudoers/ldap_conf.c:760 plugins/sudoers/ldap_util.c:326
+#: plugins/sudoers/ldap_util.c:333 plugins/sudoers/ldap_util.c:648
+#: plugins/sudoers/linux_audit.c:86 plugins/sudoers/log_client.c:105
+#: plugins/sudoers/log_client.c:381 plugins/sudoers/log_client.c:686
+#: plugins/sudoers/log_client.c:704 plugins/sudoers/log_client.c:1413
+#: plugins/sudoers/log_client.c:1626 plugins/sudoers/log_client.c:1950
+#: plugins/sudoers/log_client.c:2007 plugins/sudoers/logging.c:100
+#: plugins/sudoers/logging.c:166 plugins/sudoers/logging.c:426
+#: plugins/sudoers/logging.c:446 plugins/sudoers/logging.c:527
+#: plugins/sudoers/match_command.c:286 plugins/sudoers/match_command.c:484
+#: plugins/sudoers/match_command.c:533 plugins/sudoers/match_command.c:604
+#: plugins/sudoers/match_command.c:650 plugins/sudoers/match_digest.c:93
+#: plugins/sudoers/parse.c:199 plugins/sudoers/parse.c:216
+#: plugins/sudoers/parse.c:236 plugins/sudoers/parse.c:253
+#: plugins/sudoers/parse.c:276 plugins/sudoers/parse.c:287
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:260
+#: plugins/sudoers/parse_ldif.c:265 plugins/sudoers/parse_ldif.c:341
+#: plugins/sudoers/parse_ldif.c:352 plugins/sudoers/parse_ldif.c:379
+#: plugins/sudoers/parse_ldif.c:396 plugins/sudoers/parse_ldif.c:408
+#: plugins/sudoers/parse_ldif.c:412 plugins/sudoers/parse_ldif.c:426
+#: plugins/sudoers/parse_ldif.c:483 plugins/sudoers/parse_ldif.c:596
+#: plugins/sudoers/parse_ldif.c:626 plugins/sudoers/parse_ldif.c:651
+#: plugins/sudoers/parse_ldif.c:709 plugins/sudoers/parse_ldif.c:726
+#: plugins/sudoers/parse_ldif.c:754 plugins/sudoers/parse_ldif.c:761
+#: plugins/sudoers/policy.c:543 plugins/sudoers/policy.c:890
+#: plugins/sudoers/prompt.c:93 plugins/sudoers/pwutil.c:195
+#: plugins/sudoers/pwutil.c:266 plugins/sudoers/pwutil.c:344
+#: plugins/sudoers/pwutil.c:518 plugins/sudoers/pwutil.c:583
+#: plugins/sudoers/pwutil.c:655 plugins/sudoers/pwutil.c:854
+#: plugins/sudoers/pwutil.c:910 plugins/sudoers/pwutil.c:954
+#: plugins/sudoers/pwutil.c:1011 plugins/sudoers/sssd.c:145
+#: plugins/sudoers/sssd.c:407 plugins/sudoers/sssd.c:470
+#: plugins/sudoers/sssd.c:514 plugins/sudoers/sssd.c:561
+#: plugins/sudoers/sssd.c:754 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/stubs.c:111 plugins/sudoers/stubs.c:119
+#: plugins/sudoers/sudoers.c:299 plugins/sudoers/sudoers.c:325
+#: plugins/sudoers/sudoers.c:374 plugins/sudoers/sudoers.c:384
+#: plugins/sudoers/sudoers.c:425 plugins/sudoers/sudoers.c:787
+#: plugins/sudoers/sudoers.c:922 plugins/sudoers/sudoers.c:975
+#: plugins/sudoers/sudoers.c:1241 plugins/sudoers/sudoreplay.c:552
+#: plugins/sudoers/sudoreplay.c:555 plugins/sudoers/sudoreplay.c:1259
+#: plugins/sudoers/sudoreplay.c:1469 plugins/sudoers/sudoreplay.c:1473
+#: plugins/sudoers/testsudoers.c:128 plugins/sudoers/testsudoers.c:225
+#: plugins/sudoers/testsudoers.c:242 plugins/sudoers/testsudoers.c:581
+#: plugins/sudoers/timestamp.c:422 plugins/sudoers/timestamp.c:466
+#: plugins/sudoers/timestamp.c:967 plugins/sudoers/timestamp.c:1105
+#: plugins/sudoers/toke_util.c:77 plugins/sudoers/toke_util.c:105
+#: plugins/sudoers/toke_util.c:130 plugins/sudoers/toke_util.c:155
+#: plugins/sudoers/toke_util.c:193 plugins/sudoers/tsdump.c:123
+#: plugins/sudoers/visudo.c:143 plugins/sudoers/visudo.c:321
+#: plugins/sudoers/visudo.c:327 plugins/sudoers/visudo.c:433
+#: plugins/sudoers/visudo.c:609 plugins/sudoers/visudo.c:926
+#: plugins/sudoers/visudo.c:999 toke.l:928 toke.l:1057 toke.l:1117
+msgid "unable to allocate memory"
+msgstr "no es pot assignar memòria"
+
+#: gram.y:613
+msgid "a digest requires a path name"
+msgstr "au un resum li cal un nom de camí"
+
+#: gram.y:643
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "els valores per a «CWD» han de començar amb «/», «~» o «*»"
+
+#: gram.y:655
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "els valors per a «CHROOT» han de començar amb «/», «~», o «*»"
+
+#: gram.y:786
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "error de sintaxi, la paraula reservada %s s'ha usat com un nom d'àlies"
+
+#: gram.y:809
+msgid "invalid notbefore value"
+msgstr "valor notbefore no vàlid"
+
+#: gram.y:818
+msgid "invalid notafter value"
+msgstr "valor invàlid de notafter"
+
+#: gram.y:828 plugins/sudoers/policy.c:339
+msgid "timeout value too large"
+msgstr "valor massa llarg de temps d'espera"
+
+#: gram.y:830 plugins/sudoers/policy.c:341
+msgid "invalid timeout value"
+msgstr "valor no vàlid de temps d'espera"
+
+#: gram.y:1185
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: gram.y:1229
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "L'àlies «%s» ja està definit"
+
+#: gram.y:1650 gram.y:1700 lib/eventlog/eventlog.c:260
+#: lib/eventlog/eventlog.c:733 lib/eventlog/eventlog.c:795
+#: lib/eventlog/eventlog.c:796 lib/eventlog/eventlog.c:1053
+#: lib/iolog/iolog_json.c:125 lib/iolog/iolog_json.c:329
+#: lib/iolog/iolog_json.c:360 lib/iolog/iolog_json.c:503
+#: lib/iolog/iolog_legacy.c:100 lib/iolog/iolog_legacy.c:111
+#: lib/iolog/iolog_legacy.c:123 lib/iolog/iolog_legacy.c:133
+#: lib/iolog/iolog_legacy.c:139 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:210 logsrvd/logsrvd.c:1291 logsrvd/logsrvd.c:1304
+#: logsrvd/logsrvd.c:1349 logsrvd/sendlog.c:496 logsrvd/sendlog.c:1337
+#: logsrvd/sendlog.c:1344 logsrvd/sendlog.c:1762 plugins/sudoers/audit.c:115
+#: plugins/sudoers/audit.c:263 plugins/sudoers/auth/pam.c:502
+#: plugins/sudoers/auth/pam.c:689 plugins/sudoers/auth/rfc1938.c:111
+#: plugins/sudoers/check_aliases.c:95 plugins/sudoers/cvtsudoers.c:119
+#: plugins/sudoers/cvtsudoers.c:159 plugins/sudoers/cvtsudoers.c:176
+#: plugins/sudoers/cvtsudoers.c:187 plugins/sudoers/cvtsudoers.c:299
+#: plugins/sudoers/cvtsudoers.c:427 plugins/sudoers/cvtsudoers.c:560
+#: plugins/sudoers/cvtsudoers.c:577 plugins/sudoers/cvtsudoers.c:646
+#: plugins/sudoers/cvtsudoers.c:761 plugins/sudoers/cvtsudoers.c:768
+#: plugins/sudoers/cvtsudoers.c:1183 plugins/sudoers/cvtsudoers.c:1187
+#: plugins/sudoers/cvtsudoers.c:1289 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:150 plugins/sudoers/cvtsudoers_ldif.c:193
+#: plugins/sudoers/cvtsudoers_ldif.c:234 plugins/sudoers/cvtsudoers_ldif.c:299
+#: plugins/sudoers/cvtsudoers_ldif.c:370 plugins/sudoers/cvtsudoers_ldif.c:420
+#: plugins/sudoers/cvtsudoers_ldif.c:428 plugins/sudoers/cvtsudoers_ldif.c:439
+#: plugins/sudoers/cvtsudoers_ldif.c:446 plugins/sudoers/cvtsudoers_ldif.c:459
+#: plugins/sudoers/cvtsudoers_ldif.c:467 plugins/sudoers/cvtsudoers_ldif.c:614
+#: plugins/sudoers/defaults.c:638 plugins/sudoers/defaults.c:933
+#: plugins/sudoers/defaults.c:1108 plugins/sudoers/editor.c:181
+#: plugins/sudoers/env.c:262 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:54 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:132
+#: plugins/sudoers/interfaces.c:72 plugins/sudoers/iolog.c:609
+#: plugins/sudoers/iolog.c:626 plugins/sudoers/ldap.c:184
+#: plugins/sudoers/ldap.c:422 plugins/sudoers/ldap.c:432
+#: plugins/sudoers/ldap.c:437 plugins/sudoers/ldap.c:441
+#: plugins/sudoers/ldap.c:453 plugins/sudoers/ldap.c:744
+#: plugins/sudoers/ldap.c:908 plugins/sudoers/ldap.c:1281
+#: plugins/sudoers/ldap.c:1709 plugins/sudoers/ldap.c:1746
+#: plugins/sudoers/ldap.c:1827 plugins/sudoers/ldap.c:1962
+#: plugins/sudoers/ldap.c:2063 plugins/sudoers/ldap.c:2079
+#: plugins/sudoers/ldap_conf.c:218 plugins/sudoers/ldap_conf.c:249
+#: plugins/sudoers/ldap_conf.c:301 plugins/sudoers/ldap_conf.c:337
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:553 plugins/sudoers/ldap_conf.c:586
+#: plugins/sudoers/ldap_conf.c:677 plugins/sudoers/ldap_conf.c:760
+#: plugins/sudoers/ldap_util.c:325 plugins/sudoers/ldap_util.c:332
+#: plugins/sudoers/ldap_util.c:648 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:105 plugins/sudoers/log_client.c:214
+#: plugins/sudoers/log_client.c:235 plugins/sudoers/log_client.c:248
+#: plugins/sudoers/log_client.c:381 plugins/sudoers/log_client.c:686
+#: plugins/sudoers/log_client.c:704 plugins/sudoers/log_client.c:1413
+#: plugins/sudoers/log_client.c:1626 plugins/sudoers/log_client.c:1950
+#: plugins/sudoers/log_client.c:2007 plugins/sudoers/logging.c:100
+#: plugins/sudoers/logging.c:165 plugins/sudoers/logging.c:166
+#: plugins/sudoers/logging.c:425 plugins/sudoers/logging.c:445
+#: plugins/sudoers/logging.c:527 plugins/sudoers/match_command.c:285
+#: plugins/sudoers/match_command.c:483 plugins/sudoers/match_command.c:532
+#: plugins/sudoers/match_command.c:604 plugins/sudoers/match_command.c:649
+#: plugins/sudoers/match_digest.c:93 plugins/sudoers/parse.c:198
+#: plugins/sudoers/parse.c:215 plugins/sudoers/parse.c:235
+#: plugins/sudoers/parse.c:252 plugins/sudoers/parse.c:275
+#: plugins/sudoers/parse.c:286 plugins/sudoers/parse_ldif.c:152
+#: plugins/sudoers/parse_ldif.c:183 plugins/sudoers/parse_ldif.c:252
+#: plugins/sudoers/parse_ldif.c:259 plugins/sudoers/parse_ldif.c:264
+#: plugins/sudoers/parse_ldif.c:340 plugins/sudoers/parse_ldif.c:351
+#: plugins/sudoers/parse_ldif.c:378 plugins/sudoers/parse_ldif.c:395
+#: plugins/sudoers/parse_ldif.c:407 plugins/sudoers/parse_ldif.c:411
+#: plugins/sudoers/parse_ldif.c:425 plugins/sudoers/parse_ldif.c:483
+#: plugins/sudoers/parse_ldif.c:596 plugins/sudoers/parse_ldif.c:625
+#: plugins/sudoers/parse_ldif.c:650 plugins/sudoers/parse_ldif.c:708
+#: plugins/sudoers/parse_ldif.c:725 plugins/sudoers/parse_ldif.c:753
+#: plugins/sudoers/parse_ldif.c:760 plugins/sudoers/policy.c:149
+#: plugins/sudoers/policy.c:158 plugins/sudoers/policy.c:167
+#: plugins/sudoers/policy.c:193 plugins/sudoers/policy.c:324
+#: plugins/sudoers/policy.c:339 plugins/sudoers/policy.c:341
+#: plugins/sudoers/policy.c:371 plugins/sudoers/policy.c:380
+#: plugins/sudoers/policy.c:428 plugins/sudoers/policy.c:438
+#: plugins/sudoers/policy.c:447 plugins/sudoers/policy.c:456
+#: plugins/sudoers/policy.c:543 plugins/sudoers/policy.c:890
+#: plugins/sudoers/prompt.c:93 plugins/sudoers/pwutil.c:195
+#: plugins/sudoers/pwutil.c:266 plugins/sudoers/pwutil.c:344
+#: plugins/sudoers/pwutil.c:518 plugins/sudoers/pwutil.c:583
+#: plugins/sudoers/pwutil.c:655 plugins/sudoers/pwutil.c:854
+#: plugins/sudoers/pwutil.c:910 plugins/sudoers/pwutil.c:954
+#: plugins/sudoers/pwutil.c:1011 plugins/sudoers/set_perms.c:359
+#: plugins/sudoers/set_perms.c:698 plugins/sudoers/set_perms.c:1061
+#: plugins/sudoers/set_perms.c:1364 plugins/sudoers/set_perms.c:1529
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:407
+#: plugins/sudoers/sssd.c:470 plugins/sudoers/sssd.c:514
+#: plugins/sudoers/sssd.c:561 plugins/sudoers/sssd.c:754
+#: plugins/sudoers/strvec_join.c:53 plugins/sudoers/stubs.c:111
+#: plugins/sudoers/stubs.c:119 plugins/sudoers/sudoers.c:299
+#: plugins/sudoers/sudoers.c:325 plugins/sudoers/sudoers.c:374
+#: plugins/sudoers/sudoers.c:384 plugins/sudoers/sudoers.c:425
+#: plugins/sudoers/sudoers.c:787 plugins/sudoers/sudoers.c:922
+#: plugins/sudoers/sudoers.c:975 plugins/sudoers/sudoers.c:1241
+#: plugins/sudoers/sudoreplay.c:552 plugins/sudoers/sudoreplay.c:555
+#: plugins/sudoers/sudoreplay.c:1259 plugins/sudoers/sudoreplay.c:1469
+#: plugins/sudoers/sudoreplay.c:1473 plugins/sudoers/testsudoers.c:128
+#: plugins/sudoers/testsudoers.c:225 plugins/sudoers/testsudoers.c:242
+#: plugins/sudoers/testsudoers.c:581 plugins/sudoers/timestamp.c:422
+#: plugins/sudoers/timestamp.c:466 plugins/sudoers/timestamp.c:967
+#: plugins/sudoers/timestamp.c:1105 plugins/sudoers/toke_util.c:77
+#: plugins/sudoers/toke_util.c:105 plugins/sudoers/toke_util.c:130
+#: plugins/sudoers/toke_util.c:154 plugins/sudoers/toke_util.c:193
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:143
+#: plugins/sudoers/visudo.c:321 plugins/sudoers/visudo.c:327
+#: plugins/sudoers/visudo.c:433 plugins/sudoers/visudo.c:609
+#: plugins/sudoers/visudo.c:926 plugins/sudoers/visudo.c:999 toke.l:928
+#: toke.l:1057 toke.l:1109 toke.l:1117
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:265 lib/iolog/iolog_json.c:509
+#: lib/iolog/iolog_json.c:512 lib/iolog/iolog_json.c:514
+#: plugins/sudoers/cvtsudoers_ldif.c:244 plugins/sudoers/cvtsudoers_ldif.c:251
+#: plugins/sudoers/cvtsudoers_ldif.c:571 plugins/sudoers/env.c:326
+#: plugins/sudoers/env.c:333 plugins/sudoers/env.c:444
+#: plugins/sudoers/iolog.c:631 plugins/sudoers/ldap.c:517
+#: plugins/sudoers/ldap.c:748 plugins/sudoers/ldap.c:1081
+#: plugins/sudoers/ldap_conf.c:222 plugins/sudoers/ldap_conf.c:312
+#: plugins/sudoers/linux_audit.c:92 plugins/sudoers/policy.c:573
+#: plugins/sudoers/policy.c:728 plugins/sudoers/policy.c:738
+#: plugins/sudoers/prompt.c:161 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/testsudoers.c:246 plugins/sudoers/toke_util.c:206
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "error intern, desbordament de %s"
+
+#: lib/eventlog/eventlog.c:324
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "no es pot duplicar l'entrada estàndard: %m"
+
+#: lib/eventlog/eventlog.c:366
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "no es pot executar %s: %m"
+
+#: lib/eventlog/eventlog.c:407 plugins/sudoers/auth/aix_auth.c:198
+msgid "unable to fork"
+msgstr "no es pot bifurcar"
+
+#: lib/eventlog/eventlog.c:415 lib/eventlog/eventlog.c:469
+#, c-format
+msgid "unable to fork: %m"
+msgstr "no est pot bifurcar: %m"
+
+#: lib/eventlog/eventlog.c:459
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "no es pot obrir la canonada: %m"
+
+#: lib/eventlog/eventlog.c:882
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:911
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (ordre continuada) %s"
+
+#: lib/iolog/iolog_json.c:115
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "s'esperava JSON_STRING, s'ha obtingut %d"
+
+#: lib/iolog/iolog_json.c:120
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY massa llarg"
+
+#: lib/iolog/iolog_json.c:352
+msgid "missing double quote in name"
+msgstr "cometes doble faltant al nom"
+
+#: lib/iolog/iolog_json.c:449
+msgid "missing JSON_OBJECT"
+msgstr "JSON_OBJECT faltant"
+
+#: lib/iolog/iolog_json.c:453
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "s'esperava JSON_OBJECT, s'ha obtingut %d"
+
+#: lib/iolog/iolog_json.c:599
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "pila json exhaurida (max %u marcs)"
+
+#: lib/iolog/iolog_json.c:673
+msgid "objects must consist of name:value pairs"
+msgstr "els objectes han de consistir de parelles nom:valor"
+
+#: lib/iolog/iolog_json.c:678 lib/iolog/iolog_json.c:709
+#: lib/iolog/iolog_json.c:753 lib/iolog/iolog_json.c:775
+#: lib/iolog/iolog_json.c:797 lib/iolog/iolog_json.c:819
+#: lib/iolog/iolog_json.c:841
+msgid "missing separator between values"
+msgstr "separador faltant entre valors"
+
+#: lib/iolog/iolog_json.c:693 lib/iolog/iolog_json.c:867
+msgid "unmatched close brace"
+msgstr "clau de tancament no concordant"
+
+#: lib/iolog/iolog_json.c:704
+msgid "unexpected array"
+msgstr "matriu no esperada"
+
+#: lib/iolog/iolog_json.c:724 lib/iolog/iolog_json.c:870
+msgid "unmatched close bracket"
+msgstr "parèntesi inesperat de tancament"
+
+#: lib/iolog/iolog_json.c:735
+msgid "unexpected string"
+msgstr "cadena de caràcters inesperada"
+
+#: lib/iolog/iolog_json.c:746
+msgid "missing colon after name"
+msgstr "dos punts inesperat"
+
+#: lib/iolog/iolog_json.c:767 lib/iolog/iolog_json.c:789
+msgid "unexpected boolean"
+msgstr "booleà inesperat"
+
+#: lib/iolog/iolog_json.c:811
+msgid "unexpected null"
+msgstr "null inesperat"
+
+#: lib/iolog/iolog_json.c:832
+msgid "unexpected number"
+msgstr "nombre inesperat"
+
+#: lib/iolog/iolog_json.c:879
+msgid "parse error"
+msgstr "error d'anàlisi"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: fitxer no vàlid de registre"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: no hi ha el camp de marca horària "
+
+#: lib/iolog/iolog_legacy.c:89
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: marca horària %s: %s"
+
+#: lib/iolog/iolog_legacy.c:96
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: no hi ha el camp d'usuari runas"
+
+#: lib/iolog/iolog_legacy.c:107
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: no hi ha el camp del grup runas"
+
+#: lib/iolog/iolog_legacy.c:118
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: no es troba el camp del grup runas"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s existeix però no és un directori (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:119 lib/iolog/iolog_mkdtemp.c:72
+#: plugins/sudoers/timestamp.c:205
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "no s'ha pogut mkdir %s"
+
+#: lib/iolog/iolog_mkdtemp.c:76 plugins/sudoers/visudo.c:726
+#: plugins/sudoers/visudo.c:737
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "no s'ha pogut canviar el mode de %s a 0%o"
+
+#: lib/iolog/iolog_timing.c:255
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "error en llegir el fitxer de sincronització: %s"
+
+#: lib/iolog/iolog_timing.c:262
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "línia no vàlida de fitxer de sincronització: %s"
+
+#: logsrvd/iolog_writer.c:946
+msgid "log is already complete, cannot be restarted"
+msgstr "el registre ja està complet, no es pot reinicar"
+
+#: logsrvd/iolog_writer.c:977
+msgid "unable to restart log"
+msgstr "no s'ha pogut reiniciar el registre"
+
+#: logsrvd/logsrv_util.c:99 logsrvd/logsrv_util.c:106
+#: plugins/sudoers/sudoreplay.c:352 plugins/sudoers/sudoreplay.c:358
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "no es pot obrir %s/%s"
+
+#: logsrvd/logsrv_util.c:133
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "fitxer faltant de registre I/O %s/%s"
+
+#: logsrvd/logsrv_util.c:140
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s: no es pot cercar cap endavant %zu"
+
+#: logsrvd/logsrv_util.c:150
+#, c-format
+msgid "unable to find resume point [%lld, %ld] in %s/%s"
+msgstr "no es pot trobar el punt de represa [%lld, %ld] a %s/%s"
+
+#: logsrvd/logsrvd.c:294 logsrvd/logsrvd.c:357 logsrvd/logsrvd.c:398
+#: logsrvd/logsrvd.c:453 logsrvd/logsrvd.c:522 logsrvd/logsrvd.c:573
+#: logsrvd/logsrvd.c:605 logsrvd/logsrvd.c:637
+msgid "state machine error"
+msgstr "error d'estat de màquina"
+
+#: logsrvd/logsrvd.c:303
+msgid "invalid AcceptMessage"
+msgstr "AcceptMessage no vàlid"
+
+#: logsrvd/logsrvd.c:311
+msgid "error parsing AcceptMessage"
+msgstr "error analitzant AcceptMessage"
+
+#: logsrvd/logsrvd.c:318
+msgid "error creating I/O log"
+msgstr "error creant registre I/O"
+
+#: logsrvd/logsrvd.c:325
+msgid "error logging accept event"
+msgstr "error registrant esdeveniment d'acceptació"
+
+#: logsrvd/logsrvd.c:366
+msgid "invalid RejectMessage"
+msgstr "RejectMessage no vàlid"
+
+#: logsrvd/logsrvd.c:374
+msgid "error parsing RejectMessage"
+msgstr "error analitzant RejectMessage"
+
+#: logsrvd/logsrvd.c:380
+msgid "error logging reject event"
+msgstr "error registrant esdeveniment de rebuig"
+
+#: logsrvd/logsrvd.c:490
+msgid "invalid AlertMessage"
+msgstr "AlertMessage no vàlid"
+
+#: logsrvd/logsrvd.c:499
+msgid "error parsing AlertMessage"
+msgstr "error analitzant AlertMessage"
+
+#: logsrvd/logsrvd.c:507
+msgid "error logging alert event"
+msgstr "error registrant esdeveniment d'alerta"
+
+#: logsrvd/logsrvd.c:528 logsrvd/logsrvd.c:579 logsrvd/logsrvd.c:611
+msgid "protocol error"
+msgstr "error de protocol"
+
+#: logsrvd/logsrvd.c:538
+msgid "error writing IoBuffer"
+msgstr "error escrivint IoBuffer"
+
+#: logsrvd/logsrvd.c:590
+msgid "error writing ChangeWindowSize"
+msgstr "error escrivint ChangeWindowSize"
+
+#: logsrvd/logsrvd.c:622
+msgid "error writing CommandSuspend"
+msgstr "error escrivint CommandSuspend"
+
+#: logsrvd/logsrvd.c:707
+msgid "unrecognized ClientMessage type"
+msgstr "tipus ClientMessage no reconegut"
+
+#: logsrvd/logsrvd.c:978
+msgid "client message too large"
+msgstr "missatge de client massa llarg"
+
+#: logsrvd/logsrvd.c:1208 logsrvd/logsrvd.c:1216
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "no s'ha pogut establir la ciphersuite TLS 1.2 a %s: %s"
+
+#: logsrvd/logsrvd.c:1236 logsrvd/logsrvd.c:1244
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "no s'ha pogut establir la ciphersuite TLS 1.3 a %s: %s"
+
+#: logsrvd/logsrvd.c:1280
+#, c-format
+msgid "unable to get TLS server method: %s"
+msgstr "no s'ha pogut obtenir el mètode de servidor TLS: %s"
+
+#: logsrvd/logsrvd.c:1285
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "no s'ha pogut crear el context TLS: %s"
+
+#: logsrvd/logsrvd.c:1292 plugins/sudoers/log_client.c:236
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "no s'ha pogut carregar el certificat %s"
+
+#: logsrvd/logsrvd.c:1305 plugins/sudoers/log_client.c:216
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "no s'ha pogut carregar el paquet d'autoritat de certificat %s"
+
+#: logsrvd/logsrvd.c:1350 plugins/sudoers/log_client.c:249
+#, c-format
+msgid "unable to load private key %s"
+msgstr "no s'ha pogut carregar la clau privada %s"
+
+#: logsrvd/logsrvd.c:1367 logsrvd/logsrvd.c:1376
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "no es poden establir els paràmetres diffie-hellman: %s"
+
+#: logsrvd/logsrvd.c:1389
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "no es pot establir la versió de protocol mínim a TLS 1.2: %s"
+
+#: logsrvd/logsrvd.c:1574
+msgid "unable to get remote IP addr"
+msgstr "no s'ha pogut obtenir l'adreça remota IP"
+
+#: logsrvd/logsrvd.c:1602 plugins/sudoers/log_client.c:263
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "no es pot adjuntar les dades d'usuari a l'objecte ssl: %s"
+
+#: logsrvd/logsrvd.c:1610 logsrvd/logsrvd.c:1732 logsrvd/logsrvd.c:1834
+#: logsrvd/sendlog.c:1141 logsrvd/sendlog.c:1497 logsrvd/sendlog.c:1512
+#: logsrvd/sendlog.c:1570 plugins/sudoers/iolog.c:969
+#: plugins/sudoers/iolog.c:1102 plugins/sudoers/iolog.c:1200
+#: plugins/sudoers/log_client.c:109 plugins/sudoers/log_client.c:324
+#: plugins/sudoers/log_client.c:340 plugins/sudoers/log_client.c:386
+#: plugins/sudoers/log_client.c:585 plugins/sudoers/log_client.c:592
+#: plugins/sudoers/log_client.c:1109 plugins/sudoers/log_client.c:1382
+#: plugins/sudoers/log_client.c:1423 plugins/sudoers/log_client.c:1431
+#: plugins/sudoers/log_client.c:1582 plugins/sudoers/log_client.c:1698
+#: plugins/sudoers/log_client.c:2015 plugins/sudoers/log_client.c:2023
+#: plugins/sudoers/sudoreplay.c:512 plugins/sudoers/sudoreplay.c:559
+#: plugins/sudoers/sudoreplay.c:791 plugins/sudoers/sudoreplay.c:903
+#: plugins/sudoers/sudoreplay.c:993 plugins/sudoers/sudoreplay.c:1008
+#: plugins/sudoers/sudoreplay.c:1015 plugins/sudoers/sudoreplay.c:1022
+#: plugins/sudoers/sudoreplay.c:1029 plugins/sudoers/sudoreplay.c:1036
+#: plugins/sudoers/sudoreplay.c:1163
+msgid "unable to add event to queue"
+msgstr "no s'ha pogut afegir l'esdeveniment a la cua"
+
+#: logsrvd/logsrvd.c:1786 logsrvd/logsrvd.c:2033
+msgid "unable setup listen socket"
+msgstr "no s'ha pogut establir el sòcol d'escolta"
+
+#: logsrvd/logsrvd.c:1934
+msgid "sudo log server"
+msgstr "servidor de registre sudo"
+
+#: logsrvd/logsrvd.c:1936 logsrvd/sendlog.c:127
+msgid "Options:"
+msgstr "Opcions:"
+
+#: logsrvd/logsrvd.c:1938
+msgid "path to configuration file"
+msgstr "camí al fitxer de configuració"
+
+#: logsrvd/logsrvd.c:1940 logsrvd/sendlog.c:129
+msgid "display help message and exit"
+msgstr "mostra el missatge d'ajuda i surt"
+
+#: logsrvd/logsrvd.c:1942
+msgid "do not fork, run in the foreground"
+msgstr "no bifurquis, executa en el rerefons"
+
+#: logsrvd/logsrvd.c:1944
+msgid "percent chance connections will drop"
+msgstr "les connexions a l'atzar de percentatge es tallaran"
+
+#: logsrvd/logsrvd.c:1946 logsrvd/sendlog.c:157
+msgid "display version information and exit"
+msgstr "mostra la informació de versió i surt"
+
+#: logsrvd/logsrvd.c:1994 logsrvd/sendlog.c:1735
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "Protobuf-C versió 1.3 o més gran requerida"
+
+#: logsrvd/logsrvd.c:2012
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "valor perdut aleatori no vàlid: %s"
+
+#: logsrvd/logsrvd.c:2016 logsrvd/sendlog.c:1785
+#: plugins/sudoers/cvtsudoers.c:228 plugins/sudoers/sudoreplay.c:299
+#: plugins/sudoers/visudo.c:175
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s versió %s\n"
+
+#: logsrvd/logsrvd_conf.c:332
+msgid "TLS not supported"
+msgstr "no està suportat TLS"
+
+#: logsrvd/logsrvd_conf.c:344
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:411 logsrvd/logsrvd_conf.c:656
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s: no és un camí completament qualificat"
+
+#: logsrvd/logsrvd_conf.c:770
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d no concordat '[': %s"
+
+#: logsrvd/logsrvd_conf.c:781
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s:%d secció no vàlida de configuració: %s"
+
+#: logsrvd/logsrvd_conf.c:789
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d línia no vàlida de configuració: %s"
+
+#: logsrvd/logsrvd_conf.c:795
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d nom esperat de secció: %s"
+
+#: logsrvd/logsrvd_conf.c:809
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "valor no vàlid %s: %s"
+
+#: logsrvd/logsrvd_conf.c:817
+#, c-format
+msgid "%s:%d unknown key: %s"
+msgstr "%s:%d clau desconeguda: %s"
+
+#: logsrvd/logsrvd_conf.c:1006
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "sistema de syslog desconegut %s"
+
+#: logsrvd/logsrvd_conf.c:1010 logsrvd/logsrvd_conf.c:1014
+#: logsrvd/logsrvd_conf.c:1018
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "prioritat desconeguda de syslog %s"
+
+#: logsrvd/sendlog.c:125
+msgid "send sudo I/O log to remote server"
+msgstr "envia el registre I/O de sudo al servidor remot"
+
+#: logsrvd/sendlog.c:131
+msgid "only send an accept event (no I/O)"
+msgstr "envia sols un esdeveniment d'acceptació (no I/O)"
+
+#: logsrvd/sendlog.c:134
+msgid "certificate bundle file to verify server's cert against"
+msgstr "fitxer del paquet del certificat per usar en la verificació del certificat del servidor "
+
+#: logsrvd/sendlog.c:136
+msgid "certificate file for TLS handshake"
+msgstr "fitxer de certificat per l'encaixada TLS"
+
+#: logsrvd/sendlog.c:139
+msgid "host to send logs to"
+msgstr "com enviar registres a"
+
+#: logsrvd/sendlog.c:141
+msgid "remote ID of I/O log to be resumed"
+msgstr "es reprendrà el registre remot de l'I/O de l'ID"
+
+#: logsrvd/sendlog.c:144
+msgid "private key file"
+msgstr "fitxer de la clau privada"
+
+#: logsrvd/sendlog.c:146
+msgid "do not verify server certificate"
+msgstr "no verifiquis el certificat del servidor"
+
+#: logsrvd/sendlog.c:149
+msgid "port to use when connecting to host"
+msgstr "port a usar a les connexions a l'amfitrió"
+
+#: logsrvd/sendlog.c:151
+msgid "restart previous I/O log transfer"
+msgstr "reinicia la transferència pevia del registre I/O"
+
+#: logsrvd/sendlog.c:153
+msgid "reject the command with the given reason"
+msgstr "rebutja l'ordre amb la raó següent"
+
+#: logsrvd/sendlog.c:155
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "comprova del servidor d'auditoria enviant el registre I/O seleccionat n vegades en paral·lel"
+
+#: logsrvd/sendlog.c:180 plugins/sudoers/log_client.c:432
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "no es pot cercar %s:%s: %s"
+
+#: logsrvd/sendlog.c:218
+msgid "unable to get server IP addr"
+msgstr "no es pot obtenir l'adreça IP del servidor"
+
+#: logsrvd/sendlog.c:272 plugins/sudoers/sudoreplay.c:851
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "no es pot llegir %s/%s: %s"
+
+#: logsrvd/sendlog.c:293 plugins/sudoers/log_client.c:692
+#, c-format
+msgid "client message too large: %zu"
+msgstr "missatge de client massa llarg: %zu"
+
+#: logsrvd/sendlog.c:826
+#, c-format
+msgid "%s: write buffer already in use"
+msgstr "%s: memòria intermèdia d'escriptura ja en ús"
+
+#: logsrvd/sendlog.c:878 plugins/sudoers/iolog.c:893
+#: plugins/sudoers/iolog.c:962
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "esdeveniment I/O inesperat %d"
+
+#: logsrvd/sendlog.c:924 logsrvd/sendlog.c:941 logsrvd/sendlog.c:975
+#: plugins/sudoers/log_client.c:1124 plugins/sudoers/log_client.c:1392
+#: plugins/sudoers/log_client.c:1460 plugins/sudoers/log_client.c:1496
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: estat inesperat %d"
+
+#: logsrvd/sendlog.c:947 plugins/sudoers/log_client.c:1466
+msgid "invalid ServerHello"
+msgstr "ServerHello invàlid"
+
+#: logsrvd/sendlog.c:1011 plugins/sudoers/log_client.c:1540
+#, c-format
+msgid "error message received from server: %s"
+msgstr "s'ha rebut un missatge d'error del servidor: %s"
+
+#: logsrvd/sendlog.c:1024 plugins/sudoers/log_client.c:1553
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "avorta el missatge rebut del servidor: %s"
+
+#: logsrvd/sendlog.c:1043 plugins/sudoers/log_client.c:1572
+msgid "unable to unpack ServerMessage"
+msgstr "no es pot desempaquetar ServerMessage"
+
+#: logsrvd/sendlog.c:1083 plugins/sudoers/log_client.c:1603
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s: valor inesperat de type_case %d"
+
+#: logsrvd/sendlog.c:1112
+msgid "timeout reading from server"
+msgstr "temps d'espera exhaurit quan es llegia del servidor"
+
+#: logsrvd/sendlog.c:1190
+msgid "premature EOF"
+msgstr "final de fitxer prematur"
+
+#: logsrvd/sendlog.c:1203 plugins/sudoers/log_client.c:1761
+#, c-format
+msgid "server message too large: %u"
+msgstr "missatge del servidor massa llarg: %u"
+
+#: logsrvd/sendlog.c:1254
+msgid "timeout writing to server"
+msgstr "temps d'espera exhaurit quan s'escrivia al servidor"
+
+#: logsrvd/sendlog.c:1473 plugins/sudoers/log_client.c:296
+msgid "TLS handshake timeout occurred"
+msgstr "ha ocorregut un temps d'espera exhaurit a l'encaixada TLS"
+
+#: logsrvd/sendlog.c:1492 logsrvd/sendlog.c:1507
+#: plugins/sudoers/log_client.c:318 plugins/sudoers/log_client.c:334
+msgid "unable to set event"
+msgstr "no es pot establir l'esdeveniment"
+
+#: logsrvd/sendlog.c:1517 logsrvd/sendlog.c:1521
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "ha fallat la connexió TLS: %s"
+
+#: logsrvd/sendlog.c:1554
+#, c-format
+msgid "Unable to initialize ssl context: %s"
+msgstr "No es pot inicialitzar el context ssl: %s"
+
+#: logsrvd/sendlog.c:1559 plugins/sudoers/log_client.c:258
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "No es pot assignar l'objecte ssl: %s"
+
+#: logsrvd/sendlog.c:1564
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "No es pot adjuntar el sòcol a l'objecte ssl: %s"
+
+#: logsrvd/sendlog.c:1808
+msgid "both restart point and iolog ID must be specified"
+msgstr "s'ha d'especificar tant el punt de reinici com l'ID del iolog"
+
+#: logsrvd/sendlog.c:1812
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "no es pot establir un punt de reinici quan no s'envia cap I/O"
+
+#: logsrvd/sendlog.c:1887
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "ha sortit prematurament amb estat %d"
+
+#: logsrvd/sendlog.c:1888
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "s'ha enviat el temps transcorregut al servidor [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1890
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "punt de compromís rebut del servidor [%lld, %ld]"
+
+#: plugins/sudoers/audit.c:259 plugins/sudoers/audit.c:398
+#: plugins/sudoers/log_client.c:960 plugins/sudoers/log_client.c:1008
+#: plugins/sudoers/log_client.c:1056 plugins/sudoers/log_client.c:1181
+#: plugins/sudoers/logging.c:548 plugins/sudoers/policy.c:120
+msgid "unable to get time of day"
+msgstr "no es pot obtenir l'hora"
+
+#: plugins/sudoers/auth/aix_auth.c:277
+#, c-format
+msgid "unable to change password for %s"
+msgstr "no s'ha pogut canviar la contrasenya per a %s"
+
+#: plugins/sudoers/auth/bsdauth.c:70
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "no s'ha pogut obtenir la classe d'inici de sessió per a l'usuari %s"
+
+#: plugins/sudoers/auth/bsdauth.c:75
+msgid "unable to begin bsd authentication"
+msgstr "no s'ha pogut iniciar l'autenticació bsd"
+
+#: plugins/sudoers/auth/bsdauth.c:83
+msgid "invalid authentication type"
+msgstr "tipus no vàlida d'autenticació"
+
+#: plugins/sudoers/auth/bsdauth.c:92
+msgid "unable to initialize BSD authentication"
+msgstr "no s'ha pogut inicialitzar l'autenticació BSD"
+
+#: plugins/sudoers/auth/bsdauth.c:179
+msgid "your account has expired"
+msgstr "el vostre compte ha caducat"
+
+#: plugins/sudoers/auth/bsdauth.c:181
+msgid "approval failed"
+msgstr "ha fallat l'aprovació"
+
+#: plugins/sudoers/auth/fwtk.c:54
+msgid "unable to read fwtk config"
+msgstr "no s'ha pogut llegir la configuració fwtk"
+
+#: plugins/sudoers/auth/fwtk.c:59
+msgid "unable to connect to authentication server"
+msgstr "no s'ha pogut connectar al servidor d'autenticació"
+
+#: plugins/sudoers/auth/fwtk.c:65 plugins/sudoers/auth/fwtk.c:89
+#: plugins/sudoers/auth/fwtk.c:121
+msgid "lost connection to authentication server"
+msgstr "s'ha perdut la connexió al servidor d'autenticació"
+
+#: plugins/sudoers/auth/fwtk.c:69
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"error de servidor d'autenticació:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:110
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: no s'ha pogut convertir el principal a la cadena de caràcters ('%s'): %s"
+
+#: plugins/sudoers/auth/kerb5.c:160
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: no s'ha pogut analitzar '%s': %s"
+
+#: plugins/sudoers/auth/kerb5.c:169
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: no s'ha pogut resoldre el cau de credencials : %s"
+
+#: plugins/sudoers/auth/kerb5.c:216
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: no s'han pogut assignar les opcions: %s"
+
+#: plugins/sudoers/auth/kerb5.c:231
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: no s'ha pogut obtenir les credencials: %s"
+
+#: plugins/sudoers/auth/kerb5.c:244
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: no s'ha pogut inicialitzar el cau de credencials: %s"
+
+#: plugins/sudoers/auth/kerb5.c:247
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: no s'ha pogut emmagatzemar la credencial al cau: %s"
+
+#: plugins/sudoers/auth/kerb5.c:311
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: no s'ha pogut obtenir el principal de l'amfitrió: %s"
+
+#: plugins/sudoers/auth/kerb5.c:325
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: No s'ha pogut verificar TGT! Possible atac!: %s"
+
+#: plugins/sudoers/auth/pam.c:218
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "no s'ha pogut inicialitzar PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:337
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Error d'autenticació PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:356
+msgid "account validation failure, is your account locked?"
+msgstr "fallada de validació de compte, està bloquejat el vostre compte?"
+
+#: plugins/sudoers/auth/pam.c:367
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Ha expirat el compte o la contrasenya, restabliu la vostra contrasenya i proveu un altre cop"
+
+#: plugins/sudoers/auth/pam.c:373
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "no s'ha pogut canviar la contrasenya expirada: %s"
+
+#: plugins/sudoers/auth/pam.c:384
+msgid "Password expired, contact your system administrator"
+msgstr "Ha expirat la contrasenya, contacteu el vostre administrador de sistema"
+
+#: plugins/sudoers/auth/pam.c:389
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Ha expirat el compte o la configuració PAM no té una secció \"compte\" per a sudo, contacteu el vostre administrador de sistema"
+
+#: plugins/sudoers/auth/pam.c:397 plugins/sudoers/auth/pam.c:402
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "Error de gestió de compte PAM: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:99 plugins/sudoers/visudo.c:241
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "no existiu a la base de dades %s"
+
+#: plugins/sudoers/auth/securid5.c:72
+msgid "failed to initialise the ACE API library"
+msgstr "ha fallat la inicialització de la biblioteca ACE API"
+
+#: plugins/sudoers/auth/securid5.c:98
+msgid "unable to contact the SecurID server"
+msgstr "no s'ha pogut contactar el servidor SecurID"
+
+#: plugins/sudoers/auth/securid5.c:107
+msgid "User ID locked for SecurID Authentication"
+msgstr "L'ID de l'usuari esta bloquejat per a Autenticació SecurID"
+
+#: plugins/sudoers/auth/securid5.c:111 plugins/sudoers/auth/securid5.c:162
+msgid "invalid username length for SecurID"
+msgstr "nom d'usuari no vàlid per a SecurID"
+
+#: plugins/sudoers/auth/securid5.c:115 plugins/sudoers/auth/securid5.c:167
+msgid "invalid Authentication Handle for SecurID"
+msgstr "Mànec d'Autenticació no vàlid per a SecurID"
+
+#: plugins/sudoers/auth/securid5.c:119
+msgid "SecurID communication failed"
+msgstr "Ha fallat la comunicació SecurID"
+
+#: plugins/sudoers/auth/securid5.c:123 plugins/sudoers/auth/securid5.c:210
+msgid "unknown SecurID error"
+msgstr "error desconegut de SecurID"
+
+#: plugins/sudoers/auth/securid5.c:157
+msgid "invalid passcode length for SecurID"
+msgstr "longitud no vàlida de contrasenya per a SecurID"
+
+#: plugins/sudoers/auth/sia.c:69 plugins/sudoers/auth/sia.c:123
+msgid "unable to initialize SIA session"
+msgstr "no s'ha pogut inicialitzar la sessió SIA"
+
+#: plugins/sudoers/auth/sudo_auth.c:132
+msgid "invalid authentication methods"
+msgstr "mètodes no vàlids d'autenticació"
+
+#: plugins/sudoers/auth/sudo_auth.c:134
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Mètodes no vàlids d'autenticació compilats dins del sudo! No podeu barrejar l'autenticació independent i no independent."
+
+#: plugins/sudoers/auth/sudo_auth.c:255 plugins/sudoers/auth/sudo_auth.c:305
+msgid "no authentication methods"
+msgstr "no hi ha mètodes d'autenticació"
+
+#: plugins/sudoers/auth/sudo_auth.c:257
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "No hi ha mètodes d'autenticació compilats dins del sudo! Si voleu deshabilitar l'autenticació, useu l'opció de configuració --disable-authentication"
+
+#: plugins/sudoers/auth/sudo_auth.c:307
+msgid "Unable to initialize authentication methods."
+msgstr "No s'han pogut inicialitzar els mètodes d'autenticació."
+
+#: plugins/sudoers/auth/sudo_auth.c:471
+msgid "Authentication methods:"
+msgstr "Mètodes d'autenticació:"
+
+#: plugins/sudoers/bsm_audit.c:123 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "No s'ha pogut determinar la condició d'auditoria"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:277
+msgid "unable to commit audit record"
+msgstr "no s'ha pogut validar el registre d'auditoria"
+
+#: plugins/sudoers/check.c:264
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "s'ha produït un error quan es llegia el fitxer de lliçó %s"
+
+#: plugins/sudoers/check.c:270
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "s'ignorarà el fitxer de lecció %s: no és un fitxer regular"
+
+#: plugins/sudoers/check.c:274 plugins/sudoers/cvtsudoers.c:618
+#: plugins/sudoers/cvtsudoers.c:639 plugins/sudoers/cvtsudoers.c:1249
+#: plugins/sudoers/cvtsudoers_json.c:872 plugins/sudoers/cvtsudoers_ldif.c:688
+#: plugins/sudoers/sudoers.c:1028 plugins/sudoers/sudoreplay.c:1435
+#: plugins/sudoers/timestamp.c:431 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:913
+#, c-format
+msgid "unable to open %s"
+msgstr "no s'ha pogut obrir %s"
+
+#: plugins/sudoers/check.c:283
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Confiem que heu rebut la llissó habitual de l'Administrador del\n"
+"Sistema. Generalment es resumeix en aquestes tres coses:\n"
+"\n"
+" #1) Respecteu la privacitat dels altres.\n"
+" #2) Penseu abans d'escriure.\n"
+" #3) Tenir molt de poder està associat amb tenir molta responsabilitat.\n"
+"\n"
+
+#: plugins/sudoers/check.c:325 plugins/sudoers/check.c:335
+#: plugins/sudoers/sudoers.c:830 plugins/sudoers/sudoers.c:851
+#: plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid: %u"
+msgstr "uid desconegut: %u"
+
+#: plugins/sudoers/check.c:330 plugins/sudoers/exptilde.c:85
+#: plugins/sudoers/iolog.c:118 plugins/sudoers/policy.c:1123
+#: plugins/sudoers/sudoers.c:432 plugins/sudoers/sudoers.c:1283
+#: plugins/sudoers/testsudoers.c:216 plugins/sudoers/testsudoers.c:383
+#, c-format
+msgid "unknown user: %s"
+msgstr "usuari desconegut: %s"
+
+#: plugins/sudoers/check_aliases.c:56
+#, c-format
+msgid "Error: %s:%d:%d: cycle in %s \"%s\""
+msgstr "Error: %s:%d:%d: cicle a %s \"%s\""
+
+#: plugins/sudoers/check_aliases.c:57
+#, c-format
+msgid "Warning: %s:%d:%d: cycle in %s \"%s\""
+msgstr "Advertiment: %s:%d:%d: cicle a %s \"%s\""
+
+#: plugins/sudoers/check_aliases.c:61
+#, c-format
+msgid "Error: %s:%d:%d: %s \"%s\" referenced but not defined"
+msgstr "Error: %s:%d:%d: %s «%s» referenciat però no definit"
+
+#: plugins/sudoers/check_aliases.c:62
+#, c-format
+msgid "Warning: %s:%d:%d: %s \"%s\" referenced but not defined"
+msgstr "Advertiment: %s:%d:%d: %s «%s» referenciat però no definit"
+
+#: plugins/sudoers/cvtsudoers.c:194
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "increment d'ordre: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:210
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "ordre d'inici: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:220
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "ordre de farciment: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:230 plugins/sudoers/visudo.c:177
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s versió de la gramàtica %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:247 plugins/sudoers/testsudoers.c:167
+#, c-format
+msgid "unsupported input format %s"
+msgstr "format d'entrada %s no suportat"
+
+#: plugins/sudoers/cvtsudoers.c:262
+#, c-format
+msgid "unsupported output format %s"
+msgstr "format de sortida %s no suportat"
+
+#: plugins/sudoers/cvtsudoers.c:314
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: els fitxers d'entrada i de sortida han de ser diferents"
+
+#: plugins/sudoers/cvtsudoers.c:330 plugins/sudoers/sudoers.c:177
+#: plugins/sudoers/testsudoers.c:255 plugins/sudoers/visudo.c:247
+#: plugins/sudoers/visudo.c:597 plugins/sudoers/visudo.c:917
+msgid "unable to initialize sudoers default values"
+msgstr "no s'han pogut inicialitzar el valors predeterminats dels sudoers"
+
+#: plugins/sudoers/cvtsudoers.c:416 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:475
+#, c-format
+msgid "%s: unknown key word: %s"
+msgstr "%s: paraula clau desconeguda: %s"
+
+#: plugins/sudoers/cvtsudoers.c:521
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "tipus no vàlid de valors predeterminats: %s"
+
+#: plugins/sudoers/cvtsudoers.c:544
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "opció no vàlida de supressió: %s"
+
+#: plugins/sudoers/cvtsudoers.c:584 plugins/sudoers/cvtsudoers.c:598
+#, c-format
+msgid "invalid filter: %s"
+msgstr "filtre no vàlid: %s"
+
+#: plugins/sudoers/cvtsudoers.c:642 plugins/sudoers/visudo.c:922
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "no s'ha pogut analitzar el fitxer %s, error desconegut"
+
+#: plugins/sudoers/cvtsudoers.c:650
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr "error d'anàlisi a %s a prop de la línia %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:653
+#, c-format
+msgid "parse error in %s\n"
+msgstr "error d'anàlisi a %s\n"
+
+#: plugins/sudoers/cvtsudoers.c:1296 plugins/sudoers/sudoreplay.c:1124
+#: plugins/sudoers/timestamp.c:315 plugins/sudoers/timestamp.c:318
+#, c-format
+msgid "unable to write to %s"
+msgstr "no s'ha pogut escriure a %s"
+
+#: plugins/sudoers/cvtsudoers.c:1319
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s - converteix entre formats de fitxer de sudoers\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1321
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Options:\n"
+" -b, --base=dn el DN de base per a demandes LDAP de sudo\n"
+" -c, --config=conf_file el camí al fitxer de configuració\n"
+" -d, --defaults=deftypes convertieix únicament valors predeterminats dels tipus especificats\n"
+" -e, --expand-aliases expandeix els alias a les conversions\n"
+" -f, --output-format=format estableix el format de sortida: JSON, LDIF o sudoers\n"
+" -i, --input-format=format estableix el format d'entrada: LDIF o sudoers\n"
+" -I, --increment=num quantitat a incrementar cada sudoOrder per\n"
+" -h, --help mostra el missatge d'ajuda i surt\n"
+" -m, --match=filter converteix sols les entrades que concorden amb el filtre\n"
+" -M, --match-local el filtre de concordar usa passwd i bases de dades de grup\n"
+" -o, --output=output_file escriu el sudoers convertit a output_file\n"
+" -O, --order-start=num punt d'inici del primer sudoOrder\n"
+" -p, --prune-matches neteja els usuaris, grups i amfitrions no concordats\n"
+" -P, --padding=num farciment de base per a l'increment de sudoOrder\n"
+" -s, --suppress=sections suprimeix la sortida de certes seccions\n"
+" -V, --version mostra la informació de versió i surt"
+
+#: plugins/sudoers/cvtsudoers_json.c:480 plugins/sudoers/cvtsudoers_json.c:514
+#: plugins/sudoers/cvtsudoers_json.c:713
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "entrada «%s» desconeguda de paràmetres predeterminats"
+
+#: plugins/sudoers/cvtsudoers_json.c:651 plugins/sudoers/cvtsudoers_json.c:664
+#: plugins/sudoers/cvtsudoers_ldif.c:346 plugins/sudoers/cvtsudoers_ldif.c:357
+#: plugins/sudoers/ldap.c:503
+msgid "unable to get GMT time"
+msgstr "no s'ha pogut obtenir l'hora GMT"
+
+#: plugins/sudoers/cvtsudoers_json.c:654 plugins/sudoers/cvtsudoers_json.c:667
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:360
+#: plugins/sudoers/ldap.c:509
+msgid "unable to format timestamp"
+msgstr "no s'ha pogut donar format a la marca horària"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:640
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "massa entrades sudoers, el màxim és %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:683
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "la variable d'entorn SUDOERS_BASE no està establerta i no s'ha especificat l'opció -b"
+
+#: plugins/sudoers/def_data.c:50
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Eina syslog si s'està usant syslog per als registres: %s"
+
+#: plugins/sudoers/def_data.c:54
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Prioritat de syslog a usar quan l'usuari s'autentica amb èxit: %s"
+
+#: plugins/sudoers/def_data.c:58
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Prioritat de syslog a usar quan l'usuari no té èxit a autenticar- %s"
+
+#: plugins/sudoers/def_data.c:62
+msgid "Put OTP prompt on its own line"
+msgstr "Poseu la pregunta OTP a la seva pròpia línia"
+
+#: plugins/sudoers/def_data.c:66
+msgid "Ignore '.' in $PATH"
+msgstr "Ignoreu '.' al $PATH"
+
+#: plugins/sudoers/def_data.c:70
+msgid "Always send mail when sudo is run"
+msgstr "Envia sempre correu electrònic quan s'executi sudo"
+
+#: plugins/sudoers/def_data.c:74
+msgid "Send mail if user authentication fails"
+msgstr "Envia correu electrònic si falla l'autenticació de l'usuari"
+
+#: plugins/sudoers/def_data.c:78
+msgid "Send mail if the user is not in sudoers"
+msgstr "Envia correu electrònic si l'usuari no està als sudoers"
+
+#: plugins/sudoers/def_data.c:82
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Envia el correu electrònic si l'usuari no està als sudoers per a aquesta amfitrió"
+
+#: plugins/sudoers/def_data.c:86
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Envia correu electrònic si l'usuari no té permís per executar aquesta ordre"
+
+#: plugins/sudoers/def_data.c:90
+msgid "Send mail if the user tries to run a command"
+msgstr "Envia correu electrònic si l'usuari intenta executar una ordre"
+
+#: plugins/sudoers/def_data.c:94
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Usa una marca horària separada per a cada combinació usuari/terminal"
+
+#: plugins/sudoers/def_data.c:98
+msgid "Lecture user the first time they run sudo"
+msgstr "Dóna una llissó a l'usuari cada cop que executi sudo"
+
+#: plugins/sudoers/def_data.c:102
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Fitxer que conté la llissó de sudo: %s"
+
+#: plugins/sudoers/def_data.c:106
+msgid "Require users to authenticate by default"
+msgstr "Requereix de forma predeterminada que els usuaris s'autentiquin"
+
+#: plugins/sudoers/def_data.c:110
+msgid "Root may run sudo"
+msgstr "L'usuari primari pot executar sudo"
+
+#: plugins/sudoers/def_data.c:114
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Registra el nom del sistema amfitrió al fitxer de registre (que no és syslog)"
+
+#: plugins/sudoers/def_data.c:118
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Registra l'any al fitxer de registre (que no és syslog)"
+
+#: plugins/sudoers/def_data.c:122
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Si sudo s'invoca sense arguments, inicia un intèrpret d'ordres"
+
+#: plugins/sudoers/def_data.c:126
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Estableix $HOME per a l'usuari destí quan s'inicia un d'ordres amb -s"
+
+#: plugins/sudoers/def_data.c:130
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Estableix sempre $HOME al directori de l'usuari destí"
+
+#: plugins/sudoers/def_data.c:134
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Permet recollir alguna informació per donar missatges d'error útils"
+
+#: plugins/sudoers/def_data.c:138
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Requereix noms de sistema amfitrió qualificats completament al sudoers"
+
+#: plugins/sudoers/def_data.c:142
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Insulta a l'usuari quen entri una contrasenya incorrecta"
+
+#: plugins/sudoers/def_data.c:146
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Permet a l'usuari executar sudo únicament si té un terminal"
+
+#: plugins/sudoers/def_data.c:150
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo tindrà en compte la variable d'entorn EDITOR"
+
+#: plugins/sudoers/def_data.c:154
+msgid "Prompt for root's password, not the users's"
+msgstr "Pregunta per la contrasenya de l'usuari primari, no la de l'usuari normal"
+
+#: plugins/sudoers/def_data.c:158
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Pregunta per la contrasenya de l'usuari runas_default, no la de l'usuari normal"
+
+#: plugins/sudoers/def_data.c:162
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Pregunta per la contrasenya de l'usuari destí, no la de l'usuari normal"
+
+#: plugins/sudoers/def_data.c:166
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Aplica els paràmetres predeterminats a la classe d'inici de sessió de l'usuari destí si hi ha una"
+
+#: plugins/sudoers/def_data.c:170
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Estableix les variables d'entorn LOGNAME i USER"
+
+#: plugins/sudoers/def_data.c:174
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Estableix únicament l'uid efectiu de l'usuari destí, no l'uid real"
+
+#: plugins/sudoers/def_data.c:178
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "No inicialitzis el vector de grup perquè coincideixi amb el de l'usuari destí"
+
+#: plugins/sudoers/def_data.c:182
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "longitud a la qual ajustar les línies del fitxer de registres (0 per a no ajustar): %u"
+
+#: plugins/sudoers/def_data.c:186
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Temps màxim d'espera per a la marca horària de l'autenticació: %.1f minuts"
+
+#: plugins/sudoers/def_data.c:190
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Temps màxim d'espera per a la pregunta de la contrasenya: %.1f minuts"
+
+#: plugins/sudoers/def_data.c:194
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Nombre de intents per entrar una contrasenya: %u"
+
+#: plugins/sudoers/def_data.c:198
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Umask a usar o 0777 per usar la de l'usuari: 0%o"
+
+#: plugins/sudoers/def_data.c:202
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Camí al fitxer de registre: %s"
+
+#: plugins/sudoers/def_data.c:206
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Camí al programa de correu electrònic: %s"
+
+#: plugins/sudoers/def_data.c:210
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Indicadors per al programa de correu electrònic: %s"
+
+#: plugins/sudoers/def_data.c:214
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Adreça per enviar correu electrònic: %s"
+
+#: plugins/sudoers/def_data.c:218
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Adreça per enviar correu electrònic des de: %s"
+
+#: plugins/sudoers/def_data.c:222
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Línia d'assumpte per als missatges de correu electrònic: %s"
+
+#: plugins/sudoers/def_data.c:226
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Missatge de contrasenya incorrecta: %s"
+
+#: plugins/sudoers/def_data.c:230
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Camí al directori d'estat de la llissó: %s"
+
+#: plugins/sudoers/def_data.c:234
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Camí del directori de marques horàries d'autenticació: %s"
+
+#: plugins/sudoers/def_data.c:238
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Propietari del directori de marques horàries d'autenticació: %s"
+
+#: plugins/sudoers/def_data.c:242
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Els usuaris d'aquest grup estan exempts dels requeriments contrasenya i PATH: %s"
+
+#: plugins/sudoers/def_data.c:246
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Pregunta predeterminada de contrasenya: %s"
+
+#: plugins/sudoers/def_data.c:250
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Si està establert, la pregunta de contrasenya primarà sobre la pregunta del sistema en tots els casos."
+
+#: plugins/sudoers/def_data.c:254
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Usuari predeterminat per executar ordres com a: %s"
+
+#: plugins/sudoers/def_data.c:258
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Valor per anul·lar el $PATH de l'usuari amb: %s"
+
+#: plugins/sudoers/def_data.c:262
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Camí a l'editor a usar per visudo: %s"
+
+#: plugins/sudoers/def_data.c:266
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Quan requerir una contrasenya per a la pseudo-ordre 'list': %s"
+
+#: plugins/sudoers/def_data.c:270
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Quan requerir una contrasenya per a la pseudo-ordre 'verify': %s"
+
+#: plugins/sudoers/def_data.c:274
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "Carrega prèviament la llibreria sudo_noexec que reemplaça les funcions exec"
+
+#: plugins/sudoers/def_data.c:278
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Si el directori LDAP està actiu, ignorem el fitxer local sudoers?"
+
+#: plugins/sudoers/def_data.c:282
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Els descriptors de fitxer >= %d es tancaran abans d'executar una ordre"
+
+#: plugins/sudoers/def_data.c:286
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "Si està establert, els usuaris podran anul·lar el valor de «closeform» amb l'opció -C"
+
+#: plugins/sudoers/def_data.c:290
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Permet als usuaris fixar variables arbitràries d'entorn"
+
+#: plugins/sudoers/def_data.c:294
+msgid "Reset the environment to a default set of variables"
+msgstr "Restableix l'entorn a un conjunt predeterminat de variables"
+
+#: plugins/sudoers/def_data.c:298
+msgid "Environment variables to check for safety:"
+msgstr "Les variables d'entorn per comprovar la validesa:"
+
+#: plugins/sudoers/def_data.c:302
+msgid "Environment variables to remove:"
+msgstr "Variables d'entorn a suprimir:"
+
+#: plugins/sudoers/def_data.c:306
+msgid "Environment variables to preserve:"
+msgstr "Variables d'entorn a preservar:"
+
+#: plugins/sudoers/def_data.c:310
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "Rol SELinux a usar al nou context de seguretat: %s"
+
+#: plugins/sudoers/def_data.c:314
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "Tipus SELinux a usar al nou context de seguretat: %s"
+
+#: plugins/sudoers/def_data.c:318
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Camí al fitxer d'entorn sudo-específic: %s"
+
+#: plugins/sudoers/def_data.c:322
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Camí al fitxer restringit d'entorn especific de sudo: %s"
+
+#: plugins/sudoers/def_data.c:326
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Configuració local a usar quan s'estan analitzant els sudoers: %s"
+
+#: plugins/sudoers/def_data.c:330
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Permet a sudo preguntar per una contrasenya tot i que pugui ser visible"
+
+#: plugins/sudoers/def_data.c:334
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Proveeix retroalimentació a la pregunta de contrasenya quan hi ha una entrada per l'usuari"
+
+#: plugins/sudoers/def_data.c:338
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Usa una expansió que és menys precisa però no accedeix el sistema de fitxers"
+
+#: plugins/sudoers/def_data.c:342
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "Els permisos umask als sudoers anul·larà els permisos de l'usuari, tot i que siguin més permissius"
+
+#: plugins/sudoers/def_data.c:346
+msgid "Log user's input for the command being run"
+msgstr "Registra l'entrada feta per l'usuari per a l'ordre que s'està executant"
+
+#: plugins/sudoers/def_data.c:350
+msgid "Log the output of the command being run"
+msgstr "Registra la sortida de l'ordre que s'està executant"
+
+#: plugins/sudoers/def_data.c:354
+msgid "Compress I/O logs using zlib"
+msgstr "Comprimeix els registres d'entrada/sortida usant zlib"
+
+#: plugins/sudoers/def_data.c:358
+msgid "Always run commands in a pseudo-tty"
+msgstr "Executa sempre les ordres en un pseudo-terminal"
+
+#: plugins/sudoers/def_data.c:362
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Connector per a suport de grup no Unix: %s"
+
+#: plugins/sudoers/def_data.c:366
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Directori on arxivar els registres entrada/sortida: %s"
+
+#: plugins/sudoers/def_data.c:370
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Fitxer on arxivar el registre entrada/sortida: %s"
+
+#: plugins/sudoers/def_data.c:374
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Afegeix una entrada al fitxer utmp/utmpx quan s'estigui assignant un pty"
+
+#: plugins/sudoers/def_data.c:378
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Estableix l'usuari a utmp perquè sigui l'usuari runas, no l'usuari invocant"
+
+#: plugins/sudoers/def_data.c:382
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Conjunt de privilegis permesos: %s"
+
+#: plugins/sudoers/def_data.c:386
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Conjunt de privilegis límit: %s"
+
+#: plugins/sudoers/def_data.c:390
+msgid "Run commands on a pty in the background"
+msgstr "Executa les ordres a un pseudo-terminal (pty) al fons"
+
+#: plugins/sudoers/def_data.c:394
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "Nom del servei PAM a usar: %s"
+
+#: plugins/sudoers/def_data.c:398
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "Nom del servei PAM a usar per a intèrprets d'ordres d'inici de sessió: %s"
+
+#: plugins/sudoers/def_data.c:402
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Intent d'establir credencials PAM per a l'usuari destí"
+
+#: plugins/sudoers/def_data.c:406
+msgid "Create a new PAM session for the command to run in"
+msgstr "Crea una nova sessió PAM on s'executi l'ordre"
+
+#: plugins/sudoers/def_data.c:410
+msgid "Perform PAM account validation management"
+msgstr "Realitza la gestió de validació del compte PAM"
+
+#: plugins/sudoers/def_data.c:414
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "Nombre de seqüència de registre I/O màxim: %s"
+
+#: plugins/sudoers/def_data.c:418
+msgid "Enable sudoers netgroup support"
+msgstr "Habilita el suport de netgroup dels sudoers"
+
+#: plugins/sudoers/def_data.c:422
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Comprova que el directori pare tingui permisos d'escriptura quan s'estiguin editant fitxers amb sudoedit"
+
+#: plugins/sudoers/def_data.c:426
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Segueix els enllaços simbòlics quan s'estiguin editant fitxers amb sudoedit"
+
+#: plugins/sudoers/def_data.c:430
+msgid "Query the group plugin for unknown system groups"
+msgstr "Consulta al connector de grups per grups desconeguts de sistema"
+
+#: plugins/sudoers/def_data.c:434
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Fes concordar els grups de xarxa en base al conjunt sencer: usuari, amfitrió i domini"
+
+#: plugins/sudoers/def_data.c:438
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Permet que s'executin les ordres tot i que sudo no pot escriure al registre d'auditoria"
+
+#: plugins/sudoers/def_data.c:442
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Permet que s'executin les ordres tot i que sudo no pot escriure al registre d'entrada/sortida"
+
+#: plugins/sudoers/def_data.c:446
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Permet que s'executin les ordres tot i que sudo no pot escriure al fitxer de registre"
+
+#: plugins/sudoers/def_data.c:450
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Resol els grups a sudoers i fes concordar amb l'identificador de grup, no el nom"
+
+#: plugins/sudoers/def_data.c:454
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Les entrades de registre més grans que aquest valor es dividiran en múltiples missatges de syslog: %u"
+
+#: plugins/sudoers/def_data.c:458
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "L'usuari que serà el propietari dels fitxers d'entrada/sortida: %s"
+
+#: plugins/sudoers/def_data.c:462
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "El grup que serà el propietari dels fitxers de registre d'entrada/sortida: %s"
+
+#: plugins/sudoers/def_data.c:466
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Mode de fitxer a usar per als fitxers de registre d'entrada/sortida: 0%o"
+
+#: plugins/sudoers/def_data.c:470
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Executa les ordres pel descriptor de fitxer en comptes de pel camí: %s"
+
+#: plugins/sudoers/def_data.c:474
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Ignora les entrades desconegudes de valores predeterminats al sudoers en comptes de produir un advertiment"
+
+#: plugins/sudoers/def_data.c:478
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Temps en segons després del qual es finalitzarà l'ordre: %u"
+
+#: plugins/sudoers/def_data.c:482
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Permet a l'usuari especificar un temps d'espera a la línia d'ordres"
+
+#: plugins/sudoers/def_data.c:486
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Purga les dades de registre I/O a disc immediatament en comptes de posar-les a la memòria intermèdia"
+
+#: plugins/sudoers/def_data.c:490
+msgid "Include the process ID when logging via syslog"
+msgstr "Inclou l'ID de procés quan escriguis registres mitjançant syslog"
+
+#: plugins/sudoers/def_data.c:494
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Tipus de registre de marca de temps d'autenticació: %s"
+
+#: plugins/sudoers/def_data.c:498
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Missatge de fallada d'autenticació: %s"
+
+#: plugins/sudoers/def_data.c:502
+msgid "Ignore case when matching user names"
+msgstr "Ignora majúscules i minúscules quan concordis noms d'usuaris"
+
+#: plugins/sudoers/def_data.c:506
+msgid "Ignore case when matching group names"
+msgstr "Ignora majúscules i minúscules quan concordis noms de grups"
+
+#: plugins/sudoers/def_data.c:510
+msgid "Log when a command is allowed by sudoers"
+msgstr "Escriure un registre quan s'autoritza un ordre per sudoers"
+
+#: plugins/sudoers/def_data.c:514
+msgid "Log when a command is denied by sudoers"
+msgstr "Escriu un registre quan es denega un ordre per sudoers"
+
+#: plugins/sudoers/def_data.c:518
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "El(s) servidor(s) sudo per connectar-se amb port opcional"
+
+#: plugins/sudoers/def_data.c:522
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Temps límit del servidor de registre sudo en segons: %u"
+
+#: plugins/sudoers/def_data.c:526
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "Habilita l'opció del sòcol SO_KEEPALIVE al sòcol connectat al servidor de registre"
+
+#: plugins/sudoers/def_data.c:530
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "Camí al fitxer del paquet d'auditoria CA del servidor: %s"
+
+#: plugins/sudoers/def_data.c:534
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "Camí al fitxer d'entorn específic del sudo: %s"
+
+#: plugins/sudoers/def_data.c:538
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "Camí a la clau privada del sudoers: %s"
+
+#: plugins/sudoers/def_data.c:542
+msgid "Verify that the log server's certificate is valid"
+msgstr "Verifica que el certificat del servidor de registre és vàlid"
+
+#: plugins/sudoers/def_data.c:546
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "Permet l'ús d'un usuari runas desconegut i/o un ID de grup"
+
+#: plugins/sudoers/def_data.c:550
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "Per sols ordres d'execució com a usuari amb un entorn d'ordres vàlid"
+
+#: plugins/sudoers/def_data.c:554
+msgid "Set the pam remote user to the user running sudo"
+msgstr "Estableix l'usuari remot pam a l'usuari que executa el sudo"
+
+#: plugins/sudoers/def_data.c:558
+msgid "Set the pam remote host to the local host name"
+msgstr "Estableix l'amfitrió remot pam al nom de l'amfitrió local"
+
+#: plugins/sudoers/def_data.c:562
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "Directori de treball al qual canviar abans d'executar l'ordre: %s"
+
+#: plugins/sudoers/def_data.c:566
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "Directori arrel al qual canviar abans d'executar l'ordre: %s"
+
+#: plugins/sudoers/def_data.c:570
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "El format dels registres a produir: %s"
+
+#: plugins/sudoers/def_data.c:574
+msgid "Enable SELinux RBAC support"
+msgstr "Habiita el suport SELinux RBAC"
+
+#: plugins/sudoers/def_data.c:578
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "Camí al fitxer que es crea el primer cop que s'executa el sudo: %s"
+
+#: plugins/sudoers/defaults.c:185
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: entrada predeterminada desconeguda «%s»"
+
+#: plugins/sudoers/defaults.c:188
+#, c-format
+msgid "%s: unknown defaults entry \"%s\""
+msgstr "%s: entrada «%s» desconeguda de paràmetres predeterminats"
+
+#: plugins/sudoers/defaults.c:234
+#, c-format
+msgid "%s:%d:%d: no value specified for \"%s\""
+msgstr "%s:%d:%d: no s'ha especificat un valor per a «%s»"
+
+#: plugins/sudoers/defaults.c:237
+#, c-format
+msgid "%s: no value specified for \"%s\""
+msgstr "%s: no s'ha especificat un valor per a «%s»"
+
+#: plugins/sudoers/defaults.c:275
+#, c-format
+msgid "%s:%d:%d: option \"%s\" does not take a value"
+msgstr "%s:%d:%d: l'opció «%s» no pren un valor"
+
+#: plugins/sudoers/defaults.c:278
+#, c-format
+msgid "%s: option \"%s\" does not take a value"
+msgstr "%s: l'opció «%s» no pren un valor"
+
+#: plugins/sudoers/defaults.c:303
+#, c-format
+msgid "%s:%d:%d: invalid Defaults type 0x%x for option \"%s\""
+msgstr "%s:%d:%d: tipus no vàlid de Defaults 0x%x per a l'opció «%s»"
+
+#: plugins/sudoers/defaults.c:306
+#, c-format
+msgid "%s: invalid Defaults type 0x%x for option \"%s\""
+msgstr "%s: tipus 0x%x no vàlid de paràmetres predeterminats per a l'opció «%s»"
+
+#: plugins/sudoers/defaults.c:316
+#, c-format
+msgid "%s:%d:%d: value \"%s\" is invalid for option \"%s\""
+msgstr "%s:%d:%d: valor «%s» no és vàlid per a l'opció «%s»"
+
+#: plugins/sudoers/defaults.c:319
+#, c-format
+msgid "%s: value \"%s\" is invalid for option \"%s\""
+msgstr "%s: el valor «%s» no és vàlid per a l'opció «%s»"
+
+#: plugins/sudoers/defaults.c:1040
+#, c-format
+msgid "%s:%d:%d: values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "%s:%d:%d: els valors per a «%s» han de començar amb «/», «~», o «*»"
+
+#: plugins/sudoers/defaults.c:1044
+#, c-format
+msgid "%s: values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "%s: els valors per a «%s» han de començar amb «/», «~», o «*»"
+
+#: plugins/sudoers/defaults.c:1055
+#, c-format
+msgid "%s:%d:%d: values for \"%s\" must start with a '/'"
+msgstr "%s:%d:%d: els valor per a «%s» han de començar amb «/»"
+
+#: plugins/sudoers/defaults.c:1059
+#, c-format
+msgid "%s: values for \"%s\" must start with a '/'"
+msgstr "%s: els valors per a «%s» han de començar amb un «/»"
+
+#: plugins/sudoers/env.c:412
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: envp corrupte, discordança de longitud"
+
+#: plugins/sudoers/env.c:1095
+msgid "unable to rebuild the environment"
+msgstr "no s'ha pogut reconstruir l'entorn"
+
+#: plugins/sudoers/env.c:1169
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "ho sentim, no teniu permís d'establir les següents variables d'entorn: %s"
+
+#: plugins/sudoers/file.c:107
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr "error d'anàlisi a %s a prop de la línia %d"
+
+#: plugins/sudoers/file.c:110
+#, c-format
+msgid "parse error in %s"
+msgstr "error d'anàlisi a la línia %s"
+
+#: plugins/sudoers/filedigest.c:49
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr "tipus de resum no suportat %d per a %s"
+
+#: plugins/sudoers/filedigest.c:78
+#, c-format
+msgid "%s: read error"
+msgstr "%s: error de lectura"
+
+#: plugins/sudoers/group_plugin.c:83
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s ha de ser propietat de l'uid %d"
+
+#: plugins/sudoers/group_plugin.c:87
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr "%s ha de ser modificable sols pel seu propietari"
+
+#: plugins/sudoers/group_plugin.c:96 plugins/sudoers/sssd.c:569
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "no s'ha pogut carregar %s: %s"
+
+#: plugins/sudoers/group_plugin.c:102
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "no s'ha pogut trobar el símbol \"group_plugin\" a %s"
+
+#: plugins/sudoers/group_plugin.c:107
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: connector incompatible de group versió principal %d, s'esperava %d"
+
+#: plugins/sudoers/interfaces.c:80 plugins/sudoers/interfaces.c:97
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "no s'ha pogut analitzar l'adreça IP «%s»"
+
+#: plugins/sudoers/interfaces.c:85 plugins/sudoers/interfaces.c:102
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "no s'ha pogut analitzar la màscara de xarxa «%s»"
+
+#: plugins/sudoers/interfaces.c:130
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Adreça local IP i parelles netmask:\n"
+
+#: plugins/sudoers/iolog.c:143 plugins/sudoers/sudoers.c:437
+#: plugins/sudoers/sudoers.c:1317 plugins/sudoers/testsudoers.c:407
+#, c-format
+msgid "unknown group: %s"
+msgstr "grup desconegut: %s"
+
+#: plugins/sudoers/iolog.c:635
+msgid "unable to update sequence file"
+msgstr "no s'ha pogut actualitzar el fitxer de seqüència"
+
+#: plugins/sudoers/iolog.c:666 plugins/sudoers/iolog.c:854
+#: plugins/sudoers/iolog.c:1007 plugins/sudoers/iolog.c:1014
+#: plugins/sudoers/iolog.c:1135 plugins/sudoers/iolog.c:1142
+#: plugins/sudoers/iolog.c:1241 plugins/sudoers/iolog.c:1248
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "no s'ha pogut escriure al fitxer de registre d'entrada/sortida: %s"
+
+#: plugins/sudoers/iolog.c:674
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "no s'ha pogut crear %s/%s"
+
+#: plugins/sudoers/iolog.c:899
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: error intern, no està obert el fitxer de registre I/O per a l'event %d"
+
+#: plugins/sudoers/iolog.c:992 plugins/sudoers/iolog.c:1120
+#: plugins/sudoers/iolog.c:1225 plugins/sudoers/timestamp.c:836
+#: plugins/sudoers/timestamp.c:928 plugins/sudoers/visudo.c:487
+#: plugins/sudoers/visudo.c:493
+msgid "unable to read the clock"
+msgstr "no s'ha pogut llegir el rellotge"
+
+#: plugins/sudoers/iolog.c:1217 plugins/sudoers/log_client.c:1199
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: error intern, senyal %d no vàlid"
+
+#: plugins/sudoers/ldap.c:177 plugins/sudoers/ldap_conf.c:291
+msgid "starttls not supported when using ldaps"
+msgstr "starttls no suportat quan s'està usant ldaps"
+
+#: plugins/sudoers/ldap.c:248
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "no s'ha pogut inicialitzar el certificat SSL i la clau db: %s"
+
+#: plugins/sudoers/ldap.c:251
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "heu d'establir TLS_CERT a %s per usar SSL"
+
+#: plugins/sudoers/ldap.c:1660
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "no s'ha pogut inicialitzar LDAP: %s"
+
+#: plugins/sudoers/ldap.c:1697
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "s'ha especificat start_tls però les biblioteques LDAP no donen suport a ldap_start_tls_s() o ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:1834 plugins/sudoers/parse_ldif.c:746
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "atribut sudoOrder no vàlid: %s"
+
+#: plugins/sudoers/ldap_conf.c:200
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: port massa larg"
+
+#: plugins/sudoers/ldap_conf.c:260
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "tipus d'uri LDAP no suportat: %s"
+
+#: plugins/sudoers/ldap_conf.c:287
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "no s'han pogut barrejar el ldap i els ldaps URIs "
+
+#: plugins/sudoers/ldap_util.c:529 plugins/sudoers/ldap_util.c:536
+#: plugins/sudoers/ldap_util.c:544 plugins/sudoers/ldap_util.c:553
+#: plugins/sudoers/ldap_util.c:561 plugins/sudoers/ldap_util.c:571
+#: plugins/sudoers/ldap_util.c:579
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "sudoOption duplicada: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:598 plugins/sudoers/ldap_util.c:600
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "no s'ha pogut convertir l'opció de sudo: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "no s'ha pogut obrir el sistema d'auditoria"
+
+#: plugins/sudoers/linux_audit.c:103
+msgid "unable to send audit message"
+msgstr "no s'ha pogut enviar el missatge d'auditoria"
+
+#: plugins/sudoers/log_client.c:113 plugins/sudoers/log_client.c:391
+#: plugins/sudoers/log_client.c:1437 plugins/sudoers/log_client.c:2031
+msgid "error in event loop"
+msgstr "error al bucle d'esdeveniment"
+
+#: plugins/sudoers/log_client.c:193
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "Ha fallat la creació d'un objecte nou SSL_CTX: %s"
+
+#: plugins/sudoers/log_client.c:345 plugins/sudoers/log_client.c:350
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "Ha fallat la connexió TLS a %s:%s: %s"
+
+#: plugins/sudoers/log_client.c:519
+msgid "TLS initialization was unsuccessful"
+msgstr "La inicialització TLS no ha reeixit"
+
+#: plugins/sudoers/log_client.c:528
+msgid "TLS handshake was unsuccessful"
+msgstr "L'encaixada TLS no ha reeixit"
+
+#: plugins/sudoers/log_client.c:1208
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: error intern, estat no vàlid de sortida %d"
+
+#: plugins/sudoers/log_client.c:1724 plugins/sudoers/log_client.c:1748
+msgid "lost connection to log server"
+msgstr "s'ha perdut la connexió al servidor de registre"
+
+#: plugins/sudoers/log_client.c:1825
+msgid "missing write buffer"
+msgstr "falta la memòria intermèdia d'escriptura"
+
+#: plugins/sudoers/log_client.c:1972
+msgid "unable to connect to log server"
+msgstr "no s'ha pogut connectar al servidor de registre"
+
+#: plugins/sudoers/logging.c:244
+msgid "user NOT in sudoers"
+msgstr "l'usuari NO ESTÀ als sudoers"
+
+#: plugins/sudoers/logging.c:246
+msgid "user NOT authorized on host"
+msgstr "l'usuari NO està autoritzat a l'amfitrió"
+
+#: plugins/sudoers/logging.c:248
+msgid "command not allowed"
+msgstr "ordre no permesa"
+
+#: plugins/sudoers/logging.c:269
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr "%s no està al fitxer sudoers. S'informarà d'aquest incident.\n"
+
+#: plugins/sudoers/logging.c:272
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr "%s no té permís per executar sudo a %s. S'informarà d'aquest incident.\n"
+
+#: plugins/sudoers/logging.c:276
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Ho sentim, l'usuari %s no pot executar sudo a %s.\n"
+
+#: plugins/sudoers/logging.c:279
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr "Ho sentim, l'usuari %s no pot executar '%s%s%s' com a %s%s%s a %s.\n"
+
+#: plugins/sudoers/logging.c:316 plugins/sudoers/sudoers.c:575
+#: plugins/sudoers/sudoers.c:577 plugins/sudoers/sudoers.c:579
+#: plugins/sudoers/sudoers.c:581 plugins/sudoers/sudoers.c:723
+#: plugins/sudoers/sudoers.c:725
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: no s'ha trobat l'ordre"
+
+#: plugins/sudoers/logging.c:318 plugins/sudoers/sudoers.c:571
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"s'ignorarà «%s» trobat a «.»\n"
+"Useu «sudo ./%s» si aquest és el «%s» que voleu executar."
+
+#: plugins/sudoers/logging.c:337
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u intent incorrecte de contrasenya"
+msgstr[1] "%u intents incorrectes de contrasenya"
+
+#: plugins/sudoers/logging.c:393
+msgid "authentication failure"
+msgstr "ha fallat l'autenticació"
+
+#: plugins/sudoers/logging.c:433 plugins/sudoers/logging.c:453
+msgid "a password is required"
+msgstr "es requereix una contrasenya"
+
+#: plugins/sudoers/logging.c:739
+#, c-format
+msgid "unable to open log file: %s"
+msgstr "no s'ha pogut obrir el fitxer de registre: %s"
+
+#: plugins/sudoers/logging.c:772
+#, c-format
+msgid "unable to write log file: %s"
+msgstr "no s'ha pogut escriure el fitxer de registre: %s"
+
+#: plugins/sudoers/match_digest.c:129
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "digest per a %s (%s) no està en forma %s"
+
+#: plugins/sudoers/parse.c:530
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+"\n"
+"Rol LDAP: %s\n"
+
+#: plugins/sudoers/parse.c:533
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+"\n"
+"Entrada de sudoers:\n"
+
+#: plugins/sudoers/parse.c:535
+msgid " RunAsUsers: "
+msgstr " RunAsUsers: "
+
+#: plugins/sudoers/parse.c:550
+msgid " RunAsGroups: "
+msgstr " RunAsGroups: "
+
+#: plugins/sudoers/parse.c:560
+msgid " Options: "
+msgstr " Opcions: "
+
+#: plugins/sudoers/parse.c:614
+msgid " Commands:\n"
+msgstr " Ordres:\n"
+
+#: plugins/sudoers/parse.c:805
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Entrades predeterminades concordants per a %s a %s:\n"
+
+#: plugins/sudoers/parse.c:823
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Runas i valors predeterminats específics d'ordres per a %s:\n"
+
+#: plugins/sudoers/parse.c:841
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "L'usuari %s pot executar les ordres següents a %s:\n"
+
+#: plugins/sudoers/parse.c:856
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "L'usuari %s no té permisos per executar sudo a %s.\n"
+
+#: plugins/sudoers/parse_ldif.c:616
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "ignora completament a sudoRole: cn: %s"
+
+#: plugins/sudoers/parse_ldif.c:676
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "atribut LDIF no vàlid: %s"
+
+#: plugins/sudoers/policy.c:78 plugins/sudoers/policy.c:108
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "%.*s establert pel frontal de sudo"
+
+#: plugins/sudoers/policy.c:314 plugins/sudoers/testsudoers.c:269
+msgid "unable to parse network address list"
+msgstr "no s'ha pogut analitzar la llista d'adreces de xarxa"
+
+#: plugins/sudoers/policy.c:465
+msgid "user name not set by sudo front-end"
+msgstr "nom d'usuari no establert pel frontal de sudo"
+
+#: plugins/sudoers/policy.c:469
+msgid "user-ID not set by sudo front-end"
+msgstr "ID d'usuari no establers pel frontal de sudo"
+
+#: plugins/sudoers/policy.c:473
+msgid "group-ID not set by sudo front-end"
+msgstr "ID de grup no establert pel frontal de sudo"
+
+#: plugins/sudoers/policy.c:477
+msgid "host name not set by sudo front-end"
+msgstr "nom d'amfitrió no establert pel frontal de sudo"
+
+#: plugins/sudoers/policy.c:660
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "director de treball no vàlid: %s"
+
+#: plugins/sudoers/policy.c:828
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "directori chroot no vàlid: %s"
+
+#: plugins/sudoers/policy.c:963 plugins/sudoers/visudo.c:229
+#: plugins/sudoers/visudo.c:851
+#, c-format
+msgid "unable to execute %s"
+msgstr "no s'ha pogut executar %s"
+
+#: plugins/sudoers/policy.c:1030 plugins/sudoers/policy.c:1067
+#: plugins/sudoers/policy.c:1089 plugins/sudoers/policy.c:1115
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: etiquetes no vàlides de mode del frontal del sudo: 0x%x"
+
+#: plugins/sudoers/policy.c:1146
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Versió del connector de política de sudoers %s\n"
+
+#: plugins/sudoers/policy.c:1148
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Versió de gramàtica del fitxer sudoers %d\n"
+
+#: plugins/sudoers/policy.c:1152
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Camí del sudoers: %s\n"
+
+#: plugins/sudoers/policy.c:1155
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "camí del nsswitch: %s\n"
+
+#: plugins/sudoers/policy.c:1157
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "camí de ldap.conf: %s\n"
+
+#: plugins/sudoers/policy.c:1158
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "camí del ldap.secret: %s\n"
+
+#: plugins/sudoers/policy.c:1191
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "no s'ha pogut registrar el lligam de tipus %d (versió %d.%d)"
+
+#: plugins/sudoers/policy.c:1209
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "no s'ha pogut cancel·lar el registre del hook de tipus %d (versió %d.%d)"
+
+#: plugins/sudoers/pwutil.c:218 plugins/sudoers/pwutil.c:236
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "no s'ha pogut posar al cau l'uid %u"
+
+#: plugins/sudoers/pwutil.c:230
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "no s'ha pogut posar l'uid %u al cau, ja existeix"
+
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:308
+#: plugins/sudoers/pwutil.c:371 plugins/sudoers/pwutil.c:416
+#, c-format
+msgid "unable to cache user %s"
+msgstr "no s'ha pogut posar al cau l'usuari %s"
+
+#: plugins/sudoers/pwutil.c:303
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "no s'ha pogut posar l'usuari %s al cau, ja existeix"
+
+#: plugins/sudoers/pwutil.c:535 plugins/sudoers/pwutil.c:553
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "no s'ha pogut posar el gid %u al cau"
+
+#: plugins/sudoers/pwutil.c:547
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "no s'ha pogut posar el gid %u al cau, ja existeix"
+
+#: plugins/sudoers/pwutil.c:601 plugins/sudoers/pwutil.c:619
+#: plugins/sudoers/pwutil.c:680 plugins/sudoers/pwutil.c:730
+#, c-format
+msgid "unable to cache group %s"
+msgstr "no s'ha pogut posar al cau al grup %s"
+
+#: plugins/sudoers/pwutil.c:614
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "no s'ha pogut posar el grup %s al cau, ja existeix"
+
+#: plugins/sudoers/pwutil.c:877 plugins/sudoers/pwutil.c:928
+#: plugins/sudoers/pwutil.c:978 plugins/sudoers/pwutil.c:1030
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "no s'ha pogut la llista de grups al cau per a %s, ja existeix"
+
+#: plugins/sudoers/pwutil.c:883 plugins/sudoers/pwutil.c:933
+#: plugins/sudoers/pwutil.c:984 plugins/sudoers/pwutil.c:1035
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "no s'ha pogut posar al cau a la llista de grup %s"
+
+#: plugins/sudoers/pwutil.c:922
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "no s'han pogut analitzar els grups per a %s"
+
+#: plugins/sudoers/pwutil.c:1024
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "no s'han pogut analitzar els identificadors de grups per a %s"
+
+#: plugins/sudoers/set_perms.c:114 plugins/sudoers/set_perms.c:441
+#: plugins/sudoers/set_perms.c:844 plugins/sudoers/set_perms.c:1150
+#: plugins/sudoers/set_perms.c:1444
+msgid "perm stack overflow"
+msgstr "desbordament de la pila de permisos"
+
+#: plugins/sudoers/set_perms.c:122 plugins/sudoers/set_perms.c:372
+#: plugins/sudoers/set_perms.c:449 plugins/sudoers/set_perms.c:711
+#: plugins/sudoers/set_perms.c:852 plugins/sudoers/set_perms.c:1074
+#: plugins/sudoers/set_perms.c:1158 plugins/sudoers/set_perms.c:1377
+#: plugins/sudoers/set_perms.c:1452 plugins/sudoers/set_perms.c:1542
+msgid "perm stack underflow"
+msgstr "subdesbordament de la pila de permisos"
+
+#: plugins/sudoers/set_perms.c:181 plugins/sudoers/set_perms.c:495
+#: plugins/sudoers/set_perms.c:1211 plugins/sudoers/set_perms.c:1485
+msgid "unable to change to root gid"
+msgstr "no s'ha pogut canvir el gid de l'usuari primari"
+
+#: plugins/sudoers/set_perms.c:272 plugins/sudoers/set_perms.c:592
+#: plugins/sudoers/set_perms.c:983 plugins/sudoers/set_perms.c:1288
+msgid "unable to change to runas gid"
+msgstr "no s'ha pogut canviar el gid runas"
+
+#: plugins/sudoers/set_perms.c:277 plugins/sudoers/set_perms.c:597
+#: plugins/sudoers/set_perms.c:988 plugins/sudoers/set_perms.c:1293
+msgid "unable to set runas group vector"
+msgstr "no s'ha pogut configurar el vector de grup runas"
+
+#: plugins/sudoers/set_perms.c:288 plugins/sudoers/set_perms.c:608
+#: plugins/sudoers/set_perms.c:997 plugins/sudoers/set_perms.c:1302
+msgid "unable to change to runas uid"
+msgstr "no s'ha pogut canviar l'uid runas"
+
+#: plugins/sudoers/set_perms.c:306 plugins/sudoers/set_perms.c:626
+#: plugins/sudoers/set_perms.c:1013 plugins/sudoers/set_perms.c:1318
+msgid "unable to change to sudoers gid"
+msgstr "no s'ha pogut canvir el gid del sudoers"
+
+#: plugins/sudoers/set_perms.c:359 plugins/sudoers/set_perms.c:698
+#: plugins/sudoers/set_perms.c:1061 plugins/sudoers/set_perms.c:1364
+#: plugins/sudoers/set_perms.c:1529
+msgid "too many processes"
+msgstr "massa processos"
+
+#: plugins/sudoers/solaris_audit.c:61
+msgid "unable to get current working directory"
+msgstr "no s'ha pogut obtenir el directori actual de treball"
+
+#: plugins/sudoers/solaris_audit.c:69
+#, c-format
+msgid "truncated audit path user_cmnd: %s"
+msgstr "camí truncat d'auditoria use_cmd: %s"
+
+#: plugins/sudoers/solaris_audit.c:76
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "camí truncat d'auditoria argv[0]: %s"
+
+#: plugins/sudoers/sssd.c:572
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "no s'ha pogut inicialitzar la font del SSS. Està el SSSD instal·lat al vostre sistema?"
+
+#: plugins/sudoers/sssd.c:580 plugins/sudoers/sssd.c:589
+#: plugins/sudoers/sssd.c:598 plugins/sudoers/sssd.c:607
+#: plugins/sudoers/sssd.c:616
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "no s'ha pogut trobar el símbol \"%s\" a %s"
+
+#: plugins/sudoers/sudoers.c:213 plugins/sudoers/sudoers.c:985
+msgid "problem with defaults entries"
+msgstr "hi ha un problema amb les entrades predeterminades"
+
+#: plugins/sudoers/sudoers.c:217
+msgid "no valid sudoers sources found, quitting"
+msgstr "no s'han trobat fonts vàlides de sudoers, se sortirà"
+
+#: plugins/sudoers/sudoers.c:291
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "l'usuari no té permisos per canviar el directori arrel a %s"
+
+#: plugins/sudoers/sudoers.c:293
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "no teniu permisos per usar l'opció -R amb %s"
+
+#: plugins/sudoers/sudoers.c:318
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "l'usuari no té permisos per canviar el directori a %s"
+
+#: plugins/sudoers/sudoers.c:319
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "no teniu permisos per usar l'opció -D amb %s"
+
+#: plugins/sudoers/sudoers.c:345
+msgid "no command specified"
+msgstr "no s'ha especificat una ordre"
+
+#: plugins/sudoers/sudoers.c:355
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "el fitxer sudoers especifica que l'usuari primar no pot executar sudo"
+
+#: plugins/sudoers/sudoers.c:403
+msgid "user not allowed to override closefrom limit"
+msgstr "l'usuari no té permís per anul·lar el límit closefrom"
+
+#: plugins/sudoers/sudoers.c:404
+msgid "you are not permitted to use the -C option"
+msgstr "no teniu permisos per usar l'opció -C"
+
+#: plugins/sudoers/sudoers.c:464
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr "propietari de la marca horària (%s): No existeix aquest usuari"
+
+#: plugins/sudoers/sudoers.c:479
+msgid "no tty"
+msgstr "no hi ha una terminal"
+
+#: plugins/sudoers/sudoers.c:480
+msgid "sorry, you must have a tty to run sudo"
+msgstr "ho sentim, heu de tenir una terminal per executar sudo"
+
+#: plugins/sudoers/sudoers.c:487
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "entorn d'ordres no vàlid per a l'usuari %s: %s"
+
+#: plugins/sudoers/sudoers.c:570
+msgid "command in current directory"
+msgstr "ordre al directori actual"
+
+#: plugins/sudoers/sudoers.c:589
+msgid "user not allowed to set a command timeout"
+msgstr "l'usuari no té permís per establir un temps d'espera a l'ordre"
+
+#: plugins/sudoers/sudoers.c:591
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "ho sentim, no teniu permisos per posar un temps d'espera d'ordre"
+
+#: plugins/sudoers/sudoers.c:599
+msgid "user not allowed to preserve the environment"
+msgstr "l'usuari no té permís per preservar l'entorn"
+
+#: plugins/sudoers/sudoers.c:601
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "ho sentim, no teniu permisos per preserver l'entorn"
+
+#: plugins/sudoers/sudoers.c:936
+msgid "command too long"
+msgstr "ordre massa llarga"
+
+#: plugins/sudoers/sudoers.c:973
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "no cal executar el sudoedit mitjançant sudo"
+
+#: plugins/sudoers/sudoers.c:1032 plugins/sudoers/sudoreplay.c:1547
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "no s'ha pogut llegir %s"
+
+#: plugins/sudoers/sudoers.c:1057 plugins/sudoers/visudo.c:426
+#: plugins/sudoers/visudo.c:720
+#, c-format
+msgid "unable to stat %s"
+msgstr "no s'ha pogut accedir %s"
+
+#: plugins/sudoers/sudoers.c:1061 plugins/sudoers/visudo.c:1009
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s no és un fitxer regular"
+
+#: plugins/sudoers/sudoers.c:1065 plugins/sudoers/timestamp.c:252 toke.l:1138
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s és propietat de l'uid %u, hauria de ser %u"
+
+#: plugins/sudoers/sudoers.c:1069 toke.l:1143
+#, c-format
+msgid "%s is world writable"
+msgstr "%s te permís universal d'escriptura"
+
+#: plugins/sudoers/sudoers.c:1073 toke.l:1146
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s és propietat del gid %u, hauria de ser %u"
+
+#: plugins/sudoers/sudoers.c:1106
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "sols l'usuari primari pot usar «-c %s»"
+
+#: plugins/sudoers/sudoers.c:1125
+#, c-format
+msgid "unknown login class: %s"
+msgstr "classe desconeguda d'inici de sessió: %s"
+
+#: plugins/sudoers/sudoers.c:1211 plugins/sudoers/sudoers.c:1226
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "no s'ha pogut resoldre l'amfitrió %s"
+
+#: plugins/sudoers/sudoreplay.c:257
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "opció no vàlida de filtre: %s"
+
+#: plugins/sudoers/sudoreplay.c:273
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "espera màxima no vàlida: %s"
+
+#: plugins/sudoers/sudoreplay.c:296
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "factor no vàlid de velocitat: %s"
+
+#: plugins/sudoers/sudoreplay.c:332
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:337
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/sincronització: %s"
+
+#: plugins/sudoers/sudoreplay.c:341
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: plugins/sudoers/sudoreplay.c:365
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "S'està reproduint la sessió sudo: %s"
+
+#: plugins/sudoers/sudoreplay.c:627
+msgid "unable to set tty to raw mode"
+msgstr "no s'ha pogut configurar el terminal a mode de dades en brut"
+
+#: plugins/sudoers/sudoreplay.c:678
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr "Advertiment: el vostre terminal és massa petit per reproduir apropiadament el registre.\n"
+
+#: plugins/sudoers/sudoreplay.c:679
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "La geometria del registre és %d x %d, la geometria del vostre terminal és %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:707
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Reproducció acabada, premeu qualsevol tecla per restablir la terminal."
+
+#: plugins/sudoers/sudoreplay.c:1197 plugins/sudoers/sudoreplay.c:1227
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "expressió ambigua \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1249
+msgid "unmatched ')' in expression"
+msgstr "')' sense concordança a l'expressió"
+
+#: plugins/sudoers/sudoreplay.c:1253
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "terme desconegut de cerca \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1268
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s requereix un argument"
+
+#: plugins/sudoers/sudoreplay.c:1271 plugins/sudoers/sudoreplay.c:1523
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr "expressió regular no vàlida: %s"
+
+#: plugins/sudoers/sudoreplay.c:1276
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "no s'ha pogut analitzar la data \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1285
+msgid "unmatched '(' in expression"
+msgstr "'(' sense concordança a l'expressió"
+
+#: plugins/sudoers/sudoreplay.c:1287
+msgid "illegal trailing \"or\""
+msgstr "\"or\" final il·legal"
+
+#: plugins/sudoers/sudoreplay.c:1289
+msgid "illegal trailing \"!\""
+msgstr "\"!\" final il·legal"
+
+#: plugins/sudoers/sudoreplay.c:1347
+#, c-format
+msgid "unknown search type %d"
+msgstr "tipus desconegut de cerca %d"
+
+#: plugins/sudoers/sudoreplay.c:1614
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "ús: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1617
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "usage: %s [-h] [-d dir] -l [cerca l'expressió]\n"
+
+#: plugins/sudoers/sudoreplay.c:1626
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - reprodueix els registres de la sessió sudo\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1628
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Opcions:\n"
+" -d, --directori=dir especifiqueu el directori per als registres de la sessió\n"
+" -f, --filter=filtre especifiqueu quin(s) tipus d'entrada/sortida mostrar\n"
+" -h, --help mostra el missatge d'ajuda i surt\n"
+" -l, --list mostra una llista dels IDs de les sessions\n"
+" disponibles, amb expressions opcionals\n"
+" -m, --max-wait=num nombre màxim de segons a esperar entre esdeveniments\n"
+" -n, --non-interactive sense preguntes, la sessió s'envia a la sortida estàndard\n"
+" -R, --no-resize no intentis redimensionar la terminal\n"
+" -S, --suspend-wait espera mentre s'ha suspès l'ordre\n"
+" -s, --speed=num accelera o alenteix la sortida\n"
+" -V, --version mostra la versió d'informació i surt"
+
+#: plugins/sudoers/testsudoers.c:345
+msgid "\thost unmatched"
+msgstr "\tamfitrió sense concordança"
+
+#: plugins/sudoers/testsudoers.c:348
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Ordre permesa"
+
+#: plugins/sudoers/testsudoers.c:349
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Ordre denegada"
+
+#: plugins/sudoers/testsudoers.c:349
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Ordre sense concordança"
+
+#: plugins/sudoers/timestamp.c:260
+#, c-format
+msgid "%s is group writable"
+msgstr "%s és modificable pel grup"
+
+#: plugins/sudoers/timestamp.c:326 plugins/sudoers/timestamp.c:661
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "no s'ha pogut truncar el fitxer de marca horària a %lld bytes"
+
+#: plugins/sudoers/timestamp.c:847
+msgid "ignoring time stamp from the future"
+msgstr "s'ignorarà la marca horària del futur"
+
+#: plugins/sudoers/timestamp.c:870
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "la marca horària està massa lluny en el futur: %20.20s"
+
+#: plugins/sudoers/timestamp.c:992
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "no s'ha pogut bloquejar el fitxer de marca horària %s"
+
+#: plugins/sudoers/timestamp.c:1036 plugins/sudoers/timestamp.c:1056
+#, c-format
+msgid "lecture status path too long: %s/%s"
+msgstr "el camí de la lliçó es massa llarg: %s/%s"
+
+#: plugins/sudoers/toke_util.c:150
+msgid "sudoedit should not be specified with a path"
+msgstr "no s'hauria d'especificar el sudoedit amb un camí"
+
+#: plugins/sudoers/visudo.c:224
+msgid "the -x option will be removed in a future release"
+msgstr "s'eliminarà l'opció -x en una versió futura"
+
+#: plugins/sudoers/visudo.c:226
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "si us plau considereu usar la utilitat cvtsudoers en canvi"
+
+#: plugins/sudoers/visudo.c:277 plugins/sudoers/visudo.c:653
+#, c-format
+msgid "press return to edit %s: "
+msgstr "prem la tecla d'introducció per editar %s: "
+
+#: plugins/sudoers/visudo.c:338
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "l'editor especificat (%s) no existeix"
+
+#: plugins/sudoers/visudo.c:340
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "no s'ha trobat un editor (el camí de l'editor = %s)"
+
+#: plugins/sudoers/visudo.c:446 plugins/sudoers/visudo.c:454
+msgid "write error"
+msgstr "error d'escriptura"
+
+#: plugins/sudoers/visudo.c:500
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "no s'ha pogut accedir al fitxer temporal (%s), no s'ha modificat %s"
+
+#: plugins/sudoers/visudo.c:507
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "fitxer temporal amb longitud nul·la (%s), no s'ha modificat %s"
+
+#: plugins/sudoers/visudo.c:513
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "l'editor (%s) ha fallat, no s'ha modificat %s"
+
+#: plugins/sudoers/visudo.c:535
+#, c-format
+msgid "%s unchanged"
+msgstr "no s'ha modificat %s"
+
+#: plugins/sudoers/visudo.c:592
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "no s'ha pogut reobrir el fitxer temporal (%s), no s'ha modificat %s"
+
+#: plugins/sudoers/visudo.c:604
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "no es pot analitzar el fitxer temporal (%s), error desconegut"
+
+#: plugins/sudoers/visudo.c:642
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr "error intern, no s'ha pogut trobar %s a la llista!"
+
+#: plugins/sudoers/visudo.c:722 plugins/sudoers/visudo.c:731
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "no s'ha pogut establir (uid, gid) de %s a (%u, %u)"
+
+#: plugins/sudoers/visudo.c:754
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s i %s no estan al mateix sistema de fitxers, s'usarà mv per reanomenar"
+
+#: plugins/sudoers/visudo.c:765
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "l'ordre ha fallat: '%s %s %s', no s'ha modificat %s"
+
+#: plugins/sudoers/visudo.c:775
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "error quan s'estava reanomenant %s, no s'ha modificat %s"
+
+#: plugins/sudoers/visudo.c:796
+msgid "What now? "
+msgstr "Què fem ara? "
+
+#: plugins/sudoers/visudo.c:810
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Les opcions són:\n"
+" (e)dita el fitxer sudoers un altre cop\n"
+" (x) surt sense desar els canvis al fitxer sudoers\n"
+" (Q) surt i desa el canvis el fitxer sudoers (PERILL!)\n"
+
+#: plugins/sudoers/visudo.c:856
+#, c-format
+msgid "unable to run %s"
+msgstr "no s'ha pogut executar %s"
+
+#: plugins/sudoers/visudo.c:886
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: propietari incorrecte (uid, gid) hauria de ser (%uk, %u)\n"
+
+#: plugins/sudoers/visudo.c:893
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: permisos dolents, hauria de ser mode 0%o\n"
+
+#: plugins/sudoers/visudo.c:942 plugins/sudoers/visudo.c:949
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: s'analitzat correctament\n"
+
+#: plugins/sudoers/visudo.c:968
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s està ocupat, proveu un altre cop més tard"
+
+#: plugins/sudoers/visudo.c:971
+#, c-format
+msgid "unable to lock %s"
+msgstr "no s'ha pogut bloquejar %s"
+
+#: plugins/sudoers/visudo.c:972
+msgid "Edit anyway? [y/N]"
+msgstr "Editar igualment? [y/N]"
+
+#: plugins/sudoers/visudo.c:1067
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "Advertiment: %s:%d:%d: no usat %s «%s»"
+
+#: plugins/sudoers/visudo.c:1183
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - edita amb seguretat el fitxer sudoers\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1185
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Opcions:\n"
+" -c, --check mode de sols verificació\n"
+" -f, --file=sudoers especifiqueu la ubicació del fitxer sudoers\n"
+" -h, --help mostra el missatge d'ajuda i surt\n"
+" -q, --quiet missatges d'error de sintaxi menys informatius (silenciós)\n"
+" -s, --strict verificació estricta de la sintaxi\n"
+" -V, --version mostra la informació de la versió i surt\n"
+
+#: toke.l:187
+msgid "empty string"
+msgstr "cadena buida de caràcters"
+
+#: toke.l:199 toke.l:503
+msgid "empty group"
+msgstr "grup buit"
+
+#: toke.l:209 toke.l:501
+msgid "empty netgroup"
+msgstr "netgroup buit"
+
+#: toke.l:305 toke.l:317 toke.l:329 toke.l:345 toke.l:364 toke.l:404
+msgid "invalid line continuation"
+msgstr "continuació no vàlida de línia"
+
+#: toke.l:540 toke.l:552
+msgid "invalid IPv6 address"
+msgstr "adreça IPv6 no vàlida"
+
+#: toke.l:779
+msgid "unexpected line break in string"
+msgstr "salt inesperat de línia a la cadena de caràcters"
+
+#: toke.l:1109
+msgid "too many levels of includes"
+msgstr "massa nivells d'inclusions"
+
+#~ msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+#~ msgstr "Pre-carrega les funcions dummy exex contingudes a la biblioteca sudo_noexec"
+
+#~ msgid "sudo_ldap_conf_add_ports: port too large"
+#~ msgstr "sudo_ldap_conf_add_ports: el port és massa gran"
+
+#~ msgid "unable to lock log file: %s"
+#~ msgstr "no s'ha pogut bloquejar el fitxer de registre: %s"
+
+#~ msgid "No user or host"
+#~ msgstr "No hi ha usuari o amfitrió"
+
+#~ msgid "validation failure"
+#~ msgstr "ha fallat la validació"
+
+#~ msgid "audit_failure message too long"
+#~ msgstr "missatge audit_failure massa llarg"
+
+#~ msgid "%s/%s/timing: %s"
+#~ msgstr "%s/%s/temporització: %s"
+
+#~ msgid ""
+#~ "\n"
+#~ "LDAP Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Rol LDAP: DESCONEGUT\n"
+
+#~ msgid " Order: %s\n"
+#~ msgstr " Ordre: %s\n"
+
+#~ msgid "unable to cache user %s, out of memory"
+#~ msgstr "no s'ha pogut posar l'usuari %s, s'ha exhaurit la memòria"
+
+#~ msgid "unable to cache group %s, out of memory"
+#~ msgstr "no s'ha pogut posar el grup %s al cau, s'ha exhaurit"
+
+#~ msgid "unable to cache group list for %s, out of memory"
+#~ msgstr "no s'ha pogut la llista de grups al cau per a %s, s'ha exhaurit la memòria"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: %s\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Rol SSDD: %s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Rol SSSD: DESCONEGUT\n"
+
+#~ msgid "Warning: cycle in %s `%s'"
+#~ msgstr "Advertiment: cicle a %s `%s'"
+
+#~ msgid "Warning: %s `%s' referenced but not defined"
+#~ msgstr "Advertiment: s'ha referenciat però no s'ha definit %s `%s'"
+
+#~ msgid "Warning: unused %s `%s'"
+#~ msgstr "Advertiment: %s `%s' sense usar"
+
+#~ msgid "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+#~ msgstr "sudo_ldap_conf_add_ports: s'ha exhaurit l'espai quan s'estava expandint hostbuf"
+
+#~ msgid "sudo_ldap_parse_uri: out of space building hostbuf"
+#~ msgstr "sudo_ldap_parse_uri: s'ha exhaurit l'espai construint hostbuf"
+
+#~ msgid "sudo_ldap_build_pass1 allocation mismatch"
+#~ msgstr "discordança d'assignació de sudo_ldap_build_pass1"
+
+#~ msgid "timestamp path too long: %s/%s"
+#~ msgstr "el camí de la marca horària és massa llarg: %s/%s"
+
+#~ msgid "unable to stat editor (%s)"
+#~ msgstr "no s'ha pogut accedir l'editor (%s)"
+
+#~ msgid "internal error: insufficient space for log line"
+#~ msgstr "error intern: espai insuficient per a la línia de registre"
+
+#~ msgid "fill_args: buffer overflow"
+#~ msgstr "fill_args: desbordament de la memòria intermèdia"
diff --git a/plugins/sudoers/po/cs.mo b/plugins/sudoers/po/cs.mo
new file mode 100644
index 0000000..134e5a7
--- /dev/null
+++ b/plugins/sudoers/po/cs.mo
Binary files differ
diff --git a/plugins/sudoers/po/cs.po b/plugins/sudoers/po/cs.po
new file mode 100644
index 0000000..6554cd8
--- /dev/null
+++ b/plugins/sudoers/po/cs.po
@@ -0,0 +1,4144 @@
+# Czech translation for sudo.
+# This file is distributed under the same license as the sudo package.
+# Todd C. Miller <Todd.Miller@courtesan.com>, 2011-2013
+# Petr Pisar <petr.pisar@atlas.cz>, 2013, 2014, 2015, 2016, 2017, 2018, 2019.
+# Petr Pisar <petr.pisar@atlas.cz>, 2020, 2021, 2022, 2023.
+#
+# (AIX) registry → (AIXový) registr
+# I/O (log) → I/O (log)
+# timestamp → časové údaje
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.9.15b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-10-19 10:02-0600\n"
+"PO-Revision-Date: 2023-10-25 21:33+02:00\n"
+"Last-Translator: Petr Pisar <petr.pisar@atlas.cz>\n"
+"Language-Team: Czech <translation-team-cs@lists.sourceforge.net>\n"
+"Language: cs\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+#: confstr.sh:1 gram.y:1257 plugins/sudoers/logging.c:911
+msgid "syntax error"
+msgstr "chyba syntaxe"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "Heslo pro %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] heslo pro %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Heslo: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** BEZPEČNOSTNÍ hlášení o %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Je nám líto, zkuste to znovu."
+
+#: gram.y:238 gram.y:305 gram.y:314 gram.y:323 gram.y:333 gram.y:343 gram.y:367
+#: gram.y:394 gram.y:403 gram.y:411 gram.y:420 gram.y:429 gram.y:503 gram.y:513
+#: gram.y:525 gram.y:573 gram.y:582 gram.y:591 gram.y:600 gram.y:733 gram.y:742
+#: gram.y:757 gram.y:777 gram.y:796 gram.y:959 gram.y:964 gram.y:972 gram.y:986
+#: gram.y:992 gram.y:1004 gram.y:1010 gram.y:1135 gram.y:1144 gram.y:1152
+#: gram.y:1161 gram.y:1170 gram.y:1199 gram.y:1208 gram.y:1216 gram.y:1317
+#: gram.y:1447 gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:313 lib/eventlog/eventlog.c:765
+#: lib/eventlog/eventlog.c:842 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:484
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:185
+#: logsrvd/iolog_writer.c:218 logsrvd/iolog_writer.c:228
+#: logsrvd/iolog_writer.c:257 logsrvd/iolog_writer.c:278
+#: logsrvd/iolog_writer.c:290 logsrvd/iolog_writer.c:300
+#: logsrvd/iolog_writer.c:310 logsrvd/iolog_writer.c:320
+#: logsrvd/iolog_writer.c:330 logsrvd/iolog_writer.c:342
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:1057 logsrvd/logsrvd.c:1120 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:650
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1743
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:216
+#: logsrvd/logsrvd_journal.c:217 logsrvd/logsrvd_journal.c:274
+#: logsrvd/logsrvd_journal.c:279 logsrvd/logsrvd_journal.c:439
+#: logsrvd/logsrvd_journal.c:441 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:216 logsrvd/logsrvd_local.c:278
+#: logsrvd/logsrvd_local.c:279 logsrvd/logsrvd_local.c:417
+#: logsrvd/logsrvd_local.c:468 logsrvd/logsrvd_local.c:469
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:475
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/logsrvd_relay.c:446
+#: logsrvd/logsrvd_relay.c:748 logsrvd/logsrvd_relay.c:855
+#: logsrvd/sendlog.c:256 logsrvd/sendlog.c:265 logsrvd/sendlog.c:297
+#: logsrvd/sendlog.c:303 logsrvd/sendlog.c:352 logsrvd/sendlog.c:630
+#: logsrvd/sendlog.c:1822 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/bsdauth.c:154 plugins/sudoers/auth/kerb5.c:122
+#: plugins/sudoers/auth/kerb5.c:150 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/auth/sia.c:61
+#: plugins/sudoers/canon_path.c:129 plugins/sudoers/canon_path.c:161
+#: plugins/sudoers/check_aliases.c:128 plugins/sudoers/check_util.c:56
+#: plugins/sudoers/check_util.c:84 plugins/sudoers/cvtsudoers.c:132
+#: plugins/sudoers/cvtsudoers.c:176 plugins/sudoers/cvtsudoers.c:193
+#: plugins/sudoers/cvtsudoers.c:204 plugins/sudoers/cvtsudoers.c:338
+#: plugins/sudoers/cvtsudoers.c:379 plugins/sudoers/cvtsudoers.c:399
+#: plugins/sudoers/cvtsudoers.c:545 plugins/sudoers/cvtsudoers.c:698
+#: plugins/sudoers/cvtsudoers.c:716 plugins/sudoers/cvtsudoers.c:891
+#: plugins/sudoers/cvtsudoers.c:899 plugins/sudoers/cvtsudoers.c:1395
+#: plugins/sudoers/cvtsudoers.c:1399 plugins/sudoers/cvtsudoers.c:1501
+#: plugins/sudoers/cvtsudoers_csv.c:183 plugins/sudoers/cvtsudoers_csv.c:247
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:152
+#: plugins/sudoers/cvtsudoers_ldif.c:195 plugins/sudoers/cvtsudoers_ldif.c:236
+#: plugins/sudoers/cvtsudoers_ldif.c:302 plugins/sudoers/cvtsudoers_ldif.c:378
+#: plugins/sudoers/cvtsudoers_ldif.c:432 plugins/sudoers/cvtsudoers_ldif.c:440
+#: plugins/sudoers/cvtsudoers_ldif.c:451 plugins/sudoers/cvtsudoers_ldif.c:458
+#: plugins/sudoers/cvtsudoers_ldif.c:470 plugins/sudoers/cvtsudoers_ldif.c:483
+#: plugins/sudoers/cvtsudoers_ldif.c:491 plugins/sudoers/cvtsudoers_ldif.c:638
+#: plugins/sudoers/cvtsudoers_merge.c:47 plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1158
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:212
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:694 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:294 plugins/sudoers/ldap_util.c:301
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:402
+#: plugins/sudoers/log_client.c:717 plugins/sudoers/log_client.c:739
+#: plugins/sudoers/log_client.c:744 plugins/sudoers/log_client.c:1426
+#: plugins/sudoers/log_client.c:1547 plugins/sudoers/log_client.c:1670
+#: plugins/sudoers/log_client.c:1993 plugins/sudoers/log_client.c:2052
+#: plugins/sudoers/logging.c:110 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:872 plugins/sudoers/lookup.c:338
+#: plugins/sudoers/lookup.c:355 plugins/sudoers/lookup.c:374
+#: plugins/sudoers/lookup.c:393 plugins/sudoers/lookup.c:410
+#: plugins/sudoers/lookup.c:433 plugins/sudoers/lookup.c:444
+#: plugins/sudoers/match_command.c:302 plugins/sudoers/match_command.c:574
+#: plugins/sudoers/match_command.c:641 plugins/sudoers/match_command.c:737
+#: plugins/sudoers/match_command.c:785 plugins/sudoers/match_digest.c:88
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:595
+#: plugins/sudoers/parse_ldif.c:625 plugins/sudoers/parse_ldif.c:650
+#: plugins/sudoers/parse_ldif.c:708 plugins/sudoers/parse_ldif.c:725
+#: plugins/sudoers/parse_ldif.c:753 plugins/sudoers/parse_ldif.c:760
+#: plugins/sudoers/policy.c:646 plugins/sudoers/policy.c:1061
+#: plugins/sudoers/prompt.c:94 plugins/sudoers/pwutil.c:219
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:368
+#: plugins/sudoers/pwutil.c:542 plugins/sudoers/pwutil.c:607
+#: plugins/sudoers/pwutil.c:679 plugins/sudoers/pwutil.c:877
+#: plugins/sudoers/pwutil.c:967 plugins/sudoers/pwutil.c:1015
+#: plugins/sudoers/pwutil.c:1076 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:145 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1307 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:256
+#: plugins/sudoers/testsudoers.c:265 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:164 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1095
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1320
+msgid "unable to allocate memory"
+msgstr "nelze alokovat paměť"
+
+#: gram.y:624
+msgid "a digest requires a path name"
+msgstr "kontrolní součet vyžaduje název cesty"
+
+#: gram.y:646
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "hodnoty „CWD“ musí začínat na „/“, „~“ nebo „*“"
+
+#: gram.y:652
+msgid "\"CWD\" path too long"
+msgstr "cesta „CWD“ je příliš dlouhá"
+
+#: gram.y:662
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "hodnoty „CHROOT“ musí začínat na „/“, „~“ nebo „*“"
+
+#: gram.y:668
+msgid "\"CHROOT\" path too long"
+msgstr "cesta „CHROOT“ je příliš dlouhá"
+
+#: gram.y:817
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "chyba syntaxe, vyhrazené slovo %s použito jako název aliasu"
+
+#: gram.y:840
+msgid "invalid notbefore value"
+msgstr "neplatná hodnota notbefore (začátek platnosti)"
+
+#: gram.y:849
+msgid "invalid notafter value"
+msgstr "neplatná hodnota notafter (konec platnosti)"
+
+#: gram.y:859 plugins/sudoers/policy.c:390
+msgid "timeout value too large"
+msgstr "hodnota časového limitu je příliš velká"
+
+#: gram.y:861 plugins/sudoers/policy.c:392
+msgid "invalid timeout value"
+msgstr "neplatná hodnota časového limitu"
+
+#: gram.y:982 plugins/sudoers/sudoers.c:1162
+msgid "command too long"
+msgstr "příkaz je příliš dlouhý"
+
+#: gram.y:1016
+msgid "expected a fully-qualified path name"
+msgstr "očekává se plně kvalifikovaná cesta"
+
+#: gram.y:1261
+#, c-format
+msgid "%s:%d:%zu: %s\n"
+msgstr "%s:%d:%zu: %s\n"
+
+#: gram.y:1315
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Alias „%s“ je již definován"
+
+#: gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:765 lib/eventlog/eventlog.c:838
+#: lib/eventlog/eventlog.c:841 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:483
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:232
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:174
+#: logsrvd/iolog_writer.c:184 logsrvd/iolog_writer.c:197
+#: logsrvd/iolog_writer.c:217 logsrvd/iolog_writer.c:227
+#: logsrvd/iolog_writer.c:246 logsrvd/iolog_writer.c:256
+#: logsrvd/iolog_writer.c:267 logsrvd/iolog_writer.c:277
+#: logsrvd/iolog_writer.c:289 logsrvd/iolog_writer.c:299
+#: logsrvd/iolog_writer.c:309 logsrvd/iolog_writer.c:319
+#: logsrvd/iolog_writer.c:329 logsrvd/iolog_writer.c:341
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:530
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:668
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:1131
+#: logsrvd/logsrvd.c:1446 logsrvd/logsrvd.c:1453 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:649
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1742
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:125
+#: logsrvd/logsrvd_journal.c:216 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:250 logsrvd/logsrvd_journal.c:258
+#: logsrvd/logsrvd_journal.c:287 logsrvd/logsrvd_journal.c:291
+#: logsrvd/logsrvd_journal.c:439 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:278 logsrvd/logsrvd_local.c:468
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:493
+#: logsrvd/logsrvd_queue.c:158 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/sendlog.c:256 logsrvd/sendlog.c:265
+#: logsrvd/sendlog.c:297 logsrvd/sendlog.c:303 logsrvd/sendlog.c:352
+#: logsrvd/sendlog.c:630 logsrvd/sendlog.c:1523 logsrvd/sendlog.c:1530
+#: logsrvd/sendlog.c:1753 logsrvd/sendlog.c:1822 logsrvd/tls_init.c:305
+#: logsrvd/tls_init.c:329 logsrvd/tls_init.c:340 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/pam.c:518 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/canon_path.c:129
+#: plugins/sudoers/canon_path.c:161 plugins/sudoers/check_aliases.c:128
+#: plugins/sudoers/check_util.c:56 plugins/sudoers/check_util.c:84
+#: plugins/sudoers/cvtsudoers.c:132 plugins/sudoers/cvtsudoers.c:175
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:203
+#: plugins/sudoers/cvtsudoers.c:337 plugins/sudoers/cvtsudoers.c:544
+#: plugins/sudoers/cvtsudoers.c:697 plugins/sudoers/cvtsudoers.c:715
+#: plugins/sudoers/cvtsudoers.c:891 plugins/sudoers/cvtsudoers.c:898
+#: plugins/sudoers/cvtsudoers.c:1395 plugins/sudoers/cvtsudoers.c:1399
+#: plugins/sudoers/cvtsudoers.c:1501 plugins/sudoers/cvtsudoers_csv.c:182
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:151 plugins/sudoers/cvtsudoers_ldif.c:194
+#: plugins/sudoers/cvtsudoers_ldif.c:235 plugins/sudoers/cvtsudoers_ldif.c:301
+#: plugins/sudoers/cvtsudoers_ldif.c:377 plugins/sudoers/cvtsudoers_ldif.c:431
+#: plugins/sudoers/cvtsudoers_ldif.c:439 plugins/sudoers/cvtsudoers_ldif.c:450
+#: plugins/sudoers/cvtsudoers_ldif.c:457 plugins/sudoers/cvtsudoers_ldif.c:469
+#: plugins/sudoers/cvtsudoers_ldif.c:482 plugins/sudoers/cvtsudoers_ldif.c:490
+#: plugins/sudoers/cvtsudoers_ldif.c:637 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51 plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1157
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:211
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:693 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:293 plugins/sudoers/ldap_util.c:300
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:228
+#: plugins/sudoers/log_client.c:250 plugins/sudoers/log_client.c:264
+#: plugins/sudoers/log_client.c:402 plugins/sudoers/log_client.c:717
+#: plugins/sudoers/log_client.c:739 plugins/sudoers/log_client.c:744
+#: plugins/sudoers/log_client.c:1426 plugins/sudoers/log_client.c:1547
+#: plugins/sudoers/log_client.c:1670 plugins/sudoers/log_client.c:1993
+#: plugins/sudoers/log_client.c:2052 plugins/sudoers/logging.c:110
+#: plugins/sudoers/logging.c:189 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:755 plugins/sudoers/logging.c:872
+#: plugins/sudoers/logging.c:925 plugins/sudoers/logging.c:932
+#: plugins/sudoers/lookup.c:337 plugins/sudoers/lookup.c:354
+#: plugins/sudoers/lookup.c:373 plugins/sudoers/lookup.c:392
+#: plugins/sudoers/lookup.c:409 plugins/sudoers/lookup.c:432
+#: plugins/sudoers/lookup.c:443 plugins/sudoers/match_command.c:301
+#: plugins/sudoers/match_command.c:573 plugins/sudoers/match_command.c:640
+#: plugins/sudoers/match_command.c:737 plugins/sudoers/match_command.c:784
+#: plugins/sudoers/match_digest.c:88 plugins/sudoers/parse_ldif.c:152
+#: plugins/sudoers/parse_ldif.c:183 plugins/sudoers/parse_ldif.c:252
+#: plugins/sudoers/parse_ldif.c:260 plugins/sudoers/parse_ldif.c:265
+#: plugins/sudoers/parse_ldif.c:341 plugins/sudoers/parse_ldif.c:352
+#: plugins/sudoers/parse_ldif.c:379 plugins/sudoers/parse_ldif.c:396
+#: plugins/sudoers/parse_ldif.c:408 plugins/sudoers/parse_ldif.c:412
+#: plugins/sudoers/parse_ldif.c:426 plugins/sudoers/parse_ldif.c:484
+#: plugins/sudoers/parse_ldif.c:595 plugins/sudoers/parse_ldif.c:624
+#: plugins/sudoers/parse_ldif.c:649 plugins/sudoers/parse_ldif.c:707
+#: plugins/sudoers/parse_ldif.c:724 plugins/sudoers/parse_ldif.c:752
+#: plugins/sudoers/parse_ldif.c:759 plugins/sudoers/policy.c:157
+#: plugins/sudoers/policy.c:166 plugins/sudoers/policy.c:175
+#: plugins/sudoers/policy.c:204 plugins/sudoers/policy.c:374
+#: plugins/sudoers/policy.c:390 plugins/sudoers/policy.c:392
+#: plugins/sudoers/policy.c:430 plugins/sudoers/policy.c:439
+#: plugins/sudoers/policy.c:448 plugins/sudoers/policy.c:457
+#: plugins/sudoers/policy.c:493 plugins/sudoers/policy.c:502
+#: plugins/sudoers/policy.c:511 plugins/sudoers/policy.c:520
+#: plugins/sudoers/policy.c:529 plugins/sudoers/policy.c:538
+#: plugins/sudoers/policy.c:547 plugins/sudoers/policy.c:646
+#: plugins/sudoers/policy.c:1061 plugins/sudoers/prompt.c:94
+#: plugins/sudoers/pwutil.c:219 plugins/sudoers/pwutil.c:290
+#: plugins/sudoers/pwutil.c:368 plugins/sudoers/pwutil.c:542
+#: plugins/sudoers/pwutil.c:607 plugins/sudoers/pwutil.c:679
+#: plugins/sudoers/pwutil.c:877 plugins/sudoers/pwutil.c:967
+#: plugins/sudoers/pwutil.c:1015 plugins/sudoers/pwutil.c:1076
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1306 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:255
+#: plugins/sudoers/testsudoers.c:264 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:163 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1094
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1309 toke.l:1320
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:304
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "nelze zdvojit standardní vstup: %m"
+
+#: lib/eventlog/eventlog.c:346
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "nelze spustit %s: %m"
+
+#: lib/eventlog/eventlog.c:394 plugins/sudoers/auth/aix_auth.c:199
+msgid "unable to fork"
+msgstr "nelze vytvořit proces"
+
+#: lib/eventlog/eventlog.c:404 lib/eventlog/eventlog.c:471
+#, c-format
+msgid "unable to fork: %m"
+msgstr "nelze vytvořit proces: %m"
+
+#: lib/eventlog/eventlog.c:461
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "nelze otevřít rouru: %m"
+
+#: lib/eventlog/eventlog.c:1000
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:1029
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (příkaz pokračuje) %s"
+
+#: lib/eventlog/parse_json.c:175
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "očekáván JSON_STRING, obdrženo %d"
+
+#: lib/eventlog/parse_json.c:180
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY je příliš velké"
+
+#: lib/eventlog/parse_json.c:506
+msgid "missing double quote in name"
+msgstr "v názvu chybí dvojitá uvozovka"
+
+#: lib/eventlog/parse_json.c:624
+msgid "missing JSON_OBJECT"
+msgstr "chybí JSON_OBJECT"
+
+#: lib/eventlog/parse_json.c:628
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "očekáván JSON_OBJECT, obdrženo %d"
+
+#: lib/eventlog/parse_json.c:762
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "jsonový zásobník vyčerpán (nejvýše %u rámců)"
+
+#: lib/eventlog/parse_json.c:840
+msgid "objects must consist of name:value pairs"
+msgstr "objekty musí sestávat z dvojic název:hodnota"
+
+#: lib/eventlog/parse_json.c:845 lib/eventlog/parse_json.c:876
+#: lib/eventlog/parse_json.c:920 lib/eventlog/parse_json.c:942
+#: lib/eventlog/parse_json.c:964 lib/eventlog/parse_json.c:986
+#: lib/eventlog/parse_json.c:1008
+msgid "missing separator between values"
+msgstr "chybí oddělovač mezí hodnotami"
+
+#: lib/eventlog/parse_json.c:860 lib/eventlog/parse_json.c:1034
+msgid "unmatched close brace"
+msgstr "neodpovídající uzavírací složená závorka"
+
+#: lib/eventlog/parse_json.c:871
+msgid "unexpected array"
+msgstr "nečekané pole"
+
+#: lib/eventlog/parse_json.c:891 lib/eventlog/parse_json.c:1037
+msgid "unmatched close bracket"
+msgstr "neodpovídající uzavírající hranatá závorka"
+
+#: lib/eventlog/parse_json.c:902
+msgid "unexpected string"
+msgstr "nečekaný řetězec"
+
+#: lib/eventlog/parse_json.c:913
+msgid "missing colon after name"
+msgstr "za názvem chybí dvojtečka"
+
+#: lib/eventlog/parse_json.c:934 lib/eventlog/parse_json.c:956
+msgid "unexpected boolean"
+msgstr "nečekaná pravdivostní hodnota"
+
+#: lib/eventlog/parse_json.c:978
+msgid "unexpected null"
+msgstr "nečekaná hodnota null"
+
+#: lib/eventlog/parse_json.c:999
+msgid "unexpected number"
+msgstr "nečekané číslo"
+
+#: lib/eventlog/parse_json.c:1045
+msgid "parse error"
+msgstr "chyba rozboru"
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1290
+#: plugins/sudoers/sudoreplay.c:1291 plugins/sudoers/sudoreplay.c:1587
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr "neplatný regulární výraz „%s“: %s"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: neplatný soubor s protokolem"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: chybí položka s časovým údajem"
+
+#: lib/iolog/iolog_legacy.c:90
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: čas %s: %s"
+
+#: lib/iolog/iolog_legacy.c:97
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: chybí položka s uživatelem"
+
+#: lib/iolog/iolog_legacy.c:108
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: chybí položka s runas uživatelem"
+
+#: lib/iolog/iolog_legacy.c:119
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s chybí položka s runas skupinou"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s existuje, ale nejedná se o adresář (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:124 lib/iolog/iolog_mkdtemp.c:80
+#: logsrvd/iolog_writer.c:795 plugins/sudoers/timestamp.c:218
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "nelze vytvořit adresář %s"
+
+#: lib/iolog/iolog_mkdtemp.c:85 plugins/sudoers/visudo.c:769
+#: plugins/sudoers/visudo.c:803 plugins/sudoers/visudo.c:809
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "nelze změnit práva %s na 0%o"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "chyba při čtení časovacího souboru: %s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "neplatný řádek s časovacím souborem: %s"
+
+#: logsrvd/iolog_writer.c:65
+#, c-format
+msgid "%s: protocol error: NULL key"
+msgstr "%s: chyba protokolu: klíč je NULL"
+
+#: logsrvd/iolog_writer.c:69
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s: chyba protokolu: chybný typ pro %s"
+
+#: logsrvd/iolog_writer.c:74 logsrvd/logsrvd_local.c:109
+#: logsrvd/logsrvd_local.c:123 logsrvd/logsrvd_local.c:131
+#: logsrvd/logsrvd_local.c:149
+#, c-format
+msgid "%s: protocol error: NULL value found in %s"
+msgstr "%s: chyba protokolu: nalezena hodnota NULL v %s"
+
+#: logsrvd/iolog_writer.c:141 plugins/sudoers/logging.c:1024
+#: plugins/sudoers/policy.c:613
+msgid "unable to generate UUID"
+msgstr "nelze vytvořit UUID"
+
+#: logsrvd/iolog_writer.c:354 logsrvd/iolog_writer.c:359
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:369
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s: chyba protokolu: v AcceptMessage chybí %s"
+
+#: logsrvd/iolog_writer.c:430
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s: nelze naformátovat identifikátor relace"
+
+#: logsrvd/iolog_writer.c:444 logsrvd/iolog_writer.c:458
+#: logsrvd/iolog_writer.c:472 logsrvd/iolog_writer.c:487
+#: logsrvd/iolog_writer.c:501 logsrvd/iolog_writer.c:515
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s: %s není nastaveno"
+
+#: logsrvd/iolog_writer.c:551 logsrvd/iolog_writer.c:558
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr "nelze expandovat iolog cestu %s"
+
+#: logsrvd/iolog_writer.c:576
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr "nelze vytvořit iolog cestu %s"
+
+#: logsrvd/iolog_writer.c:606
+#, c-format
+msgid "invalid iofd %d"
+msgstr "neplatný iofd %d"
+
+#: logsrvd/iolog_writer.c:626
+#, c-format
+msgid "error closing iofd %u: %s"
+msgstr "chyba při zavírání iofd %u: %s"
+
+#: logsrvd/iolog_writer.c:647
+#, c-format
+msgid "error flushing iofd %u: %s"
+msgstr "chyba při vyprazdňování iofd %u: %s"
+
+#: logsrvd/iolog_writer.c:765
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "neplatný I/O log %s: odkazováno na %s, které není přítomno"
+
+#: logsrvd/iolog_writer.c:777 logsrvd/logsrvd_journal.c:391
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "%s: nelze nalézt bod obnovy [%lld, %ld]"
+
+#: logsrvd/iolog_writer.c:799 logsrvd/logsrvd_journal.c:434
+#: logsrvd/logsrvd_queue.c:115 logsrvd/tls_init.c:256
+#: plugins/sudoers/check.c:285 plugins/sudoers/cvtsudoers.c:758
+#: plugins/sudoers/cvtsudoers.c:780 plugins/sudoers/cvtsudoers.c:1461
+#: plugins/sudoers/cvtsudoers_csv.c:697 plugins/sudoers/cvtsudoers_json.c:902
+#: plugins/sudoers/cvtsudoers_ldif.c:711 plugins/sudoers/sudoers.c:1291
+#: plugins/sudoers/sudoers.c:1317 plugins/sudoers/sudoreplay.c:1497
+#: plugins/sudoers/timestamp.c:478 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:990
+#, c-format
+msgid "unable to open %s"
+msgstr "nelze otevřít %s"
+
+#: logsrvd/iolog_writer.c:811 logsrvd/logsrv_util.c:111
+#: logsrvd/logsrv_util.c:118 plugins/sudoers/sudoreplay.c:355
+#: plugins/sudoers/sudoreplay.c:361
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "nelze otevřít %s/%s"
+
+#: logsrvd/iolog_writer.c:824
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "%s/%s nelze zkopírovat do %s/%s: %s"
+
+#: logsrvd/iolog_writer.c:853 logsrvd/logsrvd_journal.c:198
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "%s nelze přejmenovat na %s"
+
+#: logsrvd/logsrv_util.c:153 logsrvd/logsrv_util.c:182
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s: nelze nalézt bod obnovy [%lld, %ld]"
+
+#: logsrvd/logsrv_util.c:165
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "chybí vstupně-výstupní soubor s protokolem %s/%s"
+
+#: logsrvd/logsrv_util.c:172
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s: nelze skočit vpřed o %zu"
+
+#: logsrvd/logsrvd.c:271 logsrvd/logsrvd_queue.c:135
+msgid "unable to connect to relay"
+msgstr "k relayi se nelze připojit"
+
+#: logsrvd/logsrvd.c:338 logsrvd/logsrvd_relay.c:847
+#, c-format
+msgid "server message too large: %zu"
+msgstr "správa od serveru je příliš velká: %zu"
+
+#: logsrvd/logsrvd.c:430 logsrvd/logsrvd.c:553 logsrvd/logsrvd.c:639
+#: logsrvd/logsrvd.c:881 logsrvd/logsrvd.c:895 logsrvd/logsrvd.c:1056
+#: logsrvd/logsrvd.c:1181 logsrvd/logsrvd.c:1354 logsrvd/logsrvd.c:1372
+#: logsrvd/logsrvd.c:1471 logsrvd/logsrvd.c:1596 logsrvd/logsrvd.c:1783
+#: logsrvd/logsrvd_journal.c:503 logsrvd/logsrvd_local.c:238
+#: logsrvd/logsrvd_queue.c:164 logsrvd/logsrvd_relay.c:172
+#: logsrvd/logsrvd_relay.c:249 logsrvd/logsrvd_relay.c:253
+#: logsrvd/logsrvd_relay.c:391 logsrvd/logsrvd_relay.c:583
+#: logsrvd/logsrvd_relay.c:747 logsrvd/logsrvd_relay.c:1137
+#: logsrvd/sendlog.c:1308 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:216 plugins/sudoers/audit.c:281
+#: plugins/sudoers/iolog.c:1041 plugins/sudoers/iolog.c:1175
+#: plugins/sudoers/iolog.c:1274 plugins/sudoers/log_client.c:121
+#: plugins/sudoers/log_client.c:343 plugins/sudoers/log_client.c:359
+#: plugins/sudoers/log_client.c:407 plugins/sudoers/log_client.c:613
+#: plugins/sudoers/log_client.c:620 plugins/sudoers/log_client.c:1114
+#: plugins/sudoers/log_client.c:1395 plugins/sudoers/log_client.c:1436
+#: plugins/sudoers/log_client.c:1444 plugins/sudoers/log_client.c:1603
+#: plugins/sudoers/log_client.c:1728 plugins/sudoers/log_client.c:2060
+#: plugins/sudoers/log_client.c:2068 plugins/sudoers/logging.c:148
+#: plugins/sudoers/logging.c:206 plugins/sudoers/sudoreplay.c:519
+#: plugins/sudoers/sudoreplay.c:566 plugins/sudoers/sudoreplay.c:808
+#: plugins/sudoers/sudoreplay.c:920 plugins/sudoers/sudoreplay.c:1011
+#: plugins/sudoers/sudoreplay.c:1026 plugins/sudoers/sudoreplay.c:1033
+#: plugins/sudoers/sudoreplay.c:1040 plugins/sudoers/sudoreplay.c:1047
+#: plugins/sudoers/sudoreplay.c:1054 plugins/sudoers/sudoreplay.c:1182
+msgid "unable to add event to queue"
+msgstr "událost nelze přidat do fronty"
+
+#: logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:491 logsrvd/logsrvd.c:523
+#: logsrvd/logsrvd.c:577 logsrvd/logsrvd.c:656 logsrvd/logsrvd.c:692
+#: logsrvd/logsrvd.c:728 logsrvd/logsrvd.c:764 logsrvd/logsrvd_relay.c:512
+#: logsrvd/logsrvd_relay.c:545
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr "nečekaný stav %d u %s"
+
+#: logsrvd/logsrvd.c:455 logsrvd/logsrvd.c:492 logsrvd/logsrvd.c:524
+#: logsrvd/logsrvd.c:578 logsrvd/logsrvd.c:657 logsrvd/logsrvd.c:693
+#: logsrvd/logsrvd.c:729 logsrvd/logsrvd.c:765 logsrvd/logsrvd_relay.c:514
+#: logsrvd/logsrvd_relay.c:547
+msgid "state machine error"
+msgstr "chyba stavového automatu"
+
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:462
+msgid "invalid AcceptMessage"
+msgstr "neplatná zpráva AcceptMessage"
+
+#: logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:499
+msgid "invalid RejectMessage"
+msgstr "neplatná zpráva RejectMessage"
+
+#: logsrvd/logsrvd.c:530 logsrvd/logsrvd.c:531
+msgid "invalid ExitMessage"
+msgstr "neplatná zpráva ExitMessage"
+
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:585
+msgid "invalid RestartMessage"
+msgstr "neplatná zpráva RestartMessage"
+
+#: logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:620
+msgid "invalid AlertMessage"
+msgstr "neplatná zpráva AlertMessage"
+
+#: logsrvd/logsrvd.c:661 logsrvd/logsrvd.c:697 logsrvd/logsrvd.c:733
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s: nečekaný IoBuffer"
+
+#: logsrvd/logsrvd.c:662 logsrvd/logsrvd.c:698 logsrvd/logsrvd.c:734
+msgid "protocol error"
+msgstr "chyba protokolu"
+
+#: logsrvd/logsrvd.c:668 logsrvd/logsrvd.c:669
+msgid "invalid IoBuffer"
+msgstr "neplatný IoBuffer"
+
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:705
+msgid "invalid ChangeWindowSize"
+msgstr "neplatná ChangeWindowSize"
+
+#: logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:741
+msgid "invalid CommandSuspend"
+msgstr "neplatný CommandSuspend"
+
+#: logsrvd/logsrvd.c:790 logsrvd/logsrvd_journal.c:302
+#: logsrvd/logsrvd_relay.c:654 logsrvd/sendlog.c:1207
+#: plugins/sudoers/log_client.c:1593
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "%s o velikosti %zu nelze rozbalit"
+
+#: logsrvd/logsrvd.c:835 logsrvd/logsrvd_journal.c:376
+#: logsrvd/logsrvd_relay.c:678
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "nečekaná hodnota type_case %d v %s od %s"
+
+#: logsrvd/logsrvd.c:837
+msgid "unrecognized ClientMessage type"
+msgstr "nerozpoznaný druh zprávy ClientMessage"
+
+#: logsrvd/logsrvd.c:927
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "při zapisování do klienta %s vypršel časový limit"
+
+#: logsrvd/logsrvd.c:932 logsrvd/logsrvd_relay.c:919 logsrvd/sendlog.c:1413
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr "chybí vyrovnávací paměť pro zápis do klienta %s"
+
+#: logsrvd/logsrvd.c:1027
+#, c-format
+msgid "timed out reading from client %s"
+msgstr "při čtení z klienta %s vypršel časový limit"
+
+#: logsrvd/logsrvd.c:1068 logsrvd/logsrvd_relay.c:782
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr "konec souboru od %s bez řádného ukončení TLS"
+
+#: logsrvd/logsrvd.c:1112 logsrvd/logsrvd_relay.c:205 logsrvd/sendlog.c:336
+#: plugins/sudoers/log_client.c:723
+#, c-format
+msgid "client message too large: %zu"
+msgstr "zpráva od klienta je příliš velká: %zu"
+
+#: logsrvd/logsrvd.c:1113 logsrvd/logsrvd_journal.c:259
+#: logsrvd/logsrvd_journal.c:260
+msgid "client message too large"
+msgstr "zpráva od klienta je příliš velká"
+
+#: logsrvd/logsrvd.c:1131 logsrvd/logsrvd.c:1132
+msgid "invalid ClientMessage"
+msgstr "neplatná zpráva ClientMessage"
+
+#: logsrvd/logsrvd.c:1432
+msgid "unable to get remote IP addr"
+msgstr "nelze získat vzdálenou IP adresu"
+
+#: logsrvd/logsrvd.c:1463 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:281
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "K objektu SSL nelze připojit uživatelská data: %s"
+
+#: logsrvd/logsrvd.c:1646 logsrvd/logsrvd.c:2007
+msgid "unable to setup listen socket"
+msgstr "nelze nastavit naslouchací socket"
+
+#: logsrvd/logsrvd.c:1766
+#, c-format
+msgid "unexpected signal %d"
+msgstr "nečekaný signál %d"
+
+#: logsrvd/logsrvd.c:1909
+msgid "sudo log server"
+msgstr "protokolovací server suda"
+
+#: logsrvd/logsrvd.c:1911 logsrvd/sendlog.c:126
+msgid "Options:"
+msgstr "Volby:"
+
+#: logsrvd/logsrvd.c:1913
+msgid "path to configuration file"
+msgstr "cesta ke konfiguračnímu souboru"
+
+#: logsrvd/logsrvd.c:1915 logsrvd/sendlog.c:128
+msgid "display help message and exit"
+msgstr "zobrazí nápovědu a skončí"
+
+#: logsrvd/logsrvd.c:1917
+msgid "do not fork, run in the foreground"
+msgstr "neoddělí proces, běží na popředí"
+
+#: logsrvd/logsrvd.c:1919
+msgid "percent chance connections will drop"
+msgstr "procentuální pravděpodobnost, že spojení se přeruší"
+
+#: logsrvd/logsrvd.c:1921 logsrvd/sendlog.c:158
+msgid "display version information and exit"
+msgstr "zobrazí údaje o verzi a skončí"
+
+#: logsrvd/logsrvd.c:1971 logsrvd/sendlog.c:1722
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "Je vyžadována knihovna Protobuf-C verze 1.3 nebo vyšší"
+
+#: logsrvd/logsrvd.c:1987
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "neplatná hodnota pravděpodobnosti ztráty: %s"
+
+#: logsrvd/logsrvd.c:1990 logsrvd/sendlog.c:1776
+#: plugins/sudoers/cvtsudoers.c:250 plugins/sudoers/sudoreplay.c:294
+#: plugins/sudoers/visudo.c:181
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s verze %s\n"
+
+#: logsrvd/logsrvd_conf.c:422 plugins/sudoers/check.c:69
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/sudoers.c:419 plugins/sudoers/sudoers.c:929
+#: plugins/sudoers/sudoers.c:1034 plugins/sudoers/sudoers.c:1424
+#: plugins/sudoers/testsudoers.c:169 plugins/sudoers/testsudoers.c:285
+#: plugins/sudoers/testsudoers.c:459
+#, c-format
+msgid "unknown user %s"
+msgstr "neznámý uživatel %s"
+
+#: logsrvd/logsrvd_conf.c:439 plugins/sudoers/iolog.c:148
+#: plugins/sudoers/sudoers.c:425 plugins/sudoers/sudoers.c:1458
+#: plugins/sudoers/testsudoers.c:483
+#, c-format
+msgid "unknown group %s"
+msgstr "neznámá skupina %s"
+
+#: logsrvd/logsrvd_conf.c:457
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr "nelze rozebrat režim iologu %s"
+
+#: logsrvd/logsrvd_conf.c:474 logsrvd/logsrvd_conf.c:1243
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "neplatná hodnota pro %s: %s"
+
+#: logsrvd/logsrvd_conf.c:527
+msgid "TLS not supported"
+msgstr "protokol TLS není podporován"
+
+#: logsrvd/logsrvd_conf.c:549
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:622 logsrvd/logsrvd_conf.c:1032
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s: cesta není plně kvalifikovaná"
+
+#: logsrvd/logsrvd_conf.c:951 logsrvd/logsrvd_conf.c:967
+#: logsrvd/logsrvd_conf.c:1676
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "neznámý obor systémového protokolu %s"
+
+#: logsrvd/logsrvd_conf.c:983 logsrvd/logsrvd_conf.c:999
+#: logsrvd/logsrvd_conf.c:1015 logsrvd/logsrvd_conf.c:1680
+#: logsrvd/logsrvd_conf.c:1684 logsrvd/logsrvd_conf.c:1688
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "neznámá priorita systémového protokolu: %s"
+
+#: logsrvd/logsrvd_conf.c:1197
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d nepárová „[“: %s"
+
+#: logsrvd/logsrvd_conf.c:1203
+#, c-format
+msgid "%s:%d garbage after ']': %s"
+msgstr "%s:%d smetí po „]“: %s"
+
+#: logsrvd/logsrvd_conf.c:1215
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s:%d neplatný konfigurační oddíl: %s"
+
+#: logsrvd/logsrvd_conf.c:1223
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d neplatný řádek s konfigurací: %s"
+
+#: logsrvd/logsrvd_conf.c:1229
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d očekávaný název oddílu: %s"
+
+#: logsrvd/logsrvd_conf.c:1251
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] nedovolený klíč: %s"
+
+#: logsrvd/logsrvd_conf.c:1281 plugins/sudoers/cvtsudoers.c:273
+#: plugins/sudoers/logging.c:1076
+#, c-format
+msgid "unable to open log file %s"
+msgstr "nelze otevřít soubor protokolu %s"
+
+#: logsrvd/logsrvd_conf.c:1763
+msgid "unable to initialize server TLS context"
+msgstr "TLS kontext serveru nelze inicializovat"
+
+#: logsrvd/logsrvd_conf.c:1783
+msgid "unable to initialize relay TLS context"
+msgstr "TLS kontext relay nelze inicializovat"
+
+#: logsrvd/logsrvd_journal.c:149 logsrvd/logsrvd_journal.c:430
+#: logsrvd/logsrvd_journal.c:435
+msgid "unable to create journal file"
+msgstr "soubor s žurnálem nelze vytvořit"
+
+#: logsrvd/logsrvd_journal.c:153 logsrvd/logsrvd_queue.c:109
+#: plugins/sudoers/visudo.c:1046
+#, c-format
+msgid "unable to lock %s"
+msgstr "%s nelze uzamknout"
+
+#: logsrvd/logsrvd_journal.c:156
+msgid "unable to lock journal file"
+msgstr "soubor s žurnálem nelze zamknout"
+
+#: logsrvd/logsrvd_journal.c:164
+msgid "unable to open journal file"
+msgstr "soubor s žurnálem nelze otevřít"
+
+#: logsrvd/logsrvd_journal.c:185 logsrvd/logsrvd_journal.c:466
+#: logsrvd/logsrvd_journal.c:471
+msgid "unable to write journal file"
+msgstr "soubor s žurnálem nelze zapsat"
+
+#: logsrvd/logsrvd_journal.c:193 logsrvd/logsrvd_journal.c:200
+msgid "unable to rename journal file"
+msgstr "soubor s žurnálem nelze přejmenovat"
+
+#: logsrvd/logsrvd_journal.c:247 logsrvd/logsrvd_journal.c:248
+#: logsrvd/logsrvd_journal.c:288 logsrvd/logsrvd_journal.c:289
+msgid "unexpected EOF reading journal file"
+msgstr "nečekaný konec souboru při čtení žurnálu"
+
+#: logsrvd/logsrvd_journal.c:251 logsrvd/logsrvd_journal.c:252
+#: logsrvd/logsrvd_journal.c:292 logsrvd/logsrvd_journal.c:293
+msgid "error reading journal file"
+msgstr "chyba při čtení souboru s žurnálem"
+
+#: logsrvd/logsrvd_journal.c:304 logsrvd/logsrvd_journal.c:390
+msgid "invalid journal file, unable to restart"
+msgstr "neplatný soubor s žurnálem, nelze restartovat"
+
+#: logsrvd/logsrvd_journal.c:449
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "nelze se přesunou na [%lld, %ld] v souboru žurnálu %s"
+
+#: logsrvd/logsrvd_local.c:166
+#, c-format
+msgid "unexpected value_case %d in %s from %s"
+msgstr "nečekaná hodnota value_case %d v %s od %s"
+
+#: logsrvd/logsrvd_local.c:194
+msgid "error parsing AcceptMessage"
+msgstr "chyba při rozboru zprávy AcceptMessage"
+
+#: logsrvd/logsrvd_local.c:205
+msgid "error creating I/O log"
+msgstr "chyba při vytváření vstupně-výstupního protokolu"
+
+#: logsrvd/logsrvd_local.c:228
+msgid "error logging accept event"
+msgstr "chyba při protokolování události přijetí"
+
+#: logsrvd/logsrvd_local.c:267
+msgid "error parsing RejectMessage"
+msgstr "chyba při rozboru zprávy RejectMessage"
+
+#: logsrvd/logsrvd_local.c:291
+msgid "error logging reject event"
+msgstr "chyba při protokolování události zamítnutí"
+
+#: logsrvd/logsrvd_local.c:427 logsrvd/logsrvd_local.c:437
+msgid "error logging exit event"
+msgstr "chyba při protokolování události ukončení"
+
+#: logsrvd/logsrvd_local.c:494 logsrvd/logsrvd_local.c:495
+msgid "log is already complete, cannot be restarted"
+msgstr "protokol byl již dokončen, nelze jej restartovat"
+
+#: logsrvd/logsrvd_local.c:525
+msgid "unable to restart log"
+msgstr "protokol nelze navázat"
+
+#: logsrvd/logsrvd_local.c:541
+msgid "error parsing AlertMessage"
+msgstr "chyba při rozboru zprávy AlertMessage"
+
+#: logsrvd/logsrvd_local.c:551
+msgid "error logging alert event"
+msgstr "chyba při protokolování události upozornění"
+
+#: logsrvd/logsrvd_local.c:587 logsrvd/logsrvd_local.c:650
+#: logsrvd/logsrvd_local.c:685
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr "nelze naformátovat časový údaj, délka %d"
+
+#: logsrvd/logsrvd_local.c:601 logsrvd/logsrvd_local.c:609
+#: logsrvd/logsrvd_local.c:657 logsrvd/logsrvd_local.c:692
+#: plugins/sudoers/sudoreplay.c:344 toke.l:981 toke.l:984
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: logsrvd/logsrvd_local.c:620
+msgid "randomly dropping connection"
+msgstr "náhodně zahazuje spojení"
+
+#: logsrvd/logsrvd_local.c:632
+msgid "error writing IoBuffer"
+msgstr "chyba při zápisu IoBuffer"
+
+#: logsrvd/logsrvd_local.c:667
+msgid "error writing ChangeWindowSize"
+msgstr "chyba při zápisu ChangeWindowSize"
+
+#: logsrvd/logsrvd_local.c:702
+msgid "error writing CommandSuspend"
+msgstr "chyba při zápisu CommandSuspend"
+
+#: logsrvd/logsrvd_relay.c:437
+msgid "TLS handshake with relay host failed"
+msgstr "navazování TLS spojení se strojem relaye selhalo"
+
+#: logsrvd/logsrvd_relay.c:465
+msgid "unable to connect to relay host"
+msgstr "ke stroji relaye se nelze připojit"
+
+#: logsrvd/logsrvd_relay.c:520
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s: neplatná správa ServerHello, chybí server_id"
+
+#: logsrvd/logsrvd_relay.c:522 logsrvd/sendlog.c:1111
+#: plugins/sudoers/log_client.c:1479
+msgid "invalid ServerHello"
+msgstr "neplatná správa ServerHello"
+
+#: logsrvd/logsrvd_relay.c:681
+msgid "unrecognized ServerMessage type"
+msgstr "nerozpoznaný druh zprávy ServerMessage"
+
+#: logsrvd/logsrvd_relay.c:710
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr "při čtení z relaye %s (%s) vypršel časový limit"
+
+#: logsrvd/logsrvd_relay.c:712
+msgid "timeout reading from relay"
+msgstr "při čtení z relaye vypršel časový limit"
+
+#: logsrvd/logsrvd_relay.c:767
+msgid "relay host name does not match certificate"
+msgstr "název stroje relaye neodpovídá certifikátu"
+
+#: logsrvd/logsrvd_relay.c:773 logsrvd/logsrvd_relay.c:787
+#: logsrvd/logsrvd_relay.c:794
+msgid "error reading from relay"
+msgstr "chyba při čtení z relaye"
+
+#: logsrvd/logsrvd_relay.c:815
+msgid "unable to read from relay"
+msgstr "z relaye nelze číst"
+
+#: logsrvd/logsrvd_relay.c:830 logsrvd/logsrvd_relay.c:949
+msgid "relay server closed connection"
+msgstr "relay server uzavřel spojení"
+
+#: logsrvd/logsrvd_relay.c:848
+msgid "server message too large"
+msgstr "správa od serveru je příliš velká"
+
+#: logsrvd/logsrvd_relay.c:912
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr "při zapisování do relaye %s (%s) vypršel časový limit"
+
+#: logsrvd/logsrvd_relay.c:914
+msgid "timeout writing to relay"
+msgstr "při zapisování do relaye vypršel časový limit"
+
+#: logsrvd/logsrvd_relay.c:968 logsrvd/logsrvd_relay.c:975
+#: logsrvd/logsrvd_relay.c:987
+msgid "error writing to relay"
+msgstr "chyba při zápisu do relaye"
+
+#: logsrvd/sendlog.c:124
+msgid "send sudo I/O log to remote server"
+msgstr "odešle vstupně-výstupní protokol vzdálenému serveru"
+
+#: logsrvd/sendlog.c:130
+msgid "only send an accept event (no I/O)"
+msgstr "odešle pouze událost přijetí (žádný vstup-výstup)"
+
+#: logsrvd/sendlog.c:133
+msgid "certificate bundle file to verify server's cert against"
+msgstr "soubor se svazkem certifikátů, proti kterým se má ověřit certifikát serveru"
+
+#: logsrvd/sendlog.c:135
+msgid "certificate file for TLS handshake"
+msgstr "soubor s certifikátem pro navázání TLS"
+
+#: logsrvd/sendlog.c:138
+msgid "host to send logs to"
+msgstr "stroj, kam zaslat protokoly"
+
+#: logsrvd/sendlog.c:140
+msgid "remote ID of I/O log to be resumed"
+msgstr "vzdálený identifikátor protokolu vstupu-výstupu, na kterým se má navázat"
+
+#: logsrvd/sendlog.c:143
+msgid "private key file"
+msgstr "soubor se soukromým klíčem"
+
+#: logsrvd/sendlog.c:145
+msgid "do not verify server certificate"
+msgstr "neověřovat certifikát serveru"
+
+#: logsrvd/sendlog.c:148
+msgid "port to use when connecting to host"
+msgstr "port, který se použije při připojovaní na stroj"
+
+#: logsrvd/sendlog.c:150
+msgid "restart previous I/O log transfer"
+msgstr "navázat na předchozí přenos protokolu vstupu-výstupu"
+
+#: logsrvd/sendlog.c:152
+msgid "reject the command with the given reason"
+msgstr "zamítnout příkaz se zadaným důvodem"
+
+#: logsrvd/sendlog.c:154
+msgid "stop transfer after reaching this time"
+msgstr "zastavit přenos po dosažení tohoto času"
+
+#: logsrvd/sendlog.c:156
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "vyzkoušet auditní server zasláním vybraného protokolu vstupu-výstupu n-krát souběžně"
+
+#: logsrvd/sendlog.c:181 plugins/sudoers/log_client.c:453
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "%s:%s nelze vyhledat: %s"
+
+#: logsrvd/sendlog.c:219
+msgid "unable to get server IP addr"
+msgstr "nelze získat IP adresu serveru"
+
+#: logsrvd/sendlog.c:314 plugins/sudoers/sudoreplay.c:868
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "%s/%s nelze přečíst: %s"
+
+#: logsrvd/sendlog.c:1035 plugins/sudoers/iolog.c:959
+#: plugins/sudoers/iolog.c:1034
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "nečekaná I/O událost %d"
+
+#: logsrvd/sendlog.c:1088 logsrvd/sendlog.c:1105 logsrvd/sendlog.c:1139
+#: plugins/sudoers/log_client.c:1129 plugins/sudoers/log_client.c:1405
+#: plugins/sudoers/log_client.c:1473 plugins/sudoers/log_client.c:1512
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: nečekaný stav %d"
+
+#: logsrvd/sendlog.c:1175 plugins/sudoers/log_client.c:1561
+#, c-format
+msgid "error message received from server: %s"
+msgstr "od serveru byla přijata chybová zpráva: %s"
+
+#: logsrvd/sendlog.c:1188 plugins/sudoers/log_client.c:1574
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "od serveru byla přijata zpráva o zrušení: %s"
+
+#: logsrvd/sendlog.c:1247 plugins/sudoers/log_client.c:1624
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s: nečekaná hodnota type_case %d"
+
+#: logsrvd/sendlog.c:1276
+msgid "timeout reading from server"
+msgstr "při čtení ze serveru vypršel časový limit"
+
+#: logsrvd/sendlog.c:1327 plugins/sudoers/log_client.c:1747
+msgid "host name does not match certificate"
+msgstr "název stroje neodpovídá certifikátu"
+
+#: logsrvd/sendlog.c:1361
+msgid "premature EOF"
+msgstr "předčasný konec souboru"
+
+#: logsrvd/sendlog.c:1374 plugins/sudoers/log_client.c:1795
+#, c-format
+msgid "server message too large: %u"
+msgstr "správa od serveru je příliš velká: %u"
+
+#: logsrvd/sendlog.c:1430
+msgid "timeout writing to server"
+msgstr "při zapisování do serveru vypršel časový limit"
+
+#: logsrvd/sendlog.c:1800
+msgid "both restart point and iolog ID must be specified"
+msgstr "musí být zadán jak bod navázání, tak i identifikátor iolog"
+
+#: logsrvd/sendlog.c:1804
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "bod navázání nelze nastavit, když žádný vstup/výstup nebyl odeslán"
+
+#: logsrvd/sendlog.c:1880
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "ukončeno předčasně ve stavu %d"
+
+#: logsrvd/sendlog.c:1881
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "uplynulý čas zaslaný serveru [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1883
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "od server byl přijat bod zápisu [%lld, %ld]"
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:315
+msgid "TLS handshake timeout occurred"
+msgstr "Při navazování spojení TLS vypršel časový limit"
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:337 plugins/sudoers/log_client.c:353
+msgid "unable to set event"
+msgstr "událost nelze nastavit"
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "spojení TLS selhalo: %s"
+
+#: logsrvd/tls_client.c:196
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "objekt SSL nelze alokovat: %s"
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "K objektu SSL nelze připojit socket: %s"
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr "kontext TLS nelze inicializovat"
+
+#: logsrvd/tls_init.c:138 logsrvd/tls_init.c:146
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "šifru TLS 1.2 nelze nastavit na %s: %s"
+
+#: logsrvd/tls_init.c:166 logsrvd/tls_init.c:174
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "šifru TLS 1.3 nelze nastavit na %s: %s"
+
+#: logsrvd/tls_init.c:206 logsrvd/tls_init.c:227
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "nelze nastavit parametry Diffieho-Hellmana: %s"
+
+#: logsrvd/tls_init.c:283
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "nelze vytvořit kontext TLS: %s"
+
+#: logsrvd/tls_init.c:290
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "nelze nastavit minimální verzi protokolu na TLS 1.2: %s"
+
+#: plugins/sudoers/audit.c:272 plugins/sudoers/audit.c:452
+#: plugins/sudoers/log_client.c:962 plugins/sudoers/log_client.c:1011
+#: plugins/sudoers/log_client.c:1060 plugins/sudoers/log_client.c:1185
+#: plugins/sudoers/logging.c:614 plugins/sudoers/logging.c:732
+#: plugins/sudoers/logging.c:859 plugins/sudoers/logging.c:1031
+#: plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr "nelze získat čas"
+
+#: plugins/sudoers/auth/aix_auth.c:282
+#, c-format
+msgid "unable to change password for %s"
+msgstr "prošlé heslo pro %s nelze změnit"
+
+#: plugins/sudoers/auth/bsdauth.c:78
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "nelze získat přihlašovací třídu uživatele %s"
+
+#: plugins/sudoers/auth/bsdauth.c:85
+msgid "invalid authentication type"
+msgstr "neplatný druh autentizace"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to begin BSD authentication"
+msgstr "nelze zahájit BSD autentizaci"
+
+#: plugins/sudoers/auth/bsdauth.c:97
+msgid "unable to initialize BSD authentication"
+msgstr "nelze inicializovat BSD autentizaci"
+
+#: plugins/sudoers/auth/bsdauth.c:191
+msgid "your account has expired"
+msgstr "vašemu účtu skončila platnost"
+
+#: plugins/sudoers/auth/bsdauth.c:193
+msgid "approval failed"
+msgstr "schválení selhalo"
+
+#: plugins/sudoers/auth/fwtk.c:62
+msgid "unable to read fwtk config"
+msgstr "nelze načíst konfiguraci FWTK"
+
+#: plugins/sudoers/auth/fwtk.c:67
+msgid "unable to connect to authentication server"
+msgstr "k autentizačnímu serveru se nelze připojit"
+
+#: plugins/sudoers/auth/fwtk.c:73 plugins/sudoers/auth/fwtk.c:99
+#: plugins/sudoers/auth/fwtk.c:131
+msgid "lost connection to authentication server"
+msgstr "spojení k autentizačnímu serveru ztraceno"
+
+#: plugins/sudoers/auth/fwtk.c:77
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"chyba autentizačního serveru:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:116
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: principála nelze převést na řetězec („%s“): %s"
+
+#: plugins/sudoers/auth/kerb5.c:166
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: „%s“ nelze rozebrat: %s"
+
+#: plugins/sudoers/auth/kerb5.c:175
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: nelze najít keš s pověřeními: %s"
+
+#: plugins/sudoers/auth/kerb5.c:226
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: nelze alokovat volby: %s"
+
+#: plugins/sudoers/auth/kerb5.c:241
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: nelze získat pověření: %s"
+
+#: plugins/sudoers/auth/kerb5.c:254
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: nelze inicializovat keš s pověřeními: %s"
+
+#: plugins/sudoers/auth/kerb5.c:257
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: pověření nelze uložit do keše: %s"
+
+#: plugins/sudoers/auth/kerb5.c:322
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: nelze získat principála stroje: %s"
+
+#: plugins/sudoers/auth/kerb5.c:336
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: TGT nelze ověřit! Podezření na útok!: %s"
+
+#: plugins/sudoers/auth/pam.c:233
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "PAM nelze inicializovat: %s"
+
+#: plugins/sudoers/auth/pam.c:349
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Chyba autentizace PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:369
+msgid "account validation failure, is your account locked?"
+msgstr "ověření účtu selhalo, není váš účet zamknutý?"
+
+#: plugins/sudoers/auth/pam.c:380
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Účtu nebo heslu vypršela platnost, nastavte si nové heslo a zkuste to znovu"
+
+#: plugins/sudoers/auth/pam.c:387
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "prošlé heslo nelze změnit: %s"
+
+#: plugins/sudoers/auth/pam.c:398
+msgid "Password expired, contact your system administrator"
+msgstr "Heslu vypršela platnost, kontaktujte správce svého systému"
+
+#: plugins/sudoers/auth/pam.c:403
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Účtu vypršela platnost nebo v konfiguraci PAM pro sudo chybí sekce „account“. Kontaktujte správce svého systému"
+
+#: plugins/sudoers/auth/pam.c:411 plugins/sudoers/auth/pam.c:416
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "Chyba správy účtů PAM: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:100 plugins/sudoers/visudo.c:266
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "v databázi %s neexistujete"
+
+#: plugins/sudoers/auth/securid5.c:76
+msgid "failed to initialise the ACE API library"
+msgstr "inicializace knihovny ACE selhala"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "unable to contact the SecurID server"
+msgstr "nelze kontaktovat server SecurID"
+
+#: plugins/sudoers/auth/securid5.c:117
+msgid "User ID locked for SecurID Authentication"
+msgstr "ID uživatele je pro autentizaci SecurID uzamčeno"
+
+#: plugins/sudoers/auth/securid5.c:121 plugins/sudoers/auth/securid5.c:174
+msgid "invalid username length for SecurID"
+msgstr "neplatná délka uživatelského jména pro SecurID"
+
+#: plugins/sudoers/auth/securid5.c:125 plugins/sudoers/auth/securid5.c:179
+msgid "invalid Authentication Handle for SecurID"
+msgstr "neplatný deskriptor autentizace pro SecurID"
+
+#: plugins/sudoers/auth/securid5.c:129
+msgid "SecurID communication failed"
+msgstr "komunikace se SecurID selhala"
+
+#: plugins/sudoers/auth/securid5.c:133 plugins/sudoers/auth/securid5.c:222
+msgid "unknown SecurID error"
+msgstr "neznámá chyba SecurID"
+
+#: plugins/sudoers/auth/securid5.c:169
+msgid "invalid passcode length for SecurID"
+msgstr "neplatná délka kódu pro SecurID"
+
+#: plugins/sudoers/auth/sia.c:72 plugins/sudoers/auth/sia.c:130
+msgid "unable to initialize SIA session"
+msgstr "nelze inicializovat relaci SIA"
+
+#: plugins/sudoers/auth/sudo_auth.c:141
+msgid "invalid authentication methods"
+msgstr "neplatné autentizační metody"
+
+#: plugins/sudoers/auth/sudo_auth.c:143
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Sudo bylo sestaveno s neplatnými autentizačními metodami! Nesmíte míchat samostatnou a nesamostatnou autentizaci."
+
+#: plugins/sudoers/auth/sudo_auth.c:296 plugins/sudoers/auth/sudo_auth.c:359
+msgid "no authentication methods"
+msgstr "žádné autentizační metody"
+
+#: plugins/sudoers/auth/sudo_auth.c:298
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Sudo bylo sestaveno bez autentizačních metod! Chcete-li vypnout autentizaci, použijte při sestavování přepínač --disable-autentizaci."
+
+#: plugins/sudoers/auth/sudo_auth.c:361
+msgid "Unable to initialize authentication methods."
+msgstr "Nelze inicializovat metody autentizace."
+
+#: plugins/sudoers/auth/sudo_auth.c:551
+msgid "Authentication methods:"
+msgstr "Autentizační metody:"
+
+#: plugins/sudoers/bsm_audit.c:122 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "Nebylo možné určit podmínku pro audit"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:278
+msgid "unable to commit audit record"
+msgstr "auditní zprávu nelze odeslat"
+
+#: plugins/sudoers/check.c:63 plugins/sudoers/check.c:74
+#: plugins/sudoers/lookup.c:79 plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "neznámé UID %u"
+
+#: plugins/sudoers/check.c:277
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "chyba při čtení souboru lekce %s"
+
+#: plugins/sudoers/check.c:280
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "ignoruje se soubor lekce %s: nejedná se o běžný soubor"
+
+#: plugins/sudoers/check.c:293
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Věříme, že jste od správce místního systému obdrželi obvyklé školení.\n"
+"Obvykle se jedná o tyto tři věci:\n"
+"\n"
+" 1. Respektujte soukromí druhých.\n"
+" 2. Přemýšlejte, než začnete psát.\n"
+" 3. S velkými právy přichází velká zodpovědnost.\n"
+"\n"
+
+#: plugins/sudoers/check.c:301
+msgid ""
+"For security reasons, the password you type will not be visible.\n"
+"\n"
+msgstr ""
+"Z bezpečnostních důvodů zadávané heslo nebude zobrazeno.\n"
+"\n"
+
+#: plugins/sudoers/check_aliases.c:93
+#, c-format
+msgid "cycle in %s \"%s\""
+msgstr "smyčka v %s „%s“"
+
+#: plugins/sudoers/check_aliases.c:96
+#, c-format
+msgid "%s \"%s\" referenced but not defined"
+msgstr "%s „%s“ použit, ale nedefinován"
+
+#: plugins/sudoers/cvtsudoers.c:211
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "přírůstek pořadí: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:231
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "počáteční pořadí: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:242
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "odsazení pořadí: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:252 plugins/sudoers/visudo.c:183
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "verze gramatiky %s je %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:282 plugins/sudoers/testsudoers.c:162
+#, c-format
+msgid "unsupported input format %s"
+msgstr "nepodporovaný formát vstupu %s"
+
+#: plugins/sudoers/cvtsudoers.c:300
+#, c-format
+msgid "unsupported output format %s"
+msgstr "nepodporovaný formát výstupu %s"
+
+#: plugins/sudoers/cvtsudoers.c:392
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: vstupní a výstupní soubory se musí lišit"
+
+#: plugins/sudoers/cvtsudoers.c:406 plugins/sudoers/sudoers.c:151
+#: plugins/sudoers/sudoers.c:209 plugins/sudoers/testsudoers.c:315
+#: plugins/sudoers/visudo.c:276 plugins/sudoers/visudo.c:666
+msgid "unable to initialize sudoers default values"
+msgstr "nelze inicializovat výchozí hodnoty sudoers"
+
+#: plugins/sudoers/cvtsudoers.c:533 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:612
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s: neznámé klíčové slovo %s"
+
+#: plugins/sudoers/cvtsudoers.c:658
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "neplatný druh položky defaults: %s"
+
+#: plugins/sudoers/cvtsudoers.c:681
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "neplatný druh potlačení: %s"
+
+#: plugins/sudoers/cvtsudoers.c:722 plugins/sudoers/cvtsudoers.c:738
+#, c-format
+msgid "invalid filter: %s"
+msgstr "neplatný filtr: %s"
+
+#: plugins/sudoers/cvtsudoers.c:783 plugins/sudoers/visudo.c:1000
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "rozbor souboru %s se nezdařil, neznámá chyba"
+
+#: plugins/sudoers/cvtsudoers.c:1508 plugins/sudoers/sudoreplay.c:1143
+#: plugins/sudoers/timestamp.c:353 plugins/sudoers/timestamp.c:356
+#, c-format
+msgid "unable to write to %s"
+msgstr "do %s nelze zapsat"
+
+#: plugins/sudoers/cvtsudoers.c:1536
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s – převádí mezí formáty souboru sudoers\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1538
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Přepínače:\n"
+" -b, --base=dn base DN pro ldapové dotazy suda\n"
+" -c, --config=konfigurační_soubor\n"
+" cesta ke konfiguračnímu souboru\n"
+" -d, --defaults=druhydef převede pouze Defaults zadaných druhů\n"
+" -e, --expand-aliases při převodu expanduje aliasy\n"
+" -f, --output-format=formát nastaví formát výstupu: JSON, LDIF nebo sudoers\n"
+" -i, --input-format=formát nastaví formát vstupu: LDIF nebo sudoers\n"
+" -I, --increment=číslo množství, o které zvýšit každou definici sudoOrder\n"
+" -h, --help zobrazí zprávu s nápovědou a skončí\n"
+" -m, --match=filtr převede pouze položky, které odpovídají filtru\n"
+" -M, --match-local porovnávací filtr použije databáze passwd a group\n"
+" -o, --output=výstupní_soubor\n"
+" zapíše převedený sudoers to výstupního_souboru\n"
+" -O, --order-start=číslo počáteční bod pro první sudoOrder\n"
+" -p, --prune-matches odstraní neodpovídající uživatele, skupiny a stroje\n"
+" -P, --padding=číslo základní odsazení přírůstku sudoOrder\n"
+" -s, --suppress=oddíl potlačí výstup jistých oddílů\n"
+" -V, --version zobrazí údaje o verzi a skončí"
+
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:245 plugins/sudoers/cvtsudoers_ldif.c:252
+#: plugins/sudoers/cvtsudoers_ldif.c:594 plugins/sudoers/env.c:340
+#: plugins/sudoers/env.c:347 plugins/sudoers/env.c:458
+#: plugins/sudoers/ldap.c:511 plugins/sudoers/ldap.c:629
+#: plugins/sudoers/ldap.c:1003 plugins/sudoers/ldap_conf.c:219
+#: plugins/sudoers/ldap_conf.c:310 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:93 plugins/sudoers/logging.c:479
+#: plugins/sudoers/policy.c:828 plugins/sudoers/policy.c:840
+#: plugins/sudoers/prompt.c:169 plugins/sudoers/serialize_list.c:62
+#: plugins/sudoers/serialize_list.c:71 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/sudoreplay.c:1340 plugins/sudoers/sudoreplay.c:1346
+#: plugins/sudoers/sudoreplay.c:1352 plugins/sudoers/testsudoers.c:306
+#: plugins/sudoers/toke_util.c:217 toke.l:995 toke.l:1277
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "vnitřní chyba, přetečení %s"
+
+#: plugins/sudoers/cvtsudoers_csv.c:454 plugins/sudoers/cvtsudoers_csv.c:468
+#: plugins/sudoers/cvtsudoers_json.c:661 plugins/sudoers/cvtsudoers_json.c:676
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:362
+#: plugins/sudoers/ldap.c:495
+msgid "unable to get GMT time"
+msgstr "nelze získat čas GMT"
+
+#: plugins/sudoers/cvtsudoers_csv.c:459 plugins/sudoers/cvtsudoers_csv.c:473
+#: plugins/sudoers/cvtsudoers_json.c:666 plugins/sudoers/cvtsudoers_json.c:681
+#: plugins/sudoers/cvtsudoers_ldif.c:354 plugins/sudoers/cvtsudoers_ldif.c:367
+#: plugins/sudoers/ldap.c:503
+msgid "unable to format timestamp"
+msgstr "nelze naformátovat časový údaj"
+
+#: plugins/sudoers/cvtsudoers_json.c:481 plugins/sudoers/cvtsudoers_json.c:516
+#: plugins/sudoers/cvtsudoers_json.c:732
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: neznámá položka defaults „%s“"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:663
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "příliš mnoho záznamů sudoers, maximum je %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:706
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "proměnná prostředí SUDOERS_BASE není nastavená a přepínač -b nebyl zadán."
+
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, c-format
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr "%s:%d:%d: seznam strojů se převádí na ALL"
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr "alias %s nelze nalézt"
+
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, c-format
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr "%s:%d:%d: alias %s se přejmenovává na %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr "%s:%d:%d: zdvojený alias %s se odstraňuje"
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr "%s:%d:%d: neslučitelná položka Defaults „%s“ určená pro stroj na %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, c-format
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr "%s:%d:%d: Defaults „%s“ se vyhrazuje pro stroj %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr "%s:%d:%d: Defaults „%s“ nelze vyhradit pro stroj"
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr "%s:%d:%d: Defaults „%s“ přebitá následujícími položkami se odstraňuje"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1088
+#, c-format
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr "%s:%d:%d: userspec se slučuje do %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1182
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr "%s:%d:%d: userspec přebitá následujícími položkami se odstraňuje"
+
+#: plugins/sudoers/def_data.c:56
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Obor systémového protokolu, je-li syslog použit pro protokolování: %s"
+
+#: plugins/sudoers/def_data.c:60
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Priorita systémového protokolu, která se použije při úspěšné autentizaci uživatele: %s"
+
+#: plugins/sudoers/def_data.c:64
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Priorita systémového protokolu, která se použije při neúspěšné autentizaci: %s"
+
+#: plugins/sudoers/def_data.c:68
+msgid "Put OTP prompt on its own line"
+msgstr "Dotaz na jednorázový kód bude na vlastním řádku"
+
+#: plugins/sudoers/def_data.c:72
+msgid "Ignore '.' in $PATH"
+msgstr "Ignoruje „.“ v PATH"
+
+#: plugins/sudoers/def_data.c:76
+msgid "Always send mail when sudo is run"
+msgstr "Vždy, když se použije sudo, odešle e-mail"
+
+#: plugins/sudoers/def_data.c:80
+msgid "Send mail if user authentication fails"
+msgstr "Odešle e-mail, když autentizace uživatele selže"
+
+#: plugins/sudoers/def_data.c:84
+msgid "Send mail if the user is not in sudoers"
+msgstr "Odešle e-mail, pokud uživatel není v sudoers"
+
+#: plugins/sudoers/def_data.c:88
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Odešle e-mail, když uživatel není v sudoers uveden pro tento stroj"
+
+#: plugins/sudoers/def_data.c:92
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Odešle e-mail, když uživatel nemá dovoleno spustit příkaz"
+
+#: plugins/sudoers/def_data.c:96
+msgid "Send mail if the user tries to run a command"
+msgstr "Odešle e-mail, když uživatel zkusí spustit příkaz"
+
+#: plugins/sudoers/def_data.c:100
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Pro každou kombinaci uživatele a TTY použije samostatný časovač"
+
+#: plugins/sudoers/def_data.c:104
+msgid "Lecture user the first time they run sudo"
+msgstr "Před prvním použitím sudo proškolí uživatele"
+
+#: plugins/sudoers/def_data.c:108
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Soubor obsahující školení k sudo: %s"
+
+#: plugins/sudoers/def_data.c:112
+msgid "Require users to authenticate by default"
+msgstr "Standardně vyžaduje, aby se uživatelé autentizovali"
+
+#: plugins/sudoers/def_data.c:116
+msgid "Root may run sudo"
+msgstr "Root může spustit sudo"
+
+#: plugins/sudoers/def_data.c:120
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Do (nesyslogového) protokolu zaznamenává název stroje"
+
+#: plugins/sudoers/def_data.c:124
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Do (nesyslogového) protokolu zaznamenává rok"
+
+#: plugins/sudoers/def_data.c:128
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Je-li sudo zavoláno bez argumentů, spustí shell"
+
+#: plugins/sudoers/def_data.c:132
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Nastaví HOME na cílového uživatele, když se pouští shell s -s"
+
+#: plugins/sudoers/def_data.c:136
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Vždy nastaví HOME na domovský adresář cílového uživatele"
+
+#: plugins/sudoers/def_data.c:140
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Dovolí sběr některých údajů za účelem užitečných chybových zpráv"
+
+#: plugins/sudoers/def_data.c:144
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Vyžaduje v souboru sudoers plně kvalifikované názvy strojů"
+
+#: plugins/sudoers/def_data.c:148
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Urazí uživatele, pokud zadá chybné heslo"
+
+#: plugins/sudoers/def_data.c:152
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Dovolí uživateli spustit sudo, pouze když má TTY"
+
+#: plugins/sudoers/def_data.c:156
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo bude dodržovat proměnou prostředí EDITOR"
+
+#: plugins/sudoers/def_data.c:160
+msgid "Prompt for root's password, not the users's"
+msgstr "Ptá se heslo roota, ne na heslo uživatele"
+
+#: plugins/sudoers/def_data.c:164
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Ptá se na heslo runas_default uživatele, ne na heslo uživatele"
+
+#: plugins/sudoers/def_data.c:168
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Ptá se na heslo cílového uživatele, ne na heslo uživatele"
+
+#: plugins/sudoers/def_data.c:172
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Použije výchozí nastavení v přihlašovací třídě cílového uživatele, existuje-li"
+
+#: plugins/sudoers/def_data.c:176
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Nastaví proměnné prostředí LOGNAME a USER"
+
+#: plugins/sudoers/def_data.c:180
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Nastaví pouze efektivní UID na cílového uživatele, nikoliv reálné UID"
+
+#: plugins/sudoers/def_data.c:184
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Neinicializuje vektor skupin na vektor cílového uživatele"
+
+#: plugins/sudoers/def_data.c:188
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Délka zlomu řádků v protokolu (0 pro nezalamování): %u"
+
+#: plugins/sudoers/def_data.c:192
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Limit na časové údaje autentizace: %.1f min"
+
+#: plugins/sudoers/def_data.c:196
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Limit na výzvu k heslu: %.1f min"
+
+#: plugins/sudoers/def_data.c:200
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Počet pokusů na zadání hesla: %u"
+
+#: plugins/sudoers/def_data.c:204
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Umask nebo 0777 pro hodnotu uživatele: 0%o"
+
+#: plugins/sudoers/def_data.c:208
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Cesta k souboru s protokolem: %s"
+
+#: plugins/sudoers/def_data.c:212
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Cesta k poštovnímu programu: %s"
+
+#: plugins/sudoers/def_data.c:216
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Přepínače pro poštovní program: %s"
+
+#: plugins/sudoers/def_data.c:220
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Adresa, kam zasílat poštu: %s"
+
+#: plugins/sudoers/def_data.c:224
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Adrese, ze které zasílat poštu: %s"
+
+#: plugins/sudoers/def_data.c:228
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Řádek s předmětem pro poštovní zprávy: %s"
+
+#: plugins/sudoers/def_data.c:232
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Zpráva při chybném hesle: %s"
+
+#: plugins/sudoers/def_data.c:236
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Cesta k adresáři se stavy lekcí: %s"
+
+#: plugins/sudoers/def_data.c:240
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Cesta k adresáři s časovými údaji autentizace: %s"
+
+#: plugins/sudoers/def_data.c:244
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Vlastník adresáře s časovými údaji autentizace: %s"
+
+#: plugins/sudoers/def_data.c:248
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Uživatelé v této skupině jsou vyjmuti z požadavků na heslo na PATH: %s"
+
+#: plugins/sudoers/def_data.c:252
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Výchozí výzva pro heslo: %s"
+
+#: plugins/sudoers/def_data.c:256
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Je-li nastaveno, passprompt přebije systémovou výzvu ve všech případech."
+
+#: plugins/sudoers/def_data.c:260
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Výchozí uživatel, pro kterým spouštět příkazy: %s"
+
+#: plugins/sudoers/def_data.c:264
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Hodnota, kterou přebít PATH uživatele: %s"
+
+#: plugins/sudoers/def_data.c:268
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Cesta k editoru pro potřeby visudo: %s"
+
+#: plugins/sudoers/def_data.c:272
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Kdy vyžadovat heslo pro pseudopříkaz „list“: %s"
+
+#: plugins/sudoers/def_data.c:276
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Kdy vyžadovat heslo pro pseudopříkaz „verify“: %s"
+
+#: plugins/sudoers/def_data.c:280
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "Zavést knihovnu sudo_noexec, která nahrazuje funkce exec"
+
+#: plugins/sudoers/def_data.c:284
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Pokud je adresář LDAP dostupný, ignorovat místní soubor sudoers"
+
+#: plugins/sudoers/def_data.c:288
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Souborové deskriptory >= %d budou před spuštěním příkazu uzavřeny"
+
+#: plugins/sudoers/def_data.c:292
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "Je-li nastaveno, uživatelé mohou přebít hodnotu „closefrom“ přepínačem -C"
+
+#: plugins/sudoers/def_data.c:296
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Dovolit uživatelům nastavit libovolné proměnné prostředí"
+
+#: plugins/sudoers/def_data.c:300
+msgid "Reset the environment to a default set of variables"
+msgstr "Vrátit prostředí do výchozí množiny proměnných"
+
+#: plugins/sudoers/def_data.c:304
+msgid "Environment variables to check for safety:"
+msgstr "Proměnné prostředí kontrolované na bezpečnost:"
+
+#: plugins/sudoers/def_data.c:308
+msgid "Environment variables to remove:"
+msgstr "Proměnné prostředí, které se mají odstranit:"
+
+#: plugins/sudoers/def_data.c:312
+msgid "Environment variables to preserve:"
+msgstr "Proměnné prostředí, které se mají zachovat:"
+
+#: plugins/sudoers/def_data.c:316
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "Selinuxový role, která se použije v novém bezpečnostním kontextu: %s"
+
+#: plugins/sudoers/def_data.c:320
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "Selinuxový typ, který se použije v novém bezpečnostním kontextu: %s"
+
+#: plugins/sudoers/def_data.c:324
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Cesta k souboru s prostředím určeném pro sudo: %s"
+
+#: plugins/sudoers/def_data.c:328
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Cesta k souboru s omezeným prostředím určeném pro sudo: %s"
+
+#: plugins/sudoers/def_data.c:332
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Národní prostředí, které se použije pro rozbor sudoers: %s"
+
+#: plugins/sudoers/def_data.c:336
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Dovolit sudu ptát se na heslo, i kdyby bylo čitelné"
+
+#: plugins/sudoers/def_data.c:340
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Indikovat vstup uživatele při dotazu na heslo"
+
+#: plugins/sudoers/def_data.c:344
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Použit rychlejší expanzi globů, která je méně přesná, ale nepřistupuje k souborovému systému"
+
+#: plugins/sudoers/def_data.c:348
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "Umask zadaná v sudoers přebije uživatelovu, i když je volnější"
+
+#: plugins/sudoers/def_data.c:352
+msgid "Log user's input for the command being run"
+msgstr "Zaznamenávat vstup uživatele pro spouštěný příkaz"
+
+#: plugins/sudoers/def_data.c:356
+msgid "Log the command's standard input if not connected to a terminal"
+msgstr "Zaznamenávat standardní vstup příkazu, není-li připojen terminál"
+
+#: plugins/sudoers/def_data.c:360
+msgid "Log the user's terminal input for the command being run"
+msgstr "Zaznamenávat vstup terminálu uživatele pro spouštěný příkaz"
+
+#: plugins/sudoers/def_data.c:364
+msgid "Log the output of the command being run"
+msgstr "Zaznamenávat výstup spouštěného příkazu"
+
+#: plugins/sudoers/def_data.c:368
+msgid "Log the command's standard output if not connected to a terminal"
+msgstr "Zaznamenávat standardní výstup příkazu, není připojen terminál"
+
+#: plugins/sudoers/def_data.c:372
+msgid "Log the command's standard error if not connected to a terminal"
+msgstr "Zaznamenávat chybový výstup příkazu, není-li připojen terminál"
+
+#: plugins/sudoers/def_data.c:376
+msgid "Log the terminal output of the command being run"
+msgstr "Zaznamenávat výstup terminálu spouštěného příkazu"
+
+#: plugins/sudoers/def_data.c:380
+msgid "Compress I/O logs using zlib"
+msgstr "Komprimovat protokoly o vstupu/výstupu pomocí zlib"
+
+#: plugins/sudoers/def_data.c:384
+msgid "Always run commands in a pseudo-tty"
+msgstr "Vždy spouštět příkazy v pseudoTTY"
+
+#: plugins/sudoers/def_data.c:388
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Modul pro podporu neunixových skupin: %s"
+
+#: plugins/sudoers/def_data.c:392
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Adresář, kam ukládat protokoly o vstupu/výstupu: %s"
+
+#: plugins/sudoers/def_data.c:396
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Soubor, do kterého ukládat protokol o vstupu/výstupu: %s"
+
+#: plugins/sudoers/def_data.c:400
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Při alokaci PTY přidat záznam do souboru utmp/utmpx"
+
+#: plugins/sudoers/def_data.c:404
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Do utmp zapisovat runas uživatele, nikoliv uživatele volajícího"
+
+#: plugins/sudoers/def_data.c:408
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Množina povolujících práv: %s"
+
+#: plugins/sudoers/def_data.c:412
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Množina omezujících práv: %s"
+
+#: plugins/sudoers/def_data.c:416
+msgid "Run commands on a pty in the background"
+msgstr "Spouštět příkazy v PTY na pozadí"
+
+#: plugins/sudoers/def_data.c:420
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "Použít tuto službu PAM: %s"
+
+#: plugins/sudoers/def_data.c:424
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "Název služby PAM, která se použije pro přihlašovací shelly: %s"
+
+#: plugins/sudoers/def_data.c:428
+#, c-format
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr "Název služby PAM, která se použije, když sudo běží s přepínačem -A: %s"
+
+#: plugins/sudoers/def_data.c:432
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Pokusit se získat pověření PAM pro cílového uživatele"
+
+#: plugins/sudoers/def_data.c:436
+msgid "Create a new PAM session for the command to run in"
+msgstr "Vytvořit pro spouštěný příkaz novou relaci PAM"
+
+#: plugins/sudoers/def_data.c:440
+msgid "Perform PAM account validation management"
+msgstr "Ověřit platnost účtu pomocí PAM"
+
+#: plugins/sudoers/def_data.c:444
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "Maximální pořadové číslo protokolu vstupu/výstupu: %s"
+
+#: plugins/sudoers/def_data.c:448
+msgid "Enable sudoers netgroup support"
+msgstr "Zapnout v sudoers podporu netgroup"
+
+#: plugins/sudoers/def_data.c:452
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Kontrolovat nadřazené adresáře na možnost zápisu při úpravě souborů pomocí sudoedit"
+
+#: plugins/sudoers/def_data.c:456
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Následovat symbolické odkazy při úpravě souborů pomocí sudoedit"
+
+#: plugins/sudoers/def_data.c:460
+msgid "Query the group plugin for unknown system groups"
+msgstr "Dotazovat se modulu pro skupiny na neznámé systémové skupiny"
+
+#: plugins/sudoers/def_data.c:464
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Porovnávat netgroups na celou n-tici: uživatel, stroj a doména"
+
+#: plugins/sudoers/def_data.c:468
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Dovolit spuštění příkazu, i když sudo nemůže zapsat do auditního protokolu"
+
+#: plugins/sudoers/def_data.c:472
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Dovolit spuštění příkazu, i když sudo nemůže zapsat do I/O protokolu"
+
+#: plugins/sudoers/def_data.c:476
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Dovolit spuštění příkazu, i když sudo nemůže zapsat do souboru s protokolem"
+
+#: plugins/sudoers/def_data.c:480
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Překládat skupiny v sudoers a hledat shodu na ID skupiny, ne na jméně"
+
+#: plugins/sudoers/def_data.c:484
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Položky protokolu větší než tato hodnota budou rozděleny do více zpráv syslogu: %u"
+
+#: plugins/sudoers/def_data.c:488
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Uživatel, který bude vlastnit soubory s I/O protokolem: %s"
+
+#: plugins/sudoers/def_data.c:492
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Skupina, která bude vlastnit soubory s I/O protokolem: %s"
+
+#: plugins/sudoers/def_data.c:496
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Přístupová práva k souboru s I/O protokolem: 0%o"
+
+#: plugins/sudoers/def_data.c:500
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Spustit příkazy podle deskriptoru souboru namísto podle cesty: %s"
+
+#: plugins/sudoers/def_data.c:504
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Ignorovat neznámé položky Defaults v sudoers namísto vypisování varování"
+
+#: plugins/sudoers/def_data.c:508
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Čas v sekundách, po kterém bude příkaz ukončen: %u"
+
+#: plugins/sudoers/def_data.c:512
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Povolit uživateli zadat časový limit na příkazovém řádku"
+
+#: plugins/sudoers/def_data.c:516
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Zapisovat log na disk ihned namísto po větších částech"
+
+#: plugins/sudoers/def_data.c:520
+msgid "Include the process ID when logging via syslog"
+msgstr "Při protokolování přes syslog zahrnout ID procesu"
+
+#: plugins/sudoers/def_data.c:524
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Druh záznamu s časovým údajem autentizace: %s"
+
+#: plugins/sudoers/def_data.c:528
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Zpráva o selhání autentizace: %s"
+
+#: plugins/sudoers/def_data.c:532
+msgid "Ignore case when matching user names"
+msgstr "Ignorovat velikost znaků při porovnávání jmen uživatelů"
+
+#: plugins/sudoers/def_data.c:536
+msgid "Ignore case when matching group names"
+msgstr "Ignorovat velikost znaků při porovnávání názvů skupin"
+
+#: plugins/sudoers/def_data.c:540
+msgid "Log when a command is allowed by sudoers"
+msgstr "Zaznamenat do protokolu, když je příkaz povolen v sudoers"
+
+#: plugins/sudoers/def_data.c:544
+msgid "Log when a command is denied by sudoers"
+msgstr "Zaznamenat do protokolu, když je příkaz zakázán v sudoers"
+
+#: plugins/sudoers/def_data.c:548
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "Protokolový server(y) suda, kam se připojit s volitelným portem"
+
+#: plugins/sudoers/def_data.c:552
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Časový limit protokolového serveru suda v sekundách: %u"
+
+#: plugins/sudoers/def_data.c:556
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "Zapnout volbu socketu SO_KEEPALIVE na socketu připojeném k protokolovému serveru"
+
+#: plugins/sudoers/def_data.c:560
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "Cesta k souboru se svazkem certifikátů autorit auditního serveru: %s"
+
+#: plugins/sudoers/def_data.c:564
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "Cesta k souboru s certifikátem sudoers: %s"
+
+#: plugins/sudoers/def_data.c:568
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "Cesta k souboru se soukromým klíčem sudoers: %s"
+
+#: plugins/sudoers/def_data.c:572
+msgid "Verify that the log server's certificate is valid"
+msgstr "Ověřit, že certifikát protokolovacího serveru je platný"
+
+#: plugins/sudoers/def_data.c:576
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "Dovolit použití neznámých ID uživatelů a/nebo skupin u klíčového slova runas"
+
+#: plugins/sudoers/def_data.c:580
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "Pouze dovolit spuštění příkazů jako uživatel s platným shellem"
+
+#: plugins/sudoers/def_data.c:584
+msgid "Set the pam remote user to the user running sudo"
+msgstr "Nastavit vzdáleného uživatele PAM na uživatele, který spustil sudo"
+
+#: plugins/sudoers/def_data.c:588
+msgid "Set the pam remote host to the local host name"
+msgstr "Nastavit vzdálený stroj PAM na název tohoto stroje"
+
+#: plugins/sudoers/def_data.c:592
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "Kam změnit pracovní adresář před spuštěním příkazu: %s"
+
+#: plugins/sudoers/def_data.c:596
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "Kam změnit kořenový adresář před spuštěním příkazu: %s"
+
+#: plugins/sudoers/def_data.c:600
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "Vytvářet protokol v tomto formátu: %s"
+
+#: plugins/sudoers/def_data.c:604
+msgid "Enable SELinux RBAC support"
+msgstr "Zapnout podporu pro SELinux RBAC"
+
+#: plugins/sudoers/def_data.c:608
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "Cesta k souboru, který se vytvoří při prvním spuštění suda: %s"
+
+#: plugins/sudoers/def_data.c:612
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "Zachytávat další příkazy a použít na ně omezení sudoers"
+
+#: plugins/sudoers/def_data.c:616
+msgid "Log sub-commands run by the original command"
+msgstr "Zaznamenávat podpříkazy spuštěné původním příkazem"
+
+#: plugins/sudoers/def_data.c:620
+msgid "Log the exit status of commands"
+msgstr "Zaznamenávat návratový kód příkazů"
+
+#: plugins/sudoers/def_data.c:624
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr "Posloupnost příkazů v zachycené relaci musí být autentizována"
+
+#: plugins/sudoers/def_data.c:628
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr "Dovolit zachycenému příkazu spustit setuid nebo setgid programy"
+
+#: plugins/sudoers/def_data.c:632
+#, c-format
+msgid "The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr "Největší velikost, které smí adresní prostor procesu dorůst (v bajtech): %s"
+
+#: plugins/sudoers/def_data.c:636
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr "Největší velikost souboru s obrazem paměti, který smí být vytvořen (v bajtech): %s"
+
+#: plugins/sudoers/def_data.c:640
+#, c-format
+msgid "The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr "Největší množství procesorového času, který proces smí využít (v sekundách): %s"
+
+#: plugins/sudoers/def_data.c:644
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr "Největší velikost datového segmentu procesu (v bajtech): %s"
+
+#: plugins/sudoers/def_data.c:648
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr "Největší velikost souboru, který proces smí vytvořit (v bajtech): %s"
+
+#: plugins/sudoers/def_data.c:652
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr "Největší počet zámků, které proces smí vytvořit: %s"
+
+#: plugins/sudoers/def_data.c:656
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr "Největší velikost paměti, kterou proces smí uzamknout (v bajtech): %s"
+
+#: plugins/sudoers/def_data.c:660
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr "Největší počet souboru, které proces smí držet otevřené: %s"
+
+#: plugins/sudoers/def_data.c:664
+#, c-format
+msgid "The maximum number of processes that the user may run simultaneously: %s"
+msgstr "Největší počet procesů, které uživatel smí souběžně spustit: %s"
+
+#: plugins/sudoers/def_data.c:668
+#, c-format
+msgid "The maximum size to which the process's resident set size may grow (in bytes): %s"
+msgstr "Největší velikost rezidentní paměti, které proces smí dorůst (v bajtech): %s"
+
+#: plugins/sudoers/def_data.c:672
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr "Největší velikost zásobníku, které proces smí dorůst (v bajtech): %s"
+
+#: plugins/sudoers/def_data.c:676
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr "Pokusit se o autentizaci i v neinteraktivním režimu"
+
+#: plugins/sudoers/def_data.c:680
+msgid "Store plaintext passwords in I/O log input"
+msgstr "Ukládat čitelná hesla do vstupu I/O protokolu"
+
+#: plugins/sudoers/def_data.c:684
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr "Seznam regulárních výrazů, které se použijí na rozpoznání výzvy k heslu"
+
+#: plugins/sudoers/def_data.c:688
+#, c-format
+msgid "The mechanism used by the intercept and log_subcmds options: %s"
+msgstr "Volby mechanismu použitého při zachytávání a log_subcmds: %s"
+
+#: plugins/sudoers/def_data.c:692
+msgid "Attempt to verify the command and arguments after execution"
+msgstr "Pokusit se ověřit příkaz a argumenty po spuštění"
+
+#: plugins/sudoers/def_data.c:696
+#, c-format
+msgid "AppArmor profile to use in the new security context: %s"
+msgstr "Profil AppArmoru, který se použije v novém bezpečnostním kontextu: %s"
+
+#: plugins/sudoers/defaults.c:207
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "neznámá položka defaults „%s“"
+
+#: plugins/sudoers/defaults.c:251
+#, c-format
+msgid "no value specified for \"%s\""
+msgstr "u „%s“ nebyla zadána žádná hodnota"
+
+#: plugins/sudoers/defaults.c:260
+#, c-format
+msgid "invalid operator \"%c=\" for \"%s\""
+msgstr "neplatný operátor „%c=“ u „%s“"
+
+#: plugins/sudoers/defaults.c:292
+#, c-format
+msgid "option \"%s\" does not take a value"
+msgstr "volba „%s“ nebere hodnotu"
+
+#: plugins/sudoers/defaults.c:319
+#, c-format
+msgid "invalid Defaults type 0x%x for option \"%s\""
+msgstr "neplatný typ Defaults 0x%x u volby „%s“"
+
+#: plugins/sudoers/defaults.c:326
+#, c-format
+msgid "value \"%s\" is invalid for option \"%s\""
+msgstr "hodnota „%s“ není pro volbu „%s“ platná"
+
+#: plugins/sudoers/defaults.c:1176 plugins/sudoers/policy.c:213
+#: plugins/sudoers/policy.c:222
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr "cesta pro „%s“ je příliš dlouhá"
+
+#: plugins/sudoers/defaults.c:1182
+#, c-format
+msgid "values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "hodnoty „%s“ musí začínat na „/“, „~“ nebo „*“"
+
+#: plugins/sudoers/defaults.c:1189
+#, c-format
+msgid "values for \"%s\" must start with a '/'"
+msgstr "hodnoty „%s“ musí začínat na „/“"
+
+#: plugins/sudoers/display.c:160
+#, c-format
+msgid "LDAP Role: %s\n"
+msgstr "Role LDAP: %s\n"
+
+#: plugins/sudoers/display.c:163
+#, c-format
+msgid "Sudoers entry: %s\n"
+msgstr "Položka v sudoers: %s\n"
+
+#: plugins/sudoers/display.c:166
+msgid " RunAsUsers: "
+msgstr " RunAsUsers: "
+
+#: plugins/sudoers/display.c:181
+msgid " RunAsGroups: "
+msgstr " RunAsGroups: "
+
+#: plugins/sudoers/display.c:191
+msgid " Options: "
+msgstr " Volby: "
+
+#: plugins/sudoers/display.c:255
+msgid " Commands:\n"
+msgstr " Příkazy:\n"
+
+#: plugins/sudoers/display.c:478
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Odpovídající položky Defaults pro %s na %s:\n"
+
+#: plugins/sudoers/display.c:496
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Výchozí hodnoty Runas a Command pro %s:\n"
+
+#: plugins/sudoers/display.c:514
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "Uživatel %s smí spustit následující příkazy na %s:\n"
+
+#: plugins/sudoers/display.c:530
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Uživatel %s nemá dovoleno spustit sudo na %s.\n"
+
+#: plugins/sudoers/editor.c:180
+#, c-format
+msgid "ignoring editor: %.*s"
+msgstr "ignoruje se editor: %.*s"
+
+#: plugins/sudoers/editor.c:181
+msgid "editor arguments may not contain \"--\""
+msgstr "argumenty editoru nesmí obsahovat „--“"
+
+#: plugins/sudoers/env.c:426
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: poškozené pole envp, délka nesouhlasí"
+
+#: plugins/sudoers/env.c:1119
+msgid "unable to rebuild the environment"
+msgstr "prostředí nelze znovu sestavit"
+
+#: plugins/sudoers/env.c:1199
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "je nám líto, ale nemáte dovoleno nastavovat následující proměnné prostředí: %s"
+
+#: plugins/sudoers/filedigest.c:50
+#, c-format
+msgid "unsupported digest type %u for %s"
+msgstr "nepodporovaný druh kontrolního součtu %u pro %s"
+
+#: plugins/sudoers/filedigest.c:77
+#, c-format
+msgid "%s: read error"
+msgstr "%s: chyba při čtení"
+
+#: plugins/sudoers/group_plugin.c:169 plugins/sudoers/sssd.c:578
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "nelze zavést %s: %s"
+
+#: plugins/sudoers/group_plugin.c:181
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "v %s nelze nalézt symbol „group_plugin“"
+
+#: plugins/sudoers/group_plugin.c:186
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: nekompatibilní hlavní verze modulu pro skupiny %d, očekávána %d"
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "nelze rozebrat IP adresu „%s“"
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "nelze rozebrat síťovou masku „%s“"
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Pár místní IP adresy a masky sítě:\n"
+
+#: plugins/sudoers/iolog.c:694
+msgid "unable to update sequence file"
+msgstr "nelze aktualizovat soubor s pořadovým číslem"
+
+#: plugins/sudoers/iolog.c:728 plugins/sudoers/iolog.c:917
+#: plugins/sudoers/iolog.c:1080 plugins/sudoers/iolog.c:1087
+#: plugins/sudoers/iolog.c:1209 plugins/sudoers/iolog.c:1216
+#: plugins/sudoers/iolog.c:1316 plugins/sudoers/iolog.c:1323
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "nelze zapsat do souboru s I/O protokolem: %s"
+
+#: plugins/sudoers/iolog.c:736
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "%s/%s nelze vytvořit"
+
+#: plugins/sudoers/iolog.c:965
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: vnitřní chyba, soubor s I/O protokolem pro událost %d není otevřen"
+
+#: plugins/sudoers/iolog.c:1065 plugins/sudoers/iolog.c:1194
+#: plugins/sudoers/iolog.c:1300 plugins/sudoers/timestamp.c:897
+#: plugins/sudoers/timestamp.c:989 plugins/sudoers/visudo.c:555
+#: plugins/sudoers/visudo.c:561
+msgid "unable to read the clock"
+msgstr "nelze přečíst hodiny"
+
+#: plugins/sudoers/iolog.c:1292 plugins/sudoers/log_client.c:1203
+#: plugins/sudoers/log_client.c:1213 plugins/sudoers/log_client.c:1217
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: vnitřní chyba, neplatný signál %d"
+
+#: plugins/sudoers/ldap.c:154 plugins/sudoers/ldap_conf.c:289
+msgid "starttls not supported when using ldaps"
+msgstr "při použití ldaps není starttls podporováno"
+
+#: plugins/sudoers/ldap.c:226
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "nelze inicializovat certifikát SSL a databázi klíčů: %s"
+
+#: plugins/sudoers/ldap.c:229
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "pro SSL musíte v %s nastavit TLS_CERT"
+
+#: plugins/sudoers/ldap.c:1593
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "LDAP nelze inicializovat: %s"
+
+#: plugins/sudoers/ldap.c:1630
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls uvedeno, ale knihovna LDAP nepodporuje ldap_start_tls_s_np() ani ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:1767 plugins/sudoers/parse_ldif.c:745
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "neplatný atribut sudoOrder: %s"
+
+#: plugins/sudoers/ldap_conf.c:197
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: port je příliš velký"
+
+#: plugins/sudoers/ldap_conf.c:258
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "nepodporovaný typ ldapového URI: %s"
+
+#: plugins/sudoers/ldap_conf.c:285
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "nelze míchat URI ldap a ldaps"
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "násobná sudoOption: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "nelze převést sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "nelze otevřít auditní systém"
+
+#: plugins/sudoers/linux_audit.c:104
+msgid "unable to send audit message"
+msgstr "nelze odeslat auditní zprávu"
+
+#: plugins/sudoers/log_client.c:125 plugins/sudoers/log_client.c:412
+#: plugins/sudoers/log_client.c:1450 plugins/sudoers/log_client.c:2076
+msgid "error in event loop"
+msgstr "chyba ve smyčce událostí"
+
+#: plugins/sudoers/log_client.c:205
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "Vytvoření nového objektu SSL_CTX selhalo: %s"
+
+#: plugins/sudoers/log_client.c:230
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "nelze zavést svazek certifikátů autorit %s"
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "nelze zavést certifikát %s"
+
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "unable to load private key %s"
+msgstr "nelze zavést soukromý klíč %s"
+
+#: plugins/sudoers/log_client.c:275
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "Objekt SSL nelze alokovat: %s"
+
+#: plugins/sudoers/log_client.c:364 plugins/sudoers/log_client.c:369
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "Spojení TLS s %s:%s selhalo: %s"
+
+#: plugins/sudoers/log_client.c:545
+msgid "TLS initialization was unsuccessful"
+msgstr "Inicializace TLS nebyla úspěšná"
+
+#: plugins/sudoers/log_client.c:555
+msgid "TLS handshake was unsuccessful"
+msgstr "Ustanovení spojení TLS nebylo úspěšné"
+
+#: plugins/sudoers/log_client.c:1221
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: vnitřní chyba, neplatný návratový kód %d"
+
+#: plugins/sudoers/log_client.c:1757 plugins/sudoers/log_client.c:1782
+msgid "lost connection to log server"
+msgstr "spojení k protokolovému serveru ztraceno"
+
+#: plugins/sudoers/log_client.c:1859
+msgid "missing write buffer"
+msgstr "chybí vyrovnávací paměť pro zápis"
+
+#: plugins/sudoers/log_client.c:2015
+msgid "unable to connect to log server"
+msgstr "k protokolovacímu serveru se nelze připojit"
+
+#: plugins/sudoers/logging.c:295
+msgid "user NOT in sudoers"
+msgstr "uživatel NENÍ v sudoers"
+
+#: plugins/sudoers/logging.c:297
+msgid "user NOT authorized on host"
+msgstr "uživatel NENÍ na stroji autorizován"
+
+#: plugins/sudoers/logging.c:299
+msgid "command not allowed"
+msgstr "příkaz nedovolen"
+
+#: plugins/sudoers/logging.c:320
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr "%s není v souboru sudoers.\n"
+
+#: plugins/sudoers/logging.c:323
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr "Uživatel %s nemá dovoleno spustit sudo na %s.\n"
+
+#: plugins/sudoers/logging.c:326
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Je nám líto, uživatel %s nesmí spouštět sudo na %s.\n"
+
+#: plugins/sudoers/logging.c:339
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s%s' as %s%s%s on %s.\n"
+msgstr "Je nám líto, uživatel %s nemá dovoleno spouštět „%s%s%s%s“ jako %s%s%s na %s.\n"
+
+#: plugins/sudoers/logging.c:350
+msgid "This incident has been reported to the administrator.\n"
+msgstr "Tato skutečnost byla nahlášena správci.\n"
+
+#: plugins/sudoers/logging.c:387 plugins/sudoers/sudoers.c:547
+#: plugins/sudoers/sudoers.c:549 plugins/sudoers/sudoers.c:551
+#: plugins/sudoers/sudoers.c:553 plugins/sudoers/sudoers.c:777
+#: plugins/sudoers/sudoers.c:779
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: příkaz nenalezen"
+
+#: plugins/sudoers/logging.c:389 plugins/sudoers/sudoers.c:543
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"ignoruje se „%s“ nalezený v „.“\n"
+"Použijte „sudo ./%s„, je-li toto „%s“', který chcete spustit."
+
+#: plugins/sudoers/logging.c:409
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u chybný pokus zadat heslo"
+msgstr[1] "%u chybné pokusy zadat heslo"
+msgstr[2] "%u chybných pokusů zadat heslo"
+
+#: plugins/sudoers/logging.c:500
+msgid "authentication failure"
+msgstr "selhání autentizace"
+
+#: plugins/sudoers/logging.c:539 plugins/sudoers/logging.c:558
+msgid "a password is required"
+msgstr "je vyžadováno heslo"
+
+#: plugins/sudoers/logging.c:881
+msgid "problem parsing sudoers"
+msgstr "problém při rozboru sudoers"
+
+#: plugins/sudoers/logging.c:922 plugins/sudoers/logging.c:930
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr "%s:%d:%d: %s"
+
+#: plugins/sudoers/logging.c:1108
+#, c-format
+msgid "unable to write log file %s"
+msgstr "nelze zapsat soubor protokolu %s"
+
+#: plugins/sudoers/match_digest.c:107
+#, c-format
+msgid "digest for %s (%s) bad length %zu, expected %zu"
+msgstr "součet pro %s (%s) má špatnou délku %zu, očekávaná %zu"
+
+#: plugins/sudoers/match_digest.c:126
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "součet pro %s (%s) nemá tvar %s"
+
+#: plugins/sudoers/parse_ldif.c:615
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "neúplná definice sudoRole se ignoruje: cn: %s"
+
+#: plugins/sudoers/parse_ldif.c:675
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "neplatný atribut LDIF: %s"
+
+#: plugins/sudoers/parser_warnx.c:56
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: plugins/sudoers/parser_warnx.c:59
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s: %s\n"
+
+#: plugins/sudoers/pivot.c:71
+msgid "unable to restore root directory"
+msgstr "kořenový adresář nelze obnovit"
+
+#: plugins/sudoers/pivot.c:79
+msgid "unable to restore current working directory"
+msgstr "současný pracovní adresář nelze obnovit"
+
+#: plugins/sudoers/policy.c:78 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "neplatné %.*s nenastaveno vnějším rozhraním sudo"
+
+#: plugins/sudoers/policy.c:364 plugins/sudoers/testsudoers.c:329
+msgid "unable to parse network address list"
+msgstr "nelze rozebrat seznam síťových adres"
+
+#: plugins/sudoers/policy.c:556
+msgid "user name not set by sudo front-end"
+msgstr "uživatelské jméno nenastaveno vnějším rozhraním sudo"
+
+#: plugins/sudoers/policy.c:560
+msgid "user-ID not set by sudo front-end"
+msgstr "ID uživatele nenastaveno vnějším rozhraním sudo"
+
+#: plugins/sudoers/policy.c:564
+msgid "group-ID not set by sudo front-end"
+msgstr "ID skupiny nenastaveno vnějším rozhraním sudo"
+
+#: plugins/sudoers/policy.c:568
+msgid "host name not set by sudo front-end"
+msgstr "název počítače nenastaven vnějším rozhraním sudo"
+
+#: plugins/sudoers/policy.c:757
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "neplatný pracovní adresář: %s"
+
+#: plugins/sudoers/policy.c:944
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "neplatný kořenový adresář: %s"
+
+#: plugins/sudoers/policy.c:1153 plugins/sudoers/visudo.c:919
+#: plugins/sudoers/visudo.c:1218
+#, c-format
+msgid "unable to execute %s"
+msgstr "nelze vykonat %s"
+
+#: plugins/sudoers/policy.c:1225 plugins/sudoers/policy.c:1260
+#: plugins/sudoers/policy.c:1282 plugins/sudoers/policy.c:1300
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: neplatné příznaky souboru od vnějšího rozhraní suda: 0x%x"
+
+#: plugins/sudoers/policy.c:1323
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Verze modulu s politikami sudoers je %s\n"
+
+#: plugins/sudoers/policy.c:1325
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Verze gramatiky souboru sudoers je %d\n"
+
+#: plugins/sudoers/policy.c:1329
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Cesta sudoers: %s\n"
+
+#: plugins/sudoers/policy.c:1332
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "cesta k nsswitch: %s\n"
+
+#: plugins/sudoers/policy.c:1335
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "cesta k ldap.conf: %s\n"
+
+#: plugins/sudoers/policy.c:1337
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "cesta k ldap.secret: %s\n"
+
+#: plugins/sudoers/policy.c:1370
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "nelze zaregistrovat háček typu %d (verze %d.%d)"
+
+#: plugins/sudoers/policy.c:1388
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "nelze odhlásit háček typu %d (verze %d.%d)"
+
+#: plugins/sudoers/pwutil.c:242 plugins/sudoers/pwutil.c:260
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "nelze si zapamatovat UID %u"
+
+#: plugins/sudoers/pwutil.c:254
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "nelze zapamatovat si UID %u, již existuje"
+
+#: plugins/sudoers/pwutil.c:314 plugins/sudoers/pwutil.c:332
+#: plugins/sudoers/pwutil.c:395 plugins/sudoers/pwutil.c:440
+#, c-format
+msgid "unable to cache user %s"
+msgstr "uživatele %s si nelze zapamatovat"
+
+#: plugins/sudoers/pwutil.c:327
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "nelze zapamatovat si uživatele %s, již existuje"
+
+#: plugins/sudoers/pwutil.c:559 plugins/sudoers/pwutil.c:577
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "GID %u si nelze zapamatovat"
+
+#: plugins/sudoers/pwutil.c:571
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "nelze zapamatovat si GID %u, již existuje"
+
+#: plugins/sudoers/pwutil.c:625 plugins/sudoers/pwutil.c:643
+#: plugins/sudoers/pwutil.c:704 plugins/sudoers/pwutil.c:753
+#, c-format
+msgid "unable to cache group %s"
+msgstr "skupinu %s si nelze zapamatovat"
+
+#: plugins/sudoers/pwutil.c:638
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "nelze zapamatovat si skupinu %s, již existuje"
+
+#: plugins/sudoers/pwutil.c:900 plugins/sudoers/pwutil.c:985
+#: plugins/sudoers/pwutil.c:1039 plugins/sudoers/pwutil.c:1095
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "nelze zapamatovat si seznam skupin pro %s, již existuje"
+
+#: plugins/sudoers/pwutil.c:906 plugins/sudoers/pwutil.c:990
+#: plugins/sudoers/pwutil.c:1045 plugins/sudoers/pwutil.c:1100
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "nelze si zapamatovat seznam skupin pro %s"
+
+#: plugins/sudoers/pwutil.c:979
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "nelze rozebrat skupiny pro %s"
+
+#: plugins/sudoers/pwutil.c:1089
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "nelze rozebrat čísla GID pro %s"
+
+#: plugins/sudoers/set_perms.c:120 plugins/sudoers/set_perms.c:457
+#: plugins/sudoers/set_perms.c:870 plugins/sudoers/set_perms.c:1186
+#: plugins/sudoers/set_perms.c:1490
+msgid "perm stack overflow"
+msgstr "přetečení zásobníku oprávnění"
+
+#: plugins/sudoers/set_perms.c:131 plugins/sudoers/set_perms.c:387
+#: plugins/sudoers/set_perms.c:468 plugins/sudoers/set_perms.c:736
+#: plugins/sudoers/set_perms.c:881 plugins/sudoers/set_perms.c:1109
+#: plugins/sudoers/set_perms.c:1197 plugins/sudoers/set_perms.c:1422
+#: plugins/sudoers/set_perms.c:1501 plugins/sudoers/set_perms.c:1592
+msgid "perm stack underflow"
+msgstr "podtečení zásobníku oprávnění"
+
+#: plugins/sudoers/set_perms.c:191 plugins/sudoers/set_perms.c:515
+#: plugins/sudoers/set_perms.c:1251 plugins/sudoers/set_perms.c:1535
+msgid "unable to change to root gid"
+msgstr "nelze přepnout GID na root"
+
+#: plugins/sudoers/set_perms.c:282 plugins/sudoers/set_perms.c:612
+#: plugins/sudoers/set_perms.c:1013 plugins/sudoers/set_perms.c:1328
+msgid "unable to change to runas gid"
+msgstr "nelze přepnout na běhové GID"
+
+#: plugins/sudoers/set_perms.c:287 plugins/sudoers/set_perms.c:617
+#: plugins/sudoers/set_perms.c:1018 plugins/sudoers/set_perms.c:1333
+msgid "unable to set runas group vector"
+msgstr "nelze nastavit vektor běhových skupin"
+
+#: plugins/sudoers/set_perms.c:298 plugins/sudoers/set_perms.c:628
+#: plugins/sudoers/set_perms.c:1027 plugins/sudoers/set_perms.c:1342
+msgid "unable to change to runas uid"
+msgstr "nelze přepnout na běhové UID"
+
+#: plugins/sudoers/set_perms.c:320 plugins/sudoers/set_perms.c:650
+#: plugins/sudoers/set_perms.c:1047 plugins/sudoers/set_perms.c:1362
+msgid "unable to change to sudoers gid"
+msgstr "nelze přepnout na GID sudoers"
+
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579
+msgid "too many processes"
+msgstr "příliš mnoho procesů"
+
+#: plugins/sudoers/solaris_audit.c:62
+msgid "unable to get current working directory"
+msgstr "současný pracovní adresář nelze zjistit"
+
+#: plugins/sudoers/solaris_audit.c:70
+#, c-format
+msgid "truncated audit path ctx->user.cmnd: %s"
+msgstr "zkrácená auditní cesta ctx->user.cmnd: %s"
+
+#: plugins/sudoers/solaris_audit.c:77
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "zkrácená auditní cesta argv[0]: %s"
+
+#: plugins/sudoers/sssd.c:581
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "nelze inicializovat zdroj SSS. Je SSSD nainstalován na vašem stroji?"
+
+#: plugins/sudoers/sssd.c:589 plugins/sudoers/sssd.c:598
+#: plugins/sudoers/sssd.c:607 plugins/sudoers/sssd.c:616
+#: plugins/sudoers/sssd.c:625
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "nelze nalézt symbol „%s“ v %s"
+
+#: plugins/sudoers/sudoers.c:250
+#, c-format
+msgid "unable to get defaults from %s"
+msgstr "z %s nelze získat výchozí hodnoty"
+
+#: plugins/sudoers/sudoers.c:259
+msgid "no valid sudoers sources found, quitting"
+msgstr "nenalezeny žádné platné zdroje sudoers, končí se"
+
+#: plugins/sudoers/sudoers.c:366
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers udává, že root nemá dovoleno použít sudo"
+
+#: plugins/sudoers/sudoers.c:375
+msgid "user not allowed to override closefrom limit"
+msgstr "uživatel nemá dovoleno přebít omezení „closefrom“"
+
+#: plugins/sudoers/sudoers.c:376
+msgid "you are not permitted to use the -C option"
+msgstr "nemáte dovoleno použít přepínač -C"
+
+#: plugins/sudoers/sudoers.c:440
+msgid "no tty"
+msgstr "žádné TTY"
+
+#: plugins/sudoers/sudoers.c:441
+msgid "sorry, you must have a tty to run sudo"
+msgstr "je nám líto, ale pro spuštění sudo musíte mít TTY"
+
+#: plugins/sudoers/sudoers.c:449
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "neplatný shell pro uživatele %s: %s"
+
+#: plugins/sudoers/sudoers.c:491
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "uživatel nemá dovoleno změnit kořenový adresář na %s"
+
+#: plugins/sudoers/sudoers.c:493
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "nemáte dovoleno použít přepínač -R s %s"
+
+#: plugins/sudoers/sudoers.c:506
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "uživatel nemá dovoleno změnit adresář na %s"
+
+#: plugins/sudoers/sudoers.c:507
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "nemáte dovoleno použít přepínač -D s %s"
+
+#: plugins/sudoers/sudoers.c:542
+msgid "command in current directory"
+msgstr "příkaz v aktuálním adresáři"
+
+#: plugins/sudoers/sudoers.c:557
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr "„cd“ je vestavěný příkaz shellu a nelze jej přímo spustit."
+
+#: plugins/sudoers/sudoers.c:559
+msgid "the -s option may be used to run a privileged shell."
+msgstr "přepínač -s smí být použit pro spuštění privilegovaného shellu."
+
+#: plugins/sudoers/sudoers.c:561
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr "přepínač -D smí být použit pro spuštění příkazu v určitém adresáři."
+
+#: plugins/sudoers/sudoers.c:570
+msgid "user not allowed to set a command timeout"
+msgstr "uživatel nemá dovoleno nastavit časový limit příkazu"
+
+#: plugins/sudoers/sudoers.c:572
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "je nám líto, ale nastavit časový limit nemáte dovoleno"
+
+#: plugins/sudoers/sudoers.c:580
+msgid "user not allowed to preserve the environment"
+msgstr "uživatel nemá dovoleno zachovat prostředí"
+
+#: plugins/sudoers/sudoers.c:582
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "je nám líto, ale zachovat prostředí nemáte dovoleno"
+
+#: plugins/sudoers/sudoers.c:618
+msgid "no command specified"
+msgstr "nezadán žádný příkaz"
+
+#: plugins/sudoers/sudoers.c:759
+msgid "error setting user-specified environment variables"
+msgstr "chyba při nastavování proměnných prostředí určených uživatelem"
+
+#: plugins/sudoers/sudoers.c:1211
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "sudoedit není nutné spouštět přes sudo"
+
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:1613
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "%s nelze číst"
+
+#: plugins/sudoers/sudoers.c:1321 plugins/sudoers/visudo.c:1123
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s není běžný soubor"
+
+#: plugins/sudoers/sudoers.c:1325 plugins/sudoers/timestamp.c:272 toke.l:1355
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s je vlastněn UID %u, měl by být vlastněn %u"
+
+#: plugins/sudoers/sudoers.c:1330 plugins/sudoers/timestamp.c:279 toke.l:1360
+#, c-format
+msgid "%s is world writable"
+msgstr "%s je zapisovatelný pro všechny"
+
+#: plugins/sudoers/sudoers.c:1334 plugins/sudoers/timestamp.c:284 toke.l:1363
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s je vlastněn GID %u, mělo by být %u"
+
+#: plugins/sudoers/sudoers.c:1363
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "pouze root může použít „-c %s“"
+
+#: plugins/sudoers/sudoers.c:1382
+#, c-format
+msgid "unknown login class %s"
+msgstr "neznámá přihlašovací třída %s"
+
+#: plugins/sudoers/sudoers_cb.c:120 plugins/sudoers/sudoers_cb.c:135
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "nelze přeložit název stroje %s"
+
+#: plugins/sudoers/sudoreplay.c:252
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "neplatná volba filtru: %s"
+
+#: plugins/sudoers/sudoreplay.c:268
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "neplatná maximální doba čekání: %s"
+
+#: plugins/sudoers/sudoreplay.c:291
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "neplatný násobek rychlosti: %s"
+
+#: plugins/sudoers/sudoreplay.c:326
+#, c-format
+msgid "invalid time offset %s"
+msgstr "neplatná časový značka %s"
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:340
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/časování: %s"
+
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Přehrává se relace sudo: %s"
+
+#: plugins/sudoers/sudoreplay.c:634
+msgid "unable to set tty to raw mode"
+msgstr "TTY nelze nastavit do přímého režimu"
+
+#: plugins/sudoers/sudoreplay.c:685
+msgid "Warning: your terminal is too small to properly replay the log."
+msgstr "Pozor: váš terminál je příliš malý pro správné zobrazení záznamu."
+
+#: plugins/sudoers/sudoreplay.c:686
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Rozměry záznamu jsou %d × %d, váš terminál má rozměry %d × %d."
+
+#: plugins/sudoers/sudoreplay.c:714
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Přehrávání skončilo, pro obnovení terminálu stiskněte libovolnou klávesu."
+
+#: plugins/sudoers/sudoreplay.c:1217 plugins/sudoers/sudoreplay.c:1247
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "nejednoznačný výraz „%s“"
+
+#: plugins/sudoers/sudoreplay.c:1269
+msgid "unmatched ')' in expression"
+msgstr "ve výrazu neodpovídá „)“"
+
+#: plugins/sudoers/sudoreplay.c:1273
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "neznámý vyhledávací výraz „%s“"
+
+#: plugins/sudoers/sudoreplay.c:1288
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s vyžaduje argument"
+
+#: plugins/sudoers/sudoreplay.c:1298
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "datum „%s“ se nepodařilo rozebrat"
+
+#: plugins/sudoers/sudoreplay.c:1307
+msgid "unmatched '(' in expression"
+msgstr "ve výrazu neodpovídá „(“"
+
+#: plugins/sudoers/sudoreplay.c:1309
+msgid "illegal trailing \"or\""
+msgstr "zakázané zakončení „or“"
+
+#: plugins/sudoers/sudoreplay.c:1311
+msgid "illegal trailing \"!\""
+msgstr "zakázané zakončení „!“"
+
+#: plugins/sudoers/sudoreplay.c:1417
+#, c-format
+msgid "unknown search type %d"
+msgstr "neznámý vyhledávácí typ %d"
+
+#: plugins/sudoers/sudoreplay.c:1679
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "použití: %s [-hnRS] [-d adresář] [-m číslo] [-s číslo] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1681
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "použití: %s [-h] [-d adresář] -l [vyhledávací_výraz]\n"
+
+#: plugins/sudoers/sudoreplay.c:1695
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s – přehraje záznam relace sudo\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1697
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Přepínače:\n"
+" -d, --directory=adresář\n"
+" určuje adresář pro záznamy relace\n"
+" -f, --filter=filtr určuje, které druhy I/O se mají zobrazit\n"
+" -h, --help zobrazí nápovědu a skončí\n"
+" -l, --list vypíše seznam ID dostupných relací, s volitelným\n"
+" výrazem\n"
+" -m, --max-wait=číslo čeká maximálně počet sekund mezi událostmi\n"
+" -n, --non-interactive žádné výzvy, relace se pošle na standardní výstup\n"
+" -R, --no-resize nepokouší ze změnit velikost terminálu\n"
+" -S, --suspend-wait čeká pokud byl příkaz pozastaven\n"
+" -s, --speed=číslo zrychlí nebo zpomalí výstup\n"
+" -V, --version zobrazí údaje o verzi a skončí"
+
+#: plugins/sudoers/testsudoers.c:392
+#, c-format
+msgid ""
+"\n"
+"Invalid shell for user %s: %s\n"
+msgstr ""
+"\n"
+"Neplatný shell pro uživatele %s: %s\n"
+
+#: plugins/sudoers/testsudoers.c:411
+msgid ""
+"\n"
+"Password required"
+msgstr ""
+"\n"
+"Je vyžadováno heslo"
+
+#: plugins/sudoers/testsudoers.c:422
+msgid ""
+"\n"
+"Parse error"
+msgstr ""
+"\n"
+"Chyba rozboru"
+
+#: plugins/sudoers/testsudoers.c:425
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Příkaz povolen"
+
+#: plugins/sudoers/testsudoers.c:428
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Příkaz odepřen"
+
+#: plugins/sudoers/testsudoers.c:431
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Příkaz se neshoduje"
+
+# TODO: pluralize
+#: plugins/sudoers/timestamp.c:364 plugins/sudoers/timestamp.c:711
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "nelze zkrátit soubor s časovými údaji na %lld bajtů"
+
+#: plugins/sudoers/timestamp.c:908
+msgid "ignoring time stamp from the future"
+msgstr "časový údaj z budoucnosti se ignoruje"
+
+#: plugins/sudoers/timestamp.c:931
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "časový údaj ukazuje příliš do budoucna: %20.20s"
+
+# TODO: pluralize
+#: plugins/sudoers/timestamp.c:1067
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "soubor s časovými údaji %s nelze zamknout"
+
+#: plugins/sudoers/timestamp.c:1114
+#, c-format
+msgid "%s:%d:%d timestampowner: unknown user %s"
+msgstr "%s:%d:%d: timestampowner: neznámý uživatel %s"
+
+#: plugins/sudoers/toke_util.c:159
+msgid "sudoedit should not be specified with a path"
+msgstr "sudoedit by neměl být uveden s cestou"
+
+#: plugins/sudoers/visudo.c:308 plugins/sudoers/visudo.c:714
+#, c-format
+msgid "press return to edit %s: "
+msgstr "pro úpravu %s stiskněte enter: "
+
+#: plugins/sudoers/visudo.c:323
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "obsah relace úprav zanechán v %s"
+
+#: plugins/sudoers/visudo.c:401
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "zadaný editor (%s) neexistuje"
+
+#: plugins/sudoers/visudo.c:406
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "žádný editor nenalezen (cesta k editoru = %s)"
+
+#: plugins/sudoers/visudo.c:494 plugins/sudoers/visudo.c:786
+#, c-format
+msgid "unable to stat %s"
+msgstr "nelze zjistit údaje o %s"
+
+#: plugins/sudoers/visudo.c:514 plugins/sudoers/visudo.c:522
+msgid "write error"
+msgstr "chyba zápisu"
+
+#: plugins/sudoers/visudo.c:568
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "nelze získat údaje o dočasném souboru (%s), %s nezměněno"
+
+#: plugins/sudoers/visudo.c:575
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "dočasný soubor o nulové velikosti (%s), %s nezměněno"
+
+#: plugins/sudoers/visudo.c:581
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "editor (%s) selhal, %s nezměněno"
+
+#: plugins/sudoers/visudo.c:613
+#, c-format
+msgid "%s unchanged"
+msgstr "%s nezměněno"
+
+#: plugins/sudoers/visudo.c:661
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "nelze znovu otevřít dočasný soubor (%s), %s nezměněno."
+
+#: plugins/sudoers/visudo.c:674
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "není možné rozebrat dočasný soubor (%s), neznámá chyba"
+
+#: plugins/sudoers/visudo.c:760 plugins/sudoers/visudo.c:790
+#: plugins/sudoers/visudo.c:797
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "nelze nastavit (UID, GID) %s na (%u, %u)"
+
+#: plugins/sudoers/visudo.c:825
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s a %s se nenachází na jednom souborovém systému, pro přejmenování se použije mv"
+
+#: plugins/sudoers/visudo.c:836
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "příkaz selhal: „'%s %s %s“, %s nezměněno"
+
+#: plugins/sudoers/visudo.c:843
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "chyba při přejmenování %s, %s nezměněno"
+
+#: plugins/sudoers/visudo.c:864
+msgid "What now? "
+msgstr "Co teď? "
+
+#: plugins/sudoers/visudo.c:878
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Možnosti jsou:\n"
+" (e) upravit soubor sudoers znovu\n"
+" (x) skončit bez uložení změn do souboru sudoers\n"
+" (Q) skončit a uložit změny do souboru sudoers (NEBEZPEČNÉ!)\n"
+
+#: plugins/sudoers/visudo.c:923
+#, c-format
+msgid "unable to run %s"
+msgstr "nelze spustit %s"
+
+#: plugins/sudoers/visudo.c:954
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: chybný vlastník (UID, GID), měl by být (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:965
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: chybná práva, měla by být 0%o\n"
+
+#: plugins/sudoers/visudo.c:1017 plugins/sudoers/visudo.c:1024
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: rozbor úspěšný\n"
+
+#: plugins/sudoers/visudo.c:1043
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s je zaneprázdněn, zkuste to později"
+
+# The code indeed checks for non-localized "y" character.
+#: plugins/sudoers/visudo.c:1047
+msgid "Edit anyway? [y/N]"
+msgstr "Přesto upravit? [y pro ano / N pro ne]"
+
+#: plugins/sudoers/visudo.c:1206
+msgid "the -x option will be removed in a future release"
+msgstr "přepínač -x bude v příštím vydání odstraněn"
+
+#: plugins/sudoers/visudo.c:1208
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "prosím, zvažte použití nástroje cvtsudoers"
+
+#: plugins/sudoers/visudo.c:1228
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "Pozor: %s:%d:%d: nepoužitý %s „%s“"
+
+#: plugins/sudoers/visudo.c:1341
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s – bezpečně upraví soubor sudoers\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1343
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -I, --no-includes do not edit include files\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Přepínače:\n"
+" -c, --check pouze kontroluje\n"
+" -f, --file=sudoers určuje umístění souboru sudoers\n"
+" -h, --help zobrazí nápovědu a skončí\n"
+" -I, --no-includes neupravuje vložené soubory\n"
+" -q, --quiet méně upovídaná (stručnější) hlášení chyb syntaxe\n"
+" -s, --strict přísná kontrola syntaxe\n"
+" -V, --version zobrazí údaje o verzi a skončí\n"
+
+#: toke.l:184
+msgid "empty string"
+msgstr "prázdný řetězec"
+
+#: toke.l:196 toke.l:566
+msgid "empty group"
+msgstr "prázdná skupina"
+
+#: toke.l:206 toke.l:564
+msgid "empty netgroup"
+msgstr "prázdná síťová skupina"
+
+#: toke.l:284
+msgid "unterminated regular expression"
+msgstr "neukončený regulární výraz"
+
+#: toke.l:358 toke.l:370 toke.l:382 toke.l:398 toke.l:417 toke.l:457
+msgid "invalid line continuation"
+msgstr "neplatné pokračování řádku"
+
+#: toke.l:603 toke.l:615
+msgid "invalid IPv6 address"
+msgstr "neplatná IPv6 adresa"
+
+#: toke.l:863
+msgid "unexpected line break in string"
+msgstr "nečekané zalomení řádku uvnitř řetězce"
+
+#: toke.l:982
+msgid "ignoring editor backup file"
+msgstr "ignoruje se záložní souboru editoru"
+
+#: toke.l:985
+msgid "ignoring file name containing '.'"
+msgstr "ignoruje se soubor s názvem obsahujícím „.“"
+
+#: toke.l:1310
+msgid "too many levels of includes"
+msgstr "příliš mnoho úrovní zanoření"
+
+#~ msgid "\thost unmatched"
+#~ msgstr "\tstroj se neshoduje"
+
+#~ msgid "timestamp owner (%s): No such user"
+#~ msgstr "vlastník časového údaje (%s): Takový uživatel neexistuje"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s musí být vlastněn UID %d"
+
+#~ msgid "%s must only be writable by owner"
+#~ msgstr "%s smí být zapisovatelný jen pro vlastníka"
+
+#~ msgid "%s is group writable"
+#~ msgstr "%s je zapisovatelný pro skupinu"
+
+#~ msgid "lecture status path too long: %s/%s"
+#~ msgstr "cesta ke stavům lekce je příliš dlouhý: %s/%s"
+
+#~ msgid "Error: %s:%d:%d: cycle in %s \"%s\""
+#~ msgstr "Chyba: %s:%d:%d: smyčka v %s „%s“"
+
+#~ msgid "Warning: %s:%d:%d: cycle in %s \"%s\""
+#~ msgstr "Pozor: %s:%d:%d: smyčka v %s „%s“"
+
+#~ msgid "Warning: %s:%d:%d: %s \"%s\" referenced but not defined"
+#~ msgstr "Pozor: %s:%d:%d: %s „%s“ použit, ale nedefinován"
+
+#~ msgid "parse error in %s near line %d\n"
+#~ msgstr "chyba při rozboru %s kolem řádku %d\n"
+
+#~ msgid "parse error in %s\n"
+#~ msgstr "chyba při rozboru %s\n"
+
+#~ msgid "%s: unknown defaults entry \"%s\""
+#~ msgstr "%s: neznámá položka defaults „%s“"
+
+#~ msgid "%s:%d:%d: no value specified for \"%s\""
+#~ msgstr "%s:%d:%d: u „%s“ nebyla zadána žádná hodnota"
+
+#~ msgid "%s:%d:%d: invalid operator \"%c=\" for \"%s\""
+#~ msgstr "%s:%d:%d: neplatný operátor „%c=“ u „%s“"
+
+#~ msgid "%s:%d:%d: option \"%s\" does not take a value"
+#~ msgstr "%s:%d:%d: volba „%s“ nebere hodnotu"
+
+#~ msgid "%s:%d:%d: invalid Defaults type 0x%x for option \"%s\""
+#~ msgstr "%s:%d:%d: neplatný typ Defaults 0x%x u volby „%s“"
+
+#~ msgid "%s:%d:%d: value \"%s\" is invalid for option \"%s\""
+#~ msgstr "%s:%d:%d: hodnota „%s“ je pro volbu „%s“ neplatná"
+
+#~ msgid "%s:%d:%d: path name for \"%s\" too long"
+#~ msgstr "%s:%d:%d: cesta pro „%s“ je příliš dlouhá"
+
+#~ msgid "%s: path name for \"%s\" too long"
+#~ msgstr "%s: cesta pro „%s“ je příliš dlouhá"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/', '~', or '*'"
+#~ msgstr "%s:%d:%d: hodnoty „%s“ musí začínat na „/“, „~“ nebo „*“"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/'"
+#~ msgstr "%s:%d:%d: hodnoty „%s“ musí začínat na „/“"
+
+#~ msgid "parse error in %s near line %d"
+#~ msgstr "chyba rozboru v %s kolem řádku %d"
+
+#~ msgid "parse error in %s"
+#~ msgstr "chyba rozboru v %s"
+
+#~ msgid "SELinux RBAC is not supported when intercept mode is enabled"
+#~ msgstr "SELinux RBAC není podporování, když je zapnut režim zachytávání"
+
+#~ msgid "SELinux RBAC is not supported when the log_subcmds flag is enabled"
+#~ msgstr "SELinux RBAC není podporováno, když zapnut příznak log_subcmds"
+
+#~ msgid "problem with defaults entries"
+#~ msgstr "problém s položkami defaults"
+
+#~ msgid "internal error, unable to find %s in list!"
+#~ msgstr "vnitřní chyba, v seznamu nelze nalézt %s!"
+
+#~ msgid "%s is not in the sudoers file. This incident will be reported.\n"
+#~ msgstr "%s není v souboru sudoers. Tato událost bude ohlášena.\n"
+
+#~ msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+#~ msgstr "%s nemá dovoleno spouštět sudo na %s. Tato událost bude ohlášena.\n"
+
+#~ msgid "%s: write buffer already in use"
+#~ msgstr "%s: vyrovnávací paměť pro zápis se již používá"
+
+#~ msgid "unable to read diffie-hellman parameters: %s"
+#~ msgstr "parametry Diffieho-Hellmana nelze přečíst: %s"
+
+#~ msgid "%s:%d unknown key: %s"
+#~ msgstr "%s:%d: neznámý klíč: %s"
+
+#~ msgid "unable to get TLS server method: %s"
+#~ msgstr "nelze získat metodu TLS serveru: %s"
+
+#~ msgid "%s:%u unable to parse \"%s\""
+#~ msgstr "%s:%u „%s“ nelze rozebrat"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " -f, --file path to configuration file\n"
+#~ " -h --help display help message and exit\n"
+#~ " -n, --no-fork do not fork, run in the foreground\n"
+#~ " -R, --random-drop percent chance connections will drop\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Přepínače:\n"
+#~ " -f, --file cesta ke konfiguračnímu souboru\n"
+#~ " -h, --help zobrazí nápovědu a skončí\n"
+#~ " -n, --no-fork zůstane běžet na popředí\n"
+#~ " -R, --random-drop procentuální pravděpodobnost, že se spojení ztratí\n"
+#~ " -V, --version zobrazí údaje o verzi a skončí\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " --help display help message and exit\n"
+#~ " -A, --accept only send an accept event (no I/O)\n"
+#~ " -h, --host host to send logs to\n"
+#~ " -i, --iolog_id remote ID of I/O log to be resumed\n"
+#~ " -p, --port port to use when connecting to host\n"
+#~ " -r, --restart restart previous I/O log transfer\n"
+#~ " -R, --reject reject the command with the given reason\n"
+#~ " -b, --ca-bundle certificate bundle file to verify server's cert against\n"
+#~ " -c, --cert certificate file for TLS handshake\n"
+#~ " -k, --key private key file\n"
+#~ " -n, --no-verify do not verify server certificate\n"
+#~ " -t, --test test audit server by sending selected I/O log n times in parallel\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Přepínače:\n"
+#~ " --help zobrazí nápovědu a skončí\n"
+#~ " -A, --accept zašle pouze událost přijetí (žádný vstup a výstup)\n"
+#~ " -h, --host stroj, kam posílat protokol\n"
+#~ " -i, --iolog_id vzdálený identifikátor vstupně-výstupního protokolu,\n"
+#~ " na který se má navázat\n"
+#~ " -p, --port port, který se použije při připojování na stroj\n"
+#~ " -r, --restart restartuje předchozí přenos vstupně-výstupního\n"
+#~ " protokolu\n"
+#~ " -R, --reject zamítne příkaz se zadaným důvodem\n"
+#~ " -b, --ca-bundle soubor se svazkem certifikátů, proti kterému se\n"
+#~ " bude ověřovat certifikát serveru\n"
+#~ " -c, --cert soubor s certifikátem pro navázání spojení TLS\n"
+#~ " -k, --key soubor se soukromým klíčem\n"
+#~ " -n, --no-verify neověřuje certifikát serveru\n"
+#~ " -t, --test otestuje auditní server zasláním vybraných\n"
+#~ " vstupně-výstupních protokolů n-krát souběžně\n"
+#~ " -V, --version zobrazí údaje o verzi a skončí\n"
+
+#~ msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+#~ msgstr "Přednačíst prázdné spouštěcí funkce obsažené v knihovně sudo_noexec"
+
+#~ msgid "sudo_ldap_conf_add_ports: port too large"
+#~ msgstr "sudo_ldap_conf_add_ports: port je příliš velký"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s\n"
+#~ msgstr "Funkce SSL_connect selhala: chyba_SSL=%d, zásobník=%s\n"
+
+#~ msgid "CA bundle file was not specified"
+#~ msgstr "Soubor se svazkem certifikátů autorit nebyl zadán"
+
+#~ msgid "Client certificate was not specified"
+#~ msgstr "Certifikát klienta nebyl zadán"
+
+#~ msgid "Unable to allocate ssl object: %s\n"
+#~ msgstr "Objekt SSL nelze alokovat: %s\n"
+
+#~ msgid "Unable to attach socket to the ssl object: %s\n"
+#~ msgstr "K objektu SSL nelze připojit socket: %s\n"
+
+#~ msgid "client message too large: %zu\n"
+#~ msgstr "velikost zprávy od klienta je příliš velká: %zu\n"
+
+#~ msgid "server message too large: %u\n"
+#~ msgstr "zpráva od serveru je příliš veliká: %u\n"
+
+#~ msgid "CA bundle file is not set in sudoers"
+#~ msgstr "V sudoers není nastaven soubor se svazkem certifikátů autorit"
+
+#~ msgid "Calling SSL_CTX_load_verify_locations() failed: %s"
+#~ msgstr "Volání SSL_CTX_load_verify_locations() selhalo: %s "
+
+#~ msgid "Signed certificate file is not set in sudoers"
+#~ msgstr "V sudoers není nastaven soubor s podepsaným certifikátem"
+
+#~ msgid "Unable to load private key into the ssl context: %s"
+#~ msgstr "Do kontextu SSL nelze zavést soukromý klíč: %s"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s"
+#~ msgstr "Funkce SSL_connect selhala: chyba_SSL=%d, zásobník=%s"
+
+#~ msgid "SSL_read failed: ssl_error=%d, stack=%s"
+#~ msgstr "Funkce SSL_read selhala: chyba_SSL=%d, zásobník=%s"
+
+#~ msgid "SSL_write failed: ssl_error=%d, stack=%s"
+#~ msgstr "Funkce SSL_write selhala: chyba_SSL=%d, zásobník=%s"
+
+#~ msgid "unknown address family: %d"
+#~ msgstr "neznámá rodina síťových adres: %d"
+
+#~ msgid "audit_failure message too long"
+#~ msgstr "zpráva audit_failure je příliš dlouhá"
+
+#~ msgid "No user or host"
+#~ msgstr "Žádný uživatel nebo stroj"
+
+#~ msgid "validation failure"
+#~ msgstr "selhání ověření"
+
+#~ msgid "%s/%s/timing: %s"
+#~ msgstr "%s/%s/časování: %s"
+
+#~ msgid "ignoring invalid attribute value: %s"
+#~ msgstr "neplatná hodnota hodnota atributu se ignoruje: %s"
+
+#~ msgid "unable to cache user %s, out of memory"
+#~ msgstr "nelze zapamatovat si uživatele %s, nedostatek paměti"
+
+#~ msgid "unable to cache group %s, out of memory"
+#~ msgstr "nelze zapamatovat si skupinu %s, nedostatek paměti"
+
+#~ msgid "unable to cache group list for %s, out of memory"
+#~ msgstr "nelze zapamatovat si seznam skupin pro %s, nedostatek paměti"
+
+#~ msgid ""
+#~ "\n"
+#~ "LDAP Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Role LDAP: NEZNÁMÁ\n"
+
+#~ msgid " Order: %s\n"
+#~ msgstr " Pořadí: %s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: %s\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Role SSSD: %s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Role SSSD: NEZNÁMÁ\n"
+
+#~ msgid "Warning: unused %s `%s'"
+#~ msgstr "Pozor: nepožitý %s „%s“"
+
+#~ msgid "unable allocate memory"
+#~ msgstr "nelze alokovat paměť"
+
+#~ msgid "timestamp path too long: %s/%s"
+#~ msgstr "cesta k časovým údajům je příliš dlouhá: %s/%s"
+
+#~ msgid "unable to stat editor (%s)"
+#~ msgstr "nelze zjisti údaje o editoru (%s)"
+
+#~ msgid "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+#~ msgstr "sudo_ldap_conf_add_ports: nedostatek místa na rozšíření hostbuf"
+
+#~ msgid "sudo_ldap_parse_uri: out of space building hostbuf"
+#~ msgstr "sudo_ldap_parse_uri: nedostatek místo pro vytvoření hostbuf"
+
+#~ msgid "sudo_ldap_build_pass1 allocation mismatch"
+#~ msgstr "nesouhlasí alokace sudo_ldap_build_pass1"
+
+#~ msgid "internal error: insufficient space for log line"
+#~ msgstr "vnitřní chyba: nedostatek místa pro řádek protokolu"
+
+#~ msgid "fill_args: buffer overflow"
+#~ msgstr "fill_args: přetečení bufferu"
diff --git a/plugins/sudoers/po/da.mo b/plugins/sudoers/po/da.mo
new file mode 100644
index 0000000..c1ccaef
--- /dev/null
+++ b/plugins/sudoers/po/da.mo
Binary files differ
diff --git a/plugins/sudoers/po/da.po b/plugins/sudoers/po/da.po
new file mode 100644
index 0000000..c1cb6f4
--- /dev/null
+++ b/plugins/sudoers/po/da.po
@@ -0,0 +1,2344 @@
+# Danish translation of sudoers.
+# This file is put in the public domain.
+# Joe Hansen <joedalton2@yahoo.dk>, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018.
+#
+# audit -> overvågning
+# dummy -> attrap
+# epoch -> epoke
+# execute -> udføre (run -> kør)
+# overflow -> overløb
+# principal -> værtshovedstol
+# runas -> runas ? (eller måske bedre med kør som. den er valgt indtil videre)
+# stat -> stat
+# timeout -> tidsudløb (eller ventetid, er dog lidt noget andet)
+#
+# der bliver brugt masser af forskellige citationstegn i den her ('' \" \" ``,
+# nogle gange også tre styk). De er alle lavet med »« på dansk.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.8.24b2\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2018-07-31 07:13-0600\n"
+"PO-Revision-Date: 2018-08-12 07:48+0200\n"
+"Last-Translator: joe Hansen <joedalton2@yahoo.dk>\n"
+"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
+"Language: da\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 1.8.11\n"
+
+#: confstr.sh:1
+msgid "syntax error"
+msgstr "syntaksfejl"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "%ps adgangskode: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] adgangskode for %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Adgangskode: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** SIKKERHEDSINFORMATION for %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Beklager, prøv igen."
+
+#: gram.y:194 gram.y:242 gram.y:249 gram.y:256 gram.y:263 gram.y:270
+#: gram.y:286 gram.y:310 gram.y:317 gram.y:324 gram.y:331 gram.y:338
+#: gram.y:401 gram.y:409 gram.y:419 gram.y:452 gram.y:459 gram.y:466
+#: gram.y:473 gram.y:555 gram.y:562 gram.y:571 gram.y:580 gram.y:597
+#: gram.y:709 gram.y:716 gram.y:723 gram.y:731 gram.y:831 gram.y:838
+#: gram.y:845 gram.y:852 gram.y:859 gram.y:885 gram.y:892 gram.y:899
+#: gram.y:1022 gram.y:1296 plugins/sudoers/alias.c:122
+#: plugins/sudoers/alias.c:129 plugins/sudoers/alias.c:145
+#: plugins/sudoers/auth/bsdauth.c:141 plugins/sudoers/auth/kerb5.c:119
+#: plugins/sudoers/auth/kerb5.c:145 plugins/sudoers/auth/pam.c:519
+#: plugins/sudoers/auth/rfc1938.c:109 plugins/sudoers/auth/sia.c:59
+#: plugins/sudoers/cvtsudoers.c:116 plugins/sudoers/cvtsudoers.c:157
+#: plugins/sudoers/cvtsudoers.c:174 plugins/sudoers/cvtsudoers.c:185
+#: plugins/sudoers/cvtsudoers.c:278 plugins/sudoers/cvtsudoers.c:405
+#: plugins/sudoers/cvtsudoers.c:538 plugins/sudoers/cvtsudoers.c:555
+#: plugins/sudoers/cvtsudoers.c:660 plugins/sudoers/cvtsudoers.c:773
+#: plugins/sudoers/cvtsudoers.c:781 plugins/sudoers/cvtsudoers.c:1186
+#: plugins/sudoers/cvtsudoers.c:1190 plugins/sudoers/cvtsudoers.c:1290
+#: plugins/sudoers/cvtsudoers_ldif.c:147 plugins/sudoers/cvtsudoers_ldif.c:189
+#: plugins/sudoers/cvtsudoers_ldif.c:236 plugins/sudoers/cvtsudoers_ldif.c:255
+#: plugins/sudoers/cvtsudoers_ldif.c:325 plugins/sudoers/cvtsudoers_ldif.c:380
+#: plugins/sudoers/cvtsudoers_ldif.c:388 plugins/sudoers/cvtsudoers_ldif.c:405
+#: plugins/sudoers/cvtsudoers_ldif.c:414 plugins/sudoers/cvtsudoers_ldif.c:560
+#: plugins/sudoers/cvtsudoers_ldif.c:753 plugins/sudoers/cvtsudoers_ldif.c:780
+#: plugins/sudoers/cvtsudoers_ldif.c:848 plugins/sudoers/cvtsudoers_ldif.c:855
+#: plugins/sudoers/cvtsudoers_ldif.c:860 plugins/sudoers/cvtsudoers_ldif.c:936
+#: plugins/sudoers/cvtsudoers_ldif.c:947 plugins/sudoers/cvtsudoers_ldif.c:953
+#: plugins/sudoers/cvtsudoers_ldif.c:978 plugins/sudoers/cvtsudoers_ldif.c:990
+#: plugins/sudoers/cvtsudoers_ldif.c:994
+#: plugins/sudoers/cvtsudoers_ldif.c:1008
+#: plugins/sudoers/cvtsudoers_ldif.c:1176
+#: plugins/sudoers/cvtsudoers_ldif.c:1208
+#: plugins/sudoers/cvtsudoers_ldif.c:1233
+#: plugins/sudoers/cvtsudoers_ldif.c:1262
+#: plugins/sudoers/cvtsudoers_ldif.c:1312
+#: plugins/sudoers/cvtsudoers_ldif.c:1358
+#: plugins/sudoers/cvtsudoers_ldif.c:1368 plugins/sudoers/defaults.c:656
+#: plugins/sudoers/defaults.c:952 plugins/sudoers/defaults.c:1123
+#: plugins/sudoers/editor.c:65 plugins/sudoers/editor.c:83
+#: plugins/sudoers/editor.c:94 plugins/sudoers/env.c:233
+#: plugins/sudoers/filedigest.c:61 plugins/sudoers/filedigest.c:77
+#: plugins/sudoers/gc.c:52 plugins/sudoers/group_plugin.c:131
+#: plugins/sudoers/interfaces.c:71 plugins/sudoers/iolog.c:938
+#: plugins/sudoers/iolog_path.c:167 plugins/sudoers/ldap.c:177
+#: plugins/sudoers/ldap.c:408 plugins/sudoers/ldap.c:412
+#: plugins/sudoers/ldap.c:424 plugins/sudoers/ldap.c:715
+#: plugins/sudoers/ldap.c:879 plugins/sudoers/ldap.c:1228
+#: plugins/sudoers/ldap.c:1654 plugins/sudoers/ldap.c:1691
+#: plugins/sudoers/ldap.c:1771 plugins/sudoers/ldap.c:1906
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:214 plugins/sudoers/ldap_conf.c:245
+#: plugins/sudoers/ldap_conf.c:297 plugins/sudoers/ldap_conf.c:333
+#: plugins/sudoers/ldap_conf.c:422 plugins/sudoers/ldap_conf.c:437
+#: plugins/sudoers/ldap_conf.c:533 plugins/sudoers/ldap_conf.c:566
+#: plugins/sudoers/ldap_conf.c:647 plugins/sudoers/ldap_conf.c:729
+#: plugins/sudoers/ldap_util.c:519 plugins/sudoers/ldap_util.c:575
+#: plugins/sudoers/linux_audit.c:76 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:506 plugins/sudoers/logging.c:527
+#: plugins/sudoers/logging.c:568 plugins/sudoers/logging.c:745
+#: plugins/sudoers/logging.c:1003 plugins/sudoers/match.c:693
+#: plugins/sudoers/match.c:740 plugins/sudoers/match.c:781
+#: plugins/sudoers/match.c:809 plugins/sudoers/match.c:897
+#: plugins/sudoers/match.c:977 plugins/sudoers/parse.c:192
+#: plugins/sudoers/parse.c:204 plugins/sudoers/parse.c:219
+#: plugins/sudoers/parse.c:231 plugins/sudoers/policy.c:497
+#: plugins/sudoers/policy.c:739 plugins/sudoers/prompt.c:93
+#: plugins/sudoers/pwutil.c:191 plugins/sudoers/pwutil.c:263
+#: plugins/sudoers/pwutil.c:340 plugins/sudoers/pwutil.c:514
+#: plugins/sudoers/pwutil.c:580 plugins/sudoers/pwutil.c:650
+#: plugins/sudoers/pwutil.c:808 plugins/sudoers/pwutil.c:865
+#: plugins/sudoers/pwutil.c:910 plugins/sudoers/pwutil.c:968
+#: plugins/sudoers/sssd.c:147 plugins/sudoers/sssd.c:387
+#: plugins/sudoers/sssd.c:450 plugins/sudoers/sssd.c:494
+#: plugins/sudoers/sssd.c:541 plugins/sudoers/sssd.c:732
+#: plugins/sudoers/stubs.c:96 plugins/sudoers/stubs.c:104
+#: plugins/sudoers/sudoers.c:265 plugins/sudoers/sudoers.c:275
+#: plugins/sudoers/sudoers.c:283 plugins/sudoers/sudoers.c:325
+#: plugins/sudoers/sudoers.c:648 plugins/sudoers/sudoers.c:774
+#: plugins/sudoers/sudoers.c:818 plugins/sudoers/sudoers.c:1092
+#: plugins/sudoers/sudoers_debug.c:107 plugins/sudoers/sudoreplay.c:1265
+#: plugins/sudoers/sudoreplay.c:1377 plugins/sudoers/sudoreplay.c:1417
+#: plugins/sudoers/sudoreplay.c:1426 plugins/sudoers/sudoreplay.c:1436
+#: plugins/sudoers/sudoreplay.c:1444 plugins/sudoers/sudoreplay.c:1448
+#: plugins/sudoers/sudoreplay.c:1604 plugins/sudoers/sudoreplay.c:1608
+#: plugins/sudoers/testsudoers.c:125 plugins/sudoers/testsudoers.c:215
+#: plugins/sudoers/testsudoers.c:232 plugins/sudoers/testsudoers.c:554
+#: plugins/sudoers/timestamp.c:401 plugins/sudoers/timestamp.c:445
+#: plugins/sudoers/timestamp.c:923 plugins/sudoers/toke_util.c:55
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:145
+#: plugins/sudoers/tsdump.c:125 plugins/sudoers/visudo.c:145
+#: plugins/sudoers/visudo.c:307 plugins/sudoers/visudo.c:313
+#: plugins/sudoers/visudo.c:423 plugins/sudoers/visudo.c:601
+#: plugins/sudoers/visudo.c:920 plugins/sudoers/visudo.c:987
+#: plugins/sudoers/visudo.c:1076 toke.l:847 toke.l:948 toke.l:1105
+msgid "unable to allocate memory"
+msgstr "kan ikke tildele hukommelse"
+
+#: gram.y:484
+msgid "a digest requires a path name"
+msgstr "et sammendrag kræver et stinavn"
+
+#: gram.y:610
+msgid "invalid notbefore value"
+msgstr "ugyldig notbefore-værdi"
+
+#: gram.y:618
+msgid "invalid notafter value"
+msgstr "ugyldig notafter-værdi"
+
+#: gram.y:627 plugins/sudoers/policy.c:313
+msgid "timeout value too large"
+msgstr "værdi for tidsudløb er for stor"
+
+#: gram.y:629 plugins/sudoers/policy.c:315
+msgid "invalid timeout value"
+msgstr "ugyldig værdi for tidsudløb"
+
+#: gram.y:1296 plugins/sudoers/auth/pam.c:349 plugins/sudoers/auth/pam.c:519
+#: plugins/sudoers/auth/rfc1938.c:109 plugins/sudoers/cvtsudoers.c:116
+#: plugins/sudoers/cvtsudoers.c:156 plugins/sudoers/cvtsudoers.c:173
+#: plugins/sudoers/cvtsudoers.c:184 plugins/sudoers/cvtsudoers.c:277
+#: plugins/sudoers/cvtsudoers.c:404 plugins/sudoers/cvtsudoers.c:537
+#: plugins/sudoers/cvtsudoers.c:554 plugins/sudoers/cvtsudoers.c:660
+#: plugins/sudoers/cvtsudoers.c:773 plugins/sudoers/cvtsudoers.c:780
+#: plugins/sudoers/cvtsudoers.c:1186 plugins/sudoers/cvtsudoers.c:1190
+#: plugins/sudoers/cvtsudoers.c:1290 plugins/sudoers/cvtsudoers_ldif.c:146
+#: plugins/sudoers/cvtsudoers_ldif.c:188 plugins/sudoers/cvtsudoers_ldif.c:235
+#: plugins/sudoers/cvtsudoers_ldif.c:254 plugins/sudoers/cvtsudoers_ldif.c:324
+#: plugins/sudoers/cvtsudoers_ldif.c:379 plugins/sudoers/cvtsudoers_ldif.c:387
+#: plugins/sudoers/cvtsudoers_ldif.c:404 plugins/sudoers/cvtsudoers_ldif.c:413
+#: plugins/sudoers/cvtsudoers_ldif.c:559 plugins/sudoers/cvtsudoers_ldif.c:752
+#: plugins/sudoers/cvtsudoers_ldif.c:779 plugins/sudoers/cvtsudoers_ldif.c:847
+#: plugins/sudoers/cvtsudoers_ldif.c:854 plugins/sudoers/cvtsudoers_ldif.c:859
+#: plugins/sudoers/cvtsudoers_ldif.c:935 plugins/sudoers/cvtsudoers_ldif.c:946
+#: plugins/sudoers/cvtsudoers_ldif.c:952 plugins/sudoers/cvtsudoers_ldif.c:977
+#: plugins/sudoers/cvtsudoers_ldif.c:989 plugins/sudoers/cvtsudoers_ldif.c:993
+#: plugins/sudoers/cvtsudoers_ldif.c:1007
+#: plugins/sudoers/cvtsudoers_ldif.c:1176
+#: plugins/sudoers/cvtsudoers_ldif.c:1207
+#: plugins/sudoers/cvtsudoers_ldif.c:1232
+#: plugins/sudoers/cvtsudoers_ldif.c:1261
+#: plugins/sudoers/cvtsudoers_ldif.c:1311
+#: plugins/sudoers/cvtsudoers_ldif.c:1357
+#: plugins/sudoers/cvtsudoers_ldif.c:1367 plugins/sudoers/defaults.c:656
+#: plugins/sudoers/defaults.c:952 plugins/sudoers/defaults.c:1123
+#: plugins/sudoers/editor.c:65 plugins/sudoers/editor.c:83
+#: plugins/sudoers/editor.c:94 plugins/sudoers/env.c:233
+#: plugins/sudoers/filedigest.c:61 plugins/sudoers/filedigest.c:77
+#: plugins/sudoers/gc.c:52 plugins/sudoers/group_plugin.c:131
+#: plugins/sudoers/interfaces.c:71 plugins/sudoers/iolog.c:938
+#: plugins/sudoers/iolog_path.c:167 plugins/sudoers/ldap.c:177
+#: plugins/sudoers/ldap.c:408 plugins/sudoers/ldap.c:412
+#: plugins/sudoers/ldap.c:424 plugins/sudoers/ldap.c:715
+#: plugins/sudoers/ldap.c:879 plugins/sudoers/ldap.c:1228
+#: plugins/sudoers/ldap.c:1654 plugins/sudoers/ldap.c:1691
+#: plugins/sudoers/ldap.c:1771 plugins/sudoers/ldap.c:1906
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:214 plugins/sudoers/ldap_conf.c:245
+#: plugins/sudoers/ldap_conf.c:297 plugins/sudoers/ldap_conf.c:333
+#: plugins/sudoers/ldap_conf.c:422 plugins/sudoers/ldap_conf.c:437
+#: plugins/sudoers/ldap_conf.c:533 plugins/sudoers/ldap_conf.c:566
+#: plugins/sudoers/ldap_conf.c:646 plugins/sudoers/ldap_conf.c:729
+#: plugins/sudoers/ldap_util.c:519 plugins/sudoers/ldap_util.c:575
+#: plugins/sudoers/linux_audit.c:76 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:506 plugins/sudoers/logging.c:527
+#: plugins/sudoers/logging.c:567 plugins/sudoers/logging.c:1003
+#: plugins/sudoers/match.c:692 plugins/sudoers/match.c:739
+#: plugins/sudoers/match.c:781 plugins/sudoers/match.c:809
+#: plugins/sudoers/match.c:897 plugins/sudoers/match.c:976
+#: plugins/sudoers/parse.c:191 plugins/sudoers/parse.c:203
+#: plugins/sudoers/parse.c:218 plugins/sudoers/parse.c:230
+#: plugins/sudoers/policy.c:127 plugins/sudoers/policy.c:136
+#: plugins/sudoers/policy.c:145 plugins/sudoers/policy.c:171
+#: plugins/sudoers/policy.c:298 plugins/sudoers/policy.c:313
+#: plugins/sudoers/policy.c:315 plugins/sudoers/policy.c:341
+#: plugins/sudoers/policy.c:351 plugins/sudoers/policy.c:395
+#: plugins/sudoers/policy.c:405 plugins/sudoers/policy.c:414
+#: plugins/sudoers/policy.c:423 plugins/sudoers/policy.c:497
+#: plugins/sudoers/policy.c:739 plugins/sudoers/prompt.c:93
+#: plugins/sudoers/pwutil.c:191 plugins/sudoers/pwutil.c:263
+#: plugins/sudoers/pwutil.c:340 plugins/sudoers/pwutil.c:514
+#: plugins/sudoers/pwutil.c:580 plugins/sudoers/pwutil.c:650
+#: plugins/sudoers/pwutil.c:808 plugins/sudoers/pwutil.c:865
+#: plugins/sudoers/pwutil.c:910 plugins/sudoers/pwutil.c:968
+#: plugins/sudoers/set_perms.c:387 plugins/sudoers/set_perms.c:766
+#: plugins/sudoers/set_perms.c:1150 plugins/sudoers/set_perms.c:1476
+#: plugins/sudoers/set_perms.c:1641 plugins/sudoers/sssd.c:146
+#: plugins/sudoers/sssd.c:387 plugins/sudoers/sssd.c:450
+#: plugins/sudoers/sssd.c:494 plugins/sudoers/sssd.c:541
+#: plugins/sudoers/sssd.c:732 plugins/sudoers/stubs.c:96
+#: plugins/sudoers/stubs.c:104 plugins/sudoers/sudoers.c:265
+#: plugins/sudoers/sudoers.c:275 plugins/sudoers/sudoers.c:283
+#: plugins/sudoers/sudoers.c:325 plugins/sudoers/sudoers.c:648
+#: plugins/sudoers/sudoers.c:774 plugins/sudoers/sudoers.c:818
+#: plugins/sudoers/sudoers.c:1092 plugins/sudoers/sudoers_debug.c:106
+#: plugins/sudoers/sudoreplay.c:1265 plugins/sudoers/sudoreplay.c:1377
+#: plugins/sudoers/sudoreplay.c:1417 plugins/sudoers/sudoreplay.c:1426
+#: plugins/sudoers/sudoreplay.c:1436 plugins/sudoers/sudoreplay.c:1444
+#: plugins/sudoers/sudoreplay.c:1448 plugins/sudoers/sudoreplay.c:1604
+#: plugins/sudoers/sudoreplay.c:1608 plugins/sudoers/testsudoers.c:125
+#: plugins/sudoers/testsudoers.c:215 plugins/sudoers/testsudoers.c:232
+#: plugins/sudoers/testsudoers.c:554 plugins/sudoers/timestamp.c:401
+#: plugins/sudoers/timestamp.c:445 plugins/sudoers/timestamp.c:923
+#: plugins/sudoers/toke_util.c:55 plugins/sudoers/toke_util.c:108
+#: plugins/sudoers/toke_util.c:145 plugins/sudoers/tsdump.c:125
+#: plugins/sudoers/visudo.c:145 plugins/sudoers/visudo.c:307
+#: plugins/sudoers/visudo.c:313 plugins/sudoers/visudo.c:423
+#: plugins/sudoers/visudo.c:601 plugins/sudoers/visudo.c:920
+#: plugins/sudoers/visudo.c:987 plugins/sudoers/visudo.c:1076 toke.l:847
+#: toke.l:948 toke.l:1105
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: plugins/sudoers/alias.c:140
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Alias »%s« er allerede defineret"
+
+#: plugins/sudoers/auth/bsdauth.c:68
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "kan ikke hente logindklasse for bruger %s"
+
+#: plugins/sudoers/auth/bsdauth.c:73
+msgid "unable to begin bsd authentication"
+msgstr "kan ikke starte bsd-godkendelse"
+
+#: plugins/sudoers/auth/bsdauth.c:81
+msgid "invalid authentication type"
+msgstr "ugyldig godkendelsestype"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to initialize BSD authentication"
+msgstr "kan ikke initialisere BSD-godkendelse"
+
+#: plugins/sudoers/auth/bsdauth.c:178
+msgid "your account has expired"
+msgstr "din konto er udløbet"
+
+#: plugins/sudoers/auth/bsdauth.c:180
+msgid "approval failed"
+msgstr "godkendelse mislykkedes"
+
+#: plugins/sudoers/auth/fwtk.c:52
+msgid "unable to read fwtk config"
+msgstr "kan ikke læse fwtk-konfiguration"
+
+#: plugins/sudoers/auth/fwtk.c:57
+msgid "unable to connect to authentication server"
+msgstr "kan ikke forbinde til godkendelsesserver"
+
+#: plugins/sudoers/auth/fwtk.c:63 plugins/sudoers/auth/fwtk.c:87
+#: plugins/sudoers/auth/fwtk.c:119
+msgid "lost connection to authentication server"
+msgstr "mistede forbindelsen til godkendelseserveren"
+
+#: plugins/sudoers/auth/fwtk.c:67
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"godkendelsesserverfejl:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:111
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: Kan ikke konvertere værtshovedstol til streng (»%s«): %s"
+
+#: plugins/sudoers/auth/kerb5.c:161
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: Kan ikke fortolke »%s«: %s"
+
+#: plugins/sudoers/auth/kerb5.c:170
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: Kan ikke slå akkreditivmellemlager op: %s"
+
+#: plugins/sudoers/auth/kerb5.c:217
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: Kan ikke allokere tilvalg: %s"
+
+#: plugins/sudoers/auth/kerb5.c:232
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: Kan ikke indhente akkreditiver: %s"
+
+#: plugins/sudoers/auth/kerb5.c:245
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: Kan ikke initialisere akkreditivmellemlager: %s"
+
+#: plugins/sudoers/auth/kerb5.c:248
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: Kan ikke gemme akkreditiver i mellemlager: %s"
+
+#: plugins/sudoers/auth/kerb5.c:312
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: Kan ikke indhente værtshovedstol: %s"
+
+#: plugins/sudoers/auth/kerb5.c:326
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: Kan ikke verifiere TGT! Muligt angreb!: %s"
+
+#: plugins/sudoers/auth/pam.c:108
+msgid "unable to initialize PAM"
+msgstr "kan ikke initialisere PAM"
+
+#: plugins/sudoers/auth/pam.c:199
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "PAM-godkendelsesserverfejl: %s"
+
+#: plugins/sudoers/auth/pam.c:216
+msgid "account validation failure, is your account locked?"
+msgstr "valideringsfejl for konto, er din konto låst?"
+
+#: plugins/sudoers/auth/pam.c:224
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Konto eller adgangskoder er udløbet, nulstil din adgangskode og forsøg igen"
+
+#: plugins/sudoers/auth/pam.c:233
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "kan ikke ændre udløbet adgangskode: %s"
+
+#: plugins/sudoers/auth/pam.c:241
+msgid "Password expired, contact your system administrator"
+msgstr "Adgangskode udløbet, kontakt din systemadministrator"
+
+#: plugins/sudoers/auth/pam.c:245
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Konto udløbet eller PAM-konfiguration mangler et »kontoafsnit« for sudo. Kontakt din systemadministrator"
+
+#: plugins/sudoers/auth/pam.c:252 plugins/sudoers/auth/pam.c:257
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "PAM-kontohåndteringsfejl: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:97 plugins/sudoers/visudo.c:227
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "du findes ikke i %s-databasen"
+
+#: plugins/sudoers/auth/securid5.c:73
+msgid "failed to initialise the ACE API library"
+msgstr "kunne ikke initialisere ACE API-biblioteket"
+
+#: plugins/sudoers/auth/securid5.c:99
+msgid "unable to contact the SecurID server"
+msgstr "kan ikke kontakte SecurID-serveren"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "User ID locked for SecurID Authentication"
+msgstr "Bruger-ID låst for SecurID-godkendelse"
+
+#: plugins/sudoers/auth/securid5.c:112 plugins/sudoers/auth/securid5.c:163
+msgid "invalid username length for SecurID"
+msgstr "ugyldigt brugernavnslængde for SecurID"
+
+#: plugins/sudoers/auth/securid5.c:116 plugins/sudoers/auth/securid5.c:168
+msgid "invalid Authentication Handle for SecurID"
+msgstr "ugyldigt godkendelseshåndtag for SecurID"
+
+#: plugins/sudoers/auth/securid5.c:120
+msgid "SecurID communication failed"
+msgstr "SecurID-kommunikation fejlede"
+
+#: plugins/sudoers/auth/securid5.c:124 plugins/sudoers/auth/securid5.c:213
+msgid "unknown SecurID error"
+msgstr "ukendt SecurID-fejl"
+
+#: plugins/sudoers/auth/securid5.c:158
+msgid "invalid passcode length for SecurID"
+msgstr "ugyldig adgangskodelængde for SecurID"
+
+#: plugins/sudoers/auth/sia.c:69 plugins/sudoers/auth/sia.c:124
+msgid "unable to initialize SIA session"
+msgstr "kan ikke initialisere SIA-session"
+
+#: plugins/sudoers/auth/sudo_auth.c:131
+msgid "invalid authentication methods"
+msgstr "ugyldige godkendelsesmetoder"
+
+#: plugins/sudoers/auth/sudo_auth.c:133
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Ugyldige godkendelsesmetoder kompileret ind i sudo! Du kan ikke blande uafhængig og ikkeuafhængig godkendelse."
+
+#: plugins/sudoers/auth/sudo_auth.c:254 plugins/sudoers/auth/sudo_auth.c:304
+msgid "no authentication methods"
+msgstr "ingen godkendelsesmetoder"
+
+#: plugins/sudoers/auth/sudo_auth.c:256
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Der er ingen godkendelsesmetoder kompileret ind i sudo! Hvis du ønsker at fravælge godkendelse så brug konfigurationstilvalget --disable-authentication."
+
+#: plugins/sudoers/auth/sudo_auth.c:306
+msgid "Unable to initialize authentication methods."
+msgstr "Kan ikke initialisere godkendelsesmetoder."
+
+#: plugins/sudoers/auth/sudo_auth.c:472
+msgid "Authentication methods:"
+msgstr "Godkendelsesmetoder:"
+
+#: plugins/sudoers/bsm_audit.c:120 plugins/sudoers/bsm_audit.c:211
+msgid "Could not determine audit condition"
+msgstr "Kunne ikke bestemme overvågningsbetingelse"
+
+#: plugins/sudoers/bsm_audit.c:183 plugins/sudoers/bsm_audit.c:273
+msgid "unable to commit audit record"
+msgstr "kan ikke indsende overvågningspost"
+
+#: plugins/sudoers/check.c:262
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Vi stoler på, at du har modtaget den gængse advarsel fra den lokale\n"
+"systemadministrator. Det drejer sig normalt om følgende tre ting:\n"
+"\n"
+" #1) Respekter andres privatliv.\n"
+" #2) Tænk før du taster.\n"
+" #3) Med stor magt følger stort ansvar.\n"
+"\n"
+
+#: plugins/sudoers/check.c:305 plugins/sudoers/check.c:315
+#: plugins/sudoers/sudoers.c:691 plugins/sudoers/sudoers.c:736
+#: plugins/sudoers/tsdump.c:121
+#, c-format
+msgid "unknown uid: %u"
+msgstr "ukendt uid: %u"
+
+#: plugins/sudoers/check.c:310 plugins/sudoers/iolog.c:257
+#: plugins/sudoers/policy.c:912 plugins/sudoers/sudoers.c:1131
+#: plugins/sudoers/testsudoers.c:206 plugins/sudoers/testsudoers.c:366
+#, c-format
+msgid "unknown user: %s"
+msgstr "ukendt bruger: %s"
+
+#: plugins/sudoers/cvtsudoers.c:191
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "rækkefølgeforøgelse: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:207
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "startrækkefølge: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:218 plugins/sudoers/sudoreplay.c:310
+#: plugins/sudoers/visudo.c:177
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s version %s\n"
+
+#: plugins/sudoers/cvtsudoers.c:220 plugins/sudoers/visudo.c:179
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s grammatikversion %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:237
+#, c-format
+msgid "unsupported input format %s"
+msgstr "ej understøttet inddataformat %s"
+
+#: plugins/sudoers/cvtsudoers.c:252
+#, c-format
+msgid "unsupported output format %s"
+msgstr "ej understøttet uddataformat %s"
+
+#: plugins/sudoers/cvtsudoers.c:292
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: inddata- og uddatafiler skal være forskellige"
+
+#: plugins/sudoers/cvtsudoers.c:308 plugins/sudoers/sudoers.c:168
+#: plugins/sudoers/testsudoers.c:245 plugins/sudoers/visudo.c:233
+#: plugins/sudoers/visudo.c:589 plugins/sudoers/visudo.c:911
+msgid "unable to initialize sudoers default values"
+msgstr "kan ikke initialisere sudoers' standardværdier"
+
+#: plugins/sudoers/cvtsudoers.c:393 plugins/sudoers/ldap_conf.c:412
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:452
+#, c-format
+msgid "%s: unknown key word: %s"
+msgstr "%s: ukendt nøgleord: %s"
+
+#: plugins/sudoers/cvtsudoers.c:498
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "ugyldig type for standarder: %s"
+
+#: plugins/sudoers/cvtsudoers.c:521
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "ugyldig undertrykkelsestype: %s"
+
+#: plugins/sudoers/cvtsudoers.c:561 plugins/sudoers/cvtsudoers.c:575
+#, c-format
+msgid "invalid filter: %s"
+msgstr "ugyldigt filter: %s"
+
+#: plugins/sudoers/cvtsudoers.c:653 plugins/sudoers/cvtsudoers.c:1250
+#: plugins/sudoers/cvtsudoers_json.c:1113
+#: plugins/sudoers/cvtsudoers_ldif.c:627
+#: plugins/sudoers/cvtsudoers_ldif.c:1163 plugins/sudoers/iolog.c:415
+#: plugins/sudoers/sudoers.c:898 plugins/sudoers/sudoreplay.c:356
+#: plugins/sudoers/sudoreplay.c:1366 plugins/sudoers/sudoreplay.c:1570
+#: plugins/sudoers/timestamp.c:410 plugins/sudoers/tsdump.c:130
+#: plugins/sudoers/visudo.c:907
+#, c-format
+msgid "unable to open %s"
+msgstr "kan ikke åbne %s"
+
+#: plugins/sudoers/cvtsudoers.c:656 plugins/sudoers/visudo.c:916
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "kunne ikke fortolke %s-fil, ukendt fejl"
+
+#: plugins/sudoers/cvtsudoers.c:664 plugins/sudoers/visudo.c:933
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr "fortolkningsfejl i %s nær linje %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:667 plugins/sudoers/visudo.c:936
+#, c-format
+msgid "parse error in %s\n"
+msgstr "fortolkningsfejl i %s\n"
+
+#: plugins/sudoers/cvtsudoers.c:1297 plugins/sudoers/iolog.c:502
+#: plugins/sudoers/sudoreplay.c:1135 plugins/sudoers/timestamp.c:294
+#: plugins/sudoers/timestamp.c:297
+#, c-format
+msgid "unable to write to %s"
+msgstr "kan ikke skrive til %s"
+
+#: plugins/sudoers/cvtsudoers.c:1320
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s - konverter mellem sudoers-filformater\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1322
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Tilvalg:\n"
+" -b, --base=dn base-DN'en for sudo LDAP-forespørgsler\n"
+" -d, --defaults=deftyper konverter kun Standarder for angivne typer\n"
+" -e, --expand-aliases udvid aliasser under konvertering\n"
+" -f, --output-format=format angiv uddataformat: JSON, LDIF eller sudoers\n"
+" -i, --input-format=format angiv inddataformat: LDIF eller sudoers\n"
+" -I, --increment=num mængde at øge hver sudoOrder med\n"
+" -h, --help vis denne hjælpetekst og afslut\n"
+" -m, --match=filter konverter kun poster som matcher filteret\n"
+" -M, --match-local matchfilter bruger passwd og gruppedatabaser\n"
+" -o, --output=uddatafil skriv konverteret sudoers til uddatafil\n"
+" -O, --order-start=num startpunkt for første sudoOrder\n"
+" -p, --prune-matches trim ikkematchende brugere, grupper og værter\n"
+" -s, --suppress=sektioner undertryk uddata for bestemte sektioner\n"
+" -V, --version vis information om version og afslut"
+
+#: plugins/sudoers/cvtsudoers_json.c:673 plugins/sudoers/cvtsudoers_json.c:708
+#: plugins/sudoers/cvtsudoers_json.c:924
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "ukendt indgang »%s« for standarder"
+
+#: plugins/sudoers/cvtsudoers_json.c:844 plugins/sudoers/cvtsudoers_json.c:859
+#: plugins/sudoers/cvtsudoers_ldif.c:299 plugins/sudoers/cvtsudoers_ldif.c:310
+#: plugins/sudoers/ldap.c:474
+msgid "unable to get GMT time"
+msgstr "kan ikke indhente GMT-tid"
+
+#: plugins/sudoers/cvtsudoers_json.c:847 plugins/sudoers/cvtsudoers_json.c:862
+#: plugins/sudoers/cvtsudoers_ldif.c:302 plugins/sudoers/cvtsudoers_ldif.c:313
+#: plugins/sudoers/ldap.c:480
+msgid "unable to format timestamp"
+msgstr "kan ikke formatere tidsstempel"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:517 plugins/sudoers/env.c:295
+#: plugins/sudoers/env.c:302 plugins/sudoers/env.c:407
+#: plugins/sudoers/ldap.c:488 plugins/sudoers/ldap.c:719
+#: plugins/sudoers/ldap.c:1046 plugins/sudoers/ldap_conf.c:218
+#: plugins/sudoers/ldap_conf.c:308 plugins/sudoers/linux_audit.c:82
+#: plugins/sudoers/logging.c:1008 plugins/sudoers/policy.c:618
+#: plugins/sudoers/policy.c:628 plugins/sudoers/prompt.c:161
+#: plugins/sudoers/sudoers.c:840 plugins/sudoers/testsudoers.c:236
+#: plugins/sudoers/toke_util.c:157
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "intern fejl, %s-overløb"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:622
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "miljøvariablen SUDOERS_BASE er ikke angivet og tilvalget -b var ikke angivet."
+
+#: plugins/sudoers/cvtsudoers_ldif.c:757
+#, c-format
+msgid "ignoring invalid attribute value: %s"
+msgstr "ignorerer ugyldig attributværdi: %s"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:1197
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "ignorerer ufuldstændig sudoRole: cn: %s"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:1349 plugins/sudoers/ldap.c:1778
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "ugyldig sudoOrder-attribut: %s"
+
+#: plugins/sudoers/def_data.c:42
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Syslog-facilitet hvis syslog bruges til logning: %s"
+
+#: plugins/sudoers/def_data.c:46
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Syslog-prioritet at bruge når brugergodkendelser går igennem: %s"
+
+#: plugins/sudoers/def_data.c:50
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Syslog-prioritet at bruge når brugergodkendelser ikke går igennem: %s"
+
+#: plugins/sudoers/def_data.c:54
+msgid "Put OTP prompt on its own line"
+msgstr "Placer OTP-prompter på deres egen linje"
+
+#: plugins/sudoers/def_data.c:58
+msgid "Ignore '.' in $PATH"
+msgstr "Ignorer ».« i $PATH"
+
+#: plugins/sudoers/def_data.c:62
+msgid "Always send mail when sudo is run"
+msgstr "Send altid post når sudo køres"
+
+#: plugins/sudoers/def_data.c:66
+msgid "Send mail if user authentication fails"
+msgstr "Send post hvis brugergodkendelse fejler"
+
+#: plugins/sudoers/def_data.c:70
+msgid "Send mail if the user is not in sudoers"
+msgstr "Send post hvis brugeren ikke er i suoders"
+
+#: plugins/sudoers/def_data.c:74
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Send post hvis brugeren ikke er i sudoers for denne vært"
+
+#: plugins/sudoers/def_data.c:78
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Send post hvis brugeren ikke har tilladelse til at køre en kommando"
+
+#: plugins/sudoers/def_data.c:82
+msgid "Send mail if the user tries to run a command"
+msgstr "Send post hvis brugeren forsøger at køre en kommando"
+
+#: plugins/sudoers/def_data.c:86
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Brug et separat tidsstempel for hver bruger/tty-kombination"
+
+#: plugins/sudoers/def_data.c:90
+msgid "Lecture user the first time they run sudo"
+msgstr "Undervis brugere den første gang de kører sudo"
+
+#: plugins/sudoers/def_data.c:94
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Fil indeholdende sudo-undervisningen: %s"
+
+#: plugins/sudoers/def_data.c:98
+msgid "Require users to authenticate by default"
+msgstr "Kræv som standard at brugere skal godkendes"
+
+#: plugins/sudoers/def_data.c:102
+msgid "Root may run sudo"
+msgstr "Root kan køre sudo"
+
+#: plugins/sudoers/def_data.c:106
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Log værtsnavnet i logfilen (non-syslog)"
+
+#: plugins/sudoers/def_data.c:110
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Log året i logfilen (non-syslog)"
+
+#: plugins/sudoers/def_data.c:114
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Hvis sudo er startet op uden argumenter så start en skal"
+
+#: plugins/sudoers/def_data.c:118
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Angiv $HOME for målbrugeren når der startes en skal med -s"
+
+#: plugins/sudoers/def_data.c:122
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Angiv altid $HOME for målbrugerens hjemmemappe"
+
+#: plugins/sudoers/def_data.c:126
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Tillad lidt informationsindsamling for at lave brugbare fejlbeskeder"
+
+#: plugins/sudoers/def_data.c:130
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Kræv fuldkvalificerede værtsnavne i sudoersfilen"
+
+#: plugins/sudoers/def_data.c:134
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Fornærm brugeren når de indtaster en forkert adgangskode"
+
+#: plugins/sudoers/def_data.c:138
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Tillad kun brugeren at køre sudo hvis de har en tty"
+
+#: plugins/sudoers/def_data.c:142
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo vil overholde EDITOR-miljøvariablen"
+
+#: plugins/sudoers/def_data.c:146
+msgid "Prompt for root's password, not the users's"
+msgstr "Spørg om adgangskoden for root, ikke brugerens"
+
+#: plugins/sudoers/def_data.c:150
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Spørg om brugerens kør som_standard adgangskode, ikke brugernes"
+
+#: plugins/sudoers/def_data.c:154
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Spørg om målbrugerens adgangskode, ikke brugernes"
+
+#: plugins/sudoers/def_data.c:158
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Brug standarder i målbrugerens logindklasse hvis der er en"
+
+#: plugins/sudoers/def_data.c:162
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Angiv LOGNAME- og USER-miljøvariablerne"
+
+#: plugins/sudoers/def_data.c:166
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Angiv kun den effektive uid til målbrugeren, ikke den reelle uid"
+
+#: plugins/sudoers/def_data.c:170
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Initialiser ikke gruppevektoren til målbrugerens"
+
+#: plugins/sudoers/def_data.c:174
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Længde hvor logfillinjer skal ombrydes (0 for ingen ombrydning): %u"
+
+#: plugins/sudoers/def_data.c:178
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Tidsudløb for godkendelsestidsstempel: %.1f minutter"
+
+#: plugins/sudoers/def_data.c:182
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Tidsudløb for adgangskodeprompt: %.1f minutter"
+
+#: plugins/sudoers/def_data.c:186
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Antal forsøg for indtastning af adgangskode: %u"
+
+#: plugins/sudoers/def_data.c:190
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Umask at bruge eller 0777 for at bruge brugers: 0%o"
+
+#: plugins/sudoers/def_data.c:194
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Sti til logfil: %s"
+
+#: plugins/sudoers/def_data.c:198
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Stil til postprogram: %s"
+
+#: plugins/sudoers/def_data.c:202
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Flag for postprogram: %s"
+
+#: plugins/sudoers/def_data.c:206
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Adresse at sende post til: %s"
+
+#: plugins/sudoers/def_data.c:210
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Adresse at sende post fra: %s"
+
+#: plugins/sudoers/def_data.c:214
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Emnelinje for postbeskeder: %s"
+
+#: plugins/sudoers/def_data.c:218
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Ugyldig adgangskodebesked: %s"
+
+#: plugins/sudoers/def_data.c:222
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Sti til undervisningsstatusmappen: %s"
+
+#: plugins/sudoers/def_data.c:226
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Sti til mappe for godkendelsestidsstempel: %s"
+
+#: plugins/sudoers/def_data.c:230
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Ejer af mappen for godkendelsestidsstempel: %s"
+
+#: plugins/sudoers/def_data.c:234
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Brugere i denne gruppe er undtaget fra adgangskode og STI-krav: %s"
+
+#: plugins/sudoers/def_data.c:238
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Standard for adgangskodeprompt: %s"
+
+#: plugins/sudoers/def_data.c:242
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Hvis angivet vil adgangsprompt overskrive systemprompt i alle tilfælde."
+
+#: plugins/sudoers/def_data.c:246
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Standardbruger at køre kommandoer som: %s"
+
+#: plugins/sudoers/def_data.c:250
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Værdi at overskrive brugers $PATH med: %s"
+
+#: plugins/sudoers/def_data.c:254
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Sti til redigeringsprogrammet for brug af visudo: %s"
+
+#: plugins/sudoers/def_data.c:258
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Hvornår der skal kræves en adgangskode for »list« pseudokommando: %s"
+
+#: plugins/sudoers/def_data.c:262
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Hvornår der skal kræves en adgangskode for »verify« pseudokommando: %s"
+
+#: plugins/sudoers/def_data.c:266
+msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+msgstr "Præindlæs attrap-udførelsesfunktioner indeholdt i biblioteket sudo_noexec"
+
+#: plugins/sudoers/def_data.c:270
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Hvis LDAP-mappe er sat op, ignorer vi så lokal sudoersfil"
+
+#: plugins/sudoers/def_data.c:274
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Filbeskrivelser >= %d vil blive lukket før udførelse af en kommando"
+
+#: plugins/sudoers/def_data.c:278
+msgid "If set, users may override the value of `closefrom' with the -C option"
+msgstr "Hvis angivet kan brugere overskrive værdien af »closeform« med tilvalget -C"
+
+#: plugins/sudoers/def_data.c:282
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Tillad at brugere kan angive arbitrære miljøvariabler"
+
+#: plugins/sudoers/def_data.c:286
+msgid "Reset the environment to a default set of variables"
+msgstr "Nulstil miljøet til et standardsæt af variabler"
+
+#: plugins/sudoers/def_data.c:290
+msgid "Environment variables to check for sanity:"
+msgstr "Miljøvariabler at indstillingskontrollere:"
+
+#: plugins/sudoers/def_data.c:294
+msgid "Environment variables to remove:"
+msgstr "Miljøvariabler at fjerne:"
+
+#: plugins/sudoers/def_data.c:298
+msgid "Environment variables to preserve:"
+msgstr "Miljøvariabler at bevare:"
+
+#: plugins/sudoers/def_data.c:302
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "SELinux-rolle at bruge i den nye sikkerhedskontekst: %s"
+
+#: plugins/sudoers/def_data.c:306
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "SELinux-type at bruge i den nye sikkerhedskontekst: %s"
+
+#: plugins/sudoers/def_data.c:310
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Sti til den sudo-specifikke miljøfil: %s"
+
+#: plugins/sudoers/def_data.c:314
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Sti til det begrænsede sudo-specifikke miljøfil: %s"
+
+#: plugins/sudoers/def_data.c:318
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Sprog at bruge under fortolkning af sudoers: %s"
+
+#: plugins/sudoers/def_data.c:322
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Tillad at sudo spørger om en adgangskode selv om den vil være synlig"
+
+#: plugins/sudoers/def_data.c:326
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Tilbyd visuel tilbagemeldning ved adgangskodeprompten når der er brugerinddata"
+
+#: plugins/sudoers/def_data.c:330
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Brug hurtigere globbing som er mindre præcis, men som ikke tilgår filsystemet"
+
+#: plugins/sudoers/def_data.c:334
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "Umask'en angivet i sudoers vil overskrive brugerens, også selv om den er mere tilladende"
+
+#: plugins/sudoers/def_data.c:338
+msgid "Log user's input for the command being run"
+msgstr "Log brugers inddata for kommandoen der bliver kørt"
+
+#: plugins/sudoers/def_data.c:342
+msgid "Log the output of the command being run"
+msgstr "Log uddata for kommandoen der bliver kørt"
+
+#: plugins/sudoers/def_data.c:346
+msgid "Compress I/O logs using zlib"
+msgstr "Komprimer I/O-log med brug af zlib"
+
+#: plugins/sudoers/def_data.c:350
+msgid "Always run commands in a pseudo-tty"
+msgstr "Kør altid kommandoer i en pseudo-tty"
+
+#: plugins/sudoers/def_data.c:354
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Udvidelsesmodul for ikke-Unix-gruppeunderstøttelse: %s"
+
+#: plugins/sudoers/def_data.c:358
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Mappe at gemme inddata-/uddatalogge i: %s"
+
+#: plugins/sudoers/def_data.c:362
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Fil at gemme inddata-/uddatalog i: %s"
+
+#: plugins/sudoers/def_data.c:366
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Tilføjer et punkt til utmp/utmpx-filen når der allokeres en pty"
+
+#: plugins/sudoers/def_data.c:370
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Angiv brugeren i utmp til brugeren kør som, ikke den opstartende bruger"
+
+#: plugins/sudoers/def_data.c:374
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Sæt af tilladte privilegier: %s"
+
+# Det skal forstås som et sæt af grænseprivilegier
+# https://www.sudo.ws/man/1.8.21/sudoers.man.html (se limitprivs)
+#: plugins/sudoers/def_data.c:378
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Sæt af grænseprivilegier: %s"
+
+#: plugins/sudoers/def_data.c:382
+msgid "Run commands on a pty in the background"
+msgstr "Kør kommandoer på en pty i baggrunden"
+
+#: plugins/sudoers/def_data.c:386
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "PAM-tjenestenavn der skal bruges: %s"
+
+#: plugins/sudoers/def_data.c:390
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "PAM-tjenestenavn der skal bruges for logindskaller: %s"
+
+#: plugins/sudoers/def_data.c:394
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Forsøg på at etablere PAM-akkreditiver for målbrugeren"
+
+#: plugins/sudoers/def_data.c:398
+msgid "Create a new PAM session for the command to run in"
+msgstr "Opret en ny PAM-session som kommandoen kan køre i"
+
+#: plugins/sudoers/def_data.c:402
+#, c-format
+msgid "Maximum I/O log sequence number: %u"
+msgstr "Maksimalt I/O-logsekvenstal: %u"
+
+#: plugins/sudoers/def_data.c:406
+msgid "Enable sudoers netgroup support"
+msgstr "Aktiver sudoers netgroup-understøttelse"
+
+#: plugins/sudoers/def_data.c:410
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Kontroller overmappers skriverettigheder ved redigering af filer med sudoedit"
+
+#: plugins/sudoers/def_data.c:414
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Følg symbolske henvisninger når filer redigeres med sudoedit"
+
+#: plugins/sudoers/def_data.c:418
+msgid "Query the group plugin for unknown system groups"
+msgstr "Forespørg gruppe-udvidelsesmodulet for ukendte systemgrupper"
+
+#: plugins/sudoers/def_data.c:422
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Sammenlign netgrupper baseret på hele tuplen: bruger, vært og domæne"
+
+#: plugins/sudoers/def_data.c:426
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Tillader at kommandoer køres, selv om sudo ikke kan skrive til revisionsloggen"
+
+#: plugins/sudoers/def_data.c:430
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Tillader at kommandoer køres, selv om sudo ikke kan skrive til I/O-loggen"
+
+#: plugins/sudoers/def_data.c:434
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Tillader at kommandoer køres, selv om sudo ikke kan skrive til logfilen"
+
+#: plugins/sudoers/def_data.c:438
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Slå grupper op i sudoers og match efter gruppe-id, ikke navnet"
+
+#: plugins/sudoers/def_data.c:442
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Logposter større end denne værdi vil blive opdelt i flere syslogbeskeder: %u"
+
+#: plugins/sudoers/def_data.c:446
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Bruger som vil eje I/O-logfilerne: %s"
+
+#: plugins/sudoers/def_data.c:450
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Gruppe som vil eje I/O-logfilerne: %s"
+
+#: plugins/sudoers/def_data.c:454
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Filtilstand der skal bruges for I/O-logfilerne: 0%o"
+
+#: plugins/sudoers/def_data.c:458
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Kør kommandoer efter fildeskriptor i stedet for efter sti: %s"
+
+# Defaults-punkter/indgange", vil jeg tro
+# Vil mene at det er en overskrift i konfigurationsfilen eller lignende
+#: plugins/sudoers/def_data.c:462
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Ignorer ukendte Defaults-punkter i sudoere i stedet for at give en advarsel"
+
+#: plugins/sudoers/def_data.c:466
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Tid i sekunder hvorefter kommandoen vil blive afsluttet: %u"
+
+#: plugins/sudoers/def_data.c:470
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Tillad at brugeren angiver et tidsudløb på kommandolinjen"
+
+#: plugins/sudoers/def_data.c:474
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Tøm I/O-logdata til disken med det samme i stedet for at mellemlagre den"
+
+#: plugins/sudoers/def_data.c:478
+msgid "Include the process ID when logging via syslog"
+msgstr "Inkluder proces-id'et når der logges via syslog"
+
+#: plugins/sudoers/def_data.c:482
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Elementtype for godkendelsestidsstempel: %s"
+
+#: plugins/sudoers/def_data.c:486
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "godkendelsesfejlbesked: %s"
+
+#: plugins/sudoers/def_data.c:490
+msgid "Ignore case when matching user names"
+msgstr "Ignorer store/små bogstaver når brugernavne matches"
+
+#: plugins/sudoers/def_data.c:494
+msgid "Ignore case when matching group names"
+msgstr "Ignorer store/små bogstaver når gruppenavne matches"
+
+#: plugins/sudoers/defaults.c:224
+#, c-format
+msgid "%s:%d unknown defaults entry \"%s\""
+msgstr "%s:%d ukendt indgang »%s« for standarder"
+
+#: plugins/sudoers/defaults.c:227
+#, c-format
+msgid "%s: unknown defaults entry \"%s\""
+msgstr "%s: ukendt indgang »%s« for standarder"
+
+#: plugins/sudoers/defaults.c:270
+#, c-format
+msgid "%s:%d no value specified for \"%s\""
+msgstr "%s:%d ingen værdi angivet for »%s«"
+
+#: plugins/sudoers/defaults.c:273
+#, c-format
+msgid "%s: no value specified for \"%s\""
+msgstr "%s: ingen værdi angivet for »%s«"
+
+#: plugins/sudoers/defaults.c:293
+#, c-format
+msgid "%s:%d values for \"%s\" must start with a '/'"
+msgstr "%s:%d værdier for »%s« skal begynde med en »/«"
+
+#: plugins/sudoers/defaults.c:296
+#, c-format
+msgid "%s: values for \"%s\" must start with a '/'"
+msgstr "%s: værdier for »%s« skal begynde med en »/«"
+
+#: plugins/sudoers/defaults.c:318
+#, c-format
+msgid "%s:%d option \"%s\" does not take a value"
+msgstr "%s:%d indstillingen »%s« kan ikke modtage en værdi"
+
+#: plugins/sudoers/defaults.c:321
+#, c-format
+msgid "%s: option \"%s\" does not take a value"
+msgstr "%s: indstillingen »%s« kan ikke modtage en værdi"
+
+#: plugins/sudoers/defaults.c:346
+#, c-format
+msgid "%s:%d invalid Defaults type 0x%x for option \"%s\""
+msgstr "%s:%d ugyldig standardtype 0x%x for tilvalget »%s«"
+
+#: plugins/sudoers/defaults.c:349
+#, c-format
+msgid "%s: invalid Defaults type 0x%x for option \"%s\""
+msgstr "%s: ugyldig standardtype 0x%x for tilvalget »%s«"
+
+#: plugins/sudoers/defaults.c:359
+#, c-format
+msgid "%s:%d value \"%s\" is invalid for option \"%s\""
+msgstr "%s:%d værdien »%s« er ugyldig for tilvalget »%s«"
+
+#: plugins/sudoers/defaults.c:362
+#, c-format
+msgid "%s: value \"%s\" is invalid for option \"%s\""
+msgstr "%s: værdien »%s« er ugyldig for tilvalget »%s«"
+
+#: plugins/sudoers/env.c:376
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: ødelagt envp, forskellig længde"
+
+#: plugins/sudoers/env.c:1055
+msgid "unable to rebuild the environment"
+msgstr "kan ikke genopbygge miljøet"
+
+#: plugins/sudoers/env.c:1129
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "beklager, du har ikke tilladelse til at angive de følgende miljøvariabler: %s"
+
+#: plugins/sudoers/file.c:111
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr "fortolkningsfejl i %s nær linje %d"
+
+#: plugins/sudoers/file.c:114
+#, c-format
+msgid "parse error in %s"
+msgstr "fortolkningsfejl i %s"
+
+#: plugins/sudoers/filedigest.c:56
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr "ej understøttet sammendragstype %d for %s"
+
+#: plugins/sudoers/filedigest.c:85
+#, c-format
+msgid "%s: read error"
+msgstr "%s: læsefejl"
+
+#: plugins/sudoers/group_plugin.c:83
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s skal være ejet af uid %d"
+
+#: plugins/sudoers/group_plugin.c:87
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr "%s skal være skrivbar af ejer"
+
+#: plugins/sudoers/group_plugin.c:95 plugins/sudoers/sssd.c:550
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "kan ikke indlæse %s: %s"
+
+#: plugins/sudoers/group_plugin.c:101
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "kan ikke finde symbol »group_plugin« i %s"
+
+#: plugins/sudoers/group_plugin.c:106
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: inkompatibel gruppeudvidelsesmodul for hovedversion %d, forventede %d"
+
+#: plugins/sudoers/interfaces.c:79 plugins/sudoers/interfaces.c:96
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "kan ikke fortolke IP-adressen »%s«"
+
+#: plugins/sudoers/interfaces.c:84 plugins/sudoers/interfaces.c:101
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "kan ikke fortolke netmasken »%s«"
+
+#: plugins/sudoers/interfaces.c:129
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Lokal IP-adresse og netmaskepar:\n"
+
+#: plugins/sudoers/iolog.c:119 plugins/sudoers/mkdir_parents.c:75
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s findes men er ikke en mappe (0%o)"
+
+#: plugins/sudoers/iolog.c:144 plugins/sudoers/iolog.c:184
+#: plugins/sudoers/mkdir_parents.c:64 plugins/sudoers/timestamp.c:174
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "kan ikke mkdir %s"
+
+#: plugins/sudoers/iolog.c:188 plugins/sudoers/visudo.c:718
+#: plugins/sudoers/visudo.c:728
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "kan ikke ændre tilstand på %s til 0%o"
+
+#: plugins/sudoers/iolog.c:296 plugins/sudoers/sudoers.c:1162
+#: plugins/sudoers/testsudoers.c:390
+#, c-format
+msgid "unknown group: %s"
+msgstr "ukendt gruppe: %s"
+
+#: plugins/sudoers/iolog.c:466 plugins/sudoers/sudoers.c:902
+#: plugins/sudoers/sudoreplay.c:868 plugins/sudoers/sudoreplay.c:1681
+#: plugins/sudoers/tsdump.c:140
+#, c-format
+msgid "unable to read %s"
+msgstr "kan ikke læse %s"
+
+#: plugins/sudoers/iolog.c:581 plugins/sudoers/iolog.c:800
+#, c-format
+msgid "unable to create %s"
+msgstr "kan ikke oprette %s"
+
+#: plugins/sudoers/iolog.c:1032 plugins/sudoers/iolog.c:1107
+#: plugins/sudoers/iolog.c:1188
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "kan ikke skrive til I/O-logfilen: %s"
+
+#: plugins/sudoers/iolog.c:1066
+#, c-format
+msgid "%s: internal error, file index %d not open"
+msgstr "%s: intern fejl, filindekset %d er ikke åbent"
+
+#: plugins/sudoers/ldap.c:170 plugins/sudoers/ldap_conf.c:287
+msgid "starttls not supported when using ldaps"
+msgstr "starttls er ikke understøttet, når der bruges ldaps"
+
+#: plugins/sudoers/ldap.c:241
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "kan ikke initialisere SSL-cert og key db: %s"
+
+#: plugins/sudoers/ldap.c:244
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "du skal angive at TLS_CERT i %s skal bruge SSL"
+
+#: plugins/sudoers/ldap.c:1606
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "kan ikke initialisere LDAP: %s"
+
+#: plugins/sudoers/ldap.c:1642
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls angivet men LDAP libs understøtter ikke ldap_start_tls_s() eller ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap_conf.c:196
+msgid "sudo_ldap_conf_add_ports: port too large"
+msgstr "sudo_ldap_conf_add_ports: port for stor"
+
+#: plugins/sudoers/ldap_conf.c:256
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "ikkeunderstøttet LDAP uri-type: %s"
+
+#: plugins/sudoers/ldap_conf.c:283
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "kan ikke blande ldap og ldaps URI'er"
+
+#: plugins/sudoers/ldap_util.c:470 plugins/sudoers/ldap_util.c:472
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "kan ikke konvertere sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:52
+msgid "unable to open audit system"
+msgstr "kan ikke åbne overvågningssystem"
+
+#: plugins/sudoers/linux_audit.c:93
+msgid "unable to send audit message"
+msgstr "kan ikke sende overvågningsbesked"
+
+#: plugins/sudoers/logging.c:108
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: plugins/sudoers/logging.c:136
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s: (kommando fortsat) %s"
+
+#: plugins/sudoers/logging.c:165
+#, c-format
+msgid "unable to open log file: %s"
+msgstr "kan ikke åbne logfilen: %s"
+
+#: plugins/sudoers/logging.c:173
+#, c-format
+msgid "unable to lock log file: %s"
+msgstr "kan ikke låse logfilen: %s"
+
+#: plugins/sudoers/logging.c:206
+#, c-format
+msgid "unable to write log file: %s"
+msgstr "kan ikke skrive til logfilen: %s"
+
+#: plugins/sudoers/logging.c:235
+msgid "No user or host"
+msgstr "Ingen bruger eller vært"
+
+#: plugins/sudoers/logging.c:237
+msgid "validation failure"
+msgstr "valideringsfejl"
+
+#: plugins/sudoers/logging.c:244
+msgid "user NOT in sudoers"
+msgstr "bruger IKKE i sudoers"
+
+#: plugins/sudoers/logging.c:246
+msgid "user NOT authorized on host"
+msgstr "bruger IKKE autoriseret på vært"
+
+#: plugins/sudoers/logging.c:248
+msgid "command not allowed"
+msgstr "kommando ikke tilladt"
+
+#: plugins/sudoers/logging.c:283
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr "%s er ikke sudoersfilen. Denne handling vil blive rapporteret.\n"
+
+#: plugins/sudoers/logging.c:286
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr "%s har ikke tilladelse til at køre sudo på %s. Denne handling vil blive rapporteret.\n"
+
+#: plugins/sudoers/logging.c:290
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Beklager. Bruger %s må ikke køre sudo på %s.\n"
+
+#: plugins/sudoers/logging.c:293
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr "Beklager. Bruger %s har ikke tilladelse til at køre »%s%s%s« som %s%s%s på %s.\n"
+
+#: plugins/sudoers/logging.c:330 plugins/sudoers/sudoers.c:433
+#: plugins/sudoers/sudoers.c:435 plugins/sudoers/sudoers.c:437
+#: plugins/sudoers/sudoers.c:439 plugins/sudoers/sudoers.c:594
+#: plugins/sudoers/sudoers.c:596
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: Kommando ikke fundet"
+
+#: plugins/sudoers/logging.c:332 plugins/sudoers/sudoers.c:429
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"ignorerer »%s« fundet i ».«\n"
+"Brug »sudo ./%s«, hvis dette er den »%s«, du ønsker at køre."
+
+#: plugins/sudoers/logging.c:349
+msgid "authentication failure"
+msgstr "godkendelsesfejl"
+
+#: plugins/sudoers/logging.c:375
+msgid "a password is required"
+msgstr "der kræves en adgangskode"
+
+#: plugins/sudoers/logging.c:438
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u ukorrekt adgangskodeforsøg"
+msgstr[1] "%u ukorrekte adgangskodeforsøg"
+
+#: plugins/sudoers/logging.c:659
+msgid "unable to fork"
+msgstr "kan ikke forgrene"
+
+#: plugins/sudoers/logging.c:667 plugins/sudoers/logging.c:719
+#, c-format
+msgid "unable to fork: %m"
+msgstr "kan ikke forgrene: %m"
+
+#: plugins/sudoers/logging.c:709
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "kan ikke åbne datakanal: %m"
+
+#: plugins/sudoers/logging.c:734
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "kan ikke dup stdin: %m"
+
+#: plugins/sudoers/logging.c:772
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "kan ikke køre %s: %m"
+
+#: plugins/sudoers/match.c:842
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "sammendrag for %s (%s) er ikke i %s-form"
+
+#: plugins/sudoers/mkdir_parents.c:70 plugins/sudoers/sudoers.c:913
+#: plugins/sudoers/visudo.c:416 plugins/sudoers/visudo.c:712
+#, c-format
+msgid "unable to stat %s"
+msgstr "kan ikke stat %s"
+
+#: plugins/sudoers/parse.c:434
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+"\n"
+"LDAP-rolle: %s\n"
+
+#: plugins/sudoers/parse.c:437
+#, c-format
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+"\n"
+"Sudoers-punkt:\n"
+
+#: plugins/sudoers/parse.c:439
+#, c-format
+msgid " RunAsUsers: "
+msgstr " KørSomBrugere: "
+
+#: plugins/sudoers/parse.c:454
+#, c-format
+msgid " RunAsGroups: "
+msgstr " KørSomGrupper: "
+
+#: plugins/sudoers/parse.c:464
+#, c-format
+msgid " Options: "
+msgstr " Tilvalg: "
+
+#: plugins/sudoers/parse.c:518
+#, c-format
+msgid " Commands:\n"
+msgstr " Kommandoer:\n"
+
+#: plugins/sudoers/parse.c:709
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Matchende standardpunkter for %s på %s:\n"
+
+#: plugins/sudoers/parse.c:727
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Kør som og kommandospecifikke standarder for %s:\n"
+
+#: plugins/sudoers/parse.c:745
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "Bruger %s må køre de følgende kommandoer på %s:\n"
+
+#: plugins/sudoers/parse.c:760
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Bruger %s har ikke tilladelse til at køre sudo på %s.\n"
+
+#: plugins/sudoers/policy.c:83 plugins/sudoers/policy.c:109
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "ugyldig %.*s angivet af sudo-brugerfladen"
+
+#: plugins/sudoers/policy.c:288 plugins/sudoers/testsudoers.c:259
+msgid "unable to parse network address list"
+msgstr "kan ikke fortolke netværksadresseliste"
+
+#: plugins/sudoers/policy.c:432
+msgid "user name not set by sudo front-end"
+msgstr "brugernavn er ikke angivet af sudo-brugerfladen"
+
+#: plugins/sudoers/policy.c:436
+msgid "user ID not set by sudo front-end"
+msgstr "bruger-id er ikke angivet af sudo-brugerfladen"
+
+#: plugins/sudoers/policy.c:440
+msgid "group ID not set by sudo front-end"
+msgstr "gruppe-id er ikke angivet af sudo-brugerfladen"
+
+#: plugins/sudoers/policy.c:444
+msgid "host name not set by sudo front-end"
+msgstr "værtsnavn er ikke angivet af sudo-brugerfladen"
+
+#: plugins/sudoers/policy.c:797 plugins/sudoers/visudo.c:215
+#: plugins/sudoers/visudo.c:845
+#, c-format
+msgid "unable to execute %s"
+msgstr "kan ikke udføre %s"
+
+#: plugins/sudoers/policy.c:930
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Udvidelsesmodulversion %s for sudoerspolitik\n"
+
+#: plugins/sudoers/policy.c:932
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Grammatikversion %d for sudoersfil\n"
+
+#: plugins/sudoers/policy.c:936
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Sudoers-sti: %s\n"
+
+#: plugins/sudoers/policy.c:939
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "nsswitch-sti: %s\n"
+
+#: plugins/sudoers/policy.c:941
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "ldap.conf-sti: %s\n"
+
+#: plugins/sudoers/policy.c:942
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "ldap.secret-sti: %s\n"
+
+# lidt i tvivl om hvad hook er her, så har beholdt den uoversat
+# Er OK. Er enig med hensyn til hook, skal nok forstås som
+# fastgøringspunkt, men lyder for bøvlet
+#: plugins/sudoers/policy.c:975
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "kan ikke registrere »hook« af typen %d (version %d.%d)"
+
+#: plugins/sudoers/pwutil.c:214 plugins/sudoers/pwutil.c:233
+#, c-format
+msgid "unable to cache uid %u, out of memory"
+msgstr "kan ikke cache uid %u, ikke nok hukommelse"
+
+#: plugins/sudoers/pwutil.c:227
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "kan ikke cache uid %u, findes allerede"
+
+#: plugins/sudoers/pwutil.c:287 plugins/sudoers/pwutil.c:305
+#: plugins/sudoers/pwutil.c:367 plugins/sudoers/pwutil.c:412
+#, c-format
+msgid "unable to cache user %s, out of memory"
+msgstr "kan ikke cache bruger %s, ikke nok hukommelse"
+
+#: plugins/sudoers/pwutil.c:300
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "kan ikke cache bruger %s, findes allerede"
+
+#: plugins/sudoers/pwutil.c:531 plugins/sudoers/pwutil.c:550
+#, c-format
+msgid "unable to cache gid %u, out of memory"
+msgstr "kan ikke cache gid %u, ikke nok hukommelse"
+
+#: plugins/sudoers/pwutil.c:544
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "kan ikke cache gid %u, findes allerede"
+
+#: plugins/sudoers/pwutil.c:598 plugins/sudoers/pwutil.c:616
+#: plugins/sudoers/pwutil.c:663 plugins/sudoers/pwutil.c:705
+#, c-format
+msgid "unable to cache group %s, out of memory"
+msgstr "kan ikke cache gruppe %s, ikke nok hukommelse"
+
+#: plugins/sudoers/pwutil.c:611
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "kan ikke cache gruppe %s, findes allerede"
+
+#: plugins/sudoers/pwutil.c:831 plugins/sudoers/pwutil.c:883
+#: plugins/sudoers/pwutil.c:934 plugins/sudoers/pwutil.c:987
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "kan ikke cache gruppeliste for %s, findes allerede"
+
+#: plugins/sudoers/pwutil.c:837 plugins/sudoers/pwutil.c:888
+#: plugins/sudoers/pwutil.c:940 plugins/sudoers/pwutil.c:992
+#, c-format
+msgid "unable to cache group list for %s, out of memory"
+msgstr "kan ikke cache gruppeliste for %s, ikke nok hukommelse"
+
+#: plugins/sudoers/pwutil.c:877
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "kan ikke fortolke grupper for %s"
+
+#: plugins/sudoers/pwutil.c:981
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "kan ikke fortolke gid'er for %s"
+
+#: plugins/sudoers/set_perms.c:113 plugins/sudoers/set_perms.c:469
+#: plugins/sudoers/set_perms.c:912 plugins/sudoers/set_perms.c:1239
+#: plugins/sudoers/set_perms.c:1556
+msgid "perm stack overflow"
+msgstr "permanent stakoverløb"
+
+#: plugins/sudoers/set_perms.c:121 plugins/sudoers/set_perms.c:400
+#: plugins/sudoers/set_perms.c:477 plugins/sudoers/set_perms.c:779
+#: plugins/sudoers/set_perms.c:920 plugins/sudoers/set_perms.c:1163
+#: plugins/sudoers/set_perms.c:1247 plugins/sudoers/set_perms.c:1489
+#: plugins/sudoers/set_perms.c:1564 plugins/sudoers/set_perms.c:1654
+msgid "perm stack underflow"
+msgstr "permanent stakunderløb"
+
+#: plugins/sudoers/set_perms.c:180 plugins/sudoers/set_perms.c:523
+#: plugins/sudoers/set_perms.c:1298 plugins/sudoers/set_perms.c:1596
+msgid "unable to change to root gid"
+msgstr "kan ikke ændre til root gid"
+
+#: plugins/sudoers/set_perms.c:269 plugins/sudoers/set_perms.c:620
+#: plugins/sudoers/set_perms.c:1049 plugins/sudoers/set_perms.c:1375
+msgid "unable to change to runas gid"
+msgstr "kan ikke ændre til kør som gid"
+
+#: plugins/sudoers/set_perms.c:274 plugins/sudoers/set_perms.c:625
+#: plugins/sudoers/set_perms.c:1054 plugins/sudoers/set_perms.c:1380
+msgid "unable to set runas group vector"
+msgstr "kan ikke angive kør som gruppevektor"
+
+#: plugins/sudoers/set_perms.c:285 plugins/sudoers/set_perms.c:636
+#: plugins/sudoers/set_perms.c:1063 plugins/sudoers/set_perms.c:1389
+msgid "unable to change to runas uid"
+msgstr "kan ikke ændre til kør som uid"
+
+#: plugins/sudoers/set_perms.c:303 plugins/sudoers/set_perms.c:654
+#: plugins/sudoers/set_perms.c:1079 plugins/sudoers/set_perms.c:1405
+msgid "unable to change to sudoers gid"
+msgstr "kan ikke ændre til sudoers gid"
+
+#: plugins/sudoers/set_perms.c:387 plugins/sudoers/set_perms.c:766
+#: plugins/sudoers/set_perms.c:1150 plugins/sudoers/set_perms.c:1476
+#: plugins/sudoers/set_perms.c:1641
+msgid "too many processes"
+msgstr "for mange processer"
+
+#: plugins/sudoers/solaris_audit.c:51
+msgid "unable to get current working directory"
+msgstr "kan ikke hente nuværende arbejdsmappe"
+
+#: plugins/sudoers/solaris_audit.c:59
+#, c-format
+msgid "truncated audit path user_cmnd: %s"
+msgstr "afkortet revisionssti user_cmnd: %s"
+
+#: plugins/sudoers/solaris_audit.c:66
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "afkortet revisionssti argv[0]: %s"
+
+#: plugins/sudoers/solaris_audit.c:115
+msgid "audit_failure message too long"
+msgstr "audit_failure-besked er for lang"
+
+#: plugins/sudoers/sssd.c:552
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "kan ikke initialisere SSS-kilde. Er SSSD installeret på din maskine?"
+
+#: plugins/sudoers/sssd.c:560 plugins/sudoers/sssd.c:569
+#: plugins/sudoers/sssd.c:578 plugins/sudoers/sssd.c:587
+#: plugins/sudoers/sssd.c:596
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "kan ikke finde symbol »%s« i %s"
+
+#: plugins/sudoers/sudoers.c:204 plugins/sudoers/sudoers.c:859
+msgid "problem with defaults entries"
+msgstr "problem med standardpunkter"
+
+#: plugins/sudoers/sudoers.c:208
+msgid "no valid sudoers sources found, quitting"
+msgstr "ingen gyldige sudoerskilder fundet, afslutter"
+
+#: plugins/sudoers/sudoers.c:246
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers angiver at administrator (root) ikke har tilladelse til sudo"
+
+#: plugins/sudoers/sudoers.c:303
+msgid "you are not permitted to use the -C option"
+msgstr "du har ikke tilladelse til at bruge tilvalget -C"
+
+#: plugins/sudoers/sudoers.c:350
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr "tidsstempelejer (%s): Ingen sådan bruger"
+
+#: plugins/sudoers/sudoers.c:365
+msgid "no tty"
+msgstr "ingen tty"
+
+#: plugins/sudoers/sudoers.c:366
+msgid "sorry, you must have a tty to run sudo"
+msgstr "beklager, du skal bruge en tty for at køre sudo"
+
+#: plugins/sudoers/sudoers.c:428
+msgid "command in current directory"
+msgstr "kommando i aktuel mappe"
+
+#: plugins/sudoers/sudoers.c:447
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "beklager, men du har ikke tilladelse til at angive tidsudløb for kommando"
+
+#: plugins/sudoers/sudoers.c:455
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "beklager, men du har ikke tilladelse til at bevare miljøet"
+
+#: plugins/sudoers/sudoers.c:803
+msgid "command too long"
+msgstr "kommando er for lang"
+
+#: plugins/sudoers/sudoers.c:917
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s er ikke en regulær fil"
+
+#: plugins/sudoers/sudoers.c:921 plugins/sudoers/timestamp.c:221 toke.l:968
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s er ejet af uid %u, bør være %u"
+
+#: plugins/sudoers/sudoers.c:925 toke.l:973
+#, c-format
+msgid "%s is world writable"
+msgstr "%s er skrivbar for alle"
+
+#: plugins/sudoers/sudoers.c:929 toke.l:976
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s er eget af gid %u, bør være %u"
+
+#: plugins/sudoers/sudoers.c:962
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "kun administrator (root) kan bruge »-c %s«"
+
+#: plugins/sudoers/sudoers.c:981
+#, c-format
+msgid "unknown login class: %s"
+msgstr "ukendt logindklasse: %s"
+
+#: plugins/sudoers/sudoers.c:1064 plugins/sudoers/sudoers.c:1078
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "kan ikke slå vært %s op"
+
+#: plugins/sudoers/sudoreplay.c:274
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "ugyldigt filtertilvalg: %s"
+
+#: plugins/sudoers/sudoreplay.c:287
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "ugyldig maks ventetid: %s"
+
+#: plugins/sudoers/sudoreplay.c:307
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "ugyldig hastighedsfaktor: %s"
+
+#: plugins/sudoers/sudoreplay.c:342
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s/timing: %s"
+msgstr "%s/%.2s/%.2s/%.2s/timing: %s"
+
+#: plugins/sudoers/sudoreplay.c:348
+#, c-format
+msgid "%s/%s/timing: %s"
+msgstr "%s/%s/timing: %s"
+
+#: plugins/sudoers/sudoreplay.c:364
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Genafspiller sudosession: %s"
+
+#: plugins/sudoers/sudoreplay.c:562 plugins/sudoers/sudoreplay.c:609
+#: plugins/sudoers/sudoreplay.c:816 plugins/sudoers/sudoreplay.c:906
+#: plugins/sudoers/sudoreplay.c:985 plugins/sudoers/sudoreplay.c:1000
+#: plugins/sudoers/sudoreplay.c:1007 plugins/sudoers/sudoreplay.c:1014
+#: plugins/sudoers/sudoreplay.c:1021 plugins/sudoers/sudoreplay.c:1028
+#: plugins/sudoers/sudoreplay.c:1174
+msgid "unable to add event to queue"
+msgstr "kan ikke tilføje hændelse til køen"
+
+#: plugins/sudoers/sudoreplay.c:677
+msgid "unable to set tty to raw mode"
+msgstr "kan ikke angive tty til rå (raw) tilstand"
+
+#: plugins/sudoers/sudoreplay.c:728
+#, c-format
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr "Advarsel: Din terminal er for lille til korrekt at afspille loggen.\n"
+
+#: plugins/sudoers/sudoreplay.c:729
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Loggeometri er %d x %d, din terminals geometri er %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:757
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Genafspilning er afsluttet. Tryk på en tast for at gendanne terminalen."
+
+#: plugins/sudoers/sudoreplay.c:790
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "ugyldig timingfillinje: %s"
+
+#: plugins/sudoers/sudoreplay.c:1208 plugins/sudoers/sudoreplay.c:1233
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "tvetydigt udtryk »%s«"
+
+#: plugins/sudoers/sudoreplay.c:1255
+msgid "unmatched ')' in expression"
+msgstr "manglende »)« i udtryk"
+
+#: plugins/sudoers/sudoreplay.c:1259
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "ukendt søgeterm »%s«"
+
+#: plugins/sudoers/sudoreplay.c:1274
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s kræver et argument"
+
+#: plugins/sudoers/sudoreplay.c:1277 plugins/sudoers/sudoreplay.c:1657
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr "ugyldigt regulært udtryk: %s"
+
+#: plugins/sudoers/sudoreplay.c:1281
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "kunne ikke fortolke dato »%s«"
+
+#: plugins/sudoers/sudoreplay.c:1290
+msgid "unmatched '(' in expression"
+msgstr "mangler »(« i udtryk"
+
+#: plugins/sudoers/sudoreplay.c:1292
+msgid "illegal trailing \"or\""
+msgstr "ugyldig kæde »or« (eller)"
+
+#: plugins/sudoers/sudoreplay.c:1294
+msgid "illegal trailing \"!\""
+msgstr "ugyldig kæde »!«"
+
+#: plugins/sudoers/sudoreplay.c:1343
+#, c-format
+msgid "unknown search type %d"
+msgstr "ukendt søgeterm %d"
+
+#: plugins/sudoers/sudoreplay.c:1381
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: Ugyldig logfil"
+
+#: plugins/sudoers/sudoreplay.c:1399
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: Tidsstempelfelt mangler"
+
+#: plugins/sudoers/sudoreplay.c:1406
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: Tidsstempel %s: %s"
+
+#: plugins/sudoers/sudoreplay.c:1413
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: Brugerfelt mangler"
+
+#: plugins/sudoers/sudoreplay.c:1422
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: runas-brugerfelt mangler"
+
+#: plugins/sudoers/sudoreplay.c:1431
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: runas-gruppefelt mangler"
+
+#: plugins/sudoers/sudoreplay.c:1837
+#, c-format
+msgid "usage: %s [-hnR] [-d dir] [-m num] [-s num] ID\n"
+msgstr "brug: %s [-hnR] [-d mappe] [-m num] [-s num] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1840
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "brug: %s [-h] [-d mappe] -l [søgeudtryk]\n"
+
+#: plugins/sudoers/sudoreplay.c:1849
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - genafspil sudosessionslogge\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1851
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Tilvalg:\n"
+" -d, --directory=dir angiv mappe for sessionslogge\n"
+" -f, --filter=filter angiv hvilken I/O-type at vise\n"
+" -h, --help vis denne hjælpetekst og afslut\n"
+" -l, --list vis tilgængelige sessions-ID'er med valgfrit udtryk\n"
+" -m, --max-wait=num maks antal sekunder at vente mellem hændelser\n"
+" -s, --speed=num øg eller sænk uddata\n"
+" -V, --version vis versionsinformation og afslut"
+
+#: plugins/sudoers/testsudoers.c:328
+msgid "\thost unmatched"
+msgstr "\thost matchede ikke"
+
+#: plugins/sudoers/testsudoers.c:331
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Kommando tilladt"
+
+#: plugins/sudoers/testsudoers.c:332
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Kommando nægtet"
+
+#: plugins/sudoers/testsudoers.c:332
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Kommando ikke matchet"
+
+#: plugins/sudoers/timestamp.c:229
+#, c-format
+msgid "%s is group writable"
+msgstr "%s er gruppe-skrivbar"
+
+#: plugins/sudoers/timestamp.c:305
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "kan ikke afkorte tidsstempelfil til %lld byte"
+
+#: plugins/sudoers/timestamp.c:792 plugins/sudoers/timestamp.c:884
+#: plugins/sudoers/visudo.c:477 plugins/sudoers/visudo.c:483
+msgid "unable to read the clock"
+msgstr "kan ikke læse uret"
+
+#: plugins/sudoers/timestamp.c:803
+msgid "ignoring time stamp from the future"
+msgstr "ignorerer tidsstempel fra fremtiden"
+
+#: plugins/sudoers/timestamp.c:826
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "tidsstempel for langt ude i fremtiden: %20.20s"
+
+#: plugins/sudoers/timestamp.c:948
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "kan ikke låse tidsstempelfilen %s"
+
+#: plugins/sudoers/timestamp.c:992 plugins/sudoers/timestamp.c:1012
+#, c-format
+msgid "lecture status path too long: %s/%s"
+msgstr "undervisningsstatussti er for lang: %s/%s"
+
+#: plugins/sudoers/visudo.c:211
+msgid "the -x option will be removed in a future release"
+msgstr "tilvalget -x vil blive fjernet i fremtidige udgivelser"
+
+#: plugins/sudoers/visudo.c:212
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "overvej i stedet for at bruge redskabet cvtsudoers"
+
+#: plugins/sudoers/visudo.c:263 plugins/sudoers/visudo.c:645
+#, c-format
+msgid "press return to edit %s: "
+msgstr "tryk retur for at redigere %s: "
+
+#: plugins/sudoers/visudo.c:324
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "angivet redigeringsprogram (%s) findes ikke"
+
+#: plugins/sudoers/visudo.c:326
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "intet redigeringsprogram fundet (sti for redigeringsprogram = %s)"
+
+#: plugins/sudoers/visudo.c:436 plugins/sudoers/visudo.c:444
+msgid "write error"
+msgstr "skrivefejl"
+
+#: plugins/sudoers/visudo.c:490
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "kan ikke stat midlertidig fil (%s), %s unchanged"
+
+#: plugins/sudoers/visudo.c:497
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "midlertidig fil med nullængde (%s), %s uændret"
+
+#: plugins/sudoers/visudo.c:503
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "redigeringsprogram (%s) fejlede, %s uændret"
+
+#: plugins/sudoers/visudo.c:525
+#, c-format
+msgid "%s unchanged"
+msgstr "%s uændret"
+
+#: plugins/sudoers/visudo.c:584
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "kan ikke genåbne midlertidig fil (%s), %s uændrede."
+
+#: plugins/sudoers/visudo.c:596
+#, c-format
+msgid "unabled to parse temporary file (%s), unknown error"
+msgstr "kan ikke fortolke midlertidig fil (%s), ukendt fejl"
+
+#: plugins/sudoers/visudo.c:634
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr "intern fejl, kan ikke finde %s på listen!"
+
+#: plugins/sudoers/visudo.c:714 plugins/sudoers/visudo.c:723
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "kan ikke angive (uid, gid) af %s til (%u, %u)"
+
+#: plugins/sudoers/visudo.c:745
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s og %s er ikke på det samme filsystem, bruger mv til at omdøbe"
+
+#: plugins/sudoers/visudo.c:759
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "kommando fejlede: »%s %s %s«, %s uændret"
+
+#: plugins/sudoers/visudo.c:769
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "fejl under omdøbing af %s, %s uændret"
+
+#: plugins/sudoers/visudo.c:790
+msgid "What now? "
+msgstr "Hvad nu? "
+
+#: plugins/sudoers/visudo.c:804
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Tilvalg er:\n"
+" r(e)diger sudoersfil igen\n"
+" afslut(x) uden at gemme ændringer til sudoersfil\n"
+" afslut(Q) og gem ændringer til sudoersfil (FARLIGT!)\n"
+
+#: plugins/sudoers/visudo.c:850
+#, c-format
+msgid "unable to run %s"
+msgstr "kan ikke køre %s"
+
+#: plugins/sudoers/visudo.c:880
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: forkert ejer (uid, gid) bør være (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:887
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: ugyldige rettigheder, bør være tilstand 0%o\n"
+
+#: plugins/sudoers/visudo.c:944 plugins/sudoers/visudo.c:951
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: fortolket o.k.\n"
+
+#: plugins/sudoers/visudo.c:998
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s travl, forsøg igen senere"
+
+#: plugins/sudoers/visudo.c:1038
+#, c-format
+msgid "Error: %s:%d cycle in %s \"%s\""
+msgstr "Fejl: %s:%d: cyklus i %s »%s«"
+
+#: plugins/sudoers/visudo.c:1039
+#, c-format
+msgid "Warning: %s:%d cycle in %s \"%s\""
+msgstr "Advarsel: %s:%d: cyklus i %s »%s«"
+
+#: plugins/sudoers/visudo.c:1043
+#, c-format
+msgid "Error: %s:%d %s \"%s\" referenced but not defined"
+msgstr "Fejl: %s:%d %s »%s« refereret men ikke defineret"
+
+#: plugins/sudoers/visudo.c:1044
+#, c-format
+msgid "Warning: %s:%d %s \"%s\" referenced but not defined"
+msgstr "Advarsel: %s:%d %s »%s« refereret men ikke defineret"
+
+# (ental)
+#: plugins/sudoers/visudo.c:1137
+#, c-format
+msgid "Warning: %s:%d unused %s \"%s\""
+msgstr "Advarsel: %s:%d ubrugt %s »%s«"
+
+#: plugins/sudoers/visudo.c:1252
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - rediger sikkert sudoersfilen\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1254
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Tilvalg:\n"
+" -c, --check kun kontroltilstand\n"
+" -f, --file=file angiv filplacering for sudoers\n"
+" -h, --help vis denne hjælpetekst og afslut\n"
+" -q, --quiet mindre uddybende (stille) beskeder for syntaksfejl\n"
+" -s, --strict streng syntakskontrol\n"
+" -V, --version vis information om version og afslut\n"
+
+#: toke.l:942
+msgid "too many levels of includes"
+msgstr "for mange niveauer af includes (inkluderinger)"
diff --git a/plugins/sudoers/po/de.mo b/plugins/sudoers/po/de.mo
new file mode 100644
index 0000000..fb2f8fb
--- /dev/null
+++ b/plugins/sudoers/po/de.mo
Binary files differ
diff --git a/plugins/sudoers/po/de.po b/plugins/sudoers/po/de.po
new file mode 100644
index 0000000..ba312b5
--- /dev/null
+++ b/plugins/sudoers/po/de.po
@@ -0,0 +1,3867 @@
+# Portable object template file for the sudoers plugin
+# This file is put in the public domain.
+# Todd C. Miller <Todd.Miller@courtesan.com>, 2011-2013
+# Hendrik Knackstedt <hendrik.knackstedt@t-online.de>, 2013
+# Mario Blättermann <mario.blaettermann@gmail.com>, 2015.
+# Jochen Hein <jochen@jochen.org>, 2001-2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.9.15b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-10-19 10:02-0600\n"
+"PO-Revision-Date: 2023-10-21 18:25+0200\n"
+"Last-Translator: Jochen Hein <jochen@jochen.org>\n"
+"Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 2.3\n"
+
+#: confstr.sh:1 gram.y:1257 plugins/sudoers/logging.c:911
+msgid "syntax error"
+msgstr "Syntax-Fehler"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "%p's Passwort: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] Passwort für %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Passwort: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** Sicherheits-Information für %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Das hat nicht funktioniert, bitte nochmal probieren."
+
+#: gram.y:238 gram.y:305 gram.y:314 gram.y:323 gram.y:333 gram.y:343 gram.y:367
+#: gram.y:394 gram.y:403 gram.y:411 gram.y:420 gram.y:429 gram.y:503 gram.y:513
+#: gram.y:525 gram.y:573 gram.y:582 gram.y:591 gram.y:600 gram.y:733 gram.y:742
+#: gram.y:757 gram.y:777 gram.y:796 gram.y:959 gram.y:964 gram.y:972 gram.y:986
+#: gram.y:992 gram.y:1004 gram.y:1010 gram.y:1135 gram.y:1144 gram.y:1152
+#: gram.y:1161 gram.y:1170 gram.y:1199 gram.y:1208 gram.y:1216 gram.y:1317
+#: gram.y:1447 gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:313 lib/eventlog/eventlog.c:765
+#: lib/eventlog/eventlog.c:842 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:484
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:185
+#: logsrvd/iolog_writer.c:218 logsrvd/iolog_writer.c:228
+#: logsrvd/iolog_writer.c:257 logsrvd/iolog_writer.c:278
+#: logsrvd/iolog_writer.c:290 logsrvd/iolog_writer.c:300
+#: logsrvd/iolog_writer.c:310 logsrvd/iolog_writer.c:320
+#: logsrvd/iolog_writer.c:330 logsrvd/iolog_writer.c:342
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:1057 logsrvd/logsrvd.c:1120 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:650
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1743
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:216
+#: logsrvd/logsrvd_journal.c:217 logsrvd/logsrvd_journal.c:274
+#: logsrvd/logsrvd_journal.c:279 logsrvd/logsrvd_journal.c:439
+#: logsrvd/logsrvd_journal.c:441 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:216 logsrvd/logsrvd_local.c:278
+#: logsrvd/logsrvd_local.c:279 logsrvd/logsrvd_local.c:417
+#: logsrvd/logsrvd_local.c:468 logsrvd/logsrvd_local.c:469
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:475
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/logsrvd_relay.c:446
+#: logsrvd/logsrvd_relay.c:748 logsrvd/logsrvd_relay.c:855
+#: logsrvd/sendlog.c:256 logsrvd/sendlog.c:265 logsrvd/sendlog.c:297
+#: logsrvd/sendlog.c:303 logsrvd/sendlog.c:352 logsrvd/sendlog.c:630
+#: logsrvd/sendlog.c:1822 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/bsdauth.c:154 plugins/sudoers/auth/kerb5.c:122
+#: plugins/sudoers/auth/kerb5.c:150 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/auth/sia.c:61
+#: plugins/sudoers/canon_path.c:129 plugins/sudoers/canon_path.c:161
+#: plugins/sudoers/check_aliases.c:128 plugins/sudoers/check_util.c:56
+#: plugins/sudoers/check_util.c:84 plugins/sudoers/cvtsudoers.c:132
+#: plugins/sudoers/cvtsudoers.c:176 plugins/sudoers/cvtsudoers.c:193
+#: plugins/sudoers/cvtsudoers.c:204 plugins/sudoers/cvtsudoers.c:338
+#: plugins/sudoers/cvtsudoers.c:379 plugins/sudoers/cvtsudoers.c:399
+#: plugins/sudoers/cvtsudoers.c:545 plugins/sudoers/cvtsudoers.c:698
+#: plugins/sudoers/cvtsudoers.c:716 plugins/sudoers/cvtsudoers.c:891
+#: plugins/sudoers/cvtsudoers.c:899 plugins/sudoers/cvtsudoers.c:1395
+#: plugins/sudoers/cvtsudoers.c:1399 plugins/sudoers/cvtsudoers.c:1501
+#: plugins/sudoers/cvtsudoers_csv.c:183 plugins/sudoers/cvtsudoers_csv.c:247
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:152
+#: plugins/sudoers/cvtsudoers_ldif.c:195 plugins/sudoers/cvtsudoers_ldif.c:236
+#: plugins/sudoers/cvtsudoers_ldif.c:302 plugins/sudoers/cvtsudoers_ldif.c:378
+#: plugins/sudoers/cvtsudoers_ldif.c:432 plugins/sudoers/cvtsudoers_ldif.c:440
+#: plugins/sudoers/cvtsudoers_ldif.c:451 plugins/sudoers/cvtsudoers_ldif.c:458
+#: plugins/sudoers/cvtsudoers_ldif.c:470 plugins/sudoers/cvtsudoers_ldif.c:483
+#: plugins/sudoers/cvtsudoers_ldif.c:491 plugins/sudoers/cvtsudoers_ldif.c:638
+#: plugins/sudoers/cvtsudoers_merge.c:47 plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1158
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:212
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:694 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:294 plugins/sudoers/ldap_util.c:301
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:402
+#: plugins/sudoers/log_client.c:717 plugins/sudoers/log_client.c:739
+#: plugins/sudoers/log_client.c:744 plugins/sudoers/log_client.c:1426
+#: plugins/sudoers/log_client.c:1547 plugins/sudoers/log_client.c:1670
+#: plugins/sudoers/log_client.c:1993 plugins/sudoers/log_client.c:2052
+#: plugins/sudoers/logging.c:110 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:872 plugins/sudoers/lookup.c:338
+#: plugins/sudoers/lookup.c:355 plugins/sudoers/lookup.c:374
+#: plugins/sudoers/lookup.c:393 plugins/sudoers/lookup.c:410
+#: plugins/sudoers/lookup.c:433 plugins/sudoers/lookup.c:444
+#: plugins/sudoers/match_command.c:302 plugins/sudoers/match_command.c:574
+#: plugins/sudoers/match_command.c:641 plugins/sudoers/match_command.c:737
+#: plugins/sudoers/match_command.c:785 plugins/sudoers/match_digest.c:88
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:595
+#: plugins/sudoers/parse_ldif.c:625 plugins/sudoers/parse_ldif.c:650
+#: plugins/sudoers/parse_ldif.c:708 plugins/sudoers/parse_ldif.c:725
+#: plugins/sudoers/parse_ldif.c:753 plugins/sudoers/parse_ldif.c:760
+#: plugins/sudoers/policy.c:646 plugins/sudoers/policy.c:1061
+#: plugins/sudoers/prompt.c:94 plugins/sudoers/pwutil.c:219
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:368
+#: plugins/sudoers/pwutil.c:542 plugins/sudoers/pwutil.c:607
+#: plugins/sudoers/pwutil.c:679 plugins/sudoers/pwutil.c:877
+#: plugins/sudoers/pwutil.c:967 plugins/sudoers/pwutil.c:1015
+#: plugins/sudoers/pwutil.c:1076 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:145 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1307 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:256
+#: plugins/sudoers/testsudoers.c:265 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:164 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1095
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1320
+msgid "unable to allocate memory"
+msgstr "Es kann kein Speicher mehr alloziert werden"
+
+#: gram.y:624
+msgid "a digest requires a path name"
+msgstr "Eine Prüfsumme erfordert einen Pfadnamen"
+
+#: gram.y:646
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "Werte für »CWD« müssen mit »/«, »~« oder »*« beginnen"
+
+#: gram.y:652
+msgid "\"CWD\" path too long"
+msgstr "»CWD« (aktuelles Arbeitsverzeichnis) Pfad ist zu lang"
+
+#: gram.y:662
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "Werte für »CHROOT« müssen mit »/«, »~« oder »*« beginnen"
+
+#: gram.y:668
+msgid "\"CHROOT\" path too long"
+msgstr "»CHROOT« Pfad ist zu lang"
+
+#: gram.y:817
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "Syntaxfehler, das reservierte Wort »%s« wird als Aliasname verwendet"
+
+#: gram.y:840
+msgid "invalid notbefore value"
+msgstr "ungültiger Wert für »notbefore«"
+
+#: gram.y:849
+msgid "invalid notafter value"
+msgstr "ungültiger Wert für »notafter«"
+
+#: gram.y:859 plugins/sudoers/policy.c:390
+msgid "timeout value too large"
+msgstr "Wert für Timeout ist zu groß"
+
+#: gram.y:861 plugins/sudoers/policy.c:392
+msgid "invalid timeout value"
+msgstr "ungültiger Wert für Timeout"
+
+#: gram.y:982 plugins/sudoers/sudoers.c:1162
+msgid "command too long"
+msgstr "Der Befehl ist zu lang"
+
+#: gram.y:1016
+msgid "expected a fully-qualified path name"
+msgstr "Voll qualifizierter Pfad erwartet"
+
+#: gram.y:1261
+#, c-format
+msgid "%s:%d:%zu: %s\n"
+msgstr "%s:%d:%zu: %s\n"
+
+#: gram.y:1315
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Alias »%s« ist bereits definiert"
+
+#: gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:765 lib/eventlog/eventlog.c:838
+#: lib/eventlog/eventlog.c:841 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:483
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:232
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:174
+#: logsrvd/iolog_writer.c:184 logsrvd/iolog_writer.c:197
+#: logsrvd/iolog_writer.c:217 logsrvd/iolog_writer.c:227
+#: logsrvd/iolog_writer.c:246 logsrvd/iolog_writer.c:256
+#: logsrvd/iolog_writer.c:267 logsrvd/iolog_writer.c:277
+#: logsrvd/iolog_writer.c:289 logsrvd/iolog_writer.c:299
+#: logsrvd/iolog_writer.c:309 logsrvd/iolog_writer.c:319
+#: logsrvd/iolog_writer.c:329 logsrvd/iolog_writer.c:341
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:530
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:668
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:1131
+#: logsrvd/logsrvd.c:1446 logsrvd/logsrvd.c:1453 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:649
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1742
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:125
+#: logsrvd/logsrvd_journal.c:216 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:250 logsrvd/logsrvd_journal.c:258
+#: logsrvd/logsrvd_journal.c:287 logsrvd/logsrvd_journal.c:291
+#: logsrvd/logsrvd_journal.c:439 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:278 logsrvd/logsrvd_local.c:468
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:493
+#: logsrvd/logsrvd_queue.c:158 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/sendlog.c:256 logsrvd/sendlog.c:265
+#: logsrvd/sendlog.c:297 logsrvd/sendlog.c:303 logsrvd/sendlog.c:352
+#: logsrvd/sendlog.c:630 logsrvd/sendlog.c:1523 logsrvd/sendlog.c:1530
+#: logsrvd/sendlog.c:1753 logsrvd/sendlog.c:1822 logsrvd/tls_init.c:305
+#: logsrvd/tls_init.c:329 logsrvd/tls_init.c:340 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/pam.c:518 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/canon_path.c:129
+#: plugins/sudoers/canon_path.c:161 plugins/sudoers/check_aliases.c:128
+#: plugins/sudoers/check_util.c:56 plugins/sudoers/check_util.c:84
+#: plugins/sudoers/cvtsudoers.c:132 plugins/sudoers/cvtsudoers.c:175
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:203
+#: plugins/sudoers/cvtsudoers.c:337 plugins/sudoers/cvtsudoers.c:544
+#: plugins/sudoers/cvtsudoers.c:697 plugins/sudoers/cvtsudoers.c:715
+#: plugins/sudoers/cvtsudoers.c:891 plugins/sudoers/cvtsudoers.c:898
+#: plugins/sudoers/cvtsudoers.c:1395 plugins/sudoers/cvtsudoers.c:1399
+#: plugins/sudoers/cvtsudoers.c:1501 plugins/sudoers/cvtsudoers_csv.c:182
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:151 plugins/sudoers/cvtsudoers_ldif.c:194
+#: plugins/sudoers/cvtsudoers_ldif.c:235 plugins/sudoers/cvtsudoers_ldif.c:301
+#: plugins/sudoers/cvtsudoers_ldif.c:377 plugins/sudoers/cvtsudoers_ldif.c:431
+#: plugins/sudoers/cvtsudoers_ldif.c:439 plugins/sudoers/cvtsudoers_ldif.c:450
+#: plugins/sudoers/cvtsudoers_ldif.c:457 plugins/sudoers/cvtsudoers_ldif.c:469
+#: plugins/sudoers/cvtsudoers_ldif.c:482 plugins/sudoers/cvtsudoers_ldif.c:490
+#: plugins/sudoers/cvtsudoers_ldif.c:637 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51 plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1157
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:211
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:693 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:293 plugins/sudoers/ldap_util.c:300
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:228
+#: plugins/sudoers/log_client.c:250 plugins/sudoers/log_client.c:264
+#: plugins/sudoers/log_client.c:402 plugins/sudoers/log_client.c:717
+#: plugins/sudoers/log_client.c:739 plugins/sudoers/log_client.c:744
+#: plugins/sudoers/log_client.c:1426 plugins/sudoers/log_client.c:1547
+#: plugins/sudoers/log_client.c:1670 plugins/sudoers/log_client.c:1993
+#: plugins/sudoers/log_client.c:2052 plugins/sudoers/logging.c:110
+#: plugins/sudoers/logging.c:189 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:755 plugins/sudoers/logging.c:872
+#: plugins/sudoers/logging.c:925 plugins/sudoers/logging.c:932
+#: plugins/sudoers/lookup.c:337 plugins/sudoers/lookup.c:354
+#: plugins/sudoers/lookup.c:373 plugins/sudoers/lookup.c:392
+#: plugins/sudoers/lookup.c:409 plugins/sudoers/lookup.c:432
+#: plugins/sudoers/lookup.c:443 plugins/sudoers/match_command.c:301
+#: plugins/sudoers/match_command.c:573 plugins/sudoers/match_command.c:640
+#: plugins/sudoers/match_command.c:737 plugins/sudoers/match_command.c:784
+#: plugins/sudoers/match_digest.c:88 plugins/sudoers/parse_ldif.c:152
+#: plugins/sudoers/parse_ldif.c:183 plugins/sudoers/parse_ldif.c:252
+#: plugins/sudoers/parse_ldif.c:260 plugins/sudoers/parse_ldif.c:265
+#: plugins/sudoers/parse_ldif.c:341 plugins/sudoers/parse_ldif.c:352
+#: plugins/sudoers/parse_ldif.c:379 plugins/sudoers/parse_ldif.c:396
+#: plugins/sudoers/parse_ldif.c:408 plugins/sudoers/parse_ldif.c:412
+#: plugins/sudoers/parse_ldif.c:426 plugins/sudoers/parse_ldif.c:484
+#: plugins/sudoers/parse_ldif.c:595 plugins/sudoers/parse_ldif.c:624
+#: plugins/sudoers/parse_ldif.c:649 plugins/sudoers/parse_ldif.c:707
+#: plugins/sudoers/parse_ldif.c:724 plugins/sudoers/parse_ldif.c:752
+#: plugins/sudoers/parse_ldif.c:759 plugins/sudoers/policy.c:157
+#: plugins/sudoers/policy.c:166 plugins/sudoers/policy.c:175
+#: plugins/sudoers/policy.c:204 plugins/sudoers/policy.c:374
+#: plugins/sudoers/policy.c:390 plugins/sudoers/policy.c:392
+#: plugins/sudoers/policy.c:430 plugins/sudoers/policy.c:439
+#: plugins/sudoers/policy.c:448 plugins/sudoers/policy.c:457
+#: plugins/sudoers/policy.c:493 plugins/sudoers/policy.c:502
+#: plugins/sudoers/policy.c:511 plugins/sudoers/policy.c:520
+#: plugins/sudoers/policy.c:529 plugins/sudoers/policy.c:538
+#: plugins/sudoers/policy.c:547 plugins/sudoers/policy.c:646
+#: plugins/sudoers/policy.c:1061 plugins/sudoers/prompt.c:94
+#: plugins/sudoers/pwutil.c:219 plugins/sudoers/pwutil.c:290
+#: plugins/sudoers/pwutil.c:368 plugins/sudoers/pwutil.c:542
+#: plugins/sudoers/pwutil.c:607 plugins/sudoers/pwutil.c:679
+#: plugins/sudoers/pwutil.c:877 plugins/sudoers/pwutil.c:967
+#: plugins/sudoers/pwutil.c:1015 plugins/sudoers/pwutil.c:1076
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1306 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:255
+#: plugins/sudoers/testsudoers.c:264 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:163 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1094
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1309 toke.l:1320
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:304
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "Die Standardeingabe kann nicht dupliziert werden: %m"
+
+#: lib/eventlog/eventlog.c:346
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "%s kann nicht ausgeführt werden: %m"
+
+#: lib/eventlog/eventlog.c:394 plugins/sudoers/auth/aix_auth.c:199
+msgid "unable to fork"
+msgstr "Fehler bei fork()"
+
+#: lib/eventlog/eventlog.c:404 lib/eventlog/eventlog.c:471
+#, c-format
+msgid "unable to fork: %m"
+msgstr "Fehler bei fork(): %m"
+
+#: lib/eventlog/eventlog.c:461
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "Die Pipe kann nicht geöffnet werden: %m"
+
+#: lib/eventlog/eventlog.c:1000
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:1029
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (Befehl fortgesetzt) %s"
+
+#: lib/eventlog/parse_json.c:175
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "JSON_STRING erwartet, aber »%d« bekommen"
+
+#: lib/eventlog/parse_json.c:180
+msgid "JSON_ARRAY too large"
+msgstr "Das JSON_ARRAY ist zu groß"
+
+#: lib/eventlog/parse_json.c:506
+msgid "missing double quote in name"
+msgstr "Im Name fehlt das doppelte Anführungszeichen"
+
+#: lib/eventlog/parse_json.c:624
+msgid "missing JSON_OBJECT"
+msgstr "JSON_OBJECT fehlt"
+
+#: lib/eventlog/parse_json.c:628
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "JSON_OBJECT erwartet, aber »%d« bekommen"
+
+#: lib/eventlog/parse_json.c:762
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "json Stack erschöpft (maximal %u Frames)"
+
+#: lib/eventlog/parse_json.c:840
+msgid "objects must consist of name:value pairs"
+msgstr "Objekte müssen aus Name:Wert Paaren bestehen"
+
+#: lib/eventlog/parse_json.c:845 lib/eventlog/parse_json.c:876
+#: lib/eventlog/parse_json.c:920 lib/eventlog/parse_json.c:942
+#: lib/eventlog/parse_json.c:964 lib/eventlog/parse_json.c:986
+#: lib/eventlog/parse_json.c:1008
+msgid "missing separator between values"
+msgstr "Fehlender Separator zwischen den Werten"
+
+#: lib/eventlog/parse_json.c:860 lib/eventlog/parse_json.c:1034
+msgid "unmatched close brace"
+msgstr "unpassende schließende geschweifte Klammer"
+
+#: lib/eventlog/parse_json.c:871
+msgid "unexpected array"
+msgstr "unerwartetes Array"
+
+#: lib/eventlog/parse_json.c:891 lib/eventlog/parse_json.c:1037
+msgid "unmatched close bracket"
+msgstr "unpassende schließende eckige Klammer"
+
+#: lib/eventlog/parse_json.c:902
+msgid "unexpected string"
+msgstr "unerwartete Zeichenkette"
+
+#: lib/eventlog/parse_json.c:913
+msgid "missing colon after name"
+msgstr "fehlender Doppelpunkt nach dem Name"
+
+#: lib/eventlog/parse_json.c:934 lib/eventlog/parse_json.c:956
+msgid "unexpected boolean"
+msgstr "unerwarteter boolescher Wert (true/false)"
+
+#: lib/eventlog/parse_json.c:978
+msgid "unexpected null"
+msgstr "unerwartete »null«"
+
+#: lib/eventlog/parse_json.c:999
+msgid "unexpected number"
+msgstr "unerwartete Zahl"
+
+#: lib/eventlog/parse_json.c:1045
+msgid "parse error"
+msgstr "Syntax-Fehler"
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1290
+#: plugins/sudoers/sudoreplay.c:1291 plugins/sudoers/sudoreplay.c:1587
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr "ungültiger regulärer Ausdruck »%s«: %s"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: ungültige Protokolldatei"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: Das Feld für den Zeitstempel fehlt"
+
+#: lib/iolog/iolog_legacy.c:90
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: Zeitstempel %s: %s"
+
+#: lib/iolog/iolog_legacy.c:97
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: Das Benutzerfeld fehlt"
+
+#: lib/iolog/iolog_legacy.c:108
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: Das Feld für den »runas«-Benutzer fehlt"
+
+#: lib/iolog/iolog_legacy.c:119
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: Das Feld für die »runas«-Gruppe fehlt"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s existiert, aber ist kein Verzeichnis (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:124 lib/iolog/iolog_mkdtemp.c:80
+#: logsrvd/iolog_writer.c:795 plugins/sudoers/timestamp.c:218
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "Das Verzeichnis »%s« kann nicht erstellt werden"
+
+#: lib/iolog/iolog_mkdtemp.c:85 plugins/sudoers/visudo.c:769
+#: plugins/sudoers/visudo.c:803 plugins/sudoers/visudo.c:809
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "Ändern des Modus von %s auf 0%o gescheitert"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "Fehler beim Lesen der Zeitdateizeile: %s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "Ungültige Zeitdateizeile: %s"
+
+#: logsrvd/iolog_writer.c:65
+#, c-format
+msgid "%s: protocol error: NULL key"
+msgstr "%s: Protokollfehker: NULL-Schlüssel"
+
+#: logsrvd/iolog_writer.c:69
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s: Protokollfehker: falscher Typ für %s"
+
+#: logsrvd/iolog_writer.c:74 logsrvd/logsrvd_local.c:109
+#: logsrvd/logsrvd_local.c:123 logsrvd/logsrvd_local.c:131
+#: logsrvd/logsrvd_local.c:149
+#, c-format
+msgid "%s: protocol error: NULL value found in %s"
+msgstr "%s: Protokollfehker: Wert NULL gefunden in %s"
+
+#: logsrvd/iolog_writer.c:141 plugins/sudoers/logging.c:1024
+#: plugins/sudoers/policy.c:613
+msgid "unable to generate UUID"
+msgstr "UUID kann nicht generiert werden"
+
+#: logsrvd/iolog_writer.c:354 logsrvd/iolog_writer.c:359
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:369
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s: Protokollfehler: %s fehlt in der AcceptMessage"
+
+#: logsrvd/iolog_writer.c:430
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s: Session-ID kann nicht formatiert werden"
+
+#: logsrvd/iolog_writer.c:444 logsrvd/iolog_writer.c:458
+#: logsrvd/iolog_writer.c:472 logsrvd/iolog_writer.c:487
+#: logsrvd/iolog_writer.c:501 logsrvd/iolog_writer.c:515
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s: %s ist nicht gesetzt"
+
+# Kann die Escape-Sequenzen nicht auflösen?
+#: logsrvd/iolog_writer.c:551 logsrvd/iolog_writer.c:558
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr "Kann den iolog-Pfad nicht erweitern: %s"
+
+#: logsrvd/iolog_writer.c:576
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr "Kann den iolog-Pfad »%s« nicht erstellen"
+
+#: logsrvd/iolog_writer.c:606
+#, c-format
+msgid "invalid iofd %d"
+msgstr "Ungültiger I/O Dateideskriptor: %d"
+
+#: logsrvd/iolog_writer.c:626
+#, c-format
+msgid "error closing iofd %u: %s"
+msgstr "Fehler beim Schließen des I/O Dateideskriptors %u: %s"
+
+#: logsrvd/iolog_writer.c:647
+#, c-format
+msgid "error flushing iofd %u: %s"
+msgstr "Fehler beim Leeren des I/O Dateideskriptors %u: %s"
+
+#: logsrvd/iolog_writer.c:765
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "Ungültiges I/O log %s: »%s« wird verwendet, ist aber nicht vorhanden"
+
+#: logsrvd/iolog_writer.c:777 logsrvd/logsrvd_journal.c:391
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "%s; Der Wiederaufsetz-Punkt [%lld, %ld] kann nicht gefunden werden"
+
+#: logsrvd/iolog_writer.c:799 logsrvd/logsrvd_journal.c:434
+#: logsrvd/logsrvd_queue.c:115 logsrvd/tls_init.c:256
+#: plugins/sudoers/check.c:285 plugins/sudoers/cvtsudoers.c:758
+#: plugins/sudoers/cvtsudoers.c:780 plugins/sudoers/cvtsudoers.c:1461
+#: plugins/sudoers/cvtsudoers_csv.c:697 plugins/sudoers/cvtsudoers_json.c:902
+#: plugins/sudoers/cvtsudoers_ldif.c:711 plugins/sudoers/sudoers.c:1291
+#: plugins/sudoers/sudoers.c:1317 plugins/sudoers/sudoreplay.c:1497
+#: plugins/sudoers/timestamp.c:478 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:990
+#, c-format
+msgid "unable to open %s"
+msgstr "Die Datei »%s« kann nicht geöffnet werden"
+
+#: logsrvd/iolog_writer.c:811 logsrvd/logsrv_util.c:111
+#: logsrvd/logsrv_util.c:118 plugins/sudoers/sudoreplay.c:355
+#: plugins/sudoers/sudoreplay.c:361
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "Die Datei »%s/%s« kann nicht geöffnet werden"
+
+#: logsrvd/iolog_writer.c:824
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "Fehler beim Kopieren von »%s/%s« nach »%s/%s«: %s"
+
+#: logsrvd/iolog_writer.c:853 logsrvd/logsrvd_journal.c:198
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "Die Datei »%s« kann nicht in »%s« umbenannt werden"
+
+#: logsrvd/logsrv_util.c:153 logsrvd/logsrv_util.c:182
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s: Der Wiederaufsetz-Punkt [%lld, %ld] kann nicht gefunden werden"
+
+#: logsrvd/logsrv_util.c:165
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "Die I/O Logdatei %s/%s fehlt"
+
+#: logsrvd/logsrv_util.c:172
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s: kann nicht zur Position %zu springen"
+
+#: logsrvd/logsrvd.c:271 logsrvd/logsrvd_queue.c:135
+msgid "unable to connect to relay"
+msgstr "Verbindung zum Relay kann nicht aufgebaut werden"
+
+#: logsrvd/logsrvd.c:338 logsrvd/logsrvd_relay.c:847
+#, c-format
+msgid "server message too large: %zu"
+msgstr "Server-Nachricht ist zu groß: %zu"
+
+#: logsrvd/logsrvd.c:430 logsrvd/logsrvd.c:553 logsrvd/logsrvd.c:639
+#: logsrvd/logsrvd.c:881 logsrvd/logsrvd.c:895 logsrvd/logsrvd.c:1056
+#: logsrvd/logsrvd.c:1181 logsrvd/logsrvd.c:1354 logsrvd/logsrvd.c:1372
+#: logsrvd/logsrvd.c:1471 logsrvd/logsrvd.c:1596 logsrvd/logsrvd.c:1783
+#: logsrvd/logsrvd_journal.c:503 logsrvd/logsrvd_local.c:238
+#: logsrvd/logsrvd_queue.c:164 logsrvd/logsrvd_relay.c:172
+#: logsrvd/logsrvd_relay.c:249 logsrvd/logsrvd_relay.c:253
+#: logsrvd/logsrvd_relay.c:391 logsrvd/logsrvd_relay.c:583
+#: logsrvd/logsrvd_relay.c:747 logsrvd/logsrvd_relay.c:1137
+#: logsrvd/sendlog.c:1308 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:216 plugins/sudoers/audit.c:281
+#: plugins/sudoers/iolog.c:1041 plugins/sudoers/iolog.c:1175
+#: plugins/sudoers/iolog.c:1274 plugins/sudoers/log_client.c:121
+#: plugins/sudoers/log_client.c:343 plugins/sudoers/log_client.c:359
+#: plugins/sudoers/log_client.c:407 plugins/sudoers/log_client.c:613
+#: plugins/sudoers/log_client.c:620 plugins/sudoers/log_client.c:1114
+#: plugins/sudoers/log_client.c:1395 plugins/sudoers/log_client.c:1436
+#: plugins/sudoers/log_client.c:1444 plugins/sudoers/log_client.c:1603
+#: plugins/sudoers/log_client.c:1728 plugins/sudoers/log_client.c:2060
+#: plugins/sudoers/log_client.c:2068 plugins/sudoers/logging.c:148
+#: plugins/sudoers/logging.c:206 plugins/sudoers/sudoreplay.c:519
+#: plugins/sudoers/sudoreplay.c:566 plugins/sudoers/sudoreplay.c:808
+#: plugins/sudoers/sudoreplay.c:920 plugins/sudoers/sudoreplay.c:1011
+#: plugins/sudoers/sudoreplay.c:1026 plugins/sudoers/sudoreplay.c:1033
+#: plugins/sudoers/sudoreplay.c:1040 plugins/sudoers/sudoreplay.c:1047
+#: plugins/sudoers/sudoreplay.c:1054 plugins/sudoers/sudoreplay.c:1182
+msgid "unable to add event to queue"
+msgstr "Event kann nicht zur Warteschlange hinzugefügt werden"
+
+#: logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:491 logsrvd/logsrvd.c:523
+#: logsrvd/logsrvd.c:577 logsrvd/logsrvd.c:656 logsrvd/logsrvd.c:692
+#: logsrvd/logsrvd.c:728 logsrvd/logsrvd.c:764 logsrvd/logsrvd_relay.c:512
+#: logsrvd/logsrvd_relay.c:545
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr "Unerwarteter Status %d für %s"
+
+# XXX geht das besser?
+#: logsrvd/logsrvd.c:455 logsrvd/logsrvd.c:492 logsrvd/logsrvd.c:524
+#: logsrvd/logsrvd.c:578 logsrvd/logsrvd.c:657 logsrvd/logsrvd.c:693
+#: logsrvd/logsrvd.c:729 logsrvd/logsrvd.c:765 logsrvd/logsrvd_relay.c:514
+#: logsrvd/logsrvd_relay.c:547
+msgid "state machine error"
+msgstr "Fehler der State Machine"
+
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:462
+msgid "invalid AcceptMessage"
+msgstr "ungültige AcceptMessage"
+
+#: logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:499
+msgid "invalid RejectMessage"
+msgstr "ungültige RejectMessage"
+
+#: logsrvd/logsrvd.c:530 logsrvd/logsrvd.c:531
+msgid "invalid ExitMessage"
+msgstr "ungültige ExitMessage"
+
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:585
+msgid "invalid RestartMessage"
+msgstr "ungültige RestartMessage"
+
+#: logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:620
+msgid "invalid AlertMessage"
+msgstr "ungültige AlertMessage"
+
+#: logsrvd/logsrvd.c:661 logsrvd/logsrvd.c:697 logsrvd/logsrvd.c:733
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s: unerwarteter IoBuffer"
+
+#: logsrvd/logsrvd.c:662 logsrvd/logsrvd.c:698 logsrvd/logsrvd.c:734
+msgid "protocol error"
+msgstr "Protokollfehler"
+
+#: logsrvd/logsrvd.c:668 logsrvd/logsrvd.c:669
+msgid "invalid IoBuffer"
+msgstr "Ungültiger IoBuffer"
+
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:705
+msgid "invalid ChangeWindowSize"
+msgstr "ungültige ChangeWindowSize"
+
+#: logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:741
+msgid "invalid CommandSuspend"
+msgstr "ungültiges CommandSusped"
+
+#: logsrvd/logsrvd.c:790 logsrvd/logsrvd_journal.c:302
+#: logsrvd/logsrvd_relay.c:654 logsrvd/sendlog.c:1207
+#: plugins/sudoers/log_client.c:1593
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "Kann »%s« nicht auspacken, Größe %zu"
+
+#: logsrvd/logsrvd.c:835 logsrvd/logsrvd_journal.c:376
+#: logsrvd/logsrvd_relay.c:678
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "unerwarteter type_case Wert %d in »%s« aus »%s«"
+
+#: logsrvd/logsrvd.c:837
+msgid "unrecognized ClientMessage type"
+msgstr "unbekannter ClientMessage-Typ"
+
+#: logsrvd/logsrvd.c:927
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "Zeitablauf beim Senden zum Client %s"
+
+#: logsrvd/logsrvd.c:932 logsrvd/logsrvd_relay.c:919 logsrvd/sendlog.c:1413
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr "Schreib-Puffer fehlt für Client %s"
+
+#: logsrvd/logsrvd.c:1027
+#, c-format
+msgid "timed out reading from client %s"
+msgstr "Zeitablauf beim Lesen vom Client %s"
+
+#: logsrvd/logsrvd.c:1068 logsrvd/logsrvd_relay.c:782
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr "Dateiende (EOF) von %s ohne korrekten TLS-Abscluß"
+
+#: logsrvd/logsrvd.c:1112 logsrvd/logsrvd_relay.c:205 logsrvd/sendlog.c:336
+#: plugins/sudoers/log_client.c:723
+#, c-format
+msgid "client message too large: %zu"
+msgstr "Client-Nachricht ist zu groß: %zu"
+
+#: logsrvd/logsrvd.c:1113 logsrvd/logsrvd_journal.c:259
+#: logsrvd/logsrvd_journal.c:260
+msgid "client message too large"
+msgstr "Client-Nachricht ist zu groß"
+
+#: logsrvd/logsrvd.c:1131 logsrvd/logsrvd.c:1132
+msgid "invalid ClientMessage"
+msgstr "ungültige ClientMessage"
+
+#: logsrvd/logsrvd.c:1432
+msgid "unable to get remote IP addr"
+msgstr "Kann die entfernte IP-Adresse nicht finden"
+
+#: logsrvd/logsrvd.c:1463 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:281
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "Kann die User-Daten nicht an das SSL-Objekt anhängen: %s"
+
+#: logsrvd/logsrvd.c:1646 logsrvd/logsrvd.c:2007
+msgid "unable to setup listen socket"
+msgstr "Konnte keinen Socket zum »Lauschen« einrichten"
+
+#: logsrvd/logsrvd.c:1766
+#, c-format
+msgid "unexpected signal %d"
+msgstr "unerwartete Signal %d"
+
+#: logsrvd/logsrvd.c:1909
+msgid "sudo log server"
+msgstr "sudo Log-Server"
+
+#: logsrvd/logsrvd.c:1911 logsrvd/sendlog.c:126
+msgid "Options:"
+msgstr "Optionen:"
+
+#: logsrvd/logsrvd.c:1913
+msgid "path to configuration file"
+msgstr "Pfad zur Konfigurationsdatei"
+
+#: logsrvd/logsrvd.c:1915 logsrvd/sendlog.c:128
+msgid "display help message and exit"
+msgstr "Hilfe anzeigen und beenden"
+
+#: logsrvd/logsrvd.c:1917
+msgid "do not fork, run in the foreground"
+msgstr "Nicht zum Hintergrundprozess werden, sondern im Vordergrund laufen"
+
+#: logsrvd/logsrvd.c:1919
+msgid "percent chance connections will drop"
+msgstr "Wahrscheinlichkeit in Prozent für Verbindungsabbruch"
+
+#: logsrvd/logsrvd.c:1921 logsrvd/sendlog.c:158
+msgid "display version information and exit"
+msgstr "Versionsinformation anzeigen und beenden"
+
+#: logsrvd/logsrvd.c:1971 logsrvd/sendlog.c:1722
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "Protobuf-C Version 1.3 oder höher ist notwendig"
+
+#: logsrvd/logsrvd.c:1987
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "ungültiger Wert für »random drop«: %s"
+
+#: logsrvd/logsrvd.c:1990 logsrvd/sendlog.c:1776
+#: plugins/sudoers/cvtsudoers.c:250 plugins/sudoers/sudoreplay.c:294
+#: plugins/sudoers/visudo.c:181
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s Version %s\n"
+
+#: logsrvd/logsrvd_conf.c:422 plugins/sudoers/check.c:69
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/sudoers.c:419 plugins/sudoers/sudoers.c:929
+#: plugins/sudoers/sudoers.c:1034 plugins/sudoers/sudoers.c:1424
+#: plugins/sudoers/testsudoers.c:169 plugins/sudoers/testsudoers.c:285
+#: plugins/sudoers/testsudoers.c:459
+#, c-format
+msgid "unknown user %s"
+msgstr "Unbekannter Benutzer %s"
+
+#: logsrvd/logsrvd_conf.c:439 plugins/sudoers/iolog.c:148
+#: plugins/sudoers/sudoers.c:425 plugins/sudoers/sudoers.c:1458
+#: plugins/sudoers/testsudoers.c:483
+#, c-format
+msgid "unknown group %s"
+msgstr "Unbekannte Gruppe %s"
+
+#: logsrvd/logsrvd_conf.c:457
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr "Iolog mode %s kann nicht geparst werden"
+
+#: logsrvd/logsrvd_conf.c:474 logsrvd/logsrvd_conf.c:1243
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "Ungültiger Wert für %s: %s"
+
+#: logsrvd/logsrvd_conf.c:527
+msgid "TLS not supported"
+msgstr "TLS ist nicht unterstützt"
+
+#: logsrvd/logsrvd_conf.c:549
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:622 logsrvd/logsrvd_conf.c:1032
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s: ist kein voll qualifizierter Pfad"
+
+#: logsrvd/logsrvd_conf.c:951 logsrvd/logsrvd_conf.c:967
+#: logsrvd/logsrvd_conf.c:1676
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "Unbekannte Syslog-Facility %s"
+
+#: logsrvd/logsrvd_conf.c:983 logsrvd/logsrvd_conf.c:999
+#: logsrvd/logsrvd_conf.c:1015 logsrvd/logsrvd_conf.c:1680
+#: logsrvd/logsrvd_conf.c:1684 logsrvd/logsrvd_conf.c:1688
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "Unbekannte Syslog-Priorität %s"
+
+#: logsrvd/logsrvd_conf.c:1197
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s: %d »[« ohne schliessende Klammer »]«: %s"
+
+# XXX Geht das besser?
+#: logsrvd/logsrvd_conf.c:1203
+#, c-format
+msgid "%s:%d garbage after ']': %s"
+msgstr "%s: %d unsinnige Zeichen nach »]«: %s"
+
+#: logsrvd/logsrvd_conf.c:1215
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s/%d Ungültiger Konfigurations-Abschnitt: %s"
+
+#: logsrvd/logsrvd_conf.c:1223
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s/%d Ungültige Konfigurationszeile: %s"
+
+#: logsrvd/logsrvd_conf.c:1229
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d erwartetder Section Name: %s"
+
+#: logsrvd/logsrvd_conf.c:1251
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] ungültiger Schlüssel: %s"
+
+#: logsrvd/logsrvd_conf.c:1281 plugins/sudoers/cvtsudoers.c:273
+#: plugins/sudoers/logging.c:1076
+#, c-format
+msgid "unable to open log file %s"
+msgstr "Die Protokolldatei kann nicht geöffnet werden %s"
+
+#: logsrvd/logsrvd_conf.c:1763
+msgid "unable to initialize server TLS context"
+msgstr "Server-SSL-Kontext kann nicht initialisiert werden"
+
+#: logsrvd/logsrvd_conf.c:1783
+msgid "unable to initialize relay TLS context"
+msgstr "SSL-Kontext kann nicht initialisiert werden"
+
+#: logsrvd/logsrvd_journal.c:149 logsrvd/logsrvd_journal.c:430
+#: logsrvd/logsrvd_journal.c:435
+msgid "unable to create journal file"
+msgstr "Kann die Journal-Datei nicht anlegen"
+
+#: logsrvd/logsrvd_journal.c:153 logsrvd/logsrvd_queue.c:109
+#: plugins/sudoers/visudo.c:1046
+#, c-format
+msgid "unable to lock %s"
+msgstr "Die Datei »%s« kann nicht gesperrt werden"
+
+#: logsrvd/logsrvd_journal.c:156
+msgid "unable to lock journal file"
+msgstr "Die Journal-Datei »%s« kann nicht gesperrt werden"
+
+#: logsrvd/logsrvd_journal.c:164
+msgid "unable to open journal file"
+msgstr "Die Journal-Datei kann nicht geöffnet werden"
+
+#: logsrvd/logsrvd_journal.c:185 logsrvd/logsrvd_journal.c:466
+#: logsrvd/logsrvd_journal.c:471
+msgid "unable to write journal file"
+msgstr "In die Logdatei kann nicht geschrieben werden"
+
+#: logsrvd/logsrvd_journal.c:193 logsrvd/logsrvd_journal.c:200
+msgid "unable to rename journal file"
+msgstr "Die Journal-Datei kann nicht geöffnet werden"
+
+#: logsrvd/logsrvd_journal.c:247 logsrvd/logsrvd_journal.c:248
+#: logsrvd/logsrvd_journal.c:288 logsrvd/logsrvd_journal.c:289
+msgid "unexpected EOF reading journal file"
+msgstr "unerwartetes Dateiende beim Lesen der Journal-Datei"
+
+#: logsrvd/logsrvd_journal.c:251 logsrvd/logsrvd_journal.c:252
+#: logsrvd/logsrvd_journal.c:292 logsrvd/logsrvd_journal.c:293
+msgid "error reading journal file"
+msgstr "Fehler beim Lesen der Journal-Datei"
+
+#: logsrvd/logsrvd_journal.c:304 logsrvd/logsrvd_journal.c:390
+msgid "invalid journal file, unable to restart"
+msgstr "Ungültige Journal-Datei - kann nicht neu starten"
+
+#: logsrvd/logsrvd_journal.c:449
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "Kann nicht zu [%lld, %ld] in der Journaldatei »%s« springen"
+
+#: logsrvd/logsrvd_local.c:166
+#, c-format
+msgid "unexpected value_case %d in %s from %s"
+msgstr "unerwarteter value_case Wert %d in »%s« aus »%s«"
+
+#: logsrvd/logsrvd_local.c:194
+msgid "error parsing AcceptMessage"
+msgstr "Fehler beim Parsen der AcceptMessage"
+
+#: logsrvd/logsrvd_local.c:205
+msgid "error creating I/O log"
+msgstr "Fehler beim Erstellen des Ein-/Ausgabe-Protokolls"
+
+#: logsrvd/logsrvd_local.c:228
+msgid "error logging accept event"
+msgstr "Fehler beim Protokolliereb des Accept-Events"
+
+#: logsrvd/logsrvd_local.c:267
+msgid "error parsing RejectMessage"
+msgstr "Fehler beim Parsen der RejectMessage"
+
+#: logsrvd/logsrvd_local.c:291
+msgid "error logging reject event"
+msgstr "Fehler beim Protokollieren des Reject-Events"
+
+#: logsrvd/logsrvd_local.c:427 logsrvd/logsrvd_local.c:437
+msgid "error logging exit event"
+msgstr "Fehler beim Protokollieren des Exit-Events"
+
+#: logsrvd/logsrvd_local.c:494 logsrvd/logsrvd_local.c:495
+msgid "log is already complete, cannot be restarted"
+msgstr "Das Log ist bereits abgeschlossen, kann nicht neu gestartet werden"
+
+#: logsrvd/logsrvd_local.c:525
+msgid "unable to restart log"
+msgstr "Das Log konnte nicht wieder begonnen werden"
+
+#: logsrvd/logsrvd_local.c:541
+msgid "error parsing AlertMessage"
+msgstr "Fehler beim Parsen der AlertMessage"
+
+#: logsrvd/logsrvd_local.c:551
+msgid "error logging alert event"
+msgstr "Fehler beim Protokollieren des Alert-Events"
+
+#: logsrvd/logsrvd_local.c:587 logsrvd/logsrvd_local.c:650
+#: logsrvd/logsrvd_local.c:685
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr "Der Zeitstempel kann nicht formatiert werden, Länge %d"
+
+#: logsrvd/logsrvd_local.c:601 logsrvd/logsrvd_local.c:609
+#: logsrvd/logsrvd_local.c:657 logsrvd/logsrvd_local.c:692
+#: plugins/sudoers/sudoreplay.c:344 toke.l:981 toke.l:984
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: logsrvd/logsrvd_local.c:620
+msgid "randomly dropping connection"
+msgstr "Zufällig die Verbindung beenden"
+
+#: logsrvd/logsrvd_local.c:632
+msgid "error writing IoBuffer"
+msgstr "Fehler beim Schreiben des IoBuffer"
+
+#: logsrvd/logsrvd_local.c:667
+msgid "error writing ChangeWindowSize"
+msgstr "Fehler beim Schreiben der ChangeWindowSize"
+
+#: logsrvd/logsrvd_local.c:702
+msgid "error writing CommandSuspend"
+msgstr "Fehler beim Schreiben des CommandSusped"
+
+#: logsrvd/logsrvd_relay.c:437
+msgid "TLS handshake with relay host failed"
+msgstr "TLS-Handshake mit dem Relay-Host fehlgeschlagen"
+
+#: logsrvd/logsrvd_relay.c:465
+msgid "unable to connect to relay host"
+msgstr "Verbindung zum Relay-Host kann nicht aufgebaut werden"
+
+#: logsrvd/logsrvd_relay.c:520
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s: ungültiges ServerHello, fehlende server_id"
+
+#: logsrvd/logsrvd_relay.c:522 logsrvd/sendlog.c:1111
+#: plugins/sudoers/log_client.c:1479
+msgid "invalid ServerHello"
+msgstr "ungültiges ServerHello"
+
+#: logsrvd/logsrvd_relay.c:681
+msgid "unrecognized ServerMessage type"
+msgstr "unbekannter ServerMessage-Typ"
+
+#: logsrvd/logsrvd_relay.c:710
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr "Zeitablauf beim Lesen vom Relay-Server »%s« (%s)"
+
+#: logsrvd/logsrvd_relay.c:712
+msgid "timeout reading from relay"
+msgstr "Zeitablauf beim Lesen vom Relay-Server"
+
+#: logsrvd/logsrvd_relay.c:767
+msgid "relay host name does not match certificate"
+msgstr "Der Name des Relay-Hosts passt nicht zum Zertifikat"
+
+#: logsrvd/logsrvd_relay.c:773 logsrvd/logsrvd_relay.c:787
+#: logsrvd/logsrvd_relay.c:794
+msgid "error reading from relay"
+msgstr "Fehler beim Lesen vom Relay-Host"
+
+#: logsrvd/logsrvd_relay.c:815
+msgid "unable to read from relay"
+msgstr "Vom Relay-Server kann nicht gelesen werden"
+
+#: logsrvd/logsrvd_relay.c:830 logsrvd/logsrvd_relay.c:949
+msgid "relay server closed connection"
+msgstr "Der Relay-Server hat die Verbindung geschlossen"
+
+#: logsrvd/logsrvd_relay.c:848
+msgid "server message too large"
+msgstr "Server-Nachricht ist zu groß"
+
+#: logsrvd/logsrvd_relay.c:912
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr "Zeitablauf beim Senden an den Relay-Server »%s« (%s)"
+
+#: logsrvd/logsrvd_relay.c:914
+msgid "timeout writing to relay"
+msgstr "Zeitablauf beim Senden an den Relay-Server"
+
+#: logsrvd/logsrvd_relay.c:968 logsrvd/logsrvd_relay.c:975
+#: logsrvd/logsrvd_relay.c:987
+msgid "error writing to relay"
+msgstr "Fehler beim Schreiben des zum Relay-Server"
+
+#: logsrvd/sendlog.c:124
+msgid "send sudo I/O log to remote server"
+msgstr "sende sudo I/O-Log zu einem entfernten Server"
+
+#: logsrvd/sendlog.c:130
+msgid "only send an accept event (no I/O)"
+msgstr "Nur einen Accept-Event senden (kein I/O)"
+
+#: logsrvd/sendlog.c:133
+msgid "certificate bundle file to verify server's cert against"
+msgstr "Zertifikatsbündel-Datei zur Verifikation des Server-Zertifikats"
+
+#: logsrvd/sendlog.c:135
+msgid "certificate file for TLS handshake"
+msgstr "Zertifikatsdatei für TLS-Handshake"
+
+#: logsrvd/sendlog.c:138
+msgid "host to send logs to"
+msgstr "Rechner an den die Logs gesendet werden"
+
+#: logsrvd/sendlog.c:140
+msgid "remote ID of I/O log to be resumed"
+msgstr "Entfernte ID des I/O-Logs zum Wiederaufnehmen"
+
+#: logsrvd/sendlog.c:143
+msgid "private key file"
+msgstr "Private Schlüsseldatei"
+
+#: logsrvd/sendlog.c:145
+msgid "do not verify server certificate"
+msgstr "Serverzertifikat nicht überprüfen"
+
+#: logsrvd/sendlog.c:148
+msgid "port to use when connecting to host"
+msgstr "Portnummer für die Verbindung zum Host"
+
+#: logsrvd/sendlog.c:150
+msgid "restart previous I/O log transfer"
+msgstr "Restarte die vorhergehende I/O-Log Übertragung"
+
+#: logsrvd/sendlog.c:152
+msgid "reject the command with the given reason"
+msgstr "Weise das Kommando mit dem angegebenen Grund zurück"
+
+#: logsrvd/sendlog.c:154
+msgid "stop transfer after reaching this time"
+msgstr "Beende den Transfer nach Erreichen dieser Zeit"
+
+#: logsrvd/sendlog.c:156
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "Teste den Audit-Server durch senden ausgewählter I/O-Logs n-Mal parallel"
+
+#: logsrvd/sendlog.c:181 plugins/sudoers/log_client.c:453
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "Fehler beim Lookup %s:%s: %s"
+
+#: logsrvd/sendlog.c:219
+msgid "unable to get server IP addr"
+msgstr "Kann die Server IP-Adresse nicht finden"
+
+#: logsrvd/sendlog.c:314 plugins/sudoers/sudoreplay.c:868
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "Fehler beim Lesen %s/%s: %s"
+
+#: logsrvd/sendlog.c:1035 plugins/sudoers/iolog.c:959
+#: plugins/sudoers/iolog.c:1034
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "unerwarteter I/O Event %d"
+
+#: logsrvd/sendlog.c:1088 logsrvd/sendlog.c:1105 logsrvd/sendlog.c:1139
+#: plugins/sudoers/log_client.c:1129 plugins/sudoers/log_client.c:1405
+#: plugins/sudoers/log_client.c:1473 plugins/sudoers/log_client.c:1512
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: unerwarteter Status %d"
+
+#: logsrvd/sendlog.c:1175 plugins/sudoers/log_client.c:1561
+#, c-format
+msgid "error message received from server: %s"
+msgstr "Fehler beim Empfangen der Nachricht vom Server: %s"
+
+#: logsrvd/sendlog.c:1188 plugins/sudoers/log_client.c:1574
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "Abbruch-Nachricht vom Server empfangen: %s"
+
+#: logsrvd/sendlog.c:1247 plugins/sudoers/log_client.c:1624
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s: unerwarteter type_case Wert %d"
+
+#: logsrvd/sendlog.c:1276
+msgid "timeout reading from server"
+msgstr "Zeitablauf beim Lesen vom Server"
+
+#: logsrvd/sendlog.c:1327 plugins/sudoers/log_client.c:1747
+msgid "host name does not match certificate"
+msgstr "Der Hostname passt nicht zum Zertifikat"
+
+#: logsrvd/sendlog.c:1361
+msgid "premature EOF"
+msgstr "unerwartetes Datei-Ende"
+
+#: logsrvd/sendlog.c:1374 plugins/sudoers/log_client.c:1795
+#, c-format
+msgid "server message too large: %u"
+msgstr "Server-Nachricht ist zu groß: %u"
+
+#: logsrvd/sendlog.c:1430
+msgid "timeout writing to server"
+msgstr "Zeitablauf beim Senden an den Server"
+
+#: logsrvd/sendlog.c:1800
+msgid "both restart point and iolog ID must be specified"
+msgstr "Sowohl Restart-Punkt als auch die I/O-Log ID sind notwendig"
+
+#: logsrvd/sendlog.c:1804
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "Ein Restart-Punkt kann nicht angegeben werden, wenn keine Ein/Ausgabe gesendet ist."
+
+#: logsrvd/sendlog.c:1880
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "Vorzeitig beendet mit Status %d"
+
+#: logsrvd/sendlog.c:1881
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "Abgelaufene Zeit zum Server gesendet [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1883
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "Commit Punkt vom Server empfangen [%lld, %ld]"
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:315
+msgid "TLS handshake timeout occurred"
+msgstr "Timeout beim TLS-Handshake erreicht"
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:337 plugins/sudoers/log_client.c:353
+msgid "unable to set event"
+msgstr "Konnte den Event nicht setzen"
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "TLS-Kommunikation fehlgeschlagen: %s"
+
+#: logsrvd/tls_client.c:196
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "Kann kein SSL-Objekt anlegen: %s"
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "Kann den Socket nicht an das SSL-Objekt anhängen: %s"
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr "SSL-Kontext kann nicht initialisiert werden"
+
+#: logsrvd/tls_init.c:138 logsrvd/tls_init.c:146
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "Die TLS 1.2 Cyphersuite kann nicht auf »%s« gesetzt werden: %s"
+
+#: logsrvd/tls_init.c:166 logsrvd/tls_init.c:174
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "Die TLS 1.3 Cyphersuite kann nicht auf »%s« gesetzt werden: %s"
+
+#: logsrvd/tls_init.c:206 logsrvd/tls_init.c:227
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "Kann die Diffie-Hellman Parameter nicht setzen: %s"
+
+#: logsrvd/tls_init.c:283
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "SSL-Kontext kann nicht erzeugt werden: %s"
+
+#: logsrvd/tls_init.c:290
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "Kann die minimale Protokollversion nicht auf TLS 1.2 setzen: %s"
+
+#: plugins/sudoers/audit.c:272 plugins/sudoers/audit.c:452
+#: plugins/sudoers/log_client.c:962 plugins/sudoers/log_client.c:1011
+#: plugins/sudoers/log_client.c:1060 plugins/sudoers/log_client.c:1185
+#: plugins/sudoers/logging.c:614 plugins/sudoers/logging.c:732
+#: plugins/sudoers/logging.c:859 plugins/sudoers/logging.c:1031
+#: plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr "Die aktuelle Zeit kann nicht ausgelesen werden"
+
+#: plugins/sudoers/auth/aix_auth.c:282
+#, c-format
+msgid "unable to change password for %s"
+msgstr "Das Passwort für %s« kann nicht geändert werden"
+
+#: plugins/sudoers/auth/bsdauth.c:78
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "Die Anmeldeklasse des Benutzers »%s« kann nicht gelesen werden"
+
+#: plugins/sudoers/auth/bsdauth.c:85
+msgid "invalid authentication type"
+msgstr "Ungültiger Authentifizierungstyp"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to begin BSD authentication"
+msgstr "Die BSD-Authentifizierung kann nicht begonnen werden"
+
+#: plugins/sudoers/auth/bsdauth.c:97
+msgid "unable to initialize BSD authentication"
+msgstr "Die BSD-Authentifizierung kann nicht begonnen werden"
+
+#: plugins/sudoers/auth/bsdauth.c:191
+msgid "your account has expired"
+msgstr "Ihr Account ist abgelaufen"
+
+#: plugins/sudoers/auth/bsdauth.c:193
+msgid "approval failed"
+msgstr "Genehmigung fehlgeschlagen"
+
+#: plugins/sudoers/auth/fwtk.c:62
+msgid "unable to read fwtk config"
+msgstr "Die fwtk-Konfiguration kann nicht gelesen werden"
+
+#: plugins/sudoers/auth/fwtk.c:67
+msgid "unable to connect to authentication server"
+msgstr "Verbindung zum Authentifizierungsserver kann nicht aufgebaut werden"
+
+#: plugins/sudoers/auth/fwtk.c:73 plugins/sudoers/auth/fwtk.c:99
+#: plugins/sudoers/auth/fwtk.c:131
+msgid "lost connection to authentication server"
+msgstr "Verbindung zum Authentisierungsserver verloren"
+
+#: plugins/sudoers/auth/fwtk.c:77
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"Fehler des Authentifizierungsservers:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:116
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: Principal kann nicht in eine Zeichenkette umgewandelt werden (»%s«): %s"
+
+#: plugins/sudoers/auth/kerb5.c:166
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: »%s« kann nicht ausgewertet werden: %s"
+
+# XXX check source?
+#: plugins/sudoers/auth/kerb5.c:175
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: Anmeldedaten-Zwischenspeicher kann nicht aufgelöst werden: %s"
+
+#: plugins/sudoers/auth/kerb5.c:226
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: Optionen können nicht zugewiesen werden: %s"
+
+#: plugins/sudoers/auth/kerb5.c:241
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: Anmeldedaten können nicht bekommen werden: %s"
+
+#: plugins/sudoers/auth/kerb5.c:254
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: Anmeldedaten-Zwischenspeicher kann nicht initialisiert werden: %s"
+
+#: plugins/sudoers/auth/kerb5.c:257
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: Anmeldedaten können nicht im Zwischenspeicher abgelegt werden: %s"
+
+#: plugins/sudoers/auth/kerb5.c:322
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: Rechner-Principal kann nicht bekommen werden: %s"
+
+#: plugins/sudoers/auth/kerb5.c:336
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: TGT kann nicht verifiziert werden! Möglicher Angriff!: %s"
+
+#: plugins/sudoers/auth/pam.c:233
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "PAM kann nicht initialisiert werden: %s"
+
+#: plugins/sudoers/auth/pam.c:349
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Fehler bei der PAM-Authentifizierung: %s"
+
+#: plugins/sudoers/auth/pam.c:369
+msgid "account validation failure, is your account locked?"
+msgstr "Fehler bei der Validierung des Kontos, ist das Konto gesperrt?"
+
+#: plugins/sudoers/auth/pam.c:380
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Konto oder Passwort ist abgelaufen, bitte Passwort zurücksetzen und nochmal probieren"
+
+#: plugins/sudoers/auth/pam.c:387
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "Das abgelaufene Passwort kann nicht geändert werden: %s«"
+
+#: plugins/sudoers/auth/pam.c:398
+msgid "Password expired, contact your system administrator"
+msgstr "Das Passwort ist abgelaufen, bitte wenden Sie sich an den Systemadministrator"
+
+#: plugins/sudoers/auth/pam.c:403
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Das Konto ist abgelaufen oder in der PAM-Konfiguration fehlt der »account«-Abschnitt für sudo. Bitte wenden Sie sich an den Systemadministrator"
+
+#: plugins/sudoers/auth/pam.c:411 plugins/sudoers/auth/pam.c:416
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "Fehler beim PAM-Account-Management: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:100 plugins/sudoers/visudo.c:266
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "Der Benutzer existiert in der %s-Datenbank nicht"
+
+#: plugins/sudoers/auth/securid5.c:76
+msgid "failed to initialise the ACE API library"
+msgstr "Die ACE-API-Bibliothek konnte nicht initialisiert werden"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "unable to contact the SecurID server"
+msgstr "SecurID-Server kann nicht erreicht werden"
+
+#: plugins/sudoers/auth/securid5.c:117
+msgid "User ID locked for SecurID Authentication"
+msgstr "Benutzer-ID ist für SecurID-Authentifizierung gesperrt"
+
+#: plugins/sudoers/auth/securid5.c:121 plugins/sudoers/auth/securid5.c:174
+msgid "invalid username length for SecurID"
+msgstr "Ungültige Länge des Benutzernamens für SecurID"
+
+#: plugins/sudoers/auth/securid5.c:125 plugins/sudoers/auth/securid5.c:179
+msgid "invalid Authentication Handle for SecurID"
+msgstr "Ungültiges Authentifizierungs-Handle für SecurID"
+
+#: plugins/sudoers/auth/securid5.c:129
+msgid "SecurID communication failed"
+msgstr "SecurID-Kommunikation fehlgeschlagen"
+
+#: plugins/sudoers/auth/securid5.c:133 plugins/sudoers/auth/securid5.c:222
+msgid "unknown SecurID error"
+msgstr "Unbekannter SecurID-Fehler"
+
+#: plugins/sudoers/auth/securid5.c:169
+msgid "invalid passcode length for SecurID"
+msgstr "Ungültige Länge des Passcodes für SecurID"
+
+#: plugins/sudoers/auth/sia.c:72 plugins/sudoers/auth/sia.c:130
+msgid "unable to initialize SIA session"
+msgstr "Die SIA-Sitzung kann nicht initialisiert werden"
+
+#: plugins/sudoers/auth/sudo_auth.c:141
+msgid "invalid authentication methods"
+msgstr "Ungültige Authentifizierungsmethoden"
+
+#: plugins/sudoers/auth/sudo_auth.c:143
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Ungültige Authentifizierungsmethoden sind in sudo einkompiliert! Standalone- und Nicht-Standalone-Authentifizierung können nicht zusammen verwendet werden."
+
+#: plugins/sudoers/auth/sudo_auth.c:296 plugins/sudoers/auth/sudo_auth.c:359
+msgid "no authentication methods"
+msgstr "Keine Authentifizierungsmethoden"
+
+#: plugins/sudoers/auth/sudo_auth.c:298
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Es sind keine Authentifizierungsmethoden in sudo einkompiliert! Wenn Sie die Authentifizierung wirklich abschalten wollen, verwenden Sie bitte die configure-Option »--disable-authentication«."
+
+#: plugins/sudoers/auth/sudo_auth.c:361
+msgid "Unable to initialize authentication methods."
+msgstr "Die Authentifizierungsmethoden können nicht initialisiert werden."
+
+#: plugins/sudoers/auth/sudo_auth.c:551
+msgid "Authentication methods:"
+msgstr "Authentifizierungsmethoden:"
+
+#: plugins/sudoers/bsm_audit.c:122 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "Der Audit-Zustand kann nicht bestimmt werden"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:278
+msgid "unable to commit audit record"
+msgstr "Audit-Satz kann nicht auf Platte geschrieben werden"
+
+#: plugins/sudoers/check.c:63 plugins/sudoers/check.c:74
+#: plugins/sudoers/lookup.c:79 plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "Unbekannte Benutzer-ID %u"
+
+#: plugins/sudoers/check.c:277
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "Fehler beim Lesen der Belehrungsdatei %s"
+
+#: plugins/sudoers/check.c:280
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "Ignoriere Belehrungsdatei %s: es ist keine reguläre Datei"
+
+#: plugins/sudoers/check.c:293
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Wir gehen davon aus, dass der lokale Systemadministrator Ihnen die\n"
+"Regeln erklärt hat. Normalerweise läuft es auf drei Regeln hinaus:\n"
+"\n"
+" #1) Respektieren Sie die Privatsphäre anderer.\n"
+" #2) Denken Sie nach, bevor Sie tippen.\n"
+" #3) Mit großer Macht kommt große Verantwortung.\n"
+"\n"
+
+#: plugins/sudoers/check.c:301
+msgid ""
+"For security reasons, the password you type will not be visible.\n"
+"\n"
+msgstr ""
+"Das eingegebene Passwort ist aus Sicherheitsgründen nicht sichtbar.\n"
+"\n"
+
+#: plugins/sudoers/check_aliases.c:93
+#, c-format
+msgid "cycle in %s \"%s\""
+msgstr "Zyklus in %s »%s«"
+
+#: plugins/sudoers/check_aliases.c:96
+#, c-format
+msgid "%s \"%s\" referenced but not defined"
+msgstr "%s »%s« wird verwendet, ist aber nicht definiert"
+
+#: plugins/sudoers/cvtsudoers.c:211
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "Schrittgröße: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:231
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "Start der Folge: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:242
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "Auffüllen der Folge: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:252 plugins/sudoers/visudo.c:183
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s-Grammatik Version %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:282 plugins/sudoers/testsudoers.c:162
+#, c-format
+msgid "unsupported input format %s"
+msgstr "Nicht unterstütztes Eingabeformat %s"
+
+#: plugins/sudoers/cvtsudoers.c:300
+#, c-format
+msgid "unsupported output format %s"
+msgstr "Nicht unterstütztes Ausgabeformat %s"
+
+#: plugins/sudoers/cvtsudoers.c:392
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: Eingabe- und Ausgabedatei müssen unterschiedlich sein"
+
+#: plugins/sudoers/cvtsudoers.c:406 plugins/sudoers/sudoers.c:151
+#: plugins/sudoers/sudoers.c:209 plugins/sudoers/testsudoers.c:315
+#: plugins/sudoers/visudo.c:276 plugins/sudoers/visudo.c:666
+msgid "unable to initialize sudoers default values"
+msgstr "Standardwerte für sudoers können nicht initialisiert werden"
+
+#: plugins/sudoers/cvtsudoers.c:533 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:612
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s: unbekanntes Schlüsselwort %s"
+
+#: plugins/sudoers/cvtsudoers.c:658
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "Ungültiger Standardtyp: %s"
+
+#: plugins/sudoers/cvtsudoers.c:681
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "ungültiger suppression Typ: %s"
+
+#: plugins/sudoers/cvtsudoers.c:722 plugins/sudoers/cvtsudoers.c:738
+#, c-format
+msgid "invalid filter: %s"
+msgstr "Ungültiger Filter: %s"
+
+#: plugins/sudoers/cvtsudoers.c:783 plugins/sudoers/visudo.c:1000
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "Analyse der Datei %s gescheitert, unbekannter Fehler"
+
+#: plugins/sudoers/cvtsudoers.c:1508 plugins/sudoers/sudoreplay.c:1143
+#: plugins/sudoers/timestamp.c:353 plugins/sudoers/timestamp.c:356
+#, c-format
+msgid "unable to write to %s"
+msgstr "In die Datei »%s« kann nicht geschrieben werden"
+
+#: plugins/sudoers/cvtsudoers.c:1536
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s – zwischen sudoers Dateiformaten konvertieren\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1538
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Optionen:\n"
+" -b, --base=dn Der Basis DN für sudo LDAP Abfragen\n"
+" -d, --defaults=deftypes Konvertiere nur Defaults von spezifischen Typen\n"
+" -e, --expand-aliases Expandiere Aliase beim Konvertieren\n"
+" -f, --output-format=format Ausgabeformat: JSON, LDIF oder sudoers\n"
+" -i, --input-format=format Eingabeformat: LDIF oder sudoers\n"
+" -I, --increment=num Größe der Schrittweite für sudoOrder\n"
+" -h, --help Zeige diese Hilfe an und Ende\n"
+" -m, --match=filter Konvertiere nur Einträge die zum Filter passen\n"
+" -M, --match-local Filter verwendet passwd und group Databank\n"
+" -o, --output=output_file Schreibe die konvertiere sudoers in die Ausgabe-Datei\n"
+" -O, --order-start=num Start für die erste sudoOrder\n"
+" -p, --prune-matches nicht passende Benutzer, Gruppen und Hosts nicht ausgeben\n"
+" -P, --padding=num Auffüllen der sudoOrder Folge\n"
+" -s, --suppress=sections Unterdrücke Ausgabe von bestimmten Abschnitten\n"
+" -V, --version Zeige Versionsinformationen an und Ende"
+
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:245 plugins/sudoers/cvtsudoers_ldif.c:252
+#: plugins/sudoers/cvtsudoers_ldif.c:594 plugins/sudoers/env.c:340
+#: plugins/sudoers/env.c:347 plugins/sudoers/env.c:458
+#: plugins/sudoers/ldap.c:511 plugins/sudoers/ldap.c:629
+#: plugins/sudoers/ldap.c:1003 plugins/sudoers/ldap_conf.c:219
+#: plugins/sudoers/ldap_conf.c:310 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:93 plugins/sudoers/logging.c:479
+#: plugins/sudoers/policy.c:828 plugins/sudoers/policy.c:840
+#: plugins/sudoers/prompt.c:169 plugins/sudoers/serialize_list.c:62
+#: plugins/sudoers/serialize_list.c:71 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/sudoreplay.c:1340 plugins/sudoers/sudoreplay.c:1346
+#: plugins/sudoers/sudoreplay.c:1352 plugins/sudoers/testsudoers.c:306
+#: plugins/sudoers/toke_util.c:217 toke.l:995 toke.l:1277
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "Interner Fehler, %s-Überlauf"
+
+#: plugins/sudoers/cvtsudoers_csv.c:454 plugins/sudoers/cvtsudoers_csv.c:468
+#: plugins/sudoers/cvtsudoers_json.c:661 plugins/sudoers/cvtsudoers_json.c:676
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:362
+#: plugins/sudoers/ldap.c:495
+msgid "unable to get GMT time"
+msgstr "Die GMT-Zeit kann nicht bekommen werden"
+
+#: plugins/sudoers/cvtsudoers_csv.c:459 plugins/sudoers/cvtsudoers_csv.c:473
+#: plugins/sudoers/cvtsudoers_json.c:666 plugins/sudoers/cvtsudoers_json.c:681
+#: plugins/sudoers/cvtsudoers_ldif.c:354 plugins/sudoers/cvtsudoers_ldif.c:367
+#: plugins/sudoers/ldap.c:503
+msgid "unable to format timestamp"
+msgstr "Der Zeitstempel kann nicht formatiert werden"
+
+#: plugins/sudoers/cvtsudoers_json.c:481 plugins/sudoers/cvtsudoers_json.c:516
+#: plugins/sudoers/cvtsudoers_json.c:732
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: unbekannter defaults-Eintrag »%s«"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:663
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "Zu viele sudoers Einträge, Maximum ist %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:706
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "Die Umgebunsvariable SUDOERS_BASE ist nicht gesetzt und die Option -b ist nicht angegeben."
+
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, c-format
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr "%s:%d:%d: Konvertiere die Hostliste in »ALL«"
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr "Der Alias »%s« kann nicht gefunden werden"
+
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, c-format
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr "%s:%d:%d: Benenne »%s« in »%s« um"
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr "%s:%d:%d: doppelter Alias »%s« entfernt"
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr "%s:%d:%d: widersprüchlicher »Defaults«-Eintrag \"%s\" Host-spezifisch in %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, c-format
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr "%s:%d:%d: Mache »Defaults« »%s« spezifisch für Host »%s«"
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr "%s:%d:%d: Kann Defaults »%s« nicht host-spezifisch machen"
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr "%s:%d:%d: entferne Defaults \"%s\" überschrieben in folgenden Einträgen"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1088
+#, c-format
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr "%s:%d:%d: Führe »userspec« zusammen in %s:%d:%d"
+
+# XXX
+#: plugins/sudoers/cvtsudoers_merge.c:1182
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr "%s:%d:%d: entferne durch nachfolgende Einträge überschriebene userspec "
+
+#: plugins/sudoers/def_data.c:56
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Syslog Facility, wenn syslog für Protokollierung verwendet wird: %s"
+
+#: plugins/sudoers/def_data.c:60
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Syslog-Priorität, wenn sich der Benutzer erfolgreich authentifiziert: %s"
+
+#: plugins/sudoers/def_data.c:64
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Syslog-Priorität, wenn sich der Benutzer nicht erfolgreich authentifiziert: %s"
+
+#: plugins/sudoers/def_data.c:68
+msgid "Put OTP prompt on its own line"
+msgstr "Die OTP-Eingabeaufforderung (One-Time-Passwords) in eine eigene Zeile schreiben"
+
+#: plugins/sudoers/def_data.c:72
+msgid "Ignore '.' in $PATH"
+msgstr "».« in $PATH ignorieren"
+
+#: plugins/sudoers/def_data.c:76
+msgid "Always send mail when sudo is run"
+msgstr "Immer eine Mail senden, wenn sudo gestartet wird"
+
+#: plugins/sudoers/def_data.c:80
+msgid "Send mail if user authentication fails"
+msgstr "Eine Mail senden, wenn die Authentifizierung des Benutzers fehlschlägt"
+
+#: plugins/sudoers/def_data.c:84
+msgid "Send mail if the user is not in sudoers"
+msgstr "Eine Mail senden, wenn der Benutzer nicht in der sudoers-Datei steht"
+
+#: plugins/sudoers/def_data.c:88
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Eine Mail senden, wenn der Benutzer nicht in der sudoers-Datei für diesen Rechner steht"
+
+#: plugins/sudoers/def_data.c:92
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Eine Mail senden, wenn der Benutzer nicht berechtigt ist, einen Befehl auszuführen"
+
+#: plugins/sudoers/def_data.c:96
+msgid "Send mail if the user tries to run a command"
+msgstr "Eine Mail senden, wenn der Benutzer versucht, einen Befehl auszuführen"
+
+#: plugins/sudoers/def_data.c:100
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Getrennte Zeitstempel für jede Benutzer/tty-Kombination verwenden"
+
+#: plugins/sudoers/def_data.c:104
+msgid "Lecture user the first time they run sudo"
+msgstr "Den Benutzer beim ersten Aufruf von sudo belehren"
+
+#: plugins/sudoers/def_data.c:108
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Datei mit der sudo-Belehrung: %s"
+
+#: plugins/sudoers/def_data.c:112
+msgid "Require users to authenticate by default"
+msgstr "Standardmäßig muss sich der Benutzer authentifizieren"
+
+#: plugins/sudoers/def_data.c:116
+msgid "Root may run sudo"
+msgstr "Root darf sudo verwenden"
+
+#: plugins/sudoers/def_data.c:120
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Den Hostnamen in der (nicht-syslog-)Protokolldatei speichern"
+
+#: plugins/sudoers/def_data.c:124
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Das Jahr in der (nicht-syslog-)Protokolldatei speichern"
+
+#: plugins/sudoers/def_data.c:128
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Eine Shell starten, wenn sudo ohne Parameter aufgerufen wird"
+
+#: plugins/sudoers/def_data.c:132
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Die Umgebungsvariable $HOME beim Starten einer Shell mit »-s« setzen"
+
+#: plugins/sudoers/def_data.c:136
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Immer die Variable $HOME auf das Home-Verzeichnis des Ziel-Benutzers setzen"
+
+#: plugins/sudoers/def_data.c:140
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Informationssammlung für nützliche Fehlermeldungen erlauben"
+
+#: plugins/sudoers/def_data.c:144
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Vollständige Hostnamen in der sudoers-Datei erfordern"
+
+#: plugins/sudoers/def_data.c:148
+msgid "Insult the user when they enter an incorrect password"
+msgstr "»Beschimpfung« bei Eingabe eines falschen Passwortes"
+
+#: plugins/sudoers/def_data.c:152
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Der Benutzer darf sudo nur aufrufen, wenn ein tty vorhanden ist"
+
+#: plugins/sudoers/def_data.c:156
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo beachtet die Umgebungsvariable »EDITOR«"
+
+#: plugins/sudoers/def_data.c:160
+msgid "Prompt for root's password, not the users's"
+msgstr "Nach dem root-Passwort fragen, nicht nach dem Passwort des Benutzers"
+
+#: plugins/sudoers/def_data.c:164
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Nach dem Passwort des Benutzers »runas_default« fragen, nicht nach dem Passwort des aufrufenden Benutzers"
+
+#: plugins/sudoers/def_data.c:168
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Nach dem Passwort des Ziel-Benutzers fragen, nicht nach dem Passwort des aufrufenden Benutzers"
+
+#: plugins/sudoers/def_data.c:172
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Standards auf die Anmeldeklasse des Zielbenutzers anwenden, falls diese vorhanden ist"
+
+#: plugins/sudoers/def_data.c:176
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Die Umgebungsvariablen »LOGNAME« und »USER« setzen"
+
+#: plugins/sudoers/def_data.c:180
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Nur die effektive UID auf den Ziel-Benutzer setzen, nicht die reale UID"
+
+#: plugins/sudoers/def_data.c:184
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Die sekundären Gruppen nicht auf die Gruppen des Ziel-Benutzers setzen"
+
+#: plugins/sudoers/def_data.c:188
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Zeilenlänge der Protokolldatei für Zeilenumbruch (0 für keinen Zeilenumbruch): %u"
+
+#: plugins/sudoers/def_data.c:192
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Zeitlimit für den Authentifizierungszeitstempel: %.1f Minuten"
+
+#: plugins/sudoers/def_data.c:196
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Zeitlimit bei der Eingabe des Passwortes: %.1f Minuten"
+
+#: plugins/sudoers/def_data.c:200
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Anzahl Versuche zur Eingabe des Passwortes: %u"
+
+#: plugins/sudoers/def_data.c:204
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Zu verwendende Umask oder 0777, um die Umask des Benutzers zu verwenden: 0%o"
+
+#: plugins/sudoers/def_data.c:208
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Pfad zur Protokolldatei: %s"
+
+#: plugins/sudoers/def_data.c:212
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Pfad zum Mail-Programm: %s"
+
+#: plugins/sudoers/def_data.c:216
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Parameter für das Mail-Programm: %s"
+
+#: plugins/sudoers/def_data.c:220
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Mail-Adresse des Empfängers: %s"
+
+#: plugins/sudoers/def_data.c:224
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Mail-Adresse des Absenders: %s"
+
+#: plugins/sudoers/def_data.c:228
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Betreffzeile für Mails: %s"
+
+#: plugins/sudoers/def_data.c:232
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Meldung bei Eingabe eines falschen Passwortes: %s"
+
+#: plugins/sudoers/def_data.c:236
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Verzeichnis für den Belehrungsstatus: %s"
+
+#: plugins/sudoers/def_data.c:240
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Pfad zum Authentifizierungszeitstempel-Verzeichnis: %s"
+
+#: plugins/sudoers/def_data.c:244
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Besitzer des Authentifizierungszeitstempelverzeichnisses: %s"
+
+#: plugins/sudoers/def_data.c:248
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Benutzer in dieser Gruppe sind von Passwort- und PATH-Anforderungen ausgenommen: %s"
+
+#: plugins/sudoers/def_data.c:252
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Standard-Eingabeaufforderung für das Passwort: %s"
+
+#: plugins/sudoers/def_data.c:256
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Überschreibt in allen Fällen bei der Passwortabfrage die Systemabfrage, falls gesetzt."
+
+#: plugins/sudoers/def_data.c:260
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Standardbenutzer, unter dem die Befehle ausgeführt werden: %s"
+
+#: plugins/sudoers/def_data.c:264
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Wert, mit dem der Inhalt von $PATH des Benutzers überschrieben werden soll: %s"
+
+#: plugins/sudoers/def_data.c:268
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Pfad zum Editor, den visudo verwenden soll: %s"
+
+#: plugins/sudoers/def_data.c:272
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Wann soll ein Passwort für den Pseudobefehl »list« erforderlich sein: %s"
+
+#: plugins/sudoers/def_data.c:276
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Wann soll ein Passwort für den Pseudobefehl »verify« erforderlich sein: %s"
+
+#: plugins/sudoers/def_data.c:280
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "Preload der »sudo_noexec« Bibliothek zum Ersetzen der »exec« Funktionen"
+
+#: plugins/sudoers/def_data.c:284
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Wenn das LDAP-Verzeichnis erreichbar ist, ignorieren wir die lokale sudoers-Datei"
+
+#: plugins/sudoers/def_data.c:288
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Datei-Deskriptoren >= %d werden geschlossen, bevor ein Befehl ausgeführt wird"
+
+#: plugins/sudoers/def_data.c:292
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "Benutzer können den Wert für »closefrom« mit der der Option -C überschreiben, wenn diese Option gesetzt ist"
+
+#: plugins/sudoers/def_data.c:296
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Benutzern das Setzen beliebiger Umgebungsvariablen erlauben"
+
+#: plugins/sudoers/def_data.c:300
+msgid "Reset the environment to a default set of variables"
+msgstr "Die Umgebung auf einen Standardsatz an Variablen zurücksetzen"
+
+# XXX gibt es da einen sinnvollen Begriff?
+#: plugins/sudoers/def_data.c:304
+msgid "Environment variables to check for safety:"
+msgstr "Folgende Umgebungsvariablen prüfen:"
+
+#: plugins/sudoers/def_data.c:308
+msgid "Environment variables to remove:"
+msgstr "Folgende Umgebungsvariablen löschen:"
+
+#: plugins/sudoers/def_data.c:312
+msgid "Environment variables to preserve:"
+msgstr "Folgende Umgebungsvariablen bewahren:"
+
+#: plugins/sudoers/def_data.c:316
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "Im neuen Security-Kontext von SELinux wird diese Rolle verwendet: %s"
+
+#: plugins/sudoers/def_data.c:320
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "Im neuen Security-Kontext von SELinux wird dieser Typ verwendet: %s"
+
+#: plugins/sudoers/def_data.c:324
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Pfad zur sudo-spezifischen »environment«-Datei: %s"
+
+# XXX
+#: plugins/sudoers/def_data.c:328
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Pfad zur eingeschränkten sudo »environment«-Datei: %s"
+
+#: plugins/sudoers/def_data.c:332
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Beim Auswerten der sudoers-Datei wird diese Locale verwendet: %s"
+
+#: plugins/sudoers/def_data.c:336
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "sudo erlauben, nach einem Passwort zu fragen, auch wenn das Passwort sichtbar wird"
+
+#: plugins/sudoers/def_data.c:340
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Sichtbare Rückmeldung bei der Passworteingabeaufforderung, wenn der Benutzer etwas eingibt"
+
+#: plugins/sudoers/def_data.c:344
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Schnelleren Musterabgleich verwenden, der zwar ungenauer ist, aber nicht auf das Dateisystem zugreift"
+
+#: plugins/sudoers/def_data.c:348
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "Die umask in sudoers überschreibt die umask des Benutzers, selbst wenn diese mehr Berechtigungen zulässt"
+
+#: plugins/sudoers/def_data.c:352
+msgid "Log user's input for the command being run"
+msgstr "Benutzereingaben für den ausgeführten Befehl protokollieren"
+
+#: plugins/sudoers/def_data.c:356
+msgid "Log the command's standard input if not connected to a terminal"
+msgstr "Standardeingabe des Kommandos protokollieren, wenn kein Terminal angebunden ist"
+
+#: plugins/sudoers/def_data.c:360
+msgid "Log the user's terminal input for the command being run"
+msgstr "Benutzereingaben am Terminal für den ausgeführten Befehl protokollieren"
+
+#: plugins/sudoers/def_data.c:364
+msgid "Log the output of the command being run"
+msgstr "Die Ausgabe des ausgeführten Befehls protokollieren"
+
+#: plugins/sudoers/def_data.c:368
+msgid "Log the command's standard output if not connected to a terminal"
+msgstr "Standardausgabe des Kommandos protokollieren, wenn kein Terminal angebunden ist"
+
+#: plugins/sudoers/def_data.c:372
+msgid "Log the command's standard error if not connected to a terminal"
+msgstr "Standarderror des Kommandos protokollieren, wenn kein Terminal angebunden ist<"
+
+#: plugins/sudoers/def_data.c:376
+msgid "Log the terminal output of the command being run"
+msgstr "Die Terminalausgabe des ausgeführten Befehls protokollieren"
+
+#: plugins/sudoers/def_data.c:380
+msgid "Compress I/O logs using zlib"
+msgstr "Ein-/Ausgabe-Protokolle mittels zlib protokollieren"
+
+#: plugins/sudoers/def_data.c:384
+msgid "Always run commands in a pseudo-tty"
+msgstr "Befehle immer in einem Pseudo-TTY ausführen"
+
+#: plugins/sudoers/def_data.c:388
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Plugin für Unterstützung von Nicht-Unix-Gruppen: %s"
+
+#: plugins/sudoers/def_data.c:392
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Verzeichnis zur Speicherung der Ein-/Ausgabe-Protokolle: %s"
+
+#: plugins/sudoers/def_data.c:396
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Datei zur Speicherung der Ein-/Ausgabe-Protokolle: %s"
+
+#: plugins/sudoers/def_data.c:400
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Einen Eintrag in die utmp/utmpx-Datei einfügen, wenn ein Pseudo-TTY erzeugt wird"
+
+#: plugins/sudoers/def_data.c:404
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Für den Eintrag in der utmp-Datei den runas-Benutzer verwenden, nicht den aufrufenden Benutzer"
+
+#: plugins/sudoers/def_data.c:408
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Menge der erlaubten Privilegien: %s"
+
+# XXX einschränkenden?
+#: plugins/sudoers/def_data.c:412
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Menge der eingeschränkten Privilegien: %s"
+
+#: plugins/sudoers/def_data.c:416
+msgid "Run commands on a pty in the background"
+msgstr "Befehle mit einem Pseudo-TTY im Hintergrund starten"
+
+#: plugins/sudoers/def_data.c:420
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "Verwendeter PAM-Service-Name: %s"
+
+#: plugins/sudoers/def_data.c:424
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "PAM-Service-Name für Anmelde-Shells: %s"
+
+#: plugins/sudoers/def_data.c:428
+#, c-format
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr "PAM-Service-Name für sudo-Aufruf mit der Option »-A«: %s"
+
+#: plugins/sudoers/def_data.c:432
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Versuchen, die PAM-Anmeldedaten für den Ziel-Benutzer zu bekommen"
+
+#: plugins/sudoers/def_data.c:436
+msgid "Create a new PAM session for the command to run in"
+msgstr "Eine neue PAM-Sitzung erzeugen, um den Befehl auszuführen"
+
+#: plugins/sudoers/def_data.c:440
+msgid "Perform PAM account validation management"
+msgstr "Ausführen vom PAM-Account-Management"
+
+#: plugins/sudoers/def_data.c:444
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "Maximale Sequenznummer des Ein-/Ausgabe-Protokolls: %s"
+
+#: plugins/sudoers/def_data.c:448
+msgid "Enable sudoers netgroup support"
+msgstr "Unterstützung für netgroups in sudoers aktivieren"
+
+#: plugins/sudoers/def_data.c:452
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Prüfe die übergeordneten Verzeichnisse auf Schreibbarkeit beim Editieren von Dateien mit »sudoedit«"
+
+#: plugins/sudoers/def_data.c:456
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Folge symbolischen Links beim Editieren von Dateien mit sudoedit"
+
+#: plugins/sudoers/def_data.c:460
+msgid "Query the group plugin for unknown system groups"
+msgstr "Frage das Group-Plugin nach unbekannten System-Gruppen"
+
+#: plugins/sudoers/def_data.c:464
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Prüfe die Netgroup-Zuordnung aufgrund des gesamten Tupels: Benutzer, Host und Domain"
+
+#: plugins/sudoers/def_data.c:468
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Erlaubt das Ausführen von Kommandos, auch wenn kein Audit-Log geschrieben werden kann"
+
+#: plugins/sudoers/def_data.c:472
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Erlaubt das Ausführen von Kommandos, auch wenn kein I/O-Log geschrieben werden kann"
+
+#: plugins/sudoers/def_data.c:476
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Erlaubt das Ausführen von Kommandos, auch wenn kein Log geschrieben werden kann"
+
+#: plugins/sudoers/def_data.c:480
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Beim Auflösen von Gruppen in der sudoers nach der Guppen-ID suchen, nicht nach dem Gruppenname"
+
+#: plugins/sudoers/def_data.c:484
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Log-Einträge größer als dieser Wert werden auf mehrere Syslog Einträge verteilt: %u"
+
+#: plugins/sudoers/def_data.c:488
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Eigentümer der I/O Logdateien: %s"
+
+#: plugins/sudoers/def_data.c:492
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Gruppe der I/O Logdateien: %s"
+
+#: plugins/sudoers/def_data.c:496
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Dateimode der I/O Logdatei: 0%o"
+
+#: plugins/sudoers/def_data.c:500
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Führe Kommandos mit Hilfe eines Dateideskriptors anstelle des Pfades aus: %s"
+
+#: plugins/sudoers/def_data.c:504
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Ignoriere unbekannte Default-Einträge in der Datei »sudoers« anstatt eine Warnung auszugeben"
+
+#: plugins/sudoers/def_data.c:508
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Laufzeit in Sekunde, nach der das Kommando abgebrochen wird: %u"
+
+#: plugins/sudoers/def_data.c:512
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Erlaube dem Benutzer per Kommandozeile einen Timeout anzugeben"
+
+#: plugins/sudoers/def_data.c:516
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Schreibe Log-Daten direkt ohne zu puffern"
+
+#: plugins/sudoers/def_data.c:520
+msgid "Include the process ID when logging via syslog"
+msgstr "Protokolliere auch die Prozess-ID beim Schreiben ins Systemlog"
+
+#: plugins/sudoers/def_data.c:524
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Typ des Authentifizierungszeitstempelprotokolls: %s"
+
+#: plugins/sudoers/def_data.c:528
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Fehler bei der Authentifizierung: %s"
+
+#: plugins/sudoers/def_data.c:532
+msgid "Ignore case when matching user names"
+msgstr "Ignoriere Groß-/Kleinschreibung beim Matchen von Benutzernamen"
+
+#: plugins/sudoers/def_data.c:536
+msgid "Ignore case when matching group names"
+msgstr "Ignoriere Groß-/Kleinschreibung beim Matchen von Gruppennamen"
+
+#: plugins/sudoers/def_data.c:540
+msgid "Log when a command is allowed by sudoers"
+msgstr "Protokolliere von sudo erlaubte Kommandos"
+
+#: plugins/sudoers/def_data.c:544
+msgid "Log when a command is denied by sudoers"
+msgstr "Protokolliere von sudo verweigerte Kommandos"
+
+#: plugins/sudoers/def_data.c:548
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "Sudo Log Server mit optionalem Port für die Verbindung"
+
+#: plugins/sudoers/def_data.c:552
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Sudo Log-Server Timeout in Secunden: %u"
+
+#: plugins/sudoers/def_data.c:556
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "Verwende die SO_KEEPALIVE Socket Option für die Verbindung zum Logserver"
+
+#: plugins/sudoers/def_data.c:560
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "Pfad zur Zertifikats-Bündel-Datei des Audit Servers: %s"
+
+#: plugins/sudoers/def_data.c:564
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "Pfad zur sudoers Zertifikats-Datei: %s"
+
+#: plugins/sudoers/def_data.c:568
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "Pfad zur sudoers Datei mit dem privaten Schlüssel: %s"
+
+#: plugins/sudoers/def_data.c:572
+msgid "Verify that the log server's certificate is valid"
+msgstr "Prüfe das Log-Server-Zertifikat auf Gültigkeit"
+
+#: plugins/sudoers/def_data.c:576
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "Erlaube die Verwendung eines unbekannten »runas« Benutzers oder Gruppen-ID"
+
+#: plugins/sudoers/def_data.c:580
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "Nur die Ausführung von Kommandos erlauben für Benutzer mit einer gültigen Shell"
+
+#: plugins/sudoers/def_data.c:584
+msgid "Set the pam remote user to the user running sudo"
+msgstr "Setze den PAM remote Benutzer auf den Benutzer, der sudo ausführt"
+
+#: plugins/sudoers/def_data.c:588
+msgid "Set the pam remote host to the local host name"
+msgstr "Setze den PAM remote Rechner auf den lokalen Hostname"
+
+#: plugins/sudoers/def_data.c:592
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "Arbeitsverzeichnis um vor Ausführung des Kommandos dorthin zu wechseln: %s"
+
+#: plugins/sudoers/def_data.c:596
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "Root-Verzeichnis zur Verwendung, bevor ein Befehl ausgeführt wird: %s"
+
+#: plugins/sudoers/def_data.c:600
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "Das Format der zu schreibenden Logs: %s"
+
+#: plugins/sudoers/def_data.c:604
+msgid "Enable SELinux RBAC support"
+msgstr "Schalte SELinux RBAC Support ein"
+
+#: plugins/sudoers/def_data.c:608
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "Pfad zur Datei die beim ersten sudo-Lauf erzeugt wird: %s"
+
+#: plugins/sudoers/def_data.c:612
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "Weitere Kommando abfangen und sudoers Restriktionen auf sie anwenden"
+
+#: plugins/sudoers/def_data.c:616
+msgid "Log sub-commands run by the original command"
+msgstr "Protokolliere von diesem Kommando gestartete Kind-Prozesse"
+
+#: plugins/sudoers/def_data.c:620
+msgid "Log the exit status of commands"
+msgstr "Den Exitcode des ausgeführten Befehls protokollieren"
+
+# XXX Check!
+#: plugins/sudoers/def_data.c:624
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr "Folgende Kommando in einer nachverfolgten Sitzung müssen authentifiziert werden"
+
+#: plugins/sudoers/def_data.c:628
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr "Erlaube einem abgefangenen Kommando die Ausführung von setuid oder setgid Programmen"
+
+#: plugins/sudoers/def_data.c:632
+#, c-format
+msgid "The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr "Die maximale Größe zu der der Adressbereich des Prozesse wachsen kann (in Bytes): %s"
+
+#: plugins/sudoers/def_data.c:636
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr "Die maximale Größe eines erzeugten Core Dumps (in Bytes): %s"
+
+#: plugins/sudoers/def_data.c:640
+#, c-format
+msgid "The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr "Die maximale CPU Zeit die vom Prozess genutzt werden kann (in Sekunden): %s"
+
+#: plugins/sudoers/def_data.c:644
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr "Die maximale Größe des Data Segments für den Prozess (in Bytes): %s"
+
+#: plugins/sudoers/def_data.c:648
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr "Die maximale Dateigröße für den Prozess (in Bytes): %s"
+
+#: plugins/sudoers/def_data.c:652
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr "Die maximale Anzahl von Sperren des Prozesses: %s"
+
+#: plugins/sudoers/def_data.c:656
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr "Die maximale gesperrte Speichergröße des Prozesses (in Bytes): %s"
+
+#: plugins/sudoers/def_data.c:660
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr "Die maximale Anzahl offener Dateien des Prozesses: %s"
+
+#: plugins/sudoers/def_data.c:664
+#, c-format
+msgid "The maximum number of processes that the user may run simultaneously: %s"
+msgstr "Die maximale Anzahl von gleichzeitige laufenden Prozessen des Benutzers: %s"
+
+#: plugins/sudoers/def_data.c:668
+#, c-format
+msgid "The maximum size to which the process's resident set size may grow (in bytes): %s"
+msgstr "Die maximle Größe des residenten Speichers vom Prozess (in Bytes): %s"
+
+#: plugins/sudoers/def_data.c:672
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr "Die maximale Größe des Prozess-Stacks (in Bytes): %s"
+
+#: plugins/sudoers/def_data.c:676
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr "Authentifzierung auch im nicht-interaktiven Modus versuchen"
+
+#: plugins/sudoers/def_data.c:680
+msgid "Store plaintext passwords in I/O log input"
+msgstr "Klartext-Passwörter im Ein-Ausgabe-Log als Eingabe protokollieren"
+
+#: plugins/sudoers/def_data.c:684
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr "Liste von regulären Ausdrücken zum Matchen des Passwort-Prompts"
+
+#: plugins/sudoers/def_data.c:688
+#, c-format
+msgid "The mechanism used by the intercept and log_subcmds options: %s"
+msgstr "Der Mechanismus für »intercept« und »log_subcmds« Optionen: %s"
+
+#: plugins/sudoers/def_data.c:692
+msgid "Attempt to verify the command and arguments after execution"
+msgstr "Versuche das Kommando und die Argumente nach der Ausführung zu verifizieren"
+
+#: plugins/sudoers/def_data.c:696
+#, c-format
+msgid "AppArmor profile to use in the new security context: %s"
+msgstr "Im neuen Security-Kontext von AppArmor wird diese Rolle verwendet: %s"
+
+#: plugins/sudoers/defaults.c:207
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "unbekannter defaults-Eintrag »%s«"
+
+#: plugins/sudoers/defaults.c:251
+#, c-format
+msgid "no value specified for \"%s\""
+msgstr "Kein Wert für »%s« angegeben"
+
+#: plugins/sudoers/defaults.c:260
+#, c-format
+msgid "invalid operator \"%c=\" for \"%s\""
+msgstr "Ungültiger Operator »%c=« für Option »%s«"
+
+#: plugins/sudoers/defaults.c:292
+#, c-format
+msgid "option \"%s\" does not take a value"
+msgstr "Die Option »%s« wird ohne Wert verwendet"
+
+#: plugins/sudoers/defaults.c:319
+#, c-format
+msgid "invalid Defaults type 0x%x for option \"%s\""
+msgstr "Ungültiger »Defaults« Typ 0x%x für Option »%s«"
+
+#: plugins/sudoers/defaults.c:326
+#, c-format
+msgid "value \"%s\" is invalid for option \"%s\""
+msgstr "Der Wert »%s« ist für die Option »%s« ungültig"
+
+#: plugins/sudoers/defaults.c:1176 plugins/sudoers/policy.c:213
+#: plugins/sudoers/policy.c:222
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr "Pfadname für »%s« ist zu lang"
+
+#: plugins/sudoers/defaults.c:1182
+#, c-format
+msgid "values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "Werte für »%s« müssen mit »/«, »~« oder »*« beginnen"
+
+#: plugins/sudoers/defaults.c:1189
+#, c-format
+msgid "values for \"%s\" must start with a '/'"
+msgstr "Werte für »%s« müssen mit einem »/« beginnen"
+
+#: plugins/sudoers/display.c:160
+#, c-format
+msgid "LDAP Role: %s\n"
+msgstr "LDAP-Rolle: %s\n"
+
+#: plugins/sudoers/display.c:163
+#, c-format
+msgid "Sudoers entry: %s\n"
+msgstr "Sudoers-Eintrag: %s\n"
+
+#: plugins/sudoers/display.c:166
+msgid " RunAsUsers: "
+msgstr " RunAsUsers: "
+
+#: plugins/sudoers/display.c:181
+msgid " RunAsGroups: "
+msgstr " RunAsGroups: "
+
+#: plugins/sudoers/display.c:191
+msgid " Options: "
+msgstr " Optionen: "
+
+#: plugins/sudoers/display.c:255
+msgid " Commands:\n"
+msgstr " Befehle:\n"
+
+#: plugins/sudoers/display.c:478
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Passende Defaults-Einträge für %s auf %s:\n"
+
+#: plugins/sudoers/display.c:496
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Runas und befehlsspezifische Standardwerte für %s:\n"
+
+#: plugins/sudoers/display.c:514
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "Der Benutzer %s darf die folgenden Befehle auf %s ausführen:\n"
+
+#: plugins/sudoers/display.c:530
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Der Benutzer %s darf sudo auf dem Rechner %s nicht ausführen.\n"
+
+#: plugins/sudoers/editor.c:180
+#, c-format
+msgid "ignoring editor: %.*s"
+msgstr "Ignoriere Editor: %.*s"
+
+#: plugins/sudoers/editor.c:181
+msgid "editor arguments may not contain \"--\""
+msgstr "Editor Argumente dürfen »--« nicht enthalten"
+
+#: plugins/sudoers/env.c:426
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: envp ist beschädigt, die Längen passen nicht"
+
+#: plugins/sudoers/env.c:1119
+msgid "unable to rebuild the environment"
+msgstr "Das Environment kann nicht neu erstellt werden"
+
+#: plugins/sudoers/env.c:1199
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "Leider dürfen die folgenden Umgebungsvariablen nicht gesetzt werden: %s"
+
+#: plugins/sudoers/filedigest.c:50
+#, c-format
+msgid "unsupported digest type %u for %s"
+msgstr "Prüfsummentyp %u wird für %s nicht unterstützt"
+
+#: plugins/sudoers/filedigest.c:77
+#, c-format
+msgid "%s: read error"
+msgstr "%s: Fehler beim Lesen"
+
+#: plugins/sudoers/group_plugin.c:169 plugins/sudoers/sssd.c:578
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "Laden von %s fehlgeschlagen: %s"
+
+#: plugins/sudoers/group_plugin.c:181
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "Das Symbol »group_plugin« kann in %s nicht gefunden werden"
+
+#: plugins/sudoers/group_plugin.c:186
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: Die Major-Version %d des Group-Plugins ist inkompatibel, erwartet wird %d"
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "»%s« ist keine gültige IP-Adresse"
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "»%s« ist keine gültige Netzmaske"
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Lokale IP-Adresse und Netzmaske:\n"
+
+#: plugins/sudoers/iolog.c:694
+msgid "unable to update sequence file"
+msgstr "Kann die Sequenz-Datei nicht aktualisieren"
+
+#: plugins/sudoers/iolog.c:728 plugins/sudoers/iolog.c:917
+#: plugins/sudoers/iolog.c:1080 plugins/sudoers/iolog.c:1087
+#: plugins/sudoers/iolog.c:1209 plugins/sudoers/iolog.c:1216
+#: plugins/sudoers/iolog.c:1316 plugins/sudoers/iolog.c:1323
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "In die I/O Logdatei kann nicht geschrieben werden: %s"
+
+#: plugins/sudoers/iolog.c:736
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "Die Datei %s%s kann nicht erstellt werden"
+
+#: plugins/sudoers/iolog.c:965
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: Interner Fehler, Logdatei für Event %d nicht geöffnet"
+
+#: plugins/sudoers/iolog.c:1065 plugins/sudoers/iolog.c:1194
+#: plugins/sudoers/iolog.c:1300 plugins/sudoers/timestamp.c:897
+#: plugins/sudoers/timestamp.c:989 plugins/sudoers/visudo.c:555
+#: plugins/sudoers/visudo.c:561
+msgid "unable to read the clock"
+msgstr "Die Uhrzeit kann nicht ausgelesen werden"
+
+#: plugins/sudoers/iolog.c:1292 plugins/sudoers/log_client.c:1203
+#: plugins/sudoers/log_client.c:1213 plugins/sudoers/log_client.c:1217
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: Interner Fehler, ungültiges Signal %d"
+
+#: plugins/sudoers/ldap.c:154 plugins/sudoers/ldap_conf.c:289
+msgid "starttls not supported when using ldaps"
+msgstr "starttls wird für ldaps nicht unterstützt"
+
+#: plugins/sudoers/ldap.c:226
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "Die Zertifikat- und Schlüsseldatenbank für SSL kann nicht initialisiert werden: %s"
+
+#: plugins/sudoers/ldap.c:229
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "In der Datei »%s« muss »TLS_CERT« angegeben sein, um SSL zu nutzen"
+
+#: plugins/sudoers/ldap.c:1593
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "LDAP kann nicht initialisiert werden: %s"
+
+#: plugins/sudoers/ldap.c:1630
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls ist angegeben, aber die LDAP-Bibliotheken unterstützen ldap_start_tls_s() und ldap_start_tls_s_np() nicht"
+
+#: plugins/sudoers/ldap.c:1767 plugins/sudoers/parse_ldif.c:745
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "Ungültiges »sudoOrder« Attribut: %s"
+
+#: plugins/sudoers/ldap_conf.c:197
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: Portnummer ist zu groß"
+
+#: plugins/sudoers/ldap_conf.c:258
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "LDAP-Adresstyp wird nicht unterstützt: %s"
+
+#: plugins/sudoers/ldap_conf.c:285
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "ldap- und ldaps-Adressen können nicht zusammen verwendet werden"
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "doppelte sudoOption: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "sudoOption kann nicht konvertiert werden: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "Das Audit-System kann nicht geöffnet werden"
+
+#: plugins/sudoers/linux_audit.c:104
+msgid "unable to send audit message"
+msgstr "Die Audit-Nachricht kann nicht gesendet werden"
+
+#: plugins/sudoers/log_client.c:125 plugins/sudoers/log_client.c:412
+#: plugins/sudoers/log_client.c:1450 plugins/sudoers/log_client.c:2076
+msgid "error in event loop"
+msgstr "Fehler in der Event-Schleife"
+
+#: plugins/sudoers/log_client.c:205
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "Erzeugen eines neuen SSL_CTX Objektes fehlgeschlagen: %s"
+
+#: plugins/sudoers/log_client.c:230
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "Kann das CA-Bundle »%s« nicht laden"
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "Laden von Zertifikat »%s« fehlgeschlagen"
+
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "unable to load private key %s"
+msgstr "Laden des privaten Schlüssels »%s« fehlgeschlagen"
+
+#: plugins/sudoers/log_client.c:275
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "Kann kein SSL-Objekt anlegen: %s"
+
+#: plugins/sudoers/log_client.c:364 plugins/sudoers/log_client.c:369
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "TLS Verbindung zu %s:%s fehlgeschlagen: %s"
+
+#: plugins/sudoers/log_client.c:545
+msgid "TLS initialization was unsuccessful"
+msgstr "TLS Initialisierung war nicht erfolgreich"
+
+#: plugins/sudoers/log_client.c:555
+msgid "TLS handshake was unsuccessful"
+msgstr "TLS Handshake war nicht erfolgreich"
+
+#: plugins/sudoers/log_client.c:1221
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: Interner Fehler, ungültiger Exit-Status %d"
+
+#: plugins/sudoers/log_client.c:1757 plugins/sudoers/log_client.c:1782
+msgid "lost connection to log server"
+msgstr "Verbindung zum Logserver verloren"
+
+#: plugins/sudoers/log_client.c:1859
+msgid "missing write buffer"
+msgstr "Schreib-Puffer fehlt"
+
+#: plugins/sudoers/log_client.c:2015
+msgid "unable to connect to log server"
+msgstr "Verbindung zum Logserver kann nicht aufgebaut werden"
+
+#: plugins/sudoers/logging.c:295
+msgid "user NOT in sudoers"
+msgstr "Der Benutzer ist NICHT in der sudoers-Datei enthalten"
+
+#: plugins/sudoers/logging.c:297
+msgid "user NOT authorized on host"
+msgstr "Der Benutzer ist NICHT auf dem Rechner autorisiert"
+
+#: plugins/sudoers/logging.c:299
+msgid "command not allowed"
+msgstr "Der Befehl ist nicht erlaubt"
+
+#: plugins/sudoers/logging.c:320
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr ""
+"»%s« ist nicht in der sudoers-Datei.\n"
+"\n"
+
+#: plugins/sudoers/logging.c:323
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr "»%s« darf sudo auf dem Rechner »%s« nicht ausführen.\n"
+
+#: plugins/sudoers/logging.c:326
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Leider darf der Benutzer %s sudo für %s nicht verwenden.\n"
+
+#: plugins/sudoers/logging.c:339
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s%s' as %s%s%s on %s.\n"
+msgstr "Leider darf der Benutzer %s »%s%s%s%s« als %s%s%s auf %s nicht ausführen.\n"
+
+#: plugins/sudoers/logging.c:350
+msgid "This incident has been reported to the administrator.\n"
+msgstr "Dieser Vorfall wurde an den Administrator gemeldet.\n"
+
+#: plugins/sudoers/logging.c:387 plugins/sudoers/sudoers.c:547
+#: plugins/sudoers/sudoers.c:549 plugins/sudoers/sudoers.c:551
+#: plugins/sudoers/sudoers.c:553 plugins/sudoers/sudoers.c:777
+#: plugins/sudoers/sudoers.c:779
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: Befehl nicht gefunden"
+
+#: plugins/sudoers/logging.c:389 plugins/sudoers/sudoers.c:543
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"Im aktuellen Verzeichnis ».« gefundenes »%s« wird ignoriert.\n"
+"Verwenden Sie »sudo ./%s«, wenn dies der gewünschte Befehl »%s« ist."
+
+#: plugins/sudoers/logging.c:409
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u Fehlversuch bei der Passwort-Eingabe"
+msgstr[1] "%u Fehlversuche bei der Passwort-Eingabe"
+
+#: plugins/sudoers/logging.c:500
+msgid "authentication failure"
+msgstr "Fehler bei der Authentifizierung"
+
+#: plugins/sudoers/logging.c:539 plugins/sudoers/logging.c:558
+msgid "a password is required"
+msgstr "Ein Passwort ist notwendig"
+
+#: plugins/sudoers/logging.c:881
+msgid "problem parsing sudoers"
+msgstr "Problem beim Auswerten der sudoers-Datei"
+
+#: plugins/sudoers/logging.c:922 plugins/sudoers/logging.c:930
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr "%s:%d:%d: %s"
+
+#: plugins/sudoers/logging.c:1108
+#, c-format
+msgid "unable to write log file %s"
+msgstr "In die Logdatei %s kann nicht geschrieben werden"
+
+#: plugins/sudoers/match_digest.c:107
+#, c-format
+msgid "digest for %s (%s) bad length %zu, expected %zu"
+msgstr "Prüfsumme für %s (%s) ungültige Länge %zu, %zu erwartet"
+
+#: plugins/sudoers/match_digest.c:126
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "Prüfsumme für %s (%s) ist nicht in der Form %s"
+
+#: plugins/sudoers/parse_ldif.c:615
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "ignoriere die unvollständige sudoRole: cn: %s"
+
+#: plugins/sudoers/parse_ldif.c:675
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "Ungültiges LDIF-Attribut: %s"
+
+#: plugins/sudoers/parser_warnx.c:56
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: plugins/sudoers/parser_warnx.c:59
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s: %s\n"
+
+#: plugins/sudoers/pivot.c:71
+msgid "unable to restore root directory"
+msgstr "Das Wurzelverzeichnis kann nicht wieder eingestellt werden"
+
+#: plugins/sudoers/pivot.c:79
+msgid "unable to restore current working directory"
+msgstr "Das aktuelle Arbeitsverzeichnis kann nicht wieder eingerichtet werden"
+
+#: plugins/sudoers/policy.c:78 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "ungültige Option »%.*s« durch das sudo-Frontend angegeben"
+
+#: plugins/sudoers/policy.c:364 plugins/sudoers/testsudoers.c:329
+msgid "unable to parse network address list"
+msgstr "Die Netzwerkadressliste kann nicht eingelesen werden"
+
+#: plugins/sudoers/policy.c:556
+msgid "user name not set by sudo front-end"
+msgstr "Benutzername nicht durch das sudo-Frontend angegeben"
+
+#: plugins/sudoers/policy.c:560
+msgid "user-ID not set by sudo front-end"
+msgstr "User-ID nicht durch das sudo-Frontend angegeben"
+
+#: plugins/sudoers/policy.c:564
+msgid "group-ID not set by sudo front-end"
+msgstr "Gruppen-ID nicht durch das sudo-Frontend angegeben"
+
+#: plugins/sudoers/policy.c:568
+msgid "host name not set by sudo front-end"
+msgstr "Hostname nicht durch das sudo-Frontend angegeben"
+
+#: plugins/sudoers/policy.c:757
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "Ungültiges Arbeitsverzeichnis: %s"
+
+#: plugins/sudoers/policy.c:944
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "Ungültiges »chroot« Verzeichnis: %s"
+
+#: plugins/sudoers/policy.c:1153 plugins/sudoers/visudo.c:919
+#: plugins/sudoers/visudo.c:1218
+#, c-format
+msgid "unable to execute %s"
+msgstr "%s kann nicht ausgeführt werden"
+
+#: plugins/sudoers/policy.c:1225 plugins/sudoers/policy.c:1260
+#: plugins/sudoers/policy.c:1282 plugins/sudoers/policy.c:1300
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: ungültige Mode-Flags vom sudo-Frontend: 0x%x"
+
+#: plugins/sudoers/policy.c:1323
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Sudoers-Policy-Plugin Version %s\n"
+
+#: plugins/sudoers/policy.c:1325
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Sudoers-Datei-Grammatik-Version %d\n"
+
+#: plugins/sudoers/policy.c:1329
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Sudoers-Pfad: %s\n"
+
+#: plugins/sudoers/policy.c:1332
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "nsswitch-Pfad: %s\n"
+
+#: plugins/sudoers/policy.c:1335
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "ldap.conf-Pfad: %s\n"
+
+#: plugins/sudoers/policy.c:1337
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "ldap.secret-Pfad: %s\n"
+
+#: plugins/sudoers/policy.c:1370
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "Der Hook vom Typ %d kann nicht registriert werden (Version %d.%d)"
+
+#: plugins/sudoers/policy.c:1388
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "Der Hook vom Typ %d kann nicht deregistriert werden (Version %d.%d)"
+
+#: plugins/sudoers/pwutil.c:242 plugins/sudoers/pwutil.c:260
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "Die Benutzer-ID %u kann nicht zwischengespeichert werden"
+
+#: plugins/sudoers/pwutil.c:254
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "Die Benutzer-ID %u kann nicht zwischengespeichert werden, sie existiert bereits"
+
+#: plugins/sudoers/pwutil.c:314 plugins/sudoers/pwutil.c:332
+#: plugins/sudoers/pwutil.c:395 plugins/sudoers/pwutil.c:440
+#, c-format
+msgid "unable to cache user %s"
+msgstr "Der Benutzer %s kann nicht zwischengespeichert werden"
+
+#: plugins/sudoers/pwutil.c:327
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "Der Benutzer %s kann nicht in den Zwischenspeicher aufgenommen werden, er existiert bereits"
+
+#: plugins/sudoers/pwutil.c:559 plugins/sudoers/pwutil.c:577
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "Die Gruppen-ID %u kann nicht in den Zwischenspeicher aufgenommen werden"
+
+#: plugins/sudoers/pwutil.c:571
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "Die Gruppen-ID %u kann nicht in den Zwischenspeicher aufgenommen werden, sie existiert bereits"
+
+#: plugins/sudoers/pwutil.c:625 plugins/sudoers/pwutil.c:643
+#: plugins/sudoers/pwutil.c:704 plugins/sudoers/pwutil.c:753
+#, c-format
+msgid "unable to cache group %s"
+msgstr "Die Gruppe %s kann nicht zwischengespeichert werden"
+
+#: plugins/sudoers/pwutil.c:638
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "Die Gruppe %s kann nicht in den Zwischenspeicher aufgenommen werden, sie existiert bereits"
+
+#: plugins/sudoers/pwutil.c:900 plugins/sudoers/pwutil.c:985
+#: plugins/sudoers/pwutil.c:1039 plugins/sudoers/pwutil.c:1095
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "Die Gruppen-Liste für %s kann nicht in den Zwischenspeicher aufgenommen werden, sie existiert bereits"
+
+#: plugins/sudoers/pwutil.c:906 plugins/sudoers/pwutil.c:990
+#: plugins/sudoers/pwutil.c:1045 plugins/sudoers/pwutil.c:1100
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "Die Gruppenliste für %s können nicht zwischengespeichert werden"
+
+#: plugins/sudoers/pwutil.c:979
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "Die Gruppen für %s können nicht eingelesen werden"
+
+#: plugins/sudoers/pwutil.c:1089
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "Die Gruppen für %s können nicht geparst werden"
+
+#: plugins/sudoers/set_perms.c:120 plugins/sudoers/set_perms.c:457
+#: plugins/sudoers/set_perms.c:870 plugins/sudoers/set_perms.c:1186
+#: plugins/sudoers/set_perms.c:1490
+msgid "perm stack overflow"
+msgstr "Stack-Überlauf der Zugriffsrechte"
+
+#: plugins/sudoers/set_perms.c:131 plugins/sudoers/set_perms.c:387
+#: plugins/sudoers/set_perms.c:468 plugins/sudoers/set_perms.c:736
+#: plugins/sudoers/set_perms.c:881 plugins/sudoers/set_perms.c:1109
+#: plugins/sudoers/set_perms.c:1197 plugins/sudoers/set_perms.c:1422
+#: plugins/sudoers/set_perms.c:1501 plugins/sudoers/set_perms.c:1592
+msgid "perm stack underflow"
+msgstr "Stack-Bereichsunterschreitung der Zugriffsrechte"
+
+#: plugins/sudoers/set_perms.c:191 plugins/sudoers/set_perms.c:515
+#: plugins/sudoers/set_perms.c:1251 plugins/sudoers/set_perms.c:1535
+msgid "unable to change to root gid"
+msgstr "Wechsel zur root-GID ist nicht möglich"
+
+#: plugins/sudoers/set_perms.c:282 plugins/sudoers/set_perms.c:612
+#: plugins/sudoers/set_perms.c:1013 plugins/sudoers/set_perms.c:1328
+msgid "unable to change to runas gid"
+msgstr "Wechsel zur runas-UID ist nicht möglich"
+
+#: plugins/sudoers/set_perms.c:287 plugins/sudoers/set_perms.c:617
+#: plugins/sudoers/set_perms.c:1018 plugins/sudoers/set_perms.c:1333
+msgid "unable to set runas group vector"
+msgstr "Die runas-Gruppen können nicht gesetzt werden"
+
+#: plugins/sudoers/set_perms.c:298 plugins/sudoers/set_perms.c:628
+#: plugins/sudoers/set_perms.c:1027 plugins/sudoers/set_perms.c:1342
+msgid "unable to change to runas uid"
+msgstr "Wechsel zur runas-GID ist nicht möglich"
+
+#: plugins/sudoers/set_perms.c:320 plugins/sudoers/set_perms.c:650
+#: plugins/sudoers/set_perms.c:1047 plugins/sudoers/set_perms.c:1362
+msgid "unable to change to sudoers gid"
+msgstr "Wechsel zur sudoers-GID ist nicht möglich"
+
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579
+msgid "too many processes"
+msgstr "Zu viele Prozesse"
+
+#: plugins/sudoers/solaris_audit.c:62
+msgid "unable to get current working directory"
+msgstr "Das aktuelle Arbeitsverzeichnis kann nicht bestimmt werden"
+
+#: plugins/sudoers/solaris_audit.c:70
+#, c-format
+msgid "truncated audit path ctx->user.cmnd: %s"
+msgstr "Audit-Pfad ctx->user.cmnd abgeschnitten: %s"
+
+#: plugins/sudoers/solaris_audit.c:77
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "Audit-Pfad argv[0] abgeschnitten: %s"
+
+#: plugins/sudoers/sssd.c:581
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "Die SSS-Quelle kann nicht initialisiert werden. Ist SSSD auf dem Rechner installiert?"
+
+#: plugins/sudoers/sssd.c:589 plugins/sudoers/sssd.c:598
+#: plugins/sudoers/sssd.c:607 plugins/sudoers/sssd.c:616
+#: plugins/sudoers/sssd.c:625
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "Das Symbol »%s« kann in %s nicht gefunden werden"
+
+#: plugins/sudoers/sudoers.c:250
+#, c-format
+msgid "unable to get defaults from %s"
+msgstr "Kann die Defaults von »%s« nicht bekommen"
+
+#: plugins/sudoers/sudoers.c:259
+msgid "no valid sudoers sources found, quitting"
+msgstr "Keine gültige sudoers-Quelle gefunden, Programmende"
+
+#: plugins/sudoers/sudoers.c:366
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers gibt an, dass root sudo nicht verwenden darf"
+
+#: plugins/sudoers/sudoers.c:375
+msgid "user not allowed to override closefrom limit"
+msgstr "Der Benutzer darf das »closefrom«-Limit nicht überschreiben"
+
+#: plugins/sudoers/sudoers.c:376
+msgid "you are not permitted to use the -C option"
+msgstr "Sie dürfen die Option -C nicht verwenden"
+
+#: plugins/sudoers/sudoers.c:440
+msgid "no tty"
+msgstr "Kein tty"
+
+#: plugins/sudoers/sudoers.c:441
+msgid "sorry, you must have a tty to run sudo"
+msgstr "Sie müssen ein TTY haben, um sudo zu verwenden"
+
+#: plugins/sudoers/sudoers.c:449
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "Ungültiger Shell für den Benutzer %s: %s"
+
+#: plugins/sudoers/sudoers.c:491
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "Der Benutzer darf das root-Verzeichnis nicht auf »%s« ändern"
+
+#: plugins/sudoers/sudoers.c:493
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "Sie dürfen die Option -R nicht mit dem Kommando »%s« verwenden"
+
+#: plugins/sudoers/sudoers.c:506
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "Der Benutzer darf das Verzeichnis nicht auf %s ändern"
+
+#: plugins/sudoers/sudoers.c:507
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "Sie dürfen die Option -C nicht mit dem Kommando »%s« verwenden"
+
+#: plugins/sudoers/sudoers.c:542
+msgid "command in current directory"
+msgstr "Befehl ist im aktuellen Verzeichnis"
+
+#: plugins/sudoers/sudoers.c:557
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr "»cd\"« ist ein Shell-internes Kommando, das nicht direkt gestartet werden kann."
+
+#: plugins/sudoers/sudoers.c:559
+msgid "the -s option may be used to run a privileged shell."
+msgstr "Die Option »-s« kann zum Start einer privilegierten Shell verwendet werden."
+
+#: plugins/sudoers/sudoers.c:561
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr "Die Option »-D« kann zum Start des Programms im angegebenen Verzeichnis verwendet werden."
+
+#: plugins/sudoers/sudoers.c:570
+msgid "user not allowed to set a command timeout"
+msgstr "Der Benutzer darf keinen Kommand-Timeout angeben"
+
+#: plugins/sudoers/sudoers.c:572
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "Sie dürfen keinen Timeout angeben"
+
+#: plugins/sudoers/sudoers.c:580
+msgid "user not allowed to preserve the environment"
+msgstr "Der Benutzer darf das Environment nicht erhalten"
+
+#: plugins/sudoers/sudoers.c:582
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "Sie dürfen das Environment nicht erhalten"
+
+#: plugins/sudoers/sudoers.c:618
+msgid "no command specified"
+msgstr "Kein Kommando angegeben"
+
+#: plugins/sudoers/sudoers.c:759
+msgid "error setting user-specified environment variables"
+msgstr "Fehler beim Setzen benutzerspezidischer Umgebungsvariablen"
+
+#: plugins/sudoers/sudoers.c:1211
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "»sudoedit« muss nicht mittels »sudo« aufgerufen werden"
+
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:1613
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "Die Datei »%s« kann nicht gelesen werden"
+
+#: plugins/sudoers/sudoers.c:1321 plugins/sudoers/visudo.c:1123
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s ist keine reguläre Datei"
+
+#: plugins/sudoers/sudoers.c:1325 plugins/sudoers/timestamp.c:272 toke.l:1355
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s gehört UID %u, sollte UID %u gehören"
+
+#: plugins/sudoers/sudoers.c:1330 plugins/sudoers/timestamp.c:279 toke.l:1360
+#, c-format
+msgid "%s is world writable"
+msgstr "%s ist für alle beschreibbar (world writable)"
+
+#: plugins/sudoers/sudoers.c:1334 plugins/sudoers/timestamp.c:284 toke.l:1363
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s gehört GID %u, sollte allerdings %u gehören"
+
+#: plugins/sudoers/sudoers.c:1363
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "Nur root kann »-c %s« verwenden"
+
+#: plugins/sudoers/sudoers.c:1382
+#, c-format
+msgid "unknown login class %s"
+msgstr "Unbekannte Anmeldeklasse »%s«"
+
+#: plugins/sudoers/sudoers_cb.c:120 plugins/sudoers/sudoers_cb.c:135
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "Hostname %s kann nicht aufgelöst werden"
+
+#: plugins/sudoers/sudoreplay.c:252
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "Ungültige Filteroption: %s"
+
+#: plugins/sudoers/sudoreplay.c:268
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "Ungültige maximale Wartezeit: %s"
+
+#: plugins/sudoers/sudoreplay.c:291
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "Ungültiger Geschwindigkeitsfaktor: %s"
+
+#: plugins/sudoers/sudoreplay.c:326
+#, c-format
+msgid "invalid time offset %s"
+msgstr "ungültiger Zeitversatz »%s«"
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:340
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/Zeit: %s"
+
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Sudo-Sitzung wird abgespielt: %s"
+
+#: plugins/sudoers/sudoreplay.c:634
+msgid "unable to set tty to raw mode"
+msgstr "TTY konnte nicht in den Raw-Modus versetzt werden"
+
+#: plugins/sudoers/sudoreplay.c:685
+msgid "Warning: your terminal is too small to properly replay the log."
+msgstr "Warnung: Ihr Terminal ist zu klein, um das Protokoll korrekt wiederzugeben."
+
+#: plugins/sudoers/sudoreplay.c:686
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Protokollgeometrie ist %d x %d, die Geometrie Ihres Terminals ist %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:714
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Wiedergabe beendet, eine Taste drücken um das Terminal wiederherzustellen."
+
+#: plugins/sudoers/sudoreplay.c:1217 plugins/sudoers/sudoreplay.c:1247
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "Mehrdeutiger Ausdruck »%s«"
+
+#: plugins/sudoers/sudoreplay.c:1269
+msgid "unmatched ')' in expression"
+msgstr "»)« ohne öffnende Klammer im Ausdruck"
+
+#: plugins/sudoers/sudoreplay.c:1273
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "Unbekannter Suchbegriff »%s«"
+
+#: plugins/sudoers/sudoreplay.c:1288
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s erfordert ein Argument"
+
+#: plugins/sudoers/sudoreplay.c:1298
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "Datum »%s« konnte nicht analysiert werden"
+
+#: plugins/sudoers/sudoreplay.c:1307
+msgid "unmatched '(' in expression"
+msgstr "»(« ohne schließende Klammer im Ausdruck"
+
+#: plugins/sudoers/sudoreplay.c:1309
+msgid "illegal trailing \"or\""
+msgstr "Ungültiges nachgestelltes »or«"
+
+#: plugins/sudoers/sudoreplay.c:1311
+msgid "illegal trailing \"!\""
+msgstr "Ungültiges nachgestelltes »!«"
+
+#: plugins/sudoers/sudoreplay.c:1417
+#, c-format
+msgid "unknown search type %d"
+msgstr "Unbekannter Suchtyp %d"
+
+#: plugins/sudoers/sudoreplay.c:1679
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "Aufruf: %s [-hnRS] [-d Verzeichnis] [-m Max_Wartezeit] [-s Geschwindigkeitsfaktor] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1681
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "Aufruf: %s [-h] [-d Verzeichnis] -l [Suchausdruck]\n"
+
+#: plugins/sudoers/sudoreplay.c:1695
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s – sudo-Sitzungsprotokolle abspielen\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1697
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Optionen:\n"
+" -d, --directory=Verzeichnis gibt ein Verzeichnis für Sitzungsprotokolle an\n"
+" -f, --filter=Filter gibt an, welcher E/A-Typ angezeigt werden soll\n"
+" -h, --help zeigt einen Hilfetext an und beendet\n"
+" das Programm\n"
+" -l, --list zeigt verfügbare Sitzungs-IDs an, die mit dem\n"
+" Ausdruck übereinstimmen\n"
+" -m, --max-wait=Zahl gibt die maximale Wartezeit zwischen Ereignissen\n"
+" in Sekunden an\n"
+" -n, --non-interactive keine Prompts, Sitzung wird auf die Standard-\n"
+" Ausgabe gesendet\n"
+" -R, --no-resize Terminal-Größe wird nicht verändert\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=Zahl beschleunigt oder verlangsamt die Wiedergabe\n"
+" -V, --version zeigt Versionsinformationen an und beendet\n"
+" das Programm"
+
+#: plugins/sudoers/testsudoers.c:392
+#, c-format
+msgid ""
+"\n"
+"Invalid shell for user %s: %s\n"
+msgstr ""
+"\n"
+"Ungültige Shell für den Benutzer %s: %s\n"
+
+#: plugins/sudoers/testsudoers.c:411
+msgid ""
+"\n"
+"Password required"
+msgstr ""
+"\n"
+"Ein Passwort ist notwendig"
+
+#: plugins/sudoers/testsudoers.c:422
+msgid ""
+"\n"
+"Parse error"
+msgstr ""
+"\n"
+"Syntax-Fehler"
+
+#: plugins/sudoers/testsudoers.c:425
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Befehl erlaubt"
+
+#: plugins/sudoers/testsudoers.c:428
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Befehl verweigert"
+
+#: plugins/sudoers/testsudoers.c:431
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Befehl nicht erkannt"
+
+#: plugins/sudoers/timestamp.c:364 plugins/sudoers/timestamp.c:711
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "Die Zeitstempeldatei kann nicht auf %lld Bytes abgeschnitten werden"
+
+#: plugins/sudoers/timestamp.c:908
+msgid "ignoring time stamp from the future"
+msgstr "Zeitstempel aus der Zukunft wird ignoriert"
+
+#: plugins/sudoers/timestamp.c:931
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "Zeitstempel ist zu weit in der Zukunft: %20.20s"
+
+#: plugins/sudoers/timestamp.c:1067
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "Die Zeitstempeldatei »%s« kann nicht gesperrt werden"
+
+#: plugins/sudoers/timestamp.c:1114
+#, c-format
+msgid "%s:%d:%d timestampowner: unknown user %s"
+msgstr "%s:%d:%d: timstampowner: unbekannter Benutzer »%s«"
+
+#: plugins/sudoers/toke_util.c:159
+msgid "sudoedit should not be specified with a path"
+msgstr "»sudoedit« sollte nicht mit einem Pfad angegeben werden"
+
+#: plugins/sudoers/visudo.c:308 plugins/sudoers/visudo.c:714
+#, c-format
+msgid "press return to edit %s: "
+msgstr "Drücken Sie die Eingabetaste, um %s zu bearbeiten: "
+
+#: plugins/sudoers/visudo.c:323
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "Inhalt der Editor-Sitzung bleibt in »%s« erhalten"
+
+#: plugins/sudoers/visudo.c:401
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "Der angegebene Editor (%s) ist nicht vorhanden"
+
+#: plugins/sudoers/visudo.c:406
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "Kein Editor gefunden (Pfad zum Editor = %s)"
+
+#: plugins/sudoers/visudo.c:494 plugins/sudoers/visudo.c:786
+#, c-format
+msgid "unable to stat %s"
+msgstr "stat konnte nicht auf %s angewendet werden"
+
+#: plugins/sudoers/visudo.c:514 plugins/sudoers/visudo.c:522
+msgid "write error"
+msgstr "Schreibfehler"
+
+#: plugins/sudoers/visudo.c:568
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "Anwenden von stat auf die temporäre Datei (%s) gescheitert, %s ist unverändert"
+
+#: plugins/sudoers/visudo.c:575
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "Leere temporäre Datei (%s), %s ist unverändert"
+
+#: plugins/sudoers/visudo.c:581
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "Editor-Aufruf (%s) ist gescheitert, %s ist unverändert"
+
+#: plugins/sudoers/visudo.c:613
+#, c-format
+msgid "%s unchanged"
+msgstr "%s unverändert"
+
+#: plugins/sudoers/visudo.c:661
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "Erneutes Öffnen der temporären Datei (%s) gescheitert, %s ist unverändert."
+
+#: plugins/sudoers/visudo.c:674
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "Analyse der temporären Datei (%s) gescheitert, unbekannter Fehler"
+
+#: plugins/sudoers/visudo.c:760 plugins/sudoers/visudo.c:790
+#: plugins/sudoers/visudo.c:797
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "Festlegen von (uid, gid) von %s auf (%u, %u) gescheitert"
+
+#: plugins/sudoers/visudo.c:825
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s und %s befinden sich nicht im gleichen Dateisystem, werden mit mv umbenannt"
+
+#: plugins/sudoers/visudo.c:836
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "Befehl gescheitert: »%s %s %s«, %s unverändert"
+
+#: plugins/sudoers/visudo.c:843
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "Fehler beim Umbenennen von %s, %s unverändert"
+
+#: plugins/sudoers/visudo.c:864
+msgid "What now? "
+msgstr "Was jetzt? "
+
+#: plugins/sudoers/visudo.c:878
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Optionen sind:\n"
+" sudoers-Datei (e)rneut bearbeiten\n"
+" Beenden, ohne die Änderungen an der sudoers-Datei zu speichern (mit x)\n"
+" Beenden und Änderungen an der sudoers-Datei speichern (mit Q, VORSICHT!)\n"
+
+#: plugins/sudoers/visudo.c:923
+#, c-format
+msgid "unable to run %s"
+msgstr "%s konnte nicht ausgeführt werden"
+
+#: plugins/sudoers/visudo.c:954
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: Falsche Besitzer-(uid, gid), sollte (%u, %u) sein\n"
+
+#: plugins/sudoers/visudo.c:965
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: Falsche Zugriffsrechte, sollte Modus 0%o sein\n"
+
+#: plugins/sudoers/visudo.c:1017 plugins/sudoers/visudo.c:1024
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: Analyse OK\n"
+
+#: plugins/sudoers/visudo.c:1043
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s ist in Verwendung, versuchen Sie es später erneut"
+
+# XXX
+#: plugins/sudoers/visudo.c:1047
+msgid "Edit anyway? [y/N]"
+msgstr "Trotzdem ändern? [y/N]"
+
+#: plugins/sudoers/visudo.c:1206
+msgid "the -x option will be removed in a future release"
+msgstr "Die Option »-x» wird in einer zukünftigen Version entfernt"
+
+#: plugins/sudoers/visudo.c:1208
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "Bitte verwenden Sie stattdessen das Programm »cvtsudoers«"
+
+#: plugins/sudoers/visudo.c:1228
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "Warnung: %s:%d:%d: nicht verwendet: %s »%s«"
+
+#: plugins/sudoers/visudo.c:1341
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s – Die sudoers-Datei sicher bearbeiten\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1343
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -I, --no-includes do not edit include files\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Optionen:\n"
+" -c, --check nur den Prüf-Modus verwenden\n"
+" -f, --file=sudoers gibt den Namen der sudoers Datei an\n"
+" -h, --help diese Hilfe anzeigen und beenden\n"
+" -I, --no-includes Include-Dateien nicht editieren\n"
+" -q, --quiet weniger ausführliche Syntaxfehler-Meldungen\n"
+" -s, --strict strikte Syntax-Prüfung\n"
+" -V, --version Versionsinformation anzeigen und beenden\n"
+
+#: toke.l:184
+msgid "empty string"
+msgstr "leere Zeichenkette"
+
+#: toke.l:196 toke.l:566
+msgid "empty group"
+msgstr "leere Gruppe"
+
+#: toke.l:206 toke.l:564
+msgid "empty netgroup"
+msgstr "leere Netgroup"
+
+#: toke.l:284
+msgid "unterminated regular expression"
+msgstr "nicht abgeschlossener regulärer Ausdruck"
+
+#: toke.l:358 toke.l:370 toke.l:382 toke.l:398 toke.l:417 toke.l:457
+msgid "invalid line continuation"
+msgstr "Ungültiger Zeilenfortsetzung"
+
+#: toke.l:603 toke.l:615
+msgid "invalid IPv6 address"
+msgstr "Ungültiges IPv6 Adresse: %s"
+
+#: toke.l:863
+msgid "unexpected line break in string"
+msgstr "unerwarteter Zeilenumbruch in Zeichenkette"
+
+#: toke.l:982
+msgid "ignoring editor backup file"
+msgstr "Ignoriere die Backup Datei des Editors"
+
+#: toke.l:985
+msgid "ignoring file name containing '.'"
+msgstr "Ignoriere Dateiname mit '.'"
+
+#: toke.l:1310
+msgid "too many levels of includes"
+msgstr "Zu viele geschachtelte include-Einträge"
diff --git a/plugins/sudoers/po/el.mo b/plugins/sudoers/po/el.mo
new file mode 100644
index 0000000..9cae8b9
--- /dev/null
+++ b/plugins/sudoers/po/el.mo
Binary files differ
diff --git a/plugins/sudoers/po/el.po b/plugins/sudoers/po/el.po
new file mode 100644
index 0000000..781bb8e
--- /dev/null
+++ b/plugins/sudoers/po/el.po
@@ -0,0 +1,1718 @@
+# Translation of sudoers to Greek
+# Todd C. Miller &lt;Todd.Miller@courtesan.com&gt;, 2011-2013
+# This file is distributed under the same license as the sudo package.
+# Dimitris Spingos (Δημήτρης Σπίγγος) <dmtrs32@gmail.com>, 2014.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers-1.8.10b3\n"
+"Report-Msgid-Bugs-To: http://www.sudo.ws/bugs\n"
+"POT-Creation-Date: 2014-02-07 15:13-0700\n"
+"PO-Revision-Date: 2014-06-04 08:01+0300\n"
+"Last-Translator: Dimitris Spingos (Δημήτρης Σπίγγος) <dmtrs32@gmail.com>\n"
+"Language-Team: Greek <team@lists.gnome.gr>\n"
+"Language: el\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Virtaal 0.7.0\n"
+
+#: confstr.sh:2
+msgid "Password:"
+msgstr "Κωδικός πρόσβασης:"
+
+#: confstr.sh:3
+msgid "*** SECURITY information for %h ***"
+msgstr "*** Πληροφορίες ΑΣΦΑΛΕΙΑΣ για το %h ***"
+
+#: confstr.sh:4
+msgid "Sorry, try again."
+msgstr "Συγνώμη, δοκιμάστε ξανά."
+
+#: plugins/sudoers/alias.c:136
+#, c-format
+msgid "Alias `%s' already defined"
+msgstr "Έχει ήδη οριστεί το ψευδώνυμο `%s'"
+
+#: plugins/sudoers/auth/bsdauth.c:75
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "αδύνατη η λήψη κλάσης σύνδεσης για τον χρήστη %s"
+
+#: plugins/sudoers/auth/bsdauth.c:81
+msgid "unable to begin bsd authentication"
+msgstr "αδύνατη η έναρξη της πιστοποίησης bsd"
+
+#: plugins/sudoers/auth/bsdauth.c:89
+msgid "invalid authentication type"
+msgstr "άκυρος τύπος πιστοποίησης"
+
+#: plugins/sudoers/auth/bsdauth.c:98
+msgid "unable to initialize BSD authentication"
+msgstr "αδύνατη η αρχικοποίηση της πιστοποίησης BSD"
+
+#: plugins/sudoers/auth/fwtk.c:59
+msgid "unable to read fwtk config"
+msgstr "αδύνατη η ανάγνωση του fwtk config"
+
+#: plugins/sudoers/auth/fwtk.c:64
+msgid "unable to connect to authentication server"
+msgstr "αδύνατη η σύνδεση με τον εξυπηρετητή πιστοποίησης"
+
+#: plugins/sudoers/auth/fwtk.c:70 plugins/sudoers/auth/fwtk.c:94
+#: plugins/sudoers/auth/fwtk.c:127
+msgid "lost connection to authentication server"
+msgstr "απώλεια σύνδεσης με τον εξυπηρετητή πιστοποίησης"
+
+#: plugins/sudoers/auth/fwtk.c:74
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"σφάλμα εξυπηρετητή πιστοποίησης:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:116
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: αδύνατη η μετατροπή της αρχής ασφάλειας σε συμβολοσειρά ('%s'): %s"
+
+#: plugins/sudoers/auth/kerb5.c:159
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: αδύνατη η ανάλυση του '%s': %s"
+
+#: plugins/sudoers/auth/kerb5.c:169
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: αδύνατη η επίλυση κρυφής μνήμης διαπιστευτήριων: %s"
+
+#: plugins/sudoers/auth/kerb5.c:217
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: αδύνατη η κατανομή επιλογών: %s"
+
+#: plugins/sudoers/auth/kerb5.c:233
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: αδύνατη η λήψη διαπιστευτηρίων: %s"
+
+#: plugins/sudoers/auth/kerb5.c:246
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: αδύνατη η αρχικοποίηση κρυφής μνήμης διαπιστευτηρίων: %s"
+
+#: plugins/sudoers/auth/kerb5.c:250
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: αδύνατη η αποθήκευση διαπιστευτηρίων στην κρυφή μνήμη: %s"
+
+#: plugins/sudoers/auth/kerb5.c:315
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: αδύνατη η λήψη αρχής ασφάλειας του οικοδεσπότη: %s"
+
+#: plugins/sudoers/auth/kerb5.c:330
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: Αδύνατη η επιβεβαίωση TGT! Πιθανή επίθεση!: %s"
+
+#: plugins/sudoers/auth/pam.c:98
+msgid "unable to initialize PAM"
+msgstr "αδύνατη η αρχικοποίηση του PAM"
+
+#: plugins/sudoers/auth/pam.c:149
+msgid "account validation failure, is your account locked?"
+msgstr "αποτυχία επικύρωσης λογαριασμού, είναι κλειδωμένος ο λογαριασμός σας;"
+
+#: plugins/sudoers/auth/pam.c:153
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Ο λογαριασμός ή ο κωδικός πρόσβασης έχει λήξει, επαναφέρτε τον κωδικό πρόσβασής σας και ξαναδοκιμάστε"
+
+#: plugins/sudoers/auth/pam.c:161
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "αδύνατη η αλλαγή του ληγμένου κωδικού πρόσβασης: %s"
+
+#: plugins/sudoers/auth/pam.c:166
+msgid "Password expired, contact your system administrator"
+msgstr "Ο κωδικός πρόσβασης έχει λήξει, επικοινωνήστε με τον διαχειριστή του συστήματος"
+
+#: plugins/sudoers/auth/pam.c:170
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Ο λογαριασμός έχει λήξει ή το PAM config στερείται μιας ενότητας \"λογαριασμού\" για sudo, επικοινωνήστε με τον διαχειριστή του συστήματός σας"
+
+#: plugins/sudoers/auth/pam.c:187
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Σφάλμα πιστοποίησης PAM: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:103 plugins/sudoers/visudo.c:222
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "δεν υπάρχετε στη βάση δεδομένων %s"
+
+#: plugins/sudoers/auth/securid5.c:80
+msgid "failed to initialise the ACE API library"
+msgstr "αποτυχία αρχικοποίησης της βιβλιοθήκης ACE API"
+
+#: plugins/sudoers/auth/securid5.c:106
+msgid "unable to contact the SecurID server"
+msgstr "αδύνατη η επικοινωνία με τον εξυπηρετητή SecurID"
+
+#: plugins/sudoers/auth/securid5.c:115
+msgid "User ID locked for SecurID Authentication"
+msgstr "Το αναγνωριστικό του χρήστη για πιστοποίηση SecurID είναι κλειδωμένο"
+
+#: plugins/sudoers/auth/securid5.c:119 plugins/sudoers/auth/securid5.c:170
+msgid "invalid username length for SecurID"
+msgstr "άκυρο μήκος ονόματος χρήστη για SecurID"
+
+#: plugins/sudoers/auth/securid5.c:123 plugins/sudoers/auth/securid5.c:175
+msgid "invalid Authentication Handle for SecurID"
+msgstr "άκυρη διαχείριση πιστοποίησης για SecurID"
+
+#: plugins/sudoers/auth/securid5.c:127
+msgid "SecurID communication failed"
+msgstr "αποτυχία επικοινωνίας SecurID"
+
+#: plugins/sudoers/auth/securid5.c:131 plugins/sudoers/auth/securid5.c:214
+msgid "unknown SecurID error"
+msgstr "άγνωστο σφάλμα SecurID"
+
+#: plugins/sudoers/auth/securid5.c:165
+msgid "invalid passcode length for SecurID"
+msgstr "άκυρο μήκος κωδικού περάσματος για το SecurID"
+
+#: plugins/sudoers/auth/sia.c:108
+msgid "unable to initialize SIA session"
+msgstr "αδύνατη η αρχικοποίηση της συνεδρίας SIA"
+
+#: plugins/sudoers/auth/sudo_auth.c:119
+msgid "invalid authentication methods"
+msgstr "άκυρες μέθοδοι πιστοποίησης"
+
+#: plugins/sudoers/auth/sudo_auth.c:120
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Άκυρες μεταγλωττισμένες μέθοδοι πιστοποίησης στο sudo! Δεν μπορείτε να αναμίξετε αυτόνομη και μη αυτόνομη πιστοποίηση."
+
+#: plugins/sudoers/auth/sudo_auth.c:203
+msgid "no authentication methods"
+msgstr "δεν υπάρχουν μέθοδοι πιστοποίησης"
+
+#: plugins/sudoers/auth/sudo_auth.c:205
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Δεν υπάρχουν μεταγλωττισμένες μέθοδοι πιστοποίησης στο sudo! Αν θέλετε να απενεργοποιήσετε την πιστοποίηση, χρησιμοποιήστε την επιλογή ρύθμισης --disable-authentication."
+
+#: plugins/sudoers/auth/sudo_auth.c:389
+msgid "Authentication methods:"
+msgstr "Μέθοδοι πιστοποίησης:"
+
+#: plugins/sudoers/bsm_audit.c:91 plugins/sudoers/bsm_audit.c:158
+msgid "Could not determine audit condition"
+msgstr "Αδυναμία εντοπισμού συνθήκης ελέγχου"
+
+#: plugins/sudoers/bsm_audit.c:134 plugins/sudoers/bsm_audit.c:199
+msgid "unable to commit audit record"
+msgstr "αδύνατη η υποβολή εγγραφής ελέγχου"
+
+#: plugins/sudoers/check.c:189
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Εμπιστευόμαστε ότι έχετε δεχτεί τις συνηθισμένες οδηγίες από τον\n"
+"διαχειριστή του τοπικού συστήματος. Συνήθως συμπυκνώνεται σε τρία πράγματα:\n"
+"\n"
+" #1) Σεβασμός της ιδιωτικότητας των άλλων.\n"
+" #2) Σκεφτείτε πριν πληκτρολογήσετε.\n"
+" #3) Η μεγάλη ισχύς συνυπάρχει με τη μεγάλη ευθύνη.\n"
+"\n"
+
+#: plugins/sudoers/check.c:232 plugins/sudoers/check.c:238
+#: plugins/sudoers/sudoers.c:562 plugins/sudoers/sudoers.c:588
+#, c-format
+msgid "unknown uid: %u"
+msgstr "άγνωστο uid: %u"
+
+#: plugins/sudoers/check.c:235 plugins/sudoers/policy.c:657
+#: plugins/sudoers/sudoers.c:850 plugins/sudoers/testsudoers.c:211
+#: plugins/sudoers/testsudoers.c:363
+#, c-format
+msgid "unknown user: %s"
+msgstr "άγνωστος χρήστης: %s"
+
+#: plugins/sudoers/def_data.c:27
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Ευκολία Syslog αν το syslog χρησιμοποιείται για καταγραφή: %s"
+
+#: plugins/sudoers/def_data.c:31
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Προτεραιότητα χρήσης Syslog, όταν ο χρήστης πιστοποιείται επιτυχώς: %s"
+
+#: plugins/sudoers/def_data.c:35
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Προτεραιότητα χρήσης Syslog, όταν ο χρήστης πιστοποιείται ανεπιτυχώς: %s"
+
+#: plugins/sudoers/def_data.c:39
+msgid "Put OTP prompt on its own line"
+msgstr "Τοποθέτηση της προτροπής OTP στη δική της γραμμή"
+
+#: plugins/sudoers/def_data.c:43
+msgid "Ignore '.' in $PATH"
+msgstr "Παράβλεψη '.' στο $PATH"
+
+#: plugins/sudoers/def_data.c:47
+msgid "Always send mail when sudo is run"
+msgstr "Να στέλνετε πάντα μήνυμα όταν εκτελείται το sudo"
+
+#: plugins/sudoers/def_data.c:51
+msgid "Send mail if user authentication fails"
+msgstr "Να στέλνετε μήνυμα αν η πιστοποίηση χρήστη αποτύχει"
+
+#: plugins/sudoers/def_data.c:55
+msgid "Send mail if the user is not in sudoers"
+msgstr "Να στέλνετε μήνυμα αν ο χρήστης δεν είναι στους χρήστες sudo"
+
+#: plugins/sudoers/def_data.c:59
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Να στέλνετε μήνυμα αν ο χρήστης δεν είναι στους χρήστες sudo για αυτόν τον οικοδεσπότη"
+
+#: plugins/sudoers/def_data.c:63
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Να στέλνετε μήνυμα αν ο χρήστης δεν επιτρέπεται να εκτελέσει μια εντολή"
+
+#: plugins/sudoers/def_data.c:67
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Να χρησιμοποιείται ξεχωριστή χρονική σήμανση για κάθε χρήστη/σύνθετο tty"
+
+#: plugins/sudoers/def_data.c:71
+msgid "Lecture user the first time they run sudo"
+msgstr "Να δίνονται οδηγίες στον χρήστη την πρώτη φορά που εκτελεί sudo"
+
+#: plugins/sudoers/def_data.c:75
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Το αρχείο που περιέχει τις οδηγίες sudo: %s"
+
+#: plugins/sudoers/def_data.c:79
+msgid "Require users to authenticate by default"
+msgstr "Να απαιτείται από τους χρήστες να πιστοποιούνται από προεπιλογή"
+
+#: plugins/sudoers/def_data.c:83
+msgid "Root may run sudo"
+msgstr "Ο υπερχρήστης μπορεί να εκτελεί sudo"
+
+#: plugins/sudoers/def_data.c:87
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Καταγραφή του ονόματος οικοδεσπότη στο αρχείο καταγραφής (non-syslog)"
+
+#: plugins/sudoers/def_data.c:91
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Καταγραφή του έτους στο αρχείο καταγραφής (non-syslog)"
+
+#: plugins/sudoers/def_data.c:95
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Αν το sudo κλήθηκε χωρίς ορίσματα, να αρχίσει ένα κέλυφος"
+
+#: plugins/sudoers/def_data.c:99
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Ορίστε το $HOME του προοριζόμενου χρήστη όταν ξεκινάτε ένα κέλυφος με -s"
+
+#: plugins/sudoers/def_data.c:103
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Να ορίζεται πάντα το $HOME στον προσωπικό κατάλογο του προοριζόμενου χρήστη"
+
+#: plugins/sudoers/def_data.c:107
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Να επιτρέπεται η συγκέντρωση κάποιων πληροφοριών για να δίνονται χρήσιμα μηνύματα σφαλμάτων"
+
+#: plugins/sudoers/def_data.c:111
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Να απαιτούνται πλήρως χαρακτηρισμένα ονόματα οικοδεσπότη στο αρχείο χρηστών sudo"
+
+#: plugins/sudoers/def_data.c:115
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Να ειδοποιείται ο χρήστης όταν εισάγει έναν εσφαλμένο κωδικό πρόσβασης"
+
+#: plugins/sudoers/def_data.c:119
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Να επιτρέπεται στον χρήστη να εκτελεί sudo μόνο αν έχει ένα tty"
+
+#: plugins/sudoers/def_data.c:123
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Το Visudo θα σεβαστεί τη μεταβλητή περιβάλλοντος του EDITOR"
+
+#: plugins/sudoers/def_data.c:127
+msgid "Prompt for root's password, not the users's"
+msgstr "Να ζητιέται ο κωδικός πρόσβασης του υπερχρήστη, όχι του χρήστη"
+
+#: plugins/sudoers/def_data.c:131
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Να ζητιέται ο κωδικός πρόσβασης των χρηστών runas_default, όχι των χρηστών"
+
+#: plugins/sudoers/def_data.c:135
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Να ζητιέται ο κωδικός πρόσβασης του προοριζόμενου χρήστη, όχι των χρηστών"
+
+#: plugins/sudoers/def_data.c:139
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Να εφαρμόζονται οι προεπιλογές στην κλάση σύνδεσης του προοριζόμενου χρήστη αν υπάρχει κάποιες"
+
+#: plugins/sudoers/def_data.c:143
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Να ορίζονται οι μεταβλητές περιβάλλοντος LOGNAME και USER"
+
+#: plugins/sudoers/def_data.c:147
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Να ορίζεται μόνο το ενεργό uid του προοριζόμενου χρήστη, όχι το πραγματικό uid"
+
+#: plugins/sudoers/def_data.c:151
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Να μην αρχικοποιείται το διάνυσμα ομάδας σε αυτό του προοριζόμενου χρήστη"
+
+#: plugins/sudoers/def_data.c:155
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Το μήκος στο οποίο θα αναδιπλώνονται οι γραμμές του αρχείου καταγραφής (0 για χωρίς αναδίπλωση): %u"
+
+#: plugins/sudoers/def_data.c:159
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Όριο χρόνου χρονικής σήμανσης πιστοποίησης: %.1f λεπτά"
+
+#: plugins/sudoers/def_data.c:163
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Όριο χρόνου προτροπής κωδικού πρόσβασης: %.1f λεπτά"
+
+#: plugins/sudoers/def_data.c:167
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Αριθμός προσπαθειών για να εισάγετε έναν κωδικό πρόσβασης: %u"
+
+#: plugins/sudoers/def_data.c:171
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Χρησιμοποιήστε umask ή 0777 για να χρησιμοποιήσετε του χρήστη: 0%o"
+
+#: plugins/sudoers/def_data.c:175
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Διαδρομή για το αρχείο καταγραφής: %s"
+
+#: plugins/sudoers/def_data.c:179
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Διαδρομή για το πρόγραμμα αλληλογραφίας: %s"
+
+#: plugins/sudoers/def_data.c:183
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Σημαίες για το πρόγραμμα αλληλογραφίας: %s"
+
+#: plugins/sudoers/def_data.c:187
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Διεύθυνση αποστολής αλληλογραφίας προς: %s"
+
+#: plugins/sudoers/def_data.c:191
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Διεύθυνση λήψης αλληλογραφίας από: %s"
+
+#: plugins/sudoers/def_data.c:195
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Γραμμή θέματος για μηνύματα αλληλογραφίας: %s"
+
+#: plugins/sudoers/def_data.c:199
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Εσφαλμένο μήνυμα κωδικού πρόσβασης: %s"
+
+#: plugins/sudoers/def_data.c:203
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Διαδρομή για τον κατάλογο κατάστασης οδηγιών: %s"
+
+#: plugins/sudoers/def_data.c:207
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Διαδρομή για τον κατάλογο χρονικής σήμανσης πιστοποίησης: %s"
+
+#: plugins/sudoers/def_data.c:211
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Κάτοχος καταλόγου χρονικής σήμανσης πιστοποίησης: %s"
+
+#: plugins/sudoers/def_data.c:215
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Οι χρήστες αυτής της ομάδας εξαιρούνται από τον κωδικό πρόσβασης και της απαιτήσεις PATH: %s"
+
+#: plugins/sudoers/def_data.c:219
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Προτροπή προεπιλεγμένου κωδικού πρόσβασης: %s"
+
+#: plugins/sudoers/def_data.c:223
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Αν οριστεί, η προτροπή περάσματος θα αντικαταστήσει την προτροπή συστήματος σε όλες τις περιπτώσεις."
+
+#: plugins/sudoers/def_data.c:227
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Προεπιλεγμένος χρήστης για να εκτελεί εντολές ως: %s"
+
+#: plugins/sudoers/def_data.c:231
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Τιμή που θα αντικαθιστά τη $PATH χρήστη με: %s"
+
+#: plugins/sudoers/def_data.c:235
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Διαδρομή για τον επεξεργαστή για χρήση από το visudo: %s"
+
+#: plugins/sudoers/def_data.c:239
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Πότε θα απαιτείται κωδικός πρόσβασης για τον 'κατάλογο' ψευδοεντολών: %s"
+
+#: plugins/sudoers/def_data.c:243
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Πότε θα απαιτείται κωδικός πρόσβασης για 'επιβεβαίωση' ψευδοεντολής: %s"
+
+#: plugins/sudoers/def_data.c:247
+msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+msgstr "Να προφορτώνονται οι εικονικές συναρτήσεις εκτέλεσης στη βιβλιοθήκη sudo_noexec"
+
+#: plugins/sudoers/def_data.c:251
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Αν ο κατάλογος LDAP είναι ανεβασμένος, παραβλέπουμε το τοπικό αρχείο χρηστών sudo."
+
+#: plugins/sudoers/def_data.c:255
+#, fuzzy, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Οι περιγραφείς αρχείων &gt;= %d να είναι κλειστοί πριν την εκτέλεση μιας εντολής"
+
+#: plugins/sudoers/def_data.c:259
+msgid "If set, users may override the value of `closefrom' with the -C option"
+msgstr "Αν οριστεί, οι χρήστες μπορούν να αντικαθιστούν την τιμή του `closefrom' με την επιλογή -C"
+
+#: plugins/sudoers/def_data.c:263
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Να επιτρέπεται στους χρήστες να ορίζουν ελεύθερες μεταβλητές περιβάλλοντος"
+
+#: plugins/sudoers/def_data.c:267
+msgid "Reset the environment to a default set of variables"
+msgstr "Να επαναρρυθμίζεται το περιβάλλον σε ένα προεπιλεγμένο σύνολο μεταβλητών"
+
+#: plugins/sudoers/def_data.c:271
+msgid "Environment variables to check for sanity:"
+msgstr "Οι μεταβλητές περιβάλλοντος που θα ελέγχονται για ακεραιότητα:"
+
+#: plugins/sudoers/def_data.c:275
+msgid "Environment variables to remove:"
+msgstr "Οι μεταβλητές περιβάλλοντος προς αφαίρεση:"
+
+#: plugins/sudoers/def_data.c:279
+msgid "Environment variables to preserve:"
+msgstr "Οι μεταβλητές περιβάλλοντος για διατήρηση:"
+
+#: plugins/sudoers/def_data.c:283
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "Ο ρόλος του SELinux που θα χρησιμοποιηθεί στο νέο περιεχόμενο ασφάλειας: %s"
+
+#: plugins/sudoers/def_data.c:287
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "Ο τύπος SELinux που θα χρησιμοποιηθεί στο νέο περιεχόμενο ασφάλειας: %s"
+
+#: plugins/sudoers/def_data.c:291
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Η διαδρομή προς το αρχείο περιβάλλοντος που είναι ειδικό για sudo: %s"
+
+#: plugins/sudoers/def_data.c:295
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Οι τοπικές ρυθμίσεις που θα χρησιμοποιηθούν κατά την ανάλυση των χρηστών sudo: %s"
+
+#: plugins/sudoers/def_data.c:299
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Να επιτρέπεται στο sudo να ζητά κωδικό πρόσβασης ακόμα κι αν θα είναι ορατό"
+
+#: plugins/sudoers/def_data.c:303
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Να παρέχεται οπτική ανάδραση στην προτροπή κωδικού πρόσβασης όταν υπάρχει είσοδος χρήστη"
+
+#: plugins/sudoers/def_data.c:307
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Να χρησιμοποιείται γρηγορότερη επέκταση (globbing) που είναι λιγότερο ακριβές, αλλά δεν έχει πρόσβαση στο σύστημα αρχείων"
+
+#: plugins/sudoers/def_data.c:311
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "Η umask που ορίστηκε στους χρήστες sudo θα αντικαταστήσει αυτή του χρήστη, ακόμα κι αν δίνει περισσότερα δικαιώματα."
+
+#: plugins/sudoers/def_data.c:315
+msgid "Log user's input for the command being run"
+msgstr "Να καταγράφεται η είσοδος χρήστη για την εκτελούμενη εντολή"
+
+#: plugins/sudoers/def_data.c:319
+msgid "Log the output of the command being run"
+msgstr "Να καταγράφεται η έξοδος της εκτελούμενης εντολής"
+
+#: plugins/sudoers/def_data.c:323
+msgid "Compress I/O logs using zlib"
+msgstr "Συμπίεση καταγραφών εισόδου/εξόδου χρησιμοποιώντας το zlib"
+
+#: plugins/sudoers/def_data.c:327
+msgid "Always run commands in a pseudo-tty"
+msgstr "Να εκτελούνται πάντα εντολές σε ψευδο-tty"
+
+#: plugins/sudoers/def_data.c:331
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Πρόσθετο για υποστήριξη ομάδας μη Γιούνιξ: %s"
+
+#: plugins/sudoers/def_data.c:335
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Κατάλογος στον οποίο αποθηκεύονται οι καταγραφές εισόδου/εξόδου: %s"
+
+#: plugins/sudoers/def_data.c:339
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Αρχείο στο οποίο θα αποθηκεύεται η καταγραφή εισόδου/εξόδου: %s"
+
+#: plugins/sudoers/def_data.c:343
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Να προστίθεται μια καταχώριση στο αρχείο utmp/utmpx κατά την εκχώρηση ενός pty"
+
+#: plugins/sudoers/def_data.c:347
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Να ορίζεται ο χρήστης στο utmp στον χρήστη runas, να μην καλείται ο χρήστης"
+
+#: plugins/sudoers/def_data.c:351
+msgid "Set of permitted privileges"
+msgstr "Να ορίζονται τα επιτρεπόμενα δικαιώματα"
+
+#: plugins/sudoers/def_data.c:355
+msgid "Set of limit privileges"
+msgstr "Να ορίζονται τα δικαιώματα ορίου"
+
+#: plugins/sudoers/def_data.c:359
+msgid "Run commands on a pty in the background"
+msgstr "Να εκτελούνται εντολές σε ένα pty στο παρασκήνιο"
+
+#: plugins/sudoers/def_data.c:363
+msgid "PAM service name to use"
+msgstr "Το όνομα υπηρεσίας PAM που θα χρησιμοποιηθεί"
+
+#: plugins/sudoers/def_data.c:367
+msgid "PAM service name to use for login shells"
+msgstr "Το όνομα υπηρεσίας PAM που θα χρησιμοποιηθεί για κελύφη σύνδεσης"
+
+#: plugins/sudoers/def_data.c:371
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Να γίνεται προσπάθεια δημιουργίας διαπιστευτηρίων για τον προοριζόμενο χρήστη"
+
+#: plugins/sudoers/def_data.c:375
+msgid "Create a new PAM session for the command to run in"
+msgstr "Να δημιουργείται μια νέα συνεδρία PAM για την εκτελούμενη εντολή"
+
+#: plugins/sudoers/def_data.c:379
+#, c-format
+msgid "Maximum I/O log sequence number: %u"
+msgstr "Μέγιστος αριθμός αλληλουχίας καταγραφών εισόδου/εξόδου: %u"
+
+#: plugins/sudoers/def_data.c:383
+msgid "Enable sudoers netgroup support"
+msgstr "Να ενεργοποιείται η υποστήριξη ομάδας δικτύου στους χρήστες sudo"
+
+#: plugins/sudoers/defaults.c:210 plugins/sudoers/defaults.c:600
+#: plugins/sudoers/visudo_json.c:611 plugins/sudoers/visudo_json.c:647
+#, c-format
+msgid "unknown defaults entry `%s'"
+msgstr "άγνωστες προεπιλογές καταχώρισης `%s'"
+
+#: plugins/sudoers/defaults.c:218 plugins/sudoers/defaults.c:228
+#: plugins/sudoers/defaults.c:248 plugins/sudoers/defaults.c:261
+#: plugins/sudoers/defaults.c:274 plugins/sudoers/defaults.c:287
+#: plugins/sudoers/defaults.c:300 plugins/sudoers/defaults.c:320
+#: plugins/sudoers/defaults.c:330
+#, c-format
+msgid "value `%s' is invalid for option `%s'"
+msgstr "η τιμή `%s' είναι άκυρη για την επιλογή `%s'"
+
+#: plugins/sudoers/defaults.c:221 plugins/sudoers/defaults.c:231
+#: plugins/sudoers/defaults.c:239 plugins/sudoers/defaults.c:256
+#: plugins/sudoers/defaults.c:269 plugins/sudoers/defaults.c:282
+#: plugins/sudoers/defaults.c:295 plugins/sudoers/defaults.c:315
+#: plugins/sudoers/defaults.c:326
+#, c-format
+msgid "no value specified for `%s'"
+msgstr "δεν ορίστηκε τιμή για το `%s'"
+
+#: plugins/sudoers/defaults.c:244
+#, c-format
+msgid "values for `%s' must start with a '/'"
+msgstr "οι τιμές για το `%s' πρέπει να αρχίζουν με ένα '/'"
+
+#: plugins/sudoers/defaults.c:306
+#, c-format
+msgid "option `%s' does not take a value"
+msgstr "η επιλογή `%s' δεν παίρνει τιμή"
+
+#: plugins/sudoers/env.c:288 plugins/sudoers/env.c:293
+#: plugins/sudoers/env.c:395 plugins/sudoers/linux_audit.c:82
+#: plugins/sudoers/policy.c:442 plugins/sudoers/policy.c:449
+#: plugins/sudoers/prompt.c:171 plugins/sudoers/sudoers.c:656
+#: plugins/sudoers/testsudoers.c:241
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "εσωτερικό σφάλμα, υπερχείλιση του %s"
+
+#: plugins/sudoers/env.c:367
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: αλλοιωμένο envp, ασυμφωνία μήκους"
+
+#: plugins/sudoers/env.c:1014
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "συγνώμη, δεν σας επιτρέπετε να ορίσετε τις παρακάτω μεταβλητές περιβάλλοντος: %s"
+
+#: plugins/sudoers/group_plugin.c:94
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "το %s πρέπει να κατέχεται από το uid %d"
+
+#: plugins/sudoers/group_plugin.c:98
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr "το %s πρέπει να είναι εγγράψιμο μόνο από τον κάτοχο"
+
+#: plugins/sudoers/group_plugin.c:105 plugins/sudoers/sssd.c:251
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "αδύνατη η φόρτωση του %s: %s"
+
+#: plugins/sudoers/group_plugin.c:110
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "αδύνατη η εύρεση συμβόλου \"group_plugin\" στο %s"
+
+#: plugins/sudoers/group_plugin.c:115
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: ασύμβατη μεγάλη έκδοση %d του προσθέτου ομάδας, αναμενόταν %d"
+
+#: plugins/sudoers/interfaces.c:116
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Ζεύγη τοπικής διεύθυνσης IP και μάσκας δικτύου:\n"
+
+#: plugins/sudoers/iolog.c:99 plugins/sudoers/iolog.c:112
+#: plugins/sudoers/timestamp.c:227
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "το %s υπάρχει, αλλά δεν είναι κατάλογος (0%o)"
+
+#: plugins/sudoers/iolog.c:109 plugins/sudoers/iolog.c:123
+#: plugins/sudoers/iolog.c:127 plugins/sudoers/timestamp.c:221
+#: plugins/sudoers/timestamp.c:242
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "αδύνατο το mkdir %s"
+
+#: plugins/sudoers/iolog.c:190 plugins/sudoers/sudoers.c:710
+#: plugins/sudoers/sudoreplay.c:342 plugins/sudoers/sudoreplay.c:813
+#: plugins/sudoers/sudoreplay.c:1010 plugins/sudoers/timestamp.c:345
+#: plugins/sudoers/visudo.c:823 plugins/sudoers/visudo_json.c:995
+#: plugins/sudoers/visudo_json.c:1001
+#, c-format
+msgid "unable to open %s"
+msgstr "αδύνατο το άνοιγμα του %s"
+
+#: plugins/sudoers/iolog.c:229 plugins/sudoers/sudoers.c:713
+#: plugins/sudoers/sudoreplay.c:1117
+#, c-format
+msgid "unable to read %s"
+msgstr "αδύνατη η ανάγνωση του %s"
+
+#: plugins/sudoers/iolog.c:259 plugins/sudoers/sudoreplay.c:582
+#: plugins/sudoers/timestamp.c:184
+#, c-format
+msgid "unable to write to %s"
+msgstr "αδύνατη η εγγραφή σε %s"
+
+#: plugins/sudoers/iolog.c:319 plugins/sudoers/iolog.c:512
+#, c-format
+msgid "unable to create %s"
+msgstr "αδύνατη η δημιουργία του %s"
+
+#: plugins/sudoers/ldap.c:406
+msgid "sudo_ldap_conf_add_ports: port too large"
+msgstr "sudo_ldap_conf_add_ports: υπερβολικά μεγάλη θύρα"
+
+#: plugins/sudoers/ldap.c:429
+msgid "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+msgstr "sudo_ldap_conf_add_ports: εκτός χώρου επέκτασης hostbuf"
+
+#: plugins/sudoers/ldap.c:461
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "ανυποστήρικτος τύπος LDAP uri: %s"
+
+#: plugins/sudoers/ldap.c:492
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "αδύνατη η ανάμιξη URIs ldap και ldaps"
+
+#: plugins/sudoers/ldap.c:496 plugins/sudoers/ldap.c:528
+msgid "starttls not supported when using ldaps"
+msgstr "το starttls δεν υποστηρίζεται όταν χρησιμοποιείται το ldaps"
+
+#: plugins/sudoers/ldap.c:514
+msgid "sudo_ldap_parse_uri: out of space building hostbuf"
+msgstr "sudo_ldap_parse_uri: εκτός χώρου δόμησης του hostbuf"
+
+#: plugins/sudoers/ldap.c:595
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "αδύνατη η αρχικοποίηση των cert SSL και db κλειδιών: %s"
+
+#: plugins/sudoers/ldap.c:598
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "πρέπει να ορίσετε το TLS_CERT σε %s για να χρησιμοποιήσετε το SSL"
+
+#: plugins/sudoers/ldap.c:1089
+msgid "unable to get GMT time"
+msgstr "αδύνατη η λήψη χρόνου GMT"
+
+#: plugins/sudoers/ldap.c:1095
+msgid "unable to format timestamp"
+msgstr "αδύνατη η μορφοποίηση της χρονικής σήμανσης"
+
+#: plugins/sudoers/ldap.c:1103
+msgid "unable to build time filter"
+msgstr "αδύνατη η δόμηση φίλτρου χρόνου"
+
+#: plugins/sudoers/ldap.c:1322
+msgid "sudo_ldap_build_pass1 allocation mismatch"
+msgstr "ασυμφωνία κατανομής sudo_ldap_build_pass1"
+
+#: plugins/sudoers/ldap.c:1433
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/ldap.c:1909
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+"\n"
+"Ρόλος LDAP: %s\n"
+
+#: plugins/sudoers/ldap.c:1911
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: UNKNOWN\n"
+msgstr ""
+"\n"
+"Ρόλος LDAP: ΑΓΝΩΣΤΟΣ\n"
+
+#: plugins/sudoers/ldap.c:1958
+#, c-format
+msgid " Order: %s\n"
+msgstr " Σειρά: %s\n"
+
+#: plugins/sudoers/ldap.c:1966 plugins/sudoers/parse.c:504
+#: plugins/sudoers/sssd.c:1295
+#, c-format
+msgid " Commands:\n"
+msgstr " Εντολές:\n"
+
+#: plugins/sudoers/ldap.c:2509
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "αδύνατη η αρχικοποίηση του LDAP: %s"
+
+#: plugins/sudoers/ldap.c:2551
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "ορίστηκε το start_tls, αλλά οι βιβλιοθήκες LDAP υποστηρίζουν ldap_start_tls_s() ή ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:2784
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "άκυρο γνώρισμα sudoOrder: %s"
+
+#: plugins/sudoers/linux_audit.c:57
+msgid "unable to open audit system"
+msgstr "αδύνατο το άνοιγμα συστήματος ελέγχου"
+
+#: plugins/sudoers/linux_audit.c:93
+msgid "unable to send audit message"
+msgstr "αδύνατη η αποστολή μηνύματος ελέγχου"
+
+#: plugins/sudoers/logging.c:136
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: plugins/sudoers/logging.c:164
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (συνεχιζόμενη εντολή) %s"
+
+#: plugins/sudoers/logging.c:189
+#, c-format
+msgid "unable to open log file: %s: %s"
+msgstr "αδύνατο το άνοιγμα αρχείου καταγραφής: %s: %s"
+
+#: plugins/sudoers/logging.c:192
+#, c-format
+msgid "unable to lock log file: %s: %s"
+msgstr "αδύνατο το κλείδωμα αρχείου καταγραφής: %s: %s"
+
+#: plugins/sudoers/logging.c:243
+msgid "No user or host"
+msgstr "Χωρίς χρήστη ή οικοδεσπότη"
+
+#: plugins/sudoers/logging.c:245
+msgid "validation failure"
+msgstr "αποτυχία επικύρωσης"
+
+#: plugins/sudoers/logging.c:252
+msgid "user NOT in sudoers"
+msgstr "ο χρήστης ΔΕΝ είναι στους sudo"
+
+#: plugins/sudoers/logging.c:254
+msgid "user NOT authorized on host"
+msgstr "ο χρήστης ΔΕΝ εξουσιοδοτήθηκε στον οικοδεσπότη"
+
+#: plugins/sudoers/logging.c:256
+msgid "command not allowed"
+msgstr "μη επιτρεπόμενη εντολή"
+
+#: plugins/sudoers/logging.c:286
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr "το %s δεν είναι στο αρχείο χρηστών sudo. Αυτό το συμβάν θα αναφερθεί.\n"
+
+#: plugins/sudoers/logging.c:289
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr "ο %s δεν επιτρέπεται να εκτελέσει sudo στο %s. Αυτό το συμβάν θα αναφερθεί.\n"
+
+#: plugins/sudoers/logging.c:293
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Συγνώμη, ο χρήστης %s δεν μπορεί να εκτελέσει sudo στο %s.\n"
+
+#: plugins/sudoers/logging.c:296
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr "Συγνώμη, ο χρήστης %s δεν επιτρέπεται να εκτελέσει '%s%s%s' ως %s%s%s στο %s.\n"
+
+#: plugins/sudoers/logging.c:333 plugins/sudoers/sudoers.c:382
+#: plugins/sudoers/sudoers.c:383 plugins/sudoers/sudoers.c:385
+#: plugins/sudoers/sudoers.c:386 plugins/sudoers/sudoers.c:1017
+#: plugins/sudoers/sudoers.c:1018
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: δεν βρέθηκε η εντολή"
+
+#: plugins/sudoers/logging.c:335 plugins/sudoers/sudoers.c:378
+#, c-format
+msgid ""
+"ignoring `%s' found in '.'\n"
+"Use `sudo ./%s' if this is the `%s' you wish to run."
+msgstr ""
+"παραβλέπεται το `%s' που βρέθηκε στο '.'\n"
+"Χρησιμοποιήστε `sudo ./%s' αν αυτό είναι το `%s' που θέλετε να εκτελέσετε."
+
+#: plugins/sudoers/logging.c:351
+msgid "authentication failure"
+msgstr "αποτυχία πιστοποίησης"
+
+#: plugins/sudoers/logging.c:377
+msgid "a password is required"
+msgstr "απαιτείται κωδικός πρόσβασης"
+
+#: plugins/sudoers/logging.c:441 plugins/sudoers/logging.c:495
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u ανεπιτυχής προσπάθεια κωδικού πρόσβασης"
+msgstr[1] "%u ανεπιτυχείς προσπάθειες κωδικού πρόσβασης"
+
+#: plugins/sudoers/logging.c:581
+msgid "unable to fork"
+msgstr "αδύνατη η διακλάδωση"
+
+#: plugins/sudoers/logging.c:588 plugins/sudoers/logging.c:644
+#, c-format
+msgid "unable to fork: %m"
+msgstr "αδύνατη η διακλάδωση: %m"
+
+#: plugins/sudoers/logging.c:634
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "αδύνατο το άνοιγμα της διοχέτευσης: %m"
+
+#: plugins/sudoers/logging.c:659
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "αδύνατο να dup στην τυπική είσοδο: %m"
+
+#: plugins/sudoers/logging.c:694
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "αδύνατη η εκτέλεση %s: %m"
+
+#: plugins/sudoers/logging.c:914
+msgid "internal error: insufficient space for log line"
+msgstr "εσωτερικό σφάλμα: ανεπαρκής χώρος για γραμμή καταγραφής"
+
+#: plugins/sudoers/match.c:617
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr "ανυποστήρικτος τύπος αφομοίωσης %d για %s"
+
+#: plugins/sudoers/match.c:647
+#, c-format
+msgid "%s: read error"
+msgstr "%s: σφάλμα ανάγνωσης"
+
+#: plugins/sudoers/match.c:661
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "η αφομοίωση για το %s (%s) δεν είναι στη μορφή %s"
+
+#: plugins/sudoers/parse.c:115
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr "σφάλμα ανάλυσης στο %s κοντά στη γραμμή %d"
+
+#: plugins/sudoers/parse.c:118
+#, c-format
+msgid "parse error in %s"
+msgstr "ανάλυση σφάλματος για %s"
+
+#: plugins/sudoers/parse.c:451
+#, c-format
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+"\n"
+"Καταχώριση χρηστών sudo:\n"
+
+#: plugins/sudoers/parse.c:452
+#, c-format
+msgid " RunAsUsers: "
+msgstr " RunAsUsers: "
+
+#: plugins/sudoers/parse.c:466
+#, c-format
+msgid " RunAsGroups: "
+msgstr " RunAsGroups: "
+
+#: plugins/sudoers/parse.c:475
+#, c-format
+msgid " Options: "
+msgstr " Επιλογές: "
+
+#: plugins/sudoers/policy.c:109 plugins/sudoers/policy.c:116
+#: plugins/sudoers/policy.c:123 plugins/sudoers/policy.c:145
+#: plugins/sudoers/policy.c:259 plugins/sudoers/policy.c:277
+#: plugins/sudoers/policy.c:284 plugins/sudoers/policy.c:312
+#: plugins/sudoers/policy.c:320 plugins/sudoers/policy.c:327
+#: plugins/sudoers/set_perms.c:363 plugins/sudoers/set_perms.c:702
+#: plugins/sudoers/set_perms.c:1061 plugins/sudoers/set_perms.c:1357
+#: plugins/sudoers/set_perms.c:1525
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: plugins/sudoers/policy.c:539 plugins/sudoers/visudo.c:764
+#, c-format
+msgid "unable to execute %s"
+msgstr "Αδύνατη η εκτέλεση του %s."
+
+#: plugins/sudoers/policy.c:681
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Η έκδοση προσθέτου πολιτικής χρηστών sudo %s\n"
+
+#: plugins/sudoers/policy.c:683
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Η έκδοση γραμματικής αρχείου χρηστών sudo %d\n"
+
+#: plugins/sudoers/policy.c:687
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"διαδρομή χρηστών sudo: %s\n"
+
+#: plugins/sudoers/policy.c:690
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "διαδρομή nsswitch: %s\n"
+
+#: plugins/sudoers/policy.c:692
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "διαδρομή ldap.conf: %s\n"
+
+#: plugins/sudoers/policy.c:693
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "διαδρομή ldap.secret: %s\n"
+
+#: plugins/sudoers/pwutil.c:148
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "αδύνατη η αποθήκευση του uid %u, υπάρχει ήδη"
+
+#: plugins/sudoers/pwutil.c:190
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "αδύνατη η αποθήκευση του %s χρήστη, υπάρχει ήδη"
+
+#: plugins/sudoers/pwutil.c:393
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "αδύνατη η αποθήκευση του gid %u, υπάρχει ήδη"
+
+#: plugins/sudoers/pwutil.c:429
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "αδύνατη η αποθήκευση ομάδας %s, υπάρχει ήδη"
+
+#: plugins/sudoers/pwutil.c:592 plugins/sudoers/pwutil.c:614
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "αδύνατη η αποθήκευση καταλόγου ομάδας %s, υπάρχει ήδη"
+
+#: plugins/sudoers/pwutil.c:612
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "αδύνατη η ανάλυση ομάδων για %s"
+
+#: plugins/sudoers/set_perms.c:124 plugins/sudoers/set_perms.c:449
+#: plugins/sudoers/set_perms.c:852 plugins/sudoers/set_perms.c:1149
+#: plugins/sudoers/set_perms.c:1441
+msgid "perm stack overflow"
+msgstr "υπερχείλιση στοίβας perm"
+
+#: plugins/sudoers/set_perms.c:132 plugins/sudoers/set_perms.c:457
+#: plugins/sudoers/set_perms.c:860 plugins/sudoers/set_perms.c:1157
+#: plugins/sudoers/set_perms.c:1449
+msgid "perm stack underflow"
+msgstr "υποχείλιση στοίβας perm"
+
+#: plugins/sudoers/set_perms.c:191 plugins/sudoers/set_perms.c:504
+#: plugins/sudoers/set_perms.c:1208 plugins/sudoers/set_perms.c:1481
+msgid "unable to change to root gid"
+msgstr "αδύνατη η αλλαγή σε gid υπερχρήστη"
+
+#: plugins/sudoers/set_perms.c:280 plugins/sudoers/set_perms.c:601
+#: plugins/sudoers/set_perms.c:989 plugins/sudoers/set_perms.c:1285
+msgid "unable to change to runas gid"
+msgstr "αδύνατη η αλλαγή σε gid runas"
+
+#: plugins/sudoers/set_perms.c:292 plugins/sudoers/set_perms.c:613
+#: plugins/sudoers/set_perms.c:999 plugins/sudoers/set_perms.c:1295
+msgid "unable to change to runas uid"
+msgstr "αδύνατη η αλλαγή σε uid runas"
+
+#: plugins/sudoers/set_perms.c:310 plugins/sudoers/set_perms.c:631
+#: plugins/sudoers/set_perms.c:1015 plugins/sudoers/set_perms.c:1311
+msgid "unable to change to sudoers gid"
+msgstr "αδύνατη η αλλαγή σε gid χρηστών sudo"
+
+#: plugins/sudoers/set_perms.c:363 plugins/sudoers/set_perms.c:702
+#: plugins/sudoers/set_perms.c:1061 plugins/sudoers/set_perms.c:1357
+#: plugins/sudoers/set_perms.c:1525
+msgid "too many processes"
+msgstr "υπερβολικά πολλές διεργασίες"
+
+#: plugins/sudoers/set_perms.c:1595
+msgid "unable to set runas group vector"
+msgstr "αδύνατος ο ορισμός διανύσματος ομάδας runas"
+
+#: plugins/sudoers/sssd.c:252
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "αδύνατη η αρχικοποίηση πηγής SSS. Είναι το SSSD εγκατεστημένο στο μηχάνημά σας;"
+
+#: plugins/sudoers/sssd.c:259 plugins/sudoers/sssd.c:267
+#: plugins/sudoers/sssd.c:275 plugins/sudoers/sssd.c:283
+#: plugins/sudoers/sssd.c:291
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "αδύνατη η εύρεση συμβόλου \"%s\" στο %s"
+
+#: plugins/sudoers/sudo_nss.c:283
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Συμφωνία προεπιλεγμένων καταχωρίσεων για %s στο %s:\n"
+
+#: plugins/sudoers/sudo_nss.c:296
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Runas και προεπιλεγμένες ειδικές εντολές για το %s:\n"
+
+#: plugins/sudoers/sudo_nss.c:309
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "Ο χρήστης %s μπορεί να εκτελέσει τις παρακάτω εντολές στο %s:\n"
+
+#: plugins/sudoers/sudo_nss.c:318
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Ο χρήστης %s δεν επιτρέπεται να εκτελέσει sudo στο %s.\n"
+
+#: plugins/sudoers/sudoers.c:154 plugins/sudoers/sudoers.c:188
+#: plugins/sudoers/sudoers.c:675
+msgid "problem with defaults entries"
+msgstr "πρόβλημα με τις προεπιλεγμένες καταχωρίσεις"
+
+#: plugins/sudoers/sudoers.c:160
+msgid "no valid sudoers sources found, quitting"
+msgstr "δεν βρέθηκαν έγκυρες πηγές χρηστών sudo, έξοδος"
+
+#: plugins/sudoers/sudoers.c:222
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "οι χρήστες sudo καθορίζουν ότι ο υπερχρήστης δεν επιτρέπεται να εκτελέσει sudo"
+
+#: plugins/sudoers/sudoers.c:261
+msgid "you are not permitted to use the -C option"
+msgstr "δεν επιτρέπετε να χρησιμοποιήσετε την επιλογή -C"
+
+#: plugins/sudoers/sudoers.c:314
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr "κάτοχος χρονικής σήμανσης (%s): Δεν υπάρχει τέτοιος χρήστης"
+
+#: plugins/sudoers/sudoers.c:328
+msgid "no tty"
+msgstr "χωρίς tty"
+
+#: plugins/sudoers/sudoers.c:329
+msgid "sorry, you must have a tty to run sudo"
+msgstr "συγνώμη, πρέπει να έχετε ένα tty για να εκτελέσετε sudo"
+
+#: plugins/sudoers/sudoers.c:377
+msgid "command in current directory"
+msgstr "εντολή στο τρέχοντα κατάλογο"
+
+#: plugins/sudoers/sudoers.c:394
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "συγνώμη, δεν σας επιτρέπεται να διατηρήσετε το περιβάλλον"
+
+#: plugins/sudoers/sudoers.c:725 plugins/sudoers/visudo.c:326
+#: plugins/sudoers/visudo.c:590
+#, c-format
+msgid "unable to stat %s"
+msgstr "αδύνατο να εκτελεστεί stat %s"
+
+#: plugins/sudoers/sudoers.c:728
+#, c-format
+msgid "%s is not a regular file"
+msgstr "το %s δεν είναι ένα κανονικό αρχείο"
+
+#: plugins/sudoers/sudoers.c:731 plugins/sudoers/timestamp.c:283 toke.l:923
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "το %s κατέχεται από uid %u, θα έπρεπε να είναι %u"
+
+#: plugins/sudoers/sudoers.c:735 toke.l:930
+#, c-format
+msgid "%s is world writable"
+msgstr "Το %s είναι εγγράψιμο από όλους"
+
+#: plugins/sudoers/sudoers.c:738 toke.l:935
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "το %s κατέχεται από gid %u, θα έπρεπε να είναι %u"
+
+#: plugins/sudoers/sudoers.c:764
+#, c-format
+msgid "only root can use `-c %s'"
+msgstr "μόνο ο υπερχρήστης μπορεί να χρησιμοποιήσει `-c %s'"
+
+#: plugins/sudoers/sudoers.c:781 plugins/sudoers/sudoers.c:783
+#, c-format
+msgid "unknown login class: %s"
+msgstr "άγνωστη κλάση σύνδεσης: %s"
+
+#: plugins/sudoers/sudoers.c:815
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "αδύνατη η επίλυση οικοδεσπότη %s"
+
+#: plugins/sudoers/sudoers.c:878 plugins/sudoers/testsudoers.c:387
+#, c-format
+msgid "unknown group: %s"
+msgstr "άγνωστη ομάδα: %s"
+
+#: plugins/sudoers/sudoreplay.c:274
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "άκυρη επιλογή φίλτρου: %s"
+
+#: plugins/sudoers/sudoreplay.c:287
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "άκυρη μέγιστη αναμονή: %s"
+
+#: plugins/sudoers/sudoreplay.c:293
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "άκυρος συντελεστής ταχύτητας: %s"
+
+#: plugins/sudoers/sudoreplay.c:296 plugins/sudoers/visudo.c:184
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s έκδοση %s\n"
+
+#: plugins/sudoers/sudoreplay.c:328
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s/timing: %s"
+msgstr "%s/%.2s/%.2s/%.2s/χρονισμός: %s"
+
+#: plugins/sudoers/sudoreplay.c:334
+#, c-format
+msgid "%s/%s/timing: %s"
+msgstr "%s/%s/χρονισμός: %s"
+
+#: plugins/sudoers/sudoreplay.c:350
+#, c-format
+msgid "Replaying sudo session: %s\n"
+msgstr "Αναπαράγεται η συνεδρία sudo: %s\n"
+
+#: plugins/sudoers/sudoreplay.c:356
+#, c-format
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr "Προειδοποίηση: το τερματικό σας είναι υπερβολικά μικρό για σωστή επανάληψη του ημερολογίου.\n"
+
+#: plugins/sudoers/sudoreplay.c:357
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Η γεωμετρία του ημερολογίου είναι %d x %d, η γεωμετρία του τερματικού σας είναι %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:412
+msgid "unable to set tty to raw mode"
+msgstr "αδύνατος ο ορισμός σε ακατέργαστη κατάσταση"
+
+#: plugins/sudoers/sudoreplay.c:443
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "άκυρη γραμμή αρχείου χρονισμού: %s"
+
+#: plugins/sudoers/sudoreplay.c:649 plugins/sudoers/sudoreplay.c:674
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "ασαφής παράσταση \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:696
+msgid "unmatched ')' in expression"
+msgstr "ασύμφωνο ')' σε παράσταση"
+
+#: plugins/sudoers/sudoreplay.c:700
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "άγνωστος όρος αναζήτησης \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:714
+#, c-format
+msgid "%s requires an argument"
+msgstr "το %s απαιτεί ένα όρισμα"
+
+#: plugins/sudoers/sudoreplay.c:718 plugins/sudoers/sudoreplay.c:1090
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr "άκυρη κανονική έκφραση: %s"
+
+#: plugins/sudoers/sudoreplay.c:724
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "αδύνατη η ανάλυση ημερομηνίας \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:733
+msgid "unmatched '(' in expression"
+msgstr "ασύμφωνο '(' σε παράσταση"
+
+#: plugins/sudoers/sudoreplay.c:735
+msgid "illegal trailing \"or\""
+msgstr "απαράδεκτο τελικό \"or\""
+
+#: plugins/sudoers/sudoreplay.c:737
+msgid "illegal trailing \"!\""
+msgstr "απαράδεκτο τελικό \"!\""
+
+#: plugins/sudoers/sudoreplay.c:790
+#, c-format
+msgid "unknown search type %d"
+msgstr "άγνωστος τύπος αναζήτησης %d"
+
+#: plugins/sudoers/sudoreplay.c:827
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: άκυρο αρχείο ημερολογίου"
+
+#: plugins/sudoers/sudoreplay.c:845
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: το πεδίο σήμανσης χρόνου λείπει"
+
+#: plugins/sudoers/sudoreplay.c:852
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: η σήμανση χρόνου %s: %s"
+
+#: plugins/sudoers/sudoreplay.c:859
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: το πεδίο χρήστη λείπει"
+
+#: plugins/sudoers/sudoreplay.c:867
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: το πεδίο χρήστη runas λείπει"
+
+#: plugins/sudoers/sudoreplay.c:875
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: το πεδίο ομάδας runas λείπει"
+
+#: plugins/sudoers/sudoreplay.c:1230
+#, c-format
+msgid "usage: %s [-h] [-d dir] [-m num] [-s num] ID\n"
+msgstr "χρήση: %s [-h] [-d dir] [-m num] [-s num] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1233
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "χρήση: %s [-h] [-d dir] -l [παράσταση αναζήτησης]\n"
+
+#: plugins/sudoers/sudoreplay.c:1242
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - επανάληψη ημερολογίων συνεδρίας sudo\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1244
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Επιλογές:\n"
+" -d, --directory=κατάλογος καθορισμός καταλόγου για ημερολόγια συνεδρίας\n"
+" -f, --filter=φίλτρο ορισμός ποιοι τύποι εισόδου/εξόδου να εμφανίζονται\n"
+" -h, --help εμφάνιση μηνύματος βοήθειας και έξοδος\n"
+" -l, --list κατάλογος διαθέσιμων αναγνωριστικών συνεδρίας, με προαιρετική παράσταση\n"
+" -m, --max-wait=αριθ μέγιστος αριθμός δευτερολέπτων αναμονής μεταξύ συμβάντων\n"
+" -s, --speed=αριθ επιτάχυνση ή επιβράδυνση εξόδου\n"
+" -V, --version εμφάνιση πληροφοριών έκδοσης και έξοδος"
+
+#: plugins/sudoers/testsudoers.c:326
+msgid "\thost unmatched"
+msgstr " ασύμφωνος οικοδεσπότης"
+
+#: plugins/sudoers/testsudoers.c:329
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Επιτρεπόμενη εντολή"
+
+#: plugins/sudoers/testsudoers.c:330
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Απαγορευμένη εντολή"
+
+#: plugins/sudoers/testsudoers.c:330
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"ασύμφωνη εντολή"
+
+#: plugins/sudoers/timestamp.c:191
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "αδύνατη η περικοπή αρχείου σήμανσης χρόνου σε %lld ψηφιολέξεις"
+
+#: plugins/sudoers/timestamp.c:291
+#, c-format
+msgid "%s is group writable"
+msgstr "το %s είναι εγγράψιμη ομάδα"
+
+#: plugins/sudoers/timestamp.c:311
+#, c-format
+msgid "timestamp path too long: %s/%s"
+msgstr "η διαδρομή χρονικής σήμανσης είναι υπερβολικά μεγάλη: %s/%s"
+
+#: plugins/sudoers/timestamp.c:484
+msgid "ignoring time stamp from the future"
+msgstr "να αγνοείται η χρονική σήμανση στο μέλλον"
+
+#: plugins/sudoers/timestamp.c:496
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "η χρονική σήμανση υπερβολικά μακρινή στο μέλλον: %20.20s"
+
+#: plugins/sudoers/timestamp.c:596 plugins/sudoers/timestamp.c:618
+#, c-format
+msgid "lecture status path too long: %s/%s"
+msgstr "η διαδρομή κατάστασης οδηγίας υπερβολικά μεγάλη: %s/%s"
+
+#: plugins/sudoers/toke_util.c:176
+msgid "fill_args: buffer overflow"
+msgstr "fill_args: υπερχείλιση ενδιάμεσης μνήμης"
+
+#: plugins/sudoers/visudo.c:186
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "γραμματική %s έκδοση %d\n"
+
+#: plugins/sudoers/visudo.c:257 plugins/sudoers/visudo.c:543
+#, c-format
+msgid "press return to edit %s: "
+msgstr "πατήστε return για να επεξεργαστείτε το %s: "
+
+#: plugins/sudoers/visudo.c:342 plugins/sudoers/visudo.c:348
+msgid "write error"
+msgstr "σφάλμα εγγραφής"
+
+#: plugins/sudoers/visudo.c:430
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "αδύνατη η εκτέλεση stat προσωρινού αρχείου (%s), το %s δεν άλλαξε"
+
+#: plugins/sudoers/visudo.c:435
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "προσωρινό αρχείο μηδενικού μήκους (%s), το %s αμετάβλητο"
+
+#: plugins/sudoers/visudo.c:441
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "αποτυχία επεξεργασίας του (%s), το %s αμετάβλητο"
+
+#: plugins/sudoers/visudo.c:463
+#, c-format
+msgid "%s unchanged"
+msgstr "αμετάβλητο %s"
+
+#: plugins/sudoers/visudo.c:488
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "αδύνατο το ξαναάνοιγμα του προσωρινού αρχείου (%s), το %s αμετάβλητο"
+
+#: plugins/sudoers/visudo.c:498
+#, c-format
+msgid "unabled to parse temporary file (%s), unknown error"
+msgstr "αδύνατη η ανάλυση του προσωρινού αρχείου (%s), άγνωστο σφάλμα"
+
+#: plugins/sudoers/visudo.c:534
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr "εσωτερικό σφάλμα, αδύνατη η εύρεση του %s στον κατάλογο!"
+
+#: plugins/sudoers/visudo.c:592 plugins/sudoers/visudo.c:601
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "αδύνατος ο ορισμός (uid, gid) του %s στο (%u, %u)"
+
+#: plugins/sudoers/visudo.c:596 plugins/sudoers/visudo.c:606
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "αδύνατη η αλλαγή κατάστασης του %s στο 0%o"
+
+#: plugins/sudoers/visudo.c:623
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "τα %s και %s δεν έχουν το ίδιο σύστημα αρχείων, χρησιμοποιήστε το mv για μετονομασία"
+
+#: plugins/sudoers/visudo.c:637
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "αποτυχία εντολής: '%s %s %s', το %s αμετάβλητο"
+
+#: plugins/sudoers/visudo.c:647
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "σφάλμα μετονομασίας του %s, το %s αμετάβλητο"
+
+#: plugins/sudoers/visudo.c:709
+msgid "What now? "
+msgstr "Τι να γίνει τώρα; "
+
+#: plugins/sudoers/visudo.c:723
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Οι επιλογές είναι:\n"
+" (e)dit νέα επεξεργασία του αρχείου χρηστών sudo\n"
+" e(x)it έξοδος χωρίς αποθήκευση αλλαγών στο αρχείο χρηστών sudo\n"
+" (Q)uit έξοδος και αποθήκευση αλλαγών στο αρχείο χρηστών sudo (ΚΙΝΔΥΝΟΣ!)\n"
+
+#: plugins/sudoers/visudo.c:771
+#, c-format
+msgid "unable to run %s"
+msgstr "αδύνατη η εκτέλεση του %s"
+
+#: plugins/sudoers/visudo.c:797
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: εσφαλμένος κάτοχος (uid, gid) πρέπει να είναι (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:804
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: εσφαλμένα δικαιώματα, πρέπει να είναι κατάσταση 0%o\n"
+
+#: plugins/sudoers/visudo.c:829 plugins/sudoers/visudo_json.c:1008
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "αποτυχία ανάλυσης αρχείου %s, άγνωστο σφάλμα"
+
+#: plugins/sudoers/visudo.c:845 plugins/sudoers/visudo_json.c:1017
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr "ανάλυση σφάλματος στο %s κοντά στη γραμμή %d\n"
+
+#: plugins/sudoers/visudo.c:848 plugins/sudoers/visudo_json.c:1020
+#, c-format
+msgid "parse error in %s\n"
+msgstr "ανάλυση σφάλματος %s\n"
+
+#: plugins/sudoers/visudo.c:856 plugins/sudoers/visudo.c:863
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: επιτυχής ανάλυση\n"
+
+#: plugins/sudoers/visudo.c:909
+#, c-format
+msgid "%s busy, try again later"
+msgstr "το %s είναι απασχολημένο, ξαναδοκιμάστε αργότερα"
+
+#: plugins/sudoers/visudo.c:953
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "ο συγκεκριμένος επεξεργαστής (%s) δεν υπάρχει"
+
+#: plugins/sudoers/visudo.c:976
+#, c-format
+msgid "unable to stat editor (%s)"
+msgstr "αδύνατο να εκτελέσουμε stat στον επεξεργαστή (%s)"
+
+#: plugins/sudoers/visudo.c:1024
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "δεν βρέθηκε κανένας επεξεργαστής (διαδρομή επεξεργαστή = %s)"
+
+#: plugins/sudoers/visudo.c:1117
+#, c-format
+msgid "Error: cycle in %s_Alias `%s'"
+msgstr "Σφάλμα: κύκλος στο %s_Alias `%s'"
+
+#: plugins/sudoers/visudo.c:1118
+#, c-format
+msgid "Warning: cycle in %s_Alias `%s'"
+msgstr "Προειδοποίηση: κύκλος στο %s_Alias `%s'"
+
+#: plugins/sudoers/visudo.c:1124
+#, c-format
+msgid "Error: %s_Alias `%s' referenced but not defined"
+msgstr "Σφάλμα: αναφέρθηκε το %s_Alias `%s', αλλά δεν ορίστηκε"
+
+#: plugins/sudoers/visudo.c:1125
+#, c-format
+msgid "Warning: %s_Alias `%s' referenced but not defined"
+msgstr "Προειδοποίηση: αναφέρθηκε το %s_Alias `%s', αλλά δεν ορίστηκε"
+
+#: plugins/sudoers/visudo.c:1267
+#, c-format
+msgid "%s: unused %s_Alias %s"
+msgstr "%s: αχρησιμοποίητο %s_Alias %s"
+
+#: plugins/sudoers/visudo.c:1329
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - ασφαλής επεξεργασία του αρχείου χρηστών sudo\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1331
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=file specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+" -x, --export=file export sudoers in JSON format"
+msgstr ""
+"\n"
+"Επιλογές:\n"
+" -c, --check κατάσταση μόνο ελέγχου\n"
+" -f, --file=αρχείο καθορισμός θέσης αρχείου χρηστών sudo\n"
+" -h, --help εμφάνιση μηνύματος βοήθειας και έξοδος\n"
+" -q, --quiet λιγότερο αναλυτική (αθόρυβη) σύνταξη μηνυμάτων σφαλμάτων\n"
+" -s, --strict αυστηρός έλεγχος σύνταξης\n"
+" -V, --version εμφάνιση πληροφοριών έκδοσης και έξοδος\n"
+" -x, --export=αρχείο εξαγωγή χρηστών sudo σε μορφή JSON"
+
+#: toke.l:894
+msgid "too many levels of includes"
+msgstr "περιλαμβάνει υπερβολικά πολλά επίπεδα"
diff --git a/plugins/sudoers/po/eo.mo b/plugins/sudoers/po/eo.mo
new file mode 100644
index 0000000..f2a75c6
--- /dev/null
+++ b/plugins/sudoers/po/eo.mo
Binary files differ
diff --git a/plugins/sudoers/po/eo.po b/plugins/sudoers/po/eo.po
new file mode 100644
index 0000000..26f8085
--- /dev/null
+++ b/plugins/sudoers/po/eo.po
@@ -0,0 +1,3850 @@
+# Esperanto translations for sudo package.
+# This file is distributed under the same license as the sudo package.
+# Keith Bowes <zooplah@gmail.com>, 2012, 2019-2023.
+# Felipe Castro <fefcas@gmail.com>, 2013, 2014, 2015, 2016, 2017, 2018, 2019.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.9.15b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-10-19 10:02-0600\n"
+"PO-Revision-Date: 2023-10-22 12:12-0400\n"
+"Last-Translator: Keith Bowes <zooplah@gmail.com>\n"
+"Language-Team: Esperanto <translation-team-eo@lists.sourceforge.net>\n"
+"Language: eo\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 2.0.7\n"
+
+#: confstr.sh:1 gram.y:1257 plugins/sudoers/logging.c:911
+msgid "syntax error"
+msgstr "sintaksa eraro"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "Pasvorto de %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] pasvorto por %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Pasvorto: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** SEKURECO: informoj por %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Malĝuste, reprovu."
+
+#: gram.y:238 gram.y:305 gram.y:314 gram.y:323 gram.y:333 gram.y:343 gram.y:367
+#: gram.y:394 gram.y:403 gram.y:411 gram.y:420 gram.y:429 gram.y:503 gram.y:513
+#: gram.y:525 gram.y:573 gram.y:582 gram.y:591 gram.y:600 gram.y:733 gram.y:742
+#: gram.y:757 gram.y:777 gram.y:796 gram.y:959 gram.y:964 gram.y:972 gram.y:986
+#: gram.y:992 gram.y:1004 gram.y:1010 gram.y:1135 gram.y:1144 gram.y:1152
+#: gram.y:1161 gram.y:1170 gram.y:1199 gram.y:1208 gram.y:1216 gram.y:1317
+#: gram.y:1447 gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:313 lib/eventlog/eventlog.c:765
+#: lib/eventlog/eventlog.c:842 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:484
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:185
+#: logsrvd/iolog_writer.c:218 logsrvd/iolog_writer.c:228
+#: logsrvd/iolog_writer.c:257 logsrvd/iolog_writer.c:278
+#: logsrvd/iolog_writer.c:290 logsrvd/iolog_writer.c:300
+#: logsrvd/iolog_writer.c:310 logsrvd/iolog_writer.c:320
+#: logsrvd/iolog_writer.c:330 logsrvd/iolog_writer.c:342
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:1057 logsrvd/logsrvd.c:1120 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:650
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1743
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:216
+#: logsrvd/logsrvd_journal.c:217 logsrvd/logsrvd_journal.c:274
+#: logsrvd/logsrvd_journal.c:279 logsrvd/logsrvd_journal.c:439
+#: logsrvd/logsrvd_journal.c:441 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:216 logsrvd/logsrvd_local.c:278
+#: logsrvd/logsrvd_local.c:279 logsrvd/logsrvd_local.c:417
+#: logsrvd/logsrvd_local.c:468 logsrvd/logsrvd_local.c:469
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:475
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/logsrvd_relay.c:446
+#: logsrvd/logsrvd_relay.c:748 logsrvd/logsrvd_relay.c:855
+#: logsrvd/sendlog.c:256 logsrvd/sendlog.c:265 logsrvd/sendlog.c:297
+#: logsrvd/sendlog.c:303 logsrvd/sendlog.c:352 logsrvd/sendlog.c:630
+#: logsrvd/sendlog.c:1822 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/bsdauth.c:154 plugins/sudoers/auth/kerb5.c:122
+#: plugins/sudoers/auth/kerb5.c:150 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/auth/sia.c:61
+#: plugins/sudoers/canon_path.c:129 plugins/sudoers/canon_path.c:161
+#: plugins/sudoers/check_aliases.c:128 plugins/sudoers/check_util.c:56
+#: plugins/sudoers/check_util.c:84 plugins/sudoers/cvtsudoers.c:132
+#: plugins/sudoers/cvtsudoers.c:176 plugins/sudoers/cvtsudoers.c:193
+#: plugins/sudoers/cvtsudoers.c:204 plugins/sudoers/cvtsudoers.c:338
+#: plugins/sudoers/cvtsudoers.c:379 plugins/sudoers/cvtsudoers.c:399
+#: plugins/sudoers/cvtsudoers.c:545 plugins/sudoers/cvtsudoers.c:698
+#: plugins/sudoers/cvtsudoers.c:716 plugins/sudoers/cvtsudoers.c:891
+#: plugins/sudoers/cvtsudoers.c:899 plugins/sudoers/cvtsudoers.c:1395
+#: plugins/sudoers/cvtsudoers.c:1399 plugins/sudoers/cvtsudoers.c:1501
+#: plugins/sudoers/cvtsudoers_csv.c:183 plugins/sudoers/cvtsudoers_csv.c:247
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:152
+#: plugins/sudoers/cvtsudoers_ldif.c:195 plugins/sudoers/cvtsudoers_ldif.c:236
+#: plugins/sudoers/cvtsudoers_ldif.c:302 plugins/sudoers/cvtsudoers_ldif.c:378
+#: plugins/sudoers/cvtsudoers_ldif.c:432 plugins/sudoers/cvtsudoers_ldif.c:440
+#: plugins/sudoers/cvtsudoers_ldif.c:451 plugins/sudoers/cvtsudoers_ldif.c:458
+#: plugins/sudoers/cvtsudoers_ldif.c:470 plugins/sudoers/cvtsudoers_ldif.c:483
+#: plugins/sudoers/cvtsudoers_ldif.c:491 plugins/sudoers/cvtsudoers_ldif.c:638
+#: plugins/sudoers/cvtsudoers_merge.c:47 plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1158
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:212
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:694 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:294 plugins/sudoers/ldap_util.c:301
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:402
+#: plugins/sudoers/log_client.c:717 plugins/sudoers/log_client.c:739
+#: plugins/sudoers/log_client.c:744 plugins/sudoers/log_client.c:1426
+#: plugins/sudoers/log_client.c:1547 plugins/sudoers/log_client.c:1670
+#: plugins/sudoers/log_client.c:1993 plugins/sudoers/log_client.c:2052
+#: plugins/sudoers/logging.c:110 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:872 plugins/sudoers/lookup.c:338
+#: plugins/sudoers/lookup.c:355 plugins/sudoers/lookup.c:374
+#: plugins/sudoers/lookup.c:393 plugins/sudoers/lookup.c:410
+#: plugins/sudoers/lookup.c:433 plugins/sudoers/lookup.c:444
+#: plugins/sudoers/match_command.c:302 plugins/sudoers/match_command.c:574
+#: plugins/sudoers/match_command.c:641 plugins/sudoers/match_command.c:737
+#: plugins/sudoers/match_command.c:785 plugins/sudoers/match_digest.c:88
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:595
+#: plugins/sudoers/parse_ldif.c:625 plugins/sudoers/parse_ldif.c:650
+#: plugins/sudoers/parse_ldif.c:708 plugins/sudoers/parse_ldif.c:725
+#: plugins/sudoers/parse_ldif.c:753 plugins/sudoers/parse_ldif.c:760
+#: plugins/sudoers/policy.c:646 plugins/sudoers/policy.c:1061
+#: plugins/sudoers/prompt.c:94 plugins/sudoers/pwutil.c:219
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:368
+#: plugins/sudoers/pwutil.c:542 plugins/sudoers/pwutil.c:607
+#: plugins/sudoers/pwutil.c:679 plugins/sudoers/pwutil.c:877
+#: plugins/sudoers/pwutil.c:967 plugins/sudoers/pwutil.c:1015
+#: plugins/sudoers/pwutil.c:1076 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:145 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1307 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:256
+#: plugins/sudoers/testsudoers.c:265 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:164 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1095
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1320
+msgid "unable to allocate memory"
+msgstr "ne eblas rezervi memoron"
+
+#: gram.y:624
+msgid "a digest requires a path name"
+msgstr "resumo postulas vojnomon"
+
+#: gram.y:646
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "valoroj por \"CWD\" devas komenciĝi per '/', '~' aŭ '*'"
+
+#: gram.y:652
+msgid "\"CWD\" path too long"
+msgstr "\"CWD\"-vojo tro grandas"
+
+#: gram.y:662
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "valoroj por \"CHROOT\" devas komenciĝi per '/', '~' aŭ '*'"
+
+#: gram.y:668
+msgid "\"CHROOT\" path too long"
+msgstr "\"CHROOT\"-vojo tro grandas"
+
+#: gram.y:817
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "sintakseraro: rezervita vorto %s uzata kiel kromnomo"
+
+#: gram.y:840
+msgid "invalid notbefore value"
+msgstr "malvalida valoro notafter"
+
+#: gram.y:849
+msgid "invalid notafter value"
+msgstr "validiga valoro notafter"
+
+#: gram.y:859 plugins/sudoers/policy.c:390
+msgid "timeout value too large"
+msgstr "eksvalidiĝo-valoro tro grandas"
+
+#: gram.y:861 plugins/sudoers/policy.c:392
+msgid "invalid timeout value"
+msgstr "malvalida eksvalidiĝo-valoro"
+
+#: gram.y:982 plugins/sudoers/sudoers.c:1162
+msgid "command too long"
+msgstr "komando tro longas"
+
+#: gram.y:1016
+msgid "expected a fully-qualified path name"
+msgstr "atendas tute kvalifikitan vojnomon"
+
+#: gram.y:1261
+#, c-format
+msgid "%s:%d:%zu: %s\n"
+msgstr "%s:%d:%zu: %s\n"
+
+#: gram.y:1315
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Kromnomo \"%s\" jam ekzistas"
+
+#: gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:765 lib/eventlog/eventlog.c:838
+#: lib/eventlog/eventlog.c:841 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:483
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:232
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:174
+#: logsrvd/iolog_writer.c:184 logsrvd/iolog_writer.c:197
+#: logsrvd/iolog_writer.c:217 logsrvd/iolog_writer.c:227
+#: logsrvd/iolog_writer.c:246 logsrvd/iolog_writer.c:256
+#: logsrvd/iolog_writer.c:267 logsrvd/iolog_writer.c:277
+#: logsrvd/iolog_writer.c:289 logsrvd/iolog_writer.c:299
+#: logsrvd/iolog_writer.c:309 logsrvd/iolog_writer.c:319
+#: logsrvd/iolog_writer.c:329 logsrvd/iolog_writer.c:341
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:530
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:668
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:1131
+#: logsrvd/logsrvd.c:1446 logsrvd/logsrvd.c:1453 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:649
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1742
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:125
+#: logsrvd/logsrvd_journal.c:216 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:250 logsrvd/logsrvd_journal.c:258
+#: logsrvd/logsrvd_journal.c:287 logsrvd/logsrvd_journal.c:291
+#: logsrvd/logsrvd_journal.c:439 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:278 logsrvd/logsrvd_local.c:468
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:493
+#: logsrvd/logsrvd_queue.c:158 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/sendlog.c:256 logsrvd/sendlog.c:265
+#: logsrvd/sendlog.c:297 logsrvd/sendlog.c:303 logsrvd/sendlog.c:352
+#: logsrvd/sendlog.c:630 logsrvd/sendlog.c:1523 logsrvd/sendlog.c:1530
+#: logsrvd/sendlog.c:1753 logsrvd/sendlog.c:1822 logsrvd/tls_init.c:305
+#: logsrvd/tls_init.c:329 logsrvd/tls_init.c:340 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/pam.c:518 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/canon_path.c:129
+#: plugins/sudoers/canon_path.c:161 plugins/sudoers/check_aliases.c:128
+#: plugins/sudoers/check_util.c:56 plugins/sudoers/check_util.c:84
+#: plugins/sudoers/cvtsudoers.c:132 plugins/sudoers/cvtsudoers.c:175
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:203
+#: plugins/sudoers/cvtsudoers.c:337 plugins/sudoers/cvtsudoers.c:544
+#: plugins/sudoers/cvtsudoers.c:697 plugins/sudoers/cvtsudoers.c:715
+#: plugins/sudoers/cvtsudoers.c:891 plugins/sudoers/cvtsudoers.c:898
+#: plugins/sudoers/cvtsudoers.c:1395 plugins/sudoers/cvtsudoers.c:1399
+#: plugins/sudoers/cvtsudoers.c:1501 plugins/sudoers/cvtsudoers_csv.c:182
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:151 plugins/sudoers/cvtsudoers_ldif.c:194
+#: plugins/sudoers/cvtsudoers_ldif.c:235 plugins/sudoers/cvtsudoers_ldif.c:301
+#: plugins/sudoers/cvtsudoers_ldif.c:377 plugins/sudoers/cvtsudoers_ldif.c:431
+#: plugins/sudoers/cvtsudoers_ldif.c:439 plugins/sudoers/cvtsudoers_ldif.c:450
+#: plugins/sudoers/cvtsudoers_ldif.c:457 plugins/sudoers/cvtsudoers_ldif.c:469
+#: plugins/sudoers/cvtsudoers_ldif.c:482 plugins/sudoers/cvtsudoers_ldif.c:490
+#: plugins/sudoers/cvtsudoers_ldif.c:637 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51 plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1157
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:211
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:693 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:293 plugins/sudoers/ldap_util.c:300
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:228
+#: plugins/sudoers/log_client.c:250 plugins/sudoers/log_client.c:264
+#: plugins/sudoers/log_client.c:402 plugins/sudoers/log_client.c:717
+#: plugins/sudoers/log_client.c:739 plugins/sudoers/log_client.c:744
+#: plugins/sudoers/log_client.c:1426 plugins/sudoers/log_client.c:1547
+#: plugins/sudoers/log_client.c:1670 plugins/sudoers/log_client.c:1993
+#: plugins/sudoers/log_client.c:2052 plugins/sudoers/logging.c:110
+#: plugins/sudoers/logging.c:189 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:755 plugins/sudoers/logging.c:872
+#: plugins/sudoers/logging.c:925 plugins/sudoers/logging.c:932
+#: plugins/sudoers/lookup.c:337 plugins/sudoers/lookup.c:354
+#: plugins/sudoers/lookup.c:373 plugins/sudoers/lookup.c:392
+#: plugins/sudoers/lookup.c:409 plugins/sudoers/lookup.c:432
+#: plugins/sudoers/lookup.c:443 plugins/sudoers/match_command.c:301
+#: plugins/sudoers/match_command.c:573 plugins/sudoers/match_command.c:640
+#: plugins/sudoers/match_command.c:737 plugins/sudoers/match_command.c:784
+#: plugins/sudoers/match_digest.c:88 plugins/sudoers/parse_ldif.c:152
+#: plugins/sudoers/parse_ldif.c:183 plugins/sudoers/parse_ldif.c:252
+#: plugins/sudoers/parse_ldif.c:260 plugins/sudoers/parse_ldif.c:265
+#: plugins/sudoers/parse_ldif.c:341 plugins/sudoers/parse_ldif.c:352
+#: plugins/sudoers/parse_ldif.c:379 plugins/sudoers/parse_ldif.c:396
+#: plugins/sudoers/parse_ldif.c:408 plugins/sudoers/parse_ldif.c:412
+#: plugins/sudoers/parse_ldif.c:426 plugins/sudoers/parse_ldif.c:484
+#: plugins/sudoers/parse_ldif.c:595 plugins/sudoers/parse_ldif.c:624
+#: plugins/sudoers/parse_ldif.c:649 plugins/sudoers/parse_ldif.c:707
+#: plugins/sudoers/parse_ldif.c:724 plugins/sudoers/parse_ldif.c:752
+#: plugins/sudoers/parse_ldif.c:759 plugins/sudoers/policy.c:157
+#: plugins/sudoers/policy.c:166 plugins/sudoers/policy.c:175
+#: plugins/sudoers/policy.c:204 plugins/sudoers/policy.c:374
+#: plugins/sudoers/policy.c:390 plugins/sudoers/policy.c:392
+#: plugins/sudoers/policy.c:430 plugins/sudoers/policy.c:439
+#: plugins/sudoers/policy.c:448 plugins/sudoers/policy.c:457
+#: plugins/sudoers/policy.c:493 plugins/sudoers/policy.c:502
+#: plugins/sudoers/policy.c:511 plugins/sudoers/policy.c:520
+#: plugins/sudoers/policy.c:529 plugins/sudoers/policy.c:538
+#: plugins/sudoers/policy.c:547 plugins/sudoers/policy.c:646
+#: plugins/sudoers/policy.c:1061 plugins/sudoers/prompt.c:94
+#: plugins/sudoers/pwutil.c:219 plugins/sudoers/pwutil.c:290
+#: plugins/sudoers/pwutil.c:368 plugins/sudoers/pwutil.c:542
+#: plugins/sudoers/pwutil.c:607 plugins/sudoers/pwutil.c:679
+#: plugins/sudoers/pwutil.c:877 plugins/sudoers/pwutil.c:967
+#: plugins/sudoers/pwutil.c:1015 plugins/sudoers/pwutil.c:1076
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1306 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:255
+#: plugins/sudoers/testsudoers.c:264 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:163 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1094
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1309 toke.l:1320
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:304
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "ne eblas kopii enigon: %m"
+
+#: lib/eventlog/eventlog.c:346
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "ne eblas plenumigi %s-on: %m"
+
+#: lib/eventlog/eventlog.c:394 plugins/sudoers/auth/aix_auth.c:199
+msgid "unable to fork"
+msgstr "ne eblas forki"
+
+#: lib/eventlog/eventlog.c:404 lib/eventlog/eventlog.c:471
+#, c-format
+msgid "unable to fork: %m"
+msgstr "ne eblas forki: %m"
+
+#: lib/eventlog/eventlog.c:461
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "ne eblas malfermi tubon: %m"
+
+#: lib/eventlog/eventlog.c:1000
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s: %s"
+
+#: lib/eventlog/eventlog.c:1029
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (komando daŭrigis) %s"
+
+#: lib/eventlog/parse_json.c:175
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "atendita JSON_STRING, %d ricevita"
+
+#: lib/eventlog/parse_json.c:180
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY tro grandas"
+
+#: lib/eventlog/parse_json.c:506
+msgid "missing double quote in name"
+msgstr "mankas duobla citilo en nomo"
+
+#: lib/eventlog/parse_json.c:624
+msgid "missing JSON_OBJECT"
+msgstr "mankanta JSON_OBJECT"
+
+#: lib/eventlog/parse_json.c:628
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "atendita JSON_OBJECT, %d ricevita"
+
+#: lib/eventlog/parse_json.c:762
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "json-stako eluzita (maksimume %u kandroj)"
+
+#: lib/eventlog/parse_json.c:840
+msgid "objects must consist of name:value pairs"
+msgstr "objektoj devas konsisti el paroj nomo:valoro"
+
+#: lib/eventlog/parse_json.c:845 lib/eventlog/parse_json.c:876
+#: lib/eventlog/parse_json.c:920 lib/eventlog/parse_json.c:942
+#: lib/eventlog/parse_json.c:964 lib/eventlog/parse_json.c:986
+#: lib/eventlog/parse_json.c:1008
+msgid "missing separator between values"
+msgstr "mankanta apartigilo inter valoroj"
+
+#: lib/eventlog/parse_json.c:860 lib/eventlog/parse_json.c:1034
+msgid "unmatched close brace"
+msgstr "'}' sen kongruanta '{'"
+
+#: lib/eventlog/parse_json.c:871
+msgid "unexpected array"
+msgstr "neatendita tabelo"
+
+#: lib/eventlog/parse_json.c:891 lib/eventlog/parse_json.c:1037
+msgid "unmatched close bracket"
+msgstr "']' sen kongruanta '['"
+
+#: lib/eventlog/parse_json.c:902
+msgid "unexpected string"
+msgstr "neatendita ĉeno"
+
+#: lib/eventlog/parse_json.c:913
+msgid "missing colon after name"
+msgstr "mankas dupunkto post nomo"
+
+#: lib/eventlog/parse_json.c:934 lib/eventlog/parse_json.c:956
+msgid "unexpected boolean"
+msgstr "neatendita bulea valoro"
+
+#: lib/eventlog/parse_json.c:978
+msgid "unexpected null"
+msgstr "neatendita nulo"
+
+#: lib/eventlog/parse_json.c:999
+msgid "unexpected number"
+msgstr "neatendita nombro"
+
+#: lib/eventlog/parse_json.c:1045
+msgid "parse error"
+msgstr "analiza eraro"
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1290
+#: plugins/sudoers/sudoreplay.c:1291 plugins/sudoers/sudoreplay.c:1587
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr "malvalida regulesprimo \"%s\": %s"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: malvalida protokolo-dosiero"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: mankas temp-indikila kampo"
+
+#: lib/iolog/iolog_legacy.c:90
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: temp-indikilo %s: %s"
+
+#: lib/iolog/iolog_legacy.c:97
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: mankas kampo de uzanto"
+
+#: lib/iolog/iolog_legacy.c:108
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: mankas kampo de runa uzanto"
+
+#: lib/iolog/iolog_legacy.c:119
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: mankas kampo de runa grupo"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s ekzistas sed ne dosierujo (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:124 lib/iolog/iolog_mkdtemp.c:80
+#: logsrvd/iolog_writer.c:795 plugins/sudoers/timestamp.c:218
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "ne eblas mkdir-i: %s"
+
+#: lib/iolog/iolog_mkdtemp.c:85 plugins/sudoers/visudo.c:769
+#: plugins/sudoers/visudo.c:803 plugins/sudoers/visudo.c:809
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "ne eblas ŝanĝi reĝimon de %s al 0%o"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "nelegebla tempo-registra dosiero: %s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "malvalida linio en la tempo-registran dosieron: %s"
+
+#: logsrvd/iolog_writer.c:65
+#, c-format
+msgid "%s: protocol error: NULL key"
+msgstr "%s: protokoleraro: nul-ŝlosilo"
+
+#: logsrvd/iolog_writer.c:69
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s: protokoleraro: erara tipo per %s"
+
+#: logsrvd/iolog_writer.c:74 logsrvd/logsrvd_local.c:109
+#: logsrvd/logsrvd_local.c:123 logsrvd/logsrvd_local.c:131
+#: logsrvd/logsrvd_local.c:149
+#, c-format
+msgid "%s: protocol error: NULL value found in %s"
+msgstr "%s: protokoleraro: nul-valoro trovita en %s"
+
+#: logsrvd/iolog_writer.c:141 plugins/sudoers/logging.c:1024
+#: plugins/sudoers/policy.c:613
+msgid "unable to generate UUID"
+msgstr "ne eblas genero de UUID"
+
+#: logsrvd/iolog_writer.c:354 logsrvd/iolog_writer.c:359
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:369
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s: protokola eraro: %s estas malhavata de AcceptMessage"
+
+#: logsrvd/iolog_writer.c:430
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s: ne eblas formati seancan identigilon"
+
+#: logsrvd/iolog_writer.c:444 logsrvd/iolog_writer.c:458
+#: logsrvd/iolog_writer.c:472 logsrvd/iolog_writer.c:487
+#: logsrvd/iolog_writer.c:501 logsrvd/iolog_writer.c:515
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s: %s ne estas valorizita"
+
+#: logsrvd/iolog_writer.c:551 logsrvd/iolog_writer.c:558
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr "ne eblas etendi iolog-vojn %s"
+
+#: logsrvd/iolog_writer.c:576
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr "ne eblas krei iolog-vojon %s"
+
+#: logsrvd/iolog_writer.c:606
+#, c-format
+msgid "invalid iofd %d"
+msgstr "nevalida eneliga dosierpriskribilo %d"
+
+#: logsrvd/iolog_writer.c:626
+#, c-format
+msgid "error closing iofd %u: %s"
+msgstr "eraro dum fermi eneligan dosierpriskribilon %u: %s"
+
+#: logsrvd/iolog_writer.c:647
+#, c-format
+msgid "error flushing iofd %u: %s"
+msgstr "eraro dum elbufrigi eneligan eneligan priskribilon %u: %s"
+
+#: logsrvd/iolog_writer.c:765
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "nevalida eneliga protokolo %s: %s estas referencita sed ne difinita"
+
+#: logsrvd/iolog_writer.c:777 logsrvd/logsrvd_journal.c:391
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "%s: ne eblas trovi daŭrigan punkton [%lld, %ld]"
+
+#: logsrvd/iolog_writer.c:799 logsrvd/logsrvd_journal.c:434
+#: logsrvd/logsrvd_queue.c:115 logsrvd/tls_init.c:256
+#: plugins/sudoers/check.c:285 plugins/sudoers/cvtsudoers.c:758
+#: plugins/sudoers/cvtsudoers.c:780 plugins/sudoers/cvtsudoers.c:1461
+#: plugins/sudoers/cvtsudoers_csv.c:697 plugins/sudoers/cvtsudoers_json.c:902
+#: plugins/sudoers/cvtsudoers_ldif.c:711 plugins/sudoers/sudoers.c:1291
+#: plugins/sudoers/sudoers.c:1317 plugins/sudoers/sudoreplay.c:1497
+#: plugins/sudoers/timestamp.c:478 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:990
+#, c-format
+msgid "unable to open %s"
+msgstr "ne eblas malfermi: %s"
+
+#: logsrvd/iolog_writer.c:811 logsrvd/logsrv_util.c:111
+#: logsrvd/logsrv_util.c:118 plugins/sudoers/sudoreplay.c:355
+#: plugins/sudoers/sudoreplay.c:361
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "ne eblas malfermi: %s/%s"
+
+#: logsrvd/iolog_writer.c:824
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "ne eblas kopii de %s/%s al %s/%s: %s"
+
+#: logsrvd/iolog_writer.c:853 logsrvd/logsrvd_journal.c:198
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "ne eblas alinomo de %s al %s"
+
+#: logsrvd/logsrv_util.c:153 logsrvd/logsrv_util.c:182
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s: ne eblas trovi daŭrigan punkton [%lld, %ld]"
+
+#: logsrvd/logsrv_util.c:165
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "mankas eneliga protokolo %s/%s"
+
+#: logsrvd/logsrv_util.c:172
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s: ne eblas serĉi antaŭen: %zu"
+
+#: logsrvd/logsrvd.c:271 logsrvd/logsrvd_queue.c:135
+msgid "unable to connect to relay"
+msgstr "ne eblas konektiĝi al relajso"
+
+#: logsrvd/logsrvd.c:338 logsrvd/logsrvd_relay.c:847
+#, c-format
+msgid "server message too large: %zu"
+msgstr "servila mesaĝo tro granda: %zu"
+
+#: logsrvd/logsrvd.c:430 logsrvd/logsrvd.c:553 logsrvd/logsrvd.c:639
+#: logsrvd/logsrvd.c:881 logsrvd/logsrvd.c:895 logsrvd/logsrvd.c:1056
+#: logsrvd/logsrvd.c:1181 logsrvd/logsrvd.c:1354 logsrvd/logsrvd.c:1372
+#: logsrvd/logsrvd.c:1471 logsrvd/logsrvd.c:1596 logsrvd/logsrvd.c:1783
+#: logsrvd/logsrvd_journal.c:503 logsrvd/logsrvd_local.c:238
+#: logsrvd/logsrvd_queue.c:164 logsrvd/logsrvd_relay.c:172
+#: logsrvd/logsrvd_relay.c:249 logsrvd/logsrvd_relay.c:253
+#: logsrvd/logsrvd_relay.c:391 logsrvd/logsrvd_relay.c:583
+#: logsrvd/logsrvd_relay.c:747 logsrvd/logsrvd_relay.c:1137
+#: logsrvd/sendlog.c:1308 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:216 plugins/sudoers/audit.c:281
+#: plugins/sudoers/iolog.c:1041 plugins/sudoers/iolog.c:1175
+#: plugins/sudoers/iolog.c:1274 plugins/sudoers/log_client.c:121
+#: plugins/sudoers/log_client.c:343 plugins/sudoers/log_client.c:359
+#: plugins/sudoers/log_client.c:407 plugins/sudoers/log_client.c:613
+#: plugins/sudoers/log_client.c:620 plugins/sudoers/log_client.c:1114
+#: plugins/sudoers/log_client.c:1395 plugins/sudoers/log_client.c:1436
+#: plugins/sudoers/log_client.c:1444 plugins/sudoers/log_client.c:1603
+#: plugins/sudoers/log_client.c:1728 plugins/sudoers/log_client.c:2060
+#: plugins/sudoers/log_client.c:2068 plugins/sudoers/logging.c:148
+#: plugins/sudoers/logging.c:206 plugins/sudoers/sudoreplay.c:519
+#: plugins/sudoers/sudoreplay.c:566 plugins/sudoers/sudoreplay.c:808
+#: plugins/sudoers/sudoreplay.c:920 plugins/sudoers/sudoreplay.c:1011
+#: plugins/sudoers/sudoreplay.c:1026 plugins/sudoers/sudoreplay.c:1033
+#: plugins/sudoers/sudoreplay.c:1040 plugins/sudoers/sudoreplay.c:1047
+#: plugins/sudoers/sudoreplay.c:1054 plugins/sudoers/sudoreplay.c:1182
+msgid "unable to add event to queue"
+msgstr "ne eblas aldoni eventon al atendovico"
+
+#: logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:491 logsrvd/logsrvd.c:523
+#: logsrvd/logsrvd.c:577 logsrvd/logsrvd.c:656 logsrvd/logsrvd.c:692
+#: logsrvd/logsrvd.c:728 logsrvd/logsrvd.c:764 logsrvd/logsrvd_relay.c:512
+#: logsrvd/logsrvd_relay.c:545
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr "neatendita stato %d por %s"
+
+#: logsrvd/logsrvd.c:455 logsrvd/logsrvd.c:492 logsrvd/logsrvd.c:524
+#: logsrvd/logsrvd.c:578 logsrvd/logsrvd.c:657 logsrvd/logsrvd.c:693
+#: logsrvd/logsrvd.c:729 logsrvd/logsrvd.c:765 logsrvd/logsrvd_relay.c:514
+#: logsrvd/logsrvd_relay.c:547
+msgid "state machine error"
+msgstr "statmaŝina eraro"
+
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:462
+msgid "invalid AcceptMessage"
+msgstr "nevalida AcceptMessage"
+
+#: logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:499
+msgid "invalid RejectMessage"
+msgstr "nevalida RejectMessage"
+
+#: logsrvd/logsrvd.c:530 logsrvd/logsrvd.c:531
+msgid "invalid ExitMessage"
+msgstr "nevalida ExitMessage"
+
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:585
+msgid "invalid RestartMessage"
+msgstr "nevalida RestartMessage"
+
+#: logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:620
+msgid "invalid AlertMessage"
+msgstr "nevalida AlertMessage"
+
+#: logsrvd/logsrvd.c:661 logsrvd/logsrvd.c:697 logsrvd/logsrvd.c:733
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s: neatendita IoBuffer"
+
+#: logsrvd/logsrvd.c:662 logsrvd/logsrvd.c:698 logsrvd/logsrvd.c:734
+msgid "protocol error"
+msgstr "protokolo-eraro"
+
+#: logsrvd/logsrvd.c:668 logsrvd/logsrvd.c:669
+msgid "invalid IoBuffer"
+msgstr "malvalida IoBuffer"
+
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:705
+msgid "invalid ChangeWindowSize"
+msgstr "nevalida ChangeWindowSize"
+
+#: logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:741
+msgid "invalid CommandSuspend"
+msgstr "nevalida CommandSuspend"
+
+#: logsrvd/logsrvd.c:790 logsrvd/logsrvd_journal.c:302
+#: logsrvd/logsrvd_relay.c:654 logsrvd/sendlog.c:1207
+#: plugins/sudoers/log_client.c:1593
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "ne malpakeblas %s, grando %zu"
+
+#: logsrvd/logsrvd.c:835 logsrvd/logsrvd_journal.c:376
+#: logsrvd/logsrvd_relay.c:678
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "neatendita valoro %d de type_case en %s el %s"
+
+#: logsrvd/logsrvd.c:837
+msgid "unrecognized ClientMessage type"
+msgstr "nekonata ClientMessage-tipo"
+
+#: logsrvd/logsrvd.c:927
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "eksvalidiĝo dum skribado al kliento %s"
+
+#: logsrvd/logsrvd.c:932 logsrvd/logsrvd_relay.c:919 logsrvd/sendlog.c:1413
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr "mankanta skribobufo por kliento %s"
+
+#: logsrvd/logsrvd.c:1027
+#, c-format
+msgid "timed out reading from client %s"
+msgstr "eksvalidiĝo dum legado el kliento %s"
+
+#: logsrvd/logsrvd.c:1068 logsrvd/logsrvd_relay.c:782
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr "Dosierfino de %s sen konvena TLS-finiĝo"
+
+#: logsrvd/logsrvd.c:1112 logsrvd/logsrvd_relay.c:205 logsrvd/sendlog.c:336
+#: plugins/sudoers/log_client.c:723
+#, c-format
+msgid "client message too large: %zu"
+msgstr "klienta mesaĝo tro grandas: %zu"
+
+#: logsrvd/logsrvd.c:1113 logsrvd/logsrvd_journal.c:259
+#: logsrvd/logsrvd_journal.c:260
+msgid "client message too large"
+msgstr "klienta mesaĝo tro grandas"
+
+#: logsrvd/logsrvd.c:1131 logsrvd/logsrvd.c:1132
+msgid "invalid ClientMessage"
+msgstr "nevalida ClientMessage"
+
+#: logsrvd/logsrvd.c:1432
+msgid "unable to get remote IP addr"
+msgstr "ne eblas atingi foran IP-adreson"
+
+#: logsrvd/logsrvd.c:1463 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:281
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "Ne eblas almeti uzanto-datumojn al la SSL-objekto: %s"
+
+#: logsrvd/logsrvd.c:1646 logsrvd/logsrvd.c:2007
+msgid "unable to setup listen socket"
+msgstr "ne eblas agordi aŭskultan ŝtopilingon"
+
+#: logsrvd/logsrvd.c:1766
+#, c-format
+msgid "unexpected signal %d"
+msgstr "neatendita signalo %d"
+
+#: logsrvd/logsrvd.c:1909
+msgid "sudo log server"
+msgstr "protokolo-servilo de sudo"
+
+#: logsrvd/logsrvd.c:1911 logsrvd/sendlog.c:126
+msgid "Options:"
+msgstr "Modifiloj:"
+
+#: logsrvd/logsrvd.c:1913
+msgid "path to configuration file"
+msgstr "vojo al la agordo-dosiero"
+
+#: logsrvd/logsrvd.c:1915 logsrvd/sendlog.c:128
+msgid "display help message and exit"
+msgstr "montri helpan mesaĝon kaj finiĝi"
+
+#: logsrvd/logsrvd.c:1917
+msgid "do not fork, run in the foreground"
+msgstr "ne disforkiĝi, plenumiĝi en la malfono"
+
+#: logsrvd/logsrvd.c:1919
+msgid "percent chance connections will drop"
+msgstr "elcenta ŝanco, ke konektoj malkonektiĝos"
+
+#: logsrvd/logsrvd.c:1921 logsrvd/sendlog.c:158
+msgid "display version information and exit"
+msgstr "montri eldonan informon kaj finiĝi"
+
+#: logsrvd/logsrvd.c:1971 logsrvd/sendlog.c:1722
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "Protobuf-C, eldono 1.3 aŭ pli postulata"
+
+#: logsrvd/logsrvd.c:1987
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "validiga hazarda interrompiĝo-valoro: %s"
+
+#: logsrvd/logsrvd.c:1990 logsrvd/sendlog.c:1776
+#: plugins/sudoers/cvtsudoers.c:250 plugins/sudoers/sudoreplay.c:294
+#: plugins/sudoers/visudo.c:181
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s eldono %s\n"
+
+#: logsrvd/logsrvd_conf.c:422 plugins/sudoers/check.c:69
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/sudoers.c:419 plugins/sudoers/sudoers.c:929
+#: plugins/sudoers/sudoers.c:1034 plugins/sudoers/sudoers.c:1424
+#: plugins/sudoers/testsudoers.c:169 plugins/sudoers/testsudoers.c:285
+#: plugins/sudoers/testsudoers.c:459
+#, c-format
+msgid "unknown user %s"
+msgstr "nekonata uzanto %s"
+
+#: logsrvd/logsrvd_conf.c:439 plugins/sudoers/iolog.c:148
+#: plugins/sudoers/sudoers.c:425 plugins/sudoers/sudoers.c:1458
+#: plugins/sudoers/testsudoers.c:483
+#, c-format
+msgid "unknown group %s"
+msgstr "nekonata grupo %s"
+
+#: logsrvd/logsrvd_conf.c:457
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr "ne eblas analizi iolog-reĝimon %s"
+
+#: logsrvd/logsrvd_conf.c:474 logsrvd/logsrvd_conf.c:1243
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "nevalida valoro por %s: %s"
+
+#: logsrvd/logsrvd_conf.c:527
+msgid "TLS not supported"
+msgstr "TLS ne regata"
+
+#: logsrvd/logsrvd_conf.c:549
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:622 logsrvd/logsrvd_conf.c:1032
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s: ne tute kvalifikita vojo"
+
+#: logsrvd/logsrvd_conf.c:951 logsrvd/logsrvd_conf.c:967
+#: logsrvd/logsrvd_conf.c:1676
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "nekonata syslog-instalaĵo: %s"
+
+#: logsrvd/logsrvd_conf.c:983 logsrvd/logsrvd_conf.c:999
+#: logsrvd/logsrvd_conf.c:1015 logsrvd/logsrvd_conf.c:1680
+#: logsrvd/logsrvd_conf.c:1684 logsrvd/logsrvd_conf.c:1688
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "nekonata syslog-prioritato: %s"
+
+#: logsrvd/logsrvd_conf.c:1197
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d '[' sen kongruanta ']': %s"
+
+#: logsrvd/logsrvd_conf.c:1203
+#, c-format
+msgid "%s:%d garbage after ']': %s"
+msgstr "%s:%d '[' rubo post ']': %s"
+
+#: logsrvd/logsrvd_conf.c:1215
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s:%d nevalida agordo-sekcio: %s"
+
+#: logsrvd/logsrvd_conf.c:1223
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d nevalida agordo-dosiera linio: %s"
+
+#: logsrvd/logsrvd_conf.c:1229
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d atendas sekcian nomon: %s"
+
+#: logsrvd/logsrvd_conf.c:1251
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] nevalida ŝlosilo: %s"
+
+#: logsrvd/logsrvd_conf.c:1281 plugins/sudoers/cvtsudoers.c:273
+#: plugins/sudoers/logging.c:1076
+#, c-format
+msgid "unable to open log file %s"
+msgstr "ne eblas malfermi protokolon %s"
+
+#: logsrvd/logsrvd_conf.c:1763
+msgid "unable to initialize server TLS context"
+msgstr "ne eblas ekigi servilan TLS-kuntekston"
+
+#: logsrvd/logsrvd_conf.c:1783
+msgid "unable to initialize relay TLS context"
+msgstr "ne eblas ekigi relajsan SSL-kuntekston"
+
+#: logsrvd/logsrvd_journal.c:149 logsrvd/logsrvd_journal.c:430
+#: logsrvd/logsrvd_journal.c:435
+msgid "unable to create journal file"
+msgstr "ne eblas krei ĵurnalon"
+
+#: logsrvd/logsrvd_journal.c:153 logsrvd/logsrvd_queue.c:109
+#: plugins/sudoers/visudo.c:1046
+#, c-format
+msgid "unable to lock %s"
+msgstr "ne eblas ŝlosi: %s"
+
+#: logsrvd/logsrvd_journal.c:156
+msgid "unable to lock journal file"
+msgstr "ne eblas ŝlosi ĵurnalon"
+
+#: logsrvd/logsrvd_journal.c:164
+msgid "unable to open journal file"
+msgstr "ne eblas malfermi ĵurnalon"
+
+#: logsrvd/logsrvd_journal.c:185 logsrvd/logsrvd_journal.c:466
+#: logsrvd/logsrvd_journal.c:471
+msgid "unable to write journal file"
+msgstr "ne eblas skribi ĵurnalon: %s"
+
+#: logsrvd/logsrvd_journal.c:193 logsrvd/logsrvd_journal.c:200
+msgid "unable to rename journal file"
+msgstr "ne eblas alinomi ĵurnalon"
+
+#: logsrvd/logsrvd_journal.c:247 logsrvd/logsrvd_journal.c:248
+#: logsrvd/logsrvd_journal.c:288 logsrvd/logsrvd_journal.c:289
+msgid "unexpected EOF reading journal file"
+msgstr "neatendita dosierfino en ĵurnalo"
+
+#: logsrvd/logsrvd_journal.c:251 logsrvd/logsrvd_journal.c:252
+#: logsrvd/logsrvd_journal.c:292 logsrvd/logsrvd_journal.c:293
+msgid "error reading journal file"
+msgstr "eraro dum legi prelegan ĵurnalon"
+
+#: logsrvd/logsrvd_journal.c:304 logsrvd/logsrvd_journal.c:390
+msgid "invalid journal file, unable to restart"
+msgstr "nevalida ĵurnalo, ne eblas restarti"
+
+#: logsrvd/logsrvd_journal.c:449
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "ne eblas atingi punkton [%lld, %ld] en ĵurnalo %s"
+
+#: logsrvd/logsrvd_local.c:166
+#, c-format
+msgid "unexpected value_case %d in %s from %s"
+msgstr "neatendita valoro %d de value_case en %s el %s"
+
+#: logsrvd/logsrvd_local.c:194
+msgid "error parsing AcceptMessage"
+msgstr "neanalizebla AcceptMessage"
+
+#: logsrvd/logsrvd_local.c:205
+msgid "error creating I/O log"
+msgstr "malsukcesis kreiĝo de eneliga protokolo"
+
+#: logsrvd/logsrvd_local.c:228
+msgid "error logging accept event"
+msgstr "malsukcesis protokoli akcepto-eventon"
+
+#: logsrvd/logsrvd_local.c:267
+msgid "error parsing RejectMessage"
+msgstr "neanalizebla RejectMessage"
+
+#: logsrvd/logsrvd_local.c:291
+msgid "error logging reject event"
+msgstr "malsukcesis protokoli malakcepto-eventon"
+
+#: logsrvd/logsrvd_local.c:427 logsrvd/logsrvd_local.c:437
+msgid "error logging exit event"
+msgstr "malsukcesis protokoli finigo-eventon"
+
+#: logsrvd/logsrvd_local.c:494 logsrvd/logsrvd_local.c:495
+msgid "log is already complete, cannot be restarted"
+msgstr "protokolo jam estas kompleta, ne eblas restartigi ĝin"
+
+#: logsrvd/logsrvd_local.c:525
+msgid "unable to restart log"
+msgstr "ne eblas restartigi protokolon"
+
+#: logsrvd/logsrvd_local.c:541
+msgid "error parsing AlertMessage"
+msgstr "neanalizebla AlertMessage"
+
+#: logsrvd/logsrvd_local.c:551
+msgid "error logging alert event"
+msgstr "malsukcesis protokoli alarmo-eventon"
+
+#: logsrvd/logsrvd_local.c:587 logsrvd/logsrvd_local.c:650
+#: logsrvd/logsrvd_local.c:685
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr "ne eblas aranĝi tempo-bufron, longo %d"
+
+#: logsrvd/logsrvd_local.c:601 logsrvd/logsrvd_local.c:609
+#: logsrvd/logsrvd_local.c:657 logsrvd/logsrvd_local.c:692
+#: plugins/sudoers/sudoreplay.c:344 toke.l:981 toke.l:984
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: logsrvd/logsrvd_local.c:620
+msgid "randomly dropping connection"
+msgstr "hazarde ĉesanta konekto"
+
+#: logsrvd/logsrvd_local.c:632
+msgid "error writing IoBuffer"
+msgstr "neskribebla IoBuffer"
+
+#: logsrvd/logsrvd_local.c:667
+msgid "error writing ChangeWindowSize"
+msgstr "neskribela ChangeWindowSize"
+
+#: logsrvd/logsrvd_local.c:702
+msgid "error writing CommandSuspend"
+msgstr "neskribela CommandSuspend"
+
+#: logsrvd/logsrvd_relay.c:437
+msgid "TLS handshake with relay host failed"
+msgstr "Malsukcesis TLS-manpremo kun relajsa retnodo"
+
+#: logsrvd/logsrvd_relay.c:465
+msgid "unable to connect to relay host"
+msgstr "ne eblas konektiĝi al relajsa retnodo"
+
+#: logsrvd/logsrvd_relay.c:520
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s: nevalida ServerHello, server_id mankas"
+
+#: logsrvd/logsrvd_relay.c:522 logsrvd/sendlog.c:1111
+#: plugins/sudoers/log_client.c:1479
+msgid "invalid ServerHello"
+msgstr "nevalida ServerHello"
+
+#: logsrvd/logsrvd_relay.c:681
+msgid "unrecognized ServerMessage type"
+msgstr "nekonata ServerMessage-tipo"
+
+#: logsrvd/logsrvd_relay.c:710
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr "eksvalidiĝo dum legado el relajso %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:712
+msgid "timeout reading from relay"
+msgstr "eksvalidiĝo dum legado el relajso"
+
+#: logsrvd/logsrvd_relay.c:767
+msgid "relay host name does not match certificate"
+msgstr "relajsa retnodnomo ne kongruas kun atestilo"
+
+#: logsrvd/logsrvd_relay.c:773 logsrvd/logsrvd_relay.c:787
+#: logsrvd/logsrvd_relay.c:794
+msgid "error reading from relay"
+msgstr "eraro dum legi el relajso"
+
+#: logsrvd/logsrvd_relay.c:815
+msgid "unable to read from relay"
+msgstr "ne eblas legi el relajso"
+
+#: logsrvd/logsrvd_relay.c:830 logsrvd/logsrvd_relay.c:949
+msgid "relay server closed connection"
+msgstr "relajsa servilo fermis la konekton"
+
+#: logsrvd/logsrvd_relay.c:848
+msgid "server message too large"
+msgstr "servila mesaĝo tro granda"
+
+#: logsrvd/logsrvd_relay.c:912
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr "eksvalidiĝo dum skribado al relajso %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:914
+msgid "timeout writing to relay"
+msgstr "eksvalidiĝo dum skribado al relajso"
+
+#: logsrvd/logsrvd_relay.c:968 logsrvd/logsrvd_relay.c:975
+#: logsrvd/logsrvd_relay.c:987
+msgid "error writing to relay"
+msgstr "eraro dum skribi al relajso"
+
+#: logsrvd/sendlog.c:124
+msgid "send sudo I/O log to remote server"
+msgstr "%s - sendi eneligo-protokolon de sudo al fora servilo"
+
+#: logsrvd/sendlog.c:130
+msgid "only send an accept event (no I/O)"
+msgstr "sendi nur akcepto-eventon (neniun eneligon)"
+
+#: logsrvd/sendlog.c:133
+msgid "certificate bundle file to verify server's cert against"
+msgstr "atestilara dosiero kontraŭ kiu aŭtentigi la servilan atestilon"
+
+#: logsrvd/sendlog.c:135
+msgid "certificate file for TLS handshake"
+msgstr "atestila dosiero por TLS-manpremo"
+
+#: logsrvd/sendlog.c:138
+msgid "host to send logs to"
+msgstr "retnodo al kiu sendi protokolojn"
+
+#: logsrvd/sendlog.c:140
+msgid "remote ID of I/O log to be resumed"
+msgstr "fora identigilo de eneliga protokolo rekomenciĝonta"
+
+#: logsrvd/sendlog.c:143
+msgid "private key file"
+msgstr "privatŝlosila dosiero"
+
+#: logsrvd/sendlog.c:145
+msgid "do not verify server certificate"
+msgstr "ne aŭtentigi servilan atestilon"
+
+#: logsrvd/sendlog.c:148
+msgid "port to use when connecting to host"
+msgstr "porto uzoto dum konektiĝi al retnodo"
+
+#: logsrvd/sendlog.c:150
+msgid "restart previous I/O log transfer"
+msgstr "restartigi iaman eneligo-protokolan transdonon"
+
+#: logsrvd/sendlog.c:152
+msgid "reject the command with the given reason"
+msgstr "malakcepti la komandon kun la donita kialo"
+
+#: logsrvd/sendlog.c:154
+msgid "stop transfer after reaching this time"
+msgstr "haltigi transigon post atingo de ĉi tiu tempo"
+
+#: logsrvd/sendlog.c:156
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "provi revizian servilon per sendado de elektita eneliga logo n-foje paralele"
+
+#: logsrvd/sendlog.c:181 plugins/sudoers/log_client.c:453
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "ne eblas serĉi je %s:%s %s"
+
+#: logsrvd/sendlog.c:219
+msgid "unable to get server IP addr"
+msgstr "ne eblas atingi servilan IP-adreson"
+
+#: logsrvd/sendlog.c:314 plugins/sudoers/sudoreplay.c:868
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "ne eblas legi je %s/%s: %s"
+
+#: logsrvd/sendlog.c:1035 plugins/sudoers/iolog.c:959
+#: plugins/sudoers/iolog.c:1034
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "neatendita eneliga evento %d"
+
+#: logsrvd/sendlog.c:1088 logsrvd/sendlog.c:1105 logsrvd/sendlog.c:1139
+#: plugins/sudoers/log_client.c:1129 plugins/sudoers/log_client.c:1405
+#: plugins/sudoers/log_client.c:1473 plugins/sudoers/log_client.c:1512
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: neatendita stato %d"
+
+#: logsrvd/sendlog.c:1175 plugins/sudoers/log_client.c:1561
+#, c-format
+msgid "error message received from server: %s"
+msgstr "erarmesaĝo ricevita el servilo: %s"
+
+#: logsrvd/sendlog.c:1188 plugins/sudoers/log_client.c:1574
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "abortiga mesaĝo ricevita el servilo: %s"
+
+#: logsrvd/sendlog.c:1247 plugins/sudoers/log_client.c:1624
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s neatendita valoro %d de type_case"
+
+#: logsrvd/sendlog.c:1276
+msgid "timeout reading from server"
+msgstr "eksvalidiĝo dum legado el servilo"
+
+#: logsrvd/sendlog.c:1327 plugins/sudoers/log_client.c:1747
+msgid "host name does not match certificate"
+msgstr "retnodnomo ne kongruas kun atestilo"
+
+#: logsrvd/sendlog.c:1361
+msgid "premature EOF"
+msgstr "trofrua dosierfino"
+
+#: logsrvd/sendlog.c:1374 plugins/sudoers/log_client.c:1795
+#, c-format
+msgid "server message too large: %u"
+msgstr "servila mesaĝo tro granda: %u"
+
+#: logsrvd/sendlog.c:1430
+msgid "timeout writing to server"
+msgstr "eksvalidiĝo dum skribado al servilo"
+
+#: logsrvd/sendlog.c:1800
+msgid "both restart point and iolog ID must be specified"
+msgstr "kaj restartiga punkto kaj iolog-identigilo estas specifendaj"
+
+#: logsrvd/sendlog.c:1804
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "ne rajtas estigi restartigan punkton kiam neniu eneligaĵo estas sendita"
+
+#: logsrvd/sendlog.c:1880
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "trofrue finiĝis kun stato %d"
+
+#: logsrvd/sendlog.c:1881
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "pasinta tempo sentita al servilo [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1883
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "kunsendita punkto ricevita el servilo [%lld, %ld]"
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:315
+msgid "TLS handshake timeout occurred"
+msgstr "Eksvalidiĝo de TLS-manpremo okazis"
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:337 plugins/sudoers/log_client.c:353
+msgid "unable to set event"
+msgstr "ne eblas apliki eventon"
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "TLS-konekto malsukcesis: %s"
+
+#: logsrvd/tls_client.c:196
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "ne eblas generi SSL-objekton: %s"
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "Ne eblas almeti ŝtopilingon al la SSL-objekton: %s"
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr "ne eblas ekigi TLS-kuntekston"
+
+#: logsrvd/tls_init.c:138 logsrvd/tls_init.c:146
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "ne agordi ĉifraron de TLS 1.2 al %s: %s"
+
+#: logsrvd/tls_init.c:166 logsrvd/tls_init.c:174
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "ne agordi ĉifraron de TLS 1.3 al %s: %s"
+
+#: logsrvd/tls_init.c:206 logsrvd/tls_init.c:227
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "ne ablas agordi parametrojn de diffie-hellman: %s"
+
+#: logsrvd/tls_init.c:283
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "ne eblas krei TLS-kuntekston: %s"
+
+#: logsrvd/tls_init.c:290
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "ne ablas elekti minimuman eldonon de TLS al 1.2: %s"
+
+#: plugins/sudoers/audit.c:272 plugins/sudoers/audit.c:452
+#: plugins/sudoers/log_client.c:962 plugins/sudoers/log_client.c:1011
+#: plugins/sudoers/log_client.c:1060 plugins/sudoers/log_client.c:1185
+#: plugins/sudoers/logging.c:614 plugins/sudoers/logging.c:732
+#: plugins/sudoers/logging.c:859 plugins/sudoers/logging.c:1031
+#: plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr "ne eblas akiri la tempon de la tago"
+
+#: plugins/sudoers/auth/aix_auth.c:282
+#, c-format
+msgid "unable to change password for %s"
+msgstr "ne eblas ŝanĝi pasvorton por %s"
+
+#: plugins/sudoers/auth/bsdauth.c:78
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "ne eblas akiri ensalutan klason por uzanto %s"
+
+#: plugins/sudoers/auth/bsdauth.c:85
+msgid "invalid authentication type"
+msgstr "malvalida aŭtentikiga tipo"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to begin BSD authentication"
+msgstr "ne eblas komenci BSD-aŭtentikigon"
+
+#: plugins/sudoers/auth/bsdauth.c:97
+msgid "unable to initialize BSD authentication"
+msgstr "ne eblas komenci BSD-aŭtentikigon"
+
+#: plugins/sudoers/auth/bsdauth.c:191
+msgid "your account has expired"
+msgstr "via konto eksvalidiĝis"
+
+#: plugins/sudoers/auth/bsdauth.c:193
+msgid "approval failed"
+msgstr "aprobo malsukcesis"
+
+#: plugins/sudoers/auth/fwtk.c:62
+msgid "unable to read fwtk config"
+msgstr "ne eblas legi fwtk-agordon"
+
+#: plugins/sudoers/auth/fwtk.c:67
+msgid "unable to connect to authentication server"
+msgstr "ne eblas konektiĝi al aŭtentikiga servilo"
+
+#: plugins/sudoers/auth/fwtk.c:73 plugins/sudoers/auth/fwtk.c:99
+#: plugins/sudoers/auth/fwtk.c:131
+msgid "lost connection to authentication server"
+msgstr "konekto al aŭtentikiga servilo perdita"
+
+#: plugins/sudoers/auth/fwtk.c:77
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"eraro de aŭtentikiga servilo:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:116
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s ne eblas konverti ĉefon al ĉeno ('%s'): %s"
+
+#: plugins/sudoers/auth/kerb5.c:166
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: ne eblas analizi: '%s': %s"
+
+#: plugins/sudoers/auth/kerb5.c:175
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: ne eblas trovi ccache-on: %s"
+
+#: plugins/sudoers/auth/kerb5.c:226
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: ne eblas generi elektojn: %s"
+
+#: plugins/sudoers/auth/kerb5.c:241
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: ne eblas akiri atestilojn: %s"
+
+#: plugins/sudoers/auth/kerb5.c:254
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: ne eblas ekigi atestilan kaŝmemoron: %s"
+
+#: plugins/sudoers/auth/kerb5.c:257
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: ne eblas konservi atestilon en kaŝmemoro: %s"
+
+#: plugins/sudoers/auth/kerb5.c:322
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: ne eblas atingi gastiganton ĉefan: %s"
+
+#: plugins/sudoers/auth/kerb5.c:336
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: Ne eblas kontroli TGT! Ebla atako!: %s"
+
+#: plugins/sudoers/auth/pam.c:233
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "ne eblas ekigi PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:349
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Eraro de aŭtentikiga servilo: %s"
+
+#: plugins/sudoers/auth/pam.c:369
+msgid "account validation failure, is your account locked?"
+msgstr "malsukceso ĉe konta validigo, ĉu via konto estas ŝlosita?"
+
+#: plugins/sudoers/auth/pam.c:380
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Konto aŭ pasvorto eksvalidiĝis, restarigu vian pasvorton kaj reprovu"
+
+#: plugins/sudoers/auth/pam.c:387
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "ne eblas ŝanĝi eksvalidan pasvorton: %s"
+
+#: plugins/sudoers/auth/pam.c:398
+msgid "Password expired, contact your system administrator"
+msgstr "Pasvorto eksvalidiĝis, kontaktu vian sistemestron"
+
+#: plugins/sudoers/auth/pam.c:403
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Konto eksvalidiĝis aŭ PAM-agordon malhavas sekcion \"account\" por sudo, kontaktu vian sistemestron"
+
+#: plugins/sudoers/auth/pam.c:411 plugins/sudoers/auth/pam.c:416
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "Eraro de administro de konto PAM: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:100 plugins/sudoers/visudo.c:266
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "vi ne ekzistas en la datumbazo %s"
+
+#: plugins/sudoers/auth/securid5.c:76
+msgid "failed to initialise the ACE API library"
+msgstr "malsukcesis ekigi la bibliotekon de la API ACE"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "unable to contact the SecurID server"
+msgstr "ne eblas kontakti la servilon de SecurID"
+
+#: plugins/sudoers/auth/securid5.c:117
+msgid "User ID locked for SecurID Authentication"
+msgstr "Uzanto-identigilo ŝlosita pro Aŭtentikigo SecurID"
+
+#: plugins/sudoers/auth/securid5.c:121 plugins/sudoers/auth/securid5.c:174
+msgid "invalid username length for SecurID"
+msgstr "malvalida salutnoma longo por SecurID"
+
+#: plugins/sudoers/auth/securid5.c:125 plugins/sudoers/auth/securid5.c:179
+msgid "invalid Authentication Handle for SecurID"
+msgstr "malvalida Aŭtentikiga Traktilo por SecurID"
+
+#: plugins/sudoers/auth/securid5.c:129
+msgid "SecurID communication failed"
+msgstr "Komunikiĝo kun SecurID malsukcesis"
+
+#: plugins/sudoers/auth/securid5.c:133 plugins/sudoers/auth/securid5.c:222
+msgid "unknown SecurID error"
+msgstr "nekonata SecurID-eraro"
+
+#: plugins/sudoers/auth/securid5.c:169
+msgid "invalid passcode length for SecurID"
+msgstr "malvalida paskoda longo por SecurID"
+
+#: plugins/sudoers/auth/sia.c:72 plugins/sudoers/auth/sia.c:130
+msgid "unable to initialize SIA session"
+msgstr "ne eblas ekigi SIA-seascon"
+
+#: plugins/sudoers/auth/sudo_auth.c:141
+msgid "invalid authentication methods"
+msgstr "malvalidaj aŭtentikigaj metodoj"
+
+#: plugins/sudoers/auth/sudo_auth.c:143
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Nevalidaj aŭtentikigaj metodoj kompilitaj en sudo! Vi ne rajtas miksi dependan kaj sendependan aŭtentikigon."
+
+#: plugins/sudoers/auth/sudo_auth.c:296 plugins/sudoers/auth/sudo_auth.c:359
+msgid "no authentication methods"
+msgstr "neniu aŭtentikiga metodo"
+
+#: plugins/sudoers/auth/sudo_auth.c:298
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Ekzistas neniaj aŭtentikigaj metodoj kompilitaj en sudo! Se vi volas malŝalti aŭtentikigon, uzu la agordan parametron --disable-authentication."
+
+#: plugins/sudoers/auth/sudo_auth.c:361
+msgid "Unable to initialize authentication methods."
+msgstr "Ne eblas komenci aŭtentikigajn metodojn."
+
+#: plugins/sudoers/auth/sudo_auth.c:551
+msgid "Authentication methods:"
+msgstr "Aŭtentikigaj metodoj:"
+
+#: plugins/sudoers/bsm_audit.c:122 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "Ne eblis determini revizian kondiĉon"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:278
+msgid "unable to commit audit record"
+msgstr "ne eblis konservi revizian rikordon"
+
+#: plugins/sudoers/check.c:63 plugins/sudoers/check.c:74
+#: plugins/sudoers/lookup.c:79 plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "nekonata uid %u"
+
+#: plugins/sudoers/check.c:277
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "eraro dum legi prelegan dosieron %s"
+
+#: plugins/sudoers/check.c:280
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "ignoranta prelegan dosieron %s: ne regula dosiero"
+
+#: plugins/sudoers/check.c:293
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Ni fidas, ke vi ricevis la kutiman admonojn de la loka\n"
+"sistemestro. Resume memoru la jenajn punktojn:\n"
+"\n"
+" #1) Estimu la privatecon de aliaj.\n"
+" #2) Pensu antaŭ ol tajpi.\n"
+" #3) Granda povo devigas grandan responson.\n"
+"\n"
+
+#: plugins/sudoers/check.c:301
+msgid ""
+"For security reasons, the password you type will not be visible.\n"
+"\n"
+msgstr ""
+"Pro sekureco la pasvorto, kiun vi tajpos, ne videblos.\n"
+"\n"
+
+#: plugins/sudoers/check_aliases.c:93
+#, c-format
+msgid "cycle in %s \"%s\""
+msgstr "ciklo en %s \"%s\""
+
+#: plugins/sudoers/check_aliases.c:96
+#, c-format
+msgid "%s \"%s\" referenced but not defined"
+msgstr "%s \"%s\" estas referencita sed ne difinita"
+
+#: plugins/sudoers/cvtsudoers.c:211
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "alkremento de ordo: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:231
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "komenca ordo: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:242
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "ŝtopado de ordo: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:252 plugins/sudoers/visudo.c:183
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s gramatika eldono %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:282 plugins/sudoers/testsudoers.c:162
+#, c-format
+msgid "unsupported input format %s"
+msgstr "nesubtenata enig-formo %s"
+
+#: plugins/sudoers/cvtsudoers.c:300
+#, c-format
+msgid "unsupported output format %s"
+msgstr "nesubtenata elig-formo %s"
+
+#: plugins/sudoers/cvtsudoers.c:392
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: eliga kaj eniga dosieroj devas esti malsamaj"
+
+#: plugins/sudoers/cvtsudoers.c:406 plugins/sudoers/sudoers.c:151
+#: plugins/sudoers/sudoers.c:209 plugins/sudoers/testsudoers.c:315
+#: plugins/sudoers/visudo.c:276 plugins/sudoers/visudo.c:666
+msgid "unable to initialize sudoers default values"
+msgstr "ne eblas ekigi aŭtomatajn valorojn de sudoers"
+
+#: plugins/sudoers/cvtsudoers.c:533 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:612
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s: nekonata ŝlosilvorto %s"
+
+#: plugins/sudoers/cvtsudoers.c:658
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "malvalida defaŭlto-tipo: %s"
+
+#: plugins/sudoers/cvtsudoers.c:681
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "malvalida demeto-tipo: %s"
+
+#: plugins/sudoers/cvtsudoers.c:722 plugins/sudoers/cvtsudoers.c:738
+#, c-format
+msgid "invalid filter: %s"
+msgstr "malvalida filtro: %s"
+
+#: plugins/sudoers/cvtsudoers.c:783 plugins/sudoers/visudo.c:1000
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "malsukcesis analizi dosieron %s, nekonata eraro"
+
+#: plugins/sudoers/cvtsudoers.c:1508 plugins/sudoers/sudoreplay.c:1143
+#: plugins/sudoers/timestamp.c:353 plugins/sudoers/timestamp.c:356
+#, c-format
+msgid "unable to write to %s"
+msgstr "ne eblas skribi al %s"
+
+#: plugins/sudoers/cvtsudoers.c:1536
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s - konverti inter dosierformoj de sudoers\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1538
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Modifiloj:\n"
+" -b, --base=DN la baza DN por petoj de sudo LDAP\n"
+" -c, --config=agordo la vojo al la agordo-dosiero\n"
+" -d, --defaults=deftipoj nur konverti Defaŭltojn el la indikitaj tipoj\n"
+" -e, --expand-aliases disvolvigi kromnomojn dum konverto\n"
+" -f, --output-format=formo difini elig-formon: JSON, LDIF aŭ sudoers\n"
+" -i, --input-format=formo difini enig-formon: LDIF aŭ sudoers\n"
+" -I, --increment=num kiom alkrementi po ĉiu sudoOrder\n"
+" -h, --help montri helpmesaĝo kaj eliri\n"
+" -m, --match=filtro nur konverti enigojn kiuj akordas al la filtro\n"
+" -M, --match-local akordo-filtro uzas datumbazojn de passwd kaj de group\n"
+" -o, --output=elig_dosiero skribi konvertitan sudoers al elig-dosiero\n"
+" -O, --order-start=num ekpunkto por la unua sudoOrder\n"
+" -p, --prune-matches pritondi nekongruantajn uzantojn, grupojn kaj gastigantojn\n"
+" -P, --padding=num baza ŝtopo por alkremento de sudoOrder\n"
+" -s, --suppress=sekcioj demeti eligon el kelkaj sekcioj\n"
+" -V, --version montri informon pri versio kaj eliri"
+
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:245 plugins/sudoers/cvtsudoers_ldif.c:252
+#: plugins/sudoers/cvtsudoers_ldif.c:594 plugins/sudoers/env.c:340
+#: plugins/sudoers/env.c:347 plugins/sudoers/env.c:458
+#: plugins/sudoers/ldap.c:511 plugins/sudoers/ldap.c:629
+#: plugins/sudoers/ldap.c:1003 plugins/sudoers/ldap_conf.c:219
+#: plugins/sudoers/ldap_conf.c:310 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:93 plugins/sudoers/logging.c:479
+#: plugins/sudoers/policy.c:828 plugins/sudoers/policy.c:840
+#: plugins/sudoers/prompt.c:169 plugins/sudoers/serialize_list.c:62
+#: plugins/sudoers/serialize_list.c:71 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/sudoreplay.c:1340 plugins/sudoers/sudoreplay.c:1346
+#: plugins/sudoers/sudoreplay.c:1352 plugins/sudoers/testsudoers.c:306
+#: plugins/sudoers/toke_util.c:217 toke.l:995 toke.l:1277
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "interna eraro, troo en %s"
+
+#: plugins/sudoers/cvtsudoers_csv.c:454 plugins/sudoers/cvtsudoers_csv.c:468
+#: plugins/sudoers/cvtsudoers_json.c:661 plugins/sudoers/cvtsudoers_json.c:676
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:362
+#: plugins/sudoers/ldap.c:495
+msgid "unable to get GMT time"
+msgstr "ne eblas atingi GMT-tempon"
+
+#: plugins/sudoers/cvtsudoers_csv.c:459 plugins/sudoers/cvtsudoers_csv.c:473
+#: plugins/sudoers/cvtsudoers_json.c:666 plugins/sudoers/cvtsudoers_json.c:681
+#: plugins/sudoers/cvtsudoers_ldif.c:354 plugins/sudoers/cvtsudoers_ldif.c:367
+#: plugins/sudoers/ldap.c:503
+msgid "unable to format timestamp"
+msgstr "ne eblas aranĝi tempo-indikilon"
+
+#: plugins/sudoers/cvtsudoers_json.c:481 plugins/sudoers/cvtsudoers_json.c:516
+#: plugins/sudoers/cvtsudoers_json.c:732
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: nekonata ero de defaults \"%s\""
+
+#: plugins/sudoers/cvtsudoers_ldif.c:663
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "tro multaj enigoj de sudoers, maksimume %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:706
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "la medivariablo SUDOERS_BASE ne estas difinita kaj la modifilo -b ne estis indikata."
+
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, c-format
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr "%s:%d:%d: konvertis gastigoliston al ALL"
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr "ne eblas trovi alinomon: %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, c-format
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr "%s:%d:%d: alinomo ŝanĝiĝinta de %s al %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr "%s:%d:%d: forigas duobligitan alinomon %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr "%s:%d:%d: konflikta ero Defafaults \"%s\" estas retnodo-specifa en %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, c-format
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr "%s:%d:%d: Defaults-ero \"%s\" nun specifa por retnodo %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr "%s:%d:%d ne eblas fari, ke Defaults \"%s\" estu retnodo-specifa"
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr "%s:%d:%d forigias Default-eron \"%s\" superregita de sinsekvaj eroj"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1088
+#, c-format
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr "%s:%d:%d: kunfundis userspec-on en %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1182
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr "%s:%d:%d:forigo de userspec superregita de sinsekvaj eroj"
+
+#: plugins/sudoers/def_data.c:56
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Syslog-trajto se syslog estas uzata por protokoli: %s"
+
+#: plugins/sudoers/def_data.c:60
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Syslog-prioritato por uzi, kiam uzanto sukcese aŭtentikiĝas: %s"
+
+#: plugins/sudoers/def_data.c:64
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Syslog-prioritato por uzi kiam uzanto malsukcese aŭtentikigas: %s"
+
+#: plugins/sudoers/def_data.c:68
+msgid "Put OTP prompt on its own line"
+msgstr "Meti OTP-demandilon en sia propra linio"
+
+#: plugins/sudoers/def_data.c:72
+msgid "Ignore '.' in $PATH"
+msgstr "Ignori '.' en $PATH"
+
+#: plugins/sudoers/def_data.c:76
+msgid "Always send mail when sudo is run"
+msgstr "Ĉiam sendi retmesaĝon kiam sudo plenumiĝas"
+
+#: plugins/sudoers/def_data.c:80
+msgid "Send mail if user authentication fails"
+msgstr "Sendi retmesaĝon se uzanto-aŭtentikiĝo malsukcesas"
+
+#: plugins/sudoers/def_data.c:84
+msgid "Send mail if the user is not in sudoers"
+msgstr "Sendi retmesaĝon se la uzanto ne estas en sudoers"
+
+#: plugins/sudoers/def_data.c:88
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Sendi retmesaĝon se la uzanto ne estas en sudoers por la gastiganto"
+
+#: plugins/sudoers/def_data.c:92
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Sendi retmesaĝon se la uzanto ne estas permesata plenumigi komandon"
+
+#: plugins/sudoers/def_data.c:96
+msgid "Send mail if the user tries to run a command"
+msgstr "Sendi retmesaĝon se la uzanto provi plenumigi komandon"
+
+#: plugins/sudoers/def_data.c:100
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Uzi apartan tempo-indikilon por ĉiu uzanto/tty-kombino"
+
+#: plugins/sudoers/def_data.c:104
+msgid "Lecture user the first time they run sudo"
+msgstr "Averti uzanton dum la unua fojo ĝi plenumigas je sudo"
+
+#: plugins/sudoers/def_data.c:108
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Dosiero havanta la sudo-averton: %s"
+
+#: plugins/sudoers/def_data.c:112
+msgid "Require users to authenticate by default"
+msgstr "Postulas, ke uzantoj aŭtentikiĝu aŭtomate"
+
+#: plugins/sudoers/def_data.c:116
+msgid "Root may run sudo"
+msgstr "Ĉefuzanto rajtas plenumigi: sudo"
+
+#: plugins/sudoers/def_data.c:120
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Protokoli la gastignomon en la (ne syslog) protokolo"
+
+#: plugins/sudoers/def_data.c:124
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Protokoli la jaron en la (ne syslog) protokolo"
+
+#: plugins/sudoers/def_data.c:128
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Se sudo estas vokata kun neniuj parametroj, komencu ŝelon"
+
+#: plugins/sudoers/def_data.c:132
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Valorizi medivariablon $HOME al la cela uzanto dum komenci ŝelon kun -s"
+
+#: plugins/sudoers/def_data.c:136
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Ĉiam valorizi medivariablon $HOME al la hejma dosierujo de la cela uzanto"
+
+#: plugins/sudoers/def_data.c:140
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Permesi, ke iu informokolektado por doni utilajn eraromesaĝojn"
+
+#: plugins/sudoers/def_data.c:144
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Postuli tute kvalifikitajn gastiganto-nomojn en la dosiero sudoers"
+
+#: plugins/sudoers/def_data.c:148
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Insulti la uzanton, kiam si enmetas malĝustan pasvorton"
+
+#: plugins/sudoers/def_data.c:152
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Nur permesi, ke uzanto plenumigu sudo-on se si havas tty-on"
+
+#: plugins/sudoers/def_data.c:156
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo honoru la medivariablon EDITOR"
+
+#: plugins/sudoers/def_data.c:160
+msgid "Prompt for root's password, not the users's"
+msgstr "Peti la ĉefuzantan pasvorton, ne la uzanto-pasvorton"
+
+#: plugins/sudoers/def_data.c:164
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Peti la pasvorton de runas_default, ne de la uzanto"
+
+#: plugins/sudoers/def_data.c:168
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Peti la pasvorton de la cela uzanto, ne la nuna uzanto"
+
+#: plugins/sudoers/def_data.c:172
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Apliki aŭtomataĵojn en la ensaluta klaso de la cela uzanto, se ĝi ekzistas"
+
+#: plugins/sudoers/def_data.c:176
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Valorizi la medivariablojn LOGNAME kaj USER"
+
+#: plugins/sudoers/def_data.c:180
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Nur valorizi la efikan uid-on al la cela uzanto, ne la realan uid-on"
+
+#: plugins/sudoers/def_data.c:184
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Ne ekigi la grupon vektoron al tio de la cela uzanto"
+
+#: plugins/sudoers/def_data.c:188
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Longo je kiu linfaldi la protokol-dosieraj linioj (0 por senfalda): %u"
+
+#: plugins/sudoers/def_data.c:192
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Eksvalidiĝo de la aŭtentikiga tempo-indikilo: %.1f minutoj"
+
+#: plugins/sudoers/def_data.c:196
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Eksvalidiĝo de la pasvortilo: %.1f minutoj"
+
+#: plugins/sudoers/def_data.c:200
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Nombro da provoj por enmeti pasvorton: %u"
+
+#: plugins/sudoers/def_data.c:204
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Umask uzi aŭ 07777 por uzi uzanton: 0%o"
+
+#: plugins/sudoers/def_data.c:208
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Vojo al protokolo: %s"
+
+#: plugins/sudoers/def_data.c:212
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Vojo al retpoŝtilo: %s"
+
+#: plugins/sudoers/def_data.c:216
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Parametroj por retpoŝtilo: %s"
+
+#: plugins/sudoers/def_data.c:220
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Retpoŝtadreso adresata: %s"
+
+#: plugins/sudoers/def_data.c:224
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Retpoŝtadreso adresanta: %s"
+
+#: plugins/sudoers/def_data.c:228
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Subjekta linio por ĉiuj mesaĝoj: %s"
+
+#: plugins/sudoers/def_data.c:232
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Neĝusta pasvorta mesaĝo: %s"
+
+#: plugins/sudoers/def_data.c:236
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Vojo al dosierujo de prelega stato: %s"
+
+#: plugins/sudoers/def_data.c:240
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Vojo al dosierujo de aŭtentikiga tempo-indikilo: %s"
+
+#: plugins/sudoers/def_data.c:244
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Estro de la dosierujo de aŭtentikiga tempo-indikilo: %s"
+
+#: plugins/sudoers/def_data.c:248
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Uzantoj en la grupo en devas plenumi la postulojn de pasvorto kaj PATH: %s"
+
+#: plugins/sudoers/def_data.c:252
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Defaŭlta pasvorta peto: %s"
+
+#: plugins/sudoers/def_data.c:256
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Se aktivigita, passprompt superregas sistemajn invitojn ĉiuokaze."
+
+#: plugins/sudoers/def_data.c:260
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Defaŭlta uzanto por plenumigi komandojn: %s"
+
+#: plugins/sudoers/def_data.c:264
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Valoro per kiu superregi la PATH-on de uzanto: %s"
+
+#: plugins/sudoers/def_data.c:268
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Vojo al la tekstoredaktilo uzota de visudo: %s"
+
+#: plugins/sudoers/def_data.c:272
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Kiam postuli pasvorton por la pseŭdokomando 'list' : %s"
+
+#: plugins/sudoers/def_data.c:276
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Kiam postuli pasvorton por la pseŭdokamando 'verify' : %s"
+
+#: plugins/sudoers/def_data.c:280
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "Antaŭŝargi la bibliotekon sudo_noexec, kiu anstataŭas la exec-funkciojn"
+
+#: plugins/sudoers/def_data.c:284
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Se LDAP-dosierujo estas aktiva, ni ignoru la lokan suders-dosieron"
+
+#: plugins/sudoers/def_data.c:288
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Dosiero-priskribiloj >= %d fermiĝos antaŭ ol plenumigi komandon"
+
+#: plugins/sudoers/def_data.c:292
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "Se elektita, uzantoj rajtas superregi la valoron de \"closefrom\" per la parametro -C"
+
+#: plugins/sudoers/def_data.c:296
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Permesi, ke uzantoj valorizu arbitrajn medivariablojn"
+
+#: plugins/sudoers/def_data.c:300
+msgid "Reset the environment to a default set of variables"
+msgstr "Restarigi la medion al apriora aro da variabloj"
+
+#: plugins/sudoers/def_data.c:304
+msgid "Environment variables to check for safety:"
+msgstr "Medivariabloj por kontroli por sekureco:"
+
+#: plugins/sudoers/def_data.c:308
+msgid "Environment variables to remove:"
+msgstr "Medivariabloj por forigi:"
+
+#: plugins/sudoers/def_data.c:312
+msgid "Environment variables to preserve:"
+msgstr "Medivariabloj konservi:"
+
+#: plugins/sudoers/def_data.c:316
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "SELinux-rolo por uzi en la nova sekureca kunteksto: %s"
+
+#: plugins/sudoers/def_data.c:320
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "SELinux-tipo por uzi en la nova sekureca kunteksto: %s"
+
+#: plugins/sudoers/def_data.c:324
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Vojo al media dosiero specifa al sudo: %s"
+
+#: plugins/sudoers/def_data.c:328
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Vojo al la neatingebla sudo-specifa medio-dosiero: %s"
+
+#: plugins/sudoers/def_data.c:332
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Lokaĵaro por uzi dum analizi dosieron sudoers: %s"
+
+#: plugins/sudoers/def_data.c:336
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Permesi, ke sudo peti pasvorton eĉ se ĝi estus videbla"
+
+#: plugins/sudoers/def_data.c:340
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Doni vidajn indikojn je la pasvorta enmetanta kiam ekzistas enmeto"
+
+#: plugins/sudoers/def_data.c:344
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Uzi pli rapida kunigo, kiu estas malpli ĝusta sed ne atingas la dosiersistemon"
+
+#: plugins/sudoers/def_data.c:348
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "La umask specifa en sudoers superregos tio de la uzanto, eĉ se ĝi estas pli permesema"
+
+#: plugins/sudoers/def_data.c:352
+msgid "Log user's input for the command being run"
+msgstr "Protokoli enmeton de uzanto por la komando plenumigata"
+
+#: plugins/sudoers/def_data.c:356
+msgid "Log the command's standard input if not connected to a terminal"
+msgstr "Protokoli la ĉefenigujon de komando se ne konektiĝinta al terminalo"
+
+#: plugins/sudoers/def_data.c:360
+msgid "Log the user's terminal input for the command being run"
+msgstr "Protokoli la terminalo-enmeton de uzanto por la komando plenumigata"
+
+#: plugins/sudoers/def_data.c:364
+msgid "Log the output of the command being run"
+msgstr "Protokoli la eligon de la komando, kiu estas plenumiĝi"
+
+#: plugins/sudoers/def_data.c:368
+msgid "Log the command's standard output if not connected to a terminal"
+msgstr "Protokoli la ĉefeligujon de komandon se ne konektiĝinta al terminalo"
+
+#: plugins/sudoers/def_data.c:372
+msgid "Log the command's standard error if not connected to a terminal"
+msgstr "Protokoli la ĉeferarujon de komandon se ne konektiĝinta al terminalo"
+
+#: plugins/sudoers/def_data.c:376
+msgid "Log the terminal output of the command being run"
+msgstr "Protokoli la terminalo-eligon de la komando plenumigata"
+
+#: plugins/sudoers/def_data.c:380
+msgid "Compress I/O logs using zlib"
+msgstr "Kunpremi eneligaj protokoloj per zlib"
+
+#: plugins/sudoers/def_data.c:384
+msgid "Always run commands in a pseudo-tty"
+msgstr "Ĉiam protokoli komandojn en pseŭda tty"
+
+#: plugins/sudoers/def_data.c:388
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Kromprogramo por kompreno de ne-uniksaj grupoj: %s"
+
+#: plugins/sudoers/def_data.c:392
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Dosierujo en kiu konservi eneligaj protokoloj: %s"
+
+#: plugins/sudoers/def_data.c:396
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Dosiero en kiu konservi la eneliga protokolo: %s"
+
+#: plugins/sudoers/def_data.c:400
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Aldoni eron al la utmp/utmpx-dosiero dum generi pty-on"
+
+#: plugins/sudoers/def_data.c:404
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Valorizi uzanton en utmp al la plenumigkiela uzanto, ne la vokanta uzanto"
+
+#: plugins/sudoers/def_data.c:408
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Aro da permesitaj privilegioj: %s"
+
+#: plugins/sudoers/def_data.c:412
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Aro da limigaj privilegioj: %s"
+
+#: plugins/sudoers/def_data.c:416
+msgid "Run commands on a pty in the background"
+msgstr "Plenumigi komandojn en pty en la fono"
+
+#: plugins/sudoers/def_data.c:420
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "PAM-servonomo uzota: %s"
+
+#: plugins/sudoers/def_data.c:424
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "PAM-servonomo uzota por ensalutaj ŝeloj: %s"
+
+#: plugins/sudoers/def_data.c:428
+#, c-format
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr "PAM-servonomo uzota kiam sudo estas plenumigota ken la elektebleco -A: %s"
+
+#: plugins/sudoers/def_data.c:432
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Ne eblas establi PAM-atestilojn por la cela uzanto"
+
+#: plugins/sudoers/def_data.c:436
+msgid "Create a new PAM session for the command to run in"
+msgstr "Krei novan PAM-seancon en kiu la komando plenumiĝos"
+
+#: plugins/sudoers/def_data.c:440
+msgid "Perform PAM account validation management"
+msgstr "Administradi validigon de konto PAM"
+
+#: plugins/sudoers/def_data.c:444
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "Maksimuma sinsekva numero de la eneliga protokolo: %s"
+
+#: plugins/sudoers/def_data.c:448
+msgid "Enable sudoers netgroup support"
+msgstr "Aktivigi retgrupan regon de sudoers"
+
+#: plugins/sudoers/def_data.c:452
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Kontroli gepatrajn dosierujojn pri skribeblo dum redakto de dosieroj per sudoedit"
+
+#: plugins/sudoers/def_data.c:456
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Sekvi simbolajn ligojn dum redakto de dosieroj per sudoedit"
+
+#: plugins/sudoers/def_data.c:460
+msgid "Query the group plugin for unknown system groups"
+msgstr "Informo-mendi la grupan kromprogramon por nekonataj sistem-grupoj"
+
+#: plugins/sudoers/def_data.c:464
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Kongrui retgrupoj surbaze de entuta n-opo: uzanto, gastiganto kaj domajno"
+
+#: plugins/sudoers/def_data.c:468
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Permesi ke komandoj estu plenumataj eĉ se sudo ne povas skribi al la ekzamena protokolo"
+
+#: plugins/sudoers/def_data.c:472
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Permesi ke komandoj estu plenumataj eĉ se sudo ne povas skribi al la eneliga protokolo"
+
+#: plugins/sudoers/def_data.c:476
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Permesi ke komandoj estu plenumataj eĉ se sudo ne povas skribi al la protokola dosiero"
+
+#: plugins/sudoers/def_data.c:480
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Solvi grupojn en sudoers kaj kongrui al la grupa ID, ne la nomo"
+
+#: plugins/sudoers/def_data.c:484
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Protokoleroj pli grandaj ol tiu ĉi valoro estos dividitaj en multoblajn mesaĝojn en syslog: %u"
+
+#: plugins/sudoers/def_data.c:488
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Uzanto kiu posedos la eneligajn protokol-dosierojn: %s"
+
+#: plugins/sudoers/def_data.c:492
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Grupo kiu posedos la eneligajn protokol-dosierojn: %s"
+
+#: plugins/sudoers/def_data.c:496
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Dosier-reĝimo uzota por la eneligaj protokol-dosieroj: 0%o"
+
+#: plugins/sudoers/def_data.c:500
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Plenumigi komandojn laŭ dosiernumero anstataŭ laŭ vojo: %s"
+
+#: plugins/sudoers/def_data.c:504
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Ignori nekonatajn erojn Defaults en sudoers anstataŭ prezenti averton"
+
+#: plugins/sudoers/def_data.c:508
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Tempo laŭ sekundoj pust kiu la komando finiĝos: %u"
+
+#: plugins/sudoers/def_data.c:512
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Permesi al la uzanto specifi eksvalidiĝon per la komandlinio"
+
+#: plugins/sudoers/def_data.c:516
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Tuj elbufrigi eneligo-protokolajn datumojn en diskon anstataŭ enbufrigi ĝin"
+
+#: plugins/sudoers/def_data.c:520
+msgid "Include the process ID when logging via syslog"
+msgstr "Inkluzivigi la procezan identigilon dum protokoli per syslog"
+
+#: plugins/sudoers/def_data.c:524
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Tipo de tempindika rikordo por aŭtentikigo: %s"
+
+#: plugins/sudoers/def_data.c:528
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Mesaĝo pri malsukceso dum aŭtentikigo: %s"
+
+#: plugins/sudoers/def_data.c:532
+msgid "Ignore case when matching user names"
+msgstr "Preteratenti usklecon dum kongruo al uzantnomoj"
+
+#: plugins/sudoers/def_data.c:536
+msgid "Ignore case when matching group names"
+msgstr "Preteratenti usklecon dum kongruo al grupnomoj"
+
+#: plugins/sudoers/def_data.c:540
+msgid "Log when a command is allowed by sudoers"
+msgstr "Protokoli kiam komando estas permesata de sudoers"
+
+#: plugins/sudoers/def_data.c:544
+msgid "Log when a command is denied by sudoers"
+msgstr "Protokoli kiam komando estas malpermesata de sudoers"
+
+#: plugins/sudoers/def_data.c:548
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "Sudo: protokoli servilo(j)n al kiuj konektiĝi kun libervola pordo"
+
+#: plugins/sudoers/def_data.c:552
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Sudo: protokoli servilan eksvalidiĝon laŭ sekundoj: %u"
+
+#: plugins/sudoers/def_data.c:556
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "Ebligi ŝtopilingan elekton SO_KEEPALIVE por la ŝtopilingo konektita al la protokolservilo"
+
+#: plugins/sudoers/def_data.c:560
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "Vojo al atestilara dosiero de la kontrola servilo: %s"
+
+#: plugins/sudoers/def_data.c:564
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "Vojo al atestila dosiero de sudoers: %s"
+
+#: plugins/sudoers/def_data.c:568
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "Vojo al la privatŝlosila dosiero de sudoers: %s"
+
+#: plugins/sudoers/def_data.c:572
+msgid "Verify that the log server's certificate is valid"
+msgstr "Konstati ke la atestilo de la protokolo-servilo validas"
+
+#: plugins/sudoers/def_data.c:576
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "Permesi la uzon de nekonata plenumkiel-uzanto kajaŭ grupa identigilo"
+
+#: plugins/sudoers/def_data.c:580
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "Permesi nur plenumigi komandojn kiel uzanto kun valida ŝelo"
+
+#: plugins/sudoers/def_data.c:584
+msgid "Set the pam remote user to the user running sudo"
+msgstr "Agordi la PAM-foran uzanton al la uzanto, kiu plenumigas je sudo"
+
+#: plugins/sudoers/def_data.c:588
+msgid "Set the pam remote host to the local host name"
+msgstr "Agordi la PAM-foran retnodon al la loka nodnomo"
+
+#: plugins/sudoers/def_data.c:592
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "Kuranta dosierujo ŝanĝota antaŭ ol plenumi la komandon: %s"
+
+#: plugins/sudoers/def_data.c:596
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "Radika dosierujo ŝanĝota antaŭ ol plenumi la komandon: %s"
+
+#: plugins/sudoers/def_data.c:600
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "La formato de protokoloj por produkti je %s"
+
+#: plugins/sudoers/def_data.c:604
+msgid "Enable SELinux RBAC support"
+msgstr "Aktivigu regon de SELinux-RBAC"
+
+#: plugins/sudoers/def_data.c:608
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "Vojo al la dosiero, kiu estas kreota la unan fojon, kiam sudo estas plenumiĝinta: %s"
+
+#: plugins/sudoers/def_data.c:612
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "Interkapti pluajn komandojn kaj apliki al ili limigojn el sudoers"
+
+#: plugins/sudoers/def_data.c:616
+msgid "Log sub-commands run by the original command"
+msgstr "Protokoli subkomandojn plenumigitajn de la origina komando"
+
+#: plugins/sudoers/def_data.c:620
+msgid "Log the exit status of commands"
+msgstr "Protokoli la eligon de komandoj"
+
+#: plugins/sudoers/def_data.c:624
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr "Sinsekvaj komandoj en interkaptita seanco devas esti aŭtentigita"
+
+#: plugins/sudoers/def_data.c:628
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr "Permesi al interkaptita komando plenumi iujn setuid- aŭ setgid-programojn"
+
+#: plugins/sudoers/def_data.c:632
+#, c-format
+msgid "The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr "La maksimuma grando ĝis kiu la adresspaco de la procezo rajtas kreski (laŭ bajtoj): %s"
+
+#: plugins/sudoers/def_data.c:636
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr "La plej granda ŝuto-dosiero, kiu rajtas kreiĝi (laŭ bajtoj): %s"
+
+#: plugins/sudoers/def_data.c:640
+#, c-format
+msgid "The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr "La maksimumo da ĉefprocezora tempo, kiun procezo rajtas uzi (laŭ sekundoj): %s"
+
+#: plugins/sudoers/def_data.c:644
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr "La maksimuma grando de la datuma segmento por la procezo (laŭ bajtoj): %s"
+
+#: plugins/sudoers/def_data.c:648
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr "La plaj granda dosiero, kiun procezo rajtas krei (laŭ bajtoj): %s"
+
+#: plugins/sudoers/def_data.c:652
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr "La maksimuma nombro da fiksiloj, kiujn la procezo rajtas krei: %s"
+
+#: plugins/sudoers/def_data.c:656
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr "La maksumima grando, kiun la procezo rajtas fiksi en memoron (laŭ bajtoj): %s"
+
+#: plugins/sudoers/def_data.c:660
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr "La maksimuma nombro da dosieroj, kiujn la procezo rajtas teni malfermajn: %s"
+
+#: plugins/sudoers/def_data.c:664
+#, c-format
+msgid "The maximum number of processes that the user may run simultaneously: %s"
+msgstr "La maksimuma nombro da procezoj, kiujn la uzanta rajtas samtempe plenumigi: %s"
+
+#: plugins/sudoers/def_data.c:668
+#, c-format
+msgid "The maximum size to which the process's resident set size may grow (in bytes): %s"
+msgstr "La maksimuma grando ĝis kiu la loĝa aro de la procezo rajtas kreski (laŭ bajtoj): %s"
+
+#: plugins/sudoers/def_data.c:672
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr "La maksimuma grando ĝis kiu la staplo de la procezo rajtas kreski (laŭ bajtoj): %s"
+
+#: plugins/sudoers/def_data.c:676
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr "Provi aŭtentigo eĉ kiam en neinteraga reĝimo"
+
+#: plugins/sudoers/def_data.c:680
+msgid "Store plaintext passwords in I/O log input"
+msgstr "Konservi plattekstajn pasvortojn en eneliga protokolo"
+
+#: plugins/sudoers/def_data.c:684
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr "Listo da regulesprimo uzota kiam kongruanta kun pasvorta invitilo"
+
+#: plugins/sudoers/def_data.c:688
+#, c-format
+msgid "The mechanism used by the intercept and log_subcmds options: %s"
+msgstr "La meĥanismo uzata de la intercept- kaj log_subcmd-elektoj: %s"
+
+#: plugins/sudoers/def_data.c:692
+msgid "Attempt to verify the command and arguments after execution"
+msgstr "Provi aŭtentigi la komandon kaj parametrojn post plenumiĝo"
+
+#: plugins/sudoers/def_data.c:696
+#, c-format
+msgid "AppArmor profile to use in the new security context: %s"
+msgstr "AppArmor-profile uzota en la nova sekureca kunteksto: %s"
+
+#: plugins/sudoers/defaults.c:207
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "nekonata enigo de defaults \"%s\""
+
+#: plugins/sudoers/defaults.c:251
+#, c-format
+msgid "no value specified for \"%s\""
+msgstr "neniu valoro indikita por \"%s\""
+
+#: plugins/sudoers/defaults.c:260
+#, c-format
+msgid "invalid operator \"%c=\" for \"%s\""
+msgstr "nevalida operator \"%c=\" por \"%s\""
+
+#: plugins/sudoers/defaults.c:292
+#, c-format
+msgid "option \"%s\" does not take a value"
+msgstr "parametro \"%s\" ne povas havi valoron"
+
+#: plugins/sudoers/defaults.c:319
+#, c-format
+msgid "invalid Defaults type 0x%x for option \"%s\""
+msgstr "malvalida Defaults-tipo 0x%x por parametro \"%s\""
+
+#: plugins/sudoers/defaults.c:326
+#, c-format
+msgid "value \"%s\" is invalid for option \"%s\""
+msgstr "valoro \"%s\" estas malvalida por parametro \"%s\""
+
+#: plugins/sudoers/defaults.c:1176 plugins/sudoers/policy.c:213
+#: plugins/sudoers/policy.c:222
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr "vojnomo por \"%s\" tro longas"
+
+#: plugins/sudoers/defaults.c:1182
+#, c-format
+msgid "values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "valoroj por \"%s\" devas komenciĝi per '/', '~' aŭ '*'"
+
+#: plugins/sudoers/defaults.c:1189
+#, c-format
+msgid "values for \"%s\" must start with a '/'"
+msgstr "valoroj por \"%s\" devas komenciĝi per '/'"
+
+#: plugins/sudoers/display.c:160
+#, c-format
+msgid "LDAP Role: %s\n"
+msgstr "LDAP-rolo: %s\n"
+
+#: plugins/sudoers/display.c:163
+#, c-format
+msgid "Sudoers entry: %s\n"
+msgstr "Ero en sudoers: %s\n"
+
+#: plugins/sudoers/display.c:166
+msgid " RunAsUsers: "
+msgstr " RunAsUsers: "
+
+#: plugins/sudoers/display.c:181
+msgid " RunAsGroups: "
+msgstr " RunAsGroups: "
+
+#: plugins/sudoers/display.c:191
+msgid " Options: "
+msgstr " Modifiloj: "
+
+#: plugins/sudoers/display.c:255
+msgid " Commands:\n"
+msgstr " Komandoj:\n"
+
+#: plugins/sudoers/display.c:478
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Kongruantaj eroj de Defaults: %s en %s:\n"
+
+#: plugins/sudoers/display.c:496
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Plenumigkiela komando-specifaj aŭtomataĵoj por %s:\n"
+
+#: plugins/sudoers/display.c:514
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "Uzanto %s rajtas plenumigi la jenajn komandojn en %s:\n"
+
+#: plugins/sudoers/display.c:530
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Uzanto %s ne rajtas plenumigi sudo-on en %s.\n"
+
+#: plugins/sudoers/editor.c:180
+#, c-format
+msgid "ignoring editor: %.*s"
+msgstr "ignoras redaktilon: %.*s"
+
+#: plugins/sudoers/editor.c:181
+msgid "editor arguments may not contain \"--\""
+msgstr "redaktiloj parametroj ne povas enhavi \"--\""
+
+#: plugins/sudoers/env.c:426
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: medio tro granda"
+
+#: plugins/sudoers/env.c:1119
+msgid "unable to rebuild the environment"
+msgstr "ne eblas rekonstrui la medion"
+
+#: plugins/sudoers/env.c:1199
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "bedaŭre vi ne estas permesata valorizi la jenajn medivariablojn: %s"
+
+#: plugins/sudoers/filedigest.c:50
+#, c-format
+msgid "unsupported digest type %u for %s"
+msgstr "nekonata resumo-tipo %u por %s"
+
+#: plugins/sudoers/filedigest.c:77
+#, c-format
+msgid "%s: read error"
+msgstr "%s: lega eraro"
+
+#: plugins/sudoers/group_plugin.c:169 plugins/sudoers/sssd.c:578
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "ne eblas ŝarĝi je %s: %s"
+
+#: plugins/sudoers/group_plugin.c:181
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "ne eblas trovi simbolon \"group_plugin\" en %s"
+
+#: plugins/sudoers/group_plugin.c:186
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: nekongrua grupa kromprogramo: ĉefa eldono %d, atendita %d"
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "ne eblas trakti IP-adreson \"%s\""
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "ne eblas trakti retmaskon \"%s\""
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Loka IP-adresa kaj retmaska paroj:\n"
+
+#: plugins/sudoers/iolog.c:694
+msgid "unable to update sequence file"
+msgstr "ne eblas ĝisdatigi sinsekvan dosieron"
+
+#: plugins/sudoers/iolog.c:728 plugins/sudoers/iolog.c:917
+#: plugins/sudoers/iolog.c:1080 plugins/sudoers/iolog.c:1087
+#: plugins/sudoers/iolog.c:1209 plugins/sudoers/iolog.c:1216
+#: plugins/sudoers/iolog.c:1316 plugins/sudoers/iolog.c:1323
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "ne eblas skribi al eneliga protokoldosiero: %s"
+
+#: plugins/sudoers/iolog.c:736
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "ne eblas krei: %s/%s"
+
+#: plugins/sudoers/iolog.c:965
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: interna eraro, protokola dosiero de en/eligo por evento %d ne estas malferma"
+
+#: plugins/sudoers/iolog.c:1065 plugins/sudoers/iolog.c:1194
+#: plugins/sudoers/iolog.c:1300 plugins/sudoers/timestamp.c:897
+#: plugins/sudoers/timestamp.c:989 plugins/sudoers/visudo.c:555
+#: plugins/sudoers/visudo.c:561
+msgid "unable to read the clock"
+msgstr "ne eblas legi la horloĝon"
+
+#: plugins/sudoers/iolog.c:1292 plugins/sudoers/log_client.c:1203
+#: plugins/sudoers/log_client.c:1213 plugins/sudoers/log_client.c:1217
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: interna eraro, malvalida signalo %d"
+
+#: plugins/sudoers/ldap.c:154 plugins/sudoers/ldap_conf.c:289
+msgid "starttls not supported when using ldaps"
+msgstr "starttls ne estas regata dum uzo de ldaps"
+
+#: plugins/sudoers/ldap.c:226
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "ne eblas ekigi SSL-asertilon kaj ŝlosilan datumbazon: %s"
+
+#: plugins/sudoers/ldap.c:229
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "por uzi SSL, TLS_CERT devas havi valoron en %s"
+
+#: plugins/sudoers/ldap.c:1593
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "ne eblas ekigi LDAP-on: %s"
+
+#: plugins/sudoers/ldap.c:1630
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls specifita sed LDAP-bibliotekoj ne havas la funkciojn ldap_start_tls_s() kaj ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:1767 plugins/sudoers/parse_ldif.c:745
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "malvalida atributo de sudoOrder: %s"
+
+#: plugins/sudoers/ldap_conf.c:197
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: pordo tro grandas"
+
+#: plugins/sudoers/ldap_conf.c:258
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "nekonata retadresa tipo de LDAP: %s"
+
+#: plugins/sudoers/ldap_conf.c:285
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "ne eblas miksi sekurajn kaj nesekurajn retadresojn de LDAP"
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "ne eblas duobligi sudoOption: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "ne eblas konverti sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "ne eblas malfermi revizian sistemon"
+
+#: plugins/sudoers/linux_audit.c:104
+msgid "unable to send audit message"
+msgstr "ne eblas sendi revizian mesaĝon"
+
+#: plugins/sudoers/log_client.c:125 plugins/sudoers/log_client.c:412
+#: plugins/sudoers/log_client.c:1450 plugins/sudoers/log_client.c:2076
+msgid "error in event loop"
+msgstr "eraro en evento-iteracio"
+
+#: plugins/sudoers/log_client.c:205
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "Kreiĝo de nova objekto SSL_CTX malsukcesis: %s"
+
+#: plugins/sudoers/log_client.c:230
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "Ne eblas ŝargi aŭtoritatan atestilaron: %s"
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "ne eblas ŝargi atestilon %s"
+
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "unable to load private key %s"
+msgstr "ne eblas ŝarĝi privatŝlosilon %s"
+
+#: plugins/sudoers/log_client.c:275
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "Ne eblas generi SSL-objekton: %s"
+
+#: plugins/sudoers/log_client.c:364 plugins/sudoers/log_client.c:369
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "TLS-konekto al %s:%s malsukcesis: %s"
+
+#: plugins/sudoers/log_client.c:545
+msgid "TLS initialization was unsuccessful"
+msgstr "TLS-komenciĝo malsukcesis"
+
+#: plugins/sudoers/log_client.c:555
+msgid "TLS handshake was unsuccessful"
+msgstr "TLS-manpremo malsukcesis"
+
+#: plugins/sudoers/log_client.c:1221
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: interna eraro, malvalida finiĝo-stato %d"
+
+#: plugins/sudoers/log_client.c:1757 plugins/sudoers/log_client.c:1782
+msgid "lost connection to log server"
+msgstr "konekto al protokolo-servilo perdita"
+
+#: plugins/sudoers/log_client.c:1859
+msgid "missing write buffer"
+msgstr "mankanta skribobufo"
+
+#: plugins/sudoers/log_client.c:2015
+msgid "unable to connect to log server"
+msgstr "ne eblas konektiĝi al protokolo-servilo"
+
+#: plugins/sudoers/logging.c:295
+msgid "user NOT in sudoers"
+msgstr "uzanto NE estas en sudoers"
+
+#: plugins/sudoers/logging.c:297
+msgid "user NOT authorized on host"
+msgstr "uzanto NE permesata en gastiganto"
+
+#: plugins/sudoers/logging.c:299
+msgid "command not allowed"
+msgstr "komando ne permesata"
+
+#: plugins/sudoers/logging.c:320
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr "%s ne estas en la dosiero sudoers.\n"
+
+#: plugins/sudoers/logging.c:323
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr "Uzanto %s ne rajtas plenumigi sudo-on en %s.\n"
+
+#: plugins/sudoers/logging.c:326
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Bedaŭre uzanto %s ne rajtas plenumigi sudo en %s.\n"
+
+#: plugins/sudoers/logging.c:339
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s%s' as %s%s%s on %s.\n"
+msgstr "Bedaŭre uzanto %s ne rajtas plenumigi '%s%s%s%s' kiel %s%s%s en %s.\n"
+
+#: plugins/sudoers/logging.c:350
+msgid "This incident has been reported to the administrator.\n"
+msgstr "Ĉi tiu okazo raportiĝis al la administranto.\n"
+
+#: plugins/sudoers/logging.c:387 plugins/sudoers/sudoers.c:547
+#: plugins/sudoers/sudoers.c:549 plugins/sudoers/sudoers.c:551
+#: plugins/sudoers/sudoers.c:553 plugins/sudoers/sudoers.c:777
+#: plugins/sudoers/sudoers.c:779
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: komando ne trovita"
+
+#: plugins/sudoers/logging.c:389 plugins/sudoers/sudoers.c:543
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"ni malatentas \"%s\" trovita en '.'\n"
+"Uzu \"sudo ./%s\" se tio estas la \"%s\" , kiun vi volas plenumigi."
+
+#: plugins/sudoers/logging.c:409
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u malĝusta pasvorta provo"
+msgstr[1] "%u malĝustaj pasvortaj provoj"
+
+#: plugins/sudoers/logging.c:500
+msgid "authentication failure"
+msgstr "aŭtentiga malsukceso"
+
+#: plugins/sudoers/logging.c:539 plugins/sudoers/logging.c:558
+msgid "a password is required"
+msgstr "pasvorto estas bezonata"
+
+#: plugins/sudoers/logging.c:881
+msgid "problem parsing sudoers"
+msgstr "problemo dum analizi dosieron sudoers"
+
+#: plugins/sudoers/logging.c:922 plugins/sudoers/logging.c:930
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr "%s:%d:%d: %s"
+
+#: plugins/sudoers/logging.c:1108
+#, c-format
+msgid "unable to write log file %s"
+msgstr "ne eblas skribi al protokolo %s"
+
+#: plugins/sudoers/match_digest.c:107
+#, c-format
+msgid "digest for %s (%s) bad length %zu, expected %zu"
+msgstr "resumo por %s (%s): malbona longo %zu, atendita %zu"
+
+#: plugins/sudoers/match_digest.c:126
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "resumo por %s (%s) ne estas laŭ la formo %s"
+
+#: plugins/sudoers/parse_ldif.c:615
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "ni preteratentas malkompletan sudoRole: cn: %s"
+
+#: plugins/sudoers/parse_ldif.c:675
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "malvalida LDIF-atributo: %s"
+
+#: plugins/sudoers/parser_warnx.c:56
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: plugins/sudoers/parser_warnx.c:59
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s: %s\n"
+
+#: plugins/sudoers/pivot.c:71
+msgid "unable to restore root directory"
+msgstr "ne eblas restarigi la radikan dosierujon"
+
+#: plugins/sudoers/pivot.c:79
+msgid "unable to restore current working directory"
+msgstr "ne eblas restarigi la nunan labor-dosierujon"
+
+#: plugins/sudoers/policy.c:78 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "malvalida %.*s difinita de sudo-fasado"
+
+#: plugins/sudoers/policy.c:364 plugins/sudoers/testsudoers.c:329
+msgid "unable to parse network address list"
+msgstr "ne eblas trakti reto-adresan liston"
+
+#: plugins/sudoers/policy.c:556
+msgid "user name not set by sudo front-end"
+msgstr "uzantnomo ne difinita de sudo-fasado"
+
+#: plugins/sudoers/policy.c:560
+msgid "user-ID not set by sudo front-end"
+msgstr "uzanto-ID ne difinita de sudo-fasado"
+
+#: plugins/sudoers/policy.c:564
+msgid "group-ID not set by sudo front-end"
+msgstr "grupo-ID ne difinita de sudo-fasado"
+
+#: plugins/sudoers/policy.c:568
+msgid "host name not set by sudo front-end"
+msgstr "gastiganta nomo ne difinita de sudo-fasado"
+
+#: plugins/sudoers/policy.c:757
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "nevalida kuranta dosierujo: %s"
+
+#: plugins/sudoers/policy.c:944
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "malvalida chroot-dosierujo: %s"
+
+#: plugins/sudoers/policy.c:1153 plugins/sudoers/visudo.c:919
+#: plugins/sudoers/visudo.c:1218
+#, c-format
+msgid "unable to execute %s"
+msgstr "ne eblas plenumigi: %s"
+
+#: plugins/sudoers/policy.c:1225 plugins/sudoers/policy.c:1260
+#: plugins/sudoers/policy.c:1282 plugins/sudoers/policy.c:1300
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: nevalidaj reĝimaj flagoj el la fasado de sudo: 0x%x"
+
+#: plugins/sudoers/policy.c:1323
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Eldono %s de la konduta kromprogramo\n"
+
+#: plugins/sudoers/policy.c:1325
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Eldono %d de la gramatikilo de sudoers\n"
+
+#: plugins/sudoers/policy.c:1329
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Vojo de sudoers: %s\n"
+
+#: plugins/sudoers/policy.c:1332
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "vojo de nsswitch: %s\n"
+
+#: plugins/sudoers/policy.c:1335
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "vojo de ldap.conf: %s\n"
+
+#: plugins/sudoers/policy.c:1337
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "vojo de ldap.secret: %s\n"
+
+#: plugins/sudoers/policy.c:1370
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "ne eblas registri hokon el tipo %d (versio %d.%d)"
+
+#: plugins/sudoers/policy.c:1388
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "ne eblas malregistri hokon el tipo %d (versio %d.%d)"
+
+#: plugins/sudoers/pwutil.c:242 plugins/sudoers/pwutil.c:260
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "ne eblas konservi uid-on %u"
+
+#: plugins/sudoers/pwutil.c:254
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "ne eblas konservi uid-on %u, jam ekzistas"
+
+#: plugins/sudoers/pwutil.c:314 plugins/sudoers/pwutil.c:332
+#: plugins/sudoers/pwutil.c:395 plugins/sudoers/pwutil.c:440
+#, c-format
+msgid "unable to cache user %s"
+msgstr "ne eblas krei tenejan uzanton: %s"
+
+#: plugins/sudoers/pwutil.c:327
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "ne eblas konservi uzanton %s, jam ekzistas"
+
+#: plugins/sudoers/pwutil.c:559 plugins/sudoers/pwutil.c:577
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "ne eblas konservi gid-on %u"
+
+#: plugins/sudoers/pwutil.c:571
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "ne eblas konservi gid-on %u, jam ekzistas"
+
+#: plugins/sudoers/pwutil.c:625 plugins/sudoers/pwutil.c:643
+#: plugins/sudoers/pwutil.c:704 plugins/sudoers/pwutil.c:753
+#, c-format
+msgid "unable to cache group %s"
+msgstr "ne eblas konservi grupon %s"
+
+#: plugins/sudoers/pwutil.c:638
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "ne eblas konservi grupon %s, jam ekzistas"
+
+#: plugins/sudoers/pwutil.c:900 plugins/sudoers/pwutil.c:985
+#: plugins/sudoers/pwutil.c:1039 plugins/sudoers/pwutil.c:1095
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "ne eblas konservi grupan liston por %s, jam ekzistas"
+
+#: plugins/sudoers/pwutil.c:906 plugins/sudoers/pwutil.c:990
+#: plugins/sudoers/pwutil.c:1045 plugins/sudoers/pwutil.c:1100
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "ne eblas konservi grupliston por %s"
+
+#: plugins/sudoers/pwutil.c:979
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "ne eblas trakti grupon en %s"
+
+#: plugins/sudoers/pwutil.c:1089
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "ne eblas trakti gids por %s"
+
+#: plugins/sudoers/set_perms.c:120 plugins/sudoers/set_perms.c:457
+#: plugins/sudoers/set_perms.c:870 plugins/sudoers/set_perms.c:1186
+#: plugins/sudoers/set_perms.c:1490
+msgid "perm stack overflow"
+msgstr "permeso-staka troo"
+
+#: plugins/sudoers/set_perms.c:131 plugins/sudoers/set_perms.c:387
+#: plugins/sudoers/set_perms.c:468 plugins/sudoers/set_perms.c:736
+#: plugins/sudoers/set_perms.c:881 plugins/sudoers/set_perms.c:1109
+#: plugins/sudoers/set_perms.c:1197 plugins/sudoers/set_perms.c:1422
+#: plugins/sudoers/set_perms.c:1501 plugins/sudoers/set_perms.c:1592
+msgid "perm stack underflow"
+msgstr "permeso-staka maltroo"
+
+#: plugins/sudoers/set_perms.c:191 plugins/sudoers/set_perms.c:515
+#: plugins/sudoers/set_perms.c:1251 plugins/sudoers/set_perms.c:1535
+msgid "unable to change to root gid"
+msgstr "ne eblas ŝanĝi al radika gid"
+
+#: plugins/sudoers/set_perms.c:282 plugins/sudoers/set_perms.c:612
+#: plugins/sudoers/set_perms.c:1013 plugins/sudoers/set_perms.c:1328
+msgid "unable to change to runas gid"
+msgstr "ne eblas ŝanĝi al plenumigkiela gid"
+
+#: plugins/sudoers/set_perms.c:287 plugins/sudoers/set_perms.c:617
+#: plugins/sudoers/set_perms.c:1018 plugins/sudoers/set_perms.c:1333
+msgid "unable to set runas group vector"
+msgstr "ne eblas elekti vektoron de plenumigkiela grupo"
+
+#: plugins/sudoers/set_perms.c:298 plugins/sudoers/set_perms.c:628
+#: plugins/sudoers/set_perms.c:1027 plugins/sudoers/set_perms.c:1342
+msgid "unable to change to runas uid"
+msgstr "ne eblas ŝanĝi al plenumigkiela uid"
+
+#: plugins/sudoers/set_perms.c:320 plugins/sudoers/set_perms.c:650
+#: plugins/sudoers/set_perms.c:1047 plugins/sudoers/set_perms.c:1362
+msgid "unable to change to sudoers gid"
+msgstr "ne eblas ŝanĝi al gid de sudo-redaktantoj"
+
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579
+msgid "too many processes"
+msgstr "tro da procezoj"
+
+#: plugins/sudoers/solaris_audit.c:62
+msgid "unable to get current working directory"
+msgstr "ne eblas scii la nunan labor-dosierujon"
+
+#: plugins/sudoers/solaris_audit.c:70
+#, c-format
+msgid "truncated audit path ctx->user.cmnd: %s"
+msgstr "tranĉita ekzamen-vojo ctx->user.cmnd: %s"
+
+#: plugins/sudoers/solaris_audit.c:77
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "tranĉita ekzamen-vojo argv[0]: %s"
+
+#: plugins/sudoers/sssd.c:581
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "ne eblas ekigi SSS-fonton. Ĉu SSSD estas instalita en via maŝino?"
+
+#: plugins/sudoers/sssd.c:589 plugins/sudoers/sssd.c:598
+#: plugins/sudoers/sssd.c:607 plugins/sudoers/sssd.c:616
+#: plugins/sudoers/sssd.c:625
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "ne eblas trovi simbolon \"%s\" en %s"
+
+#: plugins/sudoers/sudoers.c:250
+#, c-format
+msgid "unable to get defaults from %s"
+msgstr "ne eblas atingi aprioraĵojn el %s"
+
+#: plugins/sudoers/sudoers.c:259
+msgid "no valid sudoers sources found, quitting"
+msgstr "ne validaj fontotekstoj de sudoers trovita, ĉesiganta"
+
+#: plugins/sudoers/sudoers.c:366
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers specifas, ke ĉefuzanto ne rajtas sudo-i"
+
+#: plugins/sudoers/sudoers.c:375
+msgid "user not allowed to override closefrom limit"
+msgstr "uzanto ne permesata superregi la limigon de closefrom"
+
+#: plugins/sudoers/sudoers.c:376
+msgid "you are not permitted to use the -C option"
+msgstr "vi ne rajtas uzi la parametron -C"
+
+#: plugins/sudoers/sudoers.c:440
+msgid "no tty"
+msgstr "neniu tty"
+
+#: plugins/sudoers/sudoers.c:441
+msgid "sorry, you must have a tty to run sudo"
+msgstr "bedaŭre vi devas havi tty-on por plenumigi sudo-on"
+
+#: plugins/sudoers/sudoers.c:449
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "nevalida ŝelo por uzanto %s: %s"
+
+#: plugins/sudoers/sudoers.c:491
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "uzanto ne rajtas ŝanĝi radikan dosierujon al %s"
+
+#: plugins/sudoers/sudoers.c:493
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "vi ne rajtas uzi la parametron -R kun %s"
+
+#: plugins/sudoers/sudoers.c:506
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "uzanto ne rajtas ŝanĝi dosierujon al %s"
+
+#: plugins/sudoers/sudoers.c:507
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "vi ne rajtas uzi la parametron -D kun %s"
+
+#: plugins/sudoers/sudoers.c:542
+msgid "command in current directory"
+msgstr "komando en nuna dosierujo"
+
+#: plugins/sudoers/sudoers.c:557
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr "\"cd\" estas apriora ŝelkomando, ne eblas rekte plenumigi ĝin"
+
+#: plugins/sudoers/sudoers.c:559
+msgid "the -s option may be used to run a privileged shell."
+msgstr "La elekton -s oni rajtas uzi por plenumigi privilegiitan ŝelon."
+
+#: plugins/sudoers/sudoers.c:561
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr "la elekto -D oni rajtas uzi por plenumigi komandon en specifa dosierujo."
+
+#: plugins/sudoers/sudoers.c:570
+msgid "user not allowed to set a command timeout"
+msgstr "uzanto ne rajtas elekti komando-eksvalidiĝon"
+
+#: plugins/sudoers/sudoers.c:572
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "bedaŭre vi ne rajtas elekti komando-eksvalidiĝon"
+
+#: plugins/sudoers/sudoers.c:580
+msgid "user not allowed to preserve the environment"
+msgstr "uzanto ne rajtas konservi la medion"
+
+#: plugins/sudoers/sudoers.c:582
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "bedaŭre vi ne rajtas konservi la medion"
+
+#: plugins/sudoers/sudoers.c:618
+msgid "no command specified"
+msgstr "Neniu komando donita"
+
+#: plugins/sudoers/sudoers.c:759
+msgid "error setting user-specified environment variables"
+msgstr "eraro dum valorizo de medivariablojn valorizitaj de la uzanto"
+
+#: plugins/sudoers/sudoers.c:1211
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "sudoedit ne devas plenumiĝi per sudo"
+
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:1613
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "ne eblas legi %s"
+
+#: plugins/sudoers/sudoers.c:1321 plugins/sudoers/visudo.c:1123
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s ne estas normala dosiero"
+
+#: plugins/sudoers/sudoers.c:1325 plugins/sudoers/timestamp.c:272 toke.l:1355
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s estas estrita de uid %u, devas esti %u"
+
+#: plugins/sudoers/sudoers.c:1330 plugins/sudoers/timestamp.c:279 toke.l:1360
+#, c-format
+msgid "%s is world writable"
+msgstr "%s estas skribebla de ĉiuj"
+
+#: plugins/sudoers/sudoers.c:1334 plugins/sudoers/timestamp.c:284 toke.l:1363
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s estas estrita de gid %u, devas esti %u"
+
+#: plugins/sudoers/sudoers.c:1363
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "nur ĉefuzanto rajtas uzi \"-c %s\""
+
+#: plugins/sudoers/sudoers.c:1382
+#, c-format
+msgid "unknown login class %s"
+msgstr "nekonata ensaluta klaso: %s"
+
+#: plugins/sudoers/sudoers_cb.c:120 plugins/sudoers/sudoers_cb.c:135
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "ne eblas trovi gastiganton %s"
+
+#: plugins/sudoers/sudoreplay.c:252
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "malvalida filtrila elekto: %s"
+
+#: plugins/sudoers/sudoreplay.c:268
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "malvalida maksimuma atendo: %s"
+
+#: plugins/sudoers/sudoreplay.c:291
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "malvalida rapida faktoro: %s"
+
+#: plugins/sudoers/sudoreplay.c:326
+#, c-format
+msgid "invalid time offset %s"
+msgstr "nevalida eksvalidiĝo-deŝovo %s"
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:340
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/tempo-registrado: %s"
+
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Refaranta sudo-seancon: %s"
+
+#: plugins/sudoers/sudoreplay.c:634
+msgid "unable to set tty to raw mode"
+msgstr "ne eblas elekti tty-on en nudan reĝimon"
+
+#: plugins/sudoers/sudoreplay.c:685
+msgid "Warning: your terminal is too small to properly replay the log."
+msgstr "Averto: via terminalo estas tro malgranda por konvene revidigi la protokolon."
+
+#: plugins/sudoers/sudoreplay.c:686
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Protokola grando estas %dx%d, sed via terminala grando estas %dx%d."
+
+#: plugins/sudoers/sudoreplay.c:714
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Refarado finita, premu iu ajn klavon por restarigi la terminalon."
+
+#: plugins/sudoers/sudoreplay.c:1217 plugins/sudoers/sudoreplay.c:1247
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "ambigua esprimo \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1269
+msgid "unmatched ')' in expression"
+msgstr "mankas krampo kongruanta al ')' en esprimo"
+
+#: plugins/sudoers/sudoreplay.c:1273
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "nekonata serĉaĵo \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1288
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s bezonas parametron"
+
+#: plugins/sudoers/sudoreplay.c:1298
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "ne eblis analizi daton \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1307
+msgid "unmatched '(' in expression"
+msgstr "mankas krampo kongruanta al '(' en esprimo"
+
+#: plugins/sudoers/sudoreplay.c:1309
+msgid "illegal trailing \"or\""
+msgstr "malvalida posta \"or\""
+
+#: plugins/sudoers/sudoreplay.c:1311
+msgid "illegal trailing \"!\""
+msgstr "malvalida posta \"!\""
+
+#: plugins/sudoers/sudoreplay.c:1417
+#, c-format
+msgid "unknown search type %d"
+msgstr "nekonata serĉtipo %d"
+
+#: plugins/sudoers/sudoreplay.c:1679
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "uzado: %s [-hnRS] [-d ujo] [-m num] [-s num] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1681
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "uzado: %s [-h] [-d ujo] -l [serĉaĵo]\n"
+
+#: plugins/sudoers/sudoreplay.c:1695
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - refari sudo-seancajn protokolojn\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1697
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Modifiloj:\n"
+" -d ,--directory=ujo specifi dosierujon por seancaj protokoloj\n"
+" -f, --filter=filtrilo specifi kiajn eneligajn tipo(j)n por montri\n"
+" -h, --help montri helpan mesaĝon kaj eliri\n"
+" -l, --list listigi haveblajn seancajn ID, kun nedeviga esprimo\n"
+" -m, --max-wait=num maksimuma nombro da sekundoj por atendi inter okazoj\n"
+" -n, --non-interactive neniu invito, seanco estas sendata al la norma eligo\n"
+" -R, --no-resize ne provi regrandigi la terminalon\n"
+" -S, --suspend-wait atendi dum la komando estas paŭzigita\n"
+" -s, --speed=num rapidigi aŭ malrapidigi eligon\n"
+" -V, --version eligi eldonan informon kaj eliri"
+
+#: plugins/sudoers/testsudoers.c:392
+#, c-format
+msgid ""
+"\n"
+"Invalid shell for user %s: %s\n"
+msgstr ""
+"\n"
+"Nevalida ŝelo por uzanto %s: %s\n"
+
+#: plugins/sudoers/testsudoers.c:411
+msgid ""
+"\n"
+"Password required"
+msgstr ""
+"\n"
+"Pasvorto estas postulata"
+
+#: plugins/sudoers/testsudoers.c:422
+msgid ""
+"\n"
+"Parse error"
+msgstr ""
+"\n"
+"Analiza eraro"
+
+#: plugins/sudoers/testsudoers.c:425
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Komando permesata"
+
+#: plugins/sudoers/testsudoers.c:428
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Komando rifuzata"
+
+#: plugins/sudoers/testsudoers.c:431
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Komando sen egalo"
+
+#: plugins/sudoers/timestamp.c:364 plugins/sudoers/timestamp.c:711
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "ne eblas mallongigi tempo-indikilan dosieron ĝis %lld bajtoj"
+
+#: plugins/sudoers/timestamp.c:908
+msgid "ignoring time stamp from the future"
+msgstr "ignoranta tempo-indikilon el la estonteco"
+
+#: plugins/sudoers/timestamp.c:931
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "tempo-indikilo tro estonte: %20.20s"
+
+#: plugins/sudoers/timestamp.c:1067
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "ne eblas ŝlosi tempo-indikilan dosieron %s"
+
+#: plugins/sudoers/timestamp.c:1114
+#, c-format
+msgid "%s:%d:%d timestampowner: unknown user %s"
+msgstr "%s:%d:%d: timestampowner: nekonata uzanto %s"
+
+#: plugins/sudoers/toke_util.c:159
+msgid "sudoedit should not be specified with a path"
+msgstr "sudoedit plej bone ne specifiĝu kun vojo"
+
+#: plugins/sudoers/visudo.c:308 plugins/sudoers/visudo.c:714
+#, c-format
+msgid "press return to edit %s: "
+msgstr "premu enen-klavon por redakti %s-on: "
+
+#: plugins/sudoers/visudo.c:323
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "enhavo de redakto-seanco restigita en %s"
+
+#: plugins/sudoers/visudo.c:401
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "specifita tekstoredaktilo (%s) ne ekzistas"
+
+#: plugins/sudoers/visudo.c:406
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "neniu tekstoredaktilo trovita (vojo = %s)"
+
+#: plugins/sudoers/visudo.c:494 plugins/sudoers/visudo.c:786
+#, c-format
+msgid "unable to stat %s"
+msgstr "ne eblas apliki stat al %s"
+
+#: plugins/sudoers/visudo.c:514 plugins/sudoers/visudo.c:522
+msgid "write error"
+msgstr "skriba eraro"
+
+#: plugins/sudoers/visudo.c:568
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "ne eblas apliki stat al provizora dosiero (%s), %s neŝanĝita"
+
+#: plugins/sudoers/visudo.c:575
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "nul-longa provizora dosiero (%s), %s neŝanĝita"
+
+#: plugins/sudoers/visudo.c:581
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "redaktilo (%s) malsukcesis, %s neŝanĝita"
+
+#: plugins/sudoers/visudo.c:613
+#, c-format
+msgid "%s unchanged"
+msgstr "%s neŝanĝita"
+
+#: plugins/sudoers/visudo.c:661
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "ne eblas remalfermi provizoran dosieron (%s), %s neŝanĝita."
+
+#: plugins/sudoers/visudo.c:674
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "ne eblas analizi provizoran dosieron (%s), nekonata eraro"
+
+#: plugins/sudoers/visudo.c:760 plugins/sudoers/visudo.c:790
+#: plugins/sudoers/visudo.c:797
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "ne eblas ŝanĝi (uid, gid) de %s al (%u, %u)"
+
+#: plugins/sudoers/visudo.c:825
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s kaj %s ne estas la sama dosiersistemo, uzanta mv-on por alinomi"
+
+#: plugins/sudoers/visudo.c:836
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "komando malsukcesis: '%s %s %s', %s neŝanĝita"
+
+#: plugins/sudoers/visudo.c:843
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "eraro dum alinomi %s-on; %s neŝanĝita"
+
+#: plugins/sudoers/visudo.c:864
+msgid "What now? "
+msgstr "Kion nun? "
+
+#: plugins/sudoers/visudo.c:878
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Elektoj estas:\n"
+" r(e)dakti refoje sudoers-dosieron\n"
+" (x) eliri sen konservi ŝanĝojn al sudoers-dosiero\n"
+" (Q) Eliri kaj konservi ŝanĝojn al sudoers-dosiero (DANĜERA!)\n"
+
+#: plugins/sudoers/visudo.c:923
+#, c-format
+msgid "unable to run %s"
+msgstr "ne eblas plenumigi: %s"
+
+#: plugins/sudoers/visudo.c:954
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: malĝusta estro (uid, gid) devas esti (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:965
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: misaj permesoj, devas esti reĝimo 0%o\n"
+
+#: plugins/sudoers/visudo.c:1017 plugins/sudoers/visudo.c:1024
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: analizita senerare\n"
+
+#: plugins/sudoers/visudo.c:1043
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s okupata, reprovu pli malfrue"
+
+#: plugins/sudoers/visudo.c:1047
+msgid "Edit anyway? [y/N]"
+msgstr "Ĉu redakti ja? [y/N]"
+
+#: plugins/sudoers/visudo.c:1206
+msgid "the -x option will be removed in a future release"
+msgstr "la elekto -x estos forigita en posta eldono"
+
+#: plugins/sudoers/visudo.c:1208
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "bonvolu konsideri uzi la utilaĵon cvtsudoers anstataŭe"
+
+#: plugins/sudoers/visudo.c:1228
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "Averto: %s:%d:%d: neuzata %s \"%s\""
+
+#: plugins/sudoers/visudo.c:1341
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - sekure redakti la dosieron sudoers\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1343
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -I, --no-includes do not edit include files\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Elektoj:\n"
+" -c, --check nur kontroli\n"
+" -f, --file=sudoers indiki lokon de la dosiero sudoers\n"
+" -h, --help montri helpan mesaĝon kaj eliri\n"
+" -I, --no-includes ne redakti inkluzivitajn dosierojn\n"
+" -q, --quiet pli silenta (quiet) pri sintaksaj eraroj\n"
+" -s, --strict severa kontrolado de sintakso\n"
+" -V, --version montri eldonon kaj eliri\n"
+
+#: toke.l:184
+msgid "empty string"
+msgstr "malplena ĉeno"
+
+#: toke.l:196 toke.l:566
+msgid "empty group"
+msgstr "malplena grupo"
+
+#: toke.l:206 toke.l:564
+msgid "empty netgroup"
+msgstr "malplena retgrupo"
+
+#: toke.l:284
+msgid "unterminated regular expression"
+msgstr "nefinigita regulesprimo: %s"
+
+#: toke.l:358 toke.l:370 toke.l:382 toke.l:398 toke.l:417 toke.l:457
+msgid "invalid line continuation"
+msgstr "malvalida linio-daŭrigo"
+
+#: toke.l:603 toke.l:615
+msgid "invalid IPv6 address"
+msgstr "malvalida IPv6-adreso"
+
+#: toke.l:863
+msgid "unexpected line break in string"
+msgstr "neatendita linirompo en ĉeno"
+
+#: toke.l:982
+msgid "ignoring editor backup file"
+msgstr "ignoras redaktilan savkopian dosieron"
+
+#: toke.l:985
+msgid "ignoring file name containing '.'"
+msgstr "ignoras dosiernomon kun '.'"
+
+#: toke.l:1310
+msgid "too many levels of includes"
+msgstr "tro da niveloj de inkluzivaĵoj"
diff --git a/plugins/sudoers/po/es.mo b/plugins/sudoers/po/es.mo
new file mode 100644
index 0000000..a8dc07a
--- /dev/null
+++ b/plugins/sudoers/po/es.mo
Binary files differ
diff --git a/plugins/sudoers/po/es.po b/plugins/sudoers/po/es.po
new file mode 100644
index 0000000..5ca9663
--- /dev/null
+++ b/plugins/sudoers/po/es.po
@@ -0,0 +1,1882 @@
+# Portable object template file for the sudoers plugin
+# This file is put in the public domain.
+#
+# Todd C. Miller <Todd.Miller@courtesan.com>, 2011-2015.
+# Carlos E. Robinson <carlos.e.r@opensuse.org>, 2015, 2016.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.8.15rc3\n"
+"Report-Msgid-Bugs-To: http://www.sudo.ws/bugs\n"
+"POT-Creation-Date: 2015-10-24 06:26-0600\n"
+"PO-Revision-Date: 2016-05-08 23:06+0200\n"
+"Last-Translator: Carlos E. Robinson <carlos.e.r@opensuse.org>\n"
+"Language-Team: Spanish <es@tp.org.es>\n"
+"Language: es\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Lokalize 1.5\n"
+
+#: confstr.sh:1
+msgid "syntax error"
+msgstr "error de sintaxis"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "contraseña de %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] contraseña para %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Contraseña: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** información de SEGURIDAD para %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Lo siento, pruebe otra vez."
+
+#: gram.y:183 gram.y:201 gram.y:207 gram.y:213 gram.y:219 gram.y:225
+#: gram.y:241 gram.y:248 gram.y:255 gram.y:262 gram.y:269 gram.y:285
+#: gram.y:308 gram.y:315 gram.y:322 gram.y:329 gram.y:336 gram.y:391
+#: gram.y:399 gram.y:409 gram.y:439 gram.y:446 gram.y:453 gram.y:460
+#: gram.y:572 gram.y:579 gram.y:588 gram.y:597 gram.y:614 gram.y:670
+#: gram.y:677 gram.y:684 gram.y:692 gram.y:784 gram.y:791 gram.y:798
+#: gram.y:805 gram.y:812 gram.y:838 gram.y:845 gram.y:852 gram.y:1136
+#: gram.y:1143 plugins/sudoers/alias.c:123 plugins/sudoers/alias.c:136
+#: plugins/sudoers/auth/bsdauth.c:141 plugins/sudoers/auth/kerb5.c:119
+#: plugins/sudoers/auth/kerb5.c:145 plugins/sudoers/auth/pam.c:398
+#: plugins/sudoers/auth/pam.c:449 plugins/sudoers/auth/rfc1938.c:109
+#: plugins/sudoers/auth/sia.c:59 plugins/sudoers/defaults.c:516
+#: plugins/sudoers/defaults.c:720 plugins/sudoers/defaults.c:880
+#: plugins/sudoers/editor.c:64 plugins/sudoers/editor.c:82
+#: plugins/sudoers/editor.c:92 plugins/sudoers/env.c:233
+#: plugins/sudoers/group_plugin.c:133 plugins/sudoers/iolog.c:586
+#: plugins/sudoers/iolog.c:618 plugins/sudoers/iolog_path.c:167
+#: plugins/sudoers/ldap.c:446 plugins/sudoers/ldap.c:477
+#: plugins/sudoers/ldap.c:529 plugins/sudoers/ldap.c:562
+#: plugins/sudoers/ldap.c:914 plugins/sudoers/ldap.c:1061
+#: plugins/sudoers/ldap.c:1348 plugins/sudoers/ldap.c:1521
+#: plugins/sudoers/ldap.c:1597 plugins/sudoers/ldap.c:1733
+#: plugins/sudoers/ldap.c:1757 plugins/sudoers/ldap.c:1787
+#: plugins/sudoers/ldap.c:1840 plugins/sudoers/ldap.c:1855
+#: plugins/sudoers/ldap.c:1951 plugins/sudoers/ldap.c:1984
+#: plugins/sudoers/ldap.c:2137 plugins/sudoers/ldap.c:2234
+#: plugins/sudoers/ldap.c:3041 plugins/sudoers/ldap.c:3074
+#: plugins/sudoers/ldap.c:3388 plugins/sudoers/ldap.c:3416
+#: plugins/sudoers/ldap.c:3427 plugins/sudoers/ldap.c:3517
+#: plugins/sudoers/ldap.c:3533 plugins/sudoers/linux_audit.c:76
+#: plugins/sudoers/logging.c:188 plugins/sudoers/logging.c:666
+#: plugins/sudoers/logging.c:924 plugins/sudoers/match.c:501
+#: plugins/sudoers/match.c:537 plugins/sudoers/match.c:699
+#: plugins/sudoers/match.c:756 plugins/sudoers/parse.c:235
+#: plugins/sudoers/parse.c:247 plugins/sudoers/parse.c:262
+#: plugins/sudoers/parse.c:274 plugins/sudoers/policy.c:384
+#: plugins/sudoers/policy.c:583 plugins/sudoers/prompt.c:93
+#: plugins/sudoers/sssd.c:160 plugins/sudoers/sssd.c:192
+#: plugins/sudoers/sssd.c:235 plugins/sudoers/sssd.c:242
+#: plugins/sudoers/sssd.c:278 plugins/sudoers/sssd.c:323
+#: plugins/sudoers/sssd.c:917 plugins/sudoers/sssd.c:1050
+#: plugins/sudoers/sudoers.c:159 plugins/sudoers/sudoers.c:294
+#: plugins/sudoers/sudoers.c:304 plugins/sudoers/sudoers.c:312
+#: plugins/sudoers/sudoers.c:365 plugins/sudoers/sudoers.c:663
+#: plugins/sudoers/sudoers.c:749 plugins/sudoers/sudoers.c:793
+#: plugins/sudoers/sudoers_debug.c:107 plugins/sudoers/sudoreplay.c:472
+#: plugins/sudoers/sudoreplay.c:668 plugins/sudoers/sudoreplay.c:780
+#: plugins/sudoers/sudoreplay.c:820 plugins/sudoers/sudoreplay.c:829
+#: plugins/sudoers/sudoreplay.c:839 plugins/sudoers/sudoreplay.c:847
+#: plugins/sudoers/sudoreplay.c:851 plugins/sudoers/sudoreplay.c:1007
+#: plugins/sudoers/sudoreplay.c:1011 plugins/sudoers/testsudoers.c:130
+#: plugins/sudoers/testsudoers.c:188 plugins/sudoers/testsudoers.c:215
+#: plugins/sudoers/testsudoers.c:232 plugins/sudoers/timestamp.c:390
+#: plugins/sudoers/timestamp.c:426 plugins/sudoers/timestamp.c:838
+#: plugins/sudoers/toke_util.c:56 plugins/sudoers/toke_util.c:109
+#: plugins/sudoers/toke_util.c:147 plugins/sudoers/visudo.c:152
+#: plugins/sudoers/visudo.c:213 plugins/sudoers/visudo.c:297
+#: plugins/sudoers/visudo.c:303 plugins/sudoers/visudo.c:433
+#: plugins/sudoers/visudo.c:979 plugins/sudoers/visudo.c:1023
+#: plugins/sudoers/visudo.c:1119 toke.l:785 toke.l:806 toke.l:816 toke.l:924
+#: toke.l:1082
+msgid "unable to allocate memory"
+msgstr "no se pudo asignar memoria"
+
+#: gram.y:471
+msgid "a digest requires a path name"
+msgstr "un compendio requiere un nombre de ruta"
+
+#: gram.y:1136 gram.y:1143 plugins/sudoers/auth/pam.c:398
+#: plugins/sudoers/auth/pam.c:449 plugins/sudoers/auth/rfc1938.c:109
+#: plugins/sudoers/defaults.c:516 plugins/sudoers/defaults.c:720
+#: plugins/sudoers/defaults.c:880 plugins/sudoers/editor.c:64
+#: plugins/sudoers/editor.c:82 plugins/sudoers/editor.c:92
+#: plugins/sudoers/env.c:233 plugins/sudoers/group_plugin.c:133
+#: plugins/sudoers/iolog.c:586 plugins/sudoers/iolog.c:618
+#: plugins/sudoers/iolog_path.c:167 plugins/sudoers/ldap.c:446
+#: plugins/sudoers/ldap.c:477 plugins/sudoers/ldap.c:529
+#: plugins/sudoers/ldap.c:562 plugins/sudoers/ldap.c:914
+#: plugins/sudoers/ldap.c:1061 plugins/sudoers/ldap.c:1348
+#: plugins/sudoers/ldap.c:1521 plugins/sudoers/ldap.c:1597
+#: plugins/sudoers/ldap.c:1733 plugins/sudoers/ldap.c:1757
+#: plugins/sudoers/ldap.c:1787 plugins/sudoers/ldap.c:1840
+#: plugins/sudoers/ldap.c:1855 plugins/sudoers/ldap.c:1951
+#: plugins/sudoers/ldap.c:1984 plugins/sudoers/ldap.c:2137
+#: plugins/sudoers/ldap.c:2234 plugins/sudoers/ldap.c:3041
+#: plugins/sudoers/ldap.c:3074 plugins/sudoers/ldap.c:3388
+#: plugins/sudoers/ldap.c:3416 plugins/sudoers/ldap.c:3427
+#: plugins/sudoers/ldap.c:3517 plugins/sudoers/ldap.c:3533
+#: plugins/sudoers/linux_audit.c:76 plugins/sudoers/logging.c:188
+#: plugins/sudoers/logging.c:924 plugins/sudoers/match.c:501
+#: plugins/sudoers/match.c:537 plugins/sudoers/match.c:699
+#: plugins/sudoers/match.c:756 plugins/sudoers/parse.c:235
+#: plugins/sudoers/parse.c:247 plugins/sudoers/parse.c:262
+#: plugins/sudoers/parse.c:274 plugins/sudoers/policy.c:97
+#: plugins/sudoers/policy.c:106 plugins/sudoers/policy.c:115
+#: plugins/sudoers/policy.c:139 plugins/sudoers/policy.c:250
+#: plugins/sudoers/policy.c:271 plugins/sudoers/policy.c:280
+#: plugins/sudoers/policy.c:319 plugins/sudoers/policy.c:329
+#: plugins/sudoers/policy.c:338 plugins/sudoers/policy.c:384
+#: plugins/sudoers/policy.c:583 plugins/sudoers/prompt.c:93
+#: plugins/sudoers/set_perms.c:356 plugins/sudoers/set_perms.c:695
+#: plugins/sudoers/set_perms.c:1054 plugins/sudoers/set_perms.c:1350
+#: plugins/sudoers/set_perms.c:1514 plugins/sudoers/sssd.c:160
+#: plugins/sudoers/sssd.c:192 plugins/sudoers/sssd.c:235
+#: plugins/sudoers/sssd.c:242 plugins/sudoers/sssd.c:278
+#: plugins/sudoers/sssd.c:323 plugins/sudoers/sssd.c:917
+#: plugins/sudoers/sssd.c:1050 plugins/sudoers/sudoers.c:159
+#: plugins/sudoers/sudoers.c:294 plugins/sudoers/sudoers.c:304
+#: plugins/sudoers/sudoers.c:312 plugins/sudoers/sudoers.c:365
+#: plugins/sudoers/sudoers.c:663 plugins/sudoers/sudoers.c:749
+#: plugins/sudoers/sudoers.c:793 plugins/sudoers/sudoers_debug.c:106
+#: plugins/sudoers/sudoreplay.c:472 plugins/sudoers/sudoreplay.c:668
+#: plugins/sudoers/sudoreplay.c:780 plugins/sudoers/sudoreplay.c:820
+#: plugins/sudoers/sudoreplay.c:829 plugins/sudoers/sudoreplay.c:839
+#: plugins/sudoers/sudoreplay.c:847 plugins/sudoers/sudoreplay.c:851
+#: plugins/sudoers/sudoreplay.c:1007 plugins/sudoers/sudoreplay.c:1011
+#: plugins/sudoers/testsudoers.c:130 plugins/sudoers/testsudoers.c:188
+#: plugins/sudoers/testsudoers.c:215 plugins/sudoers/testsudoers.c:232
+#: plugins/sudoers/timestamp.c:390 plugins/sudoers/timestamp.c:426
+#: plugins/sudoers/timestamp.c:838 plugins/sudoers/toke_util.c:56
+#: plugins/sudoers/toke_util.c:109 plugins/sudoers/toke_util.c:147
+#: plugins/sudoers/visudo.c:152 plugins/sudoers/visudo.c:213
+#: plugins/sudoers/visudo.c:297 plugins/sudoers/visudo.c:303
+#: plugins/sudoers/visudo.c:433 plugins/sudoers/visudo.c:979
+#: plugins/sudoers/visudo.c:1023 plugins/sudoers/visudo.c:1119 toke.l:785
+#: toke.l:806 toke.l:816 toke.l:924 toke.l:1082
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: plugins/sudoers/alias.c:132
+#, c-format
+msgid "Alias `%s' already defined"
+msgstr "El alias `%s' ya fue definido"
+
+#: plugins/sudoers/auth/bsdauth.c:68
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "no se pudo obtener la clase de login del usuario %s"
+
+#: plugins/sudoers/auth/bsdauth.c:73
+msgid "unable to begin bsd authentication"
+msgstr "no se pudo iniciar autenticicación bsd"
+
+#: plugins/sudoers/auth/bsdauth.c:81
+msgid "invalid authentication type"
+msgstr "tipo de autenticicación inválido"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to initialize BSD authentication"
+msgstr "no se pudo inicializar la autenticicación BSD"
+
+#: plugins/sudoers/auth/fwtk.c:52
+msgid "unable to read fwtk config"
+msgstr "no se pudo leer la configuración fwtk"
+
+#: plugins/sudoers/auth/fwtk.c:57
+msgid "unable to connect to authentication server"
+msgstr "no se pudo conectar con el servidor de autenticicación"
+
+#: plugins/sudoers/auth/fwtk.c:63 plugins/sudoers/auth/fwtk.c:87
+#: plugins/sudoers/auth/fwtk.c:120
+msgid "lost connection to authentication server"
+msgstr "se perdió la conexión con el servidor de autenticicación"
+
+#: plugins/sudoers/auth/fwtk.c:67
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"error del servidor de autenticicación:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:111
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: no se pudo convertir el principal a string ('%s'): %s"
+
+#: plugins/sudoers/auth/kerb5.c:161
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: no se pudo analizar '%s': %s"
+
+#: plugins/sudoers/auth/kerb5.c:170
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: no se pudo resolver la caché de credenciales: %s"
+
+#: plugins/sudoers/auth/kerb5.c:217
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: no se pudo asignar opciones: %s"
+
+#: plugins/sudoers/auth/kerb5.c:232
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: no se pudo obtener las credenciales: %s"
+
+#: plugins/sudoers/auth/kerb5.c:245
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: no se pudo obtener la caché de credenciales: %s"
+
+#: plugins/sudoers/auth/kerb5.c:248
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: no se pudo guardar la credencial en la cache: %s"
+
+#: plugins/sudoers/auth/kerb5.c:312
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: no se pudo obtener la principal del host: %s"
+
+#: plugins/sudoers/auth/kerb5.c:326
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: ¡No se pudo verificar TGT! ¡Posible ataque!: %s"
+
+#: plugins/sudoers/auth/pam.c:92
+msgid "unable to initialize PAM"
+msgstr "no se pudo inicializar PAM"
+
+#: plugins/sudoers/auth/pam.c:164
+msgid "account validation failure, is your account locked?"
+msgstr "fallo de validación de la cuenta, ¿está su cuenta bloqueada?"
+
+#: plugins/sudoers/auth/pam.c:168
+msgid "Account or password is expired, reset your password and try again"
+msgstr "La cuenta o la contraseña ha caducado, reinicie su contraseña y pruebe de nuevo"
+
+#: plugins/sudoers/auth/pam.c:176
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "no se pudo cambiar la contraseña caducada: %s"
+
+#: plugins/sudoers/auth/pam.c:181
+msgid "Password expired, contact your system administrator"
+msgstr "La contraseña caducó, contacte con el administrador de su sistema"
+
+#: plugins/sudoers/auth/pam.c:185
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "La cuenta caducó o la configuración de PAM no tiene una sección \"account\" para sudo, contacte con el administrador de su sistema"
+
+#: plugins/sudoers/auth/pam.c:199
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Error de autenticicación PAM: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:97 plugins/sudoers/visudo.c:218
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "usted no existe el la base de datos %s"
+
+#: plugins/sudoers/auth/securid5.c:73
+msgid "failed to initialise the ACE API library"
+msgstr "no se pudo inicializar la API de la librería ACE"
+
+#: plugins/sudoers/auth/securid5.c:99
+msgid "unable to contact the SecurID server"
+msgstr "no se pudo contactar con el servidor SecurID"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "User ID locked for SecurID Authentication"
+msgstr "ID del usuario bloqueada para autenticicación SecurID"
+
+#: plugins/sudoers/auth/securid5.c:112 plugins/sudoers/auth/securid5.c:163
+msgid "invalid username length for SecurID"
+msgstr "longitud del nombre de usuario inválida para SecurID"
+
+#: plugins/sudoers/auth/securid5.c:116 plugins/sudoers/auth/securid5.c:168
+msgid "invalid Authentication Handle for SecurID"
+msgstr "Manejador de autenticicación inválido para SecurID"
+
+#: plugins/sudoers/auth/securid5.c:120
+msgid "SecurID communication failed"
+msgstr "falló la comunicación con SecurID"
+
+#: plugins/sudoers/auth/securid5.c:124 plugins/sudoers/auth/securid5.c:207
+msgid "unknown SecurID error"
+msgstr "error SecurID desconocido"
+
+#: plugins/sudoers/auth/securid5.c:158
+msgid "invalid passcode length for SecurID"
+msgstr "longitud de código de paso inválido para Securid"
+
+#: plugins/sudoers/auth/sia.c:69 plugins/sudoers/auth/sia.c:124
+msgid "unable to initialize SIA session"
+msgstr "no se pudo inicializar la sesión SIA"
+
+#: plugins/sudoers/auth/sudo_auth.c:126
+msgid "invalid authentication methods"
+msgstr "métodos de autenticicación inválidos"
+
+#: plugins/sudoers/auth/sudo_auth.c:128
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "¡El sudo ha sido compilado con métodos de autenticicación inválidos! No puede mezclar autenticicación independiente y no independiente."
+
+#: plugins/sudoers/auth/sudo_auth.c:225 plugins/sudoers/auth/sudo_auth.c:274
+msgid "no authentication methods"
+msgstr "sin métodos de autenticicación"
+
+#: plugins/sudoers/auth/sudo_auth.c:227
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "¡El sudo ha sido compilado sin métodos de autenticicación! Si desea desactivar la autenticicación, use la opción de configuración --disable-authentication."
+
+#: plugins/sudoers/auth/sudo_auth.c:276
+msgid "Unable to initialize authentication methods."
+msgstr "no se pudo inicializar los métodos de autenticicación."
+
+#: plugins/sudoers/auth/sudo_auth.c:435
+msgid "Authentication methods:"
+msgstr "Métodos de autenticicación:"
+
+#: plugins/sudoers/bsm_audit.c:111 plugins/sudoers/bsm_audit.c:200
+msgid "Could not determine audit condition"
+msgstr "No se pudo determinar la condición de la auditoría"
+
+#: plugins/sudoers/bsm_audit.c:172 plugins/sudoers/bsm_audit.c:260
+msgid "unable to commit audit record"
+msgstr ""
+
+#: plugins/sudoers/check.c:252
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Confiamos que haya recibido la charla habitual del administrador\n"
+"de sistema local. Por lo general se reduce a estas tres cosas:\n"
+"\n"
+" #1) Respeta la privacidad de otros.\n"
+" #2) Piensa antes de escribir.\n"
+" #3) Un gran poder conlleva una gran responsabilidad.\n"
+"\n"
+
+#: plugins/sudoers/check.c:295 plugins/sudoers/check.c:305
+#: plugins/sudoers/sudoers.c:699 plugins/sudoers/sudoers.c:728
+#, c-format
+msgid "unknown uid: %u"
+msgstr "uid desconocido: %u"
+
+#: plugins/sudoers/check.c:300 plugins/sudoers/policy.c:755
+#: plugins/sudoers/sudoers.c:1095 plugins/sudoers/testsudoers.c:206
+#: plugins/sudoers/testsudoers.c:361
+#, c-format
+msgid "unknown user: %s"
+msgstr "usuario desconocido: %s"
+
+#: plugins/sudoers/def_data.c:27
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Facilidad de syslog, cuando se usa syslog para el registro: %s"
+
+#: plugins/sudoers/def_data.c:31
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Prioridad de syslog a usarse cuando el usuario se autentifica con éxito: %s"
+
+#: plugins/sudoers/def_data.c:35
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Prioridad de syslog a usarse cuando el usuario no se autentifica con éxito: %s"
+
+#: plugins/sudoers/def_data.c:39
+msgid "Put OTP prompt on its own line"
+msgstr "Pone la petición de OTP en su propia línea"
+
+#: plugins/sudoers/def_data.c:43
+msgid "Ignore '.' in $PATH"
+msgstr "No hace caso del '.' en el $PATH"
+
+#: plugins/sudoers/def_data.c:47
+msgid "Always send mail when sudo is run"
+msgstr "Siempre envía el correo cuando se ejecuta sudo"
+
+#: plugins/sudoers/def_data.c:51
+msgid "Send mail if user authentication fails"
+msgstr "Envía correo si la autenticicación de usuario falla"
+
+#: plugins/sudoers/def_data.c:55
+msgid "Send mail if the user is not in sudoers"
+msgstr "Envía correo si el usuario no está en sudoers"
+
+#: plugins/sudoers/def_data.c:59
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Envía correo si el usuario no está en el sudoers de este equipo"
+
+#: plugins/sudoers/def_data.c:63
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Envía correo si no se permite al usuario ejecutar un comando"
+
+#: plugins/sudoers/def_data.c:67
+msgid "Send mail if the user tries to run a command"
+msgstr "Envía correo si el usuario trata de ejecutar un comando"
+
+#: plugins/sudoers/def_data.c:71
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Usa una marca de tiempo separada para cada combinación usuario/tty"
+
+#: plugins/sudoers/def_data.c:75
+msgid "Lecture user the first time they run sudo"
+msgstr "Da la charla al usuario la primera vez que use sudo"
+
+#: plugins/sudoers/def_data.c:79
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Fichero que contiene la charla sobre sudo: %s"
+
+#: plugins/sudoers/def_data.c:83
+msgid "Require users to authenticate by default"
+msgstr "Requiere a los usuarios que por defecto se autentifiquen"
+
+#: plugins/sudoers/def_data.c:87
+msgid "Root may run sudo"
+msgstr "Root puede usar sudo"
+
+#: plugins/sudoers/def_data.c:91
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Registra el equipo en el fichero de registro (no de syslog)"
+
+#: plugins/sudoers/def_data.c:95
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Registra el año en el fichero de registro (no de syslog)"
+
+#: plugins/sudoers/def_data.c:99
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Si se llama a sudo sin argumentos, iniciará una terminal de órdenes"
+
+#: plugins/sudoers/def_data.c:103
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Establece $HOME al usuario objetivo cuando se empieza una terminal de órdenes con -s"
+
+#: plugins/sudoers/def_data.c:107
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Establece siempre $HOME al directorio home del usuario objetivo"
+
+#: plugins/sudoers/def_data.c:111
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Permite alguna recolección de datos para dar mensajes de error útiles"
+
+#: plugins/sudoers/def_data.c:115
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Requerir nombres de equipo plenamente-cualificados en el fichero sudoers"
+
+#: plugins/sudoers/def_data.c:119
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Se insultará al usuario cuando introduzcan una contraseña incorrecta"
+
+#: plugins/sudoers/def_data.c:123
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Unicamente se permitirá al usuario ejecutar sudo si tienen una tty"
+
+#: plugins/sudoers/def_data.c:127
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo obedecerá a la variable de entorno EDITOR"
+
+#: plugins/sudoers/def_data.c:131
+msgid "Prompt for root's password, not the users's"
+msgstr "Pide la contraseña del root, no del usuario"
+
+#: plugins/sudoers/def_data.c:135
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Pide la contraseña del usuario por omisión 'runas', no del usuario"
+
+#: plugins/sudoers/def_data.c:139
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Pide la contraseña del usuario objetivo, no del usuario"
+
+#: plugins/sudoers/def_data.c:143
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Aplica valores por omisión en la clase del usuario objetivo si es que hay uno"
+
+#: plugins/sudoers/def_data.c:147
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Establece las variables de entorno LOGNAME y USER"
+
+#: plugins/sudoers/def_data.c:151
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Establece unicamente el uid efectivo unicamente al del usuario objetivo, no el uid real"
+
+#: plugins/sudoers/def_data.c:155
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "No inicializa el vector de grupo al del usuario objetivo"
+
+#: plugins/sudoers/def_data.c:159
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Longitud a la cual enrollar las lineas del registro (0 para no enrollar): %u"
+
+#: plugins/sudoers/def_data.c:163
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Temporizador de la marca de tiempo de la autenticicación: %.1f minutos"
+
+#: plugins/sudoers/def_data.c:167
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Temporizador de la solicitud de contraseña: %.1f minutos"
+
+#: plugins/sudoers/def_data.c:171
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Número de intentos para introducir una contraseña: %u"
+
+#: plugins/sudoers/def_data.c:175
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Umask que debe usarse o 0777 para usar la del usuario: 0%o"
+
+#: plugins/sudoers/def_data.c:179
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Camino al fichero de registro: %s"
+
+#: plugins/sudoers/def_data.c:183
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Camino al programa de correo: %s"
+
+#: plugins/sudoers/def_data.c:187
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Banderas para el programa de correo: %s"
+
+#: plugins/sudoers/def_data.c:191
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Dirección a la que enviar el correo: %s"
+
+#: plugins/sudoers/def_data.c:195
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Dirección desde la que enviar el correo: %s"
+
+#: plugins/sudoers/def_data.c:199
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Linea de tema a usar en los mensajes de correo: %s"
+
+#: plugins/sudoers/def_data.c:203
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Mensaje de contraseña incorrecta: %s"
+
+#: plugins/sudoers/def_data.c:207
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Camino al directorio de estado de las charlas: %s"
+
+#: plugins/sudoers/def_data.c:211
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Camino al directorio de marcas de tiempo de las autenticaciones: %s"
+
+#: plugins/sudoers/def_data.c:215
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Propietario del directorio de marcas de tiempo de las autenticaciones: %s"
+
+#: plugins/sudoers/def_data.c:219
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Los usuarios en este grupo están exentos de los requisitos de contraseña y PATH (camino): %s"
+
+#: plugins/sudoers/def_data.c:223
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Solicitud por omisión de contraseña: %s"
+
+#: plugins/sudoers/def_data.c:227
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Si se define, passprompt substituirá al indicador del sistema en todos los casos."
+
+#: plugins/sudoers/def_data.c:231
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Usuario por omisión que se utilizará para ejecutar los comandos: %s"
+
+#: plugins/sudoers/def_data.c:235
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Valor que substituirá al del usuario en el $PATH: %s"
+
+#: plugins/sudoers/def_data.c:239
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Camino al editor que se usará por visudo: %s"
+
+#: plugins/sudoers/def_data.c:243
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:247
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:251
+msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:255
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:259
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:263
+msgid "If set, users may override the value of `closefrom' with the -C option"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:267
+msgid "Allow users to set arbitrary environment variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:271
+msgid "Reset the environment to a default set of variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:275
+msgid "Environment variables to check for sanity:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:279
+msgid "Environment variables to remove:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:283
+msgid "Environment variables to preserve:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:287
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:291
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:295
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:299
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:303
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:307
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:311
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:315
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:319
+msgid "Log user's input for the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:323
+msgid "Log the output of the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:327
+msgid "Compress I/O logs using zlib"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:331
+msgid "Always run commands in a pseudo-tty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:335
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:339
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:343
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:347
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:351
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:355
+msgid "Set of permitted privileges"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:359
+msgid "Set of limit privileges"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:363
+msgid "Run commands on a pty in the background"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:367
+msgid "PAM service name to use"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:371
+msgid "PAM service name to use for login shells"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:375
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:379
+msgid "Create a new PAM session for the command to run in"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:383
+#, c-format
+msgid "Maximum I/O log sequence number: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:387
+msgid "Enable sudoers netgroup support"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:391
+msgid "Check the parent directory for writability when editing files with sudoedit"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:395
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:399
+msgid "Query the group plugin for unknown system groups"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:199 plugins/sudoers/defaults.c:608
+#: plugins/sudoers/visudo_json.c:633 plugins/sudoers/visudo_json.c:668
+#, c-format
+msgid "unknown defaults entry `%s'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:207 plugins/sudoers/defaults.c:217
+#: plugins/sudoers/defaults.c:241 plugins/sudoers/defaults.c:256
+#: plugins/sudoers/defaults.c:269 plugins/sudoers/defaults.c:282
+#: plugins/sudoers/defaults.c:295 plugins/sudoers/defaults.c:315
+#: plugins/sudoers/defaults.c:325
+#, c-format
+msgid "value `%s' is invalid for option `%s'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:210 plugins/sudoers/defaults.c:220
+#: plugins/sudoers/defaults.c:228 plugins/sudoers/defaults.c:251
+#: plugins/sudoers/defaults.c:264 plugins/sudoers/defaults.c:277
+#: plugins/sudoers/defaults.c:290 plugins/sudoers/defaults.c:310
+#: plugins/sudoers/defaults.c:321
+#, c-format
+msgid "no value specified for `%s'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:233
+#, c-format
+msgid "values for `%s' must start with a '/'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:301
+#, c-format
+msgid "option `%s' does not take a value"
+msgstr ""
+
+#: plugins/sudoers/env.c:295 plugins/sudoers/env.c:302
+#: plugins/sudoers/env.c:407 plugins/sudoers/ldap.c:450
+#: plugins/sudoers/ldap.c:540 plugins/sudoers/ldap.c:1152
+#: plugins/sudoers/ldap.c:1354 plugins/sudoers/ldap.c:1526
+#: plugins/sudoers/ldap.c:1682 plugins/sudoers/linux_audit.c:82
+#: plugins/sudoers/logging.c:929 plugins/sudoers/policy.c:502
+#: plugins/sudoers/policy.c:511 plugins/sudoers/prompt.c:161
+#: plugins/sudoers/sudoers.c:815 plugins/sudoers/testsudoers.c:236
+#: plugins/sudoers/toke_util.c:160
+#, c-format
+msgid "internal error, %s overflow"
+msgstr ""
+
+#: plugins/sudoers/env.c:376
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr ""
+
+#: plugins/sudoers/env.c:1076
+msgid "unable to rebuild the environment"
+msgstr ""
+
+#: plugins/sudoers/env.c:1150
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:85
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s debe ser propiedad del uid %d"
+
+#: plugins/sudoers/group_plugin.c:89
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:97 plugins/sudoers/sssd.c:331
+#, c-format
+msgid "unable to load %s: %s"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:103
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:108
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:117
+msgid "Local IP address and netmask pairs:\n"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:92 plugins/sudoers/iolog.c:110
+#: plugins/sudoers/timestamp.c:169
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:103 plugins/sudoers/iolog.c:124
+#: plugins/sudoers/iolog.c:131 plugins/sudoers/timestamp.c:163
+#: plugins/sudoers/timestamp.c:184
+#, c-format
+msgid "unable to mkdir %s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:200 plugins/sudoers/sudoers.c:871
+#: plugins/sudoers/sudoreplay.c:300 plugins/sudoers/sudoreplay.c:769
+#: plugins/sudoers/sudoreplay.c:973 plugins/sudoers/timestamp.c:399
+#: plugins/sudoers/visudo.c:903 plugins/sudoers/visudo_json.c:1012
+#: plugins/sudoers/visudo_json.c:1025
+#, c-format
+msgid "unable to open %s"
+msgstr "no se pudo abrir %s"
+
+#: plugins/sudoers/iolog.c:241 plugins/sudoers/sudoers.c:875
+#: plugins/sudoers/sudoreplay.c:1084
+#, c-format
+msgid "unable to read %s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:277 plugins/sudoers/sudoreplay.c:550
+#: plugins/sudoers/timestamp.c:298 plugins/sudoers/timestamp.c:301
+#, c-format
+msgid "unable to write to %s"
+msgstr "no se puede escribir en %s"
+
+#: plugins/sudoers/iolog.c:342 plugins/sudoers/iolog.c:540
+#, c-format
+msgid "unable to create %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:428
+msgid "sudo_ldap_conf_add_ports: port too large"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:488
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:515
+msgid "unable to mix ldap and ldaps URIs"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:519 plugins/sudoers/ldap.c:555
+msgid "starttls not supported when using ldaps"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:626
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:629
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1138
+msgid "unable to get GMT time"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1144
+msgid "unable to format timestamp"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1830
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2372
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2374
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: UNKNOWN\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2421
+#, c-format
+msgid " Order: %s\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2429 plugins/sudoers/parse.c:555
+#: plugins/sudoers/sssd.c:1417
+#, c-format
+msgid " Commands:\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2993
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:3029
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:3286
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr ""
+
+#: plugins/sudoers/linux_audit.c:52
+msgid "unable to open audit system"
+msgstr "no se puede de abrir el sistema de auditoría"
+
+#: plugins/sudoers/linux_audit.c:93
+msgid "unable to send audit message"
+msgstr "no se puede enviar mensaje de auditoría"
+
+#: plugins/sudoers/logging.c:106
+#, c-format
+msgid "%8s : %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:134
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:159
+#, c-format
+msgid "unable to open log file: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:162
+#, c-format
+msgid "unable to lock log file: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:211
+msgid "No user or host"
+msgstr ""
+
+#: plugins/sudoers/logging.c:213
+msgid "validation failure"
+msgstr ""
+
+#: plugins/sudoers/logging.c:220
+msgid "user NOT in sudoers"
+msgstr ""
+
+#: plugins/sudoers/logging.c:222
+msgid "user NOT authorized on host"
+msgstr ""
+
+#: plugins/sudoers/logging.c:224
+msgid "command not allowed"
+msgstr ""
+
+#: plugins/sudoers/logging.c:259
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:262
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:266
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:269
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:306 plugins/sudoers/sudoers.c:471
+#: plugins/sudoers/sudoers.c:473 plugins/sudoers/sudoers.c:475
+#: plugins/sudoers/sudoers.c:477 plugins/sudoers/sudoers.c:1222
+#: plugins/sudoers/sudoers.c:1224
+#, c-format
+msgid "%s: command not found"
+msgstr ""
+
+#: plugins/sudoers/logging.c:308 plugins/sudoers/sudoers.c:467
+#, c-format
+msgid ""
+"ignoring `%s' found in '.'\n"
+"Use `sudo ./%s' if this is the `%s' you wish to run."
+msgstr ""
+
+#: plugins/sudoers/logging.c:325
+msgid "authentication failure"
+msgstr ""
+
+#: plugins/sudoers/logging.c:351
+msgid "a password is required"
+msgstr ""
+
+#: plugins/sudoers/logging.c:422 plugins/sudoers/logging.c:484
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] ""
+msgstr[1] ""
+
+#: plugins/sudoers/logging.c:572
+msgid "unable to fork"
+msgstr "no se puede bifurcar"
+
+#: plugins/sudoers/logging.c:580 plugins/sudoers/logging.c:640
+#, c-format
+msgid "unable to fork: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:630
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:655
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:693
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr ""
+
+#: plugins/sudoers/match.c:606
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr "Tipo de compendio %d no soportado para %s"
+
+#: plugins/sudoers/match.c:639
+#, c-format
+msgid "%s: read error"
+msgstr ""
+
+#: plugins/sudoers/match.c:653
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "compendio para %s (%s) no está en la forma %s"
+
+#: plugins/sudoers/parse.c:114
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr ""
+
+#: plugins/sudoers/parse.c:117
+#, c-format
+msgid "parse error in %s"
+msgstr ""
+
+#: plugins/sudoers/parse.c:502
+#, c-format
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+
+#: plugins/sudoers/parse.c:503
+#, c-format
+msgid " RunAsUsers: "
+msgstr ""
+
+#: plugins/sudoers/parse.c:517
+#, c-format
+msgid " RunAsGroups: "
+msgstr ""
+
+#: plugins/sudoers/parse.c:526
+#, c-format
+msgid " Options: "
+msgstr ""
+
+#: plugins/sudoers/policy.c:240 plugins/sudoers/testsudoers.c:253
+msgid "unable to parse network address list"
+msgstr ""
+
+#: plugins/sudoers/policy.c:640 plugins/sudoers/visudo.c:840
+#, c-format
+msgid "unable to execute %s"
+msgstr "no se puede ejecutar %s"
+
+#: plugins/sudoers/policy.c:773
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:775
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:779
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:782
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:784
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:785
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:818
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:136 plugins/sudoers/pwutil.c:153
+#, c-format
+msgid "unable to cache uid %u, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:147
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:191 plugins/sudoers/pwutil.c:207
+#: plugins/sudoers/pwutil.c:250 plugins/sudoers/pwutil.c:294
+#, c-format
+msgid "unable to cache user %s, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:202
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:427 plugins/sudoers/pwutil.c:444
+#, c-format
+msgid "unable to cache gid %u, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:438
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:476 plugins/sudoers/pwutil.c:492
+#: plugins/sudoers/pwutil.c:524 plugins/sudoers/pwutil.c:565
+#, c-format
+msgid "unable to cache group %s, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:487
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:676 plugins/sudoers/pwutil.c:710
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:682 plugins/sudoers/pwutil.c:715
+#, c-format
+msgid "unable to cache group list for %s, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:705
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:113 plugins/sudoers/set_perms.c:438
+#: plugins/sudoers/set_perms.c:841 plugins/sudoers/set_perms.c:1138
+#: plugins/sudoers/set_perms.c:1430
+msgid "perm stack overflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:121 plugins/sudoers/set_perms.c:369
+#: plugins/sudoers/set_perms.c:446 plugins/sudoers/set_perms.c:708
+#: plugins/sudoers/set_perms.c:849 plugins/sudoers/set_perms.c:1067
+#: plugins/sudoers/set_perms.c:1146 plugins/sudoers/set_perms.c:1363
+#: plugins/sudoers/set_perms.c:1438 plugins/sudoers/set_perms.c:1527
+msgid "perm stack underflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:180 plugins/sudoers/set_perms.c:493
+#: plugins/sudoers/set_perms.c:1197 plugins/sudoers/set_perms.c:1470
+msgid "unable to change to root gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:269 plugins/sudoers/set_perms.c:590
+#: plugins/sudoers/set_perms.c:978 plugins/sudoers/set_perms.c:1274
+msgid "unable to change to runas gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:274 plugins/sudoers/set_perms.c:595
+#: plugins/sudoers/set_perms.c:983 plugins/sudoers/set_perms.c:1279
+msgid "unable to set runas group vector"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:285 plugins/sudoers/set_perms.c:606
+#: plugins/sudoers/set_perms.c:992 plugins/sudoers/set_perms.c:1288
+msgid "unable to change to runas uid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:303 plugins/sudoers/set_perms.c:624
+#: plugins/sudoers/set_perms.c:1008 plugins/sudoers/set_perms.c:1304
+msgid "unable to change to sudoers gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:356 plugins/sudoers/set_perms.c:695
+#: plugins/sudoers/set_perms.c:1054 plugins/sudoers/set_perms.c:1350
+#: plugins/sudoers/set_perms.c:1514
+msgid "too many processes"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:51
+msgid "unable to get current working directory"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:59
+#, c-format
+msgid "truncated audit path user_cmnd: %s"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:66
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:115
+msgid "audit_failure message too long"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:333
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:341 plugins/sudoers/sssd.c:350
+#: plugins/sudoers/sssd.c:359 plugins/sudoers/sssd.c:368
+#: plugins/sudoers/sssd.c:377
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:290
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:308
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:326
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:339
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:172 plugins/sudoers/testsudoers.c:245
+#: plugins/sudoers/visudo.c:223 plugins/sudoers/visudo.c:566
+msgid "unable to initialize sudoers default values"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:197 plugins/sudoers/sudoers.c:239
+#: plugins/sudoers/sudoers.c:833
+msgid "problem with defaults entries"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:205
+msgid "no valid sudoers sources found, quitting"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:275
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:332
+msgid "you are not permitted to use the -C option"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:396
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:410
+msgid "no tty"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:411
+msgid "sorry, you must have a tty to run sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:466
+msgid "command in current directory"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:486
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:778
+msgid "command too long"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:886 plugins/sudoers/visudo.c:426
+#: plugins/sudoers/visudo.c:666
+#, c-format
+msgid "unable to stat %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:890
+#, c-format
+msgid "%s is not a regular file"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:894 plugins/sudoers/timestamp.c:225 toke.l:947
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:898 toke.l:954
+#, c-format
+msgid "%s is world writable"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:902 toke.l:959
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:933
+#, c-format
+msgid "only root can use `-c %s'"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:952
+#, c-format
+msgid "unknown login class: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1031 plugins/sudoers/sudoers.c:1059
+#, c-format
+msgid "unable to resolve host %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1126 plugins/sudoers/testsudoers.c:385
+#, c-format
+msgid "unknown group: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:232
+#, c-format
+msgid "invalid filter option: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:245
+#, c-format
+msgid "invalid max wait: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:251
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:254 plugins/sudoers/visudo.c:180
+#, c-format
+msgid "%s version %s\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:286
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s/timing: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:292
+#, c-format
+msgid "%s/%s/timing: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:308
+#, c-format
+msgid "Replaying sudo session: %s\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:314
+#, c-format
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:315
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:368
+msgid "unable to set tty to raw mode"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:401
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:611 plugins/sudoers/sudoreplay.c:636
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:658
+msgid "unmatched ')' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:662
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:677
+#, c-format
+msgid "%s requires an argument"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:680 plugins/sudoers/sudoreplay.c:1060
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:684
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:693
+msgid "unmatched '(' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:695
+msgid "illegal trailing \"or\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:697
+msgid "illegal trailing \"!\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:746
+#, c-format
+msgid "unknown search type %d"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:784
+#, c-format
+msgid "%s: invalid log file"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:802
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:809
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:816
+#, c-format
+msgid "%s: user field is missing"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:825
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:834
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1197
+#, c-format
+msgid "usage: %s [-h] [-d dir] [-m num] [-s num] ID\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1200
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1209
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1211
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:324
+msgid "\thost unmatched"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:327
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:328
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:328
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:233
+#, c-format
+msgid "%s is group writable"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:309
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:742 plugins/sudoers/timestamp.c:809
+#: plugins/sudoers/visudo.c:487 plugins/sudoers/visudo.c:493
+msgid "unable to read the clock"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:756
+msgid "ignoring time stamp from the future"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:768
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:863
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:906 plugins/sudoers/timestamp.c:926
+#, c-format
+msgid "lecture status path too long: %s/%s"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:182
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:254 plugins/sudoers/visudo.c:618
+#, c-format
+msgid "press return to edit %s: "
+msgstr ""
+
+#: plugins/sudoers/visudo.c:319
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:337
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:446 plugins/sudoers/visudo.c:454
+msgid "write error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:500
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:507
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:513
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:535
+#, c-format
+msgid "%s unchanged"
+msgstr "%s sin cambios"
+
+#: plugins/sudoers/visudo.c:561
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr ""
+
+#: plugins/sudoers/visudo.c:572
+#, c-format
+msgid "unabled to parse temporary file (%s), unknown error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:609
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:668 plugins/sudoers/visudo.c:677
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:672 plugins/sudoers/visudo.c:682
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:699
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:713
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:723
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:785
+msgid "What now? "
+msgstr ""
+
+#: plugins/sudoers/visudo.c:799
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:847
+#, c-format
+msgid "unable to run %s"
+msgstr "no se puede ejecutar %s"
+
+#: plugins/sudoers/visudo.c:877
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:884
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:909 plugins/sudoers/visudo_json.c:1032
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:925 plugins/sudoers/visudo_json.c:1041
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:928 plugins/sudoers/visudo_json.c:1044
+#, c-format
+msgid "parse error in %s\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:936 plugins/sudoers/visudo.c:943
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:990
+#, c-format
+msgid "%s busy, try again later"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1086
+#, c-format
+msgid "Error: cycle in %s `%s'"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1087
+#, c-format
+msgid "Warning: cycle in %s `%s'"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1091
+#, c-format
+msgid "Error: %s `%s' referenced but not defined"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1092
+#, c-format
+msgid "Warning: %s `%s' referenced but not defined"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1235
+#, c-format
+msgid "Warning: unused %s `%s'"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1348
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1350
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+" -x, --export=output_file write sudoers in JSON format to output_file"
+msgstr ""
+
+#: plugins/sudoers/visudo_json.c:1018
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr ""
+
+#: toke.l:918
+msgid "too many levels of includes"
+msgstr ""
diff --git a/plugins/sudoers/po/eu.mo b/plugins/sudoers/po/eu.mo
new file mode 100644
index 0000000..5220f12
--- /dev/null
+++ b/plugins/sudoers/po/eu.mo
Binary files differ
diff --git a/plugins/sudoers/po/eu.po b/plugins/sudoers/po/eu.po
new file mode 100644
index 0000000..6fa330e
--- /dev/null
+++ b/plugins/sudoers/po/eu.po
@@ -0,0 +1,1679 @@
+# Basque translation of sudoers.
+# Copyright (C) 2011 Free Software Foundation, Inc.
+# This file is distributed under the same license as the sudo package.
+# Mikel Olasagasti Uranga <mikel@olasagasti.info>, 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers-1.8.2-rc2\n"
+"Report-Msgid-Bugs-To: http://www.sudo.ws/bugs\n"
+"POT-Creation-Date: 2011-06-04 18:27-0400\n"
+"PO-Revision-Date: 2011-06-06 19:15+0100\n"
+"Last-Translator: Mikel Olasagasti Uranga <mikel@olasagasti.info>\n"
+"Language-Team: Basque <translation-team-eu@lists.sourceforge.net>\n"
+"Language: \n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: plugins/sudoers/alias.c:122
+#, c-format
+msgid "Alias `%s' already defined"
+msgstr "`%s' alias-a lehendik ere definitua dago"
+
+#: plugins/sudoers/bsm_audit.c:58 plugins/sudoers/bsm_audit.c:61
+#: plugins/sudoers/bsm_audit.c:109 plugins/sudoers/bsm_audit.c:113
+#: plugins/sudoers/bsm_audit.c:163 plugins/sudoers/bsm_audit.c:167
+msgid "getaudit: failed"
+msgstr "getaudit: huts egin du"
+
+#: plugins/sudoers/bsm_audit.c:87 plugins/sudoers/bsm_audit.c:148
+msgid "Could not determine audit condition"
+msgstr "Ezin izan da auditoretza baldintza finkatu"
+
+#: plugins/sudoers/bsm_audit.c:98
+msgid "getauid failed"
+msgstr "getauid-ek huts egin du"
+
+#: plugins/sudoers/bsm_audit.c:100 plugins/sudoers/bsm_audit.c:157
+msgid "au_open: failed"
+msgstr "au_open: huts egin du"
+
+#: plugins/sudoers/bsm_audit.c:115 plugins/sudoers/bsm_audit.c:169
+msgid "au_to_subject: failed"
+msgstr "au_to_subject: huts egin du"
+
+#: plugins/sudoers/bsm_audit.c:119 plugins/sudoers/bsm_audit.c:173
+msgid "au_to_exec_args: failed"
+msgstr "au_to_exec_args: huts egin du"
+
+#: plugins/sudoers/bsm_audit.c:123 plugins/sudoers/bsm_audit.c:182
+msgid "au_to_return32: failed"
+msgstr "au_to_return32: huts egin du"
+
+#: plugins/sudoers/bsm_audit.c:126 plugins/sudoers/bsm_audit.c:185
+msgid "unable to commit audit record"
+msgstr "ezin da auditoretza sarrera gorde"
+
+#: plugins/sudoers/bsm_audit.c:155
+msgid "getauid: failed"
+msgstr "getauid: huts egin du"
+
+#: plugins/sudoers/bsm_audit.c:178
+msgid "au_to_text: failed"
+msgstr "au_to_text: huts egin du"
+
+#: plugins/sudoers/check.c:141
+#, c-format
+msgid "sorry, a password is required to run %s"
+msgstr "barkatu, pasahitz bat behar da %s abiarazteko"
+
+#: plugins/sudoers/check.c:225 plugins/sudoers/iolog.c:169
+#: plugins/sudoers/sudoers.c:939 plugins/sudoers/sudoreplay.c:325
+#: plugins/sudoers/sudoreplay.c:334 plugins/sudoers/sudoreplay.c:675
+#: plugins/sudoers/sudoreplay.c:767 plugins/sudoers/visudo.c:700
+#, c-format
+msgid "unable to open %s"
+msgstr "ezin da %s ireki"
+
+#: plugins/sudoers/check.c:229 plugins/sudoers/iolog.c:199
+#, c-format
+msgid "unable to write to %s"
+msgstr "ezin da %s-(e)ra idatzi"
+
+#: plugins/sudoers/check.c:237 plugins/sudoers/check.c:475
+#: plugins/sudoers/check.c:525 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/iolog.c:153
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "ezin da mkdir %s egin"
+
+#: plugins/sudoers/check.c:370
+#, c-format
+msgid "internal error, expand_prompt() overflow"
+msgstr "barne errorea, expand_prompt() overflow"
+
+#: plugins/sudoers/check.c:426
+#, c-format
+msgid "timestamp path too long: %s"
+msgstr ""
+
+#: plugins/sudoers/check.c:454 plugins/sudoers/check.c:498
+#: plugins/sudoers/iolog.c:155
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s existitzen da baina ez da direktorio bat (0%o)"
+
+#: plugins/sudoers/check.c:457 plugins/sudoers/check.c:501
+#: plugins/sudoers/check.c:546
+#, c-format
+msgid "%s owned by uid %u, should be uid %u"
+msgstr "%s-(r)en jabea %u uid-a da, %u uid-a beharko luke"
+
+#: plugins/sudoers/check.c:462 plugins/sudoers/check.c:506
+#, c-format
+msgid "%s writable by non-owner (0%o), should be mode 0700"
+msgstr ""
+
+#: plugins/sudoers/check.c:470 plugins/sudoers/check.c:514
+#: plugins/sudoers/check.c:582 plugins/sudoers/sudoers.c:925
+#: plugins/sudoers/visudo.c:284 plugins/sudoers/visudo.c:500
+#, c-format
+msgid "unable to stat %s"
+msgstr "ezin da stat egin %s-(r)engan"
+
+#: plugins/sudoers/check.c:540
+#, c-format
+msgid "%s exists but is not a regular file (0%o)"
+msgstr ""
+
+#: plugins/sudoers/check.c:552
+#, c-format
+msgid "%s writable by non-owner (0%o), should be mode 0600"
+msgstr ""
+
+#: plugins/sudoers/check.c:606
+#, c-format
+msgid "timestamp too far in the future: %20.20s"
+msgstr ""
+
+#: plugins/sudoers/check.c:652
+#, c-format
+msgid "unable to remove %s (%s), will reset to the epoch"
+msgstr ""
+
+#: plugins/sudoers/check.c:659
+#, c-format
+msgid "unable to reset %s to the epoch"
+msgstr ""
+
+#: plugins/sudoers/check.c:713 plugins/sudoers/check.c:719
+#, c-format
+msgid "unknown uid: %u"
+msgstr "uid ezezaguna: %u"
+
+#: plugins/sudoers/check.c:716 plugins/sudoers/sudoers.c:736
+#: plugins/sudoers/sudoers.c:802 plugins/sudoers/sudoers.c:803
+#: plugins/sudoers/sudoers.c:1056 plugins/sudoers/sudoers.c:1057
+#: plugins/sudoers/testsudoers.c:200 plugins/sudoers/testsudoers.c:330
+#, c-format
+msgid "unknown user: %s"
+msgstr "erabiltzaile ezezaguna: %s"
+
+#: plugins/sudoers/def_data.c:27
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:31
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:35
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:39
+msgid "Put OTP prompt on its own line"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:43
+msgid "Ignore '.' in $PATH"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:47
+msgid "Always send mail when sudo is run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:51
+msgid "Send mail if user authentication fails"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:55
+msgid "Send mail if the user is not in sudoers"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:59
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:63
+msgid "Send mail if the user is not allowed to run a command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:67
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:71
+msgid "Lecture user the first time they run sudo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:75
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:79
+msgid "Require users to authenticate by default"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:83
+msgid "Root may run sudo"
+msgstr "root-ek sudo abiarizi lezake"
+
+#: plugins/sudoers/def_data.c:87
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:91
+msgid "Log the year in the (non-syslog) log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:95
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:99
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:103
+msgid "Always set $HOME to the target user's home directory"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:107
+msgid "Allow some information gathering to give useful error messages"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:111
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:115
+msgid "Insult the user when they enter an incorrect password"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:119
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:123
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo-k EDITOR ingurune aldagaia erabiliko du"
+
+#: plugins/sudoers/def_data.c:127
+msgid "Prompt for root's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:131
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:135
+msgid "Prompt for the target user's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:139
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:143
+msgid "Set the LOGNAME and USER environment variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:147
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:151
+msgid "Don't initialize the group vector to that of the target user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:155
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %d"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:159
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:163
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:167
+#, c-format
+msgid "Number of tries to enter a password: %d"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:171
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:175
+#, c-format
+msgid "Path to log file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:179
+#, c-format
+msgid "Path to mail program: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:183
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:187
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:191
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:195
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:199
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:203
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:207
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:211
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:215
+#, c-format
+msgid "Default password prompt: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:219
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr ""
+
+#: plugins/sudoers/def_data.c:223
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:227
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:231
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:235
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:239
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:243
+msgid "Preload the dummy exec functions contained in 'noexec_file'"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:247
+#, c-format
+msgid "File containing dummy exec functions: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:251
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:255
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:259
+msgid "If set, users may override the value of `closefrom' with the -C option"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:263
+msgid "Allow users to set arbitrary environment variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:267
+msgid "Reset the environment to a default set of variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:271
+msgid "Environment variables to check for sanity:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:275
+msgid "Environment variables to remove:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:279
+msgid "Environment variables to preserve:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:283
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:287
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:291
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:295
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:299
+msgid "Allow sudo to prompt for a password even if it would be visisble"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:303
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:307
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:311
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:315
+msgid "Log user's input for the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:319
+msgid "Log the output of the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:323
+msgid "Compress I/O logs using zlib"
+msgstr "Trinkotu S/E gertaerak zlib erabiliz"
+
+#: plugins/sudoers/def_data.c:327
+msgid "Always run commands in a pseudo-tty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:331
+msgid "Plugin for non-Unix group support"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:335
+msgid "Directory in which to store input/output logs"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:339
+msgid "File in which to store the input/output log"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:343
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:347
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:197
+msgid ""
+"Available options in a sudoers ``Defaults'' line:\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:204 plugins/sudoers/defaults.c:215
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s: %s\n"
+
+#: plugins/sudoers/defaults.c:211
+#, c-format
+msgid "%s: %.*s\n"
+msgstr "%s: %.*s\n"
+
+#: plugins/sudoers/defaults.c:241
+#, c-format
+msgid "unknown defaults entry `%s'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:249 plugins/sudoers/defaults.c:259
+#: plugins/sudoers/defaults.c:279 plugins/sudoers/defaults.c:292
+#: plugins/sudoers/defaults.c:305 plugins/sudoers/defaults.c:318
+#: plugins/sudoers/defaults.c:331 plugins/sudoers/defaults.c:351
+#: plugins/sudoers/defaults.c:361
+#, c-format
+msgid "value `%s' is invalid for option `%s'"
+msgstr "`%s' balorea baliogabea da `%s' aukerarentzat"
+
+#: plugins/sudoers/defaults.c:252 plugins/sudoers/defaults.c:262
+#: plugins/sudoers/defaults.c:270 plugins/sudoers/defaults.c:287
+#: plugins/sudoers/defaults.c:300 plugins/sudoers/defaults.c:313
+#: plugins/sudoers/defaults.c:326 plugins/sudoers/defaults.c:346
+#: plugins/sudoers/defaults.c:357
+#, c-format
+msgid "no value specified for `%s'"
+msgstr "ez da baliorik ezarri `%s'-(r)entzat"
+
+#: plugins/sudoers/defaults.c:275
+#, c-format
+msgid "values for `%s' must start with a '/'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:337
+#, c-format
+msgid "option `%s' does not take a value"
+msgstr ""
+
+#: plugins/sudoers/env.c:259
+#, c-format
+msgid "internal error, sudo_setenv() overflow"
+msgstr ""
+
+#: plugins/sudoers/env.c:289
+#, c-format
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr ""
+
+#: plugins/sudoers/env.c:694
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr ""
+
+#: plugins/sudoers/find_path.c:68 plugins/sudoers/find_path.c:107
+#: plugins/sudoers/find_path.c:122 plugins/sudoers/iolog.c:124
+#: plugins/sudoers/sudoers.c:868 toke.l:663 toke.l:814
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: gram.y:103
+#, c-format
+msgid ">>> %s: %s near line %d <<<"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:91
+#, c-format
+msgid "%s%s: %s"
+msgstr "%s%s: %s"
+
+#: plugins/sudoers/group_plugin.c:103
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:107
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:114
+#, c-format
+msgid "unable to dlopen %s: %s"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:119
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:124
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:109
+msgid "Local IP address and netmask pairs:\n"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:176 plugins/sudoers/sudoers.c:946
+#, c-format
+msgid "unable to read %s"
+msgstr "ezin da %s irakurri"
+
+#: plugins/sudoers/iolog.c:179
+#, c-format
+msgid "invalid sequence number %s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:225 plugins/sudoers/iolog.c:228
+#: plugins/sudoers/iolog.c:478 plugins/sudoers/iolog.c:483
+#: plugins/sudoers/iolog.c:489 plugins/sudoers/iolog.c:497
+#: plugins/sudoers/iolog.c:505 plugins/sudoers/iolog.c:513
+#: plugins/sudoers/iolog.c:521
+#, c-format
+msgid "unable to create %s"
+msgstr "ezin da %s sortu"
+
+#: plugins/sudoers/iolog_path.c:245 plugins/sudoers/sudoers.c:361
+#, c-format
+msgid "unable to set locale to \"%s\", using \"C\""
+msgstr ""
+
+#: plugins/sudoers/ldap.c:363
+#, c-format
+msgid "sudo_ldap_conf_add_ports: port too large"
+msgstr "sudo_ldap_conf_add_ports: port too large"
+
+#: plugins/sudoers/ldap.c:386
+#, c-format
+msgid "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+msgstr "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+
+#: plugins/sudoers/ldap.c:415
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:444
+#, c-format
+msgid "invalid uri: %s"
+msgstr "baliogabeko uri-a: %s"
+
+#: plugins/sudoers/ldap.c:450
+#, c-format
+msgid "unable to mix ldap and ldaps URIs"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:454
+#, c-format
+msgid "unable to mix ldaps and starttls"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:473
+#, c-format
+msgid "sudo_ldap_parse_uri: out of space building hostbuf"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:536
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:932
+#, c-format
+msgid "unable to get GMT time"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:938
+#, c-format
+msgid "unable to format timestamp"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:946
+#, c-format
+msgid "unable to build time filter"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1044
+#, c-format
+msgid "sudo_ldap_build_pass1 allocation mismatch"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1539
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1541
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: UNKNOWN\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1588
+#, c-format
+msgid " Order: %s\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1596
+#, c-format
+msgid " Commands:\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1983
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2014
+#, c-format
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2245
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr ""
+
+#: plugins/sudoers/linux_audit.c:55
+#, c-format
+msgid "unable to open audit system"
+msgstr ""
+
+#: plugins/sudoers/linux_audit.c:79
+#, c-format
+msgid "internal error, linux_audit_command() overflow"
+msgstr ""
+
+#: plugins/sudoers/linux_audit.c:88
+#, c-format
+msgid "unable to send audit message"
+msgstr ""
+
+#: plugins/sudoers/logging.c:193
+#, c-format
+msgid "unable to open log file: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:196
+#, c-format
+msgid "unable to lock log file: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:295
+msgid "user NOT in sudoers"
+msgstr "erabiltzailea ez dago sudoers-en"
+
+#: plugins/sudoers/logging.c:297
+msgid "user NOT authorized on host"
+msgstr "erabiltzailea ez dago baimendutako ostalarian"
+
+#: plugins/sudoers/logging.c:299
+msgid "command not allowed"
+msgstr "komandua ez dago baimenduta"
+
+#: plugins/sudoers/logging.c:309
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr "%s ez dago sudoers fitxatzegian. Gertaeraren berri emango da.\n"
+
+#: plugins/sudoers/logging.c:312
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr "%s ez dago baimenduta sudo abiarazteko %s-(e)n. Gertaeraren berri emango da.\n"
+
+#: plugins/sudoers/logging.c:316
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Barkatu, %s erabiltzaileak ez luke sudo abiariazi beharko %s-(e)n.\n"
+
+#: plugins/sudoers/logging.c:319
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr "Barkatu, %s erabiltzaileak ez du '%s%s%s' %s%s%s bezala exekutatzeko baimenik %s-(e)n.\n"
+
+#: plugins/sudoers/logging.c:454
+#, c-format
+msgid "unable to fork"
+msgstr ""
+
+#: plugins/sudoers/logging.c:461 plugins/sudoers/logging.c:518
+#, c-format
+msgid "unable to fork: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:511
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:530
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:564
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:774
+#, c-format
+msgid "internal error: insufficient space for log line"
+msgstr ""
+
+#: plugins/sudoers/parse.c:115
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr ""
+
+#: plugins/sudoers/parse.c:369
+#, c-format
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+
+#: plugins/sudoers/parse.c:371
+#, c-format
+msgid " RunAsUsers: "
+msgstr ""
+
+#: plugins/sudoers/parse.c:386
+#, c-format
+msgid " RunAsGroups: "
+msgstr ""
+
+#: plugins/sudoers/parse.c:395
+#, c-format
+msgid ""
+" Commands:\n"
+"\t"
+msgstr ""
+
+#: plugins/sudoers/plugin_error.c:100 plugins/sudoers/plugin_error.c:105
+msgid ": "
+msgstr ": "
+
+#: plugins/sudoers/pwutil.c:244
+#, c-format
+msgid "unable to cache uid %u (%s), already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:252
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:288 plugins/sudoers/pwutil.c:297
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:511
+#, c-format
+msgid "unable to cache gid %u (%s), already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:519
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:548 plugins/sudoers/pwutil.c:557
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:249 plugins/sudoers/set_perms.c:476
+#: plugins/sudoers/set_perms.c:710
+#, c-format
+msgid "unable to change to sudoers gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:290 plugins/sudoers/set_perms.c:514
+#: plugins/sudoers/set_perms.c:748 plugins/sudoers/set_perms.c:882
+msgid "too many processes"
+msgstr "prozesu gehiegi"
+
+#: plugins/sudoers/set_perms.c:943 plugins/sudoers/set_perms.c:959
+msgid "unable to set runas group vector"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:952
+msgid "unable to get runas group vector"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:217
+msgid "unable to reset group vector"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:223
+msgid "unable to get group vector"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:266
+#, c-format
+msgid "Matching Defaults entries for %s on this host:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:279
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:292
+#, c-format
+msgid "User %s may run the following commands on this host:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:302
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:206 plugins/sudoers/sudoers.c:241
+#: plugins/sudoers/sudoers.c:876
+msgid "problem with defaults entries"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:210
+#, c-format
+msgid "no valid sudoers sources found, quitting"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:264
+#, c-format
+msgid "unable to execute %s: %s"
+msgstr "ezin da %s exekutatu: %s"
+
+#: plugins/sudoers/sudoers.c:311
+#, c-format
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:318
+#, c-format
+msgid "you are not permitted to use the -C option"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:407
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr "data-zigiluaren jabea (%s): ez dago horrelako erabiltzailerik"
+
+#: plugins/sudoers/sudoers.c:423
+msgid "no tty"
+msgstr "tty gabe"
+
+#: plugins/sudoers/sudoers.c:424
+#, c-format
+msgid "sorry, you must have a tty to run sudo"
+msgstr "barkatu, tty bat behar duzu sudo abiarazteko"
+
+#: plugins/sudoers/sudoers.c:470
+msgid "No user or host"
+msgstr "Ez dago erabiltzaile edo ostalaririk"
+
+#: plugins/sudoers/sudoers.c:484 plugins/sudoers/sudoers.c:505
+#: plugins/sudoers/sudoers.c:506 plugins/sudoers/sudoers.c:1413
+#: plugins/sudoers/sudoers.c:1414
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: komandoa ez da aurkitu"
+
+#: plugins/sudoers/sudoers.c:486 plugins/sudoers/sudoers.c:502
+#, c-format
+msgid ""
+"ignoring `%s' found in '.'\n"
+"Use `sudo ./%s' if this is the `%s' you wish to run."
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:491
+msgid "validation failure"
+msgstr "balidazio hutsegitea"
+
+#: plugins/sudoers/sudoers.c:501
+msgid "command in current directory"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:513
+#, c-format
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:860
+#, c-format
+msgid "internal error, set_cmnd() overflow"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:904
+#, c-format
+msgid "fixed mode on %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:908
+#, c-format
+msgid "set group on %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:911
+#, c-format
+msgid "unable to set group on %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:914
+#, c-format
+msgid "unable to fix mode on %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:927
+#, c-format
+msgid "%s is not a regular file"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:929
+#, c-format
+msgid "%s is mode 0%o, should be 0%o"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:933
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:936
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:980
+#, c-format
+msgid "only root can use `-c %s'"
+msgstr "soilik root-ek erabili dezake `-c %s'"
+
+#: plugins/sudoers/sudoers.c:990
+#, c-format
+msgid "unknown login class: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1024
+#, c-format
+msgid "unable to resolve host %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1076 plugins/sudoers/testsudoers.c:342
+#, c-format
+msgid "unknown group: %s"
+msgstr "talde ezezaguna: %s"
+
+#: plugins/sudoers/sudoers.c:1108
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1110
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1114
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Sudoers-en bidea: %s\n"
+
+#: plugins/sudoers/sudoers.c:1117
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "nsswitch-en bidea: %s\n"
+
+#: plugins/sudoers/sudoers.c:1119
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "ldap.conf-en bidea: %s\n"
+
+#: plugins/sudoers/sudoers.c:1120
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "ldap.secret-en bidea: %s\n"
+
+#: plugins/sudoers/sudoreplay.c:265
+#, c-format
+msgid "invalid filter option: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:278
+#, c-format
+msgid "invalid max wait: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:284
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:287 plugins/sudoers/visudo.c:174
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s bertsioa %s\n"
+
+#: plugins/sudoers/sudoreplay.c:310
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s/timing: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:316
+#, c-format
+msgid "%s/%s/timing: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:341
+#, c-format
+msgid "invalid log file %s"
+msgstr "baliogabeko %s log fitxategia"
+
+#: plugins/sudoers/sudoreplay.c:343
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:369
+#, c-format
+msgid "unable to set tty to raw mode"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:383
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:425
+#, c-format
+msgid "writing to standard output"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:455
+#, c-format
+msgid "nanosleep: tv_sec %ld, tv_nsec %ld"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:503 plugins/sudoers/sudoreplay.c:528
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:545
+#, c-format
+msgid "too many parenthesized expressions, max %d"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:556
+#, c-format
+msgid "unmatched ')' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:562
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:576
+#, c-format
+msgid "%s requires an argument"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:580
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:586
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:599
+#, c-format
+msgid "unmatched '(' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:601
+#, c-format
+msgid "illegal trailing \"or\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:603
+#, c-format
+msgid "illegal trailing \"!\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:819
+#, c-format
+msgid "invalid regex: %s"
+msgstr "baliogabeko regex-a: %s"
+
+#: plugins/sudoers/sudoreplay.c:941
+#, c-format
+msgid "usage: %s [-h] [-d directory] [-m max_wait] [-s speed_factor] ID\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:944
+#, c-format
+msgid "usage: %s [-h] [-d directory] -l [search expression]\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:953
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:955
+msgid ""
+"\n"
+"Options:\n"
+" -d directory specify directory for session logs\n"
+" -f filter specify which I/O type to display\n"
+" -h display help message and exit\n"
+" -l [expression] list available session IDs that match expression\n"
+" -m max_wait max number of seconds to wait between events\n"
+" -s speed_factor speed up or slow down output\n"
+" -V display version information and exit"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:228
+#, c-format
+msgid "internal error, init_vars() overflow"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:304
+msgid "\thost unmatched"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:307
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:308
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:308
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+
+#: toke.l:667 toke.l:793 toke.l:818 toke.l:904 plugins/sudoers/toke_util.c:111
+#: plugins/sudoers/toke_util.c:163 plugins/sudoers/toke_util.c:202
+msgid "unable to allocate memory"
+msgstr ""
+
+#: toke.l:786
+msgid "too many levels of includes"
+msgstr "include maila gehiegi"
+
+#: plugins/sudoers/toke_util.c:213
+msgid "fill_args: buffer overflow"
+msgstr "fill_args: buffer overflow"
+
+#: plugins/sudoers/visudo.c:175
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:208 plugins/sudoers/auth/rfc1938.c:103
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "ez zara %s datubasean existitzen"
+
+#: plugins/sudoers/visudo.c:238 plugins/sudoers/visudo.c:470
+#, c-format
+msgid "press return to edit %s: "
+msgstr "sakatu intro %s editatzeko:"
+
+#: plugins/sudoers/visudo.c:300 plugins/sudoers/visudo.c:306
+#, c-format
+msgid "write error"
+msgstr "idazketa errorea"
+
+#: plugins/sudoers/visudo.c:360
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:365
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:371
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:394
+#, c-format
+msgid "%s unchanged"
+msgstr "%s aldatu gabea"
+
+#: plugins/sudoers/visudo.c:418
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr ""
+
+#: plugins/sudoers/visudo.c:428
+#, c-format
+msgid "unabled to parse temporary file (%s), unknown error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:463
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:502 plugins/sudoers/visudo.c:511
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%d, %d)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:506 plugins/sudoers/visudo.c:516
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:533
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:547
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:557
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:617
+msgid "What now? "
+msgstr "Eta orain?"
+
+#: plugins/sudoers/visudo.c:631
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:668
+#, c-format
+msgid "unable to execute %s"
+msgstr "ezin da %s exekutatu"
+
+#: plugins/sudoers/visudo.c:675
+#, c-format
+msgid "unable to run %s"
+msgstr "ezin da %s abiarazi"
+
+#: plugins/sudoers/visudo.c:706
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:718
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:721
+#, c-format
+msgid "parse error in %s\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:723
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:737
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%d, %d)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:744
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:783
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s okupatuta, saiatu berriz beranduago"
+
+#: plugins/sudoers/visudo.c:826
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:849
+#, c-format
+msgid "unable to stat editor (%s)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:897
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:986
+#, c-format
+msgid "Error: cycle in %s_Alias `%s'"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:987
+#, c-format
+msgid "Warning: cycle in %s_Alias `%s'"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:990
+#, c-format
+msgid "Error: %s_Alias `%s' referenced but not defined"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:991
+#, c-format
+msgid "Warning: %s_Alias `%s' referenced but not defined"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1128
+#, c-format
+msgid "%s: unused %s_Alias %s"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1185
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1187
+msgid ""
+"\n"
+"Options:\n"
+" -c check-only mode\n"
+" -f sudoers specify sudoers file location\n"
+" -h display help message and exit\n"
+" -q less verbose (quiet) syntax error messages\n"
+" -s strict syntax checking\n"
+" -V display version information and exit"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:64
+msgid "unable to begin bsd authentication"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:71
+msgid "invalid authentication type"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:79
+msgid "unable to setup authentication"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:59
+#, c-format
+msgid "unable to read fwtk config"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:64
+#, c-format
+msgid "unable to connect to authentication server"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:70 plugins/sudoers/auth/fwtk.c:93
+#: plugins/sudoers/auth/fwtk.c:126
+#, c-format
+msgid "lost connection to authentication server"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:74
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:114
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:127
+#, c-format
+msgid "%s: unable to unparse princ ('%s'): %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:144
+#, c-format
+msgid "%s: unable to resolve ccache: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:188
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:204
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:217
+#, c-format
+msgid "%s: unable to initialize ccache: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:221
+#, c-format
+msgid "%s: unable to store cred in ccache: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:284
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:299
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:99
+msgid "unable to initialize PAM"
+msgstr "ezin da PAM hasieratu"
+
+#: plugins/sudoers/auth/pam.c:142
+msgid "account validation failure, is your account locked?"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:146
+msgid "Account or password is expired, reset your password and try again"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:153
+#, c-format
+msgid "pam_chauthtok: %s"
+msgstr "pam_chauthtok: %s"
+
+#: plugins/sudoers/auth/pam.c:157
+msgid "Password expired, contact your system administrator"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:161
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:176
+#, c-format
+msgid "pam_authenticate: %s"
+msgstr "pam_authenticate: %s"
+
+#: plugins/sudoers/auth/pam.c:296
+msgid "Password: "
+msgstr "Pasahitza: "
+
+#: plugins/sudoers/auth/pam.c:297
+msgid "Password:"
+msgstr "Pasahitza:"
+
+#: plugins/sudoers/auth/securid.c:82 plugins/sudoers/auth/securid5.c:106
+#, c-format
+msgid "unable to contact the SecurID server"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:81
+#, c-format
+msgid "failed to initialise the ACE API library"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:115
+#, c-format
+msgid "User ID locked for SecurID Authentication"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:119 plugins/sudoers/auth/securid5.c:169
+#, c-format
+msgid "invalid username length for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:123 plugins/sudoers/auth/securid5.c:174
+#, c-format
+msgid "invalid Authentication Handle for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:127
+#, c-format
+msgid "SecurID communication failed"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:131 plugins/sudoers/auth/securid5.c:213
+#, c-format
+msgid "unknown SecurID error"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:164
+#, c-format
+msgid "invalid passcode length for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/sia.c:106
+msgid "unable to initialize SIA session"
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:124
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:134
+msgid "Invalid authentication methods compiled into sudo! You may mix standalone and non-standalone authentication."
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:243
+#, c-format
+msgid "%d incorrect password attempt"
+msgid_plural "%d incorrect password attempts"
+msgstr[0] "pasahitz sartze saiakera oker %d"
+msgstr[1] "%d pasahitz sartze saiakera oker"
+
+#: plugins/sudoers/auth/sudo_auth.c:335
+msgid "Authentication methods:"
+msgstr "Autentikazio metodoak:"
diff --git a/plugins/sudoers/po/fi.mo b/plugins/sudoers/po/fi.mo
new file mode 100644
index 0000000..ed25938
--- /dev/null
+++ b/plugins/sudoers/po/fi.mo
Binary files differ
diff --git a/plugins/sudoers/po/fi.po b/plugins/sudoers/po/fi.po
new file mode 100644
index 0000000..01e5ba5
--- /dev/null
+++ b/plugins/sudoers/po/fi.po
@@ -0,0 +1,4136 @@
+# Finnish messages for sudoers.
+# This file is put in the public domain.
+# This file is distributed under the same license as the sudo package.
+# Jorma Karvonen <karvonen.jorma@gmail.com>, 2011-2017.
+# Lauri Nurmi <lanurmi@iki.fi>, 2019-2021.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.9.10b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2022-02-11 18:33-0700\n"
+"PO-Revision-Date: 2022-02-27 17:37+0200\n"
+"Last-Translator: Lauri Nurmi <lanurmi@iki.fi>\n"
+"Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\n"
+"Language: fi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 3.0.1\n"
+
+#: confstr.sh:1 gram.y:1198
+msgid "syntax error"
+msgstr "syntaksivirhe"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "%p, salasana: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] %p-käyttäjän salasana: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Salasana: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** TURVALLISUUStietoa %h-koneelta ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Yritä uudelleen."
+
+#: gram.y:233 gram.y:300 gram.y:309 gram.y:318 gram.y:328 gram.y:338
+#: gram.y:362 gram.y:389 gram.y:398 gram.y:406 gram.y:415 gram.y:424
+#: gram.y:498 gram.y:508 gram.y:520 gram.y:564 gram.y:573 gram.y:582
+#: gram.y:591 gram.y:718 gram.y:726 gram.y:737 gram.y:749 gram.y:768
+#: gram.y:923 gram.y:928 gram.y:936 gram.y:950 gram.y:956 gram.y:1078
+#: gram.y:1087 gram.y:1095 gram.y:1104 gram.y:1113 gram.y:1142 gram.y:1151
+#: gram.y:1159 gram.y:1252 gram.y:1382 gram.y:1748 gram.y:1798
+#: lib/eventlog/eventlog.c:309 lib/eventlog/eventlog.c:382
+#: lib/eventlog/eventlog.c:804 lib/eventlog/eventlog.c:881
+#: lib/eventlog/eventlog.c:1176 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:204 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_json.c:150 lib/iolog/iolog_json.c:382
+#: lib/iolog/iolog_json.c:412 lib/iolog/iolog_json.c:555
+#: lib/iolog/iolog_legacy.c:100 lib/iolog/iolog_legacy.c:111
+#: lib/iolog/iolog_legacy.c:123 lib/iolog/iolog_legacy.c:133
+#: lib/iolog/iolog_legacy.c:139 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:84
+#: logsrvd/iolog_writer.c:89 logsrvd/iolog_writer.c:123
+#: logsrvd/iolog_writer.c:172 logsrvd/iolog_writer.c:212
+#: logsrvd/iolog_writer.c:225 logsrvd/iolog_writer.c:261
+#: logsrvd/iolog_writer.c:286 logsrvd/iolog_writer.c:301
+#: logsrvd/iolog_writer.c:314 logsrvd/iolog_writer.c:327
+#: logsrvd/iolog_writer.c:340 logsrvd/iolog_writer.c:355
+#: logsrvd/iolog_writer.c:393 logsrvd/iolog_writer.c:399
+#: logsrvd/iolog_writer.c:406 logsrvd/iolog_writer.c:412
+#: logsrvd/iolog_writer.c:596 logsrvd/logsrv_util.c:64 logsrvd/logsrvd.c:296
+#: logsrvd/logsrvd.c:305 logsrvd/logsrvd.c:1011 logsrvd/logsrvd.c:1073
+#: logsrvd/logsrvd_conf.c:1443 logsrvd/logsrvd_journal.c:70
+#: logsrvd/logsrvd_journal.c:203 logsrvd/logsrvd_journal.c:204
+#: logsrvd/logsrvd_journal.c:260 logsrvd/logsrvd_journal.c:425
+#: logsrvd/logsrvd_journal.c:427 logsrvd/logsrvd_local.c:174
+#: logsrvd/logsrvd_local.c:175 logsrvd/logsrvd_local.c:237
+#: logsrvd/logsrvd_local.c:238 logsrvd/logsrvd_local.c:376
+#: logsrvd/logsrvd_local.c:425 logsrvd/logsrvd_local.c:426
+#: logsrvd/logsrvd_local.c:431 logsrvd/logsrvd_local.c:432
+#: logsrvd/logsrvd_queue.c:154 logsrvd/logsrvd_queue.c:184
+#: logsrvd/logsrvd_queue.c:261 logsrvd/logsrvd_relay.c:439
+#: logsrvd/logsrvd_relay.c:738 logsrvd/logsrvd_relay.c:843
+#: logsrvd/sendlog.c:246 logsrvd/sendlog.c:255 logsrvd/sendlog.c:333
+#: logsrvd/sendlog.c:640 plugins/sudoers/audit.c:116
+#: plugins/sudoers/auth/bsdauth.c:150 plugins/sudoers/auth/kerb5.c:118
+#: plugins/sudoers/auth/kerb5.c:146 plugins/sudoers/auth/pam.c:687
+#: plugins/sudoers/auth/rfc1938.c:111 plugins/sudoers/auth/sia.c:59
+#: plugins/sudoers/check_aliases.c:134 plugins/sudoers/cvtsudoers.c:131
+#: plugins/sudoers/cvtsudoers.c:175 plugins/sudoers/cvtsudoers.c:192
+#: plugins/sudoers/cvtsudoers.c:203 plugins/sudoers/cvtsudoers.c:333
+#: plugins/sudoers/cvtsudoers.c:372 plugins/sudoers/cvtsudoers.c:392
+#: plugins/sudoers/cvtsudoers.c:537 plugins/sudoers/cvtsudoers.c:670
+#: plugins/sudoers/cvtsudoers.c:688 plugins/sudoers/cvtsudoers.c:758
+#: plugins/sudoers/cvtsudoers.c:873 plugins/sudoers/cvtsudoers.c:881
+#: plugins/sudoers/cvtsudoers.c:1376 plugins/sudoers/cvtsudoers.c:1380
+#: plugins/sudoers/cvtsudoers.c:1482 plugins/sudoers/cvtsudoers_csv.c:183
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:76
+#: plugins/sudoers/cvtsudoers_ldif.c:151 plugins/sudoers/cvtsudoers_ldif.c:194
+#: plugins/sudoers/cvtsudoers_ldif.c:235 plugins/sudoers/cvtsudoers_ldif.c:300
+#: plugins/sudoers/cvtsudoers_ldif.c:376 plugins/sudoers/cvtsudoers_ldif.c:430
+#: plugins/sudoers/cvtsudoers_ldif.c:438 plugins/sudoers/cvtsudoers_ldif.c:449
+#: plugins/sudoers/cvtsudoers_ldif.c:456 plugins/sudoers/cvtsudoers_ldif.c:469
+#: plugins/sudoers/cvtsudoers_ldif.c:477 plugins/sudoers/cvtsudoers_ldif.c:624
+#: plugins/sudoers/cvtsudoers_merge.c:47 plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1150
+#: plugins/sudoers/cvtsudoers_merge.c:1223 plugins/sudoers/defaults.c:468
+#: plugins/sudoers/defaults.c:690 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1243 plugins/sudoers/editor.c:190
+#: plugins/sudoers/env.c:262 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:54 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:133
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:264
+#: plugins/sudoers/iolog.c:664 plugins/sudoers/iolog.c:690
+#: plugins/sudoers/ldap.c:184 plugins/sudoers/ldap.c:433
+#: plugins/sudoers/ldap.c:443 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:452 plugins/sudoers/ldap.c:464
+#: plugins/sudoers/ldap.c:760 plugins/sudoers/ldap.c:924
+#: plugins/sudoers/ldap.c:1340 plugins/sudoers/ldap.c:1766
+#: plugins/sudoers/ldap.c:1803 plugins/sudoers/ldap.c:1884
+#: plugins/sudoers/ldap.c:2019 plugins/sudoers/ldap.c:2120
+#: plugins/sudoers/ldap.c:2136 plugins/sudoers/ldap_conf.c:218
+#: plugins/sudoers/ldap_conf.c:249 plugins/sudoers/ldap_conf.c:301
+#: plugins/sudoers/ldap_conf.c:337 plugins/sudoers/ldap_conf.c:443
+#: plugins/sudoers/ldap_conf.c:458 plugins/sudoers/ldap_conf.c:563
+#: plugins/sudoers/ldap_conf.c:596 plugins/sudoers/ldap_conf.c:688
+#: plugins/sudoers/ldap_conf.c:770 plugins/sudoers/ldap_util.c:294
+#: plugins/sudoers/ldap_util.c:301 plugins/sudoers/ldap_util.c:614
+#: plugins/sudoers/linux_audit.c:86 plugins/sudoers/log_client.c:112
+#: plugins/sudoers/log_client.c:390 plugins/sudoers/log_client.c:703
+#: plugins/sudoers/log_client.c:724 plugins/sudoers/log_client.c:1444
+#: plugins/sudoers/log_client.c:1662 plugins/sudoers/log_client.c:1989
+#: plugins/sudoers/log_client.c:2045 plugins/sudoers/logging.c:104
+#: plugins/sudoers/logging.c:185 plugins/sudoers/logging.c:469
+#: plugins/sudoers/logging.c:489 plugins/sudoers/logging.c:628
+#: plugins/sudoers/match_command.c:324 plugins/sudoers/match_command.c:567
+#: plugins/sudoers/match_command.c:616 plugins/sudoers/match_command.c:688
+#: plugins/sudoers/match_command.c:736 plugins/sudoers/match_digest.c:93
+#: plugins/sudoers/parse.c:201 plugins/sudoers/parse.c:218
+#: plugins/sudoers/parse.c:250 plugins/sudoers/parse.c:267
+#: plugins/sudoers/parse.c:290 plugins/sudoers/parse.c:301
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:597
+#: plugins/sudoers/parse_ldif.c:627 plugins/sudoers/parse_ldif.c:652
+#: plugins/sudoers/parse_ldif.c:710 plugins/sudoers/parse_ldif.c:727
+#: plugins/sudoers/parse_ldif.c:755 plugins/sudoers/parse_ldif.c:762
+#: plugins/sudoers/policy.c:570 plugins/sudoers/policy.c:952
+#: plugins/sudoers/prompt.c:93 plugins/sudoers/pwutil.c:199
+#: plugins/sudoers/pwutil.c:270 plugins/sudoers/pwutil.c:348
+#: plugins/sudoers/pwutil.c:522 plugins/sudoers/pwutil.c:587
+#: plugins/sudoers/pwutil.c:659 plugins/sudoers/pwutil.c:857
+#: plugins/sudoers/pwutil.c:913 plugins/sudoers/pwutil.c:957
+#: plugins/sudoers/pwutil.c:1014 plugins/sudoers/sssd.c:145
+#: plugins/sudoers/sssd.c:185 plugins/sudoers/sssd.c:414
+#: plugins/sudoers/sssd.c:479 plugins/sudoers/sssd.c:505
+#: plugins/sudoers/sssd.c:568 plugins/sudoers/sssd.c:761
+#: plugins/sudoers/strvec_join.c:53 plugins/sudoers/stubs.c:111
+#: plugins/sudoers/stubs.c:119 plugins/sudoers/sudoers.c:335
+#: plugins/sudoers/sudoers.c:361 plugins/sudoers/sudoers.c:429
+#: plugins/sudoers/sudoers.c:438 plugins/sudoers/sudoers.c:479
+#: plugins/sudoers/sudoers.c:842 plugins/sudoers/sudoers.c:980
+#: plugins/sudoers/sudoers.c:1039 plugins/sudoers/sudoers.c:1305
+#: plugins/sudoers/sudoreplay.c:562 plugins/sudoers/sudoreplay.c:565
+#: plugins/sudoers/sudoreplay.c:1281 plugins/sudoers/sudoreplay.c:1503
+#: plugins/sudoers/sudoreplay.c:1507 plugins/sudoers/testsudoers.c:120
+#: plugins/sudoers/testsudoers.c:224 plugins/sudoers/testsudoers.c:241
+#: plugins/sudoers/testsudoers.c:580 plugins/sudoers/timestamp.c:424
+#: plugins/sudoers/timestamp.c:468 plugins/sudoers/timestamp.c:980
+#: plugins/sudoers/timestamp.c:1118 plugins/sudoers/toke_util.c:78
+#: plugins/sudoers/toke_util.c:106 plugins/sudoers/toke_util.c:131
+#: plugins/sudoers/toke_util.c:161 plugins/sudoers/toke_util.c:200
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:145
+#: plugins/sudoers/visudo.c:344 plugins/sudoers/visudo.c:350
+#: plugins/sudoers/visudo.c:456 plugins/sudoers/visudo.c:632
+#: plugins/sudoers/visudo.c:962 plugins/sudoers/visudo.c:1035 toke.l:1015
+#: toke.l:1147 toke.l:1218
+msgid "unable to allocate memory"
+msgstr "muistin varaaminen epäonnistui"
+
+#: gram.y:615
+msgid "a digest requires a path name"
+msgstr "tiiviste vaatii polkunimen"
+
+#: gram.y:637
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "”CWD”-muuttujan arvon on alettava merkillä ’/’, ’~’ tai ’*’"
+
+#: gram.y:643
+msgid "\"CWD\" path too long"
+msgstr "”CWD”-polku liian pitkä"
+
+#: gram.y:653
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "”CHROOT”-muuttujan arvon on alettava merkillä ’/’, ’~’ tai ’*’"
+
+#: gram.y:659
+msgid "\"CHROOT\" path too long"
+msgstr "”CHROOT”-polku liian pitkä"
+
+#: gram.y:788
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "syntaksivirhe, varattua sanaa %s käytetty aliaksen nimenä"
+
+#: gram.y:811
+msgid "invalid notbefore value"
+msgstr "virheellinen notbefore-arvo"
+
+#: gram.y:820
+msgid "invalid notafter value"
+msgstr "virheellinen notafter-arvo"
+
+#: gram.y:830 plugins/sudoers/policy.c:353
+msgid "timeout value too large"
+msgstr "aikakatkaisuarvo on liian suuri"
+
+#: gram.y:832 plugins/sudoers/policy.c:355
+msgid "invalid timeout value"
+msgstr "virheellinen aikakatkaisuarvo"
+
+#: gram.y:946 plugins/sudoers/sudoers.c:998
+msgid "command too long"
+msgstr "komento on liian pitkä"
+
+#: gram.y:1200
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: gram.y:1250
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Alias ”%s” on jo määritelty"
+
+#: gram.y:1748 gram.y:1798 lib/eventlog/eventlog.c:309
+#: lib/eventlog/eventlog.c:804 lib/eventlog/eventlog.c:877
+#: lib/eventlog/eventlog.c:880 lib/eventlog/eventlog.c:1176
+#: lib/iolog/iolog_filter.c:142 lib/iolog/iolog_filter.c:204
+#: lib/iolog/iolog_filter.c:232 lib/iolog/iolog_json.c:150
+#: lib/iolog/iolog_json.c:381 lib/iolog/iolog_json.c:412
+#: lib/iolog/iolog_json.c:555 lib/iolog/iolog_legacy.c:100
+#: lib/iolog/iolog_legacy.c:111 lib/iolog/iolog_legacy.c:123
+#: lib/iolog/iolog_legacy.c:133 lib/iolog/iolog_legacy.c:139
+#: lib/iolog/iolog_loginfo.c:76 lib/iolog/iolog_loginfo.c:212
+#: logsrvd/iolog_writer.c:84 logsrvd/iolog_writer.c:89
+#: logsrvd/iolog_writer.c:123 logsrvd/iolog_writer.c:162
+#: logsrvd/iolog_writer.c:171 logsrvd/iolog_writer.c:189
+#: logsrvd/iolog_writer.c:211 logsrvd/iolog_writer.c:224
+#: logsrvd/iolog_writer.c:251 logsrvd/iolog_writer.c:260
+#: logsrvd/iolog_writer.c:276 logsrvd/iolog_writer.c:285
+#: logsrvd/iolog_writer.c:300 logsrvd/iolog_writer.c:313
+#: logsrvd/iolog_writer.c:326 logsrvd/iolog_writer.c:339
+#: logsrvd/iolog_writer.c:354 logsrvd/iolog_writer.c:393
+#: logsrvd/iolog_writer.c:399 logsrvd/iolog_writer.c:406
+#: logsrvd/iolog_writer.c:412 logsrvd/iolog_writer.c:596
+#: logsrvd/logsrv_util.c:64 logsrvd/logsrvd.c:296 logsrvd/logsrvd.c:305
+#: logsrvd/logsrvd.c:448 logsrvd/logsrvd.c:485 logsrvd/logsrvd.c:593
+#: logsrvd/logsrvd.c:1084 logsrvd/logsrvd.c:1400 logsrvd/logsrvd.c:1406
+#: logsrvd/logsrvd_conf.c:1443 logsrvd/logsrvd_journal.c:70
+#: logsrvd/logsrvd_journal.c:114 logsrvd/logsrvd_journal.c:203
+#: logsrvd/logsrvd_journal.c:233 logsrvd/logsrvd_journal.c:237
+#: logsrvd/logsrvd_journal.c:245 logsrvd/logsrvd_journal.c:268
+#: logsrvd/logsrvd_journal.c:272 logsrvd/logsrvd_journal.c:425
+#: logsrvd/logsrvd_local.c:174 logsrvd/logsrvd_local.c:237
+#: logsrvd/logsrvd_local.c:425 logsrvd/logsrvd_local.c:431
+#: logsrvd/logsrvd_local.c:450 logsrvd/logsrvd_queue.c:153
+#: logsrvd/logsrvd_queue.c:184 logsrvd/logsrvd_queue.c:261
+#: logsrvd/sendlog.c:246 logsrvd/sendlog.c:255 logsrvd/sendlog.c:333
+#: logsrvd/sendlog.c:640 logsrvd/sendlog.c:1526 logsrvd/sendlog.c:1533
+#: logsrvd/sendlog.c:1756 logsrvd/tls_init.c:293 logsrvd/tls_init.c:314
+#: logsrvd/tls_init.c:324 plugins/sudoers/audit.c:116
+#: plugins/sudoers/auth/pam.c:502 plugins/sudoers/auth/pam.c:687
+#: plugins/sudoers/auth/rfc1938.c:111 plugins/sudoers/check_aliases.c:134
+#: plugins/sudoers/cvtsudoers.c:131 plugins/sudoers/cvtsudoers.c:174
+#: plugins/sudoers/cvtsudoers.c:191 plugins/sudoers/cvtsudoers.c:202
+#: plugins/sudoers/cvtsudoers.c:332 plugins/sudoers/cvtsudoers.c:536
+#: plugins/sudoers/cvtsudoers.c:669 plugins/sudoers/cvtsudoers.c:687
+#: plugins/sudoers/cvtsudoers.c:758 plugins/sudoers/cvtsudoers.c:873
+#: plugins/sudoers/cvtsudoers.c:880 plugins/sudoers/cvtsudoers.c:1376
+#: plugins/sudoers/cvtsudoers.c:1380 plugins/sudoers/cvtsudoers.c:1482
+#: plugins/sudoers/cvtsudoers_csv.c:182 plugins/sudoers/cvtsudoers_csv.c:245
+#: plugins/sudoers/cvtsudoers_json.c:75 plugins/sudoers/cvtsudoers_ldif.c:150
+#: plugins/sudoers/cvtsudoers_ldif.c:193 plugins/sudoers/cvtsudoers_ldif.c:234
+#: plugins/sudoers/cvtsudoers_ldif.c:299 plugins/sudoers/cvtsudoers_ldif.c:375
+#: plugins/sudoers/cvtsudoers_ldif.c:429 plugins/sudoers/cvtsudoers_ldif.c:437
+#: plugins/sudoers/cvtsudoers_ldif.c:448 plugins/sudoers/cvtsudoers_ldif.c:455
+#: plugins/sudoers/cvtsudoers_ldif.c:468 plugins/sudoers/cvtsudoers_ldif.c:476
+#: plugins/sudoers/cvtsudoers_ldif.c:623 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1149
+#: plugins/sudoers/cvtsudoers_merge.c:1223 plugins/sudoers/defaults.c:468
+#: plugins/sudoers/defaults.c:690 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1243 plugins/sudoers/editor.c:190
+#: plugins/sudoers/env.c:262 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:54 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:132
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:264
+#: plugins/sudoers/iolog.c:664 plugins/sudoers/iolog.c:690
+#: plugins/sudoers/ldap.c:184 plugins/sudoers/ldap.c:433
+#: plugins/sudoers/ldap.c:443 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:452 plugins/sudoers/ldap.c:464
+#: plugins/sudoers/ldap.c:760 plugins/sudoers/ldap.c:924
+#: plugins/sudoers/ldap.c:1340 plugins/sudoers/ldap.c:1766
+#: plugins/sudoers/ldap.c:1803 plugins/sudoers/ldap.c:1884
+#: plugins/sudoers/ldap.c:2019 plugins/sudoers/ldap.c:2120
+#: plugins/sudoers/ldap.c:2136 plugins/sudoers/ldap_conf.c:218
+#: plugins/sudoers/ldap_conf.c:249 plugins/sudoers/ldap_conf.c:301
+#: plugins/sudoers/ldap_conf.c:337 plugins/sudoers/ldap_conf.c:443
+#: plugins/sudoers/ldap_conf.c:458 plugins/sudoers/ldap_conf.c:563
+#: plugins/sudoers/ldap_conf.c:596 plugins/sudoers/ldap_conf.c:687
+#: plugins/sudoers/ldap_conf.c:770 plugins/sudoers/ldap_util.c:293
+#: plugins/sudoers/ldap_util.c:300 plugins/sudoers/ldap_util.c:614
+#: plugins/sudoers/linux_audit.c:86 plugins/sudoers/log_client.c:112
+#: plugins/sudoers/log_client.c:221 plugins/sudoers/log_client.c:242
+#: plugins/sudoers/log_client.c:255 plugins/sudoers/log_client.c:390
+#: plugins/sudoers/log_client.c:703 plugins/sudoers/log_client.c:724
+#: plugins/sudoers/log_client.c:1444 plugins/sudoers/log_client.c:1662
+#: plugins/sudoers/log_client.c:1989 plugins/sudoers/log_client.c:2045
+#: plugins/sudoers/logging.c:104 plugins/sudoers/logging.c:184
+#: plugins/sudoers/logging.c:185 plugins/sudoers/logging.c:468
+#: plugins/sudoers/logging.c:488 plugins/sudoers/logging.c:628
+#: plugins/sudoers/match_command.c:323 plugins/sudoers/match_command.c:566
+#: plugins/sudoers/match_command.c:615 plugins/sudoers/match_command.c:688
+#: plugins/sudoers/match_command.c:735 plugins/sudoers/match_digest.c:93
+#: plugins/sudoers/parse.c:200 plugins/sudoers/parse.c:217
+#: plugins/sudoers/parse.c:249 plugins/sudoers/parse.c:266
+#: plugins/sudoers/parse.c:289 plugins/sudoers/parse.c:300
+#: plugins/sudoers/parse_ldif.c:152 plugins/sudoers/parse_ldif.c:183
+#: plugins/sudoers/parse_ldif.c:252 plugins/sudoers/parse_ldif.c:260
+#: plugins/sudoers/parse_ldif.c:265 plugins/sudoers/parse_ldif.c:341
+#: plugins/sudoers/parse_ldif.c:352 plugins/sudoers/parse_ldif.c:379
+#: plugins/sudoers/parse_ldif.c:396 plugins/sudoers/parse_ldif.c:408
+#: plugins/sudoers/parse_ldif.c:412 plugins/sudoers/parse_ldif.c:426
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:597
+#: plugins/sudoers/parse_ldif.c:626 plugins/sudoers/parse_ldif.c:651
+#: plugins/sudoers/parse_ldif.c:709 plugins/sudoers/parse_ldif.c:726
+#: plugins/sudoers/parse_ldif.c:754 plugins/sudoers/parse_ldif.c:761
+#: plugins/sudoers/policy.c:152 plugins/sudoers/policy.c:161
+#: plugins/sudoers/policy.c:170 plugins/sudoers/policy.c:197
+#: plugins/sudoers/policy.c:338 plugins/sudoers/policy.c:353
+#: plugins/sudoers/policy.c:355 plugins/sudoers/policy.c:391
+#: plugins/sudoers/policy.c:400 plugins/sudoers/policy.c:448
+#: plugins/sudoers/policy.c:458 plugins/sudoers/policy.c:467
+#: plugins/sudoers/policy.c:476 plugins/sudoers/policy.c:570
+#: plugins/sudoers/policy.c:952 plugins/sudoers/prompt.c:93
+#: plugins/sudoers/pwutil.c:199 plugins/sudoers/pwutil.c:270
+#: plugins/sudoers/pwutil.c:348 plugins/sudoers/pwutil.c:522
+#: plugins/sudoers/pwutil.c:587 plugins/sudoers/pwutil.c:659
+#: plugins/sudoers/pwutil.c:857 plugins/sudoers/pwutil.c:913
+#: plugins/sudoers/pwutil.c:957 plugins/sudoers/pwutil.c:1014
+#: plugins/sudoers/set_perms.c:363 plugins/sudoers/set_perms.c:706
+#: plugins/sudoers/set_perms.c:1073 plugins/sudoers/set_perms.c:1380
+#: plugins/sudoers/set_perms.c:1549 plugins/sudoers/sssd.c:144
+#: plugins/sudoers/sssd.c:185 plugins/sudoers/sssd.c:414
+#: plugins/sudoers/sssd.c:479 plugins/sudoers/sssd.c:505
+#: plugins/sudoers/sssd.c:568 plugins/sudoers/sssd.c:761
+#: plugins/sudoers/strvec_join.c:53 plugins/sudoers/stubs.c:111
+#: plugins/sudoers/stubs.c:119 plugins/sudoers/sudoers.c:335
+#: plugins/sudoers/sudoers.c:361 plugins/sudoers/sudoers.c:429
+#: plugins/sudoers/sudoers.c:438 plugins/sudoers/sudoers.c:479
+#: plugins/sudoers/sudoers.c:842 plugins/sudoers/sudoers.c:980
+#: plugins/sudoers/sudoers.c:1039 plugins/sudoers/sudoers.c:1305
+#: plugins/sudoers/sudoreplay.c:562 plugins/sudoers/sudoreplay.c:565
+#: plugins/sudoers/sudoreplay.c:1281 plugins/sudoers/sudoreplay.c:1503
+#: plugins/sudoers/sudoreplay.c:1507 plugins/sudoers/testsudoers.c:120
+#: plugins/sudoers/testsudoers.c:224 plugins/sudoers/testsudoers.c:241
+#: plugins/sudoers/testsudoers.c:580 plugins/sudoers/timestamp.c:424
+#: plugins/sudoers/timestamp.c:468 plugins/sudoers/timestamp.c:980
+#: plugins/sudoers/timestamp.c:1118 plugins/sudoers/toke_util.c:78
+#: plugins/sudoers/toke_util.c:106 plugins/sudoers/toke_util.c:131
+#: plugins/sudoers/toke_util.c:160 plugins/sudoers/toke_util.c:200
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:145
+#: plugins/sudoers/visudo.c:344 plugins/sudoers/visudo.c:350
+#: plugins/sudoers/visudo.c:456 plugins/sudoers/visudo.c:632
+#: plugins/sudoers/visudo.c:962 plugins/sudoers/visudo.c:1035 toke.l:1015
+#: toke.l:1147 toke.l:1210 toke.l:1218
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:314 lib/iolog/iolog_json.c:562
+#: lib/iolog/iolog_json.c:568 lib/iolog/iolog_json.c:574
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:244 plugins/sudoers/cvtsudoers_ldif.c:251
+#: plugins/sudoers/cvtsudoers_ldif.c:580 plugins/sudoers/env.c:326
+#: plugins/sudoers/env.c:333 plugins/sudoers/env.c:444
+#: plugins/sudoers/ldap.c:531 plugins/sudoers/ldap.c:764
+#: plugins/sudoers/ldap.c:1137 plugins/sudoers/ldap_conf.c:222
+#: plugins/sudoers/ldap_conf.c:312 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:92 plugins/sudoers/policy.c:740
+#: plugins/sudoers/policy.c:751 plugins/sudoers/prompt.c:168
+#: plugins/sudoers/serialize_list.c:62 plugins/sudoers/serialize_list.c:71
+#: plugins/sudoers/strvec_join.c:62 plugins/sudoers/testsudoers.c:245
+#: plugins/sudoers/toke_util.c:213 toke.l:979 toke.l:1181
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "sisäinen virhe, %s-ylivuoto"
+
+#: lib/eventlog/eventlog.c:373
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "funktion dup kutsuminen vakiosyötteellä epäonnistui: %m"
+
+#: lib/eventlog/eventlog.c:415
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "käskyn %s suorittaminen epäonnistui: %m"
+
+#: lib/eventlog/eventlog.c:456 plugins/sudoers/auth/aix_auth.c:198
+msgid "unable to fork"
+msgstr "haarauttaminen epäonnistui"
+
+#: lib/eventlog/eventlog.c:464 lib/eventlog/eventlog.c:518
+#, c-format
+msgid "unable to fork: %m"
+msgstr "fork-funktion kutsuminen epäonnistui: %m"
+
+#: lib/eventlog/eventlog.c:508
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "putken avaaminen epäonnistui: %m"
+
+#: lib/eventlog/eventlog.c:1007
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:1036
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s: (komento jatkui) %s"
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1296
+#: plugins/sudoers/sudoreplay.c:1293 plugins/sudoers/sudoreplay.c:1558
+#, fuzzy, c-format
+#| msgid "invalid regular expression: %s"
+msgid "invalid regular expression \"%s\": %s"
+msgstr "virheellinen säännöllinen lauseke: %s"
+
+#: lib/iolog/iolog_json.c:140
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "odotettiin JSON_STRINGiä, saatiin %d"
+
+#: lib/iolog/iolog_json.c:145
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY liian suuri"
+
+#: lib/iolog/iolog_json.c:404
+msgid "missing double quote in name"
+msgstr "nimestä puuttuu lainausmerkki"
+
+#: lib/iolog/iolog_json.c:501
+msgid "missing JSON_OBJECT"
+msgstr "puuttuva JSON_OBJECT"
+
+#: lib/iolog/iolog_json.c:505
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "odotettiin JSON_OBJECTia, saatiin %d"
+
+#: lib/iolog/iolog_json.c:661
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "json-pino täyttyi (enintään %u kehystä)"
+
+#: lib/iolog/iolog_json.c:735
+msgid "objects must consist of name:value pairs"
+msgstr "objektien on oltava nimi:arvo-pareja"
+
+#: lib/iolog/iolog_json.c:740 lib/iolog/iolog_json.c:771
+#: lib/iolog/iolog_json.c:815 lib/iolog/iolog_json.c:837
+#: lib/iolog/iolog_json.c:859 lib/iolog/iolog_json.c:881
+#: lib/iolog/iolog_json.c:903
+msgid "missing separator between values"
+msgstr "arvojen välinen erotin puuttuu"
+
+#: lib/iolog/iolog_json.c:755 lib/iolog/iolog_json.c:929
+msgid "unmatched close brace"
+msgstr "pariton sulkeva aaltosulje"
+
+#: lib/iolog/iolog_json.c:766
+msgid "unexpected array"
+msgstr "odottamaton taulukko"
+
+#: lib/iolog/iolog_json.c:786 lib/iolog/iolog_json.c:932
+msgid "unmatched close bracket"
+msgstr "pariton sulkeva kulmasulje"
+
+#: lib/iolog/iolog_json.c:797
+msgid "unexpected string"
+msgstr "odottamaton merkkijono"
+
+#: lib/iolog/iolog_json.c:808
+msgid "missing colon after name"
+msgstr "puuttuva kaksoispiste nimen jälkeen"
+
+#: lib/iolog/iolog_json.c:829 lib/iolog/iolog_json.c:851
+msgid "unexpected boolean"
+msgstr "odottamaton totuusarvo"
+
+#: lib/iolog/iolog_json.c:873
+msgid "unexpected null"
+msgstr "odottamaton null"
+
+#: lib/iolog/iolog_json.c:894
+msgid "unexpected number"
+msgstr "odottamaton lukuarvo"
+
+#: lib/iolog/iolog_json.c:941
+msgid "parse error"
+msgstr "jäsennysvirhe"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: virheellinen lokitiedosto"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: aikaleimakenttä puuttuu"
+
+#: lib/iolog/iolog_legacy.c:89
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: aikaleima %s: %s"
+
+#: lib/iolog/iolog_legacy.c:96
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: käyttäjäkenttä puuttuu"
+
+#: lib/iolog/iolog_legacy.c:107
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: suorita käyttäjänä-kenttä puuttuu"
+
+#: lib/iolog/iolog_legacy.c:118
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: suorita ryhmänä-kenttä puuttuu"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s on olemassa, mutta ei ole hakemisto (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:119 lib/iolog/iolog_mkdtemp.c:77
+#: logsrvd/iolog_writer.c:807 plugins/sudoers/timestamp.c:205
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "käskyn mkdir %s suorittaminen epäonnistui"
+
+#: lib/iolog/iolog_mkdtemp.c:81 plugins/sudoers/visudo.c:731
+#: plugins/sudoers/visudo.c:765 plugins/sudoers/visudo.c:771
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "tilan %s vaihtaminen arvoon 0%o epäonnistui"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "virhe luettaessa ajoitustiedostoa: %s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "virheellinen ajoitustiedostorivi: %s"
+
+# Parametri on path, mutta saattaa sisältää suoritettavan ohjelman
+#: logsrvd/iolog_writer.c:130 plugins/sudoers/logging.c:804
+#: plugins/sudoers/policy.c:550
+msgid "unable to generate UUID"
+msgstr "UUID-tunnusta ei voi luoda"
+
+#: logsrvd/iolog_writer.c:158 logsrvd/iolog_writer.c:176
+#: logsrvd/iolog_writer.c:185 logsrvd/iolog_writer.c:203
+#: logsrvd/iolog_writer.c:216 logsrvd/iolog_writer.c:229
+#: logsrvd/iolog_writer.c:240 logsrvd/iolog_writer.c:247
+#: logsrvd/iolog_writer.c:265 logsrvd/iolog_writer.c:272
+#: logsrvd/iolog_writer.c:290 logsrvd/iolog_writer.c:305
+#: logsrvd/iolog_writer.c:318 logsrvd/iolog_writer.c:331
+#: logsrvd/iolog_writer.c:344 logsrvd/iolog_writer.c:359
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s: protokollavirhe: väärä tyyppi %s:lle"
+
+#: logsrvd/iolog_writer.c:370 logsrvd/iolog_writer.c:375
+#: logsrvd/iolog_writer.c:380 logsrvd/iolog_writer.c:385
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s: protokollavirhe: %s puuttuu AcceptMessagesta"
+
+#: logsrvd/iolog_writer.c:446
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s: istuntotunnusta ei voi muotoilla"
+
+#: logsrvd/iolog_writer.c:460 logsrvd/iolog_writer.c:474
+#: logsrvd/iolog_writer.c:488 logsrvd/iolog_writer.c:503
+#: logsrvd/iolog_writer.c:517 logsrvd/iolog_writer.c:531
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s: %s on asettamatta"
+
+#: logsrvd/iolog_writer.c:567 logsrvd/iolog_writer.c:574
+#, fuzzy, c-format
+#| msgid "unable to open log file: %s"
+msgid "unable to expand iolog path %s"
+msgstr "lokitiedoston avaaminen epäonnistui: %s"
+
+# Parametrina on pathbuf
+#: logsrvd/iolog_writer.c:592
+#, fuzzy, c-format
+#| msgid "unable to create %s/%s"
+msgid "unable to create iolog path %s"
+msgstr "tiedostoa %s/%s ei voida luoda"
+
+#: logsrvd/iolog_writer.c:622
+#, c-format
+msgid "invalid iofd %d"
+msgstr "virheellinen iofd %d"
+
+#: logsrvd/iolog_writer.c:642
+#, c-format
+msgid "error closing iofd %d: %s"
+msgstr "virhe suljettaessa iofd:tä %d: %s"
+
+#: logsrvd/iolog_writer.c:662
+#, c-format
+msgid "error flushing iofd %d: %s"
+msgstr "virhe huuhdeltaessa iofd:tä %d: %s"
+
+# Toiseksi viimeinen %s on esim. ""Host_Alias" ja viimeinen sen nimi.
+#: logsrvd/iolog_writer.c:777
+#, fuzzy, c-format
+#| msgid "Warning: %s:%d:%d: %s \"%s\" referenced but not defined"
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "Varoitus: %s:%d:%d määrittelemätön %s ”%s” viitattuna mutta määrittelemättä"
+
+#: logsrvd/iolog_writer.c:789 logsrvd/logsrvd_journal.c:377
+#, fuzzy, c-format
+#| msgid "unable to find resume point [%lld, %ld] in %s/%s"
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "jatkopistettä [%lld, %ld] ei löydy tiedostosta %s/%s"
+
+# Avaamisen kohde voi olla timestamp file, sudoers file tai pathbuf
+#: logsrvd/iolog_writer.c:811 logsrvd/logsrvd_journal.c:420
+#: logsrvd/logsrvd_queue.c:110 logsrvd/tls_init.c:245
+#: plugins/sudoers/check.c:273 plugins/sudoers/cvtsudoers.c:730
+#: plugins/sudoers/cvtsudoers.c:751 plugins/sudoers/cvtsudoers.c:1442
+#: plugins/sudoers/cvtsudoers_csv.c:681 plugins/sudoers/cvtsudoers_json.c:885
+#: plugins/sudoers/cvtsudoers_ldif.c:697 plugins/sudoers/sudoers.c:1092
+#: plugins/sudoers/sudoreplay.c:1469 plugins/sudoers/timestamp.c:433
+#: plugins/sudoers/tsdump.c:128 plugins/sudoers/visudo.c:949
+#, c-format
+msgid "unable to open %s"
+msgstr "kohteen %s avaaminen epäonnistui"
+
+# Avaamisen kohde voi olla timestamp file, sudoers file tai pathbuf
+#: logsrvd/iolog_writer.c:823 logsrvd/logsrv_util.c:100
+#: logsrvd/logsrv_util.c:107 plugins/sudoers/sudoreplay.c:362
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "ei voi avata tiedostoa %s/%s"
+
+#: logsrvd/iolog_writer.c:836
+#, fuzzy, c-format
+#| msgid "unable to read %s/%s: %s"
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "tiedostosta %s/%s lukeminen epäonnistui: %s"
+
+# Parametrina on pathbuf
+#: logsrvd/iolog_writer.c:865 logsrvd/logsrvd_journal.c:185
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "tiedoston %s uudelleennimeäminen nimelle %s epäonnistui"
+
+#: logsrvd/logsrv_util.c:139 logsrvd/logsrv_util.c:168
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s: jatkopistettä [%lld, %ld] ei löydy"
+
+#: logsrvd/logsrv_util.c:151
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "puuttuva siirräntälokitiedosto %s/%s"
+
+# Ensimmäinen parametri on auth name
+#: logsrvd/logsrv_util.c:158
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s: siirtyminen %zu tavua eteenpäin epäonnistui"
+
+#: logsrvd/logsrvd.c:266 logsrvd/logsrvd_queue.c:130
+#, fuzzy
+#| msgid "unable to connect to relay host"
+msgid "unable to connect to relay"
+msgstr "yhteyden muodostaminen välitinkoneeseen ei onnistu"
+
+#: logsrvd/logsrvd.c:325 logsrvd/logsrvd_relay.c:835
+#, c-format
+msgid "server message too large: %zu"
+msgstr "palvelinsanoma on liian suuri: %zu"
+
+#: logsrvd/logsrvd.c:417 logsrvd/logsrvd.c:534 logsrvd/logsrvd.c:613
+#: logsrvd/logsrvd.c:837 logsrvd/logsrvd.c:851 logsrvd/logsrvd.c:1010
+#: logsrvd/logsrvd.c:1134 logsrvd/logsrvd.c:1307 logsrvd/logsrvd.c:1325
+#: logsrvd/logsrvd.c:1423 logsrvd/logsrvd.c:1546 logsrvd/logsrvd.c:1730
+#: logsrvd/logsrvd_journal.c:489 logsrvd/logsrvd_local.c:197
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_relay.c:167
+#: logsrvd/logsrvd_relay.c:244 logsrvd/logsrvd_relay.c:248
+#: logsrvd/logsrvd_relay.c:384 logsrvd/logsrvd_relay.c:576
+#: logsrvd/logsrvd_relay.c:737 logsrvd/logsrvd_relay.c:1121
+#: logsrvd/sendlog.c:1316 logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: logsrvd/tls_client.c:209 plugins/sudoers/audit.c:276
+#: plugins/sudoers/iolog.c:1027 plugins/sudoers/iolog.c:1160
+#: plugins/sudoers/iolog.c:1258 plugins/sudoers/log_client.c:116
+#: plugins/sudoers/log_client.c:332 plugins/sudoers/log_client.c:348
+#: plugins/sudoers/log_client.c:395 plugins/sudoers/log_client.c:599
+#: plugins/sudoers/log_client.c:606 plugins/sudoers/log_client.c:1131
+#: plugins/sudoers/log_client.c:1413 plugins/sudoers/log_client.c:1454
+#: plugins/sudoers/log_client.c:1462 plugins/sudoers/log_client.c:1618
+#: plugins/sudoers/log_client.c:1734 plugins/sudoers/log_client.c:2053
+#: plugins/sudoers/log_client.c:2061 plugins/sudoers/logging.c:142
+#: plugins/sudoers/logging.c:199 plugins/sudoers/sudoreplay.c:522
+#: plugins/sudoers/sudoreplay.c:569 plugins/sudoers/sudoreplay.c:811
+#: plugins/sudoers/sudoreplay.c:923 plugins/sudoers/sudoreplay.c:1014
+#: plugins/sudoers/sudoreplay.c:1029 plugins/sudoers/sudoreplay.c:1036
+#: plugins/sudoers/sudoreplay.c:1043 plugins/sudoers/sudoreplay.c:1050
+#: plugins/sudoers/sudoreplay.c:1057 plugins/sudoers/sudoreplay.c:1184
+msgid "unable to add event to queue"
+msgstr "tapahtuman lisääminen jonoon epäonnistui"
+
+#: logsrvd/logsrvd.c:441 logsrvd/logsrvd.c:478 logsrvd/logsrvd.c:510
+#: logsrvd/logsrvd.c:558 logsrvd/logsrvd.c:630 logsrvd/logsrvd.c:660
+#: logsrvd/logsrvd.c:690 logsrvd/logsrvd.c:720 logsrvd/logsrvd_relay.c:505
+#: logsrvd/logsrvd_relay.c:538
+#, fuzzy, c-format
+#| msgid "%s: unexpected state %d"
+msgid "unexpected state %d for %s"
+msgstr "%s: odottamaton tila %d"
+
+#: logsrvd/logsrvd.c:442 logsrvd/logsrvd.c:479 logsrvd/logsrvd.c:511
+#: logsrvd/logsrvd.c:559 logsrvd/logsrvd.c:631 logsrvd/logsrvd.c:661
+#: logsrvd/logsrvd.c:691 logsrvd/logsrvd.c:721 logsrvd/logsrvd_relay.c:507
+#: logsrvd/logsrvd_relay.c:540
+msgid "state machine error"
+msgstr "tilakoneen virhe"
+
+#: logsrvd/logsrvd.c:448 logsrvd/logsrvd.c:449
+msgid "invalid AcceptMessage"
+msgstr "virheellinen AcceptMessage"
+
+#: logsrvd/logsrvd.c:485 logsrvd/logsrvd.c:486
+msgid "invalid RejectMessage"
+msgstr "virheellinen RejectMessage"
+
+#: logsrvd/logsrvd.c:593 logsrvd/logsrvd.c:594
+msgid "invalid AlertMessage"
+msgstr "virheellinen AlertMessage"
+
+#: logsrvd/logsrvd.c:635 logsrvd/logsrvd.c:665 logsrvd/logsrvd.c:695
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s: odottamaton IoBuffer"
+
+#: logsrvd/logsrvd.c:636 logsrvd/logsrvd.c:666 logsrvd/logsrvd.c:696
+msgid "protocol error"
+msgstr "protokollavirhe"
+
+#: logsrvd/logsrvd.c:791 logsrvd/logsrvd_journal.c:357
+#: logsrvd/logsrvd_local.c:125 logsrvd/logsrvd_relay.c:671
+#, fuzzy, c-format
+#| msgid "%s: unexpected type_case value %d"
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "%s: odottamaton type_case-arvo %d"
+
+#: logsrvd/logsrvd.c:793
+msgid "unrecognized ClientMessage type"
+msgstr "tunnistamaton ClientMessage-tyyppi"
+
+#: logsrvd/logsrvd.c:883
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "aikakatkaisu kirjoitettaessa asiakkaalle %s"
+
+#: logsrvd/logsrvd.c:888 logsrvd/logsrvd_relay.c:907 logsrvd/sendlog.c:1420
+#, fuzzy, c-format
+#| msgid "missing write buffer"
+msgid "missing write buffer for client %s"
+msgstr "puuttuva kirjoituspuskuri"
+
+#: logsrvd/logsrvd.c:981
+#, fuzzy, c-format
+#| msgid "timeout reading from relay"
+msgid "timed out reading from client %s"
+msgstr "aikakatkaisu luettaessa välittimeltä"
+
+#: logsrvd/logsrvd.c:1022 logsrvd/logsrvd_relay.c:771
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1065 logsrvd/logsrvd_relay.c:200 logsrvd/sendlog.c:317
+#: plugins/sudoers/log_client.c:709
+#, c-format
+msgid "client message too large: %zu"
+msgstr "asiakassanoma on liian suuri: %zu"
+
+#: logsrvd/logsrvd.c:1066 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:247
+msgid "client message too large"
+msgstr "asiakassanoma on liian suuri"
+
+#: logsrvd/logsrvd.c:1084 logsrvd/logsrvd.c:1085
+msgid "invalid ClientMessage"
+msgstr "virheellinen ClientMessage"
+
+#: logsrvd/logsrvd.c:1386
+msgid "unable to get remote IP addr"
+msgstr "vastapään IP-osoitteen noutaminen ei onnistu"
+
+#: logsrvd/logsrvd.c:1415 logsrvd/tls_client.c:196
+#: plugins/sudoers/log_client.c:270
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "Käyttäjätietoja ei voi liittää ssl-objektiin: %s"
+
+#: logsrvd/logsrvd.c:1596 logsrvd/logsrvd.c:1948
+msgid "unable to setup listen socket"
+msgstr "kuuntelusoketin valmistelu epäonnistui"
+
+#: logsrvd/logsrvd.c:1713
+#, c-format
+msgid "unexpected signal %d"
+msgstr "odottamaton signaali %d"
+
+#: logsrvd/logsrvd.c:1850
+msgid "sudo log server"
+msgstr "sudo-lokipalvelin"
+
+#: logsrvd/logsrvd.c:1852 logsrvd/sendlog.c:116
+msgid "Options:"
+msgstr "Valitsimet:"
+
+#: logsrvd/logsrvd.c:1854
+msgid "path to configuration file"
+msgstr "asetustiedoston polku"
+
+#: logsrvd/logsrvd.c:1856 logsrvd/sendlog.c:118
+msgid "display help message and exit"
+msgstr "näytä opasteviesti ja poistu"
+
+#: logsrvd/logsrvd.c:1858
+msgid "do not fork, run in the foreground"
+msgstr "älä haarauta, vaan suorita edustalla"
+
+#: logsrvd/logsrvd.c:1860
+msgid "percent chance connections will drop"
+msgstr "prosentin mahdollisuus yhteyksien katkeamiseen"
+
+#: logsrvd/logsrvd.c:1862 logsrvd/sendlog.c:148
+msgid "display version information and exit"
+msgstr "näytä versiotiedot ja poistu"
+
+#: logsrvd/logsrvd.c:1912 logsrvd/sendlog.c:1725
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "Protobuf-C:n versio 1.3 tai uudempi vaaditaan"
+
+#: logsrvd/logsrvd.c:1928
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "virheellinen satunnaispudotusarvo: %s"
+
+#: logsrvd/logsrvd.c:1931 logsrvd/sendlog.c:1779
+#: plugins/sudoers/cvtsudoers.c:246 plugins/sudoers/sudoreplay.c:301
+#: plugins/sudoers/visudo.c:177
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s versio %s\n"
+
+#: logsrvd/logsrvd_conf.c:417 plugins/sudoers/check.c:335
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:120
+#: plugins/sudoers/policy.c:1188 plugins/sudoers/sudoers.c:486
+#: plugins/sudoers/sudoers.c:1347 plugins/sudoers/testsudoers.c:215
+#: plugins/sudoers/testsudoers.c:382
+#, c-format
+msgid "unknown user %s"
+msgstr "tuntematon käyttäjä %s"
+
+#: logsrvd/logsrvd_conf.c:434 plugins/sudoers/iolog.c:145
+#: plugins/sudoers/sudoers.c:491 plugins/sudoers/sudoers.c:1381
+#: plugins/sudoers/testsudoers.c:406
+#, c-format
+msgid "unknown group %s"
+msgstr "tuntematon ryhmä %s"
+
+#: logsrvd/logsrvd_conf.c:452
+#, fuzzy, c-format
+#| msgid "unable to parse gids for %s"
+msgid "unable to parse iolog mode %s"
+msgstr "%s-käyttäjän ryhmä-id:iden jäsentäminen epäonnistui"
+
+#: logsrvd/logsrvd_conf.c:469 logsrvd/logsrvd_conf.c:1238
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "virheellinen %s-arvo: %s"
+
+#: logsrvd/logsrvd_conf.c:522
+msgid "TLS not supported"
+msgstr "TLS ei ole tuettu"
+
+#: logsrvd/logsrvd_conf.c:544
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:617 logsrvd/logsrvd_conf.c:1027
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s: ei ole täydellinen polku"
+
+#: logsrvd/logsrvd_conf.c:945 logsrvd/logsrvd_conf.c:961
+#: logsrvd/logsrvd_conf.c:1671
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "tuntematon syslog-lähde %s"
+
+#: logsrvd/logsrvd_conf.c:977 logsrvd/logsrvd_conf.c:993
+#: logsrvd/logsrvd_conf.c:1009 logsrvd/logsrvd_conf.c:1675
+#: logsrvd/logsrvd_conf.c:1679 logsrvd/logsrvd_conf.c:1683
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "tuntematon syslog-prioriteetti %s"
+
+# Ensimmäinen parametri on auth name
+#: logsrvd/logsrvd_conf.c:1192
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d täsmäämätön ”[”: %s"
+
+# Ensimmäinen parametri on auth name
+#: logsrvd/logsrvd_conf.c:1198
+#, fuzzy, c-format
+#| msgid "%s:%d unmatched '[': %s"
+msgid "%s:%d garbage after ']': %s"
+msgstr "%s:%d täsmäämätön ”[”: %s"
+
+#: logsrvd/logsrvd_conf.c:1210
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s:%d: virheellinen asetusosio: %s"
+
+#: logsrvd/logsrvd_conf.c:1218
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d virheellinen asetusrivi: %s"
+
+#: logsrvd/logsrvd_conf.c:1224
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d odotettiin osion nimeä: %s"
+
+#: logsrvd/logsrvd_conf.c:1246
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] virheellinen avain: %s"
+
+#: logsrvd/logsrvd_conf.c:1276 plugins/sudoers/cvtsudoers.c:268
+#: plugins/sudoers/logging.c:857
+#, c-format
+msgid "unable to open log file %s"
+msgstr "lokitiedoston %s avaaminen epäonnistui"
+
+#: logsrvd/logsrvd_conf.c:1757
+msgid "unable to initialize server TLS context"
+msgstr "TLS-kontekstia ei voi alustaa: %s"
+
+#: logsrvd/logsrvd_conf.c:1777
+msgid "unable to initialize relay TLS context"
+msgstr "välittimen TLS-kontekstia ei voi alustaa"
+
+#: logsrvd/logsrvd_journal.c:136 logsrvd/logsrvd_journal.c:416
+#: logsrvd/logsrvd_journal.c:421
+msgid "unable to create journal file"
+msgstr "kirjanpitotiedostoa ei voi luoda"
+
+# Avaamisen kohde voi olla timestamp file, sudoers file tai pathbuf
+#: logsrvd/logsrvd_journal.c:140 logsrvd/logsrvd_queue.c:104
+#: plugins/sudoers/visudo.c:1007
+#, c-format
+msgid "unable to lock %s"
+msgstr "kohteen %s lukitseminen epäonnistui"
+
+#: logsrvd/logsrvd_journal.c:143
+msgid "unable to lock journal file"
+msgstr "kirjanpitotiedostoa ei voi lukita"
+
+#: logsrvd/logsrvd_journal.c:151
+msgid "unable to open journal file"
+msgstr "kirjauskansiotiedostoa ei voi avata"
+
+#: logsrvd/logsrvd_journal.c:172 logsrvd/logsrvd_journal.c:452
+#: logsrvd/logsrvd_journal.c:457
+msgid "unable to write journal file"
+msgstr "kirjauskansiotiedostoa ei voi kirjoittaa"
+
+#: logsrvd/logsrvd_journal.c:180 logsrvd/logsrvd_journal.c:187
+msgid "unable to rename journal file"
+msgstr "kirjauskansiotiedostoa ei voi nimetä uudelleen"
+
+#: logsrvd/logsrvd_journal.c:234 logsrvd/logsrvd_journal.c:235
+#: logsrvd/logsrvd_journal.c:269 logsrvd/logsrvd_journal.c:270
+msgid "unexpected EOF reading journal file"
+msgstr "odottamaton tiedoston loppu luettaessa kirjanpitotiedostoa"
+
+#: logsrvd/logsrvd_journal.c:238 logsrvd/logsrvd_journal.c:239
+#: logsrvd/logsrvd_journal.c:273 logsrvd/logsrvd_journal.c:274
+msgid "error reading journal file"
+msgstr "virhe luettaessa kirjanpitotiedostoa"
+
+#: logsrvd/logsrvd_journal.c:285 logsrvd/logsrvd_journal.c:376
+msgid "invalid journal file, unable to restart"
+msgstr "virheellinen kirjanpitotiedosto, ei voida käynnistää uudelleen"
+
+#: logsrvd/logsrvd_journal.c:435
+#, fuzzy, c-format
+#| msgid "unable to find resume point [%lld, %ld] in %s/%s"
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "jatkopistettä [%lld, %ld] ei löydy tiedostosta %s/%s"
+
+#: logsrvd/logsrvd_local.c:153
+msgid "error parsing AcceptMessage"
+msgstr "virhe jäsennettäessä AcceptMessagea"
+
+#: logsrvd/logsrvd_local.c:164
+msgid "error creating I/O log"
+msgstr "virhe luotaessa siirräntälokia"
+
+#: logsrvd/logsrvd_local.c:187
+msgid "error logging accept event"
+msgstr "virhe hyväksymistapahtuman lokiin kirjaamisessa"
+
+#: logsrvd/logsrvd_local.c:226
+msgid "error parsing RejectMessage"
+msgstr "virhe jäsennettäessä RejectMessagea"
+
+#: logsrvd/logsrvd_local.c:250
+msgid "error logging reject event"
+msgstr "virhe hylkäystapahtuman lokiin kirjaamisessa"
+
+#: logsrvd/logsrvd_local.c:386 logsrvd/logsrvd_local.c:394
+msgid "error logging exit event"
+msgstr "virhe kirjattaessa poistumistapahtumaa"
+
+#: logsrvd/logsrvd_local.c:451 logsrvd/logsrvd_local.c:452
+msgid "log is already complete, cannot be restarted"
+msgstr "loki on jo valmis, ei voi aloittaa uudelleen"
+
+#: logsrvd/logsrvd_local.c:482
+msgid "unable to restart log"
+msgstr "lokia ei voi aloittaa uudelleen"
+
+#: logsrvd/logsrvd_local.c:498
+msgid "error parsing AlertMessage"
+msgstr "virhe jäsennettäessä AlertMessagea"
+
+#: logsrvd/logsrvd_local.c:508
+msgid "error logging alert event"
+msgstr "virhe hälytystapahtuman lokiin kirjaamisessa"
+
+#: logsrvd/logsrvd_local.c:544 logsrvd/logsrvd_local.c:607
+#: logsrvd/logsrvd_local.c:642
+#, fuzzy, c-format
+#| msgid "unable to format timestamp"
+msgid "unable to format timing buffer, length %d"
+msgstr "aikaleiman muotoileminen epäonnistui"
+
+#: logsrvd/logsrvd_local.c:558 logsrvd/logsrvd_local.c:566
+#: logsrvd/logsrvd_local.c:614 logsrvd/logsrvd_local.c:649
+#: plugins/sudoers/sudoreplay.c:351
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: logsrvd/logsrvd_local.c:577
+msgid "randomly dropping connection"
+msgstr "satunnaisesti katkeileva yhteys"
+
+#: logsrvd/logsrvd_local.c:589
+msgid "error writing IoBuffer"
+msgstr "virhe kirjoitettaessa IoBufferia"
+
+#: logsrvd/logsrvd_local.c:624
+msgid "error writing ChangeWindowSize"
+msgstr "virhe kirjoitettaessa ChangeWindowSizeä"
+
+#: logsrvd/logsrvd_local.c:659
+msgid "error writing CommandSuspend"
+msgstr "virhe kirjoitettaessa CommandSuspendia"
+
+#: logsrvd/logsrvd_relay.c:430
+msgid "TLS handshake with relay host failed"
+msgstr "TLS-kättely välitinkoneen kanssa epäonnistui"
+
+#: logsrvd/logsrvd_relay.c:458
+msgid "unable to connect to relay host"
+msgstr "yhteyden muodostaminen välitinkoneeseen ei onnistu"
+
+#: logsrvd/logsrvd_relay.c:513
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s: virheellinen ServerHello, puuttuva server_id"
+
+#: logsrvd/logsrvd_relay.c:515 logsrvd/sendlog.c:1121
+#: plugins/sudoers/log_client.c:1497
+msgid "invalid ServerHello"
+msgstr "virheellinen ServerHello"
+
+#: logsrvd/logsrvd_relay.c:674
+msgid "unrecognized ServerMessage type"
+msgstr "tunnistamaton ServerMessage-tyyppi"
+
+#: logsrvd/logsrvd_relay.c:703
+#, fuzzy, c-format
+#| msgid "timeout reading from relay"
+msgid "timed out reading from relay %s (%s)"
+msgstr "aikakatkaisu luettaessa välittimeltä"
+
+#: logsrvd/logsrvd_relay.c:705
+msgid "timeout reading from relay"
+msgstr "aikakatkaisu luettaessa välittimeltä"
+
+#: logsrvd/logsrvd_relay.c:757
+msgid "relay host name does not match certificate"
+msgstr "välitinkoneen nimi ei vastaa sertifikaattia"
+
+#: logsrvd/logsrvd_relay.c:763 logsrvd/logsrvd_relay.c:776
+#: logsrvd/logsrvd_relay.c:782
+msgid "error reading from relay"
+msgstr "virhe luettaessa välittimeltä"
+
+#: logsrvd/logsrvd_relay.c:803
+msgid "unable to read from relay"
+msgstr "ei voi lukea välittimeltä"
+
+#: logsrvd/logsrvd_relay.c:818 logsrvd/logsrvd_relay.c:936
+msgid "relay server closed connection"
+msgstr "välitinpalvelin sulki yhteyden"
+
+#: logsrvd/logsrvd_relay.c:836
+msgid "server message too large"
+msgstr "palvelinsanoma on liian suuri"
+
+#: logsrvd/logsrvd_relay.c:900
+#, fuzzy, c-format
+#| msgid "timeout writing to relay"
+msgid "timed out writing to relay %s (%s)"
+msgstr "aikakatkaisu kirjoitettaessa välittimelle"
+
+#: logsrvd/logsrvd_relay.c:902
+msgid "timeout writing to relay"
+msgstr "aikakatkaisu kirjoitettaessa välittimelle"
+
+#: logsrvd/logsrvd_relay.c:955 logsrvd/logsrvd_relay.c:961
+#: logsrvd/logsrvd_relay.c:971
+msgid "error writing to relay"
+msgstr "virhe kirjoitettaessa välittimelle"
+
+#: logsrvd/sendlog.c:114
+msgid "send sudo I/O log to remote server"
+msgstr "%s - lähetä sudon siirräntäloki etäpalvelimelle"
+
+#: logsrvd/sendlog.c:120
+msgid "only send an accept event (no I/O)"
+msgstr "lähetä vain hyväksyntätapahtuma (ei siirräntää)"
+
+#: logsrvd/sendlog.c:123
+msgid "certificate bundle file to verify server's cert against"
+msgstr "varmennepakettitiedosto, jolla palvelimen varmenne tarkistetaan"
+
+#: logsrvd/sendlog.c:125
+msgid "certificate file for TLS handshake"
+msgstr "TLS-kättelyn varmennetiedosto"
+
+#: logsrvd/sendlog.c:128
+msgid "host to send logs to"
+msgstr "kone, johon lokit lähetetään"
+
+#: logsrvd/sendlog.c:130
+msgid "remote ID of I/O log to be resumed"
+msgstr "jatkettavan I/O-lokin etätunnus"
+
+#: logsrvd/sendlog.c:133
+msgid "private key file"
+msgstr "salainen avain"
+
+#: logsrvd/sendlog.c:135
+msgid "do not verify server certificate"
+msgstr "älä tarkista palvelinvarmennetta"
+
+#: logsrvd/sendlog.c:138
+msgid "port to use when connecting to host"
+msgstr "koneeseen yhteyttä muodostettaessa käytettävä portti"
+
+#: logsrvd/sendlog.c:140
+msgid "restart previous I/O log transfer"
+msgstr "käynnistä aiempi siirräntälokin siirto uudelleen"
+
+#: logsrvd/sendlog.c:142
+msgid "reject the command with the given reason"
+msgstr "hylkää komento annetulla syyllä"
+
+#: logsrvd/sendlog.c:144
+msgid "stop transfer after reaching this time"
+msgstr "lopeta siirto tämän ajan saavuttamisen jälkeen"
+
+#: logsrvd/sendlog.c:146
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "testaa audit-palvelinta lähettämällä valittu siirräntäloki n kertaa rinnakkain"
+
+#: logsrvd/sendlog.c:171 plugins/sudoers/log_client.c:441
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "kohteen %s:%s nimenselvitys epäonnistui: %s"
+
+#: logsrvd/sendlog.c:209
+msgid "unable to get server IP addr"
+msgstr "palvelimen IP-osoitteen noutaminen ei onnistu"
+
+#: logsrvd/sendlog.c:295 plugins/sudoers/sudoreplay.c:871
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "tiedostosta %s/%s lukeminen epäonnistui: %s"
+
+#: logsrvd/sendlog.c:1045 plugins/sudoers/iolog.c:945
+#: plugins/sudoers/iolog.c:1020
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "odottamaton siirräntätapahtuma %d"
+
+#: logsrvd/sendlog.c:1098 logsrvd/sendlog.c:1115 logsrvd/sendlog.c:1149
+#: plugins/sudoers/log_client.c:1146 plugins/sudoers/log_client.c:1423
+#: plugins/sudoers/log_client.c:1491 plugins/sudoers/log_client.c:1530
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: odottamaton tila %d"
+
+#: logsrvd/sendlog.c:1185 plugins/sudoers/log_client.c:1576
+#, c-format
+msgid "error message received from server: %s"
+msgstr "virhesanoma vastaanotettu palvelimelta: %s"
+
+#: logsrvd/sendlog.c:1198 plugins/sudoers/log_client.c:1589
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "keskeytyssanoma vastaanotettu palvelimelta: %s"
+
+#: logsrvd/sendlog.c:1257 plugins/sudoers/log_client.c:1639
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s: odottamaton type_case-arvo %d"
+
+#: logsrvd/sendlog.c:1286
+msgid "timeout reading from server"
+msgstr "aikakatkaisu luettaessa palvelimelta"
+
+#: logsrvd/sendlog.c:1368
+msgid "premature EOF"
+msgstr "ennenaikainen tiedoston loppu"
+
+#: logsrvd/sendlog.c:1381 plugins/sudoers/log_client.c:1800
+#, c-format
+msgid "server message too large: %u"
+msgstr "palvelinsanoma on liian suuri: %u"
+
+#: logsrvd/sendlog.c:1437
+msgid "timeout writing to server"
+msgstr "aikakatkaisu kirjoitettaessa palvelimelle"
+
+#: logsrvd/sendlog.c:1802
+msgid "both restart point and iolog ID must be specified"
+msgstr "sekä aloituspiste että iolog-tunnus on annettava"
+
+#: logsrvd/sendlog.c:1806
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "uudelleenkäynnistyspistettä ei ehkä aseteta, kun I/O:ta ei lähetetä"
+
+#: logsrvd/sendlog.c:1882
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "poistui ennenaikaisesti tilalla %d"
+
+#: logsrvd/sendlog.c:1883
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "kulunut aika lähetetty palvelimelle [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1885
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "toimituspiste vastaanotettu palvelimelta [%lld, %ld]"
+
+#: logsrvd/tls_client.c:106 plugins/sudoers/log_client.c:304
+msgid "TLS handshake timeout occurred"
+msgstr "TLS-kättelyn aikakatkaisu tapahtui"
+
+#: logsrvd/tls_client.c:126 logsrvd/tls_client.c:142
+#: plugins/sudoers/log_client.c:326 plugins/sudoers/log_client.c:342
+msgid "unable to set event"
+msgstr "tapahtuman asettaminen ei onnistu"
+
+#: logsrvd/tls_client.c:152 logsrvd/tls_client.c:156
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "TLS-yhteys epäonnistui: %s"
+
+#: logsrvd/tls_client.c:190
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "ssl-objektia ei voi varata: %s"
+
+#: logsrvd/tls_client.c:203
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "Sokettia ei voi liittää SSL-objektiin: %s"
+
+#: logsrvd/tls_client.c:231
+msgid "unable to initialize TLS context"
+msgstr "TLS-kontekstia ei voi alustaa"
+
+#: logsrvd/tls_init.c:127 logsrvd/tls_init.c:135
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "ei voida asettaa TLS 1.2 -algoritmisarjaksi %s: %s"
+
+#: logsrvd/tls_init.c:155 logsrvd/tls_init.c:163
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "ei voida asettaa TLS 1.3 -algoritmisarjaksi %s: %s"
+
+#: logsrvd/tls_init.c:195 logsrvd/tls_init.c:216
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "diffie-hellman-parametreja ei voi asettaa: %s"
+
+#: logsrvd/tls_init.c:272
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "TLS-kontekstia ei voi luoda: %s"
+
+#: logsrvd/tls_init.c:278
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "protokollaversion vähimmäisversiota ei voi asettaa TLS 1.2:ksi: %s"
+
+#: plugins/sudoers/audit.c:267 plugins/sudoers/audit.c:419
+#: plugins/sudoers/log_client.c:979 plugins/sudoers/log_client.c:1028
+#: plugins/sudoers/log_client.c:1077 plugins/sudoers/log_client.c:1203
+#: plugins/sudoers/logging.c:552 plugins/sudoers/logging.c:649
+#: plugins/sudoers/logging.c:811 plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr "kellonajan noutaminen epäonnistui"
+
+#: plugins/sudoers/auth/aix_auth.c:280
+#, c-format
+msgid "unable to change password for %s"
+msgstr "%s-käyttäjän salasanan vaihtaminen epäonnistui"
+
+#: plugins/sudoers/auth/bsdauth.c:74
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "kirjautumisluokan saaminen käyttäjälle %s epäonnistui"
+
+#: plugins/sudoers/auth/bsdauth.c:79
+msgid "unable to begin bsd authentication"
+msgstr "bsd-todentamisen aloittaminen epäonnistui"
+
+#: plugins/sudoers/auth/bsdauth.c:87
+msgid "invalid authentication type"
+msgstr "virheellinen todennustyyppi"
+
+#: plugins/sudoers/auth/bsdauth.c:96
+msgid "unable to initialize BSD authentication"
+msgstr "BSD-todennuksen alustaminen epäonnistui"
+
+#: plugins/sudoers/auth/bsdauth.c:186
+msgid "your account has expired"
+msgstr "tilisi on vanhentunut"
+
+#: plugins/sudoers/auth/bsdauth.c:188
+msgid "approval failed"
+msgstr "hyväksyntä epäonnistui"
+
+#: plugins/sudoers/auth/fwtk.c:61
+msgid "unable to read fwtk config"
+msgstr "fwtk config -asetuksen lukeminen epäonnistui"
+
+#: plugins/sudoers/auth/fwtk.c:66
+msgid "unable to connect to authentication server"
+msgstr "todentamispalvelimelle yhdistäminen epäonnistui"
+
+#: plugins/sudoers/auth/fwtk.c:72 plugins/sudoers/auth/fwtk.c:97
+#: plugins/sudoers/auth/fwtk.c:129
+msgid "lost connection to authentication server"
+msgstr "kadotettiin yhteys todentamispalvelimelle"
+
+#: plugins/sudoers/auth/fwtk.c:76
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"todentamispalvelinvirhe:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:110
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: valtuutetun (’%s’) muuntaminen merkkijonoksi epäonnistui: %s"
+
+# Ensimmäinen parametri on auth name
+#: plugins/sudoers/auth/kerb5.c:162
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: todentamisnimen ’%s’ jäsentäminen epäonnistui: %s"
+
+#: plugins/sudoers/auth/kerb5.c:171
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: valtuustietovälimuistin nimenselvitys epäonnistui: %s"
+
+#: plugins/sudoers/auth/kerb5.c:220
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: muistin varaaminen valitsimille epäonnistui: %s"
+
+#: plugins/sudoers/auth/kerb5.c:235
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: valtuustietojen hakeminen epäonnistui: %s"
+
+#: plugins/sudoers/auth/kerb5.c:248
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: valtuustietovälimuistin alustaminen epäonnistui: %s"
+
+#: plugins/sudoers/auth/kerb5.c:251
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: valtuustietojen tallentaminen valtuustietovälimuistiin epäonnistui: %s"
+
+#: plugins/sudoers/auth/kerb5.c:315
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: tietokoneen valtuutetun hakeminen epäonnistui: %s"
+
+#: plugins/sudoers/auth/kerb5.c:329
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: TGT-lipun todentaminen epäonnistui! Mahdollinen hyökkäys!: %s"
+
+#: plugins/sudoers/auth/pam.c:224
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "PAMin alustaminen epäonnistui: %s"
+
+#: plugins/sudoers/auth/pam.c:337
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "PAM-todentamisvirhe: %s"
+
+#: plugins/sudoers/auth/pam.c:356
+msgid "account validation failure, is your account locked?"
+msgstr "tilinvahvistusvirhe, onko tilisi lukittu?"
+
+#: plugins/sudoers/auth/pam.c:367
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Tili tai salasana on vanhentunut, nollaa salasanasi tai yritä uudelleen"
+
+#: plugins/sudoers/auth/pam.c:373
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "vanhentuneen salasanan vaihtaminen epäonnistui: %s"
+
+#: plugins/sudoers/auth/pam.c:384
+msgid "Password expired, contact your system administrator"
+msgstr "Salasana vanhentunut, ota yhteyttä järjestelmän ylläpitäjään"
+
+#: plugins/sudoers/auth/pam.c:389
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Tili vanhentunut tai PAM-asetuksista puuttuu ”account”-lohko sudo-komennolle, ota yhteyttä järjestelmän ylläpitäjään"
+
+#: plugins/sudoers/auth/pam.c:397 plugins/sudoers/auth/pam.c:402
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "PAM-tilin hallintavirhe: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:99 plugins/sudoers/visudo.c:255
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "ei ole olemassa %s-tietokannassa"
+
+#: plugins/sudoers/auth/securid5.c:75
+msgid "failed to initialise the ACE API library"
+msgstr "ACE API -kirjaston alustaminen epäonnistui"
+
+#: plugins/sudoers/auth/securid5.c:106
+msgid "unable to contact the SecurID server"
+msgstr "yhteyden ottaminen SecurID-palvelimeen epäonnistui"
+
+#: plugins/sudoers/auth/securid5.c:115
+msgid "User ID locked for SecurID Authentication"
+msgstr "Käyttäjätunniste lukittu SecurID-todennukselle"
+
+#: plugins/sudoers/auth/securid5.c:119 plugins/sudoers/auth/securid5.c:170
+msgid "invalid username length for SecurID"
+msgstr "virheellinen SecurID-käyttäjänimen pituus"
+
+#: plugins/sudoers/auth/securid5.c:123 plugins/sudoers/auth/securid5.c:175
+msgid "invalid Authentication Handle for SecurID"
+msgstr "virheellinen SecurID-todennuskahva"
+
+#: plugins/sudoers/auth/securid5.c:127
+msgid "SecurID communication failed"
+msgstr "SecurID-viestintä epäonnistui"
+
+#: plugins/sudoers/auth/securid5.c:131 plugins/sudoers/auth/securid5.c:218
+msgid "unknown SecurID error"
+msgstr "tuntematon SecurID-virhe"
+
+#: plugins/sudoers/auth/securid5.c:165
+msgid "invalid passcode length for SecurID"
+msgstr "virheellinen SecurID-salasanan pituus"
+
+#: plugins/sudoers/auth/sia.c:69 plugins/sudoers/auth/sia.c:126
+msgid "unable to initialize SIA session"
+msgstr "SIA-istunnon alustaminen epäonnistui"
+
+#: plugins/sudoers/auth/sudo_auth.c:134
+msgid "invalid authentication methods"
+msgstr "virheelliset todennusmetodit"
+
+#: plugins/sudoers/auth/sudo_auth.c:136
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Virheellisiä todennusmenetelmiä käännetty sudo-ohjelmaan! Yksittäisiä ja ei-yksittäisiä todennuksia ei voi sekoittaa keskenään."
+
+#: plugins/sudoers/auth/sudo_auth.c:257 plugins/sudoers/auth/sudo_auth.c:309
+msgid "no authentication methods"
+msgstr "ei todennusmenetelmiä"
+
+#: plugins/sudoers/auth/sudo_auth.c:259
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Sudo-ohjelmaan ei ole käännetty todentamismenelmiä! Jos haluat kääntää pois todentamisen, käytä asetusvalitsinta --disable-authentication."
+
+#: plugins/sudoers/auth/sudo_auth.c:311
+msgid "Unable to initialize authentication methods."
+msgstr "Todentamismenetelmien alustaminen epäonnistui."
+
+#: plugins/sudoers/auth/sudo_auth.c:482
+msgid "Authentication methods:"
+msgstr "Todennusmenetelmät:"
+
+#: plugins/sudoers/bsm_audit.c:123 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "Audit-ehdon määrittely epäonnistui"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:277
+msgid "unable to commit audit record"
+msgstr "commit-toiminnon suorittaminen audit-tietueelle epäonnistui"
+
+#: plugins/sudoers/check.c:263
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "virhe luettaessa saarnatiedostoa: %s"
+
+#: plugins/sudoers/check.c:269
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "ohitetaan saarnatiedosto %s: ei ole tavallinen tiedosto"
+
+#: plugins/sudoers/check.c:282
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Luotamme, että olet saanut tavanomaisen saarnan paikalliselta järjestelmän\n"
+"ylläpitäjältä. Yleensä se tiivistyy kolmeen asiaan:\n"
+"\n"
+" #1) Kunnioita muiden yksityisyyttä.\n"
+" #2) Ajattele ennen kuin kirjoitat.\n"
+" #3) Suuren voiman mukana tulee suuri vastuu.\n"
+"\n"
+
+#: plugins/sudoers/check.c:330 plugins/sudoers/check.c:340
+#: plugins/sudoers/sudoers.c:885 plugins/sudoers/sudoers.c:906
+#: plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "tuntematon uid-käyttäjätunniste %u"
+
+#: plugins/sudoers/check_aliases.c:92
+#, c-format
+msgid "Error: %s:%d:%d: cycle in %s \"%s\""
+msgstr "Virhe: %s:%d:%d: %s ”%s” on kiertävä"
+
+#: plugins/sudoers/check_aliases.c:93
+#, c-format
+msgid "Warning: %s:%d:%d: cycle in %s \"%s\""
+msgstr "Varoitus: %s:%d:%d: %s ”%s” on kiertävä"
+
+# Toiseksi viimeinen %s on esim. ""Host_Alias" ja viimeinen sen nimi.
+#: plugins/sudoers/check_aliases.c:97
+#, c-format
+msgid "Error: %s:%d:%d: %s \"%s\" referenced but not defined"
+msgstr "Virhe: %s:%d:%d määrittelemätön %s ”%s” viitattuna"
+
+# Toiseksi viimeinen %s on esim. ""Host_Alias" ja viimeinen sen nimi.
+#: plugins/sudoers/check_aliases.c:98
+#, c-format
+msgid "Warning: %s:%d:%d: %s \"%s\" referenced but not defined"
+msgstr "Varoitus: %s:%d:%d määrittelemätön %s ”%s” viitattuna mutta määrittelemättä"
+
+#: plugins/sudoers/cvtsudoers.c:209
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "järjestyksen kasvatus: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:228
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "aloitusjärjestys: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:238
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "järjestyksen tasaus: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:248 plugins/sudoers/visudo.c:179
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s kielioppiversio %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:277 plugins/sudoers/testsudoers.c:159
+#, c-format
+msgid "unsupported input format %s"
+msgstr "syötemuotoa %s ei tueta"
+
+#: plugins/sudoers/cvtsudoers.c:295
+#, c-format
+msgid "unsupported output format %s"
+msgstr "tuotosmuotoa %s ei tueta"
+
+#: plugins/sudoers/cvtsudoers.c:385
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: syöte- ja tulostetiedostojen on oltava erilaiset"
+
+#: plugins/sudoers/cvtsudoers.c:399 plugins/sudoers/sudoers.c:159
+#: plugins/sudoers/sudoers.c:205 plugins/sudoers/testsudoers.c:254
+#: plugins/sudoers/visudo.c:261 plugins/sudoers/visudo.c:620
+#: plugins/sudoers/visudo.c:953
+msgid "unable to initialize sudoers default values"
+msgstr "sudoers-oletusarvojen alustaminen epäonnistui"
+
+#: plugins/sudoers/cvtsudoers.c:525 plugins/sudoers/ldap_conf.c:433
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:584
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s: tuntematon avainsana %s"
+
+#: plugins/sudoers/cvtsudoers.c:630
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "virheellisten oletusarvojen tyyppi: %s"
+
+#: plugins/sudoers/cvtsudoers.c:653
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "virheellinen vaiennustyyppi: %s"
+
+#: plugins/sudoers/cvtsudoers.c:694 plugins/sudoers/cvtsudoers.c:710
+#, c-format
+msgid "invalid filter: %s"
+msgstr "virheellinen suodatin: %s"
+
+#: plugins/sudoers/cvtsudoers.c:754 plugins/sudoers/visudo.c:958
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "tiedoston %s jäsentäminen epäonnistui, tuntematon virhe"
+
+#: plugins/sudoers/cvtsudoers.c:762
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr "jäsentämisvirhe tiedostossa %s lähellä riviä %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:765
+#, c-format
+msgid "parse error in %s\n"
+msgstr "jäsentämisvirhe tiedostossa %s\n"
+
+# Kirjoittamisen kohde voi olla timestamp file tai pathbuf
+#: plugins/sudoers/cvtsudoers.c:1489 plugins/sudoers/sudoreplay.c:1145
+#: plugins/sudoers/timestamp.c:317 plugins/sudoers/timestamp.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "kohteeseen %s kirjoittaminen epäonnistui"
+
+#: plugins/sudoers/cvtsudoers.c:1512
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr "%s - muunna sudoers-tiedostomuotojen välillä\n"
+
+#: plugins/sudoers/cvtsudoers.c:1514
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Options:\n"
+" -b, --base=dn LDAP-kyselyiden DN-perusnimi\n"
+" -c, --config=asetustied asetustiedoston polku\n"
+" -d, --defaults=deftyypit muunna vain annettujen tyyppien Defaults-arvot\n"
+" -e, --expand-aliases lavenna aliakset muuntaessa\n"
+" -f, --output-format=muoto aseta tulostemuoto: JSON, LDIF tai sudoers\n"
+" -i, --input-format=muoto aseta syötemuoto: LDIF tai sudoers\n"
+" -I, --increment=määrä kutakin sudoOrderia kasvattava määrä\n"
+" -h, --help näytä ohjeviesti ja poistu\n"
+" -m, --match=suodatin muunna vain suodattimeen täsmäävät kohdat\n"
+" -M, --match-local täsmäyssuodatin käyttää passwd and group -tietokantoja\n"
+" -o, --output=tulostied kirjoita muunnetut sudoers-tiedot tulostiedostoon\n"
+" -O, --order-start=luku ensimmäisen sudoOrderin aloituspiste\n"
+" -p, --prune-matches karsi täsmäämättömät käyttäjät, ryhmät ja koneet\n"
+" -P, --padding=luku sudoOrder-kasvatuksen perustasaus\n"
+" -s, --suppress=osiot vaienna tiettyjen osioiden tuloste\n"
+" -V, --version näytä versiotiedot ja poistu"
+
+#: plugins/sudoers/cvtsudoers_csv.c:452 plugins/sudoers/cvtsudoers_csv.c:466
+#: plugins/sudoers/cvtsudoers_json.c:654 plugins/sudoers/cvtsudoers_json.c:669
+#: plugins/sudoers/cvtsudoers_ldif.c:347 plugins/sudoers/cvtsudoers_ldif.c:360
+#: plugins/sudoers/ldap.c:515
+msgid "unable to get GMT time"
+msgstr "GMT-ajan noutaminen epäonnistui"
+
+#: plugins/sudoers/cvtsudoers_csv.c:457 plugins/sudoers/cvtsudoers_csv.c:471
+#: plugins/sudoers/cvtsudoers_json.c:659 plugins/sudoers/cvtsudoers_json.c:674
+#: plugins/sudoers/cvtsudoers_ldif.c:352 plugins/sudoers/cvtsudoers_ldif.c:365
+#: plugins/sudoers/ldap.c:523
+msgid "unable to format timestamp"
+msgstr "aikaleiman muotoileminen epäonnistui"
+
+#: plugins/sudoers/cvtsudoers_json.c:480 plugins/sudoers/cvtsudoers_json.c:515
+#: plugins/sudoers/cvtsudoers_json.c:725 plugins/sudoers/defaults.c:190
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: tuntematon oletusrivi ”%s”"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:649
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "liian monta sudoers-merkintää, enimmäismäärä %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:692
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "SUDOERS_BASE-ympäristömuuttujaa ei ole määritelty eikä -b-valitsinta annettu."
+
+# parametrinä on variable
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, fuzzy, c-format
+#| msgid "%s:%d:%d: no value specified for \"%s\""
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr "%s:%d:%d: arvoa ei ole määritelty muuttujalle ”%s”"
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr "aliasta %s ei löydy"
+
+# parametrinä on variable
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, fuzzy, c-format
+#| msgid "%s:%d:%d: no value specified for \"%s\""
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr "%s:%d:%d: arvoa ei ole määritelty muuttujalle ”%s”"
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr "%s:%d:%d: poistetaan kahdenkertainen alias %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, fuzzy, c-format
+#| msgid "%s:%d:%d: invalid Defaults type 0x%x for option \"%s\""
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr "%s:%d:%d: virheellinen Defaults-tyyppi 0x%x valitsimelle ”%s”"
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr ""
+
+# parametrinä on variable
+#: plugins/sudoers/cvtsudoers_merge.c:1080
+#, fuzzy, c-format
+#| msgid "%s:%d:%d: no value specified for \"%s\""
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr "%s:%d:%d: arvoa ei ole määritelty muuttujalle ”%s”"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1174
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:50
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Syslog-apuneuvo, jos syslog-lokia käytetään kirjautumista varten: %s"
+
+#: plugins/sudoers/def_data.c:54
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Käytettävä syslog-prioriteetti, kun käyttäjä todennetaan onnistuneesti: %s"
+
+#: plugins/sudoers/def_data.c:58
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Käytettävä syslog-prioriteetti, kun käyttäjän todennus epäonnistui: %s"
+
+#: plugins/sudoers/def_data.c:62
+msgid "Put OTP prompt on its own line"
+msgstr "Laita OPT-kehote omalle rivilleen"
+
+#: plugins/sudoers/def_data.c:66
+msgid "Ignore '.' in $PATH"
+msgstr "Ohita ’.’ $PATHissa"
+
+#: plugins/sudoers/def_data.c:70
+msgid "Always send mail when sudo is run"
+msgstr "Lähetä aina sähköpostia, kun sudo suoritetaan"
+
+#: plugins/sudoers/def_data.c:74
+msgid "Send mail if user authentication fails"
+msgstr "Lähetä sähköpostia, jos käyttäjän todennus epäonnistuu"
+
+#: plugins/sudoers/def_data.c:78
+msgid "Send mail if the user is not in sudoers"
+msgstr "Lähetä sähköpostia, jos käyttäjä ei ole sudoers-määrittelyssä"
+
+#: plugins/sudoers/def_data.c:82
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Lähetä sähköpostia, jos käyttäjä ei ole tällä tietokoneella sudoers-määrittelyssä"
+
+#: plugins/sudoers/def_data.c:86
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Lähetä sähköpostia, jos käyttäjän ei sallita suorittaa komentoa"
+
+#: plugins/sudoers/def_data.c:90
+msgid "Send mail if the user tries to run a command"
+msgstr "Lähetä sähköpostia, jos käyttäjä yrittää suorittaa komennon"
+
+#: plugins/sudoers/def_data.c:94
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Käytä erillistä aikaleimaa jokaiselle käyttäjä/tty -yhdistelmälle"
+
+#: plugins/sudoers/def_data.c:98
+msgid "Lecture user the first time they run sudo"
+msgstr "Saarnaa sudoa ensimmäistä kertaa käyttävälle"
+
+#: plugins/sudoers/def_data.c:102
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Sudo-saarnan sisältävä tiedosto: %s"
+
+#: plugins/sudoers/def_data.c:106
+msgid "Require users to authenticate by default"
+msgstr "Vaadi käyttäjien todennus oletuksena"
+
+#: plugins/sudoers/def_data.c:110
+msgid "Root may run sudo"
+msgstr "Root voi suorittaa sudo-ohjelman"
+
+#: plugins/sudoers/def_data.c:114
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Kirjaa tietokonenimi (ei-syslog)lokitiedostoon"
+
+#: plugins/sudoers/def_data.c:118
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Kirjaa vuosi (ei-syslog)lokitiedostoon"
+
+#: plugins/sudoers/def_data.c:122
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Jos sudo-ohjelmaa kutsutaan ilman argumentteja, käynnistä käyttöjärjestelmäkuori"
+
+#: plugins/sudoers/def_data.c:126
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Aseta $HOME-muuttujaksi kohdekäyttäjä kun käyttöjärjestelmäkuori käynnistetään valitsimella -s"
+
+#: plugins/sudoers/def_data.c:130
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Aseta $HOME-muuttujaksi aina kohdekäyttäjän kotihakemisto"
+
+#: plugins/sudoers/def_data.c:134
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Salli jotain tietojenkeräystä hyödyllisten virheilmoitusten tarjoamiseksi"
+
+#: plugins/sudoers/def_data.c:138
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Vaadi täysin rakennettu tietokonenimi suoders-tiedostossa"
+
+#: plugins/sudoers/def_data.c:142
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Solvaa käyttäjiä, kun he kirjoittavat väärän salasanan"
+
+#: plugins/sudoers/def_data.c:146
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Salli käyttäjien suorittaa sudo-ohjelma vain jos heillä on tty"
+
+#: plugins/sudoers/def_data.c:150
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo noudattaa EDITOR-ympäristömuuttujaa"
+
+#: plugins/sudoers/def_data.c:154
+msgid "Prompt for root's password, not the users's"
+msgstr "Kysy root-käyttäjän salasana, ei käyttäjän"
+
+#: plugins/sudoers/def_data.c:158
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Kysy runas_default-käyttäjän salasana, ei käyttäjän"
+
+#: plugins/sudoers/def_data.c:162
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Kysy kohdekäyttäjän salasana, ei käyttäjän"
+
+#: plugins/sudoers/def_data.c:166
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Käytä oletuksia kohdekäyttäjän kirjautumisluokassa, jos siinä on yhtään"
+
+#: plugins/sudoers/def_data.c:170
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Aseta LOGNAME- ja USER-ympäristömuuttujat"
+
+#: plugins/sudoers/def_data.c:174
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Aseta vain voimassa oleva uid-käyttäjätunniste kohdekäyttäjälle, ei oikeaa uid-tunnistetta"
+
+#: plugins/sudoers/def_data.c:178
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Älä alusta ryhmävektoria kohdekäyttäjän vastaavaan arvoon"
+
+#: plugins/sudoers/def_data.c:182
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Pituus, jossa pitkät lokitiedostorivit jaetaan seuraavalle riville (0 ei jaeta): %u"
+
+#: plugins/sudoers/def_data.c:186
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Todennusaikaleiman aikakatkaisu: %.1f minuuttia"
+
+#: plugins/sudoers/def_data.c:190
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Salasanakehotteen aikakatkaisu: %.1f minuuttia"
+
+#: plugins/sudoers/def_data.c:194
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Salasanayritysten lukumäärä: %u"
+
+#: plugins/sudoers/def_data.c:198
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Käytettävä umask-määrittely tai 0777 käytettäväksi käyttäjän umask-määrittelyksi: 0%o"
+
+#: plugins/sudoers/def_data.c:202
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Polku lokitiedostoon: %s"
+
+#: plugins/sudoers/def_data.c:206
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Sähköpostiohjelman polku: %s"
+
+#: plugins/sudoers/def_data.c:210
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Sähköpostiohjelman liput: %s"
+
+#: plugins/sudoers/def_data.c:214
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Sähköpostin vastaanottajan osoite: %s"
+
+#: plugins/sudoers/def_data.c:218
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Sähköpostin lähettäjän osoite: %s"
+
+#: plugins/sudoers/def_data.c:222
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Sähköpostiviestien aihe-rivi: %s"
+
+#: plugins/sudoers/def_data.c:226
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Virheellinen salasanaviesti: %s"
+
+#: plugins/sudoers/def_data.c:230
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Polku saarnatilan hakemistoon: %s"
+
+#: plugins/sudoers/def_data.c:234
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Polku todennusaikaleimahakemistoon: %s"
+
+#: plugins/sudoers/def_data.c:238
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Todennusaikaleimahakemiston omistaja: %s"
+
+#: plugins/sudoers/def_data.c:242
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Käyttäjät tässä ryhmässä on vapautettu salasana- ja PATH-vaatimuksista: %s"
+
+#: plugins/sudoers/def_data.c:246
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Oletussalasanakehote: %s"
+
+#: plugins/sudoers/def_data.c:250
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Jos asetettu, salasanakehote korvaa järjestelmäkehotteen kaikissa tapauksissa."
+
+# Tämä on tekemisessä runas_default -määrittelyn kanssa
+#: plugins/sudoers/def_data.c:254
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Oletuskäyttäjä suorittaa komennot käyttäjänä: %s"
+
+#: plugins/sudoers/def_data.c:258
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Arvo, jolla korvataan käyttäjän $PATH-asetus: %s"
+
+#: plugins/sudoers/def_data.c:262
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Visudo-editorin käyttämä polku: %s"
+
+#: plugins/sudoers/def_data.c:266
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Kun vaaditaan salasana ’list’-näennäiskomennolle: %s"
+
+#: plugins/sudoers/def_data.c:270
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Kun vaaditaan salasana ’verify’-näennäiskomennolle: %s"
+
+#: plugins/sudoers/def_data.c:274
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "Esilataa sudo_noexec-kirjasto, joka korvaa exec-funtiot"
+
+#: plugins/sudoers/def_data.c:278
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Jos LDAP-hakemisto on ylhäällä, ohitammeko paikallisen sudoers-tiedoston"
+
+#: plugins/sudoers/def_data.c:282
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Tiedostokuvaajat >= %d suljetaan ennen komennon suoritusta"
+
+#: plugins/sudoers/def_data.c:286
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "Jos asetettu, käyttäjä voi korvata ”closefrom”-arvon valitsimella -C"
+
+#: plugins/sudoers/def_data.c:290
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Salli käyttäjien asettaa mielivaltaisia ympäristömuuttujia"
+
+#: plugins/sudoers/def_data.c:294
+msgid "Reset the environment to a default set of variables"
+msgstr "Nollaa ympäristö muuttujien oletusjoukoksi"
+
+#: plugins/sudoers/def_data.c:298
+msgid "Environment variables to check for safety:"
+msgstr "Turvallisuustarkastettavat ympäristömuuttujat:"
+
+#: plugins/sudoers/def_data.c:302
+msgid "Environment variables to remove:"
+msgstr "Poistettavat ympäristömuuttujat:"
+
+#: plugins/sudoers/def_data.c:306
+msgid "Environment variables to preserve:"
+msgstr "Säilytettävät ympäristömuuttujat:"
+
+#: plugins/sudoers/def_data.c:310
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "Uudessa turva-asiayhteydessä käytettävä SELinux-rooli: %s"
+
+#: plugins/sudoers/def_data.c:314
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "Uudessa turva-asiayhteydessä käytettävä SELinux-tyyppi: %s"
+
+#: plugins/sudoers/def_data.c:318
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Polku sudo-kohtaiseen ympäristötiedostoon: %s"
+
+#: plugins/sudoers/def_data.c:322
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Polku rajoitettuun sudo-kohtaiseen ympäristötiedostoon: %s"
+
+#: plugins/sudoers/def_data.c:326
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Locale-asetus, jota käytetään sudoers-jäsentämisessä: %s"
+
+#: plugins/sudoers/def_data.c:330
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Salli sudo-ohjelman kysyä salasana vieläpä jos se olisi näkyvä"
+
+#: plugins/sudoers/def_data.c:334
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Tarjoa visuaalista palautetta salasanakehotteelta silloin kun on käyttäjäsyöte"
+
+#: plugins/sudoers/def_data.c:338
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Käyttää nopeampaa jokerimerkkien korvausta, joka on epätarkempi, mutta ei lue tiedostojärjestelmää"
+
+#: plugins/sudoers/def_data.c:342
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "Sudoers umask korvaa käyttäjän umask-määrittelyn, vieläpä jos se on sallivampi"
+
+#: plugins/sudoers/def_data.c:346
+msgid "Log user's input for the command being run"
+msgstr "Kirjaa lokiin käyttäjän syöte suoritettavalle komennolle"
+
+#: plugins/sudoers/def_data.c:350
+msgid "Log the output of the command being run"
+msgstr "Kirjaa lokiin suoritettavan komennon tuloste"
+
+#: plugins/sudoers/def_data.c:354
+msgid "Compress I/O logs using zlib"
+msgstr "Tiivistä siirräntälokit käyttäen zlib-ohjelmaa"
+
+#: plugins/sudoers/def_data.c:358
+msgid "Always run commands in a pseudo-tty"
+msgstr "Suorita aina komennot näennäis-tty:ssä"
+
+#: plugins/sudoers/def_data.c:362
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Lisäosa ei-Unix-ryhmätuelle: %s"
+
+#: plugins/sudoers/def_data.c:366
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Hakemisto, johon tallennetaan syöte-/tulostelokit: %s"
+
+#: plugins/sudoers/def_data.c:370
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Tiedosto, johon tallennetaan syöte-/tulosteloki: %s"
+
+#: plugins/sudoers/def_data.c:374
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Lisää rivi utmp-/utmpx-tiedostoon, kun varataan pty"
+
+#: plugins/sudoers/def_data.c:378
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Aseta käyttäjäksi utmp-tiedostoon suorittava käyttäjä, ei kutsuva käyttäjä"
+
+#: plugins/sudoers/def_data.c:382
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Sallittujen käyttöoikeuksien joukko: %s"
+
+#: plugins/sudoers/def_data.c:386
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Rajoitettujen käyttöoikeuksien joukko: %s"
+
+#: plugins/sudoers/def_data.c:390
+msgid "Run commands on a pty in the background"
+msgstr "Suorita komentoja pty:llä taustalla"
+
+#: plugins/sudoers/def_data.c:394
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "Käytettävä PAM-palvelunimi: %s"
+
+#: plugins/sudoers/def_data.c:398
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "Kirjautumiskomentotulkeille käytettävä PAM-palvelunimi: %s"
+
+#: plugins/sudoers/def_data.c:402
+#, c-format
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr "PAM-palvelun nimi, jota käytetään suoritettaessa sudo -A-valitsimella: %s"
+
+#: plugins/sudoers/def_data.c:406
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Yritys perustaa PAM-valtuustiedot kohdekäyttäjälle"
+
+#: plugins/sudoers/def_data.c:410
+msgid "Create a new PAM session for the command to run in"
+msgstr "Luo uusi PAM-istunto suoritettavalle komennolle"
+
+#: plugins/sudoers/def_data.c:414
+msgid "Perform PAM account validation management"
+msgstr "Suorita PAM-tilinvahvistuksen hallintaa"
+
+#: plugins/sudoers/def_data.c:418
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "Suurin siirräntälokin sarjanumero: %s"
+
+#: plugins/sudoers/def_data.c:422
+msgid "Enable sudoers netgroup support"
+msgstr "Ota käyttöön sudoers-verkkoryhmätuki"
+
+#: plugins/sudoers/def_data.c:426
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Tarkista yläpuolella olevan hakemistojen kirjoituskelpoisuus kun tiedostoja muokataan sudoedit-ohjelmalla"
+
+#: plugins/sudoers/def_data.c:430
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Seuraa symbolisia linkejä kun tiedostoja muokataan sudoedit-ohjelmalla"
+
+#: plugins/sudoers/def_data.c:434
+msgid "Query the group plugin for unknown system groups"
+msgstr "Kysy ryhmälisäosaa tuntemattomille järjestelmäryhmille"
+
+#: plugins/sudoers/def_data.c:438
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Täsmäävät verkkoryhmät perustuen koko monikolle: käyttäjä, tietokone ja verkkotunnus"
+
+#: plugins/sudoers/def_data.c:442
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Salli komentojen suorittaminen silloinkin kun sudo ei kykene kirjoittamaan valvontatarkastuslokiin"
+
+#: plugins/sudoers/def_data.c:446
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Salli komentojen suorittaminen silloinkin kun sudo ei kykene kirjoittamaan siirtolokiin"
+
+#: plugins/sudoers/def_data.c:450
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Salli komentojen suorittaminen silloinkin kun sudo ei kykene kirjoittamaan lokitiedostoon"
+
+#: plugins/sudoers/def_data.c:454
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Ratkaise sudoers-ryhmät ja täsmäytä ryhmätunnisteeseen, ei nimeen"
+
+#: plugins/sudoers/def_data.c:458
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Lokirivit, jotka ovat pitempiä kuin tämä arvo, jaetaan useisiin syslog-viesteihin: %u"
+
+#: plugins/sudoers/def_data.c:462
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Käyttäjä, joka omistaa siirräntälokitiedostot: %s"
+
+#: plugins/sudoers/def_data.c:466
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Ryhmä, joka omistaa siirräntälokitiedostot: %s"
+
+#: plugins/sudoers/def_data.c:470
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Tiedostotila käytettäväksi siirräntälokitiedostoissa: 0%o"
+
+#: plugins/sudoers/def_data.c:474
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Suorita komentoja tiedostokuvaan avulla eikä polun avulla: %s"
+
+#: plugins/sudoers/def_data.c:478
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Ohita tuntemattomat Defaults-rivit sudoers-tiedostossa sen sijaan että tuottaisit varoituksia"
+
+#: plugins/sudoers/def_data.c:482
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Sekuntimäärä, jossa komento päätetään: %u"
+
+#: plugins/sudoers/def_data.c:486
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Salli käyttäjän määritellä aikakatkaisu komentorivillä"
+
+#: plugins/sudoers/def_data.c:490
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Huuhtele siirräntälokitiedot levylle välittömästi sen sijaan että puskuroisit ne"
+
+#: plugins/sudoers/def_data.c:494
+msgid "Include the process ID when logging via syslog"
+msgstr "Sisällytä prosessitunniste, kun kirjataan syslog-tiedostoon"
+
+#: plugins/sudoers/def_data.c:498
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Todennusaikaleimatietueen tyyppi: %s"
+
+#: plugins/sudoers/def_data.c:502
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Todentamisen virheviesti: %s"
+
+#: plugins/sudoers/def_data.c:506
+msgid "Ignore case when matching user names"
+msgstr "Älä huomioi kirjainkokoa käyttäjänimien täsmäyksessä"
+
+#: plugins/sudoers/def_data.c:510
+msgid "Ignore case when matching group names"
+msgstr "Älä huomioi kirjainkokoa ryhmänimien täsmäyksessä"
+
+#: plugins/sudoers/def_data.c:514
+msgid "Log when a command is allowed by sudoers"
+msgstr "Kirjaa lokiin, kun sudoers sallii komennon"
+
+#: plugins/sudoers/def_data.c:518
+msgid "Log when a command is denied by sudoers"
+msgstr "Kirjaa lokiin, kun sudoers kieltää komennon"
+
+#: plugins/sudoers/def_data.c:522
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "Sudo-lokipalvelimet, joihin yhdistetään valinnaiseen porttiin"
+
+#: plugins/sudoers/def_data.c:526
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Sudo-lokipalvelimen aikakatkaisu sekunteina: %u"
+
+#: plugins/sudoers/def_data.c:530
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "Ota SO_KEEPALIVE-valinta käyttöön lokipalvelimeen yhdistetylle soketille"
+
+#: plugins/sudoers/def_data.c:534
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "Valvontapalvelimen CA-pakettitiedoston polku: %s"
+
+#: plugins/sudoers/def_data.c:538
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "Sudoers-varmennetiedoston polku: %s"
+
+#: plugins/sudoers/def_data.c:542
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "Sudoersin yksityisen avaintiedoston polku: %s"
+
+#: plugins/sudoers/def_data.c:546
+msgid "Verify that the log server's certificate is valid"
+msgstr "Varmista, että lokipalvelimen varmenne on kelvollinen"
+
+#: plugins/sudoers/def_data.c:550
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "Salli tuntemattoman runas-käyttäjän ja/tai ryhmä-id:n käyttö"
+
+#: plugins/sudoers/def_data.c:554
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "Salli komentojen suorittaminen vain käyttäjänä, jolla on kelvollinen kuori"
+
+#: plugins/sudoers/def_data.c:558
+msgid "Set the pam remote user to the user running sudo"
+msgstr "Aseta pam-etäkäyttäjä sudoa käyttäväksi käyttäjäksi"
+
+#: plugins/sudoers/def_data.c:562
+msgid "Set the pam remote host to the local host name"
+msgstr "Aseta pam-etäkone paikalliseksi konenimeksi"
+
+#: plugins/sudoers/def_data.c:566
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "Työhakemisto, johon vaihdetaan ennen komennon suorittamista: %s"
+
+#: plugins/sudoers/def_data.c:570
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "Juurihakemisto, johon vaihdetaan ennen komennon suorittamista: %s"
+
+#: plugins/sudoers/def_data.c:574
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "Lokien muoto: %s"
+
+#: plugins/sudoers/def_data.c:578
+msgid "Enable SELinux RBAC support"
+msgstr "Ota SELinux RBAC -tuki käyttöön"
+
+#: plugins/sudoers/def_data.c:582
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "Polku tiedostoon, joka luodaan sudon ensimmäisellä suorituskerralla: %s"
+
+#: plugins/sudoers/def_data.c:586
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "Sieppaa tulevat komennot ja sovella niihin sudoers-rajoituksia"
+
+#: plugins/sudoers/def_data.c:590
+msgid "Log sub-commands run by the original command"
+msgstr "Kirjaa alkuperäisen komennon suorittamat alikomennot lokiin"
+
+#: plugins/sudoers/def_data.c:594
+msgid "Log the exit status of commands"
+msgstr "Kirjaa lokiin komentojen poistumiskoodit"
+
+#: plugins/sudoers/def_data.c:598
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr "Siepatun istunnon seuraavat komennot on todennettava"
+
+#: plugins/sudoers/def_data.c:602
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr "Salli siepatun komennon suorittaa setuid- ja setgid-ohjelmia"
+
+#: plugins/sudoers/def_data.c:606
+#, c-format
+msgid "The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr "Prosessin osoiteavaruuden enimmäiskoko (tavuina): %s"
+
+#: plugins/sudoers/def_data.c:610
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr "Luotavan ydinvedostiedoston enimmäiskoko (tavuina): %s"
+
+#: plugins/sudoers/def_data.c:614
+#, c-format
+msgid "The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr "Prosessin käyttämän suoritinajan enimmäismäärä (sekunteina): %s"
+
+#: plugins/sudoers/def_data.c:618
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr "Prosessin datasegmentin enimmäiskoko (tavuina): %s"
+
+#: plugins/sudoers/def_data.c:622
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr "Prosessin luoman tiedoston enimmäiskoko (tavuina): %s"
+
+#: plugins/sudoers/def_data.c:626
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr "Prosessin vahvistamien lukkojen enimmäismäärä: %s"
+
+#: plugins/sudoers/def_data.c:630
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr "Prosessin lukittavaksi sallitun muistin enimmäiskoko (tavuina): %s"
+
+#: plugins/sudoers/def_data.c:634
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr "Prosessilla avoinna olevien tiedostojen enimmäismäärä: %s"
+
+#: plugins/sudoers/def_data.c:638
+#, c-format
+msgid "The maximum number of processes that the user may run simultaneously: %s"
+msgstr "Käyttäjän samanaikaisesti suoritettavien prosessien enimmäismäärä: %s"
+
+#: plugins/sudoers/def_data.c:642
+#, c-format
+msgid "The maximum size to which the process's resident set size may grow (in bytes): %s"
+msgstr "Prosessin käyttämän muistin RAM-muistissa oleva enimmäiskoko (tavuina): %s"
+
+#: plugins/sudoers/def_data.c:646
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr "Prosessin pinon enimmäiskoko (tavuina): %s"
+
+#: plugins/sudoers/def_data.c:650
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr "Yritä todennusta myös ei-vuorovaikutteisessa tilassa"
+
+#: plugins/sudoers/def_data.c:654
+msgid "Store plaintext passwords in I/O log input"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:658
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr "Salasanakehotetta täsmätessä käytettävien säännöllisten lausekkeiden luettelo"
+
+#: plugins/sudoers/defaults.c:193
+#, c-format
+msgid "%s: unknown defaults entry \"%s\""
+msgstr "%s: tuntematon oletusrivi ”%s”"
+
+# parametrinä on variable
+#: plugins/sudoers/defaults.c:242
+#, c-format
+msgid "%s:%d:%d: no value specified for \"%s\""
+msgstr "%s:%d:%d: arvoa ei ole määritelty muuttujalle ”%s”"
+
+# parametrinä on variable
+#: plugins/sudoers/defaults.c:245
+#, c-format
+msgid "%s: no value specified for \"%s\""
+msgstr "%s: arvoa ei ole määritelty muuttujalle ”%s”"
+
+# parametrinä on variable
+#: plugins/sudoers/defaults.c:258
+#, fuzzy, c-format
+#| msgid "%s:%d:%d: no value specified for \"%s\""
+msgid "%s:%d:%d: invalid operator \"%c=\" for \"%s\""
+msgstr "%s:%d:%d: arvoa ei ole määritelty muuttujalle ”%s”"
+
+#: plugins/sudoers/defaults.c:261
+#, fuzzy, c-format
+#| msgid "%s: invalid Defaults type 0x%x for option \"%s\""
+msgid "%s: invalid operator \"%c=\" for \"%s\""
+msgstr "%s: virheellinen Defaults-tyyppi 0x%x valitsimelle ”%s”"
+
+#: plugins/sudoers/defaults.c:297
+#, c-format
+msgid "%s:%d:%d: option \"%s\" does not take a value"
+msgstr "%s:%d:%d: valitsin ”%s” ei ota arvoa"
+
+#: plugins/sudoers/defaults.c:300
+#, c-format
+msgid "%s: option \"%s\" does not take a value"
+msgstr "%s: valitsin ”%s” ei ota arvoa"
+
+#: plugins/sudoers/defaults.c:328
+#, c-format
+msgid "%s:%d:%d: invalid Defaults type 0x%x for option \"%s\""
+msgstr "%s:%d:%d: virheellinen Defaults-tyyppi 0x%x valitsimelle ”%s”"
+
+#: plugins/sudoers/defaults.c:331
+#, c-format
+msgid "%s: invalid Defaults type 0x%x for option \"%s\""
+msgstr "%s: virheellinen Defaults-tyyppi 0x%x valitsimelle ”%s”"
+
+#: plugins/sudoers/defaults.c:341
+#, c-format
+msgid "%s:%d:%d: value \"%s\" is invalid for option \"%s\""
+msgstr "%s:%d:%d: arvo ”%s” on virheellinen valitsimelle ”%s”"
+
+#: plugins/sudoers/defaults.c:344
+#, c-format
+msgid "%s: value \"%s\" is invalid for option \"%s\""
+msgstr "%s: arvo ”%s” on virheellinen valitsimelle ”%s”"
+
+#: plugins/sudoers/defaults.c:1161
+#, c-format
+msgid "%s:%d:%d: path name for \"%s\" too long"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:1164
+#, c-format
+msgid "%s: path name for \"%s\" too long"
+msgstr ""
+
+# Parametri on muuttuja
+#: plugins/sudoers/defaults.c:1175
+#, c-format
+msgid "%s:%d:%d: values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "%s:%d:%d: ”%s”-muuttujan arvojen on alettava merkillä ’/’, ’~’ tai ’*’"
+
+# Parametri on muuttuja
+#: plugins/sudoers/defaults.c:1179
+#, c-format
+msgid "%s: values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "%s: ”%s”-muuttujan arvojen on alettava merkillä ’/’, ’~’ tai ’*’"
+
+# Parametri on muuttuja
+#: plugins/sudoers/defaults.c:1190
+#, c-format
+msgid "%s:%d:%d: values for \"%s\" must start with a '/'"
+msgstr "%s:%d:%d: ”%s”-muuttujan arvojen on alettava merkillä ’/’"
+
+# Parametri on muuttuja
+#: plugins/sudoers/defaults.c:1194
+#, c-format
+msgid "%s: values for \"%s\" must start with a '/'"
+msgstr "%s: ”%s”-muuttujan arvon on alettava merkillä ’/’"
+
+#: plugins/sudoers/env.c:412
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: rikkoutunut envp, pituus ei täsmää"
+
+#: plugins/sudoers/env.c:1095
+msgid "unable to rebuild the environment"
+msgstr "ympäristön rakentaminen uudelleen epäonnistui"
+
+#: plugins/sudoers/env.c:1169
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "sinun ei ole sallittua asettaa seuraavia ympäristömuuttujia: %s"
+
+#: plugins/sudoers/file.c:108
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr "jäsentämisvirhe tiedostossa %s lähellä riviä %d"
+
+#: plugins/sudoers/file.c:111
+#, c-format
+msgid "parse error in %s"
+msgstr "jäsentämisvirhe tiedostossa %s"
+
+#: plugins/sudoers/filedigest.c:49
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr "ei-tuettu tiivistetyyppi %d tiedostolle %s"
+
+#: plugins/sudoers/filedigest.c:78
+#, c-format
+msgid "%s: read error"
+msgstr "%s: kirjoitusvirhe"
+
+#: plugins/sudoers/group_plugin.c:83
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s-omistajan on oltava uid %d"
+
+#: plugins/sudoers/group_plugin.c:87
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr "%s on vain omistajan kirjoitettava"
+
+#: plugins/sudoers/group_plugin.c:96 plugins/sudoers/sssd.c:576
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "kohteen %s lataaminen epäonnistui: %s"
+
+# parametrina on path
+#: plugins/sudoers/group_plugin.c:102
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "symbolin ”group_plugin” löytäminen polusta %s epäonnistui"
+
+#: plugins/sudoers/group_plugin.c:107
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: yhteensopimaton ryhmälisäosan major-versio %d, odotettiin %d"
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "verkko-osoitteen ”%s” jäsentäminen epäonnistui"
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "verkkopeitteen ”%s” jäsentäminen epäonnistui"
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Paikallinen verkko-osoite ja verkkopeiteparit:\n"
+
+#: plugins/sudoers/iolog.c:681
+msgid "unable to update sequence file"
+msgstr "sekvenssitiedostoa ei voi päivittää"
+
+#: plugins/sudoers/iolog.c:715 plugins/sudoers/iolog.c:903
+#: plugins/sudoers/iolog.c:1065 plugins/sudoers/iolog.c:1072
+#: plugins/sudoers/iolog.c:1193 plugins/sudoers/iolog.c:1200
+#: plugins/sudoers/iolog.c:1299 plugins/sudoers/iolog.c:1306
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "siirtolokitiedostoon: %s kirjoittaminen epäonnistui"
+
+# Parametrina on pathbuf
+#: plugins/sudoers/iolog.c:723
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "tiedostoa %s/%s ei voida luoda"
+
+#: plugins/sudoers/iolog.c:951
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: sisäinen virhe, tapahtuman %d siirräntälokitiedosto ei ole avoin"
+
+#: plugins/sudoers/iolog.c:1050 plugins/sudoers/iolog.c:1178
+#: plugins/sudoers/iolog.c:1283 plugins/sudoers/timestamp.c:849
+#: plugins/sudoers/timestamp.c:941 plugins/sudoers/visudo.c:510
+#: plugins/sudoers/visudo.c:516
+msgid "unable to read the clock"
+msgstr "kellon lukeminen epäonnistui"
+
+#: plugins/sudoers/iolog.c:1275 plugins/sudoers/log_client.c:1221
+#: plugins/sudoers/log_client.c:1231 plugins/sudoers/log_client.c:1235
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: sisäinen virhe, virheellinen signaali %d"
+
+#: plugins/sudoers/ldap.c:177 plugins/sudoers/ldap_conf.c:291
+msgid "starttls not supported when using ldaps"
+msgstr "starttls ei ole tuettu ldaps-käytössä"
+
+#: plugins/sudoers/ldap.c:248
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "SSL-varmenne- ja avaintietokannan alustaminen epäonnistui: %s"
+
+#: plugins/sudoers/ldap.c:251
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "kohteessa %s TLS_CERT on asetettava käyttämään SSL:ää"
+
+#: plugins/sudoers/ldap.c:1717
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "kohteen LDAP alustaminen epäonnistui: %s"
+
+#: plugins/sudoers/ldap.c:1754
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls määritelty, mutta LDAP-kirjastot ei tue funktiota ldap_start_tls_s() tai funktiota ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:1891 plugins/sudoers/parse_ldif.c:747
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "virheellinen sudoOrder-attribuutti: %s"
+
+#: plugins/sudoers/ldap_conf.c:200
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: portti liian suuri"
+
+# URL on verkko-osoite, loogisesti URI on verkkoresurssi(osoite)
+#: plugins/sudoers/ldap_conf.c:260
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "tukematon LDAP-verkkoresurssin tunnustyyppi: %s"
+
+#: plugins/sudoers/ldap_conf.c:287
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "ldap:n ja ldap-verkkoresurssitunnuksien sekoittaminen epäonnistui"
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "kahdentunut sudoOption: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "sudoOptionia ei voi muuntaa: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "audit-järjestelmän avaaminen epäonnistui"
+
+#: plugins/sudoers/linux_audit.c:103
+msgid "unable to send audit message"
+msgstr "audit-viestin lähettäminen epäonnistui"
+
+#: plugins/sudoers/log_client.c:120 plugins/sudoers/log_client.c:400
+#: plugins/sudoers/log_client.c:1468 plugins/sudoers/log_client.c:2069
+msgid "error in event loop"
+msgstr "virhe tapahtumasilmukassa"
+
+#: plugins/sudoers/log_client.c:200
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "Uuden SSL_CTX-objektin luominen epäonnistui: %s"
+
+#: plugins/sudoers/log_client.c:223
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "varmenteen myöntäjän pakettia %s ei voitu ladata"
+
+#: plugins/sudoers/log_client.c:243
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "sertifikaatin %s lataaminen epäonnistui"
+
+#: plugins/sudoers/log_client.c:256
+#, c-format
+msgid "unable to load private key %s"
+msgstr "yksityistä avainta %s ei voi ladata"
+
+#: plugins/sudoers/log_client.c:265
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "Ssl-objektia ei voi varata: %s"
+
+#: plugins/sudoers/log_client.c:353 plugins/sudoers/log_client.c:358
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "TLS-yhteys kohteeseen %s:%s epäonnistui: %s"
+
+#: plugins/sudoers/log_client.c:531
+msgid "TLS initialization was unsuccessful"
+msgstr "TLS-alustus epäonnistui"
+
+#: plugins/sudoers/log_client.c:541
+msgid "TLS handshake was unsuccessful"
+msgstr "TLS-kättely epäonnistui"
+
+#: plugins/sudoers/log_client.c:1239
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: sisäinen virhe, virheellinen lopetustila %d"
+
+#: plugins/sudoers/log_client.c:1608
+msgid "unable to unpack ServerMessage"
+msgstr "ServerMessage-viestiä ei voi purkaa"
+
+#: plugins/sudoers/log_client.c:1763 plugins/sudoers/log_client.c:1787
+msgid "lost connection to log server"
+msgstr "yhteys lokipalvelimeen katkesi"
+
+#: plugins/sudoers/log_client.c:1864
+msgid "missing write buffer"
+msgstr "puuttuva kirjoituspuskuri"
+
+#: plugins/sudoers/log_client.c:2010
+msgid "unable to connect to log server"
+msgstr "yhteyden muodostaminen lokipalvelimeen ei onnistu"
+
+#: plugins/sudoers/logging.c:288
+msgid "user NOT in sudoers"
+msgstr "käyttäjä EI ole sudoers-tiedostossa"
+
+#: plugins/sudoers/logging.c:290
+msgid "user NOT authorized on host"
+msgstr "käyttäjä ei ole varmennettu tietokoneella"
+
+#: plugins/sudoers/logging.c:292
+msgid "command not allowed"
+msgstr "komento ei ole sallittu"
+
+#: plugins/sudoers/logging.c:313
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr "%s ei ole sudoers-tiedostossa.\n"
+
+#: plugins/sudoers/logging.c:316
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr "%s ei saa suorittaa sudoa koneella %s.\n"
+
+#: plugins/sudoers/logging.c:319
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Käyttäjä %s ei saa suorittaa sudoa %s-koneella.\n"
+
+#: plugins/sudoers/logging.c:322
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr "Käyttäjä %s ei saa suorittaa komentoa ”%s%s%s” käyttäjänä %s%s%s koneella %s.\n"
+
+#: plugins/sudoers/logging.c:359 plugins/sudoers/sudoers.c:629
+#: plugins/sudoers/sudoers.c:631 plugins/sudoers/sudoers.c:633
+#: plugins/sudoers/sudoers.c:635 plugins/sudoers/sudoers.c:785
+#: plugins/sudoers/sudoers.c:787
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: komentoa ei löytynyt"
+
+#: plugins/sudoers/logging.c:361 plugins/sudoers/sudoers.c:625
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"ohitetaan ”.”-hakemistosta löytynyt ”%s”\n"
+"Käytä komentoa ”sudo ./%s”, jos juuri tämä ”%s” halutaan suoritettavan."
+
+#: plugins/sudoers/logging.c:380
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u väärä salasanayritys"
+msgstr[1] "%u väärää salasanayritystä"
+
+#: plugins/sudoers/logging.c:436
+msgid "authentication failure"
+msgstr "todennusvirhe"
+
+#: plugins/sudoers/logging.c:476 plugins/sudoers/logging.c:496
+msgid "a password is required"
+msgstr "vaaditaan salasana"
+
+#: plugins/sudoers/logging.c:890
+#, c-format
+msgid "unable to write log file: %s"
+msgstr "lokitiedostoon: %s kirjoittaminen epäonnistui"
+
+#: plugins/sudoers/match_digest.c:129
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "tiedoston %s tiiviste (%s) ei ole %s-muodossa"
+
+#: plugins/sudoers/parse.c:233
+msgid "SELinux RBAC is not supported when intercept mode is enabled"
+msgstr "SELinux RBAC ei ole tuettu, kun sieppaustila on käytössä"
+
+#: plugins/sudoers/parse.c:238
+msgid "SELinux RBAC is not supported when the log_subcmds flag is enabled"
+msgstr "SELinux RBAC ei ole tuettu, kun log_subcmds-lippu on käytössä"
+
+#: plugins/sudoers/parse.c:549
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+"\n"
+"LDAP-rooli: %s\n"
+
+#: plugins/sudoers/parse.c:552
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+"\n"
+"Sudoers-rivi:\n"
+
+#: plugins/sudoers/parse.c:554
+msgid " RunAsUsers: "
+msgstr " SuoritaKäyttäjänä: "
+
+#: plugins/sudoers/parse.c:569
+msgid " RunAsGroups: "
+msgstr " SuoritaRyhmänä: "
+
+#: plugins/sudoers/parse.c:579
+msgid " Options: "
+msgstr " Valitsimet: "
+
+#: plugins/sudoers/parse.c:643
+msgid " Commands:\n"
+msgstr " Komennot:\n"
+
+#: plugins/sudoers/parse.c:834
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Täsmäävät Defaults-rivit käyttäjälle %s koneella %s:\n"
+
+#: plugins/sudoers/parse.c:852
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Runas- ja Command-kohtaiset oletukset käyttäjälle %s:\n"
+
+#: plugins/sudoers/parse.c:870
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "Käyttäjä %s voi suorittaa seuraavat komennot koneella %s:\n"
+
+#: plugins/sudoers/parse.c:885
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Käyttäjä %s ei saa suorittaa komentoa sudo tietokoneella %s.\n"
+
+#: plugins/sudoers/parse_ldif.c:617
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "jätetään huomiotta epätäydellinen sudoRole: cn: %s"
+
+#: plugins/sudoers/parse_ldif.c:677
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "virheellinen LDIF-määrite: %s"
+
+#: plugins/sudoers/policy.c:80 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "virheellinen sudo-edustaohjelman asettama %.*s"
+
+#: plugins/sudoers/policy.c:206 plugins/sudoers/policy.c:215
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr ""
+
+#: plugins/sudoers/policy.c:328 plugins/sudoers/testsudoers.c:268
+msgid "unable to parse network address list"
+msgstr "verkko-osoiteluettelon jäsentäminen epäonnistui"
+
+#: plugins/sudoers/policy.c:485
+msgid "user name not set by sudo front-end"
+msgstr "sudo-edustaohjelma ei määritellyt käyttäjänimeä"
+
+#: plugins/sudoers/policy.c:489
+msgid "user-ID not set by sudo front-end"
+msgstr "sudo-edustaohjelma ei määritellyt käyttäjä-ID:tä"
+
+#: plugins/sudoers/policy.c:493
+msgid "group-ID not set by sudo front-end"
+msgstr "sudo-edustaohjelma ei määritellyt ryhmä-ID:tä"
+
+#: plugins/sudoers/policy.c:497
+msgid "host name not set by sudo front-end"
+msgstr "sudo-edustaohjelma ei määritellyt konenimeä"
+
+#: plugins/sudoers/policy.c:670
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "virheellinen työhakemisto: %s"
+
+#: plugins/sudoers/policy.c:846
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "virheellinen chroot-hakemisto: %s"
+
+# Parametri on path, mutta saattaa sisältää suoritettavan ohjelman
+#: plugins/sudoers/policy.c:1025 plugins/sudoers/visudo.c:243
+#: plugins/sudoers/visudo.c:880
+#, c-format
+msgid "unable to execute %s"
+msgstr "kohteen %s suorittaminen epäonnistui"
+
+#: plugins/sudoers/policy.c:1095 plugins/sudoers/policy.c:1132
+#: plugins/sudoers/policy.c:1154 plugins/sudoers/policy.c:1180
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: virheelliset tilaliput sudo-edustaohjelmalta: 0x%x"
+
+#: plugins/sudoers/policy.c:1211
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Sudoers-menettelytapalisäosaversio %s\n"
+
+#: plugins/sudoers/policy.c:1213
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Sudoers-tiedostokielioppiversio %d\n"
+
+#: plugins/sudoers/policy.c:1217
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Sudoers-polku: %s\n"
+
+#: plugins/sudoers/policy.c:1220
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "nsswitch-polku: %s\n"
+
+#: plugins/sudoers/policy.c:1222
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "ldap.conf-polku: %s\n"
+
+#: plugins/sudoers/policy.c:1223
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "ldap.secret-polku: %s\n"
+
+#: plugins/sudoers/policy.c:1256
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "%d-tyyppisen kytkennän (versio %d.%d) rekisteröiminen epäonnistui"
+
+#: plugins/sudoers/policy.c:1274
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "%d-tyyppisen kytkennän (versio %d.%d) rekisteröinnin poisto epäonnistui"
+
+#: plugins/sudoers/pwutil.c:222 plugins/sudoers/pwutil.c:240
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "käyttäjä-id:n %u välimuistittaminen epäonnistui"
+
+#: plugins/sudoers/pwutil.c:234
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "käyttäjä-id:n %u välimuistittaminen epäonnistui, on jo olemassa"
+
+# Parametrina on pathbuf
+#: plugins/sudoers/pwutil.c:294 plugins/sudoers/pwutil.c:312
+#: plugins/sudoers/pwutil.c:375 plugins/sudoers/pwutil.c:420
+#, c-format
+msgid "unable to cache user %s"
+msgstr "%s-käyttäjän välimuistittaminen epäonnistui"
+
+#: plugins/sudoers/pwutil.c:307
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "%s-käyttäjän välimuistittaminen epäonnistui, on jo olemassa"
+
+#: plugins/sudoers/pwutil.c:539 plugins/sudoers/pwutil.c:557
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "ryhmä-id:n %u välimuistittaminen epäonnistui"
+
+#: plugins/sudoers/pwutil.c:551
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "ryhmä-id:n %u välimuistittaminen epäonnistui, on jo olemassa"
+
+#: plugins/sudoers/pwutil.c:605 plugins/sudoers/pwutil.c:623
+#: plugins/sudoers/pwutil.c:684 plugins/sudoers/pwutil.c:733
+#, c-format
+msgid "unable to cache group %s"
+msgstr "%s-ryhmän välimuistittaminen epäonnistui"
+
+#: plugins/sudoers/pwutil.c:618
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "%s-ryhmän välimuistittaminen epäonnistui, on jo olemassa"
+
+#: plugins/sudoers/pwutil.c:880 plugins/sudoers/pwutil.c:931
+#: plugins/sudoers/pwutil.c:981 plugins/sudoers/pwutil.c:1033
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "%s-käyttäjän ryhmäluettelon välimuistittaminen epäonnistui, on jo olemassa"
+
+#: plugins/sudoers/pwutil.c:886 plugins/sudoers/pwutil.c:936
+#: plugins/sudoers/pwutil.c:987 plugins/sudoers/pwutil.c:1038
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "%s-käyttäjän ryhmäluettelon välimuistittaminen epäonnistui"
+
+#: plugins/sudoers/pwutil.c:925
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "%s-käyttäjän ryhmien jäsentäminen epäonnistui"
+
+#: plugins/sudoers/pwutil.c:1027
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "%s-käyttäjän ryhmä-id:iden jäsentäminen epäonnistui"
+
+#: plugins/sudoers/set_perms.c:114 plugins/sudoers/set_perms.c:445
+#: plugins/sudoers/set_perms.c:852 plugins/sudoers/set_perms.c:1162
+#: plugins/sudoers/set_perms.c:1460
+msgid "perm stack overflow"
+msgstr "käyttöoikeuspinon ylivuoto"
+
+#: plugins/sudoers/set_perms.c:125 plugins/sudoers/set_perms.c:376
+#: plugins/sudoers/set_perms.c:456 plugins/sudoers/set_perms.c:719
+#: plugins/sudoers/set_perms.c:863 plugins/sudoers/set_perms.c:1086
+#: plugins/sudoers/set_perms.c:1173 plugins/sudoers/set_perms.c:1393
+#: plugins/sudoers/set_perms.c:1471 plugins/sudoers/set_perms.c:1562
+msgid "perm stack underflow"
+msgstr "käyttöoikeuspinon alivuoto"
+
+#: plugins/sudoers/set_perms.c:185 plugins/sudoers/set_perms.c:503
+#: plugins/sudoers/set_perms.c:1227 plugins/sudoers/set_perms.c:1505
+msgid "unable to change to root gid"
+msgstr "vaihtaminen root gid -tunnisteeksi epäonnistui"
+
+#: plugins/sudoers/set_perms.c:276 plugins/sudoers/set_perms.c:600
+#: plugins/sudoers/set_perms.c:995 plugins/sudoers/set_perms.c:1304
+msgid "unable to change to runas gid"
+msgstr "vaihtaminen runas gid -tunnisteeksi epäonnistui"
+
+#: plugins/sudoers/set_perms.c:281 plugins/sudoers/set_perms.c:605
+#: plugins/sudoers/set_perms.c:1000 plugins/sudoers/set_perms.c:1309
+msgid "unable to set runas group vector"
+msgstr "runas-ryhmävektorin asettaminen epäonnistui"
+
+#: plugins/sudoers/set_perms.c:292 plugins/sudoers/set_perms.c:616
+#: plugins/sudoers/set_perms.c:1009 plugins/sudoers/set_perms.c:1318
+msgid "unable to change to runas uid"
+msgstr "vaihtaminen runas uid -tunnisteeksi epäonnistui"
+
+#: plugins/sudoers/set_perms.c:310 plugins/sudoers/set_perms.c:634
+#: plugins/sudoers/set_perms.c:1025 plugins/sudoers/set_perms.c:1334
+msgid "unable to change to sudoers gid"
+msgstr "vaihtaminen sudoers gid-tunnisteeksi epäonnistui"
+
+#: plugins/sudoers/set_perms.c:363 plugins/sudoers/set_perms.c:706
+#: plugins/sudoers/set_perms.c:1073 plugins/sudoers/set_perms.c:1380
+#: plugins/sudoers/set_perms.c:1549
+msgid "too many processes"
+msgstr "liian monta prosessia"
+
+#: plugins/sudoers/solaris_audit.c:61
+msgid "unable to get current working directory"
+msgstr "nykyisen työhakemiston hakeminen epäonnistui"
+
+#: plugins/sudoers/solaris_audit.c:69
+#, c-format
+msgid "truncated audit path user_cmnd: %s"
+msgstr "typistetty audit-polku user_cmnd: %s"
+
+#: plugins/sudoers/solaris_audit.c:76
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "typistetty audit-polku argv[0]: %s"
+
+#: plugins/sudoers/sssd.c:579
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "lähteen SSS alustaminen epäonnistui. Onko SSSD asennettu tietokoneeseesi?"
+
+# parametrina on path
+#: plugins/sudoers/sssd.c:587 plugins/sudoers/sssd.c:596
+#: plugins/sudoers/sssd.c:605 plugins/sudoers/sssd.c:614
+#: plugins/sudoers/sssd.c:623
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "symbolin ”%s” löytäminen polusta %s epäonnistui"
+
+#: plugins/sudoers/sudoers.c:166 plugins/sudoers/sudoers.c:174
+#: plugins/sudoers/sudoers.c:228 plugins/sudoers/sudoers.c:249
+#: plugins/sudoers/sudoers.c:1049
+msgid "problem with defaults entries"
+msgstr "oletusrivien pulma"
+
+#: plugins/sudoers/sudoers.c:253
+msgid "no valid sudoers sources found, quitting"
+msgstr "ei löytynyt kelvollisia sudoers-lähteitä, poistutaan"
+
+#: plugins/sudoers/sudoers.c:327
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "käyttäjällä ei ole lupaa vaihtaa juurihakemistoksi %s"
+
+#: plugins/sudoers/sudoers.c:329
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "sinulla ei ole lupaa käyttää valitsinta -R komennolle %s"
+
+#: plugins/sudoers/sudoers.c:354
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "käyttäjällä ei ole lupaa vaihtaa hakemistoksi %s"
+
+#: plugins/sudoers/sudoers.c:355
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "sinulla ei ole lupaa käyttää valitsinta -D komennolle %s"
+
+#: plugins/sudoers/sudoers.c:382
+msgid "no command specified"
+msgstr "komentoa ei annettu"
+
+#: plugins/sudoers/sudoers.c:407
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers määrittelee, että root ei saa suorittaa sudo-komentoa"
+
+#: plugins/sudoers/sudoers.c:457
+msgid "user not allowed to override closefrom limit"
+msgstr "käyttäjällä ei ole lupaa syrjäyttää closefrom-rajaa"
+
+#: plugins/sudoers/sudoers.c:458
+msgid "you are not permitted to use the -C option"
+msgstr "sinulla ei ole lupaa käyttää valitsinta -C"
+
+#: plugins/sudoers/sudoers.c:518
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr "aikaleimaomistaja (%s): Tuntematon käyttäjä"
+
+#: plugins/sudoers/sudoers.c:533
+msgid "no tty"
+msgstr "ei tty:tä"
+
+#: plugins/sudoers/sudoers.c:534
+msgid "sorry, you must have a tty to run sudo"
+msgstr "sudo-komennon suorittamiseksi on oltava tty"
+
+#: plugins/sudoers/sudoers.c:541
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "virheellinen kuori käyttäjälle %s: %s"
+
+#: plugins/sudoers/sudoers.c:624
+msgid "command in current directory"
+msgstr "komento nykyisessä hakemistossa"
+
+#: plugins/sudoers/sudoers.c:639
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr "”cd” on kuoren sisäinen komento, sitä ei voi suorittaa suoraan."
+
+#: plugins/sudoers/sudoers.c:641
+msgid "the -s option may be used to run a privileged shell."
+msgstr "-s-valitsinta voi käyttää käyttöoikeuskorotetun kuoren suorittamiseen."
+
+#: plugins/sudoers/sudoers.c:643
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr "-D-valitsinta voi käyttää komennon suorittamiseksi tietyssä hakemistossa."
+
+#: plugins/sudoers/sudoers.c:652
+msgid "user not allowed to set a command timeout"
+msgstr "käyttäjä ei saa asettaa komennon aikakatkaisua"
+
+#: plugins/sudoers/sudoers.c:654
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "komennon aikakatkaisun asettaminen ei ole sallittua sinulle"
+
+#: plugins/sudoers/sudoers.c:662
+msgid "user not allowed to preserve the environment"
+msgstr "käyttäjä ei saa säilyttää ympäristöä"
+
+#: plugins/sudoers/sudoers.c:664
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "sinun ei ole sallittua säilöä ympäristöä"
+
+#: plugins/sudoers/sudoers.c:1037
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "sudoeditiä ei tarvitse suorittaa sudon kautta"
+
+# Parametrinä on sudoers-tiedosto tai pathbuf
+#: plugins/sudoers/sudoers.c:1096 plugins/sudoers/sudoreplay.c:1584
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "kohteen %s lukeminen epäonnistui"
+
+#: plugins/sudoers/sudoers.c:1121 plugins/sudoers/visudo.c:449
+#: plugins/sudoers/visudo.c:748
+#, c-format
+msgid "unable to stat %s"
+msgstr "funktion stat %s kutsuminen epäonnistui"
+
+#: plugins/sudoers/sudoers.c:1125 plugins/sudoers/visudo.c:1045
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s ei ole tavallinen tiedosto"
+
+#: plugins/sudoers/sudoers.c:1129 plugins/sudoers/timestamp.c:252 toke.l:1239
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s on uid %u -käyttäjän omistama, pitäisi olla %u"
+
+#: plugins/sudoers/sudoers.c:1133 toke.l:1244
+#, c-format
+msgid "%s is world writable"
+msgstr "%s on yleiskirjoitettava"
+
+#: plugins/sudoers/sudoers.c:1137 toke.l:1247
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s on gid %u -ryhmän omistama, pitäisi olla %u"
+
+#: plugins/sudoers/sudoers.c:1170
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "vain root-käyttäjä voi käyttää valitsinta ”-c %s”"
+
+#: plugins/sudoers/sudoers.c:1189
+#, c-format
+msgid "unknown login class %s"
+msgstr "tuntematon kirjautumisluokka %s"
+
+#: plugins/sudoers/sudoers.c:1275 plugins/sudoers/sudoers.c:1290
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "konenimen %s selvitys epäonnistui"
+
+#: plugins/sudoers/sudoreplay.c:259
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "virheellinen suodatinvalitsin: %s"
+
+#: plugins/sudoers/sudoreplay.c:275
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "virheellinen enimmäisodotusaika: %s"
+
+#: plugins/sudoers/sudoreplay.c:298
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "virheellinen nopeustekijä: %s"
+
+#: plugins/sudoers/sudoreplay.c:333
+#, c-format
+msgid "invalid time offset %s"
+msgstr "virheellinen aikasiirtymä %s"
+
+#: plugins/sudoers/sudoreplay.c:342
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:347
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/ajoitus: %s"
+
+#: plugins/sudoers/sudoreplay.c:375
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Toistetaan sudo-istunto: %s"
+
+#: plugins/sudoers/sudoreplay.c:637
+msgid "unable to set tty to raw mode"
+msgstr "tty:n asettaminen raakatilaan epäonnistui"
+
+#: plugins/sudoers/sudoreplay.c:688
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr "Varoitus: pääteikkunasi on liian pieni tämän lokin toistamiseksi oikein.\n"
+
+#: plugins/sudoers/sudoreplay.c:689
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Lokigeometria on %d x %d, pääteikkunasi geometria on %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:717
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Toistaminen päättyi, palaa pääteikkunaan painamalla mitä tahansa näppäintä."
+
+#: plugins/sudoers/sudoreplay.c:1219 plugins/sudoers/sudoreplay.c:1249
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "moniselitteinen lauseke \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1271
+msgid "unmatched ')' in expression"
+msgstr "täsmäämätön ’)’ lausekkeessa"
+
+#: plugins/sudoers/sudoreplay.c:1275
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "tuntematon hakutermi ”%s”"
+
+#: plugins/sudoers/sudoreplay.c:1290
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s vaatii argumentin"
+
+#: plugins/sudoers/sudoreplay.c:1300
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "päivämäärän ”%s” jäsentäminen epäonnistui"
+
+#: plugins/sudoers/sudoreplay.c:1309
+msgid "unmatched '(' in expression"
+msgstr "täsmäämätön ’(’ lausekkeessa"
+
+#: plugins/sudoers/sudoreplay.c:1311
+msgid "illegal trailing \"or\""
+msgstr "virheellinen jäljessä oleva ”or”"
+
+#: plugins/sudoers/sudoreplay.c:1313
+msgid "illegal trailing \"!\""
+msgstr "virheellinen jäljessä oleva ”!”"
+
+#: plugins/sudoers/sudoreplay.c:1371
+#, c-format
+msgid "unknown search type %d"
+msgstr "tuntematon hakutyyppi %d"
+
+#: plugins/sudoers/sudoreplay.c:1651
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "käyttö: %s [-hnRS] [-d hakemisto] [-m numero] [-s numero] tunniste\n"
+
+#: plugins/sudoers/sudoreplay.c:1654
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "käyttö: %s [-h] [-d hakemisto] -l [hakulauseke]\n"
+
+#: plugins/sudoers/sudoreplay.c:1663
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - toista sudo-istuntolokit\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1665
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Valitsimet:\n"
+" -d, --directory=hak määrittele istuntolokien hakemisto\n"
+" -f, --filter=suodatin määrittele, mitkä siirräntätyyppit näytetään\n"
+" -h, --help näytä opaste ja poistu\n"
+" -l, --list [lauseke] luettele käytettävissä oleva istuntotunnisteet;\n"
+" valinnainen täsmäyslauseke voidaan antaa\n"
+" -m, --max-wait=määrä tapahtumien välinen enimmäisodotusaika sekunteina\n"
+" -n, --non-interactive ei kehotteita, istunto lähetetään vakiotulosteeseen\n"
+" -R, --no-resize älä yritä muuttaa päätteen kokoa\n"
+" -S, --suspend-wait odota, kun komento on on pysäytetty\n"
+" -s, --speed=luku nopeuta tai hidasta tulostusta\n"
+" -V, --version näytä versiotiedot ja poistu"
+
+#: plugins/sudoers/testsudoers.c:344
+msgid "\thost unmatched"
+msgstr "\ttietokone täsmäämätön"
+
+#: plugins/sudoers/testsudoers.c:347
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Komento sallittu"
+
+#: plugins/sudoers/testsudoers.c:348
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Komento kielletty"
+
+#: plugins/sudoers/testsudoers.c:348
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Täsmäämätön komento"
+
+#: plugins/sudoers/timestamp.c:260
+#, c-format
+msgid "%s is group writable"
+msgstr "%s on ryhmäkirjoitettava"
+
+#: plugins/sudoers/timestamp.c:328 plugins/sudoers/timestamp.c:663
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "aikaleimatiedoston typistäminen %lld-tavun kokoiseksi epäonnistui"
+
+#: plugins/sudoers/timestamp.c:860
+msgid "ignoring time stamp from the future"
+msgstr "ohitetaan aikaleima tulevaisuudesta"
+
+#: plugins/sudoers/timestamp.c:883
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "aikaleima liian kaukana tulevaisuudessa: %20.20s"
+
+#: plugins/sudoers/timestamp.c:1005
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "aikaleimatiedoston %s lukitseminen epäonnistui"
+
+#: plugins/sudoers/timestamp.c:1049 plugins/sudoers/timestamp.c:1069
+#, c-format
+msgid "lecture status path too long: %s/%s"
+msgstr "saarnatilan polku on liian pitkä: %s/%s"
+
+#: plugins/sudoers/toke_util.c:156
+msgid "sudoedit should not be specified with a path"
+msgstr "sudoeditiä ei tule käynnistää polun kanssa"
+
+#: plugins/sudoers/visudo.c:238
+msgid "the -x option will be removed in a future release"
+msgstr "valitsin -x poistetaan jossakin tulevassa versiossa"
+
+#: plugins/sudoers/visudo.c:240
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "harkitse cvtsudoers-apuohjelman käyttöä"
+
+#: plugins/sudoers/visudo.c:292 plugins/sudoers/visudo.c:676
+#, c-format
+msgid "press return to edit %s: "
+msgstr "muokkaa %s painamalla enter-painiketta: "
+
+#: plugins/sudoers/visudo.c:307
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:361
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "määritelty editori (%s) ei ole olemassa"
+
+#: plugins/sudoers/visudo.c:363
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "editoria ei löytynyt (editoripolku = %s)"
+
+#: plugins/sudoers/visudo.c:469 plugins/sudoers/visudo.c:477
+msgid "write error"
+msgstr "kirjoitusvirhe"
+
+#: plugins/sudoers/visudo.c:523
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "tilapäistiedoston (%s) tilan lukeminen epäonnistui, %s ennallaan"
+
+#: plugins/sudoers/visudo.c:530
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "nollapituinen tilapäinen tiedosto (%s), %s ennallaan"
+
+#: plugins/sudoers/visudo.c:536
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "editori (%s) epäonnistui, %s ennallaan"
+
+#: plugins/sudoers/visudo.c:558
+#, c-format
+msgid "%s unchanged"
+msgstr "%s ennallaan"
+
+#: plugins/sudoers/visudo.c:615
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "tilapäisen tiedoston (%s) avaaminen uudelleen epäonnistui, %s ennallaan."
+
+#: plugins/sudoers/visudo.c:627
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "tilapäisen tiedoston (%s) jäsentäminen epäonnistui, tuntematon virhe"
+
+#: plugins/sudoers/visudo.c:665
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr "sisäinen virhe, kohteen %s löytäminen luettelosta epäonnistui!"
+
+#: plugins/sudoers/visudo.c:722 plugins/sudoers/visudo.c:752
+#: plugins/sudoers/visudo.c:759
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "kohteen %s (uid, gid) asettaminen arvoihin (%u, %u) epäonnistui"
+
+#: plugins/sudoers/visudo.c:787
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s ja %s eivät ole samassa tiedostojärjestelmässä, käytetään komentoa mv uudelleennimeämiseen"
+
+#: plugins/sudoers/visudo.c:798
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "komento epäonnistui: ’%s %s %s’, %s ennallaan"
+
+#: plugins/sudoers/visudo.c:805
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "virhe nimettäessä %s uudelleen, %s ennallaan"
+
+#: plugins/sudoers/visudo.c:825
+msgid "What now? "
+msgstr "Mitä nyt? "
+
+#: plugins/sudoers/visudo.c:839
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Valitsimia ovat:\n"
+" (e) muokkaa sudoers-tiedostoa uudelleen\n"
+" (x) poistu tallentamatta sudoers-tiedoston muutoksia\n"
+" (Q) poistu ja tallenna muutokset sudoers-tiedostoon (VAARA!)\n"
+
+# Parametri on path, mutta saattaa sisältää suoritettavan ohjelman
+#: plugins/sudoers/visudo.c:885
+#, c-format
+msgid "unable to run %s"
+msgstr "kohteen %s suorittaminen epäonnistui"
+
+#: plugins/sudoers/visudo.c:916
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: väärä omistaja (uid, gid), pitäisi olla (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:927
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: väärät käyttöoikeudet, pitäisi olla tila 0%o\n"
+
+#: plugins/sudoers/visudo.c:978 plugins/sudoers/visudo.c:985
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: jäsentäminen valmis\n"
+
+#: plugins/sudoers/visudo.c:1004
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s varattu, yritä myöhemmin uudelleen"
+
+#: plugins/sudoers/visudo.c:1008
+msgid "Edit anyway? [y/N]"
+msgstr "Muokataanko silti? [y/N]"
+
+#: plugins/sudoers/visudo.c:1104
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "Varoitus: %s:%d:%d: käyttämätön %s \"%s\""
+
+#: plugins/sudoers/visudo.c:1220
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - muokkaa sudoers-tiedostoa turvallisesti\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1222
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Valitsimet:\n"
+" -c, --check vain tarkistus -tila\n"
+" -f, --file=sudoers määrittele sudoers-tiedoston sijainti\n"
+" -h, --help näytä opasteteksti ja poistu\n"
+" -q, --quiet vähemmän laveat (hiljaiset) syntaksivirheviestit\n"
+" -s, --strict tiukka syntaksitarkistus\n"
+" -V, --version näytä versiotiedot ja poistu\n"
+
+#: toke.l:189
+msgid "empty string"
+msgstr "tyhjä merkkijono"
+
+#: toke.l:201 toke.l:571
+msgid "empty group"
+msgstr "tyhjä ryhmä"
+
+#: toke.l:211 toke.l:569
+msgid "empty netgroup"
+msgstr "tyhjä verkkoryhmä"
+
+#: toke.l:289
+msgid "unterminated regular expression"
+msgstr "päättämätön säännöllinen lauseke"
+
+#: toke.l:363 toke.l:375 toke.l:387 toke.l:403 toke.l:422 toke.l:462
+msgid "invalid line continuation"
+msgstr "virheellinen rivin jatko"
+
+#: toke.l:608 toke.l:620
+msgid "invalid IPv6 address"
+msgstr "virheellinen IPv6-osoite"
+
+#: toke.l:860
+msgid "unexpected line break in string"
+msgstr "odottamaton rivinkatkaisu merkkijonossa"
+
+#: toke.l:1210
+msgid "too many levels of includes"
+msgstr "liian monta include-tasoa"
+
+#~ msgid "%s is not in the sudoers file. This incident will be reported.\n"
+#~ msgstr "%s ei ole sudoers-tiedostossa. Tästä tehdään ilmoitus.\n"
+
+#~ msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+#~ msgstr "%s ei saa suorittaa sudoa %s-koneella. Tästä tehdään ilmoitus.\n"
+
+#~ msgid "%s: write buffer already in use"
+#~ msgstr "%s: kirjoituspuskuri on jo käytössä"
+
+#~ msgid "unable to read diffie-hellman parameters: %s"
+#~ msgstr "diffie-hellman-parametreja ei voi lukea: %s"
+
+#~ msgid "unknown defaults entry \"%s\""
+#~ msgstr "tuntematon oletusrivi \"%s\""
+
+#~ msgid "%s:%d unknown key: %s"
+#~ msgstr "%s:%d tuntematon avain: %s"
+
+#~ msgid "unable to get TLS server method: %s"
+#~ msgstr "TLS-palvelinmenetelmää ei saada noudettua: %s"
+
+# Ensimmäinen parametri on auth name
+#, fuzzy
+#~ msgid "%s:%u unable to parse \"%s\""
+#~ msgstr "%s: todentamisnimen ’%s’ jäsentäminen epäonnistui: %s"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " -f, --file path to configuration file\n"
+#~ " -h --help display help message and exit\n"
+#~ " -n, --no-fork do not fork, run in the foreground\n"
+#~ " -R, --random-drop percent chance connections will drop\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Valitsimet:\n"
+#~ " -f, --file asetustiedoston polku\n"
+#~ " -h, --help näytä opaste ja poistu\n"
+#~ " -n, --no-fork älä haarauta, vaan suorita edustalla\n"
+#~ " -R, --random-drop yhteyden katkeamisen todennäköisyys-%\n"
+#~ " -V, --version näytä versiotiedot ja poistu\n"
+
+#~ msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+#~ msgstr "Esilataa vale-exec-funktiot, jotka sisältyvät sudo_noexec-kirjastoon"
+
+#~ msgid "sudo_ldap_conf_add_ports: port too large"
+#~ msgstr "sudo_ldap_conf_add_ports: portti on liian suuri"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s\n"
+#~ msgstr "SSL_connect epäonnistui: ssl_error=%d, pino=%s\n"
+
+#~ msgid "CA bundle file was not specified"
+#~ msgstr "CA-pakettitiedostoa ei määritelty"
+
+#~ msgid "Client certificate was not specified"
+#~ msgstr "Asiakassertifikaattia ei annettu"
+
+#~ msgid "Unable to allocate ssl object: %s\n"
+#~ msgstr "Ssl-objektia ei voi varata: %s\n"
+
+#~ msgid "client message too large: %zu\n"
+#~ msgstr "asiakassanoma on liian suuri: %zu\n"
+
+#~ msgid "server message too large: %u\n"
+#~ msgstr "palvelinsanoma on liian suuri: %u\n"
+
+#, fuzzy
+#~| msgid "Send mail if the user is not in sudoers"
+#~ msgid "CA bundle file is not set in sudoers"
+#~ msgstr "Lähetä sähköpostia, jos käyttäjä ei ole sudoers-määrittelyssä"
+
+#~ msgid "Calling SSL_CTX_load_verify_locations() failed: %s"
+#~ msgstr "SSL_CTX_load_verify_locations() epäonnistui: %s"
+
+#~ msgid "Signed certificate file is not set in sudoers"
+#~ msgstr "Allekirjoitettua varmennetiedostoa ei ole määritelty sudoers-tiedostossa"
+
+#~ msgid "Unable to load private key into the ssl context: %s"
+#~ msgstr "Yksityistä avainta ei voi ladata ssl-kontekstiin: %s"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_connect epäonnistui: ssl_error=%d, pino=%s"
+
+#~ msgid "SSL_read failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_read epäonnistui: ssl_error=%d, pino=%s"
+
+#~ msgid "SSL_write failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_write epäonnistui: ssl_error=%d, pino=%s"
+
+#~ msgid "unknown address family: %d"
+#~ msgstr "tuntematon osoiteperhe: %d"
+
+#~ msgid "audit_failure message too long"
+#~ msgstr "audit_failure-viesti on liian pitkä"
+
+#~ msgid "unabled to parse temporary file (%s), unknown error"
+#~ msgstr "tilapäisen tiedoston (%s) jäsentäminen epäonnistui, tuntematon virhe"
+
+#~ msgid "No user or host"
+#~ msgstr "Ei käyttäjä eikä tietokone"
+
+#~ msgid "validation failure"
+#~ msgstr "kelpuutushäiriö"
+
+#~ msgid "%s/%s/timing: %s"
+#~ msgstr "%s/%s/ajoitus: %s"
+
+#~ msgid ""
+#~ "\n"
+#~ "LDAP Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "LDAP-rooli: TUNTEMATON\n"
+
+#~ msgid " Order: %s\n"
+#~ msgstr " Järjestys: %s\n"
+
+#~ msgid "unable to cache user %s, out of memory"
+#~ msgstr "käyttäjän %s laittaminen välimuistiin epäonnistui, muistia ei riittävästi"
+
+#~ msgid "unable to cache group %s, out of memory"
+#~ msgstr "ryhmän %s laittaminen välimuistiin epäonnistui, muistia ei riittävästi"
+
+#~ msgid "unable to cache group list for %s, out of memory"
+#~ msgstr "ryhmäluettelon laittaminen välimuistiin tiedostossa %s epäonnistui, muistia ei riittävästi"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: %s\n"
+#~ msgstr ""
+#~ "\n"
+#~ "SSSD-rooli: %s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "SSSD-rooli: TUNTEMATON\n"
+
+#~ msgid "timestamp path too long: %s/%s"
+#~ msgstr "aikaleimapolku on liian pitkä: %s/%s"
+
+#~ msgid "unable to stat editor (%s)"
+#~ msgstr "funktion stat editor (%s) kutsuminen epäonnistui"
+
+#~ msgid "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+#~ msgstr "sudo_ldap_conf_add_ports: hostbuf-puskuritila loppui"
+
+#~ msgid "sudo_ldap_parse_uri: out of space building hostbuf"
+#~ msgstr "sudo_ldap_parse_uri: hostbuf-puskuritila loppui"
+
+#~ msgid "sudo_ldap_build_pass1 allocation mismatch"
+#~ msgstr "sudo_ldap_build_pass1-varaustäsmäämättömyys"
+
+#~ msgid "Password:"
+#~ msgstr "Salasana:"
+
+#~ msgid "internal error: insufficient space for log line"
+#~ msgstr "sisäinen virhe: riittämättömästi tilaa lokiriville"
+
+#~ msgid "fill_args: buffer overflow"
+#~ msgstr "fill_args: puskuriylivuoto"
+
+#~ msgid "%s: unused %s_Alias %s"
+#~ msgstr "%s: käyttämätön %s_Alias %s"
+
+#~ msgid "%s owned by uid %u, should be uid %u"
+#~ msgstr "%s on uid %u:n omistama, pitäisi olla uid %u:n omistama"
+
+#~ msgid "%s writable by non-owner (0%o), should be mode 0700"
+#~ msgstr "%s on kirjoitettava ei-omistajalle (0%o), pitäisi olla tila 0700"
+
+#~ msgid "%s exists but is not a regular file (0%o)"
+#~ msgstr "%s on olemassa, mutta ei ole tavallinen tiedosto (0%o)"
+
+#~ msgid "%s writable by non-owner (0%o), should be mode 0600"
+#~ msgstr "%s on kirjoitettava ei-omistajalle (0%o), pitäisi olla tila 0600"
+
+#~ msgid "unable to remove %s, will reset to the Unix epoch"
+#~ msgstr "kohteen %s poistaminen epäonnistui, nollaa Unix-ajan"
+
+#~ msgid "unable to reset %s to the Unix epoch"
+#~ msgstr "kohteen %s nollaaminen Unix-ajaksi epäonnistui"
+
+#~ msgid "value out of range"
+#~ msgstr "arvo lukualueen ulkopuolella"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " -c, --check check-only mode\n"
+#~ " -f, --file=file specify sudoers file location\n"
+#~ " -h, --help display help message and exit\n"
+#~ " -q, --quiet less verbose (quiet) syntax error messages\n"
+#~ " -s, --strict strict syntax checking\n"
+#~ " -V, --version display version information and exit -x, --export export sudoers in JSON format"
+#~ msgstr ""
+#~ "\n"
+#~ "Valitsimet:\n"
+#~ " -c, --check vain tarkistus -tila\n"
+#~ " -f, --file=tiedosto määrittele sudoers-tiedoston sijainti\n"
+#~ " -h, --help näytä opasteteksti ja poistu\n"
+#~ " -q, --quiet vähemmän laveat (hiljaiset) syntaksivirheviestit\n"
+#~ " -s, --strict tiukka syntaksitarkistus\n"
+#~ " -V, --version näytä versiotiedot ja poistu -x, --export vie sudoers-tiedosto JSON-muodossa"
+
+#~ msgid "unable to mix ldaps and starttls"
+#~ msgstr "ldap- ja starttl-kohteiden sekoittaminen epäonnistui"
+
+#~ msgid "writing to standard output"
+#~ msgstr "kirjoitetaan vakiotulosteeseen"
+
+#~ msgid "too many parenthesized expressions, max %d"
+#~ msgstr "liian monta sulkumerkillistä lauseketta, enintään %d"
+
+#~ msgid "getaudit: failed"
+#~ msgstr "getaudit: epäonnistui"
+
+#~ msgid "getauid: failed"
+#~ msgstr "getauid: epäonnistui"
+
+#~ msgid "au_to_subject: failed"
+#~ msgstr "au_to_subject: epäonnistui"
+
+#~ msgid "au_to_exec_args: failed"
+#~ msgstr "au_to_exec_args: epäonnistui"
+
+#~ msgid "au_to_return32: failed"
+#~ msgstr "au_to_return32: epäonnistui"
+
+#~ msgid "au_to_text: failed"
+#~ msgstr "au_to_text: epäonnistui"
+
+#~ msgid "nanosleep: tv_sec %ld, tv_nsec %ld"
+#~ msgstr "nanosleep: tv_sec %ld, tv_nsec %ld"
+
+#~ msgid "pam_chauthtok: %s"
+#~ msgstr "pam_chauthtok: %s"
+
+#~ msgid "pam_authenticate: %s"
+#~ msgstr "pam_authenticate: %s"
+
+#~ msgid "getauid failed"
+#~ msgstr "getauid epäonnistui"
+
+#~ msgid "Unable to dlopen %s: %s"
+#~ msgstr "Funktion dlopen %s kutsuminen epäonnistui: %s"
+
+#~ msgid ">>> %s: %s near line %d <<<"
+#~ msgstr ">>> %s: %s lähellä riviä %d <<<"
+
+#~ msgid "unable to set locale to \"%s\", using \"C\""
+#~ msgstr "locale-asetuksen ”%s” asettaminen epäonnistui, käytetään ”C”"
+
+#~ msgid ""
+#~ " Commands:\n"
+#~ "\t"
+#~ msgstr ""
+#~ " Komennot:\n"
+#~ "\t"
+
+#~ msgid ": "
+#~ msgstr ": "
+
+#~ msgid "unable to cache uid %u (%s), already exists"
+#~ msgstr "käyttäjän uid %u (%s) laittaminen välimuistiin epäonnistui, käyttäjä on jo siellä"
+
+#~ msgid "unable to cache gid %u (%s), already exists"
+#~ msgstr "ryhmän gid %u (%s) laittaminen välimuistiin epäonnistui, ryhmä on jo siellä"
+
+#~ msgid "internal error, expand_prompt() overflow"
+#~ msgstr "sisäinen virhe, expand_prompt()-ylivuoto"
+
+#~ msgid "internal error, sudo_setenv2() overflow"
+#~ msgstr "sisäinen virhe, sudo_setenv2()-ylivuoto"
+
+#~ msgid "internal error, sudo_setenv() overflow"
+#~ msgstr "sisäinen virhe, sudo_setenv()-ylivuoto"
+
+#~ msgid "internal error, linux_audit_command() overflow"
+#~ msgstr "sisäinen virhe, linux_audit_command()-ylivuoto"
+
+#~ msgid "internal error, runas_groups overflow"
+#~ msgstr "sisäinen virhe, runas_groups-ylivuoto"
+
+#~ msgid "internal error, init_vars() overflow"
+#~ msgstr "sisäinen virhe, init_vars()-ylivuoto"
+
+# Parametri on sudoers file
+#~ msgid "fixed mode on %s"
+#~ msgstr "korjattu tila tiedostossa %s"
+
+#~ msgid "unable to fix mode on %s"
+#~ msgstr "tilan korjaaminen tiedostossa %s epäonnistui"
+
+#~ msgid "%s is mode 0%o, should be 0%o"
+#~ msgstr "%s on tila 0%o, pitäisi olla 0%o"
+
+#~ msgid "File containing dummy exec functions: %s"
+#~ msgstr "Tiedosto, joka sisältää vale-exec-funktioita: %s"
+
+#~ msgid ""
+#~ "Available options in a sudoers ``Defaults'' line:\n"
+#~ "\n"
+#~ msgstr ""
+#~ "Käytettävissä olevat valitsimet sudoers ’’Defaults’’ -rivillä:\n"
+#~ "\n"
+
+#~ msgid "%s: %.*s\n"
+#~ msgstr "%s: %.*s\n"
+
+#~ msgid "unable to get runas group vector"
+#~ msgstr "runas-ryhmävektorin hakeminen epäonnistui"
+
+#~ msgid "%s: %s_Alias `%s' references self"
+#~ msgstr "%s: %s_Alias ”%s” viittaa itseensä"
diff --git a/plugins/sudoers/po/fr.mo b/plugins/sudoers/po/fr.mo
new file mode 100644
index 0000000..818b1e0
--- /dev/null
+++ b/plugins/sudoers/po/fr.mo
Binary files differ
diff --git a/plugins/sudoers/po/fr.po b/plugins/sudoers/po/fr.po
new file mode 100644
index 0000000..be85c22
--- /dev/null
+++ b/plugins/sudoers/po/fr.po
@@ -0,0 +1,4195 @@
+# This file is put in the public domain.
+# This file is distributed under the same license as the sudo package.
+#
+# Frédéric Hantrais <fhantrais@gmail.com>, 2014, 2015, 2016.
+# Frédéric Marchal <fmarchal@perso.be>, 2023
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.9.15b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-10-19 10:02-0600\n"
+"PO-Revision-Date: 2023-10-21 14:37+0200\n"
+"Last-Translator: Frédéric Marchal <fmarchal@perso.be>\n"
+"Language-Team: French <traduc@traduc.org>\n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=(n >= 2);\n"
+
+#: confstr.sh:1 gram.y:1257 plugins/sudoers/logging.c:911
+msgid "syntax error"
+msgstr "erreur de syntaxe"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "Mot de passe de %p : "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] Mot de passe de %p : "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Mot de passe : "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** Informations de sécurité pour %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Désolé, essayez de nouveau."
+
+#: gram.y:238 gram.y:305 gram.y:314 gram.y:323 gram.y:333 gram.y:343 gram.y:367
+#: gram.y:394 gram.y:403 gram.y:411 gram.y:420 gram.y:429 gram.y:503 gram.y:513
+#: gram.y:525 gram.y:573 gram.y:582 gram.y:591 gram.y:600 gram.y:733 gram.y:742
+#: gram.y:757 gram.y:777 gram.y:796 gram.y:959 gram.y:964 gram.y:972 gram.y:986
+#: gram.y:992 gram.y:1004 gram.y:1010 gram.y:1135 gram.y:1144 gram.y:1152
+#: gram.y:1161 gram.y:1170 gram.y:1199 gram.y:1208 gram.y:1216 gram.y:1317
+#: gram.y:1447 gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:313 lib/eventlog/eventlog.c:765
+#: lib/eventlog/eventlog.c:842 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:484
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:185
+#: logsrvd/iolog_writer.c:218 logsrvd/iolog_writer.c:228
+#: logsrvd/iolog_writer.c:257 logsrvd/iolog_writer.c:278
+#: logsrvd/iolog_writer.c:290 logsrvd/iolog_writer.c:300
+#: logsrvd/iolog_writer.c:310 logsrvd/iolog_writer.c:320
+#: logsrvd/iolog_writer.c:330 logsrvd/iolog_writer.c:342
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:1057 logsrvd/logsrvd.c:1120 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:650
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1743
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:216
+#: logsrvd/logsrvd_journal.c:217 logsrvd/logsrvd_journal.c:274
+#: logsrvd/logsrvd_journal.c:279 logsrvd/logsrvd_journal.c:439
+#: logsrvd/logsrvd_journal.c:441 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:216 logsrvd/logsrvd_local.c:278
+#: logsrvd/logsrvd_local.c:279 logsrvd/logsrvd_local.c:417
+#: logsrvd/logsrvd_local.c:468 logsrvd/logsrvd_local.c:469
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:475
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/logsrvd_relay.c:446
+#: logsrvd/logsrvd_relay.c:748 logsrvd/logsrvd_relay.c:855
+#: logsrvd/sendlog.c:256 logsrvd/sendlog.c:265 logsrvd/sendlog.c:297
+#: logsrvd/sendlog.c:303 logsrvd/sendlog.c:352 logsrvd/sendlog.c:630
+#: logsrvd/sendlog.c:1822 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/bsdauth.c:154 plugins/sudoers/auth/kerb5.c:122
+#: plugins/sudoers/auth/kerb5.c:150 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/auth/sia.c:61
+#: plugins/sudoers/canon_path.c:129 plugins/sudoers/canon_path.c:161
+#: plugins/sudoers/check_aliases.c:128 plugins/sudoers/check_util.c:56
+#: plugins/sudoers/check_util.c:84 plugins/sudoers/cvtsudoers.c:132
+#: plugins/sudoers/cvtsudoers.c:176 plugins/sudoers/cvtsudoers.c:193
+#: plugins/sudoers/cvtsudoers.c:204 plugins/sudoers/cvtsudoers.c:338
+#: plugins/sudoers/cvtsudoers.c:379 plugins/sudoers/cvtsudoers.c:399
+#: plugins/sudoers/cvtsudoers.c:545 plugins/sudoers/cvtsudoers.c:698
+#: plugins/sudoers/cvtsudoers.c:716 plugins/sudoers/cvtsudoers.c:891
+#: plugins/sudoers/cvtsudoers.c:899 plugins/sudoers/cvtsudoers.c:1395
+#: plugins/sudoers/cvtsudoers.c:1399 plugins/sudoers/cvtsudoers.c:1501
+#: plugins/sudoers/cvtsudoers_csv.c:183 plugins/sudoers/cvtsudoers_csv.c:247
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:152
+#: plugins/sudoers/cvtsudoers_ldif.c:195 plugins/sudoers/cvtsudoers_ldif.c:236
+#: plugins/sudoers/cvtsudoers_ldif.c:302 plugins/sudoers/cvtsudoers_ldif.c:378
+#: plugins/sudoers/cvtsudoers_ldif.c:432 plugins/sudoers/cvtsudoers_ldif.c:440
+#: plugins/sudoers/cvtsudoers_ldif.c:451 plugins/sudoers/cvtsudoers_ldif.c:458
+#: plugins/sudoers/cvtsudoers_ldif.c:470 plugins/sudoers/cvtsudoers_ldif.c:483
+#: plugins/sudoers/cvtsudoers_ldif.c:491 plugins/sudoers/cvtsudoers_ldif.c:638
+#: plugins/sudoers/cvtsudoers_merge.c:47 plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1158
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:212
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:694 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:294 plugins/sudoers/ldap_util.c:301
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:402
+#: plugins/sudoers/log_client.c:717 plugins/sudoers/log_client.c:739
+#: plugins/sudoers/log_client.c:744 plugins/sudoers/log_client.c:1426
+#: plugins/sudoers/log_client.c:1547 plugins/sudoers/log_client.c:1670
+#: plugins/sudoers/log_client.c:1993 plugins/sudoers/log_client.c:2052
+#: plugins/sudoers/logging.c:110 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:872 plugins/sudoers/lookup.c:338
+#: plugins/sudoers/lookup.c:355 plugins/sudoers/lookup.c:374
+#: plugins/sudoers/lookup.c:393 plugins/sudoers/lookup.c:410
+#: plugins/sudoers/lookup.c:433 plugins/sudoers/lookup.c:444
+#: plugins/sudoers/match_command.c:302 plugins/sudoers/match_command.c:574
+#: plugins/sudoers/match_command.c:641 plugins/sudoers/match_command.c:737
+#: plugins/sudoers/match_command.c:785 plugins/sudoers/match_digest.c:88
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:595
+#: plugins/sudoers/parse_ldif.c:625 plugins/sudoers/parse_ldif.c:650
+#: plugins/sudoers/parse_ldif.c:708 plugins/sudoers/parse_ldif.c:725
+#: plugins/sudoers/parse_ldif.c:753 plugins/sudoers/parse_ldif.c:760
+#: plugins/sudoers/policy.c:646 plugins/sudoers/policy.c:1061
+#: plugins/sudoers/prompt.c:94 plugins/sudoers/pwutil.c:219
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:368
+#: plugins/sudoers/pwutil.c:542 plugins/sudoers/pwutil.c:607
+#: plugins/sudoers/pwutil.c:679 plugins/sudoers/pwutil.c:877
+#: plugins/sudoers/pwutil.c:967 plugins/sudoers/pwutil.c:1015
+#: plugins/sudoers/pwutil.c:1076 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:145 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1307 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:256
+#: plugins/sudoers/testsudoers.c:265 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:164 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1095
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1320
+msgid "unable to allocate memory"
+msgstr "impossible d'allouer la mémoire"
+
+#: gram.y:624
+msgid "a digest requires a path name"
+msgstr "un résumé (digest) nécessite un chemin d'accès"
+
+#: gram.y:646
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "les valeurs de « CWD » doivent commencer par « / », « ~ » ou « * »"
+
+#: gram.y:652
+msgid "\"CWD\" path too long"
+msgstr "chemin trop long pour « CWD »"
+
+#: gram.y:662
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "les valeurs de « CHROOT » doivent commencer par « / », « ~ » ou « * »"
+
+#: gram.y:668
+msgid "\"CHROOT\" path too long"
+msgstr "chemin trop long pour « CHROOT »"
+
+#: gram.y:817
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "erreur de syntaxe, le mot réservé %s est utilisé comme un nom de synonyme"
+
+#: gram.y:840
+msgid "invalid notbefore value"
+msgstr "valeur « notbefore » (pas avant) invalide"
+
+#: gram.y:849
+msgid "invalid notafter value"
+msgstr "valeur « notafter » (pas après) invalide"
+
+#: gram.y:859 plugins/sudoers/policy.c:390
+msgid "timeout value too large"
+msgstr "valeur trop grande pour le délai d'expiration"
+
+#: gram.y:861 plugins/sudoers/policy.c:392
+msgid "invalid timeout value"
+msgstr "valeur invalide pour le délai d'expiration"
+
+#: gram.y:982 plugins/sudoers/sudoers.c:1162
+msgid "command too long"
+msgstr "commande trop longue"
+
+#: gram.y:1016
+msgid "expected a fully-qualified path name"
+msgstr "nom de chemin totalement défini attendu"
+
+#: gram.y:1261
+#, c-format
+msgid "%s:%d:%zu: %s\n"
+msgstr "%s:%d:%zu: %s\n"
+
+#: gram.y:1315
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "L'alias « %s » est déjà défini"
+
+#: gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:765 lib/eventlog/eventlog.c:838
+#: lib/eventlog/eventlog.c:841 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:483
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:232
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:174
+#: logsrvd/iolog_writer.c:184 logsrvd/iolog_writer.c:197
+#: logsrvd/iolog_writer.c:217 logsrvd/iolog_writer.c:227
+#: logsrvd/iolog_writer.c:246 logsrvd/iolog_writer.c:256
+#: logsrvd/iolog_writer.c:267 logsrvd/iolog_writer.c:277
+#: logsrvd/iolog_writer.c:289 logsrvd/iolog_writer.c:299
+#: logsrvd/iolog_writer.c:309 logsrvd/iolog_writer.c:319
+#: logsrvd/iolog_writer.c:329 logsrvd/iolog_writer.c:341
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:530
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:668
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:1131
+#: logsrvd/logsrvd.c:1446 logsrvd/logsrvd.c:1453 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:649
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1742
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:125
+#: logsrvd/logsrvd_journal.c:216 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:250 logsrvd/logsrvd_journal.c:258
+#: logsrvd/logsrvd_journal.c:287 logsrvd/logsrvd_journal.c:291
+#: logsrvd/logsrvd_journal.c:439 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:278 logsrvd/logsrvd_local.c:468
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:493
+#: logsrvd/logsrvd_queue.c:158 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/sendlog.c:256 logsrvd/sendlog.c:265
+#: logsrvd/sendlog.c:297 logsrvd/sendlog.c:303 logsrvd/sendlog.c:352
+#: logsrvd/sendlog.c:630 logsrvd/sendlog.c:1523 logsrvd/sendlog.c:1530
+#: logsrvd/sendlog.c:1753 logsrvd/sendlog.c:1822 logsrvd/tls_init.c:305
+#: logsrvd/tls_init.c:329 logsrvd/tls_init.c:340 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/pam.c:518 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/canon_path.c:129
+#: plugins/sudoers/canon_path.c:161 plugins/sudoers/check_aliases.c:128
+#: plugins/sudoers/check_util.c:56 plugins/sudoers/check_util.c:84
+#: plugins/sudoers/cvtsudoers.c:132 plugins/sudoers/cvtsudoers.c:175
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:203
+#: plugins/sudoers/cvtsudoers.c:337 plugins/sudoers/cvtsudoers.c:544
+#: plugins/sudoers/cvtsudoers.c:697 plugins/sudoers/cvtsudoers.c:715
+#: plugins/sudoers/cvtsudoers.c:891 plugins/sudoers/cvtsudoers.c:898
+#: plugins/sudoers/cvtsudoers.c:1395 plugins/sudoers/cvtsudoers.c:1399
+#: plugins/sudoers/cvtsudoers.c:1501 plugins/sudoers/cvtsudoers_csv.c:182
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:151 plugins/sudoers/cvtsudoers_ldif.c:194
+#: plugins/sudoers/cvtsudoers_ldif.c:235 plugins/sudoers/cvtsudoers_ldif.c:301
+#: plugins/sudoers/cvtsudoers_ldif.c:377 plugins/sudoers/cvtsudoers_ldif.c:431
+#: plugins/sudoers/cvtsudoers_ldif.c:439 plugins/sudoers/cvtsudoers_ldif.c:450
+#: plugins/sudoers/cvtsudoers_ldif.c:457 plugins/sudoers/cvtsudoers_ldif.c:469
+#: plugins/sudoers/cvtsudoers_ldif.c:482 plugins/sudoers/cvtsudoers_ldif.c:490
+#: plugins/sudoers/cvtsudoers_ldif.c:637 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51 plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1157
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:211
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:693 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:293 plugins/sudoers/ldap_util.c:300
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:228
+#: plugins/sudoers/log_client.c:250 plugins/sudoers/log_client.c:264
+#: plugins/sudoers/log_client.c:402 plugins/sudoers/log_client.c:717
+#: plugins/sudoers/log_client.c:739 plugins/sudoers/log_client.c:744
+#: plugins/sudoers/log_client.c:1426 plugins/sudoers/log_client.c:1547
+#: plugins/sudoers/log_client.c:1670 plugins/sudoers/log_client.c:1993
+#: plugins/sudoers/log_client.c:2052 plugins/sudoers/logging.c:110
+#: plugins/sudoers/logging.c:189 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:755 plugins/sudoers/logging.c:872
+#: plugins/sudoers/logging.c:925 plugins/sudoers/logging.c:932
+#: plugins/sudoers/lookup.c:337 plugins/sudoers/lookup.c:354
+#: plugins/sudoers/lookup.c:373 plugins/sudoers/lookup.c:392
+#: plugins/sudoers/lookup.c:409 plugins/sudoers/lookup.c:432
+#: plugins/sudoers/lookup.c:443 plugins/sudoers/match_command.c:301
+#: plugins/sudoers/match_command.c:573 plugins/sudoers/match_command.c:640
+#: plugins/sudoers/match_command.c:737 plugins/sudoers/match_command.c:784
+#: plugins/sudoers/match_digest.c:88 plugins/sudoers/parse_ldif.c:152
+#: plugins/sudoers/parse_ldif.c:183 plugins/sudoers/parse_ldif.c:252
+#: plugins/sudoers/parse_ldif.c:260 plugins/sudoers/parse_ldif.c:265
+#: plugins/sudoers/parse_ldif.c:341 plugins/sudoers/parse_ldif.c:352
+#: plugins/sudoers/parse_ldif.c:379 plugins/sudoers/parse_ldif.c:396
+#: plugins/sudoers/parse_ldif.c:408 plugins/sudoers/parse_ldif.c:412
+#: plugins/sudoers/parse_ldif.c:426 plugins/sudoers/parse_ldif.c:484
+#: plugins/sudoers/parse_ldif.c:595 plugins/sudoers/parse_ldif.c:624
+#: plugins/sudoers/parse_ldif.c:649 plugins/sudoers/parse_ldif.c:707
+#: plugins/sudoers/parse_ldif.c:724 plugins/sudoers/parse_ldif.c:752
+#: plugins/sudoers/parse_ldif.c:759 plugins/sudoers/policy.c:157
+#: plugins/sudoers/policy.c:166 plugins/sudoers/policy.c:175
+#: plugins/sudoers/policy.c:204 plugins/sudoers/policy.c:374
+#: plugins/sudoers/policy.c:390 plugins/sudoers/policy.c:392
+#: plugins/sudoers/policy.c:430 plugins/sudoers/policy.c:439
+#: plugins/sudoers/policy.c:448 plugins/sudoers/policy.c:457
+#: plugins/sudoers/policy.c:493 plugins/sudoers/policy.c:502
+#: plugins/sudoers/policy.c:511 plugins/sudoers/policy.c:520
+#: plugins/sudoers/policy.c:529 plugins/sudoers/policy.c:538
+#: plugins/sudoers/policy.c:547 plugins/sudoers/policy.c:646
+#: plugins/sudoers/policy.c:1061 plugins/sudoers/prompt.c:94
+#: plugins/sudoers/pwutil.c:219 plugins/sudoers/pwutil.c:290
+#: plugins/sudoers/pwutil.c:368 plugins/sudoers/pwutil.c:542
+#: plugins/sudoers/pwutil.c:607 plugins/sudoers/pwutil.c:679
+#: plugins/sudoers/pwutil.c:877 plugins/sudoers/pwutil.c:967
+#: plugins/sudoers/pwutil.c:1015 plugins/sudoers/pwutil.c:1076
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1306 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:255
+#: plugins/sudoers/testsudoers.c:264 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:163 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1094
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1309 toke.l:1320
+#, c-format
+msgid "%s: %s"
+msgstr "%s : %s"
+
+#: lib/eventlog/eventlog.c:304
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "duplication (dup) de stdin impossible : %m"
+
+#: lib/eventlog/eventlog.c:346
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "exécution de %s impossible : %m"
+
+#: lib/eventlog/eventlog.c:394 plugins/sudoers/auth/aix_auth.c:199
+msgid "unable to fork"
+msgstr "création du processus fils impossible"
+
+#: lib/eventlog/eventlog.c:404 lib/eventlog/eventlog.c:471
+#, c-format
+msgid "unable to fork: %m"
+msgstr "création du processus fils impossible : %m"
+
+#: lib/eventlog/eventlog.c:461
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "ouverture du tube impossible : %m"
+
+#: lib/eventlog/eventlog.c:1000
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:1029
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (suite de la commande) %s"
+
+#: lib/eventlog/parse_json.c:175
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "JSON_STRING attendue, %d obtenu"
+
+#: lib/eventlog/parse_json.c:180
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY trop grand"
+
+#: lib/eventlog/parse_json.c:506
+msgid "missing double quote in name"
+msgstr "guillemet manquante dans le nom"
+
+#: lib/eventlog/parse_json.c:624
+msgid "missing JSON_OBJECT"
+msgstr "JSON_OBJECT manquant"
+
+#: lib/eventlog/parse_json.c:628
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "JSON_OBJECT attendu, %d obtenu"
+
+#: lib/eventlog/parse_json.c:762
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "pile json épuisée (max %u trames)"
+
+#: lib/eventlog/parse_json.c:840
+msgid "objects must consist of name:value pairs"
+msgstr "les objets doivent être des paires nom:valeur"
+
+#: lib/eventlog/parse_json.c:845 lib/eventlog/parse_json.c:876
+#: lib/eventlog/parse_json.c:920 lib/eventlog/parse_json.c:942
+#: lib/eventlog/parse_json.c:964 lib/eventlog/parse_json.c:986
+#: lib/eventlog/parse_json.c:1008
+msgid "missing separator between values"
+msgstr "séparateur manquant entre les valeurs"
+
+#: lib/eventlog/parse_json.c:860 lib/eventlog/parse_json.c:1034
+msgid "unmatched close brace"
+msgstr "accolade fermante non appariée"
+
+#: lib/eventlog/parse_json.c:871
+msgid "unexpected array"
+msgstr "tableau attendu"
+
+#: lib/eventlog/parse_json.c:891 lib/eventlog/parse_json.c:1037
+msgid "unmatched close bracket"
+msgstr "crochet fermant non apparié"
+
+#: lib/eventlog/parse_json.c:902
+msgid "unexpected string"
+msgstr "chaîne inattendue"
+
+#: lib/eventlog/parse_json.c:913
+msgid "missing colon after name"
+msgstr "deux points manquants après le nom"
+
+#: lib/eventlog/parse_json.c:934 lib/eventlog/parse_json.c:956
+msgid "unexpected boolean"
+msgstr "booléen inattendu"
+
+#: lib/eventlog/parse_json.c:978
+msgid "unexpected null"
+msgstr "nul inattendu"
+
+#: lib/eventlog/parse_json.c:999
+msgid "unexpected number"
+msgstr "nombre inattendu"
+
+#: lib/eventlog/parse_json.c:1045
+msgid "parse error"
+msgstr "erreur d'analyse grammaticale"
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1290
+#: plugins/sudoers/sudoreplay.c:1291 plugins/sudoers/sudoreplay.c:1587
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr "expression régulière « %s » invalide : %s"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: fichier de journalisation incorrect"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: il manque le champ d'horodatage"
+
+#: lib/iolog/iolog_legacy.c:90
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: horodatage %s : %s"
+
+#: lib/iolog/iolog_legacy.c:97
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: il manque le champ utilisateur"
+
+#: lib/iolog/iolog_legacy.c:108
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: il manque le champ précisant l'utilisateur effectif (runas)"
+
+#: lib/iolog/iolog_legacy.c:119
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: il manque le champ précisant le groupe effectif (runas)"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s existe mais n'est pas un répertoire (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:124 lib/iolog/iolog_mkdtemp.c:80
+#: logsrvd/iolog_writer.c:795 plugins/sudoers/timestamp.c:218
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "création du répertoire (mkdir) %s impossible"
+
+#: lib/iolog/iolog_mkdtemp.c:85 plugins/sudoers/visudo.c:769
+#: plugins/sudoers/visudo.c:803 plugins/sudoers/visudo.c:809
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "impossible de changer le mode de %s pour lui affecter 0%o"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "erreur de lecture dans le fichier de timing : %s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "ligne invalide dans le fichier de timing : %s"
+
+#: logsrvd/iolog_writer.c:65
+#, c-format
+msgid "%s: protocol error: NULL key"
+msgstr "%s : erreur de protocole : clé NULL"
+
+#: logsrvd/iolog_writer.c:69
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s : erreur de protocole : mauvais type pour %s"
+
+#: logsrvd/iolog_writer.c:74 logsrvd/logsrvd_local.c:109
+#: logsrvd/logsrvd_local.c:123 logsrvd/logsrvd_local.c:131
+#: logsrvd/logsrvd_local.c:149
+#, c-format
+msgid "%s: protocol error: NULL value found in %s"
+msgstr "%s : erreur de protocole : valeur NULL trouvée dans %s"
+
+#: logsrvd/iolog_writer.c:141 plugins/sudoers/logging.c:1024
+#: plugins/sudoers/policy.c:613
+msgid "unable to generate UUID"
+msgstr "impossible de générer le UUID"
+
+#: logsrvd/iolog_writer.c:354 logsrvd/iolog_writer.c:359
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:369
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s : erreur de protocole : %s est manquant dans AcceptMessage"
+
+#: logsrvd/iolog_writer.c:430
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s : impossible de formater l'id de session"
+
+#: logsrvd/iolog_writer.c:444 logsrvd/iolog_writer.c:458
+#: logsrvd/iolog_writer.c:472 logsrvd/iolog_writer.c:487
+#: logsrvd/iolog_writer.c:501 logsrvd/iolog_writer.c:515
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s : %s n'est pas défini"
+
+#: logsrvd/iolog_writer.c:551 logsrvd/iolog_writer.c:558
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr "impossible de développer le chemin iolog %s"
+
+#: logsrvd/iolog_writer.c:576
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr "impossible de créer le chemin iolog %s"
+
+#: logsrvd/iolog_writer.c:606
+#, c-format
+msgid "invalid iofd %d"
+msgstr "iofd %d invalide"
+
+#: logsrvd/iolog_writer.c:626
+#, c-format
+msgid "error closing iofd %u: %s"
+msgstr "erreur à la fermeture du iofd %u : %s"
+
+#: logsrvd/iolog_writer.c:647
+#, c-format
+msgid "error flushing iofd %u: %s"
+msgstr "erreur lors de la vidange du iofd %u : %s"
+
+#: logsrvd/iolog_writer.c:765
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "journal E/S %s invalide : il est fait référence à %s alors qu'il n'est pas présent"
+
+#: logsrvd/iolog_writer.c:777 logsrvd/logsrvd_journal.c:391
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "%s : impossible de trouver le point de redémarrage [%lld, %ld]"
+
+#: logsrvd/iolog_writer.c:799 logsrvd/logsrvd_journal.c:434
+#: logsrvd/logsrvd_queue.c:115 logsrvd/tls_init.c:256
+#: plugins/sudoers/check.c:285 plugins/sudoers/cvtsudoers.c:758
+#: plugins/sudoers/cvtsudoers.c:780 plugins/sudoers/cvtsudoers.c:1461
+#: plugins/sudoers/cvtsudoers_csv.c:697 plugins/sudoers/cvtsudoers_json.c:902
+#: plugins/sudoers/cvtsudoers_ldif.c:711 plugins/sudoers/sudoers.c:1291
+#: plugins/sudoers/sudoers.c:1317 plugins/sudoers/sudoreplay.c:1497
+#: plugins/sudoers/timestamp.c:478 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:990
+#, c-format
+msgid "unable to open %s"
+msgstr "ouverture de %s impossible"
+
+#: logsrvd/iolog_writer.c:811 logsrvd/logsrv_util.c:111
+#: logsrvd/logsrv_util.c:118 plugins/sudoers/sudoreplay.c:355
+#: plugins/sudoers/sudoreplay.c:361
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "ouverture de %si/%s impossible"
+
+#: logsrvd/iolog_writer.c:824
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "impossible de copier %s/%s vers %s/%s : %s"
+
+#: logsrvd/iolog_writer.c:853 logsrvd/logsrvd_journal.c:198
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "impossible de renommer %s en %s"
+
+#: logsrvd/logsrv_util.c:153 logsrvd/logsrv_util.c:182
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s : impossible de trouver le point de redémarrage [%lld, %ld]"
+
+#: logsrvd/logsrv_util.c:165
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "fichier du journal E/S %s/%s manquant"
+
+#: logsrvd/logsrv_util.c:172
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s : impossible d'examiner vers l'avant de %zu"
+
+#: logsrvd/logsrvd.c:271 logsrvd/logsrvd_queue.c:135
+msgid "unable to connect to relay"
+msgstr "impossible de se connecter au relai"
+
+#: logsrvd/logsrvd.c:338 logsrvd/logsrvd_relay.c:847
+#, c-format
+msgid "server message too large: %zu"
+msgstr "message serveur trop grand : %zu"
+
+#: logsrvd/logsrvd.c:430 logsrvd/logsrvd.c:553 logsrvd/logsrvd.c:639
+#: logsrvd/logsrvd.c:881 logsrvd/logsrvd.c:895 logsrvd/logsrvd.c:1056
+#: logsrvd/logsrvd.c:1181 logsrvd/logsrvd.c:1354 logsrvd/logsrvd.c:1372
+#: logsrvd/logsrvd.c:1471 logsrvd/logsrvd.c:1596 logsrvd/logsrvd.c:1783
+#: logsrvd/logsrvd_journal.c:503 logsrvd/logsrvd_local.c:238
+#: logsrvd/logsrvd_queue.c:164 logsrvd/logsrvd_relay.c:172
+#: logsrvd/logsrvd_relay.c:249 logsrvd/logsrvd_relay.c:253
+#: logsrvd/logsrvd_relay.c:391 logsrvd/logsrvd_relay.c:583
+#: logsrvd/logsrvd_relay.c:747 logsrvd/logsrvd_relay.c:1137
+#: logsrvd/sendlog.c:1308 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:216 plugins/sudoers/audit.c:281
+#: plugins/sudoers/iolog.c:1041 plugins/sudoers/iolog.c:1175
+#: plugins/sudoers/iolog.c:1274 plugins/sudoers/log_client.c:121
+#: plugins/sudoers/log_client.c:343 plugins/sudoers/log_client.c:359
+#: plugins/sudoers/log_client.c:407 plugins/sudoers/log_client.c:613
+#: plugins/sudoers/log_client.c:620 plugins/sudoers/log_client.c:1114
+#: plugins/sudoers/log_client.c:1395 plugins/sudoers/log_client.c:1436
+#: plugins/sudoers/log_client.c:1444 plugins/sudoers/log_client.c:1603
+#: plugins/sudoers/log_client.c:1728 plugins/sudoers/log_client.c:2060
+#: plugins/sudoers/log_client.c:2068 plugins/sudoers/logging.c:148
+#: plugins/sudoers/logging.c:206 plugins/sudoers/sudoreplay.c:519
+#: plugins/sudoers/sudoreplay.c:566 plugins/sudoers/sudoreplay.c:808
+#: plugins/sudoers/sudoreplay.c:920 plugins/sudoers/sudoreplay.c:1011
+#: plugins/sudoers/sudoreplay.c:1026 plugins/sudoers/sudoreplay.c:1033
+#: plugins/sudoers/sudoreplay.c:1040 plugins/sudoers/sudoreplay.c:1047
+#: plugins/sudoers/sudoreplay.c:1054 plugins/sudoers/sudoreplay.c:1182
+msgid "unable to add event to queue"
+msgstr "impossible d'ajouter l'événement à la queue"
+
+#: logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:491 logsrvd/logsrvd.c:523
+#: logsrvd/logsrvd.c:577 logsrvd/logsrvd.c:656 logsrvd/logsrvd.c:692
+#: logsrvd/logsrvd.c:728 logsrvd/logsrvd.c:764 logsrvd/logsrvd_relay.c:512
+#: logsrvd/logsrvd_relay.c:545
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr "état %d inattendu pour %s"
+
+#: logsrvd/logsrvd.c:455 logsrvd/logsrvd.c:492 logsrvd/logsrvd.c:524
+#: logsrvd/logsrvd.c:578 logsrvd/logsrvd.c:657 logsrvd/logsrvd.c:693
+#: logsrvd/logsrvd.c:729 logsrvd/logsrvd.c:765 logsrvd/logsrvd_relay.c:514
+#: logsrvd/logsrvd_relay.c:547
+msgid "state machine error"
+msgstr "erreur de la machine à états"
+
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:462
+msgid "invalid AcceptMessage"
+msgstr "AcceptMessage invalide"
+
+#: logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:499
+msgid "invalid RejectMessage"
+msgstr "RejectMessage invalide"
+
+#: logsrvd/logsrvd.c:530 logsrvd/logsrvd.c:531
+msgid "invalid ExitMessage"
+msgstr "ExitMessage invalide"
+
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:585
+msgid "invalid RestartMessage"
+msgstr "RestartMessage invalide"
+
+#: logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:620
+msgid "invalid AlertMessage"
+msgstr "AlertMessage invalide"
+
+#: logsrvd/logsrvd.c:661 logsrvd/logsrvd.c:697 logsrvd/logsrvd.c:733
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s : IoBuffer inattendu"
+
+#: logsrvd/logsrvd.c:662 logsrvd/logsrvd.c:698 logsrvd/logsrvd.c:734
+msgid "protocol error"
+msgstr "erreur protocole"
+
+#: logsrvd/logsrvd.c:668 logsrvd/logsrvd.c:669
+msgid "invalid IoBuffer"
+msgstr "IoBuffer invalide"
+
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:705
+msgid "invalid ChangeWindowSize"
+msgstr "ChangeWindowSize invalide"
+
+#: logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:741
+msgid "invalid CommandSuspend"
+msgstr "CommandSuspend invalide"
+
+#: logsrvd/logsrvd.c:790 logsrvd/logsrvd_journal.c:302
+#: logsrvd/logsrvd_relay.c:654 logsrvd/sendlog.c:1207
+#: plugins/sudoers/log_client.c:1593
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "impossible de décompresser %s avec une taille de %zu"
+
+#: logsrvd/logsrvd.c:835 logsrvd/logsrvd_journal.c:376
+#: logsrvd/logsrvd_relay.c:678
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "valeur type_case %d inattendue dans %s de %s"
+
+#: logsrvd/logsrvd.c:837
+msgid "unrecognized ClientMessage type"
+msgstr "type de ClientMessage non reconnu"
+
+#: logsrvd/logsrvd.c:927
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "délai d'attente expiré durant l'écriture vers le client %s"
+
+#: logsrvd/logsrvd.c:932 logsrvd/logsrvd_relay.c:919 logsrvd/sendlog.c:1413
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr "tampon d'écriture manquant pour le client %s"
+
+#: logsrvd/logsrvd.c:1027
+#, c-format
+msgid "timed out reading from client %s"
+msgstr "délai d'attente expiré durant la lecture depuis le client %s"
+
+#: logsrvd/logsrvd.c:1068 logsrvd/logsrvd_relay.c:782
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr "Fin de fichier reçu de %s sans suivre la procédure d'arrêt TLS"
+
+#: logsrvd/logsrvd.c:1112 logsrvd/logsrvd_relay.c:205 logsrvd/sendlog.c:336
+#: plugins/sudoers/log_client.c:723
+#, c-format
+msgid "client message too large: %zu"
+msgstr "message client trop grand : %zu"
+
+#: logsrvd/logsrvd.c:1113 logsrvd/logsrvd_journal.c:259
+#: logsrvd/logsrvd_journal.c:260
+msgid "client message too large"
+msgstr "message client trop grand"
+
+#: logsrvd/logsrvd.c:1131 logsrvd/logsrvd.c:1132
+msgid "invalid ClientMessage"
+msgstr "ClientMessage invalide"
+
+#: logsrvd/logsrvd.c:1432
+msgid "unable to get remote IP addr"
+msgstr "impossible d'obtenir l'adresse IP distante"
+
+#: logsrvd/logsrvd.c:1463 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:281
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "Impossible d'attacher les données utilisateur à l'objet ssl : %s"
+
+#: logsrvd/logsrvd.c:1646 logsrvd/logsrvd.c:2007
+msgid "unable to setup listen socket"
+msgstr "configuration du socket d'écoute impossible"
+
+#: logsrvd/logsrvd.c:1766
+#, c-format
+msgid "unexpected signal %d"
+msgstr "signal %d inattendu"
+
+#: logsrvd/logsrvd.c:1909
+msgid "sudo log server"
+msgstr "serveur de journalisation de sudo"
+
+#: logsrvd/logsrvd.c:1911 logsrvd/sendlog.c:126
+msgid "Options:"
+msgstr "Options :"
+
+#: logsrvd/logsrvd.c:1913
+msgid "path to configuration file"
+msgstr "chemin du fichier de configuration"
+
+#: logsrvd/logsrvd.c:1915 logsrvd/sendlog.c:128
+msgid "display help message and exit"
+msgstr "afficher le message d'aide et quitter"
+
+#: logsrvd/logsrvd.c:1917
+msgid "do not fork, run in the foreground"
+msgstr "ne pas cloner, exécuter à l'avant plan"
+
+#: logsrvd/logsrvd.c:1919
+msgid "percent chance connections will drop"
+msgstr "pourcentage de chance que les connections soient abandonnées"
+
+#: logsrvd/logsrvd.c:1921 logsrvd/sendlog.c:158
+msgid "display version information and exit"
+msgstr "afficher l'information de version et quitter"
+
+#: logsrvd/logsrvd.c:1971 logsrvd/sendlog.c:1722
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "Version 1.3 ou supérieure de Protobuf-C requise"
+
+#: logsrvd/logsrvd.c:1987
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "valeur d'abandon aléatoire invalide : %s"
+
+#: logsrvd/logsrvd.c:1990 logsrvd/sendlog.c:1776
+#: plugins/sudoers/cvtsudoers.c:250 plugins/sudoers/sudoreplay.c:294
+#: plugins/sudoers/visudo.c:181
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s version %s\n"
+
+#: logsrvd/logsrvd_conf.c:422 plugins/sudoers/check.c:69
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/sudoers.c:419 plugins/sudoers/sudoers.c:929
+#: plugins/sudoers/sudoers.c:1034 plugins/sudoers/sudoers.c:1424
+#: plugins/sudoers/testsudoers.c:169 plugins/sudoers/testsudoers.c:285
+#: plugins/sudoers/testsudoers.c:459
+#, c-format
+msgid "unknown user %s"
+msgstr "utilisateur %s inconnu"
+
+#: logsrvd/logsrvd_conf.c:439 plugins/sudoers/iolog.c:148
+#: plugins/sudoers/sudoers.c:425 plugins/sudoers/sudoers.c:1458
+#: plugins/sudoers/testsudoers.c:483
+#, c-format
+msgid "unknown group %s"
+msgstr "groupe %s inconnu"
+
+#: logsrvd/logsrvd_conf.c:457
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr "impossible d'analyser le mode iolog %s"
+
+#: logsrvd/logsrvd_conf.c:474 logsrvd/logsrvd_conf.c:1243
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "valeur invalide pour %s : %s"
+
+#: logsrvd/logsrvd_conf.c:527
+msgid "TLS not supported"
+msgstr "TLS non supporté"
+
+#: logsrvd/logsrvd_conf.c:549
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:622 logsrvd/logsrvd_conf.c:1032
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s  n'est pas un chemin totalement défini"
+
+#: logsrvd/logsrvd_conf.c:951 logsrvd/logsrvd_conf.c:967
+#: logsrvd/logsrvd_conf.c:1676
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "catégorie syslog %s inconnue"
+
+#: logsrvd/logsrvd_conf.c:983 logsrvd/logsrvd_conf.c:999
+#: logsrvd/logsrvd_conf.c:1015 logsrvd/logsrvd_conf.c:1680
+#: logsrvd/logsrvd_conf.c:1684 logsrvd/logsrvd_conf.c:1688
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "priorité syslog %s inconnue"
+
+#: logsrvd/logsrvd_conf.c:1197
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d « [ » sans correspondant : %s"
+
+#: logsrvd/logsrvd_conf.c:1203
+#, c-format
+msgid "%s:%d garbage after ']': %s"
+msgstr "%s:%d charabia après « ] » : %s"
+
+#: logsrvd/logsrvd_conf.c:1215
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s:%d section de configuration invalide : %s"
+
+#: logsrvd/logsrvd_conf.c:1223
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d ligne de configuration invalide : %s"
+
+#: logsrvd/logsrvd_conf.c:1229
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d nom de section attendu : %s"
+
+#: logsrvd/logsrvd_conf.c:1251
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] clé illégale : %s"
+
+#: logsrvd/logsrvd_conf.c:1281 plugins/sudoers/cvtsudoers.c:273
+#: plugins/sudoers/logging.c:1076
+#, c-format
+msgid "unable to open log file %s"
+msgstr "ouverture du fichier de journalisation %s impossible"
+
+#: logsrvd/logsrvd_conf.c:1763
+msgid "unable to initialize server TLS context"
+msgstr "impossible d'initialiser le contexte TLS du serveur : %s"
+
+#: logsrvd/logsrvd_conf.c:1783
+msgid "unable to initialize relay TLS context"
+msgstr "impossible d'initialiser le contexte TLS du relai : %s"
+
+#: logsrvd/logsrvd_journal.c:149 logsrvd/logsrvd_journal.c:430
+#: logsrvd/logsrvd_journal.c:435
+msgid "unable to create journal file"
+msgstr "impossible de créer le fichier de journalisation"
+
+#: logsrvd/logsrvd_journal.c:153 logsrvd/logsrvd_queue.c:109
+#: plugins/sudoers/visudo.c:1046
+#, c-format
+msgid "unable to lock %s"
+msgstr "impossible de verrouiller %s"
+
+#: logsrvd/logsrvd_journal.c:156
+msgid "unable to lock journal file"
+msgstr "verrouillage du fichier de journalisation impossible : %s"
+
+#: logsrvd/logsrvd_journal.c:164
+msgid "unable to open journal file"
+msgstr "impossible d'ouvrir le fichier de journalisation"
+
+#: logsrvd/logsrvd_journal.c:185 logsrvd/logsrvd_journal.c:466
+#: logsrvd/logsrvd_journal.c:471
+msgid "unable to write journal file"
+msgstr "impossible d'écrire le fichier de journalisation"
+
+#: logsrvd/logsrvd_journal.c:193 logsrvd/logsrvd_journal.c:200
+msgid "unable to rename journal file"
+msgstr "impossible de renommer le fichier de journalisation"
+
+#: logsrvd/logsrvd_journal.c:247 logsrvd/logsrvd_journal.c:248
+#: logsrvd/logsrvd_journal.c:288 logsrvd/logsrvd_journal.c:289
+msgid "unexpected EOF reading journal file"
+msgstr "fin de fichier inattendue en lisant le fichier de journalisation"
+
+#: logsrvd/logsrvd_journal.c:251 logsrvd/logsrvd_journal.c:252
+#: logsrvd/logsrvd_journal.c:292 logsrvd/logsrvd_journal.c:293
+msgid "error reading journal file"
+msgstr "erreur de lecture dans le fichier de journalisation"
+
+#: logsrvd/logsrvd_journal.c:304 logsrvd/logsrvd_journal.c:390
+msgid "invalid journal file, unable to restart"
+msgstr "fichier de journalisation invalide, impossible de redémarrer"
+
+#: logsrvd/logsrvd_journal.c:449
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "impossible de déplacer le pointeur vers [%lld, %ld] dans le fichier de journalisation %s"
+
+#: logsrvd/logsrvd_local.c:166
+#, c-format
+msgid "unexpected value_case %d in %s from %s"
+msgstr "valeur value_case %d inattendue dans %s de %s"
+
+#: logsrvd/logsrvd_local.c:194
+msgid "error parsing AcceptMessage"
+msgstr "erreur de l'analyse de AcceptMessage"
+
+#: logsrvd/logsrvd_local.c:205
+msgid "error creating I/O log"
+msgstr "erreur lors de la création du journal des E/S"
+
+#: logsrvd/logsrvd_local.c:228
+msgid "error logging accept event"
+msgstr "erreur en écrivant l'événement d'acceptation dans le journal"
+
+#: logsrvd/logsrvd_local.c:267
+msgid "error parsing RejectMessage"
+msgstr "erreur de l'analyse de RejectMessage"
+
+#: logsrvd/logsrvd_local.c:291
+msgid "error logging reject event"
+msgstr "erreur en écrivant l'événement de rejet dans le journal"
+
+#: logsrvd/logsrvd_local.c:427 logsrvd/logsrvd_local.c:437
+msgid "error logging exit event"
+msgstr "erreur lors de l'écriture de l'événement de sortie dans le journal"
+
+#: logsrvd/logsrvd_local.c:494 logsrvd/logsrvd_local.c:495
+msgid "log is already complete, cannot be restarted"
+msgstr "l'enregistrement du journal est déjà terminé, impossible de redémarrer"
+
+#: logsrvd/logsrvd_local.c:525
+msgid "unable to restart log"
+msgstr "impossible de redémarrer l'enregistrement du journal"
+
+#: logsrvd/logsrvd_local.c:541
+msgid "error parsing AlertMessage"
+msgstr "erreur de l'analyse de AlertMessage"
+
+#: logsrvd/logsrvd_local.c:551
+msgid "error logging alert event"
+msgstr "erreur lors de l'écriture de l'événement d'alerte dans le journal"
+
+#: logsrvd/logsrvd_local.c:587 logsrvd/logsrvd_local.c:650
+#: logsrvd/logsrvd_local.c:685
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr "impossible de formater le tampon de minutage, longueur %d"
+
+#: logsrvd/logsrvd_local.c:601 logsrvd/logsrvd_local.c:609
+#: logsrvd/logsrvd_local.c:657 logsrvd/logsrvd_local.c:692
+#: plugins/sudoers/sudoreplay.c:344 toke.l:981 toke.l:984
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s : %s"
+
+#: logsrvd/logsrvd_local.c:620
+msgid "randomly dropping connection"
+msgstr "connexion abandonnée aléatoirement"
+
+#: logsrvd/logsrvd_local.c:632
+msgid "error writing IoBuffer"
+msgstr "erreur d'écriture dans IoBuffer"
+
+#: logsrvd/logsrvd_local.c:667
+msgid "error writing ChangeWindowSize"
+msgstr "erreur de l'écriture de ChangeWindowSize"
+
+#: logsrvd/logsrvd_local.c:702
+msgid "error writing CommandSuspend"
+msgstr "erreur de l'écriture de CommandSuspend"
+
+#: logsrvd/logsrvd_relay.c:437
+msgid "TLS handshake with relay host failed"
+msgstr "la négociation TLS avec l'hôte relai a échouée"
+
+#: logsrvd/logsrvd_relay.c:465
+msgid "unable to connect to relay host"
+msgstr "impossible de se connecter à l'hôte relai"
+
+#: logsrvd/logsrvd_relay.c:520
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s : ServerHello invalide, le server_id manque"
+
+#: logsrvd/logsrvd_relay.c:522 logsrvd/sendlog.c:1111
+#: plugins/sudoers/log_client.c:1479
+msgid "invalid ServerHello"
+msgstr "ServerHello invalide"
+
+#: logsrvd/logsrvd_relay.c:681
+msgid "unrecognized ServerMessage type"
+msgstr "type de ServerMessage non reconnu"
+
+#: logsrvd/logsrvd_relay.c:710
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr "délai d'attente expiré durant la lecture depuis le relai %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:712
+msgid "timeout reading from relay"
+msgstr "délai d'attente expiré durant la lecture depuis le relai"
+
+#: logsrvd/logsrvd_relay.c:767
+msgid "relay host name does not match certificate"
+msgstr "le nom de l'hôte relai ne correspond pas au certificat"
+
+#: logsrvd/logsrvd_relay.c:773 logsrvd/logsrvd_relay.c:787
+#: logsrvd/logsrvd_relay.c:794
+msgid "error reading from relay"
+msgstr "erreur de lecture depuis le relai"
+
+#: logsrvd/logsrvd_relay.c:815
+msgid "unable to read from relay"
+msgstr "impossible de lire depuis le relai"
+
+#: logsrvd/logsrvd_relay.c:830 logsrvd/logsrvd_relay.c:949
+msgid "relay server closed connection"
+msgstr "le serveur relai a fermé la connexion"
+
+#: logsrvd/logsrvd_relay.c:848
+msgid "server message too large"
+msgstr "message serveur trop grand"
+
+#: logsrvd/logsrvd_relay.c:912
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr "délai d'attente expiré durant l'écriture vers le relai %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:914
+msgid "timeout writing to relay"
+msgstr "délai d'attente expiré durant l'écriture vers le relai"
+
+#: logsrvd/logsrvd_relay.c:968 logsrvd/logsrvd_relay.c:975
+#: logsrvd/logsrvd_relay.c:987
+msgid "error writing to relay"
+msgstr "erreur d'écriture dans le relai"
+
+#: logsrvd/sendlog.c:124
+msgid "send sudo I/O log to remote server"
+msgstr "envoyer le journal des E/S de sudo au serveur distant"
+
+#: logsrvd/sendlog.c:130
+msgid "only send an accept event (no I/O)"
+msgstr "uniquement envoyer un événement d'acceptation (pas d'E/S)"
+
+#: logsrvd/sendlog.c:133
+msgid "certificate bundle file to verify server's cert against"
+msgstr "fichier de trousseau de certificats pour vérifier le certificat du serveur"
+
+#: logsrvd/sendlog.c:135
+msgid "certificate file for TLS handshake"
+msgstr "fichier de certificat pour la négociation TLS"
+
+#: logsrvd/sendlog.c:138
+msgid "host to send logs to"
+msgstr "hôte auquel envoyer les journaux"
+
+#: logsrvd/sendlog.c:140
+msgid "remote ID of I/O log to be resumed"
+msgstr "ID distant du journal des E/S à compléter"
+
+#: logsrvd/sendlog.c:143
+msgid "private key file"
+msgstr "fichier de clé privée"
+
+#: logsrvd/sendlog.c:145
+msgid "do not verify server certificate"
+msgstr "ne pas vérifier le certificat du serveur"
+
+#: logsrvd/sendlog.c:148
+msgid "port to use when connecting to host"
+msgstr "port à utiliser lors de la connexion à l'hôte"
+
+#: logsrvd/sendlog.c:150
+msgid "restart previous I/O log transfer"
+msgstr "redémarrer le transfert de journaux E/S précédent"
+
+#: logsrvd/sendlog.c:152
+msgid "reject the command with the given reason"
+msgstr "rejeter la commande avec la raison fournie"
+
+#: logsrvd/sendlog.c:154
+msgid "stop transfer after reaching this time"
+msgstr "arrêter le transfert après avoir atteint ce temps"
+
+#: logsrvd/sendlog.c:156
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "tester le serveur d'audit en envoyant le journal des E/S sélectionné n fois en parallèle"
+
+#: logsrvd/sendlog.c:181 plugins/sudoers/log_client.c:453
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "impossible de rechercher %s:%s : %s"
+
+#: logsrvd/sendlog.c:219
+msgid "unable to get server IP addr"
+msgstr "impossible d'obtenir l'adresse IP du serveur"
+
+#: logsrvd/sendlog.c:314 plugins/sudoers/sudoreplay.c:868
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "impossible de lire %s/%s : %s"
+
+#: logsrvd/sendlog.c:1035 plugins/sudoers/iolog.c:959
+#: plugins/sudoers/iolog.c:1034
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "événement d'E/S %d inattendu"
+
+#: logsrvd/sendlog.c:1088 logsrvd/sendlog.c:1105 logsrvd/sendlog.c:1139
+#: plugins/sudoers/log_client.c:1129 plugins/sudoers/log_client.c:1405
+#: plugins/sudoers/log_client.c:1473 plugins/sudoers/log_client.c:1512
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: état %d inattendu"
+
+#: logsrvd/sendlog.c:1175 plugins/sudoers/log_client.c:1561
+#, c-format
+msgid "error message received from server: %s"
+msgstr "message d'erreur reçu du serveur : %s"
+
+#: logsrvd/sendlog.c:1188 plugins/sudoers/log_client.c:1574
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "message d'interruption reçu du serveur : %s"
+
+#: logsrvd/sendlog.c:1247 plugins/sudoers/log_client.c:1624
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s: valeur type_case %d inattendue"
+
+#: logsrvd/sendlog.c:1276
+msgid "timeout reading from server"
+msgstr "délai d'attente expiré durant la lecture depuis le serveur"
+
+#: logsrvd/sendlog.c:1327 plugins/sudoers/log_client.c:1747
+msgid "host name does not match certificate"
+msgstr "le nom de l'hôte ne correspond pas au certificat"
+
+#: logsrvd/sendlog.c:1361
+msgid "premature EOF"
+msgstr "fin de fichier prématurée"
+
+#: logsrvd/sendlog.c:1374 plugins/sudoers/log_client.c:1795
+#, c-format
+msgid "server message too large: %u"
+msgstr "message serveur trop grand : %u"
+
+#: logsrvd/sendlog.c:1430
+msgid "timeout writing to server"
+msgstr "délai d'attente expiré durant l'écriture vers le serveur"
+
+#: logsrvd/sendlog.c:1800
+msgid "both restart point and iolog ID must be specified"
+msgstr "le point de redémarrage et le ID iolog doivent être spécifiés tous les deux"
+
+#: logsrvd/sendlog.c:1804
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "un point de redémarrage ne peut pas être placé quand aucune E/S est envoyée"
+
+#: logsrvd/sendlog.c:1880
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "terminé prématurément avec l'état %d"
+
+#: logsrvd/sendlog.c:1881
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "temps écoulé envoyé au serveur [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1883
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "point d'enregistrement reçu du serveur [%lld, %ld]"
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:315
+msgid "TLS handshake timeout occurred"
+msgstr "le délai de la négociation TLS a expiré"
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:337 plugins/sudoers/log_client.c:353
+msgid "unable to set event"
+msgstr "impossible de définir l'événement"
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "la communication TLS a échoué : %s"
+
+#: logsrvd/tls_client.c:196
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "impossible d'allouer l'objet ssl : %s"
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "Impossible d'attacher le socket à l'objet ssl : %s"
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr "impossible d'initialiser le contexte TLS"
+
+#: logsrvd/tls_init.c:138 logsrvd/tls_init.c:146
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "impossible de sélectionner la suite de chiffrement %s pour TLS 1.2 : %s"
+
+#: logsrvd/tls_init.c:166 logsrvd/tls_init.c:174
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "impossible de sélectionner la suite de chiffrement %s pour TLS 1.3 : %s"
+
+#: logsrvd/tls_init.c:206 logsrvd/tls_init.c:227
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "impossible de définir les paramètres diffie-hellman : %s"
+
+#: logsrvd/tls_init.c:283
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "impossible de créer le contexte TLS : %s"
+
+#: logsrvd/tls_init.c:290
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "impossible de définir TLS 1.2 comme étant la version minimale du protocole : %s"
+
+#: plugins/sudoers/audit.c:272 plugins/sudoers/audit.c:452
+#: plugins/sudoers/log_client.c:962 plugins/sudoers/log_client.c:1011
+#: plugins/sudoers/log_client.c:1060 plugins/sudoers/log_client.c:1185
+#: plugins/sudoers/logging.c:614 plugins/sudoers/logging.c:732
+#: plugins/sudoers/logging.c:859 plugins/sudoers/logging.c:1031
+#: plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr "récupération de l'heure du jour impossible"
+
+#: plugins/sudoers/auth/aix_auth.c:282
+#, c-format
+msgid "unable to change password for %s"
+msgstr "changement du mot de passe impossible pour %s"
+
+#: plugins/sudoers/auth/bsdauth.c:78
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "récupération de la classe de connexion impossible pour l'utilisateur %s"
+
+#: plugins/sudoers/auth/bsdauth.c:85
+msgid "invalid authentication type"
+msgstr "type d'authentification non valide"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to begin BSD authentication"
+msgstr "impossible de commencer l'authentification BSD"
+
+#: plugins/sudoers/auth/bsdauth.c:97
+msgid "unable to initialize BSD authentication"
+msgstr "démarrage de l'authentification BSD impossible"
+
+#: plugins/sudoers/auth/bsdauth.c:191
+msgid "your account has expired"
+msgstr "votre compte est expiré"
+
+#: plugins/sudoers/auth/bsdauth.c:193
+msgid "approval failed"
+msgstr "échec de l'approbation"
+
+#: plugins/sudoers/auth/fwtk.c:62
+msgid "unable to read fwtk config"
+msgstr "lecture de la configuration fwtk (firewall) impossible"
+
+#: plugins/sudoers/auth/fwtk.c:67
+msgid "unable to connect to authentication server"
+msgstr "connexion au serveur d'authentification impossible"
+
+#: plugins/sudoers/auth/fwtk.c:73 plugins/sudoers/auth/fwtk.c:99
+#: plugins/sudoers/auth/fwtk.c:131
+msgid "lost connection to authentication server"
+msgstr "perte de la connexion au serveur d'authentification"
+
+#: plugins/sudoers/auth/fwtk.c:77
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"erreur du serveur d'authentification :\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:116
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s : conversion de l'identité de l'hôte en chaîne de caractères impossible(« %s ») : %s"
+
+#: plugins/sudoers/auth/kerb5.c:166
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s : analyse grammaticale (parse) de « %s » impossible : %s"
+
+#: plugins/sudoers/auth/kerb5.c:175
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s : accès au cache des données d'identification impossible : %s"
+
+#: plugins/sudoers/auth/kerb5.c:226
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s : allocation des options impossible : %s"
+
+#: plugins/sudoers/auth/kerb5.c:241
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s : récupération des données d'identification impossible : %s"
+
+#: plugins/sudoers/auth/kerb5.c:254
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s : initialisation du cache des données d'identification impossible : %s"
+
+#: plugins/sudoers/auth/kerb5.c:257
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s : enregistrement des données d'identification dans le cache impossible : %s"
+
+#: plugins/sudoers/auth/kerb5.c:322
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s : récupération de l'identité kerberos de l'hôte (« host principal ») impossible : %s"
+
+#: plugins/sudoers/auth/kerb5.c:336
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s : vérification du ticket TGT impossible ! Il s'agit peut-être d'une attaque ! : %s"
+
+#: plugins/sudoers/auth/pam.c:233
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "initialisation du module PAM impossible : %s"
+
+#: plugins/sudoers/auth/pam.c:349
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Erreur du serveur d'authentification PAM : %s"
+
+#: plugins/sudoers/auth/pam.c:369
+msgid "account validation failure, is your account locked?"
+msgstr "la validation du compte a échoué, votre compte serait-il verrouillé ?"
+
+#: plugins/sudoers/auth/pam.c:380
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Le compte ou le mot de passe a expiré, réinitialisez votre mot de passe puis réessayez de vous connecter"
+
+#: plugins/sudoers/auth/pam.c:387
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "changement du mot de passe expiré impossible : %s"
+
+#: plugins/sudoers/auth/pam.c:398
+msgid "Password expired, contact your system administrator"
+msgstr "Le mot de passe a expiré, contactez votre administrateur système"
+
+#: plugins/sudoers/auth/pam.c:403
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Le compte a expiré, ou la section « account » du module PAM n'est pas renseignée pour sudo, contactez votre administrateur système"
+
+#: plugins/sudoers/auth/pam.c:411 plugins/sudoers/auth/pam.c:416
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "Erreur de gestion du compte PAM : %s"
+
+#: plugins/sudoers/auth/rfc1938.c:100 plugins/sudoers/visudo.c:266
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "votre compte n'existe pas dans la base de données %s"
+
+#: plugins/sudoers/auth/securid5.c:76
+msgid "failed to initialise the ACE API library"
+msgstr "échec de l'initialisation de la bibliothèque d'API ACE"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "unable to contact the SecurID server"
+msgstr "le contact avec le serveur SecurID n'a pas pu être établi"
+
+#: plugins/sudoers/auth/securid5.c:117
+msgid "User ID locked for SecurID Authentication"
+msgstr "l'identifiant de l'utilisateur est verrouillé pour l'authentification SecurID"
+
+#: plugins/sudoers/auth/securid5.c:121 plugins/sudoers/auth/securid5.c:174
+msgid "invalid username length for SecurID"
+msgstr "la longueur du nom de l'utilisateur n'est pas conforme aux règles fixées pour SecurID"
+
+#: plugins/sudoers/auth/securid5.c:125 plugins/sudoers/auth/securid5.c:179
+msgid "invalid Authentication Handle for SecurID"
+msgstr "l'identifiant d'authentification (« Authentication Handle ») est invalide pour SecurID"
+
+#: plugins/sudoers/auth/securid5.c:129
+msgid "SecurID communication failed"
+msgstr "la communication avec SecurID a échoué"
+
+#: plugins/sudoers/auth/securid5.c:133 plugins/sudoers/auth/securid5.c:222
+msgid "unknown SecurID error"
+msgstr "erreur SecurID non identifiée"
+
+#: plugins/sudoers/auth/securid5.c:169
+msgid "invalid passcode length for SecurID"
+msgstr "la longueur du mot de passe est invalide pour SecurID"
+
+#: plugins/sudoers/auth/sia.c:72 plugins/sudoers/auth/sia.c:130
+msgid "unable to initialize SIA session"
+msgstr "initialisation de la session SIA impossible"
+
+#: plugins/sudoers/auth/sudo_auth.c:141
+msgid "invalid authentication methods"
+msgstr "méthodes d'authentification invalides"
+
+#: plugins/sudoers/auth/sudo_auth.c:143
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Méthodes d'authentification non valides compilées dans sudo ! La combinaison d'authentifications autonomes et non-autonomes n'est pas permise."
+
+#: plugins/sudoers/auth/sudo_auth.c:296 plugins/sudoers/auth/sudo_auth.c:359
+msgid "no authentication methods"
+msgstr "pas de méthodes d'authentification"
+
+#: plugins/sudoers/auth/sudo_auth.c:298
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Aucune méthode d'authentification compilée dans sudo ! Si vous souhaitez désactiver l'authentification, utilisez l'option de configuration --disable-authentication"
+
+#: plugins/sudoers/auth/sudo_auth.c:361
+msgid "Unable to initialize authentication methods."
+msgstr "Initialisation des méthodes d'authentification impossible."
+
+#: plugins/sudoers/auth/sudo_auth.c:551
+msgid "Authentication methods:"
+msgstr "Méthodes d'authentification : "
+
+#: plugins/sudoers/bsm_audit.c:122 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "Identification de la condition d'audit impossible"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:278
+msgid "unable to commit audit record"
+msgstr "impossible d'enregistrer l'enregistrement d'audit"
+
+#: plugins/sudoers/check.c:63 plugins/sudoers/check.c:74
+#: plugins/sudoers/lookup.c:79 plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "identifiant utilisateur %u inconnu"
+
+#: plugins/sudoers/check.c:277
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "erreur de lecture dans le fichier des recommandations d'usage : %s"
+
+#: plugins/sudoers/check.c:280
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "le fichier des recommandations d'usage %s est ignoré : il n'est pas un fichier ordinaire"
+
+#: plugins/sudoers/check.c:293
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Nous espérons que vous avez reçu de votre administrateur système local\n"
+"les consignes traditionnelles. Généralement, elles se concentrent sur ces trois éléments :\n"
+"\n"
+" #1) Respectez la vie privée des autres.\n"
+" #2) Réfléchissez avant d'utiliser le clavier.\n"
+" #3) De grands pouvoirs confèrent de grandes responsabilités.\n"
+"\n"
+
+#: plugins/sudoers/check.c:301
+msgid ""
+"For security reasons, the password you type will not be visible.\n"
+"\n"
+msgstr ""
+"Pour des raisons de sécurité, le mot de passe que vous tapez ne sera pas visible.\n"
+"\n"
+
+#: plugins/sudoers/check_aliases.c:93
+#, c-format
+msgid "cycle in %s \"%s\""
+msgstr "boucle dans %s « %s »"
+
+#: plugins/sudoers/check_aliases.c:96
+#, c-format
+msgid "%s \"%s\" referenced but not defined"
+msgstr "il est fait mention de %s « %s » alors qu'il n'a pas été défini"
+
+#: plugins/sudoers/cvtsudoers.c:211
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "incrément d'ordre : %s : %s"
+
+#: plugins/sudoers/cvtsudoers.c:231
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "ordre de départ : %s : %s"
+
+#: plugins/sudoers/cvtsudoers.c:242
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "remplissage de l'ordre : %s : %s"
+
+#: plugins/sudoers/cvtsudoers.c:252 plugins/sudoers/visudo.c:183
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "Version de la grammaire de %s : %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:282 plugins/sudoers/testsudoers.c:162
+#, c-format
+msgid "unsupported input format %s"
+msgstr "format d'entrée %s non supporté"
+
+#: plugins/sudoers/cvtsudoers.c:300
+#, c-format
+msgid "unsupported output format %s"
+msgstr "format de sortie %s non supporté"
+
+#: plugins/sudoers/cvtsudoers.c:392
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s : les fichiers d'entrée et de sortie doivent être différents"
+
+#: plugins/sudoers/cvtsudoers.c:406 plugins/sudoers/sudoers.c:151
+#: plugins/sudoers/sudoers.c:209 plugins/sudoers/testsudoers.c:315
+#: plugins/sudoers/visudo.c:276 plugins/sudoers/visudo.c:666
+msgid "unable to initialize sudoers default values"
+msgstr "initialisation des valeurs par défaut de sudoers impossible"
+
+#: plugins/sudoers/cvtsudoers.c:533 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s : %s : %s : %s"
+
+#: plugins/sudoers/cvtsudoers.c:612
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s: mot clé %s inconnu"
+
+#: plugins/sudoers/cvtsudoers.c:658
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "type par défaut invalide : %s"
+
+#: plugins/sudoers/cvtsudoers.c:681
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "type de suppression invalide : %s"
+
+#: plugins/sudoers/cvtsudoers.c:722 plugins/sudoers/cvtsudoers.c:738
+#, c-format
+msgid "invalid filter: %s"
+msgstr "filtre invalide : %s"
+
+#: plugins/sudoers/cvtsudoers.c:783 plugins/sudoers/visudo.c:1000
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "échec lors de l'analyse grammaticale de %s, erreur inconnue"
+
+#: plugins/sudoers/cvtsudoers.c:1508 plugins/sudoers/sudoreplay.c:1143
+#: plugins/sudoers/timestamp.c:353 plugins/sudoers/timestamp.c:356
+#, c-format
+msgid "unable to write to %s"
+msgstr "écriture impossible dans %s"
+
+#: plugins/sudoers/cvtsudoers.c:1536
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s - convertir entre des formats de fichiers sudoers\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1538
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Options:\n"
+" -b, --base=dn le DN de base pour les requêtes LDAP de sudo\n"
+" -c, --config=fich_conf le chemin vers le fichier de configuration\n"
+" -d, --defaults=typesdef uniquement convertir les Defaults des types spécifiés\n"
+" -e, --expand-aliases développer les alias lors de la conversion\n"
+" -f, --output-format=format définir le format de sortie : JSON, LDIF ou sudoers\n"
+" -i, --input-format=format définir le format d'entrée : LDIF ou sudoers\n"
+" -I, --increment=num valeur pour incrémenter chaque sudoOrder\n"
+" -h, --help afficher le message d'aide puis terminer\n"
+" -m, --match=filtre ne convertir que les entrées correspondant au filtre\n"
+" -M, --match-local le filtre de correspondance utilise les bases de données\n"
+" des mots de passe et des groupes\n"
+" -o, --output=fichier_sortie écrire les sudoers convertis dans fichier_sortie\n"
+" -O, --order-start=num point de départ du premier sudoers\n"
+" -p, --prune-matches éliminer les utilisateurs, groupes ou hôtes qui ne\n"
+" correspondent pas\n"
+" -P, --padding=num remplissage de base pour l'incrément de sudoOrder\n"
+" -s, --suppress=sections supprimer la sortie de certaines sections\n"
+" -V, --version afficher la version et terminer"
+
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:245 plugins/sudoers/cvtsudoers_ldif.c:252
+#: plugins/sudoers/cvtsudoers_ldif.c:594 plugins/sudoers/env.c:340
+#: plugins/sudoers/env.c:347 plugins/sudoers/env.c:458
+#: plugins/sudoers/ldap.c:511 plugins/sudoers/ldap.c:629
+#: plugins/sudoers/ldap.c:1003 plugins/sudoers/ldap_conf.c:219
+#: plugins/sudoers/ldap_conf.c:310 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:93 plugins/sudoers/logging.c:479
+#: plugins/sudoers/policy.c:828 plugins/sudoers/policy.c:840
+#: plugins/sudoers/prompt.c:169 plugins/sudoers/serialize_list.c:62
+#: plugins/sudoers/serialize_list.c:71 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/sudoreplay.c:1340 plugins/sudoers/sudoreplay.c:1346
+#: plugins/sudoers/sudoreplay.c:1352 plugins/sudoers/testsudoers.c:306
+#: plugins/sudoers/toke_util.c:217 toke.l:995 toke.l:1277
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "erreur interne, dépassement de %s"
+
+#: plugins/sudoers/cvtsudoers_csv.c:454 plugins/sudoers/cvtsudoers_csv.c:468
+#: plugins/sudoers/cvtsudoers_json.c:661 plugins/sudoers/cvtsudoers_json.c:676
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:362
+#: plugins/sudoers/ldap.c:495
+msgid "unable to get GMT time"
+msgstr "récupération de l'heure GMT impossible"
+
+#: plugins/sudoers/cvtsudoers_csv.c:459 plugins/sudoers/cvtsudoers_csv.c:473
+#: plugins/sudoers/cvtsudoers_json.c:666 plugins/sudoers/cvtsudoers_json.c:681
+#: plugins/sudoers/cvtsudoers_ldif.c:354 plugins/sudoers/cvtsudoers_ldif.c:367
+#: plugins/sudoers/ldap.c:503
+msgid "unable to format timestamp"
+msgstr "impossible de formater l'horodatage"
+
+#: plugins/sudoers/cvtsudoers_json.c:481 plugins/sudoers/cvtsudoers_json.c:516
+#: plugins/sudoers/cvtsudoers_json.c:732
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: entrées par défaut inconnues « %s »"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:663
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "trop d'entrées sudoers, maximum %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:706
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "la variable d'environnement SUDOERS_BASE n'est pas définie et l'option -b n'a pas été spécifiée."
+
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, c-format
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr "%s:%d:%d: conversion de la liste des hôtes à ALL"
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr "impossible de trouver le synonyme %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, c-format
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr "%s:%d:%d: changement de nom du synonyme %s en %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr "%s:%d:%d: suppression du synonyme %s en double"
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr "%s:%d:%d: entrées Defaults « %s » spécifiques à l'hôte conflictuelles dans %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, c-format
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr "%s:%d:%d: a rendu Defaults « %s » spécifique à l'hôte %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr "%s:%d:%d: impossible de rendre Defaults « %s » spécifique à l'hôte"
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr "%s:%d:%d: suppression de Defaults « %s » surchargée par des entrées ultérieures"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1088
+#, c-format
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr "%s:%d:%d: fusion des spécifications utilisateur dans %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1182
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr "%s:%d:%d: suppression de la spécification utilisateur surchargée par des entrées ultérieurs"
+
+#: plugins/sudoers/def_data.c:56
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Mécanisme syslog si syslog est utilisé pour la journalisation des événements : %s "
+
+#: plugins/sudoers/def_data.c:60
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Priorité syslog utilisée lorsque l'authentification de l'utilisateur est réussie : %s"
+
+#: plugins/sudoers/def_data.c:64
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Priorité Syslog utilisée lorsque l'authentification de l'utilisateur a échoué : %s"
+
+#: plugins/sudoers/def_data.c:68
+msgid "Put OTP prompt on its own line"
+msgstr "Présentation de l'invite OTP sur une ligne distincte"
+
+#: plugins/sudoers/def_data.c:72
+msgid "Ignore '.' in $PATH"
+msgstr "Ne pas tenir compte de « . » dans $PATH"
+
+#: plugins/sudoers/def_data.c:76
+msgid "Always send mail when sudo is run"
+msgstr "Toujours envoyer un courriel à chaque exécution de sudo"
+
+#: plugins/sudoers/def_data.c:80
+msgid "Send mail if user authentication fails"
+msgstr "Envoi d'un courriel lorsqu'une authentification échoue"
+
+#: plugins/sudoers/def_data.c:84
+msgid "Send mail if the user is not in sudoers"
+msgstr "Envoi d'un courriel si l'utilisateur ne figure pas dans sudoers"
+
+#: plugins/sudoers/def_data.c:88
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Envoi d'un courriel si l'utilisateur ne figure pas dans sudoers pour l'hôte sur lequel sudo est exécuté"
+
+#: plugins/sudoers/def_data.c:92
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Envoi d'un courriel si l'utilisateur n'est pas autorisé à exécuter une commande"
+
+#: plugins/sudoers/def_data.c:96
+msgid "Send mail if the user tries to run a command"
+msgstr "Envoi d'un courriel si l'utilisateur tente d'exécuter une commande"
+
+#: plugins/sudoers/def_data.c:100
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Utilisation d'un horodatage distinct pour chaque couple utilisateur/terminal (user/tty)"
+
+#: plugins/sudoers/def_data.c:104
+msgid "Lecture user the first time they run sudo"
+msgstr "Adresse les recommandations d'usage à l'utilisateur lors de la première exécution de sudo"
+
+#: plugins/sudoers/def_data.c:108
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Fichier contenant les recommandations sur l'usage de sudo : %s"
+
+#: plugins/sudoers/def_data.c:112
+msgid "Require users to authenticate by default"
+msgstr "Exige l'authentification de l'utilisateur par défaut"
+
+#: plugins/sudoers/def_data.c:116
+msgid "Root may run sudo"
+msgstr "L'utilisateur root peut exécuter sudo"
+
+#: plugins/sudoers/def_data.c:120
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Consignation du nom de l'hôte dans le fichier de journalisation (qui n'est pas syslog)"
+
+#: plugins/sudoers/def_data.c:124
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Consignation de l'année dans le fichier de journalisation (qui n'est pas syslog)"
+
+#: plugins/sudoers/def_data.c:128
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Démarrage d'un interpréteur de commande lorsque sudo est lancé sans argument"
+
+#: plugins/sudoers/def_data.c:132
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Assigner le répertoire de l'utilisateur cible dans $HOME lorsque l'interpréteur de commandes est lancé avec l'option -s"
+
+#: plugins/sudoers/def_data.c:136
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Assignation systématique du répertoire personnel de l'utilisateur cible dans $HOME"
+
+#: plugins/sudoers/def_data.c:140
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Autorise la collecte de certaines informations dans le but d'afficher des messages d'erreurs pertinents"
+
+#: plugins/sudoers/def_data.c:144
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Exige l'emploi du nom complet (fully qualified) de l'ordinateur dans le fichier sudoers"
+
+#: plugins/sudoers/def_data.c:148
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Sermonne l'utilisateur lorsqu'un mot de passe incorrect est saisi"
+
+#: plugins/sudoers/def_data.c:152
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Autorise l'utilisateur à exécuter sudo seulement à la condition qu'il dispose d'un terminal tty"
+
+#: plugins/sudoers/def_data.c:156
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo se conformera au contenu de la variable d'environnement EDITOR"
+
+#: plugins/sudoers/def_data.c:160
+msgid "Prompt for root's password, not the users's"
+msgstr "Demande de la saisie du mot de passe de root et non de celui de l'utilisateur"
+
+#: plugins/sudoers/def_data.c:164
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Demande de la saisie du mot de passe runas_default de l'utilisateur et non de son propre mot de passe"
+
+#: plugins/sudoers/def_data.c:168
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Demande de la saisie du mot de passe de l'utilisateur cible et non de celui de l'utilisateur exécutant la commande"
+
+#: plugins/sudoers/def_data.c:172
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Utilisation des paramètres par défaut de la classe de connexion de l'utilisateur cible (lorsqu'elle existe)"
+
+#: plugins/sudoers/def_data.c:176
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Définir les variables d'environnement LOGNAME et USER"
+
+#: plugins/sudoers/def_data.c:180
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Assigne uniquement l'identifiant utilisateur (UID) effectif à l'utilisateur cible, et non à l'identifiant réel."
+
+#: plugins/sudoers/def_data.c:184
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "N'initialise pas le vecteur de groupe avec les valeurs de l'utilisateur cible"
+
+#: plugins/sudoers/def_data.c:188
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Longueur après laquelle intercaler un retour à la ligne dans le fichier journal (0 indique qu'il n'y a pas de retour à la ligne) : %u"
+
+#: plugins/sudoers/def_data.c:192
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Délai d'expiration de l'horodatage de l'authentification : %.1f minutes"
+
+#: plugins/sudoers/def_data.c:196
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Délai d'expiration de l'invite de saisie de mot de passe : %.1f minutes"
+
+#: plugins/sudoers/def_data.c:200
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Nombre de tentatives de saisie du mot de passe : %u"
+
+#: plugins/sudoers/def_data.c:204
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Umask à utiliser, ou 0777 pour hériter de celui de l'utilisateur : 0%o"
+
+#: plugins/sudoers/def_data.c:208
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Emplacement du fichier de journalisation : %s"
+
+#: plugins/sudoers/def_data.c:212
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Emplacement du programme d'envoi de courriel : %s"
+
+#: plugins/sudoers/def_data.c:216
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Attributs à utiliser avec le programme d'envoi de courriel : %s"
+
+#: plugins/sudoers/def_data.c:220
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Adresse du destinataire des courriels : %s"
+
+#: plugins/sudoers/def_data.c:224
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Adresse de l'expéditeur des courriels : %s"
+
+#: plugins/sudoers/def_data.c:228
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Champ objet des courriels envoyés : %s"
+
+#: plugins/sudoers/def_data.c:232
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Message informant de la saisie d'un mot de passe incorrect : %s"
+
+#: plugins/sudoers/def_data.c:236
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Répertoire contenant l'attestation que l'utilisateur a déjà reçu les recommandations : %s"
+
+#: plugins/sudoers/def_data.c:240
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Répertoire contenant l'horodatage de l'authentification : %s"
+
+#: plugins/sudoers/def_data.c:244
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Propriétaire du répertoire contenant l'horodatage de l'authentification : %s"
+
+#: plugins/sudoers/def_data.c:248
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Les utilisateurs de ce groupe sont affranchis des contraintes relatives au mot de passe et à PATH : %s"
+
+#: plugins/sudoers/def_data.c:252
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Invite de mot de passe par défaut : %s"
+
+#: plugins/sudoers/def_data.c:256
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "S'il est défini, passprompt se substituera toujours à l'invite du système."
+
+#: plugins/sudoers/def_data.c:260
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Utilisateur par défaut avec l'identité duquel exécuter les commandes : %s"
+
+#: plugins/sudoers/def_data.c:264
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Nouvelle valeur prise par la variable $PATH de l'utilisateur : %s"
+
+#: plugins/sudoers/def_data.c:268
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Emplacement de l'éditeur appelé par visudo : %s"
+
+#: plugins/sudoers/def_data.c:272
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Quand demander un mot de passe pour l'usage de la pseudo commande « list » : %s"
+
+#: plugins/sudoers/def_data.c:276
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Quand demander un mot de passe pour l'utilisation de la pseudo commande « verify » : %s"
+
+#: plugins/sudoers/def_data.c:280
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "Précharger la bibliothèque sudo_noexec qui remplace les fonctions exec"
+
+#: plugins/sudoers/def_data.c:284
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Si un annuaire LDAP est actif, faut-il tenir compter du fichier sudoers local"
+
+#: plugins/sudoers/def_data.c:288
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Les descripteurs de fichiers >= %d seront fermés avant l'exécution d'une commande"
+
+#: plugins/sudoers/def_data.c:292
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "Si elle est définie, les utilisateurs peuvent passer outre la valeur de « closeform » grâce à l'option -C"
+
+#: plugins/sudoers/def_data.c:296
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Autorise les utilisateurs à définir des variables d'environnement arbitraires"
+
+#: plugins/sudoers/def_data.c:300
+msgid "Reset the environment to a default set of variables"
+msgstr "Réinitialise l'environnement à un jeu de variables par défaut"
+
+#: plugins/sudoers/def_data.c:304
+msgid "Environment variables to check for safety:"
+msgstr "Variables d'environnement à valider pour s'assurer de la sécurité :"
+
+#: plugins/sudoers/def_data.c:308
+msgid "Environment variables to remove:"
+msgstr "Variables d'environnement à supprimer :"
+
+#: plugins/sudoers/def_data.c:312
+msgid "Environment variables to preserve:"
+msgstr "Variables d'environnement à conserver :"
+
+#: plugins/sudoers/def_data.c:316
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "Rôle SELinux à utiliser dans le nouveau contexte de sécurité : %s"
+
+#: plugins/sudoers/def_data.c:320
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "Type SELinux à utiliser dans le nouveau contexte de sécurité : %s"
+
+#: plugins/sudoers/def_data.c:324
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Emplacement du fichier d'environnement propre à sudo : %s"
+
+#: plugins/sudoers/def_data.c:328
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Emplacement du fichier d'environnement restreint propre à sudo : %s"
+
+#: plugins/sudoers/def_data.c:332
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Environnement linguistique à utiliser lors de l'analyse syntaxique de sudoers : %s"
+
+#: plugins/sudoers/def_data.c:336
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Autoriser sudo à demander la saisie d'un mot de passe même lorsque celui-ci sera affiché « en clair »"
+
+#: plugins/sudoers/def_data.c:340
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Afficher un contrôle visuel lors de la saisie du mot de passe"
+
+#: plugins/sudoers/def_data.c:344
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Utiliser le développement rapide des noms de fichiers, qui est moins fiable, mais ne nécessite pas d'accès au système de fichiers"
+
+#: plugins/sudoers/def_data.c:348
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "L'umask indiqué dans sudoers se substituera à celui de l'utilisateur, même s'il est plus permissif"
+
+#: plugins/sudoers/def_data.c:352
+msgid "Log user's input for the command being run"
+msgstr "Consignation des saisies de l'utilisateur dans le journal pour la commande en cours d'exécution"
+
+#: plugins/sudoers/def_data.c:356
+msgid "Log the command's standard input if not connected to a terminal"
+msgstr "Consigne l'entrée standard de la commande dans le journal si elle n'est pas connectée à un terminal"
+
+#: plugins/sudoers/def_data.c:360
+msgid "Log the user's terminal input for the command being run"
+msgstr "Consignation des saisies du terminal de l'utilisateur dans le journal pour la commande en cours d'exécution"
+
+#: plugins/sudoers/def_data.c:364
+msgid "Log the output of the command being run"
+msgstr "Consignation du retour de la commande en cours d'exécution dans le journal"
+
+#: plugins/sudoers/def_data.c:368
+msgid "Log the command's standard output if not connected to a terminal"
+msgstr "Consigne la sortie standard de la commande dans le journal si elle n'est pas connectée à un terminal"
+
+#: plugins/sudoers/def_data.c:372
+msgid "Log the command's standard error if not connected to a terminal"
+msgstr "Consigne l'erreur standard de la commande dans le journal si elle n'est pas connectée à un terminal"
+
+#: plugins/sudoers/def_data.c:376
+msgid "Log the terminal output of the command being run"
+msgstr "Consigne dans le journal la sortie envoyée sur le terminal par la commande en cours d'exécution"
+
+#: plugins/sudoers/def_data.c:380
+msgid "Compress I/O logs using zlib"
+msgstr "Compression des informations renvoyées par les opérations d'E/S avec zlib"
+
+#: plugins/sudoers/def_data.c:384
+msgid "Always run commands in a pseudo-tty"
+msgstr "Exécute toujours les commandes dans un pseudo-terminal (tty)"
+
+#: plugins/sudoers/def_data.c:388
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Greffon pour la prise en charge des groupes non-Unix : %s"
+
+#: plugins/sudoers/def_data.c:392
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Répertoire dans lequel les informations renvoyées par les opérations d'entrée/sortie seront stockées : %s"
+
+#: plugins/sudoers/def_data.c:396
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Fichier dans lequel les informations renvoyées par les opérations d'entrée/sortie seront stockées : %s"
+
+#: plugins/sudoers/def_data.c:400
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Ajout d'une entrée au fichier utmp/utmpx lors de l'allocation d'un pseudo-terminal"
+
+#: plugins/sudoers/def_data.c:404
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Conservation dans utmp du nom de l'utilisateur runas, et non de celui de l'utilisateur appelant sudo"
+
+#: plugins/sudoers/def_data.c:408
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Ensemble des privilèges permis : %s"
+
+#: plugins/sudoers/def_data.c:412
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Ensemble des privilèges limités : %s"
+
+#: plugins/sudoers/def_data.c:416
+msgid "Run commands on a pty in the background"
+msgstr "Exécution des commandes sur un pseudo-terminal en tâche de fond"
+
+#: plugins/sudoers/def_data.c:420
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "Nom de service PAM à utiliser : %s"
+
+#: plugins/sudoers/def_data.c:424
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "Nom de service PAM à utiliser pour les interpréteurs de commandes : %s"
+
+#: plugins/sudoers/def_data.c:428
+#, c-format
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr "Nom de service PAM à utiliser quand sudo est exécuté avec l'option -A : %s"
+
+#: plugins/sudoers/def_data.c:432
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Tentative de création des données d'identification PAM pour l'utilisateur cible"
+
+#: plugins/sudoers/def_data.c:436
+msgid "Create a new PAM session for the command to run in"
+msgstr "Création d'une nouvelle session PAM pour l'exécution de la commande"
+
+#: plugins/sudoers/def_data.c:440
+msgid "Perform PAM account validation management"
+msgstr "Réaliser la gestion de la validation du compte PAM"
+
+#: plugins/sudoers/def_data.c:444
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "Numéro de séquence maximum dans le journal E/S : %s"
+
+#: plugins/sudoers/def_data.c:448
+msgid "Enable sudoers netgroup support"
+msgstr "Activation de la prise en charge de netgroup par sudoers"
+
+#: plugins/sudoers/def_data.c:452
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Vérification que les droits du répertoire parent autorisent la modification des fichiers avec sudoedit"
+
+#: plugins/sudoers/def_data.c:456
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Suivre les liens symboliques lors de l'édition des fichiers avec sudoedit"
+
+#: plugins/sudoers/def_data.c:460
+msgid "Query the group plugin for unknown system groups"
+msgstr "Interroge le greffon de groupe pour les groupes système inconnus"
+
+#: plugins/sudoers/def_data.c:464
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Faire correspondre les netgroups sur base du tuple entier: utilisateur, hôte et domaine"
+
+#: plugins/sudoers/def_data.c:468
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Autoriser l'exécution des commandes même si sudo ne sait pas écrire dans le journal d'audit"
+
+#: plugins/sudoers/def_data.c:472
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Autoriser l'exécution des commandes même si sudo ne sait pas écrire dans le journal des E/S"
+
+#: plugins/sudoers/def_data.c:476
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Autoriser l'exécution des commandes même si sudo ne sait pas écrire dans le fichier journal"
+
+#: plugins/sudoers/def_data.c:480
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Résoudre les groupes dans sudoers et établir la correspondance sur le ID de groupe au lieu du nom"
+
+#: plugins/sudoers/def_data.c:484
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Les entrées du journal plus longues que cette valeur seront scindées en plusieurs messages dans syslog : %u"
+
+#: plugins/sudoers/def_data.c:488
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Utilisateur qui possèdera les fichiers journaux des E/S : %s"
+
+#: plugins/sudoers/def_data.c:492
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Groupe qui possèdera les fichiers journaux des E/S : %s"
+
+#: plugins/sudoers/def_data.c:496
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Mode de permission à utiliser sur les fichiers de journaux des E/S : 0%o"
+
+#: plugins/sudoers/def_data.c:500
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Exécuter les commandes par descripteur de fichier plutôt que par chemin : %s"
+
+#: plugins/sudoers/def_data.c:504
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Ignorer les entrées « Defaults » inconnues dans sudoers au lieu d'afficher un avertissement"
+
+#: plugins/sudoers/def_data.c:508
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Temps en secondes après lequel la commande sera terminée : %u"
+
+#: plugins/sudoers/def_data.c:512
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Autoriser l'utilisateur à spécifier un délai d'expiration sur la ligne de commande"
+
+#: plugins/sudoers/def_data.c:516
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Forcer l'écriture des données du journal d'E/S sur disque immédiatement au lieu de les garde dans un tampon"
+
+#: plugins/sudoers/def_data.c:520
+msgid "Include the process ID when logging via syslog"
+msgstr "Inclure le ID du processus lors de la journalisation via syslog"
+
+#: plugins/sudoers/def_data.c:524
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Type de l'enregistrement de l'horodatage de l'authentification : %s"
+
+#: plugins/sudoers/def_data.c:528
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Message de l'échec de l'authentification : %s"
+
+#: plugins/sudoers/def_data.c:532
+msgid "Ignore case when matching user names"
+msgstr "Ignorer la casse lors de la correspondance des noms d'utilisateurs"
+
+#: plugins/sudoers/def_data.c:536
+msgid "Ignore case when matching group names"
+msgstr "Ignorer la casse lors de la correspondance des noms de groupes"
+
+#: plugins/sudoers/def_data.c:540
+msgid "Log when a command is allowed by sudoers"
+msgstr "Écrire dans le journal lorsqu'une commande est autorisée par sudoers"
+
+#: plugins/sudoers/def_data.c:544
+msgid "Log when a command is denied by sudoers"
+msgstr "Écrire dans le journal lorsqu'une commande est interdite par sudoers"
+
+#: plugins/sudoers/def_data.c:548
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "Serveur(s) des journaux sudo auquel se connecter avec un port facultatif"
+
+#: plugins/sudoers/def_data.c:552
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Délai d'expiration du serveur des journaux sudo en seconde : %u"
+
+#: plugins/sudoers/def_data.c:556
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "Activer l'option SO_KEEPALIVE du socket sur le socket connecté au serveur de journal"
+
+#: plugins/sudoers/def_data.c:560
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "Emplacement du fichier du paquet du CA d'audit du serveur : %s"
+
+#: plugins/sudoers/def_data.c:564
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "Emplacement du fichier de certificat de sudoers : %s"
+
+#: plugins/sudoers/def_data.c:568
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "Emplacement du fichier de clé privée de sudoers : %s"
+
+#: plugins/sudoers/def_data.c:572
+msgid "Verify that the log server's certificate is valid"
+msgstr "Vérifier que le certificat du serveur contenant le journal est valide"
+
+#: plugins/sudoers/def_data.c:576
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "Autoriser l'utilisation d'ID d'utilisateurs ou de groupe inconnus dans runas"
+
+#: plugins/sudoers/def_data.c:580
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "Uniquement autoriser l'exécutions de commandes en tant qu'un utilisateur avec un interpréteur de commande valide"
+
+#: plugins/sudoers/def_data.c:584
+msgid "Set the pam remote user to the user running sudo"
+msgstr "Définir l'utilisateur distant de pam à l'utilisateur qui exécute sudo"
+
+#: plugins/sudoers/def_data.c:588
+msgid "Set the pam remote host to the local host name"
+msgstr "Définir l'hôte distant de pam au nom de l'hôte local"
+
+#: plugins/sudoers/def_data.c:592
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "Le répertoire de travail à utiliser avant d'exécuter la commande : %s"
+
+#: plugins/sudoers/def_data.c:596
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "Le répertoire racine à utiliser avant d'exécuter la commande : %s"
+
+#: plugins/sudoers/def_data.c:600
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "Format des journaux à produire : %s"
+
+#: plugins/sudoers/def_data.c:604
+msgid "Enable SELinux RBAC support"
+msgstr "Activer le support pour SELinux RBAC"
+
+#: plugins/sudoers/def_data.c:608
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "Chemin vers le fichier qui est créé la première fois que sudo est exécuté : %s"
+
+#: plugins/sudoers/def_data.c:612
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "Intercepter les commandes suivantes et leur appliquer les restrictions sudoers"
+
+#: plugins/sudoers/def_data.c:616
+msgid "Log sub-commands run by the original command"
+msgstr "Consigner les sous-commandes exécutées par la commande originale"
+
+#: plugins/sudoers/def_data.c:620
+msgid "Log the exit status of commands"
+msgstr "Consigner le code de retour des commandes"
+
+#: plugins/sudoers/def_data.c:624
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr "Les commandes ultérieures dans une session interceptée doivent être authentifiées"
+
+#: plugins/sudoers/def_data.c:628
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr "Autoriser une commande interceptée à exécuter des programmes avec le fanion setuid ou setgid activé"
+
+#: plugins/sudoers/def_data.c:632
+#, c-format
+msgid "The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr "La taille maximale à laquelle l'espace d'adresses du processus peut grandir (en octets) : %s"
+
+#: plugins/sudoers/def_data.c:636
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr "La taille de la plus grande vidange système qui peut être créée (en octets) : %s"
+
+#: plugins/sudoers/def_data.c:640
+#, c-format
+msgid "The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr "Le temps CPU maximum que le processus peut utiliser (en secondes) : %s"
+
+#: plugins/sudoers/def_data.c:644
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr "La taille maximale du segment de données pour le processus (en octets) : %s"
+
+#: plugins/sudoers/def_data.c:648
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr "La taille la plus grande d'un fichier que le processus peut créer (en octets) : %s"
+
+#: plugins/sudoers/def_data.c:652
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr "Le nombre maximum de verrous que le processus peut établir : %s"
+
+#: plugins/sudoers/def_data.c:656
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr "La taille maximale que le processus peut verrouiller en mémoire (en octets) : %s"
+
+#: plugins/sudoers/def_data.c:660
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr "Le nombre maximum de fichiers que le processus peut garder ouverts : %s"
+
+#: plugins/sudoers/def_data.c:664
+#, c-format
+msgid "The maximum number of processes that the user may run simultaneously: %s"
+msgstr "Le nombre maximum de processus que l'utilisateur peut exécuter simultanément : %s"
+
+#: plugins/sudoers/def_data.c:668
+#, c-format
+msgid "The maximum size to which the process's resident set size may grow (in bytes): %s"
+msgstr "La taille maximale à laquelle l'ensemble résident du processus peut grandir (en octets) : %s"
+
+#: plugins/sudoers/def_data.c:672
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr "La taille maximale à laquelle la pile du processus peut grandir (en octets) : %s"
+
+#: plugins/sudoers/def_data.c:676
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr "Tenter une authentification même dans le mode non interactif"
+
+#: plugins/sudoers/def_data.c:680
+msgid "Store plaintext passwords in I/O log input"
+msgstr "Stocker le mot de passe en clair dans l'entrée du journal des E/S"
+
+#: plugins/sudoers/def_data.c:684
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr "Liste des expressions régulières à utiliser lors de la recherche de correspondance de l'invite du mot de passe"
+
+#: plugins/sudoers/def_data.c:688
+#, c-format
+msgid "The mechanism used by the intercept and log_subcmds options: %s"
+msgstr "Le mécanisme utilisé par les options intercept et log_subcmds : %s"
+
+#: plugins/sudoers/def_data.c:692
+msgid "Attempt to verify the command and arguments after execution"
+msgstr "Tentative de vérifier la commande et les arguments après l'exécution"
+
+#: plugins/sudoers/def_data.c:696
+#, c-format
+msgid "AppArmor profile to use in the new security context: %s"
+msgstr "Profil AppArmor à utiliser dans le nouveau contexte de sécurité : %s"
+
+#: plugins/sudoers/defaults.c:207
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "entrée par défaut inconnue « %s »"
+
+#: plugins/sudoers/defaults.c:251
+#, c-format
+msgid "no value specified for \"%s\""
+msgstr "pas de valeur précisée pour « %s »"
+
+#: plugins/sudoers/defaults.c:260
+#, c-format
+msgid "invalid operator \"%c=\" for \"%s\""
+msgstr "opérateur « %c= » invalide pour « %s »"
+
+#: plugins/sudoers/defaults.c:292
+#, c-format
+msgid "option \"%s\" does not take a value"
+msgstr "l'option « %s » ne prend pas de valeur"
+
+#: plugins/sudoers/defaults.c:319
+#, c-format
+msgid "invalid Defaults type 0x%x for option \"%s\""
+msgstr "type Defaults 0x%x invalide pour l'option «␣%s␣»"
+
+#: plugins/sudoers/defaults.c:326
+#, c-format
+msgid "value \"%s\" is invalid for option \"%s\""
+msgstr "la valeur « %s » ne convient pas pour l'option « %s »"
+
+#: plugins/sudoers/defaults.c:1176 plugins/sudoers/policy.c:213
+#: plugins/sudoers/policy.c:222
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr "chemin trop long pour « %s »"
+
+#: plugins/sudoers/defaults.c:1182
+#, c-format
+msgid "values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "les valeurs de « %s » doivent commencer par « / », « ~ » ou « * »"
+
+#: plugins/sudoers/defaults.c:1189
+#, c-format
+msgid "values for \"%s\" must start with a '/'"
+msgstr "les valeurs de « %s » doivent commencer par « / »"
+
+#: plugins/sudoers/display.c:160
+#, c-format
+msgid "LDAP Role: %s\n"
+msgstr "Rôle LDAP : %s\n"
+
+#: plugins/sudoers/display.c:163
+#, c-format
+msgid "Sudoers entry: %s\n"
+msgstr "Entrée sudoers : %s\n"
+
+#: plugins/sudoers/display.c:166
+msgid " RunAsUsers: "
+msgstr " RunAsUsers : "
+
+#: plugins/sudoers/display.c:181
+msgid " RunAsGroups: "
+msgstr " RunAsGroups : "
+
+#: plugins/sudoers/display.c:191
+msgid " Options: "
+msgstr " Options : "
+
+#: plugins/sudoers/display.c:255
+msgid " Commands:\n"
+msgstr " Commandes :\n"
+
+#: plugins/sudoers/display.c:478
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Entrées Defaults correspondant pour %s sur %s :\n"
+
+#: plugins/sudoers/display.c:496
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Paramètres par défaut de runas ou spécifiques aux commandes pour %s :\n"
+
+#: plugins/sudoers/display.c:514
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "L'utilisateur %s peut utiliser les commandes suivantes sur %s :\n"
+
+#: plugins/sudoers/display.c:530
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "L'utilisateur %s n'est pas autorisé à exécuter sudo sur %s.\n"
+
+#: plugins/sudoers/editor.c:180
+#, c-format
+msgid "ignoring editor: %.*s"
+msgstr "éditeur ignoré : %.*s"
+
+#: plugins/sudoers/editor.c:181
+msgid "editor arguments may not contain \"--\""
+msgstr "les arguments de l'éditeur ne peuvent pas contenir « -- »"
+
+#: plugins/sudoers/env.c:426
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv : envp est corrompu, longueur incorrecte"
+
+#: plugins/sudoers/env.c:1119
+msgid "unable to rebuild the environment"
+msgstr "impossible de créer à nouveau l'environnement"
+
+#: plugins/sudoers/env.c:1199
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "désolé, vous n'êtes pas autorisé à définir ces variables d'environnement : %s"
+
+#: plugins/sudoers/filedigest.c:50
+#, c-format
+msgid "unsupported digest type %u for %s"
+msgstr "le type résumé (digest type) %u pour n'est pas autorisé pour %s"
+
+#: plugins/sudoers/filedigest.c:77
+#, c-format
+msgid "%s: read error"
+msgstr "%s : erreur en lecture"
+
+#: plugins/sudoers/group_plugin.c:169 plugins/sudoers/sssd.c:578
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "chargement de %s impossible : %s"
+
+#: plugins/sudoers/group_plugin.c:181
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "le symbole « group_plugin » est introuvable dans %s"
+
+#: plugins/sudoers/group_plugin.c:186
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s : la version majeure %d du greffon group est incompatible, la version attendue est %d"
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "impossible de reconnaître le format de l'adresse IP « %s »"
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "impossible de reconnaître le format du masque de sous-réseau « %s »"
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Couples adresse IP locale/masque de sous-réseau :\n"
+
+#: plugins/sudoers/iolog.c:694
+msgid "unable to update sequence file"
+msgstr "mise à jour du fichier de séquence impossible"
+
+#: plugins/sudoers/iolog.c:728 plugins/sudoers/iolog.c:917
+#: plugins/sudoers/iolog.c:1080 plugins/sudoers/iolog.c:1087
+#: plugins/sudoers/iolog.c:1209 plugins/sudoers/iolog.c:1216
+#: plugins/sudoers/iolog.c:1316 plugins/sudoers/iolog.c:1323
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "impossible d'écrire dans le journal des E/S : %s"
+
+#: plugins/sudoers/iolog.c:736
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "impossible de créer %s/%s"
+
+#: plugins/sudoers/iolog.c:965
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: erreur interne, le fichier journal des E/S pour l'événement %d n'est pas ouvert"
+
+#: plugins/sudoers/iolog.c:1065 plugins/sudoers/iolog.c:1194
+#: plugins/sudoers/iolog.c:1300 plugins/sudoers/timestamp.c:897
+#: plugins/sudoers/timestamp.c:989 plugins/sudoers/visudo.c:555
+#: plugins/sudoers/visudo.c:561
+msgid "unable to read the clock"
+msgstr "lecture de l'horloge impossible"
+
+#: plugins/sudoers/iolog.c:1292 plugins/sudoers/log_client.c:1203
+#: plugins/sudoers/log_client.c:1213 plugins/sudoers/log_client.c:1217
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: erreur interne, signal %d invalide"
+
+#: plugins/sudoers/ldap.c:154 plugins/sudoers/ldap_conf.c:289
+msgid "starttls not supported when using ldaps"
+msgstr "starttls n'est pas pris en charge lors de l'utilisation de ldap"
+
+#: plugins/sudoers/ldap.c:226
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "impossible d'initialiser le certificat SSL et la base de clés : %s"
+
+#: plugins/sudoers/ldap.c:229
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "TLS_CERT doit être défini dans %s pour pouvoir utiliser SSL"
+
+#: plugins/sudoers/ldap.c:1593
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "initialisation de LDAP impossible : %s"
+
+#: plugins/sudoers/ldap.c:1630
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls est spécifié mais les bibliothèques LDAP ne gèrent pas ldap_start_tls_s() ou ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:1767 plugins/sudoers/parse_ldif.c:745
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "attribut sudoOrder invalide : %s"
+
+#: plugins/sudoers/ldap_conf.c:197
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: port trop grand"
+
+#: plugins/sudoers/ldap_conf.c:258
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "type d'uri LDAP non pris en charge : %s"
+
+#: plugins/sudoers/ldap_conf.c:285
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "fusion des URIs ldap et ldaps impossible"
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "sudoOption dupliqué : %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "impossible de convertir sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "ouverture du fichier d'audit du système impossible"
+
+#: plugins/sudoers/linux_audit.c:104
+msgid "unable to send audit message"
+msgstr "envoi du message d'audit impossible"
+
+#: plugins/sudoers/log_client.c:125 plugins/sudoers/log_client.c:412
+#: plugins/sudoers/log_client.c:1450 plugins/sudoers/log_client.c:2076
+msgid "error in event loop"
+msgstr "erreur dans la boucle des événements"
+
+#: plugins/sudoers/log_client.c:205
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "La création du nouvel objet SSL_CTX a échoué : %s"
+
+#: plugins/sudoers/log_client.c:230
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "impossible de charger le paquet de l'autorité du certificat %s"
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "impossible de charger le certificat %s"
+
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "unable to load private key %s"
+msgstr "impossible de charger la clé privée %s"
+
+#: plugins/sudoers/log_client.c:275
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "Impossible d'allouer l'objet ssl : %s"
+
+#: plugins/sudoers/log_client.c:364 plugins/sudoers/log_client.c:369
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "la connexion TLS à %s:%s a échoué : %s"
+
+#: plugins/sudoers/log_client.c:545
+msgid "TLS initialization was unsuccessful"
+msgstr "l'initialisation TLS n'a pas réussi"
+
+#: plugins/sudoers/log_client.c:555
+msgid "TLS handshake was unsuccessful"
+msgstr "la négociation TLS n'a pas réussi"
+
+#: plugins/sudoers/log_client.c:1221
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: erreur interne, statut de sortie %d invalide"
+
+#: plugins/sudoers/log_client.c:1757 plugins/sudoers/log_client.c:1782
+msgid "lost connection to log server"
+msgstr "perte de la connexion au serveur de journalisation"
+
+#: plugins/sudoers/log_client.c:1859
+msgid "missing write buffer"
+msgstr "tampon d'écriture manquant"
+
+#: plugins/sudoers/log_client.c:2015
+msgid "unable to connect to log server"
+msgstr "impossible de se connecter au serveur de journal"
+
+#: plugins/sudoers/logging.c:295
+msgid "user NOT in sudoers"
+msgstr "l'utilisateur n'apparaît PAS dans sudoers"
+
+#: plugins/sudoers/logging.c:297
+msgid "user NOT authorized on host"
+msgstr "l'utilisateur n'est PAS autorisé sur cet hôte"
+
+#: plugins/sudoers/logging.c:299
+msgid "command not allowed"
+msgstr "commande non autorisée"
+
+#: plugins/sudoers/logging.c:320
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr "%s n'est pas dans le fichier sudoers.\n"
+
+#: plugins/sudoers/logging.c:323
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr "%s n'est pas autorisé à exécuter sudo sur %s.\n"
+
+#: plugins/sudoers/logging.c:326
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Désolé, l'utilisateur %s ne peut pas utiliser sudo sur %s.\n"
+
+#: plugins/sudoers/logging.c:339
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s%s' as %s%s%s on %s.\n"
+msgstr "Désolé, l'utilisateur %s n'est pas autorisé à exécuter « %s%s%s%s » en tant que %s%s%s sur %s.\n"
+
+#: plugins/sudoers/logging.c:350
+msgid "This incident has been reported to the administrator.\n"
+msgstr "Cet incident a été signalé à l'administrateur.\n"
+
+#: plugins/sudoers/logging.c:387 plugins/sudoers/sudoers.c:547
+#: plugins/sudoers/sudoers.c:549 plugins/sudoers/sudoers.c:551
+#: plugins/sudoers/sudoers.c:553 plugins/sudoers/sudoers.c:777
+#: plugins/sudoers/sudoers.c:779
+#, c-format
+msgid "%s: command not found"
+msgstr "%s : commande introuvable"
+
+#: plugins/sudoers/logging.c:389 plugins/sudoers/sudoers.c:543
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"« %s » trouvé dans « . » n'a pas été exécuté\n"
+"Utilisez « sudo ./%s » si c'est bien la version de « %s » que vous souhaitez exécuter."
+
+#: plugins/sudoers/logging.c:409
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u saisie de mot de passe incorrecte"
+msgstr[1] "%u saisies de mots de passe incorrectes"
+
+#: plugins/sudoers/logging.c:500
+msgid "authentication failure"
+msgstr "échec de l'authentification"
+
+#: plugins/sudoers/logging.c:539 plugins/sudoers/logging.c:558
+msgid "a password is required"
+msgstr "il est nécessaire de saisir un mot de passe"
+
+#: plugins/sudoers/logging.c:881
+msgid "problem parsing sudoers"
+msgstr "problème lors de l'analyse syntaxique de sudoers"
+
+#: plugins/sudoers/logging.c:922 plugins/sudoers/logging.c:930
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr "%s:%d:%d: %s"
+
+#: plugins/sudoers/logging.c:1108
+#, c-format
+msgid "unable to write log file %s"
+msgstr "impossible d'écrire le fichier journal %s"
+
+#: plugins/sudoers/match_digest.c:107
+#, c-format
+msgid "digest for %s (%s) bad length %zu, expected %zu"
+msgstr "le résumé (digest) de %s (%s) a la mauvaise longueur %zu, %zu attendue"
+
+#: plugins/sudoers/match_digest.c:126
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "le résume (digest) de %s (%s) n'est pas dans le forme %s"
+
+#: plugins/sudoers/parse_ldif.c:615
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "le sudoRole incomplet est ignoré : cn : %s"
+
+#: plugins/sudoers/parse_ldif.c:675
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "attribut LDIF invalide : %s"
+
+#: plugins/sudoers/parser_warnx.c:56
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: plugins/sudoers/parser_warnx.c:59
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s : %s\n"
+
+#: plugins/sudoers/pivot.c:71
+msgid "unable to restore root directory"
+msgstr "restauration du répertoire racine impossible"
+
+#: plugins/sudoers/pivot.c:79
+msgid "unable to restore current working directory"
+msgstr "restauration du répertoire de travail impossible"
+
+#: plugins/sudoers/policy.c:78 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "%.*s invalide défini par l'interface utilisateur de sudo"
+
+#: plugins/sudoers/policy.c:364 plugins/sudoers/testsudoers.c:329
+msgid "unable to parse network address list"
+msgstr "impossible d'analyser la liste des adresses réseau"
+
+#: plugins/sudoers/policy.c:556
+msgid "user name not set by sudo front-end"
+msgstr "nom d'utilisateur pas défini par l'interface utilisateur de sudo"
+
+#: plugins/sudoers/policy.c:560
+msgid "user-ID not set by sudo front-end"
+msgstr "ID utilisateur pas défini par l'interface utilisateur de sudo"
+
+#: plugins/sudoers/policy.c:564
+msgid "group-ID not set by sudo front-end"
+msgstr "ID de groupe pas défini par l'interface utilisateur de sudo"
+
+#: plugins/sudoers/policy.c:568
+msgid "host name not set by sudo front-end"
+msgstr "nom d'hôte pas défini par l'interface utilisateur de sudo"
+
+#: plugins/sudoers/policy.c:757
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "répertoire de travail invalide : %s"
+
+#: plugins/sudoers/policy.c:944
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "répertoire chroot invalide : %s"
+
+#: plugins/sudoers/policy.c:1153 plugins/sudoers/visudo.c:919
+#: plugins/sudoers/visudo.c:1218
+#, c-format
+msgid "unable to execute %s"
+msgstr "exécution de %s impossible"
+
+#: plugins/sudoers/policy.c:1225 plugins/sudoers/policy.c:1260
+#: plugins/sudoers/policy.c:1282 plugins/sudoers/policy.c:1300
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: fanions de mode invalides dans l'interface utilisateur de sudo : 0x%x"
+
+#: plugins/sudoers/policy.c:1323
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "La version du greffon de politique de sudoers est %s\n"
+
+#: plugins/sudoers/policy.c:1325
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "La version de la grammaire du fichier sudoers est %d\n"
+
+#: plugins/sudoers/policy.c:1329
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Chemin d'accès à sudoers : %s\n"
+
+#: plugins/sudoers/policy.c:1332
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "chemin d'accès à nsswitch : %s\n"
+
+#: plugins/sudoers/policy.c:1335
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "chemin d'accès à ldap.conf : %s\n"
+
+#: plugins/sudoers/policy.c:1337
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "chemin d'accès à ldap.secret : %s\n"
+
+#: plugins/sudoers/policy.c:1370
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "activation d'un point d'ancrage de type %d (version %d.%d) impossible"
+
+#: plugins/sudoers/policy.c:1388
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "désactivation d'un point d'ancrage de type %d (version %d.%d) impossible"
+
+#: plugins/sudoers/pwutil.c:242 plugins/sudoers/pwutil.c:260
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "enregistrement de l'uid %u dans le cache impossible"
+
+#: plugins/sudoers/pwutil.c:254
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "enregistrement de l'uid %u dans le cache impossible, l'entrée existe déjà"
+
+#: plugins/sudoers/pwutil.c:314 plugins/sudoers/pwutil.c:332
+#: plugins/sudoers/pwutil.c:395 plugins/sudoers/pwutil.c:440
+#, c-format
+msgid "unable to cache user %s"
+msgstr "impossible d'écrire l'utilisateur %s dans la cache"
+
+#: plugins/sudoers/pwutil.c:327
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "enregistrement des informations de l'utilisateur %s dans le cache impossible, l'entrée existe déjà"
+
+#: plugins/sudoers/pwutil.c:559 plugins/sudoers/pwutil.c:577
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "enregistrement du gid %u dans le cache impossible"
+
+#: plugins/sudoers/pwutil.c:571
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "enregistrement du gid %u dans le cache impossible, l'entrée existe déjà"
+
+#: plugins/sudoers/pwutil.c:625 plugins/sudoers/pwutil.c:643
+#: plugins/sudoers/pwutil.c:704 plugins/sudoers/pwutil.c:753
+#, c-format
+msgid "unable to cache group %s"
+msgstr "impossible d'écrire le groupe %s dans la cache"
+
+#: plugins/sudoers/pwutil.c:638
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "enregistrement du groupe %s dans le cache impossible, l'entrée existe déjà"
+
+#: plugins/sudoers/pwutil.c:900 plugins/sudoers/pwutil.c:985
+#: plugins/sudoers/pwutil.c:1039 plugins/sudoers/pwutil.c:1095
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "enregistrement de la liste de groupe %s dans le cache impossible, l'entrée existe déjà"
+
+#: plugins/sudoers/pwutil.c:906 plugins/sudoers/pwutil.c:990
+#: plugins/sudoers/pwutil.c:1045 plugins/sudoers/pwutil.c:1100
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "impossible d'écrire la liste de groupes dans la cache pour %s"
+
+#: plugins/sudoers/pwutil.c:979
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "impossible d'analyser les groupes pour %s"
+
+#: plugins/sudoers/pwutil.c:1089
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "impossible d'analyser les gids pour %s"
+
+#: plugins/sudoers/set_perms.c:120 plugins/sudoers/set_perms.c:457
+#: plugins/sudoers/set_perms.c:870 plugins/sudoers/set_perms.c:1186
+#: plugins/sudoers/set_perms.c:1490
+msgid "perm stack overflow"
+msgstr "débordement de la pile perm"
+
+#: plugins/sudoers/set_perms.c:131 plugins/sudoers/set_perms.c:387
+#: plugins/sudoers/set_perms.c:468 plugins/sudoers/set_perms.c:736
+#: plugins/sudoers/set_perms.c:881 plugins/sudoers/set_perms.c:1109
+#: plugins/sudoers/set_perms.c:1197 plugins/sudoers/set_perms.c:1422
+#: plugins/sudoers/set_perms.c:1501 plugins/sudoers/set_perms.c:1592
+msgid "perm stack underflow"
+msgstr "débordement inférieur de la pile perm"
+
+#: plugins/sudoers/set_perms.c:191 plugins/sudoers/set_perms.c:515
+#: plugins/sudoers/set_perms.c:1251 plugins/sudoers/set_perms.c:1535
+msgid "unable to change to root gid"
+msgstr "changement de l'identificateur de groupe (gid) de root impossible"
+
+#: plugins/sudoers/set_perms.c:282 plugins/sudoers/set_perms.c:612
+#: plugins/sudoers/set_perms.c:1013 plugins/sudoers/set_perms.c:1328
+msgid "unable to change to runas gid"
+msgstr "changement du groupe effectif (runas) impossible"
+
+#: plugins/sudoers/set_perms.c:287 plugins/sudoers/set_perms.c:617
+#: plugins/sudoers/set_perms.c:1018 plugins/sudoers/set_perms.c:1333
+msgid "unable to set runas group vector"
+msgstr "définition du vecteur du groupe effectif (runas) impossible"
+
+#: plugins/sudoers/set_perms.c:298 plugins/sudoers/set_perms.c:628
+#: plugins/sudoers/set_perms.c:1027 plugins/sudoers/set_perms.c:1342
+msgid "unable to change to runas uid"
+msgstr "changement de l'uid effectif (runas) impossible"
+
+#: plugins/sudoers/set_perms.c:320 plugins/sudoers/set_perms.c:650
+#: plugins/sudoers/set_perms.c:1047 plugins/sudoers/set_perms.c:1362
+msgid "unable to change to sudoers gid"
+msgstr "changement du groupe (gid) de sudoers impossible"
+
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579
+msgid "too many processes"
+msgstr "trop de processus"
+
+#: plugins/sudoers/solaris_audit.c:62
+msgid "unable to get current working directory"
+msgstr "récupération du répertoire de travail impossible"
+
+#: plugins/sudoers/solaris_audit.c:70
+#, c-format
+msgid "truncated audit path ctx->user.cmnd: %s"
+msgstr "le chemin d'accès à l'audit ctx->user.cmnd a été tronqué : %s"
+
+#: plugins/sudoers/solaris_audit.c:77
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "le chemin d'accès à l'audit argv[0] a été tronqué : %s"
+
+#: plugins/sudoers/sssd.c:581
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "initialisation de la source SSS impossible. SSSD est-il installé sur cette machine ?"
+
+#: plugins/sudoers/sssd.c:589 plugins/sudoers/sssd.c:598
+#: plugins/sudoers/sssd.c:607 plugins/sudoers/sssd.c:616
+#: plugins/sudoers/sssd.c:625
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "Le symbole « %s » est introuvable dans %s"
+
+#: plugins/sudoers/sudoers.c:250
+#, c-format
+msgid "unable to get defaults from %s"
+msgstr "impossible d'obtenir les valeurs par défaut pour %s"
+
+#: plugins/sudoers/sudoers.c:259
+msgid "no valid sudoers sources found, quitting"
+msgstr "aucune source sudoers valide n'a été trouvée, fin d'exécution"
+
+#: plugins/sudoers/sudoers.c:366
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "il est précisé dans sudoers que root n'est pas autorisé à utiliser sudo"
+
+#: plugins/sudoers/sudoers.c:375
+msgid "user not allowed to override closefrom limit"
+msgstr "l'utilisateur n'est pas autorisé à outrepasser la limite closeform"
+
+#: plugins/sudoers/sudoers.c:376
+msgid "you are not permitted to use the -C option"
+msgstr "vous n'êtes pas autorisé à utiliser l'option -C"
+
+#: plugins/sudoers/sudoers.c:440
+msgid "no tty"
+msgstr "pas de terminal tty"
+
+#: plugins/sudoers/sudoers.c:441
+msgid "sorry, you must have a tty to run sudo"
+msgstr "désolé, vous devez avoir un terminal tty pour exécuter sudo"
+
+#: plugins/sudoers/sudoers.c:449
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "interpréteur de commande invalide pour l'utilisateur %s : %s"
+
+#: plugins/sudoers/sudoers.c:491
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "l'utilisateur n'est pas autorisé à changer le répertoire racine en %s"
+
+#: plugins/sudoers/sudoers.c:493
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "vous n'êtes pas autorisé à utiliser l'option -R avec %s"
+
+#: plugins/sudoers/sudoers.c:506
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "l'utilisateur n'est pas autorisé à changer de répertoire vers %s"
+
+#: plugins/sudoers/sudoers.c:507
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "vous n'êtes pas autorisé à utiliser l'option -D avec %s"
+
+#: plugins/sudoers/sudoers.c:542
+msgid "command in current directory"
+msgstr "commande dans le répertoire courant"
+
+#: plugins/sudoers/sudoers.c:557
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr "« cd » est une commande interne du shell, elle ne peut pas être exécutée directement."
+
+#: plugins/sudoers/sudoers.c:559
+msgid "the -s option may be used to run a privileged shell."
+msgstr "l'option -s peut être utilisée pour exécuter un shell privilégié."
+
+#: plugins/sudoers/sudoers.c:561
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr "l'option -D peut être utilisée pour exécuter une commande dans un répertoire spécifique."
+
+#: plugins/sudoers/sudoers.c:570
+msgid "user not allowed to set a command timeout"
+msgstr "l'utilisateur n'est pas autorisé à définir un délai d'expiration de la commande"
+
+#: plugins/sudoers/sudoers.c:572
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "désolé, vous n'êtes pas autorisé à définir un délai d'expiration de la commande"
+
+#: plugins/sudoers/sudoers.c:580
+msgid "user not allowed to preserve the environment"
+msgstr "l'utilisateur n'est pas autorisé à conserver l'environnement"
+
+#: plugins/sudoers/sudoers.c:582
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "désolé, vous n'êtes pas autorisé à conserver l'environnement"
+
+#: plugins/sudoers/sudoers.c:618
+msgid "no command specified"
+msgstr "aucune commande spécifiée"
+
+#: plugins/sudoers/sudoers.c:759
+msgid "error setting user-specified environment variables"
+msgstr "erreur en définissant les variables d'environnement spécifiées par l'utilisateur"
+
+#: plugins/sudoers/sudoers.c:1211
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "sudoedit n'a pas besoin d'être exécuté via sudo"
+
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:1613
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "lecture de %s impossible"
+
+#: plugins/sudoers/sudoers.c:1321 plugins/sudoers/visudo.c:1123
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s n'est pas un fichier ordinaire"
+
+#: plugins/sudoers/sudoers.c:1325 plugins/sudoers/timestamp.c:272 toke.l:1355
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "Le fichier %s est la propriété de l'utilisateur (uid) %u, alors qu'il devrait appartenir à %u"
+
+#: plugins/sudoers/sudoers.c:1330 plugins/sudoers/timestamp.c:279 toke.l:1360
+#, c-format
+msgid "%s is world writable"
+msgstr "Le fichier %s est ouvert en écriture pour tous"
+
+#: plugins/sudoers/sudoers.c:1334 plugins/sudoers/timestamp.c:284 toke.l:1363
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "Le fichier %s a pour groupe (gid) %u, alors qu'il devrait appartenir au groupe %u"
+
+#: plugins/sudoers/sudoers.c:1363
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "« -c %s » est réservé à l'utilisateur root"
+
+#: plugins/sudoers/sudoers.c:1382
+#, c-format
+msgid "unknown login class %s"
+msgstr "classe de connexion %s inconnue"
+
+#: plugins/sudoers/sudoers_cb.c:120 plugins/sudoers/sudoers_cb.c:135
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "impossible de résoudre l'hôte %s"
+
+#: plugins/sudoers/sudoreplay.c:252
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "option du filtre invalide : %s"
+
+#: plugins/sudoers/sudoreplay.c:268
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "attente maximum invalide : %s"
+
+#: plugins/sudoers/sudoreplay.c:291
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "facteur de vitesse invalide : %s"
+
+#: plugins/sudoers/sudoreplay.c:326
+#, c-format
+msgid "invalid time offset %s"
+msgstr "décalage de temps i%s invalide"
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s : %s"
+
+#: plugins/sudoers/sudoreplay.c:340
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/timing : %s"
+
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Rejeu de la session sudo : %s"
+
+#: plugins/sudoers/sudoreplay.c:634
+msgid "unable to set tty to raw mode"
+msgstr "impossible d'initialiser le terminal tty en mode direct"
+
+#: plugins/sudoers/sudoreplay.c:685
+msgid "Warning: your terminal is too small to properly replay the log."
+msgstr "Attention : la taille du terminal n'est pas suffisante pour pouvoir rejouer correctement la séquence."
+
+#: plugins/sudoers/sudoreplay.c:686
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "La taille du journal est %d × %d, la taille de votre terminal est %d × %d."
+
+#: plugins/sudoers/sudoreplay.c:714
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Rejeu terminé, appuyez sur n'importe quelle touche pour rétablir le terminal."
+
+#: plugins/sudoers/sudoreplay.c:1217 plugins/sudoers/sudoreplay.c:1247
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "expression ambiguë « %s »"
+
+#: plugins/sudoers/sudoreplay.c:1269
+msgid "unmatched ')' in expression"
+msgstr "« ) » sans parenthèse ouvrante dans l'expression"
+
+#: plugins/sudoers/sudoreplay.c:1273
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "terme de recherche « %s » inconnu"
+
+#: plugins/sudoers/sudoreplay.c:1288
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s requiert un argument"
+
+#: plugins/sudoers/sudoreplay.c:1298
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "analyse de la date « %s » impossible"
+
+#: plugins/sudoers/sudoreplay.c:1307
+msgid "unmatched '(' in expression"
+msgstr "« ( » sans parenthèse fermante dans l'expression"
+
+#: plugins/sudoers/sudoreplay.c:1309
+msgid "illegal trailing \"or\""
+msgstr "« or » n'est pas autorisé en fin d'expression"
+
+#: plugins/sudoers/sudoreplay.c:1311
+msgid "illegal trailing \"!\""
+msgstr "« ! » n'est pas autorisé en fin d'expression"
+
+#: plugins/sudoers/sudoreplay.c:1417
+#, c-format
+msgid "unknown search type %d"
+msgstr "type de recherche %d inconnu"
+
+#: plugins/sudoers/sudoreplay.c:1679
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "utilisation : %s [-hnRS] [-d répertoire] [-m nombre] [-s nombre] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1681
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "utilisation : %s [-h] [-d répertoire] -l [expression recherchée]\n"
+
+#: plugins/sudoers/sudoreplay.c:1695
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - rejeu du journal de la session sudo\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1697
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Options :\n"
+" -d, --directory=rép indique le répertoire pour les journaux de sessions\n"
+" -f, --filter=filtre indique quel(s) type(s) E/S à afficher\n"
+" -h, --help affiche le message d'aide puis termine l'exécution\n"
+" -l, --list liste les identificateurs de sessions disponibles,\n"
+" il est possible d'ajouter une expression en paramètre\n"
+" -m, --max-wait=val nombre maximum de secondes de temporisation entre les événements\n"
+" -n, --non-interactive aucune demande, la session est envoyée sur la sortie standard\n"
+" -R, --no-resize ne pas tenter de redimensionner le terminal\n"
+" -S, --suspend-wait attend pendant que la commande a été suspendue\n"
+" -s, --speed=valeur accélère ou ralentit l'exécution\n"
+" -V, --version affiche la version du programme, puis termine l'exécution"
+
+#: plugins/sudoers/testsudoers.c:392
+#, c-format
+msgid ""
+"\n"
+"Invalid shell for user %s: %s\n"
+msgstr ""
+"\n"
+"Interpréteur de commande invalide pour l'utilisateur %s : %s\n"
+
+#: plugins/sudoers/testsudoers.c:411
+msgid ""
+"\n"
+"Password required"
+msgstr ""
+"\n"
+"Il est nécessaire de saisir un mot de passe"
+
+#: plugins/sudoers/testsudoers.c:422
+msgid ""
+"\n"
+"Parse error"
+msgstr ""
+"\n"
+"Erreur d'analyse grammaticale"
+
+#: plugins/sudoers/testsudoers.c:425
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Commande autorisée"
+
+#: plugins/sudoers/testsudoers.c:428
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Commande refusée"
+
+#: plugins/sudoers/testsudoers.c:431
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Commande sans correspondance"
+
+#: plugins/sudoers/timestamp.c:364 plugins/sudoers/timestamp.c:711
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "impossible de tronquer le fichier d'horodatage à %lld octets"
+
+#: plugins/sudoers/timestamp.c:908
+msgid "ignoring time stamp from the future"
+msgstr "un horodatage dans le futur a été ignoré"
+
+#: plugins/sudoers/timestamp.c:931
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "l'horodatage est trop avancé dans le future : %20.20s"
+
+#: plugins/sudoers/timestamp.c:1067
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "verrouillage du fichier d'horodatage %s impossible"
+
+#: plugins/sudoers/timestamp.c:1114
+#, c-format
+msgid "%s:%d:%d timestampowner: unknown user %s"
+msgstr "%s:%d:%d timestampowner : utilisateur %s inconnu"
+
+#: plugins/sudoers/toke_util.c:159
+msgid "sudoedit should not be specified with a path"
+msgstr "sudoedit ne devrait pas être spécifié avec un chemin"
+
+#: plugins/sudoers/visudo.c:308 plugins/sudoers/visudo.c:714
+#, c-format
+msgid "press return to edit %s: "
+msgstr "appuyer sur entrée pour éditer %s : "
+
+#: plugins/sudoers/visudo.c:323
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "le contenu de la session d'édition a été laissé dans %s"
+
+#: plugins/sudoers/visudo.c:401
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "l'éditeur indiqué (%s) n'existe pas"
+
+#: plugins/sudoers/visudo.c:406
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "aucun éditeur trouvé (chemin d'accès à l'éditeur : %s)"
+
+#: plugins/sudoers/visudo.c:494 plugins/sudoers/visudo.c:786
+#, c-format
+msgid "unable to stat %s"
+msgstr "impossible d'appliquer la fonction stat à %s"
+
+#: plugins/sudoers/visudo.c:514 plugins/sudoers/visudo.c:522
+msgid "write error"
+msgstr "erreur en écriture"
+
+#: plugins/sudoers/visudo.c:568
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "impossible d'appliquer la fonction stat au fichier temporaire (%s), %s n'a pas été modifié"
+
+#: plugins/sudoers/visudo.c:575
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "fichier temporaire vide (%s), %s n'a pas été modifié"
+
+#: plugins/sudoers/visudo.c:581
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "l'éditeur (%s) a échoué, %s n'a pas été modifié"
+
+#: plugins/sudoers/visudo.c:613
+#, c-format
+msgid "%s unchanged"
+msgstr "%s n'a pas été modifié"
+
+#: plugins/sudoers/visudo.c:661
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "impossible de rouvrir le fichier temporaire (%s), %s n'a pas été modifié."
+
+#: plugins/sudoers/visudo.c:674
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "impossible d'analyser le fichier temporaire (%s), erreur inconnue"
+
+#: plugins/sudoers/visudo.c:760 plugins/sudoers/visudo.c:790
+#: plugins/sudoers/visudo.c:797
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "impossible de définir (uid, gid) de %s à (%u, %u)"
+
+#: plugins/sudoers/visudo.c:825
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s et %s ne sont pas dans le même système de fichiers, tentative de renommage à l'aide de la commande mv"
+
+#: plugins/sudoers/visudo.c:836
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "la commande a échoué : « %s %s %s », %s n'a pas été modifié"
+
+#: plugins/sudoers/visudo.c:843
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "erreur lors du renommage de %s, %s n'a pas été modifié"
+
+#: plugins/sudoers/visudo.c:864
+msgid "What now? "
+msgstr "Et maintenant ?"
+
+#: plugins/sudoers/visudo.c:878
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Les options sont :\n"
+" (e)dition du fichier sudoers (de nouveau)\n"
+" e(x)it sans sauvegarde des modifications apportées au fichier sudoers\n"
+" (Q)uitter et sauvegarder les modifications apportées au fichier sudoers (DANGER!)\n"
+
+#: plugins/sudoers/visudo.c:923
+#, c-format
+msgid "unable to run %s"
+msgstr "exécution de %s impossible"
+
+#: plugins/sudoers/visudo.c:954
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s : mauvais propriétaire (uid, gid), celui-ci devrait être (%u,%u)\n"
+
+#: plugins/sudoers/visudo.c:965
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s : mauvais droits d'utilisation, le mode devrait être 0%o\n"
+
+#: plugins/sudoers/visudo.c:1017 plugins/sudoers/visudo.c:1024
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s : analyse réussie\n"
+
+#: plugins/sudoers/visudo.c:1043
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s n'est pas disponible, réessayez plus tard"
+
+#: plugins/sudoers/visudo.c:1047
+msgid "Edit anyway? [y/N]"
+msgstr "Éditer quand même ? [y/N]"
+
+#: plugins/sudoers/visudo.c:1206
+msgid "the -x option will be removed in a future release"
+msgstr "l'option -x sera supprimée dans une version ultérieure"
+
+#: plugins/sudoers/visudo.c:1208
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "envisagez plutôt l'utilisation de l'utilitaire cvtsudoers"
+
+#: plugins/sudoers/visudo.c:1228
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "Attention : %s:%d:%d: %s « %s » n'est pas utilisé"
+
+#: plugins/sudoers/visudo.c:1341
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - édite le fichier sudoers en toute sécurité\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1343
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -I, --no-includes do not edit include files\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Options :\n"
+" -c, --check mode de validation\n"
+" -f, --file=fichier précise l'emplacement du fichier sudoers\n"
+" -h, --help affiche l'aide puis termine l'exécution\n"
+" -I, --no-includes ne pas éditer les fichiers inclus\n"
+" -q, --quiet moins de messages d'erreur de syntaxe (mode silencieux)\n"
+" -s, --strict validation stricte de la syntaxe\n"
+" -V, --version affiche la version, puis termine l'exécution\n"
+
+#: toke.l:184
+msgid "empty string"
+msgstr "chaîne vide"
+
+#: toke.l:196 toke.l:566
+msgid "empty group"
+msgstr "groupe vide"
+
+#: toke.l:206 toke.l:564
+msgid "empty netgroup"
+msgstr "netgroup vide"
+
+#: toke.l:284
+msgid "unterminated regular expression"
+msgstr "expression régulière non terminée"
+
+#: toke.l:358 toke.l:370 toke.l:382 toke.l:398 toke.l:417 toke.l:457
+msgid "invalid line continuation"
+msgstr "la suite de la ligne est invalide"
+
+#: toke.l:603 toke.l:615
+msgid "invalid IPv6 address"
+msgstr "adresse IPv6 invalide"
+
+#: toke.l:863
+msgid "unexpected line break in string"
+msgstr "saut de ligne inattendu dans la chaîne"
+
+#: toke.l:982
+msgid "ignoring editor backup file"
+msgstr "le fichier de sauvegarde de l'éditeur est ignoré"
+
+#: toke.l:985
+msgid "ignoring file name containing '.'"
+msgstr "le nom de fichier contenant un « . » est ignoré"
+
+#: toke.l:1310
+msgid "too many levels of includes"
+msgstr "nombre de niveaux d'inclusions trop élevé"
+
+#~ msgid "\thost unmatched"
+#~ msgstr "\tl'hôte n'a pas de correspondance"
+
+#~ msgid "timestamp owner (%s): No such user"
+#~ msgstr "propriétaire du fichier d'horodatage (%s) : utilisateur inconnu"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s doit appartenir à l'utilisateur (uid) %d"
+
+#~ msgid "%s must only be writable by owner"
+#~ msgstr "seul le propriétaire doit avoir le droit en écriture sur %s"
+
+#~ msgid "%s is group writable"
+#~ msgstr "%s est accessible en écriture pour les membres du groupe"
+
+#~ msgid "lecture status path too long: %s/%s"
+#~ msgstr "le chemin d'accès au fichier d'état de la recommandation est trop long : %s/%s"
+
+#~ msgid "Warning: %s:%d:%d: cycle in %s \"%s\""
+#~ msgstr "Attention : %s:%d:%d: boucle dans %s « %s »"
+
+#~ msgid "Warning: %s:%d:%d: %s \"%s\" referenced but not defined"
+#~ msgstr "Attention : %s:%d:%d: il est fait mention de %s « %s » alors qu'il n'a pas été défini"
+
+#~ msgid "parse error in %s near line %d\n"
+#~ msgstr "erreur lors de l'analyse grammaticale de %s au environs de la ligne %d\n"
+
+#~ msgid "parse error in %s\n"
+#~ msgstr "erreur lors de l'analyse grammaticale de %s\n"
+
+#~ msgid "%s: unknown defaults entry \"%s\""
+#~ msgstr "%s: entrée par défaut inconnue « %s »"
+
+#~ msgid "%s:%d:%d: no value specified for \"%s\""
+#~ msgstr "%s:%d:%d: pas de valeur précisée pour « %s »"
+
+#~ msgid "%s:%d:%d: invalid operator \"%c=\" for \"%s\""
+#~ msgstr "%s:%d:%d: opérateur « %c= » invalide pour « %s »"
+
+#~ msgid "%s:%d:%d: option \"%s\" does not take a value"
+#~ msgstr "%s:%d:%d: l'option « %s » ne prend pas de valeur"
+
+#~ msgid "%s:%d:%d: invalid Defaults type 0x%x for option \"%s\""
+#~ msgstr "%s:%d:%d: type Defaults 0x%x invalide pour l'option « %s »"
+
+#~ msgid "%s:%d:%d: value \"%s\" is invalid for option \"%s\""
+#~ msgstr "%s:%d:%d: la valeur « %s » ne convient pas pour l'option « %s »"
+
+#~ msgid "%s:%d:%d: path name for \"%s\" too long"
+#~ msgstr "%s:%d:%d: chemin trop long pour « %s »"
+
+#~ msgid "%s: path name for \"%s\" too long"
+#~ msgstr "%s: chemin trop long pour « %s »"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/', '~', or '*'"
+#~ msgstr "%s:%d:%d: les valeurs de « %s » doivent commencer par « / », « ~ » ou « * »"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/'"
+#~ msgstr "%s:%d:%d: les valeurs de « %s » doivent commencer par « / »"
+
+#~ msgid "parse error in %s near line %d"
+#~ msgstr "erreur d'analyse grammaticale dans %s aux environs de la ligne %d"
+
+#~ msgid "parse error in %s"
+#~ msgstr "erreur d'analyse grammaticale dans %s"
+
+#~ msgid "SELinux RBAC is not supported when intercept mode is enabled"
+#~ msgstr "SELinux RBAC n'est pas supporté quand le mode d'interception est activé"
+
+#~ msgid "SELinux RBAC is not supported when the log_subcmds flag is enabled"
+#~ msgstr "SELinux RBAC n'est pas supporté quand le fanion log_subcmds est activé"
+
+#~ msgid "problem with defaults entries"
+#~ msgstr "les entrées par défaut posent un problème"
+
+#~ msgid "internal error, unable to find %s in list!"
+#~ msgstr "erreur interne, impossible de trouver %s dans la liste !"
+
+#~ msgid "%s is not in the sudoers file. This incident will be reported.\n"
+#~ msgstr "%s n'apparaît pas dans le fichier sudoers. Cet incident sera signalé.\n"
+
+#~ msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+#~ msgstr "%s n'est pas autorisé à exécuter sudo sur %s. Cet incident sera signalé.\n"
+
+#~ msgid "%s: write buffer already in use"
+#~ msgstr "%s: tampon d'écriture déjà en cours d'utilisation"
+
+#~ msgid "unable to read diffie-hellman parameters: %s"
+#~ msgstr "impossible de lire les paramètres diffie-hellman : %s"
+
+#~ msgid "%s:%d unknown key: %s"
+#~ msgstr "%s:%d clé inconnue : %s"
+
+#~ msgid "unable to get TLS server method: %s"
+#~ msgstr "impossible d'obtenir la méthode TLS du serveur : %s"
+
+#~ msgid "%s:%u unable to parse \"%s\""
+#~ msgstr "%s:%u analyse grammaticale (parse) de « %s » impossible"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " -f, --file path to configuration file\n"
+#~ " -h --help display help message and exit\n"
+#~ " -n, --no-fork do not fork, run in the foreground\n"
+#~ " -R, --random-drop percent chance connections will drop\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Options :\n"
+#~ " -f, --file chemin vers le fichier de configuration\n"
+#~ " -h, --help affiche l'aide puis termine l'exécution\n"
+#~ " -n, --no-fork ne pas démarrer une branche, exécuter au premier plan\n"
+#~ " -R, --random-drop pourcentage de chances que la connexion soit abandonnée\n"
+#~ " -V, --version affiche la version, puis termine l'exécution\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " --help display help message and exit\n"
+#~ " -A, --accept only send an accept event (no I/O)\n"
+#~ " -h, --host host to send logs to\n"
+#~ " -i, --iolog_id remote ID of I/O log to be resumed\n"
+#~ " -p, --port port to use when connecting to host\n"
+#~ " -r, --restart restart previous I/O log transfer\n"
+#~ " -R, --reject reject the command with the given reason\n"
+#~ " -b, --ca-bundle certificate bundle file to verify server's cert against\n"
+#~ " -c, --cert certificate file for TLS handshake\n"
+#~ " -k, --key private key file\n"
+#~ " -n, --no-verify do not verify server certificate\n"
+#~ " -t, --test test audit server by sending selected I/O log n times in parallel\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Options :\n"
+#~ " --help afficher le message d'aide puis terminer\n"
+#~ " -A, --accept n'envoyer qu'un événement d'acceptation (pas d'E/S)\n"
+#~ " -h, --host hôte à qui envoyer le journal\n"
+#~ " -i, --iolog_id ID distant du journal des E/S à redémarrer\n"
+#~ " -p, --port port à utiliser lors de la connexion à l'hôte\n"
+#~ " -r, --restart redémarrer le transfert du journal des E/S précédent\n"
+#~ " -R, --reject rejeter la commande avec la raison donnée\n"
+#~ " -b, --ca-bundle fichier du paquet de certificats avec lequel vérifier le certificat du serveur\n"
+#~ " -c, --cert fichier de certificat pour l'échange TLS\n"
+#~ " -k, --key fichier de la clé privée\n"
+#~ " -n, --no-verify ne pas vérifier le certificat du serveur\n"
+#~ " -t, --test tester le serveur d'audit en envoyant le journal des E/S sélectionné n fois en parallèle\n"
+#~ " -V, --version afficher les informations de version et terminer\n"
+
+#~ msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+#~ msgstr "Préchargement des fonctions d'exécution « à blanc » contenues dans la bibliothèque sudo_noexec"
+
+#~ msgid "sudo_ldap_conf_add_ports: port too large"
+#~ msgstr "sudo_ldap_conf_add_ports : valeur de port trop élevée"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s\n"
+#~ msgstr "SSL_connect a échoué : ssl_error=%d, pile=%s\n"
+
+#~ msgid "CA bundle file was not specified"
+#~ msgstr "le fichier du paquet CA n'a pas été spécifié"
+
+#~ msgid "Client certificate was not specified"
+#~ msgstr "Le certificat du client n'a pas été spécifié"
+
+#~ msgid "Unable to allocate ssl object: %s\n"
+#~ msgstr "Impossible d'allouer l'objet ssl : %s\n"
+
+#~ msgid "Unable to attach socket to the ssl object: %s\n"
+#~ msgstr "Impossible d'attacher le socket à l'objet ssl : %s\n"
+
+#~ msgid "client message too large: %zu\n"
+#~ msgstr "message client trop grand : %zu\n"
+
+#~ msgid "server message too large: %u\n"
+#~ msgstr "message serveur trop long : %u\n"
+
+#~ msgid "CA bundle file is not set in sudoers"
+#~ msgstr "Le fichier de paquet du CA n'est pas défini dans sudoers"
+
+#~ msgid "Calling SSL_CTX_load_verify_locations() failed: %s"
+#~ msgstr "L'appel de SSL_CTX_load_verify_locations() a échoué : %s"
+
+#~ msgid "Signed certificate file is not set in sudoers"
+#~ msgstr "Le fichier de certificat signé n'est pas défini dans sudoers"
+
+#~ msgid "Unable to load private key into the ssl context: %s"
+#~ msgstr "Impossible de charger la clé privée dans le contexte ssl : %s"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_connect a échoué : ssl_error=%d, pile=%s"
+
+#~ msgid "SSL_read failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_read a échoué : ssl_error=%d, pile=%s"
+
+#~ msgid "SSL_write failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_write a échoué : ssl_error=%d, pile=%s"
+
+#~ msgid "unknown address family: %d"
+#~ msgstr "famille d'adresse inconnue : %d"
+
+#~ msgid "audit_failure message too long"
+#~ msgstr "le message audit_failure est trop long"
+
+#~ msgid "No user or host"
+#~ msgstr "Pas d'utilisateur ou d'hôte"
+
+#~ msgid "validation failure"
+#~ msgstr "échec de la validation"
+
+#~ msgid "%s/%s/timing: %s"
+#~ msgstr "%s/%s/timing : %s"
+
+#~ msgid "ignoring invalid attribute value: %s"
+#~ msgstr "la valeur d'attribut invalide est ignorée : %s"
+
+#~ msgid "unable to cache user %s, out of memory"
+#~ msgstr "enregistrement des informations de l'utilisateur %s dans le cache impossible, mémoire insuffisante"
+
+#~ msgid "unable to cache group %s, out of memory"
+#~ msgstr "enregistrement du groupe %s dans le cache impossible, mémoire insuffisante"
+
+#~ msgid "unable to cache group list for %s, out of memory"
+#~ msgstr "enregistrement de la liste de groupe %s dans le cache impossible, mémoire insuffisante"
+
+#~ msgid ""
+#~ "\n"
+#~ "LDAP Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Rôle LDAP : INCONNU\n"
+
+#~ msgid " Order: %s\n"
+#~ msgstr " Ordre : %s\n"
+
+#~ msgid "timestamp path too long: %s/%s"
+#~ msgstr "Chemin d'accès au fichier d'horodatage trop long : %s/%s"
+
+#~ msgid "unable to stat editor (%s)"
+#~ msgstr "impossible d'obtenir les stats de l'éditeur (%s)"
+
+#~ msgid "Password:"
+#~ msgstr "Mot de passe :"
+
+#~ msgid "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+#~ msgstr "sudo_ldap_conf_add_ports : espace insuffisant pour étendre hostbuf"
+
+#~ msgid "sudo_ldap_parse_uri: out of space building hostbuf"
+#~ msgstr "sudo_ldap_parse_uri :espace insuffisant pour créer hostbuf"
+
+#~ msgid "sudo_ldap_build_pass1 allocation mismatch"
+#~ msgstr "sudo_ldap_build_pass1 : erreur d'allocation"
+
+#~ msgid "unable to mix ldaps and starttls"
+#~ msgstr "fusion ldaps et starttls impossible"
+
+#~ msgid "internal error: insufficient space for log line"
+#~ msgstr "erreur interne : espace insuffisant pour la ligne de journalisation"
+
+#~ msgid "value out of range"
+#~ msgstr "valeur hors de limites "
+
+#~ msgid "writing to standard output"
+#~ msgstr "écriture vers la sortie standard"
+
+#~ msgid "too many parenthesized expressions, max %d"
+#~ msgstr "le nombre d'expressions entre parenthèses est trop élevé, le maximum autorisé est %d"
+
+#~ msgid "%s owned by uid %u, should be uid %u"
+#~ msgstr "%s appartient à l'utilisateur identifié par %u, alors qu'il devrait appartenir à l'utilisateur identifié par %u"
+
+#~ msgid "%s writable by non-owner (0%o), should be mode 0700"
+#~ msgstr "%s peut être modifié par d'autres utilisateur que son propriétaire (0%o), le mode des privilèges devrait être 0700"
+
+#~ msgid "%s exists but is not a regular file (0%o)"
+#~ msgstr "%s existe mais n'est pas un fichier ordinaire (0%o)"
+
+#~ msgid "%s writable by non-owner (0%o), should be mode 0600"
+#~ msgstr "%s peut être modifié par d'autres utilisateurs que son propriétaire (0%o), le mode des privilèges devrait être 0600"
+
+#~ msgid "unable to remove %s, will reset to the epoch"
+#~ msgstr "suppression de %s impossible, l'horodatage sera réinitialisé à la date courante"
+
+#~ msgid "fill_args: buffer overflow"
+#~ msgstr "fill_args : débordement du tampon"
+
+#~ msgid "%s: unused %s_Alias %s"
+#~ msgstr "%s : %s_Alias %s n'est pas utilisé"
+
+#~ msgid ">>> %s: %s near line %d <<<"
+#~ msgstr ">>> %s : %s aux environs de la ligne %d <<<"
+
+#~ msgid "pam_chauthtok: %s"
+#~ msgstr "pam_chauthtok : %s"
+
+#~ msgid "pam_authenticate: %s"
+#~ msgstr "pam_authenticate : %s"
+
+#~ msgid "getaudit: failed"
+#~ msgstr "getaudit : échec"
+
+#~ msgid "getauid failed"
+#~ msgstr "échec de getauid"
+
+#~ msgid "au_to_subject: failed"
+#~ msgstr "au_to_subject : échec"
+
+#~ msgid "au_to_exec_args: failed"
+#~ msgstr "au_to_exec_args : échec"
+
+#~ msgid "au_to_return32: failed"
+#~ msgstr "au_to_return32 : échec"
+
+#~ msgid "getauid: failed"
+#~ msgstr "getauid : échec"
+
+#~ msgid "au_to_text: failed"
+#~ msgstr "au_to_text : échec"
+
+#~ msgid "unable to set locale to \"%s\", using \"C\""
+#~ msgstr "impossible d'initialiser la localisation à « %s », initialisation à « C »"
+
+#~ msgid ""
+#~ " Commands:\n"
+#~ "\t"
+#~ msgstr ""
+#~ " Commandes :\n"
+#~ "\t"
+
+#~ msgid ": "
+#~ msgstr " : "
+
+#~ msgid "unable to cache uid %u (%s), already exists"
+#~ msgstr "impossible d'enregistrer l'uid %u (%s) dans le cache, l'entrée existe déjà"
+
+#~ msgid "unable to cache gid %u (%s), already exists"
+#~ msgstr "impossible d'enregistrer le gid %u (%s) dans le cache, l'entrée existe déjà"
+
+#~ msgid "Unable to dlopen %s: %s"
+#~ msgstr "impossible d'appliquer dlopen à %s : %s"
+
+#~ msgid "nanosleep: tv_sec %ld, tv_nsec %ld"
+#~ msgstr "nanosleep : tv_sec %ld, tv_nsec %ld"
diff --git a/plugins/sudoers/po/fur.mo b/plugins/sudoers/po/fur.mo
new file mode 100644
index 0000000..8fb36e6
--- /dev/null
+++ b/plugins/sudoers/po/fur.mo
Binary files differ
diff --git a/plugins/sudoers/po/fur.po b/plugins/sudoers/po/fur.po
new file mode 100644
index 0000000..4423803
--- /dev/null
+++ b/plugins/sudoers/po/fur.po
@@ -0,0 +1,2119 @@
+# Friulian translations for sudoers package
+# This file is put in the public domain.
+# Fabio Tomat <f.t.public@gmail.com>, 2017
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers-1.8.22b2\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2017-12-18 10:37-0700\n"
+"PO-Revision-Date: 2017-12-24 14:18+0100\n"
+"Last-Translator: Fabio Tomat <f.t.public@gmail.com>\n"
+"Language-Team: Friulian <f.t.public@gmail.com>\n"
+"Language: fur\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 2.0.3\n"
+
+#: confstr.sh:1
+msgid "syntax error"
+msgstr "erôr di sintassi"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "Password di %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] password par %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Password: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** informazions di SIGURECE par %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Torne prove."
+
+#: gram.y:192 gram.y:240 gram.y:247 gram.y:254 gram.y:261 gram.y:268
+#: gram.y:284 gram.y:307 gram.y:314 gram.y:321 gram.y:328 gram.y:335
+#: gram.y:398 gram.y:406 gram.y:416 gram.y:449 gram.y:456 gram.y:463
+#: gram.y:470 gram.y:552 gram.y:559 gram.y:568 gram.y:577 gram.y:594
+#: gram.y:706 gram.y:713 gram.y:720 gram.y:728 gram.y:824 gram.y:831
+#: gram.y:838 gram.y:845 gram.y:852 gram.y:878 gram.y:885 gram.y:892
+#: gram.y:1015 gram.y:1195 gram.y:1202 plugins/sudoers/alias.c:124
+#: plugins/sudoers/alias.c:139 plugins/sudoers/auth/bsdauth.c:141
+#: plugins/sudoers/auth/kerb5.c:119 plugins/sudoers/auth/kerb5.c:145
+#: plugins/sudoers/auth/pam.c:490 plugins/sudoers/auth/rfc1938.c:109
+#: plugins/sudoers/auth/sia.c:59 plugins/sudoers/defaults.c:651
+#: plugins/sudoers/defaults.c:906 plugins/sudoers/defaults.c:1077
+#: plugins/sudoers/editor.c:64 plugins/sudoers/editor.c:82
+#: plugins/sudoers/editor.c:93 plugins/sudoers/env.c:233
+#: plugins/sudoers/filedigest.c:120 plugins/sudoers/filedigest_gcrypt.c:90
+#: plugins/sudoers/filedigest_openssl.c:111 plugins/sudoers/gc.c:52
+#: plugins/sudoers/group_plugin.c:134 plugins/sudoers/interfaces.c:71
+#: plugins/sudoers/iolog.c:941 plugins/sudoers/iolog_path.c:167
+#: plugins/sudoers/ldap.c:449 plugins/sudoers/ldap.c:480
+#: plugins/sudoers/ldap.c:532 plugins/sudoers/ldap.c:566
+#: plugins/sudoers/ldap.c:980 plugins/sudoers/ldap.c:1174
+#: plugins/sudoers/ldap.c:1185 plugins/sudoers/ldap.c:1201
+#: plugins/sudoers/ldap.c:1493 plugins/sudoers/ldap.c:1653
+#: plugins/sudoers/ldap.c:1735 plugins/sudoers/ldap.c:1883
+#: plugins/sudoers/ldap.c:1907 plugins/sudoers/ldap.c:1996
+#: plugins/sudoers/ldap.c:2011 plugins/sudoers/ldap.c:2107
+#: plugins/sudoers/ldap.c:2140 plugins/sudoers/ldap.c:2221
+#: plugins/sudoers/ldap.c:2303 plugins/sudoers/ldap.c:2400
+#: plugins/sudoers/ldap.c:3235 plugins/sudoers/ldap.c:3267
+#: plugins/sudoers/ldap.c:3579 plugins/sudoers/ldap.c:3607
+#: plugins/sudoers/ldap.c:3623 plugins/sudoers/ldap.c:3713
+#: plugins/sudoers/ldap.c:3729 plugins/sudoers/linux_audit.c:76
+#: plugins/sudoers/logging.c:190 plugins/sudoers/logging.c:501
+#: plugins/sudoers/logging.c:522 plugins/sudoers/logging.c:563
+#: plugins/sudoers/logging.c:740 plugins/sudoers/logging.c:998
+#: plugins/sudoers/match.c:617 plugins/sudoers/match.c:664
+#: plugins/sudoers/match.c:714 plugins/sudoers/match.c:738
+#: plugins/sudoers/match.c:826 plugins/sudoers/match.c:915
+#: plugins/sudoers/parse.c:252 plugins/sudoers/parse.c:264
+#: plugins/sudoers/parse.c:279 plugins/sudoers/parse.c:291
+#: plugins/sudoers/policy.c:498 plugins/sudoers/policy.c:735
+#: plugins/sudoers/prompt.c:93 plugins/sudoers/pwutil.c:165
+#: plugins/sudoers/pwutil.c:236 plugins/sudoers/pwutil.c:312
+#: plugins/sudoers/pwutil.c:486 plugins/sudoers/pwutil.c:551
+#: plugins/sudoers/pwutil.c:620 plugins/sudoers/pwutil.c:778
+#: plugins/sudoers/pwutil.c:835 plugins/sudoers/pwutil.c:880
+#: plugins/sudoers/pwutil.c:938 plugins/sudoers/sssd.c:162
+#: plugins/sudoers/sssd.c:194 plugins/sudoers/sssd.c:237
+#: plugins/sudoers/sssd.c:244 plugins/sudoers/sssd.c:280
+#: plugins/sudoers/sssd.c:353 plugins/sudoers/sssd.c:392
+#: plugins/sudoers/sssd.c:1073 plugins/sudoers/sssd.c:1252
+#: plugins/sudoers/sssd.c:1266 plugins/sudoers/sssd.c:1282
+#: plugins/sudoers/sudoers.c:263 plugins/sudoers/sudoers.c:273
+#: plugins/sudoers/sudoers.c:281 plugins/sudoers/sudoers.c:365
+#: plugins/sudoers/sudoers.c:682 plugins/sudoers/sudoers.c:807
+#: plugins/sudoers/sudoers.c:851 plugins/sudoers/sudoers.c:1123
+#: plugins/sudoers/sudoers_debug.c:107 plugins/sudoers/sudoreplay.c:1254
+#: plugins/sudoers/sudoreplay.c:1366 plugins/sudoers/sudoreplay.c:1406
+#: plugins/sudoers/sudoreplay.c:1415 plugins/sudoers/sudoreplay.c:1425
+#: plugins/sudoers/sudoreplay.c:1433 plugins/sudoers/sudoreplay.c:1437
+#: plugins/sudoers/sudoreplay.c:1593 plugins/sudoers/sudoreplay.c:1597
+#: plugins/sudoers/testsudoers.c:131 plugins/sudoers/testsudoers.c:217
+#: plugins/sudoers/testsudoers.c:234 plugins/sudoers/timestamp.c:397
+#: plugins/sudoers/timestamp.c:441 plugins/sudoers/timestamp.c:868
+#: plugins/sudoers/toke_util.c:56 plugins/sudoers/toke_util.c:109
+#: plugins/sudoers/toke_util.c:146 plugins/sudoers/visudo.c:153
+#: plugins/sudoers/visudo.c:309 plugins/sudoers/visudo.c:315
+#: plugins/sudoers/visudo.c:446 plugins/sudoers/visudo.c:624
+#: plugins/sudoers/visudo.c:985 plugins/sudoers/visudo.c:1051
+#: plugins/sudoers/visudo.c:1095 plugins/sudoers/visudo.c:1197
+#: plugins/sudoers/visudo_json.c:1025 toke.l:849 toke.l:949 toke.l:1106
+msgid "unable to allocate memory"
+msgstr "impussibil assegnâ memorie"
+
+#: gram.y:481
+msgid "a digest requires a path name"
+msgstr "un digest al domande un non di percors"
+
+#: gram.y:607
+msgid "invalid notbefore value"
+msgstr ""
+
+#: gram.y:615
+msgid "invalid notafter value"
+msgstr ""
+
+#: gram.y:624 plugins/sudoers/policy.c:314
+msgid "timeout value too large"
+msgstr "valôr di timeout masse larc"
+
+#: gram.y:626 plugins/sudoers/policy.c:316
+msgid "invalid timeout value"
+msgstr "valôr di timeout no valit"
+
+#: gram.y:1195 gram.y:1202 plugins/sudoers/auth/pam.c:320
+#: plugins/sudoers/auth/pam.c:490 plugins/sudoers/auth/rfc1938.c:109
+#: plugins/sudoers/defaults.c:651 plugins/sudoers/defaults.c:906
+#: plugins/sudoers/defaults.c:1077 plugins/sudoers/editor.c:64
+#: plugins/sudoers/editor.c:82 plugins/sudoers/editor.c:93
+#: plugins/sudoers/env.c:233 plugins/sudoers/filedigest.c:120
+#: plugins/sudoers/filedigest_gcrypt.c:72
+#: plugins/sudoers/filedigest_gcrypt.c:90
+#: plugins/sudoers/filedigest_openssl.c:111 plugins/sudoers/gc.c:52
+#: plugins/sudoers/group_plugin.c:134 plugins/sudoers/interfaces.c:71
+#: plugins/sudoers/iolog.c:941 plugins/sudoers/iolog_path.c:167
+#: plugins/sudoers/ldap.c:449 plugins/sudoers/ldap.c:480
+#: plugins/sudoers/ldap.c:532 plugins/sudoers/ldap.c:566
+#: plugins/sudoers/ldap.c:980 plugins/sudoers/ldap.c:1174
+#: plugins/sudoers/ldap.c:1185 plugins/sudoers/ldap.c:1201
+#: plugins/sudoers/ldap.c:1493 plugins/sudoers/ldap.c:1653
+#: plugins/sudoers/ldap.c:1735 plugins/sudoers/ldap.c:1883
+#: plugins/sudoers/ldap.c:1907 plugins/sudoers/ldap.c:1996
+#: plugins/sudoers/ldap.c:2011 plugins/sudoers/ldap.c:2107
+#: plugins/sudoers/ldap.c:2140 plugins/sudoers/ldap.c:2220
+#: plugins/sudoers/ldap.c:2303 plugins/sudoers/ldap.c:2400
+#: plugins/sudoers/ldap.c:3235 plugins/sudoers/ldap.c:3267
+#: plugins/sudoers/ldap.c:3579 plugins/sudoers/ldap.c:3606
+#: plugins/sudoers/ldap.c:3622 plugins/sudoers/ldap.c:3713
+#: plugins/sudoers/ldap.c:3729 plugins/sudoers/linux_audit.c:76
+#: plugins/sudoers/logging.c:190 plugins/sudoers/logging.c:501
+#: plugins/sudoers/logging.c:522 plugins/sudoers/logging.c:562
+#: plugins/sudoers/logging.c:998 plugins/sudoers/match.c:616
+#: plugins/sudoers/match.c:663 plugins/sudoers/match.c:714
+#: plugins/sudoers/match.c:738 plugins/sudoers/match.c:826
+#: plugins/sudoers/match.c:914 plugins/sudoers/parse.c:252
+#: plugins/sudoers/parse.c:264 plugins/sudoers/parse.c:279
+#: plugins/sudoers/parse.c:291 plugins/sudoers/policy.c:128
+#: plugins/sudoers/policy.c:137 plugins/sudoers/policy.c:146
+#: plugins/sudoers/policy.c:172 plugins/sudoers/policy.c:299
+#: plugins/sudoers/policy.c:314 plugins/sudoers/policy.c:316
+#: plugins/sudoers/policy.c:342 plugins/sudoers/policy.c:352
+#: plugins/sudoers/policy.c:396 plugins/sudoers/policy.c:406
+#: plugins/sudoers/policy.c:415 plugins/sudoers/policy.c:424
+#: plugins/sudoers/policy.c:498 plugins/sudoers/policy.c:735
+#: plugins/sudoers/prompt.c:93 plugins/sudoers/pwutil.c:165
+#: plugins/sudoers/pwutil.c:236 plugins/sudoers/pwutil.c:312
+#: plugins/sudoers/pwutil.c:486 plugins/sudoers/pwutil.c:551
+#: plugins/sudoers/pwutil.c:620 plugins/sudoers/pwutil.c:778
+#: plugins/sudoers/pwutil.c:835 plugins/sudoers/pwutil.c:880
+#: plugins/sudoers/pwutil.c:938 plugins/sudoers/set_perms.c:387
+#: plugins/sudoers/set_perms.c:766 plugins/sudoers/set_perms.c:1150
+#: plugins/sudoers/set_perms.c:1476 plugins/sudoers/set_perms.c:1641
+#: plugins/sudoers/sssd.c:162 plugins/sudoers/sssd.c:194
+#: plugins/sudoers/sssd.c:237 plugins/sudoers/sssd.c:244
+#: plugins/sudoers/sssd.c:280 plugins/sudoers/sssd.c:352
+#: plugins/sudoers/sssd.c:392 plugins/sudoers/sssd.c:1073
+#: plugins/sudoers/sssd.c:1251 plugins/sudoers/sssd.c:1266
+#: plugins/sudoers/sssd.c:1282 plugins/sudoers/sudoers.c:263
+#: plugins/sudoers/sudoers.c:273 plugins/sudoers/sudoers.c:281
+#: plugins/sudoers/sudoers.c:365 plugins/sudoers/sudoers.c:682
+#: plugins/sudoers/sudoers.c:807 plugins/sudoers/sudoers.c:851
+#: plugins/sudoers/sudoers.c:1123 plugins/sudoers/sudoers_debug.c:106
+#: plugins/sudoers/sudoreplay.c:1254 plugins/sudoers/sudoreplay.c:1366
+#: plugins/sudoers/sudoreplay.c:1406 plugins/sudoers/sudoreplay.c:1415
+#: plugins/sudoers/sudoreplay.c:1425 plugins/sudoers/sudoreplay.c:1433
+#: plugins/sudoers/sudoreplay.c:1437 plugins/sudoers/sudoreplay.c:1593
+#: plugins/sudoers/sudoreplay.c:1597 plugins/sudoers/testsudoers.c:131
+#: plugins/sudoers/testsudoers.c:217 plugins/sudoers/testsudoers.c:234
+#: plugins/sudoers/timestamp.c:397 plugins/sudoers/timestamp.c:441
+#: plugins/sudoers/timestamp.c:868 plugins/sudoers/toke_util.c:56
+#: plugins/sudoers/toke_util.c:109 plugins/sudoers/toke_util.c:146
+#: plugins/sudoers/visudo.c:153 plugins/sudoers/visudo.c:309
+#: plugins/sudoers/visudo.c:315 plugins/sudoers/visudo.c:446
+#: plugins/sudoers/visudo.c:624 plugins/sudoers/visudo.c:985
+#: plugins/sudoers/visudo.c:1051 plugins/sudoers/visudo.c:1095
+#: plugins/sudoers/visudo.c:1197 plugins/sudoers/visudo_json.c:1025 toke.l:849
+#: toke.l:949 toke.l:1106
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: plugins/sudoers/alias.c:135
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:68
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "impussibil otignî la classe di login pal utent %s"
+
+#: plugins/sudoers/auth/bsdauth.c:73
+msgid "unable to begin bsd authentication"
+msgstr "impussibil tacâ la autenticazion bsd"
+
+#: plugins/sudoers/auth/bsdauth.c:81
+msgid "invalid authentication type"
+msgstr "gjenar di autenticazion no valit"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to initialize BSD authentication"
+msgstr "impussibil inizializâ la autenticazion BSD"
+
+#: plugins/sudoers/auth/fwtk.c:52
+msgid "unable to read fwtk config"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:57
+msgid "unable to connect to authentication server"
+msgstr "impussibil conetisi al servidôr di autenticazion"
+
+#: plugins/sudoers/auth/fwtk.c:63 plugins/sudoers/auth/fwtk.c:87
+#: plugins/sudoers/auth/fwtk.c:121
+msgid "lost connection to authentication server"
+msgstr "conession pierdude al servidôr di autenticazion"
+
+#: plugins/sudoers/auth/fwtk.c:67
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"erôr dal servidôr di autenticazion:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:111
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:161
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: impussibil analizâ '%s': %s"
+
+#: plugins/sudoers/auth/kerb5.c:170
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:217
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: impussibil assegnâ opzions: %s"
+
+#: plugins/sudoers/auth/kerb5.c:232
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: impussibil otignî credenziâls: %s"
+
+#: plugins/sudoers/auth/kerb5.c:245
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:248
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: impussibil archiviâ la credenziâl te cache: %s"
+
+#: plugins/sudoers/auth/kerb5.c:312
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:326
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: Impussibil verificâ TGT! Pussibil atac in vore!: %s"
+
+#: plugins/sudoers/auth/pam.c:108
+msgid "unable to initialize PAM"
+msgstr "impussibil inizializâ PAM"
+
+#: plugins/sudoers/auth/pam.c:194
+msgid "account validation failure, is your account locked?"
+msgstr "validazion account falide, isal blocât?"
+
+#: plugins/sudoers/auth/pam.c:198
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Acount o password scjadude, ristabilìs la password e torne prove"
+
+#: plugins/sudoers/auth/pam.c:206
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "impussibil cambiâ la password scjadude: %s"
+
+#: plugins/sudoers/auth/pam.c:211
+msgid "Password expired, contact your system administrator"
+msgstr "Password scjadude, contatâ l'aministradôr di sisteme"
+
+#: plugins/sudoers/auth/pam.c:215
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:229
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Erôr di autenticazion PAM: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:97 plugins/sudoers/visudo.c:227
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "no tu esistis te base di dâts %s"
+
+#: plugins/sudoers/auth/securid5.c:73
+msgid "failed to initialise the ACE API library"
+msgstr "no si è rivâts a inizializâ la librarie API ACE"
+
+#: plugins/sudoers/auth/securid5.c:99
+msgid "unable to contact the SecurID server"
+msgstr "impussibil contatâ il servidôr SecurID"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "User ID locked for SecurID Authentication"
+msgstr "ID utent blocât pe autenticazion SecurID"
+
+#: plugins/sudoers/auth/securid5.c:112 plugins/sudoers/auth/securid5.c:163
+msgid "invalid username length for SecurID"
+msgstr "lungjece dal non utent no valide par SecurID"
+
+#: plugins/sudoers/auth/securid5.c:116 plugins/sudoers/auth/securid5.c:168
+msgid "invalid Authentication Handle for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:120
+msgid "SecurID communication failed"
+msgstr "Comunicazion SecurID falide"
+
+#: plugins/sudoers/auth/securid5.c:124 plugins/sudoers/auth/securid5.c:213
+msgid "unknown SecurID error"
+msgstr "erôr SecurID no cognossût"
+
+#: plugins/sudoers/auth/securid5.c:158
+msgid "invalid passcode length for SecurID"
+msgstr "lungjece dal passcode no valide par SecurID"
+
+#: plugins/sudoers/auth/sia.c:69 plugins/sudoers/auth/sia.c:125
+msgid "unable to initialize SIA session"
+msgstr "impussibil inizializâ la session SIA"
+
+#: plugins/sudoers/auth/sudo_auth.c:126
+msgid "invalid authentication methods"
+msgstr "metodis di autenticazion no valits"
+
+#: plugins/sudoers/auth/sudo_auth.c:128
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:224 plugins/sudoers/auth/sudo_auth.c:274
+msgid "no authentication methods"
+msgstr "nissun metodi di autenticazion"
+
+#: plugins/sudoers/auth/sudo_auth.c:226
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:276
+msgid "Unable to initialize authentication methods."
+msgstr "Impussibil inizializâ i metodis di autenticazion."
+
+#: plugins/sudoers/auth/sudo_auth.c:441
+msgid "Authentication methods:"
+msgstr "Metodis di autenticazion:"
+
+#: plugins/sudoers/bsm_audit.c:120 plugins/sudoers/bsm_audit.c:211
+msgid "Could not determine audit condition"
+msgstr ""
+
+#: plugins/sudoers/bsm_audit.c:183 plugins/sudoers/bsm_audit.c:273
+msgid "unable to commit audit record"
+msgstr ""
+
+#: plugins/sudoers/check.c:259
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/check.c:302 plugins/sudoers/check.c:312
+#: plugins/sudoers/sudoers.c:725 plugins/sudoers/sudoers.c:770
+#, c-format
+msgid "unknown uid: %u"
+msgstr "uid no cognossût: %u"
+
+#: plugins/sudoers/check.c:307 plugins/sudoers/iolog.c:260
+#: plugins/sudoers/policy.c:908 plugins/sudoers/sudoers.c:1162
+#: plugins/sudoers/testsudoers.c:208 plugins/sudoers/testsudoers.c:366
+#, c-format
+msgid "unknown user: %s"
+msgstr "utent no cognossût: %s"
+
+#: plugins/sudoers/def_data.c:41
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:45
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:49
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:53
+msgid "Put OTP prompt on its own line"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:57
+msgid "Ignore '.' in $PATH"
+msgstr "Ignore '.' in $PATH"
+
+#: plugins/sudoers/def_data.c:61
+msgid "Always send mail when sudo is run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:65
+msgid "Send mail if user authentication fails"
+msgstr "Invie une mail se la autenticazion dal utent e falìs"
+
+#: plugins/sudoers/def_data.c:69
+msgid "Send mail if the user is not in sudoers"
+msgstr "Invie une mail se l'utent nol è tai sudoers"
+
+#: plugins/sudoers/def_data.c:73
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Invie une mail se l'utent nol è tai sudoers par chest host"
+
+#: plugins/sudoers/def_data.c:77
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Invie une mail se l'utent nol pues eseguî un comant"
+
+#: plugins/sudoers/def_data.c:81
+msgid "Send mail if the user tries to run a command"
+msgstr "Invie une mail se l'utent al cîr di eseguî un comant"
+
+#: plugins/sudoers/def_data.c:85
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:89
+msgid "Lecture user the first time they run sudo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:93
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:97
+msgid "Require users to authenticate by default"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:101
+msgid "Root may run sudo"
+msgstr "L'utent root al pues eseguî sudo"
+
+#: plugins/sudoers/def_data.c:105
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Regjistre il non host tal file di regjistri (no-syslog)"
+
+#: plugins/sudoers/def_data.c:109
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Regjistre l'an tal file di regjistri (no-syslog)"
+
+#: plugins/sudoers/def_data.c:113
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:117
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:121
+msgid "Always set $HOME to the target user's home directory"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:125
+msgid "Allow some information gathering to give useful error messages"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:129
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:133
+msgid "Insult the user when they enter an incorrect password"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:137
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:141
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:145
+msgid "Prompt for root's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:149
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:153
+msgid "Prompt for the target user's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:157
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:161
+msgid "Set the LOGNAME and USER environment variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:165
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:169
+msgid "Don't initialize the group vector to that of the target user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:173
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:177
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:181
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:185
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:189
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:193
+#, c-format
+msgid "Path to log file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:197
+#, c-format
+msgid "Path to mail program: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:201
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:205
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:209
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:213
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:217
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:221
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:225
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:229
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:233
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:237
+#, c-format
+msgid "Default password prompt: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:241
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr ""
+
+#: plugins/sudoers/def_data.c:245
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:249
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:253
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:257
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:261
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:265
+msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:269
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:273
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:277
+msgid "If set, users may override the value of `closefrom' with the -C option"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:281
+msgid "Allow users to set arbitrary environment variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:285
+msgid "Reset the environment to a default set of variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:289
+msgid "Environment variables to check for sanity:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:293
+msgid "Environment variables to remove:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:297
+msgid "Environment variables to preserve:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:301
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:305
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:309
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:313
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:317
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:321
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:325
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:329
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:333
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:337
+msgid "Log user's input for the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:341
+msgid "Log the output of the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:345
+msgid "Compress I/O logs using zlib"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:349
+msgid "Always run commands in a pseudo-tty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:353
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:357
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:361
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:365
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:369
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:373
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:377
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:381
+msgid "Run commands on a pty in the background"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:385
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "Non dal servizi PAM di doprâ: %s"
+
+#: plugins/sudoers/def_data.c:389
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "Non dal servizi PAM di doprâ pes interfacis di acès: %s"
+
+#: plugins/sudoers/def_data.c:393
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Tentatîf di stabilî lis credentziâls PAM pal utent designât"
+
+#: plugins/sudoers/def_data.c:397
+msgid "Create a new PAM session for the command to run in"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:401
+#, c-format
+msgid "Maximum I/O log sequence number: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:405
+msgid "Enable sudoers netgroup support"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:409
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:413
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:417
+msgid "Query the group plugin for unknown system groups"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:421
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:425
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:429
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:433
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:437
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:441
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:445
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:449
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:453
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:457
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:461
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:465
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:469
+msgid "Allow the user to specify a timeout on the command line"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:473
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:477
+msgid "Include the process ID when logging via syslog"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:481
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:485
+#, fuzzy, c-format
+#| msgid "Authentication methods:"
+msgid "Authentication failure message: %s"
+msgstr "Metodis di autenticazion:"
+
+#: plugins/sudoers/defaults.c:221
+#, c-format
+msgid "%s:%d unknown defaults entry \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:224
+#, c-format
+msgid "%s: unknown defaults entry \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:267
+#, c-format
+msgid "%s:%d no value specified for \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:270
+#, c-format
+msgid "%s: no value specified for \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:290
+#, c-format
+msgid "%s:%d values for \"%s\" must start with a '/'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:293
+#, c-format
+msgid "%s: values for \"%s\" must start with a '/'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:318
+#, c-format
+msgid "%s:%d option \"%s\" does not take a value"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:321
+#, c-format
+msgid "%s: option \"%s\" does not take a value"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:343
+#, c-format
+msgid "%s:%d invalid Defaults type 0x%x for option \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:346
+#, c-format
+msgid "%s: invalid Defaults type 0x%x for option \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:356
+#, c-format
+msgid "%s:%d value \"%s\" is invalid for option \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:359
+#, c-format
+msgid "%s: value \"%s\" is invalid for option \"%s\""
+msgstr ""
+
+#: plugins/sudoers/env.c:295 plugins/sudoers/env.c:302
+#: plugins/sudoers/env.c:407 plugins/sudoers/ldap.c:453
+#: plugins/sudoers/ldap.c:543 plugins/sudoers/ldap.c:1270
+#: plugins/sudoers/ldap.c:1497 plugins/sudoers/ldap.c:1822
+#: plugins/sudoers/linux_audit.c:82 plugins/sudoers/logging.c:1003
+#: plugins/sudoers/policy.c:619 plugins/sudoers/policy.c:629
+#: plugins/sudoers/prompt.c:161 plugins/sudoers/sudoers.c:873
+#: plugins/sudoers/testsudoers.c:238 plugins/sudoers/toke_util.c:158
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "erôr interni, %s overflow (stranfât)"
+
+#: plugins/sudoers/env.c:376
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr ""
+
+#: plugins/sudoers/env.c:1055
+msgid "unable to rebuild the environment"
+msgstr ""
+
+#: plugins/sudoers/env.c:1129
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr ""
+
+#: plugins/sudoers/filedigest.c:104 plugins/sudoers/filedigest_gcrypt.c:66
+#: plugins/sudoers/filedigest_openssl.c:95
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr ""
+
+#: plugins/sudoers/filedigest.c:129 plugins/sudoers/filedigest_gcrypt.c:98
+#: plugins/sudoers/filedigest_openssl.c:120
+#, c-format
+msgid "%s: read error"
+msgstr "%s: erôr di leture"
+
+#: plugins/sudoers/group_plugin.c:86
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:90
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:98 plugins/sudoers/sssd.c:400
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "impussibil cjariâ %s: %s"
+
+#: plugins/sudoers/group_plugin.c:104
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:109
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:79 plugins/sudoers/interfaces.c:96
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:84 plugins/sudoers/interfaces.c:101
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:129
+msgid "Local IP address and netmask pairs:\n"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:121 plugins/sudoers/mkdir_parents.c:75
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:146 plugins/sudoers/iolog.c:187
+#: plugins/sudoers/mkdir_parents.c:64 plugins/sudoers/timestamp.c:175
+#, c-format
+msgid "unable to mkdir %s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:191 plugins/sudoers/visudo.c:740
+#: plugins/sudoers/visudo.c:750
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:299 plugins/sudoers/sudoers.c:1193
+#: plugins/sudoers/testsudoers.c:390
+#, c-format
+msgid "unknown group: %s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:418 plugins/sudoers/sudoers.c:929
+#: plugins/sudoers/sudoreplay.c:349 plugins/sudoers/sudoreplay.c:1355
+#: plugins/sudoers/sudoreplay.c:1559 plugins/sudoers/timestamp.c:406
+#: plugins/sudoers/visudo.c:972 plugins/sudoers/visudo_json.c:1001
+#: plugins/sudoers/visudo_json.c:1014
+#, c-format
+msgid "unable to open %s"
+msgstr "impussibil vierzi %s"
+
+#: plugins/sudoers/iolog.c:469 plugins/sudoers/sudoers.c:933
+#: plugins/sudoers/sudoreplay.c:857 plugins/sudoers/sudoreplay.c:1670
+#, c-format
+msgid "unable to read %s"
+msgstr "impussibil lei %s"
+
+#: plugins/sudoers/iolog.c:505 plugins/sudoers/sudoreplay.c:1124
+#: plugins/sudoers/timestamp.c:295 plugins/sudoers/timestamp.c:298
+#, c-format
+msgid "unable to write to %s"
+msgstr "impussibil scrivi su %s"
+
+#: plugins/sudoers/iolog.c:584 plugins/sudoers/iolog.c:803
+#, c-format
+msgid "unable to create %s"
+msgstr "impussibil creâ %s"
+
+#: plugins/sudoers/iolog.c:1035 plugins/sudoers/iolog.c:1110
+#: plugins/sudoers/iolog.c:1191
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "impussibil scrivi sul file di regjistri I/O: %s"
+
+#: plugins/sudoers/iolog.c:1069
+#, c-format
+msgid "%s: internal error, file index %d not open"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:431
+msgid "sudo_ldap_conf_add_ports: port too large"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:491
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:518
+msgid "unable to mix ldap and ldaps URIs"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:522 plugins/sudoers/ldap.c:559
+msgid "starttls not supported when using ldaps"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:630
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:633
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1256
+msgid "unable to get GMT time"
+msgstr "impussibil otignî la ore GMT"
+
+#: plugins/sudoers/ldap.c:1262
+msgid "unable to format timestamp"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1986
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2559
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2561
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: UNKNOWN\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2617
+#, c-format
+msgid " Order: %s\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2625 plugins/sudoers/parse.c:618
+#: plugins/sudoers/sssd.c:1647
+#, c-format
+msgid " Commands:\n"
+msgstr " Comants:\n"
+
+#: plugins/sudoers/ldap.c:3187
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "impussibil inizializâ LDAP: %s"
+
+#: plugins/sudoers/ldap.c:3223
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:3475
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr ""
+
+#: plugins/sudoers/linux_audit.c:52
+msgid "unable to open audit system"
+msgstr "impussibil vierzi il sisteme di audit"
+
+#: plugins/sudoers/linux_audit.c:93
+msgid "unable to send audit message"
+msgstr "impussibil inviâ il messaç di audit"
+
+#: plugins/sudoers/logging.c:108
+#, c-format
+msgid "%8s : %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:136
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:165
+#, c-format
+msgid "unable to open log file: %s"
+msgstr "impussibil vierzi il file di regjistri: %s"
+
+#: plugins/sudoers/logging.c:173
+#, c-format
+msgid "unable to lock log file: %s"
+msgstr "impussibil blocâ il file di regjistri: %s"
+
+#: plugins/sudoers/logging.c:206
+#, c-format
+msgid "unable to write log file: %s"
+msgstr "impussibil scrivi il file di regjistri: %s"
+
+#: plugins/sudoers/logging.c:235
+msgid "No user or host"
+msgstr "Nissun utent o host"
+
+#: plugins/sudoers/logging.c:237
+msgid "validation failure"
+msgstr "validazion falide"
+
+#: plugins/sudoers/logging.c:244
+msgid "user NOT in sudoers"
+msgstr "l'utent NOL è in sudoers"
+
+#: plugins/sudoers/logging.c:246
+msgid "user NOT authorized on host"
+msgstr "l'utent NOL è autorizât sul host"
+
+#: plugins/sudoers/logging.c:248
+msgid "command not allowed"
+msgstr "comant no permetût"
+
+#: plugins/sudoers/logging.c:283
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr "%s nol è tal file sudoers. Chest incident al vignarà segnalât.\n"
+
+#: plugins/sudoers/logging.c:286
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr "%s nol è permetût eseguî sudo su %s. Chest incident al vignarà segnalât.\n"
+
+#: plugins/sudoers/logging.c:290
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Mi displâs, l'utent %s nol pues eseguî sudo su %s.\n"
+
+#: plugins/sudoers/logging.c:293
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:330 plugins/sudoers/sudoers.c:473
+#: plugins/sudoers/sudoers.c:475 plugins/sudoers/sudoers.c:477
+#: plugins/sudoers/sudoers.c:479 plugins/sudoers/sudoers.c:1298
+#: plugins/sudoers/sudoers.c:1300
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: comant no cjatât"
+
+#: plugins/sudoers/logging.c:332 plugins/sudoers/sudoers.c:469
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+
+#: plugins/sudoers/logging.c:349
+msgid "authentication failure"
+msgstr "autenticazion falide"
+
+#: plugins/sudoers/logging.c:375
+msgid "a password is required"
+msgstr "e covente une password"
+
+#: plugins/sudoers/logging.c:438
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] ""
+msgstr[1] ""
+
+#: plugins/sudoers/logging.c:654
+msgid "unable to fork"
+msgstr "impussibil inglovâ (fâ il fork)"
+
+#: plugins/sudoers/logging.c:662 plugins/sudoers/logging.c:714
+#, c-format
+msgid "unable to fork: %m"
+msgstr "impussibil inglovâ (fâ il fork): %m"
+
+#: plugins/sudoers/logging.c:704
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "impussibil vierzi il condot (pipe): %m"
+
+#: plugins/sudoers/logging.c:729
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "impussibil fâ il \"dup\" di \"stdin\": %m"
+
+#: plugins/sudoers/logging.c:767
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "impussibil eseguî %s: %m"
+
+#: plugins/sudoers/match.c:771
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr ""
+
+#: plugins/sudoers/mkdir_parents.c:70 plugins/sudoers/sudoers.c:944
+#: plugins/sudoers/visudo.c:439 plugins/sudoers/visudo.c:734
+#, c-format
+msgid "unable to stat %s"
+msgstr ""
+
+#: plugins/sudoers/parse.c:115
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr ""
+
+#: plugins/sudoers/parse.c:118
+#, c-format
+msgid "parse error in %s"
+msgstr ""
+
+#: plugins/sudoers/parse.c:544
+#, c-format
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+
+#: plugins/sudoers/parse.c:545
+#, c-format
+msgid " RunAsUsers: "
+msgstr ""
+
+#: plugins/sudoers/parse.c:559
+#, c-format
+msgid " RunAsGroups: "
+msgstr ""
+
+#: plugins/sudoers/parse.c:568
+#, c-format
+msgid " Options: "
+msgstr " Opzions: "
+
+#: plugins/sudoers/policy.c:84 plugins/sudoers/policy.c:110
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:289 plugins/sudoers/testsudoers.c:261
+msgid "unable to parse network address list"
+msgstr ""
+
+#: plugins/sudoers/policy.c:433
+msgid "user name not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:437
+msgid "user ID not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:441
+msgid "group ID not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:445
+msgid "host name not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:793 plugins/sudoers/visudo.c:910
+#, c-format
+msgid "unable to execute %s"
+msgstr "impussibil eseguî %s"
+
+#: plugins/sudoers/policy.c:926
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:928
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:932
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Percors di sudoers: %s\n"
+
+#: plugins/sudoers/policy.c:935
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "percors di nsswitch: %s\n"
+
+#: plugins/sudoers/policy.c:937
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "percors di ldap.conf: %s\n"
+
+#: plugins/sudoers/policy.c:938
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "percors di ldap.secret: %s\n"
+
+#: plugins/sudoers/policy.c:971
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:188 plugins/sudoers/pwutil.c:206
+#, c-format
+msgid "unable to cache uid %u, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:200
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:260 plugins/sudoers/pwutil.c:277
+#: plugins/sudoers/pwutil.c:339 plugins/sudoers/pwutil.c:384
+#, c-format
+msgid "unable to cache user %s, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:272
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:503 plugins/sudoers/pwutil.c:521
+#, c-format
+msgid "unable to cache gid %u, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:515
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:569 plugins/sudoers/pwutil.c:586
+#: plugins/sudoers/pwutil.c:633 plugins/sudoers/pwutil.c:675
+#, c-format
+msgid "unable to cache group %s, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:581
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:801 plugins/sudoers/pwutil.c:853
+#: plugins/sudoers/pwutil.c:904 plugins/sudoers/pwutil.c:957
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:807 plugins/sudoers/pwutil.c:858
+#: plugins/sudoers/pwutil.c:910 plugins/sudoers/pwutil.c:962
+#, c-format
+msgid "unable to cache group list for %s, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:847
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:951
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:113 plugins/sudoers/set_perms.c:469
+#: plugins/sudoers/set_perms.c:912 plugins/sudoers/set_perms.c:1239
+#: plugins/sudoers/set_perms.c:1556
+msgid "perm stack overflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:121 plugins/sudoers/set_perms.c:400
+#: plugins/sudoers/set_perms.c:477 plugins/sudoers/set_perms.c:779
+#: plugins/sudoers/set_perms.c:920 plugins/sudoers/set_perms.c:1163
+#: plugins/sudoers/set_perms.c:1247 plugins/sudoers/set_perms.c:1489
+#: plugins/sudoers/set_perms.c:1564 plugins/sudoers/set_perms.c:1654
+msgid "perm stack underflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:180 plugins/sudoers/set_perms.c:523
+#: plugins/sudoers/set_perms.c:1298 plugins/sudoers/set_perms.c:1596
+msgid "unable to change to root gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:269 plugins/sudoers/set_perms.c:620
+#: plugins/sudoers/set_perms.c:1049 plugins/sudoers/set_perms.c:1375
+msgid "unable to change to runas gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:274 plugins/sudoers/set_perms.c:625
+#: plugins/sudoers/set_perms.c:1054 plugins/sudoers/set_perms.c:1380
+msgid "unable to set runas group vector"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:285 plugins/sudoers/set_perms.c:636
+#: plugins/sudoers/set_perms.c:1063 plugins/sudoers/set_perms.c:1389
+msgid "unable to change to runas uid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:303 plugins/sudoers/set_perms.c:654
+#: plugins/sudoers/set_perms.c:1079 plugins/sudoers/set_perms.c:1405
+msgid "unable to change to sudoers gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:387 plugins/sudoers/set_perms.c:766
+#: plugins/sudoers/set_perms.c:1150 plugins/sudoers/set_perms.c:1476
+#: plugins/sudoers/set_perms.c:1641
+msgid "too many processes"
+msgstr "masse procès"
+
+#: plugins/sudoers/solaris_audit.c:51
+msgid "unable to get current working directory"
+msgstr "impussibil otignî la cartele di vore atuâl"
+
+#: plugins/sudoers/solaris_audit.c:59
+#, c-format
+msgid "truncated audit path user_cmnd: %s"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:66
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:115
+msgid "audit_failure message too long"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:402
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:410 plugins/sudoers/sssd.c:419
+#: plugins/sudoers/sssd.c:428 plugins/sudoers/sssd.c:437
+#: plugins/sudoers/sssd.c:446
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:1562
+#, c-format
+msgid ""
+"\n"
+"SSSD Role: %s\n"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:1567
+#, c-format
+msgid ""
+"\n"
+"SSSD Role: UNKNOWN\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:289
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:307
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:325
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "L'utent %s al pues eseguî su %s i comants chi daurman:\n"
+
+#: plugins/sudoers/sudo_nss.c:338
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "L'utent %s nol pues eseguî sudo su %s.\n"
+
+#: plugins/sudoers/sudoers.c:168 plugins/sudoers/testsudoers.c:247
+#: plugins/sudoers/visudo.c:233 plugins/sudoers/visudo.c:612
+#: plugins/sudoers/visudo.c:976
+msgid "unable to initialize sudoers default values"
+msgstr "impussibil inizializâ i valôrs predefinîts di sudoers"
+
+#: plugins/sudoers/sudoers.c:198 plugins/sudoers/sudoers.c:891
+msgid "problem with defaults entries"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:205
+msgid "no valid sudoers sources found, quitting"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:244
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:301
+msgid "you are not permitted to use the -C option"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:390
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:405
+msgid "no tty"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:406
+msgid "sorry, you must have a tty to run sudo"
+msgstr "mi displâs, si scugne vê un tty par eseguî sudo"
+
+#: plugins/sudoers/sudoers.c:468
+msgid "command in current directory"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:487
+msgid "sorry, you are not allowed set a command timeout"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:495
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:836
+msgid "command too long"
+msgstr "comant masse lunc"
+
+#: plugins/sudoers/sudoers.c:948
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s nol è un file regolâr"
+
+#: plugins/sudoers/sudoers.c:952 plugins/sudoers/timestamp.c:222 toke.l:969
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:956 toke.l:974
+#, c-format
+msgid "%s is world writable"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:960 toke.l:977
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:993
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1012
+#, c-format
+msgid "unknown login class: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1095 plugins/sudoers/sudoers.c:1109
+#, c-format
+msgid "unable to resolve host %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:275
+#, c-format
+msgid "invalid filter option: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:288
+#, c-format
+msgid "invalid max wait: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:300
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:303 plugins/sudoers/visudo.c:186
+#, c-format
+msgid "%s version %s\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s/timing: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:341
+#, c-format
+msgid "%s/%s/timing: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:357
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:555 plugins/sudoers/sudoreplay.c:602
+#: plugins/sudoers/sudoreplay.c:805 plugins/sudoers/sudoreplay.c:895
+#: plugins/sudoers/sudoreplay.c:974 plugins/sudoers/sudoreplay.c:989
+#: plugins/sudoers/sudoreplay.c:996 plugins/sudoers/sudoreplay.c:1003
+#: plugins/sudoers/sudoreplay.c:1010 plugins/sudoers/sudoreplay.c:1017
+#: plugins/sudoers/sudoreplay.c:1163
+msgid "unable to add event to queue"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:670
+msgid "unable to set tty to raw mode"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:721
+#, c-format
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:722
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:750
+msgid "Replay finished, press any key to restore the terminal."
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:783
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1197 plugins/sudoers/sudoreplay.c:1222
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1244
+msgid "unmatched ')' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1248
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1263
+#, c-format
+msgid "%s requires an argument"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1266 plugins/sudoers/sudoreplay.c:1646
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1270
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1279
+msgid "unmatched '(' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1281
+msgid "illegal trailing \"or\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1283
+msgid "illegal trailing \"!\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1332
+#, c-format
+msgid "unknown search type %d"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1370
+#, c-format
+msgid "%s: invalid log file"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1388
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1395
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1402
+#, c-format
+msgid "%s: user field is missing"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1411
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1420
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1826
+#, c-format
+msgid "usage: %s [-hnR] [-d dir] [-m num] [-s num] ID\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1829
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1838
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1840
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:329
+msgid "\thost unmatched"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:332
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:333
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:333
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:230
+#, c-format
+msgid "%s is group writable"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:306
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:772 plugins/sudoers/timestamp.c:839
+#: plugins/sudoers/visudo.c:500 plugins/sudoers/visudo.c:506
+msgid "unable to read the clock"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:786
+msgid "ignoring time stamp from the future"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:798
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:893
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:937 plugins/sudoers/timestamp.c:957
+#, c-format
+msgid "lecture status path too long: %s/%s"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:188
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:266 plugins/sudoers/visudo.c:667
+#, c-format
+msgid "press return to edit %s: "
+msgstr ""
+
+#: plugins/sudoers/visudo.c:331
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:349
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:459 plugins/sudoers/visudo.c:467
+msgid "write error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:513
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:520
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:526
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:548
+#, c-format
+msgid "%s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:607
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr ""
+
+#: plugins/sudoers/visudo.c:619
+#, c-format
+msgid "unabled to parse temporary file (%s), unknown error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:656
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:736 plugins/sudoers/visudo.c:745
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:767
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:781
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:791
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:855
+msgid "What now? "
+msgstr ""
+
+#: plugins/sudoers/visudo.c:869
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:915
+#, c-format
+msgid "unable to run %s"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:945
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:952
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:981 plugins/sudoers/visudo_json.c:1021
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:997 plugins/sudoers/visudo_json.c:1032
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1000 plugins/sudoers/visudo_json.c:1035
+#, c-format
+msgid "parse error in %s\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1008 plugins/sudoers/visudo.c:1015
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1062
+#, c-format
+msgid "%s busy, try again later"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1159
+#, c-format
+msgid "Error: %s:%d cycle in %s \"%s\""
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1160
+#, c-format
+msgid "Warning: %s:%d cycle in %s \"%s\""
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1164
+#, c-format
+msgid "Error: %s:%d %s \"%s\" referenced but not defined"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1165
+#, c-format
+msgid "Warning: %s:%d %s \"%s\" referenced but not defined"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1318
+#, c-format
+msgid "Warning: %s:%d unused %s \"%s\""
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1433
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1435
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+" -x, --export=output_file write sudoers in JSON format to output_file"
+msgstr ""
+
+#: plugins/sudoers/visudo_json.c:616 plugins/sudoers/visudo_json.c:651
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr ""
+
+#: plugins/sudoers/visudo_json.c:1007
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr ""
+
+#: toke.l:943
+msgid "too many levels of includes"
+msgstr ""
diff --git a/plugins/sudoers/po/hr.mo b/plugins/sudoers/po/hr.mo
new file mode 100644
index 0000000..626fb1c
--- /dev/null
+++ b/plugins/sudoers/po/hr.mo
Binary files differ
diff --git a/plugins/sudoers/po/hr.po b/plugins/sudoers/po/hr.po
new file mode 100644
index 0000000..4202227
--- /dev/null
+++ b/plugins/sudoers/po/hr.po
@@ -0,0 +1,4233 @@
+# Translation of sudoer to Croatian.
+# This file is put in the public domain.
+#
+# Božidar Putanec <bozidarp@yahoo.com>, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers-1.9.15b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-10-19 10:02-0600\n"
+"PO-Revision-Date: 2023-10-21 18:37-0700\n"
+"Last-Translator: Božidar Putanec <bozidarp@yahoo.com>\n"
+"Language-Team: Croatian <lokalizacija@linux.hr>\n"
+"Language: hr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 3.2.2\n"
+"X-Poedit-Basepath: ../packages/sudo-1.8.23b2\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+"X-Poedit-SearchPath-0: .\n"
+
+#: confstr.sh:1 gram.y:1257 plugins/sudoers/logging.c:911
+msgid "syntax error"
+msgstr "sintaktička greška"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "Lozinka za %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] lozinka za %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Lozinka: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** SIGURNOSNE informacije za %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Pokušajte ponovo."
+
+#: gram.y:238 gram.y:305 gram.y:314 gram.y:323 gram.y:333 gram.y:343 gram.y:367
+#: gram.y:394 gram.y:403 gram.y:411 gram.y:420 gram.y:429 gram.y:503 gram.y:513
+#: gram.y:525 gram.y:573 gram.y:582 gram.y:591 gram.y:600 gram.y:733 gram.y:742
+#: gram.y:757 gram.y:777 gram.y:796 gram.y:959 gram.y:964 gram.y:972 gram.y:986
+#: gram.y:992 gram.y:1004 gram.y:1010 gram.y:1135 gram.y:1144 gram.y:1152
+#: gram.y:1161 gram.y:1170 gram.y:1199 gram.y:1208 gram.y:1216 gram.y:1317
+#: gram.y:1447 gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:313 lib/eventlog/eventlog.c:765
+#: lib/eventlog/eventlog.c:842 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:484
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:185
+#: logsrvd/iolog_writer.c:218 logsrvd/iolog_writer.c:228
+#: logsrvd/iolog_writer.c:257 logsrvd/iolog_writer.c:278
+#: logsrvd/iolog_writer.c:290 logsrvd/iolog_writer.c:300
+#: logsrvd/iolog_writer.c:310 logsrvd/iolog_writer.c:320
+#: logsrvd/iolog_writer.c:330 logsrvd/iolog_writer.c:342
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:1057 logsrvd/logsrvd.c:1120 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:650
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1743
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:216
+#: logsrvd/logsrvd_journal.c:217 logsrvd/logsrvd_journal.c:274
+#: logsrvd/logsrvd_journal.c:279 logsrvd/logsrvd_journal.c:439
+#: logsrvd/logsrvd_journal.c:441 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:216 logsrvd/logsrvd_local.c:278
+#: logsrvd/logsrvd_local.c:279 logsrvd/logsrvd_local.c:417
+#: logsrvd/logsrvd_local.c:468 logsrvd/logsrvd_local.c:469
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:475
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/logsrvd_relay.c:446
+#: logsrvd/logsrvd_relay.c:748 logsrvd/logsrvd_relay.c:855
+#: logsrvd/sendlog.c:256 logsrvd/sendlog.c:265 logsrvd/sendlog.c:297
+#: logsrvd/sendlog.c:303 logsrvd/sendlog.c:352 logsrvd/sendlog.c:630
+#: logsrvd/sendlog.c:1822 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/bsdauth.c:154 plugins/sudoers/auth/kerb5.c:122
+#: plugins/sudoers/auth/kerb5.c:150 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/auth/sia.c:61
+#: plugins/sudoers/canon_path.c:129 plugins/sudoers/canon_path.c:161
+#: plugins/sudoers/check_aliases.c:128 plugins/sudoers/check_util.c:56
+#: plugins/sudoers/check_util.c:84 plugins/sudoers/cvtsudoers.c:132
+#: plugins/sudoers/cvtsudoers.c:176 plugins/sudoers/cvtsudoers.c:193
+#: plugins/sudoers/cvtsudoers.c:204 plugins/sudoers/cvtsudoers.c:338
+#: plugins/sudoers/cvtsudoers.c:379 plugins/sudoers/cvtsudoers.c:399
+#: plugins/sudoers/cvtsudoers.c:545 plugins/sudoers/cvtsudoers.c:698
+#: plugins/sudoers/cvtsudoers.c:716 plugins/sudoers/cvtsudoers.c:891
+#: plugins/sudoers/cvtsudoers.c:899 plugins/sudoers/cvtsudoers.c:1395
+#: plugins/sudoers/cvtsudoers.c:1399 plugins/sudoers/cvtsudoers.c:1501
+#: plugins/sudoers/cvtsudoers_csv.c:183 plugins/sudoers/cvtsudoers_csv.c:247
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:152
+#: plugins/sudoers/cvtsudoers_ldif.c:195 plugins/sudoers/cvtsudoers_ldif.c:236
+#: plugins/sudoers/cvtsudoers_ldif.c:302 plugins/sudoers/cvtsudoers_ldif.c:378
+#: plugins/sudoers/cvtsudoers_ldif.c:432 plugins/sudoers/cvtsudoers_ldif.c:440
+#: plugins/sudoers/cvtsudoers_ldif.c:451 plugins/sudoers/cvtsudoers_ldif.c:458
+#: plugins/sudoers/cvtsudoers_ldif.c:470 plugins/sudoers/cvtsudoers_ldif.c:483
+#: plugins/sudoers/cvtsudoers_ldif.c:491 plugins/sudoers/cvtsudoers_ldif.c:638
+#: plugins/sudoers/cvtsudoers_merge.c:47 plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1158
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:212
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:694 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:294 plugins/sudoers/ldap_util.c:301
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:402
+#: plugins/sudoers/log_client.c:717 plugins/sudoers/log_client.c:739
+#: plugins/sudoers/log_client.c:744 plugins/sudoers/log_client.c:1426
+#: plugins/sudoers/log_client.c:1547 plugins/sudoers/log_client.c:1670
+#: plugins/sudoers/log_client.c:1993 plugins/sudoers/log_client.c:2052
+#: plugins/sudoers/logging.c:110 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:872 plugins/sudoers/lookup.c:338
+#: plugins/sudoers/lookup.c:355 plugins/sudoers/lookup.c:374
+#: plugins/sudoers/lookup.c:393 plugins/sudoers/lookup.c:410
+#: plugins/sudoers/lookup.c:433 plugins/sudoers/lookup.c:444
+#: plugins/sudoers/match_command.c:302 plugins/sudoers/match_command.c:574
+#: plugins/sudoers/match_command.c:641 plugins/sudoers/match_command.c:737
+#: plugins/sudoers/match_command.c:785 plugins/sudoers/match_digest.c:88
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:595
+#: plugins/sudoers/parse_ldif.c:625 plugins/sudoers/parse_ldif.c:650
+#: plugins/sudoers/parse_ldif.c:708 plugins/sudoers/parse_ldif.c:725
+#: plugins/sudoers/parse_ldif.c:753 plugins/sudoers/parse_ldif.c:760
+#: plugins/sudoers/policy.c:646 plugins/sudoers/policy.c:1061
+#: plugins/sudoers/prompt.c:94 plugins/sudoers/pwutil.c:219
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:368
+#: plugins/sudoers/pwutil.c:542 plugins/sudoers/pwutil.c:607
+#: plugins/sudoers/pwutil.c:679 plugins/sudoers/pwutil.c:877
+#: plugins/sudoers/pwutil.c:967 plugins/sudoers/pwutil.c:1015
+#: plugins/sudoers/pwutil.c:1076 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:145 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1307 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:256
+#: plugins/sudoers/testsudoers.c:265 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:164 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1095
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1320
+msgid "unable to allocate memory"
+msgstr "nije moguće dodijeliti memoriju"
+
+#: gram.y:624
+msgid "a digest requires a path name"
+msgstr "kontrolni zbroj zahtijeva ime staze"
+
+#: gram.y:646
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "vrijednosti za „CWD“ moraju započeti s „/“, „~“, ili „*“"
+
+#: gram.y:652
+msgid "\"CWD\" path too long"
+msgstr "„CWD“ staza je preduga"
+
+#: gram.y:662
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "vrijednosti za „CHROOT“ moraju započeti s „/“, „~“, ili „*“"
+
+#: gram.y:668
+msgid "\"CHROOT\" path too long"
+msgstr "„CHROOT“ staza je preduga"
+
+#: gram.y:817
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "sintaktička greška -- rezervirana riječ %s korištena kao alias"
+
+#: gram.y:840
+msgid "invalid notbefore value"
+msgstr "nevaljana ‘notbefore’ vrijednost"
+
+#: gram.y:849
+msgid "invalid notafter value"
+msgstr "nevaljana ‘notafter’ vrijednost"
+
+#: gram.y:859 plugins/sudoers/policy.c:390
+msgid "timeout value too large"
+msgstr "vrijednost za tajmaut je prevelika"
+
+#: gram.y:861 plugins/sudoers/policy.c:392
+msgid "invalid timeout value"
+msgstr "nevaljana vrijednost za tajmaut"
+
+#: gram.y:982 plugins/sudoers/sudoers.c:1162
+msgid "command too long"
+msgstr "naredba je preduga"
+
+#: gram.y:1016
+msgid "expected a fully-qualified path name"
+msgstr "očekivano je potpuno kvalificirano ime staze"
+
+#: gram.y:1261
+#, c-format
+msgid "%s:%d:%zu: %s\n"
+msgstr "%s:%d:%zu: %s\n"
+
+#: gram.y:1315
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Alias „%s“ je već ranije definiran"
+
+#: gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:765 lib/eventlog/eventlog.c:838
+#: lib/eventlog/eventlog.c:841 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:483
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:232
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:174
+#: logsrvd/iolog_writer.c:184 logsrvd/iolog_writer.c:197
+#: logsrvd/iolog_writer.c:217 logsrvd/iolog_writer.c:227
+#: logsrvd/iolog_writer.c:246 logsrvd/iolog_writer.c:256
+#: logsrvd/iolog_writer.c:267 logsrvd/iolog_writer.c:277
+#: logsrvd/iolog_writer.c:289 logsrvd/iolog_writer.c:299
+#: logsrvd/iolog_writer.c:309 logsrvd/iolog_writer.c:319
+#: logsrvd/iolog_writer.c:329 logsrvd/iolog_writer.c:341
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:530
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:668
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:1131
+#: logsrvd/logsrvd.c:1446 logsrvd/logsrvd.c:1453 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:649
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1742
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:125
+#: logsrvd/logsrvd_journal.c:216 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:250 logsrvd/logsrvd_journal.c:258
+#: logsrvd/logsrvd_journal.c:287 logsrvd/logsrvd_journal.c:291
+#: logsrvd/logsrvd_journal.c:439 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:278 logsrvd/logsrvd_local.c:468
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:493
+#: logsrvd/logsrvd_queue.c:158 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/sendlog.c:256 logsrvd/sendlog.c:265
+#: logsrvd/sendlog.c:297 logsrvd/sendlog.c:303 logsrvd/sendlog.c:352
+#: logsrvd/sendlog.c:630 logsrvd/sendlog.c:1523 logsrvd/sendlog.c:1530
+#: logsrvd/sendlog.c:1753 logsrvd/sendlog.c:1822 logsrvd/tls_init.c:305
+#: logsrvd/tls_init.c:329 logsrvd/tls_init.c:340 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/pam.c:518 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/canon_path.c:129
+#: plugins/sudoers/canon_path.c:161 plugins/sudoers/check_aliases.c:128
+#: plugins/sudoers/check_util.c:56 plugins/sudoers/check_util.c:84
+#: plugins/sudoers/cvtsudoers.c:132 plugins/sudoers/cvtsudoers.c:175
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:203
+#: plugins/sudoers/cvtsudoers.c:337 plugins/sudoers/cvtsudoers.c:544
+#: plugins/sudoers/cvtsudoers.c:697 plugins/sudoers/cvtsudoers.c:715
+#: plugins/sudoers/cvtsudoers.c:891 plugins/sudoers/cvtsudoers.c:898
+#: plugins/sudoers/cvtsudoers.c:1395 plugins/sudoers/cvtsudoers.c:1399
+#: plugins/sudoers/cvtsudoers.c:1501 plugins/sudoers/cvtsudoers_csv.c:182
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:151 plugins/sudoers/cvtsudoers_ldif.c:194
+#: plugins/sudoers/cvtsudoers_ldif.c:235 plugins/sudoers/cvtsudoers_ldif.c:301
+#: plugins/sudoers/cvtsudoers_ldif.c:377 plugins/sudoers/cvtsudoers_ldif.c:431
+#: plugins/sudoers/cvtsudoers_ldif.c:439 plugins/sudoers/cvtsudoers_ldif.c:450
+#: plugins/sudoers/cvtsudoers_ldif.c:457 plugins/sudoers/cvtsudoers_ldif.c:469
+#: plugins/sudoers/cvtsudoers_ldif.c:482 plugins/sudoers/cvtsudoers_ldif.c:490
+#: plugins/sudoers/cvtsudoers_ldif.c:637 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51 plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1157
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:211
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:693 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:293 plugins/sudoers/ldap_util.c:300
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:228
+#: plugins/sudoers/log_client.c:250 plugins/sudoers/log_client.c:264
+#: plugins/sudoers/log_client.c:402 plugins/sudoers/log_client.c:717
+#: plugins/sudoers/log_client.c:739 plugins/sudoers/log_client.c:744
+#: plugins/sudoers/log_client.c:1426 plugins/sudoers/log_client.c:1547
+#: plugins/sudoers/log_client.c:1670 plugins/sudoers/log_client.c:1993
+#: plugins/sudoers/log_client.c:2052 plugins/sudoers/logging.c:110
+#: plugins/sudoers/logging.c:189 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:755 plugins/sudoers/logging.c:872
+#: plugins/sudoers/logging.c:925 plugins/sudoers/logging.c:932
+#: plugins/sudoers/lookup.c:337 plugins/sudoers/lookup.c:354
+#: plugins/sudoers/lookup.c:373 plugins/sudoers/lookup.c:392
+#: plugins/sudoers/lookup.c:409 plugins/sudoers/lookup.c:432
+#: plugins/sudoers/lookup.c:443 plugins/sudoers/match_command.c:301
+#: plugins/sudoers/match_command.c:573 plugins/sudoers/match_command.c:640
+#: plugins/sudoers/match_command.c:737 plugins/sudoers/match_command.c:784
+#: plugins/sudoers/match_digest.c:88 plugins/sudoers/parse_ldif.c:152
+#: plugins/sudoers/parse_ldif.c:183 plugins/sudoers/parse_ldif.c:252
+#: plugins/sudoers/parse_ldif.c:260 plugins/sudoers/parse_ldif.c:265
+#: plugins/sudoers/parse_ldif.c:341 plugins/sudoers/parse_ldif.c:352
+#: plugins/sudoers/parse_ldif.c:379 plugins/sudoers/parse_ldif.c:396
+#: plugins/sudoers/parse_ldif.c:408 plugins/sudoers/parse_ldif.c:412
+#: plugins/sudoers/parse_ldif.c:426 plugins/sudoers/parse_ldif.c:484
+#: plugins/sudoers/parse_ldif.c:595 plugins/sudoers/parse_ldif.c:624
+#: plugins/sudoers/parse_ldif.c:649 plugins/sudoers/parse_ldif.c:707
+#: plugins/sudoers/parse_ldif.c:724 plugins/sudoers/parse_ldif.c:752
+#: plugins/sudoers/parse_ldif.c:759 plugins/sudoers/policy.c:157
+#: plugins/sudoers/policy.c:166 plugins/sudoers/policy.c:175
+#: plugins/sudoers/policy.c:204 plugins/sudoers/policy.c:374
+#: plugins/sudoers/policy.c:390 plugins/sudoers/policy.c:392
+#: plugins/sudoers/policy.c:430 plugins/sudoers/policy.c:439
+#: plugins/sudoers/policy.c:448 plugins/sudoers/policy.c:457
+#: plugins/sudoers/policy.c:493 plugins/sudoers/policy.c:502
+#: plugins/sudoers/policy.c:511 plugins/sudoers/policy.c:520
+#: plugins/sudoers/policy.c:529 plugins/sudoers/policy.c:538
+#: plugins/sudoers/policy.c:547 plugins/sudoers/policy.c:646
+#: plugins/sudoers/policy.c:1061 plugins/sudoers/prompt.c:94
+#: plugins/sudoers/pwutil.c:219 plugins/sudoers/pwutil.c:290
+#: plugins/sudoers/pwutil.c:368 plugins/sudoers/pwutil.c:542
+#: plugins/sudoers/pwutil.c:607 plugins/sudoers/pwutil.c:679
+#: plugins/sudoers/pwutil.c:877 plugins/sudoers/pwutil.c:967
+#: plugins/sudoers/pwutil.c:1015 plugins/sudoers/pwutil.c:1076
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1306 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:255
+#: plugins/sudoers/testsudoers.c:264 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:163 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1094
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1309 toke.l:1320
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:304
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "nije moguće duplicirati stdin: %m"
+
+#: lib/eventlog/eventlog.c:346
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "nije moguće izvršiti %s: %m"
+
+#: lib/eventlog/eventlog.c:394 plugins/sudoers/auth/aix_auth.c:199
+msgid "unable to fork"
+msgstr "nije moguće stvoriti novi proces (greška u fork())"
+
+#: lib/eventlog/eventlog.c:404 lib/eventlog/eventlog.c:471
+#, c-format
+msgid "unable to fork: %m"
+msgstr "nije moguće stvoriti novi proces (greška u fork()): %m"
+
+#: lib/eventlog/eventlog.c:461
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "nije moguće otvoriti cijev: %m"
+
+#: lib/eventlog/eventlog.c:1000
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:1029
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (naredba se nastavlja) %s"
+
+#: lib/eventlog/parse_json.c:175
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "očekivan je JSON_STRING, dobiven je %d"
+
+#: lib/eventlog/parse_json.c:180
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY je prevelik"
+
+#: lib/eventlog/parse_json.c:506
+msgid "missing double quote in name"
+msgstr "imenu nedostaje navodnik (\")"
+
+#: lib/eventlog/parse_json.c:624
+msgid "missing JSON_OBJECT"
+msgstr "nedostaje JSON_OBJECT"
+
+#: lib/eventlog/parse_json.c:628
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "očekivan je JSON_OBJECT, dobiven je %d"
+
+#: lib/eventlog/parse_json.c:762
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "json stog je potrošen (max %u okvira)"
+
+#: lib/eventlog/parse_json.c:840
+msgid "objects must consist of name:value pairs"
+msgstr "objekti se moraju sastojati od parova ime:vrijednost"
+
+#: lib/eventlog/parse_json.c:845 lib/eventlog/parse_json.c:876
+#: lib/eventlog/parse_json.c:920 lib/eventlog/parse_json.c:942
+#: lib/eventlog/parse_json.c:964 lib/eventlog/parse_json.c:986
+#: lib/eventlog/parse_json.c:1008
+msgid "missing separator between values"
+msgstr "nedostaje separator između vrijednosti"
+
+#: lib/eventlog/parse_json.c:860 lib/eventlog/parse_json.c:1034
+msgid "unmatched close brace"
+msgstr "nesparena zatvorena vitičasta zagrada }"
+
+#: lib/eventlog/parse_json.c:871
+msgid "unexpected array"
+msgstr "neočekivano polje"
+
+#: lib/eventlog/parse_json.c:891 lib/eventlog/parse_json.c:1037
+msgid "unmatched close bracket"
+msgstr "nesparena zatvorena uglata zagrada ]"
+
+#: lib/eventlog/parse_json.c:902
+msgid "unexpected string"
+msgstr "neočekivani string"
+
+#: lib/eventlog/parse_json.c:913
+msgid "missing colon after name"
+msgstr "nedostaje dvotočka iza imena"
+
+#: lib/eventlog/parse_json.c:934 lib/eventlog/parse_json.c:956
+msgid "unexpected boolean"
+msgstr "neočekivana logička operacija (boolean)"
+
+#: lib/eventlog/parse_json.c:978
+msgid "unexpected null"
+msgstr "neočekivana nula"
+
+#: lib/eventlog/parse_json.c:999
+msgid "unexpected number"
+msgstr "neočekivani broj"
+
+#: lib/eventlog/parse_json.c:1045
+msgid "parse error"
+msgstr "greška u raščlambi"
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1290
+#: plugins/sudoers/sudoreplay.c:1291 plugins/sudoers/sudoreplay.c:1587
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr "nevaljani regularni izraz: „%s“: %s"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: nevaljana dnevnička datoteka"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: nedostaje polje za vremensku oznaku"
+
+#: lib/iolog/iolog_legacy.c:90
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: vremenska oznaka %s: %s"
+
+#: lib/iolog/iolog_legacy.c:97
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: nedostaje polje za korisnika"
+
+#: lib/iolog/iolog_legacy.c:108
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: nedostaje polje za runas-korisnika"
+
+#: lib/iolog/iolog_legacy.c:119
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: nedostaje polje za runas-grupe"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s postoji ali nije direktorij (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:124 lib/iolog/iolog_mkdtemp.c:80
+#: logsrvd/iolog_writer.c:795 plugins/sudoers/timestamp.c:218
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "nije moguće napraviti direktorij %s"
+
+#: lib/iolog/iolog_mkdtemp.c:85 plugins/sudoers/visudo.c:769
+#: plugins/sudoers/visudo.c:803 plugins/sudoers/visudo.c:809
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "nije moguće promijeniti mȏd od %s na 0%o"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "greška pri čitanju tajming datoteke: %s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "nevaljani redak u tajming datoteci: %s"
+
+#: logsrvd/iolog_writer.c:65
+#, c-format
+msgid "%s: protocol error: NULL key"
+msgstr "%s: greška u protokolu : NULL ključ"
+
+#: logsrvd/iolog_writer.c:69
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s: greška u protokolu : krivi tip za %s"
+
+#: logsrvd/iolog_writer.c:74 logsrvd/logsrvd_local.c:109
+#: logsrvd/logsrvd_local.c:123 logsrvd/logsrvd_local.c:131
+#: logsrvd/logsrvd_local.c:149
+#, c-format
+msgid "%s: protocol error: NULL value found in %s"
+msgstr "%s: greška u protokolu : u %s je pronađena NULL vrijednost"
+
+#: logsrvd/iolog_writer.c:141 plugins/sudoers/logging.c:1024
+#: plugins/sudoers/policy.c:613
+msgid "unable to generate UUID"
+msgstr "nije moguće generirati UUID"
+
+#: logsrvd/iolog_writer.c:354 logsrvd/iolog_writer.c:359
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:369
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s: greška u protokolu : %s nedostaje u AcceptMessage"
+
+#: logsrvd/iolog_writer.c:430
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s: nije moguće oblikovati id sesije"
+
+#: logsrvd/iolog_writer.c:444 logsrvd/iolog_writer.c:458
+#: logsrvd/iolog_writer.c:472 logsrvd/iolog_writer.c:487
+#: logsrvd/iolog_writer.c:501 logsrvd/iolog_writer.c:515
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s: %s nije postavljen"
+
+#: logsrvd/iolog_writer.c:551 logsrvd/iolog_writer.c:558
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr "nije moguće proširiti stazu iolog (I/O FD) %s"
+
+#: logsrvd/iolog_writer.c:576
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr "nije moguće stvoriti stazu iolog (I/O FD) %s"
+
+#: logsrvd/iolog_writer.c:606
+#, c-format
+msgid "invalid iofd %d"
+msgstr "nevaljani iofd (I/O FD) %d"
+
+#: logsrvd/iolog_writer.c:626
+#, c-format
+msgid "error closing iofd %u: %s"
+msgstr "greška pri zatvaranju iofd (I/O FD) %u: %s"
+
+#: logsrvd/iolog_writer.c:647
+#, c-format
+msgid "error flushing iofd %u: %s"
+msgstr "greška brisanja iofd %u: %s"
+
+#: logsrvd/iolog_writer.c:765
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "nevaljani U/I zapis %s: %s ima referenciju ali ne postoji"
+
+#: logsrvd/iolog_writer.c:777 logsrvd/logsrvd_journal.c:391
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "%s: nije moguće naći točku [%lld, %ld] od koje treba nastaviti"
+
+#: logsrvd/iolog_writer.c:799 logsrvd/logsrvd_journal.c:434
+#: logsrvd/logsrvd_queue.c:115 logsrvd/tls_init.c:256
+#: plugins/sudoers/check.c:285 plugins/sudoers/cvtsudoers.c:758
+#: plugins/sudoers/cvtsudoers.c:780 plugins/sudoers/cvtsudoers.c:1461
+#: plugins/sudoers/cvtsudoers_csv.c:697 plugins/sudoers/cvtsudoers_json.c:902
+#: plugins/sudoers/cvtsudoers_ldif.c:711 plugins/sudoers/sudoers.c:1291
+#: plugins/sudoers/sudoers.c:1317 plugins/sudoers/sudoreplay.c:1497
+#: plugins/sudoers/timestamp.c:478 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:990
+#, c-format
+msgid "unable to open %s"
+msgstr "nije moguće otvoriti %s"
+
+#: logsrvd/iolog_writer.c:811 logsrvd/logsrv_util.c:111
+#: logsrvd/logsrv_util.c:118 plugins/sudoers/sudoreplay.c:355
+#: plugins/sudoers/sudoreplay.c:361
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "nije moguće otvoriti %s/%s"
+
+#: logsrvd/iolog_writer.c:824
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "nije moguće kopirati %s/%s u %s/%s: %s"
+
+#: logsrvd/iolog_writer.c:853 logsrvd/logsrvd_journal.c:198
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "nije moguće preimenovati %s u %s"
+
+#: logsrvd/logsrv_util.c:153 logsrvd/logsrv_util.c:182
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s: nije moguće naći točku [%lld, %ld] od koje treba nastaviti"
+
+#: logsrvd/logsrv_util.c:165
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "nema dnevničke datoteke U/I %s/%s"
+
+#: logsrvd/logsrv_util.c:172
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s: nije moguće skočiti naprijed na %zu"
+
+#: logsrvd/logsrvd.c:271 logsrvd/logsrvd_queue.c:135
+msgid "unable to connect to relay"
+msgstr "nije moguće spojiti se na relej"
+
+#: logsrvd/logsrvd.c:338 logsrvd/logsrvd_relay.c:847
+#, c-format
+msgid "server message too large: %zu"
+msgstr "poruka servera je prevelika: %zu"
+
+#: logsrvd/logsrvd.c:430 logsrvd/logsrvd.c:553 logsrvd/logsrvd.c:639
+#: logsrvd/logsrvd.c:881 logsrvd/logsrvd.c:895 logsrvd/logsrvd.c:1056
+#: logsrvd/logsrvd.c:1181 logsrvd/logsrvd.c:1354 logsrvd/logsrvd.c:1372
+#: logsrvd/logsrvd.c:1471 logsrvd/logsrvd.c:1596 logsrvd/logsrvd.c:1783
+#: logsrvd/logsrvd_journal.c:503 logsrvd/logsrvd_local.c:238
+#: logsrvd/logsrvd_queue.c:164 logsrvd/logsrvd_relay.c:172
+#: logsrvd/logsrvd_relay.c:249 logsrvd/logsrvd_relay.c:253
+#: logsrvd/logsrvd_relay.c:391 logsrvd/logsrvd_relay.c:583
+#: logsrvd/logsrvd_relay.c:747 logsrvd/logsrvd_relay.c:1137
+#: logsrvd/sendlog.c:1308 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:216 plugins/sudoers/audit.c:281
+#: plugins/sudoers/iolog.c:1041 plugins/sudoers/iolog.c:1175
+#: plugins/sudoers/iolog.c:1274 plugins/sudoers/log_client.c:121
+#: plugins/sudoers/log_client.c:343 plugins/sudoers/log_client.c:359
+#: plugins/sudoers/log_client.c:407 plugins/sudoers/log_client.c:613
+#: plugins/sudoers/log_client.c:620 plugins/sudoers/log_client.c:1114
+#: plugins/sudoers/log_client.c:1395 plugins/sudoers/log_client.c:1436
+#: plugins/sudoers/log_client.c:1444 plugins/sudoers/log_client.c:1603
+#: plugins/sudoers/log_client.c:1728 plugins/sudoers/log_client.c:2060
+#: plugins/sudoers/log_client.c:2068 plugins/sudoers/logging.c:148
+#: plugins/sudoers/logging.c:206 plugins/sudoers/sudoreplay.c:519
+#: plugins/sudoers/sudoreplay.c:566 plugins/sudoers/sudoreplay.c:808
+#: plugins/sudoers/sudoreplay.c:920 plugins/sudoers/sudoreplay.c:1011
+#: plugins/sudoers/sudoreplay.c:1026 plugins/sudoers/sudoreplay.c:1033
+#: plugins/sudoers/sudoreplay.c:1040 plugins/sudoers/sudoreplay.c:1047
+#: plugins/sudoers/sudoreplay.c:1054 plugins/sudoers/sudoreplay.c:1182
+msgid "unable to add event to queue"
+msgstr "nije moguće dodati događaj u red čekanja"
+
+#: logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:491 logsrvd/logsrvd.c:523
+#: logsrvd/logsrvd.c:577 logsrvd/logsrvd.c:656 logsrvd/logsrvd.c:692
+#: logsrvd/logsrvd.c:728 logsrvd/logsrvd.c:764 logsrvd/logsrvd_relay.c:512
+#: logsrvd/logsrvd_relay.c:545
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr "neočekivano stanje %d za %s"
+
+#: logsrvd/logsrvd.c:455 logsrvd/logsrvd.c:492 logsrvd/logsrvd.c:524
+#: logsrvd/logsrvd.c:578 logsrvd/logsrvd.c:657 logsrvd/logsrvd.c:693
+#: logsrvd/logsrvd.c:729 logsrvd/logsrvd.c:765 logsrvd/logsrvd_relay.c:514
+#: logsrvd/logsrvd_relay.c:547
+msgid "state machine error"
+msgstr "greška automata (state machine)"
+
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:462
+msgid "invalid AcceptMessage"
+msgstr "nevaljani AcceptMessage"
+
+#: logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:499
+msgid "invalid RejectMessage"
+msgstr "nevaljani RejectMessage"
+
+#: logsrvd/logsrvd.c:530 logsrvd/logsrvd.c:531
+msgid "invalid ExitMessage"
+msgstr "nevaljani ExitMessage"
+
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:585
+msgid "invalid RestartMessage"
+msgstr "nevaljani RestartMessage"
+
+#: logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:620
+msgid "invalid AlertMessage"
+msgstr "nevaljani AlertMessage"
+
+#: logsrvd/logsrvd.c:661 logsrvd/logsrvd.c:697 logsrvd/logsrvd.c:733
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s: neočekivani IoBuffer"
+
+#: logsrvd/logsrvd.c:662 logsrvd/logsrvd.c:698 logsrvd/logsrvd.c:734
+msgid "protocol error"
+msgstr "greška protokola"
+
+#: logsrvd/logsrvd.c:668 logsrvd/logsrvd.c:669
+msgid "invalid IoBuffer"
+msgstr "nevaljani IoBuffer"
+
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:705
+msgid "invalid ChangeWindowSize"
+msgstr "nevaljani ChangeWindowSize"
+
+#: logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:741
+msgid "invalid CommandSuspend"
+msgstr "nevaljani CommandSuspend"
+
+#: logsrvd/logsrvd.c:790 logsrvd/logsrvd_journal.c:302
+#: logsrvd/logsrvd_relay.c:654 logsrvd/sendlog.c:1207
+#: plugins/sudoers/log_client.c:1593
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "nije moguće raspakirati %s veličinu %zu"
+
+#: logsrvd/logsrvd.c:835 logsrvd/logsrvd_journal.c:376
+#: logsrvd/logsrvd_relay.c:678
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "neočekivana type_case vrijednost %d u %s iz %s"
+
+#: logsrvd/logsrvd.c:837
+msgid "unrecognized ClientMessage type"
+msgstr "neprepoznati tip ClientMessage-a"
+
+#: logsrvd/logsrvd.c:927
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "vrijeme za pisanje klijentu %s je isteklo"
+
+#: logsrvd/logsrvd.c:932 logsrvd/logsrvd_relay.c:919 logsrvd/sendlog.c:1413
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr "nema međuspremnika za pisanje za %s klijenta"
+
+#: logsrvd/logsrvd.c:1027
+#, c-format
+msgid "timed out reading from client %s"
+msgstr "isteklo je vrijeme za čitanje od %s klijenta"
+
+#: logsrvd/logsrvd.c:1068 logsrvd/logsrvd_relay.c:782
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr "EOF od %s nije propisno zatvaranje TLS-a"
+
+#: logsrvd/logsrvd.c:1112 logsrvd/logsrvd_relay.c:205 logsrvd/sendlog.c:336
+#: plugins/sudoers/log_client.c:723
+#, c-format
+msgid "client message too large: %zu"
+msgstr "poruka klijenta je prevelika: %zu"
+
+#: logsrvd/logsrvd.c:1113 logsrvd/logsrvd_journal.c:259
+#: logsrvd/logsrvd_journal.c:260
+msgid "client message too large"
+msgstr "poruka klijenta je prevelika"
+
+#: logsrvd/logsrvd.c:1131 logsrvd/logsrvd.c:1132
+msgid "invalid ClientMessage"
+msgstr "nevaljana ClientMessage"
+
+#: logsrvd/logsrvd.c:1432
+msgid "unable to get remote IP addr"
+msgstr "nije moguće dobiti udaljenu IP adresu"
+
+#: logsrvd/logsrvd.c:1463 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:281
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "Nije moguće prikvačiti podatke korisnika na SSL objekt: %s"
+
+#: logsrvd/logsrvd.c:1646 logsrvd/logsrvd.c:2007
+msgid "unable to setup listen socket"
+msgstr "nije moguće postaviti priključak za slušanje (listen socket)"
+
+#: logsrvd/logsrvd.c:1766
+#, c-format
+msgid "unexpected signal %d"
+msgstr "neočekivani signal %d"
+
+#: logsrvd/logsrvd.c:1909
+msgid "sudo log server"
+msgstr "server sudo dnevnika"
+
+#: logsrvd/logsrvd.c:1911 logsrvd/sendlog.c:126
+msgid "Options:"
+msgstr "Opcije:"
+
+#: logsrvd/logsrvd.c:1913
+msgid "path to configuration file"
+msgstr "staza do datoteke s postavkama"
+
+#: logsrvd/logsrvd.c:1915 logsrvd/sendlog.c:128
+msgid "display help message and exit"
+msgstr "pokaže poruku s pomoći i iziđe"
+
+#: logsrvd/logsrvd.c:1917
+msgid "do not fork, run in the foreground"
+msgstr "ne stvara novi proces, radi u prednjem planu"
+
+#: logsrvd/logsrvd.c:1919
+msgid "percent chance connections will drop"
+msgstr "postotak šanse da će se veza prekinuti"
+
+#: logsrvd/logsrvd.c:1921 logsrvd/sendlog.c:158
+msgid "display version information and exit"
+msgstr "prikaže podatke o inačici i iziđe"
+
+#: logsrvd/logsrvd.c:1971 logsrvd/sendlog.c:1722
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "Potrebna je Protobuf-C inačica 1.3 ili novija"
+
+#: logsrvd/logsrvd.c:1987
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "nevaljana ‘random drop’ vrijednost: %s"
+
+#: logsrvd/logsrvd.c:1990 logsrvd/sendlog.c:1776
+#: plugins/sudoers/cvtsudoers.c:250 plugins/sudoers/sudoreplay.c:294
+#: plugins/sudoers/visudo.c:181
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s inačica %s\n"
+
+#: logsrvd/logsrvd_conf.c:422 plugins/sudoers/check.c:69
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/sudoers.c:419 plugins/sudoers/sudoers.c:929
+#: plugins/sudoers/sudoers.c:1034 plugins/sudoers/sudoers.c:1424
+#: plugins/sudoers/testsudoers.c:169 plugins/sudoers/testsudoers.c:285
+#: plugins/sudoers/testsudoers.c:459
+#, c-format
+msgid "unknown user %s"
+msgstr "nepoznati korisnik %s"
+
+#: logsrvd/logsrvd_conf.c:439 plugins/sudoers/iolog.c:148
+#: plugins/sudoers/sudoers.c:425 plugins/sudoers/sudoers.c:1458
+#: plugins/sudoers/testsudoers.c:483
+#, c-format
+msgid "unknown group %s"
+msgstr "nepoznata grupa %s"
+
+#: logsrvd/logsrvd_conf.c:457
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr "nije moguće razabrati način %s iolog-a"
+
+#: logsrvd/logsrvd_conf.c:474 logsrvd/logsrvd_conf.c:1243
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "nevaljana vrijednost za %s: %s"
+
+#: logsrvd/logsrvd_conf.c:527
+msgid "TLS not supported"
+msgstr "TLS nije podržan"
+
+#: logsrvd/logsrvd_conf.c:549
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:622 logsrvd/logsrvd_conf.c:1032
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s: to nije potpuno kvalificirana staza"
+
+#: logsrvd/logsrvd_conf.c:951 logsrvd/logsrvd_conf.c:967
+#: logsrvd/logsrvd_conf.c:1676
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "nepoznati ustroj za syslog (Protokol dnevničarenja sustava): %s"
+
+#: logsrvd/logsrvd_conf.c:983 logsrvd/logsrvd_conf.c:999
+#: logsrvd/logsrvd_conf.c:1015 logsrvd/logsrvd_conf.c:1680
+#: logsrvd/logsrvd_conf.c:1684 logsrvd/logsrvd_conf.c:1688
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "nepoznati prioritet %s za protokol dnevnika sustava (syslog)"
+
+#: logsrvd/logsrvd_conf.c:1197
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d ne podudara '[': %s"
+
+#: logsrvd/logsrvd_conf.c:1203
+#, c-format
+msgid "%s:%d garbage after ']': %s"
+msgstr "%s:%d smeće iza ']': %s"
+
+#: logsrvd/logsrvd_conf.c:1215
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s:%d nevaljana sekcija u konfiguraciji: %s"
+
+#: logsrvd/logsrvd_conf.c:1223
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d nevaljani redak u konfiguraciji: %s"
+
+#: logsrvd/logsrvd_conf.c:1229
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d očekivano ime sekcije: %s"
+
+#: logsrvd/logsrvd_conf.c:1251
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] nelegalni ključ : %s"
+
+#: logsrvd/logsrvd_conf.c:1281 plugins/sudoers/cvtsudoers.c:273
+#: plugins/sudoers/logging.c:1076
+#, c-format
+msgid "unable to open log file %s"
+msgstr "nije moguće otvoriti dnevničku datoteku %s"
+
+#: logsrvd/logsrvd_conf.c:1763
+msgid "unable to initialize server TLS context"
+msgstr "nije moguće inicijalizirati server TLS konteksta"
+
+#: logsrvd/logsrvd_conf.c:1783
+msgid "unable to initialize relay TLS context"
+msgstr "nije moguće inicijalizirati relej SSL konteksta"
+
+#: logsrvd/logsrvd_journal.c:149 logsrvd/logsrvd_journal.c:430
+#: logsrvd/logsrvd_journal.c:435
+msgid "unable to create journal file"
+msgstr "nije moguće stvoriti dnevničku datoteku"
+
+#: logsrvd/logsrvd_journal.c:153 logsrvd/logsrvd_queue.c:109
+#: plugins/sudoers/visudo.c:1046
+#, c-format
+msgid "unable to lock %s"
+msgstr "nije moguće zaključati %s"
+
+#: logsrvd/logsrvd_journal.c:156
+msgid "unable to lock journal file"
+msgstr "nije moguće zaključati dnevničku datoteku"
+
+#: logsrvd/logsrvd_journal.c:164
+msgid "unable to open journal file"
+msgstr "nije moguće otvoriti dnevničku datoteku"
+
+#: logsrvd/logsrvd_journal.c:185 logsrvd/logsrvd_journal.c:466
+#: logsrvd/logsrvd_journal.c:471
+msgid "unable to write journal file"
+msgstr "nije moguće pisati u dnevničku datoteku"
+
+#: logsrvd/logsrvd_journal.c:193 logsrvd/logsrvd_journal.c:200
+msgid "unable to rename journal file"
+msgstr "nije moguće preimenovati dnevničku datoteku"
+
+#: logsrvd/logsrvd_journal.c:247 logsrvd/logsrvd_journal.c:248
+#: logsrvd/logsrvd_journal.c:288 logsrvd/logsrvd_journal.c:289
+msgid "unexpected EOF reading journal file"
+msgstr "neočekivani EOF pri čitanju dnevnika"
+
+#: logsrvd/logsrvd_journal.c:251 logsrvd/logsrvd_journal.c:252
+#: logsrvd/logsrvd_journal.c:292 logsrvd/logsrvd_journal.c:293
+msgid "error reading journal file"
+msgstr "greška pri čitanju dnevnika"
+
+#: logsrvd/logsrvd_journal.c:304 logsrvd/logsrvd_journal.c:390
+msgid "invalid journal file, unable to restart"
+msgstr "nevaljana datoteka dnevnika, ponovno pokretanje nije uspjelo"
+
+#: logsrvd/logsrvd_journal.c:449
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "nije moguće skočiti na točku [%lld, %ld] u dnevniku %s"
+
+#: logsrvd/logsrvd_local.c:166
+#, c-format
+msgid "unexpected value_case %d in %s from %s"
+msgstr "neočekivana value_case %d u %s iz %s"
+
+#: logsrvd/logsrvd_local.c:194
+msgid "error parsing AcceptMessage"
+msgstr "greška pri raščlanivanju AcceptMessage"
+
+#: logsrvd/logsrvd_local.c:205
+msgid "error creating I/O log"
+msgstr "greška pri stvaranju U/I dnevnika"
+
+#: logsrvd/logsrvd_local.c:228
+msgid "error logging accept event"
+msgstr "greška pri upisivanju u dnevnik ‘accept’ događaja"
+
+#: logsrvd/logsrvd_local.c:267
+msgid "error parsing RejectMessage"
+msgstr "greška pri raščlanivanju RejectMessage-a"
+
+#: logsrvd/logsrvd_local.c:291
+msgid "error logging reject event"
+msgstr "greška pri upisivanju u dnevnik ‘reject’ događaja"
+
+#: logsrvd/logsrvd_local.c:427 logsrvd/logsrvd_local.c:437
+msgid "error logging exit event"
+msgstr "greška pri upisivanju u dnevnik exit događaja"
+
+#: logsrvd/logsrvd_local.c:494 logsrvd/logsrvd_local.c:495
+msgid "log is already complete, cannot be restarted"
+msgstr "dnevnik je već kompletiran -- ne može se ponovno pokrenuti"
+
+#: logsrvd/logsrvd_local.c:525
+msgid "unable to restart log"
+msgstr "nije moguće ponovno pokrenuti dnevničarenje (logging)"
+
+#: logsrvd/logsrvd_local.c:541
+msgid "error parsing AlertMessage"
+msgstr "greška pri raščlanivanju AlertMessage"
+
+#: logsrvd/logsrvd_local.c:551
+msgid "error logging alert event"
+msgstr "greška pri upisivanju u dnevnik ‘alert’ događaja"
+
+#: logsrvd/logsrvd_local.c:587 logsrvd/logsrvd_local.c:650
+#: logsrvd/logsrvd_local.c:685
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr "nije moguće oblikovati vremenski spremnik, dužine %d"
+
+#: logsrvd/logsrvd_local.c:601 logsrvd/logsrvd_local.c:609
+#: logsrvd/logsrvd_local.c:657 logsrvd/logsrvd_local.c:692
+#: plugins/sudoers/sudoreplay.c:344 toke.l:981 toke.l:984
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: logsrvd/logsrvd_local.c:620
+msgid "randomly dropping connection"
+msgstr "nasumični prekidi spajanja"
+
+#: logsrvd/logsrvd_local.c:632
+msgid "error writing IoBuffer"
+msgstr "greška pri pisanju IoBuffer-a"
+
+#: logsrvd/logsrvd_local.c:667
+msgid "error writing ChangeWindowSize"
+msgstr "greška pri pisanju ChangeWindowSize-a"
+
+#: logsrvd/logsrvd_local.c:702
+msgid "error writing CommandSuspend"
+msgstr "greška pri pisanju CommandSuspend-a"
+
+#: logsrvd/logsrvd_relay.c:437
+msgid "TLS handshake with relay host failed"
+msgstr "TLS rukovanje s hostom releja nije uspjelo"
+
+#: logsrvd/logsrvd_relay.c:465
+msgid "unable to connect to relay host"
+msgstr "nije moguće spojiti se na host releja"
+
+#: logsrvd/logsrvd_relay.c:520
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s: nevaljani ServerHello, nedostaje server_id"
+
+#: logsrvd/logsrvd_relay.c:522 logsrvd/sendlog.c:1111
+#: plugins/sudoers/log_client.c:1479
+msgid "invalid ServerHello"
+msgstr "nevaljani ServerHello"
+
+#: logsrvd/logsrvd_relay.c:681
+msgid "unrecognized ServerMessage type"
+msgstr "neprepoznati tip ServerMessage-a"
+
+#: logsrvd/logsrvd_relay.c:710
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr "isteklo je vrijeme za čitanje iz releja %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:712
+msgid "timeout reading from relay"
+msgstr "isteklo je vrijeme za čitanje iz releja"
+
+#: logsrvd/logsrvd_relay.c:767
+msgid "relay host name does not match certificate"
+msgstr "ime hosta releja ne slaže se s certifikatom"
+
+#: logsrvd/logsrvd_relay.c:773 logsrvd/logsrvd_relay.c:787
+#: logsrvd/logsrvd_relay.c:794
+msgid "error reading from relay"
+msgstr "greška čitanja iz releja"
+
+#: logsrvd/logsrvd_relay.c:815
+msgid "unable to read from relay"
+msgstr "nije moguće čitati iz releja"
+
+#: logsrvd/logsrvd_relay.c:830 logsrvd/logsrvd_relay.c:949
+msgid "relay server closed connection"
+msgstr "server releja je prekinuo vezu"
+
+#: logsrvd/logsrvd_relay.c:848
+msgid "server message too large"
+msgstr "poruka servera je prevelika"
+
+#: logsrvd/logsrvd_relay.c:912
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr "vrijeme za pisanje na relej %s (%s) je isteklo"
+
+#: logsrvd/logsrvd_relay.c:914
+msgid "timeout writing to relay"
+msgstr "vrijeme za pisanje na relej je isteklo"
+
+#: logsrvd/logsrvd_relay.c:968 logsrvd/logsrvd_relay.c:975
+#: logsrvd/logsrvd_relay.c:987
+msgid "error writing to relay"
+msgstr "greška pri pisanju na relej"
+
+#: logsrvd/sendlog.c:124
+msgid "send sudo I/O log to remote server"
+msgstr "pošalje sudo U/I dnevnik na udaljeni poslužitelj"
+
+#: logsrvd/sendlog.c:130
+msgid "only send an accept event (no I/O)"
+msgstr "pošalje samo prihvaćene događaje (ne i U/I)"
+
+#: logsrvd/sendlog.c:133
+msgid "certificate bundle file to verify server's cert against"
+msgstr "datoteka snopa certifikata radi provjere certifikata servera"
+
+#: logsrvd/sendlog.c:135
+msgid "certificate file for TLS handshake"
+msgstr "datoteka certifikata za TLS rukovanje"
+
+#: logsrvd/sendlog.c:138
+msgid "host to send logs to"
+msgstr "host kojem se šalje dnevnik"
+
+#: logsrvd/sendlog.c:140
+msgid "remote ID of I/O log to be resumed"
+msgstr "udaljeni ID U/I dnevnika koji treba nastaviti"
+
+#: logsrvd/sendlog.c:143
+msgid "private key file"
+msgstr "datoteka privatnog ključa"
+
+#: logsrvd/sendlog.c:145
+msgid "do not verify server certificate"
+msgstr "ne provjerava certifikat servera"
+
+#: logsrvd/sendlog.c:148
+msgid "port to use when connecting to host"
+msgstr "koristi taj port za spajanje na hosta"
+
+#: logsrvd/sendlog.c:150
+msgid "restart previous I/O log transfer"
+msgstr "ponovno pokrene prethodni prijenos U/I dnevnika"
+
+#: logsrvd/sendlog.c:152
+msgid "reject the command with the given reason"
+msgstr "odbije naredbu s navedenim razlogom"
+
+#: logsrvd/sendlog.c:154
+msgid "stop transfer after reaching this time"
+msgstr "zaustavi prijenos nakon tog vremena"
+
+#: logsrvd/sendlog.c:156
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "testira revizijski server slanjem odabranih zapisa U/I dnevnika paralelno n puta"
+
+#: logsrvd/sendlog.c:181 plugins/sudoers/log_client.c:453
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "nije moguće potražiti %s:%s: %s"
+
+#: logsrvd/sendlog.c:219
+msgid "unable to get server IP addr"
+msgstr "nije moguće dobiti IP adresu servera"
+
+#: logsrvd/sendlog.c:314 plugins/sudoers/sudoreplay.c:868
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "nije moguće učitati %s/%s: %s"
+
+#: logsrvd/sendlog.c:1035 plugins/sudoers/iolog.c:959
+#: plugins/sudoers/iolog.c:1034
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "neočekivani U/I događaj %d"
+
+#: logsrvd/sendlog.c:1088 logsrvd/sendlog.c:1105 logsrvd/sendlog.c:1139
+#: plugins/sudoers/log_client.c:1129 plugins/sudoers/log_client.c:1405
+#: plugins/sudoers/log_client.c:1473 plugins/sudoers/log_client.c:1512
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: neočekivano stanje %d"
+
+#: logsrvd/sendlog.c:1175 plugins/sudoers/log_client.c:1561
+#, c-format
+msgid "error message received from server: %s"
+msgstr "primljena je poruka o greškama od servera: %s"
+
+#: logsrvd/sendlog.c:1188 plugins/sudoers/log_client.c:1574
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "primljena je poruka za prekid (abort) od servera: %s"
+
+#: logsrvd/sendlog.c:1247 plugins/sudoers/log_client.c:1624
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s: neočekivana ‘type_case’ vrijednost za %d"
+
+#: logsrvd/sendlog.c:1276
+msgid "timeout reading from server"
+msgstr "isteklo je vrijeme za čitanje iz servera"
+
+#: logsrvd/sendlog.c:1327 plugins/sudoers/log_client.c:1747
+msgid "host name does not match certificate"
+msgstr "ime hosta ne slaže se s certifikatom"
+
+#: logsrvd/sendlog.c:1361
+msgid "premature EOF"
+msgstr "preuranjeni EOF (kraj datoteke)"
+
+#: logsrvd/sendlog.c:1374 plugins/sudoers/log_client.c:1795
+#, c-format
+msgid "server message too large: %u"
+msgstr "poruka servera je prevelika: %u"
+
+#: logsrvd/sendlog.c:1430
+msgid "timeout writing to server"
+msgstr "isteklo je vrijeme za pisanje na server"
+
+#: logsrvd/sendlog.c:1800
+msgid "both restart point and iolog ID must be specified"
+msgstr "i točka za ponovno pokretanje i iolog ID moraju biti specificirani"
+
+#: logsrvd/sendlog.c:1804
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "ako se ne pošalje U/I (I/O), ponovno uspostavljanje možda neće uspjeti"
+
+#: logsrvd/sendlog.c:1880
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "preuranjeni završetak (izlaz) sa stanjem %d"
+
+#: logsrvd/sendlog.c:1881
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "proteklo vrijeme poslano je na server [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1883
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "potvrđena točka primljena je od servera [%lld, %ld]"
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:315
+msgid "TLS handshake timeout occurred"
+msgstr "Vrijeme za TLS rukovanje je isteklo"
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:337 plugins/sudoers/log_client.c:353
+msgid "unable to set event"
+msgstr "nije moguće uspostaviti događaj"
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "TLS spajanje nije uspjelo: %s"
+
+#: logsrvd/tls_client.c:196
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "nije uspjelo dodijeliti memoriju za SSL objekt: %s"
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "Nije uspjelo prikvačiti utičnicu na SSL objekt: %s"
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr "nije moguće inicijalizirati TLS konteks"
+
+#: logsrvd/tls_init.c:138 logsrvd/tls_init.c:146
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "nije moguće postaviti ciphersuite na %s: %s"
+
+#: logsrvd/tls_init.c:166 logsrvd/tls_init.c:174
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "nije moguće postaviti TLS 1.3 ciphersuite to %s: %s"
+
+#: logsrvd/tls_init.c:206 logsrvd/tls_init.c:227
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "nije moguće postaviti diffie-hellman parametre: %s"
+
+#: logsrvd/tls_init.c:283
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "nije moguće stvoriti TLS kontekst: %s"
+
+#: logsrvd/tls_init.c:290
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "nije mouguće uspostaviti minimalni protokol na TLS 1.2: %s"
+
+#: plugins/sudoers/audit.c:272 plugins/sudoers/audit.c:452
+#: plugins/sudoers/log_client.c:962 plugins/sudoers/log_client.c:1011
+#: plugins/sudoers/log_client.c:1060 plugins/sudoers/log_client.c:1185
+#: plugins/sudoers/logging.c:614 plugins/sudoers/logging.c:732
+#: plugins/sudoers/logging.c:859 plugins/sudoers/logging.c:1031
+#: plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr "nije moguće dobiti doba dana (trenutno vrijeme)"
+
+#: plugins/sudoers/auth/aix_auth.c:282
+#, c-format
+msgid "unable to change password for %s"
+msgstr "nije moguće promijeniti lozinku za %s"
+
+#: plugins/sudoers/auth/bsdauth.c:78
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "nije moguće dobiti razred klasu korisnika %s"
+
+#: plugins/sudoers/auth/bsdauth.c:85
+msgid "invalid authentication type"
+msgstr "nevaljani tip autentifikacije"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to begin BSD authentication"
+msgstr "nije moguće započeti BSD autentifikaciju"
+
+#: plugins/sudoers/auth/bsdauth.c:97
+msgid "unable to initialize BSD authentication"
+msgstr "nije moguće inicijalizirati BSD autentifikaciju"
+
+#: plugins/sudoers/auth/bsdauth.c:191
+msgid "your account has expired"
+msgstr "vaš račun nije valjan, istekao je"
+
+#: plugins/sudoers/auth/bsdauth.c:193
+msgid "approval failed"
+msgstr "odobrenje nije uspjelo"
+
+#: plugins/sudoers/auth/fwtk.c:62
+msgid "unable to read fwtk config"
+msgstr "nije moguće pročitati konfiguraciju FWTK"
+
+#: plugins/sudoers/auth/fwtk.c:67
+msgid "unable to connect to authentication server"
+msgstr "nije moguće spojiti se na server za autentifikaciju"
+
+#: plugins/sudoers/auth/fwtk.c:73 plugins/sudoers/auth/fwtk.c:99
+#: plugins/sudoers/auth/fwtk.c:131
+msgid "lost connection to authentication server"
+msgstr "veza sa serverom za autentifikaciju je prekinuta (izgubljena)"
+
+#: plugins/sudoers/auth/fwtk.c:77
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"greška na serveru za autentifikaciju:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:116
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: nije moguće pretvoriti principala u string (‘%s’): %s"
+
+#: plugins/sudoers/auth/kerb5.c:166
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: nije moguće raščlaniti ‘%s’: %s"
+
+#: plugins/sudoers/auth/kerb5.c:175
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: nije moguće naći verifikacijsku predmemoriju: %s"
+
+#: plugins/sudoers/auth/kerb5.c:226
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: nije moguće dodijeliti opcije: %s"
+
+#: plugins/sudoers/auth/kerb5.c:241
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: nije moguće dobiti verifikaciju: %s"
+
+#: plugins/sudoers/auth/kerb5.c:254
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: nije moguće inicijalizirati verifikacijsku predmemoriju: %s"
+
+#: plugins/sudoers/auth/kerb5.c:257
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: nije moguće spremiti verifikaciju u predmemoriju: %s"
+
+#: plugins/sudoers/auth/kerb5.c:322
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: nije moguće dobiti principala: %s"
+
+#: plugins/sudoers/auth/kerb5.c:336
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: Nije moguće provjeriti TGT! Mogući napad!: %s"
+
+#: plugins/sudoers/auth/pam.c:233
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "nije moguće inicijalizirati PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:349
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Greška PAM autentifikacije: %s"
+
+#: plugins/sudoers/auth/pam.c:369
+msgid "account validation failure, is your account locked?"
+msgstr "provjera valjanosti računa nije uspjela, je li vaš račun zaključan?"
+
+#: plugins/sudoers/auth/pam.c:380
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Račun ili lozinka su istekli, postavite novu lozinku i pokušajte ponovo."
+
+#: plugins/sudoers/auth/pam.c:387
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "nije moguće promijeniti zastarjelu lozinku: %s"
+
+#: plugins/sudoers/auth/pam.c:398
+msgid "Password expired, contact your system administrator"
+msgstr "Lozinka je istekla, javite se vašem administratoru sustava"
+
+#: plugins/sudoers/auth/pam.c:403
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Račun je istekao ili PAM konfiguracija nema sekciju ‘account’ za sudo, javite se vašem administratoru sustava"
+
+#: plugins/sudoers/auth/pam.c:411 plugins/sudoers/auth/pam.c:416
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "Pogreška u upravljanju PAM računom: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:100 plugins/sudoers/visudo.c:266
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "vas nema u %s bazi podataka"
+
+#: plugins/sudoers/auth/securid5.c:76
+msgid "failed to initialise the ACE API library"
+msgstr "nije uspjelo inicijalizirati ACE API biblioteku"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "unable to contact the SecurID server"
+msgstr "nije moguće uspostaviti vezu sa serverom za SecurID"
+
+#: plugins/sudoers/auth/securid5.c:117
+msgid "User ID locked for SecurID Authentication"
+msgstr "Korisnikov ID je zaključan za SecurID provjeru autentičnosti"
+
+#: plugins/sudoers/auth/securid5.c:121 plugins/sudoers/auth/securid5.c:174
+msgid "invalid username length for SecurID"
+msgstr "nevaljana duljina imena korisnika za SecurID"
+
+#: plugins/sudoers/auth/securid5.c:125 plugins/sudoers/auth/securid5.c:179
+msgid "invalid Authentication Handle for SecurID"
+msgstr "nevaljani autentifikacijski token za SecurID"
+
+#: plugins/sudoers/auth/securid5.c:129
+msgid "SecurID communication failed"
+msgstr "SecurID komunikacija nije uspjela"
+
+#: plugins/sudoers/auth/securid5.c:133 plugins/sudoers/auth/securid5.c:222
+msgid "unknown SecurID error"
+msgstr "nepoznata SecurID greška"
+
+#: plugins/sudoers/auth/securid5.c:169
+msgid "invalid passcode length for SecurID"
+msgstr "nevaljana duljina lozinke za SecurID"
+
+#: plugins/sudoers/auth/sia.c:72 plugins/sudoers/auth/sia.c:130
+msgid "unable to initialize SIA session"
+msgstr "nije moguće inicijalizirati SIA sesiju"
+
+#: plugins/sudoers/auth/sudo_auth.c:141
+msgid "invalid authentication methods"
+msgstr "nevaljane metode autentifikacije"
+
+#: plugins/sudoers/auth/sudo_auth.c:143
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Nevaljane metode autentifikacije su ugrađene u sudo! Ne smijete miješati samostalne i nesamostalne autentifikacije."
+
+#: plugins/sudoers/auth/sudo_auth.c:296 plugins/sudoers/auth/sudo_auth.c:359
+msgid "no authentication methods"
+msgstr "nema metoda autentifikacije"
+
+#: plugins/sudoers/auth/sudo_auth.c:298
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Metode autentifikacije nisu ugrađene u sudo! Ako želite isključiti autentifikaciju, koristite konfiguracijsku opciju --disable-authentication."
+
+#: plugins/sudoers/auth/sudo_auth.c:361
+msgid "Unable to initialize authentication methods."
+msgstr "Nije moguće inicijalizirati metode autentifikacije."
+
+#: plugins/sudoers/auth/sudo_auth.c:551
+msgid "Authentication methods:"
+msgstr "Metode autentifikacije:"
+
+#: plugins/sudoers/bsm_audit.c:122 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "Nije bilo moguće odrediti uvjete za reviziju"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:278
+msgid "unable to commit audit record"
+msgstr "revizijski izvještaj nije bilo moguće zapisati na disk"
+
+#: plugins/sudoers/check.c:63 plugins/sudoers/check.c:74
+#: plugins/sudoers/lookup.c:79 plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "nepoznati UID %u"
+
+#: plugins/sudoers/check.c:277
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "greška pri čitanju datoteke s prodikom: %s"
+
+#: plugins/sudoers/check.c:280
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "zanemari datoteku s prodikom %s: nije regularna datoteka"
+
+#: plugins/sudoers/check.c:293
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Vjerujemo da vam je administrator lokalnog sustava održao uobičajeno\n"
+"predavanje. To se obično svodi na sljedeće tri stvari:\n"
+"\n"
+" #1) Poštujte tuđu privatnost.\n"
+" #2) Mislite prije tipkanja.\n"
+" #3) S velikim moćima dolazi velika odgovornost.\n"
+"\n"
+
+#: plugins/sudoers/check.c:301
+msgid ""
+"For security reasons, the password you type will not be visible.\n"
+"\n"
+msgstr ""
+"Radi sigurnosti utipkana lozinka bit će nevidljiva.\n"
+"\n"
+
+#: plugins/sudoers/check_aliases.c:93
+#, c-format
+msgid "cycle in %s \"%s\""
+msgstr "ciklus u %s „%s“"
+
+#: plugins/sudoers/check_aliases.c:96
+#, c-format
+msgid "%s \"%s\" referenced but not defined"
+msgstr "Greška: %s „%s“ je referenciran ali nije definiran"
+
+#: plugins/sudoers/cvtsudoers.c:211
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "inkrement redoslijeda (order): %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:231
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "početni redoslijed (order): %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:242
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "ispuna redoslijeda (order): %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:252 plugins/sudoers/visudo.c:183
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s inačica gramatike %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:282 plugins/sudoers/testsudoers.c:162
+#, c-format
+msgid "unsupported input format %s"
+msgstr "nepodržani ulazni formata %s"
+
+#: plugins/sudoers/cvtsudoers.c:300
+#, c-format
+msgid "unsupported output format %s"
+msgstr "nepodržani izlazni format %s"
+
+#: plugins/sudoers/cvtsudoers.c:392
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: ulazna i izlazna datoteka moraju biti različite datoteke"
+
+#: plugins/sudoers/cvtsudoers.c:406 plugins/sudoers/sudoers.c:151
+#: plugins/sudoers/sudoers.c:209 plugins/sudoers/testsudoers.c:315
+#: plugins/sudoers/visudo.c:276 plugins/sudoers/visudo.c:666
+msgid "unable to initialize sudoers default values"
+msgstr "nije moguće inicijalizirati zadane vrijednosti sudoers"
+
+#: plugins/sudoers/cvtsudoers.c:533 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:612
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s: nepoznata ključna riječ %s"
+
+#: plugins/sudoers/cvtsudoers.c:658
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "nevaljani zadani tip: %s"
+
+#: plugins/sudoers/cvtsudoers.c:681
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "nevaljani tip za suzbijanje: %s"
+
+#: plugins/sudoers/cvtsudoers.c:722 plugins/sudoers/cvtsudoers.c:738
+#, c-format
+msgid "invalid filter: %s"
+msgstr "nevaljani filtar: %s"
+
+#: plugins/sudoers/cvtsudoers.c:783 plugins/sudoers/visudo.c:1000
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "nije uspjelo raščlaniti %s datoteku, nepoznata greška"
+
+#: plugins/sudoers/cvtsudoers.c:1508 plugins/sudoers/sudoreplay.c:1143
+#: plugins/sudoers/timestamp.c:353 plugins/sudoers/timestamp.c:356
+#, c-format
+msgid "unable to write to %s"
+msgstr "nije moguće pisati u %s"
+
+#: plugins/sudoers/cvtsudoers.c:1536
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s - pretvara formate sudoers datoteka\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1538
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Opcije:\n"
+" -b, --base=dn osnovni DN za sudo LDAP upite\n"
+" -c, --config=conf_file staza do konfiguracijske datoteke\n"
+" -d, --defaults=deftypes pretvori samo Defaults od specificiranih deftypes\n"
+" -e, --expand-aliases proširuje aliase prilikom pretvaranja\n"
+" -f, --output-format=format izlazni format je jedan od: JSON, LDIF ili sudoers\n"
+" -i, --input-format=format ulazni format jedan od: LDIF ili sudoers\n"
+" -I, --increment=num inkrement za num svaki sudoOrder\n"
+" -h, --help pokaže poruku s pomoći i završi\n"
+" -m, --match=filter pretvori samo stavke koje podudaraju filter\n"
+" -M, --match-local filter rabi passwd i group baze podataka\n"
+" -o, --output=output_file pretvoreni sudoers zapiše u output_file\n"
+" -O, --order-start=num prvi sudoOrder započinje od num\n"
+" -p, --prune-matches izreže nepodudarne korisnike, grupe i računala\n"
+" -P, --padding=num osnovna ispuna za sudoOrder inkrement\n"
+" -s, --suppress=sections izostavi izlaz od sections sekcija\n"
+" -V, --version informira o inačici ovog programa i završi"
+
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:245 plugins/sudoers/cvtsudoers_ldif.c:252
+#: plugins/sudoers/cvtsudoers_ldif.c:594 plugins/sudoers/env.c:340
+#: plugins/sudoers/env.c:347 plugins/sudoers/env.c:458
+#: plugins/sudoers/ldap.c:511 plugins/sudoers/ldap.c:629
+#: plugins/sudoers/ldap.c:1003 plugins/sudoers/ldap_conf.c:219
+#: plugins/sudoers/ldap_conf.c:310 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:93 plugins/sudoers/logging.c:479
+#: plugins/sudoers/policy.c:828 plugins/sudoers/policy.c:840
+#: plugins/sudoers/prompt.c:169 plugins/sudoers/serialize_list.c:62
+#: plugins/sudoers/serialize_list.c:71 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/sudoreplay.c:1340 plugins/sudoers/sudoreplay.c:1346
+#: plugins/sudoers/sudoreplay.c:1352 plugins/sudoers/testsudoers.c:306
+#: plugins/sudoers/toke_util.c:217 toke.l:995 toke.l:1277
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "**interna greška**, %s prekoračenje"
+
+#: plugins/sudoers/cvtsudoers_csv.c:454 plugins/sudoers/cvtsudoers_csv.c:468
+#: plugins/sudoers/cvtsudoers_json.c:661 plugins/sudoers/cvtsudoers_json.c:676
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:362
+#: plugins/sudoers/ldap.c:495
+msgid "unable to get GMT time"
+msgstr "nije moguće dobiti GMT vrijeme"
+
+#: plugins/sudoers/cvtsudoers_csv.c:459 plugins/sudoers/cvtsudoers_csv.c:473
+#: plugins/sudoers/cvtsudoers_json.c:666 plugins/sudoers/cvtsudoers_json.c:681
+#: plugins/sudoers/cvtsudoers_ldif.c:354 plugins/sudoers/cvtsudoers_ldif.c:367
+#: plugins/sudoers/ldap.c:503
+msgid "unable to format timestamp"
+msgstr "nije moguće oblikovati vremensku oznaku"
+
+#: plugins/sudoers/cvtsudoers_json.c:481 plugins/sudoers/cvtsudoers_json.c:516
+#: plugins/sudoers/cvtsudoers_json.c:732
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: nepoznata zadana stavka „%s“"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:663
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "previše sudoers grešaka, maksimum je %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:706
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "varijabla okoline SUDOERS_BASE nije postavljena i -b opcija nije specificirana."
+
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, c-format
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr "%s:%d:%d: pretvaramo hostov popis u ALL"
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr "nije moguće naći alias %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, c-format
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr "%s:%d:%d: preimenujemo aliasa %s u %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr "%s:%d:%d: uklanjamo duplikat aliasa %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr "%s:%d:%d: konfliktni Defaults unos „%s“ specifičan za hosta u %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, c-format
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr "%s:%d:%d: napravljen je Defaults „%s“ specifičan za opciju %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr "%s:%d:%d: nije moguće napraviti Defaults „%s“ specifično za hosta"
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr "%s:%d:%d: uklanjamo Defaults „%s“ nadvladan naknadnim unosima"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1088
+#, c-format
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr "%s:%d:%d: spajanje userspec (korisnikova specifikacija) s %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1182
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr "%s:%d:%d: uklanjamo korisničke specifikacije nadvladane naknadnim unosima"
+
+#: plugins/sudoers/def_data.c:56
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Ustroj syslog-a ako se syslog koristi za pisanje dnevnika: %s"
+
+#: plugins/sudoers/def_data.c:60
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Pri uspješnoj autentifikaciji korisnika rabi se syslog prioritet: %s"
+
+#: plugins/sudoers/def_data.c:64
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Pri neuspješnoj autentifikaciji korisnika rabi se syslog prioritet: %s"
+
+#: plugins/sudoers/def_data.c:68
+msgid "Put OTP prompt on its own line"
+msgstr "Postavite OTP (One-Time-Password) prompt u zasebni, vlastiti redak"
+
+#: plugins/sudoers/def_data.c:72
+msgid "Ignore '.' in $PATH"
+msgstr "Zanemari ‘.’ u $PATH"
+
+#: plugins/sudoers/def_data.c:76
+msgid "Always send mail when sudo is run"
+msgstr "Poštu poslati kad god se pokrene sudo"
+
+#: plugins/sudoers/def_data.c:80
+msgid "Send mail if user authentication fails"
+msgstr "Poštu poslati ako autentifikacija korisnika nije uspjela"
+
+#: plugins/sudoers/def_data.c:84
+msgid "Send mail if the user is not in sudoers"
+msgstr "Poštu poslati ako korisnik nije u sudoers"
+
+#: plugins/sudoers/def_data.c:88
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Poštu poslati ako korisnik nije u sudoers na ovom računalu"
+
+#: plugins/sudoers/def_data.c:92
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Poštu poslati ako korisnik nema dopuštenje za pokretanje naredbe"
+
+#: plugins/sudoers/def_data.c:96
+msgid "Send mail if the user tries to run a command"
+msgstr "Poštu poslati ako korisnik pokušava unositi naredbe"
+
+#: plugins/sudoers/def_data.c:100
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Za svaku kombinaciju korisnik/terminal koristi se zasebna vremenska oznaka"
+
+#: plugins/sudoers/def_data.c:104
+msgid "Lecture user the first time they run sudo"
+msgstr "Korisnika podučiti prilikom prvog pokretanja sudo"
+
+#: plugins/sudoers/def_data.c:108
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Datoteka koja sadrži sudo poduku: %s"
+
+#: plugins/sudoers/def_data.c:112
+msgid "Require users to authenticate by default"
+msgstr "Zadano (by default),zahtijeva se autentifikacija korisnika"
+
+#: plugins/sudoers/def_data.c:116
+msgid "Root may run sudo"
+msgstr "Root smije pokrenuti sudo"
+
+#: plugins/sudoers/def_data.c:120
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Ime računala zapiše se u (ne-syslog) dnevničku datoteku"
+
+#: plugins/sudoers/def_data.c:124
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Godina se zapiše u (ne-syslog) dnevničku datoteku"
+
+#: plugins/sudoers/def_data.c:128
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Ako se sudo pozove bez argumenata, pokrene se ljuska"
+
+#: plugins/sudoers/def_data.c:132
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Postavlja $HOME na ciljanog korisnika pri pokretanju ljuske s opcijom -s"
+
+#: plugins/sudoers/def_data.c:136
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Uvijek postavlja $HOME na osobni direktorij ciljanog korisnika"
+
+#: plugins/sudoers/def_data.c:140
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Dopušteno je prikupljanje informacija za ispis korisnih poruka o greškama"
+
+#: plugins/sudoers/def_data.c:144
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Datoteka sudoers zahtjeva potpuno kvalificirana (fully-qualified) imena računala"
+
+#: plugins/sudoers/def_data.c:148
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Korisnika izgrditi ako upiše netočnu lozinku"
+
+#: plugins/sudoers/def_data.c:152
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Korisniku dopustiti pokretanje sudo samo ako ima tty"
+
+#: plugins/sudoers/def_data.c:156
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo poštuje varijablu okoline EDITOR"
+
+#: plugins/sudoers/def_data.c:160
+msgid "Prompt for root's password, not the users's"
+msgstr "Zatražiti root lozinku umjesto lozinke korisnika"
+
+#: plugins/sudoers/def_data.c:164
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Zatražiti lozinku runas_default korisnika a ne lozinku trenutnog korisnika"
+
+#: plugins/sudoers/def_data.c:168
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Zatražiti lozinku ciljanog korisnika a ne lozinku trenutnog korisnika"
+
+#: plugins/sudoers/def_data.c:172
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Ako postoje, primijeniti zadane vrijednosti iz login klase ciljanog korisnika"
+
+#: plugins/sudoers/def_data.c:176
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Postavlja varijable okoline LOGNAME i USER"
+
+#: plugins/sudoers/def_data.c:180
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Postavlja samo efektivni UID na onaj ciljanog korisnika umjesto stvarnog UID"
+
+#: plugins/sudoers/def_data.c:184
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Ne inicijalizirati grupni vektor na onaj od ciljanog korisnika"
+
+#: plugins/sudoers/def_data.c:188
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Pozicija na kojoj se prelamaju redci dnevničke datoteke (0, bez prelamanja): %u"
+
+#: plugins/sudoers/def_data.c:192
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Tajmaut vremenske oznake autentifikacije: %.1f minuta"
+
+#: plugins/sudoers/def_data.c:196
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Tajmaut za unos lozinke: %.1f minuta"
+
+#: plugins/sudoers/def_data.c:200
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Broj pokušaja unosa lozinke: %u"
+
+#: plugins/sudoers/def_data.c:204
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Umask za korištenje ili 0777 za korisničku: 0%o"
+
+#: plugins/sudoers/def_data.c:208
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Staza do dnevničke datoteke: %s"
+
+#: plugins/sudoers/def_data.c:212
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Staza do programa pošte: %s"
+
+#: plugins/sudoers/def_data.c:216
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Zastavice za program pošte: %s"
+
+#: plugins/sudoers/def_data.c:220
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Adresa na koju se šalje pošta: %s"
+
+#: plugins/sudoers/def_data.c:224
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Adresa s koje se šalje pošta: %s"
+
+#: plugins/sudoers/def_data.c:228
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Redak za upis predmeta (subject) poštanskih poruka: %s"
+
+#: plugins/sudoers/def_data.c:232
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Poruka za netočnu lozinku: %s"
+
+#: plugins/sudoers/def_data.c:236
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Staza do direktorija s lekcijom: %s"
+
+#: plugins/sudoers/def_data.c:240
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Staza do direktorija s vremenskim oznakama autentifikacije: %s"
+
+#: plugins/sudoers/def_data.c:244
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Vlasnik direktorija s vremenskim oznakama autentifikacije: %s"
+
+#: plugins/sudoers/def_data.c:248
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Korisnici u ovoj grupi su izuzeti od zahtjeva za unos lozinke i PATH: %s"
+
+#: plugins/sudoers/def_data.c:252
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Zadani zahtjev (prompt) za lozinku: %s"
+
+#: plugins/sudoers/def_data.c:256
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Ako je postavljen, passprompt će redefinirati prompt sustava u svim slučajevima."
+
+#: plugins/sudoers/def_data.c:260
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Zadani korisnik za pokretanje naredbi: %s"
+
+#: plugins/sudoers/def_data.c:264
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Vrijednost s kojom se zamijeni korisnikov $PATH: %s"
+
+#: plugins/sudoers/def_data.c:268
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Staza do uređivača koji će koristiti visudo: %s"
+
+#: plugins/sudoers/def_data.c:272
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Kada zatražiti lozinku za pseudonaredbu „list“: %s"
+
+#: plugins/sudoers/def_data.c:276
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Kada zatražiti lozinku za pseudonaredbu „verify“: %s"
+
+#: plugins/sudoers/def_data.c:280
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "Unaprijed učitajte biblioteku sudo_noexec koja zamjenjuje exec funkcije"
+
+#: plugins/sudoers/def_data.c:284
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Ako je dostupni LDAP direktorij, zanemaruje li se lokalna sudoers datoteka"
+
+#: plugins/sudoers/def_data.c:288
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Deskriptori datoteka >= %d bit će zatvoreni prije izvršavanja naredbe"
+
+#: plugins/sudoers/def_data.c:292
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "Ako je dana, korisnici mogu s opcijom -C redefinirati vrijednost od „closefrom“"
+
+#: plugins/sudoers/def_data.c:296
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Korisnici mogu postaviti bilo koje varijable okoline"
+
+#: plugins/sudoers/def_data.c:300
+msgid "Reset the environment to a default set of variables"
+msgstr "Okolinu vratiti u zadani skup varijabli okoline"
+
+#: plugins/sudoers/def_data.c:304
+msgid "Environment variables to check for safety:"
+msgstr "Varijable okruženja čiju sigurnost treba provjeriti:"
+
+#: plugins/sudoers/def_data.c:308
+msgid "Environment variables to remove:"
+msgstr "Varijable okoline koje treba ukloniti:"
+
+#: plugins/sudoers/def_data.c:312
+msgid "Environment variables to preserve:"
+msgstr "Varijable okoline koje treba zadržati:"
+
+#: plugins/sudoers/def_data.c:316
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "SELinux uloga za korištenje u novom sigurnosnom kontekstu: %s"
+
+#: plugins/sudoers/def_data.c:320
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "SELinux tip za korištenje u novom sigurnosnom kontekstu: %s"
+
+#: plugins/sudoers/def_data.c:324
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Staza do datoteke okoline specifične za sudo: %s"
+
+#: plugins/sudoers/def_data.c:328
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Staza do datoteke okoline s ograničenim pristupom specifične za sudo: %s"
+
+#: plugins/sudoers/def_data.c:332
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Locale za korištenje pri obradi sudoers: %s"
+
+#: plugins/sudoers/def_data.c:336
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Dopustiti da sudo zatraži lozinku čak i ako će biti vidljiva"
+
+#: plugins/sudoers/def_data.c:340
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Vizualno pokazati rezultat nakon unosa lozinke korisnikom"
+
+#: plugins/sudoers/def_data.c:344
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Rabi se brže i manje precizno podudaranje ali nema dostupa datotečnom sustavu"
+
+#: plugins/sudoers/def_data.c:348
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "umask, specificiran u sudoers redefinira korisnički, čak i ako je tolerantniji"
+
+#: plugins/sudoers/def_data.c:352
+msgid "Log user's input for the command being run"
+msgstr "Urudžbira unos korisnika za trenutno pokrenutu naredbu"
+
+#: plugins/sudoers/def_data.c:356
+msgid "Log the command's standard input if not connected to a terminal"
+msgstr "Urudžbíra izvor standardnog unosa naredbe ako naredba nije spojena na terminal"
+
+#: plugins/sudoers/def_data.c:360
+msgid "Log the user's terminal input for the command being run"
+msgstr "Urudžbira korisnikov unos u terminal za trenutno pokrenutu naredbu"
+
+#: plugins/sudoers/def_data.c:364
+msgid "Log the output of the command being run"
+msgstr "Urudžbirati izlaz pokrenute naredbe"
+
+#: plugins/sudoers/def_data.c:368
+msgid "Log the command's standard output if not connected to a terminal"
+msgstr "Urudžbira standardni izlaz naredbe ako nije naredba nije spojena na terminal"
+
+#: plugins/sudoers/def_data.c:372
+msgid "Log the command's standard error if not connected to a terminal"
+msgstr "Urudžbira standardne greške naredbe ako naredba nije spojena na terminal"
+
+#: plugins/sudoers/def_data.c:376
+msgid "Log the terminal output of the command being run"
+msgstr "Urudžbira izlaz koje trenutna naredba ispisuje na terminal"
+
+#: plugins/sudoers/def_data.c:380
+msgid "Compress I/O logs using zlib"
+msgstr "U/I urudžbirane dnevnike komprimirati s programom zlib"
+
+#: plugins/sudoers/def_data.c:384
+msgid "Always run commands in a pseudo-tty"
+msgstr "Naredbe uvijek pokrenuti u pseudo-TTY"
+
+#: plugins/sudoers/def_data.c:388
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Plugin za podršku za ne-Unix grupe: %s"
+
+#: plugins/sudoers/def_data.c:392
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Direktorij u kojem se spremaju ulazno/izlazni dnevnici: %s"
+
+#: plugins/sudoers/def_data.c:396
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Datoteka u koju se sprema ulazno/izlazni dnevnik: %s"
+
+#: plugins/sudoers/def_data.c:400
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Dodati stavku u utmp/utmpx datoteku pri dodijeli pseudoterminala"
+
+#: plugins/sudoers/def_data.c:404
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Postaviti korisnika u utmp na runas-korisnika umjesto na pozivatelja"
+
+#: plugins/sudoers/def_data.c:408
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Skup dopuštenih privilegija: %s"
+
+#: plugins/sudoers/def_data.c:412
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Skup limitiranih privilegija: %s"
+
+#: plugins/sudoers/def_data.c:416
+msgid "Run commands on a pty in the background"
+msgstr "Pokrenuti naredbe na pseudo terminalu u pozadini"
+
+#: plugins/sudoers/def_data.c:420
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "Naziv PAM usluge za upotrebu: %s"
+
+#: plugins/sudoers/def_data.c:424
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "Naziv PAM usluge za upotrebu za prijavnu ljusku: %s"
+
+#: plugins/sudoers/def_data.c:428
+#, c-format
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr "Naziv PAM usluge koja se koristi kad je sudo pozvan s opcijom -A: %s"
+
+#: plugins/sudoers/def_data.c:432
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Pokušaj da se uspostavi PAM verifikacija za ciljanog korisnika"
+
+#: plugins/sudoers/def_data.c:436
+msgid "Create a new PAM session for the command to run in"
+msgstr "Kreira novu PAM sesiju za izvršavanje naredbe"
+
+#: plugins/sudoers/def_data.c:440
+msgid "Perform PAM account validation management"
+msgstr "Provjeri upravljanje s PAM računom"
+
+#: plugins/sudoers/def_data.c:444
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "Najveći broj redoslijeda dnevnika U/I: %s"
+
+#: plugins/sudoers/def_data.c:448
+msgid "Enable sudoers netgroup support"
+msgstr "Omogućite podršku mrežnih grupa (netgroup) u sudoers"
+
+#: plugins/sudoers/def_data.c:452
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Provjerite mogućnost pisanja u naddirektorijima kad se koristi sudoedit za uređivanje"
+
+#: plugins/sudoers/def_data.c:456
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Slijedi simboličke poveznice kad se koristi sudoedit za uređivanje datoteka"
+
+#: plugins/sudoers/def_data.c:460
+msgid "Query the group plugin for unknown system groups"
+msgstr "Ispituje plugin grupe za nepoznate sustavske grupe"
+
+#: plugins/sudoers/def_data.c:464
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Podudaranje mrežnih grupa bazira se na kompletnoj n-torki: korisnik, računalo, domena"
+
+#: plugins/sudoers/def_data.c:468
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Naredbe je dopušteno izvršiti iako ih sudo ne može upisati u revizijski dnevnik"
+
+#: plugins/sudoers/def_data.c:472
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Naredbe je dopušteno izvršiti iako ih sudo ne može upisati u U/I dnevnik"
+
+#: plugins/sudoers/def_data.c:476
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Naredbe je dopušteno izvršiti iako ih sudo ne može upisati u dnevnik"
+
+#: plugins/sudoers/def_data.c:480
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Razriješi grupe u sudoers i podudari ih po ID grupe umjesto po imenu grupe"
+
+#: plugins/sudoers/def_data.c:484
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Dnevničke stavke veće od ove vrijednosti podijeliti će se u više syslog poruka: %u"
+
+#: plugins/sudoers/def_data.c:488
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Korisnik koji će biti vlasnik U/I dnevnika: %s"
+
+#: plugins/sudoers/def_data.c:492
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Grupa koja će biti vlasnik U/I dnevnika: %s"
+
+#: plugins/sudoers/def_data.c:496
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Prava pristupa za uporabu za U/I dnevnike: 0%o"
+
+#: plugins/sudoers/def_data.c:500
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Izvrši naredbe pomoću deskriptora datoteke umjesto staze: %s"
+
+#: plugins/sudoers/def_data.c:504
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Nepoznati zadani podaci za sudoers se ignoriraju umjesto ispisa upozorenja"
+
+#: plugins/sudoers/def_data.c:508
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Vrijeme u sekundama nakon kojeg se naredba prekida: %u"
+
+#: plugins/sudoers/def_data.c:512
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Dopustite korisniku da specificira tajmaut na komandnom retku"
+
+#: plugins/sudoers/def_data.c:516
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "U/I dnevnik ispisivati direktno na disk umjesto preko međuspremnika"
+
+#: plugins/sudoers/def_data.c:520
+msgid "Include the process ID when logging via syslog"
+msgstr "U syslog dnevnik upisivati i ID procesa"
+
+#: plugins/sudoers/def_data.c:524
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Tip zapisa autentifikacijskih vremenskih oznaka: %s"
+
+#: plugins/sudoers/def_data.c:528
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Greška u provjeri autentičnosti: %s"
+
+#: plugins/sudoers/def_data.c:532
+msgid "Ignore case when matching user names"
+msgstr "Zanemari veličinu slova kad se uspoređuju imena korisnika"
+
+#: plugins/sudoers/def_data.c:536
+msgid "Ignore case when matching group names"
+msgstr "Zanemari velika/mala slova pri usporedbi imena grupa"
+
+#: plugins/sudoers/def_data.c:540
+msgid "Log when a command is allowed by sudoers"
+msgstr "Dnevniči (upiše u dnevnik) onda kad sudoers dopusti naredbu"
+
+#: plugins/sudoers/def_data.c:544
+msgid "Log when a command is denied by sudoers"
+msgstr "Dnevniči (upiše u dnevnik) onda kad sudoers ne dopusti naredbu"
+
+#: plugins/sudoers/def_data.c:548
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "Server(i) sudo dnevnika za spajanje na opcionalni port"
+
+#: plugins/sudoers/def_data.c:552
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Tajmaut servera sudo dnevnika u sekundama: %u"
+
+#: plugins/sudoers/def_data.c:556
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "Omogućite opciju utičnice SO_KEEPALIVE na utičnici spojenoj na server dnevnika"
+
+#: plugins/sudoers/def_data.c:560
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "Staza do datoteke s paketom certifikata (CA) revizijskog servera: %s"
+
+#: plugins/sudoers/def_data.c:564
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "Staza do datoteke sa sudoers certifikatima: %s"
+
+#: plugins/sudoers/def_data.c:568
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "Staza do datoteke sa sudoers privatnim (tajnim) ključem: %s"
+
+#: plugins/sudoers/def_data.c:572
+msgid "Verify that the log server's certificate is valid"
+msgstr "Provjerite je li certifikat dnevničkog servera valjan"
+
+#: plugins/sudoers/def_data.c:576
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "Dopustite nepoznate vrijednosti za korisničko ime i/ili ID grupe za ‘runas’"
+
+#: plugins/sudoers/def_data.c:580
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "Dopustite izvršavanje naredbi samo korisniku s valjanom ljuskom"
+
+#: plugins/sudoers/def_data.c:584
+msgid "Set the pam remote user to the user running sudo"
+msgstr "Postavite udaljenog korisnika PAM-a na korisnika koji izvršava sudo"
+
+#: plugins/sudoers/def_data.c:588
+msgid "Set the pam remote host to the local host name"
+msgstr "Postavite PAM udaljenog hosta pam na ime lokalnog hosta (računala)"
+
+#: plugins/sudoers/def_data.c:592
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "Radni direktorij u koji treba otići prije izvršavanja naredbe: %s"
+
+#: plugins/sudoers/def_data.c:596
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "Root direktorij u koji treba otići prije izvršavanja naredbe: %s"
+
+#: plugins/sudoers/def_data.c:600
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "Format dnevnika: %s"
+
+#: plugins/sudoers/def_data.c:604
+msgid "Enable SELinux RBAC support"
+msgstr "Omogući podršku za SELinux RBAC"
+
+#: plugins/sudoers/def_data.c:608
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "Staza do datoteke koja se kreira prilikom prvog sudo pokretanja: %s"
+
+#: plugins/sudoers/def_data.c:612
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "Presretne daljnje naredbe i primijeni ograničenja sudoers-a na njih"
+
+#: plugins/sudoers/def_data.c:616
+msgid "Log sub-commands run by the original command"
+msgstr "Urudžbira podnaredbe koje izvodi naredba"
+
+#: plugins/sudoers/def_data.c:620
+msgid "Log the exit status of commands"
+msgstr "Urudžbira izlazno stanje pokrenute naredbe"
+
+#: plugins/sudoers/def_data.c:624
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr "Naredne naredbe u presretoj sesiji moraju biti ovjerene"
+
+#: plugins/sudoers/def_data.c:628
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr "Dopusti presretnutu naredbu da pokrene program za postavljnje setuid ili setgid"
+
+#: plugins/sudoers/def_data.c:632
+#, c-format
+msgid "The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr "Maksimalna veličina do koje adresni prostor procesa može narasti (u bajtovima): %s"
+
+#: plugins/sudoers/def_data.c:636
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr "Najveća veličina datoteke s damp memorijom koja se može stvoriti (u bajtovima): %s"
+
+#: plugins/sudoers/def_data.c:640
+#, c-format
+msgid "The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr "Maksimalna količina CPU vremena koje proces može koristiti (u sekundama): %s"
+
+#: plugins/sudoers/def_data.c:644
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr "Maksimalna veličina podatkovnog segmenta za proces (u bajtovima): %s"
+
+#: plugins/sudoers/def_data.c:648
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr "Najveća veličina datoteke koju proces može stvoriti (u bajtovima): %s"
+
+#: plugins/sudoers/def_data.c:652
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr "Maksimalni broj zaključavanja koje proces može uspostaviti: %s"
+
+#: plugins/sudoers/def_data.c:656
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr "Maksimalna veličina koju proces može zaključati u memoriji (u bajtovima): %s"
+
+#: plugins/sudoers/def_data.c:660
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr "Maksimalan broj datoteka koje proces može otvoriti: %s"
+
+#: plugins/sudoers/def_data.c:664
+#, c-format
+msgid "The maximum number of processes that the user may run simultaneously: %s"
+msgstr "Maksimalan broj procesa koje korisnik može istovremeno pokrenuti: %s"
+
+#: plugins/sudoers/def_data.c:668
+#, c-format
+msgid "The maximum size to which the process's resident set size may grow (in bytes): %s"
+msgstr "Maksimalna veličina do koje može narasti rezidentna postavljena veličina procesa (u bajtovima): %s"
+
+#: plugins/sudoers/def_data.c:672
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr "Maksimalna veličina do koje može narasti stȏg procesa (u bajtovima): %s"
+
+#: plugins/sudoers/def_data.c:676
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr "Pokušaj provjere autentičnosti iako se radi u neinteraktivnom načinu"
+
+#: plugins/sudoers/def_data.c:680
+msgid "Store plaintext passwords in I/O log input"
+msgstr "Sprema lozinke u čistom tekstu u U/I zapisniku ulaza"
+
+#: plugins/sudoers/def_data.c:684
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr "Popis regularnih izraza koji se koriste za podudaranje s lozinkama"
+
+#: plugins/sudoers/def_data.c:688
+#, c-format
+msgid "The mechanism used by the intercept and log_subcmds options: %s"
+msgstr "Mehanizam koji koriste opcije presretanja i log_subcmds: %s"
+
+#: plugins/sudoers/def_data.c:692
+msgid "Attempt to verify the command and arguments after execution"
+msgstr "Pokušaj provjere naredbe i argumente nakon izvršenja"
+
+#: plugins/sudoers/def_data.c:696
+#, c-format
+msgid "AppArmor profile to use in the new security context: %s"
+msgstr "AppArmor profil za upotrebu u novom sigurnosnom kontekstu: %s"
+
+#: plugins/sudoers/defaults.c:207
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "nepoznati unos defaults „%s“"
+
+#: plugins/sudoers/defaults.c:251
+#, c-format
+msgid "no value specified for \"%s\""
+msgstr "nije navedena vrijednost za „%s“"
+
+#: plugins/sudoers/defaults.c:260
+#, c-format
+msgid "invalid operator \"%c=\" for \"%s\""
+msgstr "nevaljan operator „%c=“ za „%s“"
+
+#: plugins/sudoers/defaults.c:292
+#, c-format
+msgid "option \"%s\" does not take a value"
+msgstr "opcija „%s“ ne prihvaća vrijednost"
+
+#: plugins/sudoers/defaults.c:319
+#, c-format
+msgid "invalid Defaults type 0x%x for option \"%s\""
+msgstr "nevaljani Defaults tip 0x%x za opciju „%s“"
+
+#: plugins/sudoers/defaults.c:326
+#, c-format
+msgid "value \"%s\" is invalid for option \"%s\""
+msgstr "vrijednost „%s“ nije ispravna za opciju „%s“"
+
+#: plugins/sudoers/defaults.c:1176 plugins/sudoers/policy.c:213
+#: plugins/sudoers/policy.c:222
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr "ime staze za „%s“ je predugo"
+
+#: plugins/sudoers/defaults.c:1182
+#, c-format
+msgid "values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "vrijednost za „%s“ mora započeti s „/“, „~“, ili „*“"
+
+#: plugins/sudoers/defaults.c:1189
+#, c-format
+msgid "values for \"%s\" must start with a '/'"
+msgstr "vrijednost za „%s“ mora početi s „/“"
+
+#: plugins/sudoers/display.c:160
+#, c-format
+msgid "LDAP Role: %s\n"
+msgstr "LDAP Role: %s\n"
+
+#: plugins/sudoers/display.c:163
+#, c-format
+msgid "Sudoers entry: %s\n"
+msgstr "Sudoers stavka: %s\n"
+
+#: plugins/sudoers/display.c:166
+msgid " RunAsUsers: "
+msgstr " RunAsUsers: "
+
+#: plugins/sudoers/display.c:181
+msgid " RunAsGroups: "
+msgstr " RunAsGroups: "
+
+#: plugins/sudoers/display.c:191
+msgid " Options: "
+msgstr " Opcije: "
+
+#: plugins/sudoers/display.c:255
+msgid " Commands:\n"
+msgstr " Naredbe:\n"
+
+#: plugins/sudoers/display.c:478
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Odgovarajući Defaults unosi za %s na %s:\n"
+
+#: plugins/sudoers/display.c:496
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Runas i Command-specifične zadane vrijednosti za %s:\n"
+
+#: plugins/sudoers/display.c:514
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "Korisnik %s može pokrenuti sljedeće naredbe na %s:\n"
+
+#: plugins/sudoers/display.c:530
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Korisniku %s nije dopušteno pokrenuti sudo na %s.\n"
+
+#: plugins/sudoers/editor.c:180
+#, c-format
+msgid "ignoring editor: %.*s"
+msgstr "ignoriramo editor: %.*s"
+
+#: plugins/sudoers/editor.c:181
+msgid "editor arguments may not contain \"--\""
+msgstr "argumenti editora ne smiju sadržavati „--“"
+
+#: plugins/sudoers/env.c:426
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: oštećen envp, duljina ne odgovara"
+
+#: plugins/sudoers/env.c:1119
+msgid "unable to rebuild the environment"
+msgstr "nije moguće obnoviti okolinu"
+
+#: plugins/sudoers/env.c:1199
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "nemate dopuštenje za postavljanje sljedećih varijabli okoline: %s"
+
+#: plugins/sudoers/filedigest.c:50
+#, c-format
+msgid "unsupported digest type %u for %s"
+msgstr "nepodržani tip kontrolnog zbroja %u za %s"
+
+#: plugins/sudoers/filedigest.c:77
+#, c-format
+msgid "%s: read error"
+msgstr "%s: greška pri čitanju"
+
+#: plugins/sudoers/group_plugin.c:169 plugins/sudoers/sssd.c:578
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "nije moguće učitati %s: %s"
+
+#: plugins/sudoers/group_plugin.c:181
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "nije moguće pronaći simbol „group_plugin“ u %s"
+
+#: plugins/sudoers/group_plugin.c:186
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: nekompatibilna glavna inačica plugin grupe %d, očekivano je %d"
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "„%s“ nije valjana IP adresa (nemoguće ju je raščlaniti)"
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "„%s“ nije valjana mrežna maska (nemoguće ju je raščlaniti)"
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Parovi lokalnih IP adresa i mrežnih maski:\n"
+
+#: plugins/sudoers/iolog.c:694
+msgid "unable to update sequence file"
+msgstr "nije moguće ažurirati datoteku redoslijeda (sequence file)"
+
+#: plugins/sudoers/iolog.c:728 plugins/sudoers/iolog.c:917
+#: plugins/sudoers/iolog.c:1080 plugins/sudoers/iolog.c:1087
+#: plugins/sudoers/iolog.c:1209 plugins/sudoers/iolog.c:1216
+#: plugins/sudoers/iolog.c:1316 plugins/sudoers/iolog.c:1323
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "nije moguće pisati u U/I dnevnik: %s"
+
+#: plugins/sudoers/iolog.c:736
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "nije moguće stvoriti %s/%s"
+
+#: plugins/sudoers/iolog.c:965
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: interna greška, U/I dnevnička datoteka za događaj %d nije otvorena"
+
+#: plugins/sudoers/iolog.c:1065 plugins/sudoers/iolog.c:1194
+#: plugins/sudoers/iolog.c:1300 plugins/sudoers/timestamp.c:897
+#: plugins/sudoers/timestamp.c:989 plugins/sudoers/visudo.c:555
+#: plugins/sudoers/visudo.c:561
+msgid "unable to read the clock"
+msgstr "nije moguće pročitati vrijeme (clock)"
+
+#: plugins/sudoers/iolog.c:1292 plugins/sudoers/log_client.c:1203
+#: plugins/sudoers/log_client.c:1213 plugins/sudoers/log_client.c:1217
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: interna greška, nevaljani signal %d"
+
+#: plugins/sudoers/ldap.c:154 plugins/sudoers/ldap_conf.c:289
+msgid "starttls not supported when using ldaps"
+msgstr "starttls nije podržan kad se koristi ldaps"
+
+#: plugins/sudoers/ldap.c:226
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "nije moguće inicijalizirati SSL certifikat i bazu podataka ključeva: %s"
+
+#: plugins/sudoers/ldap.c:229
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "morate postaviti TLS_CERT u %s da koristite SSL"
+
+#: plugins/sudoers/ldap.c:1593
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "nije moguće inicijalizirati LDAP: %s"
+
+#: plugins/sudoers/ldap.c:1630
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls je specificirani, ali LDAP biblioteke ne podržavaju ldap_start_tls_s() ili ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:1767 plugins/sudoers/parse_ldif.c:745
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "nevaljani sudoOrder atribut: %s"
+
+#: plugins/sudoers/ldap_conf.c:197
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: preveliki port"
+
+#: plugins/sudoers/ldap_conf.c:258
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "nepodržani tip adrese LDAP: %s"
+
+#: plugins/sudoers/ldap_conf.c:285
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "ne možete zajedno koristiti ldap i ldaps adrese"
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "duplicira sudoOption: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "nije moguće pretvoriti sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "nije moguće otvoriti revizijski sustav"
+
+#: plugins/sudoers/linux_audit.c:104
+msgid "unable to send audit message"
+msgstr "nije moguće poslati revizijsku poruku"
+
+#: plugins/sudoers/log_client.c:125 plugins/sudoers/log_client.c:412
+#: plugins/sudoers/log_client.c:1450 plugins/sudoers/log_client.c:2076
+msgid "error in event loop"
+msgstr "greška u petlji događaja"
+
+#: plugins/sudoers/log_client.c:205
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "Nije uspjelo stvoriti novi ‘SSL_CTX’ objekt: %s"
+
+#: plugins/sudoers/log_client.c:230
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "nije moguće učitati datoteku s certifikatatima (CA bundle) %s"
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "nije moguće učitati certifikate %s"
+
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "unable to load private key %s"
+msgstr "nije moguće učitati privatni ključ %s"
+
+#: plugins/sudoers/log_client.c:275
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "Nije uspjelo dodijeliti memoriju za SSL objekt: %s"
+
+#: plugins/sudoers/log_client.c:364 plugins/sudoers/log_client.c:369
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "TLS veza sa %s:%s nije uspjela: %s"
+
+#: plugins/sudoers/log_client.c:545
+msgid "TLS initialization was unsuccessful"
+msgstr "TLS inicijalizacija nije bila uspješna"
+
+#: plugins/sudoers/log_client.c:555
+msgid "TLS handshake was unsuccessful"
+msgstr "TLS rukovanje (handshake) nije bila uspješno"
+
+#: plugins/sudoers/log_client.c:1221
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: **interna greška** -- nevaljani izlazni status %d"
+
+#: plugins/sudoers/log_client.c:1757 plugins/sudoers/log_client.c:1782
+msgid "lost connection to log server"
+msgstr "veza sa serverom za autentifikaciju je prekinuta (izgubljena je)"
+
+#: plugins/sudoers/log_client.c:1859
+msgid "missing write buffer"
+msgstr "nema međuspremnika za pisanje"
+
+#: plugins/sudoers/log_client.c:2015
+msgid "unable to connect to log server"
+msgstr "nije moguće spojiti se na dnevnički server"
+
+#: plugins/sudoers/logging.c:295
+msgid "user NOT in sudoers"
+msgstr "korisnik NIJE u sudoers"
+
+# Authentication is about who somebody is.
+# Authorisation is about what they're allowed to do.
+# https://en.wikipedia.org/wiki/AAA_(computer_security)#Authorization
+#: plugins/sudoers/logging.c:297
+msgid "user NOT authorized on host"
+msgstr "korisnik NEMA ovlasti na računalu (nije autoriziran)"
+
+#: plugins/sudoers/logging.c:299
+msgid "command not allowed"
+msgstr "naredba nije dopuštena"
+
+#: plugins/sudoers/logging.c:320
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr "%s nije u sudoers datoteci\n"
+
+#: plugins/sudoers/logging.c:323
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr "%s nije dopušteno pokrenuti sudo na %s.\n"
+
+#: plugins/sudoers/logging.c:326
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Nažalost, korisnik %s ne smije pokrenuti sudo na %s.\n"
+
+#: plugins/sudoers/logging.c:339
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s%s' as %s%s%s on %s.\n"
+msgstr "Korisniku %s nije dopušteno izvršiti ‘%s%s%s%s’ kao %s%s%s na %s.\n"
+
+#: plugins/sudoers/logging.c:350
+msgid "This incident has been reported to the administrator.\n"
+msgstr "Ovaj incident bit će prijavljen administratoru.\n"
+
+#: plugins/sudoers/logging.c:387 plugins/sudoers/sudoers.c:547
+#: plugins/sudoers/sudoers.c:549 plugins/sudoers/sudoers.c:551
+#: plugins/sudoers/sudoers.c:553 plugins/sudoers/sudoers.c:777
+#: plugins/sudoers/sudoers.c:779
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: naredba nije pronađena"
+
+#: plugins/sudoers/logging.c:389 plugins/sudoers/sudoers.c:543
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"zanemaruje se „%s“ pronađen u „.“\n"
+"Koristite „sudo ./%s“ ako je to „%s“ koji želite pokrenuti."
+
+#: plugins/sudoers/logging.c:409
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u netočni pokušaj unosa lozinke"
+msgstr[1] "%u netočna pokušaja unosa lozinke"
+msgstr[2] "%u netočnih pokušaja unosa lozinke"
+
+#: plugins/sudoers/logging.c:500
+msgid "authentication failure"
+msgstr "neuspješna autentifikacija"
+
+#: plugins/sudoers/logging.c:539 plugins/sudoers/logging.c:558
+msgid "a password is required"
+msgstr "nužna je lozinka"
+
+#: plugins/sudoers/logging.c:881
+msgid "problem parsing sudoers"
+msgstr "problem sa sudoers raščlanivanjem"
+
+#: plugins/sudoers/logging.c:922 plugins/sudoers/logging.c:930
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr "%s:%d:%d: %s"
+
+#: plugins/sudoers/logging.c:1108
+#, c-format
+msgid "unable to write log file %s"
+msgstr "nije moguće zapisati dnevničku datoteku %s"
+
+#: plugins/sudoers/match_digest.c:107
+#, c-format
+msgid "digest for %s (%s) bad length %zu, expected %zu"
+msgstr "kontrolni zbroj za %s (%s) ima lošu dužinu %zu, očekivana je %zu"
+
+#: plugins/sudoers/match_digest.c:126
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "kontrolni zbroj za %s (%s) nije u %s obliku"
+
+#: plugins/sudoers/parse_ldif.c:615
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "zanemareni nekompletni sudoRole: cn: %s"
+
+#: plugins/sudoers/parse_ldif.c:675
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "nevaljani LDIF atribut: %s"
+
+#: plugins/sudoers/parser_warnx.c:56
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: plugins/sudoers/parser_warnx.c:59
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s: %s\n"
+
+#: plugins/sudoers/pivot.c:71
+msgid "unable to restore root directory"
+msgstr "nije moguće obnoviti korijenski (root) direktorij"
+
+#: plugins/sudoers/pivot.c:79
+msgid "unable to restore current working directory"
+msgstr "nije moguće obnoviti trenutni radni direktorij"
+
+#: plugins/sudoers/policy.c:78 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "nevaljana opcija %.*s postavljena kroz sudo front-end"
+
+#: plugins/sudoers/policy.c:364 plugins/sudoers/testsudoers.c:329
+msgid "unable to parse network address list"
+msgstr "nije moguće pročitati popis mrežnih adresa (nemoguće ih je raščlaniti)"
+
+#: plugins/sudoers/policy.c:556
+msgid "user name not set by sudo front-end"
+msgstr "ime korisnika nije postavio front-end sudo-a"
+
+#: plugins/sudoers/policy.c:560
+msgid "user-ID not set by sudo front-end"
+msgstr "korisnički ID (user-ID) nije postavio front-end sudo-a"
+
+#: plugins/sudoers/policy.c:564
+msgid "group-ID not set by sudo front-end"
+msgstr "grupni ID (group-ID) nije postavio front-end sudo-a"
+
+#: plugins/sudoers/policy.c:568
+msgid "host name not set by sudo front-end"
+msgstr "ime računala (host name) nije postavio front-end sudo-a"
+
+#: plugins/sudoers/policy.c:757
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "nevaljani radni direktorij: %s"
+
+#: plugins/sudoers/policy.c:944
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "nevaljani chroot direktorij: %s"
+
+#: plugins/sudoers/policy.c:1153 plugins/sudoers/visudo.c:919
+#: plugins/sudoers/visudo.c:1218
+#, c-format
+msgid "unable to execute %s"
+msgstr "nije moguće izvršiti %s"
+
+#: plugins/sudoers/policy.c:1225 plugins/sudoers/policy.c:1260
+#: plugins/sudoers/policy.c:1282 plugins/sudoers/policy.c:1300
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: nevaljane zastavice načina rada iz sudo front end: 0x%x"
+
+#: plugins/sudoers/policy.c:1323
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Inačica sudoers plugina s pravilima %s\n"
+
+#: plugins/sudoers/policy.c:1325
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Inačica sudoers datotečne gramatike %d\n"
+
+#: plugins/sudoers/policy.c:1329
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Staza do sudoers: %s\n"
+
+#: plugins/sudoers/policy.c:1332
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "nsswitch staza: %s\n"
+
+#: plugins/sudoers/policy.c:1335
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "ldap.conf staza: %s\n"
+
+#: plugins/sudoers/policy.c:1337
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "ldap.secret staza: %s\n"
+
+# hook: A location in a routine or program in which the programmer can connect or insert other routines for the purpose of debugging or enhancing functionality.
+#: plugins/sudoers/policy.c:1370
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "nije moguće registrirati rutinu (hook) tipa %d (inačica %d.%d)"
+
+# hook: A location in a routine or program in which the programmer can connect or insert other routines for the purpose of debugging or enhancing functionality.
+#: plugins/sudoers/policy.c:1388
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "nije moguće poništiti registraciju tipa (hook) %d (inačica %d.%d)"
+
+#: plugins/sudoers/pwutil.c:242 plugins/sudoers/pwutil.c:260
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "nije moguće zapamtiti (cache) UID %u"
+
+#: plugins/sudoers/pwutil.c:254
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "nije moguće predmemorirati UID %u jer već postoji"
+
+#: plugins/sudoers/pwutil.c:314 plugins/sudoers/pwutil.c:332
+#: plugins/sudoers/pwutil.c:395 plugins/sudoers/pwutil.c:440
+#, c-format
+msgid "unable to cache user %s"
+msgstr "nije moguće zapamtiti (cache) korisnika %s"
+
+#: plugins/sudoers/pwutil.c:327
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "nije moguće predmemorirati korisnika %s jer već postoji"
+
+#: plugins/sudoers/pwutil.c:559 plugins/sudoers/pwutil.c:577
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "nije moguće zapamtiti (cache) GID %u"
+
+#: plugins/sudoers/pwutil.c:571
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "nije moguće predmemorirati GID %u jer već postoji"
+
+#: plugins/sudoers/pwutil.c:625 plugins/sudoers/pwutil.c:643
+#: plugins/sudoers/pwutil.c:704 plugins/sudoers/pwutil.c:753
+#, c-format
+msgid "unable to cache group %s"
+msgstr "nije moguće zapamtiti (cache) grupu %s"
+
+#: plugins/sudoers/pwutil.c:638
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "nije moguće predmemorirati grupu %s jer već postoji"
+
+#: plugins/sudoers/pwutil.c:900 plugins/sudoers/pwutil.c:985
+#: plugins/sudoers/pwutil.c:1039 plugins/sudoers/pwutil.c:1095
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "nije moguće predmemorirati popis grupa za %s jer već postoji"
+
+#: plugins/sudoers/pwutil.c:906 plugins/sudoers/pwutil.c:990
+#: plugins/sudoers/pwutil.c:1045 plugins/sudoers/pwutil.c:1100
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "nije moguće zapamtiti (cache) popis grupa za %s"
+
+#: plugins/sudoers/pwutil.c:979
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "nije moguće pročitati grupe za %s"
+
+#: plugins/sudoers/pwutil.c:1089
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "nije moguće razabrati GID-ove za %s"
+
+#: plugins/sudoers/set_perms.c:120 plugins/sudoers/set_perms.c:457
+#: plugins/sudoers/set_perms.c:870 plugins/sudoers/set_perms.c:1186
+#: plugins/sudoers/set_perms.c:1490
+msgid "perm stack overflow"
+msgstr "prekoračenje snopa s pravima pristupa"
+
+#: plugins/sudoers/set_perms.c:131 plugins/sudoers/set_perms.c:387
+#: plugins/sudoers/set_perms.c:468 plugins/sudoers/set_perms.c:736
+#: plugins/sudoers/set_perms.c:881 plugins/sudoers/set_perms.c:1109
+#: plugins/sudoers/set_perms.c:1197 plugins/sudoers/set_perms.c:1422
+#: plugins/sudoers/set_perms.c:1501 plugins/sudoers/set_perms.c:1592
+msgid "perm stack underflow"
+msgstr "iscrpljenje snopa s pravima pristupa"
+
+#: plugins/sudoers/set_perms.c:191 plugins/sudoers/set_perms.c:515
+#: plugins/sudoers/set_perms.c:1251 plugins/sudoers/set_perms.c:1535
+msgid "unable to change to root gid"
+msgstr "nije moguće promijeniti na GID od root"
+
+#: plugins/sudoers/set_perms.c:282 plugins/sudoers/set_perms.c:612
+#: plugins/sudoers/set_perms.c:1013 plugins/sudoers/set_perms.c:1328
+msgid "unable to change to runas gid"
+msgstr "nije moguće promijeniti na runas GID"
+
+#: plugins/sudoers/set_perms.c:287 plugins/sudoers/set_perms.c:617
+#: plugins/sudoers/set_perms.c:1018 plugins/sudoers/set_perms.c:1333
+msgid "unable to set runas group vector"
+msgstr "nije moguće postaviti runas grupni vektor"
+
+#: plugins/sudoers/set_perms.c:298 plugins/sudoers/set_perms.c:628
+#: plugins/sudoers/set_perms.c:1027 plugins/sudoers/set_perms.c:1342
+msgid "unable to change to runas uid"
+msgstr "nije moguće promijeniti na runas UID"
+
+#: plugins/sudoers/set_perms.c:320 plugins/sudoers/set_perms.c:650
+#: plugins/sudoers/set_perms.c:1047 plugins/sudoers/set_perms.c:1362
+msgid "unable to change to sudoers gid"
+msgstr "nije moguće promijeniti na sudoers GID"
+
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579
+msgid "too many processes"
+msgstr "previše procesa"
+
+#: plugins/sudoers/solaris_audit.c:62
+msgid "unable to get current working directory"
+msgstr "nije moguće odrediti trenutni radni direktorij"
+
+#: plugins/sudoers/solaris_audit.c:70
+#, c-format
+msgid "truncated audit path ctx->user.cmnd: %s"
+msgstr "skraćena (audit) staza ctx->user.cmd: %s"
+
+#: plugins/sudoers/solaris_audit.c:77
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "skraćena (audit) staza revizije argv[0]: %s"
+
+#: plugins/sudoers/sssd.c:581
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "nije moguće inicijalizirati SSS izvor. Je li SSSD instaliran na vašem računalu?"
+
+#: plugins/sudoers/sssd.c:589 plugins/sudoers/sssd.c:598
+#: plugins/sudoers/sssd.c:607 plugins/sudoers/sssd.c:616
+#: plugins/sudoers/sssd.c:625
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "nije moguće pronaći simbol „%s“ u %s"
+
+#: plugins/sudoers/sudoers.c:250
+#, c-format
+msgid "unable to get defaults from %s"
+msgstr "nije moguće dobiti zadane vrijednosti (defaults) od %s"
+
+#: plugins/sudoers/sudoers.c:259
+msgid "no valid sudoers sources found, quitting"
+msgstr "nisu pronađeni valjani sudoers izvori, kraj rada"
+
+#: plugins/sudoers/sudoers.c:366
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers specificira da root ne može koristiti sudo"
+
+#: plugins/sudoers/sudoers.c:375
+msgid "user not allowed to override closefrom limit"
+msgstr "korisniku nije dopušteno redefinirati ograničenje od ‘closefrom’"
+
+#: plugins/sudoers/sudoers.c:376
+msgid "you are not permitted to use the -C option"
+msgstr "vama nije dopušteno koristi opciju -C"
+
+#: plugins/sudoers/sudoers.c:440
+msgid "no tty"
+msgstr "nema TTY"
+
+#: plugins/sudoers/sudoers.c:441
+msgid "sorry, you must have a tty to run sudo"
+msgstr "nažalost, da pokrenete sudo morate imati TTY"
+
+#: plugins/sudoers/sudoers.c:449
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "nevaljana ljuska za korisnika %s: %s"
+
+#: plugins/sudoers/sudoers.c:491
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "korisniku nije dopušteno promijeniti radni direktorij na %s"
+
+#: plugins/sudoers/sudoers.c:493
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "vama nije dopušteno koristi opciju -R s/sa %s"
+
+#: plugins/sudoers/sudoers.c:506
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "korisniku nije dopušteno promijeniti direktorij na %s"
+
+#: plugins/sudoers/sudoers.c:507
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "vama nije dopušteno koristi opciju -D s/sa %s"
+
+#: plugins/sudoers/sudoers.c:542
+msgid "command in current directory"
+msgstr "naredba u trenutnom direktoriju"
+
+#: plugins/sudoers/sudoers.c:557
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr "„cd“ naredba je ugrađena u ljusku, ne može se izravno pokrenuti."
+
+#: plugins/sudoers/sudoers.c:559
+msgid "the -s option may be used to run a privileged shell."
+msgstr "opcija -s može se koristiti za pokretanje privilegirane ljuske."
+
+#: plugins/sudoers/sudoers.c:561
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr "opcija -D može se koristiti za pokretanje naredbe u određenom direktoriju."
+
+#: plugins/sudoers/sudoers.c:570
+msgid "user not allowed to set a command timeout"
+msgstr "korisniku nije dopušteno postavljanje tajmaut naredbe"
+
+#: plugins/sudoers/sudoers.c:572
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "nažalost, vama nije dopušteno postavljanje tajmaut za naredbu"
+
+#: plugins/sudoers/sudoers.c:580
+msgid "user not allowed to preserve the environment"
+msgstr "korisniku nije dopušteno sačuvati okolinu"
+
+#: plugins/sudoers/sudoers.c:582
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "vama nije dopušteno zadržati okolinu"
+
+#: plugins/sudoers/sudoers.c:618
+msgid "no command specified"
+msgstr "nijedna naredba nije specificirana"
+
+#: plugins/sudoers/sudoers.c:759
+msgid "error setting user-specified environment variables"
+msgstr "pogreška pri postavljanju korisnikom specificiranih varijabli okruženja"
+
+#: plugins/sudoers/sudoers.c:1211
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "sudoedit se ne mora pokrenuti sa sudo"
+
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:1613
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "nije moguće pročitati %s"
+
+#: plugins/sudoers/sudoers.c:1321 plugins/sudoers/visudo.c:1123
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s nije obična datoteka"
+
+#: plugins/sudoers/sudoers.c:1325 plugins/sudoers/timestamp.c:272 toke.l:1355
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "vlasnik %s je UID %u, a treba biti %u"
+
+#: plugins/sudoers/sudoers.c:1330 plugins/sudoers/timestamp.c:279 toke.l:1360
+#, c-format
+msgid "%s is world writable"
+msgstr "%s smije svatko mijenjati/pisati"
+
+#: plugins/sudoers/sudoers.c:1334 plugins/sudoers/timestamp.c:284 toke.l:1363
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "vlasnik %s je GID %u, a treba biti %u"
+
+#: plugins/sudoers/sudoers.c:1363
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "samo root može koristiti „-c %s“"
+
+#: plugins/sudoers/sudoers.c:1382
+#, c-format
+msgid "unknown login class %s"
+msgstr "nepoznata klasa prijave %s"
+
+#: plugins/sudoers/sudoers_cb.c:120 plugins/sudoers/sudoers_cb.c:135
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "nije moguće pronaći računalo %s"
+
+#: plugins/sudoers/sudoreplay.c:252
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "nevaljana opcija filtra: %s"
+
+#: plugins/sudoers/sudoreplay.c:268
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "nevaljano maksimalno vrijeme čekanja: %s"
+
+#: plugins/sudoers/sudoreplay.c:291
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "nevaljani faktor brzine: %s"
+
+#: plugins/sudoers/sudoreplay.c:326
+#, c-format
+msgid "invalid time offset %s"
+msgstr "nevaljani vremenski odmak %s"
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:340
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/tajming: %s"
+
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Reproduciranje sudo sesije: %s"
+
+#: plugins/sudoers/sudoreplay.c:634
+msgid "unable to set tty to raw mode"
+msgstr "nije moguće postaviti TTY u direktni mȏd (da ne interpretira posebne znakove)"
+
+#: plugins/sudoers/sudoreplay.c:685
+msgid "Warning: your terminal is too small to properly replay the log."
+msgstr "Upozorenje: vaš terminal je premaleni za pravilno reproduciranje dnevnika."
+
+#: plugins/sudoers/sudoreplay.c:686
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Veličina dnevnika je %d x %d, a veličina vašeg terminala %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:714
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Reprodukcija je završena -- obnovite terminal pritiskom na bilo koju tipku."
+
+#: plugins/sudoers/sudoreplay.c:1217 plugins/sudoers/sudoreplay.c:1247
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "dvosmisleni izraz „%s“"
+
+#: plugins/sudoers/sudoreplay.c:1269
+msgid "unmatched ')' in expression"
+msgstr "nesparena „)“ u izrazu"
+
+#: plugins/sudoers/sudoreplay.c:1273
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "nepoznati pojam za pretragu „%s“"
+
+#: plugins/sudoers/sudoreplay.c:1288
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s zahtijeva argument"
+
+#: plugins/sudoers/sudoreplay.c:1298
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "nije moguće raščlaniti datum „%s“"
+
+#: plugins/sudoers/sudoreplay.c:1307
+msgid "unmatched '(' in expression"
+msgstr "nesparena „(“ u izrazu"
+
+#: plugins/sudoers/sudoreplay.c:1309
+msgid "illegal trailing \"or\""
+msgstr "nelegalni zaostali „or“"
+
+#: plugins/sudoers/sudoreplay.c:1311
+msgid "illegal trailing \"!\""
+msgstr "nelegalni zaostali „!“"
+
+#: plugins/sudoers/sudoreplay.c:1417
+#, c-format
+msgid "unknown search type %d"
+msgstr "nepoznati tip za pretragu %d"
+
+#: plugins/sudoers/sudoreplay.c:1679
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "uporaba: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1681
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "uporaba: %s [-h] [-d direktorij] -l [izraz za pretragu]\n"
+
+#: plugins/sudoers/sudoreplay.c:1695
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - reproducira dnevnike sudo sesija\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1697
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Options:\n"
+" -d, --directory=dir navedite direktorij dir za dnevnike sesija\n"
+" -f, --filter=filter navedite (filter) tip/tipove U/I koje treba pokazati\n"
+" -h, --help pokaže poruku s pomoći i iziđe\n"
+" -l, --list popis dostupnih ID-ova sjednica koji se podudaraju\n"
+" s neobveznim izrazom za pretragu\n"
+" -m, --max-wait=num čekati ne više od num sekundi između događaja\n"
+" -n, --non-interactive bez prompta - sesija se šalje na standardni izlaz\n"
+" -R, --no-resize ne mijenjati veličinu terminala\n"
+" -S, --suspend-wait čeka dok je naredba obustavljena\n"
+" -s, --speed=num ubrza ili uspori reprodukciju\n"
+" -V, --version informira o inačici ovog programa i iziđe"
+
+#: plugins/sudoers/testsudoers.c:392
+#, c-format
+msgid ""
+"\n"
+"Invalid shell for user %s: %s\n"
+msgstr ""
+"\n"
+"Nevaljana ljuska za korisnika %s: %s\n"
+
+#: plugins/sudoers/testsudoers.c:411
+msgid ""
+"\n"
+"Password required"
+msgstr ""
+"\n"
+"Potrebna je lozinka"
+
+#: plugins/sudoers/testsudoers.c:422
+msgid ""
+"\n"
+"Parse error"
+msgstr ""
+"\n"
+"Greška pri raščlambi"
+
+#: plugins/sudoers/testsudoers.c:425
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Naredba je dopuštena."
+
+#: plugins/sudoers/testsudoers.c:428
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Naredba nije dopuštena"
+
+#: plugins/sudoers/testsudoers.c:431
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Naredba nije prepoznata"
+
+#: plugins/sudoers/timestamp.c:364 plugins/sudoers/timestamp.c:711
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "nije moguće skratiti datoteku s vremenskim podacima na %lld bajtova"
+
+#: plugins/sudoers/timestamp.c:908
+msgid "ignoring time stamp from the future"
+msgstr "zanemarena vremenska oznaka iz budućnosti"
+
+#: plugins/sudoers/timestamp.c:931
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "vremenska oznaka je predaleko u budućnosti: %20.20s"
+
+#: plugins/sudoers/timestamp.c:1067
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "nije moguće zaključati datoteku s vremenskim oznakama %s"
+
+#: plugins/sudoers/timestamp.c:1114
+#, c-format
+msgid "%s:%d:%d timestampowner: unknown user %s"
+msgstr "%s:%d:%d timestampowner: nepoznati korisnik %s"
+
+#: plugins/sudoers/toke_util.c:159
+msgid "sudoedit should not be specified with a path"
+msgstr "sudoedit se ne smije specificirati sa stazom"
+
+#: plugins/sudoers/visudo.c:308 plugins/sudoers/visudo.c:714
+#, c-format
+msgid "press return to edit %s: "
+msgstr "pritisnite return/enter za redigirati %s: "
+
+#: plugins/sudoers/visudo.c:323
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "sadržaj sesije uređivanja je ostavljen u %s"
+
+#: plugins/sudoers/visudo.c:401
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "navedeni uređivač (%s) ne postoji"
+
+#: plugins/sudoers/visudo.c:406
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "nijedan uređivač nije pronađen (editor path = %s)"
+
+#: plugins/sudoers/visudo.c:494 plugins/sudoers/visudo.c:786
+#, c-format
+msgid "unable to stat %s"
+msgstr "nije moguće dobiti status od %s"
+
+#: plugins/sudoers/visudo.c:514 plugins/sudoers/visudo.c:522
+msgid "write error"
+msgstr "greška pri pisanju"
+
+#: plugins/sudoers/visudo.c:568
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "nije moguće dobiti status privremene datoteke (%s), %s nije promijenjena"
+
+#: plugins/sudoers/visudo.c:575
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "privremena datoteka duljine nula (%s), %s nije promijenjena"
+
+#: plugins/sudoers/visudo.c:581
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "greška uređivač (%s), %s nije promijenjena"
+
+#: plugins/sudoers/visudo.c:613
+#, c-format
+msgid "%s unchanged"
+msgstr "%s nije promijenjeno"
+
+#: plugins/sudoers/visudo.c:661
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "nije moguće ponovo otvoriti privremenu datoteku (%s), %s nije promijenjena."
+
+#: plugins/sudoers/visudo.c:674
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "nije moguće razabrati privremenu datoteku (%s) -- nepoznata greška"
+
+#: plugins/sudoers/visudo.c:760 plugins/sudoers/visudo.c:790
+#: plugins/sudoers/visudo.c:797
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "nije moguće postaviti (UID, GID) od %s na (%u, %u)"
+
+#: plugins/sudoers/visudo.c:825
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s i %s nisu na istom datotečnom sustavu, koristi se mv za preimenovanje"
+
+#: plugins/sudoers/visudo.c:836
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "naredba nije uspjela: „%s %s %s“, %s nije promijenjena"
+
+#: plugins/sudoers/visudo.c:843
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "greška u preimenovanju %s, %s nije promijenjena"
+
+#: plugins/sudoers/visudo.c:864
+msgid "What now? "
+msgstr "Što sada? "
+
+#: plugins/sudoers/visudo.c:878
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Mogućnosti su:\n"
+" (e) datoteku sudoers ponovno redigirati\n"
+" (x) završiti bez spremanja promjena u datoteku sudoers)\n"
+" (Q) prekinuti i spremiti promjene u datoteku sudoers (OPASNO!)\n"
+
+#: plugins/sudoers/visudo.c:923
+#, c-format
+msgid "unable to run %s"
+msgstr "nije moguće pokrenuti %s"
+
+#: plugins/sudoers/visudo.c:954
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: krivi vlasnik (UID, GID) a treba biti (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:965
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: loša prava pristupa, trebala bi biti 0%o\n"
+
+#: plugins/sudoers/visudo.c:1017 plugins/sudoers/visudo.c:1024
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: raščlamba je uspjela\n"
+
+#: plugins/sudoers/visudo.c:1043
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s je zauzeti, pokušajte ponovo kasnije"
+
+#: plugins/sudoers/visudo.c:1047
+msgid "Edit anyway? [y/N]"
+msgstr "Ipak redigirati? [y/N]"
+
+#: plugins/sudoers/visudo.c:1206
+msgid "the -x option will be removed in a future release"
+msgstr "opcija -x bit će uklonjena iz buduće inačice"
+
+#: plugins/sudoers/visudo.c:1208
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "molimo da umjesto toga pokušate rabiti cvtsudoers uslužni program"
+
+#: plugins/sudoers/visudo.c:1228
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "Upozorenje: %s:%d:%d nekorišteni %s „%s“"
+
+#: plugins/sudoers/visudo.c:1341
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - sigurno redigira sudoers datoteku\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1343
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -I, --no-includes do not edit include files\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Opcije:\n"
+" -c, --check koristi samo testni način\n"
+" -f, --file=sudoers specificira lokaciju sudoers datoteke\n"
+" -h, --help pokaže poruku s pomoći i iziđe\n"
+" -I, --no-includes uključene datoteke (include files) ne redigirati\n"
+" -q, --quite manje opširne (tihe) poruke grešaka u sintaksi\n"
+" -s, --strick striktni test sintakse sudoers datoteke\n"
+" -V, --version informira o inačici ovog programa i iziđe\n"
+
+#: toke.l:184
+msgid "empty string"
+msgstr "prazni string"
+
+#: toke.l:196 toke.l:566
+msgid "empty group"
+msgstr "prazna grupa"
+
+#: toke.l:206 toke.l:564
+msgid "empty netgroup"
+msgstr "prazna mrežna grupa (netgroup)"
+
+#: toke.l:284
+msgid "unterminated regular expression"
+msgstr "nezavršen regularni izraz"
+
+#: toke.l:358 toke.l:370 toke.l:382 toke.l:398 toke.l:417 toke.l:457
+msgid "invalid line continuation"
+msgstr "nevaljani nastavak retka"
+
+#: toke.l:603 toke.l:615
+msgid "invalid IPv6 address"
+msgstr "nevaljana IPv6 adresa"
+
+#: toke.l:863
+msgid "unexpected line break in string"
+msgstr "neočekivani prelom retka"
+
+#: toke.l:982
+msgid "ignoring editor backup file"
+msgstr "ignoriramo osiguranje (sigurnosnu kopiju) editora"
+
+#: toke.l:985
+msgid "ignoring file name containing '.'"
+msgstr "ignoriramo ime datoteke koje sadrži ‘.’"
+
+#: toke.l:1310
+msgid "too many levels of includes"
+msgstr "previše razina uključivanja"
+
+#~ msgid "\thost unmatched"
+#~ msgstr "\tračunalo se ne podudara"
+
+#~ msgid "timestamp owner (%s): No such user"
+#~ msgstr "vlasnik vremenske oznake (%s): Nema takvog korisnika"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "vlasnik %s mora biti UID %d"
+
+#~ msgid "%s must only be writable by owner"
+#~ msgstr "%s mora biti dostupan za pisanje samo vlasniku"
+
+#~ msgid "%s is group writable"
+#~ msgstr "%s članovi grupe mogu mijenjati/pisati"
+
+#~ msgid "lecture status path too long: %s/%s"
+#~ msgstr "staza do lekcije je predugačka: %s/%s"
+
+#~ msgid "Error: %s:%d:%d: cycle in %s \"%s\""
+#~ msgstr "Greška: %s:%d:%d: ciklus u %s „%s“"
+
+#~ msgid "Warning: %s:%d:%d: cycle in %s \"%s\""
+#~ msgstr "Upozorenje: %s:%d:%d: ciklus u %s „%s“"
+
+#~ msgid "Warning: %s:%d:%d: %s \"%s\" referenced but not defined"
+#~ msgstr "Upozorenje: %s:%d:%d %s „%s“ je referenciran ali nije definiran"
+
+#~ msgid "parse error in %s near line %d\n"
+#~ msgstr "greška u raščlambi u %s blizu retka %d\n"
+
+#~ msgid "parse error in %s\n"
+#~ msgstr "greška u raščlambi u %s\n"
+
+#~ msgid "%s: unknown defaults entry \"%s\""
+#~ msgstr "%s: nepoznata stavka zadanih vrijednosti „%s“"
+
+#~ msgid "%s:%d:%d: no value specified for \"%s\""
+#~ msgstr "%s:%d:%d: nije navedena vrijednost za „%s“"
+
+#~ msgid "%s:%d:%d: invalid operator \"%c=\" for \"%s\""
+#~ msgstr "%s:%d:%d: nevaljan operator \"%c=\" za „%s“"
+
+#~ msgid "%s:%d:%d: option \"%s\" does not take a value"
+#~ msgstr "%s:%d:%d: opcija „%s“ ne treba nikakvu vrijednost"
+
+#~ msgid "%s:%d:%d: invalid Defaults type 0x%x for option \"%s\""
+#~ msgstr "%s:%d:%d: nevaljana vrsta Defaults 0x%x za opciju „%s“"
+
+#~ msgid "%s:%d:%d: value \"%s\" is invalid for option \"%s\""
+#~ msgstr "%s:%d:%d: vrijednost „%s“ za opciju „%s“ nije valjana"
+
+#~ msgid "%s:%d:%d: path name for \"%s\" too long"
+#~ msgstr "%s:%d:%d: ime staze za „%s“ je predugačko"
+
+#~ msgid "%s: path name for \"%s\" too long"
+#~ msgstr "%s: ime staze za „%s“ je predugačko"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/', '~', or '*'"
+#~ msgstr "%s:%d:%d: vrijednost za „%s“ mora započeti s „/“, „~“, ili „*“"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/'"
+#~ msgstr "%s:%d:%d: vrijednost za „%s“ mora započeti s „/“"
+
+#~ msgid "parse error in %s near line %d"
+#~ msgstr "greška u raščlambi u %s blizu retka %d"
+
+#~ msgid "parse error in %s"
+#~ msgstr "greška u raščlambi u %s"
+
+#~ msgid "SELinux RBAC is not supported when intercept mode is enabled"
+#~ msgstr "SELinux RBAC nije podržan ako je omogućeno presretanje"
+
+#~ msgid "SELinux RBAC is not supported when the log_subcmds flag is enabled"
+#~ msgstr "SELinux RBAC nije podržan ako je postavljen flag od log_subcmds"
+
+#~ msgid "problem with defaults entries"
+#~ msgstr "problem sa stavkama defaults"
+
+#~ msgid "internal error, unable to find %s in list!"
+#~ msgstr "**interna greška**, nije moguće pronaći %s na popisu!"
+
+#~ msgid "%s is not in the sudoers file. This incident will be reported.\n"
+#~ msgstr "%s nije u sudoers datoteci. Ovaj će incident biti prijavljen.\n"
+
+#~ msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+#~ msgstr ""
+#~ "%s nema dopuštenja pokrenuti sudo na %s. Ovaj će incident biti prijavljen.\n"
+#~ "\n"
+
+#~ msgid "%s: write buffer already in use"
+#~ msgstr "%s: međuspremnik za pisanje je zauzet"
+
+#~ msgid "unable to read diffie-hellman parameters: %s"
+#~ msgstr "nije moguće pročitati diffie-hellman parametre: %s"
+
+#~ msgid "%s:%d unknown key: %s"
+#~ msgstr "%s: %d nepoznati ključ: %s"
+
+#~ msgid "unable to get TLS server method: %s"
+#~ msgstr "nije moguće dobiti od servera metodu: %s"
+
+#~ msgid "%s:%u unable to parse \"%s\""
+#~ msgstr "%s:%u nije moguće raščlaniti \"%s\""
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " -f, --file path to configuration file\n"
+#~ " -h --help display help message and exit\n"
+#~ " -n, --no-fork do not fork, run in the foreground\n"
+#~ " -R, --random-drop percent chance connections will drop\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Opcije:\n"
+#~ " -f, --file= staza do konfiguracijske datoteke\n"
+#~ " -h, --help pokaže ovu pomoć i iziđe\n"
+#~ " -n, --no-fork ne stvara novi proces, nego radi u prednjem planu\n"
+#~ " -R, --random-drop postotak šanse da izgubi vezu (drop connection)\n"
+#~ " -V, --version informira o inačici ovog programa i iziđe\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " --help display help message and exit\n"
+#~ " -A, --accept only send an accept event (no I/O)\n"
+#~ " -h, --host host to send logs to\n"
+#~ " -i, --iolog_id remote ID of I/O log to be resumed\n"
+#~ " -p, --port port to use when connecting to host\n"
+#~ " -r, --restart restart previous I/O log transfer\n"
+#~ " -R, --reject reject the command with the given reason\n"
+#~ " -b, --ca-bundle certificate bundle file to verify server's cert against\n"
+#~ " -c, --cert certificate file for TLS handshake\n"
+#~ " -k, --key private key file\n"
+#~ " -n, --no-verify do not verify server certificate\n"
+#~ " -t, --test test audit server by sending selected I/O log n times in parallel\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Options:\n"
+#~ " --help pokaže ovu pomoć i iziđe\n"
+#~ " -A, --accept only send an accept event (no I/O)\n"
+#~ " -h, --host host (računalo) kojemu se šalje dnevnik\n"
+#~ " -i, --iolog_id udaljeni ID od U/I dnevnika koji treba nastaviti\n"
+#~ " -p, --port port koji će se koristiti za spajanje na hosta\n"
+#~ " -r, --restart ponovi prethodni prijenos U/I dnevnika\n"
+#~ " -b, --ca-bundle datoteka s paketom certifikata (CA) za provjeru\n"
+#~ " certifikata servera\n"
+#~ " -c, --cert certificat datoteka za TLS rukovanje (handshake)\n"
+#~ " -k, --key datoteka s privatnim (tajnim) ključem (private key)\n"
+#~ " -t, --test testira revizijski server tako da paralelno\n"
+#~ " pošalje ‘n’ puta U/I dnevnik\n"
+#~ " -V, --version informira o inačici ovog programa i iziđe\n"
+
+#~ msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+#~ msgstr "Prethodno učitati prividne izvršne funkcije sadržane u biblioteci sudo_noexec."
+
+#~ msgid "sudo_ldap_conf_add_ports: port too large"
+#~ msgstr "‘sudo_ldap_conf_add_ports’: port vrijednost je prevelika"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s\n"
+#~ msgstr "SSL_connect failed: ssl_error=%d, stack=%s\n"
+
+#~ msgid "CA bundle file was not specified"
+#~ msgstr "Datoteka s paketom certifikata (CA) nije bila specificirana"
+
+#~ msgid "Client certificate was not specified"
+#~ msgstr "Certifikat klijenta nije bio specificiran"
+
+#~ msgid "Unable to allocate ssl object: %s\n"
+#~ msgstr "nije moguće dodijeliti SSL objekt: %s\n"
+
+#~ msgid "Unable to attach socket to the ssl object: %s\n"
+#~ msgstr "Nije moguće prikvačiti utičnicu na SSL objekt: %s\n"
+
+#~ msgid "client message too large: %zu\n"
+#~ msgstr "poruka klijenta je preduga: %zu\n"
+
+#~ msgid "server message too large: %u\n"
+#~ msgstr "poruka servera je preduga: %u\n"
+
+#~ msgid "CA bundle file is not set in sudoers"
+#~ msgstr "U sudoers nije zadana datoteka s paketom certifikata (CA)"
+
+#~ msgid "Calling SSL_CTX_load_verify_locations() failed: %s"
+#~ msgstr "Nije uspjelo pozvati SSL_CTX_load_verify_locations(): %s"
+
+#~ msgid "Signed certificate file is not set in sudoers"
+#~ msgstr "Potpisana datoteka certifikata nije postavljena u sudoers"
+
+#~ msgid "Unable to load private key into the ssl context: %s"
+#~ msgstr "Učitavanje privatnog (tajnog) ključa u SSL kontekst nije uspjelo: %s"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s"
+#~ msgstr "‘SSL_connect’ nije uspjela: ssl_error=%d, stack=%s"
+
+#~ msgid "SSL_read failed: ssl_error=%d, stack=%s"
+#~ msgstr "‘SSL_read’ nije uspjela: ssl_error=%d, stack=%s"
+
+#~ msgid "SSL_write failed: ssl_error=%d, stack=%s"
+#~ msgstr "‘SSL_write’ nije uspjela: ssl_error=%d, stack=%s"
+
+#~ msgid "unknown address family: %d"
+#~ msgstr "nepoznata familija adresa: %d"
+
+#~ msgid "audit_failure message too long"
+#~ msgstr "audit_failure poruka (revizije) je preduga"
+
+#~ msgid "No user or host"
+#~ msgstr "Nema korisnika ili računala"
+
+#~ msgid "validation failure"
+#~ msgstr "greška pri provjeri valjanosti"
+
+#~ msgid "%s/%s/timing: %s"
+#~ msgstr "%s/%s/vrijeme: %s"
+
+#~ msgid "ignoring invalid attribute value: %s"
+#~ msgstr "ignorira se nevaljana vrijednost atributa: %s"
+
+#~ msgid "unable to cache user %s, out of memory"
+#~ msgstr "nije moguće predmemorirati korisnika %s jer nema dovoljno memorije"
+
+#~ msgid "unable to cache group %s, out of memory"
+#~ msgstr "nije moguće predmemorirati grupu %s jer nema dovoljno memorije"
+
+#~ msgid "unable to cache group list for %s, out of memory"
+#~ msgstr "nije moguće predmemorirati popis grupa za %s jer nema dovoljno memorije"
+
+#~ msgid ""
+#~ "\n"
+#~ "LDAP Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "LDAP uloga: NEPOZNATA\n"
+
+#~ msgid " Order: %s\n"
+#~ msgstr " Redoslijed: %s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: %s\n"
+#~ msgstr ""
+#~ "\n"
+#~ "SSSD uloga: %s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "SSSD uloga: NEPOZNATA\n"
+
+#~ msgid "Warning: unused %s `%s'"
+#~ msgstr "Upozorenje: %s „%s“ nije upotrebljen"
+
+#~ msgid "Password:"
+#~ msgstr "Lozinka:"
+
+#~ msgid "pam_chauthtok: %s"
+#~ msgstr "pam_chauthtok: %s"
+
+#~ msgid "pam_authenticate: %s"
+#~ msgstr "pam_authenticate: %s"
+
+#~ msgid "getaudit: failed"
+#~ msgstr "getaudit: nije uspio"
+
+#~ msgid "getauid failed"
+#~ msgstr "getauid nije uspio"
+
+#~ msgid "au_to_subject: failed"
+#~ msgstr "au_to_subject: nije uspio"
+
+#~ msgid "au_to_exec_args: failed"
+#~ msgstr "au_to_exec_args: nije uspio"
+
+#~ msgid "au_to_return32: failed"
+#~ msgstr "au_to_return32: nije uspio"
+
+#~ msgid "getauid: failed"
+#~ msgstr "getauid: nije uspio"
+
+#~ msgid "au_to_text: failed"
+#~ msgstr "au_to_text: nije uspio"
+
+#~ msgid "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+#~ msgstr "sudo_ldap_conf_add_ports: nema dovoljno prostora za proširenje međuspremnika računala"
+
+#~ msgid "unable to mix ldaps and starttls"
+#~ msgstr "ne mogu miješati ldaps i starttls"
+
+#~ msgid "sudo_ldap_parse_uri: out of space building hostbuf"
+#~ msgstr "sudo_ldap_parse_uri: nema dovoljno prostora za izgradnju međuspremnika računala"
+
+#~ msgid "sudo_ldap_build_pass1 allocation mismatch"
+#~ msgstr "neodgovarajuća sudo_ldap_build_pass1 alokacija"
+
+#~ msgid "internal error: insufficient space for log line"
+#~ msgstr "interna greška: nema dovoljno prostora za redak dnevnika"
+
+#~ msgid "Unable to dlopen %s: %s"
+#~ msgstr "Ne mogu izvršiti dlopen %s: %s"
+
+#~ msgid "writing to standard output"
+#~ msgstr "ispisujem na standardni izlaz"
+
+#~ msgid "nanosleep: tv_sec %ld, tv_nsec %ld"
+#~ msgstr "nanosleep: tv_sec %ld, tv_nsec %ld"
+
+#~ msgid "too many parenthesized expressions, max %d"
+#~ msgstr "previše izraza u zagradama, najviše %d"
+
+#~ msgid "%s owned by uid %u, should be uid %u"
+#~ msgstr "vlasnik %s je uid %u, treba biti uid %u"
+
+#~ msgid "%s writable by non-owner (0%o), should be mode 0700"
+#~ msgstr "nevlasnici imaju dozvolu za pisanje u %s (0%o), treba biti mod 0700"
+
+#~ msgid "%s exists but is not a regular file (0%o)"
+#~ msgstr "%s postoji, ali nije obična datoteka (0%o)"
+
+#~ msgid "%s writable by non-owner (0%o), should be mode 0600"
+#~ msgstr "nevlasnici imaju dozvolu za pisanje u %s (0%o), treba biti mod 0600"
+
+#~ msgid "unable to remove %s, will reset to the epoch"
+#~ msgstr "ne mogu ukloniti %s, vratit ću na početnu epohu"
+
+#~ msgid "fill_args: buffer overflow"
+#~ msgstr "fill_args: preljev međuspremnika"
+
+#~ msgid "unable to stat editor (%s)"
+#~ msgstr "ne mogu odrediti stanje uređivača (%s)"
+
+#~ msgid ">>> %s: %s near line %d <<<"
+#~ msgstr ">>> %s: %s kod retka %d <<<"
+
+#~ msgid "unable to set locale to \"%s\", using \"C\""
+#~ msgstr "ne mogu postaviti lokal u „%s”, koristim „C”"
+
+#~ msgid ""
+#~ " Commands:\n"
+#~ "\t"
+#~ msgstr ""
+#~ " Naredbe:\n"
+#~ "\t"
+
+#~ msgid ": "
+#~ msgstr ": "
+
+#~ msgid "unable to cache uid %u (%s), already exists"
+#~ msgstr "ne mogu staviti uid %u (%s) u spremnik, već postoji"
+
+#~ msgid "unable to cache gid %u (%s), already exists"
+#~ msgstr "ne mogu staviti gid %u (%s) u spremnik, već postoji"
+
+#~ msgid "internal error, expand_prompt() overflow"
+#~ msgstr "interna greška, expand_prompt() preljev"
+
+#~ msgid "internal error, sudo_setenv2() overflow"
+#~ msgstr "interna greška, sudo_setenv2() preljev"
+
+#~ msgid "internal error, sudo_setenv() overflow"
+#~ msgstr "interna greška, sudo_setenv() preljev"
+
+#~ msgid "internal error, linux_audit_command() overflow"
+#~ msgstr "interna greška, linux_audit_command() preljev"
+
+#~ msgid "internal error, runas_groups overflow"
+#~ msgstr "interna greška, runas_groups preljev"
+
+#~ msgid "internal error, init_vars() overflow"
+#~ msgstr "interna greška, init_vars() preljev"
diff --git a/plugins/sudoers/po/hu.mo b/plugins/sudoers/po/hu.mo
new file mode 100644
index 0000000..97ad917
--- /dev/null
+++ b/plugins/sudoers/po/hu.mo
Binary files differ
diff --git a/plugins/sudoers/po/hu.po b/plugins/sudoers/po/hu.po
new file mode 100644
index 0000000..2e9239e
--- /dev/null
+++ b/plugins/sudoers/po/hu.po
@@ -0,0 +1,2152 @@
+# Hungarian translation for sudoers.
+# Portable object template file for the sudoers plugin
+# This file is put in the public domain.
+#
+# Todd C. Miller <Todd.Miller@courtesan.com>, 2011-2014.
+# Gabor Kelemen <kelemeng@ubuntu.com>, 2015.
+# Balázs Úr <urbalazs@gmail.com>, 2017, 2018.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.8.22b2\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2017-12-18 10:37-0700\n"
+"PO-Revision-Date: 2018-01-20 14:06+0100\n"
+"Last-Translator: Balázs Úr <urbalazs@gmail.com>\n"
+"Language-Team: Hungarian <translation-team-hu@lists.sourceforge.net>\n"
+"Language: hu\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Lokalize 1.2\n"
+
+#: confstr.sh:1
+msgid "syntax error"
+msgstr "szintaktikai hiba"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "%p jelszava: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] %p jelszava: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Jelszó: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** BIZTONSÁGI információk erről: %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Elnézést, próbálja újra."
+
+#: gram.y:192 gram.y:240 gram.y:247 gram.y:254 gram.y:261 gram.y:268
+#: gram.y:284 gram.y:307 gram.y:314 gram.y:321 gram.y:328 gram.y:335
+#: gram.y:398 gram.y:406 gram.y:416 gram.y:449 gram.y:456 gram.y:463
+#: gram.y:470 gram.y:552 gram.y:559 gram.y:568 gram.y:577 gram.y:594
+#: gram.y:706 gram.y:713 gram.y:720 gram.y:728 gram.y:824 gram.y:831
+#: gram.y:838 gram.y:845 gram.y:852 gram.y:878 gram.y:885 gram.y:892
+#: gram.y:1015 gram.y:1195 gram.y:1202 plugins/sudoers/alias.c:124
+#: plugins/sudoers/alias.c:139 plugins/sudoers/auth/bsdauth.c:141
+#: plugins/sudoers/auth/kerb5.c:119 plugins/sudoers/auth/kerb5.c:145
+#: plugins/sudoers/auth/pam.c:490 plugins/sudoers/auth/rfc1938.c:109
+#: plugins/sudoers/auth/sia.c:59 plugins/sudoers/defaults.c:651
+#: plugins/sudoers/defaults.c:906 plugins/sudoers/defaults.c:1077
+#: plugins/sudoers/editor.c:64 plugins/sudoers/editor.c:82
+#: plugins/sudoers/editor.c:93 plugins/sudoers/env.c:233
+#: plugins/sudoers/filedigest.c:120 plugins/sudoers/filedigest_gcrypt.c:90
+#: plugins/sudoers/filedigest_openssl.c:111 plugins/sudoers/gc.c:52
+#: plugins/sudoers/group_plugin.c:134 plugins/sudoers/interfaces.c:71
+#: plugins/sudoers/iolog.c:941 plugins/sudoers/iolog_path.c:167
+#: plugins/sudoers/ldap.c:449 plugins/sudoers/ldap.c:480
+#: plugins/sudoers/ldap.c:532 plugins/sudoers/ldap.c:566
+#: plugins/sudoers/ldap.c:980 plugins/sudoers/ldap.c:1174
+#: plugins/sudoers/ldap.c:1185 plugins/sudoers/ldap.c:1201
+#: plugins/sudoers/ldap.c:1493 plugins/sudoers/ldap.c:1653
+#: plugins/sudoers/ldap.c:1735 plugins/sudoers/ldap.c:1883
+#: plugins/sudoers/ldap.c:1907 plugins/sudoers/ldap.c:1996
+#: plugins/sudoers/ldap.c:2011 plugins/sudoers/ldap.c:2107
+#: plugins/sudoers/ldap.c:2140 plugins/sudoers/ldap.c:2221
+#: plugins/sudoers/ldap.c:2303 plugins/sudoers/ldap.c:2400
+#: plugins/sudoers/ldap.c:3235 plugins/sudoers/ldap.c:3267
+#: plugins/sudoers/ldap.c:3579 plugins/sudoers/ldap.c:3607
+#: plugins/sudoers/ldap.c:3623 plugins/sudoers/ldap.c:3713
+#: plugins/sudoers/ldap.c:3729 plugins/sudoers/linux_audit.c:76
+#: plugins/sudoers/logging.c:190 plugins/sudoers/logging.c:501
+#: plugins/sudoers/logging.c:522 plugins/sudoers/logging.c:563
+#: plugins/sudoers/logging.c:740 plugins/sudoers/logging.c:998
+#: plugins/sudoers/match.c:617 plugins/sudoers/match.c:664
+#: plugins/sudoers/match.c:714 plugins/sudoers/match.c:738
+#: plugins/sudoers/match.c:826 plugins/sudoers/match.c:915
+#: plugins/sudoers/parse.c:252 plugins/sudoers/parse.c:264
+#: plugins/sudoers/parse.c:279 plugins/sudoers/parse.c:291
+#: plugins/sudoers/policy.c:498 plugins/sudoers/policy.c:735
+#: plugins/sudoers/prompt.c:93 plugins/sudoers/pwutil.c:165
+#: plugins/sudoers/pwutil.c:236 plugins/sudoers/pwutil.c:312
+#: plugins/sudoers/pwutil.c:486 plugins/sudoers/pwutil.c:551
+#: plugins/sudoers/pwutil.c:620 plugins/sudoers/pwutil.c:778
+#: plugins/sudoers/pwutil.c:835 plugins/sudoers/pwutil.c:880
+#: plugins/sudoers/pwutil.c:938 plugins/sudoers/sssd.c:162
+#: plugins/sudoers/sssd.c:194 plugins/sudoers/sssd.c:237
+#: plugins/sudoers/sssd.c:244 plugins/sudoers/sssd.c:280
+#: plugins/sudoers/sssd.c:353 plugins/sudoers/sssd.c:392
+#: plugins/sudoers/sssd.c:1073 plugins/sudoers/sssd.c:1252
+#: plugins/sudoers/sssd.c:1266 plugins/sudoers/sssd.c:1282
+#: plugins/sudoers/sudoers.c:263 plugins/sudoers/sudoers.c:273
+#: plugins/sudoers/sudoers.c:281 plugins/sudoers/sudoers.c:365
+#: plugins/sudoers/sudoers.c:682 plugins/sudoers/sudoers.c:807
+#: plugins/sudoers/sudoers.c:851 plugins/sudoers/sudoers.c:1123
+#: plugins/sudoers/sudoers_debug.c:107 plugins/sudoers/sudoreplay.c:1254
+#: plugins/sudoers/sudoreplay.c:1366 plugins/sudoers/sudoreplay.c:1406
+#: plugins/sudoers/sudoreplay.c:1415 plugins/sudoers/sudoreplay.c:1425
+#: plugins/sudoers/sudoreplay.c:1433 plugins/sudoers/sudoreplay.c:1437
+#: plugins/sudoers/sudoreplay.c:1593 plugins/sudoers/sudoreplay.c:1597
+#: plugins/sudoers/testsudoers.c:131 plugins/sudoers/testsudoers.c:217
+#: plugins/sudoers/testsudoers.c:234 plugins/sudoers/timestamp.c:397
+#: plugins/sudoers/timestamp.c:441 plugins/sudoers/timestamp.c:868
+#: plugins/sudoers/toke_util.c:56 plugins/sudoers/toke_util.c:109
+#: plugins/sudoers/toke_util.c:146 plugins/sudoers/visudo.c:153
+#: plugins/sudoers/visudo.c:309 plugins/sudoers/visudo.c:315
+#: plugins/sudoers/visudo.c:446 plugins/sudoers/visudo.c:624
+#: plugins/sudoers/visudo.c:985 plugins/sudoers/visudo.c:1051
+#: plugins/sudoers/visudo.c:1095 plugins/sudoers/visudo.c:1197
+#: plugins/sudoers/visudo_json.c:1025 toke.l:849 toke.l:949 toke.l:1106
+msgid "unable to allocate memory"
+msgstr "nem foglalható memória"
+
+#: gram.y:481
+msgid "a digest requires a path name"
+msgstr "egy kivonat egy útvonalnevet igényel"
+
+#: gram.y:607
+msgid "invalid notbefore value"
+msgstr "érvénytelen „notbefore” érték"
+
+#: gram.y:615
+msgid "invalid notafter value"
+msgstr "érvénytelen „notafter” érték"
+
+#: gram.y:624 plugins/sudoers/policy.c:314
+msgid "timeout value too large"
+msgstr "az időkorlát értéke túl nagy"
+
+#: gram.y:626 plugins/sudoers/policy.c:316
+msgid "invalid timeout value"
+msgstr "érvénytelen időkorlát érték"
+
+#: gram.y:1195 gram.y:1202 plugins/sudoers/auth/pam.c:320
+#: plugins/sudoers/auth/pam.c:490 plugins/sudoers/auth/rfc1938.c:109
+#: plugins/sudoers/defaults.c:651 plugins/sudoers/defaults.c:906
+#: plugins/sudoers/defaults.c:1077 plugins/sudoers/editor.c:64
+#: plugins/sudoers/editor.c:82 plugins/sudoers/editor.c:93
+#: plugins/sudoers/env.c:233 plugins/sudoers/filedigest.c:120
+#: plugins/sudoers/filedigest_gcrypt.c:72
+#: plugins/sudoers/filedigest_gcrypt.c:90
+#: plugins/sudoers/filedigest_openssl.c:111 plugins/sudoers/gc.c:52
+#: plugins/sudoers/group_plugin.c:134 plugins/sudoers/interfaces.c:71
+#: plugins/sudoers/iolog.c:941 plugins/sudoers/iolog_path.c:167
+#: plugins/sudoers/ldap.c:449 plugins/sudoers/ldap.c:480
+#: plugins/sudoers/ldap.c:532 plugins/sudoers/ldap.c:566
+#: plugins/sudoers/ldap.c:980 plugins/sudoers/ldap.c:1174
+#: plugins/sudoers/ldap.c:1185 plugins/sudoers/ldap.c:1201
+#: plugins/sudoers/ldap.c:1493 plugins/sudoers/ldap.c:1653
+#: plugins/sudoers/ldap.c:1735 plugins/sudoers/ldap.c:1883
+#: plugins/sudoers/ldap.c:1907 plugins/sudoers/ldap.c:1996
+#: plugins/sudoers/ldap.c:2011 plugins/sudoers/ldap.c:2107
+#: plugins/sudoers/ldap.c:2140 plugins/sudoers/ldap.c:2220
+#: plugins/sudoers/ldap.c:2303 plugins/sudoers/ldap.c:2400
+#: plugins/sudoers/ldap.c:3235 plugins/sudoers/ldap.c:3267
+#: plugins/sudoers/ldap.c:3579 plugins/sudoers/ldap.c:3606
+#: plugins/sudoers/ldap.c:3622 plugins/sudoers/ldap.c:3713
+#: plugins/sudoers/ldap.c:3729 plugins/sudoers/linux_audit.c:76
+#: plugins/sudoers/logging.c:190 plugins/sudoers/logging.c:501
+#: plugins/sudoers/logging.c:522 plugins/sudoers/logging.c:562
+#: plugins/sudoers/logging.c:998 plugins/sudoers/match.c:616
+#: plugins/sudoers/match.c:663 plugins/sudoers/match.c:714
+#: plugins/sudoers/match.c:738 plugins/sudoers/match.c:826
+#: plugins/sudoers/match.c:914 plugins/sudoers/parse.c:252
+#: plugins/sudoers/parse.c:264 plugins/sudoers/parse.c:279
+#: plugins/sudoers/parse.c:291 plugins/sudoers/policy.c:128
+#: plugins/sudoers/policy.c:137 plugins/sudoers/policy.c:146
+#: plugins/sudoers/policy.c:172 plugins/sudoers/policy.c:299
+#: plugins/sudoers/policy.c:314 plugins/sudoers/policy.c:316
+#: plugins/sudoers/policy.c:342 plugins/sudoers/policy.c:352
+#: plugins/sudoers/policy.c:396 plugins/sudoers/policy.c:406
+#: plugins/sudoers/policy.c:415 plugins/sudoers/policy.c:424
+#: plugins/sudoers/policy.c:498 plugins/sudoers/policy.c:735
+#: plugins/sudoers/prompt.c:93 plugins/sudoers/pwutil.c:165
+#: plugins/sudoers/pwutil.c:236 plugins/sudoers/pwutil.c:312
+#: plugins/sudoers/pwutil.c:486 plugins/sudoers/pwutil.c:551
+#: plugins/sudoers/pwutil.c:620 plugins/sudoers/pwutil.c:778
+#: plugins/sudoers/pwutil.c:835 plugins/sudoers/pwutil.c:880
+#: plugins/sudoers/pwutil.c:938 plugins/sudoers/set_perms.c:387
+#: plugins/sudoers/set_perms.c:766 plugins/sudoers/set_perms.c:1150
+#: plugins/sudoers/set_perms.c:1476 plugins/sudoers/set_perms.c:1641
+#: plugins/sudoers/sssd.c:162 plugins/sudoers/sssd.c:194
+#: plugins/sudoers/sssd.c:237 plugins/sudoers/sssd.c:244
+#: plugins/sudoers/sssd.c:280 plugins/sudoers/sssd.c:352
+#: plugins/sudoers/sssd.c:392 plugins/sudoers/sssd.c:1073
+#: plugins/sudoers/sssd.c:1251 plugins/sudoers/sssd.c:1266
+#: plugins/sudoers/sssd.c:1282 plugins/sudoers/sudoers.c:263
+#: plugins/sudoers/sudoers.c:273 plugins/sudoers/sudoers.c:281
+#: plugins/sudoers/sudoers.c:365 plugins/sudoers/sudoers.c:682
+#: plugins/sudoers/sudoers.c:807 plugins/sudoers/sudoers.c:851
+#: plugins/sudoers/sudoers.c:1123 plugins/sudoers/sudoers_debug.c:106
+#: plugins/sudoers/sudoreplay.c:1254 plugins/sudoers/sudoreplay.c:1366
+#: plugins/sudoers/sudoreplay.c:1406 plugins/sudoers/sudoreplay.c:1415
+#: plugins/sudoers/sudoreplay.c:1425 plugins/sudoers/sudoreplay.c:1433
+#: plugins/sudoers/sudoreplay.c:1437 plugins/sudoers/sudoreplay.c:1593
+#: plugins/sudoers/sudoreplay.c:1597 plugins/sudoers/testsudoers.c:131
+#: plugins/sudoers/testsudoers.c:217 plugins/sudoers/testsudoers.c:234
+#: plugins/sudoers/timestamp.c:397 plugins/sudoers/timestamp.c:441
+#: plugins/sudoers/timestamp.c:868 plugins/sudoers/toke_util.c:56
+#: plugins/sudoers/toke_util.c:109 plugins/sudoers/toke_util.c:146
+#: plugins/sudoers/visudo.c:153 plugins/sudoers/visudo.c:309
+#: plugins/sudoers/visudo.c:315 plugins/sudoers/visudo.c:446
+#: plugins/sudoers/visudo.c:624 plugins/sudoers/visudo.c:985
+#: plugins/sudoers/visudo.c:1051 plugins/sudoers/visudo.c:1095
+#: plugins/sudoers/visudo.c:1197 plugins/sudoers/visudo_json.c:1025 toke.l:849
+#: toke.l:949 toke.l:1106
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: plugins/sudoers/alias.c:135
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "A(z) „%s” álnév már meg van határozva"
+
+#: plugins/sudoers/auth/bsdauth.c:68
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "a bejelentkezési osztály lekérése sikertelen ennél a felhasználónál: %s"
+
+#: plugins/sudoers/auth/bsdauth.c:73
+msgid "unable to begin bsd authentication"
+msgstr "a BSD hitelesítés elkezdése sikertelen"
+
+#: plugins/sudoers/auth/bsdauth.c:81
+msgid "invalid authentication type"
+msgstr "érvénytelen hitelesítési típus"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to initialize BSD authentication"
+msgstr "a BSD hitelesítés előkészítése sikertelen"
+
+#: plugins/sudoers/auth/fwtk.c:52
+msgid "unable to read fwtk config"
+msgstr "az fwtk beállítás olvasása sikertelen"
+
+#: plugins/sudoers/auth/fwtk.c:57
+msgid "unable to connect to authentication server"
+msgstr "a hitelesítési kiszolgálóhoz való kapcsolódás sikertelen"
+
+#: plugins/sudoers/auth/fwtk.c:63 plugins/sudoers/auth/fwtk.c:87
+#: plugins/sudoers/auth/fwtk.c:121
+msgid "lost connection to authentication server"
+msgstr "a kapcsolat megszakadt a hitelesítési kiszolgálóval"
+
+#: plugins/sudoers/auth/fwtk.c:67
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"hitelesítési kiszolgáló hiba:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:111
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: az elsődleges átalakítása karakterláncra („%s”) sikertelen: %s"
+
+#: plugins/sudoers/auth/kerb5.c:161
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: „%s” feldolgozása sikertelen: %s"
+
+#: plugins/sudoers/auth/kerb5.c:170
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: a hitelesítési adatok gyorsítótárának feloldása sikertelen: %s"
+
+#: plugins/sudoers/auth/kerb5.c:217
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: a kapcsolók lefoglalása sikertelen: %s"
+
+#: plugins/sudoers/auth/kerb5.c:232
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: a hitelesítési adatok lekérése sikertelen: %s"
+
+#: plugins/sudoers/auth/kerb5.c:245
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: a hitelesítési adatok gyorsítótárának előkészítése sikertelen: %s"
+
+#: plugins/sudoers/auth/kerb5.c:248
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: a hitelesítési adatok gyorsítótárban való tárolósa sikertelen: %s"
+
+#: plugins/sudoers/auth/kerb5.c:312
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: az elsődleges gép lekérése sikertelen: %s"
+
+#: plugins/sudoers/auth/kerb5.c:326
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: a TGT nem ellenőrizhető! Lehetséges támadás! %s"
+
+#: plugins/sudoers/auth/pam.c:108
+msgid "unable to initialize PAM"
+msgstr "a PAM előkészítése sikertelen"
+
+#: plugins/sudoers/auth/pam.c:194
+msgid "account validation failure, is your account locked?"
+msgstr "fiókellenőrzési hiba, a fiókja zárolva van?"
+
+#: plugins/sudoers/auth/pam.c:198
+msgid "Account or password is expired, reset your password and try again"
+msgstr "A fiók vagy a jelszó lejárt, állítsa vissza a jelszavát, és próbálja újra"
+
+#: plugins/sudoers/auth/pam.c:206
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "a lejárt jelszó megváltoztatása sikertelen: %s"
+
+#: plugins/sudoers/auth/pam.c:211
+msgid "Password expired, contact your system administrator"
+msgstr "A jelszó lejárt, vegye fel a kapcsolatot a rendszergazdával"
+
+#: plugins/sudoers/auth/pam.c:215
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "A fiók lejárt vagy a PAM beállításból hiányzik egy „account” szakasz a sudo számára, vegye fel a kapcsolatot a rendszergazdával"
+
+#: plugins/sudoers/auth/pam.c:229
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "PAM hitelesítési hiba: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:97 plugins/sudoers/visudo.c:227
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "Ön nem létezik a(z) %s adatbázisban"
+
+#: plugins/sudoers/auth/securid5.c:73
+msgid "failed to initialise the ACE API library"
+msgstr "nem sikerült előkészíteni az ACE API programkönyvtárat"
+
+#: plugins/sudoers/auth/securid5.c:99
+msgid "unable to contact the SecurID server"
+msgstr "a SecurID kiszolgálóhoz való kapcsolódás sikertelen"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "User ID locked for SecurID Authentication"
+msgstr "A felhasználó-azonosító zárolva van a SecurID hitelesítéshez"
+
+#: plugins/sudoers/auth/securid5.c:112 plugins/sudoers/auth/securid5.c:163
+msgid "invalid username length for SecurID"
+msgstr "érvénytelen felhasználónév hossz a SecurID-nál"
+
+#: plugins/sudoers/auth/securid5.c:116 plugins/sudoers/auth/securid5.c:168
+msgid "invalid Authentication Handle for SecurID"
+msgstr "érvénytelen hitelesítéskezelés a SecurID-nál"
+
+#: plugins/sudoers/auth/securid5.c:120
+msgid "SecurID communication failed"
+msgstr "a SecurID kommunikáció meghiúsult"
+
+#: plugins/sudoers/auth/securid5.c:124 plugins/sudoers/auth/securid5.c:213
+msgid "unknown SecurID error"
+msgstr "ismeretlen SecurID hiba"
+
+#: plugins/sudoers/auth/securid5.c:158
+msgid "invalid passcode length for SecurID"
+msgstr "érvénytelen jelkód hossz a SecurID-nál"
+
+#: plugins/sudoers/auth/sia.c:69 plugins/sudoers/auth/sia.c:125
+msgid "unable to initialize SIA session"
+msgstr "a SIA munkamenet előkészítése sikertelen"
+
+#: plugins/sudoers/auth/sudo_auth.c:126
+msgid "invalid authentication methods"
+msgstr "érvénytelen hitelesítési módszerek"
+
+#: plugins/sudoers/auth/sudo_auth.c:128
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Érvénytelen hitelesítési módszerek lettek belefordítva a sudo programba! Nem keverheti az önálló és a nem önálló hitelesítéseket."
+
+#: plugins/sudoers/auth/sudo_auth.c:224 plugins/sudoers/auth/sudo_auth.c:274
+msgid "no authentication methods"
+msgstr "nincsenek hitelesítési módszerek"
+
+#: plugins/sudoers/auth/sudo_auth.c:226
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Nincsenek hitelesítési módszerek belefordítva a sudo programba! Ha ki szeretné kapcsolni a hitelesítést, akkor használja a --disable-authentication konfigurációs kapcsolót."
+
+#: plugins/sudoers/auth/sudo_auth.c:276
+msgid "Unable to initialize authentication methods."
+msgstr "A hitelesítési módszerek előkészítése sikertelen."
+
+#: plugins/sudoers/auth/sudo_auth.c:441
+msgid "Authentication methods:"
+msgstr "Hitelesítési módszerek:"
+
+#: plugins/sudoers/bsm_audit.c:120 plugins/sudoers/bsm_audit.c:211
+msgid "Could not determine audit condition"
+msgstr "Nem sikerült meghatározni a felülvizsgálati feltételt"
+
+#: plugins/sudoers/bsm_audit.c:183 plugins/sudoers/bsm_audit.c:273
+msgid "unable to commit audit record"
+msgstr "a felülvizsgálati rekord véglegesítése sikertelen"
+
+#: plugins/sudoers/check.c:259
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Bízunk benne, hogy megkapta a szokásos tudnivalókat a helyi\n"
+"rendszergazdától. Általában a következő három dolog lényeges:\n"
+"\n"
+" #1) Tartsa tiszteletben mások személyiségi jogait.\n"
+" #2) Gondolkodjon gépelés előtt.\n"
+" #3) A nagy erő nagy felelősséggel jár.\n"
+"\n"
+
+#: plugins/sudoers/check.c:302 plugins/sudoers/check.c:312
+#: plugins/sudoers/sudoers.c:725 plugins/sudoers/sudoers.c:770
+#, c-format
+msgid "unknown uid: %u"
+msgstr "ismeretlen uid: %u"
+
+#: plugins/sudoers/check.c:307 plugins/sudoers/iolog.c:260
+#: plugins/sudoers/policy.c:908 plugins/sudoers/sudoers.c:1162
+#: plugins/sudoers/testsudoers.c:208 plugins/sudoers/testsudoers.c:366
+#, c-format
+msgid "unknown user: %s"
+msgstr "ismeretlen felhasználó: %s"
+
+#: plugins/sudoers/def_data.c:41
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Syslog képesség, ha a syslog programot használják naplózáshoz: %s"
+
+#: plugins/sudoers/def_data.c:45
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "A használandó syslog prioritás, amikor a felhasználó sikeresen hitelesíti magát: %s"
+
+#: plugins/sudoers/def_data.c:49
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "A használandó syslog prioritás, amikor a felhasználó sikertelenül hitelesíti magát: %s"
+
+#: plugins/sudoers/def_data.c:53
+msgid "Put OTP prompt on its own line"
+msgstr "Az OTP kérdés elhelyezés a saját sorába"
+
+#: plugins/sudoers/def_data.c:57
+msgid "Ignore '.' in $PATH"
+msgstr "A „.” figyelmen kívül hagyása a $PATH változóban"
+
+#: plugins/sudoers/def_data.c:61
+msgid "Always send mail when sudo is run"
+msgstr "Mindig küldjön levelet, amikor a sudo fut"
+
+#: plugins/sudoers/def_data.c:65
+msgid "Send mail if user authentication fails"
+msgstr "Levél küldése, ha a felhasználó-hitelesítés sikertelen"
+
+#: plugins/sudoers/def_data.c:69
+msgid "Send mail if the user is not in sudoers"
+msgstr "Levél küldése, ha a felhasználó nincs a sudoers fájlban"
+
+#: plugins/sudoers/def_data.c:73
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Levél küldése, ha a felhasználó nincs a sudoers fájlban ennél a gépnél"
+
+#: plugins/sudoers/def_data.c:77
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Levél küldése, ha a felhasználónak nem engedélyezett egy parancs futtatása"
+
+#: plugins/sudoers/def_data.c:81
+msgid "Send mail if the user tries to run a command"
+msgstr "Levél küldése, ha a felhasználó megpróbál egy parancsot futtatni"
+
+#: plugins/sudoers/def_data.c:85
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Különálló időbélyeg használata minden felhasználó/tty párosnál"
+
+#: plugins/sudoers/def_data.c:89
+msgid "Lecture user the first time they run sudo"
+msgstr "Felhasználó oktatása a sudo első alkalommal történő futtatásakor"
+
+#: plugins/sudoers/def_data.c:93
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "A sudo oktatóanyagot tartalmazó fájl: %s"
+
+#: plugins/sudoers/def_data.c:97
+msgid "Require users to authenticate by default"
+msgstr "Felhasználók hitelesítésének megkövetelése alapértelmezetten"
+
+#: plugins/sudoers/def_data.c:101
+msgid "Root may run sudo"
+msgstr "A rendszergazda futtathatja a sudo programot"
+
+#: plugins/sudoers/def_data.c:105
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "A gépnév naplózása a (nem syslog) naplófájlba"
+
+#: plugins/sudoers/def_data.c:109
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Az év naplózása a (nem syslog) naplófájlba"
+
+#: plugins/sudoers/def_data.c:113
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Ha a sudo programot argumentumok nélkül hívják meg, akkor indítson egy parancsértelmezőt"
+
+#: plugins/sudoers/def_data.c:117
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "A $HOME beállítása a célfelhasználóra, amikor a -s kapcsolóval indít egy parancsértelmezőt"
+
+#: plugins/sudoers/def_data.c:121
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Mindig állítsa be a $HOME értékét a célfelhasználó saját könyvtárára"
+
+#: plugins/sudoers/def_data.c:125
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Néhány információ begyűjtésének engedélyezése hasznos hibaüzenetek adásához"
+
+#: plugins/sudoers/def_data.c:129
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Teljes képzésű gépnevek megkövetelése a sudoers fájlban"
+
+#: plugins/sudoers/def_data.c:133
+msgid "Insult the user when they enter an incorrect password"
+msgstr "A felhasználó piszkálása, amikor helytelen jelszót ad meg"
+
+#: plugins/sudoers/def_data.c:137
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Csak akkor engedélyezze a sudo futtatását a felhasználónak, ha rendelkezik tty-nal"
+
+#: plugins/sudoers/def_data.c:141
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "A visudo el fogja fogadni az EDITOR környezeti változót"
+
+#: plugins/sudoers/def_data.c:145
+msgid "Prompt for root's password, not the users's"
+msgstr "A rendszergazda jelszavának bekérése, nem a felhasználóénak"
+
+#: plugins/sudoers/def_data.c:149
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "A runas_default felhasználó jelszavának bekérése, nem a felhasználóénak"
+
+#: plugins/sudoers/def_data.c:153
+msgid "Prompt for the target user's password, not the users's"
+msgstr "A célfelhasználó jelszavának bekérése, nem a felhasználóénak"
+
+#: plugins/sudoers/def_data.c:157
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Alapértelmezések alkalmazása a célfelhasználó bejelentkezési osztályán, ha van ilyen"
+
+#: plugins/sudoers/def_data.c:161
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "A LOGNAME és a USER környezeti változók beállítása"
+
+#: plugins/sudoers/def_data.c:165
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Csak a tényleges uid beállítása a célfelhasználóra, nem a valódi uid értékének"
+
+#: plugins/sudoers/def_data.c:169
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Ne készítse elő a csoportvektort a célfelhasználóéra"
+
+#: plugins/sudoers/def_data.c:173
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "A hossz, amelyre a naplófájl sorait tördelni kell (0 esetén nincs tördelés): %u"
+
+#: plugins/sudoers/def_data.c:177
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Hitelesítési időbélyeg időkorlát: %.1f perc"
+
+#: plugins/sudoers/def_data.c:181
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Jelszóbekérési időkorlát: %.1f perc"
+
+#: plugins/sudoers/def_data.c:185
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Egy jelszómegadás kísérleteinek száma: %u"
+
+#: plugins/sudoers/def_data.c:189
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "A használandó umask vagy 0777 a felhasználóé használatához: 0%o"
+
+#: plugins/sudoers/def_data.c:193
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Útvonal a naplófájlhoz: %s"
+
+#: plugins/sudoers/def_data.c:197
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Útvonal a levelezőprogramhoz: %s"
+
+#: plugins/sudoers/def_data.c:201
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Jelzők a levelezőprogramhoz: %s"
+
+#: plugins/sudoers/def_data.c:205
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "A cím, amelyre a levelet küldeni kell: %s"
+
+#: plugins/sudoers/def_data.c:209
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "A cím, amelyről a levelet küldeni kell: %s"
+
+#: plugins/sudoers/def_data.c:213
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Tárgysor a levél üzeneteihez: %s"
+
+#: plugins/sudoers/def_data.c:217
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Helytelen jelszó üzenet: %s"
+
+#: plugins/sudoers/def_data.c:221
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Útvonal az oktatóanyag állapot könyvtárához: %s"
+
+#: plugins/sudoers/def_data.c:225
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Útvonal a hitelesítési időbélyeg könyvtárához: %s"
+
+#: plugins/sudoers/def_data.c:229
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "A hitelesítési időbélyeg könyvtárának tulajdonosa: %s"
+
+#: plugins/sudoers/def_data.c:233
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Az ebben a csoportban lévő felhasználók mentesülnek a jelszó és PATH követelmények alól: %s"
+
+#: plugins/sudoers/def_data.c:237
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Alapértelmezett jelszóbekérés: %s"
+
+#: plugins/sudoers/def_data.c:241
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Ha be van állítva, akkor a jelszóbekérés minden esetben felül fogja bírálni a rendszer bekéréseit."
+
+#: plugins/sudoers/def_data.c:245
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Alapértelmezett felhasználó a parancsok futtatásához másként: %s"
+
+#: plugins/sudoers/def_data.c:249
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Érték a felhasználó $PATH változójának felülbírálásához ezzel: %s"
+
+#: plugins/sudoers/def_data.c:253
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Útvonal a visudo által használt szerkesztőhöz: %s"
+
+#: plugins/sudoers/def_data.c:257
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Mikor szükséges jelszó a „list” álparancshoz: %s"
+
+#: plugins/sudoers/def_data.c:261
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Mikor szükséges jelszó a „verify” álparancshoz: %s"
+
+#: plugins/sudoers/def_data.c:265
+msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+msgstr "A sudo_noexec programkönyvtárban található üres végrehajtási függvények előtöltése"
+
+#: plugins/sudoers/def_data.c:269
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Ha az LDAP könyvtár be van kapcsolva, akkor mellőzzük-e a helyi sodoers fájlt"
+
+#: plugins/sudoers/def_data.c:273
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "A fájlleírók >= %d le lesznek zárva a parancs végrehajtása előtt"
+
+#: plugins/sudoers/def_data.c:277
+msgid "If set, users may override the value of `closefrom' with the -C option"
+msgstr "Ha be van állítva, akkor a felhasználók felülbírálhatják a „closefrom” értékét a -C kapcsolóval"
+
+#: plugins/sudoers/def_data.c:281
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Lehetővé teszi a felhasználóknak tetszőleges környezeti változók beállítását"
+
+#: plugins/sudoers/def_data.c:285
+msgid "Reset the environment to a default set of variables"
+msgstr "A környezet visszaállítása egy alapértelmezett változókészletre"
+
+#: plugins/sudoers/def_data.c:289
+msgid "Environment variables to check for sanity:"
+msgstr "Környezeti változók az épség ellenőrzéséhez:"
+
+#: plugins/sudoers/def_data.c:293
+msgid "Environment variables to remove:"
+msgstr "Eltávolítandó környezeti változók:"
+
+#: plugins/sudoers/def_data.c:297
+msgid "Environment variables to preserve:"
+msgstr "Megőrzendő környezeti változók:"
+
+#: plugins/sudoers/def_data.c:301
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "Az új biztonsági környezetben használandó SELinux szerep: %s"
+
+#: plugins/sudoers/def_data.c:305
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "Az új biztonsági környezetben használandó SELinux típus: %s"
+
+#: plugins/sudoers/def_data.c:309
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Útvonal a sudo specifikus környezeti fájlhoz: %s"
+
+#: plugins/sudoers/def_data.c:313
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Útvonal a korlátozott sudo specifikus környezeti fájlhoz: %s"
+
+#: plugins/sudoers/def_data.c:317
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "A sudoers feldolgozásakor használandó területi beállítás: %s"
+
+#: plugins/sudoers/def_data.c:321
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Lehetővé tenni a sudo számára egy jelszó bekérését akkor is, ha látható lesz"
+
+#: plugins/sudoers/def_data.c:325
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Látható visszajelzés nyújtása a jelszóbekérésnél, amikor felhasználói bevitel van"
+
+#: plugins/sudoers/def_data.c:329
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Gyorsabb mintaillesztés használata, ami kevésbé pontos, de nem fér hozzá a fájlrendszerhez"
+
+#: plugins/sudoers/def_data.c:333
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "A sudoers fájlban megadott umask felül fogja bírálni a felhasználóét akkor is, ha az engedékenyebb"
+
+#: plugins/sudoers/def_data.c:337
+msgid "Log user's input for the command being run"
+msgstr "A futtatott parancs felhasználói bevitelének naplózása"
+
+#: plugins/sudoers/def_data.c:341
+msgid "Log the output of the command being run"
+msgstr "A futtatott parancs kimenetének naplózása"
+
+#: plugins/sudoers/def_data.c:345
+msgid "Compress I/O logs using zlib"
+msgstr "I/O naplók tömörítése zlib használatával"
+
+#: plugins/sudoers/def_data.c:349
+msgid "Always run commands in a pseudo-tty"
+msgstr "A parancsokat mindig egy ál-tty-ban futtassa"
+
+#: plugins/sudoers/def_data.c:353
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Bővítmény a nem Unix csoport támogatáshoz: %s"
+
+#: plugins/sudoers/def_data.c:357
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "A könyvtár, amelyben a bemeneti/kimeneti naplók tárolva lesznek: %s"
+
+#: plugins/sudoers/def_data.c:361
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "A fájl, amelyben a bemeneti/kimeneti napló tárolva lesz: %s"
+
+#: plugins/sudoers/def_data.c:365
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Bejegyzés hozzáadása az utmp/utmpx fájlhoz egy pty lefoglalásakor"
+
+#: plugins/sudoers/def_data.c:369
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Az utmp-ben lévő felhasználó beállítása a runas felhasználóra, nem a meghívó felhasználóra"
+
+#: plugins/sudoers/def_data.c:373
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Engedélyezett jogosultságok halmaza: %s"
+
+#: plugins/sudoers/def_data.c:377
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Korlátozott jogosultságok halmaza: %s"
+
+#: plugins/sudoers/def_data.c:381
+msgid "Run commands on a pty in the background"
+msgstr "Parancsok futtatása egy pty-on a háttérben"
+
+#: plugins/sudoers/def_data.c:385
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "A használandó PAM szolgáltatás neve: %s"
+
+#: plugins/sudoers/def_data.c:389
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "A bejelentkezési parancsértelmezőkhöz használandó PAM szolgáltatás neve: %s"
+
+#: plugins/sudoers/def_data.c:393
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "PAM hitelesítési adatok kiépítésének kísérlete a célfelhasználónál"
+
+#: plugins/sudoers/def_data.c:397
+msgid "Create a new PAM session for the command to run in"
+msgstr "Új PAM munkamenet létrehozása annál a parancsnál, amelyben fut"
+
+#: plugins/sudoers/def_data.c:401
+#, c-format
+msgid "Maximum I/O log sequence number: %u"
+msgstr "Legnagyobb I/O napló sorozatszáma: %u"
+
+#: plugins/sudoers/def_data.c:405
+msgid "Enable sudoers netgroup support"
+msgstr "A sudoers netgroup támogatásának engedélyezése"
+
+#: plugins/sudoers/def_data.c:409
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "A szülőkönyvtárak írhatóságának ellenőrzése a sudoedit programmal történő fájlszerkesztéskor"
+
+#: plugins/sudoers/def_data.c:413
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Szimbolikus linkek követése a sudoedit programmal történő fájlszerkesztéskor"
+
+#: plugins/sudoers/def_data.c:417
+msgid "Query the group plugin for unknown system groups"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:421
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:425
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:429
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:433
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:437
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:441
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:445
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:449
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:453
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:457
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:461
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:465
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:469
+msgid "Allow the user to specify a timeout on the command line"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:473
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:477
+msgid "Include the process ID when logging via syslog"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:481
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:485
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:221
+#, c-format
+msgid "%s:%d unknown defaults entry \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:224
+#, c-format
+msgid "%s: unknown defaults entry \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:267
+#, c-format
+msgid "%s:%d no value specified for \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:270
+#, c-format
+msgid "%s: no value specified for \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:290
+#, c-format
+msgid "%s:%d values for \"%s\" must start with a '/'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:293
+#, c-format
+msgid "%s: values for \"%s\" must start with a '/'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:318
+#, c-format
+msgid "%s:%d option \"%s\" does not take a value"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:321
+#, c-format
+msgid "%s: option \"%s\" does not take a value"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:343
+#, c-format
+msgid "%s:%d invalid Defaults type 0x%x for option \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:346
+#, c-format
+msgid "%s: invalid Defaults type 0x%x for option \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:356
+#, c-format
+msgid "%s:%d value \"%s\" is invalid for option \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:359
+#, c-format
+msgid "%s: value \"%s\" is invalid for option \"%s\""
+msgstr ""
+
+#: plugins/sudoers/env.c:295 plugins/sudoers/env.c:302
+#: plugins/sudoers/env.c:407 plugins/sudoers/ldap.c:453
+#: plugins/sudoers/ldap.c:543 plugins/sudoers/ldap.c:1270
+#: plugins/sudoers/ldap.c:1497 plugins/sudoers/ldap.c:1822
+#: plugins/sudoers/linux_audit.c:82 plugins/sudoers/logging.c:1003
+#: plugins/sudoers/policy.c:619 plugins/sudoers/policy.c:629
+#: plugins/sudoers/prompt.c:161 plugins/sudoers/sudoers.c:873
+#: plugins/sudoers/testsudoers.c:238 plugins/sudoers/toke_util.c:158
+#, c-format
+msgid "internal error, %s overflow"
+msgstr ""
+
+#: plugins/sudoers/env.c:376
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr ""
+
+#: plugins/sudoers/env.c:1055
+msgid "unable to rebuild the environment"
+msgstr ""
+
+#: plugins/sudoers/env.c:1129
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr ""
+
+#: plugins/sudoers/filedigest.c:104 plugins/sudoers/filedigest_gcrypt.c:66
+#: plugins/sudoers/filedigest_openssl.c:95
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr ""
+
+#: plugins/sudoers/filedigest.c:129 plugins/sudoers/filedigest_gcrypt.c:98
+#: plugins/sudoers/filedigest_openssl.c:120
+#, c-format
+msgid "%s: read error"
+msgstr "%s: olvasási hiba"
+
+#: plugins/sudoers/group_plugin.c:86
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s a(z) %d uid tulajdona kell legyen"
+
+#: plugins/sudoers/group_plugin.c:90
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr "%s csak a tulajdonos által írható lehet"
+
+#: plugins/sudoers/group_plugin.c:98 plugins/sudoers/sssd.c:400
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "a(z) %s nem tölthető be: %s"
+
+#: plugins/sudoers/group_plugin.c:104
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "nem található a „group_plugin” szimbólum ebben: %s"
+
+#: plugins/sudoers/group_plugin.c:109
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:79 plugins/sudoers/interfaces.c:96
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:84 plugins/sudoers/interfaces.c:101
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:129
+msgid "Local IP address and netmask pairs:\n"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:121 plugins/sudoers/mkdir_parents.c:75
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:146 plugins/sudoers/iolog.c:187
+#: plugins/sudoers/mkdir_parents.c:64 plugins/sudoers/timestamp.c:175
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "%s könyvtár létrehozása sikertelen"
+
+#: plugins/sudoers/iolog.c:191 plugins/sudoers/visudo.c:740
+#: plugins/sudoers/visudo.c:750
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "nem lehet a(z) %s módját megváltoztatni erre: 0%o"
+
+#: plugins/sudoers/iolog.c:299 plugins/sudoers/sudoers.c:1193
+#: plugins/sudoers/testsudoers.c:390
+#, c-format
+msgid "unknown group: %s"
+msgstr "ismeretlen csoport: %s"
+
+#: plugins/sudoers/iolog.c:418 plugins/sudoers/sudoers.c:929
+#: plugins/sudoers/sudoreplay.c:349 plugins/sudoers/sudoreplay.c:1355
+#: plugins/sudoers/sudoreplay.c:1559 plugins/sudoers/timestamp.c:406
+#: plugins/sudoers/visudo.c:972 plugins/sudoers/visudo_json.c:1001
+#: plugins/sudoers/visudo_json.c:1014
+#, c-format
+msgid "unable to open %s"
+msgstr "%s nem nyitható meg"
+
+#: plugins/sudoers/iolog.c:469 plugins/sudoers/sudoers.c:933
+#: plugins/sudoers/sudoreplay.c:857 plugins/sudoers/sudoreplay.c:1670
+#, c-format
+msgid "unable to read %s"
+msgstr "%s nem olvasható"
+
+#: plugins/sudoers/iolog.c:505 plugins/sudoers/sudoreplay.c:1124
+#: plugins/sudoers/timestamp.c:295 plugins/sudoers/timestamp.c:298
+#, c-format
+msgid "unable to write to %s"
+msgstr "az írás sikertelen ebbe: %s"
+
+#: plugins/sudoers/iolog.c:584 plugins/sudoers/iolog.c:803
+#, c-format
+msgid "unable to create %s"
+msgstr "%s létrehozása sikertelen"
+
+#: plugins/sudoers/iolog.c:1035 plugins/sudoers/iolog.c:1110
+#: plugins/sudoers/iolog.c:1191
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:1069
+#, c-format
+msgid "%s: internal error, file index %d not open"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:431
+msgid "sudo_ldap_conf_add_ports: port too large"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:491
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:518
+msgid "unable to mix ldap and ldaps URIs"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:522 plugins/sudoers/ldap.c:559
+msgid "starttls not supported when using ldaps"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:630
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:633
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1256
+msgid "unable to get GMT time"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1262
+msgid "unable to format timestamp"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1986
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2559
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2561
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: UNKNOWN\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2617
+#, c-format
+msgid " Order: %s\n"
+msgstr " Sorrend: %s\n"
+
+#: plugins/sudoers/ldap.c:2625 plugins/sudoers/parse.c:618
+#: plugins/sudoers/sssd.c:1647
+#, c-format
+msgid " Commands:\n"
+msgstr " Parancsok:\n"
+
+#: plugins/sudoers/ldap.c:3187
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:3223
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:3475
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr ""
+
+#: plugins/sudoers/linux_audit.c:52
+msgid "unable to open audit system"
+msgstr ""
+
+#: plugins/sudoers/linux_audit.c:93
+msgid "unable to send audit message"
+msgstr ""
+
+#: plugins/sudoers/logging.c:108
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: plugins/sudoers/logging.c:136
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (parancs folytatása) %s"
+
+#: plugins/sudoers/logging.c:165
+#, c-format
+msgid "unable to open log file: %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:173
+#, c-format
+msgid "unable to lock log file: %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:206
+#, c-format
+msgid "unable to write log file: %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:235
+msgid "No user or host"
+msgstr "Nem felhasználó vagy gép"
+
+#: plugins/sudoers/logging.c:237
+msgid "validation failure"
+msgstr "érvényesítési hiba"
+
+#: plugins/sudoers/logging.c:244
+msgid "user NOT in sudoers"
+msgstr "a felhasználó NINCS a sudoers-ben"
+
+#: plugins/sudoers/logging.c:246
+msgid "user NOT authorized on host"
+msgstr "a felhasználó NINCS felhatalmazva a gépen"
+
+#: plugins/sudoers/logging.c:248
+msgid "command not allowed"
+msgstr "a parancs nem engedélyezett"
+
+#: plugins/sudoers/logging.c:283
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr "%s nincs a sudoers fájlban. Ez az eset jelentésre kerül.\n"
+
+#: plugins/sudoers/logging.c:286
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr "%s nem futtathatja a sudo-t ezen: %s. Ez az eset jelentésre kerül.\n"
+
+#: plugins/sudoers/logging.c:290
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Elnézést, %s felhasználó nem futtathatja a sudo-t ezen: %s.\n"
+
+#: plugins/sudoers/logging.c:293
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:330 plugins/sudoers/sudoers.c:473
+#: plugins/sudoers/sudoers.c:475 plugins/sudoers/sudoers.c:477
+#: plugins/sudoers/sudoers.c:479 plugins/sudoers/sudoers.c:1298
+#: plugins/sudoers/sudoers.c:1300
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: parancs nem található"
+
+#: plugins/sudoers/logging.c:332 plugins/sudoers/sudoers.c:469
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+
+#: plugins/sudoers/logging.c:349
+msgid "authentication failure"
+msgstr "hitelesítési hiba"
+
+#: plugins/sudoers/logging.c:375
+msgid "a password is required"
+msgstr "jelszó szükséges"
+
+#: plugins/sudoers/logging.c:438
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u helytelen jelszópróbálkozás"
+msgstr[1] "%u helytelen jelszópróbálkozás"
+
+#: plugins/sudoers/logging.c:654
+msgid "unable to fork"
+msgstr ""
+
+#: plugins/sudoers/logging.c:662 plugins/sudoers/logging.c:714
+#, c-format
+msgid "unable to fork: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:704
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:729
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:767
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr ""
+
+#: plugins/sudoers/match.c:771
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr ""
+
+#: plugins/sudoers/mkdir_parents.c:70 plugins/sudoers/sudoers.c:944
+#: plugins/sudoers/visudo.c:439 plugins/sudoers/visudo.c:734
+#, c-format
+msgid "unable to stat %s"
+msgstr "%s nem érhető el"
+
+#: plugins/sudoers/parse.c:115
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr ""
+
+#: plugins/sudoers/parse.c:118
+#, c-format
+msgid "parse error in %s"
+msgstr ""
+
+#: plugins/sudoers/parse.c:544
+#, c-format
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+
+#: plugins/sudoers/parse.c:545
+#, c-format
+msgid " RunAsUsers: "
+msgstr ""
+
+#: plugins/sudoers/parse.c:559
+#, c-format
+msgid " RunAsGroups: "
+msgstr ""
+
+#: plugins/sudoers/parse.c:568
+#, c-format
+msgid " Options: "
+msgstr ""
+
+#: plugins/sudoers/policy.c:84 plugins/sudoers/policy.c:110
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:289 plugins/sudoers/testsudoers.c:261
+msgid "unable to parse network address list"
+msgstr ""
+
+#: plugins/sudoers/policy.c:433
+msgid "user name not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:437
+msgid "user ID not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:441
+msgid "group ID not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:445
+msgid "host name not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:793 plugins/sudoers/visudo.c:910
+#, c-format
+msgid "unable to execute %s"
+msgstr "%s nem hajtható végre"
+
+#: plugins/sudoers/policy.c:926
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:928
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:932
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:935
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:937
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:938
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:971
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:188 plugins/sudoers/pwutil.c:206
+#, c-format
+msgid "unable to cache uid %u, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:200
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:260 plugins/sudoers/pwutil.c:277
+#: plugins/sudoers/pwutil.c:339 plugins/sudoers/pwutil.c:384
+#, c-format
+msgid "unable to cache user %s, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:272
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:503 plugins/sudoers/pwutil.c:521
+#, c-format
+msgid "unable to cache gid %u, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:515
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:569 plugins/sudoers/pwutil.c:586
+#: plugins/sudoers/pwutil.c:633 plugins/sudoers/pwutil.c:675
+#, c-format
+msgid "unable to cache group %s, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:581
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:801 plugins/sudoers/pwutil.c:853
+#: plugins/sudoers/pwutil.c:904 plugins/sudoers/pwutil.c:957
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:807 plugins/sudoers/pwutil.c:858
+#: plugins/sudoers/pwutil.c:910 plugins/sudoers/pwutil.c:962
+#, c-format
+msgid "unable to cache group list for %s, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:847
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:951
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:113 plugins/sudoers/set_perms.c:469
+#: plugins/sudoers/set_perms.c:912 plugins/sudoers/set_perms.c:1239
+#: plugins/sudoers/set_perms.c:1556
+msgid "perm stack overflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:121 plugins/sudoers/set_perms.c:400
+#: plugins/sudoers/set_perms.c:477 plugins/sudoers/set_perms.c:779
+#: plugins/sudoers/set_perms.c:920 plugins/sudoers/set_perms.c:1163
+#: plugins/sudoers/set_perms.c:1247 plugins/sudoers/set_perms.c:1489
+#: plugins/sudoers/set_perms.c:1564 plugins/sudoers/set_perms.c:1654
+msgid "perm stack underflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:180 plugins/sudoers/set_perms.c:523
+#: plugins/sudoers/set_perms.c:1298 plugins/sudoers/set_perms.c:1596
+msgid "unable to change to root gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:269 plugins/sudoers/set_perms.c:620
+#: plugins/sudoers/set_perms.c:1049 plugins/sudoers/set_perms.c:1375
+msgid "unable to change to runas gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:274 plugins/sudoers/set_perms.c:625
+#: plugins/sudoers/set_perms.c:1054 plugins/sudoers/set_perms.c:1380
+msgid "unable to set runas group vector"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:285 plugins/sudoers/set_perms.c:636
+#: plugins/sudoers/set_perms.c:1063 plugins/sudoers/set_perms.c:1389
+msgid "unable to change to runas uid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:303 plugins/sudoers/set_perms.c:654
+#: plugins/sudoers/set_perms.c:1079 plugins/sudoers/set_perms.c:1405
+msgid "unable to change to sudoers gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:387 plugins/sudoers/set_perms.c:766
+#: plugins/sudoers/set_perms.c:1150 plugins/sudoers/set_perms.c:1476
+#: plugins/sudoers/set_perms.c:1641
+msgid "too many processes"
+msgstr "túl sok folyamat"
+
+#: plugins/sudoers/solaris_audit.c:51
+msgid "unable to get current working directory"
+msgstr "az aktuális munkakönyvtár lekérése meghiúsult"
+
+#: plugins/sudoers/solaris_audit.c:59
+#, c-format
+msgid "truncated audit path user_cmnd: %s"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:66
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:115
+msgid "audit_failure message too long"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:402
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:410 plugins/sudoers/sssd.c:419
+#: plugins/sudoers/sssd.c:428 plugins/sudoers/sssd.c:437
+#: plugins/sudoers/sssd.c:446
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:1562
+#, c-format
+msgid ""
+"\n"
+"SSSD Role: %s\n"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:1567
+#, c-format
+msgid ""
+"\n"
+"SSSD Role: UNKNOWN\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:289
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:307
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:325
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:338
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:168 plugins/sudoers/testsudoers.c:247
+#: plugins/sudoers/visudo.c:233 plugins/sudoers/visudo.c:612
+#: plugins/sudoers/visudo.c:976
+msgid "unable to initialize sudoers default values"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:198 plugins/sudoers/sudoers.c:891
+msgid "problem with defaults entries"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:205
+msgid "no valid sudoers sources found, quitting"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:244
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:301
+msgid "you are not permitted to use the -C option"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:390
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:405
+msgid "no tty"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:406
+msgid "sorry, you must have a tty to run sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:468
+msgid "command in current directory"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:487
+msgid "sorry, you are not allowed set a command timeout"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:495
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:836
+msgid "command too long"
+msgstr "a parancs túl hosszú"
+
+#: plugins/sudoers/sudoers.c:948
+#, c-format
+msgid "%s is not a regular file"
+msgstr "a(z) %s nem egy szabályos fájl"
+
+#: plugins/sudoers/sudoers.c:952 plugins/sudoers/timestamp.c:222 toke.l:969
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s a(z) %u uid tulajdona, ennek kellene lennie: %u"
+
+#: plugins/sudoers/sudoers.c:956 toke.l:974
+#, c-format
+msgid "%s is world writable"
+msgstr "%s bárki számára írható"
+
+#: plugins/sudoers/sudoers.c:960 toke.l:977
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s a(z) %u gid tulajdona, ennek kellene lennie: %u"
+
+#: plugins/sudoers/sudoers.c:993
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1012
+#, c-format
+msgid "unknown login class: %s"
+msgstr "ismeretlen bejelentkezési osztály: %s"
+
+#: plugins/sudoers/sudoers.c:1095 plugins/sudoers/sudoers.c:1109
+#, c-format
+msgid "unable to resolve host %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:275
+#, c-format
+msgid "invalid filter option: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:288
+#, c-format
+msgid "invalid max wait: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:300
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:303 plugins/sudoers/visudo.c:186
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s: %s verzió\n"
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s/timing: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:341
+#, c-format
+msgid "%s/%s/timing: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:357
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:555 plugins/sudoers/sudoreplay.c:602
+#: plugins/sudoers/sudoreplay.c:805 plugins/sudoers/sudoreplay.c:895
+#: plugins/sudoers/sudoreplay.c:974 plugins/sudoers/sudoreplay.c:989
+#: plugins/sudoers/sudoreplay.c:996 plugins/sudoers/sudoreplay.c:1003
+#: plugins/sudoers/sudoreplay.c:1010 plugins/sudoers/sudoreplay.c:1017
+#: plugins/sudoers/sudoreplay.c:1163
+msgid "unable to add event to queue"
+msgstr "az esemény hozzáadása a sorhoz sikertelen"
+
+#: plugins/sudoers/sudoreplay.c:670
+msgid "unable to set tty to raw mode"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:721
+#, c-format
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:722
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:750
+msgid "Replay finished, press any key to restore the terminal."
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:783
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1197 plugins/sudoers/sudoreplay.c:1222
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1244
+msgid "unmatched ')' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1248
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1263
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s egy argumentumot igényel"
+
+#: plugins/sudoers/sudoreplay.c:1266 plugins/sudoers/sudoreplay.c:1646
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr "érvénytelen reguláris kifejezés: %s"
+
+#: plugins/sudoers/sudoreplay.c:1270
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1279
+msgid "unmatched '(' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1281
+msgid "illegal trailing \"or\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1283
+msgid "illegal trailing \"!\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1332
+#, c-format
+msgid "unknown search type %d"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1370
+#, c-format
+msgid "%s: invalid log file"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1388
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1395
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1402
+#, c-format
+msgid "%s: user field is missing"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1411
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1420
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1826
+#, c-format
+msgid "usage: %s [-hnR] [-d dir] [-m num] [-s num] ID\n"
+msgstr "használat: %s [-hnR] [-d kvt] [-m szám] [-s szám] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1829
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "használat: %s [-h] [-d kvt] -l [keresőkifejezés]\n"
+
+#: plugins/sudoers/sudoreplay.c:1838
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - sudo munkamenetek naplójának újrajátszása\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1840
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Beállítások:\n"
+" -d, --directory=kvt munkamenet-naplók könyvtárának megadása\n"
+" -f, --filter=szűrő megjelenítendő I/O típusok megadása\n"
+" -h, --help súgóüzenet megjelenítése és kilépés\n"
+" -l, --list elérhető munkamenet-azonosítók listája, elhagyható\n"
+" kifejezéssel\n"
+" -m, --max-wait=szám események közti várakozás legfeljebb ennyi másodpercig\n"
+" -s, --speed=szám kimenet felgyorsítása vagy lelassítása\n"
+" -V, --version verzióinformációk kiírása és kilépés"
+
+#: plugins/sudoers/testsudoers.c:329
+msgid "\thost unmatched"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:332
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:333
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:333
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:230
+#, c-format
+msgid "%s is group writable"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:306
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:772 plugins/sudoers/timestamp.c:839
+#: plugins/sudoers/visudo.c:500 plugins/sudoers/visudo.c:506
+msgid "unable to read the clock"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:786
+msgid "ignoring time stamp from the future"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:798
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:893
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:937 plugins/sudoers/timestamp.c:957
+#, c-format
+msgid "lecture status path too long: %s/%s"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:188
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:266 plugins/sudoers/visudo.c:667
+#, c-format
+msgid "press return to edit %s: "
+msgstr ""
+
+#: plugins/sudoers/visudo.c:331
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:349
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:459 plugins/sudoers/visudo.c:467
+msgid "write error"
+msgstr "íráshiba"
+
+#: plugins/sudoers/visudo.c:513
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:520
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:526
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:548
+#, c-format
+msgid "%s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:607
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr ""
+
+#: plugins/sudoers/visudo.c:619
+#, c-format
+msgid "unabled to parse temporary file (%s), unknown error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:656
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:736 plugins/sudoers/visudo.c:745
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:767
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:781
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:791
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:855
+msgid "What now? "
+msgstr ""
+
+#: plugins/sudoers/visudo.c:869
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:915
+#, c-format
+msgid "unable to run %s"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:945
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:952
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:981 plugins/sudoers/visudo_json.c:1021
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:997 plugins/sudoers/visudo_json.c:1032
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1000 plugins/sudoers/visudo_json.c:1035
+#, c-format
+msgid "parse error in %s\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1008 plugins/sudoers/visudo.c:1015
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1062
+#, c-format
+msgid "%s busy, try again later"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1159
+#, c-format
+msgid "Error: %s:%d cycle in %s \"%s\""
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1160
+#, c-format
+msgid "Warning: %s:%d cycle in %s \"%s\""
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1164
+#, c-format
+msgid "Error: %s:%d %s \"%s\" referenced but not defined"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1165
+#, c-format
+msgid "Warning: %s:%d %s \"%s\" referenced but not defined"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1318
+#, c-format
+msgid "Warning: %s:%d unused %s \"%s\""
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1433
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - a sudoers fájl biztonságos szerkesztése\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1435
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+" -x, --export=output_file write sudoers in JSON format to output_file"
+msgstr ""
+"\n"
+"Kapcsolók:\n"
+" -c, --check csak ellenőrzés mód\n"
+" -f, --file=sudoers a sudoers fájl helyének megadása\n"
+" -h, --help súgóüzenet megjelenítése és kilépés\n"
+" -q, --quiet kevésbé részletes (csendes) szintaktikai hiba\n"
+" üzenetek\n"
+" -s, --strict szigorú szintaxis-ellenőrzés\n"
+" -V, --version verzióinformációk kiírása és kilépés\n"
+" -x, --export=KIMENETIFÁJL a sudoers kiírása JSON formátumban a\n"
+" KIMENETIFÁJLBA"
+
+#: plugins/sudoers/visudo_json.c:616 plugins/sudoers/visudo_json.c:651
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr ""
+
+#: plugins/sudoers/visudo_json.c:1007
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr ""
+
+#: toke.l:943
+msgid "too many levels of includes"
+msgstr ""
diff --git a/plugins/sudoers/po/it.mo b/plugins/sudoers/po/it.mo
new file mode 100644
index 0000000..0da45c8
--- /dev/null
+++ b/plugins/sudoers/po/it.mo
Binary files differ
diff --git a/plugins/sudoers/po/it.po b/plugins/sudoers/po/it.po
new file mode 100644
index 0000000..c665717
--- /dev/null
+++ b/plugins/sudoers/po/it.po
@@ -0,0 +1,3271 @@
+# Italian translations for sudoers package
+# This file is put in the public domain.
+# Milo Casagrande <milo@milo.name>, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers-1.9.7b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2021-05-01 16:27-0600\n"
+"PO-Revision-Date: 2021-08-19 10:51+0200\n"
+"Last-Translator: Milo Casagrande <milo@milo.name>\n"
+"Language-Team: Italian <tp@lists.linux.it>\n"
+"Language: it\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 2.4.2\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+
+#: confstr.sh:1 gram.y:1183
+msgid "syntax error"
+msgstr "errore di sintassi"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "password di %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] password di %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Password: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** Informazioni di SICUREZZA per %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Riprovare."
+
+#: gram.y:233 gram.y:300 gram.y:309 gram.y:318 gram.y:328 gram.y:338
+#: gram.y:362 gram.y:389 gram.y:398 gram.y:406 gram.y:415 gram.y:424
+#: gram.y:496 gram.y:506 gram.y:518 gram.y:562 gram.y:571 gram.y:580
+#: gram.y:589 gram.y:619 gram.y:716 gram.y:724 gram.y:735 gram.y:747
+#: gram.y:766 gram.y:914 gram.y:922 gram.y:932 gram.y:938 gram.y:1060
+#: gram.y:1069 gram.y:1077 gram.y:1086 gram.y:1095 gram.y:1124 gram.y:1133
+#: gram.y:1141 gram.y:1231 gram.y:1343 gram.y:1650 gram.y:1700
+#: lib/eventlog/eventlog.c:260 lib/eventlog/eventlog.c:333
+#: lib/eventlog/eventlog.c:733 lib/eventlog/eventlog.c:797
+#: lib/eventlog/eventlog.c:1053 lib/iolog/iolog_json.c:125
+#: lib/iolog/iolog_json.c:330 lib/iolog/iolog_json.c:360
+#: lib/iolog/iolog_json.c:503 lib/iolog/iolog_legacy.c:100
+#: lib/iolog/iolog_legacy.c:111 lib/iolog/iolog_legacy.c:123
+#: lib/iolog/iolog_legacy.c:133 lib/iolog/iolog_legacy.c:139
+#: lib/iolog/iolog_loginfo.c:76 lib/iolog/iolog_loginfo.c:210
+#: logsrvd/logsrvd.c:1021 logsrvd/logsrvd.c:1089 logsrvd/logsrvd_journal.c:142
+#: logsrvd/logsrvd_journal.c:196 logsrvd/logsrvd_journal.c:248
+#: logsrvd/logsrvd_journal.c:380 logsrvd/logsrvd_relay.c:443
+#: logsrvd/logsrvd_relay.c:743 logsrvd/logsrvd_relay.c:857
+#: logsrvd/sendlog.c:500 plugins/sudoers/audit.c:115
+#: plugins/sudoers/audit.c:263 plugins/sudoers/auth/bsdauth.c:143
+#: plugins/sudoers/auth/kerb5.c:118 plugins/sudoers/auth/kerb5.c:144
+#: plugins/sudoers/auth/pam.c:692 plugins/sudoers/auth/rfc1938.c:111
+#: plugins/sudoers/auth/sia.c:59 plugins/sudoers/check_aliases.c:95
+#: plugins/sudoers/cvtsudoers.c:119 plugins/sudoers/cvtsudoers.c:160
+#: plugins/sudoers/cvtsudoers.c:177 plugins/sudoers/cvtsudoers.c:188
+#: plugins/sudoers/cvtsudoers.c:300 plugins/sudoers/cvtsudoers.c:428
+#: plugins/sudoers/cvtsudoers.c:561 plugins/sudoers/cvtsudoers.c:578
+#: plugins/sudoers/cvtsudoers.c:646 plugins/sudoers/cvtsudoers.c:761
+#: plugins/sudoers/cvtsudoers.c:769 plugins/sudoers/cvtsudoers.c:1183
+#: plugins/sudoers/cvtsudoers.c:1187 plugins/sudoers/cvtsudoers.c:1289
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:151
+#: plugins/sudoers/cvtsudoers_ldif.c:194 plugins/sudoers/cvtsudoers_ldif.c:235
+#: plugins/sudoers/cvtsudoers_ldif.c:300 plugins/sudoers/cvtsudoers_ldif.c:371
+#: plugins/sudoers/cvtsudoers_ldif.c:421 plugins/sudoers/cvtsudoers_ldif.c:429
+#: plugins/sudoers/cvtsudoers_ldif.c:440 plugins/sudoers/cvtsudoers_ldif.c:447
+#: plugins/sudoers/cvtsudoers_ldif.c:460 plugins/sudoers/cvtsudoers_ldif.c:468
+#: plugins/sudoers/cvtsudoers_ldif.c:615 plugins/sudoers/defaults.c:638
+#: plugins/sudoers/defaults.c:933 plugins/sudoers/defaults.c:1108
+#: plugins/sudoers/editor.c:187 plugins/sudoers/env.c:262
+#: plugins/sudoers/exptilde.c:92 plugins/sudoers/filedigest.c:54
+#: plugins/sudoers/filedigest.c:70 plugins/sudoers/gc.c:57
+#: plugins/sudoers/group_plugin.c:133 plugins/sudoers/interfaces.c:72
+#: plugins/sudoers/iolog.c:609 plugins/sudoers/iolog.c:626
+#: plugins/sudoers/ldap.c:184 plugins/sudoers/ldap.c:422
+#: plugins/sudoers/ldap.c:432 plugins/sudoers/ldap.c:437
+#: plugins/sudoers/ldap.c:441 plugins/sudoers/ldap.c:453
+#: plugins/sudoers/ldap.c:744 plugins/sudoers/ldap.c:908
+#: plugins/sudoers/ldap.c:1281 plugins/sudoers/ldap.c:1709
+#: plugins/sudoers/ldap.c:1746 plugins/sudoers/ldap.c:1827
+#: plugins/sudoers/ldap.c:1962 plugins/sudoers/ldap.c:2063
+#: plugins/sudoers/ldap.c:2079 plugins/sudoers/ldap_conf.c:218
+#: plugins/sudoers/ldap_conf.c:249 plugins/sudoers/ldap_conf.c:301
+#: plugins/sudoers/ldap_conf.c:337 plugins/sudoers/ldap_conf.c:441
+#: plugins/sudoers/ldap_conf.c:456 plugins/sudoers/ldap_conf.c:553
+#: plugins/sudoers/ldap_conf.c:586 plugins/sudoers/ldap_conf.c:678
+#: plugins/sudoers/ldap_conf.c:760 plugins/sudoers/ldap_util.c:326
+#: plugins/sudoers/ldap_util.c:333 plugins/sudoers/ldap_util.c:648
+#: plugins/sudoers/linux_audit.c:86 plugins/sudoers/log_client.c:105
+#: plugins/sudoers/log_client.c:381 plugins/sudoers/log_client.c:686
+#: plugins/sudoers/log_client.c:704 plugins/sudoers/log_client.c:1413
+#: plugins/sudoers/log_client.c:1626 plugins/sudoers/log_client.c:1950
+#: plugins/sudoers/log_client.c:2007 plugins/sudoers/logging.c:100
+#: plugins/sudoers/logging.c:166 plugins/sudoers/logging.c:426
+#: plugins/sudoers/logging.c:446 plugins/sudoers/logging.c:527
+#: plugins/sudoers/match_command.c:286 plugins/sudoers/match_command.c:484
+#: plugins/sudoers/match_command.c:533 plugins/sudoers/match_command.c:604
+#: plugins/sudoers/match_command.c:650 plugins/sudoers/match_digest.c:93
+#: plugins/sudoers/parse.c:199 plugins/sudoers/parse.c:216
+#: plugins/sudoers/parse.c:236 plugins/sudoers/parse.c:253
+#: plugins/sudoers/parse.c:276 plugins/sudoers/parse.c:287
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:260
+#: plugins/sudoers/parse_ldif.c:265 plugins/sudoers/parse_ldif.c:341
+#: plugins/sudoers/parse_ldif.c:352 plugins/sudoers/parse_ldif.c:379
+#: plugins/sudoers/parse_ldif.c:396 plugins/sudoers/parse_ldif.c:408
+#: plugins/sudoers/parse_ldif.c:412 plugins/sudoers/parse_ldif.c:426
+#: plugins/sudoers/parse_ldif.c:483 plugins/sudoers/parse_ldif.c:596
+#: plugins/sudoers/parse_ldif.c:626 plugins/sudoers/parse_ldif.c:651
+#: plugins/sudoers/parse_ldif.c:709 plugins/sudoers/parse_ldif.c:726
+#: plugins/sudoers/parse_ldif.c:754 plugins/sudoers/parse_ldif.c:761
+#: plugins/sudoers/policy.c:543 plugins/sudoers/policy.c:890
+#: plugins/sudoers/prompt.c:93 plugins/sudoers/pwutil.c:195
+#: plugins/sudoers/pwutil.c:266 plugins/sudoers/pwutil.c:344
+#: plugins/sudoers/pwutil.c:518 plugins/sudoers/pwutil.c:583
+#: plugins/sudoers/pwutil.c:655 plugins/sudoers/pwutil.c:853
+#: plugins/sudoers/pwutil.c:909 plugins/sudoers/pwutil.c:953
+#: plugins/sudoers/pwutil.c:1010 plugins/sudoers/sssd.c:145
+#: plugins/sudoers/sssd.c:407 plugins/sudoers/sssd.c:470
+#: plugins/sudoers/sssd.c:514 plugins/sudoers/sssd.c:561
+#: plugins/sudoers/sssd.c:754 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/stubs.c:111 plugins/sudoers/stubs.c:119
+#: plugins/sudoers/sudoers.c:299 plugins/sudoers/sudoers.c:325
+#: plugins/sudoers/sudoers.c:374 plugins/sudoers/sudoers.c:384
+#: plugins/sudoers/sudoers.c:425 plugins/sudoers/sudoers.c:787
+#: plugins/sudoers/sudoers.c:922 plugins/sudoers/sudoers.c:975
+#: plugins/sudoers/sudoers.c:1241 plugins/sudoers/sudoreplay.c:552
+#: plugins/sudoers/sudoreplay.c:555 plugins/sudoers/sudoreplay.c:1259
+#: plugins/sudoers/sudoreplay.c:1469 plugins/sudoers/sudoreplay.c:1473
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:224
+#: plugins/sudoers/testsudoers.c:241 plugins/sudoers/testsudoers.c:580
+#: plugins/sudoers/timestamp.c:424 plugins/sudoers/timestamp.c:468
+#: plugins/sudoers/timestamp.c:980 plugins/sudoers/timestamp.c:1118
+#: plugins/sudoers/toke_util.c:77 plugins/sudoers/toke_util.c:105
+#: plugins/sudoers/toke_util.c:130 plugins/sudoers/toke_util.c:155
+#: plugins/sudoers/toke_util.c:193 plugins/sudoers/tsdump.c:123
+#: plugins/sudoers/visudo.c:143 plugins/sudoers/visudo.c:321
+#: plugins/sudoers/visudo.c:327 plugins/sudoers/visudo.c:433
+#: plugins/sudoers/visudo.c:609 plugins/sudoers/visudo.c:926
+#: plugins/sudoers/visudo.c:999 toke.l:928 toke.l:1057 toke.l:1117
+msgid "unable to allocate memory"
+msgstr "impossibile allocare memoria"
+
+#: gram.y:613
+msgid "a digest requires a path name"
+msgstr "un digest richiede il nome di percorso"
+
+#: gram.y:643
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "i valori per \"CWD\" devono iniziare con un carattere \"/\", \"~\" o \"*\""
+
+#: gram.y:655
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "i valori per \"CHROOT\" devono iniziare con un carattere \"/\", \"~\" o \"*\""
+
+#: gram.y:786
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "errore di sintassi, parola riservata %s utilizzata come alias"
+
+#: gram.y:809
+msgid "invalid notbefore value"
+msgstr "valore notbefore non valido"
+
+#: gram.y:818
+msgid "invalid notafter value"
+msgstr "valore notafter non valido"
+
+#: gram.y:828 plugins/sudoers/policy.c:339
+msgid "timeout value too large"
+msgstr "valore timeout troppo grande"
+
+#: gram.y:830 plugins/sudoers/policy.c:341
+msgid "invalid timeout value"
+msgstr "valore timeout non valido"
+
+#: gram.y:1185
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: gram.y:1229
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Alias \"%s\" già definito"
+
+#: gram.y:1650 gram.y:1700 lib/eventlog/eventlog.c:260
+#: lib/eventlog/eventlog.c:733 lib/eventlog/eventlog.c:795
+#: lib/eventlog/eventlog.c:796 lib/eventlog/eventlog.c:1053
+#: lib/iolog/iolog_json.c:125 lib/iolog/iolog_json.c:329
+#: lib/iolog/iolog_json.c:360 lib/iolog/iolog_json.c:503
+#: lib/iolog/iolog_legacy.c:100 lib/iolog/iolog_legacy.c:111
+#: lib/iolog/iolog_legacy.c:123 lib/iolog/iolog_legacy.c:133
+#: lib/iolog/iolog_legacy.c:139 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:210 logsrvd/sendlog.c:500 logsrvd/sendlog.c:1343
+#: logsrvd/sendlog.c:1350 logsrvd/sendlog.c:1545 logsrvd/tls_init.c:221
+#: logsrvd/tls_init.c:242 logsrvd/tls_init.c:252 plugins/sudoers/audit.c:115
+#: plugins/sudoers/audit.c:263 plugins/sudoers/auth/pam.c:505
+#: plugins/sudoers/auth/pam.c:692 plugins/sudoers/auth/rfc1938.c:111
+#: plugins/sudoers/check_aliases.c:95 plugins/sudoers/cvtsudoers.c:119
+#: plugins/sudoers/cvtsudoers.c:159 plugins/sudoers/cvtsudoers.c:176
+#: plugins/sudoers/cvtsudoers.c:187 plugins/sudoers/cvtsudoers.c:299
+#: plugins/sudoers/cvtsudoers.c:427 plugins/sudoers/cvtsudoers.c:560
+#: plugins/sudoers/cvtsudoers.c:577 plugins/sudoers/cvtsudoers.c:646
+#: plugins/sudoers/cvtsudoers.c:761 plugins/sudoers/cvtsudoers.c:768
+#: plugins/sudoers/cvtsudoers.c:1183 plugins/sudoers/cvtsudoers.c:1187
+#: plugins/sudoers/cvtsudoers.c:1289 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:150 plugins/sudoers/cvtsudoers_ldif.c:193
+#: plugins/sudoers/cvtsudoers_ldif.c:234 plugins/sudoers/cvtsudoers_ldif.c:299
+#: plugins/sudoers/cvtsudoers_ldif.c:370 plugins/sudoers/cvtsudoers_ldif.c:420
+#: plugins/sudoers/cvtsudoers_ldif.c:428 plugins/sudoers/cvtsudoers_ldif.c:439
+#: plugins/sudoers/cvtsudoers_ldif.c:446 plugins/sudoers/cvtsudoers_ldif.c:459
+#: plugins/sudoers/cvtsudoers_ldif.c:467 plugins/sudoers/cvtsudoers_ldif.c:614
+#: plugins/sudoers/defaults.c:638 plugins/sudoers/defaults.c:933
+#: plugins/sudoers/defaults.c:1108 plugins/sudoers/editor.c:187
+#: plugins/sudoers/env.c:262 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:54 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:132
+#: plugins/sudoers/interfaces.c:72 plugins/sudoers/iolog.c:609
+#: plugins/sudoers/iolog.c:626 plugins/sudoers/ldap.c:184
+#: plugins/sudoers/ldap.c:422 plugins/sudoers/ldap.c:432
+#: plugins/sudoers/ldap.c:437 plugins/sudoers/ldap.c:441
+#: plugins/sudoers/ldap.c:453 plugins/sudoers/ldap.c:744
+#: plugins/sudoers/ldap.c:908 plugins/sudoers/ldap.c:1281
+#: plugins/sudoers/ldap.c:1709 plugins/sudoers/ldap.c:1746
+#: plugins/sudoers/ldap.c:1827 plugins/sudoers/ldap.c:1962
+#: plugins/sudoers/ldap.c:2063 plugins/sudoers/ldap.c:2079
+#: plugins/sudoers/ldap_conf.c:218 plugins/sudoers/ldap_conf.c:249
+#: plugins/sudoers/ldap_conf.c:301 plugins/sudoers/ldap_conf.c:337
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:553 plugins/sudoers/ldap_conf.c:586
+#: plugins/sudoers/ldap_conf.c:677 plugins/sudoers/ldap_conf.c:760
+#: plugins/sudoers/ldap_util.c:325 plugins/sudoers/ldap_util.c:332
+#: plugins/sudoers/ldap_util.c:648 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:105 plugins/sudoers/log_client.c:214
+#: plugins/sudoers/log_client.c:235 plugins/sudoers/log_client.c:248
+#: plugins/sudoers/log_client.c:381 plugins/sudoers/log_client.c:686
+#: plugins/sudoers/log_client.c:704 plugins/sudoers/log_client.c:1413
+#: plugins/sudoers/log_client.c:1626 plugins/sudoers/log_client.c:1950
+#: plugins/sudoers/log_client.c:2007 plugins/sudoers/logging.c:100
+#: plugins/sudoers/logging.c:165 plugins/sudoers/logging.c:166
+#: plugins/sudoers/logging.c:425 plugins/sudoers/logging.c:445
+#: plugins/sudoers/logging.c:527 plugins/sudoers/match_command.c:285
+#: plugins/sudoers/match_command.c:483 plugins/sudoers/match_command.c:532
+#: plugins/sudoers/match_command.c:604 plugins/sudoers/match_command.c:649
+#: plugins/sudoers/match_digest.c:93 plugins/sudoers/parse.c:198
+#: plugins/sudoers/parse.c:215 plugins/sudoers/parse.c:235
+#: plugins/sudoers/parse.c:252 plugins/sudoers/parse.c:275
+#: plugins/sudoers/parse.c:286 plugins/sudoers/parse_ldif.c:152
+#: plugins/sudoers/parse_ldif.c:183 plugins/sudoers/parse_ldif.c:252
+#: plugins/sudoers/parse_ldif.c:259 plugins/sudoers/parse_ldif.c:264
+#: plugins/sudoers/parse_ldif.c:340 plugins/sudoers/parse_ldif.c:351
+#: plugins/sudoers/parse_ldif.c:378 plugins/sudoers/parse_ldif.c:395
+#: plugins/sudoers/parse_ldif.c:407 plugins/sudoers/parse_ldif.c:411
+#: plugins/sudoers/parse_ldif.c:425 plugins/sudoers/parse_ldif.c:483
+#: plugins/sudoers/parse_ldif.c:596 plugins/sudoers/parse_ldif.c:625
+#: plugins/sudoers/parse_ldif.c:650 plugins/sudoers/parse_ldif.c:708
+#: plugins/sudoers/parse_ldif.c:725 plugins/sudoers/parse_ldif.c:753
+#: plugins/sudoers/parse_ldif.c:760 plugins/sudoers/policy.c:149
+#: plugins/sudoers/policy.c:158 plugins/sudoers/policy.c:167
+#: plugins/sudoers/policy.c:193 plugins/sudoers/policy.c:324
+#: plugins/sudoers/policy.c:339 plugins/sudoers/policy.c:341
+#: plugins/sudoers/policy.c:371 plugins/sudoers/policy.c:380
+#: plugins/sudoers/policy.c:428 plugins/sudoers/policy.c:438
+#: plugins/sudoers/policy.c:447 plugins/sudoers/policy.c:456
+#: plugins/sudoers/policy.c:543 plugins/sudoers/policy.c:890
+#: plugins/sudoers/prompt.c:93 plugins/sudoers/pwutil.c:195
+#: plugins/sudoers/pwutil.c:266 plugins/sudoers/pwutil.c:344
+#: plugins/sudoers/pwutil.c:518 plugins/sudoers/pwutil.c:583
+#: plugins/sudoers/pwutil.c:655 plugins/sudoers/pwutil.c:853
+#: plugins/sudoers/pwutil.c:909 plugins/sudoers/pwutil.c:953
+#: plugins/sudoers/pwutil.c:1010 plugins/sudoers/set_perms.c:359
+#: plugins/sudoers/set_perms.c:698 plugins/sudoers/set_perms.c:1061
+#: plugins/sudoers/set_perms.c:1364 plugins/sudoers/set_perms.c:1529
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:407
+#: plugins/sudoers/sssd.c:470 plugins/sudoers/sssd.c:514
+#: plugins/sudoers/sssd.c:561 plugins/sudoers/sssd.c:754
+#: plugins/sudoers/strvec_join.c:53 plugins/sudoers/stubs.c:111
+#: plugins/sudoers/stubs.c:119 plugins/sudoers/sudoers.c:299
+#: plugins/sudoers/sudoers.c:325 plugins/sudoers/sudoers.c:374
+#: plugins/sudoers/sudoers.c:384 plugins/sudoers/sudoers.c:425
+#: plugins/sudoers/sudoers.c:787 plugins/sudoers/sudoers.c:922
+#: plugins/sudoers/sudoers.c:975 plugins/sudoers/sudoers.c:1241
+#: plugins/sudoers/sudoreplay.c:552 plugins/sudoers/sudoreplay.c:555
+#: plugins/sudoers/sudoreplay.c:1259 plugins/sudoers/sudoreplay.c:1469
+#: plugins/sudoers/sudoreplay.c:1473 plugins/sudoers/testsudoers.c:120
+#: plugins/sudoers/testsudoers.c:224 plugins/sudoers/testsudoers.c:241
+#: plugins/sudoers/testsudoers.c:580 plugins/sudoers/timestamp.c:424
+#: plugins/sudoers/timestamp.c:468 plugins/sudoers/timestamp.c:980
+#: plugins/sudoers/timestamp.c:1118 plugins/sudoers/toke_util.c:77
+#: plugins/sudoers/toke_util.c:105 plugins/sudoers/toke_util.c:130
+#: plugins/sudoers/toke_util.c:154 plugins/sudoers/toke_util.c:193
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:143
+#: plugins/sudoers/visudo.c:321 plugins/sudoers/visudo.c:327
+#: plugins/sudoers/visudo.c:433 plugins/sudoers/visudo.c:609
+#: plugins/sudoers/visudo.c:926 plugins/sudoers/visudo.c:999 toke.l:928
+#: toke.l:1057 toke.l:1109 toke.l:1117
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:265 lib/iolog/iolog_json.c:509
+#: lib/iolog/iolog_json.c:512 lib/iolog/iolog_json.c:514
+#: plugins/sudoers/cvtsudoers_ldif.c:244 plugins/sudoers/cvtsudoers_ldif.c:251
+#: plugins/sudoers/cvtsudoers_ldif.c:571 plugins/sudoers/env.c:326
+#: plugins/sudoers/env.c:333 plugins/sudoers/env.c:444
+#: plugins/sudoers/iolog.c:631 plugins/sudoers/ldap.c:517
+#: plugins/sudoers/ldap.c:748 plugins/sudoers/ldap.c:1081
+#: plugins/sudoers/ldap_conf.c:222 plugins/sudoers/ldap_conf.c:312
+#: plugins/sudoers/linux_audit.c:92 plugins/sudoers/policy.c:573
+#: plugins/sudoers/policy.c:728 plugins/sudoers/policy.c:738
+#: plugins/sudoers/prompt.c:161 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/testsudoers.c:245 plugins/sudoers/toke_util.c:206
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "errore interno, overflow di %s"
+
+#: lib/eventlog/eventlog.c:324
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "impossibile eseguire dup sullo stdin: %m"
+
+#: lib/eventlog/eventlog.c:366
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "impossibile eseguire %s: %m"
+
+#: lib/eventlog/eventlog.c:407 plugins/sudoers/auth/aix_auth.c:198
+msgid "unable to fork"
+msgstr "impossibile eseguire fork"
+
+#: lib/eventlog/eventlog.c:415 lib/eventlog/eventlog.c:469
+#, c-format
+msgid "unable to fork: %m"
+msgstr "impossibile eseguire fork: %m"
+
+#: lib/eventlog/eventlog.c:459
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "impossibile aprire una pipe: %m"
+
+#: lib/eventlog/eventlog.c:882
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:911
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (comando continuato) %s"
+
+#: lib/iolog/iolog_json.c:115
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "atteso JSON_STRING, ottenuto %d"
+
+#: lib/iolog/iolog_json.c:120
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY troppo grande"
+
+#: lib/iolog/iolog_json.c:352
+msgid "missing double quote in name"
+msgstr "virgolette doppie mancanti nel nome"
+
+#: lib/iolog/iolog_json.c:449
+msgid "missing JSON_OBJECT"
+msgstr "JSON_OBJECT mancante"
+
+#: lib/iolog/iolog_json.c:453
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "atteso JSON_OBJECT, ottenuto %d"
+
+#: lib/iolog/iolog_json.c:599
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "Stack json esaurito (max %u frame)"
+
+#: lib/iolog/iolog_json.c:673
+msgid "objects must consist of name:value pairs"
+msgstr "gli oggetti devono essere costituiti da coppie nome:valore"
+
+#: lib/iolog/iolog_json.c:678 lib/iolog/iolog_json.c:709
+#: lib/iolog/iolog_json.c:753 lib/iolog/iolog_json.c:775
+#: lib/iolog/iolog_json.c:797 lib/iolog/iolog_json.c:819
+#: lib/iolog/iolog_json.c:841
+msgid "missing separator between values"
+msgstr "separatore mancante tra i valori"
+
+#: lib/iolog/iolog_json.c:693 lib/iolog/iolog_json.c:867
+msgid "unmatched close brace"
+msgstr "parentesi graffa di chiusura senza corrispondenza"
+
+#: lib/iolog/iolog_json.c:704
+msgid "unexpected array"
+msgstr "array non atteso"
+
+#: lib/iolog/iolog_json.c:724 lib/iolog/iolog_json.c:870
+msgid "unmatched close bracket"
+msgstr "parentesi quadra di chiusura senza corrispondenza"
+
+#: lib/iolog/iolog_json.c:735
+msgid "unexpected string"
+msgstr "stringa non attesa"
+
+#: lib/iolog/iolog_json.c:746
+msgid "missing colon after name"
+msgstr "due punti mancanti dopo il nome"
+
+#: lib/iolog/iolog_json.c:767 lib/iolog/iolog_json.c:789
+msgid "unexpected boolean"
+msgstr "booleano non atteso"
+
+#: lib/iolog/iolog_json.c:811
+msgid "unexpected null"
+msgstr "null non atteso"
+
+#: lib/iolog/iolog_json.c:832
+msgid "unexpected number"
+msgstr "numero non atteso"
+
+#: lib/iolog/iolog_json.c:879
+msgid "parse error"
+msgstr "errore di analisi"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: file di registro non valido"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: manca il campo della marcatura temporale"
+
+#: lib/iolog/iolog_legacy.c:89
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: marcatura temporale %s: %s"
+
+#: lib/iolog/iolog_legacy.c:96
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: manca il campo utente"
+
+#: lib/iolog/iolog_legacy.c:107
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: manca il campo utente di runas"
+
+#: lib/iolog/iolog_legacy.c:118
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: manca il campo gruppo di runas"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s esiste, ma non è una directory (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:119 lib/iolog/iolog_mkdtemp.c:72
+#: plugins/sudoers/timestamp.c:205
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "impossibile creare la directory %s"
+
+#: lib/iolog/iolog_mkdtemp.c:76 plugins/sudoers/visudo.c:726
+#: plugins/sudoers/visudo.c:737
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "impossibile modificare la modalità di %s a 0%o"
+
+#: lib/iolog/iolog_timing.c:255
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "errore nel leggere il file di timing: %s"
+
+#: lib/iolog/iolog_timing.c:262
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "riga di timing del file non valida: %s"
+
+#: logsrvd/logsrv_util.c:99 logsrvd/logsrv_util.c:106
+#: plugins/sudoers/sudoreplay.c:352 plugins/sudoers/sudoreplay.c:358
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "impossibile aprire %s/%s"
+
+#: logsrvd/logsrv_util.c:133
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "file di registro I/O mancante %s/%s"
+
+#: logsrvd/logsrv_util.c:140
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s: impossibile spostarsi avanti %zu"
+
+#: logsrvd/logsrv_util.c:150
+#, c-format
+msgid "unable to find resume point [%lld, %ld] in %s/%s"
+msgstr "impossibile trovare il punto di ripristino [%lld, %ld] in %s/%s"
+
+#: logsrvd/logsrvd.c:434 logsrvd/logsrvd.c:473 logsrvd/logsrvd.c:507
+#: logsrvd/logsrvd.c:557 logsrvd/logsrvd.c:632 logsrvd/logsrvd.c:664
+#: logsrvd/logsrvd.c:696 logsrvd/logsrvd.c:726 logsrvd/logsrvd_relay.c:511
+#: logsrvd/logsrvd_relay.c:544
+msgid "state machine error"
+msgstr "errore della macchina di stato"
+
+#: logsrvd/logsrvd.c:443
+msgid "invalid AcceptMessage"
+msgstr "AcceptMessage non valido"
+
+#: logsrvd/logsrvd.c:482
+msgid "invalid RejectMessage"
+msgstr "RejectMessage non valido"
+
+#: logsrvd/logsrvd.c:593
+msgid "invalid AlertMessage"
+msgstr "AlertMessage non valido"
+
+#: logsrvd/logsrvd.c:638 logsrvd/logsrvd.c:670 logsrvd/logsrvd.c:702
+msgid "protocol error"
+msgstr "errore di protocollo"
+
+#: logsrvd/logsrvd.c:797
+msgid "unrecognized ClientMessage type"
+msgstr "tipo di ClientMessage non riconosciuto"
+
+#: logsrvd/logsrvd.c:1082 logsrvd/logsrvd_journal.c:238
+msgid "client message too large"
+msgstr "messaggio client troppo grande"
+
+#: logsrvd/logsrvd.c:1102
+msgid "invalid ClientMessage"
+msgstr "ClientMessage non valido"
+
+#: logsrvd/logsrvd.c:1408
+msgid "unable to get remote IP addr"
+msgstr "impossibile ottenere indirizzo IP remoto"
+
+#: logsrvd/logsrvd.c:1436 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:263
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "Impossibile allegare dati utenti all'oggetto ssl: %s"
+
+#: logsrvd/logsrvd.c:1444 logsrvd/logsrvd.c:1570 logsrvd/logsrvd.c:1755
+#: logsrvd/sendlog.c:1146 logsrvd/tls_client.c:138 logsrvd/tls_client.c:154
+#: logsrvd/tls_client.c:216 plugins/sudoers/iolog.c:969
+#: plugins/sudoers/iolog.c:1102 plugins/sudoers/iolog.c:1200
+#: plugins/sudoers/log_client.c:109 plugins/sudoers/log_client.c:324
+#: plugins/sudoers/log_client.c:340 plugins/sudoers/log_client.c:386
+#: plugins/sudoers/log_client.c:585 plugins/sudoers/log_client.c:592
+#: plugins/sudoers/log_client.c:1109 plugins/sudoers/log_client.c:1382
+#: plugins/sudoers/log_client.c:1423 plugins/sudoers/log_client.c:1431
+#: plugins/sudoers/log_client.c:1582 plugins/sudoers/log_client.c:1698
+#: plugins/sudoers/log_client.c:2015 plugins/sudoers/log_client.c:2023
+#: plugins/sudoers/sudoreplay.c:512 plugins/sudoers/sudoreplay.c:559
+#: plugins/sudoers/sudoreplay.c:791 plugins/sudoers/sudoreplay.c:903
+#: plugins/sudoers/sudoreplay.c:993 plugins/sudoers/sudoreplay.c:1008
+#: plugins/sudoers/sudoreplay.c:1015 plugins/sudoers/sudoreplay.c:1022
+#: plugins/sudoers/sudoreplay.c:1029 plugins/sudoers/sudoreplay.c:1036
+#: plugins/sudoers/sudoreplay.c:1163
+msgid "unable to add event to queue"
+msgstr "impossibile aggiungere l'evento alla coda"
+
+#: logsrvd/logsrvd.c:1620 logsrvd/logsrvd.c:1953
+msgid "unable to setup listen socket"
+msgstr "impossibile impostare il socket di ascolto"
+
+#: logsrvd/logsrvd.c:1855
+msgid "sudo log server"
+msgstr "Server di registro sudo"
+
+#: logsrvd/logsrvd.c:1857 logsrvd/sendlog.c:122
+msgid "Options:"
+msgstr "Opzioni:"
+
+#: logsrvd/logsrvd.c:1859
+msgid "path to configuration file"
+msgstr "Percorso del file di configurazione"
+
+#: logsrvd/logsrvd.c:1861 logsrvd/sendlog.c:124
+msgid "display help message and exit"
+msgstr "Visualizza il messaggio di aiuto ed esce"
+
+#: logsrvd/logsrvd.c:1863
+msgid "do not fork, run in the foreground"
+msgstr "Non esegue fork, esegue in primo piano"
+
+#: logsrvd/logsrvd.c:1865
+msgid "percent chance connections will drop"
+msgstr "Probabilità percentuale che le connessioni termineranno"
+
+#: logsrvd/logsrvd.c:1867 logsrvd/sendlog.c:152
+msgid "display version information and exit"
+msgstr "Visualizza le informazioni sulla versione ed esce"
+
+#: logsrvd/logsrvd.c:1917 logsrvd/sendlog.c:1518
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "È richiesto Protobuf-C 1.3 o successivo"
+
+#: logsrvd/logsrvd.c:1933
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "valore drop casuale non valido: %s"
+
+#: logsrvd/logsrvd.c:1936 logsrvd/sendlog.c:1568
+#: plugins/sudoers/cvtsudoers.c:228 plugins/sudoers/sudoreplay.c:299
+#: plugins/sudoers/visudo.c:175
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s versione %s\n"
+
+#: logsrvd/logsrvd_conf.c:446
+msgid "TLS not supported"
+msgstr "TLS non supportato"
+
+#: logsrvd/logsrvd_conf.c:468
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:541 logsrvd/logsrvd_conf.c:876
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s: non è un percorso completo"
+
+#: logsrvd/logsrvd_conf.c:1035
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d \"[\" non corrispondente: %s"
+
+#: logsrvd/logsrvd_conf.c:1046
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s:%d sezione configurazione non valida: %s"
+
+#: logsrvd/logsrvd_conf.c:1054
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d riga di configurazione non valida: %s"
+
+#: logsrvd/logsrvd_conf.c:1060
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d atteso nome di sezione: %s"
+
+#: logsrvd/logsrvd_conf.c:1074
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "valore non valido per \"%s\": %s"
+
+#: logsrvd/logsrvd_conf.c:1082
+#, c-format
+msgid "%s:%d unknown key: %s"
+msgstr "%s:%d chiave sconosciuta: %s"
+
+#: logsrvd/logsrvd_conf.c:1294
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "strumento syslog %s sconosciuto"
+
+#: logsrvd/logsrvd_conf.c:1298 logsrvd/logsrvd_conf.c:1302
+#: logsrvd/logsrvd_conf.c:1306
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "priorità syslog %s sconosciuta"
+
+#: logsrvd/logsrvd_conf.c:1374
+msgid "unable to initialize server TLS context"
+msgstr "impossibile inizializzare il contesto TLS del server"
+
+#: logsrvd/logsrvd_conf.c:1394
+msgid "unable to initialize relay TLS context"
+msgstr "impossibile inizializzare il contesto TLS di inoltro"
+
+#: logsrvd/logsrvd_journal.c:126 logsrvd/logsrvd_journal.c:367
+#: logsrvd/logsrvd_journal.c:373
+msgid "unable to create journal file"
+msgstr "Impossibile creare un file del registro"
+
+#: logsrvd/logsrvd_journal.c:134
+msgid "unable to lock journal file"
+msgstr "Impossibile bloccare il file del registro"
+
+#: logsrvd/logsrvd_journal.c:163 logsrvd/logsrvd_journal.c:406
+#: logsrvd/logsrvd_journal.c:411
+msgid "unable to write journal file"
+msgstr "Impossibile scrivere il file del registro"
+
+#: logsrvd/logsrvd_journal.c:171 logsrvd/logsrvd_journal.c:178
+msgid "unable to rename journal file"
+msgstr "Impossibile rinominare il file del registro"
+
+#: logsrvd/logsrvd_journal.c:228 logsrvd/logsrvd_journal.c:258
+msgid "unexpected EOF reading journal file"
+msgstr "EOF inatteso nel file del registro"
+
+#: logsrvd/logsrvd_journal.c:230 logsrvd/logsrvd_journal.c:260
+msgid "error reading journal file"
+msgstr "errore nel leggere il file del registro"
+
+#: logsrvd/logsrvd_journal.c:270 logsrvd/logsrvd_journal.c:325
+msgid "invalid journal file, unable to restart"
+msgstr "file del registro non valido, impossibile riavviare"
+
+#: logsrvd/logsrvd_local.c:149
+msgid "error parsing AcceptMessage"
+msgstr "errore nell'analizzare AcceptMessage"
+
+#: logsrvd/logsrvd_local.c:156
+msgid "error creating I/O log"
+msgstr "errore nel creare il registro I/O"
+
+#: logsrvd/logsrvd_local.c:164
+msgid "error logging accept event"
+msgstr "errore nel registrare l'evento accept"
+
+#: logsrvd/logsrvd_local.c:196
+msgid "error parsing RejectMessage"
+msgstr "errore nell'analizzare RejectMessage"
+
+#: logsrvd/logsrvd_local.c:202
+msgid "error logging reject event"
+msgstr "errore nel registrare l'evento reject"
+
+#: logsrvd/logsrvd_local.c:276
+msgid "log is already complete, cannot be restarted"
+msgstr "il registro è già completo, non può essere riavviato"
+
+#: logsrvd/logsrvd_local.c:307
+msgid "unable to restart log"
+msgstr "impossibile riavviare il registro"
+
+#: logsrvd/logsrvd_local.c:322
+msgid "error parsing AlertMessage"
+msgstr "errore nell'analizzare AlertMessage"
+
+#: logsrvd/logsrvd_local.c:330
+msgid "error logging alert event"
+msgstr "errore nel registrare l'evento alert"
+
+#: logsrvd/logsrvd_local.c:397
+msgid "error writing IoBuffer"
+msgstr "errore nello scrivere IoBuffer"
+
+#: logsrvd/logsrvd_local.c:434
+msgid "error writing ChangeWindowSize"
+msgstr "errore nello scrivere ChangeWindowSize"
+
+#: logsrvd/logsrvd_local.c:474
+msgid "error writing CommandSuspend"
+msgstr "errore nello scrivere CommandSuspend"
+
+#: logsrvd/logsrvd_relay.c:434
+msgid "TLS handshake with relay host failed"
+msgstr "handshake TLS con host di inoltro non riuscito"
+
+#: logsrvd/logsrvd_relay.c:462
+msgid "unable to connect to relay host"
+msgstr "impossibile connettersi all'host di inoltro"
+
+#: logsrvd/logsrvd_relay.c:519 logsrvd/sendlog.c:951
+#: plugins/sudoers/log_client.c:1466
+msgid "invalid ServerHello"
+msgstr "ServerHello non valido"
+
+#: logsrvd/logsrvd_relay.c:677
+msgid "unrecognized ServerMessage type"
+msgstr "tipo di ServerMessage non riconosciuto"
+
+#: logsrvd/logsrvd_relay.c:709
+msgid "timeout reading from relay"
+msgstr "timeout nel leggere dal relay"
+
+#: logsrvd/logsrvd_relay.c:761
+msgid "relay host name does not match certificate"
+msgstr "il nome host del relay non corrisponde al certificato"
+
+#: logsrvd/logsrvd_relay.c:765 logsrvd/logsrvd_relay.c:786
+#: logsrvd/logsrvd_relay.c:794
+msgid "error reading from relay"
+msgstr "errore nel leggere dal relay"
+
+#: logsrvd/logsrvd_relay.c:817
+msgid "unable to read from relay"
+msgstr "impossibile leggere dal relay"
+
+#: logsrvd/logsrvd_relay.c:831 logsrvd/logsrvd_relay.c:951
+msgid "relay server closed connection"
+msgstr "connessione chiusa del server di relay"
+
+#: logsrvd/logsrvd_relay.c:850
+msgid "server message too large"
+msgstr "messaggio server troppo grande"
+
+#: logsrvd/logsrvd_relay.c:915
+msgid "timeout writing to relay"
+msgstr "timeout nello scrivere sul relay"
+
+#: logsrvd/logsrvd_relay.c:973 logsrvd/logsrvd_relay.c:981
+#: logsrvd/logsrvd_relay.c:993
+msgid "error writing to relay"
+msgstr "errore nello scrivere sul relay"
+
+#: logsrvd/sendlog.c:120
+msgid "send sudo I/O log to remote server"
+msgstr "Invia registro I/O di sudo a un server remoto"
+
+#: logsrvd/sendlog.c:126
+msgid "only send an accept event (no I/O)"
+msgstr "Invia solo un evento di accettazione (nessun I/O)"
+
+#: logsrvd/sendlog.c:129
+msgid "certificate bundle file to verify server's cert against"
+msgstr "File bundle di certificati con cui verificare il certificato del server"
+
+#: logsrvd/sendlog.c:131
+msgid "certificate file for TLS handshake"
+msgstr "File certificato per l'handshake TLS"
+
+#: logsrvd/sendlog.c:134
+msgid "host to send logs to"
+msgstr "Host a cui inviare i registri"
+
+#: logsrvd/sendlog.c:136
+msgid "remote ID of I/O log to be resumed"
+msgstr "ID remoto del registro di I/O da riprendere"
+
+#: logsrvd/sendlog.c:139
+msgid "private key file"
+msgstr "File chiave privata"
+
+#: logsrvd/sendlog.c:141
+msgid "do not verify server certificate"
+msgstr "Non verifica il certificato del server"
+
+#: logsrvd/sendlog.c:144
+msgid "port to use when connecting to host"
+msgstr "Porta da utilizzare per la connessione all'host"
+
+#: logsrvd/sendlog.c:146
+msgid "restart previous I/O log transfer"
+msgstr "Riavvia il precedente trasferimento del registro di I/O"
+
+#: logsrvd/sendlog.c:148
+msgid "reject the command with the given reason"
+msgstr "Rifiuta il comando con il motivo indicato"
+
+#: logsrvd/sendlog.c:150
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "Prova il server di controllo inviando il registro di I/O selezionato n-volte in parallelo"
+
+#: logsrvd/sendlog.c:175 plugins/sudoers/log_client.c:432
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "impossibile cercare %s:%s: %s"
+
+#: logsrvd/sendlog.c:213
+msgid "unable to get server IP addr"
+msgstr "impossibile ottenere indirizzo IP del server"
+
+#: logsrvd/sendlog.c:267 plugins/sudoers/sudoreplay.c:851
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "impossibile leggere %s/%s: %s"
+
+#: logsrvd/sendlog.c:288 plugins/sudoers/log_client.c:692
+#, c-format
+msgid "client message too large: %zu"
+msgstr "messaggio client troppo grande: %zu"
+
+#: logsrvd/sendlog.c:830
+#, c-format
+msgid "%s: write buffer already in use"
+msgstr "%s: buffer di scrittura già in uso"
+
+#: logsrvd/sendlog.c:882 plugins/sudoers/iolog.c:893
+#: plugins/sudoers/iolog.c:962
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "evento I/O %d non atteso"
+
+#: logsrvd/sendlog.c:928 logsrvd/sendlog.c:945 logsrvd/sendlog.c:979
+#: plugins/sudoers/log_client.c:1124 plugins/sudoers/log_client.c:1392
+#: plugins/sudoers/log_client.c:1460 plugins/sudoers/log_client.c:1496
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: stato %d non atteso"
+
+#: logsrvd/sendlog.c:1015 plugins/sudoers/log_client.c:1540
+#, c-format
+msgid "error message received from server: %s"
+msgstr "messaggio di errore ricevuto dal server: %s"
+
+#: logsrvd/sendlog.c:1028 plugins/sudoers/log_client.c:1553
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "messaggio di abort ricevuto dal server: %s"
+
+#: logsrvd/sendlog.c:1047 plugins/sudoers/log_client.c:1572
+msgid "unable to unpack ServerMessage"
+msgstr "impossibile aprire ServerMessage"
+
+#: logsrvd/sendlog.c:1087 plugins/sudoers/log_client.c:1603
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s: valore type_case %d non atteso"
+
+#: logsrvd/sendlog.c:1116
+msgid "timeout reading from server"
+msgstr "timeout nel leggere dal server"
+
+#: logsrvd/sendlog.c:1195
+msgid "premature EOF"
+msgstr "EOF prematuro"
+
+#: logsrvd/sendlog.c:1208 plugins/sudoers/log_client.c:1761
+#, c-format
+msgid "server message too large: %u"
+msgstr "messaggio server troppo grande: %u"
+
+#: logsrvd/sendlog.c:1259
+msgid "timeout writing to server"
+msgstr "timeout nello scrivere sul server"
+
+#: logsrvd/sendlog.c:1591
+msgid "both restart point and iolog ID must be specified"
+msgstr "devono essere specificati sia il punto di inizio che l'ID di iolog"
+
+#: logsrvd/sendlog.c:1595
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "un punto di partenza non può essere impostato quando non è inviato alcun I/O"
+
+#: logsrvd/sendlog.c:1671
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "uscito inaspettatamente con stato %d"
+
+#: logsrvd/sendlog.c:1672
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "tempo trascorso inviato al server [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1674
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "punto di commit ricevuto dal server [%lld, %ld]"
+
+#: logsrvd/tls_client.c:113 plugins/sudoers/log_client.c:296
+msgid "TLS handshake timeout occurred"
+msgstr "timeout handshake TLS"
+
+#: logsrvd/tls_client.c:133 logsrvd/tls_client.c:149
+#: plugins/sudoers/log_client.c:318 plugins/sudoers/log_client.c:334
+msgid "unable to set event"
+msgstr "impossibile impostare evento"
+
+#: logsrvd/tls_client.c:159 logsrvd/tls_client.c:163
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "connessione TLS non riuscita: %s"
+
+#: logsrvd/tls_client.c:197
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "impossibile allocare l'oggetto ssl: %s"
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "Impossibile collegare il socket all'oggetto ssl: %s"
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr "impossibile inizializzare il contesto TLS"
+
+#: logsrvd/tls_init.c:129 logsrvd/tls_init.c:137
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "impossibile impostare il cifrario per TLS 1.2 a %s: %s"
+
+#: logsrvd/tls_init.c:157 logsrvd/tls_init.c:165
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "impossibile impostare il cifrario per TLS 1.3 a %s: %s"
+
+#: logsrvd/tls_init.c:200
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "impossibile creare il contesyo TLS: %s"
+
+#: logsrvd/tls_init.c:206
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "impossibile impostare la versione minima del protocollo a TLS 1.2: %s"
+
+#: logsrvd/tls_init.c:282
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "impossibile impostare i parametri diffie-hellman: %s"
+
+#: logsrvd/tls_init.c:291
+#, c-format
+msgid "unable to read diffie-hellman parameters: %s"
+msgstr "impossibile leggere i parametri diffie-hellman: %s"
+
+#: logsrvd/tls_init.c:296 plugins/sudoers/check.c:274
+#: plugins/sudoers/cvtsudoers.c:618 plugins/sudoers/cvtsudoers.c:639
+#: plugins/sudoers/cvtsudoers.c:1249 plugins/sudoers/cvtsudoers_json.c:872
+#: plugins/sudoers/cvtsudoers_ldif.c:688 plugins/sudoers/sudoers.c:1028
+#: plugins/sudoers/sudoreplay.c:1435 plugins/sudoers/timestamp.c:433
+#: plugins/sudoers/tsdump.c:128 plugins/sudoers/visudo.c:913
+#, c-format
+msgid "unable to open %s"
+msgstr "impossibile aprire %s"
+
+#: plugins/sudoers/audit.c:259 plugins/sudoers/audit.c:398
+#: plugins/sudoers/log_client.c:960 plugins/sudoers/log_client.c:1008
+#: plugins/sudoers/log_client.c:1056 plugins/sudoers/log_client.c:1181
+#: plugins/sudoers/logging.c:548 plugins/sudoers/policy.c:120
+msgid "unable to get time of day"
+msgstr "impossibile ottenere l'ora"
+
+#: plugins/sudoers/auth/aix_auth.c:277
+#, c-format
+msgid "unable to change password for %s"
+msgstr "impossibile modificare la password per %s"
+
+#: plugins/sudoers/auth/bsdauth.c:70
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "impossibile ottenere la classe di login per l'utente %s"
+
+#: plugins/sudoers/auth/bsdauth.c:75
+msgid "unable to begin bsd authentication"
+msgstr "impossibile iniziare l'autenticazione bsd"
+
+#: plugins/sudoers/auth/bsdauth.c:83
+msgid "invalid authentication type"
+msgstr "tipo di autenticazione non valida"
+
+#: plugins/sudoers/auth/bsdauth.c:92
+msgid "unable to initialize BSD authentication"
+msgstr "impossibile iniziare l'autenticazione BSD"
+
+#: plugins/sudoers/auth/bsdauth.c:179
+msgid "your account has expired"
+msgstr "il proprio account è scaduto"
+
+#: plugins/sudoers/auth/bsdauth.c:181
+msgid "approval failed"
+msgstr "approvazione non riuscita"
+
+#: plugins/sudoers/auth/fwtk.c:54
+msgid "unable to read fwtk config"
+msgstr "impossibile leggere la configurazione fwtk"
+
+#: plugins/sudoers/auth/fwtk.c:59
+msgid "unable to connect to authentication server"
+msgstr "impossibile connettersi al server di autenticazione"
+
+#: plugins/sudoers/auth/fwtk.c:65 plugins/sudoers/auth/fwtk.c:89
+#: plugins/sudoers/auth/fwtk.c:121
+msgid "lost connection to authentication server"
+msgstr "connessione al server di autenticazione persa"
+
+#: plugins/sudoers/auth/fwtk.c:69
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"errore del server di autenticazione:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:110
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: impossibile convertire il principal in stringa (\"%s\"): %s"
+
+#: plugins/sudoers/auth/kerb5.c:160
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: impossibile analizzare \"%s\": %s"
+
+#: plugins/sudoers/auth/kerb5.c:169
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: impossibile risolvere la cache delle credenziali: %s"
+
+#: plugins/sudoers/auth/kerb5.c:216
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: impossibile allocare le opzioni: %s"
+
+#: plugins/sudoers/auth/kerb5.c:231
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: impossibile ottenere le credenziali: %s"
+
+#: plugins/sudoers/auth/kerb5.c:244
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: impossibile inizializzare la cache delle credenziali: %s"
+
+#: plugins/sudoers/auth/kerb5.c:247
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: impossibile memorizzare le credenziali nella cache: %s"
+
+#: plugins/sudoers/auth/kerb5.c:311
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: impossibile ottenere il principal dell'host: %s"
+
+#: plugins/sudoers/auth/kerb5.c:325
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: impossibile verificare TGT. Possibile attacco in corso: %s"
+
+#: plugins/sudoers/auth/pam.c:218
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "impossibile inizializzare PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:340
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Errore autenticazione PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:359
+msgid "account validation failure, is your account locked?"
+msgstr "validazione dell'account non riuscita: forse è bloccato?"
+
+#: plugins/sudoers/auth/pam.c:370
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Account o password scaduto: reimpostare la password e provare nuovamente"
+
+#: plugins/sudoers/auth/pam.c:376
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "impossibile modificare la password scaduta: %s"
+
+#: plugins/sudoers/auth/pam.c:387
+msgid "Password expired, contact your system administrator"
+msgstr "Password scaduta, contattare l'amministratore di sistema"
+
+#: plugins/sudoers/auth/pam.c:392
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Account scaduto o alla configurazione PAM manca una sezione \"account\" per sudo: contattare l'amministratore di sistema"
+
+#: plugins/sudoers/auth/pam.c:400 plugins/sudoers/auth/pam.c:405
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "Errore gestione account PAM: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:99 plugins/sudoers/visudo.c:241
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "l'utente attuale non esiste nel database %s"
+
+#: plugins/sudoers/auth/securid5.c:72
+msgid "failed to initialise the ACE API library"
+msgstr "inizializzazione della libreria API ACE non riuscita"
+
+#: plugins/sudoers/auth/securid5.c:98
+msgid "unable to contact the SecurID server"
+msgstr "impossibile contattare il server SecurID"
+
+#: plugins/sudoers/auth/securid5.c:107
+msgid "User ID locked for SecurID Authentication"
+msgstr "ID utente bloccato per l'autenticazione SecurID"
+
+#: plugins/sudoers/auth/securid5.c:111 plugins/sudoers/auth/securid5.c:162
+msgid "invalid username length for SecurID"
+msgstr "lunghezza del nome utente per SecurID non valida"
+
+#: plugins/sudoers/auth/securid5.c:115 plugins/sudoers/auth/securid5.c:167
+msgid "invalid Authentication Handle for SecurID"
+msgstr "gestore di autenticazione per SecurID non valido"
+
+#: plugins/sudoers/auth/securid5.c:119
+msgid "SecurID communication failed"
+msgstr "Comunicazione SecurID non riuscita"
+
+#: plugins/sudoers/auth/securid5.c:123 plugins/sudoers/auth/securid5.c:210
+msgid "unknown SecurID error"
+msgstr "errore sconosciuto di SecurID"
+
+#: plugins/sudoers/auth/securid5.c:157
+msgid "invalid passcode length for SecurID"
+msgstr "lunghezza del passcode per SecurID errata"
+
+#: plugins/sudoers/auth/sia.c:69 plugins/sudoers/auth/sia.c:123
+msgid "unable to initialize SIA session"
+msgstr "impossibile inizializzare la sessione SIA"
+
+#: plugins/sudoers/auth/sudo_auth.c:132
+msgid "invalid authentication methods"
+msgstr "metodi di autenticazione non validi"
+
+#: plugins/sudoers/auth/sudo_auth.c:134
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Metodi di autenticazione non validi compilati all'interno di sudo. Non è possibile usare assieme autenticazione standalone e non-standalone."
+
+#: plugins/sudoers/auth/sudo_auth.c:255 plugins/sudoers/auth/sudo_auth.c:305
+msgid "no authentication methods"
+msgstr "nessun metodo di autenticazione"
+
+#: plugins/sudoers/auth/sudo_auth.c:257
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Non ci sono metodi di autenticazione compilati all'interno di sudo. Per disabilitare l'autenticazione, usare l'opzione di configurazione --disable-authentication."
+
+#: plugins/sudoers/auth/sudo_auth.c:307
+msgid "Unable to initialize authentication methods."
+msgstr "Impossibile inizializzare i metodi di autenticazione."
+
+#: plugins/sudoers/auth/sudo_auth.c:471
+msgid "Authentication methods:"
+msgstr "Metodi di autenticazione:"
+
+#: plugins/sudoers/bsm_audit.c:123 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "Impossibile determinare la condizione di audit"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:277
+msgid "unable to commit audit record"
+msgstr "impossibile inviare il record di audit"
+
+#: plugins/sudoers/check.c:264
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "errore nel leggere il file di lezione %s"
+
+#: plugins/sudoers/check.c:270
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "il file di lezione %s viene ignorato: non è un file regolare"
+
+#: plugins/sudoers/check.c:283
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Questa lezione dovrebbe essere stata impartita dall'amministratore\n"
+"di sistema locale. Solitamente equivale a:\n"
+"\n"
+" #1) Rispettare la privacy degli altri\n"
+" #2) Pensare prima di digitare\n"
+" #3) Da grandi poteri derivano grandi responsabilità\n"
+"\n"
+
+#: plugins/sudoers/check.c:325 plugins/sudoers/check.c:335
+#: plugins/sudoers/sudoers.c:830 plugins/sudoers/sudoers.c:851
+#: plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid: %u"
+msgstr "uid sconosciuto: %u"
+
+#: plugins/sudoers/check.c:330 plugins/sudoers/exptilde.c:85
+#: plugins/sudoers/iolog.c:118 plugins/sudoers/policy.c:1123
+#: plugins/sudoers/sudoers.c:432 plugins/sudoers/sudoers.c:1283
+#: plugins/sudoers/testsudoers.c:215 plugins/sudoers/testsudoers.c:382
+#, c-format
+msgid "unknown user: %s"
+msgstr "utente sconosciuto: %s"
+
+#: plugins/sudoers/check_aliases.c:56
+#, c-format
+msgid "Error: %s:%d:%d: cycle in %s \"%s\""
+msgstr "Errore: %s:%d:%d: ciclo in %s \"%s\""
+
+#: plugins/sudoers/check_aliases.c:57
+#, c-format
+msgid "Warning: %s:%d:%d: cycle in %s \"%s\""
+msgstr "Attenzione: %s:%d:%d: ciclo in %s \"%s\""
+
+#: plugins/sudoers/check_aliases.c:61
+#, c-format
+msgid "Error: %s:%d:%d: %s \"%s\" referenced but not defined"
+msgstr "Errore: %1$s:%2$d:%3$d: riferimento a \"%5$s\" %4$s, ma non definito"
+
+#: plugins/sudoers/check_aliases.c:62
+#, c-format
+msgid "Warning: %s:%d:%d: %s \"%s\" referenced but not defined"
+msgstr "Attenzione: %1$s:%2$d:%3$d: riferimento a \"%5$s\" %4$s, ma non definito"
+
+#: plugins/sudoers/cvtsudoers.c:194
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "ordine di incremento: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:210
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "ordine di partenza: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:220
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "ordine di riempimento: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:230 plugins/sudoers/visudo.c:177
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s versione grammaticale %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:247 plugins/sudoers/testsudoers.c:159
+#, c-format
+msgid "unsupported input format %s"
+msgstr "formato di input %s non supportato"
+
+#: plugins/sudoers/cvtsudoers.c:262
+#, c-format
+msgid "unsupported output format %s"
+msgstr "formato di output %s non supportato"
+
+#: plugins/sudoers/cvtsudoers.c:314
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: i file di input e output devono essere diversi"
+
+#: plugins/sudoers/cvtsudoers.c:330 plugins/sudoers/sudoers.c:177
+#: plugins/sudoers/testsudoers.c:254 plugins/sudoers/visudo.c:247
+#: plugins/sudoers/visudo.c:597 plugins/sudoers/visudo.c:917
+msgid "unable to initialize sudoers default values"
+msgstr "impossibile inizializzare i valori predefiniti di sudoers"
+
+#: plugins/sudoers/cvtsudoers.c:416 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:475
+#, c-format
+msgid "%s: unknown key word: %s"
+msgstr "%s: chiave sconosciuta: %s"
+
+#: plugins/sudoers/cvtsudoers.c:521
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "tipo di defaults non valido: %s"
+
+#: plugins/sudoers/cvtsudoers.c:544
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "tipo di occultamento non valido: %s"
+
+#: plugins/sudoers/cvtsudoers.c:584 plugins/sudoers/cvtsudoers.c:598
+#, c-format
+msgid "invalid filter: %s"
+msgstr "filtro non valido: %s"
+
+#: plugins/sudoers/cvtsudoers.c:642 plugins/sudoers/visudo.c:922
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "analisi del file %s non riuscita, errore sconosciuto"
+
+#: plugins/sudoers/cvtsudoers.c:650
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr "errore di analisi in %s vicino alla riga %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:653
+#, c-format
+msgid "parse error in %s\n"
+msgstr "errore di analisi in %s\n"
+
+#: plugins/sudoers/cvtsudoers.c:1296 plugins/sudoers/sudoreplay.c:1124
+#: plugins/sudoers/timestamp.c:317 plugins/sudoers/timestamp.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "impossibile scrivere su %s"
+
+#: plugins/sudoers/cvtsudoers.c:1319
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s - Converte tra formati del file sudoers\n"
+"\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1321
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Opzioni:\n"
+" -b, --base=dn Il DN base per le ricerche LDAP\n"
+" -c, --config=FILE_CONF Il percorso al file di configurazione\n"
+" -d, --defaults=TIPIDEF Converte Defaults solo dei tipi indicati\n"
+" -e, --expand-aliases Espande gli alias nella conversione\n"
+" -f, --output-format=FORMATO Imposta il formato di output: JSON, LDIF o sudoers\n"
+" -i, --input-format=FORMATO Imposta il formato di input: LDIF o sudoers\n"
+" -I, --increment=num Di quanto incrementare il valore sudoOrder\n"
+" -h, --help Mostra il messaggio di aiuto ed esce\n"
+" -m, --match=FILTRO Converte le voci che corrispondo al filtro\n"
+" -M, --match-local Il filtro usa i dati da passwd e group\n"
+" -o, --output=file_output Scrive il file convertito su file_output\n"
+" -O, --order-start=num Punto di partenza del primo sudoOrder\n"
+" -p, --prune-matches Elimina utenti, gruppi e host che non corrispondono\n"
+" -P, --padding=num Riempimento base per incrementi di sudoOrder\n"
+" -s, --suppress=SEZIONI Disabilita l'output per alcune sezioni\n"
+" -V, --version Visualizza la versione ed esce"
+
+#: plugins/sudoers/cvtsudoers_json.c:480 plugins/sudoers/cvtsudoers_json.c:514
+#: plugins/sudoers/cvtsudoers_json.c:713
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "voce Defaults \"%s\" sconosciuta"
+
+#: plugins/sudoers/cvtsudoers_json.c:651 plugins/sudoers/cvtsudoers_json.c:664
+#: plugins/sudoers/cvtsudoers_ldif.c:346 plugins/sudoers/cvtsudoers_ldif.c:357
+#: plugins/sudoers/ldap.c:503
+msgid "unable to get GMT time"
+msgstr "impossibile ottenere l'ora GMT"
+
+#: plugins/sudoers/cvtsudoers_json.c:654 plugins/sudoers/cvtsudoers_json.c:667
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:360
+#: plugins/sudoers/ldap.c:509
+msgid "unable to format timestamp"
+msgstr "impossibile formattare la marcatura temporale"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:640
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "troppe voci sudoers, massimo %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:683
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "la variabile d'ambiente SUDOERS_BASE non è impostata e non è stata specificata l'opzione -b."
+
+#: plugins/sudoers/def_data.c:50
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Infrastruttura syslog se syslog viene utilizzato per le registrazioni: %s"
+
+#: plugins/sudoers/def_data.c:54
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Priorità di syslog se l'utente si identifica con successo: %s"
+
+#: plugins/sudoers/def_data.c:58
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Priorità di syslog se l'utente non si identifica con successo: %s"
+
+#: plugins/sudoers/def_data.c:62
+msgid "Put OTP prompt on its own line"
+msgstr "Mette il prompt OTP su una riga a parte"
+
+#: plugins/sudoers/def_data.c:66
+msgid "Ignore '.' in $PATH"
+msgstr "Ignora \".\" in $PATH"
+
+#: plugins/sudoers/def_data.c:70
+msgid "Always send mail when sudo is run"
+msgstr "Invia sempre una email quando viene eseguito sudo"
+
+#: plugins/sudoers/def_data.c:74
+msgid "Send mail if user authentication fails"
+msgstr "Invia una email se l'autenticazione utente non riesce"
+
+#: plugins/sudoers/def_data.c:78
+msgid "Send mail if the user is not in sudoers"
+msgstr "Invia una email se l'utente non è tra i sudoers"
+
+#: plugins/sudoers/def_data.c:82
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Invia una email se l'utente non è tra i sudoers per questo host"
+
+#: plugins/sudoers/def_data.c:86
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Invia una email se l'utente non è abilitato a eseguire un comando"
+
+#: plugins/sudoers/def_data.c:90
+msgid "Send mail if the user tries to run a command"
+msgstr "Invia una email se l'utente tenta di eseguire un comando"
+
+#: plugins/sudoers/def_data.c:94
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Usa una marcatura temporale diversa per ogni combinazione utente/tty"
+
+#: plugins/sudoers/def_data.c:98
+msgid "Lecture user the first time they run sudo"
+msgstr "Aiuta gli utenti alla prima esecuzione di sudo"
+
+#: plugins/sudoers/def_data.c:102
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "File contenente la lezione su sudo: %s"
+
+#: plugins/sudoers/def_data.c:106
+msgid "Require users to authenticate by default"
+msgstr "Richiede in modo predefinito l'autenticazione degli utenti"
+
+#: plugins/sudoers/def_data.c:110
+msgid "Root may run sudo"
+msgstr "Root può eseguire sudo"
+
+#: plugins/sudoers/def_data.c:114
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Registra il nome host nel file di registro (non-syslog)"
+
+#: plugins/sudoers/def_data.c:118
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Registra l'anno nel file di registro (non-syslog)"
+
+#: plugins/sudoers/def_data.c:122
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Se sudo viene lanciato senza alcun argomento, avvia una shell"
+
+#: plugins/sudoers/def_data.c:126
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Imposta $HOME all'utente definito quando viene avviata una shell con -s"
+
+#: plugins/sudoers/def_data.c:130
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Imposta sempre $HOME alla directory home dell'utente definito"
+
+#: plugins/sudoers/def_data.c:134
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Consente la raccolta di alcune informazioni per dare messaggi di errore utili"
+
+#: plugins/sudoers/def_data.c:138
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Richiede nomi host completi nel file sudoers"
+
+#: plugins/sudoers/def_data.c:142
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Apostrofa l'utente quando inserisce una password errata"
+
+#: plugins/sudoers/def_data.c:146
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Consente all'utente di seguire sudo solo se dispone di un tty"
+
+#: plugins/sudoers/def_data.c:150
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "visudo utilizzerà il valore definito nella variabile EDITOR"
+
+#: plugins/sudoers/def_data.c:154
+msgid "Prompt for root's password, not the users's"
+msgstr "Chiede la password di root, non quella dell'utente"
+
+#: plugins/sudoers/def_data.c:158
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Chiede la password dell'utente runas_default, non quella dell'utente"
+
+#: plugins/sudoers/def_data.c:162
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Chiede la password dell'utente definito, non quella dell'invocante"
+
+#: plugins/sudoers/def_data.c:166
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Applica i Defaults nella classe di login dell'utente definito, se presente"
+
+#: plugins/sudoers/def_data.c:170
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Imposta le variabili d'ambiente LOGNAME e USER"
+
+#: plugins/sudoers/def_data.c:174
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Imposta lo uid effettivo all'utente definito, non lo uid reale"
+
+#: plugins/sudoers/def_data.c:178
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Non inizializza il vettore di gruppo con quello dell'utente definito"
+
+#: plugins/sudoers/def_data.c:182
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Lunghezza a cui andare a capo nei file di registro (0 per non andare a capo): %u"
+
+#: plugins/sudoers/def_data.c:186
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Timeout marcatura temporale di autenticazione: %.1f minuti"
+
+#: plugins/sudoers/def_data.c:190
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Timeout per inserimento password: %.1f minuti"
+
+#: plugins/sudoers/def_data.c:194
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Numero di tentativi per l'inserimento della password: %u"
+
+#: plugins/sudoers/def_data.c:198
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "umask da utilizzare o 0777 per utilizzare quella dell'utente: 0%o"
+
+#: plugins/sudoers/def_data.c:202
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Percorso al file di registro: %s"
+
+#: plugins/sudoers/def_data.c:206
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Percorso al programma email: %s"
+
+#: plugins/sudoers/def_data.c:210
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Flag per il programma email: %s"
+
+#: plugins/sudoers/def_data.c:214
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Indirizzo a cui mandare l'email: %s"
+
+#: plugins/sudoers/def_data.c:218
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Indirizzo da cui mandare l'email: %s"
+
+#: plugins/sudoers/def_data.c:222
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Oggetto dell'email: %s"
+
+#: plugins/sudoers/def_data.c:226
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Messaggio password errata: %s"
+
+#: plugins/sudoers/def_data.c:230
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Percorso directory di stato della lezione: %s"
+
+#: plugins/sudoers/def_data.c:234
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Percorso directory con la marcatura temporale di autenticazione: %s"
+
+#: plugins/sudoers/def_data.c:238
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Proprietario directory con la marcatura temporale di autenticazione: %s"
+
+#: plugins/sudoers/def_data.c:242
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Agli utenti di questo gruppo non sono richiesti password e PATH: %s"
+
+#: plugins/sudoers/def_data.c:246
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Prompt predefinito per la password: %s"
+
+#: plugins/sudoers/def_data.c:250
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Se impostato, passprompt scavalcherà sempre il prompt di sistema."
+
+#: plugins/sudoers/def_data.c:254
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Utente predefinito con cui eseguire i comandi: %s"
+
+#: plugins/sudoers/def_data.c:258
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Valore con cui sovrascrivere la variabile $PATH dell'utente: %s"
+
+#: plugins/sudoers/def_data.c:262
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Percorso all'editor per visudo: %s"
+
+#: plugins/sudoers/def_data.c:266
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Quando richiedere una password per il pseudo-comando \"list\": %s"
+
+#: plugins/sudoers/def_data.c:270
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Quando richiedere una password per il pseudo-comando \"verify\": %s"
+
+#: plugins/sudoers/def_data.c:274
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "Carica la libreria sudo_noexec che sostituisce le funzioni exec"
+
+#: plugins/sudoers/def_data.c:278
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Se LDAP è funzionante, viene ignorato il file sudoers locale"
+
+#: plugins/sudoers/def_data.c:282
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "I descrittori di file >= %d verranno chiusi prima dell'esecuzione di un comando"
+
+#: plugins/sudoers/def_data.c:286
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "Se impostata, gli utenti possono sovrascrivere il valore di \"closefrom\" con l'opzione -C"
+
+#: plugins/sudoers/def_data.c:290
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Consente agli utenti di impostare variabili d'ambiente"
+
+#: plugins/sudoers/def_data.c:294
+msgid "Reset the environment to a default set of variables"
+msgstr "Reimposta l'ambiente con le variabili predefinite"
+
+#: plugins/sudoers/def_data.c:298
+msgid "Environment variables to check for safety:"
+msgstr "Variabile d'ambienti da verificare per la sicurezza:"
+
+#: plugins/sudoers/def_data.c:302
+msgid "Environment variables to remove:"
+msgstr "Variabili d'ambiente da rimuovere:"
+
+#: plugins/sudoers/def_data.c:306
+msgid "Environment variables to preserve:"
+msgstr "Variabili d'ambiente da preservare:"
+
+#: plugins/sudoers/def_data.c:310
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "Ruolo SELinux da usare nel nuovo contesto di sicurezza: %s"
+
+#: plugins/sudoers/def_data.c:314
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "Tipologia di SELinux da usare nel nuovo contesto di sicurezza: %s"
+
+#: plugins/sudoers/def_data.c:318
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Percorso al file d'ambiente specifico di sudo: %s"
+
+#: plugins/sudoers/def_data.c:322
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Percorso al file d'ambiente riservato specifico di sudo: %s"
+
+#: plugins/sudoers/def_data.c:326
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Localizzazione da usare durante l'analisi del file sudoers: %s"
+
+#: plugins/sudoers/def_data.c:330
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Abilita sudo a chiedere una password anche se sarebbe visibile"
+
+#: plugins/sudoers/def_data.c:334
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Fornisce riscontro visibile al prompt della password nel caso di input utente"
+
+#: plugins/sudoers/def_data.c:338
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Usa glob più veloce e meno preciso, ma non accede al file system"
+
+#: plugins/sudoers/def_data.c:342
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "La umask definita in sudoers scavalca quella dell'utente, anche se è più permissiva"
+
+#: plugins/sudoers/def_data.c:346
+msgid "Log user's input for the command being run"
+msgstr "Registra l'input dell'utente per il comando in esecuzione"
+
+#: plugins/sudoers/def_data.c:350
+msgid "Log the output of the command being run"
+msgstr "Registra l'output del comando in esecuzione"
+
+#: plugins/sudoers/def_data.c:354
+msgid "Compress I/O logs using zlib"
+msgstr "Comprime i registri utilizzando zlib"
+
+#: plugins/sudoers/def_data.c:358
+msgid "Always run commands in a pseudo-tty"
+msgstr "Esegue sempre i comandi in uno pseudo-tty"
+
+#: plugins/sudoers/def_data.c:362
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Plugin per supporto ai gruppi non-Unix: %s"
+
+#: plugins/sudoers/def_data.c:366
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Directory in cui salvare i registri di I/O: %s"
+
+#: plugins/sudoers/def_data.c:370
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "File in cui salvare il registro I/O: %s"
+
+#: plugins/sudoers/def_data.c:374
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Aggiunge una voce al file utmp/utmpx quando viene allocato un pty"
+
+#: plugins/sudoers/def_data.c:378
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Imposta l'utente in utmp all'utente runas, non l'utente invocante"
+
+#: plugins/sudoers/def_data.c:382
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Insieme di privilegi concessi: %s"
+
+#: plugins/sudoers/def_data.c:386
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Insieme di privilegi non concessi: %s"
+
+#: plugins/sudoers/def_data.c:390
+msgid "Run commands on a pty in the background"
+msgstr "Esegue i comandi in un pty in background"
+
+#: plugins/sudoers/def_data.c:394
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "Nome del servizio PAM da usare: %s"
+
+#: plugins/sudoers/def_data.c:398
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "Nome del servizio PAM da usare per le shell di login: %s"
+
+#: plugins/sudoers/def_data.c:402
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Tentativo di stabilire le credenziali PAM per l'utente finale"
+
+#: plugins/sudoers/def_data.c:406
+msgid "Create a new PAM session for the command to run in"
+msgstr "Crea una nuova sessione PAM in cui eseguire il comando"
+
+#: plugins/sudoers/def_data.c:410
+msgid "Perform PAM account validation management"
+msgstr "Esegue la gestione della convalida dell'account PAM"
+
+#: plugins/sudoers/def_data.c:414
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "Numero massimo di sequenze I/O di registro: %s"
+
+#: plugins/sudoers/def_data.c:418
+msgid "Enable sudoers netgroup support"
+msgstr "Abilita support netgroup in sudoers"
+
+#: plugins/sudoers/def_data.c:422
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Controlla le directory superiori per accesso in scrittura durante le modifiche con sudoedit"
+
+#: plugins/sudoers/def_data.c:426
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Segue i collegamenti simbolici durante le modifiche con sudoedit"
+
+#: plugins/sudoers/def_data.c:430
+msgid "Query the group plugin for unknown system groups"
+msgstr "Interroga il plugin dei gruppi per gruppi di sistema sconosciuti"
+
+#: plugins/sudoers/def_data.c:434
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Corrispondenza gruppi di rete con tutti i valori: utente, host e dominio"
+
+#: plugins/sudoers/def_data.c:438
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Consente di eseguire i comandi anche se sudo non può scrivere sul registro di controllo"
+
+#: plugins/sudoers/def_data.c:442
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Consente di eseguire i comandi anche se sudo non può scrivere sul registro di I/O"
+
+#: plugins/sudoers/def_data.c:446
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Consente di eseguire i comandi anche se sudo non può scrivere sul file di registro"
+
+#: plugins/sudoers/def_data.c:450
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Gestisce i gruppi attraverso sudoers ed esegue la corrispondenza sull'ID del gruppo, non sul nome"
+
+#: plugins/sudoers/def_data.c:454
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Voci di registro più grandi di questo valore vengono divise su più messaggi: %u"
+
+#: plugins/sudoers/def_data.c:458
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Utente proprietario dei file di registro di I/O: %s"
+
+#: plugins/sudoers/def_data.c:462
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Gruppo proprietario dei file di registro di I/O: %s"
+
+#: plugins/sudoers/def_data.c:466
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Modalità dei file di registro di I/O: 0%o"
+
+#: plugins/sudoers/def_data.c:470
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Esegue comandi in base al descrittore del file e non sul percorso: %s"
+
+#: plugins/sudoers/def_data.c:474
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Ignora le voci Defaults sconosciute nel file sudoers invece di inviare un avviso"
+
+#: plugins/sudoers/def_data.c:478
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Tempo in secondi dopo il quale il comando viene terminato: %u"
+
+#: plugins/sudoers/def_data.c:482
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Consente all'utente di specificare un timeout attraverso la riga di comando"
+
+#: plugins/sudoers/def_data.c:486
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Scrive immediatamente i dati I/O del registro sul disco invece di tenerli in memoria"
+
+#: plugins/sudoers/def_data.c:490
+msgid "Include the process ID when logging via syslog"
+msgstr "Include l'ID del processo quando viene usato syslog"
+
+#: plugins/sudoers/def_data.c:494
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Tipo di marcatura temporale di autenticazione: %s"
+
+#: plugins/sudoers/def_data.c:498
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Messaggio di autenticazione non riuscita: %s"
+
+#: plugins/sudoers/def_data.c:502
+msgid "Ignore case when matching user names"
+msgstr "Ignora maiuscole/minuscole nella corrispondenza coi nomi utente"
+
+#: plugins/sudoers/def_data.c:506
+msgid "Ignore case when matching group names"
+msgstr "Ignora maiuscole/minuscole nella corrispondenza coi gruppi"
+
+#: plugins/sudoers/def_data.c:510
+msgid "Log when a command is allowed by sudoers"
+msgstr "Registra quando un comando è consentito da sudoers"
+
+#: plugins/sudoers/def_data.c:514
+msgid "Log when a command is denied by sudoers"
+msgstr "Registra quando un comando viene negato da sudoers"
+
+#: plugins/sudoers/def_data.c:518
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "Server di registro per sudo a cui connettersi, con la porta opzionale"
+
+#: plugins/sudoers/def_data.c:522
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Timeout server di registro per sudo, in secondi: %u"
+
+#: plugins/sudoers/def_data.c:526
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "Abilita l'opzione SO_KEEPALIVE sul socket connesso al server di registro"
+
+#: plugins/sudoers/def_data.c:530
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "Percorso al file bundle CA del server di audit: %s"
+
+#: plugins/sudoers/def_data.c:534
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "Percorso al file certificato di sudoers: %s"
+
+#: plugins/sudoers/def_data.c:538
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "Percorso al file chiave privata di sudoers: %s"
+
+#: plugins/sudoers/def_data.c:542
+msgid "Verify that the log server's certificate is valid"
+msgstr "Verifica che il certificato del server di registro è valido"
+
+#: plugins/sudoers/def_data.c:546
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "Consente l'uso di ID utente o gruppo sconosciuto per runas"
+
+#: plugins/sudoers/def_data.c:550
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "Consente di eseguire i comandi a un utente con una shell valida"
+
+#: plugins/sudoers/def_data.c:554
+msgid "Set the pam remote user to the user running sudo"
+msgstr "Imposta l'utente remoto pam all'utente che esegue sudo"
+
+#: plugins/sudoers/def_data.c:558
+msgid "Set the pam remote host to the local host name"
+msgstr "Imposta l'host remoto pam al nome host locale"
+
+#: plugins/sudoers/def_data.c:562
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "Directory di lavoro a cui passare prima dell'esecuzione del comando: %s"
+
+#: plugins/sudoers/def_data.c:566
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "Directory root a cui passare prima dell'esecuzione del comando: %s"
+
+#: plugins/sudoers/def_data.c:570
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "Il formato dei registri da creare: %s"
+
+#: plugins/sudoers/def_data.c:574
+msgid "Enable SELinux RBAC support"
+msgstr "Abilita il supporto RBAC SELinux"
+
+#: plugins/sudoers/def_data.c:578
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "Percorso del file creato la prima volta che viene eseguito sudo: %s"
+
+#: plugins/sudoers/defaults.c:185
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: voce Defaults \"%s\" sconosciuta"
+
+#: plugins/sudoers/defaults.c:188
+#, c-format
+msgid "%s: unknown defaults entry \"%s\""
+msgstr "%s: voce Defaults \"%s\" sconosciuta"
+
+#: plugins/sudoers/defaults.c:234
+#, c-format
+msgid "%s:%d:%d: no value specified for \"%s\""
+msgstr "%s:%d:%d: nessun valore specificato per \"%s\""
+
+#: plugins/sudoers/defaults.c:237
+#, c-format
+msgid "%s: no value specified for \"%s\""
+msgstr "%s: nessun valore specificato per \"%s\""
+
+#: plugins/sudoers/defaults.c:275
+#, c-format
+msgid "%s:%d:%d: option \"%s\" does not take a value"
+msgstr "%s:%d:%d: l'opzione \"%s\" non accetta un valore"
+
+#: plugins/sudoers/defaults.c:278
+#, c-format
+msgid "%s: option \"%s\" does not take a value"
+msgstr "%s: l'opzione \"%s\" non accetta un valore"
+
+#: plugins/sudoers/defaults.c:303
+#, c-format
+msgid "%s:%d:%d: invalid Defaults type 0x%x for option \"%s\""
+msgstr "%s:%d:%d: tipo Defaults 0x%x non valido per l'opzione \"%s\""
+
+#: plugins/sudoers/defaults.c:306
+#, c-format
+msgid "%s: invalid Defaults type 0x%x for option \"%s\""
+msgstr "%s: tipo Defaults 0x%x non valido per l'opzione \"%s\""
+
+#: plugins/sudoers/defaults.c:316
+#, c-format
+msgid "%s:%d:%d: value \"%s\" is invalid for option \"%s\""
+msgstr "%s:%d:%d: il valore \"%s\" non è valido per l'opzione \"%s\""
+
+#: plugins/sudoers/defaults.c:319
+#, c-format
+msgid "%s: value \"%s\" is invalid for option \"%s\""
+msgstr "%s: il valore \"%s\" non è valido per l'opzione \"%s\""
+
+#: plugins/sudoers/defaults.c:1040
+#, c-format
+msgid "%s:%d:%d: values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "%s:%d:%d: i valori per \"%s\" devono iniziare con un carattere \"/\", \"~\" o \"*\""
+
+#: plugins/sudoers/defaults.c:1044
+#, c-format
+msgid "%s: values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "%s: i valori per \"%s\" devono iniziare con un carattere \"/\", \"~\" o \"*\""
+
+#: plugins/sudoers/defaults.c:1055
+#, c-format
+msgid "%s:%d:%d: values for \"%s\" must start with a '/'"
+msgstr "%s:%d:%d: i valori per \"%s\" devono iniziare con un carattere \"/\""
+
+#: plugins/sudoers/defaults.c:1059
+#, c-format
+msgid "%s: values for \"%s\" must start with a '/'"
+msgstr "%s: i valori per \"%s\" devono iniziare con un carattere \"/\""
+
+#: plugins/sudoers/env.c:412
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: envp danneggiato, discordanza nella lunghezza"
+
+#: plugins/sudoers/env.c:1095
+msgid "unable to rebuild the environment"
+msgstr "impossibile ricostruire l’ambiente"
+
+#: plugins/sudoers/env.c:1169
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "permessi non sufficienti per impostare le seguenti variabili d'ambiente: %s"
+
+#: plugins/sudoers/file.c:107
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr "errore di analisi in %s vicino alla riga %d"
+
+#: plugins/sudoers/file.c:110
+#, c-format
+msgid "parse error in %s"
+msgstr "errore di analisi in %s"
+
+#: plugins/sudoers/filedigest.c:49
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr "tipo di digest %d non supportato per %s"
+
+#: plugins/sudoers/filedigest.c:78
+#, c-format
+msgid "%s: read error"
+msgstr "%s: errore di lettura"
+
+#: plugins/sudoers/group_plugin.c:83
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s deve essere di proprietà dello uid %d"
+
+#: plugins/sudoers/group_plugin.c:87
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr "%s deve essere scrivibile solo dal proprietario"
+
+#: plugins/sudoers/group_plugin.c:96 plugins/sudoers/sssd.c:569
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "impossibile caricare %s: %s"
+
+#: plugins/sudoers/group_plugin.c:102
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "impossibile trovare il simbolo \"group_plugin\" in %s"
+
+#: plugins/sudoers/group_plugin.c:107
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: version major %d del plugin per il gruppo non compatibile, atteso %d"
+
+#: plugins/sudoers/interfaces.c:80 plugins/sudoers/interfaces.c:97
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "impossibile analizzare l'indirizzo IP \"%s\""
+
+#: plugins/sudoers/interfaces.c:85 plugins/sudoers/interfaces.c:102
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "impossibile analizzare la maschera di rete \"%s\""
+
+#: plugins/sudoers/interfaces.c:130
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Coppia indirizzo IP locale e maschera di rete:\n"
+
+#: plugins/sudoers/iolog.c:143 plugins/sudoers/sudoers.c:437
+#: plugins/sudoers/sudoers.c:1317 plugins/sudoers/testsudoers.c:406
+#, c-format
+msgid "unknown group: %s"
+msgstr "gruppo sconosciuto: %s"
+
+#: plugins/sudoers/iolog.c:635
+msgid "unable to update sequence file"
+msgstr "impossibile aggiornare il file sequenza"
+
+#: plugins/sudoers/iolog.c:666 plugins/sudoers/iolog.c:854
+#: plugins/sudoers/iolog.c:1007 plugins/sudoers/iolog.c:1014
+#: plugins/sudoers/iolog.c:1135 plugins/sudoers/iolog.c:1142
+#: plugins/sudoers/iolog.c:1241 plugins/sudoers/iolog.c:1248
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "impossibile scrivere sul file di registro di I/O: %s"
+
+#: plugins/sudoers/iolog.c:674
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "impossibile creare %s/%s"
+
+#: plugins/sudoers/iolog.c:899
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: errore interno, file registro IO per l'evento %d non aperto"
+
+#: plugins/sudoers/iolog.c:992 plugins/sudoers/iolog.c:1120
+#: plugins/sudoers/iolog.c:1225 plugins/sudoers/timestamp.c:849
+#: plugins/sudoers/timestamp.c:941 plugins/sudoers/visudo.c:487
+#: plugins/sudoers/visudo.c:493
+msgid "unable to read the clock"
+msgstr "impossibile leggere l'orologio"
+
+#: plugins/sudoers/iolog.c:1217 plugins/sudoers/log_client.c:1199
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: errore interno, segnale %d non valido"
+
+#: plugins/sudoers/ldap.c:177 plugins/sudoers/ldap_conf.c:291
+msgid "starttls not supported when using ldaps"
+msgstr "starttls non supportato quando viene utilizzato ldaps"
+
+#: plugins/sudoers/ldap.c:248
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "impossibile inizializzare il certificato SSL e il database delle chiavi: %s"
+
+#: plugins/sudoers/ldap.c:251
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "è necessario impostare TLS_CERT in %s per usare SSL"
+
+#: plugins/sudoers/ldap.c:1660
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "impossibile inizializzare LDAP: %s"
+
+#: plugins/sudoers/ldap.c:1697
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "specificato start_tls ma le librerie LDAP non supportano ldap_start_tls_s() o ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:1834 plugins/sudoers/parse_ldif.c:746
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "attributo sudoOrder non valido: %s"
+
+#: plugins/sudoers/ldap_conf.c:200
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: porta troppo grande"
+
+#: plugins/sudoers/ldap_conf.c:260
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "tipologia di uri LDAP non supportata: %s"
+
+#: plugins/sudoers/ldap_conf.c:287
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "impossibile utilizzare URI ldap e ldaps assieme"
+
+#: plugins/sudoers/ldap_util.c:529 plugins/sudoers/ldap_util.c:536
+#: plugins/sudoers/ldap_util.c:544 plugins/sudoers/ldap_util.c:553
+#: plugins/sudoers/ldap_util.c:561 plugins/sudoers/ldap_util.c:571
+#: plugins/sudoers/ldap_util.c:579
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "sudoOption duplicato: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:598 plugins/sudoers/ldap_util.c:600
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "impossibile convertire sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "impossibile aprire il sistema di audit"
+
+#: plugins/sudoers/linux_audit.c:103
+msgid "unable to send audit message"
+msgstr "impossibile inviare il messaggio di audit"
+
+#: plugins/sudoers/log_client.c:113 plugins/sudoers/log_client.c:391
+#: plugins/sudoers/log_client.c:1437 plugins/sudoers/log_client.c:2031
+msgid "error in event loop"
+msgstr "errore nel ciclo dell'evento"
+
+#: plugins/sudoers/log_client.c:193
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "Creazione di un nuovo oggetto SSL_CTX non riuscita: %s"
+
+#: plugins/sudoers/log_client.c:216
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "impossibile caricare il bundle CA %s"
+
+#: plugins/sudoers/log_client.c:236
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "impossibile caricare il certificato %s"
+
+#: plugins/sudoers/log_client.c:249
+#, c-format
+msgid "unable to load private key %s"
+msgstr "impossibile caricare la chiave privata %s"
+
+#: plugins/sudoers/log_client.c:258
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "Impossibile allocare l'oggetto ssl: %s"
+
+#: plugins/sudoers/log_client.c:345 plugins/sudoers/log_client.c:350
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "Connessione TLS a %s:%s non riuscita: %s"
+
+#: plugins/sudoers/log_client.c:519
+msgid "TLS initialization was unsuccessful"
+msgstr "inizializzazione TLS non riuscita"
+
+#: plugins/sudoers/log_client.c:528
+msgid "TLS handshake was unsuccessful"
+msgstr "handshake TLS non riuscito"
+
+#: plugins/sudoers/log_client.c:1208
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: errore interno, stato di uscita %d non valido"
+
+#: plugins/sudoers/log_client.c:1724 plugins/sudoers/log_client.c:1748
+msgid "lost connection to log server"
+msgstr "connessione al server del registro persa"
+
+#: plugins/sudoers/log_client.c:1825
+msgid "missing write buffer"
+msgstr "manca il buffer in scrittura"
+
+#: plugins/sudoers/log_client.c:1972
+msgid "unable to connect to log server"
+msgstr "impossibile connettersi al server del registro"
+
+#: plugins/sudoers/logging.c:244
+msgid "user NOT in sudoers"
+msgstr "utente non tra i sudoers"
+
+#: plugins/sudoers/logging.c:246
+msgid "user NOT authorized on host"
+msgstr "utente non autorizzato sull'host"
+
+#: plugins/sudoers/logging.c:248
+msgid "command not allowed"
+msgstr "comando non consentito"
+
+#: plugins/sudoers/logging.c:269
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr "%s non è nel file sudoers. Questo evento verrà segnalato.\n"
+
+#: plugins/sudoers/logging.c:272
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr "A %s non è consentito eseguire sudo su %s. Questo evento verrà segnalato.\n"
+
+#: plugins/sudoers/logging.c:276
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "L'utente %s non può eseguire sudo su %s.\n"
+
+#: plugins/sudoers/logging.c:279
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr "All'utente %s non è consentito eseguire \"%s%s%s\" come %s%s%s su %s.\n"
+
+#: plugins/sudoers/logging.c:316 plugins/sudoers/sudoers.c:575
+#: plugins/sudoers/sudoers.c:577 plugins/sudoers/sudoers.c:579
+#: plugins/sudoers/sudoers.c:581 plugins/sudoers/sudoers.c:723
+#: plugins/sudoers/sudoers.c:725
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: comando non trovato"
+
+#: plugins/sudoers/logging.c:318 plugins/sudoers/sudoers.c:571
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"viene ignorato \"%s\" trovato in \".\"\n"
+"Usare \"sudo ./%s\" per eseguire \"%s\"."
+
+#: plugins/sudoers/logging.c:337
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u tentativo di immissione password non corretto"
+msgstr[1] "%u tentativi di immissione password non corretti"
+
+#: plugins/sudoers/logging.c:393
+msgid "authentication failure"
+msgstr "autenticazione non riuscita"
+
+#: plugins/sudoers/logging.c:433 plugins/sudoers/logging.c:453
+msgid "a password is required"
+msgstr "è necessaria una password"
+
+#: plugins/sudoers/logging.c:739
+#, c-format
+msgid "unable to open log file: %s"
+msgstr "impossibile aprire il file di registro: %s"
+
+#: plugins/sudoers/logging.c:772
+#, c-format
+msgid "unable to write log file: %s"
+msgstr "impossibile scrivere sul file di registro: %s"
+
+#: plugins/sudoers/match_digest.c:129
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "il digest per %s (%s) non è nella forma %s"
+
+#: plugins/sudoers/parse.c:530
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+"\n"
+"Ruolo LDAP: %s\n"
+
+#: plugins/sudoers/parse.c:533
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+"\n"
+"Voce sudoers:\n"
+
+#: plugins/sudoers/parse.c:535
+msgid " RunAsUsers: "
+msgstr " RunAsUsers: "
+
+#: plugins/sudoers/parse.c:550
+msgid " RunAsGroups: "
+msgstr " RunAsGroups: "
+
+#: plugins/sudoers/parse.c:560
+msgid " Options: "
+msgstr " Opzioni: "
+
+#: plugins/sudoers/parse.c:614
+msgid " Commands:\n"
+msgstr " Comandi:\n"
+
+#: plugins/sudoers/parse.c:805
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Corrispondenza voci Defaults per %s su %s:\n"
+
+#: plugins/sudoers/parse.c:823
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Valori predefiniti per Runas e Command per %s:\n"
+
+#: plugins/sudoers/parse.c:841
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "L'utente %s può eseguire i seguenti comandi su %s:\n"
+
+#: plugins/sudoers/parse.c:856
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "L'utente %s non è abilitato all'esecuzione di sudo su %s.\n"
+
+#: plugins/sudoers/parse_ldif.c:616
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "ignorato sudoRole non completo: cn: %s"
+
+#: plugins/sudoers/parse_ldif.c:676
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "attributo LDIF non valido: %s"
+
+#: plugins/sudoers/policy.c:78 plugins/sudoers/policy.c:108
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "%.*s non valido impostato dal front-end sudo"
+
+#: plugins/sudoers/policy.c:314 plugins/sudoers/testsudoers.c:268
+msgid "unable to parse network address list"
+msgstr "impossibile analizzare l'elenco degli indirizzi di rete"
+
+#: plugins/sudoers/policy.c:465
+msgid "user name not set by sudo front-end"
+msgstr "nome utente non impostato dal front-end sudo"
+
+#: plugins/sudoers/policy.c:469
+msgid "user-ID not set by sudo front-end"
+msgstr "ID utente non impostato dal front-end sudo"
+
+#: plugins/sudoers/policy.c:473
+msgid "group-ID not set by sudo front-end"
+msgstr "ID gruppo non impostato dal front-end sudo"
+
+#: plugins/sudoers/policy.c:477
+msgid "host name not set by sudo front-end"
+msgstr "nome dell'host non impostato dal front-end sudo"
+
+#: plugins/sudoers/policy.c:660
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "directory di lavoro non valida: %s"
+
+#: plugins/sudoers/policy.c:828
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "directory chroot non valida: %s"
+
+#: plugins/sudoers/policy.c:963 plugins/sudoers/visudo.c:229
+#: plugins/sudoers/visudo.c:851
+#, c-format
+msgid "unable to execute %s"
+msgstr "impossibile eseguire %s"
+
+#: plugins/sudoers/policy.c:1030 plugins/sudoers/policy.c:1067
+#: plugins/sudoers/policy.c:1089 plugins/sudoers/policy.c:1115
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: flag in modalità non valida dal front-end sudo: 0x%x"
+
+#: plugins/sudoers/policy.c:1146
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Versione %s del plugin della politica sudoers\n"
+
+#: plugins/sudoers/policy.c:1148
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Versione %d della grammatica del file sudoers\n"
+
+#: plugins/sudoers/policy.c:1152
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Percorso sudoers: %s\n"
+
+#: plugins/sudoers/policy.c:1155
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "percorso nsswitch: %s\n"
+
+#: plugins/sudoers/policy.c:1157
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "percorso ldap.conf: %s\n"
+
+#: plugins/sudoers/policy.c:1158
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "percorso ldap.secret: %s\n"
+
+#: plugins/sudoers/policy.c:1191
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "impossibile registrare un hook di tipo %d (versione %d.%d)"
+
+#: plugins/sudoers/policy.c:1209
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "impossibile annullare la registrazione dell'hook di tipo %d (versione %d.%d)"
+
+#: plugins/sudoers/pwutil.c:218 plugins/sudoers/pwutil.c:236
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "impossibile memorizzare in cache lo uid %u"
+
+#: plugins/sudoers/pwutil.c:230
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "impossibile memorizzare in cache lo uid %u, esiste già"
+
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:308
+#: plugins/sudoers/pwutil.c:371 plugins/sudoers/pwutil.c:416
+#, c-format
+msgid "unable to cache user %s"
+msgstr "impossibile memorizzare in cache l'utente %s"
+
+#: plugins/sudoers/pwutil.c:303
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "impossibile memorizzare in cache l'utente %s, esiste già"
+
+#: plugins/sudoers/pwutil.c:535 plugins/sudoers/pwutil.c:553
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "impossibile memorizzare in cache il gid %u"
+
+#: plugins/sudoers/pwutil.c:547
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "impossibile memorizzare in cache il gid %u, esiste già"
+
+#: plugins/sudoers/pwutil.c:601 plugins/sudoers/pwutil.c:619
+#: plugins/sudoers/pwutil.c:680 plugins/sudoers/pwutil.c:729
+#, c-format
+msgid "unable to cache group %s"
+msgstr "impossibile memorizzare in cache il gruppo %s"
+
+#: plugins/sudoers/pwutil.c:614
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "impossibile memorizzare in cache il gruppo %s, esiste già"
+
+#: plugins/sudoers/pwutil.c:876 plugins/sudoers/pwutil.c:927
+#: plugins/sudoers/pwutil.c:977 plugins/sudoers/pwutil.c:1029
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "impossibile memorizzare in cache l'elenco di gruppo %s, esiste già"
+
+#: plugins/sudoers/pwutil.c:882 plugins/sudoers/pwutil.c:932
+#: plugins/sudoers/pwutil.c:983 plugins/sudoers/pwutil.c:1034
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "impossibile memorizzare in cache l'elenco di gruppo %s"
+
+#: plugins/sudoers/pwutil.c:921
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "impossibile analizzare i gruppi per %s"
+
+#: plugins/sudoers/pwutil.c:1023
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "impossibile analizzare i gid per %s"
+
+#: plugins/sudoers/set_perms.c:114 plugins/sudoers/set_perms.c:441
+#: plugins/sudoers/set_perms.c:844 plugins/sudoers/set_perms.c:1150
+#: plugins/sudoers/set_perms.c:1444
+msgid "perm stack overflow"
+msgstr "overflow dello stack perm"
+
+#: plugins/sudoers/set_perms.c:122 plugins/sudoers/set_perms.c:372
+#: plugins/sudoers/set_perms.c:449 plugins/sudoers/set_perms.c:711
+#: plugins/sudoers/set_perms.c:852 plugins/sudoers/set_perms.c:1074
+#: plugins/sudoers/set_perms.c:1158 plugins/sudoers/set_perms.c:1377
+#: plugins/sudoers/set_perms.c:1452 plugins/sudoers/set_perms.c:1542
+msgid "perm stack underflow"
+msgstr "underflow dello stack perm"
+
+#: plugins/sudoers/set_perms.c:181 plugins/sudoers/set_perms.c:495
+#: plugins/sudoers/set_perms.c:1211 plugins/sudoers/set_perms.c:1485
+msgid "unable to change to root gid"
+msgstr "impossibile passare al gid root"
+
+#: plugins/sudoers/set_perms.c:272 plugins/sudoers/set_perms.c:592
+#: plugins/sudoers/set_perms.c:983 plugins/sudoers/set_perms.c:1288
+msgid "unable to change to runas gid"
+msgstr "impossibile passare al gid runas"
+
+#: plugins/sudoers/set_perms.c:277 plugins/sudoers/set_perms.c:597
+#: plugins/sudoers/set_perms.c:988 plugins/sudoers/set_perms.c:1293
+msgid "unable to set runas group vector"
+msgstr "impossibile impostare il vettore di gruppo per runas"
+
+#: plugins/sudoers/set_perms.c:288 plugins/sudoers/set_perms.c:608
+#: plugins/sudoers/set_perms.c:997 plugins/sudoers/set_perms.c:1302
+msgid "unable to change to runas uid"
+msgstr "impossibile passare allo uid runas"
+
+#: plugins/sudoers/set_perms.c:306 plugins/sudoers/set_perms.c:626
+#: plugins/sudoers/set_perms.c:1013 plugins/sudoers/set_perms.c:1318
+msgid "unable to change to sudoers gid"
+msgstr "impossibile passare al gid sudoers"
+
+#: plugins/sudoers/set_perms.c:359 plugins/sudoers/set_perms.c:698
+#: plugins/sudoers/set_perms.c:1061 plugins/sudoers/set_perms.c:1364
+#: plugins/sudoers/set_perms.c:1529
+msgid "too many processes"
+msgstr "troppi processi"
+
+#: plugins/sudoers/solaris_audit.c:61
+msgid "unable to get current working directory"
+msgstr "impossibile ottenere la directory di lavoro corrente"
+
+#: plugins/sudoers/solaris_audit.c:69
+#, c-format
+msgid "truncated audit path user_cmnd: %s"
+msgstr "percorso audit user_cmnd troncato: %s"
+
+#: plugins/sudoers/solaris_audit.c:76
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "percorso audit argv[0] troncato: %s"
+
+#: plugins/sudoers/sssd.c:572
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "impossibile inizializzare la sorgente SSS. È stato installato SSSD?"
+
+#: plugins/sudoers/sssd.c:580 plugins/sudoers/sssd.c:589
+#: plugins/sudoers/sssd.c:598 plugins/sudoers/sssd.c:607
+#: plugins/sudoers/sssd.c:616
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "impossibile trovare il simbolo \"%s\" in %s"
+
+#: plugins/sudoers/sudoers.c:213 plugins/sudoers/sudoers.c:985
+msgid "problem with defaults entries"
+msgstr "problema con le voci Defaults"
+
+#: plugins/sudoers/sudoers.c:217
+msgid "no valid sudoers sources found, quitting"
+msgstr "nessuna sorgente valida di sudoers trovata, uscita"
+
+#: plugins/sudoers/sudoers.c:291
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "l'utente non è autorizzato a cambiare la directory root a %s"
+
+#: plugins/sudoers/sudoers.c:293
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "non è consentito l'uso dell'opzione -R con %s"
+
+#: plugins/sudoers/sudoers.c:318
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "l'utente non è autorizzato a cambiare directory a %s"
+
+#: plugins/sudoers/sudoers.c:319
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "non è consentito l'uso dell'opzione -D con %s"
+
+#: plugins/sudoers/sudoers.c:345
+msgid "no command specified"
+msgstr "nessun comando specificato"
+
+#: plugins/sudoers/sudoers.c:355
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers indica che a root non è consentito usare sudo"
+
+#: plugins/sudoers/sudoers.c:403
+msgid "user not allowed to override closefrom limit"
+msgstr "l'utente non è autorizzato a scavalcare il limite closefrom"
+
+#: plugins/sudoers/sudoers.c:404
+msgid "you are not permitted to use the -C option"
+msgstr "utente non abilitato all'uso dell'opzione -C"
+
+#: plugins/sudoers/sudoers.c:464
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr "proprietario marcatura temporale (%s): utente inesistente"
+
+#: plugins/sudoers/sudoers.c:479
+msgid "no tty"
+msgstr "nessun tty"
+
+#: plugins/sudoers/sudoers.c:480
+msgid "sorry, you must have a tty to run sudo"
+msgstr "è necessario disporre di un tty per eseguire sudo"
+
+#: plugins/sudoers/sudoers.c:487
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "shell utente %s non valida: %s"
+
+#: plugins/sudoers/sudoers.c:570
+msgid "command in current directory"
+msgstr "comando nella directory corrente"
+
+#: plugins/sudoers/sudoers.c:589
+msgid "user not allowed to set a command timeout"
+msgstr "l'utente non è autorizzato a impostare un timeout per i comandi"
+
+#: plugins/sudoers/sudoers.c:591
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "non è consentito impostare un timeout per i comandi"
+
+#: plugins/sudoers/sudoers.c:599
+msgid "user not allowed to preserve the environment"
+msgstr "l'utente non è autorizzato a preservare l'ambiente"
+
+#: plugins/sudoers/sudoers.c:601
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "non è consentito preservare l'ambiente"
+
+#: plugins/sudoers/sudoers.c:936
+msgid "command too long"
+msgstr "comando troppo lungo"
+
+#: plugins/sudoers/sudoers.c:973
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "non è necessario eseguire sudoedit via sudo"
+
+#: plugins/sudoers/sudoers.c:1032 plugins/sudoers/sudoreplay.c:1547
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "impossibile leggere %s"
+
+#: plugins/sudoers/sudoers.c:1057 plugins/sudoers/visudo.c:426
+#: plugins/sudoers/visudo.c:720
+#, c-format
+msgid "unable to stat %s"
+msgstr "impossibile eseguire stat su %s"
+
+#: plugins/sudoers/sudoers.c:1061 plugins/sudoers/visudo.c:1009
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s non è un file regolare"
+
+#: plugins/sudoers/sudoers.c:1065 plugins/sudoers/timestamp.c:252 toke.l:1138
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s è di proprietà dello uid %u, dovrebbe essere %u"
+
+#: plugins/sudoers/sudoers.c:1069 toke.l:1143
+#, c-format
+msgid "%s is world writable"
+msgstr "%s è scrivibile da tutti"
+
+#: plugins/sudoers/sudoers.c:1073 toke.l:1146
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s è di proprietà del gid %u, dovrebbe essere %u"
+
+#: plugins/sudoers/sudoers.c:1106
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "solo root può usare \"-c %s\""
+
+#: plugins/sudoers/sudoers.c:1125
+#, c-format
+msgid "unknown login class: %s"
+msgstr "classe di login sconosciuta: %s"
+
+#: plugins/sudoers/sudoers.c:1211 plugins/sudoers/sudoers.c:1226
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "impossibile risolvere l'host %s"
+
+#: plugins/sudoers/sudoreplay.c:257
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "opzione di filtro non valida: %s"
+
+#: plugins/sudoers/sudoreplay.c:273
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "attesa massima non valida: %s"
+
+#: plugins/sudoers/sudoreplay.c:296
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "fattore di velocità non valido: %s"
+
+#: plugins/sudoers/sudoreplay.c:332
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:337
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/timing: %s"
+
+#: plugins/sudoers/sudoreplay.c:341
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: plugins/sudoers/sudoreplay.c:365
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Riproduzione della sessione sudo: %s"
+
+#: plugins/sudoers/sudoreplay.c:627
+msgid "unable to set tty to raw mode"
+msgstr "impossibile impostare il terminale in modalità raw"
+
+#: plugins/sudoers/sudoreplay.c:678
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr "Attenzione: il terminale è troppo piccolo per riprodurre correttamente il registro.\n"
+
+#: plugins/sudoers/sudoreplay.c:679
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "La geometria del registro è %dx%d, quella del terminale è %dx%d."
+
+#: plugins/sudoers/sudoreplay.c:707
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Riproduzione terminata. Premere un tasto per ripristinare il terminale."
+
+#: plugins/sudoers/sudoreplay.c:1197 plugins/sudoers/sudoreplay.c:1227
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "espressione \"%s\" ambigua"
+
+#: plugins/sudoers/sudoreplay.c:1249
+msgid "unmatched ')' in expression"
+msgstr "carattere \")\" nell'espressione non corrisposto"
+
+#: plugins/sudoers/sudoreplay.c:1253
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "termine di ricerca \"%s\" sconosciuto"
+
+#: plugins/sudoers/sudoreplay.c:1268
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s richiede un argomento"
+
+#: plugins/sudoers/sudoreplay.c:1271 plugins/sudoers/sudoreplay.c:1523
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr "espressione regolare non valida: %s"
+
+#: plugins/sudoers/sudoreplay.c:1276
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "impossibile analizzare la data \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1285
+msgid "unmatched '(' in expression"
+msgstr "carattere \"(\" nell'espressione non corrisposto"
+
+#: plugins/sudoers/sudoreplay.c:1287
+msgid "illegal trailing \"or\""
+msgstr "\"or\" finale non consentito"
+
+#: plugins/sudoers/sudoreplay.c:1289
+msgid "illegal trailing \"!\""
+msgstr "carattere \"!\" finale non consentito"
+
+#: plugins/sudoers/sudoreplay.c:1347
+#, c-format
+msgid "unknown search type %d"
+msgstr "tipo di ricerca %d sconosciuto"
+
+#: plugins/sudoers/sudoreplay.c:1614
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "uso: %s [-hnRS] [-d DIR] [-m NUM] [-s NUM] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1617
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "uso: %s [-h] [-d DIR] -l [ESPRESSIONE DI RICERCA]\n"
+
+#: plugins/sudoers/sudoreplay.c:1626
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - Riproduce i registri di sessione di sudo\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1628
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Opzioni:\n"
+" -d, --directory=DIR Specifica la directory per i registri di sessione\n"
+" -f, --filter=FILTRO Specifica il tipo di I/O da mostrare\n"
+" -h, --help Visualizza il messaggio di aiuto ed esce\n"
+" -l, --list Elenca gli ID di sessione disponibili corrispondenti\n"
+" -m, --max-wait=NUM Secondi da attendere tra gli eventi\n"
+" -n, --non-interactive Non interattivo, la sessione è inviato all'output standard\n"
+" -R, --no-resize Non ridimensiona il terminale\n"
+" -S, --suspend-wait Attende mentre il comando è sospeso\n"
+" -s, --speed=NUME Velocizza o rallenta l'output\n"
+" -V, --version Visualizza la versione ed esce"
+
+#: plugins/sudoers/testsudoers.c:344
+msgid "\thost unmatched"
+msgstr "\thost non corrispondente"
+
+#: plugins/sudoers/testsudoers.c:347
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Comando consentito"
+
+#: plugins/sudoers/testsudoers.c:348
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Comando negato"
+
+#: plugins/sudoers/testsudoers.c:348
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Comando non corrispondente"
+
+#: plugins/sudoers/timestamp.c:260
+#, c-format
+msgid "%s is group writable"
+msgstr "%s è scrivibile da tutti"
+
+#: plugins/sudoers/timestamp.c:328 plugins/sudoers/timestamp.c:663
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "impossibile troncare il file della marcatura temporale a %lld byte"
+
+#: plugins/sudoers/timestamp.c:860
+msgid "ignoring time stamp from the future"
+msgstr "marcatura temporale dal futuro ignorata"
+
+#: plugins/sudoers/timestamp.c:883
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "marcatura temporale troppo avanti nel tempo: %20.20s"
+
+#: plugins/sudoers/timestamp.c:1005
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "impossibile bloccare il file della marcatura temporale %s"
+
+#: plugins/sudoers/timestamp.c:1049 plugins/sudoers/timestamp.c:1069
+#, c-format
+msgid "lecture status path too long: %s/%s"
+msgstr "percorso dello stato della lezione troppo lungo: %s %s"
+
+#: plugins/sudoers/toke_util.c:150
+msgid "sudoedit should not be specified with a path"
+msgstr "sudoedit non dovrebbe essere specificato con un percorso"
+
+#: plugins/sudoers/visudo.c:224
+msgid "the -x option will be removed in a future release"
+msgstr "l'opzione -x verrà rimossa in una prossima versione"
+
+#: plugins/sudoers/visudo.c:226
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "utilizzare lo strumento cvtsudoers al suo posto"
+
+#: plugins/sudoers/visudo.c:277 plugins/sudoers/visudo.c:653
+#, c-format
+msgid "press return to edit %s: "
+msgstr "premere Invio per modificare %s: "
+
+#: plugins/sudoers/visudo.c:338
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "l'editor specificato (%s) non esiste"
+
+#: plugins/sudoers/visudo.c:340
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "nessun editor trovato (percorso dell'editor = %s)"
+
+#: plugins/sudoers/visudo.c:446 plugins/sudoers/visudo.c:454
+msgid "write error"
+msgstr "errore di scrittura"
+
+#: plugins/sudoers/visudo.c:500
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "impossibile eseguire stat sul file temporaneo (%s), %s non modificato"
+
+#: plugins/sudoers/visudo.c:507
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "file temporaneo di lunghezza pari a zero (%s), %s non modificato"
+
+#: plugins/sudoers/visudo.c:513
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "editor (%s) non riuscito, %s non modificato"
+
+#: plugins/sudoers/visudo.c:535
+#, c-format
+msgid "%s unchanged"
+msgstr "%s non modificato"
+
+#: plugins/sudoers/visudo.c:592
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "impossibile riaprire il file temporaneo (%s), %s non modificato."
+
+#: plugins/sudoers/visudo.c:604
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "impossibile analizzare il file temporaneo (%s), errore sconosciuto"
+
+#: plugins/sudoers/visudo.c:642
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr "errore interno, impossibile trovare %s nell'elenco."
+
+#: plugins/sudoers/visudo.c:722 plugins/sudoers/visudo.c:731
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "impossibile impostare (uid, gid) di %s a (%u, %u)"
+
+#: plugins/sudoers/visudo.c:754
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s e %s non sono sullo stesso file system, viene usato \"mv\" per rinominare"
+
+#: plugins/sudoers/visudo.c:765
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "comando non riuscito: \"%s %s %s\", %s non modificato"
+
+#: plugins/sudoers/visudo.c:775
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "errore nel rinominare %s, %s non è stato modificato"
+
+#: plugins/sudoers/visudo.c:796
+msgid "What now? "
+msgstr "Che fare ora? "
+
+#: plugins/sudoers/visudo.c:810
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Le opzioni sono:\n"
+" (e) Modifica nuovamente il file sudoers\n"
+" (x) Esce senza salvare le modifiche al file sudoers\n"
+" (Q) Esce e salva le modifiche al file sudoers (pericoloso)\n"
+
+#: plugins/sudoers/visudo.c:856
+#, c-format
+msgid "unable to run %s"
+msgstr "impossibile avviare %s"
+
+#: plugins/sudoers/visudo.c:886
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: proprietario errato (uid, gid), dovrebbe essere (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:893
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: permessi errati, dovrebbe avere modalità 0%o\n"
+
+#: plugins/sudoers/visudo.c:942 plugins/sudoers/visudo.c:949
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: analisi effettuata correttamente\n"
+
+#: plugins/sudoers/visudo.c:968
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s occupato, riprovare"
+
+#: plugins/sudoers/visudo.c:971
+#, c-format
+msgid "unable to lock %s"
+msgstr "impossibile bloccare %s"
+
+#: plugins/sudoers/visudo.c:972
+msgid "Edit anyway? [y/N]"
+msgstr "Modificare comunque? [y/N]"
+
+#: plugins/sudoers/visudo.c:1067
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "Attenzione: %s:%d:%d: inutilizzato %s \"%s\""
+
+#: plugins/sudoers/visudo.c:1183
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr "%s - Modifica in sicurezza il file sudoers\n"
+
+#: plugins/sudoers/visudo.c:1185
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Opzioni:\n"
+" -c, --check Modalità solo verifica\n"
+" -f, --file=sudoers Specifica la posizione del file sudoers\n"
+" -h, --help Visualizza il messaggio di aiuto ed esce\n"
+" -q, --quiet Messaggi di errore meno prolissi\n"
+" -s, --strict Verifica precisa della sintassi\n"
+" -V, --version Visualizza la versione ed esce\n"
+
+#: toke.l:187
+msgid "empty string"
+msgstr "stringa vuota"
+
+#: toke.l:199 toke.l:503
+msgid "empty group"
+msgstr "gruppo vuoto"
+
+#: toke.l:209 toke.l:501
+msgid "empty netgroup"
+msgstr "netgroup vuoto"
+
+#: toke.l:305 toke.l:317 toke.l:329 toke.l:345 toke.l:364 toke.l:404
+msgid "invalid line continuation"
+msgstr "continuazione riga non valida"
+
+#: toke.l:540 toke.l:552
+msgid "invalid IPv6 address"
+msgstr "indirizzo IPv6 non valido"
+
+#: toke.l:779
+msgid "unexpected line break in string"
+msgstr "interruzione riga non attesa nella stringa"
+
+#: toke.l:1109
+msgid "too many levels of includes"
+msgstr "troppi livelli di inclusioni"
diff --git a/plugins/sudoers/po/ja.mo b/plugins/sudoers/po/ja.mo
new file mode 100644
index 0000000..19caad3
--- /dev/null
+++ b/plugins/sudoers/po/ja.mo
Binary files differ
diff --git a/plugins/sudoers/po/ja.po b/plugins/sudoers/po/ja.po
new file mode 100644
index 0000000..8af9249
--- /dev/null
+++ b/plugins/sudoers/po/ja.po
@@ -0,0 +1,4210 @@
+# Japanese messages for sudoers
+# This file is put in the public domain.
+# Yasuaki Taniguchi <yasuakit@gmail.com>, 2011.
+# Takeshi Hamasaki <hmatrjp@users.sourceforge.jp>, 2012, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.9.15b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-10-19 10:02-0600\n"
+"PO-Revision-Date: 2023-10-21 20:53+0900\n"
+"Last-Translator: Takeshi Hamasaki <hmatrjp@users.sourceforge.jp>\n"
+"Language-Team: Japanese <translation-team-ja@lists.sourceforge.net>\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Poedit-Basepath: sudo-1.9.12b2\n"
+"X-Generator: Poedit 3.2.2\n"
+"X-Poedit-SearchPath-0: .\n"
+
+#: confstr.sh:1 gram.y:1257 plugins/sudoers/logging.c:911
+msgid "syntax error"
+msgstr "構文エラー"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "%p のパスワード:"
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] %p のパスワード:"
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "パスワード: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** %h のセキュリティ情報 ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "残念、また試してください。"
+
+#: gram.y:238 gram.y:305 gram.y:314 gram.y:323 gram.y:333 gram.y:343 gram.y:367
+#: gram.y:394 gram.y:403 gram.y:411 gram.y:420 gram.y:429 gram.y:503 gram.y:513
+#: gram.y:525 gram.y:573 gram.y:582 gram.y:591 gram.y:600 gram.y:733 gram.y:742
+#: gram.y:757 gram.y:777 gram.y:796 gram.y:959 gram.y:964 gram.y:972 gram.y:986
+#: gram.y:992 gram.y:1004 gram.y:1010 gram.y:1135 gram.y:1144 gram.y:1152
+#: gram.y:1161 gram.y:1170 gram.y:1199 gram.y:1208 gram.y:1216 gram.y:1317
+#: gram.y:1447 gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:313 lib/eventlog/eventlog.c:765
+#: lib/eventlog/eventlog.c:842 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:484
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:185
+#: logsrvd/iolog_writer.c:218 logsrvd/iolog_writer.c:228
+#: logsrvd/iolog_writer.c:257 logsrvd/iolog_writer.c:278
+#: logsrvd/iolog_writer.c:290 logsrvd/iolog_writer.c:300
+#: logsrvd/iolog_writer.c:310 logsrvd/iolog_writer.c:320
+#: logsrvd/iolog_writer.c:330 logsrvd/iolog_writer.c:342
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:1057 logsrvd/logsrvd.c:1120 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:650
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1743
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:216
+#: logsrvd/logsrvd_journal.c:217 logsrvd/logsrvd_journal.c:274
+#: logsrvd/logsrvd_journal.c:279 logsrvd/logsrvd_journal.c:439
+#: logsrvd/logsrvd_journal.c:441 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:216 logsrvd/logsrvd_local.c:278
+#: logsrvd/logsrvd_local.c:279 logsrvd/logsrvd_local.c:417
+#: logsrvd/logsrvd_local.c:468 logsrvd/logsrvd_local.c:469
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:475
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/logsrvd_relay.c:446
+#: logsrvd/logsrvd_relay.c:748 logsrvd/logsrvd_relay.c:855
+#: logsrvd/sendlog.c:256 logsrvd/sendlog.c:265 logsrvd/sendlog.c:297
+#: logsrvd/sendlog.c:303 logsrvd/sendlog.c:352 logsrvd/sendlog.c:630
+#: logsrvd/sendlog.c:1822 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/bsdauth.c:154 plugins/sudoers/auth/kerb5.c:122
+#: plugins/sudoers/auth/kerb5.c:150 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/auth/sia.c:61
+#: plugins/sudoers/canon_path.c:129 plugins/sudoers/canon_path.c:161
+#: plugins/sudoers/check_aliases.c:128 plugins/sudoers/check_util.c:56
+#: plugins/sudoers/check_util.c:84 plugins/sudoers/cvtsudoers.c:132
+#: plugins/sudoers/cvtsudoers.c:176 plugins/sudoers/cvtsudoers.c:193
+#: plugins/sudoers/cvtsudoers.c:204 plugins/sudoers/cvtsudoers.c:338
+#: plugins/sudoers/cvtsudoers.c:379 plugins/sudoers/cvtsudoers.c:399
+#: plugins/sudoers/cvtsudoers.c:545 plugins/sudoers/cvtsudoers.c:698
+#: plugins/sudoers/cvtsudoers.c:716 plugins/sudoers/cvtsudoers.c:891
+#: plugins/sudoers/cvtsudoers.c:899 plugins/sudoers/cvtsudoers.c:1395
+#: plugins/sudoers/cvtsudoers.c:1399 plugins/sudoers/cvtsudoers.c:1501
+#: plugins/sudoers/cvtsudoers_csv.c:183 plugins/sudoers/cvtsudoers_csv.c:247
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:152
+#: plugins/sudoers/cvtsudoers_ldif.c:195 plugins/sudoers/cvtsudoers_ldif.c:236
+#: plugins/sudoers/cvtsudoers_ldif.c:302 plugins/sudoers/cvtsudoers_ldif.c:378
+#: plugins/sudoers/cvtsudoers_ldif.c:432 plugins/sudoers/cvtsudoers_ldif.c:440
+#: plugins/sudoers/cvtsudoers_ldif.c:451 plugins/sudoers/cvtsudoers_ldif.c:458
+#: plugins/sudoers/cvtsudoers_ldif.c:470 plugins/sudoers/cvtsudoers_ldif.c:483
+#: plugins/sudoers/cvtsudoers_ldif.c:491 plugins/sudoers/cvtsudoers_ldif.c:638
+#: plugins/sudoers/cvtsudoers_merge.c:47 plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1158
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:212
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:694 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:294 plugins/sudoers/ldap_util.c:301
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:402
+#: plugins/sudoers/log_client.c:717 plugins/sudoers/log_client.c:739
+#: plugins/sudoers/log_client.c:744 plugins/sudoers/log_client.c:1426
+#: plugins/sudoers/log_client.c:1547 plugins/sudoers/log_client.c:1670
+#: plugins/sudoers/log_client.c:1993 plugins/sudoers/log_client.c:2052
+#: plugins/sudoers/logging.c:110 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:872 plugins/sudoers/lookup.c:338
+#: plugins/sudoers/lookup.c:355 plugins/sudoers/lookup.c:374
+#: plugins/sudoers/lookup.c:393 plugins/sudoers/lookup.c:410
+#: plugins/sudoers/lookup.c:433 plugins/sudoers/lookup.c:444
+#: plugins/sudoers/match_command.c:302 plugins/sudoers/match_command.c:574
+#: plugins/sudoers/match_command.c:641 plugins/sudoers/match_command.c:737
+#: plugins/sudoers/match_command.c:785 plugins/sudoers/match_digest.c:88
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:595
+#: plugins/sudoers/parse_ldif.c:625 plugins/sudoers/parse_ldif.c:650
+#: plugins/sudoers/parse_ldif.c:708 plugins/sudoers/parse_ldif.c:725
+#: plugins/sudoers/parse_ldif.c:753 plugins/sudoers/parse_ldif.c:760
+#: plugins/sudoers/policy.c:646 plugins/sudoers/policy.c:1061
+#: plugins/sudoers/prompt.c:94 plugins/sudoers/pwutil.c:219
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:368
+#: plugins/sudoers/pwutil.c:542 plugins/sudoers/pwutil.c:607
+#: plugins/sudoers/pwutil.c:679 plugins/sudoers/pwutil.c:877
+#: plugins/sudoers/pwutil.c:967 plugins/sudoers/pwutil.c:1015
+#: plugins/sudoers/pwutil.c:1076 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:145 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1307 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:256
+#: plugins/sudoers/testsudoers.c:265 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:164 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1095
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1320
+msgid "unable to allocate memory"
+msgstr "メモリ割り当てを行えませんでした"
+
+#: gram.y:624
+msgid "a digest requires a path name"
+msgstr "認証方式にはパスが必要です"
+
+#: gram.y:646
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "\"CWD\" の値は '/', '~', または '*' で開始しなければいけません"
+
+#: gram.y:652
+msgid "\"CWD\" path too long"
+msgstr "\"CWD\" パスが長すぎます"
+
+#: gram.y:662
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "\"CHROOT\" の値は '/', '~', または '*' で開始しなければいけません"
+
+#: gram.y:668
+msgid "\"CHROOT\" path too long"
+msgstr "\"CHROOT\" パスが長すぎます"
+
+#: gram.y:817
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "構文エラー、予約語 %s がエイリアス名に使われています"
+
+#: gram.y:840
+msgid "invalid notbefore value"
+msgstr "notbefore の値が無効です"
+
+#: gram.y:849
+msgid "invalid notafter value"
+msgstr "notafter の値が無効です"
+
+#: gram.y:859 plugins/sudoers/policy.c:390
+msgid "timeout value too large"
+msgstr "制限時間の値が大き過ぎます"
+
+#: gram.y:861 plugins/sudoers/policy.c:392
+msgid "invalid timeout value"
+msgstr "時間制限値が無効です"
+
+#: gram.y:982 plugins/sudoers/sudoers.c:1162
+msgid "command too long"
+msgstr "コマンド名が長すぎます"
+
+#: gram.y:1016
+msgid "expected a fully-qualified path name"
+msgstr "完全修飾パス名が必要です"
+
+#: gram.y:1261
+#, c-format
+msgid "%s:%d:%zu: %s\n"
+msgstr "%s:%d:%zu: %s\n"
+
+#: gram.y:1315
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "別名 \"%s\" はすでに定義されています"
+
+#: gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:765 lib/eventlog/eventlog.c:838
+#: lib/eventlog/eventlog.c:841 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:483
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:232
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:174
+#: logsrvd/iolog_writer.c:184 logsrvd/iolog_writer.c:197
+#: logsrvd/iolog_writer.c:217 logsrvd/iolog_writer.c:227
+#: logsrvd/iolog_writer.c:246 logsrvd/iolog_writer.c:256
+#: logsrvd/iolog_writer.c:267 logsrvd/iolog_writer.c:277
+#: logsrvd/iolog_writer.c:289 logsrvd/iolog_writer.c:299
+#: logsrvd/iolog_writer.c:309 logsrvd/iolog_writer.c:319
+#: logsrvd/iolog_writer.c:329 logsrvd/iolog_writer.c:341
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:530
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:668
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:1131
+#: logsrvd/logsrvd.c:1446 logsrvd/logsrvd.c:1453 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:649
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1742
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:125
+#: logsrvd/logsrvd_journal.c:216 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:250 logsrvd/logsrvd_journal.c:258
+#: logsrvd/logsrvd_journal.c:287 logsrvd/logsrvd_journal.c:291
+#: logsrvd/logsrvd_journal.c:439 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:278 logsrvd/logsrvd_local.c:468
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:493
+#: logsrvd/logsrvd_queue.c:158 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/sendlog.c:256 logsrvd/sendlog.c:265
+#: logsrvd/sendlog.c:297 logsrvd/sendlog.c:303 logsrvd/sendlog.c:352
+#: logsrvd/sendlog.c:630 logsrvd/sendlog.c:1523 logsrvd/sendlog.c:1530
+#: logsrvd/sendlog.c:1753 logsrvd/sendlog.c:1822 logsrvd/tls_init.c:305
+#: logsrvd/tls_init.c:329 logsrvd/tls_init.c:340 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/pam.c:518 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/canon_path.c:129
+#: plugins/sudoers/canon_path.c:161 plugins/sudoers/check_aliases.c:128
+#: plugins/sudoers/check_util.c:56 plugins/sudoers/check_util.c:84
+#: plugins/sudoers/cvtsudoers.c:132 plugins/sudoers/cvtsudoers.c:175
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:203
+#: plugins/sudoers/cvtsudoers.c:337 plugins/sudoers/cvtsudoers.c:544
+#: plugins/sudoers/cvtsudoers.c:697 plugins/sudoers/cvtsudoers.c:715
+#: plugins/sudoers/cvtsudoers.c:891 plugins/sudoers/cvtsudoers.c:898
+#: plugins/sudoers/cvtsudoers.c:1395 plugins/sudoers/cvtsudoers.c:1399
+#: plugins/sudoers/cvtsudoers.c:1501 plugins/sudoers/cvtsudoers_csv.c:182
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:151 plugins/sudoers/cvtsudoers_ldif.c:194
+#: plugins/sudoers/cvtsudoers_ldif.c:235 plugins/sudoers/cvtsudoers_ldif.c:301
+#: plugins/sudoers/cvtsudoers_ldif.c:377 plugins/sudoers/cvtsudoers_ldif.c:431
+#: plugins/sudoers/cvtsudoers_ldif.c:439 plugins/sudoers/cvtsudoers_ldif.c:450
+#: plugins/sudoers/cvtsudoers_ldif.c:457 plugins/sudoers/cvtsudoers_ldif.c:469
+#: plugins/sudoers/cvtsudoers_ldif.c:482 plugins/sudoers/cvtsudoers_ldif.c:490
+#: plugins/sudoers/cvtsudoers_ldif.c:637 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51 plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1157
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:211
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:693 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:293 plugins/sudoers/ldap_util.c:300
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:228
+#: plugins/sudoers/log_client.c:250 plugins/sudoers/log_client.c:264
+#: plugins/sudoers/log_client.c:402 plugins/sudoers/log_client.c:717
+#: plugins/sudoers/log_client.c:739 plugins/sudoers/log_client.c:744
+#: plugins/sudoers/log_client.c:1426 plugins/sudoers/log_client.c:1547
+#: plugins/sudoers/log_client.c:1670 plugins/sudoers/log_client.c:1993
+#: plugins/sudoers/log_client.c:2052 plugins/sudoers/logging.c:110
+#: plugins/sudoers/logging.c:189 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:755 plugins/sudoers/logging.c:872
+#: plugins/sudoers/logging.c:925 plugins/sudoers/logging.c:932
+#: plugins/sudoers/lookup.c:337 plugins/sudoers/lookup.c:354
+#: plugins/sudoers/lookup.c:373 plugins/sudoers/lookup.c:392
+#: plugins/sudoers/lookup.c:409 plugins/sudoers/lookup.c:432
+#: plugins/sudoers/lookup.c:443 plugins/sudoers/match_command.c:301
+#: plugins/sudoers/match_command.c:573 plugins/sudoers/match_command.c:640
+#: plugins/sudoers/match_command.c:737 plugins/sudoers/match_command.c:784
+#: plugins/sudoers/match_digest.c:88 plugins/sudoers/parse_ldif.c:152
+#: plugins/sudoers/parse_ldif.c:183 plugins/sudoers/parse_ldif.c:252
+#: plugins/sudoers/parse_ldif.c:260 plugins/sudoers/parse_ldif.c:265
+#: plugins/sudoers/parse_ldif.c:341 plugins/sudoers/parse_ldif.c:352
+#: plugins/sudoers/parse_ldif.c:379 plugins/sudoers/parse_ldif.c:396
+#: plugins/sudoers/parse_ldif.c:408 plugins/sudoers/parse_ldif.c:412
+#: plugins/sudoers/parse_ldif.c:426 plugins/sudoers/parse_ldif.c:484
+#: plugins/sudoers/parse_ldif.c:595 plugins/sudoers/parse_ldif.c:624
+#: plugins/sudoers/parse_ldif.c:649 plugins/sudoers/parse_ldif.c:707
+#: plugins/sudoers/parse_ldif.c:724 plugins/sudoers/parse_ldif.c:752
+#: plugins/sudoers/parse_ldif.c:759 plugins/sudoers/policy.c:157
+#: plugins/sudoers/policy.c:166 plugins/sudoers/policy.c:175
+#: plugins/sudoers/policy.c:204 plugins/sudoers/policy.c:374
+#: plugins/sudoers/policy.c:390 plugins/sudoers/policy.c:392
+#: plugins/sudoers/policy.c:430 plugins/sudoers/policy.c:439
+#: plugins/sudoers/policy.c:448 plugins/sudoers/policy.c:457
+#: plugins/sudoers/policy.c:493 plugins/sudoers/policy.c:502
+#: plugins/sudoers/policy.c:511 plugins/sudoers/policy.c:520
+#: plugins/sudoers/policy.c:529 plugins/sudoers/policy.c:538
+#: plugins/sudoers/policy.c:547 plugins/sudoers/policy.c:646
+#: plugins/sudoers/policy.c:1061 plugins/sudoers/prompt.c:94
+#: plugins/sudoers/pwutil.c:219 plugins/sudoers/pwutil.c:290
+#: plugins/sudoers/pwutil.c:368 plugins/sudoers/pwutil.c:542
+#: plugins/sudoers/pwutil.c:607 plugins/sudoers/pwutil.c:679
+#: plugins/sudoers/pwutil.c:877 plugins/sudoers/pwutil.c:967
+#: plugins/sudoers/pwutil.c:1015 plugins/sudoers/pwutil.c:1076
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1306 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:255
+#: plugins/sudoers/testsudoers.c:264 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:163 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1094
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1309 toke.l:1320
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:304
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "標準入力を複製できません: %m"
+
+#: lib/eventlog/eventlog.c:346
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "%s を実行できません: %m"
+
+#: lib/eventlog/eventlog.c:394 plugins/sudoers/auth/aix_auth.c:199
+msgid "unable to fork"
+msgstr "fork できません"
+
+#: lib/eventlog/eventlog.c:404 lib/eventlog/eventlog.c:471
+#, c-format
+msgid "unable to fork: %m"
+msgstr "fork できません: %m"
+
+#: lib/eventlog/eventlog.c:461
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "パイプを開けません: %m"
+
+#: lib/eventlog/eventlog.c:1000
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:1029
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (コマンド継続中) %s"
+
+#: lib/eventlog/parse_json.c:175
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "JSON_STRING を予期していたら、 %d でした"
+
+#: lib/eventlog/parse_json.c:180
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY が大きすぎます"
+
+#: lib/eventlog/parse_json.c:506
+msgid "missing double quote in name"
+msgstr "名前に二重引用符がありません"
+
+#: lib/eventlog/parse_json.c:624
+msgid "missing JSON_OBJECT"
+msgstr "JSON_OBJECT がありません"
+
+#: lib/eventlog/parse_json.c:628
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "JSON_OBJECT を予期していたら、 %d でした"
+
+#: lib/eventlog/parse_json.c:762
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "JSON スタックを使い切りました(最大 %u フレーム)"
+
+#: lib/eventlog/parse_json.c:840
+msgid "objects must consist of name:value pairs"
+msgstr "オブジェクトは 名前:値 のベアである必要があります"
+
+#: lib/eventlog/parse_json.c:845 lib/eventlog/parse_json.c:876
+#: lib/eventlog/parse_json.c:920 lib/eventlog/parse_json.c:942
+#: lib/eventlog/parse_json.c:964 lib/eventlog/parse_json.c:986
+#: lib/eventlog/parse_json.c:1008
+msgid "missing separator between values"
+msgstr "値の間の分離記号がありません"
+
+#: lib/eventlog/parse_json.c:860 lib/eventlog/parse_json.c:1034
+msgid "unmatched close brace"
+msgstr "余分な閉じ中括弧があります"
+
+#: lib/eventlog/parse_json.c:871
+msgid "unexpected array"
+msgstr "予期せぬところに配列"
+
+#: lib/eventlog/parse_json.c:891 lib/eventlog/parse_json.c:1037
+msgid "unmatched close bracket"
+msgstr "余分な閉じ角括弧があります"
+
+#: lib/eventlog/parse_json.c:902
+msgid "unexpected string"
+msgstr "予期せぬところに文字列"
+
+#: lib/eventlog/parse_json.c:913
+msgid "missing colon after name"
+msgstr "名前の後にコロンがありません"
+
+#: lib/eventlog/parse_json.c:934 lib/eventlog/parse_json.c:956
+msgid "unexpected boolean"
+msgstr "予期せぬところに真偽値"
+
+#: lib/eventlog/parse_json.c:978
+msgid "unexpected null"
+msgstr "予期せぬところにNULL"
+
+#: lib/eventlog/parse_json.c:999
+msgid "unexpected number"
+msgstr "予期せぬところに数値"
+
+#: lib/eventlog/parse_json.c:1045
+msgid "parse error"
+msgstr "構文解析エラー"
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1290
+#: plugins/sudoers/sudoreplay.c:1291 plugins/sudoers/sudoreplay.c:1587
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr "無効な正規表現です \"%s\": %s"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: 無効なログファイルのパス"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: タイムスタンプのフィールドがありません"
+
+#: lib/iolog/iolog_legacy.c:90
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: タイムスタンプ %s: %s"
+
+#: lib/iolog/iolog_legacy.c:97
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: ユーザー名フィールドがありません"
+
+#: lib/iolog/iolog_legacy.c:108
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: runasユーザー名フィールドがありません"
+
+#: lib/iolog/iolog_legacy.c:119
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: runasグループ名フィールドがありません"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s が存在しますがディレクトリではありません (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:124 lib/iolog/iolog_mkdtemp.c:80
+#: logsrvd/iolog_writer.c:795 plugins/sudoers/timestamp.c:218
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "ディレクトリ %s を作成できません"
+
+#: lib/iolog/iolog_mkdtemp.c:85 plugins/sudoers/visudo.c:769
+#: plugins/sudoers/visudo.c:803 plugins/sudoers/visudo.c:809
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "%s のアクセス権限のモードを 0%o に変更できません"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "タイミングファイルの読み込みエラー: %s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "無効なタイミングファイルの行です: %s"
+
+#: logsrvd/iolog_writer.c:65
+#, c-format
+msgid "%s: protocol error: NULL key"
+msgstr "%s: プロトコルエラー: key が NULL です"
+
+#: logsrvd/iolog_writer.c:69
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s: プロトコルエラー: %s の型としては間違っています"
+
+#: logsrvd/iolog_writer.c:74 logsrvd/logsrvd_local.c:109
+#: logsrvd/logsrvd_local.c:123 logsrvd/logsrvd_local.c:131
+#: logsrvd/logsrvd_local.c:149
+#, c-format
+msgid "%s: protocol error: NULL value found in %s"
+msgstr "%s: プロトコルエラー: %s に NULL値が入っています"
+
+#: logsrvd/iolog_writer.c:141 plugins/sudoers/logging.c:1024
+#: plugins/sudoers/policy.c:613
+msgid "unable to generate UUID"
+msgstr "uuid を生成できません"
+
+#: logsrvd/iolog_writer.c:354 logsrvd/iolog_writer.c:359
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:369
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s: プロトコルエラー: %s が AcceptMessage にありません"
+
+#: logsrvd/iolog_writer.c:430
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s: セッションIDを整形できません"
+
+#: logsrvd/iolog_writer.c:444 logsrvd/iolog_writer.c:458
+#: logsrvd/iolog_writer.c:472 logsrvd/iolog_writer.c:487
+#: logsrvd/iolog_writer.c:501 logsrvd/iolog_writer.c:515
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s: %s は設定されていません"
+
+#: logsrvd/iolog_writer.c:551 logsrvd/iolog_writer.c:558
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr "iolog のパス %s を伸長できません"
+
+#: logsrvd/iolog_writer.c:576
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr "iolog のパス %s を作成できません"
+
+#: logsrvd/iolog_writer.c:606
+#, c-format
+msgid "invalid iofd %d"
+msgstr "無効な iofd %d です"
+
+#: logsrvd/iolog_writer.c:626
+#, c-format
+msgid "error closing iofd %u: %s"
+msgstr "iofd %u を閉じる際にエラーが発生しました: %s"
+
+#: logsrvd/iolog_writer.c:647
+#, c-format
+msgid "error flushing iofd %u: %s"
+msgstr "iofd %u をフラッシュする際にエラーが発生しました: %s"
+
+#: logsrvd/iolog_writer.c:765
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "無効な I/O ログ %s: %s が参照されていますが存在しません"
+
+#: logsrvd/iolog_writer.c:777 logsrvd/logsrvd_journal.c:391
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "%s: 復元ポイントが見つかりません [%lld, %ld]"
+
+#: logsrvd/iolog_writer.c:799 logsrvd/logsrvd_journal.c:434
+#: logsrvd/logsrvd_queue.c:115 logsrvd/tls_init.c:256
+#: plugins/sudoers/check.c:285 plugins/sudoers/cvtsudoers.c:758
+#: plugins/sudoers/cvtsudoers.c:780 plugins/sudoers/cvtsudoers.c:1461
+#: plugins/sudoers/cvtsudoers_csv.c:697 plugins/sudoers/cvtsudoers_json.c:902
+#: plugins/sudoers/cvtsudoers_ldif.c:711 plugins/sudoers/sudoers.c:1291
+#: plugins/sudoers/sudoers.c:1317 plugins/sudoers/sudoreplay.c:1497
+#: plugins/sudoers/timestamp.c:478 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:990
+#, c-format
+msgid "unable to open %s"
+msgstr "%s を開けません"
+
+#: logsrvd/iolog_writer.c:811 logsrvd/logsrv_util.c:111
+#: logsrvd/logsrv_util.c:118 plugins/sudoers/sudoreplay.c:355
+#: plugins/sudoers/sudoreplay.c:361
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "%s/%s を開けません"
+
+#: logsrvd/iolog_writer.c:824
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "%s/%s から %s/%s にコピーできません: %s"
+
+#: logsrvd/iolog_writer.c:853 logsrvd/logsrvd_journal.c:198
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "%s から %s に名前を変更できません"
+
+#: logsrvd/logsrv_util.c:153 logsrvd/logsrv_util.c:182
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s: 復元ポイントが見つかりません [%lld, %ld]"
+
+#: logsrvd/logsrv_util.c:165
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "I/O ログファイル %s/%s がありません。"
+
+#: logsrvd/logsrv_util.c:172
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s: 前方検索できません %zu"
+
+#: logsrvd/logsrvd.c:271 logsrvd/logsrvd_queue.c:135
+msgid "unable to connect to relay"
+msgstr "リレーに接続できません"
+
+#: logsrvd/logsrvd.c:338 logsrvd/logsrvd_relay.c:847
+#, c-format
+msgid "server message too large: %zu"
+msgstr "サーバーメッセージが大き過ぎます: %zu"
+
+#: logsrvd/logsrvd.c:430 logsrvd/logsrvd.c:553 logsrvd/logsrvd.c:639
+#: logsrvd/logsrvd.c:881 logsrvd/logsrvd.c:895 logsrvd/logsrvd.c:1056
+#: logsrvd/logsrvd.c:1181 logsrvd/logsrvd.c:1354 logsrvd/logsrvd.c:1372
+#: logsrvd/logsrvd.c:1471 logsrvd/logsrvd.c:1596 logsrvd/logsrvd.c:1783
+#: logsrvd/logsrvd_journal.c:503 logsrvd/logsrvd_local.c:238
+#: logsrvd/logsrvd_queue.c:164 logsrvd/logsrvd_relay.c:172
+#: logsrvd/logsrvd_relay.c:249 logsrvd/logsrvd_relay.c:253
+#: logsrvd/logsrvd_relay.c:391 logsrvd/logsrvd_relay.c:583
+#: logsrvd/logsrvd_relay.c:747 logsrvd/logsrvd_relay.c:1137
+#: logsrvd/sendlog.c:1308 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:216 plugins/sudoers/audit.c:281
+#: plugins/sudoers/iolog.c:1041 plugins/sudoers/iolog.c:1175
+#: plugins/sudoers/iolog.c:1274 plugins/sudoers/log_client.c:121
+#: plugins/sudoers/log_client.c:343 plugins/sudoers/log_client.c:359
+#: plugins/sudoers/log_client.c:407 plugins/sudoers/log_client.c:613
+#: plugins/sudoers/log_client.c:620 plugins/sudoers/log_client.c:1114
+#: plugins/sudoers/log_client.c:1395 plugins/sudoers/log_client.c:1436
+#: plugins/sudoers/log_client.c:1444 plugins/sudoers/log_client.c:1603
+#: plugins/sudoers/log_client.c:1728 plugins/sudoers/log_client.c:2060
+#: plugins/sudoers/log_client.c:2068 plugins/sudoers/logging.c:148
+#: plugins/sudoers/logging.c:206 plugins/sudoers/sudoreplay.c:519
+#: plugins/sudoers/sudoreplay.c:566 plugins/sudoers/sudoreplay.c:808
+#: plugins/sudoers/sudoreplay.c:920 plugins/sudoers/sudoreplay.c:1011
+#: plugins/sudoers/sudoreplay.c:1026 plugins/sudoers/sudoreplay.c:1033
+#: plugins/sudoers/sudoreplay.c:1040 plugins/sudoers/sudoreplay.c:1047
+#: plugins/sudoers/sudoreplay.c:1054 plugins/sudoers/sudoreplay.c:1182
+msgid "unable to add event to queue"
+msgstr "イベントをキューに追加できません"
+
+#: logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:491 logsrvd/logsrvd.c:523
+#: logsrvd/logsrvd.c:577 logsrvd/logsrvd.c:656 logsrvd/logsrvd.c:692
+#: logsrvd/logsrvd.c:728 logsrvd/logsrvd.c:764 logsrvd/logsrvd_relay.c:512
+#: logsrvd/logsrvd_relay.c:545
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr "予期しない状態 %d (%sの)"
+
+#: logsrvd/logsrvd.c:455 logsrvd/logsrvd.c:492 logsrvd/logsrvd.c:524
+#: logsrvd/logsrvd.c:578 logsrvd/logsrvd.c:657 logsrvd/logsrvd.c:693
+#: logsrvd/logsrvd.c:729 logsrvd/logsrvd.c:765 logsrvd/logsrvd_relay.c:514
+#: logsrvd/logsrvd_relay.c:547
+msgid "state machine error"
+msgstr "状態マシンエラー"
+
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:462
+msgid "invalid AcceptMessage"
+msgstr "無効な AcceptMessage"
+
+#: logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:499
+msgid "invalid RejectMessage"
+msgstr "無効な RejectMessage"
+
+#: logsrvd/logsrvd.c:530 logsrvd/logsrvd.c:531
+msgid "invalid ExitMessage"
+msgstr "無効な ExitMessage"
+
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:585
+msgid "invalid RestartMessage"
+msgstr "無効な RestartMessage"
+
+#: logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:620
+msgid "invalid AlertMessage"
+msgstr "無効な AlertMessage"
+
+#: logsrvd/logsrvd.c:661 logsrvd/logsrvd.c:697 logsrvd/logsrvd.c:733
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s: 予期しない IoBuffer"
+
+#: logsrvd/logsrvd.c:662 logsrvd/logsrvd.c:698 logsrvd/logsrvd.c:734
+msgid "protocol error"
+msgstr "プロトコルエラーです"
+
+#: logsrvd/logsrvd.c:668 logsrvd/logsrvd.c:669
+msgid "invalid IoBuffer"
+msgstr "無効な IoBuffer です"
+
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:705
+msgid "invalid ChangeWindowSize"
+msgstr "無効な ChangeWindowSize"
+
+#: logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:741
+msgid "invalid CommandSuspend"
+msgstr "無効な CommandSuspend"
+
+#: logsrvd/logsrvd.c:790 logsrvd/logsrvd_journal.c:302
+#: logsrvd/logsrvd_relay.c:654 logsrvd/sendlog.c:1207
+#: plugins/sudoers/log_client.c:1593
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "%s を伸長できません (長さ %zu )"
+
+#: logsrvd/logsrvd.c:835 logsrvd/logsrvd_journal.c:376
+#: logsrvd/logsrvd_relay.c:678
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "予期しない type_case の値 %d が %s の中にあります、 %s から出てきたものです。"
+
+#: logsrvd/logsrvd.c:837
+msgid "unrecognized ClientMessage type"
+msgstr "認識できないクライアントメッセージのタイプです"
+
+#: logsrvd/logsrvd.c:927
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "クライアント %s への書き込みがタイムアウト"
+
+#: logsrvd/logsrvd.c:932 logsrvd/logsrvd_relay.c:919 logsrvd/sendlog.c:1413
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr "クライアント %s への書き込みバッファがありません"
+
+#: logsrvd/logsrvd.c:1027
+#, c-format
+msgid "timed out reading from client %s"
+msgstr "クライアント %s からの読み込みがタイムアウト"
+
+#: logsrvd/logsrvd.c:1068 logsrvd/logsrvd_relay.c:782
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr "%s からの EOF が適切な TLS 通信の終了なしに現れました"
+
+#: logsrvd/logsrvd.c:1112 logsrvd/logsrvd_relay.c:205 logsrvd/sendlog.c:336
+#: plugins/sudoers/log_client.c:723
+#, c-format
+msgid "client message too large: %zu"
+msgstr "クライアントメッセージが大き過ぎます: %zu"
+
+#: logsrvd/logsrvd.c:1113 logsrvd/logsrvd_journal.c:259
+#: logsrvd/logsrvd_journal.c:260
+msgid "client message too large"
+msgstr "クライアントメッセージが大き過ぎます"
+
+#: logsrvd/logsrvd.c:1131 logsrvd/logsrvd.c:1132
+msgid "invalid ClientMessage"
+msgstr "無効な ClientMessage"
+
+#: logsrvd/logsrvd.c:1432
+msgid "unable to get remote IP addr"
+msgstr "リモートIPアドレスを取得できません"
+
+#: logsrvd/logsrvd.c:1463 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:281
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "ユーザーデータをSSLオブジェクトに添付することができません: %s"
+
+#: logsrvd/logsrvd.c:1646 logsrvd/logsrvd.c:2007
+msgid "unable to setup listen socket"
+msgstr "接続待ちソケットを準備できません"
+
+#: logsrvd/logsrvd.c:1766
+#, c-format
+msgid "unexpected signal %d"
+msgstr "予期しないシグナル %d"
+
+#: logsrvd/logsrvd.c:1909
+msgid "sudo log server"
+msgstr "Sudo ログサーバー"
+
+#: logsrvd/logsrvd.c:1911 logsrvd/sendlog.c:126
+msgid "Options:"
+msgstr "オプション:"
+
+#: logsrvd/logsrvd.c:1913
+msgid "path to configuration file"
+msgstr "設定ファイルのパス"
+
+#: logsrvd/logsrvd.c:1915 logsrvd/sendlog.c:128
+msgid "display help message and exit"
+msgstr "ヘルプメッセージを表示して終了する"
+
+#: logsrvd/logsrvd.c:1917
+msgid "do not fork, run in the foreground"
+msgstr "フォークせずに、フォアグラウンドで実行する"
+
+#: logsrvd/logsrvd.c:1919
+msgid "percent chance connections will drop"
+msgstr "接続が切れる割合(%)"
+
+#: logsrvd/logsrvd.c:1921 logsrvd/sendlog.c:158
+msgid "display version information and exit"
+msgstr "バージョン情報を表示して終了する"
+
+#: logsrvd/logsrvd.c:1971 logsrvd/sendlog.c:1722
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "Protobuf-C バージョン 1.3 以上が必要です"
+
+#: logsrvd/logsrvd.c:1987
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "無効な乱数ドロップ値です: %s"
+
+#: logsrvd/logsrvd.c:1990 logsrvd/sendlog.c:1776
+#: plugins/sudoers/cvtsudoers.c:250 plugins/sudoers/sudoreplay.c:294
+#: plugins/sudoers/visudo.c:181
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s バージョン %s\n"
+
+#: logsrvd/logsrvd_conf.c:422 plugins/sudoers/check.c:69
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/sudoers.c:419 plugins/sudoers/sudoers.c:929
+#: plugins/sudoers/sudoers.c:1034 plugins/sudoers/sudoers.c:1424
+#: plugins/sudoers/testsudoers.c:169 plugins/sudoers/testsudoers.c:285
+#: plugins/sudoers/testsudoers.c:459
+#, c-format
+msgid "unknown user %s"
+msgstr "不明なユーザー %s"
+
+#: logsrvd/logsrvd_conf.c:439 plugins/sudoers/iolog.c:148
+#: plugins/sudoers/sudoers.c:425 plugins/sudoers/sudoers.c:1458
+#: plugins/sudoers/testsudoers.c:483
+#, c-format
+msgid "unknown group %s"
+msgstr "不明なグループ %s"
+
+#: logsrvd/logsrvd_conf.c:457
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr "iolog モード %s を解析できません"
+
+#: logsrvd/logsrvd_conf.c:474 logsrvd/logsrvd_conf.c:1243
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "%s には無効な値: %s"
+
+#: logsrvd/logsrvd_conf.c:527
+msgid "TLS not supported"
+msgstr "TLS がサポートされていません"
+
+#: logsrvd/logsrvd_conf.c:549
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:622 logsrvd/logsrvd_conf.c:1032
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s: 完全修飾パスではありません"
+
+#: logsrvd/logsrvd_conf.c:951 logsrvd/logsrvd_conf.c:967
+#: logsrvd/logsrvd_conf.c:1676
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "未知の syslog ファシリティ %s"
+
+#: logsrvd/logsrvd_conf.c:983 logsrvd/logsrvd_conf.c:999
+#: logsrvd/logsrvd_conf.c:1015 logsrvd/logsrvd_conf.c:1680
+#: logsrvd/logsrvd_conf.c:1684 logsrvd/logsrvd_conf.c:1688
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "未知の syslog プライオリティ %s"
+
+#: logsrvd/logsrvd_conf.c:1197
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d 対応しない '[': %s"
+
+#: logsrvd/logsrvd_conf.c:1203
+#, c-format
+msgid "%s:%d garbage after ']': %s"
+msgstr "%s:%d ']' の後に余計なものがあります: %s"
+
+#: logsrvd/logsrvd_conf.c:1215
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s:%d 無効な config セクション: %s"
+
+#: logsrvd/logsrvd_conf.c:1223
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d 無効な設定の行: %s"
+
+#: logsrvd/logsrvd_conf.c:1229
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d セクション名が必要です: %s"
+
+#: logsrvd/logsrvd_conf.c:1251
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] 適合しないキー: %s"
+
+#: logsrvd/logsrvd_conf.c:1281 plugins/sudoers/cvtsudoers.c:273
+#: plugins/sudoers/logging.c:1076
+#, c-format
+msgid "unable to open log file %s"
+msgstr "ログファイル %s を開けません"
+
+#: logsrvd/logsrvd_conf.c:1763
+msgid "unable to initialize server TLS context"
+msgstr "サーバーTLSコンテキストを初期化できません"
+
+#: logsrvd/logsrvd_conf.c:1783
+msgid "unable to initialize relay TLS context"
+msgstr "リレーTLSコンテキストを初期化できません"
+
+#: logsrvd/logsrvd_journal.c:149 logsrvd/logsrvd_journal.c:430
+#: logsrvd/logsrvd_journal.c:435
+msgid "unable to create journal file"
+msgstr "ジャーナルファイルを作成できません"
+
+#: logsrvd/logsrvd_journal.c:153 logsrvd/logsrvd_queue.c:109
+#: plugins/sudoers/visudo.c:1046
+#, c-format
+msgid "unable to lock %s"
+msgstr "%s をロックできません"
+
+#: logsrvd/logsrvd_journal.c:156
+msgid "unable to lock journal file"
+msgstr "ジャーナルファイルをロックできません"
+
+#: logsrvd/logsrvd_journal.c:164
+msgid "unable to open journal file"
+msgstr "ジャーナルファイルを開けません"
+
+#: logsrvd/logsrvd_journal.c:185 logsrvd/logsrvd_journal.c:466
+#: logsrvd/logsrvd_journal.c:471
+msgid "unable to write journal file"
+msgstr "ジャーナルファイルへ書き込むことができません"
+
+#: logsrvd/logsrvd_journal.c:193 logsrvd/logsrvd_journal.c:200
+msgid "unable to rename journal file"
+msgstr "ジャーナルファイルの名前を変更できません"
+
+#: logsrvd/logsrvd_journal.c:247 logsrvd/logsrvd_journal.c:248
+#: logsrvd/logsrvd_journal.c:288 logsrvd/logsrvd_journal.c:289
+msgid "unexpected EOF reading journal file"
+msgstr "ジャーナルファイルの予期せぬところにEOF"
+
+#: logsrvd/logsrvd_journal.c:251 logsrvd/logsrvd_journal.c:252
+#: logsrvd/logsrvd_journal.c:292 logsrvd/logsrvd_journal.c:293
+msgid "error reading journal file"
+msgstr "ジャーナルファイルの読み込みエラー"
+
+#: logsrvd/logsrvd_journal.c:304 logsrvd/logsrvd_journal.c:390
+msgid "invalid journal file, unable to restart"
+msgstr "無効なジャーナルファイル、再スタートできません"
+
+#: logsrvd/logsrvd_journal.c:449
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "[%lld, %ld] が見つかりません、 ジャーナルファイル %s で探索中"
+
+#: logsrvd/logsrvd_local.c:166
+#, c-format
+msgid "unexpected value_case %d in %s from %s"
+msgstr "予期しない value_case の値 %d が %s の中にあります、 %s から出てきたものです。"
+
+#: logsrvd/logsrvd_local.c:194
+msgid "error parsing AcceptMessage"
+msgstr "AcceptMessage の解析中にエラー"
+
+#: logsrvd/logsrvd_local.c:205
+msgid "error creating I/O log"
+msgstr "I/O ログの作成でエラー"
+
+#: logsrvd/logsrvd_local.c:228
+msgid "error logging accept event"
+msgstr "accept イベントのログ記録でエラー"
+
+#: logsrvd/logsrvd_local.c:267
+msgid "error parsing RejectMessage"
+msgstr "RejectMessage の解析でエラー"
+
+#: logsrvd/logsrvd_local.c:291
+msgid "error logging reject event"
+msgstr "reject イベントのログ記録でエラー"
+
+#: logsrvd/logsrvd_local.c:427 logsrvd/logsrvd_local.c:437
+msgid "error logging exit event"
+msgstr "exit イベントのログ記録でエラー"
+
+#: logsrvd/logsrvd_local.c:494 logsrvd/logsrvd_local.c:495
+msgid "log is already complete, cannot be restarted"
+msgstr "ログは完了しているので、再開できません"
+
+#: logsrvd/logsrvd_local.c:525
+msgid "unable to restart log"
+msgstr "ログを再開できません"
+
+#: logsrvd/logsrvd_local.c:541
+msgid "error parsing AlertMessage"
+msgstr "AlertMessage の解析中にエラー"
+
+#: logsrvd/logsrvd_local.c:551
+msgid "error logging alert event"
+msgstr "alert イベントのログ記録でエラー"
+
+#: logsrvd/logsrvd_local.c:587 logsrvd/logsrvd_local.c:650
+#: logsrvd/logsrvd_local.c:685
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr "タイミングバッファーを書式整形できません、長さ %d"
+
+#: logsrvd/logsrvd_local.c:601 logsrvd/logsrvd_local.c:609
+#: logsrvd/logsrvd_local.c:657 logsrvd/logsrvd_local.c:692
+#: plugins/sudoers/sudoreplay.c:344 toke.l:981 toke.l:984
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: logsrvd/logsrvd_local.c:620
+msgid "randomly dropping connection"
+msgstr "不規則に接続が落ちています"
+
+#: logsrvd/logsrvd_local.c:632
+msgid "error writing IoBuffer"
+msgstr "IoBuffer の書き込みでエラー"
+
+#: logsrvd/logsrvd_local.c:667
+msgid "error writing ChangeWindowSize"
+msgstr "ChangeWindowSize の書き込みでエラー"
+
+#: logsrvd/logsrvd_local.c:702
+msgid "error writing CommandSuspend"
+msgstr "CommandSuspend の書き込みでエラー"
+
+#: logsrvd/logsrvd_relay.c:437
+msgid "TLS handshake with relay host failed"
+msgstr "リレーホストへのTLS ハンドシェイクが失敗"
+
+#: logsrvd/logsrvd_relay.c:465
+msgid "unable to connect to relay host"
+msgstr "リレーホストに接続できません"
+
+#: logsrvd/logsrvd_relay.c:520
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s: 無効な ServerHello です、server_id がありません"
+
+#: logsrvd/logsrvd_relay.c:522 logsrvd/sendlog.c:1111
+#: plugins/sudoers/log_client.c:1479
+msgid "invalid ServerHello"
+msgstr "無効な ServerHello です"
+
+#: logsrvd/logsrvd_relay.c:681
+msgid "unrecognized ServerMessage type"
+msgstr "認識できない ServerMessage のタイプです"
+
+#: logsrvd/logsrvd_relay.c:710
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr "リレー %s (%s) からの読み込みがタイムアウト"
+
+#: logsrvd/logsrvd_relay.c:712
+msgid "timeout reading from relay"
+msgstr "リレーからの読み込みがタイムアウト"
+
+#: logsrvd/logsrvd_relay.c:767
+msgid "relay host name does not match certificate"
+msgstr "リレーホスト名が証明書と一致しません"
+
+#: logsrvd/logsrvd_relay.c:773 logsrvd/logsrvd_relay.c:787
+#: logsrvd/logsrvd_relay.c:794
+msgid "error reading from relay"
+msgstr "リレーからの読み込みでエラー"
+
+#: logsrvd/logsrvd_relay.c:815
+msgid "unable to read from relay"
+msgstr "リレーから読み込めません"
+
+#: logsrvd/logsrvd_relay.c:830 logsrvd/logsrvd_relay.c:949
+msgid "relay server closed connection"
+msgstr "リレーサーバーが接続を閉じました"
+
+#: logsrvd/logsrvd_relay.c:848
+msgid "server message too large"
+msgstr "サーバーメッセージが大き過ぎます"
+
+#: logsrvd/logsrvd_relay.c:912
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr "リレー %s (%s) への書き込みがタイムアウト"
+
+#: logsrvd/logsrvd_relay.c:914
+msgid "timeout writing to relay"
+msgstr "リレーへの書き込みがタイムアウト"
+
+#: logsrvd/logsrvd_relay.c:968 logsrvd/logsrvd_relay.c:975
+#: logsrvd/logsrvd_relay.c:987
+msgid "error writing to relay"
+msgstr "リレーへの書き込みでエラー"
+
+#: logsrvd/sendlog.c:124
+msgid "send sudo I/O log to remote server"
+msgstr "sudo I/O ログをリモートサーバーに送る"
+
+#: logsrvd/sendlog.c:130
+msgid "only send an accept event (no I/O)"
+msgstr "受け取りイベントのみを送る (I/O なし)"
+
+#: logsrvd/sendlog.c:133
+msgid "certificate bundle file to verify server's cert against"
+msgstr "サーバーの証明書を検証するために突き合わせる証明書バンドルファイル"
+
+#: logsrvd/sendlog.c:135
+msgid "certificate file for TLS handshake"
+msgstr "TLSハンドシェイクのための証明書ファイル"
+
+#: logsrvd/sendlog.c:138
+msgid "host to send logs to"
+msgstr "ログの送り先とするホスト"
+
+#: logsrvd/sendlog.c:140
+msgid "remote ID of I/O log to be resumed"
+msgstr "復元するI/O ログのリモート ID"
+
+#: logsrvd/sendlog.c:143
+msgid "private key file"
+msgstr "プライベート鍵ファイル"
+
+#: logsrvd/sendlog.c:145
+msgid "do not verify server certificate"
+msgstr "サーバーの証明書を検証しない"
+
+#: logsrvd/sendlog.c:148
+msgid "port to use when connecting to host"
+msgstr "ホストに接続するのに使用するポート"
+
+#: logsrvd/sendlog.c:150
+msgid "restart previous I/O log transfer"
+msgstr "以前の I/O ログ転送を再開する"
+
+#: logsrvd/sendlog.c:152
+msgid "reject the command with the given reason"
+msgstr "与えられた理由によりコマンドを拒否する"
+
+#: logsrvd/sendlog.c:154
+msgid "stop transfer after reaching this time"
+msgstr "この時間になったら転送を止める"
+
+#: logsrvd/sendlog.c:156
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "選んだ I/O ログを n 重に並列送信することで監査サーバーを試験する"
+
+#: logsrvd/sendlog.c:181 plugins/sudoers/log_client.c:453
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "警告: %s:%s を参照できません: %s"
+
+#: logsrvd/sendlog.c:219
+msgid "unable to get server IP addr"
+msgstr "サーバーのIPアドレスを取得できません"
+
+#: logsrvd/sendlog.c:314 plugins/sudoers/sudoreplay.c:868
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "%s/%s から読み込むことができません: %s"
+
+#: logsrvd/sendlog.c:1035 plugins/sudoers/iolog.c:959
+#: plugins/sudoers/iolog.c:1034
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "予期しない I/O イベント %d"
+
+#: logsrvd/sendlog.c:1088 logsrvd/sendlog.c:1105 logsrvd/sendlog.c:1139
+#: plugins/sudoers/log_client.c:1129 plugins/sudoers/log_client.c:1405
+#: plugins/sudoers/log_client.c:1473 plugins/sudoers/log_client.c:1512
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: 予期しない状態 %d"
+
+#: logsrvd/sendlog.c:1175 plugins/sudoers/log_client.c:1561
+#, c-format
+msgid "error message received from server: %s"
+msgstr "サーバからエラーメッセージを受け取りました: %s"
+
+#: logsrvd/sendlog.c:1188 plugins/sudoers/log_client.c:1574
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "サーバから中断メッセージを受け取りました: %s"
+
+#: logsrvd/sendlog.c:1247 plugins/sudoers/log_client.c:1624
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s: 予期しない type_case の値 %d"
+
+#: logsrvd/sendlog.c:1276
+msgid "timeout reading from server"
+msgstr "サーバーからの読み込みがタイムアウト"
+
+#: logsrvd/sendlog.c:1327 plugins/sudoers/log_client.c:1747
+msgid "host name does not match certificate"
+msgstr "ホスト名が証明書と一致しません"
+
+#: logsrvd/sendlog.c:1361
+msgid "premature EOF"
+msgstr "早すぎるファイル終端 (EOF)"
+
+#: logsrvd/sendlog.c:1374 plugins/sudoers/log_client.c:1795
+#, c-format
+msgid "server message too large: %u"
+msgstr "サーバーメッセージが大き過ぎます: %u"
+
+#: logsrvd/sendlog.c:1430
+msgid "timeout writing to server"
+msgstr "サーバーへの書き込みがタイムアウト"
+
+#: logsrvd/sendlog.c:1800
+msgid "both restart point and iolog ID must be specified"
+msgstr "再開するポイントとIOログIDを指定する必要があります"
+
+#: logsrvd/sendlog.c:1804
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "I/Oが送られない場合は再開するポイントを設定できません"
+
+#: logsrvd/sendlog.c:1880
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "ステータス %d で予期せぬ終了をしました"
+
+#: logsrvd/sendlog.c:1881
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "サーバーに送られた経過時間 [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1883
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "サーバーから受け取ったコミットポイント [%lld, %ld]"
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:315
+msgid "TLS handshake timeout occurred"
+msgstr "TLS ハンドシェイクでタイムアウトが発生"
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:337 plugins/sudoers/log_client.c:353
+msgid "unable to set event"
+msgstr "イベントを設定できません"
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "TLS接続に失敗しました: %s"
+
+#: logsrvd/tls_client.c:196
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "SSLオブジェクトを割り当てることができません: %s"
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "ソケットをSSLオブジェクトに取り付けることができません: %s"
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr "TLS コンテキストを初期化できません"
+
+#: logsrvd/tls_init.c:138 logsrvd/tls_init.c:146
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "TLS 1.2 暗号化スイートを %s に設定できません: %s"
+
+#: logsrvd/tls_init.c:166 logsrvd/tls_init.c:174
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "TLS 1.3 暗号化スイートを %s に設定できません: %s"
+
+#: logsrvd/tls_init.c:206 logsrvd/tls_init.c:227
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "ディフィー・ヘルマン パラメーターを設定できません: %s"
+
+#: logsrvd/tls_init.c:283
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "TLS コンテキストを作成できません: %s"
+
+#: logsrvd/tls_init.c:290
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "プロトコルの最小バージョンを TLS 1.2 に設定できません: %s"
+
+#: plugins/sudoers/audit.c:272 plugins/sudoers/audit.c:452
+#: plugins/sudoers/log_client.c:962 plugins/sudoers/log_client.c:1011
+#: plugins/sudoers/log_client.c:1060 plugins/sudoers/log_client.c:1185
+#: plugins/sudoers/logging.c:614 plugins/sudoers/logging.c:732
+#: plugins/sudoers/logging.c:859 plugins/sudoers/logging.c:1031
+#: plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr "時刻を取得できません"
+
+#: plugins/sudoers/auth/aix_auth.c:282
+#, c-format
+msgid "unable to change password for %s"
+msgstr "%s のパスワードを変更できません"
+
+#: plugins/sudoers/auth/bsdauth.c:78
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "ユーザー%s のログインクラスを得ることができません"
+
+#: plugins/sudoers/auth/bsdauth.c:85
+msgid "invalid authentication type"
+msgstr "無効な認証タイプです"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to begin BSD authentication"
+msgstr "BSD 認証を開始できません"
+
+#: plugins/sudoers/auth/bsdauth.c:97
+msgid "unable to initialize BSD authentication"
+msgstr "BSD 認証を開始できません"
+
+#: plugins/sudoers/auth/bsdauth.c:191
+msgid "your account has expired"
+msgstr "あなたのアカウントの有効期限が切れています"
+
+#: plugins/sudoers/auth/bsdauth.c:193
+msgid "approval failed"
+msgstr "認証に失敗しました"
+
+#: plugins/sudoers/auth/fwtk.c:62
+msgid "unable to read fwtk config"
+msgstr "fwtk 設定を読み込めません"
+
+#: plugins/sudoers/auth/fwtk.c:67
+msgid "unable to connect to authentication server"
+msgstr "認証サーバーに接続できません"
+
+#: plugins/sudoers/auth/fwtk.c:73 plugins/sudoers/auth/fwtk.c:99
+#: plugins/sudoers/auth/fwtk.c:131
+msgid "lost connection to authentication server"
+msgstr "認証サーバーへの接続が失われました"
+
+#: plugins/sudoers/auth/fwtk.c:77
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"認証サーバーエラーです:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:116
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: プリンシパルを文字列('%s')に変換できません: %s"
+
+#: plugins/sudoers/auth/kerb5.c:166
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: '%s' を構文解析できません: %s"
+
+#: plugins/sudoers/auth/kerb5.c:175
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: 資格情報キャッシュ を解決できません: %s"
+
+#: plugins/sudoers/auth/kerb5.c:226
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: オプションを設定できません: %s"
+
+#: plugins/sudoers/auth/kerb5.c:241
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: 資格情報を取得できません: %s"
+
+#: plugins/sudoers/auth/kerb5.c:254
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: 資格情報キャッシュ を初期化できません: %s"
+
+#: plugins/sudoers/auth/kerb5.c:257
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: 資格情報をキャッシュできません: %s"
+
+#: plugins/sudoers/auth/kerb5.c:322
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: ホストプリンシパルを取得できません: %s"
+
+#: plugins/sudoers/auth/kerb5.c:336
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: TGT を検証できません! おそらく攻撃です!: %s"
+
+#: plugins/sudoers/auth/pam.c:233
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "PAM を初期化できません: %s"
+
+#: plugins/sudoers/auth/pam.c:349
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "PAM 認証エラーです: %s"
+
+#: plugins/sudoers/auth/pam.c:369
+msgid "account validation failure, is your account locked?"
+msgstr "アカウントの有効性検証に失敗しました。あなたのアカウントはロックされていませんか?"
+
+#: plugins/sudoers/auth/pam.c:380
+msgid "Account or password is expired, reset your password and try again"
+msgstr "アカウントまたはパスワードが期限切れです。パスワードをリセットして再試行してください"
+
+#: plugins/sudoers/auth/pam.c:387
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "期限の切れたパスワードを変更できません: %s"
+
+#: plugins/sudoers/auth/pam.c:398
+msgid "Password expired, contact your system administrator"
+msgstr "パスワードが期限切れです。システム管理者に連絡してください"
+
+#: plugins/sudoers/auth/pam.c:403
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "アカウントの期限切れ、または sudo 用の PAM 設定に \"account\" セクションがありません。システム管理者に連絡してください"
+
+#: plugins/sudoers/auth/pam.c:411 plugins/sudoers/auth/pam.c:416
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "PAM アカウント管理エラーです: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:100 plugins/sudoers/visudo.c:266
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "あなたは %s データベース内に存在しません"
+
+#: plugins/sudoers/auth/securid5.c:76
+msgid "failed to initialise the ACE API library"
+msgstr "ACE API ライブラリの初期化に失敗しました"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "unable to contact the SecurID server"
+msgstr "SecurID サーバーに接続できません"
+
+#: plugins/sudoers/auth/securid5.c:117
+msgid "User ID locked for SecurID Authentication"
+msgstr "SecurID 認証のユーザーIDがロックされています"
+
+#: plugins/sudoers/auth/securid5.c:121 plugins/sudoers/auth/securid5.c:174
+msgid "invalid username length for SecurID"
+msgstr "SecurID 用のユーザー名の長さが無効です"
+
+#: plugins/sudoers/auth/securid5.c:125 plugins/sudoers/auth/securid5.c:179
+msgid "invalid Authentication Handle for SecurID"
+msgstr "SecurID 用の認証ハンドルが無効です"
+
+#: plugins/sudoers/auth/securid5.c:129
+msgid "SecurID communication failed"
+msgstr "SecurID 通信に失敗しました"
+
+#: plugins/sudoers/auth/securid5.c:133 plugins/sudoers/auth/securid5.c:222
+msgid "unknown SecurID error"
+msgstr "不明な SecurID エラーです"
+
+#: plugins/sudoers/auth/securid5.c:169
+msgid "invalid passcode length for SecurID"
+msgstr "SecurID 用のパスコード長が無効です"
+
+#: plugins/sudoers/auth/sia.c:72 plugins/sudoers/auth/sia.c:130
+msgid "unable to initialize SIA session"
+msgstr "SIA セッションを初期化できません"
+
+#: plugins/sudoers/auth/sudo_auth.c:141
+msgid "invalid authentication methods"
+msgstr "無効な認証方法"
+
+#: plugins/sudoers/auth/sudo_auth.c:143
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "無効な認証方法が sudo のコンパイル時に組み込まれています! スタンドアローンと非スタンドアローン認証を混在させてはいけません。"
+
+#: plugins/sudoers/auth/sudo_auth.c:296 plugins/sudoers/auth/sudo_auth.c:359
+msgid "no authentication methods"
+msgstr "認証方法がありません"
+
+#: plugins/sudoers/auth/sudo_auth.c:298
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "認証方法が sudo のコンパイル時に組み込まれていません! 認証を無効にする場合には、configure オプションで --disable-authentication を指定してください。"
+
+#: plugins/sudoers/auth/sudo_auth.c:361
+msgid "Unable to initialize authentication methods."
+msgstr "認証方法を初期化できません。"
+
+#: plugins/sudoers/auth/sudo_auth.c:551
+msgid "Authentication methods:"
+msgstr "認証方法:"
+
+#: plugins/sudoers/bsm_audit.c:122 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "監査条件を決定できませんでした"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:278
+msgid "unable to commit audit record"
+msgstr "監査レコードをコミットできません"
+
+#: plugins/sudoers/check.c:63 plugins/sudoers/check.c:74
+#: plugins/sudoers/lookup.c:79 plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "不明な uid %u"
+
+#: plugins/sudoers/check.c:277
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "講義ファイル %s の読み込みエラー"
+
+#: plugins/sudoers/check.c:280
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "講義ファイル %s を無視します: 通常ファイルではありません"
+
+#: plugins/sudoers/check.c:293
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"あなたはシステム管理者から通常の講習を受けたはずです。\n"
+"これは通常、以下の3点に要約されます:\n"
+"\n"
+" #1) 他人のプライバシーを尊重すること。\n"
+" #2) タイプする前に考えること。\n"
+" #3) 大いなる力には大いなる責任が伴うこと。\n"
+"\n"
+
+#: plugins/sudoers/check.c:301
+msgid ""
+"For security reasons, the password you type will not be visible.\n"
+"\n"
+msgstr "セキュリティー上の理由で、あなたがタイプしたパスワードは表示しません。\n"
+
+#: plugins/sudoers/check_aliases.c:93
+#, c-format
+msgid "cycle in %s \"%s\""
+msgstr "循環を発見 %s \"%s\""
+
+#: plugins/sudoers/check_aliases.c:96
+#, c-format
+msgid "%s \"%s\" referenced but not defined"
+msgstr "%s \"%s\" は参照されているのに定義されていません"
+
+#: plugins/sudoers/cvtsudoers.c:211
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "order の増分: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:231
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "開始の order: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:242
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "order の増分: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:252 plugins/sudoers/visudo.c:183
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s 文法バージョン %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:282 plugins/sudoers/testsudoers.c:162
+#, c-format
+msgid "unsupported input format %s"
+msgstr "サポートされてない入力形式です %s"
+
+#: plugins/sudoers/cvtsudoers.c:300
+#, c-format
+msgid "unsupported output format %s"
+msgstr "サポートされてない出力形式です %s"
+
+#: plugins/sudoers/cvtsudoers.c:392
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: 入力ファイルと出力ファイルは別である必要があります"
+
+#: plugins/sudoers/cvtsudoers.c:406 plugins/sudoers/sudoers.c:151
+#: plugins/sudoers/sudoers.c:209 plugins/sudoers/testsudoers.c:315
+#: plugins/sudoers/visudo.c:276 plugins/sudoers/visudo.c:666
+msgid "unable to initialize sudoers default values"
+msgstr "sudoers のデフォルト値を初期化できません"
+
+#: plugins/sudoers/cvtsudoers.c:533 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:612
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s: 不明なキーワード %s"
+
+#: plugins/sudoers/cvtsudoers.c:658
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "無効なデフォルトの指定です: %s"
+
+#: plugins/sudoers/cvtsudoers.c:681
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "無効な抑制の指定です: %s"
+
+#: plugins/sudoers/cvtsudoers.c:722 plugins/sudoers/cvtsudoers.c:738
+#, c-format
+msgid "invalid filter: %s"
+msgstr "無効なフィルターです: %s"
+
+#: plugins/sudoers/cvtsudoers.c:783 plugins/sudoers/visudo.c:1000
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "%s ファイルの構文解析に失敗しました。不明なエラーです"
+
+#: plugins/sudoers/cvtsudoers.c:1508 plugins/sudoers/sudoreplay.c:1143
+#: plugins/sudoers/timestamp.c:353 plugins/sudoers/timestamp.c:356
+#, c-format
+msgid "unable to write to %s"
+msgstr "%s へ書き込むことができません"
+
+#: plugins/sudoers/cvtsudoers.c:1536
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s - sudoers ファイル形式間での変換を行う\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1538
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"オプション:\n"
+" -b, --base=dn sudo の LDAP クエリ のベース DN\n"
+" -c, --config=conf_file 設定ファイルへのパス\n"
+" -d, --defaults=deftypes 指定した形式の Defaults のみを変換する\n"
+" -e, --expand-aliases 変換する時にエイリアスを展開する\n"
+" -f, --output-format=format 出力の書式: JSON, LDIF または sudoers\n"
+" -i, --input-format=format 入力の書式: LDIF または sudoers\n"
+" -I, --increment=num それぞれの sudoOrder の増分\n"
+" -h, --help ヘルプメッセージを表示して終了する\n"
+" -m, --match=filter filter にマッチするエントリのみを変換する\n"
+" -M, --match-local フィルタは passwd および group データベースを使用する\n"
+" -o, --output=output_file 変換された sudoers を output_file に出力する\n"
+" -O, --order-start=num 最初の sudoOrder の開始点\n"
+" -p, --prune-matches マッチしないユーザー、グループ、ホストを取り除く\n"
+" -P, --padding=num base padding for sudoOrder の増分\n"
+" -s, --suppress=sections いくつかのセクションの出力を抑制する\n"
+" -V, --version バージョン情報を表示して終了する"
+
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:245 plugins/sudoers/cvtsudoers_ldif.c:252
+#: plugins/sudoers/cvtsudoers_ldif.c:594 plugins/sudoers/env.c:340
+#: plugins/sudoers/env.c:347 plugins/sudoers/env.c:458
+#: plugins/sudoers/ldap.c:511 plugins/sudoers/ldap.c:629
+#: plugins/sudoers/ldap.c:1003 plugins/sudoers/ldap_conf.c:219
+#: plugins/sudoers/ldap_conf.c:310 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:93 plugins/sudoers/logging.c:479
+#: plugins/sudoers/policy.c:828 plugins/sudoers/policy.c:840
+#: plugins/sudoers/prompt.c:169 plugins/sudoers/serialize_list.c:62
+#: plugins/sudoers/serialize_list.c:71 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/sudoreplay.c:1340 plugins/sudoers/sudoreplay.c:1346
+#: plugins/sudoers/sudoreplay.c:1352 plugins/sudoers/testsudoers.c:306
+#: plugins/sudoers/toke_util.c:217 toke.l:995 toke.l:1277
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "内部エラー、%s がオーバーフローしました"
+
+#: plugins/sudoers/cvtsudoers_csv.c:454 plugins/sudoers/cvtsudoers_csv.c:468
+#: plugins/sudoers/cvtsudoers_json.c:661 plugins/sudoers/cvtsudoers_json.c:676
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:362
+#: plugins/sudoers/ldap.c:495
+msgid "unable to get GMT time"
+msgstr "GMT 時刻を取得できません"
+
+#: plugins/sudoers/cvtsudoers_csv.c:459 plugins/sudoers/cvtsudoers_csv.c:473
+#: plugins/sudoers/cvtsudoers_json.c:666 plugins/sudoers/cvtsudoers_json.c:681
+#: plugins/sudoers/cvtsudoers_ldif.c:354 plugins/sudoers/cvtsudoers_ldif.c:367
+#: plugins/sudoers/ldap.c:503
+msgid "unable to format timestamp"
+msgstr "タイムスタンプを書式整形できません"
+
+#: plugins/sudoers/cvtsudoers_json.c:481 plugins/sudoers/cvtsudoers_json.c:516
+#: plugins/sudoers/cvtsudoers_json.c:732
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: 未知のデフォルト項目 \"%s\" です"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:663
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "sudoers の項目が多すぎます、最大は %u です。"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:706
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "SUDOERS_BASE 環境変数が設定されておらず -b オプションも指定されていません。"
+
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, c-format
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr "%s:%d:%d: ホストのリスト を ALL に変換しています"
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr "エイリアス %s が見つかりません"
+
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, c-format
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr "%s:%d:%d: エイリアスの名前 %s を %s に変更しています"
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr "%s:%d:%d: 重複したエイリアス %s を削除しています"
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr "%s:%d:%d: Defaults のエントリー \"%s\" が %s:%d:%d にある ホスト特定指定sと衝突しています"
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, c-format
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr "%s:%d:%d: Defaults \"%s\" をホスト %s に特有のものとしました。"
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr "%s:%d:%d: Defaults \"%s\" をホストに特有のものにできません"
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr "%s:%d:%d: 後続のエントリーで上書きされた Defaults の \"%s\" を削除しています"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1088
+#, c-format
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr "%s:%d:%d: userspec を %s:%d:%d に併合しています"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1182
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr "%s:%d:%d: 後続のエントリーで上書きされた userspec を削除しています"
+
+#: plugins/sudoers/def_data.c:56
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "ログ記録時に syslog を使用する場合の syslog ファシリティ: %s"
+
+#: plugins/sudoers/def_data.c:60
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "ログ記録時に syslog を使用する場合の syslog プライオリティ: %s"
+
+#: plugins/sudoers/def_data.c:64
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "ユーザー認証に失敗したと時に使用される syslog プライオリティ: %s"
+
+#: plugins/sudoers/def_data.c:68
+msgid "Put OTP prompt on its own line"
+msgstr "ワンタイムパスワード入力要求をそれのみの行に表示します"
+
+#: plugins/sudoers/def_data.c:72
+msgid "Ignore '.' in $PATH"
+msgstr "$PATH 内にある '.' を無視します"
+
+#: plugins/sudoers/def_data.c:76
+msgid "Always send mail when sudo is run"
+msgstr "sudo を実行した時に、常にメールを送信します"
+
+#: plugins/sudoers/def_data.c:80
+msgid "Send mail if user authentication fails"
+msgstr "ユーザー認証に失敗した場合にメールを送信します"
+
+#: plugins/sudoers/def_data.c:84
+msgid "Send mail if the user is not in sudoers"
+msgstr "ユーザー他 sudoers 内に存在しない場合にメールを送信します"
+
+#: plugins/sudoers/def_data.c:88
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "ユーザーがこのホスト用の sudoers 内に存在しない場合にメールを送信します"
+
+#: plugins/sudoers/def_data.c:92
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "ユーザーが許可されていないコマンドを実行しようとした場合にメールを送信します"
+
+#: plugins/sudoers/def_data.c:96
+msgid "Send mail if the user tries to run a command"
+msgstr "ユーザーがマンドを実行しようとした場合にメールを送信します"
+
+#: plugins/sudoers/def_data.c:100
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "ユーザー/tty の組み合わせごとに分離したタイムスタンプを使用します"
+
+#: plugins/sudoers/def_data.c:104
+msgid "Lecture user the first time they run sudo"
+msgstr "ユーザーが最初に sudo を実行した時に講義を行う"
+
+#: plugins/sudoers/def_data.c:108
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "sudo の講義が含まれているファイル: %s"
+
+#: plugins/sudoers/def_data.c:112
+msgid "Require users to authenticate by default"
+msgstr "デフォルトでユーザーが認証されていることを必要とします"
+
+#: plugins/sudoers/def_data.c:116
+msgid "Root may run sudo"
+msgstr "root が sudo を実行するかもしれません"
+
+#: plugins/sudoers/def_data.c:120
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr " ログファイル (syslog 以外) に記録する時にホスト名を含めます"
+
+#: plugins/sudoers/def_data.c:124
+msgid "Log the year in the (non-syslog) log file"
+msgstr "ログファイル (syslog 以外) に記録する時に年情報を含めます"
+
+#: plugins/sudoers/def_data.c:128
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "sudo を引数無しで起動した場合、シェルを開始します"
+
+#: plugins/sudoers/def_data.c:132
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "シェルを -s で開始した時に $HOME を変更後のユーザーのホームディレクトリに設定します"
+
+#: plugins/sudoers/def_data.c:136
+msgid "Always set $HOME to the target user's home directory"
+msgstr "$HOME を常に変更後のユーザーのホームディレクトリに設定します"
+
+#: plugins/sudoers/def_data.c:140
+msgid "Allow some information gathering to give useful error messages"
+msgstr "役に立つエラーメッセージを表示するためにいくつかの情報を収集することを許可します"
+
+#: plugins/sudoers/def_data.c:144
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "sudoers ファイルに完全修飾ホスト名 (FQDN) を要求します"
+
+#: plugins/sudoers/def_data.c:148
+msgid "Insult the user when they enter an incorrect password"
+msgstr "間違ったパスワードを入力した時にユーザーを侮辱します"
+
+#: plugins/sudoers/def_data.c:152
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "tty がある場合のみ sudo の実行を許可します"
+
+#: plugins/sudoers/def_data.c:156
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "visudo が EDITOR 環境変数を尊重して使用します"
+
+#: plugins/sudoers/def_data.c:160
+msgid "Prompt for root's password, not the users's"
+msgstr "ユーザーのパスワードではなく、root のパスワードの入力を要求します"
+
+#: plugins/sudoers/def_data.c:164
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "ユーザーのパスワードではなく、 runas_default ユーザーのパスワードの入力を要求します"
+
+#: plugins/sudoers/def_data.c:168
+msgid "Prompt for the target user's password, not the users's"
+msgstr "現在のユーザーのパスワードではなく、変更先ユーザーのパスワードの入力を要求します"
+
+#: plugins/sudoers/def_data.c:172
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "変更先ユーザーのログインクラスのデフォルトが存在する場合は、デフォルトを適用します"
+
+#: plugins/sudoers/def_data.c:176
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "LOGNAME および USER 環境変数を設定します"
+
+#: plugins/sudoers/def_data.c:180
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "実効ユーザーIDのみ変更先ユーザーの UID に設定し、実ユーザーIDは変更しない"
+
+#: plugins/sudoers/def_data.c:184
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "グループベクトルを変更先ユーザーの値で初期化しない"
+
+#: plugins/sudoers/def_data.c:188
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "ログファイルの行頭から改行までの長さ (0 の場合は改行しない): %u"
+
+#: plugins/sudoers/def_data.c:192
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "認証タイムスタンプのタイムアウト値: %.1f 分"
+
+#: plugins/sudoers/def_data.c:196
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "パスワード入力要求のタイムアウト値: %.1f 分"
+
+#: plugins/sudoers/def_data.c:200
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "パスワード入力の試行回数: %u"
+
+#: plugins/sudoers/def_data.c:204
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "使用する umask 値 (0777 の場合はユーザーの設定値を使用します): 0%o"
+
+#: plugins/sudoers/def_data.c:208
+#, c-format
+msgid "Path to log file: %s"
+msgstr "ログファイルのパス: %s"
+
+#: plugins/sudoers/def_data.c:212
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "メールプログラムのパス: %s"
+
+#: plugins/sudoers/def_data.c:216
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "メールプログラムの引数フラグ: %s"
+
+#: plugins/sudoers/def_data.c:220
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "メールの送信先アドレス: %s"
+
+#: plugins/sudoers/def_data.c:224
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "メールの送信元アドレス: %s"
+
+#: plugins/sudoers/def_data.c:228
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "メールの件名 (Subject) 行: %s"
+
+#: plugins/sudoers/def_data.c:232
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "パスワードを間違った時のメッセージ: %s"
+
+#: plugins/sudoers/def_data.c:236
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "受講状況ディレクトリのパス: %s"
+
+#: plugins/sudoers/def_data.c:240
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "認証タイムスタンプディレクトリのパス: %s"
+
+#: plugins/sudoers/def_data.c:244
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "認証タイムスタンプディレクトリの所有者: %s"
+
+#: plugins/sudoers/def_data.c:248
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "パスワード入力と PATH の要求が免除されるグループに属するユーザー: %s"
+
+#: plugins/sudoers/def_data.c:252
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "パスワード入力要求時に表示される文字列: %s"
+
+#: plugins/sudoers/def_data.c:256
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "設定した場合、すべての場合において passprompt がシステムの入力要求表示を上書きします"
+
+#: plugins/sudoers/def_data.c:260
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "コマンドを実行するデフォルトの変更先ユーザー: %s"
+
+#: plugins/sudoers/def_data.c:264
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "ユーザーの $PATH を上書きする時の値: %s"
+
+#: plugins/sudoers/def_data.c:268
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "visudo で使用されるエディターのパス: %s"
+
+#: plugins/sudoers/def_data.c:272
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "'list' 疑似コマンド使用するためにパスワードを要求される時: %s"
+
+#: plugins/sudoers/def_data.c:276
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "'verify' 疑似コマンドを使用するためにパスワードを要求される時: %s"
+
+#: plugins/sudoers/def_data.c:280
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "exec 関数群を置き換える sudo_noexec ライブラリ事前ロードします"
+
+# do はたぶん強調の do
+#: plugins/sudoers/def_data.c:284
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "LDAP ディレクトリが実行中の場合、ローカルの sudoers ファイルを無視します"
+
+#: plugins/sudoers/def_data.c:288
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "%d 以上の値をもつファイル記述子をコマンド実行前に閉じます"
+
+#: plugins/sudoers/def_data.c:292
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "設定しても、ユーザーが \"closefrom\" の値を -C オプションで上書きするかもしれません"
+
+#: plugins/sudoers/def_data.c:296
+msgid "Allow users to set arbitrary environment variables"
+msgstr "ユーザーが任意の環境変数を設定することを許可します"
+
+#: plugins/sudoers/def_data.c:300
+msgid "Reset the environment to a default set of variables"
+msgstr "環境変数の集合をデフォルトに設定します"
+
+#: plugins/sudoers/def_data.c:304
+msgid "Environment variables to check for safety:"
+msgstr "安全性の確認を行う環境変数:"
+
+#: plugins/sudoers/def_data.c:308
+msgid "Environment variables to remove:"
+msgstr "削除する環境変数:"
+
+#: plugins/sudoers/def_data.c:312
+msgid "Environment variables to preserve:"
+msgstr "保護する環境変数:"
+
+#: plugins/sudoers/def_data.c:316
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "新しいセキュリティコンテキスト内で使用する SELinux の役割: %s"
+
+#: plugins/sudoers/def_data.c:320
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "新しいセキュリティコンテキスト内で使用する SELinux のタイプ: %s"
+
+#: plugins/sudoers/def_data.c:324
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "sudo 固有の環境ファイルのパス: %s"
+
+#: plugins/sudoers/def_data.c:328
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "制限付きsudo 固有の環境ファイルのパス: %s"
+
+#: plugins/sudoers/def_data.c:332
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "sudoers を構文解析する時に使用するロケール: %s"
+
+#: plugins/sudoers/def_data.c:336
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "パスワードが表示されてしまう状態であっても sudo がパスワード入力を要求することを許可します"
+
+#: plugins/sudoers/def_data.c:340
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "パスワード入力要求でユーザーの入力があった時に、視覚的なフィードバックを提供します"
+
+#: plugins/sudoers/def_data.c:344
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "ファイルシステムにアクセスしないがより正確では無い、素早い一致確認処理を行います"
+
+#: plugins/sudoers/def_data.c:348
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "sudoers で指定した umask 値でユーザーの umask 値を上書きします (ユーザーの umask 値より緩い場合でも)"
+
+#: plugins/sudoers/def_data.c:352
+msgid "Log user's input for the command being run"
+msgstr "コマンドを実行した時のユーザー入力をログに記録します"
+
+#: plugins/sudoers/def_data.c:356
+msgid "Log the command's standard input if not connected to a terminal"
+msgstr "端末に接続していない場合にコマンドの標準入力をログに記録します"
+
+#: plugins/sudoers/def_data.c:360
+msgid "Log the user's terminal input for the command being run"
+msgstr "コマンドを実行した時のユーザーの端末入力をログに記録します"
+
+#: plugins/sudoers/def_data.c:364
+msgid "Log the output of the command being run"
+msgstr "コマンドを実行した時の出力をログに記録します"
+
+#: plugins/sudoers/def_data.c:368
+msgid "Log the command's standard output if not connected to a terminal"
+msgstr "端末に接続していない場合にコマンドの標準出力をログに記録します"
+
+#: plugins/sudoers/def_data.c:372
+msgid "Log the command's standard error if not connected to a terminal"
+msgstr "端末に接続していない場合にコマンドの標準エラー出力をログに記録します"
+
+#: plugins/sudoers/def_data.c:376
+msgid "Log the terminal output of the command being run"
+msgstr "コマンドを実行した時の端末出力をログに記録します"
+
+#: plugins/sudoers/def_data.c:380
+msgid "Compress I/O logs using zlib"
+msgstr "I/O ログを zlib を使用して圧縮します"
+
+#: plugins/sudoers/def_data.c:384
+msgid "Always run commands in a pseudo-tty"
+msgstr "常に疑似 tty 内でコマンドを実行します"
+
+#: plugins/sudoers/def_data.c:388
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "UNIX 以外のグループをサポートするためのプラグインです:%s"
+
+#: plugins/sudoers/def_data.c:392
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "入出力 (I/O) ログを保存するディレクトリです:%s"
+
+#: plugins/sudoers/def_data.c:396
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "入出力 (I/O) ログを保存するファイルです:%s"
+
+#: plugins/sudoers/def_data.c:400
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "pty を割り当てた時に utmp/utmpx ファイルに記録を加えます"
+
+#: plugins/sudoers/def_data.c:404
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "utmp に記録するユーザーを、実行したユーザーではなく、変更後のユーザーにします"
+
+#: plugins/sudoers/def_data.c:408
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "許容される権限の集合: %s"
+
+#: plugins/sudoers/def_data.c:412
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "制限される権限の集合: %s"
+
+#: plugins/sudoers/def_data.c:416
+msgid "Run commands on a pty in the background"
+msgstr "コマンドを pty でバックグラウンドで実行する"
+
+#: plugins/sudoers/def_data.c:420
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "利用する PAM サービス名: %s"
+
+#: plugins/sudoers/def_data.c:424
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "ログインシェルで利用する PAM サービス名: %s"
+
+#: plugins/sudoers/def_data.c:428
+#, c-format
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr "sudo が -A オプション付きで実行されたときに使う PAM サービス名: %s"
+
+#: plugins/sudoers/def_data.c:432
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "ターゲットユーザーの PAM 資格情報による認証を試みる"
+
+#: plugins/sudoers/def_data.c:436
+msgid "Create a new PAM session for the command to run in"
+msgstr "実行するコマンドのために新しい PAM セッションを生成する"
+
+#: plugins/sudoers/def_data.c:440
+msgid "Perform PAM account validation management"
+msgstr "PAM アカウント検証管理を実行しています"
+
+#: plugins/sudoers/def_data.c:444
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "I/O ログシーケンス番号の最大値: %s"
+
+#: plugins/sudoers/def_data.c:448
+msgid "Enable sudoers netgroup support"
+msgstr "sudoers のネットグループサポートを有効にする"
+
+#: plugins/sudoers/def_data.c:452
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "ファイルを sudoedit で編集するときに親ディレクトリが書き込み可能か確かめる"
+
+#: plugins/sudoers/def_data.c:456
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "ファイルを sudoedit で編集するときにシンボリックリンクを追う"
+
+#: plugins/sudoers/def_data.c:460
+msgid "Query the group plugin for unknown system groups"
+msgstr "不明なシステムグループについて、グループプラグインに問い合わせる"
+
+#: plugins/sudoers/def_data.c:464
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "ネットグループについて、すべてのタプル(ユーザー、ホスト、ドメイン)を基に判定する"
+
+#: plugins/sudoers/def_data.c:468
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "監査ログファイルへの書き込みができなくても、コマンドの実行を許可する"
+
+#: plugins/sudoers/def_data.c:472
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "I/O ログファイルへの書き込みができなくても、コマンドの実行を許可する"
+
+#: plugins/sudoers/def_data.c:476
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "ログファイルへの書き込みができなくても、コマンドの実行を許可する"
+
+#: plugins/sudoers/def_data.c:480
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "グループの照合を sudoers の中で行い、グループ名でなくグループIDを用いる"
+
+#: plugins/sudoers/def_data.c:484
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "ログエントリーがこの値より長くなると、複数の syslog メッセージに分割されます: %u"
+
+#: plugins/sudoers/def_data.c:488
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "I/O ログの所有者となるユーザー: %s"
+
+#: plugins/sudoers/def_data.c:492
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "I/O ログの所有者となるグループ: %s"
+
+#: plugins/sudoers/def_data.c:496
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "I/O ログのファイルモード: 0%o"
+
+#: plugins/sudoers/def_data.c:500
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "コマンドの実行時にパスでなくファイル記述子を使う: %s"
+
+#: plugins/sudoers/def_data.c:504
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "sudoers の中の未知の Defaults エントリーを無視し、警告を出さない"
+
+#: plugins/sudoers/def_data.c:508
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "コマンドが中断されるまでの経過時間を秒で指定する: %u"
+
+#: plugins/sudoers/def_data.c:512
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "ユーザーがコマンド実行の制限時間をコマンドラインで指定できるようにする"
+
+#: plugins/sudoers/def_data.c:516
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "I/O ログのデータをバッファせずに、即ディスクにフラッシュする"
+
+#: plugins/sudoers/def_data.c:520
+msgid "Include the process ID when logging via syslog"
+msgstr "syslog へのログ記録時にプロセスIDを含める"
+
+#: plugins/sudoers/def_data.c:524
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "認証タイムスタンプのタイプ: %s"
+
+#: plugins/sudoers/def_data.c:528
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "認証失敗メッセージ: %s"
+
+#: plugins/sudoers/def_data.c:532
+msgid "Ignore case when matching user names"
+msgstr "ユーザー名の検索で大文字小文字を同一視する"
+
+#: plugins/sudoers/def_data.c:536
+msgid "Ignore case when matching group names"
+msgstr "グループ名の検索で大文字小文字を同一視する"
+
+#: plugins/sudoers/def_data.c:540
+msgid "Log when a command is allowed by sudoers"
+msgstr "コマンドが sudoers で許可された場合にログに記録します"
+
+#: plugins/sudoers/def_data.c:544
+msgid "Log when a command is denied by sudoers"
+msgstr "コマンドが sudoers で拒否された場合にログに記録します"
+
+#: plugins/sudoers/def_data.c:548
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "オプショナルなポートで接続する Sudo ログサーバー"
+
+#: plugins/sudoers/def_data.c:552
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Sudo ログサーバーのタイムアウト、単位は秒: %u"
+
+#: plugins/sudoers/def_data.c:556
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "ログサーバーに接続したソケットで SO_KEEPALIVE ソケットオプションを有効にする"
+
+#: plugins/sudoers/def_data.c:560
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "認証サーバーの CA バンドルファイルのパス: %s"
+
+#: plugins/sudoers/def_data.c:564
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "sudoers の証明書ファイルのパス: %s"
+
+#: plugins/sudoers/def_data.c:568
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "sudoers のプライベート鍵ファイルのパス: %s"
+
+#: plugins/sudoers/def_data.c:572
+msgid "Verify that the log server's certificate is valid"
+msgstr "ログサーバーの証明書が有効か検証する"
+
+#: plugins/sudoers/def_data.c:576
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "未知の runas ユーザーおよび/またはグループ ID を使うことを許可する"
+
+#: plugins/sudoers/def_data.c:580
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "有効なシェルを持つユーザーのみにコマンド実行を許可する"
+
+#: plugins/sudoers/def_data.c:584
+msgid "Set the pam remote user to the user running sudo"
+msgstr "PAMのリモートユーザーを sudo を実行しているユーザーに設定"
+
+#: plugins/sudoers/def_data.c:588
+msgid "Set the pam remote host to the local host name"
+msgstr "PAMのリモートホストをローカルホスト名に設定"
+
+#: plugins/sudoers/def_data.c:592
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "コマンド実行前に変更する作業ディレクトリ: %s"
+
+#: plugins/sudoers/def_data.c:596
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "コマンド実行前に変更するルートディレクトリ: %s"
+
+#: plugins/sudoers/def_data.c:600
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "生成するログの書式: %s"
+
+#: plugins/sudoers/def_data.c:604
+msgid "Enable SELinux RBAC support"
+msgstr "SELinux RBAC のサポートを有効にする"
+
+#: plugins/sudoers/def_data.c:608
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "sudo が最初に実行された時に作成されるファイルのパス: %s"
+
+#: plugins/sudoers/def_data.c:612
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "これ以降のコマンドに割り込み、sudoers による制限を適用する"
+
+#: plugins/sudoers/def_data.c:616
+msgid "Log sub-commands run by the original command"
+msgstr "コマンドが実行したサブコマンドをログに記録する"
+
+#: plugins/sudoers/def_data.c:620
+msgid "Log the exit status of commands"
+msgstr "コマンドを実行した後の終了ステータスをログに記録します"
+
+#: plugins/sudoers/def_data.c:624
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr "割り込みセッションの中で続くコマンドには認証が必要です"
+
+#: plugins/sudoers/def_data.c:628
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr "割り込まれたコマンドが setuid または setgid プログラムを実行することを許可します"
+
+#: plugins/sudoers/def_data.c:632
+#, c-format
+msgid "The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr "プロセスのアドレス空間の最大値(バイト単位): %s"
+
+#: plugins/sudoers/def_data.c:636
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr "コアダンプファイルの最大サイズ(バイト単位): %s"
+
+#: plugins/sudoers/def_data.c:640
+#, c-format
+msgid "The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr "プロセスが使用するCPU時間の最大値(秒単位): %s"
+
+#: plugins/sudoers/def_data.c:644
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr "プロセスのデータセグメントサイズの最大値(バイト単位): %s"
+
+#: plugins/sudoers/def_data.c:648
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr "プロセスが作成するファイルサイズの最大値(バイト単位): %s"
+
+#: plugins/sudoers/def_data.c:652
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr "プロセスが作るロックの最大数: %s"
+
+#: plugins/sudoers/def_data.c:656
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr "プロセスがロックするメモリーサイズの最大値(バイト単位): %s"
+
+#: plugins/sudoers/def_data.c:660
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr "プロセスが開くファイル数の最大値: %s"
+
+#: plugins/sudoers/def_data.c:664
+#, c-format
+msgid "The maximum number of processes that the user may run simultaneously: %s"
+msgstr "ユーザーが同時に走らせるプロセスの最大数: %s"
+
+#: plugins/sudoers/def_data.c:668
+#, c-format
+msgid "The maximum size to which the process's resident set size may grow (in bytes): %s"
+msgstr "プロセスが使用するメモリー(RSS)の最大値(バイト単位): %s"
+
+#: plugins/sudoers/def_data.c:672
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr "プロセスのスタックサイズの最大値(バイト単位): %s"
+
+#: plugins/sudoers/def_data.c:676
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr "非対話モードでも認証を試みる"
+
+#: plugins/sudoers/def_data.c:680
+msgid "Store plaintext passwords in I/O log input"
+msgstr "I/Oログ入力に平分のパスワードを格納する"
+
+#: plugins/sudoers/def_data.c:684
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr "パスワードのプロンプトに一致するか調べる正規表現の一覧"
+
+#: plugins/sudoers/def_data.c:688
+#, c-format
+msgid "The mechanism used by the intercept and log_subcmds options: %s"
+msgstr "インターセプトと log_subcmds オプションで使われるメカニズム: %s"
+
+#: plugins/sudoers/def_data.c:692
+msgid "Attempt to verify the command and arguments after execution"
+msgstr "コマンドと引数を実行後に検証することを試みます"
+
+#: plugins/sudoers/def_data.c:696
+#, c-format
+msgid "AppArmor profile to use in the new security context: %s"
+msgstr "新しいセキュリティコンテキスト内で使用する AppArmor プロファイル: %s"
+
+#: plugins/sudoers/defaults.c:207
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "不明なデフォルト項目 \"%s\" です"
+
+#: plugins/sudoers/defaults.c:251
+#, c-format
+msgid "no value specified for \"%s\""
+msgstr "\"%s\" に値が指定されていません"
+
+#: plugins/sudoers/defaults.c:260
+#, c-format
+msgid "invalid operator \"%c=\" for \"%s\""
+msgstr "\"%c=\" は \"%s\" には無効な演算子です"
+
+#: plugins/sudoers/defaults.c:292
+#, c-format
+msgid "option \"%s\" does not take a value"
+msgstr "オプション \"%s\" は値をとりません"
+
+#: plugins/sudoers/defaults.c:319
+#, c-format
+msgid "invalid Defaults type 0x%x for option \"%s\""
+msgstr "0x%x はオプション \"%s\" のデフォルトタイプとして無効です"
+
+#: plugins/sudoers/defaults.c:326
+#, c-format
+msgid "value \"%s\" is invalid for option \"%s\""
+msgstr "\"%s\" はオプション \"%s\" の値としては無効です"
+
+#: plugins/sudoers/defaults.c:1176 plugins/sudoers/policy.c:213
+#: plugins/sudoers/policy.c:222
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr "\"%s\" のパス名が長すぎます"
+
+#: plugins/sudoers/defaults.c:1182
+#, c-format
+msgid "values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "\"%s\" の値は '/', '~', または '*' で開始しなければいけません"
+
+#: plugins/sudoers/defaults.c:1189
+#, c-format
+msgid "values for \"%s\" must start with a '/'"
+msgstr "\"%s\" の値は '/' で開始しなければいけません"
+
+#: plugins/sudoers/display.c:160
+#, c-format
+msgid "LDAP Role: %s\n"
+msgstr "LDAP 役割: %s\n"
+
+#: plugins/sudoers/display.c:163
+#, c-format
+msgid "Sudoers entry: %s\n"
+msgstr "sudoers 項目: %s\n"
+
+#: plugins/sudoers/display.c:166
+msgid " RunAsUsers: "
+msgstr " RunAsUsers: "
+
+#: plugins/sudoers/display.c:181
+msgid " RunAsGroups: "
+msgstr " RunAsGroups: "
+
+#: plugins/sudoers/display.c:191
+msgid " Options: "
+msgstr " オプション: "
+
+#: plugins/sudoers/display.c:255
+msgid " Commands:\n"
+msgstr " コマンド:\n"
+
+#: plugins/sudoers/display.c:478
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "既定値のエントリと照合中 (ユーザー名 %s) (ホスト名 %s):\n"
+
+#: plugins/sudoers/display.c:496
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "ユーザー %s 用の Runas およびコマンド特有のデフォルト:\n"
+
+#: plugins/sudoers/display.c:514
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "ユーザー %s は %s 上で コマンドを実行できます\n"
+
+#: plugins/sudoers/display.c:530
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "ユーザー %s は %s 上で sudo を実行することを許可されていません。\n"
+
+#: plugins/sudoers/editor.c:180
+#, c-format
+msgid "ignoring editor: %.*s"
+msgstr "エディターを無視します: %.*s"
+
+#: plugins/sudoers/editor.c:181
+msgid "editor arguments may not contain \"--\""
+msgstr "エディターの引数には \"--\" を含むことができません"
+
+#: plugins/sudoers/env.c:426
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: envp が破損しています。長さが合いません"
+
+#: plugins/sudoers/env.c:1119
+msgid "unable to rebuild the environment"
+msgstr "環境を再構築できません"
+
+#: plugins/sudoers/env.c:1199
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "残念ですが、あなたは次の環境変数を設定することを許可されていません: %s"
+
+#: plugins/sudoers/filedigest.c:50
+#, c-format
+msgid "unsupported digest type %u for %s"
+msgstr "サポートされてない 認証方式 %u を %s に適用しようとしました"
+
+#: plugins/sudoers/filedigest.c:77
+#, c-format
+msgid "%s: read error"
+msgstr "%s: 読み込みエラー"
+
+#: plugins/sudoers/group_plugin.c:169 plugins/sudoers/sssd.c:578
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "%s をロードできません: %su"
+
+#: plugins/sudoers/group_plugin.c:181
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "%s 内にシンボル \"group_plugin\" がありません"
+
+#: plugins/sudoers/group_plugin.c:186
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: 互換性のないグループプラグインメジャーバージョン %d です。予期されるのは %d です"
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "IPアドレス \"%s\" を解析できません"
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "ネットマスク \"%s\" を解析できません"
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "ローカル IP アドレスとネットマスクの組:\n"
+
+#: plugins/sudoers/iolog.c:694
+msgid "unable to update sequence file"
+msgstr "シーケンスファイルを更新できません"
+
+#: plugins/sudoers/iolog.c:728 plugins/sudoers/iolog.c:917
+#: plugins/sudoers/iolog.c:1080 plugins/sudoers/iolog.c:1087
+#: plugins/sudoers/iolog.c:1209 plugins/sudoers/iolog.c:1216
+#: plugins/sudoers/iolog.c:1316 plugins/sudoers/iolog.c:1323
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "%s へ I/O ログを書き込むことができません"
+
+#: plugins/sudoers/iolog.c:736
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "%s/%s を作成できません"
+
+#: plugins/sudoers/iolog.c:965
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: 内部エラー、I/O イベント %d のログファイルを開けません"
+
+#: plugins/sudoers/iolog.c:1065 plugins/sudoers/iolog.c:1194
+#: plugins/sudoers/iolog.c:1300 plugins/sudoers/timestamp.c:897
+#: plugins/sudoers/timestamp.c:989 plugins/sudoers/visudo.c:555
+#: plugins/sudoers/visudo.c:561
+msgid "unable to read the clock"
+msgstr "時刻を読み込むことができません"
+
+#: plugins/sudoers/iolog.c:1292 plugins/sudoers/log_client.c:1203
+#: plugins/sudoers/log_client.c:1213 plugins/sudoers/log_client.c:1217
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: 内部エラー、無効なシグナル %d"
+
+#: plugins/sudoers/ldap.c:154 plugins/sudoers/ldap_conf.c:289
+msgid "starttls not supported when using ldaps"
+msgstr "starttls は ldaps を使用時にはサポートされていません"
+
+#: plugins/sudoers/ldap.c:226
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "SSL 証明書と鍵データベースを初期化できません: %s"
+
+#: plugins/sudoers/ldap.c:229
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "SSL を使用するためには %s の中の TLS_CERT を設定する必要があります"
+
+#: plugins/sudoers/ldap.c:1593
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "LDAP を初期化できません: %s"
+
+#: plugins/sudoers/ldap.c:1630
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls が指定されていますが、LDAP ライブラリが ldap_start_tls_s() または ldap_start_tls_s_np() をサポートしていません"
+
+#: plugins/sudoers/ldap.c:1767 plugins/sudoers/parse_ldif.c:745
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "無効な sudoOrder 属性です: %s"
+
+#: plugins/sudoers/ldap_conf.c:197
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: ポートが大き過ぎます"
+
+#: plugins/sudoers/ldap_conf.c:258
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "サポートされてない LDAP URI タイプです: %s"
+
+#: plugins/sudoers/ldap_conf.c:285
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "ldap と ldaps の URI を混ぜて使用できません"
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "sudoOption が重複しています: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "sudoOption を変換できません: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "監査システムを開くことができません"
+
+#: plugins/sudoers/linux_audit.c:104
+msgid "unable to send audit message"
+msgstr "監査メッセージを送ることができません"
+
+#: plugins/sudoers/log_client.c:125 plugins/sudoers/log_client.c:412
+#: plugins/sudoers/log_client.c:1450 plugins/sudoers/log_client.c:2076
+msgid "error in event loop"
+msgstr "イベントループでエラーが発生しました"
+
+#: plugins/sudoers/log_client.c:205
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "新しい SSL_CTX オブジェクトの作成に失敗しました: %s"
+
+#: plugins/sudoers/log_client.c:230
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "認証局の証明書バンドル %s をロードできません"
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "証明書 %s をロードできません"
+
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "unable to load private key %s"
+msgstr "プライベート鍵を読み込めません: %s"
+
+#: plugins/sudoers/log_client.c:275
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "SSLオブジェクトを割り当てることができません: %s"
+
+#: plugins/sudoers/log_client.c:364 plugins/sudoers/log_client.c:369
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "%s:%s へのTLS接続に失敗しました: %s"
+
+#: plugins/sudoers/log_client.c:545
+msgid "TLS initialization was unsuccessful"
+msgstr "TLS 初期化が成功しませんでした"
+
+#: plugins/sudoers/log_client.c:555
+msgid "TLS handshake was unsuccessful"
+msgstr "TLS ハンドシェイクが成功しませんでした"
+
+#: plugins/sudoers/log_client.c:1221
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: 内部エラー、無効な終了コード %d"
+
+#: plugins/sudoers/log_client.c:1757 plugins/sudoers/log_client.c:1782
+msgid "lost connection to log server"
+msgstr "ログサーバーへの接続が失われました"
+
+#: plugins/sudoers/log_client.c:1859
+msgid "missing write buffer"
+msgstr "書き込みバッファが失われました"
+
+#: plugins/sudoers/log_client.c:2015
+msgid "unable to connect to log server"
+msgstr "ログサーバーに接続できません"
+
+#: plugins/sudoers/logging.c:295
+msgid "user NOT in sudoers"
+msgstr "ユーザーが sudoers 内にありません"
+
+#: plugins/sudoers/logging.c:297
+msgid "user NOT authorized on host"
+msgstr "ホスト上でユーザーが認証されていません"
+
+#: plugins/sudoers/logging.c:299
+msgid "command not allowed"
+msgstr "コマンドが許可されていません"
+
+#: plugins/sudoers/logging.c:320
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr "%s は sudoers ファイルにありません。\n"
+
+#: plugins/sudoers/logging.c:323
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr "%s は %s 上で sudo を実行することを許可されていません。\n"
+
+#: plugins/sudoers/logging.c:326
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "残念ですが、ユーザー %s は %s 上で sudo を実行できません。\n"
+
+#: plugins/sudoers/logging.c:339
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s%s' as %s%s%s on %s.\n"
+msgstr "残念ですが、ユーザー %s は'%s%s%s%s' を %s%s%s として %s 上で実行することは許可されていません。\n"
+
+#: plugins/sudoers/logging.c:350
+msgid "This incident has been reported to the administrator.\n"
+msgstr "この出来事は管理者宛てに報告されました。\n"
+
+#: plugins/sudoers/logging.c:387 plugins/sudoers/sudoers.c:547
+#: plugins/sudoers/sudoers.c:549 plugins/sudoers/sudoers.c:551
+#: plugins/sudoers/sudoers.c:553 plugins/sudoers/sudoers.c:777
+#: plugins/sudoers/sudoers.c:779
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: コマンドが見つかりません"
+
+#: plugins/sudoers/logging.c:389 plugins/sudoers/sudoers.c:543
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"'.' 内で見つかった \"%1$s\" を無視します\n"
+"この \"%3$s\" を実行したい場合は \"sudo ./%2$s\" を使用してください。"
+
+#: plugins/sudoers/logging.c:409
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u 回パスワード試行を間違えました"
+
+#: plugins/sudoers/logging.c:500
+msgid "authentication failure"
+msgstr "認証失敗"
+
+#: plugins/sudoers/logging.c:539 plugins/sudoers/logging.c:558
+msgid "a password is required"
+msgstr "パスワードが必要です"
+
+#: plugins/sudoers/logging.c:881
+msgid "problem parsing sudoers"
+msgstr "sudoers を構文解析する時に起きた問題"
+
+#: plugins/sudoers/logging.c:922 plugins/sudoers/logging.c:930
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr "%s:%d:%d: %s"
+
+#: plugins/sudoers/logging.c:1108
+#, c-format
+msgid "unable to write log file %s"
+msgstr "ログファイル %s に書き込むことができません"
+
+#: plugins/sudoers/match_digest.c:107
+#, c-format
+msgid "digest for %s (%s) bad length %zu, expected %zu"
+msgstr "%s (%s) のハッシュの長さが %zu で、 予期される %zu ではありません"
+
+#: plugins/sudoers/match_digest.c:126
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "%s (%s) のハッシュは %s 形式ではありません"
+
+#: plugins/sudoers/parse_ldif.c:615
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "不完全な sudoRole: cn: %s を無視します"
+
+#: plugins/sudoers/parse_ldif.c:675
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "無効な LDIF 属性です: %s"
+
+#: plugins/sudoers/parser_warnx.c:56
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: plugins/sudoers/parser_warnx.c:59
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s: %s\n"
+
+#: plugins/sudoers/pivot.c:71
+msgid "unable to restore root directory"
+msgstr "ルートディレクトリを取得できません"
+
+#: plugins/sudoers/pivot.c:79
+msgid "unable to restore current working directory"
+msgstr "カレント作業ディレクトリを取得できません"
+
+#: plugins/sudoers/policy.c:78 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "無効な %.*s が sudo のフロントエンドで設定されています"
+
+#: plugins/sudoers/policy.c:364 plugins/sudoers/testsudoers.c:329
+msgid "unable to parse network address list"
+msgstr "ネットワークのアドレスリストを解析できません"
+
+#: plugins/sudoers/policy.c:556
+msgid "user name not set by sudo front-end"
+msgstr "ユーザー名が sudo のフロントエンドで設定されていません"
+
+#: plugins/sudoers/policy.c:560
+msgid "user-ID not set by sudo front-end"
+msgstr "ユーザーIDが sudo のフロントエンドで設定されていません"
+
+#: plugins/sudoers/policy.c:564
+msgid "group-ID not set by sudo front-end"
+msgstr "グループIDが sudo のフロントエンドで設定されていません"
+
+#: plugins/sudoers/policy.c:568
+msgid "host name not set by sudo front-end"
+msgstr "ホスト名が sudo のフロントエンドで設定されていません"
+
+#: plugins/sudoers/policy.c:757
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "無効な作業ディレクトリ: %s"
+
+#: plugins/sudoers/policy.c:944
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "無効な chroot ディレクトリ: %s"
+
+#: plugins/sudoers/policy.c:1153 plugins/sudoers/visudo.c:919
+#: plugins/sudoers/visudo.c:1218
+#, c-format
+msgid "unable to execute %s"
+msgstr "%s を実行できません"
+
+#: plugins/sudoers/policy.c:1225 plugins/sudoers/policy.c:1260
+#: plugins/sudoers/policy.c:1282 plugins/sudoers/policy.c:1300
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: 無効なモードフラグが sudo のフロントエンドで指定されています: 0x%x"
+
+#: plugins/sudoers/policy.c:1323
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "sudoers ポリシープラグイン バージョン %s\n"
+
+#: plugins/sudoers/policy.c:1325
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "sudoers ファイル文法バージョン %d\n"
+
+#: plugins/sudoers/policy.c:1329
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"sudoers のパス: %s\n"
+
+#: plugins/sudoers/policy.c:1332
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "nsswitch のパス: %s\n"
+
+#: plugins/sudoers/policy.c:1335
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "ldap.conf のパス: %s\n"
+
+#: plugins/sudoers/policy.c:1337
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "ldap.secret のパス: %s\n"
+
+#: plugins/sudoers/policy.c:1370
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "タイプ %d のフックを登録できません (バージョン %d.%d)"
+
+#: plugins/sudoers/policy.c:1388
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "タイプ %d のフックを登録解除できません (バージョン %d.%d)"
+
+#: plugins/sudoers/pwutil.c:242 plugins/sudoers/pwutil.c:260
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "ユーザーID %u をキャッシュできません"
+
+#: plugins/sudoers/pwutil.c:254
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "ユーザーID %u をキャッシュできません。すでに存在します"
+
+#: plugins/sudoers/pwutil.c:314 plugins/sudoers/pwutil.c:332
+#: plugins/sudoers/pwutil.c:395 plugins/sudoers/pwutil.c:440
+#, c-format
+msgid "unable to cache user %s"
+msgstr "ユーザー %s をキャッシュできません"
+
+#: plugins/sudoers/pwutil.c:327
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "ユーザー %s をキャッシュできません。すでに存在します"
+
+#: plugins/sudoers/pwutil.c:559 plugins/sudoers/pwutil.c:577
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "グループID %u をキャッシュできません"
+
+#: plugins/sudoers/pwutil.c:571
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "グループID %u をキャッシュできません。すでに存在します"
+
+#: plugins/sudoers/pwutil.c:625 plugins/sudoers/pwutil.c:643
+#: plugins/sudoers/pwutil.c:704 plugins/sudoers/pwutil.c:753
+#, c-format
+msgid "unable to cache group %s"
+msgstr "グループ %s をキャッシュできません"
+
+#: plugins/sudoers/pwutil.c:638
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "グループ %s をキャッシュできません。すでに存在します"
+
+#: plugins/sudoers/pwutil.c:900 plugins/sudoers/pwutil.c:985
+#: plugins/sudoers/pwutil.c:1039 plugins/sudoers/pwutil.c:1095
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "グループリスト %s をキャッシュできません。すでに存在します"
+
+#: plugins/sudoers/pwutil.c:906 plugins/sudoers/pwutil.c:990
+#: plugins/sudoers/pwutil.c:1045 plugins/sudoers/pwutil.c:1100
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "グループリスト %s をキャッシュできません"
+
+#: plugins/sudoers/pwutil.c:979
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "%s のグループを解析できません"
+
+#: plugins/sudoers/pwutil.c:1089
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "%s のグループIDを解析できません"
+
+#: plugins/sudoers/set_perms.c:120 plugins/sudoers/set_perms.c:457
+#: plugins/sudoers/set_perms.c:870 plugins/sudoers/set_perms.c:1186
+#: plugins/sudoers/set_perms.c:1490
+msgid "perm stack overflow"
+msgstr "perm スタックがオーバーフローしました"
+
+#: plugins/sudoers/set_perms.c:131 plugins/sudoers/set_perms.c:387
+#: plugins/sudoers/set_perms.c:468 plugins/sudoers/set_perms.c:736
+#: plugins/sudoers/set_perms.c:881 plugins/sudoers/set_perms.c:1109
+#: plugins/sudoers/set_perms.c:1197 plugins/sudoers/set_perms.c:1422
+#: plugins/sudoers/set_perms.c:1501 plugins/sudoers/set_perms.c:1592
+msgid "perm stack underflow"
+msgstr "perm スタックがアンダーフローしました"
+
+#: plugins/sudoers/set_perms.c:191 plugins/sudoers/set_perms.c:515
+#: plugins/sudoers/set_perms.c:1251 plugins/sudoers/set_perms.c:1535
+msgid "unable to change to root gid"
+msgstr "root のグループIDへ変更できません"
+
+#: plugins/sudoers/set_perms.c:282 plugins/sudoers/set_perms.c:612
+#: plugins/sudoers/set_perms.c:1013 plugins/sudoers/set_perms.c:1328
+msgid "unable to change to runas gid"
+msgstr "実行するためのグループIDに変更できません"
+
+#: plugins/sudoers/set_perms.c:287 plugins/sudoers/set_perms.c:617
+#: plugins/sudoers/set_perms.c:1018 plugins/sudoers/set_perms.c:1333
+msgid "unable to set runas group vector"
+msgstr "グループベクトルを実行するためのものに変更できません"
+
+#: plugins/sudoers/set_perms.c:298 plugins/sudoers/set_perms.c:628
+#: plugins/sudoers/set_perms.c:1027 plugins/sudoers/set_perms.c:1342
+msgid "unable to change to runas uid"
+msgstr "実行するためのユーザーIDに変更できません"
+
+#: plugins/sudoers/set_perms.c:320 plugins/sudoers/set_perms.c:650
+#: plugins/sudoers/set_perms.c:1047 plugins/sudoers/set_perms.c:1362
+msgid "unable to change to sudoers gid"
+msgstr "sudoers のグループIDへ変更できません"
+
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579
+msgid "too many processes"
+msgstr "プロセスが多すぎます"
+
+#: plugins/sudoers/solaris_audit.c:62
+msgid "unable to get current working directory"
+msgstr "カレントディレクトリを取得できません"
+
+#: plugins/sudoers/solaris_audit.c:70
+#, c-format
+msgid "truncated audit path ctx->user.cmnd: %s"
+msgstr "検証の対象とする長さを切り詰めました ctx->user.cmnd: %s"
+
+#: plugins/sudoers/solaris_audit.c:77
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "検証の対象とする長さを切り詰めました argv[0]: %s"
+
+#: plugins/sudoers/sssd.c:581
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "SSS のソースを初期化できません。SSSD はあなたのマシンにインストールされていますか?"
+
+#: plugins/sudoers/sssd.c:589 plugins/sudoers/sssd.c:598
+#: plugins/sudoers/sssd.c:607 plugins/sudoers/sssd.c:616
+#: plugins/sudoers/sssd.c:625
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "シンボル \"%s\" が %s 内にありません"
+
+#: plugins/sudoers/sudoers.c:250
+#, c-format
+msgid "unable to get defaults from %s"
+msgstr "%s から既定値を取得できません"
+
+#: plugins/sudoers/sudoers.c:259
+msgid "no valid sudoers sources found, quitting"
+msgstr "有効な sudoers のソースが見つかりません。終了します"
+
+#: plugins/sudoers/sudoers.c:366
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers の指定により root が sudo を使用することは禁止されています"
+
+#: plugins/sudoers/sudoers.c:375
+msgid "user not allowed to override closefrom limit"
+msgstr "ユーザーが closefrom 制限をオーバーライドすることは許されていません"
+
+#: plugins/sudoers/sudoers.c:376
+msgid "you are not permitted to use the -C option"
+msgstr "-C オプションを使用することは許可されていません"
+
+#: plugins/sudoers/sudoers.c:440
+msgid "no tty"
+msgstr "tty がありません"
+
+#: plugins/sudoers/sudoers.c:441
+msgid "sorry, you must have a tty to run sudo"
+msgstr "残念ですが、sudo を実行するには tty が必要です"
+
+#: plugins/sudoers/sudoers.c:449
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "ユーザー %s には無効な シェル: %s"
+
+#: plugins/sudoers/sudoers.c:491
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "ユーザーはルートディレクトリを %s に変更できません"
+
+#: plugins/sudoers/sudoers.c:493
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "-R オプションを %s と共に使用することは許可されていません"
+
+#: plugins/sudoers/sudoers.c:506
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "ユーザーはディレクトリを %s に変更できません"
+
+#: plugins/sudoers/sudoers.c:507
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "-D オプションを %s と共に使用することは許可されていません"
+
+#: plugins/sudoers/sudoers.c:542
+msgid "command in current directory"
+msgstr "コマンドがカレントディレクトリにあります"
+
+#: plugins/sudoers/sudoers.c:557
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr "\"cd\" はシェルの内蔵コマンドで、直接実行できません。"
+
+#: plugins/sudoers/sudoers.c:559
+msgid "the -s option may be used to run a privileged shell."
+msgstr "権限を昇格したシェルを実行するために -s オプションが使われることがあります。"
+
+#: plugins/sudoers/sudoers.c:561
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr "コマンドを実行するディレクトリを指定するために -D オプションを使うことができます。"
+
+#: plugins/sudoers/sudoers.c:570
+msgid "user not allowed to set a command timeout"
+msgstr "ユーザーはコマンド実行の制限時間を設定することを許可されていません"
+
+#: plugins/sudoers/sudoers.c:572
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "残念ですが、あなたはコマンド実行の制限時間を設定することを許可されていません"
+
+#: plugins/sudoers/sudoers.c:580
+msgid "user not allowed to preserve the environment"
+msgstr "ユーザーは環境変数を保存することを許可されていません"
+
+#: plugins/sudoers/sudoers.c:582
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "残念ですが、あなたは環境変数を保存することを許可されていません"
+
+#: plugins/sudoers/sudoers.c:618
+msgid "no command specified"
+msgstr "コマンドが指定されていません"
+
+#: plugins/sudoers/sudoers.c:759
+msgid "error setting user-specified environment variables"
+msgstr "ユーザーが指定した環境変数の設定でエラーです"
+
+#: plugins/sudoers/sudoers.c:1211
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "sudoedit の実行に sudo を使用する必要はありません"
+
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:1613
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "%s を読み込めません"
+
+#: plugins/sudoers/sudoers.c:1321 plugins/sudoers/visudo.c:1123
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s は通常ファイルではありません"
+
+#: plugins/sudoers/sudoers.c:1325 plugins/sudoers/timestamp.c:272 toke.l:1355
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s はユーザーID %u によって所有されています。これは %u であるべきです"
+
+#: plugins/sudoers/sudoers.c:1330 plugins/sudoers/timestamp.c:279 toke.l:1360
+#, c-format
+msgid "%s is world writable"
+msgstr "%s は誰でも書き込み可能です"
+
+#: plugins/sudoers/sudoers.c:1334 plugins/sudoers/timestamp.c:284 toke.l:1363
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s のグループIDは %u になっています。これは %u であるべきです"
+
+#: plugins/sudoers/sudoers.c:1363
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "root のみ \"-c %s\" を使用できます"
+
+#: plugins/sudoers/sudoers.c:1382
+#, c-format
+msgid "unknown login class %s"
+msgstr "不明なログインクラス %s"
+
+#: plugins/sudoers/sudoers_cb.c:120 plugins/sudoers/sudoers_cb.c:135
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "ホスト %s の名前解決ができません"
+
+#: plugins/sudoers/sudoreplay.c:252
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "無効なフィルターオプションです: %s"
+
+#: plugins/sudoers/sudoreplay.c:268
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "無効な最大待機時間です: %s"
+
+#: plugins/sudoers/sudoreplay.c:291
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "無効な speed_factor の値です: %s"
+
+#: plugins/sudoers/sudoreplay.c:326
+#, c-format
+msgid "invalid time offset %s"
+msgstr "無効な時間オフセット %s"
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:340
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/タイミング: %s"
+
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "再生する sudo セッション: %s"
+
+#: plugins/sudoers/sudoreplay.c:634
+msgid "unable to set tty to raw mode"
+msgstr "tty を raw モードに設定できません"
+
+#: plugins/sudoers/sudoreplay.c:685
+msgid "Warning: your terminal is too small to properly replay the log."
+msgstr "警告: ログをきちんとリプレイするには端末が小さすぎます。"
+
+#: plugins/sudoers/sudoreplay.c:686
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "ログの大きさは %d x %d で、端末の大きさは %d x %d です。"
+
+#: plugins/sudoers/sudoreplay.c:714
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "再生が終了しました、何かキーを押すと端末を回復します。"
+
+#: plugins/sudoers/sudoreplay.c:1217 plugins/sudoers/sudoreplay.c:1247
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "曖昧な式 \"%s です\""
+
+#: plugins/sudoers/sudoreplay.c:1269
+msgid "unmatched ')' in expression"
+msgstr "式内で ')' が不一致です"
+
+#: plugins/sudoers/sudoreplay.c:1273
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "不明な検索語 \"%s\" です"
+
+#: plugins/sudoers/sudoreplay.c:1288
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s は引数が必要です"
+
+#: plugins/sudoers/sudoreplay.c:1298
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "日付 \"%s\" を構文解析できませんでした"
+
+#: plugins/sudoers/sudoreplay.c:1307
+msgid "unmatched '(' in expression"
+msgstr "式内で '(' が不一致です"
+
+#: plugins/sudoers/sudoreplay.c:1309
+msgid "illegal trailing \"or\""
+msgstr "末尾に \"or\" を配置できません"
+
+#: plugins/sudoers/sudoreplay.c:1311
+msgid "illegal trailing \"!\""
+msgstr "末尾に \"!\" を配置できません"
+
+#: plugins/sudoers/sudoreplay.c:1417
+#, c-format
+msgid "unknown search type %d"
+msgstr "未知の検索タイプ %d"
+
+#: plugins/sudoers/sudoreplay.c:1679
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "使用法: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1681
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "使用法: %s [-h] [-d dir] -l [search expression]\n"
+
+#: plugins/sudoers/sudoreplay.c:1695
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - sudo セッションログをリプレイします\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1697
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"オプション:\n"
+" -d, --directory=dir セッションログのディレクトリを指定する\n"
+" -f, --filter=filter 表示する I/O タイプを指定する\n"
+" -h, --help ヘルプメッセージを表示して終了する\n"
+" -l, --list[=expr] 使用可能なセッションIDを一覧表示する、オプションで条件 expr を指定可能\n"
+" -m, --max-wait=num イベント間の待ち時間の最大秒数を指定する\n"
+" -n, --non-interactive プロンプトなしで、セッションは標準出力に送られます\n"
+" -R, --no-resize 端末の大きさを変更しようとしない\n"
+" -S, --suspend-wait コマンドがサスペンドされている間、待機する\n"
+" -s, --speed=num 出力速度を速くする、または遅くする\n"
+" -V, --version バージョン情報を表示して終了する"
+
+#: plugins/sudoers/testsudoers.c:392
+#, c-format
+msgid ""
+"\n"
+"Invalid shell for user %s: %s\n"
+msgstr ""
+"\n"
+"ユーザー %s には無効な シェル: %s\n"
+
+#: plugins/sudoers/testsudoers.c:411
+msgid ""
+"\n"
+"Password required"
+msgstr ""
+"\n"
+"パスワードが必要です"
+
+#: plugins/sudoers/testsudoers.c:422
+msgid ""
+"\n"
+"Parse error"
+msgstr ""
+"\n"
+"構文解析エラー"
+
+#: plugins/sudoers/testsudoers.c:425
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"コマンドが許可されました"
+
+#: plugins/sudoers/testsudoers.c:428
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"コマンドが拒否されました"
+
+#: plugins/sudoers/testsudoers.c:431
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"コマンドが一致しませんでした"
+
+#: plugins/sudoers/timestamp.c:364 plugins/sudoers/timestamp.c:711
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "タイムスタンプファイルを %lld バイトに切り詰めることができません"
+
+#: plugins/sudoers/timestamp.c:908
+msgid "ignoring time stamp from the future"
+msgstr "未来の時刻のタイムスタンプを無視します"
+
+#: plugins/sudoers/timestamp.c:931
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "タイムスタンプが遠すぎる将来になっています: %20.20s"
+
+#: plugins/sudoers/timestamp.c:1067
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "タイムスタンプファイル %s をロックすることができません"
+
+#: plugins/sudoers/timestamp.c:1114
+#, c-format
+msgid "%s:%d:%d timestampowner: unknown user %s"
+msgstr "%s:%d:%d: timestampowner: 未知のユーザー %s"
+
+#: plugins/sudoers/toke_util.c:159
+msgid "sudoedit should not be specified with a path"
+msgstr "sudoedit はパスなしで設定するべきです"
+
+#: plugins/sudoers/visudo.c:308 plugins/sudoers/visudo.c:714
+#, c-format
+msgid "press return to edit %s: "
+msgstr "%s を編集するためにリターンを押してください: "
+
+#: plugins/sudoers/visudo.c:323
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "編集セッションの内容が %s 内に残っています"
+
+#: plugins/sudoers/visudo.c:401
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "指定したエディター (%s) が存在しません"
+
+#: plugins/sudoers/visudo.c:406
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "エディターが見つかりません (エディターのパス = %s)"
+
+#: plugins/sudoers/visudo.c:494 plugins/sudoers/visudo.c:786
+#, c-format
+msgid "unable to stat %s"
+msgstr "%s の状態取得 (stat) ができません"
+
+#: plugins/sudoers/visudo.c:514 plugins/sudoers/visudo.c:522
+msgid "write error"
+msgstr "書き込みエラーです"
+
+#: plugins/sudoers/visudo.c:568
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "一時ファイル (%s) の状態取得 (stat) ができません。%s は変更されません"
+
+#: plugins/sudoers/visudo.c:575
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "一時ファイル (%s) の大きさが 0 です。%s は変更されません"
+
+#: plugins/sudoers/visudo.c:581
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "エディター (%s) が異常終了しました。%s は変更されません"
+
+#: plugins/sudoers/visudo.c:613
+#, c-format
+msgid "%s unchanged"
+msgstr "%s は変更されません"
+
+#: plugins/sudoers/visudo.c:661
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "一時ファイル (%s) を再度開くことができません。%s は変更されません。"
+
+#: plugins/sudoers/visudo.c:674
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "一時ファイル (%s) の構文解析ができません。不明なエラーです"
+
+#: plugins/sudoers/visudo.c:760 plugins/sudoers/visudo.c:790
+#: plugins/sudoers/visudo.c:797
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "%s の (ユーザーID, グループID) を (%u, %u) に設定できません"
+
+#: plugins/sudoers/visudo.c:825
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s と %s は同じファイルシステム上にありません。名前を変更するために mv を使用しています"
+
+#: plugins/sudoers/visudo.c:836
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "コマンドの失敗です: '%s %s %s'。%s は変更されません"
+
+#: plugins/sudoers/visudo.c:843
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "%s の名前変更に失敗しました。%s は変更されません"
+
+#: plugins/sudoers/visudo.c:864
+msgid "What now? "
+msgstr "次は何でしょうか? "
+
+#: plugins/sudoers/visudo.c:878
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"オプション:\n"
+" e -- sudoers ファイルを再度編集します\n"
+" x -- sudoers ファイルへの変更を保存せずに終了します\n"
+" Q -- sudoers ファイルへの変更を保存して終了します (*危険です!*)\n"
+
+#: plugins/sudoers/visudo.c:923
+#, c-format
+msgid "unable to run %s"
+msgstr "%s を実行できません"
+
+#: plugins/sudoers/visudo.c:954
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: 所有権に誤りがあります。(ユーザーID, グループID) は (%u, %u) であるべきです\n"
+
+#: plugins/sudoers/visudo.c:965
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: アクセス権限に誤りがあります。モードは 0%o であるべきです\n"
+
+#: plugins/sudoers/visudo.c:1017 plugins/sudoers/visudo.c:1024
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: 正しく構文解析されました\n"
+
+#: plugins/sudoers/visudo.c:1043
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s がビジー状態です。後で再試行してください"
+
+#: plugins/sudoers/visudo.c:1047
+msgid "Edit anyway? [y/N]"
+msgstr "それでも編集しますか? [y/N]"
+
+#: plugins/sudoers/visudo.c:1206
+msgid "the -x option will be removed in a future release"
+msgstr "-x オプションは将来のリリースでは削除されます"
+
+#: plugins/sudoers/visudo.c:1208
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "cvtsudoers ユーティリティーを代わりに使用することを検討してください"
+
+#: plugins/sudoers/visudo.c:1228
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "警告: %s:%d:%d: エイリアス %s \"%s\" は使用されていません"
+
+#: plugins/sudoers/visudo.c:1341
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - sudoers ファイルを安全に編集する\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1343
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -I, --no-includes do not edit include files\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"オプション:\n"
+" -c, --check 検査のみを行う\n"
+" -f, --file=sudoers sudoers ファイルの位置を指定する\n"
+" -h, --help ヘルプメッセージを表示して終了する\n"
+" -I, --no-includes include ファイルを編集しない\n"
+" -q, --quiet 文法エラーメッセージをより少なく (静かに) する\n"
+" -s, --strict 厳密な文法検査を行う\n"
+" -V, --version バージョン情報を表示して終了する\n"
+
+#: toke.l:184
+msgid "empty string"
+msgstr "空の文字列"
+
+#: toke.l:196 toke.l:566
+msgid "empty group"
+msgstr "空のグループ"
+
+#: toke.l:206 toke.l:564
+msgid "empty netgroup"
+msgstr "空のネットグループ"
+
+#: toke.l:284
+msgid "unterminated regular expression"
+msgstr "途中で終わっている正規表現"
+
+#: toke.l:358 toke.l:370 toke.l:382 toke.l:398 toke.l:417 toke.l:457
+msgid "invalid line continuation"
+msgstr "無効な行の継続"
+
+#: toke.l:603 toke.l:615
+msgid "invalid IPv6 address"
+msgstr "無効な IPv6 アドレス"
+
+#: toke.l:863
+msgid "unexpected line break in string"
+msgstr "文字列の予期せぬところに改行"
+
+#: toke.l:982
+msgid "ignoring editor backup file"
+msgstr "エディターのバックアップファイルを無視します"
+
+#: toke.l:985
+msgid "ignoring file name containing '.'"
+msgstr "'.' を含むファイル名を無視します"
+
+#: toke.l:1310
+msgid "too many levels of includes"
+msgstr "インクルードの階層が大きすぎます"
+
+#~ msgid "\thost unmatched"
+#~ msgstr "\tホストが一致しません"
+
+#~ msgid "timestamp owner (%s): No such user"
+#~ msgstr "タイムスタンプの所有者 (%s): そのようなユーザーはありません"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s の所有者は uid %d でなければいけません"
+
+#~ msgid "%s must only be writable by owner"
+#~ msgstr "%s は所有者のみ書き込み可能でなければいけません"
+
+#~ msgid "%s is group writable"
+#~ msgstr "%s はグループのメンバーによる書き込みが可能です"
+
+#~ msgid "lecture status path too long: %s/%s"
+#~ msgstr "受講状況格納パスが長すぎます: %s/%s"
+
+#~ msgid "Error: %s:%d:%d: cycle in %s \"%s\""
+#~ msgstr "エラー: %s:%d:%d: %s \"%s\" でエイリアス定義が循環しています"
+
+#~ msgid "Warning: %s:%d:%d: cycle in %s \"%s\""
+#~ msgstr "警告: %s:%d:%d: %s \"%s\" でエイリアス定義が循環しています"
+
+#~ msgid "Warning: %s:%d:%d: %s \"%s\" referenced but not defined"
+#~ msgstr "警告: %s:%d:%d: %s \"%s\" は参照されているのに定義されていません"
+
+#~ msgid "parse error in %s near line %d\n"
+#~ msgstr "%s 内 %d 行付近で構文解析エラーが発生しました\n"
+
+#~ msgid "parse error in %s\n"
+#~ msgstr "%s 内で構文解析エラーが発生しました\n"
+
+#~ msgid "%s: unknown defaults entry \"%s\""
+#~ msgstr "%s: 未知のデフォルト項目 \"%s\" です"
+
+#~ msgid "%s:%d:%d: no value specified for \"%s\""
+#~ msgstr "%s:%d:%d: \"%s\" に値が指定されていません"
+
+#~ msgid "%s:%d:%d: invalid operator \"%c=\" for \"%s\""
+#~ msgstr "%s:%d:%d: \"%c=\" は \"%s\" には無効な演算子です"
+
+#~ msgid "%s:%d:%d: option \"%s\" does not take a value"
+#~ msgstr "%s:%d:%d: オプション \"%s\" は値をとりません"
+
+#~ msgid "%s:%d:%d: invalid Defaults type 0x%x for option \"%s\""
+#~ msgstr "%s:%d:%d: 0x%x はオプション \"%s\" のデフォルトタイプとして無効です"
+
+#~ msgid "%s:%d:%d: value \"%s\" is invalid for option \"%s\""
+#~ msgstr "%s:%d:%d: \"%s\" はオプション \"%s\" の値としては無効です"
+
+#~ msgid "%s:%d:%d: path name for \"%s\" too long"
+#~ msgstr "%s:%d:%d: \"%s\" のパス名が長すぎます"
+
+#~ msgid "%s: path name for \"%s\" too long"
+#~ msgstr "%s: \"%s\" のパス名が長すぎます"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/', '~', or '*'"
+#~ msgstr "%s:%d:%d: \"%s\" の値は '/', '~', または '*' で開始しなければいけません"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/'"
+#~ msgstr "%s:%d:%d: \"%s\" の値は '/' で開始しなければいけません"
+
+#~ msgid "parse error in %s near line %d"
+#~ msgstr "%s 内 %d 行付近で構文解析エラーが発生しました"
+
+#~ msgid "parse error in %s"
+#~ msgstr "%s 内で構文解析エラーが発生しました"
+
+#~ msgid "SELinux RBAC is not supported when intercept mode is enabled"
+#~ msgstr "SELinux RBAC はインターセプトモードが有効になっているときにはサポートされません"
+
+#~ msgid "SELinux RBAC is not supported when the log_subcmds flag is enabled"
+#~ msgstr "SELinux RBAC はlog_subcmds フラグが有効になっているときにはサポートされません"
+
+#~ msgid "problem with defaults entries"
+#~ msgstr "デフォルト項目で問題が発生しました"
+
+#~ msgid "internal error, unable to find %s in list!"
+#~ msgstr "内部エラー、リスト内に %s が見つかりません!"
+
+#~ msgid "%s is not in the sudoers file. This incident will be reported.\n"
+#~ msgstr "%s は sudoers ファイル内にありません。この事象は記録・報告されます。\n"
+
+#~ msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+#~ msgstr "%s は %s 上で sudo を実行することを許可されていません。この事象は記録・報告されます。\n"
+
+#~ msgid "%s: write buffer already in use"
+#~ msgstr "%s: 書き込みバッファは使用中です"
+
+#~ msgid "unable to read diffie-hellman parameters: %s"
+#~ msgstr "ディフィー・ヘルマン パラメーターを読み込めません: %s"
+
+#~ msgid "%s:%d unknown key: %s"
+#~ msgstr "%s:%d 未知の鍵: %s"
+
+#~ msgid "unable to get TLS server method: %s"
+#~ msgstr "TLS サーバーメソッドを取得できません: %s"
+
+#~ msgid "%s:%u unable to parse \"%s\""
+#~ msgstr "%s:%u \"%s\" を構文解析できません"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " -f, --file path to configuration file\n"
+#~ " -h --help display help message and exit\n"
+#~ " -n, --no-fork do not fork, run in the foreground\n"
+#~ " -R, --random-drop percent chance connections will drop\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "オプション:\n"
+#~ " -f, --file=sudoers sudoers ファイルの位置を指定する\n"
+#~ " -h, --help ヘルプメッセージを表示して終了する\n"
+#~ " -n, --no-fork フォークせずに、フォアグラウンドで実行する\n"
+#~ " -R, --random-drop 接続がドロップする確率(%)\n"
+#~ " -V, --version バージョン情報を表示して終了する\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " --help display help message and exit\n"
+#~ " -A, --accept only send an accept event (no I/O)\n"
+#~ " -h, --host host to send logs to\n"
+#~ " -i, --iolog_id remote ID of I/O log to be resumed\n"
+#~ " -p, --port port to use when connecting to host\n"
+#~ " -r, --restart restart previous I/O log transfer\n"
+#~ " -R, --reject reject the command with the given reason\n"
+#~ " -b, --ca-bundle certificate bundle file to verify server's cert against\n"
+#~ " -c, --cert certificate file for TLS handshake\n"
+#~ " -k, --key private key file\n"
+#~ " -n, --no-verify do not verify server certificate\n"
+#~ " -t, --test test audit server by sending selected I/O log n times in parallel\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "オプション:\n"
+#~ " --help ヘルプメッセージを表示して終了する\n"
+#~ " -A, --accept 受け取りイベントのみを送る (I/O なし)\n"
+#~ " -h, --host ログの送り先とするホスト\n"
+#~ " -i, --iolog_id 復元するI/O ログのリモート ID \n"
+#~ " -p, --port ホストに接続するのに使用するポート\n"
+#~ " -r, --restart 以前の I/O ログ転送を再開する\n"
+#~ " -R, --reject 与えられた理由によりコマンドを拒否する\n"
+#~ " -b, --ca-bundle サーバーの証明書を検証するために突き合わせる証明書バンドルファイル\n"
+#~ " -c, --cert TLSハンドシェイクのための証明書ファイル\n"
+#~ " -k, --key 秘密鍵ファイル\n"
+#~ " -n, --no-verify サーバーの証明書を検証しない\n"
+#~ " -t, --test 選んだ I/O ログを n 重に並列送信することで監査サーバーを試験する\n"
+#~ " -V, --version バージョン情報を表示して終了する\n"
+
+#~ msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+#~ msgstr "sudo_noexec ライブラリに含まれるダミーの exec 関数群を事前ロードします"
+
+#~ msgid "sudo_ldap_conf_add_ports: port too large"
+#~ msgstr "sudo_ldap_conf_add_ports: ポートが大きすぎます"
+
+#~ msgid "No user or host"
+#~ msgstr "ユーザーまたはホストがありません"
+
+#~ msgid "validation failure"
+#~ msgstr "検証に失敗しました"
+
+#~ msgid "audit_failure message too long"
+#~ msgstr "audit_failure のメッセージが長すぎます"
+
+#~ msgid "%s/%s/timing: %s"
+#~ msgstr "%s/%s/タイミング: %s"
+
+#~ msgid "ignoring invalid attribute value: %s"
+#~ msgstr "無効な属性値を無視します: %s"
+
+#~ msgid "unable to cache user %s, out of memory"
+#~ msgstr "ユーザー %s をキャッシュできません。メモリ不足です。"
+
+#~ msgid "unable to cache group %s, out of memory"
+#~ msgstr "グループ %s をキャッシュできません。メモリ不足です。"
+
+#~ msgid "unable to cache group list for %s, out of memory"
+#~ msgstr "グループリスト %s をキャッシュできません。メモリ不足です。"
+
+#~ msgid ""
+#~ "\n"
+#~ "LDAP Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "LDAP 役割: 不明\n"
+
+#~ msgid " Order: %s\n"
+#~ msgstr " Order: %s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: %s\n"
+#~ msgstr ""
+#~ "\n"
+#~ "SSSD 役割: %s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "SSSD 役割: 不明\n"
+
+#~ msgid "Warning: unused %s `%s'"
+#~ msgstr "警告: 使われていません %s `%s'"
+
+#~ msgid "timestamp path too long: %s/%s"
+#~ msgstr "タイムスタンプのパスが長過ぎます: %s/%s"
+
+#~ msgid "unable to stat editor (%s)"
+#~ msgstr "エディター (%s) の状態取得 (stat) ができません"
+
+#~ msgid ">>> %s: %s near line %d <<<"
+#~ msgstr ">>> %s: %s (%d行付近) <<<"
+
+#~ msgid "pam_chauthtok: %s"
+#~ msgstr "pam_chauthtok: %s"
+
+#~ msgid "pam_authenticate: %s"
+#~ msgstr "pam_authenticate: %s"
+
+#~ msgid "Password:"
+#~ msgstr "パスワード:"
+
+#~ msgid "getaudit: failed"
+#~ msgstr "getaudit: 失敗しました"
+
+#~ msgid "getauid failed"
+#~ msgstr "getauid に失敗しました"
+
+#~ msgid "au_to_subject: failed"
+#~ msgstr "au_to_subject: 失敗しました"
+
+#~ msgid "au_to_exec_args: failed"
+#~ msgstr "au_to_exec_args: 失敗しました"
+
+#~ msgid "au_to_return32: failed"
+#~ msgstr "au_to_return32: 失敗しました"
+
+#~ msgid "getauid: failed"
+#~ msgstr "getauid: 失敗しました"
+
+#~ msgid "au_to_text: failed"
+#~ msgstr "au_to_text: 失敗しました"
+
+#~ msgid "%s owned by uid %u, should be uid %u"
+#~ msgstr "%s はユーザーID (uid) %u によって所有されています。これはユーザーID %u であるべきです"
+
+#~ msgid "%s writable by non-owner (0%o), should be mode 0700"
+#~ msgstr "%s は所有者以外でも書き込み可能 (0%o) です。アクセス権限のモードは 0700 であるべきです"
+
+#~ msgid "%s exists but is not a regular file (0%o)"
+#~ msgstr "%s が存在しますが通常ファイル (0%o) ではありません"
+
+#~ msgid "%s writable by non-owner (0%o), should be mode 0600"
+#~ msgstr "%s は所有者以外でも書き込み可能 (0%o) です。アクセス権限のモードは 0600 であるべきです"
+
+#~ msgid "unable to remove %s (%s), will reset to the epoch"
+#~ msgstr "%s (%s) を削除できません。エポックにリセットします"
+
+#~ msgid "unable to set locale to \"%s\", using \"C\""
+#~ msgstr "ロケールを \"%s\" に設定できません。 \"C\" を使用します"
+
+#~ msgid "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+#~ msgstr "sudo_ldap_conf_add_ports: hostbuf を拡張中にメモリ空間が不足しました"
+
+#~ msgid "unable to mix ldaps and starttls"
+#~ msgstr "ldaps と starttls を混ぜて使用できません"
+
+#~ msgid "sudo_ldap_parse_uri: out of space building hostbuf"
+#~ msgstr "sudo_ldap_parse_uri: hostbuf を構築中にメモリ空間が不足しました"
+
+#~ msgid "sudo_ldap_build_pass1 allocation mismatch"
+#~ msgstr "sudo_ldap_build_pass1 配置が一致しません"
+
+#~ msgid "internal error: insufficient space for log line"
+#~ msgstr "内部エラー: ログの行に十分な空間がありません"
+
+#~ msgid ""
+#~ " Commands:\n"
+#~ "\t"
+#~ msgstr ""
+#~ " コマンド:\n"
+#~ "\t"
+
+#~ msgid ": "
+#~ msgstr ": "
+
+#~ msgid "unable to cache uid %u (%s), already exists"
+#~ msgstr "ユーザーID %u (%s) をキャッシュできません。すでに存在します"
+
+#~ msgid "unable to cache gid %u (%s), already exists"
+#~ msgstr "グループID %u (%s) をキャッシュできません。すでに存在します"
+
+#~ msgid "Unable to dlopen %s: %s"
+#~ msgstr "dlopen %s を行うことができません: %s"
+
+#~ msgid "writing to standard output"
+#~ msgstr "標準出力に書き込んでいます"
+
+#~ msgid "nanosleep: tv_sec %ld, tv_nsec %ld"
+#~ msgstr "nanosleep: tv_sec %ld, tv_nsec %ld"
+
+#~ msgid "too many parenthesized expressions, max %d"
+#~ msgstr "式内の小括弧のくくりが多すぎます。最大は %d です。"
+
+#~ msgid "fill_args: buffer overflow"
+#~ msgstr "fill_args: バッファオーバーフローが発生しました"
+
+#~ msgid "internal error, expand_prompt() overflow"
+#~ msgstr "内部エラー、expand_prompt() がオーバーフローしました"
+
+#~ msgid "internal error, sudo_setenv2() overflow"
+#~ msgstr "内部エラー、 sudo_setenv2() がオーバーフローしました"
+
+#~ msgid "internal error, sudo_setenv() overflow"
+#~ msgstr "内部エラー、 sudo_setenv() がオーバーフローしました"
+
+#~ msgid "internal error, linux_audit_command() overflow"
+#~ msgstr "内部エラー、linux_audit_command() がオーバーフローしました"
+
+#~ msgid "internal error, runas_groups overflow"
+#~ msgstr "内部エラー、runas_groups がオーバーフローしました"
+
+#~ msgid "internal error, init_vars() overflow"
+#~ msgstr "内部エラー、init_vars() がオーバーフローしました"
+
+#~ msgid "fixed mode on %s"
+#~ msgstr "%s のアクセス権限のモードを修正しました"
+
+#~ msgid "unable to fix mode on %s"
+#~ msgstr "%s のアクセス権限のモードを修正できません"
+
+#~ msgid "%s is mode 0%o, should be 0%o"
+#~ msgstr "%s のアクセス権限のモードは 0%o です。これは 0%o であるべきです"
+
+#~ msgid "File containing dummy exec functions: %s"
+#~ msgstr "偽の exec 関数が含まれるファイル: %s"
+
+#~ msgid "Unable to allocate ssl object: %s\n"
+#~ msgstr "SSLオブジェクトを割り当てることができません: %s\n"
+
+#~ msgid "client message too large: %zu\n"
+#~ msgstr "クライアントメッセージが大き過ぎます: %zu\n"
+
+#, fuzzy
+#~| msgid "Send mail if the user is not in sudoers"
+#~ msgid "CA bundle file is not set in sudoers"
+#~ msgstr "ユーザー他 sudoers 内に存在しない場合にメールを送信します"
+
+#, fuzzy
+#~| msgid "Send mail if the user is not in sudoers"
+#~ msgid "Signed certificate file is not set in sudoers"
+#~ msgstr "ユーザー他 sudoers 内に存在しない場合にメールを送信します"
+
+#~ msgid "unknown address family: %d"
+#~ msgstr "未知のアドレスファミリー: %d"
diff --git a/plugins/sudoers/po/ka.mo b/plugins/sudoers/po/ka.mo
new file mode 100644
index 0000000..e163be7
--- /dev/null
+++ b/plugins/sudoers/po/ka.mo
Binary files differ
diff --git a/plugins/sudoers/po/ka.po b/plugins/sudoers/po/ka.po
new file mode 100644
index 0000000..cc3fa09
--- /dev/null
+++ b/plugins/sudoers/po/ka.po
@@ -0,0 +1,3715 @@
+# Portable object template file for the sudoers plugin
+# This file is put in the public domain.
+# Todd C. Miller <Todd.Miller@sudo.ws>, 2011-2018
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.9.12b2\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2022-10-10 09:13-0600\n"
+"PO-Revision-Date: 2022-11-19 07:22+0100\n"
+"Last-Translator: Temuri Doghonadze <temuri.doghonadze@gmail.com>\n"
+"Language-Team: Georgian <(nothing)>\n"
+"Language: ka\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 3.2\n"
+
+#: confstr.sh:1 gram.y:1220 plugins/sudoers/logging.c:862
+msgid "syntax error"
+msgstr "სინტაქსური შეცდომა"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "%p-ის პაროლი: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] პაროლი %p-სთვის: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "პაროლი: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** უსაფრთხოების ინფორმაცია %h -სთვის***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "თავიდან სცადეთ."
+
+#: gram.y:237 gram.y:304 gram.y:313 gram.y:322 gram.y:332 gram.y:342
+#: gram.y:366 gram.y:393 gram.y:402 gram.y:410 gram.y:419 gram.y:428
+#: gram.y:502 gram.y:512 gram.y:524 gram.y:572 gram.y:581 gram.y:590
+#: gram.y:599 gram.y:731 gram.y:739 gram.y:750 gram.y:762 gram.y:781
+#: gram.y:944 gram.y:949 gram.y:957 gram.y:971 gram.y:977 gram.y:1099
+#: gram.y:1108 gram.y:1116 gram.y:1125 gram.y:1134 gram.y:1163 gram.y:1172
+#: gram.y:1180 gram.y:1280 gram.y:1410 gram.y:1777 gram.y:1827
+#: lib/eventlog/eventlog.c:309 lib/eventlog/eventlog.c:382
+#: lib/eventlog/eventlog.c:827 lib/eventlog/eventlog.c:904
+#: lib/eventlog/eventlog.c:1204 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_json.c:150 lib/iolog/iolog_json.c:382
+#: lib/iolog/iolog_json.c:412 lib/iolog/iolog_json.c:555
+#: lib/iolog/iolog_legacy.c:100 lib/iolog/iolog_legacy.c:111
+#: lib/iolog/iolog_legacy.c:123 lib/iolog/iolog_legacy.c:133
+#: lib/iolog/iolog_legacy.c:139 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:182 logsrvd/iolog_writer.c:215
+#: logsrvd/iolog_writer.c:225 logsrvd/iolog_writer.c:254
+#: logsrvd/iolog_writer.c:275 logsrvd/iolog_writer.c:287
+#: logsrvd/iolog_writer.c:297 logsrvd/iolog_writer.c:307
+#: logsrvd/iolog_writer.c:317 logsrvd/iolog_writer.c:329
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:370
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:567 logsrvd/logsrv_util.c:69 logsrvd/logsrvd.c:301
+#: logsrvd/logsrvd.c:310 logsrvd/logsrvd.c:1050 logsrvd/logsrvd.c:1113
+#: logsrvd/logsrvd.c:1582 logsrvd/logsrvd.c:1587 logsrvd/logsrvd.c:1771
+#: logsrvd/logsrvd.c:1988 logsrvd/logsrvd_conf.c:357
+#: logsrvd/logsrvd_conf.c:370 logsrvd/logsrvd_conf.c:511
+#: logsrvd/logsrvd_conf.c:534 logsrvd/logsrvd_conf.c:538
+#: logsrvd/logsrvd_conf.c:556 logsrvd/logsrvd_conf.c:626
+#: logsrvd/logsrvd_conf.c:650 logsrvd/logsrvd_conf.c:678
+#: logsrvd/logsrvd_conf.c:692 logsrvd/logsrvd_conf.c:706
+#: logsrvd/logsrvd_conf.c:720 logsrvd/logsrvd_conf.c:734
+#: logsrvd/logsrvd_conf.c:748 logsrvd/logsrvd_conf.c:829
+#: logsrvd/logsrvd_conf.c:1036 logsrvd/logsrvd_conf.c:1053
+#: logsrvd/logsrvd_conf.c:1448 logsrvd/logsrvd_conf.c:1595
+#: logsrvd/logsrvd_conf.c:1621 logsrvd/logsrvd_conf.c:1633
+#: logsrvd/logsrvd_conf.c:1640 logsrvd/logsrvd_conf.c:1646
+#: logsrvd/logsrvd_conf.c:1743 logsrvd/logsrvd_journal.c:75
+#: logsrvd/logsrvd_journal.c:213 logsrvd/logsrvd_journal.c:214
+#: logsrvd/logsrvd_journal.c:270 logsrvd/logsrvd_journal.c:430
+#: logsrvd/logsrvd_journal.c:432 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:216 logsrvd/logsrvd_local.c:278
+#: logsrvd/logsrvd_local.c:279 logsrvd/logsrvd_local.c:417
+#: logsrvd/logsrvd_local.c:466 logsrvd/logsrvd_local.c:467
+#: logsrvd/logsrvd_local.c:472 logsrvd/logsrvd_local.c:473
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/logsrvd_relay.c:444
+#: logsrvd/logsrvd_relay.c:743 logsrvd/logsrvd_relay.c:850
+#: logsrvd/sendlog.c:251 logsrvd/sendlog.c:260 logsrvd/sendlog.c:291
+#: logsrvd/sendlog.c:338 logsrvd/sendlog.c:615 logsrvd/sendlog.c:1801
+#: plugins/sudoers/audit.c:116 plugins/sudoers/auth/bsdauth.c:150
+#: plugins/sudoers/auth/kerb5.c:121 plugins/sudoers/auth/kerb5.c:148
+#: plugins/sudoers/auth/pam.c:687 plugins/sudoers/auth/rfc1938.c:111
+#: plugins/sudoers/auth/sia.c:59 plugins/sudoers/check_aliases.c:168
+#: plugins/sudoers/cvtsudoers.c:131 plugins/sudoers/cvtsudoers.c:175
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:203
+#: plugins/sudoers/cvtsudoers.c:333 plugins/sudoers/cvtsudoers.c:372
+#: plugins/sudoers/cvtsudoers.c:392 plugins/sudoers/cvtsudoers.c:537
+#: plugins/sudoers/cvtsudoers.c:670 plugins/sudoers/cvtsudoers.c:688
+#: plugins/sudoers/cvtsudoers.c:862 plugins/sudoers/cvtsudoers.c:870
+#: plugins/sudoers/cvtsudoers.c:1365 plugins/sudoers/cvtsudoers.c:1369
+#: plugins/sudoers/cvtsudoers.c:1471 plugins/sudoers/cvtsudoers_csv.c:183
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:76
+#: plugins/sudoers/cvtsudoers_ldif.c:151 plugins/sudoers/cvtsudoers_ldif.c:194
+#: plugins/sudoers/cvtsudoers_ldif.c:235 plugins/sudoers/cvtsudoers_ldif.c:300
+#: plugins/sudoers/cvtsudoers_ldif.c:376 plugins/sudoers/cvtsudoers_ldif.c:430
+#: plugins/sudoers/cvtsudoers_ldif.c:438 plugins/sudoers/cvtsudoers_ldif.c:449
+#: plugins/sudoers/cvtsudoers_ldif.c:456 plugins/sudoers/cvtsudoers_ldif.c:468
+#: plugins/sudoers/cvtsudoers_ldif.c:481 plugins/sudoers/cvtsudoers_ldif.c:489
+#: plugins/sudoers/cvtsudoers_ldif.c:636 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1158
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:434
+#: plugins/sudoers/defaults.c:658 plugins/sudoers/defaults.c:1019
+#: plugins/sudoers/defaults.c:1187 plugins/sudoers/editor.c:188
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:54 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:228
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:668 plugins/sudoers/iolog.c:694
+#: plugins/sudoers/ldap.c:184 plugins/sudoers/ldap.c:464
+#: plugins/sudoers/ldap.c:755 plugins/sudoers/ldap.c:919
+#: plugins/sudoers/ldap.c:1335 plugins/sudoers/ldap.c:1761
+#: plugins/sudoers/ldap.c:1798 plugins/sudoers/ldap.c:1879
+#: plugins/sudoers/ldap.c:2014 plugins/sudoers/ldap.c:2115
+#: plugins/sudoers/ldap.c:2131 plugins/sudoers/ldap_conf.c:218
+#: plugins/sudoers/ldap_conf.c:250 plugins/sudoers/ldap_conf.c:302
+#: plugins/sudoers/ldap_conf.c:338 plugins/sudoers/ldap_conf.c:444
+#: plugins/sudoers/ldap_conf.c:459 plugins/sudoers/ldap_conf.c:564
+#: plugins/sudoers/ldap_conf.c:597 plugins/sudoers/ldap_conf.c:689
+#: plugins/sudoers/ldap_conf.c:771 plugins/sudoers/ldap_util.c:294
+#: plugins/sudoers/ldap_util.c:301 plugins/sudoers/ldap_util.c:614
+#: plugins/sudoers/linux_audit.c:86 plugins/sudoers/log_client.c:117
+#: plugins/sudoers/log_client.c:402 plugins/sudoers/log_client.c:715
+#: plugins/sudoers/log_client.c:736 plugins/sudoers/log_client.c:1416
+#: plugins/sudoers/log_client.c:1537 plugins/sudoers/log_client.c:1637
+#: plugins/sudoers/log_client.c:1973 plugins/sudoers/log_client.c:2032
+#: plugins/sudoers/logging.c:110 plugins/sudoers/logging.c:189
+#: plugins/sudoers/logging.c:453 plugins/sudoers/logging.c:668
+#: plugins/sudoers/logging.c:805 plugins/sudoers/match_command.c:335
+#: plugins/sudoers/match_command.c:603 plugins/sudoers/match_command.c:654
+#: plugins/sudoers/match_command.c:728 plugins/sudoers/match_command.c:776
+#: plugins/sudoers/match_digest.c:93 plugins/sudoers/parse.c:227
+#: plugins/sudoers/parse.c:244 plugins/sudoers/parse.c:263
+#: plugins/sudoers/parse.c:282 plugins/sudoers/parse.c:299
+#: plugins/sudoers/parse.c:322 plugins/sudoers/parse.c:333
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:598
+#: plugins/sudoers/parse_ldif.c:628 plugins/sudoers/parse_ldif.c:653
+#: plugins/sudoers/parse_ldif.c:711 plugins/sudoers/parse_ldif.c:728
+#: plugins/sudoers/parse_ldif.c:756 plugins/sudoers/parse_ldif.c:763
+#: plugins/sudoers/policy.c:624 plugins/sudoers/policy.c:1026
+#: plugins/sudoers/prompt.c:93 plugins/sudoers/pwutil.c:199
+#: plugins/sudoers/pwutil.c:270 plugins/sudoers/pwutil.c:348
+#: plugins/sudoers/pwutil.c:522 plugins/sudoers/pwutil.c:587
+#: plugins/sudoers/pwutil.c:659 plugins/sudoers/pwutil.c:857
+#: plugins/sudoers/pwutil.c:913 plugins/sudoers/pwutil.c:957
+#: plugins/sudoers/pwutil.c:1014 plugins/sudoers/sssd.c:145
+#: plugins/sudoers/sssd.c:185 plugins/sudoers/sssd.c:414
+#: plugins/sudoers/sssd.c:479 plugins/sudoers/sssd.c:505
+#: plugins/sudoers/sssd.c:568 plugins/sudoers/sssd.c:761
+#: plugins/sudoers/strvec_join.c:53 plugins/sudoers/stubs.c:112
+#: plugins/sudoers/stubs.c:120 plugins/sudoers/sudoers.c:354
+#: plugins/sudoers/sudoers.c:380 plugins/sudoers/sudoers.c:448
+#: plugins/sudoers/sudoers.c:457 plugins/sudoers/sudoers.c:498
+#: plugins/sudoers/sudoers.c:827 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:1015 plugins/sudoers/sudoers.c:1075
+#: plugins/sudoers/sudoers.c:1330 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:565 plugins/sudoers/sudoreplay.c:1281
+#: plugins/sudoers/sudoreplay.c:1503 plugins/sudoers/sudoreplay.c:1507
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:224
+#: plugins/sudoers/testsudoers.c:241 plugins/sudoers/testsudoers.c:588
+#: plugins/sudoers/timestamp.c:451 plugins/sudoers/timestamp.c:495
+#: plugins/sudoers/timestamp.c:1017 plugins/sudoers/timestamp.c:1146
+#: plugins/sudoers/toke_util.c:78 plugins/sudoers/toke_util.c:106
+#: plugins/sudoers/toke_util.c:131 plugins/sudoers/toke_util.c:161
+#: plugins/sudoers/toke_util.c:200 plugins/sudoers/tsdump.c:123
+#: plugins/sudoers/visudo.c:150 plugins/sudoers/visudo.c:385
+#: plugins/sudoers/visudo.c:391 plugins/sudoers/visudo.c:498
+#: plugins/sudoers/visudo.c:1054 toke.l:1023 toke.l:1155 toke.l:1226
+msgid "unable to allocate memory"
+msgstr "მეხსიერების გამოყოფის შეცდომა"
+
+#: gram.y:623
+msgid "a digest requires a path name"
+msgstr "დაიჯესტისთვის ბილიკის სახელი აუცილებელია"
+
+#: gram.y:645
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "\"CWD\" -ის მნიშვნელობები '/'-ით, '~'-ით ან '*'-ით უნდა იწყებოდეს"
+
+#: gram.y:651
+msgid "\"CWD\" path too long"
+msgstr "\"CWD\" -ის ბილიკი ძალიან გრძელია"
+
+#: gram.y:661
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr ""
+
+#: gram.y:667
+msgid "\"CHROOT\" path too long"
+msgstr "\"CHROOT\" -ის ბილიკი მეტისმეტად გრძელია"
+
+#: gram.y:802
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "სინტაქსის შეცდომა, დაჯავშნილი სიტყვა %s მეტსახელადაა გამოყენებული"
+
+#: gram.y:825
+msgid "invalid notbefore value"
+msgstr "notbefore -ის არასწორი მნიშვნელობა"
+
+#: gram.y:834
+msgid "invalid notafter value"
+msgstr "notafter -ის არასწორი მნიშვნელობა"
+
+#: gram.y:844 plugins/sudoers/policy.c:383
+msgid "timeout value too large"
+msgstr "მოლოდინის დროის მნიშვნელობა ძალიან დიდია"
+
+#: gram.y:846 plugins/sudoers/policy.c:385
+msgid "invalid timeout value"
+msgstr "მოლოდინის დროის არასწორი მნიშვნელობა"
+
+#: gram.y:967 plugins/sudoers/sudoers.c:1033
+msgid "command too long"
+msgstr "ბრძანება ძალიან გრძელია"
+
+#: gram.y:1224 plugins/sudoers/check_aliases.c:96
+#: plugins/sudoers/defaults.c:1276
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: gram.y:1278
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "მეტსახელი \"%s\" უკვე აღწერილია"
+
+#: gram.y:1777 gram.y:1827 lib/eventlog/eventlog.c:309
+#: lib/eventlog/eventlog.c:827 lib/eventlog/eventlog.c:900
+#: lib/eventlog/eventlog.c:903 lib/eventlog/eventlog.c:1204
+#: lib/iolog/iolog_filter.c:142 lib/iolog/iolog_filter.c:202
+#: lib/iolog/iolog_filter.c:232 lib/iolog/iolog_json.c:150
+#: lib/iolog/iolog_json.c:381 lib/iolog/iolog_json.c:412
+#: lib/iolog/iolog_json.c:555 lib/iolog/iolog_legacy.c:100
+#: lib/iolog/iolog_legacy.c:111 lib/iolog/iolog_legacy.c:123
+#: lib/iolog/iolog_legacy.c:133 lib/iolog/iolog_legacy.c:139
+#: lib/iolog/iolog_loginfo.c:76 lib/iolog/iolog_loginfo.c:212
+#: logsrvd/iolog_writer.c:95 logsrvd/iolog_writer.c:100
+#: logsrvd/iolog_writer.c:134 logsrvd/iolog_writer.c:171
+#: logsrvd/iolog_writer.c:181 logsrvd/iolog_writer.c:194
+#: logsrvd/iolog_writer.c:214 logsrvd/iolog_writer.c:224
+#: logsrvd/iolog_writer.c:243 logsrvd/iolog_writer.c:253
+#: logsrvd/iolog_writer.c:264 logsrvd/iolog_writer.c:274
+#: logsrvd/iolog_writer.c:286 logsrvd/iolog_writer.c:296
+#: logsrvd/iolog_writer.c:306 logsrvd/iolog_writer.c:316
+#: logsrvd/iolog_writer.c:328 logsrvd/iolog_writer.c:364
+#: logsrvd/iolog_writer.c:370 logsrvd/iolog_writer.c:377
+#: logsrvd/iolog_writer.c:383 logsrvd/iolog_writer.c:567
+#: logsrvd/logsrv_util.c:69 logsrvd/logsrvd.c:301 logsrvd/logsrvd.c:310
+#: logsrvd/logsrvd.c:453 logsrvd/logsrvd.c:490 logsrvd/logsrvd.c:522
+#: logsrvd/logsrvd.c:576 logsrvd/logsrvd.c:611 logsrvd/logsrvd.c:660
+#: logsrvd/logsrvd.c:696 logsrvd/logsrvd.c:732 logsrvd/logsrvd.c:1124
+#: logsrvd/logsrvd.c:1439 logsrvd/logsrvd.c:1446 logsrvd/logsrvd.c:1582
+#: logsrvd/logsrvd.c:1587 logsrvd/logsrvd.c:1771 logsrvd/logsrvd.c:1988
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:649
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1742
+#: logsrvd/logsrvd_journal.c:75 logsrvd/logsrvd_journal.c:122
+#: logsrvd/logsrvd_journal.c:213 logsrvd/logsrvd_journal.c:243
+#: logsrvd/logsrvd_journal.c:247 logsrvd/logsrvd_journal.c:255
+#: logsrvd/logsrvd_journal.c:278 logsrvd/logsrvd_journal.c:282
+#: logsrvd/logsrvd_journal.c:430 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:278 logsrvd/logsrvd_local.c:466
+#: logsrvd/logsrvd_local.c:472 logsrvd/logsrvd_local.c:491
+#: logsrvd/logsrvd_queue.c:158 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/sendlog.c:251 logsrvd/sendlog.c:260
+#: logsrvd/sendlog.c:291 logsrvd/sendlog.c:338 logsrvd/sendlog.c:615
+#: logsrvd/sendlog.c:1503 logsrvd/sendlog.c:1510 logsrvd/sendlog.c:1733
+#: logsrvd/sendlog.c:1801 logsrvd/tls_init.c:305 logsrvd/tls_init.c:329
+#: logsrvd/tls_init.c:340 plugins/sudoers/audit.c:116
+#: plugins/sudoers/auth/pam.c:502 plugins/sudoers/auth/pam.c:687
+#: plugins/sudoers/auth/rfc1938.c:111 plugins/sudoers/check_aliases.c:168
+#: plugins/sudoers/cvtsudoers.c:131 plugins/sudoers/cvtsudoers.c:174
+#: plugins/sudoers/cvtsudoers.c:191 plugins/sudoers/cvtsudoers.c:202
+#: plugins/sudoers/cvtsudoers.c:332 plugins/sudoers/cvtsudoers.c:536
+#: plugins/sudoers/cvtsudoers.c:669 plugins/sudoers/cvtsudoers.c:687
+#: plugins/sudoers/cvtsudoers.c:862 plugins/sudoers/cvtsudoers.c:869
+#: plugins/sudoers/cvtsudoers.c:1365 plugins/sudoers/cvtsudoers.c:1369
+#: plugins/sudoers/cvtsudoers.c:1471 plugins/sudoers/cvtsudoers_csv.c:182
+#: plugins/sudoers/cvtsudoers_csv.c:245 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:150 plugins/sudoers/cvtsudoers_ldif.c:193
+#: plugins/sudoers/cvtsudoers_ldif.c:234 plugins/sudoers/cvtsudoers_ldif.c:299
+#: plugins/sudoers/cvtsudoers_ldif.c:375 plugins/sudoers/cvtsudoers_ldif.c:429
+#: plugins/sudoers/cvtsudoers_ldif.c:437 plugins/sudoers/cvtsudoers_ldif.c:448
+#: plugins/sudoers/cvtsudoers_ldif.c:455 plugins/sudoers/cvtsudoers_ldif.c:467
+#: plugins/sudoers/cvtsudoers_ldif.c:480 plugins/sudoers/cvtsudoers_ldif.c:488
+#: plugins/sudoers/cvtsudoers_ldif.c:635 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1157
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:434
+#: plugins/sudoers/defaults.c:658 plugins/sudoers/defaults.c:1019
+#: plugins/sudoers/defaults.c:1187 plugins/sudoers/editor.c:188
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:54 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:227
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:668 plugins/sudoers/iolog.c:694
+#: plugins/sudoers/ldap.c:184 plugins/sudoers/ldap.c:464
+#: plugins/sudoers/ldap.c:755 plugins/sudoers/ldap.c:919
+#: plugins/sudoers/ldap.c:1335 plugins/sudoers/ldap.c:1761
+#: plugins/sudoers/ldap.c:1798 plugins/sudoers/ldap.c:1879
+#: plugins/sudoers/ldap.c:2014 plugins/sudoers/ldap.c:2115
+#: plugins/sudoers/ldap.c:2131 plugins/sudoers/ldap_conf.c:218
+#: plugins/sudoers/ldap_conf.c:250 plugins/sudoers/ldap_conf.c:302
+#: plugins/sudoers/ldap_conf.c:338 plugins/sudoers/ldap_conf.c:444
+#: plugins/sudoers/ldap_conf.c:459 plugins/sudoers/ldap_conf.c:564
+#: plugins/sudoers/ldap_conf.c:597 plugins/sudoers/ldap_conf.c:688
+#: plugins/sudoers/ldap_conf.c:771 plugins/sudoers/ldap_util.c:293
+#: plugins/sudoers/ldap_util.c:300 plugins/sudoers/ldap_util.c:614
+#: plugins/sudoers/linux_audit.c:86 plugins/sudoers/log_client.c:117
+#: plugins/sudoers/log_client.c:228 plugins/sudoers/log_client.c:250
+#: plugins/sudoers/log_client.c:264 plugins/sudoers/log_client.c:402
+#: plugins/sudoers/log_client.c:715 plugins/sudoers/log_client.c:736
+#: plugins/sudoers/log_client.c:1416 plugins/sudoers/log_client.c:1537
+#: plugins/sudoers/log_client.c:1637 plugins/sudoers/log_client.c:1973
+#: plugins/sudoers/log_client.c:2032 plugins/sudoers/logging.c:110
+#: plugins/sudoers/logging.c:188 plugins/sudoers/logging.c:189
+#: plugins/sudoers/logging.c:453 plugins/sudoers/logging.c:668
+#: plugins/sudoers/logging.c:805 plugins/sudoers/logging.c:876
+#: plugins/sudoers/logging.c:888 plugins/sudoers/match_command.c:334
+#: plugins/sudoers/match_command.c:602 plugins/sudoers/match_command.c:653
+#: plugins/sudoers/match_command.c:728 plugins/sudoers/match_command.c:775
+#: plugins/sudoers/match_digest.c:93 plugins/sudoers/parse.c:226
+#: plugins/sudoers/parse.c:243 plugins/sudoers/parse.c:262
+#: plugins/sudoers/parse.c:281 plugins/sudoers/parse.c:298
+#: plugins/sudoers/parse.c:321 plugins/sudoers/parse.c:332
+#: plugins/sudoers/parse_ldif.c:152 plugins/sudoers/parse_ldif.c:183
+#: plugins/sudoers/parse_ldif.c:252 plugins/sudoers/parse_ldif.c:260
+#: plugins/sudoers/parse_ldif.c:265 plugins/sudoers/parse_ldif.c:341
+#: plugins/sudoers/parse_ldif.c:352 plugins/sudoers/parse_ldif.c:379
+#: plugins/sudoers/parse_ldif.c:396 plugins/sudoers/parse_ldif.c:408
+#: plugins/sudoers/parse_ldif.c:412 plugins/sudoers/parse_ldif.c:426
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:598
+#: plugins/sudoers/parse_ldif.c:627 plugins/sudoers/parse_ldif.c:652
+#: plugins/sudoers/parse_ldif.c:710 plugins/sudoers/parse_ldif.c:727
+#: plugins/sudoers/parse_ldif.c:755 plugins/sudoers/parse_ldif.c:762
+#: plugins/sudoers/policy.c:153 plugins/sudoers/policy.c:162
+#: plugins/sudoers/policy.c:171 plugins/sudoers/policy.c:199
+#: plugins/sudoers/policy.c:368 plugins/sudoers/policy.c:383
+#: plugins/sudoers/policy.c:385 plugins/sudoers/policy.c:423
+#: plugins/sudoers/policy.c:432 plugins/sudoers/policy.c:480
+#: plugins/sudoers/policy.c:490 plugins/sudoers/policy.c:499
+#: plugins/sudoers/policy.c:508 plugins/sudoers/policy.c:517
+#: plugins/sudoers/policy.c:624 plugins/sudoers/policy.c:1026
+#: plugins/sudoers/prompt.c:93 plugins/sudoers/pwutil.c:199
+#: plugins/sudoers/pwutil.c:270 plugins/sudoers/pwutil.c:348
+#: plugins/sudoers/pwutil.c:522 plugins/sudoers/pwutil.c:587
+#: plugins/sudoers/pwutil.c:659 plugins/sudoers/pwutil.c:857
+#: plugins/sudoers/pwutil.c:913 plugins/sudoers/pwutil.c:957
+#: plugins/sudoers/pwutil.c:1014 plugins/sudoers/set_perms.c:363
+#: plugins/sudoers/set_perms.c:706 plugins/sudoers/set_perms.c:1073
+#: plugins/sudoers/set_perms.c:1380 plugins/sudoers/set_perms.c:1549
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:185
+#: plugins/sudoers/sssd.c:414 plugins/sudoers/sssd.c:479
+#: plugins/sudoers/sssd.c:505 plugins/sudoers/sssd.c:568
+#: plugins/sudoers/sssd.c:761 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/stubs.c:112 plugins/sudoers/stubs.c:120
+#: plugins/sudoers/sudoers.c:354 plugins/sudoers/sudoers.c:380
+#: plugins/sudoers/sudoers.c:448 plugins/sudoers/sudoers.c:457
+#: plugins/sudoers/sudoers.c:498 plugins/sudoers/sudoers.c:827
+#: plugins/sudoers/sudoers.c:877 plugins/sudoers/sudoers.c:1015
+#: plugins/sudoers/sudoers.c:1075 plugins/sudoers/sudoers.c:1330
+#: plugins/sudoers/sudoreplay.c:562 plugins/sudoers/sudoreplay.c:565
+#: plugins/sudoers/sudoreplay.c:1281 plugins/sudoers/sudoreplay.c:1503
+#: plugins/sudoers/sudoreplay.c:1507 plugins/sudoers/testsudoers.c:120
+#: plugins/sudoers/testsudoers.c:224 plugins/sudoers/testsudoers.c:241
+#: plugins/sudoers/testsudoers.c:588 plugins/sudoers/timestamp.c:451
+#: plugins/sudoers/timestamp.c:495 plugins/sudoers/timestamp.c:1017
+#: plugins/sudoers/timestamp.c:1146 plugins/sudoers/toke_util.c:78
+#: plugins/sudoers/toke_util.c:106 plugins/sudoers/toke_util.c:131
+#: plugins/sudoers/toke_util.c:160 plugins/sudoers/toke_util.c:200
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:150
+#: plugins/sudoers/visudo.c:385 plugins/sudoers/visudo.c:391
+#: plugins/sudoers/visudo.c:498 plugins/sudoers/visudo.c:1054 toke.l:1023
+#: toke.l:1155 toke.l:1218 toke.l:1226
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:314 lib/iolog/iolog_json.c:562
+#: lib/iolog/iolog_json.c:568 lib/iolog/iolog_json.c:574
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:244 plugins/sudoers/cvtsudoers_ldif.c:251
+#: plugins/sudoers/cvtsudoers_ldif.c:592 plugins/sudoers/env.c:340
+#: plugins/sudoers/env.c:347 plugins/sudoers/env.c:458
+#: plugins/sudoers/ldap.c:526 plugins/sudoers/ldap.c:759
+#: plugins/sudoers/ldap.c:1132 plugins/sudoers/ldap_conf.c:222
+#: plugins/sudoers/ldap_conf.c:313 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:92 plugins/sudoers/logging.c:457
+#: plugins/sudoers/logging.c:813 plugins/sudoers/logging.c:823
+#: plugins/sudoers/policy.c:800 plugins/sudoers/policy.c:811
+#: plugins/sudoers/prompt.c:168 plugins/sudoers/serialize_list.c:62
+#: plugins/sudoers/serialize_list.c:71 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/testsudoers.c:245 plugins/sudoers/toke_util.c:213
+#: toke.l:987 toke.l:1189
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "შიდა შეცდომა: %s-ის გადავსება"
+
+#: lib/eventlog/eventlog.c:373
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "stdin-ის დუბლირების შეცდომა: %m"
+
+#: lib/eventlog/eventlog.c:415
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "%s-ის შესრულების შეცდომა: %m"
+
+#: lib/eventlog/eventlog.c:463 plugins/sudoers/auth/aix_auth.c:198
+msgid "unable to fork"
+msgstr "პროცესის განტოტვის შეცდომა"
+
+#: lib/eventlog/eventlog.c:473 lib/eventlog/eventlog.c:538
+#, c-format
+msgid "unable to fork: %m"
+msgstr "განტოტვის შეცდომა: %m"
+
+#: lib/eventlog/eventlog.c:528
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "ფაიფის გახსნის შეცდომა: %m"
+
+#: lib/eventlog/eventlog.c:1030
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:1059
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (ბრძანება გაგრძელდა) %s"
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1242
+#: plugins/sudoers/sudoreplay.c:1293 plugins/sudoers/sudoreplay.c:1558
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr "არასწორი რეგულარული გამოსახულება (%s): %s"
+
+#: lib/iolog/iolog_json.c:140
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "მოველოდი JSON_STRING, მივიღე %d"
+
+#: lib/iolog/iolog_json.c:145
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY ძალიან დიდია"
+
+#: lib/iolog/iolog_json.c:404
+msgid "missing double quote in name"
+msgstr "სახელში ორმაგი ბრჭყალი აკლია"
+
+#: lib/iolog/iolog_json.c:501
+msgid "missing JSON_OBJECT"
+msgstr "\"JSON_OBJECT\" ვერ ვიპოვე"
+
+#: lib/iolog/iolog_json.c:505
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "მოველოდი JSON_OBJECT, მივიღე %d"
+
+#: lib/iolog/iolog_json.c:661
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "json-ის სტეკი გახარჯულია (მაქს %u კადრი)"
+
+#: lib/iolog/iolog_json.c:735
+msgid "objects must consist of name:value pairs"
+msgstr "ობიექტები სახელი:მნიშვნელობის წყვილებისგან უნდა შედგებოდეს"
+
+#: lib/iolog/iolog_json.c:740 lib/iolog/iolog_json.c:771
+#: lib/iolog/iolog_json.c:815 lib/iolog/iolog_json.c:837
+#: lib/iolog/iolog_json.c:859 lib/iolog/iolog_json.c:881
+#: lib/iolog/iolog_json.c:903
+msgid "missing separator between values"
+msgstr "მნიშვნელობებს შორის გამყოფი მითითებული არაა"
+
+#: lib/iolog/iolog_json.c:755 lib/iolog/iolog_json.c:929
+msgid "unmatched close brace"
+msgstr "დამხურავ ფიგურულ ფრჩხილს შესაბამისი არ გააჩნია"
+
+#: lib/iolog/iolog_json.c:766
+msgid "unexpected array"
+msgstr "მოულოდნელი მასივი"
+
+#: lib/iolog/iolog_json.c:786 lib/iolog/iolog_json.c:932
+msgid "unmatched close bracket"
+msgstr "დამხურავ ფრჩხილს შესაბამისი არ გააჩნია"
+
+#: lib/iolog/iolog_json.c:797
+msgid "unexpected string"
+msgstr "მოულოდნელი სტრიქონი"
+
+#: lib/iolog/iolog_json.c:808
+msgid "missing colon after name"
+msgstr "სახელის შემდეგ სვეტი აღმოჩენილი არაა"
+
+#: lib/iolog/iolog_json.c:829 lib/iolog/iolog_json.c:851
+msgid "unexpected boolean"
+msgstr "მოულოდნელი ლოგიკური მნიშვნელობა"
+
+#: lib/iolog/iolog_json.c:873
+msgid "unexpected null"
+msgstr "მოულოდნელი ნულოვანი მნიშვნელობა"
+
+#: lib/iolog/iolog_json.c:894
+msgid "unexpected number"
+msgstr "მოულოდნელი რიცხვი"
+
+#: lib/iolog/iolog_json.c:941
+msgid "parse error"
+msgstr "დამუშავების შეცდომა"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: არასწორი ჟურნალის ფაილი"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: დროის შტამპის ველი აკლია"
+
+#: lib/iolog/iolog_legacy.c:89
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: დროის შტამპი %s: %s"
+
+#: lib/iolog/iolog_legacy.c:96
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: მომხმარებლის ველის გარეშე"
+
+#: lib/iolog/iolog_legacy.c:107
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: runas მომხმარებლის ველის გარეშე"
+
+#: lib/iolog/iolog_legacy.c:118
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: runas ჯგუფის ველის გარეშე"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s არსებობს, მაგრამ საქაღალდეს არ წარმოადგენს (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:123 lib/iolog/iolog_mkdtemp.c:78
+#: logsrvd/iolog_writer.c:781 plugins/sudoers/timestamp.c:209
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "mkdir %s-ის შეცდომა"
+
+#: lib/iolog/iolog_mkdtemp.c:83 plugins/sudoers/visudo.c:753
+#: plugins/sudoers/visudo.c:787 plugins/sudoers/visudo.c:793
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "რეჟიმის %s-დან 0%o-ზე შეცვლა შეუძლებელია"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "დროის ფაილის წაკითხვის შეცდომა: %s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "დროის ფაილის არასწორი ხაზი: %s"
+
+#: logsrvd/iolog_writer.c:65
+#, c-format
+msgid "%s: protocol error: NULL key"
+msgstr "%s: პროტოკოლის შეცდომა: ნულოვანი გასაღები"
+
+#: logsrvd/iolog_writer.c:69
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s: პროტოკოლის შეცდომა. არასწორი ტიპი %s -სთვის"
+
+#: logsrvd/iolog_writer.c:74 logsrvd/logsrvd_local.c:109
+#: logsrvd/logsrvd_local.c:123 logsrvd/logsrvd_local.c:131
+#: logsrvd/logsrvd_local.c:149
+#, c-format
+msgid "%s: protocol error: NULL value found in %s"
+msgstr "%s: პროტოკოლის შეცდომა: %s-ში ნაპოვნი მნიშვნელობა ნულოვანია"
+
+#: logsrvd/iolog_writer.c:141 plugins/sudoers/logging.c:976
+#: plugins/sudoers/policy.c:591
+msgid "unable to generate UUID"
+msgstr "uuid-ის გენერაციის შეცდომა"
+
+#: logsrvd/iolog_writer.c:341 logsrvd/iolog_writer.c:346
+#: logsrvd/iolog_writer.c:351 logsrvd/iolog_writer.c:356
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s: პროტოკოლის შეცდომა: AcceptMessage-ს %s -ი აკლია"
+
+#: logsrvd/iolog_writer.c:417
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s: სესის id-ის დაფორმატების"
+
+#: logsrvd/iolog_writer.c:431 logsrvd/iolog_writer.c:445
+#: logsrvd/iolog_writer.c:459 logsrvd/iolog_writer.c:474
+#: logsrvd/iolog_writer.c:488 logsrvd/iolog_writer.c:502
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s: %s დაყენებული არაა"
+
+#: logsrvd/iolog_writer.c:538 logsrvd/iolog_writer.c:545
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:563
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:593
+#, c-format
+msgid "invalid iofd %d"
+msgstr "არასწორი iofd %d"
+
+#: logsrvd/iolog_writer.c:613
+#, c-format
+msgid "error closing iofd %d: %s"
+msgstr "შეცდომა iofd %d დახურვისას: %s"
+
+#: logsrvd/iolog_writer.c:633
+#, c-format
+msgid "error flushing iofd %d: %s"
+msgstr "iofd %d-ის ჩაწერის შეცდომა: %s"
+
+#: logsrvd/iolog_writer.c:751
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:763 logsrvd/logsrvd_journal.c:382
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:785 logsrvd/logsrvd_journal.c:425
+#: logsrvd/logsrvd_queue.c:115 logsrvd/tls_init.c:256
+#: plugins/sudoers/check.c:292 plugins/sudoers/cvtsudoers.c:730
+#: plugins/sudoers/cvtsudoers.c:751 plugins/sudoers/cvtsudoers.c:1431
+#: plugins/sudoers/cvtsudoers_csv.c:695 plugins/sudoers/cvtsudoers_json.c:898
+#: plugins/sudoers/cvtsudoers_ldif.c:709 plugins/sudoers/sudoers.c:1113
+#: plugins/sudoers/sudoers.c:1143 plugins/sudoers/sudoreplay.c:1469
+#: plugins/sudoers/timestamp.c:460 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:971
+#, c-format
+msgid "unable to open %s"
+msgstr "%s-ის გახსნის შეცდომა"
+
+#: logsrvd/iolog_writer.c:797 logsrvd/logsrv_util.c:105
+#: logsrvd/logsrv_util.c:112 plugins/sudoers/sudoreplay.c:362
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "შეცდომა გახსნისას %s/%s"
+
+#: logsrvd/iolog_writer.c:810
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "შეცდომა კოპირებისას: %s/%s -დან %s/%s: %s -მდე"
+
+#: logsrvd/iolog_writer.c:839 logsrvd/logsrvd_journal.c:195
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "%s-ის %s-ად გადარქმევის შეცდომა"
+
+#: logsrvd/logsrv_util.c:147 logsrvd/logsrv_util.c:176
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr ""
+
+#: logsrvd/logsrv_util.c:159
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr ""
+
+#: logsrvd/logsrv_util.c:166
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr ""
+
+#: logsrvd/logsrvd.c:271 logsrvd/logsrvd_queue.c:135
+msgid "unable to connect to relay"
+msgstr ""
+
+#: logsrvd/logsrvd.c:330 logsrvd/logsrvd_relay.c:842
+#, c-format
+msgid "server message too large: %zu"
+msgstr "სერვერის შეტყობინება ძალიან დიდია: %zu"
+
+#: logsrvd/logsrvd.c:422 logsrvd/logsrvd.c:545 logsrvd/logsrvd.c:631
+#: logsrvd/logsrvd.c:873 logsrvd/logsrvd.c:887 logsrvd/logsrvd.c:1049
+#: logsrvd/logsrvd.c:1174 logsrvd/logsrvd.c:1347 logsrvd/logsrvd.c:1365
+#: logsrvd/logsrvd.c:1464 logsrvd/logsrvd.c:1589 logsrvd/logsrvd.c:1773
+#: logsrvd/logsrvd_journal.c:494 logsrvd/logsrvd_local.c:238
+#: logsrvd/logsrvd_queue.c:164 logsrvd/logsrvd_relay.c:172
+#: logsrvd/logsrvd_relay.c:249 logsrvd/logsrvd_relay.c:253
+#: logsrvd/logsrvd_relay.c:389 logsrvd/logsrvd_relay.c:581
+#: logsrvd/logsrvd_relay.c:742 logsrvd/logsrvd_relay.c:1131
+#: logsrvd/sendlog.c:1291 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:216 plugins/sudoers/audit.c:278
+#: plugins/sudoers/iolog.c:1033 plugins/sudoers/iolog.c:1166
+#: plugins/sudoers/iolog.c:1264 plugins/sudoers/log_client.c:121
+#: plugins/sudoers/log_client.c:343 plugins/sudoers/log_client.c:359
+#: plugins/sudoers/log_client.c:407 plugins/sudoers/log_client.c:611
+#: plugins/sudoers/log_client.c:618 plugins/sudoers/log_client.c:1103
+#: plugins/sudoers/log_client.c:1385 plugins/sudoers/log_client.c:1426
+#: plugins/sudoers/log_client.c:1434 plugins/sudoers/log_client.c:1593
+#: plugins/sudoers/log_client.c:1711 plugins/sudoers/log_client.c:2040
+#: plugins/sudoers/log_client.c:2048 plugins/sudoers/logging.c:147
+#: plugins/sudoers/logging.c:205 plugins/sudoers/sudoreplay.c:522
+#: plugins/sudoers/sudoreplay.c:569 plugins/sudoers/sudoreplay.c:811
+#: plugins/sudoers/sudoreplay.c:923 plugins/sudoers/sudoreplay.c:1014
+#: plugins/sudoers/sudoreplay.c:1029 plugins/sudoers/sudoreplay.c:1036
+#: plugins/sudoers/sudoreplay.c:1043 plugins/sudoers/sudoreplay.c:1050
+#: plugins/sudoers/sudoreplay.c:1057 plugins/sudoers/sudoreplay.c:1184
+msgid "unable to add event to queue"
+msgstr "რიგში მოვლენის ჩამატების შეცდომა"
+
+#: logsrvd/logsrvd.c:446 logsrvd/logsrvd.c:483 logsrvd/logsrvd.c:515
+#: logsrvd/logsrvd.c:569 logsrvd/logsrvd.c:648 logsrvd/logsrvd.c:684
+#: logsrvd/logsrvd.c:720 logsrvd/logsrvd.c:756 logsrvd/logsrvd_relay.c:510
+#: logsrvd/logsrvd_relay.c:543
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr ""
+
+#: logsrvd/logsrvd.c:447 logsrvd/logsrvd.c:484 logsrvd/logsrvd.c:516
+#: logsrvd/logsrvd.c:570 logsrvd/logsrvd.c:649 logsrvd/logsrvd.c:685
+#: logsrvd/logsrvd.c:721 logsrvd/logsrvd.c:757 logsrvd/logsrvd_relay.c:512
+#: logsrvd/logsrvd_relay.c:545
+msgid "state machine error"
+msgstr ""
+
+#: logsrvd/logsrvd.c:453 logsrvd/logsrvd.c:454
+msgid "invalid AcceptMessage"
+msgstr "არასწორი AcceptMessage"
+
+#: logsrvd/logsrvd.c:490 logsrvd/logsrvd.c:491
+msgid "invalid RejectMessage"
+msgstr "არასწორი RejectMessage"
+
+#: logsrvd/logsrvd.c:522 logsrvd/logsrvd.c:523
+msgid "invalid ExitMessage"
+msgstr "არასწორი ExitMessage"
+
+#: logsrvd/logsrvd.c:576 logsrvd/logsrvd.c:577
+msgid "invalid RestartMessage"
+msgstr "არასწორი RestartMessage"
+
+#: logsrvd/logsrvd.c:611 logsrvd/logsrvd.c:612
+msgid "invalid AlertMessage"
+msgstr "არასწორი AlertMessage"
+
+#: logsrvd/logsrvd.c:653 logsrvd/logsrvd.c:689 logsrvd/logsrvd.c:725
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr ""
+
+#: logsrvd/logsrvd.c:654 logsrvd/logsrvd.c:690 logsrvd/logsrvd.c:726
+msgid "protocol error"
+msgstr "პროტოკოლის შეცდომა"
+
+#: logsrvd/logsrvd.c:660 logsrvd/logsrvd.c:661
+msgid "invalid IoBuffer"
+msgstr "არასწორი IoBuffer"
+
+#: logsrvd/logsrvd.c:696 logsrvd/logsrvd.c:697
+msgid "invalid ChangeWindowSize"
+msgstr "არასწორი ChangeWindowSize"
+
+#: logsrvd/logsrvd.c:732 logsrvd/logsrvd.c:733
+msgid "invalid CommandSuspend"
+msgstr "არასწორი CommandSuspend"
+
+#: logsrvd/logsrvd.c:782 logsrvd/logsrvd_journal.c:293
+#: logsrvd/logsrvd_relay.c:652 logsrvd/sendlog.c:1192
+#: plugins/sudoers/log_client.c:1583
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "შეცდომა %s -ის გაშლისას ზომა %zu"
+
+#: logsrvd/logsrvd.c:827 logsrvd/logsrvd_journal.c:367
+#: logsrvd/logsrvd_relay.c:676
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "type_case-ის მოულოდნელი მნიშვნელობა %d %s-ში %s-დან"
+
+#: logsrvd/logsrvd.c:829
+msgid "unrecognized ClientMessage type"
+msgstr ""
+
+#: logsrvd/logsrvd.c:919
+#, c-format
+msgid "timed out writing to client %s"
+msgstr ""
+
+#: logsrvd/logsrvd.c:924 logsrvd/logsrvd_relay.c:914 logsrvd/sendlog.c:1395
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1020
+#, c-format
+msgid "timed out reading from client %s"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1061 logsrvd/logsrvd_relay.c:777
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1105 logsrvd/logsrvd_relay.c:205 logsrvd/sendlog.c:322
+#: plugins/sudoers/log_client.c:721
+#, c-format
+msgid "client message too large: %zu"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1106 logsrvd/logsrvd_journal.c:256
+#: logsrvd/logsrvd_journal.c:257
+msgid "client message too large"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1124 logsrvd/logsrvd.c:1125
+msgid "invalid ClientMessage"
+msgstr "არასწორი ClientMessage"
+
+#: logsrvd/logsrvd.c:1425
+msgid "unable to get remote IP addr"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1456 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:281
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1639 logsrvd/logsrvd.c:1992
+msgid "unable to setup listen socket"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1756
+#, c-format
+msgid "unexpected signal %d"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1894
+msgid "sudo log server"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1896 logsrvd/sendlog.c:121
+msgid "Options:"
+msgstr "პარამეტრები:"
+
+#: logsrvd/logsrvd.c:1898
+msgid "path to configuration file"
+msgstr "ბილიკი კონფიგურაციის ფაილამდე"
+
+#: logsrvd/logsrvd.c:1900 logsrvd/sendlog.c:123
+msgid "display help message and exit"
+msgstr "დახმარების გამოტანა და გამოსვლა"
+
+#: logsrvd/logsrvd.c:1902
+msgid "do not fork, run in the foreground"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1904
+msgid "percent chance connections will drop"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1906 logsrvd/sendlog.c:153
+msgid "display version information and exit"
+msgstr "ვერსიის ჩვენება და გასვლა"
+
+#: logsrvd/logsrvd.c:1956 logsrvd/sendlog.c:1702
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1972
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1975 logsrvd/sendlog.c:1756
+#: plugins/sudoers/cvtsudoers.c:246 plugins/sudoers/sudoreplay.c:301
+#: plugins/sudoers/visudo.c:182
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s ვერსია %s\n"
+
+#: logsrvd/logsrvd_conf.c:422 plugins/sudoers/check.c:353
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/policy.c:1264 plugins/sudoers/sudoers.c:505
+#: plugins/sudoers/sudoers.c:1372 plugins/sudoers/testsudoers.c:215
+#: plugins/sudoers/testsudoers.c:382
+#, c-format
+msgid "unknown user %s"
+msgstr "უცნობი მომხმარებელი %s"
+
+#: logsrvd/logsrvd_conf.c:439 plugins/sudoers/iolog.c:148
+#: plugins/sudoers/sudoers.c:510 plugins/sudoers/sudoers.c:1406
+#: plugins/sudoers/testsudoers.c:406
+#, c-format
+msgid "unknown group %s"
+msgstr "უცნობი ჯგუფი %s"
+
+#: logsrvd/logsrvd_conf.c:457
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:474 logsrvd/logsrvd_conf.c:1243
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "%s-ის არასწორი მნიშვნელობა: %s"
+
+#: logsrvd/logsrvd_conf.c:527
+msgid "TLS not supported"
+msgstr "TLS მხარდაუჭერელია"
+
+#: logsrvd/logsrvd_conf.c:549
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:622 logsrvd/logsrvd_conf.c:1032
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:951 logsrvd/logsrvd_conf.c:967
+#: logsrvd/logsrvd_conf.c:1676
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:983 logsrvd/logsrvd_conf.c:999
+#: logsrvd/logsrvd_conf.c:1015 logsrvd/logsrvd_conf.c:1680
+#: logsrvd/logsrvd_conf.c:1684 logsrvd/logsrvd_conf.c:1688
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1197
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1203
+#, c-format
+msgid "%s:%d garbage after ']': %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1215
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1223
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1229
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1251
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1281 plugins/sudoers/cvtsudoers.c:268
+#: plugins/sudoers/logging.c:1029
+#, c-format
+msgid "unable to open log file %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1763
+msgid "unable to initialize server TLS context"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1783
+msgid "unable to initialize relay TLS context"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:146 logsrvd/logsrvd_journal.c:421
+#: logsrvd/logsrvd_journal.c:426
+msgid "unable to create journal file"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:150 logsrvd/logsrvd_queue.c:109
+#: plugins/sudoers/visudo.c:1026
+#, c-format
+msgid "unable to lock %s"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:153
+msgid "unable to lock journal file"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:161
+msgid "unable to open journal file"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:182 logsrvd/logsrvd_journal.c:457
+#: logsrvd/logsrvd_journal.c:462
+msgid "unable to write journal file"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:190 logsrvd/logsrvd_journal.c:197
+msgid "unable to rename journal file"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:244 logsrvd/logsrvd_journal.c:245
+#: logsrvd/logsrvd_journal.c:279 logsrvd/logsrvd_journal.c:280
+msgid "unexpected EOF reading journal file"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:248 logsrvd/logsrvd_journal.c:249
+#: logsrvd/logsrvd_journal.c:283 logsrvd/logsrvd_journal.c:284
+msgid "error reading journal file"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:295 logsrvd/logsrvd_journal.c:381
+msgid "invalid journal file, unable to restart"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:440
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:166
+#, c-format
+msgid "unexpected value_case %d in %s from %s"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:194
+msgid "error parsing AcceptMessage"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:205
+msgid "error creating I/O log"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:228
+msgid "error logging accept event"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:267
+msgid "error parsing RejectMessage"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:291
+msgid "error logging reject event"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:427 logsrvd/logsrvd_local.c:435
+msgid "error logging exit event"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:492 logsrvd/logsrvd_local.c:493
+msgid "log is already complete, cannot be restarted"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:523
+msgid "unable to restart log"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:539
+msgid "error parsing AlertMessage"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:549
+msgid "error logging alert event"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:585 logsrvd/logsrvd_local.c:648
+#: logsrvd/logsrvd_local.c:683
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:599 logsrvd/logsrvd_local.c:607
+#: logsrvd/logsrvd_local.c:655 logsrvd/logsrvd_local.c:690
+#: plugins/sudoers/sudoreplay.c:351
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: logsrvd/logsrvd_local.c:618
+msgid "randomly dropping connection"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:630
+msgid "error writing IoBuffer"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:665
+msgid "error writing ChangeWindowSize"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:700
+msgid "error writing CommandSuspend"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:435
+msgid "TLS handshake with relay host failed"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:463
+msgid "unable to connect to relay host"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:518
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:520 logsrvd/sendlog.c:1096
+#: plugins/sudoers/log_client.c:1469
+msgid "invalid ServerHello"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:679
+msgid "unrecognized ServerMessage type"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:708
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:710
+msgid "timeout reading from relay"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:762
+msgid "relay host name does not match certificate"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:768 logsrvd/logsrvd_relay.c:782
+#: logsrvd/logsrvd_relay.c:789
+msgid "error reading from relay"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:810
+msgid "unable to read from relay"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:825 logsrvd/logsrvd_relay.c:943
+msgid "relay server closed connection"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:843
+msgid "server message too large"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:907
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:909
+msgid "timeout writing to relay"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:962 logsrvd/logsrvd_relay.c:969
+#: logsrvd/logsrvd_relay.c:981
+msgid "error writing to relay"
+msgstr ""
+
+#: logsrvd/sendlog.c:119
+msgid "send sudo I/O log to remote server"
+msgstr ""
+
+#: logsrvd/sendlog.c:125
+msgid "only send an accept event (no I/O)"
+msgstr ""
+
+#: logsrvd/sendlog.c:128
+msgid "certificate bundle file to verify server's cert against"
+msgstr ""
+
+#: logsrvd/sendlog.c:130
+msgid "certificate file for TLS handshake"
+msgstr ""
+
+#: logsrvd/sendlog.c:133
+msgid "host to send logs to"
+msgstr ""
+
+#: logsrvd/sendlog.c:135
+msgid "remote ID of I/O log to be resumed"
+msgstr ""
+
+#: logsrvd/sendlog.c:138
+msgid "private key file"
+msgstr ""
+
+#: logsrvd/sendlog.c:140
+msgid "do not verify server certificate"
+msgstr ""
+
+#: logsrvd/sendlog.c:143
+msgid "port to use when connecting to host"
+msgstr ""
+
+#: logsrvd/sendlog.c:145
+msgid "restart previous I/O log transfer"
+msgstr ""
+
+#: logsrvd/sendlog.c:147
+msgid "reject the command with the given reason"
+msgstr ""
+
+#: logsrvd/sendlog.c:149
+msgid "stop transfer after reaching this time"
+msgstr ""
+
+#: logsrvd/sendlog.c:151
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr ""
+
+#: logsrvd/sendlog.c:176 plugins/sudoers/log_client.c:453
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr ""
+
+#: logsrvd/sendlog.c:214
+msgid "unable to get server IP addr"
+msgstr ""
+
+#: logsrvd/sendlog.c:300 plugins/sudoers/sudoreplay.c:871
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr ""
+
+#: logsrvd/sendlog.c:1020 plugins/sudoers/iolog.c:951
+#: plugins/sudoers/iolog.c:1026
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr ""
+
+#: logsrvd/sendlog.c:1073 logsrvd/sendlog.c:1090 logsrvd/sendlog.c:1124
+#: plugins/sudoers/log_client.c:1118 plugins/sudoers/log_client.c:1395
+#: plugins/sudoers/log_client.c:1463 plugins/sudoers/log_client.c:1502
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr ""
+
+#: logsrvd/sendlog.c:1160 plugins/sudoers/log_client.c:1551
+#, c-format
+msgid "error message received from server: %s"
+msgstr ""
+
+#: logsrvd/sendlog.c:1173 plugins/sudoers/log_client.c:1564
+#, c-format
+msgid "abort message received from server: %s"
+msgstr ""
+
+#: logsrvd/sendlog.c:1232 plugins/sudoers/log_client.c:1614
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr ""
+
+#: logsrvd/sendlog.c:1261
+msgid "timeout reading from server"
+msgstr ""
+
+#: logsrvd/sendlog.c:1310 plugins/sudoers/log_client.c:1730
+msgid "host name does not match certificate"
+msgstr ""
+
+#: logsrvd/sendlog.c:1343
+msgid "premature EOF"
+msgstr ""
+
+#: logsrvd/sendlog.c:1356 plugins/sudoers/log_client.c:1777
+#, c-format
+msgid "server message too large: %u"
+msgstr ""
+
+#: logsrvd/sendlog.c:1412
+msgid "timeout writing to server"
+msgstr ""
+
+#: logsrvd/sendlog.c:1779
+msgid "both restart point and iolog ID must be specified"
+msgstr ""
+
+#: logsrvd/sendlog.c:1783
+msgid "a restart point may not be set when no I/O is sent"
+msgstr ""
+
+#: logsrvd/sendlog.c:1859
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr ""
+
+#: logsrvd/sendlog.c:1860
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr ""
+
+#: logsrvd/sendlog.c:1862
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr ""
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:315
+msgid "TLS handshake timeout occurred"
+msgstr ""
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:337 plugins/sudoers/log_client.c:353
+msgid "unable to set event"
+msgstr ""
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr ""
+
+#: logsrvd/tls_client.c:196
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr ""
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr ""
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr ""
+
+#: logsrvd/tls_init.c:138 logsrvd/tls_init.c:146
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr ""
+
+#: logsrvd/tls_init.c:166 logsrvd/tls_init.c:174
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr ""
+
+#: logsrvd/tls_init.c:206 logsrvd/tls_init.c:227
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr ""
+
+#: logsrvd/tls_init.c:283
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr ""
+
+#: logsrvd/tls_init.c:290
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr ""
+
+#: plugins/sudoers/audit.c:269 plugins/sudoers/audit.c:429
+#: plugins/sudoers/log_client.c:951 plugins/sudoers/log_client.c:1000
+#: plugins/sudoers/log_client.c:1049 plugins/sudoers/log_client.c:1175
+#: plugins/sudoers/logging.c:591 plugins/sudoers/logging.c:689
+#: plugins/sudoers/logging.c:792 plugins/sudoers/logging.c:983
+#: plugins/sudoers/policy.c:124
+msgid "unable to get time of day"
+msgstr ""
+
+#: plugins/sudoers/auth/aix_auth.c:280
+#, c-format
+msgid "unable to change password for %s"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:74
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:79
+msgid "unable to begin bsd authentication"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:87
+msgid "invalid authentication type"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:96
+msgid "unable to initialize BSD authentication"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:186
+msgid "your account has expired"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:188
+msgid "approval failed"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:61
+msgid "unable to read fwtk config"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:66
+msgid "unable to connect to authentication server"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:72 plugins/sudoers/auth/fwtk.c:97
+#: plugins/sudoers/auth/fwtk.c:129
+msgid "lost connection to authentication server"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:76
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:115
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:164
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:173
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:222
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:237
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:250
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:253
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:317
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:331
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:224
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:337
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:356
+msgid "account validation failure, is your account locked?"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:367
+msgid "Account or password is expired, reset your password and try again"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:373
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:384
+msgid "Password expired, contact your system administrator"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:389
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:397 plugins/sudoers/auth/pam.c:402
+#, c-format
+msgid "PAM account management error: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/rfc1938.c:99 plugins/sudoers/visudo.c:271
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "ბაზაში \"%s\" თქვენ არ არსებობთ"
+
+#: plugins/sudoers/auth/securid5.c:75
+msgid "failed to initialise the ACE API library"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:106
+msgid "unable to contact the SecurID server"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:115
+msgid "User ID locked for SecurID Authentication"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:119 plugins/sudoers/auth/securid5.c:170
+msgid "invalid username length for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:123 plugins/sudoers/auth/securid5.c:175
+msgid "invalid Authentication Handle for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:127
+msgid "SecurID communication failed"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:131 plugins/sudoers/auth/securid5.c:218
+msgid "unknown SecurID error"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:165
+msgid "invalid passcode length for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/sia.c:69 plugins/sudoers/auth/sia.c:126
+msgid "unable to initialize SIA session"
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:135
+msgid "invalid authentication methods"
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:137
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:258 plugins/sudoers/auth/sudo_auth.c:310
+msgid "no authentication methods"
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:260
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:312
+msgid "Unable to initialize authentication methods."
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:486
+msgid "Authentication methods:"
+msgstr ""
+
+#: plugins/sudoers/bsm_audit.c:123 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr ""
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:277
+msgid "unable to commit audit record"
+msgstr ""
+
+#: plugins/sudoers/check.c:285
+#, c-format
+msgid "error reading lecture file %s"
+msgstr ""
+
+#: plugins/sudoers/check.c:288
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr ""
+
+#: plugins/sudoers/check.c:301
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/check.c:348 plugins/sudoers/check.c:358
+#: plugins/sudoers/parse.c:64 plugins/sudoers/sudoers.c:920
+#: plugins/sudoers/sudoers.c:941 plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr ""
+
+#: plugins/sudoers/check_aliases.c:99 plugins/sudoers/defaults.c:1279
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s: %s\n"
+
+#: plugins/sudoers/check_aliases.c:133
+#, c-format
+msgid "cycle in %s \"%s\""
+msgstr ""
+
+#: plugins/sudoers/check_aliases.c:136
+#, c-format
+msgid "%s \"%s\" referenced but not defined"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:209
+#, c-format
+msgid "order increment: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:228
+#, c-format
+msgid "starting order: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:238
+#, c-format
+msgid "order padding: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:248 plugins/sudoers/visudo.c:184
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:277 plugins/sudoers/testsudoers.c:159
+#, c-format
+msgid "unsupported input format %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:295
+#, c-format
+msgid "unsupported output format %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:385
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:399 plugins/sudoers/sudoers.c:166
+#: plugins/sudoers/sudoers.c:222 plugins/sudoers/testsudoers.c:254
+#: plugins/sudoers/visudo.c:280 plugins/sudoers/visudo.c:650
+#: plugins/sudoers/visudo.c:975
+msgid "unable to initialize sudoers default values"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:525 plugins/sudoers/ldap_conf.c:434
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:584
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:630
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:653
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:694 plugins/sudoers/cvtsudoers.c:710
+#, c-format
+msgid "invalid filter: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:754 plugins/sudoers/visudo.c:980
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:1478 plugins/sudoers/sudoreplay.c:1145
+#: plugins/sudoers/timestamp.c:343 plugins/sudoers/timestamp.c:346
+#, c-format
+msgid "unable to write to %s"
+msgstr "%s-ში ჩაწერა შეუძლებელია"
+
+#: plugins/sudoers/cvtsudoers.c:1506
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:1508
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_csv.c:452 plugins/sudoers/cvtsudoers_csv.c:466
+#: plugins/sudoers/cvtsudoers_json.c:657 plugins/sudoers/cvtsudoers_json.c:672
+#: plugins/sudoers/cvtsudoers_ldif.c:347 plugins/sudoers/cvtsudoers_ldif.c:360
+#: plugins/sudoers/ldap.c:510
+msgid "unable to get GMT time"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_csv.c:457 plugins/sudoers/cvtsudoers_csv.c:471
+#: plugins/sudoers/cvtsudoers_json.c:662 plugins/sudoers/cvtsudoers_json.c:677
+#: plugins/sudoers/cvtsudoers_ldif.c:352 plugins/sudoers/cvtsudoers_ldif.c:365
+#: plugins/sudoers/ldap.c:518
+msgid "unable to format timestamp"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_json.c:480 plugins/sudoers/cvtsudoers_json.c:515
+#: plugins/sudoers/cvtsudoers_json.c:728
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_ldif.c:661
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_ldif.c:704
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, c-format
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, c-format
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, c-format
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:1088
+#, c-format
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:1182
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:56
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:60
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:64
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:68
+msgid "Put OTP prompt on its own line"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:72
+msgid "Ignore '.' in $PATH"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:76
+msgid "Always send mail when sudo is run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:80
+msgid "Send mail if user authentication fails"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:84
+msgid "Send mail if the user is not in sudoers"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:88
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:92
+msgid "Send mail if the user is not allowed to run a command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:96
+msgid "Send mail if the user tries to run a command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:100
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:104
+msgid "Lecture user the first time they run sudo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:108
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:112
+msgid "Require users to authenticate by default"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:116
+msgid "Root may run sudo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:120
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:124
+msgid "Log the year in the (non-syslog) log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:128
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:132
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:136
+msgid "Always set $HOME to the target user's home directory"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:140
+msgid "Allow some information gathering to give useful error messages"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:144
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:148
+msgid "Insult the user when they enter an incorrect password"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:152
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:156
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:160
+msgid "Prompt for root's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:164
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:168
+msgid "Prompt for the target user's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:172
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:176
+msgid "Set the LOGNAME and USER environment variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:180
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:184
+msgid "Don't initialize the group vector to that of the target user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:188
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:192
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:196
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:200
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:204
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:208
+#, c-format
+msgid "Path to log file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:212
+#, c-format
+msgid "Path to mail program: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:216
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:220
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:224
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:228
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:232
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:236
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:240
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:244
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:248
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:252
+#, c-format
+msgid "Default password prompt: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:256
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr ""
+
+#: plugins/sudoers/def_data.c:260
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:264
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:268
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:272
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:276
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:280
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:284
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:288
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:292
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:296
+msgid "Allow users to set arbitrary environment variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:300
+msgid "Reset the environment to a default set of variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:304
+msgid "Environment variables to check for safety:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:308
+msgid "Environment variables to remove:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:312
+msgid "Environment variables to preserve:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:316
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:320
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:324
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:328
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:332
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:336
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:340
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:344
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:348
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:352
+msgid "Log user's input for the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:356
+msgid "Log the command's standard input if not connected to a terminal"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:360
+msgid "Log the user's terminal input for the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:364
+msgid "Log the output of the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:368
+msgid "Log the command's standard output if not connected to a terminal"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:372
+msgid "Log the command's standard error if not connected to a terminal"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:376
+msgid "Log the terminal output of the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:380
+msgid "Compress I/O logs using zlib"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:384
+msgid "Always run commands in a pseudo-tty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:388
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:392
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:396
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:400
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:404
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:408
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:412
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:416
+msgid "Run commands on a pty in the background"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:420
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:424
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:428
+#, c-format
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:432
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:436
+msgid "Create a new PAM session for the command to run in"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:440
+msgid "Perform PAM account validation management"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:444
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:448
+msgid "Enable sudoers netgroup support"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:452
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:456
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:460
+msgid "Query the group plugin for unknown system groups"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:464
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:468
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:472
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:476
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:480
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:484
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:488
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:492
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:496
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:500
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:504
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:508
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:512
+msgid "Allow the user to specify a timeout on the command line"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:516
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:520
+msgid "Include the process ID when logging via syslog"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:524
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:528
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:532
+msgid "Ignore case when matching user names"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:536
+msgid "Ignore case when matching group names"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:540
+msgid "Log when a command is allowed by sudoers"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:544
+msgid "Log when a command is denied by sudoers"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:548
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:552
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:556
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:560
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:564
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:568
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:572
+msgid "Verify that the log server's certificate is valid"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:576
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:580
+msgid "Only permit running commands as a user with a valid shell"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:584
+msgid "Set the pam remote user to the user running sudo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:588
+msgid "Set the pam remote host to the local host name"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:592
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:596
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:600
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:604
+msgid "Enable SELinux RBAC support"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:608
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:612
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:616
+msgid "Log sub-commands run by the original command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:620
+msgid "Log the exit status of commands"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:624
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:628
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:632
+#, c-format
+msgid "The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:636
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:640
+#, c-format
+msgid "The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:644
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:648
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:652
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:656
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:660
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:664
+#, c-format
+msgid "The maximum number of processes that the user may run simultaneously: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:668
+#, c-format
+msgid "The maximum size to which the process's resident set size may grow (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:672
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:676
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:680
+msgid "Store plaintext passwords in I/O log input"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:684
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:688
+#, c-format
+msgid "The mechanism used by the intercept and log_subcmds options: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:692
+msgid "Attempt to verify the command and arguments after execution"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:696
+#, c-format
+msgid "AppArmor profile to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:191
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:234
+#, c-format
+msgid "no value specified for \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:243
+#, c-format
+msgid "invalid operator \"%c=\" for \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:275
+#, c-format
+msgid "option \"%s\" does not take a value"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:299
+#, c-format
+msgid "invalid Defaults type 0x%x for option \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:306
+#, c-format
+msgid "value \"%s\" is invalid for option \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:1128 plugins/sudoers/policy.c:208
+#: plugins/sudoers/policy.c:217
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:1134
+#, c-format
+msgid "values for \"%s\" must start with a '/', '~', or '*'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:1141
+#, c-format
+msgid "values for \"%s\" must start with a '/'"
+msgstr ""
+
+#: plugins/sudoers/env.c:426
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr ""
+
+#: plugins/sudoers/env.c:1109
+msgid "unable to rebuild the environment"
+msgstr ""
+
+#: plugins/sudoers/env.c:1183
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr ""
+
+#: plugins/sudoers/filedigest.c:49
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr ""
+
+#: plugins/sudoers/filedigest.c:78
+#, c-format
+msgid "%s: read error"
+msgstr "%s: კითხვის შეცდომა"
+
+#: plugins/sudoers/group_plugin.c:169
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s-ის მფლობლის UID %d უნდა იყოს"
+
+#: plugins/sudoers/group_plugin.c:173
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:185 plugins/sudoers/sssd.c:576
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "%s-ის ჩატვირთვის შეცდომა: %s"
+
+#: plugins/sudoers/group_plugin.c:197
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:202
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:685
+msgid "unable to update sequence file"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:719 plugins/sudoers/iolog.c:909
+#: plugins/sudoers/iolog.c:1071 plugins/sudoers/iolog.c:1078
+#: plugins/sudoers/iolog.c:1199 plugins/sudoers/iolog.c:1206
+#: plugins/sudoers/iolog.c:1305 plugins/sudoers/iolog.c:1312
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:727
+#, c-format
+msgid "unable to create %s/%s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:957
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:1056 plugins/sudoers/iolog.c:1184
+#: plugins/sudoers/iolog.c:1289 plugins/sudoers/timestamp.c:879
+#: plugins/sudoers/timestamp.c:971 plugins/sudoers/visudo.c:552
+#: plugins/sudoers/visudo.c:558
+msgid "unable to read the clock"
+msgstr "საათის წაკითხვის შეცდომა"
+
+#: plugins/sudoers/iolog.c:1281 plugins/sudoers/log_client.c:1193
+#: plugins/sudoers/log_client.c:1203 plugins/sudoers/log_client.c:1207
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:177 plugins/sudoers/ldap_conf.c:292
+msgid "starttls not supported when using ldaps"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:248
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:251
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1712
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1749
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1886 plugins/sudoers/parse_ldif.c:748
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap_conf.c:200
+#, c-format
+msgid "%s: port too large"
+msgstr ""
+
+#: plugins/sudoers/ldap_conf.c:261
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap_conf.c:288
+msgid "unable to mix ldap and ldaps URIs"
+msgstr ""
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr ""
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr ""
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "აუდიტის სისტემის გახსნის შეცდომა"
+
+#: plugins/sudoers/linux_audit.c:103
+msgid "unable to send audit message"
+msgstr "აუდიტის შეტყობინების გაგზავნის შეცდომა"
+
+#: plugins/sudoers/log_client.c:125 plugins/sudoers/log_client.c:412
+#: plugins/sudoers/log_client.c:1440 plugins/sudoers/log_client.c:2056
+msgid "error in event loop"
+msgstr "მოვლენების მარყუჟის შეცდომა"
+
+#: plugins/sudoers/log_client.c:205
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:230
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load certificate %s"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "unable to load private key %s"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:275
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:364 plugins/sudoers/log_client.c:369
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:543
+msgid "TLS initialization was unsuccessful"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:553
+msgid "TLS handshake was unsuccessful"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:1211
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:1740 plugins/sudoers/log_client.c:1764
+msgid "lost connection to log server"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:1841
+msgid "missing write buffer"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:1995
+msgid "unable to connect to log server"
+msgstr ""
+
+#: plugins/sudoers/logging.c:290
+msgid "user NOT in sudoers"
+msgstr ""
+
+#: plugins/sudoers/logging.c:292
+msgid "user NOT authorized on host"
+msgstr ""
+
+#: plugins/sudoers/logging.c:294
+msgid "command not allowed"
+msgstr ""
+
+#: plugins/sudoers/logging.c:315
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:318
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:321
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:324
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:334
+msgid "This incident has been reported to the administrator.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:365 plugins/sudoers/sudoers.c:648
+#: plugins/sudoers/sudoers.c:650 plugins/sudoers/sudoers.c:652
+#: plugins/sudoers/sudoers.c:654 plugins/sudoers/sudoers.c:805
+#: plugins/sudoers/sudoers.c:807
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: ბრძანება ვერ ვიპოვე"
+
+#: plugins/sudoers/logging.c:367 plugins/sudoers/sudoers.c:644
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+
+#: plugins/sudoers/logging.c:387
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] ""
+msgstr[1] ""
+
+#: plugins/sudoers/logging.c:477
+msgid "authentication failure"
+msgstr ""
+
+#: plugins/sudoers/logging.c:516 plugins/sudoers/logging.c:535
+msgid "a password is required"
+msgstr ""
+
+#: plugins/sudoers/logging.c:799 plugins/sudoers/logging.c:811
+msgid "problem parsing sudoers"
+msgstr ""
+
+#: plugins/sudoers/logging.c:873 plugins/sudoers/logging.c:885
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr "%s:%d:%d: %s"
+
+#: plugins/sudoers/logging.c:1062
+#, c-format
+msgid "unable to write log file: %s"
+msgstr ""
+
+#: plugins/sudoers/match_digest.c:112
+#, c-format
+msgid "digest for %s (%s) bad length %zu, expected %zu"
+msgstr ""
+
+#: plugins/sudoers/match_digest.c:131
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr ""
+
+#: plugins/sudoers/parse.c:591
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+
+#: plugins/sudoers/parse.c:594
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+
+#: plugins/sudoers/parse.c:596
+msgid " RunAsUsers: "
+msgstr ""
+
+#: plugins/sudoers/parse.c:611
+msgid " RunAsGroups: "
+msgstr ""
+
+#: plugins/sudoers/parse.c:621
+msgid " Options: "
+msgstr ""
+
+#: plugins/sudoers/parse.c:685
+msgid " Commands:\n"
+msgstr " ბრძანებები:\n"
+
+#: plugins/sudoers/parse.c:876
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr ""
+
+#: plugins/sudoers/parse.c:894
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr ""
+
+#: plugins/sudoers/parse.c:912
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr ""
+
+#: plugins/sudoers/parse.c:927
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/parse_ldif.c:618
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr ""
+
+#: plugins/sudoers/parse_ldif.c:678
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr ""
+
+#: plugins/sudoers/policy.c:81 plugins/sudoers/policy.c:112
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:358 plugins/sudoers/testsudoers.c:268
+msgid "unable to parse network address list"
+msgstr ""
+
+#: plugins/sudoers/policy.c:526
+msgid "user name not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:530
+msgid "user-ID not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:534
+msgid "group-ID not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:538
+msgid "host name not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:730
+#, c-format
+msgid "invalid working directory: %s"
+msgstr ""
+
+#: plugins/sudoers/policy.c:914
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1101 plugins/sudoers/visudo.c:259
+#: plugins/sudoers/visudo.c:902
+#, c-format
+msgid "unable to execute %s"
+msgstr "%s-ის გაშვების შეცდომა"
+
+#: plugins/sudoers/policy.c:1171 plugins/sudoers/policy.c:1208
+#: plugins/sudoers/policy.c:1230 plugins/sudoers/policy.c:1256
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1292
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1294
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1298
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1301
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1303
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1304
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1337
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1355
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:222 plugins/sudoers/pwutil.c:240
+#, c-format
+msgid "unable to cache uid %u"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:234
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:294 plugins/sudoers/pwutil.c:312
+#: plugins/sudoers/pwutil.c:375 plugins/sudoers/pwutil.c:420
+#, c-format
+msgid "unable to cache user %s"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:307
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:539 plugins/sudoers/pwutil.c:557
+#, c-format
+msgid "unable to cache gid %u"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:551
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:605 plugins/sudoers/pwutil.c:623
+#: plugins/sudoers/pwutil.c:684 plugins/sudoers/pwutil.c:733
+#, c-format
+msgid "unable to cache group %s"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:618
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:880 plugins/sudoers/pwutil.c:931
+#: plugins/sudoers/pwutil.c:981 plugins/sudoers/pwutil.c:1033
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:886 plugins/sudoers/pwutil.c:936
+#: plugins/sudoers/pwutil.c:987 plugins/sudoers/pwutil.c:1038
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:925
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:1027
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:114 plugins/sudoers/set_perms.c:445
+#: plugins/sudoers/set_perms.c:852 plugins/sudoers/set_perms.c:1162
+#: plugins/sudoers/set_perms.c:1460
+msgid "perm stack overflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:125 plugins/sudoers/set_perms.c:376
+#: plugins/sudoers/set_perms.c:456 plugins/sudoers/set_perms.c:719
+#: plugins/sudoers/set_perms.c:863 plugins/sudoers/set_perms.c:1086
+#: plugins/sudoers/set_perms.c:1173 plugins/sudoers/set_perms.c:1393
+#: plugins/sudoers/set_perms.c:1471 plugins/sudoers/set_perms.c:1562
+msgid "perm stack underflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:185 plugins/sudoers/set_perms.c:503
+#: plugins/sudoers/set_perms.c:1227 plugins/sudoers/set_perms.c:1505
+msgid "unable to change to root gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:276 plugins/sudoers/set_perms.c:600
+#: plugins/sudoers/set_perms.c:995 plugins/sudoers/set_perms.c:1304
+msgid "unable to change to runas gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:281 plugins/sudoers/set_perms.c:605
+#: plugins/sudoers/set_perms.c:1000 plugins/sudoers/set_perms.c:1309
+msgid "unable to set runas group vector"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:292 plugins/sudoers/set_perms.c:616
+#: plugins/sudoers/set_perms.c:1009 plugins/sudoers/set_perms.c:1318
+msgid "unable to change to runas uid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:310 plugins/sudoers/set_perms.c:634
+#: plugins/sudoers/set_perms.c:1025 plugins/sudoers/set_perms.c:1334
+msgid "unable to change to sudoers gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:363 plugins/sudoers/set_perms.c:706
+#: plugins/sudoers/set_perms.c:1073 plugins/sudoers/set_perms.c:1380
+#: plugins/sudoers/set_perms.c:1549
+msgid "too many processes"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:61
+msgid "unable to get current working directory"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:69
+#, c-format
+msgid "truncated audit path user_cmnd: %s"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:76
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:579
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:587 plugins/sudoers/sssd.c:596
+#: plugins/sudoers/sssd.c:605 plugins/sudoers/sssd.c:614
+#: plugins/sudoers/sssd.c:623
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "სიმბოლო \"%s\"-ის %s-ში პოვნა შეუძლებელია"
+
+#: plugins/sudoers/sudoers.c:263
+#, c-format
+msgid "unable to get defaults from %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:270
+msgid "no valid sudoers sources found, quitting"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:346
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:348
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:373
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:374
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:401
+msgid "no command specified"
+msgstr "ბრძანება მითითებული არაა"
+
+#: plugins/sudoers/sudoers.c:426
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:476
+msgid "user not allowed to override closefrom limit"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:477
+msgid "you are not permitted to use the -C option"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:537
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:552
+msgid "no tty"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:553
+msgid "sorry, you must have a tty to run sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:560
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:643
+msgid "command in current directory"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:658
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:660
+msgid "the -s option may be used to run a privileged shell."
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:662
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:671
+msgid "user not allowed to set a command timeout"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:673
+msgid "sorry, you are not allowed set a command timeout"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:681
+msgid "user not allowed to preserve the environment"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:683
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1073
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1118 plugins/sudoers/sudoreplay.c:1584
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1147 plugins/sudoers/visudo.c:1064
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s: არ წარმოადგენს ჩვეულებრივ ფაილს"
+
+#: plugins/sudoers/sudoers.c:1151 plugins/sudoers/timestamp.c:263 toke.l:1247
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s-ის მფლობლის UID-ია %u. უნდა იყოს %u"
+
+#: plugins/sudoers/sudoers.c:1155 plugins/sudoers/timestamp.c:270 toke.l:1252
+#, c-format
+msgid "%s is world writable"
+msgstr "%s ყველას მიერ ჩაწერადია"
+
+#: plugins/sudoers/sudoers.c:1159 plugins/sudoers/timestamp.c:275 toke.l:1255
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1194
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1213
+#, c-format
+msgid "unknown login class %s"
+msgstr "შესვლის უცნობი კლასი: %s"
+
+#: plugins/sudoers/sudoers.c:1300 plugins/sudoers/sudoers.c:1315
+#, c-format
+msgid "unable to resolve host %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:259
+#, c-format
+msgid "invalid filter option: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:275
+#, c-format
+msgid "invalid max wait: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:298
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:333
+#, c-format
+msgid "invalid time offset %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:342
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:347
+#, c-format
+msgid "%s/timing: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:375
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:637
+msgid "unable to set tty to raw mode"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:688
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:689
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:717
+msgid "Replay finished, press any key to restore the terminal."
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1219 plugins/sudoers/sudoreplay.c:1249
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1271
+msgid "unmatched ')' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1275
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1290
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s არგუმენტი აუცილებელია"
+
+#: plugins/sudoers/sudoreplay.c:1300
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1309
+msgid "unmatched '(' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1311
+msgid "illegal trailing \"or\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1313
+msgid "illegal trailing \"!\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1371
+#, c-format
+msgid "unknown search type %d"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1650
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1652
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1666
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1668
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:344
+msgid "\thost unmatched"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:347
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:348
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:348
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:354 plugins/sudoers/timestamp.c:693
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:890
+msgid "ignoring time stamp from the future"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:913
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:1042
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr ""
+
+#: plugins/sudoers/toke_util.c:156
+msgid "sudoedit should not be specified with a path"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:254
+msgid "the -x option will be removed in a future release"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:256
+msgid "please consider using the cvtsudoers utility instead"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:311 plugins/sudoers/visudo.c:698
+#, c-format
+msgid "press return to edit %s: "
+msgstr ""
+
+#: plugins/sudoers/visudo.c:326
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "ნაპოვნია ჩასწორების სესიის ნარჩენი შემცველობა: %s"
+
+#: plugins/sudoers/visudo.c:402
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:404
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:491 plugins/sudoers/visudo.c:770
+#, c-format
+msgid "unable to stat %s"
+msgstr "%s-ის აღმოჩენის შეცდომა"
+
+#: plugins/sudoers/visudo.c:511 plugins/sudoers/visudo.c:519
+msgid "write error"
+msgstr "ჩაწერის შეცდომა"
+
+#: plugins/sudoers/visudo.c:565
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:572
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:578
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:600
+#, c-format
+msgid "%s unchanged"
+msgstr "%s შეუცვლელია"
+
+#: plugins/sudoers/visudo.c:645
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr ""
+
+#: plugins/sudoers/visudo.c:658
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:744 plugins/sudoers/visudo.c:774
+#: plugins/sudoers/visudo.c:781
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:809
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:820
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:827
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:847
+msgid "What now? "
+msgstr "ახლა რა ვქნათ? "
+
+#: plugins/sudoers/visudo.c:861
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:907
+#, c-format
+msgid "unable to run %s"
+msgstr "%s-ის გაშვების შეცდომა"
+
+#: plugins/sudoers/visudo.c:938
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:949
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:997 plugins/sudoers/visudo.c:1004
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1023
+#, c-format
+msgid "%s busy, try again later"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1027
+msgid "Edit anyway? [y/N]"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1128
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1240
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1242
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -I, --no-includes do not edit include files\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+
+#: toke.l:189
+msgid "empty string"
+msgstr "ცარიელი სტრიქონი"
+
+#: toke.l:201 toke.l:571
+msgid "empty group"
+msgstr "ცარიელი ჯგუფი"
+
+#: toke.l:211 toke.l:569
+msgid "empty netgroup"
+msgstr ""
+
+#: toke.l:289
+msgid "unterminated regular expression"
+msgstr ""
+
+#: toke.l:363 toke.l:375 toke.l:387 toke.l:403 toke.l:422 toke.l:462
+msgid "invalid line continuation"
+msgstr ""
+
+#: toke.l:608 toke.l:620
+msgid "invalid IPv6 address"
+msgstr "არასწორი IPv6 მისამართი"
+
+#: toke.l:868
+msgid "unexpected line break in string"
+msgstr ""
+
+#: toke.l:1218
+msgid "too many levels of includes"
+msgstr ""
diff --git a/plugins/sudoers/po/ko.mo b/plugins/sudoers/po/ko.mo
new file mode 100644
index 0000000..207943d
--- /dev/null
+++ b/plugins/sudoers/po/ko.mo
Binary files differ
diff --git a/plugins/sudoers/po/ko.po b/plugins/sudoers/po/ko.po
new file mode 100644
index 0000000..6991b62
--- /dev/null
+++ b/plugins/sudoers/po/ko.po
@@ -0,0 +1,3849 @@
+# Korean translation for the sudoers plugin
+# This file is distributed under the same license as the sudo package.
+# Todd C. Miller <Todd.Miller@courtesan.com>, 2011-2015
+# Seong-ho Cho <darkcircle.0426@gmail.com>, 2016-2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.9.15b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-10-19 10:02-0600\n"
+"PO-Revision-Date: 2023-10-23 22:32+0900\n"
+"Last-Translator: Seong-ho Cho <darkcircle.0426@gmail.com>\n"
+"Language-Team: Korean <translation-team-ko@googlegroups.com>\n"
+"Language: ko\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 3.4\n"
+
+#: confstr.sh:1 gram.y:1257 plugins/sudoers/logging.c:911
+msgid "syntax error"
+msgstr "문법 오류"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "%p 암호: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] %p 암호: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "암호: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** %h 보안 알림 ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "죄송합니다만, 다시 시도하십시오."
+
+#: gram.y:238 gram.y:305 gram.y:314 gram.y:323 gram.y:333 gram.y:343 gram.y:367
+#: gram.y:394 gram.y:403 gram.y:411 gram.y:420 gram.y:429 gram.y:503 gram.y:513
+#: gram.y:525 gram.y:573 gram.y:582 gram.y:591 gram.y:600 gram.y:733 gram.y:742
+#: gram.y:757 gram.y:777 gram.y:796 gram.y:959 gram.y:964 gram.y:972 gram.y:986
+#: gram.y:992 gram.y:1004 gram.y:1010 gram.y:1135 gram.y:1144 gram.y:1152
+#: gram.y:1161 gram.y:1170 gram.y:1199 gram.y:1208 gram.y:1216 gram.y:1317
+#: gram.y:1447 gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:313 lib/eventlog/eventlog.c:765
+#: lib/eventlog/eventlog.c:842 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:484
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:185
+#: logsrvd/iolog_writer.c:218 logsrvd/iolog_writer.c:228
+#: logsrvd/iolog_writer.c:257 logsrvd/iolog_writer.c:278
+#: logsrvd/iolog_writer.c:290 logsrvd/iolog_writer.c:300
+#: logsrvd/iolog_writer.c:310 logsrvd/iolog_writer.c:320
+#: logsrvd/iolog_writer.c:330 logsrvd/iolog_writer.c:342
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:1057 logsrvd/logsrvd.c:1120 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:650
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1743
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:216
+#: logsrvd/logsrvd_journal.c:217 logsrvd/logsrvd_journal.c:274
+#: logsrvd/logsrvd_journal.c:279 logsrvd/logsrvd_journal.c:439
+#: logsrvd/logsrvd_journal.c:441 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:216 logsrvd/logsrvd_local.c:278
+#: logsrvd/logsrvd_local.c:279 logsrvd/logsrvd_local.c:417
+#: logsrvd/logsrvd_local.c:468 logsrvd/logsrvd_local.c:469
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:475
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/logsrvd_relay.c:446
+#: logsrvd/logsrvd_relay.c:748 logsrvd/logsrvd_relay.c:855
+#: logsrvd/sendlog.c:256 logsrvd/sendlog.c:265 logsrvd/sendlog.c:297
+#: logsrvd/sendlog.c:303 logsrvd/sendlog.c:352 logsrvd/sendlog.c:630
+#: logsrvd/sendlog.c:1822 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/bsdauth.c:154 plugins/sudoers/auth/kerb5.c:122
+#: plugins/sudoers/auth/kerb5.c:150 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/auth/sia.c:61
+#: plugins/sudoers/canon_path.c:129 plugins/sudoers/canon_path.c:161
+#: plugins/sudoers/check_aliases.c:128 plugins/sudoers/check_util.c:56
+#: plugins/sudoers/check_util.c:84 plugins/sudoers/cvtsudoers.c:132
+#: plugins/sudoers/cvtsudoers.c:176 plugins/sudoers/cvtsudoers.c:193
+#: plugins/sudoers/cvtsudoers.c:204 plugins/sudoers/cvtsudoers.c:338
+#: plugins/sudoers/cvtsudoers.c:379 plugins/sudoers/cvtsudoers.c:399
+#: plugins/sudoers/cvtsudoers.c:545 plugins/sudoers/cvtsudoers.c:698
+#: plugins/sudoers/cvtsudoers.c:716 plugins/sudoers/cvtsudoers.c:891
+#: plugins/sudoers/cvtsudoers.c:899 plugins/sudoers/cvtsudoers.c:1395
+#: plugins/sudoers/cvtsudoers.c:1399 plugins/sudoers/cvtsudoers.c:1501
+#: plugins/sudoers/cvtsudoers_csv.c:183 plugins/sudoers/cvtsudoers_csv.c:247
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:152
+#: plugins/sudoers/cvtsudoers_ldif.c:195 plugins/sudoers/cvtsudoers_ldif.c:236
+#: plugins/sudoers/cvtsudoers_ldif.c:302 plugins/sudoers/cvtsudoers_ldif.c:378
+#: plugins/sudoers/cvtsudoers_ldif.c:432 plugins/sudoers/cvtsudoers_ldif.c:440
+#: plugins/sudoers/cvtsudoers_ldif.c:451 plugins/sudoers/cvtsudoers_ldif.c:458
+#: plugins/sudoers/cvtsudoers_ldif.c:470 plugins/sudoers/cvtsudoers_ldif.c:483
+#: plugins/sudoers/cvtsudoers_ldif.c:491 plugins/sudoers/cvtsudoers_ldif.c:638
+#: plugins/sudoers/cvtsudoers_merge.c:47 plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1158
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:212
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:694 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:294 plugins/sudoers/ldap_util.c:301
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:402
+#: plugins/sudoers/log_client.c:717 plugins/sudoers/log_client.c:739
+#: plugins/sudoers/log_client.c:744 plugins/sudoers/log_client.c:1426
+#: plugins/sudoers/log_client.c:1547 plugins/sudoers/log_client.c:1670
+#: plugins/sudoers/log_client.c:1993 plugins/sudoers/log_client.c:2052
+#: plugins/sudoers/logging.c:110 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:872 plugins/sudoers/lookup.c:338
+#: plugins/sudoers/lookup.c:355 plugins/sudoers/lookup.c:374
+#: plugins/sudoers/lookup.c:393 plugins/sudoers/lookup.c:410
+#: plugins/sudoers/lookup.c:433 plugins/sudoers/lookup.c:444
+#: plugins/sudoers/match_command.c:302 plugins/sudoers/match_command.c:574
+#: plugins/sudoers/match_command.c:641 plugins/sudoers/match_command.c:737
+#: plugins/sudoers/match_command.c:785 plugins/sudoers/match_digest.c:88
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:595
+#: plugins/sudoers/parse_ldif.c:625 plugins/sudoers/parse_ldif.c:650
+#: plugins/sudoers/parse_ldif.c:708 plugins/sudoers/parse_ldif.c:725
+#: plugins/sudoers/parse_ldif.c:753 plugins/sudoers/parse_ldif.c:760
+#: plugins/sudoers/policy.c:646 plugins/sudoers/policy.c:1061
+#: plugins/sudoers/prompt.c:94 plugins/sudoers/pwutil.c:219
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:368
+#: plugins/sudoers/pwutil.c:542 plugins/sudoers/pwutil.c:607
+#: plugins/sudoers/pwutil.c:679 plugins/sudoers/pwutil.c:877
+#: plugins/sudoers/pwutil.c:967 plugins/sudoers/pwutil.c:1015
+#: plugins/sudoers/pwutil.c:1076 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:145 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1307 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:256
+#: plugins/sudoers/testsudoers.c:265 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:164 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1095
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1320
+msgid "unable to allocate memory"
+msgstr "메모리를 할당할 수 없습니다"
+
+#: gram.y:624
+msgid "a digest requires a path name"
+msgstr "다이제스트에 경로 이름이 필요합니다"
+
+#: gram.y:646
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "%s: \"CWD\" 값은 '/'; '~'; '*' 문자로 시작해야합니다"
+
+#: gram.y:652
+msgid "\"CWD\" path too long"
+msgstr "\"CWD\" 경로가 너무 깁니다"
+
+#: gram.y:662
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "%s: \"CHROOT\" 값은 '/'; '~'; '*' 문자로 시작해야합니다"
+
+#: gram.y:668
+msgid "\"CHROOT\" path too long"
+msgstr "\"CHROOT\" 경로가 너무 깁니다"
+
+#: gram.y:817
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "문법 오류. %s 예약어를 별칭으로 썼습니다"
+
+#: gram.y:840
+msgid "invalid notbefore value"
+msgstr "부적절한 notbefore 값"
+
+#: gram.y:849
+msgid "invalid notafter value"
+msgstr "부적절한 notafter 값"
+
+#: gram.y:859 plugins/sudoers/policy.c:390
+msgid "timeout value too large"
+msgstr "제한 시간 값이 너무 큽니다"
+
+#: gram.y:861 plugins/sudoers/policy.c:392
+msgid "invalid timeout value"
+msgstr "부적절한 제한 시간 값"
+
+#: gram.y:982 plugins/sudoers/sudoers.c:1162
+msgid "command too long"
+msgstr "명령이 너무 깁니다"
+
+#: gram.y:1016
+msgid "expected a fully-qualified path name"
+msgstr "완전한 경로 이름이 필요합니다"
+
+#: gram.y:1261
+#, c-format
+msgid "%s:%d:%zu: %s\n"
+msgstr "%s:%d:%zu: %s\n"
+
+#: gram.y:1315
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "\"%s\" 별칭을 이미 정의했습니다"
+
+#: gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:765 lib/eventlog/eventlog.c:838
+#: lib/eventlog/eventlog.c:841 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:483
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:232
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:174
+#: logsrvd/iolog_writer.c:184 logsrvd/iolog_writer.c:197
+#: logsrvd/iolog_writer.c:217 logsrvd/iolog_writer.c:227
+#: logsrvd/iolog_writer.c:246 logsrvd/iolog_writer.c:256
+#: logsrvd/iolog_writer.c:267 logsrvd/iolog_writer.c:277
+#: logsrvd/iolog_writer.c:289 logsrvd/iolog_writer.c:299
+#: logsrvd/iolog_writer.c:309 logsrvd/iolog_writer.c:319
+#: logsrvd/iolog_writer.c:329 logsrvd/iolog_writer.c:341
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:530
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:668
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:1131
+#: logsrvd/logsrvd.c:1446 logsrvd/logsrvd.c:1453 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:649
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1742
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:125
+#: logsrvd/logsrvd_journal.c:216 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:250 logsrvd/logsrvd_journal.c:258
+#: logsrvd/logsrvd_journal.c:287 logsrvd/logsrvd_journal.c:291
+#: logsrvd/logsrvd_journal.c:439 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:278 logsrvd/logsrvd_local.c:468
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:493
+#: logsrvd/logsrvd_queue.c:158 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/sendlog.c:256 logsrvd/sendlog.c:265
+#: logsrvd/sendlog.c:297 logsrvd/sendlog.c:303 logsrvd/sendlog.c:352
+#: logsrvd/sendlog.c:630 logsrvd/sendlog.c:1523 logsrvd/sendlog.c:1530
+#: logsrvd/sendlog.c:1753 logsrvd/sendlog.c:1822 logsrvd/tls_init.c:305
+#: logsrvd/tls_init.c:329 logsrvd/tls_init.c:340 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/pam.c:518 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/canon_path.c:129
+#: plugins/sudoers/canon_path.c:161 plugins/sudoers/check_aliases.c:128
+#: plugins/sudoers/check_util.c:56 plugins/sudoers/check_util.c:84
+#: plugins/sudoers/cvtsudoers.c:132 plugins/sudoers/cvtsudoers.c:175
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:203
+#: plugins/sudoers/cvtsudoers.c:337 plugins/sudoers/cvtsudoers.c:544
+#: plugins/sudoers/cvtsudoers.c:697 plugins/sudoers/cvtsudoers.c:715
+#: plugins/sudoers/cvtsudoers.c:891 plugins/sudoers/cvtsudoers.c:898
+#: plugins/sudoers/cvtsudoers.c:1395 plugins/sudoers/cvtsudoers.c:1399
+#: plugins/sudoers/cvtsudoers.c:1501 plugins/sudoers/cvtsudoers_csv.c:182
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:151 plugins/sudoers/cvtsudoers_ldif.c:194
+#: plugins/sudoers/cvtsudoers_ldif.c:235 plugins/sudoers/cvtsudoers_ldif.c:301
+#: plugins/sudoers/cvtsudoers_ldif.c:377 plugins/sudoers/cvtsudoers_ldif.c:431
+#: plugins/sudoers/cvtsudoers_ldif.c:439 plugins/sudoers/cvtsudoers_ldif.c:450
+#: plugins/sudoers/cvtsudoers_ldif.c:457 plugins/sudoers/cvtsudoers_ldif.c:469
+#: plugins/sudoers/cvtsudoers_ldif.c:482 plugins/sudoers/cvtsudoers_ldif.c:490
+#: plugins/sudoers/cvtsudoers_ldif.c:637 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51 plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1157
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:211
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:693 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:293 plugins/sudoers/ldap_util.c:300
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:228
+#: plugins/sudoers/log_client.c:250 plugins/sudoers/log_client.c:264
+#: plugins/sudoers/log_client.c:402 plugins/sudoers/log_client.c:717
+#: plugins/sudoers/log_client.c:739 plugins/sudoers/log_client.c:744
+#: plugins/sudoers/log_client.c:1426 plugins/sudoers/log_client.c:1547
+#: plugins/sudoers/log_client.c:1670 plugins/sudoers/log_client.c:1993
+#: plugins/sudoers/log_client.c:2052 plugins/sudoers/logging.c:110
+#: plugins/sudoers/logging.c:189 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:755 plugins/sudoers/logging.c:872
+#: plugins/sudoers/logging.c:925 plugins/sudoers/logging.c:932
+#: plugins/sudoers/lookup.c:337 plugins/sudoers/lookup.c:354
+#: plugins/sudoers/lookup.c:373 plugins/sudoers/lookup.c:392
+#: plugins/sudoers/lookup.c:409 plugins/sudoers/lookup.c:432
+#: plugins/sudoers/lookup.c:443 plugins/sudoers/match_command.c:301
+#: plugins/sudoers/match_command.c:573 plugins/sudoers/match_command.c:640
+#: plugins/sudoers/match_command.c:737 plugins/sudoers/match_command.c:784
+#: plugins/sudoers/match_digest.c:88 plugins/sudoers/parse_ldif.c:152
+#: plugins/sudoers/parse_ldif.c:183 plugins/sudoers/parse_ldif.c:252
+#: plugins/sudoers/parse_ldif.c:260 plugins/sudoers/parse_ldif.c:265
+#: plugins/sudoers/parse_ldif.c:341 plugins/sudoers/parse_ldif.c:352
+#: plugins/sudoers/parse_ldif.c:379 plugins/sudoers/parse_ldif.c:396
+#: plugins/sudoers/parse_ldif.c:408 plugins/sudoers/parse_ldif.c:412
+#: plugins/sudoers/parse_ldif.c:426 plugins/sudoers/parse_ldif.c:484
+#: plugins/sudoers/parse_ldif.c:595 plugins/sudoers/parse_ldif.c:624
+#: plugins/sudoers/parse_ldif.c:649 plugins/sudoers/parse_ldif.c:707
+#: plugins/sudoers/parse_ldif.c:724 plugins/sudoers/parse_ldif.c:752
+#: plugins/sudoers/parse_ldif.c:759 plugins/sudoers/policy.c:157
+#: plugins/sudoers/policy.c:166 plugins/sudoers/policy.c:175
+#: plugins/sudoers/policy.c:204 plugins/sudoers/policy.c:374
+#: plugins/sudoers/policy.c:390 plugins/sudoers/policy.c:392
+#: plugins/sudoers/policy.c:430 plugins/sudoers/policy.c:439
+#: plugins/sudoers/policy.c:448 plugins/sudoers/policy.c:457
+#: plugins/sudoers/policy.c:493 plugins/sudoers/policy.c:502
+#: plugins/sudoers/policy.c:511 plugins/sudoers/policy.c:520
+#: plugins/sudoers/policy.c:529 plugins/sudoers/policy.c:538
+#: plugins/sudoers/policy.c:547 plugins/sudoers/policy.c:646
+#: plugins/sudoers/policy.c:1061 plugins/sudoers/prompt.c:94
+#: plugins/sudoers/pwutil.c:219 plugins/sudoers/pwutil.c:290
+#: plugins/sudoers/pwutil.c:368 plugins/sudoers/pwutil.c:542
+#: plugins/sudoers/pwutil.c:607 plugins/sudoers/pwutil.c:679
+#: plugins/sudoers/pwutil.c:877 plugins/sudoers/pwutil.c:967
+#: plugins/sudoers/pwutil.c:1015 plugins/sudoers/pwutil.c:1076
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1306 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:255
+#: plugins/sudoers/testsudoers.c:264 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:163 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1094
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1309 toke.l:1320
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:304
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "표준 입력을 복제할 수 없습니다: %m"
+
+#: lib/eventlog/eventlog.c:346
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "%s을(를) 실행할 수 없습니다: %m"
+
+#: lib/eventlog/eventlog.c:394 plugins/sudoers/auth/aix_auth.c:199
+msgid "unable to fork"
+msgstr "포킹할 수 없습니다"
+
+#: lib/eventlog/eventlog.c:404 lib/eventlog/eventlog.c:471
+#, c-format
+msgid "unable to fork: %m"
+msgstr "포킹할 수 없습니다: %m"
+
+#: lib/eventlog/eventlog.c:461
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "파이프를 열 수 없습니다: %m"
+
+#: lib/eventlog/eventlog.c:1000
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:1029
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (명령 계속 실행) %s"
+
+#: lib/eventlog/parse_json.c:175
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "JSON_STRING 값을 기대했지만, %d 결과가 나왔습니다"
+
+#: lib/eventlog/parse_json.c:180
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY 값이 너무 큽니다"
+
+#: lib/eventlog/parse_json.c:506
+msgid "missing double quote in name"
+msgstr "이름에 이중 따옴표가 빠졌습니다"
+
+#: lib/eventlog/parse_json.c:624
+msgid "missing JSON_OBJECT"
+msgstr "JSON_OBJECT 값이 빠졌습니다"
+
+#: lib/eventlog/parse_json.c:628
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "JSON_OBJECT 값을 기대했지만, %d 결과가 나왔습니다"
+
+#: lib/eventlog/parse_json.c:762
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "json 스택 용량이 부족합니다 (최대 %u 프레임)"
+
+#: lib/eventlog/parse_json.c:840
+msgid "objects must consist of name:value pairs"
+msgstr "객체는 이름:값 쌍으로 구성해야 합니다"
+
+#: lib/eventlog/parse_json.c:845 lib/eventlog/parse_json.c:876
+#: lib/eventlog/parse_json.c:920 lib/eventlog/parse_json.c:942
+#: lib/eventlog/parse_json.c:964 lib/eventlog/parse_json.c:986
+#: lib/eventlog/parse_json.c:1008
+msgid "missing separator between values"
+msgstr "값을 구분하는 구분자가 빠졌습니다"
+
+#: lib/eventlog/parse_json.c:860 lib/eventlog/parse_json.c:1034
+msgid "unmatched close brace"
+msgstr "일치하지 않는 중괄호 닫기 표시"
+
+#: lib/eventlog/parse_json.c:871
+msgid "unexpected array"
+msgstr "예기치 않은 배열 발견"
+
+#: lib/eventlog/parse_json.c:891 lib/eventlog/parse_json.c:1037
+msgid "unmatched close bracket"
+msgstr "일치하지 않는 각괄호 닫기 표시"
+
+#: lib/eventlog/parse_json.c:902
+msgid "unexpected string"
+msgstr "예기치 않은 문자열 값 발견"
+
+#: lib/eventlog/parse_json.c:913
+msgid "missing colon after name"
+msgstr "이름 뒤에 콜론이 빠졌습니다"
+
+#: lib/eventlog/parse_json.c:934 lib/eventlog/parse_json.c:956
+msgid "unexpected boolean"
+msgstr "예기치 않은 부울린 값 발견"
+
+#: lib/eventlog/parse_json.c:978
+msgid "unexpected null"
+msgstr "예기치 않은 NULL 값 발견"
+
+#: lib/eventlog/parse_json.c:999
+msgid "unexpected number"
+msgstr "예기치 않은 숫자 값 발견"
+
+#: lib/eventlog/parse_json.c:1045
+msgid "parse error"
+msgstr "해석 오류"
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1290
+#: plugins/sudoers/sudoreplay.c:1291 plugins/sudoers/sudoreplay.c:1587
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr "부적절한 정규 표현식 \"%s\": %s"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: 부적절한 로그 파일"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: 타임스탬프 필드가 빠졌습니다"
+
+#: lib/iolog/iolog_legacy.c:90
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: %s 타임스탬프: %s"
+
+#: lib/iolog/iolog_legacy.c:97
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: 사용자 필드가 빠졌습니다"
+
+#: lib/iolog/iolog_legacy.c:108
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: 실행 사용자 필드가 빠졌습니다"
+
+#: lib/iolog/iolog_legacy.c:119
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: 실행 그룹 필드가 빠졌습니다"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s이(가) 있지만 디렉터리가 아닙니다(0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:124 lib/iolog/iolog_mkdtemp.c:80
+#: logsrvd/iolog_writer.c:795 plugins/sudoers/timestamp.c:218
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "mkdir %s 명령을 실행할 수 없습니다"
+
+#: lib/iolog/iolog_mkdtemp.c:85 plugins/sudoers/visudo.c:769
+#: plugins/sudoers/visudo.c:803 plugins/sudoers/visudo.c:809
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "%s 모드를 0%o 값으로 바꿀 수 없습니다"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "타이밍 파일 읽기 오류: %s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "부적절한 타이밍 파일 행: %s"
+
+#: logsrvd/iolog_writer.c:65
+#, c-format
+msgid "%s: protocol error: NULL key"
+msgstr "%s: 프로토콜 오류: NULL키"
+
+#: logsrvd/iolog_writer.c:69
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s: 프로토콜 오류: %s의 잘못된 형식"
+
+#: logsrvd/iolog_writer.c:74 logsrvd/logsrvd_local.c:109
+#: logsrvd/logsrvd_local.c:123 logsrvd/logsrvd_local.c:131
+#: logsrvd/logsrvd_local.c:149
+#, c-format
+msgid "%s: protocol error: NULL value found in %s"
+msgstr "%s: 프로토콜 오류: %s에 NULL값 들어감"
+
+#: logsrvd/iolog_writer.c:141 plugins/sudoers/logging.c:1024
+#: plugins/sudoers/policy.c:613
+msgid "unable to generate UUID"
+msgstr "UUID를 만들 수 없습니다"
+
+#: logsrvd/iolog_writer.c:354 logsrvd/iolog_writer.c:359
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:369
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s: 프로토콜 오류: AcceptMessage에 %s 빠짐"
+
+#: logsrvd/iolog_writer.c:430
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s: 세션 ID를 포매팅할 수 없습니다"
+
+#: logsrvd/iolog_writer.c:444 logsrvd/iolog_writer.c:458
+#: logsrvd/iolog_writer.c:472 logsrvd/iolog_writer.c:487
+#: logsrvd/iolog_writer.c:501 logsrvd/iolog_writer.c:515
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s: %s을(를) 설정하지 않음"
+
+#: logsrvd/iolog_writer.c:551 logsrvd/iolog_writer.c:558
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr "%s 입출력 로그 경로를 확장할 수 없습니다"
+
+#: logsrvd/iolog_writer.c:576
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr "%s 입출력 로그 경로를 만들 수 없습니다"
+
+#: logsrvd/iolog_writer.c:606
+#, c-format
+msgid "invalid iofd %d"
+msgstr "부적절한 입출력 파일 서술자 %d번"
+
+#: logsrvd/iolog_writer.c:626
+#, c-format
+msgid "error closing iofd %u: %s"
+msgstr "%u 입출력 파일 서술자 닫기 오류: %s"
+
+#: logsrvd/iolog_writer.c:647
+#, c-format
+msgid "error flushing iofd %u: %s"
+msgstr "%u 입출력 파일 서술자 제거 오류: %s"
+
+#: logsrvd/iolog_writer.c:765
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "부적절한 %s 입출력 로그: %s을(를) 참조했지만 없습니다"
+
+#: logsrvd/iolog_writer.c:777 logsrvd/logsrvd_journal.c:391
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "%s: [%lld, %ld] 재개 지점을 찾을 수 없습니다"
+
+#: logsrvd/iolog_writer.c:799 logsrvd/logsrvd_journal.c:434
+#: logsrvd/logsrvd_queue.c:115 logsrvd/tls_init.c:256
+#: plugins/sudoers/check.c:285 plugins/sudoers/cvtsudoers.c:758
+#: plugins/sudoers/cvtsudoers.c:780 plugins/sudoers/cvtsudoers.c:1461
+#: plugins/sudoers/cvtsudoers_csv.c:697 plugins/sudoers/cvtsudoers_json.c:902
+#: plugins/sudoers/cvtsudoers_ldif.c:711 plugins/sudoers/sudoers.c:1291
+#: plugins/sudoers/sudoers.c:1317 plugins/sudoers/sudoreplay.c:1497
+#: plugins/sudoers/timestamp.c:478 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:990
+#, c-format
+msgid "unable to open %s"
+msgstr "%s을(를) 열 수 없습니다"
+
+#: logsrvd/iolog_writer.c:811 logsrvd/logsrv_util.c:111
+#: logsrvd/logsrv_util.c:118 plugins/sudoers/sudoreplay.c:355
+#: plugins/sudoers/sudoreplay.c:361
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "%s/%s을(를) 열 수 없습니다"
+
+#: logsrvd/iolog_writer.c:824
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "%s/%s을(를) %s/%s(으)로 복사할 수 없습니다: %s"
+
+#: logsrvd/iolog_writer.c:853 logsrvd/logsrvd_journal.c:198
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "%s을(를) %s(으)로 이름을 바꿀 수 없습니다"
+
+#: logsrvd/logsrv_util.c:153 logsrvd/logsrv_util.c:182
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s: [%lld, %ld] 재개 지점을 찾을 수 없습니다"
+
+#: logsrvd/logsrv_util.c:165
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "입출력 로그 파일 %s/%s 빠짐"
+
+#: logsrvd/logsrv_util.c:172
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s: %zu회 이전 탐색을 진행할 수 없습니다"
+
+#: logsrvd/logsrvd.c:271 logsrvd/logsrvd_queue.c:135
+msgid "unable to connect to relay"
+msgstr "릴레이에 연결할 수 없습니다"
+
+#: logsrvd/logsrvd.c:338 logsrvd/logsrvd_relay.c:847
+#, c-format
+msgid "server message too large: %zu"
+msgstr "서버 메시지가 너무 깁니다: %zu"
+
+#: logsrvd/logsrvd.c:430 logsrvd/logsrvd.c:553 logsrvd/logsrvd.c:639
+#: logsrvd/logsrvd.c:881 logsrvd/logsrvd.c:895 logsrvd/logsrvd.c:1056
+#: logsrvd/logsrvd.c:1181 logsrvd/logsrvd.c:1354 logsrvd/logsrvd.c:1372
+#: logsrvd/logsrvd.c:1471 logsrvd/logsrvd.c:1596 logsrvd/logsrvd.c:1783
+#: logsrvd/logsrvd_journal.c:503 logsrvd/logsrvd_local.c:238
+#: logsrvd/logsrvd_queue.c:164 logsrvd/logsrvd_relay.c:172
+#: logsrvd/logsrvd_relay.c:249 logsrvd/logsrvd_relay.c:253
+#: logsrvd/logsrvd_relay.c:391 logsrvd/logsrvd_relay.c:583
+#: logsrvd/logsrvd_relay.c:747 logsrvd/logsrvd_relay.c:1137
+#: logsrvd/sendlog.c:1308 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:216 plugins/sudoers/audit.c:281
+#: plugins/sudoers/iolog.c:1041 plugins/sudoers/iolog.c:1175
+#: plugins/sudoers/iolog.c:1274 plugins/sudoers/log_client.c:121
+#: plugins/sudoers/log_client.c:343 plugins/sudoers/log_client.c:359
+#: plugins/sudoers/log_client.c:407 plugins/sudoers/log_client.c:613
+#: plugins/sudoers/log_client.c:620 plugins/sudoers/log_client.c:1114
+#: plugins/sudoers/log_client.c:1395 plugins/sudoers/log_client.c:1436
+#: plugins/sudoers/log_client.c:1444 plugins/sudoers/log_client.c:1603
+#: plugins/sudoers/log_client.c:1728 plugins/sudoers/log_client.c:2060
+#: plugins/sudoers/log_client.c:2068 plugins/sudoers/logging.c:148
+#: plugins/sudoers/logging.c:206 plugins/sudoers/sudoreplay.c:519
+#: plugins/sudoers/sudoreplay.c:566 plugins/sudoers/sudoreplay.c:808
+#: plugins/sudoers/sudoreplay.c:920 plugins/sudoers/sudoreplay.c:1011
+#: plugins/sudoers/sudoreplay.c:1026 plugins/sudoers/sudoreplay.c:1033
+#: plugins/sudoers/sudoreplay.c:1040 plugins/sudoers/sudoreplay.c:1047
+#: plugins/sudoers/sudoreplay.c:1054 plugins/sudoers/sudoreplay.c:1182
+msgid "unable to add event to queue"
+msgstr "큐에 이벤트를 추가할 수 없습니다"
+
+#: logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:491 logsrvd/logsrvd.c:523
+#: logsrvd/logsrvd.c:577 logsrvd/logsrvd.c:656 logsrvd/logsrvd.c:692
+#: logsrvd/logsrvd.c:728 logsrvd/logsrvd.c:764 logsrvd/logsrvd_relay.c:512
+#: logsrvd/logsrvd_relay.c:545
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr "%2$s의 예기치 않은 상태 %1$d번"
+
+#: logsrvd/logsrvd.c:455 logsrvd/logsrvd.c:492 logsrvd/logsrvd.c:524
+#: logsrvd/logsrvd.c:578 logsrvd/logsrvd.c:657 logsrvd/logsrvd.c:693
+#: logsrvd/logsrvd.c:729 logsrvd/logsrvd.c:765 logsrvd/logsrvd_relay.c:514
+#: logsrvd/logsrvd_relay.c:547
+msgid "state machine error"
+msgstr "상태 머신 오류"
+
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:462
+msgid "invalid AcceptMessage"
+msgstr "부적절한 AcceptMessage"
+
+#: logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:499
+msgid "invalid RejectMessage"
+msgstr "부적절한 RejectMessage"
+
+#: logsrvd/logsrvd.c:530 logsrvd/logsrvd.c:531
+msgid "invalid ExitMessage"
+msgstr "부적절한 ExitMessage"
+
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:585
+msgid "invalid RestartMessage"
+msgstr "부적절한 RestartMessage"
+
+#: logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:620
+msgid "invalid AlertMessage"
+msgstr "부적절한 AlertMessage"
+
+#: logsrvd/logsrvd.c:661 logsrvd/logsrvd.c:697 logsrvd/logsrvd.c:733
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s: 예기치 않은 입출력 버퍼 발견"
+
+#: logsrvd/logsrvd.c:662 logsrvd/logsrvd.c:698 logsrvd/logsrvd.c:734
+msgid "protocol error"
+msgstr "프로토콜 오류"
+
+#: logsrvd/logsrvd.c:668 logsrvd/logsrvd.c:669
+msgid "invalid IoBuffer"
+msgstr "부적절한 IoBuffer"
+
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:705
+msgid "invalid ChangeWindowSize"
+msgstr "부적절한 ChangeWindowSize"
+
+#: logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:741
+msgid "invalid CommandSuspend"
+msgstr "부적절한 CommandSuspend"
+
+#: logsrvd/logsrvd.c:790 logsrvd/logsrvd_journal.c:302
+#: logsrvd/logsrvd_relay.c:654 logsrvd/sendlog.c:1207
+#: plugins/sudoers/log_client.c:1593
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "%2$zu 크기의 %1$s을(를) 언팩할 수 없습니다"
+
+#: logsrvd/logsrvd.c:835 logsrvd/logsrvd_journal.c:376
+#: logsrvd/logsrvd_relay.c:678
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "%3$s의 %2$s에서 예기지 않은 type_case 값 %1$d"
+
+#: logsrvd/logsrvd.c:837
+msgid "unrecognized ClientMessage type"
+msgstr "인식할 수 없는 ClientMessage 형식"
+
+#: logsrvd/logsrvd.c:927
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "%s 클라이언트 기록 시간 초과"
+
+#: logsrvd/logsrvd.c:932 logsrvd/logsrvd_relay.c:919 logsrvd/sendlog.c:1413
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr "%s 클라이언트에서 기록 버퍼 빠짐"
+
+#: logsrvd/logsrvd.c:1027
+#, c-format
+msgid "timed out reading from client %s"
+msgstr "%s 클라이언트에서 읽기 시간 초과"
+
+#: logsrvd/logsrvd.c:1068 logsrvd/logsrvd_relay.c:782
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr "적절한 TLS 셧다운을 수행하지 않은 %s의 파일 끝(EOF)"
+
+#: logsrvd/logsrvd.c:1112 logsrvd/logsrvd_relay.c:205 logsrvd/sendlog.c:336
+#: plugins/sudoers/log_client.c:723
+#, c-format
+msgid "client message too large: %zu"
+msgstr "클라이언드 메시지가 너무 깁니다: %zu"
+
+#: logsrvd/logsrvd.c:1113 logsrvd/logsrvd_journal.c:259
+#: logsrvd/logsrvd_journal.c:260
+msgid "client message too large"
+msgstr "클라이언트 메시지가 너무 깁니다"
+
+#: logsrvd/logsrvd.c:1131 logsrvd/logsrvd.c:1132
+msgid "invalid ClientMessage"
+msgstr "부적절한 ClientMessage"
+
+#: logsrvd/logsrvd.c:1432
+msgid "unable to get remote IP addr"
+msgstr "원격 IP 주소를 가져올 수 없습니다"
+
+#: logsrvd/logsrvd.c:1463 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:281
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "ssl 객체에 사용자 데이터를 붙일 수 없습니다: %s"
+
+#: logsrvd/logsrvd.c:1646 logsrvd/logsrvd.c:2007
+msgid "unable to setup listen socket"
+msgstr "감청 소켓을 설정할 수 없습니다"
+
+#: logsrvd/logsrvd.c:1766
+#, c-format
+msgid "unexpected signal %d"
+msgstr "예기치 않은 시그널 %d번"
+
+#: logsrvd/logsrvd.c:1909
+msgid "sudo log server"
+msgstr "sudo 로그 서버"
+
+#: logsrvd/logsrvd.c:1911 logsrvd/sendlog.c:126
+msgid "Options:"
+msgstr "옵션:"
+
+#: logsrvd/logsrvd.c:1913
+msgid "path to configuration file"
+msgstr "설정 파일 경로"
+
+#: logsrvd/logsrvd.c:1915 logsrvd/sendlog.c:128
+msgid "display help message and exit"
+msgstr "도움말 메시지를 표시한 후 빠져나갑니다"
+
+#: logsrvd/logsrvd.c:1917
+msgid "do not fork, run in the foreground"
+msgstr "프로세스를 포킹하지 않고, 포그라운드에서 실행"
+
+#: logsrvd/logsrvd.c:1919
+msgid "percent chance connections will drop"
+msgstr "연결이 끊을 확률에 대한 백분율"
+
+#: logsrvd/logsrvd.c:1921 logsrvd/sendlog.c:158
+msgid "display version information and exit"
+msgstr "버전 정보를 표시하고 빠져나갑니다"
+
+#: logsrvd/logsrvd.c:1971 logsrvd/sendlog.c:1722
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "Protobuf-C 1.3 이상의 버전이 필요합니다"
+
+#: logsrvd/logsrvd.c:1987
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "부적절한 임의 철회 값: %s"
+
+#: logsrvd/logsrvd.c:1990 logsrvd/sendlog.c:1776
+#: plugins/sudoers/cvtsudoers.c:250 plugins/sudoers/sudoreplay.c:294
+#: plugins/sudoers/visudo.c:181
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s 버전 %s\n"
+
+#: logsrvd/logsrvd_conf.c:422 plugins/sudoers/check.c:69
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/sudoers.c:419 plugins/sudoers/sudoers.c:929
+#: plugins/sudoers/sudoers.c:1034 plugins/sudoers/sudoers.c:1424
+#: plugins/sudoers/testsudoers.c:169 plugins/sudoers/testsudoers.c:285
+#: plugins/sudoers/testsudoers.c:459
+#, c-format
+msgid "unknown user %s"
+msgstr "알 수 없는 사용자 %s"
+
+#: logsrvd/logsrvd_conf.c:439 plugins/sudoers/iolog.c:148
+#: plugins/sudoers/sudoers.c:425 plugins/sudoers/sudoers.c:1458
+#: plugins/sudoers/testsudoers.c:483
+#, c-format
+msgid "unknown group %s"
+msgstr "알 수 없는 그룹 %s"
+
+#: logsrvd/logsrvd_conf.c:457
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr "%s 입출력 로그 모드를 해석할 수 없습니다"
+
+#: logsrvd/logsrvd_conf.c:474 logsrvd/logsrvd_conf.c:1243
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "부적절한 %s 값: %s"
+
+#: logsrvd/logsrvd_conf.c:527
+msgid "TLS not supported"
+msgstr "TLS를 지원하지 않습니다"
+
+#: logsrvd/logsrvd_conf.c:549
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:622 logsrvd/logsrvd_conf.c:1032
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s: 완전하지 않은 경로"
+
+#: logsrvd/logsrvd_conf.c:951 logsrvd/logsrvd_conf.c:967
+#: logsrvd/logsrvd_conf.c:1676
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "알 수 없는 syslog 수단 %s"
+
+#: logsrvd/logsrvd_conf.c:983 logsrvd/logsrvd_conf.c:999
+#: logsrvd/logsrvd_conf.c:1015 logsrvd/logsrvd_conf.c:1680
+#: logsrvd/logsrvd_conf.c:1684 logsrvd/logsrvd_conf.c:1688
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "알 수 없는 syslog 우선 순위 %s"
+
+#: logsrvd/logsrvd_conf.c:1197
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d 일치하지 않는 '[': %s"
+
+#: logsrvd/logsrvd_conf.c:1203
+#, c-format
+msgid "%s:%d garbage after ']': %s"
+msgstr "%s:%d ']' 다음 버리는 내용: %s"
+
+#: logsrvd/logsrvd_conf.c:1215
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s:%d 부적절한 설정 섹션: %s"
+
+#: logsrvd/logsrvd_conf.c:1223
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d 부적절한 설정 행: %s"
+
+#: logsrvd/logsrvd_conf.c:1229
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d(에)서 섹션 이름이 나와야 합니다: %s"
+
+#: logsrvd/logsrvd_conf.c:1251
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] 잘못된 키: %s"
+
+#: logsrvd/logsrvd_conf.c:1281 plugins/sudoers/cvtsudoers.c:273
+#: plugins/sudoers/logging.c:1076
+#, c-format
+msgid "unable to open log file %s"
+msgstr "%s 로그 파일을 열 수 없습니다"
+
+#: logsrvd/logsrvd_conf.c:1763
+msgid "unable to initialize server TLS context"
+msgstr "서버 TLS 컨텍스트를 초기화할 수 없습니다"
+
+#: logsrvd/logsrvd_conf.c:1783
+msgid "unable to initialize relay TLS context"
+msgstr "릴레이 TLS 컨텍스트를 초기화할 수 없습니다"
+
+#: logsrvd/logsrvd_journal.c:149 logsrvd/logsrvd_journal.c:430
+#: logsrvd/logsrvd_journal.c:435
+msgid "unable to create journal file"
+msgstr "저널 파일을 만들 수 없습니다"
+
+#: logsrvd/logsrvd_journal.c:153 logsrvd/logsrvd_queue.c:109
+#: plugins/sudoers/visudo.c:1046
+#, c-format
+msgid "unable to lock %s"
+msgstr "%s을(를) 잠글 수 없습니다"
+
+#: logsrvd/logsrvd_journal.c:156
+msgid "unable to lock journal file"
+msgstr "저널 파일을 잠글 수 없습니다"
+
+#: logsrvd/logsrvd_journal.c:164
+msgid "unable to open journal file"
+msgstr "저널 파일을 열 수 없습니다"
+
+#: logsrvd/logsrvd_journal.c:185 logsrvd/logsrvd_journal.c:466
+#: logsrvd/logsrvd_journal.c:471
+msgid "unable to write journal file"
+msgstr "저널 파일을 기록할 수 없습니다"
+
+#: logsrvd/logsrvd_journal.c:193 logsrvd/logsrvd_journal.c:200
+msgid "unable to rename journal file"
+msgstr "저널 파일 이름을 바꿀 수 없습니다"
+
+#: logsrvd/logsrvd_journal.c:247 logsrvd/logsrvd_journal.c:248
+#: logsrvd/logsrvd_journal.c:288 logsrvd/logsrvd_journal.c:289
+msgid "unexpected EOF reading journal file"
+msgstr "저널 파일 읽는 중 예기치 않은 파일 끝 발견"
+
+#: logsrvd/logsrvd_journal.c:251 logsrvd/logsrvd_journal.c:252
+#: logsrvd/logsrvd_journal.c:292 logsrvd/logsrvd_journal.c:293
+msgid "error reading journal file"
+msgstr "저널 파일 읽기 오류"
+
+#: logsrvd/logsrvd_journal.c:304 logsrvd/logsrvd_journal.c:390
+msgid "invalid journal file, unable to restart"
+msgstr "부적절한 저널 파일. 다시 시작할 수 없습니다"
+
+#: logsrvd/logsrvd_journal.c:449
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "%3$s 저널 파일에서 [%1$lld, %2$ld] 위치를 탐색할 수 없습니다"
+
+#: logsrvd/logsrvd_local.c:166
+#, c-format
+msgid "unexpected value_case %d in %s from %s"
+msgstr "%3$s의 %2$s에서 예기지 않은 value_case 값 %1$d"
+
+#: logsrvd/logsrvd_local.c:194
+msgid "error parsing AcceptMessage"
+msgstr "AcceptMessage 해석 오류"
+
+#: logsrvd/logsrvd_local.c:205
+msgid "error creating I/O log"
+msgstr "입출력 로그 만드는 중 오류"
+
+#: logsrvd/logsrvd_local.c:228
+msgid "error logging accept event"
+msgstr "수락 이벤트 로깅 중 오류"
+
+#: logsrvd/logsrvd_local.c:267
+msgid "error parsing RejectMessage"
+msgstr "RejectMessage 해석 오류"
+
+#: logsrvd/logsrvd_local.c:291
+msgid "error logging reject event"
+msgstr "거절 이벤트 로깅 중 오류"
+
+#: logsrvd/logsrvd_local.c:427 logsrvd/logsrvd_local.c:437
+msgid "error logging exit event"
+msgstr "끝내기 이벤트 기록 오류"
+
+#: logsrvd/logsrvd_local.c:494 logsrvd/logsrvd_local.c:495
+msgid "log is already complete, cannot be restarted"
+msgstr "로그를 이미 끝냈으며, 다시 시작할 수 없습니다"
+
+#: logsrvd/logsrvd_local.c:525
+msgid "unable to restart log"
+msgstr "로그를 다시 시작할 수 없습니다"
+
+#: logsrvd/logsrvd_local.c:541
+msgid "error parsing AlertMessage"
+msgstr "AlertMessage 해석 오류"
+
+#: logsrvd/logsrvd_local.c:551
+msgid "error logging alert event"
+msgstr "경고 이벤트 로깅 중 오류"
+
+#: logsrvd/logsrvd_local.c:587 logsrvd/logsrvd_local.c:650
+#: logsrvd/logsrvd_local.c:685
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr "길이 %d인 타이밍 버퍼를 포매팅할 수 없습니다"
+
+#: logsrvd/logsrvd_local.c:601 logsrvd/logsrvd_local.c:609
+#: logsrvd/logsrvd_local.c:657 logsrvd/logsrvd_local.c:692
+#: plugins/sudoers/sudoreplay.c:344 toke.l:981 toke.l:984
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: logsrvd/logsrvd_local.c:620
+msgid "randomly dropping connection"
+msgstr "연결이 임의로 끊김"
+
+#: logsrvd/logsrvd_local.c:632
+msgid "error writing IoBuffer"
+msgstr "입출력 버퍼 기록 중 오류"
+
+#: logsrvd/logsrvd_local.c:667
+msgid "error writing ChangeWindowSize"
+msgstr "ChangeWindowSize 기록 중 오류"
+
+#: logsrvd/logsrvd_local.c:702
+msgid "error writing CommandSuspend"
+msgstr "CommandSuspend 기록 중 오류"
+
+#: logsrvd/logsrvd_relay.c:437
+msgid "TLS handshake with relay host failed"
+msgstr "릴레이 호스트와의 TLS 핸드 셰이크 실패"
+
+#: logsrvd/logsrvd_relay.c:465
+msgid "unable to connect to relay host"
+msgstr "릴레이 호스트에 연결할 수 없습니다"
+
+#: logsrvd/logsrvd_relay.c:520
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s: 부적절한 ServerHello, server_id가 빠졌습니다"
+
+#: logsrvd/logsrvd_relay.c:522 logsrvd/sendlog.c:1111
+#: plugins/sudoers/log_client.c:1479
+msgid "invalid ServerHello"
+msgstr "부적절한 ServerHello"
+
+#: logsrvd/logsrvd_relay.c:681
+msgid "unrecognized ServerMessage type"
+msgstr "인식할 수 없는 ServerMessage 형식"
+
+#: logsrvd/logsrvd_relay.c:710
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr "릴레이 %s에서 읽기 시간 초과 (%s)"
+
+#: logsrvd/logsrvd_relay.c:712
+msgid "timeout reading from relay"
+msgstr "릴레이 데이터 읽기 시간 초과"
+
+#: logsrvd/logsrvd_relay.c:767
+msgid "relay host name does not match certificate"
+msgstr "릴레이 호스트 이름이 인증서와 일치하지 않습니다"
+
+#: logsrvd/logsrvd_relay.c:773 logsrvd/logsrvd_relay.c:787
+#: logsrvd/logsrvd_relay.c:794
+msgid "error reading from relay"
+msgstr "릴레이 데이터 읽는 중 오류"
+
+#: logsrvd/logsrvd_relay.c:815
+msgid "unable to read from relay"
+msgstr "릴레이 데이터를 읽을 수 없습니다"
+
+#: logsrvd/logsrvd_relay.c:830 logsrvd/logsrvd_relay.c:949
+msgid "relay server closed connection"
+msgstr "릴레이 서버 연결을 끊었습니다"
+
+#: logsrvd/logsrvd_relay.c:848
+msgid "server message too large"
+msgstr "서버 메시지가 너무 깁니다"
+
+#: logsrvd/logsrvd_relay.c:912
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr "릴레이 %s에 기록 시간 초과 (%s)"
+
+#: logsrvd/logsrvd_relay.c:914
+msgid "timeout writing to relay"
+msgstr "릴레이 기록 시간 초과"
+
+#: logsrvd/logsrvd_relay.c:968 logsrvd/logsrvd_relay.c:975
+#: logsrvd/logsrvd_relay.c:987
+msgid "error writing to relay"
+msgstr "릴레이 기록 중 오류"
+
+#: logsrvd/sendlog.c:124
+msgid "send sudo I/O log to remote server"
+msgstr "원격 서버에 sudo 입출력 로그를 보냅니다"
+
+#: logsrvd/sendlog.c:130
+msgid "only send an accept event (no I/O)"
+msgstr "허용 이벤트만 보냅니다 (입출력 안함)"
+
+#: logsrvd/sendlog.c:133
+msgid "certificate bundle file to verify server's cert against"
+msgstr "서버의 인증서 검증에 활용할 인증서 번들 파일"
+
+#: logsrvd/sendlog.c:135
+msgid "certificate file for TLS handshake"
+msgstr "TLS 암호 키 교환에 사용할 인증서 파일"
+
+#: logsrvd/sendlog.c:138
+msgid "host to send logs to"
+msgstr "로그를 보낼 호스트"
+
+#: logsrvd/sendlog.c:140
+msgid "remote ID of I/O log to be resumed"
+msgstr "다시 진행할 입출력 로그의 원격 ID"
+
+#: logsrvd/sendlog.c:143
+msgid "private key file"
+msgstr "개인 키 파일"
+
+#: logsrvd/sendlog.c:145
+msgid "do not verify server certificate"
+msgstr "서버 인증서를 검증하지 않습니다"
+
+#: logsrvd/sendlog.c:148
+msgid "port to use when connecting to host"
+msgstr "호스트에 연결할 때 활용할 포트 번호"
+
+#: logsrvd/sendlog.c:150
+msgid "restart previous I/O log transfer"
+msgstr "이전 입출력 로그 전송을 다시 시작합니다"
+
+#: logsrvd/sendlog.c:152
+msgid "reject the command with the given reason"
+msgstr "주어진 사유로 명령 실행을 거절합니다"
+
+#: logsrvd/sendlog.c:154
+msgid "stop transfer after reaching this time"
+msgstr "이 시간에 도달한 후 전송 중단"
+
+#: logsrvd/sendlog.c:156
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "선택한 입출력 로그를 동시에 N번 보내어 감사 서버 시험"
+
+#: logsrvd/sendlog.c:181 plugins/sudoers/log_client.c:453
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "%s:%s을(를) 찾을 수 없습니다: %s"
+
+#: logsrvd/sendlog.c:219
+msgid "unable to get server IP addr"
+msgstr "서버 IP 주소를 가져올 수 없습니다"
+
+#: logsrvd/sendlog.c:314 plugins/sudoers/sudoreplay.c:868
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "%s/%s을(를) 읽을 수 없습니다: %s"
+
+#: logsrvd/sendlog.c:1035 plugins/sudoers/iolog.c:959
+#: plugins/sudoers/iolog.c:1034
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "예기치 않은 입출력 이벤트 %d"
+
+#: logsrvd/sendlog.c:1088 logsrvd/sendlog.c:1105 logsrvd/sendlog.c:1139
+#: plugins/sudoers/log_client.c:1129 plugins/sudoers/log_client.c:1405
+#: plugins/sudoers/log_client.c:1473 plugins/sudoers/log_client.c:1512
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: 예기치 않은 상태 번호 %d"
+
+#: logsrvd/sendlog.c:1175 plugins/sudoers/log_client.c:1561
+#, c-format
+msgid "error message received from server: %s"
+msgstr "서버로부터 오류 메시지를 받았습니다: %s"
+
+#: logsrvd/sendlog.c:1188 plugins/sudoers/log_client.c:1574
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "서버로부터 중단 메시지를 받았습니다: %s"
+
+#: logsrvd/sendlog.c:1247 plugins/sudoers/log_client.c:1624
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s: 예기지 않은 type_case 값 %d"
+
+#: logsrvd/sendlog.c:1276
+msgid "timeout reading from server"
+msgstr "서버 데이터 읽기 시간 초과"
+
+#: logsrvd/sendlog.c:1327 plugins/sudoers/log_client.c:1747
+msgid "host name does not match certificate"
+msgstr "호스트 이름이 인증서와 일치하지 않습니다"
+
+#: logsrvd/sendlog.c:1361
+msgid "premature EOF"
+msgstr "갑작스러운 EOF"
+
+#: logsrvd/sendlog.c:1374 plugins/sudoers/log_client.c:1795
+#, c-format
+msgid "server message too large: %u"
+msgstr "서버 메시지가 너무 깁니다: %u"
+
+#: logsrvd/sendlog.c:1430
+msgid "timeout writing to server"
+msgstr "서버 기록 시간 초과"
+
+#: logsrvd/sendlog.c:1800
+msgid "both restart point and iolog ID must be specified"
+msgstr "다시 시작 지점과 입출력 로그 ID를 반드시 지정해야합니다"
+
+#: logsrvd/sendlog.c:1804
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "입출력을 보내지 않을 때 다시 시작 지점을 지정하지 않습니다"
+
+#: logsrvd/sendlog.c:1880
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "%d 상태로 갑자기 빠져나왔습니다"
+
+#: logsrvd/sendlog.c:1881
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "경과 시간을 서버로 보냈습니다 [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1883
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "제출 지점 정보를 서버로부터 받았습니다 [%lld, %ld]"
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:315
+msgid "TLS handshake timeout occurred"
+msgstr "TLS 핸드셰이크 시간을 초과했습니다"
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:337 plugins/sudoers/log_client.c:353
+msgid "unable to set event"
+msgstr "이벤트를 설정할 수 없습니다"
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "TLS 연결 실패: %s"
+
+#: logsrvd/tls_client.c:196
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "SSL 객체를 할당할 수 없습니다: %s"
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "SSL 객체에 소켓을 붙일 수 없습니다: %s"
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr "TLS 컨텍스트를 초기화할 수 없습니다"
+
+#: logsrvd/tls_init.c:138 logsrvd/tls_init.c:146
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "%s에 TLS 1.2 암호 모음을 설정할 수 없습니다: %s"
+
+#: logsrvd/tls_init.c:166 logsrvd/tls_init.c:174
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "%s에 TLS 1.3 암호 모음을 설정할 수 없습니다: %s"
+
+#: logsrvd/tls_init.c:206 logsrvd/tls_init.c:227
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "디피-헬먼 매개변수를 설정할 수 없습니다: %s"
+
+#: logsrvd/tls_init.c:283
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "TLS 컨텍스트를 만들 수 없습니다: %s"
+
+#: logsrvd/tls_init.c:290
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "TLS 프로토콜 최소 버전을 1.2로 설정할 수 없습니다: %s"
+
+#: plugins/sudoers/audit.c:272 plugins/sudoers/audit.c:452
+#: plugins/sudoers/log_client.c:962 plugins/sudoers/log_client.c:1011
+#: plugins/sudoers/log_client.c:1060 plugins/sudoers/log_client.c:1185
+#: plugins/sudoers/logging.c:614 plugins/sudoers/logging.c:732
+#: plugins/sudoers/logging.c:859 plugins/sudoers/logging.c:1031
+#: plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr "일시 정보를 가져올 수 없습니다"
+
+#: plugins/sudoers/auth/aix_auth.c:282
+#, c-format
+msgid "unable to change password for %s"
+msgstr "%s의 암호를 바꿀 수 없습니다"
+
+#: plugins/sudoers/auth/bsdauth.c:78
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "%s 사용자의 로그인 클래스를 가져올 수 없습니다"
+
+#: plugins/sudoers/auth/bsdauth.c:85
+msgid "invalid authentication type"
+msgstr "부적절한 인증 형식"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to begin BSD authentication"
+msgstr "BSD 인증을 시작할 수 없습니다"
+
+#: plugins/sudoers/auth/bsdauth.c:97
+msgid "unable to initialize BSD authentication"
+msgstr "BSD 인증을 초기화할 수 없습니다"
+
+#: plugins/sudoers/auth/bsdauth.c:191
+msgid "your account has expired"
+msgstr "계정 유효 기간이 지났습니다"
+
+#: plugins/sudoers/auth/bsdauth.c:193
+msgid "approval failed"
+msgstr "승인 실패"
+
+#: plugins/sudoers/auth/fwtk.c:62
+msgid "unable to read fwtk config"
+msgstr "fwtk 설정을 읽을 수 없습니다"
+
+#: plugins/sudoers/auth/fwtk.c:67
+msgid "unable to connect to authentication server"
+msgstr "인증 서버에 연결할 수 없습니다"
+
+#: plugins/sudoers/auth/fwtk.c:73 plugins/sudoers/auth/fwtk.c:99
+#: plugins/sudoers/auth/fwtk.c:131
+msgid "lost connection to authentication server"
+msgstr "인증 서버의 연결이 끊어졌습니다"
+
+#: plugins/sudoers/auth/fwtk.c:77
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"인증 서버 오류:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:116
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: 본인 정보를 문자열('%s')로 변환할 수 없습니다: %s"
+
+#: plugins/sudoers/auth/kerb5.c:166
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: '%s'을(를) 해석할 수 없습니다: %s"
+
+#: plugins/sudoers/auth/kerb5.c:175
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: 자격 정보 캐시를 해석할 수 없습니다: %s"
+
+#: plugins/sudoers/auth/kerb5.c:226
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: 옵션을 할당할 수 없습니다: %s"
+
+#: plugins/sudoers/auth/kerb5.c:241
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: 자격 정보를 가져올 수 없습니다: %s"
+
+#: plugins/sudoers/auth/kerb5.c:254
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: 자격 정보 캐시를 초기화할 수 없습니다: %s"
+
+#: plugins/sudoers/auth/kerb5.c:257
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: 캐시에 자격 정보를 저장할 수 없습니다: %s"
+
+#: plugins/sudoers/auth/kerb5.c:322
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: 호스트 정보를 가져올 수 없습니다: %s"
+
+#: plugins/sudoers/auth/kerb5.c:336
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: TGT를 검증할 수 없습니다! 공격 가능성이 있습니다!: %s"
+
+#: plugins/sudoers/auth/pam.c:233
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "PAM을 초기화할 수 없습니다: %s"
+
+#: plugins/sudoers/auth/pam.c:349
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "PAM 인증 오류: %s"
+
+#: plugins/sudoers/auth/pam.c:369
+msgid "account validation failure, is your account locked?"
+msgstr "계정 검증 실패, 계정이 잠겼습니까?"
+
+#: plugins/sudoers/auth/pam.c:380
+msgid "Account or password is expired, reset your password and try again"
+msgstr "계정 또는 암호 기한이 지났습니다. 암호를 다시 설정한 후 시도하십시오"
+
+#: plugins/sudoers/auth/pam.c:387
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "기한이 지난 암호를 바꿀 수 없습니다: %s"
+
+#: plugins/sudoers/auth/pam.c:398
+msgid "Password expired, contact your system administrator"
+msgstr "암호 기한이 지났습니다. 시스템 관리자에게 문의하십시오"
+
+#: plugins/sudoers/auth/pam.c:403
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "계정 기한이 지났거나 PAM 설정에 sudo에서 확인할 \"account\" 섹션이 빠졌습니다. 시스템 관리자에게 문의하십시오."
+
+#: plugins/sudoers/auth/pam.c:411 plugins/sudoers/auth/pam.c:416
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "PAM 계정 관리 오류: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:100 plugins/sudoers/visudo.c:266
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "%s 데이터베이스에 없습니다"
+
+#: plugins/sudoers/auth/securid5.c:76
+msgid "failed to initialise the ACE API library"
+msgstr "ACE API 라이브러리 초기화에 실패했습니다"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "unable to contact the SecurID server"
+msgstr "SecurID 서버에 연결할 수 없습니다"
+
+#: plugins/sudoers/auth/securid5.c:117
+msgid "User ID locked for SecurID Authentication"
+msgstr "SecurID 인증 과정에 사용자 ID가 잠겼습니다"
+
+#: plugins/sudoers/auth/securid5.c:121 plugins/sudoers/auth/securid5.c:174
+msgid "invalid username length for SecurID"
+msgstr "SecurID용 사용자 이름 길이가 잘못되었습니다"
+
+#: plugins/sudoers/auth/securid5.c:125 plugins/sudoers/auth/securid5.c:179
+msgid "invalid Authentication Handle for SecurID"
+msgstr "SecurID용 인증 핸들이 잘못되었습니다"
+
+#: plugins/sudoers/auth/securid5.c:129
+msgid "SecurID communication failed"
+msgstr "SecurID 통신에 실패했습니다"
+
+#: plugins/sudoers/auth/securid5.c:133 plugins/sudoers/auth/securid5.c:222
+msgid "unknown SecurID error"
+msgstr "알 수 없는 SecurID 오류"
+
+#: plugins/sudoers/auth/securid5.c:169
+msgid "invalid passcode length for SecurID"
+msgstr "SecurID용 암호 길이가 잘못되었습니다"
+
+#: plugins/sudoers/auth/sia.c:72 plugins/sudoers/auth/sia.c:130
+msgid "unable to initialize SIA session"
+msgstr "SIA 세션을 초기화할 수 없습니다"
+
+#: plugins/sudoers/auth/sudo_auth.c:141
+msgid "invalid authentication methods"
+msgstr "부적절한 인증 방식"
+
+#: plugins/sudoers/auth/sudo_auth.c:143
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "sudo에 컴파일한 인증 방식이 잘못됐습니다! 독립-비독립 인증 방식을 혼합하여 활용하면 안됩니다."
+
+#: plugins/sudoers/auth/sudo_auth.c:296 plugins/sudoers/auth/sudo_auth.c:359
+msgid "no authentication methods"
+msgstr "인증 방식 없음"
+
+#: plugins/sudoers/auth/sudo_auth.c:298
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "sudo에 컴파일한 인증 방식이 없습니다! 인증 기능을 끄려면 --disable-authentication 설정 옵션을 사용하십시오."
+
+#: plugins/sudoers/auth/sudo_auth.c:361
+msgid "Unable to initialize authentication methods."
+msgstr "인증 방식을 초기화할 수 없습니다."
+
+#: plugins/sudoers/auth/sudo_auth.c:551
+msgid "Authentication methods:"
+msgstr "인증 방식:"
+
+#: plugins/sudoers/bsm_audit.c:122 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "감사 상태를 결정할 수 없습니다"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:278
+msgid "unable to commit audit record"
+msgstr "감사 레코드를 제출할 수 없습니다"
+
+#: plugins/sudoers/check.c:63 plugins/sudoers/check.c:74
+#: plugins/sudoers/lookup.c:79 plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "알 수 없는 uid %u"
+
+#: plugins/sudoers/check.c:277
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "%s 지시 파일 읽기 오류"
+
+#: plugins/sudoers/check.c:280
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "%s 지시 파일 무시: 일반 파일이 아닙니다"
+
+#: plugins/sudoers/check.c:293
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"로컬 시스템 관리자에게 일반적인 지침을 받았으리라 믿습니다.\n"
+"보통 세가지로 요약합니다:\n"
+"\n"
+" #1) 타인의 사생활을 존중하십시오.\n"
+" #2) 입력하기 전에 한 번 더 생각하십시오.\n"
+" #3) 막강한 힘에는 상당한 책임이 뒤따릅니다.\n"
+"\n"
+
+#: plugins/sudoers/check.c:301
+msgid ""
+"For security reasons, the password you type will not be visible.\n"
+"\n"
+msgstr ""
+"보안상 사유로, 입력한 암호는 나타나지 않습니다.\n"
+"\n"
+
+#: plugins/sudoers/check_aliases.c:93
+#, c-format
+msgid "cycle in %s \"%s\""
+msgstr "%s의 사이클 \"%s\""
+
+#: plugins/sudoers/check_aliases.c:96
+#, c-format
+msgid "%s \"%s\" referenced but not defined"
+msgstr "%s \"%s\"을(를) 참조했지만 정의하지는 않았습니다"
+
+#: plugins/sudoers/cvtsudoers.c:211
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "순서 증가: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:231
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "순서 시작: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:242
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "순서 패딩: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:252 plugins/sudoers/visudo.c:183
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s 문법 버전 %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:282 plugins/sudoers/testsudoers.c:162
+#, c-format
+msgid "unsupported input format %s"
+msgstr "지원하지 않는 %s 입력 형식"
+
+#: plugins/sudoers/cvtsudoers.c:300
+#, c-format
+msgid "unsupported output format %s"
+msgstr "지원하지 않는 %s 출력 형식"
+
+#: plugins/sudoers/cvtsudoers.c:392
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: 입출력 파일은 달라야합니다"
+
+#: plugins/sudoers/cvtsudoers.c:406 plugins/sudoers/sudoers.c:151
+#: plugins/sudoers/sudoers.c:209 plugins/sudoers/testsudoers.c:315
+#: plugins/sudoers/visudo.c:276 plugins/sudoers/visudo.c:666
+msgid "unable to initialize sudoers default values"
+msgstr "sudoers 기본 값을 초기화할 수 없습니다"
+
+#: plugins/sudoers/cvtsudoers.c:533 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:612
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s: 알 수 없는 키워드 %s"
+
+#: plugins/sudoers/cvtsudoers.c:658
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "부적절한 기본 형식: %s"
+
+#: plugins/sudoers/cvtsudoers.c:681
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "부적절한 생략 형식: %s"
+
+#: plugins/sudoers/cvtsudoers.c:722 plugins/sudoers/cvtsudoers.c:738
+#, c-format
+msgid "invalid filter: %s"
+msgstr "부적절한 필터: %s"
+
+#: plugins/sudoers/cvtsudoers.c:783 plugins/sudoers/visudo.c:1000
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "%s 파일 해석에 실패했습니다. 알 수 없는 오류."
+
+#: plugins/sudoers/cvtsudoers.c:1508 plugins/sudoers/sudoreplay.c:1143
+#: plugins/sudoers/timestamp.c:353 plugins/sudoers/timestamp.c:356
+#, c-format
+msgid "unable to write to %s"
+msgstr "%s에 기록할 수 없습니다"
+
+#: plugins/sudoers/cvtsudoers.c:1536
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s - sudoers 파일 형식을 변환합니다\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1538
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"옵션:\n"
+" -b, --base=dn sudo LDAP 요청문에 사용할 기본 DN값\n"
+" -c, --config=<설정파일> 설정 파일 경로를 지정합니다\n"
+" -d, --defaults=<기본형식> 지정 <기본형식>만 변환합니다\n"
+" -e, --expand-aliases 변환시 별칭을 확장합니다.\n"
+" -f, --output-format=<형식> 출력 <형식> 지정: JSON, LDIF, sudoers\n"
+" -i, --input-format=<형식> 입력 <형식> 지정: LDIF, sudoers\n"
+" -I, --increment=<숫자> 각 sudoOrder 증가량\n"
+" -h, --help 도움말 메시지를 표시하고 빠져나갑니다\n"
+" -m, --match=<필터> <필터>에 일치하는 항목만 변환합니다\n"
+" -M, --match-local 일치 필터에서 passwd와 group 데이터베이스를 사용\n"
+" -o, --output=<출력파일> 변환한 sudoers 정보를 <출력파일>에 기록\n"
+" -O, --order-start=<숫자> sudoOrder 시작 번호\n"
+" -p, --prune-matches 일치하지 않는 사용자, 그룹, 호스트는 제외합니다\n"
+" -P, --padding=<숫자> sudoOrder 숫자를 증가할 기본 패딩값\n"
+" -s, --suppress=<섹션> 지정 <섹션> 출력은 제외합니다\n"
+" -V, --version 버전 정보를 표시하고 빠져나갑니다"
+
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:245 plugins/sudoers/cvtsudoers_ldif.c:252
+#: plugins/sudoers/cvtsudoers_ldif.c:594 plugins/sudoers/env.c:340
+#: plugins/sudoers/env.c:347 plugins/sudoers/env.c:458
+#: plugins/sudoers/ldap.c:511 plugins/sudoers/ldap.c:629
+#: plugins/sudoers/ldap.c:1003 plugins/sudoers/ldap_conf.c:219
+#: plugins/sudoers/ldap_conf.c:310 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:93 plugins/sudoers/logging.c:479
+#: plugins/sudoers/policy.c:828 plugins/sudoers/policy.c:840
+#: plugins/sudoers/prompt.c:169 plugins/sudoers/serialize_list.c:62
+#: plugins/sudoers/serialize_list.c:71 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/sudoreplay.c:1340 plugins/sudoers/sudoreplay.c:1346
+#: plugins/sudoers/sudoreplay.c:1352 plugins/sudoers/testsudoers.c:306
+#: plugins/sudoers/toke_util.c:217 toke.l:995 toke.l:1277
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "내부 오류. %s 오버플로우"
+
+#: plugins/sudoers/cvtsudoers_csv.c:454 plugins/sudoers/cvtsudoers_csv.c:468
+#: plugins/sudoers/cvtsudoers_json.c:661 plugins/sudoers/cvtsudoers_json.c:676
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:362
+#: plugins/sudoers/ldap.c:495
+msgid "unable to get GMT time"
+msgstr "GMT 시간을 가져올 수 없습니다"
+
+#: plugins/sudoers/cvtsudoers_csv.c:459 plugins/sudoers/cvtsudoers_csv.c:473
+#: plugins/sudoers/cvtsudoers_json.c:666 plugins/sudoers/cvtsudoers_json.c:681
+#: plugins/sudoers/cvtsudoers_ldif.c:354 plugins/sudoers/cvtsudoers_ldif.c:367
+#: plugins/sudoers/ldap.c:503
+msgid "unable to format timestamp"
+msgstr "타임스탬프를 형식에 맞출 수 없습니다"
+
+#: plugins/sudoers/cvtsudoers_json.c:481 plugins/sudoers/cvtsudoers_json.c:516
+#: plugins/sudoers/cvtsudoers_json.c:732
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: 알 수 없는 \"%s\" 기본 항목"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:663
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "sudoers 항목이 너무 많습니다. 최대 갯수는 %u개 입니다"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:706
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "SUDOERS_BASE 환경 변수를 설정하지 않았으며 -b 옵션을 지정하지 않았습니다."
+
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, c-format
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr "%s:%d:%d: 호스트 목록을 ALL로 바꿈"
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr "%s 별칭을 찾을 수 없습니다"
+
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, c-format
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr "%s:%d:%d: %s 별칭을 %s(으)로 바꿈"
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr "%s:%d:%d: %s 중복 별칭 제거 중"
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr "%1$s:%2$d:%3$d: %5$s:%6$d:%7$d에서 호스트별 \"%4$s\" 기본 항목 중복"
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, c-format
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr "%s:%d:%d: \"%s\"에 대한 %s 호스트를 기본으로 지정"
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr "%s:%d:%d: 호스트별 \"%s\" 기본 항목을 설정할 수 없습니다"
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr "%s:%d:%d: 하위 항목이 우선하는 기본 \"%s\" 항목 제거 중"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1088
+#, c-format
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr "%1$s:%2$d:%3$d: %4$s:%5$d:%6$d에 사용자 설정 병합"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1182
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr "%s:%d:%d: 하위 항목이 우선하는 사용자 지정 항목 제거 중"
+
+#: plugins/sudoers/def_data.c:56
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "syslog를 기록 목적으로 활용할 때의 syslog 기능: %s"
+
+#: plugins/sudoers/def_data.c:60
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "사용자 인증에 성공했을 때 사용할 syslog 우선 순위: %s"
+
+#: plugins/sudoers/def_data.c:64
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "사용자 인증에 실패했을 때 사용할 syslog 우선 순위: %s"
+
+#: plugins/sudoers/def_data.c:68
+msgid "Put OTP prompt on its own line"
+msgstr "일회용 암호 입력 프롬프트를 자체 줄에 표시"
+
+#: plugins/sudoers/def_data.c:72
+msgid "Ignore '.' in $PATH"
+msgstr "$PATH의 '.' 무시"
+
+#: plugins/sudoers/def_data.c:76
+msgid "Always send mail when sudo is run"
+msgstr "sudo를 실행할 때 항상 메일을 보냄"
+
+#: plugins/sudoers/def_data.c:80
+msgid "Send mail if user authentication fails"
+msgstr "사용자가 인증에 실패했을 때 메일을 보냄"
+
+#: plugins/sudoers/def_data.c:84
+msgid "Send mail if the user is not in sudoers"
+msgstr "사용자가 sudoer가 아닐 때 메일을 보냄"
+
+#: plugins/sudoers/def_data.c:88
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "사용자가 이 호스트의 sudoer가 아닐 때 메일을 보냄"
+
+#: plugins/sudoers/def_data.c:92
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "사용자가 명령을 실행하도록 허용하지 않았을 때 메일을 보냄"
+
+#: plugins/sudoers/def_data.c:96
+msgid "Send mail if the user tries to run a command"
+msgstr "사용자가 명령 실행을 시도했을 때 메일을 보냄"
+
+#: plugins/sudoers/def_data.c:100
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "각 사용자/tty에 타임스탬프를 따로 사용"
+
+#: plugins/sudoers/def_data.c:104
+msgid "Lecture user the first time they run sudo"
+msgstr "sudo를 처음 실행할 때 사용자에게 지침 안내"
+
+#: plugins/sudoers/def_data.c:108
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "sudo 지침 안내가 들어있는 파일: %s"
+
+#: plugins/sudoers/def_data.c:112
+msgid "Require users to authenticate by default"
+msgstr "기본적으로 사용자 인증 필요"
+
+#: plugins/sudoers/def_data.c:116
+msgid "Root may run sudo"
+msgstr "루트 사용자의 sudo 실행"
+
+#: plugins/sudoers/def_data.c:120
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "로그(비 syslog) 파일에 호스트 이름 기록"
+
+#: plugins/sudoers/def_data.c:124
+msgid "Log the year in the (non-syslog) log file"
+msgstr "로그(비 syslog) 파일에 연도 기록"
+
+#: plugins/sudoers/def_data.c:128
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "sudo에 인자를 넣어 실행하지 않으면 셸 시작"
+
+#: plugins/sudoers/def_data.c:132
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "-s 옵션으로 셸을 시작할 때 $HOME을 대상 사용자로 설정"
+
+#: plugins/sudoers/def_data.c:136
+msgid "Always set $HOME to the target user's home directory"
+msgstr "항상 $HOME을 대상 사용자의 내 폴더로 설정"
+
+#: plugins/sudoers/def_data.c:140
+msgid "Allow some information gathering to give useful error messages"
+msgstr "쓸만한 오류 메시지를 제공할 목적으로 일부 정보 수집 허용"
+
+#: plugins/sudoers/def_data.c:144
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "sudoers 파일에 완전한 형태를 갖춘 호스트 이름 필요"
+
+#: plugins/sudoers/def_data.c:148
+msgid "Insult the user when they enter an incorrect password"
+msgstr "올바르지 않은 암호를 입력했을 때 사용자 놀리기"
+
+#: plugins/sudoers/def_data.c:152
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "tty를 보유한 사용자만 sudo 실행 허용"
+
+#: plugins/sudoers/def_data.c:156
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "EDITOR 환경 변수 대신 visudo 사용"
+
+#: plugins/sudoers/def_data.c:160
+msgid "Prompt for root's password, not the users's"
+msgstr "사용자 암호가 아닌 루트 암호 요구"
+
+#: plugins/sudoers/def_data.c:164
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "사용자 암호가 아닌 runas_default 사용자 암호 요구"
+
+#: plugins/sudoers/def_data.c:168
+msgid "Prompt for the target user's password, not the users's"
+msgstr "사용자 암호가 아닌 대상 사용자 암호 요구"
+
+#: plugins/sudoers/def_data.c:172
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "대상 사용자 로그인 클래스가 있다면 기본값 적용"
+
+#: plugins/sudoers/def_data.c:176
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "LOGNAME 및 USER 환경 변수 설정"
+
+#: plugins/sudoers/def_data.c:180
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "실제 uid가 아닌 대상 사용자에게 유효한 uid 설정"
+
+#: plugins/sudoers/def_data.c:184
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "대상 사용자의 그룹 벡터 초기화 안함"
+
+#: plugins/sudoers/def_data.c:188
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "로그 파일 줄을 바꿀 줄의 한계 길이(0 값은 줄 바꿈 안함): %u"
+
+#: plugins/sudoers/def_data.c:192
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "인증 타임스탬프 제한 시간: %.1f분"
+
+#: plugins/sudoers/def_data.c:196
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "암호 요구 제한시간: %.1f분"
+
+#: plugins/sudoers/def_data.c:200
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "암호 입력 시도 횟수: %u"
+
+#: plugins/sudoers/def_data.c:204
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "사용자가 활용할 umask 또는 0777: 0%o"
+
+#: plugins/sudoers/def_data.c:208
+#, c-format
+msgid "Path to log file: %s"
+msgstr "로그 파일 경로: %s"
+
+#: plugins/sudoers/def_data.c:212
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "메일 프로그램 경로: %s"
+
+#: plugins/sudoers/def_data.c:216
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "메일 프로그램 플래그: %s"
+
+#: plugins/sudoers/def_data.c:220
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "메일을 보낼 주소: %s"
+
+#: plugins/sudoers/def_data.c:224
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "메일을 보내려는 주소: %s"
+
+#: plugins/sudoers/def_data.c:228
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "메일 메시지 제목 줄: %s"
+
+#: plugins/sudoers/def_data.c:232
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "올바르지 않은 암호 메시지: %s"
+
+#: plugins/sudoers/def_data.c:236
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "지침 상태 디렉터리 경로: %s"
+
+#: plugins/sudoers/def_data.c:240
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "인증 타임스탬프 디렉터리 경로: %s"
+
+#: plugins/sudoers/def_data.c:244
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "인증 타임스탬프 디렉터리 소유자: %s"
+
+#: plugins/sudoers/def_data.c:248
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "암호와 PATH 변수 요구를 하지 않을 이 그룹의 사용자: %s"
+
+#: plugins/sudoers/def_data.c:252
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "기본 암호 프롬프트: %s"
+
+#: plugins/sudoers/def_data.c:256
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "설정하면 모든 경우의 시스템 프롬프트 대신 이 암호 프롬프트를 사용합니다."
+
+#: plugins/sudoers/def_data.c:260
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "명령을 실행할 기본 사용자: %s"
+
+#: plugins/sudoers/def_data.c:264
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "사용자의 $PATH를 대신할 값: %s"
+
+#: plugins/sudoers/def_data.c:268
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "visudo에서 사용할 편집기 경로: %s"
+
+#: plugins/sudoers/def_data.c:272
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "'list' 유사 명령 실행시 암호가 필요할 때: %s"
+
+#: plugins/sudoers/def_data.c:276
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "'verify' 유사 명령 실행시 암호가 필요할 때: %s"
+
+#: plugins/sudoers/def_data.c:280
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "exec 함수를 대신하는 sudo_noexec 라이브러리를 미리 불러옵니다"
+
+#: plugins/sudoers/def_data.c:284
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "LDAP 디렉터리가 동작 중이라면 로컬 sudoers 파일을 무시합니다"
+
+#: plugins/sudoers/def_data.c:288
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "%d보다 큰 파일 서술자는 명령을 실행하기 전에 닫습니다"
+
+#: plugins/sudoers/def_data.c:292
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "이 값을 설정하면 -C 옵션으로 \"closefrom\" 값을 대신 사용합니다"
+
+#: plugins/sudoers/def_data.c:296
+msgid "Allow users to set arbitrary environment variables"
+msgstr "사용자가 환경 변수 값을 임의대로 설정할 수 있게 합니다"
+
+#: plugins/sudoers/def_data.c:300
+msgid "Reset the environment to a default set of variables"
+msgstr "변수 기본 설정 값으로 환경 초기화"
+
+#: plugins/sudoers/def_data.c:304
+msgid "Environment variables to check for safety:"
+msgstr "안전 검사 대상 환경 변수:"
+
+#: plugins/sudoers/def_data.c:308
+msgid "Environment variables to remove:"
+msgstr "제거할 환경 변수:"
+
+#: plugins/sudoers/def_data.c:312
+msgid "Environment variables to preserve:"
+msgstr "유지할 환경 변수:"
+
+#: plugins/sudoers/def_data.c:316
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "새 보안 컨텍스트에 사용할 SELinux 역할: %s"
+
+#: plugins/sudoers/def_data.c:320
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "새 보안 컨텍스트에 사용할 SELinux 형식: %s"
+
+#: plugins/sudoers/def_data.c:324
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "sudo용 환경 파일 경로: %s"
+
+#: plugins/sudoers/def_data.c:328
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "sudo 전용 환경 파일 경로: %s"
+
+#: plugins/sudoers/def_data.c:332
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "sudoers 파일을 해석할 때 사용할 로캘: %s"
+
+#: plugins/sudoers/def_data.c:336
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "암호가 나타나더라도 sudo에서 암호 입력 요구 허용"
+
+#: plugins/sudoers/def_data.c:340
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "사용자 입력이 있을 때 암호 프롬프트에서 시각 반응 처리"
+
+#: plugins/sudoers/def_data.c:344
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "덜 정확하지만 파일 시스템에 접근하지 않는 빠른 비교 검사 사용"
+
+#: plugins/sudoers/def_data.c:348
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "sudoers에 지정한 umask 값이 관대한 권한이라 하더라도 사용자의 umask 값으로 적용"
+
+#: plugins/sudoers/def_data.c:352
+msgid "Log user's input for the command being run"
+msgstr "실행 명령에 대한 사용자 입력 기록"
+
+#: plugins/sudoers/def_data.c:356
+msgid "Log the command's standard input if not connected to a terminal"
+msgstr "터미널에 연결하지 않았을 경우 명령 표준 입력을 기록"
+
+#: plugins/sudoers/def_data.c:360
+msgid "Log the user's terminal input for the command being run"
+msgstr "실행 명령의 터미널 입력을 기록합니다"
+
+#: plugins/sudoers/def_data.c:364
+msgid "Log the output of the command being run"
+msgstr "실행 명령에 대한 출력 기록"
+
+#: plugins/sudoers/def_data.c:368
+msgid "Log the command's standard output if not connected to a terminal"
+msgstr "터미널에 연결하지 않았을 경우 명령 표준 출력을 기록"
+
+#: plugins/sudoers/def_data.c:372
+msgid "Log the command's standard error if not connected to a terminal"
+msgstr "터미널에 연결하지 않았을 경우 명령 표준 오류를 기록"
+
+#: plugins/sudoers/def_data.c:376
+msgid "Log the terminal output of the command being run"
+msgstr "실행 명령의 터미널 출력을 기록합니다"
+
+#: plugins/sudoers/def_data.c:380
+msgid "Compress I/O logs using zlib"
+msgstr "zlib로 입출력 로그 압축"
+
+#: plugins/sudoers/def_data.c:384
+msgid "Always run commands in a pseudo-tty"
+msgstr "항상 명령을 유사 tty에서 실행"
+
+#: plugins/sudoers/def_data.c:388
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "비 유닉스 그룹을 지원하는 플러그인: %s"
+
+#: plugins/sudoers/def_data.c:392
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "입출력 로그를 저장할 디렉터리: %s"
+
+#: plugins/sudoers/def_data.c:396
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "입출력 로그를 저장할 파일: %s"
+
+#: plugins/sudoers/def_data.c:400
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "pty를 할당할 때 utmp/utmpx 파일에 항목 추가"
+
+#: plugins/sudoers/def_data.c:404
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "utmp의 사용자를 실제 실행 사용자가 아닌 대리 실행 사용자로 설정"
+
+#: plugins/sudoers/def_data.c:408
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "권한 허용 설정: %s"
+
+#: plugins/sudoers/def_data.c:412
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "권한 제한 설정: %s"
+
+#: plugins/sudoers/def_data.c:416
+msgid "Run commands on a pty in the background"
+msgstr "백그라운드의 pty에서 명령을 실행합니다"
+
+#: plugins/sudoers/def_data.c:420
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "사용할 PAM 서비스 이름: %s"
+
+#: plugins/sudoers/def_data.c:424
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "로그인 셸에서 사용할 PAM 서비스 이름: %s"
+
+#: plugins/sudoers/def_data.c:428
+#, c-format
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr "sudo를 -A 옵션으로 실행할 때 활용할 PAM 서비스 이름: %s"
+
+#: plugins/sudoers/def_data.c:432
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "대상 사용자의 PAM 인증 처리 시도합니다"
+
+#: plugins/sudoers/def_data.c:436
+msgid "Create a new PAM session for the command to run in"
+msgstr "실행할 명령에 새 PAM 세션을 만듭니다"
+
+#: plugins/sudoers/def_data.c:440
+msgid "Perform PAM account validation management"
+msgstr "PAM 계정 검증 관리를 수행합니다"
+
+#: plugins/sudoers/def_data.c:444
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "최대 입출력 로그 순차 번호: %s"
+
+#: plugins/sudoers/def_data.c:448
+msgid "Enable sudoers netgroup support"
+msgstr "sudoers에 네트워크 그룹 지원 활성화"
+
+#: plugins/sudoers/def_data.c:452
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "sudoedit로 파일을 편집할 때 상위 디렉터리 기록 가능 여부 확인"
+
+#: plugins/sudoers/def_data.c:456
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "sudoedit로 파일을 편집할 때 심볼릭 링크 따라감"
+
+#: plugins/sudoers/def_data.c:460
+msgid "Query the group plugin for unknown system groups"
+msgstr "알 수 없는 시스템 그룹에 그룹 플러그인 요청"
+
+#: plugins/sudoers/def_data.c:464
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "user, host, domain 전체 튜플을 기반으로 네트워크 그룹 비교"
+
+#: plugins/sudoers/def_data.c:468
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "sudo에서 감시 로그를 기록할 수 없을 경우에도 명령 실행 허용"
+
+#: plugins/sudoers/def_data.c:472
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "sudo에서 입출력 로그를 기록할 수 없을 경우에도 명령 실행 허용"
+
+#: plugins/sudoers/def_data.c:476
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "sudo에서 로그 파일에 기록할 수 없을 경우에도 명령 실행 허용"
+
+#: plugins/sudoers/def_data.c:480
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "sudoers의 그룹을 해석하고 그룹 이름이 아닌 ID와 비교"
+
+#: plugins/sudoers/def_data.c:484
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "이 값보다 큰 로그 항목은 다수의 syslog 메시지로 나눕니다: %u"
+
+#: plugins/sudoers/def_data.c:488
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "입출력 로그 파일을 소유할 사용자: %s"
+
+#: plugins/sudoers/def_data.c:492
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "입출력 로그 파일을 소유할 그룹: %s"
+
+#: plugins/sudoers/def_data.c:496
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "입출력 로그 파일에 사용할 파일 모드: 0%o"
+
+#: plugins/sudoers/def_data.c:500
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "경로가 아닌 파일 서술자로 명령어 실행: %s"
+
+#: plugins/sudoers/def_data.c:504
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "경고를 출력하는 대신 sudoers에서 알 수 없는 기본 항목을 무시"
+
+#: plugins/sudoers/def_data.c:508
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "명령 처리가 끝난 후의 초 단위 시간: %u"
+
+#: plugins/sudoers/def_data.c:512
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "사용자가 명령행에서 제한 시간을 지정하도록 허용"
+
+#: plugins/sudoers/def_data.c:516
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "입출력 로그 데이터를 버퍼링하는 대신 즉시 디스크로 플러싱"
+
+#: plugins/sudoers/def_data.c:520
+msgid "Include the process ID when logging via syslog"
+msgstr "syslog로 로깅할 때 프로세스 ID 포함"
+
+#: plugins/sudoers/def_data.c:524
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "인증 타임스탬프 레코드 형식: %s"
+
+#: plugins/sudoers/def_data.c:528
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "인증 실패 메시지: %s"
+
+#: plugins/sudoers/def_data.c:532
+msgid "Ignore case when matching user names"
+msgstr "사용자 이름 비교시 대소문자 무시"
+
+#: plugins/sudoers/def_data.c:536
+msgid "Ignore case when matching group names"
+msgstr "그룹 이름 비교시 대소문자 무시"
+
+#: plugins/sudoers/def_data.c:540
+msgid "Log when a command is allowed by sudoers"
+msgstr "sudoers에서 명령을 허용할 때 기록"
+
+#: plugins/sudoers/def_data.c:544
+msgid "Log when a command is denied by sudoers"
+msgstr "sudoers에서 명령을 거절할 때 기록"
+
+#: plugins/sudoers/def_data.c:548
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "개별 포트 정보를 추가하여 연결할 sudo 로그 서버"
+
+#: plugins/sudoers/def_data.c:552
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "초 단위 sudo 로그 서버 제한 시간: %u"
+
+#: plugins/sudoers/def_data.c:556
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "연결한 로그 서버 소켓에 SO_KEEPALIVE 소켓 옵션 활성화"
+
+#: plugins/sudoers/def_data.c:560
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "감사 서버의 CA 번들 파일 경로: %s"
+
+#: plugins/sudoers/def_data.c:564
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "sudoers 인증 파일 경로: %s"
+
+#: plugins/sudoers/def_data.c:568
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "sudoers 개인 키 파일 경로: %s"
+
+#: plugins/sudoers/def_data.c:572
+msgid "Verify that the log server's certificate is valid"
+msgstr "로그 서버 인증서 유효성 검증"
+
+#: plugins/sudoers/def_data.c:576
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "사용자/그룹 ID로의 알 수 없는 실행 허용"
+
+#: plugins/sudoers/def_data.c:580
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "유효한 셸에서 사용자가 명령을 실행할 경우만 허용"
+
+#: plugins/sudoers/def_data.c:584
+msgid "Set the pam remote user to the user running sudo"
+msgstr "sudo를 실행하는 사용자를 PAM 원격 사용자로 설정"
+
+#: plugins/sudoers/def_data.c:588
+msgid "Set the pam remote host to the local host name"
+msgstr "로컬 호스트 이름에 PAM 원격 사용자 설정"
+
+#: plugins/sudoers/def_data.c:592
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "명령 실행 전 바꿀 작업 디렉터리: %s"
+
+#: plugins/sudoers/def_data.c:596
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "명령 실행 전 바꿀 루트 디렉터리: %s"
+
+#: plugins/sudoers/def_data.c:600
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "로그 기록 형식: %s"
+
+#: plugins/sudoers/def_data.c:604
+msgid "Enable SELinux RBAC support"
+msgstr "SELinux RBAC 지원을 사용합니다"
+
+#: plugins/sudoers/def_data.c:608
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "sudo를 처음 실행할 때 만든 파일의 경로: %s"
+
+#: plugins/sudoers/def_data.c:612
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "추가 명령을 가로채고 sudoer 제한을 적용합니다"
+
+#: plugins/sudoers/def_data.c:616
+msgid "Log sub-commands run by the original command"
+msgstr "원본 명령으로 실행하는 하위 명령 기록"
+
+#: plugins/sudoers/def_data.c:620
+msgid "Log the exit status of commands"
+msgstr "실행 명령 끝내기 상태 기록"
+
+#: plugins/sudoers/def_data.c:624
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr "가로챈 세션에서의 순차 명령 실행시 인증해야 합니다"
+
+#: plugins/sudoers/def_data.c:628
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr "setuid 또는 setgid 프로그램을 실행할 가로채기 명령 실행 허용"
+
+#: plugins/sudoers/def_data.c:632
+#, c-format
+msgid "The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr "프로세스 주소 영역을 확장할 최대 크기(바이트 단위): %s"
+
+#: plugins/sudoers/def_data.c:636
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr "코어 덤프 파일 최대 생성 크기(바이트 단위): %s"
+
+#: plugins/sudoers/def_data.c:640
+#, c-format
+msgid "The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr "프로세스 최대 CPU 사용 시간(초 단위): %s"
+
+#: plugins/sudoers/def_data.c:644
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr "프로세스 데이터 세그먼트 최대 크기(바이트 단위): %s"
+
+#: plugins/sudoers/def_data.c:648
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr "프로세스에서 만들 최대 파일 크기(바이트 단위): %s"
+
+#: plugins/sudoers/def_data.c:652
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr "프로세스 실행 최대 잠금 횟수: %s"
+
+#: plugins/sudoers/def_data.c:656
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr "메모리에서 잠글 프로세스 최대 크기(바이트 단위): %s"
+
+#: plugins/sudoers/def_data.c:660
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr "프로세스에서 열 파일 최대 갯수: %s"
+
+#: plugins/sudoers/def_data.c:664
+#, c-format
+msgid "The maximum number of processes that the user may run simultaneously: %s"
+msgstr "사용자가 동시 실행할 최대 프로세스 갯수: %s"
+
+#: plugins/sudoers/def_data.c:668
+#, c-format
+msgid "The maximum size to which the process's resident set size may grow (in bytes): %s"
+msgstr "프로세스 상주시 최대 확장 크기(바이트 단위): %s"
+
+#: plugins/sudoers/def_data.c:672
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr "프로세스 스택 크기 증가 최대 크기(바이트 단위): %s"
+
+#: plugins/sudoers/def_data.c:676
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr "비 대화식 상태에서도 인증 시도"
+
+#: plugins/sudoers/def_data.c:680
+msgid "Store plaintext passwords in I/O log input"
+msgstr "I/O 로그 입력시 원문 암호 저장"
+
+#: plugins/sudoers/def_data.c:684
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr "암호 프롬프트 대조시 사용할 정규 표현식 목록"
+
+#: plugins/sudoers/def_data.c:688
+#, c-format
+msgid "The mechanism used by the intercept and log_subcmds options: %s"
+msgstr "intercept 옵션과 log_subcmds 옵션에서 지원하는 매커니즘: %s"
+
+#: plugins/sudoers/def_data.c:692
+msgid "Attempt to verify the command and arguments after execution"
+msgstr "실행 후 명령 및 인자 검증 시도"
+
+#: plugins/sudoers/def_data.c:696
+#, c-format
+msgid "AppArmor profile to use in the new security context: %s"
+msgstr "새 보안 컨텍스트에서 활용할 AppArmor 프로파일: %s"
+
+#: plugins/sudoers/defaults.c:207
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "알 수 없는 \"%s\" 기본 항목"
+
+#: plugins/sudoers/defaults.c:251
+#, c-format
+msgid "no value specified for \"%s\""
+msgstr "\"%s\"에 지정한 값이 없습니다"
+
+#: plugins/sudoers/defaults.c:260
+#, c-format
+msgid "invalid operator \"%c=\" for \"%s\""
+msgstr "\"%2$s\"의 부적절한 연산자 \"%1$c=\""
+
+#: plugins/sudoers/defaults.c:292
+#, c-format
+msgid "option \"%s\" does not take a value"
+msgstr "\"%s\" 옵션에 값이 없습니다"
+
+#: plugins/sudoers/defaults.c:319
+#, c-format
+msgid "invalid Defaults type 0x%x for option \"%s\""
+msgstr "\"%2$s\" 옵션의 부적절한 기본 형식 0x%1$x"
+
+#: plugins/sudoers/defaults.c:326
+#, c-format
+msgid "value \"%s\" is invalid for option \"%s\""
+msgstr "\"%s\" 값은 \"%s\" 옵션에 맞지 않습니다"
+
+#: plugins/sudoers/defaults.c:1176 plugins/sudoers/policy.c:213
+#: plugins/sudoers/policy.c:222
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr "\"%s\" 경로 이름이 너무 깁니다"
+
+#: plugins/sudoers/defaults.c:1182
+#, c-format
+msgid "values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "\"%s\" 값은 '/', '~', '*' 문자로 시작해야합니다"
+
+#: plugins/sudoers/defaults.c:1189
+#, c-format
+msgid "values for \"%s\" must start with a '/'"
+msgstr "\"%s\" 값은 '/' 문자로 시작해야합니다"
+
+#: plugins/sudoers/display.c:160
+#, c-format
+msgid "LDAP Role: %s\n"
+msgstr "LDAP 역할: %s\n"
+
+#: plugins/sudoers/display.c:163
+#, c-format
+msgid "Sudoers entry: %s\n"
+msgstr "Sudoers 항목: %s\n"
+
+#: plugins/sudoers/display.c:166
+msgid " RunAsUsers: "
+msgstr " 실행 사용자: "
+
+#: plugins/sudoers/display.c:181
+msgid " RunAsGroups: "
+msgstr " 실행 그룹: "
+
+#: plugins/sudoers/display.c:191
+msgid " Options: "
+msgstr " 옵션: "
+
+#: plugins/sudoers/display.c:255
+msgid " Commands:\n"
+msgstr " 명령:\n"
+
+#: plugins/sudoers/display.c:478
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "%2$s에서 %1$s에 일치하는 기본 항목:\n"
+
+#: plugins/sudoers/display.c:496
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "%s의 실행 권한 및 명령별 기본 값:\n"
+
+#: plugins/sudoers/display.c:514
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "%s 사용자는 %s에서 다음 명령을 실행해야 합니다:\n"
+
+#: plugins/sudoers/display.c:530
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "%s 사용자는 %s에서 sudo를 실행하도록 허가받지 않았습니다.\n"
+
+#: plugins/sudoers/editor.c:180
+#, c-format
+msgid "ignoring editor: %.*s"
+msgstr "편집기 무시: %.*s"
+
+#: plugins/sudoers/editor.c:181
+msgid "editor arguments may not contain \"--\""
+msgstr "편집기 인자에 \"--\"를 넣으면 안됩니다"
+
+#: plugins/sudoers/env.c:426
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: envp가 깨졌습니다. 길이가 일치하지 않습니다"
+
+#: plugins/sudoers/env.c:1119
+msgid "unable to rebuild the environment"
+msgstr "환경 구성을 다시 갖출 수 없습니다"
+
+#: plugins/sudoers/env.c:1199
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "죄송하지만 다음 환경 변수를 설정하도록 허가받지 않았습니다: %s"
+
+#: plugins/sudoers/filedigest.c:50
+#, c-format
+msgid "unsupported digest type %u for %s"
+msgstr "%2$s에서 지원하지 않는 다이제스트 형식 %1$u"
+
+#: plugins/sudoers/filedigest.c:77
+#, c-format
+msgid "%s: read error"
+msgstr "%s: 읽기 오류"
+
+#: plugins/sudoers/group_plugin.c:169 plugins/sudoers/sssd.c:578
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "%s을(를) 불러올 수 없습니다: %s"
+
+#: plugins/sudoers/group_plugin.c:181
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "%s에서 \"group_plugin\" 심볼을 찾을 수 없습니다"
+
+#: plugins/sudoers/group_plugin.c:186
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: 호환되지 않는 그룹 플러그인 주 버전 %d입니다. %d이(가) 필요합니다."
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "\"%s\" IP 주소를 해석할 수 없습니다"
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "\"%s\" 네트워크 마스크 주소를 해석할 수 없습니다"
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "로컬 IP 주소 및 넷마스크 쌍:\n"
+
+#: plugins/sudoers/iolog.c:694
+msgid "unable to update sequence file"
+msgstr "시퀀스 파일을 업데이트할 수 없습니다"
+
+#: plugins/sudoers/iolog.c:728 plugins/sudoers/iolog.c:917
+#: plugins/sudoers/iolog.c:1080 plugins/sudoers/iolog.c:1087
+#: plugins/sudoers/iolog.c:1209 plugins/sudoers/iolog.c:1216
+#: plugins/sudoers/iolog.c:1316 plugins/sudoers/iolog.c:1323
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "입출력 로그에 기록할 수 없습니다: %s"
+
+#: plugins/sudoers/iolog.c:736
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "%s/%s을(를) 만들 수 없습니다"
+
+#: plugins/sudoers/iolog.c:965
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: 내부 오류. 이벤트 %d 번의 입출력 로그 파일을 열지 않았습니다"
+
+#: plugins/sudoers/iolog.c:1065 plugins/sudoers/iolog.c:1194
+#: plugins/sudoers/iolog.c:1300 plugins/sudoers/timestamp.c:897
+#: plugins/sudoers/timestamp.c:989 plugins/sudoers/visudo.c:555
+#: plugins/sudoers/visudo.c:561
+msgid "unable to read the clock"
+msgstr "클록을 읽을 수 없습니다"
+
+#: plugins/sudoers/iolog.c:1292 plugins/sudoers/log_client.c:1203
+#: plugins/sudoers/log_client.c:1213 plugins/sudoers/log_client.c:1217
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: 내부 오류. 부적절한 시그널 %d번"
+
+#: plugins/sudoers/ldap.c:154 plugins/sudoers/ldap_conf.c:289
+msgid "starttls not supported when using ldaps"
+msgstr "ldaps를 사용할 때 starttls를 지원하지 않습니다"
+
+#: plugins/sudoers/ldap.c:226
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "SSL 인증서 및 키 DB를 초기화할 수 없습니다: %s"
+
+#: plugins/sudoers/ldap.c:229
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "SSL을 사용하려면 %s에서 TLS_CERT를 설정해야 합니다"
+
+#: plugins/sudoers/ldap.c:1593
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "LDAP를 초기화할 수 없습니다: %s"
+
+#: plugins/sudoers/ldap.c:1630
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls를 지정했지만 LDAP 라이브러리에서 ldap_start_tls_s() 또는 ldap_start_tls_s_np() 함수를 지원하지 않습니다"
+
+#: plugins/sudoers/ldap.c:1767 plugins/sudoers/parse_ldif.c:745
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "부적절한 sudoOrder 속성: %s"
+
+#: plugins/sudoers/ldap_conf.c:197
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: 포트 번호가 너무 큽니다"
+
+#: plugins/sudoers/ldap_conf.c:258
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "지원하지 않는 LDAP URI 형식: %s"
+
+#: plugins/sudoers/ldap_conf.c:285
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "ldap 및 ldaps URI를 함께 사용할 수 없습니다"
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "sudoOption 복제: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "sudoOption을 변환할 수 없습니다: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "감시 시스템을 열 수 없습니다"
+
+#: plugins/sudoers/linux_audit.c:104
+msgid "unable to send audit message"
+msgstr "감시 메시지를 보낼 수 없습니다"
+
+#: plugins/sudoers/log_client.c:125 plugins/sudoers/log_client.c:412
+#: plugins/sudoers/log_client.c:1450 plugins/sudoers/log_client.c:2076
+msgid "error in event loop"
+msgstr "이벤트 루프 오류"
+
+#: plugins/sudoers/log_client.c:205
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "SSL_CTX 객체 만들기 실패: %s"
+
+#: plugins/sudoers/log_client.c:230
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "%s 인증서 인증 번들을 불러올 수 없습니다"
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "%s 인증서를 불러올 수 없습니다"
+
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "unable to load private key %s"
+msgstr "%s 개인 키를 불러올 수 없습니다"
+
+#: plugins/sudoers/log_client.c:275
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "SSL 객체를 할당할 수 없습니다: %s"
+
+#: plugins/sudoers/log_client.c:364 plugins/sudoers/log_client.c:369
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "%s:%s로의 TLS 연결 실패: %s"
+
+#: plugins/sudoers/log_client.c:545
+msgid "TLS initialization was unsuccessful"
+msgstr "TLS 초기화에 실패했습니다"
+
+#: plugins/sudoers/log_client.c:555
+msgid "TLS handshake was unsuccessful"
+msgstr "TLS 핸드셰이킹에 실패했습니다"
+
+#: plugins/sudoers/log_client.c:1221
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: 내부 오류. 부적절한 종료 상태 %d"
+
+#: plugins/sudoers/log_client.c:1757 plugins/sudoers/log_client.c:1782
+msgid "lost connection to log server"
+msgstr "로그 서버의 연결이 끊어졌습니다"
+
+#: plugins/sudoers/log_client.c:1859
+msgid "missing write buffer"
+msgstr "기록 버퍼 빠짐"
+
+#: plugins/sudoers/log_client.c:2015
+msgid "unable to connect to log server"
+msgstr "로그 서버에 연결할 수 없습니다"
+
+#: plugins/sudoers/logging.c:295
+msgid "user NOT in sudoers"
+msgstr "사용자가 sudoers에 없습니다"
+
+#: plugins/sudoers/logging.c:297
+msgid "user NOT authorized on host"
+msgstr "사용자가 호스트에서 인증하지 않았습니다"
+
+#: plugins/sudoers/logging.c:299
+msgid "command not allowed"
+msgstr "명령을 허용하지 않았습니다"
+
+#: plugins/sudoers/logging.c:320
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr "%s은(는) sudoers 파일에 없습니다.\n"
+
+#: plugins/sudoers/logging.c:323
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr "%s 사용자는 %s에서 sudo를 실행할 수 없습니다.\n"
+
+#: plugins/sudoers/logging.c:326
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "죄송하지만, %s 사용자는 %s에서 sudo를 실행하면 안됩니다.\n"
+
+#: plugins/sudoers/logging.c:339
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s%s' as %s%s%s on %s.\n"
+msgstr "죄송하지만 %1$s 사용자는 '%2$s%3$s%4$s%5$s'을(를) %9$s의 %6$s%7$s%8$s(으)로 실행하도록 허가받지 않았습니다.\n"
+
+#: plugins/sudoers/logging.c:350
+msgid "This incident has been reported to the administrator.\n"
+msgstr "이번 시도는 관리자에게 보고했습니다.\n"
+
+#: plugins/sudoers/logging.c:387 plugins/sudoers/sudoers.c:547
+#: plugins/sudoers/sudoers.c:549 plugins/sudoers/sudoers.c:551
+#: plugins/sudoers/sudoers.c:553 plugins/sudoers/sudoers.c:777
+#: plugins/sudoers/sudoers.c:779
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: 명령이 없습니다"
+
+#: plugins/sudoers/logging.c:389 plugins/sudoers/sudoers.c:543
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"'.'에 무시 중인 \"%1$s\" 요소가 있습니다.\n"
+"\"%3$s\" 명령을 실행하려면, \"sudo ./%2$s\" 명령을 사용하십시오."
+
+#: plugins/sudoers/logging.c:409
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "잘못된 암호 입력 시도 %u번"
+
+#: plugins/sudoers/logging.c:500
+msgid "authentication failure"
+msgstr "인증 실패"
+
+#: plugins/sudoers/logging.c:539 plugins/sudoers/logging.c:558
+msgid "a password is required"
+msgstr "암호가 필요합니다"
+
+#: plugins/sudoers/logging.c:881
+msgid "problem parsing sudoers"
+msgstr "sudoers 해석 문제"
+
+#: plugins/sudoers/logging.c:922 plugins/sudoers/logging.c:930
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr "%s:%d:%d: %s"
+
+#: plugins/sudoers/logging.c:1108
+#, c-format
+msgid "unable to write log file %s"
+msgstr "%s 로그 파일에 기록할 수 없습니다"
+
+#: plugins/sudoers/match_digest.c:107
+#, c-format
+msgid "digest for %s (%s) bad length %zu, expected %zu"
+msgstr "%1$s 다이제스트(%2$s)는 %4$zu 길이를 기대했지만 잘못된 %3$zu 길이를 가졌습니다"
+
+#: plugins/sudoers/match_digest.c:126
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "%s 다이제스트(%s)는 %s 형식이 아닙니다"
+
+#: plugins/sudoers/parse_ldif.c:615
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "미완결 sudoRole 무시: cn: %s"
+
+#: plugins/sudoers/parse_ldif.c:675
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "부적절한 LDIF 속성: %s"
+
+#: plugins/sudoers/parser_warnx.c:56
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: plugins/sudoers/parser_warnx.c:59
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s: %s\n"
+
+#: plugins/sudoers/pivot.c:71
+msgid "unable to restore root directory"
+msgstr "루트 디렉터리를 복원할 수 없습니다"
+
+#: plugins/sudoers/pivot.c:79
+msgid "unable to restore current working directory"
+msgstr "현재 작업 디렉터리를 복원할 수 없습니다"
+
+#: plugins/sudoers/policy.c:78 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "sudo 프론트엔드의 %.*s 설정이 잘못되었습니다"
+
+#: plugins/sudoers/policy.c:364 plugins/sudoers/testsudoers.c:329
+msgid "unable to parse network address list"
+msgstr "네트워크 주소 목록을 해석할 수 없습니다"
+
+#: plugins/sudoers/policy.c:556
+msgid "user name not set by sudo front-end"
+msgstr "sudo 프론트엔드에서 사용자 이름을 설정하지 않았습니다"
+
+#: plugins/sudoers/policy.c:560
+msgid "user-ID not set by sudo front-end"
+msgstr "sudo 프론트엔드에서 사용자 ID를 설정하지 않았습니다"
+
+#: plugins/sudoers/policy.c:564
+msgid "group-ID not set by sudo front-end"
+msgstr "sudo 프론트엔드에서 그룹 ID를 지정하지 않았습니다"
+
+#: plugins/sudoers/policy.c:568
+msgid "host name not set by sudo front-end"
+msgstr "sudo 프론트엔드에서 호스트 이름을 설정하지 않았습니다"
+
+#: plugins/sudoers/policy.c:757
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "부적절한 작업 디렉터리: %s"
+
+#: plugins/sudoers/policy.c:944
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "부적절한 루트 변경 디렉터리: %s"
+
+#: plugins/sudoers/policy.c:1153 plugins/sudoers/visudo.c:919
+#: plugins/sudoers/visudo.c:1218
+#, c-format
+msgid "unable to execute %s"
+msgstr "%s을(를) 실행할 수 없습니다"
+
+#: plugins/sudoers/policy.c:1225 plugins/sudoers/policy.c:1260
+#: plugins/sudoers/policy.c:1282 plugins/sudoers/policy.c:1300
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: sudo 프론트엔드의 상태 플래그가 잘못되었습니다: 0x%x"
+
+#: plugins/sudoers/policy.c:1323
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Sudoers 정책 플러그인 버전 %s\n"
+
+#: plugins/sudoers/policy.c:1325
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Sudoers 파일 문법 버전 %d\n"
+
+#: plugins/sudoers/policy.c:1329
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Sudoers 경로: %s\n"
+
+#: plugins/sudoers/policy.c:1332
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "nsswitch 경로: %s\n"
+
+#: plugins/sudoers/policy.c:1335
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "ldap.conf 경로: %s\n"
+
+#: plugins/sudoers/policy.c:1337
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "ldap.secret 경로: %s\n"
+
+#: plugins/sudoers/policy.c:1370
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "%d 형식의 후크를 등록할 수 없습니다(버전 %d.%d)"
+
+#: plugins/sudoers/policy.c:1388
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "%d 형식의 후크 등록을 해제할 수 없습니다(버전 %d.%d)"
+
+#: plugins/sudoers/pwutil.c:242 plugins/sudoers/pwutil.c:260
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "%u uid를 캐시에 적재할 수 없습니다"
+
+#: plugins/sudoers/pwutil.c:254
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "%u uid를 캐시에 적재할 수 없습니다. 이미 존재합니다."
+
+#: plugins/sudoers/pwutil.c:314 plugins/sudoers/pwutil.c:332
+#: plugins/sudoers/pwutil.c:395 plugins/sudoers/pwutil.c:440
+#, c-format
+msgid "unable to cache user %s"
+msgstr "%s 사용자를 캐시에 적재할 수 없습니다"
+
+#: plugins/sudoers/pwutil.c:327
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "%s 사용자를 캐시에 적재할 수 없습니다. 이미 존재합니다."
+
+#: plugins/sudoers/pwutil.c:559 plugins/sudoers/pwutil.c:577
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "%u GID를 캐시에 적재할 수 없습니다"
+
+#: plugins/sudoers/pwutil.c:571
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "%u gid를 캐시에 적재할 수 없습니다. 이미 존재합니다."
+
+#: plugins/sudoers/pwutil.c:625 plugins/sudoers/pwutil.c:643
+#: plugins/sudoers/pwutil.c:704 plugins/sudoers/pwutil.c:753
+#, c-format
+msgid "unable to cache group %s"
+msgstr "%s 그룹을 캐시에 적재할 수 없습니다"
+
+#: plugins/sudoers/pwutil.c:638
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "%s 그룹을 캐시에 적재할 수 없습니다. 이미 존재합니다."
+
+#: plugins/sudoers/pwutil.c:900 plugins/sudoers/pwutil.c:985
+#: plugins/sudoers/pwutil.c:1039 plugins/sudoers/pwutil.c:1095
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "%s 그룹 목록을 캐시에 적재할 수 없습니다. 이미 존재합니다."
+
+#: plugins/sudoers/pwutil.c:906 plugins/sudoers/pwutil.c:990
+#: plugins/sudoers/pwutil.c:1045 plugins/sudoers/pwutil.c:1100
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "%s 그룹 목록을 캐시에 적재할 수 없습니다"
+
+#: plugins/sudoers/pwutil.c:979
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "%s 그룹을 해석할 수 없습니다"
+
+#: plugins/sudoers/pwutil.c:1089
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "%s 그룹 ID를 해석할 수 없습니다"
+
+#: plugins/sudoers/set_perms.c:120 plugins/sudoers/set_perms.c:457
+#: plugins/sudoers/set_perms.c:870 plugins/sudoers/set_perms.c:1186
+#: plugins/sudoers/set_perms.c:1490
+msgid "perm stack overflow"
+msgstr "권한 스택 오버플로우"
+
+#: plugins/sudoers/set_perms.c:131 plugins/sudoers/set_perms.c:387
+#: plugins/sudoers/set_perms.c:468 plugins/sudoers/set_perms.c:736
+#: plugins/sudoers/set_perms.c:881 plugins/sudoers/set_perms.c:1109
+#: plugins/sudoers/set_perms.c:1197 plugins/sudoers/set_perms.c:1422
+#: plugins/sudoers/set_perms.c:1501 plugins/sudoers/set_perms.c:1592
+msgid "perm stack underflow"
+msgstr "권한 스택 언더플로우"
+
+#: plugins/sudoers/set_perms.c:191 plugins/sudoers/set_perms.c:515
+#: plugins/sudoers/set_perms.c:1251 plugins/sudoers/set_perms.c:1535
+msgid "unable to change to root gid"
+msgstr "루트 gid로 바꿀 수 없습니다"
+
+#: plugins/sudoers/set_perms.c:282 plugins/sudoers/set_perms.c:612
+#: plugins/sudoers/set_perms.c:1013 plugins/sudoers/set_perms.c:1328
+msgid "unable to change to runas gid"
+msgstr "실행 gid로 바꿀 수 없습니다"
+
+#: plugins/sudoers/set_perms.c:287 plugins/sudoers/set_perms.c:617
+#: plugins/sudoers/set_perms.c:1018 plugins/sudoers/set_perms.c:1333
+msgid "unable to set runas group vector"
+msgstr "실행 그룹 벡터를 설정할 수 없습니다"
+
+#: plugins/sudoers/set_perms.c:298 plugins/sudoers/set_perms.c:628
+#: plugins/sudoers/set_perms.c:1027 plugins/sudoers/set_perms.c:1342
+msgid "unable to change to runas uid"
+msgstr "실행 uid로 바꿀 수 없습니다"
+
+#: plugins/sudoers/set_perms.c:320 plugins/sudoers/set_perms.c:650
+#: plugins/sudoers/set_perms.c:1047 plugins/sudoers/set_perms.c:1362
+msgid "unable to change to sudoers gid"
+msgstr "sudoers gid로 바꿀 수 없습니다"
+
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579
+msgid "too many processes"
+msgstr "동작 중인 프로세스가 너무 많습니다"
+
+#: plugins/sudoers/solaris_audit.c:62
+msgid "unable to get current working directory"
+msgstr "현재 작업 디렉터리를 가져올 수 없습니다"
+
+#: plugins/sudoers/solaris_audit.c:70
+#, c-format
+msgid "truncated audit path ctx->user.cmnd: %s"
+msgstr "ctx->user_cmnd 감사 경로가 잘렸습니다: %s"
+
+#: plugins/sudoers/solaris_audit.c:77
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "argv[0] 감사 경로가 잘렸습니다: %s"
+
+#: plugins/sudoers/sssd.c:581
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "SSS 소스를 초기화할 수 없습니다. 머신에 SSSD를 설치했습니까?"
+
+#: plugins/sudoers/sssd.c:589 plugins/sudoers/sssd.c:598
+#: plugins/sudoers/sssd.c:607 plugins/sudoers/sssd.c:616
+#: plugins/sudoers/sssd.c:625
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "%2$s에서 \"%1$s\" 심볼을 찾을 수 없습니다"
+
+#: plugins/sudoers/sudoers.c:250
+#, c-format
+msgid "unable to get defaults from %s"
+msgstr "%s의 기본값을 가져올 수 없습니다"
+
+#: plugins/sudoers/sudoers.c:259
+msgid "no valid sudoers sources found, quitting"
+msgstr "올바른 sudoers 설정 원본이 없습니다. 나갑니다."
+
+#: plugins/sudoers/sudoers.c:366
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers에서 root가 sudo를 실행하지 못하게 지정했습니다"
+
+#: plugins/sudoers/sudoers.c:375
+msgid "user not allowed to override closefrom limit"
+msgstr "사용자가 closefrom 제한 값을 따로 적용하도록 허용하지 않았습니다"
+
+#: plugins/sudoers/sudoers.c:376
+msgid "you are not permitted to use the -C option"
+msgstr "-C 옵션 사용을 허가받지 않았습니다"
+
+#: plugins/sudoers/sudoers.c:440
+msgid "no tty"
+msgstr "tty 없음"
+
+#: plugins/sudoers/sudoers.c:441
+msgid "sorry, you must have a tty to run sudo"
+msgstr "죄송하지만 sudo를 실행하려면 tty를 확보해야합니다"
+
+#: plugins/sudoers/sudoers.c:449
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "%s 사용자에게 부적절한 셸 제공: %s"
+
+#: plugins/sudoers/sudoers.c:491
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "%s을(를) 루트 디렉터리로 변환하도록 허용하지 않습니다"
+
+#: plugins/sudoers/sudoers.c:493
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "-R 옵션과 %s 옵션의 병행 사용을 허가받지 않았습니다"
+
+#: plugins/sudoers/sudoers.c:506
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "%s 디렉터리로의 이동을 허용하지 않습니다"
+
+#: plugins/sudoers/sudoers.c:507
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "-D 옵션과 %s 옵션의 병행 사용을 허가받지 않았습니다"
+
+#: plugins/sudoers/sudoers.c:542
+msgid "command in current directory"
+msgstr "현재 디렉터리의 명령"
+
+#: plugins/sudoers/sudoers.c:557
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr "\"cd\"는 셸 내장 명령으로, 직접 실행할 수 없습니다."
+
+#: plugins/sudoers/sudoers.c:559
+msgid "the -s option may be used to run a privileged shell."
+msgstr "-s 옵션은 별도 권한을 부여한 셸에서 실행할 때 사용합니다."
+
+#: plugins/sudoers/sudoers.c:561
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr "-D 옵션은 지정 디렉터리에서 명령을 실행할 때 사용합니다."
+
+#: plugins/sudoers/sudoers.c:570
+msgid "user not allowed to set a command timeout"
+msgstr "사용자가 명령 처리 제한 시간을 설정하도록 허용하지 않았습니다"
+
+#: plugins/sudoers/sudoers.c:572
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "죄송하지만, 명령 처리 제한 시간을 설정할 수 없습니다"
+
+#: plugins/sudoers/sudoers.c:580
+msgid "user not allowed to preserve the environment"
+msgstr "사용자가 환경 설정 값을 유지하도록 허용하지 않았습니다"
+
+#: plugins/sudoers/sudoers.c:582
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "죄송하지만 이 환경 상태를 유지하도록 허가받지 않았습니다"
+
+#: plugins/sudoers/sudoers.c:618
+msgid "no command specified"
+msgstr "지정한 명령이 없음"
+
+#: plugins/sudoers/sudoers.c:759
+msgid "error setting user-specified environment variables"
+msgstr "사용자 지정 환경 변수 설정 오류"
+
+#: plugins/sudoers/sudoers.c:1211
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "sudoedit는 sudo로 실행할 필요가 없습니다"
+
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:1613
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "%s을(를) 읽을 수 없습니다"
+
+#: plugins/sudoers/sudoers.c:1321 plugins/sudoers/visudo.c:1123
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s은(는) 일반 파일이 아닙니다"
+
+#: plugins/sudoers/sudoers.c:1325 plugins/sudoers/timestamp.c:272 toke.l:1355
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s은(는) %u uid가 소유했지만, %u uid가 소유해야합니다"
+
+#: plugins/sudoers/sudoers.c:1330 plugins/sudoers/timestamp.c:279 toke.l:1360
+#, c-format
+msgid "%s is world writable"
+msgstr "%s에 모두가 기록할 수 있습니다"
+
+#: plugins/sudoers/sudoers.c:1334 plugins/sudoers/timestamp.c:284 toke.l:1363
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s은(는) %u gid가 소유했지만, %u gid가 소유해야합니다"
+
+#: plugins/sudoers/sudoers.c:1363
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "루트만 \"-c %s\" 옵션을 사용할 수 있습니다"
+
+#: plugins/sudoers/sudoers.c:1382
+#, c-format
+msgid "unknown login class %s"
+msgstr "알 수 없는 로그인 클래스 %s"
+
+#: plugins/sudoers/sudoers_cb.c:120 plugins/sudoers/sudoers_cb.c:135
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "%s 호스트를 해석할 수 없습니다"
+
+#: plugins/sudoers/sudoreplay.c:252
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "부적절한 필터 옵션: %s"
+
+#: plugins/sudoers/sudoreplay.c:268
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "부적절한 최대 대기 시간 값: %s"
+
+#: plugins/sudoers/sudoreplay.c:291
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "부적절한 속도 인수: %s"
+
+#: plugins/sudoers/sudoreplay.c:326
+#, c-format
+msgid "invalid time offset %s"
+msgstr "부적절한 시간 오프셋 %s"
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:340
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/timing: %s"
+
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "sudo 세션 재현 중: %s"
+
+#: plugins/sudoers/sudoreplay.c:634
+msgid "unable to set tty to raw mode"
+msgstr "RAW 모드로 tty를 설정할 수 없습니다"
+
+#: plugins/sudoers/sudoreplay.c:685
+msgid "Warning: your terminal is too small to properly replay the log."
+msgstr "경고: 터미널 화면이 로그를 제대로 나타내기에 너무 작습니다."
+
+#: plugins/sudoers/sudoreplay.c:686
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "로그 화면 크기는 %d x %d 이지만, 터미널 화면 크기는 %d x %d 입니다."
+
+#: plugins/sudoers/sudoreplay.c:714
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "재현에 끝났습니다. 터미널을 복원하려면 아무 키나 누르십시오."
+
+#: plugins/sudoers/sudoreplay.c:1217 plugins/sudoers/sudoreplay.c:1247
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "모호한 식 \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1269
+msgid "unmatched ')' in expression"
+msgstr "수식에 일치하지 않는 ')'"
+
+#: plugins/sudoers/sudoreplay.c:1273
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "알 수 없는 검색어 \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1288
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s에 인자가 필요합니다"
+
+#: plugins/sudoers/sudoreplay.c:1298
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "\"%s\" 날짜를 해석할 수 없습니다"
+
+#: plugins/sudoers/sudoreplay.c:1307
+msgid "unmatched '(' in expression"
+msgstr "수식에 일치하지 않는 '('"
+
+#: plugins/sudoers/sudoreplay.c:1309
+msgid "illegal trailing \"or\""
+msgstr "잘못된 후위 연산자 \"or\""
+
+#: plugins/sudoers/sudoreplay.c:1311
+msgid "illegal trailing \"!\""
+msgstr "잘못된 후위 문자 \"!\""
+
+#: plugins/sudoers/sudoreplay.c:1417
+#, c-format
+msgid "unknown search type %d"
+msgstr "알 수 없는 검색 형식 %d"
+
+#: plugins/sudoers/sudoreplay.c:1679
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "사용법: %s [-hnRS] [-d <디렉터리>] [-m <숫자>] [-s <숫자>] <ID>\n"
+
+#: plugins/sudoers/sudoreplay.c:1681
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "사용법: %s [-h] [-d <디렉터리>] -l [<검색식>]\n"
+
+#: plugins/sudoers/sudoreplay.c:1695
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - sudo 세션 로그를 보여줍니다\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1697
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"옵션:\n"
+" -d, --directory=<디렉터리> 세션 로그 디렉터리를 지정합니다\n"
+" -f, --filter=<필터> 화면에 나타낼 입출력 형식을 지정합니다\n"
+" -h, --help 도움말 메시지를 나타낸 후 빠져나갑니다\n"
+" -l, --list 유효한 세션 ID 및 추가 표현식을 목록으로 보여줍니다\n"
+" -m, --max-wait=<숫자> 이벤트 처리간 초 단위 최대 대기 시간\n"
+" -n, --non-interactive 프롬프트를 표시하지 않고 세션을 표준출력으로 보냅니다\n"
+" -R, --no-resize 터미널 크기 조정 시도를 하지 않습니다\n"
+" -S, -suspend-wait 명령 실행을 멈추는 동안 대기합니다\n"
+" -s, --speed=<숫자> 출력 속도를 올리거나 내립니다\n"
+" -V, --version 버전 정보를 나타낸 후 빠져나갑니다"
+
+#: plugins/sudoers/testsudoers.c:392
+#, c-format
+msgid ""
+"\n"
+"Invalid shell for user %s: %s\n"
+msgstr ""
+"\n"
+"%s 사용자에게 부적절한 셸 제공: %s\n"
+
+#: plugins/sudoers/testsudoers.c:411
+msgid ""
+"\n"
+"Password required"
+msgstr ""
+"\n"
+"암호가 필요합니다"
+
+#: plugins/sudoers/testsudoers.c:422
+msgid ""
+"\n"
+"Parse error"
+msgstr ""
+"\n"
+"해석 오류"
+
+#: plugins/sudoers/testsudoers.c:425
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"명령 허용함"
+
+#: plugins/sudoers/testsudoers.c:428
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"명령 거부함"
+
+#: plugins/sudoers/testsudoers.c:431
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"명령이 일치하지 않음"
+
+#: plugins/sudoers/timestamp.c:364 plugins/sudoers/timestamp.c:711
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "타임스탬프 파일을 %lld 바이트로 자를 수 없습니다"
+
+#: plugins/sudoers/timestamp.c:908
+msgid "ignoring time stamp from the future"
+msgstr "미래 타임스탬프 값 무시"
+
+#: plugins/sudoers/timestamp.c:931
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "타임스탬프 값이 미래 값으로 너무 밀려있습니다: %20.20s"
+
+#: plugins/sudoers/timestamp.c:1067
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "%s 타임스탬프 파일을 잠글 수 없습니다"
+
+#: plugins/sudoers/timestamp.c:1114
+#, c-format
+msgid "%s:%d:%d timestampowner: unknown user %s"
+msgstr "%s:%d:%d timestampowner: 알 수 없는 %s 사용자"
+
+#: plugins/sudoers/toke_util.c:159
+msgid "sudoedit should not be specified with a path"
+msgstr "sudoedit에 경로를 지정하면 안됩니다"
+
+#: plugins/sudoers/visudo.c:308 plugins/sudoers/visudo.c:714
+#, c-format
+msgid "press return to edit %s: "
+msgstr "%s 항목을 편집하려면 return 키를 누르십시오: "
+
+#: plugins/sudoers/visudo.c:323
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "%s에 편집 세션 내용이 남았습니다"
+
+#: plugins/sudoers/visudo.c:401
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "지정 편집기(%s)가 없습니다"
+
+#: plugins/sudoers/visudo.c:406
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "편집기가 없습니다(편집기 경로 = %s)"
+
+#: plugins/sudoers/visudo.c:494 plugins/sudoers/visudo.c:786
+#, c-format
+msgid "unable to stat %s"
+msgstr "%s의 상태를 가져올 수 없습니다"
+
+#: plugins/sudoers/visudo.c:514 plugins/sudoers/visudo.c:522
+msgid "write error"
+msgstr "쓰기 오류"
+
+#: plugins/sudoers/visudo.c:568
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "임시 파일 상태를 가져올 수 없습니다(%s). %s을(를) 바꾸지 않았습니다"
+
+#: plugins/sudoers/visudo.c:575
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "임시 파일 길이가 0입니다(%s). %s을(를) 바꾸지 않았습니다"
+
+#: plugins/sudoers/visudo.c:581
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "편집기(%s) 실패. %s을(를) 바꾸지 않았습니다"
+
+#: plugins/sudoers/visudo.c:613
+#, c-format
+msgid "%s unchanged"
+msgstr "%s 바꾸지 않음"
+
+#: plugins/sudoers/visudo.c:661
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "임시 파일(%s)을 다시 열 수 없습니다. %s을(를) 바꾸지 않았습니다."
+
+#: plugins/sudoers/visudo.c:674
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "임시 파일(%s)을 해석할 수 없습니다. 알 수 없는 오류"
+
+#: plugins/sudoers/visudo.c:760 plugins/sudoers/visudo.c:790
+#: plugins/sudoers/visudo.c:797
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "%s의 uid/gid를 %u/%u 값으로 설정할 수 없습니다"
+
+#: plugins/sudoers/visudo.c:825
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s 및 %s은(는) 동일한 파일 시스템에 없습니다. mv 명령으로 이름을 바꿉니다"
+
+#: plugins/sudoers/visudo.c:836
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "명령 실행 실패: '%s %s %s', %s을(를) 바꾸지 않았습니다"
+
+#: plugins/sudoers/visudo.c:843
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "%s 이름 바꾸기 오류. %s을(를) 바꾸지 않았습니다"
+
+#: plugins/sudoers/visudo.c:864
+msgid "What now? "
+msgstr "어떻게 하시겠습니까? "
+
+#: plugins/sudoers/visudo.c:878
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"사용할 수 있는 옵션:\n"
+" sudoers 파일을 다시 편집합니다(E)\n"
+" sudoers 파일을 바꾼 상태에서 저장하지 않고 나갑니다(X)\n"
+" sudoers 파일을 바꾼 상태에서 저장하고 끝냅니다(Q)\n"
+
+#: plugins/sudoers/visudo.c:923
+#, c-format
+msgid "unable to run %s"
+msgstr "%s을(를) 실행할 수 없음"
+
+#: plugins/sudoers/visudo.c:954
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: 잘못된 소유자 uid/gid를 %u/%u 값으로 설정해야 합니다\n"
+
+#: plugins/sudoers/visudo.c:965
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: 잘못된 권한입니다. 0%o 모드 값을 설정해야 합니다\n"
+
+#: plugins/sudoers/visudo.c:1017 plugins/sudoers/visudo.c:1024
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: 해석 성공\n"
+
+#: plugins/sudoers/visudo.c:1043
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s을(를) 사용중입니다. 나중에 다시 시도하십시오"
+
+#: plugins/sudoers/visudo.c:1047
+msgid "Edit anyway? [y/N]"
+msgstr "그래도 편집하시겠습니까? [y/N]"
+
+#: plugins/sudoers/visudo.c:1206
+msgid "the -x option will be removed in a future release"
+msgstr "-x 옵션은 추후 릴리스에서 제거 예정입니다"
+
+#: plugins/sudoers/visudo.c:1208
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "cvtsudoers 유틸리티를 대신 사용해보십시오"
+
+#: plugins/sudoers/visudo.c:1228
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "경고: %s:%d:%d 사용하지 않는 %s \"%s\"이(가) 있습니다"
+
+#: plugins/sudoers/visudo.c:1341
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - sudoers 파일을 안전하게 편집합니다\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1343
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -I, --no-includes do not edit include files\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"옵션:\n"
+" -c, --check 확인 전용 모드\n"
+" -f, --file=sudoers sudoers 파일 위치를 지정합니다\n"
+" -h, --help 도움말 메시지를 나타낸 후 빠져나갑니다\n"
+" -I, --no-includes 인클루드 파일을 편집하지 않습니다\n"
+" -q, --quiet 자세한 문법 오류 메시지를 줄입니다(없앰)\n"
+" -s, --strict 엄격한 문법 검사를 시행합니다\n"
+" -V, --version 버전 정보를 나타낸 후 빠져나갑니다\n"
+
+#: toke.l:184
+msgid "empty string"
+msgstr "빈 문자열"
+
+#: toke.l:196 toke.l:566
+msgid "empty group"
+msgstr "빈 그룹"
+
+#: toke.l:206 toke.l:564
+msgid "empty netgroup"
+msgstr "빈 네트워크 그룹"
+
+#: toke.l:284
+msgid "unterminated regular expression"
+msgstr "끝나지 않은 정규 표현식"
+
+#: toke.l:358 toke.l:370 toke.l:382 toke.l:398 toke.l:417 toke.l:457
+msgid "invalid line continuation"
+msgstr "부적절한 연속 문자"
+
+#: toke.l:603 toke.l:615
+msgid "invalid IPv6 address"
+msgstr "부적절한 IPv6 주소"
+
+#: toke.l:863
+msgid "unexpected line break in string"
+msgstr "예기치 않은 개행 문자 발견"
+
+#: toke.l:982
+msgid "ignoring editor backup file"
+msgstr "편집기 백업 파일 무시"
+
+#: toke.l:985
+msgid "ignoring file name containing '.'"
+msgstr "'.' 문자가 들어간 파일 이름 무시"
+
+#: toke.l:1310
+msgid "too many levels of includes"
+msgstr "포함 레벨이 너무 많습니다"
diff --git a/plugins/sudoers/po/lt.mo b/plugins/sudoers/po/lt.mo
new file mode 100644
index 0000000..1d2e70d
--- /dev/null
+++ b/plugins/sudoers/po/lt.mo
Binary files differ
diff --git a/plugins/sudoers/po/lt.po b/plugins/sudoers/po/lt.po
new file mode 100644
index 0000000..8db0e29
--- /dev/null
+++ b/plugins/sudoers/po/lt.po
@@ -0,0 +1,1682 @@
+# SOME DESCRIPTIVE TITLE.
+# This file is put in the public domain.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# Algimantas Margevičius <margevicius.algimantas@gmail.com>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.8.4rc1\n"
+"Report-Msgid-Bugs-To: http://www.sudo.ws/bugs\n"
+"POT-Creation-Date: 2012-02-06 15:48-0500\n"
+"PO-Revision-Date: 2012-02-25 11:56+0200\n"
+"Last-Translator: Algimantas Margevičius <margevicius.algimantas@gmail.com>\n"
+"Language-Team: Lithuanian <komp_lt@konferencijos.lt>\n"
+"Language: lt\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
+
+#: plugins/sudoers/alias.c:125
+#, c-format
+msgid "Alias `%s' already defined"
+msgstr ""
+
+#: plugins/sudoers/bsm_audit.c:61 plugins/sudoers/bsm_audit.c:64
+#: plugins/sudoers/bsm_audit.c:113 plugins/sudoers/bsm_audit.c:117
+#: plugins/sudoers/bsm_audit.c:169 plugins/sudoers/bsm_audit.c:173
+msgid "getaudit: failed"
+msgstr ""
+
+#: plugins/sudoers/bsm_audit.c:91 plugins/sudoers/bsm_audit.c:154
+msgid "Could not determine audit condition"
+msgstr ""
+
+#: plugins/sudoers/bsm_audit.c:102
+msgid "getauid failed"
+msgstr ""
+
+#: plugins/sudoers/bsm_audit.c:104 plugins/sudoers/bsm_audit.c:163
+msgid "au_open: failed"
+msgstr ""
+
+#: plugins/sudoers/bsm_audit.c:119 plugins/sudoers/bsm_audit.c:175
+msgid "au_to_subject: failed"
+msgstr ""
+
+#: plugins/sudoers/bsm_audit.c:123 plugins/sudoers/bsm_audit.c:179
+msgid "au_to_exec_args: failed"
+msgstr ""
+
+#: plugins/sudoers/bsm_audit.c:127 plugins/sudoers/bsm_audit.c:188
+msgid "au_to_return32: failed"
+msgstr ""
+
+#: plugins/sudoers/bsm_audit.c:130 plugins/sudoers/bsm_audit.c:191
+msgid "unable to commit audit record"
+msgstr ""
+
+#: plugins/sudoers/bsm_audit.c:161
+msgid "getauid: failed"
+msgstr ""
+
+#: plugins/sudoers/bsm_audit.c:184
+msgid "au_to_text: failed"
+msgstr ""
+
+#: plugins/sudoers/check.c:158
+#, c-format
+msgid "sorry, a password is required to run %s"
+msgstr ""
+
+#: plugins/sudoers/check.c:249 plugins/sudoers/iolog.c:172
+#: plugins/sudoers/sudoers.c:992 plugins/sudoers/sudoreplay.c:348
+#: plugins/sudoers/sudoreplay.c:357 plugins/sudoers/sudoreplay.c:703
+#: plugins/sudoers/sudoreplay.c:797 plugins/sudoers/visudo.c:790
+#, c-format
+msgid "unable to open %s"
+msgstr ""
+
+#: plugins/sudoers/check.c:253 plugins/sudoers/iolog.c:202
+#, c-format
+msgid "unable to write to %s"
+msgstr ""
+
+#: plugins/sudoers/check.c:261 plugins/sudoers/check.c:506
+#: plugins/sudoers/check.c:556 plugins/sudoers/iolog.c:123
+#: plugins/sudoers/iolog.c:156
+#, c-format
+msgid "unable to mkdir %s"
+msgstr ""
+
+#: plugins/sudoers/check.c:396
+#, c-format
+msgid "internal error, expand_prompt() overflow"
+msgstr ""
+
+#: plugins/sudoers/check.c:456
+#, c-format
+msgid "timestamp path too long: %s"
+msgstr ""
+
+#: plugins/sudoers/check.c:485 plugins/sudoers/check.c:529
+#: plugins/sudoers/iolog.c:158
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr ""
+
+#: plugins/sudoers/check.c:488 plugins/sudoers/check.c:532
+#: plugins/sudoers/check.c:577
+#, c-format
+msgid "%s owned by uid %u, should be uid %u"
+msgstr ""
+
+#: plugins/sudoers/check.c:493 plugins/sudoers/check.c:537
+#, c-format
+msgid "%s writable by non-owner (0%o), should be mode 0700"
+msgstr ""
+
+#: plugins/sudoers/check.c:501 plugins/sudoers/check.c:545
+#: plugins/sudoers/check.c:613 plugins/sudoers/sudoers.c:978
+#: plugins/sudoers/visudo.c:320 plugins/sudoers/visudo.c:582
+#, c-format
+msgid "unable to stat %s"
+msgstr ""
+
+#: plugins/sudoers/check.c:571
+#, c-format
+msgid "%s exists but is not a regular file (0%o)"
+msgstr ""
+
+#: plugins/sudoers/check.c:583
+#, c-format
+msgid "%s writable by non-owner (0%o), should be mode 0600"
+msgstr ""
+
+#: plugins/sudoers/check.c:637
+#, c-format
+msgid "timestamp too far in the future: %20.20s"
+msgstr ""
+
+#: plugins/sudoers/check.c:684
+#, c-format
+msgid "unable to remove %s (%s), will reset to the epoch"
+msgstr ""
+
+#: plugins/sudoers/check.c:692
+#, c-format
+msgid "unable to reset %s to the epoch"
+msgstr ""
+
+#: plugins/sudoers/check.c:752 plugins/sudoers/check.c:758
+#: plugins/sudoers/sudoers.c:829 plugins/sudoers/sudoers.c:833
+#, c-format
+msgid "unknown uid: %u"
+msgstr ""
+
+#: plugins/sudoers/check.c:755 plugins/sudoers/sudoers.c:770
+#: plugins/sudoers/sudoers.c:1108 plugins/sudoers/testsudoers.c:218
+#: plugins/sudoers/testsudoers.c:362
+#, c-format
+msgid "unknown user: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:27
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:31
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:35
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:39
+msgid "Put OTP prompt on its own line"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:43
+msgid "Ignore '.' in $PATH"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:47
+msgid "Always send mail when sudo is run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:51
+msgid "Send mail if user authentication fails"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:55
+msgid "Send mail if the user is not in sudoers"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:59
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:63
+msgid "Send mail if the user is not allowed to run a command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:67
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:71
+msgid "Lecture user the first time they run sudo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:75
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:79
+msgid "Require users to authenticate by default"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:83
+msgid "Root may run sudo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:87
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:91
+msgid "Log the year in the (non-syslog) log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:95
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:99
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:103
+msgid "Always set $HOME to the target user's home directory"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:107
+msgid "Allow some information gathering to give useful error messages"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:111
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:115
+msgid "Insult the user when they enter an incorrect password"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:119
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:123
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:127
+msgid "Prompt for root's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:131
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:135
+msgid "Prompt for the target user's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:139
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:143
+msgid "Set the LOGNAME and USER environment variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:147
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:151
+msgid "Don't initialize the group vector to that of the target user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:155
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %d"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:159
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:163
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:167
+#, c-format
+msgid "Number of tries to enter a password: %d"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:171
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:175
+#, c-format
+msgid "Path to log file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:179
+#, c-format
+msgid "Path to mail program: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:183
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:187
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:191
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:195
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:199
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:203
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:207
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:211
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:215
+#, c-format
+msgid "Default password prompt: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:219
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr ""
+
+#: plugins/sudoers/def_data.c:223
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:227
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:231
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:235
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:239
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:243
+msgid "Preload the dummy exec functions contained in \"_PATH_SUDO_NOEXEC"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:247
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:251
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:255
+msgid "If set, users may override the value of `closefrom' with the -C option"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:259
+msgid "Allow users to set arbitrary environment variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:263
+msgid "Reset the environment to a default set of variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:267
+msgid "Environment variables to check for sanity:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:271
+msgid "Environment variables to remove:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:275
+msgid "Environment variables to preserve:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:279
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:283
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:287
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:291
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:295
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:299
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:303
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:307
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:311
+msgid "Log user's input for the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:315
+msgid "Log the output of the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:319
+msgid "Compress I/O logs using zlib"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:323
+msgid "Always run commands in a pseudo-tty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:327
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:331
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:335
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:339
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:343
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:208
+#, c-format
+msgid "unknown defaults entry `%s'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:216 plugins/sudoers/defaults.c:226
+#: plugins/sudoers/defaults.c:246 plugins/sudoers/defaults.c:259
+#: plugins/sudoers/defaults.c:272 plugins/sudoers/defaults.c:285
+#: plugins/sudoers/defaults.c:298 plugins/sudoers/defaults.c:318
+#: plugins/sudoers/defaults.c:328
+#, c-format
+msgid "value `%s' is invalid for option `%s'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:219 plugins/sudoers/defaults.c:229
+#: plugins/sudoers/defaults.c:237 plugins/sudoers/defaults.c:254
+#: plugins/sudoers/defaults.c:267 plugins/sudoers/defaults.c:280
+#: plugins/sudoers/defaults.c:293 plugins/sudoers/defaults.c:313
+#: plugins/sudoers/defaults.c:324
+#, c-format
+msgid "no value specified for `%s'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:242
+#, c-format
+msgid "values for `%s' must start with a '/'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:304
+#, c-format
+msgid "option `%s' does not take a value"
+msgstr ""
+
+#: plugins/sudoers/env.c:258
+#, c-format
+msgid "internal error, sudo_setenv() overflow"
+msgstr ""
+
+#: plugins/sudoers/env.c:291
+#, c-format
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr ""
+
+#: plugins/sudoers/env.c:710
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr ""
+
+#: plugins/sudoers/find_path.c:69 plugins/sudoers/find_path.c:108
+#: plugins/sudoers/find_path.c:123 plugins/sudoers/iolog.c:125
+#: plugins/sudoers/sudoers.c:923 toke.l:668 toke.l:823
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: gram.y:110
+#, c-format
+msgid ">>> %s: %s near line %d <<<"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:91
+#, c-format
+msgid "%s%s: %s"
+msgstr "%s%s: %s"
+
+#: plugins/sudoers/group_plugin.c:103
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s turi priklausyti uid %d"
+
+#: plugins/sudoers/group_plugin.c:107
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr "%s turi būti įrašomas tik savininkui"
+
+#: plugins/sudoers/group_plugin.c:114
+#, c-format
+msgid "unable to dlopen %s: %s"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:119
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:124
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:112
+msgid "Local IP address and netmask pairs:\n"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:179 plugins/sudoers/sudoers.c:999
+#, c-format
+msgid "unable to read %s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:182
+#, c-format
+msgid "invalid sequence number %s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:231 plugins/sudoers/iolog.c:234
+#: plugins/sudoers/iolog.c:499 plugins/sudoers/iolog.c:504
+#: plugins/sudoers/iolog.c:510 plugins/sudoers/iolog.c:518
+#: plugins/sudoers/iolog.c:526 plugins/sudoers/iolog.c:534
+#: plugins/sudoers/iolog.c:542
+#, c-format
+msgid "unable to create %s"
+msgstr ""
+
+#: plugins/sudoers/iolog_path.c:256 plugins/sudoers/sudoers.c:362
+#, c-format
+msgid "unable to set locale to \"%s\", using \"C\""
+msgstr ""
+
+#: plugins/sudoers/ldap.c:374
+#, c-format
+msgid "sudo_ldap_conf_add_ports: port too large"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:397
+#, c-format
+msgid "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:427
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:456
+#, c-format
+msgid "invalid uri: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:462
+#, c-format
+msgid "unable to mix ldap and ldaps URIs"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:466
+#, c-format
+msgid "unable to mix ldaps and starttls"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:485
+#, c-format
+msgid "sudo_ldap_parse_uri: out of space building hostbuf"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:550
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:958
+#, c-format
+msgid "unable to get GMT time"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:964
+#, c-format
+msgid "unable to format timestamp"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:972
+#, c-format
+msgid "unable to build time filter"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1185
+#, c-format
+msgid "sudo_ldap_build_pass1 allocation mismatch"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1705
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1707
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: UNKNOWN\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1754
+#, c-format
+msgid " Order: %s\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1762
+#, c-format
+msgid " Commands:\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2161
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2192
+#, c-format
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2428
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr ""
+
+#: plugins/sudoers/linux_audit.c:57
+#, c-format
+msgid "unable to open audit system"
+msgstr ""
+
+#: plugins/sudoers/linux_audit.c:82
+#, c-format
+msgid "internal error, linux_audit_command() overflow"
+msgstr ""
+
+#: plugins/sudoers/linux_audit.c:91
+#, c-format
+msgid "unable to send audit message"
+msgstr ""
+
+#: plugins/sudoers/logging.c:198
+#, c-format
+msgid "unable to open log file: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:201
+#, c-format
+msgid "unable to lock log file: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:256
+msgid "user NOT in sudoers"
+msgstr ""
+
+#: plugins/sudoers/logging.c:258
+msgid "user NOT authorized on host"
+msgstr ""
+
+#: plugins/sudoers/logging.c:260
+msgid "command not allowed"
+msgstr ""
+
+#: plugins/sudoers/logging.c:270
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr "%s nėra „sudoers“ faile. Apie šį įvykį bus pranešta.\n"
+
+#: plugins/sudoers/logging.c:273
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr "%s neleidžiama vykdyti „sudo“ kompiuteryje %s. Apie šį įvykį bus pranešta.\n"
+
+#: plugins/sudoers/logging.c:277
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Deja, naudotojas %s negali vykdyti „sudo“ kompiuteryje %s.\n"
+
+#: plugins/sudoers/logging.c:280
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr "Deja, naudotojui %s neleidžiama vykdyti „%s%s%s“ kaip %s%s%s kompiuteryje %s.\n"
+
+#: plugins/sudoers/logging.c:420
+#, c-format
+msgid "unable to fork"
+msgstr ""
+
+#: plugins/sudoers/logging.c:427 plugins/sudoers/logging.c:489
+#, c-format
+msgid "unable to fork: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:479
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:504
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:540
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:755
+#, c-format
+msgid "internal error: insufficient space for log line"
+msgstr ""
+
+#: plugins/sudoers/parse.c:123
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr ""
+
+#: plugins/sudoers/parse.c:126
+#, c-format
+msgid "parse error in %s"
+msgstr ""
+
+#: plugins/sudoers/parse.c:389
+#, c-format
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+
+#: plugins/sudoers/parse.c:391
+#, c-format
+msgid " RunAsUsers: "
+msgstr ""
+
+#: plugins/sudoers/parse.c:406
+#, c-format
+msgid " RunAsGroups: "
+msgstr ""
+
+#: plugins/sudoers/parse.c:415
+#, c-format
+msgid ""
+" Commands:\n"
+"\t"
+msgstr ""
+
+#: plugins/sudoers/plugin_error.c:100 plugins/sudoers/plugin_error.c:105
+msgid ": "
+msgstr ": "
+
+#: plugins/sudoers/pwutil.c:260
+#, c-format
+msgid "unable to cache uid %u (%s), already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:268
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:305 plugins/sudoers/pwutil.c:314
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:655
+#, c-format
+msgid "unable to cache gid %u (%s), already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:663
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:693 plugins/sudoers/pwutil.c:702
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:114 plugins/sudoers/set_perms.c:365
+#: plugins/sudoers/set_perms.c:601 plugins/sudoers/set_perms.c:837
+msgid "perm stack overflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:122 plugins/sudoers/set_perms.c:373
+#: plugins/sudoers/set_perms.c:609 plugins/sudoers/set_perms.c:845
+msgid "perm stack underflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:228 plugins/sudoers/set_perms.c:466
+#: plugins/sudoers/set_perms.c:706
+msgid "unable to change to runas gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:236 plugins/sudoers/set_perms.c:473
+#: plugins/sudoers/set_perms.c:713
+msgid "unable to change to runas uid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:250 plugins/sudoers/set_perms.c:486
+#: plugins/sudoers/set_perms.c:726
+#, c-format
+msgid "unable to change to sudoers gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:291 plugins/sudoers/set_perms.c:524
+#: plugins/sudoers/set_perms.c:764 plugins/sudoers/set_perms.c:906
+msgid "too many processes"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:970
+msgid "unable to set runas group vector"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:243
+#, c-format
+msgid "Matching Defaults entries for %s on this host:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:256
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:269
+#, c-format
+msgid "User %s may run the following commands on this host:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:279
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Naudotojui %s neleidžiama vykdyti „sudo“ kompiuteryje %s.\n"
+
+#: plugins/sudoers/sudoers.c:201 plugins/sudoers/sudoers.c:232
+#: plugins/sudoers/sudoers.c:931
+msgid "problem with defaults entries"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:205
+#, c-format
+msgid "no valid sudoers sources found, quitting"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:257
+#, c-format
+msgid "unable to execute %s: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:311
+#, c-format
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:318
+#, c-format
+msgid "you are not permitted to use the -C option"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:408
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:424
+msgid "no tty"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:425
+#, c-format
+msgid "sorry, you must have a tty to run sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:464
+msgid "No user or host"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:478 plugins/sudoers/sudoers.c:499
+#: plugins/sudoers/sudoers.c:500 plugins/sudoers/sudoers.c:1509
+#: plugins/sudoers/sudoers.c:1510
+#, c-format
+msgid "%s: command not found"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:480 plugins/sudoers/sudoers.c:496
+#, c-format
+msgid ""
+"ignoring `%s' found in '.'\n"
+"Use `sudo ./%s' if this is the `%s' you wish to run."
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:485
+msgid "validation failure"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:495
+msgid "command in current directory"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:507
+#, c-format
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:657 plugins/sudoers/sudoers.c:664
+#, c-format
+msgid "internal error, runas_groups overflow"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:914
+#, c-format
+msgid "internal error, set_cmnd() overflow"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:957
+#, c-format
+msgid "fixed mode on %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:961
+#, c-format
+msgid "set group on %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:964
+#, c-format
+msgid "unable to set group on %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:967
+#, c-format
+msgid "unable to fix mode on %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:980
+#, c-format
+msgid "%s is not a regular file"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:982
+#, c-format
+msgid "%s is mode 0%o, should be 0%o"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:986
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s priklauso uid %u, nors turėtų %u"
+
+#: plugins/sudoers/sudoers.c:989
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s priklauso gid %u, nors turėtų %u"
+
+#: plugins/sudoers/sudoers.c:1038
+#, c-format
+msgid "only root can use `-c %s'"
+msgstr "„-c %s“ gali naudoti tik „root“ naudotojas"
+
+#: plugins/sudoers/sudoers.c:1049
+#, c-format
+msgid "unknown login class: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1077
+#, c-format
+msgid "unable to resolve host %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1129 plugins/sudoers/testsudoers.c:380
+#, c-format
+msgid "unknown group: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1178
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1180
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1184
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1187
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1189
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1190
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:286
+#, c-format
+msgid "invalid filter option: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:299
+#, c-format
+msgid "invalid max wait: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:305
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:308 plugins/sudoers/visudo.c:187
+#, c-format
+msgid "%s version %s\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:333
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s/timing: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:339
+#, c-format
+msgid "%s/%s/timing: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:364
+#, c-format
+msgid "invalid log file %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:366
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:392
+#, c-format
+msgid "unable to set tty to raw mode"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:406
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:448
+#, c-format
+msgid "writing to standard output"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:480
+#, c-format
+msgid "nanosleep: tv_sec %ld, tv_nsec %ld"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:529 plugins/sudoers/sudoreplay.c:554
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:571
+#, c-format
+msgid "too many parenthesized expressions, max %d"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:582
+#, c-format
+msgid "unmatched ')' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:588
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:602
+#, c-format
+msgid "%s requires an argument"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:606
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:612
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:625
+#, c-format
+msgid "unmatched '(' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:627
+#, c-format
+msgid "illegal trailing \"or\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:629
+#, c-format
+msgid "illegal trailing \"!\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:851
+#, c-format
+msgid "invalid regex: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:976
+#, c-format
+msgid "usage: %s [-h] [-d directory] [-m max_wait] [-s speed_factor] ID\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:979
+#, c-format
+msgid "usage: %s [-h] [-d directory] -l [search expression]\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:988
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:990
+msgid ""
+"\n"
+"Options:\n"
+" -d directory specify directory for session logs\n"
+" -f filter specify which I/O type to display\n"
+" -h display help message and exit\n"
+" -l [expression] list available session IDs that match expression\n"
+" -m max_wait max number of seconds to wait between events\n"
+" -s speed_factor speed up or slow down output\n"
+" -V display version information and exit"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:246
+#, c-format
+msgid "internal error, init_vars() overflow"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:331
+msgid "\thost unmatched"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:334
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:335
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:335
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+
+#: toke.l:672 toke.l:802 toke.l:827 toke.l:923 plugins/sudoers/toke_util.c:113
+#: plugins/sudoers/toke_util.c:167 plugins/sudoers/toke_util.c:207
+msgid "unable to allocate memory"
+msgstr ""
+
+#: toke.l:795
+msgid "too many levels of includes"
+msgstr ""
+
+#: plugins/sudoers/toke_util.c:218
+msgid "fill_args: buffer overflow"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:188
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:221 plugins/sudoers/auth/rfc1938.c:104
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:253 plugins/sudoers/visudo.c:539
+#, c-format
+msgid "press return to edit %s: "
+msgstr ""
+
+#: plugins/sudoers/visudo.c:336 plugins/sudoers/visudo.c:342
+#, c-format
+msgid "write error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:424
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:429
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:435
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:458
+#, c-format
+msgid "%s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:484
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr ""
+
+#: plugins/sudoers/visudo.c:494
+#, c-format
+msgid "unabled to parse temporary file (%s), unknown error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:532
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:584 plugins/sudoers/visudo.c:593
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:588 plugins/sudoers/visudo.c:598
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:615
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:629
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:639
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:702
+msgid "What now? "
+msgstr ""
+
+#: plugins/sudoers/visudo.c:716
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:757
+#, c-format
+msgid "unable to execute %s"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:764
+#, c-format
+msgid "unable to run %s"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:796
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:808
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:811
+#, c-format
+msgid "parse error in %s\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:814 plugins/sudoers/visudo.c:816
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:826
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:833
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:880
+#, c-format
+msgid "%s busy, try again later"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:924
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:947
+#, c-format
+msgid "unable to stat editor (%s)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:995
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1089
+#, c-format
+msgid "Error: cycle in %s_Alias `%s'"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1090
+#, c-format
+msgid "Warning: cycle in %s_Alias `%s'"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1093
+#, c-format
+msgid "Error: %s_Alias `%s' referenced but not defined"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1094
+#, c-format
+msgid "Warning: %s_Alias `%s' referenced but not defined"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1229
+#, c-format
+msgid "%s: unused %s_Alias %s"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1286
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1288
+msgid ""
+"\n"
+"Options:\n"
+" -c check-only mode\n"
+" -f sudoers specify sudoers file location\n"
+" -h display help message and exit\n"
+" -q less verbose (quiet) syntax error messages\n"
+" -s strict syntax checking\n"
+" -V display version information and exit"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:78
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:84
+msgid "unable to begin bsd authentication"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:92
+msgid "invalid authentication type"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:101
+msgid "unable to setup authentication"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:60
+#, c-format
+msgid "unable to read fwtk config"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:65
+#, c-format
+msgid "unable to connect to authentication server"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:71 plugins/sudoers/auth/fwtk.c:95
+#: plugins/sudoers/auth/fwtk.c:128
+#, c-format
+msgid "lost connection to authentication server"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:75
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:117
+#, c-format
+msgid "%s: unable to unparse princ ('%s'): %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:160
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:170
+#, c-format
+msgid "%s: unable to resolve ccache: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:218
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:234
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:247
+#, c-format
+msgid "%s: unable to initialize ccache: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:251
+#, c-format
+msgid "%s: unable to store cred in ccache: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:316
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:331
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:100
+msgid "unable to initialize PAM"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:144
+msgid "account validation failure, is your account locked?"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:148
+msgid "Account or password is expired, reset your password and try again"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:155
+#, c-format
+msgid "pam_chauthtok: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:159
+msgid "Password expired, contact your system administrator"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:163
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:178
+#, c-format
+msgid "pam_authenticate: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:306
+msgid "Password: "
+msgstr "Slaptažodis: "
+
+#: plugins/sudoers/auth/pam.c:307
+msgid "Password:"
+msgstr "Slaptažodis:"
+
+#: plugins/sudoers/auth/securid5.c:81
+#, c-format
+msgid "failed to initialise the ACE API library"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:107
+#, c-format
+msgid "unable to contact the SecurID server"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:116
+#, c-format
+msgid "User ID locked for SecurID Authentication"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:120 plugins/sudoers/auth/securid5.c:171
+#, c-format
+msgid "invalid username length for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:124 plugins/sudoers/auth/securid5.c:176
+#, c-format
+msgid "invalid Authentication Handle for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:128
+#, c-format
+msgid "SecurID communication failed"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:132 plugins/sudoers/auth/securid5.c:215
+#, c-format
+msgid "unknown SecurID error"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:166
+#, c-format
+msgid "invalid passcode length for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/sia.c:109
+msgid "unable to initialize SIA session"
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:117
+msgid "Invalid authentication methods compiled into sudo! You may mix standalone and non-standalone authentication."
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:199
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:271
+#, c-format
+msgid "%d incorrect password attempt"
+msgid_plural "%d incorrect password attempts"
+msgstr[0] ""
+msgstr[1] ""
+
+#: plugins/sudoers/auth/sudo_auth.c:374
+msgid "Authentication methods:"
+msgstr ""
diff --git a/plugins/sudoers/po/nb.mo b/plugins/sudoers/po/nb.mo
new file mode 100644
index 0000000..b0d914c
--- /dev/null
+++ b/plugins/sudoers/po/nb.mo
Binary files differ
diff --git a/plugins/sudoers/po/nb.po b/plugins/sudoers/po/nb.po
new file mode 100644
index 0000000..5f323cd
--- /dev/null
+++ b/plugins/sudoers/po/nb.po
@@ -0,0 +1,2444 @@
+# Norwegian bokmål translation of sudoers.
+# This file is distributed under the same license as the sudo package.
+# Copyright (C) 2017 Free Software Foundation, Inc.
+# Todd C. Miller <Todd.Miller@courtesan.com>, 2011-2013.
+# Åka Sikrom <a4@hush.com>, 2014-2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers-1.8.29rc1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2019-10-21 19:55-0600\n"
+"PO-Revision-Date: 2020-02-02 21:12+0100\n"
+"Last-Translator: Åka Sikrom <a4@hush.com>\n"
+"Language-Team: Norwegian Bokmaal <i18n-nb@lister.ping.uio.no>\n"
+"Language: nb\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 2.0.6\n"
+
+#: confstr.sh:1
+msgid "syntax error"
+msgstr "syntaksfeil"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "passord for %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] passord for %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Passord:"
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** SIKKERHETSinformasjon om %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Feil. Prøv igjen."
+
+#: gram.y:196 gram.y:244 gram.y:251 gram.y:258 gram.y:265 gram.y:272
+#: gram.y:288 gram.y:312 gram.y:319 gram.y:326 gram.y:333 gram.y:340
+#: gram.y:403 gram.y:412 gram.y:423 gram.y:456 gram.y:463 gram.y:470
+#: gram.y:477 gram.y:559 gram.y:566 gram.y:575 gram.y:584 gram.y:601
+#: gram.y:713 gram.y:720 gram.y:727 gram.y:735 gram.y:835 gram.y:842
+#: gram.y:849 gram.y:856 gram.y:863 gram.y:889 gram.y:896 gram.y:903
+#: gram.y:1026 gram.y:1303 plugins/sudoers/alias.c:132
+#: plugins/sudoers/alias.c:139 plugins/sudoers/alias.c:155
+#: plugins/sudoers/auth/bsdauth.c:148 plugins/sudoers/auth/kerb5.c:123
+#: plugins/sudoers/auth/kerb5.c:149 plugins/sudoers/auth/pam.c:670
+#: plugins/sudoers/auth/rfc1938.c:116 plugins/sudoers/auth/sia.c:64
+#: plugins/sudoers/cvtsudoers.c:124 plugins/sudoers/cvtsudoers.c:165
+#: plugins/sudoers/cvtsudoers.c:182 plugins/sudoers/cvtsudoers.c:193
+#: plugins/sudoers/cvtsudoers.c:305 plugins/sudoers/cvtsudoers.c:433
+#: plugins/sudoers/cvtsudoers.c:566 plugins/sudoers/cvtsudoers.c:583
+#: plugins/sudoers/cvtsudoers.c:646 plugins/sudoers/cvtsudoers.c:761
+#: plugins/sudoers/cvtsudoers.c:769 plugins/sudoers/cvtsudoers.c:1179
+#: plugins/sudoers/cvtsudoers.c:1183 plugins/sudoers/cvtsudoers.c:1285
+#: plugins/sudoers/cvtsudoers_ldif.c:154 plugins/sudoers/cvtsudoers_ldif.c:197
+#: plugins/sudoers/cvtsudoers_ldif.c:244 plugins/sudoers/cvtsudoers_ldif.c:263
+#: plugins/sudoers/cvtsudoers_ldif.c:334 plugins/sudoers/cvtsudoers_ldif.c:389
+#: plugins/sudoers/cvtsudoers_ldif.c:397 plugins/sudoers/cvtsudoers_ldif.c:414
+#: plugins/sudoers/cvtsudoers_ldif.c:423 plugins/sudoers/cvtsudoers_ldif.c:570
+#: plugins/sudoers/defaults.c:666 plugins/sudoers/defaults.c:959
+#: plugins/sudoers/defaults.c:1130 plugins/sudoers/editor.c:72
+#: plugins/sudoers/editor.c:90 plugins/sudoers/editor.c:101
+#: plugins/sudoers/env.c:268 plugins/sudoers/filedigest.c:66
+#: plugins/sudoers/filedigest.c:82 plugins/sudoers/gc.c:59
+#: plugins/sudoers/group_plugin.c:138 plugins/sudoers/interfaces.c:78
+#: plugins/sudoers/iolog.c:943 plugins/sudoers/iolog_path.c:174
+#: plugins/sudoers/iolog_util.c:86 plugins/sudoers/iolog_util.c:125
+#: plugins/sudoers/iolog_util.c:134 plugins/sudoers/iolog_util.c:144
+#: plugins/sudoers/iolog_util.c:152 plugins/sudoers/iolog_util.c:156
+#: plugins/sudoers/ldap.c:185 plugins/sudoers/ldap.c:416
+#: plugins/sudoers/ldap.c:420 plugins/sudoers/ldap.c:432
+#: plugins/sudoers/ldap.c:723 plugins/sudoers/ldap.c:887
+#: plugins/sudoers/ldap.c:1241 plugins/sudoers/ldap.c:1668
+#: plugins/sudoers/ldap.c:1705 plugins/sudoers/ldap.c:1786
+#: plugins/sudoers/ldap.c:1921 plugins/sudoers/ldap.c:2022
+#: plugins/sudoers/ldap.c:2038 plugins/sudoers/ldap_conf.c:223
+#: plugins/sudoers/ldap_conf.c:254 plugins/sudoers/ldap_conf.c:306
+#: plugins/sudoers/ldap_conf.c:342 plugins/sudoers/ldap_conf.c:446
+#: plugins/sudoers/ldap_conf.c:461 plugins/sudoers/ldap_conf.c:558
+#: plugins/sudoers/ldap_conf.c:591 plugins/sudoers/ldap_conf.c:683
+#: plugins/sudoers/ldap_conf.c:765 plugins/sudoers/ldap_util.c:510
+#: plugins/sudoers/ldap_util.c:567 plugins/sudoers/linux_audit.c:83
+#: plugins/sudoers/logging.c:202 plugins/sudoers/logging.c:532
+#: plugins/sudoers/logging.c:558 plugins/sudoers/logging.c:599
+#: plugins/sudoers/logging.c:740 plugins/sudoers/logging.c:1100
+#: plugins/sudoers/match_command.c:249 plugins/sudoers/match_command.c:367
+#: plugins/sudoers/match_command.c:414 plugins/sudoers/match_command.c:485
+#: plugins/sudoers/match_digest.c:70 plugins/sudoers/parse.c:200
+#: plugins/sudoers/parse.c:212 plugins/sudoers/parse.c:227
+#: plugins/sudoers/parse.c:239 plugins/sudoers/parse_ldif.c:156
+#: plugins/sudoers/parse_ldif.c:187 plugins/sudoers/parse_ldif.c:256
+#: plugins/sudoers/parse_ldif.c:263 plugins/sudoers/parse_ldif.c:268
+#: plugins/sudoers/parse_ldif.c:344 plugins/sudoers/parse_ldif.c:355
+#: plugins/sudoers/parse_ldif.c:361 plugins/sudoers/parse_ldif.c:386
+#: plugins/sudoers/parse_ldif.c:398 plugins/sudoers/parse_ldif.c:402
+#: plugins/sudoers/parse_ldif.c:416 plugins/sudoers/parse_ldif.c:584
+#: plugins/sudoers/parse_ldif.c:614 plugins/sudoers/parse_ldif.c:639
+#: plugins/sudoers/parse_ldif.c:697 plugins/sudoers/parse_ldif.c:714
+#: plugins/sudoers/parse_ldif.c:742 plugins/sudoers/parse_ldif.c:749
+#: plugins/sudoers/policy.c:504 plugins/sudoers/policy.c:750
+#: plugins/sudoers/prompt.c:100 plugins/sudoers/pwutil.c:199
+#: plugins/sudoers/pwutil.c:270 plugins/sudoers/pwutil.c:348
+#: plugins/sudoers/pwutil.c:522 plugins/sudoers/pwutil.c:586
+#: plugins/sudoers/pwutil.c:657 plugins/sudoers/pwutil.c:816
+#: plugins/sudoers/pwutil.c:873 plugins/sudoers/pwutil.c:917
+#: plugins/sudoers/pwutil.c:975 plugins/sudoers/sssd.c:154
+#: plugins/sudoers/sssd.c:400 plugins/sudoers/sssd.c:463
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:554
+#: plugins/sudoers/sssd.c:746 plugins/sudoers/stubs.c:103
+#: plugins/sudoers/stubs.c:111 plugins/sudoers/sudoers.c:273
+#: plugins/sudoers/sudoers.c:283 plugins/sudoers/sudoers.c:292
+#: plugins/sudoers/sudoers.c:334 plugins/sudoers/sudoers.c:657
+#: plugins/sudoers/sudoers.c:786 plugins/sudoers/sudoers.c:830
+#: plugins/sudoers/sudoers.c:1124 plugins/sudoers/sudoers_debug.c:114
+#: plugins/sudoers/sudoreplay.c:584 plugins/sudoers/sudoreplay.c:587
+#: plugins/sudoers/sudoreplay.c:1265 plugins/sudoers/sudoreplay.c:1465
+#: plugins/sudoers/sudoreplay.c:1469 plugins/sudoers/testsudoers.c:136
+#: plugins/sudoers/testsudoers.c:236 plugins/sudoers/testsudoers.c:253
+#: plugins/sudoers/testsudoers.c:587 plugins/sudoers/timestamp.c:439
+#: plugins/sudoers/timestamp.c:483 plugins/sudoers/timestamp.c:960
+#: plugins/sudoers/toke_util.c:59 plugins/sudoers/toke_util.c:112
+#: plugins/sudoers/toke_util.c:149 plugins/sudoers/tsdump.c:130
+#: plugins/sudoers/visudo.c:152 plugins/sudoers/visudo.c:328
+#: plugins/sudoers/visudo.c:334 plugins/sudoers/visudo.c:444
+#: plugins/sudoers/visudo.c:622 plugins/sudoers/visudo.c:942
+#: plugins/sudoers/visudo.c:1029 plugins/sudoers/visudo.c:1118 toke.l:846
+#: toke.l:947 toke.l:1104
+msgid "unable to allocate memory"
+msgstr "klarte ikke å tildele minne"
+
+#: gram.y:488
+msgid "a digest requires a path name"
+msgstr "kontrollsummering krever at du velger et stinavn"
+
+#: gram.y:614
+msgid "invalid notbefore value"
+msgstr "ugyldig «notbefore»-verdi"
+
+#: gram.y:622
+msgid "invalid notafter value"
+msgstr "ugyldig «notafter»-verdi"
+
+#: gram.y:631 plugins/sudoers/policy.c:320
+msgid "timeout value too large"
+msgstr "for langt tidsavbrudd"
+
+#: gram.y:633 plugins/sudoers/policy.c:322
+msgid "invalid timeout value"
+msgstr "ugyldig tidsavbrudd"
+
+#: gram.y:1303 plugins/sudoers/auth/pam.c:483 plugins/sudoers/auth/pam.c:670
+#: plugins/sudoers/auth/rfc1938.c:116 plugins/sudoers/cvtsudoers.c:124
+#: plugins/sudoers/cvtsudoers.c:164 plugins/sudoers/cvtsudoers.c:181
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:304
+#: plugins/sudoers/cvtsudoers.c:432 plugins/sudoers/cvtsudoers.c:565
+#: plugins/sudoers/cvtsudoers.c:582 plugins/sudoers/cvtsudoers.c:646
+#: plugins/sudoers/cvtsudoers.c:761 plugins/sudoers/cvtsudoers.c:768
+#: plugins/sudoers/cvtsudoers.c:1179 plugins/sudoers/cvtsudoers.c:1183
+#: plugins/sudoers/cvtsudoers.c:1285 plugins/sudoers/cvtsudoers_ldif.c:153
+#: plugins/sudoers/cvtsudoers_ldif.c:196 plugins/sudoers/cvtsudoers_ldif.c:243
+#: plugins/sudoers/cvtsudoers_ldif.c:262 plugins/sudoers/cvtsudoers_ldif.c:333
+#: plugins/sudoers/cvtsudoers_ldif.c:388 plugins/sudoers/cvtsudoers_ldif.c:396
+#: plugins/sudoers/cvtsudoers_ldif.c:413 plugins/sudoers/cvtsudoers_ldif.c:422
+#: plugins/sudoers/cvtsudoers_ldif.c:569 plugins/sudoers/defaults.c:666
+#: plugins/sudoers/defaults.c:959 plugins/sudoers/defaults.c:1130
+#: plugins/sudoers/editor.c:72 plugins/sudoers/editor.c:90
+#: plugins/sudoers/editor.c:101 plugins/sudoers/env.c:268
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:82
+#: plugins/sudoers/gc.c:59 plugins/sudoers/group_plugin.c:138
+#: plugins/sudoers/interfaces.c:78 plugins/sudoers/iolog.c:943
+#: plugins/sudoers/iolog_path.c:174 plugins/sudoers/iolog_util.c:86
+#: plugins/sudoers/iolog_util.c:125 plugins/sudoers/iolog_util.c:134
+#: plugins/sudoers/iolog_util.c:144 plugins/sudoers/iolog_util.c:152
+#: plugins/sudoers/iolog_util.c:156 plugins/sudoers/ldap.c:185
+#: plugins/sudoers/ldap.c:416 plugins/sudoers/ldap.c:420
+#: plugins/sudoers/ldap.c:432 plugins/sudoers/ldap.c:723
+#: plugins/sudoers/ldap.c:887 plugins/sudoers/ldap.c:1241
+#: plugins/sudoers/ldap.c:1668 plugins/sudoers/ldap.c:1705
+#: plugins/sudoers/ldap.c:1786 plugins/sudoers/ldap.c:1921
+#: plugins/sudoers/ldap.c:2022 plugins/sudoers/ldap.c:2038
+#: plugins/sudoers/ldap_conf.c:223 plugins/sudoers/ldap_conf.c:254
+#: plugins/sudoers/ldap_conf.c:306 plugins/sudoers/ldap_conf.c:342
+#: plugins/sudoers/ldap_conf.c:446 plugins/sudoers/ldap_conf.c:461
+#: plugins/sudoers/ldap_conf.c:558 plugins/sudoers/ldap_conf.c:591
+#: plugins/sudoers/ldap_conf.c:682 plugins/sudoers/ldap_conf.c:765
+#: plugins/sudoers/ldap_util.c:510 plugins/sudoers/ldap_util.c:567
+#: plugins/sudoers/linux_audit.c:83 plugins/sudoers/logging.c:202
+#: plugins/sudoers/logging.c:532 plugins/sudoers/logging.c:558
+#: plugins/sudoers/logging.c:598 plugins/sudoers/logging.c:1100
+#: plugins/sudoers/match_command.c:248 plugins/sudoers/match_command.c:366
+#: plugins/sudoers/match_command.c:413 plugins/sudoers/match_command.c:485
+#: plugins/sudoers/match_digest.c:70 plugins/sudoers/parse.c:199
+#: plugins/sudoers/parse.c:211 plugins/sudoers/parse.c:226
+#: plugins/sudoers/parse.c:238 plugins/sudoers/parse_ldif.c:155
+#: plugins/sudoers/parse_ldif.c:186 plugins/sudoers/parse_ldif.c:255
+#: plugins/sudoers/parse_ldif.c:262 plugins/sudoers/parse_ldif.c:267
+#: plugins/sudoers/parse_ldif.c:343 plugins/sudoers/parse_ldif.c:354
+#: plugins/sudoers/parse_ldif.c:360 plugins/sudoers/parse_ldif.c:385
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:401
+#: plugins/sudoers/parse_ldif.c:415 plugins/sudoers/parse_ldif.c:584
+#: plugins/sudoers/parse_ldif.c:613 plugins/sudoers/parse_ldif.c:638
+#: plugins/sudoers/parse_ldif.c:696 plugins/sudoers/parse_ldif.c:713
+#: plugins/sudoers/parse_ldif.c:741 plugins/sudoers/parse_ldif.c:748
+#: plugins/sudoers/policy.c:134 plugins/sudoers/policy.c:143
+#: plugins/sudoers/policy.c:152 plugins/sudoers/policy.c:178
+#: plugins/sudoers/policy.c:305 plugins/sudoers/policy.c:320
+#: plugins/sudoers/policy.c:322 plugins/sudoers/policy.c:348
+#: plugins/sudoers/policy.c:358 plugins/sudoers/policy.c:402
+#: plugins/sudoers/policy.c:412 plugins/sudoers/policy.c:421
+#: plugins/sudoers/policy.c:430 plugins/sudoers/policy.c:504
+#: plugins/sudoers/policy.c:750 plugins/sudoers/prompt.c:100
+#: plugins/sudoers/pwutil.c:199 plugins/sudoers/pwutil.c:270
+#: plugins/sudoers/pwutil.c:348 plugins/sudoers/pwutil.c:522
+#: plugins/sudoers/pwutil.c:586 plugins/sudoers/pwutil.c:657
+#: plugins/sudoers/pwutil.c:816 plugins/sudoers/pwutil.c:873
+#: plugins/sudoers/pwutil.c:917 plugins/sudoers/pwutil.c:975
+#: plugins/sudoers/set_perms.c:396 plugins/sudoers/set_perms.c:775
+#: plugins/sudoers/set_perms.c:1165 plugins/sudoers/set_perms.c:1493
+#: plugins/sudoers/set_perms.c:1659 plugins/sudoers/sssd.c:153
+#: plugins/sudoers/sssd.c:400 plugins/sudoers/sssd.c:463
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:554
+#: plugins/sudoers/sssd.c:746 plugins/sudoers/stubs.c:103
+#: plugins/sudoers/stubs.c:111 plugins/sudoers/sudoers.c:273
+#: plugins/sudoers/sudoers.c:283 plugins/sudoers/sudoers.c:292
+#: plugins/sudoers/sudoers.c:334 plugins/sudoers/sudoers.c:657
+#: plugins/sudoers/sudoers.c:786 plugins/sudoers/sudoers.c:830
+#: plugins/sudoers/sudoers.c:1124 plugins/sudoers/sudoers_debug.c:113
+#: plugins/sudoers/sudoreplay.c:584 plugins/sudoers/sudoreplay.c:587
+#: plugins/sudoers/sudoreplay.c:1265 plugins/sudoers/sudoreplay.c:1465
+#: plugins/sudoers/sudoreplay.c:1469 plugins/sudoers/testsudoers.c:136
+#: plugins/sudoers/testsudoers.c:236 plugins/sudoers/testsudoers.c:253
+#: plugins/sudoers/testsudoers.c:587 plugins/sudoers/timestamp.c:439
+#: plugins/sudoers/timestamp.c:483 plugins/sudoers/timestamp.c:960
+#: plugins/sudoers/toke_util.c:59 plugins/sudoers/toke_util.c:112
+#: plugins/sudoers/toke_util.c:149 plugins/sudoers/tsdump.c:130
+#: plugins/sudoers/visudo.c:152 plugins/sudoers/visudo.c:328
+#: plugins/sudoers/visudo.c:334 plugins/sudoers/visudo.c:444
+#: plugins/sudoers/visudo.c:622 plugins/sudoers/visudo.c:942
+#: plugins/sudoers/visudo.c:1029 plugins/sudoers/visudo.c:1118 toke.l:846
+#: toke.l:947 toke.l:1104
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: plugins/sudoers/alias.c:151
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Alias «%s» er allerede definert"
+
+#: plugins/sudoers/auth/aix_auth.c:203 plugins/sudoers/logging.c:801
+msgid "unable to fork"
+msgstr "klarte ikke å kopiere prosess"
+
+#: plugins/sudoers/auth/aix_auth.c:283
+#, c-format
+msgid "unable to change password for %s"
+msgstr "klarte ikke å endre passord for %s"
+
+#: plugins/sudoers/auth/bsdauth.c:75
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "klarte ikke å hente innloggingsklasse for brukeren %s"
+
+#: plugins/sudoers/auth/bsdauth.c:80
+msgid "unable to begin bsd authentication"
+msgstr "klarte ikke å starte bsd-autentisering"
+
+#: plugins/sudoers/auth/bsdauth.c:88
+msgid "invalid authentication type"
+msgstr "ugyldig autentiseringstype"
+
+#: plugins/sudoers/auth/bsdauth.c:97
+msgid "unable to initialize BSD authentication"
+msgstr "klarte ikke å starte opp BSD-autentisering"
+
+#: plugins/sudoers/auth/bsdauth.c:185
+msgid "your account has expired"
+msgstr "kontoen din er utgått"
+
+#: plugins/sudoers/auth/bsdauth.c:187
+msgid "approval failed"
+msgstr "godkjenning mislyktes"
+
+#: plugins/sudoers/auth/fwtk.c:59
+msgid "unable to read fwtk config"
+msgstr "klarte ikke å lese fwtk-innstillinger"
+
+#: plugins/sudoers/auth/fwtk.c:64
+msgid "unable to connect to authentication server"
+msgstr "klarte ikke å koble til autentiseringstjener"
+
+#: plugins/sudoers/auth/fwtk.c:70 plugins/sudoers/auth/fwtk.c:94
+#: plugins/sudoers/auth/fwtk.c:126
+msgid "lost connection to authentication server"
+msgstr "tilkobling til autentiseringstjener ble brutt"
+
+#: plugins/sudoers/auth/fwtk.c:74
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"det oppstod en feil med autentiseringstjener:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:115
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: klarte ikke å konvertere fullmaktsgiver til streng («%s»). %s"
+
+#: plugins/sudoers/auth/kerb5.c:165
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: klarte ikke å tolke «%s». %s"
+
+#: plugins/sudoers/auth/kerb5.c:174
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: klarte ikke å slå opp i akkreditiv-hurtiglager. %s"
+
+#: plugins/sudoers/auth/kerb5.c:221
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: klarte ikke å tildele innstillinger. %s"
+
+#: plugins/sudoers/auth/kerb5.c:236
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: klarte ikke å hente akkreditiver. %s"
+
+#: plugins/sudoers/auth/kerb5.c:249
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: klarte ikke å starte opp akkreditiv-hurtiglager. %s"
+
+#: plugins/sudoers/auth/kerb5.c:252
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: klarte ikke å lagre akkreditiv i hurtiglager. %s"
+
+#: plugins/sudoers/auth/kerb5.c:316
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: klarte ikke å hente vertens fullmaktsgiver. %s"
+
+#: plugins/sudoers/auth/kerb5.c:330
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: Klarte ikke å bekrefte TGT! Dette kan være et tegn på at du er under angrep! %s"
+
+#: plugins/sudoers/auth/pam.c:223
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "klarte ikke å starte opp PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:319
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Feil ved PAM-autentisering. %s"
+
+#: plugins/sudoers/auth/pam.c:338
+msgid "account validation failure, is your account locked?"
+msgstr "det oppstod en feil ved validering av brukerkonto. Er kontoen din sperret?"
+
+#: plugins/sudoers/auth/pam.c:349
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Kontoen eller passordet er utgått. Tilbakestill passordet ditt og prøv igjen"
+
+#: plugins/sudoers/auth/pam.c:355
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "klarte ikke å endre et utgått passord. %s"
+
+#: plugins/sudoers/auth/pam.c:366
+msgid "Password expired, contact your system administrator"
+msgstr "Passordet er utgått. Kontakt systemadministratoren"
+
+#: plugins/sudoers/auth/pam.c:371
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Kontoen er utgått, eller PAM-innstillingene mangler en «account»-del for sudo. Kontakt systemadministratoren"
+
+#: plugins/sudoers/auth/pam.c:379 plugins/sudoers/auth/pam.c:384
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "Feil med PAM-kontohåndtering: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:104 plugins/sudoers/visudo.c:248
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "du finnes ikke i %s-databasen"
+
+#: plugins/sudoers/auth/securid5.c:77
+msgid "failed to initialise the ACE API library"
+msgstr "klarte ikke å starte opp ACE API-biblioteket"
+
+#: plugins/sudoers/auth/securid5.c:103
+msgid "unable to contact the SecurID server"
+msgstr "klarte ikke å kontakte SecurID-tjener"
+
+#: plugins/sudoers/auth/securid5.c:112
+msgid "User ID locked for SecurID Authentication"
+msgstr "Bruker-ID-en er sperret fra SecurID-autentisering"
+
+#: plugins/sudoers/auth/securid5.c:116 plugins/sudoers/auth/securid5.c:167
+msgid "invalid username length for SecurID"
+msgstr "lengden på brukernavnet er ugyldig for SecurID"
+
+#: plugins/sudoers/auth/securid5.c:120 plugins/sudoers/auth/securid5.c:172
+msgid "invalid Authentication Handle for SecurID"
+msgstr "ugyldig autentiseringshåndtak for SecurID"
+
+#: plugins/sudoers/auth/securid5.c:124
+msgid "SecurID communication failed"
+msgstr "Det oppstod en feil under kommunikasjon med SecurID"
+
+#: plugins/sudoers/auth/securid5.c:128 plugins/sudoers/auth/securid5.c:217
+msgid "unknown SecurID error"
+msgstr "ukjent SecurID-feil"
+
+#: plugins/sudoers/auth/securid5.c:162
+msgid "invalid passcode length for SecurID"
+msgstr "kodelengden er ugyldig for SecurID"
+
+#: plugins/sudoers/auth/sia.c:74 plugins/sudoers/auth/sia.c:129
+msgid "unable to initialize SIA session"
+msgstr "kalrte ikke å starte opp SIA-økt"
+
+#: plugins/sudoers/auth/sudo_auth.c:138
+msgid "invalid authentication methods"
+msgstr "ugyldige autentiseringsmetoder"
+
+#: plugins/sudoers/auth/sudo_auth.c:140
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Din installasjon av sudo har ugyldige autentiseringsmetoder! Du kan ikke blande selvgående og tjeneravhengige autentiseringsmetoder."
+
+#: plugins/sudoers/auth/sudo_auth.c:261 plugins/sudoers/auth/sudo_auth.c:311
+msgid "no authentication methods"
+msgstr "fant ingen autentiseringsmetoder"
+
+#: plugins/sudoers/auth/sudo_auth.c:263
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Din installasjon av sudo har ingen autentiseringsmetoder tilgjengelig! Bruk valget «--disable-authentication» hvis du vil skru av autentisering."
+
+#: plugins/sudoers/auth/sudo_auth.c:313
+msgid "Unable to initialize authentication methods."
+msgstr "Klarte ikke å starte opp autentiseringsmetoder."
+
+#: plugins/sudoers/auth/sudo_auth.c:479
+msgid "Authentication methods:"
+msgstr "Autentiseringsmetoder:"
+
+#: plugins/sudoers/bsm_audit.c:125 plugins/sudoers/bsm_audit.c:217
+msgid "Could not determine audit condition"
+msgstr "Klarte ikke å finne revisjonsstatus"
+
+#: plugins/sudoers/bsm_audit.c:190 plugins/sudoers/bsm_audit.c:281
+msgid "unable to commit audit record"
+msgstr "klarte ikke å kjøre revisjonsoppføring"
+
+#: plugins/sudoers/check.c:269
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Vi går ut i fra at systemadministrator har gitt deg en\n"
+"typisk moralpreken om det du gjør. Det koker som regel ned til tre ting:\n"
+"\n"
+" #1) Ha respekt for andres privatliv og personvern.\n"
+" #2) Tenk før du skriver.\n"
+" #3) Makt medfører plikt og ansvar.\n"
+"\n"
+
+#: plugins/sudoers/check.c:312 plugins/sudoers/check.c:322
+#: plugins/sudoers/sudoers.c:700 plugins/sudoers/sudoers.c:748
+#: plugins/sudoers/tsdump.c:126
+#, c-format
+msgid "unknown uid: %u"
+msgstr "uid-en «%u» er ukjent"
+
+#: plugins/sudoers/check.c:317 plugins/sudoers/iolog.c:255
+#: plugins/sudoers/policy.c:921 plugins/sudoers/sudoers.c:1163
+#: plugins/sudoers/testsudoers.c:227 plugins/sudoers/testsudoers.c:400
+#, c-format
+msgid "unknown user: %s"
+msgstr "brukeren %s er ukjent"
+
+#: plugins/sudoers/cvtsudoers.c:199
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "økning: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:215
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "begynnende rekkefølge: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:225
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "sorteringsutfylling: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:233 plugins/sudoers/sudoreplay.c:289
+#: plugins/sudoers/visudo.c:184
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s versjon %s\n"
+
+#: plugins/sudoers/cvtsudoers.c:235 plugins/sudoers/visudo.c:186
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s gramatikkversjon %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:252 plugins/sudoers/testsudoers.c:175
+#, c-format
+msgid "unsupported input format %s"
+msgstr "inndata-format %s støttes ikke"
+
+#: plugins/sudoers/cvtsudoers.c:267
+#, c-format
+msgid "unsupported output format %s"
+msgstr "utdata-format %s støttes ikke"
+
+#: plugins/sudoers/cvtsudoers.c:319
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: inndata- og utdatafiler må være ulike"
+
+#: plugins/sudoers/cvtsudoers.c:335 plugins/sudoers/sudoers.c:176
+#: plugins/sudoers/testsudoers.c:266 plugins/sudoers/visudo.c:254
+#: plugins/sudoers/visudo.c:610 plugins/sudoers/visudo.c:933
+msgid "unable to initialize sudoers default values"
+msgstr "klarte ikke å laste inn standardverdier for sudoers"
+
+#: plugins/sudoers/cvtsudoers.c:421 plugins/sudoers/ldap_conf.c:436
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:480
+#, c-format
+msgid "%s: unknown key word: %s"
+msgstr "%s: nøkkelord %s er ukjent"
+
+#: plugins/sudoers/cvtsudoers.c:526
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "%s er en ukjent forvalgtype"
+
+#: plugins/sudoers/cvtsudoers.c:549
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "%s er en ukjent utelatelsestype"
+
+#: plugins/sudoers/cvtsudoers.c:589 plugins/sudoers/cvtsudoers.c:603
+#, c-format
+msgid "invalid filter: %s"
+msgstr "%s er et ugyldig filter"
+
+#: plugins/sudoers/cvtsudoers.c:622 plugins/sudoers/cvtsudoers.c:639
+#: plugins/sudoers/cvtsudoers.c:1245 plugins/sudoers/cvtsudoers_json.c:1130
+#: plugins/sudoers/cvtsudoers_ldif.c:643 plugins/sudoers/iolog.c:413
+#: plugins/sudoers/iolog_util.c:75 plugins/sudoers/sudoers.c:914
+#: plugins/sudoers/sudoreplay.c:338 plugins/sudoers/sudoreplay.c:1431
+#: plugins/sudoers/timestamp.c:448 plugins/sudoers/tsdump.c:135
+#: plugins/sudoers/visudo.c:929
+#, c-format
+msgid "unable to open %s"
+msgstr "klarte ikke å åpne %s"
+
+#: plugins/sudoers/cvtsudoers.c:642 plugins/sudoers/visudo.c:938
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "klarte ikke å tolke %s. Ukjent feil"
+
+#: plugins/sudoers/cvtsudoers.c:650 plugins/sudoers/visudo.c:955
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr "tolkefeil i %s ved linje %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:653 plugins/sudoers/visudo.c:958
+#, c-format
+msgid "parse error in %s\n"
+msgstr "tolkefeil i %s\n"
+
+#: plugins/sudoers/cvtsudoers.c:1292 plugins/sudoers/iolog.c:500
+#: plugins/sudoers/sudoreplay.c:1135 plugins/sudoers/timestamp.c:332
+#: plugins/sudoers/timestamp.c:335
+#, c-format
+msgid "unable to write to %s"
+msgstr "klarte ikke å skrive til %s"
+
+#: plugins/sudoers/cvtsudoers.c:1315
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s - konverter mellom «sudoers»-filformater\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1317
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Valg:\n"
+" -b, --base=dn base-domenenavn for sudo LDAP-forespørsler\n"
+" -c, --config=fil sti til oppsettsfil\n"
+" -d, --defaults=deftypes bare konverter standardverdier av valgte typer\n"
+" -e, --expand-aliases utvid aliaser ved konvertering\n"
+" -f, --output-format=format velg utdata-format («JSON», «LDIF» eller «sudoers»)\n"
+" -i, --input-format=format velg inndata-format («LDIF» eller «sudoers»)\n"
+" -I, --increment=tall mengde som hver sudoOrder skal økes med\n"
+" -h, --help vis hjelpetekst og avslutt\n"
+" -m, --match=filter bare konverter oppføringer som samsvarer med valgt filter\n"
+" -M, --match-local filtrer på passwd- og group-databaser\n"
+" -o, --output=utdatafile lagre konvertert sudoers i valgt utdatafil\n"
+" -O, --order-start=num startpunkt for første sudoOrder\n"
+" -p, --prune-matches fjern brukere, grupper og vertsnavn som ikke samsvarer\n"
+" -P, --padding=num grunnutfylling for sudoOrder-økning\n"
+" -s, --suppress=områder fjern utdata for valgte områder\n"
+" -V, --version vis versjonsinfo og avslutt"
+
+#: plugins/sudoers/cvtsudoers_json.c:684 plugins/sudoers/cvtsudoers_json.c:720
+#: plugins/sudoers/cvtsudoers_json.c:938
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "forvalg «%s» er ukjent"
+
+#: plugins/sudoers/cvtsudoers_json.c:858 plugins/sudoers/cvtsudoers_json.c:873
+#: plugins/sudoers/cvtsudoers_ldif.c:308 plugins/sudoers/cvtsudoers_ldif.c:319
+#: plugins/sudoers/ldap.c:482
+msgid "unable to get GMT time"
+msgstr "klarte ikke å hente GMT-tid"
+
+#: plugins/sudoers/cvtsudoers_json.c:861 plugins/sudoers/cvtsudoers_json.c:876
+#: plugins/sudoers/cvtsudoers_ldif.c:311 plugins/sudoers/cvtsudoers_ldif.c:322
+#: plugins/sudoers/ldap.c:488
+msgid "unable to format timestamp"
+msgstr "klarte ikke å formatere tidsstempel"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:526 plugins/sudoers/env.c:330
+#: plugins/sudoers/env.c:337 plugins/sudoers/env.c:442
+#: plugins/sudoers/ldap.c:496 plugins/sudoers/ldap.c:727
+#: plugins/sudoers/ldap.c:1060 plugins/sudoers/ldap_conf.c:227
+#: plugins/sudoers/ldap_conf.c:317 plugins/sudoers/linux_audit.c:89
+#: plugins/sudoers/logging.c:1105 plugins/sudoers/policy.c:625
+#: plugins/sudoers/policy.c:635 plugins/sudoers/prompt.c:168
+#: plugins/sudoers/sudoers.c:852 plugins/sudoers/testsudoers.c:257
+#: plugins/sudoers/toke_util.c:161
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "intern feil: %s er full"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:595
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "sudoers inneholder for mange linjer. Maksgrense er %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:638
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "miljøvariabel «SUDOERS_BASE» er tom, og «-b» er ikke valgt."
+
+#: plugins/sudoers/def_data.c:42
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Syslog-plassering, hvis syslog brukes til loggføring: %s"
+
+#: plugins/sudoers/def_data.c:46
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Syslog-prioritet når brukeren har autentisert seg: %s"
+
+#: plugins/sudoers/def_data.c:50
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Syslog-prioritet når brukeren ikke har klart å autentisere seg: %s"
+
+#: plugins/sudoers/def_data.c:54
+msgid "Put OTP prompt on its own line"
+msgstr "Legg OTP-ledetekst på egen linje"
+
+#: plugins/sudoers/def_data.c:58
+msgid "Ignore '.' in $PATH"
+msgstr "Ignorer «.» i $PATH"
+
+#: plugins/sudoers/def_data.c:62
+msgid "Always send mail when sudo is run"
+msgstr "Send alltid e-post når noen kjører sudo"
+
+#: plugins/sudoers/def_data.c:66
+msgid "Send mail if user authentication fails"
+msgstr "Send e-post hvis en bruker mislykkes i å autentisere seg"
+
+#: plugins/sudoers/def_data.c:70
+msgid "Send mail if the user is not in sudoers"
+msgstr "Send e-post hvis bruker ikke finnes i sudoers-fil"
+
+#: plugins/sudoers/def_data.c:74
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Send e-post hvis brukeren ikke finnes i sudoers-fil for denne verten"
+
+#: plugins/sudoers/def_data.c:78
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Send e-post hvis brukeren ikke har lov til å kjøre en kommando"
+
+#: plugins/sudoers/def_data.c:82
+msgid "Send mail if the user tries to run a command"
+msgstr "Send e-post hvis brukeren prøver å kjøre en kommando"
+
+#: plugins/sudoers/def_data.c:86
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Bruk separat tidsstempel for hver kombinasjon av bruker og tty"
+
+#: plugins/sudoers/def_data.c:90
+msgid "Lecture user the first time they run sudo"
+msgstr "Gi brukere en moralpreken første gang de kjører sudo"
+
+#: plugins/sudoers/def_data.c:94
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Fil som inneholder sudo-moralpreken: %s"
+
+#: plugins/sudoers/def_data.c:98
+msgid "Require users to authenticate by default"
+msgstr "Krev at brukere skal autentisere seg som standard"
+
+#: plugins/sudoers/def_data.c:102
+msgid "Root may run sudo"
+msgstr "Rotbruker kan kjøre sudo"
+
+#: plugins/sudoers/def_data.c:106
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Ta med vertsnavn i loggfil (ikke syslog)"
+
+#: plugins/sudoers/def_data.c:110
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Ta med år i loggfil (ikke syslog)"
+
+#: plugins/sudoers/def_data.c:114
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Start et skall hvis sudo kjøres uten argumenter"
+
+#: plugins/sudoers/def_data.c:118
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Velg målbrukers $HOME når et skall startes med «-s»"
+
+#: plugins/sudoers/def_data.c:122
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Bruk alltid målbrukers hjemmemappe som $HOME"
+
+#: plugins/sudoers/def_data.c:126
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Tillat informasjonsinnhenting for å gjøre feilmeldingene nyttige"
+
+#: plugins/sudoers/def_data.c:130
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Krev fullstendige vertsnavn i sudoers-fil"
+
+#: plugins/sudoers/def_data.c:134
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Send brukere en fornærmelsestekst når de oppgir feil passord"
+
+#: plugins/sudoers/def_data.c:138
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Bare tillat brukere å kjøre sudo hvis de bruker en tty"
+
+#: plugins/sudoers/def_data.c:142
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo tar hensyn til miljøvariabelen EDITOR"
+
+#: plugins/sudoers/def_data.c:146
+msgid "Prompt for root's password, not the users's"
+msgstr "Spør etter rotbrukers passord, i stedet for eget passord"
+
+#: plugins/sudoers/def_data.c:150
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Spør etter passord for «runas_default» i stedet for eget passord"
+
+#: plugins/sudoers/def_data.c:154
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Spør etter målbrukers passord, i stedet for eget passord"
+
+#: plugins/sudoers/def_data.c:158
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Bruk standardverdier i målbrukers innloggingsklasse, hvis den finnes"
+
+#: plugins/sudoers/def_data.c:162
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Gi verdier til miljøvariablene «LOGNAME» og «USER»"
+
+#: plugins/sudoers/def_data.c:166
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Velg målbrukers uid som effektiv uid, i stedet for faktisk uid"
+
+#: plugins/sudoers/def_data.c:170
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Ikke last inn målbrukers gruppevektor"
+
+#: plugins/sudoers/def_data.c:174
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Hvilken lengde linjer i loggfiler skal pakkes ned til (bruk 0 for å deaktivere pakking): %u"
+
+#: plugins/sudoers/def_data.c:178
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Tidsavbrudd for autentiseringstidsstempel: %.1f minutter"
+
+#: plugins/sudoers/def_data.c:182
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Tidsavbrudd for passordetterspørsel: %.1f minutter"
+
+#: plugins/sudoers/def_data.c:186
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Antall forsøk på å skrive inn passord: %u"
+
+#: plugins/sudoers/def_data.c:190
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "U-maske som skal brukes, eller 0777 for å bruke egen maske: 0%o"
+
+#: plugins/sudoers/def_data.c:194
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Sti til loggfil: %s"
+
+#: plugins/sudoers/def_data.c:198
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Sti til e-postprogram: %s"
+
+#: plugins/sudoers/def_data.c:202
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Valg for e-postprogram: %s"
+
+#: plugins/sudoers/def_data.c:206
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Hvilken adresse det skal sendes e-post til: %s"
+
+#: plugins/sudoers/def_data.c:210
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Hvilken adresse e-posten skal sendes fra: %s"
+
+#: plugins/sudoers/def_data.c:214
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Emnelinje i e-postmeldinger: %s"
+
+#: plugins/sudoers/def_data.c:218
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Melding om feil passord: %s"
+
+#: plugins/sudoers/def_data.c:222
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Sti til mappe for moralpreken-status: %s"
+
+#: plugins/sudoers/def_data.c:226
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Sti til mappe for autentiseringstidsstempel: %s"
+
+#: plugins/sudoers/def_data.c:230
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Eieren av mappa for autentiseringstidsstempel: %s"
+
+#: plugins/sudoers/def_data.c:234
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Brukerne i denne gruppa fritas fra passord- og PATH-krav: %s"
+
+#: plugins/sudoers/def_data.c:238
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Standard passord-ledetekst: %s"
+
+#: plugins/sudoers/def_data.c:242
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Hvis dette er valgt, blir system-ledetekst alltid overstyrt av passord-ledetekst."
+
+#: plugins/sudoers/def_data.c:246
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Standardbruker for kjøring av kommandoer: %s"
+
+#: plugins/sudoers/def_data.c:250
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Verdi som overstyrer brukerspesifikk $PATH: %s"
+
+#: plugins/sudoers/def_data.c:254
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Filsti til tekstbehandler som visudo skal bruke: %s"
+
+#: plugins/sudoers/def_data.c:258
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Når pseudokommandoen «list» skal kreve passord: %s"
+
+#: plugins/sudoers/def_data.c:262
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Når pseudokommandoen «verify» skal kreve passord: %s"
+
+#: plugins/sudoers/def_data.c:266
+msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+msgstr "Last inn prøvekjøringsfunksjonene som ligger i biblioteket «sudo_noexec»"
+
+#: plugins/sudoers/def_data.c:270
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Om lokal sudoers-fil skal ignoreres når en LDAP er aktiv"
+
+#: plugins/sudoers/def_data.c:274
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Fildeskriptorne >= %d lukkes før en kommando blir kjørt"
+
+#: plugins/sudoers/def_data.c:278
+msgid "If set, users may override the value of `closefrom' with the -C option"
+msgstr "Hvis dette er valgt, har brukerne mulighet til å overstyre «closefrom»-verdien med valget «-C»"
+
+#: plugins/sudoers/def_data.c:282
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Tillat brukere å velge arbitrære miljøvariabler"
+
+#: plugins/sudoers/def_data.c:286
+msgid "Reset the environment to a default set of variables"
+msgstr "Tilbakestill brukermiljøet til et sett med standardvariabler"
+
+#: plugins/sudoers/def_data.c:290
+msgid "Environment variables to check for sanity:"
+msgstr "Miljøvariabler som skal kontrolleres:"
+
+#: plugins/sudoers/def_data.c:294
+msgid "Environment variables to remove:"
+msgstr "Miljøvariabler som skal fjernes:"
+
+#: plugins/sudoers/def_data.c:298
+msgid "Environment variables to preserve:"
+msgstr "Miljøvariabler som skal beholdes:"
+
+#: plugins/sudoers/def_data.c:302
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "SELinux-rolle som skal brukes i ny sikkerhetskontekst: %s"
+
+#: plugins/sudoers/def_data.c:306
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "SELinux-type som skal brukes i ny sikkerhetskontekst: %s"
+
+#: plugins/sudoers/def_data.c:310
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Sti til sudo-spesifikk miljøfil: %s"
+
+#: plugins/sudoers/def_data.c:314
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Sti til sudo-spesifikk miljøfil: %s"
+
+#: plugins/sudoers/def_data.c:318
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Regioninnstilling som skal brukes når «sudoers» tolkes: %s"
+
+#: plugins/sudoers/def_data.c:322
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Tillat sudo å spørre etter et passord som - hvis skrevet inn - blir synlig på skjermen"
+
+#: plugins/sudoers/def_data.c:326
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Gi visuell respons når brukere skriver inn passord"
+
+#: plugins/sudoers/def_data.c:330
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Bruk raskere joker-søking som er mindre presis (og som ikke søker i filsystemet)"
+
+#: plugins/sudoers/def_data.c:334
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "U-masker som er valgt i sudoers overstyrer brukermasker, selv hvis sudoers åpner for mer tilgang enn brukermaska"
+
+#: plugins/sudoers/def_data.c:338
+msgid "Log user's input for the command being run"
+msgstr "Loggfør bruker-inndata i kommandoen som kjøres"
+
+#: plugins/sudoers/def_data.c:342
+msgid "Log the output of the command being run"
+msgstr "Loggfør utskrift fra kommandoen som kjøres"
+
+#: plugins/sudoers/def_data.c:346
+msgid "Compress I/O logs using zlib"
+msgstr "Komprimer inn- og utdatalogger ved bruk av «zlib»"
+
+#: plugins/sudoers/def_data.c:350
+msgid "Always run commands in a pseudo-tty"
+msgstr "Kjør alltid kommandoer i en pseudo-tty"
+
+#: plugins/sudoers/def_data.c:354
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Støttetillegg for grupper som ikke er Unix-grupper: %s"
+
+#: plugins/sudoers/def_data.c:358
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Mappe hvor inn- og utdatalogger skal lagres: %s"
+
+#: plugins/sudoers/def_data.c:362
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Fil hvor inn- og utdatalogger skal lagres: %s"
+
+#: plugins/sudoers/def_data.c:366
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Legg til en oppføring i utmp-/utmpx-fil ved tildeling av pty"
+
+#: plugins/sudoers/def_data.c:370
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Kjør kommandoer som utmp-bruker, i stedet for brukeren som skriver inn kommando"
+
+#: plugins/sudoers/def_data.c:374
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Tillatte privilegier: %s"
+
+#: plugins/sudoers/def_data.c:378
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Begrensningsprivilegier: %s"
+
+#: plugins/sudoers/def_data.c:382
+msgid "Run commands on a pty in the background"
+msgstr "Kjør kommandoer på en pty i bakgrunnen"
+
+#: plugins/sudoers/def_data.c:386
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "PAM-tjenestenavn som skal brukes: %s"
+
+#: plugins/sudoers/def_data.c:390
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "PAM-tjenestenavn som skal brukes til innloggingsskall: %s"
+
+#: plugins/sudoers/def_data.c:394
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Prøv å sette opp PAM-akkreditiver for målbruker"
+
+#: plugins/sudoers/def_data.c:398
+msgid "Create a new PAM session for the command to run in"
+msgstr "Lag en ny PAM-økt som kommandoen kjøres i"
+
+#: plugins/sudoers/def_data.c:402
+msgid "Perform PAM account validation management"
+msgstr "Håndter validering av PAM-kontoer"
+
+#: plugins/sudoers/def_data.c:406
+#, c-format
+msgid "Maximum I/O log sequence number: %u"
+msgstr "Høyeste tillatte sekvensnummer i inn-/utdatalogg: %u"
+
+#: plugins/sudoers/def_data.c:410
+msgid "Enable sudoers netgroup support"
+msgstr "Slå på støtte for sudoers-nettgruppe"
+
+#: plugins/sudoers/def_data.c:414
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Kontroller skrivetillatelse til foreldermapper ved redigering av filer med sudoedit"
+
+#: plugins/sudoers/def_data.c:418
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Følg symbolske lenker ved redigering av filer med sudoedit"
+
+#: plugins/sudoers/def_data.c:422
+msgid "Query the group plugin for unknown system groups"
+msgstr "Spør gruppetillegget om ukjente systemgrupper"
+
+#: plugins/sudoers/def_data.c:426
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Kontroller nettgrupper basert på både bruker, vert og domene"
+
+#: plugins/sudoers/def_data.c:430
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Tillat kjøring av kommandoer selv om sudo ikke klarer å skrive til revisjonslogg"
+
+#: plugins/sudoers/def_data.c:434
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Tillat kjøring av kommandoer selv om sudo ikke klarer å skrive til I/O-logg"
+
+#: plugins/sudoers/def_data.c:438
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Tillat kjøring av kommandoer selv om sudo ikke klarer å skrive til loggfil"
+
+#: plugins/sudoers/def_data.c:442
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Slå opp grupper i sudoers på gruppe-ID i stedet for gruppenavn"
+
+#: plugins/sudoers/def_data.c:446
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Loggoppføringer som er større enn dette blir delt opp i flere syslog-meldinger: %u"
+
+#: plugins/sudoers/def_data.c:450
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Bruker som skal eie I/O-loggfiler: %s"
+
+#: plugins/sudoers/def_data.c:454
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Gruppe som skal eie I/O-loggfiler: %s"
+
+#: plugins/sudoers/def_data.c:458
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Filmodus for I/O-loggfiler: 0%o"
+
+#: plugins/sudoers/def_data.c:462
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Kjør kommandoer med fildeskriptor i stedet for sti: %s"
+
+#: plugins/sudoers/def_data.c:466
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Ignorer ukjente standardverdier i sudoers i stedet for å vise advarsel"
+
+#: plugins/sudoers/def_data.c:470
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "TIdsavbrudd for kommando: %u sekunder"
+
+#: plugins/sudoers/def_data.c:474
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "La bruker velge tidsavbrudd via kommandolinje"
+
+#: plugins/sudoers/def_data.c:478
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Tøm inn- og utdata direkte til disk i stedet for å mellomlagre"
+
+#: plugins/sudoers/def_data.c:482
+msgid "Include the process ID when logging via syslog"
+msgstr "Ta med prosess-ID ved bruk av syslog"
+
+#: plugins/sudoers/def_data.c:486
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Type autentiseringstidsstempel: %s"
+
+#: plugins/sudoers/def_data.c:490
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Feilmelding ved autentisering: %s"
+
+#: plugins/sudoers/def_data.c:494
+msgid "Ignore case when matching user names"
+msgstr "Ignorer små/store bokstaver i brukernavn"
+
+#: plugins/sudoers/def_data.c:498
+msgid "Ignore case when matching group names"
+msgstr "Ignorer små/store bokstaver i gruppenavn"
+
+#: plugins/sudoers/def_data.c:502
+msgid "Log when a command is allowed by sudoers"
+msgstr "Loggfør kommandoer som er tillatt av sudoers"
+
+#: plugins/sudoers/def_data.c:506
+msgid "Log when a command is denied by sudoers"
+msgstr "Loggfør kommandoer som er avvist av sudoers"
+
+#: plugins/sudoers/defaults.c:231
+#, c-format
+msgid "%s:%d unknown defaults entry \"%s\""
+msgstr "%s: %d «%s» er en ukjent standardoppføring"
+
+#: plugins/sudoers/defaults.c:234
+#, c-format
+msgid "%s: unknown defaults entry \"%s\""
+msgstr "%s: «%s» er en ukjent standardoppføring"
+
+#: plugins/sudoers/defaults.c:277
+#, c-format
+msgid "%s:%d no value specified for \"%s\""
+msgstr "%s: %d «%s» har ingen verdi"
+
+#: plugins/sudoers/defaults.c:280
+#, c-format
+msgid "%s: no value specified for \"%s\""
+msgstr "%s: «%s» har ingen verdi"
+
+#: plugins/sudoers/defaults.c:300
+#, c-format
+msgid "%s:%d values for \"%s\" must start with a '/'"
+msgstr "%s:%d verdier av «%s» må begynne med «/»"
+
+#: plugins/sudoers/defaults.c:303
+#, c-format
+msgid "%s: values for \"%s\" must start with a '/'"
+msgstr "%s: verdier av «%s» må begynne med «/»"
+
+#: plugins/sudoers/defaults.c:325
+#, c-format
+msgid "%s:%d option \"%s\" does not take a value"
+msgstr "%s:%d «%s» kan ikke ha en verdi"
+
+#: plugins/sudoers/defaults.c:328
+#, c-format
+msgid "%s: option \"%s\" does not take a value"
+msgstr "%s: «%s» kan ikke ha en verdi"
+
+#: plugins/sudoers/defaults.c:353
+#, c-format
+msgid "%s:%d invalid Defaults type 0x%x for option \"%s\""
+msgstr "%s:%d Defaults-type 0x%x for valget «%s» er ugyldig"
+
+#: plugins/sudoers/defaults.c:356
+#, c-format
+msgid "%s: invalid Defaults type 0x%x for option \"%s\""
+msgstr "%s: Defaults-type 0x%x for valget «%s» er ugyldig"
+
+#: plugins/sudoers/defaults.c:366
+#, c-format
+msgid "%s:%d value \"%s\" is invalid for option \"%s\""
+msgstr "%s:%d «%s» er en ugyldig verdi for valget «%s»"
+
+#: plugins/sudoers/defaults.c:369
+#, c-format
+msgid "%s: value \"%s\" is invalid for option \"%s\""
+msgstr "%s: verdien «%s» er ugyldig valget «%s»"
+
+#: plugins/sudoers/env.c:411
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: envp er korrupt (lengde samsvarer ikke)"
+
+#: plugins/sudoers/env.c:1132
+msgid "unable to rebuild the environment"
+msgstr "klarte ikke å bygge opp miljøet på nytt"
+
+#: plugins/sudoers/env.c:1206
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "du har ikke tillatelse til å bestemme følgende miljøvariabler: %s"
+
+#: plugins/sudoers/file.c:116
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr "tolkningsfeil i %s ved linje %d"
+
+#: plugins/sudoers/file.c:119
+#, c-format
+msgid "parse error in %s"
+msgstr "tolkningsfeil i %s"
+
+#: plugins/sudoers/filedigest.c:61
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr "behandlingstype %d for %s støttes ikke"
+
+#: plugins/sudoers/filedigest.c:90
+#, c-format
+msgid "%s: read error"
+msgstr "%s: lesefeil"
+
+#: plugins/sudoers/group_plugin.c:90
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s må eies av uid %d"
+
+#: plugins/sudoers/group_plugin.c:94
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr "%s kan ikke gi skrivetillatelse til andre enn eieren"
+
+#: plugins/sudoers/group_plugin.c:102 plugins/sudoers/sssd.c:562
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "klarte ikke å laste inn %s. %s"
+
+#: plugins/sudoers/group_plugin.c:108
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "fant ikke symbolet «group_plugin» i %s"
+
+#: plugins/sudoers/group_plugin.c:113
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: versjon %d av gruppetillegget passer ikke (forventet versjon %d)"
+
+#: plugins/sudoers/interfaces.c:86 plugins/sudoers/interfaces.c:103
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "klarte ikke å tolke IP-adresse «%s»"
+
+#: plugins/sudoers/interfaces.c:91 plugins/sudoers/interfaces.c:108
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "klarte ikke å tolke nettverksmaske «%s»"
+
+#: plugins/sudoers/interfaces.c:136
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Lokale par av IP-adresser og nettverksmasker:\n"
+
+#: plugins/sudoers/iolog.c:117 plugins/sudoers/mkdir_parents.c:82
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s finnes, men er ikke en mappe (0%o)"
+
+#: plugins/sudoers/iolog.c:142 plugins/sudoers/iolog.c:182
+#: plugins/sudoers/mkdir_parents.c:71 plugins/sudoers/timestamp.c:212
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "klarte ikke å utføre mkdir %s"
+
+#: plugins/sudoers/iolog.c:186 plugins/sudoers/visudo.c:739
+#: plugins/sudoers/visudo.c:750
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "klarte ikke å endre %s modus til 0%o"
+
+#: plugins/sudoers/iolog.c:294 plugins/sudoers/sudoers.c:1194
+#: plugins/sudoers/testsudoers.c:424
+#, c-format
+msgid "unknown group: %s"
+msgstr "%s er en ukjent gruppe"
+
+#: plugins/sudoers/iolog.c:464 plugins/sudoers/sudoers.c:918
+#: plugins/sudoers/sudoreplay.c:846 plugins/sudoers/sudoreplay.c:1542
+#: plugins/sudoers/tsdump.c:145
+#, c-format
+msgid "unable to read %s"
+msgstr "klarte ikke å lese %s"
+
+#: plugins/sudoers/iolog.c:579 plugins/sudoers/iolog.c:801
+#, c-format
+msgid "unable to create %s"
+msgstr "klarte ikke å opprette %s"
+
+#: plugins/sudoers/iolog.c:824 plugins/sudoers/iolog.c:1039
+#: plugins/sudoers/iolog.c:1115 plugins/sudoers/iolog.c:1209
+#: plugins/sudoers/iolog.c:1270
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "klarte ikke å skrive til I/O-loggfil: %s"
+
+#: plugins/sudoers/iolog.c:1073
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: intern feil. Inn-/ut-loggfil for hendelse %d er ikke åpen"
+
+#: plugins/sudoers/iolog.c:1233
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: intern feil. Signal %d er ugyldig"
+
+#: plugins/sudoers/iolog_util.c:90
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: ugyldig loggfil"
+
+#: plugins/sudoers/iolog_util.c:108
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: tidsstempel-felt mangler"
+
+#: plugins/sudoers/iolog_util.c:114
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: tidsstempel %s: %s"
+
+#: plugins/sudoers/iolog_util.c:121
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: brukerfelt mangler"
+
+#: plugins/sudoers/iolog_util.c:130
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: «kjør som bruker»-felt mangler"
+
+#: plugins/sudoers/iolog_util.c:139
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: «kjør som gruppe»-felt mangler"
+
+#: plugins/sudoers/ldap.c:178 plugins/sudoers/ldap_conf.c:296
+msgid "starttls not supported when using ldaps"
+msgstr "starttls støttes ikke når du bruker ldaps"
+
+#: plugins/sudoers/ldap.c:249
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "klarte ikke å starte opp database for SSL-sertifikater og -nøkler. %s"
+
+#: plugins/sudoers/ldap.c:252
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "du må velge TLS_CERT i %s for å bruke SSL"
+
+#: plugins/sudoers/ldap.c:1620
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "klarte ikke å starte opp LDAP. %s"
+
+#: plugins/sudoers/ldap.c:1656
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls er valgt, men LDAP-bibliotekene støtter hverken «ldap_start_tls_s()» eller «ldap_start_tls_s_np()»"
+
+#: plugins/sudoers/ldap.c:1793 plugins/sudoers/parse_ldif.c:734
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "«%s» er en ugyldig sudoOrder-attributt"
+
+#: plugins/sudoers/ldap_conf.c:205
+msgid "sudo_ldap_conf_add_ports: port too large"
+msgstr "sudo_ldap_conf_add_ports: portnummeret er for stort"
+
+#: plugins/sudoers/ldap_conf.c:265
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "LDAP-ens adressetype %s støttes ikke"
+
+#: plugins/sudoers/ldap_conf.c:292
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "du kan ikke blande ldap- og ldaps-nettadresser"
+
+#: plugins/sudoers/ldap_util.c:456 plugins/sudoers/ldap_util.c:458
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "klarte ikke å konvertere sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:59
+msgid "unable to open audit system"
+msgstr "klarte ikke å åpne revisjonssystemet"
+
+#: plugins/sudoers/linux_audit.c:100
+msgid "unable to send audit message"
+msgstr "klarte ikke å sende revisjonsmelding"
+
+#: plugins/sudoers/logging.c:120
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: plugins/sudoers/logging.c:148
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (kommando fortsetter) %s"
+
+#: plugins/sudoers/logging.c:177
+#, c-format
+msgid "unable to open log file: %s"
+msgstr "klarte ikke å åpne loggfil: %s"
+
+#: plugins/sudoers/logging.c:185
+#, c-format
+msgid "unable to lock log file: %s"
+msgstr "klarte ikke å låse loggfil: %s"
+
+#: plugins/sudoers/logging.c:218
+#, c-format
+msgid "unable to write log file: %s"
+msgstr "klarte ikke å skrive loggfil: %s"
+
+#: plugins/sudoers/logging.c:248
+msgid "No user or host"
+msgstr "Ingen bruker eller vert"
+
+#: plugins/sudoers/logging.c:250
+msgid "validation failure"
+msgstr "feil ved gyldighetssjekk"
+
+#: plugins/sudoers/logging.c:261
+msgid "user NOT in sudoers"
+msgstr "brukeren er IKKE i sudoers"
+
+#: plugins/sudoers/logging.c:263
+msgid "user NOT authorized on host"
+msgstr "brukeren er IKKE autorisert på verten"
+
+#: plugins/sudoers/logging.c:265
+msgid "command not allowed"
+msgstr "denne kommandoen tillates ikke"
+
+#: plugins/sudoers/logging.c:301
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr "%s finnes ikke i sudoers-fil. Denne hendelsen blir rapportert.\n"
+
+#: plugins/sudoers/logging.c:304
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr "%s has ikke tillatelse til å kjøre sudo på %s. Denne hendelsen blir rapportert.\n"
+
+#: plugins/sudoers/logging.c:308
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Brukeren %s kan ikke kjøre sudo på %s.\n"
+
+#: plugins/sudoers/logging.c:311
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr "Brukeren %s har ikke tillatelse til å kjøre «%s%s%s» som %s%s%s på %s.\n"
+
+#: plugins/sudoers/logging.c:348 plugins/sudoers/sudoers.c:442
+#: plugins/sudoers/sudoers.c:444 plugins/sudoers/sudoers.c:446
+#: plugins/sudoers/sudoers.c:448 plugins/sudoers/sudoers.c:603
+#: plugins/sudoers/sudoers.c:605
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: fant ikke kommando"
+
+#: plugins/sudoers/logging.c:350 plugins/sudoers/sudoers.c:438
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"ignorerer «%s» i «.».\n"
+"Bruk «sudo ./%s» hvis dette er «%s»-programmet du prøver å kjøre."
+
+#: plugins/sudoers/logging.c:367
+msgid "authentication failure"
+msgstr "feil ved autentisering"
+
+#: plugins/sudoers/logging.c:393
+msgid "a password is required"
+msgstr "du må oppgi et passord"
+
+#: plugins/sudoers/logging.c:463
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u mislykket passordforsøk"
+msgstr[1] "%u mislykkede passordforsøk"
+
+#: plugins/sudoers/logging.c:728
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "klarte ikke å duplisere standard innkanal. %m"
+
+#: plugins/sudoers/logging.c:768
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "klarte ikke å kjøre %s. %m"
+
+#: plugins/sudoers/logging.c:809 plugins/sudoers/logging.c:865
+#, c-format
+msgid "unable to fork: %m"
+msgstr "klarte ikke å kopiere prosess. %m"
+
+#: plugins/sudoers/logging.c:855
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "klarte ikke å åpne datarør. %m"
+
+#: plugins/sudoers/match_digest.c:103
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "behandlingen for %s (%s) er ikke i %s-skjemaet"
+
+#: plugins/sudoers/mkdir_parents.c:77 plugins/sudoers/sudoers.c:943
+#: plugins/sudoers/visudo.c:437 plugins/sudoers/visudo.c:733
+#, c-format
+msgid "unable to stat %s"
+msgstr "klarte ikke å lage statistikk av %s"
+
+#: plugins/sudoers/parse.c:449
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+"\n"
+"LDAP-rolle: %s\n"
+
+#: plugins/sudoers/parse.c:452
+#, c-format
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+"\n"
+"Oppføring i sudoers:\n"
+
+#: plugins/sudoers/parse.c:454
+#, c-format
+msgid " RunAsUsers: "
+msgstr " Kjør som-brukere: "
+
+#: plugins/sudoers/parse.c:469
+#, c-format
+msgid " RunAsGroups: "
+msgstr " Kjør som-grupper: "
+
+#: plugins/sudoers/parse.c:479
+#, c-format
+msgid " Options: "
+msgstr " Valg: "
+
+#: plugins/sudoers/parse.c:529
+#, c-format
+msgid " Commands:\n"
+msgstr " Kommandoer:\n"
+
+#: plugins/sudoers/parse.c:720
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Standardoppføringer som gjelder for %s på %s:\n"
+
+#: plugins/sudoers/parse.c:738
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Kjør-som- og kommandospesifikke standardoppføringer for %s:\n"
+
+#: plugins/sudoers/parse.c:756
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "Brukeren %s kan kjøre følgende kommandoer på %s:\n"
+
+#: plugins/sudoers/parse.c:771
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Brukeren %s har ikke tillatelse til å kjøre sudo på %s.\n"
+
+#: plugins/sudoers/parse_ldif.c:604
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "ignorerer ufullstendig sudoRole: cn: %s"
+
+#: plugins/sudoers/parse_ldif.c:664
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "«%s» er en ugyldig LDIF-attributt"
+
+#: plugins/sudoers/policy.c:90 plugins/sudoers/policy.c:116
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "ugyldig %.*s fra sudo-grenseflate"
+
+#: plugins/sudoers/policy.c:295 plugins/sudoers/testsudoers.c:280
+msgid "unable to parse network address list"
+msgstr "klarte ikke å tolke nettverksadresse-liste"
+
+#: plugins/sudoers/policy.c:439
+msgid "user name not set by sudo front-end"
+msgstr "sudo-grenseflate har ikke angitt brukernavn"
+
+#: plugins/sudoers/policy.c:443
+msgid "user-ID not set by sudo front-end"
+msgstr "sudo-grenseflate har ikke angitt bruker-ID"
+
+#: plugins/sudoers/policy.c:447
+msgid "group-ID not set by sudo front-end"
+msgstr "sudo-grenseflate har ikke valgt gruppe-ID"
+
+#: plugins/sudoers/policy.c:451
+msgid "host name not set by sudo front-end"
+msgstr "sudo-grenseflate har ikke angitt vertsnavn"
+
+#: plugins/sudoers/policy.c:808 plugins/sudoers/visudo.c:236
+#: plugins/sudoers/visudo.c:867
+#, c-format
+msgid "unable to execute %s"
+msgstr "klarte ikke å kjøre %s"
+
+#: plugins/sudoers/policy.c:939
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Sudoers regeltillegg versjon %s\n"
+
+#: plugins/sudoers/policy.c:941
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Sudoers-grammatikkversjon %d\n"
+
+#: plugins/sudoers/policy.c:945
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Sti til «sudoers»-fil: %s\n"
+
+#: plugins/sudoers/policy.c:948
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "Sti til «nsswitch»: %s\n"
+
+#: plugins/sudoers/policy.c:950
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "Sti til «ldap.conf»: %s\n"
+
+#: plugins/sudoers/policy.c:951
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "Stil til «ldap.secret»: %s\n"
+
+#: plugins/sudoers/policy.c:984
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "klarte ikke å tildele krok av typen %d (versjon %d.%d)"
+
+#: plugins/sudoers/pwutil.c:222 plugins/sudoers/pwutil.c:240
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "klarte ikke å hurtiglagre uid %u"
+
+#: plugins/sudoers/pwutil.c:234
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "klarte ikke å hurtiglagre uid %u. Uid-en eksisterer allerede"
+
+#: plugins/sudoers/pwutil.c:294 plugins/sudoers/pwutil.c:312
+#: plugins/sudoers/pwutil.c:375 plugins/sudoers/pwutil.c:420
+#, c-format
+msgid "unable to cache user %s"
+msgstr "klarte ikke å hurtiglagre bruker %s"
+
+#: plugins/sudoers/pwutil.c:307
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "klarte ikke å hurtiglagre brukeren %s. Brukeren eksisterer allerede"
+
+#: plugins/sudoers/pwutil.c:539 plugins/sudoers/pwutil.c:557
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "klarte ikke å hurtiglagre gid %u"
+
+#: plugins/sudoers/pwutil.c:551
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "klarte ikke å hurtiglagre gid %u. Gid-en eksisterer allerede"
+
+#: plugins/sudoers/pwutil.c:604 plugins/sudoers/pwutil.c:622
+#: plugins/sudoers/pwutil.c:670 plugins/sudoers/pwutil.c:712
+#, c-format
+msgid "unable to cache group %s"
+msgstr "klarte ikke å hurtiglagre gruppe %s"
+
+#: plugins/sudoers/pwutil.c:617
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "klarte ikke å hurtiglagre gruppa %s. Gruppa eksisterer allerede"
+
+#: plugins/sudoers/pwutil.c:839 plugins/sudoers/pwutil.c:891
+#: plugins/sudoers/pwutil.c:941 plugins/sudoers/pwutil.c:994
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "klarte ikke å hurtiglagre liste over %s. Lista eksisterer allerede"
+
+#: plugins/sudoers/pwutil.c:845 plugins/sudoers/pwutil.c:896
+#: plugins/sudoers/pwutil.c:947 plugins/sudoers/pwutil.c:999
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "klarte ikke å hurtiglagre gruppeliste for %s"
+
+#: plugins/sudoers/pwutil.c:885
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "klarte ikke å tolke grupper for %s"
+
+#: plugins/sudoers/pwutil.c:988
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "klarte ikke å tolke gid-er for %s"
+
+#: plugins/sudoers/set_perms.c:120 plugins/sudoers/set_perms.c:478
+#: plugins/sudoers/set_perms.c:921 plugins/sudoers/set_perms.c:1254
+#: plugins/sudoers/set_perms.c:1573
+msgid "perm stack overflow"
+msgstr "perm-stabelen er full"
+
+#: plugins/sudoers/set_perms.c:128 plugins/sudoers/set_perms.c:409
+#: plugins/sudoers/set_perms.c:486 plugins/sudoers/set_perms.c:788
+#: plugins/sudoers/set_perms.c:929 plugins/sudoers/set_perms.c:1178
+#: plugins/sudoers/set_perms.c:1262 plugins/sudoers/set_perms.c:1506
+#: plugins/sudoers/set_perms.c:1581 plugins/sudoers/set_perms.c:1672
+msgid "perm stack underflow"
+msgstr "perm-stabelen er tom"
+
+#: plugins/sudoers/set_perms.c:187 plugins/sudoers/set_perms.c:532
+#: plugins/sudoers/set_perms.c:1315 plugins/sudoers/set_perms.c:1614
+msgid "unable to change to root gid"
+msgstr "klarte ikke å endre gid til rotbruker"
+
+#: plugins/sudoers/set_perms.c:278 plugins/sudoers/set_perms.c:629
+#: plugins/sudoers/set_perms.c:1060 plugins/sudoers/set_perms.c:1392
+msgid "unable to change to runas gid"
+msgstr "klarte ikke å endre til kjør som-gid"
+
+#: plugins/sudoers/set_perms.c:283 plugins/sudoers/set_perms.c:634
+#: plugins/sudoers/set_perms.c:1065 plugins/sudoers/set_perms.c:1397
+msgid "unable to set runas group vector"
+msgstr "klarte ikke å velge «kjør som»-gruppevektor"
+
+#: plugins/sudoers/set_perms.c:294 plugins/sudoers/set_perms.c:645
+#: plugins/sudoers/set_perms.c:1074 plugins/sudoers/set_perms.c:1406
+msgid "unable to change to runas uid"
+msgstr "klarte ikke å endre uid til «kjør som»-bruker"
+
+#: plugins/sudoers/set_perms.c:312 plugins/sudoers/set_perms.c:663
+#: plugins/sudoers/set_perms.c:1090 plugins/sudoers/set_perms.c:1422
+msgid "unable to change to sudoers gid"
+msgstr "klarte ikke å endre gid til sudoers"
+
+#: plugins/sudoers/set_perms.c:396 plugins/sudoers/set_perms.c:775
+#: plugins/sudoers/set_perms.c:1165 plugins/sudoers/set_perms.c:1493
+#: plugins/sudoers/set_perms.c:1659
+msgid "too many processes"
+msgstr "for mange prosesser"
+
+#: plugins/sudoers/solaris_audit.c:58
+msgid "unable to get current working directory"
+msgstr "klarte ikke å hente gjeldende arbeidsmappe"
+
+#: plugins/sudoers/solaris_audit.c:66
+#, c-format
+msgid "truncated audit path user_cmnd: %s"
+msgstr "forkortet revisjonssti «user_cmnd»: %s"
+
+#: plugins/sudoers/solaris_audit.c:73
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "forkortet revisjonssti «argv[0]»: %s"
+
+#: plugins/sudoers/solaris_audit.c:122
+msgid "audit_failure message too long"
+msgstr "audit_failure-meldinga er for lang"
+
+#: plugins/sudoers/sssd.c:564
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "klarte ikke å starte opp SSS-kilde. Har du installert SSSD på maskinen?"
+
+#: plugins/sudoers/sssd.c:572 plugins/sudoers/sssd.c:581
+#: plugins/sudoers/sssd.c:590 plugins/sudoers/sssd.c:599
+#: plugins/sudoers/sssd.c:608
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "fant ikke symbolet «%s» i %s"
+
+#: plugins/sudoers/sudoers.c:212 plugins/sudoers/sudoers.c:871
+msgid "problem with defaults entries"
+msgstr "det har oppstått et problem med én eller flere standardoppføringer"
+
+#: plugins/sudoers/sudoers.c:216
+msgid "no valid sudoers sources found, quitting"
+msgstr "fant ingen gyldig sudoers-kilde. Avslutter."
+
+#: plugins/sudoers/sudoers.c:254
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers-fil tillater ikke rotbruker å kjøre sudo"
+
+#: plugins/sudoers/sudoers.c:312
+msgid "you are not permitted to use the -C option"
+msgstr "du har ikke tillatelse til å bruke valget «-C»"
+
+#: plugins/sudoers/sudoers.c:359
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr "eier («%s») av tidsstempel finnes ikke"
+
+#: plugins/sudoers/sudoers.c:374
+msgid "no tty"
+msgstr "ingen tty"
+
+#: plugins/sudoers/sudoers.c:375
+msgid "sorry, you must have a tty to run sudo"
+msgstr "du må ha en tty for å kunne kjøre sudo"
+
+#: plugins/sudoers/sudoers.c:437
+msgid "command in current directory"
+msgstr "kommando i gjeldende mappe"
+
+#: plugins/sudoers/sudoers.c:456
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "du har ikke tillatelse til å velge tidsavbrudd for kommandoer"
+
+#: plugins/sudoers/sudoers.c:464
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "du har ikke tillatelse til å beholde brukermiljøet"
+
+#: plugins/sudoers/sudoers.c:815
+msgid "command too long"
+msgstr "kommandoen er for lang"
+
+#: plugins/sudoers/sudoers.c:947
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s er ikke en vanlig fil"
+
+#: plugins/sudoers/sudoers.c:951 plugins/sudoers/timestamp.c:259 toke.l:967
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s eies av uid %u, som skulle vært %u"
+
+#: plugins/sudoers/sudoers.c:955 toke.l:972
+#, c-format
+msgid "%s is world writable"
+msgstr "%s kan overskrives av alle"
+
+#: plugins/sudoers/sudoers.c:959 toke.l:975
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s eies av gid %u, som skulle vært %u"
+
+#: plugins/sudoers/sudoers.c:992
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "du må være rotbruker for å velge «-c %s»"
+
+#: plugins/sudoers/sudoers.c:1011
+#, c-format
+msgid "unknown login class: %s"
+msgstr "innloggingsklasse %s er ukjent"
+
+#: plugins/sudoers/sudoers.c:1096 plugins/sudoers/sudoers.c:1110
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "klarte ikke å slå opp vertsnavn %s"
+
+#: plugins/sudoers/sudoreplay.c:250
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "%s er et ugyldig filtervalg"
+
+#: plugins/sudoers/sudoreplay.c:263
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "%s er ugyldig maksimal ventetid"
+
+#: plugins/sudoers/sudoreplay.c:286
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "%s er en ugyldig hastighetsfaktor"
+
+#: plugins/sudoers/sudoreplay.c:321
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s/timing: %s"
+msgstr "%s/%.2s/%.2s/%.2s/tidsberegning: %s"
+
+#: plugins/sudoers/sudoreplay.c:326
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/tidsberegning: %s"
+
+#: plugins/sudoers/sudoreplay.c:330
+#, c-format
+msgid "%s/%s/timing: %s"
+msgstr "%s/%s/tidsberegning: %s"
+
+#: plugins/sudoers/sudoreplay.c:346
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Spiller av sudo-økt i reprise: %s"
+
+#: plugins/sudoers/sudoreplay.c:544 plugins/sudoers/sudoreplay.c:591
+#: plugins/sudoers/sudoreplay.c:789 plugins/sudoers/sudoreplay.c:898
+#: plugins/sudoers/sudoreplay.c:983 plugins/sudoers/sudoreplay.c:998
+#: plugins/sudoers/sudoreplay.c:1005 plugins/sudoers/sudoreplay.c:1012
+#: plugins/sudoers/sudoreplay.c:1019 plugins/sudoers/sudoreplay.c:1026
+#: plugins/sudoers/sudoreplay.c:1174
+msgid "unable to add event to queue"
+msgstr "klarte ikke å legge hendelse i kø"
+
+#: plugins/sudoers/sudoreplay.c:659
+msgid "unable to set tty to raw mode"
+msgstr "klarte ikke å velge råmodus for tty"
+
+#: plugins/sudoers/sudoreplay.c:710
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr "Advarsel: terminalen din er for liten for å spille av loggen skikkelig.\n"
+
+#: plugins/sudoers/sudoreplay.c:711
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Loggens størrelse er %d x %d, mens terminalstørrelsen din er %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:739
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Sudo-reprise ferdig. Trykk på en knapp for å gå tilbake til terminal."
+
+#: plugins/sudoers/sudoreplay.c:772
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "linja for tidsberegningsfil er ugyldig: %s"
+
+#: plugins/sudoers/sudoreplay.c:1208 plugins/sudoers/sudoreplay.c:1233
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "uttrykket «%s» er flertydig"
+
+#: plugins/sudoers/sudoreplay.c:1255
+msgid "unmatched ')' in expression"
+msgstr "fant ingenting som samsvarer med deluttrykket «)»"
+
+#: plugins/sudoers/sudoreplay.c:1259
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "«%s» er et ukjent søkevalg"
+
+#: plugins/sudoers/sudoreplay.c:1274
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s krever at du bruker et argument"
+
+#: plugins/sudoers/sudoreplay.c:1277 plugins/sudoers/sudoreplay.c:1518
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr "%s er et ugyldig regulært uttrykk"
+
+#: plugins/sudoers/sudoreplay.c:1281
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "klarte ikke å tolke datoen «%s»"
+
+#: plugins/sudoers/sudoreplay.c:1290
+msgid "unmatched '(' in expression"
+msgstr "uttrykkets «(» samsvarer ikke"
+
+#: plugins/sudoers/sudoreplay.c:1292
+msgid "illegal trailing \"or\""
+msgstr "du kan ikke avslutte med «or»"
+
+#: plugins/sudoers/sudoreplay.c:1294
+msgid "illegal trailing \"!\""
+msgstr "du kan ikke avslutte med «!»"
+
+#: plugins/sudoers/sudoreplay.c:1344
+#, c-format
+msgid "unknown search type %d"
+msgstr "«%d» er en ukjent søketype"
+
+#: plugins/sudoers/sudoreplay.c:1611
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "bruk: %s [-hnRS] [-d mappe] [-m tall] [-s tall] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1614
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "bruk: %s [-h] [-d dir] -l [søkeuttrykk]\n"
+
+#: plugins/sudoers/sudoreplay.c:1623
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - spill av sudo-øktlogg\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1625
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Valg:\n"
+" -d, --directory=dir velg loggfil-mappe\n"
+" -f, --filter=filter velg hvilke(n) inn- og utdatatype(r) som skal vises\n"
+" -h, --help vis hjelpetekst og avslutt\n"
+" -l, --list vis tilgjengelige ID-er, med valgfritt uttrykk\n"
+" -m, --max-wait=num maskimal ventetid mellom hendelser (i sekunder)\n"
+" -n, --non-interactive ingen ledetekst (send alt til standardutdata)\n"
+" -R, --no-resize ikke prøv å endre terminalstørrelse\n"
+" -S, --suspend-wait vent mens kommando er på pause\n"
+" -s, --speed=num øk eller senk utskriftshastigheten\n"
+" -V, --version vis versjon og avslutt"
+
+#: plugins/sudoers/testsudoers.c:362
+msgid "\thost unmatched"
+msgstr "\tvert samsvarer ikke"
+
+#: plugins/sudoers/testsudoers.c:365
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Kommando tillatt"
+
+#: plugins/sudoers/testsudoers.c:366
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Kommandoen tillates ikke"
+
+#: plugins/sudoers/testsudoers.c:366
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Kommandoen samsvarer ikke"
+
+#: plugins/sudoers/timestamp.c:267
+#, c-format
+msgid "%s is group writable"
+msgstr "%s kan overskrives av gruppa den tilhører"
+
+#: plugins/sudoers/timestamp.c:343
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "klarte ikke å korte ned tidsstempel-fil til %lld byte"
+
+#: plugins/sudoers/timestamp.c:829 plugins/sudoers/timestamp.c:921
+#: plugins/sudoers/visudo.c:498 plugins/sudoers/visudo.c:504
+msgid "unable to read the clock"
+msgstr "klarte ikke å lese klokka"
+
+#: plugins/sudoers/timestamp.c:840
+msgid "ignoring time stamp from the future"
+msgstr "tidsstempel for fremtidig tidspunkt blir ignorert"
+
+#: plugins/sudoers/timestamp.c:863
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "tidsstempelet er for langt inn i fremtiden: %20.20s"
+
+#: plugins/sudoers/timestamp.c:985
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "klarte ikke å låse tidsstempel-fil %s"
+
+#: plugins/sudoers/timestamp.c:1029 plugins/sudoers/timestamp.c:1049
+#, c-format
+msgid "lecture status path too long: %s/%s"
+msgstr "filsti for moralpreken-status («%s/%s») er for lang"
+
+#: plugins/sudoers/visudo.c:232
+msgid "the -x option will be removed in a future release"
+msgstr "valget «-x» blir fjernet i en fremtidig versjon"
+
+#: plugins/sudoers/visudo.c:233
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "bruk verktøyet cvtsudoers i stedet"
+
+#: plugins/sudoers/visudo.c:284 plugins/sudoers/visudo.c:666
+#, c-format
+msgid "press return to edit %s: "
+msgstr "trykk linjeskift for å redigere %s: "
+
+#: plugins/sudoers/visudo.c:345
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "finner ikke valgt redigeringsprogram (%s)"
+
+#: plugins/sudoers/visudo.c:347
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "fant ingen redigeringsprogram («editor»-sti = %s)"
+
+#: plugins/sudoers/visudo.c:457 plugins/sudoers/visudo.c:465
+msgid "write error"
+msgstr "skrivefeil"
+
+#: plugins/sudoers/visudo.c:511
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "klarte ikke å undersøke midlertidig fil (%s). %s er ikke endret"
+
+#: plugins/sudoers/visudo.c:518
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "midlertidig fil (%s) er tom. %s er ikke endret"
+
+#: plugins/sudoers/visudo.c:524
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "noe gikk galt med behandleren (%s). %s er ikke endret"
+
+#: plugins/sudoers/visudo.c:546
+#, c-format
+msgid "%s unchanged"
+msgstr "%s er ikke endret"
+
+#: plugins/sudoers/visudo.c:605
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "klarte ikke å åpne midlertidig fil (%s) på nytt. %s er ikke endret"
+
+#: plugins/sudoers/visudo.c:617
+#, c-format
+msgid "unabled to parse temporary file (%s), unknown error"
+msgstr "klarte ikke å tolke midlertidig fil (%s). Ukjent feil"
+
+#: plugins/sudoers/visudo.c:655
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr "intern feil: fant ikke %s i lista!"
+
+#: plugins/sudoers/visudo.c:735 plugins/sudoers/visudo.c:744
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "klarte ikke å endre uid og gid for %s til (%u, %u)"
+
+#: plugins/sudoers/visudo.c:767
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s og %s er ikke på samme filsystem. Bruker «mv» til å gi nye navn"
+
+#: plugins/sudoers/visudo.c:781
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "kommando mislyktes. «%s %s %s». %s er ikke endret"
+
+#: plugins/sudoers/visudo.c:791
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "klarte ikke å gi %s nytt navn. %s er ikke endret"
+
+#: plugins/sudoers/visudo.c:812
+msgid "What now? "
+msgstr "Hva nå? "
+
+#: plugins/sudoers/visudo.c:826
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Du har følgende valgmuligheter:\n"
+" (e) rediger sudoers-fil på nytt\n"
+" (x) avslutt uten å lagre endringer i sudoers-fil\n"
+" (Q) avslutt og lagre endringene i sudoers-fil (FARLIG!)\n"
+
+#: plugins/sudoers/visudo.c:872
+#, c-format
+msgid "unable to run %s"
+msgstr "klarte ikke å kjøre %s"
+
+#: plugins/sudoers/visudo.c:902
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: feil eier. uid og gid skulle vært «%u, %u»\n"
+
+#: plugins/sudoers/visudo.c:909
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: feil tillatelsesmodus. Skulle vært modus 0%o\n"
+
+#: plugins/sudoers/visudo.c:966 plugins/sudoers/visudo.c:973
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: lest og tolket OK\n"
+
+#: plugins/sudoers/visudo.c:992
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s er opptatt. Prøv igjen senere"
+
+#: plugins/sudoers/visudo.c:995
+#, c-format
+msgid "unable to lock %s"
+msgstr "klarte ikke å låse %s"
+
+#: plugins/sudoers/visudo.c:996
+msgid "Edit anyway? [y/N]"
+msgstr "Vil du redigere likevel [j/N]"
+
+#: plugins/sudoers/visudo.c:1080
+#, c-format
+msgid "Error: %s:%d cycle in %s \"%s\""
+msgstr "Feil: %s:%d sløyfe i %s «%s»"
+
+#: plugins/sudoers/visudo.c:1081
+#, c-format
+msgid "Warning: %s:%d cycle in %s \"%s\""
+msgstr "Advarsel: %s:%d sløyfe i %s «%s»"
+
+#: plugins/sudoers/visudo.c:1085
+#, c-format
+msgid "Error: %s:%d %s \"%s\" referenced but not defined"
+msgstr "Feil: %s:%d referanse til %s «%s», som ikke er definert"
+
+#: plugins/sudoers/visudo.c:1086
+#, c-format
+msgid "Warning: %s:%d %s \"%s\" referenced but not defined"
+msgstr "Advarsel: %s:%d referanse til %s «%s», som ikke er definert"
+
+#: plugins/sudoers/visudo.c:1177
+#, c-format
+msgid "Warning: %s:%d unused %s \"%s\""
+msgstr "Advarsel: %s:%d %s «%s» står ubrukt"
+
+#: plugins/sudoers/visudo.c:1292
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - rediger sudoers-fil på en trygg måte\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1294
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Valg:\n"
+" -c, --check undersøkelsesmodus\n"
+" -f, --file=sudoers oppgi hvor sudoers-fila ligger\n"
+" -h, --help vis denne hjelpeteksten og avslutt\n"
+" -q, --quiet mindre detaljerte meldinger om syntaksfeil\n"
+" -s, --strict streng syntakskontroll\n"
+" -V, --version vis versjon og avslutt\n"
+
+#: toke.l:941
+msgid "too many levels of includes"
+msgstr "du har for mange nivåer av inkluderte filer"
+
+#~ msgid "ignoring invalid attribute value: %s"
+#~ msgstr "ignorerer ugyldig attributtverdi: %s"
+
+#~ msgid "unable to cache user %s, out of memory"
+#~ msgstr "klarte ikke å hurtiglagre brukeren %s. Minnet er fullt"
+
+#~ msgid "unable to cache group %s, out of memory"
+#~ msgstr "klarte ikke å hurtiglagre gruppa %s. Minnet er fullt"
+
+#~ msgid "unable to cache group list for %s, out of memory"
+#~ msgstr "klarte ikke å hurtiglagre liste over %s. Minnet er fullt"
+
+#~ msgid ""
+#~ "\n"
+#~ "LDAP Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "LDAP-role: UKJENT\n"
+
+#~ msgid " Order: %s\n"
+#~ msgstr " Sorter: %s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: %s\n"
+#~ msgstr ""
+#~ "\n"
+#~ "SSSD-rolle: %s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "SSSD-rolle: UKJENT\n"
+
+#~ msgid "Warning: cycle in %s `%s'"
+#~ msgstr "Advarsel: sløyfe i %s «%s»"
+
+#~ msgid "Warning: %s `%s' referenced but not defined"
+#~ msgstr "Advarsel: det refereres til %s «%s», som ikke er definert"
+
+#~ msgid "Warning: unused %s `%s'"
+#~ msgstr "Advarsel: %s «%s» er ubrukt"
+
+#~ msgid "unable allocate memory"
+#~ msgstr "klarte ikke å tildele minne"
+
+#~ msgid "timestamp path too long: %s/%s"
+#~ msgstr "filstien «%s/%s» for tidsstempel er for lang"
+
+#~ msgid "unable to stat editor (%s)"
+#~ msgstr "klarte ikke å undersøke redigeringsprogrammet (%s)"
+
+#~ msgid "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+#~ msgstr "sudo_ldap_conf_add_ports: ikke nok lagringsplass for å utvide vertens hurtiglager"
+
+#~ msgid "sudo_ldap_parse_uri: out of space building hostbuf"
+#~ msgstr "sudo_ldap_parse_uri: ikke nok lagringsplass til å bygge opp vertens hurtiglager"
+
+#~ msgid "sudo_ldap_build_pass1 allocation mismatch"
+#~ msgstr "sudo_ldap_build_pass1 samsvar ikke ved tildeling"
+
+#~ msgid "internal error: insufficient space for log line"
+#~ msgstr "intern feil: logglinje mangler plass"
+
+#~ msgid "fill_args: buffer overflow"
+#~ msgstr "fill_args: hurtiglageret er fullt"
diff --git a/plugins/sudoers/po/nl.mo b/plugins/sudoers/po/nl.mo
new file mode 100644
index 0000000..c07b4d6
--- /dev/null
+++ b/plugins/sudoers/po/nl.mo
Binary files differ
diff --git a/plugins/sudoers/po/nl.po b/plugins/sudoers/po/nl.po
new file mode 100644
index 0000000..3ea66a0
--- /dev/null
+++ b/plugins/sudoers/po/nl.po
@@ -0,0 +1,2282 @@
+# Dutch translation for sudoers.
+# This file is distributed under the same license as the sudo package.
+# P. Hamming <peterhamming@gmail.com>, 2013.
+# Benno Schulenberg <vertaling@coevern.nl>, 2017.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.8.22b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2017-12-01 15:42-0700\n"
+"PO-Revision-Date: 2017-12-05 21:44+0100\n"
+"Last-Translator: Benno Schulenberg <vertaling@coevern.nl>\n"
+"Language-Team: Dutch <vertaling@vrijschrift.org>\n"
+"Language: nl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Poedit 2.0.4\n"
+
+#: confstr.sh:1
+msgid "syntax error"
+msgstr "invoerfout"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "%p's wachtwoord: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] wachtwoord voor %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Wachtwoord: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** VEILIGHEIDSinformatie voor %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Sorry, probeer het opnieuw."
+
+#: gram.y:192 gram.y:240 gram.y:247 gram.y:254 gram.y:261 gram.y:268
+#: gram.y:284 gram.y:307 gram.y:314 gram.y:321 gram.y:328 gram.y:335
+#: gram.y:398 gram.y:406 gram.y:416 gram.y:449 gram.y:456 gram.y:463
+#: gram.y:470 gram.y:552 gram.y:559 gram.y:568 gram.y:577 gram.y:594
+#: gram.y:706 gram.y:713 gram.y:720 gram.y:728 gram.y:824 gram.y:831
+#: gram.y:838 gram.y:845 gram.y:852 gram.y:878 gram.y:885 gram.y:892
+#: gram.y:1015 gram.y:1195 gram.y:1202 plugins/sudoers/alias.c:124
+#: plugins/sudoers/alias.c:139 plugins/sudoers/auth/bsdauth.c:141
+#: plugins/sudoers/auth/kerb5.c:119 plugins/sudoers/auth/kerb5.c:145
+#: plugins/sudoers/auth/pam.c:490 plugins/sudoers/auth/rfc1938.c:109
+#: plugins/sudoers/auth/sia.c:59 plugins/sudoers/defaults.c:650
+#: plugins/sudoers/defaults.c:905 plugins/sudoers/defaults.c:1076
+#: plugins/sudoers/editor.c:64 plugins/sudoers/editor.c:82
+#: plugins/sudoers/editor.c:93 plugins/sudoers/env.c:233
+#: plugins/sudoers/filedigest.c:120 plugins/sudoers/filedigest_gcrypt.c:90
+#: plugins/sudoers/filedigest_openssl.c:111 plugins/sudoers/gc.c:52
+#: plugins/sudoers/group_plugin.c:134 plugins/sudoers/interfaces.c:71
+#: plugins/sudoers/iolog.c:941 plugins/sudoers/iolog_path.c:167
+#: plugins/sudoers/ldap.c:449 plugins/sudoers/ldap.c:480
+#: plugins/sudoers/ldap.c:532 plugins/sudoers/ldap.c:566
+#: plugins/sudoers/ldap.c:974 plugins/sudoers/ldap.c:1168
+#: plugins/sudoers/ldap.c:1179 plugins/sudoers/ldap.c:1195
+#: plugins/sudoers/ldap.c:1487 plugins/sudoers/ldap.c:1647
+#: plugins/sudoers/ldap.c:1729 plugins/sudoers/ldap.c:1877
+#: plugins/sudoers/ldap.c:1901 plugins/sudoers/ldap.c:1990
+#: plugins/sudoers/ldap.c:2005 plugins/sudoers/ldap.c:2101
+#: plugins/sudoers/ldap.c:2134 plugins/sudoers/ldap.c:2215
+#: plugins/sudoers/ldap.c:2297 plugins/sudoers/ldap.c:2394
+#: plugins/sudoers/ldap.c:3228 plugins/sudoers/ldap.c:3260
+#: plugins/sudoers/ldap.c:3572 plugins/sudoers/ldap.c:3600
+#: plugins/sudoers/ldap.c:3616 plugins/sudoers/ldap.c:3706
+#: plugins/sudoers/ldap.c:3722 plugins/sudoers/linux_audit.c:76
+#: plugins/sudoers/logging.c:189 plugins/sudoers/logging.c:451
+#: plugins/sudoers/logging.c:472 plugins/sudoers/logging.c:684
+#: plugins/sudoers/logging.c:942 plugins/sudoers/match.c:617
+#: plugins/sudoers/match.c:664 plugins/sudoers/match.c:714
+#: plugins/sudoers/match.c:738 plugins/sudoers/match.c:826
+#: plugins/sudoers/match.c:915 plugins/sudoers/parse.c:252
+#: plugins/sudoers/parse.c:264 plugins/sudoers/parse.c:279
+#: plugins/sudoers/parse.c:291 plugins/sudoers/policy.c:441
+#: plugins/sudoers/policy.c:678 plugins/sudoers/prompt.c:93
+#: plugins/sudoers/pwutil.c:165 plugins/sudoers/pwutil.c:236
+#: plugins/sudoers/pwutil.c:312 plugins/sudoers/pwutil.c:486
+#: plugins/sudoers/pwutil.c:551 plugins/sudoers/pwutil.c:620
+#: plugins/sudoers/pwutil.c:778 plugins/sudoers/pwutil.c:835
+#: plugins/sudoers/pwutil.c:880 plugins/sudoers/pwutil.c:938
+#: plugins/sudoers/sssd.c:162 plugins/sudoers/sssd.c:194
+#: plugins/sudoers/sssd.c:237 plugins/sudoers/sssd.c:244
+#: plugins/sudoers/sssd.c:280 plugins/sudoers/sssd.c:353
+#: plugins/sudoers/sssd.c:392 plugins/sudoers/sssd.c:1067
+#: plugins/sudoers/sssd.c:1246 plugins/sudoers/sssd.c:1260
+#: plugins/sudoers/sssd.c:1276 plugins/sudoers/sudoers.c:263
+#: plugins/sudoers/sudoers.c:273 plugins/sudoers/sudoers.c:281
+#: plugins/sudoers/sudoers.c:365 plugins/sudoers/sudoers.c:682
+#: plugins/sudoers/sudoers.c:807 plugins/sudoers/sudoers.c:851
+#: plugins/sudoers/sudoers.c:1123 plugins/sudoers/sudoers_debug.c:107
+#: plugins/sudoers/sudoreplay.c:1253 plugins/sudoers/sudoreplay.c:1365
+#: plugins/sudoers/sudoreplay.c:1405 plugins/sudoers/sudoreplay.c:1414
+#: plugins/sudoers/sudoreplay.c:1424 plugins/sudoers/sudoreplay.c:1432
+#: plugins/sudoers/sudoreplay.c:1436 plugins/sudoers/sudoreplay.c:1592
+#: plugins/sudoers/sudoreplay.c:1596 plugins/sudoers/testsudoers.c:131
+#: plugins/sudoers/testsudoers.c:217 plugins/sudoers/testsudoers.c:234
+#: plugins/sudoers/timestamp.c:389 plugins/sudoers/timestamp.c:433
+#: plugins/sudoers/timestamp.c:852 plugins/sudoers/toke_util.c:56
+#: plugins/sudoers/toke_util.c:109 plugins/sudoers/toke_util.c:146
+#: plugins/sudoers/visudo.c:153 plugins/sudoers/visudo.c:309
+#: plugins/sudoers/visudo.c:315 plugins/sudoers/visudo.c:446
+#: plugins/sudoers/visudo.c:624 plugins/sudoers/visudo.c:985
+#: plugins/sudoers/visudo.c:1051 plugins/sudoers/visudo.c:1095
+#: plugins/sudoers/visudo.c:1197 plugins/sudoers/visudo_json.c:1025 toke.l:849
+#: toke.l:949 toke.l:1106
+msgid "unable to allocate memory"
+msgstr "kan geen geheugen reserveren"
+
+#: gram.y:481
+msgid "a digest requires a path name"
+msgstr "een digest vereist een padnaam"
+
+#: gram.y:607
+msgid "invalid notbefore value"
+msgstr "ongeldige 'notbefore'-waarde"
+
+#: gram.y:615
+msgid "invalid notafter value"
+msgstr "ongeldige 'notafter'-waarde"
+
+#: gram.y:624 plugins/sudoers/policy.c:267
+msgid "timeout value too large"
+msgstr ""
+
+#: gram.y:626 plugins/sudoers/policy.c:269
+msgid "invalid timeout value"
+msgstr ""
+
+#: gram.y:1195 gram.y:1202 plugins/sudoers/auth/pam.c:320
+#: plugins/sudoers/auth/pam.c:490 plugins/sudoers/auth/rfc1938.c:109
+#: plugins/sudoers/defaults.c:650 plugins/sudoers/defaults.c:905
+#: plugins/sudoers/defaults.c:1076 plugins/sudoers/editor.c:64
+#: plugins/sudoers/editor.c:82 plugins/sudoers/editor.c:93
+#: plugins/sudoers/env.c:233 plugins/sudoers/filedigest.c:120
+#: plugins/sudoers/filedigest_gcrypt.c:72
+#: plugins/sudoers/filedigest_gcrypt.c:90
+#: plugins/sudoers/filedigest_openssl.c:111 plugins/sudoers/gc.c:52
+#: plugins/sudoers/group_plugin.c:134 plugins/sudoers/interfaces.c:71
+#: plugins/sudoers/iolog.c:941 plugins/sudoers/iolog_path.c:167
+#: plugins/sudoers/ldap.c:449 plugins/sudoers/ldap.c:480
+#: plugins/sudoers/ldap.c:532 plugins/sudoers/ldap.c:566
+#: plugins/sudoers/ldap.c:974 plugins/sudoers/ldap.c:1168
+#: plugins/sudoers/ldap.c:1179 plugins/sudoers/ldap.c:1195
+#: plugins/sudoers/ldap.c:1487 plugins/sudoers/ldap.c:1647
+#: plugins/sudoers/ldap.c:1729 plugins/sudoers/ldap.c:1877
+#: plugins/sudoers/ldap.c:1901 plugins/sudoers/ldap.c:1990
+#: plugins/sudoers/ldap.c:2005 plugins/sudoers/ldap.c:2101
+#: plugins/sudoers/ldap.c:2134 plugins/sudoers/ldap.c:2214
+#: plugins/sudoers/ldap.c:2297 plugins/sudoers/ldap.c:2394
+#: plugins/sudoers/ldap.c:3228 plugins/sudoers/ldap.c:3260
+#: plugins/sudoers/ldap.c:3572 plugins/sudoers/ldap.c:3599
+#: plugins/sudoers/ldap.c:3615 plugins/sudoers/ldap.c:3706
+#: plugins/sudoers/ldap.c:3722 plugins/sudoers/linux_audit.c:76
+#: plugins/sudoers/logging.c:189 plugins/sudoers/logging.c:451
+#: plugins/sudoers/logging.c:472 plugins/sudoers/logging.c:942
+#: plugins/sudoers/match.c:616 plugins/sudoers/match.c:663
+#: plugins/sudoers/match.c:714 plugins/sudoers/match.c:738
+#: plugins/sudoers/match.c:826 plugins/sudoers/match.c:914
+#: plugins/sudoers/parse.c:252 plugins/sudoers/parse.c:264
+#: plugins/sudoers/parse.c:279 plugins/sudoers/parse.c:291
+#: plugins/sudoers/policy.c:100 plugins/sudoers/policy.c:109
+#: plugins/sudoers/policy.c:118 plugins/sudoers/policy.c:142
+#: plugins/sudoers/policy.c:253 plugins/sudoers/policy.c:267
+#: plugins/sudoers/policy.c:269 plugins/sudoers/policy.c:293
+#: plugins/sudoers/policy.c:303 plugins/sudoers/policy.c:343
+#: plugins/sudoers/policy.c:353 plugins/sudoers/policy.c:362
+#: plugins/sudoers/policy.c:371 plugins/sudoers/policy.c:441
+#: plugins/sudoers/policy.c:678 plugins/sudoers/prompt.c:93
+#: plugins/sudoers/pwutil.c:165 plugins/sudoers/pwutil.c:236
+#: plugins/sudoers/pwutil.c:312 plugins/sudoers/pwutil.c:486
+#: plugins/sudoers/pwutil.c:551 plugins/sudoers/pwutil.c:620
+#: plugins/sudoers/pwutil.c:778 plugins/sudoers/pwutil.c:835
+#: plugins/sudoers/pwutil.c:880 plugins/sudoers/pwutil.c:938
+#: plugins/sudoers/set_perms.c:387 plugins/sudoers/set_perms.c:766
+#: plugins/sudoers/set_perms.c:1150 plugins/sudoers/set_perms.c:1476
+#: plugins/sudoers/set_perms.c:1641 plugins/sudoers/sssd.c:162
+#: plugins/sudoers/sssd.c:194 plugins/sudoers/sssd.c:237
+#: plugins/sudoers/sssd.c:244 plugins/sudoers/sssd.c:280
+#: plugins/sudoers/sssd.c:352 plugins/sudoers/sssd.c:392
+#: plugins/sudoers/sssd.c:1067 plugins/sudoers/sssd.c:1245
+#: plugins/sudoers/sssd.c:1260 plugins/sudoers/sssd.c:1276
+#: plugins/sudoers/sudoers.c:263 plugins/sudoers/sudoers.c:273
+#: plugins/sudoers/sudoers.c:281 plugins/sudoers/sudoers.c:365
+#: plugins/sudoers/sudoers.c:682 plugins/sudoers/sudoers.c:807
+#: plugins/sudoers/sudoers.c:851 plugins/sudoers/sudoers.c:1123
+#: plugins/sudoers/sudoers_debug.c:106 plugins/sudoers/sudoreplay.c:1253
+#: plugins/sudoers/sudoreplay.c:1365 plugins/sudoers/sudoreplay.c:1405
+#: plugins/sudoers/sudoreplay.c:1414 plugins/sudoers/sudoreplay.c:1424
+#: plugins/sudoers/sudoreplay.c:1432 plugins/sudoers/sudoreplay.c:1436
+#: plugins/sudoers/sudoreplay.c:1592 plugins/sudoers/sudoreplay.c:1596
+#: plugins/sudoers/testsudoers.c:131 plugins/sudoers/testsudoers.c:217
+#: plugins/sudoers/testsudoers.c:234 plugins/sudoers/timestamp.c:389
+#: plugins/sudoers/timestamp.c:433 plugins/sudoers/timestamp.c:852
+#: plugins/sudoers/toke_util.c:56 plugins/sudoers/toke_util.c:109
+#: plugins/sudoers/toke_util.c:146 plugins/sudoers/visudo.c:153
+#: plugins/sudoers/visudo.c:309 plugins/sudoers/visudo.c:315
+#: plugins/sudoers/visudo.c:446 plugins/sudoers/visudo.c:624
+#: plugins/sudoers/visudo.c:985 plugins/sudoers/visudo.c:1051
+#: plugins/sudoers/visudo.c:1095 plugins/sudoers/visudo.c:1197
+#: plugins/sudoers/visudo_json.c:1025 toke.l:849 toke.l:949 toke.l:1106
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: plugins/sudoers/alias.c:135
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Alias \"%s\" is al gedefinieerd"
+
+#: plugins/sudoers/auth/bsdauth.c:68
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "kan de loginklasse voor gebruiker %s niet verkrijgen"
+
+#: plugins/sudoers/auth/bsdauth.c:73
+msgid "unable to begin bsd authentication"
+msgstr "kan de bsd-aanmelding niet starten"
+
+#: plugins/sudoers/auth/bsdauth.c:81
+msgid "invalid authentication type"
+msgstr "ongeldig type verificatie"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to initialize BSD authentication"
+msgstr "kan de bsd-aanmelding niet initialiseren"
+
+#: plugins/sudoers/auth/fwtk.c:52
+msgid "unable to read fwtk config"
+msgstr "kan fwtk-configuratie niet lezen"
+
+#: plugins/sudoers/auth/fwtk.c:57
+msgid "unable to connect to authentication server"
+msgstr "kan niet verbinden met aanmeldingsserver"
+
+#: plugins/sudoers/auth/fwtk.c:63 plugins/sudoers/auth/fwtk.c:87
+#: plugins/sudoers/auth/fwtk.c:121
+msgid "lost connection to authentication server"
+msgstr "verbinding met aanmeldingsserver verloren"
+
+#: plugins/sudoers/auth/fwtk.c:67
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"aanmeldingsserverfout:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:111
+#, fuzzy, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: kan opdrachtgever niet converteren naar een string ('%s'): %s"
+
+#: plugins/sudoers/auth/kerb5.c:161
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: kan '%s' niet ontleden: %s"
+
+#: plugins/sudoers/auth/kerb5.c:170
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: kan cache voor aanmeldingsgegevens niet vinden: %s"
+
+#: plugins/sudoers/auth/kerb5.c:217
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: kan opties niet reserveren: %s"
+
+#: plugins/sudoers/auth/kerb5.c:232
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: kan aanmeldingsgegevens niet verkrijgen: %s"
+
+#: plugins/sudoers/auth/kerb5.c:245
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: kan cache voor aanmeldingsgegevens niet initialiseren: %s"
+
+#: plugins/sudoers/auth/kerb5.c:248
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: kan aanmeldingsgegeven niet opslaan in cache: %s"
+
+#: plugins/sudoers/auth/kerb5.c:312
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: kan belangrijkste server niet vinden: %s"
+
+#: plugins/sudoers/auth/kerb5.c:326
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: Kan TGT niet verifieren! U bent mogelijk aangevallen!: %s"
+
+#: plugins/sudoers/auth/pam.c:108
+msgid "unable to initialize PAM"
+msgstr "kan PAM niet initialiseren"
+
+#: plugins/sudoers/auth/pam.c:194
+msgid "account validation failure, is your account locked?"
+msgstr "fout bij valideren van account, is uw account geblokkeerd?"
+
+#: plugins/sudoers/auth/pam.c:198
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Account of wachtwoord is verlopen, stel uw wachtwoord opnieuw in en probeer het opnieuw"
+
+#: plugins/sudoers/auth/pam.c:206
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "kan verlopen wachtwoord niet wijzigen: %s"
+
+#: plugins/sudoers/auth/pam.c:211
+msgid "Password expired, contact your system administrator"
+msgstr "Wachtwoord is verlopen, neem contact op met uw systeembeheerder"
+
+#: plugins/sudoers/auth/pam.c:215
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Account is verlopen of PAM-configuratie heeft geen \"account\"-gedeelte voor sudo, neem contact op met uw systeembeheerder"
+
+#: plugins/sudoers/auth/pam.c:229
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "fout in PAM-aanmelding: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:97 plugins/sudoers/visudo.c:227
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "u bestaat niet in de %s-database"
+
+#: plugins/sudoers/auth/securid5.c:73
+msgid "failed to initialise the ACE API library"
+msgstr "initialiseren van de ACE API-bibliotheek is mislukt"
+
+#: plugins/sudoers/auth/securid5.c:99
+msgid "unable to contact the SecurID server"
+msgstr "kan geen contact krijgen met de SecurID-server"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "User ID locked for SecurID Authentication"
+msgstr "Gebruikers-ID is geblokkeerd voor SecurID-verificatie"
+
+#: plugins/sudoers/auth/securid5.c:112 plugins/sudoers/auth/securid5.c:163
+msgid "invalid username length for SecurID"
+msgstr "ongeldige gebruikersnaamlengte voor SecurID"
+
+#: plugins/sudoers/auth/securid5.c:116 plugins/sudoers/auth/securid5.c:168
+msgid "invalid Authentication Handle for SecurID"
+msgstr "kan verificatie voor SecurID op deze manier niet afhandelen"
+
+#: plugins/sudoers/auth/securid5.c:120
+msgid "SecurID communication failed"
+msgstr "SecurID-communicatie is mislukt"
+
+#: plugins/sudoers/auth/securid5.c:124 plugins/sudoers/auth/securid5.c:213
+msgid "unknown SecurID error"
+msgstr "onbekende SecurID-fout"
+
+#: plugins/sudoers/auth/securid5.c:158
+msgid "invalid passcode length for SecurID"
+msgstr "ongeldige lengte van passcode voor SecurID"
+
+#: plugins/sudoers/auth/sia.c:69 plugins/sudoers/auth/sia.c:125
+msgid "unable to initialize SIA session"
+msgstr "kan SIA-sessie niet initialiseren"
+
+#: plugins/sudoers/auth/sudo_auth.c:126
+msgid "invalid authentication methods"
+msgstr "ongeldige verificatiemethoden"
+
+#: plugins/sudoers/auth/sudo_auth.c:128
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Er zijn ongeldige verificatiemethoden in sudo gecompileerd! U kunt geen zelfstandige en niet-zelfstandige verificatiemethoden door elkaar gebruiken."
+
+#: plugins/sudoers/auth/sudo_auth.c:224 plugins/sudoers/auth/sudo_auth.c:274
+msgid "no authentication methods"
+msgstr "geen verificatiemethoden"
+
+#: plugins/sudoers/auth/sudo_auth.c:226
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Er zijn geen verificatie-methoden in sudo gecompileerd! Als u verificatie wilt uitschakelen, dient u de --disable-authentication configuratie-optie te gebruiken."
+
+#: plugins/sudoers/auth/sudo_auth.c:276
+msgid "Unable to initialize authentication methods."
+msgstr "Kon verificatiemethoden niet starten."
+
+#: plugins/sudoers/auth/sudo_auth.c:441
+msgid "Authentication methods:"
+msgstr "Verificatie-methoden:"
+
+#: plugins/sudoers/bsm_audit.c:120 plugins/sudoers/bsm_audit.c:211
+msgid "Could not determine audit condition"
+msgstr "Kan voorwaarden voor controle niet bepalen"
+
+#: plugins/sudoers/bsm_audit.c:183 plugins/sudoers/bsm_audit.c:273
+msgid "unable to commit audit record"
+msgstr "kan controlestructuur niet opbouwen"
+
+#: plugins/sudoers/check.c:259
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Als het goed is hebt u de gebruikelijke informatie ontvangen van uw\n"
+"systeembeheerder. Gewoonlijk komt het neer op de volgende drie punten:\n"
+"\n"
+" 1. Respecteer de privacy van anderen.\n"
+" 2. Denk na voordat u iets doet.\n"
+" 3. Veel mogelijkheden betekent veel verantwoordelijkheid.\n"
+"\n"
+
+#: plugins/sudoers/check.c:302 plugins/sudoers/check.c:312
+#: plugins/sudoers/sudoers.c:725 plugins/sudoers/sudoers.c:770
+#, c-format
+msgid "unknown uid: %u"
+msgstr "onbekend gebruikersnummer: %u"
+
+#: plugins/sudoers/check.c:307 plugins/sudoers/iolog.c:260
+#: plugins/sudoers/policy.c:851 plugins/sudoers/sudoers.c:1162
+#: plugins/sudoers/testsudoers.c:208 plugins/sudoers/testsudoers.c:366
+#, c-format
+msgid "unknown user: %s"
+msgstr "onbekende gebruiker: %s"
+
+#: plugins/sudoers/def_data.c:41
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Syslog-voorziening als syslog wordt gebruikt voor loggen: %s"
+
+#: plugins/sudoers/def_data.c:45
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Syslog-prioriteit wanneer aanmelden van gebruiker gelukt is: %s"
+
+#: plugins/sudoers/def_data.c:49
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Syslog-prioriteit wanneer aanmelden van gebruiker niet gelukt is: %s"
+
+#: plugins/sudoers/def_data.c:53
+msgid "Put OTP prompt on its own line"
+msgstr "Geef OTP-prompt een eigen regel"
+
+#: plugins/sudoers/def_data.c:57
+msgid "Ignore '.' in $PATH"
+msgstr "Negeer '.' in $PATH"
+
+#: plugins/sudoers/def_data.c:61
+msgid "Always send mail when sudo is run"
+msgstr "Stuur altijd een mail wanneer sudo is gebruikt"
+
+#: plugins/sudoers/def_data.c:65
+msgid "Send mail if user authentication fails"
+msgstr "Stuur een mail wanneer aanmelden van gebruiker mislukt"
+
+#: plugins/sudoers/def_data.c:69
+msgid "Send mail if the user is not in sudoers"
+msgstr "Stuur een mail als de gebruiker niet in sudoers staat"
+
+#: plugins/sudoers/def_data.c:73
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Stuur een mail als de gebruiker niet voor deze computer in sudoers staat"
+
+#: plugins/sudoers/def_data.c:77
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Stuur een mail als de gebruiker een opdracht niet mag gebruiken"
+
+#: plugins/sudoers/def_data.c:81
+msgid "Send mail if the user tries to run a command"
+msgstr "Stuur een mail als de gebruiker een opdracht probeert te gebruiken"
+
+#: plugins/sudoers/def_data.c:85
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Gebruik een verschillende tijd voor elke gebruiker/terminal-combinatie"
+
+#: plugins/sudoers/def_data.c:89
+msgid "Lecture user the first time they run sudo"
+msgstr "Instrueer gebruikers de eerste keer dat ze sudo gebruiken"
+
+#: plugins/sudoers/def_data.c:93
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Bestand met de sudo-instructies: %s"
+
+#: plugins/sudoers/def_data.c:97
+msgid "Require users to authenticate by default"
+msgstr "Standaard is verificatie van gebruikers vereist"
+
+#: plugins/sudoers/def_data.c:101
+msgid "Root may run sudo"
+msgstr "Root mag sudo gebruiken"
+
+#: plugins/sudoers/def_data.c:105
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Log de computernaam in het (niet-syslog) logbestand"
+
+#: plugins/sudoers/def_data.c:109
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Log het jaar in het (niet-syslog) logbestand"
+
+#: plugins/sudoers/def_data.c:113
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Start een shell als sudo wordt aangeroepen zonder argumenten"
+
+#: plugins/sudoers/def_data.c:117
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Stel $HOME in op de doelgebruiker wanneer een shell wordt gestart met -s"
+
+#: plugins/sudoers/def_data.c:121
+msgid "Always set $HOME to the target user's home directory"
+msgstr "$HOME altijd instellen op de persoonlijke map van de doelgebruiker"
+
+#: plugins/sudoers/def_data.c:125
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Sta verzamelen van informatie toe om bruikbare foutberichten te geven"
+
+#: plugins/sudoers/def_data.c:129
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Vereis volledig-gekwalificeerde computernamen (fqdn) in het sudoers-bestand"
+
+#: plugins/sudoers/def_data.c:133
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Beledig de gebruiker wanneer ze een verkeerd wachtwoord invoeren"
+
+#: plugins/sudoers/def_data.c:137
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Gebruiker alleen toestaan sudo te gebruiken wanneer deze een terminal heeft"
+
+#: plugins/sudoers/def_data.c:141
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo zal de EDITOR omgevingsvariabele in acht nemen"
+
+#: plugins/sudoers/def_data.c:145
+msgid "Prompt for root's password, not the users's"
+msgstr "Vraag naar wachtwoord van root, niet van de gebruiker"
+
+#: plugins/sudoers/def_data.c:149
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Vraag naar wachtwoord van runas_default gebruiker, niet van huidige gebruiker"
+
+#: plugins/sudoers/def_data.c:153
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Vraag naar wachtwoord van doelgebruiker, niet van huidige gebruiker"
+
+#: plugins/sudoers/def_data.c:157
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Pas de standaardinstellingen van de doelgebruikers inlogklasse toe wanneer deze bestaat"
+
+#: plugins/sudoers/def_data.c:161
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Stel de LOGNAME en USER omgevingsvariabelen in"
+
+#: plugins/sudoers/def_data.c:165
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Stel het effectieve gebruikersnummer van de doelgebuiker in, niet het werkelijke gebruikersnummer"
+
+#: plugins/sudoers/def_data.c:169
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "De groepsvector niet initialiseren naar die van de doelgebruiker"
+
+#: plugins/sudoers/def_data.c:173
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Breek regels in logbestanden af op (0 voor niet afbreken): %u"
+
+#: plugins/sudoers/def_data.c:177
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Aanmeldtijd timeout: %.1f minuten"
+
+#: plugins/sudoers/def_data.c:181
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Wachtwoordprompt timeout: %.1f minuten"
+
+#: plugins/sudoers/def_data.c:185
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Aantal pogingen om een wachtwoord in te voeren: %u"
+
+#: plugins/sudoers/def_data.c:189
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Te gebruiken umask of 0777 om die van gebruiker te gebruiken: 0%o"
+
+#: plugins/sudoers/def_data.c:193
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Pad naar logbestand: %s"
+
+#: plugins/sudoers/def_data.c:197
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Pad naar mailprogramma: %s"
+
+#: plugins/sudoers/def_data.c:201
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Opties voor mailprogramma: %s"
+
+#: plugins/sudoers/def_data.c:205
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Adres waarnaar mail wordt verzonden: %s"
+
+#: plugins/sudoers/def_data.c:209
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Afzenderadres: %s"
+
+#: plugins/sudoers/def_data.c:213
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Onderwerp voor mails: %s"
+
+#: plugins/sudoers/def_data.c:217
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Boodschap voor verkeerd wachtwoord: %s"
+
+#: plugins/sudoers/def_data.c:221
+#, fuzzy, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Pad naar aanmeld-tijdmap: %s"
+
+#: plugins/sudoers/def_data.c:225
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Pad naar aanmeld-tijdmap: %s"
+
+#: plugins/sudoers/def_data.c:229
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Eigenaar van aanmeld-tijdmap: %s"
+
+#: plugins/sudoers/def_data.c:233
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Gebruikers in deze groep zijn uitgezonderd van de wachtwoord- en PATH-vereisten: %s"
+
+#: plugins/sudoers/def_data.c:237
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Standaard wachtwoordprompt: %s"
+
+#: plugins/sudoers/def_data.c:241
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Indien ingesteld, zal de wachtwoordprompt altijd de systeemprompt vervangen."
+
+#: plugins/sudoers/def_data.c:245
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Standaardgebruiker om opdrachten uit te voeren: %s"
+
+#: plugins/sudoers/def_data.c:249
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Waarde waarmee $PATH van gebruiker wordt vervangen: %s"
+
+#: plugins/sudoers/def_data.c:253
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Pad naar de editor bij gebruik van visudo: %s"
+
+#: plugins/sudoers/def_data.c:257
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Wanneer een wachtwoord noodzakelijk is voor 'list'-pseudopdracht: %s"
+
+#: plugins/sudoers/def_data.c:261
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Wanneer een wachtwoord noodzakelijk is voor 'verify'-pseudopdracht: %s"
+
+#: plugins/sudoers/def_data.c:265
+msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+msgstr "Laadt vooraf de dummy uitvoerfuncties uit de sudo_noexec-bibliotheek"
+
+#: plugins/sudoers/def_data.c:269
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Als de LDAP-map beschikbaar is, wordt het lokale sudoersbestand genegeerd?"
+
+#: plugins/sudoers/def_data.c:273
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Bestandsdescriptors >= %d zullen worden gesloten vóór het uitvoeren van een opdracht"
+
+#: plugins/sudoers/def_data.c:277
+msgid "If set, users may override the value of `closefrom' with the -C option"
+msgstr "Indien ingesteld, mogen gebruikers de waarde van 'closefrom' vervangen met de optie -C"
+
+#: plugins/sudoers/def_data.c:281
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Gebruikers toestaan willekeurige omgevingsvariabelen in te stellen"
+
+#: plugins/sudoers/def_data.c:285
+msgid "Reset the environment to a default set of variables"
+msgstr "Stel de omgevingsvariablen in op een standaard set"
+
+#: plugins/sudoers/def_data.c:289
+msgid "Environment variables to check for sanity:"
+msgstr "Op \"gezondheid\" te controleren omgevingsvariabelen:"
+
+#: plugins/sudoers/def_data.c:293
+msgid "Environment variables to remove:"
+msgstr "Te verwijderen omgevingsvariabelen:"
+
+#: plugins/sudoers/def_data.c:297
+msgid "Environment variables to preserve:"
+msgstr "Te behouden omgevingsvariabelen:"
+
+#: plugins/sudoers/def_data.c:301
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "SELinux role om in de nieuwe beveiligingscontext te gebruiken: %s"
+
+#: plugins/sudoers/def_data.c:305
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "SELinux type om in de nieuwe beveiligingscontext te gebruiken: %s"
+
+#: plugins/sudoers/def_data.c:309
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Pad naar het omgevingsbestand voor sudo: %s"
+
+#: plugins/sudoers/def_data.c:313
+#, fuzzy, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Pad naar het omgevingsbestand voor sudo: %s"
+
+#: plugins/sudoers/def_data.c:317
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Te gebruiken taalregio bij ontleden van sudoers: %s"
+
+#: plugins/sudoers/def_data.c:321
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Sta sudo toe ook te vragen naar een wachtwoord wanneer dit zichtbaar zou worden"
+
+#: plugins/sudoers/def_data.c:325
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Zorg voor zichtbare terugkoppeling op de wachtwoordprompt wanneer er gebruikersinvoer is"
+
+#: plugins/sudoers/def_data.c:329
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Gebruik snellere expansie van jokertekens. Dit is minder nauwkeurig, maar maakt geen gebruik van het bestandsysteem"
+
+#: plugins/sudoers/def_data.c:333
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "De umask die is opgegeven in het sudoersbestand zal die van de gebruiker vervangen, ook wanneer deze meer toestaat"
+
+#: plugins/sudoers/def_data.c:337
+msgid "Log user's input for the command being run"
+msgstr "Log gebruikersinvoer voor de uitgevoerde opdracht"
+
+#: plugins/sudoers/def_data.c:341
+msgid "Log the output of the command being run"
+msgstr "Log uitvoer voor de uitgevoerde opdracht"
+
+#: plugins/sudoers/def_data.c:345
+msgid "Compress I/O logs using zlib"
+msgstr "Comprimeer in-/uitvoerlogs met zlib"
+
+#: plugins/sudoers/def_data.c:349
+msgid "Always run commands in a pseudo-tty"
+msgstr "Voer opdrachten altijd uit in een pseudo-terminal"
+
+#: plugins/sudoers/def_data.c:353
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Plugin voor ondersteuning van niet-Unixgroepen: %s"
+
+#: plugins/sudoers/def_data.c:357
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Map waarin in-/uitvoerlogs moeten worden opgeslagen: %s"
+
+#: plugins/sudoers/def_data.c:361
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Bestand waarin in-/uitvoerlogs moeten worden opgeslagen: %s"
+
+#: plugins/sudoers/def_data.c:365
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Voeg een item toe aan het utmp/utmpx-bestand wanneer een virtuele terminal wordt gereserveerd"
+
+#: plugins/sudoers/def_data.c:369
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Stel in utmp de gebruiker in op de runas-gebruiker, niet op de aanroepende gebruiker"
+
+#: plugins/sudoers/def_data.c:373
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Set van toegestane privileges: %s"
+
+#: plugins/sudoers/def_data.c:377
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Set van beperkende privileges: %s"
+
+#: plugins/sudoers/def_data.c:381
+msgid "Run commands on a pty in the background"
+msgstr "Draai opdrachten op een virtuele terminal op de achtergrond."
+
+#: plugins/sudoers/def_data.c:385
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "te gebruiken naam van PAM-service: %s"
+
+#: plugins/sudoers/def_data.c:389
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "te gebruiken naam van PAM-service voor inlog-shells: %s"
+
+#: plugins/sudoers/def_data.c:393
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Probeer PAM-aanmeldgegevens voor doelgebruiker te verkrijgen"
+
+#: plugins/sudoers/def_data.c:397
+msgid "Create a new PAM session for the command to run in"
+msgstr "Maak een nieuwe PAM-sessie om de opdracht in uit te voeren"
+
+#: plugins/sudoers/def_data.c:401
+#, c-format
+msgid "Maximum I/O log sequence number: %u"
+msgstr "Maximaal in-/uitvoerlog volgnummer: %u"
+
+#: plugins/sudoers/def_data.c:405
+msgid "Enable sudoers netgroup support"
+msgstr "Ondersteuning voor sudoers-netgroup inschakelen"
+
+#: plugins/sudoers/def_data.c:409
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:413
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:417
+msgid "Query the group plugin for unknown system groups"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:421
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:425
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:429
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:433
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:437
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:441
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:445
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:449
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:453
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:457
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:461
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:465
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:469
+msgid "Allow the user to specify a timeout on the command line"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:473
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:477
+msgid "Include the process ID when logging via syslog"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:481
+#, fuzzy, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Eigenaar van aanmeld-tijdmap: %s"
+
+#: plugins/sudoers/defaults.c:220
+#, c-format
+msgid "%s:%d unknown defaults entry \"%s\""
+msgstr "%s:%d onbekend standaarditem \"%s\""
+
+#: plugins/sudoers/defaults.c:223
+#, c-format
+msgid "%s: unknown defaults entry \"%s\""
+msgstr "%s: onbekend standaarditem \"%s\""
+
+#: plugins/sudoers/defaults.c:266
+#, c-format
+msgid "%s:%d no value specified for \"%s\""
+msgstr "%s:%d geen waarde opgegeven voor \"%s\""
+
+#: plugins/sudoers/defaults.c:269
+#, c-format
+msgid "%s: no value specified for \"%s\""
+msgstr "%s: geen waarde opgegeven voor \"%s\""
+
+#: plugins/sudoers/defaults.c:289
+#, c-format
+msgid "%s:%d values for \"%s\" must start with a '/'"
+msgstr "%s:%d waarden voor \"%s\" moeten beginnen met een '/'"
+
+#: plugins/sudoers/defaults.c:292
+#, c-format
+msgid "%s: values for \"%s\" must start with a '/'"
+msgstr "%s: waarden voor \"%s\" moeten beginnen met een '/'"
+
+#: plugins/sudoers/defaults.c:317
+#, c-format
+msgid "%s:%d option \"%s\" does not take a value"
+msgstr "%s:%d optie '%s' accepteert geen waarde"
+
+#: plugins/sudoers/defaults.c:320
+#, c-format
+msgid "%s: option \"%s\" does not take a value"
+msgstr "%s: optie '%s' accepteert geen waarde"
+
+#: plugins/sudoers/defaults.c:342
+#, fuzzy, c-format
+msgid "%s:%d invalid Defaults type 0x%x for option \"%s\""
+msgstr "ongeldige filteroptie: %s"
+
+#: plugins/sudoers/defaults.c:345
+#, fuzzy, c-format
+msgid "%s: invalid Defaults type 0x%x for option \"%s\""
+msgstr "ongeldige filteroptie: %s"
+
+#: plugins/sudoers/defaults.c:355
+#, c-format
+msgid "%s:%d value \"%s\" is invalid for option \"%s\""
+msgstr "%s:%d waarde \"%s\" is ongeldig voor optie '%s'"
+
+#: plugins/sudoers/defaults.c:358
+#, c-format
+msgid "%s: value \"%s\" is invalid for option \"%s\""
+msgstr "%s: waarde \"%s\" is ongeldig voor optie '%s'"
+
+#: plugins/sudoers/env.c:295 plugins/sudoers/env.c:302
+#: plugins/sudoers/env.c:407 plugins/sudoers/ldap.c:453
+#: plugins/sudoers/ldap.c:543 plugins/sudoers/ldap.c:1264
+#: plugins/sudoers/ldap.c:1491 plugins/sudoers/ldap.c:1816
+#: plugins/sudoers/linux_audit.c:82 plugins/sudoers/logging.c:947
+#: plugins/sudoers/policy.c:562 plugins/sudoers/policy.c:572
+#: plugins/sudoers/prompt.c:161 plugins/sudoers/sudoers.c:873
+#: plugins/sudoers/testsudoers.c:238 plugins/sudoers/toke_util.c:158
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "interne fout, %s overflow"
+
+#: plugins/sudoers/env.c:376
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: envp bevat fouten, verkeerde lengte"
+
+#: plugins/sudoers/env.c:1055
+msgid "unable to rebuild the environment"
+msgstr "kan omgeving niet opnieuw opbouwen"
+
+#: plugins/sudoers/env.c:1129
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "sorry, u mag de volgende omgevingsvariabelen niet instellen: %s"
+
+#: plugins/sudoers/filedigest.c:104 plugins/sudoers/filedigest_gcrypt.c:66
+#: plugins/sudoers/filedigest_openssl.c:95
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr "niet-ondersteund type controlegetal %d voor %s"
+
+#: plugins/sudoers/filedigest.c:129 plugins/sudoers/filedigest_gcrypt.c:98
+#: plugins/sudoers/filedigest_openssl.c:120
+#, c-format
+msgid "%s: read error"
+msgstr "%s: leesfout"
+
+#: plugins/sudoers/group_plugin.c:86
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s moet eigendom zijn van gebruikersnummer %d"
+
+#: plugins/sudoers/group_plugin.c:90
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr "%s mag enkel schrijfbaar zijn voor eigenaar"
+
+#: plugins/sudoers/group_plugin.c:98 plugins/sudoers/sssd.c:400
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "kan %s niet laden: %s"
+
+#: plugins/sudoers/group_plugin.c:104
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "kan symbool \"group_plugin\" niet vinden in %s"
+
+#: plugins/sudoers/group_plugin.c:109
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: incompatibele groepplugin hoofdversie %d, verwacht wordt %d"
+
+#: plugins/sudoers/interfaces.c:79 plugins/sudoers/interfaces.c:96
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "kan IP-adres \"%s\" niet ontleden"
+
+#: plugins/sudoers/interfaces.c:84 plugins/sudoers/interfaces.c:101
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "kan netmasker \"%s\" niet ontleden"
+
+#: plugins/sudoers/interfaces.c:129
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Combinaties van lokale IP-adressen en netwerkmaskers:\n"
+
+#: plugins/sudoers/iolog.c:121 plugins/sudoers/mkdir_parents.c:75
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s bestaat al, maar is geen map (0%o)"
+
+#: plugins/sudoers/iolog.c:146 plugins/sudoers/iolog.c:187
+#: plugins/sudoers/mkdir_parents.c:64 plugins/sudoers/timestamp.c:170
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "mkdir %s: aanmaken mislukt"
+
+#: plugins/sudoers/iolog.c:191 plugins/sudoers/visudo.c:740
+#: plugins/sudoers/visudo.c:750
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "kan modus van %s niet wijzigen naar 0%o"
+
+#: plugins/sudoers/iolog.c:299 plugins/sudoers/sudoers.c:1193
+#: plugins/sudoers/testsudoers.c:390
+#, c-format
+msgid "unknown group: %s"
+msgstr "onbekende groep: %s"
+
+#: plugins/sudoers/iolog.c:418 plugins/sudoers/sudoers.c:929
+#: plugins/sudoers/sudoreplay.c:349 plugins/sudoers/sudoreplay.c:1354
+#: plugins/sudoers/sudoreplay.c:1558 plugins/sudoers/timestamp.c:398
+#: plugins/sudoers/visudo.c:972 plugins/sudoers/visudo_json.c:1001
+#: plugins/sudoers/visudo_json.c:1014
+#, c-format
+msgid "unable to open %s"
+msgstr "kan %s niet openen"
+
+#: plugins/sudoers/iolog.c:469 plugins/sudoers/sudoers.c:933
+#: plugins/sudoers/sudoreplay.c:856 plugins/sudoers/sudoreplay.c:1669
+#, c-format
+msgid "unable to read %s"
+msgstr "kan %s niet lezen"
+
+#: plugins/sudoers/iolog.c:505 plugins/sudoers/sudoreplay.c:1123
+#: plugins/sudoers/timestamp.c:290 plugins/sudoers/timestamp.c:293
+#, c-format
+msgid "unable to write to %s"
+msgstr "kan %s niet schrijven"
+
+#: plugins/sudoers/iolog.c:584 plugins/sudoers/iolog.c:803
+#, c-format
+msgid "unable to create %s"
+msgstr "kan %s niet aanmaken"
+
+#: plugins/sudoers/iolog.c:1035 plugins/sudoers/iolog.c:1110
+#: plugins/sudoers/iolog.c:1191
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "kan niet schrijven naar in-/uitvoerlogbestand: %s"
+
+#: plugins/sudoers/iolog.c:1069
+#, fuzzy, c-format
+msgid "%s: internal error, file index %d not open"
+msgstr "interne fout, kan %s niet in de lijst vinden!"
+
+#: plugins/sudoers/ldap.c:431
+msgid "sudo_ldap_conf_add_ports: port too large"
+msgstr "sudo_ldap_conf_add_ports: poort te groot"
+
+#: plugins/sudoers/ldap.c:491
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "niet-ondersteund LDAP uri type: %s"
+
+#: plugins/sudoers/ldap.c:518
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "kan ldap en ldaps URIs niet door elkaar gebruiken"
+
+#: plugins/sudoers/ldap.c:522 plugins/sudoers/ldap.c:559
+msgid "starttls not supported when using ldaps"
+msgstr "starttls wordt niet ondersteund in combinatie met ldaps"
+
+#: plugins/sudoers/ldap.c:630
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "kan SSL cert en key db niet initialiseren: %s"
+
+#: plugins/sudoers/ldap.c:633
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "u moet TLS_CERT in %s instellen om SSL te gebruiken"
+
+#: plugins/sudoers/ldap.c:1250
+msgid "unable to get GMT time"
+msgstr "kan GMT-tijd niet verkrijgen"
+
+#: plugins/sudoers/ldap.c:1256
+msgid "unable to format timestamp"
+msgstr "kan tijd niet juist opmaken"
+
+#: plugins/sudoers/ldap.c:1980
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/ldap.c:2552
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+"\n"
+"LDAP Role: %s\n"
+
+#: plugins/sudoers/ldap.c:2554
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: UNKNOWN\n"
+msgstr ""
+"\n"
+"LDAP Role: UNKNOWN\n"
+
+#: plugins/sudoers/ldap.c:2610
+#, c-format
+msgid " Order: %s\n"
+msgstr " Volgorde: %s\n"
+
+#: plugins/sudoers/ldap.c:2618 plugins/sudoers/parse.c:618
+#: plugins/sudoers/sssd.c:1641
+#, c-format
+msgid " Commands:\n"
+msgstr " Opdrachten:\n"
+
+#: plugins/sudoers/ldap.c:3180
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "kan LDAP niet initialiseren: %s"
+
+#: plugins/sudoers/ldap.c:3216
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls opgegeven maar LDAP bibliotheken ondersteunen geen ldap_start_tls_s() of ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:3468
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "ongeldig sudoOrder kenmerk: %s"
+
+#: plugins/sudoers/linux_audit.c:52
+msgid "unable to open audit system"
+msgstr "kan controlesysteem niet openen"
+
+#: plugins/sudoers/linux_audit.c:93
+msgid "unable to send audit message"
+msgstr "kan controleboodschap niet verzenden"
+
+#: plugins/sudoers/logging.c:107
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: plugins/sudoers/logging.c:135
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (opdracht voortgezet) %s"
+
+#: plugins/sudoers/logging.c:164
+#, c-format
+msgid "unable to open log file: %s"
+msgstr "kan logbestand niet openen: %s"
+
+#: plugins/sudoers/logging.c:172
+#, c-format
+msgid "unable to lock log file: %s"
+msgstr "kan logbestand niet vergrendelen: %s"
+
+#: plugins/sudoers/logging.c:205
+#, c-format
+msgid "unable to write log file: %s"
+msgstr "kan logbestand niet schrijven: %s"
+
+#: plugins/sudoers/logging.c:234
+msgid "No user or host"
+msgstr "Geen gebruiker of computer"
+
+#: plugins/sudoers/logging.c:236
+msgid "validation failure"
+msgstr "geldigheidsfout"
+
+#: plugins/sudoers/logging.c:243
+msgid "user NOT in sudoers"
+msgstr "gebruiker NIET in sudoers"
+
+#: plugins/sudoers/logging.c:245
+msgid "user NOT authorized on host"
+msgstr "gebruiker NIET aangemeld op computer"
+
+#: plugins/sudoers/logging.c:247
+msgid "command not allowed"
+msgstr "opdracht is niet toegestaan"
+
+#: plugins/sudoers/logging.c:282
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr "%s zit niet in het sudoersbestand. Dit incident zal worden gerapporteerd.\n"
+
+#: plugins/sudoers/logging.c:285
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr "%s heeft niet het recht om sudo te gebruiken op %s. Dit incident zal worden gerapporteerd.\n"
+
+#: plugins/sudoers/logging.c:289
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Sorry, gebruiker %s mag sudo niet gebruiken op %s.\n"
+
+#: plugins/sudoers/logging.c:292
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr "Sorry, gebruiker %s mag '%s%s%s' niet uitvoeren als %s%s%s op %s.\n"
+
+#: plugins/sudoers/logging.c:329 plugins/sudoers/sudoers.c:473
+#: plugins/sudoers/sudoers.c:475 plugins/sudoers/sudoers.c:477
+#: plugins/sudoers/sudoers.c:479 plugins/sudoers/sudoers.c:1298
+#: plugins/sudoers/sudoers.c:1300
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: opdracht niet gevonden"
+
+#: plugins/sudoers/logging.c:331 plugins/sudoers/sudoers.c:469
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"\"%s\" gevonden in '.' wordt genegeerd.\n"
+"Gebruik 'sudo ./%s' als dit de '%s' die u wilt uitvoeren."
+
+#: plugins/sudoers/logging.c:348
+msgid "authentication failure"
+msgstr "aanmeldingsfout"
+
+#: plugins/sudoers/logging.c:374
+msgid "a password is required"
+msgstr "een wachtwoord is verplicht"
+
+#: plugins/sudoers/logging.c:445 plugins/sudoers/logging.c:511
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u verkeerde wachtwoordpoging"
+msgstr[1] "%u verkeerde wachtwoordpogingen"
+
+#: plugins/sudoers/logging.c:598
+msgid "unable to fork"
+msgstr "kan niet afsplitsen"
+
+#: plugins/sudoers/logging.c:606 plugins/sudoers/logging.c:658
+#, c-format
+msgid "unable to fork: %m"
+msgstr "kan niet afsplitsen: %m"
+
+#: plugins/sudoers/logging.c:648
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "kan pipe niet openen: %m"
+
+#: plugins/sudoers/logging.c:673
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "kan stdin niet klonen: %m"
+
+#: plugins/sudoers/logging.c:711
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "kan %s niet uitvoeren: %m"
+
+#: plugins/sudoers/match.c:771
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "controlegetal voor %s (%s) is niet in de %s-vorm"
+
+#: plugins/sudoers/mkdir_parents.c:70 plugins/sudoers/sudoers.c:944
+#: plugins/sudoers/visudo.c:439 plugins/sudoers/visudo.c:734
+#, c-format
+msgid "unable to stat %s"
+msgstr "kan stat op %s niet uitvoeren"
+
+#: plugins/sudoers/parse.c:115
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr "ontleedfout in %s bij regel %d"
+
+#: plugins/sudoers/parse.c:118
+#, c-format
+msgid "parse error in %s"
+msgstr "ontleedfout in %s"
+
+#: plugins/sudoers/parse.c:544
+#, c-format
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+"\n"
+"Sudoers-item:\n"
+
+#: plugins/sudoers/parse.c:545
+#, c-format
+msgid " RunAsUsers: "
+msgstr " RunAsUsers: "
+
+#: plugins/sudoers/parse.c:559
+#, c-format
+msgid " RunAsGroups: "
+msgstr " RunAsGroups: "
+
+#: plugins/sudoers/parse.c:568
+#, c-format
+msgid " Options: "
+msgstr " Opties: "
+
+#: plugins/sudoers/policy.c:243 plugins/sudoers/testsudoers.c:261
+msgid "unable to parse network address list"
+msgstr "kan netwerkadressenlijst niet ontleden"
+
+#: plugins/sudoers/policy.c:380
+msgid "user name not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:384
+msgid "user ID not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:388
+msgid "group ID not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:392
+msgid "host name not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:736 plugins/sudoers/visudo.c:910
+#, c-format
+msgid "unable to execute %s"
+msgstr "kan %s niet uitvoeren"
+
+#: plugins/sudoers/policy.c:869
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Sudoers-beleidsplugin versie %s\n"
+
+#: plugins/sudoers/policy.c:871
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Versie van sudoers-bestandsgrammatica %d\n"
+
+#: plugins/sudoers/policy.c:875
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Sudoers-pad: %s\n"
+
+#: plugins/sudoers/policy.c:878
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "nsswitch-pad: %s\n"
+
+#: plugins/sudoers/policy.c:880
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "ldap.conf-pad: %s\n"
+
+#: plugins/sudoers/policy.c:881
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "ldap.secret-pad: %s\n"
+
+#: plugins/sudoers/policy.c:914
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:188 plugins/sudoers/pwutil.c:206
+#, c-format
+msgid "unable to cache uid %u, out of memory"
+msgstr "kan gebruikersnummer %u niet bufferen, onvoldoende geheugen"
+
+#: plugins/sudoers/pwutil.c:200
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "kan gebruikersnummer %u niet bufferen, bestaat reeds"
+
+#: plugins/sudoers/pwutil.c:260 plugins/sudoers/pwutil.c:277
+#: plugins/sudoers/pwutil.c:339 plugins/sudoers/pwutil.c:384
+#, c-format
+msgid "unable to cache user %s, out of memory"
+msgstr "kan gebruiker %s niet bufferen, onvoldoende geheugen"
+
+#: plugins/sudoers/pwutil.c:272
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "kan gebruiker %s niet bufferen, bestaat reeds"
+
+#: plugins/sudoers/pwutil.c:503 plugins/sudoers/pwutil.c:521
+#, c-format
+msgid "unable to cache gid %u, out of memory"
+msgstr "kan groepsnummer %u niet bufferen, onvoldoende geheugen"
+
+#: plugins/sudoers/pwutil.c:515
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "kan groepsnummer %u niet bufferen, bestaat reeds"
+
+#: plugins/sudoers/pwutil.c:569 plugins/sudoers/pwutil.c:586
+#: plugins/sudoers/pwutil.c:633 plugins/sudoers/pwutil.c:675
+#, c-format
+msgid "unable to cache group %s, out of memory"
+msgstr "kan groep %s niet bufferen, onvoldoende geheugen"
+
+#: plugins/sudoers/pwutil.c:581
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "kan groep %s niet bufferen, bestaat reeds"
+
+#: plugins/sudoers/pwutil.c:801 plugins/sudoers/pwutil.c:853
+#: plugins/sudoers/pwutil.c:904 plugins/sudoers/pwutil.c:957
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "kan groepslijst voor %s niet bufferen, bestaat reeds"
+
+#: plugins/sudoers/pwutil.c:807 plugins/sudoers/pwutil.c:858
+#: plugins/sudoers/pwutil.c:910 plugins/sudoers/pwutil.c:962
+#, c-format
+msgid "unable to cache group list for %s, out of memory"
+msgstr "kan groepslijst voor %s niet bufferen, onvoldoende geheugen"
+
+#: plugins/sudoers/pwutil.c:847
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "kan groepen voor %s niet ontleden"
+
+#: plugins/sudoers/pwutil.c:951
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "kan groepsnummers voor %s niet ontleden"
+
+#: plugins/sudoers/set_perms.c:113 plugins/sudoers/set_perms.c:469
+#: plugins/sudoers/set_perms.c:912 plugins/sudoers/set_perms.c:1239
+#: plugins/sudoers/set_perms.c:1556
+msgid "perm stack overflow"
+msgstr "overloop van rechtenstapel"
+
+#: plugins/sudoers/set_perms.c:121 plugins/sudoers/set_perms.c:400
+#: plugins/sudoers/set_perms.c:477 plugins/sudoers/set_perms.c:779
+#: plugins/sudoers/set_perms.c:920 plugins/sudoers/set_perms.c:1163
+#: plugins/sudoers/set_perms.c:1247 plugins/sudoers/set_perms.c:1489
+#: plugins/sudoers/set_perms.c:1564 plugins/sudoers/set_perms.c:1654
+msgid "perm stack underflow"
+msgstr "onderloop van rechtenstapel"
+
+#: plugins/sudoers/set_perms.c:180 plugins/sudoers/set_perms.c:523
+#: plugins/sudoers/set_perms.c:1298 plugins/sudoers/set_perms.c:1596
+msgid "unable to change to root gid"
+msgstr "kan niet wijzigen naar rootgroepsnummer"
+
+#: plugins/sudoers/set_perms.c:269 plugins/sudoers/set_perms.c:620
+#: plugins/sudoers/set_perms.c:1049 plugins/sudoers/set_perms.c:1375
+msgid "unable to change to runas gid"
+msgstr "kan niet wijzigen naar runas-groepsnummer"
+
+#: plugins/sudoers/set_perms.c:274 plugins/sudoers/set_perms.c:625
+#: plugins/sudoers/set_perms.c:1054 plugins/sudoers/set_perms.c:1380
+msgid "unable to set runas group vector"
+msgstr "kan runas-groepsvector niet instellen"
+
+#: plugins/sudoers/set_perms.c:285 plugins/sudoers/set_perms.c:636
+#: plugins/sudoers/set_perms.c:1063 plugins/sudoers/set_perms.c:1389
+msgid "unable to change to runas uid"
+msgstr "kan niet wijzigen naar runas-gebruikersnummer"
+
+#: plugins/sudoers/set_perms.c:303 plugins/sudoers/set_perms.c:654
+#: plugins/sudoers/set_perms.c:1079 plugins/sudoers/set_perms.c:1405
+msgid "unable to change to sudoers gid"
+msgstr "kan niet wijzigen naar sudoers-groepsnummer"
+
+#: plugins/sudoers/set_perms.c:387 plugins/sudoers/set_perms.c:766
+#: plugins/sudoers/set_perms.c:1150 plugins/sudoers/set_perms.c:1476
+#: plugins/sudoers/set_perms.c:1641
+msgid "too many processes"
+msgstr "te veel processen"
+
+#: plugins/sudoers/solaris_audit.c:51
+msgid "unable to get current working directory"
+msgstr "kan huidige werkmap niet achterhalen"
+
+#: plugins/sudoers/solaris_audit.c:59
+#, c-format
+msgid "truncated audit path user_cmnd: %s"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:66
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:115
+msgid "audit_failure message too long"
+msgstr "boodschap voor audit_failure is te lang"
+
+#: plugins/sudoers/sssd.c:402
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "Kan SSS-bron niet initialiseren. Is SSSD op uw machine geinstalleerd?"
+
+#: plugins/sudoers/sssd.c:410 plugins/sudoers/sssd.c:419
+#: plugins/sudoers/sssd.c:428 plugins/sudoers/sssd.c:437
+#: plugins/sudoers/sssd.c:446
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "kan symbool \"%s\" niet vinden in %s"
+
+#: plugins/sudoers/sssd.c:1556
+#, c-format
+msgid ""
+"\n"
+"SSSD Role: %s\n"
+msgstr ""
+"\n"
+"SSSD Role: %s\n"
+
+#: plugins/sudoers/sssd.c:1561
+#, c-format
+msgid ""
+"\n"
+"SSSD Role: UNKNOWN\n"
+msgstr ""
+"\n"
+"SSSD Role: UNKNOWN\n"
+
+#: plugins/sudoers/sudo_nss.c:289
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Overeenkomende standaarditems voor %s op %s:\n"
+
+#: plugins/sudoers/sudo_nss.c:307
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Runas en opdrachtspecifieke standaarden voor %s:\n"
+
+#: plugins/sudoers/sudo_nss.c:325
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "Gebruiker %s mag de volgende opdrachten uitvoeren op %s:\n"
+
+#: plugins/sudoers/sudo_nss.c:338
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Gebruiker %s mag geen sudo gebruiken op %s.\n"
+
+#: plugins/sudoers/sudoers.c:168 plugins/sudoers/testsudoers.c:247
+#: plugins/sudoers/visudo.c:233 plugins/sudoers/visudo.c:612
+#: plugins/sudoers/visudo.c:976
+msgid "unable to initialize sudoers default values"
+msgstr "kan sudoers-standaardwaarden niet initialiseren"
+
+#: plugins/sudoers/sudoers.c:198 plugins/sudoers/sudoers.c:891
+msgid "problem with defaults entries"
+msgstr "probleem met standaarditems"
+
+#: plugins/sudoers/sudoers.c:205
+msgid "no valid sudoers sources found, quitting"
+msgstr "geen geldige sudoers-bronnen gevonden, afsluiten"
+
+#: plugins/sudoers/sudoers.c:244
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers geeft aan dat root geen sudo mag gebruiken"
+
+#: plugins/sudoers/sudoers.c:301
+msgid "you are not permitted to use the -C option"
+msgstr "u heeft niet de rechten om de optie -C te gebruiken"
+
+#: plugins/sudoers/sudoers.c:390
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr "tijd-eigenaar (%s): Gebruiker bestaat niet"
+
+#: plugins/sudoers/sudoers.c:405
+msgid "no tty"
+msgstr "geen terminal"
+
+#: plugins/sudoers/sudoers.c:406
+msgid "sorry, you must have a tty to run sudo"
+msgstr "sorry, u moet een terminal hebben om sudo te gebruiken"
+
+#: plugins/sudoers/sudoers.c:468
+msgid "command in current directory"
+msgstr "opdracht in huidige map"
+
+#: plugins/sudoers/sudoers.c:487
+#, fuzzy
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "sorry, u mag de omgeving niet behouden"
+
+#: plugins/sudoers/sudoers.c:495
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "sorry, u mag de omgeving niet behouden"
+
+#: plugins/sudoers/sudoers.c:836
+msgid "command too long"
+msgstr "opdracht is te lang"
+
+#: plugins/sudoers/sudoers.c:948
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s in geen regulier bestand"
+
+#: plugins/sudoers/sudoers.c:952 plugins/sudoers/timestamp.c:217 toke.l:969
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s is eigendom van gebruikersnummer %u, zou %u moeten zijn"
+
+#: plugins/sudoers/sudoers.c:956 toke.l:974
+#, c-format
+msgid "%s is world writable"
+msgstr "%s kan door iedereen worden geschreven"
+
+#: plugins/sudoers/sudoers.c:960 toke.l:977
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s is eigendom van groepsnummer %u, zou %u moeten zijn"
+
+#: plugins/sudoers/sudoers.c:993
+#, fuzzy, c-format
+msgid "only root can use \"-c %s\""
+msgstr "alleen root kan '-c %s' gebruiken"
+
+#: plugins/sudoers/sudoers.c:1012
+#, c-format
+msgid "unknown login class: %s"
+msgstr "onbekende loginklasse: %s"
+
+#: plugins/sudoers/sudoers.c:1095 plugins/sudoers/sudoers.c:1109
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "kan computernaam %s niet herleiden"
+
+#: plugins/sudoers/sudoreplay.c:275
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "ongeldige filteroptie: %s"
+
+#: plugins/sudoers/sudoreplay.c:288
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "ongeldige maximale wachttijd: %s"
+
+#: plugins/sudoers/sudoreplay.c:300
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "ongeldige snelheidsfactor: %s"
+
+#: plugins/sudoers/sudoreplay.c:303 plugins/sudoers/visudo.c:186
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s versie %s\n"
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s/timing: %s"
+msgstr "%s/%.2s/%.2s/%.2s/timing: %s"
+
+#: plugins/sudoers/sudoreplay.c:341
+#, c-format
+msgid "%s/%s/timing: %s"
+msgstr "%s/%s/timing: %s"
+
+#: plugins/sudoers/sudoreplay.c:357
+#, fuzzy, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Bekijken van sudo sessie: %s\n"
+
+#: plugins/sudoers/sudoreplay.c:555 plugins/sudoers/sudoreplay.c:602
+#: plugins/sudoers/sudoreplay.c:804 plugins/sudoers/sudoreplay.c:894
+#: plugins/sudoers/sudoreplay.c:973 plugins/sudoers/sudoreplay.c:988
+#: plugins/sudoers/sudoreplay.c:995 plugins/sudoers/sudoreplay.c:1002
+#: plugins/sudoers/sudoreplay.c:1009 plugins/sudoers/sudoreplay.c:1016
+#: plugins/sudoers/sudoreplay.c:1162
+msgid "unable to add event to queue"
+msgstr "kan gebeurtenis niet aan wachtrij toevoegen"
+
+#: plugins/sudoers/sudoreplay.c:670
+msgid "unable to set tty to raw mode"
+msgstr "kan terminal niet instellen op rauwe modus"
+
+#: plugins/sudoers/sudoreplay.c:721
+#, c-format
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr "Waarschuwing: uw terminal is te klein om de log goed op te bekijken.\n"
+
+#: plugins/sudoers/sudoreplay.c:722
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Logverhouding is %d x %d, de verhouding van uw terminal is %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:749
+msgid "Replay finished, press any key to restore the terminal."
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:782
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "ongeldige timingsbestandregel: %s"
+
+#: plugins/sudoers/sudoreplay.c:1196 plugins/sudoers/sudoreplay.c:1221
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "dubbelzinnige expressie \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1243
+msgid "unmatched ')' in expression"
+msgstr "ongepaarde ')' in expressie"
+
+#: plugins/sudoers/sudoreplay.c:1247
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "onbekende zoekterm \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1262
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s vereist een argument"
+
+#: plugins/sudoers/sudoreplay.c:1265 plugins/sudoers/sudoreplay.c:1645
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr "ongeldige reguliere expressie: %s"
+
+#: plugins/sudoers/sudoreplay.c:1269
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "kan datum niet ontleden \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1278
+msgid "unmatched '(' in expression"
+msgstr "ongepaarde '(' in expressie"
+
+#: plugins/sudoers/sudoreplay.c:1280
+msgid "illegal trailing \"or\""
+msgstr "ongeldige afsluitende \"or\""
+
+#: plugins/sudoers/sudoreplay.c:1282
+msgid "illegal trailing \"!\""
+msgstr "ongeldige afsluitende \"!\""
+
+#: plugins/sudoers/sudoreplay.c:1331
+#, c-format
+msgid "unknown search type %d"
+msgstr "onbekend zoektype %d"
+
+#: plugins/sudoers/sudoreplay.c:1369
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: ongeldig logbestand"
+
+#: plugins/sudoers/sudoreplay.c:1387
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: tijdveld ontbreekt"
+
+#: plugins/sudoers/sudoreplay.c:1394
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: tijdstempel %s: %s"
+
+#: plugins/sudoers/sudoreplay.c:1401
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: gebruikersveld ontbreekt"
+
+#: plugins/sudoers/sudoreplay.c:1410
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: runas-gebuikersveld ontbreekt"
+
+#: plugins/sudoers/sudoreplay.c:1419
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: runas-groepveld ontbreekt"
+
+#: plugins/sudoers/sudoreplay.c:1825
+#, c-format
+msgid "usage: %s [-hnR] [-d dir] [-m num] [-s num] ID\n"
+msgstr "Gebruik: %s [-hnR] [-d map] [-m wachttijd] [-s snelheidsfactor] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1828
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "Gebruik: %s [-h] [-d map] -l [zoek-expressie]\n"
+
+#: plugins/sudoers/sudoreplay.c:1837
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - sudo sessielogs bekijken\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1839
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Opties:\n"
+" -d, --directory=map map voor sessielogs opgeven\n"
+" -f, --filter=filter opgeven welk type in-/uitvoer moet worden weergegeven\n"
+" -h, --help geef help weer (dit bericht) en sluit af\n"
+" -l, --list [expressie] som beschikbare sessienummers\n"
+" die overeenkomen met de expressie op\n"
+" -m, --max-wait=num wacht tussen gebeurtenissen maximaal m seconden\n"
+" -s, --speed=num snelheid van uitvoer verhogen of verlagen\n"
+" -V, --version geef versieinformatie weer en sluit af"
+
+#: plugins/sudoers/testsudoers.c:329
+msgid "\thost unmatched"
+msgstr "\tcomputer komt niet overeen"
+
+#: plugins/sudoers/testsudoers.c:332
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Opdracht toegestaan"
+
+#: plugins/sudoers/testsudoers.c:333
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Opdracht niet toegestaan"
+
+#: plugins/sudoers/testsudoers.c:333
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Opdracht komt niet overeen"
+
+#: plugins/sudoers/timestamp.c:225
+#, c-format
+msgid "%s is group writable"
+msgstr "%s kan door groep worden gewijzigd"
+
+#: plugins/sudoers/timestamp.c:301
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "kan tijdstempelbestand niet inkorten naar %lld bytes"
+
+#: plugins/sudoers/timestamp.c:756 plugins/sudoers/timestamp.c:823
+#: plugins/sudoers/visudo.c:500 plugins/sudoers/visudo.c:506
+msgid "unable to read the clock"
+msgstr "kan de klok niet lezen"
+
+#: plugins/sudoers/timestamp.c:770
+msgid "ignoring time stamp from the future"
+msgstr "tijdstempel uit de toekomst wordt genegeerd"
+
+#: plugins/sudoers/timestamp.c:782
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "tijd is te ver in de toekomst: %20.20s"
+
+#: plugins/sudoers/timestamp.c:877
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "kan tijdstempelbestand %s niet vergrendelen"
+
+#: plugins/sudoers/timestamp.c:921 plugins/sudoers/timestamp.c:941
+#, fuzzy, c-format
+msgid "lecture status path too long: %s/%s"
+msgstr "tijd voor pad te lang: %s"
+
+#: plugins/sudoers/visudo.c:188
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s grammaticaversie %d\n"
+
+#: plugins/sudoers/visudo.c:266 plugins/sudoers/visudo.c:667
+#, c-format
+msgid "press return to edit %s: "
+msgstr "Druk op Enter om %s te bewerken: "
+
+#: plugins/sudoers/visudo.c:331
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "opgegeven editor (%s) bestaat niet"
+
+#: plugins/sudoers/visudo.c:349
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "geen editor gevonden (editorpad = %s)"
+
+#: plugins/sudoers/visudo.c:459 plugins/sudoers/visudo.c:467
+msgid "write error"
+msgstr "schrijffout"
+
+#: plugins/sudoers/visudo.c:513
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "kan status van tijdelijk bestand (%s) niet vaststellen, %s ongewijzigd"
+
+#: plugins/sudoers/visudo.c:520
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "tijdelijk bestand (%s) leeg, %s ongewijzigd"
+
+#: plugins/sudoers/visudo.c:526
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "editor (%s) is mislukt, %s ongewijzigd"
+
+#: plugins/sudoers/visudo.c:548
+#, c-format
+msgid "%s unchanged"
+msgstr "%s ongewijzigd"
+
+#: plugins/sudoers/visudo.c:607
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "kan tijdelijk bestand (%s) niet openen, %s ongewijzigd."
+
+#: plugins/sudoers/visudo.c:619
+#, c-format
+msgid "unabled to parse temporary file (%s), unknown error"
+msgstr "kan tijdelijke bestand (%s) niet ontleden, onbekende fout"
+
+#: plugins/sudoers/visudo.c:656
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr "interne fout, kan %s niet in de lijst vinden!"
+
+#: plugins/sudoers/visudo.c:736 plugins/sudoers/visudo.c:745
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "kan %s niet wijzigen (gebruikers- of groepsnummer) naar (%u, %u)"
+
+#: plugins/sudoers/visudo.c:767
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s en %s niet op hetzelfde bestandssyteem, gebuikt mv om te hernoemen"
+
+#: plugins/sudoers/visudo.c:781
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "opdracht mislukt: '%s %s %s', %s ongewijzigd"
+
+#: plugins/sudoers/visudo.c:791
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "fout bij hernoemen %s, %s ongewijzigd"
+
+#: plugins/sudoers/visudo.c:855
+msgid "What now? "
+msgstr "Wat nu? "
+
+#: plugins/sudoers/visudo.c:869
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Opties zijn:\n"
+" (e)dit sudoers bestand opnieuw\n"
+" e(x)it zonder de wijzigingen op te slaan\n"
+" (Q)uit en sla wijziging op in het sudoers bestand (GEVAAR!)\n"
+
+#: plugins/sudoers/visudo.c:915
+#, c-format
+msgid "unable to run %s"
+msgstr "kan %s niet uitvoeren"
+
+#: plugins/sudoers/visudo.c:945
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: verkeerde eigenaar (gebruikers-, groepsnummer) zou moeten zijn (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:952
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: verkeerde toegangsrechten, zou modus 0%o moeten zijn\n"
+
+#: plugins/sudoers/visudo.c:981 plugins/sudoers/visudo_json.c:1021
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "kan %s-bestand niet ontleden, onbekende fout"
+
+#: plugins/sudoers/visudo.c:997 plugins/sudoers/visudo_json.c:1032
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr "fout bij ontleden van %s bij regel %d\n"
+
+#: plugins/sudoers/visudo.c:1000 plugins/sudoers/visudo_json.c:1035
+#, c-format
+msgid "parse error in %s\n"
+msgstr "fout bij ontleden van %s\n"
+
+#: plugins/sudoers/visudo.c:1008 plugins/sudoers/visudo.c:1015
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: ontleden is geslaagd\n"
+
+#: plugins/sudoers/visudo.c:1062
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s bezig, probeer het later opnieuw"
+
+#: plugins/sudoers/visudo.c:1159
+#, fuzzy, c-format
+msgid "Error: %s:%d cycle in %s \"%s\""
+msgstr "Fout: cyclus in %s '%s'"
+
+#: plugins/sudoers/visudo.c:1160
+#, fuzzy, c-format
+msgid "Warning: %s:%d cycle in %s \"%s\""
+msgstr "Waarschuwing: cyclus in %s '%s'"
+
+#: plugins/sudoers/visudo.c:1164
+#, c-format
+msgid "Error: %s:%d %s \"%s\" referenced but not defined"
+msgstr "Fout: %s:%d %s \"%s\" wordt naar verwezen, maar is niet gedefinieerd"
+
+#: plugins/sudoers/visudo.c:1165
+#, c-format
+msgid "Warning: %s:%d %s \"%s\" referenced but not defined"
+msgstr "Waarschuwing: %s:%d %s \"%s\" wordt naar verwezen, maar is niet gedefinieerd"
+
+#: plugins/sudoers/visudo.c:1318
+#, fuzzy, c-format
+msgid "Warning: %s:%d unused %s \"%s\""
+msgstr "Waarschuwing: %s '%s' wordt niet gebruikt"
+
+#: plugins/sudoers/visudo.c:1433
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - bewerk het sudoersbestand voorzichtig\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1435
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+" -x, --export=output_file write sudoers in JSON format to output_file"
+msgstr ""
+"\n"
+"Opties:\n"
+" -c, --check alleen lezen modus\n"
+" -f, --file=bestand geef lokatie van sudoersbestand op\n"
+" -h, --help geef help weer (dit bericht) en sluit af\n"
+" -q, --quiet minder uitgebreide syntactische fout berichten\n"
+" -s, --strict stricte controle van syntaxis\n"
+" -V, --verion geef versieinformatie weer en sluit af"
+
+#: plugins/sudoers/visudo_json.c:616 plugins/sudoers/visudo_json.c:651
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "onbekend standaarditem '%s'"
+
+#: plugins/sudoers/visudo_json.c:1007
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: in- en uitvoerbestanden moeten verschillen"
+
+#: toke.l:943
+msgid "too many levels of includes"
+msgstr "te veel niveaus van insluitingen"
+
+#~ msgid "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+#~ msgstr "sudo_ldap_conf_add_ports: ruimte ontoereikend bij uitbreiden hostbuf"
+
+#~ msgid "sudo_ldap_parse_uri: out of space building hostbuf"
+#~ msgstr "sudo_ldap_parse_uri: ruimte ontoereikend bij bouwen van hostbuf"
+
+#~ msgid "sudo_ldap_build_pass1 allocation mismatch"
+#~ msgstr "sudo_ldap_build_pass1 reserveren mislukt"
+
+#~ msgid "timestamp path too long: %s/%s"
+#~ msgstr "tijd voor pad te lang: %s/%s"
+
+#~ msgid "unable to stat editor (%s)"
+#~ msgstr "kan status van editor (%s) niet verkrijgen"
+
+#~ msgid "Password:"
+#~ msgstr "Wachtwoord:"
+
+#~ msgid "unable to setup authentication"
+#~ msgstr "kan verificatie niet instellen"
+
+#~ msgid "invalid uri: %s"
+#~ msgstr "ongeldige uri: %s"
+
+#~ msgid "unable to mix ldaps and starttls"
+#~ msgstr "kan ldaps en starttls niet door elkaar gebruiken"
+
+#~ msgid "internal error: insufficient space for log line"
+#~ msgstr "interne fout: onvoldoende ruimte voor logregel"
+
+#~ msgid "value out of range"
+#~ msgstr "waarde buiten bereik"
+
+#~ msgid "writing to standard output"
+#~ msgstr "naar standaarduitvoer schrijven"
+
+#~ msgid "too many parenthesized expressions, max %d"
+#~ msgstr "te veel geneste expressies, maximum %d"
+
+#~ msgid "%s owned by uid %u, should be uid %u"
+#~ msgstr "%s is van gebruikersnummer %u, zou gebruikersnummer %u moeten zijn"
+
+#~ msgid "%s writable by non-owner (0%o), should be mode 0700"
+#~ msgstr "%s kan geschreven worden door niet-eigenaar (0%o), zou ingesteld moeten zijn op 0700"
+
+#~ msgid "%s exists but is not a regular file (0%o)"
+#~ msgstr "%s bestaat maar is geen normaal bestand (0%o)"
+
+#~ msgid "%s writable by non-owner (0%o), should be mode 0600"
+#~ msgstr "%s kan geschreven worden bij niet-eigenaar (0%o), zou ingesteld moeten zijn op 0600"
+
+#~ msgid "unable to remove %s, will reset to the epoch"
+#~ msgstr "kan %s niet verwijderen, wordt geherinitialiseerd op de epoch"
+
+#~ msgid "fill_args: buffer overflow"
+#~ msgstr "fill_args: stapeloverloop"
+
+#~ msgid "%s: unused %s_Alias %s"
+#~ msgstr "%s: ongebruikte %s_Alias %s"
+
+#~ msgid ">>> %s: %s near line %d <<<"
+#~ msgstr ">>> %s: %s bij regel %d <<<"
+
+#~ msgid "pam_chauthtok: %s"
+#~ msgstr "pam_chauthtok: %s"
+
+#~ msgid "pam_authenticate: %s"
+#~ msgstr "pam_authenticate: %s"
+
+#~ msgid "getaudit: failed"
+#~ msgstr "getaudit: mislukt"
+
+#~ msgid "getauid failed"
+#~ msgstr "getauid mislukt"
+
+#~ msgid "au_open: failed"
+#~ msgstr "au_open: mislukt"
+
+#~ msgid "au_to_subject: failed"
+#~ msgstr "au_to_subject: mislukt"
+
+#~ msgid "au_to_exec_args: failed"
+#~ msgstr "au_to_exec_args: mislukt"
+
+#~ msgid "au_to_return32: failed"
+#~ msgstr "au_to_return32: mislukt"
+
+#~ msgid "getauid: failed"
+#~ msgstr "getauid: failed"
+
+#~ msgid "au_to_text: failed"
+#~ msgstr "au_to_text: failed"
+
+#~ msgid "unable to set locale to \"%s\", using \"C\""
+#~ msgstr "kan taaldefinitie niet instellen op \"%s\", gebruikt wordt \"C\""
+
+#~ msgid ""
+#~ " Commands:\n"
+#~ "\t"
+#~ msgstr ""
+#~ " Opdrachten:\n"
+#~ "\t"
+
+#~ msgid "unable to cache uid %u (%s), already exists"
+#~ msgstr "kan gebruikersnummer %u niet bufferen (%s), bestaat reeds"
+
+#~ msgid "unable to cache gid %u (%s), already exists"
+#~ msgstr "kan groepsnummer %u niet bufferen (%s), bestaat reeds"
+
+#~ msgid "Unable to dlopen %s: %s"
+#~ msgstr "Kan niet dlopen %s: %s"
+
+#~ msgid "unable to execute %s: %s"
+#~ msgstr "kan %s niet uitvoeren: %s"
+
+#~ msgid "nanosleep: tv_sec %ld, tv_nsec %ld"
+#~ msgstr "nanosleep: tv_sec %ld, tv_nsec %ld"
+
+#~ msgid "invalid regex: %s"
+#~ msgstr "ongeldige reguliere expressie: %s"
diff --git a/plugins/sudoers/po/pl.mo b/plugins/sudoers/po/pl.mo
new file mode 100644
index 0000000..2f67b30
--- /dev/null
+++ b/plugins/sudoers/po/pl.mo
Binary files differ
diff --git a/plugins/sudoers/po/pl.po b/plugins/sudoers/po/pl.po
new file mode 100644
index 0000000..7be3a1d
--- /dev/null
+++ b/plugins/sudoers/po/pl.po
@@ -0,0 +1,3850 @@
+# Polish translation for sudo/sudoers.
+# This file is put in the public domain.
+# Jakub Bogusz <qboosh@pld-linux.org>, 2011-2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.9.15b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-10-19 10:02-0600\n"
+"PO-Revision-Date: 2023-10-21 17:45+0200\n"
+"Last-Translator: Jakub Bogusz <qboosh@pld-linux.org>\n"
+"Language-Team: Polish <translation-team-pl@lists.sourceforge.net>\n"
+"Language: pl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: confstr.sh:1 gram.y:1257 plugins/sudoers/logging.c:911
+msgid "syntax error"
+msgstr "błąd składni"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "Hasło użytkownika %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] hasło użytkownika %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Hasło: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** informacje dotyczące BEZPIECZEŃSTWA dla %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Niestety, proszę spróbować ponownie."
+
+#: gram.y:238 gram.y:305 gram.y:314 gram.y:323 gram.y:333 gram.y:343 gram.y:367
+#: gram.y:394 gram.y:403 gram.y:411 gram.y:420 gram.y:429 gram.y:503 gram.y:513
+#: gram.y:525 gram.y:573 gram.y:582 gram.y:591 gram.y:600 gram.y:733 gram.y:742
+#: gram.y:757 gram.y:777 gram.y:796 gram.y:959 gram.y:964 gram.y:972 gram.y:986
+#: gram.y:992 gram.y:1004 gram.y:1010 gram.y:1135 gram.y:1144 gram.y:1152
+#: gram.y:1161 gram.y:1170 gram.y:1199 gram.y:1208 gram.y:1216 gram.y:1317
+#: gram.y:1447 gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:313 lib/eventlog/eventlog.c:765
+#: lib/eventlog/eventlog.c:842 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:484
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:185
+#: logsrvd/iolog_writer.c:218 logsrvd/iolog_writer.c:228
+#: logsrvd/iolog_writer.c:257 logsrvd/iolog_writer.c:278
+#: logsrvd/iolog_writer.c:290 logsrvd/iolog_writer.c:300
+#: logsrvd/iolog_writer.c:310 logsrvd/iolog_writer.c:320
+#: logsrvd/iolog_writer.c:330 logsrvd/iolog_writer.c:342
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:1057 logsrvd/logsrvd.c:1120 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:650
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1743
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:216
+#: logsrvd/logsrvd_journal.c:217 logsrvd/logsrvd_journal.c:274
+#: logsrvd/logsrvd_journal.c:279 logsrvd/logsrvd_journal.c:439
+#: logsrvd/logsrvd_journal.c:441 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:216 logsrvd/logsrvd_local.c:278
+#: logsrvd/logsrvd_local.c:279 logsrvd/logsrvd_local.c:417
+#: logsrvd/logsrvd_local.c:468 logsrvd/logsrvd_local.c:469
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:475
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/logsrvd_relay.c:446
+#: logsrvd/logsrvd_relay.c:748 logsrvd/logsrvd_relay.c:855
+#: logsrvd/sendlog.c:256 logsrvd/sendlog.c:265 logsrvd/sendlog.c:297
+#: logsrvd/sendlog.c:303 logsrvd/sendlog.c:352 logsrvd/sendlog.c:630
+#: logsrvd/sendlog.c:1822 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/bsdauth.c:154 plugins/sudoers/auth/kerb5.c:122
+#: plugins/sudoers/auth/kerb5.c:150 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/auth/sia.c:61
+#: plugins/sudoers/canon_path.c:129 plugins/sudoers/canon_path.c:161
+#: plugins/sudoers/check_aliases.c:128 plugins/sudoers/check_util.c:56
+#: plugins/sudoers/check_util.c:84 plugins/sudoers/cvtsudoers.c:132
+#: plugins/sudoers/cvtsudoers.c:176 plugins/sudoers/cvtsudoers.c:193
+#: plugins/sudoers/cvtsudoers.c:204 plugins/sudoers/cvtsudoers.c:338
+#: plugins/sudoers/cvtsudoers.c:379 plugins/sudoers/cvtsudoers.c:399
+#: plugins/sudoers/cvtsudoers.c:545 plugins/sudoers/cvtsudoers.c:698
+#: plugins/sudoers/cvtsudoers.c:716 plugins/sudoers/cvtsudoers.c:891
+#: plugins/sudoers/cvtsudoers.c:899 plugins/sudoers/cvtsudoers.c:1395
+#: plugins/sudoers/cvtsudoers.c:1399 plugins/sudoers/cvtsudoers.c:1501
+#: plugins/sudoers/cvtsudoers_csv.c:183 plugins/sudoers/cvtsudoers_csv.c:247
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:152
+#: plugins/sudoers/cvtsudoers_ldif.c:195 plugins/sudoers/cvtsudoers_ldif.c:236
+#: plugins/sudoers/cvtsudoers_ldif.c:302 plugins/sudoers/cvtsudoers_ldif.c:378
+#: plugins/sudoers/cvtsudoers_ldif.c:432 plugins/sudoers/cvtsudoers_ldif.c:440
+#: plugins/sudoers/cvtsudoers_ldif.c:451 plugins/sudoers/cvtsudoers_ldif.c:458
+#: plugins/sudoers/cvtsudoers_ldif.c:470 plugins/sudoers/cvtsudoers_ldif.c:483
+#: plugins/sudoers/cvtsudoers_ldif.c:491 plugins/sudoers/cvtsudoers_ldif.c:638
+#: plugins/sudoers/cvtsudoers_merge.c:47 plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1158
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:212
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:694 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:294 plugins/sudoers/ldap_util.c:301
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:402
+#: plugins/sudoers/log_client.c:717 plugins/sudoers/log_client.c:739
+#: plugins/sudoers/log_client.c:744 plugins/sudoers/log_client.c:1426
+#: plugins/sudoers/log_client.c:1547 plugins/sudoers/log_client.c:1670
+#: plugins/sudoers/log_client.c:1993 plugins/sudoers/log_client.c:2052
+#: plugins/sudoers/logging.c:110 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:872 plugins/sudoers/lookup.c:338
+#: plugins/sudoers/lookup.c:355 plugins/sudoers/lookup.c:374
+#: plugins/sudoers/lookup.c:393 plugins/sudoers/lookup.c:410
+#: plugins/sudoers/lookup.c:433 plugins/sudoers/lookup.c:444
+#: plugins/sudoers/match_command.c:302 plugins/sudoers/match_command.c:574
+#: plugins/sudoers/match_command.c:641 plugins/sudoers/match_command.c:737
+#: plugins/sudoers/match_command.c:785 plugins/sudoers/match_digest.c:88
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:595
+#: plugins/sudoers/parse_ldif.c:625 plugins/sudoers/parse_ldif.c:650
+#: plugins/sudoers/parse_ldif.c:708 plugins/sudoers/parse_ldif.c:725
+#: plugins/sudoers/parse_ldif.c:753 plugins/sudoers/parse_ldif.c:760
+#: plugins/sudoers/policy.c:646 plugins/sudoers/policy.c:1061
+#: plugins/sudoers/prompt.c:94 plugins/sudoers/pwutil.c:219
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:368
+#: plugins/sudoers/pwutil.c:542 plugins/sudoers/pwutil.c:607
+#: plugins/sudoers/pwutil.c:679 plugins/sudoers/pwutil.c:877
+#: plugins/sudoers/pwutil.c:967 plugins/sudoers/pwutil.c:1015
+#: plugins/sudoers/pwutil.c:1076 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:145 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1307 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:256
+#: plugins/sudoers/testsudoers.c:265 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:164 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1095
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1320
+msgid "unable to allocate memory"
+msgstr "nie udało się przydzielić pamięci"
+
+#: gram.y:624
+msgid "a digest requires a path name"
+msgstr "skrót wymaga nazwy pliku"
+
+#: gram.y:646
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "wartości \"CWD\" muszą zaczynać się od '/', '~' lub '*'"
+
+#: gram.y:652
+msgid "\"CWD\" path too long"
+msgstr "ścieżka \"CWD\" zbyt długa"
+
+#: gram.y:662
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "wartości \"CHROOT\" muszą zaczynać się od '/', '~' lub '*'"
+
+#: gram.y:668
+msgid "\"CHROOT\" path too long"
+msgstr "ścieżka \"CHROOT\" zbyt długa"
+
+#: gram.y:817
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "błąd składni, słowo zastrzeżone %s użyte jako nazwa aliasu"
+
+#: gram.y:840
+msgid "invalid notbefore value"
+msgstr "błędna wartość notbefore"
+
+#: gram.y:849
+msgid "invalid notafter value"
+msgstr "błędna wartość notafter"
+
+#: gram.y:859 plugins/sudoers/policy.c:390
+msgid "timeout value too large"
+msgstr "wartość limitu czasu zbyt duża"
+
+#: gram.y:861 plugins/sudoers/policy.c:392
+msgid "invalid timeout value"
+msgstr "błędna wartość limitu czasu"
+
+#: gram.y:982 plugins/sudoers/sudoers.c:1162
+msgid "command too long"
+msgstr "polecenie zbyt długie"
+
+#: gram.y:1016
+msgid "expected a fully-qualified path name"
+msgstr "oczekiwano pełnej ścieżki"
+
+#: gram.y:1261
+#, c-format
+msgid "%s:%d:%zu: %s\n"
+msgstr "%s:%d:%zu: %s\n"
+
+#: gram.y:1315
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Alias \"%s\" jest już zdefiniowany"
+
+#: gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:765 lib/eventlog/eventlog.c:838
+#: lib/eventlog/eventlog.c:841 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:483
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:232
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:174
+#: logsrvd/iolog_writer.c:184 logsrvd/iolog_writer.c:197
+#: logsrvd/iolog_writer.c:217 logsrvd/iolog_writer.c:227
+#: logsrvd/iolog_writer.c:246 logsrvd/iolog_writer.c:256
+#: logsrvd/iolog_writer.c:267 logsrvd/iolog_writer.c:277
+#: logsrvd/iolog_writer.c:289 logsrvd/iolog_writer.c:299
+#: logsrvd/iolog_writer.c:309 logsrvd/iolog_writer.c:319
+#: logsrvd/iolog_writer.c:329 logsrvd/iolog_writer.c:341
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:530
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:668
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:1131
+#: logsrvd/logsrvd.c:1446 logsrvd/logsrvd.c:1453 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:649
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1742
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:125
+#: logsrvd/logsrvd_journal.c:216 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:250 logsrvd/logsrvd_journal.c:258
+#: logsrvd/logsrvd_journal.c:287 logsrvd/logsrvd_journal.c:291
+#: logsrvd/logsrvd_journal.c:439 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:278 logsrvd/logsrvd_local.c:468
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:493
+#: logsrvd/logsrvd_queue.c:158 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/sendlog.c:256 logsrvd/sendlog.c:265
+#: logsrvd/sendlog.c:297 logsrvd/sendlog.c:303 logsrvd/sendlog.c:352
+#: logsrvd/sendlog.c:630 logsrvd/sendlog.c:1523 logsrvd/sendlog.c:1530
+#: logsrvd/sendlog.c:1753 logsrvd/sendlog.c:1822 logsrvd/tls_init.c:305
+#: logsrvd/tls_init.c:329 logsrvd/tls_init.c:340 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/pam.c:518 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/canon_path.c:129
+#: plugins/sudoers/canon_path.c:161 plugins/sudoers/check_aliases.c:128
+#: plugins/sudoers/check_util.c:56 plugins/sudoers/check_util.c:84
+#: plugins/sudoers/cvtsudoers.c:132 plugins/sudoers/cvtsudoers.c:175
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:203
+#: plugins/sudoers/cvtsudoers.c:337 plugins/sudoers/cvtsudoers.c:544
+#: plugins/sudoers/cvtsudoers.c:697 plugins/sudoers/cvtsudoers.c:715
+#: plugins/sudoers/cvtsudoers.c:891 plugins/sudoers/cvtsudoers.c:898
+#: plugins/sudoers/cvtsudoers.c:1395 plugins/sudoers/cvtsudoers.c:1399
+#: plugins/sudoers/cvtsudoers.c:1501 plugins/sudoers/cvtsudoers_csv.c:182
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:151 plugins/sudoers/cvtsudoers_ldif.c:194
+#: plugins/sudoers/cvtsudoers_ldif.c:235 plugins/sudoers/cvtsudoers_ldif.c:301
+#: plugins/sudoers/cvtsudoers_ldif.c:377 plugins/sudoers/cvtsudoers_ldif.c:431
+#: plugins/sudoers/cvtsudoers_ldif.c:439 plugins/sudoers/cvtsudoers_ldif.c:450
+#: plugins/sudoers/cvtsudoers_ldif.c:457 plugins/sudoers/cvtsudoers_ldif.c:469
+#: plugins/sudoers/cvtsudoers_ldif.c:482 plugins/sudoers/cvtsudoers_ldif.c:490
+#: plugins/sudoers/cvtsudoers_ldif.c:637 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51 plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1157
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:211
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:693 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:293 plugins/sudoers/ldap_util.c:300
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:228
+#: plugins/sudoers/log_client.c:250 plugins/sudoers/log_client.c:264
+#: plugins/sudoers/log_client.c:402 plugins/sudoers/log_client.c:717
+#: plugins/sudoers/log_client.c:739 plugins/sudoers/log_client.c:744
+#: plugins/sudoers/log_client.c:1426 plugins/sudoers/log_client.c:1547
+#: plugins/sudoers/log_client.c:1670 plugins/sudoers/log_client.c:1993
+#: plugins/sudoers/log_client.c:2052 plugins/sudoers/logging.c:110
+#: plugins/sudoers/logging.c:189 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:755 plugins/sudoers/logging.c:872
+#: plugins/sudoers/logging.c:925 plugins/sudoers/logging.c:932
+#: plugins/sudoers/lookup.c:337 plugins/sudoers/lookup.c:354
+#: plugins/sudoers/lookup.c:373 plugins/sudoers/lookup.c:392
+#: plugins/sudoers/lookup.c:409 plugins/sudoers/lookup.c:432
+#: plugins/sudoers/lookup.c:443 plugins/sudoers/match_command.c:301
+#: plugins/sudoers/match_command.c:573 plugins/sudoers/match_command.c:640
+#: plugins/sudoers/match_command.c:737 plugins/sudoers/match_command.c:784
+#: plugins/sudoers/match_digest.c:88 plugins/sudoers/parse_ldif.c:152
+#: plugins/sudoers/parse_ldif.c:183 plugins/sudoers/parse_ldif.c:252
+#: plugins/sudoers/parse_ldif.c:260 plugins/sudoers/parse_ldif.c:265
+#: plugins/sudoers/parse_ldif.c:341 plugins/sudoers/parse_ldif.c:352
+#: plugins/sudoers/parse_ldif.c:379 plugins/sudoers/parse_ldif.c:396
+#: plugins/sudoers/parse_ldif.c:408 plugins/sudoers/parse_ldif.c:412
+#: plugins/sudoers/parse_ldif.c:426 plugins/sudoers/parse_ldif.c:484
+#: plugins/sudoers/parse_ldif.c:595 plugins/sudoers/parse_ldif.c:624
+#: plugins/sudoers/parse_ldif.c:649 plugins/sudoers/parse_ldif.c:707
+#: plugins/sudoers/parse_ldif.c:724 plugins/sudoers/parse_ldif.c:752
+#: plugins/sudoers/parse_ldif.c:759 plugins/sudoers/policy.c:157
+#: plugins/sudoers/policy.c:166 plugins/sudoers/policy.c:175
+#: plugins/sudoers/policy.c:204 plugins/sudoers/policy.c:374
+#: plugins/sudoers/policy.c:390 plugins/sudoers/policy.c:392
+#: plugins/sudoers/policy.c:430 plugins/sudoers/policy.c:439
+#: plugins/sudoers/policy.c:448 plugins/sudoers/policy.c:457
+#: plugins/sudoers/policy.c:493 plugins/sudoers/policy.c:502
+#: plugins/sudoers/policy.c:511 plugins/sudoers/policy.c:520
+#: plugins/sudoers/policy.c:529 plugins/sudoers/policy.c:538
+#: plugins/sudoers/policy.c:547 plugins/sudoers/policy.c:646
+#: plugins/sudoers/policy.c:1061 plugins/sudoers/prompt.c:94
+#: plugins/sudoers/pwutil.c:219 plugins/sudoers/pwutil.c:290
+#: plugins/sudoers/pwutil.c:368 plugins/sudoers/pwutil.c:542
+#: plugins/sudoers/pwutil.c:607 plugins/sudoers/pwutil.c:679
+#: plugins/sudoers/pwutil.c:877 plugins/sudoers/pwutil.c:967
+#: plugins/sudoers/pwutil.c:1015 plugins/sudoers/pwutil.c:1076
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1306 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:255
+#: plugins/sudoers/testsudoers.c:264 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:163 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1094
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1309 toke.l:1320
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:304
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "nie udało się wykonać dup na stdin: %m"
+
+#: lib/eventlog/eventlog.c:346
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "nie udało się wywołać %s: %m"
+
+#: lib/eventlog/eventlog.c:394 plugins/sudoers/auth/aix_auth.c:199
+msgid "unable to fork"
+msgstr "nie udało się wykonać fork"
+
+#: lib/eventlog/eventlog.c:404 lib/eventlog/eventlog.c:471
+#, c-format
+msgid "unable to fork: %m"
+msgstr "nie udało się wykonać fork: %m"
+
+#: lib/eventlog/eventlog.c:461
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "nie udało się otworzyć potoku: %m"
+
+#: lib/eventlog/eventlog.c:1000
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:1029
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (kontynuacja polecenia) %s"
+
+#: lib/eventlog/parse_json.c:175
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "nieoczekiwany JSON_STRING, otrzymano %d"
+
+#: lib/eventlog/parse_json.c:180
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY zbyt duża"
+
+#: lib/eventlog/parse_json.c:506
+msgid "missing double quote in name"
+msgstr "brak podwójnego cudzysłowu w nazwie"
+
+#: lib/eventlog/parse_json.c:624
+msgid "missing JSON_OBJECT"
+msgstr "brakujący JSON_OBJECT"
+
+#: lib/eventlog/parse_json.c:628
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "oczekiwany JSON_OBJECT, otrzymano %d"
+
+#: lib/eventlog/parse_json.c:762
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "stos json wyczerpany (maksimum %u ramek)"
+
+#: lib/eventlog/parse_json.c:840
+msgid "objects must consist of name:value pairs"
+msgstr "obiekty muszą składać się z kluczy nazwa:wartość"
+
+#: lib/eventlog/parse_json.c:845 lib/eventlog/parse_json.c:876
+#: lib/eventlog/parse_json.c:920 lib/eventlog/parse_json.c:942
+#: lib/eventlog/parse_json.c:964 lib/eventlog/parse_json.c:986
+#: lib/eventlog/parse_json.c:1008
+msgid "missing separator between values"
+msgstr "brak separatora między wartościami"
+
+#: lib/eventlog/parse_json.c:860 lib/eventlog/parse_json.c:1034
+msgid "unmatched close brace"
+msgstr "brak klamry zamykającej"
+
+#: lib/eventlog/parse_json.c:871
+msgid "unexpected array"
+msgstr "nieoczekiwana tablica"
+
+#: lib/eventlog/parse_json.c:891 lib/eventlog/parse_json.c:1037
+msgid "unmatched close bracket"
+msgstr "brak nawiasu zamykającego"
+
+#: lib/eventlog/parse_json.c:902
+msgid "unexpected string"
+msgstr "nieoczekiwany łańcuch"
+
+#: lib/eventlog/parse_json.c:913
+msgid "missing colon after name"
+msgstr "brak dwukropka po nazwie"
+
+#: lib/eventlog/parse_json.c:934 lib/eventlog/parse_json.c:956
+msgid "unexpected boolean"
+msgstr "nieoczekiwana wartość logiczna"
+
+#: lib/eventlog/parse_json.c:978
+msgid "unexpected null"
+msgstr "nieoczekiwana wartość pusta"
+
+#: lib/eventlog/parse_json.c:999
+msgid "unexpected number"
+msgstr "nieoczekiwana liczba"
+
+#: lib/eventlog/parse_json.c:1045
+msgid "parse error"
+msgstr "błąd składni"
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1290
+#: plugins/sudoers/sudoreplay.c:1291 plugins/sudoers/sudoreplay.c:1587
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr "błędne wyrażenie regularne \"%s\": %s"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: błędny plik logu"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: brak pola znacznika czasu"
+
+#: lib/iolog/iolog_legacy.c:90
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: znacznik czasu %s: %s"
+
+#: lib/iolog/iolog_legacy.c:97
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: brak pola z użytkownikiem"
+
+#: lib/iolog/iolog_legacy.c:108
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: brak pola z użytkownikiem runas"
+
+#: lib/iolog/iolog_legacy.c:119
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: brak pola z grupą runas"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s istnieje, ale nie jest katalogiem (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:124 lib/iolog/iolog_mkdtemp.c:80
+#: logsrvd/iolog_writer.c:795 plugins/sudoers/timestamp.c:218
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "nie udało się wykonać mkdir %s"
+
+#: lib/iolog/iolog_mkdtemp.c:85 plugins/sudoers/visudo.c:769
+#: plugins/sudoers/visudo.c:803 plugins/sudoers/visudo.c:809
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "nie udało się zmienić uprawnień %s na 0%o"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "błąd podczas czytania pliku czasu: %s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "błędna linia pliku czasu: %s"
+
+#: logsrvd/iolog_writer.c:65
+#, c-format
+msgid "%s: protocol error: NULL key"
+msgstr "%s: błąd protokołu: klucz NULL"
+
+#: logsrvd/iolog_writer.c:69
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s: błąd protokołu: niewłaściwy typ dla %s"
+
+#: logsrvd/iolog_writer.c:74 logsrvd/logsrvd_local.c:109
+#: logsrvd/logsrvd_local.c:123 logsrvd/logsrvd_local.c:131
+#: logsrvd/logsrvd_local.c:149
+#, c-format
+msgid "%s: protocol error: NULL value found in %s"
+msgstr "%s: błąd protokołu: napotkano wartość NULL w %s"
+
+#: logsrvd/iolog_writer.c:141 plugins/sudoers/logging.c:1024
+#: plugins/sudoers/policy.c:613
+msgid "unable to generate UUID"
+msgstr "nie udało się wygenerować UUID-a"
+
+#: logsrvd/iolog_writer.c:354 logsrvd/iolog_writer.c:359
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:369
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s: błąd protokołu: brak %s w AcceptMessage"
+
+#: logsrvd/iolog_writer.c:430
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s: nie udało się sformatować id sesji"
+
+#: logsrvd/iolog_writer.c:444 logsrvd/iolog_writer.c:458
+#: logsrvd/iolog_writer.c:472 logsrvd/iolog_writer.c:487
+#: logsrvd/iolog_writer.c:501 logsrvd/iolog_writer.c:515
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s: %s nie jest ustawiony"
+
+#: logsrvd/iolog_writer.c:551 logsrvd/iolog_writer.c:558
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr "nie udało się rozwinąć ścieżki iologu %s"
+
+#: logsrvd/iolog_writer.c:576
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr "nie udało się utworzyć ścieżki iologu %s"
+
+#: logsrvd/iolog_writer.c:606
+#, c-format
+msgid "invalid iofd %d"
+msgstr "błędny iofd %d"
+
+#: logsrvd/iolog_writer.c:626
+#, c-format
+msgid "error closing iofd %u: %s"
+msgstr "błąd zamykania iofd %u: %s"
+
+#: logsrvd/iolog_writer.c:647
+#, c-format
+msgid "error flushing iofd %u: %s"
+msgstr "błąd opróżniania bufora iofd %u: %s"
+
+#: logsrvd/iolog_writer.c:765
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "błędny log we/wy %s: %s użyty, ale nie zdefiniowany"
+
+#: logsrvd/iolog_writer.c:777 logsrvd/logsrvd_journal.c:391
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "%s: nie udało się odnaleźć punktu wznowienia [%lld, %ld]"
+
+#: logsrvd/iolog_writer.c:799 logsrvd/logsrvd_journal.c:434
+#: logsrvd/logsrvd_queue.c:115 logsrvd/tls_init.c:256
+#: plugins/sudoers/check.c:285 plugins/sudoers/cvtsudoers.c:758
+#: plugins/sudoers/cvtsudoers.c:780 plugins/sudoers/cvtsudoers.c:1461
+#: plugins/sudoers/cvtsudoers_csv.c:697 plugins/sudoers/cvtsudoers_json.c:902
+#: plugins/sudoers/cvtsudoers_ldif.c:711 plugins/sudoers/sudoers.c:1291
+#: plugins/sudoers/sudoers.c:1317 plugins/sudoers/sudoreplay.c:1497
+#: plugins/sudoers/timestamp.c:478 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:990
+#, c-format
+msgid "unable to open %s"
+msgstr "nie udało się otworzyć %s"
+
+#: logsrvd/iolog_writer.c:811 logsrvd/logsrv_util.c:111
+#: logsrvd/logsrv_util.c:118 plugins/sudoers/sudoreplay.c:355
+#: plugins/sudoers/sudoreplay.c:361
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "nie udało się otworzyć %s/%s"
+
+#: logsrvd/iolog_writer.c:824
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "nie udało się skopiować %s/%s do %s/%s: %s"
+
+#: logsrvd/iolog_writer.c:853 logsrvd/logsrvd_journal.c:198
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "nie udało się zmienić nazwy %s na %s"
+
+#: logsrvd/logsrv_util.c:153 logsrvd/logsrv_util.c:182
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s: nie udało się odnaleźć punktu wznowienia [%lld, %ld]"
+
+#: logsrvd/logsrv_util.c:165
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "brak pliku logu we/wy %s/%s"
+
+#: logsrvd/logsrv_util.c:172
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s: nie udało przesunąć %zu w przód"
+
+#: logsrvd/logsrvd.c:271 logsrvd/logsrvd_queue.c:135
+msgid "unable to connect to relay"
+msgstr "nie udało się połączyć z przekaźnikiem"
+
+#: logsrvd/logsrvd.c:338 logsrvd/logsrvd_relay.c:847
+#, c-format
+msgid "server message too large: %zu"
+msgstr "komunikat serwera zbyt duży: %zu"
+
+#: logsrvd/logsrvd.c:430 logsrvd/logsrvd.c:553 logsrvd/logsrvd.c:639
+#: logsrvd/logsrvd.c:881 logsrvd/logsrvd.c:895 logsrvd/logsrvd.c:1056
+#: logsrvd/logsrvd.c:1181 logsrvd/logsrvd.c:1354 logsrvd/logsrvd.c:1372
+#: logsrvd/logsrvd.c:1471 logsrvd/logsrvd.c:1596 logsrvd/logsrvd.c:1783
+#: logsrvd/logsrvd_journal.c:503 logsrvd/logsrvd_local.c:238
+#: logsrvd/logsrvd_queue.c:164 logsrvd/logsrvd_relay.c:172
+#: logsrvd/logsrvd_relay.c:249 logsrvd/logsrvd_relay.c:253
+#: logsrvd/logsrvd_relay.c:391 logsrvd/logsrvd_relay.c:583
+#: logsrvd/logsrvd_relay.c:747 logsrvd/logsrvd_relay.c:1137
+#: logsrvd/sendlog.c:1308 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:216 plugins/sudoers/audit.c:281
+#: plugins/sudoers/iolog.c:1041 plugins/sudoers/iolog.c:1175
+#: plugins/sudoers/iolog.c:1274 plugins/sudoers/log_client.c:121
+#: plugins/sudoers/log_client.c:343 plugins/sudoers/log_client.c:359
+#: plugins/sudoers/log_client.c:407 plugins/sudoers/log_client.c:613
+#: plugins/sudoers/log_client.c:620 plugins/sudoers/log_client.c:1114
+#: plugins/sudoers/log_client.c:1395 plugins/sudoers/log_client.c:1436
+#: plugins/sudoers/log_client.c:1444 plugins/sudoers/log_client.c:1603
+#: plugins/sudoers/log_client.c:1728 plugins/sudoers/log_client.c:2060
+#: plugins/sudoers/log_client.c:2068 plugins/sudoers/logging.c:148
+#: plugins/sudoers/logging.c:206 plugins/sudoers/sudoreplay.c:519
+#: plugins/sudoers/sudoreplay.c:566 plugins/sudoers/sudoreplay.c:808
+#: plugins/sudoers/sudoreplay.c:920 plugins/sudoers/sudoreplay.c:1011
+#: plugins/sudoers/sudoreplay.c:1026 plugins/sudoers/sudoreplay.c:1033
+#: plugins/sudoers/sudoreplay.c:1040 plugins/sudoers/sudoreplay.c:1047
+#: plugins/sudoers/sudoreplay.c:1054 plugins/sudoers/sudoreplay.c:1182
+msgid "unable to add event to queue"
+msgstr "nie udało się dodać zdarzenia do kolejki"
+
+#: logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:491 logsrvd/logsrvd.c:523
+#: logsrvd/logsrvd.c:577 logsrvd/logsrvd.c:656 logsrvd/logsrvd.c:692
+#: logsrvd/logsrvd.c:728 logsrvd/logsrvd.c:764 logsrvd/logsrvd_relay.c:512
+#: logsrvd/logsrvd_relay.c:545
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr "nieoczekiwany stan %d dla %s"
+
+#: logsrvd/logsrvd.c:455 logsrvd/logsrvd.c:492 logsrvd/logsrvd.c:524
+#: logsrvd/logsrvd.c:578 logsrvd/logsrvd.c:657 logsrvd/logsrvd.c:693
+#: logsrvd/logsrvd.c:729 logsrvd/logsrvd.c:765 logsrvd/logsrvd_relay.c:514
+#: logsrvd/logsrvd_relay.c:547
+msgid "state machine error"
+msgstr "błąd maszyny stanów"
+
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:462
+msgid "invalid AcceptMessage"
+msgstr "błędny AcceptMessage"
+
+#: logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:499
+msgid "invalid RejectMessage"
+msgstr "błędny RejectMessage"
+
+#: logsrvd/logsrvd.c:530 logsrvd/logsrvd.c:531
+msgid "invalid ExitMessage"
+msgstr "błędny ExitMessage"
+
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:585
+msgid "invalid RestartMessage"
+msgstr "błędny RestartMessage"
+
+#: logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:620
+msgid "invalid AlertMessage"
+msgstr "błędny AlertMessage"
+
+#: logsrvd/logsrvd.c:661 logsrvd/logsrvd.c:697 logsrvd/logsrvd.c:733
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s: nieoczekiwany IoBuffer"
+
+#: logsrvd/logsrvd.c:662 logsrvd/logsrvd.c:698 logsrvd/logsrvd.c:734
+msgid "protocol error"
+msgstr "błąd protokołu"
+
+#: logsrvd/logsrvd.c:668 logsrvd/logsrvd.c:669
+msgid "invalid IoBuffer"
+msgstr "błędny IoBuffer"
+
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:705
+msgid "invalid ChangeWindowSize"
+msgstr "błędny ChangeWindowSize"
+
+#: logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:741
+msgid "invalid CommandSuspend"
+msgstr "błędny CommandSuspend"
+
+#: logsrvd/logsrvd.c:790 logsrvd/logsrvd_journal.c:302
+#: logsrvd/logsrvd_relay.c:654 logsrvd/sendlog.c:1207
+#: plugins/sudoers/log_client.c:1593
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "nie udało się rozpakować %s, rozmiar %zu"
+
+#: logsrvd/logsrvd.c:835 logsrvd/logsrvd_journal.c:376
+#: logsrvd/logsrvd_relay.c:678
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "nieoczekiwana wartość type_case %d w %s z %s"
+
+#: logsrvd/logsrvd.c:837
+msgid "unrecognized ClientMessage type"
+msgstr "nie rozpoznany typ ClientMessage"
+
+#: logsrvd/logsrvd.c:927
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "przekroczony limit czasu przy pisaniu do klienta %s"
+
+#: logsrvd/logsrvd.c:932 logsrvd/logsrvd_relay.c:919 logsrvd/sendlog.c:1413
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr "brak bufora zapisu dla klienta %s"
+
+#: logsrvd/logsrvd.c:1027
+#, c-format
+msgid "timed out reading from client %s"
+msgstr "przekroczony limit czasu przy czytaniu od klienta %s"
+
+#: logsrvd/logsrvd.c:1068 logsrvd/logsrvd_relay.c:782
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr "EOF od %s bez właściwego zakończenia połączenia TLS"
+
+#: logsrvd/logsrvd.c:1112 logsrvd/logsrvd_relay.c:205 logsrvd/sendlog.c:336
+#: plugins/sudoers/log_client.c:723
+#, c-format
+msgid "client message too large: %zu"
+msgstr "komunikat klienta zbyt duży %zu"
+
+#: logsrvd/logsrvd.c:1113 logsrvd/logsrvd_journal.c:259
+#: logsrvd/logsrvd_journal.c:260
+msgid "client message too large"
+msgstr "komunikat klienta zbyt duży"
+
+#: logsrvd/logsrvd.c:1131 logsrvd/logsrvd.c:1132
+msgid "invalid ClientMessage"
+msgstr "błędny ClientMessage"
+
+#: logsrvd/logsrvd.c:1432
+msgid "unable to get remote IP addr"
+msgstr "nie udało się uzyskać zdalnego adresu IP"
+
+#: logsrvd/logsrvd.c:1463 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:281
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "Nie udało się dołączyć danych użytkownika do obiektu SSL: %s"
+
+#: logsrvd/logsrvd.c:1646 logsrvd/logsrvd.c:2007
+msgid "unable to setup listen socket"
+msgstr "nie udało się ustanowić gniazda nasłuchującego"
+
+#: logsrvd/logsrvd.c:1766
+#, c-format
+msgid "unexpected signal %d"
+msgstr "nieoczekiwany sygnał %d"
+
+#: logsrvd/logsrvd.c:1909
+msgid "sudo log server"
+msgstr "serwer logów sudo"
+
+#: logsrvd/logsrvd.c:1911 logsrvd/sendlog.c:126
+msgid "Options:"
+msgstr "Opcje:"
+
+#: logsrvd/logsrvd.c:1913
+msgid "path to configuration file"
+msgstr "ścieżka do pliku konfiguracyjnego"
+
+#: logsrvd/logsrvd.c:1915 logsrvd/sendlog.c:128
+msgid "display help message and exit"
+msgstr "wyświetlenie pomocy i zakończenie"
+
+#: logsrvd/logsrvd.c:1917
+msgid "do not fork, run in the foreground"
+msgstr "bez wykonywania fork, działanie na pierwszym planie"
+
+#: logsrvd/logsrvd.c:1919
+msgid "percent chance connections will drop"
+msgstr "procentowe prawdopodobieństwo odrzucenia połączenia"
+
+#: logsrvd/logsrvd.c:1921 logsrvd/sendlog.c:158
+msgid "display version information and exit"
+msgstr "wyświetlenie informacji o wersji i zakończenie"
+
+#: logsrvd/logsrvd.c:1971 logsrvd/sendlog.c:1722
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "Wymagany Protobuf-C w wersji 1.3 lub wyższej"
+
+#: logsrvd/logsrvd.c:1987
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "błędna wartość losowego gubienia: %s"
+
+#: logsrvd/logsrvd.c:1990 logsrvd/sendlog.c:1776
+#: plugins/sudoers/cvtsudoers.c:250 plugins/sudoers/sudoreplay.c:294
+#: plugins/sudoers/visudo.c:181
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s wersja %s\n"
+
+#: logsrvd/logsrvd_conf.c:422 plugins/sudoers/check.c:69
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/sudoers.c:419 plugins/sudoers/sudoers.c:929
+#: plugins/sudoers/sudoers.c:1034 plugins/sudoers/sudoers.c:1424
+#: plugins/sudoers/testsudoers.c:169 plugins/sudoers/testsudoers.c:285
+#: plugins/sudoers/testsudoers.c:459
+#, c-format
+msgid "unknown user %s"
+msgstr "nieznany użytkownik %s"
+
+#: logsrvd/logsrvd_conf.c:439 plugins/sudoers/iolog.c:148
+#: plugins/sudoers/sudoers.c:425 plugins/sudoers/sudoers.c:1458
+#: plugins/sudoers/testsudoers.c:483
+#, c-format
+msgid "unknown group %s"
+msgstr "nieznana grupa %s"
+
+#: logsrvd/logsrvd_conf.c:457
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr "nie udało się przeanalizować uprawnień iologu %s"
+
+#: logsrvd/logsrvd_conf.c:474 logsrvd/logsrvd_conf.c:1243
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "błędna wartość %s: %s"
+
+#: logsrvd/logsrvd_conf.c:527
+msgid "TLS not supported"
+msgstr "TLS nie jest obsługiwany"
+
+#: logsrvd/logsrvd_conf.c:549
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:622 logsrvd/logsrvd_conf.c:1032
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s: nie jest pełną ścieżką"
+
+#: logsrvd/logsrvd_conf.c:951 logsrvd/logsrvd_conf.c:967
+#: logsrvd/logsrvd_conf.c:1676
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "nieznana wartość facility sysloga %s"
+
+#: logsrvd/logsrvd_conf.c:983 logsrvd/logsrvd_conf.c:999
+#: logsrvd/logsrvd_conf.c:1015 logsrvd/logsrvd_conf.c:1680
+#: logsrvd/logsrvd_conf.c:1684 logsrvd/logsrvd_conf.c:1688
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "nieznany priorytet sysloga %s"
+
+#: logsrvd/logsrvd_conf.c:1197
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d niedopasowany '[': %s"
+
+#: logsrvd/logsrvd_conf.c:1203
+#, c-format
+msgid "%s:%d garbage after ']': %s"
+msgstr "%s:%d śmieci po ']': %s"
+
+#: logsrvd/logsrvd_conf.c:1215
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s: %d błędna sekcja konfiguracji: %s"
+
+#: logsrvd/logsrvd_conf.c:1223
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d błędna linia konfiguracji: %s"
+
+#: logsrvd/logsrvd_conf.c:1229
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d oczekiwano nazwy sekcji: %s"
+
+#: logsrvd/logsrvd_conf.c:1251
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] niedozwolony klucz: %s"
+
+#: logsrvd/logsrvd_conf.c:1281 plugins/sudoers/cvtsudoers.c:273
+#: plugins/sudoers/logging.c:1076
+#, c-format
+msgid "unable to open log file %s"
+msgstr "nie udało się otworzyć pliku logu %s"
+
+#: logsrvd/logsrvd_conf.c:1763
+msgid "unable to initialize server TLS context"
+msgstr "nie udało się zainicjować kontekstu serwera TLS"
+
+#: logsrvd/logsrvd_conf.c:1783
+msgid "unable to initialize relay TLS context"
+msgstr "nie udało się zainicjować kontekstu przekaźnika TLS"
+
+#: logsrvd/logsrvd_journal.c:149 logsrvd/logsrvd_journal.c:430
+#: logsrvd/logsrvd_journal.c:435
+msgid "unable to create journal file"
+msgstr "nie udało się utworzuć pliku kroniki"
+
+#: logsrvd/logsrvd_journal.c:153 logsrvd/logsrvd_queue.c:109
+#: plugins/sudoers/visudo.c:1046
+#, c-format
+msgid "unable to lock %s"
+msgstr "nie udało się zablokować %s"
+
+#: logsrvd/logsrvd_journal.c:156
+msgid "unable to lock journal file"
+msgstr "nie udało się zablokować pliku kroniki"
+
+#: logsrvd/logsrvd_journal.c:164
+msgid "unable to open journal file"
+msgstr "nie udało się otworzyć pliku kroniki"
+
+#: logsrvd/logsrvd_journal.c:185 logsrvd/logsrvd_journal.c:466
+#: logsrvd/logsrvd_journal.c:471
+msgid "unable to write journal file"
+msgstr "nie udało się zapisać pliku kroniki"
+
+#: logsrvd/logsrvd_journal.c:193 logsrvd/logsrvd_journal.c:200
+msgid "unable to rename journal file"
+msgstr "nie udało się zmienić nazwy pliku kroniki"
+
+#: logsrvd/logsrvd_journal.c:247 logsrvd/logsrvd_journal.c:248
+#: logsrvd/logsrvd_journal.c:288 logsrvd/logsrvd_journal.c:289
+msgid "unexpected EOF reading journal file"
+msgstr "nieoczekiwany koniec pliku podczas odczytu pliku kroniki"
+
+#: logsrvd/logsrvd_journal.c:251 logsrvd/logsrvd_journal.c:252
+#: logsrvd/logsrvd_journal.c:292 logsrvd/logsrvd_journal.c:293
+msgid "error reading journal file"
+msgstr "błąd podczas odczytu pliku kroniki"
+
+#: logsrvd/logsrvd_journal.c:304 logsrvd/logsrvd_journal.c:390
+msgid "invalid journal file, unable to restart"
+msgstr "błędny plik kroniki, nie udało się zrestartować"
+
+#: logsrvd/logsrvd_journal.c:449
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "nie udało się przewinąć do [%lld, %ld] w pliku kroniki %s"
+
+#: logsrvd/logsrvd_local.c:166
+#, c-format
+msgid "unexpected value_case %d in %s from %s"
+msgstr "nieoczekiwana wartość value_case %d w %s z %s"
+
+#: logsrvd/logsrvd_local.c:194
+msgid "error parsing AcceptMessage"
+msgstr "błąd analizy AcceptMessage"
+
+#: logsrvd/logsrvd_local.c:205
+msgid "error creating I/O log"
+msgstr "błąd tworzenia logu we/wy"
+
+#: logsrvd/logsrvd_local.c:228
+msgid "error logging accept event"
+msgstr "błąd logowania zdarzenia akceptacji"
+
+#: logsrvd/logsrvd_local.c:267
+msgid "error parsing RejectMessage"
+msgstr "błąd analizy RejectMessage"
+
+#: logsrvd/logsrvd_local.c:291
+msgid "error logging reject event"
+msgstr "błąd logowania zdarzenia odrzucenia"
+
+#: logsrvd/logsrvd_local.c:427 logsrvd/logsrvd_local.c:437
+msgid "error logging exit event"
+msgstr "błąd logowania zdarzenia wyjścia"
+
+#: logsrvd/logsrvd_local.c:494 logsrvd/logsrvd_local.c:495
+msgid "log is already complete, cannot be restarted"
+msgstr "log jest już kompletny, nie może być wznowiony"
+
+#: logsrvd/logsrvd_local.c:525
+msgid "unable to restart log"
+msgstr "nie udało się wznownić logu"
+
+#: logsrvd/logsrvd_local.c:541
+msgid "error parsing AlertMessage"
+msgstr "błąd analizy AlertMessage"
+
+#: logsrvd/logsrvd_local.c:551
+msgid "error logging alert event"
+msgstr "błąd logowania zdarzenia alarmu"
+
+#: logsrvd/logsrvd_local.c:587 logsrvd/logsrvd_local.c:650
+#: logsrvd/logsrvd_local.c:685
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr "nie udało się sformatować bufora czasu, długość %d"
+
+#: logsrvd/logsrvd_local.c:601 logsrvd/logsrvd_local.c:609
+#: logsrvd/logsrvd_local.c:657 logsrvd/logsrvd_local.c:692
+#: plugins/sudoers/sudoreplay.c:344 toke.l:981 toke.l:984
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: logsrvd/logsrvd_local.c:620
+msgid "randomly dropping connection"
+msgstr "losowe odrzucanie połączenia"
+
+#: logsrvd/logsrvd_local.c:632
+msgid "error writing IoBuffer"
+msgstr "błąd zapisu IoBuffer"
+
+#: logsrvd/logsrvd_local.c:667
+msgid "error writing ChangeWindowSize"
+msgstr "błąd zapisu ChangeWindowSize"
+
+#: logsrvd/logsrvd_local.c:702
+msgid "error writing CommandSuspend"
+msgstr "błąd zapisu CommandSuspend"
+
+#: logsrvd/logsrvd_relay.c:437
+msgid "TLS handshake with relay host failed"
+msgstr "przywitanie TLS z hostem przekaźnika nie powiodło się"
+
+#: logsrvd/logsrvd_relay.c:465
+msgid "unable to connect to relay host"
+msgstr "nie udało się połączyć z hostem przekaźnika"
+
+#: logsrvd/logsrvd_relay.c:520
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s: błędne ServerHello, brak server_id"
+
+#: logsrvd/logsrvd_relay.c:522 logsrvd/sendlog.c:1111
+#: plugins/sudoers/log_client.c:1479
+msgid "invalid ServerHello"
+msgstr "błędne ServerHello"
+
+#: logsrvd/logsrvd_relay.c:681
+msgid "unrecognized ServerMessage type"
+msgstr "nie rozpoznany typ ServerMessage"
+
+#: logsrvd/logsrvd_relay.c:710
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr "przekroczony limit czasu przy czytaniu z przekaźnika %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:712
+msgid "timeout reading from relay"
+msgstr "przekroczony limit czasu przy czytaniu z przekaźnika"
+
+#: logsrvd/logsrvd_relay.c:767
+msgid "relay host name does not match certificate"
+msgstr "nazwa hosta przekaźnika nie pasuje do certyfikatu"
+
+#: logsrvd/logsrvd_relay.c:773 logsrvd/logsrvd_relay.c:787
+#: logsrvd/logsrvd_relay.c:794
+msgid "error reading from relay"
+msgstr "błąd podczas odczytu z przekaźnika"
+
+#: logsrvd/logsrvd_relay.c:815
+msgid "unable to read from relay"
+msgstr "nie udał się odczyt z przekaźnika"
+
+#: logsrvd/logsrvd_relay.c:830 logsrvd/logsrvd_relay.c:949
+msgid "relay server closed connection"
+msgstr "serwer przekaźnika zamknął połączenie"
+
+#: logsrvd/logsrvd_relay.c:848
+msgid "server message too large"
+msgstr "komunikat serwera zbyt duży"
+
+#: logsrvd/logsrvd_relay.c:912
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr "przekroczony limit czasu przy pisaniu do przekaźnika %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:914
+msgid "timeout writing to relay"
+msgstr "przekroczony limit czasu przy pisaniu do przekaźnika"
+
+#: logsrvd/logsrvd_relay.c:968 logsrvd/logsrvd_relay.c:975
+#: logsrvd/logsrvd_relay.c:987
+msgid "error writing to relay"
+msgstr "błąd zapisu do przekaźnika"
+
+#: logsrvd/sendlog.c:124
+msgid "send sudo I/O log to remote server"
+msgstr "wysyłanie logu we/wy sudo na zdalny serwer"
+
+#: logsrvd/sendlog.c:130
+msgid "only send an accept event (no I/O)"
+msgstr "samo wysłanie zdarzenia akceptującego (bez we/wy)"
+
+#: logsrvd/sendlog.c:133
+msgid "certificate bundle file to verify server's cert against"
+msgstr "plik paczki certyfikatów do weryfikacji certyfikatu serwera"
+
+#: logsrvd/sendlog.c:135
+msgid "certificate file for TLS handshake"
+msgstr "plik certyfikatu do powitania TLS"
+
+#: logsrvd/sendlog.c:138
+msgid "host to send logs to"
+msgstr "host do wysyłania logów"
+
+#: logsrvd/sendlog.c:140
+msgid "remote ID of I/O log to be resumed"
+msgstr "zdalny ID logu we/wy do wznowienia"
+
+#: logsrvd/sendlog.c:143
+msgid "private key file"
+msgstr "plik klucza prywatnego"
+
+#: logsrvd/sendlog.c:145
+msgid "do not verify server certificate"
+msgstr "bez weryfikacji certyfikatu serwera"
+
+#: logsrvd/sendlog.c:148
+msgid "port to use when connecting to host"
+msgstr "port do użycia przy łączeniu z hostem"
+
+#: logsrvd/sendlog.c:150
+msgid "restart previous I/O log transfer"
+msgstr "wznowienie poprzedniego transferu logu we/wy"
+
+#: logsrvd/sendlog.c:152
+msgid "reject the command with the given reason"
+msgstr "odrzucenie polecenia z podanym powodem"
+
+#: logsrvd/sendlog.c:154
+msgid "stop transfer after reaching this time"
+msgstr "zakończenie przesyłania po osiągnięciu tego czasu"
+
+#: logsrvd/sendlog.c:156
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "test serwera audytu przez wysłanie wybranego logu we/wy N razy równolegle"
+
+#: logsrvd/sendlog.c:181 plugins/sudoers/log_client.c:453
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "nie udało się wyszukać %s:%s: %s"
+
+#: logsrvd/sendlog.c:219
+msgid "unable to get server IP addr"
+msgstr "nie udało się uzyskać adresu IP serwera"
+
+#: logsrvd/sendlog.c:314 plugins/sudoers/sudoreplay.c:868
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "nie udało się odczytać %s/%s: %s"
+
+#: logsrvd/sendlog.c:1035 plugins/sudoers/iolog.c:959
+#: plugins/sudoers/iolog.c:1034
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "nieoczekiwane zdarzenie we/wy %d"
+
+#: logsrvd/sendlog.c:1088 logsrvd/sendlog.c:1105 logsrvd/sendlog.c:1139
+#: plugins/sudoers/log_client.c:1129 plugins/sudoers/log_client.c:1405
+#: plugins/sudoers/log_client.c:1473 plugins/sudoers/log_client.c:1512
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: nieoczekiwany stan %d"
+
+#: logsrvd/sendlog.c:1175 plugins/sudoers/log_client.c:1561
+#, c-format
+msgid "error message received from server: %s"
+msgstr "odebrano od serwera komunikat błędu: %s"
+
+#: logsrvd/sendlog.c:1188 plugins/sudoers/log_client.c:1574
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "odebrano od serwera komunikat zerwania: %s"
+
+#: logsrvd/sendlog.c:1247 plugins/sudoers/log_client.c:1624
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s: nieoczekiwana wartość type_case %d"
+
+#: logsrvd/sendlog.c:1276
+msgid "timeout reading from server"
+msgstr "przekroczony limit czasu przy czytaniu z serwera"
+
+#: logsrvd/sendlog.c:1327 plugins/sudoers/log_client.c:1747
+msgid "host name does not match certificate"
+msgstr "nazwa hosta nie pasuje do certyfikatu"
+
+#: logsrvd/sendlog.c:1361
+msgid "premature EOF"
+msgstr "przedwczesny EOF"
+
+#: logsrvd/sendlog.c:1374 plugins/sudoers/log_client.c:1795
+#, c-format
+msgid "server message too large: %u"
+msgstr "komunikat serwera zbyt duży: %u"
+
+#: logsrvd/sendlog.c:1430
+msgid "timeout writing to server"
+msgstr "przekroczony limit czasu przy pisaniu do serwera"
+
+#: logsrvd/sendlog.c:1800
+msgid "both restart point and iolog ID must be specified"
+msgstr "muszą być podane jednocześnie punkt wznowienia i ID iolog"
+
+#: logsrvd/sendlog.c:1804
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "nie można ustawić punktu restartu, jeśli żadne we/wy nie jest wysyłane"
+
+#: logsrvd/sendlog.c:1880
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "zakończono przedwcześnie ze stanem %d"
+
+#: logsrvd/sendlog.c:1881
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "miniony czas wysłany do serwera [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1883
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "odebrano od serwera punkt zatwierdzenia [%lld, %ld]"
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:315
+msgid "TLS handshake timeout occurred"
+msgstr "przekroczony limit czasu powitania TLS"
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:337 plugins/sudoers/log_client.c:353
+msgid "unable to set event"
+msgstr "nie udało się ustawić zdarzenia"
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "Połączenie TLS nie powiodło się: %s"
+
+#: logsrvd/tls_client.c:196
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "nie udało się przydzielić obiektu SSL: %s"
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "Nie udało się dołączyć gniazda do obiektu SSL: %s"
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr "nie udało się zainicjować kontekstu TLS"
+
+#: logsrvd/tls_init.c:138 logsrvd/tls_init.c:146
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "nie udało się ustawić szyfrowania TLS 1.2 na %s: %s"
+
+#: logsrvd/tls_init.c:166 logsrvd/tls_init.c:174
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "nie udało się ustawić szyfrowania TLS 1.3 na %s: %s"
+
+#: logsrvd/tls_init.c:206 logsrvd/tls_init.c:227
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "nie udało się ustawić parametrów Diffie-Hellmana: %s"
+
+#: logsrvd/tls_init.c:283
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "nie udało się utworzyć kontekstu TLS: %s"
+
+#: logsrvd/tls_init.c:290
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "nie udało się ustawić minimalnej wersji protokołu na TLS 1.2: %s"
+
+#: plugins/sudoers/audit.c:272 plugins/sudoers/audit.c:452
+#: plugins/sudoers/log_client.c:962 plugins/sudoers/log_client.c:1011
+#: plugins/sudoers/log_client.c:1060 plugins/sudoers/log_client.c:1185
+#: plugins/sudoers/logging.c:614 plugins/sudoers/logging.c:732
+#: plugins/sudoers/logging.c:859 plugins/sudoers/logging.c:1031
+#: plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr "nie udało się pobrać aktualnego czasu"
+
+#: plugins/sudoers/auth/aix_auth.c:282
+#, c-format
+msgid "unable to change password for %s"
+msgstr "nie udało się zmienić hasła dla %s"
+
+#: plugins/sudoers/auth/bsdauth.c:78
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "nie udało się uzyskać klasy logowania dla użytkownika %s"
+
+#: plugins/sudoers/auth/bsdauth.c:85
+msgid "invalid authentication type"
+msgstr "błędny rodzaj uwierzytelnienia"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to begin BSD authentication"
+msgstr "nie udało się rozpocząć uwierzytelnienia BSD"
+
+#: plugins/sudoers/auth/bsdauth.c:97
+msgid "unable to initialize BSD authentication"
+msgstr "nie udało się zainicjować uwierzytelnienia BSD"
+
+#: plugins/sudoers/auth/bsdauth.c:191
+msgid "your account has expired"
+msgstr "konto wygasło"
+
+#: plugins/sudoers/auth/bsdauth.c:193
+msgid "approval failed"
+msgstr "zezwolenie nie powiodło się"
+
+#: plugins/sudoers/auth/fwtk.c:62
+msgid "unable to read fwtk config"
+msgstr "nie udało się odczytać konfiguracji fwtk"
+
+#: plugins/sudoers/auth/fwtk.c:67
+msgid "unable to connect to authentication server"
+msgstr "nie udało się połączyć z serwerem uwierzytelniającym"
+
+#: plugins/sudoers/auth/fwtk.c:73 plugins/sudoers/auth/fwtk.c:99
+#: plugins/sudoers/auth/fwtk.c:131
+msgid "lost connection to authentication server"
+msgstr "utracono połączenie z serwerem uwierzytelniającym"
+
+#: plugins/sudoers/auth/fwtk.c:77
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"błąd serwera uwierzytelniającego:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:116
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: nie udało się przekształcić nazwy principal do łańcucha ('%s'): %s"
+
+#: plugins/sudoers/auth/kerb5.c:166
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: nie udało się przeanalizować '%s': %s"
+
+#: plugins/sudoers/auth/kerb5.c:175
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: nie udało się rozwiązać pamięci podręcznej danych uwierzytelniających: %s"
+
+#: plugins/sudoers/auth/kerb5.c:226
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: nie udało się przydzielić opcji: %s"
+
+#: plugins/sudoers/auth/kerb5.c:241
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: nie udało się pobrać danych uwierzytelniających: %s"
+
+#: plugins/sudoers/auth/kerb5.c:254
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: nie udało się zainicjować pamięci podręcznej danych uwierzytelniających: %s"
+
+#: plugins/sudoers/auth/kerb5.c:257
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: nie udało się zapisać danych uwierzytelniających w pamięci podręcznej: %s"
+
+#: plugins/sudoers/auth/kerb5.c:322
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: nie udało się pobrać nazwy principal dla hosta: %s"
+
+#: plugins/sudoers/auth/kerb5.c:336
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: Nie można zweryfikować TGT! Możliwy atak!: %s"
+
+#: plugins/sudoers/auth/pam.c:233
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "nie udało się zainicjować PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:349
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Błąd uwierzytelniania PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:369
+msgid "account validation failure, is your account locked?"
+msgstr "błąd kontroli poprawności konta - konto zablokowane?"
+
+#: plugins/sudoers/auth/pam.c:380
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Konto lub hasło wygasło, należy ustawić ponownie hasło i spróbować jeszcze raz"
+
+#: plugins/sudoers/auth/pam.c:387
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "nie udało się zmienić przedawnionego hasła: %s"
+
+#: plugins/sudoers/auth/pam.c:398
+msgid "Password expired, contact your system administrator"
+msgstr "Hasło wygasło, proszę skontaktować się z administratorem systemu"
+
+#: plugins/sudoers/auth/pam.c:403
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Konto wygasło lub w konfiguracji PAM brak sekcji \"account\" dla sudo, proszę skontaktować się z administratorem systemu"
+
+#: plugins/sudoers/auth/pam.c:411 plugins/sudoers/auth/pam.c:416
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "Błąd zarządzania kontem PAM: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:100 plugins/sudoers/visudo.c:266
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "nie istniejesz w bazie danych %s"
+
+#: plugins/sudoers/auth/securid5.c:76
+msgid "failed to initialise the ACE API library"
+msgstr "nie udało się zainicjować biblioteki ACE API"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "unable to contact the SecurID server"
+msgstr "nie udało się połączyć z serwerem SecurID"
+
+#: plugins/sudoers/auth/securid5.c:117
+msgid "User ID locked for SecurID Authentication"
+msgstr "ID użytkownika zablokowany dla uwierzytelnienia SecurID"
+
+#: plugins/sudoers/auth/securid5.c:121 plugins/sudoers/auth/securid5.c:174
+msgid "invalid username length for SecurID"
+msgstr "błędna długość nazwy użytkownika dla SecurID"
+
+#: plugins/sudoers/auth/securid5.c:125 plugins/sudoers/auth/securid5.c:179
+msgid "invalid Authentication Handle for SecurID"
+msgstr "błędny uchwyt uwierzytelnienia dla SecurID"
+
+#: plugins/sudoers/auth/securid5.c:129
+msgid "SecurID communication failed"
+msgstr "błąd komunikacji SecurID"
+
+#: plugins/sudoers/auth/securid5.c:133 plugins/sudoers/auth/securid5.c:222
+msgid "unknown SecurID error"
+msgstr "nieznany błąd SecurID"
+
+#: plugins/sudoers/auth/securid5.c:169
+msgid "invalid passcode length for SecurID"
+msgstr "błędna długość hasła dla SecurID"
+
+#: plugins/sudoers/auth/sia.c:72 plugins/sudoers/auth/sia.c:130
+msgid "unable to initialize SIA session"
+msgstr "nie udało się zainicjować sesji SIA"
+
+#: plugins/sudoers/auth/sudo_auth.c:141
+msgid "invalid authentication methods"
+msgstr "błędne metody uwierzytelniania"
+
+#: plugins/sudoers/auth/sudo_auth.c:143
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "W sudo wkompilowano błędne metody uwierzytelniania! Nie można mieszać samodzielnych i niesamodzielnych sposobów uwierzytelniania."
+
+#: plugins/sudoers/auth/sudo_auth.c:296 plugins/sudoers/auth/sudo_auth.c:359
+msgid "no authentication methods"
+msgstr "brak metod uwierzytelniania"
+
+#: plugins/sudoers/auth/sudo_auth.c:298
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "W sudo nie wkompilowano żadnych metod uwierzytelniania! Aby wyłączyć uwierzytelnianie, proszę użyć opcji konfiguracyjnej --disable-authentication."
+
+#: plugins/sudoers/auth/sudo_auth.c:361
+msgid "Unable to initialize authentication methods."
+msgstr "Nie udało się zainicjować metod uwierzytelniania."
+
+#: plugins/sudoers/auth/sudo_auth.c:551
+msgid "Authentication methods:"
+msgstr "Metody uwierzytelniania:"
+
+#: plugins/sudoers/bsm_audit.c:122 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "Nie udało się określić warunku audytowego"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:278
+msgid "unable to commit audit record"
+msgstr "nie udało się zatwierdzić rekordu audytowego"
+
+#: plugins/sudoers/check.c:63 plugins/sudoers/check.c:74
+#: plugins/sudoers/lookup.c:79 plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "nieznany uid %u"
+
+#: plugins/sudoers/check.c:277
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "błąd podczas czytania pliku instrukcji %s"
+
+#: plugins/sudoers/check.c:280
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "zignorowano plik instrukcji %s: nie jest zwykłym plikiem"
+
+#: plugins/sudoers/check.c:293
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Ufamy, że lokalny administrator udzielił odpowiedniego szkolenia.\n"
+"Zwykle sprowadza się ono do tych trzech rzeczy:\n"
+"\n"
+" 1) należy respektować prywatność innych,\n"
+" 2) należy myśleć przed pisaniem,\n"
+" 3) z dużą władzą wiąże się duża odpowiedzialność.\n"
+"\n"
+
+#: plugins/sudoers/check.c:301
+msgid ""
+"For security reasons, the password you type will not be visible.\n"
+"\n"
+msgstr ""
+"Ze względów bezpieczeństwa wpisywane hasło nie będzie widoczne.\n"
+"\n"
+
+#: plugins/sudoers/check_aliases.c:93
+#, c-format
+msgid "cycle in %s \"%s\""
+msgstr "cykl w %s \"%s\""
+
+#: plugins/sudoers/check_aliases.c:96
+#, c-format
+msgid "%s \"%s\" referenced but not defined"
+msgstr "%s \"%s\" użyty, ale nie zdefiniowany"
+
+#: plugins/sudoers/cvtsudoers.c:211
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "zwiększenie rangi: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:231
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "początkowa ranga: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:242
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "wyrównanie rangi: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:252 plugins/sudoers/visudo.c:183
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s, wersja gramatyki %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:282 plugins/sudoers/testsudoers.c:162
+#, c-format
+msgid "unsupported input format %s"
+msgstr "nieobsługiwany format wejścia %s"
+
+#: plugins/sudoers/cvtsudoers.c:300
+#, c-format
+msgid "unsupported output format %s"
+msgstr "nieobsługiwany format wyjścia %s"
+
+#: plugins/sudoers/cvtsudoers.c:392
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: pliki wejściowy i wyjściowy muszą być różne"
+
+#: plugins/sudoers/cvtsudoers.c:406 plugins/sudoers/sudoers.c:151
+#: plugins/sudoers/sudoers.c:209 plugins/sudoers/testsudoers.c:315
+#: plugins/sudoers/visudo.c:276 plugins/sudoers/visudo.c:666
+msgid "unable to initialize sudoers default values"
+msgstr "nie udało się zainicjować wartości domyślnych sudoers"
+
+#: plugins/sudoers/cvtsudoers.c:533 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:612
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s: nieznane słowo kluczowe %s"
+
+#: plugins/sudoers/cvtsudoers.c:658
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "błędny typ wartości domyślnej: %s"
+
+#: plugins/sudoers/cvtsudoers.c:681
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "błędny typ ograniczenia: %s"
+
+#: plugins/sudoers/cvtsudoers.c:722 plugins/sudoers/cvtsudoers.c:738
+#, c-format
+msgid "invalid filter: %s"
+msgstr "błędny filtr: %s"
+
+#: plugins/sudoers/cvtsudoers.c:783 plugins/sudoers/visudo.c:1000
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "nie udało się przeanalizować pliku %s, nieznany błąd"
+
+#: plugins/sudoers/cvtsudoers.c:1508 plugins/sudoers/sudoreplay.c:1143
+#: plugins/sudoers/timestamp.c:353 plugins/sudoers/timestamp.c:356
+#, c-format
+msgid "unable to write to %s"
+msgstr "nie udało się zapisać do %s"
+
+#: plugins/sudoers/cvtsudoers.c:1536
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s - konwersja między formatami pliku sudoers\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1538
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Opcje:\n"
+" -b. --base=dn podstawowe DN do zapytań LDAP z sudo\n"
+" -c, --config=plik_konf ścieżka do pliku konfiguracyjnego\n"
+" -d, --defaults=typy konwersja Defaults tylko określonych typów\n"
+" -e, --expand-aliases rozwinięcie aliasów w trakcie konwersji\n"
+" -f, --output-format=format format wyjścia: JSON, LDIF lub sudoers\n"
+" -i, --input-format=format format wejścia: LDIF lub sudoers\n"
+" -I, --increment=liczba liczba, o jaką ma być zwiększane każde sudoOrder\n"
+" -h, --help wyświetlenie pomocy i zakończenie\n"
+" -m, --match=filtr konwersja tylko wpisów pasujących do filtra\n"
+" -M, --match-local filtr dopasowania używający baz passwd i group\n"
+" -o, --output=plik zapis skonwertowanego sudoers do pliku wyjciowego\n"
+" -O, --order-start=liczba początkowa wartość pierwszego sudoOrder\n"
+" -p, --prune-matches czyszczenie nie pasujących użytkowników, grup,\n"
+" hostów\n"
+" -P, --padding=num bazowe wyrównanie dla kroku sudoOrder\n"
+" -s, --suppress=sekcje pominięcie wyjścia z podanych sekcji\n"
+" -V, --version wyświetlenie informacji o wersji i zakończenie"
+
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:245 plugins/sudoers/cvtsudoers_ldif.c:252
+#: plugins/sudoers/cvtsudoers_ldif.c:594 plugins/sudoers/env.c:340
+#: plugins/sudoers/env.c:347 plugins/sudoers/env.c:458
+#: plugins/sudoers/ldap.c:511 plugins/sudoers/ldap.c:629
+#: plugins/sudoers/ldap.c:1003 plugins/sudoers/ldap_conf.c:219
+#: plugins/sudoers/ldap_conf.c:310 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:93 plugins/sudoers/logging.c:479
+#: plugins/sudoers/policy.c:828 plugins/sudoers/policy.c:840
+#: plugins/sudoers/prompt.c:169 plugins/sudoers/serialize_list.c:62
+#: plugins/sudoers/serialize_list.c:71 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/sudoreplay.c:1340 plugins/sudoers/sudoreplay.c:1346
+#: plugins/sudoers/sudoreplay.c:1352 plugins/sudoers/testsudoers.c:306
+#: plugins/sudoers/toke_util.c:217 toke.l:995 toke.l:1277
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "błąd wewnętrzny, przepełnienie %s"
+
+#: plugins/sudoers/cvtsudoers_csv.c:454 plugins/sudoers/cvtsudoers_csv.c:468
+#: plugins/sudoers/cvtsudoers_json.c:661 plugins/sudoers/cvtsudoers_json.c:676
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:362
+#: plugins/sudoers/ldap.c:495
+msgid "unable to get GMT time"
+msgstr "nie udało się pobrać czasu GMT"
+
+#: plugins/sudoers/cvtsudoers_csv.c:459 plugins/sudoers/cvtsudoers_csv.c:473
+#: plugins/sudoers/cvtsudoers_json.c:666 plugins/sudoers/cvtsudoers_json.c:681
+#: plugins/sudoers/cvtsudoers_ldif.c:354 plugins/sudoers/cvtsudoers_ldif.c:367
+#: plugins/sudoers/ldap.c:503
+msgid "unable to format timestamp"
+msgstr "nie udało się sformatować znacznika czasu"
+
+#: plugins/sudoers/cvtsudoers_json.c:481 plugins/sudoers/cvtsudoers_json.c:516
+#: plugins/sudoers/cvtsudoers_json.c:732
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: nieznany wpis domyślny \"%s\""
+
+#: plugins/sudoers/cvtsudoers_ldif.c:663
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "zbyt dużo wpisów sudoers, maksimum to %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:706
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "zmienna środowiskowa SUDOERS_BASE nie jest ustawiona i nie podano opcji -b."
+
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, c-format
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr "%s:%d:%d: konwersja listy hostów na ALL"
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr "nie udało się odnaleźć aliasu %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, c-format
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr "%s:%d:%d: zmiana nazwy aliasu %s na %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr "%s:%d:%d: usuwanie powtórzonego aliasu %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr "%s:%d:%d: konflikt z wpisem Defaults \"%s\" dla hosta w %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, c-format
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr "%s:%d:%d: uczynienie Defaults \"%s\" obowiązującym tylko dla hosta %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr "%s:%d:%d: nie udało się uczynić Defaults \"%s\" obowiązującym tylko dla hosta"
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr "%s:%d:%d: usuwanie Defaults \"%s\" nadpisanego przez kolejne wpisy"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1088
+#, c-format
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr "%s:%d:%d: łączenie userspec w %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1182
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr "%s:%d:%d: usuwanie userspec nadpisanego przez kolejne wpisy"
+
+#: plugins/sudoers/def_data.c:56
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Rodzaj komunikatu sysloga, jeśli syslog jest używany: %s"
+
+#: plugins/sudoers/def_data.c:60
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Priorytet komunikatu sysloga w przypadku udanego uwierzytelnienia: %s"
+
+#: plugins/sudoers/def_data.c:64
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Priorytet komunikatu sysloga w przypadku nieudanego uwierzytelnienia: %s"
+
+#: plugins/sudoers/def_data.c:68
+msgid "Put OTP prompt on its own line"
+msgstr "Umieszczenie zachęty OTP we własnej linii"
+
+#: plugins/sudoers/def_data.c:72
+msgid "Ignore '.' in $PATH"
+msgstr "Ignorowanie '.' w $PATH"
+
+#: plugins/sudoers/def_data.c:76
+msgid "Always send mail when sudo is run"
+msgstr "Wysyłanie listu zawsze przy uruchomieniu sudo"
+
+#: plugins/sudoers/def_data.c:80
+msgid "Send mail if user authentication fails"
+msgstr "Wysyłanie listu przy błędnym uwierzytelnieniu"
+
+#: plugins/sudoers/def_data.c:84
+msgid "Send mail if the user is not in sudoers"
+msgstr "Wysyłanie listu jeśli użytkownik nie jest w sudoers"
+
+#: plugins/sudoers/def_data.c:88
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Wysyłanie listu jeśli użytkownik nie jest w sudoers dla tego hosta"
+
+#: plugins/sudoers/def_data.c:92
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Wysyłanie listu jeśli użytkownik nie ma prawa do uruchomienia polecenia"
+
+#: plugins/sudoers/def_data.c:96
+msgid "Send mail if the user tries to run a command"
+msgstr "Wysyłanie listu jeśli użytkownik próbuje uruchomić polecenie"
+
+#: plugins/sudoers/def_data.c:100
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Użycie osobnego znacznika czasu dla każdej pary użytkownik/tty"
+
+#: plugins/sudoers/def_data.c:104
+msgid "Lecture user the first time they run sudo"
+msgstr "Poinstruowanie użytkownika przy pierwszym uruchomieniu sudo"
+
+#: plugins/sudoers/def_data.c:108
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Plik zawierający instrukcję do sudo: %s"
+
+#: plugins/sudoers/def_data.c:112
+msgid "Require users to authenticate by default"
+msgstr "Domyślne wymaganie uwierzytelnienia przez użytkowników"
+
+#: plugins/sudoers/def_data.c:116
+msgid "Root may run sudo"
+msgstr "Możliwość uruchamiania sudo przez roota"
+
+#: plugins/sudoers/def_data.c:120
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Logowanie nazwy hosta w pliku logu (niesyslogowym)"
+
+#: plugins/sudoers/def_data.c:124
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Logowanie roku w pliku logu (niesyslogowym)"
+
+#: plugins/sudoers/def_data.c:128
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Uruchomienie powłoki przy wywołaniu sudo bez argumentów"
+
+#: plugins/sudoers/def_data.c:132
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Ustawianie $HOME na katalog użytkownika docelowego przy uruchamianiu powłoki z -s"
+
+#: plugins/sudoers/def_data.c:136
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Ustawianie $HOME zawsze na katalog domowy użytkownika docelowego"
+
+#: plugins/sudoers/def_data.c:140
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Zezwolenie na zbieranie niektórych informacji do przydatnych komunikatów błędów"
+
+#: plugins/sudoers/def_data.c:144
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Wymaganie pełnych nazw hostów w pliku sudoers"
+
+#: plugins/sudoers/def_data.c:148
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Lżenie użytkownika po podaniu błędnego hasła"
+
+#: plugins/sudoers/def_data.c:152
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Możliwość uruchamiania sudo tylko z poziomu terminala"
+
+#: plugins/sudoers/def_data.c:156
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Honorowanie zmiennej środowiskowej EDITOR przez visudo"
+
+#: plugins/sudoers/def_data.c:160
+msgid "Prompt for root's password, not the users's"
+msgstr "Pytanie o hasło roota zamiast hasła użytkownika"
+
+#: plugins/sudoers/def_data.c:164
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Pytanie o hasło użytkownika runas_default zamiast uruchamiającego"
+
+#: plugins/sudoers/def_data.c:168
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Pytanie o hasło użytkownika docelowego zamiast uruchamiającego"
+
+#: plugins/sudoers/def_data.c:172
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Użycie ustawień domyślnych z klasy logowania użytkownika docelowego (jeśli są)"
+
+#: plugins/sudoers/def_data.c:176
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Ustawianie zmiennych środowiskowych LOGNAME i USER"
+
+#: plugins/sudoers/def_data.c:180
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Ustawianie na użytkownika docelowego tylko efektywnego uid-a, nie rzeczywistego uid-a"
+
+#: plugins/sudoers/def_data.c:184
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Pomijanie inicjalizacji wektora grup na grupy użytkownika docelowego"
+
+#: plugins/sudoers/def_data.c:188
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Długość, na której zawijać linie logu (0 bez zawijania): %u"
+
+#: plugins/sudoers/def_data.c:192
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Limit czasu znacznika uwierzytelniania (w minutach): %.1f"
+
+#: plugins/sudoers/def_data.c:196
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Limit czasu pytania o hasło (w minutach): %.1f"
+
+#: plugins/sudoers/def_data.c:200
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Liczba prób wpisania hasła: %u"
+
+#: plugins/sudoers/def_data.c:204
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Wartość umask lub 0777, aby użyć wartości użytkownika: 0%o"
+
+#: plugins/sudoers/def_data.c:208
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Ścieżka do pliku logu: %s"
+
+#: plugins/sudoers/def_data.c:212
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Ścieżka do programu mail: %s"
+
+#: plugins/sudoers/def_data.c:216
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Flagi dla programu mail: %s"
+
+#: plugins/sudoers/def_data.c:220
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Adres, na który mają być wysyłane listy: %s"
+
+#: plugins/sudoers/def_data.c:224
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Adres, z którego mają być wysyłane listy: %s"
+
+#: plugins/sudoers/def_data.c:228
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Temat wysyłanych listów: %s"
+
+#: plugins/sudoers/def_data.c:232
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Komunikat o błędnym haśle: %s"
+
+#: plugins/sudoers/def_data.c:236
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Ścieżka katalogu stanu instrukcji: %s"
+
+#: plugins/sudoers/def_data.c:240
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Ścieżka katalogu znaczników czasu uwierzytelniania: %s"
+
+#: plugins/sudoers/def_data.c:244
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Właściciel katalogu znaczników czasu uwierzytelniania: %s"
+
+#: plugins/sudoers/def_data.c:248
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Grupa, której użytkownicy są zwolnieni z wymagań dot. haseł i PATH: %s"
+
+#: plugins/sudoers/def_data.c:252
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Domyślne pytanie o hasło: %s"
+
+#: plugins/sudoers/def_data.c:256
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Czy passprompt ma być używane zamiast systemowego zapytania we wszystkich przypadkach"
+
+#: plugins/sudoers/def_data.c:260
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Domyślny użytkownik do uruchamiania poleceń: %s"
+
+#: plugins/sudoers/def_data.c:264
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Wartość do podstawienia za $PATH użytkownika: %s"
+
+#: plugins/sudoers/def_data.c:268
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Ścieżka do edytora, który ma być używany przez visudo: %s"
+
+#: plugins/sudoers/def_data.c:272
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Kiedy ma być wymagane hasło dla pseudopolecenia 'list': %s"
+
+#: plugins/sudoers/def_data.c:276
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Kiedy ma być wymagane hasło dla pseudopolecenia 'verify': %s"
+
+#: plugins/sudoers/def_data.c:280
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "Wczesne załadowanie biblioteki sudo_noexec, zastępującej funkcje exec"
+
+#: plugins/sudoers/def_data.c:284
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Jeśli istnieje katalog LDAP, czy ignorować lokalny plik sudoers"
+
+#: plugins/sudoers/def_data.c:288
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Deskryptory plików >= %d będą zamykane przed uruchomieniem polecenia"
+
+#: plugins/sudoers/def_data.c:292
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "Czy użytkownicy mogą zmieniać wartość \"closefrom\" opcją -C"
+
+#: plugins/sudoers/def_data.c:296
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Zezwolenie użytkownikom na ustawianie dowolnych zmiennych środowiskowych"
+
+#: plugins/sudoers/def_data.c:300
+msgid "Reset the environment to a default set of variables"
+msgstr "Wyczyszczenie środowiska do domyślnego zbioru zmiennych"
+
+#: plugins/sudoers/def_data.c:304
+msgid "Environment variables to check for safety:"
+msgstr "Zmienne środowiskowe do sprawdzania bezpieczeństwa:"
+
+#: plugins/sudoers/def_data.c:308
+msgid "Environment variables to remove:"
+msgstr "Zmienne środowiskowe do usunięcia:"
+
+#: plugins/sudoers/def_data.c:312
+msgid "Environment variables to preserve:"
+msgstr "Zmienne środowiskowe do zachowania:"
+
+#: plugins/sudoers/def_data.c:316
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "Rola SELinuksa do używania w nowym kontekście bezpieczeństwa: %s"
+
+#: plugins/sudoers/def_data.c:320
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "Typ SELinuksa do używania w nowym kontekście bezpieczeństwa: %s"
+
+#: plugins/sudoers/def_data.c:324
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Ścieżka do pliku środowiska specyficznego dla sudo: %s"
+
+#: plugins/sudoers/def_data.c:328
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Ścieżka do pliku ograniczonego środowiska specyficznego dla sudo: %s"
+
+#: plugins/sudoers/def_data.c:332
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Lokalizacja, jak ma być używana przy analizie pliku sudoers: %s"
+
+#: plugins/sudoers/def_data.c:336
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Zezwolenie sudo na pytanie o hasło nawet gdyby miało być widoczne"
+
+#: plugins/sudoers/def_data.c:340
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Uwidocznienie wprowadzania hasła przez użytkownika w miarę wpisywania"
+
+#: plugins/sudoers/def_data.c:344
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Użycie szybszych masek (glob) - mniej dokładnych, ale nie odwołujących się do systemu plików"
+
+#: plugins/sudoers/def_data.c:348
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "Wartość umask podana w sudoers ma zastąpić wartość użytkownika, nawet jeśli pozwala na więcej"
+
+#: plugins/sudoers/def_data.c:352
+msgid "Log user's input for the command being run"
+msgstr "Logowanie wejścia użytkownika dla uruchamianych poleceń"
+
+#: plugins/sudoers/def_data.c:356
+msgid "Log the command's standard input if not connected to a terminal"
+msgstr "Logowanie standardowego wejścia polecenia, jeśli nie jest podłączone do terminala"
+
+#: plugins/sudoers/def_data.c:360
+msgid "Log the user's terminal input for the command being run"
+msgstr "Logowanie wejścia terminala użytkownika dla uruchamianych poleceń"
+
+#: plugins/sudoers/def_data.c:364
+msgid "Log the output of the command being run"
+msgstr "Logowanie wyjścia z uruchamianych poleceń"
+
+#: plugins/sudoers/def_data.c:368
+msgid "Log the command's standard output if not connected to a terminal"
+msgstr "Logowanie standardowego wyjścia polecenia, jeśli nie jest podłączone do terminala"
+
+#: plugins/sudoers/def_data.c:372
+msgid "Log the command's standard error if not connected to a terminal"
+msgstr "Logowanie standardowego wyjścia błędów polecenia, jeśli nie jest podłączone do terminala"
+
+#: plugins/sudoers/def_data.c:376
+msgid "Log the terminal output of the command being run"
+msgstr "Logowanie wyjścia terminala z uruchamianych poleceń"
+
+#: plugins/sudoers/def_data.c:380
+msgid "Compress I/O logs using zlib"
+msgstr "Kompresja logów we/wy przy użyciu zliba"
+
+#: plugins/sudoers/def_data.c:384
+msgid "Always run commands in a pseudo-tty"
+msgstr "Uruchamianie poleceń zawsze na pseudoterminalu"
+
+#: plugins/sudoers/def_data.c:388
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Wtyczka do obsługi grup nieuniksowych: %s"
+
+#: plugins/sudoers/def_data.c:392
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Katalog do zapisu logów wejścia/wyjścia: %s"
+
+#: plugins/sudoers/def_data.c:396
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Plik do zapisu logu wejścia/wyjścia: %s"
+
+#: plugins/sudoers/def_data.c:400
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Dodawanie wpisu do pliku utmp/utmpx przy przydzielaniu pty"
+
+#: plugins/sudoers/def_data.c:404
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Ustawianie użytkownika w utmp jako docelowego, nie wywołującego"
+
+#: plugins/sudoers/def_data.c:408
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Zbiór dozwolonych uprawnień: %s"
+
+#: plugins/sudoers/def_data.c:412
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Zbiór ograniczonych uprawnień: %s"
+
+#: plugins/sudoers/def_data.c:416
+msgid "Run commands on a pty in the background"
+msgstr "Uruchomienie poleceń na pseudoterminalu w tle"
+
+#: plugins/sudoers/def_data.c:420
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "Nazwa usługi PAM do użycia: %s"
+
+#: plugins/sudoers/def_data.c:424
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "Nazwa usługi PAM do użycia dla powłok logowania: %s"
+
+#: plugins/sudoers/def_data.c:428
+#, c-format
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr "Nazwa usługi PAM do użycia, kiedy sudo jest uruchomione z opcją -A: %s"
+
+#: plugins/sudoers/def_data.c:432
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Próba ustanowienia danych uwierzytelniających PAM dla użytkownika docelowego"
+
+#: plugins/sudoers/def_data.c:436
+msgid "Create a new PAM session for the command to run in"
+msgstr "Utworzenie nowej sesji PAM dla uruchamianego polecenia"
+
+#: plugins/sudoers/def_data.c:440
+msgid "Perform PAM account validation management"
+msgstr "Wykonanie zarządzania poprawnością konta PAM"
+
+#: plugins/sudoers/def_data.c:444
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "Maksymalny numer sekwencji logu we/wy: %s"
+
+#: plugins/sudoers/def_data.c:448
+msgid "Enable sudoers netgroup support"
+msgstr "Włączenie obsługi grup sieciowych w sudoers"
+
+#: plugins/sudoers/def_data.c:452
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Sprawdzanie katalogów nadrzędnych pod kątem możliwości zapisu przy edycji plików programem sudoedit"
+
+#: plugins/sudoers/def_data.c:456
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Podążanie za dowiązaniami symbolicznymi przy edycji programem sudoedit"
+
+#: plugins/sudoers/def_data.c:460
+msgid "Query the group plugin for unknown system groups"
+msgstr "Odpytanie wtyczki group pod kątem nieznanych grup systemowych"
+
+#: plugins/sudoers/def_data.c:464
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Dopasowanie grup sieciowych w oparciu o całą krotkę: użytkownik, host i domena"
+
+#: plugins/sudoers/def_data.c:468
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Zezwolenie na uruchamianie poleceń nawet jeśli sudo nie może pisać do logu audytowego"
+
+#: plugins/sudoers/def_data.c:472
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Zezwolenie na uruchamianie poleceń nawet jeśli sudo nie może pisać do logu we/wy"
+
+#: plugins/sudoers/def_data.c:476
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Zezwolenie na uruchamianie poleceń nawet jeśli sudo nie może pisać do pliku logu"
+
+#: plugins/sudoers/def_data.c:480
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Rozwiązanie grup z sudoers i dopasowywanie po ID grupy zamiast nazwy"
+
+#: plugins/sudoers/def_data.c:484
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Wpisy logu większe niż ta wartość będą dzielone na wiele wiadomości sysloga: %u"
+
+#: plugins/sudoers/def_data.c:488
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Użytkownik, który będzie właścicielem plików logu we/wy: %s"
+
+#: plugins/sudoers/def_data.c:492
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Grupa, która będzie właścicielem plików logu we/wy: %s"
+
+#: plugins/sudoers/def_data.c:496
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Uprawnienia dla plików logu we/wy: 0%o"
+
+#: plugins/sudoers/def_data.c:500
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Uruchomienie poleceń poprzez deskryptor pliku zamiast ścieżki: %s"
+
+#: plugins/sudoers/def_data.c:504
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Ignorowanie nieznanych wpisów Defaults w sudoers zamiast ostrzeżenia"
+
+#: plugins/sudoers/def_data.c:508
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Czas w sekundach, po którym polecenie będzie kończone: %u"
+
+#: plugins/sudoers/def_data.c:512
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Zezwolenie użytkownikowi na określenie limitu czasu z linii poleceń"
+
+#: plugins/sudoers/def_data.c:516
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Natychmiastowy zrzut danych logu we/wy na dysk zamiast buforowania"
+
+#: plugins/sudoers/def_data.c:520
+msgid "Include the process ID when logging via syslog"
+msgstr "Dołączanie identyfikatora procesu przy logowaniu przez syslog"
+
+#: plugins/sudoers/def_data.c:524
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Rodzaj rekordu znacznika czasu uwierzytelniania: %s"
+
+#: plugins/sudoers/def_data.c:528
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Komunikat błędu uwierzytelnienia: %s"
+
+#: plugins/sudoers/def_data.c:532
+msgid "Ignore case when matching user names"
+msgstr "Ignorowanie wielkości liter przy dopasowywaniu nazw użytkownika"
+
+#: plugins/sudoers/def_data.c:536
+msgid "Ignore case when matching group names"
+msgstr "Ignorowanie wielkości liter przy dopasowywaniu nazw grup"
+
+#: plugins/sudoers/def_data.c:540
+msgid "Log when a command is allowed by sudoers"
+msgstr "Logowanie kiedy polecenie jest dozwolone przez sudoers"
+
+#: plugins/sudoers/def_data.c:544
+msgid "Log when a command is denied by sudoers"
+msgstr "Logowanie kiedy polecenie jest zabronione przez sudoers"
+
+#: plugins/sudoers/def_data.c:548
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "Serwer(y) logów sudo do połączenia, z opcjonalnym portem"
+
+#: plugins/sudoers/def_data.c:552
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Limit czasu serwera logów sudo w sekundach: %u"
+
+#: plugins/sudoers/def_data.c:556
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "Włączenie opcji gniazda SO_KEEPALIVE na gnieździe połączonym z serwerem logów"
+
+#: plugins/sudoers/def_data.c:560
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "Ścieżka do pliku paczki CA serwera audytu: %s"
+
+#: plugins/sudoers/def_data.c:564
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "Ścieżka do pliku certyfikatu sudoers: %s"
+
+#: plugins/sudoers/def_data.c:568
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "Ścieżka do pliku klucza prywatnego sudoers: %s"
+
+#: plugins/sudoers/def_data.c:572
+msgid "Verify that the log server's certificate is valid"
+msgstr "Sprawdzenie poprawności certyfikatu serwera logów"
+
+#: plugins/sudoers/def_data.c:576
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "Zezwolenie na użycie nieznanego ID użytkownika i/lub grupy runas"
+
+#: plugins/sudoers/def_data.c:580
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "Zezwolenie na uruchamianie poleceń tylko jako użytkownik z prawidłową powłoką"
+
+#: plugins/sudoers/def_data.c:584
+msgid "Set the pam remote user to the user running sudo"
+msgstr "Ustawienie użytkownika zdalnego PAM na użytkownika uruchamiającego sudo"
+
+#: plugins/sudoers/def_data.c:588
+msgid "Set the pam remote host to the local host name"
+msgstr "Ustawienie hosta zdalnego PAM nazwę hosta lokalnego"
+
+#: plugins/sudoers/def_data.c:592
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "Katalog roboczy do zmiany przed uruchomieniem polecenia: %s"
+
+#: plugins/sudoers/def_data.c:596
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "Katalog główny do zmiany przed uruchomieniem polecenia: %s"
+
+#: plugins/sudoers/def_data.c:600
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "Format logów do tworzenia: %s"
+
+#: plugins/sudoers/def_data.c:604
+msgid "Enable SELinux RBAC support"
+msgstr "Włączenie obsługi RBAC SELinux"
+
+#: plugins/sudoers/def_data.c:608
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "Ścieżka do pliku tworzonego przy pierwszym uruchomieniu sudo: %s"
+
+#: plugins/sudoers/def_data.c:612
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "Przechwycenie dalszych poleceń i zastosowanie do nich restrykcji sudoers"
+
+#: plugins/sudoers/def_data.c:616
+msgid "Log sub-commands run by the original command"
+msgstr "Logowanie podpoleceń uruchamianych przez pierwotne polecenie"
+
+#: plugins/sudoers/def_data.c:620
+msgid "Log the exit status of commands"
+msgstr "Logowanie stanu wyjścia poleceń"
+
+#: plugins/sudoers/def_data.c:624
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr "Dalsze polecenia w przechwyconej sesji muszą być uwierzytelniane"
+
+#: plugins/sudoers/def_data.c:628
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr "Zezwolenie na uruchamianie programów setuid lub setgid z przechwyconego polecenia"
+
+#: plugins/sudoers/def_data.c:632
+#, c-format
+msgid "The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr "Maksymalny rozmiar, do jakiego może rosnąć przestrzeń adresowa procesu (w bajtach): %s"
+
+#: plugins/sudoers/def_data.c:636
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr "Maksymalny rozmiar pliku core, jaki może być utworzony (w bajtach): %s"
+
+#: plugins/sudoers/def_data.c:640
+#, c-format
+msgid "The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr "Maksymalna ilość czasu CPU, jaką proces może użyć (w sekundach): %s"
+
+#: plugins/sudoers/def_data.c:644
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr "Maksymalny rozmiar segmentu danych procesu (w bajtach): %s"
+
+#: plugins/sudoers/def_data.c:648
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr "Maksymalny rozmiar pliku, jaki proces może utworzyć (w bajtach): %s"
+
+#: plugins/sudoers/def_data.c:652
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr "Maksymalna liczba blokad, jaką proces może ustanowić: %s"
+
+#: plugins/sudoers/def_data.c:656
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr "Maksymalny rozmiar, jaki proces może zablokować w pamięci (w bajtach): %s"
+
+#: plugins/sudoers/def_data.c:660
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr "Maksymalna liczba plików, jaką proces może mieć otwartych: %s"
+
+#: plugins/sudoers/def_data.c:664
+#, c-format
+msgid "The maximum number of processes that the user may run simultaneously: %s"
+msgstr "Maksymalna liczba procesów, jaką użytkownik może jednocześnie uruchomić: %s"
+
+#: plugins/sudoers/def_data.c:668
+#, c-format
+msgid "The maximum size to which the process's resident set size may grow (in bytes): %s"
+msgstr "Maksymalny rozmiar, do jakiego może urosnąć rozmiar rezydentny procesu (w bajtach): %s"
+
+#: plugins/sudoers/def_data.c:672
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr "Maksymalny rozmiar, do jakiego może urosnąć stos procesu (w bajtach): %s"
+
+#: plugins/sudoers/def_data.c:676
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr "Próba uwierzytelnienia nawet w trybie nieinteraktywnym"
+
+#: plugins/sudoers/def_data.c:680
+msgid "Store plaintext passwords in I/O log input"
+msgstr "Zapisywanie haseł czystym tekstwem na wejściu/wyjściu logu"
+
+#: plugins/sudoers/def_data.c:684
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr "Lista wyrażeń regularnych do użycia przy dopasowywania pytania o hasło"
+
+#: plugins/sudoers/def_data.c:688
+#, c-format
+msgid "The mechanism used by the intercept and log_subcmds options: %s"
+msgstr "Mechanizm używany przez opcje intercept i log_subcmds: %s"
+
+#: plugins/sudoers/def_data.c:692
+msgid "Attempt to verify the command and arguments after execution"
+msgstr "Próba weryfikacji polecenia i argumentów po uruchomieniu"
+
+#: plugins/sudoers/def_data.c:696
+#, c-format
+msgid "AppArmor profile to use in the new security context: %s"
+msgstr "Profil AppArmor do użycia w nowym kontekście bezpieczeństwa: %s"
+
+#: plugins/sudoers/defaults.c:207
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "nieznany wpis domyślny \"%s\""
+
+#: plugins/sudoers/defaults.c:251
+#, c-format
+msgid "no value specified for \"%s\""
+msgstr "nie podano wartości dla \"%s\""
+
+#: plugins/sudoers/defaults.c:260
+#, c-format
+msgid "invalid operator \"%c=\" for \"%s\""
+msgstr "błędny operator \"%c=\" dla \"%s\""
+
+#: plugins/sudoers/defaults.c:292
+#, c-format
+msgid "option \"%s\" does not take a value"
+msgstr "opcja \"%s\" nie przyjmuje wartości"
+
+#: plugins/sudoers/defaults.c:319
+#, c-format
+msgid "invalid Defaults type 0x%x for option \"%s\""
+msgstr "błędny typ Defaults 0x%x dla opcji \"%s\""
+
+#: plugins/sudoers/defaults.c:326
+#, c-format
+msgid "value \"%s\" is invalid for option \"%s\""
+msgstr "błędna wartość \"%s\" dla opcji \"%s\""
+
+#: plugins/sudoers/defaults.c:1176 plugins/sudoers/policy.c:213
+#: plugins/sudoers/policy.c:222
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr "ścieżka pliku \"%s\" zbyt długa"
+
+#: plugins/sudoers/defaults.c:1182
+#, c-format
+msgid "values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "wartości \"%s\" muszą zaczynać się od '/', '~' lub '*'"
+
+#: plugins/sudoers/defaults.c:1189
+#, c-format
+msgid "values for \"%s\" must start with a '/'"
+msgstr "wartości \"%s\" muszą zaczynać się od '/'"
+
+#: plugins/sudoers/display.c:160
+#, c-format
+msgid "LDAP Role: %s\n"
+msgstr "Rola LDAP: %s\n"
+
+#: plugins/sudoers/display.c:163
+#, c-format
+msgid "Sudoers entry: %s\n"
+msgstr "Wpis sudoers: %s\n"
+
+#: plugins/sudoers/display.c:166
+msgid " RunAsUsers: "
+msgstr " Jako użytkownicy: "
+
+#: plugins/sudoers/display.c:181
+msgid " RunAsGroups: "
+msgstr " Jako grupy: "
+
+#: plugins/sudoers/display.c:191
+msgid " Options: "
+msgstr " Opcje: "
+
+#: plugins/sudoers/display.c:255
+msgid " Commands:\n"
+msgstr " Polecenia:\n"
+
+#: plugins/sudoers/display.c:478
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Pasujące wpisy Defaults dla %s na %s:\n"
+
+#: plugins/sudoers/display.c:496
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Wartości specyficzne dla Runas i Command dla %s:\n"
+
+#: plugins/sudoers/display.c:514
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "Użytkownik %s może uruchamiać na %s następujące polecenia:\n"
+
+#: plugins/sudoers/display.c:530
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Użytkownik %s nie ma uprawnień do uruchamiania sudo na %s.\n"
+
+#: plugins/sudoers/editor.c:180
+#, c-format
+msgid "ignoring editor: %.*s"
+msgstr "zignorowano edytor: %.*s"
+
+#: plugins/sudoers/editor.c:181
+msgid "editor arguments may not contain \"--\""
+msgstr "argumenty edytora nie mogą zawierać \"--\""
+
+#: plugins/sudoers/env.c:426
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: uszkodzone envp, niezgodność długości"
+
+#: plugins/sudoers/env.c:1119
+msgid "unable to rebuild the environment"
+msgstr "nie udało się przebudować środowiska"
+
+#: plugins/sudoers/env.c:1199
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "niestety nie jest dozwolone ustawianie następujących zmiennych środowiskowych: %s"
+
+#: plugins/sudoers/filedigest.c:50
+#, c-format
+msgid "unsupported digest type %u for %s"
+msgstr "nieobsługiwany typ skrótu %u dla %s"
+
+#: plugins/sudoers/filedigest.c:77
+#, c-format
+msgid "%s: read error"
+msgstr "%s: błąd odczytu"
+
+#: plugins/sudoers/group_plugin.c:169 plugins/sudoers/sssd.c:578
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "nie udało się załadować %s: %s"
+
+#: plugins/sudoers/group_plugin.c:181
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "nie udało się odnaleźć symbolu \"group_plugin\" w %s"
+
+#: plugins/sudoers/group_plugin.c:186
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: niezgodna główna wersja wtyczki grup %d, oczekiwano %d"
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "nie udało się przeanalizować adresu IP \"%s\""
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "nie udało się przeanalizować maski sieciowej \"%s\""
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Pary lokalnych adresów IP i masek:\n"
+
+#: plugins/sudoers/iolog.c:694
+msgid "unable to update sequence file"
+msgstr "nie udało się uaktualnić pliku sekwencji"
+
+#: plugins/sudoers/iolog.c:728 plugins/sudoers/iolog.c:917
+#: plugins/sudoers/iolog.c:1080 plugins/sudoers/iolog.c:1087
+#: plugins/sudoers/iolog.c:1209 plugins/sudoers/iolog.c:1216
+#: plugins/sudoers/iolog.c:1316 plugins/sudoers/iolog.c:1323
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "nie udało się zapisać do pliku logu we/wy: %s"
+
+#: plugins/sudoers/iolog.c:736
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "nie udało się utworzyć %s/%s"
+
+#: plugins/sudoers/iolog.c:965
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: błąd wewnętrzny, plik logu we/wy dla zdarzenia %d nie jest otwarty"
+
+#: plugins/sudoers/iolog.c:1065 plugins/sudoers/iolog.c:1194
+#: plugins/sudoers/iolog.c:1300 plugins/sudoers/timestamp.c:897
+#: plugins/sudoers/timestamp.c:989 plugins/sudoers/visudo.c:555
+#: plugins/sudoers/visudo.c:561
+msgid "unable to read the clock"
+msgstr "nie udało się odczytać zegara"
+
+#: plugins/sudoers/iolog.c:1292 plugins/sudoers/log_client.c:1203
+#: plugins/sudoers/log_client.c:1213 plugins/sudoers/log_client.c:1217
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: błąd wewnętrzny, błędny sygnał %d"
+
+#: plugins/sudoers/ldap.c:154 plugins/sudoers/ldap_conf.c:289
+msgid "starttls not supported when using ldaps"
+msgstr "brak obsługi starttls w przypadku użycia ldaps"
+
+#: plugins/sudoers/ldap.c:226
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "nie udało się zainicjować bazy certyfikatów i kluczy SSL: %s"
+
+#: plugins/sudoers/ldap.c:229
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "aby używać SSL, trzeba ustawić TLS_CERT w %s"
+
+#: plugins/sudoers/ldap.c:1593
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "nie udało się zainicjować LDAP: %s"
+
+#: plugins/sudoers/ldap.c:1630
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "wybrano start_tls, ale biblioteki LDAP nie obsługują ldap_start_tls_s() ani ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:1767 plugins/sudoers/parse_ldif.c:745
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "błędny atrybut sudoOrder: %s"
+
+#: plugins/sudoers/ldap_conf.c:197
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: za duży numer portu"
+
+#: plugins/sudoers/ldap_conf.c:258
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "nieobsługiwany rodzaj URI LDAP: %s"
+
+#: plugins/sudoers/ldap_conf.c:285
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "nie można mieszać URI ldap i ldaps"
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "powtórka sudoOption: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "nie można skonwertować sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "nie udało się otworzyć systemu audytowego"
+
+#: plugins/sudoers/linux_audit.c:104
+msgid "unable to send audit message"
+msgstr "nie udało się wysłać komunikatu audytowego"
+
+#: plugins/sudoers/log_client.c:125 plugins/sudoers/log_client.c:412
+#: plugins/sudoers/log_client.c:1450 plugins/sudoers/log_client.c:2076
+msgid "error in event loop"
+msgstr "błąd w pętli zdarzeń"
+
+#: plugins/sudoers/log_client.c:205
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "Utworzenie nowego obiektu SSL_CTX nie powiodło się: %s"
+
+#: plugins/sudoers/log_client.c:230
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "nie udało się załadować paczki certyfikatów CA %s"
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "nie udało się załadować certyfikatu %s"
+
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "unable to load private key %s"
+msgstr "nie udało się załadować klucza prywatnego %s"
+
+#: plugins/sudoers/log_client.c:275
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "Nie udało się przydzielić obiektu SSL: %s"
+
+#: plugins/sudoers/log_client.c:364 plugins/sudoers/log_client.c:369
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "Połączenie TLS do %s:%s nie powiodło się: %s"
+
+#: plugins/sudoers/log_client.c:545
+msgid "TLS initialization was unsuccessful"
+msgstr "Inicjowanie TLS nie powiodło się"
+
+#: plugins/sudoers/log_client.c:555
+msgid "TLS handshake was unsuccessful"
+msgstr "Powitanie TLS nie powiodło się"
+
+#: plugins/sudoers/log_client.c:1221
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: błąd wewnętrzny, błędny kod wyjścia %d"
+
+#: plugins/sudoers/log_client.c:1757 plugins/sudoers/log_client.c:1782
+msgid "lost connection to log server"
+msgstr "utracono połączenie z serwerem logów"
+
+#: plugins/sudoers/log_client.c:1859
+msgid "missing write buffer"
+msgstr "brak bufora zapisu"
+
+#: plugins/sudoers/log_client.c:2015
+msgid "unable to connect to log server"
+msgstr "nie udało się połączyć z serwerem logów"
+
+#: plugins/sudoers/logging.c:295
+msgid "user NOT in sudoers"
+msgstr "użytkownik NIE występuje w sudoers"
+
+#: plugins/sudoers/logging.c:297
+msgid "user NOT authorized on host"
+msgstr "użytkownik NIE jest autoryzowany na hoście"
+
+#: plugins/sudoers/logging.c:299
+msgid "command not allowed"
+msgstr "polecenie niedozwolone"
+
+#: plugins/sudoers/logging.c:320
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr "%s nie jest w pliku sudoers.\n"
+
+#: plugins/sudoers/logging.c:323
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr "%s nie ma uprawnień do uruchamiania sudo na %s.\n"
+
+#: plugins/sudoers/logging.c:326
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Niestety użytkownik %s nie może uruchamiać sudo na %s.\n"
+
+#: plugins/sudoers/logging.c:339
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s%s' as %s%s%s on %s.\n"
+msgstr "Niestety użytkownik %s nie ma uprawnień do uruchamiania '%s%s%s%s' jako %s%s%s na %s.\n"
+
+#: plugins/sudoers/logging.c:350
+msgid "This incident has been reported to the administrator.\n"
+msgstr "Ten incydent został zgłoszony do administratora.\n"
+
+#: plugins/sudoers/logging.c:387 plugins/sudoers/sudoers.c:547
+#: plugins/sudoers/sudoers.c:549 plugins/sudoers/sudoers.c:551
+#: plugins/sudoers/sudoers.c:553 plugins/sudoers/sudoers.c:777
+#: plugins/sudoers/sudoers.c:779
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: nie znaleziono polecenia"
+
+#: plugins/sudoers/logging.c:389 plugins/sudoers/sudoers.c:543
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"zignorowano plik \"%s\" znaleziony w '.'\n"
+"Proszę użyć \"sudo ./%s\", jeśli to \"%s\" ma być uruchomiony."
+
+#: plugins/sudoers/logging.c:409
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u błędna próba wprowadzenia hasła"
+msgstr[1] "%u błędne próby wprowadzenia hasła"
+msgstr[2] "%u błędnych prób wprowadzenia hasła"
+
+#: plugins/sudoers/logging.c:500
+msgid "authentication failure"
+msgstr "błąd uwierzytelniania"
+
+#: plugins/sudoers/logging.c:539 plugins/sudoers/logging.c:558
+msgid "a password is required"
+msgstr "wymagane jest hasło"
+
+#: plugins/sudoers/logging.c:881
+msgid "problem parsing sudoers"
+msgstr "problem przy analizie pliku sudoers"
+
+#: plugins/sudoers/logging.c:922 plugins/sudoers/logging.c:930
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr "%s:%d:%d: %s"
+
+#: plugins/sudoers/logging.c:1108
+#, c-format
+msgid "unable to write log file %s"
+msgstr "nie udało się zapisać pliku logu %s"
+
+#: plugins/sudoers/match_digest.c:107
+#, c-format
+msgid "digest for %s (%s) bad length %zu, expected %zu"
+msgstr "skrót dla %s (%s) ma błędną długość %zu, oczekiwano %zu"
+
+#: plugins/sudoers/match_digest.c:126
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "skrót dla %s (%s) nie jest w postaci %s"
+
+#: plugins/sudoers/parse_ldif.c:615
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "zignorowano niekompletne sudoRole: cn: %s"
+
+#: plugins/sudoers/parse_ldif.c:675
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "błędny atrybut LDIF: %s"
+
+#: plugins/sudoers/parser_warnx.c:56
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: plugins/sudoers/parser_warnx.c:59
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s: %s\n"
+
+#: plugins/sudoers/pivot.c:71
+msgid "unable to restore root directory"
+msgstr "nie udało się przywrócić katalogu głównego"
+
+#: plugins/sudoers/pivot.c:79
+msgid "unable to restore current working directory"
+msgstr "nie udało się przywrócić aktualnego katalogu roboczego"
+
+#: plugins/sudoers/policy.c:78 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "błędna wartość %.*s ustawiona przez frontend sudo"
+
+#: plugins/sudoers/policy.c:364 plugins/sudoers/testsudoers.c:329
+msgid "unable to parse network address list"
+msgstr "nie udało się przeanalizować listy adresów sieciowych"
+
+#: plugins/sudoers/policy.c:556
+msgid "user name not set by sudo front-end"
+msgstr "nazwa użytkownika nie ustawiona przez frontend sudo"
+
+#: plugins/sudoers/policy.c:560
+msgid "user-ID not set by sudo front-end"
+msgstr "ID użytkownika nie ustawiony przez frontend sudo"
+
+#: plugins/sudoers/policy.c:564
+msgid "group-ID not set by sudo front-end"
+msgstr "ID grupy nie ustawiony przez frontend sudo"
+
+#: plugins/sudoers/policy.c:568
+msgid "host name not set by sudo front-end"
+msgstr "nazwa hosta nie ustawiona przez frontend sudo"
+
+#: plugins/sudoers/policy.c:757
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "błędny katalog roboczy: %s"
+
+#: plugins/sudoers/policy.c:944
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "błędny katalog chroot: %s"
+
+#: plugins/sudoers/policy.c:1153 plugins/sudoers/visudo.c:919
+#: plugins/sudoers/visudo.c:1218
+#, c-format
+msgid "unable to execute %s"
+msgstr "nie udało się wywołać %s"
+
+#: plugins/sudoers/policy.c:1225 plugins/sudoers/policy.c:1260
+#: plugins/sudoers/policy.c:1282 plugins/sudoers/policy.c:1300
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: błędne flagi trybu z frontendu sudo: 0x%x"
+
+#: plugins/sudoers/policy.c:1323
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Wersja wtyczki polityki sudoers %s\n"
+
+#: plugins/sudoers/policy.c:1325
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Wersja gramatyki pliku sudoers %d\n"
+
+#: plugins/sudoers/policy.c:1329
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Ścieżka do sudoers: %s\n"
+
+#: plugins/sudoers/policy.c:1332
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "ścieżka do nsswitch: %s\n"
+
+#: plugins/sudoers/policy.c:1335
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "ścieżka do ldap.conf: %s\n"
+
+#: plugins/sudoers/policy.c:1337
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "ścieżka do ldap.secret: %s\n"
+
+#: plugins/sudoers/policy.c:1370
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "nie udało się zarejestrować uchwytu typu %d (wersja %d.%d)"
+
+#: plugins/sudoers/policy.c:1388
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "nie udało się wyrejestrować uchwytu typu %d (wersja %d.%d)"
+
+#: plugins/sudoers/pwutil.c:242 plugins/sudoers/pwutil.c:260
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "nie udało się zapamiętać uid-a %u"
+
+#: plugins/sudoers/pwutil.c:254
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "nie udało się zapamiętać uid-a %u, już istnieje"
+
+#: plugins/sudoers/pwutil.c:314 plugins/sudoers/pwutil.c:332
+#: plugins/sudoers/pwutil.c:395 plugins/sudoers/pwutil.c:440
+#, c-format
+msgid "unable to cache user %s"
+msgstr "nie udało się zapamiętać użytkownika %s"
+
+#: plugins/sudoers/pwutil.c:327
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "nie udało się zapamiętać użytkownika %s, już istnieje"
+
+#: plugins/sudoers/pwutil.c:559 plugins/sudoers/pwutil.c:577
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "nie udało się zapamiętać gid-a %u"
+
+#: plugins/sudoers/pwutil.c:571
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "nie udało się zapamiętać gid-a %u, już istnieje"
+
+#: plugins/sudoers/pwutil.c:625 plugins/sudoers/pwutil.c:643
+#: plugins/sudoers/pwutil.c:704 plugins/sudoers/pwutil.c:753
+#, c-format
+msgid "unable to cache group %s"
+msgstr "nie udało się zapamiętać grupy %s"
+
+#: plugins/sudoers/pwutil.c:638
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "nie udało się zapamiętać grupy %s, już istnieje"
+
+#: plugins/sudoers/pwutil.c:900 plugins/sudoers/pwutil.c:985
+#: plugins/sudoers/pwutil.c:1039 plugins/sudoers/pwutil.c:1095
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "nie udało się zapamiętać listy grup dla %s, już istnieje"
+
+#: plugins/sudoers/pwutil.c:906 plugins/sudoers/pwutil.c:990
+#: plugins/sudoers/pwutil.c:1045 plugins/sudoers/pwutil.c:1100
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "nie udało się zapamiętać listy grup dla %s"
+
+#: plugins/sudoers/pwutil.c:979
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "nie udało się przeanalizować grup dla %s"
+
+#: plugins/sudoers/pwutil.c:1089
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "nie udało się przeanalizować gidów dla %s"
+
+#: plugins/sudoers/set_perms.c:120 plugins/sudoers/set_perms.c:457
+#: plugins/sudoers/set_perms.c:870 plugins/sudoers/set_perms.c:1186
+#: plugins/sudoers/set_perms.c:1490
+msgid "perm stack overflow"
+msgstr "przepełnienie stosu uprawnień"
+
+#: plugins/sudoers/set_perms.c:131 plugins/sudoers/set_perms.c:387
+#: plugins/sudoers/set_perms.c:468 plugins/sudoers/set_perms.c:736
+#: plugins/sudoers/set_perms.c:881 plugins/sudoers/set_perms.c:1109
+#: plugins/sudoers/set_perms.c:1197 plugins/sudoers/set_perms.c:1422
+#: plugins/sudoers/set_perms.c:1501 plugins/sudoers/set_perms.c:1592
+msgid "perm stack underflow"
+msgstr "niedopełnienie stosu uprawnień"
+
+#: plugins/sudoers/set_perms.c:191 plugins/sudoers/set_perms.c:515
+#: plugins/sudoers/set_perms.c:1251 plugins/sudoers/set_perms.c:1535
+msgid "unable to change to root gid"
+msgstr "nie udało się zmienić na gid roota"
+
+#: plugins/sudoers/set_perms.c:282 plugins/sudoers/set_perms.c:612
+#: plugins/sudoers/set_perms.c:1013 plugins/sudoers/set_perms.c:1328
+msgid "unable to change to runas gid"
+msgstr "nie udało się zmienić na docelowy gid"
+
+#: plugins/sudoers/set_perms.c:287 plugins/sudoers/set_perms.c:617
+#: plugins/sudoers/set_perms.c:1018 plugins/sudoers/set_perms.c:1333
+msgid "unable to set runas group vector"
+msgstr "nie udało się ustawić wektora grup docelowych"
+
+#: plugins/sudoers/set_perms.c:298 plugins/sudoers/set_perms.c:628
+#: plugins/sudoers/set_perms.c:1027 plugins/sudoers/set_perms.c:1342
+msgid "unable to change to runas uid"
+msgstr "nie udało się zmienić na docelowy uid"
+
+#: plugins/sudoers/set_perms.c:320 plugins/sudoers/set_perms.c:650
+#: plugins/sudoers/set_perms.c:1047 plugins/sudoers/set_perms.c:1362
+msgid "unable to change to sudoers gid"
+msgstr "nie udało się zmienić na gid sudoers"
+
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579
+msgid "too many processes"
+msgstr "zbyt dużo procesów"
+
+#: plugins/sudoers/solaris_audit.c:62
+msgid "unable to get current working directory"
+msgstr "nie udało się pobrać bieżącego katalogu roboczego"
+
+#: plugins/sudoers/solaris_audit.c:70
+#, c-format
+msgid "truncated audit path ctx->user.cmnd: %s"
+msgstr "ucięta ścieżka audytu ctx->user.cmnd: %s"
+
+#: plugins/sudoers/solaris_audit.c:77
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "ucięta ścieżka audytu argv[0]: %s"
+
+#: plugins/sudoers/sssd.c:581
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "nie udało się zainicjować źródła SSS. Czy SSSD jest zainstalowany na tej maszynie?"
+
+#: plugins/sudoers/sssd.c:589 plugins/sudoers/sssd.c:598
+#: plugins/sudoers/sssd.c:607 plugins/sudoers/sssd.c:616
+#: plugins/sudoers/sssd.c:625
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "nie udało się odnaleźć symbolu \"%s\" w %s"
+
+#: plugins/sudoers/sudoers.c:250
+#, c-format
+msgid "unable to get defaults from %s"
+msgstr "nie udało się pobrać wartości domyślnych z %s"
+
+#: plugins/sudoers/sudoers.c:259
+msgid "no valid sudoers sources found, quitting"
+msgstr "nie znaleziono poprawnych źródeł sudoers, zakończenie"
+
+#: plugins/sudoers/sudoers.c:366
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "wg sudoers root nie ma prawa używać sudo"
+
+#: plugins/sudoers/sudoers.c:375
+msgid "user not allowed to override closefrom limit"
+msgstr "użytkownik nie ma pozwolenia na zmianę limitu closefrom"
+
+#: plugins/sudoers/sudoers.c:376
+msgid "you are not permitted to use the -C option"
+msgstr "brak uprawnień do używania opcji -C"
+
+#: plugins/sudoers/sudoers.c:440
+msgid "no tty"
+msgstr "brak tty"
+
+#: plugins/sudoers/sudoers.c:441
+msgid "sorry, you must have a tty to run sudo"
+msgstr "niestety do uruchomienia sudo konieczny jest tty"
+
+#: plugins/sudoers/sudoers.c:449
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "błędna powłoka użytkownika %s: %s"
+
+#: plugins/sudoers/sudoers.c:491
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "użytkownik nie ma uprawnień do zmiany katalogu głównego na %s"
+
+#: plugins/sudoers/sudoers.c:493
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "brak uprawnień do używania opcji -R z %s"
+
+#: plugins/sudoers/sudoers.c:506
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "użytkownik nie ma uprawnień do zmiany katalogu na %s"
+
+#: plugins/sudoers/sudoers.c:507
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "brak uprawnień do używania opcji -D z %s"
+
+#: plugins/sudoers/sudoers.c:542
+msgid "command in current directory"
+msgstr "polecenie w bieżącym katalogu"
+
+#: plugins/sudoers/sudoers.c:557
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr "\"cd\" to polecenie wbudowane powłoki, nie może być uruchomione bezpośrednio."
+
+#: plugins/sudoers/sudoers.c:559
+msgid "the -s option may be used to run a privileged shell."
+msgstr "można użyć opcji -s do uruchomienia powłoki uprzywilejowanej."
+
+#: plugins/sudoers/sudoers.c:561
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr "można użyć opcji -D do uruchomienia polecenia w podanym katalogu."
+
+#: plugins/sudoers/sudoers.c:570
+msgid "user not allowed to set a command timeout"
+msgstr "użytkownik nie ma uprawnień do ustawienia limitu czasu polecenia"
+
+#: plugins/sudoers/sudoers.c:572
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "niestety brak uprawnień do ustawienia limitu czasu polecenia"
+
+#: plugins/sudoers/sudoers.c:580
+msgid "user not allowed to preserve the environment"
+msgstr "użytkownik nie ma uprawnień do zachowania środowiska"
+
+#: plugins/sudoers/sudoers.c:582
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "niestety brak uprawnień do zachowania środowiska"
+
+#: plugins/sudoers/sudoers.c:618
+msgid "no command specified"
+msgstr "nie podano polecenia"
+
+#: plugins/sudoers/sudoers.c:759
+msgid "error setting user-specified environment variables"
+msgstr "błąd ustawiania zmiennych środowiskowych podanych przez użytkownika"
+
+#: plugins/sudoers/sudoers.c:1211
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "sudoedit nie musi być uruchamiany przez sudo"
+
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:1613
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "nie udało się odczytać %s"
+
+#: plugins/sudoers/sudoers.c:1321 plugins/sudoers/visudo.c:1123
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s nie jest zwykłym plikiem"
+
+#: plugins/sudoers/sudoers.c:1325 plugins/sudoers/timestamp.c:272 toke.l:1355
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "właścicielem %s jest uid %u, powinien być %u"
+
+#: plugins/sudoers/sudoers.c:1330 plugins/sudoers/timestamp.c:279 toke.l:1360
+#, c-format
+msgid "%s is world writable"
+msgstr "%s jest zapisywalny dla świata"
+
+#: plugins/sudoers/sudoers.c:1334 plugins/sudoers/timestamp.c:284 toke.l:1363
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "właścicielem %s jest gid %u, powinien być %u"
+
+#: plugins/sudoers/sudoers.c:1363
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "tylko root może używać \"-c %s\""
+
+#: plugins/sudoers/sudoers.c:1382
+#, c-format
+msgid "unknown login class %s"
+msgstr "nieznana klasa logowania %s"
+
+#: plugins/sudoers/sudoers_cb.c:120 plugins/sudoers/sudoers_cb.c:135
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "nie udało się rozwiązać nazwy hosta %s"
+
+#: plugins/sudoers/sudoreplay.c:252
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "błędna opcja filtra: %s"
+
+#: plugins/sudoers/sudoreplay.c:268
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "błędny maksymalny czas oczekiwania: %s"
+
+#: plugins/sudoers/sudoreplay.c:291
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "błędny współczynnik szybkości: %s"
+
+#: plugins/sudoers/sudoreplay.c:326
+#, c-format
+msgid "invalid time offset %s"
+msgstr "błędny offset czasu %s"
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:340
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/czas: %s"
+
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Odtwarzanie sesji sudo: %s"
+
+#: plugins/sudoers/sudoreplay.c:634
+msgid "unable to set tty to raw mode"
+msgstr "nie udało się przestawić tty w tryb surowy"
+
+#: plugins/sudoers/sudoreplay.c:685
+msgid "Warning: your terminal is too small to properly replay the log."
+msgstr "Uwaga: ten terminal jest za mały, aby właściwie odtworzyć log."
+
+#: plugins/sudoers/sudoreplay.c:686
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Geometria logu to %d x %d, geometria terminala to %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:714
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Odtwarzanie zakończone, proszę nacisnąć dowolny klawisz, aby odzyskać terminal."
+
+#: plugins/sudoers/sudoreplay.c:1217 plugins/sudoers/sudoreplay.c:1247
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "niejednoznaczne wyrażenie \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1269
+msgid "unmatched ')' in expression"
+msgstr "niesparowany ')' w wyrażeniu"
+
+#: plugins/sudoers/sudoreplay.c:1273
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "nieznany warunek wyszukiwania \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1288
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s wymaga argumentu"
+
+#: plugins/sudoers/sudoreplay.c:1298
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "nie udało się przeanalizować daty \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1307
+msgid "unmatched '(' in expression"
+msgstr "niesparowany '(' w wyrażeniu"
+
+#: plugins/sudoers/sudoreplay.c:1309
+msgid "illegal trailing \"or\""
+msgstr "niedozwolone kończące \"or\""
+
+#: plugins/sudoers/sudoreplay.c:1311
+msgid "illegal trailing \"!\""
+msgstr "niedozwolony kończący \"!\""
+
+#: plugins/sudoers/sudoreplay.c:1417
+#, c-format
+msgid "unknown search type %d"
+msgstr "nieznany typ wyszukiwania %d"
+
+#: plugins/sudoers/sudoreplay.c:1679
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "Składnia: %s [-hnRS] [-d katalog] [-m liczba] [-s wsp_szybkości] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1681
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "Składnia: %s [-h] [-d katalog] -l [wyrażenie wyszukiwania]\n"
+
+#: plugins/sudoers/sudoreplay.c:1695
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - odtwarzanie logów sesji sudo\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1697
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Opcje:\n"
+" -d, --directory=kat podanie katalogu na logi sesji\n"
+" -f, --filter=filtr określenie rodzaju we/wy do wyświetlania\n"
+" -h, --help wyświetlenie opisu i zakończenie\n"
+" -l, --list lista dostępnych ID sesji pasujących do wyrażenia\n"
+" -m, --max-wait=ile maksymalna liczba sekund oczekiwania między zdarzeniami\n"
+" -n, --non-interactive bez zapytań, wysłanie sesji na standardowe wyjście\n"
+" -R, --no-resize bez próby zmiany rozmiaru terminala\n"
+" -S, --suspend-wait oczekiwanie w czasie zawieszenia polecenia\n"
+" -s, --speed=ile przyspieszenie lub spowolnienie wyjścia\n"
+" -V, --version wyświetlenie informacji o wersji i zakończenie"
+
+#: plugins/sudoers/testsudoers.c:392
+#, c-format
+msgid ""
+"\n"
+"Invalid shell for user %s: %s\n"
+msgstr ""
+"\n"
+"Błędna powłoka użytkownika %s: %s\n"
+
+#: plugins/sudoers/testsudoers.c:411
+msgid ""
+"\n"
+"Password required"
+msgstr ""
+"\n"
+"Wymagane hasło"
+
+#: plugins/sudoers/testsudoers.c:422
+msgid ""
+"\n"
+"Parse error"
+msgstr ""
+"\n"
+"Błąd składni"
+
+#: plugins/sudoers/testsudoers.c:425
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Polecenie dozwolone"
+
+#: plugins/sudoers/testsudoers.c:428
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Polecenie niedozwolone"
+
+#: plugins/sudoers/testsudoers.c:431
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Polecenie nie znalezione"
+
+#: plugins/sudoers/timestamp.c:364 plugins/sudoers/timestamp.c:711
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "nie udało się uciąć pliku znacznika czasu do długości %lld"
+
+#: plugins/sudoers/timestamp.c:908
+msgid "ignoring time stamp from the future"
+msgstr "znacznik czasu zbyt daleko w przyszłości"
+
+#: plugins/sudoers/timestamp.c:931
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "znacznik czasu zbyt daleko w przyszłości: %20.20s"
+
+#: plugins/sudoers/timestamp.c:1067
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "nie udało się zablokować pliku znacznika czasu %s"
+
+#: plugins/sudoers/timestamp.c:1114
+#, c-format
+msgid "%s:%d:%d timestampowner: unknown user %s"
+msgstr "%s:%d:%d timestampowner: nieznany użytkownik %s"
+
+#: plugins/sudoers/toke_util.c:159
+msgid "sudoedit should not be specified with a path"
+msgstr "sudoedit nie powinien być podawany ze ścieżką"
+
+#: plugins/sudoers/visudo.c:308 plugins/sudoers/visudo.c:714
+#, c-format
+msgid "press return to edit %s: "
+msgstr "wciśnięcie return przejdzie do edycji %s: "
+
+#: plugins/sudoers/visudo.c:323
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "zawartość sesji edycji pozostawiona w %s"
+
+#: plugins/sudoers/visudo.c:401
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "podany edytor (%s) nie istnieje"
+
+#: plugins/sudoers/visudo.c:406
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "nie znaleziono edytora (ścieżka = %s)"
+
+#: plugins/sudoers/visudo.c:494 plugins/sudoers/visudo.c:786
+#, c-format
+msgid "unable to stat %s"
+msgstr "nie udało się wykonać stat na %s"
+
+#: plugins/sudoers/visudo.c:514 plugins/sudoers/visudo.c:522
+msgid "write error"
+msgstr "błąd zapisu"
+
+#: plugins/sudoers/visudo.c:568
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "nie udało się wykonać stat na pliku tymczasowym (%s), %s nie zmieniony"
+
+#: plugins/sudoers/visudo.c:575
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "plik tymczasowy (%s) zerowej długości, %s nie zmieniony"
+
+#: plugins/sudoers/visudo.c:581
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "błąd edytora (%s), %s nie zmieniony"
+
+#: plugins/sudoers/visudo.c:613
+#, c-format
+msgid "%s unchanged"
+msgstr "%s nie zmieniony"
+
+#: plugins/sudoers/visudo.c:661
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "nie udało się ponownie otworzyć pliku tymczasowego (%s), %s nie zmieniony."
+
+#: plugins/sudoers/visudo.c:674
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "nie udało się przeanalizować pliku tymczasowego (%s), nieznany błąd"
+
+#: plugins/sudoers/visudo.c:760 plugins/sudoers/visudo.c:790
+#: plugins/sudoers/visudo.c:797
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "nie udało się ustawić (uid, gid) %s na (%u, %u)"
+
+#: plugins/sudoers/visudo.c:825
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s i %s nie są na tym samym systemie plików, użycie mv do zmiany nazwy"
+
+#: plugins/sudoers/visudo.c:836
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "polecenie nie powiodło się: '%s %s %s', %s nie zmieniony"
+
+#: plugins/sudoers/visudo.c:843
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "błąd podczas zmiany nazwy %s, %s nie zmieniony"
+
+#: plugins/sudoers/visudo.c:864
+msgid "What now? "
+msgstr "Co teraz? "
+
+#: plugins/sudoers/visudo.c:878
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Możliwe opcje:\n"
+" (e) ponowna edycja pliku sudoers\n"
+" (x) wyjście bez zapisu zmian do pliku sudoers\n"
+" (Q) wyjście i zapisanie zmian w pliku sudoers (NIEBEZPIECZNE!)\n"
+
+#: plugins/sudoers/visudo.c:923
+#, c-format
+msgid "unable to run %s"
+msgstr "nie udało się uruchomić %s"
+
+#: plugins/sudoers/visudo.c:954
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: błędny właściciel, (uid, gid) powinny wynosić (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:965
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: błędne uprawnienia, powinny być 0%o\n"
+
+#: plugins/sudoers/visudo.c:1017 plugins/sudoers/visudo.c:1024
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: składnia poprawna\n"
+
+#: plugins/sudoers/visudo.c:1043
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s zajęty, proszę spróbować później"
+
+#: plugins/sudoers/visudo.c:1047
+msgid "Edit anyway? [y/N]"
+msgstr "Modyfikować mimo to? [y/N]"
+
+#: plugins/sudoers/visudo.c:1206
+msgid "the -x option will be removed in a future release"
+msgstr "opcja -x będzie usunięta w kolejnej wersji"
+
+#: plugins/sudoers/visudo.c:1208
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "należy rozważyć użycie zamiast niej narzędzia cvtsudoers"
+
+#: plugins/sudoers/visudo.c:1228
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "Uwaga: %s:%d:%d: nie użyty %s \"%s\""
+
+#: plugins/sudoers/visudo.c:1341
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - bezpieczna edycja pliku sudoers\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1343
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -I, --no-includes do not edit include files\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Opcje:\n"
+" -c, --check tryb wyłącznie sprawdzający\n"
+" -f, --file=sudoers określenie położenia pliku sudoers\n"
+" -h, --help wyświetlenie opisu i zakończenie\n"
+" -I, --no-includes bez edycji plików dołączanych\n"
+" -q, --quiet mniej obszerne komunikaty o błędach składni\n"
+" -s, --strict ścisłe sprawdzanie składni\n"
+" -V, --version wyświetlenie informacji o wersji i zakończenie\n"
+
+#: toke.l:184
+msgid "empty string"
+msgstr "pusty łańcuch"
+
+#: toke.l:196 toke.l:566
+msgid "empty group"
+msgstr "pusta grupa"
+
+#: toke.l:206 toke.l:564
+msgid "empty netgroup"
+msgstr "pusta grupa sieciowa"
+
+#: toke.l:284
+msgid "unterminated regular expression"
+msgstr "niezakończone wyrażenie regularne"
+
+#: toke.l:358 toke.l:370 toke.l:382 toke.l:398 toke.l:417 toke.l:457
+msgid "invalid line continuation"
+msgstr "błędna kontynuacja linii"
+
+#: toke.l:603 toke.l:615
+msgid "invalid IPv6 address"
+msgstr "błędny adres IPv6"
+
+#: toke.l:863
+msgid "unexpected line break in string"
+msgstr "nieoczekiwany koniec linii w łańcuchu"
+
+#: toke.l:982
+msgid "ignoring editor backup file"
+msgstr "zignorowano plik kopii zapasowej edytora"
+
+#: toke.l:985
+msgid "ignoring file name containing '.'"
+msgstr "zignorowano nazwę pliku zawierającą"
+
+#: toke.l:1310
+msgid "too many levels of includes"
+msgstr "za dużo poziomów include"
diff --git a/plugins/sudoers/po/pt.mo b/plugins/sudoers/po/pt.mo
new file mode 100644
index 0000000..de304b0
--- /dev/null
+++ b/plugins/sudoers/po/pt.mo
Binary files differ
diff --git a/plugins/sudoers/po/pt.po b/plugins/sudoers/po/pt.po
new file mode 100644
index 0000000..ba8496b
--- /dev/null
+++ b/plugins/sudoers/po/pt.po
@@ -0,0 +1,3681 @@
+# Portuguese (Portugal) translation for the sudoers package.
+# Copyright (C) 2018 Free Software Foundation, Inc.
+# This file is distributed under the same license as the sudo package.
+# Todd C. Miller <Todd.Miller@sudo.ws>, 2011-2018
+# Pedro Albuquerque <pmra@protonmail.com>, 2018, 2019, 2020, 2021.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers-1.9.8b2\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2021-08-19 09:50-0600\n"
+"PO-Revision-Date: 2021-08-22 07:21+0100\n"
+"Last-Translator: Pedro Albuquerque <pmra@protonmail.com>\n"
+"Language-Team: Portuguese <translation-team-pt@lists.sourceforge.net>\n"
+"Language: pt\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"X-Generator: Poedit 2.3\n"
+
+#: confstr.sh:1 gram.y:1191
+msgid "syntax error"
+msgstr "erro de sintaxe"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "senha de %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] senha para %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Senha: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** Informação de SEGURANÇA para %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Enganou-se, tente de novo."
+
+#: gram.y:235 gram.y:302 gram.y:311 gram.y:320 gram.y:330 gram.y:340
+#: gram.y:364 gram.y:391 gram.y:400 gram.y:408 gram.y:417 gram.y:426
+#: gram.y:500 gram.y:510 gram.y:522 gram.y:566 gram.y:575 gram.y:584
+#: gram.y:593 gram.y:712 gram.y:720 gram.y:731 gram.y:743 gram.y:762
+#: gram.y:917 gram.y:922 gram.y:930 gram.y:940 gram.y:946 gram.y:1068
+#: gram.y:1077 gram.y:1085 gram.y:1094 gram.y:1103 gram.y:1132 gram.y:1141
+#: gram.y:1149 gram.y:1239 gram.y:1351 gram.y:1658 gram.y:1708
+#: lib/eventlog/eventlog.c:308 lib/eventlog/eventlog.c:381
+#: lib/eventlog/eventlog.c:783 lib/eventlog/eventlog.c:862
+#: lib/eventlog/eventlog.c:1146 lib/iolog/iolog_json.c:125
+#: lib/iolog/iolog_json.c:330 lib/iolog/iolog_json.c:360
+#: lib/iolog/iolog_json.c:503 lib/iolog/iolog_legacy.c:100
+#: lib/iolog/iolog_legacy.c:111 lib/iolog/iolog_legacy.c:123
+#: lib/iolog/iolog_legacy.c:133 lib/iolog/iolog_legacy.c:139
+#: lib/iolog/iolog_loginfo.c:76 lib/iolog/iolog_loginfo.c:210
+#: logsrvd/iolog_writer.c:85 logsrvd/iolog_writer.c:90
+#: logsrvd/iolog_writer.c:124 logsrvd/iolog_writer.c:172
+#: logsrvd/iolog_writer.c:212 logsrvd/iolog_writer.c:225
+#: logsrvd/iolog_writer.c:261 logsrvd/iolog_writer.c:286
+#: logsrvd/iolog_writer.c:301 logsrvd/iolog_writer.c:314
+#: logsrvd/iolog_writer.c:327 logsrvd/iolog_writer.c:340
+#: logsrvd/iolog_writer.c:355 logsrvd/iolog_writer.c:393
+#: logsrvd/iolog_writer.c:399 logsrvd/iolog_writer.c:406
+#: logsrvd/iolog_writer.c:412 logsrvd/iolog_writer.c:596
+#: logsrvd/logsrv_util.c:62 logsrvd/logsrvd.c:302 logsrvd/logsrvd.c:311
+#: logsrvd/logsrvd.c:1017 logsrvd/logsrvd.c:1079 logsrvd/logsrvd_conf.c:1361
+#: logsrvd/logsrvd_journal.c:71 logsrvd/logsrvd_journal.c:204
+#: logsrvd/logsrvd_journal.c:205 logsrvd/logsrvd_journal.c:261
+#: logsrvd/logsrvd_journal.c:426 logsrvd/logsrvd_journal.c:428
+#: logsrvd/logsrvd_local.c:173 logsrvd/logsrvd_local.c:174
+#: logsrvd/logsrvd_local.c:236 logsrvd/logsrvd_local.c:237
+#: logsrvd/logsrvd_local.c:317 logsrvd/logsrvd_local.c:318
+#: logsrvd/logsrvd_local.c:323 logsrvd/logsrvd_local.c:324
+#: logsrvd/logsrvd_queue.c:155 logsrvd/logsrvd_queue.c:185
+#: logsrvd/logsrvd_queue.c:262 logsrvd/logsrvd_relay.c:445
+#: logsrvd/logsrvd_relay.c:744 logsrvd/logsrvd_relay.c:846
+#: logsrvd/sendlog.c:302 logsrvd/sendlog.c:501 plugins/sudoers/audit.c:114
+#: plugins/sudoers/audit.c:271 plugins/sudoers/auth/bsdauth.c:143
+#: plugins/sudoers/auth/kerb5.c:118 plugins/sudoers/auth/kerb5.c:144
+#: plugins/sudoers/auth/pam.c:691 plugins/sudoers/auth/rfc1938.c:111
+#: plugins/sudoers/auth/sia.c:59 plugins/sudoers/check_aliases.c:95
+#: plugins/sudoers/cvtsudoers.c:119 plugins/sudoers/cvtsudoers.c:160
+#: plugins/sudoers/cvtsudoers.c:177 plugins/sudoers/cvtsudoers.c:188
+#: plugins/sudoers/cvtsudoers.c:300 plugins/sudoers/cvtsudoers.c:428
+#: plugins/sudoers/cvtsudoers.c:561 plugins/sudoers/cvtsudoers.c:578
+#: plugins/sudoers/cvtsudoers.c:646 plugins/sudoers/cvtsudoers.c:761
+#: plugins/sudoers/cvtsudoers.c:769 plugins/sudoers/cvtsudoers.c:1183
+#: plugins/sudoers/cvtsudoers.c:1187 plugins/sudoers/cvtsudoers.c:1289
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:151
+#: plugins/sudoers/cvtsudoers_ldif.c:194 plugins/sudoers/cvtsudoers_ldif.c:235
+#: plugins/sudoers/cvtsudoers_ldif.c:300 plugins/sudoers/cvtsudoers_ldif.c:371
+#: plugins/sudoers/cvtsudoers_ldif.c:425 plugins/sudoers/cvtsudoers_ldif.c:433
+#: plugins/sudoers/cvtsudoers_ldif.c:444 plugins/sudoers/cvtsudoers_ldif.c:451
+#: plugins/sudoers/cvtsudoers_ldif.c:464 plugins/sudoers/cvtsudoers_ldif.c:472
+#: plugins/sudoers/cvtsudoers_ldif.c:619 plugins/sudoers/defaults.c:652
+#: plugins/sudoers/defaults.c:947 plugins/sudoers/defaults.c:1122
+#: plugins/sudoers/editor.c:190 plugins/sudoers/env.c:262
+#: plugins/sudoers/exptilde.c:92 plugins/sudoers/filedigest.c:54
+#: plugins/sudoers/filedigest.c:70 plugins/sudoers/gc.c:57
+#: plugins/sudoers/group_plugin.c:133 plugins/sudoers/interfaces.c:68
+#: plugins/sudoers/iolog.c:606 plugins/sudoers/iolog.c:623
+#: plugins/sudoers/ldap.c:184 plugins/sudoers/ldap.c:422
+#: plugins/sudoers/ldap.c:432 plugins/sudoers/ldap.c:437
+#: plugins/sudoers/ldap.c:441 plugins/sudoers/ldap.c:453
+#: plugins/sudoers/ldap.c:744 plugins/sudoers/ldap.c:908
+#: plugins/sudoers/ldap.c:1281 plugins/sudoers/ldap.c:1709
+#: plugins/sudoers/ldap.c:1746 plugins/sudoers/ldap.c:1827
+#: plugins/sudoers/ldap.c:1962 plugins/sudoers/ldap.c:2063
+#: plugins/sudoers/ldap.c:2079 plugins/sudoers/ldap_conf.c:218
+#: plugins/sudoers/ldap_conf.c:249 plugins/sudoers/ldap_conf.c:301
+#: plugins/sudoers/ldap_conf.c:337 plugins/sudoers/ldap_conf.c:441
+#: plugins/sudoers/ldap_conf.c:456 plugins/sudoers/ldap_conf.c:553
+#: plugins/sudoers/ldap_conf.c:586 plugins/sudoers/ldap_conf.c:678
+#: plugins/sudoers/ldap_conf.c:760 plugins/sudoers/ldap_util.c:293
+#: plugins/sudoers/ldap_util.c:300 plugins/sudoers/ldap_util.c:615
+#: plugins/sudoers/linux_audit.c:86 plugins/sudoers/log_client.c:108
+#: plugins/sudoers/log_client.c:386 plugins/sudoers/log_client.c:699
+#: plugins/sudoers/log_client.c:720 plugins/sudoers/log_client.c:1440
+#: plugins/sudoers/log_client.c:1656 plugins/sudoers/log_client.c:1980
+#: plugins/sudoers/log_client.c:2037 plugins/sudoers/logging.c:101
+#: plugins/sudoers/logging.c:181 plugins/sudoers/logging.c:465
+#: plugins/sudoers/logging.c:485 plugins/sudoers/logging.c:627
+#: plugins/sudoers/match_command.c:297 plugins/sudoers/match_command.c:497
+#: plugins/sudoers/match_command.c:546 plugins/sudoers/match_command.c:618
+#: plugins/sudoers/match_command.c:666 plugins/sudoers/match_digest.c:93
+#: plugins/sudoers/parse.c:201 plugins/sudoers/parse.c:218
+#: plugins/sudoers/parse.c:238 plugins/sudoers/parse.c:255
+#: plugins/sudoers/parse.c:278 plugins/sudoers/parse.c:289
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:260
+#: plugins/sudoers/parse_ldif.c:265 plugins/sudoers/parse_ldif.c:341
+#: plugins/sudoers/parse_ldif.c:352 plugins/sudoers/parse_ldif.c:379
+#: plugins/sudoers/parse_ldif.c:396 plugins/sudoers/parse_ldif.c:408
+#: plugins/sudoers/parse_ldif.c:412 plugins/sudoers/parse_ldif.c:426
+#: plugins/sudoers/parse_ldif.c:483 plugins/sudoers/parse_ldif.c:596
+#: plugins/sudoers/parse_ldif.c:626 plugins/sudoers/parse_ldif.c:651
+#: plugins/sudoers/parse_ldif.c:709 plugins/sudoers/parse_ldif.c:726
+#: plugins/sudoers/parse_ldif.c:754 plugins/sudoers/parse_ldif.c:761
+#: plugins/sudoers/policy.c:556 plugins/sudoers/policy.c:923
+#: plugins/sudoers/prompt.c:93 plugins/sudoers/pwutil.c:195
+#: plugins/sudoers/pwutil.c:266 plugins/sudoers/pwutil.c:344
+#: plugins/sudoers/pwutil.c:518 plugins/sudoers/pwutil.c:583
+#: plugins/sudoers/pwutil.c:655 plugins/sudoers/pwutil.c:853
+#: plugins/sudoers/pwutil.c:909 plugins/sudoers/pwutil.c:953
+#: plugins/sudoers/pwutil.c:1010 plugins/sudoers/sssd.c:145
+#: plugins/sudoers/sssd.c:407 plugins/sudoers/sssd.c:470
+#: plugins/sudoers/sssd.c:514 plugins/sudoers/sssd.c:561
+#: plugins/sudoers/sssd.c:754 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/stubs.c:111 plugins/sudoers/stubs.c:119
+#: plugins/sudoers/sudoers.c:335 plugins/sudoers/sudoers.c:361
+#: plugins/sudoers/sudoers.c:429 plugins/sudoers/sudoers.c:438
+#: plugins/sudoers/sudoers.c:479 plugins/sudoers/sudoers.c:833
+#: plugins/sudoers/sudoers.c:971 plugins/sudoers/sudoers.c:1030
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:565 plugins/sudoers/sudoreplay.c:1280
+#: plugins/sudoers/sudoreplay.c:1490 plugins/sudoers/sudoreplay.c:1494
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:224
+#: plugins/sudoers/testsudoers.c:241 plugins/sudoers/testsudoers.c:580
+#: plugins/sudoers/timestamp.c:424 plugins/sudoers/timestamp.c:468
+#: plugins/sudoers/timestamp.c:980 plugins/sudoers/timestamp.c:1118
+#: plugins/sudoers/toke_util.c:77 plugins/sudoers/toke_util.c:105
+#: plugins/sudoers/toke_util.c:130 plugins/sudoers/toke_util.c:155
+#: plugins/sudoers/toke_util.c:193 plugins/sudoers/tsdump.c:123
+#: plugins/sudoers/visudo.c:143 plugins/sudoers/visudo.c:321
+#: plugins/sudoers/visudo.c:327 plugins/sudoers/visudo.c:433
+#: plugins/sudoers/visudo.c:609 plugins/sudoers/visudo.c:926
+#: plugins/sudoers/visudo.c:999 toke.l:938 toke.l:1067 toke.l:1127
+msgid "unable to allocate memory"
+msgstr "impossível alocar memória"
+
+#: gram.y:617
+msgid "a digest requires a path name"
+msgstr "um resumo requer um nome de caminho"
+
+#: gram.y:639
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "valores para \"CWD\" têm de começar por '/', '~' ou '*'"
+
+#: gram.y:651
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "valores para \"CHROOT\" têm de começar com \"/\", \"~\" ou \"*\""
+
+#: gram.y:782
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "erro de sintaxe, palavra reservada %s utilizada como nome aliás"
+
+#: gram.y:805
+msgid "invalid notbefore value"
+msgstr "valor notbefore inválido"
+
+#: gram.y:814
+msgid "invalid notafter value"
+msgstr "valor notafter inválido"
+
+#: gram.y:824 plugins/sudoers/policy.c:345
+msgid "timeout value too large"
+msgstr "valor de inacção muito grande"
+
+#: gram.y:826 plugins/sudoers/policy.c:347
+msgid "invalid timeout value"
+msgstr "valor de inacção inválido"
+
+#: gram.y:1193
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: gram.y:1237
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Aliás \"%s\" já definido"
+
+#: gram.y:1658 gram.y:1708 lib/eventlog/eventlog.c:308
+#: lib/eventlog/eventlog.c:783 lib/eventlog/eventlog.c:858
+#: lib/eventlog/eventlog.c:861 lib/eventlog/eventlog.c:1146
+#: lib/iolog/iolog_json.c:125 lib/iolog/iolog_json.c:329
+#: lib/iolog/iolog_json.c:360 lib/iolog/iolog_json.c:503
+#: lib/iolog/iolog_legacy.c:100 lib/iolog/iolog_legacy.c:111
+#: lib/iolog/iolog_legacy.c:123 lib/iolog/iolog_legacy.c:133
+#: lib/iolog/iolog_legacy.c:139 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:210 logsrvd/iolog_writer.c:85
+#: logsrvd/iolog_writer.c:90 logsrvd/iolog_writer.c:124
+#: logsrvd/iolog_writer.c:162 logsrvd/iolog_writer.c:171
+#: logsrvd/iolog_writer.c:189 logsrvd/iolog_writer.c:211
+#: logsrvd/iolog_writer.c:224 logsrvd/iolog_writer.c:251
+#: logsrvd/iolog_writer.c:260 logsrvd/iolog_writer.c:276
+#: logsrvd/iolog_writer.c:285 logsrvd/iolog_writer.c:300
+#: logsrvd/iolog_writer.c:313 logsrvd/iolog_writer.c:326
+#: logsrvd/iolog_writer.c:339 logsrvd/iolog_writer.c:354
+#: logsrvd/iolog_writer.c:393 logsrvd/iolog_writer.c:399
+#: logsrvd/iolog_writer.c:406 logsrvd/iolog_writer.c:412
+#: logsrvd/iolog_writer.c:596 logsrvd/logsrv_util.c:62 logsrvd/logsrvd.c:302
+#: logsrvd/logsrvd.c:311 logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:491
+#: logsrvd/logsrvd.c:599 logsrvd/logsrvd.c:1090 logsrvd/logsrvd.c:1402
+#: logsrvd/logsrvd.c:1408 logsrvd/logsrvd_conf.c:1361
+#: logsrvd/logsrvd_journal.c:71 logsrvd/logsrvd_journal.c:115
+#: logsrvd/logsrvd_journal.c:204 logsrvd/logsrvd_journal.c:234
+#: logsrvd/logsrvd_journal.c:238 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:269 logsrvd/logsrvd_journal.c:273
+#: logsrvd/logsrvd_journal.c:426 logsrvd/logsrvd_local.c:173
+#: logsrvd/logsrvd_local.c:236 logsrvd/logsrvd_local.c:317
+#: logsrvd/logsrvd_local.c:323 logsrvd/logsrvd_local.c:342
+#: logsrvd/logsrvd_queue.c:154 logsrvd/logsrvd_queue.c:185
+#: logsrvd/logsrvd_queue.c:262 logsrvd/sendlog.c:302 logsrvd/sendlog.c:501
+#: logsrvd/sendlog.c:1353 logsrvd/sendlog.c:1360 logsrvd/sendlog.c:1563
+#: logsrvd/tls_init.c:218 logsrvd/tls_init.c:239 logsrvd/tls_init.c:249
+#: plugins/sudoers/audit.c:114 plugins/sudoers/audit.c:271
+#: plugins/sudoers/auth/pam.c:505 plugins/sudoers/auth/pam.c:691
+#: plugins/sudoers/auth/rfc1938.c:111 plugins/sudoers/check_aliases.c:95
+#: plugins/sudoers/cvtsudoers.c:119 plugins/sudoers/cvtsudoers.c:159
+#: plugins/sudoers/cvtsudoers.c:176 plugins/sudoers/cvtsudoers.c:187
+#: plugins/sudoers/cvtsudoers.c:299 plugins/sudoers/cvtsudoers.c:427
+#: plugins/sudoers/cvtsudoers.c:560 plugins/sudoers/cvtsudoers.c:577
+#: plugins/sudoers/cvtsudoers.c:646 plugins/sudoers/cvtsudoers.c:761
+#: plugins/sudoers/cvtsudoers.c:768 plugins/sudoers/cvtsudoers.c:1183
+#: plugins/sudoers/cvtsudoers.c:1187 plugins/sudoers/cvtsudoers.c:1289
+#: plugins/sudoers/cvtsudoers_json.c:75 plugins/sudoers/cvtsudoers_ldif.c:150
+#: plugins/sudoers/cvtsudoers_ldif.c:193 plugins/sudoers/cvtsudoers_ldif.c:234
+#: plugins/sudoers/cvtsudoers_ldif.c:299 plugins/sudoers/cvtsudoers_ldif.c:370
+#: plugins/sudoers/cvtsudoers_ldif.c:424 plugins/sudoers/cvtsudoers_ldif.c:432
+#: plugins/sudoers/cvtsudoers_ldif.c:443 plugins/sudoers/cvtsudoers_ldif.c:450
+#: plugins/sudoers/cvtsudoers_ldif.c:463 plugins/sudoers/cvtsudoers_ldif.c:471
+#: plugins/sudoers/cvtsudoers_ldif.c:618 plugins/sudoers/defaults.c:652
+#: plugins/sudoers/defaults.c:947 plugins/sudoers/defaults.c:1122
+#: plugins/sudoers/editor.c:190 plugins/sudoers/env.c:262
+#: plugins/sudoers/exptilde.c:92 plugins/sudoers/filedigest.c:54
+#: plugins/sudoers/filedigest.c:70 plugins/sudoers/gc.c:57
+#: plugins/sudoers/group_plugin.c:132 plugins/sudoers/interfaces.c:68
+#: plugins/sudoers/iolog.c:606 plugins/sudoers/iolog.c:623
+#: plugins/sudoers/ldap.c:184 plugins/sudoers/ldap.c:422
+#: plugins/sudoers/ldap.c:432 plugins/sudoers/ldap.c:437
+#: plugins/sudoers/ldap.c:441 plugins/sudoers/ldap.c:453
+#: plugins/sudoers/ldap.c:744 plugins/sudoers/ldap.c:908
+#: plugins/sudoers/ldap.c:1281 plugins/sudoers/ldap.c:1709
+#: plugins/sudoers/ldap.c:1746 plugins/sudoers/ldap.c:1827
+#: plugins/sudoers/ldap.c:1962 plugins/sudoers/ldap.c:2063
+#: plugins/sudoers/ldap.c:2079 plugins/sudoers/ldap_conf.c:218
+#: plugins/sudoers/ldap_conf.c:249 plugins/sudoers/ldap_conf.c:301
+#: plugins/sudoers/ldap_conf.c:337 plugins/sudoers/ldap_conf.c:441
+#: plugins/sudoers/ldap_conf.c:456 plugins/sudoers/ldap_conf.c:553
+#: plugins/sudoers/ldap_conf.c:586 plugins/sudoers/ldap_conf.c:677
+#: plugins/sudoers/ldap_conf.c:760 plugins/sudoers/ldap_util.c:292
+#: plugins/sudoers/ldap_util.c:299 plugins/sudoers/ldap_util.c:615
+#: plugins/sudoers/linux_audit.c:86 plugins/sudoers/log_client.c:108
+#: plugins/sudoers/log_client.c:217 plugins/sudoers/log_client.c:238
+#: plugins/sudoers/log_client.c:251 plugins/sudoers/log_client.c:386
+#: plugins/sudoers/log_client.c:699 plugins/sudoers/log_client.c:720
+#: plugins/sudoers/log_client.c:1440 plugins/sudoers/log_client.c:1656
+#: plugins/sudoers/log_client.c:1980 plugins/sudoers/log_client.c:2037
+#: plugins/sudoers/logging.c:101 plugins/sudoers/logging.c:180
+#: plugins/sudoers/logging.c:181 plugins/sudoers/logging.c:464
+#: plugins/sudoers/logging.c:484 plugins/sudoers/logging.c:627
+#: plugins/sudoers/match_command.c:296 plugins/sudoers/match_command.c:496
+#: plugins/sudoers/match_command.c:545 plugins/sudoers/match_command.c:618
+#: plugins/sudoers/match_command.c:665 plugins/sudoers/match_digest.c:93
+#: plugins/sudoers/parse.c:200 plugins/sudoers/parse.c:217
+#: plugins/sudoers/parse.c:237 plugins/sudoers/parse.c:254
+#: plugins/sudoers/parse.c:277 plugins/sudoers/parse.c:288
+#: plugins/sudoers/parse_ldif.c:152 plugins/sudoers/parse_ldif.c:183
+#: plugins/sudoers/parse_ldif.c:252 plugins/sudoers/parse_ldif.c:259
+#: plugins/sudoers/parse_ldif.c:264 plugins/sudoers/parse_ldif.c:340
+#: plugins/sudoers/parse_ldif.c:351 plugins/sudoers/parse_ldif.c:378
+#: plugins/sudoers/parse_ldif.c:395 plugins/sudoers/parse_ldif.c:407
+#: plugins/sudoers/parse_ldif.c:411 plugins/sudoers/parse_ldif.c:425
+#: plugins/sudoers/parse_ldif.c:483 plugins/sudoers/parse_ldif.c:596
+#: plugins/sudoers/parse_ldif.c:625 plugins/sudoers/parse_ldif.c:650
+#: plugins/sudoers/parse_ldif.c:708 plugins/sudoers/parse_ldif.c:725
+#: plugins/sudoers/parse_ldif.c:753 plugins/sudoers/parse_ldif.c:760
+#: plugins/sudoers/policy.c:152 plugins/sudoers/policy.c:161
+#: plugins/sudoers/policy.c:170 plugins/sudoers/policy.c:197
+#: plugins/sudoers/policy.c:330 plugins/sudoers/policy.c:345
+#: plugins/sudoers/policy.c:347 plugins/sudoers/policy.c:377
+#: plugins/sudoers/policy.c:386 plugins/sudoers/policy.c:434
+#: plugins/sudoers/policy.c:444 plugins/sudoers/policy.c:453
+#: plugins/sudoers/policy.c:462 plugins/sudoers/policy.c:556
+#: plugins/sudoers/policy.c:923 plugins/sudoers/prompt.c:93
+#: plugins/sudoers/pwutil.c:195 plugins/sudoers/pwutil.c:266
+#: plugins/sudoers/pwutil.c:344 plugins/sudoers/pwutil.c:518
+#: plugins/sudoers/pwutil.c:583 plugins/sudoers/pwutil.c:655
+#: plugins/sudoers/pwutil.c:853 plugins/sudoers/pwutil.c:909
+#: plugins/sudoers/pwutil.c:953 plugins/sudoers/pwutil.c:1010
+#: plugins/sudoers/set_perms.c:363 plugins/sudoers/set_perms.c:706
+#: plugins/sudoers/set_perms.c:1073 plugins/sudoers/set_perms.c:1380
+#: plugins/sudoers/set_perms.c:1549 plugins/sudoers/sssd.c:144
+#: plugins/sudoers/sssd.c:407 plugins/sudoers/sssd.c:470
+#: plugins/sudoers/sssd.c:514 plugins/sudoers/sssd.c:561
+#: plugins/sudoers/sssd.c:754 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/stubs.c:111 plugins/sudoers/stubs.c:119
+#: plugins/sudoers/sudoers.c:335 plugins/sudoers/sudoers.c:361
+#: plugins/sudoers/sudoers.c:429 plugins/sudoers/sudoers.c:438
+#: plugins/sudoers/sudoers.c:479 plugins/sudoers/sudoers.c:833
+#: plugins/sudoers/sudoers.c:971 plugins/sudoers/sudoers.c:1030
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:565 plugins/sudoers/sudoreplay.c:1280
+#: plugins/sudoers/sudoreplay.c:1490 plugins/sudoers/sudoreplay.c:1494
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:224
+#: plugins/sudoers/testsudoers.c:241 plugins/sudoers/testsudoers.c:580
+#: plugins/sudoers/timestamp.c:424 plugins/sudoers/timestamp.c:468
+#: plugins/sudoers/timestamp.c:980 plugins/sudoers/timestamp.c:1118
+#: plugins/sudoers/toke_util.c:77 plugins/sudoers/toke_util.c:105
+#: plugins/sudoers/toke_util.c:130 plugins/sudoers/toke_util.c:154
+#: plugins/sudoers/toke_util.c:193 plugins/sudoers/tsdump.c:123
+#: plugins/sudoers/visudo.c:143 plugins/sudoers/visudo.c:321
+#: plugins/sudoers/visudo.c:327 plugins/sudoers/visudo.c:433
+#: plugins/sudoers/visudo.c:609 plugins/sudoers/visudo.c:926
+#: plugins/sudoers/visudo.c:999 toke.l:938 toke.l:1067 toke.l:1119 toke.l:1127
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:313 lib/iolog/iolog_json.c:509
+#: lib/iolog/iolog_json.c:512 lib/iolog/iolog_json.c:514
+#: plugins/sudoers/cvtsudoers_ldif.c:244 plugins/sudoers/cvtsudoers_ldif.c:251
+#: plugins/sudoers/cvtsudoers_ldif.c:575 plugins/sudoers/env.c:326
+#: plugins/sudoers/env.c:333 plugins/sudoers/env.c:444
+#: plugins/sudoers/iolog.c:628 plugins/sudoers/ldap.c:517
+#: plugins/sudoers/ldap.c:748 plugins/sudoers/ldap.c:1081
+#: plugins/sudoers/ldap_conf.c:222 plugins/sudoers/ldap_conf.c:312
+#: plugins/sudoers/linux_audit.c:92 plugins/sudoers/policy.c:586
+#: plugins/sudoers/policy.c:755 plugins/sudoers/policy.c:766
+#: plugins/sudoers/prompt.c:168 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/testsudoers.c:245 plugins/sudoers/toke_util.c:206
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "erro interno, transporte %s"
+
+#: lib/eventlog/eventlog.c:372
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "impossível duplicar stdin: %m"
+
+#: lib/eventlog/eventlog.c:414
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "impossível executar %s: %m"
+
+#: lib/eventlog/eventlog.c:455 plugins/sudoers/auth/aix_auth.c:198
+msgid "unable to fork"
+msgstr "impossível bifurcar"
+
+#: lib/eventlog/eventlog.c:463 lib/eventlog/eventlog.c:517
+#, c-format
+msgid "unable to fork: %m"
+msgstr "impossível bifurcar: %m"
+
+#: lib/eventlog/eventlog.c:507
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "impossível abrir túnel: %m"
+
+#: lib/eventlog/eventlog.c:979
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:1008
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (comando continuado) %s"
+
+#: lib/iolog/iolog_json.c:115
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "esperado JSON_STRING, obtido %d"
+
+#: lib/iolog/iolog_json.c:120
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY muito grande"
+
+#: lib/iolog/iolog_json.c:352
+msgid "missing double quote in name"
+msgstr "aspas dupla em falta no nome"
+
+#: lib/iolog/iolog_json.c:449
+msgid "missing JSON_OBJECT"
+msgstr "JSON_OBJECT em falta"
+
+#: lib/iolog/iolog_json.c:453
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "esperado JSON_OBJECT, obtido %d"
+
+#: lib/iolog/iolog_json.c:599
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "pilha json esgotada (máx. %u instâncias)"
+
+#: lib/iolog/iolog_json.c:673
+msgid "objects must consist of name:value pairs"
+msgstr "os objectos têm de consistir em pares name:value"
+
+#: lib/iolog/iolog_json.c:678 lib/iolog/iolog_json.c:709
+#: lib/iolog/iolog_json.c:753 lib/iolog/iolog_json.c:775
+#: lib/iolog/iolog_json.c:797 lib/iolog/iolog_json.c:819
+#: lib/iolog/iolog_json.c:841
+msgid "missing separator between values"
+msgstr "separador em falta entre valores"
+
+#: lib/iolog/iolog_json.c:693 lib/iolog/iolog_json.c:867
+msgid "unmatched close brace"
+msgstr "chaveta esquerda sem par"
+
+#: lib/iolog/iolog_json.c:704
+msgid "unexpected array"
+msgstr "matriz inesperada"
+
+#: lib/iolog/iolog_json.c:724 lib/iolog/iolog_json.c:870
+msgid "unmatched close bracket"
+msgstr "parêntese recto sem par"
+
+#: lib/iolog/iolog_json.c:735
+msgid "unexpected string"
+msgstr "cadeia inesperada"
+
+#: lib/iolog/iolog_json.c:746
+msgid "missing colon after name"
+msgstr "dois pontos em falta após o nome"
+
+#: lib/iolog/iolog_json.c:767 lib/iolog/iolog_json.c:789
+msgid "unexpected boolean"
+msgstr "booleano inesperado"
+
+#: lib/iolog/iolog_json.c:811
+msgid "unexpected null"
+msgstr "nulo inesperado"
+
+#: lib/iolog/iolog_json.c:832
+msgid "unexpected number"
+msgstr "número inesperado"
+
+#: lib/iolog/iolog_json.c:879
+msgid "parse error"
+msgstr "erro de análise"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: ficheiro de diário inválido"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: campo de datação em falta"
+
+#: lib/iolog/iolog_legacy.c:89
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: datação %s: %s"
+
+#: lib/iolog/iolog_legacy.c:96
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: campo de utilizador em falta"
+
+#: lib/iolog/iolog_legacy.c:107
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: campo de utilizador runas em falta"
+
+#: lib/iolog/iolog_legacy.c:118
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: campo de grupo runas em falta"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s existe mas não é uma pasta (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:119 lib/iolog/iolog_mkdtemp.c:77
+#: logsrvd/iolog_writer.c:788 plugins/sudoers/timestamp.c:205
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "impossível criar pasta %s"
+
+#: lib/iolog/iolog_mkdtemp.c:81 plugins/sudoers/visudo.c:726
+#: plugins/sudoers/visudo.c:737
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "impossível alterar o modo de %s para 0%o"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "erro ao ler ficheiro de temporização: %s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "linha de ficheiro de temporização inválida : %s"
+
+#: logsrvd/iolog_writer.c:131 plugins/sudoers/logging.c:803
+#: plugins/sudoers/policy.c:536
+msgid "unable to generate UUID"
+msgstr "impossível gerar UUID"
+
+#: logsrvd/iolog_writer.c:158 logsrvd/iolog_writer.c:176
+#: logsrvd/iolog_writer.c:185 logsrvd/iolog_writer.c:203
+#: logsrvd/iolog_writer.c:216 logsrvd/iolog_writer.c:229
+#: logsrvd/iolog_writer.c:240 logsrvd/iolog_writer.c:247
+#: logsrvd/iolog_writer.c:265 logsrvd/iolog_writer.c:272
+#: logsrvd/iolog_writer.c:290 logsrvd/iolog_writer.c:305
+#: logsrvd/iolog_writer.c:318 logsrvd/iolog_writer.c:331
+#: logsrvd/iolog_writer.c:344 logsrvd/iolog_writer.c:359
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s: erro de protocolo: tipo errado para %s"
+
+#: logsrvd/iolog_writer.c:370 logsrvd/iolog_writer.c:375
+#: logsrvd/iolog_writer.c:380 logsrvd/iolog_writer.c:385
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s: erro de protocolo: %s em falta de AcceptMessage"
+
+#: logsrvd/iolog_writer.c:446
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s: impossível formatar a id da sessão"
+
+#: logsrvd/iolog_writer.c:460 logsrvd/iolog_writer.c:474
+#: logsrvd/iolog_writer.c:488 logsrvd/iolog_writer.c:503
+#: logsrvd/iolog_writer.c:517 logsrvd/iolog_writer.c:531
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s: %s não está definido"
+
+#: logsrvd/iolog_writer.c:567 logsrvd/iolog_writer.c:574
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr "impossível expandir caminho iolog %s"
+
+#: logsrvd/iolog_writer.c:592
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr "impossível criar caminho iolog %s"
+
+#: logsrvd/iolog_writer.c:622
+#, c-format
+msgid "invalid iofd %d"
+msgstr "iofd %d inválido"
+
+#: logsrvd/iolog_writer.c:642
+#, c-format
+msgid "error closing iofd %d: %s"
+msgstr "erro ao fechar iofd %d: %s"
+
+#: logsrvd/iolog_writer.c:758
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "Diario de E/S %s inválido: %s referenciado mas ausente"
+
+#: logsrvd/iolog_writer.c:770 logsrvd/logsrvd_journal.c:378
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "%s: impossível encontrar ponto de recomeço [%lld, %ld]"
+
+#: logsrvd/iolog_writer.c:792 logsrvd/logsrvd_journal.c:421
+#: logsrvd/logsrvd_queue.c:111 logsrvd/tls_init.c:293
+#: plugins/sudoers/check.c:274 plugins/sudoers/cvtsudoers.c:618
+#: plugins/sudoers/cvtsudoers.c:639 plugins/sudoers/cvtsudoers.c:1249
+#: plugins/sudoers/cvtsudoers_json.c:877 plugins/sudoers/cvtsudoers_ldif.c:692
+#: plugins/sudoers/sudoers.c:1083 plugins/sudoers/sudoreplay.c:1456
+#: plugins/sudoers/timestamp.c:433 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:913
+#, c-format
+msgid "unable to open %s"
+msgstr "impossível abrir %s"
+
+#: logsrvd/iolog_writer.c:804 logsrvd/logsrv_util.c:98
+#: logsrvd/logsrv_util.c:105 plugins/sudoers/sudoreplay.c:362
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "impossível abrir %s/%s"
+
+#: logsrvd/iolog_writer.c:817
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "impossível copiar %s/%s para %s/%s: %s"
+
+#: logsrvd/iolog_writer.c:846 logsrvd/logsrvd_journal.c:186
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "impossível renomear %s como %s"
+
+#: logsrvd/logsrv_util.c:132
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "ficheiro de diário E/S %s/%s em falta"
+
+#: logsrvd/logsrv_util.c:139
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s: impossível procurar adiante %zu"
+
+#: logsrvd/logsrv_util.c:149
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s: impossível encontrar ponto de recomeço [%lld, %ld]"
+
+#: logsrvd/logsrvd.c:272 logsrvd/logsrvd_queue.c:131
+msgid "unable to connect to relay"
+msgstr "impossível ligar ao relé"
+
+#: logsrvd/logsrvd.c:331 logsrvd/logsrvd_relay.c:838
+#, c-format
+msgid "server message too large: %zu"
+msgstr "mensagem do servidor muito grande: %zu"
+
+#: logsrvd/logsrvd.c:423 logsrvd/logsrvd.c:540 logsrvd/logsrvd.c:619
+#: logsrvd/logsrvd.c:843 logsrvd/logsrvd.c:857 logsrvd/logsrvd.c:1016
+#: logsrvd/logsrvd.c:1140 logsrvd/logsrvd.c:1309 logsrvd/logsrvd.c:1327
+#: logsrvd/logsrvd.c:1425 logsrvd/logsrvd.c:1548 logsrvd/logsrvd.c:1732
+#: logsrvd/logsrvd_journal.c:485 logsrvd/logsrvd_local.c:196
+#: logsrvd/logsrvd_queue.c:160 logsrvd/logsrvd_relay.c:173
+#: logsrvd/logsrvd_relay.c:250 logsrvd/logsrvd_relay.c:254
+#: logsrvd/logsrvd_relay.c:390 logsrvd/logsrvd_relay.c:582
+#: logsrvd/logsrvd_relay.c:743 logsrvd/logsrvd_relay.c:1124
+#: logsrvd/sendlog.c:1156 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:214 plugins/sudoers/audit.c:281
+#: plugins/sudoers/iolog.c:966 plugins/sudoers/iolog.c:1099
+#: plugins/sudoers/iolog.c:1197 plugins/sudoers/log_client.c:112
+#: plugins/sudoers/log_client.c:328 plugins/sudoers/log_client.c:344
+#: plugins/sudoers/log_client.c:391 plugins/sudoers/log_client.c:595
+#: plugins/sudoers/log_client.c:602 plugins/sudoers/log_client.c:1127
+#: plugins/sudoers/log_client.c:1409 plugins/sudoers/log_client.c:1450
+#: plugins/sudoers/log_client.c:1458 plugins/sudoers/log_client.c:1612
+#: plugins/sudoers/log_client.c:1728 plugins/sudoers/log_client.c:2045
+#: plugins/sudoers/log_client.c:2053 plugins/sudoers/logging.c:139
+#: plugins/sudoers/logging.c:195 plugins/sudoers/sudoreplay.c:522
+#: plugins/sudoers/sudoreplay.c:569 plugins/sudoers/sudoreplay.c:811
+#: plugins/sudoers/sudoreplay.c:923 plugins/sudoers/sudoreplay.c:1014
+#: plugins/sudoers/sudoreplay.c:1029 plugins/sudoers/sudoreplay.c:1036
+#: plugins/sudoers/sudoreplay.c:1043 plugins/sudoers/sudoreplay.c:1050
+#: plugins/sudoers/sudoreplay.c:1057 plugins/sudoers/sudoreplay.c:1184
+msgid "unable to add event to queue"
+msgstr "impossível adicionar evento à fila"
+
+#: logsrvd/logsrvd.c:447 logsrvd/logsrvd.c:484 logsrvd/logsrvd.c:516
+#: logsrvd/logsrvd.c:564 logsrvd/logsrvd.c:636 logsrvd/logsrvd.c:666
+#: logsrvd/logsrvd.c:696 logsrvd/logsrvd.c:726 logsrvd/logsrvd_relay.c:511
+#: logsrvd/logsrvd_relay.c:544
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr "estado %d inesperado para %s"
+
+#: logsrvd/logsrvd.c:448 logsrvd/logsrvd.c:485 logsrvd/logsrvd.c:517
+#: logsrvd/logsrvd.c:565 logsrvd/logsrvd.c:637 logsrvd/logsrvd.c:667
+#: logsrvd/logsrvd.c:697 logsrvd/logsrvd.c:727 logsrvd/logsrvd_relay.c:513
+#: logsrvd/logsrvd_relay.c:546
+msgid "state machine error"
+msgstr "erro da máquina de estado"
+
+#: logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:455
+msgid "invalid AcceptMessage"
+msgstr "AcceptMessage inválida"
+
+#: logsrvd/logsrvd.c:491 logsrvd/logsrvd.c:492
+msgid "invalid RejectMessage"
+msgstr "RejectMessage inválida"
+
+#: logsrvd/logsrvd.c:599 logsrvd/logsrvd.c:600
+msgid "invalid AlertMessage"
+msgstr "AlertMessage inválida"
+
+#: logsrvd/logsrvd.c:641 logsrvd/logsrvd.c:671 logsrvd/logsrvd.c:701
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s: IoBuffer inesperado"
+
+#: logsrvd/logsrvd.c:642 logsrvd/logsrvd.c:672 logsrvd/logsrvd.c:702
+msgid "protocol error"
+msgstr "erro de protocolo"
+
+#: logsrvd/logsrvd.c:797 logsrvd/logsrvd_journal.c:358
+#: logsrvd/logsrvd_local.c:125 logsrvd/logsrvd_relay.c:677
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "valor type_case %d inesperado em %s de %s"
+
+#: logsrvd/logsrvd.c:799
+msgid "unrecognized ClientMessage type"
+msgstr "tipo de ClientMessage não reconhecido"
+
+#: logsrvd/logsrvd.c:889
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "expirou ao escrever no cliente %s"
+
+#: logsrvd/logsrvd.c:894 logsrvd/logsrvd_relay.c:910
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr "buffer de escrita em falta para o cliente %s"
+
+#: logsrvd/logsrvd.c:987
+#, c-format
+msgid "timed out reading from client %s"
+msgstr "expirou ao ler do cliente %s"
+
+#: logsrvd/logsrvd.c:1028 logsrvd/logsrvd_relay.c:774
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr "EOF de %s sem encerramento apropriado de TLS"
+
+#: logsrvd/logsrvd.c:1071 logsrvd/logsrvd_relay.c:206 logsrvd/sendlog.c:290
+#: plugins/sudoers/log_client.c:705
+#, c-format
+msgid "client message too large: %zu"
+msgstr "mensagem do cliente muito grande: %zu"
+
+#: logsrvd/logsrvd.c:1072 logsrvd/logsrvd_journal.c:247
+#: logsrvd/logsrvd_journal.c:248
+msgid "client message too large"
+msgstr "mensagem do cliente muito grande"
+
+#: logsrvd/logsrvd.c:1090 logsrvd/logsrvd.c:1091
+msgid "invalid ClientMessage"
+msgstr "ClientMessage inválida"
+
+#: logsrvd/logsrvd.c:1388
+msgid "unable to get remote IP addr"
+msgstr "impossível obter endereço IP remoto"
+
+#: logsrvd/logsrvd.c:1417 logsrvd/tls_client.c:201
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "Impossível anexar dados do utilizador ao objecto ssl: %s"
+
+#: logsrvd/logsrvd.c:1598 logsrvd/logsrvd.c:1951
+msgid "unable to setup listen socket"
+msgstr "impossível definir o socket de escuta"
+
+#: logsrvd/logsrvd.c:1715
+#, c-format
+msgid "unexpected signal %d"
+msgstr "sinal %d inesperado"
+
+#: logsrvd/logsrvd.c:1853
+msgid "sudo log server"
+msgstr "servidor de diário sudo"
+
+#: logsrvd/logsrvd.c:1855 logsrvd/sendlog.c:122
+msgid "Options:"
+msgstr "Opções:"
+
+#: logsrvd/logsrvd.c:1857
+msgid "path to configuration file"
+msgstr "caminho do ficheiro de configuração"
+
+#: logsrvd/logsrvd.c:1859 logsrvd/sendlog.c:124
+msgid "display help message and exit"
+msgstr "mostrar mensagem de ajuda e sair"
+
+#: logsrvd/logsrvd.c:1861
+msgid "do not fork, run in the foreground"
+msgstr "não bifurcar, executar em 2º plano"
+
+#: logsrvd/logsrvd.c:1863
+msgid "percent chance connections will drop"
+msgstr "probabilidade das ligações caírem"
+
+#: logsrvd/logsrvd.c:1865 logsrvd/sendlog.c:154
+msgid "display version information and exit"
+msgstr "mostrar informação da versão e sair"
+
+#: logsrvd/logsrvd.c:1915 logsrvd/sendlog.c:1532
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "Requerida a versão Protobuf-C 1.3 ou superior"
+
+#: logsrvd/logsrvd.c:1931
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "valor de queda aleatório inválido: %s"
+
+#: logsrvd/logsrvd.c:1934 logsrvd/sendlog.c:1586
+#: plugins/sudoers/cvtsudoers.c:228 plugins/sudoers/sudoreplay.c:301
+#: plugins/sudoers/visudo.c:175
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s versão %s\n"
+
+#: logsrvd/logsrvd_conf.c:391 plugins/sudoers/check.c:336
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:115
+#: plugins/sudoers/policy.c:1159 plugins/sudoers/sudoers.c:486
+#: plugins/sudoers/sudoers.c:1338 plugins/sudoers/testsudoers.c:215
+#: plugins/sudoers/testsudoers.c:382
+#, c-format
+msgid "unknown user %s"
+msgstr "utilizador desconhecido %s"
+
+#: logsrvd/logsrvd_conf.c:408 plugins/sudoers/iolog.c:140
+#: plugins/sudoers/sudoers.c:491 plugins/sudoers/sudoers.c:1372
+#: plugins/sudoers/testsudoers.c:406
+#, c-format
+msgid "unknown group %s"
+msgstr "grupo desconhecido %s"
+
+#: logsrvd/logsrvd_conf.c:426
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr "impossível analisar modo iolog %s"
+
+#: logsrvd/logsrvd_conf.c:443 logsrvd/logsrvd_conf.c:1172
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "valor inválido para %s: %s"
+
+#: logsrvd/logsrvd_conf.c:482
+msgid "TLS not supported"
+msgstr "TLS não suportado"
+
+#: logsrvd/logsrvd_conf.c:504
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:577 logsrvd/logsrvd_conf.c:971
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s: não é um caminho completamente qualificado"
+
+#: logsrvd/logsrvd_conf.c:889 logsrvd/logsrvd_conf.c:905
+#: logsrvd/logsrvd_conf.c:1587
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "facilidade syslog desconhecida %s"
+
+#: logsrvd/logsrvd_conf.c:921 logsrvd/logsrvd_conf.c:937
+#: logsrvd/logsrvd_conf.c:953 logsrvd/logsrvd_conf.c:1591
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1599
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "prioridade syslog desconhecida %s"
+
+#: logsrvd/logsrvd_conf.c:1133
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d \"[\" sem par: %s"
+
+#: logsrvd/logsrvd_conf.c:1144
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s:%d secção de configuração inválida: %s"
+
+#: logsrvd/logsrvd_conf.c:1152
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d linha de configuração inválida: %s"
+
+#: logsrvd/logsrvd_conf.c:1158
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d esperado um nome de secção: %s"
+
+#: logsrvd/logsrvd_conf.c:1180
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] chave ilegal: %s"
+
+#: logsrvd/logsrvd_conf.c:1210 plugins/sudoers/logging.c:856
+#, c-format
+msgid "unable to open log file %s"
+msgstr "impossível abrir o diário %s"
+
+#: logsrvd/logsrvd_conf.c:1667
+msgid "unable to initialize server TLS context"
+msgstr "impossível inicializar contexto do servidor TLS"
+
+#: logsrvd/logsrvd_conf.c:1687
+msgid "unable to initialize relay TLS context"
+msgstr "impossível inicializar contexto do intermédio TLS"
+
+#: logsrvd/logsrvd_journal.c:137 logsrvd/logsrvd_journal.c:417
+#: logsrvd/logsrvd_journal.c:422
+msgid "unable to create journal file"
+msgstr "impossível criar o ficheiro de diário"
+
+#: logsrvd/logsrvd_journal.c:141 logsrvd/logsrvd_queue.c:105
+#: plugins/sudoers/visudo.c:971
+#, c-format
+msgid "unable to lock %s"
+msgstr "impossível bloquear %s"
+
+#: logsrvd/logsrvd_journal.c:144
+msgid "unable to lock journal file"
+msgstr "impossível bloquear o diário"
+
+#: logsrvd/logsrvd_journal.c:152
+msgid "unable to open journal file"
+msgstr "impossível abrir o ficheiro de diário"
+
+#: logsrvd/logsrvd_journal.c:173 logsrvd/logsrvd_journal.c:453
+#: logsrvd/logsrvd_journal.c:458
+msgid "unable to write journal file"
+msgstr "impossível escrever no diário"
+
+#: logsrvd/logsrvd_journal.c:181 logsrvd/logsrvd_journal.c:188
+msgid "unable to rename journal file"
+msgstr "impossível renomear o diário"
+
+#: logsrvd/logsrvd_journal.c:235 logsrvd/logsrvd_journal.c:236
+#: logsrvd/logsrvd_journal.c:270 logsrvd/logsrvd_journal.c:271
+msgid "unexpected EOF reading journal file"
+msgstr "EOF inesperado ao ler o diário"
+
+#: logsrvd/logsrvd_journal.c:239 logsrvd/logsrvd_journal.c:240
+#: logsrvd/logsrvd_journal.c:274 logsrvd/logsrvd_journal.c:275
+msgid "error reading journal file"
+msgstr "erro ao ler ficheiro de diário"
+
+#: logsrvd/logsrvd_journal.c:286 logsrvd/logsrvd_journal.c:377
+msgid "invalid journal file, unable to restart"
+msgstr "ficheiro de diário inválido, impossível reiniciar"
+
+#: logsrvd/logsrvd_journal.c:436
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "impossível localizar [%lld, %ld] no ficheiro de diário %s"
+
+#: logsrvd/logsrvd_local.c:152
+msgid "error parsing AcceptMessage"
+msgstr "erro ao analisar AcceptMessage"
+
+#: logsrvd/logsrvd_local.c:163
+msgid "error creating I/O log"
+msgstr "erro ao criar diário de E/S"
+
+#: logsrvd/logsrvd_local.c:186
+msgid "error logging accept event"
+msgstr "erro ao registar evento de aceitação"
+
+#: logsrvd/logsrvd_local.c:225
+msgid "error parsing RejectMessage"
+msgstr "erro ao analisar RejectMessage"
+
+#: logsrvd/logsrvd_local.c:249
+msgid "error logging reject event"
+msgstr "erro ao registar evento de rejeição"
+
+#: logsrvd/logsrvd_local.c:284
+msgid "error logging exit event"
+msgstr "erro ao registar evento de saída"
+
+#: logsrvd/logsrvd_local.c:343 logsrvd/logsrvd_local.c:344
+msgid "log is already complete, cannot be restarted"
+msgstr "diário já concluído, impossível reiniciar"
+
+#: logsrvd/logsrvd_local.c:374
+msgid "unable to restart log"
+msgstr "impossível reiniciar o diário"
+
+#: logsrvd/logsrvd_local.c:390
+msgid "error parsing AlertMessage"
+msgstr "erro ao analisar AlertMessage"
+
+#: logsrvd/logsrvd_local.c:400
+msgid "error logging alert event"
+msgstr "erro ao registar evento de alerta"
+
+#: logsrvd/logsrvd_local.c:435 logsrvd/logsrvd_local.c:488
+#: logsrvd/logsrvd_local.c:523
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr "impossível formatar buffer de temporização, tamanho %d"
+
+#: logsrvd/logsrvd_local.c:442 logsrvd/logsrvd_local.c:450
+#: logsrvd/logsrvd_local.c:495 logsrvd/logsrvd_local.c:530
+#: plugins/sudoers/sudoreplay.c:351
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: logsrvd/logsrvd_local.c:470
+msgid "error writing IoBuffer"
+msgstr "erro ao escrever IObuffer"
+
+#: logsrvd/logsrvd_local.c:505
+msgid "error writing ChangeWindowSize"
+msgstr "erro ao escrever ChangeWindowSize"
+
+#: logsrvd/logsrvd_local.c:540
+msgid "error writing CommandSuspend"
+msgstr "erro ao escrever CommandSuspend"
+
+#: logsrvd/logsrvd_relay.c:436
+msgid "TLS handshake with relay host failed"
+msgstr "Falha no TLS handshake com o servidor intermédio"
+
+#: logsrvd/logsrvd_relay.c:464
+msgid "unable to connect to relay host"
+msgstr "impossível ligar ao servidor intermédio"
+
+#: logsrvd/logsrvd_relay.c:519
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s: ServerHello inválido, server_id em falta"
+
+#: logsrvd/logsrvd_relay.c:521 logsrvd/sendlog.c:961
+#: plugins/sudoers/log_client.c:1493
+msgid "invalid ServerHello"
+msgstr "ServerHello inválido"
+
+#: logsrvd/logsrvd_relay.c:680
+msgid "unrecognized ServerMessage type"
+msgstr "tipo de ServerMessage não reconhecido"
+
+#: logsrvd/logsrvd_relay.c:709
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr "expirou ao ler do relé %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:711
+msgid "timeout reading from relay"
+msgstr "leitura do servidor intermédio expirou"
+
+#: logsrvd/logsrvd_relay.c:762
+msgid "relay host name does not match certificate"
+msgstr "nome de servidor intermédio não corresponde ao certificado"
+
+#: logsrvd/logsrvd_relay.c:766 logsrvd/logsrvd_relay.c:779
+#: logsrvd/logsrvd_relay.c:785
+msgid "error reading from relay"
+msgstr "erro ao ler do servidor intermédio"
+
+#: logsrvd/logsrvd_relay.c:806
+msgid "unable to read from relay"
+msgstr "impossível ler do servidor intermédio"
+
+#: logsrvd/logsrvd_relay.c:821 logsrvd/logsrvd_relay.c:939
+msgid "relay server closed connection"
+msgstr "o servidor intermédio fechou a ligação"
+
+#: logsrvd/logsrvd_relay.c:839
+msgid "server message too large"
+msgstr "mensagem do servidor muito grande"
+
+#: logsrvd/logsrvd_relay.c:903
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr "expirou ao escrever no relé %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:905
+msgid "timeout writing to relay"
+msgstr "escrita no servidor intermédio expirou"
+
+#: logsrvd/logsrvd_relay.c:958 logsrvd/logsrvd_relay.c:964
+#: logsrvd/logsrvd_relay.c:974
+msgid "error writing to relay"
+msgstr "erro ao escrever no servidor intermédio"
+
+#: logsrvd/sendlog.c:120
+msgid "send sudo I/O log to remote server"
+msgstr "%s - enviar diário sudo E/S para o servidor remoto"
+
+#: logsrvd/sendlog.c:126
+msgid "only send an accept event (no I/O)"
+msgstr "enviar só um evento de aceitação (sem E/S)"
+
+#: logsrvd/sendlog.c:129
+msgid "certificate bundle file to verify server's cert against"
+msgstr "ficheiro de pacote de certificados contra o qual verificar o certificado do servidor"
+
+#: logsrvd/sendlog.c:131
+msgid "certificate file for TLS handshake"
+msgstr "ficheiro de certificado para o TLS handshake"
+
+#: logsrvd/sendlog.c:134
+msgid "host to send logs to"
+msgstr "anfitrião para onde enviar os diários"
+
+#: logsrvd/sendlog.c:136
+msgid "remote ID of I/O log to be resumed"
+msgstr "a ID remota do diário de E/S a retomar"
+
+#: logsrvd/sendlog.c:139
+msgid "private key file"
+msgstr "ficheiro de chave privada"
+
+#: logsrvd/sendlog.c:141
+msgid "do not verify server certificate"
+msgstr "não verificar certificado do servidor"
+
+#: logsrvd/sendlog.c:144
+msgid "port to use when connecting to host"
+msgstr "porta a usar ao ligar ao anfitrião"
+
+#: logsrvd/sendlog.c:146
+msgid "restart previous I/O log transfer"
+msgstr "reiniciar transferência do diário de E/S prévia"
+
+#: logsrvd/sendlog.c:148
+msgid "reject the command with the given reason"
+msgstr "rejeitar o comando com o motivo indicado"
+
+#: logsrvd/sendlog.c:150
+msgid "stop transfer after reaching this time"
+msgstr "parar transferência após atingir este tempo"
+
+#: logsrvd/sendlog.c:152
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "testar servidor de auditoria enviando o diário de E/S seleccionado n vezes em paralelo"
+
+#: logsrvd/sendlog.c:177 plugins/sudoers/log_client.c:437
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "impossível procurar %s:%s: %s"
+
+#: logsrvd/sendlog.c:215
+msgid "unable to get server IP addr"
+msgstr "impossível obter endereço IP do servidor"
+
+#: logsrvd/sendlog.c:269 plugins/sudoers/sudoreplay.c:871
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "impossível ler %s/%s: %s"
+
+#: logsrvd/sendlog.c:831
+#, c-format
+msgid "%s: write buffer already in use"
+msgstr "%s: buffer de escrita já em uso"
+
+#: logsrvd/sendlog.c:892 plugins/sudoers/iolog.c:890
+#: plugins/sudoers/iolog.c:959
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "evento de E/S %d inesperado"
+
+#: logsrvd/sendlog.c:938 logsrvd/sendlog.c:955 logsrvd/sendlog.c:989
+#: plugins/sudoers/log_client.c:1142 plugins/sudoers/log_client.c:1419
+#: plugins/sudoers/log_client.c:1487 plugins/sudoers/log_client.c:1526
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: estado %d inesperado"
+
+#: logsrvd/sendlog.c:1025 plugins/sudoers/log_client.c:1570
+#, c-format
+msgid "error message received from server: %s"
+msgstr "recebida mensagem de erro do servidos: %s"
+
+#: logsrvd/sendlog.c:1038 plugins/sudoers/log_client.c:1583
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "recebida mensagem de aborto do servidos: %s"
+
+#: logsrvd/sendlog.c:1097 plugins/sudoers/log_client.c:1633
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s: valor type_case %d inesperado"
+
+#: logsrvd/sendlog.c:1126
+msgid "timeout reading from server"
+msgstr "leitura do servidor expirou"
+
+#: logsrvd/sendlog.c:1205
+msgid "premature EOF"
+msgstr "EOF prematuro"
+
+#: logsrvd/sendlog.c:1218 plugins/sudoers/log_client.c:1791
+#, c-format
+msgid "server message too large: %u"
+msgstr "mensagem do servidor muito grande: %u"
+
+#: logsrvd/sendlog.c:1269
+msgid "timeout writing to server"
+msgstr "escrita no servidor expirou"
+
+#: logsrvd/sendlog.c:1609
+msgid "both restart point and iolog ID must be specified"
+msgstr "tem de especificar o ponto de reinício e a ID iolog"
+
+#: logsrvd/sendlog.c:1613
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "impossível definir um ponto de reinício sem E/S enviada"
+
+#: logsrvd/sendlog.c:1689
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "saída prematura com o estado %d"
+
+#: logsrvd/sendlog.c:1690
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "tempo decorrido de envio para o servidor [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1692
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "ponto de submissão recebido do servidor [%lld, %ld]"
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:300
+msgid "TLS handshake timeout occurred"
+msgstr "TLS handshake expirou"
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:322 plugins/sudoers/log_client.c:338
+msgid "unable to set event"
+msgstr "impossível definir o evento"
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "Falha na ligação TLS: %s"
+
+#: logsrvd/tls_client.c:195
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "impossível alocar objecto ssl: %s"
+
+#: logsrvd/tls_client.c:208
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "Impossível anexar socket ao objecto ssl: %s"
+
+#: logsrvd/tls_client.c:236
+msgid "unable to initialize TLS context"
+msgstr "impossível inicializar contexto TLS"
+
+#: logsrvd/tls_init.c:126 logsrvd/tls_init.c:134
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "impossível definir TLS 1.2 ciphersuite como %s: %s"
+
+#: logsrvd/tls_init.c:154 logsrvd/tls_init.c:162
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "impossível definir TLS 1.3 ciphersuite como %s: %s"
+
+#: logsrvd/tls_init.c:197
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "impossível criar contexto TLS: %s"
+
+#: logsrvd/tls_init.c:203
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "impossível definir versão mínima do protocolo como TLS 1.2: %s"
+
+#: logsrvd/tls_init.c:279
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "impossível definir parâmetros diffie-hellman: %s"
+
+#: logsrvd/tls_init.c:288
+#, c-format
+msgid "unable to read diffie-hellman parameters: %s"
+msgstr "impossível ler parâmetros diffie-hellman: %s"
+
+#: plugins/sudoers/audit.c:267 plugins/sudoers/audit.c:422
+#: plugins/sudoers/log_client.c:975 plugins/sudoers/log_client.c:1024
+#: plugins/sudoers/log_client.c:1073 plugins/sudoers/log_client.c:1199
+#: plugins/sudoers/logging.c:554 plugins/sudoers/logging.c:648
+#: plugins/sudoers/logging.c:810 plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr "impossível obter hora do dia"
+
+#: plugins/sudoers/auth/aix_auth.c:277
+#, c-format
+msgid "unable to change password for %s"
+msgstr "impossível alterar a senha para %s"
+
+#: plugins/sudoers/auth/bsdauth.c:70
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "impossível obter classe de sessão para o utilizador %s"
+
+#: plugins/sudoers/auth/bsdauth.c:75
+msgid "unable to begin bsd authentication"
+msgstr "impossível iniciar autenticação bsd"
+
+#: plugins/sudoers/auth/bsdauth.c:83
+msgid "invalid authentication type"
+msgstr "tipo de autenticação inválido"
+
+#: plugins/sudoers/auth/bsdauth.c:92
+msgid "unable to initialize BSD authentication"
+msgstr "impossível inicializar autenticação BSD"
+
+#: plugins/sudoers/auth/bsdauth.c:179
+msgid "your account has expired"
+msgstr "a sua conta expirou"
+
+#: plugins/sudoers/auth/bsdauth.c:181
+msgid "approval failed"
+msgstr "aprovação falhou"
+
+#: plugins/sudoers/auth/fwtk.c:54
+msgid "unable to read fwtk config"
+msgstr "impossível ler fwtk config"
+
+#: plugins/sudoers/auth/fwtk.c:59
+msgid "unable to connect to authentication server"
+msgstr "impossível ligar ao servidor de autenticação"
+
+#: plugins/sudoers/auth/fwtk.c:65 plugins/sudoers/auth/fwtk.c:89
+#: plugins/sudoers/auth/fwtk.c:121
+msgid "lost connection to authentication server"
+msgstr "ligação ao servidor de autenticação perdida"
+
+#: plugins/sudoers/auth/fwtk.c:69
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"erro no servidor de autenticação:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:110
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: impossível converter principal para cadeia (\"%s\"): %s"
+
+#: plugins/sudoers/auth/kerb5.c:160
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: impossível analisar \"%s\": %s"
+
+#: plugins/sudoers/auth/kerb5.c:169
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: impossível resolver cache de credenciais: %s"
+
+#: plugins/sudoers/auth/kerb5.c:216
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: impossível alocar opções: %s"
+
+#: plugins/sudoers/auth/kerb5.c:231
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: impossível obter credentiais: %s"
+
+#: plugins/sudoers/auth/kerb5.c:244
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: impossível inicializar a cache de credenciais: %s"
+
+#: plugins/sudoers/auth/kerb5.c:247
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: impossível armazenar a credencial em cache: %s"
+
+#: plugins/sudoers/auth/kerb5.c:311
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: impossível obter o principal do anfitrião: %s"
+
+#: plugins/sudoers/auth/kerb5.c:325
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: Impossível verificar TGT! Possível ataque!: %s"
+
+#: plugins/sudoers/auth/pam.c:218
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "impossível inicializar PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:340
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Erro de autenticação PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:359
+msgid "account validation failure, is your account locked?"
+msgstr "falha na validação de conta, tem a conta trancada?"
+
+#: plugins/sudoers/auth/pam.c:370
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Conta ou senha expiradas, reponha a sua senha e tente novamente"
+
+#: plugins/sudoers/auth/pam.c:376
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "impossível alterar senha expirada: %s"
+
+#: plugins/sudoers/auth/pam.c:387
+msgid "Password expired, contact your system administrator"
+msgstr "Senha expirada, contacte o administrador do sistema"
+
+#: plugins/sudoers/auth/pam.c:392
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Conta expirada ou configuração PAM sem secção \"account\" para sudo, contacte o administrador do sistema"
+
+#: plugins/sudoers/auth/pam.c:400 plugins/sudoers/auth/pam.c:405
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "Erro de gestão de conta PAM: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:99 plugins/sudoers/visudo.c:241
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "utilizador não existente na base de dados %s"
+
+#: plugins/sudoers/auth/securid5.c:72
+msgid "failed to initialise the ACE API library"
+msgstr "falha ao inicializar a biblioteca ACE API"
+
+#: plugins/sudoers/auth/securid5.c:98
+msgid "unable to contact the SecurID server"
+msgstr "impossível contactar o servidor SecurID"
+
+#: plugins/sudoers/auth/securid5.c:107
+msgid "User ID locked for SecurID Authentication"
+msgstr "ID de utilizador bloqueada para autenticação SecurID"
+
+#: plugins/sudoers/auth/securid5.c:111 plugins/sudoers/auth/securid5.c:162
+msgid "invalid username length for SecurID"
+msgstr "tamanho de nome de utilizador inválido para SecurID"
+
+#: plugins/sudoers/auth/securid5.c:115 plugins/sudoers/auth/securid5.c:167
+msgid "invalid Authentication Handle for SecurID"
+msgstr "gestão de autenticação inválida para SecurID"
+
+#: plugins/sudoers/auth/securid5.c:119
+msgid "SecurID communication failed"
+msgstr "Falha na comunicação SecurID"
+
+#: plugins/sudoers/auth/securid5.c:123 plugins/sudoers/auth/securid5.c:210
+msgid "unknown SecurID error"
+msgstr "erro SecurID desconhecido"
+
+#: plugins/sudoers/auth/securid5.c:157
+msgid "invalid passcode length for SecurID"
+msgstr "tamanho de senha inválido para SecurID"
+
+#: plugins/sudoers/auth/sia.c:69 plugins/sudoers/auth/sia.c:123
+msgid "unable to initialize SIA session"
+msgstr "impossível inicializar sessão SIA"
+
+#: plugins/sudoers/auth/sudo_auth.c:132
+msgid "invalid authentication methods"
+msgstr "métodos de autenticação inválidos"
+
+#: plugins/sudoers/auth/sudo_auth.c:134
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Métodos de autenticação inválidos compilados com sudo! Não pode misturar autenticação independente com outra."
+
+#: plugins/sudoers/auth/sudo_auth.c:255 plugins/sudoers/auth/sudo_auth.c:305
+msgid "no authentication methods"
+msgstr "sem métodos de autenticação"
+
+#: plugins/sudoers/auth/sudo_auth.c:257
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Não há métodos de autenticação compilados com sudo! Se pretende desligar a autenticação. use a opção de configuração --disable-authentication."
+
+#: plugins/sudoers/auth/sudo_auth.c:307
+msgid "Unable to initialize authentication methods."
+msgstr "Impossível inicializar métodos de autenticaçao."
+
+#: plugins/sudoers/auth/sudo_auth.c:471
+msgid "Authentication methods:"
+msgstr "Métodos de autenticação:"
+
+#: plugins/sudoers/bsm_audit.c:123 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "Impossível determinar condição de auditoria"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:277
+msgid "unable to commit audit record"
+msgstr "impossível submeter registo de auditoria"
+
+#: plugins/sudoers/check.c:264
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "erro ao ler ficheiro de palestra %s"
+
+#: plugins/sudoers/check.c:270
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "a ignorar ficheiro de palestra %s: não é um ficheiro normal"
+
+#: plugins/sudoers/check.c:283
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Acreditamos que recebeu a lição de moral do administrador de\n"
+"sistema local. Normalmente resume-se a estes três pontos:\n"
+"\n"
+" 1) respeite a privacidade dos outros;\n"
+" 2) pense antes de escrever;\n"
+" 3) lembre-se que com grande poder vem grande responsabilidade.\n"
+"\n"
+
+#: plugins/sudoers/check.c:331 plugins/sudoers/check.c:341
+#: plugins/sudoers/sudoers.c:876 plugins/sudoers/sudoers.c:897
+#: plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "uid desconhecida %u"
+
+#: plugins/sudoers/check_aliases.c:56
+#, c-format
+msgid "Error: %s:%d:%d: cycle in %s \"%s\""
+msgstr "Erro: %s:%d:%d: ciclo em %s \"%s\""
+
+#: plugins/sudoers/check_aliases.c:57
+#, c-format
+msgid "Warning: %s:%d:%d: cycle in %s \"%s\""
+msgstr "Aviso: %s:%d:%d: ciclo em %s \"%s\""
+
+#: plugins/sudoers/check_aliases.c:61
+#, c-format
+msgid "Error: %s:%d:%d: %s \"%s\" referenced but not defined"
+msgstr "Erro: %s:%d:%d: %s \"%s\" referenciado mas não definido"
+
+#: plugins/sudoers/check_aliases.c:62
+#, c-format
+msgid "Warning: %s:%d:%d: %s \"%s\" referenced but not defined"
+msgstr "Aviso: %s:%d:%d: %s \"%s\" referenciado mas não definido"
+
+#: plugins/sudoers/cvtsudoers.c:194
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "incremento de ordem: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:210
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "ordem inicial: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:220
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "espaço de ordem: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:230 plugins/sudoers/visudo.c:177
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s versão gramatical %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:247 plugins/sudoers/testsudoers.c:159
+#, c-format
+msgid "unsupported input format %s"
+msgstr "formato de entrada %s não suportado"
+
+#: plugins/sudoers/cvtsudoers.c:262
+#, c-format
+msgid "unsupported output format %s"
+msgstr "formato de saída %s não suportado"
+
+#: plugins/sudoers/cvtsudoers.c:314
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: os ficheiros de entrada e saída têm de ser diferentes"
+
+#: plugins/sudoers/cvtsudoers.c:330 plugins/sudoers/sudoers.c:159
+#: plugins/sudoers/sudoers.c:205 plugins/sudoers/testsudoers.c:254
+#: plugins/sudoers/visudo.c:247 plugins/sudoers/visudo.c:597
+#: plugins/sudoers/visudo.c:917
+msgid "unable to initialize sudoers default values"
+msgstr "impossível inicializar valores predefinidos de sudoers"
+
+#: plugins/sudoers/cvtsudoers.c:416 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:475
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s: palavra-chave desconhecida %s"
+
+#: plugins/sudoers/cvtsudoers.c:521
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "tipo de predefinições inválido: %s"
+
+#: plugins/sudoers/cvtsudoers.c:544
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "tipo de supressão inválido: %s"
+
+#: plugins/sudoers/cvtsudoers.c:584 plugins/sudoers/cvtsudoers.c:598
+#, c-format
+msgid "invalid filter: %s"
+msgstr "filtro inválido: %s"
+
+#: plugins/sudoers/cvtsudoers.c:642 plugins/sudoers/visudo.c:922
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "falha ao analisar o ficheiro %s, erro desconhecido"
+
+#: plugins/sudoers/cvtsudoers.c:650
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr "erro de análise em %s, perto da linha %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:653
+#, c-format
+msgid "parse error in %s\n"
+msgstr "erro de análise em %s\n"
+
+#: plugins/sudoers/cvtsudoers.c:1296 plugins/sudoers/sudoreplay.c:1145
+#: plugins/sudoers/timestamp.c:317 plugins/sudoers/timestamp.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "impossível escrever em %s"
+
+#: plugins/sudoers/cvtsudoers.c:1319
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s - converte entre formatos de ficheiros sudoers\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1321
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Opções:\n"
+" -b, --base=dn o DN base para consultas sudo LDAP\n"
+" -c, --config=fich_conf o caminho para o ficheiro de configuração\n"
+" -d, --defaults=tipopred só converte predefinições do tipo especificado\n"
+" -e, --expand-alias expande aliás ao converter\n"
+" -f, --output-format=formato define o formato de saída: JSON, LDIF ou sudoers\n"
+" -i, --input-format=formato define o formato de entrada: LDIF ou sudoers\n"
+" -I, --increment=número valor a incrementar cada sudoOrder\n"
+" -h, --help mostra a ajuda e sai\n"
+" -m, --match=filtro só converte entradas que cumpram o filtro\n"
+" -M, --match-local filtro de comparação usa bases de dados de senha e grupo\n"
+" -o, --output=fich_saída escreve sudoers convertidos em fich_saída\n"
+" -O, --order-start=número ponto inicial para o primeiro sudoOrder\n"
+" -p, --prune-matches poda utilizadores, grupos e anfitriões não-correspondentes\n"
+" -P, --padding=num espaço base para incremento sudoOrder\n"
+" -s, --suppress=secções suprime saída de certas secções\n"
+" -V, --version mostra informação da versão e sai"
+
+#: plugins/sudoers/cvtsudoers_json.c:480 plugins/sudoers/cvtsudoers_json.c:514
+#: plugins/sudoers/cvtsudoers_json.c:718
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "entrada de predefinições \"%s\" desconhecida"
+
+#: plugins/sudoers/cvtsudoers_json.c:651 plugins/sudoers/cvtsudoers_json.c:664
+#: plugins/sudoers/cvtsudoers_ldif.c:346 plugins/sudoers/cvtsudoers_ldif.c:357
+#: plugins/sudoers/ldap.c:503
+msgid "unable to get GMT time"
+msgstr "impossível obter hora GMT"
+
+#: plugins/sudoers/cvtsudoers_json.c:654 plugins/sudoers/cvtsudoers_json.c:667
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:360
+#: plugins/sudoers/ldap.c:509
+msgid "unable to format timestamp"
+msgstr "impossível formatar datação"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:644
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "demasiadas entradas sudoers, máximo %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:687
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "a variável de ambiente SUDOERS_BASE não está definida e a opção -b não foi especificada."
+
+#: plugins/sudoers/def_data.c:50
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Facilidade syslog se syslog estiver a ser usado para início de sessão: %s"
+
+#: plugins/sudoers/def_data.c:54
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Prioridade syslog a usar quando o utilizador se autentica com sucesso: %s"
+
+#: plugins/sudoers/def_data.c:58
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Prioridade syslog a usar quando o utilizador não se autentica com sucesso: %s"
+
+#: plugins/sudoers/def_data.c:62
+msgid "Put OTP prompt on its own line"
+msgstr "Põe o prompt OPT na sua própria linha"
+
+#: plugins/sudoers/def_data.c:66
+msgid "Ignore '.' in $PATH"
+msgstr "Ignora \".\" em $PATH"
+
+#: plugins/sudoers/def_data.c:70
+msgid "Always send mail when sudo is run"
+msgstr "Envia sempre correio quando executa sudo"
+
+#: plugins/sudoers/def_data.c:74
+msgid "Send mail if user authentication fails"
+msgstr "Envia correio se a autenticação do utilizador falhar"
+
+#: plugins/sudoers/def_data.c:78
+msgid "Send mail if the user is not in sudoers"
+msgstr "Envia correio se o utilizador não estiver em sudoers"
+
+#: plugins/sudoers/def_data.c:82
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Envia correio se o utilizador não estiver em sudoers neste anfitrião"
+
+#: plugins/sudoers/def_data.c:86
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Envia correio se o utilizador não puder executar um comando"
+
+#: plugins/sudoers/def_data.c:90
+msgid "Send mail if the user tries to run a command"
+msgstr "Envia correio se o utilizador tentar executar um comando"
+
+#: plugins/sudoers/def_data.c:94
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Usa uma datação separada para cada par utilizador/tty"
+
+#: plugins/sudoers/def_data.c:98
+msgid "Lecture user the first time they run sudo"
+msgstr "Avisar o utilizador a primeira vez que executa sudo"
+
+#: plugins/sudoers/def_data.c:102
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Ficheiro com a lição de moral sudo: %s"
+
+#: plugins/sudoers/def_data.c:106
+msgid "Require users to authenticate by default"
+msgstr "Requer autenticação dos utilizadores por predefinição"
+
+#: plugins/sudoers/def_data.c:110
+msgid "Root may run sudo"
+msgstr "Root pode executar sudo"
+
+#: plugins/sudoers/def_data.c:114
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Regista o nome de anfitrião no diário (não-syslog)"
+
+#: plugins/sudoers/def_data.c:118
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Regista o ano no diário (não-syslog)"
+
+#: plugins/sudoers/def_data.c:122
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Se sudo for chamado sem argumentos, iniciar uma shel"
+
+#: plugins/sudoers/def_data.c:126
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Definir $HOME para o utilizador alvo ao iniciar uma shell com -s"
+
+#: plugins/sudoers/def_data.c:130
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Definir $HOME sempre como a pasta home do utilizador alvo"
+
+#: plugins/sudoers/def_data.c:134
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Permite a recolha de alguma informação para dar mensagens de erro úteis"
+
+#: plugins/sudoers/def_data.c:138
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Requer nomes de anfitrião completamente qualificados no ficheiro sudoers"
+
+#: plugins/sudoers/def_data.c:142
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Insulta o utilizador quando se engana na senha"
+
+#: plugins/sudoers/def_data.c:146
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Permitir ao utilizador a execução de sudo só se tiver tty"
+
+#: plugins/sudoers/def_data.c:150
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo honra a variável de ambiente EDITOR"
+
+#: plugins/sudoers/def_data.c:154
+msgid "Prompt for root's password, not the users's"
+msgstr "Pedir senha root, não a do utilizador"
+
+#: plugins/sudoers/def_data.c:158
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Pedir a senha de utilizador runas_default, não a do utilizador"
+
+#: plugins/sudoers/def_data.c:162
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Pedir a senha do utilizador alvo, não a do utilizador"
+
+#: plugins/sudoers/def_data.c:166
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Aplica predefinições à classe de sessão do utilizador alvo, se existir"
+
+#: plugins/sudoers/def_data.c:170
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Define as variáveis de ambiente LOGNAME e USER"
+
+#: plugins/sudoers/def_data.c:174
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Definir a uid efectiva só para o utilizador alvo, não a uid real"
+
+#: plugins/sudoers/def_data.c:178
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Não inicializar o vector de grupo para o do utilizador alvo"
+
+#: plugins/sudoers/def_data.c:182
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Tamanho máximo de linhas longas do diário (0 para não quebrar): %u"
+
+#: plugins/sudoers/def_data.c:186
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Expiração da datação de autenticação: %.1f minutos"
+
+#: plugins/sudoers/def_data.c:190
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Expiração do pedido de senha: %.1f minutos"
+
+#: plugins/sudoers/def_data.c:194
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Número de tentativas de inserção de senha: %u"
+
+#: plugins/sudoers/def_data.c:198
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Umask a usar ou 0777 para usar a do utilizador: 0%o"
+
+#: plugins/sudoers/def_data.c:202
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Caminho para o ficheiro de diário: %s"
+
+#: plugins/sudoers/def_data.c:206
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Caminho para o programa de correio: %s"
+
+#: plugins/sudoers/def_data.c:210
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Bandeiras para o programa de correio: %s"
+
+#: plugins/sudoers/def_data.c:214
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Endereço para onde enviar o correio: %s"
+
+#: plugins/sudoers/def_data.c:218
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Endereço de onde enviar o correio: %s"
+
+#: plugins/sudoers/def_data.c:222
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Linha de assunto para as mensagens: %s"
+
+#: plugins/sudoers/def_data.c:226
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Mensagem de senha incorrecta: %s"
+
+#: plugins/sudoers/def_data.c:230
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Caminho para a pasta de estado da lição de moral: %s"
+
+#: plugins/sudoers/def_data.c:234
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Caminho para a pasta de datação de autenticação: %s"
+
+#: plugins/sudoers/def_data.c:238
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Dono da pasta de datação de autenticação: %s"
+
+#: plugins/sudoers/def_data.c:242
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Utilizadores deste grupo estão dispensados de usar senhas e necessidades de PATH: %s"
+
+#: plugins/sudoers/def_data.c:246
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Pedido de senha predefinido: %s"
+
+#: plugins/sudoers/def_data.c:250
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Se definido, o pedido de senha sobrepõe-se ao prompt do sistema em qualquer caso."
+
+#: plugins/sudoers/def_data.c:254
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Utilizador predefinido para executar comandos: %s"
+
+#: plugins/sudoers/def_data.c:258
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Valor a sobrepor a $PATH: %s"
+
+#: plugins/sudoers/def_data.c:262
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Caminho para o editor a usar com visudo: %s"
+
+#: plugins/sudoers/def_data.c:266
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Quando pedir uma senha para o pseudo-comando \"list\": %s"
+
+#: plugins/sudoers/def_data.c:270
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Quando pedir uma senha para o pseudo-comando \"verify\": %s"
+
+#: plugins/sudoers/def_data.c:274
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "Pré-carregar a biblioteca sudo_noexec, que substitui as funções executáveis"
+
+#: plugins/sudoers/def_data.c:278
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Se a pasta LDAP está em cima, ignoramos o ficheiro sudoers"
+
+#: plugins/sudoers/def_data.c:282
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Descritores de ficheiro >= %d será fechado antes de executar um comando"
+
+#: plugins/sudoers/def_data.c:286
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "Se definido, os utilizadores podem sobrepor o valor de \"closefrom\" com a opção -C"
+
+#: plugins/sudoers/def_data.c:290
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Permite aos utilizadores definir variáveis de ambiente arbitrárias"
+
+#: plugins/sudoers/def_data.c:294
+msgid "Reset the environment to a default set of variables"
+msgstr "Repor o ambiente num conjunto predefinido de variáveis"
+
+#: plugins/sudoers/def_data.c:298
+msgid "Environment variables to check for safety:"
+msgstr "Variáveis de ambiente para verificar a segurança:"
+
+#: plugins/sudoers/def_data.c:302
+msgid "Environment variables to remove:"
+msgstr "Variáveis de ambiente para remover:"
+
+#: plugins/sudoers/def_data.c:306
+msgid "Environment variables to preserve:"
+msgstr "Variáveis de ambiente para preservar:"
+
+#: plugins/sudoers/def_data.c:310
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "Papel SELinux a usar no novo contexto de segurança: %s"
+
+#: plugins/sudoers/def_data.c:314
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "Tipo SELinux a usar no novo contexto de segurança: %s"
+
+#: plugins/sudoers/def_data.c:318
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Caminho para o ficheiro de ambiente específico do sudo: %s"
+
+#: plugins/sudoers/def_data.c:322
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Caminho para o ficheiro restrito de ambiente específico do sudo: %s"
+
+#: plugins/sudoers/def_data.c:326
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Idioma a usar ao analisar sudoers: %s"
+
+#: plugins/sudoers/def_data.c:330
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Permite ao sudo pedir uma senha mesmo que fique visível"
+
+#: plugins/sudoers/def_data.c:334
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Fornece resposta visual no pedido de senha quando há entrada do utilizador"
+
+#: plugins/sudoers/def_data.c:338
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Usa globbing mais rápido e menos preciso, mas não acede ao sistema de ficheiros"
+
+#: plugins/sudoers/def_data.c:342
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "A umask especificada no sudoers sobrepõe-se à do utilizador, mesmo que seja mais permissiva"
+
+#: plugins/sudoers/def_data.c:346
+msgid "Log user's input for the command being run"
+msgstr "Regista as entradas do utilizador para o comando em execução"
+
+#: plugins/sudoers/def_data.c:350
+msgid "Log the output of the command being run"
+msgstr "Regista a saída do comando em execução"
+
+#: plugins/sudoers/def_data.c:354
+msgid "Compress I/O logs using zlib"
+msgstr "Comprime diários de E/S com zlib"
+
+#: plugins/sudoers/def_data.c:358
+msgid "Always run commands in a pseudo-tty"
+msgstr "Executa sempre os comandos num pseudo-tty"
+
+#: plugins/sudoers/def_data.c:362
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Extensão para suporte de grupo não-Unix: %s"
+
+#: plugins/sudoers/def_data.c:366
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Pasta onde armazenar os diários de entrada/saída: %s"
+
+#: plugins/sudoers/def_data.c:370
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Ficheiro onde armazenar o diário de entrada/saída: %s"
+
+#: plugins/sudoers/def_data.c:374
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Adiciona uma entrada ao ficheiro utmp/utmpx ao alocar um pty"
+
+#: plugins/sudoers/def_data.c:378
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Define o utilizador em utmp como utilizador runas mestre, não como utilizador chamador"
+
+#: plugins/sudoers/def_data.c:382
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Conjunto de privilégios permitidos: %s"
+
+#: plugins/sudoers/def_data.c:386
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Conjunto de privilégios limite: %s"
+
+#: plugins/sudoers/def_data.c:390
+msgid "Run commands on a pty in the background"
+msgstr "Executa comandos num pty em 2º plano"
+
+#: plugins/sudoers/def_data.c:394
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "Nome de serviço PAM a usar: %s"
+
+#: plugins/sudoers/def_data.c:398
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "Nome de serviço PAM a usar para shells de sessão: %s"
+
+#: plugins/sudoers/def_data.c:402
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Tenta estabelecer credenciais PAM para o utilizador alvo"
+
+#: plugins/sudoers/def_data.c:406
+msgid "Create a new PAM session for the command to run in"
+msgstr "Cria uma nova sessão PAM onde o comando será executado"
+
+#: plugins/sudoers/def_data.c:410
+msgid "Perform PAM account validation management"
+msgstr "Realizar gestão de validação de conta PAM"
+
+#: plugins/sudoers/def_data.c:414
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "Número de sequência máximo do diário de E/S: %s"
+
+#: plugins/sudoers/def_data.c:418
+msgid "Enable sudoers netgroup support"
+msgstr "Activa o suporte a sudoers netgroup"
+
+#: plugins/sudoers/def_data.c:422
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Verifica se as pastas-mãe se podem escrever ao editar ficheiros com sudoedit"
+
+#: plugins/sudoers/def_data.c:426
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Segue ligações simbólicas ao editar ficheiros com sudoedit"
+
+#: plugins/sudoers/def_data.c:430
+msgid "Query the group plugin for unknown system groups"
+msgstr "Consulta a extensão de grupo para grupos de sistema desconhecidos"
+
+#: plugins/sudoers/def_data.c:434
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Compara netgroups baseado em todo o conjunto: utilizador, anfitrião e domínio"
+
+#: plugins/sudoers/def_data.c:438
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Permite executar comandos mesmo que o sudo não possa escrever no diário de auditoria"
+
+#: plugins/sudoers/def_data.c:442
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Permite executar comandos mesmo que o sudo não possa escrever no diário de E/S"
+
+#: plugins/sudoers/def_data.c:446
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Permite executar comandos mesmo que o sudo não possa escrever no diário"
+
+#: plugins/sudoers/def_data.c:450
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Resolve grupos no sudoers e compara a ID de grupo, não o nome"
+
+#: plugins/sudoers/def_data.c:454
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Entradas de diário maiores que este valor serão divididas em múltiplas mensagens de syslog: %u"
+
+#: plugins/sudoers/def_data.c:458
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Utilizador que será dono dos ficheiros de E/S: %s"
+
+#: plugins/sudoers/def_data.c:462
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Grupo que será dono dos ficheiros de E/S: %s"
+
+#: plugins/sudoers/def_data.c:466
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Modo de ficheiro a usar para os ficheiros de E/S: 0%o"
+
+#: plugins/sudoers/def_data.c:470
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Executa comandos por descritor de ficheiro em vez de por caminho: %s"
+
+#: plugins/sudoers/def_data.c:474
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Ignora entradas Defaults desconhecidas no sudoers, em vez de produzir um aviso"
+
+#: plugins/sudoers/def_data.c:478
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Tempo em segundos após o qual cada comando será terminado: %u"
+
+#: plugins/sudoers/def_data.c:482
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Permite ao utilizador especificar um tempo de inacção na linha de comandos"
+
+#: plugins/sudoers/def_data.c:486
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Despejar dados de E/S para o disco imediatamente, em vez de usar um buffer"
+
+#: plugins/sudoers/def_data.c:490
+msgid "Include the process ID when logging via syslog"
+msgstr "Incluir a ID de processo ao registar via syslog"
+
+#: plugins/sudoers/def_data.c:494
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Tipo de registo de datação de autenticação: %s"
+
+#: plugins/sudoers/def_data.c:498
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Mensagem de falha na autenticação: %s"
+
+#: plugins/sudoers/def_data.c:502
+msgid "Ignore case when matching user names"
+msgstr "Ignorar maiúsculas ao comparar nomes de utilizadores"
+
+#: plugins/sudoers/def_data.c:506
+msgid "Ignore case when matching group names"
+msgstr "Ignorar maiúsculas ao comparar nomes de grupos"
+
+#: plugins/sudoers/def_data.c:510
+msgid "Log when a command is allowed by sudoers"
+msgstr "Registar um comando permitido por sudoers"
+
+#: plugins/sudoers/def_data.c:514
+msgid "Log when a command is denied by sudoers"
+msgstr "Registar um comando negado por sudoers"
+
+#: plugins/sudoers/def_data.c:518
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "Servidor(es) de diários sudo aos quais ligar com a porta opcional"
+
+#: plugins/sudoers/def_data.c:522
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Expiração do servidor de diários sudo em segundos: %u"
+
+#: plugins/sudoers/def_data.c:526
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "Activar a opção de socket SO_KEEPALIVE no socket ligado ao servidor de diários"
+
+#: plugins/sudoers/def_data.c:530
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "Caminho para o ficheiro de pacote de CA do servidor de auditoria: %s"
+
+#: plugins/sudoers/def_data.c:534
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "Caminho para o ficheiro de certificado de sudoers: %s"
+
+#: plugins/sudoers/def_data.c:538
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "Caminho para o ficheiro de chave privada de sudoers: %s"
+
+#: plugins/sudoers/def_data.c:542
+msgid "Verify that the log server's certificate is valid"
+msgstr "Verifique se o certificado do servidor de registos é válido"
+
+#: plugins/sudoers/def_data.c:546
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "Permitir o uso de runas desconhecidas e/ou ID de grupo"
+
+#: plugins/sudoers/def_data.c:550
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "Permitir só executar comandos como utilizador com shell válida"
+
+#: plugins/sudoers/def_data.c:554
+msgid "Set the pam remote user to the user running sudo"
+msgstr "Definir o utilizador remoto pam como o utilizador a executar sudo"
+
+#: plugins/sudoers/def_data.c:558
+msgid "Set the pam remote host to the local host name"
+msgstr "Definir o anfitrião remoto pam como o nome do anfitrião local"
+
+#: plugins/sudoers/def_data.c:562
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "Pasta de trabalho a alterar antes de executar o comando: %s"
+
+#: plugins/sudoers/def_data.c:566
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "Pasta raiz a alterar antes de executar o comando: %s"
+
+#: plugins/sudoers/def_data.c:570
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "O formato de diários a produzir: %s"
+
+#: plugins/sudoers/def_data.c:574
+msgid "Enable SELinux RBAC support"
+msgstr "Activar suporte a SELinux RBAC"
+
+#: plugins/sudoers/def_data.c:578
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "Caminho para o ficheiro criado na 1ª execução de sudo: %s"
+
+#: plugins/sudoers/def_data.c:582
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "Interceptar comandos posteriores e aplicar-lhes restrições sudoers"
+
+#: plugins/sudoers/def_data.c:586
+msgid "Log any child processes run by the command"
+msgstr "Registar processos filho executados pelo comando"
+
+#: plugins/sudoers/def_data.c:590
+msgid "Log the exit status of commands"
+msgstr "Registar estado da saída de comandos"
+
+#: plugins/sudoers/def_data.c:594
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr "Comandos subsequentes numa sessão interceptada têm de ser autenticados"
+
+#: plugins/sudoers/def_data.c:598
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr "Permitir que um comando interceptado execute os programas setuid ou setgid"
+
+#: plugins/sudoers/defaults.c:185
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: entrada pré-definida desconhecida \"%s\""
+
+#: plugins/sudoers/defaults.c:188
+#, c-format
+msgid "%s: unknown defaults entry \"%s\""
+msgstr "%s entrada defaults desconhecida \"%s\""
+
+#: plugins/sudoers/defaults.c:234
+#, c-format
+msgid "%s:%d:%d: no value specified for \"%s\""
+msgstr "%s:%d:%d: sem valor especificado para \"%s\""
+
+#: plugins/sudoers/defaults.c:237
+#, c-format
+msgid "%s: no value specified for \"%s\""
+msgstr "%s sem valor especificado para \"%s\""
+
+#: plugins/sudoers/defaults.c:250
+#, c-format
+msgid "%s:%d:%d: invalid operator \"%c=\" for \"%s\""
+msgstr "%s:%d:%d: operador \"%c=\" inválido para \"%s\""
+
+#: plugins/sudoers/defaults.c:253
+#, c-format
+msgid "%s: invalid operator \"%c=\" for \"%s\""
+msgstr "%s: operador \"%c=\" inválido para \"%s\""
+
+#: plugins/sudoers/defaults.c:289
+#, c-format
+msgid "%s:%d:%d: option \"%s\" does not take a value"
+msgstr "%s:%d:%d: opção \"%s\" não recebe valores"
+
+#: plugins/sudoers/defaults.c:292
+#, c-format
+msgid "%s: option \"%s\" does not take a value"
+msgstr "%s opção \"%s\" não recebe valores"
+
+#: plugins/sudoers/defaults.c:317
+#, c-format
+msgid "%s:%d:%d: invalid Defaults type 0x%x for option \"%s\""
+msgstr "%s:%d:%d: tipo Defaults 0x%x inválido para a opção \"%s\""
+
+#: plugins/sudoers/defaults.c:320
+#, c-format
+msgid "%s: invalid Defaults type 0x%x for option \"%s\""
+msgstr "%s tipo Defaults 0x%x inválido para a opção \"%s\""
+
+#: plugins/sudoers/defaults.c:330
+#, c-format
+msgid "%s:%d:%d: value \"%s\" is invalid for option \"%s\""
+msgstr "%s:%d:%d: valor \"%s\" é inválido para a opção \"%s\""
+
+#: plugins/sudoers/defaults.c:333
+#, c-format
+msgid "%s: value \"%s\" is invalid for option \"%s\""
+msgstr "%s valor \"%s\" é inválido para a opção \"%s\""
+
+#: plugins/sudoers/defaults.c:1054
+#, c-format
+msgid "%s:%d:%d: values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "%s:%d:%d: valores para \"%s\" têm de começar com \"/\", \"~\" ou \"*\""
+
+#: plugins/sudoers/defaults.c:1058
+#, c-format
+msgid "%s: values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "%s: valores para \"%s\" têm de começar com \"/\", \"~\" ou \"*\""
+
+#: plugins/sudoers/defaults.c:1069
+#, c-format
+msgid "%s:%d:%d: values for \"%s\" must start with a '/'"
+msgstr "%s:%d:%d: valores para \"%s\" têm de começar com \"/\""
+
+#: plugins/sudoers/defaults.c:1073
+#, c-format
+msgid "%s: values for \"%s\" must start with a '/'"
+msgstr "%s valores para \"%s\" têm de começar com \"/\""
+
+#: plugins/sudoers/env.c:412
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: envp corrompido, tamanho trocado"
+
+#: plugins/sudoers/env.c:1095
+msgid "unable to rebuild the environment"
+msgstr "impossível reconstruir o ambiente"
+
+#: plugins/sudoers/env.c:1169
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "desculpe, não tem permissão para definir as seguintes variáveis de ambiente: %s"
+
+#: plugins/sudoers/file.c:108
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr "erro de análise em %s perto da linha %d"
+
+#: plugins/sudoers/file.c:111
+#, c-format
+msgid "parse error in %s"
+msgstr "erro de análise em %s"
+
+#: plugins/sudoers/filedigest.c:49
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr "tipo de resumo %d não suportado para %s"
+
+#: plugins/sudoers/filedigest.c:78
+#, c-format
+msgid "%s: read error"
+msgstr "%s: erro de leitura"
+
+#: plugins/sudoers/group_plugin.c:83
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s tem de ser propriedade de uid %d"
+
+#: plugins/sudoers/group_plugin.c:87
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr "%s só pode ter permissão de escrita para o dono"
+
+#: plugins/sudoers/group_plugin.c:96 plugins/sudoers/sssd.c:569
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "impossível carregar %s: %s"
+
+#: plugins/sudoers/group_plugin.c:102
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "impossível encontrar o símbolo \"group_plugin\" em %s"
+
+#: plugins/sudoers/group_plugin.c:107
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: versão principal de extensão de grupo %d incompatível, esperada %d"
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "impossível analisar endereço IP \"%s\""
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "impossível analisar netmask \"%s\""
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Pares endereço IP local e netmask:\n"
+
+#: plugins/sudoers/iolog.c:632
+msgid "unable to update sequence file"
+msgstr "impossível actualizar o ficheiro de sequência"
+
+#: plugins/sudoers/iolog.c:663 plugins/sudoers/iolog.c:851
+#: plugins/sudoers/iolog.c:1004 plugins/sudoers/iolog.c:1011
+#: plugins/sudoers/iolog.c:1132 plugins/sudoers/iolog.c:1139
+#: plugins/sudoers/iolog.c:1238 plugins/sudoers/iolog.c:1245
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "impossível escrever no ficheiro de E/S: %s"
+
+#: plugins/sudoers/iolog.c:671
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "impossível criar %s/%s"
+
+#: plugins/sudoers/iolog.c:896
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: erro interno, ficheiro de diário E/S do evento %d não aberto"
+
+#: plugins/sudoers/iolog.c:989 plugins/sudoers/iolog.c:1117
+#: plugins/sudoers/iolog.c:1222 plugins/sudoers/timestamp.c:849
+#: plugins/sudoers/timestamp.c:941 plugins/sudoers/visudo.c:487
+#: plugins/sudoers/visudo.c:493
+msgid "unable to read the clock"
+msgstr "impossível ler o relógio"
+
+#: plugins/sudoers/iolog.c:1214 plugins/sudoers/log_client.c:1217
+#: plugins/sudoers/log_client.c:1227 plugins/sudoers/log_client.c:1231
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: erro interno, sinal inválido %d"
+
+#: plugins/sudoers/ldap.c:177 plugins/sudoers/ldap_conf.c:291
+msgid "starttls not supported when using ldaps"
+msgstr "starttls não suportado quando usa ldaps"
+
+#: plugins/sudoers/ldap.c:248
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "impossível inicializar certificado SSL e db de chave: %s"
+
+#: plugins/sudoers/ldap.c:251
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "tem de definir TLS_CERT em %s para usar SSL"
+
+#: plugins/sudoers/ldap.c:1660
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "impossível inicializar LDAP: %s"
+
+#: plugins/sudoers/ldap.c:1697
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls especificado mas LDAP libs não suporta ldap_start_tls_s() ou ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:1834 plugins/sudoers/parse_ldif.c:746
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "atributo sudoOrder inválido: %s"
+
+#: plugins/sudoers/ldap_conf.c:200
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: porta muito grande"
+
+#: plugins/sudoers/ldap_conf.c:260
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "tipo de uri LDAP não suportado: %s"
+
+#: plugins/sudoers/ldap_conf.c:287
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "impossível misturar URIs ldap e ldaps"
+
+#: plugins/sudoers/ldap_util.c:496 plugins/sudoers/ldap_util.c:503
+#: plugins/sudoers/ldap_util.c:511 plugins/sudoers/ldap_util.c:520
+#: plugins/sudoers/ldap_util.c:528 plugins/sudoers/ldap_util.c:538
+#: plugins/sudoers/ldap_util.c:546
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "sudoOption duplicada: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:565 plugins/sudoers/ldap_util.c:567
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "impossível converter sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "impossível abrir o sistema de auditoria"
+
+#: plugins/sudoers/linux_audit.c:103
+msgid "unable to send audit message"
+msgstr "impossível enviar mensagem de auditoria"
+
+#: plugins/sudoers/log_client.c:116 plugins/sudoers/log_client.c:396
+#: plugins/sudoers/log_client.c:1464 plugins/sudoers/log_client.c:2061
+msgid "error in event loop"
+msgstr "erro no ciclo do evento"
+
+#: plugins/sudoers/log_client.c:196
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "Falha ao criar o novo objecto SSL_CTX: %s"
+
+#: plugins/sudoers/log_client.c:219
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "impossível carregar pacote da autoridade do certificado %s"
+
+#: plugins/sudoers/log_client.c:239
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "impossível carregar certificado %s"
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load private key %s"
+msgstr "impossível carregar chave privada %s"
+
+#: plugins/sudoers/log_client.c:261
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "Impossível alocar objecto ssl: %s"
+
+#: plugins/sudoers/log_client.c:349 plugins/sudoers/log_client.c:354
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "Ligação TLS a %s:%s falhou: %s"
+
+#: plugins/sudoers/log_client.c:527
+msgid "TLS initialization was unsuccessful"
+msgstr "Inicialização TLS sem sucesso"
+
+#: plugins/sudoers/log_client.c:537
+msgid "TLS handshake was unsuccessful"
+msgstr "TLS handshake sem sucesso"
+
+#: plugins/sudoers/log_client.c:1235
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: erro interno, sinal de saída %d inválido"
+
+#: plugins/sudoers/log_client.c:1602
+msgid "unable to unpack ServerMessage"
+msgstr "impossível desempacotar ServerMessage"
+
+#: plugins/sudoers/log_client.c:1754 plugins/sudoers/log_client.c:1778
+msgid "lost connection to log server"
+msgstr "ligação ao servidor de diários perdida"
+
+#: plugins/sudoers/log_client.c:1855
+msgid "missing write buffer"
+msgstr "buffer de escrita em falta"
+
+#: plugins/sudoers/log_client.c:2002
+msgid "unable to connect to log server"
+msgstr "impossível ligar ao servidor de diários"
+
+#: plugins/sudoers/logging.c:283
+msgid "user NOT in sudoers"
+msgstr "utilizador NÃO está no sudores"
+
+#: plugins/sudoers/logging.c:285
+msgid "user NOT authorized on host"
+msgstr "utilizador NÃO autorizado no anfitrião"
+
+#: plugins/sudoers/logging.c:287
+msgid "command not allowed"
+msgstr "comando não permitido"
+
+#: plugins/sudoers/logging.c:308
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr "%s não está no ficheiro sudoers. O incidente será reportado.\n"
+
+#: plugins/sudoers/logging.c:311
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr "%s não tem permissão para executar sudo em %s. O incidente será reportado.\n"
+
+#: plugins/sudoers/logging.c:315
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Desculpe, %s não pode executar sudo em %s.\n"
+
+#: plugins/sudoers/logging.c:318
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr "Desculpe, %s não tem permissão para executar \"%s%s%s\" como %s%s%s em %s.\n"
+
+#: plugins/sudoers/logging.c:355 plugins/sudoers/sudoers.c:629
+#: plugins/sudoers/sudoers.c:631 plugins/sudoers/sudoers.c:633
+#: plugins/sudoers/sudoers.c:635 plugins/sudoers/sudoers.c:776
+#: plugins/sudoers/sudoers.c:778
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: comando não encontrado"
+
+#: plugins/sudoers/logging.c:357 plugins/sudoers/sudoers.c:625
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"a ignorar \"%s\" encontrado em \".\"\n"
+"Use \"sudo ./%s\" se este é o \"%s\" que deseja executar."
+
+#: plugins/sudoers/logging.c:376
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u tentativa incorrecta"
+msgstr[1] "%u tentativas incorrectas"
+
+#: plugins/sudoers/logging.c:432
+msgid "authentication failure"
+msgstr "falha de autenticação"
+
+#: plugins/sudoers/logging.c:472 plugins/sudoers/logging.c:492
+msgid "a password is required"
+msgstr "é necessária uma senha"
+
+#: plugins/sudoers/logging.c:889
+#, c-format
+msgid "unable to write log file: %s"
+msgstr "impossível escrever o diário: %s"
+
+#: plugins/sudoers/match_digest.c:129
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "resumo para %s (%s) não está na forma %s"
+
+#: plugins/sudoers/parse.c:537
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+"\n"
+"Papel LDAP: %s\n"
+
+#: plugins/sudoers/parse.c:540
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+"\n"
+"Entrada sudoers:\n"
+
+#: plugins/sudoers/parse.c:542
+msgid " RunAsUsers: "
+msgstr " RunAsUsers: "
+
+#: plugins/sudoers/parse.c:557
+msgid " RunAsGroups: "
+msgstr " RunAsGroups: "
+
+#: plugins/sudoers/parse.c:567
+msgid " Options: "
+msgstr " Opções: "
+
+#: plugins/sudoers/parse.c:623
+msgid " Commands:\n"
+msgstr " Comandos:\n"
+
+#: plugins/sudoers/parse.c:814
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Entradas Defaults correspondentes para %s em %s:\n"
+
+#: plugins/sudoers/parse.c:832
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Predefinições Runas específicas de comandos para %s:\n"
+
+#: plugins/sudoers/parse.c:850
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "O utilizador %s pode executar os seguintes comandos em %s:\n"
+
+#: plugins/sudoers/parse.c:865
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "O utilizador %s não tem permissão para executar sudo em %s.\n"
+
+#: plugins/sudoers/parse_ldif.c:616
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "a ignorar sudoRole incompleto: cn: %s"
+
+#: plugins/sudoers/parse_ldif.c:676
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "atributo LDIF inválido: %s"
+
+#: plugins/sudoers/policy.c:80 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "%.*s inválido definido pelo front-end do sudo"
+
+#: plugins/sudoers/policy.c:320 plugins/sudoers/testsudoers.c:268
+msgid "unable to parse network address list"
+msgstr "impossível analisar a lista de endereços da rede"
+
+#: plugins/sudoers/policy.c:471
+msgid "user name not set by sudo front-end"
+msgstr "nome de utilizador não definido pelo front-end do sudo"
+
+#: plugins/sudoers/policy.c:475
+msgid "user-ID not set by sudo front-end"
+msgstr "ID de utilizador não definida pelo front-end do sudo"
+
+#: plugins/sudoers/policy.c:479
+msgid "group-ID not set by sudo front-end"
+msgstr "ID de grupo não definida pelo front-end do sudo"
+
+#: plugins/sudoers/policy.c:483
+msgid "host name not set by sudo front-end"
+msgstr "nome de anfitrião não definido pelo front-end do sudo"
+
+#: plugins/sudoers/policy.c:685
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "pasta de trabalho inválida: %s"
+
+#: plugins/sudoers/policy.c:861
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "pasta chroot inválida: %s"
+
+#: plugins/sudoers/policy.c:996 plugins/sudoers/visudo.c:229
+#: plugins/sudoers/visudo.c:851
+#, c-format
+msgid "unable to execute %s"
+msgstr "impossível executar %s"
+
+#: plugins/sudoers/policy.c:1066 plugins/sudoers/policy.c:1103
+#: plugins/sudoers/policy.c:1125 plugins/sudoers/policy.c:1151
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: bandeiras de modo inválidas do front-end do sudo: 0x%x"
+
+#: plugins/sudoers/policy.c:1182
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Extensão de política sudoers versão %s\n"
+
+#: plugins/sudoers/policy.c:1184
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Gramática do ficheiro sudoers versão %d\n"
+
+#: plugins/sudoers/policy.c:1188
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Caminho do sudoers: %s\n"
+
+#: plugins/sudoers/policy.c:1191
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "caminho nsswitch: %s\n"
+
+#: plugins/sudoers/policy.c:1193
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "caminho do ldap.conf: %s\n"
+
+#: plugins/sudoers/policy.c:1194
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "caminho do ldap.secret: %s\n"
+
+#: plugins/sudoers/policy.c:1227
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "impossível registar hook do tipo %d (versão %d.%d)"
+
+#: plugins/sudoers/policy.c:1245
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "impossível de-registar hook do tipo %d (versão %d.%d)"
+
+#: plugins/sudoers/pwutil.c:218 plugins/sudoers/pwutil.c:236
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "impossível guardar uid %u"
+
+#: plugins/sudoers/pwutil.c:230
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "impossível guardar uid %u, já existe"
+
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:308
+#: plugins/sudoers/pwutil.c:371 plugins/sudoers/pwutil.c:416
+#, c-format
+msgid "unable to cache user %s"
+msgstr "impossível guardar utilizador %s"
+
+#: plugins/sudoers/pwutil.c:303
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "impossível guardar utilizador %s, já existe"
+
+#: plugins/sudoers/pwutil.c:535 plugins/sudoers/pwutil.c:553
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "impossível guardar gid %u"
+
+#: plugins/sudoers/pwutil.c:547
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "impossível guardar gid %u, já existe"
+
+#: plugins/sudoers/pwutil.c:601 plugins/sudoers/pwutil.c:619
+#: plugins/sudoers/pwutil.c:680 plugins/sudoers/pwutil.c:729
+#, c-format
+msgid "unable to cache group %s"
+msgstr "impossível guardar grupo %s"
+
+#: plugins/sudoers/pwutil.c:614
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "impossível guardar grupo %s, já existe"
+
+#: plugins/sudoers/pwutil.c:876 plugins/sudoers/pwutil.c:927
+#: plugins/sudoers/pwutil.c:977 plugins/sudoers/pwutil.c:1029
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "impossível guardar lista de grupo para %s, já existe"
+
+#: plugins/sudoers/pwutil.c:882 plugins/sudoers/pwutil.c:932
+#: plugins/sudoers/pwutil.c:983 plugins/sudoers/pwutil.c:1034
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "impossível guardar lista de grupos para %s"
+
+#: plugins/sudoers/pwutil.c:921
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "impossível analisar grupos para %s"
+
+#: plugins/sudoers/pwutil.c:1023
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "impossível analisar gids para %s"
+
+#: plugins/sudoers/set_perms.c:114 plugins/sudoers/set_perms.c:445
+#: plugins/sudoers/set_perms.c:852 plugins/sudoers/set_perms.c:1162
+#: plugins/sudoers/set_perms.c:1460
+msgid "perm stack overflow"
+msgstr "transporte de pilha perm"
+
+#: plugins/sudoers/set_perms.c:125 plugins/sudoers/set_perms.c:376
+#: plugins/sudoers/set_perms.c:456 plugins/sudoers/set_perms.c:719
+#: plugins/sudoers/set_perms.c:863 plugins/sudoers/set_perms.c:1086
+#: plugins/sudoers/set_perms.c:1173 plugins/sudoers/set_perms.c:1393
+#: plugins/sudoers/set_perms.c:1471 plugins/sudoers/set_perms.c:1562
+msgid "perm stack underflow"
+msgstr "importe de pilha perm"
+
+#: plugins/sudoers/set_perms.c:185 plugins/sudoers/set_perms.c:503
+#: plugins/sudoers/set_perms.c:1227 plugins/sudoers/set_perms.c:1505
+msgid "unable to change to root gid"
+msgstr "impossível mudar para gid root"
+
+#: plugins/sudoers/set_perms.c:276 plugins/sudoers/set_perms.c:600
+#: plugins/sudoers/set_perms.c:995 plugins/sudoers/set_perms.c:1304
+msgid "unable to change to runas gid"
+msgstr "impossível mudar para gid runas"
+
+#: plugins/sudoers/set_perms.c:281 plugins/sudoers/set_perms.c:605
+#: plugins/sudoers/set_perms.c:1000 plugins/sudoers/set_perms.c:1309
+msgid "unable to set runas group vector"
+msgstr "impossível definir vector de grupo runas"
+
+#: plugins/sudoers/set_perms.c:292 plugins/sudoers/set_perms.c:616
+#: plugins/sudoers/set_perms.c:1009 plugins/sudoers/set_perms.c:1318
+msgid "unable to change to runas uid"
+msgstr "impossível mudar para uid runas"
+
+#: plugins/sudoers/set_perms.c:310 plugins/sudoers/set_perms.c:634
+#: plugins/sudoers/set_perms.c:1025 plugins/sudoers/set_perms.c:1334
+msgid "unable to change to sudoers gid"
+msgstr "impossível mudar para gid sudoers"
+
+#: plugins/sudoers/set_perms.c:363 plugins/sudoers/set_perms.c:706
+#: plugins/sudoers/set_perms.c:1073 plugins/sudoers/set_perms.c:1380
+#: plugins/sudoers/set_perms.c:1549
+msgid "too many processes"
+msgstr "demasiados processos"
+
+#: plugins/sudoers/solaris_audit.c:61
+msgid "unable to get current working directory"
+msgstr "impossível obter a pasta de trabalho actual"
+
+#: plugins/sudoers/solaris_audit.c:69
+#, c-format
+msgid "truncated audit path user_cmnd: %s"
+msgstr "caminho de auditoria truncado user_cmnd: %s"
+
+#: plugins/sudoers/solaris_audit.c:76
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "caminho de auditoria truncado argv[0]: %s"
+
+#: plugins/sudoers/sssd.c:572
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "impossível inicializar fonte SSS. Tem o SSSD instalado?"
+
+#: plugins/sudoers/sssd.c:580 plugins/sudoers/sssd.c:589
+#: plugins/sudoers/sssd.c:598 plugins/sudoers/sssd.c:607
+#: plugins/sudoers/sssd.c:616
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "impossível encontrar símbolo \"%s\" em %s"
+
+#: plugins/sudoers/sudoers.c:166 plugins/sudoers/sudoers.c:174
+#: plugins/sudoers/sudoers.c:228 plugins/sudoers/sudoers.c:249
+#: plugins/sudoers/sudoers.c:1040
+msgid "problem with defaults entries"
+msgstr "problema com entradas defaults"
+
+#: plugins/sudoers/sudoers.c:253
+msgid "no valid sudoers sources found, quitting"
+msgstr "sme fontes sudoers válidas, a sair"
+
+#: plugins/sudoers/sudoers.c:327
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "utilizador sem permissão para alterar pasta chroot para %s"
+
+#: plugins/sudoers/sudoers.c:329
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "não tem permissão para usar a opção -R com %s"
+
+#: plugins/sudoers/sudoers.c:354
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "utilizador sem permissão para alterar pasta para %s"
+
+#: plugins/sudoers/sudoers.c:355
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "não tem permissão para usar a opção -D com %s"
+
+#: plugins/sudoers/sudoers.c:382
+msgid "no command specified"
+msgstr "nenhum comando especificado"
+
+#: plugins/sudoers/sudoers.c:407
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers especifica que root não tem permissão para sudo"
+
+#: plugins/sudoers/sudoers.c:457
+msgid "user not allowed to override closefrom limit"
+msgstr "utilizador não autorizado a sobrepor o limite closefrom"
+
+#: plugins/sudoers/sudoers.c:458
+msgid "you are not permitted to use the -C option"
+msgstr "não tem permissão para usar a opção -C"
+
+#: plugins/sudoers/sudoers.c:518
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr "dono da datação (%s): utilizador inexistente"
+
+#: plugins/sudoers/sudoers.c:533
+msgid "no tty"
+msgstr "sem tty"
+
+#: plugins/sudoers/sudoers.c:534
+msgid "sorry, you must have a tty to run sudo"
+msgstr "desculpe, tem de ter um tty para executar sudo"
+
+#: plugins/sudoers/sudoers.c:541
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "shell inválida para o utilizador %s: %s"
+
+#: plugins/sudoers/sudoers.c:624
+msgid "command in current directory"
+msgstr "comando na pasta actual"
+
+#: plugins/sudoers/sudoers.c:643
+msgid "user not allowed to set a command timeout"
+msgstr "utilizador sem permissão para definir um tempo de expiração"
+
+#: plugins/sudoers/sudoers.c:645
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "desculpe, não tem permissão para definir um tempo de inacção"
+
+#: plugins/sudoers/sudoers.c:653
+msgid "user not allowed to preserve the environment"
+msgstr "utilizador sem permissão para definir preservar o ambiente"
+
+#: plugins/sudoers/sudoers.c:655
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "desculpe, não tem permissão para preservar o ambiente"
+
+#: plugins/sudoers/sudoers.c:989
+msgid "command too long"
+msgstr "comando muito longo"
+
+#: plugins/sudoers/sudoers.c:1028
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "sudoedit não precisa de ser executado via sudo"
+
+#: plugins/sudoers/sudoers.c:1087 plugins/sudoers/sudoreplay.c:1568
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "impossível ler %s"
+
+#: plugins/sudoers/sudoers.c:1112 plugins/sudoers/visudo.c:426
+#: plugins/sudoers/visudo.c:720
+#, c-format
+msgid "unable to stat %s"
+msgstr "impossível obter informações de %s"
+
+#: plugins/sudoers/sudoers.c:1116 plugins/sudoers/visudo.c:1009
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s não é um ficheiro normal"
+
+#: plugins/sudoers/sudoers.c:1120 plugins/sudoers/timestamp.c:252 toke.l:1148
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s é propriedade de uid %u, deveria ser %u"
+
+#: plugins/sudoers/sudoers.c:1124 toke.l:1153
+#, c-format
+msgid "%s is world writable"
+msgstr "%s é escrito universalmente"
+
+#: plugins/sudoers/sudoers.c:1128 toke.l:1156
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s é propriedade de gid %u, deveria ser %u"
+
+#: plugins/sudoers/sudoers.c:1161
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "só root pode usar \"-c %s\""
+
+#: plugins/sudoers/sudoers.c:1180
+#, c-format
+msgid "unknown login class %s"
+msgstr "classe de sessão desconhecida %s"
+
+#: plugins/sudoers/sudoers.c:1266 plugins/sudoers/sudoers.c:1281
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "impossível resolver o anfitrião %s"
+
+#: plugins/sudoers/sudoreplay.c:259
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "opção de filtro inválida: %s"
+
+#: plugins/sudoers/sudoreplay.c:275
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "espera máxima inválida: %s"
+
+#: plugins/sudoers/sudoreplay.c:298
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "factor de velocidade inválido: %s"
+
+#: plugins/sudoers/sudoreplay.c:333
+#, c-format
+msgid "invalid time offset %s"
+msgstr "desvio de tempo %s inválido"
+
+#: plugins/sudoers/sudoreplay.c:342
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:347
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/temporização: %s"
+
+#: plugins/sudoers/sudoreplay.c:375
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "A reproduzir sessão sudo: %s"
+
+#: plugins/sudoers/sudoreplay.c:637
+msgid "unable to set tty to raw mode"
+msgstr "impossível definir tty para modo raw"
+
+#: plugins/sudoers/sudoreplay.c:688
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr "Aviso: o seu terminal é muito pequeno para reproduzir correctamente o diário.\n"
+
+#: plugins/sudoers/sudoreplay.c:689
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "A geometria do diário é %d x %d, o seu terminal é %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:717
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Reprodução terminada, prima qualquer tecla para restaurar o terminal."
+
+#: plugins/sudoers/sudoreplay.c:1218 plugins/sudoers/sudoreplay.c:1248
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "expressão ambígua \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1270
+msgid "unmatched ')' in expression"
+msgstr "\")\" sem par em expressão"
+
+#: plugins/sudoers/sudoreplay.c:1274
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "termo de procura \"%s\" desconhecido"
+
+#: plugins/sudoers/sudoreplay.c:1289
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s requer um argumento"
+
+#: plugins/sudoers/sudoreplay.c:1292 plugins/sudoers/sudoreplay.c:1544
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr "expressão regular inválida: %s"
+
+#: plugins/sudoers/sudoreplay.c:1297
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "impossível analisar a data \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1306
+msgid "unmatched '(' in expression"
+msgstr "\"(\" sem par em expressão"
+
+#: plugins/sudoers/sudoreplay.c:1308
+msgid "illegal trailing \"or\""
+msgstr "\"or\" final ilegal"
+
+#: plugins/sudoers/sudoreplay.c:1310
+msgid "illegal trailing \"!\""
+msgstr "\"!\" final ilegal"
+
+#: plugins/sudoers/sudoreplay.c:1368
+#, c-format
+msgid "unknown search type %d"
+msgstr "tipo de procura %d desconhecido"
+
+#: plugins/sudoers/sudoreplay.c:1635
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "uso: %s [-hnRS] [-d pasta] [-m núm] [-s núm] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1638
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "uso: %s [-h] [-d pasta] -l [expressão de procura]\n"
+
+#: plugins/sudoers/sudoreplay.c:1647
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - reproduz os diários de sessão sudo\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1649
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Opções:\n"
+" -d, --directory=pasta especifica a pasta para diários de sessão\n"
+" -f, --filter=filtro especifica os tipos de E/S a mostrar\n"
+" -h, --help mostra a ajuda e sai\n"
+" -l, --list lista as IDs de sessão disponíveis, com expressão opcional\n"
+" -m, --max-wait=número número máximo de segundos a aguardar entre eventos\n"
+" -n, --non-interactive sem prompts, a sessão é enviada para a saída padrão\n"
+" -R, --no-resize não tenta redimensionar o terminal\n"
+" -S, --suspend-wait espera enquanto o comando foi suspenso\n"
+" -s, --speed=número acelera ou trava a saída\n"
+" -V, --version mostra informação da versão e sai"
+
+#: plugins/sudoers/testsudoers.c:344
+msgid "\thost unmatched"
+msgstr "\thost sem correspondência"
+
+#: plugins/sudoers/testsudoers.c:347
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Comando permitido"
+
+#: plugins/sudoers/testsudoers.c:348
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Comando negado"
+
+#: plugins/sudoers/testsudoers.c:348
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Comando sem correspondência"
+
+#: plugins/sudoers/timestamp.c:260
+#, c-format
+msgid "%s is group writable"
+msgstr "%s é escrito pelo grupo"
+
+#: plugins/sudoers/timestamp.c:328 plugins/sudoers/timestamp.c:663
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "impossível truncar o ficheiro de datação para %lld bytes"
+
+#: plugins/sudoers/timestamp.c:860
+msgid "ignoring time stamp from the future"
+msgstr "a ignorar datação do futuro"
+
+#: plugins/sudoers/timestamp.c:883
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "datação demasiado no futuro: %20.20s"
+
+#: plugins/sudoers/timestamp.c:1005
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "impossível bloquear ficheiro de datação %s"
+
+#: plugins/sudoers/timestamp.c:1049 plugins/sudoers/timestamp.c:1069
+#, c-format
+msgid "lecture status path too long: %s/%s"
+msgstr "caminho do estado da lição de moral muito longo: %s/%s"
+
+#: plugins/sudoers/toke_util.c:150
+msgid "sudoedit should not be specified with a path"
+msgstr "sudoedit não deve ser especificado com um caminho"
+
+#: plugins/sudoers/visudo.c:224
+msgid "the -x option will be removed in a future release"
+msgstr "a opção -x será removida numa futura versão"
+
+#: plugins/sudoers/visudo.c:226
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "por favor, considere usar antes o utilitário cvtsudoers"
+
+#: plugins/sudoers/visudo.c:277 plugins/sudoers/visudo.c:653
+#, c-format
+msgid "press return to edit %s: "
+msgstr "prima Enter para editar %s: "
+
+#: plugins/sudoers/visudo.c:338
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "o editor especificado (%s) não existe"
+
+#: plugins/sudoers/visudo.c:340
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "sem editor (caminho do editor = %s)"
+
+#: plugins/sudoers/visudo.c:446 plugins/sudoers/visudo.c:454
+msgid "write error"
+msgstr "erro de escrita"
+
+#: plugins/sudoers/visudo.c:500
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "impossível obter informação do ficheiro temporário (%s), %s inalterado"
+
+#: plugins/sudoers/visudo.c:507
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "ficheiro temporário de tamanho zero (%s), %s inalterado"
+
+#: plugins/sudoers/visudo.c:513
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "falha no editor (%s), %s inalterado"
+
+#: plugins/sudoers/visudo.c:535
+#, c-format
+msgid "%s unchanged"
+msgstr "%s inalterado"
+
+#: plugins/sudoers/visudo.c:592
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "impossível reabrir o ficheiro temporário (%s), %s inalterado."
+
+#: plugins/sudoers/visudo.c:604
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "impossível analisar o ficheiro temporário (%s), erro desconhecido"
+
+#: plugins/sudoers/visudo.c:642
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr "erro interno, impossível encontrar %s na lista!"
+
+#: plugins/sudoers/visudo.c:722 plugins/sudoers/visudo.c:731
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "impossível definir (uid, gid) de %s para (%u, %u)"
+
+#: plugins/sudoers/visudo.c:754
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s e %s em sistemas de ficheiros diferentes, a usar mv para renomear"
+
+#: plugins/sudoers/visudo.c:765
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "falha no comando: \"%s %s %s\", %s inalterado"
+
+#: plugins/sudoers/visudo.c:775
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "erro ao renomear %s, %s inalterado"
+
+#: plugins/sudoers/visudo.c:796
+msgid "What now? "
+msgstr "E agora? "
+
+#: plugins/sudoers/visudo.c:810
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"As opções são:\n"
+" (e) editar o ficheiro sudoers de novo\n"
+" (x) sair sem gravar as alterações ao ficheiro sudoers\n"
+" (Q) sair e gravar as alterações ao ficheiro sudoers (PERIGO!)\n"
+
+#: plugins/sudoers/visudo.c:856
+#, c-format
+msgid "unable to run %s"
+msgstr "impossível executar %s"
+
+#: plugins/sudoers/visudo.c:886
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: dono errrado (uid, gid), deveria ser (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:893
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: permissões erradas, devia ser modo 0%o\n"
+
+#: plugins/sudoers/visudo.c:942 plugins/sudoers/visudo.c:949
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: análise com sucesso\n"
+
+#: plugins/sudoers/visudo.c:968
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s ocupado, tente mais tarde"
+
+#: plugins/sudoers/visudo.c:972
+msgid "Edit anyway? [y/N]"
+msgstr "Editar mesmo assim ? [y/N]"
+
+#: plugins/sudoers/visudo.c:1068
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "Aviso: %s:%d:%d: não usado %s \"%s\""
+
+#: plugins/sudoers/visudo.c:1184
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - editar com segurança o ficheiro sudoers\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1186
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Opções:\n"
+" -c, --check modo só de verificação\n"
+" -f, --file=sudoers especifica a localização do ficheiro sudoers\n"
+" -h, --help mostra a ajuda e sai\n"
+" -q, --quiet mensagens de erro de sintaxe menos verbosas (silêncio)\n"
+" -s, --strict verificação de sintaxe estrita\n"
+" -V, --version mostra informação da versão e sai\n"
+
+#: toke.l:187
+msgid "empty string"
+msgstr "cadeia vazia"
+
+#: toke.l:199 toke.l:513
+msgid "empty group"
+msgstr "grupo vazio"
+
+#: toke.l:209 toke.l:511
+msgid "empty netgroup"
+msgstr "grupo de rede vazio"
+
+#: toke.l:305 toke.l:317 toke.l:329 toke.l:345 toke.l:364 toke.l:404
+msgid "invalid line continuation"
+msgstr "continuação de linha inválida"
+
+#: toke.l:550 toke.l:562
+msgid "invalid IPv6 address"
+msgstr "endereço IPv6 inválido"
+
+#: toke.l:789
+msgid "unexpected line break in string"
+msgstr "quebra de linha inesperada em cadeia"
+
+#: toke.l:1119
+msgid "too many levels of includes"
+msgstr "demasiados níveis de includes"
+
+#~ msgid "%s:%d unknown key: %s"
+#~ msgstr "%s:%d chave desconhecida: %s"
+
+#~ msgid "unable to get TLS server method: %s"
+#~ msgstr "impossível obter método TLS do servidor: %s"
+
+#~ msgid "%s:%u unable to parse \"%s\""
+#~ msgstr "%s:%u impossível analisar \"%s\""
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " -f, --file path to configuration file\n"
+#~ " -h --help display help message and exit\n"
+#~ " -n, --no-fork do not fork, run in the foreground\n"
+#~ " -R, --random-drop percent chance connections will drop\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Opções:\n"
+#~ " -f, --file caminho para o ficheiro de configuração\n"
+#~ " -h --help mostrar a mensagem de ajuda e sair\n"
+#~ " -n, --no-fork não bifurcar, executar em 2º plano\n"
+#~ " -R, --random-drop percentagem de hipóteses das ligações caírem\n"
+#~ " -V, --version mostrar informação da versão e sair\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " --help display help message and exit\n"
+#~ " -A, --accept only send an accept event (no I/O)\n"
+#~ " -h, --host host to send logs to\n"
+#~ " -i, --iolog_id remote ID of I/O log to be resumed\n"
+#~ " -p, --port port to use when connecting to host\n"
+#~ " -r, --restart restart previous I/O log transfer\n"
+#~ " -R, --reject reject the command with the given reason\n"
+#~ " -b, --ca-bundle certificate bundle file to verify server's cert against\n"
+#~ " -c, --cert certificate file for TLS handshake\n"
+#~ " -k, --key private key file\n"
+#~ " -n, --no-verify do not verify server certificate\n"
+#~ " -t, --test test audit server by sending selected I/O log n times in parallel\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Opções:\n"
+#~ " --help mostrar a mensagem de ajuda e sair\n"
+#~ " -A, --accept enviar só um evento de aceitação (sem E/S)\n"
+#~ " -h, --host anfitrião a quem enviar os diários\n"
+#~ " -i, --iolog_id ID remota do diário de E/S a resumir\n"
+#~ " -p, --port porta a usar ao ligar ao anfitrião\n"
+#~ " -r, --restart reiniciar a transferência de diário de E/S prévia\n"
+#~ " -R, --reject rejeitar o comando com o motivo dado\n"
+#~ " -b, --ca-bundle ficheiro de pacote de certificados para comparar com o do servidor\n"
+#~ " -c, --cert ficheiro de certificado para o handshake TLS\n"
+#~ " -k, --key ficheiro de chave privada\n"
+#~ " -n, --no-verify não verificar o certificado do servidor\n"
+#~ " -t, --test testar servidor de auditoria enviando o diário de E/S seleccionado n vezes em paralelo\n"
+#~ " -V, --version mostrar informação da versão e sair\n"
+
+#~ msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+#~ msgstr "Pré-carregar as funções dummy exec contidas na biblioteca sudo_noexec"
+
+#~ msgid "sudo_ldap_conf_add_ports: port too large"
+#~ msgstr "sudo_ldap_conf_add_ports: porta muito grande"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s\n"
+#~ msgstr "SSL_connect falhou: ssl_error=%d, stack=%s\n"
+
+#~ msgid "CA bundle file was not specified"
+#~ msgstr "ficheiro de pacote CA não especificado"
+
+#~ msgid "Client certificate was not specified"
+#~ msgstr "Certificado do cliente não especificado"
+
+#~ msgid "Unable to allocate ssl object: %s\n"
+#~ msgstr "Impossível alocar objecto ssl: %s\n"
+
+#~ msgid "Unable to attach socket to the ssl object: %s\n"
+#~ msgstr "Impossível anexar socket ao objecto ssl: %s\n"
+
+#~ msgid "client message too large: %zu\n"
+#~ msgstr "mensagem do cliente muito grande: %zu\n"
+
+#~ msgid "server message too large: %u\n"
+#~ msgstr "mensagem do servidor muito grande: %u\n"
+
+#~ msgid "CA bundle file is not set in sudoers"
+#~ msgstr "Ficheiro de pacote CA não definido em sudoers"
+
+#~ msgid "Calling SSL_CTX_load_verify_locations() failed: %s"
+#~ msgstr "Falha ao chamar SSL_CTX_load_verify_locations(): %s"
+
+#~ msgid "Signed certificate file is not set in sudoers"
+#~ msgstr "Ficheiro de certificado assinado não definido em sudoers"
+
+#~ msgid "Unable to load private key into the ssl context: %s"
+#~ msgstr "Impossível carregar chave privada no contexto ssl: %s"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_connect falhoud: ssl_error=%d, stack=%s"
+
+#~ msgid "SSL_read failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_read falhou: ssl_error=%d, stack=%s"
+
+#~ msgid "SSL_write failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_write falhou: ssl_error=%d, stack=%s"
+
+#~ msgid "unknown address family: %d"
+#~ msgstr "família de endereços desconhecida: %d"
+
+#~ msgid "audit_failure message too long"
+#~ msgstr "mensagem audit_failure muito longa"
+
+#~ msgid "No user or host"
+#~ msgstr "Sem utilizador ou anfitrião"
+
+#~ msgid "validation failure"
+#~ msgstr "falha de validação"
+
+#~ msgid "%s/%s/timing: %s"
+#~ msgstr "%s/%s/temporização: %s"
+
+#~ msgid "ignoring invalid attribute value: %s"
+#~ msgstr "a ignorar valor de atributo inválido: %s"
+
+#~ msgid "unable to cache user %s, out of memory"
+#~ msgstr "impossível guardar utilizador %s, sem memória"
+
+#~ msgid "unable to cache group %s, out of memory"
+#~ msgstr "impossível guardar grupo %s, sem memória"
+
+#~ msgid "unable to cache group list for %s, out of memory"
+#~ msgstr "impossível guardar lista de grupo para %s, sem memória"
diff --git a/plugins/sudoers/po/pt_BR.mo b/plugins/sudoers/po/pt_BR.mo
new file mode 100644
index 0000000..cb87305
--- /dev/null
+++ b/plugins/sudoers/po/pt_BR.mo
Binary files differ
diff --git a/plugins/sudoers/po/pt_BR.po b/plugins/sudoers/po/pt_BR.po
new file mode 100644
index 0000000..576ea25
--- /dev/null
+++ b/plugins/sudoers/po/pt_BR.po
@@ -0,0 +1,3801 @@
+# Brazilian Portuguese translation for sudoers plugin.
+# Traduções em português brasileiro para o pacote sudoers.
+# Copyright (C) 2021 Free Software Foundation, Inc.
+# This file is distributed under the same license as the sudo package.
+# Rafael Fontenelle <rafaelff@gnome.org>, 2013-2021.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.9.8b2\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2021-08-19 09:50-0600\n"
+"PO-Revision-Date: 2021-08-22 10:47-0300\n"
+"Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n"
+"Language-Team: Brazilian Portuguese <ldpbr-translation@lists.sourceforge.net>\n"
+"Language: pt_BR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1)\n"
+"X-Generator: Gtranslator 40.0\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+
+#: confstr.sh:1 gram.y:1191
+msgid "syntax error"
+msgstr "erro de sintaxe"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "senha do %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] senha para %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Senha: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** Informação de SEGURANÇA para %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Sinto muito, tente novamente."
+
+#: gram.y:235 gram.y:302 gram.y:311 gram.y:320 gram.y:330 gram.y:340
+#: gram.y:364 gram.y:391 gram.y:400 gram.y:408 gram.y:417 gram.y:426
+#: gram.y:500 gram.y:510 gram.y:522 gram.y:566 gram.y:575 gram.y:584
+#: gram.y:593 gram.y:712 gram.y:720 gram.y:731 gram.y:743 gram.y:762
+#: gram.y:917 gram.y:922 gram.y:930 gram.y:940 gram.y:946 gram.y:1068
+#: gram.y:1077 gram.y:1085 gram.y:1094 gram.y:1103 gram.y:1132 gram.y:1141
+#: gram.y:1149 gram.y:1239 gram.y:1351 gram.y:1658 gram.y:1708
+#: lib/eventlog/eventlog.c:308 lib/eventlog/eventlog.c:381
+#: lib/eventlog/eventlog.c:783 lib/eventlog/eventlog.c:862
+#: lib/eventlog/eventlog.c:1146 lib/iolog/iolog_json.c:125
+#: lib/iolog/iolog_json.c:330 lib/iolog/iolog_json.c:360
+#: lib/iolog/iolog_json.c:503 lib/iolog/iolog_legacy.c:100
+#: lib/iolog/iolog_legacy.c:111 lib/iolog/iolog_legacy.c:123
+#: lib/iolog/iolog_legacy.c:133 lib/iolog/iolog_legacy.c:139
+#: lib/iolog/iolog_loginfo.c:76 lib/iolog/iolog_loginfo.c:210
+#: logsrvd/iolog_writer.c:85 logsrvd/iolog_writer.c:90
+#: logsrvd/iolog_writer.c:124 logsrvd/iolog_writer.c:172
+#: logsrvd/iolog_writer.c:212 logsrvd/iolog_writer.c:225
+#: logsrvd/iolog_writer.c:261 logsrvd/iolog_writer.c:286
+#: logsrvd/iolog_writer.c:301 logsrvd/iolog_writer.c:314
+#: logsrvd/iolog_writer.c:327 logsrvd/iolog_writer.c:340
+#: logsrvd/iolog_writer.c:355 logsrvd/iolog_writer.c:393
+#: logsrvd/iolog_writer.c:399 logsrvd/iolog_writer.c:406
+#: logsrvd/iolog_writer.c:412 logsrvd/iolog_writer.c:596
+#: logsrvd/logsrv_util.c:62 logsrvd/logsrvd.c:302 logsrvd/logsrvd.c:311
+#: logsrvd/logsrvd.c:1017 logsrvd/logsrvd.c:1079 logsrvd/logsrvd_conf.c:1361
+#: logsrvd/logsrvd_journal.c:71 logsrvd/logsrvd_journal.c:204
+#: logsrvd/logsrvd_journal.c:205 logsrvd/logsrvd_journal.c:261
+#: logsrvd/logsrvd_journal.c:426 logsrvd/logsrvd_journal.c:428
+#: logsrvd/logsrvd_local.c:173 logsrvd/logsrvd_local.c:174
+#: logsrvd/logsrvd_local.c:236 logsrvd/logsrvd_local.c:237
+#: logsrvd/logsrvd_local.c:317 logsrvd/logsrvd_local.c:318
+#: logsrvd/logsrvd_local.c:323 logsrvd/logsrvd_local.c:324
+#: logsrvd/logsrvd_queue.c:155 logsrvd/logsrvd_queue.c:185
+#: logsrvd/logsrvd_queue.c:262 logsrvd/logsrvd_relay.c:445
+#: logsrvd/logsrvd_relay.c:744 logsrvd/logsrvd_relay.c:846
+#: logsrvd/sendlog.c:302 logsrvd/sendlog.c:501 plugins/sudoers/audit.c:114
+#: plugins/sudoers/audit.c:271 plugins/sudoers/auth/bsdauth.c:143
+#: plugins/sudoers/auth/kerb5.c:118 plugins/sudoers/auth/kerb5.c:144
+#: plugins/sudoers/auth/pam.c:691 plugins/sudoers/auth/rfc1938.c:111
+#: plugins/sudoers/auth/sia.c:59 plugins/sudoers/check_aliases.c:95
+#: plugins/sudoers/cvtsudoers.c:119 plugins/sudoers/cvtsudoers.c:160
+#: plugins/sudoers/cvtsudoers.c:177 plugins/sudoers/cvtsudoers.c:188
+#: plugins/sudoers/cvtsudoers.c:300 plugins/sudoers/cvtsudoers.c:428
+#: plugins/sudoers/cvtsudoers.c:561 plugins/sudoers/cvtsudoers.c:578
+#: plugins/sudoers/cvtsudoers.c:646 plugins/sudoers/cvtsudoers.c:761
+#: plugins/sudoers/cvtsudoers.c:769 plugins/sudoers/cvtsudoers.c:1183
+#: plugins/sudoers/cvtsudoers.c:1187 plugins/sudoers/cvtsudoers.c:1289
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:151
+#: plugins/sudoers/cvtsudoers_ldif.c:194 plugins/sudoers/cvtsudoers_ldif.c:235
+#: plugins/sudoers/cvtsudoers_ldif.c:300 plugins/sudoers/cvtsudoers_ldif.c:371
+#: plugins/sudoers/cvtsudoers_ldif.c:425 plugins/sudoers/cvtsudoers_ldif.c:433
+#: plugins/sudoers/cvtsudoers_ldif.c:444 plugins/sudoers/cvtsudoers_ldif.c:451
+#: plugins/sudoers/cvtsudoers_ldif.c:464 plugins/sudoers/cvtsudoers_ldif.c:472
+#: plugins/sudoers/cvtsudoers_ldif.c:619 plugins/sudoers/defaults.c:652
+#: plugins/sudoers/defaults.c:947 plugins/sudoers/defaults.c:1122
+#: plugins/sudoers/editor.c:190 plugins/sudoers/env.c:262
+#: plugins/sudoers/exptilde.c:92 plugins/sudoers/filedigest.c:54
+#: plugins/sudoers/filedigest.c:70 plugins/sudoers/gc.c:57
+#: plugins/sudoers/group_plugin.c:133 plugins/sudoers/interfaces.c:68
+#: plugins/sudoers/iolog.c:606 plugins/sudoers/iolog.c:623
+#: plugins/sudoers/ldap.c:184 plugins/sudoers/ldap.c:422
+#: plugins/sudoers/ldap.c:432 plugins/sudoers/ldap.c:437
+#: plugins/sudoers/ldap.c:441 plugins/sudoers/ldap.c:453
+#: plugins/sudoers/ldap.c:744 plugins/sudoers/ldap.c:908
+#: plugins/sudoers/ldap.c:1281 plugins/sudoers/ldap.c:1709
+#: plugins/sudoers/ldap.c:1746 plugins/sudoers/ldap.c:1827
+#: plugins/sudoers/ldap.c:1962 plugins/sudoers/ldap.c:2063
+#: plugins/sudoers/ldap.c:2079 plugins/sudoers/ldap_conf.c:218
+#: plugins/sudoers/ldap_conf.c:249 plugins/sudoers/ldap_conf.c:301
+#: plugins/sudoers/ldap_conf.c:337 plugins/sudoers/ldap_conf.c:441
+#: plugins/sudoers/ldap_conf.c:456 plugins/sudoers/ldap_conf.c:553
+#: plugins/sudoers/ldap_conf.c:586 plugins/sudoers/ldap_conf.c:678
+#: plugins/sudoers/ldap_conf.c:760 plugins/sudoers/ldap_util.c:293
+#: plugins/sudoers/ldap_util.c:300 plugins/sudoers/ldap_util.c:615
+#: plugins/sudoers/linux_audit.c:86 plugins/sudoers/log_client.c:108
+#: plugins/sudoers/log_client.c:386 plugins/sudoers/log_client.c:699
+#: plugins/sudoers/log_client.c:720 plugins/sudoers/log_client.c:1440
+#: plugins/sudoers/log_client.c:1656 plugins/sudoers/log_client.c:1980
+#: plugins/sudoers/log_client.c:2037 plugins/sudoers/logging.c:101
+#: plugins/sudoers/logging.c:181 plugins/sudoers/logging.c:465
+#: plugins/sudoers/logging.c:485 plugins/sudoers/logging.c:627
+#: plugins/sudoers/match_command.c:297 plugins/sudoers/match_command.c:497
+#: plugins/sudoers/match_command.c:546 plugins/sudoers/match_command.c:618
+#: plugins/sudoers/match_command.c:666 plugins/sudoers/match_digest.c:93
+#: plugins/sudoers/parse.c:201 plugins/sudoers/parse.c:218
+#: plugins/sudoers/parse.c:238 plugins/sudoers/parse.c:255
+#: plugins/sudoers/parse.c:278 plugins/sudoers/parse.c:289
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:260
+#: plugins/sudoers/parse_ldif.c:265 plugins/sudoers/parse_ldif.c:341
+#: plugins/sudoers/parse_ldif.c:352 plugins/sudoers/parse_ldif.c:379
+#: plugins/sudoers/parse_ldif.c:396 plugins/sudoers/parse_ldif.c:408
+#: plugins/sudoers/parse_ldif.c:412 plugins/sudoers/parse_ldif.c:426
+#: plugins/sudoers/parse_ldif.c:483 plugins/sudoers/parse_ldif.c:596
+#: plugins/sudoers/parse_ldif.c:626 plugins/sudoers/parse_ldif.c:651
+#: plugins/sudoers/parse_ldif.c:709 plugins/sudoers/parse_ldif.c:726
+#: plugins/sudoers/parse_ldif.c:754 plugins/sudoers/parse_ldif.c:761
+#: plugins/sudoers/policy.c:556 plugins/sudoers/policy.c:923
+#: plugins/sudoers/prompt.c:93 plugins/sudoers/pwutil.c:195
+#: plugins/sudoers/pwutil.c:266 plugins/sudoers/pwutil.c:344
+#: plugins/sudoers/pwutil.c:518 plugins/sudoers/pwutil.c:583
+#: plugins/sudoers/pwutil.c:655 plugins/sudoers/pwutil.c:853
+#: plugins/sudoers/pwutil.c:909 plugins/sudoers/pwutil.c:953
+#: plugins/sudoers/pwutil.c:1010 plugins/sudoers/sssd.c:145
+#: plugins/sudoers/sssd.c:407 plugins/sudoers/sssd.c:470
+#: plugins/sudoers/sssd.c:514 plugins/sudoers/sssd.c:561
+#: plugins/sudoers/sssd.c:754 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/stubs.c:111 plugins/sudoers/stubs.c:119
+#: plugins/sudoers/sudoers.c:335 plugins/sudoers/sudoers.c:361
+#: plugins/sudoers/sudoers.c:429 plugins/sudoers/sudoers.c:438
+#: plugins/sudoers/sudoers.c:479 plugins/sudoers/sudoers.c:833
+#: plugins/sudoers/sudoers.c:971 plugins/sudoers/sudoers.c:1030
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:565 plugins/sudoers/sudoreplay.c:1280
+#: plugins/sudoers/sudoreplay.c:1490 plugins/sudoers/sudoreplay.c:1494
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:224
+#: plugins/sudoers/testsudoers.c:241 plugins/sudoers/testsudoers.c:580
+#: plugins/sudoers/timestamp.c:424 plugins/sudoers/timestamp.c:468
+#: plugins/sudoers/timestamp.c:980 plugins/sudoers/timestamp.c:1118
+#: plugins/sudoers/toke_util.c:77 plugins/sudoers/toke_util.c:105
+#: plugins/sudoers/toke_util.c:130 plugins/sudoers/toke_util.c:155
+#: plugins/sudoers/toke_util.c:193 plugins/sudoers/tsdump.c:123
+#: plugins/sudoers/visudo.c:143 plugins/sudoers/visudo.c:321
+#: plugins/sudoers/visudo.c:327 plugins/sudoers/visudo.c:433
+#: plugins/sudoers/visudo.c:609 plugins/sudoers/visudo.c:926
+#: plugins/sudoers/visudo.c:999 toke.l:938 toke.l:1067 toke.l:1127
+msgid "unable to allocate memory"
+msgstr "não foi possível alocar memória"
+
+#: gram.y:617
+msgid "a digest requires a path name"
+msgstr "um digest requer um nome de caminho"
+
+#: gram.y:639
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "valores para \"CWD\" devem iniciar com um \"/\", \"~\" ou \"*\""
+
+#: gram.y:651
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "valores para \"CHROOT\" devem iniciar com um \"/\", \"~\" ou \"*\""
+
+#: gram.y:782
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "erro de sintaxe, palavra reservada %s usada como um nome de alias"
+
+#: gram.y:805
+msgid "invalid notbefore value"
+msgstr "valor de notbefore inválido"
+
+#: gram.y:814
+msgid "invalid notafter value"
+msgstr "falha de notafter inválido"
+
+#: gram.y:824 plugins/sudoers/policy.c:345
+msgid "timeout value too large"
+msgstr "valor de timeout grande demais"
+
+#: gram.y:826 plugins/sudoers/policy.c:347
+msgid "invalid timeout value"
+msgstr "valor de timeout inválido"
+
+#: gram.y:1193
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: gram.y:1237
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Alias \"%s\" já definido"
+
+#: gram.y:1658 gram.y:1708 lib/eventlog/eventlog.c:308
+#: lib/eventlog/eventlog.c:783 lib/eventlog/eventlog.c:858
+#: lib/eventlog/eventlog.c:861 lib/eventlog/eventlog.c:1146
+#: lib/iolog/iolog_json.c:125 lib/iolog/iolog_json.c:329
+#: lib/iolog/iolog_json.c:360 lib/iolog/iolog_json.c:503
+#: lib/iolog/iolog_legacy.c:100 lib/iolog/iolog_legacy.c:111
+#: lib/iolog/iolog_legacy.c:123 lib/iolog/iolog_legacy.c:133
+#: lib/iolog/iolog_legacy.c:139 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:210 logsrvd/iolog_writer.c:85
+#: logsrvd/iolog_writer.c:90 logsrvd/iolog_writer.c:124
+#: logsrvd/iolog_writer.c:162 logsrvd/iolog_writer.c:171
+#: logsrvd/iolog_writer.c:189 logsrvd/iolog_writer.c:211
+#: logsrvd/iolog_writer.c:224 logsrvd/iolog_writer.c:251
+#: logsrvd/iolog_writer.c:260 logsrvd/iolog_writer.c:276
+#: logsrvd/iolog_writer.c:285 logsrvd/iolog_writer.c:300
+#: logsrvd/iolog_writer.c:313 logsrvd/iolog_writer.c:326
+#: logsrvd/iolog_writer.c:339 logsrvd/iolog_writer.c:354
+#: logsrvd/iolog_writer.c:393 logsrvd/iolog_writer.c:399
+#: logsrvd/iolog_writer.c:406 logsrvd/iolog_writer.c:412
+#: logsrvd/iolog_writer.c:596 logsrvd/logsrv_util.c:62 logsrvd/logsrvd.c:302
+#: logsrvd/logsrvd.c:311 logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:491
+#: logsrvd/logsrvd.c:599 logsrvd/logsrvd.c:1090 logsrvd/logsrvd.c:1402
+#: logsrvd/logsrvd.c:1408 logsrvd/logsrvd_conf.c:1361
+#: logsrvd/logsrvd_journal.c:71 logsrvd/logsrvd_journal.c:115
+#: logsrvd/logsrvd_journal.c:204 logsrvd/logsrvd_journal.c:234
+#: logsrvd/logsrvd_journal.c:238 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:269 logsrvd/logsrvd_journal.c:273
+#: logsrvd/logsrvd_journal.c:426 logsrvd/logsrvd_local.c:173
+#: logsrvd/logsrvd_local.c:236 logsrvd/logsrvd_local.c:317
+#: logsrvd/logsrvd_local.c:323 logsrvd/logsrvd_local.c:342
+#: logsrvd/logsrvd_queue.c:154 logsrvd/logsrvd_queue.c:185
+#: logsrvd/logsrvd_queue.c:262 logsrvd/sendlog.c:302 logsrvd/sendlog.c:501
+#: logsrvd/sendlog.c:1353 logsrvd/sendlog.c:1360 logsrvd/sendlog.c:1563
+#: logsrvd/tls_init.c:218 logsrvd/tls_init.c:239 logsrvd/tls_init.c:249
+#: plugins/sudoers/audit.c:114 plugins/sudoers/audit.c:271
+#: plugins/sudoers/auth/pam.c:505 plugins/sudoers/auth/pam.c:691
+#: plugins/sudoers/auth/rfc1938.c:111 plugins/sudoers/check_aliases.c:95
+#: plugins/sudoers/cvtsudoers.c:119 plugins/sudoers/cvtsudoers.c:159
+#: plugins/sudoers/cvtsudoers.c:176 plugins/sudoers/cvtsudoers.c:187
+#: plugins/sudoers/cvtsudoers.c:299 plugins/sudoers/cvtsudoers.c:427
+#: plugins/sudoers/cvtsudoers.c:560 plugins/sudoers/cvtsudoers.c:577
+#: plugins/sudoers/cvtsudoers.c:646 plugins/sudoers/cvtsudoers.c:761
+#: plugins/sudoers/cvtsudoers.c:768 plugins/sudoers/cvtsudoers.c:1183
+#: plugins/sudoers/cvtsudoers.c:1187 plugins/sudoers/cvtsudoers.c:1289
+#: plugins/sudoers/cvtsudoers_json.c:75 plugins/sudoers/cvtsudoers_ldif.c:150
+#: plugins/sudoers/cvtsudoers_ldif.c:193 plugins/sudoers/cvtsudoers_ldif.c:234
+#: plugins/sudoers/cvtsudoers_ldif.c:299 plugins/sudoers/cvtsudoers_ldif.c:370
+#: plugins/sudoers/cvtsudoers_ldif.c:424 plugins/sudoers/cvtsudoers_ldif.c:432
+#: plugins/sudoers/cvtsudoers_ldif.c:443 plugins/sudoers/cvtsudoers_ldif.c:450
+#: plugins/sudoers/cvtsudoers_ldif.c:463 plugins/sudoers/cvtsudoers_ldif.c:471
+#: plugins/sudoers/cvtsudoers_ldif.c:618 plugins/sudoers/defaults.c:652
+#: plugins/sudoers/defaults.c:947 plugins/sudoers/defaults.c:1122
+#: plugins/sudoers/editor.c:190 plugins/sudoers/env.c:262
+#: plugins/sudoers/exptilde.c:92 plugins/sudoers/filedigest.c:54
+#: plugins/sudoers/filedigest.c:70 plugins/sudoers/gc.c:57
+#: plugins/sudoers/group_plugin.c:132 plugins/sudoers/interfaces.c:68
+#: plugins/sudoers/iolog.c:606 plugins/sudoers/iolog.c:623
+#: plugins/sudoers/ldap.c:184 plugins/sudoers/ldap.c:422
+#: plugins/sudoers/ldap.c:432 plugins/sudoers/ldap.c:437
+#: plugins/sudoers/ldap.c:441 plugins/sudoers/ldap.c:453
+#: plugins/sudoers/ldap.c:744 plugins/sudoers/ldap.c:908
+#: plugins/sudoers/ldap.c:1281 plugins/sudoers/ldap.c:1709
+#: plugins/sudoers/ldap.c:1746 plugins/sudoers/ldap.c:1827
+#: plugins/sudoers/ldap.c:1962 plugins/sudoers/ldap.c:2063
+#: plugins/sudoers/ldap.c:2079 plugins/sudoers/ldap_conf.c:218
+#: plugins/sudoers/ldap_conf.c:249 plugins/sudoers/ldap_conf.c:301
+#: plugins/sudoers/ldap_conf.c:337 plugins/sudoers/ldap_conf.c:441
+#: plugins/sudoers/ldap_conf.c:456 plugins/sudoers/ldap_conf.c:553
+#: plugins/sudoers/ldap_conf.c:586 plugins/sudoers/ldap_conf.c:677
+#: plugins/sudoers/ldap_conf.c:760 plugins/sudoers/ldap_util.c:292
+#: plugins/sudoers/ldap_util.c:299 plugins/sudoers/ldap_util.c:615
+#: plugins/sudoers/linux_audit.c:86 plugins/sudoers/log_client.c:108
+#: plugins/sudoers/log_client.c:217 plugins/sudoers/log_client.c:238
+#: plugins/sudoers/log_client.c:251 plugins/sudoers/log_client.c:386
+#: plugins/sudoers/log_client.c:699 plugins/sudoers/log_client.c:720
+#: plugins/sudoers/log_client.c:1440 plugins/sudoers/log_client.c:1656
+#: plugins/sudoers/log_client.c:1980 plugins/sudoers/log_client.c:2037
+#: plugins/sudoers/logging.c:101 plugins/sudoers/logging.c:180
+#: plugins/sudoers/logging.c:181 plugins/sudoers/logging.c:464
+#: plugins/sudoers/logging.c:484 plugins/sudoers/logging.c:627
+#: plugins/sudoers/match_command.c:296 plugins/sudoers/match_command.c:496
+#: plugins/sudoers/match_command.c:545 plugins/sudoers/match_command.c:618
+#: plugins/sudoers/match_command.c:665 plugins/sudoers/match_digest.c:93
+#: plugins/sudoers/parse.c:200 plugins/sudoers/parse.c:217
+#: plugins/sudoers/parse.c:237 plugins/sudoers/parse.c:254
+#: plugins/sudoers/parse.c:277 plugins/sudoers/parse.c:288
+#: plugins/sudoers/parse_ldif.c:152 plugins/sudoers/parse_ldif.c:183
+#: plugins/sudoers/parse_ldif.c:252 plugins/sudoers/parse_ldif.c:259
+#: plugins/sudoers/parse_ldif.c:264 plugins/sudoers/parse_ldif.c:340
+#: plugins/sudoers/parse_ldif.c:351 plugins/sudoers/parse_ldif.c:378
+#: plugins/sudoers/parse_ldif.c:395 plugins/sudoers/parse_ldif.c:407
+#: plugins/sudoers/parse_ldif.c:411 plugins/sudoers/parse_ldif.c:425
+#: plugins/sudoers/parse_ldif.c:483 plugins/sudoers/parse_ldif.c:596
+#: plugins/sudoers/parse_ldif.c:625 plugins/sudoers/parse_ldif.c:650
+#: plugins/sudoers/parse_ldif.c:708 plugins/sudoers/parse_ldif.c:725
+#: plugins/sudoers/parse_ldif.c:753 plugins/sudoers/parse_ldif.c:760
+#: plugins/sudoers/policy.c:152 plugins/sudoers/policy.c:161
+#: plugins/sudoers/policy.c:170 plugins/sudoers/policy.c:197
+#: plugins/sudoers/policy.c:330 plugins/sudoers/policy.c:345
+#: plugins/sudoers/policy.c:347 plugins/sudoers/policy.c:377
+#: plugins/sudoers/policy.c:386 plugins/sudoers/policy.c:434
+#: plugins/sudoers/policy.c:444 plugins/sudoers/policy.c:453
+#: plugins/sudoers/policy.c:462 plugins/sudoers/policy.c:556
+#: plugins/sudoers/policy.c:923 plugins/sudoers/prompt.c:93
+#: plugins/sudoers/pwutil.c:195 plugins/sudoers/pwutil.c:266
+#: plugins/sudoers/pwutil.c:344 plugins/sudoers/pwutil.c:518
+#: plugins/sudoers/pwutil.c:583 plugins/sudoers/pwutil.c:655
+#: plugins/sudoers/pwutil.c:853 plugins/sudoers/pwutil.c:909
+#: plugins/sudoers/pwutil.c:953 plugins/sudoers/pwutil.c:1010
+#: plugins/sudoers/set_perms.c:363 plugins/sudoers/set_perms.c:706
+#: plugins/sudoers/set_perms.c:1073 plugins/sudoers/set_perms.c:1380
+#: plugins/sudoers/set_perms.c:1549 plugins/sudoers/sssd.c:144
+#: plugins/sudoers/sssd.c:407 plugins/sudoers/sssd.c:470
+#: plugins/sudoers/sssd.c:514 plugins/sudoers/sssd.c:561
+#: plugins/sudoers/sssd.c:754 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/stubs.c:111 plugins/sudoers/stubs.c:119
+#: plugins/sudoers/sudoers.c:335 plugins/sudoers/sudoers.c:361
+#: plugins/sudoers/sudoers.c:429 plugins/sudoers/sudoers.c:438
+#: plugins/sudoers/sudoers.c:479 plugins/sudoers/sudoers.c:833
+#: plugins/sudoers/sudoers.c:971 plugins/sudoers/sudoers.c:1030
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:565 plugins/sudoers/sudoreplay.c:1280
+#: plugins/sudoers/sudoreplay.c:1490 plugins/sudoers/sudoreplay.c:1494
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:224
+#: plugins/sudoers/testsudoers.c:241 plugins/sudoers/testsudoers.c:580
+#: plugins/sudoers/timestamp.c:424 plugins/sudoers/timestamp.c:468
+#: plugins/sudoers/timestamp.c:980 plugins/sudoers/timestamp.c:1118
+#: plugins/sudoers/toke_util.c:77 plugins/sudoers/toke_util.c:105
+#: plugins/sudoers/toke_util.c:130 plugins/sudoers/toke_util.c:154
+#: plugins/sudoers/toke_util.c:193 plugins/sudoers/tsdump.c:123
+#: plugins/sudoers/visudo.c:143 plugins/sudoers/visudo.c:321
+#: plugins/sudoers/visudo.c:327 plugins/sudoers/visudo.c:433
+#: plugins/sudoers/visudo.c:609 plugins/sudoers/visudo.c:926
+#: plugins/sudoers/visudo.c:999 toke.l:938 toke.l:1067 toke.l:1119 toke.l:1127
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:313 lib/iolog/iolog_json.c:509
+#: lib/iolog/iolog_json.c:512 lib/iolog/iolog_json.c:514
+#: plugins/sudoers/cvtsudoers_ldif.c:244 plugins/sudoers/cvtsudoers_ldif.c:251
+#: plugins/sudoers/cvtsudoers_ldif.c:575 plugins/sudoers/env.c:326
+#: plugins/sudoers/env.c:333 plugins/sudoers/env.c:444
+#: plugins/sudoers/iolog.c:628 plugins/sudoers/ldap.c:517
+#: plugins/sudoers/ldap.c:748 plugins/sudoers/ldap.c:1081
+#: plugins/sudoers/ldap_conf.c:222 plugins/sudoers/ldap_conf.c:312
+#: plugins/sudoers/linux_audit.c:92 plugins/sudoers/policy.c:586
+#: plugins/sudoers/policy.c:755 plugins/sudoers/policy.c:766
+#: plugins/sudoers/prompt.c:168 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/testsudoers.c:245 plugins/sudoers/toke_util.c:206
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "erro interno, estouro de pilha de %s"
+
+#: lib/eventlog/eventlog.c:372
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "não foi possível fazer dup da entrada padrão: %m"
+
+#: lib/eventlog/eventlog.c:414
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "não foi possível executar %s: %m"
+
+#: lib/eventlog/eventlog.c:455 plugins/sudoers/auth/aix_auth.c:198
+msgid "unable to fork"
+msgstr "não foi possível fazer fork"
+
+#: lib/eventlog/eventlog.c:463 lib/eventlog/eventlog.c:517
+#, c-format
+msgid "unable to fork: %m"
+msgstr "não foi possível fazer fork: %m"
+
+#: lib/eventlog/eventlog.c:507
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "não foi possível abrir um encadeamento (pipe): %m"
+
+#: lib/eventlog/eventlog.c:979
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:1008
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (comando continuado) %s"
+
+#: lib/iolog/iolog_json.c:115
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "esperava JSON_STRING, obteve %d"
+
+#: lib/iolog/iolog_json.c:120
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY grande demais"
+
+#: lib/iolog/iolog_json.c:352
+msgid "missing double quote in name"
+msgstr "faltando aspas duplas no nome"
+
+#: lib/iolog/iolog_json.c:449
+msgid "missing JSON_OBJECT"
+msgstr "faltando JSON_OBJECT"
+
+#: lib/iolog/iolog_json.c:453
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "esperava JSON_OBJECT, obteve %d"
+
+#: lib/iolog/iolog_json.c:599
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "pilha json esgotada (máx %u quadros)"
+
+#: lib/iolog/iolog_json.c:673
+msgid "objects must consist of name:value pairs"
+msgstr "objetos devem consistir de pares nome:valor"
+
+#: lib/iolog/iolog_json.c:678 lib/iolog/iolog_json.c:709
+#: lib/iolog/iolog_json.c:753 lib/iolog/iolog_json.c:775
+#: lib/iolog/iolog_json.c:797 lib/iolog/iolog_json.c:819
+#: lib/iolog/iolog_json.c:841
+msgid "missing separator between values"
+msgstr "faltando separador entre valores"
+
+#: lib/iolog/iolog_json.c:693 lib/iolog/iolog_json.c:867
+msgid "unmatched close brace"
+msgstr "chave de fechamento sem correspondente"
+
+#: lib/iolog/iolog_json.c:704
+msgid "unexpected array"
+msgstr "array inesperado"
+
+#: lib/iolog/iolog_json.c:724 lib/iolog/iolog_json.c:870
+msgid "unmatched close bracket"
+msgstr "colchete de fechamento sem correspondente"
+
+#: lib/iolog/iolog_json.c:735
+msgid "unexpected string"
+msgstr "string inesperada"
+
+#: lib/iolog/iolog_json.c:746
+msgid "missing colon after name"
+msgstr "faltando caractere de dois pontos após o nome"
+
+#: lib/iolog/iolog_json.c:767 lib/iolog/iolog_json.c:789
+msgid "unexpected boolean"
+msgstr "booleano inesperado"
+
+#: lib/iolog/iolog_json.c:811
+msgid "unexpected null"
+msgstr "nulo inesperado"
+
+#: lib/iolog/iolog_json.c:832
+msgid "unexpected number"
+msgstr "número inesperado"
+
+#: lib/iolog/iolog_json.c:879
+msgid "parse error"
+msgstr "erro de análise"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: arquivo de log inválido"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: campo de marca de tempo está faltando"
+
+#: lib/iolog/iolog_legacy.c:89
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: marca de tempo %s: %s"
+
+#: lib/iolog/iolog_legacy.c:96
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: campo de usuário está faltando"
+
+#: lib/iolog/iolog_legacy.c:107
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: campo de usuário, a ser executado como, está faltando"
+
+#: lib/iolog/iolog_legacy.c:118
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: campo de grupo, a ser executado como, está faltando"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s existe, mas não é um diretório (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:119 lib/iolog/iolog_mkdtemp.c:77
+#: logsrvd/iolog_writer.c:788 plugins/sudoers/timestamp.c:205
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "não foi possível fazer mkdir %s"
+
+#: lib/iolog/iolog_mkdtemp.c:81 plugins/sudoers/visudo.c:726
+#: plugins/sudoers/visudo.c:737
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "não foi possível alterar modo de %s para 0%o"
+
+# timing é o nome do arquivo gerado pelo sudo; não traduzir.
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "erro ao ler o arquivo timing: %s"
+
+# timing é o nome do arquivo gerado pelo sudo; não traduzir.
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "linha inválida no arquivo timing: %s"
+
+#: logsrvd/iolog_writer.c:131 plugins/sudoers/logging.c:803
+#: plugins/sudoers/policy.c:536
+msgid "unable to generate UUID"
+msgstr "não foi possível gerar o UUID"
+
+#: logsrvd/iolog_writer.c:158 logsrvd/iolog_writer.c:176
+#: logsrvd/iolog_writer.c:185 logsrvd/iolog_writer.c:203
+#: logsrvd/iolog_writer.c:216 logsrvd/iolog_writer.c:229
+#: logsrvd/iolog_writer.c:240 logsrvd/iolog_writer.c:247
+#: logsrvd/iolog_writer.c:265 logsrvd/iolog_writer.c:272
+#: logsrvd/iolog_writer.c:290 logsrvd/iolog_writer.c:305
+#: logsrvd/iolog_writer.c:318 logsrvd/iolog_writer.c:331
+#: logsrvd/iolog_writer.c:344 logsrvd/iolog_writer.c:359
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s erro de protocolo: tipo errado para %s"
+
+#: logsrvd/iolog_writer.c:370 logsrvd/iolog_writer.c:375
+#: logsrvd/iolog_writer.c:380 logsrvd/iolog_writer.c:385
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s: erro de protocolo: faltando %s de AcceptMessage"
+
+#: logsrvd/iolog_writer.c:446
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s: não foi possível formatar o id de sessão"
+
+#: logsrvd/iolog_writer.c:460 logsrvd/iolog_writer.c:474
+#: logsrvd/iolog_writer.c:488 logsrvd/iolog_writer.c:503
+#: logsrvd/iolog_writer.c:517 logsrvd/iolog_writer.c:531
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s: %s não está definido"
+
+#: logsrvd/iolog_writer.c:567 logsrvd/iolog_writer.c:574
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr "não foi possível expandir o caminho de iolog %s"
+
+#: logsrvd/iolog_writer.c:592
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr "não foi possível criar o caminho de iolog %s"
+
+#: logsrvd/iolog_writer.c:622
+#, c-format
+msgid "invalid iofd %d"
+msgstr "iofd inválido %d"
+
+#: logsrvd/iolog_writer.c:642
+#, c-format
+msgid "error closing iofd %d: %s"
+msgstr "erro ao fechar o iofd %d: %s"
+
+#: logsrvd/iolog_writer.c:758
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "log de E/S inválido %s: %s referenciado, mas não definido"
+
+#: logsrvd/iolog_writer.c:770 logsrvd/logsrvd_journal.c:378
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "%s: não foi possível localizar o ponto de resumo [%lld, %ld]"
+
+#: logsrvd/iolog_writer.c:792 logsrvd/logsrvd_journal.c:421
+#: logsrvd/logsrvd_queue.c:111 logsrvd/tls_init.c:293
+#: plugins/sudoers/check.c:274 plugins/sudoers/cvtsudoers.c:618
+#: plugins/sudoers/cvtsudoers.c:639 plugins/sudoers/cvtsudoers.c:1249
+#: plugins/sudoers/cvtsudoers_json.c:877 plugins/sudoers/cvtsudoers_ldif.c:692
+#: plugins/sudoers/sudoers.c:1083 plugins/sudoers/sudoreplay.c:1456
+#: plugins/sudoers/timestamp.c:433 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:913
+#, c-format
+msgid "unable to open %s"
+msgstr "não foi possível abrir %s"
+
+#: logsrvd/iolog_writer.c:804 logsrvd/logsrv_util.c:98
+#: logsrvd/logsrv_util.c:105 plugins/sudoers/sudoreplay.c:362
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "não foi possível abrir %s/%s"
+
+#: logsrvd/iolog_writer.c:817
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "não foi possível copiar %s/%s para %s/%s: %s"
+
+#: logsrvd/iolog_writer.c:846 logsrvd/logsrvd_journal.c:186
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "não foi possível renomear %s para %s"
+
+#: logsrvd/logsrv_util.c:132
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "faltando arquivo de log de E/S %s/%s"
+
+#: logsrvd/logsrv_util.c:139
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s: não foi possível buscar para frente %zu"
+
+#: logsrvd/logsrv_util.c:149
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s: não foi possível localizar o ponto de resumo [%lld, %ld]"
+
+#: logsrvd/logsrvd.c:272 logsrvd/logsrvd_queue.c:131
+msgid "unable to connect to relay"
+msgstr "não foi possível conectar à retransmissão"
+
+#: logsrvd/logsrvd.c:331 logsrvd/logsrvd_relay.c:838
+#, c-format
+msgid "server message too large: %zu"
+msgstr "mensagem do servidor grande demais: %zu"
+
+#: logsrvd/logsrvd.c:423 logsrvd/logsrvd.c:540 logsrvd/logsrvd.c:619
+#: logsrvd/logsrvd.c:843 logsrvd/logsrvd.c:857 logsrvd/logsrvd.c:1016
+#: logsrvd/logsrvd.c:1140 logsrvd/logsrvd.c:1309 logsrvd/logsrvd.c:1327
+#: logsrvd/logsrvd.c:1425 logsrvd/logsrvd.c:1548 logsrvd/logsrvd.c:1732
+#: logsrvd/logsrvd_journal.c:485 logsrvd/logsrvd_local.c:196
+#: logsrvd/logsrvd_queue.c:160 logsrvd/logsrvd_relay.c:173
+#: logsrvd/logsrvd_relay.c:250 logsrvd/logsrvd_relay.c:254
+#: logsrvd/logsrvd_relay.c:390 logsrvd/logsrvd_relay.c:582
+#: logsrvd/logsrvd_relay.c:743 logsrvd/logsrvd_relay.c:1124
+#: logsrvd/sendlog.c:1156 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:214 plugins/sudoers/audit.c:281
+#: plugins/sudoers/iolog.c:966 plugins/sudoers/iolog.c:1099
+#: plugins/sudoers/iolog.c:1197 plugins/sudoers/log_client.c:112
+#: plugins/sudoers/log_client.c:328 plugins/sudoers/log_client.c:344
+#: plugins/sudoers/log_client.c:391 plugins/sudoers/log_client.c:595
+#: plugins/sudoers/log_client.c:602 plugins/sudoers/log_client.c:1127
+#: plugins/sudoers/log_client.c:1409 plugins/sudoers/log_client.c:1450
+#: plugins/sudoers/log_client.c:1458 plugins/sudoers/log_client.c:1612
+#: plugins/sudoers/log_client.c:1728 plugins/sudoers/log_client.c:2045
+#: plugins/sudoers/log_client.c:2053 plugins/sudoers/logging.c:139
+#: plugins/sudoers/logging.c:195 plugins/sudoers/sudoreplay.c:522
+#: plugins/sudoers/sudoreplay.c:569 plugins/sudoers/sudoreplay.c:811
+#: plugins/sudoers/sudoreplay.c:923 plugins/sudoers/sudoreplay.c:1014
+#: plugins/sudoers/sudoreplay.c:1029 plugins/sudoers/sudoreplay.c:1036
+#: plugins/sudoers/sudoreplay.c:1043 plugins/sudoers/sudoreplay.c:1050
+#: plugins/sudoers/sudoreplay.c:1057 plugins/sudoers/sudoreplay.c:1184
+msgid "unable to add event to queue"
+msgstr "não foi possível adicionar evento para a fila"
+
+#: logsrvd/logsrvd.c:447 logsrvd/logsrvd.c:484 logsrvd/logsrvd.c:516
+#: logsrvd/logsrvd.c:564 logsrvd/logsrvd.c:636 logsrvd/logsrvd.c:666
+#: logsrvd/logsrvd.c:696 logsrvd/logsrvd.c:726 logsrvd/logsrvd_relay.c:511
+#: logsrvd/logsrvd_relay.c:544
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr "estado inesperado %d para %s"
+
+#: logsrvd/logsrvd.c:448 logsrvd/logsrvd.c:485 logsrvd/logsrvd.c:517
+#: logsrvd/logsrvd.c:565 logsrvd/logsrvd.c:637 logsrvd/logsrvd.c:667
+#: logsrvd/logsrvd.c:697 logsrvd/logsrvd.c:727 logsrvd/logsrvd_relay.c:513
+#: logsrvd/logsrvd_relay.c:546
+msgid "state machine error"
+msgstr "erro na máquina de estado"
+
+#: logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:455
+msgid "invalid AcceptMessage"
+msgstr "AcceptMessage inválido"
+
+#: logsrvd/logsrvd.c:491 logsrvd/logsrvd.c:492
+msgid "invalid RejectMessage"
+msgstr "RejectMessage inválido"
+
+#: logsrvd/logsrvd.c:599 logsrvd/logsrvd.c:600
+msgid "invalid AlertMessage"
+msgstr "AlertMessage inválido"
+
+#: logsrvd/logsrvd.c:641 logsrvd/logsrvd.c:671 logsrvd/logsrvd.c:701
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s: IoBuffer inesperado"
+
+#: logsrvd/logsrvd.c:642 logsrvd/logsrvd.c:672 logsrvd/logsrvd.c:702
+msgid "protocol error"
+msgstr "erro de protocolo"
+
+#: logsrvd/logsrvd.c:797 logsrvd/logsrvd_journal.c:358
+#: logsrvd/logsrvd_local.c:125 logsrvd/logsrvd_relay.c:677
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "type_case com valor inesperado %d em %s de %s"
+
+#: logsrvd/logsrvd.c:799
+msgid "unrecognized ClientMessage type"
+msgstr "tipo não reconhecido de ClientMessage"
+
+#: logsrvd/logsrvd.c:889
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "esgotado o tempo limite de escrita para cliente %s"
+
+#: logsrvd/logsrvd.c:894 logsrvd/logsrvd_relay.c:910
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr "faltando buffer de escrita para cliente %s"
+
+#: logsrvd/logsrvd.c:987
+#, c-format
+msgid "timed out reading from client %s"
+msgstr "esgotado o tempo limite de leitura do cliente %s"
+
+#: logsrvd/logsrvd.c:1028 logsrvd/logsrvd_relay.c:774
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr "EOF de %s sem desligamento TLS adequado"
+
+#: logsrvd/logsrvd.c:1071 logsrvd/logsrvd_relay.c:206 logsrvd/sendlog.c:290
+#: plugins/sudoers/log_client.c:705
+#, c-format
+msgid "client message too large: %zu"
+msgstr "mensagem do cliente grande demais: %zu"
+
+#: logsrvd/logsrvd.c:1072 logsrvd/logsrvd_journal.c:247
+#: logsrvd/logsrvd_journal.c:248
+msgid "client message too large"
+msgstr "mensagem do cliente grande demais"
+
+#: logsrvd/logsrvd.c:1090 logsrvd/logsrvd.c:1091
+msgid "invalid ClientMessage"
+msgstr "ClientMessage inválido"
+
+#: logsrvd/logsrvd.c:1388
+msgid "unable to get remote IP addr"
+msgstr "não foi possível obter o endereço IP remoto"
+
+#: logsrvd/logsrvd.c:1417 logsrvd/tls_client.c:201
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "Não foi possível anexar dados do usuário ao objeto ssl: %s"
+
+#: logsrvd/logsrvd.c:1598 logsrvd/logsrvd.c:1951
+msgid "unable to setup listen socket"
+msgstr "não foi possível configurar soquete de escuta"
+
+#: logsrvd/logsrvd.c:1715
+#, c-format
+msgid "unexpected signal %d"
+msgstr "string inesperada %d"
+
+#: logsrvd/logsrvd.c:1853
+msgid "sudo log server"
+msgstr "servidor de log do sudo"
+
+#: logsrvd/logsrvd.c:1855 logsrvd/sendlog.c:122
+msgid "Options:"
+msgstr "Opções:"
+
+#: logsrvd/logsrvd.c:1857
+msgid "path to configuration file"
+msgstr "caminho para o arquivo de autenticação"
+
+#: logsrvd/logsrvd.c:1859 logsrvd/sendlog.c:124
+msgid "display help message and exit"
+msgstr "exibe uma mensagem de ajuda e sai"
+
+#: logsrvd/logsrvd.c:1861
+msgid "do not fork, run in the foreground"
+msgstr "não faz fork, executa em primeiro plano"
+
+#: logsrvd/logsrvd.c:1863
+msgid "percent chance connections will drop"
+msgstr "chance em porcentagem das conexões caírem"
+
+#: logsrvd/logsrvd.c:1865 logsrvd/sendlog.c:154
+msgid "display version information and exit"
+msgstr "exibe as informações de versão e sai"
+
+#: logsrvd/logsrvd.c:1915 logsrvd/sendlog.c:1532
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "Protobuf-C versão 1.3 ou superior é necessário"
+
+# "random-drop" foi uma escolha por fazer referência à opção de linha de comando -- Rafael
+#: logsrvd/logsrvd.c:1931
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "valor de \"random-drop\" inválido: %s"
+
+#: logsrvd/logsrvd.c:1934 logsrvd/sendlog.c:1586
+#: plugins/sudoers/cvtsudoers.c:228 plugins/sudoers/sudoreplay.c:301
+#: plugins/sudoers/visudo.c:175
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s versão %s\n"
+
+#: logsrvd/logsrvd_conf.c:391 plugins/sudoers/check.c:336
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:115
+#: plugins/sudoers/policy.c:1159 plugins/sudoers/sudoers.c:486
+#: plugins/sudoers/sudoers.c:1338 plugins/sudoers/testsudoers.c:215
+#: plugins/sudoers/testsudoers.c:382
+#, c-format
+msgid "unknown user %s"
+msgstr "usuário desconhecido %s"
+
+#: logsrvd/logsrvd_conf.c:408 plugins/sudoers/iolog.c:140
+#: plugins/sudoers/sudoers.c:491 plugins/sudoers/sudoers.c:1372
+#: plugins/sudoers/testsudoers.c:406
+#, c-format
+msgid "unknown group %s"
+msgstr "grupo desconhecido %s"
+
+#: logsrvd/logsrvd_conf.c:426
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr "não foi possível analisar o modo iolog %s"
+
+#: logsrvd/logsrvd_conf.c:443 logsrvd/logsrvd_conf.c:1172
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "valor inválido para %s: %s"
+
+#: logsrvd/logsrvd_conf.c:482
+msgid "TLS not supported"
+msgstr "sem suporte a TLS"
+
+#: logsrvd/logsrvd_conf.c:504
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:577 logsrvd/logsrvd_conf.c:971
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s: não um caminho totalmente qualificado"
+
+#: logsrvd/logsrvd_conf.c:889 logsrvd/logsrvd_conf.c:905
+#: logsrvd/logsrvd_conf.c:1587
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "facilidade de syslog desconhecida %s"
+
+#: logsrvd/logsrvd_conf.c:921 logsrvd/logsrvd_conf.c:937
+#: logsrvd/logsrvd_conf.c:953 logsrvd/logsrvd_conf.c:1591
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1599
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "prioridade de syslog desconhecida %s"
+
+#: logsrvd/logsrvd_conf.c:1133
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d \"[\" sem correspondente: %s"
+
+#: logsrvd/logsrvd_conf.c:1144
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s:%d seção inválida de configuração: %s"
+
+#: logsrvd/logsrvd_conf.c:1152
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d linha inválida de configuração: %s"
+
+#: logsrvd/logsrvd_conf.c:1158
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d esperava um nome de seção: %s"
+
+#: logsrvd/logsrvd_conf.c:1180
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] chave ilegal: %s"
+
+#: logsrvd/logsrvd_conf.c:1210 plugins/sudoers/logging.c:856
+#, c-format
+msgid "unable to open log file %s"
+msgstr "não foi possível abrir o arquivo de log %s"
+
+#: logsrvd/logsrvd_conf.c:1667
+msgid "unable to initialize server TLS context"
+msgstr "não foi possível inicializar o contexto TLS do servidor"
+
+#: logsrvd/logsrvd_conf.c:1687
+msgid "unable to initialize relay TLS context"
+msgstr "não foi possível inicializar o contexto TLS da retransmissão"
+
+#: logsrvd/logsrvd_journal.c:137 logsrvd/logsrvd_journal.c:417
+#: logsrvd/logsrvd_journal.c:422
+msgid "unable to create journal file"
+msgstr "não foi possível criar o arquivo de journal"
+
+#: logsrvd/logsrvd_journal.c:141 logsrvd/logsrvd_queue.c:105
+#: plugins/sudoers/visudo.c:971
+#, c-format
+msgid "unable to lock %s"
+msgstr "não foi possível travar %s"
+
+#: logsrvd/logsrvd_journal.c:144
+msgid "unable to lock journal file"
+msgstr "não foi possível travar o arquivo de journal"
+
+#: logsrvd/logsrvd_journal.c:152
+msgid "unable to open journal file"
+msgstr "não foi possível abrir o arquivo de journal"
+
+#: logsrvd/logsrvd_journal.c:173 logsrvd/logsrvd_journal.c:453
+#: logsrvd/logsrvd_journal.c:458
+msgid "unable to write journal file"
+msgstr "não foi possível escrever o arquivo de journal"
+
+#: logsrvd/logsrvd_journal.c:181 logsrvd/logsrvd_journal.c:188
+msgid "unable to rename journal file"
+msgstr "não foi possível renomear o arquivo de journal"
+
+#: logsrvd/logsrvd_journal.c:235 logsrvd/logsrvd_journal.c:236
+#: logsrvd/logsrvd_journal.c:270 logsrvd/logsrvd_journal.c:271
+msgid "unexpected EOF reading journal file"
+msgstr "EOF inesperado ao ler o arquivo de journal"
+
+#: logsrvd/logsrvd_journal.c:239 logsrvd/logsrvd_journal.c:240
+#: logsrvd/logsrvd_journal.c:274 logsrvd/logsrvd_journal.c:275
+msgid "error reading journal file"
+msgstr "erro ao ler o arquivo de journal"
+
+#: logsrvd/logsrvd_journal.c:286 logsrvd/logsrvd_journal.c:377
+msgid "invalid journal file, unable to restart"
+msgstr "arquivo de journal inválido, não foi possível reiniciar"
+
+#: logsrvd/logsrvd_journal.c:436
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "não foi possível procurar [%lld, %ld] em arquivo de journal %s"
+
+#: logsrvd/logsrvd_local.c:152
+msgid "error parsing AcceptMessage"
+msgstr "erro ao analisar AcceptMessage"
+
+#: logsrvd/logsrvd_local.c:163
+msgid "error creating I/O log"
+msgstr "erro ao criar o log de E/S"
+
+#: logsrvd/logsrvd_local.c:186
+msgid "error logging accept event"
+msgstr "erro a registrar log de evento de aceite"
+
+#: logsrvd/logsrvd_local.c:225
+msgid "error parsing RejectMessage"
+msgstr "erro ao analisar RejectMessage"
+
+#: logsrvd/logsrvd_local.c:249
+msgid "error logging reject event"
+msgstr "erro a registrar log de evento de rejeição"
+
+#: logsrvd/logsrvd_local.c:284
+msgid "error logging exit event"
+msgstr "erro a registrar log de evento de saída"
+
+#: logsrvd/logsrvd_local.c:343 logsrvd/logsrvd_local.c:344
+msgid "log is already complete, cannot be restarted"
+msgstr "o log já está completo, não é possível ser reiniciado"
+
+#: logsrvd/logsrvd_local.c:374
+msgid "unable to restart log"
+msgstr "não foi possível reiniciar o log"
+
+#: logsrvd/logsrvd_local.c:390
+msgid "error parsing AlertMessage"
+msgstr "erro ao analisar AlertMessage"
+
+#: logsrvd/logsrvd_local.c:400
+msgid "error logging alert event"
+msgstr "erro a registrar log de evento de alerta"
+
+#: logsrvd/logsrvd_local.c:435 logsrvd/logsrvd_local.c:488
+#: logsrvd/logsrvd_local.c:523
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr "não é possível formatar o buffer de tempo, comprimento %d"
+
+#: logsrvd/logsrvd_local.c:442 logsrvd/logsrvd_local.c:450
+#: logsrvd/logsrvd_local.c:495 logsrvd/logsrvd_local.c:530
+#: plugins/sudoers/sudoreplay.c:351
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: logsrvd/logsrvd_local.c:470
+msgid "error writing IoBuffer"
+msgstr "erro ao escrever IoBuffer"
+
+#: logsrvd/logsrvd_local.c:505
+msgid "error writing ChangeWindowSize"
+msgstr "erro ao escrever ChangeWindowSize"
+
+#: logsrvd/logsrvd_local.c:540
+msgid "error writing CommandSuspend"
+msgstr "erro ao escrever CommandSuspend"
+
+#: logsrvd/logsrvd_relay.c:436
+msgid "TLS handshake with relay host failed"
+msgstr "falha na negociação TLS com host de retransmissão"
+
+#: logsrvd/logsrvd_relay.c:464
+msgid "unable to connect to relay host"
+msgstr "não foi possível conectar ao host de retransmissão"
+
+#: logsrvd/logsrvd_relay.c:519
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s: ServerHello inválido, faltando server_id"
+
+#: logsrvd/logsrvd_relay.c:521 logsrvd/sendlog.c:961
+#: plugins/sudoers/log_client.c:1493
+msgid "invalid ServerHello"
+msgstr "ServerHello inválido"
+
+#: logsrvd/logsrvd_relay.c:680
+msgid "unrecognized ServerMessage type"
+msgstr "tipo não reconhecido de ServerMessage"
+
+#: logsrvd/logsrvd_relay.c:709
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr "esgotado o tempo limite de leitura da retransmissão %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:711
+msgid "timeout reading from relay"
+msgstr "esgotado o tempo limite de leitura da retransmissão"
+
+#: logsrvd/logsrvd_relay.c:762
+msgid "relay host name does not match certificate"
+msgstr "o nome do host de retransmissão não corresponde ao certificado"
+
+#: logsrvd/logsrvd_relay.c:766 logsrvd/logsrvd_relay.c:779
+#: logsrvd/logsrvd_relay.c:785
+msgid "error reading from relay"
+msgstr "erro ao ler da retransmissão"
+
+#: logsrvd/logsrvd_relay.c:806
+msgid "unable to read from relay"
+msgstr "não foi possível ler da retransmissão"
+
+#: logsrvd/logsrvd_relay.c:821 logsrvd/logsrvd_relay.c:939
+msgid "relay server closed connection"
+msgstr "conexão fechada com o servidor de retransmissão"
+
+#: logsrvd/logsrvd_relay.c:839
+msgid "server message too large"
+msgstr "mensagem do servidor grande demais"
+
+#: logsrvd/logsrvd_relay.c:903
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr "esgotado o tempo limite de escrita para retransmissão %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:905
+msgid "timeout writing to relay"
+msgstr "esgotado o tempo limite de escrita para retransmissão"
+
+#: logsrvd/logsrvd_relay.c:958 logsrvd/logsrvd_relay.c:964
+#: logsrvd/logsrvd_relay.c:974
+msgid "error writing to relay"
+msgstr "erro ao escrever para retransmissão"
+
+#: logsrvd/sendlog.c:120
+msgid "send sudo I/O log to remote server"
+msgstr "envia log de E/S do sudo para servidor remoto"
+
+#: logsrvd/sendlog.c:126
+msgid "only send an accept event (no I/O)"
+msgstr "só envia um evento de aceite (sem E/S)"
+
+#: logsrvd/sendlog.c:129
+msgid "certificate bundle file to verify server's cert against"
+msgstr "arquivo de pacote de certificados para verificar o certificado do servidor"
+
+#: logsrvd/sendlog.c:131
+msgid "certificate file for TLS handshake"
+msgstr "arquivo de certificado para negociação TLS"
+
+#: logsrvd/sendlog.c:134
+msgid "host to send logs to"
+msgstr "máquina a ser enviado logs"
+
+#: logsrvd/sendlog.c:136
+msgid "remote ID of I/O log to be resumed"
+msgstr "ID remoto do log de E/S para ser resumido"
+
+#: logsrvd/sendlog.c:139
+msgid "private key file"
+msgstr "arquivo de chave privada"
+
+#: logsrvd/sendlog.c:141
+msgid "do not verify server certificate"
+msgstr "não verifica o certificado do servidor"
+
+#: logsrvd/sendlog.c:144
+msgid "port to use when connecting to host"
+msgstr "porta para usar ao conectar à máquina"
+
+#: logsrvd/sendlog.c:146
+msgid "restart previous I/O log transfer"
+msgstr "reinicia transferência anterior de log de E/S"
+
+#: logsrvd/sendlog.c:148
+msgid "reject the command with the given reason"
+msgstr "rejeita a comando com o motivo dado"
+
+#: logsrvd/sendlog.c:150
+msgid "stop transfer after reaching this time"
+msgstr "interrompe a transferência após chegar a este tempo"
+
+#: logsrvd/sendlog.c:152
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "testa o servidor de auditoria enviando o log de E/S selecionado n vezes em paralelo"
+
+#: logsrvd/sendlog.c:177 plugins/sudoers/log_client.c:437
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "não foi possível procurar %s:%s: %s"
+
+#: logsrvd/sendlog.c:215
+msgid "unable to get server IP addr"
+msgstr "não foi possível obter o endereço IP"
+
+#: logsrvd/sendlog.c:269 plugins/sudoers/sudoreplay.c:871
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "não foi possível ler %s/%s: %s"
+
+#: logsrvd/sendlog.c:831
+#, c-format
+msgid "%s: write buffer already in use"
+msgstr "%s: buffer de escrita já em uso"
+
+#: logsrvd/sendlog.c:892 plugins/sudoers/iolog.c:890
+#: plugins/sudoers/iolog.c:959
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "E/S com evento inesperado %d"
+
+#: logsrvd/sendlog.c:938 logsrvd/sendlog.c:955 logsrvd/sendlog.c:989
+#: plugins/sudoers/log_client.c:1142 plugins/sudoers/log_client.c:1419
+#: plugins/sudoers/log_client.c:1487 plugins/sudoers/log_client.c:1526
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: estado inesperado %d"
+
+#: logsrvd/sendlog.c:1025 plugins/sudoers/log_client.c:1570
+#, c-format
+msgid "error message received from server: %s"
+msgstr "mensagem de erro recebida do servidor: %s"
+
+#: logsrvd/sendlog.c:1038 plugins/sudoers/log_client.c:1583
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "mensagem de abortar recebida do servidor: %s"
+
+#: logsrvd/sendlog.c:1097 plugins/sudoers/log_client.c:1633
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s: type_case com valor inesperado %d"
+
+#: logsrvd/sendlog.c:1126
+msgid "timeout reading from server"
+msgstr "esgotado o tempo limite de leitura do servidor"
+
+#: logsrvd/sendlog.c:1205
+msgid "premature EOF"
+msgstr "EOF prematuro"
+
+#: logsrvd/sendlog.c:1218 plugins/sudoers/log_client.c:1791
+#, c-format
+msgid "server message too large: %u"
+msgstr "mensagem do servidor grande demais: %u"
+
+#: logsrvd/sendlog.c:1269
+msgid "timeout writing to server"
+msgstr "esgotado o tempo limite de escrita para servidor"
+
+#: logsrvd/sendlog.c:1609
+msgid "both restart point and iolog ID must be specified"
+msgstr "ambos ponto de ponto de reinício e ID do iolog devem ser especificados"
+
+#: logsrvd/sendlog.c:1613
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "um ponto de reinício pode não estar definido quando nenhuma E/S é enviada"
+
+#: logsrvd/sendlog.c:1689
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "sai prematuramente com estado %d"
+
+#: logsrvd/sendlog.c:1690
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "tempo decorrido enviado ao servidor [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1692
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "ponto de confirmação recebido do servidor [%lld, %ld]"
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:300
+msgid "TLS handshake timeout occurred"
+msgstr "esgotado o tempo limite da negociação TLS"
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:322 plugins/sudoers/log_client.c:338
+msgid "unable to set event"
+msgstr "não foi possível definir evento"
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "falha de conexão de TLS: %s"
+
+#: logsrvd/tls_client.c:195
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "não foi possível alocar objeto ssl: %s"
+
+#: logsrvd/tls_client.c:208
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "Não foi possível anexar soquete ao objeto ssl: %s"
+
+#: logsrvd/tls_client.c:236
+msgid "unable to initialize TLS context"
+msgstr "não foi possível inicializar o contexto TLS"
+
+#: logsrvd/tls_init.c:126 logsrvd/tls_init.c:134
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "não foi possível definir conjunto de cifras TLS 1.2 para %s: %s"
+
+#: logsrvd/tls_init.c:154 logsrvd/tls_init.c:162
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "não foi possível definir conjunto de cifras TLS 1.3 para %s: %s"
+
+#: logsrvd/tls_init.c:197
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "não foi possível criar o contexto de TLS: %s"
+
+#: logsrvd/tls_init.c:203
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "não foi possível definir a versão mínima do protocolo para TLS 1.2: %s"
+
+#: logsrvd/tls_init.c:279
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "não foi possível definir os parâmetros de diffie-hellman: %s"
+
+#: logsrvd/tls_init.c:288
+#, c-format
+msgid "unable to read diffie-hellman parameters: %s"
+msgstr "não foi possível ler os parâmetros de diffie-hellman: %s"
+
+#: plugins/sudoers/audit.c:267 plugins/sudoers/audit.c:422
+#: plugins/sudoers/log_client.c:975 plugins/sudoers/log_client.c:1024
+#: plugins/sudoers/log_client.c:1073 plugins/sudoers/log_client.c:1199
+#: plugins/sudoers/logging.c:554 plugins/sudoers/logging.c:648
+#: plugins/sudoers/logging.c:810 plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr "não foi possível obter o horário do dia"
+
+#: plugins/sudoers/auth/aix_auth.c:277
+#, c-format
+msgid "unable to change password for %s"
+msgstr "não foi possível alterar a senha para %s"
+
+#: plugins/sudoers/auth/bsdauth.c:70
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "não foi possível obter classe de login para o usuário %s"
+
+#: plugins/sudoers/auth/bsdauth.c:75
+msgid "unable to begin bsd authentication"
+msgstr "não foi possível iniciar autenticação BSD"
+
+#: plugins/sudoers/auth/bsdauth.c:83
+msgid "invalid authentication type"
+msgstr "tipo de autenticação inválida"
+
+#: plugins/sudoers/auth/bsdauth.c:92
+msgid "unable to initialize BSD authentication"
+msgstr "não foi possível inicializar autenticação BSD"
+
+#: plugins/sudoers/auth/bsdauth.c:179
+msgid "your account has expired"
+msgstr "sua conta expirou"
+
+#: plugins/sudoers/auth/bsdauth.c:181
+msgid "approval failed"
+msgstr "aprovação falhou"
+
+#: plugins/sudoers/auth/fwtk.c:54
+msgid "unable to read fwtk config"
+msgstr "não foi possível ler configuração de fwtk"
+
+#: plugins/sudoers/auth/fwtk.c:59
+msgid "unable to connect to authentication server"
+msgstr "não foi possível conectar ao servidor de autenticação"
+
+#: plugins/sudoers/auth/fwtk.c:65 plugins/sudoers/auth/fwtk.c:89
+#: plugins/sudoers/auth/fwtk.c:121
+msgid "lost connection to authentication server"
+msgstr "conexão perdida com o servidor de autenticação"
+
+#: plugins/sudoers/auth/fwtk.c:69
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"erro no servidor de autenticação:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:110
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: não foi possível converter principal para string (\"%s\"): %s"
+
+#: plugins/sudoers/auth/kerb5.c:160
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: não foi possível analisar \"%s\": %s"
+
+#: plugins/sudoers/auth/kerb5.c:169
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: não foi possível resolver cache de credenciais: %s"
+
+#: plugins/sudoers/auth/kerb5.c:216
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: não foi possível alocar opções: %s"
+
+#: plugins/sudoers/auth/kerb5.c:231
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: não foi possível obter credenciais: %s"
+
+#: plugins/sudoers/auth/kerb5.c:244
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: não foi possível inicializar cache de credenciais: %s"
+
+#: plugins/sudoers/auth/kerb5.c:247
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: não foi possível armazenar credenciais no cache: %s"
+
+#: plugins/sudoers/auth/kerb5.c:311
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: não foi possível obter principal da máquina: %s"
+
+#: plugins/sudoers/auth/kerb5.c:325
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: Não foi possível verificar TGT! Possivelmente um ataque!: %s"
+
+#: plugins/sudoers/auth/pam.c:218
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "não foi possível inicializar PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:340
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Erro de autenticação PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:359
+msgid "account validation failure, is your account locked?"
+msgstr "falha de verificação da conta; sua conta está travada?"
+
+#: plugins/sudoers/auth/pam.c:370
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Conta ou senha expirou; redefina sua senha e tente novamente"
+
+#: plugins/sudoers/auth/pam.c:376
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "não foi possível alterar a senha expirada: %s"
+
+#: plugins/sudoers/auth/pam.c:387
+msgid "Password expired, contact your system administrator"
+msgstr "Senha expirou; entre em contato com o administrador do seu sistema"
+
+#: plugins/sudoers/auth/pam.c:392
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Conta expirou ou a configuração do PAM não possui uma seção \"account\" para sudo; contate o administrador do seu sistema"
+
+#: plugins/sudoers/auth/pam.c:400 plugins/sudoers/auth/pam.c:405
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "erro de gerenciamento de conta PAM: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:99 plugins/sudoers/visudo.c:241
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "você não existe no banco de dados de %s"
+
+#: plugins/sudoers/auth/securid5.c:72
+msgid "failed to initialise the ACE API library"
+msgstr "falha ao inicializar a biblioteca API ACE"
+
+#: plugins/sudoers/auth/securid5.c:98
+msgid "unable to contact the SecurID server"
+msgstr "não foi possível contatar o servidor de SecurID"
+
+#: plugins/sudoers/auth/securid5.c:107
+msgid "User ID locked for SecurID Authentication"
+msgstr "ID de usuário travado pela autenticação SecurID"
+
+#: plugins/sudoers/auth/securid5.c:111 plugins/sudoers/auth/securid5.c:162
+msgid "invalid username length for SecurID"
+msgstr "comprimento de nome de usuário inválido para SecurID"
+
+#: plugins/sudoers/auth/securid5.c:115 plugins/sudoers/auth/securid5.c:167
+msgid "invalid Authentication Handle for SecurID"
+msgstr "manipulação inválida de autenticação para SecurID"
+
+#: plugins/sudoers/auth/securid5.c:119
+msgid "SecurID communication failed"
+msgstr "falha de comunicação de SecurID"
+
+#: plugins/sudoers/auth/securid5.c:123 plugins/sudoers/auth/securid5.c:210
+msgid "unknown SecurID error"
+msgstr "erro de SecurID desconhecido"
+
+#: plugins/sudoers/auth/securid5.c:157
+msgid "invalid passcode length for SecurID"
+msgstr "comprimento de senha inválida para SecurID"
+
+#: plugins/sudoers/auth/sia.c:69 plugins/sudoers/auth/sia.c:123
+msgid "unable to initialize SIA session"
+msgstr "não foi possível inicializar a sessão SIA"
+
+#: plugins/sudoers/auth/sudo_auth.c:132
+msgid "invalid authentication methods"
+msgstr "métodos de autenticação inválidos"
+
+#: plugins/sudoers/auth/sudo_auth.c:134
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Métodos de autenticação inválidos compilado no sudo! Você não pode misturar autenticação autônoma com não-autônoma."
+
+#: plugins/sudoers/auth/sudo_auth.c:255 plugins/sudoers/auth/sudo_auth.c:305
+msgid "no authentication methods"
+msgstr "nenhum método de autenticação"
+
+#: plugins/sudoers/auth/sudo_auth.c:257
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Não há métodos de autenticação compilados no sudo! Se você quiser desligar a autenticação, use a opção de configuração --disable-authentication."
+
+#: plugins/sudoers/auth/sudo_auth.c:307
+msgid "Unable to initialize authentication methods."
+msgstr "Não foi possível inicializar métodos de autenticação."
+
+#: plugins/sudoers/auth/sudo_auth.c:471
+msgid "Authentication methods:"
+msgstr "Métodos de autenticação:"
+
+#: plugins/sudoers/bsm_audit.c:123 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "Não foi possível determinar a condição de auditoria"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:277
+msgid "unable to commit audit record"
+msgstr "não foi possível enviar o registro de auditoria"
+
+#: plugins/sudoers/check.c:264
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "erro ao ler o arquivo de instruções: %s"
+
+#: plugins/sudoers/check.c:270
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "ignorando o arquivo de instruções %s: não é um arquivo comum"
+
+#: plugins/sudoers/check.c:283
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Presumimos que você recebeu as instruções de sempre do administrador\n"
+"de sistema local. Basicamente, resume-se a estas três coisas:\n"
+"\n"
+" #1) Respeite a privacidade dos outros.\n"
+" #2) Pense antes de digitar.\n"
+" #3) Com grandes poderes vêm grandes responsabilidades.\n"
+"\n"
+
+#: plugins/sudoers/check.c:331 plugins/sudoers/check.c:341
+#: plugins/sudoers/sudoers.c:876 plugins/sudoers/sudoers.c:897
+#: plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "uid desconhecido %u"
+
+#: plugins/sudoers/check_aliases.c:56
+#, c-format
+msgid "Error: %s:%d:%d: cycle in %s \"%s\""
+msgstr "Erro: %s:%d:%d: ciclo em %s \"%s\""
+
+#: plugins/sudoers/check_aliases.c:57
+#, c-format
+msgid "Warning: %s:%d:%d: cycle in %s \"%s\""
+msgstr "Aviso: %s:%d:%d: ciclo em %s \"%s\""
+
+#: plugins/sudoers/check_aliases.c:61
+#, c-format
+msgid "Error: %s:%d:%d: %s \"%s\" referenced but not defined"
+msgstr "Erro: %s:%d:%d: %s \"%s\" referenciado, mas não definido"
+
+#: plugins/sudoers/check_aliases.c:62
+#, c-format
+msgid "Warning: %s:%d:%d: %s \"%s\" referenced but not defined"
+msgstr "Aviso: %s:%d:%d: %s \"%s\" referenciado, mas não definido"
+
+#: plugins/sudoers/cvtsudoers.c:194
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "incremento de ordem: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:210
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "ordem inicial: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:220
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "preenchimento de ordem: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:230 plugins/sudoers/visudo.c:177
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "gramática de %s versão %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:247 plugins/sudoers/testsudoers.c:159
+#, c-format
+msgid "unsupported input format %s"
+msgstr "formato de entrada sem suporte %s"
+
+#: plugins/sudoers/cvtsudoers.c:262
+#, c-format
+msgid "unsupported output format %s"
+msgstr "formato de saída sem suporte %s"
+
+#: plugins/sudoers/cvtsudoers.c:314
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: arquivos de entrada e saída devem ser diferentes"
+
+#: plugins/sudoers/cvtsudoers.c:330 plugins/sudoers/sudoers.c:159
+#: plugins/sudoers/sudoers.c:205 plugins/sudoers/testsudoers.c:254
+#: plugins/sudoers/visudo.c:247 plugins/sudoers/visudo.c:597
+#: plugins/sudoers/visudo.c:917
+msgid "unable to initialize sudoers default values"
+msgstr "não foi possível inicializar valores padrões do sudoers"
+
+#: plugins/sudoers/cvtsudoers.c:416 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:475
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s: palavra-chave desconhecida %s"
+
+#: plugins/sudoers/cvtsudoers.c:521
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "tipo de defaults inválido: %s"
+
+#: plugins/sudoers/cvtsudoers.c:544
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "tipo de supressão inválida: %s"
+
+#: plugins/sudoers/cvtsudoers.c:584 plugins/sudoers/cvtsudoers.c:598
+#, c-format
+msgid "invalid filter: %s"
+msgstr "filtro inválido: %s"
+
+#: plugins/sudoers/cvtsudoers.c:642 plugins/sudoers/visudo.c:922
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "falha em analisar o arquivo %s, erro desconhecido"
+
+#: plugins/sudoers/cvtsudoers.c:650
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr "erro de análise em %s perto da linha %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:653
+#, c-format
+msgid "parse error in %s\n"
+msgstr "erro de análise em \"%s\"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1296 plugins/sudoers/sudoreplay.c:1145
+#: plugins/sudoers/timestamp.c:317 plugins/sudoers/timestamp.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "não foi possível gravar em %s"
+
+#: plugins/sudoers/cvtsudoers.c:1319
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s - converte entre formatos de arquivo sudoers\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1321
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Opções:\n"
+" -b, --base=dn o DN base para consultas LDAP do sudo\n"
+" -c, --config=arquivo_conf o caminho para o arquivo de configuração\n"
+" -d, --defaults=tiposdeft só converte Defaults dos tipos especificados\n"
+" -e, --expand-aliases expande aliases ao converter\n"
+" -f, --output-format=formato define formato de saída: JSON, LDIF ou sudoers\n"
+" -i, --input-format=formato define formato de entrada: LDIF ou sudoers\n"
+" -I, --increment=núm quantidade para incrementar cada sudoOrder por\n"
+" -h, --help exibe a mensagem de ajuda e sai\n"
+" -m, --match=filtro só converte entradas que corresponde ao filtro\n"
+" -M, --match-local filtro de correspondência usa bancos de dados\n"
+" passwd e group\n"
+" -o, --output=arquivo_saída escreve sudoers convertido para arquivo_saída\n"
+" -O, --order-start=núm ponto inicial para o primeiro sudoOrder\n"
+" -p, --prune-matches suprime usuário/grupo/máquina não correspondente\n"
+" -P, --padding=núm preenchimento base para incremento de sudoOrder\n"
+" -s, --suppress=seções suprime a saída de certas seções\n"
+" -V, --version exibe informações de versão e sai"
+
+#: plugins/sudoers/cvtsudoers_json.c:480 plugins/sudoers/cvtsudoers_json.c:514
+#: plugins/sudoers/cvtsudoers_json.c:718
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "entrada de Defaults \"%s\" desconhecida"
+
+#: plugins/sudoers/cvtsudoers_json.c:651 plugins/sudoers/cvtsudoers_json.c:664
+#: plugins/sudoers/cvtsudoers_ldif.c:346 plugins/sudoers/cvtsudoers_ldif.c:357
+#: plugins/sudoers/ldap.c:503
+msgid "unable to get GMT time"
+msgstr "não foi possível obter o horário GMT"
+
+#: plugins/sudoers/cvtsudoers_json.c:654 plugins/sudoers/cvtsudoers_json.c:667
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:360
+#: plugins/sudoers/ldap.c:509
+msgid "unable to format timestamp"
+msgstr "não é possível formatar marca de tempo"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:644
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "entradas de sudoers demais, máximo %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:687
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "a variável de ambiente SUDOERS_BASE não está definida e a opção -b não foi especificada."
+
+#: plugins/sudoers/def_data.c:50
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Facilidade do syslog, se syslog estiver sendo usado para registrar logs: %s"
+
+#: plugins/sudoers/def_data.c:54
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Prioridade do syslog para usar quando um usuário autenticar com sucesso: %s"
+
+#: plugins/sudoers/def_data.c:58
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Prioridade do syslog para usar quando um usuário não usuário autenticar com sucesso: %s"
+
+#: plugins/sudoers/def_data.c:62
+msgid "Put OTP prompt on its own line"
+msgstr "Colocar prompt OTP na sua própria linha"
+
+#: plugins/sudoers/def_data.c:66
+msgid "Ignore '.' in $PATH"
+msgstr "Ignorar \".\" no $PATH"
+
+#: plugins/sudoers/def_data.c:70
+msgid "Always send mail when sudo is run"
+msgstr "Sempre envia correio quando sudo for executado"
+
+#: plugins/sudoers/def_data.c:74
+msgid "Send mail if user authentication fails"
+msgstr "Envia correio se a autenticação de um usuário falhar"
+
+#: plugins/sudoers/def_data.c:78
+msgid "Send mail if the user is not in sudoers"
+msgstr "Envia correio se o usuário não estiver no sudoers"
+
+#: plugins/sudoers/def_data.c:82
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Envia correio se o usuário não estiver no sudoers desta máquina"
+
+#: plugins/sudoers/def_data.c:86
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Envia correio se o usuário não tiver permissão para executar um comando"
+
+#: plugins/sudoers/def_data.c:90
+msgid "Send mail if the user tries to run a command"
+msgstr "Envia correio se o usuário tentar executar um comando"
+
+#: plugins/sudoers/def_data.c:94
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Usa uma marca de tempo separada para cada combo usuário/tty"
+
+#: plugins/sudoers/def_data.c:98
+msgid "Lecture user the first time they run sudo"
+msgstr "Instrui o usuário na primeira vez que ele executar sudo"
+
+#: plugins/sudoers/def_data.c:102
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Arquivo contendo as instruções do sudo: %s"
+
+#: plugins/sudoers/def_data.c:106
+msgid "Require users to authenticate by default"
+msgstr "Exige que os usuários se autentiquem, por padrão"
+
+#: plugins/sudoers/def_data.c:110
+msgid "Root may run sudo"
+msgstr "Root pode executar sudo"
+
+#: plugins/sudoers/def_data.c:114
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Registra o nome da máquina no arquivo de log (não-syslog)"
+
+#: plugins/sudoers/def_data.c:118
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Registra o ano no arquivo de log (não-syslog)"
+
+#: plugins/sudoers/def_data.c:122
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Se sudo for chamado sem argumentos, inicia um shell"
+
+#: plugins/sudoers/def_data.c:126
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Define $HOME com o usuário alvo ao iniciar um shell com -s"
+
+#: plugins/sudoers/def_data.c:130
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Sempre define $HOME para a pasta pessoal do usuário alvo"
+
+#: plugins/sudoers/def_data.c:134
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Permite juntar algumas informações para fornecer mensagens de erro úteis"
+
+#: plugins/sudoers/def_data.c:138
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Exige nomes de máquina completos (FQDN) no arquivo sudoers"
+
+#: plugins/sudoers/def_data.c:142
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Insulta o usuário quando ele digitar uma senha incorreta"
+
+#: plugins/sudoers/def_data.c:146
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Permite que o usuário execute sudo apenas se ele tiver um tty"
+
+#: plugins/sudoers/def_data.c:150
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo vai honrar a variável de ambiente EDITOR"
+
+#: plugins/sudoers/def_data.c:154
+msgid "Prompt for root's password, not the users's"
+msgstr "Pede a senha do root, e não a do usuário"
+
+#: plugins/sudoers/def_data.c:158
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Pede a senha do usuário runas_default, e não a do usuário"
+
+#: plugins/sudoers/def_data.c:162
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Pede a senha do usuário alvo, e não a do usuário"
+
+#: plugins/sudoers/def_data.c:166
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Aplica o padrão na classe de login do usuário alvo, se houver alguma"
+
+#: plugins/sudoers/def_data.c:170
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Define as variáveis de ambiente LOGNAME e USER"
+
+#: plugins/sudoers/def_data.c:174
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Define o uid efetivo apenas para o usuário alvo, e não o uid real"
+
+#: plugins/sudoers/def_data.c:178
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Não inicializa o vetor de grupos para aquele usuário alvo"
+
+#: plugins/sudoers/def_data.c:182
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Comprimento da quebra de linha do arquivo de log (0 para sem quebra): %u"
+
+# "Limite de tempo da marca de tempo de autenticação" ficaria estranho, então utilizei "... expira em"
+#: plugins/sudoers/def_data.c:186
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Marca de tempo de autenticação expira em: %.1f minutos"
+
+#: plugins/sudoers/def_data.c:190
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Pedido de senha expira em: %.1f minutos"
+
+#: plugins/sudoers/def_data.c:194
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Número de tentativas para digitar senha: %u"
+
+#: plugins/sudoers/def_data.c:198
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Umask a ser usada ou 0777 para usar do usuário: 0%o"
+
+#: plugins/sudoers/def_data.c:202
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Caminho para o arquivo de log: %s"
+
+#: plugins/sudoers/def_data.c:206
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Caminho para o programa de correio: %s"
+
+#: plugins/sudoers/def_data.c:210
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Opções para o programa de correio: %s"
+
+#: plugins/sudoers/def_data.c:214
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Endereço para onde enviar correio: %s"
+
+#: plugins/sudoers/def_data.c:218
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Endereço de onde enviar correio: %s"
+
+#: plugins/sudoers/def_data.c:222
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Linha do assunto para as mensagens de correio: %s"
+
+#: plugins/sudoers/def_data.c:226
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Mensagem de senha incorreta: %s"
+
+#: plugins/sudoers/def_data.c:230
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Caminho para o diretório de status de instruções: %s"
+
+#: plugins/sudoers/def_data.c:234
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Caminho para diretório de marca de tempo de autenticação: %s"
+
+#: plugins/sudoers/def_data.c:238
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Dono do diretório de marca de tempo de autenticação: %s"
+
+#: plugins/sudoers/def_data.c:242
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Usuários neste grupo estão eximidos da exigência de senha e PATH: %s"
+
+#: plugins/sudoers/def_data.c:246
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Pedido de senha padrão: %s"
+
+#: plugins/sudoers/def_data.c:250
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Se definido, o pedido de senha vai sobrescrever o do sistema em todos os casos."
+
+#: plugins/sudoers/def_data.c:254
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Usuário padrão para se executar comandos: %s"
+
+#: plugins/sudoers/def_data.c:258
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Valor para sobrescrever o $PATH do usuário: %s"
+
+#: plugins/sudoers/def_data.c:262
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Caminho do editor a ser usado pelo visudo: %s"
+
+#: plugins/sudoers/def_data.c:266
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Quando exigir uma senha para o pseudo-comando \"list\": %s"
+
+#: plugins/sudoers/def_data.c:270
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Quando exigir uma senha para o pseudo-comando \"verify\": %s"
+
+#: plugins/sudoers/def_data.c:274
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "Pré-carrega a biblioteca sudo_noexec que substitui as funções do exec"
+
+# ideia da frase original: se acontecer algo, se deve ou não ignorar. Traduzi reorganizando a frase com a finalidade de manter a ideia original. -- Rafael
+#: plugins/sudoers/def_data.c:278
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Estando o diretório LDAP disponível, se devemos ignorar o arquivo sudoers local"
+
+#: plugins/sudoers/def_data.c:282
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Descritores, de arquivos, >= %d serão fechados antes de executar um comando"
+
+#: plugins/sudoers/def_data.c:286
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "Se definido, usuários podem sobrescrever o valor de \"closefrom\" com a opção -C"
+
+#: plugins/sudoers/def_data.c:290
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Permite que usuários definam variáveis de ambiente arbitrárias"
+
+#: plugins/sudoers/def_data.c:294
+msgid "Reset the environment to a default set of variables"
+msgstr "Redefine o ambiente para um conjunto padrão de variáveis"
+
+#: plugins/sudoers/def_data.c:298
+msgid "Environment variables to check for safety:"
+msgstr "Variáveis de ambiente para verificar por segurança:"
+
+#: plugins/sudoers/def_data.c:302
+msgid "Environment variables to remove:"
+msgstr "Variáveis de ambiente para remover:"
+
+#: plugins/sudoers/def_data.c:306
+msgid "Environment variables to preserve:"
+msgstr "Variáveis de ambiente para preservar:"
+
+#: plugins/sudoers/def_data.c:310
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "Papel SELinux para usar no novo contexto de segurança: %s"
+
+#: plugins/sudoers/def_data.c:314
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "Tipo SELinux para usar no novo contexto de segurança: %s"
+
+#: plugins/sudoers/def_data.c:318
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Caminho do arquivo de ambiente específico do sudo: %s"
+
+#: plugins/sudoers/def_data.c:322
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Caminho do arquivo restrito de ambiente específico do sudo: %s"
+
+#: plugins/sudoers/def_data.c:326
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Localização para usar ao analisar o sudoers: %s"
+
+#: plugins/sudoers/def_data.c:330
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Permite ao sudo solicitar uma senha mesmo se ele estiver visível"
+
+#: plugins/sudoers/def_data.c:334
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Fornece feedback visual na solicitação de senha quando houver entrada do usuário"
+
+#: plugins/sudoers/def_data.c:338
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Usa um englobamento mais rápido que é menos preciso, mas não acessa o sistema de arquivos"
+
+#: plugins/sudoers/def_data.c:342
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "O umask especificado no sudoers vai sobrescrever o do usuário, mesmo se ele foi mais permissivo"
+
+#: plugins/sudoers/def_data.c:346
+msgid "Log user's input for the command being run"
+msgstr "Registra no log a entrada do usuário para o comando sendo executado"
+
+#: plugins/sudoers/def_data.c:350
+msgid "Log the output of the command being run"
+msgstr "Registra no log a saída do comando sendo executado"
+
+#: plugins/sudoers/def_data.c:354
+msgid "Compress I/O logs using zlib"
+msgstr "Comprime logs I/O usando zlib"
+
+#: plugins/sudoers/def_data.c:358
+msgid "Always run commands in a pseudo-tty"
+msgstr "Sempre executa comandos em um pseudo-tty"
+
+#: plugins/sudoers/def_data.c:362
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Plug-in para suporte a grupo não-Unix: %s"
+
+#: plugins/sudoers/def_data.c:366
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Diretório no qual devem ser armazenados os logs de entrada/saída: %s"
+
+#: plugins/sudoers/def_data.c:370
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Arquivo no qual deve ser armazenado o log de entrada/saída: %s"
+
+#: plugins/sudoers/def_data.c:374
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Adiciona uma entrada ao arquivo utmp/utmpx ao alocar um pty"
+
+#: plugins/sudoers/def_data.c:378
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Define o usuário em utmp como usuário a ser executado como, e não o usuário a ser chamado"
+
+#: plugins/sudoers/def_data.c:382
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Conjunto de privilégios permitidos: %s"
+
+#: plugins/sudoers/def_data.c:386
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Conjunto de privilégios limitados: %s"
+
+#: plugins/sudoers/def_data.c:390
+msgid "Run commands on a pty in the background"
+msgstr "Executa comandos em um pty em plano de fundo"
+
+#: plugins/sudoers/def_data.c:394
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "Nome do serviço PAM para usar: %s"
+
+#: plugins/sudoers/def_data.c:398
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "Nome do serviço PAM para usar para shells de login: %s"
+
+#: plugins/sudoers/def_data.c:402
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Tenta estabelecer as credenciais PAM para o usuário alvo"
+
+#: plugins/sudoers/def_data.c:406
+msgid "Create a new PAM session for the command to run in"
+msgstr "Cria uma nova sessão PAM para o comando ser executado nela"
+
+#: plugins/sudoers/def_data.c:410
+msgid "Perform PAM account validation management"
+msgstr "Realiza de gerenciamento de validação de conta PAM"
+
+#: plugins/sudoers/def_data.c:414
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "Número máximo de sequência de log de E/S: %s"
+
+#: plugins/sudoers/def_data.c:418
+msgid "Enable sudoers netgroup support"
+msgstr "Habilita suporte a netgroup no sudoers"
+
+#: plugins/sudoers/def_data.c:422
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Verifica diretórios pai para capacidade de gravação ao editar arquivos com sudoedit"
+
+#: plugins/sudoers/def_data.c:426
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Segue links simbólicos ao editar arquivos com sudoedit"
+
+#: plugins/sudoers/def_data.c:430
+msgid "Query the group plugin for unknown system groups"
+msgstr "Consulta o plug-in de grupo por grupos de sistema desconhecidos"
+
+#: plugins/sudoers/def_data.c:434
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Compara netgroups baseada em toda tupla: usuário, máquina e domínio"
+
+#: plugins/sudoers/def_data.c:438
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Permite comandos serem executados mesmo se sudo não puder escrever em logs de auditoria"
+
+#: plugins/sudoers/def_data.c:442
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Permite comandos serem executados mesmo se sudo não puder escrever em logs de E/S"
+
+#: plugins/sudoers/def_data.c:446
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Permite comandos serem executados mesmo se sudo não puder escrever no arquivo de log"
+
+#: plugins/sudoers/def_data.c:450
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Resolve grupos no sudoers e corresponde ao ID de grupo, e não o nome"
+
+#: plugins/sudoers/def_data.c:454
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Entradas de log maiores que este valor serão divididos em múltiplas mensagens de syslog: %u"
+
+#: plugins/sudoers/def_data.c:458
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Usuário que será dono dos arquivos de log de E/S: %s"
+
+#: plugins/sudoers/def_data.c:462
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Grupo que será dono dos arquivos de log de E/S: %s"
+
+#: plugins/sudoers/def_data.c:466
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Modo de arquivo usado para os arquivos de log de E/S: 0%o"
+
+#: plugins/sudoers/def_data.c:470
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Executa comandos pelo descritor de arquivo em vez de pelo caminho: %s"
+
+#: plugins/sudoers/def_data.c:474
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Ignora entradas desconhecidas de Defaults no sudoers em vez de produzir um aviso"
+
+#: plugins/sudoers/def_data.c:478
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Tempo em segundos após o qual o comando será terminado: %u"
+
+#: plugins/sudoers/def_data.c:482
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Permite o usuário especificar um tempo limite na linha de comando"
+
+#: plugins/sudoers/def_data.c:486
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Descarrega os dados de log de E/S para o disco imediatamente em vez de armazenar no buffer"
+
+#: plugins/sudoers/def_data.c:490
+msgid "Include the process ID when logging via syslog"
+msgstr "Inclui o ID de processo ao registrar log via syslog"
+
+#: plugins/sudoers/def_data.c:494
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Tipo de registro de marca de tempo de autenticação: %s"
+
+#: plugins/sudoers/def_data.c:498
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Mensagem de falha de autenticação: %s"
+
+#: plugins/sudoers/def_data.c:502
+msgid "Ignore case when matching user names"
+msgstr "Ignora maiúsculo/minúsculo ao corresponder nomes de usuário"
+
+#: plugins/sudoers/def_data.c:506
+msgid "Ignore case when matching group names"
+msgstr "Ignora maiúsculo/minúsculo ao corresponder nomes de grupo"
+
+#: plugins/sudoers/def_data.c:510
+msgid "Log when a command is allowed by sudoers"
+msgstr "Registra quando um comando é permitido por sudoers"
+
+#: plugins/sudoers/def_data.c:514
+msgid "Log when a command is denied by sudoers"
+msgstr "Registra quando um comando é negado por sudoers"
+
+#: plugins/sudoers/def_data.c:518
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "Servidor(es) de log do sudo para conectar com porta opcional"
+
+#: plugins/sudoers/def_data.c:522
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Tempo limite do servidor de log do sudo em segundos: %u"
+
+#: plugins/sudoers/def_data.c:526
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "Habilita a opção de soquete SO_KEEPALIVE no soquete conectado ao servidor de log"
+
+#: plugins/sudoers/def_data.c:530
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "Caminho do arquivo de pacote de AC do servidor de auditoria: %s"
+
+#: plugins/sudoers/def_data.c:534
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "Caminho do arquivo de certificado do sudoers: %s"
+
+#: plugins/sudoers/def_data.c:538
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "Caminho do arquivo de chave privada do sudoers: %s"
+
+#: plugins/sudoers/def_data.c:542
+msgid "Verify that the log server's certificate is valid"
+msgstr "Verifica se o certificado do servidor de log é válido"
+
+#: plugins/sudoers/def_data.c:546
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "Permite o uso de ID desconhecido do usuário e/ou grupo a ser executado como"
+
+#: plugins/sudoers/def_data.c:550
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "Permite apenas a execução de comandos como um usuário com um shell válido"
+
+#: plugins/sudoers/def_data.c:554
+msgid "Set the pam remote user to the user running sudo"
+msgstr "Define o usuário remoto pam como o usuário executando o sudo"
+
+#: plugins/sudoers/def_data.c:558
+msgid "Set the pam remote host to the local host name"
+msgstr "Define a máquina remota pam com o nome da máquina local"
+
+#: plugins/sudoers/def_data.c:562
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "Diretório de trabalho para o qual alterar antes de executar o comando: %s"
+
+#: plugins/sudoers/def_data.c:566
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "Diretório raiz para o qual alterar antes de executar o comando: %s"
+
+#: plugins/sudoers/def_data.c:570
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "O formato dos logs para produzir: %s"
+
+#: plugins/sudoers/def_data.c:574
+msgid "Enable SELinux RBAC support"
+msgstr "Habilita suporte a RBAC no SELinux"
+
+#: plugins/sudoers/def_data.c:578
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "Caminho para o arquivo que é criado na primeira execução do sudo: %s"
+
+#: plugins/sudoers/def_data.c:582
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "Intercepta outros comandos e aplica restrições sudoers a eles"
+
+#: plugins/sudoers/def_data.c:586
+msgid "Log any child processes run by the command"
+msgstr "Registra log qualquer processo filho executado pelo comando"
+
+#: plugins/sudoers/def_data.c:590
+msgid "Log the exit status of commands"
+msgstr "Registra log o status de saída dos comandos"
+
+#: plugins/sudoers/def_data.c:594
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr "Os comandos subsequentes em uma sessão interceptada devem ser autenticados"
+
+#: plugins/sudoers/def_data.c:598
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr "Permite que um comando interceptado execute os programas setuid ou setgid definidos"
+
+#: plugins/sudoers/defaults.c:185
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: entrada padrão \"%s\" desconhecida"
+
+#: plugins/sudoers/defaults.c:188
+#, c-format
+msgid "%s: unknown defaults entry \"%s\""
+msgstr "%s: entrada padrão \"%s\" desconhecida"
+
+#: plugins/sudoers/defaults.c:234
+#, c-format
+msgid "%s:%d:%d: no value specified for \"%s\""
+msgstr "%s:%d:%d: nenhum valor especificado para \"%s\""
+
+#: plugins/sudoers/defaults.c:237
+#, c-format
+msgid "%s: no value specified for \"%s\""
+msgstr "%s: nenhum valor especificado para \"%s\""
+
+#: plugins/sudoers/defaults.c:250
+#, c-format
+msgid "%s:%d:%d: invalid operator \"%c=\" for \"%s\""
+msgstr "%s:%d:%d: operador inválido \"%c=\" para \"%s\""
+
+#: plugins/sudoers/defaults.c:253
+#, c-format
+msgid "%s: invalid operator \"%c=\" for \"%s\""
+msgstr "%s: operador inválido \"%c=\" para \"%s\""
+
+#: plugins/sudoers/defaults.c:289
+#, c-format
+msgid "%s:%d:%d: option \"%s\" does not take a value"
+msgstr "%s:%d:%d: a opção \"%s\" não aceita um valor"
+
+#: plugins/sudoers/defaults.c:292
+#, c-format
+msgid "%s: option \"%s\" does not take a value"
+msgstr "%s: a opção \"%s\" não leva um valor"
+
+#: plugins/sudoers/defaults.c:317
+#, c-format
+msgid "%s:%d:%d: invalid Defaults type 0x%x for option \"%s\""
+msgstr "%s:%d:%d: tipo de Defaults 0x%x inválido para a opção \"%s\""
+
+#: plugins/sudoers/defaults.c:320
+#, c-format
+msgid "%s: invalid Defaults type 0x%x for option \"%s\""
+msgstr "%s: Tipo de Defaults 0x%x inválido para a opção \"%s\""
+
+#: plugins/sudoers/defaults.c:330
+#, c-format
+msgid "%s:%d:%d: value \"%s\" is invalid for option \"%s\""
+msgstr "%s:%d:%d: valor \"%s\" é inválido para a opção \"%s\""
+
+#: plugins/sudoers/defaults.c:333
+#, c-format
+msgid "%s: value \"%s\" is invalid for option \"%s\""
+msgstr "%s: o valor \"%s\" é inválido para a opção \"%s\""
+
+#: plugins/sudoers/defaults.c:1054
+#, c-format
+msgid "%s:%d:%d: values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "%s:%d:%d: valores para \"%s\" devem iniciar com um \"/\", \"~\" ou \"*\""
+
+#: plugins/sudoers/defaults.c:1058
+#, c-format
+msgid "%s: values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "%s: valores para \"%s\" devem iniciar com um \"/\", '~', ou '*'"
+
+#: plugins/sudoers/defaults.c:1069
+#, c-format
+msgid "%s:%d:%d: values for \"%s\" must start with a '/'"
+msgstr "%s:%d:%d: valores para \"%s\" devem iniciar com um \"/\""
+
+#: plugins/sudoers/defaults.c:1073
+#, c-format
+msgid "%s: values for \"%s\" must start with a '/'"
+msgstr "%s: valores para \"%s\" devem iniciar com um \"/\""
+
+#: plugins/sudoers/env.c:412
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: envp corrompido, cumprimento não confere"
+
+#: plugins/sudoers/env.c:1095
+msgid "unable to rebuild the environment"
+msgstr "não foi possível recompilar o ambiente"
+
+#: plugins/sudoers/env.c:1169
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "sinto muito, você não tem permissão para definir as seguintes variáveis de ambiente: %s"
+
+#: plugins/sudoers/file.c:108
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr "erro de análise em %s próximo à linha %d"
+
+#: plugins/sudoers/file.c:111
+#, c-format
+msgid "parse error in %s"
+msgstr "erro de análise em %s"
+
+#: plugins/sudoers/filedigest.c:49
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr "tipo de digest %d sem suporte para %s"
+
+#: plugins/sudoers/filedigest.c:78
+#, c-format
+msgid "%s: read error"
+msgstr "%s: erro de leitura"
+
+#: plugins/sudoers/group_plugin.c:83
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s deve ter como dono o uid %d"
+
+#: plugins/sudoers/group_plugin.c:87
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr "%s deve ser gravável apenas pelo dono"
+
+#: plugins/sudoers/group_plugin.c:96 plugins/sudoers/sssd.c:569
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "não foi possível carregar %s: %s"
+
+#: plugins/sudoers/group_plugin.c:102
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "não foi possível localizar um símbolo \"group_plugin\" %s"
+
+#: plugins/sudoers/group_plugin.c:107
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: versão maior do plug-in de grupo %d incompatível, esperava %d"
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "não foi possível analisar o endereço IP \"%s\""
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "não foi possível analisar a máscara de rede \"%s\""
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Par de endereço IP e máscara de rede locais:\n"
+
+#: plugins/sudoers/iolog.c:632
+msgid "unable to update sequence file"
+msgstr "não foi possível atualizar o arquivo de sequência"
+
+#: plugins/sudoers/iolog.c:663 plugins/sudoers/iolog.c:851
+#: plugins/sudoers/iolog.c:1004 plugins/sudoers/iolog.c:1011
+#: plugins/sudoers/iolog.c:1132 plugins/sudoers/iolog.c:1139
+#: plugins/sudoers/iolog.c:1238 plugins/sudoers/iolog.c:1245
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "não foi possível gravar no arquivo de log de E/S: %s"
+
+#: plugins/sudoers/iolog.c:671
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "não foi possível criar %s/%s"
+
+#: plugins/sudoers/iolog.c:896
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: erro interno, o arquivo de log de E/S para evento %d não está aberto"
+
+#: plugins/sudoers/iolog.c:989 plugins/sudoers/iolog.c:1117
+#: plugins/sudoers/iolog.c:1222 plugins/sudoers/timestamp.c:849
+#: plugins/sudoers/timestamp.c:941 plugins/sudoers/visudo.c:487
+#: plugins/sudoers/visudo.c:493
+msgid "unable to read the clock"
+msgstr "não foi possível ler do relógio"
+
+#: plugins/sudoers/iolog.c:1214 plugins/sudoers/log_client.c:1217
+#: plugins/sudoers/log_client.c:1227 plugins/sudoers/log_client.c:1231
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: erro interno, sinal inválido %d"
+
+#: plugins/sudoers/ldap.c:177 plugins/sudoers/ldap_conf.c:291
+msgid "starttls not supported when using ldaps"
+msgstr "sem suporte a starttls ao usar ldaps"
+
+#: plugins/sudoers/ldap.c:248
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "não foi possível inicializar bando de dados de chaves e certificados SSL: %s"
+
+#: plugins/sudoers/ldap.c:251
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "você deve definir TLS_CERT em %s para usar SSL"
+
+#: plugins/sudoers/ldap.c:1660
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "não foi possível inicializar LDAP: %s"
+
+#: plugins/sudoers/ldap.c:1697
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls especificado, mas bibliotecas LDAP não possuem suporte a ldap_start_tls_s() ou ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:1834 plugins/sudoers/parse_ldif.c:746
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "atributo sudoOrder inválido: %s"
+
+#: plugins/sudoers/ldap_conf.c:200
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: porta grande demais"
+
+#: plugins/sudoers/ldap_conf.c:260
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "tipo de uri LDAP sem suporte: %s"
+
+#: plugins/sudoers/ldap_conf.c:287
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "não foi possível misturar ldap e ldaps URIs"
+
+#: plugins/sudoers/ldap_util.c:496 plugins/sudoers/ldap_util.c:503
+#: plugins/sudoers/ldap_util.c:511 plugins/sudoers/ldap_util.c:520
+#: plugins/sudoers/ldap_util.c:528 plugins/sudoers/ldap_util.c:538
+#: plugins/sudoers/ldap_util.c:546
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "sudoOption duplicado: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:565 plugins/sudoers/ldap_util.c:567
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "não foi possível converter sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "não foi possível abrir o sistema de auditoria"
+
+#: plugins/sudoers/linux_audit.c:103
+msgid "unable to send audit message"
+msgstr "não foi possível enviar mensagem de auditoria"
+
+#: plugins/sudoers/log_client.c:116 plugins/sudoers/log_client.c:396
+#: plugins/sudoers/log_client.c:1464 plugins/sudoers/log_client.c:2061
+msgid "error in event loop"
+msgstr "erro no evento de loop"
+
+#: plugins/sudoers/log_client.c:196
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "Criação do novo objeto SSL_CTX falhou: %s"
+
+#: plugins/sudoers/log_client.c:219
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "não foi possível carregar o novo pacote de autoridade certificadora %s"
+
+#: plugins/sudoers/log_client.c:239
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "não foi possível carregar o certificado %s"
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load private key %s"
+msgstr "não foi possível carregar a chave privada %s"
+
+#: plugins/sudoers/log_client.c:261
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "Não foi possível alocar objeto ssl: %s"
+
+#: plugins/sudoers/log_client.c:349 plugins/sudoers/log_client.c:354
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "falha de conexão de TLS com %s:%s: %s"
+
+#: plugins/sudoers/log_client.c:527
+msgid "TLS initialization was unsuccessful"
+msgstr "A inicialização do TLS não teve êxito"
+
+#: plugins/sudoers/log_client.c:537
+msgid "TLS handshake was unsuccessful"
+msgstr "A negociação TLS não teve êxito"
+
+#: plugins/sudoers/log_client.c:1235
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: erro interno, status de saída inválido %d"
+
+#: plugins/sudoers/log_client.c:1602
+msgid "unable to unpack ServerMessage"
+msgstr "não foi possível desempacotar ServerMessage"
+
+#: plugins/sudoers/log_client.c:1754 plugins/sudoers/log_client.c:1778
+msgid "lost connection to log server"
+msgstr "conexão perdida com o servidor de log"
+
+#: plugins/sudoers/log_client.c:1855
+msgid "missing write buffer"
+msgstr "faltando buffer de escrita"
+
+#: plugins/sudoers/log_client.c:2002
+msgid "unable to connect to log server"
+msgstr "não foi possível conectar ao servidor de log"
+
+#: plugins/sudoers/logging.c:283
+msgid "user NOT in sudoers"
+msgstr "usuário NÃO ESTÁ no sudoers"
+
+#: plugins/sudoers/logging.c:285
+msgid "user NOT authorized on host"
+msgstr "usuário NÃO ESTÁ autorizado na máquina"
+
+#: plugins/sudoers/logging.c:287
+msgid "command not allowed"
+msgstr "comando não permitido"
+
+#: plugins/sudoers/logging.c:308
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr "%s não está no arquivo sudoers. Este incidente será relatado.\n"
+
+#: plugins/sudoers/logging.c:311
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr "%s não tem permissão para executar sudo em %s. Este incidente será relatado.\n"
+
+#: plugins/sudoers/logging.c:315
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Sinto muito, usuário %s não pode executar sudo em %s.\n"
+
+#: plugins/sudoers/logging.c:318
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr "Sinto muito, usuário %s não tem permissão para executar \"%s%s%s\" como %s%s%s em %s.\n"
+
+#: plugins/sudoers/logging.c:355 plugins/sudoers/sudoers.c:629
+#: plugins/sudoers/sudoers.c:631 plugins/sudoers/sudoers.c:633
+#: plugins/sudoers/sudoers.c:635 plugins/sudoers/sudoers.c:776
+#: plugins/sudoers/sudoers.c:778
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: comando não encontrado"
+
+#: plugins/sudoers/logging.c:357 plugins/sudoers/sudoers.c:625
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"ignorando \"%s\" encontrado em \".\"\n"
+"Use \"sudo ./%s\" se isto é o \"%s\" que você deseja executar."
+
+#: plugins/sudoers/logging.c:376
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u tentativa de senha incorreta"
+msgstr[1] "%u tentativas de senha incorreta"
+
+#: plugins/sudoers/logging.c:432
+msgid "authentication failure"
+msgstr "falha de autenticação"
+
+#: plugins/sudoers/logging.c:472 plugins/sudoers/logging.c:492
+msgid "a password is required"
+msgstr "uma senha é necessária"
+
+#: plugins/sudoers/logging.c:889
+#, c-format
+msgid "unable to write log file: %s"
+msgstr "não foi possível gravar no arquivo de log: %s"
+
+#: plugins/sudoers/match_digest.c:129
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "digest de %s (%s) não está na forma %s"
+
+#: plugins/sudoers/parse.c:537
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+"\n"
+"Papel LDAP: %s\n"
+
+#: plugins/sudoers/parse.c:540
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+"\n"
+"Entradas no sudoers:\n"
+
+#: plugins/sudoers/parse.c:542
+msgid " RunAsUsers: "
+msgstr " UsuáriosRunAs: "
+
+#: plugins/sudoers/parse.c:557
+msgid " RunAsGroups: "
+msgstr " GruposRunAs: "
+
+#: plugins/sudoers/parse.c:567
+msgid " Options: "
+msgstr " Opções: "
+
+#: plugins/sudoers/parse.c:623
+msgid " Commands:\n"
+msgstr " Comandos:\n"
+
+#: plugins/sudoers/parse.c:814
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Entradas de Defaults correspondentes a %s em %s:\n"
+
+#: plugins/sudoers/parse.c:832
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Padrão específico de comandos e \"runas\" de %s:\n"
+
+#: plugins/sudoers/parse.c:850
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "Usuário %s pode executar os seguintes comandos em %s:\n"
+
+#: plugins/sudoers/parse.c:865
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Usuário %s não tem permissão para executar sudo em %s.\n"
+
+#: plugins/sudoers/parse_ldif.c:616
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "ignorando sudoRole incompleto: cn: %s"
+
+#: plugins/sudoers/parse_ldif.c:676
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "atributo LDIF inválido: %s"
+
+#: plugins/sudoers/policy.c:80 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "%.*s inválido definido pelo front-end do sudo"
+
+#: plugins/sudoers/policy.c:320 plugins/sudoers/testsudoers.c:268
+msgid "unable to parse network address list"
+msgstr "não foi possível analisar a lista de endereços de rede"
+
+#: plugins/sudoers/policy.c:471
+msgid "user name not set by sudo front-end"
+msgstr "nome de usuário não definido pelo front-end do sudo"
+
+#: plugins/sudoers/policy.c:475
+msgid "user-ID not set by sudo front-end"
+msgstr "ID de usuário não definido pelo front-end do sudo"
+
+#: plugins/sudoers/policy.c:479
+msgid "group-ID not set by sudo front-end"
+msgstr "ID de grupo não definido pelo front-end do sudo"
+
+#: plugins/sudoers/policy.c:483
+msgid "host name not set by sudo front-end"
+msgstr "nome da máquina não definido pelo front-end do sudo"
+
+#: plugins/sudoers/policy.c:685
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "diretório de trabalho inválido: %s"
+
+#: plugins/sudoers/policy.c:861
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "diretório de chroot inválido: %s"
+
+#: plugins/sudoers/policy.c:996 plugins/sudoers/visudo.c:229
+#: plugins/sudoers/visudo.c:851
+#, c-format
+msgid "unable to execute %s"
+msgstr "não foi possível executar %s"
+
+#: plugins/sudoers/policy.c:1066 plugins/sudoers/policy.c:1103
+#: plugins/sudoers/policy.c:1125 plugins/sudoers/policy.c:1151
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: opções de modo inválidas pelo front-end do sudo: 0x%x"
+
+#: plugins/sudoers/policy.c:1182
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Versão de plug-in de política do sudoers %s\n"
+
+#: plugins/sudoers/policy.c:1184
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Versão de gramática de arquivo do sudoers %d\n"
+
+#: plugins/sudoers/policy.c:1188
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Caminho do sudoers: %s\n"
+
+#: plugins/sudoers/policy.c:1191
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "caminho do nsswitch: %s\n"
+
+#: plugins/sudoers/policy.c:1193
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "caminho do ldap.conf: %s\n"
+
+#: plugins/sudoers/policy.c:1194
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "caminho do ldap.secret: %s\n"
+
+#: plugins/sudoers/policy.c:1227
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "não foi possível registrar hook do tipo %d (versão %d.%d)"
+
+#: plugins/sudoers/policy.c:1245
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "não foi possível cancelar registro de hook do tipo %d (versão %d.%d)"
+
+#: plugins/sudoers/pwutil.c:218 plugins/sudoers/pwutil.c:236
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "não foi possível fazer cache de uid %u"
+
+#: plugins/sudoers/pwutil.c:230
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "não foi possível fazer cache de uid %u, já existe"
+
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:308
+#: plugins/sudoers/pwutil.c:371 plugins/sudoers/pwutil.c:416
+#, c-format
+msgid "unable to cache user %s"
+msgstr "não foi possível fazer cache de usuário %s"
+
+#: plugins/sudoers/pwutil.c:303
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "não foi possível fazer cache de usuário %s, já existe"
+
+#: plugins/sudoers/pwutil.c:535 plugins/sudoers/pwutil.c:553
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "não foi possível fazer cache de gid %u"
+
+#: plugins/sudoers/pwutil.c:547
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "não foi possível fazer cache de gid %u, já existe"
+
+#: plugins/sudoers/pwutil.c:601 plugins/sudoers/pwutil.c:619
+#: plugins/sudoers/pwutil.c:680 plugins/sudoers/pwutil.c:729
+#, c-format
+msgid "unable to cache group %s"
+msgstr "não foi possível fazer cache de grupo %s"
+
+#: plugins/sudoers/pwutil.c:614
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "não foi possível fazer cache de grupo %s, já existe"
+
+#: plugins/sudoers/pwutil.c:876 plugins/sudoers/pwutil.c:927
+#: plugins/sudoers/pwutil.c:977 plugins/sudoers/pwutil.c:1029
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "não foi possível fazer cache da lista de grupos de %s, já existe"
+
+#: plugins/sudoers/pwutil.c:882 plugins/sudoers/pwutil.c:932
+#: plugins/sudoers/pwutil.c:983 plugins/sudoers/pwutil.c:1034
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "não foi fazer cache de lista de grupos para %s"
+
+#: plugins/sudoers/pwutil.c:921
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "não foi possível analisar grupos de %s"
+
+#: plugins/sudoers/pwutil.c:1023
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "não foi possível analisar os gids de %s"
+
+#: plugins/sudoers/set_perms.c:114 plugins/sudoers/set_perms.c:445
+#: plugins/sudoers/set_perms.c:852 plugins/sudoers/set_perms.c:1162
+#: plugins/sudoers/set_perms.c:1460
+msgid "perm stack overflow"
+msgstr "estouro da pilha de permissões"
+
+#: plugins/sudoers/set_perms.c:125 plugins/sudoers/set_perms.c:376
+#: plugins/sudoers/set_perms.c:456 plugins/sudoers/set_perms.c:719
+#: plugins/sudoers/set_perms.c:863 plugins/sudoers/set_perms.c:1086
+#: plugins/sudoers/set_perms.c:1173 plugins/sudoers/set_perms.c:1393
+#: plugins/sudoers/set_perms.c:1471 plugins/sudoers/set_perms.c:1562
+msgid "perm stack underflow"
+msgstr "esvaziamento da pilha de permissões"
+
+#: plugins/sudoers/set_perms.c:185 plugins/sudoers/set_perms.c:503
+#: plugins/sudoers/set_perms.c:1227 plugins/sudoers/set_perms.c:1505
+msgid "unable to change to root gid"
+msgstr "não foi possível alterar gid de root"
+
+#: plugins/sudoers/set_perms.c:276 plugins/sudoers/set_perms.c:600
+#: plugins/sudoers/set_perms.c:995 plugins/sudoers/set_perms.c:1304
+msgid "unable to change to runas gid"
+msgstr "não foi possível alterar para gid de \"runas\""
+
+#: plugins/sudoers/set_perms.c:281 plugins/sudoers/set_perms.c:605
+#: plugins/sudoers/set_perms.c:1000 plugins/sudoers/set_perms.c:1309
+msgid "unable to set runas group vector"
+msgstr "não foi possível definir vetor de grupo de \"runas\""
+
+#: plugins/sudoers/set_perms.c:292 plugins/sudoers/set_perms.c:616
+#: plugins/sudoers/set_perms.c:1009 plugins/sudoers/set_perms.c:1318
+msgid "unable to change to runas uid"
+msgstr "não foi possível alterar para uid de \"runas\""
+
+#: plugins/sudoers/set_perms.c:310 plugins/sudoers/set_perms.c:634
+#: plugins/sudoers/set_perms.c:1025 plugins/sudoers/set_perms.c:1334
+msgid "unable to change to sudoers gid"
+msgstr "não foi possível alterar para gid de sudoers"
+
+#: plugins/sudoers/set_perms.c:363 plugins/sudoers/set_perms.c:706
+#: plugins/sudoers/set_perms.c:1073 plugins/sudoers/set_perms.c:1380
+#: plugins/sudoers/set_perms.c:1549
+msgid "too many processes"
+msgstr "processos demais"
+
+#: plugins/sudoers/solaris_audit.c:61
+msgid "unable to get current working directory"
+msgstr "não foi possível definir diretório de trabalho atual"
+
+#: plugins/sudoers/solaris_audit.c:69
+#, c-format
+msgid "truncated audit path user_cmnd: %s"
+msgstr "caminho de auditoria truncado user_cmnd: %s"
+
+#: plugins/sudoers/solaris_audit.c:76
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "caminho de auditoria truncado argv[0]: %s"
+
+#: plugins/sudoers/sssd.c:572
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "não foi possível inicializar a fonte SSS. SSSD está instalado em sua máquina?"
+
+#: plugins/sudoers/sssd.c:580 plugins/sudoers/sssd.c:589
+#: plugins/sudoers/sssd.c:598 plugins/sudoers/sssd.c:607
+#: plugins/sudoers/sssd.c:616
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "não foi possível localizar símbolo \"%s\" em %s"
+
+#: plugins/sudoers/sudoers.c:166 plugins/sudoers/sudoers.c:174
+#: plugins/sudoers/sudoers.c:228 plugins/sudoers/sudoers.c:249
+#: plugins/sudoers/sudoers.c:1040
+msgid "problem with defaults entries"
+msgstr "problema com o entradas padrão"
+
+#: plugins/sudoers/sudoers.c:253
+msgid "no valid sudoers sources found, quitting"
+msgstr "nenhuma fonte de sudoers válida encontrada; saindo"
+
+#: plugins/sudoers/sudoers.c:327
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "usuário sem permissão para alterar o diretório raiz para %s"
+
+#: plugins/sudoers/sudoers.c:329
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "você não tem permissão para usar a opção -R com %s"
+
+#: plugins/sudoers/sudoers.c:354
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "usuário sem permissão para alterar o diretório para %s"
+
+#: plugins/sudoers/sudoers.c:355
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "você não tem permissão para usar a opção -D com %s"
+
+#: plugins/sudoers/sudoers.c:382
+msgid "no command specified"
+msgstr "nenhum comando especificado"
+
+#: plugins/sudoers/sudoers.c:407
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers especifica que o root não tem permissão para usar sudo"
+
+#: plugins/sudoers/sudoers.c:457
+msgid "user not allowed to override closefrom limit"
+msgstr "usuário sem permissão para substituir o limite closefrom"
+
+#: plugins/sudoers/sudoers.c:458
+msgid "you are not permitted to use the -C option"
+msgstr "você não tem permissão para usar a opção -C"
+
+#: plugins/sudoers/sudoers.c:518
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr "dono da marca de tempo (%s): Usuário inexistente"
+
+#: plugins/sudoers/sudoers.c:533
+msgid "no tty"
+msgstr "nenhum tty"
+
+#: plugins/sudoers/sudoers.c:534
+msgid "sorry, you must have a tty to run sudo"
+msgstr "sinto muito, você deve ter um tty para executar sudo"
+
+#: plugins/sudoers/sudoers.c:541
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "shell inválido para o usuário %s: %s"
+
+#: plugins/sudoers/sudoers.c:624
+msgid "command in current directory"
+msgstr "comando no diretório atual"
+
+#: plugins/sudoers/sudoers.c:643
+msgid "user not allowed to set a command timeout"
+msgstr "usuário sem permissão para definir um tempo limite de comando"
+
+#: plugins/sudoers/sudoers.c:645
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "sinto muito, você não tem permissão para definir um tempo limite de comando"
+
+#: plugins/sudoers/sudoers.c:653
+msgid "user not allowed to preserve the environment"
+msgstr "usuário sem permissão para preservar o ambiente"
+
+#: plugins/sudoers/sudoers.c:655
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "sinto muito, você não tem permissão para preservar o ambiente"
+
+#: plugins/sudoers/sudoers.c:989
+msgid "command too long"
+msgstr "comando muito grande"
+
+#: plugins/sudoers/sudoers.c:1028
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "sudoedit não precisa ser executado via sudo"
+
+#: plugins/sudoers/sudoers.c:1087 plugins/sudoers/sudoreplay.c:1568
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "não foi possível ler %s"
+
+#: plugins/sudoers/sudoers.c:1112 plugins/sudoers/visudo.c:426
+#: plugins/sudoers/visudo.c:720
+#, c-format
+msgid "unable to stat %s"
+msgstr "não foi possível obter o estado de %s"
+
+#: plugins/sudoers/sudoers.c:1116 plugins/sudoers/visudo.c:1009
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s não é um arquivo comum"
+
+#: plugins/sudoers/sudoers.c:1120 plugins/sudoers/timestamp.c:252 toke.l:1148
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s tem como dono o uid %u, deveria ser %u"
+
+#: plugins/sudoers/sudoers.c:1124 toke.l:1153
+#, c-format
+msgid "%s is world writable"
+msgstr "%s é gravável globalmente"
+
+#: plugins/sudoers/sudoers.c:1128 toke.l:1156
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s tem como dono o gid %u, deveria ser %u"
+
+#: plugins/sudoers/sudoers.c:1161
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "apenas o root pode usar \"-c %s\""
+
+#: plugins/sudoers/sudoers.c:1180
+#, c-format
+msgid "unknown login class %s"
+msgstr "classe de login desconhecida %s"
+
+#: plugins/sudoers/sudoers.c:1266 plugins/sudoers/sudoers.c:1281
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "não foi possível resolver máquina %s"
+
+#: plugins/sudoers/sudoreplay.c:259
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "opção de filtro inválida: %s"
+
+#: plugins/sudoers/sudoreplay.c:275
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "espera máxima inválida: %s"
+
+#: plugins/sudoers/sudoreplay.c:298
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "fator de velocidade inválido: %s"
+
+#: plugins/sudoers/sudoreplay.c:333
+#, c-format
+msgid "invalid time offset %s"
+msgstr "deslocamento de tempo inválido %s"
+
+# timing é o nome do arquivo gerado pelo sudo; não traduzir.
+#: plugins/sudoers/sudoreplay.c:342
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+# timing é o nome do arquivo gerado pelo sudo; não traduzir.
+#: plugins/sudoers/sudoreplay.c:347
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/timing: %s"
+
+#: plugins/sudoers/sudoreplay.c:375
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Reproduzindo sessão de sudo: %s"
+
+#: plugins/sudoers/sudoreplay.c:637
+msgid "unable to set tty to raw mode"
+msgstr "não foi possível definir o tty para modo raw"
+
+#: plugins/sudoers/sudoreplay.c:688
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr "Aviso: seu terminal é muito pequeno para reproduzir adequadamente o log.\n"
+
+#: plugins/sudoers/sudoreplay.c:689
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Geometria do log é %d x %d; geometria do seu terminal é %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:717
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Reprodução finalizada, pressione qualquer tecla para restaurar o terminal."
+
+#: plugins/sudoers/sudoreplay.c:1218 plugins/sudoers/sudoreplay.c:1248
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "expressão ambígua \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1270
+msgid "unmatched ')' in expression"
+msgstr "\")\" não coincidente na expressão"
+
+#: plugins/sudoers/sudoreplay.c:1274
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "termo de pesquisa desconhecido \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1289
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s requer um argumento"
+
+#: plugins/sudoers/sudoreplay.c:1292 plugins/sudoers/sudoreplay.c:1544
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr "expressão regular inválida: %s"
+
+#: plugins/sudoers/sudoreplay.c:1297
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "não foi possível analisar a data \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:1306
+msgid "unmatched '(' in expression"
+msgstr "\"(\" sem correspondente na expressão"
+
+#: plugins/sudoers/sudoreplay.c:1308
+msgid "illegal trailing \"or\""
+msgstr "fim de linha ilegal com \"or\""
+
+#: plugins/sudoers/sudoreplay.c:1310
+msgid "illegal trailing \"!\""
+msgstr "fim de linha ilegal com \"!\""
+
+#: plugins/sudoers/sudoreplay.c:1368
+#, c-format
+msgid "unknown search type %d"
+msgstr "tipo de pesquisa desconhecido %d"
+
+#: plugins/sudoers/sudoreplay.c:1635
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "uso: %s [-hnRS] [-d diretório] [-m número] [-s número] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1638
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "uso: %s [-h] [-d diretório] -l [expressão de pesquisa]\n"
+
+#: plugins/sudoers/sudoreplay.c:1647
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - reproduz logs de sessão do sudo\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1649
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Opções:\n"
+" -d, --directory=dir especifica o diretório dos logs de sessão\n"
+" -f, --filter=filtro especifica qual o tipo de E/S para exibir\n"
+" -h, --help exibe mensagem de ajuda e sai\n"
+" -l, --list lista IDs de sessão disponíveis, podendo ser filtrado\n"
+" com uso opcional de expressão regular\n"
+" -m, --max-wait=núm número máximo, em segundos, de espera entre eventos\n"
+" -n, --non-interactive sem interação, a sessão é enviada para a saída padrão\n"
+" -R, --no-resize não tenta redimensionar o terminal\n"
+" -S, --suspend-wait aguarda enquanto o comando estava suspenso\n"
+" -s, --speed=núm aumenta ou diminui a velocidade da saída\n"
+" -V, --version exibe a informação da versão e sai"
+
+#: plugins/sudoers/testsudoers.c:344
+msgid "\thost unmatched"
+msgstr "\tmáquina sem correspondente"
+
+#: plugins/sudoers/testsudoers.c:347
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Comando permitido"
+
+#: plugins/sudoers/testsudoers.c:348
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Comando negado"
+
+#: plugins/sudoers/testsudoers.c:348
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Comando sem correspondente"
+
+#: plugins/sudoers/timestamp.c:260
+#, c-format
+msgid "%s is group writable"
+msgstr "%s é gravável pelo grupo"
+
+#: plugins/sudoers/timestamp.c:328 plugins/sudoers/timestamp.c:663
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "não foi possível truncar o arquivo de marca de tempo para %lld bytes"
+
+#: plugins/sudoers/timestamp.c:860
+msgid "ignoring time stamp from the future"
+msgstr "ignorado marca de tempo no futuro"
+
+#: plugins/sudoers/timestamp.c:883
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "marca de tempo muito a frente no futuro: %20.20s"
+
+#: plugins/sudoers/timestamp.c:1005
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "não foi possível travar o arquivo de marca de tempo %s"
+
+#: plugins/sudoers/timestamp.c:1049 plugins/sudoers/timestamp.c:1069
+#, c-format
+msgid "lecture status path too long: %s/%s"
+msgstr "caminho de status de instruções muito longo: %s/%s"
+
+#: plugins/sudoers/toke_util.c:150
+msgid "sudoedit should not be specified with a path"
+msgstr "sudoedit não deve ser especificado com um caminho"
+
+#: plugins/sudoers/visudo.c:224
+msgid "the -x option will be removed in a future release"
+msgstr "a opção -x será removida em um lançamento futuro"
+
+#: plugins/sudoers/visudo.c:226
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "por favor, em vez disso, considere usar o utilitário cvtsudoers"
+
+#: plugins/sudoers/visudo.c:277 plugins/sudoers/visudo.c:653
+#, c-format
+msgid "press return to edit %s: "
+msgstr "pressione enter para editar %s: "
+
+#: plugins/sudoers/visudo.c:338
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "editor especificado (%s) não existe"
+
+#: plugins/sudoers/visudo.c:340
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "nenhum editor encontrado (caminho do editor = %s)"
+
+#: plugins/sudoers/visudo.c:446 plugins/sudoers/visudo.c:454
+msgid "write error"
+msgstr "erro de escrita"
+
+#: plugins/sudoers/visudo.c:500
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "não foi possível obter estado de arquivo temporário (%s), %s sem alteração"
+
+#: plugins/sudoers/visudo.c:507
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "arquivo de temporário (%s) com comprimento zero, %s sem alteração"
+
+#: plugins/sudoers/visudo.c:513
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "editor (%s) falhou, %s sem alteração"
+
+#: plugins/sudoers/visudo.c:535
+#, c-format
+msgid "%s unchanged"
+msgstr "%s sem alteração"
+
+#: plugins/sudoers/visudo.c:592
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "não foi possível reabrir arquivo temporário (%s), %s sem alteração."
+
+#: plugins/sudoers/visudo.c:604
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "não foi possível analisar arquivo temporário (%s), erro desconhecido"
+
+#: plugins/sudoers/visudo.c:642
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr "erro interno, não foi possível localizar %s na lista!"
+
+#: plugins/sudoers/visudo.c:722 plugins/sudoers/visudo.c:731
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "não foi possível definir (uid, gid) de %s para (%u, %u)"
+
+#: plugins/sudoers/visudo.c:754
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s e %s não estão no mesmo sistema de arquivos, usando mv para renomear"
+
+#: plugins/sudoers/visudo.c:765
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "comando \"%s %s %s\" falhou, %s sem alteração"
+
+#: plugins/sudoers/visudo.c:775
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "erro ao renomear %s, %s sem alteração"
+
+#: plugins/sudoers/visudo.c:796
+msgid "What now? "
+msgstr "Agora o que? "
+
+#: plugins/sudoers/visudo.c:810
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Opções são:\n"
+" (e)dit - editar arquivos sudoers novamente\n"
+" e(x)it - sair sem salvar alterações no arquivo sudoers\n"
+" (Q)uit - sair e salvar alterações no arquivo sudoers (PERIGO!)\n"
+
+#: plugins/sudoers/visudo.c:856
+#, c-format
+msgid "unable to run %s"
+msgstr "não foi possível executar %s"
+
+#: plugins/sudoers/visudo.c:886
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: dono (uid, gid) incorreto; deveria ser (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:893
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: permissões incorretas; deveria estar no modo 0%o\n"
+
+#: plugins/sudoers/visudo.c:942 plugins/sudoers/visudo.c:949
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: análise OK\n"
+
+#: plugins/sudoers/visudo.c:968
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s ocupado, tente novamente"
+
+#: plugins/sudoers/visudo.c:972
+msgid "Edit anyway? [y/N]"
+msgstr "Editar mesmo assim? [y/N]"
+
+#: plugins/sudoers/visudo.c:1068
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "Aviso: %s:%d:%d: %s não usado \"%s\""
+
+#: plugins/sudoers/visudo.c:1184
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - edita o arquivo sudoers com segurança\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1186
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Opções:\n"
+" -c, --check modo de verificação, apenas\n"
+" -f, --file=sudoers especifica localização do arquivo sudoers\n"
+" -h, --help exibe uma mensagem de ajuda e sai\n"
+" -q, --quiet mensagens de erro de sintaxe menos detalhada\n"
+" -s, --strict verificação rigorosa de sintaxe\n"
+" -V, --version exibe a informação da versão e sai\n"
+
+#: toke.l:187
+msgid "empty string"
+msgstr "string vazia"
+
+#: toke.l:199 toke.l:513
+msgid "empty group"
+msgstr "grupo vazio"
+
+#: toke.l:209 toke.l:511
+msgid "empty netgroup"
+msgstr "netgroup vazio"
+
+#: toke.l:305 toke.l:317 toke.l:329 toke.l:345 toke.l:364 toke.l:404
+msgid "invalid line continuation"
+msgstr "continuação de linha inválida"
+
+#: toke.l:550 toke.l:562
+msgid "invalid IPv6 address"
+msgstr "endereço IPv6 inválido"
+
+#: toke.l:789
+msgid "unexpected line break in string"
+msgstr "quebra de linha inesperada na string"
+
+#: toke.l:1119
+msgid "too many levels of includes"
+msgstr "níveis de inclusões demais"
+
+#~ msgid "unable to get TLS server method: %s"
+#~ msgstr "não foi possível obter o método do servidor TLS: %s"
+
+#~ msgid "%s:%d unknown key: %s"
+#~ msgstr "%s:%d chave desconhecida: %s"
+
+#~ msgid "%s:%u unable to parse \"%s\""
+#~ msgstr "%s:%u não foi possível analisar \"%s\""
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " -f, --file path to configuration file\n"
+#~ " -h --help display help message and exit\n"
+#~ " -n, --no-fork do not fork, run in the foreground\n"
+#~ " -R, --random-drop percent chance connections will drop\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Opções:\n"
+#~ " -f, --file caminho para o arquivo de configuração\n"
+#~ " -h, --help exibe uma mensagem de ajuda e sai\n"
+#~ " -n, --no-fork não faz fork, executa em primeiro plano\n"
+#~ " -R, --random-drop chance em porcentagem das conexões caírem\n"
+#~ " -V, --version exibe a informação da versão e sai\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " --help display help message and exit\n"
+#~ " -A, --accept only send an accept event (no I/O)\n"
+#~ " -h, --host host to send logs to\n"
+#~ " -i, --iolog_id remote ID of I/O log to be resumed\n"
+#~ " -p, --port port to use when connecting to host\n"
+#~ " -r, --restart restart previous I/O log transfer\n"
+#~ " -R, --reject reject the command with the given reason\n"
+#~ " -b, --ca-bundle certificate bundle file to verify server's cert against\n"
+#~ " -c, --cert certificate file for TLS handshake\n"
+#~ " -k, --key private key file\n"
+#~ " -n, --no-verify do not verify server certificate\n"
+#~ " -t, --test test audit server by sending selected I/O log n times in parallel\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Opções:\n"
+#~ " --help exibe mensagem de ajuda e sai\n"
+#~ " -A, --accept só envia um evento de aceite (sem E/S)\n"
+#~ " -h, --host máquina a ser enviado logs\n"
+#~ " -i, --iolog_id ID remoto do log de E/S para ser resumido\n"
+#~ " -p, --port porta para usar ao conectar à máquina\n"
+#~ " -r, --restart reinicia transferência anterior de log de E/S\n"
+#~ " -R, --reject rejeita a comando com o motivo dado\n"
+#~ " -b, --ca-bundle arquivo de pacote de certificados para verificar\n"
+#~ " o certificado do servidor\n"
+#~ " -c, --cert arquivo de certificado para negociação TLS\n"
+#~ " -k, --key arquivo de chave privada\n"
+#~ " -n, --no-verify não verifica o certificado do servidor\n"
+#~ " -t, --test teste o servidor de auditoria enviando o log de\n"
+#~ " E/S selecionado n vezes em paralelo\n"
+#~ " -V, --version exibe informações de versão e sai\n"
+
+#~ msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+#~ msgstr "Pré-carrega as funções de exec de teste contidas na biblioteca sudo_noexec"
+
+#~ msgid "sudo_ldap_conf_add_ports: port too large"
+#~ msgstr "sudo_ldap_conf_add_ports: porta muito grande"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s\n"
+#~ msgstr "SSL_connect falhou: ssl_error=%d, stack=%s\n"
+
+#~ msgid "CA bundle file was not specified"
+#~ msgstr "O arquivo de pacote de AC não foi especificado"
+
+#~ msgid "Client certificate was not specified"
+#~ msgstr "O certificado do cliente não foi especificado"
+
+#~| msgid "%s: unable to allocate options: %s"
+#~ msgid "Unable to allocate ssl object: %s\n"
+#~ msgstr "Não foi possível alocar objeto ssl: %s"
+
+#, fuzzy
+#~| msgid "timeout value too large"
+#~ msgid "client message too large: %zu\n"
+#~ msgstr "valor de timeout grande demais"
+
+#, fuzzy
+#~| msgid "Send mail if the user is not in sudoers"
+#~ msgid "CA bundle file is not set in sudoers"
+#~ msgstr "Envia correio se o usuário não estiver no sudoers"
+
+#, fuzzy
+#~| msgid "Send mail if the user is not in sudoers"
+#~ msgid "Signed certificate file is not set in sudoers"
+#~ msgstr "Envia correio se o usuário não estiver no sudoers"
+
+#, fuzzy
+#~| msgid "unknown search type %d"
+#~ msgid "unknown address family: %d"
+#~ msgstr "tipo de pesquisa desconhecido %d"
+
+#~ msgid "audit_failure message too long"
+#~ msgstr "mensagem de audit_failure muito grande"
+
+#~ msgid "No user or host"
+#~ msgstr "nenhum usuário ou máquina"
+
+#~ msgid "validation failure"
+#~ msgstr "falha de validação"
+
+# timing é o nome do arquivo gerado pelo sudo; não traduzir.
+#~ msgid "%s/%s/timing: %s"
+#~ msgstr "%s/%s/timing: %s"
+
+#~ msgid "ignoring invalid attribute value: %s"
+#~ msgstr "ignorando valor de atributo inválido: %s"
+
+#~ msgid "unable to cache user %s, out of memory"
+#~ msgstr "não foi possível fazer cache de usuário %s, memória insuficiente"
+
+#~ msgid "unable to cache group %s, out of memory"
+#~ msgstr "não foi possível fazer cache de grupo %s, memória insuficiente"
+
+#~ msgid "unable to cache group list for %s, out of memory"
+#~ msgstr "não foi possível fazer cache da lista de grupos de %s, memória insuficiente"
+
+#~ msgid ""
+#~ "\n"
+#~ "LDAP Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Papel LDAP: DESCONHECIDO\n"
+
+#~ msgid " Order: %s\n"
+#~ msgstr " Ordem: %s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: %s\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Papel SSSD: %s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Papel SSSD: DESCONHECIDO\n"
+
+#~ msgid "Warning: cycle in %s `%s'"
+#~ msgstr "Aviso: ciclo em %s \"%s\""
+
+#~ msgid "Warning: unused %s `%s'"
+#~ msgstr "Aviso: %s não usado \"%s\""
+
+#~ msgid "timestamp path too long: %s/%s"
+#~ msgstr "caminho de marca de tempo muito longo: %s/%s"
+
+#~ msgid "unable to stat editor (%s)"
+#~ msgstr "não foi possível obter estado do editor (%s)"
+
+# Mantive, pois hostbuf é uma variável do plugins/sudoers/ldap.c
+#~ msgid "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+#~ msgstr "sudo_ldap_conf_add_ports: sem espaço para expansão de hostbuf"
+
+# Mantive, pois hostbuf é uma variável do plugins/sudoers/ldap.c
+#~ msgid "sudo_ldap_parse_uri: out of space building hostbuf"
+#~ msgstr "sudo_ldap_parse_uri: sem espaço na construção de hostbuf"
+
+#~ msgid "sudo_ldap_build_pass1 allocation mismatch"
+#~ msgstr "alocação de sudo_ldap_build_pass1 não confere"
+
+#~ msgid "Password:"
+#~ msgstr "Senha:"
+
+#~ msgid "internal error: insufficient space for log line"
+#~ msgstr "erro interno: espaço insuficiente para linha de log"
+
+#~ msgid "fill_args: buffer overflow"
+#~ msgstr "fill_args: estouro de buffer"
+
+#~ msgid "%s owned by uid %u, should be uid %u"
+#~ msgstr "%s tem como dono o uid %u, deveria ser uid %u"
+
+#~ msgid "%s writable by non-owner (0%o), should be mode 0700"
+#~ msgstr "%s gravável por não-dono (0%o); deveria estar no modo 0700"
+
+#~ msgid "%s exists but is not a regular file (0%o)"
+#~ msgstr "%s existe, mas não é um arquivo comum (0%o)"
+
+#~ msgid "%s writable by non-owner (0%o), should be mode 0600"
+#~ msgstr "%s gravável por não-dono (0%o); deveria estar no modo 0600"
+
+#~ msgid "unable to remove %s, will reset to the Unix epoch"
+#~ msgstr "não foi possível remover %s, redefinindo para como estava no Unix"
+
+#~ msgid "unable to reset %s to the Unix epoch"
+#~ msgstr "não foi possível redefinir %s para como estava no Unix"
+
+#~ msgid "value out of range"
+#~ msgstr "valor fora da faixa"
+
+#~ msgid "unable to mix ldaps and starttls"
+#~ msgstr "não foi possível misturar ldaps e starttls"
+
+#~ msgid "writing to standard output"
+#~ msgstr "escrevendo para saída padrão"
+
+#~ msgid "too many parenthesized expressions, max %d"
+#~ msgstr "parênteses de expressões demais, máximo %d"
+
+#~ msgid "getaudit: failed"
+#~ msgstr "getaudit: falhou"
+
+#~ msgid "getauid: failed"
+#~ msgstr "getauid: falhou"
+
+#~ msgid "au_to_subject: failed"
+#~ msgstr "au_to_subject: falhou"
+
+#~ msgid "au_to_exec_args: failed"
+#~ msgstr "au_to_exec_args: falhou"
+
+#~ msgid "au_to_return32: failed"
+#~ msgstr "au_to_return32: falhou"
+
+#~ msgid "au_to_text: failed"
+#~ msgstr "au_to_text: falhou"
+
+#~ msgid "nanosleep: tv_sec %ld, tv_nsec %ld"
+#~ msgstr "nanosleep: tv_sec %ld, tv_nsec %ld"
+
+#~ msgid "pam_chauthtok: %s"
+#~ msgstr "pam_chauthtok: %s"
+
+#~ msgid "pam_authenticate: %s"
+#~ msgstr "pam_authenticate: %s"
+
+#~ msgid "getauid failed"
+#~ msgstr "getauid falhou"
+
+#, fuzzy
+#~ msgid "Unable to dlopen %s: %s"
+#~ msgstr "não foi possível fazer dlopen %s: %s"
diff --git a/plugins/sudoers/po/ro.mo b/plugins/sudoers/po/ro.mo
new file mode 100644
index 0000000..3e65c40
--- /dev/null
+++ b/plugins/sudoers/po/ro.mo
Binary files differ
diff --git a/plugins/sudoers/po/ro.po b/plugins/sudoers/po/ro.po
new file mode 100644
index 0000000..ee45d3b
--- /dev/null
+++ b/plugins/sudoers/po/ro.po
@@ -0,0 +1,4144 @@
+# Portable object template file for the sudoers plugin
+# This file is put in the public domain.
+# Todd C. Miller <Todd.Miller@sudo.ws>, 2011-2018
+# This file is distributed under the same license as the sudo package.
+#
+# Florentina Mușat <florentina.musat.28@gmail.com>, 2020.
+# Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>, 2022, 2023.
+#
+# Cronologia traducerii fișierului „sudoers”:
+# Traducera inițială, făcută de FM, pentru versiunea sudoers 1.9.2rc1.
+# Actualizare a algoritmului formelor de plural (de la „trei-vechi” la „patru”, experimental).
+# Actualizare a traducerii pentru versiunea 1.9.10b1, făcută de R-GC, feb-2022.
+# Actualizare a traducerii pentru versiunea 1.9.11b1, făcută de R-GC, mai-2022.
+# Actualizare a traducerii pentru versiunea 1.9.12b2, făcută de R-GC, oct-2022.
+# Actualizare a traducerii pentru versiunea 1.9.13b2, făcută de R-GC, ian-2023.
+# Actualizare a traducerii pentru versiunea 1.9.14b1, făcută de R-GC, iun-2023.
+# Actualizare a traducerii pentru versiunea 1.9.15b1, făcută de R-GC, oct-2023.
+# Actualizare a traducerii pentru versiunea Y, făcută de X, Z(luna-anul).
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.9.15b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-10-19 10:02-0600\n"
+"PO-Revision-Date: 2023-10-21 14:58+0200\n"
+"Last-Translator: Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>\n"
+"Language-Team: Romanian <translation-team-ro@lists.sourceforge.net>\n"
+"Language: ro\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=((n==1) ? 0 : (n==2) ? 1 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 2 : 3);\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 3.2.2\n"
+
+#: confstr.sh:1 gram.y:1257 plugins/sudoers/logging.c:911
+msgid "syntax error"
+msgstr "eroare de sintaxă"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "parola lui %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] parola pentru %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Parola: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** Informații de SECURITATE pentru %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Încercați din nou."
+
+#: gram.y:238 gram.y:305 gram.y:314 gram.y:323 gram.y:333 gram.y:343 gram.y:367
+#: gram.y:394 gram.y:403 gram.y:411 gram.y:420 gram.y:429 gram.y:503 gram.y:513
+#: gram.y:525 gram.y:573 gram.y:582 gram.y:591 gram.y:600 gram.y:733 gram.y:742
+#: gram.y:757 gram.y:777 gram.y:796 gram.y:959 gram.y:964 gram.y:972 gram.y:986
+#: gram.y:992 gram.y:1004 gram.y:1010 gram.y:1135 gram.y:1144 gram.y:1152
+#: gram.y:1161 gram.y:1170 gram.y:1199 gram.y:1208 gram.y:1216 gram.y:1317
+#: gram.y:1447 gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:313 lib/eventlog/eventlog.c:765
+#: lib/eventlog/eventlog.c:842 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:484
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:185
+#: logsrvd/iolog_writer.c:218 logsrvd/iolog_writer.c:228
+#: logsrvd/iolog_writer.c:257 logsrvd/iolog_writer.c:278
+#: logsrvd/iolog_writer.c:290 logsrvd/iolog_writer.c:300
+#: logsrvd/iolog_writer.c:310 logsrvd/iolog_writer.c:320
+#: logsrvd/iolog_writer.c:330 logsrvd/iolog_writer.c:342
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:1057 logsrvd/logsrvd.c:1120 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:650
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1743
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:216
+#: logsrvd/logsrvd_journal.c:217 logsrvd/logsrvd_journal.c:274
+#: logsrvd/logsrvd_journal.c:279 logsrvd/logsrvd_journal.c:439
+#: logsrvd/logsrvd_journal.c:441 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:216 logsrvd/logsrvd_local.c:278
+#: logsrvd/logsrvd_local.c:279 logsrvd/logsrvd_local.c:417
+#: logsrvd/logsrvd_local.c:468 logsrvd/logsrvd_local.c:469
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:475
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/logsrvd_relay.c:446
+#: logsrvd/logsrvd_relay.c:748 logsrvd/logsrvd_relay.c:855
+#: logsrvd/sendlog.c:256 logsrvd/sendlog.c:265 logsrvd/sendlog.c:297
+#: logsrvd/sendlog.c:303 logsrvd/sendlog.c:352 logsrvd/sendlog.c:630
+#: logsrvd/sendlog.c:1822 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/bsdauth.c:154 plugins/sudoers/auth/kerb5.c:122
+#: plugins/sudoers/auth/kerb5.c:150 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/auth/sia.c:61
+#: plugins/sudoers/canon_path.c:129 plugins/sudoers/canon_path.c:161
+#: plugins/sudoers/check_aliases.c:128 plugins/sudoers/check_util.c:56
+#: plugins/sudoers/check_util.c:84 plugins/sudoers/cvtsudoers.c:132
+#: plugins/sudoers/cvtsudoers.c:176 plugins/sudoers/cvtsudoers.c:193
+#: plugins/sudoers/cvtsudoers.c:204 plugins/sudoers/cvtsudoers.c:338
+#: plugins/sudoers/cvtsudoers.c:379 plugins/sudoers/cvtsudoers.c:399
+#: plugins/sudoers/cvtsudoers.c:545 plugins/sudoers/cvtsudoers.c:698
+#: plugins/sudoers/cvtsudoers.c:716 plugins/sudoers/cvtsudoers.c:891
+#: plugins/sudoers/cvtsudoers.c:899 plugins/sudoers/cvtsudoers.c:1395
+#: plugins/sudoers/cvtsudoers.c:1399 plugins/sudoers/cvtsudoers.c:1501
+#: plugins/sudoers/cvtsudoers_csv.c:183 plugins/sudoers/cvtsudoers_csv.c:247
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:152
+#: plugins/sudoers/cvtsudoers_ldif.c:195 plugins/sudoers/cvtsudoers_ldif.c:236
+#: plugins/sudoers/cvtsudoers_ldif.c:302 plugins/sudoers/cvtsudoers_ldif.c:378
+#: plugins/sudoers/cvtsudoers_ldif.c:432 plugins/sudoers/cvtsudoers_ldif.c:440
+#: plugins/sudoers/cvtsudoers_ldif.c:451 plugins/sudoers/cvtsudoers_ldif.c:458
+#: plugins/sudoers/cvtsudoers_ldif.c:470 plugins/sudoers/cvtsudoers_ldif.c:483
+#: plugins/sudoers/cvtsudoers_ldif.c:491 plugins/sudoers/cvtsudoers_ldif.c:638
+#: plugins/sudoers/cvtsudoers_merge.c:47 plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1158
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:212
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:694 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:294 plugins/sudoers/ldap_util.c:301
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:402
+#: plugins/sudoers/log_client.c:717 plugins/sudoers/log_client.c:739
+#: plugins/sudoers/log_client.c:744 plugins/sudoers/log_client.c:1426
+#: plugins/sudoers/log_client.c:1547 plugins/sudoers/log_client.c:1670
+#: plugins/sudoers/log_client.c:1993 plugins/sudoers/log_client.c:2052
+#: plugins/sudoers/logging.c:110 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:872 plugins/sudoers/lookup.c:338
+#: plugins/sudoers/lookup.c:355 plugins/sudoers/lookup.c:374
+#: plugins/sudoers/lookup.c:393 plugins/sudoers/lookup.c:410
+#: plugins/sudoers/lookup.c:433 plugins/sudoers/lookup.c:444
+#: plugins/sudoers/match_command.c:302 plugins/sudoers/match_command.c:574
+#: plugins/sudoers/match_command.c:641 plugins/sudoers/match_command.c:737
+#: plugins/sudoers/match_command.c:785 plugins/sudoers/match_digest.c:88
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:595
+#: plugins/sudoers/parse_ldif.c:625 plugins/sudoers/parse_ldif.c:650
+#: plugins/sudoers/parse_ldif.c:708 plugins/sudoers/parse_ldif.c:725
+#: plugins/sudoers/parse_ldif.c:753 plugins/sudoers/parse_ldif.c:760
+#: plugins/sudoers/policy.c:646 plugins/sudoers/policy.c:1061
+#: plugins/sudoers/prompt.c:94 plugins/sudoers/pwutil.c:219
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:368
+#: plugins/sudoers/pwutil.c:542 plugins/sudoers/pwutil.c:607
+#: plugins/sudoers/pwutil.c:679 plugins/sudoers/pwutil.c:877
+#: plugins/sudoers/pwutil.c:967 plugins/sudoers/pwutil.c:1015
+#: plugins/sudoers/pwutil.c:1076 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:145 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1307 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:256
+#: plugins/sudoers/testsudoers.c:265 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:164 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1095
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1320
+msgid "unable to allocate memory"
+msgstr "nu se poate aloca memoria"
+
+#: gram.y:624
+msgid "a digest requires a path name"
+msgstr "tabelul sumelor de control necesită un nume de rută"
+
+#: gram.y:646
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "valorile pentru „CWD” trebuie să înceapă cu un caracter: „/”, „~”, sau „*”"
+
+#: gram.y:652
+msgid "\"CWD\" path too long"
+msgstr "ruta „CWD” este prea lungă"
+
+#: gram.y:662
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "valorile pentru „CHROOT” trebuie să înceapă cu un caracter: „/”, „~”, sau „*”"
+
+#: gram.y:668
+msgid "\"CHROOT\" path too long"
+msgstr "ruta „CHROOT” este prea lungă"
+
+#: gram.y:817
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "eroare de sintaxă, cuvântul rezervat %s utilizat ca nume de alias"
+
+#: gram.y:840
+msgid "invalid notbefore value"
+msgstr "valoare „notbefore” nevalidă"
+
+#: gram.y:849
+msgid "invalid notafter value"
+msgstr "valoare „notafter” nevalidă"
+
+#: gram.y:859 plugins/sudoers/policy.c:390
+msgid "timeout value too large"
+msgstr "limită de timp prea mare"
+
+#: gram.y:861 plugins/sudoers/policy.c:392
+msgid "invalid timeout value"
+msgstr "valoare de limită de timp nevalidă"
+
+#: gram.y:982 plugins/sudoers/sudoers.c:1162
+msgid "command too long"
+msgstr "comandă prea lungă"
+
+#: gram.y:1016
+msgid "expected a fully-qualified path name"
+msgstr "se aștepta un nume de rută complet calificat"
+
+#: gram.y:1261
+#, c-format
+msgid "%s:%d:%zu: %s\n"
+msgstr "%s:%d:%zu: %s\n"
+
+#: gram.y:1315
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Aliasul „%s” este deja definit"
+
+#: gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:765 lib/eventlog/eventlog.c:838
+#: lib/eventlog/eventlog.c:841 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:483
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:232
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:174
+#: logsrvd/iolog_writer.c:184 logsrvd/iolog_writer.c:197
+#: logsrvd/iolog_writer.c:217 logsrvd/iolog_writer.c:227
+#: logsrvd/iolog_writer.c:246 logsrvd/iolog_writer.c:256
+#: logsrvd/iolog_writer.c:267 logsrvd/iolog_writer.c:277
+#: logsrvd/iolog_writer.c:289 logsrvd/iolog_writer.c:299
+#: logsrvd/iolog_writer.c:309 logsrvd/iolog_writer.c:319
+#: logsrvd/iolog_writer.c:329 logsrvd/iolog_writer.c:341
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:530
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:668
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:1131
+#: logsrvd/logsrvd.c:1446 logsrvd/logsrvd.c:1453 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:649
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1742
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:125
+#: logsrvd/logsrvd_journal.c:216 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:250 logsrvd/logsrvd_journal.c:258
+#: logsrvd/logsrvd_journal.c:287 logsrvd/logsrvd_journal.c:291
+#: logsrvd/logsrvd_journal.c:439 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:278 logsrvd/logsrvd_local.c:468
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:493
+#: logsrvd/logsrvd_queue.c:158 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/sendlog.c:256 logsrvd/sendlog.c:265
+#: logsrvd/sendlog.c:297 logsrvd/sendlog.c:303 logsrvd/sendlog.c:352
+#: logsrvd/sendlog.c:630 logsrvd/sendlog.c:1523 logsrvd/sendlog.c:1530
+#: logsrvd/sendlog.c:1753 logsrvd/sendlog.c:1822 logsrvd/tls_init.c:305
+#: logsrvd/tls_init.c:329 logsrvd/tls_init.c:340 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/pam.c:518 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/canon_path.c:129
+#: plugins/sudoers/canon_path.c:161 plugins/sudoers/check_aliases.c:128
+#: plugins/sudoers/check_util.c:56 plugins/sudoers/check_util.c:84
+#: plugins/sudoers/cvtsudoers.c:132 plugins/sudoers/cvtsudoers.c:175
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:203
+#: plugins/sudoers/cvtsudoers.c:337 plugins/sudoers/cvtsudoers.c:544
+#: plugins/sudoers/cvtsudoers.c:697 plugins/sudoers/cvtsudoers.c:715
+#: plugins/sudoers/cvtsudoers.c:891 plugins/sudoers/cvtsudoers.c:898
+#: plugins/sudoers/cvtsudoers.c:1395 plugins/sudoers/cvtsudoers.c:1399
+#: plugins/sudoers/cvtsudoers.c:1501 plugins/sudoers/cvtsudoers_csv.c:182
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:151 plugins/sudoers/cvtsudoers_ldif.c:194
+#: plugins/sudoers/cvtsudoers_ldif.c:235 plugins/sudoers/cvtsudoers_ldif.c:301
+#: plugins/sudoers/cvtsudoers_ldif.c:377 plugins/sudoers/cvtsudoers_ldif.c:431
+#: plugins/sudoers/cvtsudoers_ldif.c:439 plugins/sudoers/cvtsudoers_ldif.c:450
+#: plugins/sudoers/cvtsudoers_ldif.c:457 plugins/sudoers/cvtsudoers_ldif.c:469
+#: plugins/sudoers/cvtsudoers_ldif.c:482 plugins/sudoers/cvtsudoers_ldif.c:490
+#: plugins/sudoers/cvtsudoers_ldif.c:637 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51 plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1157
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:211
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:693 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:293 plugins/sudoers/ldap_util.c:300
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:228
+#: plugins/sudoers/log_client.c:250 plugins/sudoers/log_client.c:264
+#: plugins/sudoers/log_client.c:402 plugins/sudoers/log_client.c:717
+#: plugins/sudoers/log_client.c:739 plugins/sudoers/log_client.c:744
+#: plugins/sudoers/log_client.c:1426 plugins/sudoers/log_client.c:1547
+#: plugins/sudoers/log_client.c:1670 plugins/sudoers/log_client.c:1993
+#: plugins/sudoers/log_client.c:2052 plugins/sudoers/logging.c:110
+#: plugins/sudoers/logging.c:189 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:755 plugins/sudoers/logging.c:872
+#: plugins/sudoers/logging.c:925 plugins/sudoers/logging.c:932
+#: plugins/sudoers/lookup.c:337 plugins/sudoers/lookup.c:354
+#: plugins/sudoers/lookup.c:373 plugins/sudoers/lookup.c:392
+#: plugins/sudoers/lookup.c:409 plugins/sudoers/lookup.c:432
+#: plugins/sudoers/lookup.c:443 plugins/sudoers/match_command.c:301
+#: plugins/sudoers/match_command.c:573 plugins/sudoers/match_command.c:640
+#: plugins/sudoers/match_command.c:737 plugins/sudoers/match_command.c:784
+#: plugins/sudoers/match_digest.c:88 plugins/sudoers/parse_ldif.c:152
+#: plugins/sudoers/parse_ldif.c:183 plugins/sudoers/parse_ldif.c:252
+#: plugins/sudoers/parse_ldif.c:260 plugins/sudoers/parse_ldif.c:265
+#: plugins/sudoers/parse_ldif.c:341 plugins/sudoers/parse_ldif.c:352
+#: plugins/sudoers/parse_ldif.c:379 plugins/sudoers/parse_ldif.c:396
+#: plugins/sudoers/parse_ldif.c:408 plugins/sudoers/parse_ldif.c:412
+#: plugins/sudoers/parse_ldif.c:426 plugins/sudoers/parse_ldif.c:484
+#: plugins/sudoers/parse_ldif.c:595 plugins/sudoers/parse_ldif.c:624
+#: plugins/sudoers/parse_ldif.c:649 plugins/sudoers/parse_ldif.c:707
+#: plugins/sudoers/parse_ldif.c:724 plugins/sudoers/parse_ldif.c:752
+#: plugins/sudoers/parse_ldif.c:759 plugins/sudoers/policy.c:157
+#: plugins/sudoers/policy.c:166 plugins/sudoers/policy.c:175
+#: plugins/sudoers/policy.c:204 plugins/sudoers/policy.c:374
+#: plugins/sudoers/policy.c:390 plugins/sudoers/policy.c:392
+#: plugins/sudoers/policy.c:430 plugins/sudoers/policy.c:439
+#: plugins/sudoers/policy.c:448 plugins/sudoers/policy.c:457
+#: plugins/sudoers/policy.c:493 plugins/sudoers/policy.c:502
+#: plugins/sudoers/policy.c:511 plugins/sudoers/policy.c:520
+#: plugins/sudoers/policy.c:529 plugins/sudoers/policy.c:538
+#: plugins/sudoers/policy.c:547 plugins/sudoers/policy.c:646
+#: plugins/sudoers/policy.c:1061 plugins/sudoers/prompt.c:94
+#: plugins/sudoers/pwutil.c:219 plugins/sudoers/pwutil.c:290
+#: plugins/sudoers/pwutil.c:368 plugins/sudoers/pwutil.c:542
+#: plugins/sudoers/pwutil.c:607 plugins/sudoers/pwutil.c:679
+#: plugins/sudoers/pwutil.c:877 plugins/sudoers/pwutil.c:967
+#: plugins/sudoers/pwutil.c:1015 plugins/sudoers/pwutil.c:1076
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1306 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:255
+#: plugins/sudoers/testsudoers.c:264 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:163 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1094
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1309 toke.l:1320
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:304
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "nu se poate duplica stdin: %m"
+
+#: lib/eventlog/eventlog.c:346
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "nu se poate executa %s: %m"
+
+#: lib/eventlog/eventlog.c:394 plugins/sudoers/auth/aix_auth.c:199
+msgid "unable to fork"
+msgstr "nu se poate executa fork()"
+
+#: lib/eventlog/eventlog.c:404 lib/eventlog/eventlog.c:471
+#, c-format
+msgid "unable to fork: %m"
+msgstr "nu se poate executa fork(): %m"
+
+#: lib/eventlog/eventlog.c:461
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "nu se poate deschide linia de legătură: %m"
+
+#: lib/eventlog/eventlog.c:1000
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:1029
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (comandă continuată) %s"
+
+#: lib/eventlog/parse_json.c:175
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "se aștepta JSON_STRING, s-a obținut %d"
+
+#: lib/eventlog/parse_json.c:180
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY este prea mare"
+
+#: lib/eventlog/parse_json.c:506
+msgid "missing double quote in name"
+msgstr "lipsesc ghilimelele duble din nume"
+
+#: lib/eventlog/parse_json.c:624
+msgid "missing JSON_OBJECT"
+msgstr "JSON_OBJECT lipsește"
+
+#: lib/eventlog/parse_json.c:628
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "s-a așteptat JSON_OBJECT, s-a obținut %d"
+
+#: lib/eventlog/parse_json.c:762
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "stiva json a fost epuizată (maxim %u cadre)"
+
+#: lib/eventlog/parse_json.c:840
+msgid "objects must consist of name:value pairs"
+msgstr "obiectele trebuie să fie formate din perechi nume:valoare"
+
+#: lib/eventlog/parse_json.c:845 lib/eventlog/parse_json.c:876
+#: lib/eventlog/parse_json.c:920 lib/eventlog/parse_json.c:942
+#: lib/eventlog/parse_json.c:964 lib/eventlog/parse_json.c:986
+#: lib/eventlog/parse_json.c:1008
+msgid "missing separator between values"
+msgstr "lipsește separatorul dintre valori"
+
+#: lib/eventlog/parse_json.c:860 lib/eventlog/parse_json.c:1034
+msgid "unmatched close brace"
+msgstr "acoladă de închidere desperecheată"
+
+#: lib/eventlog/parse_json.c:871
+msgid "unexpected array"
+msgstr "matrice neașteptată"
+
+#: lib/eventlog/parse_json.c:891 lib/eventlog/parse_json.c:1037
+msgid "unmatched close bracket"
+msgstr "paranteză dreaptă închisă desperecheată"
+
+#: lib/eventlog/parse_json.c:902
+msgid "unexpected string"
+msgstr "șir neașteptat"
+
+#: lib/eventlog/parse_json.c:913
+msgid "missing colon after name"
+msgstr "lipsesc două puncte „:” după nume"
+
+#: lib/eventlog/parse_json.c:934 lib/eventlog/parse_json.c:956
+msgid "unexpected boolean"
+msgstr "valoare boleană neașteptată"
+
+#: lib/eventlog/parse_json.c:978
+msgid "unexpected null"
+msgstr "valoare null neașteptată"
+
+#: lib/eventlog/parse_json.c:999
+msgid "unexpected number"
+msgstr "număr neașteptat"
+
+#: lib/eventlog/parse_json.c:1045
+msgid "parse error"
+msgstr "eroare de analizare"
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1290
+#: plugins/sudoers/sudoreplay.c:1291 plugins/sudoers/sudoreplay.c:1587
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr "expresie regulată nevalidă „%s”: %s"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: fișier de jurnal nevalid"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: câmpul marcaj de timp lipsește"
+
+#: lib/iolog/iolog_legacy.c:90
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: marcajul de timp %s: %s"
+
+#: lib/iolog/iolog_legacy.c:97
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: câmpul utilizator lipsește"
+
+#: lib/iolog/iolog_legacy.c:108
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: câmpul de utilizator efectiv (rulează ca utilizatorul X) lipsește"
+
+#: lib/iolog/iolog_legacy.c:119
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: câmpul de grup efectiv (rulează ca grupul X) lipsește"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s există dar nu este un director (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:124 lib/iolog/iolog_mkdtemp.c:80
+#: logsrvd/iolog_writer.c:795 plugins/sudoers/timestamp.c:218
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "nu s-a putut executa «mkdir», pentru a crea directorul %s"
+
+#: lib/iolog/iolog_mkdtemp.c:85 plugins/sudoers/visudo.c:769
+#: plugins/sudoers/visudo.c:803 plugins/sudoers/visudo.c:809
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "nu s-a putut modifica modul de acces de la %s la 0%o"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "eroare la citirea fișierului de sincronizare: %s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "linie de fișier de sincronizare nevalidă: %s"
+
+#: logsrvd/iolog_writer.c:65
+#, c-format
+msgid "%s: protocol error: NULL key"
+msgstr "%s: eroare de protocol: cheie nulă (NULL)"
+
+#: logsrvd/iolog_writer.c:69
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s: eroare de protocol: tip incorect pentru %s"
+
+#: logsrvd/iolog_writer.c:74 logsrvd/logsrvd_local.c:109
+#: logsrvd/logsrvd_local.c:123 logsrvd/logsrvd_local.c:131
+#: logsrvd/logsrvd_local.c:149
+#, c-format
+msgid "%s: protocol error: NULL value found in %s"
+msgstr "%s: eroare de protocol: valoare nulă (NULL) găsită în %s"
+
+#: logsrvd/iolog_writer.c:141 plugins/sudoers/logging.c:1024
+#: plugins/sudoers/policy.c:613
+msgid "unable to generate UUID"
+msgstr "nu s-a putut genera UUID-ul"
+
+#: logsrvd/iolog_writer.c:354 logsrvd/iolog_writer.c:359
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:369
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s: eroare de protocol: lipsește %s din AcceptMessage"
+
+#: logsrvd/iolog_writer.c:430
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s: nu se poate formata ID-ul sesiunii"
+
+#: logsrvd/iolog_writer.c:444 logsrvd/iolog_writer.c:458
+#: logsrvd/iolog_writer.c:472 logsrvd/iolog_writer.c:487
+#: logsrvd/iolog_writer.c:501 logsrvd/iolog_writer.c:515
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s: %s nu este configurat"
+
+#: logsrvd/iolog_writer.c:551 logsrvd/iolog_writer.c:558
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr "nu se poate expanda ruta către iolog %s"
+
+#: logsrvd/iolog_writer.c:576
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr "nu se poate crea ruta către iolog %s"
+
+#: logsrvd/iolog_writer.c:606
+#, c-format
+msgid "invalid iofd %d"
+msgstr "iofd nevalid: %d"
+
+#: logsrvd/iolog_writer.c:626
+#, c-format
+msgid "error closing iofd %u: %s"
+msgstr "eroare la închiderea iofd %u: %s"
+
+#: logsrvd/iolog_writer.c:647
+#, c-format
+msgid "error flushing iofd %u: %s"
+msgstr "eroare la golirea iofd %u: %s"
+
+#: logsrvd/iolog_writer.c:765
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "jurnal de In/Ieș nevalid %s: %s menționat, dar nu definit"
+
+#: logsrvd/iolog_writer.c:777 logsrvd/logsrvd_journal.c:391
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "%s: nu se poate găsi punctul de reluare [%lld, %ld]"
+
+#: logsrvd/iolog_writer.c:799 logsrvd/logsrvd_journal.c:434
+#: logsrvd/logsrvd_queue.c:115 logsrvd/tls_init.c:256
+#: plugins/sudoers/check.c:285 plugins/sudoers/cvtsudoers.c:758
+#: plugins/sudoers/cvtsudoers.c:780 plugins/sudoers/cvtsudoers.c:1461
+#: plugins/sudoers/cvtsudoers_csv.c:697 plugins/sudoers/cvtsudoers_json.c:902
+#: plugins/sudoers/cvtsudoers_ldif.c:711 plugins/sudoers/sudoers.c:1291
+#: plugins/sudoers/sudoers.c:1317 plugins/sudoers/sudoreplay.c:1497
+#: plugins/sudoers/timestamp.c:478 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:990
+#, c-format
+msgid "unable to open %s"
+msgstr "nu se poate deschide %s"
+
+#: logsrvd/iolog_writer.c:811 logsrvd/logsrv_util.c:111
+#: logsrvd/logsrv_util.c:118 plugins/sudoers/sudoreplay.c:355
+#: plugins/sudoers/sudoreplay.c:361
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "nu se poate deschide %s/%s"
+
+#: logsrvd/iolog_writer.c:824
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "nu se poate copia %s/%s în %s/%s: %s"
+
+#: logsrvd/iolog_writer.c:853 logsrvd/logsrvd_journal.c:198
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "nu se poate redenumi %s în %s"
+
+#: logsrvd/logsrv_util.c:153 logsrvd/logsrv_util.c:182
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s: nu se poate găsi punctul de reluare [%lld, %ld]"
+
+#: logsrvd/logsrv_util.c:165
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "lipsește fișierul jurnal de In/Ieș %s/%s"
+
+#: logsrvd/logsrv_util.c:172
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s: nu se poate căuta mai departe %zu"
+
+#: logsrvd/logsrvd.c:271 logsrvd/logsrvd_queue.c:135
+msgid "unable to connect to relay"
+msgstr "nu se poate conecta la releu"
+
+#: logsrvd/logsrvd.c:338 logsrvd/logsrvd_relay.c:847
+#, c-format
+msgid "server message too large: %zu"
+msgstr "mesajul serverului este prea mare: %zu"
+
+#: logsrvd/logsrvd.c:430 logsrvd/logsrvd.c:553 logsrvd/logsrvd.c:639
+#: logsrvd/logsrvd.c:881 logsrvd/logsrvd.c:895 logsrvd/logsrvd.c:1056
+#: logsrvd/logsrvd.c:1181 logsrvd/logsrvd.c:1354 logsrvd/logsrvd.c:1372
+#: logsrvd/logsrvd.c:1471 logsrvd/logsrvd.c:1596 logsrvd/logsrvd.c:1783
+#: logsrvd/logsrvd_journal.c:503 logsrvd/logsrvd_local.c:238
+#: logsrvd/logsrvd_queue.c:164 logsrvd/logsrvd_relay.c:172
+#: logsrvd/logsrvd_relay.c:249 logsrvd/logsrvd_relay.c:253
+#: logsrvd/logsrvd_relay.c:391 logsrvd/logsrvd_relay.c:583
+#: logsrvd/logsrvd_relay.c:747 logsrvd/logsrvd_relay.c:1137
+#: logsrvd/sendlog.c:1308 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:216 plugins/sudoers/audit.c:281
+#: plugins/sudoers/iolog.c:1041 plugins/sudoers/iolog.c:1175
+#: plugins/sudoers/iolog.c:1274 plugins/sudoers/log_client.c:121
+#: plugins/sudoers/log_client.c:343 plugins/sudoers/log_client.c:359
+#: plugins/sudoers/log_client.c:407 plugins/sudoers/log_client.c:613
+#: plugins/sudoers/log_client.c:620 plugins/sudoers/log_client.c:1114
+#: plugins/sudoers/log_client.c:1395 plugins/sudoers/log_client.c:1436
+#: plugins/sudoers/log_client.c:1444 plugins/sudoers/log_client.c:1603
+#: plugins/sudoers/log_client.c:1728 plugins/sudoers/log_client.c:2060
+#: plugins/sudoers/log_client.c:2068 plugins/sudoers/logging.c:148
+#: plugins/sudoers/logging.c:206 plugins/sudoers/sudoreplay.c:519
+#: plugins/sudoers/sudoreplay.c:566 plugins/sudoers/sudoreplay.c:808
+#: plugins/sudoers/sudoreplay.c:920 plugins/sudoers/sudoreplay.c:1011
+#: plugins/sudoers/sudoreplay.c:1026 plugins/sudoers/sudoreplay.c:1033
+#: plugins/sudoers/sudoreplay.c:1040 plugins/sudoers/sudoreplay.c:1047
+#: plugins/sudoers/sudoreplay.c:1054 plugins/sudoers/sudoreplay.c:1182
+msgid "unable to add event to queue"
+msgstr "nu se poate adăuga evenimentul la coadă"
+
+#: logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:491 logsrvd/logsrvd.c:523
+#: logsrvd/logsrvd.c:577 logsrvd/logsrvd.c:656 logsrvd/logsrvd.c:692
+#: logsrvd/logsrvd.c:728 logsrvd/logsrvd.c:764 logsrvd/logsrvd_relay.c:512
+#: logsrvd/logsrvd_relay.c:545
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr "stare neașteptată %d pentru %s"
+
+#: logsrvd/logsrvd.c:455 logsrvd/logsrvd.c:492 logsrvd/logsrvd.c:524
+#: logsrvd/logsrvd.c:578 logsrvd/logsrvd.c:657 logsrvd/logsrvd.c:693
+#: logsrvd/logsrvd.c:729 logsrvd/logsrvd.c:765 logsrvd/logsrvd_relay.c:514
+#: logsrvd/logsrvd_relay.c:547
+msgid "state machine error"
+msgstr "eroare de stare a mașinii"
+
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:462
+msgid "invalid AcceptMessage"
+msgstr "AcceptMessage nevalid"
+
+#: logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:499
+msgid "invalid RejectMessage"
+msgstr "RejectMessage nevalid"
+
+#: logsrvd/logsrvd.c:530 logsrvd/logsrvd.c:531
+msgid "invalid ExitMessage"
+msgstr "ExitMessage nevalid"
+
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:585
+msgid "invalid RestartMessage"
+msgstr "RestartMessage nevalid"
+
+#: logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:620
+msgid "invalid AlertMessage"
+msgstr "AlertMessage nevalid"
+
+#: logsrvd/logsrvd.c:661 logsrvd/logsrvd.c:697 logsrvd/logsrvd.c:733
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s: IoBuffer neașteptat"
+
+#: logsrvd/logsrvd.c:662 logsrvd/logsrvd.c:698 logsrvd/logsrvd.c:734
+msgid "protocol error"
+msgstr "eroare de protocol"
+
+#: logsrvd/logsrvd.c:668 logsrvd/logsrvd.c:669
+msgid "invalid IoBuffer"
+msgstr "IoBuffer nevalid"
+
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:705
+msgid "invalid ChangeWindowSize"
+msgstr "ChangeWindowSize nevalid"
+
+#: logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:741
+msgid "invalid CommandSuspend"
+msgstr "CommandSuspend nevalid"
+
+#: logsrvd/logsrvd.c:790 logsrvd/logsrvd_journal.c:302
+#: logsrvd/logsrvd_relay.c:654 logsrvd/sendlog.c:1207
+#: plugins/sudoers/log_client.c:1593
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "nu se poate despacheta %s cu dimensiunea %zu"
+
+#: logsrvd/logsrvd.c:835 logsrvd/logsrvd_journal.c:376
+#: logsrvd/logsrvd_relay.c:678
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "valoare type_case %d neașteptată în %s din %s"
+
+#: logsrvd/logsrvd.c:837
+msgid "unrecognized ClientMessage type"
+msgstr "tip de ClientMessage nerecunoscut"
+
+#: logsrvd/logsrvd.c:927
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "a expirat timpul de scriere la clientul %s"
+
+#: logsrvd/logsrvd.c:932 logsrvd/logsrvd_relay.c:919 logsrvd/sendlog.c:1413
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr "lipsește memoria tampon de scriere pentru clientul %s"
+
+#: logsrvd/logsrvd.c:1027
+#, c-format
+msgid "timed out reading from client %s"
+msgstr "a expirat timpul de citire de la clientul %s"
+
+#: logsrvd/logsrvd.c:1068 logsrvd/logsrvd_relay.c:782
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr "sfârșit de fișier de la %s fără închiderea corectă a TLS"
+
+#: logsrvd/logsrvd.c:1112 logsrvd/logsrvd_relay.c:205 logsrvd/sendlog.c:336
+#: plugins/sudoers/log_client.c:723
+#, c-format
+msgid "client message too large: %zu"
+msgstr "mesajul clientului este prea mare: %zu"
+
+#: logsrvd/logsrvd.c:1113 logsrvd/logsrvd_journal.c:259
+#: logsrvd/logsrvd_journal.c:260
+msgid "client message too large"
+msgstr "mesajul clientului este prea mare"
+
+#: logsrvd/logsrvd.c:1131 logsrvd/logsrvd.c:1132
+msgid "invalid ClientMessage"
+msgstr "ClientMessage nevalid"
+
+#: logsrvd/logsrvd.c:1432
+msgid "unable to get remote IP addr"
+msgstr "nu se poate obține adresa IP de la distanță"
+
+#: logsrvd/logsrvd.c:1463 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:281
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "Nu se pot atașa datele utilizatorului la obiectul ssl: %s"
+
+#: logsrvd/logsrvd.c:1646 logsrvd/logsrvd.c:2007
+msgid "unable to setup listen socket"
+msgstr "nu se poate configura soclul de ascultare"
+
+#: logsrvd/logsrvd.c:1766
+#, c-format
+msgid "unexpected signal %d"
+msgstr "semnal neașteptat %d"
+
+#: logsrvd/logsrvd.c:1909
+msgid "sudo log server"
+msgstr "server de jurnal al sudo"
+
+#: logsrvd/logsrvd.c:1911 logsrvd/sendlog.c:126
+msgid "Options:"
+msgstr "Opțiuni:"
+
+#: logsrvd/logsrvd.c:1913
+msgid "path to configuration file"
+msgstr "ruta către fișierul de configurare"
+
+#: logsrvd/logsrvd.c:1915 logsrvd/sendlog.c:128
+msgid "display help message and exit"
+msgstr "afișează mesajul de ajutor și iese"
+
+#: logsrvd/logsrvd.c:1917
+msgid "do not fork, run in the foreground"
+msgstr "nu se bifurcă, rulează în prim-plan"
+
+#: logsrvd/logsrvd.c:1919
+msgid "percent chance connections will drop"
+msgstr "șansele procentuale de conexiuni vor scădea"
+
+#: logsrvd/logsrvd.c:1921 logsrvd/sendlog.c:158
+msgid "display version information and exit"
+msgstr "afișează informațiile despre versiune și iese"
+
+#: logsrvd/logsrvd.c:1971 logsrvd/sendlog.c:1722
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "Este necesară versiunea Protobuf-C 1.3 sau mai mare"
+
+#: logsrvd/logsrvd.c:1987
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "valoare nevalidă a probabilității de pierdere: %s"
+
+#: logsrvd/logsrvd.c:1990 logsrvd/sendlog.c:1776
+#: plugins/sudoers/cvtsudoers.c:250 plugins/sudoers/sudoreplay.c:294
+#: plugins/sudoers/visudo.c:181
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s versiunea %s\n"
+
+#: logsrvd/logsrvd_conf.c:422 plugins/sudoers/check.c:69
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/sudoers.c:419 plugins/sudoers/sudoers.c:929
+#: plugins/sudoers/sudoers.c:1034 plugins/sudoers/sudoers.c:1424
+#: plugins/sudoers/testsudoers.c:169 plugins/sudoers/testsudoers.c:285
+#: plugins/sudoers/testsudoers.c:459
+#, c-format
+msgid "unknown user %s"
+msgstr "utilizator necunoscut %s"
+
+#: logsrvd/logsrvd_conf.c:439 plugins/sudoers/iolog.c:148
+#: plugins/sudoers/sudoers.c:425 plugins/sudoers/sudoers.c:1458
+#: plugins/sudoers/testsudoers.c:483
+#, c-format
+msgid "unknown group %s"
+msgstr "grup necunoscut %s"
+
+#: logsrvd/logsrvd_conf.c:457
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr "nu se poate analiza modul iolog %s"
+
+#: logsrvd/logsrvd_conf.c:474 logsrvd/logsrvd_conf.c:1243
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "valoare nevalidă pentru %s: %s"
+
+#: logsrvd/logsrvd_conf.c:527
+msgid "TLS not supported"
+msgstr "fără suport TLS"
+
+#: logsrvd/logsrvd_conf.c:549
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:622 logsrvd/logsrvd_conf.c:1032
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s: nu este o rută complet calificată"
+
+#: logsrvd/logsrvd_conf.c:951 logsrvd/logsrvd_conf.c:967
+#: logsrvd/logsrvd_conf.c:1676
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "facilitate de syslog necunoscută %s"
+
+#: logsrvd/logsrvd_conf.c:983 logsrvd/logsrvd_conf.c:999
+#: logsrvd/logsrvd_conf.c:1015 logsrvd/logsrvd_conf.c:1680
+#: logsrvd/logsrvd_conf.c:1684 logsrvd/logsrvd_conf.c:1688
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "prioritate de syslog necunoscută %s"
+
+#: logsrvd/logsrvd_conf.c:1197
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d „[” desperecheată: %s"
+
+#: logsrvd/logsrvd_conf.c:1203
+#, c-format
+msgid "%s:%d garbage after ']': %s"
+msgstr "%s:%d gunoi după „]”: %s"
+
+#: logsrvd/logsrvd_conf.c:1215
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s:%d secțiune de configurare nevalidă: %s"
+
+#: logsrvd/logsrvd_conf.c:1223
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d linie de configurare nevalidă: %s"
+
+#: logsrvd/logsrvd_conf.c:1229
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d nume de secțiune așteptat: %s"
+
+#: logsrvd/logsrvd_conf.c:1251
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] cheie ilegală: %s"
+
+#: logsrvd/logsrvd_conf.c:1281 plugins/sudoers/cvtsudoers.c:273
+#: plugins/sudoers/logging.c:1076
+#, c-format
+msgid "unable to open log file %s"
+msgstr "nu se poate deschide fișierul de jurnal: %s"
+
+#: logsrvd/logsrvd_conf.c:1763
+msgid "unable to initialize server TLS context"
+msgstr "nu se poate inițializa contextul TLS al serverului"
+
+#: logsrvd/logsrvd_conf.c:1783
+msgid "unable to initialize relay TLS context"
+msgstr "nu se poate inițializa contextul TLS al releului"
+
+#: logsrvd/logsrvd_journal.c:149 logsrvd/logsrvd_journal.c:430
+#: logsrvd/logsrvd_journal.c:435
+msgid "unable to create journal file"
+msgstr "nu se poate crea fișierul de jurnal"
+
+#: logsrvd/logsrvd_journal.c:153 logsrvd/logsrvd_queue.c:109
+#: plugins/sudoers/visudo.c:1046
+#, c-format
+msgid "unable to lock %s"
+msgstr "nu se poate bloca %s"
+
+#: logsrvd/logsrvd_journal.c:156
+msgid "unable to lock journal file"
+msgstr "nu se poate bloca fișierul de jurnal"
+
+#: logsrvd/logsrvd_journal.c:164
+msgid "unable to open journal file"
+msgstr "nu se poate deschide fișierul de jurnal"
+
+#: logsrvd/logsrvd_journal.c:185 logsrvd/logsrvd_journal.c:466
+#: logsrvd/logsrvd_journal.c:471
+msgid "unable to write journal file"
+msgstr "nu se poate scrie fișierul de jurnal"
+
+#: logsrvd/logsrvd_journal.c:193 logsrvd/logsrvd_journal.c:200
+msgid "unable to rename journal file"
+msgstr "nu se poate redenumi fișierul de jurnal"
+
+#: logsrvd/logsrvd_journal.c:247 logsrvd/logsrvd_journal.c:248
+#: logsrvd/logsrvd_journal.c:288 logsrvd/logsrvd_journal.c:289
+msgid "unexpected EOF reading journal file"
+msgstr "sfârșit de fișier neașteptat la citirea fișierului de jurnal"
+
+#: logsrvd/logsrvd_journal.c:251 logsrvd/logsrvd_journal.c:252
+#: logsrvd/logsrvd_journal.c:292 logsrvd/logsrvd_journal.c:293
+msgid "error reading journal file"
+msgstr "eroare la citirea fișierului de jurnal"
+
+#: logsrvd/logsrvd_journal.c:304 logsrvd/logsrvd_journal.c:390
+msgid "invalid journal file, unable to restart"
+msgstr "fișier de jurnal nevalid, nu se poate reporni"
+
+#: logsrvd/logsrvd_journal.c:449
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "nu se poate ajunge la poziția [%lld, %ld] din fișierul de jurnal %s"
+
+#: logsrvd/logsrvd_local.c:166
+#, c-format
+msgid "unexpected value_case %d in %s from %s"
+msgstr "value_case neașteptată %d în %s din %s"
+
+#: logsrvd/logsrvd_local.c:194
+msgid "error parsing AcceptMessage"
+msgstr "eroare la analizarea AcceptMessage"
+
+#: logsrvd/logsrvd_local.c:205
+msgid "error creating I/O log"
+msgstr "eroare la crearea jurnalului de In/Ieș"
+
+#: logsrvd/logsrvd_local.c:228
+msgid "error logging accept event"
+msgstr "eroare la înregistrarea evenimentului de acceptare"
+
+#: logsrvd/logsrvd_local.c:267
+msgid "error parsing RejectMessage"
+msgstr "eroare la analizarea RejectMessage"
+
+#: logsrvd/logsrvd_local.c:291
+msgid "error logging reject event"
+msgstr "eroare la înregistrarea evenimentului de respingere"
+
+#: logsrvd/logsrvd_local.c:427 logsrvd/logsrvd_local.c:437
+msgid "error logging exit event"
+msgstr "eroare la înregistrarea evenimentului de ieșire"
+
+#: logsrvd/logsrvd_local.c:494 logsrvd/logsrvd_local.c:495
+msgid "log is already complete, cannot be restarted"
+msgstr "jurnalul este deja complet, nu poate fi repornit"
+
+#: logsrvd/logsrvd_local.c:525
+msgid "unable to restart log"
+msgstr "nu se poate reporni jurnalizarea"
+
+#: logsrvd/logsrvd_local.c:541
+msgid "error parsing AlertMessage"
+msgstr "eroare la analizarea AlertMessage"
+
+#: logsrvd/logsrvd_local.c:551
+msgid "error logging alert event"
+msgstr "eroare la înregistrarea evenimentului de alertă"
+
+#: logsrvd/logsrvd_local.c:587 logsrvd/logsrvd_local.c:650
+#: logsrvd/logsrvd_local.c:685
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr "nu se poate formata memoria tampon de timp, lungime %d"
+
+#: logsrvd/logsrvd_local.c:601 logsrvd/logsrvd_local.c:609
+#: logsrvd/logsrvd_local.c:657 logsrvd/logsrvd_local.c:692
+#: plugins/sudoers/sudoreplay.c:344 toke.l:981 toke.l:984
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: logsrvd/logsrvd_local.c:620
+msgid "randomly dropping connection"
+msgstr "întreruperea aleatorie a conexiunii"
+
+#: logsrvd/logsrvd_local.c:632
+msgid "error writing IoBuffer"
+msgstr "eroare la scrierea IoBuffer"
+
+#: logsrvd/logsrvd_local.c:667
+msgid "error writing ChangeWindowSize"
+msgstr "eroare la scrierea ChangeWindowSize"
+
+#: logsrvd/logsrvd_local.c:702
+msgid "error writing CommandSuspend"
+msgstr "eroare la scrierea CommandSuspend"
+
+#: logsrvd/logsrvd_relay.c:437
+msgid "TLS handshake with relay host failed"
+msgstr "negocierea TLS cu gazda releu a eșuat"
+
+#: logsrvd/logsrvd_relay.c:465
+msgid "unable to connect to relay host"
+msgstr "nu se poate conecta la gazda releu"
+
+# R-GC, scrie:
+# după revizuirea fișierului, DȘ spune:
+# «→ aici pare că lipsește un spațiu după cele două puncte.»
+# ***
+# corectare efectuată
+#: logsrvd/logsrvd_relay.c:520
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s: ServerHello nevalid, server_id lipsește"
+
+#: logsrvd/logsrvd_relay.c:522 logsrvd/sendlog.c:1111
+#: plugins/sudoers/log_client.c:1479
+msgid "invalid ServerHello"
+msgstr "ServerHello nevalid"
+
+#: logsrvd/logsrvd_relay.c:681
+msgid "unrecognized ServerMessage type"
+msgstr "tip de ServerMessage nerecunoscut"
+
+#: logsrvd/logsrvd_relay.c:710
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr "a expirat limita de timp de citire de la releu %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:712
+msgid "timeout reading from relay"
+msgstr "a expirat limita de timp de citire de la releul"
+
+#: logsrvd/logsrvd_relay.c:767
+msgid "relay host name does not match certificate"
+msgstr "numele gazdei releului nu se potrivește cu certificatul"
+
+#: logsrvd/logsrvd_relay.c:773 logsrvd/logsrvd_relay.c:787
+#: logsrvd/logsrvd_relay.c:794
+msgid "error reading from relay"
+msgstr "eroare la citirea de la releu"
+
+#: logsrvd/logsrvd_relay.c:815
+msgid "unable to read from relay"
+msgstr "nu se poate citi de la releu"
+
+#: logsrvd/logsrvd_relay.c:830 logsrvd/logsrvd_relay.c:949
+msgid "relay server closed connection"
+msgstr "conexiune închisă a serverului de releu"
+
+#: logsrvd/logsrvd_relay.c:848
+msgid "server message too large"
+msgstr "mesajul serverului este prea mare"
+
+#: logsrvd/logsrvd_relay.c:912
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr "a expirat limita de timp la scrierea la releu %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:914
+msgid "timeout writing to relay"
+msgstr "a expirat limita de timp de scriere la releu"
+
+#: logsrvd/logsrvd_relay.c:968 logsrvd/logsrvd_relay.c:975
+#: logsrvd/logsrvd_relay.c:987
+msgid "error writing to relay"
+msgstr "eroare la scrierea la releu"
+
+#: logsrvd/sendlog.c:124
+msgid "send sudo I/O log to remote server"
+msgstr "trimite jurnalul de In/Ieș al «sudo» la serverul de la distanță"
+
+#: logsrvd/sendlog.c:130
+msgid "only send an accept event (no I/O)"
+msgstr "trimite doar un eveniment de acceptare (fără In/Ieș)"
+
+#: logsrvd/sendlog.c:133
+msgid "certificate bundle file to verify server's cert against"
+msgstr "fișierul pachet de certificate pentru a verifica certificatul serverului"
+
+#: logsrvd/sendlog.c:135
+msgid "certificate file for TLS handshake"
+msgstr "fișier de certificat pentru negocierea TLS"
+
+#: logsrvd/sendlog.c:138
+msgid "host to send logs to"
+msgstr "gazda la care se trimit jurnalele"
+
+#: logsrvd/sendlog.c:140
+msgid "remote ID of I/O log to be resumed"
+msgstr "ID-ul de la distanță al jurnalului In/Ieș care urmează să fie reluat"
+
+#: logsrvd/sendlog.c:143
+msgid "private key file"
+msgstr "fișier de cheie privată"
+
+#: logsrvd/sendlog.c:145
+msgid "do not verify server certificate"
+msgstr "nu se verifică certificatul serverului"
+
+#: logsrvd/sendlog.c:148
+msgid "port to use when connecting to host"
+msgstr "portul de utilizat atunci când vă conectați la gazdă"
+
+#: logsrvd/sendlog.c:150
+msgid "restart previous I/O log transfer"
+msgstr "repornește transferul precedent de jurnal In/Ieș"
+
+#: logsrvd/sendlog.c:152
+msgid "reject the command with the given reason"
+msgstr "respinge comanda cu motivul specificat"
+
+#: logsrvd/sendlog.c:154
+msgid "stop transfer after reaching this time"
+msgstr "oprește transferul după ce s-a atins acest timp"
+
+#: logsrvd/sendlog.c:156
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "testează serverul de auditare prin trimiterea jurnalului de In/Ieș selectat de n ori în paralel"
+
+#: logsrvd/sendlog.c:181 plugins/sudoers/log_client.c:453
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "nu se poate căuta %s:%s: %s"
+
+#: logsrvd/sendlog.c:219
+msgid "unable to get server IP addr"
+msgstr "nu se poate obține adresa IP a serverului"
+
+#: logsrvd/sendlog.c:314 plugins/sudoers/sudoreplay.c:868
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "nu se poate citi %s/%s: %s"
+
+#: logsrvd/sendlog.c:1035 plugins/sudoers/iolog.c:959
+#: plugins/sudoers/iolog.c:1034
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "eveniment de In/Ieș neașteptat %d"
+
+#: logsrvd/sendlog.c:1088 logsrvd/sendlog.c:1105 logsrvd/sendlog.c:1139
+#: plugins/sudoers/log_client.c:1129 plugins/sudoers/log_client.c:1405
+#: plugins/sudoers/log_client.c:1473 plugins/sudoers/log_client.c:1512
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: stare neașteptată %d"
+
+#: logsrvd/sendlog.c:1175 plugins/sudoers/log_client.c:1561
+#, c-format
+msgid "error message received from server: %s"
+msgstr "mesaj de eroare primit de la server: %s"
+
+#: logsrvd/sendlog.c:1188 plugins/sudoers/log_client.c:1574
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "mesaj de renunțare primit de la server: %s"
+
+#: logsrvd/sendlog.c:1247 plugins/sudoers/log_client.c:1624
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s: valoare type_case neașteptată %d"
+
+#: logsrvd/sendlog.c:1276
+msgid "timeout reading from server"
+msgstr "a expirat limita de timp de citire de la server"
+
+#: logsrvd/sendlog.c:1327 plugins/sudoers/log_client.c:1747
+msgid "host name does not match certificate"
+msgstr "numele gazdei nu se potrivește cu certificatul"
+
+#: logsrvd/sendlog.c:1361
+msgid "premature EOF"
+msgstr "sfârșit de fișier prematur"
+
+#: logsrvd/sendlog.c:1374 plugins/sudoers/log_client.c:1795
+#, c-format
+msgid "server message too large: %u"
+msgstr "mesajul serverului este prea mare: %u"
+
+#: logsrvd/sendlog.c:1430
+msgid "timeout writing to server"
+msgstr "a expirat limita de timp de scriere la server"
+
+#: logsrvd/sendlog.c:1800
+msgid "both restart point and iolog ID must be specified"
+msgstr "trebuie să fie specificat atît ID-ul iolog cît și punctul de repornire"
+
+#: logsrvd/sendlog.c:1804
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "un punct de repornire poate să nu fie stabilit când nicio In/Ieș nu este stabilită"
+
+#: logsrvd/sendlog.c:1880
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "a ieșit prematur cu starea %d"
+
+#: logsrvd/sendlog.c:1881
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "timpul scurs trimis la server [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1883
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "punctul de consemnare primit de la server [%lld, %ld]"
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:315
+msgid "TLS handshake timeout occurred"
+msgstr "a expirat limita de timp a negocierii TLS"
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:337 plugins/sudoers/log_client.c:353
+msgid "unable to set event"
+msgstr "nu s-a putut configura evenimentul"
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "conexiunea TLS a eșuat: %s"
+
+#: logsrvd/tls_client.c:196
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "nu s-a putut aloca obiectul ssl: %s"
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "Nu s-a putut atașa soclul la obiectul ssl: %s"
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr "nu s-a putut inițializa contextul ssl: %s"
+
+#: logsrvd/tls_init.c:138 logsrvd/tls_init.c:146
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "nu s-a putut configura suita de cifrare TLS 1.2 la valoarea %s: %s"
+
+#: logsrvd/tls_init.c:166 logsrvd/tls_init.c:174
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "nu s-a putut configura suita de cifrare TLS 1.3 la valoarea %s: %s"
+
+#: logsrvd/tls_init.c:206 logsrvd/tls_init.c:227
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "nu se pot stabili parametrii diffie-hellman: %s"
+
+#: logsrvd/tls_init.c:283
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "nu se poate crea contextul TLS: %s"
+
+#: logsrvd/tls_init.c:290
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "nu se poate stabili versiunea de protocol minimă la TLS 1.2: %s"
+
+# R-GC, scrie:
+# este posibil ca traducerea corectă a acestui
+# mesaj, să fie:
+# «time of day» → «orele din zi» → «orarul zilei», deci:
+# „nu se poate obține orarul zilei”
+# ***
+# Opinii/Idei?
+# ===
+# după revizuirea fișierului, DȘ spune:
+# «→ eu cred că este corect traducerea curentă cu „ora actuală”; „orele
+# din zi” nu prea are sens iar „orarul zilei” ar fi „the daily schedule”»
+# ===
+# Ok, rămîne așa cum este
+#: plugins/sudoers/audit.c:272 plugins/sudoers/audit.c:452
+#: plugins/sudoers/log_client.c:962 plugins/sudoers/log_client.c:1011
+#: plugins/sudoers/log_client.c:1060 plugins/sudoers/log_client.c:1185
+#: plugins/sudoers/logging.c:614 plugins/sudoers/logging.c:732
+#: plugins/sudoers/logging.c:859 plugins/sudoers/logging.c:1031
+#: plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr "nu se poate obține ora actuală"
+
+#: plugins/sudoers/auth/aix_auth.c:282
+#, c-format
+msgid "unable to change password for %s"
+msgstr "nu se poate schimba parola pentru %s"
+
+#: plugins/sudoers/auth/bsdauth.c:78
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "nu se poate obține clasa de autentificare pentru utilizatorul %s"
+
+#: plugins/sudoers/auth/bsdauth.c:85
+msgid "invalid authentication type"
+msgstr "tip de autentificare nevalid"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to begin BSD authentication"
+msgstr "nu se poate începe autentificarea BSD"
+
+#: plugins/sudoers/auth/bsdauth.c:97
+msgid "unable to initialize BSD authentication"
+msgstr "nu se poate inițializa autentificarea BSD"
+
+#: plugins/sudoers/auth/bsdauth.c:191
+msgid "your account has expired"
+msgstr "contul a expirat"
+
+#: plugins/sudoers/auth/bsdauth.c:193
+msgid "approval failed"
+msgstr "aprobarea a eșuat"
+
+#: plugins/sudoers/auth/fwtk.c:62
+msgid "unable to read fwtk config"
+msgstr "nu se poate citi configurarea fwtk"
+
+#: plugins/sudoers/auth/fwtk.c:67
+msgid "unable to connect to authentication server"
+msgstr "nu se poate conecta la serverul de autentificare"
+
+#: plugins/sudoers/auth/fwtk.c:73 plugins/sudoers/auth/fwtk.c:99
+#: plugins/sudoers/auth/fwtk.c:131
+msgid "lost connection to authentication server"
+msgstr "s-a pierdut conexiunea la serverul de autentificare"
+
+#: plugins/sudoers/auth/fwtk.c:77
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"eroare a serverului de autentificare:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:116
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: nu se poate converti identitatea gazdei în șir („%s”): %s"
+
+#: plugins/sudoers/auth/kerb5.c:166
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: nu se poate analiza „%s”: %s"
+
+#: plugins/sudoers/auth/kerb5.c:175
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: nu s-a putut determina memoria tampon de certificare: %s"
+
+#: plugins/sudoers/auth/kerb5.c:226
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: nu se pot aloca opțiunile: %s"
+
+#: plugins/sudoers/auth/kerb5.c:241
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: nu se pot obține certificările: %s"
+
+#: plugins/sudoers/auth/kerb5.c:254
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: nu se poate inițializa memoria tampon de certificare: %s"
+
+#: plugins/sudoers/auth/kerb5.c:257
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: nu se poate stoca certificarea în memoria tampon: %s"
+
+#: plugins/sudoers/auth/kerb5.c:322
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: nu se poate obține identitatea kerberos a gazdei: %s"
+
+#: plugins/sudoers/auth/kerb5.c:336
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: Nu se poate verifica TGT! Posibil atac!: %s"
+
+#: plugins/sudoers/auth/pam.c:233
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "nu se poate inițializa PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:349
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Eroare de autentificare PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:369
+msgid "account validation failure, is your account locked?"
+msgstr "eșec la validarea contului, este contul blocat?"
+
+#: plugins/sudoers/auth/pam.c:380
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Contul sau parola au expirat, restabiliți parola și încercați din nou"
+
+#: plugins/sudoers/auth/pam.c:387
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "nu se poate schimba parola expirată: %s"
+
+#: plugins/sudoers/auth/pam.c:398
+msgid "Password expired, contact your system administrator"
+msgstr "Parolă expirată, contactați administratorul de sistem"
+
+#: plugins/sudoers/auth/pam.c:403
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Contul este expirat sau configurării PAM îi lipsește o secțiune „account” pentru «sudo», contactați administratorul de sistem"
+
+#: plugins/sudoers/auth/pam.c:411 plugins/sudoers/auth/pam.c:416
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "Eroare de gestionare a contului PAM: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:100 plugins/sudoers/visudo.c:266
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "nu existați în baza de date %s"
+
+#: plugins/sudoers/auth/securid5.c:76
+msgid "failed to initialise the ACE API library"
+msgstr "nu s-a putut inițializa biblioteca API ACE"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "unable to contact the SecurID server"
+msgstr "nu se poate contacta serverul SecurID"
+
+#: plugins/sudoers/auth/securid5.c:117
+msgid "User ID locked for SecurID Authentication"
+msgstr "ID-ul utilizatorului blocat pentru autentificarea SecurID"
+
+#: plugins/sudoers/auth/securid5.c:121 plugins/sudoers/auth/securid5.c:174
+msgid "invalid username length for SecurID"
+msgstr "lungime de nume de utilizator nevalidă pentru SecurID"
+
+#: plugins/sudoers/auth/securid5.c:125 plugins/sudoers/auth/securid5.c:179
+msgid "invalid Authentication Handle for SecurID"
+msgstr "gestionar de autentificare (Authentication Handle) nevalid pentru SecurID"
+
+#: plugins/sudoers/auth/securid5.c:129
+msgid "SecurID communication failed"
+msgstr "Comunicarea SecurID a eșuat"
+
+#: plugins/sudoers/auth/securid5.c:133 plugins/sudoers/auth/securid5.c:222
+msgid "unknown SecurID error"
+msgstr "eroare de SecurID necunoscută"
+
+#: plugins/sudoers/auth/securid5.c:169
+msgid "invalid passcode length for SecurID"
+msgstr "lungime de cod de parolă nevalidă pentru SecurID"
+
+#: plugins/sudoers/auth/sia.c:72 plugins/sudoers/auth/sia.c:130
+msgid "unable to initialize SIA session"
+msgstr "nu se poate inițializa sesiunea SIA"
+
+#: plugins/sudoers/auth/sudo_auth.c:141
+msgid "invalid authentication methods"
+msgstr "metode de autentificare nevalide"
+
+#: plugins/sudoers/auth/sudo_auth.c:143
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Metode de autentificare nevalide compilate în «sudo»! Nu se pot amesteca autentificările autonome și neautonome."
+
+#: plugins/sudoers/auth/sudo_auth.c:296 plugins/sudoers/auth/sudo_auth.c:359
+msgid "no authentication methods"
+msgstr "nu există metode de autentificare"
+
+#: plugins/sudoers/auth/sudo_auth.c:298
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Nu există metode de autentificare compilate în «sudo»! Dacă doriți să opriți autentificarea, utilizați opțiunea de configurare „--disable-authentication”."
+
+#: plugins/sudoers/auth/sudo_auth.c:361
+msgid "Unable to initialize authentication methods."
+msgstr "Nu se pot inițializa metodele de autentificare."
+
+#: plugins/sudoers/auth/sudo_auth.c:551
+msgid "Authentication methods:"
+msgstr "Metode de autentificare:"
+
+#: plugins/sudoers/bsm_audit.c:122 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "Nu s-a putut determina condiția de auditare"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:278
+msgid "unable to commit audit record"
+msgstr "nu se poate consemna înregistrarea de auditare"
+
+#: plugins/sudoers/check.c:63 plugins/sudoers/check.c:74
+#: plugins/sudoers/lookup.c:79 plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "uid necunoscut %u"
+
+#: plugins/sudoers/check.c:277
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "eroare la citirea fișierului de instrucțiuni %s"
+
+#: plugins/sudoers/check.c:280
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "se ignoră fișierul de instrucțiuni %s: nu este un fișier obișnuit"
+
+#: plugins/sudoers/check.c:293
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Avem încredere că ați primit instrucțiunile de utilizare obișnuite de\n"
+"la administratorul de sistem local. De obicei se reduce la aceste trei\n"
+"lucruri:\n"
+"\n"
+" 1. Respectă intimitatea celorlalți.\n"
+" 2. Gândește înainte de a tasta.\n"
+" 3. Cu o mare putere vine o mare responsabilitate.\n"
+"\n"
+
+#: plugins/sudoers/check.c:301
+msgid ""
+"For security reasons, the password you type will not be visible.\n"
+"\n"
+msgstr ""
+"Din motive de securitate, parola pe care o introduceți nu va fi vizibilă.n\n"
+"\n"
+
+#: plugins/sudoers/check_aliases.c:93
+#, c-format
+msgid "cycle in %s \"%s\""
+msgstr "ciclu în %s „%s”"
+
+#: plugins/sudoers/check_aliases.c:96
+#, c-format
+msgid "%s \"%s\" referenced but not defined"
+msgstr "%s „%s” menționat, dar nu definit"
+
+#: plugins/sudoers/cvtsudoers.c:211
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "incrementarea de ordine: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:231
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "ordinea de pornire: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:242
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "completarea de ordine: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:252 plugins/sudoers/visudo.c:183
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s versiune de gramatică %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:282 plugins/sudoers/testsudoers.c:162
+#, c-format
+msgid "unsupported input format %s"
+msgstr "format de intrare nesuportat %s"
+
+#: plugins/sudoers/cvtsudoers.c:300
+#, c-format
+msgid "unsupported output format %s"
+msgstr "format de ieșire nesuportat %s"
+
+#: plugins/sudoers/cvtsudoers.c:392
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: fișierele de intrare și ieșire trebuie să fie diferite"
+
+#: plugins/sudoers/cvtsudoers.c:406 plugins/sudoers/sudoers.c:151
+#: plugins/sudoers/sudoers.c:209 plugins/sudoers/testsudoers.c:315
+#: plugins/sudoers/visudo.c:276 plugins/sudoers/visudo.c:666
+msgid "unable to initialize sudoers default values"
+msgstr "nu se poate inițializa valorile implicite ale lui „sudoers”"
+
+#: plugins/sudoers/cvtsudoers.c:533 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:612
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s: cuvânt cheie necunoscut %s"
+
+#: plugins/sudoers/cvtsudoers.c:658
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "tip de valori implicite nevalid: %s"
+
+#: plugins/sudoers/cvtsudoers.c:681
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "tip de suprimare nevalid: %s"
+
+#: plugins/sudoers/cvtsudoers.c:722 plugins/sudoers/cvtsudoers.c:738
+#, c-format
+msgid "invalid filter: %s"
+msgstr "filtru nevalid: %s"
+
+#: plugins/sudoers/cvtsudoers.c:783 plugins/sudoers/visudo.c:1000
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "nu s-a putut analiza fișierul %s, eroare necunoscută"
+
+#: plugins/sudoers/cvtsudoers.c:1508 plugins/sudoers/sudoreplay.c:1143
+#: plugins/sudoers/timestamp.c:353 plugins/sudoers/timestamp.c:356
+#, c-format
+msgid "unable to write to %s"
+msgstr "nu se poate scrie la %s"
+
+#: plugins/sudoers/cvtsudoers.c:1536
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s - convertește între formatele de fișier „sudoers”\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1538
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Opțiuni:\n"
+" -b, --base=dn baza DN pentru interogări LDAP «sudo»\n"
+" -c, --config=fișier_conf ruta către fișierul de configurare\n"
+" -d, --defaults=tip_def convertește valorile implicite doar pentru tipurile specificate\n"
+" -e, --expand-aliases extinde numele de alias la conversie\n"
+" -f, --output-format=format stabilește formatul de ieșire: JSON, LDIF sau „sudoers”\n"
+" -i, --input-format=format stabilește formatul de intrare: LDIF sau „sudoers”\n"
+" -I, --increment=num cantitate cu care se mărește fiecare sudoOrder\n"
+" -h, --help afișează mesajul de ajutor și iese\n"
+" -m, --match=filtru convertește doar intrările care se potrivesc cu filtrul\n"
+" -M, --match-local filtrul de potrivire utilizează baze de date cu parole și grupuri\n"
+" -o, --output=fișier_ieșire scrie „sudoers” convertit, la fișier_ieșire\n"
+" -O, --order-start=num punctul de pornire pentru primul sudoOrder\n"
+" -p, --prune-matches elimină utilizatori, grupuri și gazde care nu se potrivesc\n"
+" -P, --padding=num completarea de bază pentru incrementarea sudoOrder\n"
+" -s, --suppress=secțiuni suprimă ieșirea anumitor secțiuni\n"
+" -V, --version afișează informația versiunii și iese"
+
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:245 plugins/sudoers/cvtsudoers_ldif.c:252
+#: plugins/sudoers/cvtsudoers_ldif.c:594 plugins/sudoers/env.c:340
+#: plugins/sudoers/env.c:347 plugins/sudoers/env.c:458
+#: plugins/sudoers/ldap.c:511 plugins/sudoers/ldap.c:629
+#: plugins/sudoers/ldap.c:1003 plugins/sudoers/ldap_conf.c:219
+#: plugins/sudoers/ldap_conf.c:310 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:93 plugins/sudoers/logging.c:479
+#: plugins/sudoers/policy.c:828 plugins/sudoers/policy.c:840
+#: plugins/sudoers/prompt.c:169 plugins/sudoers/serialize_list.c:62
+#: plugins/sudoers/serialize_list.c:71 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/sudoreplay.c:1340 plugins/sudoers/sudoreplay.c:1346
+#: plugins/sudoers/sudoreplay.c:1352 plugins/sudoers/testsudoers.c:306
+#: plugins/sudoers/toke_util.c:217 toke.l:995 toke.l:1277
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "eroare internă, depășire de %s"
+
+#: plugins/sudoers/cvtsudoers_csv.c:454 plugins/sudoers/cvtsudoers_csv.c:468
+#: plugins/sudoers/cvtsudoers_json.c:661 plugins/sudoers/cvtsudoers_json.c:676
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:362
+#: plugins/sudoers/ldap.c:495
+msgid "unable to get GMT time"
+msgstr "nu se poate obține ora GMT"
+
+#: plugins/sudoers/cvtsudoers_csv.c:459 plugins/sudoers/cvtsudoers_csv.c:473
+#: plugins/sudoers/cvtsudoers_json.c:666 plugins/sudoers/cvtsudoers_json.c:681
+#: plugins/sudoers/cvtsudoers_ldif.c:354 plugins/sudoers/cvtsudoers_ldif.c:367
+#: plugins/sudoers/ldap.c:503
+msgid "unable to format timestamp"
+msgstr "nu se poate formata marcajul de timp"
+
+#: plugins/sudoers/cvtsudoers_json.c:481 plugins/sudoers/cvtsudoers_json.c:516
+#: plugins/sudoers/cvtsudoers_json.c:732
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: intrare de valori implicite necunoscută „%s”"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:663
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "prea multe intrări „sudoers”, maxim %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:706
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "variabila de mediu $SUDOERS_BASE nu este stabilită și opțiunea „-b” nu a fost specificată."
+
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, c-format
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr "%s:%d:%d: se convertește lista de gazde în ALL"
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr "nu se poate găsi alias %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, c-format
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr "%s:%d:%d: redenumire a alias %s în %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr "%s:%d:%d: se elimină alias duplicat %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr "%s:%d:%d: intrare a valorilor Defaults „%s” în conflict cu cea specificată de gazdă în %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, c-format
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr "%s:%d:%d: a făcut ca Defaults „%s” să fie specific gazdei %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr "%s:%d:%d: nu se poate face ca Defaults „%s” să fie specific gazdei"
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr "%s:%d:%d: se elimină valorile Defaults „%s” suprascrise de intrările ulterioare"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1088
+#, c-format
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr "%s:%d:%d: se îmbină specificațiile utilizatorului în %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1182
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr "%s:%d:%d: se elimină specificația utilizatorului suprascrisă de intrările ulterioare"
+
+#: plugins/sudoers/def_data.c:56
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Facilitatea syslog dacă «syslog» este utilizat pentru înregistrarea evenimentelor: %s"
+
+#: plugins/sudoers/def_data.c:60
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Prioritatea syslog de utilizat când utilizatorul se autentifică cu succes: %s"
+
+#: plugins/sudoers/def_data.c:64
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Prioritatea syslog de utilizat când utilizatorul nu se autentifică cu succes: %s"
+
+#: plugins/sudoers/def_data.c:68
+msgid "Put OTP prompt on its own line"
+msgstr "Plasează prompterul OTP pe propria linie"
+
+#: plugins/sudoers/def_data.c:72
+msgid "Ignore '.' in $PATH"
+msgstr "Ignoră „.” în $PATH"
+
+#: plugins/sudoers/def_data.c:76
+msgid "Always send mail when sudo is run"
+msgstr "Trimite întotdeauna mail când «sudo» este rulat"
+
+#: plugins/sudoers/def_data.c:80
+msgid "Send mail if user authentication fails"
+msgstr "Trimite mail dacă autentificarea eșuează"
+
+#: plugins/sudoers/def_data.c:84
+msgid "Send mail if the user is not in sudoers"
+msgstr "Trimite mail dacă utilizatorul nu este în „sudoers”"
+
+#: plugins/sudoers/def_data.c:88
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Trimite mail dacă utilizatorul nu este în „sudoers” pentru această gazdă"
+
+#: plugins/sudoers/def_data.c:92
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Trimite mail dacă utilizatorul nu are voie să ruleze o comandă"
+
+#: plugins/sudoers/def_data.c:96
+msgid "Send mail if the user tries to run a command"
+msgstr "Trimite mail dacă utilizatorul încearcă să ruleze o comandă"
+
+#: plugins/sudoers/def_data.c:100
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Utilizează un marcaj de timp separat pentru fiecare combinație utilizator/tty"
+
+#: plugins/sudoers/def_data.c:104
+msgid "Lecture user the first time they run sudo"
+msgstr "Ține o prelegere utilizatorului când rulează pentru prima dată «sudo»"
+
+#: plugins/sudoers/def_data.c:108
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Fișierul care conține instrucțiunile de utilizare ale «sudo»: %s"
+
+#: plugins/sudoers/def_data.c:112
+msgid "Require users to authenticate by default"
+msgstr "Cere utilizatorilor să se autentifice ca implicit"
+
+#: plugins/sudoers/def_data.c:116
+msgid "Root may run sudo"
+msgstr "Root poate rula «sudo»"
+
+#: plugins/sudoers/def_data.c:120
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Înregistrează numele gazdei în fișierul de jurnal (ne-syslog)"
+
+#: plugins/sudoers/def_data.c:124
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Înregistrează anul în fișierul de jurnal (ne-syslog)"
+
+#: plugins/sudoers/def_data.c:128
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Dacă «sudo» este invocat fără argumente, pornește un shell"
+
+#: plugins/sudoers/def_data.c:132
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Stabilește $HOME pentru utilizatorul vizat când se pornește un shell cu opțiunea „-s”"
+
+#: plugins/sudoers/def_data.c:136
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Totdeauna stabilește $HOME la directorul personal al utilizatorului vizat"
+
+#: plugins/sudoers/def_data.c:140
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Permite colectarea de informații pentru a oferi mesaje de eroare utile"
+
+#: plugins/sudoers/def_data.c:144
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Necesită nume de gazdă calificate complet în fișierul „sudoers”"
+
+#: plugins/sudoers/def_data.c:148
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Insultă utilizatorul când acesta introduce o parolă incorectă"
+
+#: plugins/sudoers/def_data.c:152
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Permite utilizatorului să ruleze «sudo» doar dacă are un tty"
+
+#: plugins/sudoers/def_data.c:156
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "«Visudo» va respecta variabila de mediu $EDITOR"
+
+#: plugins/sudoers/def_data.c:160
+msgid "Prompt for root's password, not the users's"
+msgstr "Solicită parola pentru root, nu a utilizatorului"
+
+#: plugins/sudoers/def_data.c:164
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Solicită parola pentru utilizatorul runas_default, nu a utilizatorului"
+
+#: plugins/sudoers/def_data.c:168
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Solicită parola pentru utilizatorul vizat, nu a utilizatorului"
+
+#: plugins/sudoers/def_data.c:172
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Aplică valorile implicite în clasa de autentificare a utilizatorului vizat dacă aceasta există"
+
+#: plugins/sudoers/def_data.c:176
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Stabilește variabilele de mediu $LOGNAME și $USER"
+
+#: plugins/sudoers/def_data.c:180
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Stabilește pentru utilizatorul vizat doar uid-ul efectiv, nu uid-ul real"
+
+#: plugins/sudoers/def_data.c:184
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Nu inițializează vectorul de grup la cel al utilizatorului vizat"
+
+#: plugins/sudoers/def_data.c:188
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Lungimea la care să se încadreze liniile fișierului de jurnal (0 pentru fără încadrare): %u"
+
+#: plugins/sudoers/def_data.c:192
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Marcajul de timp al autentificării, expiră în: %.1f minute"
+
+#: plugins/sudoers/def_data.c:196
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Timpul pentru solicitarea parolei, expiră în: %.1f minute"
+
+#: plugins/sudoers/def_data.c:200
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Numărul de încercări pentru a introduce o parolă: %u"
+
+#: plugins/sudoers/def_data.c:204
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Valoarea necesară umask, sau 0777 pentru utilizatorul: 0%o"
+
+#: plugins/sudoers/def_data.c:208
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Ruta la fișierul de jurnal: %s"
+
+#: plugins/sudoers/def_data.c:212
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Ruta la programul de poștă electronică: %s"
+
+#: plugins/sudoers/def_data.c:216
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Opțiuni pentru programul de mail: %s"
+
+#: plugins/sudoers/def_data.c:220
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Adresa la care să se trimită mailul: %s"
+
+#: plugins/sudoers/def_data.c:224
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Adresa de la care să se trimită mailul: %s"
+
+#: plugins/sudoers/def_data.c:228
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Linia de subiect pentru mesajele de mail: %s"
+
+#: plugins/sudoers/def_data.c:232
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Mesajul de avertizare de parolă incorectă: %s"
+
+#: plugins/sudoers/def_data.c:236
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Ruta către directorul de stare a instrucțiunilor de utilizare a «sudo»(utilizatorul, le-a primit sau nu): %s"
+
+#: plugins/sudoers/def_data.c:240
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Ruta către directorul ce conține marcajele de timp ale autentificării: %s"
+
+#: plugins/sudoers/def_data.c:244
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Proprietarul directorului ce conține marcajele de timp ale autentificării: %s"
+
+#: plugins/sudoers/def_data.c:248
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Utilizatorii din acest grup sunt scutiți de la cerințele privind parola și PATH: %s"
+
+#: plugins/sudoers/def_data.c:252
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Solicitarea implicită de parolă: %s"
+
+#: plugins/sudoers/def_data.c:256
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Dacă este definită, solicitarea de parolă a «sudo», o va înlocui pe cea de sistem în toate cazurile."
+
+#: plugins/sudoers/def_data.c:260
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Utilizatorul implicit cu care să se ruleze comenzile: %s"
+
+#: plugins/sudoers/def_data.c:264
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Valoarea cu care să se suprascrie $PATH utilizatorului: %s"
+
+#: plugins/sudoers/def_data.c:268
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Ruta către editorul ce va fi utilizat de către «visudo»: %s"
+
+#: plugins/sudoers/def_data.c:272
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Când să se ceară o parolă pentru pseudocomanda „list”: %s"
+
+#: plugins/sudoers/def_data.c:276
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Când să se ceară o parolă pentru pseudocomanda „verify”: %s"
+
+#: plugins/sudoers/def_data.c:280
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "Preîncarcă biblioteca sudo_noexec care înlocuiește funcțiile exec"
+
+#: plugins/sudoers/def_data.c:284
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Dacă directorul LDAP este activ, se ignoră fișierul „sudoers” local"
+
+#: plugins/sudoers/def_data.c:288
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Descriptorii de fișier >= %d se vor închide înainte de executarea unei comenzi"
+
+#: plugins/sudoers/def_data.c:292
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "Dacă este definită, utilizatorii pot să suprascrie valoarea lui „closeform” cu opțiunea „-C”"
+
+#: plugins/sudoers/def_data.c:296
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Permite utilizatorilor să stabilească variabile de mediu arbitrare"
+
+#: plugins/sudoers/def_data.c:300
+msgid "Reset the environment to a default set of variables"
+msgstr "Restabilește mediul la un set de variabile implicite"
+
+#: plugins/sudoers/def_data.c:304
+msgid "Environment variables to check for safety:"
+msgstr "Variabile de mediu care trebuie validate pentru a asigura securitatea:"
+
+#: plugins/sudoers/def_data.c:308
+msgid "Environment variables to remove:"
+msgstr "Variabile de mediu de eliminat:"
+
+#: plugins/sudoers/def_data.c:312
+msgid "Environment variables to preserve:"
+msgstr "Variabile de mediu de păstrat:"
+
+#: plugins/sudoers/def_data.c:316
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "Regula SELinux de utilizat în contextul de securitate nou: %s"
+
+#: plugins/sudoers/def_data.c:320
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "Tipul de executare a SELinux („default” sau „mlt”), ce va fi utilizat în contextul de securitate nou: %s"
+
+#: plugins/sudoers/def_data.c:324
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Ruta către fișierul de mediu, propriu al «sudo»: %s"
+
+#: plugins/sudoers/def_data.c:328
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Ruta către fișierul restricționat de mediu, propriu al «sudo»: %s"
+
+#: plugins/sudoers/def_data.c:332
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Localizarea ce va fi utilizată în timpul analizării lui „sudoers”: %s"
+
+#: plugins/sudoers/def_data.c:336
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Permite lui «sudo» să solicite o parolă chiar dacă aceasta va fi vizibilă"
+
+#: plugins/sudoers/def_data.c:340
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Afișează un control vizual la solicitarea parolei, când aceasta este introdusă de către utilizator"
+
+#: plugins/sudoers/def_data.c:344
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Utilizează expanderea rapidă a numelor de fișiere, care este mai puțin fiabilă, dar nu necesită acces la sistemul de fișiere"
+
+#: plugins/sudoers/def_data.c:348
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "Umask(masca de Unix) specificată în „sudoers”, o va înlocui pe cea a utilizatorului, chiar dacă este mai permisivă"
+
+#: plugins/sudoers/def_data.c:352
+msgid "Log user's input for the command being run"
+msgstr "Înregistrează în jurnal intrarea utilizatorului pentru comanda care se execută"
+
+#: plugins/sudoers/def_data.c:356
+msgid "Log the command's standard input if not connected to a terminal"
+msgstr "Înregistrează în jurnal intrarea standard a comenzii dacă nu este conectată la un terminal"
+
+#: plugins/sudoers/def_data.c:360
+msgid "Log the user's terminal input for the command being run"
+msgstr "Înregistrează în jurnal intrarea terminalului utilizatorului pentru comanda care se execută"
+
+#: plugins/sudoers/def_data.c:364
+msgid "Log the output of the command being run"
+msgstr "Înregistrează în jurnal ieșirea comenzii care se execută"
+
+#: plugins/sudoers/def_data.c:368
+msgid "Log the command's standard output if not connected to a terminal"
+msgstr "Înregistrează în jurnal ieșirea standard a comenzii dacă nu este conectată la un terminal"
+
+#: plugins/sudoers/def_data.c:372
+msgid "Log the command's standard error if not connected to a terminal"
+msgstr "Înregistrează în jurnal eroarea standard a comenzii dacă nu este conectată la un terminal"
+
+#: plugins/sudoers/def_data.c:376
+msgid "Log the terminal output of the command being run"
+msgstr "Înregistrează în jurnal ieșirea terminalului comenzii care se execută"
+
+#: plugins/sudoers/def_data.c:380
+msgid "Compress I/O logs using zlib"
+msgstr "Comprimă înregistrările din jurnal de In/Ieș utilizând «zlib»"
+
+#: plugins/sudoers/def_data.c:384
+msgid "Always run commands in a pseudo-tty"
+msgstr "Execută întotdeauna comenzile într-un pseudo-tty"
+
+#: plugins/sudoers/def_data.c:388
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Modul pentru suport de grup non-Unix: %s"
+
+#: plugins/sudoers/def_data.c:392
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Directorul în care se stochează informațiile returnate de operațiile de intrare/ieșire: %s"
+
+#: plugins/sudoers/def_data.c:396
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Fișierul în care se stochează informațiile returnate de operațiile de intrare/ieșire: %s"
+
+#: plugins/sudoers/def_data.c:400
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Adaugă o intrare la fișierul „utmp/utmpx” când se alocă un pty"
+
+#: plugins/sudoers/def_data.c:404
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Stabilește utilizatorul în utmp la utilizatorul „run as”, nu la utilizatorul care invocă"
+
+#: plugins/sudoers/def_data.c:408
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Setul de privilegii permise: %s"
+
+#: plugins/sudoers/def_data.c:412
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Setul de privilegii limită: %s"
+
+#: plugins/sudoers/def_data.c:416
+msgid "Run commands on a pty in the background"
+msgstr "Rulează comenzile pe un pty în fundal"
+
+#: plugins/sudoers/def_data.c:420
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "Numele serviciului PAM de utilizat: %s"
+
+#: plugins/sudoers/def_data.c:424
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "Numele serviciului PAM de utilizat pentru shell-urile de autentificare: %s"
+
+#: plugins/sudoers/def_data.c:428
+#, c-format
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr "Numele serviciului PAM de utilizat atunci când «sudo» este rulat cu opțiunea „-A”: %s"
+
+#: plugins/sudoers/def_data.c:432
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Încearcă să stabilească certificări PAM pentru utilizatorul vizat"
+
+#: plugins/sudoers/def_data.c:436
+msgid "Create a new PAM session for the command to run in"
+msgstr "Creează o nouă sesiune PAM pentru a rula comanda în ea"
+
+#: plugins/sudoers/def_data.c:440
+msgid "Perform PAM account validation management"
+msgstr "Realizează gestionarea validării contului PAM"
+
+#: plugins/sudoers/def_data.c:444
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "Numărul maxim de secvență al jurnalului de In/Ieș: %s"
+
+#: plugins/sudoers/def_data.c:448
+msgid "Enable sudoers netgroup support"
+msgstr "Activează suportul de „netgroup” (grup de rețea) „sudoers”"
+
+#: plugins/sudoers/def_data.c:452
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Verifică directoarele părinte pentru capacitatea de scriere când se editează fișiere cu «sudoedit»"
+
+#: plugins/sudoers/def_data.c:456
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Urmărește legăturile simbolice când se editează fișierele cu «sudoedit»"
+
+#: plugins/sudoers/def_data.c:460
+msgid "Query the group plugin for unknown system groups"
+msgstr "Interoghează modulul grupului pentru grupuri de sistem necunoscute"
+
+# R-GC, scrie:
+# și, curiozitatea, omoară pisica ! 😈️
+# și ce, mama ..., înseamnă «tuple» ?
+# ***
+# citat din pagina:
+# https://en.wikipedia.org/wiki/Tuple
+# „The term originated as an abstraction of
+# the sequence: single, couple/double, triple,
+# quadruple, quintuple, sextuple, septuple,
+# octuple, ..., n‑tuple, ..., where the prefixes
+# are taken from the Latin names of the
+# numerals. The unique 0-tuple is called the
+# null tuple or empty tuple. A 1‑tuple is called
+# a single (or singleton), a 2‑tuple is called an
+# ordered pair or couple, and a 3‑tuple is
+# called a triple (or triplet).”
+# ===
+# Morala, pentru „trăznaia” unuia, se scrie o
+# pagină întreagă(destul de vastă) în Wikipedia.
+# Și „bagă în boală”, multă lume „luminată”! 😇️
+#: plugins/sudoers/def_data.c:464
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Potrivește „netgroups” (grupurile de rețea) pe baza întregului triplet: utilizator, gazdă și domeniu"
+
+#: plugins/sudoers/def_data.c:468
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Permite executarea comenzilor chiar dacă «sudo» nu poate să scrie în jurnalul auditare"
+
+#: plugins/sudoers/def_data.c:472
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Permite executarea comenzilor chiar dacă «sudo» nu poate să scrie în jurnalul de In/Ieș"
+
+#: plugins/sudoers/def_data.c:476
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Permite executarea comenzilor chiar dacă «sudo» nu poate să scrie în fișierul de jurnal"
+
+# R-GC, scrie:
+# cred că o traducere mai bună a acestui
+# mesaj, ar fi:
+# „Identifică grupurile din „sudoers” și face potrivirea după ID-ul grupului, nu după nume”
+# ***
+# Opinii/Idei?
+#: plugins/sudoers/def_data.c:480
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Rezolvă grupurile în „sudoers” și face potrivirea după ID-ul grupului, nu după nume"
+
+#: plugins/sudoers/def_data.c:484
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Intrările în jurnal mai mari decât această valoare vor fi împărțite în mai multe mesaje syslog: %u"
+
+# R-GC, scrie:
+# am înlocuit vechea traducere,
+# a acestui mesaj:
+#
+# „Utilizator care va deține fișierele istoricului I/O: %s”
+# cu cea prezentă, pentru că:
+#
+# 1. own = proprietar, stăpîn
+#
+# 2. proprietarul, deține ceva, avînd drepturi
+# depline asupra acestui lucru, bun;
+# pe cînd un chiriaș, un arendaș cu toate că
+# are drepturi asupra acestui lucru, bun;
+# drepturile acestea sunt îngrădite de
+# contractul avut cu proprietarul de drept,
+# cu arendatorul.
+#
+# 3. cu toate că fișierele de înregistrare a
+# diverselor informații despre lucrurile care
+# se întîmplă, desfășoară la un moment dat
+# în sistem, au un în general, un marcaj de
+# timp; nu înseamnă că acestea sunt un
+# istoric al acestor informații...
+# (marcajul de timp, este decît
+# „o plus valoare” a acestor informații)
+#: plugins/sudoers/def_data.c:488
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Utilizatorul ce va fi proprietarul fișierelor jurnalului de In/Ieș: %s"
+
+#: plugins/sudoers/def_data.c:492
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Grupul ce va fi proprietarul fișierelor jurnalului de In/Ieș: %s"
+
+#: plugins/sudoers/def_data.c:496
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Modul de acces la fișier, utilizat pentru fișierele jurnalului de In/Ieș: 0%o"
+
+#: plugins/sudoers/def_data.c:500
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Execută comenzile după descriptorul fișierului în loc de, după ruta de acces: %s"
+
+#: plugins/sudoers/def_data.c:504
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Ignoră intrările Defaults necunoscute din „sudoers” în loc de-a genera un avertisment"
+
+#: plugins/sudoers/def_data.c:508
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Timpul în secunde după care comanda va fi terminată: %u"
+
+#: plugins/sudoers/def_data.c:512
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Permite utilizatorul să specifice o limită de timp, de la linia de comandă"
+
+#: plugins/sudoers/def_data.c:516
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Transferă imediat datele jurnalului de In/Ieș pe disc, în loc să le stocheze în memoria tampon"
+
+#: plugins/sudoers/def_data.c:520
+msgid "Include the process ID when logging via syslog"
+msgstr "Include ID-ul procesului când se înregistrează via syslog"
+
+#: plugins/sudoers/def_data.c:524
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Tipul de înregistrare a marcajului de timp a autentificării: %s"
+
+#: plugins/sudoers/def_data.c:528
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Mesaj de autentificare eșuată: %s"
+
+#: plugins/sudoers/def_data.c:532
+msgid "Ignore case when matching user names"
+msgstr "Ignoră diferența dintre majusculele/minuscule când se caută după numele de utilizator"
+
+#: plugins/sudoers/def_data.c:536
+msgid "Ignore case when matching group names"
+msgstr "Ignoră diferența dintre majusculele/minuscule când se caută după numele de grup"
+
+#: plugins/sudoers/def_data.c:540
+msgid "Log when a command is allowed by sudoers"
+msgstr "Înregistrează când o comandă este permisă de „sudoers”"
+
+#: plugins/sudoers/def_data.c:544
+msgid "Log when a command is denied by sudoers"
+msgstr "Înregistrează când o comandă este respinsă de „sudoers”"
+
+#: plugins/sudoers/def_data.c:548
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "Server(e) de înregistrare a jurnalului «sudo», la care se conectează cu portul opțional"
+
+#: plugins/sudoers/def_data.c:552
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Limita de timp a serverului de înregistrare a jurnalului «sudo», în secunde: %u"
+
+#: plugins/sudoers/def_data.c:556
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "Activează opțiunea de soclu SO_KEEPALIVE pe soclul conectat la serverul de înregistrare a jurnalului"
+
+#: plugins/sudoers/def_data.c:560
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "Ruta către fișierul pachet CA al serverului de auditare: %s"
+
+#: plugins/sudoers/def_data.c:564
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "Ruta către fișierul certificat „sudoers”: %s"
+
+#: plugins/sudoers/def_data.c:568
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "Ruta către fișierul cheie privată „sudoers”: %s"
+
+#: plugins/sudoers/def_data.c:572
+msgid "Verify that the log server's certificate is valid"
+msgstr "Verifică dacă certificatul serverului de înregistrare a jurnalului, este valid"
+
+#: plugins/sudoers/def_data.c:576
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "Permite utilizarea de ID de grup și/sau utilizator „run as” necunoscut"
+
+#: plugins/sudoers/def_data.c:580
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "Permite doar rularea de comenzi ca un utilizator cu un shell valid"
+
+#: plugins/sudoers/def_data.c:584
+msgid "Set the pam remote user to the user running sudo"
+msgstr "Stabilește utilizatorul de la distanță de pam, la utilizatorul care rulează «sudo»"
+
+#: plugins/sudoers/def_data.c:588
+msgid "Set the pam remote host to the local host name"
+msgstr "Stabilește gazda de la distanță de pam, la numele de gazdă local"
+
+#: plugins/sudoers/def_data.c:592
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "Directorul de lucru la care trebuie să se schimbe, înainte de a executa comanda: %s"
+
+#: plugins/sudoers/def_data.c:596
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "Directorul rădăcină la care trebuie să se schimbe, înainte de a executa comanda: %s"
+
+#: plugins/sudoers/def_data.c:600
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "Formatul jurnalelor de produs: %s"
+
+#: plugins/sudoers/def_data.c:604
+msgid "Enable SELinux RBAC support"
+msgstr "Activează suportul RBAC în SELinux"
+
+#: plugins/sudoers/def_data.c:608
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "Ruta către fișierul care este creat prima dată când «sudo» este rulat: %s"
+
+#: plugins/sudoers/def_data.c:612
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "Interceptează comenzile următoare, și le aplică restricțiile „sudoers”"
+
+#: plugins/sudoers/def_data.c:616
+msgid "Log sub-commands run by the original command"
+msgstr "Înregistrează în jurnal subcomenzile executate de comanda originală"
+
+#: plugins/sudoers/def_data.c:620
+msgid "Log the exit status of commands"
+msgstr "Înregistrează în jurnal starea de ieșire a comenzilor"
+
+#: plugins/sudoers/def_data.c:624
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr "Comenzile ulterioare dintr-o sesiune interceptată trebuie să fie autentificate"
+
+#: plugins/sudoers/def_data.c:628
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr "Permite unei comenzi interceptate să execute programe marcate setuid sau setgid"
+
+#: plugins/sudoers/def_data.c:632
+#, c-format
+msgid "The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr "Dimensiunea maximă la care spațiul de adrese al procesului poate crește (în octeți): %s"
+
+# R-GC, scrie:
+# traducerea acestui mesaj, este făcută în
+# baza ideilor ce le-am putut extrage din
+# pagina:
+# https://en.wikipedia.org/wiki/Core_dump
+# ***
+# citez, de aici:
+# „In computing, a core dump,[a] memory dump, crash dump, storage dump, system dump, or ABEND dump[1] consists of the recorded state of the working memory of a computer program at a specific time, generally when the program has crashed or otherwise terminated abnormally.”
+#: plugins/sudoers/def_data.c:636
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr "Fișierul de transferare a conținutului memoriei(core dump), pentru depanare, de cea mai mare dimensiune care poate fi creat (în octeți): %s"
+
+#: plugins/sudoers/def_data.c:640
+#, c-format
+msgid "The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr "Cantitatea maximă de timp CPU pe care o poate utiliza procesul (în secunde): %s"
+
+#: plugins/sudoers/def_data.c:644
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr "Dimensiunea maximă a segmentului de date pentru proces (în octeți): %s"
+
+#: plugins/sudoers/def_data.c:648
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr "Fișierul de cea mai mare dimensiune pe care procesul îl poate crea (în octeți): %s"
+
+#: plugins/sudoers/def_data.c:652
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr "Numărul maxim de blocări pe care procesul le poate stabili: %s"
+
+#: plugins/sudoers/def_data.c:656
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr "Dimensiunea maximă pe care procesul o poate bloca în memorie (în octeți): %s"
+
+#: plugins/sudoers/def_data.c:660
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr "Numărul maxim de fișiere pe care procesul le poate avea deschise: %s"
+
+#: plugins/sudoers/def_data.c:664
+#, c-format
+msgid "The maximum number of processes that the user may run simultaneously: %s"
+msgstr "Numărul maxim de procese pe care utilizatorul le poate rula simultan: %s"
+
+#: plugins/sudoers/def_data.c:668
+#, c-format
+msgid "The maximum size to which the process's resident set size may grow (in bytes): %s"
+msgstr "Dimensiunea maximă până la care poate crește dimensiunea setului rezident al procesului (în octeți): %s"
+
+#: plugins/sudoers/def_data.c:672
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr "Dimensiunea maximă până la care poate crește stiva procesului (în octeți): %s"
+
+#: plugins/sudoers/def_data.c:676
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr "Încercați să vă autentificați chiar și în modul non-interactiv"
+
+#: plugins/sudoers/def_data.c:680
+msgid "Store plaintext passwords in I/O log input"
+msgstr "Stochează parolele în formatul de text simplu în intrarea jurnalului de In/Ieș"
+
+#: plugins/sudoers/def_data.c:684
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr "Listă de expresii regulate de utilizat atunci când se potrivește o solicitare de parolă"
+
+#: plugins/sudoers/def_data.c:688
+#, c-format
+msgid "The mechanism used by the intercept and log_subcmds options: %s"
+msgstr "Mecanismul utilizat de opțiunile „intercept” și „log_subcmds”: %s"
+
+#: plugins/sudoers/def_data.c:692
+msgid "Attempt to verify the command and arguments after execution"
+msgstr "Încearcă să verifice comanda și argumentele după execuție"
+
+#: plugins/sudoers/def_data.c:696
+#, c-format
+msgid "AppArmor profile to use in the new security context: %s"
+msgstr "Profilul AppArmor de utilizat în noul context de securitate: %s"
+
+#: plugins/sudoers/defaults.c:207
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "intrare de implicite necunoscută „%s”"
+
+#: plugins/sudoers/defaults.c:251
+#, c-format
+msgid "no value specified for \"%s\""
+msgstr "nicio valoare specificată pentru „%s”"
+
+#: plugins/sudoers/defaults.c:260
+#, c-format
+msgid "invalid operator \"%c=\" for \"%s\""
+msgstr "operator nevalid „%c=\" pentru „%s”"
+
+#: plugins/sudoers/defaults.c:292
+#, c-format
+msgid "option \"%s\" does not take a value"
+msgstr "opțiunea „%s” nu primește o valoare"
+
+#: plugins/sudoers/defaults.c:319
+#, c-format
+msgid "invalid Defaults type 0x%x for option \"%s\""
+msgstr "tip de Defaults nevalid 0x%x pentru opțiunea „%s”"
+
+#: plugins/sudoers/defaults.c:326
+#, c-format
+msgid "value \"%s\" is invalid for option \"%s\""
+msgstr "valoarea „%s” nu este validă pentru opțiunea „%s”"
+
+#: plugins/sudoers/defaults.c:1176 plugins/sudoers/policy.c:213
+#: plugins/sudoers/policy.c:222
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr "numele rutei pentru „%s” este prea lung"
+
+#: plugins/sudoers/defaults.c:1182
+#, c-format
+msgid "values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "valorile pentru „%s” trebuie să înceapă cu un „/”, „~”, sau „*”"
+
+#: plugins/sudoers/defaults.c:1189
+#, c-format
+msgid "values for \"%s\" must start with a '/'"
+msgstr "valorile pentru „%s” trebuie să înceapă cu un caracter „/”"
+
+#: plugins/sudoers/display.c:160
+#, c-format
+msgid "LDAP Role: %s\n"
+msgstr "Regula LDAP: %s\n"
+
+#: plugins/sudoers/display.c:163
+#, c-format
+msgid "Sudoers entry: %s\n"
+msgstr "Intrare „sudoers”: %s\n"
+
+#: plugins/sudoers/display.c:166
+msgid " RunAsUsers: "
+msgstr " RuleazăCaUtilizatorii: "
+
+#: plugins/sudoers/display.c:181
+msgid " RunAsGroups: "
+msgstr " RuleazăCaGrupurile: "
+
+#: plugins/sudoers/display.c:191
+msgid " Options: "
+msgstr " Opțiuni: "
+
+#: plugins/sudoers/display.c:255
+msgid " Commands:\n"
+msgstr " Comenzi:\n"
+
+#: plugins/sudoers/display.c:478
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Se potrivesc intrările Defaults pentru %s pe %s:\n"
+
+#: plugins/sudoers/display.c:496
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Valori implicite specifice „Run_as” și comenzii pentru %s:\n"
+
+#: plugins/sudoers/display.c:514
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "Utilizatorul %s poate să ruleze următoarele comenzi pe %s:\n"
+
+#: plugins/sudoers/display.c:530
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Utilizatorului %s nu îi este permis să ruleze «sudo» pe %s.\n"
+
+#: plugins/sudoers/editor.c:180
+#, c-format
+msgid "ignoring editor: %.*s"
+msgstr "se ignoră editorul: %.*s"
+
+#: plugins/sudoers/editor.c:181
+msgid "editor arguments may not contain \"--\""
+msgstr "argumentele editorului nu pot să conțină „--”"
+
+#: plugins/sudoers/env.c:426
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: envp corupt, nepotrivire a lungimii"
+
+#: plugins/sudoers/env.c:1119
+msgid "unable to rebuild the environment"
+msgstr "nu se poate reconstrui mediul"
+
+#: plugins/sudoers/env.c:1199
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "nu aveți permisiunea de a stabili următoarele variabile de mediu: %s"
+
+#: plugins/sudoers/filedigest.c:50
+#, c-format
+msgid "unsupported digest type %u for %s"
+msgstr "tip de sumă de control neacceptat %u pentru %s"
+
+#: plugins/sudoers/filedigest.c:77
+#, c-format
+msgid "%s: read error"
+msgstr "%s: eroare de citire"
+
+#: plugins/sudoers/group_plugin.c:169 plugins/sudoers/sssd.c:578
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "nu se poate încărca %s: %s"
+
+#: plugins/sudoers/group_plugin.c:181
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "nu se poate găsi simbolul „group_plugin” în %s"
+
+#: plugins/sudoers/group_plugin.c:186
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: versiunea majoră a modului de grup %d, este incompatibilă, se aștepta %d"
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "nu se poate analiza adresa IP „%s”"
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "nu se poate analiza masca de rețea „%s”"
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Perechile adresă de IP locală și mască de rețea:\n"
+
+#: plugins/sudoers/iolog.c:694
+msgid "unable to update sequence file"
+msgstr "nu se poate actualiza fișierul de secvență"
+
+#: plugins/sudoers/iolog.c:728 plugins/sudoers/iolog.c:917
+#: plugins/sudoers/iolog.c:1080 plugins/sudoers/iolog.c:1087
+#: plugins/sudoers/iolog.c:1209 plugins/sudoers/iolog.c:1216
+#: plugins/sudoers/iolog.c:1316 plugins/sudoers/iolog.c:1323
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "nu se poate scrie în fișierul jurnal de In/Ieș: %s"
+
+#: plugins/sudoers/iolog.c:736
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "nu se poate crea %s/%s"
+
+#: plugins/sudoers/iolog.c:965
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: eroare internă, fișierul jurnal de In/Ieș pentru evenimentul %d nu este deschis"
+
+#: plugins/sudoers/iolog.c:1065 plugins/sudoers/iolog.c:1194
+#: plugins/sudoers/iolog.c:1300 plugins/sudoers/timestamp.c:897
+#: plugins/sudoers/timestamp.c:989 plugins/sudoers/visudo.c:555
+#: plugins/sudoers/visudo.c:561
+msgid "unable to read the clock"
+msgstr "nu se poate citi ceasul"
+
+#: plugins/sudoers/iolog.c:1292 plugins/sudoers/log_client.c:1203
+#: plugins/sudoers/log_client.c:1213 plugins/sudoers/log_client.c:1217
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: eroare internă, semnal nevalid %d"
+
+#: plugins/sudoers/ldap.c:154 plugins/sudoers/ldap_conf.c:289
+msgid "starttls not supported when using ldaps"
+msgstr "starttls nu este acceptat când se utilizează ldaps"
+
+#: plugins/sudoers/ldap.c:226
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "nu se poate inițializa certificatul SSL și baza de date a cheii: %s"
+
+#: plugins/sudoers/ldap.c:229
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "trebuie să stabiliți TLS_CERT în %s pentru a utiliza SSL"
+
+#: plugins/sudoers/ldap.c:1593
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "nu se poate inițializa LDAP: %s"
+
+#: plugins/sudoers/ldap.c:1630
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls specificat, dar bibliotecile LDAP nu acceptă ldap_start_tls_s() sau ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:1767 plugins/sudoers/parse_ldif.c:745
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "atribut sudoOrder nevalid: %s"
+
+#: plugins/sudoers/ldap_conf.c:197
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: portul este prea mare"
+
+#: plugins/sudoers/ldap_conf.c:258
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "tip de URI LDAP neacceptat: %s"
+
+#: plugins/sudoers/ldap_conf.c:285
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "nu se pot fuziona adrese URI, ldap și ldaps"
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "sudoOption duplicată: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "nu se poate converti sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "nu se poate deschide sistemul de auditare"
+
+#: plugins/sudoers/linux_audit.c:104
+msgid "unable to send audit message"
+msgstr "nu se poate trimite mesajul de auditare"
+
+#: plugins/sudoers/log_client.c:125 plugins/sudoers/log_client.c:412
+#: plugins/sudoers/log_client.c:1450 plugins/sudoers/log_client.c:2076
+msgid "error in event loop"
+msgstr "eroare în bucla de eveniment"
+
+#: plugins/sudoers/log_client.c:205
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "Crearea unui nou obiect SSL_CTX a eșuat: %s"
+
+#: plugins/sudoers/log_client.c:230
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "nu se poate încărca pachetul de autoritate de certificare %s"
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "nu se poate încărca certificatul %s"
+
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "unable to load private key %s"
+msgstr "nu se poate încărca cheia privată %s"
+
+#: plugins/sudoers/log_client.c:275
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "Nu se poate aloca obiectul ssl: %s"
+
+#: plugins/sudoers/log_client.c:364 plugins/sudoers/log_client.c:369
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "Conexiunea TLS la %s:%s a eșuat: %s"
+
+#: plugins/sudoers/log_client.c:545
+msgid "TLS initialization was unsuccessful"
+msgstr "Inițializarea TLS nu a reușit"
+
+#: plugins/sudoers/log_client.c:555
+msgid "TLS handshake was unsuccessful"
+msgstr "Negocierea TLS nu a reușit"
+
+#: plugins/sudoers/log_client.c:1221
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: eroare internă, stare de ieșire nevalidă %d"
+
+#: plugins/sudoers/log_client.c:1757 plugins/sudoers/log_client.c:1782
+msgid "lost connection to log server"
+msgstr "a fost pierdută conexiunea la serverul de înregistrare a jurnalului"
+
+#: plugins/sudoers/log_client.c:1859
+msgid "missing write buffer"
+msgstr "lipsește memoria tampon de scriere"
+
+#: plugins/sudoers/log_client.c:2015
+msgid "unable to connect to log server"
+msgstr "nu se poate conecta la serverul de înregistrare a jurnalului"
+
+#: plugins/sudoers/logging.c:295
+msgid "user NOT in sudoers"
+msgstr "utilizatorul NU este în „sudoers”"
+
+#: plugins/sudoers/logging.c:297
+msgid "user NOT authorized on host"
+msgstr "utilizatorul NU este autorizat pe gazdă"
+
+#: plugins/sudoers/logging.c:299
+msgid "command not allowed"
+msgstr "comanda nu este permisă"
+
+#: plugins/sudoers/logging.c:320
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr "%s nu se află în fișierul „sudoers”.\n"
+
+#: plugins/sudoers/logging.c:323
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr "%s nu are permisiunea de a rula «sudo» pe %s.\n"
+
+#: plugins/sudoers/logging.c:326
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Este posibil ca utilizatorul %s să nu poată executa «sudo» pe %s.\n"
+
+#: plugins/sudoers/logging.c:339
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s%s' as %s%s%s on %s.\n"
+msgstr "Utilizatorului %s nu îi este permis să execute „%s%s%s%s” ca %s%s%s pe %s.\n"
+
+#: plugins/sudoers/logging.c:350
+msgid "This incident has been reported to the administrator.\n"
+msgstr "Acest incident a fost raportat administratorului.\n"
+
+#: plugins/sudoers/logging.c:387 plugins/sudoers/sudoers.c:547
+#: plugins/sudoers/sudoers.c:549 plugins/sudoers/sudoers.c:551
+#: plugins/sudoers/sudoers.c:553 plugins/sudoers/sudoers.c:777
+#: plugins/sudoers/sudoers.c:779
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: comanda nu a fost găsită"
+
+#: plugins/sudoers/logging.c:389 plugins/sudoers/sudoers.c:543
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"se ignoră „%s” găsit în „.”\n"
+"Utilizați «sudo ./%s» dacă aceasta este „%s” pe care doriți să o rulați."
+
+#: plugins/sudoers/logging.c:409
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "o încercare de parolă incorectă"
+msgstr[1] "două încercări de parolă incorecte"
+msgstr[2] "%u încercări de parolă incorecte"
+msgstr[3] "%u de încercări de parolă incorecte"
+
+#: plugins/sudoers/logging.c:500
+msgid "authentication failure"
+msgstr "eșec de autentificare"
+
+#: plugins/sudoers/logging.c:539 plugins/sudoers/logging.c:558
+msgid "a password is required"
+msgstr "o parolă este necesară"
+
+#: plugins/sudoers/logging.c:881
+msgid "problem parsing sudoers"
+msgstr "problemă la analizarea sintaxei lui „sudoers”"
+
+#: plugins/sudoers/logging.c:922 plugins/sudoers/logging.c:930
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr "%s:%d:%d: %s"
+
+#: plugins/sudoers/logging.c:1108
+#, c-format
+msgid "unable to write log file %s"
+msgstr "nu se poate scrie fișierul de jurnal %s"
+
+#: plugins/sudoers/match_digest.c:107
+#, c-format
+msgid "digest for %s (%s) bad length %zu, expected %zu"
+msgstr "suma de control pentru %s (%s) are lungimea greșită %zu, se aștepta %zu"
+
+#: plugins/sudoers/match_digest.c:126
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "suma de control pentru %s (%s) nu este în formatul %s"
+
+#: plugins/sudoers/parse_ldif.c:615
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "se ignoră sudoRole incompletă: cn: %s"
+
+#: plugins/sudoers/parse_ldif.c:675
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "atribut LDIF nevalid: %s"
+
+#: plugins/sudoers/parser_warnx.c:56
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: plugins/sudoers/parser_warnx.c:59
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s: %s\n"
+
+#: plugins/sudoers/pivot.c:71
+msgid "unable to restore root directory"
+msgstr "nu se poate restabili directorul rădăcină"
+
+#: plugins/sudoers/pivot.c:79
+msgid "unable to restore current working directory"
+msgstr "nu se poate restabili directorul de lucru actual"
+
+#: plugins/sudoers/policy.c:78 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "%.*s nevalid stabilit de interfața «sudo»"
+
+#: plugins/sudoers/policy.c:364 plugins/sudoers/testsudoers.c:329
+msgid "unable to parse network address list"
+msgstr "nu se poate analiza lista de adrese de rețea"
+
+#: plugins/sudoers/policy.c:556
+msgid "user name not set by sudo front-end"
+msgstr "numele de utilizator nu este stabilit de interfața sudo"
+
+#: plugins/sudoers/policy.c:560
+msgid "user-ID not set by sudo front-end"
+msgstr "ID-ul utilizatorului nu este stabilit de interfața «sudo»"
+
+#: plugins/sudoers/policy.c:564
+msgid "group-ID not set by sudo front-end"
+msgstr "ID-ul grupului nu este stabilit de interfața «sudo»"
+
+#: plugins/sudoers/policy.c:568
+msgid "host name not set by sudo front-end"
+msgstr "numele gazdei nu este stabilit de interfața sudo"
+
+#: plugins/sudoers/policy.c:757
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "director de lucru nevalid: %s"
+
+#: plugins/sudoers/policy.c:944
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "director „chroot” nevalid: %s"
+
+#: plugins/sudoers/policy.c:1153 plugins/sudoers/visudo.c:919
+#: plugins/sudoers/visudo.c:1218
+#, c-format
+msgid "unable to execute %s"
+msgstr "nu se poate executa %s"
+
+#: plugins/sudoers/policy.c:1225 plugins/sudoers/policy.c:1260
+#: plugins/sudoers/policy.c:1282 plugins/sudoers/policy.c:1300
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: indicatori de mod nevalizi în interfața «sudo»: 0x%x"
+
+#: plugins/sudoers/policy.c:1323
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Versiunea modulului de politică „sudoers”, este %s\n"
+
+#: plugins/sudoers/policy.c:1325
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Versiunea de gramatică a fișierului „sudoers”, este %d\n"
+
+#: plugins/sudoers/policy.c:1329
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Ruta „sudoers”: %s\n"
+
+#: plugins/sudoers/policy.c:1332
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "ruta nsswitch: %s\n"
+
+#: plugins/sudoers/policy.c:1335
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "ruta ldap.conf: %s\n"
+
+#: plugins/sudoers/policy.c:1337
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "ruta ldap.secret: %s\n"
+
+#: plugins/sudoers/policy.c:1370
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "nu se poate înregistra cârligul de tip %d (versiunea %d.%d)"
+
+#: plugins/sudoers/policy.c:1388
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "nu se poate anula înregistrarea cârligului de tip %d (versiunea %d.%d)"
+
+#: plugins/sudoers/pwutil.c:242 plugins/sudoers/pwutil.c:260
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "nu se poate stoca în memoria tampon uid-ul %u"
+
+#: plugins/sudoers/pwutil.c:254
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "nu se poate stoca în memoria tampon uid-ul %u, există deja"
+
+#: plugins/sudoers/pwutil.c:314 plugins/sudoers/pwutil.c:332
+#: plugins/sudoers/pwutil.c:395 plugins/sudoers/pwutil.c:440
+#, c-format
+msgid "unable to cache user %s"
+msgstr "nu se poate stoca în memoria tampon utilizatorul %s"
+
+#: plugins/sudoers/pwutil.c:327
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "nu se poate stoca în memoria tampon utilizatorul %s, există deja"
+
+#: plugins/sudoers/pwutil.c:559 plugins/sudoers/pwutil.c:577
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "nu se poate stoca în memoria tampon gid-ul %u"
+
+#: plugins/sudoers/pwutil.c:571
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "nu se poate stoca în memoria tampon gid-ul %u, există deja"
+
+#: plugins/sudoers/pwutil.c:625 plugins/sudoers/pwutil.c:643
+#: plugins/sudoers/pwutil.c:704 plugins/sudoers/pwutil.c:753
+#, c-format
+msgid "unable to cache group %s"
+msgstr "nu se poate stoca în memoria tampon grupul %s"
+
+#: plugins/sudoers/pwutil.c:638
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "nu se poate stoca în memoria tampon grupul %s, există deja"
+
+#: plugins/sudoers/pwutil.c:900 plugins/sudoers/pwutil.c:985
+#: plugins/sudoers/pwutil.c:1039 plugins/sudoers/pwutil.c:1095
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "nu se poate stoca în memoria tampon lista grupului pentru %s, există deja"
+
+#: plugins/sudoers/pwutil.c:906 plugins/sudoers/pwutil.c:990
+#: plugins/sudoers/pwutil.c:1045 plugins/sudoers/pwutil.c:1100
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "nu se poate stoca în memoria tampon lista grupului pentru %s"
+
+#: plugins/sudoers/pwutil.c:979
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "nu se pot analiza grupurile pentru %s"
+
+#: plugins/sudoers/pwutil.c:1089
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "nu se pot analiza gid-urile pentru %s"
+
+#: plugins/sudoers/set_perms.c:120 plugins/sudoers/set_perms.c:457
+#: plugins/sudoers/set_perms.c:870 plugins/sudoers/set_perms.c:1186
+#: plugins/sudoers/set_perms.c:1490
+msgid "perm stack overflow"
+msgstr "supraplin al stivei de permisiuni"
+
+#: plugins/sudoers/set_perms.c:131 plugins/sudoers/set_perms.c:387
+#: plugins/sudoers/set_perms.c:468 plugins/sudoers/set_perms.c:736
+#: plugins/sudoers/set_perms.c:881 plugins/sudoers/set_perms.c:1109
+#: plugins/sudoers/set_perms.c:1197 plugins/sudoers/set_perms.c:1422
+#: plugins/sudoers/set_perms.c:1501 plugins/sudoers/set_perms.c:1592
+msgid "perm stack underflow"
+msgstr "subnivel al stivei de permisiuni"
+
+#: plugins/sudoers/set_perms.c:191 plugins/sudoers/set_perms.c:515
+#: plugins/sudoers/set_perms.c:1251 plugins/sudoers/set_perms.c:1535
+msgid "unable to change to root gid"
+msgstr "nu se poate schimba la gid-ul root"
+
+#: plugins/sudoers/set_perms.c:282 plugins/sudoers/set_perms.c:612
+#: plugins/sudoers/set_perms.c:1013 plugins/sudoers/set_perms.c:1328
+msgid "unable to change to runas gid"
+msgstr "nu se poate schimba la gid-ul „run as”"
+
+#: plugins/sudoers/set_perms.c:287 plugins/sudoers/set_perms.c:617
+#: plugins/sudoers/set_perms.c:1018 plugins/sudoers/set_perms.c:1333
+msgid "unable to set runas group vector"
+msgstr "nu se poate stabili vectorul de grup „run as”"
+
+#: plugins/sudoers/set_perms.c:298 plugins/sudoers/set_perms.c:628
+#: plugins/sudoers/set_perms.c:1027 plugins/sudoers/set_perms.c:1342
+msgid "unable to change to runas uid"
+msgstr "nu se poate schimba uid-ul „run as”"
+
+#: plugins/sudoers/set_perms.c:320 plugins/sudoers/set_perms.c:650
+#: plugins/sudoers/set_perms.c:1047 plugins/sudoers/set_perms.c:1362
+msgid "unable to change to sudoers gid"
+msgstr "nu se poate schimba gid-ul „sudoers”"
+
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579
+msgid "too many processes"
+msgstr "prea multe procese"
+
+#: plugins/sudoers/solaris_audit.c:62
+msgid "unable to get current working directory"
+msgstr "nu se poate obține directorul de lucru actual"
+
+#: plugins/sudoers/solaris_audit.c:70
+#, c-format
+msgid "truncated audit path ctx->user.cmnd: %s"
+msgstr "ruta de auditare trunchiată ctx->user.cmnd: %s"
+
+#: plugins/sudoers/solaris_audit.c:77
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "ruta de auditare trunchiată argv[0]: %s"
+
+#: plugins/sudoers/sssd.c:581
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "nu se poate inițializa sursa SSS. Este SSSD instalat pe mașină?"
+
+#: plugins/sudoers/sssd.c:589 plugins/sudoers/sssd.c:598
+#: plugins/sudoers/sssd.c:607 plugins/sudoers/sssd.c:616
+#: plugins/sudoers/sssd.c:625
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "nu se poate găsi simbolul „%s” în %s"
+
+#: plugins/sudoers/sudoers.c:250
+#, c-format
+msgid "unable to get defaults from %s"
+msgstr "nu se pot obține valorile implicite de la %s"
+
+#: plugins/sudoers/sudoers.c:259
+msgid "no valid sudoers sources found, quitting"
+msgstr "nicio sursă „sudoers” validă, se iese"
+
+#: plugins/sudoers/sudoers.c:366
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "„sudoers” specifică că root nu are permisiunea să execute «sudo»"
+
+#: plugins/sudoers/sudoers.c:375
+msgid "user not allowed to override closefrom limit"
+msgstr "utilizatorului nu îi este permis să suprascrie limita de closefrom"
+
+#: plugins/sudoers/sudoers.c:376
+msgid "you are not permitted to use the -C option"
+msgstr "nu aveți permisiunea de a utiliza opțiunea „-C”"
+
+#: plugins/sudoers/sudoers.c:440
+msgid "no tty"
+msgstr "fără tty"
+
+#: plugins/sudoers/sudoers.c:441
+msgid "sorry, you must have a tty to run sudo"
+msgstr "trebuie să aveți un tty pentru a rula «sudo»"
+
+#: plugins/sudoers/sudoers.c:449
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "shell nevalid pentru utilizatorul %s: %s"
+
+#: plugins/sudoers/sudoers.c:491
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "utilizatorul nu are permisiunea de a schimba directorul rădăcină în %s"
+
+#: plugins/sudoers/sudoers.c:493
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "nu aveți permisiunea de a utiliza opțiunea „-R” cu %s"
+
+#: plugins/sudoers/sudoers.c:506
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "utilizatorului nu îi este permis să schimbe directorul la %s"
+
+#: plugins/sudoers/sudoers.c:507
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "nu aveți permisiunea de a utiliza opțiunea „-D” cu %s"
+
+#: plugins/sudoers/sudoers.c:542
+msgid "command in current directory"
+msgstr "comandă în directorul curent"
+
+#: plugins/sudoers/sudoers.c:557
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr "«cd» este o comandă încorporată în shell, nu poate fi rulată direct."
+
+#: plugins/sudoers/sudoers.c:559
+msgid "the -s option may be used to run a privileged shell."
+msgstr "opțiunea „-s” poate fi utilizată pentru a rula un shell privilegiat."
+
+#: plugins/sudoers/sudoers.c:561
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr "opțiunea „-D” poate fi folosită pentru a rula o comandă într-un anumit director."
+
+#: plugins/sudoers/sudoers.c:570
+msgid "user not allowed to set a command timeout"
+msgstr "utilizatorului nu îi este permis să stabilească o limită de timp a comenzii"
+
+#: plugins/sudoers/sudoers.c:572
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "nu aveți permisiunea de a stabili o limită de timp a comenzii"
+
+#: plugins/sudoers/sudoers.c:580
+msgid "user not allowed to preserve the environment"
+msgstr "utilizatorului nu îi este permis să păstreze mediul"
+
+#: plugins/sudoers/sudoers.c:582
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "nu aveți permisiunea să păstrați mediul"
+
+#: plugins/sudoers/sudoers.c:618
+msgid "no command specified"
+msgstr "nicio comandă specificată"
+
+#: plugins/sudoers/sudoers.c:759
+msgid "error setting user-specified environment variables"
+msgstr "eroare la stabilirea variabilelor de mediu specificate de utilizator"
+
+#: plugins/sudoers/sudoers.c:1211
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "«sudoedit» nu are nevoie să fie rulat via «sudo»"
+
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:1613
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "nu se poate citi %s"
+
+#: plugins/sudoers/sudoers.c:1321 plugins/sudoers/visudo.c:1123
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s nu este un fișier obișnuit"
+
+#: plugins/sudoers/sudoers.c:1325 plugins/sudoers/timestamp.c:272 toke.l:1355
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s este deținut de uid-ul %u, ar trebui să fie %u"
+
+#: plugins/sudoers/sudoers.c:1330 plugins/sudoers/timestamp.c:279 toke.l:1360
+#, c-format
+msgid "%s is world writable"
+msgstr "%s poate fi scris de oricine"
+
+#: plugins/sudoers/sudoers.c:1334 plugins/sudoers/timestamp.c:284 toke.l:1363
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s este deținut de gid-ul %u, ar trebui să fie %u"
+
+#: plugins/sudoers/sudoers.c:1363
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "doar root poate utiliza „-c %s”"
+
+#: plugins/sudoers/sudoers.c:1382
+#, c-format
+msgid "unknown login class %s"
+msgstr "clasă de autentificare necunoscută %s"
+
+#: plugins/sudoers/sudoers_cb.c:120 plugins/sudoers/sudoers_cb.c:135
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "nu se poate rezolva gazda %s"
+
+#: plugins/sudoers/sudoreplay.c:252
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "opțiune de filtru nevalidă: %s"
+
+#: plugins/sudoers/sudoreplay.c:268
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "așteptare maximă nevalidă: %s"
+
+#: plugins/sudoers/sudoreplay.c:291
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "factor de viteză nevalid: %s"
+
+#: plugins/sudoers/sudoreplay.c:326
+#, c-format
+msgid "invalid time offset %s"
+msgstr "decalaj de timp nevalid %s"
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:340
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/sincronizare: %s"
+
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Se redă sesiunea sudo: %s"
+
+#: plugins/sudoers/sudoreplay.c:634
+msgid "unable to set tty to raw mode"
+msgstr "nu se poate stabili tty la modul „raw”"
+
+#: plugins/sudoers/sudoreplay.c:685
+msgid "Warning: your terminal is too small to properly replay the log."
+msgstr "Avertisment: terminalul este prea mic pentru a putea reda bine jurnalul."
+
+#: plugins/sudoers/sudoreplay.c:686
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Geometria jurnalului este %d x %d, iar geometria terminalului este %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:714
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Redarea s-a încheiat, apăsați orice tastă pentru a restaura terminalul."
+
+#: plugins/sudoers/sudoreplay.c:1217 plugins/sudoers/sudoreplay.c:1247
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "expresie ambiguă „%s”"
+
+#: plugins/sudoers/sudoreplay.c:1269
+msgid "unmatched ')' in expression"
+msgstr "„)” fără pereche în expresie"
+
+#: plugins/sudoers/sudoreplay.c:1273
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "termen de căutare necunoscut „%s”"
+
+#: plugins/sudoers/sudoreplay.c:1288
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s necesită un argument"
+
+#: plugins/sudoers/sudoreplay.c:1298
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "nu s-a putut analiza data „%s”"
+
+#: plugins/sudoers/sudoreplay.c:1307
+msgid "unmatched '(' in expression"
+msgstr "„(” fără pereche în expresie"
+
+#: plugins/sudoers/sudoreplay.c:1309
+msgid "illegal trailing \"or\""
+msgstr "terminare ilegală a expresiei, cu „or”"
+
+#: plugins/sudoers/sudoreplay.c:1311
+msgid "illegal trailing \"!\""
+msgstr "terminare ilegală a expresiei, cu „!”"
+
+#: plugins/sudoers/sudoreplay.c:1417
+#, c-format
+msgid "unknown search type %d"
+msgstr "tip de căutare necunoscută %d"
+
+#: plugins/sudoers/sudoreplay.c:1679
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "utilizare: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1681
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "utilizare: %s [-h] [-d dir] -l [expresie de căutare]\n"
+
+#: plugins/sudoers/sudoreplay.c:1695
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - redă jurnalele de sesiune «sudo»\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1697
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specifică directorul pentru jurnalele sesiunii\n"
+" -f, --filter=filter specifică care tip(uri) de In/Ieș să se afișeze\n"
+" -h, --help afișează mesajul de ajutor și iese\n"
+" -l, --list listează ID-urile sesiunii disponibile, cu expresii opționale\n"
+" -m, --max-wait=num numărul maxim de secunde de așteptat între evenimente\n"
+" -n, --non-interactive fără solicitări, sesiunea este trimisă direct la ieșirea standard\n"
+" -R, --no-resize nu încearcă să redimensioneze terminalul\n"
+" -S, --suspend-wait așteaptă până când comanda a fost suspendată\n"
+" -s, --speed=num accelerează sau încetinește ieșirea\n"
+" -V, --version afișează informațiile de versiune și iese"
+
+#: plugins/sudoers/testsudoers.c:392
+#, c-format
+msgid ""
+"\n"
+"Invalid shell for user %s: %s\n"
+msgstr ""
+"\n"
+"Shell nevalid pentru utilizatorul %s: %s\n"
+
+#: plugins/sudoers/testsudoers.c:411
+msgid ""
+"\n"
+"Password required"
+msgstr ""
+"\n"
+"Este necesară parola"
+
+#: plugins/sudoers/testsudoers.c:422
+msgid ""
+"\n"
+"Parse error"
+msgstr ""
+"\n"
+"Eroare de analizare"
+
+#: plugins/sudoers/testsudoers.c:425
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Comandă permisă"
+
+#: plugins/sudoers/testsudoers.c:428
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Comandă negată"
+
+#: plugins/sudoers/testsudoers.c:431
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Comanda nu se potrivește"
+
+#: plugins/sudoers/timestamp.c:364 plugins/sudoers/timestamp.c:711
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "nu se poate trunchia fișierul marcajelor de timp în %lld octeți"
+
+#: plugins/sudoers/timestamp.c:908
+msgid "ignoring time stamp from the future"
+msgstr "se vor ignora marcajele de timp pe viitor"
+
+#: plugins/sudoers/timestamp.c:931
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "datarea este prea departe în viitor: %20.20s"
+
+#: plugins/sudoers/timestamp.c:1067
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "nu se poate bloca fișierul marcajelor de timp %s"
+
+#: plugins/sudoers/timestamp.c:1114
+#, c-format
+msgid "%s:%d:%d timestampowner: unknown user %s"
+msgstr "%s:%d:%d timestampowner: utilizator necunoscut %s"
+
+#: plugins/sudoers/toke_util.c:159
+msgid "sudoedit should not be specified with a path"
+msgstr "«sudoedit» nu ar trebui să fie specificat cu o rută"
+
+#: plugins/sudoers/visudo.c:308 plugins/sudoers/visudo.c:714
+#, c-format
+msgid "press return to edit %s: "
+msgstr "apăsați „enter” pentru a edita %s: "
+
+#: plugins/sudoers/visudo.c:323
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "conținutul sesiunii de editare rămase în %s"
+
+#: plugins/sudoers/visudo.c:401
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "editorul specificat (%s) nu există"
+
+#: plugins/sudoers/visudo.c:406
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "nu s-a găsit niciun editor (rută editor = %s)"
+
+#: plugins/sudoers/visudo.c:494 plugins/sudoers/visudo.c:786
+#, c-format
+msgid "unable to stat %s"
+msgstr "nu se poate stabili starea lui %s"
+
+#: plugins/sudoers/visudo.c:514 plugins/sudoers/visudo.c:522
+msgid "write error"
+msgstr "eroare de scriere"
+
+#: plugins/sudoers/visudo.c:568
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "nu se poate stabili starea fișierului temporar (%s), %s neschimbat"
+
+#: plugins/sudoers/visudo.c:575
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "fișier temporar de lungime zero (%s), %s neschimbat"
+
+#: plugins/sudoers/visudo.c:581
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "editorul (%s) a eșuat, %s neschimbat"
+
+#: plugins/sudoers/visudo.c:613
+#, c-format
+msgid "%s unchanged"
+msgstr "%s neschimbat"
+
+#: plugins/sudoers/visudo.c:661
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "nu se poate redeschide fișierul temporar (%s), %s neschimbat."
+
+#: plugins/sudoers/visudo.c:674
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "nu se poate analiza fișierul temporar (%s), eroare necunoscută"
+
+#: plugins/sudoers/visudo.c:760 plugins/sudoers/visudo.c:790
+#: plugins/sudoers/visudo.c:797
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "nu se poate stabili (uid, gid) de %s la (%u, %u)"
+
+#: plugins/sudoers/visudo.c:825
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s și %s nu sunt pe același sistem de fișiere, se utilizează «mv» pentru a redenumi"
+
+#: plugins/sudoers/visudo.c:836
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "comanda a eșuat: „%s %s %s”, %s neschimbat"
+
+#: plugins/sudoers/visudo.c:843
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "eroare la redenumirea %s, %s neschimbat"
+
+#: plugins/sudoers/visudo.c:864
+msgid "What now? "
+msgstr "Acum ce? "
+
+#: plugins/sudoers/visudo.c:878
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Opțiunile sunt:\n"
+" (e) - editează fișierul „sudoers” din nou\n"
+" (x) - ieși fără a salva modificările în fișierul „sudoers”\n"
+" (Q) - ieși și salvează modificările în fișierul „sudoers” (PERICOL!)\n"
+
+#: plugins/sudoers/visudo.c:923
+#, c-format
+msgid "unable to run %s"
+msgstr "nu se poate rula %s"
+
+#: plugins/sudoers/visudo.c:954
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: proprietarul greșit (uid, gid) ar trebui să fie (%u, %u)n\n"
+
+#: plugins/sudoers/visudo.c:965
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: permisiuni proaste, ar trebui să fie modul 0%o\n"
+
+#: plugins/sudoers/visudo.c:1017 plugins/sudoers/visudo.c:1024
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: analizat, OK\n"
+
+#: plugins/sudoers/visudo.c:1043
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s ocupat, încercați din nou mai târziu"
+
+#: plugins/sudoers/visudo.c:1047
+msgid "Edit anyway? [y/N]"
+msgstr "Editați oricum? [y/N]"
+
+#: plugins/sudoers/visudo.c:1206
+msgid "the -x option will be removed in a future release"
+msgstr "opțiunea „-x” va fi eliminată într-o lansare viitoare"
+
+#: plugins/sudoers/visudo.c:1208
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "luați în considerare utilizarea utilitarului «cvtsudoers» în schimb"
+
+#: plugins/sudoers/visudo.c:1228
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "Avertisment: %s:%d:%d: neutilizat %s „%s”"
+
+#: plugins/sudoers/visudo.c:1341
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - editează în siguranță fișierul „sudoers”\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1343
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -I, --no-includes do not edit include files\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Opțiuni:\n"
+" -c, --check modul doar verifică\n"
+" -f, --file=sudoers specifică locația fișierului „sudoers”\n"
+" -h, --help afișează mesajul de ajutor și iese\n"
+" -I, --no-includes nu editează fișierele „include”\n"
+" -q, --quiet mesaje de eroare de sintaxă mai puțin detaliate\n"
+" -s, --strict verificare strictă de sintaxă\n"
+" -V, --version afișează informațiile de versiune și iese\n"
+
+#: toke.l:184
+msgid "empty string"
+msgstr "șir gol"
+
+#: toke.l:196 toke.l:566
+msgid "empty group"
+msgstr "grup gol"
+
+#: toke.l:206 toke.l:564
+msgid "empty netgroup"
+msgstr "netgroup gol"
+
+#: toke.l:284
+msgid "unterminated regular expression"
+msgstr "expresie regulată nedeterminată"
+
+#: toke.l:358 toke.l:370 toke.l:382 toke.l:398 toke.l:417 toke.l:457
+msgid "invalid line continuation"
+msgstr "continuarea liniei nevalidă"
+
+#: toke.l:603 toke.l:615
+msgid "invalid IPv6 address"
+msgstr "adresă IPv6 invalidă"
+
+#: toke.l:863
+msgid "unexpected line break in string"
+msgstr "întrerupere de linie neașteptată în șir"
+
+#: toke.l:982
+msgid "ignoring editor backup file"
+msgstr "se ignoră fișierul de copie de rezervă al editorului"
+
+#: toke.l:985
+msgid "ignoring file name containing '.'"
+msgstr "se ignoră numele de fișier care conține „.”"
+
+#: toke.l:1310
+msgid "too many levels of includes"
+msgstr "prea multe niveluri de includeri"
+
+#~ msgid "\thost unmatched"
+#~ msgstr "\tgazda nu are nici o potrivire"
+
+#~ msgid "timestamp owner (%s): No such user"
+#~ msgstr "proprietar marcaj de timp (%s): Nu există un astfel de utilizator"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s trebuie să fie deținut de uid-ul %d"
+
+#~ msgid "%s must only be writable by owner"
+#~ msgstr "%s trebuie să poată fi scris numai de către proprietar"
+
+#~ msgid "%s is group writable"
+#~ msgstr "%s poate fi scris de membrii grupului"
+
+#~ msgid "lecture status path too long: %s/%s"
+#~ msgstr "calea fișierului de stare al instrucțiunilor de utilizare, este prea lungă: %s/%s"
+
+#~ msgid "Warning: %s:%d:%d: cycle in %s \"%s\""
+#~ msgstr "Avertisment: %s:%d:%d ciclu în %s „%s”"
+
+#~ msgid "Warning: %s:%d:%d: %s \"%s\" referenced but not defined"
+#~ msgstr "Avertisment: %s:%d:%d %s \"%s\" menționat, dar nu definit"
+
+#~ msgid "parse error in %s near line %d\n"
+#~ msgstr "eroare de analizare în %s lângă linia %d\n"
+
+#~ msgid "parse error in %s\n"
+#~ msgstr "eroare de analizare în %s\n"
+
+#~ msgid "%s: unknown defaults entry \"%s\""
+#~ msgstr "%s: intrare defaults necunoscută „%s”"
+
+#~ msgid "%s:%d:%d: no value specified for \"%s\""
+#~ msgstr "%s:%d:%d nicio valoare specificată pentru „%s”"
+
+#~ msgid "%s:%d:%d: invalid operator \"%c=\" for \"%s\""
+#~ msgstr "%s:%d:%d: operator nevalid „%c=\" pentru „%s”"
+
+#~ msgid "%s:%d:%d: option \"%s\" does not take a value"
+#~ msgstr "%s:%d:%d: opțiunea „%s” nu primește o valoare"
+
+#~ msgid "%s:%d:%d: invalid Defaults type 0x%x for option \"%s\""
+#~ msgstr "%s:%d:%d: tip de Defaults nevalid 0x%x pentru opțiunea „%s”"
+
+#~ msgid "%s:%d:%d: value \"%s\" is invalid for option \"%s\""
+#~ msgstr "%s:%d:%d: valoarea „%s” nu este validă pentru opțiunea „%s”"
+
+#~ msgid "%s:%d:%d: path name for \"%s\" too long"
+#~ msgstr "%s:%d:%d: numele căii pentru „%s” este prea lung"
+
+#~ msgid "%s: path name for \"%s\" too long"
+#~ msgstr "%s: numele căii pentru „%s” este prea lung"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/', '~', or '*'"
+#~ msgstr "%s:%d:%d: valorile pentru „%s” trebuie să înceapă cu un „/”, „~”, sau „*”"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/'"
+#~ msgstr "%s:%d:%d: valorile pentru „%s” trebuie să înceapă cu un „/”"
+
+#~ msgid "parse error in %s near line %d"
+#~ msgstr "eroare de analizare în %s lângă linia %d"
+
+#~ msgid "parse error in %s"
+#~ msgstr "eroare de analizare în %s"
+
+#~ msgid "SELinux RBAC is not supported when intercept mode is enabled"
+#~ msgstr "SELinux RBAC nu este acceptat când modul de interceptare este activat"
+
+#~ msgid "SELinux RBAC is not supported when the log_subcmds flag is enabled"
+#~ msgstr "SELinux RBAC nu este acceptat când fanionul log_subcmds este activat"
+
+#~ msgid "problem with defaults entries"
+#~ msgstr "problemă cu intrările implicite"
+
+#~ msgid "internal error, unable to find %s in list!"
+#~ msgstr "eroare internă, nu se poate găsi %s în listă!"
+
+#~ msgid "%s:%u unable to parse \"%s\""
+#~ msgstr "%s:%u nu se poate parsa „%s”"
+
+#~ msgid "unable to get TLS server method: %s"
+#~ msgstr "nu se poate obține metoda de server TLS: %s"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " -f, --file path to configuration file\n"
+#~ " -h --help display help message and exit\n"
+#~ " -n, --no-fork do not fork, run in the foreground\n"
+#~ " -R, --random-drop percent chance connections will drop\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Opțini:\n"
+#~ " -f, --file calea către fișierul de configurare\n"
+#~ " -h --help afișează mesajul de ajutor și ieși\n"
+#~ " -n, --no-fork nu da fork, rulează în prim plan\n"
+#~ " -R, --random-drop șansa în procente pentru căderea conexiunii\n"
+#~ " -V, --version afișează informațiile de versiune și ieși\n"
+
+#~ msgid "%s:%d unknown key: %s"
+#~ msgstr "%s:%d cheie necunoscută: %s"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " --help display help message and exit\n"
+#~ " -A, --accept only send an accept event (no I/O)\n"
+#~ " -h, --host host to send logs to\n"
+#~ " -i, --iolog_id remote ID of I/O log to be resumed\n"
+#~ " -p, --port port to use when connecting to host\n"
+#~ " -r, --restart restart previous I/O log transfer\n"
+#~ " -R, --reject reject the command with the given reason\n"
+#~ " -b, --ca-bundle certificate bundle file to verify server's cert against\n"
+#~ " -c, --cert certificate file for TLS handshake\n"
+#~ " -k, --key private key file\n"
+#~ " -n, --no-verify do not verify server certificate\n"
+#~ " -t, --test test audit server by sending selected I/O log n times in parallel\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Opțiuni:\n"
+#~ " --help afișează mesajul de ajutor și ieși\n"
+#~ " -A, --accept trimite doar un eveniment de acceptare (fără I/O)\n"
+#~ " -h, --host gazda la care să se trimită înregistrări\n"
+#~ " -i, --iolog_id ID-ul de la distanță al istoricului I/O de rezumat \n"
+#~ " -p, --port portul de utilizat când se conectează la gazdă\n"
+#~ " -r, --restart repornește transferul de istoric I/O anterior\n"
+#~ " -R, --reject respinge comanda cu motivul dat\n"
+#~ " -b, --ca-bundle fișier de pachet de certificat împotriva căruia se verifică certificarea serverului\n"
+#~ " -c, --cert fișierul certificat pentru conexiunea TLS\n"
+#~ " -k, --key fișier cheie privată\n"
+#~ " -n, --no-verify nu verifica certificatul serverului\n"
+#~ " -V, --version afișează informațiile de versiune și ieși\n"
+
+#~ msgid "%s: write buffer already in use"
+#~ msgstr "%s: preîncărcare de scriere deja în uz"
+
+#~ msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+#~ msgstr "Preîncarcă funcțiile de execuție dummy conținute în biblioteca sudo_nonexec"
+
+#~ msgid "sudo_ldap_conf_add_ports: port too large"
+#~ msgstr "sudo_ldap_conf_add_ports: portul prea mare"
+
+#~ msgid "%s is not in the sudoers file. This incident will be reported.\n"
+#~ msgstr "%s nu este în fișierul sudoers. Acest incident va fi raportat.\n"
+
+#~ msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+#~ msgstr "%s nu are permisiunea de a rula sudo pe %s. Acest incident va fi raportat.\n"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s\n"
+#~ msgstr "SSL_connect a eșuat: ssl_error=%d, stiva=%s\n"
+
+#~ msgid "CA bundle file was not specified"
+#~ msgstr "Fișierul de pachet CA nu a fost specificat"
+
+#~ msgid "Client certificate was not specified"
+#~ msgstr "Certificatul clientului nu a fost specificat"
+
+#~ msgid "Unable to allocate ssl object: %s\n"
+#~ msgstr "Nu se poate aloca obiectul ssl: %s\n"
+
+#~ msgid "Unable to attach socket to the ssl object: %s\n"
+#~ msgstr "Nu se poate atașa soclul la obiectul ssl: %s\n"
+
+#~ msgid "client message too large: %zu\n"
+#~ msgstr "mesajul de client este prea mare: %zu\n"
+
+#~ msgid "server message too large: %u\n"
+#~ msgstr "mesaj de server prea mare: %u\n"
+
+#~ msgid "CA bundle file is not set in sudoers"
+#~ msgstr "Fișierul pachet CA nu este stabilit în sudoers"
+
+#~ msgid "Calling SSL_CTX_load_verify_locations() failed: %s"
+#~ msgstr "Apelarea a SSL_CTX_load_verify_locations() a eșuat: %s"
+
+#~ msgid "Signed certificate file is not set in sudoers"
+#~ msgstr "Fișierul de certificat semnat nu este stabilit în sudoers"
+
+#~ msgid "Unable to load private key into the ssl context: %s"
+#~ msgstr "Nu se poate încărca cheia privată în contextul ssl: %s"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_connect a eșuat: ssl_error=%d, stivă=%s"
+
+#~ msgid "SSL_read failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_read a eșuat: ssl_error=%d, stivă=%s"
+
+#~ msgid "SSL_write failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_write a eșuat: ssl_error=%d, stivă=%s"
+
+#~ msgid "unknown address family: %d"
+#~ msgstr "familie de adrese necunoscută: %d"
+
+#~ msgid "audit_failure message too long"
+#~ msgstr "mesaj audit_failure prea mare"
diff --git a/plugins/sudoers/po/ru.mo b/plugins/sudoers/po/ru.mo
new file mode 100644
index 0000000..7f98066
--- /dev/null
+++ b/plugins/sudoers/po/ru.mo
Binary files differ
diff --git a/plugins/sudoers/po/ru.po b/plugins/sudoers/po/ru.po
new file mode 100644
index 0000000..6e7ded3
--- /dev/null
+++ b/plugins/sudoers/po/ru.po
@@ -0,0 +1,3869 @@
+# Transation of sudoers messages to Russian.
+# This file is put in the public domain.
+# This file is distributed under the same license as the sudo package.
+#
+# Artem Vorotnikov <artem@vorotnikov.me>, 2015.
+# Pavel Maryanov <acid@jack.kiev.ua>, 2015, 2022.
+# Kirill Isakov <k@isakov.net>, 2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.9.15b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-10-19 10:02-0600\n"
+"PO-Revision-Date: 2023-10-22 18:07+0600\n"
+"Last-Translator: Kirill Isakov <k@isakov.net>\n"
+"Language-Team: Russian <gnu@d07.ru>\n"
+"Language: ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: Poedit 3.3.2\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+
+#: confstr.sh:1 gram.y:1257 plugins/sudoers/logging.c:911
+msgid "syntax error"
+msgstr "ошибка синтаксиса"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "пароль %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] пароль для %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Пароль: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** Данные БЕЗОПАСНОСТИ для %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Попробуйте ещё раз."
+
+#: gram.y:238 gram.y:305 gram.y:314 gram.y:323 gram.y:333 gram.y:343 gram.y:367
+#: gram.y:394 gram.y:403 gram.y:411 gram.y:420 gram.y:429 gram.y:503 gram.y:513
+#: gram.y:525 gram.y:573 gram.y:582 gram.y:591 gram.y:600 gram.y:733 gram.y:742
+#: gram.y:757 gram.y:777 gram.y:796 gram.y:959 gram.y:964 gram.y:972 gram.y:986
+#: gram.y:992 gram.y:1004 gram.y:1010 gram.y:1135 gram.y:1144 gram.y:1152
+#: gram.y:1161 gram.y:1170 gram.y:1199 gram.y:1208 gram.y:1216 gram.y:1317
+#: gram.y:1447 gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:313 lib/eventlog/eventlog.c:765
+#: lib/eventlog/eventlog.c:842 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:484
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:185
+#: logsrvd/iolog_writer.c:218 logsrvd/iolog_writer.c:228
+#: logsrvd/iolog_writer.c:257 logsrvd/iolog_writer.c:278
+#: logsrvd/iolog_writer.c:290 logsrvd/iolog_writer.c:300
+#: logsrvd/iolog_writer.c:310 logsrvd/iolog_writer.c:320
+#: logsrvd/iolog_writer.c:330 logsrvd/iolog_writer.c:342
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:1057 logsrvd/logsrvd.c:1120 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:650
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1743
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:216
+#: logsrvd/logsrvd_journal.c:217 logsrvd/logsrvd_journal.c:274
+#: logsrvd/logsrvd_journal.c:279 logsrvd/logsrvd_journal.c:439
+#: logsrvd/logsrvd_journal.c:441 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:216 logsrvd/logsrvd_local.c:278
+#: logsrvd/logsrvd_local.c:279 logsrvd/logsrvd_local.c:417
+#: logsrvd/logsrvd_local.c:468 logsrvd/logsrvd_local.c:469
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:475
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/logsrvd_relay.c:446
+#: logsrvd/logsrvd_relay.c:748 logsrvd/logsrvd_relay.c:855
+#: logsrvd/sendlog.c:256 logsrvd/sendlog.c:265 logsrvd/sendlog.c:297
+#: logsrvd/sendlog.c:303 logsrvd/sendlog.c:352 logsrvd/sendlog.c:630
+#: logsrvd/sendlog.c:1822 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/bsdauth.c:154 plugins/sudoers/auth/kerb5.c:122
+#: plugins/sudoers/auth/kerb5.c:150 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/auth/sia.c:61
+#: plugins/sudoers/canon_path.c:129 plugins/sudoers/canon_path.c:161
+#: plugins/sudoers/check_aliases.c:128 plugins/sudoers/check_util.c:56
+#: plugins/sudoers/check_util.c:84 plugins/sudoers/cvtsudoers.c:132
+#: plugins/sudoers/cvtsudoers.c:176 plugins/sudoers/cvtsudoers.c:193
+#: plugins/sudoers/cvtsudoers.c:204 plugins/sudoers/cvtsudoers.c:338
+#: plugins/sudoers/cvtsudoers.c:379 plugins/sudoers/cvtsudoers.c:399
+#: plugins/sudoers/cvtsudoers.c:545 plugins/sudoers/cvtsudoers.c:698
+#: plugins/sudoers/cvtsudoers.c:716 plugins/sudoers/cvtsudoers.c:891
+#: plugins/sudoers/cvtsudoers.c:899 plugins/sudoers/cvtsudoers.c:1395
+#: plugins/sudoers/cvtsudoers.c:1399 plugins/sudoers/cvtsudoers.c:1501
+#: plugins/sudoers/cvtsudoers_csv.c:183 plugins/sudoers/cvtsudoers_csv.c:247
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:152
+#: plugins/sudoers/cvtsudoers_ldif.c:195 plugins/sudoers/cvtsudoers_ldif.c:236
+#: plugins/sudoers/cvtsudoers_ldif.c:302 plugins/sudoers/cvtsudoers_ldif.c:378
+#: plugins/sudoers/cvtsudoers_ldif.c:432 plugins/sudoers/cvtsudoers_ldif.c:440
+#: plugins/sudoers/cvtsudoers_ldif.c:451 plugins/sudoers/cvtsudoers_ldif.c:458
+#: plugins/sudoers/cvtsudoers_ldif.c:470 plugins/sudoers/cvtsudoers_ldif.c:483
+#: plugins/sudoers/cvtsudoers_ldif.c:491 plugins/sudoers/cvtsudoers_ldif.c:638
+#: plugins/sudoers/cvtsudoers_merge.c:47 plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1158
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:212
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:694 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:294 plugins/sudoers/ldap_util.c:301
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:402
+#: plugins/sudoers/log_client.c:717 plugins/sudoers/log_client.c:739
+#: plugins/sudoers/log_client.c:744 plugins/sudoers/log_client.c:1426
+#: plugins/sudoers/log_client.c:1547 plugins/sudoers/log_client.c:1670
+#: plugins/sudoers/log_client.c:1993 plugins/sudoers/log_client.c:2052
+#: plugins/sudoers/logging.c:110 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:872 plugins/sudoers/lookup.c:338
+#: plugins/sudoers/lookup.c:355 plugins/sudoers/lookup.c:374
+#: plugins/sudoers/lookup.c:393 plugins/sudoers/lookup.c:410
+#: plugins/sudoers/lookup.c:433 plugins/sudoers/lookup.c:444
+#: plugins/sudoers/match_command.c:302 plugins/sudoers/match_command.c:574
+#: plugins/sudoers/match_command.c:641 plugins/sudoers/match_command.c:737
+#: plugins/sudoers/match_command.c:785 plugins/sudoers/match_digest.c:88
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:595
+#: plugins/sudoers/parse_ldif.c:625 plugins/sudoers/parse_ldif.c:650
+#: plugins/sudoers/parse_ldif.c:708 plugins/sudoers/parse_ldif.c:725
+#: plugins/sudoers/parse_ldif.c:753 plugins/sudoers/parse_ldif.c:760
+#: plugins/sudoers/policy.c:646 plugins/sudoers/policy.c:1061
+#: plugins/sudoers/prompt.c:94 plugins/sudoers/pwutil.c:219
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:368
+#: plugins/sudoers/pwutil.c:542 plugins/sudoers/pwutil.c:607
+#: plugins/sudoers/pwutil.c:679 plugins/sudoers/pwutil.c:877
+#: plugins/sudoers/pwutil.c:967 plugins/sudoers/pwutil.c:1015
+#: plugins/sudoers/pwutil.c:1076 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:145 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1307 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:256
+#: plugins/sudoers/testsudoers.c:265 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:164 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1095
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1320
+msgid "unable to allocate memory"
+msgstr "не удаётся выделить память"
+
+#: gram.y:624
+msgid "a digest requires a path name"
+msgstr "для контрольной суммы нужно указать полный путь"
+
+#: gram.y:646
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "значения «CWD» должны начинаться с «/», «~» или «*»"
+
+#: gram.y:652
+msgid "\"CWD\" path too long"
+msgstr "Слишком длинный путь «CWD»"
+
+#: gram.y:662
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "значения «CHROOT» должны начинаться с «/», «~» или «*»"
+
+#: gram.y:668
+msgid "\"CHROOT\" path too long"
+msgstr "Слишком длинный путь «CHROOT»"
+
+#: gram.y:817
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "ошибка синтаксиса, зарезервированное слово %s используется в качестве псевдонима"
+
+#: gram.y:840
+msgid "invalid notbefore value"
+msgstr "некорректное значение notbefore"
+
+#: gram.y:849
+msgid "invalid notafter value"
+msgstr "некорректное значение notafter"
+
+#: gram.y:859 plugins/sudoers/policy.c:390
+msgid "timeout value too large"
+msgstr "время ожидания слишком велико"
+
+#: gram.y:861 plugins/sudoers/policy.c:392
+msgid "invalid timeout value"
+msgstr "некорректное время ожидания"
+
+#: gram.y:982 plugins/sudoers/sudoers.c:1162
+msgid "command too long"
+msgstr "слишком длинная команда"
+
+#: gram.y:1016
+msgid "expected a fully-qualified path name"
+msgstr "ожидался полный путь"
+
+#: gram.y:1261
+#, c-format
+msgid "%s:%d:%zu: %s\n"
+msgstr "%s:%d:%zu: %s\n"
+
+#: gram.y:1315
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Псевдоним «%s» уже определён"
+
+#: gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:765 lib/eventlog/eventlog.c:838
+#: lib/eventlog/eventlog.c:841 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:483
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:232
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:174
+#: logsrvd/iolog_writer.c:184 logsrvd/iolog_writer.c:197
+#: logsrvd/iolog_writer.c:217 logsrvd/iolog_writer.c:227
+#: logsrvd/iolog_writer.c:246 logsrvd/iolog_writer.c:256
+#: logsrvd/iolog_writer.c:267 logsrvd/iolog_writer.c:277
+#: logsrvd/iolog_writer.c:289 logsrvd/iolog_writer.c:299
+#: logsrvd/iolog_writer.c:309 logsrvd/iolog_writer.c:319
+#: logsrvd/iolog_writer.c:329 logsrvd/iolog_writer.c:341
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:530
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:668
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:1131
+#: logsrvd/logsrvd.c:1446 logsrvd/logsrvd.c:1453 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:649
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1742
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:125
+#: logsrvd/logsrvd_journal.c:216 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:250 logsrvd/logsrvd_journal.c:258
+#: logsrvd/logsrvd_journal.c:287 logsrvd/logsrvd_journal.c:291
+#: logsrvd/logsrvd_journal.c:439 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:278 logsrvd/logsrvd_local.c:468
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:493
+#: logsrvd/logsrvd_queue.c:158 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/sendlog.c:256 logsrvd/sendlog.c:265
+#: logsrvd/sendlog.c:297 logsrvd/sendlog.c:303 logsrvd/sendlog.c:352
+#: logsrvd/sendlog.c:630 logsrvd/sendlog.c:1523 logsrvd/sendlog.c:1530
+#: logsrvd/sendlog.c:1753 logsrvd/sendlog.c:1822 logsrvd/tls_init.c:305
+#: logsrvd/tls_init.c:329 logsrvd/tls_init.c:340 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/pam.c:518 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/canon_path.c:129
+#: plugins/sudoers/canon_path.c:161 plugins/sudoers/check_aliases.c:128
+#: plugins/sudoers/check_util.c:56 plugins/sudoers/check_util.c:84
+#: plugins/sudoers/cvtsudoers.c:132 plugins/sudoers/cvtsudoers.c:175
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:203
+#: plugins/sudoers/cvtsudoers.c:337 plugins/sudoers/cvtsudoers.c:544
+#: plugins/sudoers/cvtsudoers.c:697 plugins/sudoers/cvtsudoers.c:715
+#: plugins/sudoers/cvtsudoers.c:891 plugins/sudoers/cvtsudoers.c:898
+#: plugins/sudoers/cvtsudoers.c:1395 plugins/sudoers/cvtsudoers.c:1399
+#: plugins/sudoers/cvtsudoers.c:1501 plugins/sudoers/cvtsudoers_csv.c:182
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:151 plugins/sudoers/cvtsudoers_ldif.c:194
+#: plugins/sudoers/cvtsudoers_ldif.c:235 plugins/sudoers/cvtsudoers_ldif.c:301
+#: plugins/sudoers/cvtsudoers_ldif.c:377 plugins/sudoers/cvtsudoers_ldif.c:431
+#: plugins/sudoers/cvtsudoers_ldif.c:439 plugins/sudoers/cvtsudoers_ldif.c:450
+#: plugins/sudoers/cvtsudoers_ldif.c:457 plugins/sudoers/cvtsudoers_ldif.c:469
+#: plugins/sudoers/cvtsudoers_ldif.c:482 plugins/sudoers/cvtsudoers_ldif.c:490
+#: plugins/sudoers/cvtsudoers_ldif.c:637 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51 plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1157
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:211
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:693 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:293 plugins/sudoers/ldap_util.c:300
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:228
+#: plugins/sudoers/log_client.c:250 plugins/sudoers/log_client.c:264
+#: plugins/sudoers/log_client.c:402 plugins/sudoers/log_client.c:717
+#: plugins/sudoers/log_client.c:739 plugins/sudoers/log_client.c:744
+#: plugins/sudoers/log_client.c:1426 plugins/sudoers/log_client.c:1547
+#: plugins/sudoers/log_client.c:1670 plugins/sudoers/log_client.c:1993
+#: plugins/sudoers/log_client.c:2052 plugins/sudoers/logging.c:110
+#: plugins/sudoers/logging.c:189 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:755 plugins/sudoers/logging.c:872
+#: plugins/sudoers/logging.c:925 plugins/sudoers/logging.c:932
+#: plugins/sudoers/lookup.c:337 plugins/sudoers/lookup.c:354
+#: plugins/sudoers/lookup.c:373 plugins/sudoers/lookup.c:392
+#: plugins/sudoers/lookup.c:409 plugins/sudoers/lookup.c:432
+#: plugins/sudoers/lookup.c:443 plugins/sudoers/match_command.c:301
+#: plugins/sudoers/match_command.c:573 plugins/sudoers/match_command.c:640
+#: plugins/sudoers/match_command.c:737 plugins/sudoers/match_command.c:784
+#: plugins/sudoers/match_digest.c:88 plugins/sudoers/parse_ldif.c:152
+#: plugins/sudoers/parse_ldif.c:183 plugins/sudoers/parse_ldif.c:252
+#: plugins/sudoers/parse_ldif.c:260 plugins/sudoers/parse_ldif.c:265
+#: plugins/sudoers/parse_ldif.c:341 plugins/sudoers/parse_ldif.c:352
+#: plugins/sudoers/parse_ldif.c:379 plugins/sudoers/parse_ldif.c:396
+#: plugins/sudoers/parse_ldif.c:408 plugins/sudoers/parse_ldif.c:412
+#: plugins/sudoers/parse_ldif.c:426 plugins/sudoers/parse_ldif.c:484
+#: plugins/sudoers/parse_ldif.c:595 plugins/sudoers/parse_ldif.c:624
+#: plugins/sudoers/parse_ldif.c:649 plugins/sudoers/parse_ldif.c:707
+#: plugins/sudoers/parse_ldif.c:724 plugins/sudoers/parse_ldif.c:752
+#: plugins/sudoers/parse_ldif.c:759 plugins/sudoers/policy.c:157
+#: plugins/sudoers/policy.c:166 plugins/sudoers/policy.c:175
+#: plugins/sudoers/policy.c:204 plugins/sudoers/policy.c:374
+#: plugins/sudoers/policy.c:390 plugins/sudoers/policy.c:392
+#: plugins/sudoers/policy.c:430 plugins/sudoers/policy.c:439
+#: plugins/sudoers/policy.c:448 plugins/sudoers/policy.c:457
+#: plugins/sudoers/policy.c:493 plugins/sudoers/policy.c:502
+#: plugins/sudoers/policy.c:511 plugins/sudoers/policy.c:520
+#: plugins/sudoers/policy.c:529 plugins/sudoers/policy.c:538
+#: plugins/sudoers/policy.c:547 plugins/sudoers/policy.c:646
+#: plugins/sudoers/policy.c:1061 plugins/sudoers/prompt.c:94
+#: plugins/sudoers/pwutil.c:219 plugins/sudoers/pwutil.c:290
+#: plugins/sudoers/pwutil.c:368 plugins/sudoers/pwutil.c:542
+#: plugins/sudoers/pwutil.c:607 plugins/sudoers/pwutil.c:679
+#: plugins/sudoers/pwutil.c:877 plugins/sudoers/pwutil.c:967
+#: plugins/sudoers/pwutil.c:1015 plugins/sudoers/pwutil.c:1076
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1306 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:255
+#: plugins/sudoers/testsudoers.c:264 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:163 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1094
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1309 toke.l:1320
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:304
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "не удаётся дублировать стандартный ввод: %m"
+
+#: lib/eventlog/eventlog.c:346
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "не удаётся выполнить %s: %m"
+
+#: lib/eventlog/eventlog.c:394 plugins/sudoers/auth/aix_auth.c:199
+msgid "unable to fork"
+msgstr "не удаётся разветвить процесс"
+
+#: lib/eventlog/eventlog.c:404 lib/eventlog/eventlog.c:471
+#, c-format
+msgid "unable to fork: %m"
+msgstr "не удаётся разветвить процесс: %m"
+
+#: lib/eventlog/eventlog.c:461
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "не удаётся открыть канал: %m"
+
+#: lib/eventlog/eventlog.c:1000
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:1029
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (выполнение команды продолжено) %s"
+
+#: lib/eventlog/parse_json.c:175
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "ожидался JSON_STRING, получен %d"
+
+#: lib/eventlog/parse_json.c:180
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY слишком велик"
+
+#: lib/eventlog/parse_json.c:506
+msgid "missing double quote in name"
+msgstr "пропущены двойные кавычки в названии"
+
+#: lib/eventlog/parse_json.c:624
+msgid "missing JSON_OBJECT"
+msgstr "пропущен JSON_OBJECT"
+
+#: lib/eventlog/parse_json.c:628
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "ожидался JSON_OBJECT, получен %d"
+
+#: lib/eventlog/parse_json.c:762
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "исчерпан стек json (не больше %u кадров)"
+
+#: lib/eventlog/parse_json.c:840
+msgid "objects must consist of name:value pairs"
+msgstr "объекты должны состоять из пар «название:значение»"
+
+#: lib/eventlog/parse_json.c:845 lib/eventlog/parse_json.c:876
+#: lib/eventlog/parse_json.c:920 lib/eventlog/parse_json.c:942
+#: lib/eventlog/parse_json.c:964 lib/eventlog/parse_json.c:986
+#: lib/eventlog/parse_json.c:1008
+msgid "missing separator between values"
+msgstr "пропущен разделитель между значениями"
+
+#: lib/eventlog/parse_json.c:860 lib/eventlog/parse_json.c:1034
+msgid "unmatched close brace"
+msgstr "закрывающая фигурная скобка без открывающей"
+
+#: lib/eventlog/parse_json.c:871
+msgid "unexpected array"
+msgstr "неожиданный массив"
+
+#: lib/eventlog/parse_json.c:891 lib/eventlog/parse_json.c:1037
+msgid "unmatched close bracket"
+msgstr "закрывающая скобка без открывающей"
+
+#: lib/eventlog/parse_json.c:902
+msgid "unexpected string"
+msgstr "неожиданная строка"
+
+#: lib/eventlog/parse_json.c:913
+msgid "missing colon after name"
+msgstr "пропущено двоеточие после названия"
+
+#: lib/eventlog/parse_json.c:934 lib/eventlog/parse_json.c:956
+msgid "unexpected boolean"
+msgstr "неожиданное булево значение"
+
+#: lib/eventlog/parse_json.c:978
+msgid "unexpected null"
+msgstr "неожиданный null"
+
+#: lib/eventlog/parse_json.c:999
+msgid "unexpected number"
+msgstr "неожиданное число"
+
+#: lib/eventlog/parse_json.c:1045
+msgid "parse error"
+msgstr "ошибка разбора"
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1290
+#: plugins/sudoers/sudoreplay.c:1291 plugins/sudoers/sudoreplay.c:1587
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr "некорректное регулярное выражение «%s»: %s"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: некорректный файл журнала"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: пропущена метка времени"
+
+#: lib/iolog/iolog_legacy.c:90
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: метка времени %s: %s"
+
+#: lib/iolog/iolog_legacy.c:97
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: не указано имя пользователя"
+
+#: lib/iolog/iolog_legacy.c:108
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: не указано имя пользователя, от которого производить выполнение (runas)"
+
+#: lib/iolog/iolog_legacy.c:119
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: не указано имя группы, от которой производить выполнение (runas)"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s существует, но не является каталогом (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:124 lib/iolog/iolog_mkdtemp.c:80
+#: logsrvd/iolog_writer.c:795 plugins/sudoers/timestamp.c:218
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "не удаётся создать каталог %s"
+
+#: lib/iolog/iolog_mkdtemp.c:85 plugins/sudoers/visudo.c:769
+#: plugins/sudoers/visudo.c:803 plugins/sudoers/visudo.c:809
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "не удаётся изменить режим доступа к %s на 0%o"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "не удаётся прочитать файл временных меток: %s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "некорректная строка в файле временных меток: %s"
+
+#: logsrvd/iolog_writer.c:65
+#, c-format
+msgid "%s: protocol error: NULL key"
+msgstr "%s: ошибка протокола: ключ NULL"
+
+#: logsrvd/iolog_writer.c:69
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s: ошибка протокола: некорректный тип для %s"
+
+#: logsrvd/iolog_writer.c:74 logsrvd/logsrvd_local.c:109
+#: logsrvd/logsrvd_local.c:123 logsrvd/logsrvd_local.c:131
+#: logsrvd/logsrvd_local.c:149
+#, c-format
+msgid "%s: protocol error: NULL value found in %s"
+msgstr "%s: ошибка протокола: значение NULL встречено в %s"
+
+#: logsrvd/iolog_writer.c:141 plugins/sudoers/logging.c:1024
+#: plugins/sudoers/policy.c:613
+msgid "unable to generate UUID"
+msgstr "не удаётся создать UUID"
+
+#: logsrvd/iolog_writer.c:354 logsrvd/iolog_writer.c:359
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:369
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s: ошибка протокола: %s отсутствует в AcceptMessage"
+
+#: logsrvd/iolog_writer.c:430
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s: не удаётся выполнить форматирование идентификатора сеанса"
+
+#: logsrvd/iolog_writer.c:444 logsrvd/iolog_writer.c:458
+#: logsrvd/iolog_writer.c:472 logsrvd/iolog_writer.c:487
+#: logsrvd/iolog_writer.c:501 logsrvd/iolog_writer.c:515
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s: %s не указан"
+
+#: logsrvd/iolog_writer.c:551 logsrvd/iolog_writer.c:558
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr "не удаётся развернуть путь журнала ввода-вывода %s"
+
+#: logsrvd/iolog_writer.c:576
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr "не удаётся создать путь к журналу ввода-вывода %s"
+
+#: logsrvd/iolog_writer.c:606
+#, c-format
+msgid "invalid iofd %d"
+msgstr "некорректный дескриптор файла ввода-вывода %d"
+
+#: logsrvd/iolog_writer.c:626
+#, c-format
+msgid "error closing iofd %u: %s"
+msgstr "ошибка при закрытии дескриптора файла ввода-вывода %u: %s"
+
+#: logsrvd/iolog_writer.c:647
+#, c-format
+msgid "error flushing iofd %u: %s"
+msgstr "ошибка при сбросе дескриптора файла ввода-вывода %u: %s"
+
+#: logsrvd/iolog_writer.c:765
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "некорректный журнал ввода-вывода %s: есть ссылки на %s, но сама запись отсутствует"
+
+#: logsrvd/iolog_writer.c:777 logsrvd/logsrvd_journal.c:391
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "%s: не удаётся найти точку восстановления [%lld, %ld]"
+
+#: logsrvd/iolog_writer.c:799 logsrvd/logsrvd_journal.c:434
+#: logsrvd/logsrvd_queue.c:115 logsrvd/tls_init.c:256
+#: plugins/sudoers/check.c:285 plugins/sudoers/cvtsudoers.c:758
+#: plugins/sudoers/cvtsudoers.c:780 plugins/sudoers/cvtsudoers.c:1461
+#: plugins/sudoers/cvtsudoers_csv.c:697 plugins/sudoers/cvtsudoers_json.c:902
+#: plugins/sudoers/cvtsudoers_ldif.c:711 plugins/sudoers/sudoers.c:1291
+#: plugins/sudoers/sudoers.c:1317 plugins/sudoers/sudoreplay.c:1497
+#: plugins/sudoers/timestamp.c:478 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:990
+#, c-format
+msgid "unable to open %s"
+msgstr "не удаётся открыть %s"
+
+#: logsrvd/iolog_writer.c:811 logsrvd/logsrv_util.c:111
+#: logsrvd/logsrv_util.c:118 plugins/sudoers/sudoreplay.c:355
+#: plugins/sudoers/sudoreplay.c:361
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "не удаётся открыть %s/%s"
+
+#: logsrvd/iolog_writer.c:824
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "не удаётся скопировать %s/%s в %s/%s: %s"
+
+#: logsrvd/iolog_writer.c:853 logsrvd/logsrvd_journal.c:198
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "не удаётся переименовать %s в %s"
+
+#: logsrvd/logsrv_util.c:153 logsrvd/logsrv_util.c:182
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s: не удаётся найти точку восстановления [%lld, %ld]"
+
+#: logsrvd/logsrv_util.c:165
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "отсутствует файл журнала ввода-вывода %s/%s"
+
+#: logsrvd/logsrv_util.c:172
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s: не удаётся изменить позицию вперёд на %zu"
+
+#: logsrvd/logsrvd.c:271 logsrvd/logsrvd_queue.c:135
+msgid "unable to connect to relay"
+msgstr "не удаётся связаться с ретранслятором"
+
+#: logsrvd/logsrvd.c:338 logsrvd/logsrvd_relay.c:847
+#, c-format
+msgid "server message too large: %zu"
+msgstr "сообщение сервера слишком велико: %zu"
+
+#: logsrvd/logsrvd.c:430 logsrvd/logsrvd.c:553 logsrvd/logsrvd.c:639
+#: logsrvd/logsrvd.c:881 logsrvd/logsrvd.c:895 logsrvd/logsrvd.c:1056
+#: logsrvd/logsrvd.c:1181 logsrvd/logsrvd.c:1354 logsrvd/logsrvd.c:1372
+#: logsrvd/logsrvd.c:1471 logsrvd/logsrvd.c:1596 logsrvd/logsrvd.c:1783
+#: logsrvd/logsrvd_journal.c:503 logsrvd/logsrvd_local.c:238
+#: logsrvd/logsrvd_queue.c:164 logsrvd/logsrvd_relay.c:172
+#: logsrvd/logsrvd_relay.c:249 logsrvd/logsrvd_relay.c:253
+#: logsrvd/logsrvd_relay.c:391 logsrvd/logsrvd_relay.c:583
+#: logsrvd/logsrvd_relay.c:747 logsrvd/logsrvd_relay.c:1137
+#: logsrvd/sendlog.c:1308 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:216 plugins/sudoers/audit.c:281
+#: plugins/sudoers/iolog.c:1041 plugins/sudoers/iolog.c:1175
+#: plugins/sudoers/iolog.c:1274 plugins/sudoers/log_client.c:121
+#: plugins/sudoers/log_client.c:343 plugins/sudoers/log_client.c:359
+#: plugins/sudoers/log_client.c:407 plugins/sudoers/log_client.c:613
+#: plugins/sudoers/log_client.c:620 plugins/sudoers/log_client.c:1114
+#: plugins/sudoers/log_client.c:1395 plugins/sudoers/log_client.c:1436
+#: plugins/sudoers/log_client.c:1444 plugins/sudoers/log_client.c:1603
+#: plugins/sudoers/log_client.c:1728 plugins/sudoers/log_client.c:2060
+#: plugins/sudoers/log_client.c:2068 plugins/sudoers/logging.c:148
+#: plugins/sudoers/logging.c:206 plugins/sudoers/sudoreplay.c:519
+#: plugins/sudoers/sudoreplay.c:566 plugins/sudoers/sudoreplay.c:808
+#: plugins/sudoers/sudoreplay.c:920 plugins/sudoers/sudoreplay.c:1011
+#: plugins/sudoers/sudoreplay.c:1026 plugins/sudoers/sudoreplay.c:1033
+#: plugins/sudoers/sudoreplay.c:1040 plugins/sudoers/sudoreplay.c:1047
+#: plugins/sudoers/sudoreplay.c:1054 plugins/sudoers/sudoreplay.c:1182
+msgid "unable to add event to queue"
+msgstr "не удаётся добавить событие в очередь"
+
+#: logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:491 logsrvd/logsrvd.c:523
+#: logsrvd/logsrvd.c:577 logsrvd/logsrvd.c:656 logsrvd/logsrvd.c:692
+#: logsrvd/logsrvd.c:728 logsrvd/logsrvd.c:764 logsrvd/logsrvd_relay.c:512
+#: logsrvd/logsrvd_relay.c:545
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr "неожиданный статус %d для %s"
+
+#: logsrvd/logsrvd.c:455 logsrvd/logsrvd.c:492 logsrvd/logsrvd.c:524
+#: logsrvd/logsrvd.c:578 logsrvd/logsrvd.c:657 logsrvd/logsrvd.c:693
+#: logsrvd/logsrvd.c:729 logsrvd/logsrvd.c:765 logsrvd/logsrvd_relay.c:514
+#: logsrvd/logsrvd_relay.c:547
+msgid "state machine error"
+msgstr "ошибка конечного автомата"
+
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:462
+msgid "invalid AcceptMessage"
+msgstr "некорректный AcceptMessage"
+
+#: logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:499
+msgid "invalid RejectMessage"
+msgstr "некорректный RejectMessage"
+
+#: logsrvd/logsrvd.c:530 logsrvd/logsrvd.c:531
+msgid "invalid ExitMessage"
+msgstr "некорректный ExitMessage"
+
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:585
+msgid "invalid RestartMessage"
+msgstr "некорректный RestartMessage"
+
+#: logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:620
+msgid "invalid AlertMessage"
+msgstr "некорректный AlertMessage"
+
+#: logsrvd/logsrvd.c:661 logsrvd/logsrvd.c:697 logsrvd/logsrvd.c:733
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s: неожиданное значение IoBuffer"
+
+#: logsrvd/logsrvd.c:662 logsrvd/logsrvd.c:698 logsrvd/logsrvd.c:734
+msgid "protocol error"
+msgstr "ошибка протокола"
+
+#: logsrvd/logsrvd.c:668 logsrvd/logsrvd.c:669
+msgid "invalid IoBuffer"
+msgstr "некорректный IoBuffer"
+
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:705
+msgid "invalid ChangeWindowSize"
+msgstr "некорректный ChangeWindowSize"
+
+#: logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:741
+msgid "invalid CommandSuspend"
+msgstr "некорректный CommandSuspend"
+
+#: logsrvd/logsrvd.c:790 logsrvd/logsrvd_journal.c:302
+#: logsrvd/logsrvd_relay.c:654 logsrvd/sendlog.c:1207
+#: plugins/sudoers/log_client.c:1593
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "не удаётся распаковать %s, размер %zu"
+
+#: logsrvd/logsrvd.c:835 logsrvd/logsrvd_journal.c:376
+#: logsrvd/logsrvd_relay.c:678
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "неожиданное значение type_case %d в %s из %s"
+
+#: logsrvd/logsrvd.c:837
+msgid "unrecognized ClientMessage type"
+msgstr "неизвестный тип ClientMessage"
+
+#: logsrvd/logsrvd.c:927
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "истекло время ожидания записи клиенту %s"
+
+#: logsrvd/logsrvd.c:932 logsrvd/logsrvd_relay.c:919 logsrvd/sendlog.c:1413
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr "пропущен буфер записи для клиента %s"
+
+#: logsrvd/logsrvd.c:1027
+#, c-format
+msgid "timed out reading from client %s"
+msgstr "истекло время ожидания от клиента %s"
+
+#: logsrvd/logsrvd.c:1068 logsrvd/logsrvd_relay.c:782
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr "EOF от %s без корректного завершения сеанса TLS"
+
+#: logsrvd/logsrvd.c:1112 logsrvd/logsrvd_relay.c:205 logsrvd/sendlog.c:336
+#: plugins/sudoers/log_client.c:723
+#, c-format
+msgid "client message too large: %zu"
+msgstr "сообщение клиента слишком велико: %zu"
+
+#: logsrvd/logsrvd.c:1113 logsrvd/logsrvd_journal.c:259
+#: logsrvd/logsrvd_journal.c:260
+msgid "client message too large"
+msgstr "сообщение клиента слишком велико"
+
+#: logsrvd/logsrvd.c:1131 logsrvd/logsrvd.c:1132
+msgid "invalid ClientMessage"
+msgstr "некорректный ClientMessage"
+
+#: logsrvd/logsrvd.c:1432
+msgid "unable to get remote IP addr"
+msgstr "не удаётся получить удалённый IP-адрес"
+
+#: logsrvd/logsrvd.c:1463 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:281
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "Не удаётся присоединить данные пользователя к SSL-объекту: %s"
+
+#: logsrvd/logsrvd.c:1646 logsrvd/logsrvd.c:2007
+msgid "unable to setup listen socket"
+msgstr "не удаётся настроить слушающий сокет"
+
+#: logsrvd/logsrvd.c:1766
+#, c-format
+msgid "unexpected signal %d"
+msgstr "неожиданный сигнал %d"
+
+#: logsrvd/logsrvd.c:1909
+msgid "sudo log server"
+msgstr "сервер журнала sudo"
+
+#: logsrvd/logsrvd.c:1911 logsrvd/sendlog.c:126
+msgid "Options:"
+msgstr "Параметры:"
+
+#: logsrvd/logsrvd.c:1913
+msgid "path to configuration file"
+msgstr "путь к файлу конфигурации"
+
+#: logsrvd/logsrvd.c:1915 logsrvd/sendlog.c:128
+msgid "display help message and exit"
+msgstr "показать справку и выйти"
+
+#: logsrvd/logsrvd.c:1917
+msgid "do not fork, run in the foreground"
+msgstr "не переходить в фоновый режим"
+
+#: logsrvd/logsrvd.c:1919
+msgid "percent chance connections will drop"
+msgstr "вероятность разрыва подключений в процентах"
+
+#: logsrvd/logsrvd.c:1921 logsrvd/sendlog.c:158
+msgid "display version information and exit"
+msgstr "показать информацию о версии и выйти"
+
+#: logsrvd/logsrvd.c:1971 logsrvd/sendlog.c:1722
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "Требуется Protobuf-C версии 1.3 или выше"
+
+#: logsrvd/logsrvd.c:1987
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "некорректное значение вероятности сброса: %s"
+
+#: logsrvd/logsrvd.c:1990 logsrvd/sendlog.c:1776
+#: plugins/sudoers/cvtsudoers.c:250 plugins/sudoers/sudoreplay.c:294
+#: plugins/sudoers/visudo.c:181
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s версии %s\n"
+
+#: logsrvd/logsrvd_conf.c:422 plugins/sudoers/check.c:69
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/sudoers.c:419 plugins/sudoers/sudoers.c:929
+#: plugins/sudoers/sudoers.c:1034 plugins/sudoers/sudoers.c:1424
+#: plugins/sudoers/testsudoers.c:169 plugins/sudoers/testsudoers.c:285
+#: plugins/sudoers/testsudoers.c:459
+#, c-format
+msgid "unknown user %s"
+msgstr "неизвестный пользователь %s"
+
+#: logsrvd/logsrvd_conf.c:439 plugins/sudoers/iolog.c:148
+#: plugins/sudoers/sudoers.c:425 plugins/sudoers/sudoers.c:1458
+#: plugins/sudoers/testsudoers.c:483
+#, c-format
+msgid "unknown group %s"
+msgstr "неизвестная группа %s"
+
+#: logsrvd/logsrvd_conf.c:457
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr "не удаётся разобрать режим журнала ввода-вывода %s"
+
+#: logsrvd/logsrvd_conf.c:474 logsrvd/logsrvd_conf.c:1243
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "некорректное значение для %s: %s"
+
+#: logsrvd/logsrvd_conf.c:527
+msgid "TLS not supported"
+msgstr "TLS не поддерживается"
+
+#: logsrvd/logsrvd_conf.c:549
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:622 logsrvd/logsrvd_conf.c:1032
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s: не является полным путём"
+
+#: logsrvd/logsrvd_conf.c:951 logsrvd/logsrvd_conf.c:967
+#: logsrvd/logsrvd_conf.c:1676
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "неизвестная возможность syslog %s"
+
+#: logsrvd/logsrvd_conf.c:983 logsrvd/logsrvd_conf.c:999
+#: logsrvd/logsrvd_conf.c:1015 logsrvd/logsrvd_conf.c:1680
+#: logsrvd/logsrvd_conf.c:1684 logsrvd/logsrvd_conf.c:1688
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "неизвестный приоритет syslog %s"
+
+#: logsrvd/logsrvd_conf.c:1197
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d «[» без парной скобки: %s"
+
+#: logsrvd/logsrvd_conf.c:1203
+#, c-format
+msgid "%s:%d garbage after ']': %s"
+msgstr "%s:%d мусор после «]»: %s"
+
+#: logsrvd/logsrvd_conf.c:1215
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s:%d некорректный раздел настроек: %s"
+
+#: logsrvd/logsrvd_conf.c:1223
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d некорректная строка настроек: %s"
+
+#: logsrvd/logsrvd_conf.c:1229
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d ожидалось имя раздела: %s"
+
+#: logsrvd/logsrvd_conf.c:1251
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] недопустимый ключ: %s"
+
+#: logsrvd/logsrvd_conf.c:1281 plugins/sudoers/cvtsudoers.c:273
+#: plugins/sudoers/logging.c:1076
+#, c-format
+msgid "unable to open log file %s"
+msgstr "не удаётся открыть файл журнала %s"
+
+#: logsrvd/logsrvd_conf.c:1763
+msgid "unable to initialize server TLS context"
+msgstr "не удаётся инициализировать контекст сервера TLS"
+
+#: logsrvd/logsrvd_conf.c:1783
+msgid "unable to initialize relay TLS context"
+msgstr "не удаётся инициализировать контекст ретранслятора TLS"
+
+#: logsrvd/logsrvd_journal.c:149 logsrvd/logsrvd_journal.c:430
+#: logsrvd/logsrvd_journal.c:435
+msgid "unable to create journal file"
+msgstr "не удаётся создать файл журнала"
+
+#: logsrvd/logsrvd_journal.c:153 logsrvd/logsrvd_queue.c:109
+#: plugins/sudoers/visudo.c:1046
+#, c-format
+msgid "unable to lock %s"
+msgstr "не удаётся заблокировать %s"
+
+#: logsrvd/logsrvd_journal.c:156
+msgid "unable to lock journal file"
+msgstr "не удаётся заблокировать файл журнала"
+
+#: logsrvd/logsrvd_journal.c:164
+msgid "unable to open journal file"
+msgstr "не удаётся открыть файл журнала"
+
+#: logsrvd/logsrvd_journal.c:185 logsrvd/logsrvd_journal.c:466
+#: logsrvd/logsrvd_journal.c:471
+msgid "unable to write journal file"
+msgstr "не удаётся записать файл журнала"
+
+#: logsrvd/logsrvd_journal.c:193 logsrvd/logsrvd_journal.c:200
+msgid "unable to rename journal file"
+msgstr "не удаётся переименовать файл журнала"
+
+#: logsrvd/logsrvd_journal.c:247 logsrvd/logsrvd_journal.c:248
+#: logsrvd/logsrvd_journal.c:288 logsrvd/logsrvd_journal.c:289
+msgid "unexpected EOF reading journal file"
+msgstr "неожиданный EOF в процессе чтения файла журнала"
+
+#: logsrvd/logsrvd_journal.c:251 logsrvd/logsrvd_journal.c:252
+#: logsrvd/logsrvd_journal.c:292 logsrvd/logsrvd_journal.c:293
+msgid "error reading journal file"
+msgstr "ошибка чтения файла журнала"
+
+#: logsrvd/logsrvd_journal.c:304 logsrvd/logsrvd_journal.c:390
+msgid "invalid journal file, unable to restart"
+msgstr "некорректный файл журнала, не удаётся перезапустить"
+
+#: logsrvd/logsrvd_journal.c:449
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "невозможно найти [%lld, %ld] в файле журнала %s"
+
+#: logsrvd/logsrvd_local.c:166
+#, c-format
+msgid "unexpected value_case %d in %s from %s"
+msgstr "неожиданное значение value_case %d в %s из %s"
+
+#: logsrvd/logsrvd_local.c:194
+msgid "error parsing AcceptMessage"
+msgstr "ошибка разбора AcceptMessage"
+
+#: logsrvd/logsrvd_local.c:205
+msgid "error creating I/O log"
+msgstr "ошибка создания журнала ввода-вывода"
+
+#: logsrvd/logsrvd_local.c:228
+msgid "error logging accept event"
+msgstr "ошибка при записи события подтверждения в журнал"
+
+#: logsrvd/logsrvd_local.c:267
+msgid "error parsing RejectMessage"
+msgstr "ошибка разбора RejectMessage"
+
+#: logsrvd/logsrvd_local.c:291
+msgid "error logging reject event"
+msgstr "ошибка при записи события отклонения в журнал"
+
+#: logsrvd/logsrvd_local.c:427 logsrvd/logsrvd_local.c:437
+msgid "error logging exit event"
+msgstr "ошибка при записи события выхода в журнал"
+
+#: logsrvd/logsrvd_local.c:494 logsrvd/logsrvd_local.c:495
+msgid "log is already complete, cannot be restarted"
+msgstr "журнал уже завершён и не может быть перезапущен"
+
+#: logsrvd/logsrvd_local.c:525
+msgid "unable to restart log"
+msgstr "не удаётся перезапустить журнал"
+
+#: logsrvd/logsrvd_local.c:541
+msgid "error parsing AlertMessage"
+msgstr "ошибка разбора AlertMessage"
+
+#: logsrvd/logsrvd_local.c:551
+msgid "error logging alert event"
+msgstr "ошибка при записи события критического уведомления в журнал"
+
+#: logsrvd/logsrvd_local.c:587 logsrvd/logsrvd_local.c:650
+#: logsrvd/logsrvd_local.c:685
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr "невозможно отформатировать буфер часовых отметок, длина %d"
+
+#: logsrvd/logsrvd_local.c:601 logsrvd/logsrvd_local.c:609
+#: logsrvd/logsrvd_local.c:657 logsrvd/logsrvd_local.c:692
+#: plugins/sudoers/sudoreplay.c:344 toke.l:981 toke.l:984
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: logsrvd/logsrvd_local.c:620
+msgid "randomly dropping connection"
+msgstr "случайный сброс соединения"
+
+#: logsrvd/logsrvd_local.c:632
+msgid "error writing IoBuffer"
+msgstr "ошибка записи IoBuffer"
+
+#: logsrvd/logsrvd_local.c:667
+msgid "error writing ChangeWindowSize"
+msgstr "ошибка записи ChangeWindowSize"
+
+#: logsrvd/logsrvd_local.c:702
+msgid "error writing CommandSuspend"
+msgstr "ошибка записи CommandSuspend"
+
+#: logsrvd/logsrvd_relay.c:437
+msgid "TLS handshake with relay host failed"
+msgstr "Не удаётся согласовать TLS-подключение с узлом ретранслятора"
+
+#: logsrvd/logsrvd_relay.c:465
+msgid "unable to connect to relay host"
+msgstr "не удаётся связаться с узлом ретранслятора"
+
+#: logsrvd/logsrvd_relay.c:520
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s: некорректный ServerHello, отсутствует server_id"
+
+#: logsrvd/logsrvd_relay.c:522 logsrvd/sendlog.c:1111
+#: plugins/sudoers/log_client.c:1479
+msgid "invalid ServerHello"
+msgstr "некорректный ServerHello"
+
+#: logsrvd/logsrvd_relay.c:681
+msgid "unrecognized ServerMessage type"
+msgstr "нераспознанный тип ServerMessage"
+
+#: logsrvd/logsrvd_relay.c:710
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr "превышено время ожидания чтения от ретранслятора %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:712
+msgid "timeout reading from relay"
+msgstr "превышено время ожидания чтения от ретранслятора"
+
+#: logsrvd/logsrvd_relay.c:767
+msgid "relay host name does not match certificate"
+msgstr "имя узла ретранслятора не соответствует сертификату"
+
+#: logsrvd/logsrvd_relay.c:773 logsrvd/logsrvd_relay.c:787
+#: logsrvd/logsrvd_relay.c:794
+msgid "error reading from relay"
+msgstr "ошибка чтения от ретранслятора"
+
+#: logsrvd/logsrvd_relay.c:815
+msgid "unable to read from relay"
+msgstr "не удаётся прочитать данные от ретранслятора"
+
+#: logsrvd/logsrvd_relay.c:830 logsrvd/logsrvd_relay.c:949
+msgid "relay server closed connection"
+msgstr "сервер ретранслятора закрыл подключение"
+
+#: logsrvd/logsrvd_relay.c:848
+msgid "server message too large"
+msgstr "сообщение сервера слишком большое"
+
+#: logsrvd/logsrvd_relay.c:912
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr "превышено время ожидания записи данных ретранслятору %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:914
+msgid "timeout writing to relay"
+msgstr "превышено время ожидания записи данных ретранслятору"
+
+#: logsrvd/logsrvd_relay.c:968 logsrvd/logsrvd_relay.c:975
+#: logsrvd/logsrvd_relay.c:987
+msgid "error writing to relay"
+msgstr "ошибка записи данных ретранслятору"
+
+#: logsrvd/sendlog.c:124
+msgid "send sudo I/O log to remote server"
+msgstr "отправка журнала ввода/вывода sudo на удалённый сервер"
+
+#: logsrvd/sendlog.c:130
+msgid "only send an accept event (no I/O)"
+msgstr "отправлять только событие принятия (без ввода/вывода)"
+
+#: logsrvd/sendlog.c:133
+msgid "certificate bundle file to verify server's cert against"
+msgstr "файл пакета сертификатов для проверки сертификата сервера"
+
+#: logsrvd/sendlog.c:135
+msgid "certificate file for TLS handshake"
+msgstr "файл сертификата для согласования TLS"
+
+#: logsrvd/sendlog.c:138
+msgid "host to send logs to"
+msgstr "узел для отправки журналов"
+
+#: logsrvd/sendlog.c:140
+msgid "remote ID of I/O log to be resumed"
+msgstr "удалённый идентификатор журнала ввода/вывода, который следует продолжить"
+
+#: logsrvd/sendlog.c:143
+msgid "private key file"
+msgstr "файл закрытого ключа"
+
+#: logsrvd/sendlog.c:145
+msgid "do not verify server certificate"
+msgstr "не проверять сертификат сервера"
+
+#: logsrvd/sendlog.c:148
+msgid "port to use when connecting to host"
+msgstr "порт, используемый при подключении к узлу"
+
+#: logsrvd/sendlog.c:150
+msgid "restart previous I/O log transfer"
+msgstr "перезапустить предыдущую передачу журнала ввода/вывода"
+
+#: logsrvd/sendlog.c:152
+msgid "reject the command with the given reason"
+msgstr "отклонить команду по заданной причине"
+
+#: logsrvd/sendlog.c:154
+msgid "stop transfer after reaching this time"
+msgstr "остановить отправку по достижению этого времени"
+
+#: logsrvd/sendlog.c:156
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "проверить сервер аудита параллельной отправкой выбранного журнала ввода/вывода n раз"
+
+#: logsrvd/sendlog.c:181 plugins/sudoers/log_client.c:453
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "не удаётся выполнить поиск %s:%s: %s"
+
+#: logsrvd/sendlog.c:219
+msgid "unable to get server IP addr"
+msgstr "не удаётся получить IP-адрес сервера"
+
+#: logsrvd/sendlog.c:314 plugins/sudoers/sudoreplay.c:868
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "не удаётся прочитать %s/%s: %s"
+
+#: logsrvd/sendlog.c:1035 plugins/sudoers/iolog.c:959
+#: plugins/sudoers/iolog.c:1034
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "неожиданное событие ввода-вывода %d"
+
+#: logsrvd/sendlog.c:1088 logsrvd/sendlog.c:1105 logsrvd/sendlog.c:1139
+#: plugins/sudoers/log_client.c:1129 plugins/sudoers/log_client.c:1405
+#: plugins/sudoers/log_client.c:1473 plugins/sudoers/log_client.c:1512
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: неожиданное состояние %d"
+
+#: logsrvd/sendlog.c:1175 plugins/sudoers/log_client.c:1561
+#, c-format
+msgid "error message received from server: %s"
+msgstr "получено уведомление об ошибке от сервера: %s"
+
+#: logsrvd/sendlog.c:1188 plugins/sudoers/log_client.c:1574
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "получено уведомление о прерывании от сервера: %s"
+
+#: logsrvd/sendlog.c:1247 plugins/sudoers/log_client.c:1624
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s: неожиданное значение type_case %d"
+
+#: logsrvd/sendlog.c:1276
+msgid "timeout reading from server"
+msgstr "превышено время ожидания чтения с сервера"
+
+#: logsrvd/sendlog.c:1327 plugins/sudoers/log_client.c:1747
+msgid "host name does not match certificate"
+msgstr "имя узла не соответствует сертификату"
+
+#: logsrvd/sendlog.c:1361
+msgid "premature EOF"
+msgstr "преждевременный EOF"
+
+#: logsrvd/sendlog.c:1374 plugins/sudoers/log_client.c:1795
+#, c-format
+msgid "server message too large: %u"
+msgstr "сообщение сервера слишком большое: %u"
+
+#: logsrvd/sendlog.c:1430
+msgid "timeout writing to server"
+msgstr "превышено время ожидания записи на сервер"
+
+#: logsrvd/sendlog.c:1800
+msgid "both restart point and iolog ID must be specified"
+msgstr "должна быть указана как точка перезапуска, так и идентификатор журнала ввода-вывода"
+
+#: logsrvd/sendlog.c:1804
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "точка перезапуска не может быть установлена, когда не отправляются данные ввода/вывода"
+
+#: logsrvd/sendlog.c:1880
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "преждевременный выход из состояния %d"
+
+#: logsrvd/sendlog.c:1881
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "истёкшее время отправлено на сервер [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1883
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "точка фиксации получена от сервера [%lld, %ld]"
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:315
+msgid "TLS handshake timeout occurred"
+msgstr "время ожидания согласования TLS истекло"
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:337 plugins/sudoers/log_client.c:353
+msgid "unable to set event"
+msgstr "не удаётся назначить событие"
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "Не удаётся установить TLS-подключение: %s"
+
+#: logsrvd/tls_client.c:196
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "не удаётся выделить память под SSL-объект: %s"
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "Не удаётся подключить сокет к объекту SSL: %s"
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr "не удаётся инициализировать контекст TLS"
+
+#: logsrvd/tls_init.c:138 logsrvd/tls_init.c:146
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "не удаётся установить алгоритмы шифрования TLS 1.2 на %s: %s"
+
+#: logsrvd/tls_init.c:166 logsrvd/tls_init.c:174
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "не удаётся установить алгоритмы шифрования TLS 1.3 на %s: %s"
+
+#: logsrvd/tls_init.c:206 logsrvd/tls_init.c:227
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "невозможно установить параметры Диффи-Хеллмана: %s"
+
+#: logsrvd/tls_init.c:283
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "не удаётся создать TLS-контекст: %s"
+
+#: logsrvd/tls_init.c:290
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "не удаётся установить минимальную версию протокола на TLS 1.2: %s"
+
+#: plugins/sudoers/audit.c:272 plugins/sudoers/audit.c:452
+#: plugins/sudoers/log_client.c:962 plugins/sudoers/log_client.c:1011
+#: plugins/sudoers/log_client.c:1060 plugins/sudoers/log_client.c:1185
+#: plugins/sudoers/logging.c:614 plugins/sudoers/logging.c:732
+#: plugins/sudoers/logging.c:859 plugins/sudoers/logging.c:1031
+#: plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr "не удаётся получить время"
+
+#: plugins/sudoers/auth/aix_auth.c:282
+#, c-format
+msgid "unable to change password for %s"
+msgstr "не удаётся изменить пароль для %s"
+
+#: plugins/sudoers/auth/bsdauth.c:78
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "не удаётся получить класс логина для пользователя %s"
+
+#: plugins/sudoers/auth/bsdauth.c:85
+msgid "invalid authentication type"
+msgstr "некорректный тип аутентификации"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to begin BSD authentication"
+msgstr "не удаётся начать BSD-аутентификацию"
+
+#: plugins/sudoers/auth/bsdauth.c:97
+msgid "unable to initialize BSD authentication"
+msgstr "не удаётся запустить BSD-аутентификацию"
+
+#: plugins/sudoers/auth/bsdauth.c:191
+msgid "your account has expired"
+msgstr "срок действия вашего аккаунта истёк"
+
+#: plugins/sudoers/auth/bsdauth.c:193
+msgid "approval failed"
+msgstr "не удаётся подтвердить"
+
+#: plugins/sudoers/auth/fwtk.c:62
+msgid "unable to read fwtk config"
+msgstr "не удаётся прочитать конфигурацию ftwk"
+
+#: plugins/sudoers/auth/fwtk.c:67
+msgid "unable to connect to authentication server"
+msgstr "не удаётся связаться с сервером аутентификации"
+
+#: plugins/sudoers/auth/fwtk.c:73 plugins/sudoers/auth/fwtk.c:99
+#: plugins/sudoers/auth/fwtk.c:131
+msgid "lost connection to authentication server"
+msgstr "потеряно соединение с сервером аутентификации"
+
+#: plugins/sudoers/auth/fwtk.c:77
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"ошибка сервера аутентификации:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:116
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: не удаётся преобразовать регистрационную запись в строку ('%s'): %s"
+
+#: plugins/sudoers/auth/kerb5.c:166
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: не удаётся прочитать '%s': %s"
+
+#: plugins/sudoers/auth/kerb5.c:175
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: не удаётся разрешить кэш учётных данных: %s"
+
+#: plugins/sudoers/auth/kerb5.c:226
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: не удаётся выделить параметры: %s"
+
+#: plugins/sudoers/auth/kerb5.c:241
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: не удаётся получить учётные данные: %s"
+
+#: plugins/sudoers/auth/kerb5.c:254
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: не удаётся инициализировать кэш учётных данных: %s"
+
+#: plugins/sudoers/auth/kerb5.c:257
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: не удаётся сохранить учётные данные в кэше: %s"
+
+#: plugins/sudoers/auth/kerb5.c:322
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: не удаётся получить регистрационную запись узла: %s"
+
+#: plugins/sudoers/auth/kerb5.c:336
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: Не удаётся проверить TGT. Нас атакуют?!: %s"
+
+#: plugins/sudoers/auth/pam.c:233
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "не удаётся инициализировать PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:349
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Ошибка PAM-аутентификации: %s"
+
+#: plugins/sudoers/auth/pam.c:369
+msgid "account validation failure, is your account locked?"
+msgstr "ошибка проверки учётной записи. Она заблокирована?"
+
+#: plugins/sudoers/auth/pam.c:380
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Учётные данные устарели. Сбросьте пароль и попробуйте ещё раз"
+
+#: plugins/sudoers/auth/pam.c:387
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "не удаётся сменить устаревший пароль: %s"
+
+#: plugins/sudoers/auth/pam.c:398
+msgid "Password expired, contact your system administrator"
+msgstr "Пароль устарел. Обратитесь к системному администратору"
+
+#: plugins/sudoers/auth/pam.c:403
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Срок действия учётной записи истёк или в настройках PAM нет раздела «account» для sudo. Обратитесь к системному администратору"
+
+#: plugins/sudoers/auth/pam.c:411 plugins/sudoers/auth/pam.c:416
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "Ошибка управления аккаунтом PAM: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:100 plugins/sudoers/visudo.c:266
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "вы не существуете в базе данных %s"
+
+#: plugins/sudoers/auth/securid5.c:76
+msgid "failed to initialise the ACE API library"
+msgstr "не удаётся инициализировать библиотеку API для ACE"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "unable to contact the SecurID server"
+msgstr "не удаётся связаться с сервером SecurID"
+
+#: plugins/sudoers/auth/securid5.c:117
+msgid "User ID locked for SecurID Authentication"
+msgstr "ID пользователя заблокирован для аутентификации SecurID"
+
+#: plugins/sudoers/auth/securid5.c:121 plugins/sudoers/auth/securid5.c:174
+msgid "invalid username length for SecurID"
+msgstr "некорректная длина имени пользователя для SecurID"
+
+#: plugins/sudoers/auth/securid5.c:125 plugins/sudoers/auth/securid5.c:179
+msgid "invalid Authentication Handle for SecurID"
+msgstr "некорректный обработчик аутентификации для SecurID"
+
+#: plugins/sudoers/auth/securid5.c:129
+msgid "SecurID communication failed"
+msgstr "Ошибка связи с SecurID"
+
+#: plugins/sudoers/auth/securid5.c:133 plugins/sudoers/auth/securid5.c:222
+msgid "unknown SecurID error"
+msgstr "неизвестная ошибка SecurID"
+
+#: plugins/sudoers/auth/securid5.c:169
+msgid "invalid passcode length for SecurID"
+msgstr "некорректная длина пароля для SecurID"
+
+#: plugins/sudoers/auth/sia.c:72 plugins/sudoers/auth/sia.c:130
+msgid "unable to initialize SIA session"
+msgstr "не удаётся инициализировать сеанс SIA"
+
+#: plugins/sudoers/auth/sudo_auth.c:141
+msgid "invalid authentication methods"
+msgstr "некорректные методы аутентификации"
+
+#: plugins/sudoers/auth/sudo_auth.c:143
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Приложение sudo скомпилировано с неверными методами аутентификации. Нельзя смешивать зависимую и независимую аутентификацию."
+
+#: plugins/sudoers/auth/sudo_auth.c:296 plugins/sudoers/auth/sudo_auth.c:359
+msgid "no authentication methods"
+msgstr "методы аутентификации отсутствуют"
+
+#: plugins/sudoers/auth/sudo_auth.c:298
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Приложение sudo скомпилировано без методов аутентификации! Чтобы отключить аутентификацию, используйте параметр --disable-authentication."
+
+#: plugins/sudoers/auth/sudo_auth.c:361
+msgid "Unable to initialize authentication methods."
+msgstr "Не удаётся инициализировать методы аутентификации."
+
+#: plugins/sudoers/auth/sudo_auth.c:551
+msgid "Authentication methods:"
+msgstr "Методы аутентификации:"
+
+#: plugins/sudoers/bsm_audit.c:122 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "Не удаётся определить состояние аудита"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:278
+msgid "unable to commit audit record"
+msgstr "не удаётся отправить запись аудита"
+
+#: plugins/sudoers/check.c:63 plugins/sudoers/check.c:74
+#: plugins/sudoers/lookup.c:79 plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "неизвестный идентификатор пользователя %u"
+
+#: plugins/sudoers/check.c:277
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "ошибка при чтении файла инструкции %s"
+
+#: plugins/sudoers/check.c:280
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "игнорируем файл инструкции %s: не является обычным файлом"
+
+#: plugins/sudoers/check.c:293
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Мы полагаем, что ваш системный администратор изложил вам основы\n"
+"безопасности. Как правило, всё сводится к трём следующим правилам:\n"
+"\n"
+" №1) Уважайте частную жизнь других.\n"
+" №2) Думайте, прежде чем что-то вводить.\n"
+" №3) С большой властью приходит большая ответственность.\n"
+"\n"
+
+#: plugins/sudoers/check.c:301
+msgid ""
+"For security reasons, the password you type will not be visible.\n"
+"\n"
+msgstr ""
+"По соображениям безопасности пароль, который вы введёте, не будет виден.\n"
+"\n"
+
+#: plugins/sudoers/check_aliases.c:93
+#, c-format
+msgid "cycle in %s \"%s\""
+msgstr "цикл в %s «%s»"
+
+#: plugins/sudoers/check_aliases.c:96
+#, c-format
+msgid "%s \"%s\" referenced but not defined"
+msgstr "обнаружены ссылки на %s «%s», который не определён"
+
+#: plugins/sudoers/cvtsudoers.c:211
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "шаг порядка: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:231
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "начальный порядок: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:242
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "дополнение порядка: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:252 plugins/sudoers/visudo.c:183
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s грамматика версии %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:282 plugins/sudoers/testsudoers.c:162
+#, c-format
+msgid "unsupported input format %s"
+msgstr "неподдерживаемый формат ввода %s"
+
+#: plugins/sudoers/cvtsudoers.c:300
+#, c-format
+msgid "unsupported output format %s"
+msgstr "неподдерживаемый формат вывода %s"
+
+#: plugins/sudoers/cvtsudoers.c:392
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: входные и выходные файлы должны отличаться"
+
+#: plugins/sudoers/cvtsudoers.c:406 plugins/sudoers/sudoers.c:151
+#: plugins/sudoers/sudoers.c:209 plugins/sudoers/testsudoers.c:315
+#: plugins/sudoers/visudo.c:276 plugins/sudoers/visudo.c:666
+msgid "unable to initialize sudoers default values"
+msgstr "не удаётся инициализировать значения по умолчанию для sudoers"
+
+#: plugins/sudoers/cvtsudoers.c:533 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:612
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s: неизвестное ключевое слово %s"
+
+#: plugins/sudoers/cvtsudoers.c:658
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "некорректный тип значений по умолчанию: %s"
+
+#: plugins/sudoers/cvtsudoers.c:681
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "некорректный тип подавления: %s"
+
+#: plugins/sudoers/cvtsudoers.c:722 plugins/sudoers/cvtsudoers.c:738
+#, c-format
+msgid "invalid filter: %s"
+msgstr "некорректный фильтр: %s"
+
+#: plugins/sudoers/cvtsudoers.c:783 plugins/sudoers/visudo.c:1000
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "не удаётся разобрать файл %s, неизвестная ошибка"
+
+#: plugins/sudoers/cvtsudoers.c:1508 plugins/sudoers/sudoreplay.c:1143
+#: plugins/sudoers/timestamp.c:353 plugins/sudoers/timestamp.c:356
+#, c-format
+msgid "unable to write to %s"
+msgstr "не удаётся записать в %s"
+
+#: plugins/sudoers/cvtsudoers.c:1536
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s - конвертировать между форматами файлов sudoers\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1538
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Параметры:\n"
+" -b, --base=dn базовый DN для запросов sudo к LDAP\n"
+" -c, --config=файл путь к файлу настроек\n"
+" -d, --defaults=deftypes конвертировать записи Defaults только указанных типов\n"
+" -e, --expand-aliases раскрывать псевдонимы при конвертации\n"
+" -f, --output-format=формат формат выходных данных: JSON, LDIF или sudoers\n"
+" -i, --input-format=формат формат входных данных: LDIF или sudoers\n"
+" -I, --increment=число значение, на которое следует увеличить каждый sudoOrder\n"
+" -h, --help показать справку и выйти\n"
+" -m, --match=фильтр показывать только записи, соответствующие фильтру\n"
+" -M, --match-local устанавливать соответствие фильтра по базам данных passwd и group\n"
+" -o, --output=выходной_файл записать преобразованные данные sudoers в файл\n"
+" -O, --order-start=число начальное значение для первого sudoOrder\n"
+" -p, --prune-matches удалить несоответствующие записи пользователей, групп и узлов\n"
+" -P, --padding=число число, на которое следует увеличивать sudoOrder\n"
+" -s, --suppress=секции подавить вывод определённых секций\n"
+" -V, --version показать информацию о версии и выйти"
+
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:245 plugins/sudoers/cvtsudoers_ldif.c:252
+#: plugins/sudoers/cvtsudoers_ldif.c:594 plugins/sudoers/env.c:340
+#: plugins/sudoers/env.c:347 plugins/sudoers/env.c:458
+#: plugins/sudoers/ldap.c:511 plugins/sudoers/ldap.c:629
+#: plugins/sudoers/ldap.c:1003 plugins/sudoers/ldap_conf.c:219
+#: plugins/sudoers/ldap_conf.c:310 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:93 plugins/sudoers/logging.c:479
+#: plugins/sudoers/policy.c:828 plugins/sudoers/policy.c:840
+#: plugins/sudoers/prompt.c:169 plugins/sudoers/serialize_list.c:62
+#: plugins/sudoers/serialize_list.c:71 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/sudoreplay.c:1340 plugins/sudoers/sudoreplay.c:1346
+#: plugins/sudoers/sudoreplay.c:1352 plugins/sudoers/testsudoers.c:306
+#: plugins/sudoers/toke_util.c:217 toke.l:995 toke.l:1277
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "внутренняя ошибка, переполнение %s"
+
+#: plugins/sudoers/cvtsudoers_csv.c:454 plugins/sudoers/cvtsudoers_csv.c:468
+#: plugins/sudoers/cvtsudoers_json.c:661 plugins/sudoers/cvtsudoers_json.c:676
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:362
+#: plugins/sudoers/ldap.c:495
+msgid "unable to get GMT time"
+msgstr "не удаётся получить время по Гринвичу"
+
+#: plugins/sudoers/cvtsudoers_csv.c:459 plugins/sudoers/cvtsudoers_csv.c:473
+#: plugins/sudoers/cvtsudoers_json.c:666 plugins/sudoers/cvtsudoers_json.c:681
+#: plugins/sudoers/cvtsudoers_ldif.c:354 plugins/sudoers/cvtsudoers_ldif.c:367
+#: plugins/sudoers/ldap.c:503
+msgid "unable to format timestamp"
+msgstr "не удаётся отформатировать метку времени"
+
+#: plugins/sudoers/cvtsudoers_json.c:481 plugins/sudoers/cvtsudoers_json.c:516
+#: plugins/sudoers/cvtsudoers_json.c:732
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: неизвестная запись по умолчанию «%s»"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:663
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "слишком много записей sudoers, максимум %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:706
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "переменная окружения SUDOERS_BASE не задана и не указан параметр -b."
+
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, c-format
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr "%s:%d:%d: преобразуем список узлов в ALL"
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr "не удаётся найти псевдоним %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, c-format
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr "%s:%d:%d: переименование псевдонима %s в %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr "%s:%d:%d: удаление дубля псевдонима %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr "%s:%d:%d: конфликт записи Defaults «%s» специфичен для узла в %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, c-format
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr "%s:%d:%d: Defaults «%s» сделано специфичным для узла %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr "%s:%d:%d: не удаётся сделать Defaults «%s» специфичным для узла"
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr "%s:%d:%d: удаление Defaults «%s» переопределено последующими записями"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1088
+#, c-format
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr "%s:%d:%d: объединяем спецификации пользователей в %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1182
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr "%s:%d:%d: удаление userpec переопределено последующими записями"
+
+#: plugins/sudoers/def_data.c:56
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Средство Syslog, если syslog используется для ведения журнала: %s"
+
+#: plugins/sudoers/def_data.c:60
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Приоритет Syslog, который следует использовать при успешной аутентификации пользователя: %s"
+
+#: plugins/sudoers/def_data.c:64
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Приоритет Syslog, который следует использовать при неудачной аутентификации пользователя: %s"
+
+#: plugins/sudoers/def_data.c:68
+msgid "Put OTP prompt on its own line"
+msgstr "Размещать запрос OTP в отдельной строке"
+
+#: plugins/sudoers/def_data.c:72
+msgid "Ignore '.' in $PATH"
+msgstr "Игнорировать '.' в переменной $PATH"
+
+#: plugins/sudoers/def_data.c:76
+msgid "Always send mail when sudo is run"
+msgstr "Отправлять письмо при каждом запуске sudo"
+
+#: plugins/sudoers/def_data.c:80
+msgid "Send mail if user authentication fails"
+msgstr "Отправлять письмо при ошибке аутентификации"
+
+#: plugins/sudoers/def_data.c:84
+msgid "Send mail if the user is not in sudoers"
+msgstr "Отправлять письмо, если пользователя нет в группе sudoers"
+
+#: plugins/sudoers/def_data.c:88
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Отправлять письмо, если пользователя нет в группе sudoers для данного компьютера"
+
+#: plugins/sudoers/def_data.c:92
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Отправлять письмо, если пользователю не разрешено выполнять команду"
+
+#: plugins/sudoers/def_data.c:96
+msgid "Send mail if the user tries to run a command"
+msgstr "Отправлять письмо, если пользователь пытается выполнить команду"
+
+#: plugins/sudoers/def_data.c:100
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Отдельная метка времени для каждой комбинации пользователь/tty"
+
+#: plugins/sudoers/def_data.c:104
+msgid "Lecture user the first time they run sudo"
+msgstr "Показывать инструкцию пользователю при первом запуске sudo"
+
+#: plugins/sudoers/def_data.c:108
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Файл, содержащий инструкцию по sudo: %s"
+
+#: plugins/sudoers/def_data.c:112
+msgid "Require users to authenticate by default"
+msgstr "Требовать от пользователей аутентификацию по умолчанию"
+
+#: plugins/sudoers/def_data.c:116
+msgid "Root may run sudo"
+msgstr "Root может запускать sudo"
+
+#: plugins/sudoers/def_data.c:120
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Записывать имя узла в файл журнала (не syslog)"
+
+#: plugins/sudoers/def_data.c:124
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Записывать год в файл журнала (не syslog)"
+
+#: plugins/sudoers/def_data.c:128
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Если sudo вызывается без аргументов, запускать командную оболочку"
+
+#: plugins/sudoers/def_data.c:132
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Устанавливать $HOME на каталог целевого пользователя при запуске оболочки с -s"
+
+#: plugins/sudoers/def_data.c:136
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Всегда устанавливать $HOME на каталог целевого пользователя"
+
+#: plugins/sudoers/def_data.c:140
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Разрешить сбор информации для получения полезных сообщений об ошибках"
+
+#: plugins/sudoers/def_data.c:144
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Требовать полные имена узлов в файле sudoers"
+
+#: plugins/sudoers/def_data.c:148
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Издеваться над пользователем при вводе неправильного пароля"
+
+#: plugins/sudoers/def_data.c:152
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Разрешить пользователю запускать sudo, только если у него есть tty"
+
+#: plugins/sudoers/def_data.c:156
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo будет использовать переменную окружения EDITOR"
+
+#: plugins/sudoers/def_data.c:160
+msgid "Prompt for root's password, not the users's"
+msgstr "Запрашивать пароль root, а не пользователя"
+
+#: plugins/sudoers/def_data.c:164
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Запрашивать пароль пользователя runas_default, а не самого пользователя"
+
+#: plugins/sudoers/def_data.c:168
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Запрашивать пароль целевого пользователя, а не самого пользователя"
+
+#: plugins/sudoers/def_data.c:172
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Применить значения по умолчанию в классе целевого пользователя, если он есть"
+
+#: plugins/sudoers/def_data.c:176
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Установить переменные окружения LOGNAME и USER"
+
+#: plugins/sudoers/def_data.c:180
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Установить только эффективный uid равным целевому пользователю, без реального uid"
+
+#: plugins/sudoers/def_data.c:184
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Не инициализировать вектор группы на вектор целевого пользователя"
+
+#: plugins/sudoers/def_data.c:188
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Длина, на которой переносить строки файла журнала (0 ­— без переноса): %u"
+
+#: plugins/sudoers/def_data.c:192
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Время ожидания метки времени аутентификации: %.1f минут"
+
+#: plugins/sudoers/def_data.c:196
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Время ожидания запроса пароля: %.1f минут"
+
+#: plugins/sudoers/def_data.c:200
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Количество попыток ввода пароля: %u"
+
+#: plugins/sudoers/def_data.c:204
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Значение umask или 0777 для применения пользовательского значения: 0%o"
+
+#: plugins/sudoers/def_data.c:208
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Путь к файлу журнала: %s"
+
+#: plugins/sudoers/def_data.c:212
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Путь к почтовой программе: %s"
+
+#: plugins/sudoers/def_data.c:216
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Флаги для почтовой программы: %s"
+
+#: plugins/sudoers/def_data.c:220
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Адрес для отправки почты: %s"
+
+#: plugins/sudoers/def_data.c:224
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Адрес для отправки почты от: %s"
+
+#: plugins/sudoers/def_data.c:228
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Тема письма: %s"
+
+#: plugins/sudoers/def_data.c:232
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Сообщение о некорректном пароле: %s"
+
+#: plugins/sudoers/def_data.c:236
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Путь к каталогу состояния обучения: %s"
+
+#: plugins/sudoers/def_data.c:240
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Путь к каталогу меток времени аутентификации: %s"
+
+#: plugins/sudoers/def_data.c:244
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Владелец каталога меток времени аутентификации: %s"
+
+#: plugins/sudoers/def_data.c:248
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Пользователи этой группы освобождены от необходимости ввода пароля и PATH: %s"
+
+#: plugins/sudoers/def_data.c:252
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Подсказка пароля по умолчанию: %s"
+
+#: plugins/sudoers/def_data.c:256
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Если установлено, запрос пароля будет заменять запрос системы."
+
+#: plugins/sudoers/def_data.c:260
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Пользователь по умолчанию для выполнения команд: %s"
+
+#: plugins/sudoers/def_data.c:264
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Значение для переопределения $PATH пользователя: %s"
+
+#: plugins/sudoers/def_data.c:268
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Путь к редактору для использования visudo: %s"
+
+#: plugins/sudoers/def_data.c:272
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Когда требовать пароль для псевдокоманды «list»: %s"
+
+#: plugins/sudoers/def_data.c:276
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Когда требовать пароль для псевдокоманды «verify»: %s"
+
+#: plugins/sudoers/def_data.c:280
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "Предварительно загрузить библиотеку sudo_noexec, заменяющую функции выполнения"
+
+#: plugins/sudoers/def_data.c:284
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Игнорировать ли локальный файл sudoers, если есть доступ к каталогу LDAP"
+
+#: plugins/sudoers/def_data.c:288
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Дескрипторы файлов >= %d будут закрыты перед выполнением команды"
+
+#: plugins/sudoers/def_data.c:292
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "Если установлено, пользователи могут переопределять значение closefrom с помощью параметра -C"
+
+#: plugins/sudoers/def_data.c:296
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Разрешить пользователям устанавливать произвольные переменные окружения"
+
+#: plugins/sudoers/def_data.c:300
+msgid "Reset the environment to a default set of variables"
+msgstr "Сбрасывать окружение к набору переменных по умолчанию"
+
+#: plugins/sudoers/def_data.c:304
+msgid "Environment variables to check for safety:"
+msgstr "Переменные окружения, безопасность которых следует проверить:"
+
+#: plugins/sudoers/def_data.c:308
+msgid "Environment variables to remove:"
+msgstr "Переменные окружения, которые необходимо удалить:"
+
+#: plugins/sudoers/def_data.c:312
+msgid "Environment variables to preserve:"
+msgstr "Переменные окружения, которые необходимо сохранить:"
+
+#: plugins/sudoers/def_data.c:316
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "Роль SELinux для использования в новом контексте безопасности: %s"
+
+#: plugins/sudoers/def_data.c:320
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "Тип SELinux для использования в новом контексте безопасности: %s"
+
+#: plugins/sudoers/def_data.c:324
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Путь к специфическому для sudo файлу окружения: %s"
+
+#: plugins/sudoers/def_data.c:328
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Путь к специфическому для sudo файлу окружения с ограниченным доступом: %s"
+
+#: plugins/sudoers/def_data.c:332
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Локаль, которую следует использовать при разборе sudoers: %s"
+
+#: plugins/sudoers/def_data.c:336
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Разрешить sudo запрашивать пароль, даже если он будет виден"
+
+#: plugins/sudoers/def_data.c:340
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Сопровождать ввод пароля показом заменителей символов пароля"
+
+#: plugins/sudoers/def_data.c:344
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Использовать быструю подстановку путей, которая менее точна, но не требует доступа к файловой системе"
+
+#: plugins/sudoers/def_data.c:348
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "Значение umask, указанное в sudoers, будет переопределять значения пользователя, даже если это открывает более широкий доступ"
+
+#: plugins/sudoers/def_data.c:352
+msgid "Log user's input for the command being run"
+msgstr "Записывать в журнал данные, введённые пользователем для выполнения команды"
+
+#: plugins/sudoers/def_data.c:356
+msgid "Log the command's standard input if not connected to a terminal"
+msgstr "Записывать в журнал данные из стандартного ввода команды, если она не соединена с терминалом"
+
+#: plugins/sudoers/def_data.c:360
+msgid "Log the user's terminal input for the command being run"
+msgstr "Записывать в журнал данные, вводимые пользователем в терминал при выполнении команды"
+
+#: plugins/sudoers/def_data.c:364
+msgid "Log the output of the command being run"
+msgstr "Записывать в журнал вывод выполняемой команды"
+
+#: plugins/sudoers/def_data.c:368
+msgid "Log the command's standard output if not connected to a terminal"
+msgstr "Записывать в журнал стандартный вывод команды, если она не подключена к терминалу"
+
+#: plugins/sudoers/def_data.c:372
+msgid "Log the command's standard error if not connected to a terminal"
+msgstr "Записывать в журнал стандартный вывод ошибок команды, если она не подключена к терминалу"
+
+#: plugins/sudoers/def_data.c:376
+msgid "Log the terminal output of the command being run"
+msgstr "Записывать в журнал данные, выведенные командой в терминал во время выполнения"
+
+#: plugins/sudoers/def_data.c:380
+msgid "Compress I/O logs using zlib"
+msgstr "Сжимать журналы ввода/вывода с помощью zlib"
+
+#: plugins/sudoers/def_data.c:384
+msgid "Always run commands in a pseudo-tty"
+msgstr "Всегда запускать команды в псевдо-tty"
+
+#: plugins/sudoers/def_data.c:388
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Модель для поддержки не-Unix групп: %s"
+
+#: plugins/sudoers/def_data.c:392
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Каталог, в котором будут храниться журналы ввода/вывода: %s"
+
+#: plugins/sudoers/def_data.c:396
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Файл, в который будет сохраняться журнал ввода/вывода: %s"
+
+#: plugins/sudoers/def_data.c:400
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Добавлять запись в файл utmp/utmpx при выделении pty"
+
+#: plugins/sudoers/def_data.c:404
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Установить пользователя в utmp в значение runas, а не имя пользователя, от имени которого выполняется команда"
+
+#: plugins/sudoers/def_data.c:408
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Набор разрешённых прав доступа: %s"
+
+#: plugins/sudoers/def_data.c:412
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Набор ограничительных прав доступа: %s"
+
+#: plugins/sudoers/def_data.c:416
+msgid "Run commands on a pty in the background"
+msgstr "Выполнять команды на pty в фоновом режиме"
+
+#: plugins/sudoers/def_data.c:420
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "Название службы PAM, которую следует использовать: %s"
+
+#: plugins/sudoers/def_data.c:424
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "Название службы PAM, которую следует использовать для оболочек входа в систему: %s"
+
+#: plugins/sudoers/def_data.c:428
+#, c-format
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr "Название службы PAM, которую следует использовать, когда sudo запущен с параметром -A: %s"
+
+#: plugins/sudoers/def_data.c:432
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Попытаться установить регистрационные данные PAM для пользователя, от имени которого будут выполняться команды"
+
+#: plugins/sudoers/def_data.c:436
+msgid "Create a new PAM session for the command to run in"
+msgstr "Создать сеанс PAM для выполнения команды"
+
+#: plugins/sudoers/def_data.c:440
+msgid "Perform PAM account validation management"
+msgstr "Выполнять проверку корректности учётной записи PAM"
+
+#: plugins/sudoers/def_data.c:444
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "Максимальный номер в журнале ввода/вывода: %s"
+
+#: plugins/sudoers/def_data.c:448
+msgid "Enable sudoers netgroup support"
+msgstr "Включить поддержку сетевых групп в sudoers"
+
+#: plugins/sudoers/def_data.c:452
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Проверять родительские каталоги на возможность записи при редактировании файлов с помощью sudoedit"
+
+#: plugins/sudoers/def_data.c:456
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Переходить по символическим ссылкам при редактировании файлов с помощью sudoedit"
+
+#: plugins/sudoers/def_data.c:460
+msgid "Query the group plugin for unknown system groups"
+msgstr "Отправлять запрос в модуль групп по неизвестным группам системы"
+
+#: plugins/sudoers/def_data.c:464
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Устанавливать соответствие сетевым группам по всему кортежу данных: пользователю, узлу и домену"
+
+#: plugins/sudoers/def_data.c:468
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Разрешить выполнение команд, даже если sudo не может записать в журнал аудита"
+
+#: plugins/sudoers/def_data.c:472
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Разрешить выполнение команд, даже если sudo не может записать в журнал ввода/вывода"
+
+#: plugins/sudoers/def_data.c:476
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Разрешить выполнение команд, даже если sudo не может записать в файл журнала"
+
+#: plugins/sudoers/def_data.c:480
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Определять группы в sudoers и устанавливать соответствие по идентификатору группы, а не названию"
+
+#: plugins/sudoers/def_data.c:484
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Записи журнала, превышающие это значение, будут разделены на несколько сообщений syslog: %u"
+
+#: plugins/sudoers/def_data.c:488
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Пользователь, который будет владеть файлами журнала ввода/вывода: %s"
+
+#: plugins/sudoers/def_data.c:492
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Группа, которая будет владеть файлами журнала ввода/вывода: %s"
+
+#: plugins/sudoers/def_data.c:496
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Режим доступа к файлам журнала ввода/вывода: 0%o"
+
+#: plugins/sudoers/def_data.c:500
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Выполнять команды по дескриптору файла, а не пути: %s"
+
+#: plugins/sudoers/def_data.c:504
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Игнорировать неизвестные записи Defaults в sudoers вместо показа предупреждения"
+
+#: plugins/sudoers/def_data.c:508
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Время в секундах, после которого выполнение команды будет прервано: %u"
+
+#: plugins/sudoers/def_data.c:512
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Разрешить пользователю указывать время ожидания в командной строке"
+
+#: plugins/sudoers/def_data.c:516
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Сбрасывать данные журнала ввода/вывода на диск немедленно, без буферизации"
+
+#: plugins/sudoers/def_data.c:520
+msgid "Include the process ID when logging via syslog"
+msgstr "Включать идентификатор процесса в журнал syslog"
+
+#: plugins/sudoers/def_data.c:524
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Тип записи временной метки аутентификации: %s"
+
+#: plugins/sudoers/def_data.c:528
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Сообщение об ошибке аутентификации: %s"
+
+#: plugins/sudoers/def_data.c:532
+msgid "Ignore case when matching user names"
+msgstr "Игнорировать регистр при сопоставлении имён пользователей"
+
+#: plugins/sudoers/def_data.c:536
+msgid "Ignore case when matching group names"
+msgstr "Игнорировать регистр при сопоставлении имён групп"
+
+#: plugins/sudoers/def_data.c:540
+msgid "Log when a command is allowed by sudoers"
+msgstr "Записывать в журнал, когда выполнение команды разрешено sudoers"
+
+#: plugins/sudoers/def_data.c:544
+msgid "Log when a command is denied by sudoers"
+msgstr "Записывать в журнал, когда выполнение команды заблокировано sudoers"
+
+#: plugins/sudoers/def_data.c:548
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "Сервер(ы) журнала sudo с необязательным портом, к которым следует установить подключение"
+
+#: plugins/sudoers/def_data.c:552
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Время ожидания сервера журнала sudo в секундах: %u"
+
+#: plugins/sudoers/def_data.c:556
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "Включить опцию SO_KEEPALIVE на сокете, подключенном к серверу журналов"
+
+#: plugins/sudoers/def_data.c:560
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "Путь к файлу пакета CA сервера аудита: %s"
+
+#: plugins/sudoers/def_data.c:564
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "Путь к файлу сертификата sudoers: %s"
+
+#: plugins/sudoers/def_data.c:568
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "Путь к файлу закрытого ключа sudoers: %s"
+
+#: plugins/sudoers/def_data.c:572
+msgid "Verify that the log server's certificate is valid"
+msgstr "Проверять, что сертификат сервера журнала действителен"
+
+#: plugins/sudoers/def_data.c:576
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "Разрешить использование неизвестного идентификатора пользователя и/или группы для runas"
+
+#: plugins/sudoers/def_data.c:580
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "Разрешить выполнение команд только от имени пользователя с корректной оболочкой"
+
+#: plugins/sudoers/def_data.c:584
+msgid "Set the pam remote user to the user running sudo"
+msgstr "Установить для удалённого пользователя PAM то же имя, что и для пользователя, от имени которого запущен sudo"
+
+#: plugins/sudoers/def_data.c:588
+msgid "Set the pam remote host to the local host name"
+msgstr "Установить для удалённого узла PAM название локального узла"
+
+#: plugins/sudoers/def_data.c:592
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "Рабочий каталог, в который следует перейти перед выполнением команды: %s"
+
+#: plugins/sudoers/def_data.c:596
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "Корневой каталог, в который следует перейти перед выполнением команды: %s"
+
+#: plugins/sudoers/def_data.c:600
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "Формат журнала: %s"
+
+#: plugins/sudoers/def_data.c:604
+msgid "Enable SELinux RBAC support"
+msgstr "Включить поддержку SELinux RBAC"
+
+#: plugins/sudoers/def_data.c:608
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "Путь к файлу, который создаётся при первом запуске sudo: %s"
+
+#: plugins/sudoers/def_data.c:612
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "Перехватывать дальнейшие команды и применять к ним ограничения sudoers"
+
+#: plugins/sudoers/def_data.c:616
+msgid "Log sub-commands run by the original command"
+msgstr "Записывать в журнал подкоманды, выполняемые исходной командой"
+
+#: plugins/sudoers/def_data.c:620
+msgid "Log the exit status of commands"
+msgstr "Записывать в журнал статус выхода команд"
+
+#: plugins/sudoers/def_data.c:624
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr "Для выполнения следующих команд в перехваченном сеансе необходимо пройти аутентификацию"
+
+#: plugins/sudoers/def_data.c:628
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr "Разрешить перехваченной команде запускать программы, выполняющие setuid или setgid"
+
+#: plugins/sudoers/def_data.c:632
+#, c-format
+msgid "The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr "Максимальный размер, до которого может увеличиваться адресное пространство процесса (в байтах): %s"
+
+#: plugins/sudoers/def_data.c:636
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr "Наибольший размер файла дампа ядра, который может быть создан (в байтах): %s"
+
+#: plugins/sudoers/def_data.c:640
+#, c-format
+msgid "The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr "Максимальное количество процессорного времени, которое процесс может использовать (в секундах): %s"
+
+#: plugins/sudoers/def_data.c:644
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr "Максимальный размер сегмента данных процесса (в байтах): %s"
+
+#: plugins/sudoers/def_data.c:648
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr "Наибольший размер файла, который процесс может создать (в байтах): %s"
+
+#: plugins/sudoers/def_data.c:652
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr "Максимальное количество блокировок, которые может установить процесс: %s"
+
+#: plugins/sudoers/def_data.c:656
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr "Максимальный размер, который процесс может заблокировать в памяти (в байтах): %s"
+
+#: plugins/sudoers/def_data.c:660
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr "Максимальное количество файлов, которое может быть открыто процессом: %s"
+
+#: plugins/sudoers/def_data.c:664
+#, c-format
+msgid "The maximum number of processes that the user may run simultaneously: %s"
+msgstr "Максимальное количество процессов, которые пользователь может запускать одновременно: %s"
+
+#: plugins/sudoers/def_data.c:668
+#, c-format
+msgid "The maximum size to which the process's resident set size may grow (in bytes): %s"
+msgstr "Максимальный размер, до которого может вырасти размер резидентного набора процесса (в байтах): %s"
+
+#: plugins/sudoers/def_data.c:672
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr "Максимальный размер, до которого может вырасти стек процесса (в байтах): %s"
+
+#: plugins/sudoers/def_data.c:676
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr "Пытаться пройти аутентификацию даже в неинтерактивном режиме"
+
+#: plugins/sudoers/def_data.c:680
+msgid "Store plaintext passwords in I/O log input"
+msgstr "Сохранять вводимые пароли в открытом виде в журнале ввода-вывода"
+
+#: plugins/sudoers/def_data.c:684
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr "Список регулярных выражений, которые будут использоваться при сопоставлении запроса пароля"
+
+#: plugins/sudoers/def_data.c:688
+#, c-format
+msgid "The mechanism used by the intercept and log_subcmds options: %s"
+msgstr "Механизм, используемый параметрами intercept и log_subcmds: %s"
+
+#: plugins/sudoers/def_data.c:692
+msgid "Attempt to verify the command and arguments after execution"
+msgstr "Попытаться проверить команду и аргументы после выполнения"
+
+#: plugins/sudoers/def_data.c:696
+#, c-format
+msgid "AppArmor profile to use in the new security context: %s"
+msgstr "Профиль AppArmor, который следует использовать в новом контексте безопасности: %s"
+
+#: plugins/sudoers/defaults.c:207
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "неизвестная запись параметров по умолчанию «%s»"
+
+#: plugins/sudoers/defaults.c:251
+#, c-format
+msgid "no value specified for \"%s\""
+msgstr "для «%s» не указано значение"
+
+#: plugins/sudoers/defaults.c:260
+#, c-format
+msgid "invalid operator \"%c=\" for \"%s\""
+msgstr "некорректный оператор «%c=» для «%s»"
+
+#: plugins/sudoers/defaults.c:292
+#, c-format
+msgid "option \"%s\" does not take a value"
+msgstr "параметр «%s» не принимает значение"
+
+#: plugins/sudoers/defaults.c:319
+#, c-format
+msgid "invalid Defaults type 0x%x for option \"%s\""
+msgstr "некорректный тип Defaults 0x%x для параметра «%s»"
+
+#: plugins/sudoers/defaults.c:326
+#, c-format
+msgid "value \"%s\" is invalid for option \"%s\""
+msgstr "значение «%s» недопустимо для параметра «%s»"
+
+#: plugins/sudoers/defaults.c:1176 plugins/sudoers/policy.c:213
+#: plugins/sudoers/policy.c:222
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr "слишком длинный путь для «%s»"
+
+#: plugins/sudoers/defaults.c:1182
+#, c-format
+msgid "values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "значения для «%s» должны начинаться с «/», «~» или «*»"
+
+#: plugins/sudoers/defaults.c:1189
+#, c-format
+msgid "values for \"%s\" must start with a '/'"
+msgstr "значения для «%s» должны начинаться с «/»"
+
+#: plugins/sudoers/display.c:160
+#, c-format
+msgid "LDAP Role: %s\n"
+msgstr "Роль LDAP: %s\n"
+
+#: plugins/sudoers/display.c:163
+#, c-format
+msgid "Sudoers entry: %s\n"
+msgstr "Запись sudoers: %s\n"
+
+#: plugins/sudoers/display.c:166
+msgid " RunAsUsers: "
+msgstr " ПользователиДляЗапуска: "
+
+#: plugins/sudoers/display.c:181
+msgid " RunAsGroups: "
+msgstr " ГруппыДляЗапуска: "
+
+#: plugins/sudoers/display.c:191
+msgid " Options: "
+msgstr " Параметры: "
+
+#: plugins/sudoers/display.c:255
+msgid " Commands:\n"
+msgstr " Команды:\n"
+
+#: plugins/sudoers/display.c:478
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Соответствие записей Defaults для %s на %s:\n"
+
+#: plugins/sudoers/display.c:496
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Значения Runas и Command по умолчанию для %s:\n"
+
+#: plugins/sudoers/display.c:514
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "Пользователь %s может выполнять следующие команды на %s:\n"
+
+#: plugins/sudoers/display.c:530
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Пользователю %s не разрешено запускать sudo на %s.\n"
+
+#: plugins/sudoers/editor.c:180
+#, c-format
+msgid "ignoring editor: %.*s"
+msgstr "игнорируется редактор: %.*s"
+
+#: plugins/sudoers/editor.c:181
+msgid "editor arguments may not contain \"--\""
+msgstr "аргументы редактора не могут содержать «--»"
+
+#: plugins/sudoers/env.c:426
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: ошибочное значение envp, несоответствие длин"
+
+#: plugins/sudoers/env.c:1119
+msgid "unable to rebuild the environment"
+msgstr "не удаётся перестроить среду"
+
+#: plugins/sudoers/env.c:1199
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "извините, вам не разрешено устанавливать следующие переменные окружения: %s"
+
+#: plugins/sudoers/filedigest.c:50
+#, c-format
+msgid "unsupported digest type %u for %s"
+msgstr "неподдерживаемый тип контрольной суммы %u для %s"
+
+#: plugins/sudoers/filedigest.c:77
+#, c-format
+msgid "%s: read error"
+msgstr "%s: ошибка чтения"
+
+#: plugins/sudoers/group_plugin.c:169 plugins/sudoers/sssd.c:578
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "не удаётся загрузить %s: %s"
+
+#: plugins/sudoers/group_plugin.c:181
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "не удаётся найти символ «group_plugin» в %s"
+
+#: plugins/sudoers/group_plugin.c:186
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: несовместимая основная версия модуля групп %d, должна быть %d"
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "не удаётся разобрать IP-адрес «%s»"
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "не удаётся разобрать сетевую маску «%s»"
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Пары локальных IP-адресов и масок сети:\n"
+
+#: plugins/sudoers/iolog.c:694
+msgid "unable to update sequence file"
+msgstr "не удаётся обновить файл последовательности"
+
+#: plugins/sudoers/iolog.c:728 plugins/sudoers/iolog.c:917
+#: plugins/sudoers/iolog.c:1080 plugins/sudoers/iolog.c:1087
+#: plugins/sudoers/iolog.c:1209 plugins/sudoers/iolog.c:1216
+#: plugins/sudoers/iolog.c:1316 plugins/sudoers/iolog.c:1323
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "не удаётся добавить запись в файл журнала ввода-вывода: %s"
+
+#: plugins/sudoers/iolog.c:736
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "не удаётся создать %s/%s"
+
+#: plugins/sudoers/iolog.c:965
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: внутренняя ошибка, файл журнала ввода/вывода для события %d не открыт"
+
+#: plugins/sudoers/iolog.c:1065 plugins/sudoers/iolog.c:1194
+#: plugins/sudoers/iolog.c:1300 plugins/sudoers/timestamp.c:897
+#: plugins/sudoers/timestamp.c:989 plugins/sudoers/visudo.c:555
+#: plugins/sudoers/visudo.c:561
+msgid "unable to read the clock"
+msgstr "не удаётся прочитать время"
+
+#: plugins/sudoers/iolog.c:1292 plugins/sudoers/log_client.c:1203
+#: plugins/sudoers/log_client.c:1213 plugins/sudoers/log_client.c:1217
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: внутренняя ошибка, недопустимый сигнал %d"
+
+#: plugins/sudoers/ldap.c:154 plugins/sudoers/ldap_conf.c:289
+msgid "starttls not supported when using ldaps"
+msgstr "starttls не поддерживается при использовании ldaps"
+
+#: plugins/sudoers/ldap.c:226
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "не удаётся инициализировать базу данных сертификатов и ключей SSL: %s"
+
+#: plugins/sudoers/ldap.c:229
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "для использования SSL необходимо установить для TLS_CERT значение %s"
+
+#: plugins/sudoers/ldap.c:1593
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "не удаётся инициализировать LDAP: %s"
+
+#: plugins/sudoers/ldap.c:1630
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "указано start_tls, но библиотеки LDAP не поддерживают ldap_start_tls_s() или ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:1767 plugins/sudoers/parse_ldif.c:745
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "некорректный атрибут sudoOrder: %s"
+
+#: plugins/sudoers/ldap_conf.c:197
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: слишком большой порт"
+
+#: plugins/sudoers/ldap_conf.c:258
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "неподдерживаемый тип адреса LDAP: %s"
+
+#: plugins/sudoers/ldap_conf.c:285
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "нельзя использовать вместе адреса ldap и ldaps"
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "дубль sudoOption: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "не удаётся преобразовать запись sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "не удаётся открыть систему аудита"
+
+#: plugins/sudoers/linux_audit.c:104
+msgid "unable to send audit message"
+msgstr "не удаётся отправить сообщение аудита"
+
+#: plugins/sudoers/log_client.c:125 plugins/sudoers/log_client.c:412
+#: plugins/sudoers/log_client.c:1450 plugins/sudoers/log_client.c:2076
+msgid "error in event loop"
+msgstr "ошибка в цикле обработки событий"
+
+#: plugins/sudoers/log_client.c:205
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "Не удаётся создать объект SSL_CTX: %s"
+
+#: plugins/sudoers/log_client.c:230
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "не удаётся загрузить пакет центра сертификации %s"
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "не удаётся загрузить сертификат %s"
+
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "unable to load private key %s"
+msgstr "не удаётся загрузить закрытый ключ %s"
+
+#: plugins/sudoers/log_client.c:275
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "Не удаётся разместить SSL-объект в памяти: %s"
+
+#: plugins/sudoers/log_client.c:364 plugins/sudoers/log_client.c:369
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "Не удаётся установить TLS-соединение с %s:%s: %s"
+
+#: plugins/sudoers/log_client.c:545
+msgid "TLS initialization was unsuccessful"
+msgstr "Инициализация TLS не удалась"
+
+#: plugins/sudoers/log_client.c:555
+msgid "TLS handshake was unsuccessful"
+msgstr "Попытка согласования TLS-подключения завершилась неудачно"
+
+#: plugins/sudoers/log_client.c:1221
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: внутренняя ошибка, некорректный статус выхода %d"
+
+#: plugins/sudoers/log_client.c:1757 plugins/sudoers/log_client.c:1782
+msgid "lost connection to log server"
+msgstr "потеряно соединение с сервером журнала"
+
+#: plugins/sudoers/log_client.c:1859
+msgid "missing write buffer"
+msgstr "не указан буфер записи"
+
+#: plugins/sudoers/log_client.c:2015
+msgid "unable to connect to log server"
+msgstr "не удаётся подключиться к серверу журнала"
+
+#: plugins/sudoers/logging.c:295
+msgid "user NOT in sudoers"
+msgstr "пользователя НЕТ в списке sudoers"
+
+#: plugins/sudoers/logging.c:297
+msgid "user NOT authorized on host"
+msgstr "пользователь НЕ имеет прав на действия на узле"
+
+#: plugins/sudoers/logging.c:299
+msgid "command not allowed"
+msgstr "команда не разрешена"
+
+#: plugins/sudoers/logging.c:320
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr "%s отсутствует в файле sudoers.\n"
+
+#: plugins/sudoers/logging.c:323
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr "%s не имеет права запускать sudo на %s.\n"
+
+#: plugins/sudoers/logging.c:326
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Извините, пользователь %s не может запустить sudo на %s.\n"
+
+#: plugins/sudoers/logging.c:339
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s%s' as %s%s%s on %s.\n"
+msgstr "Извините, пользователю %s не разрешено выполнять «%s%s%s%s» как %s%s%s на %s.\n"
+
+#: plugins/sudoers/logging.c:350
+msgid "This incident has been reported to the administrator.\n"
+msgstr "Администратор был оповещён об этом событии.\n"
+
+#: plugins/sudoers/logging.c:387 plugins/sudoers/sudoers.c:547
+#: plugins/sudoers/sudoers.c:549 plugins/sudoers/sudoers.c:551
+#: plugins/sudoers/sudoers.c:553 plugins/sudoers/sudoers.c:777
+#: plugins/sudoers/sudoers.c:779
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: команда не найдена"
+
+#: plugins/sudoers/logging.c:389 plugins/sudoers/sudoers.c:543
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"пропущено «%s» найдено в «.»\n"
+"Используйте команду «sudo ./%s», если вам нужно выполнить именно этот «%s»."
+
+#: plugins/sudoers/logging.c:409
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u неправильная попытка ввода пароля"
+msgstr[1] "%u неправильные попытки ввода пароля"
+msgstr[2] "%u неправильных попыток ввода пароля"
+
+#: plugins/sudoers/logging.c:500
+msgid "authentication failure"
+msgstr "ошибка аутентификации"
+
+#: plugins/sudoers/logging.c:539 plugins/sudoers/logging.c:558
+msgid "a password is required"
+msgstr "требуется указать пароль"
+
+#: plugins/sudoers/logging.c:881
+msgid "problem parsing sudoers"
+msgstr "проблема разбора sudoers"
+
+#: plugins/sudoers/logging.c:922 plugins/sudoers/logging.c:930
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr "%s:%d:%d: %s"
+
+#: plugins/sudoers/logging.c:1108
+#, c-format
+msgid "unable to write log file %s"
+msgstr "не удаётся записать файл журнала %s"
+
+#: plugins/sudoers/match_digest.c:107
+#, c-format
+msgid "digest for %s (%s) bad length %zu, expected %zu"
+msgstr "контрольная сумма для %s (%s) имеет некорректную длину %zu, должно быть %zu"
+
+#: plugins/sudoers/match_digest.c:126
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "контрольная сумма для %s (%s) представлена не в форме %s"
+
+#: plugins/sudoers/parse_ldif.c:615
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "игнорируем неполную запись sudoRole: cn: %s"
+
+#: plugins/sudoers/parse_ldif.c:675
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "некорректный атрибут LDIF: %s"
+
+#: plugins/sudoers/parser_warnx.c:56
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: plugins/sudoers/parser_warnx.c:59
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s: %s\n"
+
+#: plugins/sudoers/pivot.c:71
+msgid "unable to restore root directory"
+msgstr "не удаётся восстановить корневой каталог"
+
+#: plugins/sudoers/pivot.c:79
+msgid "unable to restore current working directory"
+msgstr "не удаётся восстановить текущий рабочий каталог"
+
+#: plugins/sudoers/policy.c:78 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "оболочкой sudo установлено некорректное значение %.*s"
+
+#: plugins/sudoers/policy.c:364 plugins/sudoers/testsudoers.c:329
+msgid "unable to parse network address list"
+msgstr "невозможно разобрать список сетевых адресов"
+
+#: plugins/sudoers/policy.c:556
+msgid "user name not set by sudo front-end"
+msgstr "имя пользователя не указано оболочкой sudo"
+
+#: plugins/sudoers/policy.c:560
+msgid "user-ID not set by sudo front-end"
+msgstr "идентификатор пользователя не указан оболочкой sudo"
+
+#: plugins/sudoers/policy.c:564
+msgid "group-ID not set by sudo front-end"
+msgstr "идентификатор группы не указан оболочкой sudo"
+
+#: plugins/sudoers/policy.c:568
+msgid "host name not set by sudo front-end"
+msgstr "имя узла не указано оболочкой sudo"
+
+#: plugins/sudoers/policy.c:757
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "некорректный рабочий каталог: %s"
+
+#: plugins/sudoers/policy.c:944
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "некорректный каталог chroot: %s"
+
+#: plugins/sudoers/policy.c:1153 plugins/sudoers/visudo.c:919
+#: plugins/sudoers/visudo.c:1218
+#, c-format
+msgid "unable to execute %s"
+msgstr "не удаётся выполнить %s"
+
+#: plugins/sudoers/policy.c:1225 plugins/sudoers/policy.c:1260
+#: plugins/sudoers/policy.c:1282 plugins/sudoers/policy.c:1300
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: некорректные флаги режима от оболочки sudo: 0x%x"
+
+#: plugins/sudoers/policy.c:1323
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Модуль политики sudoers версии %s\n"
+
+#: plugins/sudoers/policy.c:1325
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Файл грамматики sudoers версии %d\n"
+
+#: plugins/sudoers/policy.c:1329
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Путь к sudoers: %s\n"
+
+#: plugins/sudoers/policy.c:1332
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "путь к nsswitch: %s\n"
+
+#: plugins/sudoers/policy.c:1335
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "путь к ldap.conf: %s\n"
+
+#: plugins/sudoers/policy.c:1337
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "путь к ldap.secret: %s\n"
+
+#: plugins/sudoers/policy.c:1370
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "не удаётся зарегистрировать процедуру перехвата типа %d (версия %d.%d)"
+
+#: plugins/sudoers/policy.c:1388
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "не удаётся отменить регистрацию процедуры перехвата типа %d (версия %d.%d)"
+
+#: plugins/sudoers/pwutil.c:242 plugins/sudoers/pwutil.c:260
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "не удаётся кэшировать uid %u"
+
+#: plugins/sudoers/pwutil.c:254
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "не удаётся кэшировать uid %u, запись уже существует"
+
+#: plugins/sudoers/pwutil.c:314 plugins/sudoers/pwutil.c:332
+#: plugins/sudoers/pwutil.c:395 plugins/sudoers/pwutil.c:440
+#, c-format
+msgid "unable to cache user %s"
+msgstr "не удаётся кэшировать пользователя %s"
+
+#: plugins/sudoers/pwutil.c:327
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "не удаётся кэшировать пользователя %s, запись уже существует"
+
+#: plugins/sudoers/pwutil.c:559 plugins/sudoers/pwutil.c:577
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "не удаётся кэшировать gid %u"
+
+#: plugins/sudoers/pwutil.c:571
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "не удаётся кэшировать gid %u, запись уже существует"
+
+#: plugins/sudoers/pwutil.c:625 plugins/sudoers/pwutil.c:643
+#: plugins/sudoers/pwutil.c:704 plugins/sudoers/pwutil.c:753
+#, c-format
+msgid "unable to cache group %s"
+msgstr "не удаётся кэшировать группу %s"
+
+#: plugins/sudoers/pwutil.c:638
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "не удаётся кэшировать группу %s, запись уже существует"
+
+#: plugins/sudoers/pwutil.c:900 plugins/sudoers/pwutil.c:985
+#: plugins/sudoers/pwutil.c:1039 plugins/sudoers/pwutil.c:1095
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "не удаётся кэшировать список групп для %s, запись уже существует"
+
+#: plugins/sudoers/pwutil.c:906 plugins/sudoers/pwutil.c:990
+#: plugins/sudoers/pwutil.c:1045 plugins/sudoers/pwutil.c:1100
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "не удаётся кэшировать список групп для %s"
+
+#: plugins/sudoers/pwutil.c:979
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "не удаётся разобрать записи групп для %s"
+
+#: plugins/sudoers/pwutil.c:1089
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "не удаётся разобрать записи идентификаторов групп для %s"
+
+#: plugins/sudoers/set_perms.c:120 plugins/sudoers/set_perms.c:457
+#: plugins/sudoers/set_perms.c:870 plugins/sudoers/set_perms.c:1186
+#: plugins/sudoers/set_perms.c:1490
+msgid "perm stack overflow"
+msgstr "переполнение стека доступа"
+
+#: plugins/sudoers/set_perms.c:131 plugins/sudoers/set_perms.c:387
+#: plugins/sudoers/set_perms.c:468 plugins/sudoers/set_perms.c:736
+#: plugins/sudoers/set_perms.c:881 plugins/sudoers/set_perms.c:1109
+#: plugins/sudoers/set_perms.c:1197 plugins/sudoers/set_perms.c:1422
+#: plugins/sudoers/set_perms.c:1501 plugins/sudoers/set_perms.c:1592
+msgid "perm stack underflow"
+msgstr "исчерпание стека доступа"
+
+#: plugins/sudoers/set_perms.c:191 plugins/sudoers/set_perms.c:515
+#: plugins/sudoers/set_perms.c:1251 plugins/sudoers/set_perms.c:1535
+msgid "unable to change to root gid"
+msgstr "не удаётся изменить идентификатор группы на root"
+
+#: plugins/sudoers/set_perms.c:282 plugins/sudoers/set_perms.c:612
+#: plugins/sudoers/set_perms.c:1013 plugins/sudoers/set_perms.c:1328
+msgid "unable to change to runas gid"
+msgstr "не удаётся изменить идентификатор группы на runas"
+
+#: plugins/sudoers/set_perms.c:287 plugins/sudoers/set_perms.c:617
+#: plugins/sudoers/set_perms.c:1018 plugins/sudoers/set_perms.c:1333
+msgid "unable to set runas group vector"
+msgstr "не удаётся установить вектор группы выполнения"
+
+#: plugins/sudoers/set_perms.c:298 plugins/sudoers/set_perms.c:628
+#: plugins/sudoers/set_perms.c:1027 plugins/sudoers/set_perms.c:1342
+msgid "unable to change to runas uid"
+msgstr "не удаётся изменить идентификатор пользователя на runas"
+
+#: plugins/sudoers/set_perms.c:320 plugins/sudoers/set_perms.c:650
+#: plugins/sudoers/set_perms.c:1047 plugins/sudoers/set_perms.c:1362
+msgid "unable to change to sudoers gid"
+msgstr "не удаётся изменить идентификатор группы на sudoers"
+
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579
+msgid "too many processes"
+msgstr "слишком много процессов"
+
+#: plugins/sudoers/solaris_audit.c:62
+msgid "unable to get current working directory"
+msgstr "не удаётся получить текущий рабочий каталог"
+
+#: plugins/sudoers/solaris_audit.c:70
+#, c-format
+msgid "truncated audit path ctx->user.cmnd: %s"
+msgstr "усечённый путь аудита ctx->user.cmnd: %s"
+
+#: plugins/sudoers/solaris_audit.c:77
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "усечённый путь аудита argv[0]: %s"
+
+#: plugins/sudoers/sssd.c:581
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "не удаётся инициализировать источник SSS. Установлен ли SSSD на вашей системе?"
+
+#: plugins/sudoers/sssd.c:589 plugins/sudoers/sssd.c:598
+#: plugins/sudoers/sssd.c:607 plugins/sudoers/sssd.c:616
+#: plugins/sudoers/sssd.c:625
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "не удаётся найти символ «%s» в %s"
+
+#: plugins/sudoers/sudoers.c:250
+#, c-format
+msgid "unable to get defaults from %s"
+msgstr "не удаётся получить значения по умолчанию из %s"
+
+#: plugins/sudoers/sudoers.c:259
+msgid "no valid sudoers sources found, quitting"
+msgstr "не найдены корректные источники данных sudoers, завершение работы"
+
+#: plugins/sudoers/sudoers.c:366
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers указывает, что root не имеет права выполнять sudo"
+
+#: plugins/sudoers/sudoers.c:375
+msgid "user not allowed to override closefrom limit"
+msgstr "пользователю не разрешено переопределять ограничения closefrom"
+
+#: plugins/sudoers/sudoers.c:376
+msgid "you are not permitted to use the -C option"
+msgstr "вам не разрешено использовать параметр -C"
+
+#: plugins/sudoers/sudoers.c:440
+msgid "no tty"
+msgstr "нет tty"
+
+#: plugins/sudoers/sudoers.c:441
+msgid "sorry, you must have a tty to run sudo"
+msgstr "извините, для запуска sudo у вас должен быть tty"
+
+#: plugins/sudoers/sudoers.c:449
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "некорректная оболочка для пользователя %s: %s"
+
+#: plugins/sudoers/sudoers.c:491
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "пользователю не разрешено изменять корневой каталог на %s"
+
+#: plugins/sudoers/sudoers.c:493
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "вам не разрешено использовать параметр -R с %s"
+
+#: plugins/sudoers/sudoers.c:506
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "пользователю не разрешено изменять каталог на %s"
+
+#: plugins/sudoers/sudoers.c:507
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "вам не разрешено использовать параметр -D с %s"
+
+#: plugins/sudoers/sudoers.c:542
+msgid "command in current directory"
+msgstr "команда в текущем каталоге"
+
+#: plugins/sudoers/sudoers.c:557
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr "«cd» — встроенная команда оболочки, она не может быть запущена напрямую."
+
+#: plugins/sudoers/sudoers.c:559
+msgid "the -s option may be used to run a privileged shell."
+msgstr "параметр -s может использоваться для запуска привилегированной оболочки."
+
+#: plugins/sudoers/sudoers.c:561
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr "параметр -D может использоваться для выполнения команды в определенном каталоге."
+
+#: plugins/sudoers/sudoers.c:570
+msgid "user not allowed to set a command timeout"
+msgstr "пользователю не разрешено устанавливать время ожидания выполнения команды"
+
+#: plugins/sudoers/sudoers.c:572
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "извините, вам не разрешено устанавливать время ожидания выполнения команды"
+
+#: plugins/sudoers/sudoers.c:580
+msgid "user not allowed to preserve the environment"
+msgstr "пользователю не разрешено сохранять окружение"
+
+#: plugins/sudoers/sudoers.c:582
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "извините, вам не разрешено сохранять окружение"
+
+#: plugins/sudoers/sudoers.c:618
+msgid "no command specified"
+msgstr "не указана команда"
+
+#: plugins/sudoers/sudoers.c:759
+msgid "error setting user-specified environment variables"
+msgstr "ошибка при назначении переменных окружения, заданных пользователем"
+
+#: plugins/sudoers/sudoers.c:1211
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "sudoedit не нужно запускать через sudo"
+
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:1613
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "не удаётся прочитать %s"
+
+#: plugins/sudoers/sudoers.c:1321 plugins/sudoers/visudo.c:1123
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s не является обычным файлом"
+
+#: plugins/sudoers/sudoers.c:1325 plugins/sudoers/timestamp.c:272 toke.l:1355
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s принадлежит uid %u, должно быть %u"
+
+#: plugins/sudoers/sudoers.c:1330 plugins/sudoers/timestamp.c:279 toke.l:1360
+#, c-format
+msgid "%s is world writable"
+msgstr "Запись в %s доступна любому пользователю"
+
+#: plugins/sudoers/sudoers.c:1334 plugins/sudoers/timestamp.c:284 toke.l:1363
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s принадлежит gid %u, должно быть %u"
+
+#: plugins/sudoers/sudoers.c:1363
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "использовать «-c %s» может только root"
+
+#: plugins/sudoers/sudoers.c:1382
+#, c-format
+msgid "unknown login class %s"
+msgstr "неизвестный класс входа %s"
+
+#: plugins/sudoers/sudoers_cb.c:120 plugins/sudoers/sudoers_cb.c:135
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "не удаётся определить адрес узла %s"
+
+#: plugins/sudoers/sudoreplay.c:252
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "недопустимый параметр фильтра: %s"
+
+#: plugins/sudoers/sudoreplay.c:268
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "недопустимое значение максимального ожидания: %s"
+
+#: plugins/sudoers/sudoreplay.c:291
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "некорректный коэффициент скорости: %s"
+
+#: plugins/sudoers/sudoreplay.c:326
+#, c-format
+msgid "invalid time offset %s"
+msgstr "некорректное смещение времени %s"
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:340
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/расписание: %s"
+
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Воспроизведение сеанса sudo: %s"
+
+#: plugins/sudoers/sudoreplay.c:634
+msgid "unable to set tty to raw mode"
+msgstr "не удаётся переключить tty в режим без обработки данных"
+
+#: plugins/sudoers/sudoreplay.c:685
+msgid "Warning: your terminal is too small to properly replay the log."
+msgstr "Внимание: размера вашего терминала недостаточно для корректного воспроизведения журнала."
+
+#: plugins/sudoers/sudoreplay.c:686
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Формат журнала — %d x %d, формат вашего терминала — %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:714
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Воспроизведение завершено, нажмите любую клавишу, чтобы вернуться в терминал."
+
+#: plugins/sudoers/sudoreplay.c:1217 plugins/sudoers/sudoreplay.c:1247
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "неоднозначное выражение «%s»"
+
+#: plugins/sudoers/sudoreplay.c:1269
+msgid "unmatched ')' in expression"
+msgstr "закрывающая скобка «)» без открывающей в выражении"
+
+#: plugins/sudoers/sudoreplay.c:1273
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "неизвестный ключ поиска «%s»"
+
+#: plugins/sudoers/sudoreplay.c:1288
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s требуется аргумент"
+
+#: plugins/sudoers/sudoreplay.c:1298
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "не удаётся разобрать дату «%s»"
+
+#: plugins/sudoers/sudoreplay.c:1307
+msgid "unmatched '(' in expression"
+msgstr "открывающая скобка «(» без закрывающей в выражении"
+
+#: plugins/sudoers/sudoreplay.c:1309
+msgid "illegal trailing \"or\""
+msgstr "некорректное завершающее «or»"
+
+#: plugins/sudoers/sudoreplay.c:1311
+msgid "illegal trailing \"!\""
+msgstr "некорректное завершающее «!»"
+
+#: plugins/sudoers/sudoreplay.c:1417
+#, c-format
+msgid "unknown search type %d"
+msgstr "неизвестный тип поиска %d"
+
+#: plugins/sudoers/sudoreplay.c:1679
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "использование: %s [-hnRS] [-d каталог] [-m число] [-s число] идентификатор\n"
+
+#: plugins/sudoers/sudoreplay.c:1681
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "использование: %s [-h] [-d каталог] -l [выражение для поиска]\n"
+
+#: plugins/sudoers/sudoreplay.c:1695
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - воспроизвести журналы сеансов sudo\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1697
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Параметры:\n"
+" -d, --directory=кат каталог для журналов сеанса\n"
+" -f, --filter=фильтр какие операции ввода-вывода следует показывать\n"
+" -h, --help показать справку и выйти\n"
+" -l, --list перечислить доступные идентификаторы сеансов, опционально соответствующих выражению\n"
+" -m, --max-wait=сек максимальное время ожидания между событиями, в секундах\n"
+" -n, --non-interactive не задавать вопросов, данные сеанса записываются в стандартный вывод\n"
+" -R, --no-resize не пытаться изменить размер терминала\n"
+" -S, --suspend-wait ожидать, пока исполнение команды приостановлено\n"
+" -s, --speed=чис коэффициент ускорения или замедления вывода данных\n"
+" -V, --version показать версию и выйти"
+
+#: plugins/sudoers/testsudoers.c:392
+#, c-format
+msgid ""
+"\n"
+"Invalid shell for user %s: %s\n"
+msgstr ""
+"\n"
+"Некорректная оболочка для пользователя %s: %s\n"
+
+#: plugins/sudoers/testsudoers.c:411
+msgid ""
+"\n"
+"Password required"
+msgstr ""
+"\n"
+"Требуется указать пароль"
+
+#: plugins/sudoers/testsudoers.c:422
+msgid ""
+"\n"
+"Parse error"
+msgstr ""
+"\n"
+"Ошибка разбора"
+
+#: plugins/sudoers/testsudoers.c:425
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Команда разрешена"
+
+#: plugins/sudoers/testsudoers.c:428
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Команда заблокирована"
+
+#: plugins/sudoers/testsudoers.c:431
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Соответствующая команда не найдена"
+
+#: plugins/sudoers/timestamp.c:364 plugins/sudoers/timestamp.c:711
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "не удаётся обрезать файл временных метки до %lld байт"
+
+#: plugins/sudoers/timestamp.c:908
+msgid "ignoring time stamp from the future"
+msgstr "игнорируется метка времени из будущего"
+
+#: plugins/sudoers/timestamp.c:931
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "метка времени находится слишком далеко в будущем: %20.20s"
+
+#: plugins/sudoers/timestamp.c:1067
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "не удаётся заблокировать файл журнала %s"
+
+#: plugins/sudoers/timestamp.c:1114
+#, c-format
+msgid "%s:%d:%d timestampowner: unknown user %s"
+msgstr "%s:%d:%d: неизвестный пользователь «%s»"
+
+#: plugins/sudoers/toke_util.c:159
+msgid "sudoedit should not be specified with a path"
+msgstr "sudoedit не следует указывать вместе с путём"
+
+#: plugins/sudoers/visudo.c:308 plugins/sudoers/visudo.c:714
+#, c-format
+msgid "press return to edit %s: "
+msgstr "нажмите Enter для редактирования %s: "
+
+#: plugins/sudoers/visudo.c:323
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "данные сеанса редактирования оставлены в %s"
+
+#: plugins/sudoers/visudo.c:401
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "указанный редактор (%s) не существует"
+
+#: plugins/sudoers/visudo.c:406
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "редактор не найден (путь к редактору = %s)"
+
+#: plugins/sudoers/visudo.c:494 plugins/sudoers/visudo.c:786
+#, c-format
+msgid "unable to stat %s"
+msgstr "не удаётся выполнить stat для %s"
+
+#: plugins/sudoers/visudo.c:514 plugins/sudoers/visudo.c:522
+msgid "write error"
+msgstr "ошибка записи"
+
+#: plugins/sudoers/visudo.c:568
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "не удаётся выполнить stat для временного файла (%s), %s не изменён"
+
+#: plugins/sudoers/visudo.c:575
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "временный файл (%s) имеет нулевой размер, %s не изменён"
+
+#: plugins/sudoers/visudo.c:581
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "ошибка редактора (%s), %s не изменён"
+
+#: plugins/sudoers/visudo.c:613
+#, c-format
+msgid "%s unchanged"
+msgstr "%s не изменён"
+
+#: plugins/sudoers/visudo.c:661
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "не удаётся повторно открыть временный файл (%s), %s не изменён."
+
+#: plugins/sudoers/visudo.c:674
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "не удаётся разобрать временный файл (%s), неизвестная ошибка"
+
+#: plugins/sudoers/visudo.c:760 plugins/sudoers/visudo.c:790
+#: plugins/sudoers/visudo.c:797
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "не удаётся назначить (uid, gid) %s в (%u, %u)"
+
+#: plugins/sudoers/visudo.c:825
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s и %s не находятся на одной файловой системе, для переименования используется mv"
+
+#: plugins/sudoers/visudo.c:836
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "ошибка команды: «%s %s %s», %s не изменён"
+
+#: plugins/sudoers/visudo.c:843
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "не удаётся переименовать %s, %s не изменён"
+
+#: plugins/sudoers/visudo.c:864
+msgid "What now? "
+msgstr "Что дальше? "
+
+#: plugins/sudoers/visudo.c:878
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Параметры:\n"
+" (e) — повторно отредактировать файл sudoers\n"
+" (x) — выйти без сохранения изменений файла sudoers\n"
+" (Q) — выйти с сохранением изменений файла sudoers (ОПАСНО!)\n"
+
+#: plugins/sudoers/visudo.c:923
+#, c-format
+msgid "unable to run %s"
+msgstr "не удаётся запустить %s"
+
+#: plugins/sudoers/visudo.c:954
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: некорректный владелец (uid, gid), должен быть (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:965
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: некорректные права доступа, должны быть 0%o\n"
+
+#: plugins/sudoers/visudo.c:1017 plugins/sudoers/visudo.c:1024
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: успешно обработан\n"
+
+#: plugins/sudoers/visudo.c:1043
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s занят, попробуйте позже"
+
+#: plugins/sudoers/visudo.c:1047
+msgid "Edit anyway? [y/N]"
+msgstr "Всё равно редактировать? [y/N]"
+
+#: plugins/sudoers/visudo.c:1206
+msgid "the -x option will be removed in a future release"
+msgstr "параметр -x будет удалён в одной из будущих версий"
+
+#: plugins/sudoers/visudo.c:1208
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "пожалуйста, используйте программу cvtsudoers"
+
+#: plugins/sudoers/visudo.c:1228
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "Внимание: %s:%d:%d: неиспользуемый %s \"%s\""
+
+#: plugins/sudoers/visudo.c:1341
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - безопасное редактирование файла sudoers\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1343
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -I, --no-includes do not edit include files\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Параметры:\n"
+" -c, --check режим только проверки\n"
+" -f, --file=sudoers указать путь к файлу sudoers\n"
+" -h, --help показать справку и выйти\n"
+" -I, --no-includes не редактировать включенные файлы\n"
+" -q, --quiet скрыть сообщения о синтаксических ошибках\n"
+" -s, --strict строгая проверка синтаксиса\n"
+" -V, --version показать версию и выйти\n"
+
+#: toke.l:184
+msgid "empty string"
+msgstr "пустая строка"
+
+#: toke.l:196 toke.l:566
+msgid "empty group"
+msgstr "пустая группа"
+
+#: toke.l:206 toke.l:564
+msgid "empty netgroup"
+msgstr "пустая сетевая группа"
+
+#: toke.l:284
+msgid "unterminated regular expression"
+msgstr "незавершённое регулярное выражение"
+
+#: toke.l:358 toke.l:370 toke.l:382 toke.l:398 toke.l:417 toke.l:457
+msgid "invalid line continuation"
+msgstr "некорректное продолжение строки"
+
+#: toke.l:603 toke.l:615
+msgid "invalid IPv6 address"
+msgstr "некорректный адрес IPv6"
+
+#: toke.l:863
+msgid "unexpected line break in string"
+msgstr "неожиданный перенос строки"
+
+#: toke.l:982
+msgid "ignoring editor backup file"
+msgstr "игнорируется резервная копия файла, созданная редактором"
+
+#: toke.l:985
+msgid "ignoring file name containing '.'"
+msgstr "игнорируется имя файла, содержащее '.'"
+
+#: toke.l:1310
+msgid "too many levels of includes"
+msgstr "ошибка синтаксиса"
+
+#~ msgid "\thost unmatched"
+#~ msgstr "\t соответствующий узел не найден"
+
+#~ msgid "timestamp owner (%s): No such user"
+#~ msgstr "владелец временной метки (%s): Нет такого пользователя"
+
+#~ msgid ""
+#~ "\n"
+#~ "LDAP Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Роль LDAP: НЕИЗВЕСТНО\n"
+
+#~ msgid " Order: %s\n"
+#~ msgstr " Порядок: %s\n"
diff --git a/plugins/sudoers/po/sk.mo b/plugins/sudoers/po/sk.mo
new file mode 100644
index 0000000..ec67774
--- /dev/null
+++ b/plugins/sudoers/po/sk.mo
Binary files differ
diff --git a/plugins/sudoers/po/sk.po b/plugins/sudoers/po/sk.po
new file mode 100644
index 0000000..396072f
--- /dev/null
+++ b/plugins/sudoers/po/sk.po
@@ -0,0 +1,1892 @@
+# Portable object template file for the sudoers plugin
+# This file is put in the public domain.
+# Todd C. Miller <Todd.Miller@courtesan.com>, 2011-2015
+# Dušan Kazik <prescott66@gmail.com>, 2015
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.8.15b1\n"
+"Report-Msgid-Bugs-To: http://www.sudo.ws/bugs\n"
+"POT-Creation-Date: 2015-09-10 14:28-0600\n"
+"PO-Revision-Date: 2015-10-05 13:26+0200\n"
+"Last-Translator: Dušan Kazik <prescott66@gmail.com>\n"
+"Language-Team: Slovak <sk-i18n@lists.linux.sk>\n"
+"Language: sk\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+"X-Generator: Poedit 1.8.5\n"
+"X-Poedit-Basepath: .\n"
+"X-Poedit-SearchPath-0: .\n"
+
+#: confstr.sh:1
+msgid "syntax error"
+msgstr "chyba syntaxe"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "Heslo používateľa %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] heslo pre používateľa %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Heslo: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** BEZPEČNOSTNÉ informácie pre %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Prepáčte, skúste to znovu."
+
+#: gram.y:183 gram.y:201 gram.y:207 gram.y:213 gram.y:219 gram.y:225
+#: gram.y:241 gram.y:248 gram.y:255 gram.y:262 gram.y:269 gram.y:285
+#: gram.y:308 gram.y:315 gram.y:322 gram.y:329 gram.y:336 gram.y:391
+#: gram.y:399 gram.y:409 gram.y:439 gram.y:446 gram.y:453 gram.y:460
+#: gram.y:572 gram.y:579 gram.y:588 gram.y:597 gram.y:614 gram.y:670
+#: gram.y:677 gram.y:684 gram.y:692 gram.y:784 gram.y:791 gram.y:798
+#: gram.y:805 gram.y:812 gram.y:838 gram.y:845 gram.y:852 gram.y:1136
+#: gram.y:1143 plugins/sudoers/alias.c:123 plugins/sudoers/alias.c:136
+#: plugins/sudoers/auth/bsdauth.c:141 plugins/sudoers/auth/kerb5.c:119
+#: plugins/sudoers/auth/kerb5.c:145 plugins/sudoers/auth/pam.c:397
+#: plugins/sudoers/auth/pam.c:445 plugins/sudoers/auth/rfc1938.c:109
+#: plugins/sudoers/auth/sia.c:110 plugins/sudoers/defaults.c:516
+#: plugins/sudoers/defaults.c:720 plugins/sudoers/defaults.c:880
+#: plugins/sudoers/editor.c:64 plugins/sudoers/editor.c:82
+#: plugins/sudoers/editor.c:92 plugins/sudoers/env.c:233
+#: plugins/sudoers/group_plugin.c:133 plugins/sudoers/iolog.c:586
+#: plugins/sudoers/iolog.c:618 plugins/sudoers/iolog_path.c:167
+#: plugins/sudoers/ldap.c:446 plugins/sudoers/ldap.c:477
+#: plugins/sudoers/ldap.c:529 plugins/sudoers/ldap.c:562
+#: plugins/sudoers/ldap.c:914 plugins/sudoers/ldap.c:1061
+#: plugins/sudoers/ldap.c:1348 plugins/sudoers/ldap.c:1521
+#: plugins/sudoers/ldap.c:1597 plugins/sudoers/ldap.c:1733
+#: plugins/sudoers/ldap.c:1757 plugins/sudoers/ldap.c:1787
+#: plugins/sudoers/ldap.c:1840 plugins/sudoers/ldap.c:1855
+#: plugins/sudoers/ldap.c:1951 plugins/sudoers/ldap.c:1984
+#: plugins/sudoers/ldap.c:2137 plugins/sudoers/ldap.c:2234
+#: plugins/sudoers/ldap.c:3041 plugins/sudoers/ldap.c:3074
+#: plugins/sudoers/ldap.c:3388 plugins/sudoers/ldap.c:3416
+#: plugins/sudoers/ldap.c:3427 plugins/sudoers/ldap.c:3517
+#: plugins/sudoers/ldap.c:3533 plugins/sudoers/linux_audit.c:76
+#: plugins/sudoers/logging.c:188 plugins/sudoers/logging.c:662
+#: plugins/sudoers/logging.c:916 plugins/sudoers/match.c:501
+#: plugins/sudoers/match.c:537 plugins/sudoers/match.c:699
+#: plugins/sudoers/match.c:756 plugins/sudoers/parse.c:235
+#: plugins/sudoers/parse.c:247 plugins/sudoers/parse.c:262
+#: plugins/sudoers/parse.c:274 plugins/sudoers/policy.c:384
+#: plugins/sudoers/policy.c:579 plugins/sudoers/prompt.c:93
+#: plugins/sudoers/sssd.c:160 plugins/sudoers/sssd.c:192
+#: plugins/sudoers/sssd.c:235 plugins/sudoers/sssd.c:242
+#: plugins/sudoers/sssd.c:278 plugins/sudoers/sssd.c:323
+#: plugins/sudoers/sssd.c:917 plugins/sudoers/sssd.c:1050
+#: plugins/sudoers/sudoers.c:159 plugins/sudoers/sudoers.c:294
+#: plugins/sudoers/sudoers.c:304 plugins/sudoers/sudoers.c:312
+#: plugins/sudoers/sudoers.c:365 plugins/sudoers/sudoers.c:663
+#: plugins/sudoers/sudoers.c:749 plugins/sudoers/sudoers.c:793
+#: plugins/sudoers/sudoers_debug.c:107 plugins/sudoers/sudoreplay.c:472
+#: plugins/sudoers/sudoreplay.c:668 plugins/sudoers/sudoreplay.c:780
+#: plugins/sudoers/sudoreplay.c:820 plugins/sudoers/sudoreplay.c:829
+#: plugins/sudoers/sudoreplay.c:839 plugins/sudoers/sudoreplay.c:847
+#: plugins/sudoers/sudoreplay.c:851 plugins/sudoers/sudoreplay.c:1007
+#: plugins/sudoers/sudoreplay.c:1011 plugins/sudoers/testsudoers.c:130
+#: plugins/sudoers/testsudoers.c:188 plugins/sudoers/testsudoers.c:215
+#: plugins/sudoers/testsudoers.c:232 plugins/sudoers/timestamp.c:390
+#: plugins/sudoers/timestamp.c:426 plugins/sudoers/timestamp.c:838
+#: plugins/sudoers/toke_util.c:56 plugins/sudoers/toke_util.c:109
+#: plugins/sudoers/toke_util.c:147 plugins/sudoers/visudo.c:152
+#: plugins/sudoers/visudo.c:213 plugins/sudoers/visudo.c:297
+#: plugins/sudoers/visudo.c:303 plugins/sudoers/visudo.c:433
+#: plugins/sudoers/visudo.c:974 plugins/sudoers/visudo.c:1018
+#: plugins/sudoers/visudo.c:1114 toke.l:785 toke.l:806 toke.l:816 toke.l:924
+#: toke.l:1082
+msgid "unable to allocate memory"
+msgstr "nie je možné alokovať pamäť"
+
+#: gram.y:471
+msgid "a digest requires a path name"
+msgstr ""
+
+#: gram.y:1136 gram.y:1143 plugins/sudoers/auth/pam.c:397
+#: plugins/sudoers/auth/pam.c:445 plugins/sudoers/auth/rfc1938.c:109
+#: plugins/sudoers/defaults.c:516 plugins/sudoers/defaults.c:720
+#: plugins/sudoers/defaults.c:880 plugins/sudoers/editor.c:64
+#: plugins/sudoers/editor.c:82 plugins/sudoers/editor.c:92
+#: plugins/sudoers/env.c:233 plugins/sudoers/group_plugin.c:133
+#: plugins/sudoers/iolog.c:586 plugins/sudoers/iolog.c:618
+#: plugins/sudoers/iolog_path.c:167 plugins/sudoers/ldap.c:446
+#: plugins/sudoers/ldap.c:477 plugins/sudoers/ldap.c:529
+#: plugins/sudoers/ldap.c:562 plugins/sudoers/ldap.c:914
+#: plugins/sudoers/ldap.c:1061 plugins/sudoers/ldap.c:1348
+#: plugins/sudoers/ldap.c:1521 plugins/sudoers/ldap.c:1597
+#: plugins/sudoers/ldap.c:1733 plugins/sudoers/ldap.c:1757
+#: plugins/sudoers/ldap.c:1787 plugins/sudoers/ldap.c:1840
+#: plugins/sudoers/ldap.c:1855 plugins/sudoers/ldap.c:1951
+#: plugins/sudoers/ldap.c:1984 plugins/sudoers/ldap.c:2137
+#: plugins/sudoers/ldap.c:2234 plugins/sudoers/ldap.c:3041
+#: plugins/sudoers/ldap.c:3074 plugins/sudoers/ldap.c:3388
+#: plugins/sudoers/ldap.c:3416 plugins/sudoers/ldap.c:3427
+#: plugins/sudoers/ldap.c:3517 plugins/sudoers/ldap.c:3533
+#: plugins/sudoers/linux_audit.c:76 plugins/sudoers/logging.c:188
+#: plugins/sudoers/logging.c:916 plugins/sudoers/match.c:501
+#: plugins/sudoers/match.c:537 plugins/sudoers/match.c:699
+#: plugins/sudoers/match.c:756 plugins/sudoers/parse.c:235
+#: plugins/sudoers/parse.c:247 plugins/sudoers/parse.c:262
+#: plugins/sudoers/parse.c:274 plugins/sudoers/policy.c:97
+#: plugins/sudoers/policy.c:106 plugins/sudoers/policy.c:115
+#: plugins/sudoers/policy.c:139 plugins/sudoers/policy.c:250
+#: plugins/sudoers/policy.c:271 plugins/sudoers/policy.c:280
+#: plugins/sudoers/policy.c:319 plugins/sudoers/policy.c:329
+#: plugins/sudoers/policy.c:338 plugins/sudoers/policy.c:384
+#: plugins/sudoers/policy.c:579 plugins/sudoers/prompt.c:93
+#: plugins/sudoers/set_perms.c:356 plugins/sudoers/set_perms.c:695
+#: plugins/sudoers/set_perms.c:1054 plugins/sudoers/set_perms.c:1350
+#: plugins/sudoers/set_perms.c:1514 plugins/sudoers/sssd.c:160
+#: plugins/sudoers/sssd.c:192 plugins/sudoers/sssd.c:235
+#: plugins/sudoers/sssd.c:242 plugins/sudoers/sssd.c:278
+#: plugins/sudoers/sssd.c:323 plugins/sudoers/sssd.c:917
+#: plugins/sudoers/sssd.c:1050 plugins/sudoers/sudoers.c:159
+#: plugins/sudoers/sudoers.c:294 plugins/sudoers/sudoers.c:304
+#: plugins/sudoers/sudoers.c:312 plugins/sudoers/sudoers.c:365
+#: plugins/sudoers/sudoers.c:663 plugins/sudoers/sudoers.c:749
+#: plugins/sudoers/sudoers.c:793 plugins/sudoers/sudoers_debug.c:106
+#: plugins/sudoers/sudoreplay.c:472 plugins/sudoers/sudoreplay.c:668
+#: plugins/sudoers/sudoreplay.c:780 plugins/sudoers/sudoreplay.c:820
+#: plugins/sudoers/sudoreplay.c:829 plugins/sudoers/sudoreplay.c:839
+#: plugins/sudoers/sudoreplay.c:847 plugins/sudoers/sudoreplay.c:851
+#: plugins/sudoers/sudoreplay.c:1007 plugins/sudoers/sudoreplay.c:1011
+#: plugins/sudoers/testsudoers.c:130 plugins/sudoers/testsudoers.c:188
+#: plugins/sudoers/testsudoers.c:215 plugins/sudoers/testsudoers.c:232
+#: plugins/sudoers/timestamp.c:390 plugins/sudoers/timestamp.c:426
+#: plugins/sudoers/timestamp.c:838 plugins/sudoers/toke_util.c:56
+#: plugins/sudoers/toke_util.c:109 plugins/sudoers/toke_util.c:147
+#: plugins/sudoers/visudo.c:152 plugins/sudoers/visudo.c:213
+#: plugins/sudoers/visudo.c:297 plugins/sudoers/visudo.c:303
+#: plugins/sudoers/visudo.c:433 plugins/sudoers/visudo.c:974
+#: plugins/sudoers/visudo.c:1018 plugins/sudoers/visudo.c:1114 toke.l:785
+#: toke.l:806 toke.l:816 toke.l:924 toke.l:1082
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: plugins/sudoers/alias.c:132
+#, c-format
+msgid "Alias `%s' already defined"
+msgstr "Alias „%s“ už je definovaný"
+
+#: plugins/sudoers/auth/bsdauth.c:68
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:73
+msgid "unable to begin bsd authentication"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:81
+msgid "invalid authentication type"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to initialize BSD authentication"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:52
+msgid "unable to read fwtk config"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:57
+msgid "unable to connect to authentication server"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:63 plugins/sudoers/auth/fwtk.c:87
+#: plugins/sudoers/auth/fwtk.c:120
+msgid "lost connection to authentication server"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:67
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:111
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:161
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:170
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:217
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:232
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:245
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:248
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:312
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:326
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:92
+msgid "unable to initialize PAM"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:164
+msgid "account validation failure, is your account locked?"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:168
+msgid "Account or password is expired, reset your password and try again"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:176
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:181
+msgid "Password expired, contact your system administrator"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:185
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:199
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/rfc1938.c:97 plugins/sudoers/visudo.c:218
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:73
+msgid "failed to initialise the ACE API library"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:99
+msgid "unable to contact the SecurID server"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "User ID locked for SecurID Authentication"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:112 plugins/sudoers/auth/securid5.c:163
+msgid "invalid username length for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:116 plugins/sudoers/auth/securid5.c:168
+msgid "invalid Authentication Handle for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:120
+msgid "SecurID communication failed"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:124 plugins/sudoers/auth/securid5.c:207
+msgid "unknown SecurID error"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:158
+msgid "invalid passcode length for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/sia.c:120
+msgid "unable to initialize SIA session"
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:126
+msgid "invalid authentication methods"
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:128
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:225 plugins/sudoers/auth/sudo_auth.c:274
+msgid "no authentication methods"
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:227
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:276
+msgid "Unable to initialize authentication methods."
+msgstr "Nie je možné inicializovať spôsoby overenia totožnosti."
+
+#: plugins/sudoers/auth/sudo_auth.c:435
+msgid "Authentication methods:"
+msgstr "Spôsoby overenia totožnosti:"
+
+#: plugins/sudoers/bsm_audit.c:111 plugins/sudoers/bsm_audit.c:200
+msgid "Could not determine audit condition"
+msgstr ""
+
+#: plugins/sudoers/bsm_audit.c:172 plugins/sudoers/bsm_audit.c:260
+msgid "unable to commit audit record"
+msgstr ""
+
+#: plugins/sudoers/check.c:250
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Veríme, že ste boli poučený miestnym správcom systému.\n"
+"Dodržiavajte tieto tri zásady:\n"
+"\n"
+" 1.) Rešpektujte súkromie iných.\n"
+" 2.) Premýšľajte pred tým, než niečo napíšete.\n"
+" 3.) S veľkou mocou prichádza veľká zodpovednosť.\n"
+"\n"
+
+#: plugins/sudoers/check.c:293 plugins/sudoers/check.c:303
+#: plugins/sudoers/sudoers.c:699 plugins/sudoers/sudoers.c:728
+#, c-format
+msgid "unknown uid: %u"
+msgstr ""
+
+#: plugins/sudoers/check.c:298 plugins/sudoers/policy.c:751
+#: plugins/sudoers/sudoers.c:1095 plugins/sudoers/testsudoers.c:206
+#: plugins/sudoers/testsudoers.c:361
+#, c-format
+msgid "unknown user: %s"
+msgstr "neznámy používateľ: %s"
+
+#: plugins/sudoers/def_data.c:27
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:31
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:35
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:39
+msgid "Put OTP prompt on its own line"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:43
+msgid "Ignore '.' in $PATH"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:47
+msgid "Always send mail when sudo is run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:51
+msgid "Send mail if user authentication fails"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:55
+msgid "Send mail if the user is not in sudoers"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:59
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:63
+msgid "Send mail if the user is not allowed to run a command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:67
+msgid "Send mail if the user tries to run a command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:71
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:75
+msgid "Lecture user the first time they run sudo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:79
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:83
+msgid "Require users to authenticate by default"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:87
+msgid "Root may run sudo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:91
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:95
+msgid "Log the year in the (non-syslog) log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:99
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:103
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:107
+msgid "Always set $HOME to the target user's home directory"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:111
+msgid "Allow some information gathering to give useful error messages"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:115
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:119
+msgid "Insult the user when they enter an incorrect password"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:123
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:127
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:131
+msgid "Prompt for root's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:135
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:139
+msgid "Prompt for the target user's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:143
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:147
+msgid "Set the LOGNAME and USER environment variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:151
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:155
+msgid "Don't initialize the group vector to that of the target user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:159
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:163
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:167
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:171
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:175
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:179
+#, c-format
+msgid "Path to log file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:183
+#, c-format
+msgid "Path to mail program: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:187
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:191
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:195
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:199
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:203
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:207
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:211
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:215
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:219
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:223
+#, c-format
+msgid "Default password prompt: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:227
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr ""
+
+#: plugins/sudoers/def_data.c:231
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:235
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:239
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:243
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:247
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:251
+msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:255
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:259
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:263
+msgid "If set, users may override the value of `closefrom' with the -C option"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:267
+msgid "Allow users to set arbitrary environment variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:271
+msgid "Reset the environment to a default set of variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:275
+msgid "Environment variables to check for sanity:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:279
+msgid "Environment variables to remove:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:283
+msgid "Environment variables to preserve:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:287
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:291
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:295
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:299
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:303
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:307
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:311
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:315
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:319
+msgid "Log user's input for the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:323
+msgid "Log the output of the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:327
+msgid "Compress I/O logs using zlib"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:331
+msgid "Always run commands in a pseudo-tty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:335
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:339
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:343
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:347
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:351
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:355
+msgid "Set of permitted privileges"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:359
+msgid "Set of limit privileges"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:363
+msgid "Run commands on a pty in the background"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:367
+msgid "PAM service name to use"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:371
+msgid "PAM service name to use for login shells"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:375
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:379
+msgid "Create a new PAM session for the command to run in"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:383
+#, c-format
+msgid "Maximum I/O log sequence number: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:387
+msgid "Enable sudoers netgroup support"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:391
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:199 plugins/sudoers/defaults.c:608
+#: plugins/sudoers/visudo_json.c:633 plugins/sudoers/visudo_json.c:668
+#, c-format
+msgid "unknown defaults entry `%s'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:207 plugins/sudoers/defaults.c:217
+#: plugins/sudoers/defaults.c:241 plugins/sudoers/defaults.c:256
+#: plugins/sudoers/defaults.c:269 plugins/sudoers/defaults.c:282
+#: plugins/sudoers/defaults.c:295 plugins/sudoers/defaults.c:315
+#: plugins/sudoers/defaults.c:325
+#, c-format
+msgid "value `%s' is invalid for option `%s'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:210 plugins/sudoers/defaults.c:220
+#: plugins/sudoers/defaults.c:228 plugins/sudoers/defaults.c:251
+#: plugins/sudoers/defaults.c:264 plugins/sudoers/defaults.c:277
+#: plugins/sudoers/defaults.c:290 plugins/sudoers/defaults.c:310
+#: plugins/sudoers/defaults.c:321
+#, c-format
+msgid "no value specified for `%s'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:233
+#, c-format
+msgid "values for `%s' must start with a '/'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:301
+#, c-format
+msgid "option `%s' does not take a value"
+msgstr ""
+
+#: plugins/sudoers/env.c:295 plugins/sudoers/env.c:302
+#: plugins/sudoers/env.c:407 plugins/sudoers/ldap.c:450
+#: plugins/sudoers/ldap.c:540 plugins/sudoers/ldap.c:1152
+#: plugins/sudoers/ldap.c:1354 plugins/sudoers/ldap.c:1526
+#: plugins/sudoers/ldap.c:1682 plugins/sudoers/linux_audit.c:82
+#: plugins/sudoers/logging.c:921 plugins/sudoers/policy.c:498
+#: plugins/sudoers/policy.c:507 plugins/sudoers/prompt.c:161
+#: plugins/sudoers/sudoers.c:815 plugins/sudoers/testsudoers.c:236
+#: plugins/sudoers/toke_util.c:160
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "vnútorná chyba, %s pretečenie"
+
+#: plugins/sudoers/env.c:376
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr ""
+
+#: plugins/sudoers/env.c:1052
+msgid "unable to rebuild the environment"
+msgstr ""
+
+#: plugins/sudoers/env.c:1126
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:85
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s musí byť vlastnený identifikátorom uid %d"
+
+#: plugins/sudoers/group_plugin.c:89
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:97 plugins/sudoers/sssd.c:331
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "nie je možné načítať %s:%s"
+
+#: plugins/sudoers/group_plugin.c:103
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:108
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:117
+msgid "Local IP address and netmask pairs:\n"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:92 plugins/sudoers/iolog.c:110
+#: plugins/sudoers/timestamp.c:169
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:103 plugins/sudoers/iolog.c:124
+#: plugins/sudoers/iolog.c:131 plugins/sudoers/timestamp.c:163
+#: plugins/sudoers/timestamp.c:184
+#, c-format
+msgid "unable to mkdir %s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:200 plugins/sudoers/sudoers.c:871
+#: plugins/sudoers/sudoreplay.c:300 plugins/sudoers/sudoreplay.c:769
+#: plugins/sudoers/sudoreplay.c:973 plugins/sudoers/timestamp.c:399
+#: plugins/sudoers/visudo.c:898 plugins/sudoers/visudo_json.c:1012
+#: plugins/sudoers/visudo_json.c:1025
+#, c-format
+msgid "unable to open %s"
+msgstr "nie je možné otvoriť %s"
+
+#: plugins/sudoers/iolog.c:241 plugins/sudoers/sudoers.c:875
+#: plugins/sudoers/sudoreplay.c:1084
+#, c-format
+msgid "unable to read %s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:277 plugins/sudoers/sudoreplay.c:550
+#: plugins/sudoers/timestamp.c:298 plugins/sudoers/timestamp.c:301
+#, c-format
+msgid "unable to write to %s"
+msgstr "nie je možné zapísať do %s"
+
+#: plugins/sudoers/iolog.c:342 plugins/sudoers/iolog.c:540
+#, c-format
+msgid "unable to create %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:428
+msgid "sudo_ldap_conf_add_ports: port too large"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:488
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:515
+msgid "unable to mix ldap and ldaps URIs"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:519 plugins/sudoers/ldap.c:555
+msgid "starttls not supported when using ldaps"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:626
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:629
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1138
+msgid "unable to get GMT time"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1144
+msgid "unable to format timestamp"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1830
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2372
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2374
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: UNKNOWN\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2421
+#, c-format
+msgid " Order: %s\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2429 plugins/sudoers/parse.c:555
+#: plugins/sudoers/sssd.c:1417
+#, c-format
+msgid " Commands:\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2993
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:3029
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:3286
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr ""
+
+#: plugins/sudoers/linux_audit.c:52
+msgid "unable to open audit system"
+msgstr "nie je možné otvoriť systém auditu"
+
+#: plugins/sudoers/linux_audit.c:93
+msgid "unable to send audit message"
+msgstr "nie je možné odoslať správu auditu"
+
+#: plugins/sudoers/logging.c:106
+#, c-format
+msgid "%8s : %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:134
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:159
+#, c-format
+msgid "unable to open log file: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:162
+#, c-format
+msgid "unable to lock log file: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:211
+msgid "No user or host"
+msgstr ""
+
+#: plugins/sudoers/logging.c:213
+msgid "validation failure"
+msgstr ""
+
+#: plugins/sudoers/logging.c:220
+msgid "user NOT in sudoers"
+msgstr ""
+
+#: plugins/sudoers/logging.c:222
+msgid "user NOT authorized on host"
+msgstr ""
+
+#: plugins/sudoers/logging.c:224
+msgid "command not allowed"
+msgstr ""
+
+#: plugins/sudoers/logging.c:259
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:262
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:266
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:269
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:306 plugins/sudoers/sudoers.c:471
+#: plugins/sudoers/sudoers.c:473 plugins/sudoers/sudoers.c:475
+#: plugins/sudoers/sudoers.c:477 plugins/sudoers/sudoers.c:1222
+#: plugins/sudoers/sudoers.c:1224
+#, c-format
+msgid "%s: command not found"
+msgstr ""
+
+#: plugins/sudoers/logging.c:308 plugins/sudoers/sudoers.c:467
+#, c-format
+msgid ""
+"ignoring `%s' found in '.'\n"
+"Use `sudo ./%s' if this is the `%s' you wish to run."
+msgstr ""
+
+#: plugins/sudoers/logging.c:325
+msgid "authentication failure"
+msgstr ""
+
+#: plugins/sudoers/logging.c:351
+msgid "a password is required"
+msgstr ""
+
+#: plugins/sudoers/logging.c:422 plugins/sudoers/logging.c:484
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#: plugins/sudoers/logging.c:572
+msgid "unable to fork"
+msgstr ""
+
+#: plugins/sudoers/logging.c:580 plugins/sudoers/logging.c:636
+#, c-format
+msgid "unable to fork: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:626
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:651
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:689
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr ""
+
+#: plugins/sudoers/match.c:606
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr ""
+
+#: plugins/sudoers/match.c:639
+#, c-format
+msgid "%s: read error"
+msgstr ""
+
+#: plugins/sudoers/match.c:653
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr ""
+
+#: plugins/sudoers/parse.c:114
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr ""
+
+#: plugins/sudoers/parse.c:117
+#, c-format
+msgid "parse error in %s"
+msgstr ""
+
+#: plugins/sudoers/parse.c:502
+#, c-format
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+
+#: plugins/sudoers/parse.c:503
+#, c-format
+msgid " RunAsUsers: "
+msgstr ""
+
+#: plugins/sudoers/parse.c:517
+#, c-format
+msgid " RunAsGroups: "
+msgstr ""
+
+#: plugins/sudoers/parse.c:526
+#, c-format
+msgid " Options: "
+msgstr ""
+
+#: plugins/sudoers/policy.c:240 plugins/sudoers/testsudoers.c:253
+msgid "unable to parse network address list"
+msgstr ""
+
+#: plugins/sudoers/policy.c:636 plugins/sudoers/visudo.c:839
+#, c-format
+msgid "unable to execute %s"
+msgstr "nie je možné vykonať %s"
+
+#: plugins/sudoers/policy.c:769
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:771
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:775
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:778
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:780
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:781
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:814
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:136 plugins/sudoers/pwutil.c:153
+#, c-format
+msgid "unable to cache uid %u, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:147
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:191 plugins/sudoers/pwutil.c:207
+#: plugins/sudoers/pwutil.c:250 plugins/sudoers/pwutil.c:294
+#, c-format
+msgid "unable to cache user %s, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:202
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:427 plugins/sudoers/pwutil.c:444
+#, c-format
+msgid "unable to cache gid %u, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:438
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:476 plugins/sudoers/pwutil.c:492
+#: plugins/sudoers/pwutil.c:524 plugins/sudoers/pwutil.c:565
+#, c-format
+msgid "unable to cache group %s, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:487
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:676 plugins/sudoers/pwutil.c:710
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:682 plugins/sudoers/pwutil.c:715
+#, c-format
+msgid "unable to cache group list for %s, out of memory"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:705
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:113 plugins/sudoers/set_perms.c:438
+#: plugins/sudoers/set_perms.c:841 plugins/sudoers/set_perms.c:1138
+#: plugins/sudoers/set_perms.c:1430
+msgid "perm stack overflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:121 plugins/sudoers/set_perms.c:369
+#: plugins/sudoers/set_perms.c:446 plugins/sudoers/set_perms.c:708
+#: plugins/sudoers/set_perms.c:849 plugins/sudoers/set_perms.c:1067
+#: plugins/sudoers/set_perms.c:1146 plugins/sudoers/set_perms.c:1363
+#: plugins/sudoers/set_perms.c:1438 plugins/sudoers/set_perms.c:1527
+msgid "perm stack underflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:180 plugins/sudoers/set_perms.c:493
+#: plugins/sudoers/set_perms.c:1197 plugins/sudoers/set_perms.c:1470
+msgid "unable to change to root gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:269 plugins/sudoers/set_perms.c:590
+#: plugins/sudoers/set_perms.c:978 plugins/sudoers/set_perms.c:1274
+msgid "unable to change to runas gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:274 plugins/sudoers/set_perms.c:595
+#: plugins/sudoers/set_perms.c:983 plugins/sudoers/set_perms.c:1279
+msgid "unable to set runas group vector"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:285 plugins/sudoers/set_perms.c:606
+#: plugins/sudoers/set_perms.c:992 plugins/sudoers/set_perms.c:1288
+msgid "unable to change to runas uid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:303 plugins/sudoers/set_perms.c:624
+#: plugins/sudoers/set_perms.c:1008 plugins/sudoers/set_perms.c:1304
+msgid "unable to change to sudoers gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:356 plugins/sudoers/set_perms.c:695
+#: plugins/sudoers/set_perms.c:1054 plugins/sudoers/set_perms.c:1350
+#: plugins/sudoers/set_perms.c:1514
+msgid "too many processes"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:51
+msgid "unable to get current working directory"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:59
+#, c-format
+msgid "truncated audit path user_cmnd: %s"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:66
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:115
+msgid "audit_failure message too long"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:333
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:341 plugins/sudoers/sssd.c:350
+#: plugins/sudoers/sssd.c:359 plugins/sudoers/sssd.c:368
+#: plugins/sudoers/sssd.c:377
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:290
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:308
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:326
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:339
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:172 plugins/sudoers/testsudoers.c:245
+#: plugins/sudoers/visudo.c:223 plugins/sudoers/visudo.c:565
+msgid "unable to initialize sudoers default values"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:197 plugins/sudoers/sudoers.c:239
+#: plugins/sudoers/sudoers.c:833
+msgid "problem with defaults entries"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:205
+msgid "no valid sudoers sources found, quitting"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:275
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:332
+msgid "you are not permitted to use the -C option"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:396
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:410
+msgid "no tty"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:411
+msgid "sorry, you must have a tty to run sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:466
+msgid "command in current directory"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:486
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:778
+msgid "command too long"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:886 plugins/sudoers/visudo.c:426
+#: plugins/sudoers/visudo.c:665
+#, c-format
+msgid "unable to stat %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:890
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s nie je regulárny súbor"
+
+#: plugins/sudoers/sudoers.c:894 plugins/sudoers/timestamp.c:225 toke.l:947
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s je vlastnený identifikátorom uid %u a mal by byť vlastnený %u"
+
+#: plugins/sudoers/sudoers.c:898 toke.l:954
+#, c-format
+msgid "%s is world writable"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:902 toke.l:959
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:933
+#, c-format
+msgid "only root can use `-c %s'"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:952
+#, c-format
+msgid "unknown login class: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1031 plugins/sudoers/sudoers.c:1059
+#, c-format
+msgid "unable to resolve host %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1126 plugins/sudoers/testsudoers.c:385
+#, c-format
+msgid "unknown group: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:232
+#, c-format
+msgid "invalid filter option: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:245
+#, c-format
+msgid "invalid max wait: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:251
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:254 plugins/sudoers/visudo.c:180
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s verzia %s\n"
+
+#: plugins/sudoers/sudoreplay.c:286
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s/timing: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:292
+#, c-format
+msgid "%s/%s/timing: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:308
+#, c-format
+msgid "Replaying sudo session: %s\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:314
+#, c-format
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:315
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:368
+msgid "unable to set tty to raw mode"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:401
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:611 plugins/sudoers/sudoreplay.c:636
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:658
+msgid "unmatched ')' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:662
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:677
+#, c-format
+msgid "%s requires an argument"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:680 plugins/sudoers/sudoreplay.c:1060
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:684
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:693
+msgid "unmatched '(' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:695
+msgid "illegal trailing \"or\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:697
+msgid "illegal trailing \"!\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:746
+#, c-format
+msgid "unknown search type %d"
+msgstr "neznámy typ vyhľadávania %d"
+
+#: plugins/sudoers/sudoreplay.c:784
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: neplatný súbor záznamu"
+
+#: plugins/sudoers/sudoreplay.c:802
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: chýba pole časovej značky"
+
+#: plugins/sudoers/sudoreplay.c:809
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: časová značka %s: %s"
+
+#: plugins/sudoers/sudoreplay.c:816
+#, c-format
+msgid "%s: user field is missing"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:825
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:834
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1197
+#, c-format
+msgid "usage: %s [-h] [-d dir] [-m num] [-s num] ID\n"
+msgstr "použitie: %s [-h] [-d adresár] [-m číslo] [-s číslo] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1200
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "použitie: %s [-h] [-d adresár] -l [hľadaný výraz]\n"
+
+#: plugins/sudoers/sudoreplay.c:1209
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1211
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Voľby:\n"
+" -d, --directory=adresárr určí adresár pre záznamy relácie\n"
+" -f, --filter=filter určuje, ktoré vstupno-výstupné typy sa majú zorbaziť\n"
+" -h, --help zorbazí správu pomocníka a skončí\n"
+" -l, --list vypíše identifikátory dostupných relácií, s voliteľným výrazom\n"
+" -m, --max-wait=číslo maximálny počet sekúnd čakania medzi udalosťami\n"
+" -s, --speed=číslo zrýchli alebo spomalí výstup\n"
+" -V, --version zobrazí informácie o verzii a skončí"
+
+#: plugins/sudoers/testsudoers.c:324
+msgid "\thost unmatched"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:327
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Príkaz povolený"
+
+#: plugins/sudoers/testsudoers.c:328
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Príkaz odmietnutý"
+
+#: plugins/sudoers/testsudoers.c:328
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Príkaz nevyhovujúci"
+
+#: plugins/sudoers/timestamp.c:233
+#, c-format
+msgid "%s is group writable"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:309
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:742 plugins/sudoers/timestamp.c:809
+#: plugins/sudoers/visudo.c:486 plugins/sudoers/visudo.c:492
+msgid "unable to read the clock"
+msgstr "nie je možné čítať hodiny"
+
+#: plugins/sudoers/timestamp.c:756
+msgid "ignoring time stamp from the future"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:768
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:863
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:906 plugins/sudoers/timestamp.c:926
+#, c-format
+msgid "lecture status path too long: %s/%s"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:182
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:254 plugins/sudoers/visudo.c:617
+#, c-format
+msgid "press return to edit %s: "
+msgstr ""
+
+#: plugins/sudoers/visudo.c:319
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:337
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:446 plugins/sudoers/visudo.c:454
+msgid "write error"
+msgstr "chyba zápisu"
+
+#: plugins/sudoers/visudo.c:499
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:506
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:512
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:534
+#, c-format
+msgid "%s unchanged"
+msgstr "%s nezmenený"
+
+#: plugins/sudoers/visudo.c:560
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr ""
+
+#: plugins/sudoers/visudo.c:571
+#, c-format
+msgid "unabled to parse temporary file (%s), unknown error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:608
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:667 plugins/sudoers/visudo.c:676
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:671 plugins/sudoers/visudo.c:681
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:698
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:712
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:722
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:784
+msgid "What now? "
+msgstr ""
+
+#: plugins/sudoers/visudo.c:798
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:846
+#, c-format
+msgid "unable to run %s"
+msgstr "nie je možné spustiť %s"
+
+#: plugins/sudoers/visudo.c:872
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:879
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:904 plugins/sudoers/visudo_json.c:1032
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:920 plugins/sudoers/visudo_json.c:1041
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:923 plugins/sudoers/visudo_json.c:1044
+#, c-format
+msgid "parse error in %s\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:931 plugins/sudoers/visudo.c:938
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:985
+#, c-format
+msgid "%s busy, try again later"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1081
+#, c-format
+msgid "Error: cycle in %s `%s'"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1082
+#, c-format
+msgid "Warning: cycle in %s `%s'"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1086
+#, c-format
+msgid "Error: %s `%s' referenced but not defined"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1087
+#, c-format
+msgid "Warning: %s `%s' referenced but not defined"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1230
+#, c-format
+msgid "Warning: unused %s `%s'"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1343
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - bezpečne upraví súbor sudoers\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1345
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+" -x, --export=output_file write sudoers in JSON format to output_file"
+msgstr ""
+
+#: plugins/sudoers/visudo_json.c:1018
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr ""
+
+#: toke.l:918
+msgid "too many levels of includes"
+msgstr ""
diff --git a/plugins/sudoers/po/sl.mo b/plugins/sudoers/po/sl.mo
new file mode 100644
index 0000000..832663f
--- /dev/null
+++ b/plugins/sudoers/po/sl.mo
Binary files differ
diff --git a/plugins/sudoers/po/sl.po b/plugins/sudoers/po/sl.po
new file mode 100644
index 0000000..55d6733
--- /dev/null
+++ b/plugins/sudoers/po/sl.po
@@ -0,0 +1,1758 @@
+# Slovenian translation of sudo.
+# This file is put in the public domain.
+# This file is distributed under the same license as the sudo package.
+#
+# Damir Jerovšek <damir.jerovsek@gmail.com>, 2012.
+# Klemen Košir <klemen.kosir@gmx.com>, 2012 - 2013.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.8.7b1\n"
+"Report-Msgid-Bugs-To: http://www.sudo.ws/bugs\n"
+"POT-Creation-Date: 2013-04-02 10:40-0400\n"
+"PO-Revision-Date: 2013-04-06 09:44+0100\n"
+"Last-Translator: Klemen Košir <klemen913@gmail.com>\n"
+"Language-Team: Slovenian <translation-team-sl@lists.sourceforge.net>\n"
+"Language: sl\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0);\n"
+"X-Generator: Poedit 1.5.5\n"
+
+#: confstr.sh:2 plugins/sudoers/auth/pam.c:340
+msgid "Password:"
+msgstr "Geslo:"
+
+#: confstr.sh:3
+msgid "*** SECURITY information for %h ***"
+msgstr "*** Varnostni podatki za %h ***"
+
+#: confstr.sh:4
+msgid "Sorry, try again."
+msgstr "Prosimo, poskusite znova."
+
+#: plugins/sudoers/alias.c:124
+#, c-format
+msgid "Alias `%s' already defined"
+msgstr "Vzdevek `%s' je že določen"
+
+#: plugins/sudoers/auth/bsdauth.c:77
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "prijavnega razreda uporabnika %s ni mogoče pridobiti"
+
+#: plugins/sudoers/auth/bsdauth.c:83
+msgid "unable to begin bsd authentication"
+msgstr "ni mogoče začeti overitve bsd"
+
+#: plugins/sudoers/auth/bsdauth.c:91
+msgid "invalid authentication type"
+msgstr "neveljavna vrsta overitve"
+
+#: plugins/sudoers/auth/bsdauth.c:100
+msgid "unable to setup authentication"
+msgstr "ni mogoče nastaviti overitve"
+
+#: plugins/sudoers/auth/fwtk.c:59
+#, c-format
+msgid "unable to read fwtk config"
+msgstr "ni mogoče brati nastavitev fwtk"
+
+#: plugins/sudoers/auth/fwtk.c:64
+#, c-format
+msgid "unable to connect to authentication server"
+msgstr "ni se mogoče povezati s strežnikom overitve"
+
+#: plugins/sudoers/auth/fwtk.c:70 plugins/sudoers/auth/fwtk.c:94
+#: plugins/sudoers/auth/fwtk.c:127
+#, c-format
+msgid "lost connection to authentication server"
+msgstr "povezava s strežnikom overitve je bila izgubljena"
+
+#: plugins/sudoers/auth/fwtk.c:74
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"napaka strežnika overitve:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:116
+#, c-format
+msgid "%s: unable to unparse princ ('%s'): %s"
+msgstr "%s: ni mogoče odrazčleniti princ ('%s'): %s"
+
+#: plugins/sudoers/auth/kerb5.c:159
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: ni mogoče razčleniti '%s': %s"
+
+#: plugins/sudoers/auth/kerb5.c:169
+#, c-format
+msgid "%s: unable to resolve ccache: %s"
+msgstr "%s: ni mogoče razrešiti ccache: %s"
+
+#: plugins/sudoers/auth/kerb5.c:217
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: ni mogoče dodeliti možnosti: %s"
+
+#: plugins/sudoers/auth/kerb5.c:233
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: ni mogoče dobiti poverila: %s"
+
+#: plugins/sudoers/auth/kerb5.c:246
+#, c-format
+msgid "%s: unable to initialize ccache: %s"
+msgstr "%s: ni mogoče začeti ccache: %s"
+
+#: plugins/sudoers/auth/kerb5.c:250
+#, c-format
+msgid "%s: unable to store cred in ccache: %s"
+msgstr "%s: ni mogoče shraniti cred v ccache: %s"
+
+#: plugins/sudoers/auth/kerb5.c:315
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: ni mogoče pridobiti predstojnika gostitve: %s"
+
+#: plugins/sudoers/auth/kerb5.c:330
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: ni mogoče preveriti TGT! Možen napad!: %s"
+
+#: plugins/sudoers/auth/pam.c:100
+msgid "unable to initialize PAM"
+msgstr "ni mogoče začeti PAM"
+
+#: plugins/sudoers/auth/pam.c:145
+msgid "account validation failure, is your account locked?"
+msgstr "potrditev veljavnosti računa je spodletela, je vaš račun zaklenjen?"
+
+#: plugins/sudoers/auth/pam.c:149
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Geslo ali račun je potekel, ponastavite svoje geslo in poskusite znova"
+
+#: plugins/sudoers/auth/pam.c:156
+#, c-format
+msgid "pam_chauthtok: %s"
+msgstr "pam_chauthtok: %s"
+
+#: plugins/sudoers/auth/pam.c:160
+msgid "Password expired, contact your system administrator"
+msgstr "Veljavnost gesla je potekla. Stopite v stik s svojim sistemskim skrbnikom"
+
+#: plugins/sudoers/auth/pam.c:164
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Račun je potekel ali pa nastavitvam PAM primanjkuje odsek \"account\" za sudo, obrnite se na sistemskega skrbnika"
+
+#: plugins/sudoers/auth/pam.c:181
+#, c-format
+msgid "pam_authenticate: %s"
+msgstr "pam_authenticate: %s"
+
+#: plugins/sudoers/auth/pam.c:339
+msgid "Password: "
+msgstr "Geslo: "
+
+#: plugins/sudoers/auth/rfc1938.c:103 plugins/sudoers/visudo.c:212
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "ne obstajate v podatkovni zbirki %s"
+
+#: plugins/sudoers/auth/securid5.c:80
+#, c-format
+msgid "failed to initialise the ACE API library"
+msgstr "začenjanje knjižnice ACE API je spodletelo"
+
+#: plugins/sudoers/auth/securid5.c:106
+#, c-format
+msgid "unable to contact the SecurID server"
+msgstr "ni mogoče navezati stika s strežnikom SecurID"
+
+#: plugins/sudoers/auth/securid5.c:115
+#, c-format
+msgid "User ID locked for SecurID Authentication"
+msgstr "ID uporabnika je zaklenjen zaradi overitve SecurID"
+
+#: plugins/sudoers/auth/securid5.c:119 plugins/sudoers/auth/securid5.c:170
+#, c-format
+msgid "invalid username length for SecurID"
+msgstr "neveljavna dolžina imena uporabnika za SecurID"
+
+#: plugins/sudoers/auth/securid5.c:123 plugins/sudoers/auth/securid5.c:175
+#, c-format
+msgid "invalid Authentication Handle for SecurID"
+msgstr "neveljavna ročica overitve za SecurID"
+
+#: plugins/sudoers/auth/securid5.c:127
+#, c-format
+msgid "SecurID communication failed"
+msgstr "sporazumevanje SecurID je spodletelo"
+
+#: plugins/sudoers/auth/securid5.c:131 plugins/sudoers/auth/securid5.c:214
+#, c-format
+msgid "unknown SecurID error"
+msgstr "neznana napaka SecurID"
+
+#: plugins/sudoers/auth/securid5.c:165
+#, c-format
+msgid "invalid passcode length for SecurID"
+msgstr "neveljavna dolžina gesla za SecurID"
+
+#: plugins/sudoers/auth/sia.c:108
+msgid "unable to initialize SIA session"
+msgstr "ni mogoče začeti seje SIA"
+
+#: plugins/sudoers/auth/sudo_auth.c:119
+msgid "invalid authentication methods"
+msgstr "neveljavni načini overitve"
+
+#: plugins/sudoers/auth/sudo_auth.c:120
+msgid "Invalid authentication methods compiled into sudo! You may mix standalone and non-standalone authentication."
+msgstr "Neveljavni načini overitve so kodno prevedeni v sudo! Mešate lahko samostojno in nesamostojno overjanje."
+
+#: plugins/sudoers/auth/sudo_auth.c:203
+msgid "no authentication methods"
+msgstr "ni načinov overjanja"
+
+#: plugins/sudoers/auth/sudo_auth.c:205
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Ni načinov overitve, kodno prevedenih v sudo! Če želite izklopiti overjanje, uporabite nastavitveno možnost --disable-authentication."
+
+#: plugins/sudoers/auth/sudo_auth.c:389
+msgid "Authentication methods:"
+msgstr "Načini overjanja:"
+
+#: plugins/sudoers/bsm_audit.c:60 plugins/sudoers/bsm_audit.c:63
+#: plugins/sudoers/bsm_audit.c:112 plugins/sudoers/bsm_audit.c:116
+#: plugins/sudoers/bsm_audit.c:168 plugins/sudoers/bsm_audit.c:172
+#, c-format
+msgid "getaudit: failed"
+msgstr "getaudit: spodletelo"
+
+#: plugins/sudoers/bsm_audit.c:90 plugins/sudoers/bsm_audit.c:153
+#, c-format
+msgid "Could not determine audit condition"
+msgstr "Pogoja presoje varnosti ni bilo mogoče določiti"
+
+#: plugins/sudoers/bsm_audit.c:101
+#, c-format
+msgid "getauid failed"
+msgstr "getauid je spodletel"
+
+#: plugins/sudoers/bsm_audit.c:103 plugins/sudoers/bsm_audit.c:162
+#, c-format
+msgid "au_open: failed"
+msgstr "au_open: spodletelo"
+
+#: plugins/sudoers/bsm_audit.c:118 plugins/sudoers/bsm_audit.c:174
+#, c-format
+msgid "au_to_subject: failed"
+msgstr "au_to_subject: spodletelo"
+
+#: plugins/sudoers/bsm_audit.c:122 plugins/sudoers/bsm_audit.c:178
+#, c-format
+msgid "au_to_exec_args: failed"
+msgstr "au_to_exec_args: spodletelo"
+
+#: plugins/sudoers/bsm_audit.c:126 plugins/sudoers/bsm_audit.c:187
+#, c-format
+msgid "au_to_return32: failed"
+msgstr "au_to_return32: spodletelo"
+
+#: plugins/sudoers/bsm_audit.c:129 plugins/sudoers/bsm_audit.c:190
+#, c-format
+msgid "unable to commit audit record"
+msgstr "ni bilo mogoče uveljaviti zapisa presoje varnosti"
+
+#: plugins/sudoers/bsm_audit.c:160
+#, c-format
+msgid "getauid: failed"
+msgstr "getauid: spodletelo"
+
+#: plugins/sudoers/bsm_audit.c:183
+#, c-format
+msgid "au_to_text: failed"
+msgstr "au_to_text: spodletelo"
+
+#: plugins/sudoers/check.c:174
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Verjetno vam je skrbnik sistemov že pridigal o varnosti,\n"
+"vendar si vseeno zapomnite naslednja pravila:\n"
+"\n"
+" #1) Spoštujte zasebnost drugih.\n"
+" #2) Premislite, preden izvedete ukaze.\n"
+" #3) Velika moč prinaša veliko odgovornost.\n"
+"\n"
+
+#: plugins/sudoers/check.c:212 plugins/sudoers/check.c:218
+#: plugins/sudoers/sudoers.c:562 plugins/sudoers/sudoers.c:566
+#, c-format
+msgid "unknown uid: %u"
+msgstr "neznan ID uporabnika: %u"
+
+#: plugins/sudoers/check.c:215 plugins/sudoers/policy.c:635
+#: plugins/sudoers/sudoers.c:845 plugins/sudoers/testsudoers.c:215
+#: plugins/sudoers/testsudoers.c:359
+#, c-format
+msgid "unknown user: %s"
+msgstr "neznan uporabnik: %s"
+
+#: plugins/sudoers/def_data.c:27
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Pripomoček syslog, če se syslog uporablja za beleženje: %s"
+
+#: plugins/sudoers/def_data.c:31
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Prednost syslog, ko se uporabnik uspešno overi: %s"
+
+#: plugins/sudoers/def_data.c:35
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Prednost syslog, ko se uporabnik ne overi uspešno: %s"
+
+#: plugins/sudoers/def_data.c:39
+msgid "Put OTP prompt on its own line"
+msgstr "postavi poziv OTP v svojo vrstico"
+
+#: plugins/sudoers/def_data.c:43
+msgid "Ignore '.' in $PATH"
+msgstr "Prezri '.' v $PATH"
+
+#: plugins/sudoers/def_data.c:47
+msgid "Always send mail when sudo is run"
+msgstr "Vedno pošlji pošto, kadar se zažene sudo"
+
+#: plugins/sudoers/def_data.c:51
+msgid "Send mail if user authentication fails"
+msgstr "Pošlji pošto, če overitev uporabnika spodleti"
+
+#: plugins/sudoers/def_data.c:55
+msgid "Send mail if the user is not in sudoers"
+msgstr "Pošlji pošto, če uporabnik ni v sudoers"
+
+#: plugins/sudoers/def_data.c:59
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Pošlji pošto, če uporabnik ni v sudoers za tega gostitelja"
+
+#: plugins/sudoers/def_data.c:63
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Pošlji pošto, če uporabniku ni dovoljeno zagnati ukaza"
+
+#: plugins/sudoers/def_data.c:67
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Uporabi ločen časovni žig za vsako kombinacijo uporabnik/tty"
+
+#: plugins/sudoers/def_data.c:71
+msgid "Lecture user the first time they run sudo"
+msgstr "Poduči uporabnika, ko prvič zažene sudo"
+
+#: plugins/sudoers/def_data.c:75
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Datoteka, ki vsebuje poduk sudo: %s"
+
+#: plugins/sudoers/def_data.c:79
+msgid "Require users to authenticate by default"
+msgstr "Privzeto zahtevaj od uporabnikov, da se overijo"
+
+#: plugins/sudoers/def_data.c:83
+msgid "Root may run sudo"
+msgstr "Skrbnik lahko zažene sudo"
+
+#: plugins/sudoers/def_data.c:87
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Beleži ime gostitelja v datoteko dnevnika (ne v sistemski dnevnik)"
+
+#: plugins/sudoers/def_data.c:91
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Beleži leto v (ne-syslog) dnevniško datoteko"
+
+#: plugins/sudoers/def_data.c:95
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Če je sudo poklican brez argumentov, začni lupino"
+
+#: plugins/sudoers/def_data.c:99
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Postavi $HOME ciljnemu uporabniku, kadar se začne lupina s -s"
+
+#: plugins/sudoers/def_data.c:103
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Vedno postavi $HOME domači mapi ciljnega uporabnika"
+
+#: plugins/sudoers/def_data.c:107
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Dovoli zbrati nekaj podrobnosti za uporabna sporočila napak"
+
+#: plugins/sudoers/def_data.c:111
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Zahtevaj povsem uvrščena imena gostiteljev v datoteki sudoers"
+
+#: plugins/sudoers/def_data.c:115
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Užali uporabnika, ko vnese nepravilno geslo"
+
+#: plugins/sudoers/def_data.c:119
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Dovoli uporabniku zagnati sudo samo v primeru, če imajo tty"
+
+#: plugins/sudoers/def_data.c:123
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo bo spoštoval spremenljivko okolja UREJEVALNIKA"
+
+#: plugins/sudoers/def_data.c:127
+msgid "Prompt for root's password, not the users's"
+msgstr "Pozovi za geslo skrbnika, ne uporabnika"
+
+#: plugins/sudoers/def_data.c:131
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Pozovi za geslo uporabnika runas_default namesto uporabnikovega gesla"
+
+#: plugins/sudoers/def_data.c:135
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Pozovi za geslo ciljnega uporabnika namesto uporabnikovega"
+
+#: plugins/sudoers/def_data.c:139
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Uveljavi privzete vrednosti v ciljnem uporabniškem razredu prijave, če le ta obstaja"
+
+#: plugins/sudoers/def_data.c:143
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Nastavi spremenljivke okolja LOGNAME in USER"
+
+#: plugins/sudoers/def_data.c:147
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Nastavi samo dejanski ID uporabnika ciljnemu uporabniku, ne resničnega ID-ja"
+
+#: plugins/sudoers/def_data.c:151
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Ne začenjaj vektorja skupine ciljnega uporabnika"
+
+#: plugins/sudoers/def_data.c:155
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %d"
+msgstr "Dolžina, pri kateri se naj prelomijo vrstice datotek beleženja (0 za brez lomljenja):% d"
+
+#: plugins/sudoers/def_data.c:159
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Časovni potek overitve časovnega žiga: %.1f minut"
+
+#: plugins/sudoers/def_data.c:163
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Zakasnitev poziva gesla: %.1f minut"
+
+#: plugins/sudoers/def_data.c:167
+#, c-format
+msgid "Number of tries to enter a password: %d"
+msgstr "Število poskusov vnosa gesla: %d"
+
+#: plugins/sudoers/def_data.c:171
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Uporabniška maska, ki bo uporabljena ali 0777 za uporabo uporabnikove: 0%o"
+
+#: plugins/sudoers/def_data.c:175
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Pot do datoteke beleženja: %s"
+
+#: plugins/sudoers/def_data.c:179
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Pot do programa pošte: %s"
+
+#: plugins/sudoers/def_data.c:183
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Zastavice za program pošte: %s"
+
+#: plugins/sudoers/def_data.c:187
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Naslov prejemnika pošte: %s"
+
+#: plugins/sudoers/def_data.c:191
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Naslov pošiljatelja pošte: %s"
+
+#: plugins/sudoers/def_data.c:195
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Vrstica zadeve za poštna sporočila: %s"
+
+#: plugins/sudoers/def_data.c:199
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Nepravilno sporočilo gesla: %s"
+
+#: plugins/sudoers/def_data.c:203
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Pot do mape časovnega žiga overitve: %s"
+
+#: plugins/sudoers/def_data.c:207
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Lastnik mape časovnega žiga overitve: %s"
+
+#: plugins/sudoers/def_data.c:211
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Uporabnikov v tej skupini zahteve gesla in PATH ne omejujejo: %s"
+
+#: plugins/sudoers/def_data.c:215
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Privzeti poziv gesla: %s"
+
+#: plugins/sudoers/def_data.c:219
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Če je poziv gesla nastavljen, bo prepisal sistemski poziv v vseh primerih."
+
+#: plugins/sudoers/def_data.c:223
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Privzet uporabnik za izvajanje ukazov kot: %s"
+
+#: plugins/sudoers/def_data.c:227
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Vrednost, s katerim se bo prepisal $PATH uporabnika: %s"
+
+#: plugins/sudoers/def_data.c:231
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Pot do urejevalnika za uporabo z visudo: %s"
+
+#: plugins/sudoers/def_data.c:235
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Kdaj naj bo zahtevano geslo za psevdoukaz 'list': %s"
+
+#: plugins/sudoers/def_data.c:239
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Kdaj naj bo zahtevano geslo za psevdoukaz 'verify': %s"
+
+#: plugins/sudoers/def_data.c:243
+msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+msgstr "Prednaloži preizkusne funkcije, shranjene v knjižnici sudo_noexec"
+
+#: plugins/sudoers/def_data.c:247
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Če je mapa LDAP na voljo, bodo krajevne datoteke sudoers prezrte"
+
+#: plugins/sudoers/def_data.c:251
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Opisniki datotek >= %d bodo končani pred izvedbo ukaza"
+
+#: plugins/sudoers/def_data.c:255
+msgid "If set, users may override the value of `closefrom' with the -C option"
+msgstr "Če je nastavljeno, lahko uporabniki prepišejo vrednost `closefrom' z možnostjo -C"
+
+#: plugins/sudoers/def_data.c:259
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Dovoli uporabnikom nastavljanje poljubnih spremenljivk okolja"
+
+#: plugins/sudoers/def_data.c:263
+msgid "Reset the environment to a default set of variables"
+msgstr "Ponastavi okolje na privzet nabor spremenljivk"
+
+#: plugins/sudoers/def_data.c:267
+msgid "Environment variables to check for sanity:"
+msgstr "Spremenljivke okolja, ki bodo preverjene za smiselnost:"
+
+#: plugins/sudoers/def_data.c:271
+msgid "Environment variables to remove:"
+msgstr "Spremenljivke okolja za odstranitev:"
+
+#: plugins/sudoers/def_data.c:275
+msgid "Environment variables to preserve:"
+msgstr "Spremenljivke okolja za ohranitev:"
+
+#: plugins/sudoers/def_data.c:279
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "Vloga SELinux za uporabo v novi vsebini varnosti: %s"
+
+#: plugins/sudoers/def_data.c:283
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "Vrsta SELinux za uporabo v novi vsebini varnosti: %s"
+
+#: plugins/sudoers/def_data.c:287
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Pot do določene sudo datoteke okolja: %s"
+
+#: plugins/sudoers/def_data.c:291
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Jezikovna oznaka za uporabo pri razčlenjevanju sudoers: %s"
+
+#: plugins/sudoers/def_data.c:295
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Dovoli programu sudo, da vpraša za geslo, čeprav bi bilo le-to vidno"
+
+#: plugins/sudoers/def_data.c:299
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Zagotovi viden odziv ob vnosu gesla ob vnosu uporabnika"
+
+#: plugins/sudoers/def_data.c:303
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Uporabi hitrejše razširjanje imen poti, ki je manj natančno, vendar ne dostopa do datotečnega sistema"
+
+#: plugins/sudoers/def_data.c:307
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "Uporabniška maska v sudoers bo prepisala uporabnikovo tudi, če je bolj premisivna"
+
+#: plugins/sudoers/def_data.c:311
+msgid "Log user's input for the command being run"
+msgstr "Beleži vnos uporabnika za ukaz, ki se izvaja"
+
+#: plugins/sudoers/def_data.c:315
+msgid "Log the output of the command being run"
+msgstr "Beleži izpis ukaza, ki se izvaja"
+
+#: plugins/sudoers/def_data.c:319
+msgid "Compress I/O logs using zlib"
+msgstr "Stisni dnevnike I/O s pomočjo zlib"
+
+#: plugins/sudoers/def_data.c:323
+msgid "Always run commands in a pseudo-tty"
+msgstr "Vedno zaženi ukaze v psevdo-tty"
+
+#: plugins/sudoers/def_data.c:327
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Vstavek za podporo skupinam, ki niso del Unixa: %s"
+
+#: plugins/sudoers/def_data.c:331
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Mapa, v kateri bodo shranjeni dnevniki vnosov/izpisov: %s"
+
+#: plugins/sudoers/def_data.c:335
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Datoteka, v kateri bo shranjen dnevnik vnosov/izpisov: %s"
+
+#: plugins/sudoers/def_data.c:339
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Dodaj vstop datoteki utmp/utmpx, kadar se dodeljuje pty"
+
+#: plugins/sudoers/def_data.c:343
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Nastavi uporabnika v utmp uporabniku runas, ne poklicanemu uporabniku"
+
+#: plugins/sudoers/def_data.c:347
+msgid "Set of permitted privileges"
+msgstr "Niz omogočenih dovoljenj"
+
+#: plugins/sudoers/def_data.c:351
+msgid "Set of limit privileges"
+msgstr "Niz omejenih dovoljenj"
+
+#: plugins/sudoers/def_data.c:355
+msgid "Run commands on a pty in the background"
+msgstr "Zaženi ukaze v terminalu v ozadju"
+
+#: plugins/sudoers/def_data.c:359
+msgid "Create a new PAM session for the command to run in"
+msgstr "Ustvari sejo PAM, v kateri se bodo ukazi izvajali"
+
+#: plugins/sudoers/def_data.c:363
+msgid "Maximum I/O log sequence number"
+msgstr "Največja zaporedna številka dnevnika I/O"
+
+#: plugins/sudoers/defaults.c:207 plugins/sudoers/defaults.c:587
+#, c-format
+msgid "unknown defaults entry `%s'"
+msgstr "neznan privzet vnos `%s'"
+
+#: plugins/sudoers/defaults.c:215 plugins/sudoers/defaults.c:225
+#: plugins/sudoers/defaults.c:245 plugins/sudoers/defaults.c:258
+#: plugins/sudoers/defaults.c:271 plugins/sudoers/defaults.c:284
+#: plugins/sudoers/defaults.c:297 plugins/sudoers/defaults.c:317
+#: plugins/sudoers/defaults.c:327
+#, c-format
+msgid "value `%s' is invalid for option `%s'"
+msgstr "vrednost `%s' je neveljavna za možnost `%s'"
+
+#: plugins/sudoers/defaults.c:218 plugins/sudoers/defaults.c:228
+#: plugins/sudoers/defaults.c:236 plugins/sudoers/defaults.c:253
+#: plugins/sudoers/defaults.c:266 plugins/sudoers/defaults.c:279
+#: plugins/sudoers/defaults.c:292 plugins/sudoers/defaults.c:312
+#: plugins/sudoers/defaults.c:323
+#, c-format
+msgid "no value specified for `%s'"
+msgstr "za `%s' ni določena nobena vrednost"
+
+#: plugins/sudoers/defaults.c:241
+#, c-format
+msgid "values for `%s' must start with a '/'"
+msgstr "vrednosti za `%s' se morajo začeti s '/'"
+
+#: plugins/sudoers/defaults.c:303
+#, c-format
+msgid "option `%s' does not take a value"
+msgstr "možnost `%s' ne sprejme vrednosti"
+
+#: plugins/sudoers/env.c:288 plugins/sudoers/env.c:293
+#: plugins/sudoers/env.c:395 plugins/sudoers/linux_audit.c:82
+#: plugins/sudoers/policy.c:420 plugins/sudoers/policy.c:427
+#: plugins/sudoers/prompt.c:171 plugins/sudoers/sudoers.c:654
+#: plugins/sudoers/testsudoers.c:243
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "notranja napaka, prekoračitev funkcije %s"
+
+#: plugins/sudoers/env.c:367
+#, c-format
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: pokvarjen envp, neujemanje dolžine"
+
+#: plugins/sudoers/env.c:1012
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "nimate dovoljenj nastavljati naslednjih spremenljivk okolja: %s"
+
+#: plugins/sudoers/group_plugin.c:102
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s mora biti v lasti ID-ja uporabnika %d"
+
+#: plugins/sudoers/group_plugin.c:106
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr "%s mora biti zapisljiv samo za lastnika"
+
+#: plugins/sudoers/group_plugin.c:113
+#, c-format
+msgid "unable to dlopen %s: %s"
+msgstr "ni mogoče uporabiti dlopen %s: %s"
+
+#: plugins/sudoers/group_plugin.c:118
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "ni mogoče najti simbola \"group_plugin\" v %s"
+
+#: plugins/sudoers/group_plugin.c:123
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: nezdružljiva večja različica vstavka skupin %d, pričakovana %d"
+
+#: plugins/sudoers/interfaces.c:119
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Pari krajevnih naslovov IP in omrežnih mask:\n"
+
+#: plugins/sudoers/iolog.c:131 plugins/sudoers/iolog.c:144
+#: plugins/sudoers/timestamp.c:199 plugins/sudoers/timestamp.c:243
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s že obstaja, toda ni mapa (0%o)"
+
+#: plugins/sudoers/iolog.c:141 plugins/sudoers/iolog.c:155
+#: plugins/sudoers/iolog.c:159 plugins/sudoers/timestamp.c:164
+#: plugins/sudoers/timestamp.c:220 plugins/sudoers/timestamp.c:270
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "ustvarjenje mape %s z mkdir ni mogoče"
+
+#: plugins/sudoers/iolog.c:217 plugins/sudoers/sudoers.c:708
+#: plugins/sudoers/sudoreplay.c:354 plugins/sudoers/sudoreplay.c:815
+#: plugins/sudoers/sudoreplay.c:978 plugins/sudoers/timestamp.c:154
+#: plugins/sudoers/visudo.c:809
+#, c-format
+msgid "unable to open %s"
+msgstr "ni mogoče odpreti %s"
+
+#: plugins/sudoers/iolog.c:250 plugins/sudoers/sudoers.c:711
+#, c-format
+msgid "unable to read %s"
+msgstr "ni mogoče brati %s"
+
+#: plugins/sudoers/iolog.c:274 plugins/sudoers/timestamp.c:158
+#, c-format
+msgid "unable to write to %s"
+msgstr "ni mogoče pisati v %s"
+
+#: plugins/sudoers/iolog.c:334
+#, c-format
+msgid "unable to create %s"
+msgstr "ni mogoče ustvariti %s"
+
+#: plugins/sudoers/ldap.c:385
+#, c-format
+msgid "sudo_ldap_conf_add_ports: port too large"
+msgstr "sudo_ldap_conf_add_ports: vrednost vrat je prevelika"
+
+#: plugins/sudoers/ldap.c:408
+#, c-format
+msgid "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+msgstr "sudo_ldap_conf_add_ports: med razširjanjem hostbuf je zmanjkalo prostora"
+
+#: plugins/sudoers/ldap.c:438
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "nepodprta vrsta uri-ja LDAP: %s"
+
+#: plugins/sudoers/ldap.c:467
+#, c-format
+msgid "invalid uri: %s"
+msgstr "neveljaven uri: %s"
+
+#: plugins/sudoers/ldap.c:473
+#, c-format
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "ni mogoče mešati URI-jev ldap in ldaps"
+
+#: plugins/sudoers/ldap.c:477
+#, c-format
+msgid "unable to mix ldaps and starttls"
+msgstr "ni mogoče mešati ldaps in starttls"
+
+#: plugins/sudoers/ldap.c:496
+#, c-format
+msgid "sudo_ldap_parse_uri: out of space building hostbuf"
+msgstr "sudo_ldap_parse_uri: med izgradnjo hostbuf je zmanjkalo prostora"
+
+#: plugins/sudoers/ldap.c:570
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "ni mogoče začenjati potrdila SSL in ključa db: %s"
+
+#: plugins/sudoers/ldap.c:573
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "za uporabo SSL-ja morate nastaviti TSL_CERT v datoteki %s"
+
+#: plugins/sudoers/ldap.c:996
+#, c-format
+msgid "unable to get GMT time"
+msgstr "ni mogoče dobiti časa GMT"
+
+#: plugins/sudoers/ldap.c:1002
+#, c-format
+msgid "unable to format timestamp"
+msgstr "ni mogoče oblikovati časovnega žiga"
+
+#: plugins/sudoers/ldap.c:1010
+#, c-format
+msgid "unable to build time filter"
+msgstr "ni mogoče izgraditi časovnega filtra"
+
+#: plugins/sudoers/ldap.c:1229
+#, c-format
+msgid "sudo_ldap_build_pass1 allocation mismatch"
+msgstr "sudo_ldap_build_pass1 neujemanje dodelitve"
+
+#: plugins/sudoers/ldap.c:1776
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+"\n"
+"Vloga LDAP: %s\n"
+
+#: plugins/sudoers/ldap.c:1778
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: UNKNOWN\n"
+msgstr ""
+"\n"
+"Vloga LDAP: NEZNANA\n"
+
+#: plugins/sudoers/ldap.c:1825
+#, c-format
+msgid " Order: %s\n"
+msgstr " Vrstni red: %s\n"
+
+#: plugins/sudoers/ldap.c:1833 plugins/sudoers/parse.c:515
+#: plugins/sudoers/sssd.c:1173
+#, c-format
+msgid " Commands:\n"
+msgstr " Ukazi:\n"
+
+#: plugins/sudoers/ldap.c:2255
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "ni mogoče začeti LDAP: %s"
+
+#: plugins/sudoers/ldap.c:2289
+#, c-format
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls je določen, toda knjižnice LDAP ne podpirajo ldap_start_tls_s() ali ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:2525
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "neveljaven atribut sudoOrder: %s"
+
+#: plugins/sudoers/linux_audit.c:57
+#, c-format
+msgid "unable to open audit system"
+msgstr "ni mogoče odpreti nadzornega sistema"
+
+#: plugins/sudoers/linux_audit.c:93
+#, c-format
+msgid "unable to send audit message"
+msgstr "ni mogoče poslati nadzornega sporočila"
+
+#: plugins/sudoers/logging.c:140
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: plugins/sudoers/logging.c:168
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (ukaz) %s"
+
+#: plugins/sudoers/logging.c:194
+#, c-format
+msgid "unable to open log file: %s: %s"
+msgstr "ni mogoče odpreti datoteke dnevnika: %s: %s"
+
+#: plugins/sudoers/logging.c:197
+#, c-format
+msgid "unable to lock log file: %s: %s"
+msgstr "ni mogoče zakleniti datoteke dnevnika: %s: %s"
+
+#: plugins/sudoers/logging.c:245
+msgid "No user or host"
+msgstr "Brez uporabnika ali gostitelja"
+
+#: plugins/sudoers/logging.c:247
+msgid "validation failure"
+msgstr "potrjevanje veljavnosti ni uspelo"
+
+#: plugins/sudoers/logging.c:254
+msgid "user NOT in sudoers"
+msgstr "uporabnika NI v sudoers"
+
+#: plugins/sudoers/logging.c:256
+msgid "user NOT authorized on host"
+msgstr "uporabnik NI pooblaščen na gostitelju"
+
+#: plugins/sudoers/logging.c:258
+msgid "command not allowed"
+msgstr "ukaz ni dovoljen"
+
+#: plugins/sudoers/logging.c:288
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr "%s ni v datoteki sudoers. Ta dogodek bo zabeležen.\n"
+
+#: plugins/sudoers/logging.c:291
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr "%s nima dovoljenj za izvajanje sudo na %s. Ta dogodek bo zabeležen.\n"
+
+#: plugins/sudoers/logging.c:295
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Uporabnik %s ne sme izvajati sudo na %s.\n"
+
+#: plugins/sudoers/logging.c:298
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr "Uporabnik %s ne sme zagnati '%s%s%s' kot %s%s%s na %s.\n"
+
+#: plugins/sudoers/logging.c:335 plugins/sudoers/sudoers.c:383
+#: plugins/sudoers/sudoers.c:384 plugins/sudoers/sudoers.c:386
+#: plugins/sudoers/sudoers.c:387 plugins/sudoers/sudoers.c:1001
+#: plugins/sudoers/sudoers.c:1002
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: ukaza ni bilo mogoče najti"
+
+#: plugins/sudoers/logging.c:337 plugins/sudoers/sudoers.c:379
+#, c-format
+msgid ""
+"ignoring `%s' found in '.'\n"
+"Use `sudo ./%s' if this is the `%s' you wish to run."
+msgstr ""
+"prezrtje `%s', najdenega v '.'\n"
+"Uporabite `sudo ./%s', če je to `%s', ki ga želite zagnati."
+
+#: plugins/sudoers/logging.c:353
+msgid "authentication failure"
+msgstr "napaka overitve"
+
+#: plugins/sudoers/logging.c:379
+msgid "a password is required"
+msgstr "zahtevano je geslo"
+
+#: plugins/sudoers/logging.c:443 plugins/sudoers/logging.c:487
+#, c-format
+msgid "%d incorrect password attempt"
+msgid_plural "%d incorrect password attempts"
+msgstr[0] "%d nepravilnih poskusov vnosa gesla"
+msgstr[1] "%d nepravilen poskus vnosa gesla"
+msgstr[2] "%d nepravilna poskusa vnosa gesla"
+msgstr[3] "%d nepravilni poskusi vnosa gesla"
+
+#: plugins/sudoers/logging.c:566
+#, c-format
+msgid "unable to fork"
+msgstr "ni mogoče razvejiti"
+
+#: plugins/sudoers/logging.c:573 plugins/sudoers/logging.c:629
+#, c-format
+msgid "unable to fork: %m"
+msgstr "ni mogoče razvejiti: %m"
+
+#: plugins/sudoers/logging.c:619
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "ni mogoče odpreti cevi: %m"
+
+#: plugins/sudoers/logging.c:644
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "ni mogoče podvojiti stdin: %m"
+
+#: plugins/sudoers/logging.c:680
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "ni mogoče izvesti %s: %m"
+
+#: plugins/sudoers/logging.c:899
+#, c-format
+msgid "internal error: insufficient space for log line"
+msgstr "notranja napaka: premalo prostora za vrstico dnevnika"
+
+#: plugins/sudoers/parse.c:124
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr "napaka razčlenjevanja v %s blizu vrstice %d"
+
+#: plugins/sudoers/parse.c:127
+#, c-format
+msgid "parse error in %s"
+msgstr "napaka med razčlenjevanjem datoteke %s"
+
+#: plugins/sudoers/parse.c:462
+#, c-format
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+"\n"
+"Vnos sudoers:\n"
+
+#: plugins/sudoers/parse.c:463
+#, c-format
+msgid " RunAsUsers: "
+msgstr " ZaženiKotUporabniki: "
+
+#: plugins/sudoers/parse.c:477
+#, c-format
+msgid " RunAsGroups: "
+msgstr " ZaženiKotSkupine: "
+
+#: plugins/sudoers/parse.c:486
+#, c-format
+msgid " Options: "
+msgstr " Možnosti: "
+
+#: plugins/sudoers/policy.c:517 plugins/sudoers/visudo.c:750
+#, c-format
+msgid "unable to execute %s"
+msgstr "ni mogoče izvršiti %s"
+
+#: plugins/sudoers/policy.c:659
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Vstavek pravilnika sudoers različica %s\n"
+
+#: plugins/sudoers/policy.c:661
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Datoteka slovnice sudoers različica %d\n"
+
+#: plugins/sudoers/policy.c:665
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Pot sudoers: %s\n"
+
+#: plugins/sudoers/policy.c:668
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "pot nsswitch: %s\n"
+
+#: plugins/sudoers/policy.c:670
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "pot ldap.conf: %s\n"
+
+#: plugins/sudoers/policy.c:671
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "pot ldap.secret: %s\n"
+
+#: plugins/sudoers/pwutil.c:148
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "ni mogoče predpomniti ID-ja uporabnika %u, že obstaja"
+
+#: plugins/sudoers/pwutil.c:190
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "ni mogoče predpomniti uporabnika %s, že obstaja"
+
+#: plugins/sudoers/pwutil.c:374
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "ni mogoče predpomniti ID-ja skupine %u, že obstaja"
+
+#: plugins/sudoers/pwutil.c:410
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "ni mogoče predpomniti skupine %s, že obstaja"
+
+#: plugins/sudoers/pwutil.c:564 plugins/sudoers/pwutil.c:586
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "seznama skupina za %s ni mogoče predpomniti, saj že obstaja"
+
+#: plugins/sudoers/pwutil.c:584
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "skupin za %s ni mogoče razčleniti"
+
+#: plugins/sudoers/set_perms.c:122 plugins/sudoers/set_perms.c:445
+#: plugins/sudoers/set_perms.c:846 plugins/sudoers/set_perms.c:1141
+#: plugins/sudoers/set_perms.c:1431
+msgid "perm stack overflow"
+msgstr "prekoračitev trajnega sklada"
+
+#: plugins/sudoers/set_perms.c:130 plugins/sudoers/set_perms.c:453
+#: plugins/sudoers/set_perms.c:854 plugins/sudoers/set_perms.c:1149
+#: plugins/sudoers/set_perms.c:1439
+msgid "perm stack underflow"
+msgstr "prekoračitev spodnje meje trajnega sklada"
+
+#: plugins/sudoers/set_perms.c:189 plugins/sudoers/set_perms.c:500
+#: plugins/sudoers/set_perms.c:1200 plugins/sudoers/set_perms.c:1471
+msgid "unable to change to root gid"
+msgstr "številke skupine skrbnika ni mogoče spremeniti"
+
+#: plugins/sudoers/set_perms.c:278 plugins/sudoers/set_perms.c:597
+#: plugins/sudoers/set_perms.c:983 plugins/sudoers/set_perms.c:1277
+msgid "unable to change to runas gid"
+msgstr "ni mogoče spremeniti v ID-ja skupine runas"
+
+#: plugins/sudoers/set_perms.c:290 plugins/sudoers/set_perms.c:609
+#: plugins/sudoers/set_perms.c:993 plugins/sudoers/set_perms.c:1287
+msgid "unable to change to runas uid"
+msgstr "ni mogoče spremeniti v ID-ja uporabnika runas"
+
+#: plugins/sudoers/set_perms.c:308 plugins/sudoers/set_perms.c:627
+#: plugins/sudoers/set_perms.c:1009 plugins/sudoers/set_perms.c:1303
+msgid "unable to change to sudoers gid"
+msgstr "ni mogoče spremeniti ID-ja skupine sudoers"
+
+#: plugins/sudoers/set_perms.c:361 plugins/sudoers/set_perms.c:698
+#: plugins/sudoers/set_perms.c:1055 plugins/sudoers/set_perms.c:1349
+#: plugins/sudoers/set_perms.c:1515
+msgid "too many processes"
+msgstr "preveč opravil"
+
+#: plugins/sudoers/set_perms.c:1583
+msgid "unable to set runas group vector"
+msgstr "ni mogoče nastaviti vektorja skupine runas"
+
+#: plugins/sudoers/sssd.c:256
+#, c-format
+msgid "Unable to dlopen %s: %s"
+msgstr "ni mogoče uporabiti dlopen %s: %s"
+
+#: plugins/sudoers/sssd.c:257
+#, c-format
+msgid "Unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "Vira SSS ni mogoče zagnati. Ali je SSSD pravilno nameščen?"
+
+#: plugins/sudoers/sssd.c:263 plugins/sudoers/sssd.c:271
+#: plugins/sudoers/sssd.c:278 plugins/sudoers/sssd.c:285
+#: plugins/sudoers/sssd.c:292
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "simbola \"%s\" ni mogoče najti v %s"
+
+#: plugins/sudoers/sudo_nss.c:283
+#, c-format
+msgid "Matching Defaults entries for %s on this host:\n"
+msgstr "Ujemajoči vpisi privzetih vrednosti za %s na tem gostitelju:\n"
+
+#: plugins/sudoers/sudo_nss.c:296
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Runas in ukazno določene privzete vrednosti za %s:\n"
+
+#: plugins/sudoers/sudo_nss.c:309
+#, c-format
+msgid "User %s may run the following commands on this host:\n"
+msgstr "Na tem gostitelju lahko uporabnik %s zažene naslednje ukaze:\n"
+
+#: plugins/sudoers/sudo_nss.c:318
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Uporabniku %s ni dovoljeno zagnati sudo na %s.\n"
+
+#: plugins/sudoers/sudoers.c:159 plugins/sudoers/sudoers.c:193
+#: plugins/sudoers/sudoers.c:673
+msgid "problem with defaults entries"
+msgstr "težave z vnosi privzetih vrednosti"
+
+#: plugins/sudoers/sudoers.c:165
+#, c-format
+msgid "no valid sudoers sources found, quitting"
+msgstr "najdenih niso bili nobeni veljavni viri sudoers, končanje"
+
+#: plugins/sudoers/sudoers.c:227
+#, c-format
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers določa, da skrbniku ni dovoljeno uporabiti sudo"
+
+#: plugins/sudoers/sudoers.c:234
+#, c-format
+msgid "you are not permitted to use the -C option"
+msgstr "ni vam dovoljeno uporabiti možnosti -C"
+
+#: plugins/sudoers/sudoers.c:315
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr "lastnik časovnega žiga (%s): ni takšnega uporabnika"
+
+#: plugins/sudoers/sudoers.c:329
+msgid "no tty"
+msgstr "brez tty"
+
+#: plugins/sudoers/sudoers.c:330
+#, c-format
+msgid "sorry, you must have a tty to run sudo"
+msgstr "za izvajanje sudo morate imeti tty"
+
+#: plugins/sudoers/sudoers.c:378
+msgid "command in current directory"
+msgstr "ukaz v trenutni mapi"
+
+#: plugins/sudoers/sudoers.c:395
+#, c-format
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "nimate dovoljenj za ohranjanje okolja"
+
+#: plugins/sudoers/sudoers.c:723 plugins/sudoers/timestamp.c:215
+#: plugins/sudoers/timestamp.c:259 plugins/sudoers/timestamp.c:327
+#: plugins/sudoers/visudo.c:310 plugins/sudoers/visudo.c:576
+#, c-format
+msgid "unable to stat %s"
+msgstr "stanja %s ni mogoče dobiti"
+
+#: plugins/sudoers/sudoers.c:726
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s ni običajna datoteka"
+
+#: plugins/sudoers/sudoers.c:729 toke.l:842
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s je v lasti ID-ja uporabnika %u, moral bi biti %u"
+
+#: plugins/sudoers/sudoers.c:733 toke.l:849
+#, c-format
+msgid "%s is world writable"
+msgstr "v datoteko %s lahko zapisujejo vsi uporabniki"
+
+#: plugins/sudoers/sudoers.c:736 toke.l:854
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s je v lasti ID-ja skupine %u, moral bi biti %u"
+
+#: plugins/sudoers/sudoers.c:763
+#, c-format
+msgid "only root can use `-c %s'"
+msgstr "samo skrbnik lahko uporabi `-c %s'"
+
+#: plugins/sudoers/sudoers.c:780 plugins/sudoers/sudoers.c:782
+#, c-format
+msgid "unknown login class: %s"
+msgstr "neznan razred prijave: %s"
+
+#: plugins/sudoers/sudoers.c:814
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "ni mogoče razrešiti gostitelja %s"
+
+#: plugins/sudoers/sudoers.c:866 plugins/sudoers/testsudoers.c:377
+#, c-format
+msgid "unknown group: %s"
+msgstr "neznana skupina: %s"
+
+#: plugins/sudoers/sudoreplay.c:292
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "neveljavna možnost filtra: %s"
+
+#: plugins/sudoers/sudoreplay.c:305
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "neveljavna zgornja meja čakanja: %s"
+
+#: plugins/sudoers/sudoreplay.c:311
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "neveljaven dejavnik hitrosti: %s"
+
+#: plugins/sudoers/sudoreplay.c:314 plugins/sudoers/visudo.c:179
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s različica %s\n"
+
+#: plugins/sudoers/sudoreplay.c:339
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s/timing: %s"
+msgstr "%s/%.2s/%.2s/%.2s/časovna uskladitev: %s"
+
+#: plugins/sudoers/sudoreplay.c:345
+#, c-format
+msgid "%s/%s/timing: %s"
+msgstr "%s/%s/časovna uskladitev: %s"
+
+#: plugins/sudoers/sudoreplay.c:363
+#, c-format
+msgid "Replaying sudo session: %s\n"
+msgstr "Izpisovanje dnevnika seje sudo: %s\n"
+
+#: plugins/sudoers/sudoreplay.c:369
+#, c-format
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr "Opozorilo: terminal je premajhen za pravilno izpisovanje dnevnika.\n"
+
+#: plugins/sudoers/sudoreplay.c:370
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Geometrija dnevnika je %d x %d, medtem ko je geometrija terminala %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:400
+#, c-format
+msgid "unable to set tty to raw mode"
+msgstr "ni mogoče nastaviti tty na surov način"
+
+#: plugins/sudoers/sudoreplay.c:416
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "neveljavna vrstica datoteke časovne uskladitve: %s"
+
+#: plugins/sudoers/sudoreplay.c:499
+#, c-format
+msgid "writing to standard output"
+msgstr "pisanje na standardni izhod"
+
+#: plugins/sudoers/sudoreplay.c:528
+#, c-format
+msgid "nanosleep: tv_sec %ld, tv_nsec %ld"
+msgstr "nanosleep: tv_sec %ld, tv_nsec %ld"
+
+#: plugins/sudoers/sudoreplay.c:641 plugins/sudoers/sudoreplay.c:666
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "dvoumen izraz \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:683
+#, c-format
+msgid "too many parenthesized expressions, max %d"
+msgstr "preveč izrazov z oklepaji, največje število %d"
+
+#: plugins/sudoers/sudoreplay.c:694
+#, c-format
+msgid "unmatched ')' in expression"
+msgstr "v izrazu je neujemajoč ')'"
+
+#: plugins/sudoers/sudoreplay.c:700
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "naznan iskalni izraz \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:714
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s zahteva argument"
+
+#: plugins/sudoers/sudoreplay.c:718
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr "neveljaven logični izraz: %s"
+
+#: plugins/sudoers/sudoreplay.c:724
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "ni mogoče razčleniti datuma \"%s\""
+
+#: plugins/sudoers/sudoreplay.c:737
+#, c-format
+msgid "unmatched '(' in expression"
+msgstr "v izrazu je neujemajoč '('"
+
+#: plugins/sudoers/sudoreplay.c:739
+#, c-format
+msgid "illegal trailing \"or\""
+msgstr "neveljaven zaključni \"or\""
+
+#: plugins/sudoers/sudoreplay.c:741
+#, c-format
+msgid "illegal trailing \"!\""
+msgstr "neveljaven zaključni \"!\""
+
+#: plugins/sudoers/sudoreplay.c:1058
+#, c-format
+msgid "invalid regex: %s"
+msgstr "neveljavni logični izraz: %s"
+
+#: plugins/sudoers/sudoreplay.c:1182
+#, c-format
+msgid "usage: %s [-h] [-d directory] [-m max_wait] [-s speed_factor] ID\n"
+msgstr "uporaba: %s [-h] [-d mapa] [-m zg_meja_čakanja] [-s faktor_hitrosti] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1185
+#, c-format
+msgid "usage: %s [-h] [-d directory] -l [search expression]\n"
+msgstr "uporaba: %s [-h] [-d mapa] -l [iskalni izraz]\n"
+
+#: plugins/sudoers/sudoreplay.c:1194
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - ponovno predvajaj dnevnike sej sudo\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1196
+msgid ""
+"\n"
+"Options:\n"
+" -d directory specify directory for session logs\n"
+" -f filter specify which I/O type to display\n"
+" -h display help message and exit\n"
+" -l [expression] list available session IDs that match expression\n"
+" -m max_wait max number of seconds to wait between events\n"
+" -s speed_factor speed up or slow down output\n"
+" -V display version information and exit"
+msgstr ""
+"\n"
+"Možnosti:\n"
+" -d mapa določi mapo za dnevnike sej\n"
+" -f filter navedi, katera vrsta I/O se naj prikaže \n"
+" -h prikaži sporočilo pomoči in končaj\n"
+" -l [izraz] navedi razpoložljive ID-je sej, ki se ujemajo z izrazom\n"
+" -m zg_meja_čakanja največje število sekund za čakanje med dogodki\n"
+" -s faktor_hitrosti pospeši ali upočasni izhod\n"
+" -V prikaži podrobnosti o različici in končaj"
+
+#: plugins/sudoers/testsudoers.c:328
+msgid "\thost unmatched"
+msgstr "\tgostitelj se ne ujema"
+
+#: plugins/sudoers/testsudoers.c:331
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Ukaz je dovoljen"
+
+#: plugins/sudoers/testsudoers.c:332
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Ukaz je bil zavrnjen"
+
+#: plugins/sudoers/testsudoers.c:332
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Ukaz se ne ujema"
+
+#: plugins/sudoers/timestamp.c:128
+#, c-format
+msgid "timestamp path too long: %s"
+msgstr "pot časovnega žiga je predolga : %s"
+
+#: plugins/sudoers/timestamp.c:202 plugins/sudoers/timestamp.c:246
+#: plugins/sudoers/timestamp.c:291
+#, c-format
+msgid "%s owned by uid %u, should be uid %u"
+msgstr "%s je v lasti ID-ja uporabnika %u, moral bi biti ID uporabnika %u"
+
+#: plugins/sudoers/timestamp.c:207 plugins/sudoers/timestamp.c:251
+#, c-format
+msgid "%s writable by non-owner (0%o), should be mode 0700"
+msgstr "%s je zapisljiv za ne-lastnika (0%o), moral bi biti način 0700"
+
+#: plugins/sudoers/timestamp.c:285
+#, c-format
+msgid "%s exists but is not a regular file (0%o)"
+msgstr "%s obstaja, toda ni običajna datoteka (0%o)"
+
+#: plugins/sudoers/timestamp.c:297
+#, c-format
+msgid "%s writable by non-owner (0%o), should be mode 0600"
+msgstr "%s je zapisljiv za ne-lastnika (0%o), moral bi biti način 0600"
+
+#: plugins/sudoers/timestamp.c:352
+#, c-format
+msgid "timestamp too far in the future: %20.20s"
+msgstr "časovni žig je predaleč v prihodnosti: %20.20s"
+
+#: plugins/sudoers/timestamp.c:406
+#, c-format
+msgid "unable to remove %s, will reset to the epoch"
+msgstr "%s ni mogoče odstraniti"
+
+#: plugins/sudoers/timestamp.c:413
+#, c-format
+msgid "unable to reset %s to the epoch"
+msgstr "%s ni mogoče ponastaviti na epoho"
+
+#: plugins/sudoers/toke_util.c:221
+#, c-format
+msgid "fill_args: buffer overflow"
+msgstr "fill_args: prekoračitev medpomnilnika"
+
+#: plugins/sudoers/visudo.c:180
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s različica slovnice %d\n"
+
+#: plugins/sudoers/visudo.c:243 plugins/sudoers/visudo.c:533
+#, c-format
+msgid "press return to edit %s: "
+msgstr "za urejanje %s pritisnite return: "
+
+#: plugins/sudoers/visudo.c:326 plugins/sudoers/visudo.c:332
+#, c-format
+msgid "write error"
+msgstr "napaka med pisanjem"
+
+#: plugins/sudoers/visudo.c:414
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "ni mogoče začeti začasne datoteke (%s), %s nepsremenjeno"
+
+#: plugins/sudoers/visudo.c:419
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "začasna datoteka brez dolžine (%s), %s nespremenjena"
+
+#: plugins/sudoers/visudo.c:425
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "urejevalnik (%s) je spodletel, %s nespremenjen"
+
+#: plugins/sudoers/visudo.c:448
+#, c-format
+msgid "%s unchanged"
+msgstr "%s nespremenjeno"
+
+#: plugins/sudoers/visudo.c:477
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "ni mogoče ponovno odpreti začasne datoteke (%s), %s je nespremenjen."
+
+#: plugins/sudoers/visudo.c:487
+#, c-format
+msgid "unabled to parse temporary file (%s), unknown error"
+msgstr "ni mogoče razčleniti začasne datoteke (%s), neznana napaka"
+
+#: plugins/sudoers/visudo.c:526
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr "notranja napaka, na seznamu ni mogoče najti %s!"
+
+#: plugins/sudoers/visudo.c:578 plugins/sudoers/visudo.c:587
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "ni mogoče nastaviti (ID uporabnika, ID skupine) od %s do (%u, %u)"
+
+#: plugins/sudoers/visudo.c:582 plugins/sudoers/visudo.c:592
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "ni mogoče spremeniti načina iz %s na 0%o"
+
+#: plugins/sudoers/visudo.c:609
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s in %s nista na enakem datotečnem sistemu, uporaba mv za preimenovanje"
+
+#: plugins/sudoers/visudo.c:623
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "ukaz je spodletel: '%s %s %s', %s nespremenjen"
+
+#: plugins/sudoers/visudo.c:633
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "napaka med preimenovanjem %s, %s nespremenjen"
+
+#: plugins/sudoers/visudo.c:695
+msgid "What now? "
+msgstr "Kaj pa zdaj? "
+
+#: plugins/sudoers/visudo.c:709
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Možnosti so:\n"
+" (e)ponovno uredi datoteko sudoers\n"
+" (x)končaj brez shranjevanja sprememb v datoteko sudoers\n"
+" (Q)končaj in shrani spremembe v datoteko sudoers (NEVARNOST!)\n"
+
+#: plugins/sudoers/visudo.c:757
+#, c-format
+msgid "unable to run %s"
+msgstr "ni mogoče zagnati %s"
+
+#: plugins/sudoers/visudo.c:783
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: napačen lastnik (ID uporabnika, ID skupine) moralo bi biti (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:790
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: slaba dovoljenja, moral bi biti način 0%o\n"
+
+#: plugins/sudoers/visudo.c:815
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "razčlenjevanje datoteke %s je spodletelo, neznana napaka"
+
+#: plugins/sudoers/visudo.c:831
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr "napaka razčlenjevanja v %s blizu vrstice %d\n"
+
+#: plugins/sudoers/visudo.c:834
+#, c-format
+msgid "parse error in %s\n"
+msgstr "napaka razčlenjevanja v %s\n"
+
+#: plugins/sudoers/visudo.c:841 plugins/sudoers/visudo.c:846
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: uspešno razčlenjeno\n"
+
+#: plugins/sudoers/visudo.c:893
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s zaseden, poskusite ponovno pozneje"
+
+#: plugins/sudoers/visudo.c:937
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "določen urejevalnik (%s) se ne konča"
+
+#: plugins/sudoers/visudo.c:960
+#, c-format
+msgid "unable to stat editor (%s)"
+msgstr "ni mogoče začeti urejevalnika (%s)"
+
+#: plugins/sudoers/visudo.c:1008
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "najdenega ni nobenega urejevalnika (pot urejevalnika = %s)"
+
+#: plugins/sudoers/visudo.c:1100
+#, c-format
+msgid "Error: cycle in %s_Alias `%s'"
+msgstr "Napaka: kroženje v %s_Alias `%s'"
+
+#: plugins/sudoers/visudo.c:1101
+#, c-format
+msgid "Warning: cycle in %s_Alias `%s'"
+msgstr "Opozorilo: kroženje v %s_Alias `%s'"
+
+#: plugins/sudoers/visudo.c:1104
+#, c-format
+msgid "Error: %s_Alias `%s' referenced but not defined"
+msgstr "Napaka: %s_Alias `%s' sklicevan, toda ne določen"
+
+#: plugins/sudoers/visudo.c:1105
+#, c-format
+msgid "Warning: %s_Alias `%s' referenced but not defined"
+msgstr "Warning: %s_Alias `%s' sklicevan, toda ne določen"
+
+#: plugins/sudoers/visudo.c:1240
+#, c-format
+msgid "%s: unused %s_Alias %s"
+msgstr "%s: neuporabljen %s_Alias %s"
+
+#: plugins/sudoers/visudo.c:1302
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - varno uredi datoteko sudoers\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1304
+msgid ""
+"\n"
+"Options:\n"
+" -c check-only mode\n"
+" -f sudoers specify sudoers file location\n"
+" -h display help message and exit\n"
+" -q less verbose (quiet) syntax error messages\n"
+" -s strict syntax checking\n"
+" -V display version information and exit"
+msgstr ""
+"\n"
+"Možnosti:\n"
+" -c način samo preverjanja\n"
+" -f sudoers določi mesto datoteke sudoers\n"
+" -h prikaži sporočilo pomoči in končaj\n"
+" -q manj podroben izpis (tih) sporočil skladenjskih napak\n"
+" -s strogo preverjanje skladnje\n"
+" -V prikaži podrobnosti različice in končaj"
+
+#: toke.l:815
+msgid "too many levels of includes"
+msgstr "preveč stopenj vključitev"
diff --git a/plugins/sudoers/po/sr.mo b/plugins/sudoers/po/sr.mo
new file mode 100644
index 0000000..0358ccf
--- /dev/null
+++ b/plugins/sudoers/po/sr.mo
Binary files differ
diff --git a/plugins/sudoers/po/sr.po b/plugins/sudoers/po/sr.po
new file mode 100644
index 0000000..f92196a
--- /dev/null
+++ b/plugins/sudoers/po/sr.po
@@ -0,0 +1,4094 @@
+# Serbian translation for sudoers.
+# This file is put in the public domain.
+# Мирослав Николић <miroslavnikolic@rocketmail.com>, 2014-2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers-1.9.14b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-06-07 13:27-0600\n"
+"PO-Revision-Date: 2023-07-21 08:10+0200\n"
+"Last-Translator: Мирослав Николић <miroslavnikolic@rocketmail.com>\n"
+"Language-Team: Serbian <(nothing)>\n"
+"Language: sr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Gtranslator 41.0\n"
+
+#: confstr.sh:1 gram.y:1240 plugins/sudoers/logging.c:885
+msgid "syntax error"
+msgstr "грешка синтаксе"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "Лозинка корисника %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[судо] лозинка за корисника %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Лозинка: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** информације БЕЗБЕДНОСТИ за %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Извините, покушајте поново."
+
+#: gram.y:236 gram.y:303 gram.y:312 gram.y:321 gram.y:331 gram.y:341
+#: gram.y:365 gram.y:392 gram.y:401 gram.y:409 gram.y:418 gram.y:427
+#: gram.y:501 gram.y:511 gram.y:523 gram.y:571 gram.y:580 gram.y:589
+#: gram.y:598 gram.y:730 gram.y:738 gram.y:749 gram.y:761 gram.y:780
+#: gram.y:943 gram.y:948 gram.y:956 gram.y:970 gram.y:976 gram.y:988
+#: gram.y:994 gram.y:1119 gram.y:1128 gram.y:1136 gram.y:1145 gram.y:1154
+#: gram.y:1183 gram.y:1192 gram.y:1200 gram.y:1300 gram.y:1430 gram.y:1808
+#: gram.y:1819 gram.y:1901 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:313 lib/eventlog/eventlog.c:755
+#: lib/eventlog/eventlog.c:832 lib/eventlog/eventlog.c:1133
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:472
+#: lib/eventlog/parse_json.c:502 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_legacy.c:100 lib/iolog/iolog_legacy.c:111
+#: lib/iolog/iolog_legacy.c:123 lib/iolog/iolog_legacy.c:133
+#: lib/iolog/iolog_legacy.c:139 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:182 logsrvd/iolog_writer.c:215
+#: logsrvd/iolog_writer.c:225 logsrvd/iolog_writer.c:254
+#: logsrvd/iolog_writer.c:275 logsrvd/iolog_writer.c:287
+#: logsrvd/iolog_writer.c:297 logsrvd/iolog_writer.c:307
+#: logsrvd/iolog_writer.c:317 logsrvd/iolog_writer.c:329
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:370
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:567 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:1058 logsrvd/logsrvd.c:1121 logsrvd/logsrvd.c:1590
+#: logsrvd/logsrvd.c:1595 logsrvd/logsrvd.c:1782 logsrvd/logsrvd.c:1999
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:650
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1743
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:216
+#: logsrvd/logsrvd_journal.c:217 logsrvd/logsrvd_journal.c:273
+#: logsrvd/logsrvd_journal.c:278 logsrvd/logsrvd_journal.c:438
+#: logsrvd/logsrvd_journal.c:440 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:216 logsrvd/logsrvd_local.c:278
+#: logsrvd/logsrvd_local.c:279 logsrvd/logsrvd_local.c:417
+#: logsrvd/logsrvd_local.c:466 logsrvd/logsrvd_local.c:467
+#: logsrvd/logsrvd_local.c:472 logsrvd/logsrvd_local.c:473
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/logsrvd_relay.c:446
+#: logsrvd/logsrvd_relay.c:745 logsrvd/logsrvd_relay.c:852
+#: logsrvd/sendlog.c:251 logsrvd/sendlog.c:260 logsrvd/sendlog.c:292
+#: logsrvd/sendlog.c:298 logsrvd/sendlog.c:347 logsrvd/sendlog.c:624
+#: logsrvd/sendlog.c:1810 plugins/sudoers/audit.c:116
+#: plugins/sudoers/auth/bsdauth.c:152 plugins/sudoers/auth/kerb5.c:121
+#: plugins/sudoers/auth/kerb5.c:148 plugins/sudoers/auth/pam.c:687
+#: plugins/sudoers/auth/rfc1938.c:111 plugins/sudoers/auth/sia.c:59
+#: plugins/sudoers/canon_path.c:129 plugins/sudoers/canon_path.c:160
+#: plugins/sudoers/check_aliases.c:168 plugins/sudoers/cvtsudoers.c:132
+#: plugins/sudoers/cvtsudoers.c:176 plugins/sudoers/cvtsudoers.c:193
+#: plugins/sudoers/cvtsudoers.c:204 plugins/sudoers/cvtsudoers.c:334
+#: plugins/sudoers/cvtsudoers.c:373 plugins/sudoers/cvtsudoers.c:393
+#: plugins/sudoers/cvtsudoers.c:538 plugins/sudoers/cvtsudoers.c:691
+#: plugins/sudoers/cvtsudoers.c:709 plugins/sudoers/cvtsudoers.c:883
+#: plugins/sudoers/cvtsudoers.c:891 plugins/sudoers/cvtsudoers.c:1386
+#: plugins/sudoers/cvtsudoers.c:1390 plugins/sudoers/cvtsudoers.c:1492
+#: plugins/sudoers/cvtsudoers_csv.c:183 plugins/sudoers/cvtsudoers_csv.c:247
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:151
+#: plugins/sudoers/cvtsudoers_ldif.c:194 plugins/sudoers/cvtsudoers_ldif.c:235
+#: plugins/sudoers/cvtsudoers_ldif.c:300 plugins/sudoers/cvtsudoers_ldif.c:376
+#: plugins/sudoers/cvtsudoers_ldif.c:430 plugins/sudoers/cvtsudoers_ldif.c:438
+#: plugins/sudoers/cvtsudoers_ldif.c:449 plugins/sudoers/cvtsudoers_ldif.c:456
+#: plugins/sudoers/cvtsudoers_ldif.c:468 plugins/sudoers/cvtsudoers_ldif.c:481
+#: plugins/sudoers/cvtsudoers_ldif.c:489 plugins/sudoers/cvtsudoers_ldif.c:636
+#: plugins/sudoers/cvtsudoers_merge.c:47 plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1158
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:434
+#: plugins/sudoers/defaults.c:657 plugins/sudoers/defaults.c:1018
+#: plugins/sudoers/defaults.c:1186 plugins/sudoers/editor.c:197
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:55 plugins/sudoers/filedigest.c:71
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:212
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:667 plugins/sudoers/iolog.c:693
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:447
+#: plugins/sudoers/ldap.c:622 plugins/sudoers/ldap.c:786
+#: plugins/sudoers/ldap.c:1210 plugins/sudoers/ldap.c:1636
+#: plugins/sudoers/ldap.c:1673 plugins/sudoers/ldap.c:1888
+#: plugins/sudoers/ldap.c:1997 plugins/sudoers/ldap.c:2013
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:562 plugins/sudoers/ldap_conf.c:595
+#: plugins/sudoers/ldap_conf.c:691 plugins/sudoers/ldap_conf.c:773
+#: plugins/sudoers/ldap_util.c:294 plugins/sudoers/ldap_util.c:301
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:402
+#: plugins/sudoers/log_client.c:717 plugins/sudoers/log_client.c:739
+#: plugins/sudoers/log_client.c:744 plugins/sudoers/log_client.c:1423
+#: plugins/sudoers/log_client.c:1544 plugins/sudoers/log_client.c:1667
+#: plugins/sudoers/log_client.c:1986 plugins/sudoers/log_client.c:2045
+#: plugins/sudoers/logging.c:110 plugins/sudoers/logging.c:189
+#: plugins/sudoers/logging.c:457 plugins/sudoers/logging.c:690
+#: plugins/sudoers/logging.c:846 plugins/sudoers/match_command.c:295
+#: plugins/sudoers/match_command.c:563 plugins/sudoers/match_command.c:629
+#: plugins/sudoers/match_command.c:724 plugins/sudoers/match_command.c:770
+#: plugins/sudoers/match_digest.c:82 plugins/sudoers/parse.c:279
+#: plugins/sudoers/parse.c:296 plugins/sudoers/parse.c:315
+#: plugins/sudoers/parse.c:334 plugins/sudoers/parse.c:351
+#: plugins/sudoers/parse.c:374 plugins/sudoers/parse.c:385
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:598
+#: plugins/sudoers/parse_ldif.c:628 plugins/sudoers/parse_ldif.c:653
+#: plugins/sudoers/parse_ldif.c:711 plugins/sudoers/parse_ldif.c:728
+#: plugins/sudoers/parse_ldif.c:756 plugins/sudoers/parse_ldif.c:763
+#: plugins/sudoers/policy.c:622 plugins/sudoers/policy.c:1050
+#: plugins/sudoers/prompt.c:93 plugins/sudoers/pwutil.c:199
+#: plugins/sudoers/pwutil.c:270 plugins/sudoers/pwutil.c:348
+#: plugins/sudoers/pwutil.c:522 plugins/sudoers/pwutil.c:587
+#: plugins/sudoers/pwutil.c:659 plugins/sudoers/pwutil.c:857
+#: plugins/sudoers/pwutil.c:945 plugins/sudoers/pwutil.c:993
+#: plugins/sudoers/pwutil.c:1052 plugins/sudoers/sssd.c:145
+#: plugins/sudoers/sssd.c:185 plugins/sudoers/sssd.c:414
+#: plugins/sudoers/sssd.c:479 plugins/sudoers/sssd.c:505
+#: plugins/sudoers/sssd.c:568 plugins/sudoers/sssd.c:762
+#: plugins/sudoers/strvec_join.c:53 plugins/sudoers/stubs.c:126
+#: plugins/sudoers/stubs.c:134 plugins/sudoers/sudoers.c:352
+#: plugins/sudoers/sudoers.c:378 plugins/sudoers/sudoers.c:441
+#: plugins/sudoers/sudoers.c:673 plugins/sudoers/sudoers.c:683
+#: plugins/sudoers/sudoers.c:824 plugins/sudoers/sudoers.c:890
+#: plugins/sudoers/sudoers.c:946 plugins/sudoers/sudoers.c:998
+#: plugins/sudoers/sudoers.c:1174 plugins/sudoers/sudoers.c:1241
+#: plugins/sudoers/sudoers.c:1325 plugins/sudoers/sudoers.c:1513
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1278 plugins/sudoers/sudoreplay.c:1334
+#: plugins/sudoers/sudoreplay.c:1530 plugins/sudoers/sudoreplay.c:1534
+#: plugins/sudoers/testsudoers.c:123 plugins/sudoers/testsudoers.c:220
+#: plugins/sudoers/testsudoers.c:233 plugins/sudoers/testsudoers.c:250
+#: plugins/sudoers/testsudoers.c:617 plugins/sudoers/timestamp.c:476
+#: plugins/sudoers/timestamp.c:520 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1171 plugins/sudoers/toke_util.c:78
+#: plugins/sudoers/toke_util.c:106 plugins/sudoers/toke_util.c:131
+#: plugins/sudoers/toke_util.c:161 plugins/sudoers/toke_util.c:200
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:154
+#: plugins/sudoers/visudo.c:263 plugins/sudoers/visudo.c:388
+#: plugins/sudoers/visudo.c:394 plugins/sudoers/visudo.c:505
+#: plugins/sudoers/visudo.c:1065 plugins/sudoers/visudo.c:1087
+#: plugins/sudoers/visudo.c:1180 toke.l:1032 toke.l:1195 toke.l:1223
+#: toke.l:1299
+msgid "unable to allocate memory"
+msgstr "не могу да доделим меморију"
+
+#: gram.y:622
+msgid "a digest requires a path name"
+msgstr "зборник захтева назив путање"
+
+#: gram.y:644
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "вредност за „CWD“ мора почети са /, ~, или *"
+
+#: gram.y:650
+msgid "\"CWD\" path too long"
+msgstr "„CWD“ путања је предуга"
+
+#: gram.y:660
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "вредност за „CHROOT“ мора почети са /, ~, или *"
+
+#: gram.y:666
+msgid "\"CHROOT\" path too long"
+msgstr "„CHROOT“ путања је предуга"
+
+#: gram.y:801
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "грешка синтаксе, резервисана реч „%s“ је коришћена као назив алијаса"
+
+#: gram.y:824
+msgid "invalid notbefore value"
+msgstr "неисправна вредност не-пре"
+
+#: gram.y:833
+msgid "invalid notafter value"
+msgstr "неисправна вредност не-после"
+
+#: gram.y:843 plugins/sudoers/policy.c:381
+msgid "timeout value too large"
+msgstr "вредност временског истека је превелика"
+
+#: gram.y:845 plugins/sudoers/policy.c:383
+msgid "invalid timeout value"
+msgstr "неисправна вредност временског ограничења"
+
+#: gram.y:966 plugins/sudoers/sudoers.c:1192
+msgid "command too long"
+msgstr "наредба је предуга"
+
+#: gram.y:1000
+msgid "expected a fully-qualified path name"
+msgstr "очекивах потпуно квалификован назив путање"
+
+#: gram.y:1244 plugins/sudoers/check_aliases.c:96
+#: plugins/sudoers/defaults.c:1275
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: gram.y:1298
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Псеудоним „%s“ је већ одређен"
+
+#: gram.y:1808 gram.y:1819 gram.y:1901 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:755 lib/eventlog/eventlog.c:828
+#: lib/eventlog/eventlog.c:831 lib/eventlog/eventlog.c:1133
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:471
+#: lib/eventlog/parse_json.c:502 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:232
+#: lib/iolog/iolog_legacy.c:100 lib/iolog/iolog_legacy.c:111
+#: lib/iolog/iolog_legacy.c:123 lib/iolog/iolog_legacy.c:133
+#: lib/iolog/iolog_legacy.c:139 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:171 logsrvd/iolog_writer.c:181
+#: logsrvd/iolog_writer.c:194 logsrvd/iolog_writer.c:214
+#: logsrvd/iolog_writer.c:224 logsrvd/iolog_writer.c:243
+#: logsrvd/iolog_writer.c:253 logsrvd/iolog_writer.c:264
+#: logsrvd/iolog_writer.c:274 logsrvd/iolog_writer.c:286
+#: logsrvd/iolog_writer.c:296 logsrvd/iolog_writer.c:306
+#: logsrvd/iolog_writer.c:316 logsrvd/iolog_writer.c:328
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:370
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:567 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:530
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:668
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:1132
+#: logsrvd/logsrvd.c:1447 logsrvd/logsrvd.c:1454 logsrvd/logsrvd.c:1590
+#: logsrvd/logsrvd.c:1595 logsrvd/logsrvd.c:1782 logsrvd/logsrvd.c:1999
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:649
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1742
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:125
+#: logsrvd/logsrvd_journal.c:216 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:250 logsrvd/logsrvd_journal.c:258
+#: logsrvd/logsrvd_journal.c:286 logsrvd/logsrvd_journal.c:290
+#: logsrvd/logsrvd_journal.c:438 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:278 logsrvd/logsrvd_local.c:466
+#: logsrvd/logsrvd_local.c:472 logsrvd/logsrvd_local.c:491
+#: logsrvd/logsrvd_queue.c:158 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/sendlog.c:251 logsrvd/sendlog.c:260
+#: logsrvd/sendlog.c:292 logsrvd/sendlog.c:298 logsrvd/sendlog.c:347
+#: logsrvd/sendlog.c:624 logsrvd/sendlog.c:1512 logsrvd/sendlog.c:1519
+#: logsrvd/sendlog.c:1742 logsrvd/sendlog.c:1810 logsrvd/tls_init.c:305
+#: logsrvd/tls_init.c:329 logsrvd/tls_init.c:340 plugins/sudoers/audit.c:116
+#: plugins/sudoers/auth/pam.c:502 plugins/sudoers/auth/pam.c:687
+#: plugins/sudoers/auth/rfc1938.c:111 plugins/sudoers/canon_path.c:129
+#: plugins/sudoers/canon_path.c:160 plugins/sudoers/check_aliases.c:168
+#: plugins/sudoers/cvtsudoers.c:132 plugins/sudoers/cvtsudoers.c:175
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:203
+#: plugins/sudoers/cvtsudoers.c:333 plugins/sudoers/cvtsudoers.c:537
+#: plugins/sudoers/cvtsudoers.c:690 plugins/sudoers/cvtsudoers.c:708
+#: plugins/sudoers/cvtsudoers.c:883 plugins/sudoers/cvtsudoers.c:890
+#: plugins/sudoers/cvtsudoers.c:1386 plugins/sudoers/cvtsudoers.c:1390
+#: plugins/sudoers/cvtsudoers.c:1492 plugins/sudoers/cvtsudoers_csv.c:182
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:150 plugins/sudoers/cvtsudoers_ldif.c:193
+#: plugins/sudoers/cvtsudoers_ldif.c:234 plugins/sudoers/cvtsudoers_ldif.c:299
+#: plugins/sudoers/cvtsudoers_ldif.c:375 plugins/sudoers/cvtsudoers_ldif.c:429
+#: plugins/sudoers/cvtsudoers_ldif.c:437 plugins/sudoers/cvtsudoers_ldif.c:448
+#: plugins/sudoers/cvtsudoers_ldif.c:455 plugins/sudoers/cvtsudoers_ldif.c:467
+#: plugins/sudoers/cvtsudoers_ldif.c:480 plugins/sudoers/cvtsudoers_ldif.c:488
+#: plugins/sudoers/cvtsudoers_ldif.c:635 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1157
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:434
+#: plugins/sudoers/defaults.c:657 plugins/sudoers/defaults.c:1018
+#: plugins/sudoers/defaults.c:1186 plugins/sudoers/editor.c:197
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:55 plugins/sudoers/filedigest.c:71
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:211
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:667 plugins/sudoers/iolog.c:693
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:447
+#: plugins/sudoers/ldap.c:622 plugins/sudoers/ldap.c:786
+#: plugins/sudoers/ldap.c:1210 plugins/sudoers/ldap.c:1636
+#: plugins/sudoers/ldap.c:1673 plugins/sudoers/ldap.c:1888
+#: plugins/sudoers/ldap.c:1997 plugins/sudoers/ldap.c:2013
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:562 plugins/sudoers/ldap_conf.c:595
+#: plugins/sudoers/ldap_conf.c:690 plugins/sudoers/ldap_conf.c:773
+#: plugins/sudoers/ldap_util.c:293 plugins/sudoers/ldap_util.c:300
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:228
+#: plugins/sudoers/log_client.c:250 plugins/sudoers/log_client.c:264
+#: plugins/sudoers/log_client.c:402 plugins/sudoers/log_client.c:717
+#: plugins/sudoers/log_client.c:739 plugins/sudoers/log_client.c:744
+#: plugins/sudoers/log_client.c:1423 plugins/sudoers/log_client.c:1544
+#: plugins/sudoers/log_client.c:1667 plugins/sudoers/log_client.c:1986
+#: plugins/sudoers/log_client.c:2045 plugins/sudoers/logging.c:110
+#: plugins/sudoers/logging.c:188 plugins/sudoers/logging.c:189
+#: plugins/sudoers/logging.c:457 plugins/sudoers/logging.c:690
+#: plugins/sudoers/logging.c:734 plugins/sudoers/logging.c:846
+#: plugins/sudoers/logging.c:899 plugins/sudoers/logging.c:906
+#: plugins/sudoers/match_command.c:294 plugins/sudoers/match_command.c:562
+#: plugins/sudoers/match_command.c:628 plugins/sudoers/match_command.c:724
+#: plugins/sudoers/match_command.c:769 plugins/sudoers/match_digest.c:82
+#: plugins/sudoers/parse.c:278 plugins/sudoers/parse.c:295
+#: plugins/sudoers/parse.c:314 plugins/sudoers/parse.c:333
+#: plugins/sudoers/parse.c:350 plugins/sudoers/parse.c:373
+#: plugins/sudoers/parse.c:384 plugins/sudoers/parse_ldif.c:152
+#: plugins/sudoers/parse_ldif.c:183 plugins/sudoers/parse_ldif.c:252
+#: plugins/sudoers/parse_ldif.c:260 plugins/sudoers/parse_ldif.c:265
+#: plugins/sudoers/parse_ldif.c:341 plugins/sudoers/parse_ldif.c:352
+#: plugins/sudoers/parse_ldif.c:379 plugins/sudoers/parse_ldif.c:396
+#: plugins/sudoers/parse_ldif.c:408 plugins/sudoers/parse_ldif.c:412
+#: plugins/sudoers/parse_ldif.c:426 plugins/sudoers/parse_ldif.c:484
+#: plugins/sudoers/parse_ldif.c:598 plugins/sudoers/parse_ldif.c:627
+#: plugins/sudoers/parse_ldif.c:652 plugins/sudoers/parse_ldif.c:710
+#: plugins/sudoers/parse_ldif.c:727 plugins/sudoers/parse_ldif.c:755
+#: plugins/sudoers/parse_ldif.c:762 plugins/sudoers/policy.c:148
+#: plugins/sudoers/policy.c:157 plugins/sudoers/policy.c:166
+#: plugins/sudoers/policy.c:196 plugins/sudoers/policy.c:366
+#: plugins/sudoers/policy.c:381 plugins/sudoers/policy.c:383
+#: plugins/sudoers/policy.c:421 plugins/sudoers/policy.c:430
+#: plugins/sudoers/policy.c:478 plugins/sudoers/policy.c:488
+#: plugins/sudoers/policy.c:497 plugins/sudoers/policy.c:506
+#: plugins/sudoers/policy.c:515 plugins/sudoers/policy.c:622
+#: plugins/sudoers/policy.c:1050 plugins/sudoers/prompt.c:93
+#: plugins/sudoers/pwutil.c:199 plugins/sudoers/pwutil.c:270
+#: plugins/sudoers/pwutil.c:348 plugins/sudoers/pwutil.c:522
+#: plugins/sudoers/pwutil.c:587 plugins/sudoers/pwutil.c:659
+#: plugins/sudoers/pwutil.c:857 plugins/sudoers/pwutil.c:945
+#: plugins/sudoers/pwutil.c:993 plugins/sudoers/pwutil.c:1052
+#: plugins/sudoers/set_perms.c:369 plugins/sudoers/set_perms.c:717
+#: plugins/sudoers/set_perms.c:1089 plugins/sudoers/set_perms.c:1401
+#: plugins/sudoers/set_perms.c:1570 plugins/sudoers/sssd.c:144
+#: plugins/sudoers/sssd.c:185 plugins/sudoers/sssd.c:414
+#: plugins/sudoers/sssd.c:479 plugins/sudoers/sssd.c:505
+#: plugins/sudoers/sssd.c:568 plugins/sudoers/sssd.c:762
+#: plugins/sudoers/strvec_join.c:53 plugins/sudoers/stubs.c:126
+#: plugins/sudoers/stubs.c:134 plugins/sudoers/sudoers.c:352
+#: plugins/sudoers/sudoers.c:378 plugins/sudoers/sudoers.c:441
+#: plugins/sudoers/sudoers.c:673 plugins/sudoers/sudoers.c:683
+#: plugins/sudoers/sudoers.c:824 plugins/sudoers/sudoers.c:890
+#: plugins/sudoers/sudoers.c:946 plugins/sudoers/sudoers.c:998
+#: plugins/sudoers/sudoers.c:1174 plugins/sudoers/sudoers.c:1241
+#: plugins/sudoers/sudoers.c:1324 plugins/sudoers/sudoers.c:1513
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1278 plugins/sudoers/sudoreplay.c:1334
+#: plugins/sudoers/sudoreplay.c:1530 plugins/sudoers/sudoreplay.c:1534
+#: plugins/sudoers/testsudoers.c:123 plugins/sudoers/testsudoers.c:220
+#: plugins/sudoers/testsudoers.c:233 plugins/sudoers/testsudoers.c:250
+#: plugins/sudoers/testsudoers.c:617 plugins/sudoers/timestamp.c:476
+#: plugins/sudoers/timestamp.c:520 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1171 plugins/sudoers/toke_util.c:78
+#: plugins/sudoers/toke_util.c:106 plugins/sudoers/toke_util.c:131
+#: plugins/sudoers/toke_util.c:160 plugins/sudoers/toke_util.c:200
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:154
+#: plugins/sudoers/visudo.c:263 plugins/sudoers/visudo.c:388
+#: plugins/sudoers/visudo.c:394 plugins/sudoers/visudo.c:505
+#: plugins/sudoers/visudo.c:1065 plugins/sudoers/visudo.c:1086
+#: plugins/sudoers/visudo.c:1180 toke.l:1032 toke.l:1195 toke.l:1223
+#: toke.l:1288 toke.l:1299
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:304
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "не могу да удвостручим стандардни улаз: %m"
+
+#: lib/eventlog/eventlog.c:346
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "не могу да извршим „%s“: %m"
+
+#: lib/eventlog/eventlog.c:393 plugins/sudoers/auth/aix_auth.c:198
+msgid "unable to fork"
+msgstr "не могу да исцепим"
+
+#: lib/eventlog/eventlog.c:403 lib/eventlog/eventlog.c:468
+#, c-format
+msgid "unable to fork: %m"
+msgstr "не могу да исцепим: %m"
+
+#: lib/eventlog/eventlog.c:458
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "не могу да отворим спојку: %m"
+
+#: lib/eventlog/eventlog.c:958
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:987
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (наредба је настављена) %s"
+
+#: lib/eventlog/parse_json.c:175
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "очекивах „JSON_STRING“, добих „%d“"
+
+#: lib/eventlog/parse_json.c:180
+msgid "JSON_ARRAY too large"
+msgstr "„JSON_ARRAY“ је превелик"
+
+#: lib/eventlog/parse_json.c:494
+msgid "missing double quote in name"
+msgstr "недостају наводници у називу"
+
+#: lib/eventlog/parse_json.c:612
+msgid "missing JSON_OBJECT"
+msgstr "недостаје „JSON_OBJECT“"
+
+#: lib/eventlog/parse_json.c:616
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "очекивах „JSON_OBJECT“, добих „%d“"
+
+#: lib/eventlog/parse_json.c:750
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "јсон спремник је исцрпљен (највише %u кадра)"
+
+#: lib/eventlog/parse_json.c:828
+msgid "objects must consist of name:value pairs"
+msgstr "објекти морају да садрже пар „назив:вредност“"
+
+#: lib/eventlog/parse_json.c:833 lib/eventlog/parse_json.c:864
+#: lib/eventlog/parse_json.c:908 lib/eventlog/parse_json.c:930
+#: lib/eventlog/parse_json.c:952 lib/eventlog/parse_json.c:974
+#: lib/eventlog/parse_json.c:996
+msgid "missing separator between values"
+msgstr "недостаје раздвајач између вредности"
+
+#: lib/eventlog/parse_json.c:848 lib/eventlog/parse_json.c:1022
+msgid "unmatched close brace"
+msgstr "непоклопљена затворена велика заграда"
+
+#: lib/eventlog/parse_json.c:859
+msgid "unexpected array"
+msgstr "неочекиван низ"
+
+#: lib/eventlog/parse_json.c:879 lib/eventlog/parse_json.c:1025
+msgid "unmatched close bracket"
+msgstr "непоклопљена затворена средња заграда"
+
+#: lib/eventlog/parse_json.c:890
+msgid "unexpected string"
+msgstr "неочекивана ниска"
+
+#: lib/eventlog/parse_json.c:901
+msgid "missing colon after name"
+msgstr "недостају две тачке након имена"
+
+#: lib/eventlog/parse_json.c:922 lib/eventlog/parse_json.c:944
+msgid "unexpected boolean"
+msgstr "неочекивана логичка вредност"
+
+#: lib/eventlog/parse_json.c:966
+msgid "unexpected null"
+msgstr "неочекивана ништица"
+
+#: lib/eventlog/parse_json.c:987
+msgid "unexpected number"
+msgstr "неочекивани број"
+
+#: lib/eventlog/parse_json.c:1033
+msgid "parse error"
+msgstr "грешка обраде"
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1241
+#: plugins/sudoers/sudoreplay.c:1290 plugins/sudoers/sudoreplay.c:1586
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr "неисправан регуларан израз „%s“: %s"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: неисправна датотека дневника"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: недостаје поље временске ознаке"
+
+#: lib/iolog/iolog_legacy.c:89
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: временска ознака %s: %s"
+
+#: lib/iolog/iolog_legacy.c:96
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: недостаје поље корисника"
+
+#: lib/iolog/iolog_legacy.c:107
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: недостаје поље „покрени-као корисник“"
+
+#: lib/iolog/iolog_legacy.c:118
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: недостаје поље „покрени-као група“"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s постоји али није директоријум (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:123 lib/iolog/iolog_mkdtemp.c:79
+#: logsrvd/iolog_writer.c:781 plugins/sudoers/timestamp.c:234
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "не могу да направим директоријум „%s“"
+
+#: lib/iolog/iolog_mkdtemp.c:84 plugins/sudoers/visudo.c:760
+#: plugins/sudoers/visudo.c:794 plugins/sudoers/visudo.c:800
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "не могу да променим режим „%s“ на 0%o"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "грешка читања датотеке временисања: %s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "неисправан ред датотеке временисања: %s"
+
+#: logsrvd/iolog_writer.c:65
+#, c-format
+msgid "%s: protocol error: NULL key"
+msgstr "%s: грешка протокола: тастер „NULL“"
+
+#: logsrvd/iolog_writer.c:69
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s: грешка протокола: погрешна врста за „%s“"
+
+#: logsrvd/iolog_writer.c:74 logsrvd/logsrvd_local.c:109
+#: logsrvd/logsrvd_local.c:123 logsrvd/logsrvd_local.c:131
+#: logsrvd/logsrvd_local.c:149
+#, c-format
+msgid "%s: protocol error: NULL value found in %s"
+msgstr "%s: грешка протокола: „NULL“ вредност је нађена у „%s“"
+
+#: logsrvd/iolog_writer.c:141 plugins/sudoers/logging.c:993
+#: plugins/sudoers/policy.c:589
+msgid "unable to generate UUID"
+msgstr "не могу да створим УУИБ"
+
+#: logsrvd/iolog_writer.c:341 logsrvd/iolog_writer.c:346
+#: logsrvd/iolog_writer.c:351 logsrvd/iolog_writer.c:356
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s: грешка протокола: „%s“ недостаје из прихвата поруке"
+
+#: logsrvd/iolog_writer.c:417
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s: не могу да форматирам иб сесије"
+
+#: logsrvd/iolog_writer.c:431 logsrvd/iolog_writer.c:445
+#: logsrvd/iolog_writer.c:459 logsrvd/iolog_writer.c:474
+#: logsrvd/iolog_writer.c:488 logsrvd/iolog_writer.c:502
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s: „%s“ није постављено "
+
+#: logsrvd/iolog_writer.c:538 logsrvd/iolog_writer.c:545
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr "не могу да раширим путању „%s“ У/И дневника"
+
+#: logsrvd/iolog_writer.c:563
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr "не могу да створим путању „%s“ У/И дневника"
+
+#: logsrvd/iolog_writer.c:593
+#, c-format
+msgid "invalid iofd %d"
+msgstr "неисправан описник датотеке У/И %d"
+
+#: logsrvd/iolog_writer.c:613
+#, c-format
+msgid "error closing iofd %d: %s"
+msgstr "грешка затварања описника датотеке У/И %d: %s"
+
+#: logsrvd/iolog_writer.c:633
+#, c-format
+msgid "error flushing iofd %d: %s"
+msgstr "грешка исипања описника датотеке У/И %d: %s"
+
+#: logsrvd/iolog_writer.c:751
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "неисправан У/И дневник „%s“: „%s“ је упутно али није присутно"
+
+#: logsrvd/iolog_writer.c:763 logsrvd/logsrvd_journal.c:390
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "%s: не могу да нађем тачку наставка [%lld, %ld]"
+
+#: logsrvd/iolog_writer.c:785 logsrvd/logsrvd_journal.c:433
+#: logsrvd/logsrvd_queue.c:115 logsrvd/tls_init.c:256
+#: plugins/sudoers/check.c:292 plugins/sudoers/cvtsudoers.c:751
+#: plugins/sudoers/cvtsudoers.c:772 plugins/sudoers/cvtsudoers.c:1452
+#: plugins/sudoers/cvtsudoers_csv.c:697 plugins/sudoers/cvtsudoers_json.c:902
+#: plugins/sudoers/cvtsudoers_ldif.c:709 plugins/sudoers/sudoers.c:1310
+#: plugins/sudoers/sudoers.c:1334 plugins/sudoers/sudoreplay.c:1496
+#: plugins/sudoers/timestamp.c:485 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:982
+#, c-format
+msgid "unable to open %s"
+msgstr "не могу да отворим „%s“"
+
+#: logsrvd/iolog_writer.c:797 logsrvd/logsrv_util.c:111
+#: logsrvd/logsrv_util.c:118 plugins/sudoers/sudoreplay.c:355
+#: plugins/sudoers/sudoreplay.c:361
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "не могу да отворим „%s/%s“"
+
+#: logsrvd/iolog_writer.c:810
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "не могу да умножим „%s/%s“ у „%s/%s“: %s"
+
+#: logsrvd/iolog_writer.c:839 logsrvd/logsrvd_journal.c:198
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "не могу да преименујем „%s“ у „%s“"
+
+#: logsrvd/logsrv_util.c:153 logsrvd/logsrv_util.c:182
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s: не могу да нађем тачку наставка [%lld, %ld]"
+
+#: logsrvd/logsrv_util.c:165
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "недостаје У/И датотека дневника „%s/%s“"
+
+#: logsrvd/logsrv_util.c:172
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s: не могу да премотам унапред „%zu“"
+
+#: logsrvd/logsrvd.c:271 logsrvd/logsrvd_queue.c:135
+msgid "unable to connect to relay"
+msgstr "не могу да се повежем са преносником"
+
+#: logsrvd/logsrvd.c:338 logsrvd/logsrvd_relay.c:844
+#, c-format
+msgid "server message too large: %zu"
+msgstr "порука сервера је превелика: %zu"
+
+#: logsrvd/logsrvd.c:430 logsrvd/logsrvd.c:553 logsrvd/logsrvd.c:639
+#: logsrvd/logsrvd.c:881 logsrvd/logsrvd.c:895 logsrvd/logsrvd.c:1057
+#: logsrvd/logsrvd.c:1182 logsrvd/logsrvd.c:1355 logsrvd/logsrvd.c:1373
+#: logsrvd/logsrvd.c:1472 logsrvd/logsrvd.c:1597 logsrvd/logsrvd.c:1784
+#: logsrvd/logsrvd_journal.c:502 logsrvd/logsrvd_local.c:238
+#: logsrvd/logsrvd_queue.c:164 logsrvd/logsrvd_relay.c:172
+#: logsrvd/logsrvd_relay.c:249 logsrvd/logsrvd_relay.c:253
+#: logsrvd/logsrvd_relay.c:391 logsrvd/logsrvd_relay.c:583
+#: logsrvd/logsrvd_relay.c:744 logsrvd/logsrvd_relay.c:1133
+#: logsrvd/sendlog.c:1300 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:216 plugins/sudoers/audit.c:277
+#: plugins/sudoers/iolog.c:1030 plugins/sudoers/iolog.c:1163
+#: plugins/sudoers/iolog.c:1261 plugins/sudoers/log_client.c:121
+#: plugins/sudoers/log_client.c:343 plugins/sudoers/log_client.c:359
+#: plugins/sudoers/log_client.c:407 plugins/sudoers/log_client.c:613
+#: plugins/sudoers/log_client.c:620 plugins/sudoers/log_client.c:1111
+#: plugins/sudoers/log_client.c:1392 plugins/sudoers/log_client.c:1433
+#: plugins/sudoers/log_client.c:1441 plugins/sudoers/log_client.c:1600
+#: plugins/sudoers/log_client.c:1724 plugins/sudoers/log_client.c:2053
+#: plugins/sudoers/log_client.c:2061 plugins/sudoers/logging.c:147
+#: plugins/sudoers/logging.c:205 plugins/sudoers/sudoreplay.c:519
+#: plugins/sudoers/sudoreplay.c:566 plugins/sudoers/sudoreplay.c:808
+#: plugins/sudoers/sudoreplay.c:920 plugins/sudoers/sudoreplay.c:1011
+#: plugins/sudoers/sudoreplay.c:1026 plugins/sudoers/sudoreplay.c:1033
+#: plugins/sudoers/sudoreplay.c:1040 plugins/sudoers/sudoreplay.c:1047
+#: plugins/sudoers/sudoreplay.c:1054 plugins/sudoers/sudoreplay.c:1181
+msgid "unable to add event to queue"
+msgstr "не могу да додам догађај у ред"
+
+#: logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:491 logsrvd/logsrvd.c:523
+#: logsrvd/logsrvd.c:577 logsrvd/logsrvd.c:656 logsrvd/logsrvd.c:692
+#: logsrvd/logsrvd.c:728 logsrvd/logsrvd.c:764 logsrvd/logsrvd_relay.c:512
+#: logsrvd/logsrvd_relay.c:545
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr "неочекивано стање %d за „%s“"
+
+#: logsrvd/logsrvd.c:455 logsrvd/logsrvd.c:492 logsrvd/logsrvd.c:524
+#: logsrvd/logsrvd.c:578 logsrvd/logsrvd.c:657 logsrvd/logsrvd.c:693
+#: logsrvd/logsrvd.c:729 logsrvd/logsrvd.c:765 logsrvd/logsrvd_relay.c:514
+#: logsrvd/logsrvd_relay.c:547
+msgid "state machine error"
+msgstr "грешка машине стања"
+
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:462
+msgid "invalid AcceptMessage"
+msgstr "неисправна „Порука прихвата“"
+
+#: logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:499
+msgid "invalid RejectMessage"
+msgstr "неисправна „Порука одбијања“"
+
+#: logsrvd/logsrvd.c:530 logsrvd/logsrvd.c:531
+msgid "invalid ExitMessage"
+msgstr "неисправна „Порука излаза“"
+
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:585
+msgid "invalid RestartMessage"
+msgstr "неисправна „Порука поновног покретања“"
+
+#: logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:620
+msgid "invalid AlertMessage"
+msgstr "неисправна „Порука узбуне“"
+
+#: logsrvd/logsrvd.c:661 logsrvd/logsrvd.c:697 logsrvd/logsrvd.c:733
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s: неочекивана У/И међумеморија"
+
+#: logsrvd/logsrvd.c:662 logsrvd/logsrvd.c:698 logsrvd/logsrvd.c:734
+msgid "protocol error"
+msgstr "грешка протокола"
+
+#: logsrvd/logsrvd.c:668 logsrvd/logsrvd.c:669
+msgid "invalid IoBuffer"
+msgstr "неисправна УиМеђумеморија"
+
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:705
+msgid "invalid ChangeWindowSize"
+msgstr "неисправно „Промени_величину_прозора“"
+
+#: logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:741
+msgid "invalid CommandSuspend"
+msgstr "неисправна „Обустава_наредбе“"
+
+#: logsrvd/logsrvd.c:790 logsrvd/logsrvd_journal.c:301
+#: logsrvd/logsrvd_relay.c:654 logsrvd/sendlog.c:1201
+#: plugins/sudoers/log_client.c:1590
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "не могу да отпакујем „%s“ величине %zu"
+
+#: logsrvd/logsrvd.c:835 logsrvd/logsrvd_journal.c:375
+#: logsrvd/logsrvd_relay.c:678
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "неочекивана вредност врсте_слова %d у „%s“ из „%s“"
+
+#: logsrvd/logsrvd.c:837
+msgid "unrecognized ClientMessage type"
+msgstr "непозната врста „Поруке_клијента“"
+
+#: logsrvd/logsrvd.c:927
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "истекло је време писања на клијенту „%s“"
+
+#: logsrvd/logsrvd.c:932 logsrvd/logsrvd_relay.c:916 logsrvd/sendlog.c:1404
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr "недостаје међумеморија писања за клијента „%s“"
+
+#: logsrvd/logsrvd.c:1028
+#, c-format
+msgid "timed out reading from client %s"
+msgstr "истекло је време читања са клијента „%s“"
+
+#: logsrvd/logsrvd.c:1069 logsrvd/logsrvd_relay.c:779
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr "крај датотеке из „%s“ без одговарајућег ТЛС гашења"
+
+#: logsrvd/logsrvd.c:1113 logsrvd/logsrvd_relay.c:205 logsrvd/sendlog.c:331
+#: plugins/sudoers/log_client.c:723
+#, c-format
+msgid "client message too large: %zu"
+msgstr "порука клијента је превелика: %zu"
+
+#: logsrvd/logsrvd.c:1114 logsrvd/logsrvd_journal.c:259
+#: logsrvd/logsrvd_journal.c:260
+msgid "client message too large"
+msgstr "порука клијента је превелика"
+
+#: logsrvd/logsrvd.c:1132 logsrvd/logsrvd.c:1133
+msgid "invalid ClientMessage"
+msgstr "неисправна „Порука клијента“"
+
+#: logsrvd/logsrvd.c:1433
+msgid "unable to get remote IP addr"
+msgstr "не могу да добавим удаљену ИП адресу"
+
+#: logsrvd/logsrvd.c:1464 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:281
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "Не могу да прикачим податке корисника ссл објекту: %s"
+
+#: logsrvd/logsrvd.c:1647 logsrvd/logsrvd.c:2003
+msgid "unable to setup listen socket"
+msgstr "не могу да подесим прикључницу ослушкивања"
+
+#: logsrvd/logsrvd.c:1767
+#, c-format
+msgid "unexpected signal %d"
+msgstr "неочекивани сигнал %d"
+
+#: logsrvd/logsrvd.c:1905
+msgid "sudo log server"
+msgstr "сервер судо дневника"
+
+#: logsrvd/logsrvd.c:1907 logsrvd/sendlog.c:121
+msgid "Options:"
+msgstr "Опције:"
+
+#: logsrvd/logsrvd.c:1909
+msgid "path to configuration file"
+msgstr "путања до датотеке подешавања"
+
+#: logsrvd/logsrvd.c:1911 logsrvd/sendlog.c:123
+msgid "display help message and exit"
+msgstr "приказује поруку помоћи и излази"
+
+#: logsrvd/logsrvd.c:1913
+msgid "do not fork, run in the foreground"
+msgstr "не клонира, ради у првом плану"
+
+#: logsrvd/logsrvd.c:1915
+msgid "percent chance connections will drop"
+msgstr "просенат шанси за одбацивање веза"
+
+#: logsrvd/logsrvd.c:1917 logsrvd/sendlog.c:153
+msgid "display version information and exit"
+msgstr "приказује податке о издању и излази"
+
+#: logsrvd/logsrvd.c:1967 logsrvd/sendlog.c:1711
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "Потребно је „Protobuf-C“ издање 1.3 или новије"
+
+#: logsrvd/logsrvd.c:1983
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "неисправна вредност одбацивања насумичности: %s"
+
+#: logsrvd/logsrvd.c:1986 logsrvd/sendlog.c:1765
+#: plugins/sudoers/cvtsudoers.c:247 plugins/sudoers/sudoreplay.c:294
+#: plugins/sudoers/visudo.c:186
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s издање %s\n"
+
+#: logsrvd/logsrvd_conf.c:422 plugins/sudoers/check.c:358
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/sudoers.c:448 plugins/sudoers/sudoers.c:939
+#: plugins/sudoers/sudoers.c:1041 plugins/sudoers/sudoers.c:1062
+#: plugins/sudoers/sudoers.c:1555 plugins/sudoers/testsudoers.c:224
+#: plugins/sudoers/testsudoers.c:393
+#, c-format
+msgid "unknown user %s"
+msgstr "непознат корисник „%s“"
+
+#: logsrvd/logsrvd_conf.c:439 plugins/sudoers/iolog.c:148
+#: plugins/sudoers/sudoers.c:453 plugins/sudoers/sudoers.c:1589
+#: plugins/sudoers/testsudoers.c:417
+#, c-format
+msgid "unknown group %s"
+msgstr "непозната група „%s“"
+
+#: logsrvd/logsrvd_conf.c:457
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr "не могу да обрадим режим У/И дневника „%s“"
+
+#: logsrvd/logsrvd_conf.c:474 logsrvd/logsrvd_conf.c:1243
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "неисправна вредност за „%s“: %s"
+
+#: logsrvd/logsrvd_conf.c:527
+msgid "TLS not supported"
+msgstr "ТЛС није подржано"
+
+#: logsrvd/logsrvd_conf.c:549
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:622 logsrvd/logsrvd_conf.c:1032
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s: није потпуно квалификована путања"
+
+#: logsrvd/logsrvd_conf.c:951 logsrvd/logsrvd_conf.c:967
+#: logsrvd/logsrvd_conf.c:1676
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "непознато постројење системског дневика „%s“"
+
+#: logsrvd/logsrvd_conf.c:983 logsrvd/logsrvd_conf.c:999
+#: logsrvd/logsrvd_conf.c:1015 logsrvd/logsrvd_conf.c:1680
+#: logsrvd/logsrvd_conf.c:1684 logsrvd/logsrvd_conf.c:1688
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "непознат приоритет системског дневика „%s“"
+
+#: logsrvd/logsrvd_conf.c:1197
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "„%s:%d“ непоклопљена [: %s"
+
+#: logsrvd/logsrvd_conf.c:1203
+#, c-format
+msgid "%s:%d garbage after ']': %s"
+msgstr "„%s:%d“ ђубре након ]: %s"
+
+#: logsrvd/logsrvd_conf.c:1215
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "„%s:%d“ неисправан одељак подешавања: %s"
+
+#: logsrvd/logsrvd_conf.c:1223
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "„%s:%d“ неисправан ред подешавања: %s"
+
+#: logsrvd/logsrvd_conf.c:1229
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "„%s:%d“ очекиван је назив одељка: %s"
+
+#: logsrvd/logsrvd_conf.c:1251
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] неисправан кључ: %s"
+
+#: logsrvd/logsrvd_conf.c:1281 plugins/sudoers/cvtsudoers.c:269
+#: plugins/sudoers/logging.c:1046
+#, c-format
+msgid "unable to open log file %s"
+msgstr "не могу да отворим датотеку дневника „%s“"
+
+#: logsrvd/logsrvd_conf.c:1763
+msgid "unable to initialize server TLS context"
+msgstr "не могу да покренем ТЛС контекст сервера"
+
+#: logsrvd/logsrvd_conf.c:1783
+msgid "unable to initialize relay TLS context"
+msgstr "не могу да покренем ТЛС контекст преносника"
+
+#: logsrvd/logsrvd_journal.c:149 logsrvd/logsrvd_journal.c:429
+#: logsrvd/logsrvd_journal.c:434
+msgid "unable to create journal file"
+msgstr "не могу да направим датотеку дневника"
+
+#: logsrvd/logsrvd_journal.c:153 logsrvd/logsrvd_queue.c:109
+#: plugins/sudoers/visudo.c:1038
+#, c-format
+msgid "unable to lock %s"
+msgstr "не могу да закључам „%s“"
+
+#: logsrvd/logsrvd_journal.c:156
+msgid "unable to lock journal file"
+msgstr "не могу да закључам датотеку дневника"
+
+#: logsrvd/logsrvd_journal.c:164
+msgid "unable to open journal file"
+msgstr "не могу да отворим датотеку дневника"
+
+#: logsrvd/logsrvd_journal.c:185 logsrvd/logsrvd_journal.c:465
+#: logsrvd/logsrvd_journal.c:470
+msgid "unable to write journal file"
+msgstr "не могу да запишем датотеку дневника"
+
+#: logsrvd/logsrvd_journal.c:193 logsrvd/logsrvd_journal.c:200
+msgid "unable to rename journal file"
+msgstr "не могу да преименујем датотеку дневника"
+
+#: logsrvd/logsrvd_journal.c:247 logsrvd/logsrvd_journal.c:248
+#: logsrvd/logsrvd_journal.c:287 logsrvd/logsrvd_journal.c:288
+msgid "unexpected EOF reading journal file"
+msgstr "неочекивани крај датотеке читајући датотеку дневника"
+
+#: logsrvd/logsrvd_journal.c:251 logsrvd/logsrvd_journal.c:252
+#: logsrvd/logsrvd_journal.c:291 logsrvd/logsrvd_journal.c:292
+msgid "error reading journal file"
+msgstr "грешка читања датотеке дневника"
+
+#: logsrvd/logsrvd_journal.c:303 logsrvd/logsrvd_journal.c:389
+msgid "invalid journal file, unable to restart"
+msgstr "неисправна датотека дневника, не могу поново да почнем"
+
+#: logsrvd/logsrvd_journal.c:448
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "не могу да премотам на [%lld, %ld] у датотеци дневника „%s“"
+
+#: logsrvd/logsrvd_local.c:166
+#, c-format
+msgid "unexpected value_case %d in %s from %s"
+msgstr "неочекивана вредност врсте_слова %d у „%s“ из „%s“"
+
+#: logsrvd/logsrvd_local.c:194
+msgid "error parsing AcceptMessage"
+msgstr "грешка обраде „Поруке прихвата“"
+
+#: logsrvd/logsrvd_local.c:205
+msgid "error creating I/O log"
+msgstr "грешка стварања У/И дневника"
+
+#: logsrvd/logsrvd_local.c:228
+msgid "error logging accept event"
+msgstr "грешка прибележавања догађаја прихвата"
+
+#: logsrvd/logsrvd_local.c:267
+msgid "error parsing RejectMessage"
+msgstr "грешка обраде „Поруке одбијања“"
+
+#: logsrvd/logsrvd_local.c:291
+msgid "error logging reject event"
+msgstr "грешка прибележавања догађаја одбијања"
+
+#: logsrvd/logsrvd_local.c:427 logsrvd/logsrvd_local.c:435
+msgid "error logging exit event"
+msgstr "грешка прибележавања догађаја излаза"
+
+#: logsrvd/logsrvd_local.c:492 logsrvd/logsrvd_local.c:493
+msgid "log is already complete, cannot be restarted"
+msgstr "дневик је већ довршен, не може бити поново покренут"
+
+#: logsrvd/logsrvd_local.c:523
+msgid "unable to restart log"
+msgstr "не могу поново да покренем дневник"
+
+#: logsrvd/logsrvd_local.c:539
+msgid "error parsing AlertMessage"
+msgstr "грешка обраде „Поруке узбуне“"
+
+#: logsrvd/logsrvd_local.c:549
+msgid "error logging alert event"
+msgstr "грешка прибележавања догађаја упозорења"
+
+#: logsrvd/logsrvd_local.c:585 logsrvd/logsrvd_local.c:648
+#: logsrvd/logsrvd_local.c:683
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr "не могу да обликујем међумеморију временисања, трајање %d"
+
+#: logsrvd/logsrvd_local.c:599 logsrvd/logsrvd_local.c:607
+#: logsrvd/logsrvd_local.c:655 logsrvd/logsrvd_local.c:690
+#: plugins/sudoers/sudoreplay.c:344 toke.l:982 toke.l:985
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: logsrvd/logsrvd_local.c:618
+msgid "randomly dropping connection"
+msgstr "насумично одбацујем везу"
+
+#: logsrvd/logsrvd_local.c:630
+msgid "error writing IoBuffer"
+msgstr "Грешка писања „Уи_Међумеморије“"
+
+#: logsrvd/logsrvd_local.c:665
+msgid "error writing ChangeWindowSize"
+msgstr "грешка писања „Промени_величину_прозора“"
+
+#: logsrvd/logsrvd_local.c:700
+msgid "error writing CommandSuspend"
+msgstr "грешка писања „Обуставе_наредбе“"
+
+#: logsrvd/logsrvd_relay.c:437
+msgid "TLS handshake with relay host failed"
+msgstr "ТЛС руковање са домаћином преносника није успело"
+
+#: logsrvd/logsrvd_relay.c:465
+msgid "unable to connect to relay host"
+msgstr "Не могу да се повежем са домаћином преносника"
+
+#: logsrvd/logsrvd_relay.c:520
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s: неисправан поздрав сервера, недостаје иб сервера"
+
+#: logsrvd/logsrvd_relay.c:522 logsrvd/sendlog.c:1105
+#: plugins/sudoers/log_client.c:1476
+msgid "invalid ServerHello"
+msgstr "неисправан „Поздрав_сервера“"
+
+#: logsrvd/logsrvd_relay.c:681
+msgid "unrecognized ServerMessage type"
+msgstr "непозната врста „Поруке_сервера“"
+
+#: logsrvd/logsrvd_relay.c:710
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr "истекло је време читања са преносника „%s“ (%s)"
+
+#: logsrvd/logsrvd_relay.c:712
+msgid "timeout reading from relay"
+msgstr "истекло је време читања са преносника"
+
+#: logsrvd/logsrvd_relay.c:764
+msgid "relay host name does not match certificate"
+msgstr "назив домаћина преносника не одговара уверењу"
+
+#: logsrvd/logsrvd_relay.c:770 logsrvd/logsrvd_relay.c:784
+#: logsrvd/logsrvd_relay.c:791
+msgid "error reading from relay"
+msgstr "грешка читања са преносника"
+
+#: logsrvd/logsrvd_relay.c:812
+msgid "unable to read from relay"
+msgstr "не могу да читам са преносника"
+
+#: logsrvd/logsrvd_relay.c:827 logsrvd/logsrvd_relay.c:945
+msgid "relay server closed connection"
+msgstr "сервер преносника је затворио везу"
+
+#: logsrvd/logsrvd_relay.c:845
+msgid "server message too large"
+msgstr "порука сервера је превелика"
+
+#: logsrvd/logsrvd_relay.c:909
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr "истекло је време писања на преноснику „%s“ (%s)"
+
+#: logsrvd/logsrvd_relay.c:911
+msgid "timeout writing to relay"
+msgstr "истекло је време писања на преноснику"
+
+#: logsrvd/logsrvd_relay.c:964 logsrvd/logsrvd_relay.c:971
+#: logsrvd/logsrvd_relay.c:983
+msgid "error writing to relay"
+msgstr "грешка писања на преноснику"
+
+#: logsrvd/sendlog.c:119
+msgid "send sudo I/O log to remote server"
+msgstr "шаље У/И дневник судоа удаљеном серверу"
+
+#: logsrvd/sendlog.c:125
+msgid "only send an accept event (no I/O)"
+msgstr "шаље само догађај прихвата (не У/И)"
+
+#: logsrvd/sendlog.c:128
+msgid "certificate bundle file to verify server's cert against"
+msgstr "датотека скупа уверења за проверавање уверења сервера"
+
+#: logsrvd/sendlog.c:130
+msgid "certificate file for TLS handshake"
+msgstr "датотека уверења за ТЛС руковање"
+
+#: logsrvd/sendlog.c:133
+msgid "host to send logs to"
+msgstr "домаћин коме шаље дневнике"
+
+#: logsrvd/sendlog.c:135
+msgid "remote ID of I/O log to be resumed"
+msgstr "ИБ удаљеног У/И дневника који ће бити враћен"
+
+#: logsrvd/sendlog.c:138
+msgid "private key file"
+msgstr "датотека приватног кључа"
+
+#: logsrvd/sendlog.c:140
+msgid "do not verify server certificate"
+msgstr "не проверава уверење сервера"
+
+#: logsrvd/sendlog.c:143
+msgid "port to use when connecting to host"
+msgstr "прикључник за коришћење приликом повезивања на домаћина"
+
+#: logsrvd/sendlog.c:145
+msgid "restart previous I/O log transfer"
+msgstr "поново покреће претходни пренос У/И дневника"
+
+#: logsrvd/sendlog.c:147
+msgid "reject the command with the given reason"
+msgstr "одбацује наредбу са датим разлогом"
+
+#: logsrvd/sendlog.c:149
+msgid "stop transfer after reaching this time"
+msgstr "прекида пренос након достизања овог времена"
+
+#: logsrvd/sendlog.c:151
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "тестира анкетни сервер шаљући изабрани У/И дневник n пута у паралели"
+
+#: logsrvd/sendlog.c:176 plugins/sudoers/log_client.c:453
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "не могу да потражим „%s:%s“: %s"
+
+#: logsrvd/sendlog.c:214
+msgid "unable to get server IP addr"
+msgstr "не могу да добавим ИП адресу сервера"
+
+#: logsrvd/sendlog.c:309 plugins/sudoers/sudoreplay.c:868
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "не могу да прочитам „%s/%s“: %s"
+
+#: logsrvd/sendlog.c:1029 plugins/sudoers/iolog.c:948
+#: plugins/sudoers/iolog.c:1023
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "неочекивани У/И догађај „%d“"
+
+#: logsrvd/sendlog.c:1082 logsrvd/sendlog.c:1099 logsrvd/sendlog.c:1133
+#: plugins/sudoers/log_client.c:1126 plugins/sudoers/log_client.c:1402
+#: plugins/sudoers/log_client.c:1470 plugins/sudoers/log_client.c:1509
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: неочекивано стање „%d“"
+
+#: logsrvd/sendlog.c:1169 plugins/sudoers/log_client.c:1558
+#, c-format
+msgid "error message received from server: %s"
+msgstr "порука грешке је примљена са сервера: %s"
+
+#: logsrvd/sendlog.c:1182 plugins/sudoers/log_client.c:1571
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "порука прекида је примљена са сервера: %s"
+
+#: logsrvd/sendlog.c:1241 plugins/sudoers/log_client.c:1621
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s: неочекивана вредност врсте_слова „%d“"
+
+#: logsrvd/sendlog.c:1270
+msgid "timeout reading from server"
+msgstr "истекло је време читања са сервера"
+
+#: logsrvd/sendlog.c:1319 plugins/sudoers/log_client.c:1743
+msgid "host name does not match certificate"
+msgstr "назив домаћина не одговара уверењу"
+
+#: logsrvd/sendlog.c:1352
+msgid "premature EOF"
+msgstr "прерани крај датотеке"
+
+#: logsrvd/sendlog.c:1365 plugins/sudoers/log_client.c:1790
+#, c-format
+msgid "server message too large: %u"
+msgstr "порука сервера је превелика: %u"
+
+#: logsrvd/sendlog.c:1421
+msgid "timeout writing to server"
+msgstr "истекло је време писања на сервер"
+
+#: logsrvd/sendlog.c:1788
+msgid "both restart point and iolog ID must be specified"
+msgstr "мора бити наведена и тачка поновног покретања и ИБ уи_дневника"
+
+#: logsrvd/sendlog.c:1792
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "тачка поновног покретања се не може подесити када није послат У/И"
+
+#: logsrvd/sendlog.c:1868
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "изађох прерано са стањем „%d“"
+
+#: logsrvd/sendlog.c:1869
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "протекло време послато серверу [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1871
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "тачка слања примљена са сервера [%lld, %ld]"
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:315
+msgid "TLS handshake timeout occurred"
+msgstr "дошло је до временског истека ТЛС руковања"
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:337 plugins/sudoers/log_client.c:353
+msgid "unable to set event"
+msgstr "не могу да подесим догађај"
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "ТЛС веза није успела: %s"
+
+#: logsrvd/tls_client.c:196
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "не могу да доделим ссл објекат: %s"
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "Не могу да прикачим прикључницу ссл објекту: %s"
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr "не могу да покренем ТЛС контекст"
+
+#: logsrvd/tls_init.c:138 logsrvd/tls_init.c:146
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "не могу да подесим шифрарник ТЛС-а 1.2 на „%s“: %s"
+
+#: logsrvd/tls_init.c:166 logsrvd/tls_init.c:174
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "не могу да подесим шифрарник ТЛС-а 1.3 на „%s“: %s"
+
+#: logsrvd/tls_init.c:206 logsrvd/tls_init.c:227
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "не могу да подесим „diffie-hellman“ параметре: %s"
+
+#: logsrvd/tls_init.c:283
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "Не могу да створим ТЛС контекст: %s"
+
+#: logsrvd/tls_init.c:290
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "не могу да подесим најмање издање протокола на „TLS 1.2“: %s"
+
+#: plugins/sudoers/audit.c:268 plugins/sudoers/audit.c:428
+#: plugins/sudoers/log_client.c:959 plugins/sudoers/log_client.c:1008
+#: plugins/sudoers/log_client.c:1057 plugins/sudoers/log_client.c:1182
+#: plugins/sudoers/logging.c:595 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:833 plugins/sudoers/logging.c:1000
+#: plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr "не могу да добавим време дана"
+
+#: plugins/sudoers/auth/aix_auth.c:280
+#, c-format
+msgid "unable to change password for %s"
+msgstr "не могу да изменим лозинку за „%s“"
+
+#: plugins/sudoers/auth/bsdauth.c:77
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "не могу да добавим разред пријаве за корисника „%s“"
+
+#: plugins/sudoers/auth/bsdauth.c:84
+msgid "invalid authentication type"
+msgstr "неисправна врста потврђивање идентитета"
+
+#: plugins/sudoers/auth/bsdauth.c:89
+msgid "unable to begin BSD authentication"
+msgstr "не могу да почнем BSD потврђивање идентитета"
+
+#: plugins/sudoers/auth/bsdauth.c:96
+msgid "unable to initialize BSD authentication"
+msgstr "не могу да покренем БСД потврђивање идентитета"
+
+#: plugins/sudoers/auth/bsdauth.c:188
+msgid "your account has expired"
+msgstr "ваш налог је истекао"
+
+#: plugins/sudoers/auth/bsdauth.c:190
+msgid "approval failed"
+msgstr "доказивање није успело"
+
+#: plugins/sudoers/auth/fwtk.c:61
+msgid "unable to read fwtk config"
+msgstr "не могу да читам „fwtk“ подешавања"
+
+#: plugins/sudoers/auth/fwtk.c:66
+msgid "unable to connect to authentication server"
+msgstr "не могу да се повежем на сервер потврђивања идентитета"
+
+#: plugins/sudoers/auth/fwtk.c:72 plugins/sudoers/auth/fwtk.c:97
+#: plugins/sudoers/auth/fwtk.c:129
+msgid "lost connection to authentication server"
+msgstr "изгубио сам везу са сервером потврђивања идентитета"
+
+#: plugins/sudoers/auth/fwtk.c:76
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"грешка сервера потврђивања идентитета:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:115
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: не могу да претворим главника у ниску („%s“): %s"
+
+#: plugins/sudoers/auth/kerb5.c:164
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: не могу да обрадим „%s“: %s"
+
+#: plugins/sudoers/auth/kerb5.c:173
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: не могу да решим оставу пуномоћства: %s"
+
+#: plugins/sudoers/auth/kerb5.c:222
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: не могу да доделим опције: %s"
+
+#: plugins/sudoers/auth/kerb5.c:237
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: не могу да добавим пуномоћства: %s"
+
+#: plugins/sudoers/auth/kerb5.c:250
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: не могу да покренем оставу пуномоћства: %s"
+
+#: plugins/sudoers/auth/kerb5.c:253
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: не могу да сместим пуномоћства у оставу: %s"
+
+#: plugins/sudoers/auth/kerb5.c:317
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: не могу да добавим главника домаћина: %s"
+
+#: plugins/sudoers/auth/kerb5.c:331
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: Не могу потврдити ТГТ! Могући напад!: %s"
+
+#: plugins/sudoers/auth/pam.c:224
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "не могу да покренем ПАМ: %s"
+
+#: plugins/sudoers/auth/pam.c:337
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Грешка ПАМ потврђивања идентитета: %s"
+
+#: plugins/sudoers/auth/pam.c:356
+msgid "account validation failure, is your account locked?"
+msgstr "неуспех провере налога, да ли је ваш налог закључан?"
+
+#: plugins/sudoers/auth/pam.c:367
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Налог или лозинка је истекла, поново поставите лозинку и покушајте поново"
+
+#: plugins/sudoers/auth/pam.c:373
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "не могу да изменим истеклу лозинку: %s"
+
+#: plugins/sudoers/auth/pam.c:384
+msgid "Password expired, contact your system administrator"
+msgstr "Лозинка је истекла, обратите се администратору система"
+
+#: plugins/sudoers/auth/pam.c:389
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Налог је истекао или ПАМ подешавањима недостаје одељак „налог“ за судо, обратите се администратору система"
+
+#: plugins/sudoers/auth/pam.c:397 plugins/sudoers/auth/pam.c:402
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "грешка управљања ПАМ налогом: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:99 plugins/sudoers/visudo.c:271
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "ви не постојите у бази подтака „%s“"
+
+#: plugins/sudoers/auth/securid5.c:75
+msgid "failed to initialise the ACE API library"
+msgstr "нисам успео да покренем АЦЕ АПИ библиотеку"
+
+#: plugins/sudoers/auth/securid5.c:106
+msgid "unable to contact the SecurID server"
+msgstr "не могу да ступим у везу са сервером безбеднног ИБ-а"
+
+#: plugins/sudoers/auth/securid5.c:115
+msgid "User ID locked for SecurID Authentication"
+msgstr "ИБ корисника је закључан за потврђивање идентитета безбедног ИБ-а"
+
+#: plugins/sudoers/auth/securid5.c:119 plugins/sudoers/auth/securid5.c:171
+msgid "invalid username length for SecurID"
+msgstr "неисправна дужина корисничког имена за безбедни ИБ"
+
+#: plugins/sudoers/auth/securid5.c:123 plugins/sudoers/auth/securid5.c:176
+msgid "invalid Authentication Handle for SecurID"
+msgstr "неисправна ручка потврђивања идентитета за безбедни ИБ"
+
+#: plugins/sudoers/auth/securid5.c:127
+msgid "SecurID communication failed"
+msgstr "Није успело комуницирање безбедног ИБ-а"
+
+#: plugins/sudoers/auth/securid5.c:131 plugins/sudoers/auth/securid5.c:219
+msgid "unknown SecurID error"
+msgstr "непозната грешка безбедног ИБ-а"
+
+#: plugins/sudoers/auth/securid5.c:166
+msgid "invalid passcode length for SecurID"
+msgstr "неисправна дужина пропусне шифре за безбедни ИБ"
+
+#: plugins/sudoers/auth/sia.c:69 plugins/sudoers/auth/sia.c:126
+msgid "unable to initialize SIA session"
+msgstr "не могу да покренем СИА сесију"
+
+#: plugins/sudoers/auth/sudo_auth.c:135
+msgid "invalid authentication methods"
+msgstr "неисправни начини потврђивања идентитета"
+
+#: plugins/sudoers/auth/sudo_auth.c:137
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Неисправни начини потврђивања идентитета су преведени у судоу! Не можете мешати самостално и несамостално потврђивање идентитета."
+
+#: plugins/sudoers/auth/sudo_auth.c:258 plugins/sudoers/auth/sudo_auth.c:310
+msgid "no authentication methods"
+msgstr "нема начина потврђивања идентитета"
+
+#: plugins/sudoers/auth/sudo_auth.c:260
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Нема начина потврђивања идентитета преведених у судоу! Ако желите да искључите потврђивање идентитета, користите „--disable-authentication“."
+
+#: plugins/sudoers/auth/sudo_auth.c:312
+msgid "Unable to initialize authentication methods."
+msgstr "Не могу да покренем методе потврђивања идентитета."
+
+#: plugins/sudoers/auth/sudo_auth.c:486
+msgid "Authentication methods:"
+msgstr "Начини потврђивања идентитета:"
+
+#: plugins/sudoers/bsm_audit.c:123 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "Не могу да утврдим услов прегледа"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:277
+msgid "unable to commit audit record"
+msgstr "не могу да предам снимак прегледа"
+
+#: plugins/sudoers/check.c:285
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "грешка читања датотеке обучавања „%s“"
+
+#: plugins/sudoers/check.c:288
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "занемарујем датотеку обучавања „%s“: није обична датотека"
+
+#: plugins/sudoers/check.c:301
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Верујемо да вам је администратор система објаснио неке ствари.\n"
+"Обично се своде на следеће три:\n"
+"\n"
+" #1) Поштујте приватност других.\n"
+" #2) Размислите пре куцања.\n"
+" #3) Са великом моћи долази и велика одговорност.\n"
+"\n"
+
+#: plugins/sudoers/check.c:309
+msgid ""
+"For security reasons, the password you type will not be visible.\n"
+"\n"
+msgstr ""
+"Из безбедносних разлога, лозинка коју упишете неће бити видљива.\n"
+"\n"
+
+#: plugins/sudoers/check.c:353 plugins/sudoers/check.c:363
+#: plugins/sudoers/parse.c:80 plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "непознат јиб %u"
+
+#: plugins/sudoers/check_aliases.c:99 plugins/sudoers/defaults.c:1278
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s: %s\n"
+
+#: plugins/sudoers/check_aliases.c:133
+#, c-format
+msgid "cycle in %s \"%s\""
+msgstr "циклус у „%s“ „%s“"
+
+#: plugins/sudoers/check_aliases.c:136
+#, c-format
+msgid "%s \"%s\" referenced but not defined"
+msgstr "упута за „%s“ „%s“ постоји али није дефинисана"
+
+#: plugins/sudoers/cvtsudoers.c:210
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "повећање поретка: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:229
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "поредак почетка: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:239
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "попуњавање поретка: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:249 plugins/sudoers/visudo.c:188
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s граматика издање %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:278 plugins/sudoers/testsudoers.c:163
+#, c-format
+msgid "unsupported input format %s"
+msgstr "неподржан запис улаза „%s“"
+
+#: plugins/sudoers/cvtsudoers.c:296
+#, c-format
+msgid "unsupported output format %s"
+msgstr "неподржан запис излаза „%s“"
+
+#: plugins/sudoers/cvtsudoers.c:386
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: улазна датотека треба да се разликује од излазне"
+
+#: plugins/sudoers/cvtsudoers.c:400 plugins/sudoers/sudoers.c:163
+#: plugins/sudoers/sudoers.c:221 plugins/sudoers/testsudoers.c:263
+#: plugins/sudoers/visudo.c:280 plugins/sudoers/visudo.c:657
+msgid "unable to initialize sudoers default values"
+msgstr "не могу да покренем основне вредности судоерса"
+
+#: plugins/sudoers/cvtsudoers.c:526 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:605
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s: непозната реч кључа „%s“"
+
+#: plugins/sudoers/cvtsudoers.c:651
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "неисправна врста основности: %s"
+
+#: plugins/sudoers/cvtsudoers.c:674
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "неисправна врста потискивања: %s"
+
+#: plugins/sudoers/cvtsudoers.c:715 plugins/sudoers/cvtsudoers.c:731
+#, c-format
+msgid "invalid filter: %s"
+msgstr "неисправан филтер: %s"
+
+#: plugins/sudoers/cvtsudoers.c:775 plugins/sudoers/visudo.c:992
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "нисам успео да обрадим %s датотеку, непозната грешка"
+
+#: plugins/sudoers/cvtsudoers.c:1499 plugins/sudoers/sudoreplay.c:1142
+#: plugins/sudoers/timestamp.c:368 plugins/sudoers/timestamp.c:371
+#, c-format
+msgid "unable to write to %s"
+msgstr "не могу да пишем у „%s“"
+
+#: plugins/sudoers/cvtsudoers.c:1527
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s – претвара међусобно записе датотеке судоерса\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1529
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Опције:\n"
+" -b, --base=нд основни НД за „sudo LDAP“ пропитивања\n"
+" -c, --config=дат_под путања до датотеке подешавања\n"
+" -d, --defaults=врсте_осн претвара само основности наведених врста\n"
+" -e, --expand-aliases шири алијасе приликом претварања\n"
+" -f, --output-format=запис поставља запис излаза: „JSON“, „LDIF“ или „sudoers“\n"
+" -i, --input-format=запис поставља запис улаза: „LDIF“ или „sudoers“\n"
+" -I, --increment=бр. износ за повећање сваког „sudoOrder“-а\n"
+" -h, --help приказује поруку помоћи и излази\n"
+" -m, --match=филтер претвара само уносе који одговарају филтеру\n"
+" -M, --match-local упоређује филтерско коришћење базе података лозинке и групе\n"
+" -o, --output=дат_изл пише претворене судоерсе у датотеку_излаза\n"
+" -O, --order-start=бр. почетна тачка за првог „sudoOrder“-а\n"
+" -p, --prune-matches избацује неодговарајуће кориснике, групе и домаћине\n"
+" -P, --padding=бр. попуњавање осниове за „sudoOrder“ повећање\n"
+" -s, --suppress=одељци потискује излаз неких одељака\n"
+" -V, --version приказује податке о издању и излази"
+
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:244 plugins/sudoers/cvtsudoers_ldif.c:251
+#: plugins/sudoers/cvtsudoers_ldif.c:592 plugins/sudoers/env.c:340
+#: plugins/sudoers/env.c:347 plugins/sudoers/env.c:458
+#: plugins/sudoers/ldap.c:509 plugins/sudoers/ldap.c:626
+#: plugins/sudoers/ldap.c:999 plugins/sudoers/ldap_conf.c:219
+#: plugins/sudoers/ldap_conf.c:310 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:92 plugins/sudoers/logging.c:461
+#: plugins/sudoers/policy.c:824 plugins/sudoers/policy.c:835
+#: plugins/sudoers/prompt.c:168 plugins/sudoers/serialize_list.c:62
+#: plugins/sudoers/serialize_list.c:71 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/sudoreplay.c:1339 plugins/sudoers/sudoreplay.c:1345
+#: plugins/sudoers/sudoreplay.c:1351 plugins/sudoers/testsudoers.c:254
+#: plugins/sudoers/toke_util.c:213 toke.l:996 toke.l:1259
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "унутрашња грешка, прекорачење „%s“"
+
+#: plugins/sudoers/cvtsudoers_csv.c:454 plugins/sudoers/cvtsudoers_csv.c:468
+#: plugins/sudoers/cvtsudoers_json.c:661 plugins/sudoers/cvtsudoers_json.c:676
+#: plugins/sudoers/cvtsudoers_ldif.c:347 plugins/sudoers/cvtsudoers_ldif.c:360
+#: plugins/sudoers/ldap.c:493
+msgid "unable to get GMT time"
+msgstr "не могу да добавим ГМТ време"
+
+#: plugins/sudoers/cvtsudoers_csv.c:459 plugins/sudoers/cvtsudoers_csv.c:473
+#: plugins/sudoers/cvtsudoers_json.c:666 plugins/sudoers/cvtsudoers_json.c:681
+#: plugins/sudoers/cvtsudoers_ldif.c:352 plugins/sudoers/cvtsudoers_ldif.c:365
+#: plugins/sudoers/ldap.c:501
+msgid "unable to format timestamp"
+msgstr "не могу да обликујем временску ознаку"
+
+#: plugins/sudoers/cvtsudoers_json.c:481 plugins/sudoers/cvtsudoers_json.c:516
+#: plugins/sudoers/cvtsudoers_json.c:732
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: непознат унос основности „%s“"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:661
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "превише уноса судоерса, највише %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:704
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "променљива „SUDOERS_BASE“ окружења није постављена и „-b“ опција није наведена."
+
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, c-format
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr "%s:%d:%d: претварам списак домаћина у „ALL“"
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr "не могу да нађем алијас „%s“"
+
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, c-format
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr "%s:%d:%d: преименујем алијаса „%s“ у „%s“"
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr "%s:%d:%d: уклањам двоструког алијаса „%s“"
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr "%s:%d:%d: сукобљавајући унос основности „%s“ домаћину специфичан у „%s:%d:%d“"
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, c-format
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr "%s:%d:%d: правим основности „%s“ специфичне домаћину „%s“"
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr "%s:%d:%d: не могу да учиним основности „%s“ домаћину специфичне"
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr "%s:%d:%d: уклањам основности „%s“ преписане следећим уносима"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1088
+#, c-format
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr "%s:%d:%d: стапам корисничку спецификацију у „%s:%d:%d“"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1182
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr "%s:%d:%d: уклањам корисничку специфичност преписану следећим уносима"
+
+#: plugins/sudoers/def_data.c:56
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Помоћник сисдневника ако је сисдневник коришћен за пријављивање: %s"
+
+#: plugins/sudoers/def_data.c:60
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Приоритет системског дневника за коришћење када корисник успешно потврди идентитет: %s"
+
+#: plugins/sudoers/def_data.c:64
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Приоритет системског дневника за коришћење када корисник неуспешно потврди идентитет: %s"
+
+#: plugins/sudoers/def_data.c:68
+msgid "Put OTP prompt on its own line"
+msgstr "Поставља ОТП упит на свом реду"
+
+#: plugins/sudoers/def_data.c:72
+msgid "Ignore '.' in $PATH"
+msgstr "Занемарује . у $ПУТАЊИ"
+
+#: plugins/sudoers/def_data.c:76
+msgid "Always send mail when sudo is run"
+msgstr "Увек шаље пошту када је судо покренут"
+
+#: plugins/sudoers/def_data.c:80
+msgid "Send mail if user authentication fails"
+msgstr "Пошаљи поруку ако потврђивање идентитета корисника не успе"
+
+#: plugins/sudoers/def_data.c:84
+msgid "Send mail if the user is not in sudoers"
+msgstr "Пошаљи поруку ако корисник није у судоерсу"
+
+#: plugins/sudoers/def_data.c:88
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Пошаљи поруку ако корисник није у судоерсу за овог домаћина"
+
+#: plugins/sudoers/def_data.c:92
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Пошаљи поруку ако кориснику није дозвољено да покрене наредбу"
+
+#: plugins/sudoers/def_data.c:96
+msgid "Send mail if the user tries to run a command"
+msgstr "Пошаљи поруку ако корисник покуша да покрене наредбу"
+
+#: plugins/sudoers/def_data.c:100
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Користи одвојене временске ознаке за сваку комбинацију корисник/конзола"
+
+#: plugins/sudoers/def_data.c:104
+msgid "Lecture user the first time they run sudo"
+msgstr "Подучава корисника када први пут покрену судо"
+
+#: plugins/sudoers/def_data.c:108
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Датотека садржи судо обучавања: %s"
+
+#: plugins/sudoers/def_data.c:112
+msgid "Require users to authenticate by default"
+msgstr "Захтева да корисници потврде идентитет по основи"
+
+#: plugins/sudoers/def_data.c:116
+msgid "Root may run sudo"
+msgstr "Администратор може да покрене судо"
+
+#: plugins/sudoers/def_data.c:120
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Бележи назив домаћина у (не-сисдневник) датотеци дневника"
+
+#: plugins/sudoers/def_data.c:124
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Бележи годину у (не-сисдневник) датотеци дневника"
+
+#: plugins/sudoers/def_data.c:128
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Ако је судо призван без аргумената, покреће шкољку"
+
+#: plugins/sudoers/def_data.c:132
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Подешава $HOME на крајњег корисника када покреће шкољку са „-s“"
+
+#: plugins/sudoers/def_data.c:136
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Увек подешава $HOME на циљни лични директоријум корисника"
+
+#: plugins/sudoers/def_data.c:140
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Дозвољава прикупљање неких података да би дао корисне поруке грешака"
+
+#: plugins/sudoers/def_data.c:144
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Захтева потпуно одређене називе домаћина у датотеци судоерса"
+
+#: plugins/sudoers/def_data.c:148
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Вређа корисника када унесе нетачну лозинку"
+
+#: plugins/sudoers/def_data.c:152
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Дозвољава кориснику да покрене судо само ако има конзолу"
+
+#: plugins/sudoers/def_data.c:156
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Висудо ће поштовати променљиву окружења УРЕЂИВАЧА"
+
+#: plugins/sudoers/def_data.c:160
+msgid "Prompt for root's password, not the users's"
+msgstr "Тражи администраторову лозинку, а не корисника"
+
+#: plugins/sudoers/def_data.c:164
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Тражи корисникову лозинку покреникао_основни, а не корисника"
+
+#: plugins/sudoers/def_data.c:168
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Тражи корисникову лозинку мете, а не корисника"
+
+#: plugins/sudoers/def_data.c:172
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Примењује основности у циљни кориснички разред пријављивања ако постоји"
+
+#: plugins/sudoers/def_data.c:176
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Подешава променљиве окружења НАЗИВДНЕВНИКА и КОРИСНИК"
+
+#: plugins/sudoers/def_data.c:180
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Подешава само ефективни јиб на крајњег корисника, а не стваран јиб"
+
+#: plugins/sudoers/def_data.c:184
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Не покреће вектор групе ка оном крајњег корисника"
+
+#: plugins/sudoers/def_data.c:188
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Дужина за преламање редова у датотеци дневника (0 — без преламања): %u"
+
+#: plugins/sudoers/def_data.c:192
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Време истека временске ознаке потврђивања идентитета: %.1f минута"
+
+#: plugins/sudoers/def_data.c:196
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Време истека упита лозинке: %.1f минута"
+
+#: plugins/sudoers/def_data.c:200
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Број покушаја за уношење лозинке: %u"
+
+#: plugins/sudoers/def_data.c:204
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Умаска за коришћење или 0777 за коришћење корисника: 0%o"
+
+#: plugins/sudoers/def_data.c:208
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Путања до датотеке дневника: %s"
+
+#: plugins/sudoers/def_data.c:212
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Путања до програма поште: %s"
+
+#: plugins/sudoers/def_data.c:216
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Опције за програм поште: %s"
+
+#: plugins/sudoers/def_data.c:220
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Адреса на коју послати поруку: %s"
+
+#: plugins/sudoers/def_data.c:224
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Адреса са које послати поруку: %s"
+
+#: plugins/sudoers/def_data.c:228
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Ред теме за поруке поште: %s"
+
+#: plugins/sudoers/def_data.c:232
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Порука нетачне лозинке: %s"
+
+#: plugins/sudoers/def_data.c:236
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Путања до директоријума стања обучавања: %s"
+
+#: plugins/sudoers/def_data.c:240
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Путања до директоријума временске ознаке потврђивања идентитета: %s"
+
+#: plugins/sudoers/def_data.c:244
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Власник директоријума временске ознаке потврђивања идентитета: %s"
+
+#: plugins/sudoers/def_data.c:248
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Корисницима у овој групи се не захтева лозинка и ПУТАЊА: %s"
+
+#: plugins/sudoers/def_data.c:252
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Основни упит лозинке: %s"
+
+#: plugins/sudoers/def_data.c:256
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Ако је подешено, упит лозинке ће преписати системски упит у свим случајевима."
+
+#: plugins/sudoers/def_data.c:260
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Основни корисник за покретање наредби као: %s"
+
+#: plugins/sudoers/def_data.c:264
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Вредност за преписивање корисничке $ПУТАЊЕ са: %s"
+
+#: plugins/sudoers/def_data.c:268
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Путања до уређивача кога ће да користи висудо: %s"
+
+#: plugins/sudoers/def_data.c:272
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Када да затражи лозинку за псеудонаредбу „list“: %s"
+
+#: plugins/sudoers/def_data.c:276
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Када да затражи лозинку за псеудонаредбу „verify“: %s"
+
+#: plugins/sudoers/def_data.c:280
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "Унапред учитава „sudo_noexec“ библиотеку која мења функцију извршавања"
+
+#: plugins/sudoers/def_data.c:284
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Ако је ЛДАП директоријум изнет, да ли занемарујемо месну датотеку судоерса"
+
+#: plugins/sudoers/def_data.c:288
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Описници датотека >= %d ће бити затворени пре извршавања наредбе"
+
+#: plugins/sudoers/def_data.c:292
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "Ако је подешено, корисници могу да препишу вредност „closefrom“ са опцијом „-C“"
+
+#: plugins/sudoers/def_data.c:296
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Дозвољава корисницима да подесе произвољне променљиве окружења"
+
+#: plugins/sudoers/def_data.c:300
+msgid "Reset the environment to a default set of variables"
+msgstr "Враћа окружење на основни скуп променљивих"
+
+#: plugins/sudoers/def_data.c:304
+msgid "Environment variables to check for safety:"
+msgstr "Променљиве окружења за проверу исправности:"
+
+#: plugins/sudoers/def_data.c:308
+msgid "Environment variables to remove:"
+msgstr "Променљиве окружења за уклањање:"
+
+#: plugins/sudoers/def_data.c:312
+msgid "Environment variables to preserve:"
+msgstr "Променљиве окружења за очување:"
+
+#: plugins/sudoers/def_data.c:316
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "СЕЛинукс улога за употребу у новом контексту безбедности: %s"
+
+#: plugins/sudoers/def_data.c:320
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "СЕЛинукс врста за употребу у новом контексту безбедности: %s"
+
+#: plugins/sudoers/def_data.c:324
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Путања до судо-посебне датотеке окружења: %s"
+
+#: plugins/sudoers/def_data.c:328
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Путања до ограничене судо-посебне датотеке окружења: %s"
+
+#: plugins/sudoers/def_data.c:332
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Језк за коришћење при обради судоерса: %s"
+
+#: plugins/sudoers/def_data.c:336
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Дозвољава да судо тражи лозинку чак и ако би била видљива"
+
+#: plugins/sudoers/def_data.c:340
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Обезбеђује видну повратну поруку при тражењу лозинке када постоји унос корисника"
+
+#: plugins/sudoers/def_data.c:344
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Користи брже упоређивање које је мање тачно али не приступа систему датотека"
+
+#: plugins/sudoers/def_data.c:348
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "Умаска наведена у судоерсима ће преписати корисникову, чак и ако има већа овлашћења"
+
+#: plugins/sudoers/def_data.c:352
+msgid "Log user's input for the command being run"
+msgstr "Бележи корисников улаз за покренуту наредбу"
+
+#: plugins/sudoers/def_data.c:356
+msgid "Log the command's standard input if not connected to a terminal"
+msgstr "Записује у дневник стандардни улаз наредбе ако није повезан на терминал"
+
+#: plugins/sudoers/def_data.c:360
+msgid "Log the user's terminal input for the command being run"
+msgstr "Записује у дневник корисников улаз терминала за покренуту наредбу"
+
+#: plugins/sudoers/def_data.c:364
+msgid "Log the output of the command being run"
+msgstr "Бележи излаз покренуте наредбе"
+
+#: plugins/sudoers/def_data.c:368
+msgid "Log the command's standard output if not connected to a terminal"
+msgstr "Записује у дневник стандардни излаз наредбе ако није повезан на терминал"
+
+#: plugins/sudoers/def_data.c:372
+msgid "Log the command's standard error if not connected to a terminal"
+msgstr "Записује у дневник стандардну грешку наредбе ако није повезан на терминал"
+
+#: plugins/sudoers/def_data.c:376
+msgid "Log the terminal output of the command being run"
+msgstr "Записује у дневник излаз терминала покренуте наредбе"
+
+#: plugins/sudoers/def_data.c:380
+msgid "Compress I/O logs using zlib"
+msgstr "Пакује У/И дневнике користећи злиб"
+
+#: plugins/sudoers/def_data.c:384
+msgid "Always run commands in a pseudo-tty"
+msgstr "Увек покреће наредбе у привидној конзоли"
+
+#: plugins/sudoers/def_data.c:388
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Прикључак за подршку не-Јуникс групе: %s"
+
+#: plugins/sudoers/def_data.c:392
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Директоријум за смештај улазних/излазних дневника: %s"
+
+#: plugins/sudoers/def_data.c:396
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Датотека за смештај улазно/излазног дневника: %s"
+
+#: plugins/sudoers/def_data.c:400
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Додаје унос у датотеку „utmp/utmpx“ када додељује „pty“"
+
+#: plugins/sudoers/def_data.c:404
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Подешава корисника у „utmp“-у на корисника покрени-као, не призивајући корисника"
+
+#: plugins/sudoers/def_data.c:408
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Скуп допуштених повластица: %s"
+
+#: plugins/sudoers/def_data.c:412
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Скуп повластица ограничења: %s"
+
+#: plugins/sudoers/def_data.c:416
+msgid "Run commands on a pty in the background"
+msgstr "Покреће наредбе у позадини на назовитерминалу"
+
+#: plugins/sudoers/def_data.c:420
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "Назив ПАМ услуге за коришћење: %s"
+
+#: plugins/sudoers/def_data.c:424
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "Назив ПАМ услуге за шкољке пријављивања: %s"
+
+#: plugins/sudoers/def_data.c:428
+#, c-format
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr "Назив ПАМ услуге за коришћење када судо ради са опцијом „-A“: %s"
+
+#: plugins/sudoers/def_data.c:432
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Покушава да успостави ПАМ пуномоћства за циљног корисника"
+
+#: plugins/sudoers/def_data.c:436
+msgid "Create a new PAM session for the command to run in"
+msgstr "Прави нову ПАМ сесију за покретање наредбе"
+
+#: plugins/sudoers/def_data.c:440
+msgid "Perform PAM account validation management"
+msgstr "Обавља управљање провером ПАМ налога"
+
+#: plugins/sudoers/def_data.c:444
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "Највећи број низа У/И дневника: %s"
+
+#: plugins/sudoers/def_data.c:448
+msgid "Enable sudoers netgroup support"
+msgstr "Укључује подршку нетгрупе судоерса"
+
+#: plugins/sudoers/def_data.c:452
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Проверава родитељски директоријум за уписивошћу када уређује датотеке са „sudoedit“"
+
+#: plugins/sudoers/def_data.c:456
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Прати симболичке везе када уређује датотеке са „sudoedit“"
+
+#: plugins/sudoers/def_data.c:460
+msgid "Query the group plugin for unknown system groups"
+msgstr "Пропитује прикључак групе за непознатим групама система"
+
+#: plugins/sudoers/def_data.c:464
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Упоређује мрежне групе на основу читавог слога: корисник, домаћин и домен"
+
+#: plugins/sudoers/def_data.c:468
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Допушта покретање наредби чак и ако судо не може да пише у дневник прегледа"
+
+#: plugins/sudoers/def_data.c:472
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Допушта покретање наредби чак и ако судо не може да пише у дневник У/И"
+
+#: plugins/sudoers/def_data.c:476
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Допушта покретање наредби чак и ако судо не може да пише у датотеку дневника"
+
+#: plugins/sudoers/def_data.c:480
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Решава групе у судоерсима и упоређује ИД групе, а не назив"
+
+#: plugins/sudoers/def_data.c:484
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Уноси дневника већи од ове вредности биће подељени на више порука системског дневника: %u"
+
+#: plugins/sudoers/def_data.c:488
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Корисник који ће поседовати датотеке дневника У/И: %s"
+
+#: plugins/sudoers/def_data.c:492
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Група која ће поседовати датотеке дневника У/И: %s"
+
+#: plugins/sudoers/def_data.c:496
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Режим датотеке за коришћење за датотеке дневника У/И: 0%o"
+
+#: plugins/sudoers/def_data.c:500
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Извршава наредбе описником датотеке уместо путањом: %s"
+
+#: plugins/sudoers/def_data.c:504
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Занемарује непознате уносе основности у судоерсу уместо да даје упозорење"
+
+#: plugins/sudoers/def_data.c:508
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Време у секундама након ког ће наредба бити окончана: %u"
+
+#: plugins/sudoers/def_data.c:512
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Допушта кориснику да наведе време на линији наредби"
+
+#: plugins/sudoers/def_data.c:516
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Пребацује У/И податке дневника на диск одмах уместо да га смешта у међумеморију"
+
+#: plugins/sudoers/def_data.c:520
+msgid "Include the process ID when logging via syslog"
+msgstr "Укључује ИБ процеса приликом пријављивања путем дневника система"
+
+#: plugins/sudoers/def_data.c:524
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Врста временске ознаке потврђивања идентитета: %s"
+
+#: plugins/sudoers/def_data.c:528
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Потврђивање идентитета није успело: %s"
+
+#: plugins/sudoers/def_data.c:532
+msgid "Ignore case when matching user names"
+msgstr "Занемарује величину слова приликом поклапања назива корисника"
+
+#: plugins/sudoers/def_data.c:536
+msgid "Ignore case when matching group names"
+msgstr "Занемарује величину слова приликом поклапања назива групе"
+
+#: plugins/sudoers/def_data.c:540
+msgid "Log when a command is allowed by sudoers"
+msgstr "Пише дневник када судоерси дозвољавају наредбу"
+
+#: plugins/sudoers/def_data.c:544
+msgid "Log when a command is denied by sudoers"
+msgstr "Пише дневник када судоерси не дозвољавају наредбу"
+
+#: plugins/sudoers/def_data.c:548
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "Судо сервер(и) дневника за повезивање са изборним прикључником"
+
+#: plugins/sudoers/def_data.c:552
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Време истека судо сервера дневника у секундама: %u"
+
+#: plugins/sudoers/def_data.c:556
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "Укључује „SO_KEEPALIVE“ опцију прикључнице са повезаном прикључницом са сервером дневника"
+
+#: plugins/sudoers/def_data.c:560
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "Путања до датотеке групних издавача уверења сервера испитивања: %s"
+
+#: plugins/sudoers/def_data.c:564
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "Путања до датотеке уверења судоерса: %s"
+
+#: plugins/sudoers/def_data.c:568
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "Путања до датотеке датотеке личног кључа судоерса: %s"
+
+#: plugins/sudoers/def_data.c:572
+msgid "Verify that the log server's certificate is valid"
+msgstr "Потврђује да је исправно уверење дневника сервера"
+
+#: plugins/sudoers/def_data.c:576
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "Допушта коришћење непознатог „runas“ корисника и/или ИБ-а групе"
+
+#: plugins/sudoers/def_data.c:580
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "Допушта покретање наредби као корисник само са исправном шкољком"
+
+#: plugins/sudoers/def_data.c:584
+msgid "Set the pam remote user to the user running sudo"
+msgstr "Поставља пам удаљеног корисника на корисника покретача судо-а"
+
+#: plugins/sudoers/def_data.c:588
+msgid "Set the pam remote host to the local host name"
+msgstr "Поставља пам удаљеног домаћина на назив локалног домаћина"
+
+#: plugins/sudoers/def_data.c:592
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "Радни директоријум за прелазак пре извршавања наредбе: %s"
+
+#: plugins/sudoers/def_data.c:596
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "Корени директоријум за прелазак пре извршавања наредбе: %s"
+
+#: plugins/sudoers/def_data.c:600
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "Формат резултирајућих дневника: %s"
+
+#: plugins/sudoers/def_data.c:604
+msgid "Enable SELinux RBAC support"
+msgstr "Укључује СЕЛинукс РБАЦ подршку"
+
+#: plugins/sudoers/def_data.c:608
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "Путања до датотеке која је створена приликом првог покретања судоа: %s"
+
+#: plugins/sudoers/def_data.c:612
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "Пресреће будуће наредбе и примењује „sudoers“ ограничења на њима"
+
+#: plugins/sudoers/def_data.c:616
+msgid "Log sub-commands run by the original command"
+msgstr "Бележи поднаредбе које покрене изворна наредба"
+
+#: plugins/sudoers/def_data.c:620
+msgid "Log the exit status of commands"
+msgstr "Бележи стање излаза наредбе"
+
+#: plugins/sudoers/def_data.c:624
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr "Наредне наредбе у пресретнутој сесији морају бити аутентификоване"
+
+#: plugins/sudoers/def_data.c:628
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr "Омогућава пресретнутој наредби да покрене поставку „setuid“ или „setgid“ програма"
+
+#: plugins/sudoers/def_data.c:632
+#, c-format
+msgid "The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr "Највећа величина до које може да нарасте адресни простор процеса (у бајтовима): %s"
+
+#: plugins/sudoers/def_data.c:636
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr "Највећа величина избачаја датотеке језгра која се може направити (у бајтовима): %s"
+
+#: plugins/sudoers/def_data.c:640
+#, c-format
+msgid "The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr "Највећа количина времена процесора које процес може да користи (у секундама): %s"
+
+#: plugins/sudoers/def_data.c:644
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr "Највећа величина сегмента података за процес (у бајтовима): %s"
+
+#: plugins/sudoers/def_data.c:648
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr "Највећа величина датотеке коју процес може да направи (у бајтовима): %s"
+
+#: plugins/sudoers/def_data.c:652
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr "Највећи број закључавања која процес може да успостави: %s"
+
+#: plugins/sudoers/def_data.c:656
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr "Највећа величина коју процес може да закључа у меморији (у бајтовима): %s"
+
+#: plugins/sudoers/def_data.c:660
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr "Највећи број датотека које процес може да отвори: %s"
+
+#: plugins/sudoers/def_data.c:664
+#, c-format
+msgid "The maximum number of processes that the user may run simultaneously: %s"
+msgstr "Највећи број процеса које корисник може да покрене истовремено: %s"
+
+#: plugins/sudoers/def_data.c:668
+#, c-format
+msgid "The maximum size to which the process's resident set size may grow (in bytes): %s"
+msgstr "Највећа величина до које може да нарасте резидентна величина скупа процеса (у бајтовима): %s"
+
+#: plugins/sudoers/def_data.c:672
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr "Највећа величина до које може да нарасте спремник процеса (у бајтовима): %s"
+
+#: plugins/sudoers/def_data.c:676
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr "Покушава потврђивање идентитета чак и када није у не-међудејственом режиму"
+
+#: plugins/sudoers/def_data.c:680
+msgid "Store plaintext passwords in I/O log input"
+msgstr "Смешта обично-текстуалне лозинке у У/И улаз дневника"
+
+#: plugins/sudoers/def_data.c:684
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr "Списак регуларних израза за коришћење приликом поређења упита лозинке"
+
+#: plugins/sudoers/def_data.c:688
+#, c-format
+msgid "The mechanism used by the intercept and log_subcmds options: %s"
+msgstr "Механизам који користе опције „intercept“ и „log_subcmds“: %s"
+
+#: plugins/sudoers/def_data.c:692
+msgid "Attempt to verify the command and arguments after execution"
+msgstr "Покушава да провери наредбу и аргументе након извршавања"
+
+#: plugins/sudoers/def_data.c:696
+#, c-format
+msgid "AppArmor profile to use in the new security context: %s"
+msgstr "АпАрмор профил за коришћење у новом контексту безбедности: %s"
+
+#: plugins/sudoers/defaults.c:191
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "непознат унос основности „%s“"
+
+#: plugins/sudoers/defaults.c:234
+#, c-format
+msgid "no value specified for \"%s\""
+msgstr "није наведена вредност за „%s“"
+
+#: plugins/sudoers/defaults.c:243
+#, c-format
+msgid "invalid operator \"%c=\" for \"%s\""
+msgstr "неисправан оператор „%c=“ за „%s“"
+
+#: plugins/sudoers/defaults.c:275
+#, c-format
+msgid "option \"%s\" does not take a value"
+msgstr "опција „%s“ не узима вредност"
+
+#: plugins/sudoers/defaults.c:299
+#, c-format
+msgid "invalid Defaults type 0x%x for option \"%s\""
+msgstr "неисправна врста основности 0x%x за опцију „%s“"
+
+#: plugins/sudoers/defaults.c:306
+#, c-format
+msgid "value \"%s\" is invalid for option \"%s\""
+msgstr "вредност „%s“ је неисправна за опцију „%s“"
+
+#: plugins/sudoers/defaults.c:1127 plugins/sudoers/policy.c:205
+#: plugins/sudoers/policy.c:214
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr "назив путање за „%s“ је предуг"
+
+#: plugins/sudoers/defaults.c:1133
+#, c-format
+msgid "values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "вредност за „%s“ мора да почиње са /, ~ или *"
+
+#: plugins/sudoers/defaults.c:1140
+#, c-format
+msgid "values for \"%s\" must start with a '/'"
+msgstr "вредност за „%s“ мора да почне /"
+
+#: plugins/sudoers/editor.c:180
+#, c-format
+msgid "ignoring editor: %.*s"
+msgstr "занемарујем уређивача: %.*s"
+
+#: plugins/sudoers/editor.c:181
+msgid "editor arguments may not contain \"--\""
+msgstr "аргументи уређивача не могу да садрже „--“"
+
+#: plugins/sudoers/env.c:426
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: оштећено стави окружење, дужине не одговарају"
+
+#: plugins/sudoers/env.c:1113
+msgid "unable to rebuild the environment"
+msgstr "не могу поново да изградим окружење"
+
+#: plugins/sudoers/env.c:1192
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "извините, није вам дозвољено да подесите следеће променљиве окружења: %s"
+
+#: plugins/sudoers/filedigest.c:50
+#, c-format
+msgid "unsupported digest type %u for %s"
+msgstr "неподржана врста сажетка поруке „%u“ за „%s“"
+
+#: plugins/sudoers/filedigest.c:79
+#, c-format
+msgid "%s: read error"
+msgstr "%s: грешка читања"
+
+#: plugins/sudoers/group_plugin.c:169 plugins/sudoers/sssd.c:576
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "не могу да учитам %s: %s"
+
+#: plugins/sudoers/group_plugin.c:181
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "не могу да нађем симбол „group_plugin“ у „%s“"
+
+#: plugins/sudoers/group_plugin.c:186
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: несагласно веће издање прикључка групе %d, очекивано је %d"
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "не могу да обрадим ИП адресу „%s“"
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "не могу да обрадим мрежну маску „%s“"
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Месна ИП адреса и парови мрежне маске:\n"
+
+#: plugins/sudoers/iolog.c:684
+msgid "unable to update sequence file"
+msgstr "не могу да освежим датотеку низа"
+
+#: plugins/sudoers/iolog.c:718 plugins/sudoers/iolog.c:906
+#: plugins/sudoers/iolog.c:1068 plugins/sudoers/iolog.c:1075
+#: plugins/sudoers/iolog.c:1196 plugins/sudoers/iolog.c:1203
+#: plugins/sudoers/iolog.c:1302 plugins/sudoers/iolog.c:1309
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "не могу да пишем у датотеку дневника У/И: %s"
+
+#: plugins/sudoers/iolog.c:726
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "не могу да направим „%s/%s“"
+
+#: plugins/sudoers/iolog.c:954
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: унутрашња грешка, датотека У/И дневника за догађај %d није отворена"
+
+#: plugins/sudoers/iolog.c:1053 plugins/sudoers/iolog.c:1181
+#: plugins/sudoers/iolog.c:1286 plugins/sudoers/timestamp.c:904
+#: plugins/sudoers/timestamp.c:996 plugins/sudoers/visudo.c:559
+#: plugins/sudoers/visudo.c:565
+msgid "unable to read the clock"
+msgstr "не могу да прочитам сат"
+
+#: plugins/sudoers/iolog.c:1278 plugins/sudoers/log_client.c:1200
+#: plugins/sudoers/log_client.c:1210 plugins/sudoers/log_client.c:1214
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: унутрашња грешка, неисправан сигнал %d"
+
+#: plugins/sudoers/ldap.c:154 plugins/sudoers/ldap_conf.c:289
+msgid "starttls not supported when using ldaps"
+msgstr "старттлс није подржано када се користи лдапс"
+
+#: plugins/sudoers/ldap.c:225
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "не могу да покренем ССЛ уверење и бп кључа: %s"
+
+#: plugins/sudoers/ldap.c:228
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "морате да подесите „TLS_CERT“ у „%s“ да користите ССЛ"
+
+#: plugins/sudoers/ldap.c:1587
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "не могу да покренем ЛДАП: %s"
+
+#: plugins/sudoers/ldap.c:1624
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "„start_tls“ је наведено али ЛДАП библиотеке не подржавају „ldap_start_tls_s()“ или „ldap_start_tls_s_np()“"
+
+#: plugins/sudoers/ldap.c:1761 plugins/sudoers/parse_ldif.c:748
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "неисправна особина „sudoOrder“: %s"
+
+#: plugins/sudoers/ldap_conf.c:197
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: прикључник је превелик"
+
+#: plugins/sudoers/ldap_conf.c:258
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "неподржана врста ЛДАП путање: %s"
+
+#: plugins/sudoers/ldap_conf.c:285
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "не могу да помешам лдап и лдапс путање"
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "двострука судо опција: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "не могу да претворим „sudoOption“: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "не могу да отворим систем прегледа"
+
+#: plugins/sudoers/linux_audit.c:103
+msgid "unable to send audit message"
+msgstr "не могу да пошаљем поруку прегледа"
+
+#: plugins/sudoers/log_client.c:125 plugins/sudoers/log_client.c:412
+#: plugins/sudoers/log_client.c:1447 plugins/sudoers/log_client.c:2069
+msgid "error in event loop"
+msgstr "грешка у петљи догађаја"
+
+#: plugins/sudoers/log_client.c:205
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "Стварање новог „SSL_CTX“ објекта није успело: %s"
+
+#: plugins/sudoers/log_client.c:230
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "не могу да учитам комплет ауторитета уверења „%s“"
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "не могу да учитам уверење „%s“"
+
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "unable to load private key %s"
+msgstr "не могу да учитам лични кључ „%s“"
+
+#: plugins/sudoers/log_client.c:275
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "Не могу да доделим ссл објекат: %s"
+
+#: plugins/sudoers/log_client.c:364 plugins/sudoers/log_client.c:369
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "ТЛС повезивање са „%s:%s“ није успело: %s"
+
+#: plugins/sudoers/log_client.c:545
+msgid "TLS initialization was unsuccessful"
+msgstr "ТЛС покретање беше безуспешно"
+
+#: plugins/sudoers/log_client.c:555
+msgid "TLS handshake was unsuccessful"
+msgstr "ТЛС руковање беше безуспешно"
+
+#: plugins/sudoers/log_client.c:1218
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: унутрашња грешка, неисправно излазно стање %d"
+
+#: plugins/sudoers/log_client.c:1753 plugins/sudoers/log_client.c:1777
+msgid "lost connection to log server"
+msgstr "изгубих везу са сервером дневника"
+
+#: plugins/sudoers/log_client.c:1854
+msgid "missing write buffer"
+msgstr "недостаје међумеморија писања"
+
+#: plugins/sudoers/log_client.c:2008
+msgid "unable to connect to log server"
+msgstr "не могу да се повежем на сервер дневника"
+
+#: plugins/sudoers/logging.c:290
+msgid "user NOT in sudoers"
+msgstr "корисник НИЈЕ у судоерсу"
+
+#: plugins/sudoers/logging.c:292
+msgid "user NOT authorized on host"
+msgstr "корисник НИЈЕ овлашћен на домаћину"
+
+#: plugins/sudoers/logging.c:294
+msgid "command not allowed"
+msgstr "наредба није допуштена"
+
+#: plugins/sudoers/logging.c:315
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr "„%s“ није у датотеци судоерса.\n"
+
+#: plugins/sudoers/logging.c:318
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr "Кориснику „%s“ није допуштено да покрене судо на „%s“.\n"
+
+#: plugins/sudoers/logging.c:321
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Извините, корисник %s не може покренути судо на %s.\n"
+
+#: plugins/sudoers/logging.c:324
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s%s' as %s%s%s on %s.\n"
+msgstr "Извините, кориснику %s није дозвољено да изврши „%s%s%s%s“ као %s%s%s на %s.\n"
+
+#: plugins/sudoers/logging.c:334
+msgid "This incident has been reported to the administrator.\n"
+msgstr "Овај инцидент је пријављен администратору.\n"
+
+#: plugins/sudoers/logging.c:369 plugins/sudoers/sudoers.c:566
+#: plugins/sudoers/sudoers.c:567 plugins/sudoers/sudoers.c:569
+#: plugins/sudoers/sudoers.c:570 plugins/sudoers/sudoers.c:791
+#: plugins/sudoers/sudoers.c:793
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: нема такве наредбе"
+
+#: plugins/sudoers/logging.c:371 plugins/sudoers/sudoers.c:562
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"занемарујем „%s“ пронађено у „.“\n"
+"Користите „sudo ./%s“ ако је то „%s“ које желите да покренете."
+
+#: plugins/sudoers/logging.c:391
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u покушај нетачне лозинке"
+msgstr[1] "%u покушаја нетачне лозинке"
+msgstr[2] "%u покушаја нетачне лозинке"
+
+#: plugins/sudoers/logging.c:481
+msgid "authentication failure"
+msgstr "потврђивање идентитета није успело"
+
+#: plugins/sudoers/logging.c:520 plugins/sudoers/logging.c:539
+msgid "a password is required"
+msgstr "потребна је лозинка"
+
+#: plugins/sudoers/logging.c:855
+msgid "problem parsing sudoers"
+msgstr "проблем обраде судоерса"
+
+#: plugins/sudoers/logging.c:896 plugins/sudoers/logging.c:904
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr "%s:%d:%d: %s"
+
+#: plugins/sudoers/logging.c:1079
+#, c-format
+msgid "unable to write log file: %s"
+msgstr "не могу да запишем датотеку дневника: %s"
+
+#: plugins/sudoers/match_digest.c:101
+#, c-format
+msgid "digest for %s (%s) bad length %zu, expected %zu"
+msgstr "приказ за „%s“ (%s) је лоше дужине %zu, очекивах %zu"
+
+#: plugins/sudoers/match_digest.c:120
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "приказ за %s (%s) није у %s облику"
+
+#: plugins/sudoers/parse.c:643
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+"\n"
+"ЛДАП улога: %s\n"
+
+#: plugins/sudoers/parse.c:646
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+"\n"
+"Унос судоерса:\n"
+
+#: plugins/sudoers/parse.c:648
+msgid " RunAsUsers: "
+msgstr " „Покрени-као“ корисници: "
+
+#: plugins/sudoers/parse.c:663
+msgid " RunAsGroups: "
+msgstr " „Покрени-као“ групе: "
+
+#: plugins/sudoers/parse.c:673
+msgid " Options: "
+msgstr " Опције: "
+
+#: plugins/sudoers/parse.c:737
+msgid " Commands:\n"
+msgstr " Наредбе:\n"
+
+#: plugins/sudoers/parse.c:928
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Упоређује уносе основности за „%s“ на %s:\n"
+
+#: plugins/sudoers/parse.c:946
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Покрени-као и Наредбено-посебне основности за „%s“:\n"
+
+#: plugins/sudoers/parse.c:964
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "Корисник „%s“ може да покреће следеће наредбе на %s:\n"
+
+#: plugins/sudoers/parse.c:979
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Корисник „%s“ нема права да покрене судо над „%s“.\n"
+
+#: plugins/sudoers/parse_ldif.c:618
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "занемарујем непотпуно „sudoRole“: cn: %s"
+
+#: plugins/sudoers/parse_ldif.c:678
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "неисправна особина „LDIF“: %s"
+
+#: plugins/sudoers/pivot.c:74
+msgid "unable to restore root directory"
+msgstr "не могу да повратим корени директоријум"
+
+#: plugins/sudoers/pivot.c:82
+msgid "unable to restore current working directory"
+msgstr "не могу да повратим тренутни радни директоријум"
+
+#: plugins/sudoers/policy.c:80 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "судо челник је поставио неисправну „%.*s“"
+
+#: plugins/sudoers/policy.c:356 plugins/sudoers/testsudoers.c:277
+msgid "unable to parse network address list"
+msgstr "не могу да обрадим списак адреса мреже"
+
+#: plugins/sudoers/policy.c:524
+msgid "user name not set by sudo front-end"
+msgstr "судо челник није поставио име корисника"
+
+#: plugins/sudoers/policy.c:528
+msgid "user-ID not set by sudo front-end"
+msgstr "судо челник није поставио ИБ корисника"
+
+#: plugins/sudoers/policy.c:532
+msgid "group-ID not set by sudo front-end"
+msgstr "судо челник није поставио ИБ групе"
+
+#: plugins/sudoers/policy.c:536
+msgid "host name not set by sudo front-end"
+msgstr "судо челник није поставио назив домаћина"
+
+#: plugins/sudoers/policy.c:754
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "неисправан радни директоријум: %s"
+
+#: plugins/sudoers/policy.c:938
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "неисправан „chroot“ директоријум: %s"
+
+#: plugins/sudoers/policy.c:1125 plugins/sudoers/visudo.c:910
+#: plugins/sudoers/visudo.c:1209
+#, c-format
+msgid "unable to execute %s"
+msgstr "не могу да извршим „%s“"
+
+#: plugins/sudoers/policy.c:1195 plugins/sudoers/policy.c:1230
+#: plugins/sudoers/policy.c:1252 plugins/sudoers/policy.c:1274
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: неисправне заставице од судо челника: 0×%x"
+
+#: plugins/sudoers/policy.c:1294
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Издање %s прикључка политике судоерса\n"
+
+#: plugins/sudoers/policy.c:1296
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Граматика датотеке судоерса издање %d\n"
+
+#: plugins/sudoers/policy.c:1300
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Путања судоерса: %s\n"
+
+#: plugins/sudoers/policy.c:1303
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "путања нс-прекидача: %s\n"
+
+#: plugins/sudoers/policy.c:1305
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "путања лдап.подешавања: %s\n"
+
+#: plugins/sudoers/policy.c:1306
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "путања лдап.тајне: %s\n"
+
+#: plugins/sudoers/policy.c:1339
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "немогу да региструјем прикачку врсте „%d“ (издање %d.%d)"
+
+#: plugins/sudoers/policy.c:1357
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "немогу да поништим регистровање прикачке врсте „%d“ (издање %d.%d)"
+
+#: plugins/sudoers/pwutil.c:222 plugins/sudoers/pwutil.c:240
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "не могу да сместим у оставу јиб „%u“"
+
+#: plugins/sudoers/pwutil.c:234
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "не могу да сместим у оставу јиб „%u“, већ постоји"
+
+#: plugins/sudoers/pwutil.c:294 plugins/sudoers/pwutil.c:312
+#: plugins/sudoers/pwutil.c:375 plugins/sudoers/pwutil.c:420
+#, c-format
+msgid "unable to cache user %s"
+msgstr "не могу да сместим у оставу корисника „%s“"
+
+#: plugins/sudoers/pwutil.c:307
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "не могу да сместим у оставу корисника „%s“, већ постоји"
+
+#: plugins/sudoers/pwutil.c:539 plugins/sudoers/pwutil.c:557
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "не могу да сместим у оставу гиб „%u“"
+
+#: plugins/sudoers/pwutil.c:551
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "не могу да сместим у оставу гиб „%u“, већ постоји"
+
+#: plugins/sudoers/pwutil.c:605 plugins/sudoers/pwutil.c:623
+#: plugins/sudoers/pwutil.c:684 plugins/sudoers/pwutil.c:733
+#, c-format
+msgid "unable to cache group %s"
+msgstr "не могу да сместим у оставу групу „%s“"
+
+#: plugins/sudoers/pwutil.c:618
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "не могу да сместим у оставу групу „%s“, већ постоји"
+
+#: plugins/sudoers/pwutil.c:880 plugins/sudoers/pwutil.c:963
+#: plugins/sudoers/pwutil.c:1017 plugins/sudoers/pwutil.c:1071
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "не могу да сместим у оставу списак групе за „%s“, већ постоји"
+
+#: plugins/sudoers/pwutil.c:886 plugins/sudoers/pwutil.c:968
+#: plugins/sudoers/pwutil.c:1023 plugins/sudoers/pwutil.c:1076
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "не могу да сместим у оставу списак групе за „%s“"
+
+#: plugins/sudoers/pwutil.c:957
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "не могу да обрадим групе за „%s“"
+
+#: plugins/sudoers/pwutil.c:1065
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "не могу да обрадим гид-ове за „%s“"
+
+#: plugins/sudoers/set_perms.c:115 plugins/sudoers/set_perms.c:451
+#: plugins/sudoers/set_perms.c:863 plugins/sudoers/set_perms.c:1178
+#: plugins/sudoers/set_perms.c:1481
+msgid "perm stack overflow"
+msgstr "стално прекорачење спремника"
+
+#: plugins/sudoers/set_perms.c:126 plugins/sudoers/set_perms.c:382
+#: plugins/sudoers/set_perms.c:462 plugins/sudoers/set_perms.c:730
+#: plugins/sudoers/set_perms.c:874 plugins/sudoers/set_perms.c:1102
+#: plugins/sudoers/set_perms.c:1189 plugins/sudoers/set_perms.c:1414
+#: plugins/sudoers/set_perms.c:1492 plugins/sudoers/set_perms.c:1583
+msgid "perm stack underflow"
+msgstr "стално поткорачење спремника"
+
+#: plugins/sudoers/set_perms.c:186 plugins/sudoers/set_perms.c:509
+#: plugins/sudoers/set_perms.c:1243 plugins/sudoers/set_perms.c:1526
+msgid "unable to change to root gid"
+msgstr "не могу да пређем на гиб администратора"
+
+#: plugins/sudoers/set_perms.c:277 plugins/sudoers/set_perms.c:606
+#: plugins/sudoers/set_perms.c:1006 plugins/sudoers/set_perms.c:1320
+msgid "unable to change to runas gid"
+msgstr "не могу да пређем на гиб покреникао"
+
+#: plugins/sudoers/set_perms.c:282 plugins/sudoers/set_perms.c:611
+#: plugins/sudoers/set_perms.c:1011 plugins/sudoers/set_perms.c:1325
+msgid "unable to set runas group vector"
+msgstr "не могу да подесим вектор „покрени-као група“"
+
+#: plugins/sudoers/set_perms.c:293 plugins/sudoers/set_perms.c:622
+#: plugins/sudoers/set_perms.c:1020 plugins/sudoers/set_perms.c:1334
+msgid "unable to change to runas uid"
+msgstr "не могу да пређем на јиб покреникао"
+
+#: plugins/sudoers/set_perms.c:315 plugins/sudoers/set_perms.c:644
+#: plugins/sudoers/set_perms.c:1040 plugins/sudoers/set_perms.c:1354
+msgid "unable to change to sudoers gid"
+msgstr "не могу да пређем на гиб судоерса"
+
+#: plugins/sudoers/set_perms.c:369 plugins/sudoers/set_perms.c:717
+#: plugins/sudoers/set_perms.c:1089 plugins/sudoers/set_perms.c:1401
+#: plugins/sudoers/set_perms.c:1570
+msgid "too many processes"
+msgstr "превише процеса"
+
+#: plugins/sudoers/solaris_audit.c:61
+msgid "unable to get current working directory"
+msgstr "не могу да добавим тренутни радни директоријум"
+
+#: plugins/sudoers/solaris_audit.c:69
+#, c-format
+msgid "truncated audit path user_cmnd: %s"
+msgstr "корисничка_наредба скраћене путање прегледа: %s"
+
+#: plugins/sudoers/solaris_audit.c:76
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "„argv[0]“ скраћене путање прегледа: %s"
+
+#: plugins/sudoers/sssd.c:579
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "не могу да покренем ССС извор. Да ли је СССД инсталиран на вашем рачунару?"
+
+#: plugins/sudoers/sssd.c:587 plugins/sudoers/sssd.c:596
+#: plugins/sudoers/sssd.c:605 plugins/sudoers/sssd.c:614
+#: plugins/sudoers/sssd.c:623
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "не могу да нађем симбол „%s“ у „%s“"
+
+#: plugins/sudoers/sudoers.c:261
+#, c-format
+msgid "unable to get defaults from %s"
+msgstr "не могу да добавим основности за „%s“"
+
+#: plugins/sudoers/sudoers.c:268
+msgid "no valid sudoers sources found, quitting"
+msgstr "нисам пронашао исправне изворе судоерса, прекидам"
+
+#: plugins/sudoers/sudoers.c:344
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "кориснику није дозвољено да промени корени директоријум у „%s“"
+
+#: plugins/sudoers/sudoers.c:346
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "није вам допуштено да користите опцију „-R“ са „%s“"
+
+#: plugins/sudoers/sudoers.c:371
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "кориснику није дозвољено да промени директоријум у „%s“"
+
+#: plugins/sudoers/sudoers.c:372
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "није вам допуштено да користите опцију „-D“ са „%s“"
+
+#: plugins/sudoers/sudoers.c:412
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "судоерси наводе да администратор није дозвољен у судоу"
+
+#: plugins/sudoers/sudoers.c:421
+msgid "user not allowed to override closefrom limit"
+msgstr "кориснику није дозвољено да препише „closefrom“ ограничење"
+
+#: plugins/sudoers/sudoers.c:422
+msgid "you are not permitted to use the -C option"
+msgstr "није вам допуштено да користите опцију „-C“"
+
+#: plugins/sudoers/sudoers.c:468
+msgid "no tty"
+msgstr "нема конзоле"
+
+#: plugins/sudoers/sudoers.c:469
+msgid "sorry, you must have a tty to run sudo"
+msgstr "извините, морате имати конзолу да покренете судо"
+
+#: plugins/sudoers/sudoers.c:477
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "неисправна шкољка за корисника „%s“: %s"
+
+#: plugins/sudoers/sudoers.c:561
+msgid "command in current directory"
+msgstr "наредба у текућем директоријуму"
+
+#: plugins/sudoers/sudoers.c:574
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr "„cd“ је уграђена наредба шкољке, не може бити покренута директно."
+
+#: plugins/sudoers/sudoers.c:576
+msgid "the -s option may be used to run a privileged shell."
+msgstr "опција „-s“ се може користити за покретање привилеговане шкољке."
+
+#: plugins/sudoers/sudoers.c:578
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr "опција „-D“ се може користити за покретање наредбе у специфичном директоријуму."
+
+#: plugins/sudoers/sudoers.c:587
+msgid "user not allowed to set a command timeout"
+msgstr "кориснику није дозвољено да подеси време истека наредбе"
+
+#: plugins/sudoers/sudoers.c:589
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "извините, није вам дозвољено да подесите време истека наредбе"
+
+#: plugins/sudoers/sudoers.c:597
+msgid "user not allowed to preserve the environment"
+msgstr "кориснику није дозвољено да сачува окружење"
+
+#: plugins/sudoers/sudoers.c:599
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "извините, није вам дозвољено да сачувате окружење"
+
+#: plugins/sudoers/sudoers.c:635
+msgid "no command specified"
+msgstr "није наведена наредба"
+
+#: plugins/sudoers/sudoers.c:774
+msgid "error setting user-specified environment variables"
+msgstr "грешка постављања променљивих окружења које је навео корисник"
+
+#: plugins/sudoers/sudoers.c:1239
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "„sudoedit“ не треба да се покреће путем „sudo“-а"
+
+#: plugins/sudoers/sudoers.c:1314 plugins/sudoers/sudoreplay.c:1612
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "не могу да прочитам „%s“"
+
+#: plugins/sudoers/sudoers.c:1337 plugins/sudoers/visudo.c:1114
+#, c-format
+msgid "%s is not a regular file"
+msgstr "„%s“ није обична датотека"
+
+#: plugins/sudoers/sudoers.c:1341 plugins/sudoers/timestamp.c:288 toke.l:1325
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s је у власништву уиб-а %u, а треба бити %u"
+
+#: plugins/sudoers/sudoers.c:1345 plugins/sudoers/timestamp.c:295 toke.l:1330
+#, c-format
+msgid "%s is world writable"
+msgstr "Сви могу да пишу у „%s“"
+
+#: plugins/sudoers/sudoers.c:1349 plugins/sudoers/timestamp.c:300 toke.l:1333
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s је у власништву уиб-а %u, а треба бити %u"
+
+#: plugins/sudoers/sudoers.c:1377
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "само администратор може да користи „-c %s“"
+
+#: plugins/sudoers/sudoers.c:1396
+#, c-format
+msgid "unknown login class %s"
+msgstr "непознат разред пријављивања „%s“"
+
+#: plugins/sudoers/sudoers.c:1483 plugins/sudoers/sudoers.c:1498
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "не могу да решим домаћина „%s“"
+
+#: plugins/sudoers/sudoers.c:1636
+#, c-format
+msgid "%s:%d:%d timestampowner: unknown user %s"
+msgstr "%s:%d:%d: власник_временске_ознаке: непознат корисник „%s“"
+
+#: plugins/sudoers/sudoreplay.c:252
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "неисправна опција пропусника: %s"
+
+#: plugins/sudoers/sudoreplay.c:268
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "неисправно најдуже чекање: %s"
+
+#: plugins/sudoers/sudoreplay.c:291
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "неисправан чинилац брзине: %s"
+
+#: plugins/sudoers/sudoreplay.c:326
+#, c-format
+msgid "invalid time offset %s"
+msgstr "неисправан временски помак „%s“"
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:340
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/временисање: %s"
+
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Понављам сесију судоа: %s"
+
+#: plugins/sudoers/sudoreplay.c:634
+msgid "unable to set tty to raw mode"
+msgstr "не могу да подесим конзолу на сирови режим"
+
+#: plugins/sudoers/sudoreplay.c:685
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr "Упозорење: ваш терминал је премали да би исправно приказао дневник.\n"
+
+#: plugins/sudoers/sudoreplay.c:686
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Геометрија дневника је %d x %d, а геометрија терминала је %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:714
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Одговор је завршен, притисните неки тастер да повратите терминал."
+
+#: plugins/sudoers/sudoreplay.c:1216 plugins/sudoers/sudoreplay.c:1246
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "нејасан израз „%s“"
+
+#: plugins/sudoers/sudoreplay.c:1268
+msgid "unmatched ')' in expression"
+msgstr "непоклопљена ) у изразу"
+
+#: plugins/sudoers/sudoreplay.c:1272
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "непознат појам претраге „%s“"
+
+#: plugins/sudoers/sudoreplay.c:1287
+#, c-format
+msgid "%s requires an argument"
+msgstr "„%s“ захтева аргумент"
+
+#: plugins/sudoers/sudoreplay.c:1297
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "не могу да обрадим датум „%s“"
+
+#: plugins/sudoers/sudoreplay.c:1306
+msgid "unmatched '(' in expression"
+msgstr "непоклопљена ( у изразу"
+
+#: plugins/sudoers/sudoreplay.c:1308
+msgid "illegal trailing \"or\""
+msgstr "недозвољено пратеће „или“"
+
+#: plugins/sudoers/sudoreplay.c:1310
+msgid "illegal trailing \"!\""
+msgstr "недозвољени пратећи „!“"
+
+#: plugins/sudoers/sudoreplay.c:1416
+#, c-format
+msgid "unknown search type %d"
+msgstr "непозната врста претраге „%d“"
+
+#: plugins/sudoers/sudoreplay.c:1678
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "употреба: %s [-hnRS] [-d дир] [-m број] [-s број] ИБ\n"
+
+#: plugins/sudoers/sudoreplay.c:1680
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "употреба: %s [-h] [-d дир] -l [израз претраге]\n"
+
+#: plugins/sudoers/sudoreplay.c:1694
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s — понавља дневнике сесије судоа\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1696
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Опције:\n"
+" -d, --directory=дир наводи директоријум за дневнике сесије\n"
+" -f, --filter=пропусник наводи У/И врсту(е) за приказивање\n"
+" -h, --help приказује поруку помоћи и излази\n"
+" -l, --list исписује доступне ИБ-ове сесије, са изборним изразом\n"
+" -m, --max-wait=број највећи број секунди за чекање између догађаја\n"
+" -n, --non-interactive без упита, сесија се шаље на стандардни излаз\n"
+" -R, --no-resize не покушава да промени величину терминала\n"
+" -S, --suspend-wait чека док се не обустави наредба\n"
+" -s, --speed=број убрзава или успорава излаз\n"
+" -V, --version приказује податке о издању и излази"
+
+#: plugins/sudoers/testsudoers.c:355
+msgid "\thost unmatched"
+msgstr "\tдомаћин није поклопљен"
+
+#: plugins/sudoers/testsudoers.c:358
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Наредба је допуштена"
+
+#: plugins/sudoers/testsudoers.c:359
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Наредба је одбијена"
+
+#: plugins/sudoers/testsudoers.c:359
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Наредба није поклопљена"
+
+#: plugins/sudoers/timestamp.c:379 plugins/sudoers/timestamp.c:718
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "не могу да скратим датотеку временске ознаке на %lld бајта"
+
+#: plugins/sudoers/timestamp.c:915
+msgid "ignoring time stamp from the future"
+msgstr "занемарујем временску ознаку из будућности"
+
+#: plugins/sudoers/timestamp.c:938
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "временска ознака је превише у будућности: %20.20s"
+
+#: plugins/sudoers/timestamp.c:1067
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "не могу да закључам датотеку временске ознаке „%s“"
+
+#: plugins/sudoers/toke_util.c:156
+msgid "sudoedit should not be specified with a path"
+msgstr "„sudoedit“ не треба да се наводи са путањом"
+
+#: plugins/sudoers/visudo.c:314 plugins/sudoers/visudo.c:705
+#, c-format
+msgid "press return to edit %s: "
+msgstr "притисните „унеси“ да уредите „%s“: "
+
+#: plugins/sudoers/visudo.c:329
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "садржај сесије уређивања је остао у „%s“"
+
+#: plugins/sudoers/visudo.c:406
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "наведени уређивач (%s) не постоји"
+
+#: plugins/sudoers/visudo.c:411
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "нисам пронашао уређивача (путања уређивача = %s)"
+
+#: plugins/sudoers/visudo.c:498 plugins/sudoers/visudo.c:777
+#, c-format
+msgid "unable to stat %s"
+msgstr "не могу да добијем податке о „%s“"
+
+#: plugins/sudoers/visudo.c:518 plugins/sudoers/visudo.c:526
+msgid "write error"
+msgstr "грешка писања"
+
+#: plugins/sudoers/visudo.c:572
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "не могу да добавим податке привремене датотеке (%s), %s је неизмењено"
+
+#: plugins/sudoers/visudo.c:579
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "привремена датотека нулте дужине (%s), %s је неизмењено"
+
+#: plugins/sudoers/visudo.c:585
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "уређивач (%s) није успео, %s је неизмењено"
+
+#: plugins/sudoers/visudo.c:607
+#, c-format
+msgid "%s unchanged"
+msgstr "„%s“ је неизмењено"
+
+#: plugins/sudoers/visudo.c:652
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "не могу поново да отворим привремену датотеку (%s), %s је неизмењено."
+
+#: plugins/sudoers/visudo.c:665
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "не могу да обрадим привремену датотеку (%s), непозната грешка"
+
+#: plugins/sudoers/visudo.c:751 plugins/sudoers/visudo.c:781
+#: plugins/sudoers/visudo.c:788
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "не могу да подесим (јиб, гиб) за %s на (%u, %u)"
+
+#: plugins/sudoers/visudo.c:816
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "„%s“ и „%s“ нису на истом систему датотека, користим „mv“ за преименовање"
+
+#: plugins/sudoers/visudo.c:827
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "наредба није успела: „%s %s %s“, %s је неизмењено"
+
+#: plugins/sudoers/visudo.c:834
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "грешка преименовања „%s“, %s је неизмењено"
+
+#: plugins/sudoers/visudo.c:855
+msgid "What now? "
+msgstr "Шта сада? "
+
+#: plugins/sudoers/visudo.c:869
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Опције су:\n"
+" e — опет уређује датотеку судоерса\n"
+" x — излази без чувања измена у датотеци судоерса\n"
+" Q — прекида и чува измене у датотеци судоерса (ОПАСНО!)\n"
+
+#: plugins/sudoers/visudo.c:915
+#, c-format
+msgid "unable to run %s"
+msgstr "не могу да покренем %s"
+
+#: plugins/sudoers/visudo.c:946
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: погрешан власник (јиб, гиб) треба бити (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:957
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: лоша овлашћења, требају бити у режиму 0%o\n"
+
+#: plugins/sudoers/visudo.c:1009 plugins/sudoers/visudo.c:1016
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: успешно је обрађено\n"
+
+#: plugins/sudoers/visudo.c:1035
+#, c-format
+msgid "%s busy, try again later"
+msgstr "„%s“ је заузет, покушајте касније"
+
+#: plugins/sudoers/visudo.c:1039
+msgid "Edit anyway? [y/N]"
+msgstr "Да ипак уреим? [д/Н]"
+
+#: plugins/sudoers/visudo.c:1197
+msgid "the -x option will be removed in a future release"
+msgstr "опција „-x“ биће уклоњена у наредном издању"
+
+#: plugins/sudoers/visudo.c:1199
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "размотрите коришћење помагала „cvtsudoers“"
+
+#: plugins/sudoers/visudo.c:1219
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "Упозорење: %s:%d:%d: некоришћено „%s“ „%s“"
+
+#: plugins/sudoers/visudo.c:1332
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s — безбедно уређује датотеку судоерса\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1334
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -I, --no-includes do not edit include files\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Опције:\n"
+" -c, --check режим само провере\n"
+" -f, --file=судоерс наводи место датотеке судоерса\n"
+" -h, --help приказује поруку помоћи и излази\n"
+" -I, --no-includes не уређује датотеке укључења\n"
+" -q, --quiet мање опширне (тихе) поруке грешке синтаксе\n"
+" -s, --strict строга провера синтаксе\n"
+" -V, --version приказује податке о издању и излази\n"
+
+#: toke.l:184
+msgid "empty string"
+msgstr "празна ниска"
+
+#: toke.l:196 toke.l:566
+msgid "empty group"
+msgstr "празна група"
+
+#: toke.l:206 toke.l:564
+msgid "empty netgroup"
+msgstr "празна мрежна група"
+
+#: toke.l:284
+msgid "unterminated regular expression"
+msgstr "неокончан регуларни израз"
+
+#: toke.l:358 toke.l:370 toke.l:382 toke.l:398 toke.l:417 toke.l:457
+msgid "invalid line continuation"
+msgstr "неисправан наставак реда"
+
+#: toke.l:603 toke.l:615
+msgid "invalid IPv6 address"
+msgstr "неисправна ИПв6 адреса"
+
+#: toke.l:863
+msgid "unexpected line break in string"
+msgstr "неочекивани прекид реда у нисци"
+
+#: toke.l:983
+msgid "ignoring editor backup file"
+msgstr "занемарујем датотеку резерве уређивача"
+
+#: toke.l:986
+msgid "ignoring file name containing '.'"
+msgstr "занемарујем назив датотеке који садржи „.“"
+
+#: toke.l:1289
+msgid "too many levels of includes"
+msgstr "превише нивоа укључивања"
+
+#~ msgid "timestamp owner (%s): No such user"
+#~ msgstr "власник временске ознаке (%s): нема таквог корисника"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "„%s“ мора бити у власништву јиб-а %d"
+
+#~ msgid "%s must only be writable by owner"
+#~ msgstr "Само корисник може да пише у „%s“"
+
+#~ msgid "%s is group writable"
+#~ msgstr "Група може да пише у „%s“"
+
+#~ msgid "lecture status path too long: %s/%s"
+#~ msgstr "путања стања обучавања је предуга: %s/%s"
+
+#~ msgid "Error: %s:%d:%d: cycle in %s \"%s\""
+#~ msgstr "Грешка: %s:%d:%d: циклус у „%s“ „%s“"
+
+#~ msgid "Warning: %s:%d:%d: cycle in %s \"%s\""
+#~ msgstr "Упозорење: %s:%d:%d: циклус у „%s“ „%s“"
+
+#~ msgid "Warning: %s:%d:%d: %s \"%s\" referenced but not defined"
+#~ msgstr "Упозорење: %s:%d:%d: упута за „%s“ „%s“ постоји али није одређена"
+
+#~ msgid "parse error in %s near line %d\n"
+#~ msgstr "грешка обраде у %s близу реда %d\n"
+
+#~ msgid "parse error in %s\n"
+#~ msgstr "грешка обраде у %s\n"
+
+#~ msgid "%s: unknown defaults entry \"%s\""
+#~ msgstr "%s: непознат унос основности „%s“"
+
+#~ msgid "%s:%d:%d: no value specified for \"%s\""
+#~ msgstr "%s:%d:%d: није наведена вредност за „%s“"
+
+#~ msgid "%s:%d:%d: invalid operator \"%c=\" for \"%s\""
+#~ msgstr "%s:%d:%d: неисправан оператор „%c=“ за „%s“"
+
+#~ msgid "%s:%d:%d: option \"%s\" does not take a value"
+#~ msgstr "%s:%d:%d: опција „%s“ не узима вредност"
+
+#~ msgid "%s:%d:%d: invalid Defaults type 0x%x for option \"%s\""
+#~ msgstr "%s:%d:%d: неисправна врста основности 0x%x за опцију „%s“"
+
+#~ msgid "%s:%d:%d: value \"%s\" is invalid for option \"%s\""
+#~ msgstr "%s:%d:%d: вредност „%s“ је неисправна за опцију „%s“"
+
+#~ msgid "%s:%d:%d: path name for \"%s\" too long"
+#~ msgstr "%s:%d:%d: назив путање за „%s“ је предуг"
+
+#~ msgid "%s: path name for \"%s\" too long"
+#~ msgstr "%s: назив путање за „%s“ је предуг"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/', '~', or '*'"
+#~ msgstr "%s:%d:%d: вредност за „%s“ мора да почиње са /, ~ или *"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/'"
+#~ msgstr "%s:%d:%d: вредност за „%s“ мора да почиње са /"
+
+#~ msgid "parse error in %s near line %d"
+#~ msgstr "грешка обраде у %s близу реда %d"
+
+#~ msgid "parse error in %s"
+#~ msgstr "грешка обраде у %s"
+
+#~ msgid "SELinux RBAC is not supported when intercept mode is enabled"
+#~ msgstr "„SELinux RBAC“ није подржано када је укључен режим пресретања"
+
+#~ msgid "SELinux RBAC is not supported when the log_subcmds flag is enabled"
+#~ msgstr "„SELinux RBAC“ није подржано када је укључена заставица „log_subcmds“"
+
+#~ msgid "problem with defaults entries"
+#~ msgstr "неприлике са основним уносима"
+
+#~ msgid "internal error, unable to find %s in list!"
+#~ msgstr "унутрашња грешка, не могу да пронађем „%s“ на списку!"
+
+#~ msgid "%s is not in the sudoers file. This incident will be reported.\n"
+#~ msgstr "„%s“ се не налази у датотеци судоерса. О овом инциденту ће бити поднет извештај.\n"
+
+#~ msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+#~ msgstr "„%s“ нема права да покрене судо над „%s“. О овом инциденту ће бити поднет извештај.\n"
+
+#~ msgid "%s: write buffer already in use"
+#~ msgstr "%s: међумеморија писања је већ у употреби"
+
+#~ msgid "unable to read diffie-hellman parameters: %s"
+#~ msgstr "не могу да читам „diffie-hellman“ параметре: %s"
+
+#~ msgid "%s:%d unknown key: %s"
+#~ msgstr "„%s:%d“ непознат кључ: %s"
+
+#~ msgid "unable to get TLS server method: %s"
+#~ msgstr "не могу да добавим метод ТЛС сервера: %s"
+
+#~ msgid "%s:%u unable to parse \"%s\""
+#~ msgstr "„%s:%u“ не могу да обрадим „%s“"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " -f, --file path to configuration file\n"
+#~ " -h --help display help message and exit\n"
+#~ " -n, --no-fork do not fork, run in the foreground\n"
+#~ " -R, --random-drop percent chance connections will drop\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Опције:\n"
+#~ " -f, --file путања до датотеке подешавања\n"
+#~ " -h --help приказује поруку помоћи и излази\n"
+#~ " -n, --no-fork не исцепљује, ради у првом плану\n"
+#~ " -R, --random-drop процентуалне шансе везе ће одбацити\n"
+#~ " -V, --version приказује податке о издању и излази\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " --help display help message and exit\n"
+#~ " -A, --accept only send an accept event (no I/O)\n"
+#~ " -h, --host host to send logs to\n"
+#~ " -i, --iolog_id remote ID of I/O log to be resumed\n"
+#~ " -p, --port port to use when connecting to host\n"
+#~ " -r, --restart restart previous I/O log transfer\n"
+#~ " -R, --reject reject the command with the given reason\n"
+#~ " -b, --ca-bundle certificate bundle file to verify server's cert against\n"
+#~ " -c, --cert certificate file for TLS handshake\n"
+#~ " -k, --key private key file\n"
+#~ " -n, --no-verify do not verify server certificate\n"
+#~ " -t, --test test audit server by sending selected I/O log n times in parallel\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Опције:\n"
+#~ " --help приказује поруку помоћи и излази\n"
+#~ " -A, --accept шаље само догађај прихвата (не У/И)\n"
+#~ " -h, --host домаћин коме се шаљу дневници\n"
+#~ " -i, --iolog_id удаљени ИБ У/И дневника који ће се наставити\n"
+#~ " -p, --port прикључник за коришћење приликом повезивања са домаћином\n"
+#~ " -r, --restart поново покреће претходни пренос У/И дневника\n"
+#~ " -R, --reject одбацује наредбу са датим разлогом\n"
+#~ " -b, --ca-bundle датотека групе уверења за проверу уверења сервера\n"
+#~ " -c, --cert датотека уверења за ТЛС руковање\n"
+#~ " -k, --key датотека личног кључа\n"
+#~ " -n, --no-verify не потврђује уверење сервера\n"
+#~ " -t, --test проверава сервер испитивања шаљући изабрани У/И дневник n пута у паралели\n"
+#~ " -V, --version приказује податке о издању и излази\n"
+
+#~ msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+#~ msgstr "Унапред учитава лажне функције извршавања које се налазе у библиотеци „sudo_noexec“"
+
+#~ msgid "sudo_ldap_conf_add_ports: port too large"
+#~ msgstr "sudo_ldap_conf_add_ports: прикључник је превелик"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s\n"
+#~ msgstr "„SSL_повезивање“ није успело: ssl_грешка=%d, спремник=%s\n"
+
+#~ msgid "CA bundle file was not specified"
+#~ msgstr "датотека групних издавача уверења није наведена"
+
+#~ msgid "Client certificate was not specified"
+#~ msgstr "Уверење клијента није наведено"
+
+#~ msgid "Unable to allocate ssl object: %s\n"
+#~ msgstr "Не могу да доделим ссл објекат: %s\n"
+
+#~ msgid "Unable to attach socket to the ssl object: %s\n"
+#~ msgstr "Не могу да прикачим прикључницу ссл објекту: %s\n"
+
+#~ msgid "client message too large: %zu\n"
+#~ msgstr "порука клијента је превелика: %zu\n"
+
+#~ msgid "server message too large: %u\n"
+#~ msgstr "порука сервера је превелика: %u\n"
+
+#~ msgid "CA bundle file is not set in sudoers"
+#~ msgstr "Датотека групних издавача уверења није постављена у судоерсу"
+
+#~ msgid "Calling SSL_CTX_load_verify_locations() failed: %s"
+#~ msgstr "Позивање „SSL_CTX_load_verify_locations()“ није успело: %s"
+
+#~ msgid "Signed certificate file is not set in sudoers"
+#~ msgstr "Потписана датотека уверења није постављена у судоерсу"
+
+#~ msgid "Unable to load private key into the ssl context: %s"
+#~ msgstr "Не могу да учитам лични кључ у ссл контекст: %s"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s"
+#~ msgstr "„SSL_повезивање“ није успело: ssl_грешка=%d, спремник=%s"
+
+#~ msgid "SSL_read failed: ssl_error=%d, stack=%s"
+#~ msgstr "„SSL_читање“ није успело: ssl_грешка=%d, спремник=%s"
+
+#~ msgid "SSL_write failed: ssl_error=%d, stack=%s"
+#~ msgstr "„SSL_писање“ није успело: ssl_грешка=%d, спремник=%s"
+
+#~ msgid "unknown address family: %d"
+#~ msgstr "непозната породица адресе: %d"
+
+#~ msgid "audit_failure message too long"
+#~ msgstr "порука неуспеха прегледа је предуга"
+
+#~ msgid ""
+#~ "\n"
+#~ "LDAP Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "ЛДАП улога: НЕПОЗНАТО\n"
+
+#~ msgid " Order: %s\n"
+#~ msgstr " Поредак: %s\n"
+
+#~ msgid "No user or host"
+#~ msgstr "Нема корисника или домаћина"
+
+#~ msgid "validation failure"
+#~ msgstr "неуспех потврђивања"
+
+#~ msgid "unable to cache user %s, out of memory"
+#~ msgstr "не могу да сместим у оставу корисника „%s“, нема више меморије"
+
+#~ msgid "unable to cache group %s, out of memory"
+#~ msgstr "не могу да сместим у оставу групу „%s“, нема више меморије"
+
+#~ msgid "unable to cache group list for %s, out of memory"
+#~ msgstr "не могу да сместим у оставу списак групе за „%s“, нема више меморије"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: %s\n"
+#~ msgstr ""
+#~ "\n"
+#~ "СССД улога: %s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "СССД улога: НЕПОЗНАТО\n"
+
+#~ msgid "Warning: unused %s `%s'"
+#~ msgstr "Упозорење: некоришћено „%s“ „%s“"
+
+#~ msgid "timestamp path too long: %s/%s"
+#~ msgstr "путања временске ознаке је предуга: %s/%s"
+
+#~ msgid "unable to stat editor (%s)"
+#~ msgstr "не могу да добавим податке уређивача (%s)"
+
+#~ msgid "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+#~ msgstr "sudo_ldap_conf_add_ports: нестаде простора проширујући међумеморију домаћина"
+
+#~ msgid "sudo_ldap_parse_uri: out of space building hostbuf"
+#~ msgstr "sudo_ldap_parse_uri: нестаде простора изграђујући међумеморију домаћина"
+
+#~ msgid "sudo_ldap_build_pass1 allocation mismatch"
+#~ msgstr "не поклапа се додела „sudo_ldap_build_pass1“"
+
+#~ msgid "internal error: insufficient space for log line"
+#~ msgstr "унутрашња грешка: недовољно простора за ред дневника"
+
+#~ msgid "fill_args: buffer overflow"
+#~ msgstr "fill_args: прекорачење међумеморије"
diff --git a/plugins/sudoers/po/sudoers.pot b/plugins/sudoers/po/sudoers.pot
new file mode 100644
index 0000000..d95261a
--- /dev/null
+++ b/plugins/sudoers/po/sudoers.pot
@@ -0,0 +1,3797 @@
+# Portable object template file for the sudoers plugin
+# This file is put in the public domain.
+# Todd C. Miller <Todd.Miller@sudo.ws>, 2011-2018
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.15\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-10-19 10:02-0600\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+
+#: confstr.sh:1 gram.y:1257 plugins/sudoers/logging.c:911
+msgid "syntax error"
+msgstr ""
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr ""
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr ""
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr ""
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr ""
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr ""
+
+#: gram.y:238 gram.y:305 gram.y:314 gram.y:323 gram.y:333 gram.y:343 gram.y:367
+#: gram.y:394 gram.y:403 gram.y:411 gram.y:420 gram.y:429 gram.y:503 gram.y:513
+#: gram.y:525 gram.y:573 gram.y:582 gram.y:591 gram.y:600 gram.y:733 gram.y:742
+#: gram.y:757 gram.y:777 gram.y:796 gram.y:959 gram.y:964 gram.y:972 gram.y:986
+#: gram.y:992 gram.y:1004 gram.y:1010 gram.y:1135 gram.y:1144 gram.y:1152
+#: gram.y:1161 gram.y:1170 gram.y:1199 gram.y:1208 gram.y:1216 gram.y:1317
+#: gram.y:1447 gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:313 lib/eventlog/eventlog.c:765
+#: lib/eventlog/eventlog.c:842 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:484
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:185
+#: logsrvd/iolog_writer.c:218 logsrvd/iolog_writer.c:228
+#: logsrvd/iolog_writer.c:257 logsrvd/iolog_writer.c:278
+#: logsrvd/iolog_writer.c:290 logsrvd/iolog_writer.c:300
+#: logsrvd/iolog_writer.c:310 logsrvd/iolog_writer.c:320
+#: logsrvd/iolog_writer.c:330 logsrvd/iolog_writer.c:342
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:1057 logsrvd/logsrvd.c:1120 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:650
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1743
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:216
+#: logsrvd/logsrvd_journal.c:217 logsrvd/logsrvd_journal.c:274
+#: logsrvd/logsrvd_journal.c:279 logsrvd/logsrvd_journal.c:439
+#: logsrvd/logsrvd_journal.c:441 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:216 logsrvd/logsrvd_local.c:278
+#: logsrvd/logsrvd_local.c:279 logsrvd/logsrvd_local.c:417
+#: logsrvd/logsrvd_local.c:468 logsrvd/logsrvd_local.c:469
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:475
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/logsrvd_relay.c:446
+#: logsrvd/logsrvd_relay.c:748 logsrvd/logsrvd_relay.c:855
+#: logsrvd/sendlog.c:256 logsrvd/sendlog.c:265 logsrvd/sendlog.c:297
+#: logsrvd/sendlog.c:303 logsrvd/sendlog.c:352 logsrvd/sendlog.c:630
+#: logsrvd/sendlog.c:1822 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/bsdauth.c:154 plugins/sudoers/auth/kerb5.c:122
+#: plugins/sudoers/auth/kerb5.c:150 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/auth/sia.c:61
+#: plugins/sudoers/canon_path.c:129 plugins/sudoers/canon_path.c:161
+#: plugins/sudoers/check_aliases.c:128 plugins/sudoers/check_util.c:56
+#: plugins/sudoers/check_util.c:84 plugins/sudoers/cvtsudoers.c:132
+#: plugins/sudoers/cvtsudoers.c:176 plugins/sudoers/cvtsudoers.c:193
+#: plugins/sudoers/cvtsudoers.c:204 plugins/sudoers/cvtsudoers.c:338
+#: plugins/sudoers/cvtsudoers.c:379 plugins/sudoers/cvtsudoers.c:399
+#: plugins/sudoers/cvtsudoers.c:545 plugins/sudoers/cvtsudoers.c:698
+#: plugins/sudoers/cvtsudoers.c:716 plugins/sudoers/cvtsudoers.c:891
+#: plugins/sudoers/cvtsudoers.c:899 plugins/sudoers/cvtsudoers.c:1395
+#: plugins/sudoers/cvtsudoers.c:1399 plugins/sudoers/cvtsudoers.c:1501
+#: plugins/sudoers/cvtsudoers_csv.c:183 plugins/sudoers/cvtsudoers_csv.c:247
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:152
+#: plugins/sudoers/cvtsudoers_ldif.c:195 plugins/sudoers/cvtsudoers_ldif.c:236
+#: plugins/sudoers/cvtsudoers_ldif.c:302 plugins/sudoers/cvtsudoers_ldif.c:378
+#: plugins/sudoers/cvtsudoers_ldif.c:432 plugins/sudoers/cvtsudoers_ldif.c:440
+#: plugins/sudoers/cvtsudoers_ldif.c:451 plugins/sudoers/cvtsudoers_ldif.c:458
+#: plugins/sudoers/cvtsudoers_ldif.c:470 plugins/sudoers/cvtsudoers_ldif.c:483
+#: plugins/sudoers/cvtsudoers_ldif.c:491 plugins/sudoers/cvtsudoers_ldif.c:638
+#: plugins/sudoers/cvtsudoers_merge.c:47 plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1158
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:212
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:694 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:294 plugins/sudoers/ldap_util.c:301
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:402
+#: plugins/sudoers/log_client.c:717 plugins/sudoers/log_client.c:739
+#: plugins/sudoers/log_client.c:744 plugins/sudoers/log_client.c:1426
+#: plugins/sudoers/log_client.c:1547 plugins/sudoers/log_client.c:1670
+#: plugins/sudoers/log_client.c:1993 plugins/sudoers/log_client.c:2052
+#: plugins/sudoers/logging.c:110 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:872 plugins/sudoers/lookup.c:338
+#: plugins/sudoers/lookup.c:355 plugins/sudoers/lookup.c:374
+#: plugins/sudoers/lookup.c:393 plugins/sudoers/lookup.c:410
+#: plugins/sudoers/lookup.c:433 plugins/sudoers/lookup.c:444
+#: plugins/sudoers/match_command.c:302 plugins/sudoers/match_command.c:574
+#: plugins/sudoers/match_command.c:641 plugins/sudoers/match_command.c:737
+#: plugins/sudoers/match_command.c:785 plugins/sudoers/match_digest.c:88
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:595
+#: plugins/sudoers/parse_ldif.c:625 plugins/sudoers/parse_ldif.c:650
+#: plugins/sudoers/parse_ldif.c:708 plugins/sudoers/parse_ldif.c:725
+#: plugins/sudoers/parse_ldif.c:753 plugins/sudoers/parse_ldif.c:760
+#: plugins/sudoers/policy.c:646 plugins/sudoers/policy.c:1061
+#: plugins/sudoers/prompt.c:94 plugins/sudoers/pwutil.c:219
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:368
+#: plugins/sudoers/pwutil.c:542 plugins/sudoers/pwutil.c:607
+#: plugins/sudoers/pwutil.c:679 plugins/sudoers/pwutil.c:877
+#: plugins/sudoers/pwutil.c:967 plugins/sudoers/pwutil.c:1015
+#: plugins/sudoers/pwutil.c:1076 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:145 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1307 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:256
+#: plugins/sudoers/testsudoers.c:265 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:164 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1095
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1320
+msgid "unable to allocate memory"
+msgstr ""
+
+#: gram.y:624
+msgid "a digest requires a path name"
+msgstr ""
+
+#: gram.y:646
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr ""
+
+#: gram.y:652
+msgid "\"CWD\" path too long"
+msgstr ""
+
+#: gram.y:662
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr ""
+
+#: gram.y:668
+msgid "\"CHROOT\" path too long"
+msgstr ""
+
+#: gram.y:817
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr ""
+
+#: gram.y:840
+msgid "invalid notbefore value"
+msgstr ""
+
+#: gram.y:849
+msgid "invalid notafter value"
+msgstr ""
+
+#: gram.y:859 plugins/sudoers/policy.c:390
+msgid "timeout value too large"
+msgstr ""
+
+#: gram.y:861 plugins/sudoers/policy.c:392
+msgid "invalid timeout value"
+msgstr ""
+
+#: gram.y:982 plugins/sudoers/sudoers.c:1162
+msgid "command too long"
+msgstr ""
+
+#: gram.y:1016
+msgid "expected a fully-qualified path name"
+msgstr ""
+
+#: gram.y:1261
+#, c-format
+msgid "%s:%d:%zu: %s\n"
+msgstr ""
+
+#: gram.y:1315
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr ""
+
+#: gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:765 lib/eventlog/eventlog.c:838
+#: lib/eventlog/eventlog.c:841 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:483
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:232
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:174
+#: logsrvd/iolog_writer.c:184 logsrvd/iolog_writer.c:197
+#: logsrvd/iolog_writer.c:217 logsrvd/iolog_writer.c:227
+#: logsrvd/iolog_writer.c:246 logsrvd/iolog_writer.c:256
+#: logsrvd/iolog_writer.c:267 logsrvd/iolog_writer.c:277
+#: logsrvd/iolog_writer.c:289 logsrvd/iolog_writer.c:299
+#: logsrvd/iolog_writer.c:309 logsrvd/iolog_writer.c:319
+#: logsrvd/iolog_writer.c:329 logsrvd/iolog_writer.c:341
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:530
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:668
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:1131
+#: logsrvd/logsrvd.c:1446 logsrvd/logsrvd.c:1453 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:649
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1742
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:125
+#: logsrvd/logsrvd_journal.c:216 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:250 logsrvd/logsrvd_journal.c:258
+#: logsrvd/logsrvd_journal.c:287 logsrvd/logsrvd_journal.c:291
+#: logsrvd/logsrvd_journal.c:439 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:278 logsrvd/logsrvd_local.c:468
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:493
+#: logsrvd/logsrvd_queue.c:158 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/sendlog.c:256 logsrvd/sendlog.c:265
+#: logsrvd/sendlog.c:297 logsrvd/sendlog.c:303 logsrvd/sendlog.c:352
+#: logsrvd/sendlog.c:630 logsrvd/sendlog.c:1523 logsrvd/sendlog.c:1530
+#: logsrvd/sendlog.c:1753 logsrvd/sendlog.c:1822 logsrvd/tls_init.c:305
+#: logsrvd/tls_init.c:329 logsrvd/tls_init.c:340 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/pam.c:518 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/canon_path.c:129
+#: plugins/sudoers/canon_path.c:161 plugins/sudoers/check_aliases.c:128
+#: plugins/sudoers/check_util.c:56 plugins/sudoers/check_util.c:84
+#: plugins/sudoers/cvtsudoers.c:132 plugins/sudoers/cvtsudoers.c:175
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:203
+#: plugins/sudoers/cvtsudoers.c:337 plugins/sudoers/cvtsudoers.c:544
+#: plugins/sudoers/cvtsudoers.c:697 plugins/sudoers/cvtsudoers.c:715
+#: plugins/sudoers/cvtsudoers.c:891 plugins/sudoers/cvtsudoers.c:898
+#: plugins/sudoers/cvtsudoers.c:1395 plugins/sudoers/cvtsudoers.c:1399
+#: plugins/sudoers/cvtsudoers.c:1501 plugins/sudoers/cvtsudoers_csv.c:182
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:151 plugins/sudoers/cvtsudoers_ldif.c:194
+#: plugins/sudoers/cvtsudoers_ldif.c:235 plugins/sudoers/cvtsudoers_ldif.c:301
+#: plugins/sudoers/cvtsudoers_ldif.c:377 plugins/sudoers/cvtsudoers_ldif.c:431
+#: plugins/sudoers/cvtsudoers_ldif.c:439 plugins/sudoers/cvtsudoers_ldif.c:450
+#: plugins/sudoers/cvtsudoers_ldif.c:457 plugins/sudoers/cvtsudoers_ldif.c:469
+#: plugins/sudoers/cvtsudoers_ldif.c:482 plugins/sudoers/cvtsudoers_ldif.c:490
+#: plugins/sudoers/cvtsudoers_ldif.c:637 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51 plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1157
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:211
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:693 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:293 plugins/sudoers/ldap_util.c:300
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:228
+#: plugins/sudoers/log_client.c:250 plugins/sudoers/log_client.c:264
+#: plugins/sudoers/log_client.c:402 plugins/sudoers/log_client.c:717
+#: plugins/sudoers/log_client.c:739 plugins/sudoers/log_client.c:744
+#: plugins/sudoers/log_client.c:1426 plugins/sudoers/log_client.c:1547
+#: plugins/sudoers/log_client.c:1670 plugins/sudoers/log_client.c:1993
+#: plugins/sudoers/log_client.c:2052 plugins/sudoers/logging.c:110
+#: plugins/sudoers/logging.c:189 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:755 plugins/sudoers/logging.c:872
+#: plugins/sudoers/logging.c:925 plugins/sudoers/logging.c:932
+#: plugins/sudoers/lookup.c:337 plugins/sudoers/lookup.c:354
+#: plugins/sudoers/lookup.c:373 plugins/sudoers/lookup.c:392
+#: plugins/sudoers/lookup.c:409 plugins/sudoers/lookup.c:432
+#: plugins/sudoers/lookup.c:443 plugins/sudoers/match_command.c:301
+#: plugins/sudoers/match_command.c:573 plugins/sudoers/match_command.c:640
+#: plugins/sudoers/match_command.c:737 plugins/sudoers/match_command.c:784
+#: plugins/sudoers/match_digest.c:88 plugins/sudoers/parse_ldif.c:152
+#: plugins/sudoers/parse_ldif.c:183 plugins/sudoers/parse_ldif.c:252
+#: plugins/sudoers/parse_ldif.c:260 plugins/sudoers/parse_ldif.c:265
+#: plugins/sudoers/parse_ldif.c:341 plugins/sudoers/parse_ldif.c:352
+#: plugins/sudoers/parse_ldif.c:379 plugins/sudoers/parse_ldif.c:396
+#: plugins/sudoers/parse_ldif.c:408 plugins/sudoers/parse_ldif.c:412
+#: plugins/sudoers/parse_ldif.c:426 plugins/sudoers/parse_ldif.c:484
+#: plugins/sudoers/parse_ldif.c:595 plugins/sudoers/parse_ldif.c:624
+#: plugins/sudoers/parse_ldif.c:649 plugins/sudoers/parse_ldif.c:707
+#: plugins/sudoers/parse_ldif.c:724 plugins/sudoers/parse_ldif.c:752
+#: plugins/sudoers/parse_ldif.c:759 plugins/sudoers/policy.c:157
+#: plugins/sudoers/policy.c:166 plugins/sudoers/policy.c:175
+#: plugins/sudoers/policy.c:204 plugins/sudoers/policy.c:374
+#: plugins/sudoers/policy.c:390 plugins/sudoers/policy.c:392
+#: plugins/sudoers/policy.c:430 plugins/sudoers/policy.c:439
+#: plugins/sudoers/policy.c:448 plugins/sudoers/policy.c:457
+#: plugins/sudoers/policy.c:493 plugins/sudoers/policy.c:502
+#: plugins/sudoers/policy.c:511 plugins/sudoers/policy.c:520
+#: plugins/sudoers/policy.c:529 plugins/sudoers/policy.c:538
+#: plugins/sudoers/policy.c:547 plugins/sudoers/policy.c:646
+#: plugins/sudoers/policy.c:1061 plugins/sudoers/prompt.c:94
+#: plugins/sudoers/pwutil.c:219 plugins/sudoers/pwutil.c:290
+#: plugins/sudoers/pwutil.c:368 plugins/sudoers/pwutil.c:542
+#: plugins/sudoers/pwutil.c:607 plugins/sudoers/pwutil.c:679
+#: plugins/sudoers/pwutil.c:877 plugins/sudoers/pwutil.c:967
+#: plugins/sudoers/pwutil.c:1015 plugins/sudoers/pwutil.c:1076
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1306 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:255
+#: plugins/sudoers/testsudoers.c:264 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:163 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1094
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1309 toke.l:1320
+#, c-format
+msgid "%s: %s"
+msgstr ""
+
+#: lib/eventlog/eventlog.c:304
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr ""
+
+#: lib/eventlog/eventlog.c:346
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr ""
+
+#: lib/eventlog/eventlog.c:394 plugins/sudoers/auth/aix_auth.c:199
+msgid "unable to fork"
+msgstr ""
+
+#: lib/eventlog/eventlog.c:404 lib/eventlog/eventlog.c:471
+#, c-format
+msgid "unable to fork: %m"
+msgstr ""
+
+#: lib/eventlog/eventlog.c:461
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr ""
+
+#: lib/eventlog/eventlog.c:1000
+#, c-format
+msgid "%8s : %s"
+msgstr ""
+
+#: lib/eventlog/eventlog.c:1029
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr ""
+
+#: lib/eventlog/parse_json.c:175
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr ""
+
+#: lib/eventlog/parse_json.c:180
+msgid "JSON_ARRAY too large"
+msgstr ""
+
+#: lib/eventlog/parse_json.c:506
+msgid "missing double quote in name"
+msgstr ""
+
+#: lib/eventlog/parse_json.c:624
+msgid "missing JSON_OBJECT"
+msgstr ""
+
+#: lib/eventlog/parse_json.c:628
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr ""
+
+#: lib/eventlog/parse_json.c:762
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr ""
+
+#: lib/eventlog/parse_json.c:840
+msgid "objects must consist of name:value pairs"
+msgstr ""
+
+#: lib/eventlog/parse_json.c:845 lib/eventlog/parse_json.c:876
+#: lib/eventlog/parse_json.c:920 lib/eventlog/parse_json.c:942
+#: lib/eventlog/parse_json.c:964 lib/eventlog/parse_json.c:986
+#: lib/eventlog/parse_json.c:1008
+msgid "missing separator between values"
+msgstr ""
+
+#: lib/eventlog/parse_json.c:860 lib/eventlog/parse_json.c:1034
+msgid "unmatched close brace"
+msgstr ""
+
+#: lib/eventlog/parse_json.c:871
+msgid "unexpected array"
+msgstr ""
+
+#: lib/eventlog/parse_json.c:891 lib/eventlog/parse_json.c:1037
+msgid "unmatched close bracket"
+msgstr ""
+
+#: lib/eventlog/parse_json.c:902
+msgid "unexpected string"
+msgstr ""
+
+#: lib/eventlog/parse_json.c:913
+msgid "missing colon after name"
+msgstr ""
+
+#: lib/eventlog/parse_json.c:934 lib/eventlog/parse_json.c:956
+msgid "unexpected boolean"
+msgstr ""
+
+#: lib/eventlog/parse_json.c:978
+msgid "unexpected null"
+msgstr ""
+
+#: lib/eventlog/parse_json.c:999
+msgid "unexpected number"
+msgstr ""
+
+#: lib/eventlog/parse_json.c:1045
+msgid "parse error"
+msgstr ""
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1290
+#: plugins/sudoers/sudoreplay.c:1291 plugins/sudoers/sudoreplay.c:1587
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr ""
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr ""
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr ""
+
+#: lib/iolog/iolog_legacy.c:90
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr ""
+
+#: lib/iolog/iolog_legacy.c:97
+#, c-format
+msgid "%s: user field is missing"
+msgstr ""
+
+#: lib/iolog/iolog_legacy.c:108
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr ""
+
+#: lib/iolog/iolog_legacy.c:119
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr ""
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr ""
+
+#: lib/iolog/iolog_mkdirs.c:124 lib/iolog/iolog_mkdtemp.c:80
+#: logsrvd/iolog_writer.c:795 plugins/sudoers/timestamp.c:218
+#, c-format
+msgid "unable to mkdir %s"
+msgstr ""
+
+#: lib/iolog/iolog_mkdtemp.c:85 plugins/sudoers/visudo.c:769
+#: plugins/sudoers/visudo.c:803 plugins/sudoers/visudo.c:809
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr ""
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr ""
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:65
+#, c-format
+msgid "%s: protocol error: NULL key"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:69
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:74 logsrvd/logsrvd_local.c:109
+#: logsrvd/logsrvd_local.c:123 logsrvd/logsrvd_local.c:131
+#: logsrvd/logsrvd_local.c:149
+#, c-format
+msgid "%s: protocol error: NULL value found in %s"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:141 plugins/sudoers/logging.c:1024
+#: plugins/sudoers/policy.c:613
+msgid "unable to generate UUID"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:354 logsrvd/iolog_writer.c:359
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:369
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:430
+#, c-format
+msgid "%s: unable to format session id"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:444 logsrvd/iolog_writer.c:458
+#: logsrvd/iolog_writer.c:472 logsrvd/iolog_writer.c:487
+#: logsrvd/iolog_writer.c:501 logsrvd/iolog_writer.c:515
+#, c-format
+msgid "%s: %s is not set"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:551 logsrvd/iolog_writer.c:558
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:576
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:606
+#, c-format
+msgid "invalid iofd %d"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:626
+#, c-format
+msgid "error closing iofd %u: %s"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:647
+#, c-format
+msgid "error flushing iofd %u: %s"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:765
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:777 logsrvd/logsrvd_journal.c:391
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:799 logsrvd/logsrvd_journal.c:434
+#: logsrvd/logsrvd_queue.c:115 logsrvd/tls_init.c:256
+#: plugins/sudoers/check.c:285 plugins/sudoers/cvtsudoers.c:758
+#: plugins/sudoers/cvtsudoers.c:780 plugins/sudoers/cvtsudoers.c:1461
+#: plugins/sudoers/cvtsudoers_csv.c:697 plugins/sudoers/cvtsudoers_json.c:902
+#: plugins/sudoers/cvtsudoers_ldif.c:711 plugins/sudoers/sudoers.c:1291
+#: plugins/sudoers/sudoers.c:1317 plugins/sudoers/sudoreplay.c:1497
+#: plugins/sudoers/timestamp.c:478 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:990
+#, c-format
+msgid "unable to open %s"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:811 logsrvd/logsrv_util.c:111
+#: logsrvd/logsrv_util.c:118 plugins/sudoers/sudoreplay.c:355
+#: plugins/sudoers/sudoreplay.c:361
+#, c-format
+msgid "unable to open %s/%s"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:824
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr ""
+
+#: logsrvd/iolog_writer.c:853 logsrvd/logsrvd_journal.c:198
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr ""
+
+#: logsrvd/logsrv_util.c:153 logsrvd/logsrv_util.c:182
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr ""
+
+#: logsrvd/logsrv_util.c:165
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr ""
+
+#: logsrvd/logsrv_util.c:172
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr ""
+
+#: logsrvd/logsrvd.c:271 logsrvd/logsrvd_queue.c:135
+msgid "unable to connect to relay"
+msgstr ""
+
+#: logsrvd/logsrvd.c:338 logsrvd/logsrvd_relay.c:847
+#, c-format
+msgid "server message too large: %zu"
+msgstr ""
+
+#: logsrvd/logsrvd.c:430 logsrvd/logsrvd.c:553 logsrvd/logsrvd.c:639
+#: logsrvd/logsrvd.c:881 logsrvd/logsrvd.c:895 logsrvd/logsrvd.c:1056
+#: logsrvd/logsrvd.c:1181 logsrvd/logsrvd.c:1354 logsrvd/logsrvd.c:1372
+#: logsrvd/logsrvd.c:1471 logsrvd/logsrvd.c:1596 logsrvd/logsrvd.c:1783
+#: logsrvd/logsrvd_journal.c:503 logsrvd/logsrvd_local.c:238
+#: logsrvd/logsrvd_queue.c:164 logsrvd/logsrvd_relay.c:172
+#: logsrvd/logsrvd_relay.c:249 logsrvd/logsrvd_relay.c:253
+#: logsrvd/logsrvd_relay.c:391 logsrvd/logsrvd_relay.c:583
+#: logsrvd/logsrvd_relay.c:747 logsrvd/logsrvd_relay.c:1137
+#: logsrvd/sendlog.c:1308 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:216 plugins/sudoers/audit.c:281
+#: plugins/sudoers/iolog.c:1041 plugins/sudoers/iolog.c:1175
+#: plugins/sudoers/iolog.c:1274 plugins/sudoers/log_client.c:121
+#: plugins/sudoers/log_client.c:343 plugins/sudoers/log_client.c:359
+#: plugins/sudoers/log_client.c:407 plugins/sudoers/log_client.c:613
+#: plugins/sudoers/log_client.c:620 plugins/sudoers/log_client.c:1114
+#: plugins/sudoers/log_client.c:1395 plugins/sudoers/log_client.c:1436
+#: plugins/sudoers/log_client.c:1444 plugins/sudoers/log_client.c:1603
+#: plugins/sudoers/log_client.c:1728 plugins/sudoers/log_client.c:2060
+#: plugins/sudoers/log_client.c:2068 plugins/sudoers/logging.c:148
+#: plugins/sudoers/logging.c:206 plugins/sudoers/sudoreplay.c:519
+#: plugins/sudoers/sudoreplay.c:566 plugins/sudoers/sudoreplay.c:808
+#: plugins/sudoers/sudoreplay.c:920 plugins/sudoers/sudoreplay.c:1011
+#: plugins/sudoers/sudoreplay.c:1026 plugins/sudoers/sudoreplay.c:1033
+#: plugins/sudoers/sudoreplay.c:1040 plugins/sudoers/sudoreplay.c:1047
+#: plugins/sudoers/sudoreplay.c:1054 plugins/sudoers/sudoreplay.c:1182
+msgid "unable to add event to queue"
+msgstr ""
+
+#: logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:491 logsrvd/logsrvd.c:523
+#: logsrvd/logsrvd.c:577 logsrvd/logsrvd.c:656 logsrvd/logsrvd.c:692
+#: logsrvd/logsrvd.c:728 logsrvd/logsrvd.c:764 logsrvd/logsrvd_relay.c:512
+#: logsrvd/logsrvd_relay.c:545
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr ""
+
+#: logsrvd/logsrvd.c:455 logsrvd/logsrvd.c:492 logsrvd/logsrvd.c:524
+#: logsrvd/logsrvd.c:578 logsrvd/logsrvd.c:657 logsrvd/logsrvd.c:693
+#: logsrvd/logsrvd.c:729 logsrvd/logsrvd.c:765 logsrvd/logsrvd_relay.c:514
+#: logsrvd/logsrvd_relay.c:547
+msgid "state machine error"
+msgstr ""
+
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:462
+msgid "invalid AcceptMessage"
+msgstr ""
+
+#: logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:499
+msgid "invalid RejectMessage"
+msgstr ""
+
+#: logsrvd/logsrvd.c:530 logsrvd/logsrvd.c:531
+msgid "invalid ExitMessage"
+msgstr ""
+
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:585
+msgid "invalid RestartMessage"
+msgstr ""
+
+#: logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:620
+msgid "invalid AlertMessage"
+msgstr ""
+
+#: logsrvd/logsrvd.c:661 logsrvd/logsrvd.c:697 logsrvd/logsrvd.c:733
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr ""
+
+#: logsrvd/logsrvd.c:662 logsrvd/logsrvd.c:698 logsrvd/logsrvd.c:734
+msgid "protocol error"
+msgstr ""
+
+#: logsrvd/logsrvd.c:668 logsrvd/logsrvd.c:669
+msgid "invalid IoBuffer"
+msgstr ""
+
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:705
+msgid "invalid ChangeWindowSize"
+msgstr ""
+
+#: logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:741
+msgid "invalid CommandSuspend"
+msgstr ""
+
+#: logsrvd/logsrvd.c:790 logsrvd/logsrvd_journal.c:302
+#: logsrvd/logsrvd_relay.c:654 logsrvd/sendlog.c:1207
+#: plugins/sudoers/log_client.c:1593
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr ""
+
+#: logsrvd/logsrvd.c:835 logsrvd/logsrvd_journal.c:376
+#: logsrvd/logsrvd_relay.c:678
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr ""
+
+#: logsrvd/logsrvd.c:837
+msgid "unrecognized ClientMessage type"
+msgstr ""
+
+#: logsrvd/logsrvd.c:927
+#, c-format
+msgid "timed out writing to client %s"
+msgstr ""
+
+#: logsrvd/logsrvd.c:932 logsrvd/logsrvd_relay.c:919 logsrvd/sendlog.c:1413
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1027
+#, c-format
+msgid "timed out reading from client %s"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1068 logsrvd/logsrvd_relay.c:782
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1112 logsrvd/logsrvd_relay.c:205 logsrvd/sendlog.c:336
+#: plugins/sudoers/log_client.c:723
+#, c-format
+msgid "client message too large: %zu"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1113 logsrvd/logsrvd_journal.c:259
+#: logsrvd/logsrvd_journal.c:260
+msgid "client message too large"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1131 logsrvd/logsrvd.c:1132
+msgid "invalid ClientMessage"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1432
+msgid "unable to get remote IP addr"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1463 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:281
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1646 logsrvd/logsrvd.c:2007
+msgid "unable to setup listen socket"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1766
+#, c-format
+msgid "unexpected signal %d"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1909
+msgid "sudo log server"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1911 logsrvd/sendlog.c:126
+msgid "Options:"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1913
+msgid "path to configuration file"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1915 logsrvd/sendlog.c:128
+msgid "display help message and exit"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1917
+msgid "do not fork, run in the foreground"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1919
+msgid "percent chance connections will drop"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1921 logsrvd/sendlog.c:158
+msgid "display version information and exit"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1971 logsrvd/sendlog.c:1722
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1987
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr ""
+
+#: logsrvd/logsrvd.c:1990 logsrvd/sendlog.c:1776
+#: plugins/sudoers/cvtsudoers.c:250 plugins/sudoers/sudoreplay.c:294
+#: plugins/sudoers/visudo.c:181
+#, c-format
+msgid "%s version %s\n"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:422 plugins/sudoers/check.c:69
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/sudoers.c:419 plugins/sudoers/sudoers.c:929
+#: plugins/sudoers/sudoers.c:1034 plugins/sudoers/sudoers.c:1424
+#: plugins/sudoers/testsudoers.c:169 plugins/sudoers/testsudoers.c:285
+#: plugins/sudoers/testsudoers.c:459
+#, c-format
+msgid "unknown user %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:439 plugins/sudoers/iolog.c:148
+#: plugins/sudoers/sudoers.c:425 plugins/sudoers/sudoers.c:1458
+#: plugins/sudoers/testsudoers.c:483
+#, c-format
+msgid "unknown group %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:457
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:474 logsrvd/logsrvd_conf.c:1243
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:527
+msgid "TLS not supported"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:549
+#, c-format
+msgid "%s:%s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:622 logsrvd/logsrvd_conf.c:1032
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:951 logsrvd/logsrvd_conf.c:967
+#: logsrvd/logsrvd_conf.c:1676
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:983 logsrvd/logsrvd_conf.c:999
+#: logsrvd/logsrvd_conf.c:1015 logsrvd/logsrvd_conf.c:1680
+#: logsrvd/logsrvd_conf.c:1684 logsrvd/logsrvd_conf.c:1688
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1197
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1203
+#, c-format
+msgid "%s:%d garbage after ']': %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1215
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1223
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1229
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1251
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1281 plugins/sudoers/cvtsudoers.c:273
+#: plugins/sudoers/logging.c:1076
+#, c-format
+msgid "unable to open log file %s"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1763
+msgid "unable to initialize server TLS context"
+msgstr ""
+
+#: logsrvd/logsrvd_conf.c:1783
+msgid "unable to initialize relay TLS context"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:149 logsrvd/logsrvd_journal.c:430
+#: logsrvd/logsrvd_journal.c:435
+msgid "unable to create journal file"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:153 logsrvd/logsrvd_queue.c:109
+#: plugins/sudoers/visudo.c:1046
+#, c-format
+msgid "unable to lock %s"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:156
+msgid "unable to lock journal file"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:164
+msgid "unable to open journal file"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:185 logsrvd/logsrvd_journal.c:466
+#: logsrvd/logsrvd_journal.c:471
+msgid "unable to write journal file"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:193 logsrvd/logsrvd_journal.c:200
+msgid "unable to rename journal file"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:247 logsrvd/logsrvd_journal.c:248
+#: logsrvd/logsrvd_journal.c:288 logsrvd/logsrvd_journal.c:289
+msgid "unexpected EOF reading journal file"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:251 logsrvd/logsrvd_journal.c:252
+#: logsrvd/logsrvd_journal.c:292 logsrvd/logsrvd_journal.c:293
+msgid "error reading journal file"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:304 logsrvd/logsrvd_journal.c:390
+msgid "invalid journal file, unable to restart"
+msgstr ""
+
+#: logsrvd/logsrvd_journal.c:449
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:166
+#, c-format
+msgid "unexpected value_case %d in %s from %s"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:194
+msgid "error parsing AcceptMessage"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:205
+msgid "error creating I/O log"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:228
+msgid "error logging accept event"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:267
+msgid "error parsing RejectMessage"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:291
+msgid "error logging reject event"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:427 logsrvd/logsrvd_local.c:437
+msgid "error logging exit event"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:494 logsrvd/logsrvd_local.c:495
+msgid "log is already complete, cannot be restarted"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:525
+msgid "unable to restart log"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:541
+msgid "error parsing AlertMessage"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:551
+msgid "error logging alert event"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:587 logsrvd/logsrvd_local.c:650
+#: logsrvd/logsrvd_local.c:685
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:601 logsrvd/logsrvd_local.c:609
+#: logsrvd/logsrvd_local.c:657 logsrvd/logsrvd_local.c:692
+#: plugins/sudoers/sudoreplay.c:344 toke.l:981 toke.l:984
+#, c-format
+msgid "%s/%s: %s"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:620
+msgid "randomly dropping connection"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:632
+msgid "error writing IoBuffer"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:667
+msgid "error writing ChangeWindowSize"
+msgstr ""
+
+#: logsrvd/logsrvd_local.c:702
+msgid "error writing CommandSuspend"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:437
+msgid "TLS handshake with relay host failed"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:465
+msgid "unable to connect to relay host"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:520
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:522 logsrvd/sendlog.c:1111
+#: plugins/sudoers/log_client.c:1479
+msgid "invalid ServerHello"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:681
+msgid "unrecognized ServerMessage type"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:710
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:712
+msgid "timeout reading from relay"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:767
+msgid "relay host name does not match certificate"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:773 logsrvd/logsrvd_relay.c:787
+#: logsrvd/logsrvd_relay.c:794
+msgid "error reading from relay"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:815
+msgid "unable to read from relay"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:830 logsrvd/logsrvd_relay.c:949
+msgid "relay server closed connection"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:848
+msgid "server message too large"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:912
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:914
+msgid "timeout writing to relay"
+msgstr ""
+
+#: logsrvd/logsrvd_relay.c:968 logsrvd/logsrvd_relay.c:975
+#: logsrvd/logsrvd_relay.c:987
+msgid "error writing to relay"
+msgstr ""
+
+#: logsrvd/sendlog.c:124
+msgid "send sudo I/O log to remote server"
+msgstr ""
+
+#: logsrvd/sendlog.c:130
+msgid "only send an accept event (no I/O)"
+msgstr ""
+
+#: logsrvd/sendlog.c:133
+msgid "certificate bundle file to verify server's cert against"
+msgstr ""
+
+#: logsrvd/sendlog.c:135
+msgid "certificate file for TLS handshake"
+msgstr ""
+
+#: logsrvd/sendlog.c:138
+msgid "host to send logs to"
+msgstr ""
+
+#: logsrvd/sendlog.c:140
+msgid "remote ID of I/O log to be resumed"
+msgstr ""
+
+#: logsrvd/sendlog.c:143
+msgid "private key file"
+msgstr ""
+
+#: logsrvd/sendlog.c:145
+msgid "do not verify server certificate"
+msgstr ""
+
+#: logsrvd/sendlog.c:148
+msgid "port to use when connecting to host"
+msgstr ""
+
+#: logsrvd/sendlog.c:150
+msgid "restart previous I/O log transfer"
+msgstr ""
+
+#: logsrvd/sendlog.c:152
+msgid "reject the command with the given reason"
+msgstr ""
+
+#: logsrvd/sendlog.c:154
+msgid "stop transfer after reaching this time"
+msgstr ""
+
+#: logsrvd/sendlog.c:156
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr ""
+
+#: logsrvd/sendlog.c:181 plugins/sudoers/log_client.c:453
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr ""
+
+#: logsrvd/sendlog.c:219
+msgid "unable to get server IP addr"
+msgstr ""
+
+#: logsrvd/sendlog.c:314 plugins/sudoers/sudoreplay.c:868
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr ""
+
+#: logsrvd/sendlog.c:1035 plugins/sudoers/iolog.c:959
+#: plugins/sudoers/iolog.c:1034
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr ""
+
+#: logsrvd/sendlog.c:1088 logsrvd/sendlog.c:1105 logsrvd/sendlog.c:1139
+#: plugins/sudoers/log_client.c:1129 plugins/sudoers/log_client.c:1405
+#: plugins/sudoers/log_client.c:1473 plugins/sudoers/log_client.c:1512
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr ""
+
+#: logsrvd/sendlog.c:1175 plugins/sudoers/log_client.c:1561
+#, c-format
+msgid "error message received from server: %s"
+msgstr ""
+
+#: logsrvd/sendlog.c:1188 plugins/sudoers/log_client.c:1574
+#, c-format
+msgid "abort message received from server: %s"
+msgstr ""
+
+#: logsrvd/sendlog.c:1247 plugins/sudoers/log_client.c:1624
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr ""
+
+#: logsrvd/sendlog.c:1276
+msgid "timeout reading from server"
+msgstr ""
+
+#: logsrvd/sendlog.c:1327 plugins/sudoers/log_client.c:1747
+msgid "host name does not match certificate"
+msgstr ""
+
+#: logsrvd/sendlog.c:1361
+msgid "premature EOF"
+msgstr ""
+
+#: logsrvd/sendlog.c:1374 plugins/sudoers/log_client.c:1795
+#, c-format
+msgid "server message too large: %u"
+msgstr ""
+
+#: logsrvd/sendlog.c:1430
+msgid "timeout writing to server"
+msgstr ""
+
+#: logsrvd/sendlog.c:1800
+msgid "both restart point and iolog ID must be specified"
+msgstr ""
+
+#: logsrvd/sendlog.c:1804
+msgid "a restart point may not be set when no I/O is sent"
+msgstr ""
+
+#: logsrvd/sendlog.c:1880
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr ""
+
+#: logsrvd/sendlog.c:1881
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr ""
+
+#: logsrvd/sendlog.c:1883
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr ""
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:315
+msgid "TLS handshake timeout occurred"
+msgstr ""
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:337 plugins/sudoers/log_client.c:353
+msgid "unable to set event"
+msgstr ""
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr ""
+
+#: logsrvd/tls_client.c:196
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr ""
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr ""
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr ""
+
+#: logsrvd/tls_init.c:138 logsrvd/tls_init.c:146
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr ""
+
+#: logsrvd/tls_init.c:166 logsrvd/tls_init.c:174
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr ""
+
+#: logsrvd/tls_init.c:206 logsrvd/tls_init.c:227
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr ""
+
+#: logsrvd/tls_init.c:283
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr ""
+
+#: logsrvd/tls_init.c:290
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr ""
+
+#: plugins/sudoers/audit.c:272 plugins/sudoers/audit.c:452
+#: plugins/sudoers/log_client.c:962 plugins/sudoers/log_client.c:1011
+#: plugins/sudoers/log_client.c:1060 plugins/sudoers/log_client.c:1185
+#: plugins/sudoers/logging.c:614 plugins/sudoers/logging.c:732
+#: plugins/sudoers/logging.c:859 plugins/sudoers/logging.c:1031
+#: plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr ""
+
+#: plugins/sudoers/auth/aix_auth.c:282
+#, c-format
+msgid "unable to change password for %s"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:78
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:85
+msgid "invalid authentication type"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to begin BSD authentication"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:97
+msgid "unable to initialize BSD authentication"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:191
+msgid "your account has expired"
+msgstr ""
+
+#: plugins/sudoers/auth/bsdauth.c:193
+msgid "approval failed"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:62
+msgid "unable to read fwtk config"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:67
+msgid "unable to connect to authentication server"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:73 plugins/sudoers/auth/fwtk.c:99
+#: plugins/sudoers/auth/fwtk.c:131
+msgid "lost connection to authentication server"
+msgstr ""
+
+#: plugins/sudoers/auth/fwtk.c:77
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:116
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:166
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:175
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:226
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:241
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:254
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:257
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:322
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:336
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:233
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:349
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:369
+msgid "account validation failure, is your account locked?"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:380
+msgid "Account or password is expired, reset your password and try again"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:387
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:398
+msgid "Password expired, contact your system administrator"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:403
+msgid ""
+"Account expired or PAM config lacks an \"account\" section for sudo, contact "
+"your system administrator"
+msgstr ""
+
+#: plugins/sudoers/auth/pam.c:411 plugins/sudoers/auth/pam.c:416
+#, c-format
+msgid "PAM account management error: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/rfc1938.c:100 plugins/sudoers/visudo.c:266
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:76
+msgid "failed to initialise the ACE API library"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "unable to contact the SecurID server"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:117
+msgid "User ID locked for SecurID Authentication"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:121 plugins/sudoers/auth/securid5.c:174
+msgid "invalid username length for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:125 plugins/sudoers/auth/securid5.c:179
+msgid "invalid Authentication Handle for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:129
+msgid "SecurID communication failed"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:133 plugins/sudoers/auth/securid5.c:222
+msgid "unknown SecurID error"
+msgstr ""
+
+#: plugins/sudoers/auth/securid5.c:169
+msgid "invalid passcode length for SecurID"
+msgstr ""
+
+#: plugins/sudoers/auth/sia.c:72 plugins/sudoers/auth/sia.c:130
+msgid "unable to initialize SIA session"
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:141
+msgid "invalid authentication methods"
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:143
+msgid ""
+"Invalid authentication methods compiled into sudo! You may not mix "
+"standalone and non-standalone authentication."
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:296 plugins/sudoers/auth/sudo_auth.c:359
+msgid "no authentication methods"
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:298
+msgid ""
+"There are no authentication methods compiled into sudo! If you want to turn "
+"off authentication, use the --disable-authentication configure option."
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:361
+msgid "Unable to initialize authentication methods."
+msgstr ""
+
+#: plugins/sudoers/auth/sudo_auth.c:551
+msgid "Authentication methods:"
+msgstr ""
+
+#: plugins/sudoers/bsm_audit.c:122 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr ""
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:278
+msgid "unable to commit audit record"
+msgstr ""
+
+#: plugins/sudoers/check.c:63 plugins/sudoers/check.c:74
+#: plugins/sudoers/lookup.c:79 plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr ""
+
+#: plugins/sudoers/check.c:277
+#, c-format
+msgid "error reading lecture file %s"
+msgstr ""
+
+#: plugins/sudoers/check.c:280
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr ""
+
+#: plugins/sudoers/check.c:293
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/check.c:301
+msgid ""
+"For security reasons, the password you type will not be visible.\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/check_aliases.c:93
+#, c-format
+msgid "cycle in %s \"%s\""
+msgstr ""
+
+#: plugins/sudoers/check_aliases.c:96
+#, c-format
+msgid "%s \"%s\" referenced but not defined"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:211
+#, c-format
+msgid "order increment: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:231
+#, c-format
+msgid "starting order: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:242
+#, c-format
+msgid "order padding: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:252 plugins/sudoers/visudo.c:183
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:282 plugins/sudoers/testsudoers.c:162
+#, c-format
+msgid "unsupported input format %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:300
+#, c-format
+msgid "unsupported output format %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:392
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:406 plugins/sudoers/sudoers.c:151
+#: plugins/sudoers/sudoers.c:209 plugins/sudoers/testsudoers.c:315
+#: plugins/sudoers/visudo.c:276 plugins/sudoers/visudo.c:666
+msgid "unable to initialize sudoers default values"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:533 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:612
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:658
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:681
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:722 plugins/sudoers/cvtsudoers.c:738
+#, c-format
+msgid "invalid filter: %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:783 plugins/sudoers/visudo.c:1000
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:1508 plugins/sudoers/sudoreplay.c:1143
+#: plugins/sudoers/timestamp.c:353 plugins/sudoers/timestamp.c:356
+#, c-format
+msgid "unable to write to %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:1536
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers.c:1538
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:245 plugins/sudoers/cvtsudoers_ldif.c:252
+#: plugins/sudoers/cvtsudoers_ldif.c:594 plugins/sudoers/env.c:340
+#: plugins/sudoers/env.c:347 plugins/sudoers/env.c:458
+#: plugins/sudoers/ldap.c:511 plugins/sudoers/ldap.c:629
+#: plugins/sudoers/ldap.c:1003 plugins/sudoers/ldap_conf.c:219
+#: plugins/sudoers/ldap_conf.c:310 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:93 plugins/sudoers/logging.c:479
+#: plugins/sudoers/policy.c:828 plugins/sudoers/policy.c:840
+#: plugins/sudoers/prompt.c:169 plugins/sudoers/serialize_list.c:62
+#: plugins/sudoers/serialize_list.c:71 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/sudoreplay.c:1340 plugins/sudoers/sudoreplay.c:1346
+#: plugins/sudoers/sudoreplay.c:1352 plugins/sudoers/testsudoers.c:306
+#: plugins/sudoers/toke_util.c:217 toke.l:995 toke.l:1277
+#, c-format
+msgid "internal error, %s overflow"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_csv.c:454 plugins/sudoers/cvtsudoers_csv.c:468
+#: plugins/sudoers/cvtsudoers_json.c:661 plugins/sudoers/cvtsudoers_json.c:676
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:362
+#: plugins/sudoers/ldap.c:495
+msgid "unable to get GMT time"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_csv.c:459 plugins/sudoers/cvtsudoers_csv.c:473
+#: plugins/sudoers/cvtsudoers_json.c:666 plugins/sudoers/cvtsudoers_json.c:681
+#: plugins/sudoers/cvtsudoers_ldif.c:354 plugins/sudoers/cvtsudoers_ldif.c:367
+#: plugins/sudoers/ldap.c:503
+msgid "unable to format timestamp"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_json.c:481 plugins/sudoers/cvtsudoers_json.c:516
+#: plugins/sudoers/cvtsudoers_json.c:732
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_ldif.c:663
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_ldif.c:706
+msgid ""
+"the SUDOERS_BASE environment variable is not set and the -b option was not "
+"specified."
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, c-format
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, c-format
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, c-format
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:1088
+#, c-format
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:1182
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:56
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:60
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:64
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:68
+msgid "Put OTP prompt on its own line"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:72
+msgid "Ignore '.' in $PATH"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:76
+msgid "Always send mail when sudo is run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:80
+msgid "Send mail if user authentication fails"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:84
+msgid "Send mail if the user is not in sudoers"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:88
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:92
+msgid "Send mail if the user is not allowed to run a command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:96
+msgid "Send mail if the user tries to run a command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:100
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:104
+msgid "Lecture user the first time they run sudo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:108
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:112
+msgid "Require users to authenticate by default"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:116
+msgid "Root may run sudo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:120
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:124
+msgid "Log the year in the (non-syslog) log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:128
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:132
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:136
+msgid "Always set $HOME to the target user's home directory"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:140
+msgid "Allow some information gathering to give useful error messages"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:144
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:148
+msgid "Insult the user when they enter an incorrect password"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:152
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:156
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:160
+msgid "Prompt for root's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:164
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:168
+msgid "Prompt for the target user's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:172
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:176
+msgid "Set the LOGNAME and USER environment variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:180
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:184
+msgid "Don't initialize the group vector to that of the target user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:188
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:192
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:196
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:200
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:204
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:208
+#, c-format
+msgid "Path to log file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:212
+#, c-format
+msgid "Path to mail program: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:216
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:220
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:224
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:228
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:232
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:236
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:240
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:244
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:248
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:252
+#, c-format
+msgid "Default password prompt: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:256
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr ""
+
+#: plugins/sudoers/def_data.c:260
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:264
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:268
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:272
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:276
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:280
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:284
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:288
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:292
+msgid ""
+"If set, users may override the value of \"closefrom\" with the -C option"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:296
+msgid "Allow users to set arbitrary environment variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:300
+msgid "Reset the environment to a default set of variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:304
+msgid "Environment variables to check for safety:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:308
+msgid "Environment variables to remove:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:312
+msgid "Environment variables to preserve:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:316
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:320
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:324
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:328
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:332
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:336
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:340
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:344
+msgid ""
+"Use faster globbing that is less accurate but does not access the filesystem"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:348
+msgid ""
+"The umask specified in sudoers will override the user's, even if it is more "
+"permissive"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:352
+msgid "Log user's input for the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:356
+msgid "Log the command's standard input if not connected to a terminal"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:360
+msgid "Log the user's terminal input for the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:364
+msgid "Log the output of the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:368
+msgid "Log the command's standard output if not connected to a terminal"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:372
+msgid "Log the command's standard error if not connected to a terminal"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:376
+msgid "Log the terminal output of the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:380
+msgid "Compress I/O logs using zlib"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:384
+msgid "Always run commands in a pseudo-tty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:388
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:392
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:396
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:400
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:404
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:408
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:412
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:416
+msgid "Run commands on a pty in the background"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:420
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:424
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:428
+#, c-format
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:432
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:436
+msgid "Create a new PAM session for the command to run in"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:440
+msgid "Perform PAM account validation management"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:444
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:448
+msgid "Enable sudoers netgroup support"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:452
+msgid ""
+"Check parent directories for writability when editing files with sudoedit"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:456
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:460
+msgid "Query the group plugin for unknown system groups"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:464
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:468
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:472
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:476
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:480
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:484
+#, c-format
+msgid ""
+"Log entries larger than this value will be split into multiple syslog "
+"messages: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:488
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:492
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:496
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:500
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:504
+msgid ""
+"Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:508
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:512
+msgid "Allow the user to specify a timeout on the command line"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:516
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:520
+msgid "Include the process ID when logging via syslog"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:524
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:528
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:532
+msgid "Ignore case when matching user names"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:536
+msgid "Ignore case when matching group names"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:540
+msgid "Log when a command is allowed by sudoers"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:544
+msgid "Log when a command is denied by sudoers"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:548
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:552
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:556
+msgid ""
+"Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:560
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:564
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:568
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:572
+msgid "Verify that the log server's certificate is valid"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:576
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:580
+msgid "Only permit running commands as a user with a valid shell"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:584
+msgid "Set the pam remote user to the user running sudo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:588
+msgid "Set the pam remote host to the local host name"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:592
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:596
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:600
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:604
+msgid "Enable SELinux RBAC support"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:608
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:612
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:616
+msgid "Log sub-commands run by the original command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:620
+msgid "Log the exit status of commands"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:624
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:628
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:632
+#, c-format
+msgid ""
+"The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:636
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:640
+#, c-format
+msgid ""
+"The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:644
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:648
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:652
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:656
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:660
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:664
+#, c-format
+msgid ""
+"The maximum number of processes that the user may run simultaneously: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:668
+#, c-format
+msgid ""
+"The maximum size to which the process's resident set size may grow (in "
+"bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:672
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:676
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:680
+msgid "Store plaintext passwords in I/O log input"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:684
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:688
+#, c-format
+msgid "The mechanism used by the intercept and log_subcmds options: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:692
+msgid "Attempt to verify the command and arguments after execution"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:696
+#, c-format
+msgid "AppArmor profile to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:207
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:251
+#, c-format
+msgid "no value specified for \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:260
+#, c-format
+msgid "invalid operator \"%c=\" for \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:292
+#, c-format
+msgid "option \"%s\" does not take a value"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:319
+#, c-format
+msgid "invalid Defaults type 0x%x for option \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:326
+#, c-format
+msgid "value \"%s\" is invalid for option \"%s\""
+msgstr ""
+
+#: plugins/sudoers/defaults.c:1176 plugins/sudoers/policy.c:213
+#: plugins/sudoers/policy.c:222
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:1182
+#, c-format
+msgid "values for \"%s\" must start with a '/', '~', or '*'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:1189
+#, c-format
+msgid "values for \"%s\" must start with a '/'"
+msgstr ""
+
+#: plugins/sudoers/display.c:160
+#, c-format
+msgid "LDAP Role: %s\n"
+msgstr ""
+
+#: plugins/sudoers/display.c:163
+#, c-format
+msgid "Sudoers entry: %s\n"
+msgstr ""
+
+#: plugins/sudoers/display.c:166
+msgid " RunAsUsers: "
+msgstr ""
+
+#: plugins/sudoers/display.c:181
+msgid " RunAsGroups: "
+msgstr ""
+
+#: plugins/sudoers/display.c:191
+msgid " Options: "
+msgstr ""
+
+#: plugins/sudoers/display.c:255
+msgid " Commands:\n"
+msgstr ""
+
+#: plugins/sudoers/display.c:478
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr ""
+
+#: plugins/sudoers/display.c:496
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr ""
+
+#: plugins/sudoers/display.c:514
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr ""
+
+#: plugins/sudoers/display.c:530
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/editor.c:180
+#, c-format
+msgid "ignoring editor: %.*s"
+msgstr ""
+
+#: plugins/sudoers/editor.c:181
+msgid "editor arguments may not contain \"--\""
+msgstr ""
+
+#: plugins/sudoers/env.c:426
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr ""
+
+#: plugins/sudoers/env.c:1119
+msgid "unable to rebuild the environment"
+msgstr ""
+
+#: plugins/sudoers/env.c:1199
+#, c-format
+msgid ""
+"sorry, you are not allowed to set the following environment variables: %s"
+msgstr ""
+
+#: plugins/sudoers/filedigest.c:50
+#, c-format
+msgid "unsupported digest type %u for %s"
+msgstr ""
+
+#: plugins/sudoers/filedigest.c:77
+#, c-format
+msgid "%s: read error"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:169 plugins/sudoers/sssd.c:578
+#, c-format
+msgid "unable to load %s: %s"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:181
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:186
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:694
+msgid "unable to update sequence file"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:728 plugins/sudoers/iolog.c:917
+#: plugins/sudoers/iolog.c:1080 plugins/sudoers/iolog.c:1087
+#: plugins/sudoers/iolog.c:1209 plugins/sudoers/iolog.c:1216
+#: plugins/sudoers/iolog.c:1316 plugins/sudoers/iolog.c:1323
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:736
+#, c-format
+msgid "unable to create %s/%s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:965
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:1065 plugins/sudoers/iolog.c:1194
+#: plugins/sudoers/iolog.c:1300 plugins/sudoers/timestamp.c:897
+#: plugins/sudoers/timestamp.c:989 plugins/sudoers/visudo.c:555
+#: plugins/sudoers/visudo.c:561
+msgid "unable to read the clock"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:1292 plugins/sudoers/log_client.c:1203
+#: plugins/sudoers/log_client.c:1213 plugins/sudoers/log_client.c:1217
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:154 plugins/sudoers/ldap_conf.c:289
+msgid "starttls not supported when using ldaps"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:226
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:229
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1593
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1630
+msgid ""
+"start_tls specified but LDAP libs do not support ldap_start_tls_s() or "
+"ldap_start_tls_s_np()"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1767 plugins/sudoers/parse_ldif.c:745
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap_conf.c:197
+#, c-format
+msgid "%s: port too large"
+msgstr ""
+
+#: plugins/sudoers/ldap_conf.c:258
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap_conf.c:285
+msgid "unable to mix ldap and ldaps URIs"
+msgstr ""
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr ""
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr ""
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr ""
+
+#: plugins/sudoers/linux_audit.c:104
+msgid "unable to send audit message"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:125 plugins/sudoers/log_client.c:412
+#: plugins/sudoers/log_client.c:1450 plugins/sudoers/log_client.c:2076
+msgid "error in event loop"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:205
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:230
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load certificate %s"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "unable to load private key %s"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:275
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:364 plugins/sudoers/log_client.c:369
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:545
+msgid "TLS initialization was unsuccessful"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:555
+msgid "TLS handshake was unsuccessful"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:1221
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:1757 plugins/sudoers/log_client.c:1782
+msgid "lost connection to log server"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:1859
+msgid "missing write buffer"
+msgstr ""
+
+#: plugins/sudoers/log_client.c:2015
+msgid "unable to connect to log server"
+msgstr ""
+
+#: plugins/sudoers/logging.c:295
+msgid "user NOT in sudoers"
+msgstr ""
+
+#: plugins/sudoers/logging.c:297
+msgid "user NOT authorized on host"
+msgstr ""
+
+#: plugins/sudoers/logging.c:299
+msgid "command not allowed"
+msgstr ""
+
+#: plugins/sudoers/logging.c:320
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:323
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:326
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:339
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s%s' as %s%s%s on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:350
+msgid "This incident has been reported to the administrator.\n"
+msgstr ""
+
+#: plugins/sudoers/logging.c:387 plugins/sudoers/sudoers.c:547
+#: plugins/sudoers/sudoers.c:549 plugins/sudoers/sudoers.c:551
+#: plugins/sudoers/sudoers.c:553 plugins/sudoers/sudoers.c:777
+#: plugins/sudoers/sudoers.c:779
+#, c-format
+msgid "%s: command not found"
+msgstr ""
+
+#: plugins/sudoers/logging.c:389 plugins/sudoers/sudoers.c:543
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+
+#: plugins/sudoers/logging.c:409
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] ""
+msgstr[1] ""
+
+#: plugins/sudoers/logging.c:500
+msgid "authentication failure"
+msgstr ""
+
+#: plugins/sudoers/logging.c:539 plugins/sudoers/logging.c:558
+msgid "a password is required"
+msgstr ""
+
+#: plugins/sudoers/logging.c:881
+msgid "problem parsing sudoers"
+msgstr ""
+
+#: plugins/sudoers/logging.c:922 plugins/sudoers/logging.c:930
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:1108
+#, c-format
+msgid "unable to write log file %s"
+msgstr ""
+
+#: plugins/sudoers/match_digest.c:107
+#, c-format
+msgid "digest for %s (%s) bad length %zu, expected %zu"
+msgstr ""
+
+#: plugins/sudoers/match_digest.c:126
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr ""
+
+#: plugins/sudoers/parse_ldif.c:615
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr ""
+
+#: plugins/sudoers/parse_ldif.c:675
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr ""
+
+#: plugins/sudoers/parser_warnx.c:56
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr ""
+
+#: plugins/sudoers/parser_warnx.c:59
+#, c-format
+msgid "%s: %s\n"
+msgstr ""
+
+#: plugins/sudoers/pivot.c:71
+msgid "unable to restore root directory"
+msgstr ""
+
+#: plugins/sudoers/pivot.c:79
+msgid "unable to restore current working directory"
+msgstr ""
+
+#: plugins/sudoers/policy.c:78 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:364 plugins/sudoers/testsudoers.c:329
+msgid "unable to parse network address list"
+msgstr ""
+
+#: plugins/sudoers/policy.c:556
+msgid "user name not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:560
+msgid "user-ID not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:564
+msgid "group-ID not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:568
+msgid "host name not set by sudo front-end"
+msgstr ""
+
+#: plugins/sudoers/policy.c:757
+#, c-format
+msgid "invalid working directory: %s"
+msgstr ""
+
+#: plugins/sudoers/policy.c:944
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1153 plugins/sudoers/visudo.c:919
+#: plugins/sudoers/visudo.c:1218
+#, c-format
+msgid "unable to execute %s"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1225 plugins/sudoers/policy.c:1260
+#: plugins/sudoers/policy.c:1282 plugins/sudoers/policy.c:1300
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1323
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1325
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1329
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1332
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1335
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1337
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1370
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr ""
+
+#: plugins/sudoers/policy.c:1388
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:242 plugins/sudoers/pwutil.c:260
+#, c-format
+msgid "unable to cache uid %u"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:254
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:314 plugins/sudoers/pwutil.c:332
+#: plugins/sudoers/pwutil.c:395 plugins/sudoers/pwutil.c:440
+#, c-format
+msgid "unable to cache user %s"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:327
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:559 plugins/sudoers/pwutil.c:577
+#, c-format
+msgid "unable to cache gid %u"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:571
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:625 plugins/sudoers/pwutil.c:643
+#: plugins/sudoers/pwutil.c:704 plugins/sudoers/pwutil.c:753
+#, c-format
+msgid "unable to cache group %s"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:638
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:900 plugins/sudoers/pwutil.c:985
+#: plugins/sudoers/pwutil.c:1039 plugins/sudoers/pwutil.c:1095
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:906 plugins/sudoers/pwutil.c:990
+#: plugins/sudoers/pwutil.c:1045 plugins/sudoers/pwutil.c:1100
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:979
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:1089
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:120 plugins/sudoers/set_perms.c:457
+#: plugins/sudoers/set_perms.c:870 plugins/sudoers/set_perms.c:1186
+#: plugins/sudoers/set_perms.c:1490
+msgid "perm stack overflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:131 plugins/sudoers/set_perms.c:387
+#: plugins/sudoers/set_perms.c:468 plugins/sudoers/set_perms.c:736
+#: plugins/sudoers/set_perms.c:881 plugins/sudoers/set_perms.c:1109
+#: plugins/sudoers/set_perms.c:1197 plugins/sudoers/set_perms.c:1422
+#: plugins/sudoers/set_perms.c:1501 plugins/sudoers/set_perms.c:1592
+msgid "perm stack underflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:191 plugins/sudoers/set_perms.c:515
+#: plugins/sudoers/set_perms.c:1251 plugins/sudoers/set_perms.c:1535
+msgid "unable to change to root gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:282 plugins/sudoers/set_perms.c:612
+#: plugins/sudoers/set_perms.c:1013 plugins/sudoers/set_perms.c:1328
+msgid "unable to change to runas gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:287 plugins/sudoers/set_perms.c:617
+#: plugins/sudoers/set_perms.c:1018 plugins/sudoers/set_perms.c:1333
+msgid "unable to set runas group vector"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:298 plugins/sudoers/set_perms.c:628
+#: plugins/sudoers/set_perms.c:1027 plugins/sudoers/set_perms.c:1342
+msgid "unable to change to runas uid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:320 plugins/sudoers/set_perms.c:650
+#: plugins/sudoers/set_perms.c:1047 plugins/sudoers/set_perms.c:1362
+msgid "unable to change to sudoers gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579
+msgid "too many processes"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:62
+msgid "unable to get current working directory"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:70
+#, c-format
+msgid "truncated audit path ctx->user.cmnd: %s"
+msgstr ""
+
+#: plugins/sudoers/solaris_audit.c:77
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:581
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:589 plugins/sudoers/sssd.c:598
+#: plugins/sudoers/sssd.c:607 plugins/sudoers/sssd.c:616
+#: plugins/sudoers/sssd.c:625
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:250
+#, c-format
+msgid "unable to get defaults from %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:259
+msgid "no valid sudoers sources found, quitting"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:366
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:375
+msgid "user not allowed to override closefrom limit"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:376
+msgid "you are not permitted to use the -C option"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:440
+msgid "no tty"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:441
+msgid "sorry, you must have a tty to run sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:449
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:491
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:493
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:506
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:507
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:542
+msgid "command in current directory"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:557
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:559
+msgid "the -s option may be used to run a privileged shell."
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:561
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:570
+msgid "user not allowed to set a command timeout"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:572
+msgid "sorry, you are not allowed set a command timeout"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:580
+msgid "user not allowed to preserve the environment"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:582
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:618
+msgid "no command specified"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:759
+msgid "error setting user-specified environment variables"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1211
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:1613
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1321 plugins/sudoers/visudo.c:1123
+#, c-format
+msgid "%s is not a regular file"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1325 plugins/sudoers/timestamp.c:272 toke.l:1355
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1330 plugins/sudoers/timestamp.c:279 toke.l:1360
+#, c-format
+msgid "%s is world writable"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1334 plugins/sudoers/timestamp.c:284 toke.l:1363
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1363
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:1382
+#, c-format
+msgid "unknown login class %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers_cb.c:120 plugins/sudoers/sudoers_cb.c:135
+#, c-format
+msgid "unable to resolve host %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:252
+#, c-format
+msgid "invalid filter option: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:268
+#, c-format
+msgid "invalid max wait: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:291
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:326
+#, c-format
+msgid "invalid time offset %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:340
+#, c-format
+msgid "%s/timing: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:634
+msgid "unable to set tty to raw mode"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:685
+msgid "Warning: your terminal is too small to properly replay the log."
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:686
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:714
+msgid "Replay finished, press any key to restore the terminal."
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1217 plugins/sudoers/sudoreplay.c:1247
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1269
+msgid "unmatched ')' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1273
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1288
+#, c-format
+msgid "%s requires an argument"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1298
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1307
+msgid "unmatched '(' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1309
+msgid "illegal trailing \"or\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1311
+msgid "illegal trailing \"!\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1417
+#, c-format
+msgid "unknown search type %d"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1679
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1681
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1695
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1697
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional "
+"expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:392
+#, c-format
+msgid ""
+"\n"
+"Invalid shell for user %s: %s\n"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:411
+msgid ""
+"\n"
+"Password required"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:422
+msgid ""
+"\n"
+"Parse error"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:425
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:428
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:431
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:364 plugins/sudoers/timestamp.c:711
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:908
+msgid "ignoring time stamp from the future"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:931
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:1067
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:1114
+#, c-format
+msgid "%s:%d:%d timestampowner: unknown user %s"
+msgstr ""
+
+#: plugins/sudoers/toke_util.c:159
+msgid "sudoedit should not be specified with a path"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:308 plugins/sudoers/visudo.c:714
+#, c-format
+msgid "press return to edit %s: "
+msgstr ""
+
+#: plugins/sudoers/visudo.c:323
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:401
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:406
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:494 plugins/sudoers/visudo.c:786
+#, c-format
+msgid "unable to stat %s"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:514 plugins/sudoers/visudo.c:522
+msgid "write error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:568
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:575
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:581
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:613
+#, c-format
+msgid "%s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:661
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr ""
+
+#: plugins/sudoers/visudo.c:674
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:760 plugins/sudoers/visudo.c:790
+#: plugins/sudoers/visudo.c:797
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:825
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:836
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:843
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:864
+msgid "What now? "
+msgstr ""
+
+#: plugins/sudoers/visudo.c:878
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:923
+#, c-format
+msgid "unable to run %s"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:954
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:965
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1017 plugins/sudoers/visudo.c:1024
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1043
+#, c-format
+msgid "%s busy, try again later"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1047
+msgid "Edit anyway? [y/N]"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1206
+msgid "the -x option will be removed in a future release"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1208
+msgid "please consider using the cvtsudoers utility instead"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1228
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1341
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1343
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -I, --no-includes do not edit include files\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+
+#: toke.l:184
+msgid "empty string"
+msgstr ""
+
+#: toke.l:196 toke.l:566
+msgid "empty group"
+msgstr ""
+
+#: toke.l:206 toke.l:564
+msgid "empty netgroup"
+msgstr ""
+
+#: toke.l:284
+msgid "unterminated regular expression"
+msgstr ""
+
+#: toke.l:358 toke.l:370 toke.l:382 toke.l:398 toke.l:417 toke.l:457
+msgid "invalid line continuation"
+msgstr ""
+
+#: toke.l:603 toke.l:615
+msgid "invalid IPv6 address"
+msgstr ""
+
+#: toke.l:863
+msgid "unexpected line break in string"
+msgstr ""
+
+#: toke.l:982
+msgid "ignoring editor backup file"
+msgstr ""
+
+#: toke.l:985
+msgid "ignoring file name containing '.'"
+msgstr ""
+
+#: toke.l:1310
+msgid "too many levels of includes"
+msgstr ""
diff --git a/plugins/sudoers/po/sv.mo b/plugins/sudoers/po/sv.mo
new file mode 100644
index 0000000..661d49a
--- /dev/null
+++ b/plugins/sudoers/po/sv.mo
Binary files differ
diff --git a/plugins/sudoers/po/sv.po b/plugins/sudoers/po/sv.po
new file mode 100644
index 0000000..cec3337
--- /dev/null
+++ b/plugins/sudoers/po/sv.po
@@ -0,0 +1,4178 @@
+# Swedish translation for sudoers.
+# Copyright © 2012, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Free Software Foundation, Inc.
+# This file is put in the public domain.
+# Daniel Nylander <po@danielnylander.se>, 2012.
+# Sebastian Rasmussen <sebras@gmail.com>, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023.
+# Luna Jernberg <droidbittin@gmail.com>, 2021.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.9.15b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-10-19 10:02-0600\n"
+"PO-Revision-Date: 2023-10-23 01:52+0200\n"
+"Last-Translator: Sebastian Rasmussen <sebras@gmail.com>\n"
+"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
+"Language: sv\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 3.3.2\n"
+
+#: confstr.sh:1 gram.y:1257 plugins/sudoers/logging.c:911
+msgid "syntax error"
+msgstr "syntaxfel"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "lösenord för %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] lösenord för %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Lösenord: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** SÄKERHETSINFORMATION för %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Försök igen."
+
+#: gram.y:238 gram.y:305 gram.y:314 gram.y:323 gram.y:333 gram.y:343 gram.y:367
+#: gram.y:394 gram.y:403 gram.y:411 gram.y:420 gram.y:429 gram.y:503 gram.y:513
+#: gram.y:525 gram.y:573 gram.y:582 gram.y:591 gram.y:600 gram.y:733 gram.y:742
+#: gram.y:757 gram.y:777 gram.y:796 gram.y:959 gram.y:964 gram.y:972 gram.y:986
+#: gram.y:992 gram.y:1004 gram.y:1010 gram.y:1135 gram.y:1144 gram.y:1152
+#: gram.y:1161 gram.y:1170 gram.y:1199 gram.y:1208 gram.y:1216 gram.y:1317
+#: gram.y:1447 gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:313 lib/eventlog/eventlog.c:765
+#: lib/eventlog/eventlog.c:842 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:484
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:185
+#: logsrvd/iolog_writer.c:218 logsrvd/iolog_writer.c:228
+#: logsrvd/iolog_writer.c:257 logsrvd/iolog_writer.c:278
+#: logsrvd/iolog_writer.c:290 logsrvd/iolog_writer.c:300
+#: logsrvd/iolog_writer.c:310 logsrvd/iolog_writer.c:320
+#: logsrvd/iolog_writer.c:330 logsrvd/iolog_writer.c:342
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:1057 logsrvd/logsrvd.c:1120 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:650
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1743
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:216
+#: logsrvd/logsrvd_journal.c:217 logsrvd/logsrvd_journal.c:274
+#: logsrvd/logsrvd_journal.c:279 logsrvd/logsrvd_journal.c:439
+#: logsrvd/logsrvd_journal.c:441 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:216 logsrvd/logsrvd_local.c:278
+#: logsrvd/logsrvd_local.c:279 logsrvd/logsrvd_local.c:417
+#: logsrvd/logsrvd_local.c:468 logsrvd/logsrvd_local.c:469
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:475
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/logsrvd_relay.c:446
+#: logsrvd/logsrvd_relay.c:748 logsrvd/logsrvd_relay.c:855
+#: logsrvd/sendlog.c:256 logsrvd/sendlog.c:265 logsrvd/sendlog.c:297
+#: logsrvd/sendlog.c:303 logsrvd/sendlog.c:352 logsrvd/sendlog.c:630
+#: logsrvd/sendlog.c:1822 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/bsdauth.c:154 plugins/sudoers/auth/kerb5.c:122
+#: plugins/sudoers/auth/kerb5.c:150 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/auth/sia.c:61
+#: plugins/sudoers/canon_path.c:129 plugins/sudoers/canon_path.c:161
+#: plugins/sudoers/check_aliases.c:128 plugins/sudoers/check_util.c:56
+#: plugins/sudoers/check_util.c:84 plugins/sudoers/cvtsudoers.c:132
+#: plugins/sudoers/cvtsudoers.c:176 plugins/sudoers/cvtsudoers.c:193
+#: plugins/sudoers/cvtsudoers.c:204 plugins/sudoers/cvtsudoers.c:338
+#: plugins/sudoers/cvtsudoers.c:379 plugins/sudoers/cvtsudoers.c:399
+#: plugins/sudoers/cvtsudoers.c:545 plugins/sudoers/cvtsudoers.c:698
+#: plugins/sudoers/cvtsudoers.c:716 plugins/sudoers/cvtsudoers.c:891
+#: plugins/sudoers/cvtsudoers.c:899 plugins/sudoers/cvtsudoers.c:1395
+#: plugins/sudoers/cvtsudoers.c:1399 plugins/sudoers/cvtsudoers.c:1501
+#: plugins/sudoers/cvtsudoers_csv.c:183 plugins/sudoers/cvtsudoers_csv.c:247
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:152
+#: plugins/sudoers/cvtsudoers_ldif.c:195 plugins/sudoers/cvtsudoers_ldif.c:236
+#: plugins/sudoers/cvtsudoers_ldif.c:302 plugins/sudoers/cvtsudoers_ldif.c:378
+#: plugins/sudoers/cvtsudoers_ldif.c:432 plugins/sudoers/cvtsudoers_ldif.c:440
+#: plugins/sudoers/cvtsudoers_ldif.c:451 plugins/sudoers/cvtsudoers_ldif.c:458
+#: plugins/sudoers/cvtsudoers_ldif.c:470 plugins/sudoers/cvtsudoers_ldif.c:483
+#: plugins/sudoers/cvtsudoers_ldif.c:491 plugins/sudoers/cvtsudoers_ldif.c:638
+#: plugins/sudoers/cvtsudoers_merge.c:47 plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1158
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:212
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:694 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:294 plugins/sudoers/ldap_util.c:301
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:402
+#: plugins/sudoers/log_client.c:717 plugins/sudoers/log_client.c:739
+#: plugins/sudoers/log_client.c:744 plugins/sudoers/log_client.c:1426
+#: plugins/sudoers/log_client.c:1547 plugins/sudoers/log_client.c:1670
+#: plugins/sudoers/log_client.c:1993 plugins/sudoers/log_client.c:2052
+#: plugins/sudoers/logging.c:110 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:872 plugins/sudoers/lookup.c:338
+#: plugins/sudoers/lookup.c:355 plugins/sudoers/lookup.c:374
+#: plugins/sudoers/lookup.c:393 plugins/sudoers/lookup.c:410
+#: plugins/sudoers/lookup.c:433 plugins/sudoers/lookup.c:444
+#: plugins/sudoers/match_command.c:302 plugins/sudoers/match_command.c:574
+#: plugins/sudoers/match_command.c:641 plugins/sudoers/match_command.c:737
+#: plugins/sudoers/match_command.c:785 plugins/sudoers/match_digest.c:88
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:595
+#: plugins/sudoers/parse_ldif.c:625 plugins/sudoers/parse_ldif.c:650
+#: plugins/sudoers/parse_ldif.c:708 plugins/sudoers/parse_ldif.c:725
+#: plugins/sudoers/parse_ldif.c:753 plugins/sudoers/parse_ldif.c:760
+#: plugins/sudoers/policy.c:646 plugins/sudoers/policy.c:1061
+#: plugins/sudoers/prompt.c:94 plugins/sudoers/pwutil.c:219
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:368
+#: plugins/sudoers/pwutil.c:542 plugins/sudoers/pwutil.c:607
+#: plugins/sudoers/pwutil.c:679 plugins/sudoers/pwutil.c:877
+#: plugins/sudoers/pwutil.c:967 plugins/sudoers/pwutil.c:1015
+#: plugins/sudoers/pwutil.c:1076 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:145 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1307 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:256
+#: plugins/sudoers/testsudoers.c:265 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:164 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1095
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1320
+msgid "unable to allocate memory"
+msgstr "kan inte allokera minne"
+
+#: gram.y:624
+msgid "a digest requires a path name"
+msgstr "en kontrollsumma kräver ett sökvägsnamn"
+
+#: gram.y:646
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "värden för ”CWD” måste börja med ett ”/”, ”~” eller ”*”"
+
+#: gram.y:652
+msgid "\"CWD\" path too long"
+msgstr "”CWD”-sökväg för lång"
+
+#: gram.y:662
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "värden för ”CHROOT” måste börja med ett ”/”, ”~” eller ”*”"
+
+#: gram.y:668
+msgid "\"CHROOT\" path too long"
+msgstr "”CHROOT”-sökväg för lång"
+
+#: gram.y:817
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "syntaxfel, reserverat ord %s använt som ett aliasnamn"
+
+#: gram.y:840
+msgid "invalid notbefore value"
+msgstr "ogiltigt notbefore-värde"
+
+#: gram.y:849
+msgid "invalid notafter value"
+msgstr "ogiltigt notafter-värde"
+
+#: gram.y:859 plugins/sudoers/policy.c:390
+msgid "timeout value too large"
+msgstr "tidsgränsvärde för stort"
+
+#: gram.y:861 plugins/sudoers/policy.c:392
+msgid "invalid timeout value"
+msgstr "ogiltigt värde för tidsgräns"
+
+#: gram.y:982 plugins/sudoers/sudoers.c:1162
+msgid "command too long"
+msgstr "kommandot för långt"
+
+#: gram.y:1016
+msgid "expected a fully-qualified path name"
+msgstr "förväntade en fullständigt kvalificerad sökväg"
+
+#: gram.y:1261
+#, c-format
+msgid "%s:%d:%zu: %s\n"
+msgstr "%s:%d:%zu: %s\n"
+
+#: gram.y:1315
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Aliaset ”%s” är redan definierat"
+
+#: gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:765 lib/eventlog/eventlog.c:838
+#: lib/eventlog/eventlog.c:841 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:483
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:232
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:174
+#: logsrvd/iolog_writer.c:184 logsrvd/iolog_writer.c:197
+#: logsrvd/iolog_writer.c:217 logsrvd/iolog_writer.c:227
+#: logsrvd/iolog_writer.c:246 logsrvd/iolog_writer.c:256
+#: logsrvd/iolog_writer.c:267 logsrvd/iolog_writer.c:277
+#: logsrvd/iolog_writer.c:289 logsrvd/iolog_writer.c:299
+#: logsrvd/iolog_writer.c:309 logsrvd/iolog_writer.c:319
+#: logsrvd/iolog_writer.c:329 logsrvd/iolog_writer.c:341
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:530
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:668
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:1131
+#: logsrvd/logsrvd.c:1446 logsrvd/logsrvd.c:1453 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:649
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1742
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:125
+#: logsrvd/logsrvd_journal.c:216 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:250 logsrvd/logsrvd_journal.c:258
+#: logsrvd/logsrvd_journal.c:287 logsrvd/logsrvd_journal.c:291
+#: logsrvd/logsrvd_journal.c:439 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:278 logsrvd/logsrvd_local.c:468
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:493
+#: logsrvd/logsrvd_queue.c:158 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/sendlog.c:256 logsrvd/sendlog.c:265
+#: logsrvd/sendlog.c:297 logsrvd/sendlog.c:303 logsrvd/sendlog.c:352
+#: logsrvd/sendlog.c:630 logsrvd/sendlog.c:1523 logsrvd/sendlog.c:1530
+#: logsrvd/sendlog.c:1753 logsrvd/sendlog.c:1822 logsrvd/tls_init.c:305
+#: logsrvd/tls_init.c:329 logsrvd/tls_init.c:340 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/pam.c:518 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/canon_path.c:129
+#: plugins/sudoers/canon_path.c:161 plugins/sudoers/check_aliases.c:128
+#: plugins/sudoers/check_util.c:56 plugins/sudoers/check_util.c:84
+#: plugins/sudoers/cvtsudoers.c:132 plugins/sudoers/cvtsudoers.c:175
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:203
+#: plugins/sudoers/cvtsudoers.c:337 plugins/sudoers/cvtsudoers.c:544
+#: plugins/sudoers/cvtsudoers.c:697 plugins/sudoers/cvtsudoers.c:715
+#: plugins/sudoers/cvtsudoers.c:891 plugins/sudoers/cvtsudoers.c:898
+#: plugins/sudoers/cvtsudoers.c:1395 plugins/sudoers/cvtsudoers.c:1399
+#: plugins/sudoers/cvtsudoers.c:1501 plugins/sudoers/cvtsudoers_csv.c:182
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:151 plugins/sudoers/cvtsudoers_ldif.c:194
+#: plugins/sudoers/cvtsudoers_ldif.c:235 plugins/sudoers/cvtsudoers_ldif.c:301
+#: plugins/sudoers/cvtsudoers_ldif.c:377 plugins/sudoers/cvtsudoers_ldif.c:431
+#: plugins/sudoers/cvtsudoers_ldif.c:439 plugins/sudoers/cvtsudoers_ldif.c:450
+#: plugins/sudoers/cvtsudoers_ldif.c:457 plugins/sudoers/cvtsudoers_ldif.c:469
+#: plugins/sudoers/cvtsudoers_ldif.c:482 plugins/sudoers/cvtsudoers_ldif.c:490
+#: plugins/sudoers/cvtsudoers_ldif.c:637 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51 plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1157
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:211
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:693 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:293 plugins/sudoers/ldap_util.c:300
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:228
+#: plugins/sudoers/log_client.c:250 plugins/sudoers/log_client.c:264
+#: plugins/sudoers/log_client.c:402 plugins/sudoers/log_client.c:717
+#: plugins/sudoers/log_client.c:739 plugins/sudoers/log_client.c:744
+#: plugins/sudoers/log_client.c:1426 plugins/sudoers/log_client.c:1547
+#: plugins/sudoers/log_client.c:1670 plugins/sudoers/log_client.c:1993
+#: plugins/sudoers/log_client.c:2052 plugins/sudoers/logging.c:110
+#: plugins/sudoers/logging.c:189 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:755 plugins/sudoers/logging.c:872
+#: plugins/sudoers/logging.c:925 plugins/sudoers/logging.c:932
+#: plugins/sudoers/lookup.c:337 plugins/sudoers/lookup.c:354
+#: plugins/sudoers/lookup.c:373 plugins/sudoers/lookup.c:392
+#: plugins/sudoers/lookup.c:409 plugins/sudoers/lookup.c:432
+#: plugins/sudoers/lookup.c:443 plugins/sudoers/match_command.c:301
+#: plugins/sudoers/match_command.c:573 plugins/sudoers/match_command.c:640
+#: plugins/sudoers/match_command.c:737 plugins/sudoers/match_command.c:784
+#: plugins/sudoers/match_digest.c:88 plugins/sudoers/parse_ldif.c:152
+#: plugins/sudoers/parse_ldif.c:183 plugins/sudoers/parse_ldif.c:252
+#: plugins/sudoers/parse_ldif.c:260 plugins/sudoers/parse_ldif.c:265
+#: plugins/sudoers/parse_ldif.c:341 plugins/sudoers/parse_ldif.c:352
+#: plugins/sudoers/parse_ldif.c:379 plugins/sudoers/parse_ldif.c:396
+#: plugins/sudoers/parse_ldif.c:408 plugins/sudoers/parse_ldif.c:412
+#: plugins/sudoers/parse_ldif.c:426 plugins/sudoers/parse_ldif.c:484
+#: plugins/sudoers/parse_ldif.c:595 plugins/sudoers/parse_ldif.c:624
+#: plugins/sudoers/parse_ldif.c:649 plugins/sudoers/parse_ldif.c:707
+#: plugins/sudoers/parse_ldif.c:724 plugins/sudoers/parse_ldif.c:752
+#: plugins/sudoers/parse_ldif.c:759 plugins/sudoers/policy.c:157
+#: plugins/sudoers/policy.c:166 plugins/sudoers/policy.c:175
+#: plugins/sudoers/policy.c:204 plugins/sudoers/policy.c:374
+#: plugins/sudoers/policy.c:390 plugins/sudoers/policy.c:392
+#: plugins/sudoers/policy.c:430 plugins/sudoers/policy.c:439
+#: plugins/sudoers/policy.c:448 plugins/sudoers/policy.c:457
+#: plugins/sudoers/policy.c:493 plugins/sudoers/policy.c:502
+#: plugins/sudoers/policy.c:511 plugins/sudoers/policy.c:520
+#: plugins/sudoers/policy.c:529 plugins/sudoers/policy.c:538
+#: plugins/sudoers/policy.c:547 plugins/sudoers/policy.c:646
+#: plugins/sudoers/policy.c:1061 plugins/sudoers/prompt.c:94
+#: plugins/sudoers/pwutil.c:219 plugins/sudoers/pwutil.c:290
+#: plugins/sudoers/pwutil.c:368 plugins/sudoers/pwutil.c:542
+#: plugins/sudoers/pwutil.c:607 plugins/sudoers/pwutil.c:679
+#: plugins/sudoers/pwutil.c:877 plugins/sudoers/pwutil.c:967
+#: plugins/sudoers/pwutil.c:1015 plugins/sudoers/pwutil.c:1076
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1306 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:255
+#: plugins/sudoers/testsudoers.c:264 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:163 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1094
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1309 toke.l:1320
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:304
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "kan inte duplicera stdin: %m"
+
+#: lib/eventlog/eventlog.c:346
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "kan inte köra %s: %m"
+
+#: lib/eventlog/eventlog.c:394 plugins/sudoers/auth/aix_auth.c:199
+msgid "unable to fork"
+msgstr "kan inte grena process"
+
+#: lib/eventlog/eventlog.c:404 lib/eventlog/eventlog.c:471
+#, c-format
+msgid "unable to fork: %m"
+msgstr "kan inte grena process: %m"
+
+#: lib/eventlog/eventlog.c:461
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "kan inte öppna rör: %m"
+
+#: lib/eventlog/eventlog.c:1000
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:1029
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (kommando fortsätter) %s"
+
+#: lib/eventlog/parse_json.c:175
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "förväntade JSON_STRING, fick %d"
+
+#: lib/eventlog/parse_json.c:180
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY för stor"
+
+#: lib/eventlog/parse_json.c:506
+msgid "missing double quote in name"
+msgstr "saknar citationstecken i namn"
+
+#: lib/eventlog/parse_json.c:624
+msgid "missing JSON_OBJECT"
+msgstr "saknar JSON_OBJECT"
+
+#: lib/eventlog/parse_json.c:628
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "förväntade JSON_OBJECT, fick %d"
+
+#: lib/eventlog/parse_json.c:762
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "json-stack utarmad (max %u ramar)"
+
+#: lib/eventlog/parse_json.c:840
+msgid "objects must consist of name:value pairs"
+msgstr "objekt måste bestå av namn:värde-par"
+
+#: lib/eventlog/parse_json.c:845 lib/eventlog/parse_json.c:876
+#: lib/eventlog/parse_json.c:920 lib/eventlog/parse_json.c:942
+#: lib/eventlog/parse_json.c:964 lib/eventlog/parse_json.c:986
+#: lib/eventlog/parse_json.c:1008
+msgid "missing separator between values"
+msgstr "saknar separator mellan värden"
+
+#: lib/eventlog/parse_json.c:860 lib/eventlog/parse_json.c:1034
+msgid "unmatched close brace"
+msgstr "omatchad avslutningsklammerparentes"
+
+#: lib/eventlog/parse_json.c:871
+msgid "unexpected array"
+msgstr "oväntad array"
+
+#: lib/eventlog/parse_json.c:891 lib/eventlog/parse_json.c:1037
+msgid "unmatched close bracket"
+msgstr "omatchad avslutningsklammer"
+
+#: lib/eventlog/parse_json.c:902
+msgid "unexpected string"
+msgstr "oväntad sträng"
+
+#: lib/eventlog/parse_json.c:913
+msgid "missing colon after name"
+msgstr "saknar kolon efter namn"
+
+#: lib/eventlog/parse_json.c:934 lib/eventlog/parse_json.c:956
+msgid "unexpected boolean"
+msgstr "oväntad boolean"
+
+#: lib/eventlog/parse_json.c:978
+msgid "unexpected null"
+msgstr "oväntat null"
+
+#: lib/eventlog/parse_json.c:999
+msgid "unexpected number"
+msgstr "oväntat nummer"
+
+#: lib/eventlog/parse_json.c:1045
+msgid "parse error"
+msgstr "tolkningsfel"
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1290
+#: plugins/sudoers/sudoreplay.c:1291 plugins/sudoers/sudoreplay.c:1587
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr "ogiltigt reguljärt uttryck ”%s”: %s"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: ogiltig loggfil"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: tidsstämpelfält saknas"
+
+#: lib/iolog/iolog_legacy.c:90
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: tidsstämpel %s: %s"
+
+#: lib/iolog/iolog_legacy.c:97
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: användarfältet saknas"
+
+#: lib/iolog/iolog_legacy.c:108
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: runas-användarfältet saknas"
+
+#: lib/iolog/iolog_legacy.c:119
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: runas-gruppfältet saknas"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s finns men är inte en katalog (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:124 lib/iolog/iolog_mkdtemp.c:80
+#: logsrvd/iolog_writer.c:795 plugins/sudoers/timestamp.c:218
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "kan inte skapa katalogen %s"
+
+#: lib/iolog/iolog_mkdtemp.c:85 plugins/sudoers/visudo.c:769
+#: plugins/sudoers/visudo.c:803 plugins/sudoers/visudo.c:809
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "kan inte ändra läge för %s till 0%o"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "fel vid inläsning av tidsmätningsfil: %s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "ogiltig rad i tidsmätningsfil: %s"
+
+#: logsrvd/iolog_writer.c:65
+#, c-format
+msgid "%s: protocol error: NULL key"
+msgstr "%s: protokollfel: NULL-nyckel"
+
+#: logsrvd/iolog_writer.c:69
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s: protokollfel: fel typ för %s"
+
+#: logsrvd/iolog_writer.c:74 logsrvd/logsrvd_local.c:109
+#: logsrvd/logsrvd_local.c:123 logsrvd/logsrvd_local.c:131
+#: logsrvd/logsrvd_local.c:149
+#, c-format
+msgid "%s: protocol error: NULL value found in %s"
+msgstr "%s: protokollfel: NULL-värde hittat i %s"
+
+#: logsrvd/iolog_writer.c:141 plugins/sudoers/logging.c:1024
+#: plugins/sudoers/policy.c:613
+msgid "unable to generate UUID"
+msgstr "kan inte generera UUID"
+
+#: logsrvd/iolog_writer.c:354 logsrvd/iolog_writer.c:359
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:369
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s: protokollfel: %s saknas i AcceptMessage"
+
+#: logsrvd/iolog_writer.c:430
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s: kan inte formattera sessions-id"
+
+#: logsrvd/iolog_writer.c:444 logsrvd/iolog_writer.c:458
+#: logsrvd/iolog_writer.c:472 logsrvd/iolog_writer.c:487
+#: logsrvd/iolog_writer.c:501 logsrvd/iolog_writer.c:515
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s: %s: är inte satt"
+
+#: logsrvd/iolog_writer.c:551 logsrvd/iolog_writer.c:558
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr "kan inte öppna iolog-sökväg %s"
+
+#: logsrvd/iolog_writer.c:576
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr "kan inte skapa iolog-sökväg %s"
+
+#: logsrvd/iolog_writer.c:606
+#, c-format
+msgid "invalid iofd %d"
+msgstr "ogiltig iofd %d"
+
+#: logsrvd/iolog_writer.c:626
+#, c-format
+msgid "error closing iofd %u: %s"
+msgstr "fel vid stängning av iofd %u: %s"
+
+#: logsrvd/iolog_writer.c:647
+#, c-format
+msgid "error flushing iofd %u: %s"
+msgstr "fel vid tömning av iofd %u: %s"
+
+#: logsrvd/iolog_writer.c:765
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "ogiltig I/O-logg %s: %s refererad men inte närvarande"
+
+#: logsrvd/iolog_writer.c:777 logsrvd/logsrvd_journal.c:391
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "%s: kan inte hitta omstartspunkt [%lld, %ld]"
+
+#: logsrvd/iolog_writer.c:799 logsrvd/logsrvd_journal.c:434
+#: logsrvd/logsrvd_queue.c:115 logsrvd/tls_init.c:256
+#: plugins/sudoers/check.c:285 plugins/sudoers/cvtsudoers.c:758
+#: plugins/sudoers/cvtsudoers.c:780 plugins/sudoers/cvtsudoers.c:1461
+#: plugins/sudoers/cvtsudoers_csv.c:697 plugins/sudoers/cvtsudoers_json.c:902
+#: plugins/sudoers/cvtsudoers_ldif.c:711 plugins/sudoers/sudoers.c:1291
+#: plugins/sudoers/sudoers.c:1317 plugins/sudoers/sudoreplay.c:1497
+#: plugins/sudoers/timestamp.c:478 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:990
+#, c-format
+msgid "unable to open %s"
+msgstr "kan inte öppna %s"
+
+#: logsrvd/iolog_writer.c:811 logsrvd/logsrv_util.c:111
+#: logsrvd/logsrv_util.c:118 plugins/sudoers/sudoreplay.c:355
+#: plugins/sudoers/sudoreplay.c:361
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "kan inte öppna %s/%s"
+
+#: logsrvd/iolog_writer.c:824
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "kan inte kopiera %s/%s till %s/%s: %s"
+
+#: logsrvd/iolog_writer.c:853 logsrvd/logsrvd_journal.c:198
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "kan inte byta namn på %s till %s"
+
+#: logsrvd/logsrv_util.c:153 logsrvd/logsrv_util.c:182
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s: kan inte hitta omstartspunkt [%lld, %ld]"
+
+#: logsrvd/logsrv_util.c:165
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "saknar I/O-loggfil %s/%s"
+
+#: logsrvd/logsrv_util.c:172
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s: kan inte söka framåt %zu"
+
+#: logsrvd/logsrvd.c:271 logsrvd/logsrvd_queue.c:135
+msgid "unable to connect to relay"
+msgstr "kan inte ansluta till relä"
+
+#: logsrvd/logsrvd.c:338 logsrvd/logsrvd_relay.c:847
+#, c-format
+msgid "server message too large: %zu"
+msgstr "servermeddelande för långt: %zu"
+
+#: logsrvd/logsrvd.c:430 logsrvd/logsrvd.c:553 logsrvd/logsrvd.c:639
+#: logsrvd/logsrvd.c:881 logsrvd/logsrvd.c:895 logsrvd/logsrvd.c:1056
+#: logsrvd/logsrvd.c:1181 logsrvd/logsrvd.c:1354 logsrvd/logsrvd.c:1372
+#: logsrvd/logsrvd.c:1471 logsrvd/logsrvd.c:1596 logsrvd/logsrvd.c:1783
+#: logsrvd/logsrvd_journal.c:503 logsrvd/logsrvd_local.c:238
+#: logsrvd/logsrvd_queue.c:164 logsrvd/logsrvd_relay.c:172
+#: logsrvd/logsrvd_relay.c:249 logsrvd/logsrvd_relay.c:253
+#: logsrvd/logsrvd_relay.c:391 logsrvd/logsrvd_relay.c:583
+#: logsrvd/logsrvd_relay.c:747 logsrvd/logsrvd_relay.c:1137
+#: logsrvd/sendlog.c:1308 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:216 plugins/sudoers/audit.c:281
+#: plugins/sudoers/iolog.c:1041 plugins/sudoers/iolog.c:1175
+#: plugins/sudoers/iolog.c:1274 plugins/sudoers/log_client.c:121
+#: plugins/sudoers/log_client.c:343 plugins/sudoers/log_client.c:359
+#: plugins/sudoers/log_client.c:407 plugins/sudoers/log_client.c:613
+#: plugins/sudoers/log_client.c:620 plugins/sudoers/log_client.c:1114
+#: plugins/sudoers/log_client.c:1395 plugins/sudoers/log_client.c:1436
+#: plugins/sudoers/log_client.c:1444 plugins/sudoers/log_client.c:1603
+#: plugins/sudoers/log_client.c:1728 plugins/sudoers/log_client.c:2060
+#: plugins/sudoers/log_client.c:2068 plugins/sudoers/logging.c:148
+#: plugins/sudoers/logging.c:206 plugins/sudoers/sudoreplay.c:519
+#: plugins/sudoers/sudoreplay.c:566 plugins/sudoers/sudoreplay.c:808
+#: plugins/sudoers/sudoreplay.c:920 plugins/sudoers/sudoreplay.c:1011
+#: plugins/sudoers/sudoreplay.c:1026 plugins/sudoers/sudoreplay.c:1033
+#: plugins/sudoers/sudoreplay.c:1040 plugins/sudoers/sudoreplay.c:1047
+#: plugins/sudoers/sudoreplay.c:1054 plugins/sudoers/sudoreplay.c:1182
+msgid "unable to add event to queue"
+msgstr "kan inte lägga till händelse till kö"
+
+#: logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:491 logsrvd/logsrvd.c:523
+#: logsrvd/logsrvd.c:577 logsrvd/logsrvd.c:656 logsrvd/logsrvd.c:692
+#: logsrvd/logsrvd.c:728 logsrvd/logsrvd.c:764 logsrvd/logsrvd_relay.c:512
+#: logsrvd/logsrvd_relay.c:545
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr "oväntat tillstånd %d för %s"
+
+#: logsrvd/logsrvd.c:455 logsrvd/logsrvd.c:492 logsrvd/logsrvd.c:524
+#: logsrvd/logsrvd.c:578 logsrvd/logsrvd.c:657 logsrvd/logsrvd.c:693
+#: logsrvd/logsrvd.c:729 logsrvd/logsrvd.c:765 logsrvd/logsrvd_relay.c:514
+#: logsrvd/logsrvd_relay.c:547
+msgid "state machine error"
+msgstr "fel i tillståndsmaskin"
+
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:462
+msgid "invalid AcceptMessage"
+msgstr "ogiltigt AcceptMessage"
+
+#: logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:499
+msgid "invalid RejectMessage"
+msgstr "ogiltigt RejectMessage"
+
+#: logsrvd/logsrvd.c:530 logsrvd/logsrvd.c:531
+msgid "invalid ExitMessage"
+msgstr "ogiltigt ExitMessage"
+
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:585
+msgid "invalid RestartMessage"
+msgstr "ogiltigt RestartMessage"
+
+#: logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:620
+msgid "invalid AlertMessage"
+msgstr "ogiltigt AlertMessage"
+
+#: logsrvd/logsrvd.c:661 logsrvd/logsrvd.c:697 logsrvd/logsrvd.c:733
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s: oväntad IoBuffer"
+
+#: logsrvd/logsrvd.c:662 logsrvd/logsrvd.c:698 logsrvd/logsrvd.c:734
+msgid "protocol error"
+msgstr "protokollfel"
+
+#: logsrvd/logsrvd.c:668 logsrvd/logsrvd.c:669
+msgid "invalid IoBuffer"
+msgstr "ogiltig IoBuffer"
+
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:705
+msgid "invalid ChangeWindowSize"
+msgstr "ogiltig ChangeWindowSize"
+
+#: logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:741
+msgid "invalid CommandSuspend"
+msgstr "ogiltig CommandSuspend"
+
+#: logsrvd/logsrvd.c:790 logsrvd/logsrvd_journal.c:302
+#: logsrvd/logsrvd_relay.c:654 logsrvd/sendlog.c:1207
+#: plugins/sudoers/log_client.c:1593
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "kan inte packa upp %s storlek %zu"
+
+#: logsrvd/logsrvd.c:835 logsrvd/logsrvd_journal.c:376
+#: logsrvd/logsrvd_relay.c:678
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "oväntat type_case-värde %d i %s från %s"
+
+#: logsrvd/logsrvd.c:837
+msgid "unrecognized ClientMessage type"
+msgstr "okänd ClientMessage-typ"
+
+#: logsrvd/logsrvd.c:927
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "tidsgräns passerad vid skrivning till klient %s"
+
+#: logsrvd/logsrvd.c:932 logsrvd/logsrvd_relay.c:919 logsrvd/sendlog.c:1413
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr "saknar skrivbuffert för klient %s"
+
+#: logsrvd/logsrvd.c:1027
+#, c-format
+msgid "timed out reading from client %s"
+msgstr "tidsgräns passerad vid läsning från klient %s"
+
+#: logsrvd/logsrvd.c:1068 logsrvd/logsrvd_relay.c:782
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr "EOF från %s utan korrekt TLS-nedstängning"
+
+#: logsrvd/logsrvd.c:1112 logsrvd/logsrvd_relay.c:205 logsrvd/sendlog.c:336
+#: plugins/sudoers/log_client.c:723
+#, c-format
+msgid "client message too large: %zu"
+msgstr "klientmeddelande för stort: %zu"
+
+#: logsrvd/logsrvd.c:1113 logsrvd/logsrvd_journal.c:259
+#: logsrvd/logsrvd_journal.c:260
+msgid "client message too large"
+msgstr "klientmeddelande för stort"
+
+#: logsrvd/logsrvd.c:1131 logsrvd/logsrvd.c:1132
+msgid "invalid ClientMessage"
+msgstr "ogiltigt ClientMessage"
+
+#: logsrvd/logsrvd.c:1432
+msgid "unable to get remote IP addr"
+msgstr "kan inte hämta fjärr-IP-adress"
+
+#: logsrvd/logsrvd.c:1463 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:281
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "Kan inte fästa användardata på ssl-objektet: %s"
+
+#: logsrvd/logsrvd.c:1646 logsrvd/logsrvd.c:2007
+msgid "unable to setup listen socket"
+msgstr "det går inte att ställa in lyssningsuttag"
+
+#: logsrvd/logsrvd.c:1766
+#, c-format
+msgid "unexpected signal %d"
+msgstr "oväntad signal %d"
+
+#: logsrvd/logsrvd.c:1909
+msgid "sudo log server"
+msgstr "sudo-loggserver"
+
+#: logsrvd/logsrvd.c:1911 logsrvd/sendlog.c:126
+msgid "Options:"
+msgstr "Alternativ:"
+
+#: logsrvd/logsrvd.c:1913
+msgid "path to configuration file"
+msgstr "sökväg till konfigurationsfil"
+
+#: logsrvd/logsrvd.c:1915 logsrvd/sendlog.c:128
+msgid "display help message and exit"
+msgstr "visa hjälpmeddelande och avsluta"
+
+#: logsrvd/logsrvd.c:1917
+msgid "do not fork, run in the foreground"
+msgstr "grena inte, kör i förgrunden"
+
+#: logsrvd/logsrvd.c:1919
+msgid "percent chance connections will drop"
+msgstr "procents chans att anslutningar slängs"
+
+#: logsrvd/logsrvd.c:1921 logsrvd/sendlog.c:158
+msgid "display version information and exit"
+msgstr "visa versionsinformation och avsluta"
+
+#: logsrvd/logsrvd.c:1971 logsrvd/sendlog.c:1722
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "Protobuf-C version 1.3 eller högre krävs"
+
+#: logsrvd/logsrvd.c:1987
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "ogiltigt slumpmässigt avbrottsvärde: %s"
+
+#: logsrvd/logsrvd.c:1990 logsrvd/sendlog.c:1776
+#: plugins/sudoers/cvtsudoers.c:250 plugins/sudoers/sudoreplay.c:294
+#: plugins/sudoers/visudo.c:181
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s version %s\n"
+
+#: logsrvd/logsrvd_conf.c:422 plugins/sudoers/check.c:69
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/sudoers.c:419 plugins/sudoers/sudoers.c:929
+#: plugins/sudoers/sudoers.c:1034 plugins/sudoers/sudoers.c:1424
+#: plugins/sudoers/testsudoers.c:169 plugins/sudoers/testsudoers.c:285
+#: plugins/sudoers/testsudoers.c:459
+#, c-format
+msgid "unknown user %s"
+msgstr "okänd användare %s"
+
+#: logsrvd/logsrvd_conf.c:439 plugins/sudoers/iolog.c:148
+#: plugins/sudoers/sudoers.c:425 plugins/sudoers/sudoers.c:1458
+#: plugins/sudoers/testsudoers.c:483
+#, c-format
+msgid "unknown group %s"
+msgstr "okänd grupp %s"
+
+#: logsrvd/logsrvd_conf.c:457
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr "kan inte tolka iolog-läge %s"
+
+#: logsrvd/logsrvd_conf.c:474 logsrvd/logsrvd_conf.c:1243
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "ogiltigt värde för %s: %s"
+
+#: logsrvd/logsrvd_conf.c:527
+msgid "TLS not supported"
+msgstr "TLS stöds inte"
+
+#: logsrvd/logsrvd_conf.c:549
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:622 logsrvd/logsrvd_conf.c:1032
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s: inte fullständigt kvalificerad sökväg"
+
+#: logsrvd/logsrvd_conf.c:951 logsrvd/logsrvd_conf.c:967
+#: logsrvd/logsrvd_conf.c:1676
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "okänd syslog-funktionalitet: %s"
+
+#: logsrvd/logsrvd_conf.c:983 logsrvd/logsrvd_conf.c:999
+#: logsrvd/logsrvd_conf.c:1015 logsrvd/logsrvd_conf.c:1680
+#: logsrvd/logsrvd_conf.c:1684 logsrvd/logsrvd_conf.c:1688
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "okänd syslog-prioritet: %s"
+
+#: logsrvd/logsrvd_conf.c:1197
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d omatchad ”[”: %s"
+
+#: logsrvd/logsrvd_conf.c:1203
+#, c-format
+msgid "%s:%d garbage after ']': %s"
+msgstr "%s:%d skräp eft ”]”: %s"
+
+#: logsrvd/logsrvd_conf.c:1215
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s:%d ogiltigt konfigurationsavsnitt: %s"
+
+#: logsrvd/logsrvd_conf.c:1223
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d ogiltig konfigurationsrad: %s"
+
+#: logsrvd/logsrvd_conf.c:1229
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d avsnittsnamn förväntades: %s"
+
+#: logsrvd/logsrvd_conf.c:1251
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] ogiltig nyckel: %s"
+
+#: logsrvd/logsrvd_conf.c:1281 plugins/sudoers/cvtsudoers.c:273
+#: plugins/sudoers/logging.c:1076
+#, c-format
+msgid "unable to open log file %s"
+msgstr "kan inte öppna loggfil %s"
+
+#: logsrvd/logsrvd_conf.c:1763
+msgid "unable to initialize server TLS context"
+msgstr "kan inte initiera TLS-serverkontext"
+
+#: logsrvd/logsrvd_conf.c:1783
+msgid "unable to initialize relay TLS context"
+msgstr "kan inte initiera TLS-reläkontext"
+
+#: logsrvd/logsrvd_journal.c:149 logsrvd/logsrvd_journal.c:430
+#: logsrvd/logsrvd_journal.c:435
+msgid "unable to create journal file"
+msgstr "kan inte skapa journalfil"
+
+#: logsrvd/logsrvd_journal.c:153 logsrvd/logsrvd_queue.c:109
+#: plugins/sudoers/visudo.c:1046
+#, c-format
+msgid "unable to lock %s"
+msgstr "kan inte låsa %s"
+
+#: logsrvd/logsrvd_journal.c:156
+msgid "unable to lock journal file"
+msgstr "kan inte låsa journalfil"
+
+#: logsrvd/logsrvd_journal.c:164
+msgid "unable to open journal file"
+msgstr "kan inte öppna journalfil"
+
+#: logsrvd/logsrvd_journal.c:185 logsrvd/logsrvd_journal.c:466
+#: logsrvd/logsrvd_journal.c:471
+msgid "unable to write journal file"
+msgstr "kan inte skriva journalfil"
+
+#: logsrvd/logsrvd_journal.c:193 logsrvd/logsrvd_journal.c:200
+msgid "unable to rename journal file"
+msgstr "kan inte byta namn på journalfil"
+
+#: logsrvd/logsrvd_journal.c:247 logsrvd/logsrvd_journal.c:248
+#: logsrvd/logsrvd_journal.c:288 logsrvd/logsrvd_journal.c:289
+msgid "unexpected EOF reading journal file"
+msgstr "oväntat filslut vid läsning av journalfil"
+
+#: logsrvd/logsrvd_journal.c:251 logsrvd/logsrvd_journal.c:252
+#: logsrvd/logsrvd_journal.c:292 logsrvd/logsrvd_journal.c:293
+msgid "error reading journal file"
+msgstr "fel vid inläsning av journalfil"
+
+#: logsrvd/logsrvd_journal.c:304 logsrvd/logsrvd_journal.c:390
+msgid "invalid journal file, unable to restart"
+msgstr "ogiltig journalfil, kunde inte starta om"
+
+#: logsrvd/logsrvd_journal.c:449
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "kan inte söka till [%lld, %ld] i journalfil %s"
+
+#: logsrvd/logsrvd_local.c:166
+#, c-format
+msgid "unexpected value_case %d in %s from %s"
+msgstr "oväntat value_case %d i %s från %s"
+
+#: logsrvd/logsrvd_local.c:194
+msgid "error parsing AcceptMessage"
+msgstr "fel vid tolkning av AcceptMessage"
+
+#: logsrvd/logsrvd_local.c:205
+msgid "error creating I/O log"
+msgstr "fel vid skapande av I/O-logg"
+
+#: logsrvd/logsrvd_local.c:228
+msgid "error logging accept event"
+msgstr "fel vid loggning av acceptanshändelse"
+
+#: logsrvd/logsrvd_local.c:267
+msgid "error parsing RejectMessage"
+msgstr "fel vid tolkning av RejectMessage"
+
+#: logsrvd/logsrvd_local.c:291
+msgid "error logging reject event"
+msgstr "fel vid loggning av avböjningshändelse"
+
+#: logsrvd/logsrvd_local.c:427 logsrvd/logsrvd_local.c:437
+msgid "error logging exit event"
+msgstr "fel vid loggning av avslutningshändelse"
+
+#: logsrvd/logsrvd_local.c:494 logsrvd/logsrvd_local.c:495
+msgid "log is already complete, cannot be restarted"
+msgstr "logg är redan komplett, kan inte startas om"
+
+#: logsrvd/logsrvd_local.c:525
+msgid "unable to restart log"
+msgstr "kan inte starta om logg"
+
+#: logsrvd/logsrvd_local.c:541
+msgid "error parsing AlertMessage"
+msgstr "fel vid tolkning av AlertMessage"
+
+#: logsrvd/logsrvd_local.c:551
+msgid "error logging alert event"
+msgstr "fel vid loggning av alarmhändelse"
+
+#: logsrvd/logsrvd_local.c:587 logsrvd/logsrvd_local.c:650
+#: logsrvd/logsrvd_local.c:685
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr "kan inte formatera tidsbuffert, längd %d"
+
+#: logsrvd/logsrvd_local.c:601 logsrvd/logsrvd_local.c:609
+#: logsrvd/logsrvd_local.c:657 logsrvd/logsrvd_local.c:692
+#: plugins/sudoers/sudoreplay.c:344 toke.l:981 toke.l:984
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: logsrvd/logsrvd_local.c:620
+msgid "randomly dropping connection"
+msgstr "släpper slumpmässigt anslutningen"
+
+#: logsrvd/logsrvd_local.c:632
+msgid "error writing IoBuffer"
+msgstr "fel vid skrivning av IoBuffer"
+
+#: logsrvd/logsrvd_local.c:667
+msgid "error writing ChangeWindowSize"
+msgstr "fel vid skrivning av ChangeWindowSize"
+
+#: logsrvd/logsrvd_local.c:702
+msgid "error writing CommandSuspend"
+msgstr "fel vid skrivning av CommandSuspend"
+
+#: logsrvd/logsrvd_relay.c:437
+msgid "TLS handshake with relay host failed"
+msgstr "TLS-handskakning med relävärd misslyckades"
+
+#: logsrvd/logsrvd_relay.c:465
+msgid "unable to connect to relay host"
+msgstr "kan inte ansluta till relävärd"
+
+#: logsrvd/logsrvd_relay.c:520
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s: ogiltigt ServerHello, saknar server_id"
+
+#: logsrvd/logsrvd_relay.c:522 logsrvd/sendlog.c:1111
+#: plugins/sudoers/log_client.c:1479
+msgid "invalid ServerHello"
+msgstr "ogiltigt ServerHello"
+
+#: logsrvd/logsrvd_relay.c:681
+msgid "unrecognized ServerMessage type"
+msgstr "okänd ServerMessage-typ"
+
+#: logsrvd/logsrvd_relay.c:710
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr "tidsgräns passerad vid läsning från relä %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:712
+msgid "timeout reading from relay"
+msgstr "tidsgräns passerad vid läsning från relä"
+
+#: logsrvd/logsrvd_relay.c:767
+msgid "relay host name does not match certificate"
+msgstr "relävärdnamnet matchar inte certifikatet"
+
+#: logsrvd/logsrvd_relay.c:773 logsrvd/logsrvd_relay.c:787
+#: logsrvd/logsrvd_relay.c:794
+msgid "error reading from relay"
+msgstr "fel vid läsning från relä"
+
+#: logsrvd/logsrvd_relay.c:815
+msgid "unable to read from relay"
+msgstr "kan inte läsa från relä"
+
+#: logsrvd/logsrvd_relay.c:830 logsrvd/logsrvd_relay.c:949
+msgid "relay server closed connection"
+msgstr "reläserver stängde anslutningen"
+
+#: logsrvd/logsrvd_relay.c:848
+msgid "server message too large"
+msgstr "servermeddelandet för stort"
+
+#: logsrvd/logsrvd_relay.c:912
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr "tidsgräns passerad vid skrivning till relä %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:914
+msgid "timeout writing to relay"
+msgstr "tidsgräns passerad vid skrivning till relä"
+
+#: logsrvd/logsrvd_relay.c:968 logsrvd/logsrvd_relay.c:975
+#: logsrvd/logsrvd_relay.c:987
+msgid "error writing to relay"
+msgstr "fel vid skrivning till relä"
+
+#: logsrvd/sendlog.c:124
+msgid "send sudo I/O log to remote server"
+msgstr "skicka sudo I/O-logg till fjärrserver"
+
+#: logsrvd/sendlog.c:130
+msgid "only send an accept event (no I/O)"
+msgstr "skicka endast en accepteringshändelse (ingen I/O)"
+
+#: logsrvd/sendlog.c:133
+msgid "certificate bundle file to verify server's cert against"
+msgstr "certifikatbuntfil för att verifiera serverns certifikat mot"
+
+#: logsrvd/sendlog.c:135
+msgid "certificate file for TLS handshake"
+msgstr "certifikatfil för TLS-handskakning"
+
+#: logsrvd/sendlog.c:138
+msgid "host to send logs to"
+msgstr "värd att skicka loggar till"
+
+#: logsrvd/sendlog.c:140
+msgid "remote ID of I/O log to be resumed"
+msgstr "fjärr-ID för I/O-logg som ska återupptas"
+
+#: logsrvd/sendlog.c:143
+msgid "private key file"
+msgstr "privat nyckelfil"
+
+#: logsrvd/sendlog.c:145
+msgid "do not verify server certificate"
+msgstr "verifiera inte servercertifikat"
+
+#: logsrvd/sendlog.c:148
+msgid "port to use when connecting to host"
+msgstr "port som ska användas när du ansluter till värd"
+
+#: logsrvd/sendlog.c:150
+msgid "restart previous I/O log transfer"
+msgstr "starta om tidigare I/O-loggöverföring"
+
+#: logsrvd/sendlog.c:152
+msgid "reject the command with the given reason"
+msgstr "avvisa kommandot med angiven anledning"
+
+#: logsrvd/sendlog.c:154
+msgid "stop transfer after reaching this time"
+msgstr "stoppa överföring efter att ha nått denna tid"
+
+#: logsrvd/sendlog.c:156
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "testa granskningsservern genom att skicka utvalda I/O-loggar n gånger parallellt"
+
+#: logsrvd/sendlog.c:181 plugins/sudoers/log_client.c:453
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "kan inte slå upp %s:%s: %s"
+
+#: logsrvd/sendlog.c:219
+msgid "unable to get server IP addr"
+msgstr "kan inte hämta server-IP-adress"
+
+#: logsrvd/sendlog.c:314 plugins/sudoers/sudoreplay.c:868
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "kan inte läsa %s/%s: %s"
+
+#: logsrvd/sendlog.c:1035 plugins/sudoers/iolog.c:959
+#: plugins/sudoers/iolog.c:1034
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "oväntad I/O-händelse %d"
+
+#: logsrvd/sendlog.c:1088 logsrvd/sendlog.c:1105 logsrvd/sendlog.c:1139
+#: plugins/sudoers/log_client.c:1129 plugins/sudoers/log_client.c:1405
+#: plugins/sudoers/log_client.c:1473 plugins/sudoers/log_client.c:1512
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: oväntat tillstånd %d"
+
+#: logsrvd/sendlog.c:1175 plugins/sudoers/log_client.c:1561
+#, c-format
+msgid "error message received from server: %s"
+msgstr "felmeddelande mottaget från server: %s"
+
+#: logsrvd/sendlog.c:1188 plugins/sudoers/log_client.c:1574
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "avbrottsmeddelande mottaget från server: %s"
+
+#: logsrvd/sendlog.c:1247 plugins/sudoers/log_client.c:1624
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s: oväntat type_case-värde %d"
+
+#: logsrvd/sendlog.c:1276
+msgid "timeout reading from server"
+msgstr "tidsgräns passerad vid läsning från server"
+
+#: logsrvd/sendlog.c:1327 plugins/sudoers/log_client.c:1747
+msgid "host name does not match certificate"
+msgstr "värdnamn matchar inte certifikat"
+
+#: logsrvd/sendlog.c:1361
+msgid "premature EOF"
+msgstr "oväntad EOF"
+
+#: logsrvd/sendlog.c:1374 plugins/sudoers/log_client.c:1795
+#, c-format
+msgid "server message too large: %u"
+msgstr "servermeddelande för långt: %u"
+
+#: logsrvd/sendlog.c:1430
+msgid "timeout writing to server"
+msgstr "tidsgräns passerad vid skrivning till server"
+
+#: logsrvd/sendlog.c:1800
+msgid "both restart point and iolog ID must be specified"
+msgstr "både omstartspunkt och iolog-ID måste anges"
+
+#: logsrvd/sendlog.c:1804
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "en omstartspunkt får inte sättas när ingen I/O skickas"
+
+#: logsrvd/sendlog.c:1880
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "avslutade oväntat i tillstånd %d"
+
+#: logsrvd/sendlog.c:1881
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "förfluten tid skickad till server [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1883
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "incheckningspunkt mottagen från server [%lld, %ld]"
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:315
+msgid "TLS handshake timeout occurred"
+msgstr "Tidsgräns för TLS-handskakning uppnådd"
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:337 plugins/sudoers/log_client.c:353
+msgid "unable to set event"
+msgstr "kan inte ställa in händelse"
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "TLS-anslutning misslyckades: %s"
+
+#: logsrvd/tls_client.c:196
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "kan inte allokera ssl-objekt: %s"
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "Kan inte fästa kontakt på ssl-objektet: %s"
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr "kan inte initiera TLS-kontext"
+
+#: logsrvd/tls_init.c:138 logsrvd/tls_init.c:146
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "kan inte ställa in TLS 1.2-krypteringssvit till %s: %s"
+
+#: logsrvd/tls_init.c:166 logsrvd/tls_init.c:174
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "kan inte ställa in TLS 1.3-krypteringssvit till %s: %s"
+
+#: logsrvd/tls_init.c:206 logsrvd/tls_init.c:227
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "kunde inte sätta diffie-hellman-parametrar: %s"
+
+#: logsrvd/tls_init.c:283
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "kan inte skapa TLS-kontext: %s"
+
+#: logsrvd/tls_init.c:290
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "kunde inte sätta minsta protokollversion till TLS 1.2: %s"
+
+#: plugins/sudoers/audit.c:272 plugins/sudoers/audit.c:452
+#: plugins/sudoers/log_client.c:962 plugins/sudoers/log_client.c:1011
+#: plugins/sudoers/log_client.c:1060 plugins/sudoers/log_client.c:1185
+#: plugins/sudoers/logging.c:614 plugins/sudoers/logging.c:732
+#: plugins/sudoers/logging.c:859 plugins/sudoers/logging.c:1031
+#: plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr "kan inte hämta tid på dagen"
+
+#: plugins/sudoers/auth/aix_auth.c:282
+#, c-format
+msgid "unable to change password for %s"
+msgstr "kan inte ändra lösenord för %s"
+
+#: plugins/sudoers/auth/bsdauth.c:78
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "kan inte hämta inloggningsklass för användaren %s"
+
+#: plugins/sudoers/auth/bsdauth.c:85
+msgid "invalid authentication type"
+msgstr "ogiltig autentiseringstyp"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to begin BSD authentication"
+msgstr "kan inte påbörja BSD-autentisering"
+
+#: plugins/sudoers/auth/bsdauth.c:97
+msgid "unable to initialize BSD authentication"
+msgstr "kan inte initiera BSD-autentisering"
+
+#: plugins/sudoers/auth/bsdauth.c:191
+msgid "your account has expired"
+msgstr "ditt konto har gått ut"
+
+#: plugins/sudoers/auth/bsdauth.c:193
+msgid "approval failed"
+msgstr "godkännande misslyckades"
+
+#: plugins/sudoers/auth/fwtk.c:62
+msgid "unable to read fwtk config"
+msgstr "kan inte läsa fwtk-konfiguration"
+
+#: plugins/sudoers/auth/fwtk.c:67
+msgid "unable to connect to authentication server"
+msgstr "kan inte ansluta till autentiseringsservern"
+
+#: plugins/sudoers/auth/fwtk.c:73 plugins/sudoers/auth/fwtk.c:99
+#: plugins/sudoers/auth/fwtk.c:131
+msgid "lost connection to authentication server"
+msgstr "förlorade kontakten med autentiseringsservern"
+
+#: plugins/sudoers/auth/fwtk.c:77
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"fel i autentiseringsservern:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:116
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: kan inte konvertera principal till sträng (”%s”): %s"
+
+#: plugins/sudoers/auth/kerb5.c:166
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: kan inte tolka ”%s”: %s"
+
+#: plugins/sudoers/auth/kerb5.c:175
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: kan inte slå upp inloggningsuppgiftscache: %s"
+
+#: plugins/sudoers/auth/kerb5.c:226
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: kan inte allokera flaggor: %s"
+
+#: plugins/sudoers/auth/kerb5.c:241
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: kan inte hämta inloggningsuppgifter: %s"
+
+#: plugins/sudoers/auth/kerb5.c:254
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: kan inte initiera inloggningsuppgiftscache: %s"
+
+#: plugins/sudoers/auth/kerb5.c:257
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: kan inte lagra inloggningsuppgifter i cache: %s"
+
+#: plugins/sudoers/auth/kerb5.c:322
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: kan inte hämta principal för värd: %s"
+
+#: plugins/sudoers/auth/kerb5.c:336
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: Kan inte verifiera TGT! Möjlig attack!: %s"
+
+#: plugins/sudoers/auth/pam.c:233
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "kan inte initiera PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:349
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "PAM-autentiseringsfel: %s"
+
+#: plugins/sudoers/auth/pam.c:369
+msgid "account validation failure, is your account locked?"
+msgstr "kontovalidering misslyckades. Är ditt konto låst?"
+
+#: plugins/sudoers/auth/pam.c:380
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Kontot eller lösenordet har gått ut. Återställ ditt lösenord och försök igen"
+
+#: plugins/sudoers/auth/pam.c:387
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "kan inte ändra utgånget lösenord: %s"
+
+#: plugins/sudoers/auth/pam.c:398
+msgid "Password expired, contact your system administrator"
+msgstr "Lösenordet har gått ut. Kontakta din systemadministratör"
+
+#: plugins/sudoers/auth/pam.c:403
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Konto utgånget eller så saknar PAM-konfigurationen ett ”account”-avsnitt för sudo, kontakta din systemadministratör"
+
+#: plugins/sudoers/auth/pam.c:411 plugins/sudoers/auth/pam.c:416
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "Fel vid hantering av PAM-konto: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:100 plugins/sudoers/visudo.c:266
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "du finns inte i %s-databasen"
+
+#: plugins/sudoers/auth/securid5.c:76
+msgid "failed to initialise the ACE API library"
+msgstr "misslyckades med att initiera ACE API-biblioteket"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "unable to contact the SecurID server"
+msgstr "kan inte kontakta SecurID-servern"
+
+#: plugins/sudoers/auth/securid5.c:117
+msgid "User ID locked for SecurID Authentication"
+msgstr "Användar-ID låst för SecurID-autentisering"
+
+#: plugins/sudoers/auth/securid5.c:121 plugins/sudoers/auth/securid5.c:174
+msgid "invalid username length for SecurID"
+msgstr "ogiltig längd för användarnamn för SecurID"
+
+#: plugins/sudoers/auth/securid5.c:125 plugins/sudoers/auth/securid5.c:179
+msgid "invalid Authentication Handle for SecurID"
+msgstr "ogiltigt autentiseringshandtag för SecurID"
+
+#: plugins/sudoers/auth/securid5.c:129
+msgid "SecurID communication failed"
+msgstr "SecurID-kommunikation misslyckades"
+
+#: plugins/sudoers/auth/securid5.c:133 plugins/sudoers/auth/securid5.c:222
+msgid "unknown SecurID error"
+msgstr "okänt SecurID-fel"
+
+#: plugins/sudoers/auth/securid5.c:169
+msgid "invalid passcode length for SecurID"
+msgstr "ogiltig lösenordslängd för SecurID"
+
+#: plugins/sudoers/auth/sia.c:72 plugins/sudoers/auth/sia.c:130
+msgid "unable to initialize SIA session"
+msgstr "kan inte initiera SIA-session"
+
+#: plugins/sudoers/auth/sudo_auth.c:141
+msgid "invalid authentication methods"
+msgstr "ogiltiga autentiseringsmetoder"
+
+#: plugins/sudoers/auth/sudo_auth.c:143
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Ogiltiga autentiseringsmetoder inkompilerade i sudo! Du får inte blanda fristående och icke-fristående autentisering."
+
+#: plugins/sudoers/auth/sudo_auth.c:296 plugins/sudoers/auth/sudo_auth.c:359
+msgid "no authentication methods"
+msgstr "inga autentiseringsmetoder"
+
+#: plugins/sudoers/auth/sudo_auth.c:298
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Det finns inga autentiseringsmetoder inbyggda i sudo! Om du vill inaktivera autentisering, använd konfigurationsflaggan --disable-authentication."
+
+#: plugins/sudoers/auth/sudo_auth.c:361
+msgid "Unable to initialize authentication methods."
+msgstr "Kan inte initiera autentiseringsmetoder."
+
+#: plugins/sudoers/auth/sudo_auth.c:551
+msgid "Authentication methods:"
+msgstr "Autentiseringsmetoder:"
+
+#: plugins/sudoers/bsm_audit.c:122 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "Kunde inte fastställa granskningsvillkor"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:278
+msgid "unable to commit audit record"
+msgstr "kan inte bekräfta granskningsberättelse"
+
+#: plugins/sudoers/check.c:63 plugins/sudoers/check.c:74
+#: plugins/sudoers/lookup.c:79 plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "okänt uid %u"
+
+#: plugins/sudoers/check.c:277
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "fel vid inläsning av lektionsfil %s"
+
+#: plugins/sudoers/check.c:280
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "hoppar över lektionsfil %s: inte en vanlig fil"
+
+#: plugins/sudoers/check.c:293
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Vi litar på att du har fått den vanliga lektionen från den lokala system-\n"
+"administratören. Den kan vanligtvis reduceras till dessa tre saker:\n"
+"\n"
+" #1) Respektera andras integritet.\n"
+" #2) Tänk innan du skriver.\n"
+" #3) Med stor makt kommer ett stort ansvar.\n"
+"\n"
+
+#: plugins/sudoers/check.c:301
+msgid ""
+"For security reasons, the password you type will not be visible.\n"
+"\n"
+msgstr ""
+"Av säkerhetsskäl kommer lösenordet du skriver in inte att synas.\n"
+"\n"
+
+#: plugins/sudoers/check_aliases.c:93
+#, c-format
+msgid "cycle in %s \"%s\""
+msgstr "cykel i %s ”%s”"
+
+#: plugins/sudoers/check_aliases.c:96
+#, c-format
+msgid "%s \"%s\" referenced but not defined"
+msgstr "%s ”%s” refererad till men inte definierad"
+
+#: plugins/sudoers/cvtsudoers.c:211
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "ordningsinkrement: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:231
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "startordning: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:242
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "ordningsutfyllnad: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:252 plugins/sudoers/visudo.c:183
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s grammatikversion %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:282 plugins/sudoers/testsudoers.c:162
+#, c-format
+msgid "unsupported input format %s"
+msgstr "inmatningsformat %s stöds inte"
+
+#: plugins/sudoers/cvtsudoers.c:300
+#, c-format
+msgid "unsupported output format %s"
+msgstr "utmatningsformat %s stöds inte"
+
+#: plugins/sudoers/cvtsudoers.c:392
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: in- och utmatningsfiler måste vara olika"
+
+#: plugins/sudoers/cvtsudoers.c:406 plugins/sudoers/sudoers.c:151
+#: plugins/sudoers/sudoers.c:209 plugins/sudoers/testsudoers.c:315
+#: plugins/sudoers/visudo.c:276 plugins/sudoers/visudo.c:666
+msgid "unable to initialize sudoers default values"
+msgstr "kan inte initiera sudoers standardvärden"
+
+#: plugins/sudoers/cvtsudoers.c:533 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:612
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s: okänt nyckelord %s"
+
+#: plugins/sudoers/cvtsudoers.c:658
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "ogiltig standardtyp: %s"
+
+#: plugins/sudoers/cvtsudoers.c:681
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "ogiltig undertryckningstyp: %s"
+
+#: plugins/sudoers/cvtsudoers.c:722 plugins/sudoers/cvtsudoers.c:738
+#, c-format
+msgid "invalid filter: %s"
+msgstr "ogiltigt filter: %s"
+
+#: plugins/sudoers/cvtsudoers.c:783 plugins/sudoers/visudo.c:1000
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "misslyckades med att tolka %s-filen, okänt fel"
+
+#: plugins/sudoers/cvtsudoers.c:1508 plugins/sudoers/sudoreplay.c:1143
+#: plugins/sudoers/timestamp.c:353 plugins/sudoers/timestamp.c:356
+#, c-format
+msgid "unable to write to %s"
+msgstr "kan inte skriva till %s"
+
+#: plugins/sudoers/cvtsudoers.c:1536
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s - konvertera mellan sudoers filformat\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1538
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Flaggor:\n"
+" -b, --base=dn DN-bas för sudo LDAP-förfrågningar\n"
+" -c, --config=konffil sökvägen till konfigurationsfilen\n"
+" -d, --defaults=stdtyper konvertera endast Standard av de angivna typerna\n"
+" -e, --expand-aliases expandera alias under konvertering\n"
+" -f, --output-format=format ställ in utmatningsformat: JSON, LDIF eller sudoers\n"
+" -i, --input-format=format ställ in inmatningsformat: LDIF eller sudoers\n"
+" -I, --increment=ant antal att öka varje sudoOrder med\n"
+" -h, --help visa hjälpmeddelande och avsluta\n"
+" -m, --match=filter konvertera endast poster som matchar filtret\n"
+" -M, --match-local filtermatchning använder passwd och gruppdatabaser\n"
+" -o, --output=utmatningsfil skriv konverterad sudoers till utmatningsfil\n"
+" -O, --order-start=ant startpunkt för första sudoOrder\n"
+" -p, --prune-matches skala bort användare, grupper och värdar som inte matchar\n"
+" -P, --padding=num basutfyllnad för sudoOrder-inkrement\n"
+" -s, --suppress=avsnitt undertryck utmatning av vissa avsnitt\n"
+" -V, --version visa versionsinformation och avsluta"
+
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:245 plugins/sudoers/cvtsudoers_ldif.c:252
+#: plugins/sudoers/cvtsudoers_ldif.c:594 plugins/sudoers/env.c:340
+#: plugins/sudoers/env.c:347 plugins/sudoers/env.c:458
+#: plugins/sudoers/ldap.c:511 plugins/sudoers/ldap.c:629
+#: plugins/sudoers/ldap.c:1003 plugins/sudoers/ldap_conf.c:219
+#: plugins/sudoers/ldap_conf.c:310 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:93 plugins/sudoers/logging.c:479
+#: plugins/sudoers/policy.c:828 plugins/sudoers/policy.c:840
+#: plugins/sudoers/prompt.c:169 plugins/sudoers/serialize_list.c:62
+#: plugins/sudoers/serialize_list.c:71 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/sudoreplay.c:1340 plugins/sudoers/sudoreplay.c:1346
+#: plugins/sudoers/sudoreplay.c:1352 plugins/sudoers/testsudoers.c:306
+#: plugins/sudoers/toke_util.c:217 toke.l:995 toke.l:1277
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "internt fel, %s spill"
+
+#: plugins/sudoers/cvtsudoers_csv.c:454 plugins/sudoers/cvtsudoers_csv.c:468
+#: plugins/sudoers/cvtsudoers_json.c:661 plugins/sudoers/cvtsudoers_json.c:676
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:362
+#: plugins/sudoers/ldap.c:495
+msgid "unable to get GMT time"
+msgstr "kan inte hämta GMT-tid"
+
+#: plugins/sudoers/cvtsudoers_csv.c:459 plugins/sudoers/cvtsudoers_csv.c:473
+#: plugins/sudoers/cvtsudoers_json.c:666 plugins/sudoers/cvtsudoers_json.c:681
+#: plugins/sudoers/cvtsudoers_ldif.c:354 plugins/sudoers/cvtsudoers_ldif.c:367
+#: plugins/sudoers/ldap.c:503
+msgid "unable to format timestamp"
+msgstr "kan inte formatera tidsstämpel"
+
+#: plugins/sudoers/cvtsudoers_json.c:481 plugins/sudoers/cvtsudoers_json.c:516
+#: plugins/sudoers/cvtsudoers_json.c:732
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: okänd standardpost ”%s”"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:663
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "för många sudoers-poster, maximalt %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:706
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "miljövariabeln SUDOERS_BASE är inte satt och flaggan -b angavs inte."
+
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, c-format
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr "%s:%d:%d: konverterar värdlista till ALL"
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr "kan inte hitta alias %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, c-format
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr "%s:%d:%d: byter namn på alias %s till %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr "%s:%d:%d: tar bort duplicerat alias %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr "%s:%d:%d: Defaults-post ”%s” står i konflikt med värdspecifik på %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, c-format
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr "%s:%d:%d: gjorde Defaults ”%s” specifika för värd %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr "%s:%d:%d: kan inte göra Defaults ”%s” värdspecifik"
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr "%s:%d:%d: tar bort Defaults ”%s” åsidosatt av efterföljande poster"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1088
+#, c-format
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr "%s:%d:%d: sammanfogar användarspec till %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1182
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr "%s:%d:%d: tar bort användarspec åsidosatt av efterföljande poster"
+
+#: plugins/sudoers/def_data.c:56
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Syslog-facilitet om syslog används för loggning: %s"
+
+#: plugins/sudoers/def_data.c:60
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Syslog-prioritet att använda när användaren lyckas med autentisering: %s"
+
+#: plugins/sudoers/def_data.c:64
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Syslog-prioritet att använda när användaren misslyckas med autentisering: %s"
+
+#: plugins/sudoers/def_data.c:68
+msgid "Put OTP prompt on its own line"
+msgstr "Lägg OTP-prompt på en egen rad"
+
+#: plugins/sudoers/def_data.c:72
+msgid "Ignore '.' in $PATH"
+msgstr "Ignorera ”.” i $PATH"
+
+#: plugins/sudoers/def_data.c:76
+msgid "Always send mail when sudo is run"
+msgstr "Skicka alltid e-post när sudo körs"
+
+#: plugins/sudoers/def_data.c:80
+msgid "Send mail if user authentication fails"
+msgstr "Skicka e-post om användarens autentisering misslyckas"
+
+#: plugins/sudoers/def_data.c:84
+msgid "Send mail if the user is not in sudoers"
+msgstr "Skicka e-post om användaren inte finns med i sudoers"
+
+#: plugins/sudoers/def_data.c:88
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Skicka e-post om användaren inte finns med i sudoers för denna värddator"
+
+#: plugins/sudoers/def_data.c:92
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Skicka e-post om användaren inte tillåts att köra ett kommando"
+
+#: plugins/sudoers/def_data.c:96
+msgid "Send mail if the user tries to run a command"
+msgstr "Skicka e-post om användaren försöker köra ett kommando"
+
+#: plugins/sudoers/def_data.c:100
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Använd en separat tidsstämpel för varje användar-/tty-kombination"
+
+#: plugins/sudoers/def_data.c:104
+msgid "Lecture user the first time they run sudo"
+msgstr "Lär upp användaren första gången de kör sudo"
+
+#: plugins/sudoers/def_data.c:108
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Fil som innehåller sudo-lektion: %s"
+
+#: plugins/sudoers/def_data.c:112
+msgid "Require users to authenticate by default"
+msgstr "Kräv att användare autentiseras som standard"
+
+#: plugins/sudoers/def_data.c:116
+msgid "Root may run sudo"
+msgstr "Root får köra sudo"
+
+#: plugins/sudoers/def_data.c:120
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Logga värdnamnet i (den icke syslog-baserade) loggfilen"
+
+#: plugins/sudoers/def_data.c:124
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Logga året i (den icke syslog-baserade) loggfilen"
+
+#: plugins/sudoers/def_data.c:128
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Om sudo startas utan argument, starta ett skal"
+
+#: plugins/sudoers/def_data.c:132
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Ställ in $HOME till målanvändaren när ett skal startas med -s"
+
+#: plugins/sudoers/def_data.c:136
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Ställ alltid in $HOME till målanvändarens hemkatalog"
+
+#: plugins/sudoers/def_data.c:140
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Tillåt viss informationsinsamling för att ge meningsfulla felmeddelanden"
+
+#: plugins/sudoers/def_data.c:144
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Kräv fullständiga värdnamn i sudoers-filen"
+
+#: plugins/sudoers/def_data.c:148
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Förolämpa användaren när de anger ett felaktigt lösenord"
+
+#: plugins/sudoers/def_data.c:152
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Tillåt bara användare att köra sudo om de har en tty"
+
+#: plugins/sudoers/def_data.c:156
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo kommer att respektera miljövariabeln EDITOR"
+
+#: plugins/sudoers/def_data.c:160
+msgid "Prompt for root's password, not the users's"
+msgstr "Fråga efter root-lösenordet, inte användarens"
+
+#: plugins/sudoers/def_data.c:164
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Fråga efter runas_default-användarens lösenord, inte användarens"
+
+#: plugins/sudoers/def_data.c:168
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Fråga efter målanvändarens lösenord, inte användarens"
+
+#: plugins/sudoers/def_data.c:172
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Tillämpa standardvärden i målanvändarens inloggningsklass om det finns en"
+
+#: plugins/sudoers/def_data.c:176
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Ställ in miljövariablerna LOGNAME och USER"
+
+#: plugins/sudoers/def_data.c:180
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Sätt bara det effektiva uid:t till målanvändaren, inte till det riktiga uid:t"
+
+#: plugins/sudoers/def_data.c:184
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Initiera inte gruppvektorn till den från målanvändaren"
+
+#: plugins/sudoers/def_data.c:188
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Längden vid vilken långa loggfilsrader radbryts (0 för att inte radbryta): %u"
+
+#: plugins/sudoers/def_data.c:192
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Tidsgräns för autentiseringstidsstämpel: %.1f minuter"
+
+#: plugins/sudoers/def_data.c:196
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Tidsgräns för lösenordsprompt: %.1f minuter"
+
+#: plugins/sudoers/def_data.c:200
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Antal försök att ange ett lösenord: %u"
+
+#: plugins/sudoers/def_data.c:204
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Umask att använda eller 0777 för att använda användarens: 0%o"
+
+#: plugins/sudoers/def_data.c:208
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Sökväg till loggfil: %s"
+
+#: plugins/sudoers/def_data.c:212
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Sökväg till e-postprogram: %s"
+
+#: plugins/sudoers/def_data.c:216
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Flaggor för e-postprogram: %s"
+
+#: plugins/sudoers/def_data.c:220
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Adress att skicka e-post till: %s"
+
+#: plugins/sudoers/def_data.c:224
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Adress att skicka e-post från: %s"
+
+#: plugins/sudoers/def_data.c:228
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Ämnesrad för e-postmeddelanden: %s"
+
+#: plugins/sudoers/def_data.c:232
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Meddelande vid felaktigt lösenord: %s"
+
+#: plugins/sudoers/def_data.c:236
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Sökväg till lektionsstatuskatalog: %s"
+
+#: plugins/sudoers/def_data.c:240
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Sökväg till katalog för autentiseringstidsstämplar: %s"
+
+#: plugins/sudoers/def_data.c:244
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Ägare av katalogen för autentiseringstidsstämplar: %s"
+
+#: plugins/sudoers/def_data.c:248
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Användare i denna grupp är undantagna från lösenords- och SÖKVÄGs-kraven: %s"
+
+#: plugins/sudoers/def_data.c:252
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Standard lösenordsprompt: %s"
+
+#: plugins/sudoers/def_data.c:256
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Om inställt kommer passprompt att åsidosätta systemprompten i varje fall."
+
+#: plugins/sudoers/def_data.c:260
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Standardanvändaren att köra kommandon som: %s"
+
+#: plugins/sudoers/def_data.c:264
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Värde att åsidosätta användarens $PATH med: %s"
+
+#: plugins/sudoers/def_data.c:268
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Sökväg till textredigerare för användning av visudo: %s"
+
+#: plugins/sudoers/def_data.c:272
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "När ett lösenord ska krävas för pseudokommandot ”list”: %s"
+
+#: plugins/sudoers/def_data.c:276
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "När lösenord ska krävas för pseudokommandot ”verify”: %s"
+
+#: plugins/sudoers/def_data.c:280
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "Förinläs sudo_noexec-biblioteket vilket ersätter exec-funktionerna"
+
+#: plugins/sudoers/def_data.c:284
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Om LDAP-registret är uppe, ignorerar vi den lokala sudoers-filen"
+
+#: plugins/sudoers/def_data.c:288
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Fildeskriptorer >= %d kommer att stängas innan ett kommando körs"
+
+#: plugins/sudoers/def_data.c:292
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "Om inställt kan användare åsidosätta värdet ”closefrom” med flaggan -C"
+
+#: plugins/sudoers/def_data.c:296
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Låt användare ställa in godtyckliga miljövariabler"
+
+#: plugins/sudoers/def_data.c:300
+msgid "Reset the environment to a default set of variables"
+msgstr "Återställ miljön till standarduppsättningen av variabler"
+
+#: plugins/sudoers/def_data.c:304
+msgid "Environment variables to check for safety:"
+msgstr "Miljövariabler att säkerhetskontrollera:"
+
+#: plugins/sudoers/def_data.c:308
+msgid "Environment variables to remove:"
+msgstr "Miljövariabler att ta bort:"
+
+#: plugins/sudoers/def_data.c:312
+msgid "Environment variables to preserve:"
+msgstr "Miljövariabler att behålla:"
+
+#: plugins/sudoers/def_data.c:316
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "SELinux-roll att använda i den nya säkerhetskontexten: %s"
+
+#: plugins/sudoers/def_data.c:320
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "SELinux-typ att använda i den nya säkerhetskontexten: %s"
+
+#: plugins/sudoers/def_data.c:324
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Sökväg till den sudo-specifika miljöfilen: %s"
+
+#: plugins/sudoers/def_data.c:328
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Sökväg till den begränsade sudo-specifika miljöfilen: %s"
+
+#: plugins/sudoers/def_data.c:332
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Lokalanpassning att använda vid tolkning av sudoers: %s"
+
+#: plugins/sudoers/def_data.c:336
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Tillåt sudo att fråga efter ett lösenord även om det skulle vara synligt"
+
+#: plugins/sudoers/def_data.c:340
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Ge visuell återkoppling vid lösenordsprompten när det finns användarinmatad data"
+
+#: plugins/sudoers/def_data.c:344
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Använd snabbare matchning som är mindre exakt men inte använder filsystemet"
+
+#: plugins/sudoers/def_data.c:348
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "Umasken angiven i sudoers kommer att åsidosätta användarens, även om den är mer tillåtande"
+
+#: plugins/sudoers/def_data.c:352
+msgid "Log user's input for the command being run"
+msgstr "Logga användarens inmatning för kommandot som körs"
+
+#: plugins/sudoers/def_data.c:356
+msgid "Log the command's standard input if not connected to a terminal"
+msgstr "Logga kommandots standard in om inte ansluten till en terminal"
+
+#: plugins/sudoers/def_data.c:360
+msgid "Log the user's terminal input for the command being run"
+msgstr "Logga användarens terminalinmatning för kommandot som körs"
+
+#: plugins/sudoers/def_data.c:364
+msgid "Log the output of the command being run"
+msgstr "Logga utmatningen för kommandot som körs"
+
+#: plugins/sudoers/def_data.c:368
+msgid "Log the command's standard output if not connected to a terminal"
+msgstr "Logga kommandots standard ut om inte ansluten till en terminal"
+
+#: plugins/sudoers/def_data.c:372
+msgid "Log the command's standard error if not connected to a terminal"
+msgstr "Logga kommandots standard fel om inte ansluten till en terminal"
+
+#: plugins/sudoers/def_data.c:376
+msgid "Log the terminal output of the command being run"
+msgstr "Logga terminalutmatningen för kommandot som körs"
+
+#: plugins/sudoers/def_data.c:380
+msgid "Compress I/O logs using zlib"
+msgstr "Komprimera I/O-loggar med hjälp av zlib"
+
+#: plugins/sudoers/def_data.c:384
+msgid "Always run commands in a pseudo-tty"
+msgstr "Kör alltid kommandon i en pseudo-tty"
+
+#: plugins/sudoers/def_data.c:388
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Insticksmodul för stöd för icke-Unix-grupper: %s"
+
+#: plugins/sudoers/def_data.c:392
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Katalog i vilken in-/utmatningsloggar lagras: %s"
+
+#: plugins/sudoers/def_data.c:396
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Fil i vilken in-/utmatningsloggar lagras: %s"
+
+#: plugins/sudoers/def_data.c:400
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Lägg till en post till utmp/utmpx-filen när en pty allokeras"
+
+#: plugins/sudoers/def_data.c:404
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Sätt användaren i utmp till runas-användaren, inte användaren som anropar"
+
+#: plugins/sudoers/def_data.c:408
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Uppsättning tillåtna rättigheter: %s"
+
+#: plugins/sudoers/def_data.c:412
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Uppsättning av begränsningsrättigheter: %s"
+
+#: plugins/sudoers/def_data.c:416
+msgid "Run commands on a pty in the background"
+msgstr "Kör kommandon i en pty i bakgrunden"
+
+#: plugins/sudoers/def_data.c:420
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "PAM-tjänstnamn att använda: %s"
+
+#: plugins/sudoers/def_data.c:424
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "PAM-tjänstnamn att använda för inloggningsskal: %s"
+
+#: plugins/sudoers/def_data.c:428
+#, c-format
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr "PAM-tjänstnamn att använda när sudo körs med flaggan -A: %s"
+
+#: plugins/sudoers/def_data.c:432
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Försök att etablera PAM-inloggningsuppgifter för målanvändaren"
+
+#: plugins/sudoers/def_data.c:436
+msgid "Create a new PAM session for the command to run in"
+msgstr "Skapa en ny PAM-session för kommandot att köra i"
+
+#: plugins/sudoers/def_data.c:440
+msgid "Perform PAM account validation management"
+msgstr "Utför valideringshantering av PAM-konto"
+
+#: plugins/sudoers/def_data.c:444
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "Största sekvensnummer i I/O-logg: %s"
+
+#: plugins/sudoers/def_data.c:448
+msgid "Enable sudoers netgroup support"
+msgstr "Aktivera sudoers nätgruppsstöd"
+
+#: plugins/sudoers/def_data.c:452
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Kontrollera överordnade kataloger för skrivbarhet när filer redigeras med sudoedit"
+
+#: plugins/sudoers/def_data.c:456
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Följ symboliska länkar när filer redigeras med sudoedit"
+
+#: plugins/sudoers/def_data.c:460
+msgid "Query the group plugin for unknown system groups"
+msgstr "Fråga gruppinsticksmodulen efter okända systemgrupper"
+
+#: plugins/sudoers/def_data.c:464
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Matcha nätgrupper baserat på hela tupeln: användare, värd och domän"
+
+#: plugins/sudoers/def_data.c:468
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Tillåt kommandon att köras även om sudo inte kan skriva till granskningsloggen"
+
+#: plugins/sudoers/def_data.c:472
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Tillåt kommandon att köras även om sudo inte kan skriva I/O-loggen"
+
+#: plugins/sudoers/def_data.c:476
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Tillåt kommandon att köras även om sudo inte kan skriva till loggfilen"
+
+#: plugins/sudoers/def_data.c:480
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Gör namnupplösning för grupper i sudoers och matcha efter grupp-ID, inte namnet"
+
+#: plugins/sudoers/def_data.c:484
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Loggposter större än detta värde kommer att delas upp i flera syslog-meddelanden: %u"
+
+#: plugins/sudoers/def_data.c:488
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Användare som kommer att äga I/O-loggfilerna: %s"
+
+#: plugins/sudoers/def_data.c:492
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Grupp som kommer att äga I/O-loggfilerna: %s"
+
+#: plugins/sudoers/def_data.c:496
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Filrättigheter att använda för I/O-loggfilerna: 0%o"
+
+#: plugins/sudoers/def_data.c:500
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Kör kommandon efter fildeskriptor istället för efter sökväg: %s"
+
+#: plugins/sudoers/def_data.c:504
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Hoppa över okända Defaults-poster i sudoers istället för att skriva ut en varning"
+
+#: plugins/sudoers/def_data.c:508
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Tid i sekunder efter vilka kommandot kommer att avslutas: %u"
+
+#: plugins/sudoers/def_data.c:512
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Tillåt användaren att ange en tidsgräns på kommandoraden"
+
+#: plugins/sudoers/def_data.c:516
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Spola ut I/O-loggdata till disk omedelbart istället för att buffra det"
+
+#: plugins/sudoers/def_data.c:520
+msgid "Include the process ID when logging via syslog"
+msgstr "Inkludera process-ID:t vid loggning via syslog"
+
+#: plugins/sudoers/def_data.c:524
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Typ av post för autentiseringstidsstämplar: %s"
+
+#: plugins/sudoers/def_data.c:528
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Autentiseringsfelsmeddelande: %s"
+
+#: plugins/sudoers/def_data.c:532
+msgid "Ignore case when matching user names"
+msgstr "Matcha användarnamn skiftlägesokänsligt"
+
+#: plugins/sudoers/def_data.c:536
+msgid "Ignore case when matching group names"
+msgstr "Matcha gruppnamn skiftlägesokänsligt"
+
+#: plugins/sudoers/def_data.c:540
+msgid "Log when a command is allowed by sudoers"
+msgstr "Logga när ett kommando tillåts av sudoers"
+
+#: plugins/sudoers/def_data.c:544
+msgid "Log when a command is denied by sudoers"
+msgstr "Logga när ett kommando nekas av sudoers"
+
+#: plugins/sudoers/def_data.c:548
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "Sudo-loggservrar att ansluta till med valfri port"
+
+#: plugins/sudoers/def_data.c:552
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Tidsgräns för sudo-loggserver i sekunder: %u"
+
+#: plugins/sudoers/def_data.c:556
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "Aktivera SO_KEEPALIVE-kontaktalternativ på kontakten ansluten till loggservern"
+
+#: plugins/sudoers/def_data.c:560
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "Sökväg till granskningsserverns CA-buntfil: %s"
+
+#: plugins/sudoers/def_data.c:564
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "Sökväg till sudoers certifikatfil: %s"
+
+#: plugins/sudoers/def_data.c:568
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "Sökväg till sudoers privata nyckelfil: %s"
+
+#: plugins/sudoers/def_data.c:572
+msgid "Verify that the log server's certificate is valid"
+msgstr "Verifiera att loggserverns certifikatfil är giltig"
+
+#: plugins/sudoers/def_data.c:576
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "Tillåt användningen av okänd runas-användare och/eller grupp-ID"
+
+#: plugins/sudoers/def_data.c:580
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "Tillåt endast körning av kommandon som en användare med ett giltigt skal"
+
+#: plugins/sudoers/def_data.c:584
+msgid "Set the pam remote user to the user running sudo"
+msgstr "Ställ in pam-fjärranvändaren för användaren som kör sudo"
+
+#: plugins/sudoers/def_data.c:588
+msgid "Set the pam remote host to the local host name"
+msgstr "Ställ in pam-fjärrvärden till det lokala värdnamnet"
+
+#: plugins/sudoers/def_data.c:592
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "Arbetskatalog att ändra till före körning av kommandot: %s"
+
+#: plugins/sudoers/def_data.c:596
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "Rotkatalog att ändra till innan kommandot körs: %s"
+
+#: plugins/sudoers/def_data.c:600
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "Formatet för loggarna som ska produceras: %s"
+
+#: plugins/sudoers/def_data.c:604
+msgid "Enable SELinux RBAC support"
+msgstr "Aktivera SELinux RBAC-stöd"
+
+#: plugins/sudoers/def_data.c:608
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "Sökväg till filen som skapas första gången sudo körs: %s"
+
+#: plugins/sudoers/def_data.c:612
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "Fånga in vidare kommando och tillämpa sudoers-begränsningar på dem"
+
+#: plugins/sudoers/def_data.c:616
+msgid "Log sub-commands run by the original command"
+msgstr "Logga underkommandon som körs av originalkommandot"
+
+#: plugins/sudoers/def_data.c:620
+msgid "Log the exit status of commands"
+msgstr "Logga avslutningsstatus för kommandon"
+
+#: plugins/sudoers/def_data.c:624
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr "Framtida kommandon i en infångad session måste autentiseras"
+
+#: plugins/sudoers/def_data.c:628
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr "Tillåt ett infångat kommando att köra setuid- eller setgid-program"
+
+#: plugins/sudoers/def_data.c:632
+#, c-format
+msgid "The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr "Maximal storlek upp till vilken processens adressområde får växa (i byte): %s"
+
+#: plugins/sudoers/def_data.c:636
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr "Största storlek för kärndumpfil som får skapas (i byte): %s"
+
+#: plugins/sudoers/def_data.c:640
+#, c-format
+msgid "The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr "Maximal mängd CPU-tid som processen får använda (i sekunder): %s"
+
+#: plugins/sudoers/def_data.c:644
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr "Maximal storlek på datasegmentet för processen (i byte): %s"
+
+#: plugins/sudoers/def_data.c:648
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr "Största filstorlek som processen får skapa (i byte): %s"
+
+#: plugins/sudoers/def_data.c:652
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr "Största antalet lås som processen får etablera: %s"
+
+#: plugins/sudoers/def_data.c:656
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr "Maximal storlek som processen får låsa i minnet (i byte): %s"
+
+#: plugins/sudoers/def_data.c:660
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr "Maximalt antal filer som processen får ha öppna: %s"
+
+#: plugins/sudoers/def_data.c:664
+#, c-format
+msgid "The maximum number of processes that the user may run simultaneously: %s"
+msgstr "Maximalt antal processer som användaren får köra samtidigt: %s"
+
+#: plugins/sudoers/def_data.c:668
+#, c-format
+msgid "The maximum size to which the process's resident set size may grow (in bytes): %s"
+msgstr "Maximal storlek upp till vilken processens residenta mängd får växa (i byte): %s"
+
+#: plugins/sudoers/def_data.c:672
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr "Maximal storlek upp till vilken processen stack får växa (i byte) : %s"
+
+#: plugins/sudoers/def_data.c:676
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr "Försök att autentisera även i icke-interaktivt läge"
+
+#: plugins/sudoers/def_data.c:680
+msgid "Store plaintext passwords in I/O log input"
+msgstr "Spara lösenord i klartext i I/O-logg-indata"
+
+#: plugins/sudoers/def_data.c:684
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr "Lista över reguljära uttryck att använda vid matchning av en lösenordsförfrågan"
+
+#: plugins/sudoers/def_data.c:688
+#, c-format
+msgid "The mechanism used by the intercept and log_subcmds options: %s"
+msgstr "Mekanismen som används av infångning och log_subcmd-flaggorna: %s"
+
+#: plugins/sudoers/def_data.c:692
+msgid "Attempt to verify the command and arguments after execution"
+msgstr "Försök att verifiera kommandot och argumenten efter körning"
+
+#: plugins/sudoers/def_data.c:696
+#, c-format
+msgid "AppArmor profile to use in the new security context: %s"
+msgstr "AppArmor-profil att använda i den nya säkerhetskontexten: %s"
+
+#: plugins/sudoers/defaults.c:207
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "okänd standardpost ”%s”"
+
+#: plugins/sudoers/defaults.c:251
+#, c-format
+msgid "no value specified for \"%s\""
+msgstr "inget värde angivet för ”%s”"
+
+#: plugins/sudoers/defaults.c:260
+#, c-format
+msgid "invalid operator \"%c=\" for \"%s\""
+msgstr "ogiltig operator ”%c=” för ”%s”"
+
+#: plugins/sudoers/defaults.c:292
+#, c-format
+msgid "option \"%s\" does not take a value"
+msgstr "flaggan ”%s” tar inte emot något värde"
+
+#: plugins/sudoers/defaults.c:319
+#, c-format
+msgid "invalid Defaults type 0x%x for option \"%s\""
+msgstr "ogiltig Defaults-typ 0x%x för flagga ”%s”"
+
+#: plugins/sudoers/defaults.c:326
+#, c-format
+msgid "value \"%s\" is invalid for option \"%s\""
+msgstr "värdet ”%s” är ogiltigt för flaggan ”%s”"
+
+#: plugins/sudoers/defaults.c:1176 plugins/sudoers/policy.c:213
+#: plugins/sudoers/policy.c:222
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr "sökvägsnamn för ”%s” för långt"
+
+#: plugins/sudoers/defaults.c:1182
+#, c-format
+msgid "values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "värden för ”%s” måste börja med ett ”/”, ”~” eller ”*”"
+
+#: plugins/sudoers/defaults.c:1189
+#, c-format
+msgid "values for \"%s\" must start with a '/'"
+msgstr "värden för ”%s” måste börja med ett ”/”"
+
+#: plugins/sudoers/display.c:160
+#, c-format
+msgid "LDAP Role: %s\n"
+msgstr "LDAP-roll: %s\n"
+
+#: plugins/sudoers/display.c:163
+#, c-format
+msgid "Sudoers entry: %s\n"
+msgstr "Sudoers-post: %s\n"
+
+#: plugins/sudoers/display.c:166
+msgid " RunAsUsers: "
+msgstr " KörSomAnvändare: "
+
+#: plugins/sudoers/display.c:181
+msgid " RunAsGroups: "
+msgstr " KörSomGrupper: "
+
+#: plugins/sudoers/display.c:191
+msgid " Options: "
+msgstr " Flaggor: "
+
+#: plugins/sudoers/display.c:255
+msgid " Commands:\n"
+msgstr " Kommandon:\n"
+
+#: plugins/sudoers/display.c:478
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Matchande standardposter för %s på %s:\n"
+
+#: plugins/sudoers/display.c:496
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Runas- och kommando-specifika standardvärden för %s:\n"
+
+#: plugins/sudoers/display.c:514
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "Användare %s får köra följande kommandon på %s:\n"
+
+#: plugins/sudoers/display.c:530
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Användaren %s tillåts inte att köra sudo på %s.\n"
+
+#: plugins/sudoers/editor.c:180
+#, c-format
+msgid "ignoring editor: %.*s"
+msgstr "ignorerar textredigerare: %.*s"
+
+#: plugins/sudoers/editor.c:181
+msgid "editor arguments may not contain \"--\""
+msgstr "textredigerarargument får inte innehålla ”--”"
+
+#: plugins/sudoers/env.c:426
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: trasig envp, längd stämmer inte"
+
+#: plugins/sudoers/env.c:1119
+msgid "unable to rebuild the environment"
+msgstr "kan inte återuppbygga miljön"
+
+#: plugins/sudoers/env.c:1199
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "du får inte lov att ställa in följande miljövariabler: %s"
+
+#: plugins/sudoers/filedigest.c:50
+#, c-format
+msgid "unsupported digest type %u for %s"
+msgstr "kontrollsumma av typ %u av stöds inte för %s"
+
+#: plugins/sudoers/filedigest.c:77
+#, c-format
+msgid "%s: read error"
+msgstr "%s: läsfel"
+
+#: plugins/sudoers/group_plugin.c:169 plugins/sudoers/sssd.c:578
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "kan inte läsa in %s: %s"
+
+#: plugins/sudoers/group_plugin.c:181
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "kan inte hitta symbolen ”group_plugin” i %s"
+
+#: plugins/sudoers/group_plugin.c:186
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: inkompatibel gruppinsticksmodul huvudversion %d, förväntade %d"
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "kan inte tolka IP-adress ”%s”"
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "kan inte tolka nätmask ”%s”"
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Lokala IP-adress- och nätmaskpar:\n"
+
+#: plugins/sudoers/iolog.c:694
+msgid "unable to update sequence file"
+msgstr "kan inte uppdatera sekvensfil"
+
+#: plugins/sudoers/iolog.c:728 plugins/sudoers/iolog.c:917
+#: plugins/sudoers/iolog.c:1080 plugins/sudoers/iolog.c:1087
+#: plugins/sudoers/iolog.c:1209 plugins/sudoers/iolog.c:1216
+#: plugins/sudoers/iolog.c:1316 plugins/sudoers/iolog.c:1323
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "kan inte skriva till I/O-loggfil: %s"
+
+#: plugins/sudoers/iolog.c:736
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "kan inte skapa %s/%s"
+
+#: plugins/sudoers/iolog.c:965
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: internt fel, I/O-loggfil för händelse %d inte öppen"
+
+#: plugins/sudoers/iolog.c:1065 plugins/sudoers/iolog.c:1194
+#: plugins/sudoers/iolog.c:1300 plugins/sudoers/timestamp.c:897
+#: plugins/sudoers/timestamp.c:989 plugins/sudoers/visudo.c:555
+#: plugins/sudoers/visudo.c:561
+msgid "unable to read the clock"
+msgstr "kan inte läsa klockan"
+
+#: plugins/sudoers/iolog.c:1292 plugins/sudoers/log_client.c:1203
+#: plugins/sudoers/log_client.c:1213 plugins/sudoers/log_client.c:1217
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: internt fel, ogiltig signal %d"
+
+#: plugins/sudoers/ldap.c:154 plugins/sudoers/ldap_conf.c:289
+msgid "starttls not supported when using ldaps"
+msgstr "starttls stöds inte när ldaps används"
+
+#: plugins/sudoers/ldap.c:226
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "kan inte initiera SSL-certifikat och nyckeldatabas: %s"
+
+#: plugins/sudoers/ldap.c:229
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "du måste ställa in TLS_CERT i %s för att använda SSL"
+
+#: plugins/sudoers/ldap.c:1593
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "kan inte initiera LDAP: %s"
+
+#: plugins/sudoers/ldap.c:1630
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls angivet men LDAP-bibliotek har inte stöd för ldap_start_tls_s() eller ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:1767 plugins/sudoers/parse_ldif.c:745
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "ogiltigt sudoOrder-attribut: %s"
+
+#: plugins/sudoers/ldap_conf.c:197
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: port för stor"
+
+#: plugins/sudoers/ldap_conf.c:258
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "LDAP-uri-typ stöds ej: %s"
+
+#: plugins/sudoers/ldap_conf.c:285
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "kan inte blanda ldap- och ldaps-URI:er"
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "duplicerad sudoOption: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "kan inte konvertera sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "kan inte öppna granskningssystem"
+
+#: plugins/sudoers/linux_audit.c:104
+msgid "unable to send audit message"
+msgstr "kan inte skicka granskningsmeddelande"
+
+#: plugins/sudoers/log_client.c:125 plugins/sudoers/log_client.c:412
+#: plugins/sudoers/log_client.c:1450 plugins/sudoers/log_client.c:2076
+msgid "error in event loop"
+msgstr "fel i händelseloop"
+
+#: plugins/sudoers/log_client.c:205
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "Skapande av nytt SSL_CTX-objekt misslyckades: %s"
+
+#: plugins/sudoers/log_client.c:230
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "kan inte läsa in certifikatauktoritetsbunt %s"
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "kan inte läsa in certifikat %s"
+
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "unable to load private key %s"
+msgstr "kan inte läsa in privat nyckel %s"
+
+#: plugins/sudoers/log_client.c:275
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "Kan inte allokera ssl-objekt: %s"
+
+#: plugins/sudoers/log_client.c:364 plugins/sudoers/log_client.c:369
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "TLS-anslutning till %s:%s misslyckades: %s"
+
+#: plugins/sudoers/log_client.c:545
+msgid "TLS initialization was unsuccessful"
+msgstr "TLS-initiering misslyckades"
+
+#: plugins/sudoers/log_client.c:555
+msgid "TLS handshake was unsuccessful"
+msgstr "TLS-handskakning misslyckades"
+
+#: plugins/sudoers/log_client.c:1221
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: internt fel, ogiltig avslutningskod %d"
+
+#: plugins/sudoers/log_client.c:1757 plugins/sudoers/log_client.c:1782
+msgid "lost connection to log server"
+msgstr "förlorade kontakten med loggservern"
+
+#: plugins/sudoers/log_client.c:1859
+msgid "missing write buffer"
+msgstr "saknar skrivbuffert"
+
+#: plugins/sudoers/log_client.c:2015
+msgid "unable to connect to log server"
+msgstr "kan inte ansluta till loggserver"
+
+#: plugins/sudoers/logging.c:295
+msgid "user NOT in sudoers"
+msgstr "användare finns INTE i sudoers"
+
+#: plugins/sudoers/logging.c:297
+msgid "user NOT authorized on host"
+msgstr "användaren är INTE auktoriserad på värddatorn"
+
+#: plugins/sudoers/logging.c:299
+msgid "command not allowed"
+msgstr "kommandot tillåts inte"
+
+#: plugins/sudoers/logging.c:320
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr "%s finns inte i sudoers-filen.\n"
+
+#: plugins/sudoers/logging.c:323
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr "%s tillåts inte att köra sudo på %s.\n"
+
+#: plugins/sudoers/logging.c:326
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Tyvärr, användaren %s får inte köra sudo på %s.\n"
+
+#: plugins/sudoers/logging.c:339
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s%s' as %s%s%s on %s.\n"
+msgstr "Tyvärr, användaren %s tillåts inte att köra ”%s%s%s%s” som %s%s%s på %s.\n"
+
+#: plugins/sudoers/logging.c:350
+msgid "This incident has been reported to the administrator.\n"
+msgstr "Denna incident har rapporterats till administratören.\n"
+
+#: plugins/sudoers/logging.c:387 plugins/sudoers/sudoers.c:547
+#: plugins/sudoers/sudoers.c:549 plugins/sudoers/sudoers.c:551
+#: plugins/sudoers/sudoers.c:553 plugins/sudoers/sudoers.c:777
+#: plugins/sudoers/sudoers.c:779
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: kommandot hittades inte"
+
+#: plugins/sudoers/logging.c:389 plugins/sudoers/sudoers.c:543
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"ignorerar ”%s” som hittades i ”.”\n"
+"Använd ”sudo ./%s” om detta är den ”%s” som du vill köra."
+
+#: plugins/sudoers/logging.c:409
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u felaktigt lösenordsförsök"
+msgstr[1] "%u felaktiga lösenordsförsök"
+
+#: plugins/sudoers/logging.c:500
+msgid "authentication failure"
+msgstr "autentiseringsfel"
+
+#: plugins/sudoers/logging.c:539 plugins/sudoers/logging.c:558
+msgid "a password is required"
+msgstr "ett lösenord krävs"
+
+#: plugins/sudoers/logging.c:881
+msgid "problem parsing sudoers"
+msgstr "problem vid tolkning av sudoers"
+
+#: plugins/sudoers/logging.c:922 plugins/sudoers/logging.c:930
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr "%s:%d:%d: %s"
+
+#: plugins/sudoers/logging.c:1108
+#, c-format
+msgid "unable to write log file %s"
+msgstr "kan inte skriva till loggfil %s"
+
+#: plugins/sudoers/match_digest.c:107
+#, c-format
+msgid "digest for %s (%s) bad length %zu, expected %zu"
+msgstr "kontrollsumma för %s (%s) felaktig längd %zu, förväntade %zu"
+
+#: plugins/sudoers/match_digest.c:126
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "kontrollsumma för %s (%s) är inte på %s-form"
+
+#: plugins/sudoers/parse_ldif.c:615
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "hoppar över ofullständig sudoRole: cn: %s"
+
+#: plugins/sudoers/parse_ldif.c:675
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "ogiltigt LDIF-attribut: %s"
+
+#: plugins/sudoers/parser_warnx.c:56
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: plugins/sudoers/parser_warnx.c:59
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s: %s\n"
+
+#: plugins/sudoers/pivot.c:71
+msgid "unable to restore root directory"
+msgstr "kan inte återställa rotkatalog"
+
+#: plugins/sudoers/pivot.c:79
+msgid "unable to restore current working directory"
+msgstr "kan inte återställa aktuell arbetskatalog"
+
+#: plugins/sudoers/policy.c:78 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "ogiltigt %.*s inställt av sudo-framände"
+
+#: plugins/sudoers/policy.c:364 plugins/sudoers/testsudoers.c:329
+msgid "unable to parse network address list"
+msgstr "kan inte tolka nätverksadresslista"
+
+#: plugins/sudoers/policy.c:556
+msgid "user name not set by sudo front-end"
+msgstr "användarnamn inte inställt av sudo-framände"
+
+#: plugins/sudoers/policy.c:560
+msgid "user-ID not set by sudo front-end"
+msgstr "användar-ID inte inställt av sudo-framände"
+
+#: plugins/sudoers/policy.c:564
+msgid "group-ID not set by sudo front-end"
+msgstr "grupp-ID inte inställt av sudo-framände"
+
+#: plugins/sudoers/policy.c:568
+msgid "host name not set by sudo front-end"
+msgstr "värdnamn inte inställt av sudo-framände"
+
+#: plugins/sudoers/policy.c:757
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "ogiltig arbetskatalog: %s"
+
+#: plugins/sudoers/policy.c:944
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "ogiltig chroot-katalog: %s"
+
+#: plugins/sudoers/policy.c:1153 plugins/sudoers/visudo.c:919
+#: plugins/sudoers/visudo.c:1218
+#, c-format
+msgid "unable to execute %s"
+msgstr "kan inte köra %s"
+
+#: plugins/sudoers/policy.c:1225 plugins/sudoers/policy.c:1260
+#: plugins/sudoers/policy.c:1282 plugins/sudoers/policy.c:1300
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: ogiltiga lägesflaggor från sudo-framände: 0x%x"
+
+#: plugins/sudoers/policy.c:1323
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Sudoers policyinsticksmodul version %s\n"
+
+#: plugins/sudoers/policy.c:1325
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Sudoers-filgrammatik version %d\n"
+
+#: plugins/sudoers/policy.c:1329
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Sökväg till sudoers: %s\n"
+
+#: plugins/sudoers/policy.c:1332
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "Sökväg till nsswitch: %s\n"
+
+#: plugins/sudoers/policy.c:1335
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "Sökväg till ldap.conf: %s\n"
+
+#: plugins/sudoers/policy.c:1337
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "Sökväg till ldap.secret: %s\n"
+
+#: plugins/sudoers/policy.c:1370
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "kan inte registrera krok av typ %d (version %d.%d)"
+
+#: plugins/sudoers/policy.c:1388
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "kan inte avregistrera krok av typ %d (version %d.%d)"
+
+#: plugins/sudoers/pwutil.c:242 plugins/sudoers/pwutil.c:260
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "kan inte cacha uid %u"
+
+#: plugins/sudoers/pwutil.c:254
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "kan inte cacha uid %u, finns redan"
+
+#: plugins/sudoers/pwutil.c:314 plugins/sudoers/pwutil.c:332
+#: plugins/sudoers/pwutil.c:395 plugins/sudoers/pwutil.c:440
+#, c-format
+msgid "unable to cache user %s"
+msgstr "kan inte cacha användare %s"
+
+#: plugins/sudoers/pwutil.c:327
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "kan inte cacha användare %s, finns redan"
+
+#: plugins/sudoers/pwutil.c:559 plugins/sudoers/pwutil.c:577
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "kan inte cacha gid %u"
+
+#: plugins/sudoers/pwutil.c:571
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "kan inte cacha gid %u, finns redan"
+
+#: plugins/sudoers/pwutil.c:625 plugins/sudoers/pwutil.c:643
+#: plugins/sudoers/pwutil.c:704 plugins/sudoers/pwutil.c:753
+#, c-format
+msgid "unable to cache group %s"
+msgstr "kan inte cacha grupp %s"
+
+#: plugins/sudoers/pwutil.c:638
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "kan inte cacha grupp %s, finns redan"
+
+#: plugins/sudoers/pwutil.c:900 plugins/sudoers/pwutil.c:985
+#: plugins/sudoers/pwutil.c:1039 plugins/sudoers/pwutil.c:1095
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "kan inte cacha grupplista för %s, finns redan"
+
+#: plugins/sudoers/pwutil.c:906 plugins/sudoers/pwutil.c:990
+#: plugins/sudoers/pwutil.c:1045 plugins/sudoers/pwutil.c:1100
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "kan inte cacha grupplista för %s"
+
+#: plugins/sudoers/pwutil.c:979
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "kan inte tolka grupper för %s"
+
+#: plugins/sudoers/pwutil.c:1089
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "kan inte tolka gids för %s"
+
+#: plugins/sudoers/set_perms.c:120 plugins/sudoers/set_perms.c:457
+#: plugins/sudoers/set_perms.c:870 plugins/sudoers/set_perms.c:1186
+#: plugins/sudoers/set_perms.c:1490
+msgid "perm stack overflow"
+msgstr "perm-stackspill"
+
+#: plugins/sudoers/set_perms.c:131 plugins/sudoers/set_perms.c:387
+#: plugins/sudoers/set_perms.c:468 plugins/sudoers/set_perms.c:736
+#: plugins/sudoers/set_perms.c:881 plugins/sudoers/set_perms.c:1109
+#: plugins/sudoers/set_perms.c:1197 plugins/sudoers/set_perms.c:1422
+#: plugins/sudoers/set_perms.c:1501 plugins/sudoers/set_perms.c:1592
+msgid "perm stack underflow"
+msgstr "perm-stackunderspill"
+
+#: plugins/sudoers/set_perms.c:191 plugins/sudoers/set_perms.c:515
+#: plugins/sudoers/set_perms.c:1251 plugins/sudoers/set_perms.c:1535
+msgid "unable to change to root gid"
+msgstr "kan inte ändra till root-gid"
+
+#: plugins/sudoers/set_perms.c:282 plugins/sudoers/set_perms.c:612
+#: plugins/sudoers/set_perms.c:1013 plugins/sudoers/set_perms.c:1328
+msgid "unable to change to runas gid"
+msgstr "kan inte ändra till runas-gid"
+
+#: plugins/sudoers/set_perms.c:287 plugins/sudoers/set_perms.c:617
+#: plugins/sudoers/set_perms.c:1018 plugins/sudoers/set_perms.c:1333
+msgid "unable to set runas group vector"
+msgstr "kan inte ställa in gruppvektor för runas"
+
+#: plugins/sudoers/set_perms.c:298 plugins/sudoers/set_perms.c:628
+#: plugins/sudoers/set_perms.c:1027 plugins/sudoers/set_perms.c:1342
+msgid "unable to change to runas uid"
+msgstr "kan inte ändra till runas-uid"
+
+#: plugins/sudoers/set_perms.c:320 plugins/sudoers/set_perms.c:650
+#: plugins/sudoers/set_perms.c:1047 plugins/sudoers/set_perms.c:1362
+msgid "unable to change to sudoers gid"
+msgstr "kan inte ändra till sudoers-gid"
+
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579
+msgid "too many processes"
+msgstr "för många processer"
+
+#: plugins/sudoers/solaris_audit.c:62
+msgid "unable to get current working directory"
+msgstr "kan inte hämta aktuell arbetskatalog"
+
+#: plugins/sudoers/solaris_audit.c:70
+#, c-format
+msgid "truncated audit path ctx->user.cmnd: %s"
+msgstr "trunkerad granskningssökväg ctx->user_cmnd: %s"
+
+#: plugins/sudoers/solaris_audit.c:77
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "trunkerad granskningssökväg argv[0]: %s"
+
+#: plugins/sudoers/sssd.c:581
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "kan inte initiera SSS-källa. Är SSSD installerat på din maskin?"
+
+#: plugins/sudoers/sssd.c:589 plugins/sudoers/sssd.c:598
+#: plugins/sudoers/sssd.c:607 plugins/sudoers/sssd.c:616
+#: plugins/sudoers/sssd.c:625
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "kan inte hitta symbol ”%s” i %s"
+
+#: plugins/sudoers/sudoers.c:250
+#, c-format
+msgid "unable to get defaults from %s"
+msgstr "kan inte hämta standardvärden från %s"
+
+#: plugins/sudoers/sudoers.c:259
+msgid "no valid sudoers sources found, quitting"
+msgstr "inga giltiga sudoers-källor hittades, avslutar"
+
+#: plugins/sudoers/sudoers.c:366
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers anger att root inte tillåts att använda sudo"
+
+#: plugins/sudoers/sudoers.c:375
+msgid "user not allowed to override closefrom limit"
+msgstr "användare inte tillåten att åsidosätta closefrom-begränsning"
+
+#: plugins/sudoers/sudoers.c:376
+msgid "you are not permitted to use the -C option"
+msgstr "du tillåts inte att använda flaggan -C"
+
+#: plugins/sudoers/sudoers.c:440
+msgid "no tty"
+msgstr "ingen tty"
+
+#: plugins/sudoers/sudoers.c:441
+msgid "sorry, you must have a tty to run sudo"
+msgstr "tyvärr, du måste ha en tty för att köra sudo"
+
+#: plugins/sudoers/sudoers.c:449
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "ogiltigt skal för användare %s: %s"
+
+#: plugins/sudoers/sudoers.c:491
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "användare inte tillåten att ändra rotkatalog till %s"
+
+#: plugins/sudoers/sudoers.c:493
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "du tillåts inte att använda flaggan -R med %s"
+
+#: plugins/sudoers/sudoers.c:506
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "användare inte tillåten att ändra katalog till %s"
+
+#: plugins/sudoers/sudoers.c:507
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "du tillåts inte att använda flaggan -D med %s"
+
+#: plugins/sudoers/sudoers.c:542
+msgid "command in current directory"
+msgstr "kommando i aktuell katalog"
+
+#: plugins/sudoers/sudoers.c:557
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr "”cd” är ett inbyggt shell-kommando, det kan inte köras direkt."
+
+#: plugins/sudoers/sudoers.c:559
+msgid "the -s option may be used to run a privileged shell."
+msgstr "flaggan -s får inte användas för att köra ett privilegierat skal."
+
+#: plugins/sudoers/sudoers.c:561
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr "flaggan -D får inte användas för att köra ett kommando i en specifik katalog."
+
+#: plugins/sudoers/sudoers.c:570
+msgid "user not allowed to set a command timeout"
+msgstr "användare inte tillåten att ställa in en tidsgräns för kommandon"
+
+#: plugins/sudoers/sudoers.c:572
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "tyvärr, du tillåts inte att ställa in en tidsgräns för kommandon"
+
+#: plugins/sudoers/sudoers.c:580
+msgid "user not allowed to preserve the environment"
+msgstr "användare inte tillåten att behålla miljön"
+
+#: plugins/sudoers/sudoers.c:582
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "tyvärr, du tillåts inte att behålla miljövariabler"
+
+#: plugins/sudoers/sudoers.c:618
+msgid "no command specified"
+msgstr "inget kommando specificerat"
+
+#: plugins/sudoers/sudoers.c:759
+msgid "error setting user-specified environment variables"
+msgstr "fel vid sättning av användarspecificerade miljövariabler"
+
+#: plugins/sudoers/sudoers.c:1211
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "sudoedit behöver inte köras via sudo"
+
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:1613
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "kan inte läsa %s"
+
+#: plugins/sudoers/sudoers.c:1321 plugins/sudoers/visudo.c:1123
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s är inte en vanlig fil"
+
+#: plugins/sudoers/sudoers.c:1325 plugins/sudoers/timestamp.c:272 toke.l:1355
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s ägs av uid %u, ska vara %u"
+
+#: plugins/sudoers/sudoers.c:1330 plugins/sudoers/timestamp.c:279 toke.l:1360
+#, c-format
+msgid "%s is world writable"
+msgstr "%s är skrivbar för alla"
+
+#: plugins/sudoers/sudoers.c:1334 plugins/sudoers/timestamp.c:284 toke.l:1363
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s ägs av gid %u, ska vara %u"
+
+#: plugins/sudoers/sudoers.c:1363
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "endast root kan använda ”-c %s”"
+
+#: plugins/sudoers/sudoers.c:1382
+#, c-format
+msgid "unknown login class %s"
+msgstr "okänd inloggningsklass %s"
+
+#: plugins/sudoers/sudoers_cb.c:120 plugins/sudoers/sudoers_cb.c:135
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "kan inte slå upp värddatorn %s"
+
+#: plugins/sudoers/sudoreplay.c:252
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "ogiltig filterflagga: %s"
+
+#: plugins/sudoers/sudoreplay.c:268
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "ogiltig största väntan: %s"
+
+#: plugins/sudoers/sudoreplay.c:291
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "ogiltig hastighetsfaktor: %s"
+
+#: plugins/sudoers/sudoreplay.c:326
+#, c-format
+msgid "invalid time offset %s"
+msgstr "ogiltigt värde för tidsavstånd %s"
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:340
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/tidsmätning: %s"
+
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Spelar upp sudo-session: %s"
+
+#: plugins/sudoers/sudoreplay.c:634
+msgid "unable to set tty to raw mode"
+msgstr "kan inte ställa in tty i råläge"
+
+#: plugins/sudoers/sudoreplay.c:685
+msgid "Warning: your terminal is too small to properly replay the log."
+msgstr "Varning: din terminal är för liten för att korrekt spela upp loggen."
+
+#: plugins/sudoers/sudoreplay.c:686
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Logg-geometri är %d x %d, din terminals geometri är %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:714
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Uppspelning avslutad, tryck på en tangent för att återställa terminalen."
+
+#: plugins/sudoers/sudoreplay.c:1217 plugins/sudoers/sudoreplay.c:1247
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "tvetydigt uttryck ”%s”"
+
+#: plugins/sudoers/sudoreplay.c:1269
+msgid "unmatched ')' in expression"
+msgstr "omatchat ”)” i uttryck"
+
+#: plugins/sudoers/sudoreplay.c:1273
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "okänt sökvillkor ”%s”"
+
+#: plugins/sudoers/sudoreplay.c:1288
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s kräver ett argument"
+
+#: plugins/sudoers/sudoreplay.c:1298
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "kunde inte tolka datumet ”%s”"
+
+#: plugins/sudoers/sudoreplay.c:1307
+msgid "unmatched '(' in expression"
+msgstr "omatchat ”(” i uttryck"
+
+#: plugins/sudoers/sudoreplay.c:1309
+msgid "illegal trailing \"or\""
+msgstr "ogiltigt avslutande ”or”"
+
+#: plugins/sudoers/sudoreplay.c:1311
+msgid "illegal trailing \"!\""
+msgstr "ogiltigt efterföljande ”!”"
+
+#: plugins/sudoers/sudoreplay.c:1417
+#, c-format
+msgid "unknown search type %d"
+msgstr "okänd söktyp %d"
+
+#: plugins/sudoers/sudoreplay.c:1679
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "användning: %s [-hnRS] [-d kat] [-m num] [-s num] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1681
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "användning: %s [-h] [-d kat] -l [sökuttryck]\n"
+
+#: plugins/sudoers/sudoreplay.c:1695
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - spela upp loggar från sudo-session\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1697
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Flaggor:\n"
+" -d, --directory=kat ange katalog för sessionsloggar\n"
+" -f, --filter=filter ange vilka I/O-typer som ska visas\n"
+" -h, --help visa hjälptext och avsluta\n"
+" -l, --list lista tillgängliga sessions-ID:n, med valfritt uttryck\n"
+" -m, --max-wait=num största antal sekunder att vänta mellan händelser\n"
+" -n, --non-interactive inga frågor, sessionen skickas till standard ut\n"
+" -R, --no-resize försök inte att ändra storlek på terminalen\n"
+" -S, --suspend-wait vänta medan kommandot var i viloläge\n"
+" -s, --speed=num påskynda eller fördröj utmatning\n"
+" -V, --version visa versionsinformation och avsluta"
+
+#: plugins/sudoers/testsudoers.c:392
+#, c-format
+msgid ""
+"\n"
+"Invalid shell for user %s: %s\n"
+msgstr ""
+"\n"
+"Ogiltigt skal för användare %s: %s\n"
+
+#: plugins/sudoers/testsudoers.c:411
+msgid ""
+"\n"
+"Password required"
+msgstr ""
+"\n"
+"Ett lösenord krävs"
+
+#: plugins/sudoers/testsudoers.c:422
+msgid ""
+"\n"
+"Parse error"
+msgstr ""
+"\n"
+"Tolkningsfel"
+
+#: plugins/sudoers/testsudoers.c:425
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Kommandot tillåts"
+
+#: plugins/sudoers/testsudoers.c:428
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Kommandot nekades"
+
+#: plugins/sudoers/testsudoers.c:431
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Kommando omatchat"
+
+#: plugins/sudoers/timestamp.c:364 plugins/sudoers/timestamp.c:711
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "kan inte trunkera tidsstämpelfil till %lld byte"
+
+#: plugins/sudoers/timestamp.c:908
+msgid "ignoring time stamp from the future"
+msgstr "ignorerar tidsstämpel från framtiden"
+
+#: plugins/sudoers/timestamp.c:931
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "tidsstämpel är för långt in i framtiden: %20.20s"
+
+#: plugins/sudoers/timestamp.c:1067
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "kan inte låsa tidsstämpelfil %s"
+
+#: plugins/sudoers/timestamp.c:1114
+#, c-format
+msgid "%s:%d:%d timestampowner: unknown user %s"
+msgstr "%s:%d:%d: tidstämpelägare: okänd användare %s"
+
+#: plugins/sudoers/toke_util.c:159
+msgid "sudoedit should not be specified with a path"
+msgstr "sudoedit ska inte anges med en sökväg"
+
+#: plugins/sudoers/visudo.c:308 plugins/sudoers/visudo.c:714
+#, c-format
+msgid "press return to edit %s: "
+msgstr "tryck på retur för att redigera %s: "
+
+#: plugins/sudoers/visudo.c:323
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "innehållet från redigeringssessionen lämnat i %s"
+
+#: plugins/sudoers/visudo.c:401
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "angiven textredigerare (%s) finns inte"
+
+#: plugins/sudoers/visudo.c:406
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "ingen textredigerare hittad (sökväg för textredigerare = %s)"
+
+#: plugins/sudoers/visudo.c:494 plugins/sudoers/visudo.c:786
+#, c-format
+msgid "unable to stat %s"
+msgstr "kan inte ta status på %s"
+
+#: plugins/sudoers/visudo.c:514 plugins/sudoers/visudo.c:522
+msgid "write error"
+msgstr "skrivfel"
+
+#: plugins/sudoers/visudo.c:568
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "kan inte hämta filinformation för temporärfil (%s), %s oförändrad"
+
+# sebras: not an exact translation, but I think it captures the meaning of the original text.
+#: plugins/sudoers/visudo.c:575
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "temporärfil tom (%s), %s oförändrad"
+
+#: plugins/sudoers/visudo.c:581
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "textredigeraren (%s) misslyckades, %s är oförändrad"
+
+#: plugins/sudoers/visudo.c:613
+#, c-format
+msgid "%s unchanged"
+msgstr "%s oförändrad"
+
+#: plugins/sudoers/visudo.c:661
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "kan inte återöppna temporärfil (%s), %s är oförändrad."
+
+#: plugins/sudoers/visudo.c:674
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "kan inte tolka temporärfil (%s), okänt fel"
+
+#: plugins/sudoers/visudo.c:760 plugins/sudoers/visudo.c:790
+#: plugins/sudoers/visudo.c:797
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "kan inte ställa in (uid, gid) för %s till (%u, %u)"
+
+#: plugins/sudoers/visudo.c:825
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s och %s finns inte på samma filsystem, använder mv för att byta namn"
+
+#: plugins/sudoers/visudo.c:836
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "kommandot misslyckades: ”%s %s %s”, %s är oförändrad"
+
+#: plugins/sudoers/visudo.c:843
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "fel vid namnbyte för %s, %s är oförändrad"
+
+#: plugins/sudoers/visudo.c:864
+msgid "What now? "
+msgstr "Nu då? "
+
+#: plugins/sudoers/visudo.c:878
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Alternativen är:\n"
+" r(e)digera sudoers-filen igen\n"
+" avsluta (x) utan att spara ändringar i sudoers-filen\n"
+" Avsluta (Q) och spara ändringar i sudoers-filen (FARLIGT!)\n"
+
+#: plugins/sudoers/visudo.c:923
+#, c-format
+msgid "unable to run %s"
+msgstr "kan inte köra %s"
+
+#: plugins/sudoers/visudo.c:954
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: felaktig ägare (uid, gid) ska vara (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:965
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: felaktiga rättigheter, bör vara läge 0%o\n"
+
+#: plugins/sudoers/visudo.c:1017 plugins/sudoers/visudo.c:1024
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: tolkad OK\n"
+
+#: plugins/sudoers/visudo.c:1043
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s är upptagen, försök igen senare"
+
+#: plugins/sudoers/visudo.c:1047
+msgid "Edit anyway? [y/N]"
+msgstr "Redigera ändå? [y/N]"
+
+#: plugins/sudoers/visudo.c:1206
+msgid "the -x option will be removed in a future release"
+msgstr "flaggan -x kommer att tas bort i en framtida version"
+
+#: plugins/sudoers/visudo.c:1208
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "överväg att använda verktyget cvtsudoers istället"
+
+#: plugins/sudoers/visudo.c:1228
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "Varning: %s:%d:%d: oanvänd %s ”%s”"
+
+#: plugins/sudoers/visudo.c:1341
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - redigera sudoers-filen på ett säkert sätt\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1343
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -I, --no-includes do not edit include files\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Flaggor:\n"
+" -c, --check genomför endast kontroller\n"
+" -f, --file=sudoers ange plats för sudoers-filen\n"
+" -h, --help visa hjälptext och avsluta\n"
+" -I, --no-includes redigera inte include-filer\n"
+" -q, --quiet mindre utförliga (tysta) syntaxfelmeddelanden\n"
+" -s, --strict strikt syntaxkontroll\n"
+" -V, --version visa versionsinformation och avsluta\n"
+
+#: toke.l:184
+msgid "empty string"
+msgstr "tom sträng"
+
+#: toke.l:196 toke.l:566
+msgid "empty group"
+msgstr "tom grupp"
+
+#: toke.l:206 toke.l:564
+msgid "empty netgroup"
+msgstr "tom nätgrupp"
+
+#: toke.l:284
+msgid "unterminated regular expression"
+msgstr "oavslutat reguljärt uttryck"
+
+#: toke.l:358 toke.l:370 toke.l:382 toke.l:398 toke.l:417 toke.l:457
+msgid "invalid line continuation"
+msgstr "ogiltig radfortsättning"
+
+#: toke.l:603 toke.l:615
+msgid "invalid IPv6 address"
+msgstr "ogiltig IPv6-adress"
+
+#: toke.l:863
+msgid "unexpected line break in string"
+msgstr "oväntad radbrytning i sträng"
+
+#: toke.l:982
+msgid "ignoring editor backup file"
+msgstr "ignorerar säkerhetskopiefil för textredigerare"
+
+#: toke.l:985
+msgid "ignoring file name containing '.'"
+msgstr "ignorerar filnamn som innehåller ”.”"
+
+#: toke.l:1310
+msgid "too many levels of includes"
+msgstr "för många nivåer av inkluderingar"
+
+#, c-format
+#~ msgid "timestamp owner (%s): No such user"
+#~ msgstr "tidsstämpelägare (%s): Det finns ingen sådan användare"
+
+#~ msgid "\thost unmatched"
+#~ msgstr "\tvärd omatchad"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s måste ägas av uid %d"
+
+#~ msgid "%s must only be writable by owner"
+#~ msgstr "%s får endast vara skrivbar av ägaren"
+
+#~ msgid "%s:%d unknown key: %s"
+#~ msgstr "%s:%d okänd nyckel: %s"
+
+#~ msgid "%s: write buffer already in use"
+#~ msgstr "%s: skrivbuffert används redan"
+
+#~ msgid "unable to read diffie-hellman parameters: %s"
+#~ msgstr "kunde inte läsa diffie-hellman-parametrar: %s"
+
+#~ msgid "Error: %s:%d:%d: cycle in %s \"%s\""
+#~ msgstr "Fel: %s:%d:%d: cykel i %s ”%s”"
+
+#~ msgid "Warning: %s:%d:%d: cycle in %s \"%s\""
+#~ msgstr "Varning: %s:%d:%d: cykel i %s ”%s”"
+
+#~ msgid "Error: %s:%d:%d: %s \"%s\" referenced but not defined"
+#~ msgstr "Fel: %s:%d:%d: %s ”%s” refererad till men inte definierad"
+
+#~ msgid "Warning: %s:%d:%d: %s \"%s\" referenced but not defined"
+#~ msgstr "Varning: %s:%d:%d: %s ”%s” refererad till men inte definierad"
+
+#~ msgid "parse error in %s near line %d\n"
+#~ msgstr "tolkningsfel i %s nära rad %d\n"
+
+#~ msgid "parse error in %s\n"
+#~ msgstr "tolkningsfel i %s\n"
+
+#~ msgid "%s: unknown defaults entry \"%s\""
+#~ msgstr "%s: okänd standardpost ”%s”"
+
+#~ msgid "%s:%d:%d: no value specified for \"%s\""
+#~ msgstr "%s:%d:%d: inget värde angivet för ”%s”"
+
+#~ msgid "%s:%d:%d: option \"%s\" does not take a value"
+#~ msgstr "%s:%d:%d: flaggan ”%s” tar inte emot något värde"
+
+#~ msgid "%s:%d:%d: value \"%s\" is invalid for option \"%s\""
+#~ msgstr "%s:%d:%d: värdet ”%s” är ogiltigt för flaggan ”%s”"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/', '~', or '*'"
+#~ msgstr "%s:%d:%d: värden för ”%s” måste börja med ett ”/”, ”~” eller ”*”"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/'"
+#~ msgstr "%s:%d:%d: värden för ”%s” måste börja med ett ”/”"
+
+#~ msgid "parse error in %s near line %d"
+#~ msgstr "tolkningsfel i %s nära rad %d"
+
+#~ msgid "parse error in %s"
+#~ msgstr "tolkningsfel i %s"
+
+#~ msgid "%s is not in the sudoers file. This incident will be reported.\n"
+#~ msgstr "%s finns inte i filen sudoers. Denna incident kommer att rapporteras.\n"
+
+#~ msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+#~ msgstr "%s tillåts inte att köra sudo på %s. Denna incident kommer att rapporteras.\n"
+
+#~ msgid "problem with defaults entries"
+#~ msgstr "problem med standardposter"
+
+#~ msgid "%s is group writable"
+#~ msgstr "%s är skrivbar för gruppen"
+
+#~ msgid "lecture status path too long: %s/%s"
+#~ msgstr "sökväg för lektionsstatus för lång: %s/%s"
+
+#~ msgid "internal error, unable to find %s in list!"
+#~ msgstr "internt fel, kan inte hitta %s i listan!"
+
+#~ msgid "%s:%u unable to parse \"%s\""
+#~ msgstr "%s:%u kan inte tolka ”%s”"
+
+#~ msgid "unable to get TLS server method: %s"
+#~ msgstr "kan inte hämta TLS-servermetod: %s"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " -f, --file path to configuration file\n"
+#~ " -h --help display help message and exit\n"
+#~ " -n, --no-fork do not fork, run in the foreground\n"
+#~ " -R, --random-drop percent chance connections will drop\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Flaggor:\n"
+#~ " -f, --file sökväg till konfigurationsfil\n"
+#~ " -h --help visa hjälptext och avslutan\n"
+#~ " -n, --no-fork grena inte, kör i förgrunden\n"
+#~ " -R, --random-drop antal procents chans att anslutningar bryts\n"
+#~ " -V, --version visa versionsinformation och avsluta\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " --help display help message and exit\n"
+#~ " -A, --accept only send an accept event (no I/O)\n"
+#~ " -h, --host host to send logs to\n"
+#~ " -i, --iolog_id remote ID of I/O log to be resumed\n"
+#~ " -p, --port port to use when connecting to host\n"
+#~ " -r, --restart restart previous I/O log transfer\n"
+#~ " -R, --reject reject the command with the given reason\n"
+#~ " -b, --ca-bundle certificate bundle file to verify server's cert against\n"
+#~ " -c, --cert certificate file for TLS handshake\n"
+#~ " -k, --key private key file\n"
+#~ " -n, --no-verify do not verify server certificate\n"
+#~ " -t, --test test audit server by sending selected I/O log n times in parallel\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Flaggor:\n"
+#~ " --help visa hjälpmeddelande och avsluta\n"
+#~ " -A, --accept skicka endast en accepteringshändelse (ingen I/O)\n"
+#~ " -h, --host värd att skicka loggar till\n"
+#~ " -i, --iolog_id fjärr-ID för I/O-logg som ska återupptas\n"
+#~ " -p, --port port att använda vid anslutning till värd\n"
+#~ " -r, --restart start om förgående överföring av I/O-logg\n"
+#~ " -R, --reject avböj kommandot med angiven anledning\n"
+#~ " -b, --ca-bundle certifikatbuntfil att verifiera serverns certifikat mot\n"
+#~ " -c, --cert certifikatfil för TLS-handskakning\n"
+#~ " -k, --key privat nyckelfil\n"
+#~ " -n, --no-verify verifiera inter servercertifikat\n"
+#~ " -t, --test testa granskningsserver genom att skicka valda I/O-loggmeddelanden parallellt n gånger\n"
+#~ " -V, --version visa versionsinformation och avsluta\n"
+
+#~ msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+#~ msgstr "Förinläs attrapp-exec-funktioner som finns i biblioteket sudo_noexec"
+
+#~ msgid "sudo_ldap_conf_add_ports: port too large"
+#~ msgstr "sudo_ldap_conf_add_ports: port är för stor"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s\n"
+#~ msgstr "SSL_connect misslyckades: ssl_error=%d, stack=%s\n"
+
+#~ msgid "CA bundle file was not specified"
+#~ msgstr "Fil för CA-bunt angavs inte"
+
+#~ msgid "Client certificate was not specified"
+#~ msgstr "Klientcertifikat angavs inte"
+
+#~ msgid "Unable to allocate ssl object: %s\n"
+#~ msgstr "Kan inte allokera ssl-objekt: %s\n"
+
+#~ msgid "Unable to attach socket to the ssl object: %s\n"
+#~ msgstr "Kan inte fästa kontakt på ssl-objektet: %s\n"
+
+#~ msgid "client message too large: %zu\n"
+#~ msgstr "klientmeddelande för stort: %zu\n"
+
+#~ msgid "server message too large: %u\n"
+#~ msgstr "servermeddelande för långt: %u\n"
+
+#~ msgid "CA bundle file is not set in sudoers"
+#~ msgstr "CA-buntfil inte inställd i sudoers"
+
+#~ msgid "Calling SSL_CTX_load_verify_locations() failed: %s"
+#~ msgstr "Anrop av SSL_CTX_load_verify_locations() misslyckades: %s"
+
+#~ msgid "Signed certificate file is not set in sudoers"
+#~ msgstr "Signerad certifikatfil inte inställd i sudoers"
+
+#~ msgid "Unable to load private key into the ssl context: %s"
+#~ msgstr "Kan inte läsa in privatnyckel in i ssl-kontexten: %s"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_connect misslyckades: ssl_error=%d, stack=%s"
+
+#~ msgid "SSL_read failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_read misslyckades: ssl_error=%d, stack=%s"
+
+#~ msgid "SSL_write failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_write misslyckades: ssl_error=%d, stack=%s"
+
+#~ msgid "unknown address family: %d"
+#~ msgstr "okänd adressfamilj: %d"
+
+#~ msgid "audit_failure message too long"
+#~ msgstr "audit_failure-meddelande för långt"
+
+#~ msgid "No user or host"
+#~ msgstr "Ingen användare eller värddator"
+
+#~ msgid "validation failure"
+#~ msgstr "valideringsfel"
+
+#~ msgid "%s/%s/timing: %s"
+#~ msgstr "%s/%s/tidsmätning: %s"
+
+#~ msgid "ignoring invalid attribute value: %s"
+#~ msgstr "ignorerar ogiltigt attributvärde: %s"
+
+#~ msgid "unable to cache user %s, out of memory"
+#~ msgstr "kan inte cacha användare %s, slut på minne"
+
+#~ msgid "unable to cache group %s, out of memory"
+#~ msgstr "kan inte cacha grupp %s, slut på minne"
+
+#~ msgid "unable to cache group list for %s, out of memory"
+#~ msgstr "kan inte cacha grupplista för %s, slut på minne"
+
+#~ msgid ""
+#~ "\n"
+#~ "LDAP Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "LDAP-roll: OKÄND\n"
+
+#~ msgid " Order: %s\n"
+#~ msgstr " Ordning: %s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: %s\n"
+#~ msgstr ""
+#~ "\n"
+#~ "SSSD-roll: %s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "SSSD-roll: OKÄND\n"
+
+#~ msgid "getaudit: failed"
+#~ msgstr "getaudit: misslyckades"
+
+#~ msgid "getauid failed"
+#~ msgstr "getauid misslyckades"
+
+#~ msgid "au_to_subject: failed"
+#~ msgstr "au_to_subject: misslyckades"
+
+#~ msgid "au_to_exec_args: failed"
+#~ msgstr "au_to_exec_args: misslyckades"
+
+#~ msgid "au_to_return32: failed"
+#~ msgstr "au_to_return32: misslyckades"
+
+#~ msgid "getauid: failed"
+#~ msgstr "getauid: misslyckades"
+
+#~ msgid "au_to_text: failed"
+#~ msgstr "au_to_text: misslyckades"
+
+#~ msgid "internal error, expand_prompt() overflow"
+#~ msgstr "internt fel, stackspill i expand_prompt()"
+
+#~ msgid "%s owned by uid %u, should be uid %u"
+#~ msgstr "%s ägs av uid %u, ska vara uid %u"
+
+#~ msgid "%s exists but is not a regular file (0%o)"
+#~ msgstr "%s finns men är inte en vanlig fil (0%o)"
+
+#~ msgid "internal error, sudo_setenv2() overflow"
+#~ msgstr "internt fel, stackspill i sudo_setenv2()"
+
+#~ msgid "internal error, sudo_setenv() overflow"
+#~ msgstr "internt fel, stackspill i sudo_setenv()"
+
+#~ msgid ">>> %s: %s near line %d <<<"
+#~ msgstr ">>> %s: %s nära rad %d <<<"
+
+#~ msgid "unable to set locale to \"%s\", using \"C\""
+#~ msgstr "kunde inte ställa in lokalanpassning till \"%s\", använder \"C\""
+
+#~ msgid "unable to mix ldaps and starttls"
+#~ msgstr "kunde inte blanda ldaps och starttls"
+
+#~ msgid "internal error, linux_audit_command() overflow"
+#~ msgstr "internt fel, stackspill i linux_audit_command()"
+
+#~ msgid "internal error: insufficient space for log line"
+#~ msgstr "internt fel: otillräckligt utrymme för loggrad"
+
+#~ msgid ""
+#~ " Commands:\n"
+#~ "\t"
+#~ msgstr ""
+#~ " Kommandon:\n"
+#~ "\t"
+
+#~ msgid ": "
+#~ msgstr ": "
+
+#~ msgid "unable to cache uid %u (%s), already exists"
+#~ msgstr "kunde inte mellanlagra uid %u (%s), finns redan"
+
+#~ msgid "unable to cache gid %u (%s), already exists"
+#~ msgstr "kunde inte mellanlagra gid %u (%s), finns redan"
+
+#~ msgid "internal error, runas_groups overflow"
+#~ msgstr "internt fel, stackspill i runas_groups"
+
+#~ msgid "writing to standard output"
+#~ msgstr "skriver till standard ut"
+
+#~ msgid "internal error, init_vars() overflow"
+#~ msgstr "internt fel, stackspill i init_vars()"
+
+#~ msgid "fill_args: buffer overflow"
+#~ msgstr "fill_args: buffertöverflöde"
+
+#~ msgid "pam_chauthtok: %s"
+#~ msgstr "pam_chauthtok: %s"
+
+#~ msgid "pam_authenticate: %s"
+#~ msgstr "pam_authenticate: %s"
+
+#~ msgid "Password:"
+#~ msgstr "Lösenord:"
diff --git a/plugins/sudoers/po/tr.mo b/plugins/sudoers/po/tr.mo
new file mode 100644
index 0000000..da71fd4
--- /dev/null
+++ b/plugins/sudoers/po/tr.mo
Binary files differ
diff --git a/plugins/sudoers/po/tr.po b/plugins/sudoers/po/tr.po
new file mode 100644
index 0000000..a7b94d3
--- /dev/null
+++ b/plugins/sudoers/po/tr.po
@@ -0,0 +1,1721 @@
+# Turkish translations for sudoers package
+# This file is put in the public domain.
+# Todd C. Miller <Todd.Miller@courtesan.com>, 2011-2013
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.8.7b2\n"
+"Report-Msgid-Bugs-To: http://www.sudo.ws/bugs\n"
+"POT-Creation-Date: 2013-04-17 15:52-0400\n"
+"PO-Revision-Date: 2013-04-27 23:41+0200\n"
+"Last-Translator: Özgür Sarıer <ozgursarier1011601115@gmail.com>\n"
+"Language-Team: Turkish <gnu-tr-u12a@lists.sourceforge.net>\n"
+"Language: tr\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 1.5.5\n"
+
+#: confstr.sh:2
+msgid "Password:"
+msgstr "Parola:"
+
+#: confstr.sh:3
+msgid "*** SECURITY information for %h ***"
+msgstr "*** %h için GÜVENLİK bilgisi ***"
+
+#: confstr.sh:4
+msgid "Sorry, try again."
+msgstr "Üzgünüm, yeniden deneyin."
+
+#: plugins/sudoers/alias.c:124
+#, c-format
+msgid "Alias `%s' already defined"
+msgstr "Takma ad `%s' önceden tanımlanmış"
+
+#: plugins/sudoers/auth/bsdauth.c:77
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "kullanıcı %s için oturum açma sınıfı elde edilemedi"
+
+#: plugins/sudoers/auth/bsdauth.c:83
+msgid "unable to begin bsd authentication"
+msgstr "bsd kimlik doğrulama işlemine başlanılamadı"
+
+#: plugins/sudoers/auth/bsdauth.c:91
+msgid "invalid authentication type"
+msgstr "geçersiz kimlik doğrulama türü"
+
+#: plugins/sudoers/auth/bsdauth.c:100
+msgid "unable to setup authentication"
+msgstr "kimlik doğrulama gerçekleştirilemedi"
+
+#: plugins/sudoers/auth/fwtk.c:59
+#, c-format
+msgid "unable to read fwtk config"
+msgstr "fwtk yapılandırması okunamadı"
+
+#: plugins/sudoers/auth/fwtk.c:64
+#, c-format
+msgid "unable to connect to authentication server"
+msgstr "kimlik doğrulama sunucusuna bağlanılamadı"
+
+#: plugins/sudoers/auth/fwtk.c:70 plugins/sudoers/auth/fwtk.c:94
+#: plugins/sudoers/auth/fwtk.c:127
+#, c-format
+msgid "lost connection to authentication server"
+msgstr "kimlik doğrulama sunucusunda bağlantı kaybı"
+
+#: plugins/sudoers/auth/fwtk.c:74
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"kimlik doğrulama sunucusu hatası:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:116
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:159
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: ayrıştırılamayan öge '%s': %s"
+
+#: plugins/sudoers/auth/kerb5.c:169
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: kimlik bilgisi önbelleği çözülemedi: %s"
+
+#: plugins/sudoers/auth/kerb5.c:217
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: seçenekler ayrılamadı: %s"
+
+#: plugins/sudoers/auth/kerb5.c:233
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: kimlik bilgileri elde edilemedi: %s"
+
+#: plugins/sudoers/auth/kerb5.c:246
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: kimlik bilgisi önbelleği hazırlanamadı: %s"
+
+#: plugins/sudoers/auth/kerb5.c:250
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: kimlik bilgisi önbellekte saklanamadı: %s"
+
+#: plugins/sudoers/auth/kerb5.c:315
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr ""
+
+#: plugins/sudoers/auth/kerb5.c:330
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: TGT doğrulanamadı! Muhtemel saldırı!: %s"
+
+#: plugins/sudoers/auth/pam.c:105
+msgid "unable to initialize PAM"
+msgstr "PAM başlatılamadı"
+
+#: plugins/sudoers/auth/pam.c:150
+msgid "account validation failure, is your account locked?"
+msgstr "hesap geçerliliği teyit edilemedi, hesabınız kilitli mi?"
+
+#: plugins/sudoers/auth/pam.c:154
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Hesabın veya hesap parolasının süresi dolmuş, parolanızı sıfırlayınız ve yeniden deneyiniz"
+
+#: plugins/sudoers/auth/pam.c:162
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "zaman aşımına uğramış parola değiştirilemedi: %s"
+
+#: plugins/sudoers/auth/pam.c:167
+msgid "Password expired, contact your system administrator"
+msgstr "Parola geçerlilik süresi dolmuş, sistem yöneticinizle temasa geçiniz"
+
+#: plugins/sudoers/auth/pam.c:171
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Hesap geçerlilik süresi dolmuş veya sudo için PAM yapılandırması bir \"account\" bölümünden yoksun, sistem yöneticinizle temasa geçiniz"
+
+#: plugins/sudoers/auth/pam.c:188
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "PAM kimlik doğrulama hatası: %s"
+
+#: plugins/sudoers/auth/pam.c:247
+#, c-format
+msgid "unable to establish credentials: %s"
+msgstr "kimlik bilgileri oluşturulamadı: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:103 plugins/sudoers/visudo.c:212
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "%s veritabanında bulunmuyorsunuz"
+
+#: plugins/sudoers/auth/securid5.c:80
+#, c-format
+msgid "failed to initialise the ACE API library"
+msgstr "ACE API kütüphanesinin hazırlanması başarısız oldu"
+
+#: plugins/sudoers/auth/securid5.c:106
+#, c-format
+msgid "unable to contact the SecurID server"
+msgstr "SecurID sunucusuyla bağlantı kurulamadı"
+
+#: plugins/sudoers/auth/securid5.c:115
+#, c-format
+msgid "User ID locked for SecurID Authentication"
+msgstr "Kullanıcı Kimliği(User ID), SecurID Kimlik Doğrulaması için kilitli"
+
+#: plugins/sudoers/auth/securid5.c:119 plugins/sudoers/auth/securid5.c:170
+#, c-format
+msgid "invalid username length for SecurID"
+msgstr "SecurID için geçersiz kullanıcı adı uzunluğu"
+
+#: plugins/sudoers/auth/securid5.c:123 plugins/sudoers/auth/securid5.c:175
+#, c-format
+msgid "invalid Authentication Handle for SecurID"
+msgstr "SecurID için geçersiz Kimlik Doğrulama İşleyicisi"
+
+#: plugins/sudoers/auth/securid5.c:127
+#, c-format
+msgid "SecurID communication failed"
+msgstr "SecurID iletişimi başarısız oldu"
+
+#: plugins/sudoers/auth/securid5.c:131 plugins/sudoers/auth/securid5.c:214
+#, c-format
+msgid "unknown SecurID error"
+msgstr "bilinmeyen SecurID hatası"
+
+#: plugins/sudoers/auth/securid5.c:165
+#, c-format
+msgid "invalid passcode length for SecurID"
+msgstr "SecurID için geçersiz şifre uzunluğu"
+
+#: plugins/sudoers/auth/sia.c:108
+msgid "unable to initialize SIA session"
+msgstr "SIA oturumu başlatılamadı"
+
+#: plugins/sudoers/auth/sudo_auth.c:119
+msgid "invalid authentication methods"
+msgstr "geçersiz kimlik doğrulama yöntemleri"
+
+#: plugins/sudoers/auth/sudo_auth.c:120
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Sudo içinde geçersiz kimlik doğrulama yöntemleri derlenmiş! Bağımsız ve bağımsız olmayan kimlik doğrulama yöntemlerini karma bir şekilde kullanamayabilirsiniz."
+
+#: plugins/sudoers/auth/sudo_auth.c:203
+msgid "no authentication methods"
+msgstr "kimlik doğrulama yöntemleri yok"
+
+#: plugins/sudoers/auth/sudo_auth.c:205
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Sudo içinde herhangi bir kimlik doğrulama yöntemi derlenmemiş! Kimlik doğrulamayı kapatmak isterseniz, --disable-authentication seçeneğini kullanınız."
+
+#: plugins/sudoers/auth/sudo_auth.c:389
+msgid "Authentication methods:"
+msgstr "Kimlik doğrulama yöntemleri:"
+
+#: plugins/sudoers/bsm_audit.c:60 plugins/sudoers/bsm_audit.c:63
+#: plugins/sudoers/bsm_audit.c:112 plugins/sudoers/bsm_audit.c:116
+#: plugins/sudoers/bsm_audit.c:168 plugins/sudoers/bsm_audit.c:172
+#, c-format
+msgid "getaudit: failed"
+msgstr "getaudit: işlem başarısız"
+
+#: plugins/sudoers/bsm_audit.c:90 plugins/sudoers/bsm_audit.c:153
+#, c-format
+msgid "Could not determine audit condition"
+msgstr "Denetim durumu belirlenemedi"
+
+#: plugins/sudoers/bsm_audit.c:101 plugins/sudoers/bsm_audit.c:160
+#, c-format
+msgid "getauid: failed"
+msgstr "getauid: işlem başarısız"
+
+#: plugins/sudoers/bsm_audit.c:103 plugins/sudoers/bsm_audit.c:162
+#, c-format
+msgid "au_open: failed"
+msgstr "au_open: işlem başarısız"
+
+#: plugins/sudoers/bsm_audit.c:118 plugins/sudoers/bsm_audit.c:174
+#, c-format
+msgid "au_to_subject: failed"
+msgstr "au_to_subject: işlem başarısız"
+
+#: plugins/sudoers/bsm_audit.c:122 plugins/sudoers/bsm_audit.c:178
+#, c-format
+msgid "au_to_exec_args: failed"
+msgstr "au_to_exec_args: işlem başarısız"
+
+#: plugins/sudoers/bsm_audit.c:126 plugins/sudoers/bsm_audit.c:187
+#, c-format
+msgid "au_to_return32: failed"
+msgstr "au_to_return32: işlem başarısız"
+
+#: plugins/sudoers/bsm_audit.c:129 plugins/sudoers/bsm_audit.c:190
+#, c-format
+msgid "unable to commit audit record"
+msgstr "denetim kaydı işlenemiyor"
+
+#: plugins/sudoers/bsm_audit.c:183
+#, c-format
+msgid "au_to_text: failed"
+msgstr "au_to_text: işlem başarısız"
+
+#: plugins/sudoers/check.c:189
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Yerel Sistem Yöneticisinden olağan öğütleri aldığınıza güveniyoruz.\n"
+"Bunları genellikle aşağıdaki üç şeyle özetleyebiliriz:\n"
+"\n"
+" #1) Diğer kişilerin özel hayatına saygı gösterin.\n"
+" #2) Bir yazmadan önce iki kere düşünün.\n"
+" #3) Büyük gücün büyük bir sorumluluk getirdiğini unutmayın.\n"
+"\n"
+
+#: plugins/sudoers/check.c:227 plugins/sudoers/check.c:233
+#: plugins/sudoers/sudoers.c:562 plugins/sudoers/sudoers.c:566
+#, c-format
+msgid "unknown uid: %u"
+msgstr "bilinmeyen uid: %u"
+
+#: plugins/sudoers/check.c:230 plugins/sudoers/policy.c:635
+#: plugins/sudoers/sudoers.c:845 plugins/sudoers/testsudoers.c:215
+#: plugins/sudoers/testsudoers.c:359
+#, c-format
+msgid "unknown user: %s"
+msgstr "bilinmeyen kullanıcı: %s"
+
+#: plugins/sudoers/def_data.c:27
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:31
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:35
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:39
+msgid "Put OTP prompt on its own line"
+msgstr "OTP güdüsünü kendi satırına yerleştir"
+
+#: plugins/sudoers/def_data.c:43
+msgid "Ignore '.' in $PATH"
+msgstr "$PATH içindeki '.' ögesini yoksay"
+
+#: plugins/sudoers/def_data.c:47
+msgid "Always send mail when sudo is run"
+msgstr "Sudonun çalıştırıldığı her zaman e-posta gönder"
+
+#: plugins/sudoers/def_data.c:51
+msgid "Send mail if user authentication fails"
+msgstr "Kullanıcı kimlik doğrulaması başarısız olursa e-posta gönder"
+
+#: plugins/sudoers/def_data.c:55
+msgid "Send mail if the user is not in sudoers"
+msgstr "Kullanıcı sudoers içinde değilse e-posta gönder"
+
+#: plugins/sudoers/def_data.c:59
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Kullanıcı bu makinedeki sudoers içinde değilse e-posta gönder"
+
+#: plugins/sudoers/def_data.c:63
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Kullanıcının bir komut çalıştırmasına izin verilmiyor ise e-posta gönder"
+
+#: plugins/sudoers/def_data.c:67
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Her kullanıcı/tty birleşik girişi için ayrı bir zaman damgası kullan"
+
+#: plugins/sudoers/def_data.c:71
+msgid "Lecture user the first time they run sudo"
+msgstr "Sudoyu ilk defa çalıştırdıkları zaman kullanıcıya gerekli öğütleri ver"
+
+#: plugins/sudoers/def_data.c:75
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Dosya sudo öğüdü içeriyor: %s"
+
+#: plugins/sudoers/def_data.c:79
+msgid "Require users to authenticate by default"
+msgstr "Öntanımlı olarak kullanıcıların kimlik doğrulaması gerekmektedir"
+
+#: plugins/sudoers/def_data.c:83
+msgid "Root may run sudo"
+msgstr "Kök kullanıcı (root) sudoyu çalıştırabilir"
+
+#: plugins/sudoers/def_data.c:87
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:91
+msgid "Log the year in the (non-syslog) log file"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:95
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Eğer sudo herhangi bir bağımsız değişkenle uyandırılmazsa, bir kabuk başlat"
+
+#: plugins/sudoers/def_data.c:99
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Kabuğu -s ile başlatırken $HOME çevre değişkenini hedef kullanıcıya ata"
+
+#: plugins/sudoers/def_data.c:103
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Her zaman $HOME çevre değişkenini hedef kullanıcının ev dizinine ata"
+
+#: plugins/sudoers/def_data.c:107
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Yararlı hata iletilerinin verilmesi için bazı bilgilerin toplanmasına izin ver"
+
+#: plugins/sudoers/def_data.c:111
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Sudoers dosyası içerisinde tam nitelikli ana makine adlarının olması gerekmektedir"
+
+#: plugins/sudoers/def_data.c:115
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Hatalı parola girdikleri zaman kullanıcıyı aşağıla"
+
+#: plugins/sudoers/def_data.c:119
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Ancak bir tty sahibi iseler kullanıcıya sudoyu çalıştırma izni ver"
+
+#: plugins/sudoers/def_data.c:123
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo EDITOR çevre değişkeninin gereğini şerefle yerine getirecektir."
+
+#: plugins/sudoers/def_data.c:127
+msgid "Prompt for root's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:131
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:135
+msgid "Prompt for the target user's password, not the users's"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:139
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Eğer bir tane varsa hedef kullanıcı oturum açma sınıfında öntanımlıları uygula"
+
+#: plugins/sudoers/def_data.c:143
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "LOGNAME ve USER çevre değişkenlerini ata"
+
+#: plugins/sudoers/def_data.c:147
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:151
+msgid "Don't initialize the group vector to that of the target user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:155
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %d"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:159
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:163
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:167
+#, c-format
+msgid "Number of tries to enter a password: %d"
+msgstr "Bir parola girişinde deneme sayısı: %d"
+
+#: plugins/sudoers/def_data.c:171
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:175
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Günlük kütüğü yolu: %s"
+
+#: plugins/sudoers/def_data.c:179
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "E-posta programı yolu: %s"
+
+#: plugins/sudoers/def_data.c:183
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "E-posta programı için bayraklar: %s"
+
+#: plugins/sudoers/def_data.c:187
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:191
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:195
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "E-posta iletileri için konu satırı: %s"
+
+#: plugins/sudoers/def_data.c:199
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Hatalı parola iletisi: %s"
+
+#: plugins/sudoers/def_data.c:203
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Kimlik doğrulama zaman damgası dizininin yolu: %s"
+
+#: plugins/sudoers/def_data.c:207
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Kimlik doğrulama zaman damgası dizininin sahibi: %s"
+
+#: plugins/sudoers/def_data.c:211
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:215
+#, c-format
+msgid "Default password prompt: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:219
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr ""
+
+#: plugins/sudoers/def_data.c:223
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:227
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:231
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Visudo tarafından kullanılacak düzenleyici yolu: %s"
+
+#: plugins/sudoers/def_data.c:235
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:239
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:243
+msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+msgstr "Sudo_noexec kütüphanesinin içerdiği taklit exec işlevlerini önyükle"
+
+#: plugins/sudoers/def_data.c:247
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "LDAP dizini kullanılabilir durumda ise, yerel sudoers dosyalarını yok sayalım mı"
+
+#: plugins/sudoers/def_data.c:251
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:255
+msgid "If set, users may override the value of `closefrom' with the -C option"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:259
+msgid "Allow users to set arbitrary environment variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:263
+msgid "Reset the environment to a default set of variables"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:267
+msgid "Environment variables to check for sanity:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:271
+msgid "Environment variables to remove:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:275
+msgid "Environment variables to preserve:"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:279
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:283
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:287
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:291
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:295
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:299
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:303
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:307
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:311
+msgid "Log user's input for the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:315
+msgid "Log the output of the command being run"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:319
+msgid "Compress I/O logs using zlib"
+msgstr "I/O günlüklerini zlib kullanarak sıkıştır"
+
+#: plugins/sudoers/def_data.c:323
+msgid "Always run commands in a pseudo-tty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:327
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:331
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:335
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:339
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:343
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:347
+msgid "Set of permitted privileges"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:351
+msgid "Set of limit privileges"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:355
+msgid "Run commands on a pty in the background"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:359
+msgid "Create a new PAM session for the command to run in"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:363
+msgid "Maximum I/O log sequence number"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:207 plugins/sudoers/defaults.c:587
+#, c-format
+msgid "unknown defaults entry `%s'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:215 plugins/sudoers/defaults.c:225
+#: plugins/sudoers/defaults.c:245 plugins/sudoers/defaults.c:258
+#: plugins/sudoers/defaults.c:271 plugins/sudoers/defaults.c:284
+#: plugins/sudoers/defaults.c:297 plugins/sudoers/defaults.c:317
+#: plugins/sudoers/defaults.c:327
+#, c-format
+msgid "value `%s' is invalid for option `%s'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:218 plugins/sudoers/defaults.c:228
+#: plugins/sudoers/defaults.c:236 plugins/sudoers/defaults.c:253
+#: plugins/sudoers/defaults.c:266 plugins/sudoers/defaults.c:279
+#: plugins/sudoers/defaults.c:292 plugins/sudoers/defaults.c:312
+#: plugins/sudoers/defaults.c:323
+#, c-format
+msgid "no value specified for `%s'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:241
+#, c-format
+msgid "values for `%s' must start with a '/'"
+msgstr ""
+
+#: plugins/sudoers/defaults.c:303
+#, c-format
+msgid "option `%s' does not take a value"
+msgstr ""
+
+#: plugins/sudoers/env.c:288 plugins/sudoers/env.c:293
+#: plugins/sudoers/env.c:395 plugins/sudoers/linux_audit.c:82
+#: plugins/sudoers/policy.c:420 plugins/sudoers/policy.c:427
+#: plugins/sudoers/prompt.c:171 plugins/sudoers/sudoers.c:654
+#: plugins/sudoers/testsudoers.c:243
+#, c-format
+msgid "internal error, %s overflow"
+msgstr ""
+
+#: plugins/sudoers/env.c:367
+#, c-format
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr ""
+
+#: plugins/sudoers/env.c:1012
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:102
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:106
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:113 plugins/sudoers/sssd.c:256
+#, c-format
+msgid "unable to dlopen %s: %s"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:118
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr ""
+
+#: plugins/sudoers/group_plugin.c:123
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr ""
+
+#: plugins/sudoers/interfaces.c:119
+msgid "Local IP address and netmask pairs:\n"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:131 plugins/sudoers/iolog.c:144
+#: plugins/sudoers/timestamp.c:200 plugins/sudoers/timestamp.c:244
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:141 plugins/sudoers/iolog.c:155
+#: plugins/sudoers/iolog.c:159 plugins/sudoers/timestamp.c:165
+#: plugins/sudoers/timestamp.c:221 plugins/sudoers/timestamp.c:271
+#, c-format
+msgid "unable to mkdir %s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:217 plugins/sudoers/sudoers.c:708
+#: plugins/sudoers/sudoreplay.c:354 plugins/sudoers/sudoreplay.c:815
+#: plugins/sudoers/sudoreplay.c:978 plugins/sudoers/timestamp.c:155
+#: plugins/sudoers/visudo.c:809
+#, c-format
+msgid "unable to open %s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:250 plugins/sudoers/sudoers.c:711
+#, c-format
+msgid "unable to read %s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:274 plugins/sudoers/timestamp.c:159
+#, c-format
+msgid "unable to write to %s"
+msgstr ""
+
+#: plugins/sudoers/iolog.c:334
+#, c-format
+msgid "unable to create %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:385
+#, c-format
+msgid "sudo_ldap_conf_add_ports: port too large"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:408
+#, c-format
+msgid "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:438
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:467
+#, c-format
+msgid "invalid uri: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:473
+#, c-format
+msgid "unable to mix ldap and ldaps URIs"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:477
+#, c-format
+msgid "unable to mix ldaps and starttls"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:496
+#, c-format
+msgid "sudo_ldap_parse_uri: out of space building hostbuf"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:570
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:573
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1062
+#, c-format
+msgid "unable to get GMT time"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1068
+#, c-format
+msgid "unable to format timestamp"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1076
+#, c-format
+msgid "unable to build time filter"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1295
+#, c-format
+msgid "sudo_ldap_build_pass1 allocation mismatch"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1842
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1844
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: UNKNOWN\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1891
+#, c-format
+msgid " Order: %s\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:1899 plugins/sudoers/parse.c:515
+#: plugins/sudoers/sssd.c:1242
+#, c-format
+msgid " Commands:\n"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2321
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2355
+#, c-format
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr ""
+
+#: plugins/sudoers/ldap.c:2591
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr ""
+
+#: plugins/sudoers/linux_audit.c:57
+#, c-format
+msgid "unable to open audit system"
+msgstr ""
+
+#: plugins/sudoers/linux_audit.c:93
+#, c-format
+msgid "unable to send audit message"
+msgstr ""
+
+#: plugins/sudoers/logging.c:140
+#, c-format
+msgid "%8s : %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:168
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr ""
+
+#: plugins/sudoers/logging.c:194
+#, c-format
+msgid "unable to open log file: %s: %s"
+msgstr "günlük kütüğü açılamadı: %s: %s"
+
+#: plugins/sudoers/logging.c:197
+#, c-format
+msgid "unable to lock log file: %s: %s"
+msgstr "günlük kütüğü kilitlenemedi: %s: %s"
+
+#: plugins/sudoers/logging.c:245
+msgid "No user or host"
+msgstr "Kullanıcı veya ana makine yok"
+
+#: plugins/sudoers/logging.c:247
+msgid "validation failure"
+msgstr "doğrulama başarısız"
+
+#: plugins/sudoers/logging.c:254
+msgid "user NOT in sudoers"
+msgstr "kullancı sudoers içinde DEĞİL"
+
+#: plugins/sudoers/logging.c:256
+msgid "user NOT authorized on host"
+msgstr "kullanıcı ana makine üzerinde yetkili DEĞİL"
+
+#: plugins/sudoers/logging.c:258
+msgid "command not allowed"
+msgstr "komuta izin verilmiyor"
+
+#: plugins/sudoers/logging.c:288
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr "%s sudoers dosyası içinde değil. Bu olay rapor edilecek.\n"
+
+#: plugins/sudoers/logging.c:291
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr "%s, %s üzerinde sudoyu çalıştırma iznine sahip değil. Bu olay rapor edilecek.\n"
+
+#: plugins/sudoers/logging.c:295
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Üzgünüm, %s kullanıcısı %s üzerinde sudoyu çalıştıramayabilir.\n"
+
+#: plugins/sudoers/logging.c:298
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr "Üzgünüm, %s kullanıcısı '%s%s%s' komutunu %s%s%s olarak %s üzerinde çalıştırma iznine sahip değil.\n"
+
+#: plugins/sudoers/logging.c:335 plugins/sudoers/sudoers.c:383
+#: plugins/sudoers/sudoers.c:384 plugins/sudoers/sudoers.c:386
+#: plugins/sudoers/sudoers.c:387 plugins/sudoers/sudoers.c:1001
+#: plugins/sudoers/sudoers.c:1002
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: komut bulunamadı"
+
+#: plugins/sudoers/logging.c:337 plugins/sudoers/sudoers.c:379
+#, c-format
+msgid ""
+"ignoring `%s' found in '.'\n"
+"Use `sudo ./%s' if this is the `%s' you wish to run."
+msgstr ""
+
+#: plugins/sudoers/logging.c:353
+msgid "authentication failure"
+msgstr ""
+
+#: plugins/sudoers/logging.c:379
+msgid "a password is required"
+msgstr ""
+
+#: plugins/sudoers/logging.c:443 plugins/sudoers/logging.c:487
+#, c-format
+msgid "%d incorrect password attempt"
+msgid_plural "%d incorrect password attempts"
+msgstr[0] ""
+msgstr[1] ""
+
+#: plugins/sudoers/logging.c:566
+#, c-format
+msgid "unable to fork"
+msgstr ""
+
+#: plugins/sudoers/logging.c:573 plugins/sudoers/logging.c:629
+#, c-format
+msgid "unable to fork: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:619
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:644
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:680
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr ""
+
+#: plugins/sudoers/logging.c:899
+#, c-format
+msgid "internal error: insufficient space for log line"
+msgstr ""
+
+#: plugins/sudoers/match.c:631
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr ""
+
+#: plugins/sudoers/match.c:661
+#, c-format
+msgid "%s: read error"
+msgstr ""
+
+#: plugins/sudoers/match.c:670
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr ""
+
+#: plugins/sudoers/parse.c:124
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr ""
+
+#: plugins/sudoers/parse.c:127
+#, c-format
+msgid "parse error in %s"
+msgstr ""
+
+#: plugins/sudoers/parse.c:462
+#, c-format
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+
+#: plugins/sudoers/parse.c:463
+#, c-format
+msgid " RunAsUsers: "
+msgstr ""
+
+#: plugins/sudoers/parse.c:477
+#, c-format
+msgid " RunAsGroups: "
+msgstr ""
+
+#: plugins/sudoers/parse.c:486
+#, c-format
+msgid " Options: "
+msgstr ""
+
+#: plugins/sudoers/policy.c:517 plugins/sudoers/visudo.c:750
+#, c-format
+msgid "unable to execute %s"
+msgstr ""
+
+#: plugins/sudoers/policy.c:659
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:661
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:665
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:668
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:670
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/policy.c:671
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:148
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:190
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:374
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:410
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:564 plugins/sudoers/pwutil.c:586
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr ""
+
+#: plugins/sudoers/pwutil.c:584
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:122 plugins/sudoers/set_perms.c:445
+#: plugins/sudoers/set_perms.c:846 plugins/sudoers/set_perms.c:1141
+#: plugins/sudoers/set_perms.c:1431
+msgid "perm stack overflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:130 plugins/sudoers/set_perms.c:453
+#: plugins/sudoers/set_perms.c:854 plugins/sudoers/set_perms.c:1149
+#: plugins/sudoers/set_perms.c:1439
+msgid "perm stack underflow"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:189 plugins/sudoers/set_perms.c:500
+#: plugins/sudoers/set_perms.c:1200 plugins/sudoers/set_perms.c:1471
+msgid "unable to change to root gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:278 plugins/sudoers/set_perms.c:597
+#: plugins/sudoers/set_perms.c:983 plugins/sudoers/set_perms.c:1277
+msgid "unable to change to runas gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:290 plugins/sudoers/set_perms.c:609
+#: plugins/sudoers/set_perms.c:993 plugins/sudoers/set_perms.c:1287
+msgid "unable to change to runas uid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:308 plugins/sudoers/set_perms.c:627
+#: plugins/sudoers/set_perms.c:1009 plugins/sudoers/set_perms.c:1303
+msgid "unable to change to sudoers gid"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:361 plugins/sudoers/set_perms.c:698
+#: plugins/sudoers/set_perms.c:1055 plugins/sudoers/set_perms.c:1349
+#: plugins/sudoers/set_perms.c:1515
+msgid "too many processes"
+msgstr ""
+
+#: plugins/sudoers/set_perms.c:1583
+msgid "unable to set runas group vector"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:257
+#, c-format
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr ""
+
+#: plugins/sudoers/sssd.c:263 plugins/sudoers/sssd.c:271
+#: plugins/sudoers/sssd.c:278 plugins/sudoers/sssd.c:285
+#: plugins/sudoers/sssd.c:292
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:283
+#, c-format
+msgid "Matching Defaults entries for %s on this host:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:296
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:309
+#, c-format
+msgid "User %s may run the following commands on this host:\n"
+msgstr ""
+
+#: plugins/sudoers/sudo_nss.c:318
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:159 plugins/sudoers/sudoers.c:193
+#: plugins/sudoers/sudoers.c:673
+msgid "problem with defaults entries"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:165
+#, c-format
+msgid "no valid sudoers sources found, quitting"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:227
+#, c-format
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:234
+#, c-format
+msgid "you are not permitted to use the -C option"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:315
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:329
+msgid "no tty"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:330
+#, c-format
+msgid "sorry, you must have a tty to run sudo"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:378
+msgid "command in current directory"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:395
+#, c-format
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:723 plugins/sudoers/timestamp.c:216
+#: plugins/sudoers/timestamp.c:260 plugins/sudoers/timestamp.c:328
+#: plugins/sudoers/visudo.c:310 plugins/sudoers/visudo.c:576
+#, c-format
+msgid "unable to stat %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:726
+#, c-format
+msgid "%s is not a regular file"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:729 toke.l:913
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:733 toke.l:920
+#, c-format
+msgid "%s is world writable"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:736 toke.l:925
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:763
+#, c-format
+msgid "only root can use `-c %s'"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:780 plugins/sudoers/sudoers.c:782
+#, c-format
+msgid "unknown login class: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:814
+#, c-format
+msgid "unable to resolve host %s"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:866 plugins/sudoers/testsudoers.c:377
+#, c-format
+msgid "unknown group: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:292
+#, c-format
+msgid "invalid filter option: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:305
+#, c-format
+msgid "invalid max wait: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:311
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:314 plugins/sudoers/visudo.c:179
+#, c-format
+msgid "%s version %s\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:339
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s/timing: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:345
+#, c-format
+msgid "%s/%s/timing: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:363
+#, c-format
+msgid "Replaying sudo session: %s\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:369
+#, c-format
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:370
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:400
+#, c-format
+msgid "unable to set tty to raw mode"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:416
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:499
+#, c-format
+msgid "writing to standard output"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:528
+#, c-format
+msgid "nanosleep: tv_sec %ld, tv_nsec %ld"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:641 plugins/sudoers/sudoreplay.c:666
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:683
+#, c-format
+msgid "too many parenthesized expressions, max %d"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:694
+#, c-format
+msgid "unmatched ')' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:700
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:714
+#, c-format
+msgid "%s requires an argument"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:718 plugins/sudoers/sudoreplay.c:1058
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:724
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:737
+#, c-format
+msgid "unmatched '(' in expression"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:739
+#, c-format
+msgid "illegal trailing \"or\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:741
+#, c-format
+msgid "illegal trailing \"!\""
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1182
+#, c-format
+msgid "usage: %s [-h] [-d directory] [-m max_wait] [-s speed_factor] ID\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1185
+#, c-format
+msgid "usage: %s [-h] [-d directory] -l [search expression]\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1194
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/sudoreplay.c:1196
+msgid ""
+"\n"
+"Options:\n"
+" -d directory specify directory for session logs\n"
+" -f filter specify which I/O type to display\n"
+" -h display help message and exit\n"
+" -l [expression] list available session IDs that match expression\n"
+" -m max_wait max number of seconds to wait between events\n"
+" -s speed_factor speed up or slow down output\n"
+" -V display version information and exit"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:328
+msgid "\thost unmatched"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:331
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:332
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+
+#: plugins/sudoers/testsudoers.c:332
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:129
+#, c-format
+msgid "timestamp path too long: %s"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:203 plugins/sudoers/timestamp.c:247
+#: plugins/sudoers/timestamp.c:292
+#, c-format
+msgid "%s owned by uid %u, should be uid %u"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:208 plugins/sudoers/timestamp.c:252
+#, c-format
+msgid "%s writable by non-owner (0%o), should be mode 0700"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:286
+#, c-format
+msgid "%s exists but is not a regular file (0%o)"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:298
+#, c-format
+msgid "%s writable by non-owner (0%o), should be mode 0600"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:353
+#, c-format
+msgid "timestamp too far in the future: %20.20s"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:407
+#, c-format
+msgid "unable to remove %s, will reset to the epoch"
+msgstr ""
+
+#: plugins/sudoers/timestamp.c:414
+#, c-format
+msgid "unable to reset %s to the epoch"
+msgstr ""
+
+#: plugins/sudoers/toke_util.c:176
+#, c-format
+msgid "fill_args: buffer overflow"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:180
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:243 plugins/sudoers/visudo.c:533
+#, c-format
+msgid "press return to edit %s: "
+msgstr ""
+
+#: plugins/sudoers/visudo.c:326 plugins/sudoers/visudo.c:332
+#, c-format
+msgid "write error"
+msgstr "yazma hatası"
+
+#: plugins/sudoers/visudo.c:414
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:419
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:425
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:448
+#, c-format
+msgid "%s unchanged"
+msgstr "%s değişmemiş"
+
+#: plugins/sudoers/visudo.c:477
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "geçici dosya (%s) yeniden açılamadı, %s değişmemiş."
+
+#: plugins/sudoers/visudo.c:487
+#, c-format
+msgid "unabled to parse temporary file (%s), unknown error"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:526
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:578 plugins/sudoers/visudo.c:587
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:582 plugins/sudoers/visudo.c:592
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:609
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:623
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:633
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:695
+msgid "What now? "
+msgstr ""
+
+#: plugins/sudoers/visudo.c:709
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:757
+#, c-format
+msgid "unable to run %s"
+msgstr "%s çalıştırılamadı"
+
+#: plugins/sudoers/visudo.c:783
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:790
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:815
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "%s dosyasının ayrıştırılması başarısız oldu, bilinmeyen hata"
+
+#: plugins/sudoers/visudo.c:831
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr "%s içindeki %d satırı yakınında ayrıştırma hatası\n"
+
+#: plugins/sudoers/visudo.c:834
+#, c-format
+msgid "parse error in %s\n"
+msgstr "%s içinde ayrıştırma hatası\n"
+
+#: plugins/sudoers/visudo.c:841 plugins/sudoers/visudo.c:846
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: ayrıştırma TAMAM\n"
+
+#: plugins/sudoers/visudo.c:893
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s meşgul, daha sonra tekrar deneyin"
+
+#: plugins/sudoers/visudo.c:937
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "belirtilen düzenleyici (%s) yok"
+
+#: plugins/sudoers/visudo.c:960
+#, c-format
+msgid "unable to stat editor (%s)"
+msgstr "düzenleyici (%s) başlatılamadı"
+
+#: plugins/sudoers/visudo.c:1008
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "hiçbir düzenleyici bulunamadı (düzenleyici yolu = %s)"
+
+#: plugins/sudoers/visudo.c:1100
+#, c-format
+msgid "Error: cycle in %s_Alias `%s'"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1101
+#, c-format
+msgid "Warning: cycle in %s_Alias `%s'"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1104
+#, c-format
+msgid "Error: %s_Alias `%s' referenced but not defined"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1105
+#, c-format
+msgid "Warning: %s_Alias `%s' referenced but not defined"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1240
+#, c-format
+msgid "%s: unused %s_Alias %s"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1302
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:1304
+msgid ""
+"\n"
+"Options:\n"
+" -c check-only mode\n"
+" -f sudoers specify sudoers file location\n"
+" -h display help message and exit\n"
+" -q less verbose (quiet) syntax error messages\n"
+" -s strict syntax checking\n"
+" -V display version information and exit"
+msgstr ""
+"\n"
+"Seçenekler:\n"
+" -c sadece denetim kipi\n"
+" -f sudoers sudoers dosyasının konumu\n"
+" -h yardım iletisini görüntüle ve çık\n"
+" -q daha az ayrıntılı (sessiz=quiet) sözdizim hata iletileri\n"
+" -s sıkı sözdizim denetimi\n"
+" -V sürüm bilgisini görüntüle ve çık"
+
+#: toke.l:886
+msgid "too many levels of includes"
+msgstr ""
diff --git a/plugins/sudoers/po/uk.mo b/plugins/sudoers/po/uk.mo
new file mode 100644
index 0000000..09cd79a
--- /dev/null
+++ b/plugins/sudoers/po/uk.mo
Binary files differ
diff --git a/plugins/sudoers/po/uk.po b/plugins/sudoers/po/uk.po
new file mode 100644
index 0000000..1ce1f3d
--- /dev/null
+++ b/plugins/sudoers/po/uk.po
@@ -0,0 +1,3926 @@
+# Ukrainian translation for sudoers.
+# This file is put in the public domain.
+#
+# Yuri Chornoivan <yurchor@ukr.net>, 2011-2021, 2022, 2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.9.15b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-10-19 10:02-0600\n"
+"PO-Revision-Date: 2023-10-21 18:30+0300\n"
+"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
+"Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\n"
+"Language: uk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"X-Generator: Lokalize 20.12.0\n"
+
+#: confstr.sh:1 gram.y:1257 plugins/sudoers/logging.c:911
+msgid "syntax error"
+msgstr "синтаксична помилка"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "Пароль %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] пароль до %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Пароль: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** Дані щодо ЗАХИСТУ %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Вибачте, повторіть спробу."
+
+#: gram.y:238 gram.y:305 gram.y:314 gram.y:323 gram.y:333 gram.y:343 gram.y:367
+#: gram.y:394 gram.y:403 gram.y:411 gram.y:420 gram.y:429 gram.y:503 gram.y:513
+#: gram.y:525 gram.y:573 gram.y:582 gram.y:591 gram.y:600 gram.y:733 gram.y:742
+#: gram.y:757 gram.y:777 gram.y:796 gram.y:959 gram.y:964 gram.y:972 gram.y:986
+#: gram.y:992 gram.y:1004 gram.y:1010 gram.y:1135 gram.y:1144 gram.y:1152
+#: gram.y:1161 gram.y:1170 gram.y:1199 gram.y:1208 gram.y:1216 gram.y:1317
+#: gram.y:1447 gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:313 lib/eventlog/eventlog.c:765
+#: lib/eventlog/eventlog.c:842 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:484
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:185
+#: logsrvd/iolog_writer.c:218 logsrvd/iolog_writer.c:228
+#: logsrvd/iolog_writer.c:257 logsrvd/iolog_writer.c:278
+#: logsrvd/iolog_writer.c:290 logsrvd/iolog_writer.c:300
+#: logsrvd/iolog_writer.c:310 logsrvd/iolog_writer.c:320
+#: logsrvd/iolog_writer.c:330 logsrvd/iolog_writer.c:342
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:1057 logsrvd/logsrvd.c:1120 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:650
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1743
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:216
+#: logsrvd/logsrvd_journal.c:217 logsrvd/logsrvd_journal.c:274
+#: logsrvd/logsrvd_journal.c:279 logsrvd/logsrvd_journal.c:439
+#: logsrvd/logsrvd_journal.c:441 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:216 logsrvd/logsrvd_local.c:278
+#: logsrvd/logsrvd_local.c:279 logsrvd/logsrvd_local.c:417
+#: logsrvd/logsrvd_local.c:468 logsrvd/logsrvd_local.c:469
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:475
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/logsrvd_relay.c:446
+#: logsrvd/logsrvd_relay.c:748 logsrvd/logsrvd_relay.c:855
+#: logsrvd/sendlog.c:256 logsrvd/sendlog.c:265 logsrvd/sendlog.c:297
+#: logsrvd/sendlog.c:303 logsrvd/sendlog.c:352 logsrvd/sendlog.c:630
+#: logsrvd/sendlog.c:1822 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/bsdauth.c:154 plugins/sudoers/auth/kerb5.c:122
+#: plugins/sudoers/auth/kerb5.c:150 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/auth/sia.c:61
+#: plugins/sudoers/canon_path.c:129 plugins/sudoers/canon_path.c:161
+#: plugins/sudoers/check_aliases.c:128 plugins/sudoers/check_util.c:56
+#: plugins/sudoers/check_util.c:84 plugins/sudoers/cvtsudoers.c:132
+#: plugins/sudoers/cvtsudoers.c:176 plugins/sudoers/cvtsudoers.c:193
+#: plugins/sudoers/cvtsudoers.c:204 plugins/sudoers/cvtsudoers.c:338
+#: plugins/sudoers/cvtsudoers.c:379 plugins/sudoers/cvtsudoers.c:399
+#: plugins/sudoers/cvtsudoers.c:545 plugins/sudoers/cvtsudoers.c:698
+#: plugins/sudoers/cvtsudoers.c:716 plugins/sudoers/cvtsudoers.c:891
+#: plugins/sudoers/cvtsudoers.c:899 plugins/sudoers/cvtsudoers.c:1395
+#: plugins/sudoers/cvtsudoers.c:1399 plugins/sudoers/cvtsudoers.c:1501
+#: plugins/sudoers/cvtsudoers_csv.c:183 plugins/sudoers/cvtsudoers_csv.c:247
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:152
+#: plugins/sudoers/cvtsudoers_ldif.c:195 plugins/sudoers/cvtsudoers_ldif.c:236
+#: plugins/sudoers/cvtsudoers_ldif.c:302 plugins/sudoers/cvtsudoers_ldif.c:378
+#: plugins/sudoers/cvtsudoers_ldif.c:432 plugins/sudoers/cvtsudoers_ldif.c:440
+#: plugins/sudoers/cvtsudoers_ldif.c:451 plugins/sudoers/cvtsudoers_ldif.c:458
+#: plugins/sudoers/cvtsudoers_ldif.c:470 plugins/sudoers/cvtsudoers_ldif.c:483
+#: plugins/sudoers/cvtsudoers_ldif.c:491 plugins/sudoers/cvtsudoers_ldif.c:638
+#: plugins/sudoers/cvtsudoers_merge.c:47 plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1158
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:212
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:694 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:294 plugins/sudoers/ldap_util.c:301
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:402
+#: plugins/sudoers/log_client.c:717 plugins/sudoers/log_client.c:739
+#: plugins/sudoers/log_client.c:744 plugins/sudoers/log_client.c:1426
+#: plugins/sudoers/log_client.c:1547 plugins/sudoers/log_client.c:1670
+#: plugins/sudoers/log_client.c:1993 plugins/sudoers/log_client.c:2052
+#: plugins/sudoers/logging.c:110 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:872 plugins/sudoers/lookup.c:338
+#: plugins/sudoers/lookup.c:355 plugins/sudoers/lookup.c:374
+#: plugins/sudoers/lookup.c:393 plugins/sudoers/lookup.c:410
+#: plugins/sudoers/lookup.c:433 plugins/sudoers/lookup.c:444
+#: plugins/sudoers/match_command.c:302 plugins/sudoers/match_command.c:574
+#: plugins/sudoers/match_command.c:641 plugins/sudoers/match_command.c:737
+#: plugins/sudoers/match_command.c:785 plugins/sudoers/match_digest.c:88
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:595
+#: plugins/sudoers/parse_ldif.c:625 plugins/sudoers/parse_ldif.c:650
+#: plugins/sudoers/parse_ldif.c:708 plugins/sudoers/parse_ldif.c:725
+#: plugins/sudoers/parse_ldif.c:753 plugins/sudoers/parse_ldif.c:760
+#: plugins/sudoers/policy.c:646 plugins/sudoers/policy.c:1061
+#: plugins/sudoers/prompt.c:94 plugins/sudoers/pwutil.c:219
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:368
+#: plugins/sudoers/pwutil.c:542 plugins/sudoers/pwutil.c:607
+#: plugins/sudoers/pwutil.c:679 plugins/sudoers/pwutil.c:877
+#: plugins/sudoers/pwutil.c:967 plugins/sudoers/pwutil.c:1015
+#: plugins/sudoers/pwutil.c:1076 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:145 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1307 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:256
+#: plugins/sudoers/testsudoers.c:265 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:164 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1095
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1320
+msgid "unable to allocate memory"
+msgstr "не вдалося отримати потрібний об’єм пам’яті"
+
+#: gram.y:624
+msgid "a digest requires a path name"
+msgstr "для контрольної суми слід вказати шлях"
+
+#: gram.y:646
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "значення «CWD» мають починатися з «/», «~» або «*»"
+
+#: gram.y:652
+msgid "\"CWD\" path too long"
+msgstr "Шлях «CWD» є надто довгим"
+
+#: gram.y:662
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "значення «CHROOT» мають починатися з «/», «~» або «*»"
+
+#: gram.y:668
+msgid "\"CHROOT\" path too long"
+msgstr "Шлях «CHROOT» є надто довгим"
+
+#: gram.y:817
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "синтаксична помилка, як назву замінника використано зарезервоване слово %s"
+
+#: gram.y:840
+msgid "invalid notbefore value"
+msgstr "некоректне значення notbefore"
+
+#: gram.y:849
+msgid "invalid notafter value"
+msgstr "некоректне значення notafter"
+
+#: gram.y:859 plugins/sudoers/policy.c:390
+msgid "timeout value too large"
+msgstr "значення часу очікування є надто великим"
+
+#: gram.y:861 plugins/sudoers/policy.c:392
+msgid "invalid timeout value"
+msgstr "некоректне значення часу очікування"
+
+#: gram.y:982 plugins/sudoers/sudoers.c:1162
+msgid "command too long"
+msgstr "надто довга команда"
+
+#: gram.y:1016
+msgid "expected a fully-qualified path name"
+msgstr "мало бути вказано назву шляху повністю"
+
+#: gram.y:1261
+#, c-format
+msgid "%s:%d:%zu: %s\n"
+msgstr "%s:%d:%zu: %s\n"
+
+#: gram.y:1315
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Замінник «%s» вже визначено"
+
+#: gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:765 lib/eventlog/eventlog.c:838
+#: lib/eventlog/eventlog.c:841 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:483
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:232
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:174
+#: logsrvd/iolog_writer.c:184 logsrvd/iolog_writer.c:197
+#: logsrvd/iolog_writer.c:217 logsrvd/iolog_writer.c:227
+#: logsrvd/iolog_writer.c:246 logsrvd/iolog_writer.c:256
+#: logsrvd/iolog_writer.c:267 logsrvd/iolog_writer.c:277
+#: logsrvd/iolog_writer.c:289 logsrvd/iolog_writer.c:299
+#: logsrvd/iolog_writer.c:309 logsrvd/iolog_writer.c:319
+#: logsrvd/iolog_writer.c:329 logsrvd/iolog_writer.c:341
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:530
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:668
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:1131
+#: logsrvd/logsrvd.c:1446 logsrvd/logsrvd.c:1453 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:649
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1742
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:125
+#: logsrvd/logsrvd_journal.c:216 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:250 logsrvd/logsrvd_journal.c:258
+#: logsrvd/logsrvd_journal.c:287 logsrvd/logsrvd_journal.c:291
+#: logsrvd/logsrvd_journal.c:439 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:278 logsrvd/logsrvd_local.c:468
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:493
+#: logsrvd/logsrvd_queue.c:158 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/sendlog.c:256 logsrvd/sendlog.c:265
+#: logsrvd/sendlog.c:297 logsrvd/sendlog.c:303 logsrvd/sendlog.c:352
+#: logsrvd/sendlog.c:630 logsrvd/sendlog.c:1523 logsrvd/sendlog.c:1530
+#: logsrvd/sendlog.c:1753 logsrvd/sendlog.c:1822 logsrvd/tls_init.c:305
+#: logsrvd/tls_init.c:329 logsrvd/tls_init.c:340 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/pam.c:518 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/canon_path.c:129
+#: plugins/sudoers/canon_path.c:161 plugins/sudoers/check_aliases.c:128
+#: plugins/sudoers/check_util.c:56 plugins/sudoers/check_util.c:84
+#: plugins/sudoers/cvtsudoers.c:132 plugins/sudoers/cvtsudoers.c:175
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:203
+#: plugins/sudoers/cvtsudoers.c:337 plugins/sudoers/cvtsudoers.c:544
+#: plugins/sudoers/cvtsudoers.c:697 plugins/sudoers/cvtsudoers.c:715
+#: plugins/sudoers/cvtsudoers.c:891 plugins/sudoers/cvtsudoers.c:898
+#: plugins/sudoers/cvtsudoers.c:1395 plugins/sudoers/cvtsudoers.c:1399
+#: plugins/sudoers/cvtsudoers.c:1501 plugins/sudoers/cvtsudoers_csv.c:182
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:151 plugins/sudoers/cvtsudoers_ldif.c:194
+#: plugins/sudoers/cvtsudoers_ldif.c:235 plugins/sudoers/cvtsudoers_ldif.c:301
+#: plugins/sudoers/cvtsudoers_ldif.c:377 plugins/sudoers/cvtsudoers_ldif.c:431
+#: plugins/sudoers/cvtsudoers_ldif.c:439 plugins/sudoers/cvtsudoers_ldif.c:450
+#: plugins/sudoers/cvtsudoers_ldif.c:457 plugins/sudoers/cvtsudoers_ldif.c:469
+#: plugins/sudoers/cvtsudoers_ldif.c:482 plugins/sudoers/cvtsudoers_ldif.c:490
+#: plugins/sudoers/cvtsudoers_ldif.c:637 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51 plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1157
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:211
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:693 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:293 plugins/sudoers/ldap_util.c:300
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:228
+#: plugins/sudoers/log_client.c:250 plugins/sudoers/log_client.c:264
+#: plugins/sudoers/log_client.c:402 plugins/sudoers/log_client.c:717
+#: plugins/sudoers/log_client.c:739 plugins/sudoers/log_client.c:744
+#: plugins/sudoers/log_client.c:1426 plugins/sudoers/log_client.c:1547
+#: plugins/sudoers/log_client.c:1670 plugins/sudoers/log_client.c:1993
+#: plugins/sudoers/log_client.c:2052 plugins/sudoers/logging.c:110
+#: plugins/sudoers/logging.c:189 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:755 plugins/sudoers/logging.c:872
+#: plugins/sudoers/logging.c:925 plugins/sudoers/logging.c:932
+#: plugins/sudoers/lookup.c:337 plugins/sudoers/lookup.c:354
+#: plugins/sudoers/lookup.c:373 plugins/sudoers/lookup.c:392
+#: plugins/sudoers/lookup.c:409 plugins/sudoers/lookup.c:432
+#: plugins/sudoers/lookup.c:443 plugins/sudoers/match_command.c:301
+#: plugins/sudoers/match_command.c:573 plugins/sudoers/match_command.c:640
+#: plugins/sudoers/match_command.c:737 plugins/sudoers/match_command.c:784
+#: plugins/sudoers/match_digest.c:88 plugins/sudoers/parse_ldif.c:152
+#: plugins/sudoers/parse_ldif.c:183 plugins/sudoers/parse_ldif.c:252
+#: plugins/sudoers/parse_ldif.c:260 plugins/sudoers/parse_ldif.c:265
+#: plugins/sudoers/parse_ldif.c:341 plugins/sudoers/parse_ldif.c:352
+#: plugins/sudoers/parse_ldif.c:379 plugins/sudoers/parse_ldif.c:396
+#: plugins/sudoers/parse_ldif.c:408 plugins/sudoers/parse_ldif.c:412
+#: plugins/sudoers/parse_ldif.c:426 plugins/sudoers/parse_ldif.c:484
+#: plugins/sudoers/parse_ldif.c:595 plugins/sudoers/parse_ldif.c:624
+#: plugins/sudoers/parse_ldif.c:649 plugins/sudoers/parse_ldif.c:707
+#: plugins/sudoers/parse_ldif.c:724 plugins/sudoers/parse_ldif.c:752
+#: plugins/sudoers/parse_ldif.c:759 plugins/sudoers/policy.c:157
+#: plugins/sudoers/policy.c:166 plugins/sudoers/policy.c:175
+#: plugins/sudoers/policy.c:204 plugins/sudoers/policy.c:374
+#: plugins/sudoers/policy.c:390 plugins/sudoers/policy.c:392
+#: plugins/sudoers/policy.c:430 plugins/sudoers/policy.c:439
+#: plugins/sudoers/policy.c:448 plugins/sudoers/policy.c:457
+#: plugins/sudoers/policy.c:493 plugins/sudoers/policy.c:502
+#: plugins/sudoers/policy.c:511 plugins/sudoers/policy.c:520
+#: plugins/sudoers/policy.c:529 plugins/sudoers/policy.c:538
+#: plugins/sudoers/policy.c:547 plugins/sudoers/policy.c:646
+#: plugins/sudoers/policy.c:1061 plugins/sudoers/prompt.c:94
+#: plugins/sudoers/pwutil.c:219 plugins/sudoers/pwutil.c:290
+#: plugins/sudoers/pwutil.c:368 plugins/sudoers/pwutil.c:542
+#: plugins/sudoers/pwutil.c:607 plugins/sudoers/pwutil.c:679
+#: plugins/sudoers/pwutil.c:877 plugins/sudoers/pwutil.c:967
+#: plugins/sudoers/pwutil.c:1015 plugins/sudoers/pwutil.c:1076
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1306 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:255
+#: plugins/sudoers/testsudoers.c:264 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:163 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1094
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1309 toke.l:1320
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/eventlog/eventlog.c:304
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "не вдалося здублювати stdin: %m"
+
+#: lib/eventlog/eventlog.c:346
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "не вдалося виконати %s: %m"
+
+#: lib/eventlog/eventlog.c:394 plugins/sudoers/auth/aix_auth.c:199
+msgid "unable to fork"
+msgstr "не вдалося створити відгалуження"
+
+#: lib/eventlog/eventlog.c:404 lib/eventlog/eventlog.c:471
+#, c-format
+msgid "unable to fork: %m"
+msgstr "не вдалося створити відгалуження: %m"
+
+#: lib/eventlog/eventlog.c:461
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "не вдалося відкрити канал: %m"
+
+#: lib/eventlog/eventlog.c:1000
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:1029
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (команда продовжується) %s"
+
+#: lib/eventlog/parse_json.c:175
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "мало бути використано JSON_STRING, отримано %d"
+
+#: lib/eventlog/parse_json.c:180
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY є надто великим"
+
+#: lib/eventlog/parse_json.c:506
+msgid "missing double quote in name"
+msgstr "пропущено подвійні лапки у назві"
+
+#: lib/eventlog/parse_json.c:624
+msgid "missing JSON_OBJECT"
+msgstr "пропущено JSON_OBJECT"
+
+#: lib/eventlog/parse_json.c:628
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "мало бути використано JSON_OBJECT, отримано %d"
+
+#: lib/eventlog/parse_json.c:762
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "вичерпано стек json (у стеку має бути не більше %u кадрів)"
+
+#: lib/eventlog/parse_json.c:840
+msgid "objects must consist of name:value pairs"
+msgstr "об'єкти мають складатися з пар «назва:значення»"
+
+#: lib/eventlog/parse_json.c:845 lib/eventlog/parse_json.c:876
+#: lib/eventlog/parse_json.c:920 lib/eventlog/parse_json.c:942
+#: lib/eventlog/parse_json.c:964 lib/eventlog/parse_json.c:986
+#: lib/eventlog/parse_json.c:1008
+msgid "missing separator between values"
+msgstr "пропущено роздільник між значеннями"
+
+#: lib/eventlog/parse_json.c:860 lib/eventlog/parse_json.c:1034
+msgid "unmatched close brace"
+msgstr "завершальна фігурна дужка без початкової"
+
+#: lib/eventlog/parse_json.c:871
+msgid "unexpected array"
+msgstr "неочікуваний масив"
+
+#: lib/eventlog/parse_json.c:891 lib/eventlog/parse_json.c:1037
+msgid "unmatched close bracket"
+msgstr "завершальна дужка без початкової"
+
+#: lib/eventlog/parse_json.c:902
+msgid "unexpected string"
+msgstr "неочікуваний рядок"
+
+#: lib/eventlog/parse_json.c:913
+msgid "missing colon after name"
+msgstr "пропущено двокрапку після назви"
+
+#: lib/eventlog/parse_json.c:934 lib/eventlog/parse_json.c:956
+msgid "unexpected boolean"
+msgstr "неочікуване булеве значення"
+
+#: lib/eventlog/parse_json.c:978
+msgid "unexpected null"
+msgstr "неочікуване порожнє значення"
+
+#: lib/eventlog/parse_json.c:999
+msgid "unexpected number"
+msgstr "неочікуване число"
+
+#: lib/eventlog/parse_json.c:1045
+msgid "parse error"
+msgstr "помилка обробки"
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1290
+#: plugins/sudoers/sudoreplay.c:1291 plugins/sudoers/sudoreplay.c:1587
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr "некоректний формальний вираз «%s»: %s"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: некоректний файл журналу"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: не вказано даних щодо часової позначки"
+
+#: lib/iolog/iolog_legacy.c:90
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: часова позначка %s: %s"
+
+#: lib/iolog/iolog_legacy.c:97
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: не вказано даних щодо користувача"
+
+#: lib/iolog/iolog_legacy.c:108
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: не вказано даних щодо користувача, від імені якого відбуватиметься виконання"
+
+#: lib/iolog/iolog_legacy.c:119
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: не вказано даних щодо групи, від імені якої відбуватиметься виконання"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s існує, але не є каталогом (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:124 lib/iolog/iolog_mkdtemp.c:80
+#: logsrvd/iolog_writer.c:795 plugins/sudoers/timestamp.c:218
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "не вдалося створити каталог %s"
+
+#: lib/iolog/iolog_mkdtemp.c:85 plugins/sudoers/visudo.c:769
+#: plugins/sudoers/visudo.c:803 plugins/sudoers/visudo.c:809
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "не вдалося змінити режим доступу до %s на значення 0%o"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "помилка під час спроби читання файла часових позначок: %s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "некоректний рядок у файлі timing: %s"
+
+#: logsrvd/iolog_writer.c:65
+#, c-format
+msgid "%s: protocol error: NULL key"
+msgstr "%s: помилка протоколу: ключ NULL"
+
+#: logsrvd/iolog_writer.c:69
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s: помилка протоколу: помилковий тип для %s"
+
+#: logsrvd/iolog_writer.c:74 logsrvd/logsrvd_local.c:109
+#: logsrvd/logsrvd_local.c:123 logsrvd/logsrvd_local.c:131
+#: logsrvd/logsrvd_local.c:149
+#, c-format
+msgid "%s: protocol error: NULL value found in %s"
+msgstr "%s: помилка протоколу: виявлено значення NULL у %s"
+
+#: logsrvd/iolog_writer.c:141 plugins/sudoers/logging.c:1024
+#: plugins/sudoers/policy.c:613
+msgid "unable to generate UUID"
+msgstr "не вдалося створити UUID"
+
+#: logsrvd/iolog_writer.c:354 logsrvd/iolog_writer.c:359
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:369
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s: помилка протоколу: не вистачає %s з AcceptMessage"
+
+#: logsrvd/iolog_writer.c:430
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s: не вдалося виконати форматування ідентифікатора сеансу"
+
+#: logsrvd/iolog_writer.c:444 logsrvd/iolog_writer.c:458
+#: logsrvd/iolog_writer.c:472 logsrvd/iolog_writer.c:487
+#: logsrvd/iolog_writer.c:501 logsrvd/iolog_writer.c:515
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s: %s не встановлено"
+
+#: logsrvd/iolog_writer.c:551 logsrvd/iolog_writer.c:558
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr "не вдалося розгорнути шлях iolog %s"
+
+#: logsrvd/iolog_writer.c:576
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr "не вдалося створити шлях iolog %s"
+
+#: logsrvd/iolog_writer.c:606
+#, c-format
+msgid "invalid iofd %d"
+msgstr "некоректний файловий дескриптор введення-виведення %d"
+
+#: logsrvd/iolog_writer.c:626
+#, c-format
+msgid "error closing iofd %u: %s"
+msgstr "помилка під час спроби закрити дескриптор файла введення-виведення %u: %s"
+
+#: logsrvd/iolog_writer.c:647
+#, c-format
+msgid "error flushing iofd %u: %s"
+msgstr "помилка під час спроби витерти дескриптор файла введення-виведення %u: %s"
+
+#: logsrvd/iolog_writer.c:765
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "некоректний журнал введення-виведення %s: маємо посилання на %s без самого запису"
+
+#: logsrvd/iolog_writer.c:777 logsrvd/logsrvd_journal.c:391
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "%s: не вдалося знайти точку відновлення [%lld, %ld]"
+
+#: logsrvd/iolog_writer.c:799 logsrvd/logsrvd_journal.c:434
+#: logsrvd/logsrvd_queue.c:115 logsrvd/tls_init.c:256
+#: plugins/sudoers/check.c:285 plugins/sudoers/cvtsudoers.c:758
+#: plugins/sudoers/cvtsudoers.c:780 plugins/sudoers/cvtsudoers.c:1461
+#: plugins/sudoers/cvtsudoers_csv.c:697 plugins/sudoers/cvtsudoers_json.c:902
+#: plugins/sudoers/cvtsudoers_ldif.c:711 plugins/sudoers/sudoers.c:1291
+#: plugins/sudoers/sudoers.c:1317 plugins/sudoers/sudoreplay.c:1497
+#: plugins/sudoers/timestamp.c:478 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:990
+#, c-format
+msgid "unable to open %s"
+msgstr "не вдалося відкрити %s"
+
+#: logsrvd/iolog_writer.c:811 logsrvd/logsrv_util.c:111
+#: logsrvd/logsrv_util.c:118 plugins/sudoers/sudoreplay.c:355
+#: plugins/sudoers/sudoreplay.c:361
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "не вдалося відкрити %s/%s"
+
+#: logsrvd/iolog_writer.c:824
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "не вдалося скопіювати %s/%s до %s/%s: %s"
+
+#: logsrvd/iolog_writer.c:853 logsrvd/logsrvd_journal.c:198
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "не вдалося перейменувати %s на %s"
+
+#: logsrvd/logsrv_util.c:153 logsrvd/logsrv_util.c:182
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s: не вдалося знайти точку відновлення [%lld, %ld]"
+
+#: logsrvd/logsrv_util.c:165
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "не вистачає файла журналу введення-виведення, %s/%s"
+
+#: logsrvd/logsrv_util.c:172
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s: неможливо виконати позиціювання вперед на %zu"
+
+#: logsrvd/logsrvd.c:271 logsrvd/logsrvd_queue.c:135
+msgid "unable to connect to relay"
+msgstr "не вдалося встановити з'єднання із ретранслятором"
+
+#: logsrvd/logsrvd.c:338 logsrvd/logsrvd_relay.c:847
+#, c-format
+msgid "server message too large: %zu"
+msgstr "надто велике повідомлення сервера: %zu"
+
+#: logsrvd/logsrvd.c:430 logsrvd/logsrvd.c:553 logsrvd/logsrvd.c:639
+#: logsrvd/logsrvd.c:881 logsrvd/logsrvd.c:895 logsrvd/logsrvd.c:1056
+#: logsrvd/logsrvd.c:1181 logsrvd/logsrvd.c:1354 logsrvd/logsrvd.c:1372
+#: logsrvd/logsrvd.c:1471 logsrvd/logsrvd.c:1596 logsrvd/logsrvd.c:1783
+#: logsrvd/logsrvd_journal.c:503 logsrvd/logsrvd_local.c:238
+#: logsrvd/logsrvd_queue.c:164 logsrvd/logsrvd_relay.c:172
+#: logsrvd/logsrvd_relay.c:249 logsrvd/logsrvd_relay.c:253
+#: logsrvd/logsrvd_relay.c:391 logsrvd/logsrvd_relay.c:583
+#: logsrvd/logsrvd_relay.c:747 logsrvd/logsrvd_relay.c:1137
+#: logsrvd/sendlog.c:1308 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:216 plugins/sudoers/audit.c:281
+#: plugins/sudoers/iolog.c:1041 plugins/sudoers/iolog.c:1175
+#: plugins/sudoers/iolog.c:1274 plugins/sudoers/log_client.c:121
+#: plugins/sudoers/log_client.c:343 plugins/sudoers/log_client.c:359
+#: plugins/sudoers/log_client.c:407 plugins/sudoers/log_client.c:613
+#: plugins/sudoers/log_client.c:620 plugins/sudoers/log_client.c:1114
+#: plugins/sudoers/log_client.c:1395 plugins/sudoers/log_client.c:1436
+#: plugins/sudoers/log_client.c:1444 plugins/sudoers/log_client.c:1603
+#: plugins/sudoers/log_client.c:1728 plugins/sudoers/log_client.c:2060
+#: plugins/sudoers/log_client.c:2068 plugins/sudoers/logging.c:148
+#: plugins/sudoers/logging.c:206 plugins/sudoers/sudoreplay.c:519
+#: plugins/sudoers/sudoreplay.c:566 plugins/sudoers/sudoreplay.c:808
+#: plugins/sudoers/sudoreplay.c:920 plugins/sudoers/sudoreplay.c:1011
+#: plugins/sudoers/sudoreplay.c:1026 plugins/sudoers/sudoreplay.c:1033
+#: plugins/sudoers/sudoreplay.c:1040 plugins/sudoers/sudoreplay.c:1047
+#: plugins/sudoers/sudoreplay.c:1054 plugins/sudoers/sudoreplay.c:1182
+msgid "unable to add event to queue"
+msgstr "не вдалося додати подію до черги обробки"
+
+#: logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:491 logsrvd/logsrvd.c:523
+#: logsrvd/logsrvd.c:577 logsrvd/logsrvd.c:656 logsrvd/logsrvd.c:692
+#: logsrvd/logsrvd.c:728 logsrvd/logsrvd.c:764 logsrvd/logsrvd_relay.c:512
+#: logsrvd/logsrvd_relay.c:545
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr "неочікуваний стан %d %s"
+
+#: logsrvd/logsrvd.c:455 logsrvd/logsrvd.c:492 logsrvd/logsrvd.c:524
+#: logsrvd/logsrvd.c:578 logsrvd/logsrvd.c:657 logsrvd/logsrvd.c:693
+#: logsrvd/logsrvd.c:729 logsrvd/logsrvd.c:765 logsrvd/logsrvd_relay.c:514
+#: logsrvd/logsrvd_relay.c:547
+msgid "state machine error"
+msgstr "помилка скінченного автомата"
+
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:462
+msgid "invalid AcceptMessage"
+msgstr "некоректне AcceptMessage"
+
+#: logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:499
+msgid "invalid RejectMessage"
+msgstr "некоректне RejectMessage"
+
+#: logsrvd/logsrvd.c:530 logsrvd/logsrvd.c:531
+msgid "invalid ExitMessage"
+msgstr "некоректне ExitMessage"
+
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:585
+msgid "invalid RestartMessage"
+msgstr "некоректне RestartMessage"
+
+#: logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:620
+msgid "invalid AlertMessage"
+msgstr "некоректне AlertMessage"
+
+#: logsrvd/logsrvd.c:661 logsrvd/logsrvd.c:697 logsrvd/logsrvd.c:733
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s: неочікуване значення IoBuffer"
+
+#: logsrvd/logsrvd.c:662 logsrvd/logsrvd.c:698 logsrvd/logsrvd.c:734
+msgid "protocol error"
+msgstr "помилка протоколу"
+
+#: logsrvd/logsrvd.c:668 logsrvd/logsrvd.c:669
+msgid "invalid IoBuffer"
+msgstr "некоректне IoBuffer"
+
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:705
+msgid "invalid ChangeWindowSize"
+msgstr "некоректне ChangeWindowSize"
+
+#: logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:741
+msgid "invalid CommandSuspend"
+msgstr "некоректне CommandSuspend"
+
+#: logsrvd/logsrvd.c:790 logsrvd/logsrvd_journal.c:302
+#: logsrvd/logsrvd_relay.c:654 logsrvd/sendlog.c:1207
+#: plugins/sudoers/log_client.c:1593
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "не вдалося розпакувати %s, розмір %zu"
+
+#: logsrvd/logsrvd.c:835 logsrvd/logsrvd_journal.c:376
+#: logsrvd/logsrvd_relay.c:678
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "неочікуване значення type_case %d у %s від %s"
+
+#: logsrvd/logsrvd.c:837
+msgid "unrecognized ClientMessage type"
+msgstr "нерозпізнаний тип ClientMessage"
+
+#: logsrvd/logsrvd.c:927
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "перевищено час очікування на завершення запису до клієнта %s"
+
+#: logsrvd/logsrvd.c:932 logsrvd/logsrvd_relay.c:919 logsrvd/sendlog.c:1413
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr "пропущено буфер запису для клієнта %s"
+
+#: logsrvd/logsrvd.c:1027
+#, c-format
+msgid "timed out reading from client %s"
+msgstr "перевищено час очікування на читання з клієнта %s"
+
+#: logsrvd/logsrvd.c:1068 logsrvd/logsrvd_relay.c:782
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr "EOF від %s без належного закриття TLS"
+
+#: logsrvd/logsrvd.c:1112 logsrvd/logsrvd_relay.c:205 logsrvd/sendlog.c:336
+#: plugins/sudoers/log_client.c:723
+#, c-format
+msgid "client message too large: %zu"
+msgstr "повідомлення клієнта є надто довгим: %zu"
+
+#: logsrvd/logsrvd.c:1113 logsrvd/logsrvd_journal.c:259
+#: logsrvd/logsrvd_journal.c:260
+msgid "client message too large"
+msgstr "повідомлення клієнта є надто великим"
+
+#: logsrvd/logsrvd.c:1131 logsrvd/logsrvd.c:1132
+msgid "invalid ClientMessage"
+msgstr "некоректне ClientMessage"
+
+#: logsrvd/logsrvd.c:1432
+msgid "unable to get remote IP addr"
+msgstr "не вдалося отримати віддалену IP-адресу"
+
+#: logsrvd/logsrvd.c:1463 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:281
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "Не вдалося долучити дані користувача до об'єкта SSL: %s"
+
+#: logsrvd/logsrvd.c:1646 logsrvd/logsrvd.c:2007
+msgid "unable to setup listen socket"
+msgstr "не вдалося налаштувати сокет очікування на дані"
+
+#: logsrvd/logsrvd.c:1766
+#, c-format
+msgid "unexpected signal %d"
+msgstr "неочікуваний сигнал %d"
+
+#: logsrvd/logsrvd.c:1909
+msgid "sudo log server"
+msgstr "сервер журналу sudo"
+
+#: logsrvd/logsrvd.c:1911 logsrvd/sendlog.c:126
+msgid "Options:"
+msgstr "Параметри:"
+
+#: logsrvd/logsrvd.c:1913
+msgid "path to configuration file"
+msgstr "шлях до файла налаштувань"
+
+#: logsrvd/logsrvd.c:1915 logsrvd/sendlog.c:128
+msgid "display help message and exit"
+msgstr "показати довідкове повідомлення і завершити роботу"
+
+#: logsrvd/logsrvd.c:1917
+msgid "do not fork, run in the foreground"
+msgstr "не відгалужувати, не переходити у фоновий режим під час виконання"
+
+#: logsrvd/logsrvd.c:1919
+msgid "percent chance connections will drop"
+msgstr "ймовірність розірвання з'єднання"
+
+#: logsrvd/logsrvd.c:1921 logsrvd/sendlog.c:158
+msgid "display version information and exit"
+msgstr "показати дані щодо версії і завершити роботу"
+
+#: logsrvd/logsrvd.c:1971 logsrvd/sendlog.c:1722
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "Потрібна версія Protobuf-C 1.3 або новіша"
+
+#: logsrvd/logsrvd.c:1987
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "некоректне значення ймовірності скидання: %s"
+
+#: logsrvd/logsrvd.c:1990 logsrvd/sendlog.c:1776
+#: plugins/sudoers/cvtsudoers.c:250 plugins/sudoers/sudoreplay.c:294
+#: plugins/sudoers/visudo.c:181
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s, версія %s\n"
+
+#: logsrvd/logsrvd_conf.c:422 plugins/sudoers/check.c:69
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/sudoers.c:419 plugins/sudoers/sudoers.c:929
+#: plugins/sudoers/sudoers.c:1034 plugins/sudoers/sudoers.c:1424
+#: plugins/sudoers/testsudoers.c:169 plugins/sudoers/testsudoers.c:285
+#: plugins/sudoers/testsudoers.c:459
+#, c-format
+msgid "unknown user %s"
+msgstr "невідомий користувач %s"
+
+#: logsrvd/logsrvd_conf.c:439 plugins/sudoers/iolog.c:148
+#: plugins/sudoers/sudoers.c:425 plugins/sudoers/sudoers.c:1458
+#: plugins/sudoers/testsudoers.c:483
+#, c-format
+msgid "unknown group %s"
+msgstr "невідома група %s"
+
+#: logsrvd/logsrvd_conf.c:457
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr "не вдалося обробити запис режиму iolog %s"
+
+#: logsrvd/logsrvd_conf.c:474 logsrvd/logsrvd_conf.c:1243
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "некоректне значення %s: %s"
+
+#: logsrvd/logsrvd_conf.c:527
+msgid "TLS not supported"
+msgstr "Підтримки TLS не передбачено"
+
+#: logsrvd/logsrvd_conf.c:549
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:622 logsrvd/logsrvd_conf.c:1032
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s: не є повноцінним записом шляхуnot a fully qualified path"
+
+#: logsrvd/logsrvd_conf.c:951 logsrvd/logsrvd_conf.c:967
+#: logsrvd/logsrvd_conf.c:1676
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "невідома можливість syslog %s"
+
+#: logsrvd/logsrvd_conf.c:983 logsrvd/logsrvd_conf.c:999
+#: logsrvd/logsrvd_conf.c:1015 logsrvd/logsrvd_conf.c:1680
+#: logsrvd/logsrvd_conf.c:1684 logsrvd/logsrvd_conf.c:1688
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "невідома пріоритетність syslog %s"
+
+#: logsrvd/logsrvd_conf.c:1197
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d «[» без пари: %s"
+
+#: logsrvd/logsrvd_conf.c:1203
+#, c-format
+msgid "%s:%d garbage after ']': %s"
+msgstr "%s:%d мотлох після «]»: %s"
+
+#: logsrvd/logsrvd_conf.c:1215
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s:%d некоректний розділ налаштувань: %s"
+
+#: logsrvd/logsrvd_conf.c:1223
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d некоректний рядок налаштувань: %s"
+
+#: logsrvd/logsrvd_conf.c:1229
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d мало бути вказано назву розділу: %s"
+
+#: logsrvd/logsrvd_conf.c:1251
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] заборонений ключ: %s"
+
+#: logsrvd/logsrvd_conf.c:1281 plugins/sudoers/cvtsudoers.c:273
+#: plugins/sudoers/logging.c:1076
+#, c-format
+msgid "unable to open log file %s"
+msgstr "не вдалося відкрити файл журналу %s"
+
+#: logsrvd/logsrvd_conf.c:1763
+msgid "unable to initialize server TLS context"
+msgstr "не вдалося ініціалізувати контекст сервера TLS"
+
+#: logsrvd/logsrvd_conf.c:1783
+msgid "unable to initialize relay TLS context"
+msgstr "не вдалося ініціалізувати контекст ретранслятора TLS"
+
+#: logsrvd/logsrvd_journal.c:149 logsrvd/logsrvd_journal.c:430
+#: logsrvd/logsrvd_journal.c:435
+msgid "unable to create journal file"
+msgstr "не вдалося створити файл журналу"
+
+#: logsrvd/logsrvd_journal.c:153 logsrvd/logsrvd_queue.c:109
+#: plugins/sudoers/visudo.c:1046
+#, c-format
+msgid "unable to lock %s"
+msgstr "не вдалося заблокувати %s"
+
+#: logsrvd/logsrvd_journal.c:156
+msgid "unable to lock journal file"
+msgstr "не вдалося заблокувати файл журналу"
+
+#: logsrvd/logsrvd_journal.c:164
+msgid "unable to open journal file"
+msgstr "не вдалося відкрити файл журналу"
+
+#: logsrvd/logsrvd_journal.c:185 logsrvd/logsrvd_journal.c:466
+#: logsrvd/logsrvd_journal.c:471
+msgid "unable to write journal file"
+msgstr "не вдалося записати файл журналу"
+
+#: logsrvd/logsrvd_journal.c:193 logsrvd/logsrvd_journal.c:200
+msgid "unable to rename journal file"
+msgstr "не вдалося перейменувати файл журналу"
+
+#: logsrvd/logsrvd_journal.c:247 logsrvd/logsrvd_journal.c:248
+#: logsrvd/logsrvd_journal.c:288 logsrvd/logsrvd_journal.c:289
+msgid "unexpected EOF reading journal file"
+msgstr "неочікуваний символ кінця файла під час читання файла журналу"
+
+#: logsrvd/logsrvd_journal.c:251 logsrvd/logsrvd_journal.c:252
+#: logsrvd/logsrvd_journal.c:292 logsrvd/logsrvd_journal.c:293
+msgid "error reading journal file"
+msgstr "помилка під час спроби читання файла журналу"
+
+#: logsrvd/logsrvd_journal.c:304 logsrvd/logsrvd_journal.c:390
+msgid "invalid journal file, unable to restart"
+msgstr "некоректний файл журналу, неможливо перезапустити"
+
+#: logsrvd/logsrvd_journal.c:449
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "не вдалося встановити позицію [%lld, %ld] у файлі журналу %s"
+
+#: logsrvd/logsrvd_local.c:166
+#, c-format
+msgid "unexpected value_case %d in %s from %s"
+msgstr "неочікуване значення value_case %d у %s з %s"
+
+#: logsrvd/logsrvd_local.c:194
+msgid "error parsing AcceptMessage"
+msgstr "помилка під час спроби обробити AcceptMessage"
+
+#: logsrvd/logsrvd_local.c:205
+msgid "error creating I/O log"
+msgstr "помилка під час створення журналу введення-виведення"
+
+#: logsrvd/logsrvd_local.c:228
+msgid "error logging accept event"
+msgstr "помилка під час обробки події підтвердження дії журналу"
+
+#: logsrvd/logsrvd_local.c:267
+msgid "error parsing RejectMessage"
+msgstr "помилка під час проби обробити RejectMessage"
+
+#: logsrvd/logsrvd_local.c:291
+msgid "error logging reject event"
+msgstr "помилка під час обробки події відмови у записі до журналу"
+
+#: logsrvd/logsrvd_local.c:427 logsrvd/logsrvd_local.c:437
+msgid "error logging exit event"
+msgstr "помилка під час спроби записати до журналу подію виходу"
+
+#: logsrvd/logsrvd_local.c:494 logsrvd/logsrvd_local.c:495
+msgid "log is already complete, cannot be restarted"
+msgstr "журнал вже завершено — його не можна перезапустити"
+
+#: logsrvd/logsrvd_local.c:525
+msgid "unable to restart log"
+msgstr "не вдалося перезапустити журнал"
+
+#: logsrvd/logsrvd_local.c:541
+msgid "error parsing AlertMessage"
+msgstr "помилка під час спроби обробити AlertMessage"
+
+#: logsrvd/logsrvd_local.c:551
+msgid "error logging alert event"
+msgstr "помилка під час обробки події критичного повідомлення журналу"
+
+#: logsrvd/logsrvd_local.c:587 logsrvd/logsrvd_local.c:650
+#: logsrvd/logsrvd_local.c:685
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr "не вдалося виконати форматування буфера часових позначок, довжина — %d"
+
+#: logsrvd/logsrvd_local.c:601 logsrvd/logsrvd_local.c:609
+#: logsrvd/logsrvd_local.c:657 logsrvd/logsrvd_local.c:692
+#: plugins/sudoers/sudoreplay.c:344 toke.l:981 toke.l:984
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: logsrvd/logsrvd_local.c:620
+msgid "randomly dropping connection"
+msgstr "випадковим чином розривати з'єднання"
+
+#: logsrvd/logsrvd_local.c:632
+msgid "error writing IoBuffer"
+msgstr "помилка під час спроби записати IoBuffer"
+
+#: logsrvd/logsrvd_local.c:667
+msgid "error writing ChangeWindowSize"
+msgstr "помилка під час спроби записати ChangeWindowSize"
+
+#: logsrvd/logsrvd_local.c:702
+msgid "error writing CommandSuspend"
+msgstr "помилка під час спроби записати CommandSuspend"
+
+#: logsrvd/logsrvd_relay.c:437
+msgid "TLS handshake with relay host failed"
+msgstr "помилка спроби ініціалізації зв'язку TLS із вузлом ретранслятора"
+
+#: logsrvd/logsrvd_relay.c:465
+msgid "unable to connect to relay host"
+msgstr "не вдалося встановити з'єднання із вузлом ретранслятора"
+
+#: logsrvd/logsrvd_relay.c:520
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s: некоректне значення ServerHello — пропущено server_id"
+
+#: logsrvd/logsrvd_relay.c:522 logsrvd/sendlog.c:1111
+#: plugins/sudoers/log_client.c:1479
+msgid "invalid ServerHello"
+msgstr "некоректне ServerHello"
+
+#: logsrvd/logsrvd_relay.c:681
+msgid "unrecognized ServerMessage type"
+msgstr "нерозпізнаний тип ServerMessage"
+
+#: logsrvd/logsrvd_relay.c:710
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr "перевищено час очікування на читання з ретранслятора %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:712
+msgid "timeout reading from relay"
+msgstr "перевищено час очікування на читання з ретранслятора"
+
+#: logsrvd/logsrvd_relay.c:767
+msgid "relay host name does not match certificate"
+msgstr "назва вузла ретранслятора не відповідає сертифікату"
+
+#: logsrvd/logsrvd_relay.c:773 logsrvd/logsrvd_relay.c:787
+#: logsrvd/logsrvd_relay.c:794
+msgid "error reading from relay"
+msgstr "помилка під час спроби читання з ретранслятора"
+
+#: logsrvd/logsrvd_relay.c:815
+msgid "unable to read from relay"
+msgstr "не вдалося прочитати з ретранслятора"
+
+#: logsrvd/logsrvd_relay.c:830 logsrvd/logsrvd_relay.c:949
+msgid "relay server closed connection"
+msgstr "сервер-ретранслятор розірвав з'єднання"
+
+#: logsrvd/logsrvd_relay.c:848
+msgid "server message too large"
+msgstr "повідомлення сервера є надто великим"
+
+#: logsrvd/logsrvd_relay.c:912
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr "перевищено час очікування на завершення запису до ретранслятора %s (%s)"
+
+#: logsrvd/logsrvd_relay.c:914
+msgid "timeout writing to relay"
+msgstr "перевищено час очікування на запис до ретранслятора"
+
+#: logsrvd/logsrvd_relay.c:968 logsrvd/logsrvd_relay.c:975
+#: logsrvd/logsrvd_relay.c:987
+msgid "error writing to relay"
+msgstr "помилка під час спроби записати до ретранслятора"
+
+#: logsrvd/sendlog.c:124
+msgid "send sudo I/O log to remote server"
+msgstr "надіслати журнал введення-виведення sudo на віддалений сервер"
+
+#: logsrvd/sendlog.c:130
+msgid "only send an accept event (no I/O)"
+msgstr "надіслати лише подію прийняття (без введення-виведення)"
+
+#: logsrvd/sendlog.c:133
+msgid "certificate bundle file to verify server's cert against"
+msgstr "файл пакунка сертифікатів, за яким слід перевіряти сертифікат сервера"
+
+#: logsrvd/sendlog.c:135
+msgid "certificate file for TLS handshake"
+msgstr "файл сертифіката для підтвердження зв'язку TLS"
+
+#: logsrvd/sendlog.c:138
+msgid "host to send logs to"
+msgstr "вузол, на який слід надіслати журнал"
+
+#: logsrvd/sendlog.c:140
+msgid "remote ID of I/O log to be resumed"
+msgstr "віддалений ідентифікатор журналу введення-виведення, який слід продовжити"
+
+#: logsrvd/sendlog.c:143
+msgid "private key file"
+msgstr "файл закритого ключа"
+
+#: logsrvd/sendlog.c:145
+msgid "do not verify server certificate"
+msgstr "не перевіряти сертифікат сервера"
+
+#: logsrvd/sendlog.c:148
+msgid "port to use when connecting to host"
+msgstr "порт, яким слід скористатися для з'єднання із вузлом"
+
+#: logsrvd/sendlog.c:150
+msgid "restart previous I/O log transfer"
+msgstr "перезапустити попередній обмін даними журналу введення-виведення"
+
+#: logsrvd/sendlog.c:152
+msgid "reject the command with the given reason"
+msgstr "відкинути команду із вказаною причиною"
+
+#: logsrvd/sendlog.c:154
+msgid "stop transfer after reaching this time"
+msgstr "припинити передавання даних після досягнення цієї тривалості"
+
+#: logsrvd/sendlog.c:156
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "перевірити сервер аудиту надсиланням вибраного журналу введення-виведення n разів у паралельному режимі"
+
+#: logsrvd/sendlog.c:181 plugins/sudoers/log_client.c:453
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "не вдалося виконати пошук %s:%s: %s"
+
+#: logsrvd/sendlog.c:219
+msgid "unable to get server IP addr"
+msgstr "не вдалося отримати IP-адресу сервера"
+
+#: logsrvd/sendlog.c:314 plugins/sudoers/sudoreplay.c:868
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "не вдалося прочитати %s/%s: %s"
+
+#: logsrvd/sendlog.c:1035 plugins/sudoers/iolog.c:959
+#: plugins/sudoers/iolog.c:1034
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "неочікувана подія введення-виведення — %d"
+
+#: logsrvd/sendlog.c:1088 logsrvd/sendlog.c:1105 logsrvd/sendlog.c:1139
+#: plugins/sudoers/log_client.c:1129 plugins/sudoers/log_client.c:1405
+#: plugins/sudoers/log_client.c:1473 plugins/sudoers/log_client.c:1512
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s: неочікуваний стан — %d"
+
+#: logsrvd/sendlog.c:1175 plugins/sudoers/log_client.c:1561
+#, c-format
+msgid "error message received from server: %s"
+msgstr "отримано повідомлення про помилку від сервера: %s"
+
+#: logsrvd/sendlog.c:1188 plugins/sudoers/log_client.c:1574
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "отримано повідомлення про переривання від сервера: %s"
+
+#: logsrvd/sendlog.c:1247 plugins/sudoers/log_client.c:1624
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s: неочікуване значення type_case — %d"
+
+#: logsrvd/sendlog.c:1276
+msgid "timeout reading from server"
+msgstr "перевищено час очікування на читання з сервера"
+
+#: logsrvd/sendlog.c:1327 plugins/sudoers/log_client.c:1747
+msgid "host name does not match certificate"
+msgstr "назва вузла не відповідає сертифікату"
+
+#: logsrvd/sendlog.c:1361
+msgid "premature EOF"
+msgstr "передчасне завершення файла"
+
+#: logsrvd/sendlog.c:1374 plugins/sudoers/log_client.c:1795
+#, c-format
+msgid "server message too large: %u"
+msgstr "повідомлення сервера є надто великим: %u"
+
+#: logsrvd/sendlog.c:1430
+msgid "timeout writing to server"
+msgstr "перевищено час очікування на запис на сервері"
+
+#: logsrvd/sendlog.c:1800
+msgid "both restart point and iolog ID must be specified"
+msgstr "слід вказати одночасно точку перезапуску та ідентифікатор журналу введення-виведення"
+
+#: logsrvd/sendlog.c:1804
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "точку перезапуску не можна встановлювати, якщо не надсилається жодних даних введення-виведення"
+
+#: logsrvd/sendlog.c:1880
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "передчасний вихід зі станом %d"
+
+#: logsrvd/sendlog.c:1881
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "на сервер надіслано дані щодо часу, який лишився [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1883
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "отримано точку внеску від сервера [%lld, %ld]"
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:315
+msgid "TLS handshake timeout occurred"
+msgstr "сталося перевищення часу очікування на узгодження зв'язку TLS"
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:337 plugins/sudoers/log_client.c:353
+msgid "unable to set event"
+msgstr "не вдалося встановити подію"
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "Не вдалося встановити з'єднання TLS: %s"
+
+#: logsrvd/tls_client.c:196
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "не вдалося розмістити об'єкт SSL у пам'яті: %s"
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "Не вдалося долучити сокет до об'єкта SSL: %s"
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr "не вдалося ініціалізувати контекст TLS"
+
+#: logsrvd/tls_init.c:138 logsrvd/tls_init.c:146
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "не вдалося встановити комплекс шифрування TLS 1.2 у %s: %s"
+
+#: logsrvd/tls_init.c:166 logsrvd/tls_init.c:174
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "не вдалося встановити комплекс шифрування TLS 1.3 у %s: %s"
+
+#: logsrvd/tls_init.c:206 logsrvd/tls_init.c:227
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "не вдалося встановити параметри Діфі-Гелмана: %s"
+
+#: logsrvd/tls_init.c:283
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "не вдалося створити контекст TLS: %s"
+
+#: logsrvd/tls_init.c:290
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "не вдалося встановити мінімальну версію протоколу у значення TLS 1.2: %s"
+
+#: plugins/sudoers/audit.c:272 plugins/sudoers/audit.c:452
+#: plugins/sudoers/log_client.c:962 plugins/sudoers/log_client.c:1011
+#: plugins/sudoers/log_client.c:1060 plugins/sudoers/log_client.c:1185
+#: plugins/sudoers/logging.c:614 plugins/sudoers/logging.c:732
+#: plugins/sudoers/logging.c:859 plugins/sudoers/logging.c:1031
+#: plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr "не вдалося отримати дані щодо пори доби"
+
+#: plugins/sudoers/auth/aix_auth.c:282
+#, c-format
+msgid "unable to change password for %s"
+msgstr "не вдалося змінити пароль до %s"
+
+#: plugins/sudoers/auth/bsdauth.c:78
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "не вдалося отримати клас входу до системи для користувача %s"
+
+#: plugins/sudoers/auth/bsdauth.c:85
+msgid "invalid authentication type"
+msgstr "некоректний тип розпізнавання"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to begin BSD authentication"
+msgstr "не вдалося розпочати розпізнавання за BSD"
+
+#: plugins/sudoers/auth/bsdauth.c:97
+msgid "unable to initialize BSD authentication"
+msgstr "не вдалося ініціалізувати розпізнавання за BSD"
+
+#: plugins/sudoers/auth/bsdauth.c:191
+msgid "your account has expired"
+msgstr "термін дії вашого облікового запису вичерпано"
+
+#: plugins/sudoers/auth/bsdauth.c:193
+msgid "approval failed"
+msgstr "не вдалося підтвердити"
+
+#: plugins/sudoers/auth/fwtk.c:62
+msgid "unable to read fwtk config"
+msgstr "не вдалося прочитати налаштування fwtk"
+
+#: plugins/sudoers/auth/fwtk.c:67
+msgid "unable to connect to authentication server"
+msgstr "не вдалося встановити з’єднання з сервером розпізнавання"
+
+#: plugins/sudoers/auth/fwtk.c:73 plugins/sudoers/auth/fwtk.c:99
+#: plugins/sudoers/auth/fwtk.c:131
+msgid "lost connection to authentication server"
+msgstr "втрачено зв’язок з сервером розпізнавання"
+
+#: plugins/sudoers/auth/fwtk.c:77
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"помилка сервера розпізнавання:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:116
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: не вдалося перетворити реєстраційний запис на рядок («%s»): %s"
+
+#: plugins/sudoers/auth/kerb5.c:166
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: не вдалося обробити «%s»: %s"
+
+#: plugins/sudoers/auth/kerb5.c:175
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: не вдалося визначити кеш реєстраційних даних: %s"
+
+#: plugins/sudoers/auth/kerb5.c:226
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: не вдалося розмістити параметри: %s"
+
+#: plugins/sudoers/auth/kerb5.c:241
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: не вдалося отримати реєстраційні дані: %s"
+
+#: plugins/sudoers/auth/kerb5.c:254
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: не вдалося ініціалізувати кеш реєстраційних даних: %s"
+
+#: plugins/sudoers/auth/kerb5.c:257
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: не вдалося зберегти реєстраційні дані у кеші: %s"
+
+#: plugins/sudoers/auth/kerb5.c:322
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: не вдалося отримати реєстраційний запис вузла: %s"
+
+#: plugins/sudoers/auth/kerb5.c:336
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: спроба перевірки TGT зазнала невдачі! Ймовірно, вас атаковано: %s"
+
+#: plugins/sudoers/auth/pam.c:233
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "не вдалося ініціалізувати PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:349
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "Помилка розпізнавання PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:369
+msgid "account validation failure, is your account locked?"
+msgstr "помилка під час спроби перевірки облікового запису. Ваш обліковий запис заблоковано?"
+
+#: plugins/sudoers/auth/pam.c:380
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Строк дії облікового запису або пароля збіг, визначте новий пароль і повторіть спробу"
+
+#: plugins/sudoers/auth/pam.c:387
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "не вдалося змінити пароль, строк дії якого завершився: %s"
+
+#: plugins/sudoers/auth/pam.c:398
+msgid "Password expired, contact your system administrator"
+msgstr "Строк дії пароля збіг, зверніться до адміністратора вашої системи щодо поновлення пароля"
+
+#: plugins/sudoers/auth/pam.c:403
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Строк дії облікового запису збіг або у файлі налаштувань PAM немає розділу \"account\" для sudo. Повідомте про це адміністратора вашої системи."
+
+#: plugins/sudoers/auth/pam.c:411 plugins/sudoers/auth/pam.c:416
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "Помилка керування обліковими записами PAM: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:100 plugins/sudoers/visudo.c:266
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "вас немає у базі даних %s"
+
+#: plugins/sudoers/auth/securid5.c:76
+msgid "failed to initialise the ACE API library"
+msgstr "не вдалося ініціалізувати бібліотеку програмного інтерфейсу до ACE"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "unable to contact the SecurID server"
+msgstr "не вдалося встановити зв’язок з сервером SecurID"
+
+#: plugins/sudoers/auth/securid5.c:117
+msgid "User ID locked for SecurID Authentication"
+msgstr "Ідентифікатор користувача заблоковано для розпізнавання SecurID"
+
+#: plugins/sudoers/auth/securid5.c:121 plugins/sudoers/auth/securid5.c:174
+msgid "invalid username length for SecurID"
+msgstr "некоректна довжина імені користувача для SecurID"
+
+#: plugins/sudoers/auth/securid5.c:125 plugins/sudoers/auth/securid5.c:179
+msgid "invalid Authentication Handle for SecurID"
+msgstr "некоректний дескриптор розпізнавання для SecurID"
+
+#: plugins/sudoers/auth/securid5.c:129
+msgid "SecurID communication failed"
+msgstr "спроба обміну даними з SecurID зазнала невдачі"
+
+#: plugins/sudoers/auth/securid5.c:133 plugins/sudoers/auth/securid5.c:222
+msgid "unknown SecurID error"
+msgstr "невідома помилка SecurID"
+
+#: plugins/sudoers/auth/securid5.c:169
+msgid "invalid passcode length for SecurID"
+msgstr "некоректна довжина коду пароля для SecurID"
+
+#: plugins/sudoers/auth/sia.c:72 plugins/sudoers/auth/sia.c:130
+msgid "unable to initialize SIA session"
+msgstr "не вдалося ініціалізувати сеанс SIA"
+
+#: plugins/sudoers/auth/sudo_auth.c:141
+msgid "invalid authentication methods"
+msgstr "некоректні способи розпізнавання"
+
+#: plugins/sudoers/auth/sudo_auth.c:143
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "sudo зібрано з підтримкою некоректних способів розпізнавання! Не можна змішувати власні і зовнішні способи розпізнавання."
+
+#: plugins/sudoers/auth/sudo_auth.c:296 plugins/sudoers/auth/sudo_auth.c:359
+msgid "no authentication methods"
+msgstr "немає способів розпізнавання"
+
+#: plugins/sudoers/auth/sudo_auth.c:298
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "sudo зібрано без можливостей з взаємодії з інструментами розпізнавання! Якщо ви хочете вимкнути розпізнавання, скористайтеся параметром налаштування --disable-authentication."
+
+#: plugins/sudoers/auth/sudo_auth.c:361
+msgid "Unable to initialize authentication methods."
+msgstr "Не вдалося ініціалізувати методи розпізнавання."
+
+#: plugins/sudoers/auth/sudo_auth.c:551
+msgid "Authentication methods:"
+msgstr "Способи розпізнавання:"
+
+#: plugins/sudoers/bsm_audit.c:122 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "Не вдалося визначити умови аудита"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:278
+msgid "unable to commit audit record"
+msgstr "не вдалося надіслати запис аудита"
+
+#: plugins/sudoers/check.c:63 plugins/sudoers/check.c:74
+#: plugins/sudoers/lookup.c:79 plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "невідоме значення uid %u"
+
+#: plugins/sudoers/check.c:277
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "помилка під час спроби читання файла настанов %s"
+
+#: plugins/sudoers/check.c:280
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "ігноруємо файл настанов %s: він не є звичайним файлом"
+
+#: plugins/sudoers/check.c:293
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Ми сподіваємося, що ви отримали належні настанови від адміністратора\n"
+"локальної системи. Зазвичай, подібні настанови зводяться до такого:\n"
+"\n"
+" #1) Поважайте конфіденційність даних інших користувачів.\n"
+" #2) Обдумайте свої дії, перш ніж виконувати їх.\n"
+" #3) Користування широкими правами розширює сферу відповідальності.\n"
+"\n"
+
+#: plugins/sudoers/check.c:301
+msgid ""
+"For security reasons, the password you type will not be visible.\n"
+"\n"
+msgstr ""
+"З міркувань безпеки введений вами пароль не буде показано.\n"
+"\n"
+
+#: plugins/sudoers/check_aliases.c:93
+#, c-format
+msgid "cycle in %s \"%s\""
+msgstr "цикл у %s «%s»"
+
+#: plugins/sudoers/check_aliases.c:96
+#, c-format
+msgid "%s \"%s\" referenced but not defined"
+msgstr "виявлено посилання %s «%s», яке не визначено"
+
+#: plugins/sudoers/cvtsudoers.c:211
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "збільшення порядку: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:231
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "початковий порядок: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:242
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "доповнення порядку: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:252 plugins/sudoers/visudo.c:183
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "Граматична перевірка %s, версія %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:282 plugins/sudoers/testsudoers.c:162
+#, c-format
+msgid "unsupported input format %s"
+msgstr "непідтримуваний формат вхідних даних, %s"
+
+#: plugins/sudoers/cvtsudoers.c:300
+#, c-format
+msgid "unsupported output format %s"
+msgstr "непідтримуваний формат виведення, %s"
+
+#: plugins/sudoers/cvtsudoers.c:392
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: файли вхідних і вихідних даних мають бути різними файлами"
+
+#: plugins/sudoers/cvtsudoers.c:406 plugins/sudoers/sudoers.c:151
+#: plugins/sudoers/sudoers.c:209 plugins/sudoers/testsudoers.c:315
+#: plugins/sudoers/visudo.c:276 plugins/sudoers/visudo.c:666
+msgid "unable to initialize sudoers default values"
+msgstr "не вдалося ініціалізувати типові значення sudoers"
+
+#: plugins/sudoers/cvtsudoers.c:533 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:612
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s: невідоме ключове слово %s"
+
+#: plugins/sudoers/cvtsudoers.c:658
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "некоректний тип типових значень: %s"
+
+#: plugins/sudoers/cvtsudoers.c:681
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "некоректний тип придушення: %s"
+
+#: plugins/sudoers/cvtsudoers.c:722 plugins/sudoers/cvtsudoers.c:738
+#, c-format
+msgid "invalid filter: %s"
+msgstr "некоректний фільтр: %s"
+
+#: plugins/sudoers/cvtsudoers.c:783 plugins/sudoers/visudo.c:1000
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "не вдалося обробити файл %s, невідома помилка"
+
+#: plugins/sudoers/cvtsudoers.c:1508 plugins/sudoers/sudoreplay.c:1143
+#: plugins/sudoers/timestamp.c:353 plugins/sudoers/timestamp.c:356
+#, c-format
+msgid "unable to write to %s"
+msgstr "не вдалося виконати запис до %s"
+
+#: plugins/sudoers/cvtsudoers.c:1536
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s — перетворення форматів файлів sudoers\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1538
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Параметри:\n"
+" -b, --base=dn базовий DN для запитів sudo до LDAP\n"
+" -c, --config=файл_налашт шлях до файла налаштувань\n"
+" -d, --defaults=типи перетворювати лише записи Defaults вказаних типів\n"
+" -e, --expand-aliases розгортати псевдоніми під час перетворення\n"
+" -f, --output-format=формат встановити формат виведення: JSON, LDIF або sudoers\n"
+" -i, --input-format=формат встановити формат вхідних даних: LDIF або sudoers\n"
+" -I, --increment=число число, на яке слід збільшувати sudoOrder\n"
+" -h, --help вивести довідкове повідомлення і завершити роботу\n"
+" -m, --match=фільтр перетворювати лише записи, які відповідають фільтру\n"
+" -M, --match-local встановлювати відповідність фільтра за базами даних passwd та груп\n"
+" -o, --output=файл_результатів записати перетворені дані sudoers до файла файл_результатів\n"
+" -O, --order-start=число початкова точка для першого sudoOrder\n"
+" -p, --prune-matches вилучити невідповідні записи користувачів, груп і вузлів\n"
+" -P, --padding=число доповнення основи для нарощування sudoOrder\n"
+" -s, --suppress=розділи придушити виведення певних розділів\n"
+" -V, --version вивести дані щодо версії і завершити роботу"
+
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:245 plugins/sudoers/cvtsudoers_ldif.c:252
+#: plugins/sudoers/cvtsudoers_ldif.c:594 plugins/sudoers/env.c:340
+#: plugins/sudoers/env.c:347 plugins/sudoers/env.c:458
+#: plugins/sudoers/ldap.c:511 plugins/sudoers/ldap.c:629
+#: plugins/sudoers/ldap.c:1003 plugins/sudoers/ldap_conf.c:219
+#: plugins/sudoers/ldap_conf.c:310 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:93 plugins/sudoers/logging.c:479
+#: plugins/sudoers/policy.c:828 plugins/sudoers/policy.c:840
+#: plugins/sudoers/prompt.c:169 plugins/sudoers/serialize_list.c:62
+#: plugins/sudoers/serialize_list.c:71 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/sudoreplay.c:1340 plugins/sudoers/sudoreplay.c:1346
+#: plugins/sudoers/sudoreplay.c:1352 plugins/sudoers/testsudoers.c:306
+#: plugins/sudoers/toke_util.c:217 toke.l:995 toke.l:1277
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "внутрішня помилка, переповнення %s"
+
+#: plugins/sudoers/cvtsudoers_csv.c:454 plugins/sudoers/cvtsudoers_csv.c:468
+#: plugins/sudoers/cvtsudoers_json.c:661 plugins/sudoers/cvtsudoers_json.c:676
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:362
+#: plugins/sudoers/ldap.c:495
+msgid "unable to get GMT time"
+msgstr "не вдалося отримати гринвіцький час"
+
+#: plugins/sudoers/cvtsudoers_csv.c:459 plugins/sudoers/cvtsudoers_csv.c:473
+#: plugins/sudoers/cvtsudoers_json.c:666 plugins/sudoers/cvtsudoers_json.c:681
+#: plugins/sudoers/cvtsudoers_ldif.c:354 plugins/sudoers/cvtsudoers_ldif.c:367
+#: plugins/sudoers/ldap.c:503
+msgid "unable to format timestamp"
+msgstr "не вдалося виконати форматування часового штампа"
+
+#: plugins/sudoers/cvtsudoers_json.c:481 plugins/sudoers/cvtsudoers_json.c:516
+#: plugins/sudoers/cvtsudoers_json.c:732
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: невідомий запис типових параметрів, «%s»"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:663
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "забагато записів sudoers, максимальна кількість — %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:706
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "не встановлено значення змінної середовища SUDOERS_BASE і не вказано параметра -b."
+
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, c-format
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr "%s:%d:%d: перетворюємо список вузлів на ALL"
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr "не вдалося знайти альтернативну назву %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, c-format
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr "%s:%d:%d: перейменування альтернативної назви %s на %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr "%s:%d:%d: вилучення дубліката альтернативної назви %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr "%s:%d:%d: конфлікт запису Defaults «%s» специфічним для вузла у %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, c-format
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr "%s:%d:%d: Defaults «%s» зроблено специфічним для вузла %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr "%s:%d:%d: не вдалося зробити Defaults «%s» специфічними для вузла"
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr "%s:%d:%d: вилучення Defaults «%s» перевизначено наступними записами"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1088
+#, c-format
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr "%s:%d:%d: об'єднуємо специфікації користувачів у %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1182
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr "%s:%d:%d: вилучення userspec перевизначено наступними записами"
+
+#: plugins/sudoers/def_data.c:56
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Інструмент ведення журналу, якщо використано syslog: %s"
+
+#: plugins/sudoers/def_data.c:60
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Пріоритетність, яка використовуватиметься у syslog для успішних розпізнавань: %s"
+
+#: plugins/sudoers/def_data.c:64
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Пріоритетність, яка використовуватиметься у syslog для неуспішних розпізнавань: %s"
+
+#: plugins/sudoers/def_data.c:68
+msgid "Put OTP prompt on its own line"
+msgstr "Розташовувати запит щодо OTP у окремому рядку"
+
+#: plugins/sudoers/def_data.c:72
+msgid "Ignore '.' in $PATH"
+msgstr "Ігнорувати «.» у $PATH"
+
+#: plugins/sudoers/def_data.c:76
+msgid "Always send mail when sudo is run"
+msgstr "Завжди надсилати листа, коли викликано sudo"
+
+#: plugins/sudoers/def_data.c:80
+msgid "Send mail if user authentication fails"
+msgstr "Надсилати листа, якщо користувачу не вдалося пройти розпізнавання"
+
+#: plugins/sudoers/def_data.c:84
+msgid "Send mail if the user is not in sudoers"
+msgstr "Надсилати листа, якщо користувача немає серед sudoers"
+
+#: plugins/sudoers/def_data.c:88
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Надсилати листа, якщо користувача немає у списку sudoers цього вузла"
+
+#: plugins/sudoers/def_data.c:92
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Надсилати листа, якщо користувачеві заборонено виконувати команду"
+
+#: plugins/sudoers/def_data.c:96
+msgid "Send mail if the user tries to run a command"
+msgstr "Надсилати листа, якщо користувач намагається віддати команду"
+
+#: plugins/sudoers/def_data.c:100
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Окремий часовий штамп для кожної комбінації користувач/tty"
+
+#: plugins/sudoers/def_data.c:104
+msgid "Lecture user the first time they run sudo"
+msgstr "Показувати настанови користувачеві під час першого запуску sudo"
+
+#: plugins/sudoers/def_data.c:108
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "Файл з настановами щодо sudo: %s"
+
+#: plugins/sudoers/def_data.c:112
+msgid "Require users to authenticate by default"
+msgstr "Типово, вимагати розпізнавання"
+
+#: plugins/sudoers/def_data.c:116
+msgid "Root may run sudo"
+msgstr "Root може виконувати sudo"
+
+#: plugins/sudoers/def_data.c:120
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Записувати назву вузла до файла журналу (не syslog)"
+
+#: plugins/sudoers/def_data.c:124
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Записувати рік до файла журналу (не syslog)"
+
+#: plugins/sudoers/def_data.c:128
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Якщо sudo викликано без параметрів, запускати командну оболонку"
+
+#: plugins/sudoers/def_data.c:132
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Встановлювати $HOME відповідно до вказаного користувача для запуску оболонки з -s"
+
+#: plugins/sudoers/def_data.c:136
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Завжди встановлювати значенням $HOME домашній каталог вказаного користувача"
+
+#: plugins/sudoers/def_data.c:140
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Дозволити збирання даних з метою формування зрозумілих повідомлень про помилки"
+
+#: plugins/sudoers/def_data.c:144
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "У файлі sudoers слід вказати повні назви вузлів"
+
+#: plugins/sudoers/def_data.c:148
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Знущатися з користувача, якщо введено помилковий пароль"
+
+#: plugins/sudoers/def_data.c:152
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Дозволяти користувачеві виконувати sudo, лише якщо з ним пов’язано tty"
+
+#: plugins/sudoers/def_data.c:156
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo зважатимwill honor the EDITOR environment variable"
+
+#: plugins/sudoers/def_data.c:160
+msgid "Prompt for root's password, not the users's"
+msgstr "Надсилати запит на пароль root, а не користувача"
+
+#: plugins/sudoers/def_data.c:164
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Надсилати запит щодо пароля runas_default, але пароля самого користувача"
+
+#: plugins/sudoers/def_data.c:168
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Надсилати запит щодо пароля потрібного користувача, але пароля самого користувача"
+
+#: plugins/sudoers/def_data.c:172
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Застосовувати типові параметри у класі вказаного користувача, якщо такий клас є"
+
+#: plugins/sudoers/def_data.c:176
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Встановити значення змінних середовища LOGNAME і USER"
+
+#: plugins/sudoers/def_data.c:180
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Встановлювати для потрібного користувача ефективний uid, а не справжній uid"
+
+#: plugins/sudoers/def_data.c:184
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Не ініціалізувати вектор групи відповідно до вказаного користувача"
+
+#: plugins/sudoers/def_data.c:188
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Позиція, на якій слід переносити рядки файла журналу (0 — без перенесення): %u"
+
+#: plugins/sudoers/def_data.c:192
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Час очікування на часовий штамп розпізнавання: %.1f хвилина"
+
+#: plugins/sudoers/def_data.c:196
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Час очікування на введення пароля: %.1f хвилина"
+
+#: plugins/sudoers/def_data.c:200
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Кількість спроб введення пароля: %u"
+
+#: plugins/sudoers/def_data.c:204
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Потрібне значення umask або 0777 для користувачевого: 0%o"
+
+#: plugins/sudoers/def_data.c:208
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Шлях до файла журналу: %s"
+
+#: plugins/sudoers/def_data.c:212
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Шлях до програми ел. пошти: %s"
+
+#: plugins/sudoers/def_data.c:216
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Параметри програми ел. пошти: %s"
+
+#: plugins/sudoers/def_data.c:220
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Адреса, на яку надсилатимуться листи: %s"
+
+#: plugins/sudoers/def_data.c:224
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Адреса, з якої надсилатимуться листи: %s"
+
+#: plugins/sudoers/def_data.c:228
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Тема листів: %s"
+
+#: plugins/sudoers/def_data.c:232
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Повідомлення про помилковий пароль: %s"
+
+#: plugins/sudoers/def_data.c:236
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Шлях до каталогу стану отримання настанов: %s"
+
+#: plugins/sudoers/def_data.c:240
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Шлях до каталогу часових штампів розпізнавання: %s"
+
+#: plugins/sudoers/def_data.c:244
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Власник каталогу часових штампів розпізнавання: %s"
+
+#: plugins/sudoers/def_data.c:248
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Користувачів цієї групи звільнено від потреби у введенні пароля і PATH: %s"
+
+#: plugins/sudoers/def_data.c:252
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Типовий запит пароля: %s"
+
+#: plugins/sudoers/def_data.c:256
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Якщо встановлено, запит щодо паролю замінюватиме запит системи."
+
+#: plugins/sudoers/def_data.c:260
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Типовий користувач для запуску команд: %s"
+
+#: plugins/sudoers/def_data.c:264
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Значення для заміни $PATH користувача: %s"
+
+#: plugins/sudoers/def_data.c:268
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Шлях до редактора, який використовуватиме visudo: %s"
+
+#: plugins/sudoers/def_data.c:272
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Умови запиту пароля для псевдокоманди «list»: %s"
+
+#: plugins/sudoers/def_data.c:276
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Умови запиту пароля для псевдокоманди «verify»: %s"
+
+#: plugins/sudoers/def_data.c:280
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "Попередньо завантажити бібліотеку sudo_noexec, яка замінює функції виконання"
+
+#: plugins/sudoers/def_data.c:284
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Чи слід ігнорувати локальний файл sudoers, якщо є доступ до каталогу LDAP"
+
+#: plugins/sudoers/def_data.c:288
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Дескриптори файлів >= %d буде закрито перед виконанням команди"
+
+#: plugins/sudoers/def_data.c:292
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "Якщо встановлено, користувачі можуть перевизначати значення closefrom за допомогою параметра -C"
+
+#: plugins/sudoers/def_data.c:296
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Дозволити користувачам встановлювати значення довільних змінних середовища"
+
+#: plugins/sudoers/def_data.c:300
+msgid "Reset the environment to a default set of variables"
+msgstr "Відновити типовий набір змінних середовища"
+
+#: plugins/sudoers/def_data.c:304
+msgid "Environment variables to check for safety:"
+msgstr "Змінні середовища, безпечність яких слід перевіряти:"
+
+#: plugins/sudoers/def_data.c:308
+msgid "Environment variables to remove:"
+msgstr "Змінні середовища, які слід вилучити:"
+
+#: plugins/sudoers/def_data.c:312
+msgid "Environment variables to preserve:"
+msgstr "Змінні середовища, які слід зберегти:"
+
+#: plugins/sudoers/def_data.c:316
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "Роль SELinux, яку слід використати у новому контексті захисту: %s"
+
+#: plugins/sudoers/def_data.c:320
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "Тип SELinux, який слід використати у новому контексті захисту: %s"
+
+#: plugins/sudoers/def_data.c:324
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Шлях до специфічного для sudo файла середовища: %s"
+
+#: plugins/sudoers/def_data.c:328
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Шлях до специфічного для sudo файла середовища з обмеженим доступом: %s"
+
+#: plugins/sudoers/def_data.c:332
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Локаль, яку слід використати під час обробки sudoers: %s"
+
+#: plugins/sudoers/def_data.c:336
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Дозволити sudo надсилати запит щодо пароля, навіть якщо цей пароль буде видимим"
+
+#: plugins/sudoers/def_data.c:340
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Супроводжувати введення користувачем пароля показом замінників символів пароля"
+
+#: plugins/sudoers/def_data.c:344
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Швидше встановлення відповідності, менш точне, але без доступу до файлової системи"
+
+#: plugins/sudoers/def_data.c:348
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "Значення umask, вказане у sudoers, перевизначатиме значення користувача, навіть якщо це значення відкриває ширший доступ"
+
+#: plugins/sudoers/def_data.c:352
+msgid "Log user's input for the command being run"
+msgstr "Записувати дані, вказані користувачем під час виконання команди"
+
+#: plugins/sudoers/def_data.c:356
+msgid "Log the command's standard input if not connected to a terminal"
+msgstr "Записувати до журналу джерело стандартних вхідних даних команди, якщо команду не з'єднано із терміналом"
+
+#: plugins/sudoers/def_data.c:360
+msgid "Log the user's terminal input for the command being run"
+msgstr "Записувати дані, вказані користувачем у терміналі, під час виконання команди"
+
+#: plugins/sudoers/def_data.c:364
+msgid "Log the output of the command being run"
+msgstr "Записувати дані, виведені командою під час виконання"
+
+#: plugins/sudoers/def_data.c:368
+msgid "Log the command's standard output if not connected to a terminal"
+msgstr "Записувати до журналу стандартне виведення команди, якщо команду не з'єднано із терміналом"
+
+#: plugins/sudoers/def_data.c:372
+msgid "Log the command's standard error if not connected to a terminal"
+msgstr "Записувати до журналу стандартне виведення помилок команди, якщо команду не з'єднано із терміналом"
+
+#: plugins/sudoers/def_data.c:376
+msgid "Log the terminal output of the command being run"
+msgstr "Записувати дані, виведені командою до термінала під час виконання"
+
+#: plugins/sudoers/def_data.c:380
+msgid "Compress I/O logs using zlib"
+msgstr "Стискати журнали за допомогою zlib"
+
+#: plugins/sudoers/def_data.c:384
+msgid "Always run commands in a pseudo-tty"
+msgstr "Завжди запускати команди у псевдо-tty"
+
+#: plugins/sudoers/def_data.c:388
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Додаток для підтримки не-Unix груп: %s"
+
+#: plugins/sudoers/def_data.c:392
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Каталог, у якому слід зберігати журнали введення/виведення: %s"
+
+#: plugins/sudoers/def_data.c:396
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Файл, у якому слід зберігати журнал введення/виведення даних: %s"
+
+#: plugins/sudoers/def_data.c:400
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Додати запис до файла utmp/utmpx під час розміщення pty"
+
+#: plugins/sudoers/def_data.c:404
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Встановити користувача у utmp у значення користувача, від імені якого виконується команда"
+
+#: plugins/sudoers/def_data.c:408
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Набір дозвільних прав доступу: %s"
+
+#: plugins/sudoers/def_data.c:412
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Набір обмежувальних прав доступу: %s"
+
+#: plugins/sudoers/def_data.c:416
+msgid "Run commands on a pty in the background"
+msgstr "Виконувати команди у pty у фоновому режимі"
+
+#: plugins/sudoers/def_data.c:420
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "Назва служби PAM, якою слід скористатися: %s"
+
+#: plugins/sudoers/def_data.c:424
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "Назва служби PAM, якою слід скористатися для оболонок входу до системи: %s"
+
+#: plugins/sudoers/def_data.c:428
+#, c-format
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr "Назва служби PAM, якою слід скористатися, якщо sudo запущено з параметром -A: %s"
+
+#: plugins/sudoers/def_data.c:432
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Спробувати встановити реєстраційні дані PAM для користувача, від імені якого виконуватимуться дії"
+
+#: plugins/sudoers/def_data.c:436
+msgid "Create a new PAM session for the command to run in"
+msgstr "Створити сеанс PAM для виконання команди"
+
+#: plugins/sudoers/def_data.c:440
+msgid "Perform PAM account validation management"
+msgstr "Виконати керування коректністю облікового запису PAM"
+
+#: plugins/sudoers/def_data.c:444
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "Максимальний номер у послідовності журналу введення-виведення: %s"
+
+#: plugins/sudoers/def_data.c:448
+msgid "Enable sudoers netgroup support"
+msgstr "Увімкнути підтримку мережевих груп у sudoers"
+
+#: plugins/sudoers/def_data.c:452
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Перевіряти можливість запису до батьківського каталогу під час редагування фалів за допомогою sudoedit"
+
+#: plugins/sudoers/def_data.c:456
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Переходити за символічними посиланнями під час редагування файлів за допомогою sudoedit"
+
+#: plugins/sudoers/def_data.c:460
+msgid "Query the group plugin for unknown system groups"
+msgstr "Надсилати запит до додатка груп щодо невідомих груп системи"
+
+#: plugins/sudoers/def_data.c:464
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Встановлювати відповідність мережевим групам за усім кортежем даних: користувачем, вузлом і доменом"
+
+#: plugins/sudoers/def_data.c:468
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Дозволити виконання команд, навіть якщо sudo не може здійснювати запис до журналу аудиту"
+
+#: plugins/sudoers/def_data.c:472
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Дозволити виконання команд, навіть якщо sudo не може здійснювати запис до журналу введення-виведення"
+
+#: plugins/sudoers/def_data.c:476
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Дозволити виконання команд, навіть якщо sudo не може здійснювати запис до файла журналу"
+
+#: plugins/sudoers/def_data.c:480
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Визначати групи у sudoers і встановлювати відповідність не назві, а ідентифікатору групи"
+
+#: plugins/sudoers/def_data.c:484
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Записи журналу, які виявляться довшими за це значення, буде поділено на декілька повідомлень журналу системи: %u"
+
+#: plugins/sudoers/def_data.c:488
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Користувач, який буде власником усіх файлів журналу введення-виведення: %s"
+
+#: plugins/sudoers/def_data.c:492
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Група, яка буде власником усіх файлів журналу введення-виведення: %s"
+
+#: plugins/sudoers/def_data.c:496
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Режим доступу до файлів, яким слід скористатися для файлів журналу введення-виведення: 0%o"
+
+#: plugins/sudoers/def_data.c:500
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Виконати команди за дескриптором файла замість виконання за шляхом: %s"
+
+#: plugins/sudoers/def_data.c:504
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Ігнорувати невідомі записи Defaults у sudoers замість показу попередження"
+
+#: plugins/sudoers/def_data.c:508
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Час у секундах, який має минути, щоб команду буде перервано: %u"
+
+#: plugins/sudoers/def_data.c:512
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Надати змогу користувачеві встановлювати час очікування у командному рядку"
+
+#: plugins/sudoers/def_data.c:516
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Скидати дані журналу введення-виведення на диск негайно, без буферизації"
+
+#: plugins/sudoers/def_data.c:520
+msgid "Include the process ID when logging via syslog"
+msgstr "Включати ідентифікатор процесу до журналів syslog"
+
+#: plugins/sudoers/def_data.c:524
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Тип запису часової позначки розпізнавання: %s"
+
+#: plugins/sudoers/def_data.c:528
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Повідомлення про помилку розпізнавання: %s"
+
+#: plugins/sudoers/def_data.c:532
+msgid "Ignore case when matching user names"
+msgstr "Ігнорувати регістр символів при пошуку імен користувачів"
+
+#: plugins/sudoers/def_data.c:536
+msgid "Ignore case when matching group names"
+msgstr "Ігнорувати регістр символів при пошуку назв груп"
+
+#: plugins/sudoers/def_data.c:540
+msgid "Log when a command is allowed by sudoers"
+msgstr "Записувати до журналу дані, коли виконання команди дозволене sudoers"
+
+#: plugins/sudoers/def_data.c:544
+msgid "Log when a command is denied by sudoers"
+msgstr "Записувати до журналу дані, коли виконання команди заборонене sudoers"
+
+#: plugins/sudoers/def_data.c:548
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "Сервер або сервери журналу sudo, з якими слід встановити з'єднання, з необов'язковим зазначенням порту"
+
+#: plugins/sudoers/def_data.c:552
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Час очікування на дії сервера журналу sudo у секундах: %u"
+
+#: plugins/sudoers/def_data.c:556
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "Увімкнути параметр сокета SO_KEEPALIVE на сокеті, який з'єднано із сервером журналу"
+
+#: plugins/sudoers/def_data.c:560
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "Шлях до файла пакета CA сервера аудиту: %s"
+
+#: plugins/sudoers/def_data.c:564
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "Шлях до файла сертифікатів sudoers: %s"
+
+#: plugins/sudoers/def_data.c:568
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "Шлях до файла закритого ключа sudoers: %s"
+
+#: plugins/sudoers/def_data.c:572
+msgid "Verify that the log server's certificate is valid"
+msgstr "Перевірити, чи є сертифікат сервера журналювання чинним"
+
+#: plugins/sudoers/def_data.c:576
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "Дозволити використання невідомих значень імені користувача і/або ідентифікатора групи для runas"
+
+#: plugins/sudoers/def_data.c:580
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "Дозволяти виконання команд лише від імені користувачів із коректним записом командної оболонки"
+
+#: plugins/sudoers/def_data.c:584
+msgid "Set the pam remote user to the user running sudo"
+msgstr "Встановити для віддаленого користувача PAM те саме ім'я, що і для користувача, від імені якого запущено sudo"
+
+#: plugins/sudoers/def_data.c:588
+msgid "Set the pam remote host to the local host name"
+msgstr "Встановити для віддаленого вузла PAM назву локального вузла"
+
+#: plugins/sudoers/def_data.c:592
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "Робочий каталог, до якого слід перейти перед виконанням команди: %s"
+
+#: plugins/sudoers/def_data.c:596
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "Кореневий каталог, до якого слід перейти перед виконанням команди: %s"
+
+#: plugins/sudoers/def_data.c:600
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "Формат журналу: %s"
+
+#: plugins/sudoers/def_data.c:604
+msgid "Enable SELinux RBAC support"
+msgstr "Увімкнути підтримку RBAC SELinux"
+
+#: plugins/sudoers/def_data.c:608
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "Шлях до файла, який було створено під час першого запуску sudo: %s"
+
+#: plugins/sudoers/def_data.c:612
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "Перехоплювати подальші команди і застосовувати до них обмеження sudoers"
+
+#: plugins/sudoers/def_data.c:616
+msgid "Log sub-commands run by the original command"
+msgstr "Записувати до журналу підкоманди, які запущено початковою командою"
+
+#: plugins/sudoers/def_data.c:620
+msgid "Log the exit status of commands"
+msgstr "Записувати до журналу стан виходу команд"
+
+#: plugins/sudoers/def_data.c:624
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr "Для виконання наступних команд у перехопленому сеансі слід пройти розпізнавання"
+
+#: plugins/sudoers/def_data.c:628
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr "Дозволити перехопленій команді запускати програми зі встановлення setuid або setgid"
+
+#: plugins/sudoers/def_data.c:632
+#, c-format
+msgid "The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr "Максимальний розмір, до якого може зростати адресний простір процесу (у байтах): %s"
+
+#: plugins/sudoers/def_data.c:636
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr "Найбільший розмір файла дампа ядра, який може бути створено (у байтах): %s"
+
+#: plugins/sudoers/def_data.c:640
+#, c-format
+msgid "The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr "Максимальна кількість часу процесора, який може використовувати процес (у секундах): %s"
+
+#: plugins/sudoers/def_data.c:644
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr "Максимальний розмір сегмента даних для процесу (у байтах): %s"
+
+#: plugins/sudoers/def_data.c:648
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr "Найбільший розмір файла, який може створювати процес (у байтах): %s"
+
+#: plugins/sudoers/def_data.c:652
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr "Максимальна кількість блокувань, які може встановлювати процес: %s"
+
+#: plugins/sudoers/def_data.c:656
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr "Максимальний розмір, який процес може блокувати у пам'яті (у байтах): %s"
+
+#: plugins/sudoers/def_data.c:660
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr "Максимальна кількість файлів, які може відкривати процес: %s"
+
+#: plugins/sudoers/def_data.c:664
+#, c-format
+msgid "The maximum number of processes that the user may run simultaneously: %s"
+msgstr "Максимальна кількість процесів, які користувач може запускати одночасно: %s"
+
+#: plugins/sudoers/def_data.c:668
+#, c-format
+msgid "The maximum size to which the process's resident set size may grow (in bytes): %s"
+msgstr "Максимальний розмір, до якого може зростати розмір резидентного набору (у байтах): %s"
+
+#: plugins/sudoers/def_data.c:672
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr "Максимальний розмір, до якого може зростати стос процесу (у байтах): %s"
+
+#: plugins/sudoers/def_data.c:676
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr "Намагатися пройти розпізнавання, навіть якщо працюємо не в інтерактивному режимі"
+
+#: plugins/sudoers/def_data.c:680
+msgid "Store plaintext passwords in I/O log input"
+msgstr "Зберігати звичайний текст паролів у вхідних даних журналу введення-виведення"
+
+#: plugins/sudoers/def_data.c:684
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr "Список формальних виразів для встановлення відповідності при запиті пароля"
+
+#: plugins/sudoers/def_data.c:688
+#, c-format
+msgid "The mechanism used by the intercept and log_subcmds options: %s"
+msgstr "Механізм, який використано для параметрів intercept і log_subcmds: %s"
+
+#: plugins/sudoers/def_data.c:692
+msgid "Attempt to verify the command and arguments after execution"
+msgstr "Спробувати перевірити команду і аргументи після виконання"
+
+#: plugins/sudoers/def_data.c:696
+#, c-format
+msgid "AppArmor profile to use in the new security context: %s"
+msgstr "Профіль AppArmor, який слід використати у новому контексті захисту: %s"
+
+#: plugins/sudoers/defaults.c:207
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "невідомий запис типових параметрів «%s»"
+
+#: plugins/sudoers/defaults.c:251
+#, c-format
+msgid "no value specified for \"%s\""
+msgstr "не вказано значення для «%s»"
+
+#: plugins/sudoers/defaults.c:260
+#, c-format
+msgid "invalid operator \"%c=\" for \"%s\""
+msgstr "некоректний оператор «%c=» для «%s»"
+
+#: plugins/sudoers/defaults.c:292
+#, c-format
+msgid "option \"%s\" does not take a value"
+msgstr "параметру «%s» не потрібно передавати значення"
+
+#: plugins/sudoers/defaults.c:319
+#, c-format
+msgid "invalid Defaults type 0x%x for option \"%s\""
+msgstr "некоректний тип Defaults, 0x%x, для параметра «%s»"
+
+#: plugins/sudoers/defaults.c:326
+#, c-format
+msgid "value \"%s\" is invalid for option \"%s\""
+msgstr "значення «%s» є некоректним для параметра «%s»"
+
+#: plugins/sudoers/defaults.c:1176 plugins/sudoers/policy.c:213
+#: plugins/sudoers/policy.c:222
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr "назва шляху для «%s» є надто довгою"
+
+#: plugins/sudoers/defaults.c:1182
+#, c-format
+msgid "values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "значення для «%s» має починатися з «/», «~» або «*»"
+
+#: plugins/sudoers/defaults.c:1189
+#, c-format
+msgid "values for \"%s\" must start with a '/'"
+msgstr "значення для «%s» має починатися з «/»"
+
+#: plugins/sudoers/display.c:160
+#, c-format
+msgid "LDAP Role: %s\n"
+msgstr "Роль LDAP: %s\n"
+
+#: plugins/sudoers/display.c:163
+#, c-format
+msgid "Sudoers entry: %s\n"
+msgstr "Запис sudoers: %s\n"
+
+#: plugins/sudoers/display.c:166
+msgid " RunAsUsers: "
+msgstr " Користувачі для запуску: "
+
+#: plugins/sudoers/display.c:181
+msgid " RunAsGroups: "
+msgstr " Групи для запуску: "
+
+#: plugins/sudoers/display.c:191
+msgid " Options: "
+msgstr " Параметри: "
+
+#: plugins/sudoers/display.c:255
+msgid " Commands:\n"
+msgstr " Команди:\n"
+
+#: plugins/sudoers/display.c:478
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Відповідність записів Defaults для %s на %s:\n"
+
+#: plugins/sudoers/display.c:496
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Типові значення для запуску від імені і команд для %s:\n"
+
+#: plugins/sudoers/display.c:514
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "Користувач %s має право виконувати на %s такі команди:\n"
+
+#: plugins/sudoers/display.c:530
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Користувач %s не має права виконувати sudo на %s.\n"
+
+#: plugins/sudoers/editor.c:180
+#, c-format
+msgid "ignoring editor: %.*s"
+msgstr "ігноруємо редактор: %.*s"
+
+#: plugins/sudoers/editor.c:181
+msgid "editor arguments may not contain \"--\""
+msgstr "в записі аргументів редактора не може міститися \"--\""
+
+#: plugins/sudoers/env.c:426
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: помилкове значення envp, невідповідність довжин"
+
+#: plugins/sudoers/env.c:1119
+msgid "unable to rebuild the environment"
+msgstr "не вдалося перебудувати середовище"
+
+#: plugins/sudoers/env.c:1199
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "вибачте, вам не дозволено встановлювати такі змінні середовища: %s"
+
+#: plugins/sudoers/filedigest.c:50
+#, c-format
+msgid "unsupported digest type %u for %s"
+msgstr "непідтримуваний тип контрольної суми, %u, для %s"
+
+#: plugins/sudoers/filedigest.c:77
+#, c-format
+msgid "%s: read error"
+msgstr "%s: помилка читання"
+
+#: plugins/sudoers/group_plugin.c:169 plugins/sudoers/sssd.c:578
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "не вдалося завантажити %s: %s"
+
+#: plugins/sudoers/group_plugin.c:181
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "не вдалося знайти символ «group_plugin» у %s"
+
+#: plugins/sudoers/group_plugin.c:186
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: несумісна основна версія додатка обробки груп %d, мало бути — %d"
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "не вдалося обробити IP-адресу «%s»"
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "не вдалося обробити маску мережі «%s»"
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Пари локальних IP-адрес і масок мережі:\n"
+
+#: plugins/sudoers/iolog.c:694
+msgid "unable to update sequence file"
+msgstr "не вдалося оновити файл послідовності"
+
+#: plugins/sudoers/iolog.c:728 plugins/sudoers/iolog.c:917
+#: plugins/sudoers/iolog.c:1080 plugins/sudoers/iolog.c:1087
+#: plugins/sudoers/iolog.c:1209 plugins/sudoers/iolog.c:1216
+#: plugins/sudoers/iolog.c:1316 plugins/sudoers/iolog.c:1323
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "не вдалося здійснити запис до файла журналу введення-виведення: %s"
+
+#: plugins/sudoers/iolog.c:736
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "не вдалося створити %s/%s"
+
+#: plugins/sudoers/iolog.c:965
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: внутрішня помилка, файл журналу введення-виведення для події %d не відкрито"
+
+#: plugins/sudoers/iolog.c:1065 plugins/sudoers/iolog.c:1194
+#: plugins/sudoers/iolog.c:1300 plugins/sudoers/timestamp.c:897
+#: plugins/sudoers/timestamp.c:989 plugins/sudoers/visudo.c:555
+#: plugins/sudoers/visudo.c:561
+msgid "unable to read the clock"
+msgstr "не вдалося прочитати час на годиннику"
+
+#: plugins/sudoers/iolog.c:1292 plugins/sudoers/log_client.c:1203
+#: plugins/sudoers/log_client.c:1213 plugins/sudoers/log_client.c:1217
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: внутрішня помилка, некоректний сигнал %d"
+
+#: plugins/sudoers/ldap.c:154 plugins/sudoers/ldap_conf.c:289
+msgid "starttls not supported when using ldaps"
+msgstr "підтримки starttls, якщо використовується ldaps, не передбачено"
+
+#: plugins/sudoers/ldap.c:226
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "не вдалося ініціалізувати базу даних сертифікатів і ключів SSL: %s"
+
+#: plugins/sudoers/ldap.c:229
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "щоб скористатися SSL, вам слід встановити для TLS_CERT значення %s"
+
+#: plugins/sudoers/ldap.c:1593
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "не вдалося ініціалізувати LDAP: %s"
+
+#: plugins/sudoers/ldap.c:1630
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls вказано, але у бібліотеках LDAP не передбачено підтримки ldap_start_tls_s() або ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:1767 plugins/sudoers/parse_ldif.c:745
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "некоректний атрибут sudoOrder: %s"
+
+#: plugins/sudoers/ldap_conf.c:197
+#, c-format
+msgid "%s: port too large"
+msgstr "%s: порт є надто великим"
+
+#: plugins/sudoers/ldap_conf.c:258
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "непідтримуваний тип адреси LDAP: %s"
+
+#: plugins/sudoers/ldap_conf.c:285
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "не можна використовувати суміш з адрес ldap і ldaps"
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "дублювання sudoOption: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "не вдалося перетворити запис sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "не вдалося відкрити систему аудита"
+
+#: plugins/sudoers/linux_audit.c:104
+msgid "unable to send audit message"
+msgstr "не вдалося надіслати повідомлення аудита"
+
+#: plugins/sudoers/log_client.c:125 plugins/sudoers/log_client.c:412
+#: plugins/sudoers/log_client.c:1450 plugins/sudoers/log_client.c:2076
+msgid "error in event loop"
+msgstr "помилка у циклі обробки подій"
+
+#: plugins/sudoers/log_client.c:205
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "Не вдалося створити об'єкт SSL_CTX: %s"
+
+#: plugins/sudoers/log_client.c:230
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "не вдалося завантажити комплект служби сертифікації %s"
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "не вдалося завантажити сертифікат %s"
+
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "unable to load private key %s"
+msgstr "не вдалося завантажити закритий ключ %s"
+
+#: plugins/sudoers/log_client.c:275
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "Не вдалося розмістити об'єкт SSL у пам'яті: %s"
+
+#: plugins/sudoers/log_client.c:364 plugins/sudoers/log_client.c:369
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "Не вдалося встановити з'єднання TLS із %s:%s: %s"
+
+#: plugins/sudoers/log_client.c:545
+msgid "TLS initialization was unsuccessful"
+msgstr "Спроба ініціалізувати TLS завершилася невдало"
+
+#: plugins/sudoers/log_client.c:555
+msgid "TLS handshake was unsuccessful"
+msgstr "Спроба узгодити зв'язок TLS завершилася невдало"
+
+#: plugins/sudoers/log_client.c:1221
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s: внутрішня помилка, некоректний стан виходу %d"
+
+#: plugins/sudoers/log_client.c:1757 plugins/sudoers/log_client.c:1782
+msgid "lost connection to log server"
+msgstr "втрачено зв’язок з сервером журналу"
+
+#: plugins/sudoers/log_client.c:1859
+msgid "missing write buffer"
+msgstr "не вказано буфер запису"
+
+#: plugins/sudoers/log_client.c:2015
+msgid "unable to connect to log server"
+msgstr "не вдалося встановити з'єднання із сервером журналу"
+
+#: plugins/sudoers/logging.c:295
+msgid "user NOT in sudoers"
+msgstr "користувача немає у списку sudoers"
+
+#: plugins/sudoers/logging.c:297
+msgid "user NOT authorized on host"
+msgstr "користувача не уповноважено на дії на вузлі"
+
+#: plugins/sudoers/logging.c:299
+msgid "command not allowed"
+msgstr "виконання команди заборонено"
+
+#: plugins/sudoers/logging.c:320
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr "%s немає у файлі sudoers.\n"
+
+#: plugins/sudoers/logging.c:323
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr "%s не має права виконувати sudo на %s.\n"
+
+#: plugins/sudoers/logging.c:326
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Вибачте, користувач %s не має права виконувати sudo на %s.\n"
+
+#: plugins/sudoers/logging.c:339
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s%s' as %s%s%s on %s.\n"
+msgstr "Вибачте, користувач %s не має права виконувати «%s%s%s%s» від імені %s%s%s на %s.\n"
+
+#: plugins/sudoers/logging.c:350
+msgid "This incident has been reported to the administrator.\n"
+msgstr "Про цю подію подано звіт адміністратору.\n"
+
+#: plugins/sudoers/logging.c:387 plugins/sudoers/sudoers.c:547
+#: plugins/sudoers/sudoers.c:549 plugins/sudoers/sudoers.c:551
+#: plugins/sudoers/sudoers.c:553 plugins/sudoers/sudoers.c:777
+#: plugins/sudoers/sudoers.c:779
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: команду не знайдено"
+
+#: plugins/sudoers/logging.c:389 plugins/sudoers/sudoers.c:543
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"пропущено «%s» знайдений у «.»\n"
+"Скористайтеся командою «sudo ./%s», якщо вам потрібно виконати саме «%s»."
+
+#: plugins/sudoers/logging.c:409
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u невдала спроба введення пароля"
+msgstr[1] "%u невдалих спроби введення пароля"
+msgstr[2] "%u невдалих спроб введення пароля"
+msgstr[3] "одна невдала спроба введення пароля"
+
+#: plugins/sudoers/logging.c:500
+msgid "authentication failure"
+msgstr "помилка під час спроби розпізнавання"
+
+#: plugins/sudoers/logging.c:539 plugins/sudoers/logging.c:558
+msgid "a password is required"
+msgstr "слід вказати пароль"
+
+#: plugins/sudoers/logging.c:881
+msgid "problem parsing sudoers"
+msgstr "проблема із обробкою sudoers"
+
+#: plugins/sudoers/logging.c:922 plugins/sudoers/logging.c:930
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr "%s:%d:%d: %s"
+
+#: plugins/sudoers/logging.c:1108
+#, c-format
+msgid "unable to write log file %s"
+msgstr "не вдалося виконати запис до файла журналу %s"
+
+#: plugins/sudoers/match_digest.c:107
+#, c-format
+msgid "digest for %s (%s) bad length %zu, expected %zu"
+msgstr "контрольна сума для %s (%s) має помилкову довжину %zu, мало бути %zu"
+
+#: plugins/sudoers/match_digest.c:126
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "контрольну суму для %s (%s) подано не у формі %s"
+
+#: plugins/sudoers/parse_ldif.c:615
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "ігноруємо неповний запис sudoRole: cn: %s"
+
+#: plugins/sudoers/parse_ldif.c:675
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "некоректний атрибут LDIF: %s"
+
+#: plugins/sudoers/parser_warnx.c:56
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: plugins/sudoers/parser_warnx.c:59
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s: %s\n"
+
+#: plugins/sudoers/pivot.c:71
+msgid "unable to restore root directory"
+msgstr "не вдалося відновити кореневий каталог"
+
+#: plugins/sudoers/pivot.c:79
+msgid "unable to restore current working directory"
+msgstr "не вдалося відновити поточний робочий каталог"
+
+#: plugins/sudoers/policy.c:78 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "оболонкою sudo встановлено некоректне значення параметра %.*s"
+
+#: plugins/sudoers/policy.c:364 plugins/sudoers/testsudoers.c:329
+msgid "unable to parse network address list"
+msgstr "не вдалося обробити список мережевих адрес"
+
+#: plugins/sudoers/policy.c:556
+msgid "user name not set by sudo front-end"
+msgstr "ім'я користувача не встановлено за допомогою оболонки sudo"
+
+#: plugins/sudoers/policy.c:560
+msgid "user-ID not set by sudo front-end"
+msgstr "ідентифікатор користувача не встановлено за допомогою оболонки sudo"
+
+#: plugins/sudoers/policy.c:564
+msgid "group-ID not set by sudo front-end"
+msgstr "ідентифікатор групи не встановлено за допомогою оболонки sudo"
+
+#: plugins/sudoers/policy.c:568
+msgid "host name not set by sudo front-end"
+msgstr "назву вузла не встановлено за допомогою оболонки sudo"
+
+#: plugins/sudoers/policy.c:757
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "некоректний робочий каталог: %s"
+
+#: plugins/sudoers/policy.c:944
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "некоректний каталог chroot: %s"
+
+#: plugins/sudoers/policy.c:1153 plugins/sudoers/visudo.c:919
+#: plugins/sudoers/visudo.c:1218
+#, c-format
+msgid "unable to execute %s"
+msgstr "не вдалося виконати %s"
+
+#: plugins/sudoers/policy.c:1225 plugins/sudoers/policy.c:1260
+#: plugins/sudoers/policy.c:1282 plugins/sudoers/policy.c:1300
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s: некоректні прапорці режиму від оболонки sudo: 0x%x"
+
+#: plugins/sudoers/policy.c:1323
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Додаток правил sudoers версії %s\n"
+
+#: plugins/sudoers/policy.c:1325
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Граматична перевірка файла sudoers версії %d\n"
+
+#: plugins/sudoers/policy.c:1329
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Шлях до sudoers: %s\n"
+
+#: plugins/sudoers/policy.c:1332
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "Шлях до nsswitch: %s\n"
+
+#: plugins/sudoers/policy.c:1335
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "Шлях до ldap.conf: %s\n"
+
+#: plugins/sudoers/policy.c:1337
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "Шлях до ldap.secret: %s\n"
+
+#: plugins/sudoers/policy.c:1370
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "неможливо зареєструвати процедуру перехоплення типу %d (версія %d.%d)"
+
+#: plugins/sudoers/policy.c:1388
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "неможливо скасувати реєстрацію процедури перехоплення типу %d (версія %d.%d)"
+
+#: plugins/sudoers/pwutil.c:242 plugins/sudoers/pwutil.c:260
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "не вдалося кешувати uid %u"
+
+#: plugins/sudoers/pwutil.c:254
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "не вдалося кешувати uid %u, запис вже існує"
+
+#: plugins/sudoers/pwutil.c:314 plugins/sudoers/pwutil.c:332
+#: plugins/sudoers/pwutil.c:395 plugins/sudoers/pwutil.c:440
+#, c-format
+msgid "unable to cache user %s"
+msgstr "не вдалося кешувати користувача %s"
+
+#: plugins/sudoers/pwutil.c:327
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "не вдалося кешувати користувача %s, запис вже існує"
+
+#: plugins/sudoers/pwutil.c:559 plugins/sudoers/pwutil.c:577
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "не вдалося кешувати gid %u"
+
+#: plugins/sudoers/pwutil.c:571
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "не вдалося кешувати gid %u, запис вже існує"
+
+#: plugins/sudoers/pwutil.c:625 plugins/sudoers/pwutil.c:643
+#: plugins/sudoers/pwutil.c:704 plugins/sudoers/pwutil.c:753
+#, c-format
+msgid "unable to cache group %s"
+msgstr "не вдалося кешувати групу %s"
+
+#: plugins/sudoers/pwutil.c:638
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "не вдалося кешувати групу %s, запис вже існує"
+
+#: plugins/sudoers/pwutil.c:900 plugins/sudoers/pwutil.c:985
+#: plugins/sudoers/pwutil.c:1039 plugins/sudoers/pwutil.c:1095
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "не вдалося кешувати список груп %s, запис вже існує"
+
+#: plugins/sudoers/pwutil.c:906 plugins/sudoers/pwutil.c:990
+#: plugins/sudoers/pwutil.c:1045 plugins/sudoers/pwutil.c:1100
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "не вдалося кешувати список груп %s"
+
+#: plugins/sudoers/pwutil.c:979
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "не вдалося обробити записи груп %s"
+
+#: plugins/sudoers/pwutil.c:1089
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "не вдалося обробити записи ідентифікаторів груп %s"
+
+#: plugins/sudoers/set_perms.c:120 plugins/sudoers/set_perms.c:457
+#: plugins/sudoers/set_perms.c:870 plugins/sudoers/set_perms.c:1186
+#: plugins/sudoers/set_perms.c:1490
+msgid "perm stack overflow"
+msgstr "переповнення стека доступу"
+
+#: plugins/sudoers/set_perms.c:131 plugins/sudoers/set_perms.c:387
+#: plugins/sudoers/set_perms.c:468 plugins/sudoers/set_perms.c:736
+#: plugins/sudoers/set_perms.c:881 plugins/sudoers/set_perms.c:1109
+#: plugins/sudoers/set_perms.c:1197 plugins/sudoers/set_perms.c:1422
+#: plugins/sudoers/set_perms.c:1501 plugins/sudoers/set_perms.c:1592
+msgid "perm stack underflow"
+msgstr "вичерпання стека доступу"
+
+#: plugins/sudoers/set_perms.c:191 plugins/sudoers/set_perms.c:515
+#: plugins/sudoers/set_perms.c:1251 plugins/sudoers/set_perms.c:1535
+msgid "unable to change to root gid"
+msgstr "не вдалося змінити ідентифікатор групи (gid) root"
+
+#: plugins/sudoers/set_perms.c:282 plugins/sudoers/set_perms.c:612
+#: plugins/sudoers/set_perms.c:1013 plugins/sudoers/set_perms.c:1328
+msgid "unable to change to runas gid"
+msgstr "не вдалося змінити gid на runas"
+
+#: plugins/sudoers/set_perms.c:287 plugins/sudoers/set_perms.c:617
+#: plugins/sudoers/set_perms.c:1018 plugins/sudoers/set_perms.c:1333
+msgid "unable to set runas group vector"
+msgstr "не вдалося встановити вектор групи виконання"
+
+#: plugins/sudoers/set_perms.c:298 plugins/sudoers/set_perms.c:628
+#: plugins/sudoers/set_perms.c:1027 plugins/sudoers/set_perms.c:1342
+msgid "unable to change to runas uid"
+msgstr "не вдалося змінити uid на runas"
+
+#: plugins/sudoers/set_perms.c:320 plugins/sudoers/set_perms.c:650
+#: plugins/sudoers/set_perms.c:1047 plugins/sudoers/set_perms.c:1362
+msgid "unable to change to sudoers gid"
+msgstr "не вдалося змінити gid на sudoers"
+
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579
+msgid "too many processes"
+msgstr "забагато процесів"
+
+#: plugins/sudoers/solaris_audit.c:62
+msgid "unable to get current working directory"
+msgstr "не вдалося отримати поточний робочий каталог"
+
+#: plugins/sudoers/solaris_audit.c:70
+#, c-format
+msgid "truncated audit path ctx->user.cmnd: %s"
+msgstr "обрізаний шлях аудиту ctx->user.cmnd: %s"
+
+#: plugins/sudoers/solaris_audit.c:77
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "обрізаний шлях аудиту argv[0]: %s"
+
+#: plugins/sudoers/sssd.c:581
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "Не вдалося ініціалізувати джерело SSS. Чи встановлено у вашій системі SSSD?"
+
+#: plugins/sudoers/sssd.c:589 plugins/sudoers/sssd.c:598
+#: plugins/sudoers/sssd.c:607 plugins/sudoers/sssd.c:616
+#: plugins/sudoers/sssd.c:625
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "не вдалося знайти символ «%s» у %s"
+
+#: plugins/sudoers/sudoers.c:250
+#, c-format
+msgid "unable to get defaults from %s"
+msgstr "на вдалося отримати типові значення від %s"
+
+#: plugins/sudoers/sudoers.c:259
+msgid "no valid sudoers sources found, quitting"
+msgstr "не знайдено коректних джерел даних sudoers, завершення роботи"
+
+#: plugins/sudoers/sudoers.c:366
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers вказує, що sudo не можна користуватися для виконання команд від root"
+
+#: plugins/sudoers/sudoers.c:375
+msgid "user not allowed to override closefrom limit"
+msgstr "користувачеві заборонено перевизначати обмеження closefrom"
+
+#: plugins/sudoers/sudoers.c:376
+msgid "you are not permitted to use the -C option"
+msgstr "вам не дозволено використовувати параметр -C"
+
+#: plugins/sudoers/sudoers.c:440
+msgid "no tty"
+msgstr "немає tty"
+
+#: plugins/sudoers/sudoers.c:441
+msgid "sorry, you must have a tty to run sudo"
+msgstr "вибачте, для виконання sudo вашому користувачеві потрібен tty"
+
+#: plugins/sudoers/sudoers.c:449
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "некоректний запис оболонки для користувача %s: %s"
+
+#: plugins/sudoers/sudoers.c:491
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "користувачеві заборонено змінювати кореневий каталог на %s"
+
+#: plugins/sudoers/sudoers.c:493
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "вам не дозволено використовувати параметр -R з %s"
+
+#: plugins/sudoers/sudoers.c:506
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "користувачеві заборонено змінювати каталог на %s"
+
+#: plugins/sudoers/sudoers.c:507
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "вам не дозволено використовувати параметр -D з %s"
+
+#: plugins/sudoers/sudoers.c:542
+msgid "command in current directory"
+msgstr "команда у поточному каталозі"
+
+#: plugins/sudoers/sudoers.c:557
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr "«cd» є вбудованою командою оболонки, її не може бути запущено безпосередньо."
+
+#: plugins/sudoers/sudoers.c:559
+msgid "the -s option may be used to run a privileged shell."
+msgstr "параметр -s може бути використано для запуску привілейованої оболонки."
+
+#: plugins/sudoers/sudoers.c:561
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr "параметр -D може бути використано для запуску команди у вказаному каталозі."
+
+#: plugins/sudoers/sudoers.c:570
+msgid "user not allowed to set a command timeout"
+msgstr "користувачеві заборонено встановлювати час очікування на виконання команди"
+
+#: plugins/sudoers/sudoers.c:572
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "вибачте, вам не дозволено встановлювати час очікування на виконання команди"
+
+#: plugins/sudoers/sudoers.c:580
+msgid "user not allowed to preserve the environment"
+msgstr "користувачеві заборонено зберігати середовище"
+
+#: plugins/sudoers/sudoers.c:582
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "вибачте, вам не дозволено зберігати середовище"
+
+#: plugins/sudoers/sudoers.c:618
+msgid "no command specified"
+msgstr "не вказано команду"
+
+#: plugins/sudoers/sudoers.c:759
+msgid "error setting user-specified environment variables"
+msgstr "помилка під час спроби встановити значення змінних середовища, які вказано користувачем"
+
+#: plugins/sudoers/sudoers.c:1211
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "Немає потреби у запуску sudoedit за допомогою sudo"
+
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:1613
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "не вдалося прочитати %s"
+
+#: plugins/sudoers/sudoers.c:1321 plugins/sudoers/visudo.c:1123
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s не є звичайним файлом"
+
+#: plugins/sudoers/sudoers.c:1325 plugins/sudoers/timestamp.c:272 toke.l:1355
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s належить uid %u, має належати %u"
+
+#: plugins/sudoers/sudoers.c:1330 plugins/sudoers/timestamp.c:279 toke.l:1360
+#, c-format
+msgid "%s is world writable"
+msgstr "Запис до «%s» можливий для довільного користувача"
+
+#: plugins/sudoers/sudoers.c:1334 plugins/sudoers/timestamp.c:284 toke.l:1363
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s належить gid %u, має належати %u"
+
+#: plugins/sudoers/sudoers.c:1363
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "використовувати «-c %s» може лише root"
+
+#: plugins/sudoers/sudoers.c:1382
+#, c-format
+msgid "unknown login class %s"
+msgstr "невідомий клас входу %s"
+
+#: plugins/sudoers/sudoers_cb.c:120 plugins/sudoers/sudoers_cb.c:135
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "не вдалося визначити адресу вузла %s"
+
+#: plugins/sudoers/sudoreplay.c:252
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "некоректний параметр фільтрування: %s"
+
+#: plugins/sudoers/sudoreplay.c:268
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "некоректне значення макс. очікування: %s"
+
+#: plugins/sudoers/sudoreplay.c:291
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "некоректний коефіцієнт швидкості: %s"
+
+#: plugins/sudoers/sudoreplay.c:326
+#, c-format
+msgid "invalid time offset %s"
+msgstr "некоректний зсув часу %s"
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:340
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/розклад за часом: %s"
+
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Відтворення сеансу sudo: %s"
+
+#: plugins/sudoers/sudoreplay.c:634
+msgid "unable to set tty to raw mode"
+msgstr "не вдалося перевести tty у режим без обробки даних"
+
+#: plugins/sudoers/sudoreplay.c:685
+msgid "Warning: your terminal is too small to properly replay the log."
+msgstr "Попередження: розміри вашого термінала є замалими для належного показу журналу."
+
+#: plugins/sudoers/sudoreplay.c:686
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Встановлено формат журналу %d x %d, тоді як формат термінала — %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:714
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Відтворення завершено, натисніть будь-яку клавішу, щоб повернутися до термінала."
+
+#: plugins/sudoers/sudoreplay.c:1217 plugins/sudoers/sudoreplay.c:1247
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "неоднозначний вираз «%s»"
+
+#: plugins/sudoers/sudoreplay.c:1269
+msgid "unmatched ')' in expression"
+msgstr "зайва дужка, «)», у виразі"
+
+#: plugins/sudoers/sudoreplay.c:1273
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "невідомий ключ пошуку «%s»"
+
+#: plugins/sudoers/sudoreplay.c:1288
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s потребує визначення аргументу"
+
+#: plugins/sudoers/sudoreplay.c:1298
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "не вдалося обробити дату «%s»"
+
+#: plugins/sudoers/sudoreplay.c:1307
+msgid "unmatched '(' in expression"
+msgstr "зайва дужка, «(», у виразі"
+
+#: plugins/sudoers/sudoreplay.c:1309
+msgid "illegal trailing \"or\""
+msgstr "помилкове завершальне «or»"
+
+#: plugins/sudoers/sudoreplay.c:1311
+msgid "illegal trailing \"!\""
+msgstr "помилкове завершальне «!»"
+
+#: plugins/sudoers/sudoreplay.c:1417
+#, c-format
+msgid "unknown search type %d"
+msgstr "невідомий тип пошуку %d"
+
+#: plugins/sudoers/sudoreplay.c:1679
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "користування: %s [-hnRS] [-d каталог] [-m число] [-s число] ідентифікатор\n"
+
+#: plugins/sudoers/sudoreplay.c:1681
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "використання: %s [-h] [-d каталог] -l [вираз для пошуку]\n"
+
+#: plugins/sudoers/sudoreplay.c:1695
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s — відтворення журналів сеансів sudo\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1697
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Параметри:\n"
+" -d, --directory=каталог вказати каталог для журналів сеансу\n"
+" -f, --filter=фільтр вказати, який тип вводу-виводу слід показувати\n"
+" -h, --help показати довідкове повідомлення і завершити роботу\n"
+" -l, --list показати список можливих ідентифікаторів сеансів, відповідних до виразу\n"
+" -m, --max-wait=макс_очік максимальний час (у секундах) очікування між подіями\n"
+" -n, --non-interactive на надсилати запитів, сеанс роботи буде надіслано до стандартного виведення\n"
+" -R, --no-resize не намагатися змінити розміри термінала\n"
+" -S, --suspend-wait очікувати, доки виконання команди призупинено\n"
+" -s, --speed=коеф_швидк коефіцієнт прискорення або сповільнення виводу даних\n"
+" -V, --version показати дані щодо версії і завершити роботу"
+
+#: plugins/sudoers/testsudoers.c:392
+#, c-format
+msgid ""
+"\n"
+"Invalid shell for user %s: %s\n"
+msgstr ""
+"\n"
+"Некоректний запис оболонки для користувача %s: %s\n"
+
+#: plugins/sudoers/testsudoers.c:411
+msgid ""
+"\n"
+"Password required"
+msgstr ""
+"\n"
+"Слід вказати пароль"
+
+#: plugins/sudoers/testsudoers.c:422
+msgid ""
+"\n"
+"Parse error"
+msgstr ""
+"\n"
+"Помилка обробки"
+
+#: plugins/sudoers/testsudoers.c:425
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Команду дозволено"
+
+#: plugins/sudoers/testsudoers.c:428
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Команду заборонено"
+
+#: plugins/sudoers/testsudoers.c:431
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Не знайдено відповідника команди"
+
+#: plugins/sudoers/timestamp.c:364 plugins/sudoers/timestamp.c:711
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "не вдалося обрізати файл часової позначки до %lld байтів"
+
+#: plugins/sudoers/timestamp.c:908
+msgid "ignoring time stamp from the future"
+msgstr "ігноруємо часову позначку з майбутнього"
+
+#: plugins/sudoers/timestamp.c:931
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "занадто далека часова позначка у майбутньому: %20.20s"
+
+#: plugins/sudoers/timestamp.c:1067
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "не вдалося заблокувати файл часової позначки %s"
+
+#: plugins/sudoers/timestamp.c:1114
+#, c-format
+msgid "%s:%d:%d timestampowner: unknown user %s"
+msgstr "%s:%d:%d timestampowner: невідомий користувач %s"
+
+#: plugins/sudoers/toke_util.c:159
+msgid "sudoedit should not be specified with a path"
+msgstr "sudoedit не слід вказувати разом із шляхом"
+
+#: plugins/sudoers/visudo.c:308 plugins/sudoers/visudo.c:714
+#, c-format
+msgid "press return to edit %s: "
+msgstr "натисніть Enter для редагування %s: "
+
+#: plugins/sudoers/visudo.c:323
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "дані сеансу редагування залишилися у %s"
+
+#: plugins/sudoers/visudo.c:401
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "вказаного редактора (%s) не існує"
+
+#: plugins/sudoers/visudo.c:406
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "не знайдено жодного редактора (шлях до редактора = %s)"
+
+#: plugins/sudoers/visudo.c:494 plugins/sudoers/visudo.c:786
+#, c-format
+msgid "unable to stat %s"
+msgstr "не вдалося виконати stat для %s"
+
+#: plugins/sudoers/visudo.c:514 plugins/sudoers/visudo.c:522
+msgid "write error"
+msgstr "помилка запису"
+
+#: plugins/sudoers/visudo.c:568
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "не вдалося обробити stat файл тимчасових даних (%s), %s не змінено"
+
+#: plugins/sudoers/visudo.c:575
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "файл тимчасових даних має нульовий об’єм (%s), %s не змінено"
+
+#: plugins/sudoers/visudo.c:581
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "помилка редактора (%s), %s не змінено"
+
+#: plugins/sudoers/visudo.c:613
+#, c-format
+msgid "%s unchanged"
+msgstr "%s не змінено"
+
+#: plugins/sudoers/visudo.c:661
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "не вдалося повторно відкрити файл тимчасових даних (%s), %s не змінено."
+
+#: plugins/sudoers/visudo.c:674
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "не вдалося обробити файл тимчасових даних (%s), невідома помилка"
+
+#: plugins/sudoers/visudo.c:760 plugins/sudoers/visudo.c:790
+#: plugins/sudoers/visudo.c:797
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "не вдалося встановити (uid, gid) %s у значення (%u, %u)"
+
+#: plugins/sudoers/visudo.c:825
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s і %s не перебувають у одній файловій системі, використовуємо mv для перейменування"
+
+#: plugins/sudoers/visudo.c:836
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "помилка команди: «%s %s %s», %s не змінено"
+
+#: plugins/sudoers/visudo.c:843
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "помилка перейменування %s, %s не змінено"
+
+#: plugins/sudoers/visudo.c:864
+msgid "What now? "
+msgstr "А зараз що? "
+
+#: plugins/sudoers/visudo.c:878
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Параметри:\n"
+" (e) — повторне редагування файла sudoers\n"
+" (x) — вийти без внесення змін до файла sudoers\n"
+" (Q) — вийти зі збереженням файла sudoers (НЕБЕЗПЕЧНО!)\n"
+
+#: plugins/sudoers/visudo.c:923
+#, c-format
+msgid "unable to run %s"
+msgstr "не вдалося виконати %s"
+
+#: plugins/sudoers/visudo.c:954
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: помилковий власник (uid, gid), має бути (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:965
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: помилкові права доступу, режим доступу має бути 0%o\n"
+
+#: plugins/sudoers/visudo.c:1017 plugins/sudoers/visudo.c:1024
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: вдала обробка\n"
+
+#: plugins/sudoers/visudo.c:1043
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s зайнято, повторіть спробу пізніше"
+
+#: plugins/sudoers/visudo.c:1047
+msgid "Edit anyway? [y/N]"
+msgstr "Редагувати попри усе? [y/N]"
+
+#: plugins/sudoers/visudo.c:1206
+msgid "the -x option will be removed in a future release"
+msgstr "параметр -x буде вилучено у наступному випуску"
+
+#: plugins/sudoers/visudo.c:1208
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "будь ласка, скористайтеся замість нього програмою cvtsudoers"
+
+#: plugins/sudoers/visudo.c:1228
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "Попередження: %s:%d:%d: не використано %s «%s»"
+
+#: plugins/sudoers/visudo.c:1341
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s — безпечне редагування файла sudoers\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1343
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -I, --no-includes do not edit include files\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Параметри:\n"
+" -c, --check режим лише перевірки\n"
+" -f, --file=файл вказати розташування файла sudoers\n"
+" -h, --help показати довідкове повідомлення і завершити роботу\n"
+" -I, --no-includes не редагувати включені файли\n"
+" -q, --quiet стислі повідомлення щодо синтаксичних помилок\n"
+" -s, --strict строга перевірка синтаксису\n"
+" -V, --version показати дані щодо версії і завершити роботу\n"
+
+#: toke.l:184
+msgid "empty string"
+msgstr "порожній рядок"
+
+#: toke.l:196 toke.l:566
+msgid "empty group"
+msgstr "порожня група"
+
+#: toke.l:206 toke.l:564
+msgid "empty netgroup"
+msgstr "порожня мережева група"
+
+#: toke.l:284
+msgid "unterminated regular expression"
+msgstr "незавершений формальний вираз"
+
+#: toke.l:358 toke.l:370 toke.l:382 toke.l:398 toke.l:417 toke.l:457
+msgid "invalid line continuation"
+msgstr "некоректне продовження рядка"
+
+#: toke.l:603 toke.l:615
+msgid "invalid IPv6 address"
+msgstr "некоректна адреса IPv6"
+
+#: toke.l:863
+msgid "unexpected line break in string"
+msgstr "неочікуваний розрив рядків у рядку"
+
+#: toke.l:982
+msgid "ignoring editor backup file"
+msgstr "ігноруємо створений редактором файл резервної копії"
+
+#: toke.l:985
+msgid "ignoring file name containing '.'"
+msgstr "ігноруємо назву файла, що містить '.'"
+
+#: toke.l:1310
+msgid "too many levels of includes"
+msgstr "занадто високий рівень вкладеності"
+
+#~ msgid "\thost unmatched"
+#~ msgstr "\tвідповідника вузла не знайдено"
+
+#~ msgid "timestamp owner (%s): No such user"
+#~ msgstr "власник часового штампа (%s): не знайдено користувача з таким іменем"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s має належати користувачеві з uid %d"
+
+#~ msgid "%s must only be writable by owner"
+#~ msgstr "%s має бути доступним до запису лише для власника"
+
+#~ msgid "%s is group writable"
+#~ msgstr "%s доступний до запису учасниками групи"
+
+#~ msgid "lecture status path too long: %s/%s"
+#~ msgstr "шлях до даних щодо стану отримання настанов є занадто довгим: %s/%s"
+
+#~ msgid "Warning: %s:%d:%d: cycle in %s \"%s\""
+#~ msgstr "Попередження: %s:%d:%d: цикл у %s «%s»"
+
+#~ msgid "Warning: %s:%d:%d: %s \"%s\" referenced but not defined"
+#~ msgstr "Попередження: виявлено посилання %s:%d:%d: %s «%s», яке не визначено"
+
+#~ msgid "parse error in %s near line %d\n"
+#~ msgstr "помилка обробки у %s поблизу рядка %d\n"
+
+#~ msgid "parse error in %s\n"
+#~ msgstr "помилка обробки у %s\n"
+
+#~ msgid "%s:%d:%d: no value specified for \"%s\""
+#~ msgstr "%s:%d:%d: не вказано значення для «%s»"
+
+#~ msgid "%s:%d:%d: invalid operator \"%c=\" for \"%s\""
+#~ msgstr "%s:%d:%d: некоректний оператор «%c=» для «%s»"
+
+#~ msgid "%s:%d:%d: option \"%s\" does not take a value"
+#~ msgstr "%s:%d:%d: параметру «%s» не потрібно передавати значення"
+
+#~ msgid "%s:%d:%d: invalid Defaults type 0x%x for option \"%s\""
+#~ msgstr "%s:%d:%d: некоректний тип Defaults, 0x%x, для параметра «%s»"
+
+#~ msgid "%s:%d:%d: value \"%s\" is invalid for option \"%s\""
+#~ msgstr "%s:%d:%d: значення «%s» є некоректним для параметра «%s»"
+
+#~ msgid "%s:%d:%d: path name for \"%s\" too long"
+#~ msgstr "%s:%d:%d: назва шляху «%s» є надто довгою"
+
+#~ msgid "%s: path name for \"%s\" too long"
+#~ msgstr "%s: назва шляху для «%s» є надто довгою"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/', '~', or '*'"
+#~ msgstr "%s:%d:%d: значення для «%s» має починатися з «/», «~» або «*»"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/'"
+#~ msgstr "%s:%d:%d: значення для «%s» має починатися з «/»"
+
+#~ msgid "parse error in %s near line %d"
+#~ msgstr "помилка обробки у %s поблизу рядка %d"
+
+#~ msgid "parse error in %s"
+#~ msgstr "помилка обробки у %s"
+
+#~ msgid "SELinux RBAC is not supported when intercept mode is enabled"
+#~ msgstr "Якщо увімкнено режим перехоплення, підтримки RBAC SELinux не передбачено"
+
+#~ msgid "SELinux RBAC is not supported when the log_subcmds flag is enabled"
+#~ msgstr "Якщо увімкнено прапорець log_subcmds, підтримки RBAC SELinux не передбачено"
+
+#~ msgid "problem with defaults entries"
+#~ msgstr "проблема з типовими записами"
+
+#~ msgid "internal error, unable to find %s in list!"
+#~ msgstr "внутрішня помилка, не вдалося знайти %s у списку!"
diff --git a/plugins/sudoers/po/vi.mo b/plugins/sudoers/po/vi.mo
new file mode 100644
index 0000000..b0901ab
--- /dev/null
+++ b/plugins/sudoers/po/vi.mo
Binary files differ
diff --git a/plugins/sudoers/po/vi.po b/plugins/sudoers/po/vi.po
new file mode 100644
index 0000000..0cc0095
--- /dev/null
+++ b/plugins/sudoers/po/vi.po
@@ -0,0 +1,2502 @@
+# Vietnamese translation for sudo.
+# Bản dịch tiếng Việt dành cho sudo.
+# This file is put in the public domain.
+# Trần Ngọc Quân <vnwildman@gmail.com>, 2012-2014, 2015, 2016, 2017, 2018.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.8.26b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2018-10-29 08:31-0600\n"
+"PO-Revision-Date: 2018-11-01 14:10+0700\n"
+"Last-Translator: Trần Ngọc Quân <vnwildman@gmail.com>\n"
+"Language-Team: Vietnamese <translation-team-vi@lists.sourceforge.net>\n"
+"Language: vi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Language-Team-Website: <http://translationproject.org/team/vi.html>\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+"X-Generator: Gtranslator 2.91.7\n"
+
+#: confstr.sh:1
+msgid "syntax error"
+msgstr "lỗi cú pháp"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "Mật khẩu của %p: "
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] mật khẩu dành cho %p: "
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "Mật khẩu: "
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** Thông tin AN NINH cho %h ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "Rất tiếc, hãy thử lại."
+
+#: gram.y:192 gram.y:240 gram.y:247 gram.y:254 gram.y:261 gram.y:268
+#: gram.y:284 gram.y:308 gram.y:315 gram.y:322 gram.y:329 gram.y:336
+#: gram.y:399 gram.y:407 gram.y:417 gram.y:450 gram.y:457 gram.y:464
+#: gram.y:471 gram.y:553 gram.y:560 gram.y:569 gram.y:578 gram.y:595
+#: gram.y:707 gram.y:714 gram.y:721 gram.y:729 gram.y:829 gram.y:836
+#: gram.y:843 gram.y:850 gram.y:857 gram.y:883 gram.y:890 gram.y:897
+#: gram.y:1020 gram.y:1294 plugins/sudoers/alias.c:130
+#: plugins/sudoers/alias.c:137 plugins/sudoers/alias.c:153
+#: plugins/sudoers/auth/bsdauth.c:146 plugins/sudoers/auth/kerb5.c:121
+#: plugins/sudoers/auth/kerb5.c:147 plugins/sudoers/auth/pam.c:524
+#: plugins/sudoers/auth/rfc1938.c:114 plugins/sudoers/auth/sia.c:62
+#: plugins/sudoers/cvtsudoers.c:123 plugins/sudoers/cvtsudoers.c:164
+#: plugins/sudoers/cvtsudoers.c:181 plugins/sudoers/cvtsudoers.c:192
+#: plugins/sudoers/cvtsudoers.c:304 plugins/sudoers/cvtsudoers.c:432
+#: plugins/sudoers/cvtsudoers.c:565 plugins/sudoers/cvtsudoers.c:582
+#: plugins/sudoers/cvtsudoers.c:645 plugins/sudoers/cvtsudoers.c:760
+#: plugins/sudoers/cvtsudoers.c:768 plugins/sudoers/cvtsudoers.c:1178
+#: plugins/sudoers/cvtsudoers.c:1182 plugins/sudoers/cvtsudoers.c:1284
+#: plugins/sudoers/cvtsudoers_ldif.c:152 plugins/sudoers/cvtsudoers_ldif.c:195
+#: plugins/sudoers/cvtsudoers_ldif.c:242 plugins/sudoers/cvtsudoers_ldif.c:261
+#: plugins/sudoers/cvtsudoers_ldif.c:332 plugins/sudoers/cvtsudoers_ldif.c:387
+#: plugins/sudoers/cvtsudoers_ldif.c:395 plugins/sudoers/cvtsudoers_ldif.c:412
+#: plugins/sudoers/cvtsudoers_ldif.c:421 plugins/sudoers/cvtsudoers_ldif.c:568
+#: plugins/sudoers/defaults.c:661 plugins/sudoers/defaults.c:954
+#: plugins/sudoers/defaults.c:1125 plugins/sudoers/editor.c:70
+#: plugins/sudoers/editor.c:88 plugins/sudoers/editor.c:99
+#: plugins/sudoers/env.c:247 plugins/sudoers/filedigest.c:64
+#: plugins/sudoers/filedigest.c:80 plugins/sudoers/gc.c:57
+#: plugins/sudoers/group_plugin.c:136 plugins/sudoers/interfaces.c:76
+#: plugins/sudoers/iolog.c:939 plugins/sudoers/iolog_path.c:172
+#: plugins/sudoers/iolog_util.c:83 plugins/sudoers/iolog_util.c:122
+#: plugins/sudoers/iolog_util.c:131 plugins/sudoers/iolog_util.c:141
+#: plugins/sudoers/iolog_util.c:149 plugins/sudoers/iolog_util.c:153
+#: plugins/sudoers/ldap.c:183 plugins/sudoers/ldap.c:414
+#: plugins/sudoers/ldap.c:418 plugins/sudoers/ldap.c:430
+#: plugins/sudoers/ldap.c:721 plugins/sudoers/ldap.c:885
+#: plugins/sudoers/ldap.c:1233 plugins/sudoers/ldap.c:1660
+#: plugins/sudoers/ldap.c:1697 plugins/sudoers/ldap.c:1778
+#: plugins/sudoers/ldap.c:1913 plugins/sudoers/ldap.c:2014
+#: plugins/sudoers/ldap.c:2030 plugins/sudoers/ldap_conf.c:221
+#: plugins/sudoers/ldap_conf.c:252 plugins/sudoers/ldap_conf.c:304
+#: plugins/sudoers/ldap_conf.c:340 plugins/sudoers/ldap_conf.c:443
+#: plugins/sudoers/ldap_conf.c:458 plugins/sudoers/ldap_conf.c:555
+#: plugins/sudoers/ldap_conf.c:588 plugins/sudoers/ldap_conf.c:680
+#: plugins/sudoers/ldap_conf.c:762 plugins/sudoers/ldap_util.c:508
+#: plugins/sudoers/ldap_util.c:564 plugins/sudoers/linux_audit.c:81
+#: plugins/sudoers/logging.c:195 plugins/sudoers/logging.c:511
+#: plugins/sudoers/logging.c:532 plugins/sudoers/logging.c:573
+#: plugins/sudoers/logging.c:752 plugins/sudoers/logging.c:1010
+#: plugins/sudoers/match.c:725 plugins/sudoers/match.c:772
+#: plugins/sudoers/match.c:813 plugins/sudoers/match.c:841
+#: plugins/sudoers/match.c:929 plugins/sudoers/match.c:1009
+#: plugins/sudoers/parse.c:195 plugins/sudoers/parse.c:207
+#: plugins/sudoers/parse.c:222 plugins/sudoers/parse.c:234
+#: plugins/sudoers/parse_ldif.c:141 plugins/sudoers/parse_ldif.c:168
+#: plugins/sudoers/parse_ldif.c:237 plugins/sudoers/parse_ldif.c:244
+#: plugins/sudoers/parse_ldif.c:249 plugins/sudoers/parse_ldif.c:325
+#: plugins/sudoers/parse_ldif.c:336 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:367 plugins/sudoers/parse_ldif.c:379
+#: plugins/sudoers/parse_ldif.c:383 plugins/sudoers/parse_ldif.c:397
+#: plugins/sudoers/parse_ldif.c:564 plugins/sudoers/parse_ldif.c:594
+#: plugins/sudoers/parse_ldif.c:619 plugins/sudoers/parse_ldif.c:679
+#: plugins/sudoers/parse_ldif.c:698 plugins/sudoers/parse_ldif.c:744
+#: plugins/sudoers/parse_ldif.c:754 plugins/sudoers/policy.c:502
+#: plugins/sudoers/policy.c:744 plugins/sudoers/prompt.c:98
+#: plugins/sudoers/pwutil.c:197 plugins/sudoers/pwutil.c:269
+#: plugins/sudoers/pwutil.c:346 plugins/sudoers/pwutil.c:520
+#: plugins/sudoers/pwutil.c:586 plugins/sudoers/pwutil.c:656
+#: plugins/sudoers/pwutil.c:814 plugins/sudoers/pwutil.c:871
+#: plugins/sudoers/pwutil.c:916 plugins/sudoers/pwutil.c:974
+#: plugins/sudoers/sssd.c:152 plugins/sudoers/sssd.c:398
+#: plugins/sudoers/sssd.c:461 plugins/sudoers/sssd.c:505
+#: plugins/sudoers/sssd.c:552 plugins/sudoers/sssd.c:743
+#: plugins/sudoers/stubs.c:101 plugins/sudoers/stubs.c:109
+#: plugins/sudoers/sudoers.c:269 plugins/sudoers/sudoers.c:279
+#: plugins/sudoers/sudoers.c:288 plugins/sudoers/sudoers.c:330
+#: plugins/sudoers/sudoers.c:653 plugins/sudoers/sudoers.c:779
+#: plugins/sudoers/sudoers.c:823 plugins/sudoers/sudoers.c:1097
+#: plugins/sudoers/sudoers_debug.c:112 plugins/sudoers/sudoreplay.c:579
+#: plugins/sudoers/sudoreplay.c:582 plugins/sudoers/sudoreplay.c:1259
+#: plugins/sudoers/sudoreplay.c:1459 plugins/sudoers/sudoreplay.c:1463
+#: plugins/sudoers/testsudoers.c:134 plugins/sudoers/testsudoers.c:234
+#: plugins/sudoers/testsudoers.c:251 plugins/sudoers/testsudoers.c:585
+#: plugins/sudoers/timestamp.c:437 plugins/sudoers/timestamp.c:481
+#: plugins/sudoers/timestamp.c:958 plugins/sudoers/toke_util.c:57
+#: plugins/sudoers/toke_util.c:110 plugins/sudoers/toke_util.c:147
+#: plugins/sudoers/tsdump.c:128 plugins/sudoers/visudo.c:150
+#: plugins/sudoers/visudo.c:312 plugins/sudoers/visudo.c:318
+#: plugins/sudoers/visudo.c:428 plugins/sudoers/visudo.c:606
+#: plugins/sudoers/visudo.c:926 plugins/sudoers/visudo.c:1013
+#: plugins/sudoers/visudo.c:1102 toke.l:844 toke.l:945 toke.l:1102
+msgid "unable to allocate memory"
+msgstr "không thể cấp phát bộ nhớ"
+
+#: gram.y:482
+msgid "a digest requires a path name"
+msgstr "tóm lược yêu cầu một đối số là tên đường dẫn"
+
+#: gram.y:608
+msgid "invalid notbefore value"
+msgstr "giá trị notbefore không hợp lệ"
+
+#: gram.y:616
+msgid "invalid notafter value"
+msgstr "giá trị notafter không hợp lệ"
+
+#: gram.y:625 plugins/sudoers/policy.c:318
+msgid "timeout value too large"
+msgstr "giá trị timeout quá lớn"
+
+#: gram.y:627 plugins/sudoers/policy.c:320
+msgid "invalid timeout value"
+msgstr "giá trị timeout không hợp lệ"
+
+#: gram.y:1294 plugins/sudoers/auth/pam.c:354 plugins/sudoers/auth/pam.c:524
+#: plugins/sudoers/auth/rfc1938.c:114 plugins/sudoers/cvtsudoers.c:123
+#: plugins/sudoers/cvtsudoers.c:163 plugins/sudoers/cvtsudoers.c:180
+#: plugins/sudoers/cvtsudoers.c:191 plugins/sudoers/cvtsudoers.c:303
+#: plugins/sudoers/cvtsudoers.c:431 plugins/sudoers/cvtsudoers.c:564
+#: plugins/sudoers/cvtsudoers.c:581 plugins/sudoers/cvtsudoers.c:645
+#: plugins/sudoers/cvtsudoers.c:760 plugins/sudoers/cvtsudoers.c:767
+#: plugins/sudoers/cvtsudoers.c:1178 plugins/sudoers/cvtsudoers.c:1182
+#: plugins/sudoers/cvtsudoers.c:1284 plugins/sudoers/cvtsudoers_ldif.c:151
+#: plugins/sudoers/cvtsudoers_ldif.c:194 plugins/sudoers/cvtsudoers_ldif.c:241
+#: plugins/sudoers/cvtsudoers_ldif.c:260 plugins/sudoers/cvtsudoers_ldif.c:331
+#: plugins/sudoers/cvtsudoers_ldif.c:386 plugins/sudoers/cvtsudoers_ldif.c:394
+#: plugins/sudoers/cvtsudoers_ldif.c:411 plugins/sudoers/cvtsudoers_ldif.c:420
+#: plugins/sudoers/cvtsudoers_ldif.c:567 plugins/sudoers/defaults.c:661
+#: plugins/sudoers/defaults.c:954 plugins/sudoers/defaults.c:1125
+#: plugins/sudoers/editor.c:70 plugins/sudoers/editor.c:88
+#: plugins/sudoers/editor.c:99 plugins/sudoers/env.c:247
+#: plugins/sudoers/filedigest.c:64 plugins/sudoers/filedigest.c:80
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:136
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/iolog.c:939
+#: plugins/sudoers/iolog_path.c:172 plugins/sudoers/iolog_util.c:83
+#: plugins/sudoers/iolog_util.c:122 plugins/sudoers/iolog_util.c:131
+#: plugins/sudoers/iolog_util.c:141 plugins/sudoers/iolog_util.c:149
+#: plugins/sudoers/iolog_util.c:153 plugins/sudoers/ldap.c:183
+#: plugins/sudoers/ldap.c:414 plugins/sudoers/ldap.c:418
+#: plugins/sudoers/ldap.c:430 plugins/sudoers/ldap.c:721
+#: plugins/sudoers/ldap.c:885 plugins/sudoers/ldap.c:1233
+#: plugins/sudoers/ldap.c:1660 plugins/sudoers/ldap.c:1697
+#: plugins/sudoers/ldap.c:1778 plugins/sudoers/ldap.c:1913
+#: plugins/sudoers/ldap.c:2014 plugins/sudoers/ldap.c:2030
+#: plugins/sudoers/ldap_conf.c:221 plugins/sudoers/ldap_conf.c:252
+#: plugins/sudoers/ldap_conf.c:304 plugins/sudoers/ldap_conf.c:340
+#: plugins/sudoers/ldap_conf.c:443 plugins/sudoers/ldap_conf.c:458
+#: plugins/sudoers/ldap_conf.c:555 plugins/sudoers/ldap_conf.c:588
+#: plugins/sudoers/ldap_conf.c:679 plugins/sudoers/ldap_conf.c:762
+#: plugins/sudoers/ldap_util.c:508 plugins/sudoers/ldap_util.c:564
+#: plugins/sudoers/linux_audit.c:81 plugins/sudoers/logging.c:195
+#: plugins/sudoers/logging.c:511 plugins/sudoers/logging.c:532
+#: plugins/sudoers/logging.c:572 plugins/sudoers/logging.c:1010
+#: plugins/sudoers/match.c:724 plugins/sudoers/match.c:771
+#: plugins/sudoers/match.c:813 plugins/sudoers/match.c:841
+#: plugins/sudoers/match.c:929 plugins/sudoers/match.c:1008
+#: plugins/sudoers/parse.c:194 plugins/sudoers/parse.c:206
+#: plugins/sudoers/parse.c:221 plugins/sudoers/parse.c:233
+#: plugins/sudoers/parse_ldif.c:140 plugins/sudoers/parse_ldif.c:167
+#: plugins/sudoers/parse_ldif.c:236 plugins/sudoers/parse_ldif.c:243
+#: plugins/sudoers/parse_ldif.c:248 plugins/sudoers/parse_ldif.c:324
+#: plugins/sudoers/parse_ldif.c:335 plugins/sudoers/parse_ldif.c:341
+#: plugins/sudoers/parse_ldif.c:366 plugins/sudoers/parse_ldif.c:378
+#: plugins/sudoers/parse_ldif.c:382 plugins/sudoers/parse_ldif.c:396
+#: plugins/sudoers/parse_ldif.c:564 plugins/sudoers/parse_ldif.c:593
+#: plugins/sudoers/parse_ldif.c:618 plugins/sudoers/parse_ldif.c:678
+#: plugins/sudoers/parse_ldif.c:697 plugins/sudoers/parse_ldif.c:743
+#: plugins/sudoers/parse_ldif.c:753 plugins/sudoers/policy.c:132
+#: plugins/sudoers/policy.c:141 plugins/sudoers/policy.c:150
+#: plugins/sudoers/policy.c:176 plugins/sudoers/policy.c:303
+#: plugins/sudoers/policy.c:318 plugins/sudoers/policy.c:320
+#: plugins/sudoers/policy.c:346 plugins/sudoers/policy.c:356
+#: plugins/sudoers/policy.c:400 plugins/sudoers/policy.c:410
+#: plugins/sudoers/policy.c:419 plugins/sudoers/policy.c:428
+#: plugins/sudoers/policy.c:502 plugins/sudoers/policy.c:744
+#: plugins/sudoers/prompt.c:98 plugins/sudoers/pwutil.c:197
+#: plugins/sudoers/pwutil.c:269 plugins/sudoers/pwutil.c:346
+#: plugins/sudoers/pwutil.c:520 plugins/sudoers/pwutil.c:586
+#: plugins/sudoers/pwutil.c:656 plugins/sudoers/pwutil.c:814
+#: plugins/sudoers/pwutil.c:871 plugins/sudoers/pwutil.c:916
+#: plugins/sudoers/pwutil.c:974 plugins/sudoers/set_perms.c:392
+#: plugins/sudoers/set_perms.c:771 plugins/sudoers/set_perms.c:1155
+#: plugins/sudoers/set_perms.c:1481 plugins/sudoers/set_perms.c:1646
+#: plugins/sudoers/sssd.c:151 plugins/sudoers/sssd.c:398
+#: plugins/sudoers/sssd.c:461 plugins/sudoers/sssd.c:505
+#: plugins/sudoers/sssd.c:552 plugins/sudoers/sssd.c:743
+#: plugins/sudoers/stubs.c:101 plugins/sudoers/stubs.c:109
+#: plugins/sudoers/sudoers.c:269 plugins/sudoers/sudoers.c:279
+#: plugins/sudoers/sudoers.c:288 plugins/sudoers/sudoers.c:330
+#: plugins/sudoers/sudoers.c:653 plugins/sudoers/sudoers.c:779
+#: plugins/sudoers/sudoers.c:823 plugins/sudoers/sudoers.c:1097
+#: plugins/sudoers/sudoers_debug.c:111 plugins/sudoers/sudoreplay.c:579
+#: plugins/sudoers/sudoreplay.c:582 plugins/sudoers/sudoreplay.c:1259
+#: plugins/sudoers/sudoreplay.c:1459 plugins/sudoers/sudoreplay.c:1463
+#: plugins/sudoers/testsudoers.c:134 plugins/sudoers/testsudoers.c:234
+#: plugins/sudoers/testsudoers.c:251 plugins/sudoers/testsudoers.c:585
+#: plugins/sudoers/timestamp.c:437 plugins/sudoers/timestamp.c:481
+#: plugins/sudoers/timestamp.c:958 plugins/sudoers/toke_util.c:57
+#: plugins/sudoers/toke_util.c:110 plugins/sudoers/toke_util.c:147
+#: plugins/sudoers/tsdump.c:128 plugins/sudoers/visudo.c:150
+#: plugins/sudoers/visudo.c:312 plugins/sudoers/visudo.c:318
+#: plugins/sudoers/visudo.c:428 plugins/sudoers/visudo.c:606
+#: plugins/sudoers/visudo.c:926 plugins/sudoers/visudo.c:1013
+#: plugins/sudoers/visudo.c:1102 toke.l:844 toke.l:945 toke.l:1102
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: plugins/sudoers/alias.c:148
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "Bí danh “%s” đã được định nghĩa rồi"
+
+#: plugins/sudoers/auth/bsdauth.c:73
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "không thể lấy lớp đăng nhập cho tài khoản %s"
+
+#: plugins/sudoers/auth/bsdauth.c:78
+msgid "unable to begin bsd authentication"
+msgstr "không thể khởi chạy xác thực kiểu bsd"
+
+#: plugins/sudoers/auth/bsdauth.c:86
+msgid "invalid authentication type"
+msgstr "kiểu xác thực không hợp lệ"
+
+#: plugins/sudoers/auth/bsdauth.c:95
+msgid "unable to initialize BSD authentication"
+msgstr "không thể khởi tạo xác thực kiểu BSD"
+
+#: plugins/sudoers/auth/bsdauth.c:183
+msgid "your account has expired"
+msgstr "tài khoản bạn đã hết hiệu lực"
+
+#: plugins/sudoers/auth/bsdauth.c:185
+msgid "approval failed"
+msgstr "gặp lỗi khi chấp thuận"
+
+#: plugins/sudoers/auth/fwtk.c:57
+msgid "unable to read fwtk config"
+msgstr "không thể đọc cấu hình fwtk"
+
+#: plugins/sudoers/auth/fwtk.c:62
+msgid "unable to connect to authentication server"
+msgstr "không thể kết nối tới máy chủ xác thực"
+
+#: plugins/sudoers/auth/fwtk.c:68 plugins/sudoers/auth/fwtk.c:92
+#: plugins/sudoers/auth/fwtk.c:124
+msgid "lost connection to authentication server"
+msgstr "mất kết nối đến máy phục vụ xác thực"
+
+#: plugins/sudoers/auth/fwtk.c:72
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"lỗi máy phục vụ xác thực:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:113
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s: không thể chuyển đổi người ủy nhiệm sang chuỗi (“%s”): %s"
+
+#: plugins/sudoers/auth/kerb5.c:163
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s: không thể phân tích “%s”: %s"
+
+#: plugins/sudoers/auth/kerb5.c:172
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s: không thể phân giải bộ nhớ đệm “credential”: %s"
+
+#: plugins/sudoers/auth/kerb5.c:219
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s: không thể phân bổ các tùy chọn: %s"
+
+#: plugins/sudoers/auth/kerb5.c:234
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s: không thể lấy giấy ủy nhiệm: %s"
+
+#: plugins/sudoers/auth/kerb5.c:247
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s: không thể khởi tạo bộ nhớ đệm “credential”: %s"
+
+#: plugins/sudoers/auth/kerb5.c:250
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s: không thể cất giữ “credential” trong bộ nhớ tạm: %s"
+
+#: plugins/sudoers/auth/kerb5.c:314
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s: không thể lấy tên máy chủ chính: %s"
+
+#: plugins/sudoers/auth/kerb5.c:328
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s: Không thể thẩm tra TGT! Gần như chắc chắn là bị tấn công!: %s"
+
+#: plugins/sudoers/auth/pam.c:113
+msgid "unable to initialize PAM"
+msgstr "không thể khởi tạo PAM"
+
+#: plugins/sudoers/auth/pam.c:204
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "lỗi xác thực PAM: %s"
+
+#: plugins/sudoers/auth/pam.c:221
+msgid "account validation failure, is your account locked?"
+msgstr "xác thực tài khoản gặp lỗi nghiêm trọng, có phải tài khoản của bạn đã bị khóa?"
+
+#: plugins/sudoers/auth/pam.c:229
+msgid "Account or password is expired, reset your password and try again"
+msgstr "Mật khẩu hay tài khoản đã hết hạn sử dụng, hãy đặt lại mật khẩu của bạn và thử lại"
+
+#: plugins/sudoers/auth/pam.c:238
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "không thể thay đổi mật khẩu đã hết hạn: %s"
+
+#: plugins/sudoers/auth/pam.c:246
+msgid "Password expired, contact your system administrator"
+msgstr "Mật khẩu đã hết hạn dùng, hãy liên lạc với người quản trị hệ thống của bạn"
+
+#: plugins/sudoers/auth/pam.c:250
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "Tài khoản hết hạn hoặc cấu hình PAM không có phiên “tài khoản” cho sudo, hãy liên hệ với người quản trị hệ thống của bạn"
+
+#: plugins/sudoers/auth/pam.c:257 plugins/sudoers/auth/pam.c:262
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "lỗi quản lý tài khoảnthực PAM: %s"
+
+#: plugins/sudoers/auth/rfc1938.c:102 plugins/sudoers/visudo.c:232
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "bạn không tồn tại trong cơ sở dữ liệu %s"
+
+#: plugins/sudoers/auth/securid5.c:75
+msgid "failed to initialise the ACE API library"
+msgstr "gặp lỗi khi khởi tạo thư viện “ACE API”"
+
+#: plugins/sudoers/auth/securid5.c:101
+msgid "unable to contact the SecurID server"
+msgstr "không thể liên lạc được với máy chủ SecurID"
+
+#: plugins/sudoers/auth/securid5.c:110
+msgid "User ID locked for SecurID Authentication"
+msgstr "ID người dùng bị khóa với “SecurID Authentication”"
+
+#: plugins/sudoers/auth/securid5.c:114 plugins/sudoers/auth/securid5.c:165
+msgid "invalid username length for SecurID"
+msgstr "sai chiều dài tên tài khoản cho SecurID"
+
+#: plugins/sudoers/auth/securid5.c:118 plugins/sudoers/auth/securid5.c:170
+msgid "invalid Authentication Handle for SecurID"
+msgstr "sai Bộ Tiếp Hợp Xác Thực cho SecurID"
+
+#: plugins/sudoers/auth/securid5.c:122
+msgid "SecurID communication failed"
+msgstr "Truyền thông với SecurID gặp lỗi"
+
+#: plugins/sudoers/auth/securid5.c:126 plugins/sudoers/auth/securid5.c:215
+msgid "unknown SecurID error"
+msgstr "không hiểu lỗi SecurID"
+
+#: plugins/sudoers/auth/securid5.c:160
+msgid "invalid passcode length for SecurID"
+msgstr "sai chiều dài passcode cho SecurID"
+
+#: plugins/sudoers/auth/sia.c:72 plugins/sudoers/auth/sia.c:127
+msgid "unable to initialize SIA session"
+msgstr "không thể khởi tạo phiên SIA"
+
+#: plugins/sudoers/auth/sudo_auth.c:136
+msgid "invalid authentication methods"
+msgstr "Phương thức xác thực không hợp lệ"
+
+#: plugins/sudoers/auth/sudo_auth.c:138
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "Phương thức xác thực không hợp lệ được biên dịch vào trong sudo! Bạn không thể pha trộn kiểu xác thực giữa standalone và non-standalone"
+
+#: plugins/sudoers/auth/sudo_auth.c:259 plugins/sudoers/auth/sudo_auth.c:309
+msgid "no authentication methods"
+msgstr "chưa có phương thức xác thực"
+
+#: plugins/sudoers/auth/sudo_auth.c:261
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "Ở đây không có phương thức xác thực nào được dịch vào trong sudo! Nếu bạn muốn tắt xác thực, sử dụng tùy chọn cấu hình --disable-authentication"
+
+#: plugins/sudoers/auth/sudo_auth.c:311
+msgid "Unable to initialize authentication methods."
+msgstr "Không thể khởi tạo phương thức xác thực."
+
+#: plugins/sudoers/auth/sudo_auth.c:477
+msgid "Authentication methods:"
+msgstr "Phương thức xác thực:"
+
+#: plugins/sudoers/bsm_audit.c:123 plugins/sudoers/bsm_audit.c:215
+msgid "Could not determine audit condition"
+msgstr "Không thể phân giải điều kiện audit"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:279
+msgid "unable to commit audit record"
+msgstr "không thể chuyển giao bản ghi “audit”"
+
+#: plugins/sudoers/check.c:267
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"Chúng tôi tin rằng bạn đã nhận được bài giảng từ Quản trị Hệ thống\n"
+"nội bộ. Có thể tóm lược chúng lại thành một số điểm quan trọng sau:\n"
+"\n"
+" #1) Tôn trọng sự riêng tư của người khác.\n"
+" #2) Nghĩ trước khi gõ một lệnh.\n"
+" #3) Quyền lực lớn đi kèm với trách nhiệm lớn.\n"
+"\n"
+
+#: plugins/sudoers/check.c:310 plugins/sudoers/check.c:320
+#: plugins/sudoers/sudoers.c:696 plugins/sudoers/sudoers.c:741
+#: plugins/sudoers/tsdump.c:124
+#, c-format
+msgid "unknown uid: %u"
+msgstr "không biết mã số người dùng: %u"
+
+#: plugins/sudoers/check.c:315 plugins/sudoers/iolog.c:253
+#: plugins/sudoers/policy.c:915 plugins/sudoers/sudoers.c:1136
+#: plugins/sudoers/testsudoers.c:225 plugins/sudoers/testsudoers.c:398
+#, c-format
+msgid "unknown user: %s"
+msgstr "không biết người dùng: %s"
+
+#: plugins/sudoers/cvtsudoers.c:198
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "gia tăng thứ tự: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:214
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "bắt đầu thứ tự: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:224
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "đệm thứ tự: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:232 plugins/sudoers/sudoreplay.c:287
+#: plugins/sudoers/visudo.c:182
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s phiên bản %s\n"
+
+#: plugins/sudoers/cvtsudoers.c:234 plugins/sudoers/visudo.c:184
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "Ngữ pháp %s phiên bản %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:251 plugins/sudoers/testsudoers.c:173
+#, c-format
+msgid "unsupported input format %s"
+msgstr "không hỗ trợ định dạng đầu vào %s"
+
+#: plugins/sudoers/cvtsudoers.c:266
+#, c-format
+msgid "unsupported output format %s"
+msgstr "không hỗ trợ định dạng đầu ra %s"
+
+#: plugins/sudoers/cvtsudoers.c:318
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s: các tập tin đầu vào và đầu ra phải khác nhau"
+
+#: plugins/sudoers/cvtsudoers.c:334 plugins/sudoers/sudoers.c:172
+#: plugins/sudoers/testsudoers.c:264 plugins/sudoers/visudo.c:238
+#: plugins/sudoers/visudo.c:594 plugins/sudoers/visudo.c:917
+msgid "unable to initialize sudoers default values"
+msgstr "không thể khởi giá trị mặc định sudoers"
+
+#: plugins/sudoers/cvtsudoers.c:420 plugins/sudoers/ldap_conf.c:433
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:479
+#, c-format
+msgid "%s: unknown key word: %s"
+msgstr "%s: không biết từ khóa: %s"
+
+#: plugins/sudoers/cvtsudoers.c:525
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "kiểu mặc định không hợp lệ: %s"
+
+#: plugins/sudoers/cvtsudoers.c:548
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "kiểu biểu thức không hợp lệ: %s"
+
+#: plugins/sudoers/cvtsudoers.c:588 plugins/sudoers/cvtsudoers.c:602
+#, c-format
+msgid "invalid filter: %s"
+msgstr "bộ lọc không hợp lệ: %s"
+
+#: plugins/sudoers/cvtsudoers.c:621 plugins/sudoers/cvtsudoers.c:638
+#: plugins/sudoers/cvtsudoers.c:1244 plugins/sudoers/cvtsudoers_json.c:1128
+#: plugins/sudoers/cvtsudoers_ldif.c:641 plugins/sudoers/iolog.c:411
+#: plugins/sudoers/iolog_util.c:72 plugins/sudoers/sudoers.c:903
+#: plugins/sudoers/sudoreplay.c:333 plugins/sudoers/sudoreplay.c:1425
+#: plugins/sudoers/timestamp.c:446 plugins/sudoers/tsdump.c:133
+#: plugins/sudoers/visudo.c:913
+#, c-format
+msgid "unable to open %s"
+msgstr "không thể mở “%s”"
+
+#: plugins/sudoers/cvtsudoers.c:641 plugins/sudoers/visudo.c:922
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "gặp lỗi khi phân tích tập tin %s, không rõ bị lỗi gì"
+
+#: plugins/sudoers/cvtsudoers.c:649 plugins/sudoers/visudo.c:939
+#, c-format
+msgid "parse error in %s near line %d\n"
+msgstr "lỗi cú pháp trong %s gần dòng %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:652 plugins/sudoers/visudo.c:942
+#, c-format
+msgid "parse error in %s\n"
+msgstr "lỗi cú pháp trong %s\n"
+
+#: plugins/sudoers/cvtsudoers.c:1291 plugins/sudoers/iolog.c:498
+#: plugins/sudoers/sudoreplay.c:1129 plugins/sudoers/timestamp.c:330
+#: plugins/sudoers/timestamp.c:333
+#, c-format
+msgid "unable to write to %s"
+msgstr "không thể ghi vào %s"
+
+#: plugins/sudoers/cvtsudoers.c:1314
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr "%s - chuyển đổi giữa các định dạng các tập tin sudoers\n"
+
+#: plugins/sudoers/cvtsudoers.c:1316
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Options:\n"
+" -b, --base=dn DN cơ sở cho sudo truy vấn LDAP\n"
+" -d, --defaults=deftypes chỉ chuyển đổi mặc định của kiểu đã cho\n"
+" -e, --expand-aliases khai triển bí danh khi chuyển đổi\n"
+" -f, --output-format=format đặt định dạng đầu ra: JSON, LDIF hay sudoers\n"
+" -i, --input-format=format đặt định dạng đầu vào: LDIF hoặc sudoers\n"
+" -I, --increment=số tổng gia tăng cho từng sudoOrder\n"
+" -h, --help hiển thị trợ giúp rồi thoát\n"
+" -m, --match=filter chỉ chuyển đổi những hạng mục khớp bộ lọc\n"
+" -M, --match-local khớp lọc sử dụng cơ sở dữ liệu passwd và group người dùng\n"
+" -o, --output=tập_tin_đầu_ra ghi sudoers đã chuyển đổi sang tập_tin_đầu_ra\n"
+" -O, --order-start=số điểm đầu cho sudoOrder đầu tiên\n"
+" -p, --prune-matches cắt bỏ những người dùng, nhóm và máy không khớp mẫu\n"
+" -P, --padding=số đệm cơ sở cho gia tăng sudoOrder\n"
+" -s, --suppress=sections chặn xuất cho từng phần cụ thể\n"
+" -V, --version hiển thị phiên bản rồi thoát"
+
+#: plugins/sudoers/cvtsudoers_json.c:682 plugins/sudoers/cvtsudoers_json.c:718
+#: plugins/sudoers/cvtsudoers_json.c:936
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "không hiểu mục tin mặc định “%s”"
+
+#: plugins/sudoers/cvtsudoers_json.c:856 plugins/sudoers/cvtsudoers_json.c:871
+#: plugins/sudoers/cvtsudoers_ldif.c:306 plugins/sudoers/cvtsudoers_ldif.c:317
+#: plugins/sudoers/ldap.c:480
+msgid "unable to get GMT time"
+msgstr "không thể lấy giờ quốc tế (GMT)"
+
+#: plugins/sudoers/cvtsudoers_json.c:859 plugins/sudoers/cvtsudoers_json.c:874
+#: plugins/sudoers/cvtsudoers_ldif.c:309 plugins/sudoers/cvtsudoers_ldif.c:320
+#: plugins/sudoers/ldap.c:486
+msgid "unable to format timestamp"
+msgstr "không thể định dạng dấu-vết-thời-gian"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:524 plugins/sudoers/env.c:309
+#: plugins/sudoers/env.c:316 plugins/sudoers/env.c:421
+#: plugins/sudoers/ldap.c:494 plugins/sudoers/ldap.c:725
+#: plugins/sudoers/ldap.c:1052 plugins/sudoers/ldap_conf.c:225
+#: plugins/sudoers/ldap_conf.c:315 plugins/sudoers/linux_audit.c:87
+#: plugins/sudoers/logging.c:1015 plugins/sudoers/policy.c:623
+#: plugins/sudoers/policy.c:633 plugins/sudoers/prompt.c:166
+#: plugins/sudoers/sudoers.c:845 plugins/sudoers/testsudoers.c:255
+#: plugins/sudoers/toke_util.c:159
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "lỗi nội bộ, %s bị tràn"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:593
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "Quá nhiều mục tin sudoers, tối đa là %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:636
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "biến môi trường SUDOERS_BASE chưa được đặt và tùy chọn chưa được đưa ra."
+
+#: plugins/sudoers/def_data.c:42
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "Trang bị Syslog nếu syslog được sử dụng cho việc ghi nhật ký: %s"
+
+#: plugins/sudoers/def_data.c:46
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "Mức ưu tiên Syslog sẽ sử dụng khi người dùng đăng nhập thành công: %s"
+
+#: plugins/sudoers/def_data.c:50
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "Mức ưu tiên Syslog sẽ sử dụng khi người dùng đăng nhập không thành công: %s"
+
+#: plugins/sudoers/def_data.c:54
+msgid "Put OTP prompt on its own line"
+msgstr "Đặt nhắc OTP (mật khẩu dùng một lần) tại dòng nó sở hữu"
+
+#: plugins/sudoers/def_data.c:58
+msgid "Ignore '.' in $PATH"
+msgstr "Bỏ qua “.” trong biến $PATH"
+
+#: plugins/sudoers/def_data.c:62
+msgid "Always send mail when sudo is run"
+msgstr "Luôn gửi thư mỗi khi chạy lệnh sudo"
+
+#: plugins/sudoers/def_data.c:66
+msgid "Send mail if user authentication fails"
+msgstr "Gửi thư nếu xác thực người dùng gặp lỗi"
+
+#: plugins/sudoers/def_data.c:70
+msgid "Send mail if the user is not in sudoers"
+msgstr "Gửi thư nếu người dùng không ở trong sudoers"
+
+#: plugins/sudoers/def_data.c:74
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "Gửi thư nếu người dùng không có trong sudoers cho máy chủ này"
+
+#: plugins/sudoers/def_data.c:78
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "Gửi thư nếu người dùng không được phép chạy lệnh nào đó"
+
+#: plugins/sudoers/def_data.c:82
+msgid "Send mail if the user tries to run a command"
+msgstr "Gửi thư nếu người cố chạy lệnh nào đó"
+
+#: plugins/sudoers/def_data.c:86
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "Sử dụng dấu vết thời gian riêng rẽ cho từng cặp tkhoản/tty"
+
+#: plugins/sudoers/def_data.c:90
+msgid "Lecture user the first time they run sudo"
+msgstr "Hướng dẫn người dùng lần đầu tiên họ chạy lệnh sudo"
+
+#: plugins/sudoers/def_data.c:94
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "TẬP-TIN chứa thuyết trình về “sudo”: %s"
+
+#: plugins/sudoers/def_data.c:98
+msgid "Require users to authenticate by default"
+msgstr "Yêu cầu người dùng chứng thực theo mặc định"
+
+#: plugins/sudoers/def_data.c:102
+msgid "Root may run sudo"
+msgstr "Siêu người dùng (root) có thể chạy lệnh sudo"
+
+#: plugins/sudoers/def_data.c:106
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "Ghi nhật ký tên-máy-chủ vào tập tin nhật ký (không dùng syslog)"
+
+#: plugins/sudoers/def_data.c:110
+msgid "Log the year in the (non-syslog) log file"
+msgstr "Ghi nhật ký năm vào tập tin nhật ký (không dùng syslog)"
+
+#: plugins/sudoers/def_data.c:114
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "Nếu lệnh sudo được triệu gọi mà không đưa ra tham số thì khởi chạy hệ vỏ"
+
+#: plugins/sudoers/def_data.c:118
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "Đặt biến $HOME cho người dùng đích khi sử dụng hệ vỏ (shell) với tùy chọn -s"
+
+#: plugins/sudoers/def_data.c:122
+msgid "Always set $HOME to the target user's home directory"
+msgstr "Luôn đặt biến $HOME cho thư mục cá nhân của người dùng đích"
+
+#: plugins/sudoers/def_data.c:126
+msgid "Allow some information gathering to give useful error messages"
+msgstr "Cho phép một số thông tin được thu thập để đưa ra các thông tin về lỗi hữu dụng"
+
+#: plugins/sudoers/def_data.c:130
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "Yêu cầu tên máy chủ dạng đầy đủ trong tập tin sudoers"
+
+#: plugins/sudoers/def_data.c:134
+msgid "Insult the user when they enter an incorrect password"
+msgstr "Lăng mạ người dùng khi họ nhập vào mật khẩu sai"
+
+#: plugins/sudoers/def_data.c:138
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "Chỉ cho phép người dùng chạy lệnh sudo nếu họ có tty"
+
+#: plugins/sudoers/def_data.c:142
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo sẽ tôn trọng biến môi trường EDITOR"
+
+#: plugins/sudoers/def_data.c:146
+msgid "Prompt for root's password, not the users's"
+msgstr "Hỏi mật khẩu của siêu người dùng, chứ không phải của người dùng"
+
+#: plugins/sudoers/def_data.c:150
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "Nhắc mật khẩu của người dùng runas_mặc_định, không phải của người dùng"
+
+#: plugins/sudoers/def_data.c:154
+msgid "Prompt for the target user's password, not the users's"
+msgstr "Nhắc mật khẩu của người dùng đích, không phải cái hiện tại"
+
+#: plugins/sudoers/def_data.c:158
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "Áp dụng mặc định trong lớp đăng nhập người dùng đích nếu ở đây có một"
+
+#: plugins/sudoers/def_data.c:162
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "Đặt biến môi trường LOGNAME và USER"
+
+#: plugins/sudoers/def_data.c:166
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "Chỉ đặt uid đang có hiệu lực cho người dùng đích, không sử dụng uid thật"
+
+#: plugins/sudoers/def_data.c:170
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "Không khởi tạo véc-tơ nhóm cho người dùng đích"
+
+#: plugins/sudoers/def_data.c:174
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "Độ dài mà tại đó các dòng trong tập tin nhật ký được ngắt dòng (0 là không ngắt dòng): %u"
+
+#: plugins/sudoers/def_data.c:178
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "Thời gian chờ dấu vết thời gian xác thực tối đa: %.1f phút"
+
+#: plugins/sudoers/def_data.c:182
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "Thời gian chờ nhắc mật khẩu tối đa: %.1f phút"
+
+#: plugins/sudoers/def_data.c:186
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "Số lần nhập mật khẩu: %u"
+
+#: plugins/sudoers/def_data.c:190
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "Umask để sử dụng hoặc 0777 để sử dụng của người dùng: 0%o"
+
+#: plugins/sudoers/def_data.c:194
+#, c-format
+msgid "Path to log file: %s"
+msgstr "Đường dẫn tới tập tin nhật ký: “%s”"
+
+#: plugins/sudoers/def_data.c:198
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "Đường dẫn tới chương trình gửi thư (mail) %s"
+
+#: plugins/sudoers/def_data.c:202
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "Các cờ dành cho chương trình gửi thư (mail): %s"
+
+#: plugins/sudoers/def_data.c:206
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "Địa chỉ để gửi thư đến: %s"
+
+#: plugins/sudoers/def_data.c:210
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "Địa chỉ dùng để gửi thư từ: %s"
+
+#: plugins/sudoers/def_data.c:214
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "Chủ đề cho thư: %s"
+
+#: plugins/sudoers/def_data.c:218
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "Mật khẩu không đúng: %s"
+
+#: plugins/sudoers/def_data.c:222
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "Đường dẫn đến thư mục trạng thái thuyết trình: %s"
+
+#: plugins/sudoers/def_data.c:226
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "Đường dẫn thư mục dấu vết thời gian xác thực: %s"
+
+#: plugins/sudoers/def_data.c:230
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "Chủ sở hữu đường dẫn thư mục dấu vết thời gian xác thực: %s"
+
+#: plugins/sudoers/def_data.c:234
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "Những tài khoản trong nhóm này được miễn mật khẩu và yêu cầu PATH: %s"
+
+#: plugins/sudoers/def_data.c:238
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "Lời nhắc nhập mật khẩu mặc định: %s"
+
+#: plugins/sudoers/def_data.c:242
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "Nếu được đặt, lời nhắc mật khẩu sẽ đè lên dấu nhắc hệ thống trong mọi trường hợp."
+
+#: plugins/sudoers/def_data.c:246
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "Tài khoản mặc định chạy lệnh như là: %s"
+
+#: plugins/sudoers/def_data.c:250
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "Giá trị dùng để ghi đè lên $PATH của người dùng: %s"
+
+#: plugins/sudoers/def_data.c:254
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "Đường dẫn tới trình biên soạn để sử dụng cho lệnh visudo: %s"
+
+#: plugins/sudoers/def_data.c:258
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "Khi được yêu cầu mật khẩu cho “liệt kê” lệnh-giả: %s"
+
+#: plugins/sudoers/def_data.c:262
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "Khi được yêu cầu mật khẩu cho lệnh-giả “verify” (“thẩm tra”): %s"
+
+#: plugins/sudoers/def_data.c:266
+msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+msgstr "Tải trước các hàm thi hành giả được chứa trong thư viện sudo_noexec"
+
+#: plugins/sudoers/def_data.c:270
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "Nếu thư mục LDAP đã bật, chúng tôi sẽ lờ đi tập tin sudoers phải không"
+
+#: plugins/sudoers/def_data.c:274
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr "Các bộ mô tả tập tin >= %d sẽ bị đóng trước khi chạy một lệnh"
+
+#: plugins/sudoers/def_data.c:278
+msgid "If set, users may override the value of `closefrom' with the -C option"
+msgstr "Nếu được đặt, người dùng có thể ghi đè lên giá trị của “closefrom” bằng tùy chọn -C"
+
+#: plugins/sudoers/def_data.c:282
+msgid "Allow users to set arbitrary environment variables"
+msgstr "Cho phép người dùng đặt biến môi trường tùy ý"
+
+#: plugins/sudoers/def_data.c:286
+msgid "Reset the environment to a default set of variables"
+msgstr "Đặt lại biến môi trường thành giá trị mặc định của chúng"
+
+#: plugins/sudoers/def_data.c:290
+msgid "Environment variables to check for sanity:"
+msgstr "Các biến môi trường được kiểm tra xem có đúng mực không:"
+
+#: plugins/sudoers/def_data.c:294
+msgid "Environment variables to remove:"
+msgstr "Các biến môi trường bị gỡ bỏ:"
+
+#: plugins/sudoers/def_data.c:298
+msgid "Environment variables to preserve:"
+msgstr "Các biến môi trường được giữ lại:"
+
+#: plugins/sudoers/def_data.c:302
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "Vai trò SELinux được dùng trong ngữ cảnh an ninh mới: %s"
+
+#: plugins/sudoers/def_data.c:306
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "Kiểu SELinux được dùng trong ngữ cảnh an ninh mới: %s"
+
+#: plugins/sudoers/def_data.c:310
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "Đường dẫn tới tập tin môi trường đặc-tả-sudo: %s"
+
+#: plugins/sudoers/def_data.c:314
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "Đường dẫn tới tập tin môi trường đặc-tả-sudo-hạn-chế: %s"
+
+#: plugins/sudoers/def_data.c:318
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "Miền địa phương sẽ sử dụng khi phân tích sudoers: %s"
+
+#: plugins/sudoers/def_data.c:322
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "Cho phép sudo hỏi mật khẩu thậm chí ngay cả khi nó đã rõ ràng"
+
+#: plugins/sudoers/def_data.c:326
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "Cung cấp phản hồi ảo lúc nhắc mật khẩu khi đây là đầu nhập người dùng"
+
+#: plugins/sudoers/def_data.c:330
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "Sử dụng globbing kiểu nhanh hơn mà nó thì kém chính xác hơn nhưng lại không cần truy cập hệ thống tập tin"
+
+#: plugins/sudoers/def_data.c:334
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "Giá trị umask được chỉ định trong sudoers sẽ ghi đè lên giá trị này của người dùng, thậm chí nó còn dễ dãi hơn"
+
+#: plugins/sudoers/def_data.c:338
+msgid "Log user's input for the command being run"
+msgstr "Ghi nhật ký kết xuất từ người dùng cho lệnh đang chạy"
+
+#: plugins/sudoers/def_data.c:342
+msgid "Log the output of the command being run"
+msgstr "Ghi lại nhật ký kết xuất của lệnh đang chạy"
+
+#: plugins/sudoers/def_data.c:346
+msgid "Compress I/O logs using zlib"
+msgstr "Nén nhật ký V/R sử dụng định dạng zlib"
+
+#: plugins/sudoers/def_data.c:350
+msgid "Always run commands in a pseudo-tty"
+msgstr "Luôn chạy lệnh ở tty-giả"
+
+#: plugins/sudoers/def_data.c:354
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "Phần bổ sung cho hỗ trợ nhóm không-Unix: %s"
+
+#: plugins/sudoers/def_data.c:358
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "Thư mục mà nó sẽ lưu nhật ký vào/ra: %s"
+
+#: plugins/sudoers/def_data.c:362
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "Tập tin mà nó sẽ lưu nhật ký vào/ra: %s"
+
+#: plugins/sudoers/def_data.c:366
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "Thêm một mục vào tập tin utmp/utmpx khi phân bổ một pty"
+
+#: plugins/sudoers/def_data.c:370
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "Đặt người dùng trong utmp thành người dùng runasr, không phải người dùng gọi"
+
+#: plugins/sudoers/def_data.c:374
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "Tập hợp các đặc quyền được phép: %s"
+
+#: plugins/sudoers/def_data.c:378
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "Tập hợp các quyền bị giới hạn: %s"
+
+#: plugins/sudoers/def_data.c:382
+msgid "Run commands on a pty in the background"
+msgstr "Chạy các câu lệnh trên một pty trong nền hệ thống"
+
+#: plugins/sudoers/def_data.c:386
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "Tên dịch vụ PAM được dùng: %s"
+
+#: plugins/sudoers/def_data.c:390
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "Tên dịch vụ PAM được dùng cho các hệ vỏ đăng nhập: %s"
+
+#: plugins/sudoers/def_data.c:394
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "Thử thiết lập ủy nhiệm PAM cho người dùng đích"
+
+#: plugins/sudoers/def_data.c:398
+msgid "Create a new PAM session for the command to run in"
+msgstr "Tạo một phiên PAM mới để lệnh chạy với nó"
+
+#: plugins/sudoers/def_data.c:402
+#, c-format
+msgid "Maximum I/O log sequence number: %u"
+msgstr "Số lượng nhật ký I/O tối đa: %u"
+
+#: plugins/sudoers/def_data.c:406
+msgid "Enable sudoers netgroup support"
+msgstr "Bật hỗ trợ nhóm-mạng “sudoers”"
+
+#: plugins/sudoers/def_data.c:410
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "Kiểm tra xem các thư mục cha có ghi được hay không khi sửa các tập tin bằng sudoedit"
+
+#: plugins/sudoers/def_data.c:414
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "Theo các liên kết mềm khi sửa các tập tin bằng sudoedit"
+
+#: plugins/sudoers/def_data.c:418
+msgid "Query the group plugin for unknown system groups"
+msgstr "Truy vấn các phần bổ sung nhóm cho các nhóm hệ thống chưa biết"
+
+#: plugins/sudoers/def_data.c:422
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "Khớp nhóm mạng trên cơ sở toàn thể bộ dữ liệu : tài khoản, tên máy và tên miền"
+
+#: plugins/sudoers/def_data.c:426
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "Cho phép các lệnh có thể chạy ngay cả khi sudo không thể ghi vào nhật ký audit"
+
+#: plugins/sudoers/def_data.c:430
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "Cho phép các lệnh có thể chạy ngay cả khi sudo không thể ghi vào nhật ký V/R"
+
+#: plugins/sudoers/def_data.c:434
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "Cho phép các lệnh có thể chạy ngay cả khi sudo không thể ghi vào tập tin nhật ký"
+
+#: plugins/sudoers/def_data.c:438
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "Phân giải các nhóm trong sudoers và khớp dựa trên mã số nhóm, không phải là tên"
+
+#: plugins/sudoers/def_data.c:442
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "Các mục tin của nhật ký lớn hơn giá trị này sẽ được chia thành nhiều chuỗi syslog nhỏ: %u"
+
+#: plugins/sudoers/def_data.c:446
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "Người mà sẽ sở hữu tập tin nhật ký V/R: %s"
+
+#: plugins/sudoers/def_data.c:450
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "Nhóm mà sẽ sở hữu tập tin nhật ký V/R: %s"
+
+#: plugins/sudoers/def_data.c:454
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "Chế độ tập tin được dùng cho tập tin nhật ký V/R: 0%o"
+
+#: plugins/sudoers/def_data.c:458
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "Thực thi các lệnh theo bộ mô tả tập tin thay cho đường dẫn: %s"
+
+#: plugins/sudoers/def_data.c:462
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "Bỏ qua các mục tin Mặc định chưa biết trong sudoers thay vì đưa ra cảnh báo"
+
+#: plugins/sudoers/def_data.c:466
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "Thời gian theo giây sau đó thì lệnh sẽ bị chấm dứt: %u"
+
+#: plugins/sudoers/def_data.c:470
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "Cho phép người dùng chỉ định thời gian chờ dòng lệnh tối đa"
+
+#: plugins/sudoers/def_data.c:474
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "Đẩy dữ liệu nhật ký V/R lên đĩa ngay lập tức thay vì nhớ đệm nó"
+
+#: plugins/sudoers/def_data.c:478
+msgid "Include the process ID when logging via syslog"
+msgstr "Bao gồm mã số tiến trình khi ghi nhật ký thông qua syslog"
+
+#: plugins/sudoers/def_data.c:482
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "Kiểu của bản ghi dấu vết thời gian xác thực: %s"
+
+#: plugins/sudoers/def_data.c:486
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "Thông tin xác thực gặp lỗi nghiêm trọng: %s"
+
+#: plugins/sudoers/def_data.c:490
+msgid "Ignore case when matching user names"
+msgstr "Bỏ qua HOA/thường khi khớp tên người dùng"
+
+#: plugins/sudoers/def_data.c:494
+msgid "Ignore case when matching group names"
+msgstr "Bỏ qua HOA/thường khi khớp tên nhóm"
+
+#: plugins/sudoers/defaults.c:229
+#, c-format
+msgid "%s:%d unknown defaults entry \"%s\""
+msgstr "%s:%d không hiểu mục tin mặc định “%s”"
+
+#: plugins/sudoers/defaults.c:232
+#, c-format
+msgid "%s: unknown defaults entry \"%s\""
+msgstr "%s: không hiểu mục tin mặc định “%s”"
+
+#: plugins/sudoers/defaults.c:275
+#, c-format
+msgid "%s:%d no value specified for \"%s\""
+msgstr "%s:%d chưa chỉ ra giá trị cho “%s”"
+
+#: plugins/sudoers/defaults.c:278
+#, c-format
+msgid "%s: no value specified for \"%s\""
+msgstr "%s: chưa chỉ ra giá trị cho “%s”"
+
+#: plugins/sudoers/defaults.c:298
+#, c-format
+msgid "%s:%d values for \"%s\" must start with a '/'"
+msgstr "%s:%d giá trị cho “%s” phải bắt đầu bằng dấu “/”"
+
+#: plugins/sudoers/defaults.c:301
+#, c-format
+msgid "%s: values for \"%s\" must start with a '/'"
+msgstr "%s: giá trị cho “%s” phải bắt đầu bằng dấu “/”"
+
+#: plugins/sudoers/defaults.c:323
+#, c-format
+msgid "%s:%d option \"%s\" does not take a value"
+msgstr "%s:%d tùy chọn “%s” không nhận giá trị"
+
+#: plugins/sudoers/defaults.c:326
+#, c-format
+msgid "%s: option \"%s\" does not take a value"
+msgstr "%s: tùy chọn “%s” không nhận giá trị"
+
+#: plugins/sudoers/defaults.c:351
+#, c-format
+msgid "%s:%d invalid Defaults type 0x%x for option \"%s\""
+msgstr "%s:%d kiểu Defaults không hợp lệ 0x%x cho tùy chọn “%s”"
+
+#: plugins/sudoers/defaults.c:354
+#, c-format
+msgid "%s: invalid Defaults type 0x%x for option \"%s\""
+msgstr "%s: kiểu Defaults không hợp lệ 0x%x cho tùy chọn “%s”"
+
+#: plugins/sudoers/defaults.c:364
+#, c-format
+msgid "%s:%d value \"%s\" is invalid for option \"%s\""
+msgstr "%s:%d giá trị “%s” là không hợp lệ đối với tùy chọn “%s”"
+
+#: plugins/sudoers/defaults.c:367
+#, c-format
+msgid "%s: value \"%s\" is invalid for option \"%s\""
+msgstr "%s: giá trị “%s” là không hợp lệ đối với tùy chọn “%s”"
+
+#: plugins/sudoers/env.c:390
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv: envp sai hỏng, chiều dài không khớp"
+
+#: plugins/sudoers/env.c:1111
+msgid "unable to rebuild the environment"
+msgstr "không thể xây dựng lại môi trường"
+
+#: plugins/sudoers/env.c:1185
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "rất tiếc, bạn không được phép đặt các biến môi trường sau đây: %1s"
+
+#: plugins/sudoers/file.c:114
+#, c-format
+msgid "parse error in %s near line %d"
+msgstr "lỗi phân tích trong %s gần dòng %d"
+
+#: plugins/sudoers/file.c:117
+#, c-format
+msgid "parse error in %s"
+msgstr "gặp lỗi phân tích trong %s"
+
+#: plugins/sudoers/filedigest.c:59
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr "không hỗ trợ kiểu tóm lược %d dành cho %s"
+
+#: plugins/sudoers/filedigest.c:88
+#, c-format
+msgid "%s: read error"
+msgstr "%s: lỗi đọc"
+
+#: plugins/sudoers/group_plugin.c:88
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s phải được sở hữu bởi uid %d"
+
+#: plugins/sudoers/group_plugin.c:92
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr "%s phải là những thứ chỉ có thể ghi bởi chủ sở hữu"
+
+#: plugins/sudoers/group_plugin.c:100 plugins/sudoers/sssd.c:561
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "không thể tải %s: %s"
+
+#: plugins/sudoers/group_plugin.c:106
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "không tìm thấy ký hiệu “group_plugin” trong %s"
+
+#: plugins/sudoers/group_plugin.c:111
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s: phiên bản số lớn phần bổ sung nhóm không tương thích %d, mong đợi %d"
+
+#: plugins/sudoers/interfaces.c:84 plugins/sudoers/interfaces.c:101
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "không thể phân tích địa chỉ IP \"%s\""
+
+#: plugins/sudoers/interfaces.c:89 plugins/sudoers/interfaces.c:106
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "không thể phân tích mặt nạ mạng \"%s\""
+
+#: plugins/sudoers/interfaces.c:134
+msgid "Local IP address and netmask pairs:\n"
+msgstr "Cặp địa chỉ IP và mặt nạ cục bộ:\n"
+
+#: plugins/sudoers/iolog.c:115 plugins/sudoers/mkdir_parents.c:80
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s có tồn tại nhưng nó không phải là một thư mục (0%o)"
+
+#: plugins/sudoers/iolog.c:140 plugins/sudoers/iolog.c:180
+#: plugins/sudoers/mkdir_parents.c:69 plugins/sudoers/timestamp.c:210
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "không thể tạo thư mục “%s”"
+
+#: plugins/sudoers/iolog.c:184 plugins/sudoers/visudo.c:723
+#: plugins/sudoers/visudo.c:734
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "không thể chuyển đổi chế độ của %s thành 0%o"
+
+#: plugins/sudoers/iolog.c:292 plugins/sudoers/sudoers.c:1167
+#: plugins/sudoers/testsudoers.c:422
+#, c-format
+msgid "unknown group: %s"
+msgstr "không nhận ra nhóm: %s"
+
+#: plugins/sudoers/iolog.c:462 plugins/sudoers/sudoers.c:907
+#: plugins/sudoers/sudoreplay.c:840 plugins/sudoers/sudoreplay.c:1536
+#: plugins/sudoers/tsdump.c:143
+#, c-format
+msgid "unable to read %s"
+msgstr "không thể đọc %s"
+
+#: plugins/sudoers/iolog.c:577 plugins/sudoers/iolog.c:797
+#, c-format
+msgid "unable to create %s"
+msgstr "không thể tạo “%s”"
+
+#: plugins/sudoers/iolog.c:820 plugins/sudoers/iolog.c:1035
+#: plugins/sudoers/iolog.c:1111 plugins/sudoers/iolog.c:1205
+#: plugins/sudoers/iolog.c:1265
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "không thể ghi vào tập tin nhật ký V/R: %s"
+
+#: plugins/sudoers/iolog.c:1069
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s: lỗi bên trong, tập tin nhật ký vào ra cho sự kiện %d chưa được mở"
+
+#: plugins/sudoers/iolog.c:1228
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s: lỗi bên trong, tín hiệu %d không hợp lệ"
+
+#: plugins/sudoers/iolog_util.c:87
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s: tập tin nhật ký không hợp lệ"
+
+#: plugins/sudoers/iolog_util.c:105
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s: thiếu trường dấu vết thời gian"
+
+#: plugins/sudoers/iolog_util.c:111
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s: dấu vết thời gian “%s”: %s"
+
+#: plugins/sudoers/iolog_util.c:118
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s: thiếu trường tài khoản người dùng"
+
+#: plugins/sudoers/iolog_util.c:127
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s: thiếu trường “runas user” (chạy với tư cách tài khoản này)"
+
+#: plugins/sudoers/iolog_util.c:136
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s: thiếu trường “runas group” (chạy dưới danh nghĩa nhóm này)"
+
+#: plugins/sudoers/ldap.c:176 plugins/sudoers/ldap_conf.c:294
+msgid "starttls not supported when using ldaps"
+msgstr "“starttls” chỉ được hỗ trợ khi dùng với “ldaps”"
+
+#: plugins/sudoers/ldap.c:247
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "không thể khởi tạo chứng nhận SSL và csdl khóa: %s"
+
+#: plugins/sudoers/ldap.c:250
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "bạn phải đặt TLS_CERT trong %s để sử dụng SSL"
+
+#: plugins/sudoers/ldap.c:1612
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "không thể khởi tạo LDAP: %s"
+
+#: plugins/sudoers/ldap.c:1648
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "start_tls được chỉ ra nhưng thư viện LDAP không hỗ trợ ldap_start_tls_s() hoặc ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:1785 plugins/sudoers/parse_ldif.c:735
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "thuộc tính sudoOrder không hợp lệ: %s"
+
+#: plugins/sudoers/ldap_conf.c:203
+msgid "sudo_ldap_conf_add_ports: port too large"
+msgstr "sudo_ldap_conf_add_ports: cổng quá lớn"
+
+#: plugins/sudoers/ldap_conf.c:263
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "không hỗ trợ kiểu “LDAP uri”: %s"
+
+#: plugins/sudoers/ldap_conf.c:290
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "không thể trộn ldap và ldaps URIs"
+
+#: plugins/sudoers/ldap_util.c:454 plugins/sudoers/ldap_util.c:456
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "không thể chuyển đổi sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:57
+msgid "unable to open audit system"
+msgstr "không thể mở hệ thống audit"
+
+#: plugins/sudoers/linux_audit.c:98
+msgid "unable to send audit message"
+msgstr "không thể gửi thông tin audit"
+
+#: plugins/sudoers/logging.c:113
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: plugins/sudoers/logging.c:141
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (lệnh tiếp tục) %s"
+
+#: plugins/sudoers/logging.c:170
+#, c-format
+msgid "unable to open log file: %s"
+msgstr "không thể mở tập tin nhật ký: %s"
+
+#: plugins/sudoers/logging.c:178
+#, c-format
+msgid "unable to lock log file: %s"
+msgstr "không thể khóa tập tin nhật ký: %s"
+
+#: plugins/sudoers/logging.c:211
+#, c-format
+msgid "unable to write log file: %s"
+msgstr "không thể ghi vào tập tin nhật ký: %s"
+
+#: plugins/sudoers/logging.c:240
+msgid "No user or host"
+msgstr "Không có tài khoản hay tên máy chủ"
+
+#: plugins/sudoers/logging.c:242
+msgid "validation failure"
+msgstr "việc phê chuẩn thất bại"
+
+#: plugins/sudoers/logging.c:249
+msgid "user NOT in sudoers"
+msgstr "tài khoản KHÔNG có trong sudoers"
+
+#: plugins/sudoers/logging.c:251
+msgid "user NOT authorized on host"
+msgstr "tài khoản KHÔNG được cho phép sử dụng trên máy chủ"
+
+#: plugins/sudoers/logging.c:253
+msgid "command not allowed"
+msgstr "lệnh không được phép"
+
+#: plugins/sudoers/logging.c:288
+#, c-format
+msgid "%s is not in the sudoers file. This incident will be reported.\n"
+msgstr "%s không trong tập tin sudoers. Sự việc này sẽ được báo cáo.\n"
+
+#: plugins/sudoers/logging.c:291
+#, c-format
+msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+msgstr "%s không được phép chạy lệnh sudo trên %s. Sự việc này sẽ được báo cáo.\n"
+
+#: plugins/sudoers/logging.c:295
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "Rất tiếc, tài khoản %s không được chạy lệnh sudo trên %s.\n"
+
+#: plugins/sudoers/logging.c:298
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr "Rất tiếc, tài khoản %s không được phép thi hành “%s%s%s” như là %s%s%s trên %s.\n"
+
+#: plugins/sudoers/logging.c:335 plugins/sudoers/sudoers.c:438
+#: plugins/sudoers/sudoers.c:440 plugins/sudoers/sudoers.c:442
+#: plugins/sudoers/sudoers.c:444 plugins/sudoers/sudoers.c:599
+#: plugins/sudoers/sudoers.c:601
+#, c-format
+msgid "%s: command not found"
+msgstr "%s: không tìm thấy lệnh"
+
+#: plugins/sudoers/logging.c:337 plugins/sudoers/sudoers.c:434
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"đang bỏ qua “%s” được tìm thấy trong “.”\n"
+"Sử dụng “sudo ./%s” nếu đây là “%s” bạn muốn chạy."
+
+#: plugins/sudoers/logging.c:354
+msgid "authentication failure"
+msgstr "xác thực gặp lỗi nghiêm trọng"
+
+#: plugins/sudoers/logging.c:380
+msgid "a password is required"
+msgstr "bắt buộc phải có mật khẩu"
+
+#: plugins/sudoers/logging.c:443
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "đã sai mật khẩu %u lần"
+
+#: plugins/sudoers/logging.c:666
+msgid "unable to fork"
+msgstr "không thể tạo tiến trình con"
+
+#: plugins/sudoers/logging.c:674 plugins/sudoers/logging.c:726
+#, c-format
+msgid "unable to fork: %m"
+msgstr "không thể tạo tiến trình con: %m"
+
+#: plugins/sudoers/logging.c:716
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "không thể mở ống dẫn lệnh: %m"
+
+#: plugins/sudoers/logging.c:741
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "không thể dup (nhân đôi) stdin: %m"
+
+#: plugins/sudoers/logging.c:779
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "không thể thực thi %s: %m"
+
+#: plugins/sudoers/match.c:874
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "tóm lược cho %s (%s) không ở dạng thức %s"
+
+#: plugins/sudoers/mkdir_parents.c:75 plugins/sudoers/sudoers.c:918
+#: plugins/sudoers/visudo.c:421 plugins/sudoers/visudo.c:717
+#, c-format
+msgid "unable to stat %s"
+msgstr "không thể lấy thống kê %s"
+
+#: plugins/sudoers/parse.c:444
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+"\n"
+"Vai trò LDAP: %s\n"
+
+#: plugins/sudoers/parse.c:447
+#, c-format
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+"\n"
+"Mục Sudoers:\n"
+
+#: plugins/sudoers/parse.c:449
+#, c-format
+msgid " RunAsUsers: "
+msgstr " ChạyVớiTưCáchNgườiDùng: "
+
+#: plugins/sudoers/parse.c:464
+#, c-format
+msgid " RunAsGroups: "
+msgstr " ChạyVớiTưCáchNhóm: "
+
+#: plugins/sudoers/parse.c:474
+#, c-format
+msgid " Options: "
+msgstr " Tùy chọn: "
+
+#: plugins/sudoers/parse.c:528
+#, c-format
+msgid " Commands:\n"
+msgstr " Lệnh:\n"
+
+#: plugins/sudoers/parse.c:719
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "Các mục mặc định khớp cho %s trên máy %s:\n"
+
+#: plugins/sudoers/parse.c:737
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "Runas và Đặc-tả-lệnh mặc định cho %s:\n"
+
+#: plugins/sudoers/parse.c:755
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "Người dùng %s có thể chạy những lệnh sau trên máy %s:\n"
+
+#: plugins/sudoers/parse.c:770
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "Tài khoản %s không được phép thi hành sudo trên %s.\n"
+
+#: plugins/sudoers/parse_ldif.c:145
+#, c-format
+msgid "ignoring invalid attribute value: %s"
+msgstr "bỏ qua giá trị thuộc tính không hợp lệ: %s"
+
+#: plugins/sudoers/parse_ldif.c:584
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "bỏ qua sudoRole chưa hoàn thiện: cn: %s"
+
+#: plugins/sudoers/policy.c:88 plugins/sudoers/policy.c:114
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "%.*s không hợp lệ đặt bởi ứng dụng chạy phía trước sudo"
+
+#: plugins/sudoers/policy.c:293 plugins/sudoers/testsudoers.c:278
+msgid "unable to parse network address list"
+msgstr "không thể phân tích danh sách địa chỉ mạng"
+
+#: plugins/sudoers/policy.c:437
+msgid "user name not set by sudo front-end"
+msgstr "tên người dùng không đặt bởi ứng dụng chạy phía trước sudo"
+
+#: plugins/sudoers/policy.c:441
+msgid "user ID not set by sudo front-end"
+msgstr "mã số người dùng không đặt bởi ứng dụng chạy phía trước sudo"
+
+#: plugins/sudoers/policy.c:445
+msgid "group ID not set by sudo front-end"
+msgstr "mã số nhóm không đặt bởi ứng dụng chạy phía trước sudo"
+
+#: plugins/sudoers/policy.c:449
+msgid "host name not set by sudo front-end"
+msgstr "tên máy không đặt bởi ứng dụng chạy phía trước sudo"
+
+#: plugins/sudoers/policy.c:802 plugins/sudoers/visudo.c:220
+#: plugins/sudoers/visudo.c:851
+#, c-format
+msgid "unable to execute %s"
+msgstr "không thể thực thi %s"
+
+#: plugins/sudoers/policy.c:933
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Phiên bản của phần bổ sung chính sách Sudoers %s\n"
+
+#: plugins/sudoers/policy.c:935
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Phiên bản ngữ pháp tập tin Sudoers %d\n"
+
+#: plugins/sudoers/policy.c:939
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Đường dẫn Sudoers: %s\n"
+
+#: plugins/sudoers/policy.c:942
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "đường dẫn nsswitch: %s\n"
+
+#: plugins/sudoers/policy.c:944
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "đường dẫn ldap.conf: %s\n"
+
+#: plugins/sudoers/policy.c:945
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "đường dẫn ldap.secret: %s\n"
+
+#: plugins/sudoers/policy.c:978
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "không thể đăng ký móc kiểu %d (phiên bản %d.%d)"
+
+#: plugins/sudoers/pwutil.c:220 plugins/sudoers/pwutil.c:239
+#, c-format
+msgid "unable to cache uid %u, out of memory"
+msgstr "không thể lưu nhớ tạm uid %u, hết bộ nhớ rồi"
+
+#: plugins/sudoers/pwutil.c:233
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "không thể lưu nhớ tạm uid %u, đã có sẵn rồi"
+
+#: plugins/sudoers/pwutil.c:293 plugins/sudoers/pwutil.c:311
+#: plugins/sudoers/pwutil.c:373 plugins/sudoers/pwutil.c:418
+#, c-format
+msgid "unable to cache user %s, out of memory"
+msgstr "không thể lưu nhớ tạm tài khoản %s, hết bộ nhớ rồi"
+
+#: plugins/sudoers/pwutil.c:306
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "không thể lưu nhớ tạm tài khoản %s, đã có sẵn rồi"
+
+#: plugins/sudoers/pwutil.c:537 plugins/sudoers/pwutil.c:556
+#, c-format
+msgid "unable to cache gid %u, out of memory"
+msgstr "không thể lưu nhớ tạm gid %u, đã hết bộ nhớ rồi"
+
+#: plugins/sudoers/pwutil.c:550
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "không thể lưu nhớ tạm gid %u, đã có sẵn rồi"
+
+#: plugins/sudoers/pwutil.c:604 plugins/sudoers/pwutil.c:622
+#: plugins/sudoers/pwutil.c:669 plugins/sudoers/pwutil.c:711
+#, c-format
+msgid "unable to cache group %s, out of memory"
+msgstr "không thể lưu nhớ tạm nhóm %s, đã hết bộ nhớ rồi"
+
+#: plugins/sudoers/pwutil.c:617
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "không thể lưu nhớ tạm nhóm %s, đã có sẵn rồi"
+
+#: plugins/sudoers/pwutil.c:837 plugins/sudoers/pwutil.c:889
+#: plugins/sudoers/pwutil.c:940 plugins/sudoers/pwutil.c:993
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "không thể lưu nhớ tạm danh sách nhóm cho %s, đã có sẵn rồi"
+
+#: plugins/sudoers/pwutil.c:843 plugins/sudoers/pwutil.c:894
+#: plugins/sudoers/pwutil.c:946 plugins/sudoers/pwutil.c:998
+#, c-format
+msgid "unable to cache group list for %s, out of memory"
+msgstr "không thể lưu nhớ tạm danh sách nhóm cho %s, đã hết bộ nhớ rồi"
+
+#: plugins/sudoers/pwutil.c:883
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "không thể phân tích nhóm cho %s"
+
+#: plugins/sudoers/pwutil.c:987
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "không thể phân tích mã số nhóm cho %s"
+
+#: plugins/sudoers/set_perms.c:118 plugins/sudoers/set_perms.c:474
+#: plugins/sudoers/set_perms.c:917 plugins/sudoers/set_perms.c:1244
+#: plugins/sudoers/set_perms.c:1561
+msgid "perm stack overflow"
+msgstr "ngăn xếp perm bị tràn"
+
+#: plugins/sudoers/set_perms.c:126 plugins/sudoers/set_perms.c:405
+#: plugins/sudoers/set_perms.c:482 plugins/sudoers/set_perms.c:784
+#: plugins/sudoers/set_perms.c:925 plugins/sudoers/set_perms.c:1168
+#: plugins/sudoers/set_perms.c:1252 plugins/sudoers/set_perms.c:1494
+#: plugins/sudoers/set_perms.c:1569 plugins/sudoers/set_perms.c:1659
+msgid "perm stack underflow"
+msgstr "ngăn xếp stack tràn ngầm"
+
+#: plugins/sudoers/set_perms.c:185 plugins/sudoers/set_perms.c:528
+#: plugins/sudoers/set_perms.c:1303 plugins/sudoers/set_perms.c:1601
+msgid "unable to change to root gid"
+msgstr "không thể thay đổi mã số nhóm của siêu người dùng root"
+
+#: plugins/sudoers/set_perms.c:274 plugins/sudoers/set_perms.c:625
+#: plugins/sudoers/set_perms.c:1054 plugins/sudoers/set_perms.c:1380
+msgid "unable to change to runas gid"
+msgstr "không thể thay đổi thành runas gid"
+
+#: plugins/sudoers/set_perms.c:279 plugins/sudoers/set_perms.c:630
+#: plugins/sudoers/set_perms.c:1059 plugins/sudoers/set_perms.c:1385
+msgid "unable to set runas group vector"
+msgstr "không thể đặt véc-tơ nhóm runas"
+
+#: plugins/sudoers/set_perms.c:290 plugins/sudoers/set_perms.c:641
+#: plugins/sudoers/set_perms.c:1068 plugins/sudoers/set_perms.c:1394
+msgid "unable to change to runas uid"
+msgstr "không thể thay đổi thành runas uid"
+
+#: plugins/sudoers/set_perms.c:308 plugins/sudoers/set_perms.c:659
+#: plugins/sudoers/set_perms.c:1084 plugins/sudoers/set_perms.c:1410
+msgid "unable to change to sudoers gid"
+msgstr "không thể thay đổi thành mã số nhóm sudoers"
+
+#: plugins/sudoers/set_perms.c:392 plugins/sudoers/set_perms.c:771
+#: plugins/sudoers/set_perms.c:1155 plugins/sudoers/set_perms.c:1481
+#: plugins/sudoers/set_perms.c:1646
+msgid "too many processes"
+msgstr "quá nhiều tiến trình"
+
+#: plugins/sudoers/solaris_audit.c:56
+msgid "unable to get current working directory"
+msgstr "không thể lấy thư mục làm việc hiện tại"
+
+#: plugins/sudoers/solaris_audit.c:64
+#, c-format
+msgid "truncated audit path user_cmnd: %s"
+msgstr "đã cắt ngắn đường dẫn audit user_cmnd: %s"
+
+#: plugins/sudoers/solaris_audit.c:71
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "đã cắt ngắn đường dẫn audit argv[0]: %s"
+
+#: plugins/sudoers/solaris_audit.c:120
+msgid "audit_failure message too long"
+msgstr "thông điệp audit_failure quá dài"
+
+#: plugins/sudoers/sssd.c:563
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "không thể khởi tạo nguồn SSS. SSSD đã được cài đặt trên máy của bạn chưa vậy?"
+
+#: plugins/sudoers/sssd.c:571 plugins/sudoers/sssd.c:580
+#: plugins/sudoers/sssd.c:589 plugins/sudoers/sssd.c:598
+#: plugins/sudoers/sssd.c:607
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "không thể tìm thấy ký hiệu “%s” trong %s"
+
+#: plugins/sudoers/sudoers.c:208 plugins/sudoers/sudoers.c:864
+msgid "problem with defaults entries"
+msgstr "trục trặc với các mục mặc định"
+
+#: plugins/sudoers/sudoers.c:212
+msgid "no valid sudoers sources found, quitting"
+msgstr "không có người dùng hợp lệ nào được tìm thấy, đang thoát ra"
+
+#: plugins/sudoers/sudoers.c:250
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers đã ghi rõ là siêu người dùng (root) không được phép chạy sudo"
+
+#: plugins/sudoers/sudoers.c:308
+msgid "you are not permitted to use the -C option"
+msgstr "bạn không được phép sử dụng tùy chọn -C"
+
+#: plugins/sudoers/sudoers.c:355
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr "người sở hữu dấu vết thời gian (%s): Không có người dùng nào như vậy"
+
+#: plugins/sudoers/sudoers.c:370
+msgid "no tty"
+msgstr "không có tty"
+
+#: plugins/sudoers/sudoers.c:371
+msgid "sorry, you must have a tty to run sudo"
+msgstr "rất tiếc, bạn phải có tty mới có thể chạy sudo"
+
+#: plugins/sudoers/sudoers.c:433
+msgid "command in current directory"
+msgstr "lệnh trong thư mục hiện hành"
+
+#: plugins/sudoers/sudoers.c:452
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "rất tiếc, bạn không được phép đặt thời gian chờ lệnh tối đa"
+
+#: plugins/sudoers/sudoers.c:460
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "rất tiếc, bạn không được phép giữ lại môi trường"
+
+#: plugins/sudoers/sudoers.c:808
+msgid "command too long"
+msgstr "lệnh quá dài"
+
+#: plugins/sudoers/sudoers.c:922
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s không phải tập tin thường"
+
+#: plugins/sudoers/sudoers.c:926 plugins/sudoers/timestamp.c:257 toke.l:965
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s được sở hữu bởi người dùng mang mã số %u, nên là %u"
+
+#: plugins/sudoers/sudoers.c:930 toke.l:970
+#, c-format
+msgid "%s is world writable"
+msgstr "%s ai ghi cũng được"
+
+#: plugins/sudoers/sudoers.c:934 toke.l:973
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s được sở hữu bởi nhóm mang mã số %u, nên là %u"
+
+#: plugins/sudoers/sudoers.c:967
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "chỉ có siêu người dùng (root) mới có thể sử dụng “-c %s”"
+
+#: plugins/sudoers/sudoers.c:986
+#, c-format
+msgid "unknown login class: %s"
+msgstr "không rõ lớp đăng nhập: %s"
+
+#: plugins/sudoers/sudoers.c:1069 plugins/sudoers/sudoers.c:1083
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "không thể phân giải địa chỉ của máy %s"
+
+#: plugins/sudoers/sudoreplay.c:248
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "tùy chọn lọc không hợp lệ: %s"
+
+#: plugins/sudoers/sudoreplay.c:261
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "thời gian chờ tối đa không hợp lệ: %s"
+
+#: plugins/sudoers/sudoreplay.c:284
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "sai hệ số nhân tốc độ: %s"
+
+#: plugins/sudoers/sudoreplay.c:319
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s/timing: %s"
+msgstr "%s/%.2s/%.2s/%.2s/thời-gian: %s"
+
+#: plugins/sudoers/sudoreplay.c:325
+#, c-format
+msgid "%s/%s/timing: %s"
+msgstr "%s/%s/thời-gian: %s"
+
+#: plugins/sudoers/sudoreplay.c:341
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "Đang chạy lại phiên sudo: %s"
+
+#: plugins/sudoers/sudoreplay.c:539 plugins/sudoers/sudoreplay.c:586
+#: plugins/sudoers/sudoreplay.c:783 plugins/sudoers/sudoreplay.c:892
+#: plugins/sudoers/sudoreplay.c:977 plugins/sudoers/sudoreplay.c:992
+#: plugins/sudoers/sudoreplay.c:999 plugins/sudoers/sudoreplay.c:1006
+#: plugins/sudoers/sudoreplay.c:1013 plugins/sudoers/sudoreplay.c:1020
+#: plugins/sudoers/sudoreplay.c:1168
+msgid "unable to add event to queue"
+msgstr "không thể thêm sự kiện vào hàng đợi"
+
+#: plugins/sudoers/sudoreplay.c:654
+msgid "unable to set tty to raw mode"
+msgstr "không thể đặt thiết bị tty chế độ thô (raw)"
+
+#: plugins/sudoers/sudoreplay.c:705
+#, c-format
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr "Cảnh báo: thiết bị cuối quá nhỏ để có thể chạy nhật ký một cách đúng đắn.\n"
+
+#: plugins/sudoers/sudoreplay.c:706
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "Định dạng của nhật ký là %d x %d, định dạng của thiết bị cuối là %d x %d."
+
+#: plugins/sudoers/sudoreplay.c:734
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "Trình diễn lại đã kết thúc, vui lòng bấm một phím bất kỳ để hoàn lại thiết bị cuối."
+
+#: plugins/sudoers/sudoreplay.c:766
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "sai dòng ghi thời gian trong tập tin: %s"
+
+#: plugins/sudoers/sudoreplay.c:1202 plugins/sudoers/sudoreplay.c:1227
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "biểu thức không rõ ràng “%s”"
+
+#: plugins/sudoers/sudoreplay.c:1249
+msgid "unmatched ')' in expression"
+msgstr "thiếu “)” trong biểu thức"
+
+#: plugins/sudoers/sudoreplay.c:1253
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "không hiểu giới hạn tìm kiếm “%s”"
+
+#: plugins/sudoers/sudoreplay.c:1268
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s yêu cầu một đối số"
+
+#: plugins/sudoers/sudoreplay.c:1271 plugins/sudoers/sudoreplay.c:1512
+#, c-format
+msgid "invalid regular expression: %s"
+msgstr "biểu thức chính quy không hợp lệ: %s"
+
+#: plugins/sudoers/sudoreplay.c:1275
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "không thể phân tích ngày tháng “%s”"
+
+#: plugins/sudoers/sudoreplay.c:1284
+msgid "unmatched '(' in expression"
+msgstr "thiếu “(” trong biểu thức"
+
+#: plugins/sudoers/sudoreplay.c:1286
+msgid "illegal trailing \"or\""
+msgstr "thừa “or” ở cuối"
+
+#: plugins/sudoers/sudoreplay.c:1288
+msgid "illegal trailing \"!\""
+msgstr "thừa “!” ở cuối"
+
+#: plugins/sudoers/sudoreplay.c:1338
+#, c-format
+msgid "unknown search type %d"
+msgstr "không hiểu kiểu tìm kiếm “%d”"
+
+#: plugins/sudoers/sudoreplay.c:1605
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "cách dùng: %s [-hnRS] [-d thư-mục] [-m số] [-s số] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1608
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "cách dùng: %s [-h] [-d th.mục] -l [biểu thức tìm kiếm]\n"
+
+#: plugins/sudoers/sudoreplay.c:1617
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - chạy lại nhật ký phiên sudo\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1619
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"Tùy chọn:\n"
+" -d, --directory=th.mục chỉ định thư mục cho nhật ký phiên\n"
+" -f, --filter=bộ-lọc chỉ định kiểu V/R để hiển thị\n"
+" -h, --help hiển thị thông tin trợ giúp rồi thoát\n"
+" -l, --list liệt kê ID phiên sẵn có, với biểu thức tùy chọn\n"
+" -m, --max-wait=sô số giây tối đa sẽ chờ giữa hai sự kiện\n"
+" -S, --suspend-wait chờ trong khi lệnh bị treo\n"
+" -s, --speed=số tăng hoặc giảm tốc độ kết xuất\n"
+" -V, --version hiển thị thông tin về phiên bản rồi thoát"
+
+#: plugins/sudoers/testsudoers.c:360
+msgid "\thost unmatched"
+msgstr "\tmáy chủ không khớp"
+
+#: plugins/sudoers/testsudoers.c:363
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"Lệnh được phép"
+
+#: plugins/sudoers/testsudoers.c:364
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"Lệnh bị cấm"
+
+#: plugins/sudoers/testsudoers.c:364
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"Lệnh không khớp"
+
+#: plugins/sudoers/timestamp.c:265
+#, c-format
+msgid "%s is group writable"
+msgstr "%s là người cùng nhóm được ghi"
+
+#: plugins/sudoers/timestamp.c:341
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "không thể cắt ngắn tập tin dấu-vết-thời-gian thành %lld byte"
+
+#: plugins/sudoers/timestamp.c:827 plugins/sudoers/timestamp.c:919
+#: plugins/sudoers/visudo.c:482 plugins/sudoers/visudo.c:488
+msgid "unable to read the clock"
+msgstr "không thể đọc khóa"
+
+#: plugins/sudoers/timestamp.c:838
+msgid "ignoring time stamp from the future"
+msgstr "bỏ qua dấu vết thời gian nằm ở thì tương lai"
+
+#: plugins/sudoers/timestamp.c:861
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "dấu vết thời gian nằm ở thì tương lai: %20.20s"
+
+#: plugins/sudoers/timestamp.c:983
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "không thể khóa tập tin dấu-vết-thời-gian %s"
+
+#: plugins/sudoers/timestamp.c:1027 plugins/sudoers/timestamp.c:1047
+#, c-format
+msgid "lecture status path too long: %s/%s"
+msgstr "đường dẫn đến thư mục thuyết trình quá dài: %s/%s"
+
+#: plugins/sudoers/visudo.c:216
+msgid "the -x option will be removed in a future release"
+msgstr "tùy chọn -x sẽ bị xóa bỏ trong tương lai"
+
+#: plugins/sudoers/visudo.c:217
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "vui lòng cân nhắc sử dụng tiện ích cvtsudoers để thay thế"
+
+#: plugins/sudoers/visudo.c:268 plugins/sudoers/visudo.c:650
+#, c-format
+msgid "press return to edit %s: "
+msgstr "bấm phím <Enter> để trở về chỉnh sửa %s:"
+
+#: plugins/sudoers/visudo.c:329
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "trình biên soạn đã chỉ ra (%s) không tồn tại"
+
+#: plugins/sudoers/visudo.c:331
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "không tìm thấy trình biên soạn (đường dẫn của nó = %s)"
+
+#: plugins/sudoers/visudo.c:441 plugins/sudoers/visudo.c:449
+msgid "write error"
+msgstr "lỗi ghi"
+
+#: plugins/sudoers/visudo.c:495
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "không thể lấy thống kê tập tin tạm (%s), %s không thay đổi gì."
+
+#: plugins/sudoers/visudo.c:502
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "tập tin tạm (%s) có kích cỡ bằng không, %s không thay đổi gì"
+
+#: plugins/sudoers/visudo.c:508
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "trình biên soạn (%s) gặp lỗi, %s không thay đổi gì"
+
+#: plugins/sudoers/visudo.c:530
+#, c-format
+msgid "%s unchanged"
+msgstr "%s không thay đổi"
+
+#: plugins/sudoers/visudo.c:589
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "không thể mở lại tập tin tạm (%s), %s không thay đổi gì."
+
+#: plugins/sudoers/visudo.c:601
+#, c-format
+msgid "unabled to parse temporary file (%s), unknown error"
+msgstr "không thể phân tích tập tin tạm (%s), lỗi chưa được biết"
+
+#: plugins/sudoers/visudo.c:639
+#, c-format
+msgid "internal error, unable to find %s in list!"
+msgstr "lỗi hệ thống, không thể tìm thấy %s trong danh sách!"
+
+#: plugins/sudoers/visudo.c:719 plugins/sudoers/visudo.c:728
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "không thể đặt (uid, gid) của %s thành (%u, %u)"
+
+#: plugins/sudoers/visudo.c:751
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s và %s không ở trên cùng một hệ thống tập tin, sử dụng lệnh mv để đổi tên"
+
+#: plugins/sudoers/visudo.c:765
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "thực hiện lệnh gặp lỗi: “%s %s %s”, %s không thay đổi"
+
+#: plugins/sudoers/visudo.c:775
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "gặp lỗi khi đổi tên %s, %s không thay đổi"
+
+#: plugins/sudoers/visudo.c:796
+msgid "What now? "
+msgstr "Vậy làm gì bây giờ? "
+
+#: plugins/sudoers/visudo.c:810
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"Các tùy chọn là:\n"
+" (e) sửa lại tập tin sudoers\n"
+" (x) thoát ra mà không ghi lại tập tin sudoerse\n"
+" (q) thoát ra và ghi lại tập tin sudoers (NGUY HIỂM!)\n"
+
+#: plugins/sudoers/visudo.c:856
+#, c-format
+msgid "unable to run %s"
+msgstr "không thể chạy %s"
+
+#: plugins/sudoers/visudo.c:886
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s: sai sở hữu (uid, gid) đáng lẽ là (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:893
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s: phân quyền sai, phải ở chế độ 0%o\n"
+
+#: plugins/sudoers/visudo.c:950 plugins/sudoers/visudo.c:957
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s: vượt qua kiểm duyệt\n"
+
+#: plugins/sudoers/visudo.c:976
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s đang bận, hãy thử lại sau"
+
+#: plugins/sudoers/visudo.c:979
+#, c-format
+msgid "unable to lock %s"
+msgstr "không thể khóa %s"
+
+#: plugins/sudoers/visudo.c:980
+msgid "Edit anyway? [y/N]"
+msgstr "Vẫn sửa? (có/KHÔNG) [y/N]"
+
+#: plugins/sudoers/visudo.c:1064
+#, c-format
+msgid "Error: %s:%d cycle in %s \"%s\""
+msgstr "Lỗi: %s:%d bị quẩn tròn trong %s “%s”"
+
+#: plugins/sudoers/visudo.c:1065
+#, c-format
+msgid "Warning: %s:%d cycle in %s \"%s\""
+msgstr "Cảnh báo: %s:%d bị quẩn tròn trong %s “%s”"
+
+#: plugins/sudoers/visudo.c:1069
+#, c-format
+msgid "Error: %s:%d %s \"%s\" referenced but not defined"
+msgstr "Lỗi: %s:%d %s “%s” được tham chiếu nhưng chưa được định nghĩa"
+
+#: plugins/sudoers/visudo.c:1070
+#, c-format
+msgid "Warning: %s:%d %s \"%s\" referenced but not defined"
+msgstr "Cảnh báo: %s:%d %s “%s” được tham chiếu nhưng chưa được định nghĩa"
+
+#: plugins/sudoers/visudo.c:1161
+#, c-format
+msgid "Warning: %s:%d unused %s \"%s\""
+msgstr "Cảnh báo: %s:%d không dùng %s “%s”"
+
+#: plugins/sudoers/visudo.c:1276
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - sửa tập tin sudoers một cách an toàn\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1278
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"Các tùy chọn:\n"
+" -c, --check chế độ chỉ kiểm tra\n"
+" -f, --file=tập-tin chỉ định vị trí tập tin sudoers\n"
+" -h, --help hiển thị thông tin trợ giúp rồi thoát\n"
+" -q, --quiet tối thiểu hóa các thông tin (quiet: im lặng)\n"
+" -s, --strict kiểm tra cú pháp ngặt nghèo\n"
+" -V, --version hiển thị thông tin về phiên bản rồi thoát\n"
+
+#: toke.l:939
+msgid "too many levels of includes"
+msgstr "quá nhiều cấp bao gồm (include)"
+
+#~ msgid ""
+#~ "\n"
+#~ "LDAP Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Vai trò LDAP: KHÔNG HIỂU\n"
+
+#~ msgid " Order: %s\n"
+#~ msgstr " Thứ tự: %s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: %s\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Vai trò SSSD: %s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Vai trò SSSD: KHÔNG HIỂU\n"
+
+#~ msgid "Warning: cycle in %s `%s'"
+#~ msgstr "Cảnh báo: quẩn tròn trong %s “%s”"
+
+#~ msgid "Warning: %s `%s' referenced but not defined"
+#~ msgstr "Cảnh báo: %s “%s” được tham chiếu nhưng chưa được định nghĩa"
+
+#~ msgid "Warning: unused %s `%s'"
+#~ msgstr "Cảnh báo: chưa được dùng %s “%s”"
+
+#~ msgid "unable allocate memory"
+#~ msgstr "không thể cấp phát bộ nhớ"
+
+#~ msgid "timestamp path too long: %s/%s"
+#~ msgstr "đường dẫn dấu vết thời gian quá dài: %s/%s"
+
+#~ msgid "unable to stat editor (%s)"
+#~ msgstr "không thể lấy thống kê trình biên soạn (%s)"
+
+#~ msgid "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+#~ msgstr "sudo_ldap_conf_add_ports: hết bộ nhớ để mở rộng hostbuf"
+
+#~ msgid "sudo_ldap_parse_uri: out of space building hostbuf"
+#~ msgstr "sudo_ldap_parse_uri: hết bộ nhớ để biên dịch “hostbuf”"
+
+#~ msgid "sudo_ldap_build_pass1 allocation mismatch"
+#~ msgstr "sudo_ldap_build_pass1 phân bổ không khớp"
+
+#~ msgid "Password:"
+#~ msgstr "Mật khẩu:"
+
+#~ msgid "internal error: insufficient space for log line"
+#~ msgstr "lỗi nội bộ: thiếu khoảng trống cho dòng ghi nhật ký"
+
+#~ msgid "fill_args: buffer overflow"
+#~ msgstr "fill_args: bộ đệm bị tràn"
+
+#~ msgid "%s owned by uid %u, should be uid %u"
+#~ msgstr "%s được sở hữu bởi uid %u, nên là %u"
+
+#~ msgid "%s writable by non-owner (0%o), should be mode 0700"
+#~ msgstr "%s có thể được ghi bởi người không sở hữu nó (0%o), cần đặt chế độ 0700"
+
+#~ msgid "%s exists but is not a regular file (0%o)"
+#~ msgstr "%s đã sẵn có nhưng không phải là một tập tin bình thường (0%o)"
+
+#~ msgid "%s writable by non-owner (0%o), should be mode 0600"
+#~ msgstr "%s có thể được ghi bởi người không sở hữu nó (0%o), cần đặt chế độ 0600"
+
+#~ msgid "unable to remove %s, will reset to the Unix epoch"
+#~ msgstr "không thể gỡ bỏ %s, sẽ đặt lại thành thời điểm bắt đầu kiểu Unix"
+
+#~ msgid "unable to reset %s to the Unix epoch"
+#~ msgstr "không thể đặt lại %s thành thời điểm bắt đầu kiểu Unix"
+
+#~ msgid "value out of range"
+#~ msgstr "giá trị nằm ngoài phạm vi"
+
+#~ msgid "invalid uri: %s"
+#~ msgstr "URI không hợp lệ: %s"
+
+#~ msgid "unable to mix ldaps and starttls"
+#~ msgstr "không thể trộn ldaps và starttls"
+
+#~ msgid "writing to standard output"
+#~ msgstr "ghi vào đầu ra tiêu chuẩn"
+
+#~ msgid "too many parenthesized expressions, max %d"
+#~ msgstr "có quá nhiều biểu thức trong dấu ngoặc đơn, tối đa là %d"
+
+#~ msgid "unable to setup authentication"
+#~ msgstr "không thể cài đặt xác thực"
+
+#~ msgid "getaudit: failed"
+#~ msgstr "getaudit: gặp lỗi"
+
+#~ msgid "getauid: failed"
+#~ msgstr "getauid: gặp lỗi"
+
+#~ msgid "au_to_subject: failed"
+#~ msgstr "au_to_subject: gặp lỗi"
+
+#~ msgid "au_to_exec_args: failed"
+#~ msgstr "au_to_exec_args: gặp lỗi"
+
+#~ msgid "au_to_return32: failed"
+#~ msgstr "au_to_return32: gặp lỗi"
+
+#~ msgid "au_to_text: failed"
+#~ msgstr "au_to_text: gặp lỗi"
+
+#~ msgid "nanosleep: tv_sec %ld, tv_nsec %ld"
+#~ msgstr "nanosleep: tv_sec %ld, tv_nsec %ld"
+
+#~ msgid "pam_chauthtok: %s"
+#~ msgstr "pam_chauthtok: %s"
+
+#~ msgid "pam_authenticate: %s"
+#~ msgstr "pam_authenticate: %s"
+
+#~ msgid "getauid failed"
+#~ msgstr "getauid gặp lỗi"
+
+#~ msgid "Unable to dlopen %s: %s"
+#~ msgstr "Không thể dlopen %s: %s"
+
+#~ msgid "invalid regex: %s"
+#~ msgstr "biểu thức chính quy không hợp lệ: %s"
+
+#~ msgid ">>> %s: %s near line %d <<<"
+#~ msgstr ">>> %s: %s gần dòng %d <<<"
+
+#~ msgid "unable to set locale to \"%s\", using \"C\""
+#~ msgstr "không thể đặt địa phương thành “%s”, sẽ dùng “C”"
+
+#~ msgid ""
+#~ " Commands:\n"
+#~ "\t"
+#~ msgstr ""
+#~ " Lệnh:\n"
+#~ "\t"
+
+#~ msgid ": "
+#~ msgstr ": "
+
+#~ msgid "unable to cache uid %u (%s), already exists"
+#~ msgstr "không thể lưu nhớ tạm uid %u (%s), đã có sẵn rồi"
+
+#~ msgid "unable to cache gid %u (%s), already exists"
+#~ msgstr "không thể lưu nhớ tạm gid %u (%s), đã có sẵn rồi"
+
+#~ msgid "unable to execute %s: %s"
+#~ msgstr "không thể thực thi %s: %s"
diff --git a/plugins/sudoers/po/zh_CN.mo b/plugins/sudoers/po/zh_CN.mo
new file mode 100644
index 0000000..59fc977
--- /dev/null
+++ b/plugins/sudoers/po/zh_CN.mo
Binary files differ
diff --git a/plugins/sudoers/po/zh_CN.po b/plugins/sudoers/po/zh_CN.po
new file mode 100644
index 0000000..64c0011
--- /dev/null
+++ b/plugins/sudoers/po/zh_CN.po
@@ -0,0 +1,4134 @@
+# Chinese simplified translation for sudoers.
+# This file is put in the public domain.
+# Wylmer Wang <wantinghard@gmail.com>, 2011-2018
+# Boyuan Yang <073plan@gmail.com>, 2019, 2020, 2021, 2022.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.9.12b2\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2022-10-10 09:13-0600\n"
+"PO-Revision-Date: 2022-11-29 14:54-0500\n"
+"Last-Translator: Boyuan Yang <073plan@gmail.com>\n"
+"Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
+"Language: zh_CN\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 3.2\n"
+
+#: confstr.sh:1 gram.y:1220 plugins/sudoers/logging.c:862
+msgid "syntax error"
+msgstr "语法错误"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "%p 的密码:"
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] %p 的密码:"
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "密码:"
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** %h 安全信息 ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "对不起,请重试。"
+
+#: gram.y:237 gram.y:304 gram.y:313 gram.y:322 gram.y:332 gram.y:342
+#: gram.y:366 gram.y:393 gram.y:402 gram.y:410 gram.y:419 gram.y:428
+#: gram.y:502 gram.y:512 gram.y:524 gram.y:572 gram.y:581 gram.y:590
+#: gram.y:599 gram.y:731 gram.y:739 gram.y:750 gram.y:762 gram.y:781
+#: gram.y:944 gram.y:949 gram.y:957 gram.y:971 gram.y:977 gram.y:1099
+#: gram.y:1108 gram.y:1116 gram.y:1125 gram.y:1134 gram.y:1163 gram.y:1172
+#: gram.y:1180 gram.y:1280 gram.y:1410 gram.y:1777 gram.y:1827
+#: lib/eventlog/eventlog.c:309 lib/eventlog/eventlog.c:382
+#: lib/eventlog/eventlog.c:827 lib/eventlog/eventlog.c:904
+#: lib/eventlog/eventlog.c:1204 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_json.c:150 lib/iolog/iolog_json.c:382
+#: lib/iolog/iolog_json.c:412 lib/iolog/iolog_json.c:555
+#: lib/iolog/iolog_legacy.c:100 lib/iolog/iolog_legacy.c:111
+#: lib/iolog/iolog_legacy.c:123 lib/iolog/iolog_legacy.c:133
+#: lib/iolog/iolog_legacy.c:139 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:182 logsrvd/iolog_writer.c:215
+#: logsrvd/iolog_writer.c:225 logsrvd/iolog_writer.c:254
+#: logsrvd/iolog_writer.c:275 logsrvd/iolog_writer.c:287
+#: logsrvd/iolog_writer.c:297 logsrvd/iolog_writer.c:307
+#: logsrvd/iolog_writer.c:317 logsrvd/iolog_writer.c:329
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:370
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:567 logsrvd/logsrv_util.c:69 logsrvd/logsrvd.c:301
+#: logsrvd/logsrvd.c:310 logsrvd/logsrvd.c:1050 logsrvd/logsrvd.c:1113
+#: logsrvd/logsrvd.c:1582 logsrvd/logsrvd.c:1587 logsrvd/logsrvd.c:1771
+#: logsrvd/logsrvd.c:1988 logsrvd/logsrvd_conf.c:357
+#: logsrvd/logsrvd_conf.c:370 logsrvd/logsrvd_conf.c:511
+#: logsrvd/logsrvd_conf.c:534 logsrvd/logsrvd_conf.c:538
+#: logsrvd/logsrvd_conf.c:556 logsrvd/logsrvd_conf.c:626
+#: logsrvd/logsrvd_conf.c:650 logsrvd/logsrvd_conf.c:678
+#: logsrvd/logsrvd_conf.c:692 logsrvd/logsrvd_conf.c:706
+#: logsrvd/logsrvd_conf.c:720 logsrvd/logsrvd_conf.c:734
+#: logsrvd/logsrvd_conf.c:748 logsrvd/logsrvd_conf.c:829
+#: logsrvd/logsrvd_conf.c:1036 logsrvd/logsrvd_conf.c:1053
+#: logsrvd/logsrvd_conf.c:1448 logsrvd/logsrvd_conf.c:1595
+#: logsrvd/logsrvd_conf.c:1621 logsrvd/logsrvd_conf.c:1633
+#: logsrvd/logsrvd_conf.c:1640 logsrvd/logsrvd_conf.c:1646
+#: logsrvd/logsrvd_conf.c:1743 logsrvd/logsrvd_journal.c:75
+#: logsrvd/logsrvd_journal.c:213 logsrvd/logsrvd_journal.c:214
+#: logsrvd/logsrvd_journal.c:270 logsrvd/logsrvd_journal.c:430
+#: logsrvd/logsrvd_journal.c:432 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:216 logsrvd/logsrvd_local.c:278
+#: logsrvd/logsrvd_local.c:279 logsrvd/logsrvd_local.c:417
+#: logsrvd/logsrvd_local.c:466 logsrvd/logsrvd_local.c:467
+#: logsrvd/logsrvd_local.c:472 logsrvd/logsrvd_local.c:473
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/logsrvd_relay.c:444
+#: logsrvd/logsrvd_relay.c:743 logsrvd/logsrvd_relay.c:850
+#: logsrvd/sendlog.c:251 logsrvd/sendlog.c:260 logsrvd/sendlog.c:291
+#: logsrvd/sendlog.c:338 logsrvd/sendlog.c:615 logsrvd/sendlog.c:1801
+#: plugins/sudoers/audit.c:116 plugins/sudoers/auth/bsdauth.c:150
+#: plugins/sudoers/auth/kerb5.c:121 plugins/sudoers/auth/kerb5.c:148
+#: plugins/sudoers/auth/pam.c:687 plugins/sudoers/auth/rfc1938.c:111
+#: plugins/sudoers/auth/sia.c:59 plugins/sudoers/check_aliases.c:168
+#: plugins/sudoers/cvtsudoers.c:131 plugins/sudoers/cvtsudoers.c:175
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:203
+#: plugins/sudoers/cvtsudoers.c:333 plugins/sudoers/cvtsudoers.c:372
+#: plugins/sudoers/cvtsudoers.c:392 plugins/sudoers/cvtsudoers.c:537
+#: plugins/sudoers/cvtsudoers.c:670 plugins/sudoers/cvtsudoers.c:688
+#: plugins/sudoers/cvtsudoers.c:862 plugins/sudoers/cvtsudoers.c:870
+#: plugins/sudoers/cvtsudoers.c:1365 plugins/sudoers/cvtsudoers.c:1369
+#: plugins/sudoers/cvtsudoers.c:1471 plugins/sudoers/cvtsudoers_csv.c:183
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:76
+#: plugins/sudoers/cvtsudoers_ldif.c:151 plugins/sudoers/cvtsudoers_ldif.c:194
+#: plugins/sudoers/cvtsudoers_ldif.c:235 plugins/sudoers/cvtsudoers_ldif.c:300
+#: plugins/sudoers/cvtsudoers_ldif.c:376 plugins/sudoers/cvtsudoers_ldif.c:430
+#: plugins/sudoers/cvtsudoers_ldif.c:438 plugins/sudoers/cvtsudoers_ldif.c:449
+#: plugins/sudoers/cvtsudoers_ldif.c:456 plugins/sudoers/cvtsudoers_ldif.c:468
+#: plugins/sudoers/cvtsudoers_ldif.c:481 plugins/sudoers/cvtsudoers_ldif.c:489
+#: plugins/sudoers/cvtsudoers_ldif.c:636 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1158
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:434
+#: plugins/sudoers/defaults.c:658 plugins/sudoers/defaults.c:1019
+#: plugins/sudoers/defaults.c:1187 plugins/sudoers/editor.c:188
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:54 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:228
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:668 plugins/sudoers/iolog.c:694
+#: plugins/sudoers/ldap.c:184 plugins/sudoers/ldap.c:464
+#: plugins/sudoers/ldap.c:755 plugins/sudoers/ldap.c:919
+#: plugins/sudoers/ldap.c:1335 plugins/sudoers/ldap.c:1761
+#: plugins/sudoers/ldap.c:1798 plugins/sudoers/ldap.c:1879
+#: plugins/sudoers/ldap.c:2014 plugins/sudoers/ldap.c:2115
+#: plugins/sudoers/ldap.c:2131 plugins/sudoers/ldap_conf.c:218
+#: plugins/sudoers/ldap_conf.c:250 plugins/sudoers/ldap_conf.c:302
+#: plugins/sudoers/ldap_conf.c:338 plugins/sudoers/ldap_conf.c:444
+#: plugins/sudoers/ldap_conf.c:459 plugins/sudoers/ldap_conf.c:564
+#: plugins/sudoers/ldap_conf.c:597 plugins/sudoers/ldap_conf.c:689
+#: plugins/sudoers/ldap_conf.c:771 plugins/sudoers/ldap_util.c:294
+#: plugins/sudoers/ldap_util.c:301 plugins/sudoers/ldap_util.c:614
+#: plugins/sudoers/linux_audit.c:86 plugins/sudoers/log_client.c:117
+#: plugins/sudoers/log_client.c:402 plugins/sudoers/log_client.c:715
+#: plugins/sudoers/log_client.c:736 plugins/sudoers/log_client.c:1416
+#: plugins/sudoers/log_client.c:1537 plugins/sudoers/log_client.c:1637
+#: plugins/sudoers/log_client.c:1973 plugins/sudoers/log_client.c:2032
+#: plugins/sudoers/logging.c:110 plugins/sudoers/logging.c:189
+#: plugins/sudoers/logging.c:453 plugins/sudoers/logging.c:668
+#: plugins/sudoers/logging.c:805 plugins/sudoers/match_command.c:335
+#: plugins/sudoers/match_command.c:603 plugins/sudoers/match_command.c:654
+#: plugins/sudoers/match_command.c:728 plugins/sudoers/match_command.c:776
+#: plugins/sudoers/match_digest.c:93 plugins/sudoers/parse.c:227
+#: plugins/sudoers/parse.c:244 plugins/sudoers/parse.c:263
+#: plugins/sudoers/parse.c:282 plugins/sudoers/parse.c:299
+#: plugins/sudoers/parse.c:322 plugins/sudoers/parse.c:333
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:598
+#: plugins/sudoers/parse_ldif.c:628 plugins/sudoers/parse_ldif.c:653
+#: plugins/sudoers/parse_ldif.c:711 plugins/sudoers/parse_ldif.c:728
+#: plugins/sudoers/parse_ldif.c:756 plugins/sudoers/parse_ldif.c:763
+#: plugins/sudoers/policy.c:624 plugins/sudoers/policy.c:1026
+#: plugins/sudoers/prompt.c:93 plugins/sudoers/pwutil.c:199
+#: plugins/sudoers/pwutil.c:270 plugins/sudoers/pwutil.c:348
+#: plugins/sudoers/pwutil.c:522 plugins/sudoers/pwutil.c:587
+#: plugins/sudoers/pwutil.c:659 plugins/sudoers/pwutil.c:857
+#: plugins/sudoers/pwutil.c:913 plugins/sudoers/pwutil.c:957
+#: plugins/sudoers/pwutil.c:1014 plugins/sudoers/sssd.c:145
+#: plugins/sudoers/sssd.c:185 plugins/sudoers/sssd.c:414
+#: plugins/sudoers/sssd.c:479 plugins/sudoers/sssd.c:505
+#: plugins/sudoers/sssd.c:568 plugins/sudoers/sssd.c:761
+#: plugins/sudoers/strvec_join.c:53 plugins/sudoers/stubs.c:112
+#: plugins/sudoers/stubs.c:120 plugins/sudoers/sudoers.c:354
+#: plugins/sudoers/sudoers.c:380 plugins/sudoers/sudoers.c:448
+#: plugins/sudoers/sudoers.c:457 plugins/sudoers/sudoers.c:498
+#: plugins/sudoers/sudoers.c:827 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:1015 plugins/sudoers/sudoers.c:1075
+#: plugins/sudoers/sudoers.c:1330 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:565 plugins/sudoers/sudoreplay.c:1281
+#: plugins/sudoers/sudoreplay.c:1503 plugins/sudoers/sudoreplay.c:1507
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:224
+#: plugins/sudoers/testsudoers.c:241 plugins/sudoers/testsudoers.c:588
+#: plugins/sudoers/timestamp.c:451 plugins/sudoers/timestamp.c:495
+#: plugins/sudoers/timestamp.c:1017 plugins/sudoers/timestamp.c:1146
+#: plugins/sudoers/toke_util.c:78 plugins/sudoers/toke_util.c:106
+#: plugins/sudoers/toke_util.c:131 plugins/sudoers/toke_util.c:161
+#: plugins/sudoers/toke_util.c:200 plugins/sudoers/tsdump.c:123
+#: plugins/sudoers/visudo.c:150 plugins/sudoers/visudo.c:385
+#: plugins/sudoers/visudo.c:391 plugins/sudoers/visudo.c:498
+#: plugins/sudoers/visudo.c:1054 toke.l:1023 toke.l:1155 toke.l:1226
+msgid "unable to allocate memory"
+msgstr "无法分配内存"
+
+#: gram.y:623
+msgid "a digest requires a path name"
+msgstr "摘要需要路径参数"
+
+#: gram.y:645
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "“CWD”的值必须以“/”、“~”或“*”开头"
+
+#: gram.y:651
+msgid "\"CWD\" path too long"
+msgstr "“CWD”路径过长"
+
+#: gram.y:661
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "“CHROOT”的值必须以“/”、“~”或“*”开头"
+
+#: gram.y:667
+msgid "\"CHROOT\" path too long"
+msgstr "“CHROOT”路径过长"
+
+#: gram.y:802
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "语法错误,保留字 %s 被用作别名"
+
+#: gram.y:825
+msgid "invalid notbefore value"
+msgstr "无效的 notbefore 值"
+
+#: gram.y:834
+msgid "invalid notafter value"
+msgstr "无效的 notafter 值"
+
+#: gram.y:844 plugins/sudoers/policy.c:383
+msgid "timeout value too large"
+msgstr "超时值过大"
+
+#: gram.y:846 plugins/sudoers/policy.c:385
+msgid "invalid timeout value"
+msgstr "无效的超时值"
+
+#: gram.y:967 plugins/sudoers/sudoers.c:1033
+msgid "command too long"
+msgstr "命令过长"
+
+#: gram.y:1224 plugins/sudoers/check_aliases.c:96
+#: plugins/sudoers/defaults.c:1276
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: gram.y:1278
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "别名“%s”已定义过"
+
+#: gram.y:1777 gram.y:1827 lib/eventlog/eventlog.c:309
+#: lib/eventlog/eventlog.c:827 lib/eventlog/eventlog.c:900
+#: lib/eventlog/eventlog.c:903 lib/eventlog/eventlog.c:1204
+#: lib/iolog/iolog_filter.c:142 lib/iolog/iolog_filter.c:202
+#: lib/iolog/iolog_filter.c:232 lib/iolog/iolog_json.c:150
+#: lib/iolog/iolog_json.c:381 lib/iolog/iolog_json.c:412
+#: lib/iolog/iolog_json.c:555 lib/iolog/iolog_legacy.c:100
+#: lib/iolog/iolog_legacy.c:111 lib/iolog/iolog_legacy.c:123
+#: lib/iolog/iolog_legacy.c:133 lib/iolog/iolog_legacy.c:139
+#: lib/iolog/iolog_loginfo.c:76 lib/iolog/iolog_loginfo.c:212
+#: logsrvd/iolog_writer.c:95 logsrvd/iolog_writer.c:100
+#: logsrvd/iolog_writer.c:134 logsrvd/iolog_writer.c:171
+#: logsrvd/iolog_writer.c:181 logsrvd/iolog_writer.c:194
+#: logsrvd/iolog_writer.c:214 logsrvd/iolog_writer.c:224
+#: logsrvd/iolog_writer.c:243 logsrvd/iolog_writer.c:253
+#: logsrvd/iolog_writer.c:264 logsrvd/iolog_writer.c:274
+#: logsrvd/iolog_writer.c:286 logsrvd/iolog_writer.c:296
+#: logsrvd/iolog_writer.c:306 logsrvd/iolog_writer.c:316
+#: logsrvd/iolog_writer.c:328 logsrvd/iolog_writer.c:364
+#: logsrvd/iolog_writer.c:370 logsrvd/iolog_writer.c:377
+#: logsrvd/iolog_writer.c:383 logsrvd/iolog_writer.c:567
+#: logsrvd/logsrv_util.c:69 logsrvd/logsrvd.c:301 logsrvd/logsrvd.c:310
+#: logsrvd/logsrvd.c:453 logsrvd/logsrvd.c:490 logsrvd/logsrvd.c:522
+#: logsrvd/logsrvd.c:576 logsrvd/logsrvd.c:611 logsrvd/logsrvd.c:660
+#: logsrvd/logsrvd.c:696 logsrvd/logsrvd.c:732 logsrvd/logsrvd.c:1124
+#: logsrvd/logsrvd.c:1439 logsrvd/logsrvd.c:1446 logsrvd/logsrvd.c:1582
+#: logsrvd/logsrvd.c:1587 logsrvd/logsrvd.c:1771 logsrvd/logsrvd.c:1988
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:649
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1742
+#: logsrvd/logsrvd_journal.c:75 logsrvd/logsrvd_journal.c:122
+#: logsrvd/logsrvd_journal.c:213 logsrvd/logsrvd_journal.c:243
+#: logsrvd/logsrvd_journal.c:247 logsrvd/logsrvd_journal.c:255
+#: logsrvd/logsrvd_journal.c:278 logsrvd/logsrvd_journal.c:282
+#: logsrvd/logsrvd_journal.c:430 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:278 logsrvd/logsrvd_local.c:466
+#: logsrvd/logsrvd_local.c:472 logsrvd/logsrvd_local.c:491
+#: logsrvd/logsrvd_queue.c:158 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/sendlog.c:251 logsrvd/sendlog.c:260
+#: logsrvd/sendlog.c:291 logsrvd/sendlog.c:338 logsrvd/sendlog.c:615
+#: logsrvd/sendlog.c:1503 logsrvd/sendlog.c:1510 logsrvd/sendlog.c:1733
+#: logsrvd/sendlog.c:1801 logsrvd/tls_init.c:305 logsrvd/tls_init.c:329
+#: logsrvd/tls_init.c:340 plugins/sudoers/audit.c:116
+#: plugins/sudoers/auth/pam.c:502 plugins/sudoers/auth/pam.c:687
+#: plugins/sudoers/auth/rfc1938.c:111 plugins/sudoers/check_aliases.c:168
+#: plugins/sudoers/cvtsudoers.c:131 plugins/sudoers/cvtsudoers.c:174
+#: plugins/sudoers/cvtsudoers.c:191 plugins/sudoers/cvtsudoers.c:202
+#: plugins/sudoers/cvtsudoers.c:332 plugins/sudoers/cvtsudoers.c:536
+#: plugins/sudoers/cvtsudoers.c:669 plugins/sudoers/cvtsudoers.c:687
+#: plugins/sudoers/cvtsudoers.c:862 plugins/sudoers/cvtsudoers.c:869
+#: plugins/sudoers/cvtsudoers.c:1365 plugins/sudoers/cvtsudoers.c:1369
+#: plugins/sudoers/cvtsudoers.c:1471 plugins/sudoers/cvtsudoers_csv.c:182
+#: plugins/sudoers/cvtsudoers_csv.c:245 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:150 plugins/sudoers/cvtsudoers_ldif.c:193
+#: plugins/sudoers/cvtsudoers_ldif.c:234 plugins/sudoers/cvtsudoers_ldif.c:299
+#: plugins/sudoers/cvtsudoers_ldif.c:375 plugins/sudoers/cvtsudoers_ldif.c:429
+#: plugins/sudoers/cvtsudoers_ldif.c:437 plugins/sudoers/cvtsudoers_ldif.c:448
+#: plugins/sudoers/cvtsudoers_ldif.c:455 plugins/sudoers/cvtsudoers_ldif.c:467
+#: plugins/sudoers/cvtsudoers_ldif.c:480 plugins/sudoers/cvtsudoers_ldif.c:488
+#: plugins/sudoers/cvtsudoers_ldif.c:635 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1157
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:434
+#: plugins/sudoers/defaults.c:658 plugins/sudoers/defaults.c:1019
+#: plugins/sudoers/defaults.c:1187 plugins/sudoers/editor.c:188
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:54 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:227
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:668 plugins/sudoers/iolog.c:694
+#: plugins/sudoers/ldap.c:184 plugins/sudoers/ldap.c:464
+#: plugins/sudoers/ldap.c:755 plugins/sudoers/ldap.c:919
+#: plugins/sudoers/ldap.c:1335 plugins/sudoers/ldap.c:1761
+#: plugins/sudoers/ldap.c:1798 plugins/sudoers/ldap.c:1879
+#: plugins/sudoers/ldap.c:2014 plugins/sudoers/ldap.c:2115
+#: plugins/sudoers/ldap.c:2131 plugins/sudoers/ldap_conf.c:218
+#: plugins/sudoers/ldap_conf.c:250 plugins/sudoers/ldap_conf.c:302
+#: plugins/sudoers/ldap_conf.c:338 plugins/sudoers/ldap_conf.c:444
+#: plugins/sudoers/ldap_conf.c:459 plugins/sudoers/ldap_conf.c:564
+#: plugins/sudoers/ldap_conf.c:597 plugins/sudoers/ldap_conf.c:688
+#: plugins/sudoers/ldap_conf.c:771 plugins/sudoers/ldap_util.c:293
+#: plugins/sudoers/ldap_util.c:300 plugins/sudoers/ldap_util.c:614
+#: plugins/sudoers/linux_audit.c:86 plugins/sudoers/log_client.c:117
+#: plugins/sudoers/log_client.c:228 plugins/sudoers/log_client.c:250
+#: plugins/sudoers/log_client.c:264 plugins/sudoers/log_client.c:402
+#: plugins/sudoers/log_client.c:715 plugins/sudoers/log_client.c:736
+#: plugins/sudoers/log_client.c:1416 plugins/sudoers/log_client.c:1537
+#: plugins/sudoers/log_client.c:1637 plugins/sudoers/log_client.c:1973
+#: plugins/sudoers/log_client.c:2032 plugins/sudoers/logging.c:110
+#: plugins/sudoers/logging.c:188 plugins/sudoers/logging.c:189
+#: plugins/sudoers/logging.c:453 plugins/sudoers/logging.c:668
+#: plugins/sudoers/logging.c:805 plugins/sudoers/logging.c:876
+#: plugins/sudoers/logging.c:888 plugins/sudoers/match_command.c:334
+#: plugins/sudoers/match_command.c:602 plugins/sudoers/match_command.c:653
+#: plugins/sudoers/match_command.c:728 plugins/sudoers/match_command.c:775
+#: plugins/sudoers/match_digest.c:93 plugins/sudoers/parse.c:226
+#: plugins/sudoers/parse.c:243 plugins/sudoers/parse.c:262
+#: plugins/sudoers/parse.c:281 plugins/sudoers/parse.c:298
+#: plugins/sudoers/parse.c:321 plugins/sudoers/parse.c:332
+#: plugins/sudoers/parse_ldif.c:152 plugins/sudoers/parse_ldif.c:183
+#: plugins/sudoers/parse_ldif.c:252 plugins/sudoers/parse_ldif.c:260
+#: plugins/sudoers/parse_ldif.c:265 plugins/sudoers/parse_ldif.c:341
+#: plugins/sudoers/parse_ldif.c:352 plugins/sudoers/parse_ldif.c:379
+#: plugins/sudoers/parse_ldif.c:396 plugins/sudoers/parse_ldif.c:408
+#: plugins/sudoers/parse_ldif.c:412 plugins/sudoers/parse_ldif.c:426
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:598
+#: plugins/sudoers/parse_ldif.c:627 plugins/sudoers/parse_ldif.c:652
+#: plugins/sudoers/parse_ldif.c:710 plugins/sudoers/parse_ldif.c:727
+#: plugins/sudoers/parse_ldif.c:755 plugins/sudoers/parse_ldif.c:762
+#: plugins/sudoers/policy.c:153 plugins/sudoers/policy.c:162
+#: plugins/sudoers/policy.c:171 plugins/sudoers/policy.c:199
+#: plugins/sudoers/policy.c:368 plugins/sudoers/policy.c:383
+#: plugins/sudoers/policy.c:385 plugins/sudoers/policy.c:423
+#: plugins/sudoers/policy.c:432 plugins/sudoers/policy.c:480
+#: plugins/sudoers/policy.c:490 plugins/sudoers/policy.c:499
+#: plugins/sudoers/policy.c:508 plugins/sudoers/policy.c:517
+#: plugins/sudoers/policy.c:624 plugins/sudoers/policy.c:1026
+#: plugins/sudoers/prompt.c:93 plugins/sudoers/pwutil.c:199
+#: plugins/sudoers/pwutil.c:270 plugins/sudoers/pwutil.c:348
+#: plugins/sudoers/pwutil.c:522 plugins/sudoers/pwutil.c:587
+#: plugins/sudoers/pwutil.c:659 plugins/sudoers/pwutil.c:857
+#: plugins/sudoers/pwutil.c:913 plugins/sudoers/pwutil.c:957
+#: plugins/sudoers/pwutil.c:1014 plugins/sudoers/set_perms.c:363
+#: plugins/sudoers/set_perms.c:706 plugins/sudoers/set_perms.c:1073
+#: plugins/sudoers/set_perms.c:1380 plugins/sudoers/set_perms.c:1549
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:185
+#: plugins/sudoers/sssd.c:414 plugins/sudoers/sssd.c:479
+#: plugins/sudoers/sssd.c:505 plugins/sudoers/sssd.c:568
+#: plugins/sudoers/sssd.c:761 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/stubs.c:112 plugins/sudoers/stubs.c:120
+#: plugins/sudoers/sudoers.c:354 plugins/sudoers/sudoers.c:380
+#: plugins/sudoers/sudoers.c:448 plugins/sudoers/sudoers.c:457
+#: plugins/sudoers/sudoers.c:498 plugins/sudoers/sudoers.c:827
+#: plugins/sudoers/sudoers.c:877 plugins/sudoers/sudoers.c:1015
+#: plugins/sudoers/sudoers.c:1075 plugins/sudoers/sudoers.c:1330
+#: plugins/sudoers/sudoreplay.c:562 plugins/sudoers/sudoreplay.c:565
+#: plugins/sudoers/sudoreplay.c:1281 plugins/sudoers/sudoreplay.c:1503
+#: plugins/sudoers/sudoreplay.c:1507 plugins/sudoers/testsudoers.c:120
+#: plugins/sudoers/testsudoers.c:224 plugins/sudoers/testsudoers.c:241
+#: plugins/sudoers/testsudoers.c:588 plugins/sudoers/timestamp.c:451
+#: plugins/sudoers/timestamp.c:495 plugins/sudoers/timestamp.c:1017
+#: plugins/sudoers/timestamp.c:1146 plugins/sudoers/toke_util.c:78
+#: plugins/sudoers/toke_util.c:106 plugins/sudoers/toke_util.c:131
+#: plugins/sudoers/toke_util.c:160 plugins/sudoers/toke_util.c:200
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:150
+#: plugins/sudoers/visudo.c:385 plugins/sudoers/visudo.c:391
+#: plugins/sudoers/visudo.c:498 plugins/sudoers/visudo.c:1054 toke.l:1023
+#: toke.l:1155 toke.l:1218 toke.l:1226
+#, c-format
+msgid "%s: %s"
+msgstr "%s:%s"
+
+#: lib/eventlog/eventlog.c:314 lib/iolog/iolog_json.c:562
+#: lib/iolog/iolog_json.c:568 lib/iolog/iolog_json.c:574
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:244 plugins/sudoers/cvtsudoers_ldif.c:251
+#: plugins/sudoers/cvtsudoers_ldif.c:592 plugins/sudoers/env.c:340
+#: plugins/sudoers/env.c:347 plugins/sudoers/env.c:458
+#: plugins/sudoers/ldap.c:526 plugins/sudoers/ldap.c:759
+#: plugins/sudoers/ldap.c:1132 plugins/sudoers/ldap_conf.c:222
+#: plugins/sudoers/ldap_conf.c:313 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:92 plugins/sudoers/logging.c:457
+#: plugins/sudoers/logging.c:813 plugins/sudoers/logging.c:823
+#: plugins/sudoers/policy.c:800 plugins/sudoers/policy.c:811
+#: plugins/sudoers/prompt.c:168 plugins/sudoers/serialize_list.c:62
+#: plugins/sudoers/serialize_list.c:71 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/testsudoers.c:245 plugins/sudoers/toke_util.c:213
+#: toke.l:987 toke.l:1189
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "内部错误,%s 溢出"
+
+#: lib/eventlog/eventlog.c:373
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "无法 dup stdin:%m"
+
+#: lib/eventlog/eventlog.c:415
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "无法执行 %s:%m"
+
+#: lib/eventlog/eventlog.c:463 plugins/sudoers/auth/aix_auth.c:198
+msgid "unable to fork"
+msgstr "无法执行 fork"
+
+#: lib/eventlog/eventlog.c:473 lib/eventlog/eventlog.c:538
+#, c-format
+msgid "unable to fork: %m"
+msgstr "无法执行 fork:%m"
+
+#: lib/eventlog/eventlog.c:528
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "无法打开管道:%m"
+
+#: lib/eventlog/eventlog.c:1030
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s:%s"
+
+#: lib/eventlog/eventlog.c:1059
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s:(命令继续执行) %s"
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1242
+#: plugins/sudoers/sudoreplay.c:1293 plugins/sudoers/sudoreplay.c:1558
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr "无效的正则表达式“%s”:%s"
+
+#: lib/iolog/iolog_json.c:140
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "期望得到 JSON_STRING,但得到了 %d"
+
+#: lib/iolog/iolog_json.c:145
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY 过大"
+
+#: lib/iolog/iolog_json.c:404
+msgid "missing double quote in name"
+msgstr "名称中缺少双引号"
+
+#: lib/iolog/iolog_json.c:501
+msgid "missing JSON_OBJECT"
+msgstr "缺少 JSON_OBJECT"
+
+#: lib/iolog/iolog_json.c:505
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "期望得到 JSON_OBJECT,但得到了 %d"
+
+#: lib/iolog/iolog_json.c:661
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "json 栈耗尽(最大 %u 帧)"
+
+#: lib/iolog/iolog_json.c:735
+msgid "objects must consist of name:value pairs"
+msgstr "对象必须包含 名称:值 对"
+
+#: lib/iolog/iolog_json.c:740 lib/iolog/iolog_json.c:771
+#: lib/iolog/iolog_json.c:815 lib/iolog/iolog_json.c:837
+#: lib/iolog/iolog_json.c:859 lib/iolog/iolog_json.c:881
+#: lib/iolog/iolog_json.c:903
+msgid "missing separator between values"
+msgstr "值之间缺少分隔符"
+
+#: lib/iolog/iolog_json.c:755 lib/iolog/iolog_json.c:929
+msgid "unmatched close brace"
+msgstr "不匹配的右括号"
+
+#: lib/iolog/iolog_json.c:766
+msgid "unexpected array"
+msgstr "未预期的数组"
+
+#: lib/iolog/iolog_json.c:786 lib/iolog/iolog_json.c:932
+msgid "unmatched close bracket"
+msgstr "不匹配的右花括号"
+
+#: lib/iolog/iolog_json.c:797
+msgid "unexpected string"
+msgstr "未预期的字符串"
+
+#: lib/iolog/iolog_json.c:808
+msgid "missing colon after name"
+msgstr "名称后缺少冒号"
+
+#: lib/iolog/iolog_json.c:829 lib/iolog/iolog_json.c:851
+msgid "unexpected boolean"
+msgstr "未预期的布尔值"
+
+#: lib/iolog/iolog_json.c:873
+msgid "unexpected null"
+msgstr "未预期的 null"
+
+#: lib/iolog/iolog_json.c:894
+msgid "unexpected number"
+msgstr "未预期的数字"
+
+#: lib/iolog/iolog_json.c:941
+msgid "parse error"
+msgstr "解析错误"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s:无效的日志文件"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s:缺少 时间戳 字段"
+
+#: lib/iolog/iolog_legacy.c:89
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s:时间戳 %s:%s"
+
+#: lib/iolog/iolog_legacy.c:96
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s:缺少 用户 字段"
+
+#: lib/iolog/iolog_legacy.c:107
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s:缺少 runas 用户 字段"
+
+#: lib/iolog/iolog_legacy.c:118
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s:缺少 runas 组 字段"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s 存在,但不是目录(0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:123 lib/iolog/iolog_mkdtemp.c:78
+#: logsrvd/iolog_writer.c:781 plugins/sudoers/timestamp.c:209
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "无法创建目录 %s"
+
+#: lib/iolog/iolog_mkdtemp.c:83 plugins/sudoers/visudo.c:753
+#: plugins/sudoers/visudo.c:787 plugins/sudoers/visudo.c:793
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "无法将 %s 的模式更改为 0%o"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "读取时序文件出错:%s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "无效的时序文件行:%s"
+
+#: logsrvd/iolog_writer.c:65
+#, c-format
+msgid "%s: protocol error: NULL key"
+msgstr "%s:协议错误:NULL 键"
+
+#: logsrvd/iolog_writer.c:69
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s:协议错误:%s 的错误类型"
+
+#: logsrvd/iolog_writer.c:74 logsrvd/logsrvd_local.c:109
+#: logsrvd/logsrvd_local.c:123 logsrvd/logsrvd_local.c:131
+#: logsrvd/logsrvd_local.c:149
+#, c-format
+msgid "%s: protocol error: NULL value found in %s"
+msgstr "%s:协议错误:%s 中找到了 NULL 值"
+
+#: logsrvd/iolog_writer.c:141 plugins/sudoers/logging.c:976
+#: plugins/sudoers/policy.c:591
+msgid "unable to generate UUID"
+msgstr "无法生成 UUID"
+
+#: logsrvd/iolog_writer.c:341 logsrvd/iolog_writer.c:346
+#: logsrvd/iolog_writer.c:351 logsrvd/iolog_writer.c:356
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s:协议错误:AcceptMessage 中 %s 缺失"
+
+#: logsrvd/iolog_writer.c:417
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s:无法格式化会话 id"
+
+#: logsrvd/iolog_writer.c:431 logsrvd/iolog_writer.c:445
+#: logsrvd/iolog_writer.c:459 logsrvd/iolog_writer.c:474
+#: logsrvd/iolog_writer.c:488 logsrvd/iolog_writer.c:502
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s:%s 未设置"
+
+#: logsrvd/iolog_writer.c:538 logsrvd/iolog_writer.c:545
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr "无法展开 iolog 路径 %s"
+
+#: logsrvd/iolog_writer.c:563
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr "无法创建 iolog 路径 %s"
+
+#: logsrvd/iolog_writer.c:593
+#, c-format
+msgid "invalid iofd %d"
+msgstr "无效的 iofd %d"
+
+#: logsrvd/iolog_writer.c:613
+#, c-format
+msgid "error closing iofd %d: %s"
+msgstr "关闭 iofd %d 时出错:%s"
+
+#: logsrvd/iolog_writer.c:633
+#, c-format
+msgid "error flushing iofd %d: %s"
+msgstr "冲刷 iofd %d 时出错:%s"
+
+#: logsrvd/iolog_writer.c:751
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "无效的 I/O 日志 %s:%s 被引用但不存在"
+
+#: logsrvd/iolog_writer.c:763 logsrvd/logsrvd_journal.c:382
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "%s:无法找到恢复点 [%lld, %ld]"
+
+#: logsrvd/iolog_writer.c:785 logsrvd/logsrvd_journal.c:425
+#: logsrvd/logsrvd_queue.c:115 logsrvd/tls_init.c:256
+#: plugins/sudoers/check.c:292 plugins/sudoers/cvtsudoers.c:730
+#: plugins/sudoers/cvtsudoers.c:751 plugins/sudoers/cvtsudoers.c:1431
+#: plugins/sudoers/cvtsudoers_csv.c:695 plugins/sudoers/cvtsudoers_json.c:898
+#: plugins/sudoers/cvtsudoers_ldif.c:709 plugins/sudoers/sudoers.c:1113
+#: plugins/sudoers/sudoers.c:1143 plugins/sudoers/sudoreplay.c:1469
+#: plugins/sudoers/timestamp.c:460 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:971
+#, c-format
+msgid "unable to open %s"
+msgstr "无法打开 %s"
+
+#: logsrvd/iolog_writer.c:797 logsrvd/logsrv_util.c:105
+#: logsrvd/logsrv_util.c:112 plugins/sudoers/sudoreplay.c:362
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "无法打开 %s/%s"
+
+#: logsrvd/iolog_writer.c:810
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "无法复制 %s/%s 到 %s/%s:%s"
+
+#: logsrvd/iolog_writer.c:839 logsrvd/logsrvd_journal.c:195
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "无法将 %s 重命名为 %s"
+
+#: logsrvd/logsrv_util.c:147 logsrvd/logsrv_util.c:176
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s:无法找到恢复点 [%lld, %ld]"
+
+#: logsrvd/logsrv_util.c:159
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "缺失 I/O 日志文件 %s/%s"
+
+#: logsrvd/logsrv_util.c:166
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s:无法向前查找 %zu"
+
+#: logsrvd/logsrvd.c:271 logsrvd/logsrvd_queue.c:135
+msgid "unable to connect to relay"
+msgstr "无法连接到中继"
+
+#: logsrvd/logsrvd.c:330 logsrvd/logsrvd_relay.c:842
+#, c-format
+msgid "server message too large: %zu"
+msgstr "服务器消息过大:%zu"
+
+#: logsrvd/logsrvd.c:422 logsrvd/logsrvd.c:545 logsrvd/logsrvd.c:631
+#: logsrvd/logsrvd.c:873 logsrvd/logsrvd.c:887 logsrvd/logsrvd.c:1049
+#: logsrvd/logsrvd.c:1174 logsrvd/logsrvd.c:1347 logsrvd/logsrvd.c:1365
+#: logsrvd/logsrvd.c:1464 logsrvd/logsrvd.c:1589 logsrvd/logsrvd.c:1773
+#: logsrvd/logsrvd_journal.c:494 logsrvd/logsrvd_local.c:238
+#: logsrvd/logsrvd_queue.c:164 logsrvd/logsrvd_relay.c:172
+#: logsrvd/logsrvd_relay.c:249 logsrvd/logsrvd_relay.c:253
+#: logsrvd/logsrvd_relay.c:389 logsrvd/logsrvd_relay.c:581
+#: logsrvd/logsrvd_relay.c:742 logsrvd/logsrvd_relay.c:1131
+#: logsrvd/sendlog.c:1291 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:216 plugins/sudoers/audit.c:278
+#: plugins/sudoers/iolog.c:1033 plugins/sudoers/iolog.c:1166
+#: plugins/sudoers/iolog.c:1264 plugins/sudoers/log_client.c:121
+#: plugins/sudoers/log_client.c:343 plugins/sudoers/log_client.c:359
+#: plugins/sudoers/log_client.c:407 plugins/sudoers/log_client.c:611
+#: plugins/sudoers/log_client.c:618 plugins/sudoers/log_client.c:1103
+#: plugins/sudoers/log_client.c:1385 plugins/sudoers/log_client.c:1426
+#: plugins/sudoers/log_client.c:1434 plugins/sudoers/log_client.c:1593
+#: plugins/sudoers/log_client.c:1711 plugins/sudoers/log_client.c:2040
+#: plugins/sudoers/log_client.c:2048 plugins/sudoers/logging.c:147
+#: plugins/sudoers/logging.c:205 plugins/sudoers/sudoreplay.c:522
+#: plugins/sudoers/sudoreplay.c:569 plugins/sudoers/sudoreplay.c:811
+#: plugins/sudoers/sudoreplay.c:923 plugins/sudoers/sudoreplay.c:1014
+#: plugins/sudoers/sudoreplay.c:1029 plugins/sudoers/sudoreplay.c:1036
+#: plugins/sudoers/sudoreplay.c:1043 plugins/sudoers/sudoreplay.c:1050
+#: plugins/sudoers/sudoreplay.c:1057 plugins/sudoers/sudoreplay.c:1184
+msgid "unable to add event to queue"
+msgstr "无法将事件添加到队列"
+
+#: logsrvd/logsrvd.c:446 logsrvd/logsrvd.c:483 logsrvd/logsrvd.c:515
+#: logsrvd/logsrvd.c:569 logsrvd/logsrvd.c:648 logsrvd/logsrvd.c:684
+#: logsrvd/logsrvd.c:720 logsrvd/logsrvd.c:756 logsrvd/logsrvd_relay.c:510
+#: logsrvd/logsrvd_relay.c:543
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr "未预期的状态 %d 对于 %s"
+
+#: logsrvd/logsrvd.c:447 logsrvd/logsrvd.c:484 logsrvd/logsrvd.c:516
+#: logsrvd/logsrvd.c:570 logsrvd/logsrvd.c:649 logsrvd/logsrvd.c:685
+#: logsrvd/logsrvd.c:721 logsrvd/logsrvd.c:757 logsrvd/logsrvd_relay.c:512
+#: logsrvd/logsrvd_relay.c:545
+msgid "state machine error"
+msgstr "状态机错误"
+
+#: logsrvd/logsrvd.c:453 logsrvd/logsrvd.c:454
+msgid "invalid AcceptMessage"
+msgstr "无效的 AcceptMessage"
+
+#: logsrvd/logsrvd.c:490 logsrvd/logsrvd.c:491
+msgid "invalid RejectMessage"
+msgstr "无效的 RejectMessage"
+
+#: logsrvd/logsrvd.c:522 logsrvd/logsrvd.c:523
+msgid "invalid ExitMessage"
+msgstr "无效的 ExitMessage"
+
+#: logsrvd/logsrvd.c:576 logsrvd/logsrvd.c:577
+msgid "invalid RestartMessage"
+msgstr "无效的 RestartMessage"
+
+#: logsrvd/logsrvd.c:611 logsrvd/logsrvd.c:612
+msgid "invalid AlertMessage"
+msgstr "无效的 AlertMessage"
+
+#: logsrvd/logsrvd.c:653 logsrvd/logsrvd.c:689 logsrvd/logsrvd.c:725
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s:未预期的 IoBuffer"
+
+#: logsrvd/logsrvd.c:654 logsrvd/logsrvd.c:690 logsrvd/logsrvd.c:726
+msgid "protocol error"
+msgstr "协议错误"
+
+#: logsrvd/logsrvd.c:660 logsrvd/logsrvd.c:661
+msgid "invalid IoBuffer"
+msgstr "无效的 IoBuffer"
+
+#: logsrvd/logsrvd.c:696 logsrvd/logsrvd.c:697
+msgid "invalid ChangeWindowSize"
+msgstr "无效的 ChangeWindowSize"
+
+#: logsrvd/logsrvd.c:732 logsrvd/logsrvd.c:733
+msgid "invalid CommandSuspend"
+msgstr "无效的 CommandSuspend"
+
+#: logsrvd/logsrvd.c:782 logsrvd/logsrvd_journal.c:293
+#: logsrvd/logsrvd_relay.c:652 logsrvd/sendlog.c:1192
+#: plugins/sudoers/log_client.c:1583
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "无法解包 %s,大小为 %zu"
+
+#: logsrvd/logsrvd.c:827 logsrvd/logsrvd_journal.c:367
+#: logsrvd/logsrvd_relay.c:676
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "未预期的 type_case 值 %d 在 %s 来自 %s"
+
+#: logsrvd/logsrvd.c:829
+msgid "unrecognized ClientMessage type"
+msgstr "无法识别的 ClientMessage 类型"
+
+#: logsrvd/logsrvd.c:919
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "写入客户端 %s 时超时"
+
+#: logsrvd/logsrvd.c:924 logsrvd/logsrvd_relay.c:914 logsrvd/sendlog.c:1395
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr "客户端 %s 缺失写缓冲"
+
+#: logsrvd/logsrvd.c:1020
+#, c-format
+msgid "timed out reading from client %s"
+msgstr "从客户端 %s 读取超时"
+
+#: logsrvd/logsrvd.c:1061 logsrvd/logsrvd_relay.c:777
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr "没有正确关闭 TLS 连接的情况下接收到了来自 %s 的 EOF"
+
+#: logsrvd/logsrvd.c:1105 logsrvd/logsrvd_relay.c:205 logsrvd/sendlog.c:322
+#: plugins/sudoers/log_client.c:721
+#, c-format
+msgid "client message too large: %zu"
+msgstr "客户端消息过大:%zu"
+
+#: logsrvd/logsrvd.c:1106 logsrvd/logsrvd_journal.c:256
+#: logsrvd/logsrvd_journal.c:257
+msgid "client message too large"
+msgstr "客户端消息过长"
+
+#: logsrvd/logsrvd.c:1124 logsrvd/logsrvd.c:1125
+msgid "invalid ClientMessage"
+msgstr "无效的 ClientMessage"
+
+#: logsrvd/logsrvd.c:1425
+msgid "unable to get remote IP addr"
+msgstr "无法获取远程 IP 地址"
+
+#: logsrvd/logsrvd.c:1456 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:281
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "无法将用户数据附加到 ssl 对象上:%s"
+
+#: logsrvd/logsrvd.c:1639 logsrvd/logsrvd.c:1992
+msgid "unable to setup listen socket"
+msgstr "无法设置监听套接字"
+
+#: logsrvd/logsrvd.c:1756
+#, c-format
+msgid "unexpected signal %d"
+msgstr "未预期的信号 %d"
+
+#: logsrvd/logsrvd.c:1894
+msgid "sudo log server"
+msgstr "sudo 日志服务器"
+
+#: logsrvd/logsrvd.c:1896 logsrvd/sendlog.c:121
+msgid "Options:"
+msgstr "选项:"
+
+#: logsrvd/logsrvd.c:1898
+msgid "path to configuration file"
+msgstr "配置文件路径"
+
+#: logsrvd/logsrvd.c:1900 logsrvd/sendlog.c:123
+msgid "display help message and exit"
+msgstr "显示帮助信息并退出"
+
+#: logsrvd/logsrvd.c:1902
+msgid "do not fork, run in the foreground"
+msgstr "不要进行 fork,在前台运行"
+
+#: logsrvd/logsrvd.c:1904
+msgid "percent chance connections will drop"
+msgstr "连接被丢弃的百分比概率"
+
+#: logsrvd/logsrvd.c:1906 logsrvd/sendlog.c:153
+msgid "display version information and exit"
+msgstr "显示版本信息并退出"
+
+#: logsrvd/logsrvd.c:1956 logsrvd/sendlog.c:1702
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "需要 Protobuf-C 1.3 版或更高版本"
+
+#: logsrvd/logsrvd.c:1972
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "无效的随机丢弃值:%s"
+
+#: logsrvd/logsrvd.c:1975 logsrvd/sendlog.c:1756
+#: plugins/sudoers/cvtsudoers.c:246 plugins/sudoers/sudoreplay.c:301
+#: plugins/sudoers/visudo.c:182
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s 版本 %s\n"
+
+#: logsrvd/logsrvd_conf.c:422 plugins/sudoers/check.c:353
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/policy.c:1264 plugins/sudoers/sudoers.c:505
+#: plugins/sudoers/sudoers.c:1372 plugins/sudoers/testsudoers.c:215
+#: plugins/sudoers/testsudoers.c:382
+#, c-format
+msgid "unknown user %s"
+msgstr "未知用户 %s"
+
+#: logsrvd/logsrvd_conf.c:439 plugins/sudoers/iolog.c:148
+#: plugins/sudoers/sudoers.c:510 plugins/sudoers/sudoers.c:1406
+#: plugins/sudoers/testsudoers.c:406
+#, c-format
+msgid "unknown group %s"
+msgstr "未知组 %s"
+
+#: logsrvd/logsrvd_conf.c:457
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr "无法解析 iolog 模式 %s"
+
+#: logsrvd/logsrvd_conf.c:474 logsrvd/logsrvd_conf.c:1243
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "用于 %s 的无效的值:%s"
+
+#: logsrvd/logsrvd_conf.c:527
+msgid "TLS not supported"
+msgstr "不支持 TLS"
+
+#: logsrvd/logsrvd_conf.c:549
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:622 logsrvd/logsrvd_conf.c:1032
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s:不是完全合格的路径"
+
+#: logsrvd/logsrvd_conf.c:951 logsrvd/logsrvd_conf.c:967
+#: logsrvd/logsrvd_conf.c:1676
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "未知的 syslog 设施 %s"
+
+#: logsrvd/logsrvd_conf.c:983 logsrvd/logsrvd_conf.c:999
+#: logsrvd/logsrvd_conf.c:1015 logsrvd/logsrvd_conf.c:1680
+#: logsrvd/logsrvd_conf.c:1684 logsrvd/logsrvd_conf.c:1688
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "位置的 syslog 优先级 %s"
+
+#: logsrvd/logsrvd_conf.c:1197
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d 不匹配的 '[':%s"
+
+#: logsrvd/logsrvd_conf.c:1203
+#, c-format
+msgid "%s:%d garbage after ']': %s"
+msgstr "%s:%d 多余内容出现在 '[' 之后:%s"
+
+#: logsrvd/logsrvd_conf.c:1215
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s:%d 无效的配置段:%s"
+
+#: logsrvd/logsrvd_conf.c:1223
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d 无效的配置行:%s"
+
+#: logsrvd/logsrvd_conf.c:1229
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d 期望的节名称:%s"
+
+#: logsrvd/logsrvd_conf.c:1251
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] 无效键:%s"
+
+#: logsrvd/logsrvd_conf.c:1281 plugins/sudoers/cvtsudoers.c:268
+#: plugins/sudoers/logging.c:1029
+#, c-format
+msgid "unable to open log file %s"
+msgstr "无法打开日志文件 %s"
+
+#: logsrvd/logsrvd_conf.c:1763
+msgid "unable to initialize server TLS context"
+msgstr "无法初始化服务器 TLS 上下文"
+
+#: logsrvd/logsrvd_conf.c:1783
+msgid "unable to initialize relay TLS context"
+msgstr "无法初始化中继 TLS 上下文"
+
+#: logsrvd/logsrvd_journal.c:146 logsrvd/logsrvd_journal.c:421
+#: logsrvd/logsrvd_journal.c:426
+msgid "unable to create journal file"
+msgstr "无法创建日志文件"
+
+#: logsrvd/logsrvd_journal.c:150 logsrvd/logsrvd_queue.c:109
+#: plugins/sudoers/visudo.c:1026
+#, c-format
+msgid "unable to lock %s"
+msgstr "无法锁定 %s"
+
+#: logsrvd/logsrvd_journal.c:153
+msgid "unable to lock journal file"
+msgstr "无法锁定日志文件"
+
+#: logsrvd/logsrvd_journal.c:161
+msgid "unable to open journal file"
+msgstr "无法打开日志文件"
+
+#: logsrvd/logsrvd_journal.c:182 logsrvd/logsrvd_journal.c:457
+#: logsrvd/logsrvd_journal.c:462
+msgid "unable to write journal file"
+msgstr "无法写入日志文件"
+
+#: logsrvd/logsrvd_journal.c:190 logsrvd/logsrvd_journal.c:197
+msgid "unable to rename journal file"
+msgstr "无法重命名日志文件"
+
+#: logsrvd/logsrvd_journal.c:244 logsrvd/logsrvd_journal.c:245
+#: logsrvd/logsrvd_journal.c:279 logsrvd/logsrvd_journal.c:280
+msgid "unexpected EOF reading journal file"
+msgstr "读取日志文件时未预期的 EOF"
+
+#: logsrvd/logsrvd_journal.c:248 logsrvd/logsrvd_journal.c:249
+#: logsrvd/logsrvd_journal.c:283 logsrvd/logsrvd_journal.c:284
+msgid "error reading journal file"
+msgstr "读取日志文件出错"
+
+#: logsrvd/logsrvd_journal.c:295 logsrvd/logsrvd_journal.c:381
+msgid "invalid journal file, unable to restart"
+msgstr "无效的日志文件,无法重新启动"
+
+#: logsrvd/logsrvd_journal.c:440
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "无法 seek 跳转到 [%lld, %ld](在日志文件 %s 中)"
+
+#: logsrvd/logsrvd_local.c:166
+#, c-format
+msgid "unexpected value_case %d in %s from %s"
+msgstr "未预期的 value_case 值 %d 在 %s 来自 %s"
+
+#: logsrvd/logsrvd_local.c:194
+msgid "error parsing AcceptMessage"
+msgstr "解析 AcceptMessage 出错"
+
+#: logsrvd/logsrvd_local.c:205
+msgid "error creating I/O log"
+msgstr "创建 I/O 日志出错"
+
+#: logsrvd/logsrvd_local.c:228
+msgid "error logging accept event"
+msgstr "记录接受事件时出错"
+
+#: logsrvd/logsrvd_local.c:267
+msgid "error parsing RejectMessage"
+msgstr "解析 RejectMessage 出错"
+
+#: logsrvd/logsrvd_local.c:291
+msgid "error logging reject event"
+msgstr "记录拒绝事件时出错"
+
+#: logsrvd/logsrvd_local.c:427 logsrvd/logsrvd_local.c:435
+msgid "error logging exit event"
+msgstr "记录退出事件时出错"
+
+#: logsrvd/logsrvd_local.c:492 logsrvd/logsrvd_local.c:493
+msgid "log is already complete, cannot be restarted"
+msgstr "日志已完成,无法重新启动"
+
+#: logsrvd/logsrvd_local.c:523
+msgid "unable to restart log"
+msgstr "无法重新启动 log"
+
+#: logsrvd/logsrvd_local.c:539
+msgid "error parsing AlertMessage"
+msgstr "解析 AlertMessage 出错"
+
+#: logsrvd/logsrvd_local.c:549
+msgid "error logging alert event"
+msgstr "记录警告事件时出错"
+
+#: logsrvd/logsrvd_local.c:585 logsrvd/logsrvd_local.c:648
+#: logsrvd/logsrvd_local.c:683
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr "无法格式化时间缓冲区,长度 %d"
+
+#: logsrvd/logsrvd_local.c:599 logsrvd/logsrvd_local.c:607
+#: logsrvd/logsrvd_local.c:655 logsrvd/logsrvd_local.c:690
+#: plugins/sudoers/sudoreplay.c:351
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s:%s"
+
+#: logsrvd/logsrvd_local.c:618
+msgid "randomly dropping connection"
+msgstr "随机丢弃连接"
+
+#: logsrvd/logsrvd_local.c:630
+msgid "error writing IoBuffer"
+msgstr "写入 IoBuffer 出错"
+
+#: logsrvd/logsrvd_local.c:665
+msgid "error writing ChangeWindowSize"
+msgstr "写入 ChangeWindowSize 出错"
+
+#: logsrvd/logsrvd_local.c:700
+msgid "error writing CommandSuspend"
+msgstr "写入 CommandSuspend 出错"
+
+#: logsrvd/logsrvd_relay.c:435
+msgid "TLS handshake with relay host failed"
+msgstr "与中继主机的 TLS 握手失败"
+
+#: logsrvd/logsrvd_relay.c:463
+msgid "unable to connect to relay host"
+msgstr "无法连接到中继主机"
+
+#: logsrvd/logsrvd_relay.c:518
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s:无效的 ServerHello,缺少 server_id"
+
+#: logsrvd/logsrvd_relay.c:520 logsrvd/sendlog.c:1096
+#: plugins/sudoers/log_client.c:1469
+msgid "invalid ServerHello"
+msgstr "无效的 ServerHello"
+
+#: logsrvd/logsrvd_relay.c:679
+msgid "unrecognized ServerMessage type"
+msgstr "无法识别的 ServerMessage 类型"
+
+#: logsrvd/logsrvd_relay.c:708
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr "从中继 %s 读取超时(%s)"
+
+#: logsrvd/logsrvd_relay.c:710
+msgid "timeout reading from relay"
+msgstr "从中继读取超时"
+
+#: logsrvd/logsrvd_relay.c:762
+msgid "relay host name does not match certificate"
+msgstr "中继主机名称与证书不匹配"
+
+#: logsrvd/logsrvd_relay.c:768 logsrvd/logsrvd_relay.c:782
+#: logsrvd/logsrvd_relay.c:789
+msgid "error reading from relay"
+msgstr "从中继读取出错"
+
+#: logsrvd/logsrvd_relay.c:810
+msgid "unable to read from relay"
+msgstr "无法从中继读取"
+
+#: logsrvd/logsrvd_relay.c:825 logsrvd/logsrvd_relay.c:943
+msgid "relay server closed connection"
+msgstr "中继服务器关闭了连接"
+
+#: logsrvd/logsrvd_relay.c:843
+msgid "server message too large"
+msgstr "服务器消息过大"
+
+#: logsrvd/logsrvd_relay.c:907
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr "写入中继 %s 时超时(%s)"
+
+#: logsrvd/logsrvd_relay.c:909
+msgid "timeout writing to relay"
+msgstr "写入中继时超时"
+
+#: logsrvd/logsrvd_relay.c:962 logsrvd/logsrvd_relay.c:969
+#: logsrvd/logsrvd_relay.c:981
+msgid "error writing to relay"
+msgstr "写入中继时出错"
+
+#: logsrvd/sendlog.c:119
+msgid "send sudo I/O log to remote server"
+msgstr "将 sudo I/O 日志发送到远程服务器"
+
+#: logsrvd/sendlog.c:125
+msgid "only send an accept event (no I/O)"
+msgstr "只发送一个 accept 事件(没有 I/O)"
+
+#: logsrvd/sendlog.c:128
+msgid "certificate bundle file to verify server's cert against"
+msgstr ""
+
+#: logsrvd/sendlog.c:130
+msgid "certificate file for TLS handshake"
+msgstr "用于 TLS 握手的证书文件"
+
+#: logsrvd/sendlog.c:133
+msgid "host to send logs to"
+msgstr "主机发送日志到"
+
+#: logsrvd/sendlog.c:135
+msgid "remote ID of I/O log to be resumed"
+msgstr ""
+
+#: logsrvd/sendlog.c:138
+msgid "private key file"
+msgstr "私钥文件"
+
+#: logsrvd/sendlog.c:140
+msgid "do not verify server certificate"
+msgstr "不要验证服务器证书"
+
+#: logsrvd/sendlog.c:143
+msgid "port to use when connecting to host"
+msgstr "连接到主机时使用的端口"
+
+#: logsrvd/sendlog.c:145
+msgid "restart previous I/O log transfer"
+msgstr "重新开始先前的 I/O 日志传输"
+
+#: logsrvd/sendlog.c:147
+msgid "reject the command with the given reason"
+msgstr ""
+
+#: logsrvd/sendlog.c:149
+msgid "stop transfer after reaching this time"
+msgstr ""
+
+#: logsrvd/sendlog.c:151
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr ""
+
+#: logsrvd/sendlog.c:176 plugins/sudoers/log_client.c:453
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "无法查找 %s:%s:%s"
+
+#: logsrvd/sendlog.c:214
+msgid "unable to get server IP addr"
+msgstr "无法获取服务器 IP 地址"
+
+#: logsrvd/sendlog.c:300 plugins/sudoers/sudoreplay.c:871
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "无法读取 %s/%s:%s"
+
+#: logsrvd/sendlog.c:1020 plugins/sudoers/iolog.c:951
+#: plugins/sudoers/iolog.c:1026
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "未预期的 I/O 事件 %d"
+
+#: logsrvd/sendlog.c:1073 logsrvd/sendlog.c:1090 logsrvd/sendlog.c:1124
+#: plugins/sudoers/log_client.c:1118 plugins/sudoers/log_client.c:1395
+#: plugins/sudoers/log_client.c:1463 plugins/sudoers/log_client.c:1502
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s:未预期的状态 %d"
+
+#: logsrvd/sendlog.c:1160 plugins/sudoers/log_client.c:1551
+#, c-format
+msgid "error message received from server: %s"
+msgstr "从服务器收到了错误消息:%s"
+
+#: logsrvd/sendlog.c:1173 plugins/sudoers/log_client.c:1564
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "从服务器收到了中止消息:%s"
+
+#: logsrvd/sendlog.c:1232 plugins/sudoers/log_client.c:1614
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s:未预期的 type_case 值 %d"
+
+#: logsrvd/sendlog.c:1261
+msgid "timeout reading from server"
+msgstr "从服务器读取超时"
+
+#: logsrvd/sendlog.c:1310 plugins/sudoers/log_client.c:1730
+msgid "host name does not match certificate"
+msgstr "主机名称与证书不匹配"
+
+#: logsrvd/sendlog.c:1343
+msgid "premature EOF"
+msgstr "过早的文件结束"
+
+#: logsrvd/sendlog.c:1356 plugins/sudoers/log_client.c:1777
+#, c-format
+msgid "server message too large: %u"
+msgstr "服务器消息过大:%u"
+
+#: logsrvd/sendlog.c:1412
+msgid "timeout writing to server"
+msgstr "写入服务器时超时"
+
+#: logsrvd/sendlog.c:1779
+msgid "both restart point and iolog ID must be specified"
+msgstr ""
+
+#: logsrvd/sendlog.c:1783
+msgid "a restart point may not be set when no I/O is sent"
+msgstr ""
+
+#: logsrvd/sendlog.c:1859
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "过早地退出,状态码为 %d"
+
+#: logsrvd/sendlog.c:1860
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr ""
+
+#: logsrvd/sendlog.c:1862
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr ""
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:315
+msgid "TLS handshake timeout occurred"
+msgstr "TLS 握手超时"
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:337 plugins/sudoers/log_client.c:353
+msgid "unable to set event"
+msgstr "无法设置事件"
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "TLS 连接失败:%s"
+
+#: logsrvd/tls_client.c:196
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "无法分配 ssl 对象:%s"
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "无法将套接字附加给 ssl 对象:%s"
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr "无法初始化 TLS 上下文"
+
+#: logsrvd/tls_init.c:138 logsrvd/tls_init.c:146
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "无法将 TLS 1.2 密码套件设置为 %s: %s"
+
+#: logsrvd/tls_init.c:166 logsrvd/tls_init.c:174
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "无法将 TLS 1.3 密码套件设置为 %s: %s"
+
+#: logsrvd/tls_init.c:206 logsrvd/tls_init.c:227
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "无法设置 diffie-hellman 参数:%s"
+
+#: logsrvd/tls_init.c:283
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "无法创建 TLS 上下文:%s"
+
+#: logsrvd/tls_init.c:290
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "无法将最低协议版本设置为 TLS 1.2:%s"
+
+#: plugins/sudoers/audit.c:269 plugins/sudoers/audit.c:429
+#: plugins/sudoers/log_client.c:951 plugins/sudoers/log_client.c:1000
+#: plugins/sudoers/log_client.c:1049 plugins/sudoers/log_client.c:1175
+#: plugins/sudoers/logging.c:591 plugins/sudoers/logging.c:689
+#: plugins/sudoers/logging.c:792 plugins/sudoers/logging.c:983
+#: plugins/sudoers/policy.c:124
+msgid "unable to get time of day"
+msgstr "无法获取时间"
+
+#: plugins/sudoers/auth/aix_auth.c:280
+#, c-format
+msgid "unable to change password for %s"
+msgstr "无法为 %s 更改密码"
+
+#: plugins/sudoers/auth/bsdauth.c:74
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "无法获取用户 %s 的登录类别(login class)"
+
+#: plugins/sudoers/auth/bsdauth.c:79
+msgid "unable to begin bsd authentication"
+msgstr "无法开始 bsd 认证"
+
+#: plugins/sudoers/auth/bsdauth.c:87
+msgid "invalid authentication type"
+msgstr "无效的认证类型"
+
+#: plugins/sudoers/auth/bsdauth.c:96
+msgid "unable to initialize BSD authentication"
+msgstr "无法初始化 bsd 认证"
+
+#: plugins/sudoers/auth/bsdauth.c:186
+msgid "your account has expired"
+msgstr "您的账户已过期"
+
+#: plugins/sudoers/auth/bsdauth.c:188
+msgid "approval failed"
+msgstr "批准失败"
+
+#: plugins/sudoers/auth/fwtk.c:61
+msgid "unable to read fwtk config"
+msgstr "无法读取 fwtk 配置"
+
+#: plugins/sudoers/auth/fwtk.c:66
+msgid "unable to connect to authentication server"
+msgstr "无法连接到认证服务器"
+
+#: plugins/sudoers/auth/fwtk.c:72 plugins/sudoers/auth/fwtk.c:97
+#: plugins/sudoers/auth/fwtk.c:129
+msgid "lost connection to authentication server"
+msgstr "丢失了到认证服务器的连接"
+
+#: plugins/sudoers/auth/fwtk.c:76
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"认证服务器错误:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:115
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s:无法将主体(principal)转换为字符串(“%s”):%s"
+
+#: plugins/sudoers/auth/kerb5.c:164
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s:无法解析“%s”:%s"
+
+#: plugins/sudoers/auth/kerb5.c:173
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s:无法解析凭据缓存:%s"
+
+#: plugins/sudoers/auth/kerb5.c:222
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s:无法分配选项:%s"
+
+#: plugins/sudoers/auth/kerb5.c:237
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s:无法获取凭据:%s"
+
+#: plugins/sudoers/auth/kerb5.c:250
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s:无法初始化凭据缓存:%s"
+
+#: plugins/sudoers/auth/kerb5.c:253
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s:无法在缓存中储存凭据:%s"
+
+#: plugins/sudoers/auth/kerb5.c:317
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s:无法获取主机主体(principal):%s"
+
+#: plugins/sudoers/auth/kerb5.c:331
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s:无法验证目标!可能遭到了攻击!:%s"
+
+#: plugins/sudoers/auth/pam.c:224
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "无法初始化 PAM:%s"
+
+#: plugins/sudoers/auth/pam.c:337
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "PAM 认证出错:%s"
+
+#: plugins/sudoers/auth/pam.c:356
+msgid "account validation failure, is your account locked?"
+msgstr "账户验证失败,您的账户是不是上锁了?"
+
+#: plugins/sudoers/auth/pam.c:367
+msgid "Account or password is expired, reset your password and try again"
+msgstr "账户或密码过期,重置您的密码并重试"
+
+#: plugins/sudoers/auth/pam.c:373
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "无法更改过期的密码:%s"
+
+#: plugins/sudoers/auth/pam.c:384
+msgid "Password expired, contact your system administrator"
+msgstr "密码过期,联系您的系统管理员"
+
+#: plugins/sudoers/auth/pam.c:389
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "账户过期,或 PAM 配置缺少 sudo 使用的“account”节,联系您的系统管理员"
+
+#: plugins/sudoers/auth/pam.c:397 plugins/sudoers/auth/pam.c:402
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "PAM 账户管理出错:%s"
+
+#: plugins/sudoers/auth/rfc1938.c:99 plugins/sudoers/visudo.c:271
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "%s 数据库中没有您"
+
+#: plugins/sudoers/auth/securid5.c:75
+msgid "failed to initialise the ACE API library"
+msgstr "初始化 ACE API 库失败"
+
+#: plugins/sudoers/auth/securid5.c:106
+msgid "unable to contact the SecurID server"
+msgstr "无法联络 SecurID 服务器"
+
+#: plugins/sudoers/auth/securid5.c:115
+msgid "User ID locked for SecurID Authentication"
+msgstr "为进行 SecurID 认证,已锁定用户 ID"
+
+#: plugins/sudoers/auth/securid5.c:119 plugins/sudoers/auth/securid5.c:170
+msgid "invalid username length for SecurID"
+msgstr "SecurID 的用户名长度无效"
+
+#: plugins/sudoers/auth/securid5.c:123 plugins/sudoers/auth/securid5.c:175
+msgid "invalid Authentication Handle for SecurID"
+msgstr "SecurID 的认证句柄无效"
+
+#: plugins/sudoers/auth/securid5.c:127
+msgid "SecurID communication failed"
+msgstr "SecurID 通讯失败"
+
+#: plugins/sudoers/auth/securid5.c:131 plugins/sudoers/auth/securid5.c:218
+msgid "unknown SecurID error"
+msgstr "未知的 SecurID 错误"
+
+#: plugins/sudoers/auth/securid5.c:165
+msgid "invalid passcode length for SecurID"
+msgstr "无效的 SecurID 密码长度"
+
+#: plugins/sudoers/auth/sia.c:69 plugins/sudoers/auth/sia.c:126
+msgid "unable to initialize SIA session"
+msgstr "无法初始化 SIA 会话"
+
+#: plugins/sudoers/auth/sudo_auth.c:135
+msgid "invalid authentication methods"
+msgstr "无效的认证方法"
+
+#: plugins/sudoers/auth/sudo_auth.c:137
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "编译进 sudo 的认证方法无效!您不能混用独立和非独立认证。"
+
+#: plugins/sudoers/auth/sudo_auth.c:258 plugins/sudoers/auth/sudo_auth.c:310
+msgid "no authentication methods"
+msgstr "无认证方法"
+
+#: plugins/sudoers/auth/sudo_auth.c:260
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "sudo 编译时没有加入任何认证方法!如果您想关闭认证,使用 --disable-authentication 配置选项。"
+
+#: plugins/sudoers/auth/sudo_auth.c:312
+msgid "Unable to initialize authentication methods."
+msgstr "无法初始化认证方法。"
+
+#: plugins/sudoers/auth/sudo_auth.c:486
+msgid "Authentication methods:"
+msgstr "认证方法:"
+
+#: plugins/sudoers/bsm_audit.c:123 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "无法确定审核条件"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:277
+msgid "unable to commit audit record"
+msgstr "无法提交审核记录"
+
+#: plugins/sudoers/check.c:285
+#, fuzzy, c-format
+#| msgid "error reading timing file: %s"
+msgid "error reading lecture file %s"
+msgstr "读取时序文件出错:%s"
+
+#: plugins/sudoers/check.c:288
+#, fuzzy, c-format
+#| msgid "%s is not a regular file"
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "%s 不是常规文件"
+
+#: plugins/sudoers/check.c:301
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"我们信任您已经从系统管理员那里了解了日常注意事项。\n"
+"总结起来无外乎这三点:\n"
+"\n"
+" #1) 尊重别人的隐私。\n"
+" #2) 输入前要先考虑(后果和风险)。\n"
+" #3) 权力越大,责任越大。\n"
+"\n"
+
+#: plugins/sudoers/check.c:348 plugins/sudoers/check.c:358
+#: plugins/sudoers/parse.c:64 plugins/sudoers/sudoers.c:920
+#: plugins/sudoers/sudoers.c:941 plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "未知的用户 ID %u"
+
+#: plugins/sudoers/check_aliases.c:99 plugins/sudoers/defaults.c:1279
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s:%s\n"
+
+#: plugins/sudoers/check_aliases.c:133
+#, c-format
+msgid "cycle in %s \"%s\""
+msgstr "在 %s“%s”中循环"
+
+#: plugins/sudoers/check_aliases.c:136
+#, fuzzy, c-format
+#| msgid "Error: %s:%d:%d: %s \"%s\" referenced but not defined"
+msgid "%s \"%s\" referenced but not defined"
+msgstr "错误:%s:%d:%d:引用了 %s“%s”但尚未定义"
+
+#: plugins/sudoers/cvtsudoers.c:209
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "顺序增量:%s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:228
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "起始顺序:%s:%s"
+
+#: plugins/sudoers/cvtsudoers.c:238
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "顺序填充:%s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:248 plugins/sudoers/visudo.c:184
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s 语法版本 %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:277 plugins/sudoers/testsudoers.c:159
+#, c-format
+msgid "unsupported input format %s"
+msgstr "不支持的输入格式 %s"
+
+#: plugins/sudoers/cvtsudoers.c:295
+#, c-format
+msgid "unsupported output format %s"
+msgstr "不支持的输出格式 %s"
+
+#: plugins/sudoers/cvtsudoers.c:385
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s:输入和输出文件不能相同"
+
+#: plugins/sudoers/cvtsudoers.c:399 plugins/sudoers/sudoers.c:166
+#: plugins/sudoers/sudoers.c:222 plugins/sudoers/testsudoers.c:254
+#: plugins/sudoers/visudo.c:280 plugins/sudoers/visudo.c:650
+#: plugins/sudoers/visudo.c:975
+msgid "unable to initialize sudoers default values"
+msgstr "无法初始化 sudoers 默认值"
+
+#: plugins/sudoers/cvtsudoers.c:525 plugins/sudoers/ldap_conf.c:434
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s:%s:%s:%s"
+
+#: plugins/sudoers/cvtsudoers.c:584
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s:未知的关键词 %s"
+
+#: plugins/sudoers/cvtsudoers.c:630
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "无效的默认值类型:%s"
+
+#: plugins/sudoers/cvtsudoers.c:653
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "无效的压缩类型:%s"
+
+#: plugins/sudoers/cvtsudoers.c:694 plugins/sudoers/cvtsudoers.c:710
+#, c-format
+msgid "invalid filter: %s"
+msgstr "无效的过滤器:%s"
+
+#: plugins/sudoers/cvtsudoers.c:754 plugins/sudoers/visudo.c:980
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "解析 %s 文件失败,未知错误"
+
+#: plugins/sudoers/cvtsudoers.c:1478 plugins/sudoers/sudoreplay.c:1145
+#: plugins/sudoers/timestamp.c:343 plugins/sudoers/timestamp.c:346
+#, c-format
+msgid "unable to write to %s"
+msgstr "无法写入 %s"
+
+#: plugins/sudoers/cvtsudoers.c:1506
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s - 转换 sudoers 文件格式\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1508
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"选项:\n"
+" -b, --base=dn 用于 sudo LDAP 查询的基础 DN\n"
+" -c, --config=conf_file 指向配置文件的路径\n"
+" -d, --defaults=deftypes 只转换指定类型的默认值\n"
+" -e, --expand-aliases 在转换时展开别名\n"
+" -f, --output-format=format 设置输出格式:JSON、LDIF 或 sudoers\n"
+" -i, --input-format=format 设置输入格式:LDIF 或 sudoers\n"
+" -I, --increment=num 每个 sudoOrder 的增加量\n"
+" -h, --help 显示帮助消息并退出\n"
+" -m, --match=filter 只转换与过滤器匹配的条目\n"
+" -M, --match-local 让匹配过滤器使用 passwd 和 group 数据库\n"
+" -o, --output=output_file 将转换后的 sudoers 写入 output_file\n"
+" -O, --order-start=num 第一个 sudoOrder 的起点\n"
+" -p, --prune-matches 清理不匹配的用户、组和主机\n"
+" -P, --padding=num sudoOrder 的增加基数\n"
+" -s, --suppress=sections 压缩某些部分的输出\n"
+" -V, --version 显示版本信息并退出"
+
+#: plugins/sudoers/cvtsudoers_csv.c:452 plugins/sudoers/cvtsudoers_csv.c:466
+#: plugins/sudoers/cvtsudoers_json.c:657 plugins/sudoers/cvtsudoers_json.c:672
+#: plugins/sudoers/cvtsudoers_ldif.c:347 plugins/sudoers/cvtsudoers_ldif.c:360
+#: plugins/sudoers/ldap.c:510
+msgid "unable to get GMT time"
+msgstr "无法获取 GMT 时间"
+
+#: plugins/sudoers/cvtsudoers_csv.c:457 plugins/sudoers/cvtsudoers_csv.c:471
+#: plugins/sudoers/cvtsudoers_json.c:662 plugins/sudoers/cvtsudoers_json.c:677
+#: plugins/sudoers/cvtsudoers_ldif.c:352 plugins/sudoers/cvtsudoers_ldif.c:365
+#: plugins/sudoers/ldap.c:518
+msgid "unable to format timestamp"
+msgstr "无法格式化时间戳"
+
+#: plugins/sudoers/cvtsudoers_json.c:480 plugins/sudoers/cvtsudoers_json.c:515
+#: plugins/sudoers/cvtsudoers_json.c:728
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d:未知的默认条目“%s”"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:661
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "sudoers 条目过多,最多为 %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:704
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "没有设置 SUDOERS_BASE 环境变量,并且没有指定 -b 选项。"
+
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, fuzzy, c-format
+#| msgid "%s:%d no value specified for \"%s\""
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr "%s:%d 没有给“%s”指定值"
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr "无法找到别名 %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, c-format
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr "%s:%d:%d:重命名别名 %s 为 %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr "%s:%d:%d:移除重复别名 %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, fuzzy, c-format
+#| msgid "%s:%d invalid Defaults type 0x%x for option \"%s\""
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr "%1$s:%2$d 选项“%4$s”的默认类型 0x%3$x 无效"
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:1088
+#, fuzzy, c-format
+#| msgid "%s:%d no value specified for \"%s\""
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr "%s:%d 没有给“%s”指定值"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1182
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:56
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "若使用了 syslog,用于记录日志的 syslog 设施:%s"
+
+#: plugins/sudoers/def_data.c:60
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "用户认证成功时使用的 syslog 优先级:%s"
+
+#: plugins/sudoers/def_data.c:64
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "用户认证不成功时使用的 syslog 优先级:%s"
+
+#: plugins/sudoers/def_data.c:68
+msgid "Put OTP prompt on its own line"
+msgstr "将 OPT 提示放在独自的行中"
+
+#: plugins/sudoers/def_data.c:72
+msgid "Ignore '.' in $PATH"
+msgstr "忽略 $PATH 中的“.”"
+
+#: plugins/sudoers/def_data.c:76
+msgid "Always send mail when sudo is run"
+msgstr "在运行 sudo 时总是发送邮件"
+
+#: plugins/sudoers/def_data.c:80
+msgid "Send mail if user authentication fails"
+msgstr "在用户认证失败时发送邮件"
+
+#: plugins/sudoers/def_data.c:84
+msgid "Send mail if the user is not in sudoers"
+msgstr "在用户不在 sudoers 列表中时发送邮件"
+
+#: plugins/sudoers/def_data.c:88
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "在用户不在此主机的 sudoers 列表中时发送邮件"
+
+#: plugins/sudoers/def_data.c:92
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "在用户不允许执行某个命令时发送邮件"
+
+#: plugins/sudoers/def_data.c:96
+msgid "Send mail if the user tries to run a command"
+msgstr "在用户尝试执行某个命令时发送邮件"
+
+#: plugins/sudoers/def_data.c:100
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "对每个用户/终端组合使用独立的时间戳"
+
+#: plugins/sudoers/def_data.c:104
+msgid "Lecture user the first time they run sudo"
+msgstr "在用户第一次运行 sudo 时向他致辞"
+
+#: plugins/sudoers/def_data.c:108
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "包含 sudo 致辞的文件:%s"
+
+#: plugins/sudoers/def_data.c:112
+msgid "Require users to authenticate by default"
+msgstr "默认要求用户认证"
+
+#: plugins/sudoers/def_data.c:116
+msgid "Root may run sudo"
+msgstr "root 可以运行 sudo"
+
+#: plugins/sudoers/def_data.c:120
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "将主机名记录在(非 syslog)的日志文件中"
+
+#: plugins/sudoers/def_data.c:124
+msgid "Log the year in the (non-syslog) log file"
+msgstr "将年份记录在(非 syslog)的日志文件中"
+
+#: plugins/sudoers/def_data.c:128
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "如果不带参数调用 sudo,启动一个 shell"
+
+#: plugins/sudoers/def_data.c:132
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "若使用 -s 选项启动 shell,将 $HOME 设为目标用户的主目录"
+
+#: plugins/sudoers/def_data.c:136
+msgid "Always set $HOME to the target user's home directory"
+msgstr "总是将 $HOME 设为目标用户的主目录"
+
+#: plugins/sudoers/def_data.c:140
+msgid "Allow some information gathering to give useful error messages"
+msgstr "允许收集一些信息,以提供有用的错误消息"
+
+#: plugins/sudoers/def_data.c:144
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "要求 sudoers 文件中包含完全限定的主机名"
+
+#: plugins/sudoers/def_data.c:148
+msgid "Insult the user when they enter an incorrect password"
+msgstr "在用户输入错误密码时对他们进行(玩笑式的)嘲讽"
+
+#: plugins/sudoers/def_data.c:152
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "只允许拥有终端的用户执行 sudo"
+
+#: plugins/sudoers/def_data.c:156
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo 将优先考虑 EDITOR 环境变量"
+
+#: plugins/sudoers/def_data.c:160
+msgid "Prompt for root's password, not the users's"
+msgstr "询问 root 用户的密码而非用户的密码"
+
+#: plugins/sudoers/def_data.c:164
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "询问 runas_default 用户的密码,而非用户密码"
+
+#: plugins/sudoers/def_data.c:168
+msgid "Prompt for the target user's password, not the users's"
+msgstr "询问目标用户的密码,而非用户密码"
+
+#: plugins/sudoers/def_data.c:172
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "应用目标用户登录类别中的默认设置,如果没有设置的话"
+
+#: plugins/sudoers/def_data.c:176
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "设置 LOGNAME 和 USER 环境变量"
+
+#: plugins/sudoers/def_data.c:180
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "只将有效用户 ID 设为目标用户的,而不是实际用户 ID"
+
+#: plugins/sudoers/def_data.c:184
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "不将组向量初始化为目标用户的"
+
+#: plugins/sudoers/def_data.c:188
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "日志文件折行的长度(0 则不折行):%u"
+
+#: plugins/sudoers/def_data.c:192
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "认证时间戳延时:%.1f 分钟"
+
+#: plugins/sudoers/def_data.c:196
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "密码提示延时:%.1f 分钟"
+
+#: plugins/sudoers/def_data.c:200
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "输入密码的尝试次数:%u"
+
+#: plugins/sudoers/def_data.c:204
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "要使用的 umask,或 0777 使用用户的:0%o"
+
+#: plugins/sudoers/def_data.c:208
+#, c-format
+msgid "Path to log file: %s"
+msgstr "日志文件路径:%s"
+
+#: plugins/sudoers/def_data.c:212
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "邮件程序路径:%s"
+
+#: plugins/sudoers/def_data.c:216
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "邮件程序标志:%s"
+
+#: plugins/sudoers/def_data.c:220
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "发送邮件的地址:%s"
+
+#: plugins/sudoers/def_data.c:224
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "接收邮件的地址:%s"
+
+#: plugins/sudoers/def_data.c:228
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "邮件消息的主题行:%s"
+
+#: plugins/sudoers/def_data.c:232
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "密码错误消息:%s"
+
+#: plugins/sudoers/def_data.c:236
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "致辞(lecture)状态文件夹的路径:%s"
+
+#: plugins/sudoers/def_data.c:240
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "认证时间戳文件夹的路径:%s"
+
+#: plugins/sudoers/def_data.c:244
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "认证时间戳的所有者:%s"
+
+#: plugins/sudoers/def_data.c:248
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "此组的用户不要求密码和 PATH:%s"
+
+#: plugins/sudoers/def_data.c:252
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "默认密码提示:%s"
+
+#: plugins/sudoers/def_data.c:256
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "如果设置,密码提示将覆盖各种情况下的系统提示。"
+
+#: plugins/sudoers/def_data.c:260
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "运行命令的默认用户:%s"
+
+#: plugins/sudoers/def_data.c:264
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "覆盖用户的 $PATH 变量的值:%s"
+
+#: plugins/sudoers/def_data.c:268
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "visudo 所使用的编辑器的路径:%s"
+
+#: plugins/sudoers/def_data.c:272
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "何时为“list”伪命令请求密码:%s"
+
+#: plugins/sudoers/def_data.c:276
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "何时为“verify”伪命令请求密码:%s"
+
+#: plugins/sudoers/def_data.c:280
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "预加载替代 exec 函数的 sudo_noexec 库"
+
+#: plugins/sudoers/def_data.c:284
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "如果 LDAP 目录有效,是不是忽略本地的 sudoers 文件"
+
+#: plugins/sudoers/def_data.c:288
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr ">= %d 的文件描述符将会在执行命令前关闭"
+
+#: plugins/sudoers/def_data.c:292
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "如果设置,用户可以通过 -C 选项覆盖“closefrom”的值"
+
+#: plugins/sudoers/def_data.c:296
+msgid "Allow users to set arbitrary environment variables"
+msgstr "允许用户设置任意的环境变量"
+
+#: plugins/sudoers/def_data.c:300
+msgid "Reset the environment to a default set of variables"
+msgstr "将环境重设为默认的变量集"
+
+#: plugins/sudoers/def_data.c:304
+msgid "Environment variables to check for safety:"
+msgstr "要检查安全性的环境变量:"
+
+#: plugins/sudoers/def_data.c:308
+msgid "Environment variables to remove:"
+msgstr "要移除的环境变量:"
+
+#: plugins/sudoers/def_data.c:312
+msgid "Environment variables to preserve:"
+msgstr "要保留的环境变量:"
+
+#: plugins/sudoers/def_data.c:316
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "在新的安全环境中使用的 SELinux 角色:%s"
+
+#: plugins/sudoers/def_data.c:320
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "在新的安全环境中使用的 SELinux 类型:%s"
+
+#: plugins/sudoers/def_data.c:324
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "sudo 特定环境文件的路径:%s"
+
+#: plugins/sudoers/def_data.c:328
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "受限的 sudo 特定环境文件的路径:%s"
+
+#: plugins/sudoers/def_data.c:332
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "解析 sudoers 时使用的区域设置:%s"
+
+#: plugins/sudoers/def_data.c:336
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "允许 sudo 询问密码,即使它不可见"
+
+#: plugins/sudoers/def_data.c:340
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "用户在询问密码窗口输入时提供视觉反馈"
+
+#: plugins/sudoers/def_data.c:344
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "使用不太精确但不访问文件系统的较快通配方法"
+
+#: plugins/sudoers/def_data.c:348
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "sudoers 中指定的 umask 会覆盖用户的,即使它允许的权限更多"
+
+#: plugins/sudoers/def_data.c:352
+msgid "Log user's input for the command being run"
+msgstr "记录用户在所执行命令中的输入"
+
+#: plugins/sudoers/def_data.c:356
+msgid "Log the command's standard input if not connected to a terminal"
+msgstr "记录命令的标准输入内容,如果它未连接终端的话"
+
+#: plugins/sudoers/def_data.c:360
+msgid "Log the user's terminal input for the command being run"
+msgstr "记录用户在所执行命令中的终端输入"
+
+#: plugins/sudoers/def_data.c:364
+msgid "Log the output of the command being run"
+msgstr "记录所执行命令的输出"
+
+#: plugins/sudoers/def_data.c:368
+msgid "Log the command's standard output if not connected to a terminal"
+msgstr "记录命令的标准输出内容,如果它未连接终端的话"
+
+#: plugins/sudoers/def_data.c:372
+msgid "Log the command's standard error if not connected to a terminal"
+msgstr "记录命令的标准错误内容,如果它未连接终端的话"
+
+#: plugins/sudoers/def_data.c:376
+msgid "Log the terminal output of the command being run"
+msgstr "记录所执行命令的终端输出"
+
+#: plugins/sudoers/def_data.c:380
+msgid "Compress I/O logs using zlib"
+msgstr "使用 zlib 压缩 I/O 日志"
+
+#: plugins/sudoers/def_data.c:384
+msgid "Always run commands in a pseudo-tty"
+msgstr "总是在伪终端中运行命令"
+
+#: plugins/sudoers/def_data.c:388
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "用于非 Unix 组支持的插件:%s"
+
+#: plugins/sudoers/def_data.c:392
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "用于保存输入/输出日志的目录:%s"
+
+#: plugins/sudoers/def_data.c:396
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "用于保存输入/输出日志的文件:%s"
+
+#: plugins/sudoers/def_data.c:400
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "在分配伪终端时向 utmp/utmpx 文件中添加一条记录"
+
+#: plugins/sudoers/def_data.c:404
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "将 utmp 中的用户设为 runas 用户,而不是调用用户"
+
+#: plugins/sudoers/def_data.c:408
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "允许权限的集合:%s"
+
+#: plugins/sudoers/def_data.c:412
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "限制权限的集合:%s"
+
+#: plugins/sudoers/def_data.c:416
+msgid "Run commands on a pty in the background"
+msgstr "在后台的伪终端上运行命令"
+
+#: plugins/sudoers/def_data.c:420
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "要使用的 PAM 服务名称:%s"
+
+#: plugins/sudoers/def_data.c:424
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "用于登录 shell 的 PAM 服务名称:%s"
+
+#: plugins/sudoers/def_data.c:428
+#, fuzzy, c-format
+#| msgid "PAM service name to use for login shells: %s"
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr "用于登录 shell 的 PAM 服务名称:%s"
+
+#: plugins/sudoers/def_data.c:432
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "尝试为目标用户建立 PAM 凭据"
+
+#: plugins/sudoers/def_data.c:436
+msgid "Create a new PAM session for the command to run in"
+msgstr "创建一个新的 PAM 会话来运行该命令"
+
+#: plugins/sudoers/def_data.c:440
+msgid "Perform PAM account validation management"
+msgstr "执行 PAM 账户验证管理"
+
+#: plugins/sudoers/def_data.c:444
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "最大 I/O 日志序列号:%s"
+
+#: plugins/sudoers/def_data.c:448
+msgid "Enable sudoers netgroup support"
+msgstr "启用 support netgroup 支持"
+
+#: plugins/sudoers/def_data.c:452
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "在使用 sudoedit 编辑文件时检查上级目录是否可写"
+
+#: plugins/sudoers/def_data.c:456
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "使用 sudoedit 编辑文件时循符号连接(定位到原文件)"
+
+#: plugins/sudoers/def_data.c:460
+msgid "Query the group plugin for unknown system groups"
+msgstr "通过 组 插件查询未知的系统组"
+
+#: plugins/sudoers/def_data.c:464
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "基于整个元组(用户、主机和域)来匹配网络组"
+
+#: plugins/sudoers/def_data.c:468
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "即使 sudo 无法写入审核日志也允许命令运行"
+
+#: plugins/sudoers/def_data.c:472
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "即使 sudo 无法写入 I/O 日志也允许命令运行"
+
+#: plugins/sudoers/def_data.c:476
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "即使 sudo 无法写入日志文件也允许命令允许"
+
+#: plugins/sudoers/def_data.c:480
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "解析 sudoers 中的组并与 组 ID (而不是名字) 匹配"
+
+#: plugins/sudoers/def_data.c:484
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "大于此数值的日志条目会分为多条 syslog 消息:%u"
+
+#: plugins/sudoers/def_data.c:488
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "将拥有 I/O 日志文件的用户:%s"
+
+#: plugins/sudoers/def_data.c:492
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "将拥有 I/O 日志文件的组:%s"
+
+#: plugins/sudoers/def_data.c:496
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "I/O 日志文件要使用的文件模式:0%o"
+
+#: plugins/sudoers/def_data.c:500
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "根据文件描述符执行命令,而非根据路径:%s"
+
+#: plugins/sudoers/def_data.c:504
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "忽略 sudoers 中未知的 Defaults 条目而非产生警告"
+
+#: plugins/sudoers/def_data.c:508
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "超过指定时间后终止命令(秒):%u"
+
+#: plugins/sudoers/def_data.c:512
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "允许用户在命令行中指定超时时间"
+
+#: plugins/sudoers/def_data.c:516
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "立即冲洗(flush) I/O 日志数据而非将其缓存"
+
+#: plugins/sudoers/def_data.c:520
+msgid "Include the process ID when logging via syslog"
+msgstr "通过 syslog 登录时包含进程 ID"
+
+#: plugins/sudoers/def_data.c:524
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "认证时间戳记录的类型:%s"
+
+#: plugins/sudoers/def_data.c:528
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "认证失败消息:%s"
+
+#: plugins/sudoers/def_data.c:532
+msgid "Ignore case when matching user names"
+msgstr "在匹配 用户 名时忽略大小写"
+
+#: plugins/sudoers/def_data.c:536
+msgid "Ignore case when matching group names"
+msgstr "在匹配 组 名时忽略大小写"
+
+#: plugins/sudoers/def_data.c:540
+msgid "Log when a command is allowed by sudoers"
+msgstr "命令被 sudoers 允许时的日志"
+
+#: plugins/sudoers/def_data.c:544
+msgid "Log when a command is denied by sudoers"
+msgstr "命令被 sudoers 拒绝时的日志"
+
+#: plugins/sudoers/def_data.c:548
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:552
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Sudo 日志服务器超时秒数:%u"
+
+#: plugins/sudoers/def_data.c:556
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:560
+#, fuzzy, c-format
+#| msgid "Path to the sudo-specific environment file: %s"
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "sudo 特定环境文件的路径:%s"
+
+#: plugins/sudoers/def_data.c:564
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "到 sudoers 证书文件的路径:%s"
+
+#: plugins/sudoers/def_data.c:568
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "到 sudoers 私钥文件的路径:%s"
+
+#: plugins/sudoers/def_data.c:572
+msgid "Verify that the log server's certificate is valid"
+msgstr "验证日志服务器证书有效性"
+
+#: plugins/sudoers/def_data.c:576
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:580
+msgid "Only permit running commands as a user with a valid shell"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:584
+msgid "Set the pam remote user to the user running sudo"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:588
+msgid "Set the pam remote host to the local host name"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:592
+#, fuzzy, c-format
+#| msgid "File descriptors >= %d will be closed before executing a command"
+msgid "Working directory to change to before executing the command: %s"
+msgstr ">= %d 的文件描述符将会在执行命令前关闭"
+
+#: plugins/sudoers/def_data.c:596
+#, fuzzy, c-format
+#| msgid "File descriptors >= %d will be closed before executing a command"
+msgid "Root directory to change to before executing the command: %s"
+msgstr ">= %d 的文件描述符将会在执行命令前关闭"
+
+#: plugins/sudoers/def_data.c:600
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "要产生日志的格式:%s"
+
+#: plugins/sudoers/def_data.c:604
+msgid "Enable SELinux RBAC support"
+msgstr "启用 SELinux RBAC 支持"
+
+#: plugins/sudoers/def_data.c:608
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "在 sudo 第一次运行时要创建的文件的路径:%s"
+
+#: plugins/sudoers/def_data.c:612
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "截取未来的命令并对其施加 sudoers 限制"
+
+#: plugins/sudoers/def_data.c:616
+msgid "Log sub-commands run by the original command"
+msgstr "记录原始命令所执行的子命令"
+
+#: plugins/sudoers/def_data.c:620
+msgid "Log the exit status of commands"
+msgstr "记录所执行命令的返回状态值"
+
+#: plugins/sudoers/def_data.c:624
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:628
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:632
+#, c-format
+msgid "The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:636
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:640
+#, c-format
+msgid "The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:644
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:648
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:652
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:656
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:660
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:664
+#, c-format
+msgid "The maximum number of processes that the user may run simultaneously: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:668
+#, c-format
+msgid "The maximum size to which the process's resident set size may grow (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:672
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:676
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr "即便在非交互模式下也尝试进行认证"
+
+#: plugins/sudoers/def_data.c:680
+msgid "Store plaintext passwords in I/O log input"
+msgstr "在 I/O 日志输入中存储纯文本密码"
+
+#: plugins/sudoers/def_data.c:684
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr "尝试匹配密码提示符时要使用的正则表达式列表"
+
+#: plugins/sudoers/def_data.c:688
+#, c-format
+msgid "The mechanism used by the intercept and log_subcmds options: %s"
+msgstr ""
+
+#: plugins/sudoers/def_data.c:692
+msgid "Attempt to verify the command and arguments after execution"
+msgstr "在执行之后尝试验证命令和参数"
+
+#: plugins/sudoers/def_data.c:696
+#, c-format
+msgid "AppArmor profile to use in the new security context: %s"
+msgstr "在新的安全环境中使用的 SELinux 配置文件:%s"
+
+#: plugins/sudoers/defaults.c:191
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "未知的默认条目“%s”"
+
+#: plugins/sudoers/defaults.c:234
+#, c-format
+msgid "no value specified for \"%s\""
+msgstr "没有给“%s”指定值"
+
+#: plugins/sudoers/defaults.c:243
+#, fuzzy, c-format
+#| msgid "%s: invalid Defaults type 0x%x for option \"%s\""
+msgid "invalid operator \"%c=\" for \"%s\""
+msgstr "%1$s:选项“%3$s”的默认类型 0x%2$x 无效"
+
+#: plugins/sudoers/defaults.c:275
+#, fuzzy, c-format
+#| msgid "%s: option \"%s\" does not take a value"
+msgid "option \"%s\" does not take a value"
+msgstr "%s:“%s”选项不接受值"
+
+#: plugins/sudoers/defaults.c:299
+#, fuzzy, c-format
+#| msgid "%s: invalid Defaults type 0x%x for option \"%s\""
+msgid "invalid Defaults type 0x%x for option \"%s\""
+msgstr "%1$s:选项“%3$s”的默认类型 0x%2$x 无效"
+
+#: plugins/sudoers/defaults.c:306
+#, fuzzy, c-format
+#| msgid "%s: value \"%s\" is invalid for option \"%s\""
+msgid "value \"%s\" is invalid for option \"%s\""
+msgstr "%s:值“%s”对选项“%s”无效"
+
+#: plugins/sudoers/defaults.c:1128 plugins/sudoers/policy.c:208
+#: plugins/sudoers/policy.c:217
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr "“%s”的路径名过长"
+
+#: plugins/sudoers/defaults.c:1134
+#, c-format
+msgid "values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "“%s”的值必须以“/”、“~”或“*”开头"
+
+#: plugins/sudoers/defaults.c:1141
+#, c-format
+msgid "values for \"%s\" must start with a '/'"
+msgstr "“%s”的值必须以“/”开头"
+
+#: plugins/sudoers/env.c:426
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv:envp 损坏,长度不符"
+
+#: plugins/sudoers/env.c:1109
+msgid "unable to rebuild the environment"
+msgstr "无法重建环境"
+
+#: plugins/sudoers/env.c:1183
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "对不起,您无权设置以下环境变量:%s"
+
+#: plugins/sudoers/filedigest.c:49
+#, c-format
+msgid "unsupported digest type %d for %s"
+msgstr "%2$s 的摘要类型 %1$d 不支持"
+
+#: plugins/sudoers/filedigest.c:78
+#, c-format
+msgid "%s: read error"
+msgstr "%s:写错误"
+
+#: plugins/sudoers/group_plugin.c:169
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s 必须属于用户 ID %d"
+
+#: plugins/sudoers/group_plugin.c:173
+#, c-format
+msgid "%s must only be writable by owner"
+msgstr "%s 必须只对所有者可写"
+
+#: plugins/sudoers/group_plugin.c:185 plugins/sudoers/sssd.c:576
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "无法加载 %s:%s"
+
+#: plugins/sudoers/group_plugin.c:197
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "无法在 %s 中找到符号“group_plugin”"
+
+#: plugins/sudoers/group_plugin.c:202
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s:不兼容的组插件主版本号 %d,应为 %d"
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "无法解析 IP 地址列表“%s”"
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "无法解析网络掩码“%s”"
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "本地 IP 地址和网络掩码对:\n"
+
+#: plugins/sudoers/iolog.c:685
+msgid "unable to update sequence file"
+msgstr "无法更新序列文件"
+
+#: plugins/sudoers/iolog.c:719 plugins/sudoers/iolog.c:909
+#: plugins/sudoers/iolog.c:1071 plugins/sudoers/iolog.c:1078
+#: plugins/sudoers/iolog.c:1199 plugins/sudoers/iolog.c:1206
+#: plugins/sudoers/iolog.c:1305 plugins/sudoers/iolog.c:1312
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "无法写入 I/O 日志文件:%s"
+
+#: plugins/sudoers/iolog.c:727
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "无法创建 %s/%s"
+
+#: plugins/sudoers/iolog.c:957
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s:内部错误,事件 %d 的 I/O 日志文件未打开"
+
+#: plugins/sudoers/iolog.c:1056 plugins/sudoers/iolog.c:1184
+#: plugins/sudoers/iolog.c:1289 plugins/sudoers/timestamp.c:879
+#: plugins/sudoers/timestamp.c:971 plugins/sudoers/visudo.c:552
+#: plugins/sudoers/visudo.c:558
+msgid "unable to read the clock"
+msgstr "无法读取时钟"
+
+#: plugins/sudoers/iolog.c:1281 plugins/sudoers/log_client.c:1193
+#: plugins/sudoers/log_client.c:1203 plugins/sudoers/log_client.c:1207
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s:内部错误,信号 %d 无效"
+
+#: plugins/sudoers/ldap.c:177 plugins/sudoers/ldap_conf.c:292
+msgid "starttls not supported when using ldaps"
+msgstr "使用 ldaps 时不支持 starttls"
+
+#: plugins/sudoers/ldap.c:248
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "无法初始化 SSL 证书和密钥数据库:%s"
+
+#: plugins/sudoers/ldap.c:251
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "要使用 SSL,您必须在 %s 中设置 TLS_CERT"
+
+#: plugins/sudoers/ldap.c:1712
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "无法初始化 LDAP:%s"
+
+#: plugins/sudoers/ldap.c:1749
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "指定了 start_tls,但 LDAP 库不支持 ldap_start_tls_s() 或 ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:1886 plugins/sudoers/parse_ldif.c:748
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "无效的 sudoOrder 属性:%s"
+
+#: plugins/sudoers/ldap_conf.c:200
+#, c-format
+msgid "%s: port too large"
+msgstr "%s:端口过大"
+
+#: plugins/sudoers/ldap_conf.c:261
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "不支持的 LDAP URI 类型:%s"
+
+#: plugins/sudoers/ldap_conf.c:288
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "无法混合 ldap 和 ldaps URI"
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "重复的 sudoOption: %s%s%s"
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "无法转换 sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "无法打开审核系统"
+
+#: plugins/sudoers/linux_audit.c:103
+msgid "unable to send audit message"
+msgstr "无法发送审核消息"
+
+#: plugins/sudoers/log_client.c:125 plugins/sudoers/log_client.c:412
+#: plugins/sudoers/log_client.c:1440 plugins/sudoers/log_client.c:2056
+msgid "error in event loop"
+msgstr "事件循环中出错"
+
+#: plugins/sudoers/log_client.c:205
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "创建新的 SSL_CTX 对象失败:%s"
+
+#: plugins/sudoers/log_client.c:230
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "无法加载数字证书认证机构集合(CA bundle) %s"
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "无法加载证书 %s"
+
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "unable to load private key %s"
+msgstr "无法加载私钥 %s"
+
+#: plugins/sudoers/log_client.c:275
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "无法分配 ssl 对象:%s"
+
+#: plugins/sudoers/log_client.c:364 plugins/sudoers/log_client.c:369
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "到 %s:%s 的 TLS 连接失败:%s"
+
+#: plugins/sudoers/log_client.c:543
+msgid "TLS initialization was unsuccessful"
+msgstr "TLS 初始化不成功"
+
+#: plugins/sudoers/log_client.c:553
+msgid "TLS handshake was unsuccessful"
+msgstr "TLS 握手不成功"
+
+#: plugins/sudoers/log_client.c:1211
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s:内部错误,无效的退出状态 %d"
+
+#: plugins/sudoers/log_client.c:1740 plugins/sudoers/log_client.c:1764
+msgid "lost connection to log server"
+msgstr "丢失了到日志服务器的连接"
+
+#: plugins/sudoers/log_client.c:1841
+msgid "missing write buffer"
+msgstr "缺失写缓冲"
+
+#: plugins/sudoers/log_client.c:1995
+msgid "unable to connect to log server"
+msgstr "无法连接到日志服务器"
+
+#: plugins/sudoers/logging.c:290
+msgid "user NOT in sudoers"
+msgstr "用户不在 sudoers 中"
+
+#: plugins/sudoers/logging.c:292
+msgid "user NOT authorized on host"
+msgstr "用户未获得此主机上的授权"
+
+#: plugins/sudoers/logging.c:294
+msgid "command not allowed"
+msgstr "命令禁止使用"
+
+#: plugins/sudoers/logging.c:315
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr "%s 不是 sudoers 文件。\n"
+
+#: plugins/sudoers/logging.c:318
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr "%s 无权在 %s 上运行 sudo。\n"
+
+#: plugins/sudoers/logging.c:321
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "对不起,用户 %s 不能在 %s 上运行 sudo。\n"
+
+#: plugins/sudoers/logging.c:324
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n"
+msgstr "对不起,用户 %1$s 无权以 %5$s%6$s%7$s 的身份在 %8$s 上执行 %2$s%3$s%4$s。\n"
+
+#: plugins/sudoers/logging.c:334
+msgid "This incident has been reported to the administrator.\n"
+msgstr "该事件已报告给管理员。\n"
+
+#: plugins/sudoers/logging.c:365 plugins/sudoers/sudoers.c:648
+#: plugins/sudoers/sudoers.c:650 plugins/sudoers/sudoers.c:652
+#: plugins/sudoers/sudoers.c:654 plugins/sudoers/sudoers.c:805
+#: plugins/sudoers/sudoers.c:807
+#, c-format
+msgid "%s: command not found"
+msgstr "%s:找不到命令"
+
+#: plugins/sudoers/logging.c:367 plugins/sudoers/sudoers.c:644
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"忽略在“.”中找到的“%s”\n"
+"请使用“sudo ./%s”,如果这是您想运行的“%s”。"
+
+#: plugins/sudoers/logging.c:387
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u 次错误密码尝试"
+
+#: plugins/sudoers/logging.c:477
+msgid "authentication failure"
+msgstr "认证失败"
+
+#: plugins/sudoers/logging.c:516 plugins/sudoers/logging.c:535
+msgid "a password is required"
+msgstr "需要密码"
+
+#: plugins/sudoers/logging.c:799 plugins/sudoers/logging.c:811
+msgid "problem parsing sudoers"
+msgstr "解析 sudoers 时出现问题"
+
+#: plugins/sudoers/logging.c:873 plugins/sudoers/logging.c:885
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr "%s:%d:%d: %s"
+
+#: plugins/sudoers/logging.c:1062
+#, c-format
+msgid "unable to write log file: %s"
+msgstr "无法写入日志文件: %s"
+
+#: plugins/sudoers/match_digest.c:112
+#, c-format
+msgid "digest for %s (%s) bad length %zu, expected %zu"
+msgstr "%s(%s) 的摘要具有错误的长度 %zu,期望为 %zu"
+
+#: plugins/sudoers/match_digest.c:131
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "%s(%s) 的摘要不是 %s 形式"
+
+#: plugins/sudoers/parse.c:591
+#, c-format
+msgid ""
+"\n"
+"LDAP Role: %s\n"
+msgstr ""
+"\n"
+"LDAP 角色:%s\n"
+
+#: plugins/sudoers/parse.c:594
+msgid ""
+"\n"
+"Sudoers entry:\n"
+msgstr ""
+"\n"
+"Sudoers 条目:\n"
+
+#: plugins/sudoers/parse.c:596
+msgid " RunAsUsers: "
+msgstr " RunAs 用户:"
+
+#: plugins/sudoers/parse.c:611
+msgid " RunAsGroups: "
+msgstr " RunAs 组:"
+
+#: plugins/sudoers/parse.c:621
+msgid " Options: "
+msgstr " 选项:"
+
+#: plugins/sudoers/parse.c:685
+msgid " Commands:\n"
+msgstr " 命令:\n"
+
+#: plugins/sudoers/parse.c:876
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "匹配 %2$s 上 %1$s 的默认条目:\n"
+
+#: plugins/sudoers/parse.c:894
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "%s Runas 和命令特定的默认值:\n"
+
+#: plugins/sudoers/parse.c:912
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "用户 %s 可以在 %s 上运行以下命令:\n"
+
+#: plugins/sudoers/parse.c:927
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "用户 %s 无权在 %s 上运行 sudo。\n"
+
+#: plugins/sudoers/parse_ldif.c:618
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "将忽略不完整的 sudoRole:cn:%s"
+
+#: plugins/sudoers/parse_ldif.c:678
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "无效的 LDIF 属性:%s"
+
+#: plugins/sudoers/policy.c:81 plugins/sudoers/policy.c:112
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "sudo 前端设置了无效的 %.*s"
+
+#: plugins/sudoers/policy.c:358 plugins/sudoers/testsudoers.c:268
+msgid "unable to parse network address list"
+msgstr "无法解析网络地址列表"
+
+#: plugins/sudoers/policy.c:526
+msgid "user name not set by sudo front-end"
+msgstr "用户名未通过 sudo 前端设置"
+
+#: plugins/sudoers/policy.c:530
+msgid "user-ID not set by sudo front-end"
+msgstr "用户 ID 未通过 sudo 前端设置"
+
+#: plugins/sudoers/policy.c:534
+msgid "group-ID not set by sudo front-end"
+msgstr "组 ID 未通过 sudo 前端设置"
+
+#: plugins/sudoers/policy.c:538
+msgid "host name not set by sudo front-end"
+msgstr "主机名未通过 sudo 前端设置"
+
+#: plugins/sudoers/policy.c:730
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "无效的工作目录:%s"
+
+#: plugins/sudoers/policy.c:914
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "无法的 chroot 目录:%s"
+
+#: plugins/sudoers/policy.c:1101 plugins/sudoers/visudo.c:259
+#: plugins/sudoers/visudo.c:902
+#, c-format
+msgid "unable to execute %s"
+msgstr "无法执行 %s"
+
+#: plugins/sudoers/policy.c:1171 plugins/sudoers/policy.c:1208
+#: plugins/sudoers/policy.c:1230 plugins/sudoers/policy.c:1256
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s:sudo 前端无效的模式标志位:0x%x"
+
+#: plugins/sudoers/policy.c:1292
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Sudoers 策略插件版本 %s\n"
+
+#: plugins/sudoers/policy.c:1294
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Sudoers 文件语法版本 %d\n"
+
+#: plugins/sudoers/policy.c:1298
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Sudoers 路径:%s\n"
+
+#: plugins/sudoers/policy.c:1301
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "nsswitch 路径:%s\n"
+
+#: plugins/sudoers/policy.c:1303
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "ldap.conf 路径:%s\n"
+
+#: plugins/sudoers/policy.c:1304
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "ldap.secret 路径:%s\n"
+
+#: plugins/sudoers/policy.c:1337
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "无法注册类型为 %d 的钩子(hook)(版本 %d.%d)"
+
+#: plugins/sudoers/policy.c:1355
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "无法取消注册类型为 %d 的钩子(hook)(版本 %d.%d)"
+
+#: plugins/sudoers/pwutil.c:222 plugins/sudoers/pwutil.c:240
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "无法缓存用户 ID %u"
+
+#: plugins/sudoers/pwutil.c:234
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "无法缓存用户 ID %u,已存在"
+
+#: plugins/sudoers/pwutil.c:294 plugins/sudoers/pwutil.c:312
+#: plugins/sudoers/pwutil.c:375 plugins/sudoers/pwutil.c:420
+#, c-format
+msgid "unable to cache user %s"
+msgstr "无法缓存用户 %s"
+
+#: plugins/sudoers/pwutil.c:307
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "无法缓存用户 %s,已存在"
+
+#: plugins/sudoers/pwutil.c:539 plugins/sudoers/pwutil.c:557
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "无法缓存组 ID %u"
+
+#: plugins/sudoers/pwutil.c:551
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "无法缓存组 ID %u,已存在"
+
+#: plugins/sudoers/pwutil.c:605 plugins/sudoers/pwutil.c:623
+#: plugins/sudoers/pwutil.c:684 plugins/sudoers/pwutil.c:733
+#, c-format
+msgid "unable to cache group %s"
+msgstr "无法缓存组 %s"
+
+#: plugins/sudoers/pwutil.c:618
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "无法缓存组 %s,已存在"
+
+#: plugins/sudoers/pwutil.c:880 plugins/sudoers/pwutil.c:931
+#: plugins/sudoers/pwutil.c:981 plugins/sudoers/pwutil.c:1033
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "无法缓存组列表 %s,已存在"
+
+#: plugins/sudoers/pwutil.c:886 plugins/sudoers/pwutil.c:936
+#: plugins/sudoers/pwutil.c:987 plugins/sudoers/pwutil.c:1038
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "无法缓存组列表 %s"
+
+#: plugins/sudoers/pwutil.c:925
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "无法对 %s 解析组"
+
+#: plugins/sudoers/pwutil.c:1027
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "无法解析 %s 的组 ID"
+
+#: plugins/sudoers/set_perms.c:114 plugins/sudoers/set_perms.c:445
+#: plugins/sudoers/set_perms.c:852 plugins/sudoers/set_perms.c:1162
+#: plugins/sudoers/set_perms.c:1460
+msgid "perm stack overflow"
+msgstr "权限堆栈上溢"
+
+#: plugins/sudoers/set_perms.c:125 plugins/sudoers/set_perms.c:376
+#: plugins/sudoers/set_perms.c:456 plugins/sudoers/set_perms.c:719
+#: plugins/sudoers/set_perms.c:863 plugins/sudoers/set_perms.c:1086
+#: plugins/sudoers/set_perms.c:1173 plugins/sudoers/set_perms.c:1393
+#: plugins/sudoers/set_perms.c:1471 plugins/sudoers/set_perms.c:1562
+msgid "perm stack underflow"
+msgstr "权限堆栈下溢"
+
+#: plugins/sudoers/set_perms.c:185 plugins/sudoers/set_perms.c:503
+#: plugins/sudoers/set_perms.c:1227 plugins/sudoers/set_perms.c:1505
+msgid "unable to change to root gid"
+msgstr "无法切换为 root 组 ID"
+
+#: plugins/sudoers/set_perms.c:276 plugins/sudoers/set_perms.c:600
+#: plugins/sudoers/set_perms.c:995 plugins/sudoers/set_perms.c:1304
+msgid "unable to change to runas gid"
+msgstr "无法切换为 runas 组 ID"
+
+#: plugins/sudoers/set_perms.c:281 plugins/sudoers/set_perms.c:605
+#: plugins/sudoers/set_perms.c:1000 plugins/sudoers/set_perms.c:1309
+msgid "unable to set runas group vector"
+msgstr "无法设置 runas 组向量"
+
+#: plugins/sudoers/set_perms.c:292 plugins/sudoers/set_perms.c:616
+#: plugins/sudoers/set_perms.c:1009 plugins/sudoers/set_perms.c:1318
+msgid "unable to change to runas uid"
+msgstr "无法切换为 runas 用户 ID"
+
+#: plugins/sudoers/set_perms.c:310 plugins/sudoers/set_perms.c:634
+#: plugins/sudoers/set_perms.c:1025 plugins/sudoers/set_perms.c:1334
+msgid "unable to change to sudoers gid"
+msgstr "无法切换为 sudoers 组 ID"
+
+#: plugins/sudoers/set_perms.c:363 plugins/sudoers/set_perms.c:706
+#: plugins/sudoers/set_perms.c:1073 plugins/sudoers/set_perms.c:1380
+#: plugins/sudoers/set_perms.c:1549
+msgid "too many processes"
+msgstr "进程过多"
+
+#: plugins/sudoers/solaris_audit.c:61
+msgid "unable to get current working directory"
+msgstr "无法获取当前工作目录"
+
+#: plugins/sudoers/solaris_audit.c:69
+#, c-format
+msgid "truncated audit path user_cmnd: %s"
+msgstr "截断的审核路径 user_cmnd:%s"
+
+#: plugins/sudoers/solaris_audit.c:76
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "截断的审核路径 argv[0]:%s"
+
+#: plugins/sudoers/sssd.c:579
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "无法初始化 SSS 资源。您的计算机上安装 SSSD 了吗?"
+
+#: plugins/sudoers/sssd.c:587 plugins/sudoers/sssd.c:596
+#: plugins/sudoers/sssd.c:605 plugins/sudoers/sssd.c:614
+#: plugins/sudoers/sssd.c:623
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "无法在 %s 中找到符号“%s”"
+
+#: plugins/sudoers/sudoers.c:263
+#, fuzzy, c-format
+#| msgid "unable to parse gids for %s"
+msgid "unable to get defaults from %s"
+msgstr "无法解析 %s 的组 ID"
+
+#: plugins/sudoers/sudoers.c:270
+msgid "no valid sudoers sources found, quitting"
+msgstr "没有找到有效的 sudoers 资源,退出"
+
+#: plugins/sudoers/sudoers.c:346
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "用户不允许将根目录设置为 %s"
+
+#: plugins/sudoers/sudoers.c:348
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "您无权和 %s 一起使用 -R 选项"
+
+#: plugins/sudoers/sudoers.c:373
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "用户不允许将目录变更为 %s"
+
+#: plugins/sudoers/sudoers.c:374
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "您无权和 %s 一起使用 -D 选项"
+
+#: plugins/sudoers/sudoers.c:401
+msgid "no command specified"
+msgstr "未指定命令"
+
+#: plugins/sudoers/sudoers.c:426
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers 指定 root 不允许执行 sudo"
+
+#: plugins/sudoers/sudoers.c:476
+msgid "user not allowed to override closefrom limit"
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:477
+msgid "you are not permitted to use the -C option"
+msgstr "您无权使用 -C 选项"
+
+#: plugins/sudoers/sudoers.c:537
+#, c-format
+msgid "timestamp owner (%s): No such user"
+msgstr "时间戳所有者(%s):无此用户"
+
+#: plugins/sudoers/sudoers.c:552
+msgid "no tty"
+msgstr "无终端"
+
+#: plugins/sudoers/sudoers.c:553
+msgid "sorry, you must have a tty to run sudo"
+msgstr "抱歉,您必须拥有一个终端来执行 sudo"
+
+#: plugins/sudoers/sudoers.c:560
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "用户 %s 的无效 shell:%s"
+
+#: plugins/sudoers/sudoers.c:643
+msgid "command in current directory"
+msgstr "当前目录中的命令"
+
+#: plugins/sudoers/sudoers.c:658
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr "“cd”是 shell 内置命令,它无法直接运行。"
+
+#: plugins/sudoers/sudoers.c:660
+msgid "the -s option may be used to run a privileged shell."
+msgstr "-s 选项必须在特权 shell 中使用。"
+
+#: plugins/sudoers/sudoers.c:662
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr ""
+
+#: plugins/sudoers/sudoers.c:671
+msgid "user not allowed to set a command timeout"
+msgstr "不允许用户设置超时时间"
+
+#: plugins/sudoers/sudoers.c:673
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "抱歉,您无权设置超时时间"
+
+#: plugins/sudoers/sudoers.c:681
+msgid "user not allowed to preserve the environment"
+msgstr "不允许用户保留环境"
+
+#: plugins/sudoers/sudoers.c:683
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "抱歉,您无权保留环境"
+
+#: plugins/sudoers/sudoers.c:1073
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "sudoedit 无需经由 sudo 运行"
+
+#: plugins/sudoers/sudoers.c:1118 plugins/sudoers/sudoreplay.c:1584
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "无法读取 %s"
+
+#: plugins/sudoers/sudoers.c:1147 plugins/sudoers/visudo.c:1064
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s 不是常规文件"
+
+#: plugins/sudoers/sudoers.c:1151 plugins/sudoers/timestamp.c:263 toke.l:1247
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s 属于用户 ID %u,应为 %u"
+
+#: plugins/sudoers/sudoers.c:1155 plugins/sudoers/timestamp.c:270 toke.l:1252
+#, c-format
+msgid "%s is world writable"
+msgstr "%s 可被任何人写"
+
+#: plugins/sudoers/sudoers.c:1159 plugins/sudoers/timestamp.c:275 toke.l:1255
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s 属于组 ID %u,应为 %u"
+
+#: plugins/sudoers/sudoers.c:1194
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "只有 root 才能使用“-c %s”"
+
+#: plugins/sudoers/sudoers.c:1213
+#, c-format
+msgid "unknown login class %s"
+msgstr "未知的登录类别 %s"
+
+#: plugins/sudoers/sudoers.c:1300 plugins/sudoers/sudoers.c:1315
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "无法解析主机:%s"
+
+#: plugins/sudoers/sudoreplay.c:259
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "无效的过滤器选项:%s"
+
+#: plugins/sudoers/sudoreplay.c:275
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "无效的最大等待:%s"
+
+#: plugins/sudoers/sudoreplay.c:298
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "无法的速度系数:%s"
+
+#: plugins/sudoers/sudoreplay.c:333
+#, c-format
+msgid "invalid time offset %s"
+msgstr "无效的时间偏移量 %s"
+
+#: plugins/sudoers/sudoreplay.c:342
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:347
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/时序:%s"
+
+#: plugins/sudoers/sudoreplay.c:375
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "回放 sudo 会话:%s"
+
+#: plugins/sudoers/sudoreplay.c:637
+msgid "unable to set tty to raw mode"
+msgstr "无法将终端设为原始模式"
+
+#: plugins/sudoers/sudoreplay.c:688
+msgid "Warning: your terminal is too small to properly replay the log.\n"
+msgstr "警告:您的终端尺寸太小,不能正常地回放日志。\n"
+
+#: plugins/sudoers/sudoreplay.c:689
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "日志的几何尺寸为 %dx%d,您终端的几何尺寸为 %dx%d。"
+
+#: plugins/sudoers/sudoreplay.c:717
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "回放完成,请按任意键返回终端。"
+
+#: plugins/sudoers/sudoreplay.c:1219 plugins/sudoers/sudoreplay.c:1249
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "有歧义的表达式“%s”"
+
+#: plugins/sudoers/sudoreplay.c:1271
+msgid "unmatched ')' in expression"
+msgstr "表达式中的“)”不匹配"
+
+#: plugins/sudoers/sudoreplay.c:1275
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "未知的搜索词“%s”"
+
+#: plugins/sudoers/sudoreplay.c:1290
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s 需要参数"
+
+#: plugins/sudoers/sudoreplay.c:1300
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "无法解析日期“%s”"
+
+#: plugins/sudoers/sudoreplay.c:1309
+msgid "unmatched '(' in expression"
+msgstr "表达式中的“(”不匹配"
+
+#: plugins/sudoers/sudoreplay.c:1311
+msgid "illegal trailing \"or\""
+msgstr "非法的结尾字符“or”"
+
+#: plugins/sudoers/sudoreplay.c:1313
+msgid "illegal trailing \"!\""
+msgstr "非法的结尾字符“!”"
+
+#: plugins/sudoers/sudoreplay.c:1371
+#, c-format
+msgid "unknown search type %d"
+msgstr "未知的搜索类型 %d"
+
+#: plugins/sudoers/sudoreplay.c:1650
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "用法:%s [-hnRS] [-d 目录] [-m 数值] [-s 数值] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1652
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "用法:%s [-h] [-d 目录] -l [搜索表达式]\n"
+
+#: plugins/sudoers/sudoreplay.c:1666
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - 回放 sudo 会话记录\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1668
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"选项:\n"
+" -d, --directory=目录 指定会话日志目录\n"
+" -f, --filter=过滤器 指定要显示的 I/O 类型\n"
+" -h, --help 显示帮助信息并退出\n"
+" -l, --list 列出可用会话 ID,可加表达式限定\n"
+" -m, --max-wait=数值 事件间等待的最大秒数\n"
+" -n, --non-interactive 不进行提示,会话由标准输出送出\n"
+" -R, --no-resize 不要尝试改变终端尺寸\n"
+" -S, --suspend-wait 在命令挂起时等待\n"
+" -s, --speed=数值 加速或减慢输出\n"
+" -V, --version 显示版本信息并退出"
+
+#: plugins/sudoers/testsudoers.c:344
+msgid "\thost unmatched"
+msgstr "\t主机不匹配"
+
+#: plugins/sudoers/testsudoers.c:347
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"命令允许"
+
+#: plugins/sudoers/testsudoers.c:348
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"命令被拒"
+
+#: plugins/sudoers/testsudoers.c:348
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"命令不匹配"
+
+#: plugins/sudoers/timestamp.c:354 plugins/sudoers/timestamp.c:693
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "无法将时间戳文件截短为 %lld 字节"
+
+#: plugins/sudoers/timestamp.c:890
+msgid "ignoring time stamp from the future"
+msgstr "将忽略超前的时间戳"
+
+#: plugins/sudoers/timestamp.c:913
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "时间戳太超前:%20.20s"
+
+#: plugins/sudoers/timestamp.c:1042
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "无法锁定时间戳文件 %s"
+
+#: plugins/sudoers/toke_util.c:156
+msgid "sudoedit should not be specified with a path"
+msgstr "不应当带路径调用 sudoedit"
+
+#: plugins/sudoers/visudo.c:254
+msgid "the -x option will be removed in a future release"
+msgstr "未来版本中 -x 选项会移除"
+
+#: plugins/sudoers/visudo.c:256
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "请考虑换用 cvtsudoers 工具"
+
+#: plugins/sudoers/visudo.c:311 plugins/sudoers/visudo.c:698
+#, c-format
+msgid "press return to edit %s: "
+msgstr "按回车键编辑 %s:"
+
+#: plugins/sudoers/visudo.c:326
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr ""
+
+#: plugins/sudoers/visudo.c:402
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "指定的编辑器(%s)不存在"
+
+#: plugins/sudoers/visudo.c:404
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "未找到编辑器(编辑器路径 = %s)"
+
+#: plugins/sudoers/visudo.c:491 plugins/sudoers/visudo.c:770
+#, c-format
+msgid "unable to stat %s"
+msgstr "无法 stat %s"
+
+#: plugins/sudoers/visudo.c:511 plugins/sudoers/visudo.c:519
+msgid "write error"
+msgstr "写错误"
+
+#: plugins/sudoers/visudo.c:565
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "无法 stat 临时文件(%s),%s 未更改"
+
+#: plugins/sudoers/visudo.c:572
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "零长度的临时文件(%s),%s 未更改"
+
+#: plugins/sudoers/visudo.c:578
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "编辑器(%s)失败,%s 未更改"
+
+#: plugins/sudoers/visudo.c:600
+#, c-format
+msgid "%s unchanged"
+msgstr "%s 未更改"
+
+#: plugins/sudoers/visudo.c:645
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "无法重新打开临时文件(%s),%s 未更改。"
+
+#: plugins/sudoers/visudo.c:658
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "无法解析临时文件(%s),未知错误"
+
+#: plugins/sudoers/visudo.c:744 plugins/sudoers/visudo.c:774
+#: plugins/sudoers/visudo.c:781
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "无法将 %s 的 (uid, gid) 设为 (%u, %u)"
+
+#: plugins/sudoers/visudo.c:809
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s 和 %s 不在同一个文件系统,使用 mv 进行重命名"
+
+#: plugins/sudoers/visudo.c:820
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "命令失败:“%s %s %s”,%s 未更改"
+
+#: plugins/sudoers/visudo.c:827
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "重命名 %s 出错,%s 未更改"
+
+#: plugins/sudoers/visudo.c:847
+msgid "What now? "
+msgstr "现在做什么?"
+
+#: plugins/sudoers/visudo.c:861
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"选项有:\n"
+" 重新编辑 sudoers 文件(e)\n"
+" 退出,不保存对 sudoers 文件的更改(x)\n"
+" 退出并将更改保存到 sudoers 文件(危险!)(Q)\n"
+
+#: plugins/sudoers/visudo.c:907
+#, c-format
+msgid "unable to run %s"
+msgstr "无法运行 %s"
+
+#: plugins/sudoers/visudo.c:938
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s:错误的所有者(uid, gid),应为 (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:949
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s:权限不正确,模式应该是 0%o\n"
+
+#: plugins/sudoers/visudo.c:997 plugins/sudoers/visudo.c:1004
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s:解析正确\n"
+
+#: plugins/sudoers/visudo.c:1023
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s 忙,请稍后重试"
+
+#: plugins/sudoers/visudo.c:1027
+msgid "Edit anyway? [y/N]"
+msgstr "仍然编辑?[y/N]"
+
+#: plugins/sudoers/visudo.c:1128
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "警告:%s:%d:%d:未使用的 %s“%s”"
+
+#: plugins/sudoers/visudo.c:1240
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - 安全地编辑 sudoers 文件\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1242
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -I, --no-includes do not edit include files\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"选项:\n"
+" -c, --check 纯检查模式\n"
+" -f, --file=sudoers 指定 sudoers 文件的位置\n"
+" -h, --help 显示帮助信息并退出\n"
+" -I, --no-includes 不要编辑 include 文件\n"
+" -q, --quiet 较简略(安静)的语法错误信息\n"
+" -s, --strict 严格语法检查\n"
+" -V, --version 显示版本信息并退出\n"
+
+#: toke.l:189
+msgid "empty string"
+msgstr "空字符串"
+
+#: toke.l:201 toke.l:571
+msgid "empty group"
+msgstr "空组"
+
+#: toke.l:211 toke.l:569
+msgid "empty netgroup"
+msgstr ""
+
+#: toke.l:289
+msgid "unterminated regular expression"
+msgstr "未结束的正则表达式"
+
+#: toke.l:363 toke.l:375 toke.l:387 toke.l:403 toke.l:422 toke.l:462
+#, fuzzy
+#| msgid "invalid authentication type"
+msgid "invalid line continuation"
+msgstr "无效的认证类型"
+
+#: toke.l:608 toke.l:620
+msgid "invalid IPv6 address"
+msgstr "无效的 IPv6 地址"
+
+#: toke.l:868
+msgid "unexpected line break in string"
+msgstr "字符串中未预期的换行"
+
+#: toke.l:1218
+msgid "too many levels of includes"
+msgstr "include 嵌套层数过多"
+
+#~ msgid "Error: %s:%d:%d: cycle in %s \"%s\""
+#~ msgstr "错误:%s:%d:%d 在 %s “%s”中循环"
+
+#~ msgid "Warning: %s:%d:%d: cycle in %s \"%s\""
+#~ msgstr "警告:%s:%d:%d 在 %s “%s”中循环"
+
+#~ msgid "Warning: %s:%d:%d: %s \"%s\" referenced but not defined"
+#~ msgstr "警告:%s:%d:%d:引用了 %s“%s”但尚未定义"
+
+#~ msgid "parse error in %s near line %d\n"
+#~ msgstr "%s 中第 %d 行附近出现解析错误\n"
+
+#~ msgid "parse error in %s\n"
+#~ msgstr "%s 中出现解析错误\n"
+
+#~ msgid "%s: unknown defaults entry \"%s\""
+#~ msgstr "%s:未知的默认条目“%s”"
+
+#~ msgid "%s:%d:%d: no value specified for \"%s\""
+#~ msgstr "%s:%d:%d:没有为“%s”指定值"
+
+#, fuzzy
+#~| msgid "%s:%d no value specified for \"%s\""
+#~ msgid "%s:%d:%d: invalid operator \"%c=\" for \"%s\""
+#~ msgstr "%s:%d 没有给“%s”指定值"
+
+#~ msgid "%s:%d:%d: option \"%s\" does not take a value"
+#~ msgstr "%s:%d:%d:选项“%s”不接受值"
+
+#, fuzzy
+#~| msgid "%s:%d invalid Defaults type 0x%x for option \"%s\""
+#~ msgid "%s:%d:%d: invalid Defaults type 0x%x for option \"%s\""
+#~ msgstr "%1$s:%2$d 选项“%4$s”的默认类型 0x%3$x 无效"
+
+#, fuzzy
+#~| msgid "%s:%d value \"%s\" is invalid for option \"%s\""
+#~ msgid "%s:%d:%d: value \"%s\" is invalid for option \"%s\""
+#~ msgstr "%1$s:%2$d 值“%3$s”对选项“%4$s”无效"
+
+#~ msgid "%s:%d:%d: path name for \"%s\" too long"
+#~ msgstr "%s:%d:%d:“%s”的路径名过长"
+
+#~ msgid "%s: path name for \"%s\" too long"
+#~ msgstr "%s:“%s”的路径名过长"
+
+#, fuzzy
+#~| msgid "%s:%d values for \"%s\" must start with a '/'"
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/', '~', or '*'"
+#~ msgstr "%s:%d “%s”的值必须以“/”开头"
+
+#, fuzzy
+#~| msgid "%s:%d values for \"%s\" must start with a '/'"
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/'"
+#~ msgstr "%s:%d “%s”的值必须以“/”开头"
+
+#~ msgid "parse error in %s near line %d"
+#~ msgstr "%s 中第 %d 行附近有解析错误"
+
+#~ msgid "parse error in %s"
+#~ msgstr "%s 中出现解析错误"
+
+#~ msgid "SELinux RBAC is not supported when the log_subcmds flag is enabled"
+#~ msgstr "在 log_subcmds 启用时不支持 SELinux RBAC"
+
+#~ msgid "problem with defaults entries"
+#~ msgstr "默认条目有问题"
+
+#~ msgid "%s is group writable"
+#~ msgstr "%s 可被组写"
+
+#~ msgid "lecture status path too long: %s/%s"
+#~ msgstr "致辞(lecture)状态路径过长:%s/%s"
+
+#~ msgid "internal error, unable to find %s in list!"
+#~ msgstr "内部错误,在列表中找不到 %s!"
+
+#~ msgid "%s is not in the sudoers file. This incident will be reported.\n"
+#~ msgstr "%s 不在 sudoers 文件中。此事将被报告。\n"
+
+#~ msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+#~ msgstr "%s 无权在 %s 上运行 sudo。此事将被报告。\n"
+
+#~ msgid "%s: write buffer already in use"
+#~ msgstr "%s:写缓冲已在使用"
+
+#~ msgid "unable to read diffie-hellman parameters: %s"
+#~ msgstr "无法读取 diffie-hellman 参数:%s"
+
+#~ msgid "%s:%d unknown key: %s"
+#~ msgstr "%s:%d 未知的键:%s"
+
+#~ msgid "unable to get TLS server method: %s"
+#~ msgstr "无法获取 TLS 服务器方法:%s"
+
+#~ msgid "%s:%u unable to parse \"%s\""
+#~ msgstr "%s:%u 无法解析 \"%s\""
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " -f, --file path to configuration file\n"
+#~ " -h --help display help message and exit\n"
+#~ " -n, --no-fork do not fork, run in the foreground\n"
+#~ " -R, --random-drop percent chance connections will drop\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "选项:\n"
+#~ " -f, --file 指定配置文件的位置\n"
+#~ " -h, --help 显示帮助信息并退出\n"
+#~ " -n, --no-fork 不要进行 fork,在前台运行\n"
+#~ " -R, --random-drop 指定丢弃连接的百分比概率\n"
+#~ " -V, --version 显示版本信息并退出\n"
+
+#~ msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+#~ msgstr "预加载“sudo_noexec”库中包含的哑 exec 函数"
+
+#~ msgid "sudo_ldap_conf_add_ports: port too large"
+#~ msgstr "sudo_ldap_conf_add_ports:端口太大"
+
+#~ msgid "No user or host"
+#~ msgstr "无用户或主机"
+
+#~ msgid "validation failure"
+#~ msgstr "校验失败"
+
+#~ msgid "audit_failure message too long"
+#~ msgstr "audit_failure(审核失败)消息过长"
+
+#~ msgid "%s/%s/timing: %s"
+#~ msgstr "%s/%s/时序:%s"
+
+#~ msgid "ignoring invalid attribute value: %s"
+#~ msgstr "将忽略无效的属性值:%s"
+
+#~ msgid "unable to cache user %s, out of memory"
+#~ msgstr "无法缓存用户 %s,内存不足"
+
+#~ msgid "unable to cache group %s, out of memory"
+#~ msgstr "无法缓存组 %s,内存不足"
+
+#~ msgid "unable to cache group list for %s, out of memory"
+#~ msgstr "无法缓存组列表 %s,内存不足"
+
+#~ msgid ""
+#~ "\n"
+#~ "LDAP Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "LDAP 角色:未知\n"
+
+#~ msgid " Order: %s\n"
+#~ msgstr " 顺序:%s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: %s\n"
+#~ msgstr ""
+#~ "\n"
+#~ "SSSD 角色:%s\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "SSSD Role: UNKNOWN\n"
+#~ msgstr ""
+#~ "\n"
+#~ "SSSD 角色:未知\n"
+
+#~ msgid "Warning: unused %s `%s'"
+#~ msgstr "警告:%s “%s”未使用"
+
+#~ msgid "unable allocate memory"
+#~ msgstr "无法分配内存"
+
+#~ msgid "timestamp path too long: %s/%s"
+#~ msgstr "时间戳路径过长:%s/%s"
+
+#~ msgid "unable to stat editor (%s)"
+#~ msgstr "无法 stat 编辑器(%s)"
+
+#~ msgid "sudo_ldap_conf_add_ports: out of space expanding hostbuf"
+#~ msgstr "sudo_ldap_conf_add_ports:扩展主机缓存时空间不足"
+
+#~ msgid "sudo_ldap_parse_uri: out of space building hostbuf"
+#~ msgstr "sudo_ldap_parse_uri:构建主机缓存时空间不足"
+
+#~ msgid "sudo_ldap_build_pass1 allocation mismatch"
+#~ msgstr "sudo_ldap_build_pass1 分配不匹配"
+
+#~ msgid "Password:"
+#~ msgstr "密码:"
+
+#~ msgid "internal error: insufficient space for log line"
+#~ msgstr "内部错误:没有足够的空间存放日志行"
+
+#~ msgid "fill_args: buffer overflow"
+#~ msgstr "fill_args:缓存溢出"
+
+#~ msgid "%s owned by uid %u, should be uid %u"
+#~ msgstr "%s 属于用户 ID %u,应为用户 ID %u"
+
+#~ msgid "%s writable by non-owner (0%o), should be mode 0700"
+#~ msgstr "%s 对非所有者可写(0%o),模式应该为 0700"
+
+#~ msgid "%s exists but is not a regular file (0%o)"
+#~ msgstr "%s 存在,但不是常规文件(0%o)"
+
+#~ msgid "%s writable by non-owner (0%o), should be mode 0600"
+#~ msgstr "%s 对非所有者可写(0%o),模式应该为 0600"
+
+#~ msgid "unable to remove %s, will reset to the Unix epoch"
+#~ msgstr "无法移除 %s ,将重设为 Unix 戳记"
+
+#~ msgid "unable to reset %s to the Unix epoch"
+#~ msgstr "无法将 %s 重设为 Unix 戳记"
+
+#~ msgid "value out of range"
+#~ msgstr "值超出范围"
+
+#~ msgid "unable to mix ldaps and starttls"
+#~ msgstr "无法混合 ldaps 和 starttls"
+
+#~ msgid "writing to standard output"
+#~ msgstr "写入标准输出"
+
+#~ msgid "too many parenthesized expressions, max %d"
+#~ msgstr "括号表达式过多,最多 %d"
+
+#~ msgid "getaudit: failed"
+#~ msgstr "getaudit:失败"
+
+#~ msgid "getauid: failed"
+#~ msgstr "getauid:失败"
+
+#~ msgid "au_to_subject: failed"
+#~ msgstr "au_to_subject:失败"
+
+#~ msgid "au_to_exec_args: failed"
+#~ msgstr "au_to_exec_args:失败"
+
+#~ msgid "au_to_return32: failed"
+#~ msgstr "au_to_return32:失败"
+
+#~ msgid "au_to_text: failed"
+#~ msgstr "au_to_text:失败"
+
+#~ msgid "nanosleep: tv_sec %ld, tv_nsec %ld"
+#~ msgstr "nanosleep:tv_sec %ld,tv_nsec %ld"
+
+#~ msgid "pam_chauthtok: %s"
+#~ msgstr "pam_chauthtok:%s"
+
+#~ msgid "pam_authenticate: %s"
+#~ msgstr "pam_authenticate:%s"
+
+#~ msgid "getauid failed"
+#~ msgstr "getauid 失败"
+
+#~ msgid "Unable to dlopen %s: %s"
+#~ msgstr "无法执行 dlopen %s:%s"
+
+#~ msgid ">>> %s: %s near line %d <<<"
+#~ msgstr ">>> %s:%s 在行 %d 附近<<<"
+
+#~ msgid "unable to set locale to \"%s\", using \"C\""
+#~ msgstr "无法将区域设置为“%s”,将使用“C”"
+
+#~ msgid ""
+#~ " Commands:\n"
+#~ "\t"
+#~ msgstr ""
+#~ " 命令:\n"
+#~ "\t"
+
+#~ msgid ": "
+#~ msgstr ":"
+
+#~ msgid "unable to cache uid %u (%s), already exists"
+#~ msgstr "无法缓存用户 ID %u(%s),已存在"
+
+#~ msgid "unable to cache gid %u (%s), already exists"
+#~ msgstr "无法缓存组 ID %u(%s),已存在"
+
+#~ msgid "internal error, expand_prompt() overflow"
+#~ msgstr "内部错误,expand_prompt() 溢出"
+
+#~ msgid "internal error, sudo_setenv2() overflow"
+#~ msgstr "内部错误,sudo_setenv2() 溢出"
+
+#~ msgid "internal error, sudo_setenv() overflow"
+#~ msgstr "内部错误,sudo_setenv()溢出"
+
+#~ msgid "internal error, linux_audit_command() overflow"
+#~ msgstr "内部错误,linux_audit_command() 溢出"
+
+#~ msgid "internal error, runas_groups overflow"
+#~ msgstr "内部错误,runas_groups 溢出"
+
+#~ msgid "internal error, init_vars() overflow"
+#~ msgstr "内部错误,init_vars() 溢出"
+
+#~ msgid "fixed mode on %s"
+#~ msgstr "对 %s 修正了模式"
+
+#~ msgid "unable to fix mode on %s"
+#~ msgstr "无法对 %s 修正模式"
+
+#~ msgid "%s is mode 0%o, should be 0%o"
+#~ msgstr "%s 的模式为 0%o,应为 0%o"
+
+#~ msgid "File containing dummy exec functions: %s"
+#~ msgstr "含有哑 exec 函数的文件:%s"
+
+#~ msgid ""
+#~ "Available options in a sudoers ``Defaults'' line:\n"
+#~ "\n"
+#~ msgstr ""
+#~ "sudoers 中“Defaults”行中的可用选项:\n"
+#~ "\n"
+
+#~ msgid "%s: %.*s\n"
+#~ msgstr "%s:%.*s\n"
+
+#~ msgid "unable to get runas group vector"
+#~ msgstr "无法获取 runas 组向量"
+
+#~ msgid "%s: %s_Alias `%s' references self"
+#~ msgstr "%s:%s_Alias “%s”引用了自己"
diff --git a/plugins/sudoers/po/zh_TW.mo b/plugins/sudoers/po/zh_TW.mo
new file mode 100644
index 0000000..30a3809
--- /dev/null
+++ b/plugins/sudoers/po/zh_TW.mo
Binary files differ
diff --git a/plugins/sudoers/po/zh_TW.po b/plugins/sudoers/po/zh_TW.po
new file mode 100644
index 0000000..a273e3e
--- /dev/null
+++ b/plugins/sudoers/po/zh_TW.po
@@ -0,0 +1,4076 @@
+# Portable object template file for the sudoers plugin
+# This file is put in the public domain.
+#
+# Todd C. Miller <Todd.Miller@sudo.ws>, 2011-2018.
+# Hugwalk <baozou0421@gmail.com>, 2019.
+# Yi-Jyun Pan <pan93412@gmail.com>, 2019, 2020, 2021.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudoers 1.9.15b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-10-19 10:02-0600\n"
+"PO-Revision-Date: 2023-10-21 20:21+0800\n"
+"Last-Translator: Yi-Jyun Pan <pan93412@gmail.com>\n"
+"Language-Team: Chinese (traditional) <zh-l10n@lists.slat.org>\n"
+"Language: zh_TW\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 3.4\n"
+
+#: confstr.sh:1 gram.y:1257 plugins/sudoers/logging.c:911
+msgid "syntax error"
+msgstr "語法錯誤"
+
+#: confstr.sh:2
+msgid "%p's password: "
+msgstr "%p 的密碼:"
+
+#: confstr.sh:3
+msgid "[sudo] password for %p: "
+msgstr "[sudo] %p 的密碼:"
+
+#: confstr.sh:4
+msgid "Password: "
+msgstr "密碼:"
+
+#: confstr.sh:5
+msgid "*** SECURITY information for %h ***"
+msgstr "*** %h 須知的安全資訊 ***"
+
+#: confstr.sh:6
+msgid "Sorry, try again."
+msgstr "抱歉,請重試。"
+
+#: gram.y:238 gram.y:305 gram.y:314 gram.y:323 gram.y:333 gram.y:343 gram.y:367
+#: gram.y:394 gram.y:403 gram.y:411 gram.y:420 gram.y:429 gram.y:503 gram.y:513
+#: gram.y:525 gram.y:573 gram.y:582 gram.y:591 gram.y:600 gram.y:733 gram.y:742
+#: gram.y:757 gram.y:777 gram.y:796 gram.y:959 gram.y:964 gram.y:972 gram.y:986
+#: gram.y:992 gram.y:1004 gram.y:1010 gram.y:1135 gram.y:1144 gram.y:1152
+#: gram.y:1161 gram.y:1170 gram.y:1199 gram.y:1208 gram.y:1216 gram.y:1317
+#: gram.y:1447 gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:313 lib/eventlog/eventlog.c:765
+#: lib/eventlog/eventlog.c:842 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:484
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:233
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:185
+#: logsrvd/iolog_writer.c:218 logsrvd/iolog_writer.c:228
+#: logsrvd/iolog_writer.c:257 logsrvd/iolog_writer.c:278
+#: logsrvd/iolog_writer.c:290 logsrvd/iolog_writer.c:300
+#: logsrvd/iolog_writer.c:310 logsrvd/iolog_writer.c:320
+#: logsrvd/iolog_writer.c:330 logsrvd/iolog_writer.c:342
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:1057 logsrvd/logsrvd.c:1120 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:650
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1743
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:216
+#: logsrvd/logsrvd_journal.c:217 logsrvd/logsrvd_journal.c:274
+#: logsrvd/logsrvd_journal.c:279 logsrvd/logsrvd_journal.c:439
+#: logsrvd/logsrvd_journal.c:441 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:216 logsrvd/logsrvd_local.c:278
+#: logsrvd/logsrvd_local.c:279 logsrvd/logsrvd_local.c:417
+#: logsrvd/logsrvd_local.c:468 logsrvd/logsrvd_local.c:469
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:475
+#: logsrvd/logsrvd_queue.c:159 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/logsrvd_relay.c:446
+#: logsrvd/logsrvd_relay.c:748 logsrvd/logsrvd_relay.c:855
+#: logsrvd/sendlog.c:256 logsrvd/sendlog.c:265 logsrvd/sendlog.c:297
+#: logsrvd/sendlog.c:303 logsrvd/sendlog.c:352 logsrvd/sendlog.c:630
+#: logsrvd/sendlog.c:1822 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/bsdauth.c:154 plugins/sudoers/auth/kerb5.c:122
+#: plugins/sudoers/auth/kerb5.c:150 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/auth/sia.c:61
+#: plugins/sudoers/canon_path.c:129 plugins/sudoers/canon_path.c:161
+#: plugins/sudoers/check_aliases.c:128 plugins/sudoers/check_util.c:56
+#: plugins/sudoers/check_util.c:84 plugins/sudoers/cvtsudoers.c:132
+#: plugins/sudoers/cvtsudoers.c:176 plugins/sudoers/cvtsudoers.c:193
+#: plugins/sudoers/cvtsudoers.c:204 plugins/sudoers/cvtsudoers.c:338
+#: plugins/sudoers/cvtsudoers.c:379 plugins/sudoers/cvtsudoers.c:399
+#: plugins/sudoers/cvtsudoers.c:545 plugins/sudoers/cvtsudoers.c:698
+#: plugins/sudoers/cvtsudoers.c:716 plugins/sudoers/cvtsudoers.c:891
+#: plugins/sudoers/cvtsudoers.c:899 plugins/sudoers/cvtsudoers.c:1395
+#: plugins/sudoers/cvtsudoers.c:1399 plugins/sudoers/cvtsudoers.c:1501
+#: plugins/sudoers/cvtsudoers_csv.c:183 plugins/sudoers/cvtsudoers_csv.c:247
+#: plugins/sudoers/cvtsudoers_json.c:76 plugins/sudoers/cvtsudoers_ldif.c:152
+#: plugins/sudoers/cvtsudoers_ldif.c:195 plugins/sudoers/cvtsudoers_ldif.c:236
+#: plugins/sudoers/cvtsudoers_ldif.c:302 plugins/sudoers/cvtsudoers_ldif.c:378
+#: plugins/sudoers/cvtsudoers_ldif.c:432 plugins/sudoers/cvtsudoers_ldif.c:440
+#: plugins/sudoers/cvtsudoers_ldif.c:451 plugins/sudoers/cvtsudoers_ldif.c:458
+#: plugins/sudoers/cvtsudoers_ldif.c:470 plugins/sudoers/cvtsudoers_ldif.c:483
+#: plugins/sudoers/cvtsudoers_ldif.c:491 plugins/sudoers/cvtsudoers_ldif.c:638
+#: plugins/sudoers/cvtsudoers_merge.c:47 plugins/sudoers/cvtsudoers_merge.c:52
+#: plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:446
+#: plugins/sudoers/cvtsudoers_merge.c:467
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1158
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:212
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:694 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:294 plugins/sudoers/ldap_util.c:301
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:402
+#: plugins/sudoers/log_client.c:717 plugins/sudoers/log_client.c:739
+#: plugins/sudoers/log_client.c:744 plugins/sudoers/log_client.c:1426
+#: plugins/sudoers/log_client.c:1547 plugins/sudoers/log_client.c:1670
+#: plugins/sudoers/log_client.c:1993 plugins/sudoers/log_client.c:2052
+#: plugins/sudoers/logging.c:110 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:872 plugins/sudoers/lookup.c:338
+#: plugins/sudoers/lookup.c:355 plugins/sudoers/lookup.c:374
+#: plugins/sudoers/lookup.c:393 plugins/sudoers/lookup.c:410
+#: plugins/sudoers/lookup.c:433 plugins/sudoers/lookup.c:444
+#: plugins/sudoers/match_command.c:302 plugins/sudoers/match_command.c:574
+#: plugins/sudoers/match_command.c:641 plugins/sudoers/match_command.c:737
+#: plugins/sudoers/match_command.c:785 plugins/sudoers/match_digest.c:88
+#: plugins/sudoers/parse_ldif.c:153 plugins/sudoers/parse_ldif.c:184
+#: plugins/sudoers/parse_ldif.c:253 plugins/sudoers/parse_ldif.c:261
+#: plugins/sudoers/parse_ldif.c:266 plugins/sudoers/parse_ldif.c:342
+#: plugins/sudoers/parse_ldif.c:353 plugins/sudoers/parse_ldif.c:380
+#: plugins/sudoers/parse_ldif.c:397 plugins/sudoers/parse_ldif.c:409
+#: plugins/sudoers/parse_ldif.c:413 plugins/sudoers/parse_ldif.c:427
+#: plugins/sudoers/parse_ldif.c:484 plugins/sudoers/parse_ldif.c:595
+#: plugins/sudoers/parse_ldif.c:625 plugins/sudoers/parse_ldif.c:650
+#: plugins/sudoers/parse_ldif.c:708 plugins/sudoers/parse_ldif.c:725
+#: plugins/sudoers/parse_ldif.c:753 plugins/sudoers/parse_ldif.c:760
+#: plugins/sudoers/policy.c:646 plugins/sudoers/policy.c:1061
+#: plugins/sudoers/prompt.c:94 plugins/sudoers/pwutil.c:219
+#: plugins/sudoers/pwutil.c:290 plugins/sudoers/pwutil.c:368
+#: plugins/sudoers/pwutil.c:542 plugins/sudoers/pwutil.c:607
+#: plugins/sudoers/pwutil.c:679 plugins/sudoers/pwutil.c:877
+#: plugins/sudoers/pwutil.c:967 plugins/sudoers/pwutil.c:1015
+#: plugins/sudoers/pwutil.c:1076 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:145 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1307 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:256
+#: plugins/sudoers/testsudoers.c:265 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:164 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1095
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1320
+msgid "unable to allocate memory"
+msgstr "無法分配記憶體"
+
+#: gram.y:624
+msgid "a digest requires a path name"
+msgstr "摘要需要路徑名稱"
+
+#: gram.y:646
+msgid "values for \"CWD\" must start with a '/', '~', or '*'"
+msgstr "\"CWD\" 的值開頭必須是 '/'、'~' 或 '*'"
+
+#: gram.y:652
+msgid "\"CWD\" path too long"
+msgstr "「CWD」路徑過長"
+
+#: gram.y:662
+msgid "values for \"CHROOT\" must start with a '/', '~', or '*'"
+msgstr "\"CHROOT\" 的值開頭必須是 '/'、'~' 或 '*'"
+
+#: gram.y:668
+msgid "\"CHROOT\" path too long"
+msgstr "「CHROOT」路徑過長 "
+
+#: gram.y:817
+#, c-format
+msgid "syntax error, reserved word %s used as an alias name"
+msgstr "語法錯誤,保留字 %s 被用作別名名稱"
+
+#: gram.y:840
+msgid "invalid notbefore value"
+msgstr "notbefore 的值無效"
+
+#: gram.y:849
+msgid "invalid notafter value"
+msgstr "notafter 的值無效"
+
+#: gram.y:859 plugins/sudoers/policy.c:390
+msgid "timeout value too large"
+msgstr "timeout 值過長"
+
+#: gram.y:861 plugins/sudoers/policy.c:392
+msgid "invalid timeout value"
+msgstr "timeout 值無效"
+
+#: gram.y:982 plugins/sudoers/sudoers.c:1162
+msgid "command too long"
+msgstr "指令過長"
+
+#: gram.y:1016
+msgid "expected a fully-qualified path name"
+msgstr "預期完全合法的路徑名稱"
+
+#: gram.y:1261
+#, c-format
+msgid "%s:%d:%zu: %s\n"
+msgstr "%s:%d:%zu: %s\n"
+
+#: gram.y:1315
+#, c-format
+msgid "Alias \"%s\" already defined"
+msgstr "別名「%s」已定義過"
+
+#: gram.y:1829 gram.y:1840 gram.y:1922 lib/eventlog/eventlog.c:236
+#: lib/eventlog/eventlog.c:765 lib/eventlog/eventlog.c:838
+#: lib/eventlog/eventlog.c:841 lib/eventlog/eventlog.c:1175
+#: lib/eventlog/parse_json.c:185 lib/eventlog/parse_json.c:483
+#: lib/eventlog/parse_json.c:514 lib/iolog/iolog_filter.c:142
+#: lib/iolog/iolog_filter.c:202 lib/iolog/iolog_filter.c:232
+#: lib/iolog/iolog_legacy.c:101 lib/iolog/iolog_legacy.c:112
+#: lib/iolog/iolog_legacy.c:124 lib/iolog/iolog_legacy.c:134
+#: lib/iolog/iolog_legacy.c:140 lib/iolog/iolog_loginfo.c:76
+#: lib/iolog/iolog_loginfo.c:212 logsrvd/iolog_writer.c:95
+#: logsrvd/iolog_writer.c:100 logsrvd/iolog_writer.c:134
+#: logsrvd/iolog_writer.c:147 logsrvd/iolog_writer.c:174
+#: logsrvd/iolog_writer.c:184 logsrvd/iolog_writer.c:197
+#: logsrvd/iolog_writer.c:217 logsrvd/iolog_writer.c:227
+#: logsrvd/iolog_writer.c:246 logsrvd/iolog_writer.c:256
+#: logsrvd/iolog_writer.c:267 logsrvd/iolog_writer.c:277
+#: logsrvd/iolog_writer.c:289 logsrvd/iolog_writer.c:299
+#: logsrvd/iolog_writer.c:309 logsrvd/iolog_writer.c:319
+#: logsrvd/iolog_writer.c:329 logsrvd/iolog_writer.c:341
+#: logsrvd/iolog_writer.c:377 logsrvd/iolog_writer.c:383
+#: logsrvd/iolog_writer.c:390 logsrvd/iolog_writer.c:396
+#: logsrvd/iolog_writer.c:580 logsrvd/logsrv_util.c:92 logsrvd/logsrvd.c:323
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:530
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:668
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:1131
+#: logsrvd/logsrvd.c:1446 logsrvd/logsrvd.c:1453 logsrvd/logsrvd.c:1589
+#: logsrvd/logsrvd.c:1594 logsrvd/logsrvd.c:1781 logsrvd/logsrvd.c:2003
+#: logsrvd/logsrvd_conf.c:357 logsrvd/logsrvd_conf.c:370
+#: logsrvd/logsrvd_conf.c:511 logsrvd/logsrvd_conf.c:534
+#: logsrvd/logsrvd_conf.c:538 logsrvd/logsrvd_conf.c:556
+#: logsrvd/logsrvd_conf.c:626 logsrvd/logsrvd_conf.c:649
+#: logsrvd/logsrvd_conf.c:678 logsrvd/logsrvd_conf.c:692
+#: logsrvd/logsrvd_conf.c:706 logsrvd/logsrvd_conf.c:720
+#: logsrvd/logsrvd_conf.c:734 logsrvd/logsrvd_conf.c:748
+#: logsrvd/logsrvd_conf.c:829 logsrvd/logsrvd_conf.c:1036
+#: logsrvd/logsrvd_conf.c:1053 logsrvd/logsrvd_conf.c:1448
+#: logsrvd/logsrvd_conf.c:1595 logsrvd/logsrvd_conf.c:1621
+#: logsrvd/logsrvd_conf.c:1633 logsrvd/logsrvd_conf.c:1640
+#: logsrvd/logsrvd_conf.c:1646 logsrvd/logsrvd_conf.c:1742
+#: logsrvd/logsrvd_journal.c:76 logsrvd/logsrvd_journal.c:125
+#: logsrvd/logsrvd_journal.c:216 logsrvd/logsrvd_journal.c:246
+#: logsrvd/logsrvd_journal.c:250 logsrvd/logsrvd_journal.c:258
+#: logsrvd/logsrvd_journal.c:287 logsrvd/logsrvd_journal.c:291
+#: logsrvd/logsrvd_journal.c:439 logsrvd/logsrvd_local.c:215
+#: logsrvd/logsrvd_local.c:278 logsrvd/logsrvd_local.c:468
+#: logsrvd/logsrvd_local.c:474 logsrvd/logsrvd_local.c:493
+#: logsrvd/logsrvd_queue.c:158 logsrvd/logsrvd_queue.c:189
+#: logsrvd/logsrvd_queue.c:266 logsrvd/sendlog.c:256 logsrvd/sendlog.c:265
+#: logsrvd/sendlog.c:297 logsrvd/sendlog.c:303 logsrvd/sendlog.c:352
+#: logsrvd/sendlog.c:630 logsrvd/sendlog.c:1523 logsrvd/sendlog.c:1530
+#: logsrvd/sendlog.c:1753 logsrvd/sendlog.c:1822 logsrvd/tls_init.c:305
+#: logsrvd/tls_init.c:329 logsrvd/tls_init.c:340 plugins/sudoers/audit.c:118
+#: plugins/sudoers/auth/pam.c:518 plugins/sudoers/auth/pam.c:697
+#: plugins/sudoers/auth/rfc1938.c:112 plugins/sudoers/canon_path.c:129
+#: plugins/sudoers/canon_path.c:161 plugins/sudoers/check_aliases.c:128
+#: plugins/sudoers/check_util.c:56 plugins/sudoers/check_util.c:84
+#: plugins/sudoers/cvtsudoers.c:132 plugins/sudoers/cvtsudoers.c:175
+#: plugins/sudoers/cvtsudoers.c:192 plugins/sudoers/cvtsudoers.c:203
+#: plugins/sudoers/cvtsudoers.c:337 plugins/sudoers/cvtsudoers.c:544
+#: plugins/sudoers/cvtsudoers.c:697 plugins/sudoers/cvtsudoers.c:715
+#: plugins/sudoers/cvtsudoers.c:891 plugins/sudoers/cvtsudoers.c:898
+#: plugins/sudoers/cvtsudoers.c:1395 plugins/sudoers/cvtsudoers.c:1399
+#: plugins/sudoers/cvtsudoers.c:1501 plugins/sudoers/cvtsudoers_csv.c:182
+#: plugins/sudoers/cvtsudoers_csv.c:246 plugins/sudoers/cvtsudoers_json.c:75
+#: plugins/sudoers/cvtsudoers_ldif.c:151 plugins/sudoers/cvtsudoers_ldif.c:194
+#: plugins/sudoers/cvtsudoers_ldif.c:235 plugins/sudoers/cvtsudoers_ldif.c:301
+#: plugins/sudoers/cvtsudoers_ldif.c:377 plugins/sudoers/cvtsudoers_ldif.c:431
+#: plugins/sudoers/cvtsudoers_ldif.c:439 plugins/sudoers/cvtsudoers_ldif.c:450
+#: plugins/sudoers/cvtsudoers_ldif.c:457 plugins/sudoers/cvtsudoers_ldif.c:469
+#: plugins/sudoers/cvtsudoers_ldif.c:482 plugins/sudoers/cvtsudoers_ldif.c:490
+#: plugins/sudoers/cvtsudoers_ldif.c:637 plugins/sudoers/cvtsudoers_merge.c:47
+#: plugins/sudoers/cvtsudoers_merge.c:51 plugins/sudoers/cvtsudoers_merge.c:353
+#: plugins/sudoers/cvtsudoers_merge.c:399
+#: plugins/sudoers/cvtsudoers_merge.c:445
+#: plugins/sudoers/cvtsudoers_merge.c:466
+#: plugins/sudoers/cvtsudoers_merge.c:553
+#: plugins/sudoers/cvtsudoers_merge.c:561
+#: plugins/sudoers/cvtsudoers_merge.c:564
+#: plugins/sudoers/cvtsudoers_merge.c:630
+#: plugins/sudoers/cvtsudoers_merge.c:633
+#: plugins/sudoers/cvtsudoers_merge.c:1157
+#: plugins/sudoers/cvtsudoers_merge.c:1231 plugins/sudoers/defaults.c:455
+#: plugins/sudoers/defaults.c:689 plugins/sudoers/defaults.c:1051
+#: plugins/sudoers/defaults.c:1235 plugins/sudoers/editor.c:198
+#: plugins/sudoers/env.c:263 plugins/sudoers/exptilde.c:92
+#: plugins/sudoers/filedigest.c:66 plugins/sudoers/filedigest.c:70
+#: plugins/sudoers/gc.c:57 plugins/sudoers/group_plugin.c:211
+#: plugins/sudoers/interfaces.c:68 plugins/sudoers/iolog.c:268
+#: plugins/sudoers/iolog.c:675 plugins/sudoers/iolog.c:703
+#: plugins/sudoers/ldap.c:161 plugins/sudoers/ldap.c:448
+#: plugins/sudoers/ldap.c:625 plugins/sudoers/ldap.c:789
+#: plugins/sudoers/ldap.c:1214 plugins/sudoers/ldap.c:1642
+#: plugins/sudoers/ldap.c:1679 plugins/sudoers/ldap.c:1897
+#: plugins/sudoers/ldap.c:2007 plugins/sudoers/ldap.c:2023
+#: plugins/sudoers/ldap_conf.c:215 plugins/sudoers/ldap_conf.c:247
+#: plugins/sudoers/ldap_conf.c:299 plugins/sudoers/ldap_conf.c:335
+#: plugins/sudoers/ldap_conf.c:441 plugins/sudoers/ldap_conf.c:456
+#: plugins/sudoers/ldap_conf.c:565 plugins/sudoers/ldap_conf.c:598
+#: plugins/sudoers/ldap_conf.c:693 plugins/sudoers/ldap_conf.c:776
+#: plugins/sudoers/ldap_util.c:293 plugins/sudoers/ldap_util.c:300
+#: plugins/sudoers/ldap_util.c:614 plugins/sudoers/linux_audit.c:86
+#: plugins/sudoers/log_client.c:117 plugins/sudoers/log_client.c:228
+#: plugins/sudoers/log_client.c:250 plugins/sudoers/log_client.c:264
+#: plugins/sudoers/log_client.c:402 plugins/sudoers/log_client.c:717
+#: plugins/sudoers/log_client.c:739 plugins/sudoers/log_client.c:744
+#: plugins/sudoers/log_client.c:1426 plugins/sudoers/log_client.c:1547
+#: plugins/sudoers/log_client.c:1670 plugins/sudoers/log_client.c:1993
+#: plugins/sudoers/log_client.c:2052 plugins/sudoers/logging.c:110
+#: plugins/sudoers/logging.c:189 plugins/sudoers/logging.c:190
+#: plugins/sudoers/logging.c:475 plugins/sudoers/logging.c:711
+#: plugins/sudoers/logging.c:755 plugins/sudoers/logging.c:872
+#: plugins/sudoers/logging.c:925 plugins/sudoers/logging.c:932
+#: plugins/sudoers/lookup.c:337 plugins/sudoers/lookup.c:354
+#: plugins/sudoers/lookup.c:373 plugins/sudoers/lookup.c:392
+#: plugins/sudoers/lookup.c:409 plugins/sudoers/lookup.c:432
+#: plugins/sudoers/lookup.c:443 plugins/sudoers/match_command.c:301
+#: plugins/sudoers/match_command.c:573 plugins/sudoers/match_command.c:640
+#: plugins/sudoers/match_command.c:737 plugins/sudoers/match_command.c:784
+#: plugins/sudoers/match_digest.c:88 plugins/sudoers/parse_ldif.c:152
+#: plugins/sudoers/parse_ldif.c:183 plugins/sudoers/parse_ldif.c:252
+#: plugins/sudoers/parse_ldif.c:260 plugins/sudoers/parse_ldif.c:265
+#: plugins/sudoers/parse_ldif.c:341 plugins/sudoers/parse_ldif.c:352
+#: plugins/sudoers/parse_ldif.c:379 plugins/sudoers/parse_ldif.c:396
+#: plugins/sudoers/parse_ldif.c:408 plugins/sudoers/parse_ldif.c:412
+#: plugins/sudoers/parse_ldif.c:426 plugins/sudoers/parse_ldif.c:484
+#: plugins/sudoers/parse_ldif.c:595 plugins/sudoers/parse_ldif.c:624
+#: plugins/sudoers/parse_ldif.c:649 plugins/sudoers/parse_ldif.c:707
+#: plugins/sudoers/parse_ldif.c:724 plugins/sudoers/parse_ldif.c:752
+#: plugins/sudoers/parse_ldif.c:759 plugins/sudoers/policy.c:157
+#: plugins/sudoers/policy.c:166 plugins/sudoers/policy.c:175
+#: plugins/sudoers/policy.c:204 plugins/sudoers/policy.c:374
+#: plugins/sudoers/policy.c:390 plugins/sudoers/policy.c:392
+#: plugins/sudoers/policy.c:430 plugins/sudoers/policy.c:439
+#: plugins/sudoers/policy.c:448 plugins/sudoers/policy.c:457
+#: plugins/sudoers/policy.c:493 plugins/sudoers/policy.c:502
+#: plugins/sudoers/policy.c:511 plugins/sudoers/policy.c:520
+#: plugins/sudoers/policy.c:529 plugins/sudoers/policy.c:538
+#: plugins/sudoers/policy.c:547 plugins/sudoers/policy.c:646
+#: plugins/sudoers/policy.c:1061 plugins/sudoers/prompt.c:94
+#: plugins/sudoers/pwutil.c:219 plugins/sudoers/pwutil.c:290
+#: plugins/sudoers/pwutil.c:368 plugins/sudoers/pwutil.c:542
+#: plugins/sudoers/pwutil.c:607 plugins/sudoers/pwutil.c:679
+#: plugins/sudoers/pwutil.c:877 plugins/sudoers/pwutil.c:967
+#: plugins/sudoers/pwutil.c:1015 plugins/sudoers/pwutil.c:1076
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579 plugins/sudoers/sethost.c:85
+#: plugins/sudoers/sssd.c:144 plugins/sudoers/sssd.c:186
+#: plugins/sudoers/sssd.c:415 plugins/sudoers/sssd.c:480
+#: plugins/sudoers/sssd.c:507 plugins/sudoers/sssd.c:570
+#: plugins/sudoers/sssd.c:765 plugins/sudoers/strvec_join.c:53
+#: plugins/sudoers/sudoers.c:405 plugins/sudoers/sudoers.c:412
+#: plugins/sudoers/sudoers.c:656 plugins/sudoers/sudoers.c:666
+#: plugins/sudoers/sudoers.c:811 plugins/sudoers/sudoers.c:877
+#: plugins/sudoers/sudoers.c:936 plugins/sudoers/sudoers.c:985
+#: plugins/sudoers/sudoers.c:1144 plugins/sudoers/sudoers.c:1213
+#: plugins/sudoers/sudoers.c:1306 plugins/sudoers/sudoers_cb.c:150
+#: plugins/sudoers/sudoreplay.c:559 plugins/sudoers/sudoreplay.c:562
+#: plugins/sudoers/sudoreplay.c:1279 plugins/sudoers/sudoreplay.c:1335
+#: plugins/sudoers/sudoreplay.c:1531 plugins/sudoers/sudoreplay.c:1535
+#: plugins/sudoers/testsudoers.c:120 plugins/sudoers/testsudoers.c:255
+#: plugins/sudoers/testsudoers.c:264 plugins/sudoers/testsudoers.c:275
+#: plugins/sudoers/testsudoers.c:282 plugins/sudoers/testsudoers.c:302
+#: plugins/sudoers/testsudoers.c:758 plugins/sudoers/timestamp.c:469
+#: plugins/sudoers/timestamp.c:513 plugins/sudoers/timestamp.c:1042
+#: plugins/sudoers/timestamp.c:1216 plugins/sudoers/toke_util.c:79
+#: plugins/sudoers/toke_util.c:108 plugins/sudoers/toke_util.c:134
+#: plugins/sudoers/toke_util.c:163 plugins/sudoers/toke_util.c:204
+#: plugins/sudoers/tsdump.c:123 plugins/sudoers/visudo.c:151
+#: plugins/sudoers/visudo.c:258 plugins/sudoers/visudo.c:383
+#: plugins/sudoers/visudo.c:389 plugins/sudoers/visudo.c:501
+#: plugins/sudoers/visudo.c:1073 plugins/sudoers/visudo.c:1094
+#: plugins/sudoers/visudo.c:1189 toke.l:1031 toke.l:1194 toke.l:1213
+#: toke.l:1240 toke.l:1309 toke.l:1320
+#, c-format
+msgid "%s: %s"
+msgstr "%s:%s"
+
+#: lib/eventlog/eventlog.c:304
+#, c-format
+msgid "unable to dup stdin: %m"
+msgstr "無法 dup stdin:%m"
+
+#: lib/eventlog/eventlog.c:346
+#, c-format
+msgid "unable to execute %s: %m"
+msgstr "無法執行 %s:%m"
+
+#: lib/eventlog/eventlog.c:394 plugins/sudoers/auth/aix_auth.c:199
+msgid "unable to fork"
+msgstr "無法執行 fork"
+
+#: lib/eventlog/eventlog.c:404 lib/eventlog/eventlog.c:471
+#, c-format
+msgid "unable to fork: %m"
+msgstr "無法執行 fork:%m"
+
+#: lib/eventlog/eventlog.c:461
+#, c-format
+msgid "unable to open pipe: %m"
+msgstr "無法開啟管線:%m"
+
+#: lib/eventlog/eventlog.c:1000
+#, c-format
+msgid "%8s : %s"
+msgstr "%8s : %s"
+
+#: lib/eventlog/eventlog.c:1029
+#, c-format
+msgid "%8s : (command continued) %s"
+msgstr "%8s : (指令繼續執行) %s"
+
+#: lib/eventlog/parse_json.c:175
+#, c-format
+msgid "expected JSON_STRING, got %d"
+msgstr "應為 JSON_STRNG,但收到 %d"
+
+#: lib/eventlog/parse_json.c:180
+msgid "JSON_ARRAY too large"
+msgstr "JSON_ARRAY 太大"
+
+#: lib/eventlog/parse_json.c:506
+msgid "missing double quote in name"
+msgstr "名稱中缺少雙引號"
+
+#: lib/eventlog/parse_json.c:624
+msgid "missing JSON_OBJECT"
+msgstr "缺少 JSON_OBJECT"
+
+#: lib/eventlog/parse_json.c:628
+#, c-format
+msgid "expected JSON_OBJECT, got %d"
+msgstr "應為 JSON_OBJECT,但收到 %d"
+
+#: lib/eventlog/parse_json.c:762
+#, c-format
+msgid "json stack exhausted (max %u frames)"
+msgstr "JSON 堆疊用盡(最多 %u 個框架)"
+
+#: lib/eventlog/parse_json.c:840
+msgid "objects must consist of name:value pairs"
+msgstr "物件必須由「鍵:值」對組成"
+
+#: lib/eventlog/parse_json.c:845 lib/eventlog/parse_json.c:876
+#: lib/eventlog/parse_json.c:920 lib/eventlog/parse_json.c:942
+#: lib/eventlog/parse_json.c:964 lib/eventlog/parse_json.c:986
+#: lib/eventlog/parse_json.c:1008
+msgid "missing separator between values"
+msgstr "數值間缺少分隔符號"
+
+#: lib/eventlog/parse_json.c:860 lib/eventlog/parse_json.c:1034
+msgid "unmatched close brace"
+msgstr "未對稱的右大括弧"
+
+#: lib/eventlog/parse_json.c:871
+msgid "unexpected array"
+msgstr "不應有陣列"
+
+#: lib/eventlog/parse_json.c:891 lib/eventlog/parse_json.c:1037
+msgid "unmatched close bracket"
+msgstr "未對稱的右中括弧"
+
+#: lib/eventlog/parse_json.c:902
+msgid "unexpected string"
+msgstr "不應有字串"
+
+#: lib/eventlog/parse_json.c:913
+msgid "missing colon after name"
+msgstr "名稱後缺少冒號"
+
+#: lib/eventlog/parse_json.c:934 lib/eventlog/parse_json.c:956
+msgid "unexpected boolean"
+msgstr "不應有布林值"
+
+#: lib/eventlog/parse_json.c:978
+msgid "unexpected null"
+msgstr "不應有 null"
+
+#: lib/eventlog/parse_json.c:999
+msgid "unexpected number"
+msgstr "不應有數字"
+
+#: lib/eventlog/parse_json.c:1045
+msgid "parse error"
+msgstr "解析發生錯誤"
+
+#: lib/iolog/iolog_filter.c:133 plugins/sudoers/defaults.c:1290
+#: plugins/sudoers/sudoreplay.c:1291 plugins/sudoers/sudoreplay.c:1587
+#, c-format
+msgid "invalid regular expression \"%s\": %s"
+msgstr "無效的「%s」正規表達式:%s"
+
+#: lib/iolog/iolog_legacy.c:65
+#, c-format
+msgid "%s: invalid log file"
+msgstr "%s:無效的記錄檔案"
+
+#: lib/iolog/iolog_legacy.c:83
+#, c-format
+msgid "%s: time stamp field is missing"
+msgstr "%s:缺少 時間戳 欄位"
+
+#: lib/iolog/iolog_legacy.c:90
+#, c-format
+msgid "%s: time stamp %s: %s"
+msgstr "%s:時間戳 %s:%s"
+
+#: lib/iolog/iolog_legacy.c:97
+#, c-format
+msgid "%s: user field is missing"
+msgstr "%s:缺少 使用者 欄位"
+
+#: lib/iolog/iolog_legacy.c:108
+#, c-format
+msgid "%s: runas user field is missing"
+msgstr "%s:缺少 runas 使用者 欄位"
+
+#: lib/iolog/iolog_legacy.c:119
+#, c-format
+msgid "%s: runas group field is missing"
+msgstr "%s:缺少 runas 群組 欄位"
+
+#: lib/iolog/iolog_mkdirs.c:89
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s 存在,但非目錄 (0%o)"
+
+#: lib/iolog/iolog_mkdirs.c:124 lib/iolog/iolog_mkdtemp.c:80
+#: logsrvd/iolog_writer.c:795 plugins/sudoers/timestamp.c:218
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "無法建立目錄 %s"
+
+#: lib/iolog/iolog_mkdtemp.c:85 plugins/sudoers/visudo.c:769
+#: plugins/sudoers/visudo.c:803 plugins/sudoers/visudo.c:809
+#, c-format
+msgid "unable to change mode of %s to 0%o"
+msgstr "無法將 %s 的模式變更為 0%o"
+
+#: lib/iolog/iolog_timing.c:261
+#, c-format
+msgid "error reading timing file: %s"
+msgstr "讀取計時檔案時發生錯誤:%s"
+
+#: lib/iolog/iolog_timing.c:268
+#, c-format
+msgid "invalid timing file line: %s"
+msgstr "無效的計時檔案行號:%s"
+
+#: logsrvd/iolog_writer.c:65
+#, c-format
+msgid "%s: protocol error: NULL key"
+msgstr "%s:通訊協定有誤:NULL 鍵"
+
+#: logsrvd/iolog_writer.c:69
+#, c-format
+msgid "%s: protocol error: wrong type for %s"
+msgstr "%s:通訊協定有誤:%s 類型有錯"
+
+#: logsrvd/iolog_writer.c:74 logsrvd/logsrvd_local.c:109
+#: logsrvd/logsrvd_local.c:123 logsrvd/logsrvd_local.c:131
+#: logsrvd/logsrvd_local.c:149
+#, c-format
+msgid "%s: protocol error: NULL value found in %s"
+msgstr "%s:通訊協定有誤:%s 中有 NULL 值"
+
+#: logsrvd/iolog_writer.c:141 plugins/sudoers/logging.c:1024
+#: plugins/sudoers/policy.c:613
+msgid "unable to generate UUID"
+msgstr "無法產生 UUID"
+
+#: logsrvd/iolog_writer.c:354 logsrvd/iolog_writer.c:359
+#: logsrvd/iolog_writer.c:364 logsrvd/iolog_writer.c:369
+#, c-format
+msgid "%s: protocol error: %s missing from AcceptMessage"
+msgstr "%s:通訊協定有誤:AcceptMessage 缺少 %s"
+
+#: logsrvd/iolog_writer.c:430
+#, c-format
+msgid "%s: unable to format session id"
+msgstr "%s:無法格式化工作階段 ID"
+
+#: logsrvd/iolog_writer.c:444 logsrvd/iolog_writer.c:458
+#: logsrvd/iolog_writer.c:472 logsrvd/iolog_writer.c:487
+#: logsrvd/iolog_writer.c:501 logsrvd/iolog_writer.c:515
+#, c-format
+msgid "%s: %s is not set"
+msgstr "%s:%s 未設定"
+
+#: logsrvd/iolog_writer.c:551 logsrvd/iolog_writer.c:558
+#, c-format
+msgid "unable to expand iolog path %s"
+msgstr "無法展開 iolog 路徑 %s"
+
+#: logsrvd/iolog_writer.c:576
+#, c-format
+msgid "unable to create iolog path %s"
+msgstr "無法建立 iolog 路徑 %s"
+
+#: logsrvd/iolog_writer.c:606
+#, c-format
+msgid "invalid iofd %d"
+msgstr "無效的 iofd %d"
+
+#: logsrvd/iolog_writer.c:626
+#, c-format
+msgid "error closing iofd %u: %s"
+msgstr "關閉 iofd %u 時發生錯誤:%s"
+
+#: logsrvd/iolog_writer.c:647
+#, c-format
+msgid "error flushing iofd %u: %s"
+msgstr "排清 iofd %u 時發生錯誤:%s"
+
+#: logsrvd/iolog_writer.c:765
+#, c-format
+msgid "invalid I/O log %s: %s referenced but not present"
+msgstr "無效的 I/O log %s:%s 有參考,但未呈現"
+
+#: logsrvd/iolog_writer.c:777 logsrvd/logsrvd_journal.c:391
+#, c-format
+msgid "%s: unable to find resume point [%lld, %ld]"
+msgstr "%s:找不到繼續點 [%lld, %ld]"
+
+#: logsrvd/iolog_writer.c:799 logsrvd/logsrvd_journal.c:434
+#: logsrvd/logsrvd_queue.c:115 logsrvd/tls_init.c:256
+#: plugins/sudoers/check.c:285 plugins/sudoers/cvtsudoers.c:758
+#: plugins/sudoers/cvtsudoers.c:780 plugins/sudoers/cvtsudoers.c:1461
+#: plugins/sudoers/cvtsudoers_csv.c:697 plugins/sudoers/cvtsudoers_json.c:902
+#: plugins/sudoers/cvtsudoers_ldif.c:711 plugins/sudoers/sudoers.c:1291
+#: plugins/sudoers/sudoers.c:1317 plugins/sudoers/sudoreplay.c:1497
+#: plugins/sudoers/timestamp.c:478 plugins/sudoers/tsdump.c:128
+#: plugins/sudoers/visudo.c:990
+#, c-format
+msgid "unable to open %s"
+msgstr "無法開啟 %s"
+
+#: logsrvd/iolog_writer.c:811 logsrvd/logsrv_util.c:111
+#: logsrvd/logsrv_util.c:118 plugins/sudoers/sudoreplay.c:355
+#: plugins/sudoers/sudoreplay.c:361
+#, c-format
+msgid "unable to open %s/%s"
+msgstr "無法開啟 %s/%s"
+
+#: logsrvd/iolog_writer.c:824
+#, c-format
+msgid "unable to copy %s/%s to %s/%s: %s"
+msgstr "無法複製 %s/%s 至 %s/%s:%s"
+
+#: logsrvd/iolog_writer.c:853 logsrvd/logsrvd_journal.c:198
+#, c-format
+msgid "unable to rename %s to %s"
+msgstr "無法重新命名 %s 至 %s"
+
+#: logsrvd/logsrv_util.c:153 logsrvd/logsrv_util.c:182
+#, c-format
+msgid "%s/%s: unable to find resume point [%lld, %ld]"
+msgstr "%s/%s:找不到繼續點 [%lld, %ld]"
+
+#: logsrvd/logsrv_util.c:165
+#, c-format
+msgid "missing I/O log file %s/%s"
+msgstr "缺少 I/O 記錄檔 %s/%s"
+
+#: logsrvd/logsrv_util.c:172
+#, c-format
+msgid "%s/%s: unable to seek forward %zu"
+msgstr "%s/%s:無法往前搜尋 %zu"
+
+#: logsrvd/logsrvd.c:271 logsrvd/logsrvd_queue.c:135
+msgid "unable to connect to relay"
+msgstr "無法連線至轉送點"
+
+#: logsrvd/logsrvd.c:338 logsrvd/logsrvd_relay.c:847
+#, c-format
+msgid "server message too large: %zu"
+msgstr "伺服器訊息過長:%zu"
+
+#: logsrvd/logsrvd.c:430 logsrvd/logsrvd.c:553 logsrvd/logsrvd.c:639
+#: logsrvd/logsrvd.c:881 logsrvd/logsrvd.c:895 logsrvd/logsrvd.c:1056
+#: logsrvd/logsrvd.c:1181 logsrvd/logsrvd.c:1354 logsrvd/logsrvd.c:1372
+#: logsrvd/logsrvd.c:1471 logsrvd/logsrvd.c:1596 logsrvd/logsrvd.c:1783
+#: logsrvd/logsrvd_journal.c:503 logsrvd/logsrvd_local.c:238
+#: logsrvd/logsrvd_queue.c:164 logsrvd/logsrvd_relay.c:172
+#: logsrvd/logsrvd_relay.c:249 logsrvd/logsrvd_relay.c:253
+#: logsrvd/logsrvd_relay.c:391 logsrvd/logsrvd_relay.c:583
+#: logsrvd/logsrvd_relay.c:747 logsrvd/logsrvd_relay.c:1137
+#: logsrvd/sendlog.c:1308 logsrvd/tls_client.c:136 logsrvd/tls_client.c:152
+#: logsrvd/tls_client.c:216 plugins/sudoers/audit.c:281
+#: plugins/sudoers/iolog.c:1041 plugins/sudoers/iolog.c:1175
+#: plugins/sudoers/iolog.c:1274 plugins/sudoers/log_client.c:121
+#: plugins/sudoers/log_client.c:343 plugins/sudoers/log_client.c:359
+#: plugins/sudoers/log_client.c:407 plugins/sudoers/log_client.c:613
+#: plugins/sudoers/log_client.c:620 plugins/sudoers/log_client.c:1114
+#: plugins/sudoers/log_client.c:1395 plugins/sudoers/log_client.c:1436
+#: plugins/sudoers/log_client.c:1444 plugins/sudoers/log_client.c:1603
+#: plugins/sudoers/log_client.c:1728 plugins/sudoers/log_client.c:2060
+#: plugins/sudoers/log_client.c:2068 plugins/sudoers/logging.c:148
+#: plugins/sudoers/logging.c:206 plugins/sudoers/sudoreplay.c:519
+#: plugins/sudoers/sudoreplay.c:566 plugins/sudoers/sudoreplay.c:808
+#: plugins/sudoers/sudoreplay.c:920 plugins/sudoers/sudoreplay.c:1011
+#: plugins/sudoers/sudoreplay.c:1026 plugins/sudoers/sudoreplay.c:1033
+#: plugins/sudoers/sudoreplay.c:1040 plugins/sudoers/sudoreplay.c:1047
+#: plugins/sudoers/sudoreplay.c:1054 plugins/sudoers/sudoreplay.c:1182
+msgid "unable to add event to queue"
+msgstr "無法將事件附加到佇列"
+
+#: logsrvd/logsrvd.c:454 logsrvd/logsrvd.c:491 logsrvd/logsrvd.c:523
+#: logsrvd/logsrvd.c:577 logsrvd/logsrvd.c:656 logsrvd/logsrvd.c:692
+#: logsrvd/logsrvd.c:728 logsrvd/logsrvd.c:764 logsrvd/logsrvd_relay.c:512
+#: logsrvd/logsrvd_relay.c:545
+#, c-format
+msgid "unexpected state %d for %s"
+msgstr "%2$s 發生非預期狀態 %1$d"
+
+#: logsrvd/logsrvd.c:455 logsrvd/logsrvd.c:492 logsrvd/logsrvd.c:524
+#: logsrvd/logsrvd.c:578 logsrvd/logsrvd.c:657 logsrvd/logsrvd.c:693
+#: logsrvd/logsrvd.c:729 logsrvd/logsrvd.c:765 logsrvd/logsrvd_relay.c:514
+#: logsrvd/logsrvd_relay.c:547
+msgid "state machine error"
+msgstr "狀態機器發生錯誤"
+
+#: logsrvd/logsrvd.c:461 logsrvd/logsrvd.c:462
+msgid "invalid AcceptMessage"
+msgstr "無效的 AcceptMessage"
+
+#: logsrvd/logsrvd.c:498 logsrvd/logsrvd.c:499
+msgid "invalid RejectMessage"
+msgstr "無效的 RejectMessage"
+
+#: logsrvd/logsrvd.c:530 logsrvd/logsrvd.c:531
+msgid "invalid ExitMessage"
+msgstr "無效的 ExitMessage"
+
+#: logsrvd/logsrvd.c:584 logsrvd/logsrvd.c:585
+msgid "invalid RestartMessage"
+msgstr "無效的 RestartMessage"
+
+#: logsrvd/logsrvd.c:619 logsrvd/logsrvd.c:620
+msgid "invalid AlertMessage"
+msgstr "無效的 AlertMessage"
+
+#: logsrvd/logsrvd.c:661 logsrvd/logsrvd.c:697 logsrvd/logsrvd.c:733
+#, c-format
+msgid "%s: unexpected IoBuffer"
+msgstr "%s:非預期的 IoBuffer"
+
+#: logsrvd/logsrvd.c:662 logsrvd/logsrvd.c:698 logsrvd/logsrvd.c:734
+msgid "protocol error"
+msgstr "通訊協定錯誤"
+
+#: logsrvd/logsrvd.c:668 logsrvd/logsrvd.c:669
+msgid "invalid IoBuffer"
+msgstr "無效的 IoBuffer"
+
+#: logsrvd/logsrvd.c:704 logsrvd/logsrvd.c:705
+msgid "invalid ChangeWindowSize"
+msgstr "無效的 ChangeWindowSize"
+
+#: logsrvd/logsrvd.c:740 logsrvd/logsrvd.c:741
+msgid "invalid CommandSuspend"
+msgstr "無效的 CommandSuspend"
+
+#: logsrvd/logsrvd.c:790 logsrvd/logsrvd_journal.c:302
+#: logsrvd/logsrvd_relay.c:654 logsrvd/sendlog.c:1207
+#: plugins/sudoers/log_client.c:1593
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "無法解開 %s(大小 %zu)"
+
+#: logsrvd/logsrvd.c:835 logsrvd/logsrvd_journal.c:376
+#: logsrvd/logsrvd_relay.c:678
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "從 %3$s 收到的 %2$s 中,發現非預期的 type_case 值 %1$d"
+
+#: logsrvd/logsrvd.c:837
+msgid "unrecognized ClientMessage type"
+msgstr "無法識別的 ClientMessage 類型"
+
+#: logsrvd/logsrvd.c:927
+#, c-format
+msgid "timed out writing to client %s"
+msgstr "寫入 %s 用戶端等待逾時"
+
+#: logsrvd/logsrvd.c:932 logsrvd/logsrvd_relay.c:919 logsrvd/sendlog.c:1413
+#, c-format
+msgid "missing write buffer for client %s"
+msgstr "缺少 %s 用戶端的寫入緩衝區"
+
+#: logsrvd/logsrvd.c:1027
+#, c-format
+msgid "timed out reading from client %s"
+msgstr "從 %s 用戶端讀取等待逾時"
+
+#: logsrvd/logsrvd.c:1068 logsrvd/logsrvd_relay.c:782
+#, c-format
+msgid "EOF from %s without proper TLS shutdown"
+msgstr "從 %s 收到 EOF,但其未正確關閉 TLS。"
+
+#: logsrvd/logsrvd.c:1112 logsrvd/logsrvd_relay.c:205 logsrvd/sendlog.c:336
+#: plugins/sudoers/log_client.c:723
+#, c-format
+msgid "client message too large: %zu"
+msgstr "用戶端訊息過長:%zu"
+
+#: logsrvd/logsrvd.c:1113 logsrvd/logsrvd_journal.c:259
+#: logsrvd/logsrvd_journal.c:260
+msgid "client message too large"
+msgstr "用戶端訊息過長"
+
+#: logsrvd/logsrvd.c:1131 logsrvd/logsrvd.c:1132
+msgid "invalid ClientMessage"
+msgstr "無效的 ClientMessage"
+
+#: logsrvd/logsrvd.c:1432
+msgid "unable to get remote IP addr"
+msgstr "無法取得遠端 IP 地址"
+
+#: logsrvd/logsrvd.c:1463 logsrvd/tls_client.c:203
+#: plugins/sudoers/log_client.c:281
+#, c-format
+msgid "Unable to attach user data to the ssl object: %s"
+msgstr "無法將使用者資料連結至 SSL 物件:%s"
+
+#: logsrvd/logsrvd.c:1646 logsrvd/logsrvd.c:2007
+msgid "unable to setup listen socket"
+msgstr "無法設定監聽 socket 通訊端"
+
+#: logsrvd/logsrvd.c:1766
+#, c-format
+msgid "unexpected signal %d"
+msgstr "發生非預期信號 %d"
+
+#: logsrvd/logsrvd.c:1909
+msgid "sudo log server"
+msgstr "sudo 記錄伺服器"
+
+#: logsrvd/logsrvd.c:1911 logsrvd/sendlog.c:126
+msgid "Options:"
+msgstr "選項:"
+
+#: logsrvd/logsrvd.c:1913
+msgid "path to configuration file"
+msgstr "設定檔路徑"
+
+#: logsrvd/logsrvd.c:1915 logsrvd/sendlog.c:128
+msgid "display help message and exit"
+msgstr "顯示說明訊息後結束"
+
+#: logsrvd/logsrvd.c:1917
+msgid "do not fork, run in the foreground"
+msgstr "不要 fork,在前景執行"
+
+#: logsrvd/logsrvd.c:1919
+msgid "percent chance connections will drop"
+msgstr "拋棄連線的機率百分比"
+
+#: logsrvd/logsrvd.c:1921 logsrvd/sendlog.c:158
+msgid "display version information and exit"
+msgstr "顯示版本資訊後結束"
+
+#: logsrvd/logsrvd.c:1971 logsrvd/sendlog.c:1722
+msgid "Protobuf-C version 1.3 or higher required"
+msgstr "需要 Protobuf-C 版本 1.3 或更高版本"
+
+#: logsrvd/logsrvd.c:1987
+#, c-format
+msgid "invalid random drop value: %s"
+msgstr "隨機丟棄值無效:%s"
+
+#: logsrvd/logsrvd.c:1990 logsrvd/sendlog.c:1776
+#: plugins/sudoers/cvtsudoers.c:250 plugins/sudoers/sudoreplay.c:294
+#: plugins/sudoers/visudo.c:181
+#, c-format
+msgid "%s version %s\n"
+msgstr "%s 版本 %s\n"
+
+#: logsrvd/logsrvd_conf.c:422 plugins/sudoers/check.c:69
+#: plugins/sudoers/exptilde.c:85 plugins/sudoers/iolog.c:122
+#: plugins/sudoers/sudoers.c:419 plugins/sudoers/sudoers.c:929
+#: plugins/sudoers/sudoers.c:1034 plugins/sudoers/sudoers.c:1424
+#: plugins/sudoers/testsudoers.c:169 plugins/sudoers/testsudoers.c:285
+#: plugins/sudoers/testsudoers.c:459
+#, c-format
+msgid "unknown user %s"
+msgstr "未知使用者 %s"
+
+#: logsrvd/logsrvd_conf.c:439 plugins/sudoers/iolog.c:148
+#: plugins/sudoers/sudoers.c:425 plugins/sudoers/sudoers.c:1458
+#: plugins/sudoers/testsudoers.c:483
+#, c-format
+msgid "unknown group %s"
+msgstr "未知群組 %s"
+
+#: logsrvd/logsrvd_conf.c:457
+#, c-format
+msgid "unable to parse iolog mode %s"
+msgstr "無法解析 iolog 模式 %s"
+
+#: logsrvd/logsrvd_conf.c:474 logsrvd/logsrvd_conf.c:1243
+#, c-format
+msgid "invalid value for %s: %s"
+msgstr "%s 的值無效:%s"
+
+#: logsrvd/logsrvd_conf.c:527
+msgid "TLS not supported"
+msgstr "不支援 TLS"
+
+#: logsrvd/logsrvd_conf.c:549
+#, c-format
+msgid "%s:%s"
+msgstr "%s:%s"
+
+#: logsrvd/logsrvd_conf.c:622 logsrvd/logsrvd_conf.c:1032
+#, c-format
+msgid "%s: not a fully qualified path"
+msgstr "%s:路徑不完全合法"
+
+#: logsrvd/logsrvd_conf.c:951 logsrvd/logsrvd_conf.c:967
+#: logsrvd/logsrvd_conf.c:1676
+#, c-format
+msgid "unknown syslog facility %s"
+msgstr "未知的 syslog 裝置 %s"
+
+#: logsrvd/logsrvd_conf.c:983 logsrvd/logsrvd_conf.c:999
+#: logsrvd/logsrvd_conf.c:1015 logsrvd/logsrvd_conf.c:1680
+#: logsrvd/logsrvd_conf.c:1684 logsrvd/logsrvd_conf.c:1688
+#, c-format
+msgid "unknown syslog priority %s"
+msgstr "未知 syslog 優先級 %s"
+
+#: logsrvd/logsrvd_conf.c:1197
+#, c-format
+msgid "%s:%d unmatched '[': %s"
+msgstr "%s:%d 不對稱的 '[': %s"
+
+#: logsrvd/logsrvd_conf.c:1203
+#, c-format
+msgid "%s:%d garbage after ']': %s"
+msgstr "%s:%d ‘]’ 後有垃圾資料:%s"
+
+#: logsrvd/logsrvd_conf.c:1215
+#, c-format
+msgid "%s:%d invalid config section: %s"
+msgstr "%s:%d 無效的設定檔區段:%s"
+
+#: logsrvd/logsrvd_conf.c:1223
+#, c-format
+msgid "%s:%d invalid configuration line: %s"
+msgstr "%s:%d 無效的設定檔行:%s"
+
+#: logsrvd/logsrvd_conf.c:1229
+#, c-format
+msgid "%s:%d expected section name: %s"
+msgstr "%s:%d 應有區段名稱:%s"
+
+#: logsrvd/logsrvd_conf.c:1251
+#, c-format
+msgid "%s:%d [%s] illegal key: %s"
+msgstr "%s:%d [%s] 本設定鍵無效:%s"
+
+#: logsrvd/logsrvd_conf.c:1281 plugins/sudoers/cvtsudoers.c:273
+#: plugins/sudoers/logging.c:1076
+#, c-format
+msgid "unable to open log file %s"
+msgstr "無法開啟記錄檔案 %s"
+
+#: logsrvd/logsrvd_conf.c:1763
+msgid "unable to initialize server TLS context"
+msgstr "無法初始化伺服器 TLS 上下文"
+
+#: logsrvd/logsrvd_conf.c:1783
+msgid "unable to initialize relay TLS context"
+msgstr "無法初始化轉送 TLS 上下文"
+
+#: logsrvd/logsrvd_journal.c:149 logsrvd/logsrvd_journal.c:430
+#: logsrvd/logsrvd_journal.c:435
+msgid "unable to create journal file"
+msgstr "無法建立日誌檔案"
+
+#: logsrvd/logsrvd_journal.c:153 logsrvd/logsrvd_queue.c:109
+#: plugins/sudoers/visudo.c:1046
+#, c-format
+msgid "unable to lock %s"
+msgstr "無法鎖定 %s"
+
+#: logsrvd/logsrvd_journal.c:156
+msgid "unable to lock journal file"
+msgstr "無法鎖定日誌檔案"
+
+#: logsrvd/logsrvd_journal.c:164
+msgid "unable to open journal file"
+msgstr "無法開啟日誌檔案"
+
+#: logsrvd/logsrvd_journal.c:185 logsrvd/logsrvd_journal.c:466
+#: logsrvd/logsrvd_journal.c:471
+msgid "unable to write journal file"
+msgstr "無法寫入日誌檔案"
+
+#: logsrvd/logsrvd_journal.c:193 logsrvd/logsrvd_journal.c:200
+msgid "unable to rename journal file"
+msgstr "無法重新命名日誌檔案"
+
+#: logsrvd/logsrvd_journal.c:247 logsrvd/logsrvd_journal.c:248
+#: logsrvd/logsrvd_journal.c:288 logsrvd/logsrvd_journal.c:289
+msgid "unexpected EOF reading journal file"
+msgstr "讀取日誌檔案時遇到非預期的結束字元 (EOF)"
+
+#: logsrvd/logsrvd_journal.c:251 logsrvd/logsrvd_journal.c:252
+#: logsrvd/logsrvd_journal.c:292 logsrvd/logsrvd_journal.c:293
+msgid "error reading journal file"
+msgstr "讀取日誌檔案時發生錯誤"
+
+#: logsrvd/logsrvd_journal.c:304 logsrvd/logsrvd_journal.c:390
+msgid "invalid journal file, unable to restart"
+msgstr "日誌檔案無效,無法重新開始"
+
+#: logsrvd/logsrvd_journal.c:449
+#, c-format
+msgid "unable to seek to [%lld, %ld] in journal file %s"
+msgstr "無法搜尋至 %3$s 檔案的 [%1$lld, %2$ld] 位置"
+
+#: logsrvd/logsrvd_local.c:166
+#, c-format
+msgid "unexpected value_case %d in %s from %s"
+msgstr "從 %3$s 收到的 %2$s 中,發現非預期的 value_case %1$d"
+
+#: logsrvd/logsrvd_local.c:194
+msgid "error parsing AcceptMessage"
+msgstr "解析 AcceptMessage 時發生錯誤"
+
+#: logsrvd/logsrvd_local.c:205
+msgid "error creating I/O log"
+msgstr "建立 I/O 日誌時發生錯誤"
+
+#: logsrvd/logsrvd_local.c:228
+msgid "error logging accept event"
+msgstr "記錄接受事件時發生錯誤"
+
+#: logsrvd/logsrvd_local.c:267
+msgid "error parsing RejectMessage"
+msgstr "解析 RejectMessage 時發生錯誤"
+
+#: logsrvd/logsrvd_local.c:291
+msgid "error logging reject event"
+msgstr "記錄拒絕事件時發生錯誤"
+
+#: logsrvd/logsrvd_local.c:427 logsrvd/logsrvd_local.c:437
+msgid "error logging exit event"
+msgstr "記錄離開 (exit) 事件時發生錯誤"
+
+#: logsrvd/logsrvd_local.c:494 logsrvd/logsrvd_local.c:495
+msgid "log is already complete, cannot be restarted"
+msgstr "記錄已完成,無法重新開始"
+
+#: logsrvd/logsrvd_local.c:525
+msgid "unable to restart log"
+msgstr "無法重新啟動記錄"
+
+#: logsrvd/logsrvd_local.c:541
+msgid "error parsing AlertMessage"
+msgstr "解析 AlertMessage 時發生錯誤"
+
+#: logsrvd/logsrvd_local.c:551
+msgid "error logging alert event"
+msgstr "記錄提醒事件時發生錯誤"
+
+#: logsrvd/logsrvd_local.c:587 logsrvd/logsrvd_local.c:650
+#: logsrvd/logsrvd_local.c:685
+#, c-format
+msgid "unable to format timing buffer, length %d"
+msgstr "無法格式化計時緩衝區,長度 %d"
+
+#: logsrvd/logsrvd_local.c:601 logsrvd/logsrvd_local.c:609
+#: logsrvd/logsrvd_local.c:657 logsrvd/logsrvd_local.c:692
+#: plugins/sudoers/sudoreplay.c:344 toke.l:981 toke.l:984
+#, c-format
+msgid "%s/%s: %s"
+msgstr "%s/%s: %s"
+
+#: logsrvd/logsrvd_local.c:620
+msgid "randomly dropping connection"
+msgstr "隨機丟棄連接"
+
+#: logsrvd/logsrvd_local.c:632
+msgid "error writing IoBuffer"
+msgstr "寫入 IoBuffer 時發生錯誤"
+
+#: logsrvd/logsrvd_local.c:667
+msgid "error writing ChangeWindowSize"
+msgstr "寫入 ChangeWindowSize 時發生錯誤"
+
+#: logsrvd/logsrvd_local.c:702
+msgid "error writing CommandSuspend"
+msgstr "寫入 CommandSuspend 時發生錯誤"
+
+#: logsrvd/logsrvd_relay.c:437
+msgid "TLS handshake with relay host failed"
+msgstr "無法與轉送主機進行 TLS 交握"
+
+#: logsrvd/logsrvd_relay.c:465
+msgid "unable to connect to relay host"
+msgstr "無法連線至轉送主機"
+
+#: logsrvd/logsrvd_relay.c:520
+#, c-format
+msgid "%s: invalid ServerHello, missing server_id"
+msgstr "%s:無效的 ServerHello,缺少 server_id"
+
+#: logsrvd/logsrvd_relay.c:522 logsrvd/sendlog.c:1111
+#: plugins/sudoers/log_client.c:1479
+msgid "invalid ServerHello"
+msgstr "無效的 ServerHello"
+
+#: logsrvd/logsrvd_relay.c:681
+msgid "unrecognized ServerMessage type"
+msgstr "未知 ServerMessage 類型"
+
+#: logsrvd/logsrvd_relay.c:710
+#, c-format
+msgid "timed out reading from relay %s (%s)"
+msgstr "從轉送點 %s 讀取等待逾時 (%s)"
+
+#: logsrvd/logsrvd_relay.c:712
+msgid "timeout reading from relay"
+msgstr "從轉送點讀取時等待逾時"
+
+#: logsrvd/logsrvd_relay.c:767
+msgid "relay host name does not match certificate"
+msgstr "轉送點主機名稱與憑證不同"
+
+#: logsrvd/logsrvd_relay.c:773 logsrvd/logsrvd_relay.c:787
+#: logsrvd/logsrvd_relay.c:794
+msgid "error reading from relay"
+msgstr "從轉送點讀取時發生錯誤"
+
+#: logsrvd/logsrvd_relay.c:815
+msgid "unable to read from relay"
+msgstr "無法從轉送點讀取"
+
+#: logsrvd/logsrvd_relay.c:830 logsrvd/logsrvd_relay.c:949
+msgid "relay server closed connection"
+msgstr "轉送伺服器已經關閉連線"
+
+#: logsrvd/logsrvd_relay.c:848
+msgid "server message too large"
+msgstr "伺服器訊息過長"
+
+#: logsrvd/logsrvd_relay.c:912
+#, c-format
+msgid "timed out writing to relay %s (%s)"
+msgstr "寫入轉送點 %s 等待逾時 (%s)"
+
+#: logsrvd/logsrvd_relay.c:914
+msgid "timeout writing to relay"
+msgstr "寫入至轉送點時等待逾時"
+
+#: logsrvd/logsrvd_relay.c:968 logsrvd/logsrvd_relay.c:975
+#: logsrvd/logsrvd_relay.c:987
+msgid "error writing to relay"
+msgstr "寫入至轉送點時發生錯誤"
+
+#: logsrvd/sendlog.c:124
+msgid "send sudo I/O log to remote server"
+msgstr "傳送 sudo I/O 記錄到遠端伺服器"
+
+#: logsrvd/sendlog.c:130
+msgid "only send an accept event (no I/O)"
+msgstr "只傳送接受事件(無 I/O)"
+
+#: logsrvd/sendlog.c:133
+msgid "certificate bundle file to verify server's cert against"
+msgstr "用來驗證伺服器 cert against 的憑證組合檔案"
+
+#: logsrvd/sendlog.c:135
+msgid "certificate file for TLS handshake"
+msgstr "用在 TLS 交握的憑證檔案"
+
+#: logsrvd/sendlog.c:138
+msgid "host to send logs to"
+msgstr "記錄的傳送目的地主機"
+
+#: logsrvd/sendlog.c:140
+msgid "remote ID of I/O log to be resumed"
+msgstr "要恢復的 I/O 記錄的遠端 ID"
+
+#: logsrvd/sendlog.c:143
+msgid "private key file"
+msgstr "私鑰檔案"
+
+#: logsrvd/sendlog.c:145
+msgid "do not verify server certificate"
+msgstr "不要驗證伺服器的憑證"
+
+#: logsrvd/sendlog.c:148
+msgid "port to use when connecting to host"
+msgstr "連接主機時要使用的連接埠"
+
+#: logsrvd/sendlog.c:150
+msgid "restart previous I/O log transfer"
+msgstr "重新開始上一個 I/O 記錄傳輸"
+
+#: logsrvd/sendlog.c:152
+msgid "reject the command with the given reason"
+msgstr "以指定理由拒絕命令"
+
+#: logsrvd/sendlog.c:154
+msgid "stop transfer after reaching this time"
+msgstr "超過指定時間時停止傳輸"
+
+#: logsrvd/sendlog.c:156
+msgid "test audit server by sending selected I/O log n times in parallel"
+msgstr "透過平行傳送選取 I/O 記錄 n 次來測試稽核伺服器"
+
+#: logsrvd/sendlog.c:181 plugins/sudoers/log_client.c:453
+#, c-format
+msgid "unable to look up %s:%s: %s"
+msgstr "無法查看 %s:%s: %s"
+
+#: logsrvd/sendlog.c:219
+msgid "unable to get server IP addr"
+msgstr "無法取得伺服器 IP 地址"
+
+#: logsrvd/sendlog.c:314 plugins/sudoers/sudoreplay.c:868
+#, c-format
+msgid "unable to read %s/%s: %s"
+msgstr "無法讀取 %s/%s: %s"
+
+#: logsrvd/sendlog.c:1035 plugins/sudoers/iolog.c:959
+#: plugins/sudoers/iolog.c:1034
+#, c-format
+msgid "unexpected I/O event %d"
+msgstr "不應有的 I/O 事件 %d"
+
+#: logsrvd/sendlog.c:1088 logsrvd/sendlog.c:1105 logsrvd/sendlog.c:1139
+#: plugins/sudoers/log_client.c:1129 plugins/sudoers/log_client.c:1405
+#: plugins/sudoers/log_client.c:1473 plugins/sudoers/log_client.c:1512
+#, c-format
+msgid "%s: unexpected state %d"
+msgstr "%s:不應有的狀態 %d"
+
+#: logsrvd/sendlog.c:1175 plugins/sudoers/log_client.c:1561
+#, c-format
+msgid "error message received from server: %s"
+msgstr "自伺服器接收到錯誤訊息:%s"
+
+#: logsrvd/sendlog.c:1188 plugins/sudoers/log_client.c:1574
+#, c-format
+msgid "abort message received from server: %s"
+msgstr "自伺服器接收到中止訊息:%s"
+
+#: logsrvd/sendlog.c:1247 plugins/sudoers/log_client.c:1624
+#, c-format
+msgid "%s: unexpected type_case value %d"
+msgstr "%s:不應有的 type_case 值 %d"
+
+#: logsrvd/sendlog.c:1276
+msgid "timeout reading from server"
+msgstr "從伺服器讀取逾時"
+
+#: logsrvd/sendlog.c:1327 plugins/sudoers/log_client.c:1747
+msgid "host name does not match certificate"
+msgstr "主機名稱和憑證不符"
+
+#: logsrvd/sendlog.c:1361
+msgid "premature EOF"
+msgstr "檔案過早結束"
+
+#: logsrvd/sendlog.c:1374 plugins/sudoers/log_client.c:1795
+#, c-format
+msgid "server message too large: %u"
+msgstr "伺服器訊息過長:%u"
+
+#: logsrvd/sendlog.c:1430
+msgid "timeout writing to server"
+msgstr "寫入至伺服器逾時"
+
+#: logsrvd/sendlog.c:1800
+msgid "both restart point and iolog ID must be specified"
+msgstr "必須指定重新啟動點 (restart point) 和 iolog ID"
+
+#: logsrvd/sendlog.c:1804
+msgid "a restart point may not be set when no I/O is sent"
+msgstr "未傳送 I/O 時,不應設定重新開始點"
+
+#: logsrvd/sendlog.c:1880
+#, c-format
+msgid "exited prematurely with state %d"
+msgstr "過早結束,狀態碼 %d"
+
+#: logsrvd/sendlog.c:1881
+#, c-format
+msgid "elapsed time sent to server [%lld, %ld]"
+msgstr "已傳送耗用時間至伺服器 [%lld, %ld]"
+
+#: logsrvd/sendlog.c:1883
+#, c-format
+msgid "commit point received from server [%lld, %ld]"
+msgstr "自伺服器接收到提交點 (commit point) [%lld, %ld]"
+
+#: logsrvd/tls_client.c:111 plugins/sudoers/log_client.c:315
+msgid "TLS handshake timeout occurred"
+msgstr "遇到 TLS 交握逾時"
+
+#: logsrvd/tls_client.c:131 logsrvd/tls_client.c:147
+#: plugins/sudoers/log_client.c:337 plugins/sudoers/log_client.c:353
+msgid "unable to set event"
+msgstr "無法設定事件"
+
+#: logsrvd/tls_client.c:157 logsrvd/tls_client.c:161
+#, c-format
+msgid "TLS connection failed: %s"
+msgstr "TLS 連線失敗:%s"
+
+#: logsrvd/tls_client.c:196
+#, c-format
+msgid "unable to allocate ssl object: %s"
+msgstr "無法配置 SSL 物件:%s"
+
+#: logsrvd/tls_client.c:210
+#, c-format
+msgid "Unable to attach socket to the ssl object: %s"
+msgstr "無法將 socket 通訊端連結至 SSL 物件:%s"
+
+#: logsrvd/tls_client.c:238
+msgid "unable to initialize TLS context"
+msgstr "無法初始化 TLS 上下文"
+
+#: logsrvd/tls_init.c:138 logsrvd/tls_init.c:146
+#, c-format
+msgid "unable to set TLS 1.2 ciphersuite to %s: %s"
+msgstr "無法將 TLS 1.2 加密套件設為 %s:%s"
+
+#: logsrvd/tls_init.c:166 logsrvd/tls_init.c:174
+#, c-format
+msgid "unable to set TLS 1.3 ciphersuite to %s: %s"
+msgstr "無法將 TLS 1.3 加密套件設為 %s:%s"
+
+#: logsrvd/tls_init.c:206 logsrvd/tls_init.c:227
+#, c-format
+msgid "unable to set diffie-hellman parameters: %s"
+msgstr "無法設定迪菲-赫爾曼參數:%s"
+
+#: logsrvd/tls_init.c:283
+#, c-format
+msgid "unable to create TLS context: %s"
+msgstr "無法建立 TLS 情境:%s"
+
+#: logsrvd/tls_init.c:290
+#, c-format
+msgid "unable to set minimum protocol version to TLS 1.2: %s"
+msgstr "無法將最低通訊協定版本設為 TLS 1.2:%s"
+
+#: plugins/sudoers/audit.c:272 plugins/sudoers/audit.c:452
+#: plugins/sudoers/log_client.c:962 plugins/sudoers/log_client.c:1011
+#: plugins/sudoers/log_client.c:1060 plugins/sudoers/log_client.c:1185
+#: plugins/sudoers/logging.c:614 plugins/sudoers/logging.c:732
+#: plugins/sudoers/logging.c:859 plugins/sudoers/logging.c:1031
+#: plugins/sudoers/policy.c:123
+msgid "unable to get time of day"
+msgstr "無法取得一日時間"
+
+#: plugins/sudoers/auth/aix_auth.c:282
+#, c-format
+msgid "unable to change password for %s"
+msgstr "無法變更 %s 的密碼"
+
+#: plugins/sudoers/auth/bsdauth.c:78
+#, c-format
+msgid "unable to get login class for user %s"
+msgstr "無法取得使用者 %s 的登入類別"
+
+#: plugins/sudoers/auth/bsdauth.c:85
+msgid "invalid authentication type"
+msgstr "無效的認證類型"
+
+#: plugins/sudoers/auth/bsdauth.c:90
+msgid "unable to begin BSD authentication"
+msgstr "無法開始進行 BSD 認證"
+
+#: plugins/sudoers/auth/bsdauth.c:97
+msgid "unable to initialize BSD authentication"
+msgstr "無法初始化 BSD 認證程序"
+
+#: plugins/sudoers/auth/bsdauth.c:191
+msgid "your account has expired"
+msgstr "您的帳號已經過期"
+
+#: plugins/sudoers/auth/bsdauth.c:193
+msgid "approval failed"
+msgstr "核可失敗"
+
+#: plugins/sudoers/auth/fwtk.c:62
+msgid "unable to read fwtk config"
+msgstr "無法讀取 fwtk 組態設定"
+
+#: plugins/sudoers/auth/fwtk.c:67
+msgid "unable to connect to authentication server"
+msgstr "無法連線到認證伺服器"
+
+#: plugins/sudoers/auth/fwtk.c:73 plugins/sudoers/auth/fwtk.c:99
+#: plugins/sudoers/auth/fwtk.c:131
+msgid "lost connection to authentication server"
+msgstr "失去對認證伺服器的連線"
+
+#: plugins/sudoers/auth/fwtk.c:77
+#, c-format
+msgid ""
+"authentication server error:\n"
+"%s"
+msgstr ""
+"認證伺服器發生錯誤:\n"
+"%s"
+
+#: plugins/sudoers/auth/kerb5.c:116
+#, c-format
+msgid "%s: unable to convert principal to string ('%s'): %s"
+msgstr "%s:無法將主體轉換成字串 ('%s'):%s"
+
+#: plugins/sudoers/auth/kerb5.c:166
+#, c-format
+msgid "%s: unable to parse '%s': %s"
+msgstr "%s:無法解析「%s」:%s"
+
+#: plugins/sudoers/auth/kerb5.c:175
+#, c-format
+msgid "%s: unable to resolve credential cache: %s"
+msgstr "%s:無法解析憑證快取:%s"
+
+#: plugins/sudoers/auth/kerb5.c:226
+#, c-format
+msgid "%s: unable to allocate options: %s"
+msgstr "%s:無法分配選項:%s"
+
+#: plugins/sudoers/auth/kerb5.c:241
+#, c-format
+msgid "%s: unable to get credentials: %s"
+msgstr "%s:無法取得憑證:%s"
+
+#: plugins/sudoers/auth/kerb5.c:254
+#, c-format
+msgid "%s: unable to initialize credential cache: %s"
+msgstr "%s:無法初始化憑證快取:%s"
+
+#: plugins/sudoers/auth/kerb5.c:257
+#, c-format
+msgid "%s: unable to store credential in cache: %s"
+msgstr "%s:無法將憑證儲存於快取:%s"
+
+#: plugins/sudoers/auth/kerb5.c:322
+#, c-format
+msgid "%s: unable to get host principal: %s"
+msgstr "%s:無法取得主機主體:%s"
+
+#: plugins/sudoers/auth/kerb5.c:336
+#, c-format
+msgid "%s: Cannot verify TGT! Possible attack!: %s"
+msgstr "%s:無法驗證 TGT!可能發生攻擊事件!:%s"
+
+#: plugins/sudoers/auth/pam.c:233
+#, c-format
+msgid "unable to initialize PAM: %s"
+msgstr "無法初始化 PAM:%s"
+
+#: plugins/sudoers/auth/pam.c:349
+#, c-format
+msgid "PAM authentication error: %s"
+msgstr "PAM 認證發生錯誤:%s"
+
+#: plugins/sudoers/auth/pam.c:369
+msgid "account validation failure, is your account locked?"
+msgstr "檢查帳號有效性失敗,請檢查您的帳號是否被鎖定。"
+
+#: plugins/sudoers/auth/pam.c:380
+msgid "Account or password is expired, reset your password and try again"
+msgstr "帳號或密碼已標為過期,請重設密碼後重試"
+
+#: plugins/sudoers/auth/pam.c:387
+#, c-format
+msgid "unable to change expired password: %s"
+msgstr "無法變更已過期密碼:%s"
+
+#: plugins/sudoers/auth/pam.c:398
+msgid "Password expired, contact your system administrator"
+msgstr "密碼已標為過期,請聯絡您的系統管理員"
+
+#: plugins/sudoers/auth/pam.c:403
+msgid "Account expired or PAM config lacks an \"account\" section for sudo, contact your system administrator"
+msgstr "帳號已過期或是 PAM 組態設定缺少 sudo 的 \"account\" 部份,請聯絡您的系統管理員"
+
+#: plugins/sudoers/auth/pam.c:411 plugins/sudoers/auth/pam.c:416
+#, c-format
+msgid "PAM account management error: %s"
+msgstr "PAM 帳號管理發生錯誤:%s"
+
+#: plugins/sudoers/auth/rfc1938.c:100 plugins/sudoers/visudo.c:266
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "您不在 %s 資料庫中"
+
+#: plugins/sudoers/auth/securid5.c:76
+msgid "failed to initialise the ACE API library"
+msgstr "無法初始化 ACE API 函式庫"
+
+#: plugins/sudoers/auth/securid5.c:108
+msgid "unable to contact the SecurID server"
+msgstr "無法聯繫 SecurID 伺服器"
+
+#: plugins/sudoers/auth/securid5.c:117
+msgid "User ID locked for SecurID Authentication"
+msgstr "用於 SecurID 認證的使用者 ID 已被鎖定"
+
+#: plugins/sudoers/auth/securid5.c:121 plugins/sudoers/auth/securid5.c:174
+msgid "invalid username length for SecurID"
+msgstr "用於 SecurID 的使用者名稱長度無效"
+
+#: plugins/sudoers/auth/securid5.c:125 plugins/sudoers/auth/securid5.c:179
+msgid "invalid Authentication Handle for SecurID"
+msgstr "用於 SecurID 的認證處理無效"
+
+#: plugins/sudoers/auth/securid5.c:129
+msgid "SecurID communication failed"
+msgstr "SecurID 通訊失敗"
+
+#: plugins/sudoers/auth/securid5.c:133 plugins/sudoers/auth/securid5.c:222
+msgid "unknown SecurID error"
+msgstr "未知 SecurID 錯誤"
+
+#: plugins/sudoers/auth/securid5.c:169
+msgid "invalid passcode length for SecurID"
+msgstr "用於 SecurID 的密碼長度無效"
+
+#: plugins/sudoers/auth/sia.c:72 plugins/sudoers/auth/sia.c:130
+msgid "unable to initialize SIA session"
+msgstr "無法初始化 SIA 工作階段"
+
+#: plugins/sudoers/auth/sudo_auth.c:141
+msgid "invalid authentication methods"
+msgstr "無效的認證方式"
+
+#: plugins/sudoers/auth/sudo_auth.c:143
+msgid "Invalid authentication methods compiled into sudo! You may not mix standalone and non-standalone authentication."
+msgstr "sudo 被編譯進無效的認證方式!您不能混合獨立及非獨立認證方式。"
+
+#: plugins/sudoers/auth/sudo_auth.c:296 plugins/sudoers/auth/sudo_auth.c:359
+msgid "no authentication methods"
+msgstr "沒有認證方式"
+
+#: plugins/sudoers/auth/sudo_auth.c:298
+msgid "There are no authentication methods compiled into sudo! If you want to turn off authentication, use the --disable-authentication configure option."
+msgstr "沒有編譯進 sudo 的認證方式!若要關閉認證功能,請使用 --disable-authentication 設定選項。"
+
+#: plugins/sudoers/auth/sudo_auth.c:361
+msgid "Unable to initialize authentication methods."
+msgstr "無法初始化認證方式。"
+
+#: plugins/sudoers/auth/sudo_auth.c:551
+msgid "Authentication methods:"
+msgstr "認證方式:"
+
+#: plugins/sudoers/bsm_audit.c:122 plugins/sudoers/bsm_audit.c:214
+msgid "Could not determine audit condition"
+msgstr "無法確定稽核條件"
+
+#: plugins/sudoers/bsm_audit.c:188 plugins/sudoers/bsm_audit.c:278
+msgid "unable to commit audit record"
+msgstr "無法提交稽核記錄"
+
+#: plugins/sudoers/check.c:63 plugins/sudoers/check.c:74
+#: plugins/sudoers/lookup.c:79 plugins/sudoers/tsdump.c:119
+#, c-format
+msgid "unknown uid %u"
+msgstr "未知 uid %u"
+
+#: plugins/sudoers/check.c:277
+#, c-format
+msgid "error reading lecture file %s"
+msgstr "讀取使用指引檔案 %s 時發生錯誤"
+
+#: plugins/sudoers/check.c:280
+#, c-format
+msgid "ignoring lecture file %s: not a regular file"
+msgstr "忽略使用指引檔案 %s:不是一般檔案"
+
+#: plugins/sudoers/check.c:293
+msgid ""
+"\n"
+"We trust you have received the usual lecture from the local System\n"
+"Administrator. It usually boils down to these three things:\n"
+"\n"
+" #1) Respect the privacy of others.\n"
+" #2) Think before you type.\n"
+" #3) With great power comes great responsibility.\n"
+"\n"
+msgstr ""
+"\n"
+"我們相信您已經從本機系統管理員取得\n"
+"日常注意事項。注意事項通常可以歸結為三件事情:\n"
+"\n"
+" #1) 尊重他人隱私。\n"
+" #2) 輸入指令前先三思。\n"
+" #3) 權力越大則責任越大。\n"
+"\n"
+
+#: plugins/sudoers/check.c:301
+msgid ""
+"For security reasons, the password you type will not be visible.\n"
+"\n"
+msgstr ""
+"考量到安全性因素,不會顯示您輸入的密碼。\n"
+"\n"
+
+#: plugins/sudoers/check_aliases.c:93
+#, c-format
+msgid "cycle in %s \"%s\""
+msgstr "%s「%s」中有循環"
+
+#: plugins/sudoers/check_aliases.c:96
+#, c-format
+msgid "%s \"%s\" referenced but not defined"
+msgstr "引用了尚未定義的 %s「%s」"
+
+#: plugins/sudoers/cvtsudoers.c:211
+#, c-format
+msgid "order increment: %s: %s"
+msgstr "新增順序:%s:%s"
+
+#: plugins/sudoers/cvtsudoers.c:231
+#, c-format
+msgid "starting order: %s: %s"
+msgstr "順序開頭:%s:%s"
+
+#: plugins/sudoers/cvtsudoers.c:242
+#, c-format
+msgid "order padding: %s: %s"
+msgstr "順序間距:%s:%s"
+
+#: plugins/sudoers/cvtsudoers.c:252 plugins/sudoers/visudo.c:183
+#, c-format
+msgid "%s grammar version %d\n"
+msgstr "%s 語法版本 %d\n"
+
+#: plugins/sudoers/cvtsudoers.c:282 plugins/sudoers/testsudoers.c:162
+#, c-format
+msgid "unsupported input format %s"
+msgstr "不支援的輸入格式 %s"
+
+#: plugins/sudoers/cvtsudoers.c:300
+#, c-format
+msgid "unsupported output format %s"
+msgstr "不支援的輸出格式 %s"
+
+#: plugins/sudoers/cvtsudoers.c:392
+#, c-format
+msgid "%s: input and output files must be different"
+msgstr "%s:輸入及輸出檔案必須不一致"
+
+#: plugins/sudoers/cvtsudoers.c:406 plugins/sudoers/sudoers.c:151
+#: plugins/sudoers/sudoers.c:209 plugins/sudoers/testsudoers.c:315
+#: plugins/sudoers/visudo.c:276 plugins/sudoers/visudo.c:666
+msgid "unable to initialize sudoers default values"
+msgstr "無法初始化 sudoers 預設值"
+
+#: plugins/sudoers/cvtsudoers.c:533 plugins/sudoers/ldap_conf.c:431
+#, c-format
+msgid "%s: %s: %s: %s"
+msgstr "%s: %s: %s: %s"
+
+#: plugins/sudoers/cvtsudoers.c:612
+#, c-format
+msgid "%s: unknown key word %s"
+msgstr "%s:未知關鍵字 %s"
+
+#: plugins/sudoers/cvtsudoers.c:658
+#, c-format
+msgid "invalid defaults type: %s"
+msgstr "預設類型無效:%s"
+
+#: plugins/sudoers/cvtsudoers.c:681
+#, c-format
+msgid "invalid suppression type: %s"
+msgstr "隱藏類型無效:%s"
+
+#: plugins/sudoers/cvtsudoers.c:722 plugins/sudoers/cvtsudoers.c:738
+#, c-format
+msgid "invalid filter: %s"
+msgstr "篩選器無效:%s"
+
+#: plugins/sudoers/cvtsudoers.c:783 plugins/sudoers/visudo.c:1000
+#, c-format
+msgid "failed to parse %s file, unknown error"
+msgstr "無法解析 %s 檔案,原因:未知錯誤"
+
+#: plugins/sudoers/cvtsudoers.c:1508 plugins/sudoers/sudoreplay.c:1143
+#: plugins/sudoers/timestamp.c:353 plugins/sudoers/timestamp.c:356
+#, c-format
+msgid "unable to write to %s"
+msgstr "無法寫入 %s"
+
+#: plugins/sudoers/cvtsudoers.c:1536
+#, c-format
+msgid ""
+"%s - convert between sudoers file formats\n"
+"\n"
+msgstr ""
+"%s - 轉換 sudoers 檔案之間的格式\n"
+"\n"
+
+#: plugins/sudoers/cvtsudoers.c:1538
+msgid ""
+"\n"
+"Options:\n"
+" -b, --base=dn the base DN for sudo LDAP queries\n"
+" -c, --config=conf_file the path to the configuration file\n"
+" -d, --defaults=deftypes only convert Defaults of the specified types\n"
+" -e, --expand-aliases expand aliases when converting\n"
+" -f, --output-format=format set output format: JSON, LDIF or sudoers\n"
+" -i, --input-format=format set input format: LDIF or sudoers\n"
+" -I, --increment=num amount to increase each sudoOrder by\n"
+" -h, --help display help message and exit\n"
+" -m, --match=filter only convert entries that match the filter\n"
+" -M, --match-local match filter uses passwd and group databases\n"
+" -o, --output=output_file write converted sudoers to output_file\n"
+" -O, --order-start=num starting point for first sudoOrder\n"
+" -p, --prune-matches prune non-matching users, groups and hosts\n"
+" -P, --padding=num base padding for sudoOrder increment\n"
+" -s, --suppress=sections suppress output of certain sections\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"選項:\n"
+" -b, --base=dn 用於 sudo LDAP 查詢的基礎 DN\n"
+" -c, --config=設定檔 組態設定檔的路徑\n"
+" -d, --defaults=deftypes 只轉換指定類型的預設值\n"
+" -e, --expand-aliases 在轉換時展開別名\n"
+" -f, --output-format=格式 設定輸出格式:JSON、LDIF 或 sudoers\n"
+" -i, --input-format=格式 設定輸入格式:LDIF 或 sudoers\n"
+" -I, --increment=量 每個 sudoOrder 的增加量\n"
+" -h, --help 顯示說明訊息後退出\n"
+" -m, --match=篩選器 只轉換符合過濾器的條目\n"
+" -M, --match-local 符合使用 passwd 和群組資料庫的篩選器\n"
+" -o, --output=輸出檔 將轉換後的 sudoers 寫入 <輸出檔>\n"
+" -O, --order-start=起點值 第一個 sudoOrder 的起點\n"
+" -p, --prune-matches 清理不符合的使用者、群組和主機\n"
+" -P, --padding=間隔 sudoOrder 的增加間隔\n"
+" -s, --suppress=部份 隱藏某些部分的輸出\n"
+" -V, --version 顯示版本訊息後退出"
+
+#: plugins/sudoers/cvtsudoers_csv.c:192 plugins/sudoers/cvtsudoers_csv.c:199
+#: plugins/sudoers/cvtsudoers_ldif.c:245 plugins/sudoers/cvtsudoers_ldif.c:252
+#: plugins/sudoers/cvtsudoers_ldif.c:594 plugins/sudoers/env.c:340
+#: plugins/sudoers/env.c:347 plugins/sudoers/env.c:458
+#: plugins/sudoers/ldap.c:511 plugins/sudoers/ldap.c:629
+#: plugins/sudoers/ldap.c:1003 plugins/sudoers/ldap_conf.c:219
+#: plugins/sudoers/ldap_conf.c:310 plugins/sudoers/ldap_util.c:486
+#: plugins/sudoers/linux_audit.c:93 plugins/sudoers/logging.c:479
+#: plugins/sudoers/policy.c:828 plugins/sudoers/policy.c:840
+#: plugins/sudoers/prompt.c:169 plugins/sudoers/serialize_list.c:62
+#: plugins/sudoers/serialize_list.c:71 plugins/sudoers/strvec_join.c:62
+#: plugins/sudoers/sudoreplay.c:1340 plugins/sudoers/sudoreplay.c:1346
+#: plugins/sudoers/sudoreplay.c:1352 plugins/sudoers/testsudoers.c:306
+#: plugins/sudoers/toke_util.c:217 toke.l:995 toke.l:1277
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "內部錯誤,%s 溢出"
+
+#: plugins/sudoers/cvtsudoers_csv.c:454 plugins/sudoers/cvtsudoers_csv.c:468
+#: plugins/sudoers/cvtsudoers_json.c:661 plugins/sudoers/cvtsudoers_json.c:676
+#: plugins/sudoers/cvtsudoers_ldif.c:349 plugins/sudoers/cvtsudoers_ldif.c:362
+#: plugins/sudoers/ldap.c:495
+msgid "unable to get GMT time"
+msgstr "無法取得 GMT 時間"
+
+#: plugins/sudoers/cvtsudoers_csv.c:459 plugins/sudoers/cvtsudoers_csv.c:473
+#: plugins/sudoers/cvtsudoers_json.c:666 plugins/sudoers/cvtsudoers_json.c:681
+#: plugins/sudoers/cvtsudoers_ldif.c:354 plugins/sudoers/cvtsudoers_ldif.c:367
+#: plugins/sudoers/ldap.c:503
+msgid "unable to format timestamp"
+msgstr "無法格式化時間戳"
+
+#: plugins/sudoers/cvtsudoers_json.c:481 plugins/sudoers/cvtsudoers_json.c:516
+#: plugins/sudoers/cvtsudoers_json.c:732
+#, c-format
+msgid "%s:%d:%d: unknown defaults entry \"%s\""
+msgstr "%s:%d:%d: 未知的預設條目「%s」"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:663
+#, c-format
+msgid "too many sudoers entries, maximum %u"
+msgstr "過多 sudoers 項,最大值為 %u"
+
+#: plugins/sudoers/cvtsudoers_ldif.c:706
+msgid "the SUDOERS_BASE environment variable is not set and the -b option was not specified."
+msgstr "未設定 SUDOERS_BASE 環境變數,且亦未指定 -b 選項。"
+
+#: plugins/sudoers/cvtsudoers_merge.c:273
+#: plugins/sudoers/cvtsudoers_merge.c:309
+#, c-format
+msgid "%s:%d:%d: converting host list to ALL"
+msgstr "%s:%d:%d: 將主機清單轉換為 ALL"
+
+#: plugins/sudoers/cvtsudoers_merge.c:545
+#, c-format
+msgid "unable to find alias %s"
+msgstr "找不到 %s 別名"
+
+#: plugins/sudoers/cvtsudoers_merge.c:548
+#, c-format
+msgid "%s:%d:%d: renaming alias %s to %s"
+msgstr "%s:%d:%d: 將 %s 別名重新命名為 %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:605
+#, c-format
+msgid "%s:%d:%d: removing duplicate alias %s"
+msgstr "%s:%d:%d: 移除重複別名 %s"
+
+#: plugins/sudoers/cvtsudoers_merge.c:830
+#, c-format
+msgid "%s:%d:%d: conflicting Defaults entry \"%s\" host-specific in %s:%d:%d"
+msgstr ""
+
+#: plugins/sudoers/cvtsudoers_merge.c:864
+#, c-format
+msgid "%s:%d:%d: made Defaults \"%s\" specific to host %s"
+msgstr "%s:%d:%d: 讓 Defaults “%s” 針對 %s 主機"
+
+#: plugins/sudoers/cvtsudoers_merge.c:882
+#, c-format
+msgid "%s:%d:%d: unable to make Defaults \"%s\" host-specific"
+msgstr "%s:%d:%d: 無法讓 Defaults「%s」限定於主機"
+
+#: plugins/sudoers/cvtsudoers_merge.c:892
+#, c-format
+msgid "%s:%d:%d: removing Defaults \"%s\" overridden by subsequent entries"
+msgstr "%s:%d:%d: 移除被後續項目覆蓋的 Defaults「%s」"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1088
+#, c-format
+msgid "%s:%d:%d: merging userspec into %s:%d:%d"
+msgstr "%s:%d:%d: 將使用者規格 (userspec) 合併至 %s:%d:%d"
+
+#: plugins/sudoers/cvtsudoers_merge.c:1182
+#, c-format
+msgid "%s:%d:%d: removing userspec overridden by subsequent entries"
+msgstr "%s:%d:%d: 移除被後續項目覆蓋的 userspec"
+
+#: plugins/sudoers/def_data.c:56
+#, c-format
+msgid "Syslog facility if syslog is being used for logging: %s"
+msgstr "若使用了 syslog 記錄,要使用的 syslog 裝置:%s"
+
+#: plugins/sudoers/def_data.c:60
+#, c-format
+msgid "Syslog priority to use when user authenticates successfully: %s"
+msgstr "使用者認證成功時要使用的 syslog 記錄優先級:%s"
+
+#: plugins/sudoers/def_data.c:64
+#, c-format
+msgid "Syslog priority to use when user authenticates unsuccessfully: %s"
+msgstr "使用者認證不成功時使用的 syslog 記錄優先級:%s"
+
+#: plugins/sudoers/def_data.c:68
+msgid "Put OTP prompt on its own line"
+msgstr "將 OPT 提示放在獨自的行中"
+
+#: plugins/sudoers/def_data.c:72
+msgid "Ignore '.' in $PATH"
+msgstr "忽略 $PATH 中的「.」"
+
+#: plugins/sudoers/def_data.c:76
+msgid "Always send mail when sudo is run"
+msgstr "永遠在 sudo 執行時傳送信件"
+
+#: plugins/sudoers/def_data.c:80
+msgid "Send mail if user authentication fails"
+msgstr "使用者認證失敗後傳送信件"
+
+#: plugins/sudoers/def_data.c:84
+msgid "Send mail if the user is not in sudoers"
+msgstr "當使用者不在 sudoers 中時傳送信件"
+
+#: plugins/sudoers/def_data.c:88
+msgid "Send mail if the user is not in sudoers for this host"
+msgstr "當使用者不在此主機的 sudoers 中時傳送信件"
+
+#: plugins/sudoers/def_data.c:92
+msgid "Send mail if the user is not allowed to run a command"
+msgstr "當使用者不允許執行某指令時傳送信件"
+
+#: plugins/sudoers/def_data.c:96
+msgid "Send mail if the user tries to run a command"
+msgstr "當使用者嘗試執行某指令時傳送信件"
+
+#: plugins/sudoers/def_data.c:100
+msgid "Use a separate timestamp for each user/tty combo"
+msgstr "對每個使用者和終端組合使用單獨的時間戳"
+
+#: plugins/sudoers/def_data.c:104
+msgid "Lecture user the first time they run sudo"
+msgstr "在使用者第一次執行 sudo 時,通知使用者相關使用指引"
+
+#: plugins/sudoers/def_data.c:108
+#, c-format
+msgid "File containing the sudo lecture: %s"
+msgstr "包含 sudo 使用指引的檔案:%s"
+
+#: plugins/sudoers/def_data.c:112
+msgid "Require users to authenticate by default"
+msgstr "預設要求使用者認證"
+
+#: plugins/sudoers/def_data.c:116
+msgid "Root may run sudo"
+msgstr "Root 可以執行 sudo"
+
+#: plugins/sudoers/def_data.c:120
+msgid "Log the hostname in the (non-syslog) log file"
+msgstr "在(非 syslog)記錄檔中記錄主機名稱"
+
+#: plugins/sudoers/def_data.c:124
+msgid "Log the year in the (non-syslog) log file"
+msgstr "在(非 syslog)記錄檔中記錄年份"
+
+#: plugins/sudoers/def_data.c:128
+msgid "If sudo is invoked with no arguments, start a shell"
+msgstr "若 sudo 不傳入參數呼叫,就開啟 shell"
+
+#: plugins/sudoers/def_data.c:132
+msgid "Set $HOME to the target user when starting a shell with -s"
+msgstr "若以 -s 參數開啟 shell,就設定目標使用者的 $HOME"
+
+#: plugins/sudoers/def_data.c:136
+msgid "Always set $HOME to the target user's home directory"
+msgstr "永遠將 $HOME 設定為目標使用者的家目錄"
+
+#: plugins/sudoers/def_data.c:140
+msgid "Allow some information gathering to give useful error messages"
+msgstr "允許收集一些訊息以提供有用的錯誤訊息"
+
+#: plugins/sudoers/def_data.c:144
+msgid "Require fully-qualified hostnames in the sudoers file"
+msgstr "要求在 sudoers 檔案中包含完整的主機名稱"
+
+#: plugins/sudoers/def_data.c:148
+msgid "Insult the user when they enter an incorrect password"
+msgstr "在使用者輸入錯誤密碼時嘲諷他們"
+
+#: plugins/sudoers/def_data.c:152
+msgid "Only allow the user to run sudo if they have a tty"
+msgstr "只允許有終端的使用者執行 sudo"
+
+#: plugins/sudoers/def_data.c:156
+msgid "Visudo will honor the EDITOR environment variable"
+msgstr "Visudo 將優先考慮 EDITOR 環境變數"
+
+#: plugins/sudoers/def_data.c:160
+msgid "Prompt for root's password, not the users's"
+msgstr "詢問 root 使用者的密碼而非使用者的密碼"
+
+#: plugins/sudoers/def_data.c:164
+msgid "Prompt for the runas_default user's password, not the users's"
+msgstr "詢問 runas_default 使用者的密碼,而非使用者密碼"
+
+#: plugins/sudoers/def_data.c:168
+msgid "Prompt for the target user's password, not the users's"
+msgstr "詢問目標使用者的密碼,而非使用者密碼"
+
+#: plugins/sudoers/def_data.c:172
+msgid "Apply defaults in the target user's login class if there is one"
+msgstr "若有則套用目標使用者登入類別中的預設設定"
+
+#: plugins/sudoers/def_data.c:176
+msgid "Set the LOGNAME and USER environment variables"
+msgstr "設定 LOGNAME 和 USER 環境變數"
+
+#: plugins/sudoers/def_data.c:180
+msgid "Only set the effective uid to the target user, not the real uid"
+msgstr "只將有效使用者 ID 設為目標使用者的 ID,而非實際使用者的 ID"
+
+#: plugins/sudoers/def_data.c:184
+msgid "Don't initialize the group vector to that of the target user"
+msgstr "不將群組集合初始化成目標使用者的群組集合"
+
+#: plugins/sudoers/def_data.c:188
+#, c-format
+msgid "Length at which to wrap log file lines (0 for no wrap): %u"
+msgstr "記錄檔案要換行的長度 (0 則不換行):%u"
+
+#: plugins/sudoers/def_data.c:192
+#, c-format
+msgid "Authentication timestamp timeout: %.1f minutes"
+msgstr "認證時間戳逾時:%.1f 分鐘"
+
+#: plugins/sudoers/def_data.c:196
+#, c-format
+msgid "Password prompt timeout: %.1f minutes"
+msgstr "密碼提示逾時:%.1f 分鐘"
+
+#: plugins/sudoers/def_data.c:200
+#, c-format
+msgid "Number of tries to enter a password: %u"
+msgstr "密碼輸入嘗試次數:%u"
+
+#: plugins/sudoers/def_data.c:204
+#, c-format
+msgid "Umask to use or 0777 to use user's: 0%o"
+msgstr "要使用的 umask,或設定 0777 以使用使用者的 umask:0%o"
+
+#: plugins/sudoers/def_data.c:208
+#, c-format
+msgid "Path to log file: %s"
+msgstr "記錄檔案路徑:%s"
+
+#: plugins/sudoers/def_data.c:212
+#, c-format
+msgid "Path to mail program: %s"
+msgstr "郵件程式路徑:%s"
+
+#: plugins/sudoers/def_data.c:216
+#, c-format
+msgid "Flags for mail program: %s"
+msgstr "郵件程式旗標:%s"
+
+#: plugins/sudoers/def_data.c:220
+#, c-format
+msgid "Address to send mail to: %s"
+msgstr "傳送郵件的位址:%s"
+
+#: plugins/sudoers/def_data.c:224
+#, c-format
+msgid "Address to send mail from: %s"
+msgstr "接收郵件的位址:%s"
+
+#: plugins/sudoers/def_data.c:228
+#, c-format
+msgid "Subject line for mail messages: %s"
+msgstr "郵件訊息的主旨:%s"
+
+#: plugins/sudoers/def_data.c:232
+#, c-format
+msgid "Incorrect password message: %s"
+msgstr "密碼不正確的訊息:%s"
+
+#: plugins/sudoers/def_data.c:236
+#, c-format
+msgid "Path to lecture status dir: %s"
+msgstr "指引狀態資料夾的路徑:%s"
+
+#: plugins/sudoers/def_data.c:240
+#, c-format
+msgid "Path to authentication timestamp dir: %s"
+msgstr "認證時間戳資料夾的路徑:%s"
+
+#: plugins/sudoers/def_data.c:244
+#, c-format
+msgid "Owner of the authentication timestamp dir: %s"
+msgstr "認證時間戳的所有者:%s"
+
+#: plugins/sudoers/def_data.c:248
+#, c-format
+msgid "Users in this group are exempt from password and PATH requirements: %s"
+msgstr "此群組內的使用者不需要輸入密碼和 PATH:%s"
+
+#: plugins/sudoers/def_data.c:252
+#, c-format
+msgid "Default password prompt: %s"
+msgstr "預設密碼提示:%s"
+
+#: plugins/sudoers/def_data.c:256
+msgid "If set, passprompt will override system prompt in all cases."
+msgstr "如果設定,密碼提示將覆蓋所有情況下的系統提示。"
+
+#: plugins/sudoers/def_data.c:260
+#, c-format
+msgid "Default user to run commands as: %s"
+msgstr "要執行指令的預設使用者:%s"
+
+#: plugins/sudoers/def_data.c:264
+#, c-format
+msgid "Value to override user's $PATH with: %s"
+msgstr "要覆蓋使用者 $PATH 變數的值:%s"
+
+#: plugins/sudoers/def_data.c:268
+#, c-format
+msgid "Path to the editor for use by visudo: %s"
+msgstr "visudo 所使用編輯器的路徑:%s"
+
+#: plugins/sudoers/def_data.c:272
+#, c-format
+msgid "When to require a password for 'list' pseudocommand: %s"
+msgstr "何時要為「list」偽指令請求密碼:%s"
+
+#: plugins/sudoers/def_data.c:276
+#, c-format
+msgid "When to require a password for 'verify' pseudocommand: %s"
+msgstr "何時要為「verify」偽指令請求密碼:%s"
+
+#: plugins/sudoers/def_data.c:280
+msgid "Preload the sudo_noexec library which replaces the exec functions"
+msgstr "預載會替換掉 exec 函數的 sudo_noexec 函式庫"
+
+#: plugins/sudoers/def_data.c:284
+msgid "If LDAP directory is up, do we ignore local sudoers file"
+msgstr "如果有啟用 LDAP 目錄,是否要忽略本機的 sudoers 檔案"
+
+#: plugins/sudoers/def_data.c:288
+#, c-format
+msgid "File descriptors >= %d will be closed before executing a command"
+msgstr ">= %d 的檔案描述符將會在執行指令前關閉"
+
+#: plugins/sudoers/def_data.c:292
+msgid "If set, users may override the value of \"closefrom\" with the -C option"
+msgstr "如果設定,使用者可以透過 -C 選項覆蓋「closefrom」的值"
+
+#: plugins/sudoers/def_data.c:296
+msgid "Allow users to set arbitrary environment variables"
+msgstr "允許使用者設定任意的環境變數"
+
+#: plugins/sudoers/def_data.c:300
+msgid "Reset the environment to a default set of variables"
+msgstr "將環境重設為預設的變數集"
+
+#: plugins/sudoers/def_data.c:304
+msgid "Environment variables to check for safety:"
+msgstr "用來檢查安全性的環境變數:"
+
+#: plugins/sudoers/def_data.c:308
+msgid "Environment variables to remove:"
+msgstr "要移除的環境變數:"
+
+#: plugins/sudoers/def_data.c:312
+msgid "Environment variables to preserve:"
+msgstr "要保留的環境變數:"
+
+#: plugins/sudoers/def_data.c:316
+#, c-format
+msgid "SELinux role to use in the new security context: %s"
+msgstr "要在新的安全上下文中使用的 SELinux 角色:%s"
+
+#: plugins/sudoers/def_data.c:320
+#, c-format
+msgid "SELinux type to use in the new security context: %s"
+msgstr "要在新的安全上下文中使用的 SELinux 類型:%s"
+
+#: plugins/sudoers/def_data.c:324
+#, c-format
+msgid "Path to the sudo-specific environment file: %s"
+msgstr "sudo 特定環境檔案的路徑:%s"
+
+#: plugins/sudoers/def_data.c:328
+#, c-format
+msgid "Path to the restricted sudo-specific environment file: %s"
+msgstr "受限 sudo 特定環境檔案的路徑:%s"
+
+#: plugins/sudoers/def_data.c:332
+#, c-format
+msgid "Locale to use while parsing sudoers: %s"
+msgstr "解析 sudoers 時要使用的區域設定:%s"
+
+#: plugins/sudoers/def_data.c:336
+msgid "Allow sudo to prompt for a password even if it would be visible"
+msgstr "允許 sudo 詢問密碼,即使它不可見"
+
+#: plugins/sudoers/def_data.c:340
+msgid "Provide visual feedback at the password prompt when there is user input"
+msgstr "使用者在密碼提示輸入時提供視覺回饋"
+
+#: plugins/sudoers/def_data.c:344
+msgid "Use faster globbing that is less accurate but does not access the filesystem"
+msgstr "使用不太精確但不用存取檔案系統的較快 glob 方法"
+
+#: plugins/sudoers/def_data.c:348
+msgid "The umask specified in sudoers will override the user's, even if it is more permissive"
+msgstr "sudoers 中指定的 umask 會覆蓋使用者的 umask,即使使用者允許的權限更多"
+
+#: plugins/sudoers/def_data.c:352
+msgid "Log user's input for the command being run"
+msgstr "記錄指令執行時使用者的輸入內容"
+
+#: plugins/sudoers/def_data.c:356
+msgid "Log the command's standard input if not connected to a terminal"
+msgstr "如果未連結至終端機,則記錄命令的標準輸入"
+
+#: plugins/sudoers/def_data.c:360
+msgid "Log the user's terminal input for the command being run"
+msgstr "記錄命令執行時,使用者在終端機的輸入內容"
+
+#: plugins/sudoers/def_data.c:364
+msgid "Log the output of the command being run"
+msgstr "記錄命令執行時的輸出內容"
+
+#: plugins/sudoers/def_data.c:368
+msgid "Log the command's standard output if not connected to a terminal"
+msgstr "如果未連結至終端機,則記錄命令的標準輸出"
+
+#: plugins/sudoers/def_data.c:372
+msgid "Log the command's standard error if not connected to a terminal"
+msgstr "如果未連結至終端機,則記錄命令的標準錯誤"
+
+#: plugins/sudoers/def_data.c:376
+msgid "Log the terminal output of the command being run"
+msgstr "記錄命令執行時的終端機輸出內容"
+
+#: plugins/sudoers/def_data.c:380
+msgid "Compress I/O logs using zlib"
+msgstr "使用 zlib 壓縮 I/O 記錄"
+
+#: plugins/sudoers/def_data.c:384
+msgid "Always run commands in a pseudo-tty"
+msgstr "總是在偽終端中執行指令"
+
+#: plugins/sudoers/def_data.c:388
+#, c-format
+msgid "Plugin for non-Unix group support: %s"
+msgstr "用於非 Unix 群組支援的外掛程式:%s"
+
+#: plugins/sudoers/def_data.c:392
+#, c-format
+msgid "Directory in which to store input/output logs: %s"
+msgstr "用於儲存輸入/輸出記錄的目錄:%s"
+
+#: plugins/sudoers/def_data.c:396
+#, c-format
+msgid "File in which to store the input/output log: %s"
+msgstr "用於儲存輸入/輸出記錄的檔案:%s"
+
+#: plugins/sudoers/def_data.c:400
+msgid "Add an entry to the utmp/utmpx file when allocating a pty"
+msgstr "在分配偽終端時向 utmp/utmpx 檔案中附加一條記錄"
+
+#: plugins/sudoers/def_data.c:404
+msgid "Set the user in utmp to the runas user, not the invoking user"
+msgstr "將 utmp 中的使用者設為 runas 使用者,而不是呼叫使用者"
+
+#: plugins/sudoers/def_data.c:408
+#, c-format
+msgid "Set of permitted privileges: %s"
+msgstr "核准的權限集合:%s"
+
+#: plugins/sudoers/def_data.c:412
+#, c-format
+msgid "Set of limit privileges: %s"
+msgstr "限制的權限集合:%s"
+
+#: plugins/sudoers/def_data.c:416
+msgid "Run commands on a pty in the background"
+msgstr "在背景的偽終端上執行指令"
+
+#: plugins/sudoers/def_data.c:420
+#, c-format
+msgid "PAM service name to use: %s"
+msgstr "要使用的 PAM 服務名稱:%s"
+
+#: plugins/sudoers/def_data.c:424
+#, c-format
+msgid "PAM service name to use for login shells: %s"
+msgstr "用於登入 shell 的 PAM 服務名稱:%s"
+
+#: plugins/sudoers/def_data.c:428
+#, c-format
+msgid "PAM service name to use when sudo is run with the -A option: %s"
+msgstr "sudo 以 -A 選項執行時,要使用的 PAM 服務名稱:%s"
+
+#: plugins/sudoers/def_data.c:432
+msgid "Attempt to establish PAM credentials for the target user"
+msgstr "嘗試為目標使用者建立 PAM 憑證"
+
+#: plugins/sudoers/def_data.c:436
+msgid "Create a new PAM session for the command to run in"
+msgstr "建立一個新的 PAM 工作階段來執行該指令"
+
+#: plugins/sudoers/def_data.c:440
+msgid "Perform PAM account validation management"
+msgstr "執行 PAM 帳戶驗證管理工具"
+
+#: plugins/sudoers/def_data.c:444
+#, c-format
+msgid "Maximum I/O log sequence number: %s"
+msgstr "最大 I/O 記錄序號:%s"
+
+#: plugins/sudoers/def_data.c:448
+msgid "Enable sudoers netgroup support"
+msgstr "啟用 sudoers netgroup 支援"
+
+#: plugins/sudoers/def_data.c:452
+msgid "Check parent directories for writability when editing files with sudoedit"
+msgstr "在使用 sudoedit 編輯檔案時檢查上層目錄是否可寫"
+
+#: plugins/sudoers/def_data.c:456
+msgid "Follow symbolic links when editing files with sudoedit"
+msgstr "使用 sudoedit 編輯檔案時跟隨符號連結(定位到原檔案)"
+
+#: plugins/sudoers/def_data.c:460
+msgid "Query the group plugin for unknown system groups"
+msgstr "透過群組外掛程式查詢未知的系統群組"
+
+#: plugins/sudoers/def_data.c:464
+msgid "Match netgroups based on the entire tuple: user, host and domain"
+msgstr "基於整個元組(使用者、主機和網域)來符合網路群組"
+
+#: plugins/sudoers/def_data.c:468
+msgid "Allow commands to be run even if sudo cannot write to the audit log"
+msgstr "即使 sudo 無法寫入稽核記錄也允許執行指令"
+
+#: plugins/sudoers/def_data.c:472
+msgid "Allow commands to be run even if sudo cannot write to the I/O log"
+msgstr "即使 sudo 無法寫入 I/O 記錄也允許執行指令"
+
+#: plugins/sudoers/def_data.c:476
+msgid "Allow commands to be run even if sudo cannot write to the log file"
+msgstr "即使 sudo 無法寫入記錄檔案也允許執行指令"
+
+#: plugins/sudoers/def_data.c:480
+msgid "Resolve groups in sudoers and match on the group ID, not the name"
+msgstr "解析 sudoers 中的群組並基於群組 ID(不是名稱)比較"
+
+#: plugins/sudoers/def_data.c:484
+#, c-format
+msgid "Log entries larger than this value will be split into multiple syslog messages: %u"
+msgstr "大於此數值的記錄條目會分為多條 syslog 訊息:%u"
+
+#: plugins/sudoers/def_data.c:488
+#, c-format
+msgid "User that will own the I/O log files: %s"
+msgstr "將擁有 I/O 記錄檔案的使用者:%s"
+
+#: plugins/sudoers/def_data.c:492
+#, c-format
+msgid "Group that will own the I/O log files: %s"
+msgstr "將擁有 I/O 記錄檔案的群組:%s"
+
+#: plugins/sudoers/def_data.c:496
+#, c-format
+msgid "File mode to use for the I/O log files: 0%o"
+msgstr "I/O 記錄檔案要使用的檔案模式:0%o"
+
+#: plugins/sudoers/def_data.c:500
+#, c-format
+msgid "Execute commands by file descriptor instead of by path: %s"
+msgstr "根據檔案描述符執行指令,而非根據路徑:%s"
+
+#: plugins/sudoers/def_data.c:504
+msgid "Ignore unknown Defaults entries in sudoers instead of producing a warning"
+msgstr "忽略 sudoers 中未知的預設 (Defaults) 條目而非產生警告"
+
+#: plugins/sudoers/def_data.c:508
+#, c-format
+msgid "Time in seconds after which the command will be terminated: %u"
+msgstr "超過指定時間後終止指令 (秒):%u"
+
+#: plugins/sudoers/def_data.c:512
+msgid "Allow the user to specify a timeout on the command line"
+msgstr "允許使用者在指令行中指定逾時時間"
+
+#: plugins/sudoers/def_data.c:516
+msgid "Flush I/O log data to disk immediately instead of buffering it"
+msgstr "立即重新整理 I/O 記錄資料而非快取資料"
+
+#: plugins/sudoers/def_data.c:520
+msgid "Include the process ID when logging via syslog"
+msgstr "透過 syslog 登入時包含行程 ID"
+
+#: plugins/sudoers/def_data.c:524
+#, c-format
+msgid "Type of authentication timestamp record: %s"
+msgstr "認證時間戳記錄的類型:%s"
+
+#: plugins/sudoers/def_data.c:528
+#, c-format
+msgid "Authentication failure message: %s"
+msgstr "認證失敗訊息:%s"
+
+#: plugins/sudoers/def_data.c:532
+msgid "Ignore case when matching user names"
+msgstr "在比較使用者名稱時忽略大小寫"
+
+#: plugins/sudoers/def_data.c:536
+msgid "Ignore case when matching group names"
+msgstr "在比較群組名稱時忽略大小寫"
+
+#: plugins/sudoers/def_data.c:540
+msgid "Log when a command is allowed by sudoers"
+msgstr "當指令被 sudoers 允許通行時記錄"
+
+#: plugins/sudoers/def_data.c:544
+msgid "Log when a command is denied by sudoers"
+msgstr "當指令被 sudoers 拒絕通行時記錄"
+
+#: plugins/sudoers/def_data.c:548
+msgid "Sudo log server(s) to connect to with optional port"
+msgstr "要連線的 Sudo 記錄伺服器 (可加連線埠)"
+
+#: plugins/sudoers/def_data.c:552
+#, c-format
+msgid "Sudo log server timeout in seconds: %u"
+msgstr "Sudo 記錄伺服器逾時 (秒):%u"
+
+#: plugins/sudoers/def_data.c:556
+msgid "Enable SO_KEEPALIVE socket option on the socket connected to the logserver"
+msgstr "請在已連線至記錄伺服器的 socket 通訊端啟用 SO_KEEPALIVE socket 選項"
+
+#: plugins/sudoers/def_data.c:560
+#, c-format
+msgid "Path to the audit server's CA bundle file: %s"
+msgstr "稽核伺服器的 CA 組合 (bundle) 檔案路徑:%s"
+
+#: plugins/sudoers/def_data.c:564
+#, c-format
+msgid "Path to the sudoers certificate file: %s"
+msgstr "sudoers 憑證檔案的路徑:%s"
+
+#: plugins/sudoers/def_data.c:568
+#, c-format
+msgid "Path to the sudoers private key file: %s"
+msgstr "sudoers 私鑰檔案的路徑:%s"
+
+#: plugins/sudoers/def_data.c:572
+msgid "Verify that the log server's certificate is valid"
+msgstr "核驗記錄伺服器的憑證是否有效"
+
+#: plugins/sudoers/def_data.c:576
+msgid "Allow the use of unknown runas user and/or group ID"
+msgstr "允許使用未知 runas 使用者及 (或) 群組 ID"
+
+#: plugins/sudoers/def_data.c:580
+msgid "Only permit running commands as a user with a valid shell"
+msgstr "只允許以使用有效 Shell 的使用者執行命令"
+
+#: plugins/sudoers/def_data.c:584
+msgid "Set the pam remote user to the user running sudo"
+msgstr "設定 pam 遠端使用者為執行 sudo 的使用者"
+
+#: plugins/sudoers/def_data.c:588
+msgid "Set the pam remote host to the local host name"
+msgstr "設定 pam 遠端主機至本機主機名稱"
+
+#: plugins/sudoers/def_data.c:592
+#, c-format
+msgid "Working directory to change to before executing the command: %s"
+msgstr "執行命令前,要切換到的工作目錄:%s"
+
+#: plugins/sudoers/def_data.c:596
+#, c-format
+msgid "Root directory to change to before executing the command: %s"
+msgstr "執行命令前,要切換到的根目錄:%s"
+
+#: plugins/sudoers/def_data.c:600
+#, c-format
+msgid "The format of logs to produce: %s"
+msgstr "要產出的記錄格式:%s"
+
+#: plugins/sudoers/def_data.c:604
+msgid "Enable SELinux RBAC support"
+msgstr "啟用 SELinux RBAC 支援"
+
+#: plugins/sudoers/def_data.c:608
+#, c-format
+msgid "Path to the file that is created the first time sudo is run: %s"
+msgstr "sudo 第一次執行時建立的檔案路徑:%s"
+
+#: plugins/sudoers/def_data.c:612
+msgid "Intercept further commands and apply sudoers restrictions to them"
+msgstr "攔截之後的命令,並對這些命令套用 sudoers 限制"
+
+#: plugins/sudoers/def_data.c:616
+msgid "Log sub-commands run by the original command"
+msgstr "記錄原始命令執行的子命令"
+
+#: plugins/sudoers/def_data.c:620
+msgid "Log the exit status of commands"
+msgstr "記錄命令的離開狀態碼"
+
+#: plugins/sudoers/def_data.c:624
+msgid "Subsequent commands in an intercepted session must be authenticated"
+msgstr "被攔截工作階段中的後續命令需要進行身份驗證"
+
+#: plugins/sudoers/def_data.c:628
+msgid "Allow an intercepted command to run set setuid or setgid programs"
+msgstr "允許被攔截的命令執行設定 setuid 或 setgid 的程式"
+
+#: plugins/sudoers/def_data.c:632
+#, c-format
+msgid "The maximum size to which the process's address space may grow (in bytes): %s"
+msgstr "這個處理程序的地址空間可能增長到的最大大小(位元組):%s"
+
+#: plugins/sudoers/def_data.c:636
+#, c-format
+msgid "The largest size core dump file that may be created (in bytes): %s"
+msgstr "可能建立出的最大核心傾印檔案大小(位元組):%s"
+
+#: plugins/sudoers/def_data.c:640
+#, c-format
+msgid "The maximum amount of CPU time that the process may use (in seconds): %s"
+msgstr "處理程序最長可能耗用的 CPU 時間(秒):%s"
+
+#: plugins/sudoers/def_data.c:644
+#, c-format
+msgid "The maximum size of the data segment for the process (in bytes): %s"
+msgstr "處理程序資料區段的最大大小(位元組):%s"
+
+#: plugins/sudoers/def_data.c:648
+#, c-format
+msgid "The largest size file that the process may create (in bytes): %s"
+msgstr "處理程式最大可能建立出的檔案大小(位元組):%s"
+
+#: plugins/sudoers/def_data.c:652
+#, c-format
+msgid "The maximum number of locks that the process may establish: %s"
+msgstr "處理程序最多可能建立的鎖 (lock) 數量:%s"
+
+#: plugins/sudoers/def_data.c:656
+#, c-format
+msgid "The maximum size that the process may lock in memory (in bytes): %s"
+msgstr "處理程序最大可能在記憶體中鎖定的大小(位元組):%s"
+
+#: plugins/sudoers/def_data.c:660
+#, c-format
+msgid "The maximum number of files that the process may have open: %s"
+msgstr "處理程序最多可能開啟的檔案數量:%s"
+
+#: plugins/sudoers/def_data.c:664
+#, c-format
+msgid "The maximum number of processes that the user may run simultaneously: %s"
+msgstr "使用者可能同時執行的最大處理程序數量:%s"
+
+#: plugins/sudoers/def_data.c:668
+#, c-format
+msgid "The maximum size to which the process's resident set size may grow (in bytes): %s"
+msgstr "這個處理程序的 resident set 可能增長到的最大大小(位元組):%s"
+
+#: plugins/sudoers/def_data.c:672
+#, c-format
+msgid "The maximum size to which the process's stack may grow (in bytes): %s"
+msgstr "這個處理程序的堆疊可能增長到的最大大小(位元組):%s"
+
+#: plugins/sudoers/def_data.c:676
+msgid "Attempt authentication even when in non-interactive mode"
+msgstr "非互動模式下仍嘗試進行身份認證"
+
+#: plugins/sudoers/def_data.c:680
+msgid "Store plaintext passwords in I/O log input"
+msgstr "在 I/O 日誌輸入儲存純文字密碼"
+
+#: plugins/sudoers/def_data.c:684
+msgid "List of regular expressions to use when matching a password prompt"
+msgstr "比對密碼提示時,要使用的正規表達式清單"
+
+#: plugins/sudoers/def_data.c:688
+#, c-format
+msgid "The mechanism used by the intercept and log_subcmds options: %s"
+msgstr "intercept 和 log_subcmds 選項使用的機制:%s"
+
+#: plugins/sudoers/def_data.c:692
+msgid "Attempt to verify the command and arguments after execution"
+msgstr "嘗試在執行後驗證命令和引數"
+
+#: plugins/sudoers/def_data.c:696
+#, c-format
+msgid "AppArmor profile to use in the new security context: %s"
+msgstr "要在新的安全上下文中使用的 AppArmor 設定檔:%s"
+
+#: plugins/sudoers/defaults.c:207
+#, c-format
+msgid "unknown defaults entry \"%s\""
+msgstr "預設項目「%s」未知"
+
+#: plugins/sudoers/defaults.c:251
+#, c-format
+msgid "no value specified for \"%s\""
+msgstr "未指定「%s」的值"
+
+#: plugins/sudoers/defaults.c:260
+#, c-format
+msgid "invalid operator \"%c=\" for \"%s\""
+msgstr "「%2$s」的運算子「%1$c=」無效"
+
+#: plugins/sudoers/defaults.c:292
+#, c-format
+msgid "option \"%s\" does not take a value"
+msgstr "「%s」選項不取數值"
+
+#: plugins/sudoers/defaults.c:319
+#, c-format
+msgid "invalid Defaults type 0x%x for option \"%s\""
+msgstr "「%2$s」選項的 Defaults 類型 0x%1$x 無效"
+
+#: plugins/sudoers/defaults.c:326
+#, c-format
+msgid "value \"%s\" is invalid for option \"%s\""
+msgstr "「%s」數值對「%s」選項無效"
+
+#: plugins/sudoers/defaults.c:1176 plugins/sudoers/policy.c:213
+#: plugins/sudoers/policy.c:222
+#, c-format
+msgid "path name for \"%s\" too long"
+msgstr "「%s」的路徑名稱太長"
+
+#: plugins/sudoers/defaults.c:1182
+#, c-format
+msgid "values for \"%s\" must start with a '/', '~', or '*'"
+msgstr "「%s」的值必須以「/」、「~」或「*」開頭"
+
+#: plugins/sudoers/defaults.c:1189
+#, c-format
+msgid "values for \"%s\" must start with a '/'"
+msgstr "「%s」的值必須以「/」開頭"
+
+#: plugins/sudoers/display.c:160
+#, c-format
+msgid "LDAP Role: %s\n"
+msgstr "LDAP 角色:%s\n"
+
+#: plugins/sudoers/display.c:163
+#, c-format
+msgid "Sudoers entry: %s\n"
+msgstr "Sudoers 條目:%s\n"
+
+#: plugins/sudoers/display.c:166
+msgid " RunAsUsers: "
+msgstr " RunAs 使用者:"
+
+#: plugins/sudoers/display.c:181
+msgid " RunAsGroups: "
+msgstr " RunAs 群組:"
+
+#: plugins/sudoers/display.c:191
+msgid " Options: "
+msgstr " 選項:"
+
+#: plugins/sudoers/display.c:255
+msgid " Commands:\n"
+msgstr " 指令:\n"
+
+#: plugins/sudoers/display.c:478
+#, c-format
+msgid "Matching Defaults entries for %s on %s:\n"
+msgstr "比較 %s (%s 上) 的預設條目:\n"
+
+#: plugins/sudoers/display.c:496
+#, c-format
+msgid "Runas and Command-specific defaults for %s:\n"
+msgstr "%s RunAs 和指令指定的預設值:\n"
+
+#: plugins/sudoers/display.c:514
+#, c-format
+msgid "User %s may run the following commands on %s:\n"
+msgstr "使用者 %s 可以在 %s 上執行以下指令:\n"
+
+#: plugins/sudoers/display.c:530
+#, c-format
+msgid "User %s is not allowed to run sudo on %s.\n"
+msgstr "使用者 %s 沒有權限在 %s 上執行 sudo。\n"
+
+#: plugins/sudoers/editor.c:180
+#, c-format
+msgid "ignoring editor: %.*s"
+msgstr "忽略編輯器:%.*s"
+
+#: plugins/sudoers/editor.c:181
+msgid "editor arguments may not contain \"--\""
+msgstr "編輯器引數不能包含「--」"
+
+#: plugins/sudoers/env.c:426
+msgid "sudo_putenv: corrupted envp, length mismatch"
+msgstr "sudo_putenv:envp 損壞,長度不符"
+
+#: plugins/sudoers/env.c:1119
+msgid "unable to rebuild the environment"
+msgstr "無法重建環境"
+
+#: plugins/sudoers/env.c:1199
+#, c-format
+msgid "sorry, you are not allowed to set the following environment variables: %s"
+msgstr "對不起,您沒有權限設定以下環境變數:%s"
+
+#: plugins/sudoers/filedigest.c:50
+#, c-format
+msgid "unsupported digest type %u for %s"
+msgstr "不支援 %2$s 的摘要類型 %1$u"
+
+#: plugins/sudoers/filedigest.c:77
+#, c-format
+msgid "%s: read error"
+msgstr "%s:讀取錯誤"
+
+#: plugins/sudoers/group_plugin.c:169 plugins/sudoers/sssd.c:578
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "無法載入 %s:%s"
+
+#: plugins/sudoers/group_plugin.c:181
+#, c-format
+msgid "unable to find symbol \"group_plugin\" in %s"
+msgstr "無法在 %s 中找到符號「group_plugin」"
+
+#: plugins/sudoers/group_plugin.c:186
+#, c-format
+msgid "%s: incompatible group plugin major version %d, expected %d"
+msgstr "%s:不相容的群組外掛程式主要版本號碼 %d,版本應該為 %d"
+
+#: plugins/sudoers/interfaces.c:76 plugins/sudoers/interfaces.c:93
+#, c-format
+msgid "unable to parse IP address \"%s\""
+msgstr "無法解析 IP 位址列表「%s」"
+
+#: plugins/sudoers/interfaces.c:81 plugins/sudoers/interfaces.c:98
+#, c-format
+msgid "unable to parse netmask \"%s\""
+msgstr "無法解析網路遮罩「%s」"
+
+#: plugins/sudoers/interfaces.c:126
+msgid "Local IP address and netmask pairs:\n"
+msgstr "本機 IP 位址和網路遮罩配對:\n"
+
+#: plugins/sudoers/iolog.c:694
+msgid "unable to update sequence file"
+msgstr "無法更新序列檔"
+
+#: plugins/sudoers/iolog.c:728 plugins/sudoers/iolog.c:917
+#: plugins/sudoers/iolog.c:1080 plugins/sudoers/iolog.c:1087
+#: plugins/sudoers/iolog.c:1209 plugins/sudoers/iolog.c:1216
+#: plugins/sudoers/iolog.c:1316 plugins/sudoers/iolog.c:1323
+#, c-format
+msgid "unable to write to I/O log file: %s"
+msgstr "無法寫入 I/O 記錄檔案:%s"
+
+#: plugins/sudoers/iolog.c:736
+#, c-format
+msgid "unable to create %s/%s"
+msgstr "無法建立 %s/%s"
+
+#: plugins/sudoers/iolog.c:965
+#, c-format
+msgid "%s: internal error, I/O log file for event %d not open"
+msgstr "%s:內部錯誤,未開啟事件 %d 的 I/O 記錄檔案"
+
+#: plugins/sudoers/iolog.c:1065 plugins/sudoers/iolog.c:1194
+#: plugins/sudoers/iolog.c:1300 plugins/sudoers/timestamp.c:897
+#: plugins/sudoers/timestamp.c:989 plugins/sudoers/visudo.c:555
+#: plugins/sudoers/visudo.c:561
+msgid "unable to read the clock"
+msgstr "無法讀取時鐘"
+
+#: plugins/sudoers/iolog.c:1292 plugins/sudoers/log_client.c:1203
+#: plugins/sudoers/log_client.c:1213 plugins/sudoers/log_client.c:1217
+#, c-format
+msgid "%s: internal error, invalid signal %d"
+msgstr "%s:內部錯誤,訊號 %d 無效"
+
+#: plugins/sudoers/ldap.c:154 plugins/sudoers/ldap_conf.c:289
+msgid "starttls not supported when using ldaps"
+msgstr "使用 ldaps 時不支援使用 starttls"
+
+#: plugins/sudoers/ldap.c:226
+#, c-format
+msgid "unable to initialize SSL cert and key db: %s"
+msgstr "無法初始化 SSL 憑證和金鑰資料庫:%s"
+
+#: plugins/sudoers/ldap.c:229
+#, c-format
+msgid "you must set TLS_CERT in %s to use SSL"
+msgstr "要使用 SSL,您必須在 %s 設定 TLS_CERT"
+
+#: plugins/sudoers/ldap.c:1593
+#, c-format
+msgid "unable to initialize LDAP: %s"
+msgstr "無法初始化 LDAP:%s"
+
+#: plugins/sudoers/ldap.c:1630
+msgid "start_tls specified but LDAP libs do not support ldap_start_tls_s() or ldap_start_tls_s_np()"
+msgstr "指定了 start_tls,但 LDAP 函式庫不支援 ldap_start_tls_s() 或 ldap_start_tls_s_np()"
+
+#: plugins/sudoers/ldap.c:1767 plugins/sudoers/parse_ldif.c:745
+#, c-format
+msgid "invalid sudoOrder attribute: %s"
+msgstr "無效的 sudoOrder 屬性:%s"
+
+#: plugins/sudoers/ldap_conf.c:197
+#, c-format
+msgid "%s: port too large"
+msgstr "%s:連線埠過大"
+
+#: plugins/sudoers/ldap_conf.c:258
+#, c-format
+msgid "unsupported LDAP uri type: %s"
+msgstr "不支援的 LDAP URI 類型:%s"
+
+#: plugins/sudoers/ldap_conf.c:285
+msgid "unable to mix ldap and ldaps URIs"
+msgstr "無法混合 ldap 和 ldaps URI"
+
+#: plugins/sudoers/ldap_util.c:499 plugins/sudoers/ldap_util.c:506
+#: plugins/sudoers/ldap_util.c:514 plugins/sudoers/ldap_util.c:523
+#: plugins/sudoers/ldap_util.c:531 plugins/sudoers/ldap_util.c:541
+#: plugins/sudoers/ldap_util.c:549
+#, c-format
+msgid "duplicate sudoOption: %s%s%s"
+msgstr "sudoOption 有重複:%s%s%s"
+
+#: plugins/sudoers/ldap_util.c:568 plugins/sudoers/ldap_util.c:570
+#, c-format
+msgid "unable to convert sudoOption: %s%s%s"
+msgstr "無法轉換 sudoOption: %s%s%s"
+
+#: plugins/sudoers/linux_audit.c:58 plugins/sudoers/linux_audit.c:60
+msgid "unable to open audit system"
+msgstr "無法開啟稽核系統"
+
+#: plugins/sudoers/linux_audit.c:104
+msgid "unable to send audit message"
+msgstr "無法傳送稽核訊息"
+
+#: plugins/sudoers/log_client.c:125 plugins/sudoers/log_client.c:412
+#: plugins/sudoers/log_client.c:1450 plugins/sudoers/log_client.c:2076
+msgid "error in event loop"
+msgstr "事件循環中發生錯誤"
+
+#: plugins/sudoers/log_client.c:205
+#, c-format
+msgid "Creation of new SSL_CTX object failed: %s"
+msgstr "建立新 SSL_CTX 物件失敗:%s"
+
+#: plugins/sudoers/log_client.c:230
+#, c-format
+msgid "unable to load certificate authority bundle %s"
+msgstr "無法載入 %s 憑證授權單位組合"
+
+#: plugins/sudoers/log_client.c:252
+#, c-format
+msgid "unable to load certificate %s"
+msgstr "無法載入 %s 憑證"
+
+#: plugins/sudoers/log_client.c:266
+#, c-format
+msgid "unable to load private key %s"
+msgstr "無法載入 %s 私鑰"
+
+#: plugins/sudoers/log_client.c:275
+#, c-format
+msgid "Unable to allocate ssl object: %s"
+msgstr "無法配置 SSL 物件:%s"
+
+#: plugins/sudoers/log_client.c:364 plugins/sudoers/log_client.c:369
+#, c-format
+msgid "TLS connection to %s:%s failed: %s"
+msgstr "TLS 連線至 %s:%s 失敗:%s"
+
+#: plugins/sudoers/log_client.c:545
+msgid "TLS initialization was unsuccessful"
+msgstr "TLS 初始化失敗"
+
+#: plugins/sudoers/log_client.c:555
+msgid "TLS handshake was unsuccessful"
+msgstr "TLS 交握失敗"
+
+#: plugins/sudoers/log_client.c:1221
+#, c-format
+msgid "%s: internal error, invalid exit status %d"
+msgstr "%s:內部錯誤,退出狀態碼 %d 無效"
+
+#: plugins/sudoers/log_client.c:1757 plugins/sudoers/log_client.c:1782
+msgid "lost connection to log server"
+msgstr "失去對記錄伺服器的連線"
+
+#: plugins/sudoers/log_client.c:1859
+msgid "missing write buffer"
+msgstr "缺少寫入緩衝區"
+
+#: plugins/sudoers/log_client.c:2015
+msgid "unable to connect to log server"
+msgstr "無法連線到記錄伺服器"
+
+#: plugins/sudoers/logging.c:295
+msgid "user NOT in sudoers"
+msgstr "使用者不在 sudoers 中"
+
+#: plugins/sudoers/logging.c:297
+msgid "user NOT authorized on host"
+msgstr "使用者未取得此主機上的授權"
+
+#: plugins/sudoers/logging.c:299
+msgid "command not allowed"
+msgstr "不允許使用指令"
+
+#: plugins/sudoers/logging.c:320
+#, c-format
+msgid "%s is not in the sudoers file.\n"
+msgstr "%s 不在 sudoers 檔案中。\n"
+
+#: plugins/sudoers/logging.c:323
+#, c-format
+msgid "%s is not allowed to run sudo on %s.\n"
+msgstr "%s 不允許在 %s 執行 sudo。\n"
+
+#: plugins/sudoers/logging.c:326
+#, c-format
+msgid "Sorry, user %s may not run sudo on %s.\n"
+msgstr "對不起,使用者 %s 不能在 %s 上執行 sudo。\n"
+
+#: plugins/sudoers/logging.c:339
+#, c-format
+msgid "Sorry, user %s is not allowed to execute '%s%s%s%s' as %s%s%s on %s.\n"
+msgstr "對不起,使用者 %1$s 不允許在 %9$s 以 %6$s%7$s%8$s 的身份執行「%2$s%3$s%4$s%5$s」。\n"
+
+#: plugins/sudoers/logging.c:350
+msgid "This incident has been reported to the administrator.\n"
+msgstr "本事件已向管理員報告。\n"
+
+#: plugins/sudoers/logging.c:387 plugins/sudoers/sudoers.c:547
+#: plugins/sudoers/sudoers.c:549 plugins/sudoers/sudoers.c:551
+#: plugins/sudoers/sudoers.c:553 plugins/sudoers/sudoers.c:777
+#: plugins/sudoers/sudoers.c:779
+#, c-format
+msgid "%s: command not found"
+msgstr "%s:找不到指令"
+
+#: plugins/sudoers/logging.c:389 plugins/sudoers/sudoers.c:543
+#, c-format
+msgid ""
+"ignoring \"%s\" found in '.'\n"
+"Use \"sudo ./%s\" if this is the \"%s\" you wish to run."
+msgstr ""
+"忽略在「.」中找到的「%s」\n"
+"請使用「sudo ./%s」,若這是您想執行的「%s」。"
+
+#: plugins/sudoers/logging.c:409
+#, c-format
+msgid "%u incorrect password attempt"
+msgid_plural "%u incorrect password attempts"
+msgstr[0] "%u 次密碼錯誤嘗試"
+
+#: plugins/sudoers/logging.c:500
+msgid "authentication failure"
+msgstr "認證失敗"
+
+#: plugins/sudoers/logging.c:539 plugins/sudoers/logging.c:558
+msgid "a password is required"
+msgstr "需要密碼"
+
+#: plugins/sudoers/logging.c:881
+msgid "problem parsing sudoers"
+msgstr "解析 sudoers 時發生問題"
+
+#: plugins/sudoers/logging.c:922 plugins/sudoers/logging.c:930
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr "%s:%d:%d: %s"
+
+#: plugins/sudoers/logging.c:1108
+#, c-format
+msgid "unable to write log file %s"
+msgstr "無法寫入記錄檔 %s"
+
+#: plugins/sudoers/match_digest.c:107
+#, c-format
+msgid "digest for %s (%s) bad length %zu, expected %zu"
+msgstr "%s (%s) 的摘要長度 %zu 是錯誤的(預期是 %zu)"
+
+#: plugins/sudoers/match_digest.c:126
+#, c-format
+msgid "digest for %s (%s) is not in %s form"
+msgstr "%s(%s) 的摘要的形式不是 %s"
+
+#: plugins/sudoers/parse_ldif.c:615
+#, c-format
+msgid "ignoring incomplete sudoRole: cn: %s"
+msgstr "將忽略不完整的 sudoRole:cn:%s"
+
+#: plugins/sudoers/parse_ldif.c:675
+#, c-format
+msgid "invalid LDIF attribute: %s"
+msgstr "LDIF 屬性無效:%s"
+
+#: plugins/sudoers/parser_warnx.c:56
+#, c-format
+msgid "%s:%d:%d: %s\n"
+msgstr "%s:%d:%d: %s\n"
+
+#: plugins/sudoers/parser_warnx.c:59
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s:%s\n"
+
+#: plugins/sudoers/pivot.c:71
+msgid "unable to restore root directory"
+msgstr "無法復原根目錄"
+
+#: plugins/sudoers/pivot.c:79
+msgid "unable to restore current working directory"
+msgstr "無法復原目前工作目錄"
+
+#: plugins/sudoers/policy.c:78 plugins/sudoers/policy.c:111
+#, c-format
+msgid "invalid %.*s set by sudo front-end"
+msgstr "sudo 前端設定的 %.*s 無效"
+
+#: plugins/sudoers/policy.c:364 plugins/sudoers/testsudoers.c:329
+msgid "unable to parse network address list"
+msgstr "無法解析網路位址列表"
+
+#: plugins/sudoers/policy.c:556
+msgid "user name not set by sudo front-end"
+msgstr "sudo 前端未設定使用者名稱"
+
+#: plugins/sudoers/policy.c:560
+msgid "user-ID not set by sudo front-end"
+msgstr "sudo 前端未設定使用者 ID (user-ID)"
+
+#: plugins/sudoers/policy.c:564
+msgid "group-ID not set by sudo front-end"
+msgstr "sudo 前端未設定群組 ID (group-ID)"
+
+#: plugins/sudoers/policy.c:568
+msgid "host name not set by sudo front-end"
+msgstr "sudo 前端未設定主機名稱"
+
+#: plugins/sudoers/policy.c:757
+#, c-format
+msgid "invalid working directory: %s"
+msgstr "無效的工作目錄:%s"
+
+#: plugins/sudoers/policy.c:944
+#, c-format
+msgid "invalid chroot directory: %s"
+msgstr "無效的 chroot 目錄:%s"
+
+#: plugins/sudoers/policy.c:1153 plugins/sudoers/visudo.c:919
+#: plugins/sudoers/visudo.c:1218
+#, c-format
+msgid "unable to execute %s"
+msgstr "無法執行 %s"
+
+#: plugins/sudoers/policy.c:1225 plugins/sudoers/policy.c:1260
+#: plugins/sudoers/policy.c:1282 plugins/sudoers/policy.c:1300
+#, c-format
+msgid "%s: invalid mode flags from sudo front end: 0x%x"
+msgstr "%s:來自 sudo 前端的無效 mode 旗標:0x%x"
+
+#: plugins/sudoers/policy.c:1323
+#, c-format
+msgid "Sudoers policy plugin version %s\n"
+msgstr "Sudoers 策略外掛程式版本 %s\n"
+
+#: plugins/sudoers/policy.c:1325
+#, c-format
+msgid "Sudoers file grammar version %d\n"
+msgstr "Sudoers 檔案文法版本 %d\n"
+
+#: plugins/sudoers/policy.c:1329
+#, c-format
+msgid ""
+"\n"
+"Sudoers path: %s\n"
+msgstr ""
+"\n"
+"Sudoers 路徑:%s\n"
+
+#: plugins/sudoers/policy.c:1332
+#, c-format
+msgid "nsswitch path: %s\n"
+msgstr "nsswitch 路徑:%s\n"
+
+#: plugins/sudoers/policy.c:1335
+#, c-format
+msgid "ldap.conf path: %s\n"
+msgstr "ldap.conf 路徑:%s\n"
+
+#: plugins/sudoers/policy.c:1337
+#, c-format
+msgid "ldap.secret path: %s\n"
+msgstr "ldap.secret 路徑:%s\n"
+
+#: plugins/sudoers/policy.c:1370
+#, c-format
+msgid "unable to register hook of type %d (version %d.%d)"
+msgstr "無法註冊類型為 %d 的觸發器 (版本 %d.%d)"
+
+#: plugins/sudoers/policy.c:1388
+#, c-format
+msgid "unable to deregister hook of type %d (version %d.%d)"
+msgstr "無法取消註冊類型為 %d 的觸發器 (版本 %d.%d)"
+
+#: plugins/sudoers/pwutil.c:242 plugins/sudoers/pwutil.c:260
+#, c-format
+msgid "unable to cache uid %u"
+msgstr "無法快取使用者 ID %u"
+
+#: plugins/sudoers/pwutil.c:254
+#, c-format
+msgid "unable to cache uid %u, already exists"
+msgstr "無法快取使用者 ID %u,原因:使用者 ID 已存在"
+
+#: plugins/sudoers/pwutil.c:314 plugins/sudoers/pwutil.c:332
+#: plugins/sudoers/pwutil.c:395 plugins/sudoers/pwutil.c:440
+#, c-format
+msgid "unable to cache user %s"
+msgstr "無法快取 %s 使用者"
+
+#: plugins/sudoers/pwutil.c:327
+#, c-format
+msgid "unable to cache user %s, already exists"
+msgstr "無法快取使用者 %s,原因:已存在"
+
+#: plugins/sudoers/pwutil.c:559 plugins/sudoers/pwutil.c:577
+#, c-format
+msgid "unable to cache gid %u"
+msgstr "無法快取群組 ID %u"
+
+#: plugins/sudoers/pwutil.c:571
+#, c-format
+msgid "unable to cache gid %u, already exists"
+msgstr "無法快取群組 ID %u,原因:已經存在"
+
+#: plugins/sudoers/pwutil.c:625 plugins/sudoers/pwutil.c:643
+#: plugins/sudoers/pwutil.c:704 plugins/sudoers/pwutil.c:753
+#, c-format
+msgid "unable to cache group %s"
+msgstr "無法快取 %s 群組"
+
+#: plugins/sudoers/pwutil.c:638
+#, c-format
+msgid "unable to cache group %s, already exists"
+msgstr "無法快取群組 %s,原因:已經存在"
+
+#: plugins/sudoers/pwutil.c:900 plugins/sudoers/pwutil.c:985
+#: plugins/sudoers/pwutil.c:1039 plugins/sudoers/pwutil.c:1095
+#, c-format
+msgid "unable to cache group list for %s, already exists"
+msgstr "無法快取群組列表 %s,原因:已經存在"
+
+#: plugins/sudoers/pwutil.c:906 plugins/sudoers/pwutil.c:990
+#: plugins/sudoers/pwutil.c:1045 plugins/sudoers/pwutil.c:1100
+#, c-format
+msgid "unable to cache group list for %s"
+msgstr "無法快取 %s 的群組列表"
+
+#: plugins/sudoers/pwutil.c:979
+#, c-format
+msgid "unable to parse groups for %s"
+msgstr "無法解析 %s 的群組"
+
+#: plugins/sudoers/pwutil.c:1089
+#, c-format
+msgid "unable to parse gids for %s"
+msgstr "無法解析 %s 的群組 ID"
+
+#: plugins/sudoers/set_perms.c:120 plugins/sudoers/set_perms.c:457
+#: plugins/sudoers/set_perms.c:870 plugins/sudoers/set_perms.c:1186
+#: plugins/sudoers/set_perms.c:1490
+msgid "perm stack overflow"
+msgstr "權限堆疊溢位"
+
+#: plugins/sudoers/set_perms.c:131 plugins/sudoers/set_perms.c:387
+#: plugins/sudoers/set_perms.c:468 plugins/sudoers/set_perms.c:736
+#: plugins/sudoers/set_perms.c:881 plugins/sudoers/set_perms.c:1109
+#: plugins/sudoers/set_perms.c:1197 plugins/sudoers/set_perms.c:1422
+#: plugins/sudoers/set_perms.c:1501 plugins/sudoers/set_perms.c:1592
+msgid "perm stack underflow"
+msgstr "權限堆疊反向溢位"
+
+#: plugins/sudoers/set_perms.c:191 plugins/sudoers/set_perms.c:515
+#: plugins/sudoers/set_perms.c:1251 plugins/sudoers/set_perms.c:1535
+msgid "unable to change to root gid"
+msgstr "無法切換為 root 群組 ID"
+
+#: plugins/sudoers/set_perms.c:282 plugins/sudoers/set_perms.c:612
+#: plugins/sudoers/set_perms.c:1013 plugins/sudoers/set_perms.c:1328
+msgid "unable to change to runas gid"
+msgstr "無法切換為 runas 群組 ID"
+
+#: plugins/sudoers/set_perms.c:287 plugins/sudoers/set_perms.c:617
+#: plugins/sudoers/set_perms.c:1018 plugins/sudoers/set_perms.c:1333
+msgid "unable to set runas group vector"
+msgstr "無法設定 runas 群組集合"
+
+#: plugins/sudoers/set_perms.c:298 plugins/sudoers/set_perms.c:628
+#: plugins/sudoers/set_perms.c:1027 plugins/sudoers/set_perms.c:1342
+msgid "unable to change to runas uid"
+msgstr "無法切換成 runas 使用者 ID"
+
+#: plugins/sudoers/set_perms.c:320 plugins/sudoers/set_perms.c:650
+#: plugins/sudoers/set_perms.c:1047 plugins/sudoers/set_perms.c:1362
+msgid "unable to change to sudoers gid"
+msgstr "無法切換為 sudoers 群組 ID"
+
+#: plugins/sudoers/set_perms.c:374 plugins/sudoers/set_perms.c:723
+#: plugins/sudoers/set_perms.c:1096 plugins/sudoers/set_perms.c:1409
+#: plugins/sudoers/set_perms.c:1579
+msgid "too many processes"
+msgstr "行程過多"
+
+#: plugins/sudoers/solaris_audit.c:62
+msgid "unable to get current working directory"
+msgstr "無法取得目前工作目錄"
+
+#: plugins/sudoers/solaris_audit.c:70
+#, c-format
+msgid "truncated audit path ctx->user.cmnd: %s"
+msgstr "截短的稽核路徑 ctx->user_cmnd:%s"
+
+#: plugins/sudoers/solaris_audit.c:77
+#, c-format
+msgid "truncated audit path argv[0]: %s"
+msgstr "截短的稽核路徑 argv[0]:%s"
+
+#: plugins/sudoers/sssd.c:581
+msgid "unable to initialize SSS source. Is SSSD installed on your machine?"
+msgstr "無法初始化 SSS 來源。是否已在您的電腦上安裝 SSSD?"
+
+#: plugins/sudoers/sssd.c:589 plugins/sudoers/sssd.c:598
+#: plugins/sudoers/sssd.c:607 plugins/sudoers/sssd.c:616
+#: plugins/sudoers/sssd.c:625
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "無法在 %2$s 中找到符號「%1$s」"
+
+#: plugins/sudoers/sudoers.c:250
+#, c-format
+msgid "unable to get defaults from %s"
+msgstr "無法從 %s 取得預設值"
+
+#: plugins/sudoers/sudoers.c:259
+msgid "no valid sudoers sources found, quitting"
+msgstr "未找到有效的 sudoers 來源,退出"
+
+#: plugins/sudoers/sudoers.c:366
+msgid "sudoers specifies that root is not allowed to sudo"
+msgstr "sudoers 指定 root 不允許執行 sudo"
+
+#: plugins/sudoers/sudoers.c:375
+msgid "user not allowed to override closefrom limit"
+msgstr "使用者不允許覆蓋 closefrom 限制"
+
+#: plugins/sudoers/sudoers.c:376
+msgid "you are not permitted to use the -C option"
+msgstr "您沒有權限使用 -C 選項"
+
+#: plugins/sudoers/sudoers.c:440
+msgid "no tty"
+msgstr "找不到終端"
+
+#: plugins/sudoers/sudoers.c:441
+msgid "sorry, you must have a tty to run sudo"
+msgstr "抱歉,您必須先要有終端才能執行 sudo"
+
+#: plugins/sudoers/sudoers.c:449
+#, c-format
+msgid "invalid shell for user %s: %s"
+msgstr "%s 使用者的 Shell 無效:%s"
+
+#: plugins/sudoers/sudoers.c:491
+#, c-format
+msgid "user not allowed to change root directory to %s"
+msgstr "不允許使用者切換根目錄至 %s"
+
+#: plugins/sudoers/sudoers.c:493
+#, c-format
+msgid "you are not permitted to use the -R option with %s"
+msgstr "不允許您將 -R 選項與 %s 一起使用"
+
+#: plugins/sudoers/sudoers.c:506
+#, c-format
+msgid "user not allowed to change directory to %s"
+msgstr "不允許使用者切換至 %s 目錄"
+
+#: plugins/sudoers/sudoers.c:507
+#, c-format
+msgid "you are not permitted to use the -D option with %s"
+msgstr "不允許您將 -D 選項與 %s 一起使用"
+
+#: plugins/sudoers/sudoers.c:542
+msgid "command in current directory"
+msgstr "目前目錄中的指令"
+
+#: plugins/sudoers/sudoers.c:557
+msgid "\"cd\" is a shell built-in command, it cannot be run directly."
+msgstr "「cd」是 shell 內建的命令,不能直接執行。"
+
+#: plugins/sudoers/sudoers.c:559
+msgid "the -s option may be used to run a privileged shell."
+msgstr "-s 選項可用來執行具特殊權限的 shell。"
+
+#: plugins/sudoers/sudoers.c:561
+msgid "the -D option may be used to run a command in a specific directory."
+msgstr "-D 選項可用來在特定目錄執行命令。"
+
+#: plugins/sudoers/sudoers.c:570
+msgid "user not allowed to set a command timeout"
+msgstr "使用者不允許設定命令逾時"
+
+#: plugins/sudoers/sudoers.c:572
+msgid "sorry, you are not allowed set a command timeout"
+msgstr "抱歉,您沒有權限設定逾時時間"
+
+#: plugins/sudoers/sudoers.c:580
+msgid "user not allowed to preserve the environment"
+msgstr "使用者不允許保留環境"
+
+#: plugins/sudoers/sudoers.c:582
+msgid "sorry, you are not allowed to preserve the environment"
+msgstr "抱歉,您沒有權限保留環境"
+
+#: plugins/sudoers/sudoers.c:618
+msgid "no command specified"
+msgstr "未指定命令"
+
+#: plugins/sudoers/sudoers.c:759
+msgid "error setting user-specified environment variables"
+msgstr "設定使用者指定的環境變數時發生錯誤"
+
+#: plugins/sudoers/sudoers.c:1211
+msgid "sudoedit doesn't need to be run via sudo"
+msgstr "sudoedit 不用以 sudo 執行"
+
+#: plugins/sudoers/sudoers.c:1296 plugins/sudoers/sudoreplay.c:1613
+#: plugins/sudoers/tsdump.c:138
+#, c-format
+msgid "unable to read %s"
+msgstr "無法讀取 %s"
+
+#: plugins/sudoers/sudoers.c:1321 plugins/sudoers/visudo.c:1123
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s 不是一般檔案"
+
+#: plugins/sudoers/sudoers.c:1325 plugins/sudoers/timestamp.c:272 toke.l:1355
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s 由使用者 ID %u 所有,應為 %u"
+
+#: plugins/sudoers/sudoers.c:1330 plugins/sudoers/timestamp.c:279 toke.l:1360
+#, c-format
+msgid "%s is world writable"
+msgstr "%s 允許任何人寫入"
+
+#: plugins/sudoers/sudoers.c:1334 plugins/sudoers/timestamp.c:284 toke.l:1363
+#, c-format
+msgid "%s is owned by gid %u, should be %u"
+msgstr "%s 屬於群組 ID %u,應為 %u"
+
+#: plugins/sudoers/sudoers.c:1363
+#, c-format
+msgid "only root can use \"-c %s\""
+msgstr "只有 root 才能使用「-c %s」"
+
+#: plugins/sudoers/sudoers.c:1382
+#, c-format
+msgid "unknown login class %s"
+msgstr "未知登入類別 %s"
+
+#: plugins/sudoers/sudoers_cb.c:120 plugins/sudoers/sudoers_cb.c:135
+#, c-format
+msgid "unable to resolve host %s"
+msgstr "無法解析主機:%s"
+
+#: plugins/sudoers/sudoreplay.c:252
+#, c-format
+msgid "invalid filter option: %s"
+msgstr "無效的過濾器選項:%s"
+
+#: plugins/sudoers/sudoreplay.c:268
+#, c-format
+msgid "invalid max wait: %s"
+msgstr "無效的最大等待時間:%s"
+
+#: plugins/sudoers/sudoreplay.c:291
+#, c-format
+msgid "invalid speed factor: %s"
+msgstr "無效的速度因數:%s"
+
+#: plugins/sudoers/sudoreplay.c:326
+#, c-format
+msgid "invalid time offset %s"
+msgstr "時間偏移值 %s 無效"
+
+#: plugins/sudoers/sudoreplay.c:335
+#, c-format
+msgid "%s/%.2s/%.2s/%.2s: %s"
+msgstr "%s/%.2s/%.2s/%.2s: %s"
+
+#: plugins/sudoers/sudoreplay.c:340
+#, c-format
+msgid "%s/timing: %s"
+msgstr "%s/計時:%s"
+
+#: plugins/sudoers/sudoreplay.c:368
+#, c-format
+msgid "Replaying sudo session: %s"
+msgstr "重播 sudo 工作階段:%s"
+
+#: plugins/sudoers/sudoreplay.c:634
+msgid "unable to set tty to raw mode"
+msgstr "無法將終端設為原始 (RAW) 模式"
+
+#: plugins/sudoers/sudoreplay.c:685
+msgid "Warning: your terminal is too small to properly replay the log."
+msgstr "警告:您的終端尺寸太小,不能正常地重播記錄。"
+
+#: plugins/sudoers/sudoreplay.c:686
+#, c-format
+msgid "Log geometry is %d x %d, your terminal's geometry is %d x %d."
+msgstr "記錄的幾何尺寸為 %dx%d,但您終端的幾何尺寸為 %dx%d。"
+
+#: plugins/sudoers/sudoreplay.c:714
+msgid "Replay finished, press any key to restore the terminal."
+msgstr "重播完成,請按任意鍵返回終端。"
+
+#: plugins/sudoers/sudoreplay.c:1217 plugins/sudoers/sudoreplay.c:1247
+#, c-format
+msgid "ambiguous expression \"%s\""
+msgstr "不明確的表達式「%s」"
+
+#: plugins/sudoers/sudoreplay.c:1269
+msgid "unmatched ')' in expression"
+msgstr "表達式中的「)」不對稱"
+
+#: plugins/sudoers/sudoreplay.c:1273
+#, c-format
+msgid "unknown search term \"%s\""
+msgstr "未知的搜尋詞彙「%s」"
+
+#: plugins/sudoers/sudoreplay.c:1288
+#, c-format
+msgid "%s requires an argument"
+msgstr "%s 需要參數"
+
+#: plugins/sudoers/sudoreplay.c:1298
+#, c-format
+msgid "could not parse date \"%s\""
+msgstr "無法解析日期「%s」"
+
+#: plugins/sudoers/sudoreplay.c:1307
+msgid "unmatched '(' in expression"
+msgstr "表達式中的「(」不對稱"
+
+#: plugins/sudoers/sudoreplay.c:1309
+msgid "illegal trailing \"or\""
+msgstr "無效的結尾字元「or」"
+
+#: plugins/sudoers/sudoreplay.c:1311
+msgid "illegal trailing \"!\""
+msgstr "無效的結尾字元「!」"
+
+#: plugins/sudoers/sudoreplay.c:1417
+#, c-format
+msgid "unknown search type %d"
+msgstr "未知的搜尋類型 %d"
+
+#: plugins/sudoers/sudoreplay.c:1679
+#, c-format
+msgid "usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"
+msgstr "用法:%s [-hnRS] [-d 目錄] [-m 數值] [-s 數值] ID\n"
+
+#: plugins/sudoers/sudoreplay.c:1681
+#, c-format
+msgid "usage: %s [-h] [-d dir] -l [search expression]\n"
+msgstr "用法:%s [-h] [-d 目錄] -l [搜尋表達式]\n"
+
+#: plugins/sudoers/sudoreplay.c:1695
+#, c-format
+msgid ""
+"%s - replay sudo session logs\n"
+"\n"
+msgstr ""
+"%s - 重播 sudo 工作階段記錄\n"
+"\n"
+
+#: plugins/sudoers/sudoreplay.c:1697
+msgid ""
+"\n"
+"Options:\n"
+" -d, --directory=dir specify directory for session logs\n"
+" -f, --filter=filter specify which I/O type(s) to display\n"
+" -h, --help display help message and exit\n"
+" -l, --list list available session IDs, with optional expression\n"
+" -m, --max-wait=num max number of seconds to wait between events\n"
+" -n, --non-interactive no prompts, session is sent to the standard output\n"
+" -R, --no-resize do not attempt to re-size the terminal\n"
+" -S, --suspend-wait wait while the command was suspended\n"
+" -s, --speed=num speed up or slow down output\n"
+" -V, --version display version information and exit"
+msgstr ""
+"\n"
+"選項:\n"
+" -d, --directory=目錄 指定工作階段的記錄目錄\n"
+" -f, --filter=過濾器 指定要顯示的 I/O 類型\n"
+" -h, --help 顯示說明訊息並退出\n"
+" -l, --list 列出可用工作階段 ID,可加表達式限定列出階段\n"
+" -m, --max-wait=數值 事件間等待的最大秒數\n"
+" -n, --non-interactive 不提示,將工作階段送至標準輸出\n"
+" -R, --no-resize 不嘗試重新調整終端機大小\n"
+" -S, --suspend-wait 在指令暫停時等待\n"
+" -s, --speed=數值 加速或減速輸出速度\n"
+" -V, --version 顯示版本訊息並退出"
+
+#: plugins/sudoers/testsudoers.c:392
+#, c-format
+msgid ""
+"\n"
+"Invalid shell for user %s: %s\n"
+msgstr ""
+"\n"
+"%s 使用者的 shell 無效:%s\n"
+
+#: plugins/sudoers/testsudoers.c:411
+msgid ""
+"\n"
+"Password required"
+msgstr ""
+"\n"
+"需要密碼"
+
+#: plugins/sudoers/testsudoers.c:422
+msgid ""
+"\n"
+"Parse error"
+msgstr ""
+"\n"
+"解析發生錯誤"
+
+#: plugins/sudoers/testsudoers.c:425
+msgid ""
+"\n"
+"Command allowed"
+msgstr ""
+"\n"
+"指令已允許"
+
+#: plugins/sudoers/testsudoers.c:428
+msgid ""
+"\n"
+"Command denied"
+msgstr ""
+"\n"
+"指令被拒"
+
+#: plugins/sudoers/testsudoers.c:431
+msgid ""
+"\n"
+"Command unmatched"
+msgstr ""
+"\n"
+"指令不相符"
+
+#: plugins/sudoers/timestamp.c:364 plugins/sudoers/timestamp.c:711
+#, c-format
+msgid "unable to truncate time stamp file to %lld bytes"
+msgstr "無法將時間戳檔案截短為 %lld 位元組"
+
+#: plugins/sudoers/timestamp.c:908
+msgid "ignoring time stamp from the future"
+msgstr "將忽略未來時間的時間戳"
+
+#: plugins/sudoers/timestamp.c:931
+#, c-format
+msgid "time stamp too far in the future: %20.20s"
+msgstr "時間戳超前目前時間過多:%20.20s"
+
+#: plugins/sudoers/timestamp.c:1067
+#, c-format
+msgid "unable to lock time stamp file %s"
+msgstr "無法鎖定時間戳檔案 %s"
+
+#: plugins/sudoers/timestamp.c:1114
+#, c-format
+msgid "%s:%d:%d timestampowner: unknown user %s"
+msgstr "%s:%d:%d timestampowner: 未知使用者 %s"
+
+#: plugins/sudoers/toke_util.c:159
+msgid "sudoedit should not be specified with a path"
+msgstr "sudoedit 不應用路徑指定"
+
+#: plugins/sudoers/visudo.c:308 plugins/sudoers/visudo.c:714
+#, c-format
+msgid "press return to edit %s: "
+msgstr "按確認鍵編輯 %s:"
+
+#: plugins/sudoers/visudo.c:323
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "編輯階段的內容留在 %s"
+
+#: plugins/sudoers/visudo.c:401
+#, c-format
+msgid "specified editor (%s) doesn't exist"
+msgstr "指定的編輯器 (%s) 不存在"
+
+#: plugins/sudoers/visudo.c:406
+#, c-format
+msgid "no editor found (editor path = %s)"
+msgstr "未找到編輯器 (編輯器路徑 = %s)"
+
+#: plugins/sudoers/visudo.c:494 plugins/sudoers/visudo.c:786
+#, c-format
+msgid "unable to stat %s"
+msgstr "無法 stat %s"
+
+#: plugins/sudoers/visudo.c:514 plugins/sudoers/visudo.c:522
+msgid "write error"
+msgstr "寫入時發生錯誤"
+
+#: plugins/sudoers/visudo.c:568
+#, c-format
+msgid "unable to stat temporary file (%s), %s unchanged"
+msgstr "無法 stat 暫存檔 (%s),%s 未變更"
+
+#: plugins/sudoers/visudo.c:575
+#, c-format
+msgid "zero length temporary file (%s), %s unchanged"
+msgstr "暫存檔內沒有內容 (%s),%s 未變更"
+
+#: plugins/sudoers/visudo.c:581
+#, c-format
+msgid "editor (%s) failed, %s unchanged"
+msgstr "編輯器 (%s) 執行失敗,%s 未變更"
+
+#: plugins/sudoers/visudo.c:613
+#, c-format
+msgid "%s unchanged"
+msgstr "%s 未變更"
+
+#: plugins/sudoers/visudo.c:661
+#, c-format
+msgid "unable to re-open temporary file (%s), %s unchanged."
+msgstr "無法重新開啟暫存檔 (%s),%s 未變更。"
+
+#: plugins/sudoers/visudo.c:674
+#, c-format
+msgid "unable to parse temporary file (%s), unknown error"
+msgstr "無法解析暫存檔 (%s),未知錯誤"
+
+#: plugins/sudoers/visudo.c:760 plugins/sudoers/visudo.c:790
+#: plugins/sudoers/visudo.c:797
+#, c-format
+msgid "unable to set (uid, gid) of %s to (%u, %u)"
+msgstr "無法將 %s 的 (uid, gid) 設為 (%u, %u)"
+
+#: plugins/sudoers/visudo.c:825
+#, c-format
+msgid "%s and %s not on the same file system, using mv to rename"
+msgstr "%s 和 %s 不在同一個檔案系統,將使用 mv 進行重新命名"
+
+#: plugins/sudoers/visudo.c:836
+#, c-format
+msgid "command failed: '%s %s %s', %s unchanged"
+msgstr "指令失敗:「%s %s %s」,%s 未變更"
+
+#: plugins/sudoers/visudo.c:843
+#, c-format
+msgid "error renaming %s, %s unchanged"
+msgstr "重新命名 %s 發生錯誤,%s 未變更"
+
+#: plugins/sudoers/visudo.c:864
+msgid "What now? "
+msgstr "現在該做些什麼?"
+
+#: plugins/sudoers/visudo.c:878
+msgid ""
+"Options are:\n"
+" (e)dit sudoers file again\n"
+" e(x)it without saving changes to sudoers file\n"
+" (Q)uit and save changes to sudoers file (DANGER!)\n"
+msgstr ""
+"選項有:\n"
+" 重新編輯 sudoers 檔案 (e)\n"
+" 退出,不儲存對 sudoers 檔案的變更 (x)\n"
+" 退出並將變更儲存到 sudoers 檔案(十分危險!)(Q)\n"
+
+#: plugins/sudoers/visudo.c:923
+#, c-format
+msgid "unable to run %s"
+msgstr "無法執行 %s"
+
+#: plugins/sudoers/visudo.c:954
+#, c-format
+msgid "%s: wrong owner (uid, gid) should be (%u, %u)\n"
+msgstr "%s:所有者無效,(uid, gid) 應為 (%u, %u)\n"
+
+#: plugins/sudoers/visudo.c:965
+#, c-format
+msgid "%s: bad permissions, should be mode 0%o\n"
+msgstr "%s:權限不正確,模式應該是 0%o\n"
+
+#: plugins/sudoers/visudo.c:1017 plugins/sudoers/visudo.c:1024
+#, c-format
+msgid "%s: parsed OK\n"
+msgstr "%s:解析正確\n"
+
+#: plugins/sudoers/visudo.c:1043
+#, c-format
+msgid "%s busy, try again later"
+msgstr "%s 忙碌中,請稍後重試"
+
+#: plugins/sudoers/visudo.c:1047
+msgid "Edit anyway? [y/N]"
+msgstr "仍然編輯?[y/N]"
+
+#: plugins/sudoers/visudo.c:1206
+msgid "the -x option will be removed in a future release"
+msgstr "未來版本會移除 -x 選項"
+
+#: plugins/sudoers/visudo.c:1208
+msgid "please consider using the cvtsudoers utility instead"
+msgstr "請考慮換用 cvtsudoers 工具"
+
+#: plugins/sudoers/visudo.c:1228
+#, c-format
+msgid "Warning: %s:%d:%d: unused %s \"%s\""
+msgstr "警告:%s:%d:%d: %s「%s」未使用"
+
+#: plugins/sudoers/visudo.c:1341
+#, c-format
+msgid ""
+"%s - safely edit the sudoers file\n"
+"\n"
+msgstr ""
+"%s - 安全地編輯 sudoers 檔案\n"
+"\n"
+
+#: plugins/sudoers/visudo.c:1343
+msgid ""
+"\n"
+"Options:\n"
+" -c, --check check-only mode\n"
+" -f, --file=sudoers specify sudoers file location\n"
+" -h, --help display help message and exit\n"
+" -I, --no-includes do not edit include files\n"
+" -q, --quiet less verbose (quiet) syntax error messages\n"
+" -s, --strict strict syntax checking\n"
+" -V, --version display version information and exit\n"
+msgstr ""
+"\n"
+"選項:\n"
+" -c, --check 純檢查模式\n"
+" -f, --file=sudoers 指定 sudoers 檔的位置\n"
+" -h, --help 顯示說明訊息並退出\n"
+" -I, --no-includes 不要編輯 include 檔案\n"
+" -q, --quiet 不詳細(不輸出)的語法錯誤訊息\n"
+" -s, --strict 嚴格語法檢查\n"
+" -V, --version 顯示版本訊息並退出\n"
+
+#: toke.l:184
+msgid "empty string"
+msgstr "字串空白"
+
+#: toke.l:196 toke.l:566
+msgid "empty group"
+msgstr "group 空白"
+
+#: toke.l:206 toke.l:564
+msgid "empty netgroup"
+msgstr "netgroup 空白"
+
+#: toke.l:284
+msgid "unterminated regular expression"
+msgstr "未終止的正規表達式"
+
+#: toke.l:358 toke.l:370 toke.l:382 toke.l:398 toke.l:417 toke.l:457
+msgid "invalid line continuation"
+msgstr "無效的行接續符號"
+
+#: toke.l:603 toke.l:615
+msgid "invalid IPv6 address"
+msgstr "無效的 IPv6 地址"
+
+#: toke.l:863
+msgid "unexpected line break in string"
+msgstr "字串中有非預期的斷行字元"
+
+#: toke.l:982
+msgid "ignoring editor backup file"
+msgstr "忽略編輯器備份檔"
+
+#: toke.l:985
+msgid "ignoring file name containing '.'"
+msgstr "忽略內含 “.” 的檔名"
+
+#: toke.l:1310
+msgid "too many levels of includes"
+msgstr "include 嵌套層數過多"
+
+#, c-format
+#~ msgid "timestamp owner (%s): No such user"
+#~ msgstr "時間戳所有者 (%s):無此使用者"
+
+#~ msgid "\thost unmatched"
+#~ msgstr "\t主機不相符"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s 必須由使用者 ID %d 所有"
+
+#~ msgid "%s must only be writable by owner"
+#~ msgstr "%s 必須只允許所有者可寫"
+
+#~ msgid "Warning: %s:%d:%d: cycle in %s \"%s\""
+#~ msgstr "警告:%s:%d:%d: %s「%s」中有循環"
+
+#~ msgid "Warning: %s:%d:%d: %s \"%s\" referenced but not defined"
+#~ msgstr "警告:%s:%d:%d: 已引用但未定義 %s「%s」"
+
+#~ msgid "parse error in %s near line %d\n"
+#~ msgstr "因接近行 %2$d 的 %1$s 字串而導致解析錯誤\n"
+
+#~ msgid "parse error in %s\n"
+#~ msgstr "因 %s 導致解析錯誤\n"
+
+#~ msgid "%s: unknown defaults entry \"%s\""
+#~ msgstr "%s:未知的預設條目「%s」"
+
+#~ msgid "%s:%d:%d: no value specified for \"%s\""
+#~ msgstr "%s:%d:%d: 沒有指定「%s」的值"
+
+#~ msgid "%s:%d:%d: invalid operator \"%c=\" for \"%s\""
+#~ msgstr "%1$s:%2$d:%3$d: 「%5$s」的運算子「%4$c=」無效"
+
+#~ msgid "%s:%d:%d: option \"%s\" does not take a value"
+#~ msgstr "%s:%d:%d: 「%s」選項不帶值"
+
+#~ msgid "%s:%d:%d: invalid Defaults type 0x%x for option \"%s\""
+#~ msgstr "%1$s:%2$d:%3$d: 選項「%5$s」的預設 (Defaults) 類型 0x%4$x 無效"
+
+#~ msgid "%s:%d:%d: value \"%s\" is invalid for option \"%s\""
+#~ msgstr "%s:%d:%d: 「%s」值對「%s」選項無效"
+
+#~ msgid "%s:%d:%d: path name for \"%s\" too long"
+#~ msgstr "%s:%d:%d: 「%s」的路徑名稱過長"
+
+#~ msgid "%s: path name for \"%s\" too long"
+#~ msgstr "%s:「%s」的路徑名稱過長"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/', '~', or '*'"
+#~ msgstr "%s:%d:%d: \"%s\" 的值開頭必須是 '/'、'~' 或 '*'"
+
+#~ msgid "%s:%d:%d: values for \"%s\" must start with a '/'"
+#~ msgstr "%s:%d:%d: \"%s\" 的值開頭必須是 '/'"
+
+#~ msgid "parse error in %s near line %d"
+#~ msgstr "解析接近第 %2$d 行的 %1$s 時發生錯誤"
+
+#~ msgid "parse error in %s"
+#~ msgstr "解析 %s 中的內容時發生錯誤"
+
+#~ msgid "SELinux RBAC is not supported when intercept mode is enabled"
+#~ msgstr "不支援在啟用攔截模式時使用 SELinux RBAC"
+
+#~ msgid "SELinux RBAC is not supported when the log_subcmds flag is enabled"
+#~ msgstr "不支援在啟用 log_subcmds 旗標時使用 SELinux RBAC"
+
+#~ msgid "problem with defaults entries"
+#~ msgstr "預設條目有問題"
+
+#~ msgid "%s is group writable"
+#~ msgstr "%s 允許群組寫入"
+
+#~ msgid "lecture status path too long: %s/%s"
+#~ msgstr "指引狀態路徑過長:%s/%s"
+
+#~ msgid "internal error, unable to find %s in list!"
+#~ msgstr "內部錯誤,原因:列表中找不到 %s!"
+
+#~ msgid "%s is not in the sudoers file. This incident will be reported.\n"
+#~ msgstr "%s 不在 sudoers 檔案中。此事件將會回報。\n"
+
+#~ msgid "%s is not allowed to run sudo on %s. This incident will be reported.\n"
+#~ msgstr "%s 沒有權限在 %s 上執行 sudo。此事件將會回報。\n"
+
+#~ msgid "%s: write buffer already in use"
+#~ msgstr "%s:寫入緩衝區正被使用"
+
+#~ msgid "unable to read diffie-hellman parameters: %s"
+#~ msgstr "無法讀取 Diffie-Hellman 參數:%s"
+
+#~ msgid "%s:%d unknown key: %s"
+#~ msgstr "%s:%d 未知鍵:%s"
+
+#~ msgid "unable to get TLS server method: %s"
+#~ msgstr "無法取得 TLS 伺服器方法:%s"
+
+#~ msgid "%s:%u unable to parse \"%s\""
+#~ msgstr "%s:%u 無法解析「%s」"
+
+#, fuzzy
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " -f, --file path to configuration file\n"
+#~ " -h --help display help message and exit\n"
+#~ " -n, --no-fork do not fork, run in the foreground\n"
+#~ " -R, --random-drop percent chance connections will drop\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "選項:\n"
+#~ " -f, --file 設定檔路徑\n"
+#~ " -h, --help 顯示說明訊息並退出\n"
+#~ " -n, --no-fork 不要 fork,在前景執行\n"
+#~ " -R, --random-drop percent chance connections will drop\n"
+#~ " -V, --version 顯示版本資訊後離開\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "Options:\n"
+#~ " --help display help message and exit\n"
+#~ " -A, --accept only send an accept event (no I/O)\n"
+#~ " -h, --host host to send logs to\n"
+#~ " -i, --iolog_id remote ID of I/O log to be resumed\n"
+#~ " -p, --port port to use when connecting to host\n"
+#~ " -r, --restart restart previous I/O log transfer\n"
+#~ " -R, --reject reject the command with the given reason\n"
+#~ " -b, --ca-bundle certificate bundle file to verify server's cert against\n"
+#~ " -c, --cert certificate file for TLS handshake\n"
+#~ " -k, --key private key file\n"
+#~ " -n, --no-verify do not verify server certificate\n"
+#~ " -t, --test test audit server by sending selected I/O log n times in parallel\n"
+#~ " -V, --version display version information and exit\n"
+#~ msgstr ""
+#~ "\n"
+#~ "選項:\n"
+#~ " --help 顯示說明訊息後離開\n"
+#~ " -A, --accept 只傳送接受事件 (無 I/O)\n"
+#~ " -h, --host 要傳送記錄至的目標主機\n"
+#~ " -i, --iolog_id 要繼續的 I/O 記錄的遠端 ID\n"
+#~ " -p, --port 連線到主機時要使用的連線埠\n"
+#~ " -r, --restart 重新啟動上次的 I/O 記錄傳輸\n"
+#~ " -R, --reject 以提供的原因拒絕命令\n"
+#~ " -b, --ca-bundle 用來核驗伺服器憑證針對對象的憑證組合檔案\n"
+#~ " -c, --cert 用於 TLS 交握的憑證檔案\n"
+#~ " -k, --key 私鑰檔案\n"
+#~ " -n, --no-verify 不核驗伺服器憑證\n"
+#~ " -t, --test 透過並行傳送選取的 I/O 記錄 n 次來測試稽核伺服器\n"
+#~ " -V, --version 顯示版本資訊後離開\n"
+
+#~ msgid "Preload the dummy exec functions contained in the sudo_noexec library"
+#~ msgstr "預載「sudo_noexec」函式庫中包含的空 exec 函數"
+
+#~ msgid "sudo_ldap_conf_add_ports: port too large"
+#~ msgstr "sudo_ldap_conf_add_ports:連線埠過大"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s\n"
+#~ msgstr "SSL_connect 失敗:ssl_error=%d, stack=%s\n"
+
+#~ msgid "CA bundle file was not specified"
+#~ msgstr "未指定 CA bundle 檔案"
+
+#~ msgid "Client certificate was not specified"
+#~ msgstr "未指定用戶端憑證"
+
+#~ msgid "Unable to allocate ssl object: %s\n"
+#~ msgstr "無法配置 SSL 物件:%s\n"
+
+#~ msgid "Unable to attach socket to the ssl object: %s\n"
+#~ msgstr "無法將 socket 通訊端連結到 SSL 物件:%s\v\n"
+
+#~ msgid "client message too large: %zu\n"
+#~ msgstr "用戶端訊息過長:%zu\n"
+
+#~ msgid "server message too large: %u\n"
+#~ msgstr "伺服器訊息過長:%u\n"
+
+#~ msgid "CA bundle file is not set in sudoers"
+#~ msgstr "sudoers 中未設定 CA bundle 檔案"
+
+#~ msgid "Calling SSL_CTX_load_verify_locations() failed: %s"
+#~ msgstr "呼叫 SSL_CTX_load_verify_locations() 失敗:%s"
+
+#~ msgid "Signed certificate file is not set in sudoers"
+#~ msgstr "sudoers 中未設定已簽名的憑證檔案"
+
+#~ msgid "Unable to load private key into the ssl context: %s"
+#~ msgstr "無法載入私鑰進 SSL 上下文:%s"
+
+#~ msgid "SSL_connect failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_connect 失敗:ssl_error=%d, stack=%s"
+
+#~ msgid "SSL_read failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_read 失敗:ssl_error=%d, stack=%s"
+
+#~ msgid "SSL_write failed: ssl_error=%d, stack=%s"
+#~ msgstr "SSL_write 失敗:ssl_error=%d, stack=%s"
+
+#~ msgid "unknown address family: %d"
+#~ msgstr "未知的位址家族:%d"
+
+#~ msgid "audit_failure message too long"
+#~ msgstr "audit_failure 訊息過長"
+
+#~ msgid "No user or host"
+#~ msgstr "找不到使用者或主機"
+
+#~ msgid "validation failure"
+#~ msgstr "檢查有效性失敗"
+
+#~ msgid "%s/%s/timing: %s"
+#~ msgstr "%s/%s/計時:%s"
+
+#~ msgid "ignoring invalid attribute value: %s"
+#~ msgstr "將忽略無效的屬性值:%s"
+
+#~ msgid "unable to cache user %s, out of memory"
+#~ msgstr "無法快取使用者 %s,原因:記憶體不足"
+
+#~ msgid "unable to cache group %s, out of memory"
+#~ msgstr "無法快取群組 %s,原因:記憶體不足"
+
+#~ msgid "unable to cache group list for %s, out of memory"
+#~ msgstr "無法快取群組列表 %s,原因:已經存在"
diff --git a/plugins/sudoers/policy.c b/plugins/sudoers/policy.c
new file mode 100644
index 0000000..ac05dcf
--- /dev/null
+++ b/plugins/sudoers/policy.c
@@ -0,0 +1,1406 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <pwd.h>
+
+#include <sudoers.h>
+#include <sudoers_version.h>
+#include <timestamp.h>
+#include <interfaces.h>
+#include "auth/sudo_auth.h"
+
+static char **command_info;
+
+/*
+ * Command execution args to be filled in: argv, envp and command info.
+ */
+struct sudoers_exec_args {
+ char ***argv;
+ char ***envp;
+ char ***info;
+};
+
+static unsigned int sudo_version;
+static const char *interfaces_string;
+sudo_conv_t sudo_conv;
+sudo_printf_t sudo_printf;
+struct sudo_plugin_event * (*plugin_event_alloc)(void);
+static const char *path_sudoers = _PATH_SUDOERS;
+static bool session_opened;
+
+extern sudo_dso_public struct policy_plugin sudoers_policy;
+
+static int
+parse_bool(const char *line, int varlen, unsigned int *flags, unsigned int fval)
+{
+ debug_decl(parse_bool, SUDOERS_DEBUG_PLUGIN);
+
+ switch (sudo_strtobool(line + varlen + 1)) {
+ case true:
+ SET(*flags, fval);
+ debug_return_int(true);
+ case false:
+ CLR(*flags, fval);
+ debug_return_int(false);
+ default:
+ sudo_warnx(U_("invalid %.*s set by sudo front-end"),
+ varlen, line);
+ debug_return_int(-1);
+ }
+}
+
+#define RUN_VALID_FLAGS (MODE_ASKPASS|MODE_PRESERVE_ENV|MODE_RESET_HOME|MODE_IMPLIED_SHELL|MODE_LOGIN_SHELL|MODE_NONINTERACTIVE|MODE_IGNORE_TICKET|MODE_UPDATE_TICKET|MODE_PRESERVE_GROUPS|MODE_SHELL|MODE_RUN|MODE_POLICY_INTERCEPTED)
+#define EDIT_VALID_FLAGS (MODE_ASKPASS|MODE_NONINTERACTIVE|MODE_IGNORE_TICKET|MODE_UPDATE_TICKET|MODE_EDIT)
+#define LIST_VALID_FLAGS (MODE_ASKPASS|MODE_NONINTERACTIVE|MODE_IGNORE_TICKET|MODE_UPDATE_TICKET|MODE_LIST|MODE_CHECK)
+#define VALIDATE_VALID_FLAGS (MODE_ASKPASS|MODE_NONINTERACTIVE|MODE_IGNORE_TICKET|MODE_UPDATE_TICKET|MODE_VALIDATE)
+#define INVALIDATE_VALID_FLAGS (MODE_ASKPASS|MODE_NONINTERACTIVE|MODE_IGNORE_TICKET|MODE_UPDATE_TICKET|MODE_INVALIDATE)
+
+/*
+ * Deserialize args, settings and user_info arrays.
+ * Fills in struct sudoers_user_context and other common sudoers state.
+ */
+unsigned int
+sudoers_policy_deserialize_info(struct sudoers_context *ctx, void *v,
+ struct defaults_list *defaults)
+{
+ const char *p, *errstr, *groups = NULL;
+ struct sudoers_open_info *info = v;
+ unsigned int flags = MODE_UPDATE_TICKET;
+ const char *host = NULL;
+ const char *remhost = NULL;
+ unsigned char uuid[16];
+ char * const *cur;
+ debug_decl(sudoers_policy_deserialize_info, SUDOERS_DEBUG_PLUGIN);
+
+#define MATCHES(s, v) \
+ (strncmp((s), (v), sizeof(v) - 1) == 0)
+
+#define INVALID(v) do { \
+ sudo_warnx(U_("invalid %.*s set by sudo front-end"), \
+ (int)(sizeof(v) - 2), (v)); \
+} while (0)
+
+#define CHECK(s, v) do { \
+ if ((s)[sizeof(v) - 1] == '\0') { \
+ INVALID(v); \
+ goto bad; \
+ } \
+} while (0)
+
+ if (sudo_gettime_real(&ctx->submit_time) == -1) {
+ sudo_warn("%s", U_("unable to get time of day"));
+ goto bad;
+ }
+
+ /* Parse sudo.conf plugin args. */
+ if (info->plugin_args != NULL) {
+ for (cur = info->plugin_args; *cur != NULL; cur++) {
+ if (MATCHES(*cur, "error_recovery=")) {
+ int val = sudo_strtobool(*cur + sizeof("error_recovery=") - 1);
+ if (val == -1) {
+ INVALID("error_recovery="); /* Not a fatal error. */
+ } else {
+ ctx->parser_conf.recovery = val;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "ignore_perms=")) {
+ int val = sudo_strtobool(*cur + sizeof("ignore_perms=") - 1);
+ if (val == -1) {
+ INVALID("ignore_perms="); /* Not a fatal error. */
+ } else {
+ ctx->parser_conf.ignore_perms = val;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "sudoers_file=")) {
+ CHECK(*cur, "sudoers_file=");
+ path_sudoers = *cur + sizeof("sudoers_file=") - 1;
+ continue;
+ }
+ if (MATCHES(*cur, "sudoers_uid=")) {
+ p = *cur + sizeof("sudoers_uid=") - 1;
+ ctx->parser_conf.sudoers_uid = (uid_t)sudo_strtoid(p, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "sudoers_gid=")) {
+ p = *cur + sizeof("sudoers_gid=") - 1;
+ ctx->parser_conf.sudoers_gid = (gid_t)sudo_strtoid(p, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "sudoers_mode=")) {
+ p = *cur + sizeof("sudoers_mode=") - 1;
+ ctx->parser_conf.sudoers_mode = sudo_strtomode(p, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "ldap_conf=")) {
+ CHECK(*cur, "ldap_conf=");
+ ctx->settings.ldap_conf = *cur + sizeof("ldap_conf=") - 1;
+ continue;
+ }
+ if (MATCHES(*cur, "ldap_secret=")) {
+ CHECK(*cur, "ldap_secret=");
+ ctx->settings.ldap_secret = *cur + sizeof("ldap_secret=") - 1;
+ continue;
+ }
+ }
+ }
+ ctx->parser_conf.sudoers_path = path_sudoers;
+
+ /* Parse command line settings. */
+ ctx->settings.flags = 0;
+ ctx->user.closefrom = -1;
+ ctx->sudoedit_nfiles = 0;
+ ctx->mode = 0;
+ for (cur = info->settings; *cur != NULL; cur++) {
+ if (MATCHES(*cur, "closefrom=")) {
+ p = *cur + sizeof("closefrom=") - 1;
+ ctx->user.closefrom = (int)sudo_strtonum(p, 3, INT_MAX, &errstr);
+ if (ctx->user.closefrom == 0) {
+ sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "cmnd_chroot=")) {
+ CHECK(*cur, "cmnd_chroot=");
+ ctx->runas.chroot = *cur + sizeof("cmnd_chroot=") - 1;
+ if (strlen(ctx->runas.chroot) >= PATH_MAX) {
+ sudo_warnx(U_("path name for \"%s\" too long"), "cmnd_chroot");
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "cmnd_cwd=")) {
+ CHECK(*cur, "cmnd_cwd=");
+ ctx->runas.cwd = *cur + sizeof("cmnd_cwd=") - 1;
+ if (strlen(ctx->runas.cwd) >= PATH_MAX) {
+ sudo_warnx(U_("path name for \"%s\" too long"), "cmnd_cwd");
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "runas_user=")) {
+ CHECK(*cur, "runas_user=");
+ ctx->runas.user = *cur + sizeof("runas_user=") - 1;
+ SET(ctx->settings.flags, RUNAS_USER_SPECIFIED);
+ continue;
+ }
+ if (MATCHES(*cur, "runas_group=")) {
+ CHECK(*cur, "runas_group=");
+ ctx->runas.group = *cur + sizeof("runas_group=") - 1;
+ SET(ctx->settings.flags, RUNAS_GROUP_SPECIFIED);
+ continue;
+ }
+ if (MATCHES(*cur, "prompt=")) {
+ /* Allow epmpty prompt. */
+ ctx->user.prompt = *cur + sizeof("prompt=") - 1;
+ if (!append_default("passprompt_override", NULL, true, NULL, defaults))
+ goto oom;
+ continue;
+ }
+ if (MATCHES(*cur, "set_home=")) {
+ if (parse_bool(*cur, sizeof("set_home") - 1, &flags,
+ MODE_RESET_HOME) == -1)
+ goto bad;
+ continue;
+ }
+ if (MATCHES(*cur, "preserve_environment=")) {
+ if (parse_bool(*cur, sizeof("preserve_environment") - 1, &flags,
+ MODE_PRESERVE_ENV) == -1)
+ goto bad;
+ continue;
+ }
+ if (MATCHES(*cur, "run_shell=")) {
+ if (parse_bool(*cur, sizeof("run_shell") -1, &flags,
+ MODE_SHELL) == -1)
+ goto bad;
+ continue;
+ }
+ if (MATCHES(*cur, "login_shell=")) {
+ if (parse_bool(*cur, sizeof("login_shell") - 1, &flags,
+ MODE_LOGIN_SHELL) == -1)
+ goto bad;
+ continue;
+ }
+ if (MATCHES(*cur, "implied_shell=")) {
+ if (parse_bool(*cur, sizeof("implied_shell") - 1, &flags,
+ MODE_IMPLIED_SHELL) == -1)
+ goto bad;
+ continue;
+ }
+ if (MATCHES(*cur, "preserve_groups=")) {
+ if (parse_bool(*cur, sizeof("preserve_groups") - 1, &flags,
+ MODE_PRESERVE_GROUPS) == -1)
+ goto bad;
+ continue;
+ }
+ if (MATCHES(*cur, "ignore_ticket=")) {
+ if (parse_bool(*cur, sizeof("ignore_ticket") -1, &flags,
+ MODE_IGNORE_TICKET) == -1)
+ goto bad;
+ continue;
+ }
+ if (MATCHES(*cur, "update_ticket=")) {
+ if (parse_bool(*cur, sizeof("update_ticket") -1, &flags,
+ MODE_UPDATE_TICKET) == -1)
+ goto bad;
+ continue;
+ }
+ if (MATCHES(*cur, "noninteractive=")) {
+ if (parse_bool(*cur, sizeof("noninteractive") - 1, &flags,
+ MODE_NONINTERACTIVE) == -1)
+ goto bad;
+ continue;
+ }
+ if (MATCHES(*cur, "sudoedit=")) {
+ if (parse_bool(*cur, sizeof("sudoedit") - 1, &flags,
+ MODE_EDIT) == -1)
+ goto bad;
+ continue;
+ }
+ if (MATCHES(*cur, "login_class=")) {
+ CHECK(*cur, "login_class=");
+ ctx->runas.class = *cur + sizeof("login_class=") - 1;
+ if (!append_default("use_loginclass", NULL, true, NULL, defaults))
+ goto oom;
+ continue;
+ }
+ if (MATCHES(*cur, "intercept_ptrace=")) {
+ if (parse_bool(*cur, sizeof("intercept_ptrace") - 1, &ctx->settings.flags,
+ HAVE_INTERCEPT_PTRACE) == -1)
+ goto bad;
+ continue;
+ }
+ if (MATCHES(*cur, "intercept_setid=")) {
+ if (parse_bool(*cur, sizeof("intercept_setid") - 1, &ctx->settings.flags,
+ CAN_INTERCEPT_SETID) == -1)
+ goto bad;
+ continue;
+ }
+#ifdef HAVE_SELINUX
+ if (MATCHES(*cur, "selinux_role=")) {
+ CHECK(*cur, "selinux_role=");
+ free(ctx->runas.role);
+ ctx->runas.role = strdup(*cur + sizeof("selinux_role=") - 1);
+ if (ctx->runas.role == NULL)
+ goto oom;
+ continue;
+ }
+ if (MATCHES(*cur, "selinux_type=")) {
+ CHECK(*cur, "selinux_type=");
+ free(ctx->runas.type);
+ ctx->runas.type = strdup(*cur + sizeof("selinux_type=") - 1);
+ if (ctx->runas.type == NULL)
+ goto oom;
+ continue;
+ }
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_APPARMOR
+ if (MATCHES(*cur, "apparmor_profile=")) {
+ CHECK(*cur, "apparmor_profile=");
+ free(ctx->runas.apparmor_profile);
+ ctx->runas.apparmor_profile = strdup(*cur + sizeof("apparmor_profile=") - 1);
+ if (ctx->runas.apparmor_profile == NULL)
+ goto oom;
+ continue;
+ }
+#endif /* HAVE_APPARMOR */
+#ifdef HAVE_BSD_AUTH_H
+ if (MATCHES(*cur, "bsdauth_type=")) {
+ CHECK(*cur, "bsdauth_type=");
+ p = *cur + sizeof("bsdauth_type=") - 1;
+ bsdauth_set_style(p);
+ continue;
+ }
+#endif /* HAVE_BSD_AUTH_H */
+ if (MATCHES(*cur, "network_addrs=")) {
+ interfaces_string = *cur + sizeof("network_addrs=") - 1;
+ if (!set_interfaces(interfaces_string)) {
+ sudo_warn("%s", U_("unable to parse network address list"));
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "max_groups=")) {
+ int max_groups;
+ p = *cur + sizeof("max_groups=") - 1;
+ max_groups = (int)sudo_strtonum(p, 1, 1024, &errstr);
+ if (max_groups == 0) {
+ sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
+ goto bad;
+ }
+ sudo_pwutil_set_max_groups(max_groups);
+ continue;
+ }
+ if (MATCHES(*cur, "remote_host=")) {
+ CHECK(*cur, "remote_host=");
+ remhost = *cur + sizeof("remote_host=") - 1;
+ continue;
+ }
+ if (MATCHES(*cur, "timeout=")) {
+ p = *cur + sizeof("timeout=") - 1;
+ ctx->user.timeout = parse_timeout(p);
+ if (ctx->user.timeout == -1) {
+ if (errno == ERANGE)
+ sudo_warnx(U_("%s: %s"), p, U_("timeout value too large"));
+ else
+ sudo_warnx(U_("%s: %s"), p, U_("invalid timeout value"));
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "askpass=")) {
+ if (parse_bool(*cur, sizeof("askpass") - 1, &flags,
+ MODE_ASKPASS) == -1)
+ goto bad;
+ continue;
+ }
+#ifdef ENABLE_SUDO_PLUGIN_API
+ if (MATCHES(*cur, "plugin_dir=")) {
+ CHECK(*cur, "plugin_dir=");
+ ctx->settings.plugin_dir = *cur + sizeof("plugin_dir=") - 1;
+ continue;
+ }
+#endif
+ }
+ /* Ignore ticket trumps update. */
+ if (ISSET(flags, MODE_IGNORE_TICKET))
+ CLR(flags, MODE_UPDATE_TICKET);
+
+ ctx->user.gid = (gid_t)-1;
+ ctx->user.uid = (gid_t)-1;
+ ctx->user.umask = (mode_t)-1;
+ for (cur = info->user_info; *cur != NULL; cur++) {
+ if (MATCHES(*cur, "user=")) {
+ CHECK(*cur, "user=");
+ free(ctx->user.name);
+ if ((ctx->user.name = strdup(*cur + sizeof("user=") - 1)) == NULL)
+ goto oom;
+ continue;
+ }
+ if (MATCHES(*cur, "euid=")) {
+ p = *cur + sizeof("euid=") - 1;
+ ctx->user.euid = (uid_t) sudo_strtoid(p, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "uid=")) {
+ p = *cur + sizeof("uid=") - 1;
+ ctx->user.uid = (uid_t) sudo_strtoid(p, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "egid=")) {
+ p = *cur + sizeof("egid=") - 1;
+ ctx->user.egid = (gid_t) sudo_strtoid(p, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "gid=")) {
+ p = *cur + sizeof("gid=") - 1;
+ ctx->user.gid = (gid_t) sudo_strtoid(p, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "groups=")) {
+ CHECK(*cur, "groups=");
+ groups = *cur + sizeof("groups=") - 1;
+ continue;
+ }
+ if (MATCHES(*cur, "cwd=")) {
+ CHECK(*cur, "cwd=");
+ free(ctx->user.cwd);
+ if ((ctx->user.cwd = strdup(*cur + sizeof("cwd=") - 1)) == NULL)
+ goto oom;
+ continue;
+ }
+ if (MATCHES(*cur, "tty=")) {
+ CHECK(*cur, "tty=");
+ free(ctx->user.ttypath);
+ if ((ctx->user.ttypath = strdup(*cur + sizeof("tty=") - 1)) == NULL)
+ goto oom;
+ ctx->user.tty = ctx->user.ttypath;
+ if (strncmp(ctx->user.tty, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
+ ctx->user.tty += sizeof(_PATH_DEV) - 1;
+ continue;
+ }
+ if (MATCHES(*cur, "host=")) {
+ CHECK(*cur, "host=");
+ host = *cur + sizeof("host=") - 1;
+ continue;
+ }
+ if (MATCHES(*cur, "lines=")) {
+ p = *cur + sizeof("lines=") - 1;
+ ctx->user.lines = (int)sudo_strtonum(p, 1, INT_MAX, &errstr);
+ if (ctx->user.lines == 0) {
+ sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "cols=")) {
+ p = *cur + sizeof("cols=") - 1;
+ ctx->user.cols = (int)sudo_strtonum(p, 1, INT_MAX, &errstr);
+ if (ctx->user.cols == 0) {
+ sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "pid=")) {
+ p = *cur + sizeof("pid=") - 1;
+ ctx->user.pid = (pid_t) sudo_strtoid(p, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "ppid=")) {
+ p = *cur + sizeof("ppid=") - 1;
+ ctx->user.ppid = (pid_t) sudo_strtoid(p, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "sid=")) {
+ p = *cur + sizeof("sid=") - 1;
+ ctx->user.sid = (pid_t) sudo_strtoid(p, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "tcpgid=")) {
+ p = *cur + sizeof("tcpgid=") - 1;
+ ctx->user.tcpgid = (pid_t) sudo_strtoid(p, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
+ goto bad;
+ }
+ continue;
+ }
+ if (MATCHES(*cur, "umask=")) {
+ p = *cur + sizeof("umask=") - 1;
+ ctx->user.umask = sudo_strtomode(p, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), *cur, U_(errstr));
+ goto bad;
+ }
+ continue;
+ }
+ }
+
+ /* User name, user-ID, group-ID and host name must be specified. */
+ if (ctx->user.name == NULL) {
+ sudo_warnx("%s", U_("user name not set by sudo front-end"));
+ goto bad;
+ }
+ if (ctx->user.uid == (uid_t)-1) {
+ sudo_warnx("%s", U_("user-ID not set by sudo front-end"));
+ goto bad;
+ }
+ if (ctx->user.gid == (gid_t)-1) {
+ sudo_warnx("%s", U_("group-ID not set by sudo front-end"));
+ goto bad;
+ }
+ if (host == NULL) {
+ sudo_warnx("%s", U_("host name not set by sudo front-end"));
+ goto bad;
+ }
+
+ if (!sudoers_sethost(ctx, host, remhost)) {
+ /* sudoers_sethost() will print a warning on error. */
+ goto bad;
+ }
+ if (ctx->user.tty == NULL) {
+ if ((ctx->user.tty = strdup("unknown")) == NULL)
+ goto oom;
+ /* ctx->user.ttypath remains NULL */
+ }
+
+ ctx->user.pw = sudo_getpwnam(ctx->user.name);
+ if (ctx->user.pw != NULL && groups != NULL) {
+ /* sudo_parse_gids() will print a warning on error. */
+ GETGROUPS_T *gids;
+ int ngids = sudo_parse_gids(groups, &ctx->user.gid, &gids);
+ if (ngids == -1)
+ goto bad;
+
+ /* sudo_set_gidlist will adopt gids[] */
+ if (sudo_set_gidlist(ctx->user.pw, ngids, gids, NULL, ENTRY_TYPE_FRONTEND) == -1) {
+ free(gids);
+ goto bad;
+ }
+ }
+
+ /* umask is only set in user_info[] for API 1.10 and above. */
+ if (ctx->user.umask == (mode_t)-1) {
+ ctx->user.umask = umask(0);
+ umask(ctx->user.umask);
+ }
+
+ /* Always reset the environment for a login shell. */
+ if (ISSET(flags, MODE_LOGIN_SHELL))
+ def_env_reset = true;
+
+ /* Some systems support fexecve() which we use for digest matches. */
+ ctx->runas.execfd = -1;
+
+ /* Create a UUID to store in the event log. */
+ sudo_uuid_create(uuid);
+ if (sudo_uuid_to_string(uuid, ctx->uuid_str, sizeof(ctx->uuid_str)) == NULL) {
+ sudo_warnx("%s", U_("unable to generate UUID"));
+ goto bad;
+ }
+
+ /*
+ * Set intercept defaults based on flags set above.
+ * We pass -1 as the operator to indicate it is set by the front end.
+ */
+ if (ISSET(ctx->settings.flags, HAVE_INTERCEPT_PTRACE)) {
+ if (!append_default("intercept_type", "trace", -1, NULL, defaults))
+ goto oom;
+ }
+ if (ISSET(ctx->settings.flags, CAN_INTERCEPT_SETID)) {
+ if (!append_default("intercept_allow_setid", NULL, -1, NULL, defaults))
+ goto oom;
+ }
+
+#ifdef NO_ROOT_MAILER
+ eventlog_set_mailuid(ctx->user.uid);
+#endif
+
+ /* Dump settings and user info (XXX - plugin args) */
+ for (cur = info->settings; *cur != NULL; cur++)
+ sudo_debug_printf(SUDO_DEBUG_INFO, "settings: %s", *cur);
+ for (cur = info->user_info; *cur != NULL; cur++)
+ sudo_debug_printf(SUDO_DEBUG_INFO, "user_info: %s", *cur);
+
+#undef MATCHES
+#undef INVALID
+#undef CHECK
+ debug_return_uint(flags);
+
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+bad:
+ debug_return_uint(MODE_ERROR);
+}
+
+/*
+ * Store the execution environment and other front-end settings.
+ * Builds up the command_info list and sets argv and envp.
+ * Consumes iolog_path if not NULL.
+ * Returns true on success, else false.
+ */
+bool
+sudoers_policy_store_result(struct sudoers_context *ctx, bool accepted,
+ char *argv[], char *envp[], mode_t cmnd_umask, char *iolog_path, void *v)
+{
+ struct sudoers_exec_args *exec_args = v;
+ unsigned int info_len = 0;
+ debug_decl(sudoers_policy_store_result, SUDOERS_DEBUG_PLUGIN);
+
+ if (exec_args == NULL)
+ debug_return_bool(true); /* nothing to do */
+
+ /* Free old data, if any. */
+ if (command_info != NULL) {
+ char **cur;
+ sudoers_gc_remove(GC_VECTOR, command_info);
+ for (cur = command_info; *cur != NULL; cur++)
+ free(*cur);
+ free(command_info);
+ }
+
+ /* Increase the length of command_info as needed, it is *not* checked. */
+ command_info = calloc(74, sizeof(char *));
+ if (command_info == NULL)
+ goto oom;
+
+ if (ctx->runas.cmnd != NULL) {
+ command_info[info_len] = sudo_new_key_val("command", ctx->runas.cmnd);
+ if (command_info[info_len++] == NULL)
+ goto oom;
+ }
+ if (def_log_subcmds) {
+ if ((command_info[info_len++] = strdup("log_subcmds=true")) == NULL)
+ goto oom;
+ }
+ if (iolog_enabled) {
+ if (iolog_path)
+ command_info[info_len++] = iolog_path; /* now owned */
+ if (def_log_stdin) {
+ if ((command_info[info_len++] = strdup("iolog_stdin=true")) == NULL)
+ goto oom;
+ }
+ if (def_log_stdout) {
+ if ((command_info[info_len++] = strdup("iolog_stdout=true")) == NULL)
+ goto oom;
+ }
+ if (def_log_stderr) {
+ if ((command_info[info_len++] = strdup("iolog_stderr=true")) == NULL)
+ goto oom;
+ }
+ if (def_log_ttyin) {
+ if ((command_info[info_len++] = strdup("iolog_ttyin=true")) == NULL)
+ goto oom;
+ }
+ if (def_log_ttyout) {
+ if ((command_info[info_len++] = strdup("iolog_ttyout=true")) == NULL)
+ goto oom;
+ }
+ if (def_compress_io) {
+ if ((command_info[info_len++] = strdup("iolog_compress=true")) == NULL)
+ goto oom;
+ }
+ if (def_iolog_flush) {
+ if ((command_info[info_len++] = strdup("iolog_flush=true")) == NULL)
+ goto oom;
+ }
+ if ((command_info[info_len++] = sudo_new_key_val("log_passwords",
+ def_log_passwords ? "true" : "false")) == NULL)
+ goto oom;
+ if (!SLIST_EMPTY(&def_passprompt_regex)) {
+ char *passprompt_regex =
+ serialize_list("passprompt_regex", &def_passprompt_regex);
+ if (passprompt_regex == NULL)
+ goto oom;
+ command_info[info_len++] = passprompt_regex;
+ }
+ if (def_maxseq != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("maxseq", def_maxseq)) == NULL)
+ goto oom;
+ }
+ }
+ if (ISSET(ctx->mode, MODE_EDIT)) {
+ if ((command_info[info_len++] = strdup("sudoedit=true")) == NULL)
+ goto oom;
+ if (ctx->sudoedit_nfiles > 0) {
+ if (asprintf(&command_info[info_len++], "sudoedit_nfiles=%d",
+ ctx->sudoedit_nfiles) == -1)
+ goto oom;
+ }
+ if (!def_sudoedit_checkdir) {
+ if ((command_info[info_len++] = strdup("sudoedit_checkdir=false")) == NULL)
+ goto oom;
+ }
+ if (def_sudoedit_follow) {
+ if ((command_info[info_len++] = strdup("sudoedit_follow=true")) == NULL)
+ goto oom;
+ }
+ }
+ if (def_runcwd && strcmp(def_runcwd, "*") != 0) {
+ /* Set cwd to explicit value (sudoers or user-specified). */
+ if (!expand_tilde(&def_runcwd, ctx->runas.pw->pw_name)) {
+ sudo_warnx(U_("invalid working directory: %s"), def_runcwd);
+ goto bad;
+ }
+ if ((command_info[info_len++] = sudo_new_key_val("cwd", def_runcwd)) == NULL)
+ goto oom;
+ } else if (ISSET(ctx->mode, MODE_LOGIN_SHELL)) {
+ /* Set cwd to run user's homedir. */
+ if ((command_info[info_len++] = sudo_new_key_val("cwd", ctx->runas.pw->pw_dir)) == NULL)
+ goto oom;
+ if ((command_info[info_len++] = strdup("cwd_optional=true")) == NULL)
+ goto oom;
+ }
+ if ((command_info[info_len++] = sudo_new_key_val("runas_user", ctx->runas.pw->pw_name)) == NULL)
+ goto oom;
+ if (ctx->runas.gr != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("runas_group", ctx->runas.gr->gr_name)) == NULL)
+ goto oom;
+ }
+ if (def_stay_setuid) {
+ if (asprintf(&command_info[info_len++], "runas_uid=%u",
+ (unsigned int)ctx->user.uid) == -1)
+ goto oom;
+ if (asprintf(&command_info[info_len++], "runas_gid=%u",
+ (unsigned int)ctx->user.gid) == -1)
+ goto oom;
+ if (asprintf(&command_info[info_len++], "runas_euid=%u",
+ (unsigned int)ctx->runas.pw->pw_uid) == -1)
+ goto oom;
+ if (asprintf(&command_info[info_len++], "runas_egid=%u",
+ ctx->runas.gr ? (unsigned int)ctx->runas.gr->gr_gid :
+ (unsigned int)ctx->runas.pw->pw_gid) == -1)
+ goto oom;
+ } else {
+ if (asprintf(&command_info[info_len++], "runas_uid=%u",
+ (unsigned int)ctx->runas.pw->pw_uid) == -1)
+ goto oom;
+ if (asprintf(&command_info[info_len++], "runas_gid=%u",
+ ctx->runas.gr ? (unsigned int)ctx->runas.gr->gr_gid :
+ (unsigned int)ctx->runas.pw->pw_gid) == -1)
+ goto oom;
+ }
+ if (def_preserve_groups) {
+ if ((command_info[info_len++] = strdup("preserve_groups=true")) == NULL)
+ goto oom;
+ } else {
+ int i, len;
+ gid_t egid;
+ size_t glsize;
+ char *cp, *gid_list;
+ struct gid_list *gidlist;
+
+ /* Only use results from a group db query, not the front end. */
+ gidlist = sudo_get_gidlist(ctx->runas.pw, ENTRY_TYPE_QUERIED);
+
+ /* We reserve an extra spot in the list for the effective gid. */
+ glsize = sizeof("runas_groups=") - 1 +
+ (((size_t)gidlist->ngids + 1) * (STRLEN_MAX_UNSIGNED(gid_t) + 1));
+ gid_list = malloc(glsize);
+ if (gid_list == NULL) {
+ sudo_gidlist_delref(gidlist);
+ goto oom;
+ }
+ memcpy(gid_list, "runas_groups=", sizeof("runas_groups=") - 1);
+ cp = gid_list + sizeof("runas_groups=") - 1;
+ glsize -= (size_t)(cp - gid_list);
+
+ /* On BSD systems the effective gid is the first group in the list. */
+ egid = ctx->runas.gr ? (unsigned int)ctx->runas.gr->gr_gid :
+ (unsigned int)ctx->runas.pw->pw_gid;
+ len = snprintf(cp, glsize, "%u", (unsigned int)egid);
+ if (len < 0 || (size_t)len >= glsize) {
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ free(gid_list);
+ sudo_gidlist_delref(gidlist);
+ goto bad;
+ }
+ cp += len;
+ glsize -= (size_t)len;
+ for (i = 0; i < gidlist->ngids; i++) {
+ if (gidlist->gids[i] != egid) {
+ len = snprintf(cp, glsize, ",%u",
+ (unsigned int)gidlist->gids[i]);
+ if (len < 0 || (size_t)len >= glsize) {
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ free(gid_list);
+ sudo_gidlist_delref(gidlist);
+ goto bad;
+ }
+ cp += len;
+ glsize -= (size_t)len;
+ }
+ }
+ command_info[info_len++] = gid_list;
+ sudo_gidlist_delref(gidlist);
+ }
+ if (def_closefrom >= 0) {
+ if (asprintf(&command_info[info_len++], "closefrom=%d", def_closefrom) == -1)
+ goto oom;
+ }
+ if (def_ignore_iolog_errors) {
+ if ((command_info[info_len++] = strdup("ignore_iolog_errors=true")) == NULL)
+ goto oom;
+ }
+ if (def_intercept) {
+ if ((command_info[info_len++] = strdup("intercept=true")) == NULL)
+ goto oom;
+ }
+ if (def_intercept_type == trace) {
+ if ((command_info[info_len++] = strdup("use_ptrace=true")) == NULL)
+ goto oom;
+ }
+ if (def_intercept_verify) {
+ if ((command_info[info_len++] = strdup("intercept_verify=true")) == NULL)
+ goto oom;
+ }
+ if (def_noexec) {
+ if ((command_info[info_len++] = strdup("noexec=true")) == NULL)
+ goto oom;
+ }
+ if (def_exec_background) {
+ if ((command_info[info_len++] = strdup("exec_background=true")) == NULL)
+ goto oom;
+ }
+ if (def_set_utmp) {
+ if ((command_info[info_len++] = strdup("set_utmp=true")) == NULL)
+ goto oom;
+ }
+ if (def_use_pty) {
+ if ((command_info[info_len++] = strdup("use_pty=true")) == NULL)
+ goto oom;
+ }
+ if (def_utmp_runas) {
+ if ((command_info[info_len++] = sudo_new_key_val("utmp_user", ctx->runas.pw->pw_name)) == NULL)
+ goto oom;
+ }
+ if (def_iolog_mode != (S_IRUSR|S_IWUSR)) {
+ if (asprintf(&command_info[info_len++], "iolog_mode=0%o", (unsigned int)def_iolog_mode) == -1)
+ goto oom;
+ }
+ if (def_iolog_user != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("iolog_user", def_iolog_user)) == NULL)
+ goto oom;
+ }
+ if (def_iolog_group != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("iolog_group", def_iolog_group)) == NULL)
+ goto oom;
+ }
+ if (!SLIST_EMPTY(&def_log_servers)) {
+ char *log_servers = serialize_list("log_servers", &def_log_servers);
+ if (log_servers == NULL)
+ goto oom;
+ command_info[info_len++] = log_servers;
+
+ if (asprintf(&command_info[info_len++], "log_server_timeout=%u", def_log_server_timeout) == -1)
+ goto oom;
+ }
+
+ if ((command_info[info_len++] = sudo_new_key_val("log_server_keepalive",
+ def_log_server_keepalive ? "true" : "false")) == NULL)
+ goto oom;
+
+ if ((command_info[info_len++] = sudo_new_key_val("log_server_verify",
+ def_log_server_verify ? "true" : "false")) == NULL)
+ goto oom;
+
+ if (def_log_server_cabundle != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("log_server_cabundle", def_log_server_cabundle)) == NULL)
+ goto oom;
+ }
+ if (def_log_server_peer_cert != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("log_server_peer_cert", def_log_server_peer_cert)) == NULL)
+ goto oom;
+ }
+ if (def_log_server_peer_key != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("log_server_peer_key", def_log_server_peer_key)) == NULL)
+ goto oom;
+ }
+
+ if (def_command_timeout > 0 || ctx->user.timeout > 0) {
+ int timeout = ctx->user.timeout;
+ if (timeout == 0 || (def_command_timeout > 0 && def_command_timeout < timeout))
+ timeout = def_command_timeout;
+ if (asprintf(&command_info[info_len++], "timeout=%u", timeout) == -1)
+ goto oom;
+ }
+ if (def_runchroot != NULL && strcmp(def_runchroot, "*") != 0) {
+ if (!expand_tilde(&def_runchroot, ctx->runas.pw->pw_name)) {
+ sudo_warnx(U_("invalid chroot directory: %s"), def_runchroot);
+ goto bad;
+ }
+ if ((command_info[info_len++] = sudo_new_key_val("chroot", def_runchroot)) == NULL)
+ goto oom;
+ }
+ if (cmnd_umask != ACCESSPERMS) {
+ if (asprintf(&command_info[info_len++], "umask=0%o", (unsigned int)cmnd_umask) == -1)
+ goto oom;
+ }
+ if (sudoers_override_umask()) {
+ if ((command_info[info_len++] = strdup("umask_override=true")) == NULL)
+ goto oom;
+ }
+ if (ctx->runas.execfd != -1) {
+ if (sudo_version < SUDO_API_MKVERSION(1, 9)) {
+ /* execfd only supported by plugin API 1.9 and higher */
+ close(ctx->runas.execfd);
+ ctx->runas.execfd = -1;
+ } else {
+ if (asprintf(&command_info[info_len++], "execfd=%d", ctx->runas.execfd) == -1)
+ goto oom;
+ }
+ }
+ if (def_rlimit_as != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("rlimit_as", def_rlimit_as)) == NULL)
+ goto oom;
+ }
+ if (def_rlimit_core != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("rlimit_core", def_rlimit_core)) == NULL)
+ goto oom;
+ }
+ if (def_rlimit_cpu != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("rlimit_cpu", def_rlimit_cpu)) == NULL)
+ goto oom;
+ }
+ if (def_rlimit_data != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("rlimit_data", def_rlimit_data)) == NULL)
+ goto oom;
+ }
+ if (def_rlimit_fsize != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("rlimit_fsize", def_rlimit_fsize)) == NULL)
+ goto oom;
+ }
+ if (def_rlimit_locks != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("rlimit_locks", def_rlimit_locks)) == NULL)
+ goto oom;
+ }
+ if (def_rlimit_memlock != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("rlimit_memlock", def_rlimit_memlock)) == NULL)
+ goto oom;
+ }
+ if (def_rlimit_nofile != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("rlimit_nofile", def_rlimit_nofile)) == NULL)
+ goto oom;
+ }
+ if (def_rlimit_nproc != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("rlimit_nproc", def_rlimit_nproc)) == NULL)
+ goto oom;
+ }
+ if (def_rlimit_rss != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("rlimit_rss", def_rlimit_rss)) == NULL)
+ goto oom;
+ }
+ if (def_rlimit_stack != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("rlimit_stack", def_rlimit_stack)) == NULL)
+ goto oom;
+ }
+ if (ctx->source != NULL) {
+ command_info[info_len] = sudo_new_key_val("source", ctx->source);
+ if (command_info[info_len++] == NULL)
+ goto oom;
+ }
+#ifdef HAVE_LOGIN_CAP_H
+ if (def_use_loginclass) {
+ if ((command_info[info_len++] = sudo_new_key_val("login_class", ctx->runas.class)) == NULL)
+ goto oom;
+ }
+#endif /* HAVE_LOGIN_CAP_H */
+#ifdef HAVE_SELINUX
+ if (def_selinux && ctx->runas.role != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("selinux_role", ctx->runas.role)) == NULL)
+ goto oom;
+ }
+ if (def_selinux && ctx->runas.type != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("selinux_type", ctx->runas.type)) == NULL)
+ goto oom;
+ }
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_APPARMOR
+ if (ctx->runas.apparmor_profile != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("apparmor_profile", ctx->runas.apparmor_profile)) == NULL)
+ goto oom;
+ }
+#endif /* HAVE_APPARMOR */
+#ifdef HAVE_PRIV_SET
+ if (ctx->runas.privs != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("runas_privs", ctx->runas.privs)) == NULL)
+ goto oom;
+ }
+ if (ctx->runas.limitprivs != NULL) {
+ if ((command_info[info_len++] = sudo_new_key_val("runas_limitprivs", ctx->runas.limitprivs)) == NULL)
+ goto oom;
+ }
+#endif /* HAVE_PRIV_SET */
+
+ /* Fill in exec environment info. */
+ *(exec_args->argv) = argv;
+ *(exec_args->envp) = envp;
+ *(exec_args->info) = command_info;
+
+ /* Free command_info on exit. */
+ sudoers_gc_add(GC_VECTOR, command_info);
+
+ debug_return_bool(true);
+
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+bad:
+ free(audit_msg);
+ audit_msg = NULL;
+ while (info_len)
+ free(command_info[--info_len]);
+ free(command_info);
+ command_info = NULL;
+ debug_return_bool(false);
+}
+
+bool
+sudoers_tty_present(struct sudoers_context *ctx)
+{
+ debug_decl(sudoers_tty_present, SUDOERS_DEBUG_PLUGIN);
+
+ if (ctx->user.tcpgid == 0 && ctx->user.ttypath == NULL) {
+ /* No job control or terminal, check /dev/tty. */
+ int fd = open(_PATH_TTY, O_RDWR);
+ if (fd == -1)
+ debug_return_bool(false);
+ close(fd);
+ }
+ debug_return_bool(true);
+}
+
+static int
+sudoers_policy_open(unsigned int version, sudo_conv_t conversation,
+ sudo_printf_t plugin_printf, char * const settings[],
+ char * const user_info[], char * const envp[], char * const args[],
+ const char **errstr)
+{
+ struct sudo_conf_debug_file_list debug_files = TAILQ_HEAD_INITIALIZER(debug_files);
+ struct sudoers_open_info info;
+ const char *cp, *plugin_path = NULL;
+ char * const *cur;
+ int ret;
+ debug_decl(sudoers_policy_open, SUDOERS_DEBUG_PLUGIN);
+
+ sudo_version = version;
+ sudo_conv = conversation;
+ sudo_printf = plugin_printf;
+ if (sudoers_policy.event_alloc != NULL)
+ plugin_event_alloc = sudoers_policy.event_alloc;
+
+ /* Plugin args are only specified for API version 1.2 and higher. */
+ if (sudo_version < SUDO_API_MKVERSION(1, 2))
+ args = NULL;
+
+ /* Initialize the debug subsystem. */
+ for (cur = settings; (cp = *cur) != NULL; cur++) {
+ if (strncmp(cp, "debug_flags=", sizeof("debug_flags=") - 1) == 0) {
+ cp += sizeof("debug_flags=") - 1;
+ if (!sudoers_debug_parse_flags(&debug_files, cp))
+ debug_return_int(-1);
+ continue;
+ }
+ if (strncmp(cp, "plugin_path=", sizeof("plugin_path=") - 1) == 0) {
+ plugin_path = cp + sizeof("plugin_path=") - 1;
+ continue;
+ }
+ }
+ if (!sudoers_debug_register(plugin_path, &debug_files))
+ debug_return_int(-1);
+
+ /* Call the sudoers init function. */
+ info.settings = settings;
+ info.user_info = user_info;
+ info.plugin_args = args;
+ ret = sudoers_init(&info, log_parse_error, envp);
+
+ /* The audit functions set audit_msg on failure. */
+ if (ret != 1 && audit_msg != NULL) {
+ if (sudo_version >= SUDO_API_MKVERSION(1, 15))
+ *errstr = audit_msg;
+ }
+
+ debug_return_int(ret);
+}
+
+static void
+sudoers_policy_close(int exit_status, int error_code)
+{
+ const struct sudoers_context *ctx = sudoers_get_context();
+ debug_decl(sudoers_policy_close, SUDOERS_DEBUG_PLUGIN);
+
+ if (session_opened) {
+ /* Close the session we opened in sudoers_policy_init_session(). */
+ (void)sudo_auth_end_session();
+
+ if (error_code) {
+ errno = error_code;
+ sudo_warn(U_("unable to execute %s"), ctx->runas.cmnd);
+ } else {
+ log_exit_status(ctx, exit_status);
+ }
+ }
+
+ /* Deregister the callback for sudo_fatal()/sudo_fatalx(). */
+ sudo_fatal_callback_deregister(sudoers_cleanup);
+
+ /* Free sudoers sources, ctx->user.and passwd/group caches. */
+ sudoers_cleanup();
+
+ /* command_info was freed by the g/c code. */
+ command_info = NULL;
+
+ /* Free error message passed back to front-end, if any. */
+ free(audit_msg);
+ audit_msg = NULL;
+
+ /* sudoers_debug_deregister() calls sudo_debug_exit() for us. */
+ sudoers_debug_deregister();
+}
+
+/*
+ * The init_session function is called before executing the command
+ * and before uid/gid changes occur.
+ * Returns 1 on success, 0 on failure and -1 on error.
+ */
+static int
+sudoers_policy_init_session(struct passwd *pwd, char **user_env[],
+ const char **errstr)
+{
+ const struct sudoers_context *ctx = sudoers_get_context();
+ int ret;
+ debug_decl(sudoers_policy_init_session, SUDOERS_DEBUG_PLUGIN);
+
+ /* user_env is only specified for API version 1.2 and higher. */
+ if (sudo_version < SUDO_API_MKVERSION(1, 2))
+ user_env = NULL;
+
+ ret = sudo_auth_begin_session(ctx, pwd, user_env);
+
+ if (ret == 1) {
+ session_opened = true;
+ } else if (audit_msg != NULL) {
+ /* The audit functions set audit_msg on failure. */
+ if (sudo_version >= SUDO_API_MKVERSION(1, 15))
+ *errstr = audit_msg;
+ }
+ debug_return_int(ret);
+}
+
+static int
+sudoers_policy_check(int argc, char * const argv[], char *env_add[],
+ char **command_infop[], char **argv_out[], char **user_env_out[],
+ const char **errstr)
+{
+ const struct sudoers_context *ctx = sudoers_get_context();
+ unsigned int valid_flags = RUN_VALID_FLAGS;
+ unsigned int flags = MODE_RUN;
+ struct sudoers_exec_args exec_args;
+ int ret;
+ debug_decl(sudoers_policy_check, SUDOERS_DEBUG_PLUGIN);
+
+ if (ISSET(ctx->mode, MODE_EDIT)) {
+ valid_flags = EDIT_VALID_FLAGS;
+ flags = 0;
+ }
+ if (!sudoers_set_mode(flags, valid_flags)) {
+ sudo_warnx(U_("%s: invalid mode flags from sudo front end: 0x%x"),
+ __func__, ctx->mode);
+ debug_return_int(-1);
+ }
+
+ exec_args.argv = argv_out;
+ exec_args.envp = user_env_out;
+ exec_args.info = command_infop;
+
+ ret = sudoers_check_cmnd(argc, argv, env_add, &exec_args);
+#ifndef NO_LEAKS
+ if (ret == true && sudo_version >= SUDO_API_MKVERSION(1, 3)) {
+ /* Unset close function if we don't need it to avoid extra process. */
+ if (!iolog_enabled && !def_use_pty && !def_log_exit_status &&
+ SLIST_EMPTY(&def_log_servers) && !sudo_auth_needs_end_session())
+ sudoers_policy.close = NULL;
+ }
+#endif
+
+ /* The audit functions set audit_msg on failure. */
+ if (ret != 1 && audit_msg != NULL) {
+ if (sudo_version >= SUDO_API_MKVERSION(1, 15))
+ *errstr = audit_msg;
+ }
+ debug_return_int(ret);
+}
+
+static int
+sudoers_policy_validate(const char **errstr)
+{
+ const struct sudoers_context *ctx = sudoers_get_context();
+ int ret;
+ debug_decl(sudoers_policy_validate, SUDOERS_DEBUG_PLUGIN);
+
+ if (!sudoers_set_mode(MODE_VALIDATE, VALIDATE_VALID_FLAGS)) {
+ sudo_warnx(U_("%s: invalid mode flags from sudo front end: 0x%x"),
+ __func__, ctx->mode);
+ debug_return_int(-1);
+ }
+
+ ret = sudoers_validate_user();
+
+ /* The audit functions set audit_msg on failure. */
+ if (ret != 1 && audit_msg != NULL) {
+ if (sudo_version >= SUDO_API_MKVERSION(1, 15))
+ *errstr = audit_msg;
+ }
+ debug_return_int(ret);
+}
+
+static void
+sudoers_policy_invalidate(int unlinkit)
+{
+ const struct sudoers_context *ctx = sudoers_get_context();
+ debug_decl(sudoers_policy_invalidate, SUDOERS_DEBUG_PLUGIN);
+
+ if (!sudoers_set_mode(MODE_INVALIDATE, INVALIDATE_VALID_FLAGS)) {
+ sudo_warnx(U_("%s: invalid mode flags from sudo front end: 0x%x"),
+ __func__, ctx->mode);
+ } else {
+ timestamp_remove(ctx, unlinkit);
+ }
+
+ debug_return;
+}
+
+static int
+sudoers_policy_list(int argc, char * const argv[], int verbose,
+ const char *list_user, const char **errstr)
+{
+ const struct sudoers_context *ctx = sudoers_get_context();
+ int ret;
+ debug_decl(sudoers_policy_list, SUDOERS_DEBUG_PLUGIN);
+
+ if (!sudoers_set_mode(argc ? MODE_CHECK : MODE_LIST, LIST_VALID_FLAGS)) {
+ sudo_warnx(U_("%s: invalid mode flags from sudo front end: 0x%x"),
+ __func__, ctx->mode);
+ debug_return_int(-1);
+ }
+
+ ret = sudoers_list(argc, argv, list_user, verbose);
+
+ /* The audit functions set audit_msg on failure. */
+ if (ret != 1 && audit_msg != NULL) {
+ if (sudo_version >= SUDO_API_MKVERSION(1, 15))
+ *errstr = audit_msg;
+ }
+ debug_return_int(ret);
+}
+
+static int
+sudoers_policy_version(int verbose)
+{
+#ifdef HAVE_LDAP
+ const struct sudoers_context *ctx = sudoers_get_context();
+#endif
+ debug_decl(sudoers_policy_version, SUDOERS_DEBUG_PLUGIN);
+
+ sudo_printf(SUDO_CONV_INFO_MSG, _("Sudoers policy plugin version %s\n"),
+ PACKAGE_VERSION);
+ sudo_printf(SUDO_CONV_INFO_MSG, _("Sudoers file grammar version %d\n"),
+ SUDOERS_GRAMMAR_VERSION);
+
+ if (verbose) {
+ sudo_printf(SUDO_CONV_INFO_MSG, _("\nSudoers path: %s\n"), path_sudoers);
+#ifdef HAVE_LDAP
+# ifdef _PATH_NSSWITCH_CONF
+ sudo_printf(SUDO_CONV_INFO_MSG, _("nsswitch path: %s\n"), _PATH_NSSWITCH_CONF);
+# endif
+ if (ctx->settings.ldap_conf != NULL)
+ sudo_printf(SUDO_CONV_INFO_MSG, _("ldap.conf path: %s\n"), ctx->settings.ldap_conf);
+ if (ctx->settings.ldap_secret != NULL)
+ sudo_printf(SUDO_CONV_INFO_MSG, _("ldap.secret path: %s\n"), ctx->settings.ldap_secret);
+#endif
+ dump_auth_methods();
+ dump_defaults();
+ sudo_printf(SUDO_CONV_INFO_MSG, "\n");
+ if (interfaces_string != NULL) {
+ dump_interfaces(interfaces_string);
+ sudo_printf(SUDO_CONV_INFO_MSG, "\n");
+ }
+ }
+ debug_return_int(true);
+}
+
+static struct sudo_hook sudoers_hooks[] = {
+ { SUDO_HOOK_VERSION, SUDO_HOOK_SETENV, sudoers_hook_setenv, NULL },
+ { SUDO_HOOK_VERSION, SUDO_HOOK_UNSETENV, sudoers_hook_unsetenv, NULL },
+ { SUDO_HOOK_VERSION, SUDO_HOOK_GETENV, sudoers_hook_getenv, NULL },
+ { SUDO_HOOK_VERSION, SUDO_HOOK_PUTENV, sudoers_hook_putenv, NULL },
+ { 0, 0, NULL, NULL }
+};
+
+/*
+ * Register environment function hooks.
+ * Note that we have not registered sudoers with the debug subsystem yet.
+ */
+static void
+sudoers_policy_register_hooks(int version, int (*register_hook)(struct sudo_hook *hook))
+{
+ struct sudo_hook *hook;
+
+ for (hook = sudoers_hooks; hook->hook_fn != NULL; hook++) {
+ if (register_hook(hook) != 0) {
+ sudo_warn_nodebug(
+ U_("unable to register hook of type %d (version %d.%d)"),
+ hook->hook_type, SUDO_API_VERSION_GET_MAJOR(hook->hook_version),
+ SUDO_API_VERSION_GET_MINOR(hook->hook_version));
+ }
+ }
+}
+
+/*
+ * De-register environment function hooks.
+ */
+static void
+sudoers_policy_deregister_hooks(int version, int (*deregister_hook)(struct sudo_hook *hook))
+{
+ struct sudo_hook *hook;
+
+ for (hook = sudoers_hooks; hook->hook_fn != NULL; hook++) {
+ if (deregister_hook(hook) != 0) {
+ sudo_warn_nodebug(
+ U_("unable to deregister hook of type %d (version %d.%d)"),
+ hook->hook_type, SUDO_API_VERSION_GET_MAJOR(hook->hook_version),
+ SUDO_API_VERSION_GET_MINOR(hook->hook_version));
+ }
+ }
+}
+
+sudo_dso_public struct policy_plugin sudoers_policy = {
+ SUDO_POLICY_PLUGIN,
+ SUDO_API_VERSION,
+ sudoers_policy_open,
+ sudoers_policy_close,
+ sudoers_policy_version,
+ sudoers_policy_check,
+ sudoers_policy_list,
+ sudoers_policy_validate,
+ sudoers_policy_invalidate,
+ sudoers_policy_init_session,
+ sudoers_policy_register_hooks,
+ sudoers_policy_deregister_hooks,
+ NULL /* event_alloc() filled in by sudo */
+};
diff --git a/plugins/sudoers/prompt.c b/plugins/sudoers/prompt.c
new file mode 100644
index 0000000..50e9389
--- /dev/null
+++ b/plugins/sudoers/prompt.c
@@ -0,0 +1,171 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1993-1996,1998-2005, 2007-2015
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+
+#include <sudoers.h>
+
+/*
+ * Expand %h and %u escapes (if present) in the prompt and pass back
+ * the dynamically allocated result.
+ */
+char *
+expand_prompt(const struct sudoers_context *ctx,
+ const char *restrict old_prompt, const char *restrict auth_user)
+{
+ size_t len, n;
+ int subst;
+ const char *p;
+ char *np, *new_prompt;
+ debug_decl(expand_prompt, SUDOERS_DEBUG_AUTH);
+
+ /* How much space do we need to malloc for the prompt? */
+ subst = 0;
+ for (p = old_prompt, len = strlen(old_prompt); *p != '\0'; p++) {
+ if (p[0] =='%') {
+ switch (p[1]) {
+ case 'h':
+ p++;
+ len += strlen(ctx->user.shost) - 2;
+ subst = 1;
+ break;
+ case 'H':
+ p++;
+ len += strlen(ctx->user.host) - 2;
+ subst = 1;
+ break;
+ case 'p':
+ p++;
+ len += strlen(auth_user) - 2;
+ subst = 1;
+ break;
+ case 'u':
+ p++;
+ len += strlen(ctx->user.name) - 2;
+ subst = 1;
+ break;
+ case 'U':
+ p++;
+ len += strlen(ctx->runas.pw->pw_name) - 2;
+ subst = 1;
+ break;
+ case '%':
+ p++;
+ len--;
+ subst = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if ((new_prompt = malloc(++len)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_str(NULL);
+ }
+
+ if (subst) {
+ for (p = old_prompt, np = new_prompt; *p != '\0'; p++) {
+ if (p[0] =='%') {
+ switch (p[1]) {
+ case 'h':
+ p++;
+ n = strlcpy(np, ctx->user.shost, len);
+ if (n >= len)
+ goto oflow;
+ np += n;
+ len -= n;
+ continue;
+ case 'H':
+ p++;
+ n = strlcpy(np, ctx->user.host, len);
+ if (n >= len)
+ goto oflow;
+ np += n;
+ len -= n;
+ continue;
+ case 'p':
+ p++;
+ n = strlcpy(np, auth_user, len);
+ if (n >= len)
+ goto oflow;
+ np += n;
+ len -= n;
+ continue;
+ case 'u':
+ p++;
+ n = strlcpy(np, ctx->user.name, len);
+ if (n >= len)
+ goto oflow;
+ np += n;
+ len -= n;
+ continue;
+ case 'U':
+ p++;
+ n = strlcpy(np, ctx->runas.pw->pw_name, len);
+ if (n >= len)
+ goto oflow;
+ np += n;
+ len -= n;
+ continue;
+ case '%':
+ /* convert %% -> % */
+ p++;
+ break;
+ default:
+ /* no conversion */
+ break;
+ }
+ }
+ if (len < 2) /* len includes NUL */
+ goto oflow;
+ *np++ = *p;
+ len--;
+ }
+ if (len != 1)
+ goto oflow;
+ *np = '\0';
+ } else {
+ /* Nothing to expand. */
+ memcpy(new_prompt, old_prompt, len); /* len includes NUL */
+ }
+
+ debug_return_str(new_prompt);
+
+oflow:
+ /* We pre-allocate enough space, so this should never happen. */
+ free(new_prompt);
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ debug_return_str(NULL);
+}
diff --git a/plugins/sudoers/pwutil.c b/plugins/sudoers/pwutil.c
new file mode 100644
index 0000000..79033a6
--- /dev/null
+++ b/plugins/sudoers/pwutil.c
@@ -0,0 +1,1224 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2007-2018
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h> /* strcasecmp */
+#endif
+#ifdef HAVE_SETAUTHDB
+# include <usersec.h>
+#endif /* HAVE_SETAUTHDB */
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <sudoers.h>
+#include <redblack.h>
+#include <pwutil.h>
+
+/*
+ * The passwd and group caches.
+ */
+static struct rbtree *pwcache_byuid, *pwcache_byname;
+static struct rbtree *grcache_bygid, *grcache_byname;
+static struct rbtree *gidlist_cache, *grlist_cache;
+
+static int cmp_pwuid(const void *, const void *);
+static int cmp_pwnam(const void *, const void *);
+static int cmp_grgid(const void *, const void *);
+
+static int max_groups;
+
+/*
+ * Default functions for building cache items.
+ */
+static sudo_make_pwitem_t make_pwitem = sudo_make_pwitem;
+static sudo_make_gritem_t make_gritem = sudo_make_gritem;
+static sudo_make_gidlist_item_t make_gidlist_item = sudo_make_gidlist_item;
+static sudo_make_grlist_item_t make_grlist_item = sudo_make_grlist_item;
+static sudo_valid_shell_t valid_shell = sudo_valid_shell;
+
+#define cmp_grnam cmp_pwnam
+
+/*
+ * AIX has the concept of authentication registries (files, NIS, LDAP, etc).
+ * This allows you to have separate ID <-> name mappings based on which
+ * authentication registries the user was looked up in.
+ * We store the registry as part of the key and use it when matching.
+ */
+#ifdef HAVE_SETAUTHDB
+# define getauthregistry(u, r) aix_getauthregistry((u), (r))
+#else
+# define getauthregistry(u, r) ((r)[0] = '\0')
+#endif
+
+/*
+ * Change the default pwutil backend functions.
+ * The default functions query the password and group databases.
+ */
+void
+sudo_pwutil_set_backend(sudo_make_pwitem_t pwitem, sudo_make_gritem_t gritem,
+ sudo_make_gidlist_item_t gidlist_item, sudo_make_grlist_item_t grlist_item,
+ sudo_valid_shell_t check_shell)
+{
+ debug_decl(sudo_pwutil_set_backend, SUDOERS_DEBUG_NSS);
+
+ if (pwitem != NULL)
+ make_pwitem = pwitem;
+ if (gritem != NULL)
+ make_gritem = gritem;
+ if (gidlist_item != NULL)
+ make_gidlist_item = gidlist_item;
+ if (grlist_item != NULL)
+ make_grlist_item = grlist_item;
+ if (check_shell != NULL)
+ valid_shell = check_shell;
+
+ debug_return;
+}
+
+/* Get the max number of user groups if set, or 0 if not set. */
+int
+sudo_pwutil_get_max_groups(void)
+{
+ return max_groups;
+}
+
+/* Set the max number of user groups (negative values ignored). */
+void
+sudo_pwutil_set_max_groups(int n)
+{
+ max_groups = n > 0 ? n : 0;
+}
+
+/*
+ * Compare by user-ID.
+ * v1 is the key to find or data to insert, v2 is in-tree data.
+ */
+static int
+cmp_pwuid(const void *v1, const void *v2)
+{
+ const struct cache_item *ci1 = (const struct cache_item *) v1;
+ const struct cache_item *ci2 = (const struct cache_item *) v2;
+ if (ci1->k.uid == ci2->k.uid)
+ return strcmp(ci1->registry, ci2->registry);
+ if (ci1->k.uid < ci2->k.uid)
+ return -1;
+ return 1;
+}
+
+/*
+ * Compare by user/group name.
+ * v1 is the key to find or data to insert, v2 is in-tree data.
+ */
+static int
+cmp_pwnam(const void *v1, const void *v2)
+{
+ const struct cache_item *ci1 = (const struct cache_item *) v1;
+ const struct cache_item *ci2 = (const struct cache_item *) v2;
+ int ret = strcmp(ci1->k.name, ci2->k.name);
+ if (ret == 0)
+ ret = strcmp(ci1->registry, ci2->registry);
+ return ret;
+}
+
+/*
+ * Compare by user name, taking into account the source type.
+ * Need to differentiate between group-IDs received from the front-end
+ * (via getgroups()) and groups IDs queried from the group database.
+ * v1 is the key to find or data to insert, v2 is in-tree data.
+ */
+static int
+cmp_gidlist(const void *v1, const void *v2)
+{
+ const struct cache_item *ci1 = (const struct cache_item *) v1;
+ const struct cache_item *ci2 = (const struct cache_item *) v2;
+ int ret = strcmp(ci1->k.name, ci2->k.name);
+ if (ret == 0) {
+ if (ci1->type == ENTRY_TYPE_ANY || ci1->type == ci2->type)
+ return strcmp(ci1->registry, ci2->registry);
+ if (ci1->type < ci2->type)
+ return -1;
+ return 1;
+ }
+ return ret;
+}
+
+void
+sudo_pw_addref(struct passwd *pw)
+{
+ debug_decl(sudo_pw_addref, SUDOERS_DEBUG_NSS);
+ ptr_to_item(pw)->refcnt++;
+ debug_return;
+}
+
+static void
+sudo_pw_delref_item(void *v)
+{
+ struct cache_item *item = v;
+ debug_decl(sudo_pw_delref_item, SUDOERS_DEBUG_NSS);
+
+ if (--item->refcnt == 0)
+ free(item);
+
+ debug_return;
+}
+
+void
+sudo_pw_delref(struct passwd *pw)
+{
+ debug_decl(sudo_pw_delref, SUDOERS_DEBUG_NSS);
+ sudo_pw_delref_item(ptr_to_item(pw));
+ debug_return;
+}
+
+/*
+ * Get a password entry by uid and allocate space for it.
+ */
+struct passwd *
+sudo_getpwuid(uid_t uid)
+{
+ struct cache_item key, *item;
+ struct rbnode *node;
+ debug_decl(sudo_getpwuid, SUDOERS_DEBUG_NSS);
+
+ if (pwcache_byuid == NULL) {
+ pwcache_byuid = rbcreate(cmp_pwuid);
+ if (pwcache_byuid == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_ptr(NULL);
+ }
+ }
+
+ key.k.uid = uid;
+ getauthregistry(IDtouser(uid), key.registry);
+ if ((node = rbfind(pwcache_byuid, &key)) != NULL) {
+ item = node->data;
+ goto done;
+ }
+ /*
+ * Cache passwd db entry if it exists or a negative response if not.
+ */
+#ifdef HAVE_SETAUTHDB
+ aix_setauthdb(IDtouser(uid), key.registry);
+#endif
+ item = make_pwitem(uid, NULL);
+#ifdef HAVE_SETAUTHDB
+ aix_restoreauthdb();
+#endif
+ if (item == NULL) {
+ if (errno != ENOENT || (item = calloc(1, sizeof(*item))) == NULL) {
+ sudo_warn(U_("unable to cache uid %u"), (unsigned int) uid);
+ /* cppcheck-suppress memleak */
+ debug_return_ptr(NULL);
+ }
+ item->refcnt = 1;
+ item->k.uid = uid;
+ /* item->d.pw = NULL; */
+ }
+ strlcpy(item->registry, key.registry, sizeof(item->registry));
+ switch (rbinsert(pwcache_byuid, item, NULL)) {
+ case 1:
+ /* should not happen */
+ sudo_warnx(U_("unable to cache uid %u, already exists"),
+ (unsigned int) uid);
+ item->refcnt = 0;
+ break;
+ case -1:
+ /* can't cache item, just return it */
+ sudo_warn(U_("unable to cache uid %u"), (unsigned int) uid);
+ item->refcnt = 0;
+ break;
+ }
+done:
+ if (item->refcnt != 0) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s: uid %u [%s] -> user %s [%s] (%s)", __func__,
+ (unsigned int)uid, key.registry,
+ item->d.pw ? item->d.pw->pw_name : "unknown",
+ item->registry, node ? "cache hit" : "cached");
+ }
+ if (item->d.pw != NULL)
+ item->refcnt++;
+ debug_return_ptr(item->d.pw);
+}
+
+/*
+ * Get a password entry by name and allocate space for it.
+ */
+struct passwd *
+sudo_getpwnam(const char *name)
+{
+ struct cache_item key, *item;
+ struct rbnode *node;
+ debug_decl(sudo_getpwnam, SUDOERS_DEBUG_NSS);
+
+ if (pwcache_byname == NULL) {
+ pwcache_byname = rbcreate(cmp_pwnam);
+ if (pwcache_byname == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_ptr(NULL);
+ }
+ }
+
+ key.k.name = (char *) name;
+ getauthregistry((char *) name, key.registry);
+ if ((node = rbfind(pwcache_byname, &key)) != NULL) {
+ item = node->data;
+ goto done;
+ }
+ /*
+ * Cache passwd db entry if it exists or a negative response if not.
+ */
+#ifdef HAVE_SETAUTHDB
+ aix_setauthdb((char *) name, key.registry);
+#endif
+ item = make_pwitem((uid_t)-1, name);
+#ifdef HAVE_SETAUTHDB
+ aix_restoreauthdb();
+#endif
+ if (item == NULL) {
+ const size_t len = strlen(name) + 1;
+ if (errno != ENOENT || (item = calloc(1, sizeof(*item) + len)) == NULL) {
+ sudo_warn(U_("unable to cache user %s"), name);
+ /* cppcheck-suppress memleak */
+ debug_return_ptr(NULL);
+ }
+ item->refcnt = 1;
+ item->k.name = (char *) item + sizeof(*item);
+ memcpy(item->k.name, name, len);
+ /* item->d.pw = NULL; */
+ }
+ strlcpy(item->registry, key.registry, sizeof(item->registry));
+ switch (rbinsert(pwcache_byname, item, NULL)) {
+ case 1:
+ /* should not happen */
+ sudo_warnx(U_("unable to cache user %s, already exists"), name);
+ item->refcnt = 0;
+ break;
+ case -1:
+ /* can't cache item, just return it */
+ sudo_warn(U_("unable to cache user %s"), name);
+ item->refcnt = 0;
+ break;
+ }
+done:
+ if (item->refcnt != 0) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s: user %s [%s] -> uid %d [%s] (%s)", __func__, name,
+ key.registry, item->d.pw ? (int)item->d.pw->pw_uid : -1,
+ item->registry, node ? "cache hit" : "cached");
+ }
+ if (item->d.pw != NULL)
+ item->refcnt++;
+ debug_return_ptr(item->d.pw);
+}
+
+/*
+ * Take a user, uid, gid, home and shell and return a faked up passwd struct.
+ * If home or shell are NULL default values will be used.
+ */
+struct passwd *
+sudo_mkpwent(const char *user, uid_t uid, gid_t gid, const char *home,
+ const char *shell)
+{
+ struct cache_item_pw *pwitem;
+ struct cache_item *item;
+ struct passwd *pw;
+ size_t len, name_len, home_len, shell_len;
+ unsigned int i;
+ debug_decl(sudo_mkpwent, SUDOERS_DEBUG_NSS);
+
+ if (pwcache_byuid == NULL)
+ pwcache_byuid = rbcreate(cmp_pwuid);
+ if (pwcache_byname == NULL)
+ pwcache_byname = rbcreate(cmp_pwnam);
+ if (pwcache_byuid == NULL || pwcache_byname == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_ptr(NULL);
+ }
+
+ /* Optional arguments. */
+ if (home == NULL)
+ home = "/";
+ if (shell == NULL)
+ shell = _PATH_BSHELL;
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s: creating and caching passwd struct for %s:%u:%u:%s:%s", __func__,
+ user, (unsigned int)uid, (unsigned int)gid, home, shell);
+
+ name_len = strlen(user);
+ home_len = strlen(home);
+ shell_len = strlen(shell);
+ len = sizeof(*pwitem) + name_len + 1 /* pw_name */ +
+ sizeof("*") /* pw_passwd */ + sizeof("") /* pw_gecos */ +
+ home_len + 1 /* pw_dir */ + shell_len + 1 /* pw_shell */;
+
+ for (i = 0; i < 2; i++) {
+ struct rbtree *pwcache;
+ struct rbnode *node;
+
+ pwitem = calloc(1, len);
+ if (pwitem == NULL) {
+ sudo_warn(U_("unable to cache user %s"), user);
+ debug_return_ptr(NULL);
+ }
+ pw = &pwitem->pw;
+ pw->pw_uid = uid;
+ pw->pw_gid = gid;
+ pw->pw_name = (char *)(pwitem + 1);
+ memcpy(pw->pw_name, user, name_len + 1);
+ pw->pw_passwd = pw->pw_name + name_len + 1;
+ memcpy(pw->pw_passwd, "*", 2);
+ pw->pw_gecos = pw->pw_passwd + 2;
+ pw->pw_gecos[0] = '\0';
+ pw->pw_dir = pw->pw_gecos + 1;
+ memcpy(pw->pw_dir, home, home_len + 1);
+ pw->pw_shell = pw->pw_dir + home_len + 1;
+ memcpy(pw->pw_shell, shell, shell_len + 1);
+
+ item = &pwitem->cache;
+ item->refcnt = 1;
+ item->d.pw = pw;
+ if (i == 0) {
+ /* Store by uid. */
+ item->k.uid = pw->pw_uid;
+ pwcache = pwcache_byuid;
+ } else {
+ /* Store by name. */
+ item->k.name = pw->pw_name;
+ pwcache = pwcache_byname;
+ }
+ getauthregistry(NULL, item->registry);
+ switch (rbinsert(pwcache, item, &node)) {
+ case 1:
+ /* Already exists. */
+ item = node->data;
+ if (item->d.pw == NULL) {
+ /* Negative cache entry, replace with ours. */
+ sudo_pw_delref_item(item);
+ item = node->data = &pwitem->cache;
+ } else {
+ /* Good entry, discard our fake one. */
+ free(pwitem);
+ }
+ break;
+ case -1:
+ /* can't cache item, just return it */
+ sudo_warn(U_("unable to cache user %s"), user);
+ item->refcnt = 0;
+ break;
+ }
+ }
+ item->refcnt++;
+ debug_return_ptr(item->d.pw);
+}
+
+/*
+ * Take a uid in string form "#123" and return a faked up passwd struct.
+ */
+struct passwd *
+sudo_fakepwnam(const char *user, gid_t gid)
+{
+ const char *errstr;
+ uid_t uid;
+ debug_decl(sudo_fakepwnam, SUDOERS_DEBUG_NSS);
+
+ uid = (uid_t) sudo_strtoid(user + 1, &errstr);
+ if (errstr != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_DIAG|SUDO_DEBUG_LINENO,
+ "uid %s %s", user, errstr);
+ debug_return_ptr(NULL);
+ }
+ debug_return_ptr(sudo_mkpwent(user, uid, gid, NULL, NULL));
+}
+
+void
+sudo_freepwcache(void)
+{
+ debug_decl(sudo_freepwcache, SUDOERS_DEBUG_NSS);
+
+ if (pwcache_byuid != NULL) {
+ rbdestroy(pwcache_byuid, sudo_pw_delref_item);
+ pwcache_byuid = NULL;
+ }
+ if (pwcache_byname != NULL) {
+ rbdestroy(pwcache_byname, sudo_pw_delref_item);
+ pwcache_byname = NULL;
+ }
+
+ debug_return;
+}
+
+/*
+ * Compare by group-ID.
+ * v1 is the key to find or data to insert, v2 is in-tree data.
+ */
+static int
+cmp_grgid(const void *v1, const void *v2)
+{
+ const struct cache_item *ci1 = (const struct cache_item *) v1;
+ const struct cache_item *ci2 = (const struct cache_item *) v2;
+ if (ci1->k.gid == ci2->k.gid)
+ return strcmp(ci1->registry, ci2->registry);
+ if (ci1->k.gid < ci2->k.gid)
+ return -1;
+ return 1;
+}
+
+void
+sudo_gr_addref(struct group *gr)
+{
+ debug_decl(sudo_gr_addref, SUDOERS_DEBUG_NSS);
+ ptr_to_item(gr)->refcnt++;
+ debug_return;
+}
+
+static void
+sudo_gr_delref_item(void *v)
+{
+ struct cache_item *item = v;
+ debug_decl(sudo_gr_delref_item, SUDOERS_DEBUG_NSS);
+
+ if (--item->refcnt == 0)
+ free(item);
+
+ debug_return;
+}
+
+void
+sudo_gr_delref(struct group *gr)
+{
+ debug_decl(sudo_gr_delref, SUDOERS_DEBUG_NSS);
+ sudo_gr_delref_item(ptr_to_item(gr));
+ debug_return;
+}
+
+/*
+ * Get a group entry by gid and allocate space for it.
+ */
+struct group *
+sudo_getgrgid(gid_t gid)
+{
+ struct cache_item key, *item;
+ struct rbnode *node;
+ debug_decl(sudo_getgrgid, SUDOERS_DEBUG_NSS);
+
+ if (grcache_bygid == NULL) {
+ grcache_bygid = rbcreate(cmp_grgid);
+ if (grcache_bygid == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_ptr(NULL);
+ }
+ }
+
+ key.k.gid = gid;
+ getauthregistry(NULL, key.registry);
+ if ((node = rbfind(grcache_bygid, &key)) != NULL) {
+ item = node->data;
+ goto done;
+ }
+ /*
+ * Cache group db entry if it exists or a negative response if not.
+ */
+ item = make_gritem(gid, NULL);
+ if (item == NULL) {
+ if (errno != ENOENT || (item = calloc(1, sizeof(*item))) == NULL) {
+ sudo_warn(U_("unable to cache gid %u"), (unsigned int) gid);
+ /* cppcheck-suppress memleak */
+ debug_return_ptr(NULL);
+ }
+ item->refcnt = 1;
+ item->k.gid = gid;
+ /* item->d.gr = NULL; */
+ }
+ strlcpy(item->registry, key.registry, sizeof(item->registry));
+ switch (rbinsert(grcache_bygid, item, NULL)) {
+ case 1:
+ /* should not happen */
+ sudo_warnx(U_("unable to cache gid %u, already exists"),
+ (unsigned int) gid);
+ item->refcnt = 0;
+ break;
+ case -1:
+ /* can't cache item, just return it */
+ sudo_warn(U_("unable to cache gid %u"), (unsigned int) gid);
+ item->refcnt = 0;
+ break;
+ }
+done:
+ if (item->refcnt != 0) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s: gid %u [%s] -> group %s [%s] (%s)", __func__,
+ (unsigned int)gid, key.registry,
+ item->d.gr ? item->d.gr->gr_name : "unknown",
+ item->registry, node ? "cache hit" : "cached");
+ }
+ if (item->d.gr != NULL)
+ item->refcnt++;
+ debug_return_ptr(item->d.gr);
+}
+
+/*
+ * Get a group entry by name and allocate space for it.
+ */
+struct group *
+sudo_getgrnam(const char *name)
+{
+ struct cache_item key, *item;
+ struct rbnode *node;
+ debug_decl(sudo_getgrnam, SUDOERS_DEBUG_NSS);
+
+ if (grcache_byname == NULL) {
+ grcache_byname = rbcreate(cmp_grnam);
+ if (grcache_byname == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_ptr(NULL);
+ }
+ }
+
+ key.k.name = (char *) name;
+ getauthregistry(NULL, key.registry);
+ if ((node = rbfind(grcache_byname, &key)) != NULL) {
+ item = node->data;
+ goto done;
+ }
+ /*
+ * Cache group db entry if it exists or a negative response if not.
+ */
+ item = make_gritem((gid_t)-1, name);
+ if (item == NULL) {
+ const size_t len = strlen(name) + 1;
+ if (errno != ENOENT || (item = calloc(1, sizeof(*item) + len)) == NULL) {
+ sudo_warn(U_("unable to cache group %s"), name);
+ /* cppcheck-suppress memleak */
+ debug_return_ptr(NULL);
+ }
+ item->refcnt = 1;
+ item->k.name = (char *) item + sizeof(*item);
+ memcpy(item->k.name, name, len);
+ /* item->d.gr = NULL; */
+ }
+ strlcpy(item->registry, key.registry, sizeof(item->registry));
+ switch (rbinsert(grcache_byname, item, NULL)) {
+ case 1:
+ /* should not happen */
+ sudo_warnx(U_("unable to cache group %s, already exists"), name);
+ item->refcnt = 0;
+ break;
+ case -1:
+ /* can't cache item, just return it */
+ sudo_warn(U_("unable to cache group %s"), name);
+ item->refcnt = 0;
+ break;
+ }
+done:
+ if (item->refcnt != 0) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s: group %s [%s] -> gid %d [%s] (%s)", __func__, name,
+ key.registry, item->d.gr ? (int)item->d.gr->gr_gid : -1,
+ item->registry, node ? "cache hit" : "cached");
+ }
+ if (item->d.gr != NULL)
+ item->refcnt++;
+ debug_return_ptr(item->d.gr);
+}
+
+/*
+ * Take a group name, ID, members and return a faked up group struct.
+ */
+struct group *
+sudo_mkgrent(const char *group, gid_t gid, ...)
+{
+ struct cache_item_gr *gritem;
+ struct cache_item *item;
+ struct group *gr;
+ size_t nmem, nsize, total;
+ char *cp, *mem;
+ va_list ap;
+ unsigned int i;
+ debug_decl(sudo_mkgrent, SUDOERS_DEBUG_NSS);
+
+ if (grcache_bygid == NULL)
+ grcache_bygid = rbcreate(cmp_grgid);
+ if (grcache_byname == NULL)
+ grcache_byname = rbcreate(cmp_grnam);
+ if (grcache_bygid == NULL || grcache_byname == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_ptr(NULL);
+ }
+
+ /* Allocate in one big chunk for easy freeing. */
+ nsize = strlen(group) + 1;
+ total = sizeof(*gritem) + nsize;
+ va_start(ap, gid);
+ for (nmem = 1; (mem = va_arg(ap, char *)) != NULL; nmem++) {
+ total += strlen(mem) + 1;
+ }
+ va_end(ap);
+ total += sizeof(char *) * nmem;
+
+ for (i = 0; i < 2; i++) {
+ struct rbtree *grcache;
+ struct rbnode *node;
+
+ /*
+ * Fill in group contents and make strings relative to space
+ * at the end of the buffer. Note that gr_mem must come
+ * immediately after struct group to guarantee proper alignment.
+ */
+ gritem = calloc(1, total);
+ if (gritem == NULL) {
+ sudo_warn(U_("unable to cache group %s"), group);
+ debug_return_ptr(NULL);
+ }
+ gr = &gritem->gr;
+ gr->gr_gid = gid;
+ gr->gr_passwd = (char *)"*";
+ cp = (char *)(gritem + 1);
+ gr->gr_mem = (char **)cp;
+ cp += sizeof(char *) * nmem;
+ va_start(ap, gid);
+ for (nmem = 0; (mem = va_arg(ap, char *)) != NULL; nmem++) {
+ size_t len = strlen(mem) + 1;
+ memcpy(cp, mem, len);
+ gr->gr_mem[nmem] = cp;
+ cp += len;
+ }
+ va_end(ap);
+ gr->gr_mem[nmem] = NULL;
+ gr->gr_name = cp;
+ memcpy(gr->gr_name, group, nsize);
+
+ item = &gritem->cache;
+ item->refcnt = 1;
+ item->d.gr = gr;
+ if (i == 0) {
+ /* Store by gid if it doesn't already exist. */
+ item->k.gid = gr->gr_gid;
+ grcache = grcache_bygid;
+ } else {
+ /* Store by name, overwriting cached version. */
+ gritem->cache.k.name = gr->gr_name;
+ grcache = grcache_byname;
+ }
+ getauthregistry(NULL, item->registry);
+ switch (rbinsert(grcache, item, &node)) {
+ case 1:
+ /* Already exists. */
+ item = node->data;
+ if (item->d.gr == NULL) {
+ /* Negative cache entry, replace with ours. */
+ sudo_gr_delref_item(item);
+ item = node->data = &gritem->cache;
+ } else {
+ /* Good entry, discard our fake one. */
+ free(gritem);
+ }
+ break;
+ case -1:
+ /* can't cache item, just return it */
+ sudo_warn(U_("unable to cache group %s"), group);
+ item->refcnt = 0;
+ break;
+ }
+ }
+ if (item->d.gr != NULL)
+ item->refcnt++;
+ debug_return_ptr(item->d.gr);
+}
+
+/*
+ * Take a gid in string form "#123" and return a faked up group struct.
+ */
+struct group *
+sudo_fakegrnam(const char *group)
+{
+ const char *errstr;
+ gid_t gid;
+ debug_decl(sudo_fakegrnam, SUDOERS_DEBUG_NSS);
+
+ gid = (gid_t) sudo_strtoid(group + 1, &errstr);
+ if (errstr != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_DIAG|SUDO_DEBUG_LINENO,
+ "gid %s %s", group, errstr);
+ debug_return_ptr(NULL);
+ }
+
+ debug_return_ptr(sudo_mkgrent(group, gid, (char *)NULL));
+}
+
+void
+sudo_gidlist_addref(struct gid_list *gidlist)
+{
+ debug_decl(sudo_gidlist_addref, SUDOERS_DEBUG_NSS);
+ ptr_to_item(gidlist)->refcnt++;
+ debug_return;
+}
+
+static void
+sudo_gidlist_delref_item(void *v)
+{
+ struct cache_item *item = v;
+ debug_decl(sudo_gidlist_delref_item, SUDOERS_DEBUG_NSS);
+
+ if (--item->refcnt == 0)
+ free(item);
+
+ debug_return;
+}
+
+void
+sudo_gidlist_delref(struct gid_list *gidlist)
+{
+ debug_decl(sudo_gidlist_delref, SUDOERS_DEBUG_NSS);
+ sudo_gidlist_delref_item(ptr_to_item(gidlist));
+ debug_return;
+}
+
+void
+sudo_grlist_addref(struct group_list *grlist)
+{
+ debug_decl(sudo_grlist_addref, SUDOERS_DEBUG_NSS);
+ ptr_to_item(grlist)->refcnt++;
+ debug_return;
+}
+
+static void
+sudo_grlist_delref_item(void *v)
+{
+ struct cache_item *item = v;
+ debug_decl(sudo_grlist_delref_item, SUDOERS_DEBUG_NSS);
+
+ if (--item->refcnt == 0)
+ free(item);
+
+ debug_return;
+}
+
+void
+sudo_grlist_delref(struct group_list *grlist)
+{
+ debug_decl(sudo_grlist_delref, SUDOERS_DEBUG_NSS);
+ sudo_grlist_delref_item(ptr_to_item(grlist));
+ debug_return;
+}
+
+void
+sudo_freegrcache(void)
+{
+ debug_decl(sudo_freegrcache, SUDOERS_DEBUG_NSS);
+
+ if (grcache_bygid != NULL) {
+ rbdestroy(grcache_bygid, sudo_gr_delref_item);
+ grcache_bygid = NULL;
+ }
+ if (grcache_byname != NULL) {
+ rbdestroy(grcache_byname, sudo_gr_delref_item);
+ grcache_byname = NULL;
+ }
+ if (grlist_cache != NULL) {
+ rbdestroy(grlist_cache, sudo_grlist_delref_item);
+ grlist_cache = NULL;
+ }
+ if (gidlist_cache != NULL) {
+ rbdestroy(gidlist_cache, sudo_gidlist_delref_item);
+ gidlist_cache = NULL;
+ }
+
+ debug_return;
+}
+
+struct group_list *
+sudo_get_grlist(const struct passwd *pw)
+{
+ struct cache_item key, *item;
+ struct rbnode *node;
+ debug_decl(sudo_get_grlist, SUDOERS_DEBUG_NSS);
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: looking up group names for %s",
+ __func__, pw->pw_name);
+
+ if (grlist_cache == NULL) {
+ grlist_cache = rbcreate(cmp_pwnam);
+ if (grlist_cache == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_ptr(NULL);
+ }
+ }
+
+ key.k.name = pw->pw_name;
+ getauthregistry(pw->pw_name, key.registry);
+ if ((node = rbfind(grlist_cache, &key)) != NULL) {
+ item = node->data;
+ goto done;
+ }
+ /*
+ * Cache group db entry if it exists or a negative response if not.
+ */
+ item = make_grlist_item(pw, NULL);
+ if (item == NULL) {
+ /* Out of memory? */
+ debug_return_ptr(NULL);
+ }
+ strlcpy(item->registry, key.registry, sizeof(item->registry));
+ switch (rbinsert(grlist_cache, item, NULL)) {
+ case 1:
+ /* should not happen */
+ sudo_warnx(U_("unable to cache group list for %s, already exists"),
+ pw->pw_name);
+ item->refcnt = 0;
+ break;
+ case -1:
+ /* can't cache item, just return it */
+ sudo_warn(U_("unable to cache group list for %s"), pw->pw_name);
+ item->refcnt = 0;
+ break;
+ }
+ if (item->d.grlist != NULL) {
+ int i;
+ for (i = 0; i < item->d.grlist->ngroups; i++) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s: user %s is a member of group %s", __func__,
+ pw->pw_name, item->d.grlist->groups[i]);
+ }
+ }
+done:
+ if (item->d.grlist != NULL)
+ item->refcnt++;
+ debug_return_ptr(item->d.grlist);
+}
+
+static void
+sudo_debug_group_list(const char *user, char * const *groups,
+ unsigned int level)
+{
+ size_t i, len = 0;
+ debug_decl(sudo_debug_group_list, SUDOERS_DEBUG_NSS);
+
+ if (groups == NULL || !sudo_debug_needed(level))
+ debug_return;
+
+ for (i = 0; groups[i] != NULL; i++) {
+ len += strlen(groups[i]) + 1;
+ }
+ if (len != 0) {
+ char *groupstr = malloc(len);
+ if (groupstr != NULL) {
+ char *cp = groupstr;
+ for (i = 0; groups[i] != NULL; i++) {
+ size_t n = (size_t)snprintf(cp, len, "%s%s", i ? "," : "",
+ groups[i]);
+ if (n >= len)
+ break;
+ cp += n;
+ len -= n;
+ }
+ sudo_debug_printf(level, "%s: %s", user, groupstr);
+ free(groupstr);
+ }
+ }
+ debug_return;
+}
+
+int
+sudo_set_grlist(struct passwd *pw, char * const *groups)
+{
+ struct cache_item key, *item;
+ debug_decl(sudo_set_grlist, SUDOERS_DEBUG_NSS);
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: setting group names for %s",
+ __func__, pw->pw_name);
+
+ sudo_debug_group_list(pw->pw_name, groups, SUDO_DEBUG_DEBUG);
+
+ if (grlist_cache == NULL) {
+ grlist_cache = rbcreate(cmp_pwnam);
+ if (grlist_cache == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(-1);
+ }
+ }
+
+ /*
+ * Cache group db entry if it doesn't already exist
+ */
+ key.k.name = pw->pw_name;
+ getauthregistry(pw->pw_name, key.registry);
+ if (rbfind(grlist_cache, &key) == NULL) {
+ if ((item = make_grlist_item(pw, groups)) == NULL) {
+ sudo_warnx(U_("unable to parse groups for %s"), pw->pw_name);
+ debug_return_int(-1);
+ }
+ strlcpy(item->registry, key.registry, sizeof(item->registry));
+ switch (rbinsert(grlist_cache, item, NULL)) {
+ case 1:
+ sudo_warnx(U_("unable to cache group list for %s, already exists"),
+ pw->pw_name);
+ sudo_grlist_delref_item(item);
+ break;
+ case -1:
+ sudo_warn(U_("unable to cache group list for %s"), pw->pw_name);
+ sudo_grlist_delref_item(item);
+ debug_return_int(-1);
+ }
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "groups for user %s are already cached", pw->pw_name);
+ }
+
+ debug_return_int(0);
+}
+
+struct gid_list *
+sudo_get_gidlist(const struct passwd *pw, unsigned int type)
+{
+ struct cache_item key, *item;
+ struct rbnode *node;
+ debug_decl(sudo_get_gidlist, SUDOERS_DEBUG_NSS);
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: looking up group-IDs for %s",
+ __func__, pw->pw_name);
+
+ if (gidlist_cache == NULL) {
+ gidlist_cache = rbcreate(cmp_gidlist);
+ if (gidlist_cache == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_ptr(NULL);
+ }
+ }
+
+ key.k.name = pw->pw_name;
+ key.type = type;
+ getauthregistry(pw->pw_name, key.registry);
+ if ((node = rbfind(gidlist_cache, &key)) != NULL) {
+ item = node->data;
+ goto done;
+ }
+ /*
+ * Cache group db entry if it exists or a negative response if not.
+ */
+ item = make_gidlist_item(pw, -1, NULL, NULL, type);
+ if (item == NULL) {
+ /* Out of memory? */
+ debug_return_ptr(NULL);
+ }
+ strlcpy(item->registry, key.registry, sizeof(item->registry));
+ switch (rbinsert(gidlist_cache, item, NULL)) {
+ case 1:
+ /* should not happen */
+ sudo_warnx(U_("unable to cache group list for %s, already exists"),
+ pw->pw_name);
+ item->refcnt = 0;
+ break;
+ case -1:
+ /* can't cache item, just return it */
+ sudo_warn(U_("unable to cache group list for %s"), pw->pw_name);
+ item->refcnt = 0;
+ break;
+ }
+ if (item->d.gidlist != NULL) {
+ int i;
+ for (i = 0; i < item->d.gidlist->ngids; i++) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s: user %s has supplementary gid %u", __func__,
+ pw->pw_name, (unsigned int)item->d.gidlist->gids[i]);
+ }
+ }
+done:
+ if (item->d.gidlist != NULL)
+ item->refcnt++;
+ debug_return_ptr(item->d.gidlist);
+}
+
+int
+sudo_set_gidlist(struct passwd *pw, int ngids, GETGROUPS_T *gids,
+ char * const *gidstrs, unsigned int type)
+{
+ struct cache_item key, *item;
+ debug_decl(sudo_set_gidlist, SUDOERS_DEBUG_NSS);
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: setting group-IDs for %s",
+ __func__, pw->pw_name);
+
+ /* XXX - ngids/gids too */
+ sudo_debug_group_list(pw->pw_name, gidstrs, SUDO_DEBUG_DEBUG);
+
+ if (gidlist_cache == NULL) {
+ gidlist_cache = rbcreate(cmp_gidlist);
+ if (gidlist_cache == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(-1);
+ }
+ }
+
+ /*
+ * Cache group db entry if it doesn't already exist
+ */
+ key.k.name = pw->pw_name;
+ key.type = type;
+ getauthregistry(pw->pw_name, key.registry);
+ if (rbfind(gidlist_cache, &key) == NULL) {
+ if ((item = make_gidlist_item(pw, ngids, gids, gidstrs, type)) == NULL) {
+ sudo_warnx(U_("unable to parse gids for %s"), pw->pw_name);
+ debug_return_int(-1);
+ }
+ strlcpy(item->registry, key.registry, sizeof(item->registry));
+ switch (rbinsert(gidlist_cache, item, NULL)) {
+ case 1:
+ sudo_warnx(U_("unable to cache group list for %s, already exists"),
+ pw->pw_name);
+ sudo_gidlist_delref_item(item);
+ break;
+ case -1:
+ sudo_warn(U_("unable to cache group list for %s"), pw->pw_name);
+ sudo_gidlist_delref_item(item);
+ debug_return_int(-1);
+ }
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "gids for user %s are already cached", pw->pw_name);
+ }
+
+ debug_return_int(0);
+}
+
+bool
+user_in_group(const struct passwd *pw, const char *group)
+{
+ struct group_list *grlist = NULL;
+ struct gid_list *gidlist = NULL;
+ struct group *grp = NULL;
+ bool matched = false;
+ int i;
+ debug_decl(user_in_group, SUDOERS_DEBUG_NSS);
+
+ /*
+ * If it could be a sudo-style group-ID check gids first.
+ */
+ if (group[0] == '#') {
+ const char *errstr;
+ gid_t gid = (gid_t) sudo_strtoid(group + 1, &errstr);
+ if (errstr != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_DIAG|SUDO_DEBUG_LINENO,
+ "gid %s %s", group, errstr);
+ } else {
+ if (gid == pw->pw_gid) {
+ matched = true;
+ goto done;
+ }
+ if ((gidlist = sudo_get_gidlist(pw, ENTRY_TYPE_ANY)) != NULL) {
+ for (i = 0; i < gidlist->ngids; i++) {
+ if (gid == gidlist->gids[i]) {
+ matched = true;
+ goto done;
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Next match the group name. By default, sudoers resolves all the user's
+ * group-IDs to names and matches by name. If match_group_by_gid is
+ * set, each group is sudoers is resolved and matching is by group-ID.
+ */
+ if (def_match_group_by_gid) {
+ gid_t gid;
+
+ /* Look up the ID of the group in sudoers. */
+ if ((grp = sudo_getgrnam(group)) == NULL)
+ goto done;
+ gid = grp->gr_gid;
+
+ /* Check against user's primary (passwd file) group-ID. */
+ if (gid == pw->pw_gid) {
+ matched = true;
+ goto done;
+ }
+
+ /* Check the supplementary group vector. */
+ if (gidlist == NULL) {
+ if ((gidlist = sudo_get_gidlist(pw, ENTRY_TYPE_ANY)) != NULL) {
+ for (i = 0; i < gidlist->ngids; i++) {
+ if (gid == gidlist->gids[i]) {
+ matched = true;
+ goto done;
+ }
+ }
+ }
+ }
+ } else if ((grlist = sudo_get_grlist(pw)) != NULL) {
+ int (*compare)(const char *, const char *);
+ if (def_case_insensitive_group)
+ compare = strcasecmp;
+ else
+ compare = strcmp;
+
+ /* Check the user's group vector, which includes the primary group. */
+ for (i = 0; i < grlist->ngroups; i++) {
+ if (compare(group, grlist->groups[i]) == 0) {
+ matched = true;
+ goto done;
+ }
+ }
+ }
+
+done:
+ if (grp != NULL)
+ sudo_gr_delref(grp);
+ if (grlist != NULL)
+ sudo_grlist_delref(grlist);
+ if (gidlist != NULL)
+ sudo_gidlist_delref(gidlist);
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: user %s %sin group %s",
+ __func__, pw->pw_name, matched ? "" : "NOT ", group);
+ debug_return_bool(matched);
+}
+
+/*
+ * Returns true if the user's shell is considered to be valid.
+ */
+bool
+user_shell_valid(const struct passwd *pw)
+{
+ debug_decl(user_shell_valid, SUDOERS_DEBUG_NSS);
+
+ if (!def_runas_check_shell)
+ debug_return_bool(true);
+
+ debug_return_bool(valid_shell(pw->pw_shell));
+}
diff --git a/plugins/sudoers/pwutil.h b/plugins/sudoers/pwutil.h
new file mode 100644
index 0000000..ac80580
--- /dev/null
+++ b/plugins/sudoers/pwutil.h
@@ -0,0 +1,78 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2013, 2015-2017 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_PWUTIL_H
+#define SUDOERS_PWUTIL_H
+
+#define ptr_to_item(p) ((struct cache_item *)((char *)p - offsetof(struct cache_item_##p, p)))
+
+/*
+ * Generic cache element.
+ */
+struct cache_item {
+ unsigned int refcnt;
+ unsigned int type; /* only used for gidlist */
+ char registry[16]; /* AIX-specific, empty otherwise */
+ /* key */
+ union {
+ uid_t uid;
+ gid_t gid;
+ char *name;
+ } k;
+ /* datum */
+ union {
+ struct passwd *pw;
+ struct group *gr;
+ struct group_list *grlist;
+ struct gid_list *gidlist;
+ } d;
+};
+
+/*
+ * Container structs to simpify size and offset calculations and guarantee
+ * proper alignment of struct passwd, group, gid_list and group_list.
+ */
+struct cache_item_pw {
+ struct cache_item cache;
+ struct passwd pw;
+};
+
+struct cache_item_gr {
+ struct cache_item cache;
+ struct group gr;
+};
+
+struct cache_item_grlist {
+ struct cache_item cache;
+ struct group_list grlist;
+ /* actually bigger */
+};
+
+struct cache_item_gidlist {
+ struct cache_item cache;
+ struct gid_list gidlist;
+ /* actually bigger */
+};
+
+struct cache_item *sudo_make_gritem(gid_t gid, const char *group);
+struct cache_item *sudo_make_grlist_item(const struct passwd *pw, char * const *groups);
+struct cache_item *sudo_make_gidlist_item(const struct passwd *pw, int ngids, GETGROUPS_T *gids, char * const *gidstrs, unsigned int type);
+struct cache_item *sudo_make_pwitem(uid_t uid, const char *user);
+bool sudo_valid_shell(const char *shell);
+
+#endif /* SUDOERS_PWUTIL_H */
diff --git a/plugins/sudoers/pwutil_impl.c b/plugins/sudoers/pwutil_impl.c
new file mode 100644
index 0000000..a2e3394
--- /dev/null
+++ b/plugins/sudoers/pwutil_impl.c
@@ -0,0 +1,473 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2007-2018
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <sudoers.h>
+#include <pwutil.h>
+
+#ifndef LOGIN_NAME_MAX
+# ifdef _POSIX_LOGIN_NAME_MAX
+# define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX
+# else
+# define LOGIN_NAME_MAX 9
+# endif
+#endif /* LOGIN_NAME_MAX */
+
+/*
+ * For testsudoers and cvtsudoers need to support building with a different
+ * function prefix and using custom getpwnam/getpwuid/getgrnam/getgrgid.
+ */
+#define EXPAND(p, f) p ## _ ## f
+#define WRAP(p, f) EXPAND(p, f)
+#ifdef PWUTIL_PREFIX
+# define CALL(x) WRAP(PWUTIL_PREFIX, x)
+# define PREFIX(x) WRAP(PWUTIL_PREFIX, x)
+#else
+# define CALL(x) x
+# define PREFIX(x) WRAP(sudo, x)
+#endif
+
+#define FIELD_SIZE(src, name, size) \
+do { \
+ if (src->name) { \
+ size = strlen(src->name) + 1; \
+ total += size; \
+ } else { \
+ size = 0; \
+ } \
+} while (0)
+
+#define FIELD_COPY(src, dst, name, size) \
+do { \
+ if (src->name) { \
+ memcpy(cp, src->name, size); \
+ dst->name = cp; \
+ cp += size; \
+ } \
+} while (0)
+
+/*
+ * Dynamically allocate space for a struct item plus the key and data
+ * elements. If name is non-NULL it is used as the key, else the
+ * uid is the key. Fills in datum from struct password.
+ * Returns NULL on calloc error or unknown name/id, setting errno
+ * to ENOMEM or ENOENT respectively.
+ */
+struct cache_item *
+PREFIX(make_pwitem)(uid_t uid, const char *name)
+{
+ char *cp;
+ const char *pw_shell;
+ size_t nsize, psize, gsize, dsize, ssize, total;
+#ifdef HAVE_LOGIN_CAP_H
+ size_t csize;
+#endif
+ struct cache_item_pw *pwitem;
+ struct passwd *pw, *newpw;
+ debug_decl(sudo_make_pwitem, SUDOERS_DEBUG_NSS);
+
+ /* Look up by name or uid. */
+ pw = name ? CALL(getpwnam)(name) : CALL(getpwuid)(uid);
+ if (pw == NULL) {
+ errno = ENOENT;
+ debug_return_ptr(NULL);
+ }
+
+ /* If shell field is empty, expand to _PATH_BSHELL. */
+ pw_shell = (pw->pw_shell == NULL || pw->pw_shell[0] == '\0')
+ ? _PATH_BSHELL : pw->pw_shell;
+
+ /* Allocate in one big chunk for easy freeing. */
+ total = sizeof(*pwitem);
+ FIELD_SIZE(pw, pw_name, nsize);
+ FIELD_SIZE(pw, pw_passwd, psize);
+#ifdef HAVE_LOGIN_CAP_H
+ FIELD_SIZE(pw, pw_class, csize);
+#endif
+ FIELD_SIZE(pw, pw_gecos, gsize);
+ FIELD_SIZE(pw, pw_dir, dsize);
+ /* Treat shell specially since we expand "" -> _PATH_BSHELL */
+ ssize = strlen(pw_shell) + 1;
+ total += ssize;
+ if (name != NULL)
+ total += strlen(name) + 1;
+
+ /* Allocate space for struct item, struct passwd and the strings. */
+ if ((pwitem = calloc(1, total)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+ newpw = &pwitem->pw;
+
+ /*
+ * Copy in passwd contents and make strings relative to space
+ * at the end of the struct.
+ */
+ memcpy(newpw, pw, sizeof(*pw));
+ cp = (char *)(pwitem + 1);
+ FIELD_COPY(pw, newpw, pw_name, nsize);
+ FIELD_COPY(pw, newpw, pw_passwd, psize);
+#ifdef HAVE_LOGIN_CAP_H
+ FIELD_COPY(pw, newpw, pw_class, csize);
+#endif
+ FIELD_COPY(pw, newpw, pw_gecos, gsize);
+ FIELD_COPY(pw, newpw, pw_dir, dsize);
+ /* Treat shell specially since we expand "" -> _PATH_BSHELL */
+ memcpy(cp, pw_shell, ssize);
+ newpw->pw_shell = cp;
+ cp += ssize;
+
+ /* Set key and datum. */
+ if (name != NULL) {
+ memcpy(cp, name, strlen(name) + 1);
+ pwitem->cache.k.name = cp;
+ } else {
+ pwitem->cache.k.uid = pw->pw_uid;
+ }
+ pwitem->cache.d.pw = newpw;
+ pwitem->cache.refcnt = 1;
+
+ debug_return_ptr(&pwitem->cache);
+}
+
+/*
+ * Dynamically allocate space for a struct item plus the key and data
+ * elements. If name is non-NULL it is used as the key, else the
+ * gid is the key. Fills in datum from struct group.
+ * Returns NULL on calloc error or unknown name/id, setting errno
+ * to ENOMEM or ENOENT respectively.
+ */
+struct cache_item *
+PREFIX(make_gritem)(gid_t gid, const char *name)
+{
+ char *cp;
+ size_t nsize, psize, total, len, nmem = 0;
+ struct cache_item_gr *gritem;
+ struct group *gr, *newgr;
+ debug_decl(sudo_make_gritem, SUDOERS_DEBUG_NSS);
+
+ /* Look up by name or gid. */
+ gr = name ? CALL(getgrnam)(name) : CALL(getgrgid)(gid);
+ if (gr == NULL) {
+ errno = ENOENT;
+ debug_return_ptr(NULL);
+ }
+
+ /* Allocate in one big chunk for easy freeing. */
+ total = sizeof(*gritem);
+ FIELD_SIZE(gr, gr_name, nsize);
+ FIELD_SIZE(gr, gr_passwd, psize);
+ if (gr->gr_mem) {
+ for (nmem = 0; gr->gr_mem[nmem] != NULL; nmem++)
+ total += strlen(gr->gr_mem[nmem]) + 1;
+ nmem++;
+ total += sizeof(char *) * nmem;
+ }
+ if (name != NULL)
+ total += strlen(name) + 1;
+
+ if ((gritem = calloc(1, total)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+
+ /*
+ * Copy in group contents and make strings relative to space
+ * at the end of the buffer. Note that gr_mem must come
+ * immediately after struct group to guarantee proper alignment.
+ */
+ newgr = &gritem->gr;
+ memcpy(newgr, gr, sizeof(*gr));
+ cp = (char *)(gritem + 1);
+ if (gr->gr_mem) {
+ newgr->gr_mem = (char **)cp;
+ cp += sizeof(char *) * nmem;
+ for (nmem = 0; gr->gr_mem[nmem] != NULL; nmem++) {
+ len = strlen(gr->gr_mem[nmem]) + 1;
+ memcpy(cp, gr->gr_mem[nmem], len);
+ newgr->gr_mem[nmem] = cp;
+ cp += len;
+ }
+ newgr->gr_mem[nmem] = NULL;
+ }
+ FIELD_COPY(gr, newgr, gr_passwd, psize);
+ FIELD_COPY(gr, newgr, gr_name, nsize);
+
+ /* Set key and datum. */
+ if (name != NULL) {
+ memcpy(cp, name, strlen(name) + 1);
+ gritem->cache.k.name = cp;
+ } else {
+ gritem->cache.k.gid = gr->gr_gid;
+ }
+ gritem->cache.d.gr = newgr;
+ gritem->cache.refcnt = 1;
+
+ debug_return_ptr(&gritem->cache);
+}
+
+/*
+ * Dynamically allocate space for a struct item plus the key and data elements.
+ */
+struct cache_item *
+PREFIX(make_gidlist_item)(const struct passwd *pw, int ngids, GETGROUPS_T *gids,
+ char * const *gidstrs, unsigned int type)
+{
+ char *cp;
+ size_t nsize, total;
+ struct cache_item_gidlist *glitem;
+ struct gid_list *gidlist;
+ int i;
+ debug_decl(sudo_make_gidlist_item, SUDOERS_DEBUG_NSS);
+
+ /*
+ * Ignore supplied gids if the entry type says we must query the group db.
+ */
+ if (type != ENTRY_TYPE_QUERIED && (gids != NULL || gidstrs != NULL)) {
+ if (gids == NULL) {
+ /* Convert the supplied gids list from string format to gid_t. */
+ ngids = 1;
+ for (i = 0; gidstrs[i] != NULL; i++)
+ ngids++;
+ gids = reallocarray(NULL, (size_t)ngids, sizeof(GETGROUPS_T));
+ if (gids == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+ ngids = 1;
+ gids[0] = pw->pw_gid;
+ for (i = 0; gidstrs[i] != NULL; i++) {
+ const char *errstr;
+ GETGROUPS_T gid = (gid_t) sudo_strtoid(gidstrs[i], &errstr);
+ if (errstr != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_DIAG|SUDO_DEBUG_LINENO,
+ "gid %s %s", gidstrs[i], errstr);
+ continue;
+ }
+ if (gid != gids[0])
+ gids[ngids++] = gid;
+ }
+ }
+ type = ENTRY_TYPE_FRONTEND;
+ } else {
+ type = ENTRY_TYPE_QUERIED;
+ ngids = sudo_pwutil_get_max_groups();
+ if (ngids > 0) {
+ gids = reallocarray(NULL, (size_t)ngids, sizeof(GETGROUPS_T));
+ if (gids == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+ /* Clamp to max_groups if insufficient space for all groups. */
+ if (PREFIX(getgrouplist2)(pw->pw_name, pw->pw_gid, &gids, &ngids) == -1)
+ ngids = sudo_pwutil_get_max_groups();
+ } else {
+ gids = NULL;
+ if (PREFIX(getgrouplist2)(pw->pw_name, pw->pw_gid, &gids, &ngids) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+ }
+ }
+ if (ngids <= 0) {
+ free(gids);
+ errno = ENOENT;
+ debug_return_ptr(NULL);
+ }
+
+ /* Allocate in one big chunk for easy freeing. */
+ nsize = strlen(pw->pw_name) + 1;
+ total = sizeof(*glitem) + nsize;
+ total += sizeof(gid_t *) * (size_t)ngids;
+
+ if ((glitem = calloc(1, total)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ free(gids);
+ debug_return_ptr(NULL);
+ }
+
+ /*
+ * Copy in group list and make pointers relative to space
+ * at the end of the buffer. Note that the groups array must come
+ * immediately after struct group to guarantee proper alignment.
+ */
+ gidlist = &glitem->gidlist;
+ cp = (char *)(glitem + 1);
+ gidlist->gids = (gid_t *)cp;
+ cp += sizeof(gid_t) * (size_t)ngids;
+
+ /* Set key and datum. */
+ memcpy(cp, pw->pw_name, nsize);
+ glitem->cache.k.name = cp;
+ glitem->cache.d.gidlist = gidlist;
+ glitem->cache.refcnt = 1;
+ glitem->cache.type = type;
+
+ /*
+ * Store group IDs.
+ */
+ for (i = 0; i < ngids; i++)
+ gidlist->gids[i] = gids[i];
+ gidlist->ngids = ngids;
+ free(gids);
+
+ debug_return_ptr(&glitem->cache);
+}
+
+/*
+ * Dynamically allocate space for a struct item plus the key and data
+ * elements. Fills in group names from a call to sudo_get_gidlist().
+ */
+struct cache_item *
+PREFIX(make_grlist_item)(const struct passwd *pw, char * const *unused1)
+{
+ char *cp;
+ size_t groupname_len, len, ngroups, nsize, total;
+ struct cache_item_grlist *grlitem;
+ struct group_list *grlist;
+ struct gid_list *gidlist;
+ struct group *grp = NULL;
+ int i;
+ debug_decl(sudo_make_grlist_item, SUDOERS_DEBUG_NSS);
+
+ gidlist = sudo_get_gidlist(pw, ENTRY_TYPE_ANY);
+ if (gidlist == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "no gid list for use %s", pw->pw_name);
+ errno = ENOENT;
+ debug_return_ptr(NULL);
+ }
+
+#ifdef _SC_LOGIN_NAME_MAX
+ groupname_len = (size_t)MAX(sysconf(_SC_LOGIN_NAME_MAX), 32);
+#else
+ groupname_len = MAX(LOGIN_NAME_MAX, 32);
+#endif
+
+ /* Allocate in one big chunk for easy freeing. */
+ nsize = strlen(pw->pw_name) + 1;
+ total = sizeof(*grlitem) + nsize;
+ total += sizeof(char *) * (size_t)gidlist->ngids;
+ total += groupname_len * (size_t)gidlist->ngids;
+
+again:
+ if ((grlitem = calloc(1, total)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ sudo_gidlist_delref(gidlist);
+ debug_return_ptr(NULL);
+ }
+
+ /*
+ * Copy in group list and make pointers relative to space
+ * at the end of the buffer. Note that the groups array must come
+ * immediately after struct group to guarantee proper alignment.
+ */
+ grlist = &grlitem->grlist;
+ cp = (char *)(grlitem + 1);
+ grlist->groups = (char **)cp;
+ cp += sizeof(char *) * (size_t)gidlist->ngids;
+
+ /* Set key and datum. */
+ memcpy(cp, pw->pw_name, nsize);
+ grlitem->cache.k.name = cp;
+ grlitem->cache.d.grlist = grlist;
+ grlitem->cache.refcnt = 1;
+ cp += nsize;
+
+ /*
+ * Resolve and store group names by ID.
+ */
+#ifdef HAVE_SETAUTHDB
+ if (grp == NULL)
+ aix_setauthdb((char *) pw->pw_name, NULL);
+#endif
+ ngroups = 0;
+ for (i = 0; i < gidlist->ngids; i++) {
+ if ((grp = sudo_getgrgid(gidlist->gids[i])) != NULL) {
+ len = strlen(grp->gr_name) + 1;
+ if ((size_t)(cp - (char *)grlitem) + len > total) {
+ total += len + groupname_len;
+ free(grlitem);
+ sudo_gr_delref(grp);
+ goto again;
+ }
+ memcpy(cp, grp->gr_name, len);
+ grlist->groups[ngroups++] = cp;
+ cp += len;
+ sudo_gr_delref(grp);
+ }
+ }
+ grlist->ngroups = (int)ngroups;
+ sudo_gidlist_delref(gidlist);
+
+#ifdef HAVE_SETAUTHDB
+ aix_restoreauthdb();
+#endif
+
+ debug_return_ptr(&grlitem->cache);
+}
+
+/*
+ * Returns true if the specified shell is allowed by /etc/shells, else false.
+ */
+bool
+PREFIX(valid_shell)(const char *shell)
+{
+ const char *entry;
+ debug_decl(valid_shell, SUDOERS_DEBUG_NSS);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: checking /etc/shells for %s", __func__, shell);
+
+ CALL(setusershell)();
+ while ((entry = CALL(getusershell)()) != NULL) {
+ if (strcmp(entry, shell) == 0)
+ debug_return_bool(true);
+ }
+ CALL(endusershell)();
+
+ debug_return_bool(false);
+}
diff --git a/plugins/sudoers/redblack.c b/plugins/sudoers/redblack.c
new file mode 100644
index 0000000..58762c3
--- /dev/null
+++ b/plugins/sudoers/redblack.c
@@ -0,0 +1,479 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2004-2005, 2007, 2009-2015
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+/*
+ * Adapted from the following code written by Emin Martinian:
+ * http://web.mit.edu/~emin/www/source_code/red_black_tree/index.html
+ *
+ * Copyright (c) 2001 Emin Martinian
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that neither the name of Emin
+ * Martinian nor the names of any contributors are be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sudoers.h>
+#include <redblack.h>
+
+static void rbrepair(struct rbtree *, struct rbnode *);
+static void rotate_left(struct rbtree *, struct rbnode *);
+static void rotate_right(struct rbtree *, struct rbnode *);
+static void rbdestroy_int(struct rbtree *, struct rbnode *, void (*)(void *));
+
+/*
+ * Red-Black tree, see http://en.wikipedia.org/wiki/Red-black_tree
+ *
+ * A red-black tree is a binary search tree where each node has a color
+ * attribute, the value of which is either red or black. Essentially, it
+ * is just a convenient way to express a 2-3-4 binary search tree where
+ * the color indicates whether the node is part of a 3-node or a 4-node.
+ * In addition to the ordinary requirements imposed on binary search
+ * trees, we make the following additional requirements of any valid
+ * red-black tree:
+ * 1) Every node is either red or black.
+ * 2) The root is black.
+ * 3) All leaves are black.
+ * 4) Both children of each red node are black.
+ * 5) The paths from each leaf up to the root each contain the same
+ * number of black nodes.
+ */
+
+/*
+ * Create a red black tree struct using the specified compare routine.
+ * Allocates and returns the initialized (empty) tree or NULL if
+ * memory cannot be allocated.
+ */
+struct rbtree *
+rbcreate(int (*compar)(const void *, const void*))
+{
+ struct rbtree *tree;
+ debug_decl(rbcreate, SUDOERS_DEBUG_RBTREE);
+
+ if ((tree = malloc(sizeof(*tree))) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_ptr(NULL);
+ }
+
+ tree->compar = compar;
+
+ /*
+ * We use a self-referencing sentinel node called nil to simplify the
+ * code by avoiding the need to check for NULL pointers.
+ */
+ tree->nil.left = tree->nil.right = tree->nil.parent = &tree->nil;
+ tree->nil.color = black;
+ tree->nil.data = NULL;
+
+ /*
+ * Similarly, the fake root node keeps us from having to worry
+ * about splitting the root.
+ */
+ tree->root.left = tree->root.right = tree->root.parent = &tree->nil; // -V778
+ tree->root.color = black;
+ tree->root.data = NULL;
+
+ debug_return_ptr(tree);
+}
+
+/*
+ * Perform a left rotation starting at node.
+ */
+static void
+rotate_left(struct rbtree *tree, struct rbnode *node)
+{
+ struct rbnode *child;
+ debug_decl(rotate_left, SUDOERS_DEBUG_RBTREE);
+
+ child = node->right;
+ node->right = child->left;
+
+ if (child->left != rbnil(tree))
+ child->left->parent = node;
+ child->parent = node->parent;
+
+ if (node == node->parent->left)
+ node->parent->left = child;
+ else
+ node->parent->right = child;
+ child->left = node;
+ node->parent = child;
+
+ debug_return;
+}
+
+/*
+ * Perform a right rotation starting at node.
+ */
+static void
+rotate_right(struct rbtree *tree, struct rbnode *node)
+{
+ struct rbnode *child;
+ debug_decl(rotate_right, SUDOERS_DEBUG_RBTREE);
+
+ child = node->left;
+ node->left = child->right;
+
+ if (child->right != rbnil(tree))
+ child->right->parent = node;
+ child->parent = node->parent;
+
+ if (node == node->parent->left)
+ node->parent->left = child;
+ else
+ node->parent->right = child;
+ child->right = node;
+ node->parent = child;
+
+ debug_return;
+}
+
+/*
+ * Insert data pointer into a redblack tree.
+ * Returns a 0 on success, 1 if a node matching "data" already exists
+ * (filling in "existing" if not NULL), or -1 on malloc() failure.
+ */
+int
+rbinsert(struct rbtree *tree, void *data, struct rbnode **existing)
+{
+ struct rbnode *node = rbfirst(tree);
+ struct rbnode *parent = rbroot(tree);
+ int res;
+ debug_decl(rbinsert, SUDOERS_DEBUG_RBTREE);
+
+ /* Find correct insertion point. */
+ while (node != rbnil(tree)) {
+ parent = node;
+ if ((res = tree->compar(data, node->data)) == 0) {
+ if (existing != NULL)
+ *existing = node;
+ debug_return_int(1);
+ }
+ node = res < 0 ? node->left : node->right;
+ }
+
+ node = malloc(sizeof(*node));
+ if (node == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_int(-1);
+ }
+ node->data = data;
+ node->left = node->right = rbnil(tree);
+ node->parent = parent;
+ if (parent == rbroot(tree) || tree->compar(data, parent->data) < 0)
+ parent->left = node;
+ else
+ parent->right = node;
+ node->color = red;
+
+ /*
+ * If the parent node is black we are all set, if it is red we have
+ * the following possible cases to deal with. We iterate through
+ * the rest of the tree to make sure none of the required properties
+ * is violated.
+ *
+ * 1) The uncle is red. We repaint both the parent and uncle black
+ * and repaint the grandparent node red.
+ *
+ * 2) The uncle is black and the new node is the right child of its
+ * parent, and the parent in turn is the left child of its parent.
+ * We do a left rotation to switch the roles of the parent and
+ * child, relying on further iterations to fixup the old parent.
+ *
+ * 3) The uncle is black and the new node is the left child of its
+ * parent, and the parent in turn is the left child of its parent.
+ * We switch the colors of the parent and grandparent and perform
+ * a right rotation around the grandparent. This makes the former
+ * parent the parent of the new node and the former grandparent.
+ *
+ * Note that because we use a sentinel for the root node we never
+ * need to worry about replacing the root.
+ */
+ while (node->parent->color == red) {
+ struct rbnode *uncle;
+ if (node->parent == node->parent->parent->left) {
+ uncle = node->parent->parent->right;
+ if (uncle->color == red) {
+ node->parent->color = black;
+ uncle->color = black;
+ node->parent->parent->color = red;
+ node = node->parent->parent;
+ } else /* if (uncle->color == black) */ {
+ if (node == node->parent->right) {
+ node = node->parent;
+ rotate_left(tree, node);
+ }
+ node->parent->color = black;
+ node->parent->parent->color = red;
+ rotate_right(tree, node->parent->parent);
+ }
+ } else { /* if (node->parent == node->parent->parent->right) */
+ uncle = node->parent->parent->left;
+ if (uncle->color == red) {
+ node->parent->color = black;
+ uncle->color = black;
+ node->parent->parent->color = red;
+ node = node->parent->parent;
+ } else /* if (uncle->color == black) */ {
+ if (node == node->parent->left) {
+ node = node->parent;
+ rotate_right(tree, node);
+ }
+ node->parent->color = black;
+ node->parent->parent->color = red;
+ rotate_left(tree, node->parent->parent);
+ }
+ }
+ }
+ rbfirst(tree)->color = black; /* first node is always black */
+ debug_return_int(0);
+}
+
+/*
+ * Look for a node matching key in tree.
+ * Returns a pointer to the node if found, else NULL.
+ */
+struct rbnode *
+rbfind(struct rbtree *tree, void *key)
+{
+ struct rbnode *node = rbfirst(tree);
+ int res;
+ debug_decl(rbfind, SUDOERS_DEBUG_RBTREE);
+
+ while (node != rbnil(tree)) {
+ if ((res = tree->compar(key, node->data)) == 0)
+ debug_return_ptr(node);
+ node = res < 0 ? node->left : node->right;
+ }
+ debug_return_ptr(NULL);
+}
+
+/*
+ * Call func() for each node, passing it the node data and a cookie;
+ * If func() returns non-zero for a node, the traversal stops and the
+ * error value is returned. Returns 0 on successful traversal.
+ */
+int
+rbapply_node(struct rbtree *tree, struct rbnode *node,
+ int (*func)(void *, void *), void *cookie, enum rbtraversal order)
+{
+ int error;
+ debug_decl(rbapply_node, SUDOERS_DEBUG_RBTREE);
+
+ if (node != rbnil(tree)) {
+ if (order == preorder)
+ if ((error = func(node->data, cookie)) != 0)
+ debug_return_int(error);
+ if ((error = rbapply_node(tree, node->left, func, cookie, order)) != 0)
+ debug_return_int(error);
+ if (order == inorder)
+ if ((error = func(node->data, cookie)) != 0)
+ debug_return_int(error);
+ if ((error = rbapply_node(tree, node->right, func, cookie, order)) != 0)
+ debug_return_int(error);
+ if (order == postorder)
+ if ((error = func(node->data, cookie)) != 0)
+ debug_return_int(error);
+ }
+ debug_return_int(0);
+}
+
+/*
+ * Returns the successor of node, or nil if there is none.
+ */
+static struct rbnode *
+rbsuccessor(struct rbtree *tree, struct rbnode *node)
+{
+ struct rbnode *succ;
+ debug_decl(rbsuccessor, SUDOERS_DEBUG_RBTREE);
+
+ if ((succ = node->right) != rbnil(tree)) {
+ while (succ->left != rbnil(tree))
+ succ = succ->left;
+ } else {
+ /* No right child, move up until we find it or hit the root */
+ for (succ = node->parent; node == succ->right; succ = succ->parent)
+ node = succ;
+ if (succ == rbroot(tree))
+ succ = rbnil(tree);
+ }
+ debug_return_ptr(succ);
+}
+
+/*
+ * Recursive portion of rbdestroy().
+ */
+static void
+rbdestroy_int(struct rbtree *tree, struct rbnode *node, void (*destroy)(void *))
+{
+ debug_decl(rbdestroy_int, SUDOERS_DEBUG_RBTREE);
+ if (node != rbnil(tree)) {
+ rbdestroy_int(tree, node->left, destroy);
+ rbdestroy_int(tree, node->right, destroy);
+ if (destroy != NULL)
+ destroy(node->data);
+ free(node);
+ }
+ debug_return;
+}
+
+/*
+ * Destroy the specified tree, calling the destructor "destroy"
+ * for each node and then freeing the tree itself.
+ */
+void
+rbdestroy(struct rbtree *tree, void (*destroy)(void *))
+{
+ debug_decl(rbdestroy, SUDOERS_DEBUG_RBTREE);
+ rbdestroy_int(tree, rbfirst(tree), destroy);
+ free(tree);
+ debug_return;
+}
+
+/*
+ * Delete node 'z' from the tree and return its data pointer.
+ */
+void *rbdelete(struct rbtree *tree, struct rbnode *z)
+{
+ struct rbnode *x, *y;
+ void *data = z->data;
+ debug_decl(rbdelete, SUDOERS_DEBUG_RBTREE);
+
+ if (z->left == rbnil(tree) || z->right == rbnil(tree))
+ y = z;
+ else
+ y = rbsuccessor(tree, z);
+ x = (y->left == rbnil(tree)) ? y->right : y->left;
+
+ if ((x->parent = y->parent) == rbroot(tree)) {
+ rbfirst(tree) = x;
+ } else {
+ if (y == y->parent->left)
+ y->parent->left = x;
+ else
+ y->parent->right = x;
+ }
+ if (y->color == black)
+ rbrepair(tree, x);
+ if (y != z) {
+ y->left = z->left;
+ y->right = z->right;
+ y->parent = z->parent;
+ y->color = z->color;
+ z->left->parent = z->right->parent = y;
+ if (z == z->parent->left)
+ z->parent->left = y;
+ else
+ z->parent->right = y;
+ }
+ free(z);
+
+ debug_return_ptr(data);
+}
+
+/*
+ * Repair the tree after a node has been deleted by rotating and repainting
+ * colors to restore the 4 properties inherent in red-black trees.
+ */
+static void
+rbrepair(struct rbtree *tree, struct rbnode *node)
+{
+ struct rbnode *sibling;
+ debug_decl(rbrepair, SUDOERS_DEBUG_RBTREE);
+
+ while (node->color == black && node != rbfirst(tree)) {
+ if (node == node->parent->left) {
+ sibling = node->parent->right;
+ if (sibling->color == red) {
+ sibling->color = black;
+ node->parent->color = red;
+ rotate_left(tree, node->parent);
+ sibling = node->parent->right;
+ }
+ if (sibling->right->color == black && sibling->left->color == black) {
+ sibling->color = red;
+ node = node->parent;
+ } else {
+ if (sibling->right->color == black) {
+ sibling->left->color = black;
+ sibling->color = red;
+ rotate_right(tree, sibling);
+ sibling = node->parent->right;
+ }
+ sibling->color = node->parent->color;
+ node->parent->color = black;
+ sibling->right->color = black;
+ rotate_left(tree, node->parent);
+ node = rbfirst(tree); /* exit loop */
+ }
+ } else { /* if (node == node->parent->right) */
+ sibling = node->parent->left;
+ if (sibling->color == red) {
+ sibling->color = black;
+ node->parent->color = red;
+ rotate_right(tree, node->parent);
+ sibling = node->parent->left;
+ }
+ if (sibling->right->color == black && sibling->left->color == black) {
+ sibling->color = red;
+ node = node->parent;
+ } else {
+ if (sibling->left->color == black) {
+ sibling->right->color = black;
+ sibling->color = red;
+ rotate_left(tree, sibling);
+ sibling = node->parent->left;
+ }
+ sibling->color = node->parent->color;
+ node->parent->color = black;
+ sibling->left->color = black;
+ rotate_right(tree, node->parent);
+ node = rbfirst(tree); /* exit loop */
+ }
+ }
+ }
+ node->color = black;
+
+ debug_return;
+}
diff --git a/plugins/sudoers/redblack.h b/plugins/sudoers/redblack.h
new file mode 100644
index 0000000..300383d
--- /dev/null
+++ b/plugins/sudoers/redblack.h
@@ -0,0 +1,60 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2004, 2007, 2010, 2013
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_REDBLACK_H
+#define SUDOERS_REDBLACK_H
+
+enum rbcolor {
+ red,
+ black
+};
+
+enum rbtraversal {
+ preorder,
+ inorder,
+ postorder
+};
+
+struct rbnode {
+ struct rbnode *left, *right, *parent;
+ void *data;
+ enum rbcolor color;
+};
+
+struct rbtree {
+ int (*compar)(const void *, const void *);
+ struct rbnode root;
+ struct rbnode nil;
+};
+
+#define rbapply(t, f, c, o) rbapply_node((t), (t)->root.left, (f), (c), (o))
+#define rbisempty(t) ((t)->root.left == &(t)->nil && (t)->root.right == &(t)->nil)
+#define rbfirst(t) ((t)->root.left)
+#define rbroot(t) (&(t)->root)
+#define rbnil(t) (&(t)->nil)
+
+void *rbdelete(struct rbtree *, struct rbnode *);
+int rbapply_node(struct rbtree *, struct rbnode *,
+ int (*)(void *, void *), void *, enum rbtraversal);
+struct rbnode *rbfind(struct rbtree *, void *);
+int rbinsert(struct rbtree *, void *, struct rbnode **);
+struct rbtree *rbcreate(int (*)(const void *, const void *));
+void rbdestroy(struct rbtree *, void (*)(void *));
+
+#endif /* SUDOERS_REDBLACK_H */
diff --git a/plugins/sudoers/regress/check_symbols/check_symbols.c b/plugins/sudoers/regress/check_symbols/check_symbols.c
new file mode 100644
index 0000000..41e9479
--- /dev/null
+++ b/plugins/sudoers/regress/check_symbols/check_symbols.c
@@ -0,0 +1,114 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2012-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <sudo_compat.h>
+#include <sudo_dso.h>
+#include <sudo_util.h>
+#include <sudo_fatal.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+sudo_noreturn static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-v] plugin.so symbols_file\n", getprogname());
+ exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char *argv[])
+{
+ void *handle, *sym;
+ const char *plugin_path;
+ const char *symbols_file;
+ char *cp, line[LINE_MAX];
+ FILE *fp;
+ int ch, ntests = 0, errors = 0;
+
+ initprogname(argc > 0 ? argv[0] : "check_symbols");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignored */
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 2)
+ usage();
+ plugin_path = argv[0];
+ symbols_file = argv[1];
+
+ handle = sudo_dso_load(plugin_path, SUDO_DSO_LAZY|SUDO_DSO_GLOBAL);
+ if (handle == NULL) {
+ const char *errstr = sudo_dso_strerror();
+ sudo_fatalx_nodebug("unable to load %s: %s", plugin_path,
+ errstr ? errstr : "unknown error");
+ }
+
+ fp = fopen(symbols_file, "r");
+ if (fp == NULL)
+ sudo_fatal_nodebug("unable to open %s", symbols_file);
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ ntests++;
+ if ((cp = strchr(line, '\n')) != NULL)
+ *cp = '\0';
+ sym = sudo_dso_findsym(handle, line);
+ if (sym == NULL) {
+ const char *errstr = sudo_dso_strerror();
+ printf("%s: test %d: unable to resolve symbol %s: %s\n",
+ getprogname(), ntests, line, errstr ? errstr : "unknown error");
+ errors++;
+ }
+ }
+
+ /*
+ * Make sure unexported symbols are not available.
+ */
+ ntests++;
+ sym = sudo_dso_findsym(handle, "user_in_group");
+ if (sym != NULL) {
+ printf("%s: test %d: able to resolve local symbol user_in_group\n",
+ getprogname(), ntests);
+ errors++;
+ }
+
+ sudo_dso_unload(handle);
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ exit(errors);
+}
diff --git a/plugins/sudoers/regress/corpus/seed/ldif/invalid_b64.ldif b/plugins/sudoers/regress/corpus/seed/ldif/invalid_b64.ldif
new file mode 100644
index 0000000..b8c7b99
--- /dev/null
+++ b/plugins/sudoers/regress/corpus/seed/ldif/invalid_b64.ldif
@@ -0,0 +1,33 @@
+# defaults, SUDOers, sudo.ws
+dn:: Y249ZGVmYXVsdHMsb3U9U1VET2VycyxkYz1zdWRvLGRjPXdz
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption:: bG9nX29@1dHB1dA==
+
+# root, SUDOers, sudo.ws
+dn:: Y249cm9vdCxvdT1TVURPZXJzLGRjPXN1ZG8sZGM9_d3M=
+objectClass: top
+objectClass: sudoRole
+cn: root
+sudoUser: root
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: ALL
+sudoCommand: ALL
+sudoOption: !authenticate
+sudoOrder: 10
+
+# %wheel, SUDOers, sudo.ws
+dn:: Y249JXdoZWVsLG91PVNVRE9lcnMsZGM9c3VkbyxkYz13cw!==
+objectClass: top
+objectClass: sudoRole
+cn: %wheel
+sudoUser: %wheel
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: +sudo-hosts
+sudoCommand: ALL
+sudoOption: !authenticate
+sudoOrder: 10
diff --git a/plugins/sudoers/regress/corpus/seed/ldif/pr196.ldif b/plugins/sudoers/regress/corpus/seed/ldif/pr196.ldif
new file mode 100644
index 0000000..78c150a
--- /dev/null
+++ b/plugins/sudoers/regress/corpus/seed/ldif/pr196.ldif
@@ -0,0 +1,6 @@
+# Exercise the fix for https://github.com/sudo-project/sudo/pull/169
+#
+# If the last byte of the input file was a backslash, the parser would
+# read past the end of the buffer.
+#
+dn: cn= Manager\ \ No newline at end of file
diff --git a/plugins/sudoers/regress/corpus/seed/ldif/sample.ldif b/plugins/sudoers/regress/corpus/seed/ldif/sample.ldif
new file mode 100644
index 0000000..81474a1
--- /dev/null
+++ b/plugins/sudoers/regress/corpus/seed/ldif/sample.ldif
@@ -0,0 +1,295 @@
+# LDIF version of the example sudoers file
+
+# Unable to translate ./examples/sudoers:12:17:
+# Defaults>root !set_logname
+
+# Unable to translate ./examples/sudoers:16:24:
+# Defaults!/usr/bin/more, /usr/bin/pg, /usr/bin/less noexec
+
+dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: syslog=auth
+sudoOption: runcwd=~
+
+dn: cn=root,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: root
+sudoUser: root
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOrder: 1
+
+dn: cn=%wheel,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: %wheel
+sudoUser: %wheel
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOrder: 2
+
+dn: cn=FULLTIMERS,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: FULLTIMERS
+sudoUser: millert
+sudoUser: mikef
+sudoUser: dowdy
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoOption: !authenticate
+sudoOption: !lecture
+sudoOption: !runchroot=*
+sudoCommand: ALL
+sudoOrder: 3
+
+dn: cn=PARTTIMERS,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: PARTTIMERS
+sudoUser: bostley
+sudoUser: jwfox
+sudoUser: crawl
+sudoHost: ALL
+sudoCommand: ALL
+sudoOrder: 4
+
+dn: cn=jack,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: jack
+sudoUser: jack
+sudoHost: 128.138.243.0
+sudoHost: 128.138.204.0/24
+sudoHost: 128.138.242.0
+sudoCommand: ALL
+sudoOrder: 5
+
+dn: cn=lisa,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: lisa
+sudoUser: lisa
+sudoHost: 128.138.0.0/255.255.0.0
+sudoCommand: ALL
+sudoOrder: 6
+
+dn: cn=operator,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: operator
+sudoUser: operator
+sudoHost: ALL
+sudoCommand: /usr/sbin/dump
+sudoCommand: /usr/sbin/rdump
+sudoCommand: /usr/sbin/restore
+sudoCommand: /usr/sbin/rrestore
+sudoCommand: /usr/bin/mt
+sudoCommand: sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ== /home/operator/bin/start_backups
+sudoCommand: /usr/bin/kill
+sudoCommand: /usr/bin/top
+sudoCommand: /usr/sbin/shutdown
+sudoCommand: /usr/sbin/halt
+sudoCommand: /usr/sbin/reboot
+sudoCommand: /usr/sbin/lpc
+sudoCommand: /usr/bin/lprm
+sudoCommand: sudoedit /etc/printcap
+sudoCommand: /usr/oper/bin/
+sudoOrder: 7
+
+dn: cn=joe,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: joe
+sudoUser: joe
+sudoHost: ALL
+sudoCommand: /usr/bin/su operator
+sudoOrder: 8
+
+dn: cn=pete,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: pete
+sudoUser: pete
+sudoHost: boa
+sudoHost: nag
+sudoHost: python
+sudoCommand: /usr/bin/passwd ^[a-zA-Z0-9_]+$
+sudoCommand: !/usr/bin/passwd root
+sudoOrder: 9
+
+dn: cn=bob,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: bob
+sudoUser: bob
+sudoHost: bigtime
+sudoHost: eclipse
+sudoHost: moet
+sudoHost: anchor
+sudoRunAsUser: root
+sudoRunAsUser: operator
+sudoCommand: ALL
+sudoOrder: 10
+
+dn: cn=bob_1,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: bob_1
+sudoUser: bob
+sudoHost: grolsch
+sudoHost: dandelion
+sudoHost: black
+sudoRunAsUser: root
+sudoRunAsUser: operator
+sudoCommand: ALL
+sudoOrder: 11
+
+dn: cn=jim,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: jim
+sudoUser: jim
+sudoHost: +biglab
+sudoCommand: ALL
+sudoOrder: 12
+
+dn: cn=\+secretaries,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: \+secretaries
+sudoUser: +secretaries
+sudoHost: ALL
+sudoCommand: /usr/sbin/lpc
+sudoCommand: /usr/bin/lprm
+sudoCommand: /usr/bin/adduser
+sudoCommand: /usr/bin/rmuser
+sudoOrder: 13
+
+dn: cn=fred,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: fred
+sudoUser: fred
+sudoHost: ALL
+sudoRunAsUser: oracle
+sudoRunAsUser: sybase
+sudoOption: !authenticate
+sudoCommand: ALL
+sudoOrder: 14
+
+dn: cn=john,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: john
+sudoUser: john
+sudoHost: widget
+sudoHost: thalamus
+sudoHost: foobar
+sudoCommand: /usr/bin/su ^[a-zA-Z0-9_]+$
+sudoCommand: !/usr/bin/su root
+sudoOrder: 15
+
+dn: cn=jen,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: jen
+sudoUser: jen
+sudoHost: ALL
+sudoHost: !primary
+sudoHost: !mail
+sudoHost: !www
+sudoHost: !ns
+sudoCommand: ALL
+sudoOrder: 16
+
+dn: cn=jill,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: jill
+sudoUser: jill
+sudoHost: primary
+sudoHost: mail
+sudoHost: www
+sudoHost: ns
+sudoOption: log_year
+sudoOption: logfile=/var/log/sudo.log
+sudoCommand: /usr/bin/
+sudoCommand: !/usr/bin/su
+sudoCommand: !/sbin/sh
+sudoCommand: !/usr/bin/sh
+sudoCommand: !/usr/bin/csh
+sudoCommand: !/usr/bin/ksh
+sudoCommand: !/usr/local/bin/tcsh
+sudoCommand: !/usr/bin/rsh
+sudoCommand: !/usr/local/bin/zsh
+sudoOrder: 17
+
+dn: cn=steve,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: steve
+sudoUser: steve
+sudoHost: 128.138.243.0
+sudoHost: 128.138.204.0/24
+sudoHost: 128.138.242.0
+sudoRunAsUser: operator
+sudoCommand: /usr/local/op_commands/
+sudoOrder: 18
+
+dn: cn=matt,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: matt
+sudoUser: matt
+sudoHost: valkyrie
+sudoCommand: /usr/bin/kill
+sudoCommand: /usr/bin/top
+sudoOrder: 19
+
+dn: cn=WEBADMIN,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: WEBADMIN
+sudoUser: will
+sudoUser: wendy
+sudoUser: wim
+sudoHost: www
+sudoRunAsUser: www
+sudoCommand: ALL
+sudoOrder: 20
+
+dn: cn=WEBADMIN_1,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: WEBADMIN_1
+sudoUser: will
+sudoUser: wendy
+sudoUser: wim
+sudoHost: www
+sudoRunAsUser: root
+sudoCommand: /usr/bin/su www
+sudoOrder: 21
+
+dn: cn=ALL,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: ALL
+sudoUser: ALL
+sudoHost: orion
+sudoHost: perseus
+sudoHost: hercules
+sudoOption: !authenticate
+sudoCommand: /sbin/umount /CDROM
+sudoCommand: /sbin/mount -o nosuid,nodev /dev/cd0a /CDROM
+sudoOrder: 22
+
diff --git a/plugins/sudoers/regress/corpus/seed/ldif/valid_b64.ldif b/plugins/sudoers/regress/corpus/seed/ldif/valid_b64.ldif
new file mode 100644
index 0000000..d17e670
--- /dev/null
+++ b/plugins/sudoers/regress/corpus/seed/ldif/valid_b64.ldif
@@ -0,0 +1,44 @@
+# defaults, SUDOers, sudo.ws
+dn:: Y249ZGVmYXVsdHMsb3U9U1VET2VycyxkYz1zdWRvLGRjPXdz
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption:: bG9nX291dHB1dA==
+
+# root, SUDOers, sudo.ws
+dn:: Y249cm9vdCxvdT1TVURPZXJzLGRjPXN1ZG8sZGM9d3M=
+objectClass: top
+objectClass: sudoRole
+cn: root
+sudoUser: root
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: ALL
+sudoCommand: ALL
+sudoOption: !authenticate
+sudoOrder: 10
+
+# %wheel, SUDOers, sudo.ws
+dn:: Y249JXdoZWVsLG91PVNVRE9lcnMsZGM9c3VkbyxkYz13cw==
+objectClass: top
+objectClass: sudoRole
+cn: %wheel
+sudoUser: %wheel
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: +sudo-hosts
+sudoCommand: ALL
+sudoOption: !authenticate
+sudoOrder: 10
+
+# millert, SUDOers, other-domain.com
+dn:: Y249bWlsbGVydCxvdT1TVURPZXJzLGRjPW90aGVyLWRvbWFpbixkYz1jb20=
+objectClass: top
+objectClass: sudoRole
+cn: millert
+sudoUser: millert
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: ALL
+sudoOrder: 5
diff --git a/plugins/sudoers/regress/corpus/seed/policy/policy.1 b/plugins/sudoers/regress/corpus/seed/policy/policy.1
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/plugins/sudoers/regress/corpus/seed/policy/policy.1
@@ -0,0 +1 @@
+
diff --git a/plugins/sudoers/regress/corpus/seed/policy/policy.2 b/plugins/sudoers/regress/corpus/seed/policy/policy.2
new file mode 100644
index 0000000..ea1793d
--- /dev/null
+++ b/plugins/sudoers/regress/corpus/seed/policy/policy.2
@@ -0,0 +1,5 @@
+# Minimal test case
+user=root
+uid=0
+gid=0
+host=localhost
diff --git a/plugins/sudoers/regress/corpus/seed/policy/policy.3 b/plugins/sudoers/regress/corpus/seed/policy/policy.3
new file mode 100644
index 0000000..b865e4c
--- /dev/null
+++ b/plugins/sudoers/regress/corpus/seed/policy/policy.3
@@ -0,0 +1,11 @@
+# Reproduce CVE-2021-3156
+run_shell=true
+sudoedit=true
+user=millert
+uid=1000
+gid=1000
+cwd=/home/millert
+host=localhost
+argv=foo
+argv=\
+argv=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
diff --git a/plugins/sudoers/regress/corpus/seed/policy/policy.4 b/plugins/sudoers/regress/corpus/seed/policy/policy.4
new file mode 100644
index 0000000..e5e3191
--- /dev/null
+++ b/plugins/sudoers/regress/corpus/seed/policy/policy.4
@@ -0,0 +1,36 @@
+# sudo -u nobody /usr/bin/id
+
+plugin_path=/usr/libexec/sudo/sudoers.so
+runas_user=nobody
+progname=sudo
+network_addrs=127.0.0.1/255.255.255.0
+plugin_dir=/usr/libexec/sudo/
+
+user=millert
+pid=1234
+ppid=1230
+pgid=1234
+tcpgid=1234
+sid=1230
+uid=1000
+euid=0
+gid=1000
+egid=1000
+groups=20,0,1000
+umask=022
+cwd=/home/millert
+tty=/dev/pts/1
+host=sudo.ws
+lines=24
+cols=80
+rlimit_core=infinity,infinity
+rlimit_cpu=infinity,infinity
+rlimit_data=1610612736,34359738368
+rlimit_fsize=infinity,infinity
+rlimit_memlock=2727370752,8182112256
+rlimit_nofile=256,1024
+rlimit_nproc=256,512
+rlimit_rss=8175603712,8182112256
+rlimit_stack=4194304,33554432
+
+argv=/usr/bin/id
diff --git a/plugins/sudoers/regress/corpus/seed/policy/policy.5 b/plugins/sudoers/regress/corpus/seed/policy/policy.5
new file mode 100644
index 0000000..bffae4d
--- /dev/null
+++ b/plugins/sudoers/regress/corpus/seed/policy/policy.5
@@ -0,0 +1,36 @@
+# sudoedit /etc/hosts
+
+plugin_path=/usr/libexec/sudo/sudoers.so
+progname=sudoedit
+network_addrs=127.0.0.1/255.255.255.0
+plugin_dir=/usr/libexec/sudo/
+
+user=millert
+pid=1234
+ppid=1230
+pgid=1234
+tcpgid=1234
+sid=1230
+uid=1000
+euid=0
+gid=1000
+egid=1000
+groups=20,0,1000
+umask=022
+cwd=/home/millert
+tty=/dev/pts/1
+host=sudo.ws
+lines=24
+cols=80
+rlimit_core=infinity,infinity
+rlimit_cpu=infinity,infinity
+rlimit_data=1610612736,34359738368
+rlimit_fsize=infinity,infinity
+rlimit_memlock=2727370752,8182112256
+rlimit_nofile=256,1024
+rlimit_nproc=256,512
+rlimit_rss=8175603712,8182112256
+rlimit_stack=4194304,33554432
+
+argv=sudoedit
+argv=/etc/hosts
diff --git a/plugins/sudoers/regress/cvtsudoers/sudoers b/plugins/sudoers/regress/cvtsudoers/sudoers
new file mode 100644
index 0000000..8a926f8
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/sudoers
@@ -0,0 +1,126 @@
+#
+# Sample /etc/sudoers file.
+#
+# This file MUST be edited with the 'visudo' command as root.
+#
+# See the sudoers man page for the details on how to write a sudoers file.
+
+##
+# Override built-in defaults
+##
+Defaults syslog=auth
+Defaults>root !set_logname
+Defaults:FULLTIMERS !lecture
+Defaults:millert !authenticate
+Defaults@SERVERS log_year, logfile=/var/log/sudo.log
+Defaults!PAGERS noexec
+
+##
+# User alias specification
+##
+User_Alias FULLTIMERS = millert, mikef, dowdy
+User_Alias PARTTIMERS = bostley, jwfox, crawl
+User_Alias WEBADMIN = will, wendy, wim
+
+##
+# Runas alias specification
+##
+Runas_Alias OP = root, operator
+Runas_Alias DB = oracle, sybase
+
+##
+# Host alias specification
+##
+Host_Alias SPARC = bigtime, eclipse, moet, anchor:\
+ SGI = grolsch, dandelion, black:\
+ ALPHA = widget, thalamus, foobar:\
+ HPPA = boa, nag, python
+Host_Alias CUNETS = 128.138.0.0/255.255.0.0
+Host_Alias CSNETS = 128.138.243.0, 128.138.204.0/24, 128.138.242.0
+Host_Alias SERVERS = primary, mail, www, ns
+Host_Alias CDROM = orion, perseus, hercules
+
+##
+# Cmnd alias specification
+##
+Cmnd_Alias DUMPS = /usr/sbin/dump, /usr/sbin/rdump, /usr/sbin/restore, \
+ /usr/sbin/rrestore, /usr/bin/mt, \
+ sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ== \
+ /home/operator/bin/start_backups
+Cmnd_Alias KILL = /usr/bin/kill, /usr/bin/top
+Cmnd_Alias PRINTING = /usr/sbin/lpc, /usr/bin/lprm
+Cmnd_Alias SHUTDOWN = /usr/sbin/shutdown
+Cmnd_Alias HALT = /usr/sbin/halt
+Cmnd_Alias REBOOT = /usr/sbin/reboot
+Cmnd_Alias SHELLS = /sbin/sh, /usr/bin/sh, /usr/bin/csh, /usr/bin/ksh, \
+ /usr/local/bin/tcsh, /usr/bin/rsh, \
+ /usr/local/bin/zsh
+Cmnd_Alias SU = /usr/bin/su
+Cmnd_Alias VIPW = /usr/sbin/vipw, /usr/bin/passwd, /usr/bin/chsh, \
+ /usr/bin/chfn
+Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less
+
+##
+# User specification
+##
+
+# root and users in group wheel can run anything on any machine as any user
+root ALL = (ALL) ALL
+%wheel ALL = (ALL) ALL
+
+# full time sysadmins can run anything on any machine without a password
+FULLTIMERS ALL = NOPASSWD: ALL
+
+# part time sysadmins may run anything but need a password
+PARTTIMERS ALL = ALL
+
+# jack may run anything on machines in CSNETS
+jack CSNETS = ALL
+
+# lisa may run any command on any host in CUNETS (a class B network)
+lisa CUNETS = ALL
+
+# operator may run maintenance commands and anything in /usr/oper/bin/
+operator ALL = DUMPS, KILL, SHUTDOWN, HALT, REBOOT, PRINTING,\
+ sudoedit /etc/printcap, /usr/oper/bin/
+
+# joe may su only to operator
+joe ALL = /usr/bin/su operator
+
+# pete may change passwords for anyone but root on the hp snakes
+pete HPPA = /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd *root*
+
+# bob may run anything on the sparc and sgi machines as any user
+# listed in the Runas_Alias "OP" (ie: root and operator)
+bob SPARC = (OP) ALL : SGI = (OP) ALL
+
+# fred can run commands as oracle or sybase without a password
+fred ALL = (DB) NOPASSWD: ALL
+
+# on the alphas, john may su to anyone but root and flags are not allowed
+john ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root*
+
+# jen can run anything on all machines except the ones
+# in the "SERVERS" Host_Alias
+jen ALL, !SERVERS = ALL
+
+# jill can run any commands in the directory /usr/bin/, except for
+# those in the SU and SHELLS aliases.
+jill SERVERS = /usr/bin/, !SU, !SHELLS
+
+# steve can run any command in the directory /usr/local/op_commands/
+# as user operator.
+steve CSNETS = (operator) /usr/local/op_commands/
+
+# matt needs to be able to kill things on his workstation when
+# they get hung.
+matt valkyrie = KILL
+
+# users in the WEBADMIN User_Alias (will, wendy, and wim)
+# may run any command as user www (which owns the web pages)
+# or simply su to www.
+WEBADMIN www = (www) ALL, (root) /usr/bin/su www
+
+# anyone can mount/unmount a cd-rom on the machines in the CDROM alias
+ALL CDROM = NOPASSWD: /sbin/umount /CDROM,\
+ /sbin/mount -o nosuid\,nodev /dev/cd0a /CDROM
diff --git a/plugins/sudoers/regress/cvtsudoers/sudoers.defs b/plugins/sudoers/regress/cvtsudoers/sudoers.defs
new file mode 100755
index 0000000..b374930
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/sudoers.defs
@@ -0,0 +1,19 @@
+Defaults syslog=auth
+Defaults>ROOT !set_logname
+Defaults:FULLTIMERS !lecture
+Defaults:millert !authenticate
+Defaults@SERVERS log_year, logfile=/var/log/sudo.log
+Defaults!PAGERS noexec
+
+User_Alias FULLTIMERS = millert, mikef, dowdy
+User_Alias PARTTIMERS = bostley, jwfox, crawl
+
+Host_Alias SERVERS = primary, mail, www, ns
+Host_Alias CDROM = orion, perseus, hercules
+
+Cmnd_Alias VIPW = /usr/sbin/vipw, /usr/bin/passwd, /usr/bin/chsh, \
+ /usr/bin/chfn
+Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less
+
+Runas_Alias ROOT = root, toor
+Runas_Alias OPERATOR = operator, backup
diff --git a/plugins/sudoers/regress/cvtsudoers/sudoers1 b/plugins/sudoers/regress/cvtsudoers/sudoers1
new file mode 100644
index 0000000..d7a05ca
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/sudoers1
@@ -0,0 +1,97 @@
+## sudoers file.
+##
+## This file MUST be edited with the 'visudo' command as root.
+## Failure to use 'visudo' may result in syntax or file permission errors
+## that prevent sudo from running.
+##
+## See the sudoers man page for the details on how to write a sudoers file.
+##
+
+##
+## Host alias specification
+##
+## Groups of machines. These may include host names (optionally with wildcards),
+## IP addresses, network numbers or netgroups.
+Host_Alias WEBSERVERS = www1, www2, www3
+
+##
+## User alias specification
+##
+## Groups of users. These may consist of user names, uids, Unix groups,
+## or netgroups.
+User_Alias ADMINS = millert, dowdy, mikef
+
+##
+## Cmnd alias specification
+##
+## Groups of commands. Often used to group related commands together.
+Cmnd_Alias PROCESSES = /usr/bin/nice, /bin/kill, /usr/bin/renice, \
+ /usr/bin/pkill, /usr/bin/top
+Cmnd_Alias REBOOT = /sbin/halt, /sbin/reboot, /sbin/poweroff
+
+##
+## Defaults specification
+##
+## You may wish to keep some of the following environment variables
+## when running commands via sudo.
+##
+## Locale settings
+# Defaults env_keep += "LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET"
+##
+## Run X applications through sudo; HOME is used to find the
+## .Xauthority file. Note that other programs use HOME to find
+## configuration files and this may lead to privilege escalation!
+# Defaults env_keep += "HOME"
+##
+## X11 resource path settings
+# Defaults env_keep += "XAPPLRESDIR XFILESEARCHPATH XUSERFILESEARCHPATH"
+##
+## Desktop path settings
+# Defaults env_keep += "QTDIR KDEDIR"
+##
+## Allow sudo-run commands to inherit the callers' ConsoleKit session
+# Defaults env_keep += "XDG_SESSION_COOKIE"
+##
+## Uncomment to enable special input methods. Care should be taken as
+## this may allow users to subvert the command being run via sudo.
+# Defaults env_keep += "XMODIFIERS GTK_IM_MODULE QT_IM_MODULE QT_IM_SWITCHER"
+##
+## Uncomment to use a hard-coded PATH instead of the user's to find commands
+Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+##
+## Uncomment to send mail if the user does not enter the correct password.
+# Defaults mail_badpass
+##
+## Uncomment to enable logging of a command's output, except for
+## sudoreplay and reboot. Use sudoreplay to play back logged sessions.
+Defaults log_output
+Defaults!/usr/bin/sudoreplay !log_output
+Defaults!/usr/local/bin/sudoreplay !log_output
+Defaults!REBOOT !log_output
+
+##
+## Runas alias specification
+##
+
+##
+## User privilege specification
+##
+root ALL=(ALL) ALL
+ALL ALL=(ALL) /usr/bin/id
+
+## Uncomment to allow members of group wheel to execute any command
+# %wheel ALL=(ALL) ALL
+
+## Same thing without a password
+# %wheel ALL=(ALL) NOPASSWD: ALL
+
+## Uncomment to allow members of group sudo to execute any command
+# %sudo ALL=(ALL) ALL
+
+## Uncomment to allow any user to run sudo if they know the password
+## of the user they are running the command as (root by default).
+# Defaults targetpw # Ask for the password of the target user
+# ALL ALL=(ALL) ALL # WARNING: only use this together with 'Defaults targetpw'
+
+## Read drop-in files from /etc/sudoers.d
+#@includedir /etc/sudoers.d
diff --git a/plugins/sudoers/regress/cvtsudoers/sudoers2 b/plugins/sudoers/regress/cvtsudoers/sudoers2
new file mode 100644
index 0000000..442d5e6
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/sudoers2
@@ -0,0 +1,97 @@
+## sudoers file.
+##
+## This file MUST be edited with the 'visudo' command as root.
+## Failure to use 'visudo' may result in syntax or file permission errors
+## that prevent sudo from running.
+##
+## See the sudoers man page for the details on how to write a sudoers file.
+##
+
+##
+## Host alias specification
+##
+## Groups of machines. These may include host names (optionally with wildcards),
+## IP addresses, network numbers or netgroups.
+Host_Alias WEBSERVERS = www1, www2, www3, www4
+
+##
+## User alias specification
+##
+## Groups of users. These may consist of user names, uids, Unix groups,
+## or netgroups.
+User_Alias ADMINS = millert, dowdy, mikef
+
+##
+## Cmnd alias specification
+##
+## Groups of commands. Often used to group related commands together.
+Cmnd_Alias PROCESSES = /usr/bin/nice, /bin/kill, /usr/bin/renice, \
+ /usr/bin/pkill, /usr/bin/top
+Cmnd_Alias REBOOT = /sbin/halt, /sbin/reboot, /sbin/poweroff
+
+##
+## Defaults specification
+##
+## You may wish to keep some of the following environment variables
+## when running commands via sudo.
+##
+## Locale settings
+# Defaults env_keep += "LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET"
+##
+## Run X applications through sudo; HOME is used to find the
+## .Xauthority file. Note that other programs use HOME to find
+## configuration files and this may lead to privilege escalation!
+# Defaults env_keep += "HOME"
+##
+## X11 resource path settings
+# Defaults env_keep += "XAPPLRESDIR XFILESEARCHPATH XUSERFILESEARCHPATH"
+##
+## Desktop path settings
+# Defaults env_keep += "QTDIR KDEDIR"
+##
+## Allow sudo-run commands to inherit the callers' ConsoleKit session
+# Defaults env_keep += "XDG_SESSION_COOKIE"
+##
+## Uncomment to enable special input methods. Care should be taken as
+## this may allow users to subvert the command being run via sudo.
+# Defaults env_keep += "XMODIFIERS GTK_IM_MODULE QT_IM_MODULE QT_IM_SWITCHER"
+##
+## Uncomment to use a hard-coded PATH instead of the user's to find commands
+Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+##
+## Uncomment to send mail if the user does not enter the correct password.
+# Defaults mail_badpass
+##
+## Uncomment to enable logging of a command's output, except for
+## sudoreplay and reboot. Use sudoreplay to play back logged sessions.
+Defaults log_output
+Defaults!/usr/bin/sudoreplay !log_output
+Defaults!/usr/local/bin/sudoreplay !log_output
+Defaults!REBOOT !log_output
+
+##
+## Runas alias specification
+##
+
+##
+## User privilege specification
+##
+root ALL=(ALL) ALL
+ALL ALL=(ALL) /usr/bin/id
+
+## Uncomment to allow members of group wheel to execute any command
+# %wheel ALL=(ALL) ALL
+
+## Same thing without a password
+# %wheel ALL=(ALL) NOPASSWD: ALL
+
+## Uncomment to allow members of group sudo to execute any command
+# %sudo ALL=(ALL) ALL
+
+## Uncomment to allow any user to run sudo if they know the password
+## of the user they are running the command as (root by default).
+# Defaults targetpw # Ask for the password of the target user
+# ALL ALL=(ALL) ALL # WARNING: only use this together with 'Defaults targetpw'
+
+## Read drop-in files from /etc/sudoers.d
+#@includedir /etc/sudoers.d
diff --git a/plugins/sudoers/regress/cvtsudoers/sudoers3 b/plugins/sudoers/regress/cvtsudoers/sudoers3
new file mode 100644
index 0000000..ee2769e
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/sudoers3
@@ -0,0 +1,97 @@
+## sudoers file.
+##
+## This file MUST be edited with the 'visudo' command as root.
+## Failure to use 'visudo' may result in syntax or file permission errors
+## that prevent sudo from running.
+##
+## See the sudoers man page for the details on how to write a sudoers file.
+##
+
+##
+## Host alias specification
+##
+## Groups of machines. These may include host names (optionally with wildcards),
+## IP addresses, network numbers or netgroups.
+Host_Alias WEBSERVERS_1 = www1, www2, www3, www5
+
+##
+## User alias specification
+##
+## Groups of users. These may consist of user names, uids, Unix groups,
+## or netgroups.
+User_Alias ADMINS = millert, dowdy, mikef
+
+##
+## Cmnd alias specification
+##
+## Groups of commands. Often used to group related commands together.
+Cmnd_Alias PROCESSES = /usr/bin/nice, /bin/kill, /usr/bin/renice, \
+ /usr/bin/pkill, /usr/bin/top
+Cmnd_Alias REBOOT = /sbin/halt, /sbin/reboot, /sbin/poweroff
+
+##
+## Defaults specification
+##
+## You may wish to keep some of the following environment variables
+## when running commands via sudo.
+##
+## Locale settings
+# Defaults env_keep += "LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET"
+##
+## Run X applications through sudo; HOME is used to find the
+## .Xauthority file. Note that other programs use HOME to find
+## configuration files and this may lead to privilege escalation!
+# Defaults env_keep += "HOME"
+##
+## X11 resource path settings
+# Defaults env_keep += "XAPPLRESDIR XFILESEARCHPATH XUSERFILESEARCHPATH"
+##
+## Desktop path settings
+# Defaults env_keep += "QTDIR KDEDIR"
+##
+## Allow sudo-run commands to inherit the callers' ConsoleKit session
+# Defaults env_keep += "XDG_SESSION_COOKIE"
+##
+## Uncomment to enable special input methods. Care should be taken as
+## this may allow users to subvert the command being run via sudo.
+# Defaults env_keep += "XMODIFIERS GTK_IM_MODULE QT_IM_MODULE QT_IM_SWITCHER"
+##
+## Uncomment to use a hard-coded PATH instead of the user's to find commands
+Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+##
+## Uncomment to send mail if the user does not enter the correct password.
+# Defaults mail_badpass
+##
+## Uncomment to enable logging of a command's output, except for
+## sudoreplay and reboot. Use sudoreplay to play back logged sessions.
+# Defaults log_output
+# Defaults!/usr/bin/sudoreplay !log_output
+# Defaults!/usr/local/bin/sudoreplay !log_output
+# Defaults!REBOOT !log_output
+
+##
+## Runas alias specification
+##
+
+##
+## User privilege specification
+##
+root ALL=(ALL) ALL
+ALL ALL=(ALL) /usr/bin/id
+
+## Uncomment to allow members of group wheel to execute any command
+# %wheel ALL=(ALL) ALL
+
+## Same thing without a password
+# %wheel ALL=(ALL) NOPASSWD: ALL
+
+## Uncomment to allow members of group sudo to execute any command
+# %sudo ALL=(ALL) ALL
+
+## Uncomment to allow any user to run sudo if they know the password
+## of the user they are running the command as (root by default).
+# Defaults targetpw # Ask for the password of the target user
+# ALL ALL=(ALL) ALL # WARNING: only use this together with 'Defaults targetpw'
+
+## Read drop-in files from /etc/sudoers.d
+#@includedir /etc/sudoers.d
diff --git a/plugins/sudoers/regress/cvtsudoers/sudoers4 b/plugins/sudoers/regress/cvtsudoers/sudoers4
new file mode 100644
index 0000000..c85b0dc
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/sudoers4
@@ -0,0 +1,97 @@
+## sudoers file.
+##
+## This file MUST be edited with the 'visudo' command as root.
+## Failure to use 'visudo' may result in syntax or file permission errors
+## that prevent sudo from running.
+##
+## See the sudoers man page for the details on how to write a sudoers file.
+##
+
+##
+## Host alias specification
+##
+## Groups of machines. These may include host names (optionally with wildcards),
+## IP addresses, network numbers or netgroups.
+Host_Alias WEBSERVERS_1 = www1, www2, www3, www5
+
+##
+## User alias specification
+##
+## Groups of users. These may consist of user names, uids, Unix groups,
+## or netgroups.
+User_Alias ADMINS = millert, dowdy, mikef
+
+##
+## Cmnd alias specification
+##
+## Groups of commands. Often used to group related commands together.
+Cmnd_Alias PROCESSES = /usr/bin/nice, /bin/kill, /usr/bin/renice, \
+ /usr/bin/pkill, /usr/bin/top
+Cmnd_Alias REBOOT = /sbin/halt, /sbin/reboot, /sbin/poweroff
+
+##
+## Defaults specification
+##
+## You may wish to keep some of the following environment variables
+## when running commands via sudo.
+##
+## Locale settings
+# Defaults env_keep += "LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET"
+##
+## Run X applications through sudo; HOME is used to find the
+## .Xauthority file. Note that other programs use HOME to find
+## configuration files and this may lead to privilege escalation!
+# Defaults env_keep += "HOME"
+##
+## X11 resource path settings
+# Defaults env_keep += "XAPPLRESDIR XFILESEARCHPATH XUSERFILESEARCHPATH"
+##
+## Desktop path settings
+# Defaults env_keep += "QTDIR KDEDIR"
+##
+## Allow sudo-run commands to inherit the callers' ConsoleKit session
+# Defaults env_keep += "XDG_SESSION_COOKIE"
+##
+## Uncomment to enable special input methods. Care should be taken as
+## this may allow users to subvert the command being run via sudo.
+# Defaults env_keep += "XMODIFIERS GTK_IM_MODULE QT_IM_MODULE QT_IM_SWITCHER"
+##
+## Uncomment to use a hard-coded PATH instead of the user's to find commands
+Defaults secure_path="/opt/sudo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+##
+## Uncomment to send mail if the user does not enter the correct password.
+# Defaults mail_badpass
+##
+## Uncomment to enable logging of a command's output, except for
+## sudoreplay and reboot. Use sudoreplay to play back logged sessions.
+# Defaults log_output
+# Defaults!/usr/bin/sudoreplay !log_output
+# Defaults!/usr/local/bin/sudoreplay !log_output
+# Defaults!REBOOT !log_output
+
+##
+## Runas alias specification
+##
+
+##
+## User privilege specification
+##
+root ALL=(ALL) ALL
+ALL ALL=(ALL) /usr/bin/id
+
+## Uncomment to allow members of group wheel to execute any command
+# %wheel ALL=(ALL) ALL
+
+## Same thing without a password
+# %wheel ALL=(ALL) NOPASSWD: ALL
+
+## Uncomment to allow members of group sudo to execute any command
+# %sudo ALL=(ALL) ALL
+
+## Uncomment to allow any user to run sudo if they know the password
+## of the user they are running the command as (root by default).
+# Defaults targetpw # Ask for the password of the target user
+# ALL ALL=(ALL) ALL # WARNING: only use this together with 'Defaults targetpw'
+
+## Read drop-in files from /etc/sudoers.d
+#@includedir /etc/sudoers.d
diff --git a/plugins/sudoers/regress/cvtsudoers/test1.out.ok b/plugins/sudoers/regress/cvtsudoers/test1.out.ok
new file mode 100644
index 0000000..da3f555
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test1.out.ok
@@ -0,0 +1,14 @@
+Defaults syslog=auth
+Defaults>root !set_logname
+Defaults:FULLTIMERS !lecture
+Defaults:millert !authenticate
+Defaults!PAGERS noexec
+
+Host_Alias CDROM = orion, perseus, hercules
+User_Alias FULLTIMERS = millert, mikef, dowdy
+Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less
+
+FULLTIMERS ALL = NOPASSWD: ALL
+
+ALL CDROM = NOPASSWD: /sbin/umount /CDROM, /sbin/mount -o nosuid\,nodev\
+ /dev/cd0a /CDROM
diff --git a/plugins/sudoers/regress/cvtsudoers/test1.sh b/plugins/sudoers/regress/cvtsudoers/test1.sh
new file mode 100755
index 0000000..ba5f87f
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test1.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Test user and host filters
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -m user=millert,host=hercules $TESTDIR/sudoers
+
+exit 0
diff --git a/plugins/sudoers/regress/cvtsudoers/test10.out.ok b/plugins/sudoers/regress/cvtsudoers/test10.out.ok
new file mode 100644
index 0000000..26a05d2
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test10.out.ok
@@ -0,0 +1 @@
+Defaults!PAGERS noexec
diff --git a/plugins/sudoers/regress/cvtsudoers/test10.sh b/plugins/sudoers/regress/cvtsudoers/test10.sh
new file mode 100755
index 0000000..38550a9
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test10.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Test command defaults filtering
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -s aliases,privileges -d command $TESTDIR/sudoers
+
+exit 0
diff --git a/plugins/sudoers/regress/cvtsudoers/test11.out.ok b/plugins/sudoers/regress/cvtsudoers/test11.out.ok
new file mode 100644
index 0000000..5c4c4e8
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test11.out.ok
@@ -0,0 +1,7 @@
+Defaults!PAGERS noexec
+
+Host_Alias CDROM = orion, perseus, hercules
+Runas_Alias OPERATOR = operator, backup
+Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less
+User_Alias PARTTIMERS = bostley, jwfox, crawl
+Cmnd_Alias VIPW = /usr/sbin/vipw, /usr/bin/passwd, /usr/bin/chsh, /usr/bin/chfn
diff --git a/plugins/sudoers/regress/cvtsudoers/test11.sh b/plugins/sudoers/regress/cvtsudoers/test11.sh
new file mode 100755
index 0000000..f8d37ef
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test11.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# Test that Aliases are removed when filtering by defaults type
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -d command $TESTDIR/sudoers.defs
diff --git a/plugins/sudoers/regress/cvtsudoers/test12.out.ok b/plugins/sudoers/regress/cvtsudoers/test12.out.ok
new file mode 100644
index 0000000..7f2b15e
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test12.out.ok
@@ -0,0 +1,8 @@
+Defaults:FULLTIMERS !lecture
+Defaults:millert !authenticate
+
+Host_Alias CDROM = orion, perseus, hercules
+User_Alias FULLTIMERS = millert, mikef, dowdy
+Runas_Alias OPERATOR = operator, backup
+User_Alias PARTTIMERS = bostley, jwfox, crawl
+Cmnd_Alias VIPW = /usr/sbin/vipw, /usr/bin/passwd, /usr/bin/chsh, /usr/bin/chfn
diff --git a/plugins/sudoers/regress/cvtsudoers/test12.sh b/plugins/sudoers/regress/cvtsudoers/test12.sh
new file mode 100755
index 0000000..dd2cab0
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test12.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# Test that Aliases are removed when filtering by defaults type
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -d user $TESTDIR/sudoers.defs
diff --git a/plugins/sudoers/regress/cvtsudoers/test13.out.ok b/plugins/sudoers/regress/cvtsudoers/test13.out.ok
new file mode 100644
index 0000000..5276327
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test13.out.ok
@@ -0,0 +1,7 @@
+Defaults@SERVERS log_year, logfile=/var/log/sudo.log
+
+Host_Alias CDROM = orion, perseus, hercules
+Runas_Alias OPERATOR = operator, backup
+User_Alias PARTTIMERS = bostley, jwfox, crawl
+Host_Alias SERVERS = primary, mail, www, ns
+Cmnd_Alias VIPW = /usr/sbin/vipw, /usr/bin/passwd, /usr/bin/chsh, /usr/bin/chfn
diff --git a/plugins/sudoers/regress/cvtsudoers/test13.sh b/plugins/sudoers/regress/cvtsudoers/test13.sh
new file mode 100755
index 0000000..8ee6000
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test13.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# Test that Aliases are removed when filtering by defaults type
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -d host $TESTDIR/sudoers.defs
diff --git a/plugins/sudoers/regress/cvtsudoers/test14.out.ok b/plugins/sudoers/regress/cvtsudoers/test14.out.ok
new file mode 100644
index 0000000..3f7710a
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test14.out.ok
@@ -0,0 +1,7 @@
+Defaults>ROOT !set_logname
+
+Host_Alias CDROM = orion, perseus, hercules
+Runas_Alias OPERATOR = operator, backup
+User_Alias PARTTIMERS = bostley, jwfox, crawl
+Runas_Alias ROOT = root, toor
+Cmnd_Alias VIPW = /usr/sbin/vipw, /usr/bin/passwd, /usr/bin/chsh, /usr/bin/chfn
diff --git a/plugins/sudoers/regress/cvtsudoers/test14.sh b/plugins/sudoers/regress/cvtsudoers/test14.sh
new file mode 100755
index 0000000..4486faa
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test14.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# Test that Aliases are removed when filtering by defaults type
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -d runas $TESTDIR/sudoers.defs
diff --git a/plugins/sudoers/regress/cvtsudoers/test15.out.ok b/plugins/sudoers/regress/cvtsudoers/test15.out.ok
new file mode 100644
index 0000000..5177139
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test15.out.ok
@@ -0,0 +1 @@
+user1 host1, host2, host3 = ALL
diff --git a/plugins/sudoers/regress/cvtsudoers/test15.sh b/plugins/sudoers/regress/cvtsudoers/test15.sh
new file mode 100755
index 0000000..6d65c78
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test15.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Test filters and pruning
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -p -m user=user1 <<EOF
+user1, user2, user3, %group1 host1, host2, host3 = ALL
+EOF
diff --git a/plugins/sudoers/regress/cvtsudoers/test16.out.ok b/plugins/sudoers/regress/cvtsudoers/test16.out.ok
new file mode 100644
index 0000000..38359b1
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test16.out.ok
@@ -0,0 +1 @@
+user2 host2 = ALL
diff --git a/plugins/sudoers/regress/cvtsudoers/test16.sh b/plugins/sudoers/regress/cvtsudoers/test16.sh
new file mode 100755
index 0000000..4a1632c
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test16.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Test filters and pruning
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -p -m user=user2,host=host2 <<EOF
+user1, user2, user3, %group1 host1, host2, host3 = ALL
+EOF
diff --git a/plugins/sudoers/regress/cvtsudoers/test17.out.ok b/plugins/sudoers/regress/cvtsudoers/test17.out.ok
new file mode 100644
index 0000000..d35dd06
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test17.out.ok
@@ -0,0 +1 @@
+%group1 host1 = ALL
diff --git a/plugins/sudoers/regress/cvtsudoers/test17.sh b/plugins/sudoers/regress/cvtsudoers/test17.sh
new file mode 100755
index 0000000..e8e8082
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test17.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Test filters and pruning
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -p -m group=group1,host=host1 <<EOF
+user1, user2, user3, %group1 host1, host2, host3 = ALL
+EOF
diff --git a/plugins/sudoers/regress/cvtsudoers/test18.out.ok b/plugins/sudoers/regress/cvtsudoers/test18.out.ok
new file mode 100644
index 0000000..3055452
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test18.out.ok
@@ -0,0 +1 @@
+%group1 ALL = ALL
diff --git a/plugins/sudoers/regress/cvtsudoers/test18.sh b/plugins/sudoers/regress/cvtsudoers/test18.sh
new file mode 100755
index 0000000..cceed89
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test18.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Test filters and pruning
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -p -m group=group1,host=somehost <<EOF
+user1, user2, user3, %group1 ALL = ALL
+EOF
diff --git a/plugins/sudoers/regress/cvtsudoers/test19.out.ok b/plugins/sudoers/regress/cvtsudoers/test19.out.ok
new file mode 100644
index 0000000..66b95ac
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test19.out.ok
@@ -0,0 +1,11 @@
+Defaults syslog=auth
+Defaults>root !set_logname
+Defaults:FULLTIMERS !lecture
+Defaults@SERVERS log_year, logfile=/var/log/sudo.log
+Defaults!PAGERS noexec
+
+User_Alias FULLTIMERS = millert, mikef, dowdy
+Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less
+Host_Alias SERVERS = primary, mail, www, ns
+
+FULLTIMERS ALL = NOPASSWD: ALL
diff --git a/plugins/sudoers/regress/cvtsudoers/test19.sh b/plugins/sudoers/regress/cvtsudoers/test19.sh
new file mode 100755
index 0000000..b3c1bf7
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test19.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# Test filters and pruning; alias contents don't get pruned
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -p -m user=FULLTIMERS,host=SERVERS $TESTDIR/sudoers
diff --git a/plugins/sudoers/regress/cvtsudoers/test2.out.ok b/plugins/sudoers/regress/cvtsudoers/test2.out.ok
new file mode 100644
index 0000000..d99e0e5
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test2.out.ok
@@ -0,0 +1,10 @@
+Defaults syslog=auth
+Defaults>root !set_logname
+Defaults:millert, mikef, dowdy !lecture
+Defaults:millert !authenticate
+Defaults!/usr/bin/more, /usr/bin/pg, /usr/bin/less noexec
+
+millert, mikef, dowdy ALL = NOPASSWD: ALL
+
+ALL orion, perseus, hercules = NOPASSWD: /sbin/umount /CDROM, /sbin/mount -o\
+ nosuid\,nodev /dev/cd0a /CDROM
diff --git a/plugins/sudoers/regress/cvtsudoers/test2.sh b/plugins/sudoers/regress/cvtsudoers/test2.sh
new file mode 100755
index 0000000..70e9553
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test2.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Test user and host filters, expanding aliases
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -e -m user=millert,host=hercules $TESTDIR/sudoers
+
+exit 0
diff --git a/plugins/sudoers/regress/cvtsudoers/test20.conf b/plugins/sudoers/regress/cvtsudoers/test20.conf
new file mode 100644
index 0000000..b60725c
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test20.conf
@@ -0,0 +1,6 @@
+defaults = global
+expand_aliases = yes
+input_format = sudoers
+match = user=user2
+output_format = sudoers
+prune_matches = yes
diff --git a/plugins/sudoers/regress/cvtsudoers/test20.out.ok b/plugins/sudoers/regress/cvtsudoers/test20.out.ok
new file mode 100644
index 0000000..79b420b
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test20.out.ok
@@ -0,0 +1 @@
+user2 ALL = /usr/bin/id
diff --git a/plugins/sudoers/regress/cvtsudoers/test20.sh b/plugins/sudoers/regress/cvtsudoers/test20.sh
new file mode 100755
index 0000000..e651e16
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test20.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+# Test cvtsudoers.conf
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c $TESTDIR/test20.conf <<EOF
+Defaults:SOMEUSERS authenticate, timestamp_timeout=0
+User_Alias SOMEUSERS = user1, user2, user3
+
+SOMEUSERS ALL = /usr/bin/id
+EOF
diff --git a/plugins/sudoers/regress/cvtsudoers/test21.conf b/plugins/sudoers/regress/cvtsudoers/test21.conf
new file mode 100644
index 0000000..01fd3a3
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test21.conf
@@ -0,0 +1,8 @@
+defaults = all
+expand_aliases = no
+input_format = sudoers
+order_increment = 10
+order_start = 1000
+output_format = ldif
+sudoers_base = ou=SUDOers,dc=my-domain,dc=com
+suppress = defaults
diff --git a/plugins/sudoers/regress/cvtsudoers/test21.out.ok b/plugins/sudoers/regress/cvtsudoers/test21.out.ok
new file mode 100644
index 0000000..78285f1
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test21.out.ok
@@ -0,0 +1,24 @@
+dn: cn=ALL,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: ALL
+sudoUser: ALL
+sudoHost: ALL
+sudoRunAsUser:
+sudoOption: !authenticate
+sudoCommand: /usr/bin/id
+sudoOrder: 1000
+
+dn: cn=FULLTIMERS,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: FULLTIMERS
+sudoUser: user1
+sudoUser: user2
+sudoUser: user3
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOrder: 1010
+
diff --git a/plugins/sudoers/regress/cvtsudoers/test21.sh b/plugins/sudoers/regress/cvtsudoers/test21.sh
new file mode 100755
index 0000000..836a353
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test21.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# Test cvtsudoers.conf
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c $TESTDIR/test21.conf <<EOF
+Defaults authenticate, timestamp_timeout=0
+User_Alias FULLTIMERS = user1, user2, user3
+
+ALL ALL = (:) NOPASSWD:/usr/bin/id
+FULLTIMERS ALL = (ALL:ALL) ALL
+EOF
diff --git a/plugins/sudoers/regress/cvtsudoers/test22.out.ok b/plugins/sudoers/regress/cvtsudoers/test22.out.ok
new file mode 100644
index 0000000..d404815
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test22.out.ok
@@ -0,0 +1,31 @@
+dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: log_output
+
+dn: cn=root,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: root
+sudoUser: root
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoOption: !authenticate
+sudoCommand: ALL
+sudoOrder: 10
+
+dn: cn=%wheel,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: %wheel
+sudoUser: %wheel
+sudoHost: +sudo-hosts
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoOption: !authenticate
+sudoCommand: ALL
+sudoOrder: 20
+
diff --git a/plugins/sudoers/regress/cvtsudoers/test22.sh b/plugins/sudoers/regress/cvtsudoers/test22.sh
new file mode 100755
index 0000000..9b4899b
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test22.sh
@@ -0,0 +1,73 @@
+#!/bin/sh
+#
+# Test LDAP base filtering.
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -i ldif -b "ou=SUDOers,dc=sudo,dc=ws" -I 10 -O 10 <<EOF
+dn: dc=sudo,dc=ws
+objectClass: dcObject
+objectClass: organization
+dc: courtesan
+o: Sudo World Headquarters
+description: Sudo World Headquarters
+
+# Organizational Role for Directory Manager
+dn: cn=Manager,dc=sudo,dc=ws
+objectClass: organizationalRole
+cn: Manager
+description: Directory Manager
+
+# SUDOers, sudo.ws
+dn: ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: organizationalUnit
+description: SUDO Configuration Subtree
+ou: SUDOers
+
+# defaults, SUDOers, sudo.ws
+dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: log_output
+
+# root, SUDOers, sudo.ws
+dn: cn=root,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: root
+sudoUser: root
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: ALL
+sudoCommand: ALL
+sudoOption: !authenticate
+sudoOrder: 10
+
+# %wheel, SUDOers, sudo.ws
+dn: cn=%wheel,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: %wheel
+sudoUser: %wheel
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: +sudo-hosts
+sudoCommand: ALL
+sudoOption: !authenticate
+sudoOrder: 10
+
+# millert, SUDOers, other-domain.com
+dn: cn=millert,ou=SUDOers,dc=other-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: millert
+sudoUser: millert
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: ALL
+sudoOrder: 5
+EOF
diff --git a/plugins/sudoers/regress/cvtsudoers/test23.out.ok b/plugins/sudoers/regress/cvtsudoers/test23.out.ok
new file mode 100644
index 0000000..7fc33c2
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test23.out.ok
@@ -0,0 +1,20 @@
+Defaults logfile=/var/log/sudo
+
+root ALL = (ALL) ALL
+
+%wheel ALL = (ALL) ALL
+
++admins ALL = NOPASSWD: ALL
+
+jack 128.138.204.0/24, 128.138.242.0, 128.138.243.0 = ALL
+
+lisa 128.138.0.0/255.255.0.0 = ALL
+
+operator ALL = /usr/sbin/dump, /usr/sbin/rdump, /usr/sbin/restore,\
+ /usr/sbin/rrestore, /usr/bin/mt,\
+ sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ==\
+ /home/operator/bin/start_backups, /usr/bin/kill, /usr/bin/top,\
+ /usr/sbin/shutdown, /usr/sbin/halt, /usr/sbin/reboot, /usr/sbin/lpc,\
+ /usr/bin/lprm, sudoedit /etc/printcap, /usr/oper/bin/
+
+joe ALL = /usr/bin/su operator
diff --git a/plugins/sudoers/regress/cvtsudoers/test23.sh b/plugins/sudoers/regress/cvtsudoers/test23.sh
new file mode 100755
index 0000000..02b8238
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test23.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+#
+# Test round-tripping of sudoers -> LDIF -> sudoers
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -b "ou=SUDOers,dc=sudo,dc=ws" $TESTDIR/test23.out.ok | \
+ $CVTSUDOERS -c "" -i LDIF -f sudoers | grep -v '^#'
diff --git a/plugins/sudoers/regress/cvtsudoers/test24.out.ok b/plugins/sudoers/regress/cvtsudoers/test24.out.ok
new file mode 100644
index 0000000..0951767
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test24.out.ok
@@ -0,0 +1,89 @@
+dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: logfile=/var/log/sudo
+
+dn: cn=root,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: root
+sudoUser: root
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoCommand: ALL
+sudoOrder: 1
+
+dn: cn=%wheel,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: %wheel
+sudoUser: %wheel
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoCommand: ALL
+sudoOrder: 2
+
+dn: cn=\+admins,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: \+admins
+sudoUser: +admins
+sudoHost: ALL
+sudoOption: !authenticate
+sudoCommand: ALL
+sudoOrder: 3
+
+dn: cn=jack,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: jack
+sudoUser: jack
+sudoHost: 128.138.204.0/24
+sudoHost: 128.138.242.0
+sudoHost: 128.138.243.0
+sudoCommand: ALL
+sudoOrder: 4
+
+dn: cn=lisa,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: lisa
+sudoUser: lisa
+sudoHost: 128.138.0.0/255.255.0.0
+sudoCommand: ALL
+sudoOrder: 5
+
+dn: cn=operator,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: operator
+sudoUser: operator
+sudoHost: ALL
+sudoCommand: /usr/sbin/dump
+sudoCommand: /usr/sbin/rdump
+sudoCommand: /usr/sbin/restore
+sudoCommand: /usr/sbin/rrestore
+sudoCommand: /usr/bin/mt
+sudoCommand: sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ== /home/operator/bin/start_backups
+sudoCommand: /usr/bin/kill
+sudoCommand: /usr/bin/top
+sudoCommand: /usr/sbin/shutdown
+sudoCommand: /usr/sbin/halt
+sudoCommand: /usr/sbin/reboot
+sudoCommand: /usr/sbin/lpc
+sudoCommand: /usr/bin/lprm
+sudoCommand: sudoedit /etc/printcap
+sudoCommand: /usr/oper/bin/
+sudoOrder: 6
+
+dn: cn=joe,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: joe
+sudoUser: joe
+sudoHost: ALL
+sudoCommand: /usr/bin/su operator
+sudoOrder: 7
+
diff --git a/plugins/sudoers/regress/cvtsudoers/test24.sh b/plugins/sudoers/regress/cvtsudoers/test24.sh
new file mode 100755
index 0000000..72d9983
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test24.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+#
+# Test round-tripping of LDIF -> sudoers -> LDIF
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -i LDIF -f sudoers $TESTDIR/test24.out.ok | \
+ $CVTSUDOERS -c "" -b "ou=SUDOers,dc=sudo,dc=ws"
diff --git a/plugins/sudoers/regress/cvtsudoers/test25.out.ok b/plugins/sudoers/regress/cvtsudoers/test25.out.ok
new file mode 100644
index 0000000..d404815
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test25.out.ok
@@ -0,0 +1,31 @@
+dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: log_output
+
+dn: cn=root,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: root
+sudoUser: root
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoOption: !authenticate
+sudoCommand: ALL
+sudoOrder: 10
+
+dn: cn=%wheel,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: %wheel
+sudoUser: %wheel
+sudoHost: +sudo-hosts
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoOption: !authenticate
+sudoCommand: ALL
+sudoOrder: 20
+
diff --git a/plugins/sudoers/regress/cvtsudoers/test25.sh b/plugins/sudoers/regress/cvtsudoers/test25.sh
new file mode 100755
index 0000000..bbb9b51
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test25.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+#
+# Test LDIF base64 attribute parsing
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -i ldif -b "ou=SUDOers,dc=sudo,dc=ws" -I 10 -O 10 <<EOF
+# defaults, SUDOers, sudo.ws
+dn:: Y249ZGVmYXVsdHMsb3U9U1VET2VycyxkYz1zdWRvLGRjPXdz
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption:: bG9nX291dHB1dA==
+
+# root, SUDOers, sudo.ws
+dn:: Y249cm9vdCxvdT1TVURPZXJzLGRjPXN1ZG8sZGM9d3M=
+objectClass: top
+objectClass: sudoRole
+cn: root
+sudoUser: root
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: ALL
+sudoCommand: ALL
+sudoOption: !authenticate
+sudoOrder: 10
+
+# %wheel, SUDOers, sudo.ws
+dn:: Y249JXdoZWVsLG91PVNVRE9lcnMsZGM9c3VkbyxkYz13cw==
+objectClass: top
+objectClass: sudoRole
+cn: %wheel
+sudoUser: %wheel
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: +sudo-hosts
+sudoCommand: ALL
+sudoOption: !authenticate
+sudoOrder: 10
+
+# millert, SUDOers, other-domain.com
+dn:: Y249bWlsbGVydCxvdT1TVURPZXJzLGRjPW90aGVyLWRvbWFpbixkYz1jb20=
+objectClass: top
+objectClass: sudoRole
+cn: millert
+sudoUser: millert
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: ALL
+sudoOrder: 5
+EOF
diff --git a/plugins/sudoers/regress/cvtsudoers/test26.err.ok b/plugins/sudoers/regress/cvtsudoers/test26.err.ok
new file mode 100644
index 0000000..a9c5e6a
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test26.err.ok
@@ -0,0 +1,3 @@
+cvtsudoers: invalid LDIF attribute: sudoOption:: bG9nX29@1dHB1dA==
+cvtsudoers: invalid LDIF attribute: dn:: Y249cm9vdCxvdT1TVURPZXJzLGRjPXN1ZG8sZGM9_d3M=
+cvtsudoers: invalid LDIF attribute: dn:: Y249JXdoZWVsLG91PVNVRE9lcnMsZGM9c3VkbyxkYz13cw!==
diff --git a/plugins/sudoers/regress/cvtsudoers/test26.out.ok b/plugins/sudoers/regress/cvtsudoers/test26.out.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test26.out.ok
diff --git a/plugins/sudoers/regress/cvtsudoers/test26.sh b/plugins/sudoers/regress/cvtsudoers/test26.sh
new file mode 100755
index 0000000..08c0246
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test26.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+#
+# Test LDIF invalid base64 attribute parsing
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -i ldif -b "ou=SUDOers,dc=sudo,dc=ws" -I 10 -O 10 <<EOF
+# defaults, SUDOers, sudo.ws
+dn:: Y249ZGVmYXVsdHMsb3U9U1VET2VycyxkYz1zdWRvLGRjPXdz
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption:: bG9nX29@1dHB1dA==
+
+# root, SUDOers, sudo.ws
+dn:: Y249cm9vdCxvdT1TVURPZXJzLGRjPXN1ZG8sZGM9_d3M=
+objectClass: top
+objectClass: sudoRole
+cn: root
+sudoUser: root
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: ALL
+sudoCommand: ALL
+sudoOption: !authenticate
+sudoOrder: 10
+
+# %wheel, SUDOers, sudo.ws
+dn:: Y249JXdoZWVsLG91PVNVRE9lcnMsZGM9c3VkbyxkYz13cw!==
+objectClass: top
+objectClass: sudoRole
+cn: %wheel
+sudoUser: %wheel
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: +sudo-hosts
+sudoCommand: ALL
+sudoOption: !authenticate
+sudoOrder: 10
+EOF
+
+# cvtsudoers should exit with an error
+if [ $? -eq 0 ]; then
+ exit 1
+else
+ exit 0
+fi
diff --git a/plugins/sudoers/regress/cvtsudoers/test27.out.ok b/plugins/sudoers/regress/cvtsudoers/test27.out.ok
new file mode 100644
index 0000000..ab9c948
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test27.out.ok
@@ -0,0 +1,16 @@
+dn:: Y249ZGVmYXVsdHMsb3U9U1VET2Vyc8KpLGRjPXN1ZG8sZGM9d3M=
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption:: YmFkcGFzc19tZXNzYWdlPUJhZCBwYXNzd29yZMKh
+
+dn:: Y249cm9vdCxvdT1TVURPZXJzwqksZGM9c3VkbyxkYz13cw==
+objectClass: top
+objectClass: sudoRole
+cn: root
+sudoUser: root
+sudoHost: ALL
+sudoCommand: ALL
+sudoOrder: 1
+
diff --git a/plugins/sudoers/regress/cvtsudoers/test27.sh b/plugins/sudoers/regress/cvtsudoers/test27.sh
new file mode 100755
index 0000000..c1a2df3
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test27.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+#
+# Test base64 encoding of non-safe strings
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -b "ou=SUDOers©,dc=sudo,dc=ws" <<EOF
+Defaults badpass_message="Bad password¡"
+
+root ALL = ALL
+EOF
diff --git a/plugins/sudoers/regress/cvtsudoers/test28.out.ok b/plugins/sudoers/regress/cvtsudoers/test28.out.ok
new file mode 100644
index 0000000..ba19cb9
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test28.out.ok
@@ -0,0 +1,10 @@
+Defaults log_output
+
+# sudoRole millert
+millert ALL = (ALL : ALL) ALL
+
+# sudoRole root
+root ALL = (ALL : ALL) NOPASSWD: ALL
+
+# sudoRole %wheel
+%wheel +sudo-hosts = (ALL : ALL) NOPASSWD: ALL
diff --git a/plugins/sudoers/regress/cvtsudoers/test28.sh b/plugins/sudoers/regress/cvtsudoers/test28.sh
new file mode 100755
index 0000000..e902355
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test28.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+#
+# Test LDAP sudoOrder when converting to sudoers.
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -i ldif -b "ou=SUDOers,dc=sudo,dc=ws" -f sudoers <<EOF
+dn: dc=sudo,dc=ws
+objectClass: dcObject
+objectClass: organization
+dc: courtesan
+o: Sudo World Headquarters
+description: Sudo World Headquarters
+
+# Organizational Role for Directory Manager
+dn: cn=Manager,dc=sudo,dc=ws
+objectClass: organizationalRole
+cn: Manager
+description: Directory Manager
+
+# SUDOers, sudo.ws
+dn: ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: organizationalUnit
+description: SUDO Configuration Subtree
+ou: SUDOers
+
+# defaults, SUDOers, sudo.ws
+dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: log_output
+
+# root, SUDOers, sudo.ws
+dn: cn=root,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: root
+sudoUser: root
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: ALL
+sudoCommand: ALL
+sudoOption: !authenticate
+sudoOrder: 10
+
+# %wheel, SUDOers, sudo.ws
+dn: cn=%wheel,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: %wheel
+sudoUser: %wheel
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: +sudo-hosts
+sudoCommand: ALL
+sudoOption: !authenticate
+sudoOrder: 20
+
+# millert, SUDOers, sudo.ws
+dn: cn=millert,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: millert
+sudoUser: millert
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: ALL
+sudoCommand: ALL
+sudoOrder: 5
+EOF
diff --git a/plugins/sudoers/regress/cvtsudoers/test29.out.ok b/plugins/sudoers/regress/cvtsudoers/test29.out.ok
new file mode 100644
index 0000000..c168898
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test29.out.ok
@@ -0,0 +1,4 @@
+Defaults log_output
+
+# sudoRole millert, millert2
+millert ALL = (ALL : ALL) ALL, NOPASSWD: ALL
diff --git a/plugins/sudoers/regress/cvtsudoers/test29.sh b/plugins/sudoers/regress/cvtsudoers/test29.sh
new file mode 100755
index 0000000..2cb50f3
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test29.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+#
+# Test LDAP sudoOrder when converting to sudoers.
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -i ldif -b "ou=SUDOers,dc=sudo,dc=ws" -f sudoers <<EOF
+dn: dc=sudo,dc=ws
+objectClass: dcObject
+objectClass: organization
+dc: courtesan
+o: Sudo World Headquarters
+description: Sudo World Headquarters
+
+# Organizational Role for Directory Manager
+dn: cn=Manager,dc=sudo,dc=ws
+objectClass: organizationalRole
+cn: Manager
+description: Directory Manager
+
+# SUDOers, sudo.ws
+dn: ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: organizationalUnit
+description: SUDO Configuration Subtree
+ou: SUDOers
+
+# defaults, SUDOers, sudo.ws
+dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: log_output
+
+# millert, SUDOers, sudo.ws
+dn: cn=millert,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: millert
+sudoUser: millert
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: ALL
+sudoCommand: ALL
+sudoOrder: 5
+
+# millert2, SUDOers, sudo.ws
+dn: cn=millert2,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: millert2
+sudoUser: millert
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: ALL
+sudoCommand: ALL
+sudoOption: !authenticate
+sudoOrder: 10
+EOF
diff --git a/plugins/sudoers/regress/cvtsudoers/test3.out.ok b/plugins/sudoers/regress/cvtsudoers/test3.out.ok
new file mode 100644
index 0000000..8a37975
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test3.out.ok
@@ -0,0 +1,7 @@
+Defaults syslog=auth
+Defaults>root !set_logname
+Defaults!PAGERS noexec
+
+Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less
+
+%wheel ALL = (ALL) ALL
diff --git a/plugins/sudoers/regress/cvtsudoers/test3.sh b/plugins/sudoers/regress/cvtsudoers/test3.sh
new file mode 100755
index 0000000..8e42cbc
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test3.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Test group and host filters
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -m group=wheel,host=blackhole $TESTDIR/sudoers
+
+exit 0
diff --git a/plugins/sudoers/regress/cvtsudoers/test30.out.ok b/plugins/sudoers/regress/cvtsudoers/test30.out.ok
new file mode 100644
index 0000000..009a54e
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test30.out.ok
@@ -0,0 +1,26 @@
+{
+ "User_Specs": [
+ {
+ "User_List": [
+ { "username": "user1" },
+ { "username": "user2" },
+ { "username": "user3" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "command": "/path/to/cmda" },
+ {
+ "command": "/path/to/cmdb",
+ "negated": true
+ },
+ { "command": "/path/to/cmdc" }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/cvtsudoers/test30.sh b/plugins/sudoers/regress/cvtsudoers/test30.sh
new file mode 100755
index 0000000..c5f7615
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test30.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Test alias expansion when converting to JSON.
+# See https://bugzilla.sudo.ws/show_bug.cgi?id=853
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -e -f json <<EOF
+Cmnd_Alias CMDA=/path/to/cmda
+Cmnd_Alias CMDB=/path/to/cmdb
+Cmnd_Alias CMDC=/path/to/cmdc
+User_Alias USERS=user1,user2,user3
+USERS ALL=CMDA,!CMDB,CMDC
+EOF
diff --git a/plugins/sudoers/regress/cvtsudoers/test31.conf b/plugins/sudoers/regress/cvtsudoers/test31.conf
new file mode 100644
index 0000000..345dbfc
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test31.conf
@@ -0,0 +1,9 @@
+defaults = all
+expand_aliases = no
+input_format = sudoers
+order_increment = 5
+order_padding = 2
+order_start = 1000
+output_format = ldif
+sudoers_base = ou=SUDOers,dc=my-domain,dc=com
+suppress = defaults
diff --git a/plugins/sudoers/regress/cvtsudoers/test31.out.ok b/plugins/sudoers/regress/cvtsudoers/test31.out.ok
new file mode 100644
index 0000000..41ffd1b
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test31.out.ok
@@ -0,0 +1,24 @@
+dn: cn=ALL,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: ALL
+sudoUser: ALL
+sudoHost: ALL
+sudoRunAsUser:
+sudoOption: !authenticate
+sudoCommand: /usr/bin/id
+sudoOrder: 100000
+
+dn: cn=FULLTIMERS,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: FULLTIMERS
+sudoUser: user1
+sudoUser: user2
+sudoUser: user3
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOrder: 100005
+
diff --git a/plugins/sudoers/regress/cvtsudoers/test31.sh b/plugins/sudoers/regress/cvtsudoers/test31.sh
new file mode 100755
index 0000000..38dd93c
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test31.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# Test cvtsudoers.conf with padding
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c $TESTDIR/test31.conf <<EOF
+Defaults authenticate, timestamp_timeout=0
+User_Alias FULLTIMERS = user1, user2, user3
+
+ALL ALL = (:) NOPASSWD:/usr/bin/id
+FULLTIMERS ALL = (ALL:ALL) ALL
+EOF
diff --git a/plugins/sudoers/regress/cvtsudoers/test32.err.ok b/plugins/sudoers/regress/cvtsudoers/test32.err.ok
new file mode 100644
index 0000000..c001436
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test32.err.ok
@@ -0,0 +1 @@
+cvtsudoers: too many sudoers entries, maximum 10
diff --git a/plugins/sudoers/regress/cvtsudoers/test32.out.ok b/plugins/sudoers/regress/cvtsudoers/test32.out.ok
new file mode 100644
index 0000000..9900199
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test32.out.ok
@@ -0,0 +1,119 @@
+dn: cn=user0,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: user0
+sudoUser: user0
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOrder: 10000
+
+dn: cn=user1,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: user1
+sudoUser: user1
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOrder: 10001
+
+dn: cn=user2,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: user2
+sudoUser: user2
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOrder: 10002
+
+dn: cn=user3,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: user3
+sudoUser: user3
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOrder: 10003
+
+dn: cn=user4,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: user4
+sudoUser: user4
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOrder: 10004
+
+dn: cn=user5,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: user5
+sudoUser: user5
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOrder: 10005
+
+dn: cn=user6,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: user6
+sudoUser: user6
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOrder: 10006
+
+dn: cn=user7,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: user7
+sudoUser: user7
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOrder: 10007
+
+dn: cn=user8,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: user8
+sudoUser: user8
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOrder: 10008
+
+dn: cn=user9,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: user9
+sudoUser: user9
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOrder: 10009
+
+dn: cn=user10,ou=SUDOers,dc=my-domain,dc=com
+objectClass: top
+objectClass: sudoRole
+cn: user10
+sudoUser: user10
+sudoHost: ALL
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoCommand: ALL
diff --git a/plugins/sudoers/regress/cvtsudoers/test32.sh b/plugins/sudoers/regress/cvtsudoers/test32.sh
new file mode 100755
index 0000000..2119da1
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test32.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Test cvtsudoers.conf with invalid padding
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -b "ou=SUDOers,dc=my-domain,dc=com" -O 1000 -P 1 <<EOF
+user0 ALL = (ALL:ALL) ALL
+user1 ALL = (ALL:ALL) ALL
+user2 ALL = (ALL:ALL) ALL
+user3 ALL = (ALL:ALL) ALL
+user4 ALL = (ALL:ALL) ALL
+user5 ALL = (ALL:ALL) ALL
+user6 ALL = (ALL:ALL) ALL
+user7 ALL = (ALL:ALL) ALL
+user8 ALL = (ALL:ALL) ALL
+user9 ALL = (ALL:ALL) ALL
+user10 ALL = (ALL:ALL) ALL
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/cvtsudoers/test33.out.ok b/plugins/sudoers/regress/cvtsudoers/test33.out.ok
new file mode 100644
index 0000000..6584701
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test33.out.ok
@@ -0,0 +1,7 @@
+Defaults log_output
+
+# sudoRole root
+root ALL = (ALL : ALL) NOPASSWD: ALL
+
+# sudoRole millert
+millert ALL = (ALL, !bin, !root : ALL, !wheel) ALL
diff --git a/plugins/sudoers/regress/cvtsudoers/test33.sh b/plugins/sudoers/regress/cvtsudoers/test33.sh
new file mode 100755
index 0000000..1fdd20d
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test33.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+#
+# Test LDAP negated sudoRunAsUser and sudoRunAsGroup converted to sudoers.
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -i ldif -b "ou=SUDOers,dc=sudo,dc=ws" -f sudoers <<EOF
+dn: dc=sudo,dc=ws
+objectClass: dcObject
+objectClass: organization
+dc: courtesan
+o: Sudo World Headquarters
+description: Sudo World Headquarters
+
+# Organizational Role for Directory Manager
+dn: cn=Manager,dc=sudo,dc=ws
+objectClass: organizationalRole
+cn: Manager
+description: Directory Manager
+
+# SUDOers, sudo.ws
+dn: ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: organizationalUnit
+description: SUDO Configuration Subtree
+ou: SUDOers
+
+# defaults, SUDOers, sudo.ws
+dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: log_output
+
+# root, SUDOers, sudo.ws
+dn: cn=root,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: root
+sudoUser: root
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoHost: ALL
+sudoCommand: ALL
+sudoOption: !authenticate
+
+# millert, SUDOers, sudo.ws
+dn: cn=millert,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: millert
+sudoUser: millert
+sudoRunAsUser: !bin
+sudoRunAsUser: !root
+sudoRunAsUser: ALL
+sudoRunAsGroup: ALL
+sudoRunAsGroup: !wheel
+sudoHost: ALL
+sudoCommand: ALL
+EOF
diff --git a/plugins/sudoers/regress/cvtsudoers/test34.out.ok b/plugins/sudoers/regress/cvtsudoers/test34.out.ok
new file mode 100644
index 0000000..6a3655e
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test34.out.ok
@@ -0,0 +1,18 @@
+Defaults log_output
+Defaults!/usr/bin/sudoreplay !log_output
+Defaults!/usr/local/bin/sudoreplay !log_output
+Defaults!REBOOT !log_output
+Defaults\
+ secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
+
+User_Alias ADMINS = millert, dowdy, mikef
+Cmnd_Alias PROCESSES = /usr/bin/nice, /bin/kill, /usr/bin/renice,\
+ /usr/bin/pkill, /usr/bin/top
+Cmnd_Alias REBOOT = /sbin/halt, /sbin/reboot, /sbin/poweroff
+Host_Alias WEBSERVERS = www1, www2, www3
+Host_Alias WEBSERVERS_1 = www1, www2, www3, www5
+Host_Alias WEBSERVERS_2 = www1, www2, www3, www4
+
+root ALL = (ALL) ALL
+
+ALL ALL = (ALL) /usr/bin/id
diff --git a/plugins/sudoers/regress/cvtsudoers/test34.sh b/plugins/sudoers/regress/cvtsudoers/test34.sh
new file mode 100755
index 0000000..d9f22e2
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test34.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+#
+# Test cvtsudoers merge
+# * three files, two bound to a host, one global
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -f sudoers -l /dev/null xerxes:${TESTDIR}/sudoers1 ${TESTDIR}/sudoers2 xyzzy:${TESTDIR}/sudoers3
diff --git a/plugins/sudoers/regress/cvtsudoers/test35.out.ok b/plugins/sudoers/regress/cvtsudoers/test35.out.ok
new file mode 100644
index 0000000..47ef832
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test35.out.ok
@@ -0,0 +1,18 @@
+Defaults@xerxes, xyzzy log_output
+Defaults!/usr/bin/sudoreplay !log_output
+Defaults!/usr/local/bin/sudoreplay !log_output
+Defaults!REBOOT !log_output
+Defaults\
+ secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
+
+User_Alias ADMINS = millert, dowdy, mikef
+Cmnd_Alias PROCESSES = /usr/bin/nice, /bin/kill, /usr/bin/renice,\
+ /usr/bin/pkill, /usr/bin/top
+Cmnd_Alias REBOOT = /sbin/halt, /sbin/reboot, /sbin/poweroff
+Host_Alias WEBSERVERS = www1, www2, www3
+Host_Alias WEBSERVERS_1 = www1, www2, www3, www5
+Host_Alias WEBSERVERS_2 = www1, www2, www3, www4
+
+root ALL = (ALL) ALL
+
+ALL ALL = (ALL) /usr/bin/id
diff --git a/plugins/sudoers/regress/cvtsudoers/test35.sh b/plugins/sudoers/regress/cvtsudoers/test35.sh
new file mode 100755
index 0000000..5c2cc1d
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test35.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+#
+# Test cvtsudoers merge
+# * three files, two bound to a host, one global
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -f sudoers -l /dev/null xerxes:${TESTDIR}/sudoers1 xyzzy:${TESTDIR}/sudoers2 ${TESTDIR}/sudoers3
diff --git a/plugins/sudoers/regress/cvtsudoers/test36.out.ok b/plugins/sudoers/regress/cvtsudoers/test36.out.ok
new file mode 100644
index 0000000..5c87fbc
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test36.out.ok
@@ -0,0 +1,17 @@
+Defaults\
+ secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
+Defaults log_output
+Defaults!/usr/bin/sudoreplay !log_output
+Defaults!/usr/local/bin/sudoreplay !log_output
+Defaults!REBOOT !log_output
+
+User_Alias ADMINS = millert, dowdy, mikef
+Cmnd_Alias PROCESSES = /usr/bin/nice, /bin/kill, /usr/bin/renice,\
+ /usr/bin/pkill, /usr/bin/top
+Cmnd_Alias REBOOT = /sbin/halt, /sbin/reboot, /sbin/poweroff
+Host_Alias WEBSERVERS = www1, www2, www3
+Host_Alias WEBSERVERS_1 = www1, www2, www3, www4
+
+root ALL = (ALL) ALL
+
+ALL ALL = (ALL) /usr/bin/id
diff --git a/plugins/sudoers/regress/cvtsudoers/test36.sh b/plugins/sudoers/regress/cvtsudoers/test36.sh
new file mode 100755
index 0000000..be02415
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test36.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+#
+# Test cvtsudoers merge
+# * three files, each bound to a host
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -f sudoers -l /dev/null xerxes:${TESTDIR}/sudoers1 xyzzy:${TESTDIR}/sudoers2 plugh:${TESTDIR}/sudoers2
diff --git a/plugins/sudoers/regress/cvtsudoers/test37.out.ok b/plugins/sudoers/regress/cvtsudoers/test37.out.ok
new file mode 100644
index 0000000..5c87fbc
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test37.out.ok
@@ -0,0 +1,17 @@
+Defaults\
+ secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
+Defaults log_output
+Defaults!/usr/bin/sudoreplay !log_output
+Defaults!/usr/local/bin/sudoreplay !log_output
+Defaults!REBOOT !log_output
+
+User_Alias ADMINS = millert, dowdy, mikef
+Cmnd_Alias PROCESSES = /usr/bin/nice, /bin/kill, /usr/bin/renice,\
+ /usr/bin/pkill, /usr/bin/top
+Cmnd_Alias REBOOT = /sbin/halt, /sbin/reboot, /sbin/poweroff
+Host_Alias WEBSERVERS = www1, www2, www3
+Host_Alias WEBSERVERS_1 = www1, www2, www3, www4
+
+root ALL = (ALL) ALL
+
+ALL ALL = (ALL) /usr/bin/id
diff --git a/plugins/sudoers/regress/cvtsudoers/test37.sh b/plugins/sudoers/regress/cvtsudoers/test37.sh
new file mode 100755
index 0000000..0f38b90
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test37.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Test cvtsudoers merge:
+# * two files, each bound to a host
+# * only difference is a conflicting WEBSERVERS definition
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -f sudoers -l /dev/null xerxes:${TESTDIR}/sudoers1 xyzzy:${TESTDIR}/sudoers2
diff --git a/plugins/sudoers/regress/cvtsudoers/test38.out.ok b/plugins/sudoers/regress/cvtsudoers/test38.out.ok
new file mode 100644
index 0000000..26ac014
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test38.out.ok
@@ -0,0 +1,14 @@
+Defaults@xerxes\
+ secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
+Defaults@xyzzy\
+ secure_path=/opt/sudo/bin\:/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
+
+User_Alias ADMINS = millert, dowdy, mikef
+Cmnd_Alias PROCESSES = /usr/bin/nice, /bin/kill, /usr/bin/renice,\
+ /usr/bin/pkill, /usr/bin/top
+Cmnd_Alias REBOOT = /sbin/halt, /sbin/reboot, /sbin/poweroff
+Host_Alias WEBSERVERS_1 = www1, www2, www3, www5
+
+root ALL = (ALL) ALL
+
+ALL ALL = (ALL) /usr/bin/id
diff --git a/plugins/sudoers/regress/cvtsudoers/test38.sh b/plugins/sudoers/regress/cvtsudoers/test38.sh
new file mode 100755
index 0000000..4273136
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test38.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Test cvtsudoers merge:
+# * two files, each bound to a host
+# * only difference is a conflicting secure_path definition
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -f sudoers -l /dev/null xerxes:${TESTDIR}/sudoers3 xyzzy:${TESTDIR}/sudoers4
diff --git a/plugins/sudoers/regress/cvtsudoers/test39.out.ok b/plugins/sudoers/regress/cvtsudoers/test39.out.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test39.out.ok
diff --git a/plugins/sudoers/regress/cvtsudoers/test39.sh b/plugins/sudoers/regress/cvtsudoers/test39.sh
new file mode 100755
index 0000000..8ece026
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test39.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+#
+# Test handling of a backslash at EOF with no trailing newline.
+#
+# If compiled with address sanitizer, cvtsudoers will crash without the
+# fix in ceaf706ab74b from https://github.com/sudo-project/sudo/pull/196.
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+printf 'dn: cn= Manager\\' | \
+ $CVTSUDOERS -c "" -b "ou=SUDOers,dc=sudo,dc=ws" -i ldif -f sudoers
diff --git a/plugins/sudoers/regress/cvtsudoers/test4.out.ok b/plugins/sudoers/regress/cvtsudoers/test4.out.ok
new file mode 100644
index 0000000..f8e7d2e
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test4.out.ok
@@ -0,0 +1,5 @@
+Defaults syslog=auth
+Defaults>root !set_logname
+Defaults!/usr/bin/more, /usr/bin/pg, /usr/bin/less noexec
+
+%wheel ALL = (ALL) ALL
diff --git a/plugins/sudoers/regress/cvtsudoers/test4.sh b/plugins/sudoers/regress/cvtsudoers/test4.sh
new file mode 100755
index 0000000..860eff4
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test4.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Test group and host filters, expanding aliases
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -e -m group=wheel,host=blackhole $TESTDIR/sudoers
+
+exit 0
diff --git a/plugins/sudoers/regress/cvtsudoers/test40.out.ok b/plugins/sudoers/regress/cvtsudoers/test40.out.ok
new file mode 100644
index 0000000..0fc19e4
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test40.out.ok
@@ -0,0 +1,10 @@
+dn: cn=user0,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user0
+sudoUser: user0
+sudoHost: A00
+sudoRunAsUser: 0
+sudoCommand: /bin/ls
+sudoOrder: 1
+
diff --git a/plugins/sudoers/regress/cvtsudoers/test40.sh b/plugins/sudoers/regress/cvtsudoers/test40.sh
new file mode 100755
index 0000000..ff03c2c
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test40.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# Test use-after-free in cvtsudoers when filtering by command.
+#
+# If compiled with address sanitizer, cvtsudoers will crash without the
+# fix in 9da99e0e671e.
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -i ldif -b "ou=SUDOers,dc=sudo,dc=ws" -m cmd='/bin/ls' -p <<EOF
+objectClass:sudoRole
+sudoUser:user0
+sudoHost:A00
+sudoCommand:/bin/ls
+sudoRunAs:0
+
+objectClass:sudoRole
+sudoUser:user0
+sudoHost:A00
+sudoRunAsUser:
+sudoCommand:
+
+objectClass:sudoRole
+sudoUser:user0
+sudoHost:A00
+sudoRunAs:
+sudoCommand:
+EOF
diff --git a/plugins/sudoers/regress/cvtsudoers/test5.out.ok b/plugins/sudoers/regress/cvtsudoers/test5.out.ok
new file mode 100644
index 0000000..d209fdf
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test5.out.ok
@@ -0,0 +1,6 @@
+Defaults syslog=auth
+Defaults>root !set_logname
+Defaults:FULLTIMERS !lecture
+Defaults:millert !authenticate
+Defaults@SERVERS log_year, logfile=/var/log/sudo.log
+Defaults!PAGERS noexec
diff --git a/plugins/sudoers/regress/cvtsudoers/test5.sh b/plugins/sudoers/regress/cvtsudoers/test5.sh
new file mode 100755
index 0000000..dd7782d
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test5.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Test defaults type filtering
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -s aliases,privileges -d all $TESTDIR/sudoers
+
+exit 0
diff --git a/plugins/sudoers/regress/cvtsudoers/test6.out.ok b/plugins/sudoers/regress/cvtsudoers/test6.out.ok
new file mode 100644
index 0000000..5e65e61
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test6.out.ok
@@ -0,0 +1 @@
+Defaults syslog=auth
diff --git a/plugins/sudoers/regress/cvtsudoers/test6.sh b/plugins/sudoers/regress/cvtsudoers/test6.sh
new file mode 100755
index 0000000..a6c7ec4
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test6.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Test global defaults filtering
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -s aliases,privileges -d global $TESTDIR/sudoers
+
+exit 0
diff --git a/plugins/sudoers/regress/cvtsudoers/test7.out.ok b/plugins/sudoers/regress/cvtsudoers/test7.out.ok
new file mode 100644
index 0000000..381de43
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test7.out.ok
@@ -0,0 +1,2 @@
+Defaults:FULLTIMERS !lecture
+Defaults:millert !authenticate
diff --git a/plugins/sudoers/regress/cvtsudoers/test7.sh b/plugins/sudoers/regress/cvtsudoers/test7.sh
new file mode 100755
index 0000000..2f1a301
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test7.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Test user defaults filtering
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -s aliases,privileges -d user $TESTDIR/sudoers
+
+exit 0
diff --git a/plugins/sudoers/regress/cvtsudoers/test8.out.ok b/plugins/sudoers/regress/cvtsudoers/test8.out.ok
new file mode 100644
index 0000000..7079ee0
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test8.out.ok
@@ -0,0 +1 @@
+Defaults>root !set_logname
diff --git a/plugins/sudoers/regress/cvtsudoers/test8.sh b/plugins/sudoers/regress/cvtsudoers/test8.sh
new file mode 100755
index 0000000..d00f90e
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test8.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Test runas defaults filtering
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -s aliases,privileges -d runas $TESTDIR/sudoers
+
+exit 0
diff --git a/plugins/sudoers/regress/cvtsudoers/test9.out.ok b/plugins/sudoers/regress/cvtsudoers/test9.out.ok
new file mode 100644
index 0000000..d2a39c4
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test9.out.ok
@@ -0,0 +1 @@
+Defaults@SERVERS log_year, logfile=/var/log/sudo.log
diff --git a/plugins/sudoers/regress/cvtsudoers/test9.sh b/plugins/sudoers/regress/cvtsudoers/test9.sh
new file mode 100755
index 0000000..b668e1f
--- /dev/null
+++ b/plugins/sudoers/regress/cvtsudoers/test9.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Test host defaults filtering
+#
+
+: ${CVTSUDOERS=cvtsudoers}
+
+$CVTSUDOERS -c "" -f sudoers -s aliases,privileges -d host $TESTDIR/sudoers
+
+exit 0
diff --git a/plugins/sudoers/regress/editor/check_editor.c b/plugins/sudoers/regress/editor/check_editor.c
new file mode 100644
index 0000000..65e00c0
--- /dev/null
+++ b/plugins/sudoers/regress/editor/check_editor.c
@@ -0,0 +1,174 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudoers.h>
+#include <def_data.c>
+
+/* Note hard-coded array lengths. */
+struct test_data {
+ const char *editor_var;
+ int nfiles;
+ const char *files[4];
+ const char *editor_path;
+ int edit_argc;
+ const char *edit_argv[10];
+} test_data[] = {
+ {
+ /* Bug #942 */
+ "SUDO_EDITOR=sh -c \"vi \\$1\"",
+ 1,
+ { "/etc/motd", NULL },
+ "/usr/bin/sh",
+ 5,
+ { "sh", "-c", "vi $1", "--", "/etc/motd", NULL }
+ },
+ {
+ /* Try connecting to the emacs server, falling back on plain emacs. */
+ "VISUAL=sh -c \"emacsclient -a emacs -n \\\"\\$@\\\" || emacs \\\"\\$@\\\"\"",
+ 1,
+ { "/etc/motd", NULL },
+ "/usr/bin/sh",
+ 5,
+ { "sh", "-c", "emacsclient -a emacs -n \"$@\" || emacs \"$@\"", "--", "/etc/motd", NULL }
+ },
+ {
+ /* GitHub issue #99 */
+ "EDITOR=/usr/bin/vi\\",
+ 1,
+ { "/etc/hosts", "/bogus/file", NULL },
+ "/usr/bin/vi\\",
+ 3,
+ { "/usr/bin/vi\\", "--", "/etc/hosts", "/bogus/file", NULL }
+ },
+ {
+ /* GitHub issue #179 */
+ "EDITOR=sed -rie s/^\\\\(foo\\\\)/waldo\\\\1/",
+ 1,
+ { "/etc/sudoers", NULL },
+ "/usr/bin/sed",
+ 5,
+ { "sed", "-rie", "s/^\\(foo\\)/waldo\\1/", "--", "/etc/sudoers", NULL }
+ },
+ { NULL }
+};
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/* STUB */
+int
+find_path(const char *infile, char **outfile, struct stat *sbp,
+ const char *path, bool ignore_dot, char * const *allowlist)
+{
+ if (infile[0] == '/') {
+ *outfile = strdup(infile);
+ } else {
+ if (asprintf(outfile, "/usr/bin/%s", infile) == -1)
+ *outfile = NULL;
+ }
+ if (*outfile == NULL)
+ return NOT_FOUND_ERROR;
+ return FOUND;
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct test_data *data;
+ int ch, ntests = 0, errors = 0;
+
+ initprogname(argc > 0 ? argv[0] : "check_editor");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignored */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ for (data = test_data; data->editor_var != NULL; data++) {
+ const char *env_editor = NULL;
+ char *cp, *editor_path, **edit_argv = NULL;
+ int i, edit_argc = 0;
+
+ /* clear existing editor environment vars */
+ putenv((char *)"VISUAL=");
+ putenv((char *)"EDITOR=");
+ putenv((char *)"SUDO_EDITOR=");
+
+ putenv((char *)data->editor_var);
+ editor_path = find_editor(data->nfiles, (char **)data->files,
+ &edit_argc, &edit_argv, NULL, &env_editor);
+ ntests++;
+ if (strcmp(editor_path, data->editor_path) != 0) {
+ sudo_warnx("test %d: editor_path: expected \"%s\", got \"%s\"",
+ ntests, data->editor_path, editor_path);
+ errors++;
+ }
+ ntests++;
+ cp = strchr(data->editor_var, '=') + 1;
+ if (strcmp(env_editor, cp) != 0) {
+ sudo_warnx("test %d: env_editor: expected \"%s\", got \"%s\"",
+ ntests, cp, env_editor ? env_editor : "(NULL)");
+ errors++;
+ }
+ ntests++;
+ if (edit_argc != data->edit_argc) {
+ sudo_warnx("test %d: edit_argc: expected %d, got %d",
+ ntests, data->edit_argc, edit_argc);
+ errors++;
+ } else {
+ ntests++;
+ for (i = 0; i < edit_argc; i++) {
+ if (strcmp(edit_argv[i], data->edit_argv[i]) != 0) {
+ sudo_warnx("test %d: edit_argv[%d]: expected \"%s\", got \"%s\"",
+ ntests, i, data->edit_argv[i], edit_argv[i]);
+ errors++;
+ break;
+ }
+ }
+ }
+
+ free(editor_path);
+ edit_argc -= data->nfiles + 1;
+ for (i = 0; i < edit_argc; i++) {
+ free(edit_argv[i]);
+ }
+ free(edit_argv);
+ }
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ exit(errors);
+}
diff --git a/plugins/sudoers/regress/env_match/check_env_pattern.c b/plugins/sudoers/regress/env_match/check_env_pattern.c
new file mode 100644
index 0000000..81649c1
--- /dev/null
+++ b/plugins/sudoers/regress/env_match/check_env_pattern.c
@@ -0,0 +1,96 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2017 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudoers.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+sudo_noreturn static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-v] [inputfile]\n", getprogname());
+ exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char *argv[])
+{
+ FILE *fp = stdin;
+ char pattern[1024], string[1024];
+ int ch, errors = 0, tests = 0, got, want;
+
+ initprogname(argc > 0 ? argv[0] : "check_env_pattern");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignored */
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0) {
+ if ((fp = fopen(argv[0], "r")) == NULL) {
+ perror(argv[0]);
+ return EXIT_FAILURE;
+ }
+ }
+
+ /*
+ * Read in test file, which is formatted thusly:
+ *
+ * pattern string 1/0
+ *
+ */
+ for (;;) {
+ bool full_match = false;
+
+ got = fscanf(fp, "%s %s %d\n", pattern, string, &want);
+ if (got == EOF)
+ break;
+ if (got == 3) {
+ got = matches_env_pattern(pattern, string, &full_match);
+ if (full_match)
+ got++;
+ if (got != want) {
+ fprintf(stderr,
+ "%s: %s %s: want %d, got %d\n",
+ getprogname(), pattern, string, want, got);
+ errors++;
+ }
+ tests++;
+ }
+ }
+ if (tests != 0) {
+ printf("%s: %d test%s run, %d errors, %d%% success rate\n",
+ getprogname(), tests, tests == 1 ? "" : "s", errors,
+ (tests - errors) * 100 / tests);
+ }
+ return errors;
+}
diff --git a/plugins/sudoers/regress/env_match/data b/plugins/sudoers/regress/env_match/data
new file mode 100644
index 0000000..ea28b1b
--- /dev/null
+++ b/plugins/sudoers/regress/env_match/data
@@ -0,0 +1,22 @@
+foo=(){false;} foo=(){false;} 2
+foo foo=(){false;} 1
+foo= foo=(){false;} 0
+foo=* foo=(){false;} 1
+foo=(* foo=(){false;} 2
+foo=()* foo=(){false;} 2
+foo=*()* foo=(){false;} 2
+foo() foo()=a 1
+foo*() foo()=b 1
+foo*()* foo()= 1
+foo()* foo()= 1
+foo* foo()= 1
+fo*o*() foo()= 1
+fo*o*() fooo()== 1
+fo*o*() foooo()= 1
+fo*o*() foooo 0
+MYPATH=*:/mydir:* MYPATH=/dir1/subdir1:/mydir:/dir2:/dir3/subdir2 2
+MYPATH=*:/mydir:** MYPATH=/dir1/subdir1:/mydir:/dir2:/dir3/subdir2 2
+MYPATH=*:/mdir:* MYPATH=/dir1/subdir1:/mydir:/dir2:/dir3/subdir2 0
+a*a*a*a*a*a* aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=b 1
+a*a*a*a*a*a*=b* aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=b 2
+a*a*a*a*a*a*=* aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=c 1
diff --git a/plugins/sudoers/regress/exptilde/check_exptilde.c b/plugins/sudoers/regress/exptilde/check_exptilde.c
new file mode 100644
index 0000000..6962a94
--- /dev/null
+++ b/plugins/sudoers/regress/exptilde/check_exptilde.c
@@ -0,0 +1,113 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudoers.h>
+
+#include <def_data.c>
+
+struct test_data {
+ const char *input;
+ const char *output;
+ const char *user;
+ bool result;
+} test_data[] = {
+ { "foo/bar", NULL, NULL, false },
+ { "~root", "/", NULL, true },
+ { "~", "/home/millert", "millert", true },
+ { "~/foo", "/home/millert/foo", "millert", true },
+ { "~millert", "/home/millert", "millert", true },
+ { "~millert/bar", "/home/millert/bar", "millert", true },
+ { NULL }
+};
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+int
+main(int argc, char *argv[])
+{
+ int ch, ntests = 0, errors = 0;
+ struct test_data *td;
+ struct passwd *pw;
+ char *path = NULL;
+ bool result;
+
+ initprogname(argc > 0 ? argv[0] : "check_exptilde");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignored */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* Prime the passwd cache */
+ pw = sudo_mkpwent("root", 0, 0, "/", "/bin/sh");
+ if (pw == NULL)
+ sudo_fatalx("unable to create passwd entry for root");
+ sudo_pw_delref(pw);
+
+ pw = sudo_mkpwent("millert", 8036, 20, "/home/millert", "/bin/tcsh");
+ if (pw == NULL)
+ sudo_fatalx("unable to create passwd entry for millert");
+ sudo_pw_delref(pw);
+
+ for (td = test_data; td->input != NULL; td++) {
+ ntests++;
+ if ((path = strdup(td->input)) == NULL)
+ sudo_fatal(NULL);
+ result = expand_tilde(&path, td->user);
+ if (result != td->result) {
+ errors++;
+ if (result) {
+ sudo_warnx("unexpected success: input %s, output %s",
+ td->input, path);
+ } else {
+ sudo_warnx("unexpected failure: input %s", td->input);
+ }
+ } else if (td->result && strcmp(path, td->output) != 0) {
+ errors++;
+ sudo_warnx("incorrect output for input %s: expected %s, got %s",
+ td->input, td->output, path);
+ }
+ free(path);
+ }
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
diff --git a/plugins/sudoers/regress/fuzz/fuzz_policy.c b/plugins/sudoers/regress/fuzz/fuzz_policy.c
new file mode 100644
index 0000000..0b01e4e
--- /dev/null
+++ b/plugins/sudoers/regress/fuzz/fuzz_policy.c
@@ -0,0 +1,932 @@
+/*
+ * Copyright (c) 2021-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <string.h>
+#ifndef HAVE_GETADDRINFO
+# include <compat/getaddrinfo.h>
+#endif
+
+#include <sudoers.h>
+#include <sudo_iolog.h>
+#include <interfaces.h>
+#include <timestamp.h>
+#include "auth/sudo_auth.h"
+
+extern char **environ;
+extern sudo_dso_public struct policy_plugin sudoers_policy;
+
+char *audit_msg;
+
+static int pass;
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+static FILE *
+open_data(const uint8_t *data, size_t size)
+{
+#ifdef HAVE_FMEMOPEN
+ /* Operate in-memory. */
+ return fmemopen((void *)data, size, "r");
+#else
+ char tempfile[] = "/tmp/sudoers.XXXXXX";
+ size_t nwritten;
+ int fd;
+
+ /* Use (unlinked) temporary file. */
+ fd = mkstemp(tempfile);
+ if (fd == -1)
+ return NULL;
+ unlink(tempfile);
+ nwritten = write(fd, data, size);
+ if (nwritten != size) {
+ close(fd);
+ return NULL;
+ }
+ lseek(fd, 0, SEEK_SET);
+ return fdopen(fd, "r");
+#endif
+}
+
+/*
+ * Array that gets resized as needed.
+ */
+struct dynamic_array {
+ char **entries;
+ size_t len;
+ size_t size;
+};
+
+static void
+free_strvec(char **vec)
+{
+ size_t i;
+
+ for (i = 0; vec[i] != NULL; i++)
+ free(vec[i]);
+}
+
+static void
+free_dynamic_array(struct dynamic_array *arr)
+{
+ if (arr->entries != NULL) {
+ free_strvec(arr->entries);
+ free(arr->entries);
+ }
+ memset(arr, 0, sizeof(*arr));
+}
+
+static bool
+push(struct dynamic_array *arr, const char *entry)
+{
+ char *copy = NULL;
+
+ if (entry != NULL) {
+ if ((copy = strdup(entry)) == NULL)
+ return false;
+ }
+
+ if (arr->len + (entry != NULL) >= arr->size) {
+ char **tmp = reallocarray(arr->entries, arr->size + 1024, sizeof(char *));
+ if (tmp == NULL) {
+ free(copy);
+ return false;
+ }
+ arr->entries = tmp;
+ arr->size += 1024;
+ }
+ if (copy != NULL)
+ arr->entries[arr->len++] = copy;
+ arr->entries[arr->len] = NULL;
+
+ return true;
+}
+
+static int
+fuzz_conversation(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
+{
+ int n;
+
+ for (n = 0; n < num_msgs; n++) {
+ const struct sudo_conv_message *msg = &msgs[n];
+
+ switch (msg->msg_type & 0xff) {
+ case SUDO_CONV_PROMPT_ECHO_ON:
+ case SUDO_CONV_PROMPT_MASK:
+ case SUDO_CONV_PROMPT_ECHO_OFF:
+ /* input not supported */
+ return -1;
+ case SUDO_CONV_ERROR_MSG:
+ case SUDO_CONV_INFO_MSG:
+ /* no output for fuzzers */
+ break;
+ default:
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+fuzz_printf(int msg_type, const char * restrict fmt, ...)
+{
+ return 0;
+}
+
+static int
+fuzz_hook_stub(struct sudo_hook *hook)
+{
+ return 0;
+}
+
+/*
+ * The fuzzing environment may not have DNS available, this may result
+ * in long delays that cause a timeout when fuzzing.
+ * This getaddrinfo() resolves every name as "localhost" (127.0.0.1).
+ */
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+/* Avoid compilation errors if getaddrinfo() or freeaddrinfo() are macros. */
+# undef getaddrinfo
+# undef freeaddrinfo
+
+int
+# ifdef HAVE_GETADDRINFO
+getaddrinfo(
+# else
+sudo_getaddrinfo(
+# endif
+ const char *nodename, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res)
+{
+ struct addrinfo *ai;
+ struct in_addr addr;
+ unsigned short port = 0;
+
+ /* Stub getaddrinfo(3) to avoid a DNS timeout in CIfuzz. */
+ if (servname == NULL) {
+ /* Must have either nodename or servname. */
+ if (nodename == NULL)
+ return EAI_NONAME;
+ } else {
+ struct servent *servent;
+ const char *errstr;
+
+ /* Parse servname as a port number or IPv4 TCP service name. */
+ port = sudo_strtonum(servname, 0, USHRT_MAX, &errstr);
+ if (errstr != NULL && errno == ERANGE)
+ return EAI_SERVICE;
+ if (hints != NULL && ISSET(hints->ai_flags, AI_NUMERICSERV))
+ return EAI_NONAME;
+ servent = getservbyname(servname, "tcp");
+ if (servent == NULL)
+ return EAI_NONAME;
+ port = htons(servent->s_port);
+ }
+
+ /* Hard-code IPv4 localhost for fuzzing. */
+ ai = calloc(1, sizeof(*ai) + sizeof(struct sockaddr_in));
+ if (ai == NULL)
+ return EAI_MEMORY;
+ ai->ai_canonname = strdup("localhost");
+ if (ai == NULL) {
+ free(ai);
+ return EAI_MEMORY;
+ }
+ ai->ai_family = AF_INET;
+ ai->ai_protocol = IPPROTO_TCP;
+ ai->ai_addrlen = sizeof(struct sockaddr_in);
+ ai->ai_addr = (struct sockaddr *)(ai + 1);
+ inet_pton(AF_INET, "127.0.0.1", &addr);
+ ((struct sockaddr_in *)ai->ai_addr)->sin_family = AF_INET;
+ ((struct sockaddr_in *)ai->ai_addr)->sin_addr = addr;
+ ((struct sockaddr_in *)ai->ai_addr)->sin_port = htons(port);
+ *res = ai;
+ return 0;
+}
+
+void
+# ifdef HAVE_GETADDRINFO
+freeaddrinfo(struct addrinfo *ai)
+# else
+sudo_freeaddrinfo(struct addrinfo *ai)
+# endif
+{
+ struct addrinfo *next;
+
+ while (ai != NULL) {
+ next = ai->ai_next;
+ free(ai->ai_canonname);
+ free(ai);
+ ai = next;
+ }
+}
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
+
+enum fuzz_policy_pass {
+ PASS_NONE,
+ PASS_VERSION,
+ PASS_CHECK_LOG_LOCAL,
+ PASS_CHECK_LOG_REMOTE,
+ PASS_CHECK_NOT_FOUND,
+ PASS_CHECK_NOT_FOUND_DOT,
+ PASS_LIST,
+ PASS_LIST_OTHER,
+ PASS_LIST_CHECK,
+ PASS_VALIDATE,
+ PASS_INVALIDATE
+};
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ struct dynamic_array plugin_args = { NULL };
+ struct dynamic_array settings = { NULL };
+ struct dynamic_array user_info = { NULL };
+ struct dynamic_array argv = { NULL };
+ struct dynamic_array env_add = { NULL };
+ char **command_info = NULL, **argv_out = NULL, **user_env_out = NULL;
+ const char *errstr = NULL;
+ const int num_passes = 10;
+ char *line = NULL;
+ size_t linesize = 0;
+ ssize_t linelen;
+ int res = 1;
+ FILE *fp;
+
+ fp = open_data(data, size);
+ if (fp == NULL)
+ return 0;
+
+ initprogname("fuzz_policy");
+ sudoers_debug_register(getprogname(), NULL);
+ if (getenv("SUDO_FUZZ_VERBOSE") == NULL)
+ sudo_warn_set_conversation(fuzz_conversation);
+
+ /* user_info and settings must be non-NULL (even if empty). */
+ push(&user_info, NULL);
+ push(&settings, NULL);
+
+ /* Iterate over each line of data. */
+ while ((linelen = getdelim(&line, &linesize, '\n', fp)) != -1) {
+ if (line[linelen - 1] == '\n')
+ line[linelen - 1] = '\0';
+
+ /* Skip comments and blank lines. */
+ if (line[0] == '#' || line[0] == '\0')
+ continue;
+
+ /* plugin args */
+ if (strncmp(line, "error_recovery=", sizeof("error_recovery=") - 1) == 0) {
+ push(&plugin_args, line);
+ continue;
+ }
+ if (strncmp(line, "sudoers_file=", sizeof("sudoers_file=") - 1) == 0) {
+ push(&plugin_args, line);
+ continue;
+ }
+ if (strncmp(line, "sudoers_mode=", sizeof("sudoers_mode=") - 1) == 0) {
+ push(&plugin_args, line);
+ continue;
+ }
+ if (strncmp(line, "sudoers_gid=", sizeof("sudoers_gid=") - 1) == 0) {
+ push(&plugin_args, line);
+ continue;
+ }
+ if (strncmp(line, "sudoers_uid=", sizeof("sudoers_uid=") - 1) == 0) {
+ push(&plugin_args, line);
+ continue;
+ }
+ if (strncmp(line, "ldap_conf=", sizeof("ldap_conf=") - 1) == 0) {
+ push(&plugin_args, line);
+ continue;
+ }
+ if (strncmp(line, "ldap_secret=", sizeof("ldap_secret=") - 1) == 0) {
+ push(&plugin_args, line);
+ continue;
+ }
+
+ /* user info */
+ if (strncmp(line, "user=", sizeof("user=") - 1) == 0) {
+ push(&user_info, line);
+ continue;
+ }
+ if (strncmp(line, "uid=", sizeof("uid=") - 1) == 0) {
+ push(&user_info, line);
+ continue;
+ }
+ if (strncmp(line, "gid=", sizeof("gid=") - 1) == 0) {
+ push(&user_info, line);
+ continue;
+ }
+ if (strncmp(line, "groups=", sizeof("groups=") - 1) == 0) {
+ push(&user_info, line);
+ continue;
+ }
+ if (strncmp(line, "cwd=", sizeof("cwd=") - 1) == 0) {
+ push(&user_info, line);
+ continue;
+ }
+ if (strncmp(line, "tty=", sizeof("tty=") - 1) == 0) {
+ push(&user_info, line);
+ continue;
+ }
+ if (strncmp(line, "host=", sizeof("host=") - 1) == 0) {
+ push(&user_info, line);
+ continue;
+ }
+ if (strncmp(line, "lines=", sizeof("lines=") - 1) == 0) {
+ push(&user_info, line);
+ continue;
+ }
+ if (strncmp(line, "cols=", sizeof("cols=") - 1) == 0) {
+ push(&user_info, line);
+ continue;
+ }
+ if (strncmp(line, "sid=", sizeof("sid=") - 1) == 0) {
+ push(&user_info, line);
+ continue;
+ }
+ if (strncmp(line, "umask=", sizeof("umask=") - 1) == 0) {
+ push(&user_info, line);
+ continue;
+ }
+ if (strncmp(line, "rlimit_", sizeof("rlimit_") - 1) == 0) {
+ push(&user_info, line);
+ continue;
+ }
+
+ /* First argv entry is the command, the rest are args. */
+ if (strncmp(line, "argv=", sizeof("argv=") - 1) == 0) {
+ push(&argv, line);
+ continue;
+ }
+
+ /* Additional environment variables to add. */
+ if (strncmp(line, "env=", sizeof("env=") - 1) == 0) {
+ const char *cp = line + sizeof("env=") - 1;
+ if (strchr(cp, '=') != NULL)
+ push(&env_add, cp);
+ continue;
+ }
+
+ /* Treat anything else as a setting. */
+ push(&settings, line);
+ }
+ fclose(fp);
+ free(line);
+ line = NULL;
+
+ /* Exercise code paths that use KRB5CCNAME and SUDO_PROMPT. */
+ putenv((char *)"KRB5CCNAME=/tmp/krb5cc_123456");
+ putenv((char *)"SUDO_PROMPT=[sudo] password for %p: ");
+
+ sudoers_policy.register_hooks(SUDO_API_VERSION, fuzz_hook_stub);
+
+ for (pass = 1; res == 1 && pass <= num_passes; pass++) {
+ /* Call policy open function */
+ res = sudoers_policy.open(SUDO_API_VERSION, fuzz_conversation,
+ fuzz_printf, settings.entries, user_info.entries, environ,
+ plugin_args.entries, &errstr);
+ if (res == 1) {
+ if (argv.len == 0) {
+ /* Must have a command to check. */
+ push(&argv, "/usr/bin/id");
+ }
+
+ switch (pass) {
+ case PASS_NONE:
+ break;
+ case PASS_VERSION:
+ /* sudo -V */
+ sudoers_policy.show_version(true);
+ break;
+ case PASS_CHECK_LOG_LOCAL: {
+ /* sudo command w/ local I/O logging (MODE_RUN) */
+ sudoers_policy.check_policy((int)argv.len, argv.entries,
+ env_add.entries, &command_info, &argv_out, &user_env_out,
+ &errstr);
+ /* call check_policy() again to check for leaks. */
+ sudoers_policy.check_policy((int)argv.len, argv.entries,
+ env_add.entries, &command_info, &argv_out, &user_env_out,
+ &errstr);
+ /* sudo_auth_begin_session() is stubbed out below. */
+ sudoers_policy.init_session(NULL, NULL, NULL);
+ break;
+ }
+ case PASS_CHECK_LOG_REMOTE:
+ /* sudo command w/ remote I/O logging (MODE_RUN) */
+ sudoers_policy.check_policy((int)argv.len, argv.entries,
+ env_add.entries, &command_info, &argv_out, &user_env_out,
+ &errstr);
+ /* call check_policy() again to check for leaks. */
+ sudoers_policy.check_policy((int)argv.len, argv.entries,
+ env_add.entries, &command_info, &argv_out, &user_env_out,
+ &errstr);
+ /* sudo_auth_begin_session() is stubbed out below. */
+ sudoers_policy.init_session(NULL, NULL, NULL);
+ break;
+ case PASS_CHECK_NOT_FOUND:
+ /* sudo command (not found) */
+ sudoers_policy.check_policy((int)argv.len, argv.entries,
+ env_add.entries, &command_info, &argv_out, &user_env_out,
+ &errstr);
+ /* sudo_auth_begin_session() is stubbed out below. */
+ sudoers_policy.init_session(NULL, NULL, NULL);
+ break;
+ case PASS_CHECK_NOT_FOUND_DOT:
+ /* sudo command (found but in cwd) */
+ sudoers_policy.check_policy((int)argv.len, argv.entries,
+ env_add.entries, &command_info, &argv_out, &user_env_out,
+ &errstr);
+ /* call check_policy() again to check for leaks. */
+ sudoers_policy.check_policy((int)argv.len, argv.entries,
+ env_add.entries, &command_info, &argv_out, &user_env_out,
+ &errstr);
+ /* sudo_auth_begin_session() is stubbed out below. */
+ sudoers_policy.init_session(NULL, NULL, NULL);
+ break;
+ case PASS_LIST:
+ /* sudo -l (MODE_LIST) */
+ sudoers_policy.list(0, NULL, false, NULL, &errstr);
+ /* call list() again to check for leaks. */
+ sudoers_policy.list(0, NULL, false, NULL, &errstr);
+ break;
+ case PASS_LIST_OTHER:
+ /* sudo -l -U root (MODE_LIST) */
+ sudoers_policy.list(0, NULL, false, "root", &errstr);
+ /* call list() again to check for leaks. */
+ sudoers_policy.list(0, NULL, false, "root", &errstr);
+ break;
+ case PASS_LIST_CHECK:
+ /* sudo -l command (MODE_CHECK) */
+ sudoers_policy.list((int)argv.len, argv.entries, false, NULL,
+ &errstr);
+ /* call list() again to check for leaks. */
+ sudoers_policy.list((int)argv.len, argv.entries, false, NULL,
+ &errstr);
+ break;
+ case PASS_VALIDATE:
+ /* sudo -v (MODE_VALIDATE) */
+ sudoers_policy.validate(&errstr);
+ /* call validate() again to check for leaks. */
+ sudoers_policy.validate(&errstr);
+ break;
+ case PASS_INVALIDATE:
+ /* sudo -k */
+ sudoers_policy.invalidate(false);
+ /* call invalidate() again to check for leaks. */
+ sudoers_policy.invalidate(false);
+ break;
+ }
+ }
+
+ /* Free resources. */
+ if (sudoers_policy.close != NULL)
+ sudoers_policy.close(0, 0);
+ else
+ sudoers_cleanup();
+ }
+
+ sudoers_policy.deregister_hooks(SUDO_API_VERSION, fuzz_hook_stub);
+
+ free_dynamic_array(&plugin_args);
+ free_dynamic_array(&settings);
+ free_dynamic_array(&user_info);
+ free_dynamic_array(&argv);
+ free_dynamic_array(&env_add);
+
+ sudoers_debug_deregister();
+
+ fflush(stdout);
+
+ return 0;
+}
+
+/* STUB */
+bool
+user_is_exempt(const struct sudoers_context *ctx)
+{
+ return false;
+}
+
+/* STUB */
+bool
+set_interfaces(const char *ai)
+{
+ return true;
+}
+
+/* STUB */
+void
+dump_interfaces(const char *ai)
+{
+ return;
+}
+
+/* STUB */
+void
+dump_auth_methods(void)
+{
+ return;
+}
+
+/* STUB */
+int
+sudo_auth_begin_session(const struct sudoers_context *ctx, struct passwd *pw,
+ char **user_env[])
+{
+ return 1;
+}
+
+/* STUB */
+int
+sudo_auth_end_session(void)
+{
+ return 1;
+}
+
+/* STUB */
+bool
+sudo_auth_needs_end_session(void)
+{
+ return false;
+}
+
+/* STUB */
+int
+timestamp_remove(const struct sudoers_context *ctx, bool unlink_it)
+{
+ return true;
+}
+
+/* STUB */
+int
+create_admin_success_flag(const struct sudoers_context *ctx)
+{
+ return true;
+}
+
+/* STUB */
+static int
+sudo_file_open(struct sudoers_context *ctx, struct sudo_nss *nss)
+{
+ return 0;
+}
+
+/* STUB */
+static int
+sudo_file_close(struct sudoers_context *ctx, struct sudo_nss *nss)
+{
+ return 0;
+}
+
+/* STUB */
+static struct sudoers_parse_tree *
+sudo_file_parse(struct sudoers_context *ctx, const struct sudo_nss *nss)
+{
+ static struct sudoers_parse_tree parse_tree;
+
+ return &parse_tree;
+}
+
+/* STUB */
+static int
+sudo_file_query(struct sudoers_context *ctx, const struct sudo_nss *nss,
+ struct passwd *pw)
+{
+ return 0;
+}
+
+/* STUB */
+static int
+sudo_file_getdefs(struct sudoers_context *ctx, const struct sudo_nss *nss)
+{
+ /* Set some Defaults */
+ set_default(ctx, "log_input", NULL, true, "sudoers", 1, 1, false);
+ set_default(ctx, "log_output", NULL, true, "sudoers", 1, 1, false);
+ set_default(ctx, "env_file", "/dev/null", true, "sudoers", 1, 1, false);
+ set_default(ctx, "restricted_env_file", "/dev/null", true, "sudoers", 1, 1, false);
+ set_default(ctx, "exempt_group", "sudo", true, "sudoers", 1, 1, false);
+ set_default(ctx, "runchroot", "/", true, "sudoers", 1, 1, false);
+ set_default(ctx, "runcwd", "~", true, "sudoers", 1, 1, false);
+ set_default(ctx, "fqdn", NULL, true, "sudoers", 1, 1, false);
+ set_default(ctx, "runas_default", "root", true, "sudoers", 1, 1, false);
+ set_default(ctx, "tty_tickets", NULL, true, "sudoers", 1, 1, false);
+ set_default(ctx, "umask", "022", true, "sudoers", 1, 1, false);
+ set_default(ctx, "logfile", "/var/log/sudo", true, "sudoers", 1, 1, false);
+ set_default(ctx, "syslog", "auth", true, "sudoers", 1, 1, false);
+ set_default(ctx, "syslog_goodpri", "notice", true, "sudoers", 1, 1, false);
+ set_default(ctx, "syslog_badpri", "alert", true, "sudoers", 1, 1, false);
+ set_default(ctx, "syslog_maxlen", "2048", true, "sudoers", 1, 1, false);
+ set_default(ctx, "loglinelen", "0", true, "sudoers", 1, 1, false);
+ set_default(ctx, "log_year", NULL, true, "sudoers", 1, 1, false);
+ set_default(ctx, "log_host", NULL, true, "sudoers", 1, 1, false);
+ set_default(ctx, "mailerpath", NULL, false, "sudoers", 1, 1, false);
+ set_default(ctx, "mailerflags", "-t", true, "sudoers", 1, 1, false);
+ set_default(ctx, "mailto", "root@localhost", true, "sudoers", 1, 1, false);
+ set_default(ctx, "mailfrom", "sudo@sudo.ws", true, "sudoers", 1, 1, false);
+ set_default(ctx, "mailsub", "Someone has been naughty on %h", true, "sudoers", 1, 1, false);
+ set_default(ctx, "timestampowner", "#0", true, "sudoers", 1, 1, false);
+ set_default(ctx, "compress_io", NULL, true, "sudoers", 1, 1, false);
+ set_default(ctx, "iolog_flush", NULL, true, "sudoers", 1, 1, false);
+ set_default(ctx, "iolog_flush", NULL, true, "sudoers", 1, 1, false);
+ set_default(ctx, "maxseq", "2176782336", true, "sudoers", 1, 1, false);
+ set_default(ctx, "sudoedit_checkdir", NULL, false, "sudoers", 1, 1, false);
+ set_default(ctx, "sudoedit_follow", NULL, true, "sudoers", 1, 1, false);
+ set_default(ctx, "ignore_iolog_errors", NULL, true, "sudoers", 1, 1, false);
+ set_default(ctx, "ignore_iolog_errors", NULL, true, "sudoers", 1, 1, false);
+ set_default(ctx, "noexec", NULL, true, "sudoers", 1, 1, false);
+ set_default(ctx, "exec_background", NULL, true, "sudoers", 1, 1, false);
+ set_default(ctx, "use_pty", NULL, true, "sudoers", 1, 1, false);
+ set_default(ctx, "utmp_runas", NULL, true, "sudoers", 1, 1, false);
+ set_default(ctx, "iolog_mode", "0640", true, "sudoers", 1, 1, false);
+ set_default(ctx, "iolog_user", NULL, false, "sudoers", 1, 1, false);
+ set_default(ctx, "iolog_group", NULL, false, "sudoers", 1, 1, false);
+ if (pass != PASS_CHECK_LOG_LOCAL) {
+ set_default(ctx, "log_servers", "localhost", true, "sudoers", 1, 1, false);
+ set_default(ctx, "log_server_timeout", "30", true, "sudoers", 1, 1, false);
+ set_default(ctx, "log_server_cabundle", "/etc/ssl/cacert.pem", true, "sudoers", 1, 1, false);
+ set_default(ctx, "log_server_peer_cert", "/etc/ssl/localhost.crt", true, "sudoers", 1, 1, false);
+ set_default(ctx, "log_server_peer_key", "/etc/ssl/private/localhost.key", true, "sudoers", 1, 1, false);
+ }
+
+ return 0;
+}
+
+static struct sudo_nss sudo_nss_file = {
+ { NULL, NULL },
+ "sudoers",
+ sudo_file_open,
+ sudo_file_close,
+ sudo_file_parse,
+ sudo_file_query,
+ sudo_file_getdefs
+};
+
+struct sudo_nss_list *
+sudo_read_nss(void)
+{
+ static struct sudo_nss_list snl = TAILQ_HEAD_INITIALIZER(snl);
+
+ if (TAILQ_EMPTY(&snl))
+ TAILQ_INSERT_TAIL(&snl, &sudo_nss_file, entries);
+
+ return &snl;
+}
+
+/* STUB */
+int
+check_user(struct sudoers_context *ctx, unsigned int validated,
+ unsigned int mode)
+{
+ return AUTH_SUCCESS;
+}
+
+/* STUB */
+int
+check_user_runchroot(const char *runchroot)
+{
+ return true;
+}
+
+/* STUB */
+int
+check_user_runcwd(const char *runcwd)
+{
+ return true;
+}
+
+/* STUB */
+void
+group_plugin_unload(void)
+{
+ return;
+}
+
+/* STUB */
+bool
+log_warning(const struct sudoers_context *ctx, unsigned int flags,
+ const char * restrict fmt, ...)
+{
+ return true;
+}
+
+/* STUB */
+bool
+log_warningx(const struct sudoers_context *ctx, unsigned int flags,
+ const char * restrict fmt, ...)
+{
+ return true;
+}
+
+/* STUB */
+bool
+gai_log_warning(const struct sudoers_context *ctx, unsigned int flags,
+ int errnum, const char * restrict fmt, ...)
+{
+ return true;
+}
+
+/* STUB */
+bool
+log_denial(const struct sudoers_context *ctx, unsigned int status,
+ bool inform_user)
+{
+ return true;
+}
+
+/* STUB */
+bool
+log_failure(const struct sudoers_context *ctx,unsigned int status, int flags)
+{
+ return true;
+}
+
+/* STUB */
+bool
+log_exit_status(const struct sudoers_context *ctx, int exit_status)
+{
+ return true;
+}
+
+/* STUB */
+bool
+mail_parse_errors(const struct sudoers_context *ctx)
+{
+ return true;
+}
+
+/* STUB */
+bool
+log_parse_error(const struct sudoers_context *ctx, const char *file,
+ int line, int column, const char * restrict fmt, va_list args)
+{
+ return true;
+}
+
+/* STUB */
+int
+audit_failure(const struct sudoers_context *ctx, char *const argv[],
+ char const * restrict const fmt, ...)
+{
+ return 0;
+}
+
+/* STUB */
+unsigned int
+sudoers_lookup(struct sudo_nss_list *snl, struct sudoers_context *ctx,
+ time_t now, sudoers_lookup_callback_fn_t callback, void *cb_data,
+ int *cmnd_status, int pwflag)
+{
+ return VALIDATE_SUCCESS;
+}
+
+/* STUB */
+int
+display_cmnd(struct sudoers_context *ctx, const struct sudo_nss_list *snl,
+ struct passwd *pw, int verbose)
+{
+ return true;
+}
+
+/* STUB */
+int
+display_privs(struct sudoers_context *ctx, const struct sudo_nss_list *snl,
+ struct passwd *pw, int verbose)
+{
+ return true;
+}
+
+/* STUB */
+int
+find_path(const char *infile, char **outfile, struct stat *sbp,
+ const char *path, bool ignore_dot, char * const *allowlist)
+{
+ switch (pass) {
+ case PASS_CHECK_NOT_FOUND:
+ return NOT_FOUND;
+ case PASS_CHECK_NOT_FOUND_DOT:
+ return NOT_FOUND_DOT;
+ default:
+ if (infile[0] == '/') {
+ *outfile = strdup(infile);
+ } else {
+ if (asprintf(outfile, "/usr/bin/%s", infile) == -1)
+ *outfile = NULL;
+ }
+ if (*outfile == NULL)
+ return NOT_FOUND_ERROR;
+ return FOUND;
+ }
+}
+
+/* STUB */
+int
+resolve_cmnd(struct sudoers_context *ctx, const char *infile, char **outfile,
+ const char *path)
+{
+ return find_path(infile, outfile, NULL, path, false, NULL);
+}
+
+/* STUB */
+bool
+expand_iolog_path(const char *inpath, char *path, size_t pathlen,
+ const struct iolog_path_escape *escapes, void *closure)
+{
+ return strlcpy(path, inpath, pathlen) < pathlen;
+}
+
+/* STUB */
+bool
+iolog_nextid(const char *iolog_dir, char sessid[7])
+{
+ strlcpy(sessid, "000001", 7);
+ return true;
+}
+
+/* STUB */
+bool
+cb_maxseq(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ return true;
+}
+
+/* STUB */
+bool
+cb_iolog_user(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ return true;
+}
+
+/* STUB */
+bool
+cb_iolog_group(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ return true;
+}
+
+/* STUB */
+bool
+cb_iolog_mode(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ return true;
+}
+
+/* STUB */
+bool
+cb_group_plugin(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ return true;
+}
+
+/* STUB */
+bool
+cb_timestampowner(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ return true;
+}
+
+/* STUB */
+void
+bsdauth_set_style(const char *style)
+{
+ return;
+}
diff --git a/plugins/sudoers/regress/fuzz/fuzz_policy.dict b/plugins/sudoers/regress/fuzz/fuzz_policy.dict
new file mode 100644
index 0000000..d00aeae
--- /dev/null
+++ b/plugins/sudoers/regress/fuzz/fuzz_policy.dict
@@ -0,0 +1,56 @@
+# Policy plugin keywords (all are keyword = value)
+
+# sudoers plugin options from sudo.conf
+"error_recovery"
+"sudoers_file"
+"sudoers_uid"
+"sudoers_gid"
+"sudoers_mode"
+"ldap_conf"
+"ldap_secret"
+
+# command line settings from front-end
+"closefrom"
+"cmnd_chroot"
+"cmnd_cwd"
+"runas_user"
+"runas_group"
+"prompt"
+"set_home"
+"preserve_environment"
+"run_shell"
+"login_shell"
+"implied_shell"
+"preserve_groups"
+"ignore_ticket"
+"update_ticket"
+"noninteractive"
+"sudoedit"
+"login_class"
+"intercept_setid"
+"intercept_ptrace"
+"selinux_role"
+"selinux_type"
+"apparmor_profile"
+"bsdauth_type"
+"network_addrs"
+"max_groups"
+"remote_host"
+"timeout"
+"askpass"
+"plugin_dir"
+"progname"
+
+# user information from front-end
+"user"
+"uid"
+"gid"
+"groups"
+"cwd"
+"tty"
+"host"
+"lines"
+"cols"
+"sid"
+"tcpgid"
+"umask"
diff --git a/plugins/sudoers/regress/fuzz/fuzz_stubs.c b/plugins/sudoers/regress/fuzz/fuzz_stubs.c
new file mode 100644
index 0000000..ce47bf5
--- /dev/null
+++ b/plugins/sudoers/regress/fuzz/fuzz_stubs.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <sys/socket.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <unistd.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#ifdef NEED_RESOLV_H
+# include <arpa/nameser.h>
+# include <resolv.h>
+#endif /* NEED_RESOLV_H */
+#include <netdb.h>
+
+#include <sudoers.h>
+#include <timestamp.h>
+#include <interfaces.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+struct interface_list *
+get_interfaces(void)
+{
+ static struct interface_list empty = SLIST_HEAD_INITIALIZER(interfaces);
+ return &empty;
+}
+
+void
+init_eventlog_config(void)
+{
+ return;
+}
+
+bool
+pivot_root(const char *new_root, struct sudoers_pivot *state)
+{
+ return true;
+}
+
+bool
+unpivot_root(struct sudoers_pivot *state)
+{
+ return true;
+}
+
+int
+group_plugin_query(const char *user, const char *group, const struct passwd *pw)
+{
+ return false;
+}
+
+bool
+set_perms(const struct sudoers_context *ctx, int perm)
+{
+ return true;
+}
+
+bool
+restore_perms(void)
+{
+ return true;
+}
+
+bool
+rewind_perms(void)
+{
+ return true;
+}
+
+bool
+sudo_nss_can_continue(const struct sudo_nss *nss, int match)
+{
+ return true;
+}
diff --git a/plugins/sudoers/regress/fuzz/fuzz_sudoers.c b/plugins/sudoers/regress/fuzz/fuzz_sudoers.c
new file mode 100644
index 0000000..e77634a
--- /dev/null
+++ b/plugins/sudoers/regress/fuzz/fuzz_sudoers.c
@@ -0,0 +1,419 @@
+/*
+ * Copyright (c) 2021-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <sys/socket.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <unistd.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#ifdef NEED_RESOLV_H
+# include <arpa/nameser.h>
+# include <resolv.h>
+#endif /* NEED_RESOLV_H */
+#include <netdb.h>
+
+#include <sudoers.h>
+#include <interfaces.h>
+
+static int fuzz_conversation(int num_msgs, const struct sudo_conv_message msgs[], struct sudo_conv_reply replies[], struct sudo_conv_callback *callback);
+static int fuzz_printf(int msg_type, const char * restrict fmt, ...);
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+/* For set_cmnd_path() */
+static const char *orig_cmnd;
+
+/* Required to link with parser. */
+sudo_conv_t sudo_conv = fuzz_conversation;
+sudo_printf_t sudo_printf = fuzz_printf;
+
+FILE *
+open_sudoers(const char *file, char **outfile, bool doedit, bool *keepopen)
+{
+ /*
+ * If we allow the fuzzer to choose include paths it will
+ * include random files in the file system.
+ * This leads to bug reports that cannot be reproduced.
+ */
+ return NULL;
+}
+
+static int
+fuzz_printf(int msg_type, const char * restrict fmt, ...)
+{
+ return 0;
+}
+
+static int
+fuzz_conversation(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
+{
+ int n;
+
+ for (n = 0; n < num_msgs; n++) {
+ const struct sudo_conv_message *msg = &msgs[n];
+
+ switch (msg->msg_type & 0xff) {
+ case SUDO_CONV_PROMPT_ECHO_ON:
+ case SUDO_CONV_PROMPT_MASK:
+ case SUDO_CONV_PROMPT_ECHO_OFF:
+ /* input not supported */
+ return -1;
+ case SUDO_CONV_ERROR_MSG:
+ case SUDO_CONV_INFO_MSG:
+ /* no output for fuzzers */
+ break;
+ default:
+ return -1;
+ }
+ }
+ return 0;
+}
+
+bool
+init_envtables(void)
+{
+ return true;
+}
+
+int
+set_cmnd_path(struct sudoers_context *ctx, const char *runchroot)
+{
+ /* Reallocate ctx->user.cmnd to catch bugs in command_matches(). */
+ char *new_cmnd = strdup(orig_cmnd);
+ if (new_cmnd == NULL)
+ return NOT_FOUND_ERROR;
+ free(ctx->user.cmnd);
+ ctx->user.cmnd = new_cmnd;
+ return FOUND;
+}
+
+/* STUB */
+bool
+mail_parse_errors(const struct sudoers_context *ctx)
+{
+ return true;
+}
+
+/* STUB */
+bool
+log_warningx(const struct sudoers_context *ctx, unsigned int flags,
+ const char * restrict fmt, ...)
+{
+ return true;
+}
+
+static int
+sudo_fuzz_query(struct sudoers_context *ctx, const struct sudo_nss *nss,
+ struct passwd *pw)
+{
+ return 0;
+}
+
+static int
+cb_unused(struct sudoers_parse_tree *parse_tree, struct alias *a, void *v)
+{
+ return 0;
+}
+
+bool
+cb_log_input(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ return 0;
+}
+
+bool
+cb_log_output(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ return 0;
+}
+
+static FILE *
+open_data(const uint8_t *data, size_t size)
+{
+#ifdef HAVE_FMEMOPEN
+ /* Operate in-memory. */
+ return fmemopen((void *)data, size, "r");
+#else
+ char tempfile[] = "/tmp/sudoers.XXXXXX";
+ size_t nwritten;
+ int fd;
+
+ /* Use (unlinked) temporary file. */
+ fd = mkstemp(tempfile);
+ if (fd == -1)
+ return NULL;
+ unlink(tempfile);
+ nwritten = write(fd, data, size);
+ if (nwritten != size) {
+ close(fd);
+ return NULL;
+ }
+ lseek(fd, 0, SEEK_SET);
+ return fdopen(fd, "r");
+#endif
+}
+
+static struct user_data {
+ const char *user;
+ const char *runuser;
+ const char *rungroup;
+} user_data[] = {
+ { "root", NULL, NULL },
+ { "millert", "operator", NULL },
+ { "millert", NULL, "wheel" },
+ { "operator", NULL, NULL },
+ { NULL }
+};
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ struct sudoers_context ctx = { { NULL } };
+ struct user_data *ud;
+ struct sudo_nss sudo_nss_fuzz;
+ struct sudo_nss_list snl = TAILQ_HEAD_INITIALIZER(snl);
+ struct sudoers_parse_tree parse_tree;
+ struct interface_list *interfaces;
+ struct passwd *pw;
+ struct group *gr;
+ const char *gids[10];
+ time_t now;
+ FILE *fp;
+
+ /* Don't waste time fuzzing tiny inputs. */
+ if (size < 5)
+ return 0;
+
+ fp = open_data(data, size);
+ if (fp == NULL)
+ return 0;
+
+ initprogname("fuzz_sudoers");
+ sudoers_debug_register(getprogname(), NULL);
+ if (getenv("SUDO_FUZZ_VERBOSE") == NULL)
+ sudo_warn_set_conversation(fuzz_conversation);
+
+ /* Sudoers locale setup. */
+ sudoers_initlocale(setlocale(LC_ALL, ""), "C");
+ sudo_warn_set_locale_func(sudoers_warn_setlocale);
+ bindtextdomain("sudoers", LOCALEDIR);
+ textdomain("sudoers");
+
+ /* Use the sudoers locale for everything. */
+ sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, NULL);
+
+ /* Prime the group cache */
+ gr = sudo_mkgrent("wheel", 0, "millert", "root", (char *)NULL);
+ if (gr == NULL)
+ goto done;
+ sudo_gr_delref(gr);
+
+ gr = sudo_mkgrent("operator", 5, "operator", "root", "millert", (char *)NULL);
+ if (gr == NULL)
+ goto done;
+ sudo_gr_delref(gr);
+
+ gr = sudo_mkgrent("staff", 20, "root", "millert", (char *)NULL);
+ if (gr == NULL)
+ goto done;
+ sudo_gr_delref(gr);
+
+ gr = sudo_mkgrent("sudo", 100, "root", "millert", (char *)NULL);
+ if (gr == NULL)
+ goto done;
+ sudo_gr_delref(gr);
+
+ /* Prime the passwd cache */
+ pw = sudo_mkpwent("root", 0, 0, "/", "/bin/sh");
+ if (pw == NULL)
+ goto done;
+ gids[0] = "0";
+ gids[1] = "20";
+ gids[2] = "5";
+ gids[3] = NULL;
+ if (sudo_set_gidlist(pw, -1, NULL, (char **)gids, ENTRY_TYPE_FRONTEND) == -1)
+ goto done;
+ sudo_pw_delref(pw);
+
+ pw = sudo_mkpwent("operator", 2, 5, "/operator", "/sbin/nologin");
+ if (pw == NULL)
+ goto done;
+ gids[0] = "5";
+ gids[1] = NULL;
+ if (sudo_set_gidlist(pw, -1, NULL, (char **)gids, ENTRY_TYPE_FRONTEND) == -1)
+ goto done;
+ sudo_pw_delref(pw);
+
+ pw = sudo_mkpwent("millert", 8036, 20, "/home/millert", "/bin/tcsh");
+ if (pw == NULL)
+ goto done;
+ gids[0] = "0";
+ gids[1] = "20";
+ gids[2] = "5";
+ gids[3] = "100";
+ gids[4] = NULL;
+ if (sudo_set_gidlist(pw, -1, NULL, (char **)gids, ENTRY_TYPE_FRONTEND) == -1)
+ goto done;
+ sudo_pw_delref(pw);
+
+ /* The minimum needed to perform matching. */
+ ctx.user.host = ctx.user.shost = strdup("localhost");
+ ctx.runas.host = ctx.runas.shost = strdup("localhost");
+ orig_cmnd = (char *)"/usr/bin/id";
+ ctx.user.cmnd = strdup(orig_cmnd);
+ ctx.user.cmnd_args = strdup("-u");
+ if (ctx.user.host == NULL || ctx.runas.host == NULL ||
+ ctx.user.cmnd == NULL || ctx.user.cmnd_args == NULL)
+ goto done;
+ ctx.user.cmnd_base = sudo_basename(ctx.user.cmnd);
+ time(&now);
+
+ /* Add a fake network interfaces. */
+ interfaces = get_interfaces();
+ if (SLIST_EMPTY(interfaces)) {
+ static struct interface interface;
+
+ interface.family = AF_INET;
+ inet_pton(AF_INET, "128.138.243.151", &interface.addr.ip4);
+ inet_pton(AF_INET, "255.255.255.0", &interface.netmask.ip4);
+ SLIST_INSERT_HEAD(interfaces, &interface, entries);
+ }
+
+ /* Only one sudoers source, the sudoers file itself. */
+ init_parse_tree(&parse_tree, NULL, NULL, &ctx, NULL);
+ memset(&sudo_nss_fuzz, 0, sizeof(sudo_nss_fuzz));
+ sudo_nss_fuzz.parse_tree = &parse_tree;
+ sudo_nss_fuzz.query = sudo_fuzz_query;
+ TAILQ_INSERT_TAIL(&snl, &sudo_nss_fuzz, entries);
+
+ /* Initialize defaults and parse sudoers. */
+ init_defaults();
+ init_parser(&ctx, "sudoers");
+ sudoersrestart(fp);
+ sudoersparse();
+ reparent_parse_tree(&parse_tree);
+
+ if (!parse_error) {
+ /* Match user/host/command against parsed policy. */
+ for (ud = user_data; ud->user != NULL; ud++) {
+ int cmnd_status;
+
+ /* Invoking user. */
+ free(ctx.user.name);
+ ctx.user.name = strdup(ud->user);
+ if (ctx.user.name == NULL)
+ goto done;
+ if (ctx.user.pw != NULL)
+ sudo_pw_delref(ctx.user.pw);
+ ctx.user.pw = sudo_getpwnam(ctx.user.name);
+ if (ctx.user.pw == NULL) {
+ sudo_warnx_nodebug("unknown user %s", ctx.user.name);
+ continue;
+ }
+
+ /* Run user. */
+ if (ctx.runas.pw != NULL)
+ sudo_pw_delref(ctx.runas.pw);
+ if (ud->runuser != NULL) {
+ ctx.runas.user = (char *)ud->runuser;
+ SET(ctx.settings.flags, RUNAS_USER_SPECIFIED);
+ ctx.runas.pw = sudo_getpwnam(ctx.runas.user);
+ } else {
+ ctx.runas.user = NULL;
+ CLR(ctx.settings.flags, RUNAS_USER_SPECIFIED);
+ ctx.runas.pw = sudo_getpwnam("root");
+ }
+ if (ctx.runas.pw == NULL) {
+ sudo_warnx_nodebug("unknown run user %s", ctx.runas.user);
+ continue;
+ }
+
+ /* Run group. */
+ if (ctx.runas.gr != NULL)
+ sudo_gr_delref(ctx.runas.gr);
+ if (ud->rungroup != NULL) {
+ ctx.runas.group = (char *)ud->rungroup;
+ SET(ctx.settings.flags, RUNAS_GROUP_SPECIFIED);
+ ctx.runas.gr = sudo_getgrnam(ctx.runas.group);
+ if (ctx.runas.gr == NULL) {
+ sudo_warnx_nodebug("unknown run group %s",
+ ctx.runas.group);
+ continue;
+ }
+ } else {
+ ctx.runas.group = NULL;
+ CLR(ctx.settings.flags, RUNAS_GROUP_SPECIFIED);
+ ctx.runas.gr = NULL;
+ }
+
+ update_defaults(&ctx, &parse_tree, NULL, SETDEF_ALL, false);
+
+ sudoers_lookup(&snl, &ctx, now, NULL, NULL, &cmnd_status,
+ false);
+
+ /* Match again as a pseudo-command (list, validate, etc). */
+ sudoers_lookup(&snl, &ctx, now, NULL, NULL, &cmnd_status,
+ true);
+
+ /* Display privileges. */
+ display_privs(&ctx, &snl, ctx.user.pw, false);
+ display_privs(&ctx, &snl, ctx.user.pw, true);
+ }
+
+ /* Expand tildes in runcwd and runchroot. */
+ if (ctx.runas.pw != NULL) {
+ if (def_runcwd != NULL && strcmp(def_runcwd, "*") != 0) {
+ expand_tilde(&def_runcwd, ctx.runas.pw->pw_name);
+ }
+ if (def_runchroot != NULL && strcmp(def_runchroot, "*") != 0) {
+ expand_tilde(&def_runchroot, ctx.runas.pw->pw_name);
+ }
+ }
+
+ /* Check Defaults and aliases. */
+ check_defaults(&parse_tree, false);
+ check_aliases(&parse_tree, true, false, cb_unused);
+ }
+
+done:
+ /* Cleanup. */
+ fclose(fp);
+ free_parse_tree(&parse_tree);
+ reset_parser();
+ sudoers_ctx_free(&ctx);
+ sudo_freepwcache();
+ sudo_freegrcache();
+ sudoers_setlocale(SUDOERS_LOCALE_USER, NULL);
+ sudoers_debug_deregister();
+ fflush(stdout);
+
+ return 0;
+}
diff --git a/plugins/sudoers/regress/fuzz/fuzz_sudoers.dict b/plugins/sudoers/regress/fuzz/fuzz_sudoers.dict
new file mode 100644
index 0000000..101e002
--- /dev/null
+++ b/plugins/sudoers/regress/fuzz/fuzz_sudoers.dict
@@ -0,0 +1,221 @@
+# Sudoers policy keywords (all are keyword = value)
+
+# Users and groups
+"root"
+"wheel"
+"staff"
+"sudo"
+
+# Aliases
+"Cmnd_Alias"
+"Cmd_Alias"
+"Host_Alias"
+"Runas_Alias"
+"User_Alias"
+
+# Special keywords
+"ALL"
+"(ALL:ALL)"
+"sudoedit"
+
+# Date_Spec
+"20170214083000Z"
+"2017021408Z"
+"20160315220000-0500"
+"20151201235900"
+
+# Timeout_Spec
+"7d8h30m10s"
+"14d"
+"8h30m"
+"600s"
+"3600"
+
+# Command digests
+"sha224:"
+"sha256:"
+"sha384:"
+"sha512:"
+
+# Command tags
+"NOPASSWD"
+"PASSWD"
+"NOEXEC"
+"EXEC"
+"SETENV"
+"NOSETENV"
+"LOG_INPUT"
+"NOLOG_INPUT"
+"LOG_OUTPUT"
+"NOLOG_OUTPUT"
+"FOLLOWLNK"
+"NOFOLLOWLNK"
+"MAIL"
+"NOMAIL"
+
+# Command options
+"CHROOT"
+"CWD"
+"CMND_TIMEOUT"
+"NOTBEFORE"
+"NOTAFTER"
+"ROLE"
+"TYPE"
+"APPARMOR_PROFILE"
+"PRIVS"
+"LIMITPRIVS"
+
+# Defaults settings
+"Defaults"
+"syslog"
+"syslog_goodpri"
+"syslog_badpri"
+"long_otp_prompt"
+"ignore_dot"
+"mail_always"
+"mail_badpass"
+"mail_no_user"
+"mail_no_host"
+"mail_no_perms"
+"mail_all_cmnds"
+"tty_tickets"
+"lecture"
+"lecture_file"
+"authenticate"
+"root_sudo"
+"log_host"
+"log_year"
+"shell_noargs"
+"set_home"
+"always_set_home"
+"path_info"
+"fqdn"
+"insults"
+"requiretty"
+"env_editor"
+"rootpw"
+"runaspw"
+"targetpw"
+"use_loginclass"
+"set_logname"
+"stay_setuid"
+"preserve_groups"
+"loglinelen"
+"timestamp_timeout"
+"passwd_timeout"
+"passwd_tries"
+"umask"
+"logfile"
+"mailerpath"
+"mailerflags"
+"mailto"
+"mailfrom"
+"mailsub"
+"badpass_message"
+"lecture_status_dir"
+"timestampdir"
+"timestampowner"
+"exempt_group"
+"passprompt"
+"passprompt_override"
+"runas_default"
+"secure_path"
+"editor"
+"listpw"
+"verifypw"
+"noexec"
+"ignore_local_sudoers"
+"closefrom"
+"closefrom_override"
+"setenv"
+"env_reset"
+"env_check"
+"env_delete"
+"env_keep"
+"role"
+"type"
+"apparmor_profile"
+"env_file"
+"restricted_env_file"
+"sudoers_locale"
+"visiblepw"
+"pwfeedback"
+"fast_glob"
+"umask_override"
+"log_input"
+"log_output"
+"compress_io"
+"use_pty"
+"group_plugin"
+"iolog_dir"
+"iolog_file"
+"set_utmp"
+"utmp_runas"
+"privs"
+"limitprivs"
+"exec_background"
+"pam_service"
+"pam_login_service"
+"pam_setcred"
+"pam_session"
+"pam_acct_mgmt"
+"maxseq"
+"use_netgroups"
+"sudoedit_checkdir"
+"sudoedit_follow"
+"always_query_group_plugin"
+"netgroup_tuple"
+"ignore_audit_errors"
+"ignore_iolog_errors"
+"ignore_logfile_errors"
+"match_group_by_gid"
+"syslog_maxlen"
+"iolog_user"
+"iolog_group"
+"iolog_mode"
+"fdexec"
+"ignore_unknown_defaults"
+"command_timeout"
+"user_command_timeouts"
+"iolog_flush"
+"syslog_pid"
+"timestamp_type"
+"authfail_message"
+"case_insensitive_user"
+"case_insensitive_group"
+"log_allowed"
+"log_denied"
+"log_servers"
+"log_server_timeout"
+"log_server_keepalive"
+"log_server_cabundle"
+"log_server_peer_cert"
+"log_server_peer_key"
+"log_server_verify"
+"runas_allow_unknown_id"
+"runas_check_shell"
+"pam_ruser"
+"pam_rhost"
+"runcwd"
+"runchroot"
+"log_format"
+"selinux"
+"admin_flag"
+"intercept"
+"log_subcmds"
+"log_exit_status"
+"intercept_authenticate"
+"intercept_allow_setid"
+"rlimit_as"
+"rlimit_core"
+"rlimit_cpu"
+"rlimit_data"
+"rlimit_fsize"
+"rlimit_locks"
+"rlimit_memlock"
+"rlimit_nofile"
+"rlimit_nproc"
+"rlimit_rss"
+"rlimit_stack"
+"log_passwords"
+"passprompt_regex"
diff --git a/plugins/sudoers/regress/fuzz/fuzz_sudoers.out.ok b/plugins/sudoers/regress/fuzz/fuzz_sudoers.out.ok
new file mode 100644
index 0000000..11f2ca8
--- /dev/null
+++ b/plugins/sudoers/regress/fuzz/fuzz_sudoers.out.ok
@@ -0,0 +1,577 @@
+Running: examples/sudoers
+Matching Defaults entries for root on localhost:
+ syslog=auth, runcwd=~
+
+Runas and Command-specific defaults for root:
+ Defaults>root !set_logname Defaults!/usr/bin/more, /usr/bin/pg, /usr/bin/less noexec
+
+
+User root may run the following commands on localhost:
+ (ALL) ALL
+ (ALL) ALL
+
+Matching Defaults entries for root on localhost:
+ syslog=auth, runcwd=~
+
+Runas and Command-specific defaults for root:
+ Defaults>root !set_logname Defaults!/usr/bin/more, /usr/bin/pg, /usr/bin/less noexec
+
+
+User root may run the following commands on localhost:
+
+Sudoers entry:
+ RunAsUsers: ALL
+ Commands:
+ ALL
+
+Sudoers entry:
+ RunAsUsers: ALL
+ Commands:
+ ALL
+
+Matching Defaults entries for millert on localhost:
+ syslog=auth, runcwd=~, !lecture, runchroot=*, !authenticate
+
+Runas and Command-specific defaults for millert:
+ Defaults>root !set_logname Defaults!/usr/bin/more, /usr/bin/pg, /usr/bin/less noexec
+
+
+User millert may run the following commands on localhost:
+ (ALL) ALL
+ (root) NOPASSWD: ALL
+
+Matching Defaults entries for millert on localhost:
+ syslog=auth, runcwd=~, !lecture, runchroot=*, !authenticate
+
+Runas and Command-specific defaults for millert:
+ Defaults>root !set_logname Defaults!/usr/bin/more, /usr/bin/pg, /usr/bin/less noexec
+
+
+User millert may run the following commands on localhost:
+
+Sudoers entry:
+ RunAsUsers: ALL
+ Commands:
+ ALL
+
+Sudoers entry:
+ RunAsUsers: root
+ Options: !authenticate
+ Commands:
+ ALL
+
+Matching Defaults entries for millert on localhost:
+ syslog=auth, runcwd=~, !lecture, runchroot=*, !authenticate
+
+Runas and Command-specific defaults for millert:
+ Defaults>root !set_logname Defaults!/usr/bin/more, /usr/bin/pg, /usr/bin/less noexec
+
+
+User millert may run the following commands on localhost:
+ (ALL) ALL
+ (root) NOPASSWD: ALL
+
+Matching Defaults entries for millert on localhost:
+ syslog=auth, runcwd=~, !lecture, runchroot=*, !authenticate
+
+Runas and Command-specific defaults for millert:
+ Defaults>root !set_logname Defaults!/usr/bin/more, /usr/bin/pg, /usr/bin/less noexec
+
+
+User millert may run the following commands on localhost:
+
+Sudoers entry:
+ RunAsUsers: ALL
+ Commands:
+ ALL
+
+Sudoers entry:
+ RunAsUsers: root
+ Options: !authenticate
+ Commands:
+ ALL
+
+Matching Defaults entries for operator on localhost:
+ syslog=auth, runcwd=~
+
+Runas and Command-specific defaults for operator:
+ Defaults>root !set_logname Defaults!/usr/bin/more, /usr/bin/pg, /usr/bin/less noexec
+
+
+User operator may run the following commands on localhost:
+ (root) /usr/sbin/dump, /usr/sbin/rdump, /usr/sbin/restore, /usr/sbin/rrestore, /usr/bin/mt, sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ== /home/operator/bin/start_backups, /usr/bin/kill, /usr/bin/top, /usr/sbin/shutdown, /usr/sbin/halt, /usr/sbin/reboot, /usr/sbin/lpc, /usr/bin/lprm, sudoedit /etc/printcap, /usr/oper/bin/
+
+Matching Defaults entries for operator on localhost:
+ syslog=auth, runcwd=~
+
+Runas and Command-specific defaults for operator:
+ Defaults>root !set_logname Defaults!/usr/bin/more, /usr/bin/pg, /usr/bin/less noexec
+
+
+User operator may run the following commands on localhost:
+
+Sudoers entry:
+ RunAsUsers: root
+ Commands:
+ /usr/sbin/dump
+ /usr/sbin/rdump
+ /usr/sbin/restore
+ /usr/sbin/rrestore
+ /usr/bin/mt
+ sha224:0GomF8mNN3wlDt1HD9XldjJ3SNgpFdbjO1+NsQ== /home/operator/bin/start_backups
+ /usr/bin/kill
+ /usr/bin/top
+ /usr/sbin/shutdown
+ /usr/sbin/halt
+ /usr/sbin/reboot
+ /usr/sbin/lpc
+ /usr/bin/lprm
+ sudoedit /etc/printcap
+ /usr/oper/bin/
+
+Executed examples/sudoers
+Running: regress/sudoers/test1.in
+User root is not allowed to run sudo on localhost.
+
+User root is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+Executed regress/sudoers/test1.in
+Running: regress/sudoers/test2.in
+User root is not allowed to run sudo on localhost.
+
+User root is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+Executed regress/sudoers/test2.in
+Running: regress/sudoers/test3.in
+User root is not allowed to run sudo on localhost.
+
+User root is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+Executed regress/sudoers/test3.in
+Running: regress/sudoers/test4.in
+sudoers:7:1: invalid line continuation
+User_Alias BAR = bar
+^~~~~~~~~~
+Executed regress/sudoers/test4.in
+Running: regress/sudoers/test5.in
+sudoers:2:19: empty string
+User_Alias FOO = ""
+ ^
+sudoers:3:2: empty string
+"" ALL = ALL
+ ^
+Executed regress/sudoers/test5.in
+Running: regress/sudoers/test6.in
+Runas and Command-specific defaults for root:
+ Defaults>#123 set_home
+ Defaults>#123 set_home
+
+
+User root may run the following commands on localhost:
+ (root) ALL
+ (#0 : #0) ALL
+ (root) ALL
+ (#0 : #0) ALL
+ (root) ALL
+ (root) ALL
+
+Runas and Command-specific defaults for root:
+ Defaults>#123 set_home
+ Defaults>#123 set_home
+
+
+User root may run the following commands on localhost:
+
+Sudoers entry:
+ RunAsUsers: root
+ Commands:
+ ALL
+
+Sudoers entry:
+ RunAsUsers: #0
+ RunAsGroups: #0
+ Commands:
+ ALL
+
+Sudoers entry:
+ RunAsUsers: root
+ Commands:
+ ALL
+
+Sudoers entry:
+ RunAsUsers: #0
+ RunAsGroups: #0
+ Commands:
+ ALL
+
+Sudoers entry:
+ RunAsUsers: root
+ Commands:
+ ALL
+
+Sudoers entry:
+ RunAsUsers: root
+ Commands:
+ ALL
+
+Runas and Command-specific defaults for millert:
+ Defaults>#123 set_home
+ Defaults>#123 set_home
+
+
+User millert may run the following commands on localhost:
+ (root) ALL
+ (root) ALL
+
+Runas and Command-specific defaults for millert:
+ Defaults>#123 set_home
+ Defaults>#123 set_home
+
+
+User millert may run the following commands on localhost:
+
+Sudoers entry:
+ RunAsUsers: root
+ Commands:
+ ALL
+
+Sudoers entry:
+ RunAsUsers: root
+ Commands:
+ ALL
+
+Runas and Command-specific defaults for millert:
+ Defaults>#123 set_home
+ Defaults>#123 set_home
+
+
+User millert may run the following commands on localhost:
+ (root) ALL
+ (root) ALL
+
+Runas and Command-specific defaults for millert:
+ Defaults>#123 set_home
+ Defaults>#123 set_home
+
+
+User millert may run the following commands on localhost:
+
+Sudoers entry:
+ RunAsUsers: root
+ Commands:
+ ALL
+
+Sudoers entry:
+ RunAsUsers: root
+ Commands:
+ ALL
+
+User operator is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+Executed regress/sudoers/test6.in
+Running: regress/sudoers/test7.in
+sudoers:2:21: empty group
+User_Alias FOO1 = "%"
+ ^
+sudoers:3:22: empty group
+User_Alias FOO2 = "%:"
+ ^
+sudoers:4:21: empty netgroup
+User_Alias FOO3 = "+"
+ ^
+sudoers:5:19: empty group
+User_Alias FOO4 = %
+ ^
+sudoers:6:19: empty group
+User_Alias FOO5 = %:
+ ^~
+sudoers:7:19: empty netgroup
+User_Alias FOO6 = +
+ ^
+Executed regress/sudoers/test7.in
+Running: regress/sudoers/test8.in
+sudoers:8:20: unexpected line break in string
+User_Alias UA4 = "x
+ ^
+Executed regress/sudoers/test8.in
+Running: regress/sudoers/test9.in
+Executed regress/sudoers/test9.in
+Running: regress/sudoers/test10.in
+Executed regress/sudoers/test10.in
+Running: regress/sudoers/test11.in
+sudoers:1:6: syntax error
+bogus
+ ^
+Executed regress/sudoers/test11.in
+Running: regress/sudoers/test12.in
+sudoers:1:17: syntax error
+user ALL = (ALL)
+ ^
+Executed regress/sudoers/test12.in
+Running: regress/sudoers/test13.in
+sudoers:1:17: syntax error
+user ALL = (ALL)
+ ^
+Executed regress/sudoers/test13.in
+Running: regress/sudoers/test14.in
+User root is not allowed to run sudo on localhost.
+
+User root is not allowed to run sudo on localhost.
+
+User millert may run the following commands on localhost:
+ (root) sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1, sha224:d7910e1967342b4605cb73a550944044c631cd3514001900966962ac /bin/ls, sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh, sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw /bin/kill
+
+User millert may run the following commands on localhost:
+
+Sudoers entry:
+ RunAsUsers: root
+ Commands:
+ sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1, sha224:d7910e1967342b4605cb73a550944044c631cd3514001900966962ac /bin/ls
+ sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh
+ sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw /bin/kill
+
+User millert may run the following commands on localhost:
+ (root) sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1, sha224:d7910e1967342b4605cb73a550944044c631cd3514001900966962ac /bin/ls, sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh, sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw /bin/kill
+
+User millert may run the following commands on localhost:
+
+Sudoers entry:
+ RunAsUsers: root
+ Commands:
+ sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1, sha224:d7910e1967342b4605cb73a550944044c631cd3514001900966962ac /bin/ls
+ sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh
+ sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw /bin/kill
+
+User operator may run the following commands on localhost:
+ (root) sha384:knMlCLkJ71K6uRrKo5C1CAvZ5kq+mRpjKDD/RofGosFjiGcYhiYYZORVyiRHgBnu, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= ALL
+
+User operator may run the following commands on localhost:
+
+Sudoers entry:
+ RunAsUsers: root
+ Commands:
+ sha384:knMlCLkJ71K6uRrKo5C1CAvZ5kq+mRpjKDD/RofGosFjiGcYhiYYZORVyiRHgBnu, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= ALL
+
+Executed regress/sudoers/test14.in
+Running: regress/sudoers/test15.in
+User root is not allowed to run sudo on localhost.
+
+User root is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+Executed regress/sudoers/test15.in
+Running: regress/sudoers/test16.in
+User root is not allowed to run sudo on localhost.
+
+User root is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+Executed regress/sudoers/test16.in
+Running: regress/sudoers/test17.in
+User root is not allowed to run sudo on localhost.
+
+User root is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+Executed regress/sudoers/test17.in
+Running: regress/sudoers/test18.in
+sudoers:4:21: invalid timeout value
+user0 ALL = TIMEOUT=7dd4h10m30s /usr/bin/id, /usr/bin/who, TIMEOUT=0 /bin/ls
+ ^~~~~~~~~~~
+sudoers:5:21: invalid timeout value
+user1 ALL = TIMEOUT=7d4h10mm30s /usr/bin/id
+ ^~~~~~~~~~~
+sudoers:6:21: invalid timeout value
+user2 ALL = TIMEOUT=4hg10m30s /usr/bin/id
+ ^~~~~~~~~
+sudoers:7:21: invalid timeout value
+user3 ALL = TIMEOUT=10m30ss /usr/bin/id
+ ^~~~~~~
+sudoers:8:21: invalid timeout value
+user4 ALL = TIMEOUT=14g /usr/bin/id
+ ^~~
+Executed regress/sudoers/test18.in
+Running: regress/sudoers/test19.in
+User root is not allowed to run sudo on localhost.
+
+User root is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+Executed regress/sudoers/test19.in
+Running: regress/sudoers/test20.in
+User root is not allowed to run sudo on localhost.
+
+User root is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+Executed regress/sudoers/test20.in
+Running: regress/sudoers/test21.in
+User root is not allowed to run sudo on localhost.
+
+User root is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+Executed regress/sudoers/test21.in
+Running: regress/sudoers/test22.in
+User root is not allowed to run sudo on localhost.
+
+User root is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+Executed regress/sudoers/test22.in
+Running: regress/sudoers/test23.in
+User root is not allowed to run sudo on localhost.
+
+User root is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+Executed regress/sudoers/test23.in
+Running: regress/sudoers/test24.in
+User root is not allowed to run sudo on localhost.
+
+User root is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User millert is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+User operator is not allowed to run sudo on localhost.
+
+Executed regress/sudoers/test24.in
+Running: regress/sudoers/test25.in
+sudoers:4:28: syntax error
+foo ALL = CWD=~ron /bin/ls \
+ ^~
+Executed regress/sudoers/test25.in
diff --git a/plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c b/plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c
new file mode 100644
index 0000000..9f9b394
--- /dev/null
+++ b/plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+
+#include <sudoers.h>
+
+static int fuzz_printf(int msg_type, const char * restrict fmt, ...);
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+/* Required to link with parser. */
+sudo_printf_t sudo_printf = fuzz_printf;
+
+FILE *
+open_sudoers(const char *file, char **outfile, bool doedit, bool *keepopen)
+{
+ /*
+ * If we allow the fuzzer to choose include paths it will
+ * include random files in the file system.
+ * This leads to bug reports that cannot be reproduced.
+ */
+ return NULL;
+}
+
+static int
+fuzz_printf(int msg_type, const char * restrict fmt, ...)
+{
+ return 0;
+}
+
+bool
+init_envtables(void)
+{
+ return true;
+}
+
+int
+set_cmnd_path(struct sudoers_context *ctx, const char *runchroot)
+{
+ /* Cannot return FOUND without also setting ctx->user.cmnd to a new value. */
+ return NOT_FOUND;
+}
+
+static FILE *
+open_data(const uint8_t *data, size_t size)
+{
+#ifdef HAVE_FMEMOPEN
+ /* Operate in-memory. */
+ return fmemopen((void *)data, size, "r");
+#else
+ char tempfile[] = "/tmp/ldif.XXXXXX";
+ size_t nwritten;
+ int fd;
+
+ /* Use (unlinked) temporary file. */
+ fd = mkstemp(tempfile);
+ if (fd == -1)
+ return NULL;
+ unlink(tempfile);
+ nwritten = write(fd, data, size);
+ if (nwritten != size) {
+ close(fd);
+ return NULL;
+ }
+ lseek(fd, 0, SEEK_SET);
+ return fdopen(fd, "r");
+#endif
+}
+
+static int
+fuzz_conversation(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
+{
+ int n;
+
+ for (n = 0; n < num_msgs; n++) {
+ const struct sudo_conv_message *msg = &msgs[n];
+
+ switch (msg->msg_type & 0xff) {
+ case SUDO_CONV_PROMPT_ECHO_ON:
+ case SUDO_CONV_PROMPT_MASK:
+ case SUDO_CONV_PROMPT_ECHO_OFF:
+ /* input not supported */
+ return -1;
+ case SUDO_CONV_ERROR_MSG:
+ case SUDO_CONV_INFO_MSG:
+ /* no output for fuzzers */
+ break;
+ default:
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ struct sudoers_context ctx = { { NULL } };
+ struct sudoers_parse_tree parse_tree;
+ FILE *fp;
+
+ /* Don't waste time fuzzing tiny inputs. */
+ if (size < 5)
+ return 0;
+
+ fp = open_data(data, size);
+ if (fp == NULL)
+ return 0;
+
+ initprogname("fuzz_sudoers_ldif");
+ sudoers_debug_register(getprogname(), NULL);
+ if (getenv("SUDO_FUZZ_VERBOSE") == NULL)
+ sudo_warn_set_conversation(fuzz_conversation);
+
+ /* Initialize defaults and parse LDIF-format sudoers. */
+ init_defaults();
+ init_parse_tree(&parse_tree, NULL, NULL, &ctx, NULL);
+ sudoers_parse_ldif(&parse_tree, fp, "ou=SUDOers,dc=sudo,dc=ws", true);
+
+ /* Cleanup. */
+ free_parse_tree(&parse_tree);
+ fclose(fp);
+ sudoers_debug_deregister();
+ fflush(stdout);
+
+ return 0;
+}
diff --git a/plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.dict b/plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.dict
new file mode 100644
index 0000000..7c4d2d0
--- /dev/null
+++ b/plugins/sudoers/regress/fuzz/fuzz_sudoers_ldif.dict
@@ -0,0 +1,14 @@
+# Sudoers LDIF attributes
+
+"description"
+"objectClass"
+"organizationalRole"
+"sudoCommand"
+"sudoHost"
+"sudoOption"
+"sudoOption"
+"sudoOrder"
+"sudoRunAs"
+"sudoRunAsGroup"
+"sudoRunAsUser"
+"sudoUser"
diff --git a/plugins/sudoers/regress/harness.in b/plugins/sudoers/regress/harness.in
new file mode 100755
index 0000000..9aa6e76
--- /dev/null
+++ b/plugins/sudoers/regress/harness.in
@@ -0,0 +1,217 @@
+#!/bin/sh
+#
+# Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# Simple test harness for sudoers tests.
+# usage: harness [-v] test_group [test_name ...]
+#
+srcdir="@abs_srcdir@"
+builddir="@abs_builddir@"
+SHELL=@SHELL@
+verbose=0
+rval=0
+ntests=0
+errors=0
+
+umask 022
+
+if [ "$1" = "-v" ]; then
+ verbose=1
+ shift
+fi
+
+if [ $# -eq 0 ]; then
+ echo "usage: harness test_group [test_name ...]" >&2
+ exit 1
+fi
+group="$1"
+shift
+srcdir=${srcdir%"/regress"}
+builddir=${builddir%"/regress"}
+
+if [ ! -d "$srcdir/regress/$group" ]; then
+ echo "missing test group: regress/$group" >&2
+ exit 1
+fi
+
+case "$group" in
+sudoers)
+ mkdir -p "$builddir/regress/$group"
+ if [ $# -eq 0 ]; then
+ tests=
+ for t in $srcdir/regress/$group/*.in; do
+ tests="$tests `basename $t .in`"
+ done
+ set -- $tests
+ fi
+ while [ $# -ne 0 ]; do
+ test="$1"
+ shift
+ in="$srcdir/regress/sudoers/${test}.in"
+ out="$builddir/regress/sudoers/${test}.out"
+ out_ok="$srcdir/regress/sudoers/${test}.out.ok"
+ toke="$builddir/regress/sudoers/${test}.toke"
+ toke_ok="$srcdir/regress/sudoers/${test}.toke.ok"
+ json="$builddir/regress/sudoers/${test}.json"
+ json_ok="$srcdir/regress/sudoers/${test}.json.ok"
+ ldif="$builddir/regress/sudoers/${test}.ldif"
+ ldif_ok="$srcdir/regress/sudoers/${test}.ldif.ok"
+ ldif2sudo="$builddir/regress/sudoers/${test}.ldif2sudo"
+ ldif2sudo_ok="$srcdir/regress/sudoers/${test}.ldif2sudo.ok"
+ sudo="$builddir/regress/sudoers/${test}.sudo"
+
+ $builddir/testsudoers -dt <$in >$out 2>$toke || true
+ ntests=`expr $ntests + 1`
+ if cmp $out $out_ok >/dev/null; then
+ if [ $verbose -eq 1 ]; then
+ echo "$group/$test (parse): OK"
+ fi
+ else
+ errors=`expr $errors + 1`
+ echo "$group/$test (parse): FAIL"
+ diff $out $out_ok || true
+ fi
+ ntests=`expr $ntests + 1`
+ if cmp $toke $toke_ok >/dev/null; then
+ if [ $verbose -eq 1 ]; then
+ echo "$group/$test (toke): OK"
+ fi
+ else
+ errors=`expr $errors + 1`
+ echo "$group/$test (toke): FAIL"
+ diff $toke $toke_ok || true
+ fi
+
+ $builddir/cvtsudoers -c "" -f json $in >$json 2>/dev/null || true
+ ntests=`expr $ntests + 1`
+ if cmp $json $json_ok >/dev/null; then
+ if [ $verbose -eq 1 ]; then
+ echo "$group/$test (json): OK"
+ fi
+ else
+ errors=`expr $errors + 1`
+ echo "$group/$test (json): FAIL"
+ diff $json $json_ok || true
+ fi
+
+ SUDOERS_BASE="ou=SUDOers,dc=sudo,dc=ws" \
+ $builddir/cvtsudoers -c "" -f ldif < $in >$ldif 2>/dev/null || true
+ ntests=`expr $ntests + 1`
+ if cmp $ldif $ldif_ok >/dev/null; then
+ if [ $verbose -eq 1 ]; then
+ echo "$group/$test (ldif): OK"
+ fi
+ else
+ errors=`expr $errors + 1`
+ echo "$group/$test: (ldif) FAIL"
+ diff $ldif $ldif_ok || true
+ fi
+
+ $builddir/cvtsudoers -c "" -f sudoers $in >$sudo 2>/dev/null || true
+ ntests=`expr $ntests + 1`
+ if $builddir/visudo -qcf $sudo; then
+ if [ $verbose -eq 1 ]; then
+ echo "$group/$test (reparse): OK"
+ fi
+ else
+ errors=`expr $errors + 1`
+ echo "$group/$test: (reparse) FAIL"
+ $builddir/visudo -cf $sudo || true
+ fi
+
+ if test -s $ldif_ok; then
+ $builddir/cvtsudoers -c "" -i ldif -f sudoers $ldif_ok >$ldif2sudo || true
+ ntests=`expr $ntests + 1`
+ if cmp $ldif2sudo $ldif2sudo_ok >/dev/null; then
+ if [ $verbose -eq 1 ]; then
+ echo "$group/$test (ldif2sudo): OK"
+ fi
+ else
+ errors=`expr $errors + 1`
+ echo "$group/$test: (ldif2sudo) FAIL"
+ diff $ldif $ldif_ok || true
+ fi
+ fi
+ done
+ ${AWK-awk} -v group=$group -v ntests=$ntests -v errors=$errors \
+ 'END {printf("%s: %d tests run, %d errors, %d%% success rate\n", group, ntests, errors, (ntests - errors) * 100 / ntests)}' < /dev/null
+ if test $errors -ne 0; then
+ rval=`expr $rval + $errors`
+ fi
+ ;;
+*)
+ TESTSUDOERS=$builddir/testsudoers; export TESTSUDOERS
+ VISUDO=$builddir/visudo; export VISUDO
+ CVTSUDOERS=$builddir/cvtsudoers; export CVTSUDOERS
+ mkdir -p "regress/$group"
+ if [ $# -eq 0 ]; then
+ tests=
+ for t in $srcdir/regress/$group/*.sh; do
+ tests="$tests `basename $t .sh`"
+ done
+ set -- $tests
+ fi
+ while [ $# -ne 0 ]; do
+ test="$1"
+ shift
+
+ cmd="$srcdir/regress/$group/${test}.sh"
+ out="$builddir/regress/$group/${test}.out"
+ out_ok="$srcdir/regress/$group/${test}.out.ok"
+ err="$builddir/regress/$group/${test}.err"
+ err_ok="$srcdir/regress/$group/${test}.err.ok"
+ status=0
+ TESTDIR=$srcdir/regress/$group $SHELL $cmd >$out 2>$err || status=$?
+ ntests=`expr $ntests + 1`
+ if cmp $out $out_ok >/dev/null; then
+ if test $status -eq 0; then
+ if [ $verbose -eq 1 ]; then
+ echo "$group/$test: OK"
+ fi
+ else
+ errors=`expr $errors + 1`
+ echo "$group/$test (exit $status): FAIL"
+ fi
+ else
+ errors=`expr $errors + 1`
+ echo "$group/$test: FAIL"
+ diff $out $out_ok || true
+ fi
+ ntests=`expr $ntests + 1`
+ if test -s $err_ok; then
+ if cmp $err $err_ok >/dev/null; then
+ if [ $verbose -eq 1 ]; then
+ echo "$group/$test (stderr): OK"
+ fi
+ else
+ errors=`expr $errors + 1`
+ echo "$group/$test (stderr): FAIL"
+ diff $err $err_ok || true
+ fi
+ elif test -s $err; then
+ errors=`expr $errors + 1`
+ echo "$group/$test (stderr): FAIL"
+ cat $err 1>&2
+ fi
+ done
+ ${AWK-awk} -v group=$group -v ntests=$ntests -v errors=$errors \
+ 'END {printf("%s: %d tests run, %d errors, %d%% success rate\n", group, ntests, errors, (ntests - errors) * 100 / ntests)}' < /dev/null
+ if test $errors -ne 0; then
+ rval=`expr $rval + $errors`
+ fi
+ ;;
+esac
+
+exit $rval
diff --git a/plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c b/plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c
new file mode 100644
index 0000000..991c30c
--- /dev/null
+++ b/plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c
@@ -0,0 +1,455 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2018-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudoers.h>
+#include <sudo_eventlog.h>
+#include <sudo_iolog.h>
+#include <sudo_plugin.h>
+
+#include <def_data.c> /* for iolog_path.c */
+
+extern struct io_plugin sudoers_io;
+
+sudo_printf_t sudo_printf;
+sudo_conv_t sudo_conv;
+struct sudo_plugin_event * (*plugin_event_alloc)(void);
+
+static struct sudoers_context io_ctx = SUDOERS_CONTEXT_INITIALIZER;
+
+sudo_dso_public int main(int argc, char *argv[], char *envp[]);
+
+sudo_noreturn static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-v] pathname\n", getprogname());
+ exit(EXIT_FAILURE);
+}
+
+static int
+sudo_printf_int(int msg_type, const char * restrict fmt, ...)
+{
+ va_list ap;
+ int len;
+
+ switch (msg_type) {
+ case SUDO_CONV_INFO_MSG:
+ va_start(ap, fmt);
+ len = vfprintf(stdout, fmt, ap);
+ va_end(ap);
+ break;
+ case SUDO_CONV_ERROR_MSG:
+ va_start(ap, fmt);
+ len = vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ break;
+ default:
+ len = -1;
+ errno = EINVAL;
+ break;
+ }
+
+ return len;
+}
+
+static bool
+validate_iolog_info(const char *log_dir, bool legacy)
+{
+ struct eventlog *evlog;
+ time_t now;
+
+ time(&now);
+
+ /* Parse log file. */
+ if ((evlog = iolog_parse_loginfo(-1, log_dir)) == NULL)
+ return false;
+
+ if (evlog->cwd == NULL || strcmp(evlog->cwd, "/") != 0) {
+ sudo_warnx("bad cwd: want \"/\", got \"%s\"",
+ evlog->cwd ? evlog->cwd : "NULL");
+ return false;
+ }
+
+ /* No host in the legacy log file. */
+ if (!legacy) {
+ if (evlog->submithost == NULL || strcmp(evlog->submithost, "localhost") != 0) {
+ sudo_warnx("bad host: want \"localhost\", got \"%s\"",
+ evlog->submithost ? evlog->submithost : "NULL");
+ return false;
+ }
+ }
+
+ if (evlog->submituser == NULL || strcmp(evlog->submituser, "nobody") != 0) {
+ sudo_warnx("bad user: want \"nobody\" got \"%s\"",
+ evlog->submituser ? evlog->submituser : "NULL");
+ return false;
+ }
+
+ if (evlog->runuser == NULL || strcmp(evlog->runuser, "root") != 0) {
+ sudo_warnx("bad runuser: want \"root\" got \"%s\"",
+ evlog->runuser ? evlog->runuser : "NULL");
+ return false;
+ }
+
+ /* No runas group specified, should be NULL. */
+ if (evlog->rungroup != NULL) {
+ sudo_warnx("bad rungroup: want \"\" got \"%s\"", evlog->rungroup);
+ return false;
+ }
+
+ if (evlog->ttyname == NULL || strcmp(evlog->ttyname, "/dev/console") != 0) {
+ sudo_warnx("bad tty: want \"/dev/console\" got \"%s\"",
+ evlog->ttyname ? evlog->ttyname : "NULL");
+ return false;
+ }
+
+ if (evlog->command == NULL || strcmp(evlog->command, "/usr/bin/id") != 0) {
+ sudo_warnx("bad command: want \"/usr/bin/id\" got \"%s\"",
+ evlog->command ? evlog->command : "NULL");
+ return false;
+ }
+
+ if (evlog->lines != 24) {
+ sudo_warnx("bad lines: want 24 got %d", evlog->lines);
+ return false;
+ }
+
+ if (evlog->columns != 80) {
+ sudo_warnx("bad columns: want 80 got %d", evlog->columns);
+ return false;
+ }
+
+ if (evlog->submit_time.tv_sec < now - 10 || evlog->submit_time.tv_sec > now + 10) {
+ sudo_warnx("bad submit_time: want %lld got %lld", (long long)now,
+ (long long)evlog->submit_time.tv_sec);
+ return false;
+ }
+
+ eventlog_free(evlog);
+
+ return true;
+}
+
+static bool
+validate_timing(FILE *fp, int recno, int type, unsigned int p1, unsigned int p2)
+{
+ struct timing_closure timing;
+ char buf[LINE_MAX];
+
+ if (!fgets(buf, sizeof(buf), fp)) {
+ sudo_warn("unable to read timing file");
+ return false;
+ }
+ buf[strcspn(buf, "\n")] = '\0';
+ if (!iolog_parse_timing(buf, &timing)) {
+ sudo_warnx("invalid timing file line: %s", buf);
+ return false;
+ }
+ if (timing.event != type) {
+ sudo_warnx("record %d: want type %d, got type %d", recno, type,
+ timing.event);
+ return false;
+ }
+ if (type == IO_EVENT_WINSIZE) {
+ if (timing.u.winsize.lines != (int)p1) {
+ sudo_warnx("record %d: want %u lines, got %u", recno, p1,
+ timing.u.winsize.lines);
+ return false;
+ }
+ if (timing.u.winsize.cols != (int)p2) {
+ sudo_warnx("record %d: want %u cols, got %u", recno, p2,
+ timing.u.winsize.cols);
+ return false;
+ }
+ } else {
+ if (timing.u.nbytes != p1) {
+ sudo_warnx("record %d: want len %u, got type %zu", recno, p1,
+ timing.u.nbytes);
+ return false;
+ }
+ }
+ if (timing.delay.tv_sec != 0) {
+ sudo_warnx("record %d: got excessive delay %lld.%09ld", recno,
+ (long long)timing.delay.tv_sec, timing.delay.tv_nsec);
+ return false;
+ }
+
+ return true;
+}
+
+
+/*
+ * Test sudoers I/O log plugin endpoints.
+ */
+static void
+test_endpoints(const struct sudoers_context *ctx, int *ntests, int *nerrors,
+ const char *iolog_dir, char *envp[])
+{
+ int rc, cmnd_argc = 1;
+ const char *errstr = NULL;
+ char buf[1024], iolog_path[PATH_MAX];
+ char runas_gid[64], runas_uid[64];
+ FILE *fp;
+ const char *cmnd_argv[] = {
+ "/usr/bin/id",
+ NULL
+ };
+ const char *user_info[] = {
+ "cols=80",
+ "lines=24",
+ "cwd=/",
+ "host=localhost",
+ "tty=/dev/console",
+ "user=nobody",
+ NULL
+ };
+ const char *command_info[] = {
+ "command=/usr/bin/id",
+ iolog_path,
+ "iolog_stdin=true",
+ "iolog_stdout=true",
+ "iolog_stderr=true",
+ "iolog_ttyin=true",
+ "iolog_ttyout=true",
+ "iolog_compress=false",
+ "iolog_mode=0644",
+ runas_gid,
+ runas_uid,
+ NULL
+ };
+ char *settings[] = {
+ NULL
+ };
+ const char output[] = "uid=0(root) gid=0(wheel)\r\n";
+ const unsigned int outlen = sizeof(output) - 1;
+
+ /* Set runas uid/gid to root. */
+ snprintf(runas_uid, sizeof(runas_uid), "runas_uid=%u",
+ (unsigned int)ctx->runas.pw->pw_uid);
+ snprintf(runas_gid, sizeof(runas_gid), "runas_gid=%u",
+ (unsigned int)ctx->runas.pw->pw_gid);
+
+ /* Set path to the iolog directory the user passed in. */
+ snprintf(iolog_path, sizeof(iolog_path), "iolog_path=%s", iolog_dir);
+
+ /* Test open endpoint. */
+ rc = sudoers_io.open(SUDO_API_VERSION, NULL, sudo_printf_int, settings,
+ (char **)user_info, (char **)command_info, cmnd_argc,
+ (char **)cmnd_argv, envp, NULL, &errstr);
+ (*ntests)++;
+ if (rc != 1) {
+ sudo_warnx("I/O log open endpoint failed");
+ (*nerrors)++;
+ return;
+ }
+
+ /* Test log_ttyout endpoint. */
+ rc = sudoers_io.log_ttyout(output, outlen, &errstr);
+ (*ntests)++;
+ if (rc != 1) {
+ sudo_warnx("I/O log_ttyout endpoint failed");
+ (*nerrors)++;
+ return;
+ }
+
+ /* Test change_winsize endpoint (twice). */
+ rc = sudoers_io.change_winsize(32, 128, &errstr);
+ (*ntests)++;
+ if (rc != 1) {
+ sudo_warnx("I/O change_winsize endpoint failed");
+ (*nerrors)++;
+ return;
+ }
+ rc = sudoers_io.change_winsize(24, 80, &errstr);
+ (*ntests)++;
+ if (rc != 1) {
+ sudo_warnx("I/O change_winsize endpoint failed");
+ (*nerrors)++;
+ return;
+ }
+
+ /* Close the plugin. */
+ sudoers_io.close(0, 0);
+
+ /* Validate I/O log info file (json). */
+ (*ntests)++;
+ if (!validate_iolog_info(iolog_dir, false))
+ (*nerrors)++;
+
+ /* Validate I/O log info file (legacy). */
+ snprintf(iolog_path, sizeof(iolog_path), "%s/log.json", iolog_dir);
+ unlink(iolog_path);
+ (*ntests)++;
+ if (!validate_iolog_info(iolog_dir, true))
+ (*nerrors)++;
+
+ /* Validate the timing file. */
+ snprintf(iolog_path, sizeof(iolog_path), "%s/timing", iolog_dir);
+ (*ntests)++;
+ if ((fp = fopen(iolog_path, "r")) == NULL) {
+ sudo_warn("unable to open %s", iolog_path);
+ (*nerrors)++;
+ return;
+ }
+
+ /* Line 1: output of id command. */
+ if (!validate_timing(fp, 1, IO_EVENT_TTYOUT, outlen, 0)) {
+ (*nerrors)++;
+ return;
+ }
+
+ /* Line 2: window size change. */
+ if (!validate_timing(fp, 2, IO_EVENT_WINSIZE, 32, 128)) {
+ (*nerrors)++;
+ return;
+ }
+
+ /* Line 3: window size change. */
+ if (!validate_timing(fp, 3, IO_EVENT_WINSIZE, 24, 80)) {
+ (*nerrors)++;
+ return;
+ }
+
+ /* Validate ttyout log file. */
+ snprintf(iolog_path, sizeof(iolog_path), "%s/ttyout", iolog_dir);
+ (*ntests)++;
+ fclose(fp);
+ if ((fp = fopen(iolog_path, "r")) == NULL) {
+ sudo_warn("unable to open %s", iolog_path);
+ (*nerrors)++;
+ return;
+ }
+ if (!fgets(buf, sizeof(buf), fp)) {
+ sudo_warn("unable to read %s", iolog_path);
+ (*nerrors)++;
+ return;
+ }
+ if (strcmp(buf, output) != 0) {
+ sudo_warnx("ttylog mismatch: want \"%s\", got \"%s\"", output, buf);
+ (*nerrors)++;
+ return;
+ }
+}
+
+int
+main(int argc, char *argv[], char *envp[])
+{
+ struct passwd *tpw;
+ int ch, tests = 0, errors = 0;
+ const char *iolog_dir;
+
+ initprogname(argc > 0 ? argv[0] : "check_iolog_plugin");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignored */
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1)
+ usage();
+ iolog_dir = argv[0];
+
+ /* Set runas user. */
+ if ((tpw = getpwuid(0)) == NULL) {
+ if ((tpw = getpwnam("root")) == NULL)
+ sudo_fatalx("unable to look up uid 0 or root");
+ }
+ io_ctx.runas.pw = pw_dup(tpw);
+
+ /* Set invoking user. */
+ if ((tpw = getpwuid(geteuid())) == NULL)
+ sudo_fatalx("unable to look up invoking user's uid");
+ io_ctx.user.pw = pw_dup(tpw);
+
+ /* Set iolog uid/gid to invoking user. */
+ iolog_set_owner(io_ctx.user.pw->pw_uid, io_ctx.user.pw->pw_gid);
+
+ test_endpoints(&io_ctx, &tests, &errors, iolog_dir, envp);
+
+ if (tests != 0) {
+ printf("check_iolog_plugin: %d test%s run, %d errors, %d%% success rate\n",
+ tests, tests == 1 ? "" : "s", errors,
+ (tests - errors) * 100 / tests);
+ }
+
+ exit(errors);
+}
+
+/* Stub functions */
+
+bool
+set_perms(const struct sudoers_context *ctx, int perm)
+{
+ return true;
+}
+
+bool
+restore_perms(void)
+{
+ return true;
+}
+
+bool
+log_warning(const struct sudoers_context *ctx, unsigned int flags,
+ const char * restrict fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ sudo_vwarn_nodebug(fmt, ap);
+ va_end(ap);
+
+ return true;
+}
+
+bool
+log_warningx(const struct sudoers_context *ctx, unsigned int flags,
+ const char * restrict fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ sudo_vwarnx_nodebug(fmt, ap);
+ va_end(ap);
+
+ return true;
+}
+
+const struct sudoers_context *
+sudoers_get_context(void)
+{
+ return &io_ctx;
+}
diff --git a/plugins/sudoers/regress/parser/check_addr.c b/plugins/sudoers/regress/parser/check_addr.c
new file mode 100644
index 0000000..3db53c6
--- /dev/null
+++ b/plugins/sudoers/regress/parser/check_addr.c
@@ -0,0 +1,152 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011-2013 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudoers.h>
+#include <interfaces.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+static int
+check_addr(char *input)
+{
+ int expected, matched;
+ const char *errstr;
+ size_t len;
+ char *cp;
+
+ while (isspace((unsigned char)*input))
+ input++;
+
+ /* input: "addr[/mask] 1/0" */
+ len = strcspn(input, " \t");
+ cp = input + len;
+ while (isspace((unsigned char)*cp))
+ cp++;
+ expected = (int)sudo_strtonum(cp, 0, 1, &errstr);
+ if (errstr != NULL)
+ sudo_fatalx("expecting 0 or 1, got %s", cp);
+ input[len] = '\0';
+
+ matched = addr_matches(input) == ALLOW;
+ if (matched != expected) {
+ sudo_warnx("%s %smatched: FAIL", input, matched ? "" : "not ");
+ return 1;
+ }
+ return 0;
+}
+
+sudo_noreturn static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-v] datafile\n", getprogname());
+ exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch, ntests = 0, errors = 0;
+ char *cp, line[2048];
+ size_t len;
+ FILE *fp;
+
+ initprogname(argc > 0 ? argv[0] : "check_addr");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignored */
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1)
+ usage();
+
+ fp = fopen(argv[0], "r");
+ if (fp == NULL)
+ sudo_fatalx("unable to open %s", argv[0]);
+
+ /*
+ * Input is in the following format. There are two types of
+ * lines: interfaces, which sets the address and mask of the
+ * locally connected ethernet interfaces for the lines that
+ * follow and, address lines that include and address (with
+ * optional netmask) to match, followed by expected match status
+ * (1 or 0). E.g.
+ *
+ * interfaces: addr1/mask addr2/mask ...
+ * address: addr[/mask] 1/0
+ * address: addr[/mask] 1/0
+ * interfaces: addr3/mask addr4/mask ...
+ * address: addr[/mask] 1/0
+ */
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ len = strcspn(line, "\n");
+ line[len] = '\0';
+
+ /* Ignore comments */
+ if ((cp = strchr(line, '#')) != NULL)
+ *cp = '\0';
+
+ /* Skip blank lines. */
+ if (line[0] == '\0')
+ continue;
+
+ if (strncmp(line, "interfaces:", sizeof("interfaces:") - 1) == 0) {
+ if (!set_interfaces(line + sizeof("interfaces:") - 1)) {
+ sudo_warn("unable to parse interfaces list");
+ errors++;
+ }
+ } else if (strncmp(line, "address:", sizeof("address:") - 1) == 0) {
+ errors += check_addr(line + sizeof("address:") - 1);
+ ntests++;
+ } else {
+ sudo_warnx("unexpected data line: %s", line);
+ continue;
+ }
+ }
+
+ if (ntests != 0) {
+ printf("check_addr: %d tests run, %d errors, %d%% success rate\n",
+ ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ exit(errors);
+}
diff --git a/plugins/sudoers/regress/parser/check_addr.in b/plugins/sudoers/regress/parser/check_addr.in
new file mode 100644
index 0000000..a3c8612
--- /dev/null
+++ b/plugins/sudoers/regress/parser/check_addr.in
@@ -0,0 +1,13 @@
+#
+interfaces: 10.5.54.73/255.255.240.0
+address: 10.5.48.0 1
+address: 10.5.54.0/20 1
+#
+interfaces: 128.138.243.151/255.255.255.0 128.138.241.53/255.255.255.0
+address: 128.138.243.0 1
+address: 128.138.243.0/24 1
+address: 128.138.241.0 1
+address: 128.138.241.0/24 1
+address: 128.138.242.0/24 0
+address: 128.138.0.0 0
+address: 128.138.0.0/16 1
diff --git a/plugins/sudoers/regress/parser/check_base64.c b/plugins/sudoers/regress/parser/check_base64.c
new file mode 100644
index 0000000..4fe54ad
--- /dev/null
+++ b/plugins/sudoers/regress/parser/check_base64.c
@@ -0,0 +1,130 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+/* From parse.h */
+extern size_t base64_decode(const char *str, unsigned char *dst, size_t dsize);
+extern size_t base64_encode(const unsigned char *in, size_t in_len, char *out, size_t out_len);
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+static unsigned char bstring1[] = { 0xea, 0xb8, 0xa2, 0x71, 0xef, 0x67, 0xc1, 0xcd, 0x0d, 0xd9, 0xa6, 0xaa, 0xa8, 0x24, 0x77, 0x2a, 0xfc, 0x6f, 0x76, 0x37, 0x1b, 0xed, 0x9e, 0x1a, 0x90, 0x5f, 0xcf, 0xbc, 0x00 };
+
+struct base64_test {
+ const char *ascii;
+ const char *encoded;
+} test_strings[] = {
+ {
+ (char *)bstring1,
+ "6riice9nwc0N2aaqqCR3Kvxvdjcb7Z4akF/PvA=="
+ },
+ {
+ "any carnal pleasure.",
+ "YW55IGNhcm5hbCBwbGVhc3VyZS4="
+ },
+ {
+ "any carnal pleasure",
+ "YW55IGNhcm5hbCBwbGVhc3VyZQ=="
+ },
+ {
+ "any carnal pleasur",
+ "YW55IGNhcm5hbCBwbGVhc3Vy"
+ },
+ {
+ "any carnal pleasu",
+ "YW55IGNhcm5hbCBwbGVhc3U="
+ },
+ {
+ "any carnal pleas",
+ "YW55IGNhcm5hbCBwbGVhcw=="
+ }
+};
+
+int
+main(int argc, char *argv[])
+{
+ int ch, ntests = nitems(test_strings);
+ int i, errors = 0;
+ unsigned char buf[64];
+ size_t len;
+
+ initprogname(argc > 0 ? argv[0] : "check_base64");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignored */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ for (i = 0; i < ntests; i++) {
+ /* Test decode. */
+ len = base64_decode(test_strings[i].encoded, buf, sizeof(buf));
+ if (len == (size_t)-1) {
+ fprintf(stderr, "check_base64: failed to decode %s\n",
+ test_strings[i].encoded);
+ errors++;
+ } else {
+ buf[len] = '\0';
+ if (strcmp(test_strings[i].ascii, (char *)buf) != 0) {
+ fprintf(stderr, "check_base64: expected %s, got %s\n",
+ test_strings[i].ascii, buf);
+ errors++;
+ }
+ }
+
+ /* Test encode. */
+ len = base64_encode((unsigned char *)test_strings[i].ascii,
+ strlen(test_strings[i].ascii), (char *)buf, sizeof(buf));
+ if (len == (size_t)-1) {
+ fprintf(stderr, "check_base64: failed to encode %s\n",
+ test_strings[i].ascii);
+ errors++;
+ } else {
+ if (strcmp(test_strings[i].encoded, (char *)buf) != 0) {
+ fprintf(stderr, "check_base64: expected %s, got %s\n",
+ test_strings[i].encoded, buf);
+ errors++;
+ }
+ }
+ }
+ ntests *= 2; /* we test in both directions */
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ exit(errors);
+}
diff --git a/plugins/sudoers/regress/parser/check_digest.c b/plugins/sudoers/regress/parser/check_digest.c
new file mode 100644
index 0000000..66527a6
--- /dev/null
+++ b/plugins/sudoers/regress/parser/check_digest.c
@@ -0,0 +1,140 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_queue.h>
+#include <sudo_digest.h>
+#include <sudo_util.h>
+#include <parse.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+#define NUM_TESTS 8
+static const char *test_strings[NUM_TESTS] = {
+ "",
+ "a",
+ "abc",
+ "message digest",
+ "abcdefghijklmnopqrstuvwxyz",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ "12345678901234567890123456789012345678901234567890123456789"
+ "012345678901234567890",
+};
+
+static unsigned char *
+check_digest(unsigned int digest_type, const char *buf, size_t buflen,
+ size_t *digest_len)
+{
+ char tfile[] = "digest.XXXXXX";
+ unsigned char *digest = NULL;
+ int tfd;
+
+ /* Write test data to temporary file. */
+ tfd = mkstemp(tfile);
+ if (tfd == -1) {
+ sudo_warn_nodebug("mkstemp");
+ goto done;
+ }
+ if ((size_t)write(tfd, buf, buflen) != buflen) {
+ sudo_warn_nodebug("write");
+ goto done;
+ }
+ lseek(tfd, 0, SEEK_SET);
+
+ /* Get file digest. */
+ digest = sudo_filedigest(tfd, tfile, digest_type, digest_len);
+ if (digest == NULL) {
+ /* Warning (if any) printed by sudo_filedigest() */
+ goto done;
+ }
+done:
+ if (tfd != -1) {
+ close(tfd);
+ unlink(tfile);
+ }
+ return digest;
+}
+
+int
+main(int argc, char *argv[])
+{
+ static const char hex[] = "0123456789abcdef";
+ char buf[1000 * 1000];
+ unsigned char *digest;
+ unsigned int i, j;
+ size_t digest_len;
+ int ch;
+ unsigned int digest_type;
+
+ initprogname(argc > 0 ? argv[0] : "check_digest");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignored */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ for (digest_type = 0; digest_type < SUDO_DIGEST_INVALID; digest_type++) {
+ for (i = 0; i < NUM_TESTS; i++) {
+ digest = check_digest(digest_type, test_strings[i],
+ strlen(test_strings[i]), &digest_len);
+ if (digest != NULL) {
+ printf("%s (\"%s\") = ", digest_type_to_name(digest_type),
+ test_strings[i]);
+ for (j = 0; j < digest_len; j++) {
+ putchar(hex[digest[j] >> 4]);
+ putchar(hex[digest[j] & 0x0f]);
+ }
+ putchar('\n');
+ free(digest);
+ }
+ }
+
+ /* Simulate a string of a million 'a' characters. */
+ memset(buf, 'a', sizeof(buf));
+ digest = check_digest(digest_type, buf, sizeof(buf), &digest_len);
+ if (digest != NULL) {
+ printf("%s (one million 'a' characters) = ",
+ digest_type_to_name(digest_type));
+ for (j = 0; j < digest_len; j++) {
+ putchar(hex[digest[j] >> 4]);
+ putchar(hex[digest[j] & 0x0f]);
+ }
+ putchar('\n');
+ free(digest);
+ }
+ }
+
+ return 0;
+}
diff --git a/plugins/sudoers/regress/parser/check_digest.out.ok b/plugins/sudoers/regress/parser/check_digest.out.ok
new file mode 100644
index 0000000..a353664
--- /dev/null
+++ b/plugins/sudoers/regress/parser/check_digest.out.ok
@@ -0,0 +1,36 @@
+sha224 ("") = d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f
+sha224 ("a") = abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5
+sha224 ("abc") = 23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7
+sha224 ("message digest") = 2cb21c83ae2f004de7e81c3c7019cbcb65b71ab656b22d6d0c39b8eb
+sha224 ("abcdefghijklmnopqrstuvwxyz") = 45a5f72c39c5cff2522eb3429799e49e5f44b356ef926bcf390dccc2
+sha224 ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525
+sha224 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = bff72b4fcb7d75e5632900ac5f90d219e05e97a7bde72e740db393d9
+sha224 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = b50aecbe4e9bb0b57bc5f3ae760a8e01db24f203fb3cdcd13148046e
+sha224 (one million 'a' characters) = 20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67
+sha256 ("") = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
+sha256 ("a") = ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb
+sha256 ("abc") = ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
+sha256 ("message digest") = f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650
+sha256 ("abcdefghijklmnopqrstuvwxyz") = 71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73
+sha256 ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1
+sha256 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0
+sha256 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e
+sha256 (one million 'a' characters) = cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0
+sha384 ("") = 38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b
+sha384 ("a") = 54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31
+sha384 ("abc") = cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7
+sha384 ("message digest") = 473ed35167ec1f5d8e550368a3db39be54639f828868e9454c239fc8b52e3c61dbd0d8b4de1390c256dcbb5d5fd99cd5
+sha384 ("abcdefghijklmnopqrstuvwxyz") = feb67349df3db6f5924815d6c3dc133f091809213731fe5c7b5f4999e463479ff2877f5f2936fa63bb43784b12f3ebb4
+sha384 ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b
+sha384 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = 1761336e3f7cbfe51deb137f026f89e01a448e3b1fafa64039c1464ee8732f11a5341a6f41e0c202294736ed64db1a84
+sha384 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = b12932b0627d1c060942f5447764155655bd4da0c9afa6dd9b9ef53129af1b8fb0195996d2de9ca0df9d821ffee67026
+sha384 (one million 'a' characters) = 9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985
+sha512 ("") = cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e
+sha512 ("a") = 1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75
+sha512 ("abc") = ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f
+sha512 ("message digest") = 107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c
+sha512 ("abcdefghijklmnopqrstuvwxyz") = 4dbff86cc2ca1bae1e16468a05cb9881c97f1753bce3619034898faa1aabe429955a1bf8ec483d7421fe3c1646613a59ed5441fb0f321389f77f48a879c7b1f1
+sha512 ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445
+sha512 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = 1e07be23c26a86ea37ea810c8ec7809352515a970e9253c26f536cfc7a9996c45c8370583e0a78fa4a90041d71a4ceab7423f19c71b9d5a3e01249f0bebd5894
+sha512 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 72ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d1914042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843
+sha512 (one million 'a' characters) = e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b
diff --git a/plugins/sudoers/regress/parser/check_fill.c b/plugins/sudoers/regress/parser/check_fill.c
new file mode 100644
index 0000000..cd8475f
--- /dev/null
+++ b/plugins/sudoers/regress/parser/check_fill.c
@@ -0,0 +1,225 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011-2016 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_queue.h>
+#include <parse.h>
+#include <toke.h>
+#include <sudo_plugin.h>
+#include <sudo_util.h>
+#include <gram.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+/*
+ * TODO: test realloc
+ */
+
+YYSTYPE sudoerslval;
+
+struct fill_test {
+ const char *input;
+ const char *output;
+ int len;
+ bool addspace;
+};
+
+/*
+ * In "normal" fill, anything can be escaped and hex chars are expanded.
+ */
+static struct fill_test txt_data[] = {
+ { "Embedded\\x20Space", "Embedded Space", 0 },
+ { "\\x20Leading", " Leading", 0 },
+ { "Trailing\\x20", "Trailing ", 0 },
+ { "Multiple\\x20\\x20Spaces", "Multiple Spaces", 0 },
+ { "Hexparse\\x200Check", "Hexparse 0Check", 0 },
+ { "Escaped\\\\Escape", "Escaped\\Escape", 0 },
+ { "LongGroupName", "LongGrou", 8 }
+};
+
+/*
+ * The only escaped chars in a command should be [,:= \t#]
+ * The rest are done by glob() or fnmatch().
+ */
+static struct fill_test cmd_data[] = {
+ { "foo\\,bar", "foo,bar", 0 },
+ { "this\\:that", "this:that", 0 },
+ { "foo\\=bar", "foo=bar", 0 },
+ { "tab\\\tstop", "tab\tstop", 0 },
+ { "not a \\#comment", "not a #comment", 0 }
+};
+
+/*
+ * No escaped characters in command line args.
+ * Arguments get appended.
+ */
+static struct fill_test args_data[] = {
+ { "/", "/", 0, false },
+ { "-type", "/ -type", 0, true },
+ { "f", "/ -type f", 0, true },
+ { "-exec", "/ -type f -exec", 0, true },
+ { "ls", "/ -type f -exec ls", 0, true },
+ { "{}", "/ -type f -exec ls {}", 0, true }
+};
+
+static int
+check_fill(const char *input, int len, bool addspace, const char *expect, char **resultp)
+{
+ if (sudoerslval.string != NULL) {
+ free(sudoerslval.string);
+ sudoerslval.string = NULL;
+ }
+ if (!fill(input, len))
+ return -1;
+ *resultp = sudoerslval.string;
+ return !strcmp(sudoerslval.string, expect);
+}
+
+static int
+check_fill_cmnd(const char *input, int len, bool addspace, const char *expect, char **resultp)
+{
+ if (sudoerslval.command.cmnd != NULL) {
+ free(sudoerslval.command.cmnd);
+ sudoerslval.command.cmnd = NULL;
+ }
+ if (!fill_cmnd(input, len))
+ return -1;
+ *resultp = sudoerslval.command.cmnd;
+ return !strcmp(sudoerslval.command.cmnd, expect);
+}
+
+static int
+check_fill_args(const char *input, int len, bool addspace, const char *expect, char **resultp)
+{
+ /* Must not free old sudoerslval.command.args as gets appended to. */
+ if (!fill_args(input, len, addspace))
+ return -1;
+ *resultp = sudoerslval.command.args;
+ return !strcmp(sudoerslval.command.args, expect);
+}
+
+static int
+do_tests(int (*checker)(const char *, int, bool, const char *, char **),
+ struct fill_test *data, size_t ntests)
+{
+ int errors = 0;
+ unsigned int i;
+ int len;
+ char *result;
+
+ for (i = 0; i < ntests; i++) {
+ if (data[i].len == 0)
+ len = (int)strlen(data[i].input);
+ else
+ len = data[i].len;
+
+ switch ((*checker)(data[i].input, len, data[i].addspace, data[i].output, &result)) {
+ case 0:
+ /* no match */
+ fprintf(stderr, "Failed parsing %.*s: expected [%s], got [%s]\n",
+ (int)data[i].len, data[i].input, data[i].output, result);
+ errors++;
+ break;
+ case 1:
+ /* match */
+ break;
+ default:
+ /* error */
+ fprintf(stderr, "Failed parsing %.*s: fill function failure\n",
+ (int)data[i].len, data[i].input);
+ errors++;
+ break;
+ }
+ }
+
+ return errors;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch, ntests, errors = 0;
+
+ initprogname(argc > 0 ? argv[0] : "check_fill");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignored */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ errors += do_tests(check_fill, txt_data, nitems(txt_data));
+ errors += do_tests(check_fill_cmnd, cmd_data, nitems(cmd_data));
+ errors += do_tests(check_fill_args, args_data, nitems(args_data));
+
+ ntests = nitems(txt_data) + nitems(cmd_data) + nitems(args_data);
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
+
+/* STUB */
+void
+sudoerserror(const char *s)
+{
+ return;
+}
+
+/* STUB */
+bool
+sudoers_strict(void)
+{
+ return false;
+}
+
+/* STUB */
+bool
+parser_leak_add(enum parser_leak_types type, void *v)
+{
+ return true;
+}
+
+/* STUB */
+bool
+parser_leak_remove(enum parser_leak_types type, void *v)
+{
+ return true;
+}
diff --git a/plugins/sudoers/regress/parser/check_gentime.c b/plugins/sudoers/regress/parser/check_gentime.c
new file mode 100644
index 0000000..8b1e0f6
--- /dev/null
+++ b/plugins/sudoers/regress/parser/check_gentime.c
@@ -0,0 +1,98 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2017 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudoers_debug.h>
+#include <parse.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+const struct gentime_test {
+ const char *gentime;
+ time_t unixtime;
+} tests[] = {
+ { "199412161032ZZ", -1 },
+ { "199412161032Z", 787573920 },
+ { "199412160532-0500", 787573920 },
+ { "199412160532-05000", -1 },
+ { "199412160532", 787573920 }, /* local time is EST */
+ { "20170214083000-0500", 1487079000 },
+ { "201702140830-0500", 1487079000 },
+ { "201702140830", 1487079000 }, /* local time is EST */
+ { "201702140830.3-0500", 1487079018 },
+ { "201702140830,3-0500", 1487079018 },
+ { "20170214083000.5Z", 1487061000 },
+ { "20170214083000,5Z", 1487061000 },
+ { "201702142359.4Z", 1487116764 },
+ { "201702142359,4Z", 1487116764 },
+ { "2017021408.5Z", 1487061000 },
+ { "2017021408,5Z", 1487061000 },
+ { "20170214Z", -1 },
+};
+
+int
+main(int argc, char *argv[])
+{
+ const int ntests = nitems(tests);
+ int ch, i, errors = 0;
+ time_t result;
+
+ initprogname(argc > 0 ? argv[0] : "check_gentime");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignored */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* Do local time tests in Eastern Standard Time. */
+ putenv((char *)"TZ=EST5EST5");
+ tzset();
+
+ for (i = 0; i < ntests; i++) {
+ result = parse_gentime(tests[i].gentime);
+ if (result != tests[i].unixtime) {
+ fprintf(stderr, "check_gentime[%d]: %s: expected %lld, got %lld\n",
+ i, tests[i].gentime,
+ (long long)tests[i].unixtime, (long long)result);
+ errors++;
+ }
+ }
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+ exit(errors);
+}
diff --git a/plugins/sudoers/regress/serialize_list/check_serialize_list.c b/plugins/sudoers/regress/serialize_list/check_serialize_list.c
new file mode 100644
index 0000000..cf559c5
--- /dev/null
+++ b/plugins/sudoers/regress/serialize_list/check_serialize_list.c
@@ -0,0 +1,96 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudoers.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+static void
+test_serialize_list(int *ntests_out, int *errors_out)
+{
+ int ntests = *ntests_out;
+ int errors = *errors_out;
+ const char *expected = "myvar=a value with spaces,this\\,and\\,that,\\,";
+ struct list_members members = SLIST_HEAD_INITIALIZER(members);
+ struct list_member lm1, lm2, lm3;
+ char *result;
+
+ lm1.value = (char *)"a value with spaces";
+ lm2.value = (char *)"this,and,that";
+ lm3.value = (char *)",";
+ SLIST_INSERT_HEAD(&members, &lm3, entries);
+ SLIST_INSERT_HEAD(&members, &lm2, entries);
+ SLIST_INSERT_HEAD(&members, &lm1, entries);
+
+ ntests++;
+ result = serialize_list("myvar", &members);
+ if (result == NULL) {
+ sudo_warnx("serialize_list returns NULL");
+ ++errors;
+ goto done;
+ }
+ ntests++;
+ if (strcmp(result, expected) != 0) {
+ sudo_warnx("got \"%s\", expected \"%s\"", result, expected);
+ ++errors;
+ goto done;
+ }
+
+done:
+ free(result);
+ *ntests_out = ntests;
+ *errors_out = errors;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch, ntests = 0, errors = 0;
+
+ initprogname(argc > 0 ? argv[0] : "check_serialize_list");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignored */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ test_serialize_list(&ntests, &errors);
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ exit(errors);
+}
diff --git a/plugins/sudoers/regress/starttime/check_starttime.c b/plugins/sudoers/regress/starttime/check_starttime.c
new file mode 100644
index 0000000..406d7fb
--- /dev/null
+++ b/plugins/sudoers/regress/starttime/check_starttime.c
@@ -0,0 +1,154 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2017 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_fatal.h>
+#include <timestamp.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+#if defined(sudo_kinfo_proc) || defined(__linux__) || defined(HAVE_STRUCT_PSINFO_PR_TTYDEV) || defined(HAVE_PSTAT_GETPROC) || defined(__gnu_hurd__)
+
+#ifdef __linux__
+static int
+get_now(struct timespec *now)
+{
+ const char *errstr;
+ char buf[1024];
+ time_t seconds;
+ int ret = -1;
+ FILE *fp;
+
+ /* Linux process start time is relative to boot time. */
+ fp = fopen("/proc/stat", "r");
+ if (fp != NULL) {
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ if (strncmp(buf, "btime ", 6) != 0)
+ continue;
+ buf[strcspn(buf, "\n")] = '\0';
+
+ /* Boot time is in seconds since the epoch. */
+ seconds = sudo_strtonum(buf + 6, 0, TIME_T_MAX, &errstr);
+ if (errstr != NULL)
+ return -1;
+
+ /* Instead of the real time, "now" is relative to boot time. */
+ if (sudo_gettime_real(now) == -1)
+ return -1;
+ now->tv_sec -= seconds;
+ ret = 0;
+ break;
+ }
+ fclose(fp);
+ }
+ return ret;
+}
+#else
+static int
+get_now(struct timespec *now)
+{
+ /* Process start time is relative to wall clock time. */
+ return sudo_gettime_real(now);
+}
+#endif
+
+int
+main(int argc, char *argv[])
+{
+ int ch, ntests = 0, errors = 0;
+ struct timespec now, then, delta;
+ time_t timeoff = 0;
+ pid_t pids[2];
+ char *faketime;
+ unsigned int i;
+
+ initprogname(argc > 0 ? argv[0] : "check_starttime");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignored */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (get_now(&now) == -1)
+ sudo_fatal_nodebug("unable to get current time");
+
+ pids[0] = getpid();
+ pids[1] = getppid();
+
+ /* Debian CI pipeline runs tests using faketime. */
+ faketime = getenv("FAKETIME");
+ if (faketime != NULL)
+ timeoff = sudo_strtonum(faketime, TIME_T_MIN, TIME_T_MAX, NULL);
+
+ for (i = 0; i < 2; i++) {
+ ntests++;
+ if (get_starttime(pids[i], &then) == -1) {
+ printf("%s: test %d: unable to get start time for pid %d\n",
+ getprogname(), ntests, (int)pids[i]);
+ errors++;
+ }
+ if (i != 0)
+ continue;
+
+ /* Verify our own process start time, allowing for some drift. */
+ ntests++;
+ sudo_timespecsub(&then, &now, &delta);
+ delta.tv_sec += timeoff;
+ if (delta.tv_sec > 30 || delta.tv_sec < -30) {
+ printf("%s: test %d: unexpected start time for pid %d: %s",
+ getprogname(), ntests, (int)pids[i], ctime(&then.tv_sec));
+ errors++;
+ }
+ }
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ return errors;
+}
+
+#else
+
+int
+main(int argc, char *argv[])
+{
+ /* get_starttime not supported */
+ return 0;
+}
+
+#endif
diff --git a/plugins/sudoers/regress/sudoers/test1.in b/plugins/sudoers/regress/sudoers/test1.in
new file mode 100644
index 0000000..d87c872
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test1.in
@@ -0,0 +1,12 @@
+#
+# Verify that all command tags are parsed OK.
+# See https://bugzilla.sudo.ws/show_bug.cgi?id=437
+#
+user1 ALL = LOG_INPUT: LOG_OUTPUT: /usr/bin/su -:\
+ ALL = NOLOG_INPUT: NOLOG_OUTPUT: /usr/bin/id
+user2 ALL = NOPASSWD: NOEXEC: SETENV: /usr/bin/vi:\
+ ALL = PASSWD: EXEC: NOSETENV: /usr/bin/echo
+user3 ALL = MAIL: /bin/sh:\
+ ALL = NOMAIL: /usr/bin/id
+user4 ALL = FOLLOW: sudoedit /etc/motd:\
+ ALL = NOFOLLOW: sudoedit /home/*/*
diff --git a/plugins/sudoers/regress/sudoers/test1.json.ok b/plugins/sudoers/regress/sudoers/test1.json.ok
new file mode 100644
index 0000000..9523e4a
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test1.json.ok
@@ -0,0 +1,154 @@
+{
+ "User_Specs": [
+ {
+ "User_List": [
+ { "username": "user1" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "log_input": true },
+ { "log_output": true }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/su -" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user1" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "log_input": false },
+ { "log_output": false }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user2" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "authenticate": false },
+ { "noexec": true },
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/vi" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user2" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "authenticate": true },
+ { "noexec": false },
+ { "setenv": false }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/echo" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user3" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "send_mail": true }
+ ],
+ "Commands": [
+ { "command": "/bin/sh" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user3" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "send_mail": false }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user4" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "sudoedit_follow": true }
+ ],
+ "Commands": [
+ { "command": "sudoedit /etc/motd" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user4" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "sudoedit_follow": false }
+ ],
+ "Commands": [
+ { "command": "sudoedit /home/*/*" }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/sudoers/test1.ldif.ok b/plugins/sudoers/regress/sudoers/test1.ldif.ok
new file mode 100644
index 0000000..7f3fcfc
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test1.ldif.ok
@@ -0,0 +1,88 @@
+dn: cn=user1,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user1
+sudoUser: user1
+sudoHost: ALL
+sudoOption: log_input
+sudoOption: log_output
+sudoCommand: /usr/bin/su -
+sudoOrder: 1
+
+dn: cn=user1_1,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user1_1
+sudoUser: user1
+sudoHost: ALL
+sudoOption: !log_input
+sudoOption: !log_output
+sudoCommand: /usr/bin/id
+sudoOrder: 2
+
+dn: cn=user2,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user2
+sudoUser: user2
+sudoHost: ALL
+sudoOption: !authenticate
+sudoOption: noexec
+sudoOption: setenv
+sudoCommand: /usr/bin/vi
+sudoOrder: 3
+
+dn: cn=user2_1,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user2_1
+sudoUser: user2
+sudoHost: ALL
+sudoOption: authenticate
+sudoOption: !noexec
+sudoOption: !setenv
+sudoCommand: /usr/bin/echo
+sudoOrder: 4
+
+dn: cn=user3,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user3
+sudoUser: user3
+sudoHost: ALL
+sudoOption: mail_all_cmnds
+sudoCommand: /bin/sh
+sudoOrder: 5
+
+dn: cn=user3_1,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user3_1
+sudoUser: user3
+sudoHost: ALL
+sudoOption: !mail_all_cmnds
+sudoOption: !mail_always
+sudoOption: !mail_no_perms
+sudoCommand: /usr/bin/id
+sudoOrder: 6
+
+dn: cn=user4,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user4
+sudoUser: user4
+sudoHost: ALL
+sudoOption: sudoedit_follow
+sudoCommand: sudoedit /etc/motd
+sudoOrder: 7
+
+dn: cn=user4_1,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user4_1
+sudoUser: user4
+sudoHost: ALL
+sudoOption: !sudoedit_follow
+sudoCommand: sudoedit /home/*/*
+sudoOrder: 8
+
diff --git a/plugins/sudoers/regress/sudoers/test1.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test1.ldif2sudo.ok
new file mode 100644
index 0000000..126fe91
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test1.ldif2sudo.ok
@@ -0,0 +1,13 @@
+# sudoRole user1, user1_1
+user1 ALL = LOG_INPUT: LOG_OUTPUT: /usr/bin/su -, NOLOG_INPUT: NOLOG_OUTPUT:\
+ /usr/bin/id
+
+# sudoRole user2, user2_1
+user2 ALL = SETENV: NOEXEC: NOPASSWD: /usr/bin/vi, NOSETENV: EXEC: PASSWD:\
+ /usr/bin/echo
+
+# sudoRole user3, user3_1
+user3 ALL = MAIL: /bin/sh, NOMAIL: /usr/bin/id
+
+# sudoRole user4, user4_1
+user4 ALL = FOLLOW: sudoedit /etc/motd, NOFOLLOW: sudoedit /home/*/*
diff --git a/plugins/sudoers/regress/sudoers/test1.out.ok b/plugins/sudoers/regress/sudoers/test1.out.ok
new file mode 100644
index 0000000..3d6bab4
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test1.out.ok
@@ -0,0 +1,6 @@
+Parses OK
+
+user1 ALL = LOG_INPUT: LOG_OUTPUT: /usr/bin/su - : ALL = NOLOG_INPUT: NOLOG_OUTPUT: /usr/bin/id
+user2 ALL = SETENV: NOEXEC: NOPASSWD: /usr/bin/vi : ALL = NOSETENV: EXEC: PASSWD: /usr/bin/echo
+user3 ALL = MAIL: /bin/sh : ALL = NOMAIL: /usr/bin/id
+user4 ALL = FOLLOW: sudoedit /etc/motd : ALL = NOFOLLOW: sudoedit /home/*/*
diff --git a/plugins/sudoers/regress/sudoers/test1.toke.ok b/plugins/sudoers/regress/sudoers/test1.toke.ok
new file mode 100644
index 0000000..28c8592
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test1.toke.ok
@@ -0,0 +1,8 @@
+#
+#
+#
+#
+WORD(6) ALL = LOG_INPUT LOG_OUTPUT COMMAND ARG : ALL = NOLOG_INPUT NOLOG_OUTPUT COMMAND
+WORD(6) ALL = NOPASSWD NOEXEC SETENV COMMAND : ALL = PASSWD EXEC NOSETENV COMMAND
+WORD(6) ALL = MAIL COMMAND : ALL = NOMAIL COMMAND
+WORD(6) ALL = FOLLOW COMMAND ARG : ALL = NOFOLLOW COMMAND ARG
diff --git a/plugins/sudoers/regress/sudoers/test10.in b/plugins/sudoers/regress/sudoers/test10.in
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test10.in
@@ -0,0 +1 @@
+
diff --git a/plugins/sudoers/regress/sudoers/test10.json.ok b/plugins/sudoers/regress/sudoers/test10.json.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test10.json.ok
diff --git a/plugins/sudoers/regress/sudoers/test10.ldif.ok b/plugins/sudoers/regress/sudoers/test10.ldif.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test10.ldif.ok
diff --git a/plugins/sudoers/regress/sudoers/test10.out.ok b/plugins/sudoers/regress/sudoers/test10.out.ok
new file mode 100644
index 0000000..5af5c53
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test10.out.ok
@@ -0,0 +1,2 @@
+Parses OK
+
diff --git a/plugins/sudoers/regress/sudoers/test10.toke.ok b/plugins/sudoers/regress/sudoers/test10.toke.ok
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test10.toke.ok
@@ -0,0 +1 @@
+
diff --git a/plugins/sudoers/regress/sudoers/test11.in b/plugins/sudoers/regress/sudoers/test11.in
new file mode 100644
index 0000000..5ffba7b
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test11.in
@@ -0,0 +1 @@
+bogus
diff --git a/plugins/sudoers/regress/sudoers/test11.json.ok b/plugins/sudoers/regress/sudoers/test11.json.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test11.json.ok
diff --git a/plugins/sudoers/regress/sudoers/test11.ldif.ok b/plugins/sudoers/regress/sudoers/test11.ldif.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test11.ldif.ok
diff --git a/plugins/sudoers/regress/sudoers/test11.out.ok b/plugins/sudoers/regress/sudoers/test11.out.ok
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test11.out.ok
@@ -0,0 +1 @@
+
diff --git a/plugins/sudoers/regress/sudoers/test11.toke.ok b/plugins/sudoers/regress/sudoers/test11.toke.ok
new file mode 100644
index 0000000..bfef7a7
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test11.toke.ok
@@ -0,0 +1,2 @@
+WORD(6)
+<*> \ No newline at end of file
diff --git a/plugins/sudoers/regress/sudoers/test12.in b/plugins/sudoers/regress/sudoers/test12.in
new file mode 100644
index 0000000..23bda4a
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test12.in
@@ -0,0 +1 @@
+user ALL = (ALL)
diff --git a/plugins/sudoers/regress/sudoers/test12.json.ok b/plugins/sudoers/regress/sudoers/test12.json.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test12.json.ok
diff --git a/plugins/sudoers/regress/sudoers/test12.ldif.ok b/plugins/sudoers/regress/sudoers/test12.ldif.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test12.ldif.ok
diff --git a/plugins/sudoers/regress/sudoers/test12.out.ok b/plugins/sudoers/regress/sudoers/test12.out.ok
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test12.out.ok
@@ -0,0 +1 @@
+
diff --git a/plugins/sudoers/regress/sudoers/test12.toke.ok b/plugins/sudoers/regress/sudoers/test12.toke.ok
new file mode 100644
index 0000000..0d79959
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test12.toke.ok
@@ -0,0 +1,2 @@
+WORD(6) ALL = ( ALL )
+<*> \ No newline at end of file
diff --git a/plugins/sudoers/regress/sudoers/test13.in b/plugins/sudoers/regress/sudoers/test13.in
new file mode 100644
index 0000000..b8002bc
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test13.in
@@ -0,0 +1 @@
+user ALL = (ALL) \ No newline at end of file
diff --git a/plugins/sudoers/regress/sudoers/test13.json.ok b/plugins/sudoers/regress/sudoers/test13.json.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test13.json.ok
diff --git a/plugins/sudoers/regress/sudoers/test13.ldif.ok b/plugins/sudoers/regress/sudoers/test13.ldif.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test13.ldif.ok
diff --git a/plugins/sudoers/regress/sudoers/test13.out.ok b/plugins/sudoers/regress/sudoers/test13.out.ok
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test13.out.ok
@@ -0,0 +1 @@
+
diff --git a/plugins/sudoers/regress/sudoers/test13.toke.ok b/plugins/sudoers/regress/sudoers/test13.toke.ok
new file mode 100644
index 0000000..0d79959
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test13.toke.ok
@@ -0,0 +1,2 @@
+WORD(6) ALL = ( ALL )
+<*> \ No newline at end of file
diff --git a/plugins/sudoers/regress/sudoers/test14.in b/plugins/sudoers/regress/sudoers/test14.in
new file mode 100644
index 0000000..bdbac68
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test14.in
@@ -0,0 +1,6 @@
+Cmnd_Alias LS = sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1, sha224:d7910e1967342b4605cb73a550944044c631cd3514001900966962ac /bin/ls
+Cmnd_Alias SH = sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh
+
+millert ALL = LS, SH, sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw /bin/kill
+
+operator ALL = sha384:knMlCLkJ71K6uRrKo5C1CAvZ5kq+mRpjKDD/RofGosFjiGcYhiYYZORVyiRHgBnu, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= ALL
diff --git a/plugins/sudoers/regress/sudoers/test14.json.ok b/plugins/sudoers/regress/sudoers/test14.json.ok
new file mode 100644
index 0000000..7e0e3c3
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test14.json.ok
@@ -0,0 +1,62 @@
+{
+ "Command_Aliases": {
+ "LS": [
+ {
+ "command": "/bin/ls",
+ "sha224": "d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1",
+ "sha224": "d7910e1967342b4605cb73a550944044c631cd3514001900966962ac"
+ }
+ ],
+ "SH": [
+ {
+ "command": "/bin/sh",
+ "sha256": "hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=",
+ "sha256": "1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4="
+ }
+ ]
+ },
+ "User_Specs": [
+ {
+ "User_List": [
+ { "username": "millert" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "cmndalias": "LS" },
+ { "cmndalias": "SH" },
+ {
+ "command": "/bin/kill",
+ "sha512": "srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "operator" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ {
+ "command": "ALL",
+ "sha384": "knMlCLkJ71K6uRrKo5C1CAvZ5kq+mRpjKDD/RofGosFjiGcYhiYYZORVyiRHgBnu",
+ "sha256": "1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4="
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/sudoers/test14.ldif.ok b/plugins/sudoers/regress/sudoers/test14.ldif.ok
new file mode 100644
index 0000000..4d26c5d
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test14.ldif.ok
@@ -0,0 +1,20 @@
+dn: cn=millert,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: millert
+sudoUser: millert
+sudoHost: ALL
+sudoCommand: sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1, sha224:d7910e1967342b4605cb73a550944044c631cd3514001900966962ac /bin/ls
+sudoCommand: sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh
+sudoCommand: sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw /bin/kill
+sudoOrder: 1
+
+dn: cn=operator,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: operator
+sudoUser: operator
+sudoHost: ALL
+sudoCommand: sha384:knMlCLkJ71K6uRrKo5C1CAvZ5kq+mRpjKDD/RofGosFjiGcYhiYYZORVyiRHgBnu, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= ALL
+sudoOrder: 2
+
diff --git a/plugins/sudoers/regress/sudoers/test14.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test14.ldif2sudo.ok
new file mode 100644
index 0000000..c742a95
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test14.ldif2sudo.ok
@@ -0,0 +1,12 @@
+# sudoRole millert
+millert ALL = sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1,\
+ sha224:d7910e1967342b4605cb73a550944044c631cd3514001900966962ac /bin/ls,\
+ sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=,\
+ sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh,\
+ sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw\
+ /bin/kill
+
+# sudoRole operator
+operator ALL =\
+ sha384:knMlCLkJ71K6uRrKo5C1CAvZ5kq+mRpjKDD/RofGosFjiGcYhiYYZORVyiRHgBnu,\
+ sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= ALL
diff --git a/plugins/sudoers/regress/sudoers/test14.out.ok b/plugins/sudoers/regress/sudoers/test14.out.ok
new file mode 100644
index 0000000..658f74d
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test14.out.ok
@@ -0,0 +1,7 @@
+Parses OK
+
+Cmnd_Alias LS = sha224:d06a2617c98d377c250edd470fd5e576327748d82915d6e33b5f8db1, sha224:d7910e1967342b4605cb73a550944044c631cd3514001900966962ac /bin/ls
+Cmnd_Alias SH = sha256:hOtoe/iK6SlGg7w4BfZBBdSsXjUmTJ5+ts51yjh7vkM=, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= /bin/sh
+
+millert ALL = LS, SH, sha512:srzYEQ2aqzm+it3f74opTMkIImZRLxBARVpb0g9RSouJYdLt7DTRMEY4Ry9NyaOiDoUIplpNjqYH0JMYPVdFnw /bin/kill
+operator ALL = sha384:knMlCLkJ71K6uRrKo5C1CAvZ5kq+mRpjKDD/RofGosFjiGcYhiYYZORVyiRHgBnu, sha256:1IXHRCxXgSnIEnb+xBz4PAfWaPdXIBWKFF0QCwxJ5G4= ALL
diff --git a/plugins/sudoers/regress/sudoers/test14.toke.ok b/plugins/sudoers/regress/sudoers/test14.toke.ok
new file mode 100644
index 0000000..edf8099
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test14.toke.ok
@@ -0,0 +1,6 @@
+CMNDALIAS ALIAS = SHA224_TOK : DIGEST , SHA224_TOK : DIGEST COMMAND
+CMNDALIAS ALIAS = SHA256_TOK : DIGEST , SHA256_TOK : DIGEST COMMAND
+
+WORD(6) ALL = ALIAS , ALIAS , SHA512_TOK : DIGEST COMMAND
+
+WORD(6) ALL = SHA384_TOK : DIGEST , SHA256_TOK : DIGEST ALL
diff --git a/plugins/sudoers/regress/sudoers/test15.in b/plugins/sudoers/regress/sudoers/test15.in
new file mode 100644
index 0000000..11bcb13
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test15.in
@@ -0,0 +1,2 @@
+# Test parsing of sudoedit rule
+user ALL = sudoedit /etc/motd
diff --git a/plugins/sudoers/regress/sudoers/test15.json.ok b/plugins/sudoers/regress/sudoers/test15.json.ok
new file mode 100644
index 0000000..ff1795a
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test15.json.ok
@@ -0,0 +1,19 @@
+{
+ "User_Specs": [
+ {
+ "User_List": [
+ { "username": "user" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "command": "sudoedit /etc/motd" }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/sudoers/test15.ldif.ok b/plugins/sudoers/regress/sudoers/test15.ldif.ok
new file mode 100644
index 0000000..ac35ba0
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test15.ldif.ok
@@ -0,0 +1,9 @@
+dn: cn=user,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user
+sudoUser: user
+sudoHost: ALL
+sudoCommand: sudoedit /etc/motd
+sudoOrder: 1
+
diff --git a/plugins/sudoers/regress/sudoers/test15.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test15.ldif2sudo.ok
new file mode 100644
index 0000000..775d59e
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test15.ldif2sudo.ok
@@ -0,0 +1,2 @@
+# sudoRole user
+user ALL = sudoedit /etc/motd
diff --git a/plugins/sudoers/regress/sudoers/test15.out.ok b/plugins/sudoers/regress/sudoers/test15.out.ok
new file mode 100644
index 0000000..b230cf2
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test15.out.ok
@@ -0,0 +1,3 @@
+Parses OK
+
+user ALL = sudoedit /etc/motd
diff --git a/plugins/sudoers/regress/sudoers/test15.toke.ok b/plugins/sudoers/regress/sudoers/test15.toke.ok
new file mode 100644
index 0000000..08bb2b8
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test15.toke.ok
@@ -0,0 +1,2 @@
+#
+WORD(6) ALL = COMMAND ARG
diff --git a/plugins/sudoers/regress/sudoers/test16.in b/plugins/sudoers/regress/sudoers/test16.in
new file mode 100644
index 0000000..d2a79ea
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test16.in
@@ -0,0 +1,3 @@
+# Test parsing of sudoedit rule in a Cmnd_Alias
+Cmnd_Alias EDIT = sudoedit /etc/motd
+user ALL = EDIT
diff --git a/plugins/sudoers/regress/sudoers/test16.json.ok b/plugins/sudoers/regress/sudoers/test16.json.ok
new file mode 100644
index 0000000..7c42654
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test16.json.ok
@@ -0,0 +1,24 @@
+{
+ "Command_Aliases": {
+ "EDIT": [
+ { "command": "sudoedit /etc/motd" }
+ ]
+ },
+ "User_Specs": [
+ {
+ "User_List": [
+ { "username": "user" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "cmndalias": "EDIT" }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/sudoers/test16.ldif.ok b/plugins/sudoers/regress/sudoers/test16.ldif.ok
new file mode 100644
index 0000000..ac35ba0
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test16.ldif.ok
@@ -0,0 +1,9 @@
+dn: cn=user,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user
+sudoUser: user
+sudoHost: ALL
+sudoCommand: sudoedit /etc/motd
+sudoOrder: 1
+
diff --git a/plugins/sudoers/regress/sudoers/test16.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test16.ldif2sudo.ok
new file mode 100644
index 0000000..775d59e
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test16.ldif2sudo.ok
@@ -0,0 +1,2 @@
+# sudoRole user
+user ALL = sudoedit /etc/motd
diff --git a/plugins/sudoers/regress/sudoers/test16.out.ok b/plugins/sudoers/regress/sudoers/test16.out.ok
new file mode 100644
index 0000000..7b8c918
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test16.out.ok
@@ -0,0 +1,5 @@
+Parses OK
+
+Cmnd_Alias EDIT = sudoedit /etc/motd
+
+user ALL = EDIT
diff --git a/plugins/sudoers/regress/sudoers/test16.toke.ok b/plugins/sudoers/regress/sudoers/test16.toke.ok
new file mode 100644
index 0000000..debc4c7
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test16.toke.ok
@@ -0,0 +1,3 @@
+#
+CMNDALIAS ALIAS = COMMAND ARG
+WORD(6) ALL = ALIAS
diff --git a/plugins/sudoers/regress/sudoers/test17.in b/plugins/sudoers/regress/sudoers/test17.in
new file mode 100644
index 0000000..37d066c
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test17.in
@@ -0,0 +1,13 @@
+# Test parsing of command_timeout and TIMEOUT syntax
+Defaults command_timeout=2d8h10m59s
+user0 ALL = TIMEOUT=7D4H10M30S /usr/bin/id, /usr/bin/who, TIMEOUT=0 /bin/ls
+user1 ALL = TIMEOUT=7d4h10m30s /usr/bin/id
+user2 ALL = TIMEOUT=4h10m30s /usr/bin/id
+user3 ALL = TIMEOUT=10m30s /usr/bin/id
+user4 ALL = TIMEOUT=14d /usr/bin/id
+user5 ALL = TIMEOUT=5m /usr/bin/id
+user6 ALL = TIMEOUT=30s /usr/bin/id
+user7 ALL = TIMEOUT=45 /usr/bin/id
+user8 ALL = TIMEOUT=7d4h10m30s /usr/bin/id, TIMEOUT=4h10m30s /usr/bin/id, \
+ TIMEOUT=10m30s /usr/bin/id, TIMEOUT=14d /usr/bin/id, \
+ TIMEOUT=5m /usr/bin/id, TIMEOUT=30s /usr/bin/id
diff --git a/plugins/sudoers/regress/sudoers/test17.json.ok b/plugins/sudoers/regress/sudoers/test17.json.ok
new file mode 100644
index 0000000..2f39a37
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test17.json.ok
@@ -0,0 +1,180 @@
+{
+ "Defaults": [
+ {
+ "Options": [
+ { "command_timeout": "2d8h10m59s" }
+ ]
+ }
+ ],
+ "User_Specs": [
+ {
+ "User_List": [
+ { "username": "user0" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "command_timeout": 619830 }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" },
+ { "command": "/usr/bin/who" },
+ { "command": "/bin/ls" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user1" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "command_timeout": 619830 }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user2" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "command_timeout": 15030 }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user3" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "command_timeout": 630 }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user4" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "command_timeout": 1209600 }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user5" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "command_timeout": 300 }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user6" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "command_timeout": 30 }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user7" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "command_timeout": 45 }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user8" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "command_timeout": 619830 }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" },
+ { "command": "/usr/bin/id" },
+ { "command": "/usr/bin/id" },
+ { "command": "/usr/bin/id" },
+ { "command": "/usr/bin/id" },
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/sudoers/test17.ldif.ok b/plugins/sudoers/regress/sudoers/test17.ldif.ok
new file mode 100644
index 0000000..bdc784c
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test17.ldif.ok
@@ -0,0 +1,104 @@
+dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: command_timeout=2d8h10m59s
+
+dn: cn=user0,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user0
+sudoUser: user0
+sudoHost: ALL
+sudoOption: command_timeout=619830
+sudoCommand: /usr/bin/id
+sudoCommand: /usr/bin/who
+sudoCommand: /bin/ls
+sudoOrder: 1
+
+dn: cn=user1,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user1
+sudoUser: user1
+sudoHost: ALL
+sudoOption: command_timeout=619830
+sudoCommand: /usr/bin/id
+sudoOrder: 2
+
+dn: cn=user2,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user2
+sudoUser: user2
+sudoHost: ALL
+sudoOption: command_timeout=15030
+sudoCommand: /usr/bin/id
+sudoOrder: 3
+
+dn: cn=user3,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user3
+sudoUser: user3
+sudoHost: ALL
+sudoOption: command_timeout=630
+sudoCommand: /usr/bin/id
+sudoOrder: 4
+
+dn: cn=user4,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user4
+sudoUser: user4
+sudoHost: ALL
+sudoOption: command_timeout=1209600
+sudoCommand: /usr/bin/id
+sudoOrder: 5
+
+dn: cn=user5,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user5
+sudoUser: user5
+sudoHost: ALL
+sudoOption: command_timeout=300
+sudoCommand: /usr/bin/id
+sudoOrder: 6
+
+dn: cn=user6,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user6
+sudoUser: user6
+sudoHost: ALL
+sudoOption: command_timeout=30
+sudoCommand: /usr/bin/id
+sudoOrder: 7
+
+dn: cn=user7,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user7
+sudoUser: user7
+sudoHost: ALL
+sudoOption: command_timeout=45
+sudoCommand: /usr/bin/id
+sudoOrder: 8
+
+dn: cn=user8,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user8
+sudoUser: user8
+sudoHost: ALL
+sudoOption: command_timeout=619830
+sudoCommand: /usr/bin/id
+sudoCommand: /usr/bin/id
+sudoCommand: /usr/bin/id
+sudoCommand: /usr/bin/id
+sudoCommand: /usr/bin/id
+sudoCommand: /usr/bin/id
+sudoOrder: 9
+
diff --git a/plugins/sudoers/regress/sudoers/test17.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test17.ldif2sudo.ok
new file mode 100644
index 0000000..608f52f
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test17.ldif2sudo.ok
@@ -0,0 +1,29 @@
+Defaults command_timeout=2d8h10m59s
+
+# sudoRole user0
+user0 ALL = TIMEOUT=619830 /usr/bin/id, /usr/bin/who, /bin/ls
+
+# sudoRole user1
+user1 ALL = TIMEOUT=619830 /usr/bin/id
+
+# sudoRole user2
+user2 ALL = TIMEOUT=15030 /usr/bin/id
+
+# sudoRole user3
+user3 ALL = TIMEOUT=630 /usr/bin/id
+
+# sudoRole user4
+user4 ALL = TIMEOUT=1209600 /usr/bin/id
+
+# sudoRole user5
+user5 ALL = TIMEOUT=300 /usr/bin/id
+
+# sudoRole user6
+user6 ALL = TIMEOUT=30 /usr/bin/id
+
+# sudoRole user7
+user7 ALL = TIMEOUT=45 /usr/bin/id
+
+# sudoRole user8
+user8 ALL = TIMEOUT=619830 /usr/bin/id, /usr/bin/id, /usr/bin/id, /usr/bin/id,\
+ /usr/bin/id, /usr/bin/id
diff --git a/plugins/sudoers/regress/sudoers/test17.out.ok b/plugins/sudoers/regress/sudoers/test17.out.ok
new file mode 100644
index 0000000..f0c8086
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test17.out.ok
@@ -0,0 +1,13 @@
+Parses OK
+
+Defaults command_timeout=2d8h10m59s
+
+user0 ALL = TIMEOUT=619830 /usr/bin/id, /usr/bin/who, /bin/ls
+user1 ALL = TIMEOUT=619830 /usr/bin/id
+user2 ALL = TIMEOUT=15030 /usr/bin/id
+user3 ALL = TIMEOUT=630 /usr/bin/id
+user4 ALL = TIMEOUT=1209600 /usr/bin/id
+user5 ALL = TIMEOUT=300 /usr/bin/id
+user6 ALL = TIMEOUT=30 /usr/bin/id
+user7 ALL = TIMEOUT=45 /usr/bin/id
+user8 ALL = TIMEOUT=619830 /usr/bin/id, TIMEOUT=15030 /usr/bin/id, TIMEOUT=630 /usr/bin/id, TIMEOUT=1209600 /usr/bin/id, TIMEOUT=300 /usr/bin/id, TIMEOUT=30 /usr/bin/id
diff --git a/plugins/sudoers/regress/sudoers/test17.toke.ok b/plugins/sudoers/regress/sudoers/test17.toke.ok
new file mode 100644
index 0000000..d0a82ca
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test17.toke.ok
@@ -0,0 +1,11 @@
+#
+DEFAULTS DEFVAR = WORD(2)
+WORD(6) ALL = CMND_TIMEOUT = WORD(6) COMMAND , COMMAND , CMND_TIMEOUT = WORD(6) COMMAND
+WORD(6) ALL = CMND_TIMEOUT = WORD(6) COMMAND
+WORD(6) ALL = CMND_TIMEOUT = WORD(6) COMMAND
+WORD(6) ALL = CMND_TIMEOUT = WORD(6) COMMAND
+WORD(6) ALL = CMND_TIMEOUT = WORD(6) COMMAND
+WORD(6) ALL = CMND_TIMEOUT = WORD(6) COMMAND
+WORD(6) ALL = CMND_TIMEOUT = WORD(6) COMMAND
+WORD(6) ALL = CMND_TIMEOUT = WORD(6) COMMAND
+WORD(6) ALL = CMND_TIMEOUT = WORD(6) COMMAND , CMND_TIMEOUT = WORD(6) COMMAND , CMND_TIMEOUT = WORD(6) COMMAND , CMND_TIMEOUT = WORD(6) COMMAND , CMND_TIMEOUT = WORD(6) COMMAND , CMND_TIMEOUT = WORD(6) COMMAND
diff --git a/plugins/sudoers/regress/sudoers/test18.in b/plugins/sudoers/regress/sudoers/test18.in
new file mode 100644
index 0000000..8d94ec7
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test18.in
@@ -0,0 +1,8 @@
+# Test command_timeout and TIMEOUT syntax errors
+Defaults command_timeout=2d8h10m59ss
+Defaults:root command_timeout=15f
+user0 ALL = TIMEOUT=7dd4h10m30s /usr/bin/id, /usr/bin/who, TIMEOUT=0 /bin/ls
+user1 ALL = TIMEOUT=7d4h10mm30s /usr/bin/id
+user2 ALL = TIMEOUT=4hg10m30s /usr/bin/id
+user3 ALL = TIMEOUT=10m30ss /usr/bin/id
+user4 ALL = TIMEOUT=14g /usr/bin/id
diff --git a/plugins/sudoers/regress/sudoers/test18.json.ok b/plugins/sudoers/regress/sudoers/test18.json.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test18.json.ok
diff --git a/plugins/sudoers/regress/sudoers/test18.ldif.ok b/plugins/sudoers/regress/sudoers/test18.ldif.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test18.ldif.ok
diff --git a/plugins/sudoers/regress/sudoers/test18.out.ok b/plugins/sudoers/regress/sudoers/test18.out.ok
new file mode 100644
index 0000000..03f9ef6
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test18.out.ok
@@ -0,0 +1,3 @@
+
+Defaults command_timeout=2d8h10m59ss
+Defaults:root command_timeout=15f
diff --git a/plugins/sudoers/regress/sudoers/test18.toke.ok b/plugins/sudoers/regress/sudoers/test18.toke.ok
new file mode 100644
index 0000000..7c800a8
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test18.toke.ok
@@ -0,0 +1,10 @@
+#
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS_USER WORD(6) DEFVAR = WORD(2)
+WORD(6) ALL = CMND_TIMEOUT = WORD(6) <*> COMMAND , COMMAND , CMND_TIMEOUT = WORD(6) COMMAND
+WORD(6) ALL = CMND_TIMEOUT = WORD(6) <*> COMMAND
+WORD(6) ALL = CMND_TIMEOUT = WORD(6) <*> COMMAND
+WORD(6) ALL = CMND_TIMEOUT = WORD(6) <*> COMMAND
+WORD(6) ALL = CMND_TIMEOUT = WORD(6) <*> COMMAND
+sudoers:2:26: value "2d8h10m59ss" is invalid for option "command_timeout"
+sudoers:3:31: value "15f" is invalid for option "command_timeout"
diff --git a/plugins/sudoers/regress/sudoers/test19.in b/plugins/sudoers/regress/sudoers/test19.in
new file mode 100644
index 0000000..5f637a7
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test19.in
@@ -0,0 +1,12 @@
+# Test parsing of NOTBEFORE and NOTAFTER syntax
+# Local time zone parsing is checked in visudo/test10.sh
+user0 ALL = NOTBEFORE=20170214083000Z NOTAFTER=20170301083000Z /usr/bin/id, /bin/ls
+user1 ALL = NOTBEFORE=201702140830Z /usr/bin/id, NOTAFTER=20170301083000Z /bin/ls
+user2 ALL = NOTBEFORE=201702140830.3Z /usr/bin/id
+user3 ALL = NOTBEFORE=2017021408Z /usr/bin/id
+user4 ALL = NOTBEFORE=2017021408.4Z /usr/bin/id
+user5 ALL = NOTBEFORE=20170214083000.5Z /usr/bin/id
+user6 ALL = NOTBEFORE=20170214083000\,5Z /usr/bin/id
+user7 ALL = NOTBEFORE=20170214033000-0500 /usr/bin/id
+user8 ALL = NOTBEFORE=20170214033000.0-0500 /usr/bin/id
+user9 ALL = NOTBEFORE=20170214033000\,0-0500 /usr/bin/id
diff --git a/plugins/sudoers/regress/sudoers/test19.json.ok b/plugins/sudoers/regress/sudoers/test19.json.ok
new file mode 100644
index 0000000..c9a1bfd
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test19.json.ok
@@ -0,0 +1,187 @@
+{
+ "User_Specs": [
+ {
+ "User_List": [
+ { "username": "user0" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "notbefore": "20170214083000Z" },
+ { "notafter": "20170301083000Z" }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" },
+ { "command": "/bin/ls" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user1" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "notbefore": "20170214083000Z" }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" },
+ { "command": "/bin/ls" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user2" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "notbefore": "20170214083018Z" }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user3" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "notbefore": "20170214080000Z" }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user4" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "notbefore": "20170214082400Z" }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user5" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "notbefore": "20170214083000Z" }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user6" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "notbefore": "20170214083000Z" }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user7" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "notbefore": "20170214083000Z" }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user8" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "notbefore": "20170214083000Z" }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user9" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "notbefore": "20170214083000Z" }
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/sudoers/test19.ldif.ok b/plugins/sudoers/regress/sudoers/test19.ldif.ok
new file mode 100644
index 0000000..362aa9e
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test19.ldif.ok
@@ -0,0 +1,103 @@
+dn: cn=user0,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user0
+sudoUser: user0
+sudoHost: ALL
+sudoNotBefore: 20170214083000Z
+sudoNotAfter: 20170301083000Z
+sudoCommand: /usr/bin/id
+sudoCommand: /bin/ls
+sudoOrder: 1
+
+dn: cn=user1,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user1
+sudoUser: user1
+sudoHost: ALL
+sudoNotBefore: 20170214083000Z
+sudoCommand: /usr/bin/id
+sudoCommand: /bin/ls
+sudoOrder: 2
+
+dn: cn=user2,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user2
+sudoUser: user2
+sudoHost: ALL
+sudoNotBefore: 20170214083018Z
+sudoCommand: /usr/bin/id
+sudoOrder: 3
+
+dn: cn=user3,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user3
+sudoUser: user3
+sudoHost: ALL
+sudoNotBefore: 20170214080000Z
+sudoCommand: /usr/bin/id
+sudoOrder: 4
+
+dn: cn=user4,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user4
+sudoUser: user4
+sudoHost: ALL
+sudoNotBefore: 20170214082400Z
+sudoCommand: /usr/bin/id
+sudoOrder: 5
+
+dn: cn=user5,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user5
+sudoUser: user5
+sudoHost: ALL
+sudoNotBefore: 20170214083000Z
+sudoCommand: /usr/bin/id
+sudoOrder: 6
+
+dn: cn=user6,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user6
+sudoUser: user6
+sudoHost: ALL
+sudoNotBefore: 20170214083000Z
+sudoCommand: /usr/bin/id
+sudoOrder: 7
+
+dn: cn=user7,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user7
+sudoUser: user7
+sudoHost: ALL
+sudoNotBefore: 20170214083000Z
+sudoCommand: /usr/bin/id
+sudoOrder: 8
+
+dn: cn=user8,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user8
+sudoUser: user8
+sudoHost: ALL
+sudoNotBefore: 20170214083000Z
+sudoCommand: /usr/bin/id
+sudoOrder: 9
+
+dn: cn=user9,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user9
+sudoUser: user9
+sudoHost: ALL
+sudoNotBefore: 20170214083000Z
+sudoCommand: /usr/bin/id
+sudoOrder: 10
+
diff --git a/plugins/sudoers/regress/sudoers/test19.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test19.ldif2sudo.ok
new file mode 100644
index 0000000..1aef1bc
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test19.ldif2sudo.ok
@@ -0,0 +1,30 @@
+# sudoRole user0
+user0 ALL = NOTBEFORE=20170214083000Z NOTAFTER=20170301083000Z /usr/bin/id,\
+ /bin/ls
+
+# sudoRole user1
+user1 ALL = NOTBEFORE=20170214083000Z /usr/bin/id, /bin/ls
+
+# sudoRole user2
+user2 ALL = NOTBEFORE=20170214083018Z /usr/bin/id
+
+# sudoRole user3
+user3 ALL = NOTBEFORE=20170214080000Z /usr/bin/id
+
+# sudoRole user4
+user4 ALL = NOTBEFORE=20170214082400Z /usr/bin/id
+
+# sudoRole user5
+user5 ALL = NOTBEFORE=20170214083000Z /usr/bin/id
+
+# sudoRole user6
+user6 ALL = NOTBEFORE=20170214083000Z /usr/bin/id
+
+# sudoRole user7
+user7 ALL = NOTBEFORE=20170214083000Z /usr/bin/id
+
+# sudoRole user8
+user8 ALL = NOTBEFORE=20170214083000Z /usr/bin/id
+
+# sudoRole user9
+user9 ALL = NOTBEFORE=20170214083000Z /usr/bin/id
diff --git a/plugins/sudoers/regress/sudoers/test19.out.ok b/plugins/sudoers/regress/sudoers/test19.out.ok
new file mode 100644
index 0000000..dacfefd
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test19.out.ok
@@ -0,0 +1,12 @@
+Parses OK
+
+user0 ALL = NOTBEFORE=20170214083000Z NOTAFTER=20170301083000Z /usr/bin/id, /bin/ls
+user1 ALL = NOTBEFORE=20170214083000Z /usr/bin/id, NOTAFTER=20170301083000Z /bin/ls
+user2 ALL = NOTBEFORE=20170214083018Z /usr/bin/id
+user3 ALL = NOTBEFORE=20170214080000Z /usr/bin/id
+user4 ALL = NOTBEFORE=20170214082400Z /usr/bin/id
+user5 ALL = NOTBEFORE=20170214083000Z /usr/bin/id
+user6 ALL = NOTBEFORE=20170214083000Z /usr/bin/id
+user7 ALL = NOTBEFORE=20170214083000Z /usr/bin/id
+user8 ALL = NOTBEFORE=20170214083000Z /usr/bin/id
+user9 ALL = NOTBEFORE=20170214083000Z /usr/bin/id
diff --git a/plugins/sudoers/regress/sudoers/test19.toke.ok b/plugins/sudoers/regress/sudoers/test19.toke.ok
new file mode 100644
index 0000000..04461d9
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test19.toke.ok
@@ -0,0 +1,12 @@
+#
+#
+WORD(6) ALL = NOTBEFORE = WORD(6) NOTAFTER = WORD(6) COMMAND , COMMAND
+WORD(6) ALL = NOTBEFORE = WORD(6) COMMAND , NOTAFTER = WORD(6) COMMAND
+WORD(6) ALL = NOTBEFORE = WORD(6) COMMAND
+WORD(6) ALL = NOTBEFORE = WORD(6) COMMAND
+WORD(6) ALL = NOTBEFORE = WORD(6) COMMAND
+WORD(6) ALL = NOTBEFORE = WORD(6) COMMAND
+WORD(6) ALL = NOTBEFORE = WORD(6) COMMAND
+WORD(6) ALL = NOTBEFORE = WORD(6) COMMAND
+WORD(6) ALL = NOTBEFORE = WORD(6) COMMAND
+WORD(6) ALL = NOTBEFORE = WORD(6) COMMAND
diff --git a/plugins/sudoers/regress/sudoers/test2.in b/plugins/sudoers/regress/sudoers/test2.in
new file mode 100644
index 0000000..b81ae54
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test2.in
@@ -0,0 +1,63 @@
+# Check quoted user name in User_Alias
+User_Alias UA1 = "foo"
+User_Alias UA2 = "foo.bar"
+User_Alias UA3 = "foo\""
+User_Alias UA4 = "foo:bar"
+User_Alias UA5 = "foo:bar\""
+
+# Check quoted group name in User_Alias
+User_Alias UA6 = "%baz"
+User_Alias UA7 = "%baz.biz"
+
+# Check quoted non-Unix group name in User_Alias
+User_Alias UA8 = "%:C/non UNIX 0 c"
+User_Alias UA9 = "%:C/non\'UNIX\'1 c"
+User_Alias UA10 = "%:C/non\"UNIX\"0 c"
+User_Alias UA11 = "%:C/non_UNIX_0 c"
+User_Alias UA12 = "%:C/non\'UNIX_3 c"
+
+# Check quoted user name in Runas_Alias
+Runas_Alias RA1 = "foo"
+Runas_Alias RA2 = "foo\""
+Runas_Alias RA3 = "foo:bar"
+Runas_Alias RA4 = "foo:bar\""
+
+# Check quoted host name in Defaults
+Defaults@"somehost" set_home
+Defaults@"quoted\"" set_home
+
+# Check quoted user name in Defaults
+Defaults:"you" set_home
+Defaults:"us\"" set_home
+Defaults:"%them" set_home
+Defaults:"%: non UNIX 0 c" set_home
+Defaults:"+net" set_home
+
+# Check quoted runas name in Defaults
+Defaults>"someone" set_home
+Defaults>"some one" set_home
+
+# Check quoted command in Defaults
+# XXX - not currently supported
+#Defaults!"/bin/ls -l" set_home
+#Defaults!"/bin/ls -l \"foo\"" set_home
+
+# Check quoted user, runas and host name in Cmnd_Spec
+"foo" "hosta" = ("root") ALL
+"foo.bar" "hostb" = ("root") ALL
+"foo\"" "hostc" = ("root") ALL
+"foo:bar" "hostd" = ("root") ALL
+"foo:bar\"" "hoste" = ("root") ALL
+
+# Check quoted group/netgroup name in Cmnd_Spec
+"%baz" "hosta" = ("root") ALL
+"%baz.biz" "hostb" = ("root") ALL
+"%:C/non UNIX 0 c" "hostc" = ("root") ALL
+"%:C/non\'UNIX\'1 c" "hostd" = ("root") ALL
+"%:C/non\"UNIX\"0 c" "hoste" = ("root") ALL
+"%:C/non_UNIX_0 c" "hostf" = ("root") ALL
+"%:C/non\'UNIX_3 c" "hostg" = ("root") ALL
+"+netgr" "hosth" = ("root") ALL
+
+# Check that quotes don't need escaping in command and args
+user ALL = /bin/ls "", /bin/echo " ", /bin/foo"bar ""
diff --git a/plugins/sudoers/regress/sudoers/test2.json.ok b/plugins/sudoers/regress/sudoers/test2.json.ok
new file mode 100644
index 0000000..46e4c48
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test2.json.ok
@@ -0,0 +1,420 @@
+{
+ "Defaults": [
+ {
+ "Binding": [
+ { "hostname": "somehost" }
+ ],
+ "Options": [
+ { "set_home": true }
+ ]
+ },
+ {
+ "Binding": [
+ { "hostname": "quoted\"" }
+ ],
+ "Options": [
+ { "set_home": true }
+ ]
+ },
+ {
+ "Binding": [
+ { "username": "you" }
+ ],
+ "Options": [
+ { "set_home": true }
+ ]
+ },
+ {
+ "Binding": [
+ { "username": "us\"" }
+ ],
+ "Options": [
+ { "set_home": true }
+ ]
+ },
+ {
+ "Binding": [
+ { "usergroup": "them" }
+ ],
+ "Options": [
+ { "set_home": true }
+ ]
+ },
+ {
+ "Binding": [
+ { "nonunixgroup": " non UNIX 0 c" }
+ ],
+ "Options": [
+ { "set_home": true }
+ ]
+ },
+ {
+ "Binding": [
+ { "netgroup": "net" }
+ ],
+ "Options": [
+ { "set_home": true }
+ ]
+ },
+ {
+ "Binding": [
+ { "username": "someone" }
+ ],
+ "Options": [
+ { "set_home": true }
+ ]
+ },
+ {
+ "Binding": [
+ { "username": "some one" }
+ ],
+ "Options": [
+ { "set_home": true }
+ ]
+ }
+ ],
+ "User_Aliases": {
+ "UA1": [
+ { "username": "foo" }
+ ],
+ "UA10": [
+ { "nonunixgroup": "C/non\"UNIX\"0 c" }
+ ],
+ "UA11": [
+ { "nonunixgroup": "C/non_UNIX_0 c" }
+ ],
+ "UA12": [
+ { "nonunixgroup": "C/non\\'UNIX_3 c" }
+ ],
+ "UA2": [
+ { "username": "foo.bar" }
+ ],
+ "UA3": [
+ { "username": "foo\"" }
+ ],
+ "UA4": [
+ { "username": "foo:bar" }
+ ],
+ "UA5": [
+ { "username": "foo:bar\"" }
+ ],
+ "UA6": [
+ { "usergroup": "baz" }
+ ],
+ "UA7": [
+ { "usergroup": "baz.biz" }
+ ],
+ "UA8": [
+ { "nonunixgroup": "C/non UNIX 0 c" }
+ ],
+ "UA9": [
+ { "nonunixgroup": "C/non\\'UNIX\\'1 c" }
+ ]
+ },
+ "Runas_Aliases": {
+ "RA1": [
+ { "username": "foo" }
+ ],
+ "RA2": [
+ { "username": "foo\"" }
+ ],
+ "RA3": [
+ { "username": "foo:bar" }
+ ],
+ "RA4": [
+ { "username": "foo:bar\"" }
+ ]
+ },
+ "User_Specs": [
+ {
+ "User_List": [
+ { "username": "foo" }
+ ],
+ "Host_List": [
+ { "hostname": "hosta" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "root" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "foo.bar" }
+ ],
+ "Host_List": [
+ { "hostname": "hostb" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "root" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "foo\"" }
+ ],
+ "Host_List": [
+ { "hostname": "hostc" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "root" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "foo:bar" }
+ ],
+ "Host_List": [
+ { "hostname": "hostd" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "root" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "foo:bar\"" }
+ ],
+ "Host_List": [
+ { "hostname": "hoste" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "root" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "usergroup": "baz" }
+ ],
+ "Host_List": [
+ { "hostname": "hosta" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "root" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "usergroup": "baz.biz" }
+ ],
+ "Host_List": [
+ { "hostname": "hostb" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "root" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "nonunixgroup": "C/non UNIX 0 c" }
+ ],
+ "Host_List": [
+ { "hostname": "hostc" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "root" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "nonunixgroup": "C/non\\'UNIX\\'1 c" }
+ ],
+ "Host_List": [
+ { "hostname": "hostd" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "root" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "nonunixgroup": "C/non\"UNIX\"0 c" }
+ ],
+ "Host_List": [
+ { "hostname": "hoste" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "root" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "nonunixgroup": "C/non_UNIX_0 c" }
+ ],
+ "Host_List": [
+ { "hostname": "hostf" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "root" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "nonunixgroup": "C/non\\'UNIX_3 c" }
+ ],
+ "Host_List": [
+ { "hostname": "hostg" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "root" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "netgroup": "netgr" }
+ ],
+ "Host_List": [
+ { "hostname": "hosth" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "root" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "command": "/bin/ls \"\"" },
+ { "command": "/bin/echo \" \"" },
+ { "command": "/bin/foo\"bar \"\"" }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/sudoers/test2.ldif.ok b/plugins/sudoers/regress/sudoers/test2.ldif.ok
new file mode 100644
index 0000000..31d708f
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test2.ldif.ok
@@ -0,0 +1,168 @@
+# Unable to translate stdin:26:29:
+# Defaults@somehost set_home
+
+# Unable to translate stdin:27:29:
+# Defaults@quoted\" set_home
+
+# Unable to translate stdin:30:24:
+# Defaults:you set_home
+
+# Unable to translate stdin:31:25:
+# Defaults:us\" set_home
+
+# Unable to translate stdin:32:26:
+# Defaults:%them set_home
+
+# Unable to translate stdin:33:36:
+# Defaults:"%: non UNIX 0 c" set_home
+
+# Unable to translate stdin:34:25:
+# Defaults:+net set_home
+
+# Unable to translate stdin:37:28:
+# Defaults>someone set_home
+
+# Unable to translate stdin:38:29:
+# Defaults>"some one" set_home
+
+dn: cn=foo,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: foo
+sudoUser: foo
+sudoHost: hosta
+sudoRunAsUser: root
+sudoCommand: ALL
+sudoOrder: 1
+
+dn: cn=foo.bar,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: foo.bar
+sudoUser: foo.bar
+sudoHost: hostb
+sudoRunAsUser: root
+sudoCommand: ALL
+sudoOrder: 2
+
+dn: cn=foo\",ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: foo\"
+sudoUser: foo"
+sudoHost: hostc
+sudoRunAsUser: root
+sudoCommand: ALL
+sudoOrder: 3
+
+dn: cn=foo:bar,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: foo:bar
+sudoUser: foo:bar
+sudoHost: hostd
+sudoRunAsUser: root
+sudoCommand: ALL
+sudoOrder: 4
+
+dn: cn=foo:bar\",ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: foo:bar\"
+sudoUser: foo:bar"
+sudoHost: hoste
+sudoRunAsUser: root
+sudoCommand: ALL
+sudoOrder: 5
+
+dn: cn=%baz,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: %baz
+sudoUser: %baz
+sudoHost: hosta
+sudoRunAsUser: root
+sudoCommand: ALL
+sudoOrder: 6
+
+dn: cn=%baz.biz,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: %baz.biz
+sudoUser: %baz.biz
+sudoHost: hostb
+sudoRunAsUser: root
+sudoCommand: ALL
+sudoOrder: 7
+
+dn: cn=%:C/non UNIX 0 c,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: %:C/non UNIX 0 c
+sudoUser: %:C/non UNIX 0 c
+sudoHost: hostc
+sudoRunAsUser: root
+sudoCommand: ALL
+sudoOrder: 8
+
+dn: cn=%:C/non\\'UNIX\\'1 c,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: %:C/non\\'UNIX\\'1 c
+sudoUser: %:C/non\'UNIX\'1 c
+sudoHost: hostd
+sudoRunAsUser: root
+sudoCommand: ALL
+sudoOrder: 9
+
+dn: cn=%:C/non\"UNIX\"0 c,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: %:C/non\"UNIX\"0 c
+sudoUser: %:C/non"UNIX"0 c
+sudoHost: hoste
+sudoRunAsUser: root
+sudoCommand: ALL
+sudoOrder: 10
+
+dn: cn=%:C/non_UNIX_0 c,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: %:C/non_UNIX_0 c
+sudoUser: %:C/non_UNIX_0 c
+sudoHost: hostf
+sudoRunAsUser: root
+sudoCommand: ALL
+sudoOrder: 11
+
+dn: cn=%:C/non\\'UNIX_3 c,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: %:C/non\\'UNIX_3 c
+sudoUser: %:C/non\'UNIX_3 c
+sudoHost: hostg
+sudoRunAsUser: root
+sudoCommand: ALL
+sudoOrder: 12
+
+dn: cn=\+netgr,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: \+netgr
+sudoUser: +netgr
+sudoHost: hosth
+sudoRunAsUser: root
+sudoCommand: ALL
+sudoOrder: 13
+
+dn: cn=user,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user
+sudoUser: user
+sudoHost: ALL
+sudoCommand: /bin/ls ""
+sudoCommand: /bin/echo " "
+sudoCommand: /bin/foo"bar ""
+sudoOrder: 14
+
diff --git a/plugins/sudoers/regress/sudoers/test2.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test2.ldif2sudo.ok
new file mode 100644
index 0000000..0277437
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test2.ldif2sudo.ok
@@ -0,0 +1,41 @@
+# sudoRole foo
+foo hosta = (root) ALL
+
+# sudoRole foo.bar
+foo.bar hostb = (root) ALL
+
+# sudoRole foo"
+foo\" hostc = (root) ALL
+
+# sudoRole foo:bar
+foo\:bar hostd = (root) ALL
+
+# sudoRole foo:bar"
+foo\:bar\" hoste = (root) ALL
+
+# sudoRole %baz
+%baz hosta = (root) ALL
+
+# sudoRole %baz.biz
+%baz.biz hostb = (root) ALL
+
+# sudoRole %:C/non UNIX 0 c
+"%:C/non UNIX 0 c" hostc = (root) ALL
+
+# sudoRole %:C/non\'UNIX\'1 c
+"%:C/non\'UNIX\'1 c" hostd = (root) ALL
+
+# sudoRole %:C/non"UNIX"0 c
+"%:C/non\"UNIX\"0 c" hoste = (root) ALL
+
+# sudoRole %:C/non_UNIX_0 c
+"%:C/non_UNIX_0 c" hostf = (root) ALL
+
+# sudoRole %:C/non\'UNIX_3 c
+"%:C/non\'UNIX_3 c" hostg = (root) ALL
+
+# sudoRole +netgr
++netgr hosth = (root) ALL
+
+# sudoRole user
+user ALL = /bin/ls "", /bin/echo " ", /bin/foo"bar ""
diff --git a/plugins/sudoers/regress/sudoers/test2.out.ok b/plugins/sudoers/regress/sudoers/test2.out.ok
new file mode 100644
index 0000000..99171b9
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test2.out.ok
@@ -0,0 +1,43 @@
+Parses OK
+
+Defaults@somehost set_home
+Defaults@quoted\" set_home
+Defaults:you set_home
+Defaults:us\" set_home
+Defaults:%them set_home
+Defaults:"%: non UNIX 0 c" set_home
+Defaults:+net set_home
+Defaults>someone set_home
+Defaults>"some one" set_home
+
+Runas_Alias RA1 = foo
+Runas_Alias RA2 = foo\"
+Runas_Alias RA3 = foo\:bar
+Runas_Alias RA4 = foo\:bar\"
+User_Alias UA1 = foo
+User_Alias UA10 = "%:C/non\"UNIX\"0 c"
+User_Alias UA11 = "%:C/non_UNIX_0 c"
+User_Alias UA12 = "%:C/non\'UNIX_3 c"
+User_Alias UA2 = foo.bar
+User_Alias UA3 = foo\"
+User_Alias UA4 = foo\:bar
+User_Alias UA5 = foo\:bar\"
+User_Alias UA6 = %baz
+User_Alias UA7 = %baz.biz
+User_Alias UA8 = "%:C/non UNIX 0 c"
+User_Alias UA9 = "%:C/non\'UNIX\'1 c"
+
+foo hosta = (root) ALL
+foo.bar hostb = (root) ALL
+foo\" hostc = (root) ALL
+foo\:bar hostd = (root) ALL
+foo\:bar\" hoste = (root) ALL
+%baz hosta = (root) ALL
+%baz.biz hostb = (root) ALL
+"%:C/non UNIX 0 c" hostc = (root) ALL
+"%:C/non\'UNIX\'1 c" hostd = (root) ALL
+"%:C/non\"UNIX\"0 c" hoste = (root) ALL
+"%:C/non_UNIX_0 c" hostf = (root) ALL
+"%:C/non\'UNIX_3 c" hostg = (root) ALL
++netgr hosth = (root) ALL
+user ALL = /bin/ls "", /bin/echo " ", /bin/foo"bar ""
diff --git a/plugins/sudoers/regress/sudoers/test2.toke.ok b/plugins/sudoers/regress/sudoers/test2.toke.ok
new file mode 100644
index 0000000..4c4b88d
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test2.toke.ok
@@ -0,0 +1,63 @@
+#
+USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4)
+USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4)
+USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4)
+USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4)
+USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4)
+
+#
+USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR USERGROUP
+USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR USERGROUP
+
+#
+USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR USERGROUP
+USERALIAS ALIAS = BEGINSTR STRBODY BACKSLASH STRBODY BACKSLASH STRBODY ENDSTR USERGROUP
+USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR USERGROUP
+USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR USERGROUP
+USERALIAS ALIAS = BEGINSTR STRBODY BACKSLASH STRBODY ENDSTR USERGROUP
+
+#
+RUNASALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4)
+RUNASALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4)
+RUNASALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4)
+RUNASALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4)
+
+#
+DEFAULTS_HOST BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR
+DEFAULTS_HOST BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR
+
+#
+DEFAULTS_USER BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR
+DEFAULTS_USER BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR
+DEFAULTS_USER BEGINSTR STRBODY ENDSTR USERGROUP DEFVAR
+DEFAULTS_USER BEGINSTR STRBODY ENDSTR USERGROUP DEFVAR
+DEFAULTS_USER BEGINSTR STRBODY ENDSTR NETGROUP DEFVAR
+
+#
+DEFAULTS_RUNAS BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR
+DEFAULTS_RUNAS BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR
+
+#
+#
+#
+#
+
+#
+BEGINSTR STRBODY ENDSTR WORD(4) BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL
+BEGINSTR STRBODY ENDSTR WORD(4) BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL
+BEGINSTR STRBODY ENDSTR WORD(4) BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL
+BEGINSTR STRBODY ENDSTR WORD(4) BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL
+BEGINSTR STRBODY ENDSTR WORD(4) BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL
+
+#
+BEGINSTR STRBODY ENDSTR USERGROUP BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL
+BEGINSTR STRBODY ENDSTR USERGROUP BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL
+BEGINSTR STRBODY ENDSTR USERGROUP BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL
+BEGINSTR STRBODY BACKSLASH STRBODY BACKSLASH STRBODY ENDSTR USERGROUP BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL
+BEGINSTR STRBODY ENDSTR USERGROUP BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL
+BEGINSTR STRBODY ENDSTR USERGROUP BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL
+BEGINSTR STRBODY BACKSLASH STRBODY ENDSTR USERGROUP BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL
+BEGINSTR STRBODY ENDSTR NETGROUP BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL
+
+#
+WORD(6) ALL = COMMAND ARG , COMMAND ARG ARG , COMMAND ARG
diff --git a/plugins/sudoers/regress/sudoers/test20.in b/plugins/sudoers/regress/sudoers/test20.in
new file mode 100644
index 0000000..c24f88a
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test20.in
@@ -0,0 +1,26 @@
+# Test parsing of tuples
+Defaults lecture
+Defaults !lecture
+Defaults lecture=never
+Defaults lecture=once
+Defaults lecture=always
+
+Defaults listpw
+Defaults !listpw
+Defaults listpw=never
+Defaults listpw=any
+Defaults listpw=all
+Defaults listpw=always
+
+Defaults verifypw
+Defaults !verifypw
+Defaults verifypw=never
+Defaults verifypw=any
+Defaults verifypw=all
+Defaults verifypw=always
+
+Defaults fdexec
+Defaults !fdexec
+Defaults fdexec=never
+Defaults fdexec=digest_only
+Defaults fdexec=always
diff --git a/plugins/sudoers/regress/sudoers/test20.json.ok b/plugins/sudoers/regress/sudoers/test20.json.ok
new file mode 100644
index 0000000..f2f1d55
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test20.json.ok
@@ -0,0 +1,114 @@
+{
+ "Defaults": [
+ {
+ "Options": [
+ { "lecture": true }
+ ]
+ },
+ {
+ "Options": [
+ { "lecture": false }
+ ]
+ },
+ {
+ "Options": [
+ { "lecture": "never" }
+ ]
+ },
+ {
+ "Options": [
+ { "lecture": "once" }
+ ]
+ },
+ {
+ "Options": [
+ { "lecture": "always" }
+ ]
+ },
+ {
+ "Options": [
+ { "listpw": true }
+ ]
+ },
+ {
+ "Options": [
+ { "listpw": false }
+ ]
+ },
+ {
+ "Options": [
+ { "listpw": "never" }
+ ]
+ },
+ {
+ "Options": [
+ { "listpw": "any" }
+ ]
+ },
+ {
+ "Options": [
+ { "listpw": "all" }
+ ]
+ },
+ {
+ "Options": [
+ { "listpw": "always" }
+ ]
+ },
+ {
+ "Options": [
+ { "verifypw": true }
+ ]
+ },
+ {
+ "Options": [
+ { "verifypw": false }
+ ]
+ },
+ {
+ "Options": [
+ { "verifypw": "never" }
+ ]
+ },
+ {
+ "Options": [
+ { "verifypw": "any" }
+ ]
+ },
+ {
+ "Options": [
+ { "verifypw": "all" }
+ ]
+ },
+ {
+ "Options": [
+ { "verifypw": "always" }
+ ]
+ },
+ {
+ "Options": [
+ { "fdexec": true }
+ ]
+ },
+ {
+ "Options": [
+ { "fdexec": false }
+ ]
+ },
+ {
+ "Options": [
+ { "fdexec": "never" }
+ ]
+ },
+ {
+ "Options": [
+ { "fdexec": "digest_only" }
+ ]
+ },
+ {
+ "Options": [
+ { "fdexec": "always" }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/sudoers/test20.ldif.ok b/plugins/sudoers/regress/sudoers/test20.ldif.ok
new file mode 100644
index 0000000..de01cde
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test20.ldif.ok
@@ -0,0 +1,28 @@
+dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: lecture
+sudoOption: !lecture
+sudoOption: lecture=never
+sudoOption: lecture=once
+sudoOption: lecture=always
+sudoOption: listpw
+sudoOption: !listpw
+sudoOption: listpw=never
+sudoOption: listpw=any
+sudoOption: listpw=all
+sudoOption: listpw=always
+sudoOption: verifypw
+sudoOption: !verifypw
+sudoOption: verifypw=never
+sudoOption: verifypw=any
+sudoOption: verifypw=all
+sudoOption: verifypw=always
+sudoOption: fdexec
+sudoOption: !fdexec
+sudoOption: fdexec=never
+sudoOption: fdexec=digest_only
+sudoOption: fdexec=always
+
diff --git a/plugins/sudoers/regress/sudoers/test20.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test20.ldif2sudo.ok
new file mode 100644
index 0000000..e1c743c
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test20.ldif2sudo.ok
@@ -0,0 +1,22 @@
+Defaults lecture
+Defaults !lecture
+Defaults lecture=never
+Defaults lecture=once
+Defaults lecture=always
+Defaults listpw
+Defaults !listpw
+Defaults listpw=never
+Defaults listpw=any
+Defaults listpw=all
+Defaults listpw=always
+Defaults verifypw
+Defaults !verifypw
+Defaults verifypw=never
+Defaults verifypw=any
+Defaults verifypw=all
+Defaults verifypw=always
+Defaults fdexec
+Defaults !fdexec
+Defaults fdexec=never
+Defaults fdexec=digest_only
+Defaults fdexec=always
diff --git a/plugins/sudoers/regress/sudoers/test20.out.ok b/plugins/sudoers/regress/sudoers/test20.out.ok
new file mode 100644
index 0000000..260be81
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test20.out.ok
@@ -0,0 +1,24 @@
+Parses OK
+
+Defaults lecture
+Defaults !lecture
+Defaults lecture=never
+Defaults lecture=once
+Defaults lecture=always
+Defaults listpw
+Defaults !listpw
+Defaults listpw=never
+Defaults listpw=any
+Defaults listpw=all
+Defaults listpw=always
+Defaults verifypw
+Defaults !verifypw
+Defaults verifypw=never
+Defaults verifypw=any
+Defaults verifypw=all
+Defaults verifypw=always
+Defaults fdexec
+Defaults !fdexec
+Defaults fdexec=never
+Defaults fdexec=digest_only
+Defaults fdexec=always
diff --git a/plugins/sudoers/regress/sudoers/test20.toke.ok b/plugins/sudoers/regress/sudoers/test20.toke.ok
new file mode 100644
index 0000000..1847149
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test20.toke.ok
@@ -0,0 +1,26 @@
+#
+DEFAULTS DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+
+DEFAULTS DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+
+DEFAULTS DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+
+DEFAULTS DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
diff --git a/plugins/sudoers/regress/sudoers/test21.in b/plugins/sudoers/regress/sudoers/test21.in
new file mode 100644
index 0000000..65416cf
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test21.in
@@ -0,0 +1,36 @@
+# Test parsing of syslog settings
+Defaults syslog
+Defaults !syslog
+Defaults syslog=auth
+Defaults syslog=daemon
+Defaults syslog=user
+Defaults syslog=local0
+Defaults syslog=local1
+Defaults syslog=local2
+Defaults syslog=local3
+Defaults syslog=local4
+Defaults syslog=local5
+Defaults syslog=local6
+Defaults syslog=local7
+
+Defaults !syslog_goodpri
+Defaults syslog_goodpri=alert
+Defaults syslog_goodpri=crit
+Defaults syslog_goodpri=debug
+Defaults syslog_goodpri=emerg
+Defaults syslog_goodpri=err
+Defaults syslog_goodpri=info
+Defaults syslog_goodpri=notice
+Defaults syslog_goodpri=warning
+Defaults syslog_goodpri=none
+
+Defaults !syslog_badpri
+Defaults syslog_badpri=alert
+Defaults syslog_badpri=crit
+Defaults syslog_badpri=debug
+Defaults syslog_badpri=emerg
+Defaults syslog_badpri=err
+Defaults syslog_badpri=info
+Defaults syslog_badpri=notice
+Defaults syslog_badpri=warning
+Defaults syslog_badpri=none
diff --git a/plugins/sudoers/regress/sudoers/test21.json.ok b/plugins/sudoers/regress/sudoers/test21.json.ok
new file mode 100644
index 0000000..7896965
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test21.json.ok
@@ -0,0 +1,169 @@
+{
+ "Defaults": [
+ {
+ "Options": [
+ { "syslog": true }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog": false }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog": "auth" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog": "daemon" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog": "user" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog": "local0" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog": "local1" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog": "local2" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog": "local3" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog": "local4" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog": "local5" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog": "local6" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog": "local7" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_goodpri": false }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_goodpri": "alert" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_goodpri": "crit" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_goodpri": "debug" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_goodpri": "emerg" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_goodpri": "err" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_goodpri": "info" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_goodpri": "notice" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_goodpri": "warning" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_goodpri": "none" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_badpri": false }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_badpri": "alert" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_badpri": "crit" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_badpri": "debug" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_badpri": "emerg" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_badpri": "err" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_badpri": "info" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_badpri": "notice" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_badpri": "warning" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_badpri": "none" }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/sudoers/test21.ldif.ok b/plugins/sudoers/regress/sudoers/test21.ldif.ok
new file mode 100644
index 0000000..b3bede8
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test21.ldif.ok
@@ -0,0 +1,39 @@
+dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: syslog
+sudoOption: !syslog
+sudoOption: syslog=auth
+sudoOption: syslog=daemon
+sudoOption: syslog=user
+sudoOption: syslog=local0
+sudoOption: syslog=local1
+sudoOption: syslog=local2
+sudoOption: syslog=local3
+sudoOption: syslog=local4
+sudoOption: syslog=local5
+sudoOption: syslog=local6
+sudoOption: syslog=local7
+sudoOption: !syslog_goodpri
+sudoOption: syslog_goodpri=alert
+sudoOption: syslog_goodpri=crit
+sudoOption: syslog_goodpri=debug
+sudoOption: syslog_goodpri=emerg
+sudoOption: syslog_goodpri=err
+sudoOption: syslog_goodpri=info
+sudoOption: syslog_goodpri=notice
+sudoOption: syslog_goodpri=warning
+sudoOption: syslog_goodpri=none
+sudoOption: !syslog_badpri
+sudoOption: syslog_badpri=alert
+sudoOption: syslog_badpri=crit
+sudoOption: syslog_badpri=debug
+sudoOption: syslog_badpri=emerg
+sudoOption: syslog_badpri=err
+sudoOption: syslog_badpri=info
+sudoOption: syslog_badpri=notice
+sudoOption: syslog_badpri=warning
+sudoOption: syslog_badpri=none
+
diff --git a/plugins/sudoers/regress/sudoers/test21.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test21.ldif2sudo.ok
new file mode 100644
index 0000000..56e09ff
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test21.ldif2sudo.ok
@@ -0,0 +1,33 @@
+Defaults syslog
+Defaults !syslog
+Defaults syslog=auth
+Defaults syslog=daemon
+Defaults syslog=user
+Defaults syslog=local0
+Defaults syslog=local1
+Defaults syslog=local2
+Defaults syslog=local3
+Defaults syslog=local4
+Defaults syslog=local5
+Defaults syslog=local6
+Defaults syslog=local7
+Defaults !syslog_goodpri
+Defaults syslog_goodpri=alert
+Defaults syslog_goodpri=crit
+Defaults syslog_goodpri=debug
+Defaults syslog_goodpri=emerg
+Defaults syslog_goodpri=err
+Defaults syslog_goodpri=info
+Defaults syslog_goodpri=notice
+Defaults syslog_goodpri=warning
+Defaults syslog_goodpri=none
+Defaults !syslog_badpri
+Defaults syslog_badpri=alert
+Defaults syslog_badpri=crit
+Defaults syslog_badpri=debug
+Defaults syslog_badpri=emerg
+Defaults syslog_badpri=err
+Defaults syslog_badpri=info
+Defaults syslog_badpri=notice
+Defaults syslog_badpri=warning
+Defaults syslog_badpri=none
diff --git a/plugins/sudoers/regress/sudoers/test21.out.ok b/plugins/sudoers/regress/sudoers/test21.out.ok
new file mode 100644
index 0000000..136ec64
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test21.out.ok
@@ -0,0 +1,35 @@
+Parses OK
+
+Defaults syslog
+Defaults !syslog
+Defaults syslog=auth
+Defaults syslog=daemon
+Defaults syslog=user
+Defaults syslog=local0
+Defaults syslog=local1
+Defaults syslog=local2
+Defaults syslog=local3
+Defaults syslog=local4
+Defaults syslog=local5
+Defaults syslog=local6
+Defaults syslog=local7
+Defaults !syslog_goodpri
+Defaults syslog_goodpri=alert
+Defaults syslog_goodpri=crit
+Defaults syslog_goodpri=debug
+Defaults syslog_goodpri=emerg
+Defaults syslog_goodpri=err
+Defaults syslog_goodpri=info
+Defaults syslog_goodpri=notice
+Defaults syslog_goodpri=warning
+Defaults syslog_goodpri=none
+Defaults !syslog_badpri
+Defaults syslog_badpri=alert
+Defaults syslog_badpri=crit
+Defaults syslog_badpri=debug
+Defaults syslog_badpri=emerg
+Defaults syslog_badpri=err
+Defaults syslog_badpri=info
+Defaults syslog_badpri=notice
+Defaults syslog_badpri=warning
+Defaults syslog_badpri=none
diff --git a/plugins/sudoers/regress/sudoers/test21.toke.ok b/plugins/sudoers/regress/sudoers/test21.toke.ok
new file mode 100644
index 0000000..871584b
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test21.toke.ok
@@ -0,0 +1,36 @@
+#
+DEFAULTS DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
diff --git a/plugins/sudoers/regress/sudoers/test22.in b/plugins/sudoers/regress/sudoers/test22.in
new file mode 100644
index 0000000..ecf2fd9
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test22.in
@@ -0,0 +1,6 @@
+# Test parsing of empty Runas_List
+
+user1 ALL = ( : ) ALL
+user2 ALL = (:) ALL
+user3 ALL = ( ) ALL
+user4 ALL = () ALL
diff --git a/plugins/sudoers/regress/sudoers/test22.json.ok b/plugins/sudoers/regress/sudoers/test22.json.ok
new file mode 100644
index 0000000..22141a1
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test22.json.ok
@@ -0,0 +1,88 @@
+{
+ "User_Specs": [
+ {
+ "User_List": [
+ { "username": "user1" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user2" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user3" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user4" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/sudoers/test22.ldif.ok b/plugins/sudoers/regress/sudoers/test22.ldif.ok
new file mode 100644
index 0000000..14c3df4
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test22.ldif.ok
@@ -0,0 +1,40 @@
+dn: cn=user1,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user1
+sudoUser: user1
+sudoHost: ALL
+sudoRunAsUser:
+sudoCommand: ALL
+sudoOrder: 1
+
+dn: cn=user2,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user2
+sudoUser: user2
+sudoHost: ALL
+sudoRunAsUser:
+sudoCommand: ALL
+sudoOrder: 2
+
+dn: cn=user3,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user3
+sudoUser: user3
+sudoHost: ALL
+sudoRunAsUser:
+sudoCommand: ALL
+sudoOrder: 3
+
+dn: cn=user4,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user4
+sudoUser: user4
+sudoHost: ALL
+sudoRunAsUser:
+sudoCommand: ALL
+sudoOrder: 4
+
diff --git a/plugins/sudoers/regress/sudoers/test22.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test22.ldif2sudo.ok
new file mode 100644
index 0000000..e0c98e0
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test22.ldif2sudo.ok
@@ -0,0 +1,11 @@
+# sudoRole user1
+user1 ALL = () ALL
+
+# sudoRole user2
+user2 ALL = () ALL
+
+# sudoRole user3
+user3 ALL = () ALL
+
+# sudoRole user4
+user4 ALL = () ALL
diff --git a/plugins/sudoers/regress/sudoers/test22.out.ok b/plugins/sudoers/regress/sudoers/test22.out.ok
new file mode 100644
index 0000000..7117e18
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test22.out.ok
@@ -0,0 +1,6 @@
+Parses OK
+
+user1 ALL = (root) ALL
+user2 ALL = (root) ALL
+user3 ALL = (root) ALL
+user4 ALL = (root) ALL
diff --git a/plugins/sudoers/regress/sudoers/test22.toke.ok b/plugins/sudoers/regress/sudoers/test22.toke.ok
new file mode 100644
index 0000000..9eeb964
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test22.toke.ok
@@ -0,0 +1,6 @@
+#
+
+WORD(6) ALL = ( : ) ALL
+WORD(6) ALL = ( : ) ALL
+WORD(6) ALL = ( ) ALL
+WORD(6) ALL = ( ) ALL
diff --git a/plugins/sudoers/regress/sudoers/test23.in b/plugins/sudoers/regress/sudoers/test23.in
new file mode 100644
index 0000000..5e03d9e
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test23.in
@@ -0,0 +1,11 @@
+# Test parsing of env_check, env_delete and env_keep
+Defaults env_check = "COLORTERM LANG LANGUAGE LC_* LINGUAS"
+Defaults env_check += "TERM TZ"
+
+Defaults env_delete = "IFS CDPATH LOCALDOMAIN RES_OPTIONS HOSTALIASES"
+Defaults env_delete += "NLSPATH PATH_LOCALE LD_* _RLD*"
+
+Defaults env_keep += "LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET"
+Defaults env_keep -= _XKB_CHARSET
+Defaults env_keep += "XAPPLRESDIR XFILESEARCHPATH XUSERFILESEARCHPATH"
+Defaults env_keep += XDG_SESSION_COOKIE
diff --git a/plugins/sudoers/regress/sudoers/test23.json.ok b/plugins/sudoers/regress/sudoers/test23.json.ok
new file mode 100644
index 0000000..5e8b0da
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test23.json.ok
@@ -0,0 +1,102 @@
+{
+ "Defaults": [
+ {
+ "Options": [
+ {
+ "operation": "list_assign",
+ "env_check": [
+ "COLORTERM",
+ "LANG",
+ "LANGUAGE",
+ "LC_*",
+ "LINGUAS"
+ ]
+ }
+ ]
+ },
+ {
+ "Options": [
+ {
+ "operation": "list_add",
+ "env_check": [
+ "TERM",
+ "TZ"
+ ]
+ }
+ ]
+ },
+ {
+ "Options": [
+ {
+ "operation": "list_assign",
+ "env_delete": [
+ "IFS",
+ "CDPATH",
+ "LOCALDOMAIN",
+ "RES_OPTIONS",
+ "HOSTALIASES"
+ ]
+ }
+ ]
+ },
+ {
+ "Options": [
+ {
+ "operation": "list_add",
+ "env_delete": [
+ "NLSPATH",
+ "PATH_LOCALE",
+ "LD_*",
+ "_RLD*"
+ ]
+ }
+ ]
+ },
+ {
+ "Options": [
+ {
+ "operation": "list_add",
+ "env_keep": [
+ "LANG",
+ "LANGUAGE",
+ "LINGUAS",
+ "LC_*",
+ "_XKB_CHARSET"
+ ]
+ }
+ ]
+ },
+ {
+ "Options": [
+ {
+ "operation": "list_remove",
+ "env_keep": [
+ "_XKB_CHARSET"
+ ]
+ }
+ ]
+ },
+ {
+ "Options": [
+ {
+ "operation": "list_add",
+ "env_keep": [
+ "XAPPLRESDIR",
+ "XFILESEARCHPATH",
+ "XUSERFILESEARCHPATH"
+ ]
+ }
+ ]
+ },
+ {
+ "Options": [
+ {
+ "operation": "list_add",
+ "env_keep": [
+ "XDG_SESSION_COOKIE"
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/sudoers/test23.ldif.ok b/plugins/sudoers/regress/sudoers/test23.ldif.ok
new file mode 100644
index 0000000..97c1fbd
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test23.ldif.ok
@@ -0,0 +1,14 @@
+dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: env_check=COLORTERM LANG LANGUAGE LC_* LINGUAS
+sudoOption: env_check+=TERM TZ
+sudoOption: env_delete=IFS CDPATH LOCALDOMAIN RES_OPTIONS HOSTALIASES
+sudoOption: env_delete+=NLSPATH PATH_LOCALE LD_* _RLD*
+sudoOption: env_keep+=LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET
+sudoOption: env_keep-=_XKB_CHARSET
+sudoOption: env_keep+=XAPPLRESDIR XFILESEARCHPATH XUSERFILESEARCHPATH
+sudoOption: env_keep+=XDG_SESSION_COOKIE
+
diff --git a/plugins/sudoers/regress/sudoers/test23.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test23.ldif2sudo.ok
new file mode 100644
index 0000000..bb9f2e9
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test23.ldif2sudo.ok
@@ -0,0 +1,8 @@
+Defaults env_check="COLORTERM LANG LANGUAGE LC_* LINGUAS"
+Defaults env_check+="TERM TZ"
+Defaults env_delete="IFS CDPATH LOCALDOMAIN RES_OPTIONS HOSTALIASES"
+Defaults env_delete+="NLSPATH PATH_LOCALE LD_* _RLD*"
+Defaults env_keep+="LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET"
+Defaults env_keep-=_XKB_CHARSET
+Defaults env_keep+="XAPPLRESDIR XFILESEARCHPATH XUSERFILESEARCHPATH"
+Defaults env_keep+=XDG_SESSION_COOKIE
diff --git a/plugins/sudoers/regress/sudoers/test23.out.ok b/plugins/sudoers/regress/sudoers/test23.out.ok
new file mode 100644
index 0000000..fe6e415
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test23.out.ok
@@ -0,0 +1,10 @@
+Parses OK
+
+Defaults env_check="COLORTERM LANG LANGUAGE LC_* LINGUAS"
+Defaults env_check+="TERM TZ"
+Defaults env_delete="IFS CDPATH LOCALDOMAIN RES_OPTIONS HOSTALIASES"
+Defaults env_delete+="NLSPATH PATH_LOCALE LD_* _RLD*"
+Defaults env_keep+="LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET"
+Defaults env_keep-=_XKB_CHARSET
+Defaults env_keep+="XAPPLRESDIR XFILESEARCHPATH XUSERFILESEARCHPATH"
+Defaults env_keep+=XDG_SESSION_COOKIE
diff --git a/plugins/sudoers/regress/sudoers/test23.toke.ok b/plugins/sudoers/regress/sudoers/test23.toke.ok
new file mode 100644
index 0000000..3d7cd84
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test23.toke.ok
@@ -0,0 +1,11 @@
+#
+DEFAULTS DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4)
+DEFAULTS DEFVAR += BEGINSTR STRBODY ENDSTR WORD(4)
+
+DEFAULTS DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4)
+DEFAULTS DEFVAR += BEGINSTR STRBODY ENDSTR WORD(4)
+
+DEFAULTS DEFVAR += BEGINSTR STRBODY ENDSTR WORD(4)
+DEFAULTS DEFVAR -= WORD(2)
+DEFAULTS DEFVAR += BEGINSTR STRBODY ENDSTR WORD(4)
+DEFAULTS DEFVAR += WORD(2)
diff --git a/plugins/sudoers/regress/sudoers/test24.in b/plugins/sudoers/regress/sudoers/test24.in
new file mode 100644
index 0000000..3fc3bbc
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test24.in
@@ -0,0 +1,6 @@
+# Test parsing of CHROOT and CWD syntax
+Defaults runcwd=~
+Defaults runchroot=/
+#
+user0 ALL = CHROOT=/var/www CWD=/htdocs /bin/ksh
+user1 ALL = CWD=~root /usr/bin/id, CWD=/tmp /bin/ls
diff --git a/plugins/sudoers/regress/sudoers/test24.json.ok b/plugins/sudoers/regress/sudoers/test24.json.ok
new file mode 100644
index 0000000..964359c
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test24.json.ok
@@ -0,0 +1,61 @@
+{
+ "Defaults": [
+ {
+ "Options": [
+ { "runcwd": "~" }
+ ]
+ },
+ {
+ "Options": [
+ { "runchroot": "/" }
+ ]
+ }
+ ],
+ "User_Specs": [
+ {
+ "User_List": [
+ { "username": "user0" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ "runchroot": "/var/www",
+ "runcwd": "/htdocs"
+ ],
+ "Commands": [
+ { "command": "/bin/ksh" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user1" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ "runcwd": "~root"
+ ],
+ "Commands": [
+ { "command": "/usr/bin/id" }
+ ]
+ },
+ {
+ "Options": [
+ "runcwd": "/tmp"
+ ],
+ "Commands": [
+ { "command": "/bin/ls" }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/sudoers/test24.ldif.ok b/plugins/sudoers/regress/sudoers/test24.ldif.ok
new file mode 100644
index 0000000..aeb5f7a
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test24.ldif.ok
@@ -0,0 +1,39 @@
+dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: runcwd=~
+sudoOption: runchroot=/
+
+dn: cn=user0,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user0
+sudoUser: user0
+sudoHost: ALL
+sudoOption: runchroot=/var/www
+sudoOption: runcwd=/htdocs
+sudoCommand: /bin/ksh
+sudoOrder: 1
+
+dn: cn=user1,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user1
+sudoUser: user1
+sudoHost: ALL
+sudoOption: runcwd=~root
+sudoCommand: /usr/bin/id
+sudoOrder: 2
+
+dn: cn=user1_1,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user1_1
+sudoUser: user1
+sudoHost: ALL
+sudoOption: runcwd=/tmp
+sudoCommand: /bin/ls
+sudoOrder: 3
+
diff --git a/plugins/sudoers/regress/sudoers/test24.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test24.ldif2sudo.ok
new file mode 100644
index 0000000..4c09657
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test24.ldif2sudo.ok
@@ -0,0 +1,8 @@
+Defaults runcwd=~
+Defaults runchroot=/
+
+# sudoRole user0
+user0 ALL = CHROOT=/var/www CWD=/htdocs /bin/ksh
+
+# sudoRole user1, user1_1
+user1 ALL = CWD=~root /usr/bin/id, CWD=/tmp /bin/ls
diff --git a/plugins/sudoers/regress/sudoers/test24.out.ok b/plugins/sudoers/regress/sudoers/test24.out.ok
new file mode 100644
index 0000000..530b700
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test24.out.ok
@@ -0,0 +1,7 @@
+Parses OK
+
+Defaults runcwd=~
+Defaults runchroot=/
+
+user0 ALL = CHROOT=/var/www CWD=/htdocs /bin/ksh
+user1 ALL = CWD=~root /usr/bin/id, CWD=/tmp /bin/ls
diff --git a/plugins/sudoers/regress/sudoers/test24.toke.ok b/plugins/sudoers/regress/sudoers/test24.toke.ok
new file mode 100644
index 0000000..47842f4
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test24.toke.ok
@@ -0,0 +1,6 @@
+#
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+#
+WORD(6) ALL = CHROOT = WORD(5) CWD = WORD(5) COMMAND
+WORD(6) ALL = CWD = WORD(5) COMMAND , CWD = WORD(5) COMMAND
diff --git a/plugins/sudoers/regress/sudoers/test25.in b/plugins/sudoers/regress/sudoers/test25.in
new file mode 100644
index 0000000..fe35587
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test25.in
@@ -0,0 +1,3 @@
+# Test continuation character when there is nothing to continue
+# Used to leak "~ron" when run under address sanitizer
+foo ALL = CWD=~ron /bin/ls \
diff --git a/plugins/sudoers/regress/sudoers/test25.json.ok b/plugins/sudoers/regress/sudoers/test25.json.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test25.json.ok
diff --git a/plugins/sudoers/regress/sudoers/test25.ldif.ok b/plugins/sudoers/regress/sudoers/test25.ldif.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test25.ldif.ok
diff --git a/plugins/sudoers/regress/sudoers/test25.out.ok b/plugins/sudoers/regress/sudoers/test25.out.ok
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test25.out.ok
@@ -0,0 +1 @@
+
diff --git a/plugins/sudoers/regress/sudoers/test25.toke.ok b/plugins/sudoers/regress/sudoers/test25.toke.ok
new file mode 100644
index 0000000..e58461e
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test25.toke.ok
@@ -0,0 +1,3 @@
+#
+#
+WORD(6) ALL = CWD = WORD(5) COMMAND <*> \ No newline at end of file
diff --git a/plugins/sudoers/regress/sudoers/test26.in b/plugins/sudoers/regress/sudoers/test26.in
new file mode 100644
index 0000000..842f2b4
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test26.in
@@ -0,0 +1,128 @@
+# Defaults settings that trigger callbacks
+Defaults fqdn
+Defaults runas_default=root
+Defaults tty_tickets
+Defaults umask=022
+Defaults runchroot=/
+Defaults logfile=/var/log/sudo
+Defaults log_format=json
+Defaults syslog=auth, syslog_badpri=alert, syslog_goodpri=notice
+Defaults syslog_maxlen=2048
+Defaults !loglinelen, log_year, log_host
+Defaults !mailerpath, mailerflags="-t", mailfrom="sudo@sudo.ws", mailto="root@localhost", mailsub="*** Sudo information for %h ***"
+
+# All other Defaults settings
+Defaults long_otp_prompt
+Defaults ignore_dot
+Defaults !mail_always
+Defaults !mail_badpass
+Defaults !mail_no_user
+Defaults !mail_no_host
+Defaults !mail_no_perms
+Defaults !mail_all_cmnds
+Defaults lecture=always
+Defaults lecture_file=/etc/sudo.lecture
+Defaults authenticate
+Defaults root_sudo
+Defaults shell_noargs
+Defaults set_home
+Defaults always_set_home
+Defaults path_info
+Defaults insults
+Defaults !requiretty
+Defaults env_editor
+Defaults !rootpw
+Defaults !runaspw
+Defaults !targetpw
+Defaults use_loginclass
+Defaults set_logname
+Defaults !stay_setuid
+Defaults !preserve_groups
+Defaults timestamp_timeout=.5
+Defaults passwd_timeout=5
+Defaults passwd_tries=3
+Defaults badpass_message="Take off, eh!"
+Defaults lecture_status_dir="/var/lib/sudo/lectured"
+Defaults timestampdir="/run/sudo/ts"
+Defaults timestampowner=root
+Defaults exempt_group=sudo
+Defaults passprompt="%p's sudo password: "
+Defaults passprompt_override
+Defaults secure_path="/usr/bin:/usr/sbin:/bin:/sbin"
+Defaults editor=/usr/bin/vi
+Defaults listpw=any
+Defaults verifypw=all
+Defaults noexec
+Defaults ignore_local_sudoers
+Defaults closefrom=3
+Defaults closefrom_override
+Defaults !setenv
+Defaults env_reset
+Defaults env_check += "TERMCAP"
+Defaults !env_delete
+Defaults env_keep += "LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET"
+#Defaults role
+#Defaults type
+Defaults env_file="/etc/environment"
+Defaults restricted_env_file="/etc/environment.sudo"
+Defaults sudoers_locale=C
+Defaults !visiblepw
+Defaults pwfeedback
+Defaults fast_glob
+Defaults umask_override
+Defaults log_input
+Defaults log_output
+Defaults compress_io
+Defaults use_pty
+#Defaults group_plugin
+Defaults iolog_dir="/var/log/sudo-io"
+Defaults iolog_file="%{seq}"
+Defaults set_utmp
+Defaults utmp_runas
+#Defaults privs
+#Defaults limitprivs
+Defaults !exec_background
+Defaults pam_service="sudo"
+Defaults pam_login_service="sudo-login"
+Defaults pam_setcred
+Defaults pam_session
+Defaults pam_acct_mgmt
+Defaults maxseq=2176782336
+Defaults use_netgroups
+Defaults sudoedit_checkdir
+Defaults !sudoedit_follow
+Defaults always_query_group_plugin
+Defaults netgroup_tuple
+Defaults ignore_audit_errors
+Defaults ignore_iolog_errors
+Defaults ignore_logfile_errors
+Defaults !match_group_by_gid
+Defaults iolog_user=root
+Defaults iolog_group=root
+Defaults iolog_mode=0600
+Defaults fdexec=digest_only
+Defaults !ignore_unknown_defaults
+Defaults command_timeout=7d8h30m10s
+Defaults user_command_timeouts
+Defaults iolog_flush
+Defaults syslog_pid
+Defaults timestamp_type=tty
+Defaults authfail_message="Learn to type!"
+Defaults case_insensitive_user
+Defaults case_insensitive_group
+Defaults log_allowed
+Defaults log_denied
+Defaults !log_servers
+Defaults log_server_timeout=10
+Defaults log_server_keepalive
+Defaults !log_server_cabundle
+Defaults !log_server_peer_cert
+Defaults !log_server_peer_key
+Defaults !log_server_verify
+Defaults runas_allow_unknown_id
+Defaults runas_check_shell
+Defaults pam_ruser
+Defaults pam_rhost
+Defaults runcwd=~
+Defaults !selinux
+Defaults !admin_flag
diff --git a/plugins/sudoers/regress/sudoers/test26.json.ok b/plugins/sudoers/regress/sudoers/test26.json.ok
new file mode 100644
index 0000000..4fabe5f
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test26.json.ok
@@ -0,0 +1,626 @@
+{
+ "Defaults": [
+ {
+ "Options": [
+ { "fqdn": true }
+ ]
+ },
+ {
+ "Options": [
+ { "runas_default": "root" }
+ ]
+ },
+ {
+ "Options": [
+ { "tty_tickets": true }
+ ]
+ },
+ {
+ "Options": [
+ { "umask": "022" }
+ ]
+ },
+ {
+ "Options": [
+ { "runchroot": "/" }
+ ]
+ },
+ {
+ "Options": [
+ { "logfile": "/var/log/sudo" }
+ ]
+ },
+ {
+ "Options": [
+ { "log_format": "json" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog": "auth" },
+ { "syslog_badpri": "alert" },
+ { "syslog_goodpri": "notice" }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_maxlen": "2048" }
+ ]
+ },
+ {
+ "Options": [
+ { "loglinelen": false },
+ { "log_year": true },
+ { "log_host": true }
+ ]
+ },
+ {
+ "Options": [
+ { "mailerpath": false },
+ { "mailerflags": "-t" },
+ { "mailfrom": "sudo@sudo.ws" },
+ { "mailto": "root@localhost" },
+ { "mailsub": "*** Sudo information for %h ***" }
+ ]
+ },
+ {
+ "Options": [
+ { "long_otp_prompt": true }
+ ]
+ },
+ {
+ "Options": [
+ { "ignore_dot": true }
+ ]
+ },
+ {
+ "Options": [
+ { "mail_always": false }
+ ]
+ },
+ {
+ "Options": [
+ { "mail_badpass": false }
+ ]
+ },
+ {
+ "Options": [
+ { "mail_no_user": false }
+ ]
+ },
+ {
+ "Options": [
+ { "mail_no_host": false }
+ ]
+ },
+ {
+ "Options": [
+ { "mail_no_perms": false }
+ ]
+ },
+ {
+ "Options": [
+ { "mail_all_cmnds": false }
+ ]
+ },
+ {
+ "Options": [
+ { "lecture": "always" }
+ ]
+ },
+ {
+ "Options": [
+ { "lecture_file": "/etc/sudo.lecture" }
+ ]
+ },
+ {
+ "Options": [
+ { "authenticate": true }
+ ]
+ },
+ {
+ "Options": [
+ { "root_sudo": true }
+ ]
+ },
+ {
+ "Options": [
+ { "shell_noargs": true }
+ ]
+ },
+ {
+ "Options": [
+ { "set_home": true }
+ ]
+ },
+ {
+ "Options": [
+ { "always_set_home": true }
+ ]
+ },
+ {
+ "Options": [
+ { "path_info": true }
+ ]
+ },
+ {
+ "Options": [
+ { "insults": true }
+ ]
+ },
+ {
+ "Options": [
+ { "requiretty": false }
+ ]
+ },
+ {
+ "Options": [
+ { "env_editor": true }
+ ]
+ },
+ {
+ "Options": [
+ { "rootpw": false }
+ ]
+ },
+ {
+ "Options": [
+ { "runaspw": false }
+ ]
+ },
+ {
+ "Options": [
+ { "targetpw": false }
+ ]
+ },
+ {
+ "Options": [
+ { "use_loginclass": true }
+ ]
+ },
+ {
+ "Options": [
+ { "set_logname": true }
+ ]
+ },
+ {
+ "Options": [
+ { "stay_setuid": false }
+ ]
+ },
+ {
+ "Options": [
+ { "preserve_groups": false }
+ ]
+ },
+ {
+ "Options": [
+ { "timestamp_timeout": ".5" }
+ ]
+ },
+ {
+ "Options": [
+ { "passwd_timeout": "5" }
+ ]
+ },
+ {
+ "Options": [
+ { "passwd_tries": "3" }
+ ]
+ },
+ {
+ "Options": [
+ { "badpass_message": "Take off, eh!" }
+ ]
+ },
+ {
+ "Options": [
+ { "lecture_status_dir": "/var/lib/sudo/lectured" }
+ ]
+ },
+ {
+ "Options": [
+ { "timestampdir": "/run/sudo/ts" }
+ ]
+ },
+ {
+ "Options": [
+ { "timestampowner": "root" }
+ ]
+ },
+ {
+ "Options": [
+ { "exempt_group": "sudo" }
+ ]
+ },
+ {
+ "Options": [
+ { "passprompt": "%p's sudo password: " }
+ ]
+ },
+ {
+ "Options": [
+ { "passprompt_override": true }
+ ]
+ },
+ {
+ "Options": [
+ { "secure_path": "/usr/bin:/usr/sbin:/bin:/sbin" }
+ ]
+ },
+ {
+ "Options": [
+ { "editor": "/usr/bin/vi" }
+ ]
+ },
+ {
+ "Options": [
+ { "listpw": "any" }
+ ]
+ },
+ {
+ "Options": [
+ { "verifypw": "all" }
+ ]
+ },
+ {
+ "Options": [
+ { "noexec": true }
+ ]
+ },
+ {
+ "Options": [
+ { "ignore_local_sudoers": true }
+ ]
+ },
+ {
+ "Options": [
+ { "closefrom": "3" }
+ ]
+ },
+ {
+ "Options": [
+ { "closefrom_override": true }
+ ]
+ },
+ {
+ "Options": [
+ { "setenv": false }
+ ]
+ },
+ {
+ "Options": [
+ { "env_reset": true }
+ ]
+ },
+ {
+ "Options": [
+ {
+ "operation": "list_add",
+ "env_check": [
+ "TERMCAP"
+ ]
+ }
+ ]
+ },
+ {
+ "Options": [
+ { "env_delete": false }
+ ]
+ },
+ {
+ "Options": [
+ {
+ "operation": "list_add",
+ "env_keep": [
+ "LANG",
+ "LANGUAGE",
+ "LINGUAS",
+ "LC_*",
+ "_XKB_CHARSET"
+ ]
+ }
+ ]
+ },
+ {
+ "Options": [
+ { "env_file": "/etc/environment" }
+ ]
+ },
+ {
+ "Options": [
+ { "restricted_env_file": "/etc/environment.sudo" }
+ ]
+ },
+ {
+ "Options": [
+ { "sudoers_locale": "C" }
+ ]
+ },
+ {
+ "Options": [
+ { "visiblepw": false }
+ ]
+ },
+ {
+ "Options": [
+ { "pwfeedback": true }
+ ]
+ },
+ {
+ "Options": [
+ { "fast_glob": true }
+ ]
+ },
+ {
+ "Options": [
+ { "umask_override": true }
+ ]
+ },
+ {
+ "Options": [
+ { "log_input": true }
+ ]
+ },
+ {
+ "Options": [
+ { "log_output": true }
+ ]
+ },
+ {
+ "Options": [
+ { "compress_io": true }
+ ]
+ },
+ {
+ "Options": [
+ { "use_pty": true }
+ ]
+ },
+ {
+ "Options": [
+ { "iolog_dir": "/var/log/sudo-io" }
+ ]
+ },
+ {
+ "Options": [
+ { "iolog_file": "%{seq}" }
+ ]
+ },
+ {
+ "Options": [
+ { "set_utmp": true }
+ ]
+ },
+ {
+ "Options": [
+ { "utmp_runas": true }
+ ]
+ },
+ {
+ "Options": [
+ { "exec_background": false }
+ ]
+ },
+ {
+ "Options": [
+ { "pam_service": "sudo" }
+ ]
+ },
+ {
+ "Options": [
+ { "pam_login_service": "sudo-login" }
+ ]
+ },
+ {
+ "Options": [
+ { "pam_setcred": true }
+ ]
+ },
+ {
+ "Options": [
+ { "pam_session": true }
+ ]
+ },
+ {
+ "Options": [
+ { "pam_acct_mgmt": true }
+ ]
+ },
+ {
+ "Options": [
+ { "maxseq": "2176782336" }
+ ]
+ },
+ {
+ "Options": [
+ { "use_netgroups": true }
+ ]
+ },
+ {
+ "Options": [
+ { "sudoedit_checkdir": true }
+ ]
+ },
+ {
+ "Options": [
+ { "sudoedit_follow": false }
+ ]
+ },
+ {
+ "Options": [
+ { "always_query_group_plugin": true }
+ ]
+ },
+ {
+ "Options": [
+ { "netgroup_tuple": true }
+ ]
+ },
+ {
+ "Options": [
+ { "ignore_audit_errors": true }
+ ]
+ },
+ {
+ "Options": [
+ { "ignore_iolog_errors": true }
+ ]
+ },
+ {
+ "Options": [
+ { "ignore_logfile_errors": true }
+ ]
+ },
+ {
+ "Options": [
+ { "match_group_by_gid": false }
+ ]
+ },
+ {
+ "Options": [
+ { "iolog_user": "root" }
+ ]
+ },
+ {
+ "Options": [
+ { "iolog_group": "root" }
+ ]
+ },
+ {
+ "Options": [
+ { "iolog_mode": "0600" }
+ ]
+ },
+ {
+ "Options": [
+ { "fdexec": "digest_only" }
+ ]
+ },
+ {
+ "Options": [
+ { "ignore_unknown_defaults": false }
+ ]
+ },
+ {
+ "Options": [
+ { "command_timeout": "7d8h30m10s" }
+ ]
+ },
+ {
+ "Options": [
+ { "user_command_timeouts": true }
+ ]
+ },
+ {
+ "Options": [
+ { "iolog_flush": true }
+ ]
+ },
+ {
+ "Options": [
+ { "syslog_pid": true }
+ ]
+ },
+ {
+ "Options": [
+ { "timestamp_type": "tty" }
+ ]
+ },
+ {
+ "Options": [
+ { "authfail_message": "Learn to type!" }
+ ]
+ },
+ {
+ "Options": [
+ { "case_insensitive_user": true }
+ ]
+ },
+ {
+ "Options": [
+ { "case_insensitive_group": true }
+ ]
+ },
+ {
+ "Options": [
+ { "log_allowed": true }
+ ]
+ },
+ {
+ "Options": [
+ { "log_denied": true }
+ ]
+ },
+ {
+ "Options": [
+ { "log_servers": false }
+ ]
+ },
+ {
+ "Options": [
+ { "log_server_timeout": "10" }
+ ]
+ },
+ {
+ "Options": [
+ { "log_server_keepalive": true }
+ ]
+ },
+ {
+ "Options": [
+ { "log_server_cabundle": false }
+ ]
+ },
+ {
+ "Options": [
+ { "log_server_peer_cert": false }
+ ]
+ },
+ {
+ "Options": [
+ { "log_server_peer_key": false }
+ ]
+ },
+ {
+ "Options": [
+ { "log_server_verify": false }
+ ]
+ },
+ {
+ "Options": [
+ { "runas_allow_unknown_id": true }
+ ]
+ },
+ {
+ "Options": [
+ { "runas_check_shell": true }
+ ]
+ },
+ {
+ "Options": [
+ { "pam_ruser": true }
+ ]
+ },
+ {
+ "Options": [
+ { "pam_rhost": true }
+ ]
+ },
+ {
+ "Options": [
+ { "runcwd": "~" }
+ ]
+ },
+ {
+ "Options": [
+ { "selinux": false }
+ ]
+ },
+ {
+ "Options": [
+ { "admin_flag": false }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/sudoers/test26.ldif.ok b/plugins/sudoers/regress/sudoers/test26.ldif.ok
new file mode 100644
index 0000000..912e265
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test26.ldif.ok
@@ -0,0 +1,134 @@
+dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: fqdn
+sudoOption: runas_default=root
+sudoOption: tty_tickets
+sudoOption: umask=022
+sudoOption: runchroot=/
+sudoOption: logfile=/var/log/sudo
+sudoOption: log_format=json
+sudoOption: syslog=auth
+sudoOption: syslog_badpri=alert
+sudoOption: syslog_goodpri=notice
+sudoOption: syslog_maxlen=2048
+sudoOption: !loglinelen
+sudoOption: log_year
+sudoOption: log_host
+sudoOption: !mailerpath
+sudoOption: mailerflags=-t
+sudoOption: mailfrom=sudo@sudo.ws
+sudoOption: mailto=root@localhost
+sudoOption: mailsub=*** Sudo information for %h ***
+sudoOption: long_otp_prompt
+sudoOption: ignore_dot
+sudoOption: !mail_always
+sudoOption: !mail_badpass
+sudoOption: !mail_no_user
+sudoOption: !mail_no_host
+sudoOption: !mail_no_perms
+sudoOption: !mail_all_cmnds
+sudoOption: lecture=always
+sudoOption: lecture_file=/etc/sudo.lecture
+sudoOption: authenticate
+sudoOption: root_sudo
+sudoOption: shell_noargs
+sudoOption: set_home
+sudoOption: always_set_home
+sudoOption: path_info
+sudoOption: insults
+sudoOption: !requiretty
+sudoOption: env_editor
+sudoOption: !rootpw
+sudoOption: !runaspw
+sudoOption: !targetpw
+sudoOption: use_loginclass
+sudoOption: set_logname
+sudoOption: !stay_setuid
+sudoOption: !preserve_groups
+sudoOption: timestamp_timeout=.5
+sudoOption: passwd_timeout=5
+sudoOption: passwd_tries=3
+sudoOption: badpass_message=Take off, eh!
+sudoOption: lecture_status_dir=/var/lib/sudo/lectured
+sudoOption: timestampdir=/run/sudo/ts
+sudoOption: timestampowner=root
+sudoOption: exempt_group=sudo
+sudoOption: passprompt=%p's sudo password:
+sudoOption: passprompt_override
+sudoOption: secure_path=/usr/bin:/usr/sbin:/bin:/sbin
+sudoOption: editor=/usr/bin/vi
+sudoOption: listpw=any
+sudoOption: verifypw=all
+sudoOption: noexec
+sudoOption: ignore_local_sudoers
+sudoOption: closefrom=3
+sudoOption: closefrom_override
+sudoOption: !setenv
+sudoOption: env_reset
+sudoOption: env_check+=TERMCAP
+sudoOption: !env_delete
+sudoOption: env_keep+=LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET
+sudoOption: env_file=/etc/environment
+sudoOption: restricted_env_file=/etc/environment.sudo
+sudoOption: sudoers_locale=C
+sudoOption: !visiblepw
+sudoOption: pwfeedback
+sudoOption: fast_glob
+sudoOption: umask_override
+sudoOption: log_input
+sudoOption: log_output
+sudoOption: compress_io
+sudoOption: use_pty
+sudoOption: iolog_dir=/var/log/sudo-io
+sudoOption: iolog_file=%{seq}
+sudoOption: set_utmp
+sudoOption: utmp_runas
+sudoOption: !exec_background
+sudoOption: pam_service=sudo
+sudoOption: pam_login_service=sudo-login
+sudoOption: pam_setcred
+sudoOption: pam_session
+sudoOption: pam_acct_mgmt
+sudoOption: maxseq=2176782336
+sudoOption: use_netgroups
+sudoOption: sudoedit_checkdir
+sudoOption: !sudoedit_follow
+sudoOption: always_query_group_plugin
+sudoOption: netgroup_tuple
+sudoOption: ignore_audit_errors
+sudoOption: ignore_iolog_errors
+sudoOption: ignore_logfile_errors
+sudoOption: !match_group_by_gid
+sudoOption: iolog_user=root
+sudoOption: iolog_group=root
+sudoOption: iolog_mode=0600
+sudoOption: fdexec=digest_only
+sudoOption: !ignore_unknown_defaults
+sudoOption: command_timeout=7d8h30m10s
+sudoOption: user_command_timeouts
+sudoOption: iolog_flush
+sudoOption: syslog_pid
+sudoOption: timestamp_type=tty
+sudoOption: authfail_message=Learn to type!
+sudoOption: case_insensitive_user
+sudoOption: case_insensitive_group
+sudoOption: log_allowed
+sudoOption: log_denied
+sudoOption: !log_servers
+sudoOption: log_server_timeout=10
+sudoOption: log_server_keepalive
+sudoOption: !log_server_cabundle
+sudoOption: !log_server_peer_cert
+sudoOption: !log_server_peer_key
+sudoOption: !log_server_verify
+sudoOption: runas_allow_unknown_id
+sudoOption: runas_check_shell
+sudoOption: pam_ruser
+sudoOption: pam_rhost
+sudoOption: runcwd=~
+sudoOption: !selinux
+sudoOption: !admin_flag
+
diff --git a/plugins/sudoers/regress/sudoers/test26.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test26.ldif2sudo.ok
new file mode 100644
index 0000000..706c6fd
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test26.ldif2sudo.ok
@@ -0,0 +1,128 @@
+Defaults fqdn
+Defaults runas_default=root
+Defaults tty_tickets
+Defaults umask=022
+Defaults runchroot=/
+Defaults logfile=/var/log/sudo
+Defaults log_format=json
+Defaults syslog=auth
+Defaults syslog_badpri=alert
+Defaults syslog_goodpri=notice
+Defaults syslog_maxlen=2048
+Defaults !loglinelen
+Defaults log_year
+Defaults log_host
+Defaults !mailerpath
+Defaults mailerflags=-t
+Defaults mailfrom=sudo@sudo.ws
+Defaults mailto=root@localhost
+Defaults mailsub="*** Sudo information for %h ***"
+Defaults long_otp_prompt
+Defaults ignore_dot
+Defaults !mail_always
+Defaults !mail_badpass
+Defaults !mail_no_user
+Defaults !mail_no_host
+Defaults !mail_no_perms
+Defaults !mail_all_cmnds
+Defaults lecture=always
+Defaults lecture_file=/etc/sudo.lecture
+Defaults authenticate
+Defaults root_sudo
+Defaults shell_noargs
+Defaults set_home
+Defaults always_set_home
+Defaults path_info
+Defaults insults
+Defaults !requiretty
+Defaults env_editor
+Defaults !rootpw
+Defaults !runaspw
+Defaults !targetpw
+Defaults use_loginclass
+Defaults set_logname
+Defaults !stay_setuid
+Defaults !preserve_groups
+Defaults timestamp_timeout=.5
+Defaults passwd_timeout=5
+Defaults passwd_tries=3
+Defaults badpass_message="Take off, eh!"
+Defaults lecture_status_dir=/var/lib/sudo/lectured
+Defaults timestampdir=/run/sudo/ts
+Defaults timestampowner=root
+Defaults exempt_group=sudo
+Defaults passprompt="%p's sudo password:"
+Defaults passprompt_override
+Defaults secure_path=/usr/bin\:/usr/sbin\:/bin\:/sbin
+Defaults editor=/usr/bin/vi
+Defaults listpw=any
+Defaults verifypw=all
+Defaults noexec
+Defaults ignore_local_sudoers
+Defaults closefrom=3
+Defaults closefrom_override
+Defaults !setenv
+Defaults env_reset
+Defaults env_check+=TERMCAP
+Defaults !env_delete
+Defaults env_keep+="LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET"
+Defaults env_file=/etc/environment
+Defaults restricted_env_file=/etc/environment.sudo
+Defaults sudoers_locale=C
+Defaults !visiblepw
+Defaults pwfeedback
+Defaults fast_glob
+Defaults umask_override
+Defaults log_input
+Defaults log_output
+Defaults compress_io
+Defaults use_pty
+Defaults iolog_dir=/var/log/sudo-io
+Defaults iolog_file=%{seq}
+Defaults set_utmp
+Defaults utmp_runas
+Defaults !exec_background
+Defaults pam_service=sudo
+Defaults pam_login_service=sudo-login
+Defaults pam_setcred
+Defaults pam_session
+Defaults pam_acct_mgmt
+Defaults maxseq=2176782336
+Defaults use_netgroups
+Defaults sudoedit_checkdir
+Defaults !sudoedit_follow
+Defaults always_query_group_plugin
+Defaults netgroup_tuple
+Defaults ignore_audit_errors
+Defaults ignore_iolog_errors
+Defaults ignore_logfile_errors
+Defaults !match_group_by_gid
+Defaults iolog_user=root
+Defaults iolog_group=root
+Defaults iolog_mode=0600
+Defaults fdexec=digest_only
+Defaults !ignore_unknown_defaults
+Defaults command_timeout=7d8h30m10s
+Defaults user_command_timeouts
+Defaults iolog_flush
+Defaults syslog_pid
+Defaults timestamp_type=tty
+Defaults authfail_message="Learn to type!"
+Defaults case_insensitive_user
+Defaults case_insensitive_group
+Defaults log_allowed
+Defaults log_denied
+Defaults !log_servers
+Defaults log_server_timeout=10
+Defaults log_server_keepalive
+Defaults !log_server_cabundle
+Defaults !log_server_peer_cert
+Defaults !log_server_peer_key
+Defaults !log_server_verify
+Defaults runas_allow_unknown_id
+Defaults runas_check_shell
+Defaults pam_ruser
+Defaults pam_rhost
+Defaults runcwd=~
+Defaults !selinux
+Defaults !admin_flag
diff --git a/plugins/sudoers/regress/sudoers/test26.out.ok b/plugins/sudoers/regress/sudoers/test26.out.ok
new file mode 100644
index 0000000..e9f07fb
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test26.out.ok
@@ -0,0 +1,122 @@
+Parses OK
+
+Defaults fqdn
+Defaults runas_default=root
+Defaults tty_tickets
+Defaults umask=022
+Defaults runchroot=/
+Defaults logfile=/var/log/sudo
+Defaults log_format=json
+Defaults syslog=auth, syslog_badpri=alert, syslog_goodpri=notice
+Defaults syslog_maxlen=2048
+Defaults !loglinelen, log_year, log_host
+Defaults !mailerpath, mailerflags=-t, mailfrom=sudo@sudo.ws, mailto=root@localhost, mailsub="*** Sudo information for %h ***"
+Defaults long_otp_prompt
+Defaults ignore_dot
+Defaults !mail_always
+Defaults !mail_badpass
+Defaults !mail_no_user
+Defaults !mail_no_host
+Defaults !mail_no_perms
+Defaults !mail_all_cmnds
+Defaults lecture=always
+Defaults lecture_file=/etc/sudo.lecture
+Defaults authenticate
+Defaults root_sudo
+Defaults shell_noargs
+Defaults set_home
+Defaults always_set_home
+Defaults path_info
+Defaults insults
+Defaults !requiretty
+Defaults env_editor
+Defaults !rootpw
+Defaults !runaspw
+Defaults !targetpw
+Defaults use_loginclass
+Defaults set_logname
+Defaults !stay_setuid
+Defaults !preserve_groups
+Defaults timestamp_timeout=.5
+Defaults passwd_timeout=5
+Defaults passwd_tries=3
+Defaults badpass_message="Take off, eh!"
+Defaults lecture_status_dir=/var/lib/sudo/lectured
+Defaults timestampdir=/run/sudo/ts
+Defaults timestampowner=root
+Defaults exempt_group=sudo
+Defaults passprompt="%p's sudo password: "
+Defaults passprompt_override
+Defaults secure_path=/usr/bin\:/usr/sbin\:/bin\:/sbin
+Defaults editor=/usr/bin/vi
+Defaults listpw=any
+Defaults verifypw=all
+Defaults noexec
+Defaults ignore_local_sudoers
+Defaults closefrom=3
+Defaults closefrom_override
+Defaults !setenv
+Defaults env_reset
+Defaults env_check+=TERMCAP
+Defaults !env_delete
+Defaults env_keep+="LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET"
+Defaults env_file=/etc/environment
+Defaults restricted_env_file=/etc/environment.sudo
+Defaults sudoers_locale=C
+Defaults !visiblepw
+Defaults pwfeedback
+Defaults fast_glob
+Defaults umask_override
+Defaults log_input
+Defaults log_output
+Defaults compress_io
+Defaults use_pty
+Defaults iolog_dir=/var/log/sudo-io
+Defaults iolog_file=%{seq}
+Defaults set_utmp
+Defaults utmp_runas
+Defaults !exec_background
+Defaults pam_service=sudo
+Defaults pam_login_service=sudo-login
+Defaults pam_setcred
+Defaults pam_session
+Defaults pam_acct_mgmt
+Defaults maxseq=2176782336
+Defaults use_netgroups
+Defaults sudoedit_checkdir
+Defaults !sudoedit_follow
+Defaults always_query_group_plugin
+Defaults netgroup_tuple
+Defaults ignore_audit_errors
+Defaults ignore_iolog_errors
+Defaults ignore_logfile_errors
+Defaults !match_group_by_gid
+Defaults iolog_user=root
+Defaults iolog_group=root
+Defaults iolog_mode=0600
+Defaults fdexec=digest_only
+Defaults !ignore_unknown_defaults
+Defaults command_timeout=7d8h30m10s
+Defaults user_command_timeouts
+Defaults iolog_flush
+Defaults syslog_pid
+Defaults timestamp_type=tty
+Defaults authfail_message="Learn to type!"
+Defaults case_insensitive_user
+Defaults case_insensitive_group
+Defaults log_allowed
+Defaults log_denied
+Defaults !log_servers
+Defaults log_server_timeout=10
+Defaults log_server_keepalive
+Defaults !log_server_cabundle
+Defaults !log_server_peer_cert
+Defaults !log_server_peer_key
+Defaults !log_server_verify
+Defaults runas_allow_unknown_id
+Defaults runas_check_shell
+Defaults pam_ruser
+Defaults pam_rhost
+Defaults runcwd=~
+Defaults !selinux
+Defaults !admin_flag
diff --git a/plugins/sudoers/regress/sudoers/test26.toke.ok b/plugins/sudoers/regress/sudoers/test26.toke.ok
new file mode 100644
index 0000000..9e125fe
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test26.toke.ok
@@ -0,0 +1,128 @@
+#
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2) , DEFVAR = WORD(2) , DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS !DEFVAR , DEFVAR , DEFVAR
+DEFAULTS !DEFVAR , DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4) , DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4) , DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4) , DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4)
+
+#
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4)
+DEFAULTS DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4)
+DEFAULTS DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4)
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR += BEGINSTR STRBODY ENDSTR WORD(4)
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR += BEGINSTR STRBODY ENDSTR WORD(4)
+#
+#
+DEFAULTS DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4)
+DEFAULTS DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+#
+DEFAULTS DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4)
+DEFAULTS DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4)
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+#
+#
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4)
+DEFAULTS DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4)
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4)
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS !DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR
+DEFAULTS DEFVAR = WORD(2)
+DEFAULTS !DEFVAR
+DEFAULTS !DEFVAR
diff --git a/plugins/sudoers/regress/sudoers/test27.in b/plugins/sudoers/regress/sudoers/test27.in
new file mode 100644
index 0000000..9e6c28f
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test27.in
@@ -0,0 +1,13 @@
+# Query the group plugin too (if there is one)
+Defaults always_query_group_plugin
+
+# Test RunasGroup with and without RunasUser
+root ALL = ( root : wheel ) ALL
+millert ALL = ( : wheel ) ALL
+%sudo ALL = ( : ALL ) ALL
+
+# Test RunasUser with %group syntax
+operator ALL = ( %wheel ) ALL
+
+# Test netgroup for user and host
++netusers +nethosts = ( +netrunas ) ALL
diff --git a/plugins/sudoers/regress/sudoers/test27.json.ok b/plugins/sudoers/regress/sudoers/test27.json.ok
new file mode 100644
index 0000000..f097b0e
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test27.json.ok
@@ -0,0 +1,125 @@
+{
+ "Defaults": [
+ {
+ "Options": [
+ { "always_query_group_plugin": true }
+ ]
+ }
+ ],
+ "User_Specs": [
+ {
+ "User_List": [
+ { "username": "root" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "root" }
+ ],
+ "runasgroups": [
+ { "usergroup": "wheel" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "millert" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "" }
+ ],
+ "runasgroups": [
+ { "usergroup": "wheel" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "usergroup": "sudo" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "" }
+ ],
+ "runasgroups": [
+ { "usergroup": "ALL" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "operator" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "usergroup": "wheel" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "netgroup": "netusers" }
+ ],
+ "Host_List": [
+ { "netgroup": "nethosts" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "netgroup": "netrunas" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/sudoers/test27.ldif.ok b/plugins/sudoers/regress/sudoers/test27.ldif.ok
new file mode 100644
index 0000000..e6be300
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test27.ldif.ok
@@ -0,0 +1,60 @@
+dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: always_query_group_plugin
+
+dn: cn=root,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: root
+sudoUser: root
+sudoHost: ALL
+sudoRunAsUser: root
+sudoRunAsGroup: wheel
+sudoCommand: ALL
+sudoOrder: 1
+
+dn: cn=millert,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: millert
+sudoUser: millert
+sudoHost: ALL
+sudoRunAsUser:
+sudoRunAsGroup: wheel
+sudoCommand: ALL
+sudoOrder: 2
+
+dn: cn=%sudo,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: %sudo
+sudoUser: %sudo
+sudoHost: ALL
+sudoRunAsUser:
+sudoRunAsGroup: ALL
+sudoCommand: ALL
+sudoOrder: 3
+
+dn: cn=operator,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: operator
+sudoUser: operator
+sudoHost: ALL
+sudoRunAsUser: %wheel
+sudoCommand: ALL
+sudoOrder: 4
+
+dn: cn=\+netusers,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: \+netusers
+sudoUser: +netusers
+sudoHost: +nethosts
+sudoRunAsUser: +netrunas
+sudoCommand: ALL
+sudoOrder: 5
+
diff --git a/plugins/sudoers/regress/sudoers/test27.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test27.ldif2sudo.ok
new file mode 100644
index 0000000..a73f459
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test27.ldif2sudo.ok
@@ -0,0 +1,16 @@
+Defaults always_query_group_plugin
+
+# sudoRole root
+root ALL = (root : wheel) ALL
+
+# sudoRole millert
+millert ALL = ( : wheel) ALL
+
+# sudoRole %sudo
+%sudo ALL = ( : ALL) ALL
+
+# sudoRole operator
+operator ALL = (%wheel) ALL
+
+# sudoRole +netusers
++netusers +nethosts = (+netrunas) ALL
diff --git a/plugins/sudoers/regress/sudoers/test27.out.ok b/plugins/sudoers/regress/sudoers/test27.out.ok
new file mode 100644
index 0000000..70cdc04
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test27.out.ok
@@ -0,0 +1,9 @@
+Parses OK
+
+Defaults always_query_group_plugin
+
+root ALL = (root : wheel) ALL
+millert ALL = (root : wheel) ALL
+%sudo ALL = (root : ALL) ALL
+operator ALL = (%wheel) ALL
++netusers +nethosts = (+netrunas) ALL
diff --git a/plugins/sudoers/regress/sudoers/test27.toke.ok b/plugins/sudoers/regress/sudoers/test27.toke.ok
new file mode 100644
index 0000000..e7b3eb6
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test27.toke.ok
@@ -0,0 +1,13 @@
+#
+DEFAULTS DEFVAR
+
+#
+WORD(6) ALL = ( WORD(6) : WORD(6) ) ALL
+WORD(6) ALL = ( : WORD(6) ) ALL
+USERGROUP ALL = ( : ALL ) ALL
+
+#
+WORD(6) ALL = ( USERGROUP ) ALL
+
+#
+NETGROUP NETGROUP = ( NETGROUP ) ALL
diff --git a/plugins/sudoers/regress/sudoers/test28.in b/plugins/sudoers/regress/sudoers/test28.in
new file mode 100644
index 0000000..e546aed
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test28.in
@@ -0,0 +1,36 @@
+# Test passprompt_regex
+Defaults passprompt_regex="(?i)password: *"
+
+# Test simple command with regex args
+user ALL = /bin/ls ^/etc/(hosts|motd|issue)$
+
+# Test wildcard command with regex args
+user ALL = /usr/bin/c* ^/etc/(hosts|motd|issue)$
+
+# Test regex command with no args
+user ALL = ^/usr/bin/(who|w|id|whoami)$
+
+# Test regex command with empty args
+user ALL = ^/usr/bin/(who|w|id|whoami)$ ""
+
+# Test regex command with simple args
+user ALL = ^/usr/bin/(who|w|id|whoami)$ root
+
+# Test regex command with wildcard args
+user ALL = ^/usr/bin/(who|w|id|whoami)$ -*
+
+# Test regex command with regex args
+user ALL = ^/usr/bin/(who|w|id|whoami)$ ^(-[ahi] ?)+$
+
+# Test sudoedit with regex args
+user ALL = sudoedit ^/etc/(hosts|motd|issue)$
+
+# Test regex command with escapted '$', no args
+user ALL = ^/usr/bin/\$tree$
+
+# Combined entry
+user host1 = /bin/ls ^/etc/(hosts|motd|issue)$, \
+ /usr/bin/c* ^/etc/(hosts|motd|issue)$ : \
+ host2 = ^/usr/bin/(who|w|id|whoami)$ "", \
+ ^/usr/bin/(who|w|id|whoami)$ root : \
+ host3 = /bin/echo ^\$foo$
diff --git a/plugins/sudoers/regress/sudoers/test28.json.ok b/plugins/sudoers/regress/sudoers/test28.json.ok
new file mode 100644
index 0000000..4fa4145
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test28.json.ok
@@ -0,0 +1,199 @@
+{
+ "Defaults": [
+ {
+ "Options": [
+ {
+ "operation": "list_assign",
+ "passprompt_regex": [
+ "(?i)password:",
+ "*"
+ ]
+ }
+ ]
+ }
+ ],
+ "User_Specs": [
+ {
+ "User_List": [
+ { "username": "user" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "command": "/bin/ls ^/etc/(hosts|motd|issue)$" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "command": "/usr/bin/c* ^/etc/(hosts|motd|issue)$" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "command": "^/usr/bin/(who|w|id|whoami)$" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "command": "^/usr/bin/(who|w|id|whoami)$ \"\"" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "command": "^/usr/bin/(who|w|id|whoami)$ root" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "command": "^/usr/bin/(who|w|id|whoami)$ -*" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "command": "^/usr/bin/(who|w|id|whoami)$ ^(-[ahi] ?)+$" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "command": "sudoedit ^/etc/(hosts|motd|issue)$" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "command": "^/usr/bin/\\$tree$" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user" }
+ ],
+ "Host_List": [
+ { "hostname": "host1" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "command": "/bin/ls ^/etc/(hosts|motd|issue)$" },
+ { "command": "/usr/bin/c* ^/etc/(hosts|motd|issue)$" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user" }
+ ],
+ "Host_List": [
+ { "hostname": "host2" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "command": "^/usr/bin/(who|w|id|whoami)$ \"\"" },
+ { "command": "^/usr/bin/(who|w|id|whoami)$ root" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user" }
+ ],
+ "Host_List": [
+ { "hostname": "host3" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "command": "/bin/echo ^\\$foo$" }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/sudoers/test28.ldif.ok b/plugins/sudoers/regress/sudoers/test28.ldif.ok
new file mode 100644
index 0000000..1ecc586
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test28.ldif.ok
@@ -0,0 +1,117 @@
+dn: cn=defaults,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: defaults
+description: Default sudoOption's go here
+sudoOption: passprompt_regex=(?i)password: *
+
+dn: cn=user,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user
+sudoUser: user
+sudoHost: ALL
+sudoCommand: /bin/ls ^/etc/(hosts|motd|issue)$
+sudoOrder: 1
+
+dn: cn=user_1,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user_1
+sudoUser: user
+sudoHost: ALL
+sudoCommand: /usr/bin/c* ^/etc/(hosts|motd|issue)$
+sudoOrder: 2
+
+dn: cn=user_2,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user_2
+sudoUser: user
+sudoHost: ALL
+sudoCommand: ^/usr/bin/(who|w|id|whoami)$
+sudoOrder: 3
+
+dn: cn=user_3,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user_3
+sudoUser: user
+sudoHost: ALL
+sudoCommand: ^/usr/bin/(who|w|id|whoami)$ ""
+sudoOrder: 4
+
+dn: cn=user_4,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user_4
+sudoUser: user
+sudoHost: ALL
+sudoCommand: ^/usr/bin/(who|w|id|whoami)$ root
+sudoOrder: 5
+
+dn: cn=user_5,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user_5
+sudoUser: user
+sudoHost: ALL
+sudoCommand: ^/usr/bin/(who|w|id|whoami)$ -*
+sudoOrder: 6
+
+dn: cn=user_6,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user_6
+sudoUser: user
+sudoHost: ALL
+sudoCommand: ^/usr/bin/(who|w|id|whoami)$ ^(-[ahi] ?)+$
+sudoOrder: 7
+
+dn: cn=user_7,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user_7
+sudoUser: user
+sudoHost: ALL
+sudoCommand: sudoedit ^/etc/(hosts|motd|issue)$
+sudoOrder: 8
+
+dn: cn=user_8,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user_8
+sudoUser: user
+sudoHost: ALL
+sudoCommand: ^/usr/bin/\$tree$
+sudoOrder: 9
+
+dn: cn=user_9,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user_9
+sudoUser: user
+sudoHost: host1
+sudoCommand: /bin/ls ^/etc/(hosts|motd|issue)$
+sudoCommand: /usr/bin/c* ^/etc/(hosts|motd|issue)$
+sudoOrder: 10
+
+dn: cn=user_10,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user_10
+sudoUser: user
+sudoHost: host2
+sudoCommand: ^/usr/bin/(who|w|id|whoami)$ ""
+sudoCommand: ^/usr/bin/(who|w|id|whoami)$ root
+sudoOrder: 11
+
+dn: cn=user_11,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user_11
+sudoUser: user
+sudoHost: host3
+sudoCommand: /bin/echo ^\$foo$
+sudoOrder: 12
+
diff --git a/plugins/sudoers/regress/sudoers/test28.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test28.ldif2sudo.ok
new file mode 100644
index 0000000..0b642fe
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test28.ldif2sudo.ok
@@ -0,0 +1,12 @@
+Defaults passprompt_regex="(?i)password: *"
+
+# sudoRole user, user_1, user_2, user_3, user_4, user_5, user_6, user_7,
+# user_8, user_9, user_10, user_11
+user ALL = /bin/ls ^/etc/(hosts|motd|issue)$, /usr/bin/c*\
+ ^/etc/(hosts|motd|issue)$, ^/usr/bin/(who|w|id|whoami)$,\
+ ^/usr/bin/(who|w|id|whoami)$ "", ^/usr/bin/(who|w|id|whoami)$ root,\
+ ^/usr/bin/(who|w|id|whoami)$ -*, ^/usr/bin/(who|w|id|whoami)$ ^(-[ahi]\
+ ?)+$, sudoedit ^/etc/(hosts|motd|issue)$, ^/usr/bin/\$tree$ : host1 =\
+ /bin/ls ^/etc/(hosts|motd|issue)$, /usr/bin/c* ^/etc/(hosts|motd|issue)$ :\
+ host2 = ^/usr/bin/(who|w|id|whoami)$ "", ^/usr/bin/(who|w|id|whoami)$ root\
+ : host3 = /bin/echo ^\$foo$
diff --git a/plugins/sudoers/regress/sudoers/test28.out.ok b/plugins/sudoers/regress/sudoers/test28.out.ok
new file mode 100644
index 0000000..443573c
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test28.out.ok
@@ -0,0 +1,14 @@
+Parses OK
+
+Defaults passprompt_regex="(?i)password: *"
+
+user ALL = /bin/ls ^/etc/(hosts|motd|issue)$
+user ALL = /usr/bin/c* ^/etc/(hosts|motd|issue)$
+user ALL = ^/usr/bin/(who|w|id|whoami)$
+user ALL = ^/usr/bin/(who|w|id|whoami)$ ""
+user ALL = ^/usr/bin/(who|w|id|whoami)$ root
+user ALL = ^/usr/bin/(who|w|id|whoami)$ -*
+user ALL = ^/usr/bin/(who|w|id|whoami)$ ^(-[ahi] ?)+$
+user ALL = sudoedit ^/etc/(hosts|motd|issue)$
+user ALL = ^/usr/bin/\$tree$
+user host1 = /bin/ls ^/etc/(hosts|motd|issue)$, /usr/bin/c* ^/etc/(hosts|motd|issue)$ : host2 = ^/usr/bin/(who|w|id|whoami)$ "", ^/usr/bin/(who|w|id|whoami)$ root : host3 = /bin/echo ^\$foo$
diff --git a/plugins/sudoers/regress/sudoers/test28.toke.ok b/plugins/sudoers/regress/sudoers/test28.toke.ok
new file mode 100644
index 0000000..03918b9
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test28.toke.ok
@@ -0,0 +1,32 @@
+#
+DEFAULTS DEFVAR = BEGINSTR STRBODY ENDSTR WORD(4)
+
+#
+WORD(6) ALL = COMMAND ARG REGEX
+
+#
+WORD(6) ALL = COMMAND ARG REGEX
+
+#
+WORD(6) ALL = COMMAND
+
+#
+WORD(6) ALL = COMMAND ARG
+
+#
+WORD(6) ALL = COMMAND ARG
+
+#
+WORD(6) ALL = COMMAND ARG
+
+#
+WORD(6) ALL = COMMAND ARG REGEX
+
+#
+WORD(6) ALL = COMMAND ARG REGEX
+
+#
+WORD(6) ALL = COMMAND
+
+#
+WORD(6) WORD(6) = COMMAND ARG REGEX , COMMAND ARG REGEX : WORD(6) = COMMAND ARG , COMMAND ARG : WORD(6) = COMMAND ARG REGEX QUOTEDCHAR
diff --git a/plugins/sudoers/regress/sudoers/test29.in b/plugins/sudoers/regress/sudoers/test29.in
new file mode 100644
index 0000000..34092cd
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test29.in
@@ -0,0 +1,11 @@
+# Test lexer regex syntax errors
+# We don't test regcomp() errors since regerror() strings are not
+# standardized.
+
+user ALL = /bin/ls ^/etc/(hosts|motd|issue
+
+user ALL = ^/bin/ls
+
+user ALL = ^/bin/ls$ ^error
+
+user ALL = ^/bin/ls$ ^error # comment
diff --git a/plugins/sudoers/regress/sudoers/test29.json.ok b/plugins/sudoers/regress/sudoers/test29.json.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test29.json.ok
diff --git a/plugins/sudoers/regress/sudoers/test29.ldif.ok b/plugins/sudoers/regress/sudoers/test29.ldif.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test29.ldif.ok
diff --git a/plugins/sudoers/regress/sudoers/test29.out.ok b/plugins/sudoers/regress/sudoers/test29.out.ok
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test29.out.ok
@@ -0,0 +1 @@
+
diff --git a/plugins/sudoers/regress/sudoers/test29.toke.ok b/plugins/sudoers/regress/sudoers/test29.toke.ok
new file mode 100644
index 0000000..ce3a4a9
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test29.toke.ok
@@ -0,0 +1,11 @@
+#
+#
+#
+
+WORD(6) ALL = COMMAND ARG REGEX ERROR <*>
+
+WORD(6) ALL = WORD(6) <*>
+
+WORD(6) ALL = COMMAND ARG REGEX ERROR <*>
+
+WORD(6) ALL = COMMAND ARG REGEX ERROR <*> #
diff --git a/plugins/sudoers/regress/sudoers/test3.in b/plugins/sudoers/regress/sudoers/test3.in
new file mode 100644
index 0000000..82fcd83
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test3.in
@@ -0,0 +1,6 @@
+# Test whitespace in User_List as part of a per-user Defaults entry
+User_Alias FOO = foo, bar
+Defaults:FOO env_reset
+Defaults:foo,bar env_reset
+Defaults:foo,\ bar env_reset
+Defaults:foo, bar env_reset
diff --git a/plugins/sudoers/regress/sudoers/test3.json.ok b/plugins/sudoers/regress/sudoers/test3.json.ok
new file mode 100644
index 0000000..fc69eb1
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test3.json.ok
@@ -0,0 +1,45 @@
+{
+ "Defaults": [
+ {
+ "Binding": [
+ { "useralias": "FOO" }
+ ],
+ "Options": [
+ { "env_reset": true }
+ ]
+ },
+ {
+ "Binding": [
+ { "username": "foo" },
+ { "username": "bar" }
+ ],
+ "Options": [
+ { "env_reset": true }
+ ]
+ },
+ {
+ "Binding": [
+ { "username": "foo" },
+ { "username": " bar" }
+ ],
+ "Options": [
+ { "env_reset": true }
+ ]
+ },
+ {
+ "Binding": [
+ { "username": "foo" },
+ { "username": "bar" }
+ ],
+ "Options": [
+ { "env_reset": true }
+ ]
+ }
+ ],
+ "User_Aliases": {
+ "FOO": [
+ { "username": "foo" },
+ { "username": "bar" }
+ ]
+ }
+}
diff --git a/plugins/sudoers/regress/sudoers/test3.ldif.ok b/plugins/sudoers/regress/sudoers/test3.ldif.ok
new file mode 100644
index 0000000..783cde5
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test3.ldif.ok
@@ -0,0 +1,12 @@
+# Unable to translate stdin:3:23:
+# Defaults:foo, bar env_reset
+
+# Unable to translate stdin:4:27:
+# Defaults:foo, bar env_reset
+
+# Unable to translate stdin:5:29:
+# Defaults:foo, " bar" env_reset
+
+# Unable to translate stdin:6:28:
+# Defaults:foo, bar env_reset
+
diff --git a/plugins/sudoers/regress/sudoers/test3.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test3.ldif2sudo.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test3.ldif2sudo.ok
diff --git a/plugins/sudoers/regress/sudoers/test3.out.ok b/plugins/sudoers/regress/sudoers/test3.out.ok
new file mode 100644
index 0000000..7f620c4
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test3.out.ok
@@ -0,0 +1,8 @@
+Parses OK
+
+Defaults:FOO env_reset
+Defaults:foo, bar env_reset
+Defaults:foo, " bar" env_reset
+Defaults:foo, bar env_reset
+
+User_Alias FOO = foo, bar
diff --git a/plugins/sudoers/regress/sudoers/test3.toke.ok b/plugins/sudoers/regress/sudoers/test3.toke.ok
new file mode 100644
index 0000000..028f333
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test3.toke.ok
@@ -0,0 +1,6 @@
+#
+USERALIAS ALIAS = WORD(6) , WORD(6)
+DEFAULTS_USER ALIAS DEFVAR
+DEFAULTS_USER WORD(6) , WORD(6) DEFVAR
+DEFAULTS_USER WORD(6) , WORD(6) DEFVAR
+DEFAULTS_USER WORD(6) , WORD(6) DEFVAR
diff --git a/plugins/sudoers/regress/sudoers/test30.in b/plugins/sudoers/regress/sudoers/test30.in
new file mode 100644
index 0000000..c89d739
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test30.in
@@ -0,0 +1,10 @@
+# Test parsing of "list" pseudo-command.
+# It should be allowed as a command but also as a user or host.
+
+user1 ALL = list
+
+list ALL = ALL
+
+user2 ALL = (list : list) ALL
+
+user3 list = ALL
diff --git a/plugins/sudoers/regress/sudoers/test30.json.ok b/plugins/sudoers/regress/sudoers/test30.json.ok
new file mode 100644
index 0000000..e95f2c6
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test30.json.ok
@@ -0,0 +1,79 @@
+{
+ "User_Specs": [
+ {
+ "User_List": [
+ { "username": "user1" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Commands": [
+ { "command": "list" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "list" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user2" }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "username": "list" }
+ ],
+ "runasgroups": [
+ { "usergroup": "list" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "username": "user3" }
+ ],
+ "Host_List": [
+ { "hostname": "list" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/sudoers/test30.ldif.ok b/plugins/sudoers/regress/sudoers/test30.ldif.ok
new file mode 100644
index 0000000..2c1913f
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test30.ldif.ok
@@ -0,0 +1,38 @@
+dn: cn=user1,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user1
+sudoUser: user1
+sudoHost: ALL
+sudoCommand: list
+sudoOrder: 1
+
+dn: cn=list,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: list
+sudoUser: list
+sudoHost: ALL
+sudoCommand: ALL
+sudoOrder: 2
+
+dn: cn=user2,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user2
+sudoUser: user2
+sudoHost: ALL
+sudoRunAsUser: list
+sudoRunAsGroup: list
+sudoCommand: ALL
+sudoOrder: 3
+
+dn: cn=user3,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: user3
+sudoUser: user3
+sudoHost: list
+sudoCommand: ALL
+sudoOrder: 4
+
diff --git a/plugins/sudoers/regress/sudoers/test30.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test30.ldif2sudo.ok
new file mode 100644
index 0000000..8e7b68e
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test30.ldif2sudo.ok
@@ -0,0 +1,11 @@
+# sudoRole user1
+user1 ALL = list
+
+# sudoRole list
+list ALL = ALL
+
+# sudoRole user2
+user2 ALL = (list : list) ALL
+
+# sudoRole user3
+user3 list = ALL
diff --git a/plugins/sudoers/regress/sudoers/test30.out.ok b/plugins/sudoers/regress/sudoers/test30.out.ok
new file mode 100644
index 0000000..95fc8ff
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test30.out.ok
@@ -0,0 +1,6 @@
+Parses OK
+
+user1 ALL = list
+list ALL = ALL
+user2 ALL = (list : list) ALL
+user3 list = ALL
diff --git a/plugins/sudoers/regress/sudoers/test30.sudo.ok b/plugins/sudoers/regress/sudoers/test30.sudo.ok
new file mode 100644
index 0000000..1f34b03
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test30.sudo.ok
@@ -0,0 +1,7 @@
+user1 ALL = list
+
+list ALL = ALL
+
+user2 ALL = (list : list) ALL
+
+user3 list = ALL
diff --git a/plugins/sudoers/regress/sudoers/test30.toke.ok b/plugins/sudoers/regress/sudoers/test30.toke.ok
new file mode 100644
index 0000000..a6a05ef
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test30.toke.ok
@@ -0,0 +1,10 @@
+#
+#
+
+WORD(6) ALL = WORD(6)
+
+WORD(6) ALL = ALL
+
+WORD(6) ALL = ( WORD(6) : WORD(6) ) ALL
+
+WORD(6) WORD(6) = ALL
diff --git a/plugins/sudoers/regress/sudoers/test4.in b/plugins/sudoers/regress/sudoers/test4.in
new file mode 100644
index 0000000..b8df454
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test4.in
@@ -0,0 +1,7 @@
+# Test line continuation with anchored matches
+User_Alias FOO = foo \
+: BAR = bar
+
+# This used to pass for sudo < 1.8.1 (though it should not have)
+User_Alias FOO = foo \
+User_Alias BAR = bar
diff --git a/plugins/sudoers/regress/sudoers/test4.json.ok b/plugins/sudoers/regress/sudoers/test4.json.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test4.json.ok
diff --git a/plugins/sudoers/regress/sudoers/test4.ldif.ok b/plugins/sudoers/regress/sudoers/test4.ldif.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test4.ldif.ok
diff --git a/plugins/sudoers/regress/sudoers/test4.out.ok b/plugins/sudoers/regress/sudoers/test4.out.ok
new file mode 100644
index 0000000..de27db3
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test4.out.ok
@@ -0,0 +1,3 @@
+
+User_Alias BAR = bar
+User_Alias FOO = foo
diff --git a/plugins/sudoers/regress/sudoers/test4.toke.ok b/plugins/sudoers/regress/sudoers/test4.toke.ok
new file mode 100644
index 0000000..a808e5a
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test4.toke.ok
@@ -0,0 +1,5 @@
+#
+USERALIAS ALIAS = WORD(6) : ALIAS = WORD(6)
+
+#
+USERALIAS ALIAS = WORD(6) ERROR <*> ALIAS = WORD(6)
diff --git a/plugins/sudoers/regress/sudoers/test5.in b/plugins/sudoers/regress/sudoers/test5.in
new file mode 100644
index 0000000..354f589
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test5.in
@@ -0,0 +1,3 @@
+# Test empty string in User_Alias and Command_Spec
+User_Alias FOO = ""
+"" ALL = ALL
diff --git a/plugins/sudoers/regress/sudoers/test5.json.ok b/plugins/sudoers/regress/sudoers/test5.json.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test5.json.ok
diff --git a/plugins/sudoers/regress/sudoers/test5.ldif.ok b/plugins/sudoers/regress/sudoers/test5.ldif.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test5.ldif.ok
diff --git a/plugins/sudoers/regress/sudoers/test5.out.ok b/plugins/sudoers/regress/sudoers/test5.out.ok
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test5.out.ok
@@ -0,0 +1 @@
+
diff --git a/plugins/sudoers/regress/sudoers/test5.toke.ok b/plugins/sudoers/regress/sudoers/test5.toke.ok
new file mode 100644
index 0000000..9376455
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test5.toke.ok
@@ -0,0 +1,3 @@
+#
+USERALIAS ALIAS = BEGINSTR ENDSTR ERROR <*>
+BEGINSTR ENDSTR ERROR <*> ALL = ALL
diff --git a/plugins/sudoers/regress/sudoers/test6.in b/plugins/sudoers/regress/sudoers/test6.in
new file mode 100644
index 0000000..e804571
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test6.in
@@ -0,0 +1,15 @@
+# Check that uids work in per-user and per-runas Defaults
+Defaults:#123 set_home
+Defaults>#123 set_home
+Defaults:"#123" set_home
+Defaults>"#123" set_home
+
+# Check that uids work in a Command_Spec
+#0 ALL = ALL
+#0 ALL = (#0 : #0) ALL
+"#0" ALL = ALL
+"#0" ALL = ("#0" : "#0") ALL
+
+# Check that gids work in a Command_Spec
+%#0 ALL = ALL
+"%#0" ALL = ALL
diff --git a/plugins/sudoers/regress/sudoers/test6.json.ok b/plugins/sudoers/regress/sudoers/test6.json.ok
new file mode 100644
index 0000000..be1f80f
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test6.json.ok
@@ -0,0 +1,158 @@
+{
+ "Defaults": [
+ {
+ "Binding": [
+ { "userid": 123 }
+ ],
+ "Options": [
+ { "set_home": true }
+ ]
+ },
+ {
+ "Binding": [
+ { "userid": 123 }
+ ],
+ "Options": [
+ { "set_home": true }
+ ]
+ },
+ {
+ "Binding": [
+ { "userid": 123 }
+ ],
+ "Options": [
+ { "set_home": true }
+ ]
+ },
+ {
+ "Binding": [
+ { "userid": 123 }
+ ],
+ "Options": [
+ { "set_home": true }
+ ]
+ }
+ ],
+ "User_Specs": [
+ {
+ "User_List": [
+ { "userid": 0 }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "userid": 0 }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "userid": 0 }
+ ],
+ "runasgroups": [
+ { "usergroup": "#0" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "userid": 0 }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "userid": 0 }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "runasusers": [
+ { "userid": 0 }
+ ],
+ "runasgroups": [
+ { "usergroup": "#0" }
+ ],
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "usergid": 0 }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ },
+ {
+ "User_List": [
+ { "usergid": 0 }
+ ],
+ "Host_List": [
+ { "hostname": "ALL" }
+ ],
+ "Cmnd_Specs": [
+ {
+ "Options": [
+ { "setenv": true }
+ ],
+ "Commands": [
+ { "command": "ALL" }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/plugins/sudoers/regress/sudoers/test6.ldif.ok b/plugins/sudoers/regress/sudoers/test6.ldif.ok
new file mode 100644
index 0000000..046b334
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test6.ldif.ok
@@ -0,0 +1,70 @@
+# Unable to translate stdin:2:23:
+# Defaults:#123 set_home
+
+# Unable to translate stdin:3:23:
+# Defaults>#123 set_home
+
+# Unable to translate stdin:4:25:
+# Defaults:#123 set_home
+
+# Unable to translate stdin:5:25:
+# Defaults>#123 set_home
+
+dn: cn=\#0,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: \#0
+sudoUser: #0
+sudoHost: ALL
+sudoCommand: ALL
+sudoOrder: 1
+
+dn: cn=\#0_1,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: \#0_1
+sudoUser: #0
+sudoHost: ALL
+sudoRunAsUser: #0
+sudoRunAsGroup: #0
+sudoCommand: ALL
+sudoOrder: 2
+
+dn: cn=\#0_2,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: \#0_2
+sudoUser: #0
+sudoHost: ALL
+sudoCommand: ALL
+sudoOrder: 3
+
+dn: cn=\#0_3,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: \#0_3
+sudoUser: #0
+sudoHost: ALL
+sudoRunAsUser: #0
+sudoRunAsGroup: #0
+sudoCommand: ALL
+sudoOrder: 4
+
+dn: cn=%\#0,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: %\#0
+sudoUser: %#0
+sudoHost: ALL
+sudoCommand: ALL
+sudoOrder: 5
+
+dn: cn=%\#0_1,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: %\#0_1
+sudoUser: %#0
+sudoHost: ALL
+sudoCommand: ALL
+sudoOrder: 6
+
diff --git a/plugins/sudoers/regress/sudoers/test6.ldif2sudo.ok b/plugins/sudoers/regress/sudoers/test6.ldif2sudo.ok
new file mode 100644
index 0000000..bfe40bb
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test6.ldif2sudo.ok
@@ -0,0 +1,5 @@
+# sudoRole #0, #0_1, #0_2, #0_3
+#0 ALL = ALL, (#0 : #0) ALL, ALL, (#0 : #0) ALL
+
+# sudoRole %#0, %#0_1
+%#0 ALL = ALL, ALL
diff --git a/plugins/sudoers/regress/sudoers/test6.out.ok b/plugins/sudoers/regress/sudoers/test6.out.ok
new file mode 100644
index 0000000..73b8fe0
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test6.out.ok
@@ -0,0 +1,13 @@
+Parses OK
+
+Defaults:#123 set_home
+Defaults>#123 set_home
+Defaults:#123 set_home
+Defaults>#123 set_home
+
+#0 ALL = ALL
+#0 ALL = (#0 : #0) ALL
+#0 ALL = ALL
+#0 ALL = (#0 : #0) ALL
+%#0 ALL = ALL
+%#0 ALL = ALL
diff --git a/plugins/sudoers/regress/sudoers/test6.toke.ok b/plugins/sudoers/regress/sudoers/test6.toke.ok
new file mode 100644
index 0000000..db8e1c5
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test6.toke.ok
@@ -0,0 +1,15 @@
+#
+DEFAULTS_USER WORD(6) DEFVAR
+DEFAULTS_RUNAS WORD(6) DEFVAR
+DEFAULTS_USER BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR
+DEFAULTS_RUNAS BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR
+
+#
+WORD(6) ALL = ALL
+WORD(6) ALL = ( WORD(6) : WORD(6) ) ALL
+BEGINSTR STRBODY ENDSTR WORD(4) ALL = ALL
+BEGINSTR STRBODY ENDSTR WORD(4) ALL = ( BEGINSTR STRBODY ENDSTR WORD(4) : BEGINSTR STRBODY ENDSTR WORD(4) ) ALL
+
+#
+USERGROUP ALL = ALL
+BEGINSTR STRBODY ENDSTR USERGROUP ALL = ALL
diff --git a/plugins/sudoers/regress/sudoers/test7.in b/plugins/sudoers/regress/sudoers/test7.in
new file mode 100644
index 0000000..7b241d0
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test7.in
@@ -0,0 +1,7 @@
+# These should all be syntax errors
+User_Alias FOO1 = "%"
+User_Alias FOO2 = "%:"
+User_Alias FOO3 = "+"
+User_Alias FOO4 = %
+User_Alias FOO5 = %:
+User_Alias FOO6 = +
diff --git a/plugins/sudoers/regress/sudoers/test7.json.ok b/plugins/sudoers/regress/sudoers/test7.json.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test7.json.ok
diff --git a/plugins/sudoers/regress/sudoers/test7.ldif.ok b/plugins/sudoers/regress/sudoers/test7.ldif.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test7.ldif.ok
diff --git a/plugins/sudoers/regress/sudoers/test7.out.ok b/plugins/sudoers/regress/sudoers/test7.out.ok
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test7.out.ok
@@ -0,0 +1 @@
+
diff --git a/plugins/sudoers/regress/sudoers/test7.toke.ok b/plugins/sudoers/regress/sudoers/test7.toke.ok
new file mode 100644
index 0000000..a5bf018
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test7.toke.ok
@@ -0,0 +1,7 @@
+#
+USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR ERROR <*>
+USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR ERROR <*>
+USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR ERROR <*>
+USERALIAS ALIAS = ERROR <*>
+USERALIAS ALIAS = ERROR <*>
+USERALIAS ALIAS = ERROR <*>
diff --git a/plugins/sudoers/regress/sudoers/test8.in b/plugins/sudoers/regress/sudoers/test8.in
new file mode 100644
index 0000000..d25e834
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test8.in
@@ -0,0 +1,8 @@
+# Test quoted strings
+User_Alias UA1 = "xy"
+User_Alias UA2 = "x\
+y"
+User_Alias UA3 = x\"y
+
+# A newline in the middle of a string is an error
+User_Alias UA4 = "x
diff --git a/plugins/sudoers/regress/sudoers/test8.json.ok b/plugins/sudoers/regress/sudoers/test8.json.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test8.json.ok
diff --git a/plugins/sudoers/regress/sudoers/test8.ldif.ok b/plugins/sudoers/regress/sudoers/test8.ldif.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test8.ldif.ok
diff --git a/plugins/sudoers/regress/sudoers/test8.out.ok b/plugins/sudoers/regress/sudoers/test8.out.ok
new file mode 100644
index 0000000..e62f97f
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test8.out.ok
@@ -0,0 +1,4 @@
+
+User_Alias UA1 = xy
+User_Alias UA2 = xy
+User_Alias UA3 = x\"y
diff --git a/plugins/sudoers/regress/sudoers/test8.toke.ok b/plugins/sudoers/regress/sudoers/test8.toke.ok
new file mode 100644
index 0000000..1bc46cb
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test8.toke.ok
@@ -0,0 +1,7 @@
+#
+USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4)
+USERALIAS ALIAS = BEGINSTR STRBODY STRBODY ENDSTR WORD(4)
+USERALIAS ALIAS = WORD(6)
+
+#
+USERALIAS ALIAS = BEGINSTR STRBODY ERROR <*>
diff --git a/plugins/sudoers/regress/sudoers/test9.in b/plugins/sudoers/regress/sudoers/test9.in
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test9.in
diff --git a/plugins/sudoers/regress/sudoers/test9.json.ok b/plugins/sudoers/regress/sudoers/test9.json.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test9.json.ok
diff --git a/plugins/sudoers/regress/sudoers/test9.ldif.ok b/plugins/sudoers/regress/sudoers/test9.ldif.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test9.ldif.ok
diff --git a/plugins/sudoers/regress/sudoers/test9.out.ok b/plugins/sudoers/regress/sudoers/test9.out.ok
new file mode 100644
index 0000000..5af5c53
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test9.out.ok
@@ -0,0 +1,2 @@
+Parses OK
+
diff --git a/plugins/sudoers/regress/sudoers/test9.toke.ok b/plugins/sudoers/regress/sudoers/test9.toke.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/sudoers/test9.toke.ok
diff --git a/plugins/sudoers/regress/testsudoers/group b/plugins/sudoers/regress/testsudoers/group
new file mode 100644
index 0000000..f272010
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/group
@@ -0,0 +1,17 @@
+wheel:*:0:root
+daemon:*:1:daemon
+kmem:*:2:root
+sys:*:3:root
+tty:*:4:root
+operator:*:5:root
+bin:*:7:
+wsrc:*:9:
+users:*:10:
+auth:*:11:
+games:*:13:
+staff:*:20:root
+guest:*:31:root
+admin:*:1000:
+fakeshell:*:1001:
+nogroup:*:32766:
+nobody:*:32767:
diff --git a/plugins/sudoers/regress/testsudoers/passwd b/plugins/sudoers/regress/testsudoers/passwd
new file mode 100644
index 0000000..c3d0a9c
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/passwd
@@ -0,0 +1,7 @@
+root:*:0:0:Charlie &:/root:/bin/sh
+daemon:*:1:1:The devil himself:/root:/sbin/nologin
+operator:*:2:5:System &:/operator:/sbin/nologin
+bin:*:3:7:Binaries Commands and Source:/:/sbin/nologin
+admin:*:1000:1000:Admin user:/home/admin:/bin/sh
+fakeshell:*:1001:1001:Shell test user:/home/fakeshell:/shell/does/not/exist
+nobody:*:32767:32767:Unprivileged user:/nonexistent:/sbin/nologin
diff --git a/plugins/sudoers/regress/testsudoers/test1.out.ok b/plugins/sudoers/regress/testsudoers/test1.out.ok
new file mode 100644
index 0000000..06c27c4
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test1.out.ok
@@ -0,0 +1,11 @@
+Parses OK
+
+Entries for user root:
+
+ALL = ALL
+ host allowed
+ runas unmatched
+
+Password required
+
+Command unmatched
diff --git a/plugins/sudoers/regress/testsudoers/test1.sh b/plugins/sudoers/regress/testsudoers/test1.sh
new file mode 100755
index 0000000..495f237
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test1.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Test for NULL dereference with "sudo -g group" when the sudoers rule
+# has no runas user or group listed.
+# This is RedHat bug Bug 667103.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+$TESTSUDOERS -g bin -P ${TESTDIR}/group root id <<EOF
+root ALL = ALL
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test10.out.ok b/plugins/sudoers/regress/testsudoers/test10.out.ok
new file mode 100644
index 0000000..94e912e
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test10.out.ok
@@ -0,0 +1,59 @@
+Testing @include of a path with escaped white space
+
+Parses OK
+
+Entries for user root:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+Testing @include of a double-quoted path with white space
+
+Parses OK
+
+Entries for user root:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+Testing #include of a path with escaped white space
+
+Parses OK
+
+Entries for user root:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+Testing #include of a double-quoted path with white space
+
+Parses OK
+
+Entries for user root:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test10.sh b/plugins/sudoers/regress/testsudoers/test10.sh
new file mode 100755
index 0000000..c4f0f2d
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test10.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# Test @include of a file with embedded white space
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+# Create test file
+TESTDIR="`pwd`/regress/testsudoers"
+cat >"$TESTDIR/test 10.inc" <<EOF
+root ALL = ALL
+EOF
+
+MYUID=`\ls -lnd "$TESTDIR/test 10.inc" | awk '{print $3}'`
+MYGID=`\ls -lnd "$TESTDIR/test 10.inc" | awk '{print $4}'`
+exec 2>&1
+
+echo "Testing @include of a path with escaped white space"
+echo ""
+$TESTSUDOERS -U $MYUID -G $MYGID root id <<-EOF
+ @include $TESTDIR/test\ 10.inc
+EOF
+
+echo ""
+echo "Testing @include of a double-quoted path with white space"
+echo ""
+$TESTSUDOERS -U $MYUID -G $MYGID root id <<-EOF
+ @include "$TESTDIR/test 10.inc"
+EOF
+
+echo ""
+echo "Testing #include of a path with escaped white space"
+echo ""
+$TESTSUDOERS -U $MYUID -G $MYGID root id <<-EOF
+ #include $TESTDIR/test\ 10.inc
+EOF
+
+echo ""
+echo "Testing #include of a double-quoted path with white space"
+echo ""
+$TESTSUDOERS -U $MYUID -G $MYGID root id <<-EOF
+ #include "$TESTDIR/test 10.inc"
+EOF
+
+rm -f "$TESTDIR/test 10.inc"
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test11.out.ok b/plugins/sudoers/regress/testsudoers/test11.out.ok
new file mode 100644
index 0000000..ee98540
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test11.out.ok
@@ -0,0 +1,25 @@
+Testing @include with garbage after the path name
+
+sudoers:1:24: syntax error
+@include sudoers.local womp womp
+ ^~~~
+testsudoers: unable to open sudoers.local: No such file or directory
+
+Entries for user root:
+
+Password required
+
+Parse error
+
+Testing #include with garbage after the path name
+
+sudoers:1:24: syntax error
+#include sudoers.local womp womp
+ ^~~~
+testsudoers: unable to open sudoers.local: No such file or directory
+
+Entries for user root:
+
+Password required
+
+Parse error
diff --git a/plugins/sudoers/regress/testsudoers/test11.sh b/plugins/sudoers/regress/testsudoers/test11.sh
new file mode 100755
index 0000000..d52754d
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test11.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Test @include with garbage after the path name
+# The standard error output is dup'd to the standard output.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+MYUID=`\ls -ln $TESTDIR/test2.inc | awk '{print $3}'`
+MYGID=`\ls -ln $TESTDIR/test2.inc | awk '{print $4}'`
+
+echo "Testing @include with garbage after the path name"
+echo ""
+$TESTSUDOERS -U $MYUID -G $MYGID root id <<EOF 2>&1 | sed 's/\(syntax error\), .*/\1/'
+@include sudoers.local womp womp
+EOF
+
+echo ""
+echo "Testing #include with garbage after the path name"
+echo ""
+$TESTSUDOERS -U $MYUID -G $MYGID root id <<EOF 2>&1 | sed 's/\(syntax error\), .*/\1/'
+#include sudoers.local womp womp
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test12.out.ok b/plugins/sudoers/regress/testsudoers/test12.out.ok
new file mode 100644
index 0000000..a28a831
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test12.out.ok
@@ -0,0 +1,18 @@
+Testing sudoers with multiple syntax errors
+
+sudoers:1:20: syntax error
+User_Alias A1 = u1 u2 : A2 = u3, u4
+ ^~
+sudoers:3:26: syntax error
+millert ALL = /fail : foo
+ ^
+sudoers:5:16: syntax error
+root ALL = ALL bar
+ ^~~
+sudoers:7:12: expected a fully-qualified path name
+root ALL = baz
+ ^~~
+
+User_Alias A1 = u1
+
+millert ALL = /fail
diff --git a/plugins/sudoers/regress/testsudoers/test12.sh b/plugins/sudoers/regress/testsudoers/test12.sh
new file mode 100755
index 0000000..8890ca5
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test12.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Test sudoers file with multiple syntax errors
+# The standard error output is dup'd to the standard output.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+echo "Testing sudoers with multiple syntax errors"
+echo ""
+$TESTSUDOERS -d <<EOF 2>&1 | sed 's/\(syntax error\), .*/\1/'
+User_Alias A1 = u1 u2 : A2 = u3, u4
+
+millert ALL = /fail : foo
+
+root ALL = ALL bar
+
+root ALL = baz
+EOF
diff --git a/plugins/sudoers/regress/testsudoers/test13.out.ok b/plugins/sudoers/regress/testsudoers/test13.out.ok
new file mode 100644
index 0000000..bfb9f53
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test13.out.ok
@@ -0,0 +1,22 @@
+Testing alias definitions using reserved words
+
+sudoers:1:12: syntax error, reserved word ALL used as an alias name
+Cmnd_Alias ALL=ALL
+ ^~~
+sudoers:2:12: syntax error, reserved word CHROOT used as an alias name
+Cmnd_Alias CHROOT=foo
+ ^~~~~~
+sudoers:3:12: syntax error, reserved word CMND_TIMEOUT used as an alias name
+User_Alias TIMEOUT=foo
+ ^~~~~~~
+sudoers:4:13: syntax error, reserved word CWD used as an alias name
+Runas_Alias CWD=bar
+ ^~~
+sudoers:5:12: syntax error, reserved word NOTBEFORE used as an alias name
+Host_Alias NOTBEFORE=baz
+ ^~~~~~~~~
+sudoers:6:12: syntax error, reserved word NOTAFTER used as an alias name
+Host_Alias NOTAFTER=biff
+ ^~~~~~~~
+
+root ALL = ALL
diff --git a/plugins/sudoers/regress/testsudoers/test13.sh b/plugins/sudoers/regress/testsudoers/test13.sh
new file mode 100755
index 0000000..d9c3d0c
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test13.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Test sudoers file with reserved words as alias names.
+# The standard error output is dup'd to the standard output.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+echo "Testing alias definitions using reserved words"
+echo ""
+$TESTSUDOERS -d <<EOF 2>&1
+Cmnd_Alias ALL=ALL
+Cmnd_Alias CHROOT=foo
+User_Alias TIMEOUT=foo
+Runas_Alias CWD=bar
+Host_Alias NOTBEFORE=baz
+Host_Alias NOTAFTER=biff
+
+root ALL = ALL
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test14.out.ok b/plugins/sudoers/regress/testsudoers/test14.out.ok
new file mode 100644
index 0000000..add1bb2
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test14.out.ok
@@ -0,0 +1,18 @@
+
+Testing user privilege without a newline
+
+Parses OK
+
+millert ALL = ALL
+
+Testing alias without a newline
+
+Parses OK
+
+Cmnd_Alias FOO = /bin/bar
+
+Testing Defaults without a newline
+
+Parses OK
+
+Defaults log_output
diff --git a/plugins/sudoers/regress/testsudoers/test14.sh b/plugins/sudoers/regress/testsudoers/test14.sh
new file mode 100755
index 0000000..7739c67
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test14.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Test entries with no trailing newline.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+
+echo ""
+echo "Testing user privilege without a newline"
+echo ""
+printf "millert ALL = ALL" | $TESTSUDOERS -d
+
+echo ""
+echo "Testing alias without a newline"
+echo ""
+printf "Cmnd_Alias FOO=/bin/bar" | $TESTSUDOERS -d
+
+echo ""
+echo "Testing Defaults without a newline"
+echo ""
+printf "Defaults log_output" | $TESTSUDOERS -d
+
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test15.out.ok b/plugins/sudoers/regress/testsudoers/test15.out.ok
new file mode 100644
index 0000000..cc4361d
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test15.out.ok
@@ -0,0 +1,19 @@
+Testing @include of a file with a missing newline
+
+Parses OK
+
+Entries for user root:
+
+ALL = /usr/bin/id
+ host allowed
+ runas allowed
+ cmnd unmatched
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test15.sh b/plugins/sudoers/regress/testsudoers/test15.sh
new file mode 100755
index 0000000..a4596cd
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test15.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Test @include of a file with a missing newline
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+# Create test file
+TESTDIR="`pwd`/regress/testsudoers"
+printf "root ALL = ALL" >"$TESTDIR/test15.inc"
+
+MYUID=`\ls -lnd "$TESTDIR/test15.inc" | awk '{print $3}'`
+MYGID=`\ls -lnd "$TESTDIR/test15.inc" | awk '{print $4}'`
+exec 2>&1
+
+echo "Testing @include of a file with a missing newline"
+echo ""
+$TESTSUDOERS -U $MYUID -G $MYGID root id <<-EOF
+ @include $TESTDIR/test15.inc
+ ALL ALL = /usr/bin/id
+EOF
+
+rm -f "$TESTDIR/test15.inc"
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test16.out.ok b/plugins/sudoers/regress/testsudoers/test16.out.ok
new file mode 100644
index 0000000..3c4e7fa
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test16.out.ok
@@ -0,0 +1,12 @@
+Parses OK
+
+Entries for user root:
+
+ALL = (ALL) ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test16.sh b/plugins/sudoers/regress/testsudoers/test16.sh
new file mode 100755
index 0000000..507bdd4
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test16.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+#
+# Test to exercise Bug #994, a crash matching sudoCommand ALL.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+$TESTSUDOERS -i ldif root id <<-EOF
+dn: dc=sudo,dc=ws
+objectClass: dcObject
+objectClass: organization
+dc: bigwheel
+o: Big Wheel
+description: Big Wheel
+
+# Organizational Role for Directory Manager
+dn: cn=Manager,dc=sudo,dc=ws
+objectClass: organizationalRole
+cn: Manager
+description: Directory Manager
+
+# SUDOers, sudo.ws
+dn: ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: organizationalUnit
+description: SUDO Configuration Subtree
+ou: SUDOers
+
+# root, SUDOers, sudo.ws
+dn: cn=root,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: root
+sudoUser: root
+sudoRunAs: ALL
+sudoHost: ALL
+sudoCommand: ALL
+sudoOrder: 10
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test17.out.ok b/plugins/sudoers/regress/testsudoers/test17.out.ok
new file mode 100644
index 0000000..56c4715
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test17.out.ok
@@ -0,0 +1,12 @@
+Parses OK
+
+Entries for user root:
+
+ALL = (ALL) sha224:fIoq2MAfM/PZKTbkn9RE4VZ8YHjwnwTgE28Hxw== ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test17.sh b/plugins/sudoers/regress/testsudoers/test17.sh
new file mode 100755
index 0000000..b98b907
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test17.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+#
+# Test that digest matching works with LDAP sudoCommand: ALL
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+# Create test command with known digest
+TESTDIR="`pwd`/regress/testsudoers"
+cat >"$TESTDIR/hello" <<EOF
+#!/bin/sh
+echo Hello World
+EOF
+chmod 755 "$TESTDIR/hello"
+SHA224_DIGEST="fIoq2MAfM/PZKTbkn9RE4VZ8YHjwnwTgE28Hxw=="
+
+$TESTSUDOERS -i ldif root "${TESTDIR}/hello" <<-EOF
+dn: dc=sudo,dc=ws
+objectClass: dcObject
+objectClass: organization
+dc: bigwheel
+o: Big Wheel
+description: Big Wheel
+
+# Organizational Role for Directory Manager
+dn: cn=Manager,dc=sudo,dc=ws
+objectClass: organizationalRole
+cn: Manager
+description: Directory Manager
+
+# SUDOers, sudo.ws
+dn: ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: organizationalUnit
+description: SUDO Configuration Subtree
+ou: SUDOers
+
+# root, SUDOers, sudo.ws
+dn: cn=root,ou=SUDOers,dc=sudo,dc=ws
+objectClass: top
+objectClass: sudoRole
+cn: root
+sudoUser: root
+sudoRunAs: ALL
+sudoHost: ALL
+sudoCommand: sha224:$SHA224_DIGEST ALL
+sudoOrder: 10
+EOF
+
+rm -f "$TESTDIR/hello"
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test18.out.ok b/plugins/sudoers/regress/testsudoers/test18.out.ok
new file mode 100644
index 0000000..c497a7a
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test18.out.ok
@@ -0,0 +1,72 @@
+Parses OK
+
+Entries for user root:
+
+ALL = ^/bin/ls$ ^-[lAt]$
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+Parses OK
+
+Entries for user root:
+
+ALL = ^/bin/cat$ /var/log/*
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+Parses OK
+
+Entries for user root:
+
+ALL = /bin/cat ^/var/log/[^/]+$
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+Parses OK
+
+Entries for user root:
+
+ALL = /bin/*at ^/var/log/[^/]+$
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+Parses OK
+
+Entries for user root:
+
+ALL = /usr/bin/grep \^foo$
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+Parses OK
+
+Entries for user root:
+
+ALL = sudoedit ^/etc/(motd|issue|hosts)$
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test18.sh b/plugins/sudoers/regress/testsudoers/test18.sh
new file mode 100755
index 0000000..645b9a5
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test18.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+#
+# Test regular expressions
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+
+# Command and args: regex
+$TESTSUDOERS root /bin/ls -l <<'EOF'
+root ALL = ^/bin/ls$ ^-[lAt]$
+EOF
+
+# Command: regex, args: wildcard
+$TESTSUDOERS root /bin/cat /var/log/syslog <<'EOF'
+root ALL = ^/bin/cat$ /var/log/*
+EOF
+
+# Command: path, args: regex
+$TESTSUDOERS root /bin/cat /var/log/authlog <<'EOF'
+root ALL = /bin/cat ^/var/log/[^/]+$
+EOF
+
+# Command: wildcard, args: regex
+$TESTSUDOERS root /bin/cat /var/log/mail <<'EOF'
+root ALL = /bin/*at ^/var/log/[^/]+$
+EOF
+
+# Command: path, args: args start with escaped ^
+$TESTSUDOERS root /usr/bin/grep '^foo$' <<'EOF'
+root ALL = /usr/bin/grep \^foo$
+EOF
+
+# Command: sudoedit, args: regex
+$TESTSUDOERS root sudoedit /etc/motd <<'EOF'
+root ALL = sudoedit ^/etc/(motd|issue|hosts)$
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test19.out.ok b/plugins/sudoers/regress/testsudoers/test19.out.ok
new file mode 100644
index 0000000..db2142d
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test19.out.ok
@@ -0,0 +1,24 @@
+Parses OK
+
+Entries for user root:
+
+ALL = /bin/ls ""
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+Parses OK
+
+Entries for user root:
+
+ALL = /bin/ls ""
+ host allowed
+ runas allowed
+ cmnd unmatched
+
+Password required
+
+Command unmatched
diff --git a/plugins/sudoers/regress/testsudoers/test19.sh b/plugins/sudoers/regress/testsudoers/test19.sh
new file mode 100755
index 0000000..113eb2a
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test19.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Verify that "" in sudoers does not match a literal "" on the command line.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+
+# This should succeed
+$TESTSUDOERS root /bin/ls <<'EOF'
+root ALL = /bin/ls ""
+EOF
+
+# This should fail
+$TESTSUDOERS root /bin/ls '""' <<'EOF'
+root ALL = /bin/ls ""
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test2.inc b/plugins/sudoers/regress/testsudoers/test2.inc
new file mode 100644
index 0000000..52ca040
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test2.inc
@@ -0,0 +1 @@
+root ALL = ALL
diff --git a/plugins/sudoers/regress/testsudoers/test2.out.ok b/plugins/sudoers/regress/testsudoers/test2.out.ok
new file mode 100644
index 0000000..a017d8a
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test2.out.ok
@@ -0,0 +1,29 @@
+Testing @include
+
+Parses OK
+
+Entries for user root:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+Testing #include
+
+Parses OK
+
+Entries for user root:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test2.sh b/plugins/sudoers/regress/testsudoers/test2.sh
new file mode 100755
index 0000000..0b0b3f8
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test2.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Test @include facility
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+MYUID=`\ls -ln $TESTDIR/test2.inc | awk '{print $3}'`
+MYGID=`\ls -ln $TESTDIR/test2.inc | awk '{print $4}'`
+exec 2>&1
+
+echo "Testing @include"
+echo ""
+$TESTSUDOERS -U $MYUID -G $MYGID root id <<EOF
+@include $TESTDIR/test2.inc
+EOF
+
+echo ""
+echo "Testing #include"
+echo ""
+$TESTSUDOERS -U $MYUID -G $MYGID root id <<EOF
+#include $TESTDIR/test2.inc
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test20.out.ok b/plugins/sudoers/regress/testsudoers/test20.out.ok
new file mode 100644
index 0000000..6a8e451
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test20.out.ok
@@ -0,0 +1,12 @@
+Parses OK
+
+Entries for user root:
+
+ALL = CHROOT=/ /bin/ls
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test20.sh b/plugins/sudoers/regress/testsudoers/test20.sh
new file mode 100755
index 0000000..4325175
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test20.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+#
+# Verify CHROOT and CWD support
+# This will catch an unpatched double-free in set_cmnd_path() under ASAN.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+
+# Exercise double free of user_cmnd in set_cmnd_path() under ASAN.
+# We need more than one rule where the last rule matches and has CHROOT.
+$TESTSUDOERS root /bin/ls <<'EOF'
+root ALL = CWD=/ /bin/pwd
+root ALL = CHROOT=/ /bin/ls
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test21.out.ok b/plugins/sudoers/regress/testsudoers/test21.out.ok
new file mode 100644
index 0000000..391b668
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test21.out.ok
@@ -0,0 +1,12 @@
+Parses OK
+
+Entries for user admin:
+
+ALL = (USERALIAS : GROUPALIAS) /bin/ls
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test21.sh b/plugins/sudoers/regress/testsudoers/test21.sh
new file mode 100755
index 0000000..714caf1
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test21.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Verify that a Runas_Alias works in both user and group lists.
+# This tests a bug fixed in sudo 1.9.14.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+
+# The user in USERALIAS must *not* belong to the group in GROUPALIAS
+# in the group or passwd file in order to reproduce the bug.
+$TESTSUDOERS -u root -g bin -p ${TESTDIR}/passwd -P ${TESTDIR}/group \
+ admin /bin/ls <<'EOF'
+Runas_Alias USERALIAS = root
+Runas_Alias GROUPALIAS = bin
+admin ALL = (USERALIAS : GROUPALIAS) /bin/ls
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test22.out.ok b/plugins/sudoers/regress/testsudoers/test22.out.ok
new file mode 100644
index 0000000..54f273f
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test22.out.ok
@@ -0,0 +1,11 @@
+Parses OK
+
+Entries for user admin:
+
+ALL = /bin/ls
+ host allowed
+ runas unmatched
+
+Password required
+
+Command unmatched
diff --git a/plugins/sudoers/regress/testsudoers/test22.sh b/plugins/sudoers/regress/testsudoers/test22.sh
new file mode 100755
index 0000000..9d4dbcb
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test22.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+#
+# Verify that a user is only allowed to run commands with a group
+# that is specified by sudoers (or that the runas user is a member of).
+# This tests a bug fixed in sudo 1.9.14.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+
+# The root user must *not* belong to the group specified below.
+$TESTSUDOERS -u root -g bin -p ${TESTDIR}/passwd -P ${TESTDIR}/group \
+ admin /bin/ls <<'EOF'
+admin ALL = /bin/ls
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test23.out.ok b/plugins/sudoers/regress/testsudoers/test23.out.ok
new file mode 100644
index 0000000..2e99ac8
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test23.out.ok
@@ -0,0 +1,11 @@
+Parses OK
+
+Entries for user admin:
+
+ALL = (root) /bin/ls
+ host allowed
+ runas unmatched
+
+Password required
+
+Command unmatched
diff --git a/plugins/sudoers/regress/testsudoers/test23.sh b/plugins/sudoers/regress/testsudoers/test23.sh
new file mode 100755
index 0000000..a790c6a
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test23.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Verify that a user is not allowed to run commands with their own
+# user and group if sudoers doesn't explicitly permit it.
+# This tests a bug fixed in sudo 1.9.14.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+
+$TESTSUDOERS -u admin -g admin -p ${TESTDIR}/passwd -P ${TESTDIR}/group \
+ admin /bin/ls <<'EOF'
+admin ALL = (root) /bin/ls
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test24.out.ok b/plugins/sudoers/regress/testsudoers/test24.out.ok
new file mode 100644
index 0000000..0a38de3
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test24.out.ok
@@ -0,0 +1,48 @@
+Parses OK
+
+Entries for user root:
+
+ALL = NOTBEFORE=20170214083000Z /bin/ls
+ host allowed
+ date allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+Parses OK
+
+Entries for user root:
+
+ALL = NOTBEFORE=20170214083001Z /bin/ls
+ host allowed
+ date denied
+
+Password required
+
+Command unmatched
+Parses OK
+
+Entries for user root:
+
+ALL = NOTAFTER=20170214083000Z /bin/ls
+ host allowed
+ date allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+Parses OK
+
+Entries for user root:
+
+ALL = NOTAFTER=20170214083000Z /bin/ls
+ host allowed
+ date denied
+
+Password required
+
+Command unmatched
diff --git a/plugins/sudoers/regress/testsudoers/test24.sh b/plugins/sudoers/regress/testsudoers/test24.sh
new file mode 100755
index 0000000..8be4ebc
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test24.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+#
+# Verify that NOTBEFORE and NOTAFTER work as expected.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+
+retval=0
+
+$TESTSUDOERS -T 20170214083000Z root /bin/ls <<'EOF'
+root ALL = NOTBEFORE=20170214083000Z /bin/ls
+EOF
+if [ $? -ne 0 ]; then
+ retval=$?
+fi
+
+# expect failure
+$TESTSUDOERS -T 20170214083000Z root /bin/ls <<'EOF'
+root ALL = NOTBEFORE=20170214083001Z /bin/ls
+EOF
+if [ $? -eq 0 ]; then
+ retval=1
+fi
+
+$TESTSUDOERS -T 20170214083000Z root /bin/ls <<'EOF'
+root ALL = NOTAFTER=20170214083000Z /bin/ls
+EOF
+if [ $? -ne 0 ]; then
+ retval=$?
+fi
+
+# expect failure
+$TESTSUDOERS -T 20170214083001Z root /bin/ls <<'EOF'
+root ALL = NOTAFTER=20170214083000Z /bin/ls
+EOF
+if [ $? -eq 0 ]; then
+ retval=1
+fi
+
+exit $retval
diff --git a/plugins/sudoers/regress/testsudoers/test25.out.ok b/plugins/sudoers/regress/testsudoers/test25.out.ok
new file mode 100644
index 0000000..d23bdb2
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test25.out.ok
@@ -0,0 +1,59 @@
+A simple sudoers rule should not allow the user to set the cwd:
+Parses OK
+
+Entries for user root:
+
+ALL = /bin/ls
+ host allowed
+ runas allowed
+ cmnd allowed
+
+User root is not allowed to change directory to /
+
+Password required
+
+Command denied
+
+User cannot override the sudoers cwd:
+Parses OK
+
+Entries for user root:
+
+ALL = CWD=/some/where/else /bin/ls
+ host allowed
+ runas allowed
+ cmnd allowed
+
+User root is not allowed to change directory to /
+
+Password required
+
+Command denied
+
+User can set cwd if sudoers rule sets cwd to '*':
+Parses OK
+
+Entries for user root:
+
+ALL = CWD=* /bin/ls
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+User can set cwd runcwd Defaults is '*':
+Parses OK
+
+Entries for user root:
+
+ALL = /bin/ls
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test25.sh b/plugins/sudoers/regress/testsudoers/test25.sh
new file mode 100755
index 0000000..a3c395c
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test25.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+#
+# Test user-specified cwd handling
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+cd /
+
+retval=0
+
+# Sudo used to allow the user to set the cwd to the current value.
+# Now, a cwd must be explicitly set in sudoers to use the -D option.
+printf "A simple sudoers rule should not allow the user to set the cwd:\n"
+$TESTSUDOERS -D / root /bin/ls <<'EOF'
+root ALL = /bin/ls
+EOF
+if [ $? -eq 0 ]; then
+ retval=1
+fi
+
+printf "\nUser cannot override the sudoers cwd:\n"
+$TESTSUDOERS -D / root /bin/ls <<'EOF'
+root ALL = CWD=/some/where/else /bin/ls
+EOF
+if [ $? -eq 0 ]; then
+ retval=1
+fi
+
+printf "\nUser can set cwd if sudoers rule sets cwd to '*':\n"
+$TESTSUDOERS -D /usr root /bin/ls <<'EOF'
+root ALL = CWD=* /bin/ls
+EOF
+if [ $? -ne 0 ]; then
+ retval=$?
+fi
+
+printf "\nUser can set cwd runcwd Defaults is '*':\n"
+$TESTSUDOERS -D /usr root /bin/ls <<'EOF'
+Defaults runcwd = "*"
+root ALL = /bin/ls
+EOF
+if [ $? -ne 0 ]; then
+ retval=$?
+fi
+
+exit $retval
diff --git a/plugins/sudoers/regress/testsudoers/test26.out.ok b/plugins/sudoers/regress/testsudoers/test26.out.ok
new file mode 100644
index 0000000..281817c
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test26.out.ok
@@ -0,0 +1,57 @@
+A simple sudoers rule should not allow the user to chroot:
+Parses OK
+
+Entries for user root:
+
+ALL = /bin/ls
+ host allowed
+ runas allowed
+ cmnd allowed
+
+User root is not allowed to change root directory to /
+
+Password required
+
+Command denied
+
+User cannot override the sudoers chroot:
+Parses OK
+
+Entries for user root:
+
+ALL = CHROOT=/some/where/else /bin/ls
+ host allowed
+ runas allowed
+ cmnd unmatched
+
+Password required
+
+Command unmatched
+
+User can chroot if sudoers rule sets chroot to '*':
+Parses OK
+
+Entries for user root:
+
+ALL = CHROOT=* /bin/ls
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+User can chroot if runchroot Defaults is '*':
+Parses OK
+
+Entries for user root:
+
+ALL = /bin/ls
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test26.sh b/plugins/sudoers/regress/testsudoers/test26.sh
new file mode 100755
index 0000000..bef55da
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test26.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# Test user-specified chroot handling
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+cd /
+
+retval=0
+
+printf "A simple sudoers rule should not allow the user to chroot:\n"
+$TESTSUDOERS -R / root /bin/ls <<'EOF'
+root ALL = /bin/ls
+EOF
+if [ $? -eq 0 ]; then
+ retval=1
+fi
+
+# Because command_matches() uses the per-rule CHROOT, this results in
+# an unmatched rule instead of a matched rule that is rejected later.
+# This is different from the CWD checking which is performed after
+# matching is done.
+printf "\nUser cannot override the sudoers chroot:\n"
+$TESTSUDOERS -R / root /bin/ls <<'EOF'
+root ALL = CHROOT=/some/where/else /bin/ls
+EOF
+if [ $? -eq 0 ]; then
+ retval=1
+fi
+
+printf "\nUser can chroot if sudoers rule sets chroot to '*':\n"
+$TESTSUDOERS -R /usr root /bin/ls <<'EOF'
+root ALL = CHROOT=* /bin/ls
+EOF
+if [ $? -ne 0 ]; then
+ retval=$?
+fi
+
+printf "\nUser can chroot if runchroot Defaults is '*':\n"
+$TESTSUDOERS -R /usr root /bin/ls <<'EOF'
+Defaults runchroot = "*"
+root ALL = /bin/ls
+EOF
+if [ $? -ne 0 ]; then
+ retval=$?
+fi
+
+exit $retval
diff --git a/plugins/sudoers/regress/testsudoers/test27.out.ok b/plugins/sudoers/regress/testsudoers/test27.out.ok
new file mode 100644
index 0000000..73c06b7
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test27.out.ok
@@ -0,0 +1,14 @@
+Parses OK
+
+Entries for user admin:
+
+ALL = (ALL) /bin/ls
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Invalid shell for user fakeshell: /shell/does/not/exist
+
+Password required
+
+Command denied
diff --git a/plugins/sudoers/regress/testsudoers/test27.sh b/plugins/sudoers/regress/testsudoers/test27.sh
new file mode 100755
index 0000000..8733bb8
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test27.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Verify that runas_check_shell works as expected.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+
+# This should fail due to fakeshell's shell
+$TESTSUDOERS -u fakeshell -p ${TESTDIR}/passwd -P ${TESTDIR}/group \
+ admin /bin/ls <<'EOF'
+Defaults runas_check_shell
+admin ALL = (ALL) /bin/ls
+EOF
+
+# Expected failure
+if [ $? -eq 0 ]; then
+ exit 1
+else
+ exit 0
+fi
diff --git a/plugins/sudoers/regress/testsudoers/test28.out.ok b/plugins/sudoers/regress/testsudoers/test28.out.ok
new file mode 100644
index 0000000..188d8de
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test28.out.ok
@@ -0,0 +1,125 @@
+This should match the 'ALL=ALL' rule.
+Parses OK
+
+Entries for user admin:
+
+ALL = (admin : staff) NOPASSWD: ALL
+ host allowed
+ runas unmatched
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+This should match the 'ALL=ALL' rule.
+Parses OK
+
+Entries for user admin:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+This should match the 'ALL=(:staff) NOPASSWD: ALL' rule.
+Parses OK
+
+Entries for user admin:
+
+ALL = (admin : staff) NOPASSWD: ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Command allowed
+
+This should match the 'ALL=(:staff) NOPASSWD: ALL' rule.
+Parses OK
+
+Entries for user admin:
+
+ALL = ALL
+ host allowed
+ runas unmatched
+
+ALL = (admin : staff) NOPASSWD: ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Command allowed
+
+This should match the 'ALL=(:staff) NOPASSWD: ALL' rule.
+Parses OK
+
+Entries for user admin:
+
+ALL = ALL
+ host allowed
+ runas unmatched
+
+ALL = (admin : staff) NOPASSWD: ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Command allowed
+
+This should match the 'ALL=(:staff) NOPASSWD: ALL' rule.
+Parses OK
+
+Entries for user admin:
+
+ALL = ALL
+ host allowed
+ runas unmatched
+
+ALL = (admin : staff) NOPASSWD: ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Command allowed
+
+This should not match any rules.
+Parses OK
+
+Entries for user admin:
+
+ALL = ALL
+ host allowed
+ runas unmatched
+
+ALL = (admin : staff) NOPASSWD: ALL
+ host allowed
+ runas unmatched
+
+Password required
+
+Command unmatched
+
+This should not match any rules.
+Parses OK
+
+Entries for user admin:
+
+ALL = ALL
+ host allowed
+ runas unmatched
+
+ALL = (admin : users) NOPASSWD: ALL
+ host allowed
+ runas unmatched
+
+Password required
+
+Command unmatched
diff --git a/plugins/sudoers/regress/testsudoers/test28.sh b/plugins/sudoers/regress/testsudoers/test28.sh
new file mode 100755
index 0000000..0465531
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test28.sh
@@ -0,0 +1,99 @@
+#!/bin/sh
+#
+# Verify that a rule with an empty Runas user matches correctly.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+
+status=0
+
+echo "This should match the 'ALL=ALL' rule."
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group \
+ admin /bin/ls <<'EOF'
+admin ALL = ALL
+ALL ALL=(:staff) NOPASSWD: ALL
+EOF
+if [ $? -ne 0 ]; then
+ status=1
+fi
+
+echo ""
+echo "This should match the 'ALL=ALL' rule."
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group \
+ admin /bin/ls <<'EOF'
+ALL ALL=(:staff) NOPASSWD: ALL
+admin ALL = ALL
+EOF
+if [ $? -ne 0 ]; then
+ status=1
+fi
+
+echo ""
+echo "This should match the 'ALL=(:staff) NOPASSWD: ALL' rule."
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -g staff \
+ admin /bin/ls <<'EOF'
+admin ALL = ALL
+ALL ALL=(:staff) NOPASSWD: ALL
+EOF
+if [ $? -ne 0 ]; then
+ status=1
+fi
+
+echo ""
+echo "This should match the 'ALL=(:staff) NOPASSWD: ALL' rule."
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -g staff \
+ admin /bin/ls <<'EOF'
+ALL ALL=(:staff) NOPASSWD: ALL
+admin ALL = ALL
+EOF
+if [ $? -ne 0 ]; then
+ status=1
+fi
+
+echo ""
+echo "This should match the 'ALL=(:staff) NOPASSWD: ALL' rule."
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -u admin \
+ admin /bin/ls <<'EOF'
+ALL ALL=(:staff) NOPASSWD: ALL
+admin ALL = ALL
+EOF
+if [ $? -ne 0 ]; then
+ status=1
+fi
+
+echo ""
+echo "This should match the 'ALL=(:staff) NOPASSWD: ALL' rule."
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -u admin -g staff \
+ admin /bin/ls <<'EOF'
+ALL ALL=(:staff) NOPASSWD: ALL
+admin ALL = ALL
+EOF
+if [ $? -ne 0 ]; then
+ status=1
+fi
+
+echo ""
+echo "This should not match any rules."
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -g guest \
+ admin /bin/ls <<'EOF'
+ALL ALL=(:staff) NOPASSWD: ALL
+admin ALL = ALL
+EOF
+if [ $? -eq 0 ]; then
+ status=1
+fi
+
+echo ""
+echo "This should not match any rules."
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -u root -g users \
+ admin /bin/ls <<'EOF'
+ALL ALL=(:users) NOPASSWD: ALL
+admin ALL = ALL
+EOF
+if [ $? -eq 0 ]; then
+ status=1
+fi
+
+exit $status
diff --git a/plugins/sudoers/regress/testsudoers/test29.out.ok b/plugins/sudoers/regress/testsudoers/test29.out.ok
new file mode 100644
index 0000000..bf145c7
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test29.out.ok
@@ -0,0 +1,133 @@
+listpw = all, 'sudo -l' should require a password
+Parses OK
+
+Entries for user admin:
+
+ALL = NOPASSWD: ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+ALL = /usr/bin/id
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+listpw = all, 'sudo -l' should require a password
+Parses OK
+
+Entries for user admin:
+
+ALL = /usr/bin/id
+ host allowed
+ runas allowed
+ cmnd allowed
+
+ALL = NOPASSWD: ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+listpw = all, 'sudo -l' should not require a password
+Parses OK
+
+Entries for user admin:
+
+ALL = NOPASSWD: ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+ALL = NOPASSWD: /usr/bin/id
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Command allowed
+
+listpw = always, 'sudo -l' should require a password
+Parses OK
+
+Entries for user admin:
+
+ALL = NOPASSWD: ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+listpw = any, 'sudo -l' should require a password
+Parses OK
+
+Entries for user admin:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+ALL = /usr/bin/id
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+listpw = any, 'sudo -l' should not require a password
+Parses OK
+
+Entries for user admin:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+ALL = NOPASSWD: /usr/bin/id
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Command allowed
+
+listpw = any, 'sudo -l' should not require a password
+Parses OK
+
+Entries for user admin:
+
+ALL = NOPASSWD: /usr/bin/id
+ host allowed
+ runas allowed
+ cmnd allowed
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Command allowed
+
+listpw = never, 'sudo -l' should not require a password
+Parses OK
+
+Entries for user admin:
+
+ALL = PASSWD: /usr/bin/id
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test29.sh b/plugins/sudoers/regress/testsudoers/test29.sh
new file mode 100755
index 0000000..802b812
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test29.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# Exercise listpw Defaults settings.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+
+status=0
+
+echo "listpw = all, 'sudo -l' should require a password"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -l admin <<'EOF'
+Defaults listpw = all
+admin ALL = NOPASSWD: ALL
+admin ALL = /usr/bin/id
+EOF
+
+echo ""
+echo "listpw = all, 'sudo -l' should require a password"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -l admin <<'EOF'
+Defaults listpw = all
+admin ALL = /usr/bin/id
+admin ALL = NOPASSWD: ALL
+EOF
+
+echo ""
+echo "listpw = all, 'sudo -l' should not require a password"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -l admin <<'EOF'
+Defaults listpw = all
+admin ALL = NOPASSWD: ALL
+admin ALL = NOPASSWD: /usr/bin/id
+EOF
+
+echo ""
+echo "listpw = always, 'sudo -l' should require a password"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -l admin <<'EOF'
+Defaults listpw = always
+admin ALL = NOPASSWD: ALL
+EOF
+
+echo ""
+echo "listpw = any, 'sudo -l' should require a password"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -l admin <<'EOF'
+Defaults listpw = any
+admin ALL = ALL
+admin ALL = /usr/bin/id
+EOF
+
+echo ""
+echo "listpw = any, 'sudo -l' should not require a password"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -l admin <<'EOF'
+Defaults listpw = any
+admin ALL = ALL
+admin ALL = NOPASSWD: /usr/bin/id
+EOF
+
+echo ""
+echo "listpw = any, 'sudo -l' should not require a password"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -l admin <<'EOF'
+Defaults listpw = any
+admin ALL = NOPASSWD: /usr/bin/id
+admin ALL = ALL
+EOF
+
+echo ""
+echo "listpw = never, 'sudo -l' should not require a password"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -l admin <<'EOF'
+Defaults listpw = never
+admin ALL = PASSWD: /usr/bin/id
+EOF
diff --git a/plugins/sudoers/regress/testsudoers/test3.out.ok b/plugins/sudoers/regress/testsudoers/test3.out.ok
new file mode 100644
index 0000000..fc61e3d
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test3.out.ok
@@ -0,0 +1,59 @@
+Testing @includedir of an unquoted path
+
+Parses OK
+
+Entries for user root:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+Testing @includedir of a double-quoted path
+
+Parses OK
+
+Entries for user root:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+Testing #includedir of an unquoted path
+
+Parses OK
+
+Entries for user root:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+Testing #includedir of a double-quoted path
+
+Parses OK
+
+Entries for user root:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test3.sh b/plugins/sudoers/regress/testsudoers/test3.sh
new file mode 100755
index 0000000..d166de9
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test3.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+#
+# Test @includedir facility
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+TESTDIR="`pwd`/regress/testsudoers"
+# make sure include file is owned by current user
+rm -rf "$TESTDIR/test3.d"
+mkdir "$TESTDIR/test3.d"
+cat >"$TESTDIR/test3.d/root" <<-EOF
+ root ALL = ALL
+EOF
+
+MYUID=`\ls -lnd $TESTDIR/test3.d | awk '{print $3}'`
+MYGID=`\ls -lnd $TESTDIR/test3.d | awk '{print $4}'`
+exec 2>&1
+
+echo "Testing @includedir of an unquoted path"
+echo ""
+$TESTSUDOERS -U $MYUID -G $MYGID root id <<-EOF
+ @includedir $TESTDIR/test3.d
+EOF
+
+echo ""
+echo "Testing @includedir of a double-quoted path"
+echo ""
+$TESTSUDOERS -U $MYUID -G $MYGID root id <<-EOF
+ @includedir "$TESTDIR/test3.d"
+EOF
+
+echo ""
+echo "Testing #includedir of an unquoted path"
+echo ""
+$TESTSUDOERS -U $MYUID -G $MYGID root id <<-EOF
+ #includedir $TESTDIR/test3.d
+EOF
+
+echo ""
+echo "Testing #includedir of a double-quoted path"
+echo ""
+$TESTSUDOERS -U $MYUID -G $MYGID root id <<-EOF
+ #includedir "$TESTDIR/test3.d"
+EOF
+
+rm -rf "$TESTDIR/test3.d"
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test30.out.ok b/plugins/sudoers/regress/testsudoers/test30.out.ok
new file mode 100644
index 0000000..5763072
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test30.out.ok
@@ -0,0 +1,133 @@
+verifypw = all, 'sudo -v' should require a password
+Parses OK
+
+Entries for user admin:
+
+ALL = NOPASSWD: ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+ALL = /usr/bin/id
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+verifypw = all, 'sudo -v' should require a password
+Parses OK
+
+Entries for user admin:
+
+ALL = /usr/bin/id
+ host allowed
+ runas allowed
+ cmnd allowed
+
+ALL = NOPASSWD: ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+verifypw = all, 'sudo -v' should not require a password
+Parses OK
+
+Entries for user admin:
+
+ALL = NOPASSWD: ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+ALL = NOPASSWD: /usr/bin/id
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Command allowed
+
+verifypw = always, 'sudo -v' should require a password
+Parses OK
+
+Entries for user admin:
+
+ALL = NOPASSWD: ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+verifypw = any, 'sudo -v' should require a password
+Parses OK
+
+Entries for user admin:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+ALL = /usr/bin/id
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+verifypw = any, 'sudo -v' should not require a password
+Parses OK
+
+Entries for user admin:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+ALL = NOPASSWD: /usr/bin/id
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Command allowed
+
+verifypw = any, 'sudo -v' should not require a password
+Parses OK
+
+Entries for user admin:
+
+ALL = NOPASSWD: /usr/bin/id
+ host allowed
+ runas allowed
+ cmnd allowed
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Command allowed
+
+verifypw = never, 'sudo -v' should not require a password
+Parses OK
+
+Entries for user admin:
+
+ALL = PASSWD: /usr/bin/id
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test30.sh b/plugins/sudoers/regress/testsudoers/test30.sh
new file mode 100755
index 0000000..57b30ae
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test30.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# Exercise verifypw Defaults settings.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+
+status=0
+
+echo "verifypw = all, 'sudo -v' should require a password"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -v admin <<'EOF'
+Defaults verifypw = all
+admin ALL = NOPASSWD: ALL
+admin ALL = /usr/bin/id
+EOF
+
+echo ""
+echo "verifypw = all, 'sudo -v' should require a password"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -v admin <<'EOF'
+Defaults verifypw = all
+admin ALL = /usr/bin/id
+admin ALL = NOPASSWD: ALL
+EOF
+
+echo ""
+echo "verifypw = all, 'sudo -v' should not require a password"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -v admin <<'EOF'
+Defaults verifypw = all
+admin ALL = NOPASSWD: ALL
+admin ALL = NOPASSWD: /usr/bin/id
+EOF
+
+echo ""
+echo "verifypw = always, 'sudo -v' should require a password"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -v admin <<'EOF'
+Defaults verifypw = always
+admin ALL = NOPASSWD: ALL
+EOF
+
+echo ""
+echo "verifypw = any, 'sudo -v' should require a password"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -v admin <<'EOF'
+Defaults verifypw = any
+admin ALL = ALL
+admin ALL = /usr/bin/id
+EOF
+
+echo ""
+echo "verifypw = any, 'sudo -v' should not require a password"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -v admin <<'EOF'
+Defaults verifypw = any
+admin ALL = ALL
+admin ALL = NOPASSWD: /usr/bin/id
+EOF
+
+echo ""
+echo "verifypw = any, 'sudo -v' should not require a password"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -v admin <<'EOF'
+Defaults verifypw = any
+admin ALL = NOPASSWD: /usr/bin/id
+admin ALL = ALL
+EOF
+
+echo ""
+echo "verifypw = never, 'sudo -v' should not require a password"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -v admin <<'EOF'
+Defaults verifypw = never
+admin ALL = PASSWD: /usr/bin/id
+EOF
diff --git a/plugins/sudoers/regress/testsudoers/test31.out.ok b/plugins/sudoers/regress/testsudoers/test31.out.ok
new file mode 100644
index 0000000..04b2347
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test31.out.ok
@@ -0,0 +1,131 @@
+'sudo -U root -l' with no matching rules
+Parses OK
+
+Entries for user admin:
+
+Password required
+
+Command denied
+
+'sudo -U root -l' with a matching ALL=ALL rule
+Parses OK
+
+Entries for user admin:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+'sudo -U root -l' with a matching list rule
+Parses OK
+
+Entries for user admin:
+
+ALL = NOPASSWD: list
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Command allowed
+
+'sudo -U root -l' without a matching list rule
+Parses OK
+
+Entries for user admin:
+
+ALL = (operator) list
+ host allowed
+ runas unmatched
+
+Password required
+
+Command denied
+
+'sudo -U root -l' with a negated list rule
+Parses OK
+
+Entries for user admin:
+
+ALL = !list
+ host allowed
+ runas allowed
+ cmnd denied
+
+Password required
+
+Command denied
+
+'sudo -U root -l' with a list rule that is later negated
+Parses OK
+
+Entries for user admin:
+
+ALL = NOPASSWD: list, !list
+ host allowed
+ runas allowed
+ cmnd allowed
+ runas allowed
+ cmnd denied
+
+Command denied
+
+'sudo -l command' with a matching command
+Parses OK
+
+Entries for user admin:
+
+ALL = /bin/ls
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+'sudo -l command' without a matching command
+Parses OK
+
+Entries for user admin:
+
+ALL = /bin/ls
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+'sudo -U root -l command' without list privileges
+Parses OK
+
+Entries for user admin:
+
+ALL = /usr/bin/id
+ host allowed
+ runas allowed
+ cmnd unmatched
+
+Password required
+
+Command denied
+
+'sudo -U root -l command' with list privileges
+Parses OK
+
+Entries for user admin:
+
+ALL = list
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test31.sh b/plugins/sudoers/regress/testsudoers/test31.sh
new file mode 100755
index 0000000..a40906d
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test31.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# Exercise "sudo -U user -l [command]"
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+
+status=0
+
+echo "'sudo -U root -l' with no matching rules"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -L root admin <<'EOF'
+root ALL = ALL
+EOF
+
+echo ""
+echo "'sudo -U root -l' with a matching ALL=ALL rule"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -L root admin <<'EOF'
+admin ALL = ALL
+EOF
+
+echo ""
+echo "'sudo -U root -l' with a matching list rule"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -L root admin <<'EOF'
+admin ALL = NOPASSWD: list
+EOF
+
+echo ""
+echo "'sudo -U root -l' without a matching list rule"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -L root admin <<'EOF'
+admin ALL = (operator) list
+EOF
+
+echo ""
+echo "'sudo -U root -l' with a negated list rule"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -L root admin <<'EOF'
+admin ALL = !list
+EOF
+
+echo ""
+echo "'sudo -U root -l' with a list rule that is later negated"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -L root admin <<'EOF'
+admin ALL = NOPASSWD: list, !list
+EOF
+
+echo ""
+echo "'sudo -l command' with a matching command"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -l admin /bin/ls <<'EOF'
+admin ALL = /bin/ls
+EOF
+
+echo ""
+echo "'sudo -l command' without a matching command"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -l admin /usr/bin/id <<'EOF'
+admin ALL = /bin/ls
+EOF
+
+echo ""
+echo "'sudo -U root -l command' without list privileges"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -L root admin /bin/ls <<'EOF'
+root ALL = ALL
+admin ALL = /usr/bin/id
+EOF
+
+echo ""
+echo "'sudo -U root -l command' with list privileges"
+$TESTSUDOERS -p ${TESTDIR}/passwd -P ${TESTDIR}/group -L root admin /bin/ls <<'EOF'
+root ALL = ALL
+admin ALL = list
+EOF
diff --git a/plugins/sudoers/regress/testsudoers/test4.out.ok b/plugins/sudoers/regress/testsudoers/test4.out.ok
new file mode 100644
index 0000000..4987d8b
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test4.out.ok
@@ -0,0 +1,7 @@
+testsudoers: test2.inc should be owned by uid 1
+
+Entries for user root:
+
+Password required
+
+Parse error
diff --git a/plugins/sudoers/regress/testsudoers/test4.sh b/plugins/sudoers/regress/testsudoers/test4.sh
new file mode 100755
index 0000000..4d496c7
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test4.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+# Test sudoers owner check
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+$TESTSUDOERS -U 1 root id <<EOF
+@include $TESTDIR/test2.inc
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test5.out.ok b/plugins/sudoers/regress/testsudoers/test5.out.ok
new file mode 100644
index 0000000..3bd1747
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test5.out.ok
@@ -0,0 +1,14 @@
+testsudoers: test5.inc is world writable
+
+Entries for user root:
+
+Password required
+
+Parse error
+testsudoers: test5.inc should be owned by gid 4294967294
+
+Entries for user root:
+
+Password required
+
+Parse error
diff --git a/plugins/sudoers/regress/testsudoers/test5.sh b/plugins/sudoers/regress/testsudoers/test5.sh
new file mode 100755
index 0000000..317ad98
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test5.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+# Test sudoers file mode check
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+# Create test file
+TESTFILE="`pwd`/regress/testsudoers/test5.inc"
+cat >"$TESTFILE" <<EOF
+root ALL = ALL
+EOF
+
+MYUID=`\ls -ln $TESTFILE | awk '{print $3}'`
+MYGID=`\ls -ln $TESTFILE | awk '{print $4}'`
+exec 2>&1
+
+# Test world writable
+chmod 666 $TESTFILE
+$TESTSUDOERS -U $MYUID -G $MYGID root id <<EOF
+@include $TESTFILE
+EOF
+
+# Test group writable
+chmod 664 $TESTFILE
+$TESTSUDOERS -U $MYUID -G -2 root id <<EOF
+@include $TESTFILE
+EOF
+
+rm -f $TESTFILE
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test6.out.ok b/plugins/sudoers/regress/testsudoers/test6.out.ok
new file mode 100644
index 0000000..71eb49c
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test6.out.ok
@@ -0,0 +1,12 @@
+Parses OK
+
+Entries for user root:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test6.sh b/plugins/sudoers/regress/testsudoers/test6.sh
new file mode 100755
index 0000000..f3b54f8
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test6.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+# Verify sudoers matching by uid.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+$TESTSUDOERS root id <<EOF
+#0 ALL = ALL
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test7.out.ok b/plugins/sudoers/regress/testsudoers/test7.out.ok
new file mode 100644
index 0000000..71eb49c
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test7.out.ok
@@ -0,0 +1,12 @@
+Parses OK
+
+Entries for user root:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test7.sh b/plugins/sudoers/regress/testsudoers/test7.sh
new file mode 100755
index 0000000..9e28c1a
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test7.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+# Verify sudoers matching by gid.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+exec 2>&1
+$TESTSUDOERS root id <<EOF
+%#0 ALL = ALL
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test8.out.ok b/plugins/sudoers/regress/testsudoers/test8.out.ok
new file mode 100644
index 0000000..51fa7cf
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test8.out.ok
@@ -0,0 +1,29 @@
+Testing @include without a newline
+
+Parses OK
+
+Entries for user root:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
+
+Testing #include without a newline
+
+Parses OK
+
+Entries for user root:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test8.sh b/plugins/sudoers/regress/testsudoers/test8.sh
new file mode 100755
index 0000000..c22b590
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test8.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Test @include facility w/o a final newline.
+# Same as test2.sh but missing the final newline.
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+MYUID=`\ls -ln $TESTDIR/test2.inc | awk '{print $3}'`
+MYGID=`\ls -ln $TESTDIR/test2.inc | awk '{print $4}'`
+exec 2>&1
+
+echo "Testing @include without a newline"
+echo ""
+printf "@include $TESTDIR/test2.inc" | \
+ $TESTSUDOERS -U $MYUID -G $MYGID root id
+
+echo ""
+echo "Testing #include without a newline"
+echo ""
+printf "#include $TESTDIR/test2.inc" | \
+ $TESTSUDOERS -U $MYUID -G $MYGID root id
+
+exit 0
diff --git a/plugins/sudoers/regress/testsudoers/test9.out.ok b/plugins/sudoers/regress/testsudoers/test9.out.ok
new file mode 100644
index 0000000..71eb49c
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test9.out.ok
@@ -0,0 +1,12 @@
+Parses OK
+
+Entries for user root:
+
+ALL = ALL
+ host allowed
+ runas allowed
+ cmnd allowed
+
+Password required
+
+Command allowed
diff --git a/plugins/sudoers/regress/testsudoers/test9.sh b/plugins/sudoers/regress/testsudoers/test9.sh
new file mode 100755
index 0000000..850bbac
--- /dev/null
+++ b/plugins/sudoers/regress/testsudoers/test9.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Test #include facility
+#
+
+: ${TESTSUDOERS=testsudoers}
+
+MYUID=`\ls -ln $TESTDIR/test2.inc | awk '{print $3}'`
+MYGID=`\ls -ln $TESTDIR/test2.inc | awk '{print $4}'`
+exec 2>&1
+$TESTSUDOERS -U $MYUID -G $MYGID root id <<EOF
+#include $TESTDIR/test2.inc
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/unescape/check_unesc.c b/plugins/sudoers/regress/unescape/check_unesc.c
new file mode 100644
index 0000000..87497c8
--- /dev/null
+++ b/plugins/sudoers/regress/unescape/check_unesc.c
@@ -0,0 +1,203 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define SUDO_ERROR_WRAP 0
+
+#include <sudoers.h>
+
+struct test_data {
+ const char *input;
+ const char *result;
+ size_t result_len;
+ size_t bufsize;
+};
+
+/* strlcpy_unescape() does not unescape whitespace */
+static struct test_data strlcpy_unescape_test_data[] = {
+ { "\\\0ABC", "\\", 1, 2 }, /* 1 */
+ { "\\ \\;", "\\ ;", 3, 4 }, /* 2 */
+ { "\\\t\\;", "\\\t;", 3, 4 }, /* 3 */
+ { "\\foo", "foo", 3, 4 }, /* 4 */
+ { "foo\\ bar", "foo\\ bar", 8, 9 }, /* 5 */
+ { "foo bar", "f", 7, 2 }, /* 6 */
+ { "foo bar", "", 7, 1 }, /* 7 */
+ { "foo bar", NULL, 7, 0 }, /* 8 */
+ { NULL }
+};
+
+/* unescape_string() _does_ unescape whitespace */
+static struct test_data unescape_string_test_data[] = {
+ { "foo\\ bar", "foo bar", 7, 8 }, /* 1 */
+ { "foo\\,bar", "foo,bar", 7, 8 }, /* 2 */
+ { "baz \\", "baz \\", 5, 5 }, /* 3 */
+ { "\\foo", "foo", 3, 4 }, /* 4 */
+ { "var=aaa,b\\,b", "var=aaa,b,b", 11, 12 }, /* 5 */
+ { "\\a\\ b\\ c\\\\", "a b c\\", 6, 10 }, /* 6 */
+ { "\\", "\\", 1, 1 }, /* 7 */
+ { "foo", "foo", 3, 3 }, /* 8 */
+ { "", "", 0, 0 }, /* 9 */
+ { NULL }
+};
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+static void
+test_strlcpy_unescape(int *ntests_out, int *errors_out)
+{
+ int ntests = *ntests_out;
+ int errors = *errors_out;
+ struct test_data *td;
+ char buf[1024];
+ size_t len;
+
+ for (td = strlcpy_unescape_test_data; td->input != NULL; td++) {
+ ntests++;
+ memset(buf, 'A', sizeof(buf));
+ len = strlcpy_unescape(buf, td->input, td->bufsize);
+ if (len != td->result_len) {
+ sudo_warnx("%d: \"%s\": bad return %zu, expected %zu",
+ ntests, td->input, len, td->result_len);
+ errors++;
+ }
+ len = td->result ? strlen(td->result) : 0;
+ if ((len != 0 || td->bufsize != 0) && len >= td->bufsize) {
+ sudo_warnx("%d: \"%s\": bad length %zu >= %zu",
+ ntests, td->input, len, td->bufsize);
+ errors++;
+ }
+ if (td->result != NULL && strcmp(td->result, buf) != 0) {
+ sudo_warnx("%d: \"%s\": got \"%s\", expected \"%s\"",
+ ntests, td->input, buf, td->result);
+ errors++;
+ }
+ if (buf[td->bufsize] != 'A') {
+ sudo_warnx("%d: \"%s\": wrote past end of buffer at %zu (0x%x)",
+ ntests, td->input, td->bufsize, buf[td->bufsize]);
+ errors++;
+ }
+ }
+
+ *ntests_out = ntests;
+ *errors_out = errors;
+}
+
+static void
+test_unescape_string(int *ntests_out, int *errors_out)
+{
+ int ntests = *ntests_out;
+ int errors = *errors_out;
+ struct test_data *td;
+ char buf[1024];
+
+ for (td = unescape_string_test_data; td->input != NULL; td++) {
+ ntests++;
+ memset(buf, 'A', sizeof(buf));
+ memcpy(buf, td->input, td->bufsize);
+ buf[td->bufsize] = '\0';
+ unescape_string(buf);
+ if (strcmp(td->result, buf) != 0) {
+ sudo_warnx("%d: \"%s\": got \"%s\", expected \"%s\"",
+ ntests, td->input, buf, td->result);
+ errors++;
+ }
+ }
+
+ *ntests_out = ntests;
+ *errors_out = errors;
+}
+
+static void
+test_strvec_join(char sep, int *ntests_out, int *errors_out)
+{
+ int ntests = *ntests_out;
+ int errors = *errors_out;
+ char buf[64*1024 + 1], expected[64*1024 + 3];
+ char *argv[3], *result;
+
+ /* Test joining an argument vector while unescaping. */
+ /* Simulate: sudoedit -s '\' `perl -e 'print "A" x 65536'` */
+ memset(buf, 'A', sizeof(buf));
+ buf[sizeof(buf) - 1] = '\0';
+ argv[0] = (char *)"\\";
+ argv[1] = buf;
+ argv[2] = NULL;
+
+ memset(expected, 'A', sizeof(expected));
+ expected[0] = '\\';
+ expected[1] = sep;
+ expected[sizeof(expected) - 1] = '\0';
+
+ ntests++;
+ result = strvec_join(argv, sep, strlcpy_unescape);
+ if (result == NULL) {
+ sudo_warnx("%d: failed to join argument vector", ntests);
+ errors++;
+ } else if (strcmp(result, expected) != 0) {
+ sudo_warnx("%d: got \"%s\", expected \"%s\"", ntests,
+ result, expected);
+ errors++;
+ }
+ free(result);
+
+ *ntests_out = ntests;
+ *errors_out = errors;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch, ntests = 0, errors = 0;
+
+ initprogname(argc > 0 ? argv[0] : "check_unesc");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ /* ignored */
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* strlcpy_unescape tests */
+ test_strlcpy_unescape(&ntests, &errors);
+
+ /* unescape_string test */
+ test_unescape_string(&ntests, &errors);
+
+ /* strvec_join test */
+ test_strvec_join(' ', &ntests, &errors);
+ test_strvec_join('\n', &ntests, &errors);
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+
+ exit(errors);
+}
diff --git a/plugins/sudoers/regress/visudo/test1.out.ok b/plugins/sudoers/regress/visudo/test1.out.ok
new file mode 100644
index 0000000..e5c355c
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test1.out.ok
@@ -0,0 +1 @@
+stdin: parsed OK
diff --git a/plugins/sudoers/regress/visudo/test1.sh b/plugins/sudoers/regress/visudo/test1.sh
new file mode 100755
index 0000000..5676eea
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test1.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# Sudo Bug 519:
+# Visudo in strict mode reports "parse error" even if there is no error
+#
+
+: ${VISUDO=visudo}
+
+$VISUDO -csf - <<EOF
+User_Alias FOO = nobody
+FOO ALL=(ALL) NOPASSWD: ALL
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/visudo/test10.out.ok b/plugins/sudoers/regress/visudo/test10.out.ok
new file mode 100644
index 0000000..e5c355c
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test10.out.ok
@@ -0,0 +1 @@
+stdin: parsed OK
diff --git a/plugins/sudoers/regress/visudo/test10.sh b/plugins/sudoers/regress/visudo/test10.sh
new file mode 100755
index 0000000..38b7f3e
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test10.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+# Test parsing of NOTBEFORE/NOTAFTER using local time zone
+#
+
+: ${VISUDO=visudo}
+
+$VISUDO -cf - <<-EOF
+ user1 ALL = NOTBEFORE=20151201235900 /usr/bin/id
+ user2 ALL = NOTBEFORE=20151201235900.2 /usr/bin/id
+ user3 ALL = NOTBEFORE=20151201235900\,2 /usr/bin/id
+ user4 ALL = NOTBEFORE=2015120123 /usr/bin/id
+ EOF
diff --git a/plugins/sudoers/regress/visudo/test2.err.ok b/plugins/sudoers/regress/visudo/test2.err.ok
new file mode 100644
index 0000000..d4b356f
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test2.err.ok
@@ -0,0 +1 @@
+stdin:1:12: cycle in User_Alias "FOO"
diff --git a/plugins/sudoers/regress/visudo/test2.out.ok b/plugins/sudoers/regress/visudo/test2.out.ok
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test2.out.ok
diff --git a/plugins/sudoers/regress/visudo/test2.sh b/plugins/sudoers/regress/visudo/test2.sh
new file mode 100755
index 0000000..8ab2382
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test2.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Test cycle detection
+# Prior to sudo 1.8.6p5 this resulted in a core dump (stack smash)
+# The names of the aliases (or rather their lexical order) is important.
+#
+
+: ${VISUDO=visudo}
+
+$VISUDO -csf - <<EOF
+User_Alias YYY = FOO
+User_Alias XXX = nobody
+User_Alias FOO = XXX, YYY
+FOO ALL = ALL
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/visudo/test3.err.ok b/plugins/sudoers/regress/visudo/test3.err.ok
new file mode 100644
index 0000000..38fe9b8
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test3.err.ok
@@ -0,0 +1,2 @@
+Warning: stdin:1:12: unused User_Alias "A"
+Warning: stdin:2:12: unused User_Alias "B"
diff --git a/plugins/sudoers/regress/visudo/test3.out.ok b/plugins/sudoers/regress/visudo/test3.out.ok
new file mode 100644
index 0000000..e5c355c
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test3.out.ok
@@ -0,0 +1 @@
+stdin: parsed OK
diff --git a/plugins/sudoers/regress/visudo/test3.sh b/plugins/sudoers/regress/visudo/test3.sh
new file mode 100755
index 0000000..d219f56
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test3.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# Sudo Bug 361:
+# Exercises a bug in the redblack tree code.
+#
+
+: ${VISUDO=visudo}
+
+$VISUDO -cf - <<EOF
+User_Alias A=a
+User_Alias B=a
+User_Alias C=a
+User_Alias D=a
+User_Alias E=a
+User_Alias F=a
+User_Alias G=a
+User_Alias H=a
+User_Alias I=a
+User_Alias J=a
+User_Alias K=a
+User_Alias L=a
+User_Alias M=a
+
+C ALL=(ALL) ALL
+E ALL=(ALL) ALL
+J ALL=(ALL) ALL
+D ALL=(ALL) ALL
+L ALL=(ALL) ALL
+H ALL=(ALL) ALL
+F ALL=(ALL) ALL
+G ALL=(ALL) ALL
+M ALL=(ALL) ALL
+K ALL=(ALL) ALL
+I ALL=(ALL) ALL
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/visudo/test4.out.ok b/plugins/sudoers/regress/visudo/test4.out.ok
new file mode 100644
index 0000000..e5c355c
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test4.out.ok
@@ -0,0 +1 @@
+stdin: parsed OK
diff --git a/plugins/sudoers/regress/visudo/test4.sh b/plugins/sudoers/regress/visudo/test4.sh
new file mode 100755
index 0000000..465b91c
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test4.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Test cycle detection and duplicate entries.
+# Prior to sudo 1.8.7 this resulted in a false positive.
+#
+
+: ${VISUDO=visudo}
+
+$VISUDO -csf - <<EOF
+Host_Alias H1 = host1
+Host_Alias H2 = H1, host2
+Host_Alias H3 = H1, H2
+root H3 = ALL
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/visudo/test5.out.ok b/plugins/sudoers/regress/visudo/test5.out.ok
new file mode 100644
index 0000000..e5c355c
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test5.out.ok
@@ -0,0 +1 @@
+stdin: parsed OK
diff --git a/plugins/sudoers/regress/visudo/test5.sh b/plugins/sudoers/regress/visudo/test5.sh
new file mode 100755
index 0000000..c870df9
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test5.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Test comment on the last line with no newline
+#
+
+: ${VISUDO=visudo}
+
+printf "# one comment\n#two comments" | $VISUDO -csf -
+
+exit 0
diff --git a/plugins/sudoers/regress/visudo/test6.out.ok b/plugins/sudoers/regress/visudo/test6.out.ok
new file mode 100644
index 0000000..e5c355c
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test6.out.ok
@@ -0,0 +1 @@
+stdin: parsed OK
diff --git a/plugins/sudoers/regress/visudo/test6.sh b/plugins/sudoers/regress/visudo/test6.sh
new file mode 100755
index 0000000..5f7adee
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test6.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# Verify parsing of Defaults syntax
+#
+
+: ${VISUDO=visudo}
+
+$VISUDO -csf - <<EOF
+Defaults syslog=auth
+Defaults>root !set_logname
+Defaults:FULLTIMERS !lecture
+Defaults:millert !authenticate
+Defaults@SERVERS log_year, logfile=/var/log/sudo.log
+Defaults!PAGERS noexec
+
+Defaults env_keep -= "HOME"
+Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS"
+Defaults env_keep += "MAIL PS1 PS2 QTDIR LANG LC_ADDRESS LC_CTYPE"
+
+User_Alias FULLTIMERS = millert, mikef, dowdy
+
+Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less
+
+Host_Alias SERVERS = primary, mail, www, ns
+EOF
+
+exit 0
diff --git a/plugins/sudoers/regress/visudo/test7.out.ok b/plugins/sudoers/regress/visudo/test7.out.ok
new file mode 100644
index 0000000..e5c355c
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test7.out.ok
@@ -0,0 +1 @@
+stdin: parsed OK
diff --git a/plugins/sudoers/regress/visudo/test7.sh b/plugins/sudoers/regress/visudo/test7.sh
new file mode 100755
index 0000000..b993fe7
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test7.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+# Test sudoers_locale early Defaults
+#
+
+: ${VISUDO=visudo}
+
+LANG=C; export LANG
+LC_NUMERIC=fr_FR.UTF-8; export LC_NUMERIC
+
+# First check that visudo supports non-C locales
+# Note that older versions of sudo did not set the locale
+# until sudoers was read so this check will fail on them.
+$VISUDO -csf - >/dev/null 2>&1 <<-EOF
+ Defaults sudoers_locale = fr_FR.UTF-8
+ Defaults passwd_timeout = "2,5"
+ EOF
+
+# Now make sure we can set passwd_timeout to a floating point value
+# using a non-C locale.
+if [ $? -eq 0 ]; then
+ $VISUDO -csf - <<-EOF
+ Defaults passwd_timeout = "2,5"
+ Defaults sudoers_locale = fr_FR.UTF-8
+ EOF
+else
+ # No support for LC_NUMERIC?
+ echo "stdin: parsed OK"
+fi
+
+exit 0
diff --git a/plugins/sudoers/regress/visudo/test8.err.ok b/plugins/sudoers/regress/visudo/test8.err.ok
new file mode 100644
index 0000000..3e71f62
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test8.err.ok
@@ -0,0 +1 @@
+visudo: stdin:1: value "2.5" is invalid for option "passwd_timeout"
diff --git a/plugins/sudoers/regress/visudo/test8.out.ok b/plugins/sudoers/regress/visudo/test8.out.ok
new file mode 100644
index 0000000..16ebc45
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test8.out.ok
@@ -0,0 +1 @@
+parse error in stdin near line 1
diff --git a/plugins/sudoers/regress/visudo/test8.sh b/plugins/sudoers/regress/visudo/test8.sh
new file mode 100755
index 0000000..85bdd9f
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test8.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# Test sudoers_locale early Defaults
+#
+
+: ${VISUDO=visudo}
+
+LANG=C; export LANG
+LC_NUMERIC=fr_FR.UTF-8; export LC_NUMERIC
+
+# First check that visudo supports non-C locales
+# Note that older versions of sudo did not set the locale
+# until sudoers was read so this check will fail on them.
+$VISUDO -csf - >/dev/null 2>&1 <<-EOF
+ Defaults sudoers_locale = fr_FR.UTF-8
+ Defaults passwd_timeout = "2,5"
+ EOF
+
+# Now make sure we can set passwd_timeout to a floating point value
+# using a non-C locale.
+if [ $? -eq 0 ]; then
+ $VISUDO -csf - <<-EOF
+ Defaults passwd_timeout = "2.5"
+ Defaults sudoers_locale = fr_FR.UTF-8
+ EOF
+else
+ # No support for LC_NUMERIC?
+ echo "parse error in stdin near line 1"
+ echo 'visudo: stdin:1: value "2.5" is invalid for option "passwd_timeout"' 1>&2
+fi
+
+exit 0
diff --git a/plugins/sudoers/regress/visudo/test9.out.ok b/plugins/sudoers/regress/visudo/test9.out.ok
new file mode 100644
index 0000000..e5c355c
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test9.out.ok
@@ -0,0 +1 @@
+stdin: parsed OK
diff --git a/plugins/sudoers/regress/visudo/test9.sh b/plugins/sudoers/regress/visudo/test9.sh
new file mode 100755
index 0000000..175ad6e
--- /dev/null
+++ b/plugins/sudoers/regress/visudo/test9.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# Test IP and network address in host-based Defaults statements
+# Bugzilla #766
+#
+
+: ${VISUDO=visudo}
+
+$VISUDO -cf - <<-EOF
+ Defaults@127.0.0.1 !authenticate
+ Defaults@10.0.0.0/8 !always_set_home
+ EOF
+
+exit 0
diff --git a/plugins/sudoers/resolve_cmnd.c b/plugins/sudoers/resolve_cmnd.c
new file mode 100644
index 0000000..24e34de
--- /dev/null
+++ b/plugins/sudoers/resolve_cmnd.c
@@ -0,0 +1,59 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sudoers.h>
+
+/*
+ * Calls find_path() first with PERM_RUNAS, falling back to PERM_USER.
+ * Returns FOUND if the command was found, NOT_FOUND if it was not found,
+ * NOT_FOUND_DOT if it would have been found but it is in '.' and
+ * def_ignore_dot is set or NOT_FOUND_ERROR if an error occurred.
+ * The caller is responsible for freeing the output file.
+ */
+int
+resolve_cmnd(struct sudoers_context *ctx, const char *infile,
+ char **outfile, const char *path)
+{
+ int ret = NOT_FOUND_ERROR;
+ debug_decl(resolve_cmnd, SUDOERS_DEBUG_UTIL);
+
+ if (!set_perms(ctx, PERM_RUNAS))
+ goto done;
+ ret = find_path(infile, outfile, ctx->user.cmnd_stat, path,
+ def_ignore_dot, NULL);
+ if (!restore_perms())
+ goto done;
+ if (ret == NOT_FOUND) {
+ /* Failed as runas user, try as invoking user. */
+ if (!set_perms(ctx, PERM_USER))
+ goto done;
+ ret = find_path(infile, outfile, ctx->user.cmnd_stat, path,
+ def_ignore_dot, NULL);
+ if (!restore_perms())
+ goto done;
+ }
+done:
+ debug_return_int(ret);
+}
diff --git a/plugins/sudoers/serialize_list.c b/plugins/sudoers/serialize_list.c
new file mode 100644
index 0000000..11d2c28
--- /dev/null
+++ b/plugins/sudoers/serialize_list.c
@@ -0,0 +1,82 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2019, 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudoers.h>
+
+/*
+ * Convert struct list_members to a comma-separated string with
+ * the given variable name. Escapes backslashes and commas.
+ */
+char *
+serialize_list(const char *varname, struct list_members *members)
+{
+ struct list_member *lm, *next;
+ size_t len, result_size;
+ char *cp, *result;
+ debug_decl(serialize_list, SUDOERS_DEBUG_PLUGIN);
+
+ result_size = strlen(varname) + 1;
+ SLIST_FOREACH(lm, members, entries) {
+ for (cp = lm->value; *cp != '\0'; cp++) {
+ result_size++;
+ if (*cp == '\\' || *cp == ',')
+ result_size++;
+ }
+ result_size++;
+ }
+ if ((result = malloc(result_size)) == NULL)
+ goto bad;
+ /* No need to check len for overflow here. */
+ len = strlcpy(result, varname, result_size);
+ result[len++] = '=';
+ SLIST_FOREACH_SAFE(lm, members, entries, next) {
+ for (cp = lm->value; *cp != '\0'; cp++) {
+ bool escape = (*cp == '\\' || *cp == ',');
+ if (len + 1 + escape >= result_size) {
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ goto bad;
+ }
+ if (escape)
+ result[len++] = '\\';
+ result[len++] = *cp;
+ }
+ if (next != NULL) {
+ if (len + 1 >= result_size) {
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ goto bad;
+ }
+ result[len++] = ',';
+ }
+ result[len] = '\0';
+ }
+ debug_return_str(result);
+bad:
+ free(result);
+ debug_return_str(NULL);
+}
diff --git a/plugins/sudoers/set_perms.c b/plugins/sudoers/set_perms.c
new file mode 100644
index 0000000..9f80094
--- /dev/null
+++ b/plugins/sudoers/set_perms.c
@@ -0,0 +1,1643 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1994-1996, 1998-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef _AIX
+# include <sys/id.h>
+#endif
+#include <pwd.h>
+#include <errno.h>
+#include <grp.h>
+
+#include <sudoers.h>
+#include <timestamp.h>
+
+/* No change when passed to setresuid(), etc. */
+#define NO_UID (uid_t)-1
+#define NO_GID (gid_t)-1
+
+/*
+ * Prototypes
+ */
+#if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID)
+static struct gid_list *runas_setgroups(const struct sudoers_context *ctx);
+#endif
+
+/*
+ * We keep track of the current permisstions and use a stack to restore
+ * the old permissions. A depth of 16 is overkill.
+ */
+struct perm_state {
+ uid_t ruid;
+ uid_t euid;
+#if defined(HAVE_SETRESUID) || defined(ID_SAVED)
+ uid_t suid;
+#endif
+ gid_t rgid;
+ gid_t egid;
+#if defined(HAVE_SETRESUID) || defined(ID_SAVED)
+ gid_t sgid;
+#endif
+ struct gid_list *gidlist;
+};
+
+#define PERM_STACK_MAX 16
+static struct perm_state perm_stack[PERM_STACK_MAX];
+static int perm_stack_depth = 0;
+
+#undef ID
+#define ID(x) (state->x == ostate->x ? NO_UID : state->x)
+#undef OID
+#define OID(x) (ostate->x == state->x ? NO_UID : ostate->x)
+
+bool
+rewind_perms(void)
+{
+ debug_decl(rewind_perms, SUDOERS_DEBUG_PERMS);
+
+ if (perm_stack_depth > 0) {
+ while (perm_stack_depth > 1) {
+ if (!restore_perms())
+ debug_return_bool(false);
+ }
+ sudo_gidlist_delref(perm_stack[0].gidlist);
+ }
+
+ debug_return_bool(true);
+}
+
+#if defined(HAVE_SETRESUID)
+
+#define UID_CHANGED (state->ruid != ostate->ruid || state->euid != ostate->euid || state->suid != ostate->suid)
+#define GID_CHANGED (state->rgid != ostate->rgid || state->egid != ostate->egid || state->sgid != ostate->sgid)
+
+/*
+ * Set real and effective and saved uids and gids based on perm.
+ * We always retain a saved uid of 0 unless we are headed for an exec().
+ * We only flip the effective gid since it only changes for PERM_SUDOERS.
+ * The ctx argument may be NULL for PERM_ROOT, PERM_SUDOERS and PERM_TIMESTAMP.
+ * This version of set_perms() works fine with the "stay_setuid" option.
+ */
+bool
+set_perms(const struct sudoers_context *ctx, int perm)
+{
+ struct perm_state *state, *ostate = NULL;
+ char errbuf[1024];
+ const char *errstr = errbuf;
+ debug_decl(set_perms, SUDOERS_DEBUG_PERMS);
+
+ if (perm_stack_depth == PERM_STACK_MAX) {
+ errstr = N_("perm stack overflow");
+ errno = EINVAL;
+ goto bad;
+ }
+
+ if (perm == PERM_INITIAL) {
+ if (perm_stack_depth > 1)
+ rewind_perms();
+ perm_stack_depth = 0;
+ } else {
+ if (perm_stack_depth == 0) {
+ errstr = N_("perm stack underflow");
+ errno = EINVAL;
+ goto bad;
+ }
+ ostate = &perm_stack[perm_stack_depth - 1];
+ }
+ state = &perm_stack[perm_stack_depth];
+
+ switch (perm) {
+ case PERM_INITIAL:
+ /* Stash initial state */
+#ifdef HAVE_GETRESUID
+ if (getresuid(&state->ruid, &state->euid, &state->suid)) {
+ errstr = "PERM_INITIAL: getresuid";
+ goto bad;
+
+ }
+ if (getresgid(&state->rgid, &state->egid, &state->sgid)) {
+ errstr = "PERM_INITIAL: getresgid";
+ goto bad;
+ }
+#else
+ state->ruid = getuid();
+ state->euid = geteuid();
+ state->suid = state->euid; /* in case we are setuid */
+
+ state->rgid = getgid();
+ state->egid = getegid();
+ state->sgid = state->egid; /* in case we are setgid */
+#endif
+ state->gidlist = ctx->user.gid_list;
+ sudo_gidlist_addref(state->gidlist);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
+ "ruid: %d, euid: %d, suid: %d, rgid: %d, egid: %d, sgid: %d",
+ __func__, (int)state->ruid, (int)state->euid, (int)state->suid,
+ (int)state->rgid, (int)state->egid, (int)state->sgid);
+ break;
+
+ case PERM_ROOT:
+ state->ruid = ROOT_UID;
+ state->euid = ROOT_UID;
+ state->suid = ROOT_UID;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
+ (int)state->ruid, (int)state->euid, (int)state->suid);
+ if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_ROOT: setresuid(%d, %d, %d)",
+ (int)ID(ruid), (int)ID(euid), (int)ID(suid));
+ goto bad;
+ }
+ state->rgid = ostate->rgid;
+ state->egid = ROOT_GID;
+ state->sgid = ostate->sgid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
+ (int)state->rgid, (int)state->egid, (int)state->sgid);
+ if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) {
+ errstr = N_("unable to change to root gid");
+ goto bad;
+ }
+ state->gidlist = ostate->gidlist;
+ sudo_gidlist_addref(state->gidlist);
+ break;
+
+ case PERM_USER:
+ state->rgid = ostate->rgid;
+ state->egid = ctx->user.gid;
+ state->sgid = ostate->sgid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: gid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
+ (int)state->rgid, (int)state->egid, (int)state->sgid);
+ if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_USER: setresgid(%d, %d, %d)",
+ (int)ID(rgid), (int)ID(egid), (int)ID(sgid));
+ goto bad;
+ }
+ state->gidlist = ctx->user.gid_list;
+ sudo_gidlist_addref(state->gidlist);
+ if (state->gidlist != ostate->gidlist) {
+ if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
+ errstr = "PERM_USER: setgroups";
+ goto bad;
+ }
+ }
+ state->ruid = ctx->user.uid;
+ state->euid = ctx->user.uid;
+ state->suid = ROOT_UID;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: uid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
+ (int)state->ruid, (int)state->euid, (int)state->suid);
+ if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_USER: setresuid(%d, %d, %d)",
+ (int)ID(ruid), (int)ID(euid), (int)ID(suid));
+ goto bad;
+ }
+ break;
+
+ case PERM_FULL_USER:
+ /* headed for exec() */
+ state->rgid = ctx->user.gid;
+ state->egid = ctx->user.gid;
+ state->sgid = ctx->user.gid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
+ (int)state->rgid, (int)state->egid, (int)state->sgid);
+ if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_FULL_USER: setresgid(%d, %d, %d)",
+ (int)ID(rgid), (int)ID(egid), (int)ID(sgid));
+ goto bad;
+ }
+ state->gidlist = ctx->user.gid_list;
+ sudo_gidlist_addref(state->gidlist);
+ if (state->gidlist != ostate->gidlist) {
+ if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
+ errstr = "PERM_FULL_USER: setgroups";
+ goto bad;
+ }
+ }
+ state->ruid = ctx->user.uid;
+ state->euid = ctx->user.uid;
+ state->suid = ctx->user.uid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
+ (int)state->ruid, (int)state->euid, (int)state->suid);
+ if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_FULL_USER: setresuid(%d, %d, %d)",
+ (int)ID(ruid), (int)ID(euid), (int)ID(suid));
+ goto bad;
+ }
+ break;
+
+ case PERM_RUNAS:
+ state->rgid = ostate->rgid;
+ state->egid = ctx->runas.gr ? ctx->runas.gr->gr_gid : ctx->runas.pw->pw_gid; // -V595
+ state->sgid = ostate->sgid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: gid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
+ (int)state->rgid, (int)state->egid, (int)state->sgid);
+ if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) {
+ errstr = N_("unable to change to runas gid");
+ goto bad;
+ }
+ state->gidlist = runas_setgroups(ctx);
+ if (state->gidlist == NULL) {
+ errstr = N_("unable to set runas group vector");
+ goto bad;
+ }
+ state->ruid = ostate->ruid;
+ state->euid = ctx->runas.pw ? ctx->runas.pw->pw_uid : ctx->user.uid;
+ state->suid = ostate->suid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: uid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
+ (int)state->ruid, (int)state->euid, (int)state->suid);
+ if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
+ errstr = N_("unable to change to runas uid");
+ goto bad;
+ }
+ break;
+
+ case PERM_SUDOERS: {
+ const uid_t sudoers_uid = sudoers_file_uid();
+ const gid_t sudoers_gid = sudoers_file_gid();
+ const mode_t sudoers_mode = sudoers_file_mode();
+
+ state->gidlist = ostate->gidlist;
+ sudo_gidlist_addref(state->gidlist);
+
+ /* assumes euid == ROOT_UID, ruid == user */
+ state->rgid = ostate->rgid;
+ state->egid = sudoers_gid;
+ state->sgid = ostate->sgid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: gid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
+ (int)state->rgid, (int)state->egid, (int)state->sgid);
+ if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) {
+ errstr = N_("unable to change to sudoers gid");
+ goto bad;
+ }
+
+ state->ruid = ROOT_UID;
+ /*
+ * If sudoers_uid == ROOT_UID and sudoers_mode is group readable
+ * we use a non-zero uid in order to avoid NFS lossage.
+ * Using uid 1 is a bit bogus but should work on all OS's.
+ */
+ if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP))
+ state->euid = 1;
+ else
+ state->euid = sudoers_uid;
+ state->suid = ROOT_UID;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: uid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
+ (int)state->ruid, (int)state->euid, (int)state->suid);
+ if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_SUDOERS: setresuid(%d, %d, %d)",
+ (int)ID(ruid), (int)ID(euid), (int)ID(suid));
+ goto bad;
+ }
+ break;
+ }
+
+ case PERM_TIMESTAMP:
+ state->gidlist = ostate->gidlist;
+ sudo_gidlist_addref(state->gidlist);
+ state->rgid = ostate->rgid;
+ state->egid = ostate->egid;
+ state->sgid = ostate->sgid;
+ state->ruid = ROOT_UID;
+ state->euid = timestamp_get_uid();
+ state->suid = ROOT_UID;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_TIMESTAMP: uid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
+ (int)state->ruid, (int)state->euid, (int)state->suid);
+ if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_TIMESTAMP: setresuid(%d, %d, %d)",
+ (int)ID(ruid), (int)ID(euid), (int)ID(suid));
+ goto bad;
+ }
+ break;
+ }
+
+ perm_stack_depth++;
+ debug_return_bool(true);
+bad:
+ if (errno == EAGAIN)
+ sudo_warnx(U_("%s: %s"), U_(errstr), U_("too many processes"));
+ else
+ sudo_warn("%s", U_(errstr));
+ debug_return_bool(false);
+}
+
+bool
+restore_perms(void)
+{
+ struct perm_state *state, *ostate;
+ debug_decl(restore_perms, SUDOERS_DEBUG_PERMS);
+
+ if (perm_stack_depth < 2) {
+ sudo_warnx("%s", U_("perm stack underflow"));
+ debug_return_bool(true);
+ }
+
+ state = &perm_stack[perm_stack_depth - 1];
+ ostate = &perm_stack[perm_stack_depth - 2];
+ perm_stack_depth--;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d, %d, %d] -> [%d, %d, %d]",
+ __func__, (int)state->ruid, (int)state->euid, (int)state->suid,
+ (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d, %d, %d] -> [%d, %d, %d]",
+ __func__, (int)state->rgid, (int)state->egid, (int)state->sgid,
+ (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid);
+
+ /* XXX - more cases here where euid != ruid */
+ if (OID(euid) == ROOT_UID) {
+ if (setresuid(NO_UID, ROOT_UID, NO_UID)) {
+ sudo_warn("setresuid() [%d, %d, %d] -> [%d, %d, %d]",
+ (int)state->ruid, (int)state->euid, (int)state->suid,
+ -1, ROOT_UID, -1);
+ goto bad;
+ }
+ }
+ if (setresgid(OID(rgid), OID(egid), OID(sgid))) {
+ sudo_warn("setresgid() [%d, %d, %d] -> [%d, %d, %d]",
+ (int)state->rgid, (int)state->egid, (int)state->sgid,
+ (int)OID(rgid), (int)OID(egid), (int)OID(sgid));
+ goto bad;
+ }
+ if (state->gidlist != ostate->gidlist) {
+ if (sudo_setgroups(ostate->gidlist->ngids, ostate->gidlist->gids)) {
+ sudo_warn("setgroups()");
+ goto bad;
+ }
+ }
+ if (setresuid(OID(ruid), OID(euid), OID(suid))) {
+ sudo_warn("setresuid() [%d, %d, %d] -> [%d, %d, %d]",
+ (int)state->ruid, (int)state->euid, (int)state->suid,
+ (int)OID(ruid), (int)OID(euid), (int)OID(suid));
+ goto bad;
+ }
+ sudo_gidlist_delref(state->gidlist);
+ debug_return_bool(true);
+
+bad:
+ debug_return_bool(false);
+}
+
+#elif defined(_AIX) && defined(ID_SAVED)
+
+#define UID_CHANGED (state->ruid != ostate->ruid || state->euid != ostate->euid || state->suid != ostate->suid)
+#define GID_CHANGED (state->rgid != ostate->rgid || state->egid != ostate->egid || state->sgid != ostate->sgid)
+
+/*
+ * Set real and effective and saved uids and gids based on perm.
+ * We always retain a saved uid of 0 unless we are headed for an exec().
+ * We only flip the effective gid since it only changes for PERM_SUDOERS.
+ * The ctx argument may be NULL for PERM_ROOT, PERM_SUDOERS and PERM_TIMESTAMP.
+ * This version of set_perms() works fine with the "stay_setuid" option.
+ */
+bool
+set_perms(const struct sudoers_context *ctx, int perm)
+{
+ struct perm_state *state, *ostate = NULL;
+ char errbuf[1024];
+ const char *errstr = errbuf;
+ debug_decl(set_perms, SUDOERS_DEBUG_PERMS);
+
+ if (perm_stack_depth == PERM_STACK_MAX) {
+ errstr = N_("perm stack overflow");
+ errno = EINVAL;
+ goto bad;
+ }
+
+ if (perm == PERM_INITIAL) {
+ if (perm_stack_depth > 1)
+ rewind_perms();
+ perm_stack_depth = 0;
+ } else {
+ if (perm_stack_depth == 0) {
+ errstr = N_("perm stack underflow");
+ errno = EINVAL;
+ goto bad;
+ }
+ ostate = &perm_stack[perm_stack_depth - 1];
+ }
+ state = &perm_stack[perm_stack_depth];
+
+ switch (perm) {
+ case PERM_INITIAL:
+ /* Stash initial state */
+ state->ruid = getuidx(ID_REAL);
+ state->euid = getuidx(ID_EFFECTIVE);
+ state->suid = getuidx(ID_SAVED);
+ state->rgid = getgidx(ID_REAL);
+ state->egid = getgidx(ID_EFFECTIVE);
+ state->sgid = getgidx(ID_SAVED);
+ state->gidlist = ctx->user.gid_list;
+ sudo_gidlist_addref(state->gidlist);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
+ "ruid: %d, euid: %d, suid: %d, rgid: %d, egid: %d, sgid: %d",
+ __func__, (int)state->ruid, (int)state->euid, (int)state->suid,
+ (int)state->rgid, (int)state->egid, (int)state->sgid);
+ break;
+
+ case PERM_ROOT:
+ state->ruid = ROOT_UID;
+ state->euid = ROOT_UID;
+ state->suid = ROOT_UID;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
+ (int)state->ruid, (int)state->euid, (int)state->suid);
+ if (UID_CHANGED && setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_ROOT: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
+ ROOT_UID);
+ goto bad;
+ }
+ state->rgid = ostate->rgid;
+ state->egid = ROOT_GID;
+ state->sgid = ostate->sgid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
+ (int)state->rgid, (int)state->egid, (int)state->sgid);
+ if (GID_CHANGED && setgidx(ID_EFFECTIVE, ROOT_GID)) {
+ errstr = N_("unable to change to root gid");
+ goto bad;
+ }
+ state->gidlist = ostate->gidlist;
+ sudo_gidlist_addref(state->gidlist);
+ break;
+
+ case PERM_USER:
+ state->rgid = ostate->rgid;
+ state->egid = ctx->user.gid;
+ state->sgid = ostate->sgid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: gid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
+ (int)state->rgid, (int)state->egid, (int)state->sgid);
+ if (GID_CHANGED && setgidx(ID_EFFECTIVE, ctx->user.gid)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_USER: setgidx(ID_EFFECTIVE, %d)", (int)ctx->user.gid);
+ goto bad;
+ }
+ state->gidlist = ctx->user.gid_list;
+ sudo_gidlist_addref(state->gidlist);
+ if (state->gidlist != ostate->gidlist) {
+ if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
+ errstr = "PERM_USER: setgroups";
+ goto bad;
+ }
+ }
+ state->ruid = ctx->user.uid;
+ state->euid = ctx->user.uid;
+ state->suid = ROOT_UID;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: uid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
+ (int)state->ruid, (int)state->euid, (int)state->suid);
+ if (ostate->euid != ROOT_UID || ostate->suid != ROOT_UID) {
+ if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_USER: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
+ ROOT_UID);
+ goto bad;
+ }
+ }
+ if (setuidx(ID_EFFECTIVE|ID_REAL, ctx->user.uid)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_USER: setuidx(ID_EFFECTIVE|ID_REAL, %d)", (int)ctx->user.uid);
+ goto bad;
+ }
+ break;
+
+ case PERM_FULL_USER:
+ /* headed for exec() */
+ state->rgid = ctx->user.gid;
+ state->egid = ctx->user.gid;
+ state->sgid = ctx->user.gid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
+ (int)state->rgid, (int)state->egid, (int)state->sgid);
+ if (GID_CHANGED && setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ctx->user.gid)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_FULL_USER: setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
+ (int)ctx->user.gid);
+ goto bad;
+ }
+ state->gidlist = ctx->user.gid_list;
+ sudo_gidlist_addref(state->gidlist);
+ if (state->gidlist != ostate->gidlist) {
+ if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
+ errstr = "PERM_FULL_USER: setgroups";
+ goto bad;
+ }
+ }
+ state->ruid = ctx->user.uid;
+ state->euid = ctx->user.uid;
+ state->suid = ctx->user.uid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
+ (int)state->ruid, (int)state->euid, (int)state->suid);
+ if (UID_CHANGED && setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ctx->user.uid)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_FULL_USER: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
+ (int)ctx->user.uid);
+ goto bad;
+ }
+ break;
+
+ case PERM_RUNAS:
+ state->rgid = ostate->rgid;
+ state->egid = ctx->runas.gr ? ctx->runas.gr->gr_gid : ctx->runas.pw->pw_gid;
+ state->sgid = ostate->sgid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: gid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
+ (int)state->rgid, (int)state->egid, (int)state->sgid);
+ if (GID_CHANGED && setgidx(ID_EFFECTIVE, state->egid)) {
+ errstr = N_("unable to change to runas gid");
+ goto bad;
+ }
+ state->gidlist = runas_setgroups(ctx);
+ if (state->gidlist == NULL) {
+ errstr = N_("unable to set runas group vector");
+ goto bad;
+ }
+ state->ruid = ostate->ruid;
+ state->euid = ctx->runas.pw ? ctx->runas.pw->pw_uid : ctx->user.uid;
+ state->suid = ostate->suid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: uid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
+ (int)state->ruid, (int)state->euid, (int)state->suid);
+ if (UID_CHANGED && setuidx(ID_EFFECTIVE, state->euid)) {
+ errstr = N_("unable to change to runas uid");
+ goto bad;
+ }
+ break;
+
+ case PERM_SUDOERS: {
+ const uid_t sudoers_uid = sudoers_file_uid();
+ const gid_t sudoers_gid = sudoers_file_gid();
+ const mode_t sudoers_mode = sudoers_file_mode();
+
+ state->gidlist = ostate->gidlist;
+ sudo_gidlist_addref(state->gidlist);
+
+ /* assume euid == ROOT_UID, ruid == user */
+ state->rgid = ostate->rgid;
+ state->egid = sudoers_gid;
+ state->sgid = ostate->sgid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: gid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
+ (int)state->rgid, (int)state->egid, (int)state->sgid);
+ if (GID_CHANGED && setgidx(ID_EFFECTIVE, sudoers_gid)) {
+ errstr = N_("unable to change to sudoers gid");
+ goto bad;
+ }
+
+ state->ruid = ROOT_UID;
+ /*
+ * If sudoers_uid == ROOT_UID and sudoers_mode is group readable
+ * we use a non-zero uid in order to avoid NFS lossage.
+ * Using uid 1 is a bit bogus but should work on all OS's.
+ */
+ if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP))
+ state->euid = 1;
+ else
+ state->euid = sudoers_uid;
+ state->suid = ROOT_UID;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: uid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
+ (int)state->ruid, (int)state->euid, (int)state->suid);
+ if (UID_CHANGED) {
+ if (ostate->ruid != ROOT_UID || ostate->suid != ROOT_UID) {
+ if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_SUDOERS: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
+ ROOT_UID);
+ goto bad;
+ }
+ }
+ if (setuidx(ID_EFFECTIVE, state->euid)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_SUDOERS: setuidx(ID_EFFECTIVE, %d)", (int)sudoers_uid);
+ goto bad;
+ }
+ }
+ break;
+ }
+
+ case PERM_TIMESTAMP:
+ state->gidlist = ostate->gidlist;
+ sudo_gidlist_addref(state->gidlist);
+ state->rgid = ostate->rgid;
+ state->egid = ostate->egid;
+ state->sgid = ostate->sgid;
+ state->ruid = ROOT_UID;
+ state->euid = timestamp_get_uid();
+ state->suid = ROOT_UID;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_TIMESTAMP: uid: "
+ "[%d, %d, %d] -> [%d, %d, %d]", __func__,
+ (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
+ (int)state->ruid, (int)state->euid, (int)state->suid);
+ if (UID_CHANGED) {
+ if (ostate->ruid != ROOT_UID || ostate->suid != ROOT_UID) {
+ if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_TIMESTAMP: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
+ ROOT_UID);
+ goto bad;
+ }
+ }
+ if (setuidx(ID_EFFECTIVE, state->euid)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_TIMESTAMP: setuidx(ID_EFFECTIVE, %d)",
+ (int)state->euid);
+ goto bad;
+ }
+ }
+ break;
+ }
+
+ perm_stack_depth++;
+ debug_return_bool(true);
+bad:
+ if (errno == EAGAIN)
+ sudo_warnx(U_("%s: %s"), U_(errstr), U_("too many processes"));
+ else
+ sudo_warn("%s", U_(errstr));
+ debug_return_bool(false);
+}
+
+bool
+restore_perms(void)
+{
+ struct perm_state *state, *ostate;
+ debug_decl(restore_perms, SUDOERS_DEBUG_PERMS);
+
+ if (perm_stack_depth < 2) {
+ sudo_warnx("%s", U_("perm stack underflow"));
+ debug_return_bool(true);
+ }
+
+ state = &perm_stack[perm_stack_depth - 1];
+ ostate = &perm_stack[perm_stack_depth - 2];
+ perm_stack_depth--;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d, %d, %d] -> [%d, %d, %d]",
+ __func__, (int)state->ruid, (int)state->euid, (int)state->suid,
+ (int)ostate->ruid, (int)ostate->euid, (int)ostate->suid);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d, %d, %d] -> [%d, %d, %d]",
+ __func__, (int)state->rgid, (int)state->egid, (int)state->sgid,
+ (int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid);
+
+ if (OID(ruid) != NO_UID || OID(euid) != NO_UID || OID(suid) != NO_UID) {
+ if (OID(euid) == ROOT_UID) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: setuidx(ID_EFFECTIVE, %d)",
+ __func__, ROOT_UID);
+ if (setuidx(ID_EFFECTIVE, ROOT_UID)) {
+ sudo_warn("setuidx(ID_EFFECTIVE) [%d, %d, %d] -> [%d, %d, %d]",
+ (int)state->ruid, (int)state->euid, (int)state->suid,
+ -1, ROOT_UID, -1);
+ goto bad;
+ }
+ }
+ if (OID(ruid) == OID(euid) && OID(euid) == OID(suid)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
+ __func__, (int)OID(ruid));
+ if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, OID(ruid))) {
+ sudo_warn("setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED) [%d, %d, %d] -> [%d, %d, %d]",
+ (int)state->ruid, (int)state->euid, (int)state->suid,
+ (int)OID(ruid), (int)OID(euid), (int)OID(suid));
+ goto bad;
+ }
+ } else if (OID(ruid) == NO_UID && OID(suid) == NO_UID) {
+ /* May have already changed euid to ROOT_UID above. */
+ if (OID(euid) != ROOT_UID) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: setuidx(ID_EFFECTIVE, %d)", __func__, OID(euid));
+ if (setuidx(ID_EFFECTIVE, OID(euid))) {
+ sudo_warn("setuidx(ID_EFFECTIVE) [%d, %d, %d] -> [%d, %d, %d]",
+ (int)state->ruid, (int)state->euid, (int)state->suid,
+ (int)OID(ruid), (int)OID(euid), (int)OID(suid));
+ goto bad;
+ }
+ }
+ } else if (OID(suid) == NO_UID) {
+ /* Cannot set the real uid alone. */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: setuidx(ID_REAL|ID_EFFECTIVE, %d)", __func__, OID(ruid));
+ if (setuidx(ID_REAL|ID_EFFECTIVE, OID(ruid))) {
+ sudo_warn("setuidx(ID_REAL|ID_EFFECTIVE) [%d, %d, %d] -> [%d, %d, %d]",
+ (int)state->ruid, (int)state->euid, (int)state->suid,
+ (int)OID(ruid), (int)OID(euid), (int)OID(suid));
+ goto bad;
+ }
+ /* Restore the effective euid if it doesn't match the ruid. */
+ if (OID(euid) != OID(ruid)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: setuidx(ID_EFFECTIVE, %d)", __func__, ostate->euid);
+ if (setuidx(ID_EFFECTIVE, ostate->euid)) {
+ sudo_warn("setuidx(ID_EFFECTIVE, %d)", (int)ostate->euid);
+ goto bad;
+ }
+ }
+ }
+ }
+ if (OID(rgid) != NO_GID || OID(egid) != NO_GID || OID(sgid) != NO_GID) {
+ if (OID(rgid) == OID(egid) && OID(egid) == OID(sgid)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
+ __func__, (int)OID(rgid));
+ if (setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, OID(rgid))) {
+ sudo_warn("setgidx(ID_EFFECTIVE|ID_REAL|ID_SAVED) [%d, %d, %d] -> [%d, %d, %d]",
+ (int)state->rgid, (int)state->egid, (int)state->sgid,
+ (int)OID(rgid), (int)OID(egid), (int)OID(sgid));
+ goto bad;
+ }
+ } else if (OID(rgid) == NO_GID && OID(sgid) == NO_GID) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: setgidx(ID_EFFECTIVE, %d)",
+ __func__, (int)OID(egid));
+ if (setgidx(ID_EFFECTIVE, OID(egid))) {
+ sudo_warn("setgidx(ID_EFFECTIVE) [%d, %d, %d] -> [%d, %d, %d]",
+ (int)state->rgid, (int)state->egid, (int)state->sgid,
+ (int)OID(rgid), (int)OID(egid), (int)OID(sgid));
+ goto bad;
+ }
+ } else if (OID(sgid) == NO_GID) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: setgidx(ID_EFFECTIVE|ID_REAL, %d)", __func__, OID(rgid));
+ if (setgidx(ID_REAL|ID_EFFECTIVE, OID(rgid))) {
+ sudo_warn("setgidx(ID_REAL|ID_EFFECTIVE) [%d, %d, %d] -> [%d, %d, %d]",
+ (int)state->rgid, (int)state->egid, (int)state->sgid,
+ (int)OID(rgid), (int)OID(egid), (int)OID(sgid));
+ goto bad;
+ }
+ }
+ }
+ if (state->gidlist != ostate->gidlist) {
+ if (sudo_setgroups(ostate->gidlist->ngids, ostate->gidlist->gids)) {
+ sudo_warn("setgroups()");
+ goto bad;
+ }
+ }
+ sudo_gidlist_delref(state->gidlist);
+ debug_return_bool(true);
+
+bad:
+ debug_return_bool(false);
+}
+
+#elif defined(HAVE_SETREUID)
+
+#define UID_CHANGED (state->ruid != ostate->ruid || state->euid != ostate->euid)
+#define GID_CHANGED (state->rgid != ostate->rgid || state->egid != ostate->egid)
+
+/*
+ * Set real and effective and saved uids and gids based on perm.
+ * We always retain a saved uid of 0 unless we are headed for an exec().
+ * We only flip the effective gid since it only changes for PERM_SUDOERS.
+ * The ctx argument may be NULL for PERM_ROOT, PERM_SUDOERS and PERM_TIMESTAMP.
+ * This version of set_perms() works fine with the "stay_setuid" option.
+ */
+bool
+set_perms(const struct sudoers_context *ctx, int perm)
+{
+ struct perm_state *state, *ostate = NULL;
+ char errbuf[1024];
+ const char *errstr = errbuf;
+ debug_decl(set_perms, SUDOERS_DEBUG_PERMS);
+
+ if (perm_stack_depth == PERM_STACK_MAX) {
+ errstr = N_("perm stack overflow");
+ errno = EINVAL;
+ goto bad;
+ }
+
+ if (perm == PERM_INITIAL) {
+ if (perm_stack_depth > 1)
+ rewind_perms();
+ perm_stack_depth = 0;
+ } else {
+ if (perm_stack_depth == 0) {
+ errstr = N_("perm stack underflow");
+ errno = EINVAL;
+ goto bad;
+ }
+ ostate = &perm_stack[perm_stack_depth - 1];
+ }
+ state = &perm_stack[perm_stack_depth];
+
+ switch (perm) {
+ case PERM_INITIAL:
+ /* Stash initial state */
+ state->ruid = getuid();
+ state->euid = geteuid();
+ state->rgid = getgid();
+ state->egid = getegid();
+ state->gidlist = ctx->user.gid_list;
+ sudo_gidlist_addref(state->gidlist);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
+ "ruid: %d, euid: %d, rgid: %d, egid: %d", __func__,
+ (int)state->ruid, (int)state->euid,
+ (int)state->rgid, (int)state->egid);
+ break;
+
+ case PERM_ROOT:
+ state->ruid = ROOT_UID;
+ state->euid = ROOT_UID;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
+ (int)ostate->euid, (int)state->ruid, (int)state->euid);
+ /*
+ * setreuid(0, 0) may fail on some systems if euid is not already 0.
+ */
+ if (ostate->euid != ROOT_UID) {
+ if (setreuid(NO_UID, ROOT_UID)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_ROOT: setreuid(-1, %d)", ROOT_UID);
+ goto bad;
+ }
+ }
+ if (ostate->ruid != ROOT_UID) {
+ if (setreuid(ROOT_UID, NO_UID)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_ROOT: setreuid(%d, -1)", ROOT_UID);
+ goto bad;
+ }
+ }
+ state->rgid = ostate->rgid;
+ state->egid = ROOT_GID;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
+ (int)ostate->egid, (int)state->rgid, (int)state->egid);
+ if (GID_CHANGED && setregid(ID(rgid), ID(egid))) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_ROOT: setregid(%d, %d)", (int)ID(rgid), (int)ID(egid));
+ goto bad;
+ }
+ state->gidlist = ostate->gidlist;
+ sudo_gidlist_addref(state->gidlist);
+ break;
+
+ case PERM_USER:
+ state->rgid = ostate->rgid;
+ state->egid = ctx->user.gid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: gid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
+ (int)ostate->egid, (int)state->rgid, (int)state->egid);
+ if (GID_CHANGED && setregid(ID(rgid), ID(egid))) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_USER: setregid(%d, %d)", (int)ID(rgid), (int)ID(egid));
+ goto bad;
+ }
+ state->gidlist = ctx->user.gid_list;
+ sudo_gidlist_addref(state->gidlist);
+ if (state->gidlist != ostate->gidlist) {
+ if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
+ errstr = "PERM_USER: setgroups";
+ goto bad;
+ }
+ }
+ state->ruid = ROOT_UID;
+ state->euid = ctx->user.uid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: uid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
+ (int)ostate->euid, (int)state->ruid, (int)state->euid);
+ if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_USER: setreuid(%d, %d)", (int)ID(ruid), (int)ID(euid));
+ goto bad;
+ }
+ break;
+
+ case PERM_FULL_USER:
+ /* headed for exec() */
+ state->rgid = ctx->user.gid;
+ state->egid = ctx->user.gid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
+ (int)ostate->egid, (int)state->rgid, (int)state->egid);
+ if (GID_CHANGED && setregid(ID(rgid), ID(egid))) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_FULL_USER: setregid(%d, %d)",
+ (int)ID(rgid), (int)ID(egid));
+ goto bad;
+ }
+ state->gidlist = ctx->user.gid_list;
+ sudo_gidlist_addref(state->gidlist);
+ if (state->gidlist != ostate->gidlist) {
+ if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
+ errstr = "PERM_FULL_USER: setgroups";
+ goto bad;
+ }
+ }
+ state->ruid = ctx->user.uid;
+ state->euid = ctx->user.uid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
+ (int)ostate->euid, (int)state->ruid, (int)state->euid);
+ if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_FULL_USER: setreuid(%d, %d)",
+ (int)ID(ruid), (int)ID(euid));
+ goto bad;
+ }
+ break;
+
+ case PERM_RUNAS:
+ state->rgid = ostate->rgid;
+ state->egid = ctx->runas.gr ? ctx->runas.gr->gr_gid : ctx->runas.pw->pw_gid; // -V595
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: gid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
+ (int)ostate->egid, (int)state->rgid, (int)state->egid);
+ if (GID_CHANGED && setregid(ID(rgid), ID(egid))) {
+ errstr = N_("unable to change to runas gid");
+ goto bad;
+ }
+ state->gidlist = runas_setgroups(ctx);
+ if (state->gidlist == NULL) {
+ errstr = N_("unable to set runas group vector");
+ goto bad;
+ }
+ state->ruid = ROOT_UID;
+ state->euid = ctx->runas.pw ? ctx->runas.pw->pw_uid : ctx->user.uid; // -V595
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: uid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
+ (int)ostate->euid, (int)state->ruid, (int)state->euid);
+ if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) {
+ errstr = N_("unable to change to runas uid");
+ goto bad;
+ }
+ break;
+
+ case PERM_SUDOERS: {
+ const uid_t sudoers_uid = sudoers_file_uid();
+ const gid_t sudoers_gid = sudoers_file_gid();
+ const mode_t sudoers_mode = sudoers_file_mode();
+
+ state->gidlist = ostate->gidlist;
+ sudo_gidlist_addref(state->gidlist);
+
+ /* assume euid == ROOT_UID, ruid == user */
+ state->rgid = ostate->rgid;
+ state->egid = sudoers_gid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: gid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
+ (int)ostate->egid, (int)state->rgid, (int)state->egid);
+ if (GID_CHANGED && setregid(ID(rgid), ID(egid))) {
+ errstr = N_("unable to change to sudoers gid");
+ goto bad;
+ }
+
+ state->ruid = ROOT_UID;
+ /*
+ * If sudoers_uid == ROOT_UID and sudoers_mode is group readable
+ * we use a non-zero uid in order to avoid NFS lossage.
+ * Using uid 1 is a bit bogus but should work on all OS's.
+ */
+ if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP))
+ state->euid = 1;
+ else
+ state->euid = sudoers_uid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: uid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
+ (int)ostate->euid, (int)state->ruid, (int)state->euid);
+ if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_SUDOERS: setreuid(%d, %d)",
+ (int)ID(ruid), (int)ID(euid));
+ goto bad;
+ }
+ break;
+ }
+
+ case PERM_TIMESTAMP:
+ state->gidlist = ostate->gidlist;
+ sudo_gidlist_addref(state->gidlist);
+ state->rgid = ostate->rgid;
+ state->egid = ostate->egid;
+ state->ruid = ROOT_UID;
+ state->euid = timestamp_get_uid();
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_TIMESTAMP: uid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
+ (int)ostate->euid, (int)state->ruid, (int)state->euid);
+ if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_TIMESTAMP: setreuid(%d, %d)",
+ (int)ID(ruid), (int)ID(euid));
+ goto bad;
+ }
+ break;
+ }
+
+ perm_stack_depth++;
+ debug_return_bool(true);
+bad:
+ if (errno == EAGAIN)
+ sudo_warnx(U_("%s: %s"), U_(errstr), U_("too many processes"));
+ else
+ sudo_warn("%s", U_(errstr));
+ debug_return_bool(false);
+}
+
+bool
+restore_perms(void)
+{
+ struct perm_state *state, *ostate;
+ debug_decl(restore_perms, SUDOERS_DEBUG_PERMS);
+
+ if (perm_stack_depth < 2) {
+ sudo_warnx("%s", U_("perm stack underflow"));
+ debug_return_bool(true);
+ }
+
+ state = &perm_stack[perm_stack_depth - 1];
+ ostate = &perm_stack[perm_stack_depth - 2];
+ perm_stack_depth--;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d, %d] -> [%d, %d]",
+ __func__, (int)state->ruid, (int)state->euid,
+ (int)ostate->ruid, (int)ostate->euid);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d, %d] -> [%d, %d]",
+ __func__, (int)state->rgid, (int)state->egid,
+ (int)ostate->rgid, (int)ostate->egid);
+
+ /*
+ * When changing euid to ROOT_UID, setreuid() may fail even if
+ * the ruid is ROOT_UID so call setuid() first.
+ */
+ if (OID(euid) == ROOT_UID) {
+ /* setuid() may not set the saved ID unless the euid is ROOT_UID */
+ if (ID(euid) != ROOT_UID) {
+ if (setreuid(NO_UID, ROOT_UID) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "setreuid() [%d, %d] -> [-1, %d)", (int)state->ruid,
+ (int)state->euid, ROOT_UID);
+ }
+ }
+ if (setuid(ROOT_UID)) {
+ sudo_warn("setuid() [%d, %d] -> %d)", (int)state->ruid,
+ (int)state->euid, ROOT_UID);
+ goto bad;
+ }
+ }
+ if (setreuid(OID(ruid), OID(euid))) {
+ sudo_warn("setreuid() [%d, %d] -> [%d, %d]", (int)state->ruid,
+ (int)state->euid, (int)OID(ruid), (int)OID(euid));
+ goto bad;
+ }
+ if (setregid(OID(rgid), OID(egid))) {
+ sudo_warn("setregid() [%d, %d] -> [%d, %d]", (int)state->rgid,
+ (int)state->egid, (int)OID(rgid), (int)OID(egid));
+ goto bad;
+ }
+ if (state->gidlist != ostate->gidlist) {
+ if (sudo_setgroups(ostate->gidlist->ngids, ostate->gidlist->gids)) {
+ sudo_warn("setgroups()");
+ goto bad;
+ }
+ }
+ sudo_gidlist_delref(state->gidlist);
+ debug_return_bool(true);
+
+bad:
+ debug_return_bool(false);
+}
+
+#elif defined(HAVE_SETEUID)
+
+#define GID_CHANGED (state->rgid != ostate->rgid || state->egid != ostate->egid)
+
+/*
+ * Set real and effective uids and gids based on perm.
+ * We always retain a real or effective uid of ROOT_UID unless
+ * we are headed for an exec().
+ * The ctx argument may be NULL for PERM_ROOT, PERM_SUDOERS and PERM_TIMESTAMP.
+ * This version of set_perms() works fine with the "stay_setuid" option.
+ */
+bool
+set_perms(const struct sudoers_context *ctx, int perm)
+{
+ struct perm_state *state, *ostate = NULL;
+ char errbuf[1024];
+ const char *errstr = errbuf;
+ debug_decl(set_perms, SUDOERS_DEBUG_PERMS);
+
+ if (perm_stack_depth == PERM_STACK_MAX) {
+ errstr = N_("perm stack overflow");
+ errno = EINVAL;
+ goto bad;
+ }
+
+ if (perm == PERM_INITIAL) {
+ if (perm_stack_depth > 1)
+ rewind_perms();
+ perm_stack_depth = 0;
+ } else {
+ if (perm_stack_depth == 0) {
+ errstr = N_("perm stack underflow");
+ errno = EINVAL;
+ goto bad;
+ }
+ ostate = &perm_stack[perm_stack_depth - 1];
+ }
+ state = &perm_stack[perm_stack_depth];
+
+ /*
+ * Since we only have setuid() and seteuid() and semantics
+ * for these calls differ on various systems, we set
+ * real and effective uids to ROOT_UID initially to be safe.
+ */
+ if (perm != PERM_INITIAL) {
+ if (ostate->euid != ROOT_UID && seteuid(ROOT_UID)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "set_perms: seteuid(%d)", ROOT_UID);
+ goto bad;
+ }
+ if (ostate->ruid != ROOT_UID && setuid(ROOT_UID)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "set_perms: setuid(%d)", ROOT_UID);
+ goto bad;
+ }
+ }
+
+ switch (perm) {
+ case PERM_INITIAL:
+ /* Stash initial state */
+ state->ruid = getuid();
+ state->euid = geteuid();
+ state->rgid = getgid();
+ state->egid = getegid();
+ state->gidlist = ctx->user.gid_list;
+ sudo_gidlist_addref(state->gidlist);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
+ "ruid: %d, euid: %d, rgid: %d, egid: %d", __func__,
+ (int)state->ruid, (int)state->euid,
+ (int)state->rgid, (int)state->egid);
+ break;
+
+ case PERM_ROOT:
+ /* We already set ruid/euid above. */
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
+ (int)ostate->euid, ROOT_UID, ROOT_UID);
+ state->ruid = ROOT_UID;
+ state->euid = ROOT_UID;
+ state->rgid = ostate->rgid;
+ state->egid = ROOT_GID;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
+ (int)ostate->egid, ROOT_GID, ROOT_GID);
+ if (GID_CHANGED && setegid(ROOT_GID)) {
+ errstr = N_("unable to change to root gid");
+ goto bad;
+ }
+ state->gidlist = ostate->gidlist;
+ sudo_gidlist_addref(state->gidlist);
+ break;
+
+ case PERM_USER:
+ state->egid = ctx->user.gid;
+ state->rgid = ostate->rgid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: gid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
+ (int)ostate->egid, (int)state->rgid, (int)state->egid);
+ if (GID_CHANGED && setegid(ctx->user.gid)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_USER: setegid(%d)", (int)ctx->user.gid);
+ goto bad;
+ }
+ state->gidlist = ctx->user.gid_list;
+ sudo_gidlist_addref(state->gidlist);
+ if (state->gidlist != ostate->gidlist) {
+ if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
+ errstr = "PERM_USER: setgroups";
+ goto bad;
+ }
+ }
+ state->ruid = ROOT_UID;
+ state->euid = ctx->user.uid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_USER: uid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
+ (int)ostate->euid, (int)state->ruid, (int)state->euid);
+ if (seteuid(ctx->user.uid)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_USER: seteuid(%d)", (int)ctx->user.uid);
+ goto bad;
+ }
+ break;
+
+ case PERM_FULL_USER:
+ /* headed for exec() */
+ state->rgid = ctx->user.gid;
+ state->egid = ctx->user.gid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
+ (int)ostate->egid, (int)state->rgid, (int)state->egid);
+ if (GID_CHANGED && setgid(ctx->user.gid)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_FULL_USER: setgid(%d)", (int)ctx->user.gid);
+ goto bad;
+ }
+ state->gidlist = ctx->user.gid_list;
+ sudo_gidlist_addref(state->gidlist);
+ if (state->gidlist != ostate->gidlist) {
+ if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
+ errstr = "PERM_FULL_USER: setgroups";
+ goto bad;
+ }
+ }
+ state->ruid = ctx->user.uid;
+ state->euid = ctx->user.uid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
+ (int)ostate->euid, (int)state->ruid, (int)state->euid);
+ if (setuid(ctx->user.uid)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_FULL_USER: setuid(%d)", (int)ctx->user.uid);
+ goto bad;
+ }
+ break;
+
+ case PERM_RUNAS:
+ state->rgid = ostate->rgid;
+ state->egid = ctx->runas.gr ? ctx->runas.gr->gr_gid : ctx->runas.pw->pw_gid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: gid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
+ (int)ostate->egid, (int)state->rgid, (int)state->egid);
+ if (GID_CHANGED && setegid(state->egid)) {
+ errstr = N_("unable to change to runas gid");
+ goto bad;
+ }
+ state->gidlist = runas_setgroups(ctx);
+ if (state->gidlist == NULL) {
+ errstr = N_("unable to set runas group vector");
+ goto bad;
+ }
+ state->ruid = ostate->ruid;
+ state->euid = ctx->runas.pw ? ctx->runas.pw->pw_uid : ctx->user.uid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_RUNAS: uid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
+ (int)ostate->euid, (int)state->ruid, (int)state->euid);
+ if (seteuid(state->euid)) {
+ errstr = N_("unable to change to runas uid");
+ goto bad;
+ }
+ break;
+
+ case PERM_SUDOERS: {
+ const uid_t sudoers_uid = sudoers_file_uid();
+ const gid_t sudoers_gid = sudoers_file_gid();
+ const mode_t sudoers_mode = sudoers_file_mode();
+
+ state->gidlist = ostate->gidlist;
+ sudo_gidlist_addref(state->gidlist);
+
+ /* assume euid == ROOT_UID, ruid == user */
+ state->rgid = ostate->rgid;
+ state->egid = sudoers_gid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: gid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
+ (int)ostate->egid, (int)state->rgid, (int)state->egid);
+ if (GID_CHANGED && setegid(sudoers_gid)) {
+ errstr = N_("unable to change to sudoers gid");
+ goto bad;
+ }
+
+ state->ruid = ROOT_UID;
+ /*
+ * If sudoers_uid == ROOT_UID and sudoers_mode is group readable
+ * we use a non-zero uid in order to avoid NFS lossage.
+ * Using uid 1 is a bit bogus but should work on all OS's.
+ */
+ if (sudoers_uid == ROOT_UID && (sudoers_mode & S_IRGRP))
+ state->euid = 1;
+ else
+ state->euid = sudoers_uid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_SUDOERS: uid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
+ (int)ostate->euid, (int)state->ruid, (int)state->euid);
+ if (seteuid(state->euid)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_SUDOERS: seteuid(%d)", (int)state->euid);
+ goto bad;
+ }
+ break;
+ }
+
+ case PERM_TIMESTAMP:
+ state->gidlist = ostate->gidlist;
+ sudo_gidlist_addref(state->gidlist);
+ state->rgid = ostate->rgid;
+ state->egid = ostate->egid;
+ state->ruid = ROOT_UID;
+ state->euid = timestamp_get_uid();
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_TIMESTAMP: uid: "
+ "[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
+ (int)ostate->euid, (int)state->ruid, (int)state->euid);
+ if (seteuid(state->euid)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_TIMESTAMP: seteuid(%d)", (int)state->euid);
+ goto bad;
+ }
+ break;
+ }
+
+ perm_stack_depth++;
+ debug_return_bool(true);
+bad:
+ if (errno == EAGAIN)
+ sudo_warnx(U_("%s: %s"), U_(errstr), U_("too many processes"));
+ else
+ sudo_warn("%s", U_(errstr));
+ debug_return_bool(false);
+}
+
+bool
+restore_perms(void)
+{
+ struct perm_state *state, *ostate;
+ debug_decl(restore_perms, SUDOERS_DEBUG_PERMS);
+
+ if (perm_stack_depth < 2) {
+ sudo_warnx("%s", U_("perm stack underflow"));
+ debug_return_bool(true);
+ }
+
+ state = &perm_stack[perm_stack_depth - 1];
+ ostate = &perm_stack[perm_stack_depth - 2];
+ perm_stack_depth--;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d, %d] -> [%d, %d]",
+ __func__, (int)state->ruid, (int)state->euid,
+ (int)ostate->ruid, (int)ostate->euid);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d, %d] -> [%d, %d]",
+ __func__, (int)state->rgid, (int)state->egid,
+ (int)ostate->rgid, (int)ostate->egid);
+
+ /*
+ * Since we only have setuid() and seteuid() and semantics
+ * for these calls differ on various systems, we set
+ * real and effective uids to ROOT_UID initially to be safe.
+ */
+ if (seteuid(ROOT_UID)) {
+ sudo_warn("seteuid() [%d] -> [%d]", (int)state->euid, ROOT_UID);
+ goto bad;
+ }
+ if (setuid(ROOT_UID)) {
+ sudo_warn("setuid() [%d, %d] -> [%d, %d]", (int)state->ruid, ROOT_UID,
+ ROOT_UID, ROOT_UID);
+ goto bad;
+ }
+
+ if (OID(egid) != NO_GID && setegid(ostate->egid)) {
+ sudo_warn("setegid(%d)", (int)ostate->egid);
+ goto bad;
+ }
+ if (state->gidlist != ostate->gidlist) {
+ if (sudo_setgroups(ostate->gidlist->ngids, ostate->gidlist->gids)) {
+ sudo_warn("setgroups()");
+ goto bad;
+ }
+ }
+ if (OID(euid) != NO_UID && seteuid(ostate->euid)) {
+ sudo_warn("seteuid(%d)", (int)ostate->euid);
+ goto bad;
+ }
+ sudo_gidlist_delref(state->gidlist);
+ debug_return_bool(true);
+
+bad:
+ debug_return_bool(false);
+}
+
+#else /* !HAVE_SETRESUID && !HAVE_SETREUID && !HAVE_SETEUID */
+
+/*
+ * Set uids and gids based on perm via setuid() and setgid().
+ * The ctx argument may be NULL for PERM_ROOT, PERM_SUDOERS and PERM_TIMESTAMP.
+ * NOTE: does not support the "stay_setuid" or timestampowner options.
+ * Also, sudoers_uid and sudoers_gid are not used.
+ */
+bool
+set_perms(const struct sudoers_context *ctx, int perm)
+{
+ struct perm_state *state, *ostate = NULL;
+ char errbuf[1024];
+ const char *errstr = errbuf;
+ debug_decl(set_perms, SUDOERS_DEBUG_PERMS);
+
+ if (perm_stack_depth == PERM_STACK_MAX) {
+ errstr = N_("perm stack overflow");
+ errno = EINVAL;
+ goto bad;
+ }
+
+ if (perm == PERM_INITIAL) {
+ if (perm_stack_depth > 1)
+ rewind_perms();
+ perm_stack_depth = 0;
+ } else {
+ if (perm_stack_depth == 0) {
+ errstr = N_("perm stack underflow");
+ errno = EINVAL;
+ goto bad;
+ }
+ ostate = &perm_stack[perm_stack_depth - 1];
+ }
+ state = &perm_stack[perm_stack_depth];
+
+ switch (perm) {
+ case PERM_INITIAL:
+ /* Stash initial state */
+ state->ruid = geteuid() == ROOT_UID ? ROOT_UID : getuid();
+ state->rgid = getgid();
+ state->gidlist = ctx->user.gid_list;
+ sudo_gidlist_addref(state->gidlist);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
+ "ruid: %d, rgid: %d", __func__, (int)state->ruid, (int)state->rgid);
+ break;
+
+ case PERM_ROOT:
+ state->ruid = ROOT_UID;
+ state->rgid = ROOT_GID;
+ state->gidlist = ostate->gidlist;
+ sudo_gidlist_addref(state->gidlist);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: "
+ "[%d] -> [%d]", __func__, (int)ostate->ruid, (int)state->ruid);
+ if (setuid(ROOT_UID)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_ROOT: setuid(%d)", ROOT_UID);
+ goto bad;
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: gid: "
+ "[%d] -> [%d]", __func__, (int)ostate->rgid, (int)state->rgid);
+ if (setgid(ROOT_GID)) {
+ errstr = N_("unable to change to root gid");
+ goto bad;
+ }
+ break;
+
+ case PERM_FULL_USER:
+ state->rgid = ctx->user.gid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: "
+ "[%d] -> [%d]", __func__, (int)ostate->rgid, (int)state->rgid);
+ (void) setgid(ctx->user.gid);
+ state->gidlist = ctx->user.gid_list;
+ sudo_gidlist_addref(state->gidlist);
+ if (state->gidlist != ostate->gidlist) {
+ if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
+ errstr = "PERM_FULL_USER: setgroups";
+ goto bad;
+ }
+ }
+ state->ruid = ctx->user.uid;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: uid: "
+ "[%d] -> [%d]", __func__, (int)ostate->ruid, (int)state->ruid);
+ if (setuid(ctx->user.uid)) {
+ (void)snprintf(errbuf, sizeof(errbuf),
+ "PERM_FULL_USER: setuid(%d)", (int)ctx->user.uid);
+ goto bad;
+ }
+ break;
+
+ case PERM_USER:
+ case PERM_SUDOERS:
+ case PERM_RUNAS:
+ case PERM_TIMESTAMP:
+ /* Unsupported since we can't set euid. */
+ state->ruid = ostate->ruid;
+ state->rgid = ostate->rgid;
+ state->gidlist = ostate->gidlist;
+ sudo_gidlist_addref(state->gidlist);
+ break;
+ }
+
+ perm_stack_depth++;
+ debug_return_bool(true);
+bad:
+ if (errno == EAGAIN)
+ sudo_warnx(U_("%s: %s"), U_(errstr), U_("too many processes"));
+ else
+ sudo_warn("%s", U_(errstr));
+ debug_return_bool(false);
+}
+
+bool
+restore_perms(void)
+{
+ struct perm_state *state, *ostate;
+ debug_decl(restore_perms, SUDOERS_DEBUG_PERMS);
+
+ if (perm_stack_depth < 2) {
+ sudo_warnx("%s", U_("perm stack underflow"));
+ debug_return_bool(true);
+ }
+
+ state = &perm_stack[perm_stack_depth - 1];
+ ostate = &perm_stack[perm_stack_depth - 2];
+ perm_stack_depth--;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: uid: [%d] -> [%d]",
+ __func__, (int)state->ruid, (int)ostate->ruid);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: gid: [%d] -> [%d]",
+ __func__, (int)state->rgid, (int)ostate->rgid);
+
+ if (OID(rgid) != NO_GID && setgid(ostate->rgid)) {
+ sudo_warn("setgid(%d)", (int)ostate->rgid);
+ goto bad;
+ }
+ if (state->gidlist != ostate->gidlist) {
+ if (sudo_setgroups(ostate->gidlist->ngids, ostate->gidlist->gids)) {
+ sudo_warn("setgroups()");
+ goto bad;
+ }
+ }
+ sudo_gidlist_delref(state->gidlist);
+ if (OID(ruid) != NO_UID && setuid(ostate->ruid)) {
+ sudo_warn("setuid(%d)", (int)ostate->ruid);
+ goto bad;
+ }
+ debug_return_bool(true);
+
+bad:
+ debug_return_bool(false);
+}
+#endif /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */
+
+#if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID)
+static struct gid_list *
+runas_setgroups(const struct sudoers_context *ctx)
+{
+ struct gid_list *gidlist;
+ debug_decl(runas_setgroups, SUDOERS_DEBUG_PERMS);
+
+ gidlist = runas_getgroups(ctx);
+ if (gidlist != NULL && !def_preserve_groups) {
+ if (sudo_setgroups(gidlist->ngids, gidlist->gids) < 0) {
+ sudo_gidlist_delref(gidlist);
+ gidlist = NULL;
+ }
+ }
+ debug_return_ptr(gidlist);
+}
+#endif /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */
diff --git a/plugins/sudoers/sethost.c b/plugins/sudoers/sethost.c
new file mode 100644
index 0000000..37545a6
--- /dev/null
+++ b/plugins/sudoers/sethost.c
@@ -0,0 +1,91 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2018-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudoers.h>
+
+/*
+ * Set ctx->user.host. ctx->user.shost, ctx->runas.host and ctx->runas.shost
+ * based on the local and remote host names. If host is NULL, the local
+ * host name is used. If remhost is NULL, the same value as host is used.
+ */
+bool
+sudoers_sethost(struct sudoers_context *ctx, const char *host,
+ const char *remhost)
+{
+ char *cp;
+ debug_decl(sudoers_sethost, SUDOERS_DEBUG_UTIL);
+
+ if (ctx->user.shost != ctx->user.host)
+ free(ctx->user.shost);
+ free(ctx->user.host);
+ ctx->user.host = NULL;
+ ctx->user.shost = NULL;
+
+ if (host == NULL) {
+ ctx->user.host = sudo_gethostname();
+ if (ctx->user.host == NULL && errno != ENOMEM)
+ ctx->user.host = strdup("localhost");
+ } else {
+ ctx->user.host = strdup(host);
+ }
+ if (ctx->user.host == NULL)
+ goto oom;
+ if ((cp = strchr(ctx->user.host, '.')) != NULL) {
+ ctx->user.shost = strndup(ctx->user.host,
+ (size_t)(cp - ctx->user.host));
+ if (ctx->user.shost == NULL)
+ goto oom;
+ } else {
+ ctx->user.shost = ctx->user.host;
+ }
+
+ if (ctx->runas.shost != ctx->runas.host)
+ free(ctx->runas.shost);
+ free(ctx->runas.host);
+ ctx->runas.host = NULL;
+ ctx->runas.shost = NULL;
+
+ ctx->runas.host = strdup(remhost ? remhost : ctx->user.host);
+ if (ctx->runas.host == NULL)
+ goto oom;
+ if ((cp = strchr(ctx->runas.host, '.')) != NULL) {
+ ctx->runas.shost = strndup(ctx->runas.host,
+ (size_t)(cp - ctx->runas.host));
+ if (ctx->runas.shost == NULL)
+ goto oom;
+ } else {
+ ctx->runas.shost = ctx->runas.host;
+ }
+
+ debug_return_bool(true);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+}
diff --git a/plugins/sudoers/solaris_audit.c b/plugins/sudoers/solaris_audit.c
new file mode 100644
index 0000000..bfbea7e
--- /dev/null
+++ b/plugins/sudoers/solaris_audit.c
@@ -0,0 +1,141 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2014, Oracle and/or its affiliates.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_SOLARIS_AUDIT
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
+
+#include <bsm/adt.h>
+#include <bsm/adt_event.h>
+
+#include <sudoers.h>
+#include <solaris_audit.h>
+
+static adt_session_data_t *ah; /* audit session handle */
+static adt_event_data_t *event; /* event to be generated */
+static char cwd[PATH_MAX];
+static char cmdpath[PATH_MAX];
+
+static int
+adt_sudo_common(const struct sudoers_context *ctx, char *const argv[])
+{
+ int argc;
+
+ if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) {
+ log_warning(ctx, SLOG_NO_STDERR, "adt_start_session");
+ return -1;
+ }
+ if ((event = adt_alloc_event(ah, ADT_sudo)) == NULL) {
+ log_warning(ctx, SLOG_NO_STDERR, "alloc_event");
+ (void) adt_end_session(ah);
+ return -1;
+ }
+ if ((event->adt_sudo.cwdpath = getcwd(cwd, sizeof(cwd))) == NULL) {
+ log_warning(ctx, SLOG_NO_STDERR,
+ _("unable to get current working directory"));
+ }
+
+ /* get the real executable name */
+ if (ctx->user.cmnd != NULL) {
+ if (strlcpy(cmdpath, ctx->user.cmnd,
+ sizeof(cmdpath)) >= sizeof(cmdpath)) {
+ log_warningx(ctx, SLOG_NO_STDERR,
+ _("truncated audit path ctx->user.cmnd: %s"),
+ ctx->user.cmnd);
+ }
+ } else {
+ if (strlcpy(cmdpath, argv[0],
+ sizeof(cmdpath)) >= sizeof(cmdpath)) {
+ log_warningx(ctx, SLOG_NO_STDERR,
+ _("truncated audit path argv[0]: %s"),
+ argv[0]);
+ }
+ }
+
+ for (argc = 0; argv[argc] != NULL; argc++)
+ continue;
+
+ event->adt_sudo.cmdpath = cmdpath;
+ event->adt_sudo.argc = argc - 1;
+ event->adt_sudo.argv = (char **)&argv[1];
+ event->adt_sudo.envp = env_get();
+
+ return 0;
+}
+
+
+/*
+ * Returns 0 on success or -1 on error.
+ */
+int
+solaris_audit_success(const struct sudoers_context *ctx, char *const argv[])
+{
+ int rc = -1;
+
+ if (adt_sudo_common(ctx, argv) != 0) {
+ return -1;
+ }
+ if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
+ log_warning(ctx, SLOG_NO_STDERR, "adt_put_event(ADT_SUCCESS)");
+ } else {
+ rc = 0;
+ }
+ adt_free_event(event);
+ (void) adt_end_session(ah);
+
+ return rc;
+}
+
+/*
+ * Returns 0 on success or -1 on error.
+ */
+int
+solaris_audit_failure(const struct sudoers_context *ctx, char *const argv[],
+ const char *errmsg)
+{
+ int rc = -1;
+
+ if (adt_sudo_common(ctx, argv) != 0) {
+ return -1;
+ }
+
+ event->adt_sudo.errmsg = (char *)errmsg;
+ if (adt_put_event(event, ADT_FAILURE, ADT_FAIL_VALUE_PROGRAM) != 0) {
+ log_warning(ctx, SLOG_NO_STDERR, "adt_put_event(ADT_FAILURE)");
+ } else {
+ rc = 0;
+ }
+ adt_free_event(event);
+ (void) adt_end_session(ah);
+
+ return rc;
+}
+
+#endif /* HAVE_SOLARIS_AUDIT */
diff --git a/plugins/sudoers/solaris_audit.h b/plugins/sudoers/solaris_audit.h
new file mode 100644
index 0000000..7790b6b
--- /dev/null
+++ b/plugins/sudoers/solaris_audit.h
@@ -0,0 +1,26 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2014, Oracle and/or its affiliates.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_SOLARIS_AUDIT_H
+#define SUDOERS_SOLARIS_AUDIT_H
+
+struct sudoers_context;
+int solaris_audit_success(const struct sudoers_context *ctx, char *const argv[]);
+int solaris_audit_failure(const struct sudoers_context *ctx, char *const argv[], const char *errmsg);
+
+#endif /* SUDOERS_SOLARIS_AUDIT_H */
diff --git a/plugins/sudoers/sssd.c b/plugins/sudoers/sssd.c
new file mode 100644
index 0000000..c0804cb
--- /dev/null
+++ b/plugins/sudoers/sssd.c
@@ -0,0 +1,817 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2003-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ * Copyright (c) 2011 Daniel Kopecek <dkopecek@redhat.com>
+ *
+ * This code is derived from software contributed by Aaron Spangler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_SSSD
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <ctype.h>
+#include <errno.h>
+#include <pwd.h>
+
+#include <sudoers.h>
+#include <sudo_lbuf.h>
+#include <sudo_ldap.h>
+#include <sudo_dso.h>
+
+/* SSSD <--> SUDO interface - do not change */
+struct sss_sudo_attr {
+ char *name;
+ char **values;
+ unsigned int num_values;
+};
+
+struct sss_sudo_rule {
+ unsigned int num_attrs;
+ struct sss_sudo_attr *attrs;
+};
+
+struct sss_sudo_result {
+ unsigned int num_rules;
+ struct sss_sudo_rule *rules;
+};
+
+typedef int (*sss_sudo_send_recv_t)(uid_t, const char*, const char*,
+ uint32_t*, struct sss_sudo_result**);
+
+typedef int (*sss_sudo_send_recv_defaults_t)(uid_t, const char*, uint32_t*,
+ char**, struct sss_sudo_result**);
+
+typedef void (*sss_sudo_free_result_t)(struct sss_sudo_result*);
+
+typedef int (*sss_sudo_get_values_t)(struct sss_sudo_rule*, const char*,
+ char***);
+
+typedef void (*sss_sudo_free_values_t)(char**);
+
+/* sudo_nss handle */
+struct sudo_sss_handle {
+ char *domainname;
+ char *ipa_host;
+ char *ipa_shost;
+ struct passwd *pw;
+ void *ssslib;
+ struct sudoers_parse_tree parse_tree;
+ sss_sudo_send_recv_t fn_send_recv;
+ sss_sudo_send_recv_defaults_t fn_send_recv_defaults;
+ sss_sudo_free_result_t fn_free_result;
+ sss_sudo_get_values_t fn_get_values;
+ sss_sudo_free_values_t fn_free_values;
+};
+
+static int
+get_ipa_hostname(const struct sudoers_context *ctx, char **shostp, char **lhostp)
+{
+ size_t linesize = 0;
+ char *lhost = NULL;
+ char *shost = NULL;
+ char *line = NULL;
+ int ret = false;
+ ssize_t len;
+ FILE *fp;
+ debug_decl(get_ipa_hostname, SUDOERS_DEBUG_SSSD);
+
+ fp = fopen(_PATH_SSSD_CONF, "r");
+ if (fp != NULL) {
+ while ((len = getdelim(&line, &linesize, '\n', fp)) != -1) {
+ char *cp = line;
+
+ /* Trim trailing and leading spaces. */
+ while (len > 0 && isspace((unsigned char)line[len - 1]))
+ line[--len] = '\0';
+ while (isspace((unsigned char)*cp))
+ cp++;
+
+ /*
+ * Match ipa_hostname = foo
+ * Note: currently ignores the domain (XXX)
+ */
+ if (strncmp(cp, "ipa_hostname", 12) == 0) {
+ cp += 12;
+ /* Trim " = " after "ipa_hostname" */
+ while (isblank((unsigned char)*cp))
+ cp++;
+ if (*cp++ != '=')
+ continue;
+ while (isblank((unsigned char)*cp))
+ cp++;
+ /* Ignore empty value */
+ if (*cp == '\0')
+ continue;
+ lhost = strdup(cp);
+ if (lhost != NULL && (cp = strchr(lhost, '.')) != NULL) {
+ shost = strndup(lhost, (size_t)(cp - lhost));
+ } else {
+ shost = lhost;
+ }
+ if (shost != NULL && lhost != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "ipa_hostname %s overrides %s", lhost, ctx->user.host);
+ *shostp = shost;
+ *lhostp = lhost;
+ ret = true;
+ } else {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ free(shost);
+ free(lhost);
+ ret = -1;
+ }
+ break;
+ }
+ }
+ fclose(fp);
+ free(line);
+ }
+ debug_return_int(ret);
+}
+
+/*
+ * SSSD doesn't handle netgroups, we have to ensure they are correctly filtered
+ * in sudo. The rules may contain mixed sudoUser specification so we have to
+ * check not only for netgroup membership but also for user and group matches.
+ * Otherwise, a netgroup non-match could override a user/group match.
+ */
+static bool
+sudo_sss_check_user(struct sudoers_context *ctx, struct sudo_sss_handle *handle,
+ struct sss_sudo_rule *rule)
+{
+ const char *host = handle->ipa_host ? handle->ipa_host : ctx->runas.host;
+ const char *shost = handle->ipa_shost ? handle->ipa_shost : ctx->runas.shost;
+ char **val_array;
+ int i, rc, ret = false;
+ debug_decl(sudo_sss_check_user, SUDOERS_DEBUG_SSSD);
+
+ if (rule == NULL)
+ debug_return_bool(false);
+
+ rc = handle->fn_get_values(rule, "sudoUser", &val_array);
+ switch (rc) {
+ case 0:
+ break;
+ case ENOENT:
+ sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
+ debug_return_bool(false);
+ case ENOMEM:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ FALLTHROUGH;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "handle->fn_get_values(sudoOption): rc=%d", rc);
+ debug_return_bool(false);
+ }
+
+ /* Walk through sudoUser values. */
+ for (i = 0; val_array[i] != NULL && !ret; ++i) {
+ const char *val = val_array[i];
+ bool negated = false;
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "val[%d]=%s", i, val);
+ if (*val == '!') {
+ val++;
+ negated = true;
+ }
+ switch (*val) {
+ case '+':
+ /* Netgroup spec found, check membership. */
+ if (netgr_matches(NULL, val, def_netgroup_tuple ? host : NULL,
+ def_netgroup_tuple ? shost : NULL, handle->pw->pw_name) == ALLOW) {
+ ret = true;
+ }
+ break;
+ case '%':
+ /* User group found, check membership. */
+ if (usergr_matches(val, handle->pw->pw_name, handle->pw) == ALLOW) {
+ ret = true;
+ }
+ break;
+ default:
+ /* Not a netgroup or user group. */
+ if (strcmp(val, "ALL") == 0 ||
+ userpw_matches(val, handle->pw->pw_name, handle->pw) == ALLOW) {
+ ret = true;
+ }
+ break;
+ }
+ sudo_debug_printf(SUDO_DEBUG_DIAG,
+ "sssd/ldap sudoUser '%s%s' ... %s (%s)", negated ? "!" : "",
+ val, ret ? "MATCH!" : "not", handle->pw->pw_name);
+
+ /* A negated match overrides all other entries. */
+ if (ret && negated) {
+ ret = false;
+ break;
+ }
+ }
+ handle->fn_free_values(val_array);
+ debug_return_bool(ret);
+}
+
+static char *
+val_array_iter(void **vp)
+{
+ char **val_array = *vp;
+
+ *vp = val_array + 1;
+
+ return *val_array;
+}
+
+/*
+ * Wrapper for sudo_ldap_role_to_priv() that takes an sss rule..
+ * Returns a struct privilege on success or NULL on failure.
+ */
+static struct privilege *
+sss_rule_to_priv(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule,
+ int *rc_out)
+{
+ char **cmnds = NULL, **runasusers = NULL, **runasgroups = NULL;
+ char **opts = NULL, **notbefore = NULL, **notafter = NULL;
+ char **hosts = NULL, **cn_array = NULL, *cn = NULL;
+ struct privilege *priv = NULL;
+ int rc;
+ debug_decl(sss_rule_to_priv, SUDOERS_DEBUG_SSSD);
+
+ /* Ignore sudoRole without sudoCommand or sudoHost. */
+ rc = handle->fn_get_values(rule, "sudoCommand", &cmnds);
+ if (rc != 0)
+ goto cleanup;
+ rc = handle->fn_get_values(rule, "sudoHost", &hosts);
+ if (rc != 0)
+ goto cleanup;
+
+ /* Get the entry's dn for long format printing. */
+ rc = handle->fn_get_values(rule, "cn", &cn_array);
+ if (rc != 0)
+ goto cleanup;
+ cn = cn_array[0];
+
+ /* Get sudoRunAsUser / sudoRunAs */
+ rc = handle->fn_get_values(rule, "sudoRunAsUser", &runasusers);
+ switch (rc) {
+ case 0:
+ break;
+ case ENOENT:
+ rc = handle->fn_get_values(rule, "sudoRunAs", &runasusers);
+ switch (rc) {
+ case 0:
+ case ENOENT:
+ break;
+ default:
+ goto cleanup;
+ }
+ break;
+ default:
+ goto cleanup;
+ }
+
+ /* Get sudoRunAsGroup */
+ rc = handle->fn_get_values(rule, "sudoRunAsGroup", &runasgroups);
+ switch (rc) {
+ case 0:
+ case ENOENT:
+ break;
+ default:
+ goto cleanup;
+ }
+
+ /* Get sudoNotBefore */
+ rc = handle->fn_get_values(rule, "sudoNotBefore", &notbefore);
+ switch (rc) {
+ case 0:
+ case ENOENT:
+ break;
+ default:
+ goto cleanup;
+ }
+
+ /* Get sudoNotAfter */
+ rc = handle->fn_get_values(rule, "sudoNotAfter", &notafter);
+ switch (rc) {
+ case 0:
+ case ENOENT:
+ break;
+ default:
+ goto cleanup;
+ }
+
+ /* Parse sudoOptions. */
+ rc = handle->fn_get_values(rule, "sudoOption", &opts);
+ switch (rc) {
+ case 0:
+ case ENOENT:
+ break;
+ default:
+ goto cleanup;
+ }
+
+ priv = sudo_ldap_role_to_priv(cn, hosts, runasusers, runasgroups,
+ cmnds, opts, notbefore ? notbefore[0] : NULL,
+ notafter ? notafter[0] : NULL, false, true, val_array_iter);
+ if (priv == NULL) {
+ rc = ENOMEM;
+ goto cleanup;
+ }
+ rc = 0;
+
+cleanup:
+ handle->fn_free_values(cn_array);
+ handle->fn_free_values(cmnds);
+ handle->fn_free_values(hosts);
+ handle->fn_free_values(runasusers);
+ handle->fn_free_values(runasgroups);
+ handle->fn_free_values(opts);
+ handle->fn_free_values(notbefore);
+ handle->fn_free_values(notafter);
+
+ *rc_out = rc;
+
+ debug_return_ptr(priv);
+}
+
+static bool
+sss_to_sudoers(struct sudoers_context *ctx, struct sudo_sss_handle *handle,
+ struct sss_sudo_result *sss_result)
+{
+ struct userspec *us;
+ struct member *m;
+ unsigned int i;
+ debug_decl(sss_to_sudoers, SUDOERS_DEBUG_SSSD);
+
+ /* We only have a single userspec */
+ if ((us = calloc(1, sizeof(*us))) == NULL)
+ goto oom;
+ us->file = sudo_rcstr_dup("SSSD");
+ TAILQ_INIT(&us->users);
+ TAILQ_INIT(&us->privileges);
+ STAILQ_INIT(&us->comments);
+ TAILQ_INSERT_TAIL(&handle->parse_tree.userspecs, us, entries);
+
+ /* We only include rules where the user matches. */
+ if ((m = sudo_ldap_new_member_all()) == NULL)
+ goto oom;
+ TAILQ_INSERT_TAIL(&us->users, m, entries);
+
+ /*
+ * Treat each rule as a separate privilege.
+ *
+ * Sssd has already sorted the rules in descending order.
+ * The conversion to a sudoers parse tree requires that entries be
+ * in *ascending* order so we we iterate from last to first.
+ */
+ for (i = sss_result->num_rules; i; ) {
+ struct sss_sudo_rule *rule = sss_result->rules + --i;
+ struct privilege *priv;
+ int rc;
+
+ /*
+ * We don't know whether a rule was included due to a user/group
+ * match or because it contained a netgroup.
+ */
+ if (!sudo_sss_check_user(ctx, handle, rule))
+ continue;
+
+ if ((priv = sss_rule_to_priv(handle, rule, &rc)) == NULL) {
+ if (rc == ENOMEM)
+ goto oom;
+ continue;
+ }
+ TAILQ_INSERT_TAIL(&us->privileges, priv, entries);
+ }
+
+ debug_return_bool(true);
+
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ free_userspecs(&handle->parse_tree.userspecs);
+ debug_return_bool(false);
+}
+
+static bool
+sudo_sss_parse_options(struct sudo_sss_handle *handle, struct sss_sudo_rule *rule, struct defaults_list *defs)
+{
+ int i, rc;
+ char *source = NULL;
+ bool ret = false;
+ char **val_array = NULL;
+ char **cn_array = NULL;
+ debug_decl(sudo_sss_parse_options, SUDOERS_DEBUG_SSSD);
+
+ if (rule == NULL)
+ debug_return_bool(true);
+
+ rc = handle->fn_get_values(rule, "sudoOption", &val_array);
+ switch (rc) {
+ case 0:
+ break;
+ case ENOENT:
+ sudo_debug_printf(SUDO_DEBUG_INFO, "No result.");
+ debug_return_bool(true);
+ case ENOMEM:
+ goto oom;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "handle->fn_get_values(sudoOption): rc=%d", rc);
+ debug_return_bool(false);
+ }
+
+ /* Use sudoRole in place of file name in defaults. */
+ if (handle->fn_get_values(rule, "cn", &cn_array) == 0) {
+ if (cn_array[0] != NULL) {
+ char *cp;
+ if (asprintf(&cp, "sudoRole %s", cn_array[0]) == -1)
+ goto oom;
+ source = sudo_rcstr_dup(cp);
+ free(cp);
+ if (source == NULL)
+ goto oom;
+ }
+ handle->fn_free_values(cn_array);
+ cn_array = NULL;
+ }
+ if (source == NULL) {
+ if ((source = sudo_rcstr_dup("sudoRole UNKNOWN")) == NULL)
+ goto oom;
+ }
+
+ /* Walk through options, appending to defs. */
+ for (i = 0; val_array[i] != NULL; i++) {
+ char *var, *val;
+ int op;
+
+ op = sudo_ldap_parse_option(val_array[i], &var, &val);
+ if (!append_default(var, val, op, source, defs))
+ goto oom;
+ }
+ ret = true;
+ goto done;
+
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+done:
+ sudo_rcstr_delref(source);
+ handle->fn_free_values(val_array);
+ debug_return_bool(ret);
+}
+
+static struct sss_sudo_result *
+sudo_sss_result_get(const struct sudo_nss *nss, struct passwd *pw)
+{
+ struct sudo_sss_handle *handle = nss->handle;
+ struct sss_sudo_result *sss_result = NULL;
+ uint32_t sss_error = 0;
+ int rc;
+ debug_decl(sudo_sss_result_get, SUDOERS_DEBUG_SSSD);
+
+ sudo_debug_printf(SUDO_DEBUG_DIAG, " username=%s", pw->pw_name);
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "domainname=%s",
+ handle->domainname ? handle->domainname : "NULL");
+
+ rc = handle->fn_send_recv(pw->pw_uid, pw->pw_name,
+ handle->domainname, &sss_error, &sss_result);
+ switch (rc) {
+ case 0:
+ break;
+ case ENOMEM:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ FALLTHROUGH;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "handle->fn_send_recv: rc=%d", rc);
+ debug_return_ptr(NULL);
+ }
+
+ switch (sss_error) {
+ case 0:
+ if (sss_result != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "Received %u rule(s)",
+ sss_result->num_rules);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "Internal error: sss_result == NULL && sss_error == 0");
+ debug_return_ptr(NULL);
+ }
+ break;
+ case ENOENT:
+ sudo_debug_printf(SUDO_DEBUG_INFO, "The user was not found in SSSD.");
+ debug_return_ptr(NULL);
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "sss_error=%u\n", sss_error);
+ debug_return_ptr(NULL);
+ }
+
+ debug_return_ptr(sss_result);
+}
+
+/* sudo_nss implementation */
+static int
+sudo_sss_close(struct sudoers_context *ctx, struct sudo_nss *nss)
+{
+ struct sudo_sss_handle *handle = nss->handle;
+ debug_decl(sudo_sss_close, SUDOERS_DEBUG_SSSD);
+
+ if (handle != NULL) {
+ sudo_dso_unload(handle->ssslib);
+ if (handle->pw != NULL)
+ sudo_pw_delref(handle->pw);
+ free_parse_tree(&handle->parse_tree);
+ free(handle);
+ nss->handle = NULL;
+ }
+ debug_return_int(0);
+}
+
+static int
+sudo_sss_open(struct sudoers_context *ctx, struct sudo_nss *nss)
+{
+ struct sudo_sss_handle *handle;
+ static const char path[] = _PATH_SSSD_LIB"/libsss_sudo.so";
+ debug_decl(sudo_sss_open, SUDOERS_DEBUG_SSSD);
+
+ if (nss->handle != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: called with non-NULL handle %p", __func__, nss->handle);
+ sudo_sss_close(ctx, nss);
+ }
+
+ /* Create a handle container. */
+ handle = calloc(1, sizeof(struct sudo_sss_handle));
+ if (handle == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(ENOMEM);
+ }
+
+ /* Load symbols */
+ handle->ssslib = sudo_dso_load(path, SUDO_DSO_LAZY);
+ if (handle->ssslib == NULL) {
+ const char *errstr = sudo_dso_strerror();
+ sudo_warnx(U_("unable to load %s: %s"), path,
+ errstr ? errstr : "unknown error");
+ sudo_warnx("%s",
+ U_("unable to initialize SSS source. Is SSSD installed on your machine?"));
+ free(handle);
+ debug_return_int(EFAULT);
+ }
+
+ handle->fn_send_recv =
+ sudo_dso_findsym(handle->ssslib, "sss_sudo_send_recv");
+ if (handle->fn_send_recv == NULL) {
+ sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
+ "sss_sudo_send_recv");
+ free(handle);
+ debug_return_int(EFAULT);
+ }
+
+ handle->fn_send_recv_defaults =
+ sudo_dso_findsym(handle->ssslib, "sss_sudo_send_recv_defaults");
+ if (handle->fn_send_recv_defaults == NULL) {
+ sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
+ "sss_sudo_send_recv_defaults");
+ free(handle);
+ debug_return_int(EFAULT);
+ }
+
+ handle->fn_free_result =
+ sudo_dso_findsym(handle->ssslib, "sss_sudo_free_result");
+ if (handle->fn_free_result == NULL) {
+ sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
+ "sss_sudo_free_result");
+ free(handle);
+ debug_return_int(EFAULT);
+ }
+
+ handle->fn_get_values =
+ sudo_dso_findsym(handle->ssslib, "sss_sudo_get_values");
+ if (handle->fn_get_values == NULL) {
+ sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
+ "sss_sudo_get_values");
+ free(handle);
+ debug_return_int(EFAULT);
+ }
+
+ handle->fn_free_values =
+ sudo_dso_findsym(handle->ssslib, "sss_sudo_free_values");
+ if (handle->fn_free_values == NULL) {
+ sudo_warnx(U_("unable to find symbol \"%s\" in %s"), path,
+ "sss_sudo_free_values");
+ free(handle);
+ debug_return_int(EFAULT);
+ }
+
+ /*
+ * If the runas host matches the local host, check for ipa_hostname
+ * in sssd.conf and use it in preference to ctx->runas.host.
+ */
+ if (strcasecmp(ctx->runas.host, ctx->user.host) == 0) {
+ if (get_ipa_hostname(ctx, &handle->ipa_shost, &handle->ipa_host) == -1) {
+ free(handle);
+ debug_return_int(ENOMEM);
+ }
+ }
+
+ /* The "parse tree" contains userspecs, defaults, aliases and hostnames. */
+ init_parse_tree(&handle->parse_tree, handle->ipa_host, handle->ipa_shost,
+ ctx, nss);
+ nss->handle = handle;
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "handle=%p", handle);
+
+ debug_return_int(0);
+}
+
+/*
+ * Perform query for user and host and convert to sudoers parse tree.
+ */
+static int
+sudo_sss_query(struct sudoers_context *ctx, const struct sudo_nss *nss,
+ struct passwd *pw)
+{
+ struct sudo_sss_handle *handle = nss->handle;
+ struct sss_sudo_result *sss_result = NULL;
+ int ret = 0;
+ debug_decl(sudo_sss_query, SUDOERS_DEBUG_SSSD);
+
+ if (handle == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: called with NULL handle", __func__);
+ debug_return_int(-1);
+ }
+
+ /* Use cached result if it matches pw. */
+ if (handle->pw != NULL) {
+ if (pw == handle->pw)
+ goto done;
+ sudo_pw_delref(handle->pw);
+ handle->pw = NULL;
+ }
+
+ /* Free old userspecs, if any. */
+ free_userspecs(&handle->parse_tree.userspecs);
+
+ /* Fetch list of sudoRole entries that match user and host. */
+ sss_result = sudo_sss_result_get(nss, pw);
+
+ sudo_debug_printf(SUDO_DEBUG_DIAG,
+ "searching SSSD/LDAP for sudoers entries for user %s, host %s",
+ pw->pw_name, ctx->runas.host);
+
+ /* Stash a ref to the passwd struct in the handle. */
+ sudo_pw_addref(pw);
+ handle->pw = pw;
+
+ /* Convert to sudoers parse tree if the user was found. */
+ if (sss_result != NULL) {
+ if (!sss_to_sudoers(ctx, handle, sss_result)) {
+ ret = -1;
+ goto done;
+ }
+ }
+
+done:
+ /* Cleanup */
+ handle->fn_free_result(sss_result);
+ if (ret == -1) {
+ free_userspecs(&handle->parse_tree.userspecs);
+ if (handle->pw != NULL) {
+ sudo_pw_delref(handle->pw);
+ handle->pw = NULL;
+ }
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "Done with LDAP searches");
+
+ debug_return_int(ret);
+}
+
+/*
+ * Return the initialized (but empty) sudoers parse tree.
+ * The contents will be populated by the getdefs() and query() functions.
+ */
+static struct sudoers_parse_tree *
+sudo_sss_parse(struct sudoers_context *ctx, const struct sudo_nss *nss)
+{
+ struct sudo_sss_handle *handle = nss->handle;
+ debug_decl(sudo_sss_parse, SUDOERS_DEBUG_SSSD);
+
+ if (handle == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: called with NULL handle", __func__);
+ debug_return_ptr(NULL);
+ }
+
+ debug_return_ptr(&handle->parse_tree);
+}
+
+static int
+sudo_sss_getdefs(struct sudoers_context *ctx, const struct sudo_nss *nss)
+{
+ struct sudo_sss_handle *handle = nss->handle;
+ struct sss_sudo_result *sss_result = NULL;
+ static bool cached;
+ uint32_t sss_error;
+ unsigned int i;
+ int rc;
+ debug_decl(sudo_sss_getdefs, SUDOERS_DEBUG_SSSD);
+
+ if (handle == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: called with NULL handle", __func__);
+ debug_return_int(-1);
+ }
+
+ /* Use cached result if present. */
+ if (cached)
+ debug_return_int(0);
+
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "Looking for cn=defaults");
+
+ /* NOTE: these are global defaults, user-ID and name are not used. */
+ rc = handle->fn_send_recv_defaults(ctx->user.pw->pw_uid,
+ ctx->user.pw->pw_name, &sss_error, &handle->domainname, &sss_result);
+ switch (rc) {
+ case 0:
+ break;
+ case ENOMEM:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(-1);
+ default:
+ /*
+ * Unable to connect to the sudo SSSD connector.
+ * SSSD may not be configured for sudo, treat as non-fatal.
+ */
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "handle->fn_send_recv_defaults: rc=%d, sss_error=%u", rc, sss_error);
+ debug_return_int(0);
+ }
+
+ switch (sss_error) {
+ case 0:
+ /* Success */
+ for (i = 0; i < sss_result->num_rules; ++i) {
+ struct sss_sudo_rule *sss_rule = sss_result->rules + i;
+ sudo_debug_printf(SUDO_DEBUG_DIAG,
+ "Parsing cn=defaults, %d/%d", i, sss_result->num_rules);
+ if (!sudo_sss_parse_options(handle, sss_rule,
+ &handle->parse_tree.defaults))
+ goto bad;
+ }
+ break;
+ case ENOENT:
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "No global defaults entry found in SSSD.");
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "sss_error=%u\n", sss_error);
+ goto bad;
+ }
+ handle->fn_free_result(sss_result);
+ cached = true;
+ debug_return_int(0);
+
+bad:
+ handle->fn_free_result(sss_result);
+ debug_return_int(-1);
+}
+
+/* sudo_nss implementation */
+struct sudo_nss sudo_nss_sss = {
+ { NULL, NULL },
+ "sss",
+ sudo_sss_open,
+ sudo_sss_close,
+ sudo_sss_parse,
+ sudo_sss_query,
+ sudo_sss_getdefs
+};
+
+#endif /* HAVE_SSSD */
diff --git a/plugins/sudoers/starttime.c b/plugins/sudoers/starttime.c
new file mode 100644
index 0000000..cbdbf16
--- /dev/null
+++ b/plugins/sudoers/starttime.c
@@ -0,0 +1,342 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2012-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+/* Large files not supported by procfs.h on Solaris. */
+#if defined(HAVE_STRUCT_PSINFO_PR_TTYDEV)
+# undef _FILE_OFFSET_BITS
+# undef _LARGE_FILES
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined(HAVE_KINFO_PROC_44BSD) || defined (HAVE_KINFO_PROC_OPENBSD) || defined(HAVE_KINFO_PROC2_NETBSD)
+# include <sys/sysctl.h>
+#elif defined(HAVE_KINFO_PROC_FREEBSD) || defined(HAVE_KINFO_PROC_DFLY)
+# include <sys/param.h>
+# include <sys/sysctl.h>
+# include <sys/user.h>
+#endif
+#if defined(HAVE_PROCFS_H)
+# include <procfs.h>
+#elif defined(HAVE_SYS_PROCFS_H)
+# include <sys/procfs.h>
+#endif
+#ifdef HAVE_PSTAT_GETPROC
+# include <sys/pstat.h>
+#endif
+
+#if defined(__gnu_hurd__)
+# include <hurd.h>
+# include <mach/task_info.h>
+# include <mach/time_value.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+
+#include <sudoers.h>
+#include <timestamp.h>
+
+/*
+ * Arguments for sysctl(2) when reading the process start time.
+ */
+#if defined(HAVE_KINFO_PROC2_NETBSD)
+# define SUDO_KERN_PROC KERN_PROC2
+# define sudo_kinfo_proc kinfo_proc2
+# define sudo_kp_namelen 6
+#elif defined(HAVE_KINFO_PROC_OPENBSD)
+# define SUDO_KERN_PROC KERN_PROC
+# define sudo_kinfo_proc kinfo_proc
+# define sudo_kp_namelen 6
+#elif defined(HAVE_KINFO_PROC_FREEBSD) || defined(HAVE_KINFO_PROC_DFLY) || defined(HAVE_KINFO_PROC_44BSD)
+# define SUDO_KERN_PROC KERN_PROC
+# define sudo_kinfo_proc kinfo_proc
+# define sudo_kp_namelen 4
+#endif
+
+/*
+ * Store start time of the specified process in starttime.
+ */
+
+#if defined(sudo_kinfo_proc)
+int
+get_starttime(pid_t pid, struct timespec *starttime)
+{
+ struct sudo_kinfo_proc *ki_proc = NULL;
+ size_t size = sizeof(*ki_proc);
+ int mib[6], rc;
+ debug_decl(get_starttime, SUDOERS_DEBUG_UTIL);
+
+ /*
+ * Lookup start time for pid via sysctl.
+ */
+ mib[0] = CTL_KERN;
+ mib[1] = SUDO_KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = (int)pid;
+ mib[4] = sizeof(*ki_proc);
+ mib[5] = 1;
+ for (;;) {
+ struct sudo_kinfo_proc *kp;
+
+ size += size / 10;
+ if ((kp = realloc(ki_proc, size)) == NULL) {
+ rc = -1;
+ break; /* really out of memory. */
+ }
+ ki_proc = kp;
+ rc = sysctl(mib, sudo_kp_namelen, ki_proc, &size, NULL, 0);
+ if (rc != -1 || errno != ENOMEM)
+ break;
+ }
+ if (rc != -1) {
+#if defined(HAVE_KINFO_PROC_FREEBSD)
+ /* FreeBSD. */
+ TIMEVAL_TO_TIMESPEC(&ki_proc->ki_start, starttime);
+#elif defined(HAVE_KINFO_PROC_DFLY)
+ /* Dragonfly. */
+ TIMEVAL_TO_TIMESPEC(&ki_proc->kp_start, starttime);
+#elif defined(HAVE_KINFO_PROC_44BSD)
+ /* 4.4BSD and macOS */
+ TIMEVAL_TO_TIMESPEC(&ki_proc->kp_proc.p_starttime, starttime);
+#else
+ /* NetBSD and OpenBSD */
+ starttime->tv_sec = (time_t)ki_proc->p_ustart_sec;
+ starttime->tv_nsec = (long)(ki_proc->p_ustart_usec * 1000);
+#endif
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: start time for %d: { %lld, %ld }", __func__,
+ (int)pid, (long long)starttime->tv_sec, (long)starttime->tv_nsec);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to get start time for %d via KERN_PROC", (int)pid);
+ }
+ free(ki_proc);
+
+ debug_return_int(rc == -1 ? -1 : 0);
+}
+#elif defined(HAVE_STRUCT_PSINFO_PR_TTYDEV)
+int
+get_starttime(pid_t pid, struct timespec *starttime)
+{
+ struct psinfo psinfo;
+ char path[PATH_MAX];
+ ssize_t nread;
+ int fd, ret = -1;
+ debug_decl(get_starttime, SUDOERS_DEBUG_UTIL);
+
+ /* Determine the start time from pr_start in /proc/pid/psinfo. */
+ (void)snprintf(path, sizeof(path), "/proc/%u/psinfo", (unsigned int)pid);
+ if ((fd = open(path, O_RDONLY, 0)) != -1) {
+ nread = read(fd, &psinfo, sizeof(psinfo));
+ close(fd);
+ if (nread == (ssize_t)sizeof(psinfo)) {
+ starttime->tv_sec = psinfo.pr_start.tv_sec;
+ starttime->tv_nsec = psinfo.pr_start.tv_nsec;
+ ret = 0;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: start time for %d: { %lld, %ld }", __func__, (int)pid,
+ (long long)starttime->tv_sec, (long)starttime->tv_nsec);
+ }
+ }
+
+ if (ret == -1)
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to get start time for %d via %s", (int)pid, path);
+ debug_return_int(ret);
+}
+#elif defined(__linux__)
+int
+get_starttime(pid_t pid, struct timespec *starttime)
+{
+ char path[PATH_MAX];
+ char *cp, buf[1024];
+ ssize_t nread;
+ int ret = -1;
+ int fd = -1;
+ long tps;
+ debug_decl(get_starttime, SUDOERS_DEBUG_UTIL);
+
+ /*
+ * Start time is in ticks per second on Linux.
+ */
+ tps = sysconf(_SC_CLK_TCK);
+ if (tps == -1)
+ goto done;
+
+ /*
+ * Determine the start time from 22nd field in /proc/pid/stat.
+ * Ignore /proc/self/stat if it contains embedded NUL bytes.
+ * XXX - refactor common code with ttyname.c?
+ */
+ (void)snprintf(path, sizeof(path), "/proc/%u/stat", (unsigned int)pid);
+ if ((fd = open(path, O_RDONLY | O_NOFOLLOW)) != -1) {
+ cp = buf;
+ while ((nread = read(fd, cp, sizeof(buf) - (size_t)(cp - buf))) != 0) {
+ if (nread == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ break;
+ }
+ cp += nread;
+ if (cp >= buf + sizeof(buf))
+ break;
+ }
+ if (nread == 0 && memchr(buf, '\0', (size_t)(cp - buf)) == NULL) {
+ /*
+ * Field 22 is the start time (%ull).
+ * Since the process name at field 2 "(comm)" may include
+ * whitespace (including newlines), start at the last ')' found.
+ */
+ *cp = '\0';
+ cp = strrchr(buf, ')');
+ if (cp != NULL) {
+ char *ep = cp;
+ int field = 1;
+
+ while (*++ep != '\0') {
+ if (*ep == ' ') {
+ if (++field == 22) {
+ unsigned long long ullval;
+
+ /* Must start with a digit (not negative). */
+ if (!isdigit((unsigned char)*cp)) {
+ errno = EINVAL;
+ goto done;
+ }
+
+ /* starttime is %ul in 2.4 and %ull in >= 2.6 */
+ errno = 0;
+ ullval = strtoull(cp, &ep, 10);
+ if (ep == cp || *ep != ' ') {
+ errno = EINVAL;
+ goto done;
+ }
+ if (errno == ERANGE && ullval == ULLONG_MAX)
+ goto done;
+
+ /* Convert from ticks to timespec */
+ starttime->tv_sec = (time_t)(ullval / tps);
+ starttime->tv_nsec =
+ (long)(ullval % tps) * (1000000000 / tps);
+ ret = 0;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: start time for %d: { %lld, %ld }",
+ __func__, (int)pid,
+ (long long)starttime->tv_sec,
+ (long)starttime->tv_nsec);
+
+ goto done;
+ }
+ cp = ep + 1;
+ }
+ }
+ }
+ }
+ }
+ errno = ENOENT;
+
+done:
+ if (fd != -1)
+ close(fd);
+ if (ret == -1)
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to get start time for %d via %s", (int)pid, path);
+
+ debug_return_int(ret);
+}
+#elif defined(HAVE_PSTAT_GETPROC)
+int
+get_starttime(pid_t pid, struct timespec *starttime)
+{
+ struct pst_status pst;
+ int rc;
+ debug_decl(get_starttime, SUDOERS_DEBUG_UTIL);
+
+ /*
+ * Determine the start time from pst_start in struct pst_status.
+ * EOVERFLOW is not a fatal error for the fields we use.
+ * See the "EOVERFLOW Error" section of pstat_getvminfo(3).
+ */
+ rc = pstat_getproc(&pst, sizeof(pst), 0, pid);
+ if (rc != -1 || errno == EOVERFLOW) {
+ starttime->tv_sec = (time_t)pst.pst_start;
+ starttime->tv_nsec = 0;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: start time for %d: { %lld, %ld }", __func__,
+ (int)pid, (long long)starttime->tv_sec, (long)starttime->tv_nsec);
+
+ debug_return_int(0);
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to get start time for %d via pstat_getproc", (int)pid);
+ debug_return_int(-1);
+}
+#elif defined(__gnu_hurd__)
+int
+get_starttime(pid_t pid, struct timespec *starttime)
+{
+ mach_msg_type_number_t count;
+ struct task_basic_info info;
+ kern_return_t error;
+ task_t target;
+ debug_decl(get_starttime, SUDOERS_DEBUG_UTIL);
+
+ target = pid2task(pid);
+ if (target != MACH_PORT_NULL) {
+ count = sizeof(info) / sizeof(integer_t);
+ error = task_info(target, TASK_BASIC_INFO, (task_info_t)&info, &count);
+ if (error == KERN_SUCCESS) {
+ starttime->tv_sec = (time_t)info.creation_time.seconds;
+ starttime->tv_nsec = (long)(info.creation_time.microseconds * 1000);
+ debug_return_int(0);
+ }
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to get start time for %d via task_info", (int)pid);
+ debug_return_int(-1);
+}
+#else
+int
+get_starttime(pid_t pid, struct timespec *starttime)
+{
+ debug_decl(get_starttime, SUDOERS_DEBUG_UTIL);
+
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "process start time not supported by sudo on this system");
+ debug_return_int(-1);
+}
+#endif
diff --git a/plugins/sudoers/strlcpy_unesc.c b/plugins/sudoers/strlcpy_unesc.c
new file mode 100644
index 0000000..3df6e8b
--- /dev/null
+++ b/plugins/sudoers/strlcpy_unesc.c
@@ -0,0 +1,55 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include <sudoers.h>
+
+/*
+ * Like strlcpy() but collapses non-space chars escaped with a backslash.
+ */
+size_t
+strlcpy_unescape(char *restrict dst, const char *restrict src, size_t size)
+{
+ size_t len = 0;
+ char ch;
+ debug_decl(strlcpy_unescape, SUDOERS_DEBUG_UTIL);
+
+ while ((ch = *src++) != '\0') {
+ if (ch == '\\' && *src != '\0' && !isspace((unsigned char)*src))
+ ch = *src++;
+ if (size > 1) {
+ *dst++ = ch;
+ size--;
+ }
+ len++;
+ }
+ if (size > 0)
+ *dst = '\0';
+
+ debug_return_size_t(len);
+}
diff --git a/plugins/sudoers/strlist.c b/plugins/sudoers/strlist.c
new file mode 100644
index 0000000..912ce46
--- /dev/null
+++ b/plugins/sudoers/strlist.c
@@ -0,0 +1,92 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudo_compat.h>
+#include <sudo_queue.h>
+#include <sudo_util.h>
+#include <sudoers_debug.h>
+#include <strlist.h>
+
+struct sudoers_string *
+sudoers_string_alloc(const char *s)
+{
+ struct sudoers_string *cs;
+ debug_decl(sudoers_string_alloc, SUDOERS_DEBUG_UTIL);
+
+ if ((cs = malloc(sizeof(*cs))) != NULL) {
+ if ((cs->str = strdup(s)) == NULL) {
+ free(cs);
+ cs = NULL;
+ }
+ }
+
+ debug_return_ptr(cs);
+}
+
+void
+sudoers_string_free(struct sudoers_string *cs)
+{
+ if (cs != NULL) {
+ free(cs->str);
+ free(cs);
+ }
+}
+
+struct sudoers_str_list *
+str_list_alloc(void)
+{
+ struct sudoers_str_list *strlist;
+ debug_decl(str_list_alloc, SUDOERS_DEBUG_UTIL);
+
+ strlist = malloc(sizeof(*strlist));
+ if (strlist != NULL) {
+ STAILQ_INIT(strlist);
+ strlist->refcnt = 1;
+ }
+
+ debug_return_ptr(strlist);
+}
+
+void
+str_list_free(void *v)
+{
+ struct sudoers_str_list *strlist = v;
+ struct sudoers_string *first;
+ debug_decl(str_list_free, SUDOERS_DEBUG_UTIL);
+
+ if (strlist != NULL) {
+ if (--strlist->refcnt == 0) {
+ while ((first = STAILQ_FIRST(strlist)) != NULL) {
+ STAILQ_REMOVE_HEAD(strlist, entries);
+ sudoers_string_free(first);
+ }
+ free(strlist);
+ }
+ }
+ debug_return;
+}
diff --git a/plugins/sudoers/strlist.h b/plugins/sudoers/strlist.h
new file mode 100644
index 0000000..022f52b
--- /dev/null
+++ b/plugins/sudoers/strlist.h
@@ -0,0 +1,40 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_STRLIST_H
+#define SUDOERS_STRLIST_H
+
+/*
+ * Simple string list with optional reference count.
+ */
+struct sudoers_string {
+ STAILQ_ENTRY(sudoers_string) entries;
+ char *str;
+};
+struct sudoers_str_list {
+ struct sudoers_string *stqh_first;
+ struct sudoers_string **stqh_last;
+ unsigned int refcnt;
+};
+
+struct sudoers_str_list *str_list_alloc(void);
+void str_list_free(void *v);
+struct sudoers_string *sudoers_string_alloc(const char *s);
+void sudoers_string_free(struct sudoers_string *ls);
+
+#endif /* SUDOERS_STRLIST_H */
diff --git a/plugins/sudoers/strvec_join.c b/plugins/sudoers/strvec_join.c
new file mode 100644
index 0000000..bee2e44
--- /dev/null
+++ b/plugins/sudoers/strvec_join.c
@@ -0,0 +1,74 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudoers.h>
+
+#ifdef HAVE_STRLCPY
+# define cpy_default strlcpy
+#else
+# define cpy_default sudo_strlcpy
+#endif
+
+/*
+ * Join a NULL-terminated array of strings using the specified separator
+ * char. If non-NULL, the copy function must have strlcpy-like semantics.
+ */
+char *
+strvec_join(char *const argv[], char sep, size_t (*cpy)(char *, const char *, size_t))
+{
+ char *dst, *result = NULL;
+ char *const *av;
+ size_t n, size = 0;
+ debug_decl(strvec_join, SUDOERS_DEBUG_UTIL);
+
+ for (av = argv; *av != NULL; av++)
+ size += strlen(*av) + 1;
+ if (size == 0 || (result = malloc(size)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_ptr(NULL);
+ }
+
+ if (cpy == NULL)
+ cpy = cpy_default;
+ for (dst = result, av = argv; *av != NULL; av++) {
+ n = cpy(dst, *av, size);
+ if (n >= size) {
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ free(result);
+ debug_return_ptr(NULL);
+ }
+ dst += n;
+ size -= n;
+ *dst++ = sep;
+ size--;
+ }
+ dst[-1] = '\0';
+
+ debug_return_str(result);
+}
diff --git a/plugins/sudoers/stubs.c b/plugins/sudoers/stubs.c
new file mode 100644
index 0000000..b8bc104
--- /dev/null
+++ b/plugins/sudoers/stubs.c
@@ -0,0 +1,110 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2018-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+/*
+ * Stub versions of functions needed by the parser.
+ * Required to link cvtsudoers and visudo.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <sudoers.h>
+#include <interfaces.h>
+
+/* STUB */
+bool
+init_envtables(void)
+{
+ return true;
+}
+
+/* STUB */
+bool
+user_is_exempt(const struct sudoers_context *ctx)
+{
+ return false;
+}
+
+/* STUB */
+void
+sudo_setspent(void)
+{
+ return;
+}
+
+/* STUB */
+void
+sudo_endspent(void)
+{
+ return;
+}
+
+/* STUB */
+int
+group_plugin_query(const char *user, const char *group, const struct passwd *pw)
+{
+ return false;
+}
+
+/* STUB */
+struct interface_list *
+get_interfaces(void)
+{
+ static struct interface_list empty = SLIST_HEAD_INITIALIZER(interfaces);
+ return &empty;
+}
+
+/* STUB */
+int
+set_cmnd_path(struct sudoers_context *ctx, const char *runchroot)
+{
+ /* Cannot return FOUND without also setting ctx->user.cmnd to a new value. */
+ return NOT_FOUND;
+}
+
+/* STUB */
+void
+init_eventlog_config(void)
+{
+ return;
+}
+
+/* STUB */
+bool
+pivot_root(const char *new_root, struct sudoers_pivot *state)
+{
+ return true;
+}
+
+/* STUB */
+bool
+unpivot_root(struct sudoers_pivot *state)
+{
+ return true;
+}
diff --git a/plugins/sudoers/sudo_ldap.h b/plugins/sudoers/sudo_ldap.h
new file mode 100644
index 0000000..be12c65
--- /dev/null
+++ b/plugins/sudoers/sudo_ldap.h
@@ -0,0 +1,109 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2018, 2021, 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_LDAP_H
+#define SUDOERS_LDAP_H
+
+#ifndef LDAP_OPT_RESULT_CODE
+# define LDAP_OPT_RESULT_CODE LDAP_OPT_ERROR_NUMBER
+#endif
+
+#if !defined(LDAP_OPT_NETWORK_TIMEOUT) && defined(LDAP_OPT_CONNECT_TIMEOUT)
+# define LDAP_OPT_NETWORK_TIMEOUT LDAP_OPT_CONNECT_TIMEOUT
+#endif
+
+#ifndef LDAP_OPT_SUCCESS
+# define LDAP_OPT_SUCCESS LDAP_SUCCESS
+#endif
+
+#ifndef HAVE_LDAP_SEARCH_EXT_S
+# ifdef HAVE_LDAP_SEARCH_ST
+# define ldap_search_ext_s(a, b, c, d, e, f, g, h, i, j, k) \
+ ldap_search_st(a, b, c, d, e, f, i, k)
+# else
+# define ldap_search_ext_s(a, b, c, d, e, f, g, h, i, j, k) \
+ ldap_search_s(a, b, c, d, e, f, k)
+# endif
+#endif
+
+/* Macros for checking strlcpy/strlcat/sudo_ldap_value_cat return value. */
+#define CHECK_STRLCPY(d, s, l) do { \
+ if (strlcpy((d), (s), (l)) >= (l)) { \
+ goto overflow; \
+ } \
+} while (0)
+#define CHECK_STRLCAT(d, s, l) do { \
+ if (strlcat((d), (s), (l)) >= (l)) { \
+ goto overflow; \
+ } \
+} while (0)
+#define CHECK_LDAP_VCAT(d, s, l) do { \
+ if (sudo_ldap_value_cat((d), (s), (l)) >= (l)) { \
+ goto overflow; \
+ } \
+} while (0)
+
+#if defined(__GNUC__) && __GNUC__ == 2
+# define DPRINTF1(fmt...) do { \
+ sudo_debug_printf(SUDO_DEBUG_DIAG, fmt); \
+ if (ldap_conf.debug >= 1) { \
+ sudo_warnx_nodebug(fmt); \
+ } \
+} while (0)
+# define DPRINTF2(fmt...) do { \
+ sudo_debug_printf(SUDO_DEBUG_INFO, fmt); \
+ if (ldap_conf.debug >= 2) { \
+ sudo_warnx_nodebug(fmt); \
+ } \
+} while (0)
+#else
+# define DPRINTF1(...) do { \
+ sudo_debug_printf(SUDO_DEBUG_DIAG, __VA_ARGS__); \
+ if (ldap_conf.debug >= 1) { \
+ sudo_warnx_nodebug(__VA_ARGS__); \
+ } \
+} while (0)
+# define DPRINTF2(...) do { \
+ sudo_debug_printf(SUDO_DEBUG_INFO, __VA_ARGS__); \
+ if (ldap_conf.debug >= 2) { \
+ sudo_warnx_nodebug(__VA_ARGS__); \
+ } \
+} while (0)
+#endif
+
+#define LDAP_FOREACH(var, ld, res) \
+ for ((var) = ldap_first_entry((ld), (res)); \
+ (var) != NULL; \
+ (var) = ldap_next_entry((ld), (var)))
+
+/* Iterators used by sudo_ldap_role_to_priv() to handle bervar ** or char ** */
+typedef char * (*sudo_ldap_iter_t)(void **);
+
+/* ldap_innetgr.c */
+int sudo_ldap_innetgr_int(void *v, const char *netgr, const char *host, const char *user, const char *domain);
+
+/* ldap_util.c */
+bool sudo_ldap_is_negated(char **valp);
+size_t sudo_ldap_value_len(const char *value);
+size_t sudo_ldap_value_cat(char * restrict dst, const char * restrict src, size_t size);
+char *sudo_ldap_value_dup(const char *src);
+int sudo_ldap_parse_option(char *optstr, char **varp, char **valp);
+struct privilege *sudo_ldap_role_to_priv(const char *cn, void *hosts, void *runasusers, void *runasgroups, void *cmnds, void *opts, const char *notbefore, const char *notafter, bool warnings, bool store_options, sudo_ldap_iter_t iter);
+struct member *sudo_ldap_new_member_all(void);
+
+#endif /* SUDOERS_LDAP_H */
diff --git a/plugins/sudoers/sudo_ldap_conf.h b/plugins/sudoers/sudo_ldap_conf.h
new file mode 100644
index 0000000..d95265b
--- /dev/null
+++ b/plugins/sudoers/sudo_ldap_conf.h
@@ -0,0 +1,100 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_LDAP_CONF_H
+#define SUDOERS_LDAP_CONF_H
+
+/*
+ * Configuration data types.
+ * When adding a new data type, be sure to update sudo_ldap_parse_keyword()
+ * and sudo_ldap_set_options_table().
+ */
+#define CONF_BOOL 0
+#define CONF_INT 1
+#define CONF_STR 2
+#define CONF_LIST_STR 4
+#define CONF_DEREF_VAL 5
+#define CONF_REQCERT_VAL 6
+
+#define SUDO_LDAP_CLEAR 0
+#define SUDO_LDAP_SSL 1
+#define SUDO_LDAP_STARTTLS 2
+
+struct ldap_config_table {
+ const char *conf_str; /* config file string */
+ int type; /* CONF_* value, see above */
+ int opt_val; /* LDAP_OPT_* (or -1 for sudo internal) */
+ void *valp; /* pointer into ldap_conf */
+};
+
+struct ldap_config_str {
+ STAILQ_ENTRY(ldap_config_str) entries;
+ char val[];
+};
+STAILQ_HEAD(ldap_config_str_list, ldap_config_str);
+
+/* LDAP configuration structure */
+struct ldap_config {
+ int port;
+ int version;
+ int debug;
+ int ldap_debug;
+ int tls_checkpeer;
+ int tls_reqcert;
+ int timelimit;
+ int timeout;
+ int bind_timelimit;
+ int use_sasl;
+ int rootuse_sasl;
+ int ssl_mode;
+ int timed;
+ int deref;
+ int netgroup_query;
+ char *host;
+ struct ldap_config_str_list uri;
+ char *binddn;
+ char *bindpw;
+ char *rootbinddn;
+ struct ldap_config_str_list base;
+ struct ldap_config_str_list netgroup_base;
+ char *search_filter;
+ char *netgroup_search_filter;
+ char *ssl;
+ char *tls_cacertfile;
+ char *tls_cacertdir;
+ char *tls_random_file;
+ char *tls_cipher_suite;
+ char *tls_certfile;
+ char *tls_keyfile;
+ char *tls_keypw;
+ char *sasl_mech;
+ char *sasl_auth_id;
+ char *rootsasl_auth_id;
+ char *sasl_secprops;
+ char *krb5_ccname;
+};
+
+extern struct ldap_config ldap_conf;
+
+struct sudoers_context;
+const char *sudo_krb5_ccname_path(const char *old_ccname);
+bool sudo_ldap_read_config(const struct sudoers_context *ctx);
+int sudo_ldap_set_options_global(void);
+int sudo_ldap_set_options_conn(LDAP *ld);
+
+#endif /* SUDOERS_LDAP_CONF_H */
diff --git a/plugins/sudoers/sudo_nss.c b/plugins/sudoers/sudo_nss.c
new file mode 100644
index 0000000..83eeaa2
--- /dev/null
+++ b/plugins/sudoers/sudo_nss.c
@@ -0,0 +1,264 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2007-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <ctype.h>
+
+#include <sudoers.h>
+
+extern struct sudo_nss sudo_nss_file;
+#ifdef HAVE_LDAP
+extern struct sudo_nss sudo_nss_ldap;
+#endif
+#ifdef HAVE_SSSD
+extern struct sudo_nss sudo_nss_sss;
+#endif
+
+/* Make sure we have not already inserted the nss entry. */
+#define SUDO_NSS_CHECK_UNUSED(nss, tag) \
+ if (nss.entries.tqe_next != NULL || nss.entries.tqe_prev != NULL) { \
+ sudo_warnx("internal error: nsswitch entry \"%s\" already in use", \
+ tag); \
+ continue; \
+ }
+
+#if (defined(HAVE_LDAP) || defined(HAVE_SSSD)) && defined(_PATH_NSSWITCH_CONF)
+/*
+ * Read in /etc/nsswitch.conf
+ * Returns a tail queue of matches.
+ */
+struct sudo_nss_list *
+sudo_read_nss(void)
+{
+ FILE *fp;
+ char *line = NULL;
+ size_t linesize = 0;
+#ifdef HAVE_SSSD
+ bool saw_sss = false;
+#endif
+#ifdef HAVE_LDAP
+ bool saw_ldap = false;
+#endif
+ bool saw_files = false;
+ bool got_match = false;
+ static struct sudo_nss_list snl = TAILQ_HEAD_INITIALIZER(snl);
+ debug_decl(sudo_read_nss, SUDOERS_DEBUG_NSS);
+
+ if ((fp = fopen(_PATH_NSSWITCH_CONF, "r")) == NULL)
+ goto nomatch;
+
+ while (sudo_parseln(&line, &linesize, NULL, fp, 0) != -1) {
+ char *cp, *last;
+
+ /* Skip blank or comment lines */
+ if (*line == '\0')
+ continue;
+
+ /* Look for a line starting with "sudoers:" */
+ if (strncasecmp(line, "sudoers:", 8) != 0)
+ continue;
+
+ /* Parse line */
+ for ((cp = strtok_r(line + 8, " \t", &last)); cp != NULL; (cp = strtok_r(NULL, " \t", &last))) {
+ if (strcasecmp(cp, "files") == 0 && !saw_files) {
+ SUDO_NSS_CHECK_UNUSED(sudo_nss_file, "files");
+ TAILQ_INSERT_TAIL(&snl, &sudo_nss_file, entries);
+ got_match = saw_files = true;
+#ifdef HAVE_LDAP
+ } else if (strcasecmp(cp, "ldap") == 0 && !saw_ldap) {
+ SUDO_NSS_CHECK_UNUSED(sudo_nss_ldap, "ldap");
+ TAILQ_INSERT_TAIL(&snl, &sudo_nss_ldap, entries);
+ got_match = saw_ldap = true;
+#endif
+#ifdef HAVE_SSSD
+ } else if (strcasecmp(cp, "sss") == 0 && !saw_sss) {
+ SUDO_NSS_CHECK_UNUSED(sudo_nss_sss, "sss");
+ TAILQ_INSERT_TAIL(&snl, &sudo_nss_sss, entries);
+ got_match = saw_sss = true;
+#endif
+ } else if (strcasecmp(cp, "[NOTFOUND=return]") == 0 && got_match) {
+ /* NOTFOUND affects the most recent entry */
+ TAILQ_LAST(&snl, sudo_nss_list)->ret_if_notfound = true;
+ got_match = false;
+ } else if (strcasecmp(cp, "[SUCCESS=return]") == 0 && got_match) {
+ /* SUCCESS affects the most recent entry */
+ TAILQ_LAST(&snl, sudo_nss_list)->ret_if_found = true;
+ got_match = false;
+ } else
+ got_match = false;
+ }
+ /* Only parse the first "sudoers:" line */
+ break;
+ }
+ free(line);
+ fclose(fp);
+
+nomatch:
+ /* Default to files only if no matches */
+ if (TAILQ_EMPTY(&snl))
+ TAILQ_INSERT_TAIL(&snl, &sudo_nss_file, entries);
+
+ debug_return_ptr(&snl);
+}
+
+#else /* (HAVE_LDAP || HAVE_SSSD) && _PATH_NSSWITCH_CONF */
+
+# if (defined(HAVE_LDAP) || defined(HAVE_SSSD)) && defined(_PATH_NETSVC_CONF)
+
+/*
+ * Read in /etc/netsvc.conf (like nsswitch.conf on AIX)
+ * Returns a tail queue of matches.
+ */
+struct sudo_nss_list *
+sudo_read_nss(void)
+{
+ FILE *fp;
+ char *cp, *ep, *last, *line = NULL;
+ size_t linesize = 0;
+#ifdef HAVE_SSSD
+ bool saw_sss = false;
+#endif
+ bool saw_files = false;
+ bool saw_ldap = false;
+ bool got_match = false;
+ static struct sudo_nss_list snl = TAILQ_HEAD_INITIALIZER(snl);
+ debug_decl(sudo_read_nss, SUDOERS_DEBUG_NSS);
+
+ if ((fp = fopen(_PATH_NETSVC_CONF, "r")) == NULL)
+ goto nomatch;
+
+ while (sudo_parseln(&line, &linesize, NULL, fp, 0) != -1) {
+ /* Skip blank or comment lines */
+ if (*(cp = line) == '\0')
+ continue;
+
+ /* Look for a line starting with "sudoers = " */
+ if (strncasecmp(cp, "sudoers", 7) != 0)
+ continue;
+ cp += 7;
+ while (isspace((unsigned char)*cp))
+ cp++;
+ if (*cp++ != '=')
+ continue;
+
+ /* Parse line */
+ for ((cp = strtok_r(cp, ",", &last)); cp != NULL; (cp = strtok_r(NULL, ",", &last))) {
+ /* Trim leading whitespace. */
+ while (isspace((unsigned char)*cp))
+ cp++;
+
+ if (!saw_files && strncasecmp(cp, "files", 5) == 0 &&
+ (isspace((unsigned char)cp[5]) || cp[5] == '\0')) {
+ TAILQ_INSERT_TAIL(&snl, &sudo_nss_file, entries);
+ got_match = saw_files = true;
+ ep = &cp[5];
+#ifdef HAVE_LDAP
+ } else if (!saw_ldap && strncasecmp(cp, "ldap", 4) == 0 &&
+ (isspace((unsigned char)cp[4]) || cp[4] == '\0')) {
+ TAILQ_INSERT_TAIL(&snl, &sudo_nss_ldap, entries);
+ got_match = saw_ldap = true;
+ ep = &cp[4];
+#endif
+#ifdef HAVE_SSSD
+ } else if (!saw_sss && strncasecmp(cp, "sss", 3) == 0 &&
+ (isspace((unsigned char)cp[3]) || cp[3] == '\0')) {
+ TAILQ_INSERT_TAIL(&snl, &sudo_nss_sss, entries);
+ got_match = saw_sss = true;
+ ep = &cp[3];
+#endif
+ } else {
+ got_match = false;
+ }
+
+ /* check for = auth qualifier */
+ if (got_match && *ep) {
+ cp = ep;
+ while (isspace((unsigned char)*cp) || *cp == '=')
+ cp++;
+ if (strncasecmp(cp, "auth", 4) == 0 &&
+ (isspace((unsigned char)cp[4]) || cp[4] == '\0')) {
+ TAILQ_LAST(&snl, sudo_nss_list)->ret_if_found = true;
+ }
+ }
+ }
+ /* Only parse the first "sudoers" line */
+ break;
+ }
+ fclose(fp);
+
+nomatch:
+ /* Default to files only if no matches */
+ if (TAILQ_EMPTY(&snl))
+ TAILQ_INSERT_TAIL(&snl, &sudo_nss_file, entries);
+
+ debug_return_ptr(&snl);
+}
+
+# else /* !_PATH_NETSVC_CONF && !_PATH_NSSWITCH_CONF */
+
+/*
+ * Non-nsswitch.conf version with hard-coded order.
+ */
+struct sudo_nss_list *
+sudo_read_nss(void)
+{
+ static struct sudo_nss_list snl = TAILQ_HEAD_INITIALIZER(snl);
+ debug_decl(sudo_read_nss, SUDOERS_DEBUG_NSS);
+
+# ifdef HAVE_SSSD
+ TAILQ_INSERT_TAIL(&snl, &sudo_nss_sss, entries);
+# endif
+# ifdef HAVE_LDAP
+ TAILQ_INSERT_TAIL(&snl, &sudo_nss_ldap, entries);
+# endif
+ TAILQ_INSERT_TAIL(&snl, &sudo_nss_file, entries);
+
+ debug_return_ptr(&snl);
+}
+
+# endif /* !HAVE_LDAP || !_PATH_NETSVC_CONF */
+
+#endif /* HAVE_LDAP && _PATH_NSSWITCH_CONF */
+
+bool
+sudo_nss_can_continue(const struct sudo_nss *nss, int match)
+{
+ debug_decl(sudo_nss_should_continue, SUDOERS_DEBUG_NSS);
+
+ /* Handle [NOTFOUND=return] */
+ if (nss->ret_if_notfound && match == UNSPEC)
+ debug_return_bool(false);
+
+ /* Handle [SUCCESS=return] */
+ if (nss->ret_if_found && match != UNSPEC)
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
diff --git a/plugins/sudoers/sudo_nss.h b/plugins/sudoers/sudo_nss.h
new file mode 100644
index 0000000..9e77020
--- /dev/null
+++ b/plugins/sudoers/sudo_nss.h
@@ -0,0 +1,50 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2007-2011, 2013-2015, 2017-2018
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_NSS_H
+#define SUDOERS_NSS_H
+
+struct passwd;
+struct userspec_list;
+struct defaults_list;
+struct sudoers_context;
+
+/* XXX - parse_tree, ret_if_found and ret_if_notfound should be private */
+struct sudo_nss {
+ TAILQ_ENTRY(sudo_nss) entries;
+ const char *source;
+ int (*open)(struct sudoers_context *ctx, struct sudo_nss *nss);
+ int (*close)(struct sudoers_context *ctx, struct sudo_nss *nss);
+ struct sudoers_parse_tree *(*parse)(struct sudoers_context *ctx, const struct sudo_nss *nss);
+ int (*query)(struct sudoers_context *ctx, const struct sudo_nss *nss, struct passwd *pw);
+ int (*getdefs)(struct sudoers_context *ctx, const struct sudo_nss *nss);
+ int (*innetgr)(const struct sudo_nss *nss, const char *netgr,
+ const char *host, const char *user, const char *domain);
+ void *handle;
+ struct sudoers_parse_tree *parse_tree;
+ bool ret_if_found;
+ bool ret_if_notfound;
+};
+
+TAILQ_HEAD(sudo_nss_list, sudo_nss);
+
+struct sudo_nss_list *sudo_read_nss(void);
+bool sudo_nss_can_continue(const struct sudo_nss *nss, int match);
+
+#endif /* SUDOERS_NSS_H */
diff --git a/plugins/sudoers/sudo_printf.c b/plugins/sudoers/sudo_printf.c
new file mode 100644
index 0000000..f5ca602
--- /dev/null
+++ b/plugins/sudoers/sudo_printf.c
@@ -0,0 +1,90 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2012 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+#include <sudo_plugin.h>
+#include <sudo_debug.h>
+#include <pathnames.h>
+
+static int
+sudo_printf_int(int msg_type, const char * restrict fmt, ...)
+{
+ FILE *fp = stdout;
+ FILE *ttyfp = NULL;
+ char sbuf[8192];
+ char *buf = sbuf;
+ va_list ap;
+ int len;
+
+ if (ISSET(msg_type, SUDO_CONV_PREFER_TTY)) {
+ /* Try writing to /dev/tty first. */
+ ttyfp = fopen(_PATH_TTY, "w");
+ }
+
+ switch (msg_type & 0xff) {
+ case SUDO_CONV_ERROR_MSG:
+ fp = stderr;
+ FALLTHROUGH;
+ case SUDO_CONV_INFO_MSG:
+ /*
+ * We use vsnprintf() instead of vfprintf() here to avoid
+ * problems on systems where the system printf(3) is not
+ * C99-compliant. We use our own snprintf() on such systems.
+ */
+ va_start(ap, fmt);
+ len = vsnprintf(sbuf, sizeof(sbuf), fmt, ap);
+ va_end(ap);
+ if (len < 0 || len >= ssizeof(sbuf)) {
+ /* Try again with a dynamically-sized buffer. */
+ va_start(ap, fmt);
+ len = vasprintf(&buf, fmt, ap);
+ va_end(ap);
+ }
+ if (len != -1) {
+ if (fwrite(buf, 1, len, ttyfp ? ttyfp : fp) == 0)
+ len = -1;
+ if (buf != sbuf)
+ free(buf);
+ }
+ break;
+ default:
+ len = -1;
+ errno = EINVAL;
+ break;
+ }
+
+ if (ttyfp != NULL)
+ fclose(ttyfp);
+
+ return len;
+}
+
+sudo_printf_t sudo_printf = sudo_printf_int;
diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c
new file mode 100644
index 0000000..6778e4e
--- /dev/null
+++ b/plugins/sudoers/sudoers.c
@@ -0,0 +1,1556 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1993-1996, 1998-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#ifdef __TANDEM
+# include <floss.h>
+#endif
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <netdb.h>
+#ifdef HAVE_LOGIN_CAP_H
+# include <login_cap.h>
+# ifndef LOGIN_DEFROOTCLASS
+# define LOGIN_DEFROOTCLASS "daemon"
+# endif
+# ifndef LOGIN_SETENV
+# define LOGIN_SETENV 0
+# endif
+#endif
+#ifdef HAVE_SELINUX
+# include <selinux/selinux.h>
+#endif
+#include <ctype.h>
+#ifndef HAVE_GETADDRINFO
+# include <compat/getaddrinfo.h>
+#endif
+
+#include <sudoers.h>
+#include <timestamp.h>
+#include <sudo_iolog.h>
+
+/*
+ * Prototypes
+ */
+static int set_cmnd(struct sudoers_context *ctx);
+static bool init_vars(struct sudoers_context *ctx, char * const *);
+static bool set_loginclass(struct sudoers_context *);
+static bool set_runaspw(struct sudoers_context *ctx, const char *, bool);
+static bool set_runasgr(struct sudoers_context *ctx, const char *, bool);
+
+/*
+ * Globals
+ */
+static char *prev_user;
+static struct sudoers_context sudoers_ctx = SUDOERS_CONTEXT_INITIALIZER;
+static struct sudo_nss_list *snl;
+static bool unknown_runas_uid;
+static bool unknown_runas_gid;
+static int cmnd_status = NOT_FOUND_ERROR;
+static struct defaults_list initial_defaults = TAILQ_HEAD_INITIALIZER(initial_defaults);
+
+#ifdef __linux__
+static struct rlimit nproclimit;
+#endif
+
+#ifdef SUDOERS_LOG_CLIENT
+# define remote_iologs (!SLIST_EMPTY(&def_log_servers))
+#else
+# define remote_iologs 0
+#endif
+
+/*
+ * Unlimit the number of processes since Linux's setuid() will
+ * apply resource limits when changing uid and return EAGAIN if
+ * nproc would be exceeded by the uid switch.
+ */
+static void
+unlimit_nproc(void)
+{
+#ifdef __linux__
+ struct rlimit rl;
+ debug_decl(unlimit_nproc, SUDOERS_DEBUG_UTIL);
+
+ if (getrlimit(RLIMIT_NPROC, &nproclimit) != 0)
+ sudo_warn("getrlimit(RLIMIT_NPROC)");
+ rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
+ if (setrlimit(RLIMIT_NPROC, &rl) != 0) {
+ rl.rlim_cur = rl.rlim_max = nproclimit.rlim_max;
+ if (setrlimit(RLIMIT_NPROC, &rl) != 0)
+ sudo_warn("setrlimit(RLIMIT_NPROC)");
+ }
+ debug_return;
+#endif /* __linux__ */
+}
+
+/*
+ * Restore saved value of RLIMIT_NPROC.
+ */
+static void
+restore_nproc(void)
+{
+#ifdef __linux__
+ debug_decl(restore_nproc, SUDOERS_DEBUG_UTIL);
+
+ if (setrlimit(RLIMIT_NPROC, &nproclimit) != 0)
+ sudo_warn("setrlimit(RLIMIT_NPROC)");
+
+ debug_return;
+#endif /* __linux__ */
+}
+
+/*
+ * Re-initialize Defaults settings.
+ * We do not warn, log or send mail for errors when reinitializing,
+ * this would have already been done the first time through.
+ */
+static bool
+sudoers_reinit_defaults(struct sudoers_context *ctx)
+{
+ struct sudo_nss *nss, *nss_next;
+ sudoers_logger_t logger = sudoers_error_hook;
+ debug_decl(sudoers_reinit_defaults, SUDOERS_DEBUG_PLUGIN);
+
+ if (!init_defaults()) {
+ sudo_warnx("%s", U_("unable to initialize sudoers default values"));
+ debug_return_bool(false);
+ }
+
+ /* It should not be possible for the initial defaults to fail to apply. */
+ if (!update_defaults(ctx, NULL, &initial_defaults,
+ SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER|SETDEF_RUNAS, false))
+ debug_return_bool(false);
+
+ /* Disable error logging while re-processing defaults. */
+ sudoers_error_hook = NULL;
+
+ TAILQ_FOREACH_SAFE(nss, snl, entries, nss_next) {
+ /* Missing/invalid defaults is not a fatal error. */
+ if (nss->getdefs(ctx, nss) != -1) {
+ (void)update_defaults(ctx, nss->parse_tree, NULL,
+ SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER|SETDEF_RUNAS, true);
+ }
+ }
+
+ /* Restore error logging. */
+ sudoers_error_hook = logger;
+
+ /* No need to check the admin flag file multiple times. */
+ if (ISSET(ctx->mode, MODE_POLICY_INTERCEPTED)) {
+ free(def_admin_flag);
+ def_admin_flag = NULL;
+ }
+
+ debug_return_bool(true);
+}
+
+int
+sudoers_init(void *info, sudoers_logger_t logger, char * const envp[])
+{
+ struct sudo_nss *nss, *nss_next;
+ int oldlocale, sources = 0;
+ static int ret = -1;
+ debug_decl(sudoers_init, SUDOERS_DEBUG_PLUGIN);
+
+ /* Only initialize once. */
+ if (snl != NULL)
+ debug_return_int(ret);
+
+ bindtextdomain("sudoers", LOCALEDIR);
+
+ /* Hook up logging function for parse errors. */
+ sudoers_error_hook = logger;
+
+ /* Register fatal/fatalx callback. */
+ sudo_fatal_callback_register(sudoers_cleanup);
+
+ /* Initialize environment functions (including replacements). */
+ if (!env_init(envp))
+ debug_return_int(-1);
+
+ /* Setup defaults data structures. */
+ if (!init_defaults()) {
+ sudo_warnx("%s", U_("unable to initialize sudoers default values"));
+ debug_return_int(-1);
+ }
+
+ /* Parse info from front-end. */
+ sudoers_ctx.mode = sudoers_policy_deserialize_info(&sudoers_ctx, info,
+ &initial_defaults);
+ if (ISSET(sudoers_ctx.mode, MODE_ERROR))
+ debug_return_int(-1);
+
+ if (!init_vars(&sudoers_ctx, envp))
+ debug_return_int(-1);
+
+ /* Parse nsswitch.conf for sudoers order. */
+ snl = sudo_read_nss();
+
+ /* LDAP or NSS may modify the euid so we need to be root for the open. */
+ if (!set_perms(NULL, PERM_ROOT))
+ debug_return_int(-1);
+
+ /* Use the C locale unless another is specified in sudoers. */
+ sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
+ sudo_warn_set_locale_func(sudoers_warn_setlocale);
+
+ /* Update defaults set by front-end. */
+ if (!update_defaults(&sudoers_ctx, NULL, &initial_defaults,
+ SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER|SETDEF_RUNAS, false)) {
+ goto cleanup;
+ }
+
+ /* Open and parse sudoers, set global defaults. */
+ TAILQ_FOREACH_SAFE(nss, snl, entries, nss_next) {
+ if (nss->open(&sudoers_ctx, nss) == -1 || (nss->parse_tree = nss->parse(&sudoers_ctx, nss)) == NULL) {
+ TAILQ_REMOVE(snl, nss, entries);
+ continue;
+ }
+ sources++;
+
+ /* Missing/invalid defaults is not a fatal error. */
+ if (nss->getdefs(&sudoers_ctx, nss) == -1) {
+ log_warningx(&sudoers_ctx, SLOG_PARSE_ERROR|SLOG_NO_STDERR,
+ N_("unable to get defaults from %s"), nss->source);
+ } else {
+ (void)update_defaults(&sudoers_ctx, nss->parse_tree, NULL,
+ SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER|SETDEF_RUNAS, false);
+ }
+ }
+ if (sources == 0) {
+ /* Display an extra warning if there are multiple sudoers sources. */
+ if (TAILQ_FIRST(snl) != TAILQ_LAST(snl, sudo_nss_list))
+ sudo_warnx("%s", U_("no valid sudoers sources found, quitting"));
+ goto cleanup;
+ }
+
+ /* Set login class if applicable (after sudoers is parsed). */
+ if (set_loginclass(&sudoers_ctx))
+ ret = true;
+
+cleanup:
+ mail_parse_errors(&sudoers_ctx);
+
+ if (!restore_perms())
+ ret = -1;
+
+ /* Restore user's locale. */
+ sudo_warn_set_locale_func(NULL);
+ sudoers_setlocale(oldlocale, NULL);
+
+ debug_return_int(ret);
+}
+
+/*
+ * Expand I/O log dir and file into a full path.
+ * Returns the full I/O log path prefixed with "iolog_path=".
+ * Sets ctx->iolog_file and ctx->iolog_path as a side effect.
+ */
+static char *
+format_iolog_path(struct sudoers_context *ctx)
+{
+ char dir[PATH_MAX], file[PATH_MAX];
+ char *iolog_path = NULL;
+ int oldlocale;
+ bool ok;
+ debug_decl(format_iolog_path, SUDOERS_DEBUG_PLUGIN);
+
+ /* Use sudoers locale for strftime() */
+ sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
+ ok = expand_iolog_path(def_iolog_dir, dir, sizeof(dir),
+ &sudoers_iolog_path_escapes[1], ctx);
+ if (ok) {
+ ctx->iolog_dir = dir;
+ ok = expand_iolog_path(def_iolog_file, file, sizeof(file),
+ &sudoers_iolog_path_escapes[0], ctx);
+ ctx->iolog_dir = NULL;
+ }
+ sudoers_setlocale(oldlocale, NULL);
+ if (!ok)
+ goto done;
+
+ if (asprintf(&iolog_path, "iolog_path=%s/%s", dir, file) == -1) {
+ iolog_path = NULL;
+ goto done;
+ }
+
+ /* Stash pointer to the I/O log for the event log. */
+ ctx->iolog_path = iolog_path + sizeof("iolog_path=") - 1;
+ ctx->iolog_file = ctx->iolog_path + 1 + strlen(dir);
+
+done:
+ debug_return_str(iolog_path);
+}
+
+static void
+cb_lookup(const struct sudoers_parse_tree *parse_tree,
+ const struct userspec *us, int user_match, const struct privilege *priv,
+ int host_match, const struct cmndspec *cs, int date_match, int runas_match,
+ int cmnd_match, void *closure)
+{
+ struct sudoers_match_info *info = closure;
+
+ if (cmnd_match != UNSPEC) {
+ info->us = us;
+ info->priv = priv;
+ info->cs = cs;
+ }
+}
+
+/*
+ * Find the command, perform a sudoers lookup, ask for a password as
+ * needed, and perform post-lokup checks. Logs success/failure.
+ * This is used by the check, list and validate plugin methods.
+ *
+ * Returns true if allowed, false if denied, -1 on error and
+ * -2 for usage error.
+ */
+static int
+sudoers_check_common(struct sudoers_context *ctx, int pwflag)
+{
+ struct sudoers_match_info match_info = { NULL };
+ int oldlocale, ret = -1;
+ unsigned int validated;
+ time_t now;
+ debug_decl(sudoers_check_common, SUDOERS_DEBUG_PLUGIN);
+
+ /* If given the -P option, set the "preserve_groups" flag. */
+ if (ISSET(ctx->mode, MODE_PRESERVE_GROUPS))
+ def_preserve_groups = true;
+
+ /* Find command in path and apply per-command Defaults. */
+ cmnd_status = set_cmnd(ctx);
+ if (cmnd_status == NOT_FOUND_ERROR)
+ goto done;
+
+ /* Is root even allowed to run sudo? */
+ if (ctx->user.uid == 0 && !def_root_sudo) {
+ /* Not an audit event (should it be?). */
+ sudo_warnx("%s",
+ U_("sudoers specifies that root is not allowed to sudo"));
+ ret = false;
+ goto done;
+ }
+
+ /* Check for -C overriding def_closefrom. */
+ if (ctx->user.closefrom >= 0 && ctx->user.closefrom != def_closefrom) {
+ if (!def_closefrom_override) {
+ log_warningx(ctx, SLOG_NO_STDERR|SLOG_AUDIT,
+ N_("user not allowed to override closefrom limit"));
+ sudo_warnx("%s", U_("you are not permitted to use the -C option"));
+ goto bad;
+ }
+ def_closefrom = ctx->user.closefrom;
+ }
+
+ /*
+ * Check sudoers sources, using the locale specified in sudoers.
+ */
+ time(&now);
+ sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
+ validated = sudoers_lookup(snl, ctx, now, cb_lookup, &match_info,
+ &cmnd_status, pwflag);
+ sudoers_setlocale(oldlocale, NULL);
+ if (ISSET(validated, VALIDATE_ERROR)) {
+ /* The lookup function should have printed an error. */
+ goto done;
+ }
+
+ if (match_info.us != NULL && match_info.us->file != NULL) {
+ free(ctx->source);
+ if (match_info.us->line != 0) {
+ if (asprintf(&ctx->source, "%s:%d:%d", match_info.us->file,
+ match_info.us->line, match_info.us->column) == -1)
+ ctx->source = NULL;
+ } else {
+ ctx->source = strdup(match_info.us->file);
+ }
+ if (ctx->source == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ }
+
+ if (ctx->runas.cmnd == NULL) {
+ if ((ctx->runas.cmnd = strdup(ctx->user.cmnd)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ }
+
+ /* Defer uid/gid checks until after defaults have been updated. */
+ if (unknown_runas_uid && !def_runas_allow_unknown_id) {
+ log_warningx(ctx, SLOG_AUDIT, N_("unknown user %s"),
+ ctx->runas.pw->pw_name);
+ goto done;
+ }
+ if (ctx->runas.gr != NULL) {
+ if (unknown_runas_gid && !def_runas_allow_unknown_id) {
+ log_warningx(ctx, SLOG_AUDIT, N_("unknown group %s"),
+ ctx->runas.gr->gr_name);
+ goto done;
+ }
+ }
+
+ /* If no command line args and "shell_noargs" is not set, error out. */
+ if (ISSET(ctx->mode, MODE_IMPLIED_SHELL) && !def_shell_noargs) {
+ /* Not an audit event. */
+ ret = -2; /* usage error */
+ goto done;
+ }
+
+ /* Bail if a tty is required and we don't have one. */
+ if (def_requiretty && !sudoers_tty_present(ctx)) {
+ log_warningx(ctx, SLOG_NO_STDERR|SLOG_AUDIT, N_("no tty"));
+ sudo_warnx("%s", U_("sorry, you must have a tty to run sudo"));
+ goto bad;
+ }
+
+ /* Check runas user's shell if running (or checking) a command. */
+ if (ISSET(ctx->mode, MODE_RUN|MODE_CHECK)) {
+ if (!user_shell_valid(ctx->runas.pw)) {
+ log_warningx(ctx, SLOG_RAW_MSG|SLOG_AUDIT,
+ N_("invalid shell for user %s: %s"),
+ ctx->runas.pw->pw_name, ctx->runas.pw->pw_shell);
+ goto bad;
+ }
+ }
+
+ /*
+ * We don't reset the environment for sudoedit or if the user
+ * specified the -E command line flag and they have setenv privs.
+ */
+ if (ISSET(ctx->mode, MODE_EDIT) ||
+ (ISSET(ctx->mode, MODE_PRESERVE_ENV) && def_setenv))
+ def_env_reset = false;
+
+ /* Build a new environment that avoids any nasty bits. */
+ if (!rebuild_env(ctx))
+ goto bad;
+
+ /* Require a password if sudoers says so. */
+ switch (check_user(ctx, validated, ctx->mode)) {
+ case AUTH_SUCCESS:
+ /* user authenticated successfully. */
+ break;
+ case AUTH_FAILURE:
+ /* Note: log_denial() calls audit for us. */
+ if (!ISSET(validated, VALIDATE_SUCCESS)) {
+ /* Only display a denial message if no password was read. */
+ if (!log_denial(ctx, validated, def_passwd_tries <= 0))
+ goto done;
+ }
+ goto bad;
+ default:
+ /* some other error, ret is -1. */
+ goto done;
+ }
+
+ /* Check whether ctx->runas.chroot is permitted (if specified). */
+ switch (check_user_runchroot(ctx->runas.chroot)) {
+ case true:
+ break;
+ case false:
+ log_warningx(ctx, SLOG_NO_STDERR|SLOG_AUDIT,
+ N_("user not allowed to change root directory to %s"),
+ ctx->runas.chroot);
+ sudo_warnx(U_("you are not permitted to use the -R option with %s"),
+ ctx->user.cmnd);
+ goto bad;
+ default:
+ goto done;
+ }
+
+ /* Check whether ctx->runas.cwd is permitted (if specified). */
+ switch (check_user_runcwd(ctx->runas.cwd)) {
+ case true:
+ break;
+ case false:
+ log_warningx(ctx, SLOG_NO_STDERR|SLOG_AUDIT,
+ N_("user not allowed to change directory to %s"), ctx->runas.cwd);
+ sudo_warnx(U_("you are not permitted to use the -D option with %s"),
+ ctx->user.cmnd);
+ goto bad;
+ default:
+ goto done;
+ }
+
+ /* If run as root with SUDO_USER set, set ctx->user.pw to that user. */
+ /* XXX - causes confusion when root is not listed in sudoers */
+ if (ISSET(ctx->mode, MODE_RUN|MODE_EDIT) && prev_user != NULL) {
+ if (ctx->user.uid == 0 && strcmp(prev_user, "root") != 0) {
+ struct passwd *pw;
+
+ if ((pw = sudo_getpwnam(prev_user)) != NULL) {
+ if (ctx->user.pw != NULL)
+ sudo_pw_delref(ctx->user.pw);
+ ctx->user.pw = pw;
+ }
+ }
+ }
+
+ /* If the user was not allowed to run the command we are done. */
+ if (!ISSET(validated, VALIDATE_SUCCESS)) {
+ /* Note: log_failure() calls audit for us. */
+ if (!log_failure(ctx, validated, cmnd_status))
+ goto done;
+ goto bad;
+ }
+
+ /*
+ * Check if the user is trying to run a setid binary in intercept mode.
+ * For the DSO intercept_type, we reject attempts to run setid binaries
+ * by default since the dynamic loader will clear LD_PRELOAD, defeating
+ * intercept.
+ */
+ if (def_intercept || ISSET(ctx->mode, MODE_POLICY_INTERCEPTED)) {
+ if (!def_intercept_allow_setid && ctx->user.cmnd_stat != NULL) {
+ if (ISSET(ctx->user.cmnd_stat->st_mode, S_ISUID|S_ISGID)) {
+ CLR(validated, VALIDATE_SUCCESS);
+ if (!log_denial(ctx, validated|FLAG_INTERCEPT_SETID, true))
+ goto done;
+ goto bad;
+ }
+ }
+ }
+
+ /* Create Ubuntu-style dot file to indicate sudo was successful. */
+ if (create_admin_success_flag(ctx) == -1)
+ goto done;
+
+ /* Finally tell the user if the command did not exist. */
+ if (cmnd_status == NOT_FOUND_DOT) {
+ audit_failure(ctx, ctx->runas.argv, N_("command in current directory"));
+ sudo_warnx(U_("ignoring \"%s\" found in '.'\nUse \"sudo ./%s\" if this is the \"%s\" you wish to run."), ctx->user.cmnd, ctx->user.cmnd, ctx->user.cmnd);
+ goto bad;
+ } else if (cmnd_status == NOT_FOUND) {
+ if (ISSET(ctx->mode, MODE_CHECK)) {
+ audit_failure(ctx, ctx->runas.argv, N_("%s: command not found"),
+ ctx->runas.argv[1]);
+ sudo_warnx(U_("%s: command not found"), ctx->runas.argv[1]);
+ } else {
+ audit_failure(ctx, ctx->runas.argv, N_("%s: command not found"),
+ ctx->user.cmnd);
+ sudo_warnx(U_("%s: command not found"), ctx->user.cmnd);
+ if (strncmp(ctx->user.cmnd, "cd", 2) == 0 && (ctx->user.cmnd[2] == '\0' ||
+ isblank((unsigned char)ctx->user.cmnd[2]))) {
+ sudo_warnx("%s",
+ U_("\"cd\" is a shell built-in command, it cannot be run directly."));
+ sudo_warnx("%s",
+ U_("the -s option may be used to run a privileged shell."));
+ sudo_warnx("%s",
+ U_("the -D option may be used to run a command in a specific directory."));
+ }
+ }
+ goto bad;
+ }
+
+ /* If user specified a timeout make sure sudoers allows it. */
+ if (!def_user_command_timeouts && ctx->user.timeout > 0) {
+ log_warningx(ctx, SLOG_NO_STDERR|SLOG_AUDIT,
+ N_("user not allowed to set a command timeout"));
+ sudo_warnx("%s",
+ U_("sorry, you are not allowed set a command timeout"));
+ goto bad;
+ }
+
+ /* If user specified env vars make sure sudoers allows it. */
+ if (ISSET(ctx->mode, MODE_RUN) && !def_setenv) {
+ if (ISSET(ctx->mode, MODE_PRESERVE_ENV)) {
+ log_warningx(ctx, SLOG_NO_STDERR|SLOG_AUDIT,
+ N_("user not allowed to preserve the environment"));
+ sudo_warnx("%s",
+ U_("sorry, you are not allowed to preserve the environment"));
+ goto bad;
+ } else {
+ if (!validate_env_vars(ctx, ctx->user.env_add))
+ goto bad;
+ }
+ }
+
+ ret = true;
+ goto done;
+
+bad:
+ ret = false;
+done:
+ debug_return_int(ret);
+}
+
+static bool need_reinit;
+
+/*
+ * Check whether the user is allowed to run the specified command.
+ * Returns true if allowed, false if denied, -1 on error and
+ * -2 for usage error.
+ */
+int
+sudoers_check_cmnd(int argc, char * const argv[], char *env_add[],
+ void *closure)
+{
+ char *iolog_path = NULL;
+ mode_t cmnd_umask = ACCESSPERMS;
+ int ret = -1;
+ debug_decl(sudoers_check_cmnd, SUDOERS_DEBUG_PLUGIN);
+
+ sudo_warn_set_locale_func(sudoers_warn_setlocale);
+
+ if (argc == 0) {
+ sudo_warnx("%s", U_("no command specified"));
+ debug_return_int(-1);
+ }
+
+ if (need_reinit) {
+ /* Was previous command intercepted? */
+ if (ISSET(sudoers_ctx.mode, MODE_RUN) && def_intercept)
+ SET(sudoers_ctx.mode, MODE_POLICY_INTERCEPTED);
+
+ /* Only certain mode flags are legal for intercepted commands. */
+ if (ISSET(sudoers_ctx.mode, MODE_POLICY_INTERCEPTED))
+ sudoers_ctx.mode &= MODE_INTERCEPT_MASK;
+
+ /* Re-initialize defaults if we are called multiple times. */
+ if (!sudoers_reinit_defaults(&sudoers_ctx))
+ debug_return_int(-1);
+ }
+ need_reinit = true;
+
+ unlimit_nproc();
+
+ if (!set_perms(&sudoers_ctx, PERM_INITIAL))
+ goto bad;
+
+ /* Environment variables specified on the command line. */
+ if (env_add != NULL && env_add[0] != NULL)
+ sudoers_ctx.user.env_add = env_add;
+
+ /*
+ * Make a local copy of argc/argv, with special handling for the
+ * '-i' option. We also allocate an extra slot for bash's --login.
+ */
+ if (sudoers_ctx.runas.argv != NULL && sudoers_ctx.runas.argv != sudoers_ctx.runas.argv_saved) {
+ sudoers_gc_remove(GC_PTR, sudoers_ctx.runas.argv);
+ free(sudoers_ctx.runas.argv);
+ }
+ sudoers_ctx.runas.argv = reallocarray(NULL, (size_t)argc + 2, sizeof(char *));
+ if (sudoers_ctx.runas.argv == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto error;
+ }
+ sudoers_gc_add(GC_PTR, sudoers_ctx.runas.argv);
+ memcpy(sudoers_ctx.runas.argv, argv, (size_t)argc * sizeof(char *));
+ sudoers_ctx.runas.argc = argc;
+ sudoers_ctx.runas.argv[sudoers_ctx.runas.argc] = NULL;
+ if (ISSET(sudoers_ctx.mode, MODE_LOGIN_SHELL) && sudoers_ctx.runas.pw != NULL) {
+ sudoers_ctx.runas.argv[0] = strdup(sudoers_ctx.runas.pw->pw_shell);
+ if (sudoers_ctx.runas.argv[0] == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto error;
+ }
+ sudoers_gc_add(GC_PTR, sudoers_ctx.runas.argv[0]);
+ }
+
+ ret = sudoers_check_common(&sudoers_ctx, 0);
+ if (ret != true)
+ goto done;
+
+ if (!remote_iologs) {
+ if (iolog_enabled && def_iolog_file && def_iolog_dir) {
+ if ((iolog_path = format_iolog_path(&sudoers_ctx)) == NULL) {
+ if (!def_ignore_iolog_errors)
+ goto error;
+ /* Unable to expand I/O log path, disable I/O logging. */
+ def_log_input = false;
+ def_log_output = false;
+ def_log_stdin = false;
+ def_log_stdout = false;
+ def_log_stderr = false;
+ def_log_ttyin = false;
+ def_log_ttyout = false;
+ }
+ }
+ }
+
+ /*
+ * Set umask based on sudoers.
+ * If user's umask is more restrictive, OR in those bits too
+ * unless umask_override is set.
+ */
+ if (def_umask != ACCESSPERMS) {
+ cmnd_umask = def_umask;
+ if (!def_umask_override)
+ cmnd_umask |= sudoers_ctx.user.umask;
+ }
+
+ if (ISSET(sudoers_ctx.mode, MODE_LOGIN_SHELL)) {
+ char *p;
+
+ /* Convert /bin/sh -> -sh so shell knows it is a login shell */
+ if ((p = strrchr(sudoers_ctx.runas.argv[0], '/')) == NULL)
+ p = sudoers_ctx.runas.argv[0];
+ *p = '-';
+ sudoers_ctx.runas.argv[0] = p;
+
+ /*
+ * Newer versions of bash require the --login option to be used
+ * in conjunction with the -c option even if the shell name starts
+ * with a '-'. Unfortunately, bash 1.x uses -login, not --login
+ * so this will cause an error for that.
+ */
+ if (sudoers_ctx.runas.argc > 1 && strcmp(sudoers_ctx.runas.argv[0], "-bash") == 0 &&
+ strcmp(sudoers_ctx.runas.argv[1], "-c") == 0) {
+ /* We allocated extra space for the --login above. */
+ memmove(&sudoers_ctx.runas.argv[2], &sudoers_ctx.runas.argv[1],
+ (size_t)sudoers_ctx.runas.argc * sizeof(char *));
+ sudoers_ctx.runas.argv[1] = (char *)"--login";
+ sudoers_ctx.runas.argc++;
+ }
+
+#ifdef _PATH_ENVIRONMENT
+ /* Insert system-wide environment variables. */
+ if (!read_env_file(&sudoers_ctx, _PATH_ENVIRONMENT, true, false))
+ sudo_warn("%s", _PATH_ENVIRONMENT);
+#endif
+#ifdef HAVE_LOGIN_CAP_H
+ /* Set environment based on login class. */
+ if (sudoers_ctx.runas.class) {
+ login_cap_t *lc = login_getclass(sudoers_ctx.runas.class);
+ if (lc != NULL) {
+ setusercontext(lc, sudoers_ctx.runas.pw,
+ sudoers_ctx.runas.pw->pw_uid, LOGIN_SETPATH|LOGIN_SETENV);
+ login_close(lc);
+ }
+ }
+#endif /* HAVE_LOGIN_CAP_H */
+ }
+
+ /* Insert system-wide environment variables. */
+ if (def_restricted_env_file) {
+ if (!read_env_file(&sudoers_ctx, def_restricted_env_file, false, true))
+ sudo_warn("%s", def_restricted_env_file);
+ }
+ if (def_env_file) {
+ if (!read_env_file(&sudoers_ctx, def_env_file, false, false))
+ sudo_warn("%s", def_env_file);
+ }
+
+ /* Insert user-specified environment variables. */
+ if (!insert_env_vars(sudoers_ctx.user.env_add)) {
+ sudo_warnx("%s",
+ U_("error setting user-specified environment variables"));
+ goto error;
+ }
+
+ /* Note: must call audit before uid change. */
+ if (ISSET(sudoers_ctx.mode, MODE_EDIT)) {
+ const char *env_editor = NULL;
+ char **edit_argv;
+ int edit_argc;
+
+ sudoers_ctx.sudoedit_nfiles = sudoers_ctx.runas.argc - 1;
+ free(sudoers_ctx.runas.cmnd);
+ sudoers_ctx.runas.cmnd = find_editor(sudoers_ctx.sudoedit_nfiles,
+ sudoers_ctx.runas.argv + 1, &edit_argc, &edit_argv, NULL, &env_editor);
+ if (sudoers_ctx.runas.cmnd == NULL) {
+ switch (errno) {
+ case ENOENT:
+ audit_failure(&sudoers_ctx, sudoers_ctx.runas.argv,
+ N_("%s: command not found"),
+ env_editor ? env_editor : def_editor);
+ sudo_warnx(U_("%s: command not found"),
+ env_editor ? env_editor : def_editor);
+ goto error;
+ case EINVAL:
+ if (def_env_editor && env_editor != NULL) {
+ /* User tried to do something funny with the editor. */
+ log_warningx(&sudoers_ctx,
+ SLOG_NO_STDERR|SLOG_AUDIT|SLOG_SEND_MAIL,
+ "invalid user-specified editor: %s", env_editor);
+ goto error;
+ }
+ FALLTHROUGH;
+ default:
+ goto error;
+ }
+ }
+ /* find_editor() already g/c'd edit_argv[] */
+ if (sudoers_ctx.runas.argv != sudoers_ctx.runas.argv_saved) {
+ sudoers_gc_remove(GC_PTR, sudoers_ctx.runas.argv);
+ free(sudoers_ctx.runas.argv);
+ }
+ sudoers_ctx.runas.argv = edit_argv;
+ sudoers_ctx.runas.argc = edit_argc;
+
+ /* We want to run the editor with the unmodified environment. */
+ env_swap_old();
+ }
+
+ /* Save the initial command and argv so we have it for exit logging. */
+ if (sudoers_ctx.runas.cmnd_saved == NULL) {
+ sudoers_ctx.runas.cmnd_saved = strdup(sudoers_ctx.runas.cmnd);
+ if (sudoers_ctx.runas.cmnd_saved == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto error;
+ }
+ sudoers_ctx.runas.argv_saved = sudoers_ctx.runas.argv;
+ }
+
+ ret = true;
+ goto done;
+
+bad:
+ ret = false;
+ goto done;
+
+error:
+ ret = -1;
+
+done:
+ mail_parse_errors(&sudoers_ctx);
+
+ if (def_group_plugin)
+ group_plugin_unload();
+ reset_parser();
+
+ if (ret == -1) {
+ /* Free locally-allocated strings. */
+ free(iolog_path);
+ } else {
+ /* Store settings to pass back to front-end. */
+ if (!sudoers_policy_store_result(&sudoers_ctx, ret,
+ sudoers_ctx.runas.argv, env_get(), cmnd_umask, iolog_path, closure))
+ ret = -1;
+ }
+
+ /* Zero out stashed copy of environment, it is owned by the front-end. */
+ (void)env_init(NULL);
+
+ if (!rewind_perms())
+ ret = -1;
+
+ restore_nproc();
+
+ sudo_warn_set_locale_func(NULL);
+
+ debug_return_int(ret);
+}
+
+/*
+ * Validate the user and update their timestamp file entry.
+ * Returns true if allowed, false if denied, -1 on error and
+ * -2 for usage error.
+ */
+int
+sudoers_validate_user(void)
+{
+ int ret = -1;
+ debug_decl(sudoers_validate_user, SUDOERS_DEBUG_PLUGIN);
+
+ sudo_warn_set_locale_func(sudoers_warn_setlocale);
+
+ unlimit_nproc();
+
+ if (!set_perms(&sudoers_ctx, PERM_INITIAL))
+ goto done;
+
+ sudoers_ctx.runas.argv = reallocarray(NULL, 2, sizeof(char *));
+ if (sudoers_ctx.runas.argv == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ sudoers_gc_add(GC_PTR, sudoers_ctx.runas.argv);
+ sudoers_ctx.runas.argv[0] = (char *)"validate";
+ sudoers_ctx.runas.argv[1] = NULL;
+ sudoers_ctx.runas.argc = 2;
+
+ ret = sudoers_check_common(&sudoers_ctx, I_VERIFYPW);
+
+done:
+ mail_parse_errors(&sudoers_ctx);
+
+ if (def_group_plugin)
+ group_plugin_unload();
+ reset_parser();
+ env_init(NULL);
+
+ if (!rewind_perms())
+ ret = -1;
+
+ restore_nproc();
+
+ sudo_warn_set_locale_func(NULL);
+
+ debug_return_int(ret);
+}
+
+/*
+ * List a user's privileges or check whether a specific command may be run.
+ * Returns true if allowed, false if denied, -1 on error and
+ * -2 for usage error.
+ */
+int
+sudoers_list(int argc, char * const argv[], const char *list_user, int verbose)
+{
+ struct passwd *pw;
+ int ret = -1;
+ debug_decl(sudoers_list, SUDOERS_DEBUG_PLUGIN);
+
+ sudo_warn_set_locale_func(sudoers_warn_setlocale);
+
+ unlimit_nproc();
+
+ if (!set_perms(&sudoers_ctx, PERM_INITIAL))
+ goto done;
+
+ if (list_user) {
+ if (sudoers_ctx.runas.list_pw != NULL)
+ sudo_pw_delref(sudoers_ctx.runas.list_pw);
+ sudoers_ctx.runas.list_pw = sudo_getpwnam(list_user);
+ if (sudoers_ctx.runas.list_pw == NULL) {
+ sudo_warnx(U_("unknown user %s"), list_user);
+ goto done;
+ }
+ }
+
+ sudoers_ctx.runas.argv = reallocarray(NULL, (size_t)argc + 2, sizeof(char *));
+ if (sudoers_ctx.runas.argv == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ sudoers_gc_add(GC_PTR, sudoers_ctx.runas.argv);
+ sudoers_ctx.runas.argv[0] = (char *)"list";
+ if (argc != 0)
+ memcpy(sudoers_ctx.runas.argv + 1, argv, (size_t)argc * sizeof(char *));
+ sudoers_ctx.runas.argc = argc + 1;
+ sudoers_ctx.runas.argv[sudoers_ctx.runas.argc] = NULL;
+
+ ret = sudoers_check_common(&sudoers_ctx, I_LISTPW);
+ if (ret != true)
+ goto done;
+
+ pw = sudoers_ctx.runas.list_pw ? sudoers_ctx.runas.list_pw : sudoers_ctx.user.pw;
+ if (ISSET(sudoers_ctx.mode, MODE_CHECK))
+ ret = display_cmnd(&sudoers_ctx, snl, pw, verbose);
+ else
+ ret = display_privs(&sudoers_ctx, snl, pw, verbose);
+
+done:
+ mail_parse_errors(&sudoers_ctx);
+
+ if (def_group_plugin)
+ group_plugin_unload();
+ reset_parser();
+ env_init(NULL);
+
+ if (!rewind_perms())
+ ret = -1;
+
+ restore_nproc();
+
+ sudo_warn_set_locale_func(NULL);
+
+ debug_return_int(ret);
+}
+
+/*
+ * Initialize timezone and fill in ctx->user.
+ */
+static bool
+init_vars(struct sudoers_context *ctx, char * const envp[])
+{
+ char * const * ep;
+ bool unknown_user = false;
+ debug_decl(init_vars, SUDOERS_DEBUG_PLUGIN);
+
+ if (!sudoers_initlocale(setlocale(LC_ALL, NULL), def_sudoers_locale)) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+
+#define MATCHES(s, v) \
+ (strncmp((s), (v), sizeof(v) - 1) == 0 && (s)[sizeof(v) - 1] != '\0')
+
+ ctx->user.envp = envp;
+ for (ep = ctx->user.envp; *ep; ep++) {
+ switch (**ep) {
+ case 'K':
+ if (MATCHES(*ep, "KRB5CCNAME="))
+ ctx->user.ccname = *ep + sizeof("KRB5CCNAME=") - 1;
+ break;
+ case 'P':
+ if (MATCHES(*ep, "PATH="))
+ ctx->user.path = *ep + sizeof("PATH=") - 1;
+ break;
+ case 'S':
+ if (MATCHES(*ep, "SUDO_PROMPT=")) {
+ /* Don't override "sudo -p prompt" */
+ if (ctx->user.prompt == NULL)
+ ctx->user.prompt = *ep + sizeof("SUDO_PROMPT=") - 1;
+ break;
+ }
+ if (MATCHES(*ep, "SUDO_USER="))
+ prev_user = *ep + sizeof("SUDO_USER=") - 1;
+ break;
+ }
+ }
+#undef MATCHES
+
+ if (ctx->user.pw == NULL) {
+ /* Fake a struct passwd for the call to log_warningx(). */
+ ctx->user.pw = sudo_mkpwent(ctx->user.name, ctx->user.uid,
+ ctx->user.gid, NULL, NULL);
+ unknown_user = true;
+ }
+ if (ctx->user.gid_list == NULL)
+ ctx->user.gid_list = sudo_get_gidlist(ctx->user.pw, ENTRY_TYPE_ANY);
+
+ /* Store initialize permissions so we can restore them later. */
+ if (!set_perms(ctx, PERM_INITIAL))
+ debug_return_bool(false);
+
+ /* Set parse callbacks */
+ set_callbacks();
+
+ /* It is now safe to use log_warningx() and set_perms() */
+ if (unknown_user) {
+ log_warningx(ctx, SLOG_SEND_MAIL, N_("unknown user %s"), ctx->user.name);
+ debug_return_bool(false);
+ }
+
+ /*
+ * Set runas passwd/group entries based on command line or sudoers.
+ * Note that if runas_group was specified without runas_user we
+ * run the command as the invoking user.
+ */
+ if (ctx->runas.group != NULL) {
+ if (!set_runasgr(ctx, ctx->runas.group, false))
+ debug_return_bool(false);
+ if (!set_runaspw(ctx, ctx->runas.user ?
+ ctx->runas.user : ctx->user.name, false))
+ debug_return_bool(false);
+ } else {
+ if (!set_runaspw(ctx, ctx->runas.user ?
+ ctx->runas.user : def_runas_default, false))
+ debug_return_bool(false);
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Fill in ctx->user.cmnd and ctx->user.cmnd_stat variables.
+ * Does not fill in ctx->user.cmnd_base.
+ */
+int
+set_cmnd_path(struct sudoers_context *ctx, const char *runchroot)
+{
+ struct sudoers_pivot pivot_state = SUDOERS_PIVOT_INITIALIZER;
+ const char *cmnd_in;
+ char *cmnd_out = NULL;
+ char *path = ctx->user.path;
+ int ret;
+ debug_decl(set_cmnd_path, SUDOERS_DEBUG_PLUGIN);
+
+ cmnd_in = ISSET(ctx->mode, MODE_CHECK) ?
+ ctx->runas.argv[1] : ctx->runas.argv[0];
+
+ free(ctx->user.cmnd_list);
+ ctx->user.cmnd_list = NULL;
+ free(ctx->user.cmnd);
+ ctx->user.cmnd = NULL;
+ canon_path_free(ctx->user.cmnd_dir);
+ ctx->user.cmnd_dir = NULL;
+ if (def_secure_path && !user_is_exempt(ctx))
+ path = def_secure_path;
+
+ /* Pivot root. */
+ if (runchroot != NULL) {
+ if (!pivot_root(runchroot, &pivot_state))
+ goto error;
+ }
+
+ ret = resolve_cmnd(ctx, cmnd_in, &cmnd_out, path);
+ if (ret == FOUND) {
+ char *slash = strrchr(cmnd_out, '/');
+ if (slash != NULL) {
+ *slash = '\0';
+ ctx->user.cmnd_dir = canon_path(cmnd_out);
+ if (ctx->user.cmnd_dir == NULL && errno == ENOMEM)
+ goto error;
+ *slash = '/';
+ }
+ }
+
+ if (ISSET(ctx->mode, MODE_CHECK))
+ ctx->user.cmnd_list = cmnd_out;
+ else
+ ctx->user.cmnd = cmnd_out;
+
+ /* Restore root. */
+ if (runchroot != NULL)
+ (void)unpivot_root(&pivot_state);
+
+ debug_return_int(ret);
+error:
+ if (runchroot != NULL)
+ (void)unpivot_root(&pivot_state);
+ free(cmnd_out);
+ debug_return_int(NOT_FOUND_ERROR);
+}
+
+/*
+ * Fill in ctx->user.cmnd, ctx->user.cmnd_stat and cmnd_status variables.
+ * Does not fill in ctx->user.cmnd_base.
+ */
+void
+set_cmnd_status(struct sudoers_context *ctx, const char *runchroot)
+{
+ cmnd_status = set_cmnd_path(ctx, runchroot);
+}
+
+/*
+ * Fill in ctx->user.cmnd, ctx->user.cmnd_args, ctx->user.cmnd_base and
+ * ctx->user.cmnd_stat variables and apply any command-specific defaults entries.
+ */
+static int
+set_cmnd(struct sudoers_context *ctx)
+{
+ struct sudo_nss *nss;
+ int ret = FOUND;
+ debug_decl(set_cmnd, SUDOERS_DEBUG_PLUGIN);
+
+ /* Allocate ctx->user.cmnd_stat for find_path() and match functions. */
+ free(ctx->user.cmnd_stat);
+ ctx->user.cmnd_stat = calloc(1, sizeof(struct stat));
+ if (ctx->user.cmnd_stat == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(NOT_FOUND_ERROR);
+ }
+
+ /* Re-initialize for when we are called multiple times. */
+ free(ctx->runas.cmnd);
+ ctx->runas.cmnd = NULL;
+
+ if (ISSET(ctx->mode, MODE_RUN|MODE_EDIT|MODE_CHECK)) {
+ if (!ISSET(ctx->mode, MODE_EDIT)) {
+ const char *runchroot = ctx->runas.chroot;
+ if (runchroot == NULL && def_runchroot != NULL &&
+ strcmp(def_runchroot, "*") != 0)
+ runchroot = def_runchroot;
+
+ ret = set_cmnd_path(ctx, runchroot);
+ if (ret == NOT_FOUND_ERROR) {
+ if (errno == ENAMETOOLONG) {
+ audit_failure(ctx, ctx->runas.argv, N_("command too long"));
+ }
+ log_warning(ctx, 0, "%s", ctx->runas.argv[0]);
+ debug_return_int(ret);
+ }
+ }
+
+ /* set ctx->user.cmnd_args */
+ free(ctx->user.cmnd_args);
+ ctx->user.cmnd_args = NULL;
+ if (ISSET(ctx->mode, MODE_CHECK)) {
+ if (ctx->runas.argc > 2) {
+ /* Skip the command being listed in ctx->runas.argv[1]. */
+ ctx->user.cmnd_args = strvec_join(ctx->runas.argv + 2, ' ', NULL);
+ if (ctx->user.cmnd_args == NULL)
+ debug_return_int(NOT_FOUND_ERROR);
+ }
+ } else if (ctx->runas.argc > 1) {
+ if (ISSET(ctx->mode, MODE_SHELL|MODE_LOGIN_SHELL) &&
+ ISSET(ctx->mode, MODE_RUN)) {
+ /*
+ * When running a command via a shell, the sudo front-end
+ * escapes potential meta chars. We unescape non-spaces
+ * for sudoers matching and logging purposes.
+ * TODO: move escaping to the policy plugin instead
+ */
+ ctx->user.cmnd_args = strvec_join(ctx->runas.argv + 1, ' ',
+ strlcpy_unescape);
+ } else {
+ ctx->user.cmnd_args = strvec_join(ctx->runas.argv + 1, ' ',
+ NULL);
+ }
+ if (ctx->user.cmnd_args == NULL)
+ debug_return_int(NOT_FOUND_ERROR);
+ }
+ }
+ if (ctx->user.cmnd == NULL) {
+ ctx->user.cmnd = strdup(ctx->runas.argv[0]);
+ if (ctx->user.cmnd == NULL)
+ debug_return_int(NOT_FOUND_ERROR);
+ }
+ ctx->user.cmnd_base = sudo_basename(ctx->user.cmnd);
+
+ /* Convert "sudo sudoedit" -> "sudoedit" */
+ if (ISSET(ctx->mode, MODE_RUN) && strcmp(ctx->user.cmnd_base, "sudoedit") == 0) {
+ char *new_cmnd;
+
+ CLR(ctx->mode, MODE_RUN);
+ SET(ctx->mode, MODE_EDIT);
+ sudo_warnx("%s", U_("sudoedit doesn't need to be run via sudo"));
+ if ((new_cmnd = strdup("sudoedit")) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(NOT_FOUND_ERROR);
+ }
+ free(ctx->user.cmnd);
+ ctx->user.cmnd_base = ctx->user.cmnd = new_cmnd;
+ }
+
+ TAILQ_FOREACH(nss, snl, entries) {
+ /* Missing/invalid defaults is not a fatal error. */
+ (void)update_defaults(ctx, nss->parse_tree, NULL, SETDEF_CMND, false);
+ }
+
+ debug_return_int(ret);
+}
+
+static int
+open_file(const char *path, int flags)
+{
+ int fd;
+ debug_decl(open_file, SUDOERS_DEBUG_PLUGIN);
+
+ if (!set_perms(NULL, PERM_SUDOERS))
+ debug_return_int(-1);
+
+ fd = open(path, flags);
+ if (fd == -1 && errno == EACCES && geteuid() != ROOT_UID) {
+ /*
+ * If we tried to open sudoers as non-root but got EACCES,
+ * try again as root.
+ */
+ int serrno = errno;
+ if (restore_perms() && set_perms(NULL, PERM_ROOT))
+ fd = open(path, flags);
+ errno = serrno;
+ }
+ if (!restore_perms()) {
+ /* unable to change back to root */
+ if (fd != -1) {
+ close(fd);
+ fd = -1;
+ }
+ }
+
+ debug_return_int(fd);
+}
+
+/*
+ * Open sudoers file and check mode/owner/type.
+ * Returns a handle to the sudoers file or NULL on error.
+ */
+FILE *
+open_sudoers(const char *path, char **outfile, bool doedit, bool *keepopen)
+{
+ char fname[PATH_MAX];
+ FILE *fp = NULL;
+ struct stat sb;
+ int error, fd;
+ debug_decl(open_sudoers, SUDOERS_DEBUG_PLUGIN);
+
+ fd = sudo_open_conf_path(path, fname, sizeof(fname), open_file);
+ if (sudoers_ctx.parser_conf.ignore_perms) {
+ /* Skip sudoers security checks when ignore_perms is set. */
+ if (fd == -1 || fstat(fd, &sb) == -1)
+ error = SUDO_PATH_MISSING;
+ else
+ error = SUDO_PATH_SECURE;
+ } else {
+ error = sudo_secure_fd(fd, S_IFREG, sudoers_file_uid(),
+ sudoers_file_gid(), &sb);
+ }
+ switch (error) {
+ case SUDO_PATH_SECURE:
+ /*
+ * Make sure we can read the file so we can present the
+ * user with a reasonable error message (unlike the lexer).
+ */
+ if ((fp = fdopen(fd, "r")) == NULL) {
+ log_warning(&sudoers_ctx, SLOG_PARSE_ERROR,
+ N_("unable to open %s"), fname);
+ } else {
+ fd = -1;
+ if (sb.st_size != 0 && fgetc(fp) == EOF) {
+ log_warning(&sudoers_ctx, SLOG_PARSE_ERROR,
+ N_("unable to read %s"), fname);
+ fclose(fp);
+ fp = NULL;
+ } else {
+ /* Rewind fp and set close on exec flag. */
+ rewind(fp);
+ (void)fcntl(fileno(fp), F_SETFD, 1);
+ if (outfile != NULL) {
+ *outfile = sudo_rcstr_dup(fname);
+ if (*outfile == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ fclose(fp);
+ fp = NULL;
+ }
+ }
+ }
+ }
+ break;
+ case SUDO_PATH_MISSING:
+ log_warning(&sudoers_ctx, SLOG_PARSE_ERROR,
+ N_("unable to open %s"), path);
+ break;
+ case SUDO_PATH_BAD_TYPE:
+ log_warningx(&sudoers_ctx, SLOG_PARSE_ERROR,
+ N_("%s is not a regular file"), fname);
+ break;
+ case SUDO_PATH_WRONG_OWNER:
+ log_warningx(&sudoers_ctx, SLOG_PARSE_ERROR,
+ N_("%s is owned by uid %u, should be %u"), fname,
+ (unsigned int)sb.st_uid, (unsigned int)sudoers_file_uid());
+ break;
+ case SUDO_PATH_WORLD_WRITABLE:
+ log_warningx(&sudoers_ctx, SLOG_PARSE_ERROR,
+ N_("%s is world writable"), fname);
+ break;
+ case SUDO_PATH_GROUP_WRITABLE:
+ log_warningx(&sudoers_ctx, SLOG_PARSE_ERROR,
+ N_("%s is owned by gid %u, should be %u"), fname,
+ (unsigned int)sb.st_gid, (unsigned int)sudoers_file_gid());
+ break;
+ default:
+ sudo_warnx("%s: internal error, unexpected error %d", __func__, error);
+ break;
+ }
+
+ if (fp == NULL && fd != -1)
+ close(fd);
+
+ debug_return_ptr(fp);
+}
+
+#ifdef HAVE_LOGIN_CAP_H
+static bool
+set_loginclass(struct sudoers_context *ctx)
+{
+ const struct passwd *pw = ctx->runas.pw ? ctx->runas.pw : ctx->user.pw;
+ const unsigned int errflags = SLOG_RAW_MSG;
+ login_cap_t *lc;
+ bool ret = true;
+ debug_decl(set_loginclass, SUDOERS_DEBUG_PLUGIN);
+
+ if (!def_use_loginclass)
+ goto done;
+
+ if (ctx->runas.class && strcmp(ctx->runas.class, "-") != 0) {
+ if (ctx->user.uid != 0 && pw->pw_uid != 0) {
+ sudo_warnx(U_("only root can use \"-c %s\""), ctx->runas.class);
+ ret = false;
+ goto done;
+ }
+ } else {
+ ctx->runas.class = pw->pw_class;
+ if (!ctx->runas.class || !*ctx->runas.class)
+ ctx->runas.class = (char *)
+ ((pw->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS);
+ }
+
+ /* Make sure specified login class is valid. */
+ lc = login_getclass(ctx->runas.class);
+ if (!lc || !lc->lc_class || strcmp(lc->lc_class, ctx->runas.class) != 0) {
+ /*
+ * Don't make it an error if the user didn't specify the login
+ * class themselves. We do this because if login.conf gets
+ * corrupted we want the admin to be able to use sudo to fix it.
+ */
+ log_warningx(ctx, errflags, N_("unknown login class %s"),
+ ctx->runas.class);
+ def_use_loginclass = false;
+ if (ctx->runas.class)
+ ret = false;
+ }
+ login_close(lc);
+done:
+ debug_return_bool(ret);
+}
+#else
+static bool
+set_loginclass(struct sudoers_context *ctx)
+{
+ return true;
+}
+#endif /* HAVE_LOGIN_CAP_H */
+
+/*
+ * Get passwd entry for the user we are going to run commands as
+ * and store it in ctx->runas.pw. By default, commands run as "root".
+ */
+static bool
+set_runaspw(struct sudoers_context *ctx, const char *user, bool quiet)
+{
+ struct passwd *pw = NULL;
+ debug_decl(set_runaspw, SUDOERS_DEBUG_PLUGIN);
+
+ unknown_runas_uid = false;
+ if (*user == '#') {
+ const char *errstr;
+ uid_t uid = sudo_strtoid(user + 1, &errstr);
+ if (errstr == NULL) {
+ if ((pw = sudo_getpwuid(uid)) == NULL) {
+ unknown_runas_uid = true;
+ pw = sudo_fakepwnam(user, ctx->user.gid);
+ }
+ }
+ }
+ if (pw == NULL) {
+ if ((pw = sudo_getpwnam(user)) == NULL) {
+ if (!quiet)
+ log_warningx(ctx, SLOG_AUDIT, N_("unknown user %s"), user);
+ debug_return_bool(false);
+ }
+ }
+ if (ctx->runas.pw != NULL)
+ sudo_pw_delref(ctx->runas.pw);
+ ctx->runas.pw = pw;
+ debug_return_bool(true);
+}
+
+/*
+ * Get group entry for the group we are going to run commands as
+ * and store it in ctx->runas.gr.
+ */
+static bool
+set_runasgr(struct sudoers_context *ctx, const char *group, bool quiet)
+{
+ struct group *gr = NULL;
+ debug_decl(set_runasgr, SUDOERS_DEBUG_PLUGIN);
+
+ unknown_runas_gid = false;
+ if (*group == '#') {
+ const char *errstr;
+ gid_t gid = sudo_strtoid(group + 1, &errstr);
+ if (errstr == NULL) {
+ if ((gr = sudo_getgrgid(gid)) == NULL) {
+ unknown_runas_gid = true;
+ gr = sudo_fakegrnam(group);
+ }
+ }
+ }
+ if (gr == NULL) {
+ if ((gr = sudo_getgrnam(group)) == NULL) {
+ if (!quiet)
+ log_warningx(ctx, SLOG_AUDIT, N_("unknown group %s"), group);
+ debug_return_bool(false);
+ }
+ }
+ if (ctx->runas.gr != NULL)
+ sudo_gr_delref(ctx->runas.gr);
+ ctx->runas.gr = gr;
+ debug_return_bool(true);
+}
+
+/*
+ * Callback for runas_default sudoers setting.
+ */
+bool
+cb_runas_default(struct sudoers_context *ctx, const char *file, int line,
+ int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_runas_default, SUDOERS_DEBUG_PLUGIN);
+
+ /* Only reset runaspw if user didn't specify one. */
+ if (ctx->runas.user == NULL && ctx->runas.group == NULL)
+ debug_return_bool(set_runaspw(ctx, sd_un->str, true));
+ debug_return_bool(true);
+}
+
+/*
+ * Cleanup hook for sudo_fatal()/sudo_fatalx()
+ * Also called at policy close time.
+ */
+void
+sudoers_cleanup(void)
+{
+ struct sudo_nss *nss;
+ struct defaults *def;
+ debug_decl(sudoers_cleanup, SUDOERS_DEBUG_PLUGIN);
+
+ if (snl != NULL) {
+ TAILQ_FOREACH(nss, snl, entries) {
+ nss->close(&sudoers_ctx, nss);
+ }
+ snl = NULL;
+ reset_parser();
+ }
+ while ((def = TAILQ_FIRST(&initial_defaults)) != NULL) {
+ TAILQ_REMOVE(&initial_defaults, def, entries);
+ free(def->var);
+ free(def->val);
+ free(def);
+ }
+ need_reinit = false;
+ if (def_group_plugin)
+ group_plugin_unload();
+ sudoers_ctx_free(&sudoers_ctx);
+ sudo_freepwcache();
+ sudo_freegrcache();
+ canon_path_free_cache();
+
+ /* We must free the cached environment before running g/c. */
+ env_free();
+
+ /* Run garbage collector. */
+ sudoers_gc_run();
+
+ /* Clear globals */
+ prev_user = NULL;
+
+ debug_return;
+}
+
+bool
+sudoers_set_mode(unsigned int flags, unsigned int mask)
+{
+ SET(sudoers_ctx.mode, flags);
+ return ((sudoers_ctx.mode & mask) == sudoers_ctx.mode);
+}
+
+const struct sudoers_context *
+sudoers_get_context(void)
+{
+ return &sudoers_ctx;
+}
diff --git a/plugins/sudoers/sudoers.exp b/plugins/sudoers/sudoers.exp
new file mode 100644
index 0000000..f0b2c97
--- /dev/null
+++ b/plugins/sudoers/sudoers.exp
@@ -0,0 +1,7 @@
+sudoers_policy
+sudoers_io
+sudoers_audit
+sudo_getgrgid
+sudo_getgrnam
+sudo_gr_addref
+sudo_gr_delref
diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h
new file mode 100644
index 0000000..c7f386b
--- /dev/null
+++ b/plugins/sudoers/sudoers.h
@@ -0,0 +1,518 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1993-1996, 1998-2005, 2007-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#ifndef SUDOERS_SUDOERS_H
+#define SUDOERS_SUDOERS_H
+
+#include <sys/types.h> /* for gid_t, mode_t, pid_t, size_t, uid_t */
+#include <limits.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+
+#define DEFAULT_TEXT_DOMAIN "sudoers"
+
+#include <pathnames.h>
+#include <sudo_compat.h>
+#include <sudo_conf.h>
+#include <sudo_eventlog.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_nss.h>
+#include <sudo_plugin.h>
+#include <sudo_queue.h>
+#include <sudo_util.h>
+#include <sudoers_debug.h>
+
+#include <defaults.h>
+#include <logging.h>
+#include <parse.h>
+#include <pivot.h>
+
+/*
+ * Info passed in from the sudo front-end.
+ */
+struct sudoers_open_info {
+ char * const *settings;
+ char * const *user_info;
+ char * const *plugin_args;
+};
+
+/*
+ * Supplementary group IDs for a user.
+ */
+struct gid_list {
+ int ngids;
+ GETGROUPS_T *gids;
+};
+
+/*
+ * Supplementary group names for a user.
+ */
+struct group_list {
+ int ngroups;
+ char **groups;
+};
+
+/*
+ * Parse configuration settings.
+ */
+struct sudoers_parser_config {
+ const char *sudoers_path;
+ int strict;
+ int verbose;
+ bool recovery;
+ bool ignore_perms;
+ mode_t sudoers_mode;
+ uid_t sudoers_uid;
+ gid_t sudoers_gid;
+};
+#define SUDOERS_PARSER_CONFIG_INITIALIZER { \
+ .sudoers_path = NULL, \
+ .strict = false, \
+ .verbose = 1, \
+ .recovery = true, \
+ .ignore_perms = false, \
+ .sudoers_mode = SUDOERS_MODE, \
+ .sudoers_uid = SUDOERS_UID, \
+ .sudoers_gid = SUDOERS_GID \
+}
+
+/*
+ * Settings passed in from the sudo front-end.
+ */
+struct sudoers_plugin_settings {
+ const char *plugin_dir;
+ const char *ldap_conf;
+ const char *ldap_secret;
+ unsigned int flags;
+};
+#define SUDOERS_PLUGIN_SETTINGS_INITIALIZER { \
+ .plugin_dir = _PATH_SUDO_PLUGIN_DIR, \
+ .ldap_conf = _PATH_LDAP_CONF, \
+ .ldap_secret = _PATH_LDAP_SECRET \
+}
+
+/*
+ * Info pertaining to the invoking user.
+ */
+struct sudoers_user_context {
+ struct passwd *pw;
+ struct stat *cmnd_stat;
+ char *cwd;
+ char *name;
+ char *path;
+ char *tty;
+ char *ttypath;
+ char *host;
+ char *shost;
+ char *prompt;
+ char *cmnd;
+ char *cmnd_args;
+ char *cmnd_base;
+ char *cmnd_dir;
+ char *cmnd_list;
+ char *ccname;
+ struct gid_list *gid_list;
+ char * const * envp;
+ char * const * env_add;
+ int closefrom;
+ int lines;
+ int cols;
+ int timeout;
+ mode_t umask;
+ uid_t euid;
+ uid_t uid;
+ uid_t egid;
+ uid_t gid;
+ pid_t pid;
+ pid_t ppid;
+ pid_t sid;
+ pid_t tcpgid;
+};
+
+/*
+ * Info pertaining to the runas user.
+ */
+struct sudoers_runas_context {
+ int execfd;
+ int argc;
+ char **argv;
+ char **argv_saved;
+ struct passwd *pw;
+ struct group *gr;
+ struct passwd *list_pw;
+ char *chroot;
+ char *class;
+ char *cmnd;
+ char *cmnd_saved;
+ char *cwd;
+ char *group;
+ char *host;
+ char *shost;
+ char *user;
+#ifdef HAVE_SELINUX
+ char *role;
+ char *type;
+#endif
+#ifdef HAVE_APPARMOR
+ char *apparmor_profile;
+#endif
+#ifdef HAVE_PRIV_SET
+ char *privs;
+ char *limitprivs;
+#endif
+};
+
+/*
+ * Global configuration for the sudoers module.
+ */
+struct sudoers_context {
+ struct sudoers_parser_config parser_conf;
+ struct sudoers_plugin_settings settings;
+ struct sudoers_user_context user;
+ struct sudoers_runas_context runas;
+ struct timespec submit_time;
+ char *source;
+ char *iolog_file;
+ char *iolog_dir;
+ char *iolog_path;
+ int sudoedit_nfiles;
+ unsigned int mode;
+ char uuid_str[37];
+};
+#define SUDOERS_CONTEXT_INITIALIZER { \
+ SUDOERS_PARSER_CONFIG_INITIALIZER, \
+ SUDOERS_PLUGIN_SETTINGS_INITIALIZER, \
+}
+
+/*
+ * sudo_get_gidlist() type values
+ */
+#define ENTRY_TYPE_ANY 0x00
+#define ENTRY_TYPE_QUERIED 0x01
+#define ENTRY_TYPE_FRONTEND 0x02
+
+/*
+ * sudoers_plugin_settings.flag values
+ */
+#define RUNAS_USER_SPECIFIED 0x01U
+#define RUNAS_GROUP_SPECIFIED 0x02U
+#define CAN_INTERCEPT_SETID 0x04U
+#define HAVE_INTERCEPT_PTRACE 0x08U
+#define USER_INTERCEPT_SETID 0x10U
+
+/*
+ * Return values for sudoers_lookup(), also used as arguments for log_auth()
+ * Note: cannot use '0' as a value here.
+ */
+#define VALIDATE_ERROR 0x001U
+#define VALIDATE_SUCCESS 0x002U
+#define VALIDATE_FAILURE 0x004U
+#define FLAG_CHECK_USER 0x010U
+#define FLAG_NO_USER 0x020U
+#define FLAG_NO_HOST 0x040U
+#define FLAG_NO_CHECK 0x080U
+#define FLAG_NO_USER_INPUT 0x100U
+#define FLAG_BAD_PASSWORD 0x200U
+#define FLAG_INTERCEPT_SETID 0x400U
+
+/*
+ * Return values for check_user() (rowhammer resistant).
+ */
+#undef AUTH_SUCCESS
+#define AUTH_SUCCESS 0x52a2925 /* 0101001010100010100100100101 */
+#undef AUTH_FAILURE
+#define AUTH_FAILURE 0xad5d6da /* 1010110101011101011011011010 */
+#undef AUTH_ERROR
+#define AUTH_ERROR 0x1fc8d3ac /* 11111110010001101001110101100 */
+
+/*
+ * find_path()/set_cmnd() return values
+ */
+#define FOUND 0
+#define NOT_FOUND 1
+#define NOT_FOUND_DOT 2
+#define NOT_FOUND_ERROR 3
+#define NOT_FOUND_PATH 4
+
+/*
+ * Various modes sudo can be in (based on arguments) in hex
+ */
+#define MODE_RUN 0x00000001U
+#define MODE_EDIT 0x00000002U
+#define MODE_VALIDATE 0x00000004U
+#define MODE_INVALIDATE 0x00000008U
+#define MODE_VERSION 0x00000010U
+#define MODE_HELP 0x00000020U
+#define MODE_LIST 0x00000040U
+#define MODE_CHECK 0x00000080U
+#define MODE_ERROR 0x00000100U
+#define MODE_MASK 0x0000ffffU
+
+/* Mode flags */
+#define MODE_ASKPASS 0x00010000U
+#define MODE_SHELL 0x00020000U
+#define MODE_LOGIN_SHELL 0x00040000U
+#define MODE_IMPLIED_SHELL 0x00080000U
+#define MODE_RESET_HOME 0x00100000U
+#define MODE_PRESERVE_GROUPS 0x00200000U
+#define MODE_PRESERVE_ENV 0x00400000U
+#define MODE_NONINTERACTIVE 0x00800000U
+#define MODE_IGNORE_TICKET 0x01000000U
+#define MODE_UPDATE_TICKET 0x02000000U
+#define MODE_POLICY_INTERCEPTED 0x04000000U
+
+/* Mode bits allowed for intercepted commands. */
+#define MODE_INTERCEPT_MASK (MODE_RUN|MODE_NONINTERACTIVE|MODE_IGNORE_TICKET|MODE_POLICY_INTERCEPTED)
+
+/*
+ * Used with set_perms()
+ */
+#define PERM_INITIAL 0x00
+#define PERM_ROOT 0x01
+#define PERM_USER 0x02
+#define PERM_FULL_USER 0x03
+#define PERM_SUDOERS 0x04
+#define PERM_RUNAS 0x05
+#define PERM_TIMESTAMP 0x06
+#define PERM_IOLOG 0x07
+
+/* Default sudoers uid/gid/mode if not set by the Makefile. */
+#ifndef SUDOERS_UID
+# define SUDOERS_UID 0
+#endif
+#ifndef SUDOERS_GID
+# define SUDOERS_GID 0
+#endif
+#ifndef SUDOERS_MODE
+# define SUDOERS_MODE 0600
+#endif
+
+struct sudo_lbuf;
+struct passwd;
+struct stat;
+struct timespec;
+
+/*
+ * Function prototypes
+ */
+/* goodpath.c */
+bool sudo_goodpath(const char *path, struct stat *sbp);
+
+/* findpath.c */
+int find_path(const char *infile, char **outfile, struct stat *sbp,
+ const char *path, bool ignore_dot, char * const *allowlist);
+
+/* resolve_cmnd.c */
+int resolve_cmnd(struct sudoers_context *ctx, const char *infile,
+ char **outfile, const char *path);
+
+/* check.c */
+int check_user(struct sudoers_context *ctx, unsigned int validated, unsigned int mode);
+bool user_is_exempt(const struct sudoers_context *ctx);
+
+/* check_util.c */
+int check_user_runchroot(const char *runchroot);
+int check_user_runcwd(const char *runcwd);
+
+/* prompt.c */
+char *expand_prompt(const struct sudoers_context *ctx, const char *restrict old_prompt, const char *restrict auth_user);
+
+/* sudo_auth.c */
+bool sudo_auth_needs_end_session(void);
+int verify_user(const struct sudoers_context *ctx, struct passwd *pw, char *prompt, unsigned int validated, struct sudo_conv_callback *callback);
+int sudo_auth_begin_session(const struct sudoers_context *ctx, struct passwd *pw, char **user_env[]);
+int sudo_auth_end_session(void);
+int sudo_auth_init(const struct sudoers_context *ctx, struct passwd *pw, unsigned int mode);
+int sudo_auth_approval(const struct sudoers_context *ctx, struct passwd *pw, unsigned int validated, bool exempt);
+int sudo_auth_cleanup(const struct sudoers_context *ctx, struct passwd *pw, bool force);
+
+/* set_perms.c */
+bool rewind_perms(void);
+bool set_perms(const struct sudoers_context *, int);
+bool restore_perms(void);
+int pam_prep_user(struct passwd *);
+
+/* defaults.c */
+void dump_defaults(void);
+void dump_auth_methods(void);
+
+/* getspwuid.c */
+char *sudo_getepw(const struct passwd *);
+
+/* pwutil.c */
+typedef struct cache_item * (*sudo_make_pwitem_t)(uid_t uid, const char *user);
+typedef struct cache_item * (*sudo_make_gritem_t)(gid_t gid, const char *group);
+typedef struct cache_item * (*sudo_make_gidlist_item_t)(const struct passwd *pw, int ngids, GETGROUPS_T *gids, char * const *gidstrs, unsigned int type);
+typedef struct cache_item * (*sudo_make_grlist_item_t)(const struct passwd *pw, char * const *groups);
+typedef bool (*sudo_valid_shell_t)(const char *shell);
+sudo_dso_public struct group *sudo_getgrgid(gid_t);
+sudo_dso_public struct group *sudo_getgrnam(const char *);
+sudo_dso_public void sudo_gr_addref(struct group *);
+sudo_dso_public void sudo_gr_delref(struct group *);
+bool user_in_group(const struct passwd *, const char *);
+struct group *sudo_fakegrnam(const char *);
+struct group *sudo_mkgrent(const char *group, gid_t gid, ...);
+struct gid_list *sudo_get_gidlist(const struct passwd *pw, unsigned int type);
+struct group_list *sudo_get_grlist(const struct passwd *pw);
+struct passwd *sudo_fakepwnam(const char *, gid_t);
+struct passwd *sudo_mkpwent(const char *user, uid_t uid, gid_t gid, const char *home, const char *shell);
+struct passwd *sudo_getpwnam(const char *);
+struct passwd *sudo_getpwuid(uid_t);
+void sudo_endspent(void);
+void sudo_freegrcache(void);
+void sudo_freepwcache(void);
+void sudo_gidlist_addref(struct gid_list *);
+void sudo_gidlist_delref(struct gid_list *);
+void sudo_grlist_addref(struct group_list *);
+void sudo_grlist_delref(struct group_list *);
+void sudo_pw_addref(struct passwd *);
+void sudo_pw_delref(struct passwd *);
+int sudo_set_gidlist(struct passwd *pw, int ngids, GETGROUPS_T *gids, char * const *gidstrs, unsigned int type);
+int sudo_set_grlist(struct passwd *pw, char * const *groups);
+int sudo_pwutil_get_max_groups(void);
+void sudo_pwutil_set_max_groups(int);
+void sudo_pwutil_set_backend(sudo_make_pwitem_t, sudo_make_gritem_t, sudo_make_gidlist_item_t, sudo_make_grlist_item_t, sudo_valid_shell_t);
+void sudo_setspent(void);
+bool user_shell_valid(const struct passwd *pw);
+
+/* timestr.c */
+char *get_timestr(time_t, int);
+
+/* boottime.c */
+bool get_boottime(struct timespec *);
+
+/* iolog.c */
+bool cb_maxseq(struct sudoers_context *ctx, const char *file, int line, int column, const union sudo_defs_val *sd_un, int op);
+bool cb_iolog_user(struct sudoers_context *ctx, const char *file, int line, int column, const union sudo_defs_val *sd_un, int op);
+bool cb_iolog_group(struct sudoers_context *ctx, const char *file, int line, int column, const union sudo_defs_val *sd_un, int op);
+bool cb_iolog_mode(struct sudoers_context *ctx, const char *file, int line, int column, const union sudo_defs_val *sd_un, int op);
+
+/* iolog_path_escapes.c */
+struct iolog_path_escape;
+extern const struct iolog_path_escape *sudoers_iolog_path_escapes;
+
+/* env.c */
+char **env_get(void);
+bool env_merge(const struct sudoers_context *ctx, char * const envp[]);
+bool env_swap_old(void);
+void env_free(void);
+bool env_init(char * const envp[]);
+bool init_envtables(void);
+bool insert_env_vars(char * const envp[]);
+bool read_env_file(const struct sudoers_context *ctx, const char *path, bool overwrite, bool restricted);
+bool rebuild_env(const struct sudoers_context *ctx);
+bool validate_env_vars(const struct sudoers_context *ctx, char * const envp[]);
+int sudo_setenv(const char *var, const char *val, int overwrite);
+int sudo_unsetenv(const char *var);
+char *sudo_getenv(const char *name);
+char *sudo_getenv_nodebug(const char *name);
+int sudo_putenv_nodebug(char *str, bool dupcheck, bool overwrite);
+int sudo_unsetenv_nodebug(const char *var);
+int sudoers_hook_getenv(const char *name, char **value, void *closure);
+int sudoers_hook_putenv(char *string, void *closure);
+int sudoers_hook_setenv(const char *name, const char *value, int overwrite, void *closure);
+int sudoers_hook_unsetenv(const char *name, void *closure);
+void register_env_file(void * (*ef_open)(const char *), void (*ef_close)(void *), char * (*ef_next)(void *, int *), bool sys);
+
+/* env_pattern.c */
+bool matches_env_pattern(const char *pattern, const char *var, bool *full_match);
+
+/* sudoers_cb.c */
+void set_callbacks(void);
+bool cb_log_input(struct sudoers_context *ctx, const char *file, int line, int column, const union sudo_defs_val *sd_un, int op);
+bool cb_log_output(struct sudoers_context *ctx, const char *file, int line, int column, const union sudo_defs_val *sd_un, int op);
+
+/* sudoers.c */
+FILE *open_sudoers(const char *, char **, bool, bool *);
+bool cb_runas_default(struct sudoers_context *ctx, const char *file, int line, int column, const union sudo_defs_val *sd_un, int op);
+int set_cmnd_path(struct sudoers_context *ctx, const char *runchroot);
+void set_cmnd_status(struct sudoers_context *ctx, const char *runchroot);
+int sudoers_init(void *info, sudoers_logger_t logger, char * const envp[]);
+int sudoers_check_cmnd(int argc, char *const argv[], char *env_add[], void *closure);
+int sudoers_list(int argc, char *const argv[], const char *list_user, int verbose);
+int sudoers_validate_user(void);
+void sudoers_cleanup(void);
+bool sudoers_override_umask(void);
+const struct sudoers_context *sudoers_get_context(void);
+bool sudoers_set_mode(unsigned int flags, unsigned int mask);
+
+/* sudoers_ctx_free.c */
+void sudoers_ctx_free(struct sudoers_context *ctx);
+
+/* policy.c */
+unsigned int sudoers_policy_deserialize_info(struct sudoers_context *ctx, void *v, struct defaults_list *defaults);
+bool sudoers_policy_store_result(struct sudoers_context *ctx, bool accepted, char *argv[], char *envp[], mode_t cmnd_umask, char *iolog_path, void *v);
+bool sudoers_tty_present(struct sudoers_context *ctx);
+extern sudo_conv_t sudo_conv;
+extern sudo_printf_t sudo_printf;
+extern struct sudo_plugin_event * (*plugin_event_alloc)(void);
+
+/* group_plugin.c */
+void group_plugin_unload(void);
+int group_plugin_query(const char *user, const char *group,
+ const struct passwd *pwd);
+bool cb_group_plugin(struct sudoers_context *ctx, const char *file, int line, int column, const union sudo_defs_val *sd_un, int op);
+
+/* editor.c */
+char *find_editor(int nfiles, char * const *files, int *argc_out,
+ char ***argv_out, char * const *allowlist, const char **env_editor);
+
+/* exptilde.c */
+bool expand_tilde(char **path, const char *user);
+
+/* gc.c */
+enum sudoers_gc_types {
+ GC_UNKNOWN,
+ GC_VECTOR,
+ GC_PTR
+};
+bool sudoers_gc_add(enum sudoers_gc_types type, void *ptr);
+bool sudoers_gc_remove(enum sudoers_gc_types type, void *ptr);
+void sudoers_gc_init(void);
+void sudoers_gc_run(void);
+
+/* canon_path.c */
+char *canon_path(const char *inpath);
+void canon_path_free(char *resolved);
+void canon_path_free_cache(void);
+
+/* strlcpy_unesc.c */
+size_t strlcpy_unescape(char *restrict dst, const char *restrict src, size_t size);
+
+/* strvec_join.c */
+char *strvec_join(char *const argv[], char sep, size_t (*cpy)(char *, const char *, size_t));
+
+/* unesc_str.c */
+void unescape_string(char *str);
+
+/* serialize_list.c */
+char *serialize_list(const char *varname, struct list_members *members);
+
+/* sethost.c */
+bool sudoers_sethost(struct sudoers_context *ctx, const char *host, const char *remhost);
+
+#endif /* SUDOERS_SUDOERS_H */
diff --git a/plugins/sudoers/sudoers.in b/plugins/sudoers/sudoers.in
new file mode 100644
index 0000000..e0ef51c
--- /dev/null
+++ b/plugins/sudoers/sudoers.in
@@ -0,0 +1,122 @@
+## sudoers file.
+##
+## This file MUST be edited with the 'visudo' command as root.
+## Failure to use 'visudo' may result in syntax or file permission errors
+## that prevent sudo from running.
+##
+## See the sudoers man page for the details on how to write a sudoers file.
+##
+
+##
+## Host alias specification
+##
+## Groups of machines. These may include host names (optionally with wildcards),
+## IP addresses, network numbers or netgroups.
+# Host_Alias WEBSERVERS = www1, www2, www3
+
+##
+## User alias specification
+##
+## Groups of users. These may consist of user names, uids, Unix groups,
+## or netgroups.
+# User_Alias ADMINS = millert, dowdy, mikef
+
+##
+## Cmnd alias specification
+##
+## Groups of commands. Often used to group related commands together.
+# Cmnd_Alias PROCESSES = /usr/bin/nice, /bin/kill, /usr/bin/renice, \
+# /usr/bin/pkill, /usr/bin/top
+#
+# Cmnd_Alias REBOOT = /sbin/halt, /sbin/reboot, /sbin/poweroff
+#
+# Cmnd_Alias DEBUGGERS = /usr/bin/gdb, /usr/bin/lldb, /usr/bin/strace, \
+# /usr/bin/truss, /usr/bin/bpftrace, \
+# /usr/bin/dtrace, /usr/bin/dtruss
+#
+# Cmnd_Alias PKGMAN = /usr/bin/apt, /usr/bin/dpkg, /usr/bin/rpm, \
+# /usr/bin/yum, /usr/bin/dnf, /usr/bin/zypper, \
+# /usr/bin/pacman
+
+##
+## Defaults specification
+##
+## You may wish to keep some of the following environment variables
+## when running commands via sudo.
+##
+## Locale settings
+# Defaults env_keep += "LANG LANGUAGE LINGUAS LC_* _XKB_CHARSET"
+##
+## Run X applications through sudo; HOME is used to find the
+## .Xauthority file. Note that other programs use HOME to find
+## configuration files and this may lead to privilege escalation!
+# Defaults env_keep += "HOME"
+##
+## X11 resource path settings
+# Defaults env_keep += "XAPPLRESDIR XFILESEARCHPATH XUSERFILESEARCHPATH"
+##
+## Desktop path settings
+# Defaults env_keep += "QTDIR KDEDIR"
+##
+## Allow sudo-run commands to inherit the callers' ConsoleKit session
+# Defaults env_keep += "XDG_SESSION_COOKIE"
+##
+## Uncomment to enable special input methods. Care should be taken as
+## this may allow users to subvert the command being run via sudo.
+# Defaults env_keep += "XMODIFIERS GTK_IM_MODULE QT_IM_MODULE QT_IM_SWITCHER"
+##
+## Uncomment to use a hard-coded PATH instead of the user's to find commands
+# Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+##
+## Uncomment to restore the historic behavior where a command is run in
+## the user's own terminal.
+# Defaults !use_pty
+##
+## Uncomment to send mail if the user does not enter the correct password.
+# Defaults mail_badpass
+##
+## Uncomment to enable logging of a command's output, except for
+## sudoreplay and reboot. Use sudoreplay to play back logged sessions.
+## Sudo will create up to 2,176,782,336 I/O logs before recycling them.
+## Set maxseq to a smaller number if you don't have unlimited disk space.
+# Defaults log_output
+# Defaults!/usr/bin/sudoreplay !log_output
+# Defaults!/usr/local/bin/sudoreplay !log_output
+# Defaults!REBOOT !log_output
+# Defaults maxseq = 1000
+##
+## Uncomment to disable intercept and log_subcmds for debuggers and
+## tracers. Otherwise, anything that uses ptrace(2) will be unable
+## to run under sudo if intercept_type is set to "trace".
+# Defaults!DEBUGGERS !intercept, !log_subcmds
+##
+## Uncomment to disable intercept and log_subcmds for package managers.
+## Some package scripts run a huge number of commands, which is made
+## slower by these options and also can clutter up the logs.
+# Defaults!PKGMAN !intercept, !log_subcmds
+
+##
+## Runas alias specification
+##
+
+##
+## User privilege specification
+##
+root ALL=(ALL:ALL) ALL
+
+## Uncomment to allow members of group wheel to execute any command
+# %wheel ALL=(ALL:ALL) ALL
+
+## Same thing without a password
+# %wheel ALL=(ALL:ALL) NOPASSWD: ALL
+
+## Uncomment to allow members of group sudo to execute any command
+# %sudo ALL=(ALL:ALL) ALL
+
+## Uncomment to allow any user to run sudo if they know the password
+## of the user they are running the command as (root by default).
+# Defaults targetpw # Ask for the password of the target user
+# ALL ALL=(ALL:ALL) ALL # WARNING: only use this together with 'Defaults targetpw'
+
+## Read drop-in files from @sysconfdir@/sudoers.d
+@includedir @sysconfdir@/sudoers.d
diff --git a/plugins/sudoers/sudoers_cb.c b/plugins/sudoers/sudoers_cb.c
new file mode 100644
index 0000000..4fc4c54
--- /dev/null
+++ b/plugins/sudoers/sudoers_cb.c
@@ -0,0 +1,508 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#ifdef __TANDEM
+# include <floss.h>
+#endif
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+#include <netdb.h>
+#ifndef HAVE_GETADDRINFO
+# include <compat/getaddrinfo.h>
+#endif
+
+#include <sudoers.h>
+#include <timestamp.h>
+#include <sudo_iolog.h>
+
+#ifndef AI_FQDN
+# define AI_FQDN AI_CANONNAME
+#endif
+
+static bool override_umask;
+
+/*
+ * Look up the fully qualified domain name of host.
+ * Use AI_FQDN if available since "canonical" is not always the same as fqdn.
+ * Returns 0 on success, setting longp and shortp.
+ * Returns non-zero on failure, longp and shortp are unchanged.
+ * See gai_strerror() for the list of error return codes.
+ */
+static int
+resolve_host(const char *host, char **longp, char **shortp)
+{
+ struct addrinfo *res0, hint;
+ char *cp, *lname, *sname;
+ int ret;
+ debug_decl(resolve_host, SUDOERS_DEBUG_PLUGIN);
+
+ memset(&hint, 0, sizeof(hint));
+ hint.ai_family = PF_UNSPEC;
+ hint.ai_flags = AI_FQDN;
+
+ if ((ret = getaddrinfo(host, NULL, &hint, &res0)) != 0)
+ debug_return_int(ret);
+ if ((lname = strdup(res0->ai_canonname)) == NULL) {
+ freeaddrinfo(res0);
+ debug_return_int(EAI_MEMORY);
+ }
+ if ((cp = strchr(lname, '.')) != NULL) {
+ sname = strndup(lname, (size_t)(cp - lname));
+ if (sname == NULL) {
+ free(lname);
+ freeaddrinfo(res0);
+ debug_return_int(EAI_MEMORY);
+ }
+ } else {
+ sname = lname;
+ }
+ freeaddrinfo(res0);
+ *longp = lname;
+ *shortp = sname;
+
+ debug_return_int(0);
+}
+
+/*
+ * Look up the fully qualified domain name of user and runas hosts.
+ * Sets ctx->user.host, ctx->user.shost, ctx->runas.host and ctx->runas.shost.
+ */
+static bool
+cb_fqdn(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ bool remote;
+ int rc;
+ char *lhost, *shost;
+ debug_decl(cb_fqdn, SUDOERS_DEBUG_PLUGIN);
+
+ /* Nothing to do if fqdn flag is disabled. */
+ if (sd_un != NULL && !sd_un->flag)
+ debug_return_bool(true);
+
+ /* If the -h flag was given we need to resolve both host names. */
+ remote = strcmp(ctx->runas.host, ctx->user.host) != 0;
+
+ /* First resolve ctx->user.host, setting host and shost. */
+ if (resolve_host(ctx->user.host, &lhost, &shost) != 0) {
+ if ((rc = resolve_host(ctx->runas.host, &lhost, &shost)) != 0) {
+ gai_log_warning(ctx, SLOG_PARSE_ERROR|SLOG_RAW_MSG, rc,
+ N_("unable to resolve host %s"), ctx->user.host);
+ debug_return_bool(false);
+ }
+ }
+ if (ctx->user.shost != ctx->user.host)
+ free(ctx->user.shost);
+ free(ctx->user.host);
+ ctx->user.host = lhost;
+ ctx->user.shost = shost;
+
+ /* Next resolve ctx->runas.host, setting host and shost in ctx->runas. */
+ lhost = shost = NULL;
+ if (remote) {
+ if ((rc = resolve_host(ctx->runas.host, &lhost, &shost)) != 0) {
+ gai_log_warning(ctx, SLOG_NO_LOG|SLOG_RAW_MSG, rc,
+ N_("unable to resolve host %s"), ctx->runas.host);
+ debug_return_bool(false);
+ }
+ } else {
+ /* Not remote, just use ctx->user.host. */
+ if ((lhost = strdup(ctx->user.host)) != NULL) {
+ if (ctx->user.shost != ctx->user.host)
+ shost = strdup(ctx->user.shost);
+ else
+ shost = lhost;
+ }
+ if (lhost == NULL || shost == NULL) {
+ free(lhost);
+ if (lhost != shost)
+ free(shost);
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ }
+ if (lhost != NULL && shost != NULL) {
+ if (ctx->runas.shost != ctx->runas.host)
+ free(ctx->runas.shost);
+ free(ctx->runas.host);
+ ctx->runas.host = lhost;
+ ctx->runas.shost = shost;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "host %s, shost %s, runas host %s, runas shost %s",
+ ctx->user.host, ctx->user.shost, ctx->runas.host, ctx->runas.shost);
+ debug_return_bool(true);
+}
+
+static bool
+cb_tty_tickets(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_tty_tickets, SUDOERS_DEBUG_PLUGIN);
+
+ /* Convert tty_tickets -> timestamp_type */
+ if (sd_un->flag)
+ def_timestamp_type = tty;
+ else
+ def_timestamp_type = global;
+ debug_return_bool(true);
+}
+
+static bool
+cb_umask(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_umask, SUDOERS_DEBUG_PLUGIN);
+
+ /* Override umask if explicitly set in sudoers. */
+ override_umask = sd_un->mode != ACCESSPERMS;
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_runchroot(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_runchroot, SUDOERS_DEBUG_PLUGIN);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "def_runchroot now %s", sd_un->str);
+ if (ctx->user.cmnd != NULL) {
+ /* Update ctx->user.cmnd and cmnd_status based on the new chroot. */
+ set_cmnd_status(ctx, sd_un->str);
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "ctx->user.cmnd now %s", ctx->user.cmnd);
+ }
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_logfile(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ int logtype = def_syslog ? EVLOG_SYSLOG : EVLOG_NONE;
+ debug_decl(cb_logfile, SUDOERS_DEBUG_PLUGIN);
+
+ if (sd_un->str != NULL)
+ SET(logtype, EVLOG_FILE);
+ eventlog_set_type(logtype);
+ eventlog_set_logpath(sd_un->str);
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_log_format(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_log_format, SUDOERS_DEBUG_PLUGIN);
+
+ eventlog_set_format(sd_un->tuple == sudo ? EVLOG_SUDO : EVLOG_JSON);
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_syslog(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ int logtype = def_logfile ? EVLOG_FILE : EVLOG_NONE;
+ debug_decl(cb_syslog, SUDOERS_DEBUG_PLUGIN);
+
+ if (sd_un->str != NULL)
+ SET(logtype, EVLOG_SYSLOG);
+ eventlog_set_type(logtype);
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_syslog_goodpri(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_syslog_goodpri, SUDOERS_DEBUG_PLUGIN);
+
+ eventlog_set_syslog_acceptpri(sd_un->ival);
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_syslog_badpri(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_syslog_badpri, SUDOERS_DEBUG_PLUGIN);
+
+ eventlog_set_syslog_rejectpri(sd_un->ival);
+ eventlog_set_syslog_alertpri(sd_un->ival);
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_syslog_maxlen(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_syslog_maxlen, SUDOERS_DEBUG_PLUGIN);
+
+ eventlog_set_syslog_maxlen((size_t)sd_un->ival);
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_loglinelen(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_loglinelen, SUDOERS_DEBUG_PLUGIN);
+
+ eventlog_set_file_maxlen((size_t)sd_un->ival);
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_log_year(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_syslog_maxlen, SUDOERS_DEBUG_PLUGIN);
+
+ eventlog_set_time_fmt(sd_un->flag ? "%h %e %T %Y" : "%h %e %T");
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_log_host(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_syslog_maxlen, SUDOERS_DEBUG_PLUGIN);
+
+ eventlog_set_omit_hostname(!sd_un->flag);
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_mailerpath(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_mailerpath, SUDOERS_DEBUG_PLUGIN);
+
+ eventlog_set_mailerpath(sd_un->str);
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_mailerflags(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_mailerflags, SUDOERS_DEBUG_PLUGIN);
+
+ eventlog_set_mailerflags(sd_un->str);
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_mailfrom(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_mailfrom, SUDOERS_DEBUG_PLUGIN);
+
+ eventlog_set_mailfrom(sd_un->str);
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_mailto(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_mailto, SUDOERS_DEBUG_PLUGIN);
+
+ eventlog_set_mailto(sd_un->str);
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_mailsub(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_mailsub, SUDOERS_DEBUG_PLUGIN);
+
+ eventlog_set_mailsub(sd_un->str);
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_intercept_type(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_intercept_type, SUDOERS_DEBUG_PLUGIN);
+
+ if (op != -1) {
+ /* Set explicitly in sudoers. */
+ if (sd_un->tuple == dso) {
+ /* Reset intercept_allow_setid default value. */
+ if (!ISSET(ctx->settings.flags, USER_INTERCEPT_SETID))
+ def_intercept_allow_setid = false;
+ }
+ }
+
+ debug_return_bool(true);
+}
+
+static bool
+cb_intercept_allow_setid(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_intercept_allow_setid, SUDOERS_DEBUG_PLUGIN);
+
+ /* Operator will be -1 if set by front-end. */
+ if (op != -1) {
+ /* Set explicitly in sudoers. */
+ SET(ctx->settings.flags, USER_INTERCEPT_SETID);
+ }
+
+ debug_return_bool(true);
+}
+
+bool
+cb_log_input(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_log_input, SUDOERS_DEBUG_PLUGIN);
+
+ def_log_stdin = op;
+ def_log_ttyin = op;
+
+ debug_return_bool(true);
+}
+
+bool
+cb_log_output(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ debug_decl(cb_log_output, SUDOERS_DEBUG_PLUGIN);
+
+ def_log_stdout = op;
+ def_log_stderr = op;
+ def_log_ttyout = op;
+
+ debug_return_bool(true);
+}
+
+/*
+ * Set parser Defaults callbacks.
+ * We do this here instead in def_data.in so we don't have to
+ * stub out the callbacks for visudo and testsudoers.
+ */
+void
+set_callbacks(void)
+{
+ debug_decl(set_callbacks, SUDOERS_DEBUG_PLUGIN);
+
+ /* Set fqdn callback. */
+ sudo_defs_table[I_FQDN].callback = cb_fqdn;
+
+ /* Set group_plugin callback. */
+ sudo_defs_table[I_GROUP_PLUGIN].callback = cb_group_plugin;
+
+ /* Set runas callback. */
+ sudo_defs_table[I_RUNAS_DEFAULT].callback = cb_runas_default;
+
+ /* Set locale callback. */
+ sudo_defs_table[I_SUDOERS_LOCALE].callback = sudoers_locale_callback;
+
+#ifdef SESSID_MAX
+ /* Set maxseq callback. */
+ sudo_defs_table[I_MAXSEQ].callback = cb_maxseq;
+
+ /* Set iolog_user callback. */
+ sudo_defs_table[I_IOLOG_USER].callback = cb_iolog_user;
+
+ /* Set iolog_group callback. */
+ sudo_defs_table[I_IOLOG_GROUP].callback = cb_iolog_group;
+
+ /* Set iolog_mode callback. */
+ sudo_defs_table[I_IOLOG_MODE].callback = cb_iolog_mode;
+#endif /* SESSID_MAX */
+
+ /* Set timestampowner callback. */
+ sudo_defs_table[I_TIMESTAMPOWNER].callback = cb_timestampowner;
+
+ /* Set tty_tickets callback. */
+ sudo_defs_table[I_TTY_TICKETS].callback = cb_tty_tickets;
+
+ /* Set umask callback. */
+ sudo_defs_table[I_UMASK].callback = cb_umask;
+
+ /* Set runchroot callback. */
+ sudo_defs_table[I_RUNCHROOT].callback = cb_runchroot;
+
+ /* eventlog callbacks */
+ sudo_defs_table[I_SYSLOG].callback = cb_syslog;
+ sudo_defs_table[I_SYSLOG_GOODPRI].callback = cb_syslog_goodpri;
+ sudo_defs_table[I_SYSLOG_BADPRI].callback = cb_syslog_badpri;
+ sudo_defs_table[I_SYSLOG_MAXLEN].callback = cb_syslog_maxlen;
+ sudo_defs_table[I_LOGLINELEN].callback = cb_loglinelen;
+ sudo_defs_table[I_LOG_HOST].callback = cb_log_host;
+ sudo_defs_table[I_LOGFILE].callback = cb_logfile;
+ sudo_defs_table[I_LOG_FORMAT].callback = cb_log_format;
+ sudo_defs_table[I_LOG_YEAR].callback = cb_log_year;
+ sudo_defs_table[I_MAILERPATH].callback = cb_mailerpath;
+ sudo_defs_table[I_MAILERFLAGS].callback = cb_mailerflags;
+ sudo_defs_table[I_MAILFROM].callback = cb_mailfrom;
+ sudo_defs_table[I_MAILTO].callback = cb_mailto;
+ sudo_defs_table[I_MAILSUB].callback = cb_mailsub;
+ sudo_defs_table[I_PASSPROMPT_REGEX].callback = cb_passprompt_regex;
+ sudo_defs_table[I_INTERCEPT_TYPE].callback = cb_intercept_type;
+ sudo_defs_table[I_INTERCEPT_ALLOW_SETID].callback = cb_intercept_allow_setid;
+ sudo_defs_table[I_LOG_INPUT].callback = cb_log_input;
+ sudo_defs_table[I_LOG_OUTPUT].callback = cb_log_output;
+
+ debug_return;
+}
+
+bool
+sudoers_override_umask(void)
+{
+ return override_umask;
+}
diff --git a/plugins/sudoers/sudoers_ctx_free.c b/plugins/sudoers/sudoers_ctx_free.c
new file mode 100644
index 0000000..b9c5af6
--- /dev/null
+++ b/plugins/sudoers/sudoers_ctx_free.c
@@ -0,0 +1,94 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudoers.h>
+
+/*
+ * Free memory allocated for struct sudoers_context.
+ */
+void
+sudoers_ctx_free(struct sudoers_context *ctx)
+{
+ debug_decl(sudoers_ctx_free, SUDOERS_DEBUG_PLUGIN);
+
+ /* Free remaining references to password and group entries. */
+ if (ctx->user.pw != NULL)
+ sudo_pw_delref(ctx->user.pw);
+ if (ctx->user.gid_list != NULL)
+ sudo_gidlist_delref(ctx->user.gid_list);
+
+ /* Free dynamic contents of user_ctx. */
+ free(ctx->user.cwd);
+ free(ctx->user.name);
+ if (ctx->user.ttypath != NULL)
+ free(ctx->user.ttypath);
+ else
+ free(ctx->user.tty);
+ if (ctx->user.shost != ctx->user.host)
+ free(ctx->user.shost);
+ free(ctx->user.host);
+ free(ctx->user.cmnd);
+ canon_path_free(ctx->user.cmnd_dir);
+ free(ctx->user.cmnd_args);
+ free(ctx->user.cmnd_list);
+ free(ctx->user.cmnd_stat);
+
+ /* Free remaining references to password and group entries. */
+ if (ctx->runas.pw != NULL)
+ sudo_pw_delref(ctx->runas.pw);
+ if (ctx->runas.gr != NULL)
+ sudo_gr_delref(ctx->runas.gr);
+ if (ctx->runas.list_pw != NULL)
+ sudo_pw_delref(ctx->runas.list_pw);
+
+ /* Free dynamic contents of ctx->runas. */
+ free(ctx->runas.cmnd);
+ free(ctx->runas.cmnd_saved);
+ if (ctx->runas.shost != ctx->runas.host)
+ free(ctx->runas.shost);
+ free(ctx->runas.host);
+#ifdef HAVE_SELINUX
+ free(ctx->runas.role);
+ free(ctx->runas.type);
+#endif
+#ifdef HAVE_APPARMOR
+ free(ctx->runas.apparmor_profile);
+#endif
+#ifdef HAVE_PRIV_SET
+ free(ctx->runas.privs);
+ free(ctx->runas.limitprivs);
+#endif
+
+ /* Free dynamic contents of ctx. */
+ free(ctx->source);
+
+ memset(ctx, 0, sizeof(*ctx));
+
+ debug_return;
+}
diff --git a/plugins/sudoers/sudoers_debug.c b/plugins/sudoers/sudoers_debug.c
new file mode 100644
index 0000000..0c1efe7
--- /dev/null
+++ b/plugins/sudoers/sudoers_debug.c
@@ -0,0 +1,135 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2014-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sudoers.h>
+
+static int sudoers_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
+static unsigned int sudoers_debug_refcnt;
+
+static const char *const sudoers_subsystem_names[] = {
+ "alias",
+ "audit",
+ "auth",
+ "defaults",
+ "env",
+ "event",
+ "ldap",
+ "logging",
+ "main",
+ "match",
+ "netif",
+ "nss",
+ "parser",
+ "perms",
+ "plugin",
+ "rbtree",
+ "sssd",
+ "util",
+ NULL
+};
+
+#define NUM_SUBSYSTEMS (nitems(sudoers_subsystem_names) - 1)
+
+/* Subsystem IDs assigned at registration time. */
+unsigned int sudoers_subsystem_ids[NUM_SUBSYSTEMS];
+
+/*
+ * Parse the "filename flags,..." debug_flags entry and insert a new
+ * sudo_debug_file struct into debug_files.
+ */
+bool
+sudoers_debug_parse_flags(struct sudo_conf_debug_file_list *debug_files,
+ const char *entry)
+{
+ /* Already initialized? */
+ if (sudoers_debug_instance != SUDO_DEBUG_INSTANCE_INITIALIZER)
+ return true;
+
+ return sudo_debug_parse_flags(debug_files, entry) != -1;
+}
+
+/*
+ * Register the specified debug files and program with the
+ * debug subsystem, freeing the debug list when done.
+ * Sets the active debug instance as a side effect.
+ */
+bool
+sudoers_debug_register(const char *program,
+ struct sudo_conf_debug_file_list *debug_files)
+{
+ int instance = sudoers_debug_instance;
+ struct sudo_debug_file *debug_file, *debug_next;
+
+ /* Setup debugging if indicated. */
+ if (debug_files != NULL && !TAILQ_EMPTY(debug_files)) {
+ if (program != NULL) {
+ instance = sudo_debug_register(program, sudoers_subsystem_names,
+ sudoers_subsystem_ids, debug_files, -1);
+ }
+ TAILQ_FOREACH_SAFE(debug_file, debug_files, entries, debug_next) {
+ TAILQ_REMOVE(debug_files, debug_file, entries);
+ free(debug_file->debug_file);
+ free(debug_file->debug_flags);
+ free(debug_file);
+ }
+ }
+
+ switch (instance) {
+ case SUDO_DEBUG_INSTANCE_ERROR:
+ return false;
+ case SUDO_DEBUG_INSTANCE_INITIALIZER:
+ /* Nothing to do */
+ break;
+ default:
+ /* New debug instance or additional reference on existing one. */
+ sudoers_debug_instance = instance;
+ sudo_debug_set_active_instance(sudoers_debug_instance);
+ sudoers_debug_refcnt++;
+ break;
+ }
+
+ return true;
+}
+
+/*
+ * Deregister sudoers_debug_instance if it is registered.
+ */
+void
+sudoers_debug_deregister(void)
+{
+ debug_decl(sudoers_debug_deregister, SUDOERS_DEBUG_PLUGIN);
+
+ if (sudoers_debug_refcnt != 0) {
+ sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
+ if (--sudoers_debug_refcnt == 0) {
+ if (sudo_debug_deregister(sudoers_debug_instance) < 1)
+ sudoers_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
+ }
+ }
+}
diff --git a/plugins/sudoers/sudoers_debug.h b/plugins/sudoers/sudoers_debug.h
new file mode 100644
index 0000000..f97f9af
--- /dev/null
+++ b/plugins/sudoers/sudoers_debug.h
@@ -0,0 +1,52 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2014 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_DEBUG_H
+#define SUDOERS_DEBUG_H
+
+#include <sudo_debug.h>
+
+/*
+ * Sudoers debug subsystems.
+ * Note that sudoers_subsystem_ids[] is filled in at debug registration time.
+ */
+extern unsigned int sudoers_subsystem_ids[];
+#define SUDOERS_DEBUG_ALIAS (sudoers_subsystem_ids[ 0]) /* sudoers alias functions */
+#define SUDOERS_DEBUG_AUDIT (sudoers_subsystem_ids[ 1]) /* audit */
+#define SUDOERS_DEBUG_AUTH (sudoers_subsystem_ids[ 2]) /* authentication functions */
+#define SUDOERS_DEBUG_DEFAULTS (sudoers_subsystem_ids[ 3]) /* sudoers defaults settings */
+#define SUDOERS_DEBUG_ENV (sudoers_subsystem_ids[ 4]) /* environment handling */
+#define SUDOERS_DEBUG_EVENT (sudoers_subsystem_ids[ 5]) /* event handling */
+#define SUDOERS_DEBUG_LDAP (sudoers_subsystem_ids[ 6]) /* sudoers LDAP */
+#define SUDOERS_DEBUG_LOGGING (sudoers_subsystem_ids[ 7]) /* logging functions */
+#define SUDOERS_DEBUG_MAIN (sudoers_subsystem_ids[ 8]) /* main() */
+#define SUDOERS_DEBUG_MATCH (sudoers_subsystem_ids[ 9]) /* sudoers matching */
+#define SUDOERS_DEBUG_NETIF (sudoers_subsystem_ids[10]) /* network interface functions */
+#define SUDOERS_DEBUG_NSS (sudoers_subsystem_ids[11]) /* network service switch */
+#define SUDOERS_DEBUG_PARSER (sudoers_subsystem_ids[12]) /* sudoers parser */
+#define SUDOERS_DEBUG_PERMS (sudoers_subsystem_ids[13]) /* uid/gid swapping functions */
+#define SUDOERS_DEBUG_PLUGIN (sudoers_subsystem_ids[14]) /* main plugin functions */
+#define SUDOERS_DEBUG_RBTREE (sudoers_subsystem_ids[15]) /* red-black tree functions */
+#define SUDOERS_DEBUG_SSSD (sudoers_subsystem_ids[16]) /* sudoers SSSD */
+#define SUDOERS_DEBUG_UTIL (sudoers_subsystem_ids[17]) /* utility functions */
+
+bool sudoers_debug_parse_flags(struct sudo_conf_debug_file_list *debug_files, const char *entry);
+bool sudoers_debug_register(const char *plugin_path, struct sudo_conf_debug_file_list *debug_files);
+void sudoers_debug_deregister(void);
+
+#endif /* SUDOERS_DEBUG_H */
diff --git a/plugins/sudoers/sudoers_hooks.c b/plugins/sudoers/sudoers_hooks.c
new file mode 100644
index 0000000..480af41
--- /dev/null
+++ b/plugins/sudoers/sudoers_hooks.c
@@ -0,0 +1,155 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2000-2005, 2007-2019
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sudoers.h>
+
+/*
+ * Similar to setenv(3) but operates on a private copy of the environment.
+ * Does not include warnings or debugging to avoid recursive calls.
+ */
+static int
+sudo_setenv_nodebug(const char *var, const char *val, int overwrite)
+{
+ char *ep, *estring = NULL;
+ const char *cp;
+ size_t esize;
+ int ret = -1;
+
+ if (var == NULL || *var == '\0') {
+ errno = EINVAL;
+ goto done;
+ }
+
+ /*
+ * POSIX says a var name with '=' is an error but BSD
+ * just ignores the '=' and anything after it.
+ */
+ for (cp = var; *cp && *cp != '='; cp++)
+ continue;
+ esize = (size_t)(cp - var) + 2;
+ if (val) {
+ esize += strlen(val); /* glibc treats a NULL val as "" */
+ }
+
+ /* Allocate and fill in estring. */
+ if ((estring = ep = malloc(esize)) == NULL)
+ goto done;
+ for (cp = var; *cp && *cp != '='; cp++)
+ *ep++ = *cp;
+ *ep++ = '=';
+ if (val) {
+ for (cp = val; *cp; cp++)
+ *ep++ = *cp;
+ }
+ *ep = '\0';
+
+ ret = sudo_putenv_nodebug(estring, true, overwrite);
+done:
+ if (ret == -1)
+ free(estring);
+ else
+ sudoers_gc_add(GC_PTR, estring);
+ return ret;
+}
+
+int
+sudoers_hook_getenv(const char *name, char **value, void *closure)
+{
+ static bool in_progress = false; /* avoid recursion */
+
+ if (in_progress || env_get() == NULL)
+ return SUDO_HOOK_RET_NEXT;
+
+ in_progress = true;
+
+ /* Hack to make GNU gettext() find the sudoers locale when needed. */
+ if (*name == 'L' && sudoers_getlocale() == SUDOERS_LOCALE_SUDOERS) {
+ if (strcmp(name, "LANGUAGE") == 0 || strcmp(name, "LANG") == 0) {
+ *value = NULL;
+ goto done;
+ }
+ if (strcmp(name, "LC_ALL") == 0 || strcmp(name, "LC_MESSAGES") == 0) {
+ *value = def_sudoers_locale;
+ goto done;
+ }
+ }
+
+ *value = sudo_getenv_nodebug(name);
+done:
+ in_progress = false;
+ return SUDO_HOOK_RET_STOP;
+}
+
+int
+sudoers_hook_putenv(char *string, void *closure)
+{
+ static bool in_progress = false; /* avoid recursion */
+
+ if (in_progress || env_get() == NULL)
+ return SUDO_HOOK_RET_NEXT;
+
+ in_progress = true;
+ sudo_putenv_nodebug(string, true, true);
+ in_progress = false;
+ return SUDO_HOOK_RET_STOP;
+}
+
+int
+sudoers_hook_setenv(const char *name, const char *value, int overwrite, void *closure)
+{
+ static bool in_progress = false; /* avoid recursion */
+
+ if (in_progress || env_get() == NULL)
+ return SUDO_HOOK_RET_NEXT;
+
+ in_progress = true;
+ sudo_setenv_nodebug(name, value, overwrite);
+ in_progress = false;
+ return SUDO_HOOK_RET_STOP;
+}
+
+int
+sudoers_hook_unsetenv(const char *name, void *closure)
+{
+ static bool in_progress = false; /* avoid recursion */
+
+ if (in_progress || env_get() == NULL)
+ return SUDO_HOOK_RET_NEXT;
+
+ in_progress = true;
+ sudo_unsetenv_nodebug(name);
+ in_progress = false;
+ return SUDO_HOOK_RET_STOP;
+}
diff --git a/plugins/sudoers/sudoers_version.h b/plugins/sudoers/sudoers_version.h
new file mode 100644
index 0000000..ecb2b21
--- /dev/null
+++ b/plugins/sudoers/sudoers_version.h
@@ -0,0 +1,81 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011-2013, 2015, 2017, 2019-2020
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Major sudoers grammar changes are documented here.
+ * Note that minor changes such as added Defaults options are not listed here.
+ *
+ * 1 sudo 1.1
+ * 2 sudo 1.3, adds support specifying a directory instead of a command.
+ * 3 sudo 1.3.2, new parser, Aliases have to be upper case
+ * 4 sudo 1.3.2, adds User_Alias
+ * 5 sudo 1.3.4, netgroup support
+ * 6 sudo 1.3.5, support for escaping special chars
+ * 7 sudo 1.3.7, unix group support
+ * 8 sudo 1.4.1, wildcard support
+ * 9 sudo 1.4.2, double quote support in sudoers command line args
+ * 10 sudo 1.4.3, added NOPASSWD tag
+ * 11 sudo 1.4.3, added Runas_Spec
+ * 12 sudo 1.4.3, wildcards may be used in the pathname
+ * 13 sudo 1.4.3, command args of "" means no args allowed
+ * 14 sudo 1.4.4, '(' in command args no longer are a syntax error.
+ * 15 sudo 1.4.4, '!command' works in the presence of runas user or NOPASSWD.
+ * 16 sudo 1.4.4, all-caps user and host names are now handled properly.
+ * 17 sudo 1.5.0, usernames may now begin with a digit
+ * 18 sudo 1.5.3, adds Runas_Alias
+ * 19 sudo 1.5.7, %group may be used in a Runas_List
+ * 20 sudo 1.6.0, The runas user and NOPASSWD tags are now persistent across entries in a command list. A PASSWD tag has been added to reverse NOPASSWD
+ * 21 sudo 1.6.0, The '!' operator can be used in a Runas_Spec or an *_Alias
+ * 22 sudo 1.6.0, a list of hosts may be used in a Host_Spec
+ * 23 sudo 1.6.0, a list of users may be used in a User_Spec
+ * 24 sudo 1.6.0, It is now possible to escape "special" characters in usernames, hostnames, etc with a backslash.
+ * 25 sudo 1.6.0, Added Defaults run-time settings in sudoers.
+ * 26 sudo 1.6.0, relaxed the regexp for matching user, host, group names.
+ * 27 sudo 1.6.1, #uid is now allowed in a Runas_Alias.
+ * 28 sudo 1.6.2, Wildcards are now allowed in hostnames.
+ * 29 sudo 1.6.3p7, escaped special characters may be included in pathnames.
+ * 30 sudo 1.6.8, added NOEXEC and EXEC tags.
+ * 31 sudo 1.6.9, added SETENV and NOSETENV tags.
+ * 32 sudo 1.6.9p4, support for IPv6 address matching.
+ * 33 sudo 1.7.0, #include support.
+ * 34 sudo 1.7.0, Runas_Group support.
+ * 35 sudo 1.7.0, uid may now be used anywhere a username is valid.
+ * 36 sudo 1.7.2, #includedir support.
+ * 37 sudo 1.7.4, per-command Defaults support.
+ * 38 sudo 1.7.4, added LOG_INPUT/LOG_OUTPUT and NOLOG_INPUT/NOLOG_OUTPUT tags
+ * 39 sudo 1.7.6/1.8.1, White space is now permitted within a User_List in a per-user Defaults definition.
+ * 40 sudo 1.7.6/1.8.1, A group ID is now allowed in a User_List or Runas_List.
+ * 41 sudo 1.7.6/1.8.4, Support for relative paths in #include and #includedir
+ * 42 sudo 1.8.6, Support for empty Runas_List (with or without a colon) to mean the invoking user. Support for Solaris Privilege Sets (PRIVS= and LIMITPRIVS=).
+ * 43 sudo 1.8.7, Support for specifying a digest along with the command.
+ * 44 sudo 1.8.13, added MAIL/NOMAIL tags.
+ * 45 sudo 1.8.15, added FOLLOW/NOFOLLOW tags as well as sudoedit_follow and sudoedit_checkdir Defaults.
+ * 46 sudo 1.8.20, added TIMEOUT, NOTBEFORE and NOTAFTER options.
+ * 47 sudo 1.9.0, Cmd_Alias treated as Cmnd_Alias, support for multiple digests per command and for ALL.
+ * 48 sudo 1.9.1, @include and @includedir, include path escaping/quoting.
+ * 49 sudo 1.9.3, added CWD and CHROOT options.
+ * 50 sudo 1.9.13, added the list pseudo-command.
+ */
+
+#ifndef SUDOERS_VERSION_H
+#define SUDOERS_VERSION_H
+
+#define SUDOERS_GRAMMAR_VERSION 50
+
+#endif /* SUDOERS_VERSION_H */
diff --git a/plugins/sudoers/sudoreplay.c b/plugins/sudoers/sudoreplay.c
new file mode 100644
index 0000000..ffdcc35
--- /dev/null
+++ b/plugins/sudoers/sudoreplay.c
@@ -0,0 +1,1721 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <dirent.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <regex.h>
+#include <signal.h>
+#ifdef HAVE_GETOPT_LONG
+# include <getopt.h>
+# else
+# include <compat/getopt.h>
+#endif /* HAVE_GETOPT_LONG */
+
+#include <pathnames.h>
+#include <sudo_compat.h>
+#include <sudo_conf.h>
+#include <sudo_debug.h>
+#include <sudo_event.h>
+#include <sudo_eventlog.h>
+#include <sudo_lbuf.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_iolog.h>
+#include <sudo_plugin.h>
+#include <sudo_queue.h>
+#include <sudo_util.h>
+
+#include <logging.h>
+
+struct replay_closure {
+ const char *iolog_dir;
+ struct sudo_event_base *evbase;
+ struct sudo_event *delay_ev;
+ struct sudo_event *keyboard_ev;
+ struct sudo_event *output_ev;
+ struct sudo_event *sighup_ev;
+ struct sudo_event *sigint_ev;
+ struct sudo_event *sigquit_ev;
+ struct sudo_event *sigterm_ev;
+ struct sudo_event *sigtstp_ev;
+ struct timespec *offset;
+ struct timespec *max_delay;
+ struct timing_closure timing;
+ int iolog_dir_fd;
+ bool interactive;
+ bool suspend_wait;
+ struct io_buffer {
+ size_t len; /* buffer length (how much produced) */
+ size_t off; /* write position (how much already consumed) */
+ size_t toread; /* how much remains to be read */
+ int lastc; /* last char written */
+ char buf[64 * 1024];
+ } iobuf;
+};
+
+/*
+ * Handle expressions like:
+ * ( user millert or user root ) and tty console and command /bin/sh
+ */
+STAILQ_HEAD(search_node_list, search_node);
+struct search_node {
+ STAILQ_ENTRY(search_node) entries;
+#define ST_EXPR 1
+#define ST_TTY 2
+#define ST_USER 3
+#define ST_PATTERN 4
+#define ST_RUNASUSER 5
+#define ST_RUNASGROUP 6
+#define ST_FROMDATE 7
+#define ST_TODATE 8
+#define ST_CWD 9
+#define ST_HOST 10
+ char type;
+ bool negated;
+ bool or;
+ union {
+ regex_t cmdre;
+ struct timespec tstamp;
+ char *cwd;
+ char *host;
+ char *tty;
+ char *user;
+ char *runas_group;
+ char *runas_user;
+ struct search_node_list expr;
+ void *ptr;
+ } u;
+};
+
+static struct search_node_list search_expr = STAILQ_HEAD_INITIALIZER(search_expr);
+
+static double speed_factor = 1.0;
+
+static const char *session_dir = _PATH_SUDO_IO_LOGDIR;
+
+static bool terminal_can_resize, terminal_was_resized, follow_mode;
+
+static int terminal_lines, terminal_cols;
+
+static int ttyfd = -1;
+
+static struct iolog_file iolog_files[] = {
+ { false }, /* IOFD_STDIN */
+ { false }, /* IOFD_STDOUT */
+ { false }, /* IOFD_STDERR */
+ { false }, /* IOFD_TTYIN */
+ { false }, /* IOFD_TTYOUT */
+ { true, }, /* IOFD_TIMING */
+};
+
+static const char short_opts[] = "d:f:Fhlm:nRSs:V";
+static struct option long_opts[] = {
+ { "directory", required_argument, NULL, 'd' },
+ { "filter", required_argument, NULL, 'f' },
+ { "follow", no_argument, NULL, 'F' },
+ { "help", no_argument, NULL, 'h' },
+ { "list", no_argument, NULL, 'l' },
+ { "max-wait", required_argument, NULL, 'm' },
+ { "non-interactive", no_argument, NULL, 'n' },
+ { "no-resize", no_argument, NULL, 'R' },
+ { "suspend-wait", no_argument, NULL, 'S' },
+ { "speed", required_argument, NULL, 's' },
+ { "version", no_argument, NULL, 'V' },
+ { NULL, no_argument, NULL, '\0' },
+};
+
+/* XXX move to separate header? (currently in sudoers.h) */
+extern char *get_timestr(time_t, int);
+extern time_t get_date(char *);
+
+static int list_sessions(int, char **, const char *, const char *, const char *);
+static int parse_expr(struct search_node_list *, char **, bool);
+static void read_keyboard(int fd, int what, void *v);
+static int replay_session(int iolog_dir_fd, const char *iolog_dir,
+ struct timespec *offset, struct timespec *max_wait, const char *decimal,
+ bool interactive, bool suspend_wait);
+static void sudoreplay_cleanup(void);
+static void write_output(int fd, int what, void *v);
+static void restore_terminal_size(void);
+static void setup_terminal(struct eventlog *evlog, bool interactive, bool resize);
+sudo_noreturn static void help(void);
+sudo_noreturn static void usage(void);
+
+#define VALID_ID(s) (isalnum((unsigned char)(s)[0]) && \
+ isalnum((unsigned char)(s)[1]) && isalnum((unsigned char)(s)[2]) && \
+ isalnum((unsigned char)(s)[3]) && isalnum((unsigned char)(s)[4]) && \
+ isalnum((unsigned char)(s)[5]) && (s)[6] == '\0')
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+int
+main(int argc, char *argv[])
+{
+ int ch, i, iolog_dir_fd, len, exitcode = EXIT_FAILURE;
+ bool def_filter = true, listonly = false;
+ bool interactive = true, suspend_wait = false, resize = true;
+ const char *decimal, *id, *user = NULL, *pattern = NULL, *tty = NULL;
+ char *cp, *ep, iolog_dir[PATH_MAX];
+ struct timespec offset = { 0, 0};
+ struct eventlog *evlog;
+ struct timespec max_delay_storage, *max_delay = NULL;
+ double dval;
+ debug_decl(main, SUDO_DEBUG_MAIN);
+
+#if defined(SUDO_DEVEL) && defined(__OpenBSD__)
+ {
+ extern char *malloc_options;
+ malloc_options = "S";
+ }
+#endif
+
+ initprogname(argc > 0 ? argv[0] : "sudoreplay");
+ setlocale(LC_ALL, "");
+ decimal = localeconv()->decimal_point;
+ bindtextdomain("sudoers", LOCALEDIR); /* XXX - should have sudoreplay domain */
+ textdomain("sudoers");
+
+ /* Register fatal/fatalx callback. */
+ sudo_fatal_callback_register(sudoreplay_cleanup);
+
+ /* Read sudo.conf and initialize the debug subsystem. */
+ if (sudo_conf_read(NULL, SUDO_CONF_DEBUG) == -1)
+ return EXIT_FAILURE;
+ sudo_debug_register(getprogname(), NULL, NULL,
+ sudo_conf_debug_files(getprogname()), -1);
+
+ while ((ch = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
+ switch (ch) {
+ case 'd':
+ session_dir = optarg;
+ break;
+ case 'f':
+ /* Set the replay filter. */
+ def_filter = false;
+ for (cp = strtok_r(optarg, ",", &ep); cp; cp = strtok_r(NULL, ",", &ep)) {
+ if (strcmp(cp, "stdin") == 0)
+ iolog_files[IOFD_STDIN].enabled = true;
+ else if (strcmp(cp, "stdout") == 0)
+ iolog_files[IOFD_STDOUT].enabled = true;
+ else if (strcmp(cp, "stderr") == 0)
+ iolog_files[IOFD_STDERR].enabled = true;
+ else if (strcmp(cp, "ttyin") == 0)
+ iolog_files[IOFD_TTYIN].enabled = true;
+ else if (strcmp(cp, "ttyout") == 0)
+ iolog_files[IOFD_TTYOUT].enabled = true;
+ else
+ sudo_fatalx(U_("invalid filter option: %s"), optarg);
+ }
+ break;
+ case 'F':
+ follow_mode = true;
+ break;
+ case 'h':
+ help();
+ /* NOTREACHED */
+ case 'l':
+ listonly = true;
+ break;
+ case 'm':
+ errno = 0;
+ dval = strtod(optarg, &ep);
+ if (*ep != '\0' || errno != 0)
+ sudo_fatalx(U_("invalid max wait: %s"), optarg);
+ if (dval <= 0.0) {
+ sudo_timespecclear(&max_delay_storage);
+ } else {
+ max_delay_storage.tv_sec = (time_t)dval;
+ max_delay_storage.tv_nsec = (long)
+ ((dval - (double)max_delay_storage.tv_sec) * 1000000000.0);
+ }
+ max_delay = &max_delay_storage;
+ break;
+ case 'n':
+ interactive = false;
+ break;
+ case 'R':
+ resize = false;
+ break;
+ case 'S':
+ suspend_wait = true;
+ break;
+ case 's':
+ errno = 0;
+ speed_factor = strtod(optarg, &ep);
+ if (*ep != '\0' || errno != 0)
+ sudo_fatalx(U_("invalid speed factor: %s"), optarg);
+ break;
+ case 'V':
+ (void) printf(_("%s version %s\n"), getprogname(), PACKAGE_VERSION);
+ exitcode = EXIT_SUCCESS;
+ goto done;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (listonly) {
+ exitcode = list_sessions(argc, argv, pattern, user, tty);
+ goto done;
+ }
+
+ if (argc != 1)
+ usage();
+
+ /* By default we replay stdout, stderr and ttyout. */
+ if (def_filter) {
+ iolog_files[IOFD_STDOUT].enabled = true;
+ iolog_files[IOFD_STDERR].enabled = true;
+ iolog_files[IOFD_TTYOUT].enabled = true;
+ }
+
+ /* Check for offset in @sec.nsec form at the end of the id. */
+ id = argv[0];
+ if ((cp = strchr(id, '@')) != NULL) {
+ ep = iolog_parse_delay(cp + 1, &offset, decimal);
+ if (ep == NULL || *ep != '\0')
+ sudo_fatalx(U_("invalid time offset %s"), cp + 1);
+ *cp = '\0';
+ }
+
+ /* 6 digit ID in base 36, e.g. 01G712AB or free-form name */
+ if (VALID_ID(id)) {
+ len = snprintf(iolog_dir, sizeof(iolog_dir), "%s/%.2s/%.2s/%.2s",
+ session_dir, id, &id[2], &id[4]);
+ if (len < 0 || len >= ssizeof(iolog_dir))
+ sudo_fatalx(U_("%s/%.2s/%.2s/%.2s: %s"), session_dir,
+ id, &id[2], &id[4], strerror(ENAMETOOLONG));
+ } else if (id[0] == '/') {
+ len = snprintf(iolog_dir, sizeof(iolog_dir), "%s", id);
+ if (len < 0 || len >= ssizeof(iolog_dir))
+ sudo_fatalx(U_("%s/timing: %s"), id, strerror(ENAMETOOLONG));
+ } else {
+ len = snprintf(iolog_dir, sizeof(iolog_dir), "%s/%s", session_dir, id);
+ if (len < 0 || len >= ssizeof(iolog_dir)) {
+ sudo_fatalx(U_("%s/%s: %s"), session_dir, id,
+ strerror(ENAMETOOLONG));
+ }
+ }
+
+ /* Open files for replay, applying replay filter for the -f flag. */
+ if ((iolog_dir_fd = iolog_openat(AT_FDCWD, iolog_dir, O_RDONLY)) == -1)
+ sudo_fatal("%s", iolog_dir);
+ for (i = 0; i < IOFD_MAX; i++) {
+ if (!iolog_open(&iolog_files[i], iolog_dir_fd, i, "r")) {
+ if (errno != ENOENT) {
+ sudo_fatal(U_("unable to open %s/%s"), iolog_dir,
+ iolog_fd_to_name(i));
+ }
+ }
+ }
+ if (!iolog_files[IOFD_TIMING].enabled) {
+ sudo_fatal(U_("unable to open %s/%s"), iolog_dir,
+ iolog_fd_to_name(IOFD_TIMING));
+ }
+
+ /* Parse log file. */
+ if ((evlog = iolog_parse_loginfo(iolog_dir_fd, iolog_dir)) == NULL)
+ goto done;
+ printf(_("Replaying sudo session: %s"), evlog->command);
+ if (evlog->runargv != NULL && evlog->runargv[0] != NULL) {
+ for (i = 1; evlog->runargv[i] != NULL; i++)
+ printf(" %s", evlog->runargv[i]);
+ }
+
+ /* Setup terminal if appropriate. */
+ if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO))
+ interactive = false;
+ setup_terminal(evlog, interactive, resize);
+ putchar('\r');
+ putchar('\n');
+
+ /* Done with parsed log file. */
+ eventlog_free(evlog);
+ evlog = NULL;
+
+ /* Replay session corresponding to iolog_files[]. */
+ exitcode = replay_session(iolog_dir_fd, iolog_dir, &offset, max_delay,
+ decimal, interactive, suspend_wait);
+
+ restore_terminal_size();
+ sudo_term_restore(ttyfd, true);
+done:
+ sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, exitcode);
+ return exitcode;
+}
+
+/*
+ * List of terminals that support xterm-like resizing.
+ * This is not an exhaustive list.
+ * For a list of VT100 style escape codes, see:
+ * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#VT100%20Mode
+ */
+struct term_names {
+ const char *name;
+ unsigned int len;
+} compatible_terms[] = {
+ { "Eterm", 5 },
+ { "aterm", 5 },
+ { "dtterm", 6 },
+ { "gnome", 5 },
+ { "konsole", 7 },
+ { "kvt\0", 4 },
+ { "mlterm", 6 },
+ { "rxvt", 4 },
+ { "xterm", 5 },
+ { NULL, 0 }
+};
+
+struct getsize_closure {
+ int nums[2];
+ int nums_depth;
+ int nums_maxdepth;
+ int state;
+ const char *cp;
+ struct sudo_event *ev;
+ struct timespec timeout;
+};
+
+/* getsize states */
+#define INITIAL 0x00
+#define NEW_NUMBER 0x01
+#define NUMBER 0x02
+#define GOTSIZE 0x04
+#define READCHAR 0x10
+
+/*
+ * Callback for reading the terminal size response.
+ * We use an event for this to support timeouts.
+ */
+static void
+getsize_cb(int fd, int what, void *v)
+{
+ struct getsize_closure *gc = v;
+ unsigned char ch = '\0';
+ debug_decl(getsize_cb, SUDO_DEBUG_UTIL);
+
+ for (;;) {
+ if (gc->cp[0] == '\0') {
+ gc->state = GOTSIZE;
+ goto done;
+ }
+ if (ISSET(gc->state, READCHAR)) {
+ ssize_t nread = read(ttyfd, &ch, 1);
+ switch (nread) {
+ case -1:
+ if (errno == EAGAIN)
+ goto another;
+ FALLTHROUGH;
+ case 0:
+ goto done;
+ default:
+ CLR(gc->state, READCHAR);
+ break;
+ }
+ }
+ switch (gc->state) {
+ case INITIAL:
+ if (ch == 0233 && gc->cp[0] == '\033') {
+ /* meta escape, equivalent to ESC[ */
+ ch = '[';
+ gc->cp++;
+ }
+ if (gc->cp[0] == '%' && gc->cp[1] == 'd') {
+ gc->state = NEW_NUMBER;
+ continue;
+ }
+ if (gc->cp[0] != ch) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "got %d, expected %d", ch, gc->cp[0]);
+ goto done;
+ }
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "got %d", ch);
+ SET(gc->state, READCHAR);
+ gc->cp++;
+ break;
+ case NEW_NUMBER:
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "parsing number");
+ if (!isdigit(ch))
+ goto done;
+ gc->cp += 2;
+ if (gc->nums_depth > gc->nums_maxdepth)
+ goto done;
+ gc->nums[gc->nums_depth] = 0;
+ gc->state = NUMBER;
+ FALLTHROUGH;
+ case NUMBER:
+ if (!isdigit(ch)) {
+ /* done with number, reparse ch */
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "number %d (ch %d)", gc->nums[gc->nums_depth], ch);
+ gc->nums_depth++;
+ gc->state = INITIAL;
+ continue;
+ }
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "got %d", ch);
+ if (gc->nums[gc->nums_depth] > INT_MAX / 10)
+ goto done;
+ gc->nums[gc->nums_depth] *= 10;
+ gc->nums[gc->nums_depth] += (ch - '0');
+ SET(gc->state, READCHAR);
+ break;
+ }
+ }
+
+another:
+ if (sudo_ev_add(NULL, gc->ev, &gc->timeout, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+done:
+ debug_return;
+}
+
+
+/*
+ * Get the terminal size using vt100 terminal escapes.
+ */
+static bool
+xterm_get_size(int *new_lines, int *new_cols)
+{
+ struct sudo_event_base *evbase;
+ struct getsize_closure gc;
+ const char getsize_request[] = "\0337\033[r\033[999;999H\033[6n";
+ const char getsize_response[] = "\033[%d;%dR";
+ bool ret = false;
+ debug_decl(xterm_get_size, SUDO_DEBUG_UTIL);
+
+ /* request the terminal's size */
+ if (write(ttyfd, getsize_request, strlen(getsize_request)) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "%s: error writing xterm size request", __func__);
+ goto done;
+ }
+
+ /*
+ * Callback info for reading back the size with a 10 second timeout.
+ * We expect two numbers (lines and cols).
+ */
+ gc.state = INITIAL|READCHAR;
+ gc.nums_depth = 0;
+ gc.nums_maxdepth = 1;
+ gc.cp = getsize_response;
+ gc.timeout.tv_sec = 10;
+ gc.timeout.tv_nsec = 0;
+
+ /* Setup an event for reading the terminal size */
+ evbase = sudo_ev_base_alloc();
+ if (evbase == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ gc.ev = sudo_ev_alloc(ttyfd, SUDO_EV_READ, getsize_cb, &gc);
+ if (gc.ev == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ /* Read back terminal size response */
+ if (sudo_ev_add(evbase, gc.ev, &gc.timeout, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+ sudo_ev_dispatch(evbase);
+
+ if (gc.state == GOTSIZE) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "terminal size %d x %x", gc.nums[0], gc.nums[1]);
+ *new_lines = gc.nums[0];
+ *new_cols = gc.nums[1];
+ ret = true;
+ }
+
+ sudo_ev_base_free(evbase);
+ sudo_ev_free(gc.ev);
+
+done:
+ debug_return_bool(ret);
+}
+
+/*
+ * Set the size of the text area to lines and cols.
+ * Depending on the terminal implementation, the window itself may
+ * or may not shrink to a smaller size.
+ */
+static bool
+xterm_set_size(int lines, int cols)
+{
+ const char setsize_fmt[] = "\033[8;%d;%dt";
+ int len, new_lines, new_cols;
+ bool ret = false;
+ char buf[1024];
+ debug_decl(xterm_set_size, SUDO_DEBUG_UTIL);
+
+ /* XXX - save cursor and position restore after resizing */
+ len = snprintf(buf, sizeof(buf), setsize_fmt, lines, cols);
+ if (len < 0 || len >= ssizeof(buf)) {
+ /* not possible due to size of buf */
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: internal error, buffer too small?", __func__);
+ goto done;
+ }
+ if (write(ttyfd, buf, strlen(buf)) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "%s: error writing xterm resize request", __func__);
+ goto done;
+ }
+ /* XXX - keyboard input will interfere with this */
+ if (!xterm_get_size(&new_lines, &new_cols))
+ goto done;
+ if (lines == new_lines && cols == new_cols)
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+static void
+setup_terminal(struct eventlog *evlog, bool interactive, bool resize)
+{
+ const char *term;
+ debug_decl(check_terminal, SUDO_DEBUG_UTIL);
+
+ fflush(stdout);
+
+ /* Open fd for /dev/tty and set to raw mode. */
+ if (interactive) {
+ ttyfd = open(_PATH_TTY, O_RDWR);
+ if (ttyfd == -1)
+ sudo_fatal("%s", U_("unable to set tty to raw mode"));
+ while (!sudo_term_raw(ttyfd, SUDO_TERM_ISIG)) {
+ if (errno != EINTR)
+ sudo_fatal("%s", U_("unable to set tty to raw mode"));
+ kill(getpid(), SIGTTOU);
+ }
+ }
+
+ /* Find terminal size if the session has size info. */
+ if (evlog->lines == 0 && evlog->columns == 0) {
+ /* no tty size info, hope for the best... */
+ debug_return;
+ }
+
+ if (resize && ttyfd != -1) {
+ term = getenv("TERM");
+ if (term != NULL && *term != '\0') {
+ struct term_names *tn;
+
+ for (tn = compatible_terms; tn->name != NULL; tn++) {
+ if (strncmp(term, tn->name, tn->len) == 0) {
+ /* xterm-like terminals can resize themselves. */
+ if (xterm_get_size(&terminal_lines, &terminal_cols))
+ terminal_can_resize = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!terminal_can_resize) {
+ /* either not xterm or not interactive */
+ sudo_get_ttysize(ttyfd, &terminal_lines, &terminal_cols);
+ }
+
+ if (evlog->lines == terminal_lines && evlog->columns == terminal_cols) {
+ /* nothing to change */
+ debug_return;
+ }
+
+ if (terminal_can_resize) {
+ /* session terminal size is different, try to resize ours */
+ if (xterm_set_size(evlog->lines, evlog->columns)) {
+ /* success */
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "resized terminal to %d x %x", evlog->lines, evlog->columns);
+ terminal_was_resized = true;
+ debug_return;
+ }
+ /* resize failed, don't try again */
+ terminal_can_resize = false;
+ }
+
+ if (evlog->lines > terminal_lines || evlog->columns > terminal_cols) {
+ puts(_("Warning: your terminal is too small to properly replay the log."));
+ printf(_("Log geometry is %d x %d, your terminal's geometry is %d x %d."), evlog->lines, evlog->columns, terminal_lines, terminal_cols);
+ }
+ debug_return;
+}
+
+static void
+resize_terminal(int lines, int cols)
+{
+ debug_decl(resize_terminal, SUDO_DEBUG_UTIL);
+
+ if (terminal_can_resize) {
+ if (xterm_set_size(lines, cols))
+ terminal_was_resized = true;
+ else
+ terminal_can_resize = false;
+ }
+
+ debug_return;
+}
+
+static void
+restore_terminal_size(void)
+{
+ debug_decl(restore_terminal, SUDO_DEBUG_UTIL);
+
+ if (terminal_was_resized) {
+ /* We are still in raw mode, hence the carriage return. */
+ putchar('\r');
+ fputs(U_("Replay finished, press any key to restore the terminal."),
+ stdout);
+ fflush(stdout);
+ (void)getchar();
+ xterm_set_size(terminal_lines, terminal_cols);
+ putchar('\r');
+ putchar('\n');
+ }
+
+ debug_return;
+}
+
+static bool
+iolog_complete(struct replay_closure *closure)
+{
+ struct stat sb;
+ debug_decl(iolog_complete, SUDO_DEBUG_UTIL);
+
+ if (fstatat(closure->iolog_dir_fd, "timing", &sb, 0) != -1) {
+ if (ISSET(sb.st_mode, S_IWUSR|S_IWGRP|S_IWOTH))
+ debug_return_bool(false);
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Read the next record from the timing file and schedule a delay
+ * event with the specified timeout.
+ * In follow mode, ignore EOF and just delay for a short time.
+ * Return 0 on success, 1 on EOF and -1 on error.
+ */
+static int
+get_timing_record(struct replay_closure *closure)
+{
+ struct timing_closure *timing = &closure->timing;
+ bool nodelay = false;
+ debug_decl(get_timing_record, SUDO_DEBUG_UTIL);
+
+ if (follow_mode && timing->event == IO_EVENT_COUNT) {
+ /* In follow mode, we already waited. */
+ nodelay = true;
+ }
+
+ switch (iolog_read_timing_record(&iolog_files[IOFD_TIMING], timing)) {
+ case -1:
+ /* error */
+ debug_return_int(-1);
+ case 1:
+ /* EOF */
+ if (!follow_mode || iolog_complete(closure)) {
+ debug_return_int(1);
+ }
+ /* Follow mode, keep reading until done. */
+ iolog_clearerr(&iolog_files[IOFD_TIMING]);
+ timing->delay.tv_sec = 0;
+ timing->delay.tv_nsec = 1000000;
+ timing->iol = NULL;
+ timing->event = IO_EVENT_COUNT;
+ break;
+ default:
+ /* Record number bytes to read. */
+ if (timing->event != IO_EVENT_WINSIZE &&
+ timing->event != IO_EVENT_SUSPEND) {
+ closure->iobuf.len = 0;
+ closure->iobuf.off = 0;
+ closure->iobuf.lastc = '\0';
+ closure->iobuf.toread = timing->u.nbytes;
+ }
+
+ if (sudo_timespecisset(closure->offset)) {
+ if (sudo_timespeccmp(&timing->delay, closure->offset, >)) {
+ sudo_timespecsub(&timing->delay, closure->offset, &timing->delay);
+ sudo_timespecclear(closure->offset);
+ } else {
+ sudo_timespecsub(closure->offset, &timing->delay, closure->offset);
+ sudo_timespecclear(&timing->delay);
+ }
+ }
+
+ if (nodelay) {
+ /* Already waited, fire immediately. */
+ timing->delay.tv_sec = 0;
+ timing->delay.tv_nsec = 0;
+ } else {
+ /* Adjust delay using speed factor and max_delay. */
+ iolog_adjust_delay(&timing->delay, closure->max_delay,
+ speed_factor);
+ }
+ break;
+ }
+
+ /* Schedule the delay event. */
+ if (sudo_ev_add(closure->evbase, closure->delay_ev, &timing->delay, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ debug_return_int(0);
+}
+
+/*
+ * Read next timing record.
+ * Exits the event loop on EOF, breaks out on error.
+ */
+static void
+next_timing_record(struct replay_closure *closure)
+{
+ debug_decl(next_timing_record, SUDO_DEBUG_UTIL);
+
+again:
+ switch (get_timing_record(closure)) {
+ case 0:
+ /* success */
+ if (closure->timing.event == IO_EVENT_SUSPEND &&
+ closure->timing.u.signo == SIGCONT && !closure->suspend_wait) {
+ /* Ignore time spent suspended. */
+ goto again;
+ }
+ break;
+ case 1:
+ /* EOF */
+ sudo_ev_loopexit(closure->evbase);
+ break;
+ default:
+ /* error */
+ sudo_ev_loopbreak(closure->evbase);
+ break;
+ }
+ debug_return;
+}
+
+static bool
+fill_iobuf(struct replay_closure *closure)
+{
+ const size_t space = sizeof(closure->iobuf.buf) - closure->iobuf.len;
+ const struct timing_closure *timing = &closure->timing;
+ const char *errstr;
+ debug_decl(fill_iobuf, SUDO_DEBUG_UTIL);
+
+ if (closure->iobuf.toread != 0 && space != 0) {
+ const size_t len =
+ closure->iobuf.toread < space ? closure->iobuf.toread : space;
+ ssize_t nread = iolog_read(timing->iol,
+ closure->iobuf.buf + closure->iobuf.off, len, &errstr);
+ if (nread <= 0) {
+ if (nread == 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s/%s: premature EOF, expected %zu bytes",
+ closure->iolog_dir, iolog_fd_to_name(timing->event),
+ closure->iobuf.toread);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s/%s: read error: %s", closure->iolog_dir,
+ iolog_fd_to_name(timing->event), errstr);
+ }
+ sudo_warnx(U_("unable to read %s/%s: %s"),
+ closure->iolog_dir, iolog_fd_to_name(timing->event), errstr);
+ debug_return_bool(false);
+ }
+ closure->iobuf.toread -= (size_t)nread;
+ closure->iobuf.len += (size_t)nread;
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Called when the inter-record delay has expired.
+ * Depending on the record type, either reads the next
+ * record or changes window size.
+ */
+static void
+delay_cb(int fd, int what, void *v)
+{
+ struct replay_closure *closure = v;
+ struct timing_closure *timing = &closure->timing;
+ debug_decl(delay_cb, SUDO_DEBUG_UTIL);
+
+ switch (timing->event) {
+ case IO_EVENT_WINSIZE:
+ resize_terminal(timing->u.winsize.lines, timing->u.winsize.cols);
+ break;
+ case IO_EVENT_STDIN:
+ if (iolog_files[IOFD_STDIN].enabled)
+ timing->iol = &iolog_files[IOFD_STDIN];
+ break;
+ case IO_EVENT_STDOUT:
+ if (iolog_files[IOFD_STDOUT].enabled)
+ timing->iol = &iolog_files[IOFD_STDOUT];
+ break;
+ case IO_EVENT_STDERR:
+ if (iolog_files[IOFD_STDERR].enabled)
+ timing->iol = &iolog_files[IOFD_STDERR];
+ break;
+ case IO_EVENT_TTYIN:
+ if (iolog_files[IOFD_TTYIN].enabled)
+ timing->iol = &iolog_files[IOFD_TTYIN];
+ break;
+ case IO_EVENT_TTYOUT:
+ if (iolog_files[IOFD_TTYOUT].enabled)
+ timing->iol = &iolog_files[IOFD_TTYOUT];
+ break;
+ }
+
+ if (timing->iol != NULL) {
+ /* If the stream is open, enable the write event. */
+ if (sudo_ev_add(closure->evbase, closure->output_ev, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+ } else {
+ /* Not replaying, get the next timing record and continue. */
+ next_timing_record(closure);
+ }
+
+ debug_return;
+}
+
+static void
+replay_closure_free(struct replay_closure *closure)
+{
+ /*
+ * Free events and event base, then the closure itself.
+ */
+ if (closure->iolog_dir_fd != -1)
+ close(closure->iolog_dir_fd);
+ sudo_ev_free(closure->delay_ev);
+ sudo_ev_free(closure->keyboard_ev);
+ sudo_ev_free(closure->output_ev);
+ sudo_ev_free(closure->sighup_ev);
+ sudo_ev_free(closure->sigint_ev);
+ sudo_ev_free(closure->sigquit_ev);
+ sudo_ev_free(closure->sigterm_ev);
+ sudo_ev_free(closure->sigtstp_ev);
+ sudo_ev_base_free(closure->evbase);
+ free(closure);
+}
+
+static void
+signal_cb(int signo, int what, void *v)
+{
+ struct replay_closure *closure = v;
+ debug_decl(signal_cb, SUDO_DEBUG_UTIL);
+
+ switch (signo) {
+ case SIGHUP:
+ case SIGINT:
+ case SIGQUIT:
+ case SIGTERM:
+ /* Free the event base and restore signal handlers. */
+ replay_closure_free(closure);
+
+ /* Restore the terminal and die. */
+ sudoreplay_cleanup();
+ kill(getpid(), signo);
+ break;
+ case SIGTSTP:
+ /* Ignore ^Z since we have no way to restore the screen. */
+ break;
+ }
+
+ debug_return;
+}
+
+static struct replay_closure *
+replay_closure_alloc(int iolog_dir_fd, const char *iolog_dir,
+ struct timespec *offset, struct timespec *max_delay, const char *decimal,
+ bool interactive, bool suspend_wait)
+{
+ struct replay_closure *closure;
+ debug_decl(replay_closure_alloc, SUDO_DEBUG_UTIL);
+
+ if ((closure = calloc(1, sizeof(*closure))) == NULL)
+ debug_return_ptr(NULL);
+
+ closure->iolog_dir_fd = iolog_dir_fd;
+ closure->iolog_dir = iolog_dir;
+ closure->interactive = interactive;
+ closure->offset = offset;
+ closure->suspend_wait = suspend_wait;
+ closure->max_delay = max_delay;
+ closure->timing.decimal = decimal;
+
+ /*
+ * Setup event base and delay, input and output events.
+ * If interactive, take input from and write to /dev/tty.
+ * If not interactive there is no input event.
+ */
+ closure->evbase = sudo_ev_base_alloc();
+ if (closure->evbase == NULL)
+ goto bad;
+ closure->delay_ev = sudo_ev_alloc(-1, SUDO_EV_TIMEOUT, delay_cb, closure);
+ if (closure->delay_ev == NULL)
+ goto bad;
+ if (interactive) {
+ closure->keyboard_ev = sudo_ev_alloc(ttyfd, SUDO_EV_READ|SUDO_EV_PERSIST,
+ read_keyboard, closure);
+ if (closure->keyboard_ev == NULL)
+ goto bad;
+ if (sudo_ev_add(closure->evbase, closure->keyboard_ev, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+ }
+ closure->output_ev = sudo_ev_alloc(interactive ? ttyfd : STDOUT_FILENO,
+ SUDO_EV_WRITE, write_output, closure);
+ if (closure->output_ev == NULL)
+ goto bad;
+
+ /*
+ * Setup signal events, we need to restore the terminal if killed.
+ */
+ closure->sighup_ev = sudo_ev_alloc(SIGHUP, SUDO_EV_SIGNAL, signal_cb,
+ closure);
+ if (closure->sighup_ev == NULL)
+ goto bad;
+ if (sudo_ev_add(closure->evbase, closure->sighup_ev, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ closure->sigint_ev = sudo_ev_alloc(SIGINT, SUDO_EV_SIGNAL, signal_cb,
+ closure);
+ if (closure->sigint_ev == NULL)
+ goto bad;
+ if (sudo_ev_add(closure->evbase, closure->sigint_ev, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ closure->sigquit_ev = sudo_ev_alloc(SIGQUIT, SUDO_EV_SIGNAL, signal_cb,
+ closure);
+ if (closure->sigquit_ev == NULL)
+ goto bad;
+ if (sudo_ev_add(closure->evbase, closure->sigquit_ev, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ closure->sigterm_ev = sudo_ev_alloc(SIGTERM, SUDO_EV_SIGNAL, signal_cb,
+ closure);
+ if (closure->sigterm_ev == NULL)
+ goto bad;
+ if (sudo_ev_add(closure->evbase, closure->sigterm_ev, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ closure->sigtstp_ev = sudo_ev_alloc(SIGTSTP, SUDO_EV_SIGNAL, signal_cb,
+ closure);
+ if (closure->sigtstp_ev == NULL)
+ goto bad;
+ if (sudo_ev_add(closure->evbase, closure->sigtstp_ev, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ debug_return_ptr(closure);
+bad:
+ replay_closure_free(closure);
+ debug_return_ptr(NULL);
+}
+
+static int
+replay_session(int iolog_dir_fd, const char *iolog_dir, struct timespec *offset,
+ struct timespec *max_delay, const char *decimal, bool interactive,
+ bool suspend_wait)
+{
+ struct replay_closure *closure;
+ int ret = 0;
+ debug_decl(replay_session, SUDO_DEBUG_UTIL);
+
+ /* Allocate the delay closure and read the first timing record. */
+ closure = replay_closure_alloc(iolog_dir_fd, iolog_dir, offset, max_delay,
+ decimal, interactive, suspend_wait);
+ if (get_timing_record(closure) != 0) {
+ ret = 1;
+ goto done;
+ }
+
+ /* Run event loop. */
+ sudo_ev_dispatch(closure->evbase);
+ if (sudo_ev_got_break(closure->evbase))
+ ret = 1;
+
+done:
+ /* Clean up and return. */
+ replay_closure_free(closure);
+ debug_return_int(ret);
+}
+
+/*
+ * Write the I/O buffer.
+ */
+static void
+write_output(int fd, int what, void *v)
+{
+ struct replay_closure *closure = v;
+ const struct timing_closure *timing = &closure->timing;
+ struct io_buffer *iobuf = &closure->iobuf;
+ int iovcnt = 1;
+ struct iovec iov[2];
+ bool added_cr = false;
+ size_t nbytes;
+ ssize_t nwritten;
+ debug_decl(write_output, SUDO_DEBUG_UTIL);
+
+ /* Refill iobuf if there is more to read and buf is empty. */
+ if (!fill_iobuf(closure)) {
+ sudo_ev_loopbreak(closure->evbase);
+ debug_return;
+ }
+
+ nbytes = iobuf->len - iobuf->off;
+ iov[0].iov_base = iobuf->buf + iobuf->off;
+ iov[0].iov_len = nbytes;
+
+ if (closure->interactive &&
+ (timing->event == IO_EVENT_STDOUT || timing->event == IO_EVENT_STDERR)) {
+ char *nl;
+
+ /*
+ * We may need to insert a carriage return before the newline.
+ * Note that the carriage return may have already been written.
+ */
+ nl = memchr(iov[0].iov_base, '\n', iov[0].iov_len);
+ if (nl != NULL) {
+ size_t len = (size_t)(nl - (char *)iov[0].iov_base);
+ if ((nl == iov[0].iov_base && iobuf->lastc != '\r') ||
+ (nl != iov[0].iov_base && nl[-1] != '\r')) {
+ iov[0].iov_len = len;
+ iov[1].iov_base = (char *)"\r\n";
+ iov[1].iov_len = 2;
+ iovcnt = 2;
+ nbytes = iov[0].iov_len + iov[1].iov_len;
+ added_cr = true;
+ }
+ }
+ }
+
+ nwritten = writev(fd, iov, iovcnt);
+ switch (nwritten) {
+ case -1:
+ if (errno != EINTR && errno != EAGAIN)
+ sudo_fatal(U_("unable to write to %s"), "stdout");
+ break;
+ case 0:
+ /* Should not happen. */
+ break;
+ default:
+ if (added_cr && (size_t)nwritten >= nbytes - 1) {
+ /* The last char written was either '\r' or '\n'. */
+ iobuf->lastc = (size_t)nwritten == nbytes ? '\n' : '\r';
+ } else {
+ /* Stash the last char written. */
+ iobuf->lastc = *((char *)iov[0].iov_base + nwritten);
+ }
+ if (added_cr) {
+ /* Subtract one for the carriage return we added above. */
+ nwritten--;
+ }
+ iobuf->off += (size_t)nwritten;
+ break;
+ }
+
+ if (iobuf->off == iobuf->len) {
+ /* Write complete, go to next timing entry if possible. */
+ switch (get_timing_record(closure)) {
+ case 0:
+ /* success */
+ break;
+ case 1:
+ /* EOF */
+ sudo_ev_loopexit(closure->evbase);
+ break;
+ default:
+ /* error */
+ sudo_ev_loopbreak(closure->evbase);
+ break;
+ }
+ } else {
+ /* Reschedule event to write remainder. */
+ if (sudo_ev_add(NULL, closure->output_ev, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+ }
+ debug_return;
+}
+
+/*
+ * Build expression list from search args
+ */
+static int
+parse_expr(struct search_node_list *head, char *argv[], bool sub_expr)
+{
+ bool or = false, not = false;
+ struct search_node *sn;
+ char type, **av;
+ const char *errstr;
+ debug_decl(parse_expr, SUDO_DEBUG_UTIL);
+
+ for (av = argv; *av != NULL; av++) {
+ switch (av[0][0]) {
+ case 'a': /* and (ignore) */
+ if (strncmp(*av, "and", strlen(*av)) != 0)
+ goto bad;
+ continue;
+ case 'o': /* or */
+ if (strncmp(*av, "or", strlen(*av)) != 0)
+ goto bad;
+ or = true;
+ continue;
+ case '!': /* negate */
+ if (av[0][1] != '\0')
+ goto bad;
+ not = true;
+ continue;
+ case 'c': /* cwd or command */
+ if (av[0][1] == '\0')
+ sudo_fatalx(U_("ambiguous expression \"%s\""), *av);
+ if (strncmp(*av, "cwd", strlen(*av)) == 0)
+ type = ST_CWD;
+ else if (strncmp(*av, "command", strlen(*av)) == 0)
+ type = ST_PATTERN;
+ else
+ goto bad;
+ break;
+ case 'f': /* from date */
+ if (strncmp(*av, "fromdate", strlen(*av)) != 0)
+ goto bad;
+ type = ST_FROMDATE;
+ break;
+ case 'g': /* runas group */
+ if (strncmp(*av, "group", strlen(*av)) != 0)
+ goto bad;
+ type = ST_RUNASGROUP;
+ break;
+ case 'h': /* host */
+ if (strncmp(*av, "host", strlen(*av)) != 0)
+ goto bad;
+ type = ST_HOST;
+ break;
+ case 'r': /* runas user */
+ if (strncmp(*av, "runas", strlen(*av)) != 0)
+ goto bad;
+ type = ST_RUNASUSER;
+ break;
+ case 't': /* tty or to date */
+ if (av[0][1] == '\0')
+ sudo_fatalx(U_("ambiguous expression \"%s\""), *av);
+ if (strncmp(*av, "todate", strlen(*av)) == 0)
+ type = ST_TODATE;
+ else if (strncmp(*av, "tty", strlen(*av)) == 0)
+ type = ST_TTY;
+ else
+ goto bad;
+ break;
+ case 'u': /* user */
+ if (strncmp(*av, "user", strlen(*av)) != 0)
+ goto bad;
+ type = ST_USER;
+ break;
+ case '(': /* start sub-expression */
+ if (av[0][1] != '\0')
+ goto bad;
+ type = ST_EXPR;
+ break;
+ case ')': /* end sub-expression */
+ if (av[0][1] != '\0')
+ goto bad;
+ if (!sub_expr)
+ sudo_fatalx("%s", U_("unmatched ')' in expression"));
+ debug_return_int((int)(av - argv) + 1);
+ default:
+ bad:
+ sudo_fatalx(U_("unknown search term \"%s\""), *av);
+ /* NOTREACHED */
+ }
+
+ /* Allocate new search node */
+ if ((sn = calloc(1, sizeof(*sn))) == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ sn->type = type;
+ sn->or = or;
+ sn->negated = not;
+ if (type == ST_EXPR) {
+ STAILQ_INIT(&sn->u.expr);
+ av += parse_expr(&sn->u.expr, av + 1, true);
+ } else {
+ if (*(++av) == NULL)
+ sudo_fatalx(U_("%s requires an argument"), av[-1]);
+ if (type == ST_PATTERN) {
+ if (!sudo_regex_compile(&sn->u.cmdre, *av, &errstr)) {
+ sudo_fatalx(U_("invalid regular expression \"%s\": %s"),
+ *av, U_(errstr));
+ }
+ } else if (type == ST_TODATE || type == ST_FROMDATE) {
+ sn->u.tstamp.tv_sec = get_date(*av);
+ sn->u.tstamp.tv_nsec = 0;
+ if (sn->u.tstamp.tv_sec == -1)
+ sudo_fatalx(U_("could not parse date \"%s\""), *av);
+ } else {
+ sn->u.ptr = *av;
+ }
+ }
+ not = or = false; /* reset state */
+ STAILQ_INSERT_TAIL(head, sn, entries);
+ }
+ if (sub_expr)
+ sudo_fatalx("%s", U_("unmatched '(' in expression"));
+ if (or)
+ sudo_fatalx("%s", U_("illegal trailing \"or\""));
+ if (not)
+ sudo_fatalx("%s", U_("illegal trailing \"!\""));
+
+ debug_return_int((int)(av - argv));
+}
+
+static char *
+expand_command(struct eventlog *evlog, char **newbuf)
+{
+ size_t len, bufsize = strlen(evlog->command) + 1;
+ char *cp, *buf;
+ int ac;
+ debug_decl(expand_command, SUDO_DEBUG_UTIL);
+
+ if (evlog->runargv == NULL || evlog->runargv[0] == NULL || evlog->runargv[1] == NULL) {
+ /* No arguments, we can use the command as-is. */
+ *newbuf = NULL;
+ debug_return_str(evlog->command);
+ }
+
+ /* Skip argv[0], we use evlog->command instead. */
+ for (ac = 1; evlog->runargv[ac] != NULL; ac++)
+ bufsize += strlen(evlog->runargv[ac]) + 1;
+
+ if ((buf = malloc(bufsize)) == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ cp = buf;
+
+ len = strlcpy(cp, evlog->command, bufsize);
+ if (len >= bufsize)
+ sudo_fatalx(U_("internal error, %s overflow"), __func__);
+ cp += len;
+ bufsize -= len;
+
+ for (ac = 1; evlog->runargv[ac] != NULL; ac++) {
+ if (bufsize < 2)
+ sudo_fatalx(U_("internal error, %s overflow"), __func__);
+ *cp++ = ' ';
+ bufsize--;
+
+ len = strlcpy(cp, evlog->runargv[ac], bufsize);
+ if (len >= bufsize)
+ sudo_fatalx(U_("internal error, %s overflow"), __func__);
+ cp += len;
+ bufsize -= len;
+ }
+
+ *newbuf = buf;
+ debug_return_str(buf);
+}
+
+static bool
+match_expr(struct search_node_list *head, struct eventlog *evlog, bool last_match)
+{
+ struct search_node *sn;
+ bool res = false, matched = last_match;
+ char *tofree;
+ int rc;
+ debug_decl(match_expr, SUDO_DEBUG_UTIL);
+
+ STAILQ_FOREACH(sn, head, entries) {
+ switch (sn->type) {
+ case ST_EXPR:
+ res = match_expr(&sn->u.expr, evlog, matched);
+ break;
+ case ST_CWD:
+ if (evlog->cwd != NULL)
+ res = strcmp(sn->u.cwd, evlog->cwd) == 0;
+ break;
+ case ST_HOST:
+ if (evlog->submithost != NULL)
+ res = strcmp(sn->u.host, evlog->submithost) == 0;
+ break;
+ case ST_TTY:
+ if (evlog->ttyname != NULL)
+ res = strcmp(sn->u.tty, evlog->ttyname) == 0;
+ break;
+ case ST_RUNASGROUP:
+ if (evlog->rungroup != NULL)
+ res = strcmp(sn->u.runas_group, evlog->rungroup) == 0;
+ break;
+ case ST_RUNASUSER:
+ if (evlog->runuser != NULL)
+ res = strcmp(sn->u.runas_user, evlog->runuser) == 0;
+ break;
+ case ST_USER:
+ if (evlog->submituser != NULL)
+ res = strcmp(sn->u.user, evlog->submituser) == 0;
+ break;
+ case ST_PATTERN:
+ rc = regexec(&sn->u.cmdre, expand_command(evlog, &tofree),
+ 0, NULL, 0);
+ if (rc && rc != REG_NOMATCH) {
+ char buf[BUFSIZ];
+ regerror(rc, &sn->u.cmdre, buf, sizeof(buf));
+ sudo_fatalx("%s", buf);
+ }
+ res = rc == REG_NOMATCH ? 0 : 1;
+ free(tofree);
+ break;
+ case ST_FROMDATE:
+ res = sudo_timespeccmp(&evlog->submit_time, &sn->u.tstamp, >=);
+ break;
+ case ST_TODATE:
+ res = sudo_timespeccmp(&evlog->submit_time, &sn->u.tstamp, <=);
+ break;
+ default:
+ sudo_fatalx(U_("unknown search type %d"), sn->type);
+ /* NOTREACHED */
+ }
+ if (sn->negated)
+ res = !res;
+ matched = sn->or ? (res || last_match) : (res && last_match);
+ last_match = matched;
+ }
+ debug_return_bool(matched);
+}
+
+static int
+list_session(struct sudo_lbuf *lbuf, char *log_dir, regex_t *re,
+ const char *user, const char *tty)
+{
+ struct eventlog *evlog = NULL;
+ const char *timestr;
+ int ret = -1;
+ debug_decl(list_session, SUDO_DEBUG_UTIL);
+
+ if ((evlog = iolog_parse_loginfo(-1, log_dir)) == NULL)
+ goto done;
+
+ if (evlog->command == NULL || evlog->submituser == NULL ||
+ evlog->runuser == NULL) {
+ goto done;
+ }
+ evlog->iolog_file = log_dir + strlen(session_dir) + 1;
+
+ /* Match on search expression if there is one. */
+ if (!STAILQ_EMPTY(&search_expr) && !match_expr(&search_expr, evlog, true))
+ goto done;
+
+ timestr = get_timestr(evlog->submit_time.tv_sec, 1);
+ sudo_lbuf_append_esc(lbuf, LBUF_ESC_CNTRL, "%s : %s : ",
+ timestr ? timestr : "invalid date", evlog->submituser);
+
+ if (eventlog_store_sudo(EVLOG_ACCEPT, evlog, lbuf)) {
+ puts(lbuf->buf);
+ ret = 0;
+ }
+
+done:
+ lbuf->error = 0;
+ lbuf->len = 0;
+ eventlog_free(evlog);
+ debug_return_int(ret);
+}
+
+static int
+session_compare(const void *v1, const void *v2)
+{
+ const char *s1 = *(const char **)v1;
+ const char *s2 = *(const char **)v2;
+ return strcmp(s1, s2);
+}
+
+/* XXX - always returns 0, calls sudo_fatal() on failure */
+static int
+find_sessions(const char *dir, regex_t *re, const char *user, const char *tty)
+{
+ DIR *d;
+ struct dirent *dp;
+ struct stat sb;
+ struct sudo_lbuf lbuf;
+ size_t sdlen, sessions_len = 0, sessions_size = 0;
+ size_t i;
+ int len;
+ char pathbuf[PATH_MAX], **sessions = NULL;
+#ifdef HAVE_STRUCT_DIRENT_D_TYPE
+ bool checked_type = true;
+#else
+ const bool checked_type = false;
+#endif
+ debug_decl(find_sessions, SUDO_DEBUG_UTIL);
+
+ sudo_lbuf_init(&lbuf, NULL, 0, NULL, 0);
+
+ d = opendir(dir);
+ if (d == NULL)
+ sudo_fatal(U_("unable to open %s"), dir);
+
+ /* XXX - would be faster to use openat() and relative names */
+ sdlen = strlcpy(pathbuf, dir, sizeof(pathbuf));
+ if (sdlen + 1 >= sizeof(pathbuf)) {
+ errno = ENAMETOOLONG;
+ sudo_fatal("%s/", dir);
+ }
+ pathbuf[sdlen++] = '/';
+ pathbuf[sdlen] = '\0';
+
+ /* Store potential session dirs for sorting. */
+ while ((dp = readdir(d)) != NULL) {
+ /* Skip "." and ".." */
+ if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
+ (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
+ continue;
+#ifdef HAVE_STRUCT_DIRENT_D_TYPE
+ if (checked_type) {
+ if (dp->d_type != DT_DIR) {
+ /* Not all file systems support d_type. */
+ if (dp->d_type != DT_UNKNOWN)
+ continue;
+ checked_type = false;
+ }
+ }
+#endif
+
+ /* Add name to session list. */
+ if (sessions_len + 1 > sessions_size) {
+ if (sessions_size == 0)
+ sessions_size = 36 * 36 / 2;
+ sessions = reallocarray(sessions, sessions_size, 2 * sizeof(char *));
+ if (sessions == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ sessions_size *= 2;
+ }
+ if ((sessions[sessions_len] = strdup(dp->d_name)) == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ sessions_len++;
+ }
+ closedir(d);
+
+ /* Sort and list the sessions. */
+ if (sessions != NULL) {
+ qsort(sessions, sessions_len, sizeof(char *), session_compare);
+ for (i = 0; i < sessions_len; i++) {
+ len = snprintf(&pathbuf[sdlen], sizeof(pathbuf) - sdlen,
+ "%s/log", sessions[i]);
+ if (len < 0 || (size_t)len >= sizeof(pathbuf) - sdlen) {
+ errno = ENAMETOOLONG;
+ sudo_fatal("%s/%s/log", dir, sessions[i]);
+ }
+ free(sessions[i]);
+
+ /* Check for dir with a log file. */
+ if (lstat(pathbuf, &sb) == 0 && S_ISREG(sb.st_mode)) {
+ pathbuf[sdlen + (size_t)len - 4] = '\0';
+ list_session(&lbuf, pathbuf, re, user, tty);
+ } else {
+ /* Strip off "/log" and recurse if a non-log dir. */
+ pathbuf[sdlen + (size_t)len - 4] = '\0';
+ if (checked_type ||
+ (lstat(pathbuf, &sb) == 0 && S_ISDIR(sb.st_mode)))
+ find_sessions(pathbuf, re, user, tty);
+ }
+ }
+ free(sessions);
+ }
+ sudo_lbuf_destroy(&lbuf);
+
+ debug_return_int(0);
+}
+
+/* XXX - always returns 0, calls sudo_fatal() on failure */
+static int
+list_sessions(int argc, char **argv, const char *pattern, const char *user,
+ const char *tty)
+{
+ regex_t rebuf, *re = NULL;
+ const char *errstr;
+ debug_decl(list_sessions, SUDO_DEBUG_UTIL);
+
+ /* Parse search expression if present */
+ parse_expr(&search_expr, argv, false);
+
+ /* optional regex */
+ if (pattern) {
+ re = &rebuf;
+ if (!sudo_regex_compile(re, pattern, &errstr)) {
+ sudo_fatalx(U_("invalid regular expression \"%s\": %s"),
+ pattern, U_(errstr));
+ }
+ }
+
+ debug_return_int(find_sessions(session_dir, re, user, tty));
+}
+
+/*
+ * Check keyboard for ' ', '<', '>', return
+ * pause, slow, fast, next
+ */
+static void
+read_keyboard(int fd, int what, void *v)
+{
+ struct replay_closure *closure = v;
+ static bool paused = false;
+ struct timespec ts;
+ ssize_t nread;
+ char ch;
+ debug_decl(read_keyboard, SUDO_DEBUG_UTIL);
+
+ nread = read(fd, &ch, 1);
+ switch (nread) {
+ case -1:
+ if (errno != EINTR && errno != EAGAIN)
+ sudo_fatal(U_("unable to read %s"), "stdin");
+ break;
+ case 0:
+ /* Ignore EOF. */
+ break;
+ default:
+ if (paused) {
+ /* Any key will unpause, run the delay callback directly. */
+ paused = false;
+ delay_cb(-1, SUDO_EV_TIMEOUT, closure);
+ debug_return;
+ }
+ switch (ch) {
+ case ' ':
+ paused = true;
+ /* Disable the delay event until we unpause. */
+ sudo_ev_del(closure->evbase, closure->delay_ev);
+ break;
+ case '<':
+ speed_factor /= 2;
+ if (sudo_ev_pending(closure->delay_ev, SUDO_EV_TIMEOUT, &ts)) {
+ /* Double remaining timeout. */
+ ts.tv_sec *= 2;
+ ts.tv_nsec *= 2;
+ if (ts.tv_nsec >= 1000000000) {
+ ts.tv_sec++;
+ ts.tv_nsec -= 1000000000;
+ }
+ if (sudo_ev_add(NULL, closure->delay_ev, &ts, false) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "failed to double remaining delay timeout");
+ }
+ }
+ break;
+ case '>':
+ speed_factor *= 2;
+ if (sudo_ev_pending(closure->delay_ev, SUDO_EV_TIMEOUT, &ts)) {
+ /* Halve remaining timeout. */
+ if (ts.tv_sec & 1)
+ ts.tv_nsec += 500000000;
+ ts.tv_sec /= 2;
+ ts.tv_nsec /= 2;
+ if (sudo_ev_add(NULL, closure->delay_ev, &ts, false) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "failed to halve remaining delay timeout");
+ }
+ }
+ break;
+ case '\r':
+ case '\n':
+ /* Cancel existing delay, run callback directly. */
+ sudo_ev_del(closure->evbase, closure->delay_ev);
+ delay_cb(-1, SUDO_EV_TIMEOUT, closure);
+ break;
+ default:
+ /* Unknown key, nothing to do. */
+ break;
+ }
+ break;
+ }
+ debug_return;
+}
+
+static void
+display_usage(FILE *fp)
+{
+ fprintf(fp, _("usage: %s [-hnRS] [-d dir] [-m num] [-s num] ID\n"),
+ getprogname());
+ fprintf(fp, _("usage: %s [-h] [-d dir] -l [search expression]\n"),
+ getprogname());
+}
+
+sudo_noreturn static void
+usage(void)
+{
+ display_usage(stderr);
+ exit(EXIT_FAILURE);
+}
+
+sudo_noreturn static void
+help(void)
+{
+ (void) printf(_("%s - replay sudo session logs\n\n"), getprogname());
+ display_usage(stdout);
+ (void) puts(_("\nOptions:\n"
+ " -d, --directory=dir specify directory for session logs\n"
+ " -f, --filter=filter specify which I/O type(s) to display\n"
+ " -h, --help display help message and exit\n"
+ " -l, --list list available session IDs, with optional expression\n"
+ " -m, --max-wait=num max number of seconds to wait between events\n"
+ " -n, --non-interactive no prompts, session is sent to the standard output\n"
+ " -R, --no-resize do not attempt to re-size the terminal\n"
+ " -S, --suspend-wait wait while the command was suspended\n"
+ " -s, --speed=num speed up or slow down output\n"
+ " -V, --version display version information and exit"));
+ exit(EXIT_SUCCESS);
+}
+
+/*
+ * Cleanup hook for sudo_fatal()/sudo_fatalx()
+ */
+static void
+sudoreplay_cleanup(void)
+{
+ restore_terminal_size();
+ sudo_term_restore(ttyfd, false);
+}
diff --git a/plugins/sudoers/testsudoers.c b/plugins/sudoers/testsudoers.c
new file mode 100644
index 0000000..2ebd7b4
--- /dev/null
+++ b/plugins/sudoers/testsudoers.c
@@ -0,0 +1,782 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2007-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <unistd.h>
+#include <errno.h>
+
+#include <testsudoers_pwutil.h>
+#include <toke.h>
+#include <tsgetgrpw.h>
+#include <sudoers.h>
+#include <interfaces.h>
+#include <sudo_conf.h>
+#include <sudo_lbuf.h>
+#include <gram.h>
+
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+enum sudoers_formats {
+ format_ldif,
+ format_sudoers
+};
+
+/*
+ * Function Prototypes
+ */
+static void dump_sudoers(void);
+static void set_runaspw(struct sudoers_context *ctx, const char *);
+static void set_runasgr(struct sudoers_context *ctx, const char *);
+static int testsudoers_error(const char * restrict buf);
+static int testsudoers_output(const char * restrict buf);
+sudo_noreturn static void usage(void);
+static void cb_lookup(const struct sudoers_parse_tree *parse_tree, const struct userspec *us, int user_match, const struct privilege *priv, int host_match, const struct cmndspec *cs, int date_match, int runas_match, int cmnd_match, void *closure);
+static int testsudoers_query(struct sudoers_context *ctx, const struct sudo_nss *nss, struct passwd *pw);
+
+/*
+ * Globals
+ */
+static const char *orig_cmnd;
+static char *runas_group, *runas_user;
+
+#if defined(SUDO_DEVEL) && defined(__OpenBSD__)
+extern char *malloc_options;
+#endif
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+int
+main(int argc, char *argv[])
+{
+ struct sudoers_context test_ctx = SUDOERS_CONTEXT_INITIALIZER;
+ struct sudo_nss_list snl = TAILQ_HEAD_INITIALIZER(snl);
+ enum sudoers_formats input_format = format_sudoers;
+ struct sudo_nss testsudoers_nss;
+ char *p, *grfile, *pwfile, *shells;
+ const char *host = NULL;
+ const char *errstr;
+ int ch, dflag, exitcode = EXIT_FAILURE;
+ unsigned int validated;
+ int status = FOUND;
+ int pwflag = 0;
+ char cwdbuf[PATH_MAX];
+ time_t now;
+ id_t id;
+ debug_decl(main, SUDOERS_DEBUG_MAIN);
+
+#if defined(SUDO_DEVEL) && defined(__OpenBSD__)
+ malloc_options = "S";
+#endif
+#if YYDEBUG
+ sudoersdebug = 1;
+#endif
+
+ initprogname(argc > 0 ? argv[0] : "testsudoers");
+
+ if (!sudoers_initlocale(setlocale(LC_ALL, ""), def_sudoers_locale))
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ sudo_warn_set_locale_func(sudoers_warn_setlocale);
+ bindtextdomain("sudoers", LOCALEDIR); /* XXX - should have own domain */
+ textdomain("sudoers");
+ time(&now);
+
+ /* Initialize the debug subsystem. */
+ if (sudo_conf_read(NULL, SUDO_CONF_DEBUG) == -1)
+ goto done;
+ if (!sudoers_debug_register(getprogname(), sudo_conf_debug_files(getprogname())))
+ goto done;
+
+ dflag = 0;
+ grfile = pwfile = shells = NULL;
+ test_ctx.mode = MODE_RUN;
+ while ((ch = getopt(argc, argv, "+D:dg:G:h:i:L:lP:p:R:S:T:tu:U:v")) != -1) {
+ switch (ch) {
+ case 'D':
+ test_ctx.runas.cwd = optarg;
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 'G':
+ id = sudo_strtoid(optarg, &errstr);
+ if (errstr != NULL)
+ sudo_fatalx("group-ID %s: %s", optarg, errstr);
+ test_ctx.parser_conf.sudoers_gid = (gid_t)id;
+ break;
+ case 'g':
+ runas_group = optarg;
+ SET(test_ctx.settings.flags, RUNAS_GROUP_SPECIFIED);
+ break;
+ case 'h':
+ host = optarg;
+ break;
+ case 'i':
+ if (strcasecmp(optarg, "ldif") == 0) {
+ input_format = format_ldif;
+ } else if (strcasecmp(optarg, "sudoers") == 0) {
+ input_format = format_sudoers;
+ } else {
+ sudo_warnx(U_("unsupported input format %s"), optarg);
+ usage();
+ }
+ break;
+ case 'L':
+ test_ctx.runas.list_pw = sudo_getpwnam(optarg);
+ if (test_ctx.runas.list_pw == NULL) {
+ sudo_warnx(U_("unknown user %s"), optarg);
+ usage();
+ }
+ FALLTHROUGH;
+ case 'l':
+ if (test_ctx.mode != MODE_RUN) {
+ sudo_warnx(
+ "only one of the -l or -v flags may be specified");
+ usage();
+ }
+ test_ctx.mode = MODE_LIST;
+ pwflag = I_LISTPW;
+ orig_cmnd = "list";
+ break;
+ case 'p':
+ pwfile = optarg;
+ break;
+ case 'P':
+ grfile = optarg;
+ break;
+ case 'S':
+ shells = optarg;
+ break;
+ case 'T':
+ now = parse_gentime(optarg);
+ if (now == -1)
+ sudo_fatalx("invalid time: %s", optarg);
+ break;
+ case 'R':
+ test_ctx.runas.chroot = optarg;
+ break;
+ case 't':
+ trace_print = testsudoers_error;
+ break;
+ case 'U':
+ id = sudo_strtoid(optarg, &errstr);
+ if (errstr != NULL)
+ sudo_fatalx("user-ID %s: %s", optarg, errstr);
+ test_ctx.parser_conf.sudoers_uid = (uid_t)id;
+ break;
+ case 'u':
+ runas_user = optarg;
+ SET(test_ctx.settings.flags, RUNAS_USER_SPECIFIED);
+ break;
+ case 'v':
+ if (test_ctx.mode != MODE_RUN) {
+ sudo_warnx(
+ "only one of the -l or -v flags may be specified");
+ usage();
+ }
+ test_ctx.mode = MODE_VALIDATE;
+ pwflag = I_VERIFYPW;
+ orig_cmnd = "validate";
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (grfile != NULL || pwfile != NULL || shells != NULL) {
+ /* Set group/passwd/shells file and init the cache. */
+ if (grfile)
+ testsudoers_setgrfile(grfile);
+ if (pwfile)
+ testsudoers_setpwfile(pwfile);
+ if (shells)
+ testsudoers_setshellfile(shells);
+
+ /* Use custom passwd/group backend. */
+ sudo_pwutil_set_backend(testsudoers_make_pwitem,
+ testsudoers_make_gritem, testsudoers_make_gidlist_item,
+ testsudoers_make_grlist_item, testsudoers_valid_shell);
+ }
+
+ if (argc < 2) {
+ /* No command or user specified. */
+ if (dflag) {
+ orig_cmnd = "true";
+ } else if (pwflag == 0) {
+ usage();
+ }
+ test_ctx.user.name = strdup(argc ? *argv++ : "root");
+ if (test_ctx.user.name == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ argc = 0;
+ } else {
+ if (argc > 2 && test_ctx.mode == MODE_LIST)
+ test_ctx.mode = MODE_CHECK;
+ test_ctx.user.name = strdup(*argv++);
+ if (test_ctx.user.name == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ argc--;
+ if (orig_cmnd == NULL) {
+ orig_cmnd = *argv++;
+ argc--;
+ }
+ }
+ test_ctx.user.cmnd = strdup(orig_cmnd);
+ if (test_ctx.user.cmnd == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ test_ctx.user.cmnd_base = sudo_basename(test_ctx.user.cmnd);
+
+ if (getcwd(cwdbuf, sizeof(cwdbuf)) == NULL)
+ strlcpy(cwdbuf, "/", sizeof(cwdbuf));
+ test_ctx.user.cwd = strdup(cwdbuf);
+ if (test_ctx.user.cwd == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ if ((test_ctx.user.pw = sudo_getpwnam(test_ctx.user.name)) == NULL)
+ sudo_fatalx(U_("unknown user %s"), test_ctx.user.name);
+ test_ctx.user.uid = test_ctx.user.pw->pw_uid;
+ test_ctx.user.gid = test_ctx.user.pw->pw_gid;
+
+ if (!sudoers_sethost(&test_ctx, host, NULL))
+ goto done;
+
+ /* Fill in test_ctx.user.cmnd_args from argv. */
+ if (argc > 0) {
+ size_t n, size = 0;
+ char *cp;
+ int i;
+
+ for (i = 0; i < argc; i++)
+ size += strlen(argv[i]) + 1;
+
+ if ((test_ctx.user.cmnd_args = malloc(size)) == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ for (cp = test_ctx.user.cmnd_args, i = 0; i < argc; i++) {
+ n = strlcpy(cp, argv[i], size - (size_t)(cp - test_ctx.user.cmnd_args));
+ if (n >= size - (size_t)(cp - test_ctx.user.cmnd_args))
+ sudo_fatalx(U_("internal error, %s overflow"), getprogname());
+ cp += n;
+ *cp++ = ' ';
+ }
+ *--cp = '\0';
+ }
+
+ /* Initialize default values. */
+ if (!init_defaults())
+ sudo_fatalx("%s", U_("unable to initialize sudoers default values"));
+
+ /* Set group_plugin callback. */
+ sudo_defs_table[I_GROUP_PLUGIN].callback = cb_group_plugin;
+
+ /* Set runas callback. */
+ sudo_defs_table[I_RUNAS_DEFAULT].callback = cb_runas_default;
+
+ /* Set locale callback. */
+ sudo_defs_table[I_SUDOERS_LOCALE].callback = sudoers_locale_callback;
+
+ /* Load ip addr/mask for each interface. */
+ if (get_net_ifs(&p) > 0) {
+ if (!set_interfaces(p))
+ sudo_fatal("%s", U_("unable to parse network address list"));
+ free(p);
+ }
+
+ /* Initialize the parser and set sudoers filename to "sudoers". */
+ test_ctx.parser_conf.strict = true;
+ test_ctx.parser_conf.verbose = 2;
+ init_parser(&test_ctx, "sudoers");
+
+ /*
+ * Set runas passwd/group entries based on command line or sudoers.
+ * Note that if runas_group was specified without runas_user we
+ * run the command as the invoking user.
+ */
+ if (runas_group != NULL) {
+ set_runasgr(&test_ctx, runas_group);
+ set_runaspw(&test_ctx, runas_user ? runas_user : test_ctx.user.name);
+ } else
+ set_runaspw(&test_ctx, runas_user ? runas_user : def_runas_default);
+
+ /* Parse the policy file. */
+ sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, NULL);
+ switch (input_format) {
+ case format_ldif:
+ if (!sudoers_parse_ldif(&parsed_policy, stdin, NULL, true)) {
+ (void) puts("Parse error in LDIF");
+ parse_error = true;
+ }
+ break;
+ case format_sudoers:
+ if (sudoersparse() != 0)
+ parse_error = true;
+ break;
+ default:
+ sudo_fatalx("error: unhandled input %d", input_format);
+ }
+ if (!update_defaults(&test_ctx, &parsed_policy, NULL, SETDEF_ALL, false))
+ parse_error = true;
+
+ if (!parse_error)
+ (void) puts("Parses OK");
+
+ if (dflag) {
+ (void) putchar('\n');
+ dump_sudoers();
+ if (argc < 2) {
+ exitcode = parse_error ? 1 : 0;
+ goto done;
+ }
+ }
+
+ /* Fake up a minimal sudo nss list with the parsed policy. */
+ TAILQ_INSERT_TAIL(&snl, &testsudoers_nss, entries);
+ testsudoers_nss.query = testsudoers_query;
+ testsudoers_nss.parse_tree = &parsed_policy;
+
+ printf("\nEntries for user %s:\n", test_ctx.user.name);
+ validated = sudoers_lookup(&snl, &test_ctx, now, cb_lookup, NULL,
+ &status, pwflag);
+
+ /* Validate user-specified chroot or cwd (if any) and runas user shell. */
+ if (ISSET(validated, VALIDATE_SUCCESS)) {
+ if (!user_shell_valid(test_ctx.runas.pw)) {
+ printf(U_("\nInvalid shell for user %s: %s\n"),
+ test_ctx.runas.pw->pw_name, test_ctx.runas.pw->pw_shell);
+ CLR(validated, VALIDATE_SUCCESS);
+ SET(validated, VALIDATE_FAILURE);
+ }
+ if (check_user_runchroot(test_ctx.runas.chroot) != true) {
+ printf("\nUser %s is not allowed to change root directory to %s\n",
+ test_ctx.user.name, test_ctx.runas.chroot);
+ CLR(validated, VALIDATE_SUCCESS);
+ SET(validated, VALIDATE_FAILURE);
+ }
+ if (check_user_runcwd(test_ctx.runas.cwd) != true) {
+ printf("\nUser %s is not allowed to change directory to %s\n",
+ test_ctx.user.name, test_ctx.runas.cwd);
+ CLR(validated, VALIDATE_SUCCESS);
+ SET(validated, VALIDATE_FAILURE);
+ }
+ }
+ if (def_authenticate) {
+ puts(U_("\nPassword required"));
+ }
+
+ /*
+ * Exit codes:
+ * 0 - parsed OK and command matched.
+ * 1 - parse error
+ * 2 - command not matched
+ * 3 - command denied
+ */
+ if (parse_error || ISSET(validated, VALIDATE_ERROR)) {
+ puts(U_("\nParse error"));
+ exitcode = 1;
+ } else if (ISSET(validated, VALIDATE_SUCCESS)) {
+ puts(U_("\nCommand allowed"));
+ exitcode = 0;
+ } else if (ISSET(validated, VALIDATE_FAILURE)) {
+ puts(U_("\nCommand denied"));
+ exitcode = 3;
+ } else {
+ puts(U_("\nCommand unmatched"));
+ exitcode = 2;
+ }
+
+done:
+ sudoers_ctx_free(&test_ctx);
+ sudo_freepwcache();
+ sudo_freegrcache();
+ sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, exitcode);
+ return exitcode;
+}
+
+static void
+set_runaspw(struct sudoers_context *ctx, const char *user)
+{
+ struct passwd *pw = NULL;
+ debug_decl(set_runaspw, SUDOERS_DEBUG_UTIL);
+
+ if (*user == '#') {
+ const char *errstr;
+ uid_t uid = sudo_strtoid(user + 1, &errstr);
+ if (errstr == NULL) {
+ if ((pw = sudo_getpwuid(uid)) == NULL)
+ pw = sudo_fakepwnam(user, ctx->user.gid);
+ }
+ }
+ if (pw == NULL) {
+ if ((pw = sudo_getpwnam(user)) == NULL)
+ sudo_fatalx(U_("unknown user %s"), user);
+ }
+ if (ctx->runas.pw != NULL)
+ sudo_pw_delref(ctx->runas.pw);
+ ctx->runas.pw = pw;
+ debug_return;
+}
+
+static void
+set_runasgr(struct sudoers_context *ctx, const char *group)
+{
+ struct group *gr = NULL;
+ debug_decl(set_runasgr, SUDOERS_DEBUG_UTIL);
+
+ if (*group == '#') {
+ const char *errstr;
+ gid_t gid = sudo_strtoid(group + 1, &errstr);
+ if (errstr == NULL) {
+ if ((gr = sudo_getgrgid(gid)) == NULL)
+ gr = sudo_fakegrnam(group);
+ }
+ }
+ if (gr == NULL) {
+ if ((gr = sudo_getgrnam(group)) == NULL)
+ sudo_fatalx(U_("unknown group %s"), group);
+ }
+ if (ctx->runas.gr != NULL)
+ sudo_gr_delref(ctx->runas.gr);
+ ctx->runas.gr = gr;
+ debug_return;
+}
+
+bool
+cb_log_input(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ return true;
+}
+
+bool
+cb_log_output(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ return true;
+}
+
+/*
+ * Callback for runas_default sudoers setting.
+ */
+bool
+cb_runas_default(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ /* Only reset runaspw if user didn't specify one. */
+ if (!runas_user && !runas_group)
+ set_runaspw(ctx, sd_un->str);
+ return true;
+}
+
+bool
+sudo_nss_can_continue(const struct sudo_nss *nss, int match)
+{
+ return true;
+}
+
+void
+sudo_setspent(void)
+{
+ return;
+}
+
+void
+sudo_endspent(void)
+{
+ return;
+}
+
+FILE *
+open_sudoers(const char *file, char **outfile, bool doedit, bool *keepopen)
+{
+ struct stat sb;
+ FILE *fp = NULL;
+ const char *base;
+ int error, fd;
+ debug_decl(open_sudoers, SUDOERS_DEBUG_UTIL);
+
+ /* Report errors using the basename for consistent test output. */
+ base = sudo_basename(file);
+ fd = sudo_secure_open_file(file, sudoers_file_uid(), sudoers_file_gid(),
+ &sb, &error);
+ if (fd != -1) {
+ if ((fp = fdopen(fd, "r")) == NULL) {
+ sudo_warn("unable to open %s", base);
+ close(fd);
+ }
+ } else {
+ switch (error) {
+ case SUDO_PATH_MISSING:
+ sudo_warn("unable to open %s", base);
+ break;
+ case SUDO_PATH_BAD_TYPE:
+ sudo_warnx("%s is not a regular file", base);
+ break;
+ case SUDO_PATH_WRONG_OWNER:
+ sudo_warnx("%s should be owned by uid %u",
+ base, (unsigned int) sudoers_file_uid());
+ break;
+ case SUDO_PATH_WORLD_WRITABLE:
+ sudo_warnx("%s is world writable", base);
+ break;
+ case SUDO_PATH_GROUP_WRITABLE:
+ sudo_warnx("%s should be owned by gid %u",
+ base, (unsigned int) sudoers_file_gid());
+ break;
+ default:
+ sudo_warnx("%s: internal error, unexpected error %d",
+ __func__, error);
+ break;
+ }
+ }
+
+ debug_return_ptr(fp);
+}
+
+bool
+init_envtables(void)
+{
+ return(true);
+}
+
+bool
+set_perms(const struct sudoers_context *ctx, int perm)
+{
+ return true;
+}
+
+bool
+restore_perms(void)
+{
+ return true;
+}
+
+void
+init_eventlog_config(void)
+{
+ return;
+}
+
+bool
+pivot_root(const char *new_root, struct sudoers_pivot *state)
+{
+ return true;
+}
+
+bool
+unpivot_root(struct sudoers_pivot *state)
+{
+ return true;
+}
+
+int
+set_cmnd_path(struct sudoers_context *ctx, const char *runchroot)
+{
+ /* Reallocate test_ctx.user.cmnd to catch bugs in command_matches(). */
+ char *new_cmnd = strdup(orig_cmnd);
+ if (new_cmnd == NULL)
+ return NOT_FOUND_ERROR;
+ free(ctx->user.cmnd);
+ ctx->user.cmnd = new_cmnd;
+ return FOUND;
+}
+
+static void
+cb_lookup(const struct sudoers_parse_tree *parse_tree,
+ const struct userspec *us, int user_match, const struct privilege *priv,
+ int host_match, const struct cmndspec *cs, int date_match, int runas_match,
+ int cmnd_match, void *closure)
+{
+ static const struct privilege *prev_priv;
+ struct sudo_lbuf lbuf;
+
+ /* Only output info for the selected user. */
+ if (user_match != ALLOW) {
+ prev_priv = NULL;
+ return;
+ }
+
+ if (priv != prev_priv) {
+ /* No word wrap on output. */
+ sudo_lbuf_init(&lbuf, testsudoers_output, 0, NULL, 0);
+ sudo_lbuf_append(&lbuf, "\n");
+ sudoers_format_privilege(&lbuf, &parsed_policy, priv, false);
+ sudo_lbuf_print(&lbuf);
+ sudo_lbuf_destroy(&lbuf);
+
+ printf("\thost %s\n", host_match == ALLOW ? "allowed" :
+ host_match == DENY ? "denied" : "unmatched");
+ }
+
+ if (host_match == ALLOW) {
+ if (date_match != UNSPEC)
+ printf("\tdate %s\n", date_match == ALLOW ? "allowed" : "denied");
+ if (date_match != DENY) {
+ printf("\trunas %s\n", runas_match == ALLOW ? "allowed" :
+ runas_match == DENY ? "denied" : "unmatched");
+ if (runas_match == ALLOW) {
+ printf("\tcmnd %s\n", cmnd_match == ALLOW ? "allowed" :
+ cmnd_match == DENY ? "denied" : "unmatched");
+ }
+ }
+ }
+
+ prev_priv = priv;
+}
+
+static int
+testsudoers_query(struct sudoers_context *ctx, const struct sudo_nss *nss,
+ struct passwd *pw)
+{
+ /* Nothing to do. */
+ return 0;
+}
+
+static bool
+print_defaults(struct sudo_lbuf *lbuf)
+{
+ struct defaults *def, *next;
+ debug_decl(print_defaults, SUDOERS_DEBUG_UTIL);
+
+ TAILQ_FOREACH_SAFE(def, &parsed_policy.defaults, entries, next)
+ sudoers_format_default_line(lbuf, &parsed_policy, def, &next, false);
+
+ debug_return_bool(!sudo_lbuf_error(lbuf));
+}
+
+static int
+print_alias(struct sudoers_parse_tree *parse_tree, struct alias *a, void *v)
+{
+ struct sudo_lbuf *lbuf = v;
+ struct member *m;
+ debug_decl(print_alias, SUDOERS_DEBUG_UTIL);
+
+ sudo_lbuf_append(lbuf, "%s %s = ", alias_type_to_string(a->type),
+ a->name);
+ TAILQ_FOREACH(m, &a->members, entries) {
+ if (m != TAILQ_FIRST(&a->members))
+ sudo_lbuf_append(lbuf, ", ");
+ sudoers_format_member(lbuf, parse_tree, m, NULL, UNSPEC);
+ }
+ sudo_lbuf_append(lbuf, "\n");
+
+ debug_return_int(sudo_lbuf_error(lbuf) ? -1 : 0);
+}
+
+static bool
+print_aliases(struct sudo_lbuf *lbuf)
+{
+ debug_decl(print_aliases, SUDOERS_DEBUG_UTIL);
+
+ alias_apply(&parsed_policy, print_alias, lbuf);
+
+ debug_return_bool(!sudo_lbuf_error(lbuf));
+}
+
+static void
+dump_sudoers(void)
+{
+ struct sudo_lbuf lbuf;
+ debug_decl(dump_sudoers, SUDOERS_DEBUG_UTIL);
+
+ /* No word wrap on output. */
+ sudo_lbuf_init(&lbuf, testsudoers_output, 0, NULL, 0);
+
+ /* Print Defaults */
+ if (!print_defaults(&lbuf))
+ goto done;
+ if (lbuf.len > 0) {
+ sudo_lbuf_print(&lbuf);
+ sudo_lbuf_append(&lbuf, "\n");
+ }
+
+ /* Print Aliases */
+ if (!print_aliases(&lbuf))
+ goto done;
+ if (lbuf.len > 1) {
+ sudo_lbuf_print(&lbuf);
+ sudo_lbuf_append(&lbuf, "\n");
+ }
+
+ /* Print User_Specs */
+ if (!sudoers_format_userspecs(&lbuf, &parsed_policy, NULL, false, true))
+ goto done;
+ if (lbuf.len > 1) {
+ sudo_lbuf_print(&lbuf);
+ }
+
+done:
+ if (sudo_lbuf_error(&lbuf)) {
+ if (errno == ENOMEM)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ }
+ sudo_lbuf_destroy(&lbuf);
+
+ debug_return;
+}
+
+static int
+testsudoers_output(const char * restrict buf)
+{
+ return fputs(buf, stdout);
+}
+
+static int
+testsudoers_error(const char *restrict buf)
+{
+ return fputs(buf, stderr);
+}
+
+sudo_noreturn static void
+usage(void)
+{
+ (void) fprintf(stderr, "usage: %s [-dltv] [-G sudoers_gid] [-g group] [-h host] [-i input_format] [-L list_user] [-P grfile] [-p pwfile] [-S shells] [-U sudoers_uid] [-u user] <user> <command> [args]\n", getprogname());
+ exit(EXIT_FAILURE);
+}
diff --git a/plugins/sudoers/testsudoers_pwutil.c b/plugins/sudoers/testsudoers_pwutil.c
new file mode 100644
index 0000000..474278d
--- /dev/null
+++ b/plugins/sudoers/testsudoers_pwutil.c
@@ -0,0 +1,10 @@
+/*
+ * Build pwutil_impl.c with a function prefix of "testsudoers_" instead
+ * of "sudo_" and call our custom getpwnam/getpwuid/getgrnam/getgrgid.
+ */
+
+#define PWUTIL_PREFIX testsudoers
+
+#include <testsudoers_pwutil.h>
+#include <tsgetgrpw.h>
+#include "pwutil_impl.c"
diff --git a/plugins/sudoers/testsudoers_pwutil.h b/plugins/sudoers/testsudoers_pwutil.h
new file mode 100644
index 0000000..a0e140f
--- /dev/null
+++ b/plugins/sudoers/testsudoers_pwutil.h
@@ -0,0 +1,38 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef TESTSUDOERS_PWUTIL_H
+#define TESTSUDOERS_PWUTIL_H
+
+#include <config.h>
+
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <grp.h>
+#include <pwd.h>
+
+struct cache_item *testsudoers_make_gritem(gid_t gid, const char *group);
+struct cache_item *testsudoers_make_grlist_item(const struct passwd *pw, char * const *groups);
+struct cache_item *testsudoers_make_gidlist_item(const struct passwd *pw, int ngids, GETGROUPS_T *gids, char * const *gidstrs, unsigned int type);
+struct cache_item *testsudoers_make_pwitem(uid_t uid, const char *user);
+bool testsudoers_valid_shell(const char *shell);
+
+#endif /* TESTSUDOERS_PWUTIL_H */
diff --git a/plugins/sudoers/timeout.c b/plugins/sudoers/timeout.c
new file mode 100644
index 0000000..4ed168c
--- /dev/null
+++ b/plugins/sudoers/timeout.c
@@ -0,0 +1,109 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2017 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <sudo_compat.h>
+#include <sudoers_debug.h>
+#include <parse.h>
+
+/*
+ * Parse a command timeout in sudoers in the format 1d2h3m4s
+ * (days, hours, minutes, seconds) or a number of seconds with no suffix.
+ * Returns the number of seconds or -1 on error.
+ */
+int
+parse_timeout(const char *timestr)
+{
+ debug_decl(parse_timeout, SUDOERS_DEBUG_PARSER);
+ const char suffixes[] = "dhms";
+ const char *cp = timestr;
+ int timeout = 0;
+ int idx = 0;
+
+ do {
+ char *ep;
+ int ch;
+ long l;
+
+ /* Parse number, must be present and positive. */
+ errno = 0;
+ l = strtol(cp, &ep, 10);
+ if (ep == cp) {
+ /* missing timeout */
+ errno = EINVAL;
+ debug_return_int(-1);
+ }
+ if (errno == ERANGE || l < 0 || l > INT_MAX)
+ goto overflow;
+
+ /* Find a matching suffix or return an error. */
+ if (*ep != '\0') {
+ ch = tolower((unsigned char)*ep++);
+ while (suffixes[idx] != ch) {
+ if (suffixes[idx] == '\0') {
+ /* parse error */
+ errno = EINVAL;
+ debug_return_int(-1);
+ }
+ idx++;
+ }
+
+ /* Apply suffix. */
+ switch (ch) {
+ case 'd':
+ if (l > INT_MAX / (24 * 60 * 60))
+ goto overflow;
+ l *= 24 * 60 * 60;
+ break;
+ case 'h':
+ if (l > INT_MAX / (60 * 60))
+ goto overflow;
+ l *= 60 * 60;
+ break;
+ case 'm':
+ if (l > INT_MAX / 60)
+ goto overflow;
+ l *= 60;
+ break;
+ }
+ }
+ cp = ep;
+
+ if (l > INT_MAX - timeout)
+ goto overflow;
+ timeout += (int)l;
+ } while (*cp != '\0');
+
+ debug_return_int(timeout);
+overflow:
+ errno = ERANGE;
+ debug_return_int(-1);
+}
diff --git a/plugins/sudoers/timestamp.c b/plugins/sudoers/timestamp.c
new file mode 100644
index 0000000..9493e37
--- /dev/null
+++ b/plugins/sudoers/timestamp.c
@@ -0,0 +1,1276 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2014-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <signal.h>
+
+#include <sudoers.h>
+#include <timestamp.h>
+
+#define TIMESTAMP_OPEN_ERROR -1
+#define TIMESTAMP_PERM_ERROR -2
+
+/*
+ * Each user has a single time stamp file that contains multiple records.
+ * Records are locked to ensure that changes are serialized.
+ *
+ * The first record is of type TS_LOCKEXCL and is used to gain exclusive
+ * access to create new records. This is a short-term lock and sudo
+ * should not sleep while holding it (or the user will not be able to sudo).
+ * The TS_LOCKEXCL entry must be unlocked before locking the actual record.
+ */
+
+struct ts_cookie {
+ const struct sudoers_context *ctx;
+ char *fname;
+ int fd;
+ bool locked;
+ off_t pos;
+ struct timestamp_entry key;
+};
+
+static uid_t timestamp_uid = ROOT_UID;
+static gid_t timestamp_gid = ROOT_GID;
+
+uid_t
+timestamp_get_uid(void)
+{
+ return timestamp_uid;
+}
+
+/*
+ * Returns true if entry matches key, else false.
+ * We don't match on the sid or actual time stamp.
+ */
+static bool
+ts_match_record(struct timestamp_entry *key, struct timestamp_entry *entry,
+ unsigned int recno)
+{
+ debug_decl(ts_match_record, SUDOERS_DEBUG_AUTH);
+
+ if (entry->version != key->version) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s:%u record version mismatch (want %u, got %u)", __func__, recno,
+ key->version, entry->version);
+ debug_return_bool(false);
+ }
+ if (!ISSET(key->flags, TS_ANYUID) && entry->auth_uid != key->auth_uid) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s:%u record uid mismatch (want %u, got %u)", __func__, recno,
+ (unsigned int)key->auth_uid, (unsigned int)entry->auth_uid);
+ debug_return_bool(false);
+ }
+ if (entry->type != key->type) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s:%u record type mismatch (want %u, got %u)", __func__, recno,
+ key->type, entry->type);
+ debug_return_bool(false);
+ }
+ switch (entry->type) {
+ case TS_GLOBAL:
+ /* no ppid or tty to match */
+ break;
+ case TS_PPID:
+ /* verify parent pid */
+ if (entry->u.ppid != key->u.ppid) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s:%u record ppid mismatch (want %d, got %d)", __func__, recno,
+ (int)key->u.ppid, (int)entry->u.ppid);
+ debug_return_bool(false);
+ }
+ if (sudo_timespeccmp(&entry->start_time, &key->start_time, !=)) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s:%u ppid start time mismatch", __func__, recno);
+ debug_return_bool(false);
+ }
+ break;
+ case TS_TTY:
+ if (entry->u.ttydev != key->u.ttydev) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s:%u record tty mismatch (want 0x%x, got 0x%x)", __func__,
+ recno, (unsigned int)key->u.ttydev, (unsigned int)entry->u.ttydev);
+ debug_return_bool(false);
+ }
+ if (sudo_timespeccmp(&entry->start_time, &key->start_time, !=)) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s:%u session leader start time mismatch", __func__, recno);
+ debug_return_bool(false);
+ }
+ break;
+ default:
+ /* unknown record type, ignore it */
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "%s:%u unknown time stamp record type %d", __func__, recno,
+ entry->type);
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+/*
+ * Searches the time stamp file descriptor for a record that matches key.
+ * On success, fills in entry with the matching record and returns true.
+ * On failure, returns false.
+ *
+ * Note that records are searched starting at the current file offset,
+ * which may not be the beginning of the file.
+ */
+static bool
+ts_find_record(int fd, struct timestamp_entry *key, struct timestamp_entry *entry)
+{
+ struct timestamp_entry cur;
+ unsigned int recno = 0;
+ debug_decl(ts_find_record, SUDOERS_DEBUG_AUTH);
+
+ /*
+ * Find a matching record (does not match sid or time stamp value).
+ */
+ while (read(fd, &cur, sizeof(cur)) == sizeof(cur)) {
+ recno++;
+ if (cur.size != sizeof(cur)) {
+ /* wrong size, seek to start of next record */
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "wrong sized record, got %hu, expected %zu",
+ cur.size, sizeof(cur));
+ if (lseek(fd, (off_t)cur.size - (off_t)sizeof(cur), SEEK_CUR) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "unable to seek forward %zd",
+ cur.size - ssizeof(cur));
+ break;
+ }
+ if (cur.size == 0)
+ break; /* size must be non-zero */
+ continue;
+ }
+ if (ts_match_record(key, &cur, recno)) {
+ memcpy(entry, &cur, sizeof(struct timestamp_entry));
+ debug_return_bool(true);
+ }
+ }
+ debug_return_bool(false);
+}
+
+/*
+ * Create a directory and any missing parent directories with the
+ * specified mode.
+ * Returns an fd usable with the *at() functions on success.
+ * Returns -1 on failure, setting errno.
+ */
+static int
+ts_mkdirs(const char *path, uid_t owner, gid_t group, mode_t mode,
+ mode_t parent_mode, bool quiet)
+{
+ int parentfd, fd = -1;
+ const char *base;
+ mode_t omask;
+ debug_decl(ts_mkdirs, SUDOERS_DEBUG_AUTH);
+
+ /* Child directory we will create. */
+ base = sudo_basename(path);
+
+ /* umask must not be more restrictive than the file modes. */
+ omask = umask(ACCESSPERMS & ~(mode|parent_mode));
+ parentfd = sudo_open_parent_dir(path, owner, group, parent_mode, quiet);
+ if (parentfd != -1) {
+ /* Create final path component. */
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "mkdir %s, mode 0%o, uid %d, gid %d", path, (unsigned int)mode,
+ (int)owner, (int)group);
+ if (mkdirat(parentfd, base, mode) != 0 && errno != EEXIST) {
+ if (!quiet)
+ sudo_warn(U_("unable to mkdir %s"), path);
+ } else {
+ fd = openat(parentfd, base, O_RDONLY|O_NONBLOCK, 0);
+ if (fd == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to open %s", __func__, path);
+ } else if (fchown(fd, owner, group) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to chown %d:%d %s", __func__,
+ (int)owner, (int)group, path);
+ }
+ }
+ close(parentfd);
+ }
+ umask(omask);
+ debug_return_int(fd);
+}
+
+/*
+ * Check that path is owned by timestamp_uid and not writable by
+ * group or other. If path is missing and make_it is true, create
+ * the directory and its parent dirs.
+ *
+ * Returns an fd usable with the *at() functions on success.
+ * Returns -1 on failure, setting errno.
+ */
+static int
+ts_secure_opendir(const char *path, bool make_it, bool quiet)
+{
+ int error, fd;
+ struct stat sb;
+ debug_decl(ts_secure_opendir, SUDOERS_DEBUG_AUTH);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, "checking %s", path);
+ fd = sudo_secure_open_dir(path, timestamp_uid, timestamp_gid, &sb, &error);
+ if (fd == -1) {
+ switch (error) {
+ case SUDO_PATH_MISSING:
+ if (make_it) {
+ fd = ts_mkdirs(path, timestamp_uid, timestamp_gid, S_IRWXU,
+ S_IRWXU|S_IXGRP|S_IXOTH, quiet);
+ if (fd != -1)
+ break;
+ }
+ if (!quiet)
+ sudo_warn("%s", path);
+ break;
+ case SUDO_PATH_BAD_TYPE:
+ errno = ENOTDIR;
+ if (!quiet)
+ sudo_warn("%s", path);
+ break;
+ case SUDO_PATH_WRONG_OWNER:
+ if (!quiet) {
+ sudo_warnx(U_("%s is owned by uid %u, should be %u"),
+ path, (unsigned int)sb.st_uid, (unsigned int)timestamp_uid);
+ }
+ errno = EACCES;
+ break;
+ case SUDO_PATH_WORLD_WRITABLE:
+ if (!quiet)
+ sudo_warnx(U_("%s is world writable"), path);
+ errno = EACCES;
+ break;
+ case SUDO_PATH_GROUP_WRITABLE:
+ if (!quiet) {
+ sudo_warnx(U_("%s is owned by gid %u, should be %u"),
+ path, (unsigned int)sb.st_gid, (unsigned int)timestamp_gid);
+ }
+ errno = EACCES;
+ break;
+ default:
+ if (!quiet) {
+ sudo_warnx("%s: internal error, unexpected error %d",
+ __func__, error);
+ errno = EINVAL;
+ }
+ break;
+ }
+ }
+
+ debug_return_int(fd);
+}
+
+/*
+ * Open the specified timestamp or lecture file and set the
+ * close on exec flag.
+ * Returns open file descriptor on success.
+ * Returns TIMESTAMP_OPEN_ERROR or TIMESTAMP_PERM_ERROR on error.
+ */
+static int
+ts_openat(int dfd, const char *path, int flags)
+{
+ bool uid_changed = false;
+ int fd;
+ debug_decl(ts_openat, SUDOERS_DEBUG_AUTH);
+
+ if (timestamp_uid != 0)
+ uid_changed = set_perms(NULL, PERM_TIMESTAMP);
+ fd = openat(dfd, path, flags, S_IRUSR|S_IWUSR);
+ if (uid_changed && !restore_perms()) {
+ /* Unable to restore permissions, should not happen. */
+ if (fd != -1) {
+ int serrno = errno;
+ close(fd);
+ errno = serrno;
+ fd = TIMESTAMP_PERM_ERROR;
+ }
+ }
+ if (fd >= 0)
+ (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+ debug_return_int(fd);
+}
+
+static ssize_t
+ts_write(const struct sudoers_context *ctx, int fd, const char *fname,
+ struct timestamp_entry *entry, off_t offset)
+{
+ ssize_t nwritten;
+ off_t old_eof;
+ debug_decl(ts_write, SUDOERS_DEBUG_AUTH);
+
+ if (offset == -1) {
+ old_eof = lseek(fd, 0, SEEK_CUR);
+ if (old_eof == -1)
+ debug_return_ssize_t(-1);
+ nwritten = write(fd, entry, entry->size);
+ } else {
+ old_eof = offset;
+ nwritten = pwrite(fd, entry, entry->size, offset);
+ }
+ if ((size_t)nwritten != entry->size) {
+ if (nwritten == -1) {
+ log_warning(ctx, SLOG_SEND_MAIL,
+ N_("unable to write to %s"), fname);
+ } else {
+ log_warningx(ctx, SLOG_SEND_MAIL,
+ N_("unable to write to %s"), fname);
+ }
+
+ /* Truncate on partial write to be safe (assumes end of file). */
+ if (nwritten > 0) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "short write, truncating partial time stamp record");
+ if (ftruncate(fd, old_eof) != 0) {
+ sudo_warn(U_("unable to truncate time stamp file to %lld bytes"),
+ (long long)old_eof);
+ }
+ }
+ debug_return_ssize_t(-1);
+ }
+ debug_return_ssize_t(nwritten);
+}
+
+/*
+ * Full in struct timestamp_entry with the specified flags
+ * based on auth user pw. Does not set the time stamp.
+ */
+static void
+ts_init_key(const struct sudoers_context *ctx,
+ struct timestamp_entry *entry, struct passwd *pw,
+ unsigned short flags, enum def_tuple ticket_type)
+{
+ struct stat sb;
+ debug_decl(ts_init_key, SUDOERS_DEBUG_AUTH);
+
+ memset(entry, 0, sizeof(*entry));
+ entry->version = TS_VERSION;
+ entry->size = sizeof(*entry);
+ entry->flags = flags;
+ if (pw != NULL) {
+ entry->auth_uid = pw->pw_uid;
+ } else {
+ entry->flags |= TS_ANYUID;
+ }
+ entry->sid = ctx->user.sid;
+ switch (ticket_type) {
+ default:
+ /* Unknown time stamp ticket type, treat as tty (should not happen). */
+ sudo_warnx("unknown time stamp ticket type %d", ticket_type);
+ FALLTHROUGH;
+ case tty:
+ if (ctx->user.ttypath != NULL && stat(ctx->user.ttypath, &sb) == 0) {
+ /* tty-based time stamp */
+ entry->type = TS_TTY;
+ entry->u.ttydev = sb.st_rdev;
+ if (entry->sid != -1)
+ get_starttime(entry->sid, &entry->start_time);
+ break;
+ }
+ FALLTHROUGH;
+ case kernel:
+ case ppid:
+ /* ppid-based time stamp */
+ entry->type = TS_PPID;
+ entry->u.ppid = ctx->user.ppid;
+ get_starttime(entry->u.ppid, &entry->start_time);
+ break;
+ case global:
+ /* global time stamp */
+ entry->type = TS_GLOBAL;
+ break;
+ }
+
+ debug_return;
+}
+
+static void
+ts_init_key_nonglobal(const struct sudoers_context *ctx,
+ struct timestamp_entry *entry, struct passwd *pw, unsigned short flags)
+{
+ /*
+ * Even if the timestamp type is global or kernel we still want to do
+ * per-tty or per-ppid locking so sudo works predictably in a pipeline.
+ */
+ ts_init_key(ctx, entry, pw, flags,
+ def_timestamp_type == ppid ? ppid : tty);
+}
+
+/*
+ * Open the user's time stamp file.
+ * Returns a cookie or NULL on error, does not lock the file.
+ */
+void *
+timestamp_open(const struct sudoers_context *ctx)
+{
+ int tries, len, dfd = -1, fd = -1;
+ char uidstr[STRLEN_MAX_UNSIGNED(uid_t) + 1];
+ struct ts_cookie *cookie;
+ char *fname = NULL;
+ debug_decl(timestamp_open, SUDOERS_DEBUG_AUTH);
+
+ /* Zero timeout means don't use the time stamp file. */
+ if (!sudo_timespecisset(&def_timestamp_timeout)) {
+ errno = ENOENT;
+ goto bad;
+ }
+
+ /* Check the validity of timestamp dir and create if missing. */
+ dfd = ts_secure_opendir(def_timestampdir, true, false);
+ if (dfd == -1)
+ goto bad;
+
+ /* Open time stamp file. */
+ len = snprintf(uidstr, sizeof(uidstr), "%u", (unsigned int)ctx->user.uid);
+ if (len < 0 || len >= ssizeof(uidstr)) {
+ errno = EINVAL;
+ goto bad;
+ }
+ if (asprintf(&fname, "%s/%s", def_timestampdir, uidstr) == -1) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ for (tries = 1; ; tries++) {
+ struct stat sb;
+
+ fd = ts_openat(dfd, uidstr, O_RDWR|O_CREAT);
+ switch (fd) {
+ case TIMESTAMP_OPEN_ERROR:
+ log_warning(ctx, SLOG_SEND_MAIL, N_("unable to open %s"), fname);
+ goto bad;
+ case TIMESTAMP_PERM_ERROR:
+ /* Already logged set_perms/restore_perms error. */
+ goto bad;
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: opened time stamp file %s",
+ __func__, fname);
+
+ /* Remove time stamp file if its mtime predates boot time. */
+ if (tries == 1 && fstat(fd, &sb) == 0) {
+ struct timespec boottime, mtime, now;
+
+ if (sudo_gettime_real(&now) == 0 && get_boottime(&boottime)) {
+ /* Ignore a boot time that is in the future. */
+ if (sudo_timespeccmp(&now, &boottime, <)) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "ignoring boot time that is in the future");
+ } else {
+ mtim_get(&sb, mtime);
+ if (sudo_timespeccmp(&mtime, &boottime, <)) {
+ /* Time stamp file too old, remove it. */
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "removing time stamp file that predates boot time");
+ close(fd);
+ unlinkat(dfd, uidstr, 0);
+ continue;
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ /* Allocate and fill in cookie to store state. */
+ cookie = malloc(sizeof(*cookie));
+ if (cookie == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ cookie->ctx = ctx;
+ cookie->fd = fd;
+ cookie->fname = fname;
+ cookie->pos = -1;
+
+ close(dfd);
+ debug_return_ptr(cookie);
+bad:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: unable to open time stamp file %s", __func__, fname);
+ if (dfd != -1)
+ close(dfd);
+ if (fd >= 0)
+ close(fd);
+ free(fname);
+ debug_return_ptr(NULL);
+}
+
+static volatile sig_atomic_t got_signal;
+
+static void
+timestamp_handler(int s)
+{
+ got_signal = s;
+}
+
+/*
+ * Wrapper for sudo_lock_region() that is interruptible.
+ */
+static bool
+timestamp_lock_record(int fd, off_t pos, off_t len)
+{
+ struct sigaction sa, saveint, savequit;
+ sigset_t mask, omask;
+ bool ret;
+ debug_decl(timestamp_lock_record, SUDOERS_DEBUG_AUTH);
+
+ if (pos >= 0 && lseek(fd, pos, SEEK_SET) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "unable to seek to %lld", (long long)pos);
+ debug_return_bool(false);
+ }
+
+ /* Allow SIGINT and SIGQUIT to interrupt a lock. */
+ got_signal = 0;
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0; /* don't restart system calls */
+ sa.sa_handler = timestamp_handler;
+ (void) sigaction(SIGINT, &sa, &saveint);
+ (void) sigaction(SIGQUIT, &sa, &savequit);
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGQUIT);
+ (void) sigprocmask(SIG_UNBLOCK, &mask, &omask);
+
+ ret = sudo_lock_region(fd, SUDO_LOCK, len);
+ if (!ret) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "failed to lock fd %d [%lld, %lld]", fd,
+ (long long)pos, (long long)len);
+ }
+
+ /* Restore the old mask (SIGINT and SIGQUIT blocked) and handlers. */
+ (void) sigprocmask(SIG_SETMASK, &omask, NULL);
+ (void) sigaction(SIGINT, &saveint, NULL);
+ (void) sigaction(SIGQUIT, &savequit, NULL);
+
+ /* Re-deliver the signal that interrupted the lock, if any. */
+ if (!ret && got_signal)
+ kill(getpid(), got_signal);
+
+ debug_return_bool(ret);
+}
+
+static bool
+timestamp_unlock_record(int fd, off_t pos, off_t len)
+{
+ debug_decl(timestamp_unlock_record, SUDOERS_DEBUG_AUTH);
+
+ if (pos >= 0 && lseek(fd, pos, SEEK_SET) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "unable to seek to %lld", (long long)pos);
+ debug_return_bool(false);
+ }
+ debug_return_bool(sudo_lock_region(fd, SUDO_UNLOCK, len));
+}
+
+/*
+ * Seek to the record's position and read it, locking as needed.
+ */
+static ssize_t
+ts_read(struct ts_cookie *cookie, struct timestamp_entry *entry)
+{
+ ssize_t nread = -1;
+ bool should_unlock = false;
+ debug_decl(ts_read, SUDOERS_DEBUG_AUTH);
+
+ /* If the record is not already locked, lock it now. */
+ if (!cookie->locked) {
+ if (!timestamp_lock_record(cookie->fd, cookie->pos, sizeof(*entry)))
+ goto done;
+ should_unlock = true;
+ }
+
+ /* Seek to the record position and read it. */
+ nread = pread(cookie->fd, entry, sizeof(*entry), cookie->pos);
+ if (nread != sizeof(*entry)) {
+ /* short read, should not happen */
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "short read (%zd vs %zu), truncated time stamp file?",
+ nread, sizeof(*entry));
+ goto done;
+ }
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "read %zd byte record at %lld", nread, (long long)cookie->pos);
+
+done:
+ /* If the record was not locked initially, unlock it. */
+ if (should_unlock)
+ timestamp_unlock_record(cookie->fd, cookie->pos, sizeof(*entry));
+
+ debug_return_ssize_t(nread);
+}
+
+/*
+ * Write a TS_LOCKEXCL record at the beginning of the time stamp file.
+ */
+static bool
+timestamp_lock_write(struct ts_cookie *cookie)
+{
+ struct timestamp_entry entry;
+ bool ret = true;
+ debug_decl(timestamp_lock_write, SUDOERS_DEBUG_AUTH);
+
+ memset(&entry, 0, sizeof(entry));
+ entry.version = TS_VERSION;
+ entry.size = sizeof(entry);
+ entry.type = TS_LOCKEXCL;
+ if (ts_write(cookie->ctx, cookie->fd, cookie->fname, &entry, -1) == -1)
+ ret = false;
+ debug_return_bool(ret);
+}
+
+/*
+ * Lock a record in the time stamp file for exclusive access.
+ * If the record does not exist, it is created (as disabled).
+ */
+bool
+timestamp_lock(void *vcookie, struct passwd *pw)
+{
+ struct ts_cookie *cookie = vcookie;
+ struct timestamp_entry entry;
+ bool overwrite = false;
+ off_t lock_pos;
+ ssize_t nread;
+ debug_decl(timestamp_lock, SUDOERS_DEBUG_AUTH);
+
+ if (cookie == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "called with a NULL cookie!");
+ debug_return_bool(false);
+ }
+
+ /*
+ * Take a lock on the "write" record (the first record in the file).
+ * This will let us seek for the record or extend as needed
+ * without colliding with anyone else.
+ */
+ if (!timestamp_lock_record(cookie->fd, 0, sizeof(struct timestamp_entry)))
+ debug_return_bool(false);
+
+ /* Make sure the first record is of type TS_LOCKEXCL. */
+ memset(&entry, 0, sizeof(entry));
+ nread = read(cookie->fd, &entry, sizeof(entry));
+ if (nread < ssizeof(struct timestamp_entry_v1)) {
+ /* New or invalid time stamp file. */
+ overwrite = true;
+ } else if (entry.type != TS_LOCKEXCL) {
+ if (entry.size == sizeof(struct timestamp_entry_v1)) {
+ /* Old sudo record, convert it to TS_LOCKEXCL. */
+ entry.type = TS_LOCKEXCL;
+ memset((char *)&entry + offsetof(struct timestamp_entry, flags), 0,
+ (size_t)nread - offsetof(struct timestamp_entry, flags));
+ if (ts_write(cookie->ctx, cookie->fd, cookie->fname, &entry, 0) == -1)
+ debug_return_bool(false);
+ } else {
+ /* Corrupted time stamp file? Just overwrite it. */
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "corrupt initial record, type: %hu, size: %hu (expected %zu)",
+ entry.type, entry.size, sizeof(struct timestamp_entry_v1));
+ overwrite = true;
+ }
+ }
+ if (overwrite) {
+ /* Rewrite existing time stamp file or create new one. */
+ if (ftruncate(cookie->fd, 0) != 0) {
+ sudo_warn(U_("unable to truncate time stamp file to %lld bytes"),
+ 0LL);
+ debug_return_bool(false);
+ }
+ if (!timestamp_lock_write(cookie))
+ debug_return_bool(false);
+ } else if (entry.size != sizeof(entry)) {
+ /* Reset position if the lock record has an unexpected size. */
+ if (lseek(cookie->fd, entry.size, SEEK_SET) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "unable to seek to %hu", entry.size);
+ debug_return_bool(false);
+ }
+ }
+
+ /* Search for a tty/ppid-based record or append a new one. */
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "searching for %s time stamp record",
+ def_timestamp_type == ppid ? "ppid" : "tty");
+ ts_init_key_nonglobal(cookie->ctx, &cookie->key, pw, TS_DISABLED);
+ if (ts_find_record(cookie->fd, &cookie->key, &entry)) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "found existing %s time stamp record",
+ def_timestamp_type == ppid ? "ppid" : "tty");
+ lock_pos = lseek(cookie->fd, 0, SEEK_CUR) - (off_t)entry.size;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "appending new %s time stamp record",
+ def_timestamp_type == ppid ? "ppid" : "tty");
+ lock_pos = lseek(cookie->fd, 0, SEEK_CUR);
+ if (ts_write(cookie->ctx, cookie->fd, cookie->fname, &cookie->key, -1) == -1)
+ debug_return_bool(false);
+ }
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "%s time stamp position is %lld",
+ def_timestamp_type == ppid ? "ppid" : "tty", (long long)lock_pos);
+
+ if (def_timestamp_type == global) {
+ /*
+ * For global tickets we use a separate record lock that we
+ * cannot hold long-term since it is shared between all ttys.
+ */
+ cookie->locked = false;
+ cookie->key.type = TS_GLOBAL; /* find a global record */
+
+ if (lseek(cookie->fd, 0, SEEK_SET) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "unable to rewind fd");
+ debug_return_bool(false);
+ }
+ if (ts_find_record(cookie->fd, &cookie->key, &entry)) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "found existing global record");
+ cookie->pos = lseek(cookie->fd, 0, SEEK_CUR) - (off_t)entry.size;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "appending new global record");
+ cookie->pos = lseek(cookie->fd, 0, SEEK_CUR);
+ if (ts_write(cookie->ctx, cookie->fd, cookie->fname, &cookie->key, -1) == -1)
+ debug_return_bool(false);
+ }
+ } else {
+ /* For tty/ppid tickets the tty lock is the same as the record lock. */
+ cookie->pos = lock_pos;
+ cookie->locked = true;
+ }
+
+ /* Unlock the TS_LOCKEXCL record. */
+ timestamp_unlock_record(cookie->fd, 0, sizeof(struct timestamp_entry));
+
+ /* Lock the per-tty record (may sleep). */
+ if (!timestamp_lock_record(cookie->fd, lock_pos, sizeof(struct timestamp_entry)))
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+void
+timestamp_close(void *vcookie)
+{
+ struct ts_cookie *cookie = vcookie;
+ debug_decl(timestamp_close, SUDOERS_DEBUG_AUTH);
+
+ if (cookie != NULL) {
+ close(cookie->fd);
+ free(cookie->fname);
+ free(cookie);
+ }
+
+ debug_return;
+}
+
+#define TIMESPEC_VALID(ts) \
+ ((ts)->tv_sec >= 0 && (ts)->tv_nsec >= 0 && (ts)->tv_nsec < 1000000000L)
+
+/*
+ * Check the time stamp file and directory and return their status.
+ * Called with the file position before the locked record to read.
+ * Returns one of TS_CURRENT, TS_OLD, TS_MISSING, TS_ERROR, TS_FATAL.
+ * Fills in fdp with an open file descriptor positioned at the
+ * appropriate (and locked) record.
+ */
+int
+timestamp_status(void *vcookie, struct passwd *pw)
+{
+ struct ts_cookie *cookie = vcookie;
+ struct timestamp_entry entry;
+ struct timespec diff, now;
+ int status = TS_ERROR; /* assume the worst */
+ ssize_t nread;
+ debug_decl(timestamp_status, SUDOERS_DEBUG_AUTH);
+
+ /* Zero timeout means don't use time stamp files. */
+ if (!sudo_timespecisset(&def_timestamp_timeout)) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "timestamps disabled");
+ status = TS_OLD;
+ goto done;
+ }
+ if (cookie == NULL || cookie->pos < 0) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "NULL cookie or invalid position");
+ status = TS_OLD;
+ goto done;
+ }
+
+#ifdef TIOCCHKVERAUTH
+ if (def_timestamp_type == kernel) {
+ int fd = open(_PATH_TTY, O_RDWR);
+ if (fd != -1) {
+ if (ioctl(fd, TIOCCHKVERAUTH) == 0)
+ status = TS_CURRENT;
+ else
+ status = TS_OLD;
+ close(fd);
+ goto done;
+ }
+ }
+#endif
+
+ /* Read the record at the correct position. */
+ if ((nread = ts_read(cookie, &entry)) != sizeof(entry))
+ goto done;
+
+ /* Make sure what we read matched the expected record. */
+ if (entry.version != TS_VERSION || entry.size != nread) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "invalid time stamp file @ %lld", (long long)cookie->pos);
+ status = TS_OLD;
+ goto done;
+ }
+
+ /* Sanity check time stamps. */
+ if (!TIMESPEC_VALID(&entry.start_time) || !TIMESPEC_VALID(&entry.ts)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "invalid timespec in time stamp file @ %lld",
+ (long long)cookie->pos);
+ status = TS_OLD;
+ goto done;
+ }
+
+ if (ISSET(entry.flags, TS_DISABLED)) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "time stamp record disabled");
+ status = TS_OLD; /* disabled via sudo -k */
+ goto done;
+ }
+
+ if (entry.type != TS_GLOBAL && entry.sid != cookie->ctx->user.sid) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "time stamp record sid mismatch");
+ status = TS_OLD; /* belongs to different session */
+ goto done;
+ }
+
+ /* Negative timeouts only expire manually (sudo -k). */
+ sudo_timespecclear(&diff);
+ if (sudo_timespeccmp(&def_timestamp_timeout, &diff, <)) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "time stamp record does not expire");
+ status = TS_CURRENT;
+ goto done;
+ }
+
+ /* Compare stored time stamp with current time. */
+ if (sudo_gettime_mono(&now) == -1) {
+ log_warning(cookie->ctx, 0, N_("unable to read the clock"));
+ status = TS_ERROR;
+ goto done;
+ }
+ sudo_timespecsub(&now, &entry.ts, &diff);
+ if (sudo_timespeccmp(&diff, &def_timestamp_timeout, <)) {
+ status = TS_CURRENT;
+#if defined(CLOCK_MONOTONIC) || defined(__MACH__)
+ /* A monotonic clock should never run backwards. */
+ if (diff.tv_sec < 0) {
+ log_warningx(cookie->ctx, SLOG_SEND_MAIL,
+ N_("ignoring time stamp from the future"));
+ status = TS_OLD;
+ SET(entry.flags, TS_DISABLED);
+ (void)ts_write(cookie->ctx, cookie->fd, cookie->fname, &entry, cookie->pos);
+ }
+#else
+ /*
+ * Check for bogus (future) time in the stampfile.
+ * If diff / 2 > timeout, someone has been fooling with the clock.
+ */
+ sudo_timespecsub(&entry.ts, &now, &diff);
+ diff.tv_nsec /= 2;
+ if (diff.tv_sec & 1)
+ diff.tv_nsec += 500000000;
+ diff.tv_sec /= 2;
+ while (diff.tv_nsec >= 1000000000) {
+ diff.tv_sec++;
+ diff.tv_nsec -= 1000000000;
+ }
+
+ if (sudo_timespeccmp(&diff, &def_timestamp_timeout, >)) {
+ time_t tv_sec = (time_t)entry.ts.tv_sec;
+ log_warningx(cookie->ctx, SLOG_SEND_MAIL,
+ N_("time stamp too far in the future: %20.20s"),
+ 4 + ctime(&tv_sec));
+ status = TS_OLD;
+ SET(entry.flags, TS_DISABLED);
+ (void)ts_write(cookie->ctx, cookie->fd, cookie->fname, &entry, cookie->pos);
+ }
+#endif /* CLOCK_MONOTONIC */
+ } else {
+ status = TS_OLD;
+ }
+
+done:
+ debug_return_int(status);
+}
+
+/*
+ * Update the time on the time stamp file/dir or create it if necessary.
+ * Returns true on success, false on failure or -1 on setuid failure.
+ */
+bool
+timestamp_update(void *vcookie, struct passwd *pw)
+{
+ struct ts_cookie *cookie = vcookie;
+ bool ret = false;
+ debug_decl(timestamp_update, SUDOERS_DEBUG_AUTH);
+
+ /* Zero timeout means don't use time stamp files. */
+ if (!sudo_timespecisset(&def_timestamp_timeout)) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "timestamps disabled");
+ goto done;
+ }
+ if (cookie == NULL || cookie->pos < 0) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "NULL cookie or invalid position");
+ goto done;
+ }
+
+#ifdef TIOCSETVERAUTH
+ if (def_timestamp_type == kernel) {
+ int fd = open(_PATH_TTY, O_RDWR);
+ if (fd != -1) {
+ int secs = (int)def_timestamp_timeout.tv_sec;
+ if (secs > 0) {
+ if (secs > 3600)
+ secs = 3600; /* OpenBSD limitation */
+ if (ioctl(fd, TIOCSETVERAUTH, &secs) != 0)
+ sudo_warn("TIOCSETVERAUTH");
+ }
+ close(fd);
+ goto done;
+ }
+ }
+#endif
+
+ /* Update timestamp in key and enable it. */
+ CLR(cookie->key.flags, TS_DISABLED);
+ if (sudo_gettime_mono(&cookie->key.ts) == -1) {
+ log_warning(cookie->ctx, 0, N_("unable to read the clock"));
+ goto done;
+ }
+
+ /* Write out the locked record. */
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "writing %zu byte record at %lld", sizeof(cookie->key),
+ (long long)cookie->pos);
+ if (ts_write(cookie->ctx, cookie->fd, cookie->fname, &cookie->key, cookie->pos) != -1)
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+/*
+ * Remove the timestamp entry or file if unlink_it is set.
+ * Returns true on success, false on failure or -1 on setuid failure.
+ * A missing timestamp entry is not considered an error.
+ */
+int
+timestamp_remove(const struct sudoers_context *ctx, bool unlink_it)
+{
+ struct timestamp_entry key, entry;
+ int len, dfd = -1, fd = -1, ret = true;
+ char uidstr[STRLEN_MAX_UNSIGNED(uid_t) + 1];
+ char *fname = NULL;
+ debug_decl(timestamp_remove, SUDOERS_DEBUG_AUTH);
+
+#ifdef TIOCCLRVERAUTH
+ if (def_timestamp_type == kernel) {
+ fd = open(_PATH_TTY, O_RDWR);
+ if (fd != -1) {
+ ioctl(fd, TIOCCLRVERAUTH);
+ goto done;
+ }
+ }
+#endif
+
+ dfd = open(def_timestampdir, O_RDONLY|O_NONBLOCK);
+ if (dfd == -1) {
+ if (errno != ENOENT)
+ ret = -1;
+ goto done;
+ }
+
+ len = snprintf(uidstr, sizeof(uidstr), "%u", (unsigned int)ctx->user.uid);
+ if (len < 0 || len >= ssizeof(uidstr)) {
+ errno = EINVAL;
+ ret = -1;
+ goto done;
+ }
+ if (asprintf(&fname, "%s/%s", def_timestampdir, uidstr) == -1) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ ret = -1;
+ goto done;
+ }
+
+ /* For "sudo -K" simply unlink the time stamp file. */
+ if (unlink_it) {
+ ret = unlinkat(dfd, uidstr, 0) ? -1 : true;
+ goto done;
+ }
+
+ /* Open time stamp file and lock it for exclusive access. */
+ fd = ts_openat(dfd, uidstr, O_RDWR);
+ switch (fd) {
+ case TIMESTAMP_OPEN_ERROR:
+ if (errno != ENOENT)
+ ret = false;
+ goto done;
+ case TIMESTAMP_PERM_ERROR:
+ /* Already logged set_perms/restore_perms error. */
+ ret = -1;
+ goto done;
+ }
+ /* Lock first record to gain exclusive access. */
+ if (!timestamp_lock_record(fd, -1, sizeof(struct timestamp_entry))) {
+ sudo_warn(U_("unable to lock time stamp file %s"), fname);
+ ret = -1;
+ goto done;
+ }
+
+ /*
+ * Find matching entries and invalidate them.
+ */
+ ts_init_key(ctx, &key, NULL, 0, def_timestamp_type);
+ while (ts_find_record(fd, &key, &entry)) {
+ /* Back up and disable the entry. */
+ if (!ISSET(entry.flags, TS_DISABLED)) {
+ SET(entry.flags, TS_DISABLED);
+ if (lseek(fd, 0 - (off_t)sizeof(entry), SEEK_CUR) != -1) {
+ if (ts_write(ctx, fd, fname, &entry, -1) == -1)
+ ret = false;
+ }
+ }
+ }
+
+done:
+ if (dfd != -1)
+ close(dfd);
+ if (fd >= 0)
+ close(fd);
+ free(fname);
+ debug_return_int(ret);
+}
+
+bool
+cb_timestampowner(struct sudoers_context *ctx, const char *file,
+ int line, int column, const union sudo_defs_val *sd_un, int op)
+{
+ struct passwd *pw = NULL;
+ const char *user = sd_un->str;
+ debug_decl(cb_timestampowner, SUDOERS_DEBUG_AUTH);
+
+ if (*user == '#') {
+ const char *errstr;
+ uid_t uid = sudo_strtoid(user + 1, &errstr);
+ if (errstr == NULL)
+ pw = sudo_getpwuid(uid);
+ }
+ if (pw == NULL)
+ pw = sudo_getpwnam(user);
+ if (pw == NULL) {
+ log_warningx(ctx, SLOG_AUDIT|SLOG_PARSE_ERROR,
+ N_("%s:%d:%d timestampowner: unknown user %s"), file, line,
+ column, user);
+ debug_return_bool(false);
+ }
+ timestamp_uid = pw->pw_uid;
+ timestamp_gid = pw->pw_gid;
+ sudo_pw_delref(pw);
+
+ debug_return_bool(true);
+}
+
+/*
+ * Returns true if the user has already been lectured.
+ */
+bool
+already_lectured(const struct sudoers_context *ctx)
+{
+ char uidstr[STRLEN_MAX_UNSIGNED(uid_t) + 1];
+ bool ret = false;
+ struct stat sb;
+ int dfd, len;
+ debug_decl(already_lectured, SUDOERS_DEBUG_AUTH);
+
+ /* Check the existence and validity of timestamp dir. */
+ dfd = ts_secure_opendir(def_lecture_status_dir, false, true);
+ if (dfd == -1)
+ goto done;
+
+ len = snprintf(uidstr, sizeof(uidstr), "%u", (unsigned int)ctx->user.uid);
+ if (len < 0 || len >= ssizeof(uidstr))
+ goto done;
+
+ ret = fstatat(dfd, uidstr, &sb, AT_SYMLINK_NOFOLLOW) == 0;
+ if (!ret && errno == ENOENT && strchr(ctx->user.name, '/') == NULL) {
+ /* No uid-based lecture path, check for username-based path. */
+ ret = fstatat(dfd, ctx->user.name, &sb, AT_SYMLINK_NOFOLLOW) == 0;
+ if (ret) {
+ /* Migrate lecture file to uid-based path. */
+#ifdef HAVE_RENAMEAT
+ if (renameat(dfd, ctx->user.name, dfd, uidstr) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to rename %s/%s to %s/%s", __func__,
+ def_lecture_status_dir, ctx->user.name,
+ def_lecture_status_dir, uidstr);
+ }
+#else
+ char from[PATH_MAX], to[PATH_MAX];
+ len = snprintf(from, sizeof(from), "%s/%s", def_lecture_status_dir,
+ ctx->user.name);
+ if (len < 0 || len >= ssizeof(from))
+ goto done;
+ len = snprintf(to, sizeof(to), "%s/%s", def_lecture_status_dir,
+ uidstr);
+ if (len < 0 || len >= ssizeof(to))
+ goto done;
+ if (rename(from, to) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to rename %s to %s", __func__, from, to);
+ }
+#endif
+ }
+ }
+
+done:
+ if (dfd != -1)
+ close(dfd);
+ debug_return_bool(ret);
+}
+
+/*
+ * Create the lecture status file.
+ * Returns true on success, false on failure or -1 on setuid failure.
+ */
+int
+set_lectured(const struct sudoers_context *ctx)
+{
+ char uidstr[STRLEN_MAX_UNSIGNED(uid_t) + 1];
+ int dfd, fd, len, ret = false;
+ debug_decl(set_lectured, SUDOERS_DEBUG_AUTH);
+
+ /* Check the validity of timestamp dir and create if missing. */
+ dfd = ts_secure_opendir(def_lecture_status_dir, true, false);
+ if (dfd == -1)
+ goto done;
+
+ len = snprintf(uidstr, sizeof(uidstr), "%u", (unsigned int)ctx->user.uid);
+ if (len < 0 || len >= ssizeof(uidstr))
+ goto done;
+
+ /* Create lecture file. */
+ fd = ts_openat(dfd, uidstr, O_WRONLY|O_CREAT|O_EXCL);
+ switch (fd) {
+ case TIMESTAMP_OPEN_ERROR:
+ /* Failed to open, not a fatal error. */
+ break;
+ case TIMESTAMP_PERM_ERROR:
+ /* Already logged set_perms/restore_perms error. */
+ ret = -1;
+ break;
+ default:
+ /* Success. */
+ close(fd);
+ ret = true;
+ break;
+ }
+
+done:
+ if (dfd != -1)
+ close(dfd);
+ debug_return_int(ret);
+}
+
+#ifdef _PATH_SUDO_ADMIN_FLAG
+int
+create_admin_success_flag(const struct sudoers_context *ctx)
+{
+ struct passwd *pw = ctx->user.pw;
+ char *flagfile;
+ int ret = -1;
+ debug_decl(create_admin_success_flag, SUDOERS_DEBUG_AUTH);
+
+ /* Is the admin flag file even enabled? */
+ if (!def_admin_flag)
+ debug_return_int(true);
+
+ /* Check whether the user is in the sudo or admin group. */
+ if (!user_in_group(pw, "sudo") && !user_in_group(pw, "admin"))
+ debug_return_int(true);
+
+ /* Build path to flag file. */
+ if ((flagfile = strdup(def_admin_flag)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(-1);
+ }
+ if (!expand_tilde(&flagfile, pw->pw_name)) {
+ free(flagfile);
+ debug_return_int(false);
+ }
+
+ /* Create admin flag file if it doesn't already exist. */
+ if (set_perms(ctx, PERM_USER)) {
+ int fd = open(flagfile, O_CREAT|O_WRONLY|O_NONBLOCK|O_EXCL, 0644);
+ ret = fd != -1 || errno == EEXIST;
+ if (fd != -1)
+ close(fd);
+ if (!restore_perms())
+ ret = -1;
+ }
+ free(flagfile);
+ debug_return_int(ret);
+}
+#else /* !_PATH_SUDO_ADMIN_FLAG */
+int
+create_admin_success_flag(const struct sudoers_context *ctx)
+{
+ /* STUB */
+ return true;
+}
+#endif /* _PATH_SUDO_ADMIN_FLAG */
diff --git a/plugins/sudoers/timestamp.h b/plugins/sudoers/timestamp.h
new file mode 100644
index 0000000..924d84c
--- /dev/null
+++ b/plugins/sudoers/timestamp.h
@@ -0,0 +1,104 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1993-1996, 1998-2005, 2007-2015, 2017-2018, 2021-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#ifndef SUDOERS_TIMESTAMP_H
+#define SUDOERS_TIMESTAMP_H
+
+struct passwd;
+struct sudoers_context;
+struct getpass_closure {
+ int lectured;
+ void *cookie;
+ struct passwd *auth_pw;
+ const struct sudoers_context *ctx;
+};
+
+/* Status codes for timestamp_status() */
+#define TS_CURRENT 0
+#define TS_OLD 1
+#define TS_MISSING 2
+#define TS_ERROR 3
+#define TS_FATAL 4
+
+/*
+ * Time stamps are now stored in a single file which contains multiple
+ * records. Each record starts with a 16-bit version number and a 16-bit
+ * record size. Multiple record types can coexist in the same file.
+ */
+#define TS_VERSION 2
+
+/* Time stamp entry types */
+#define TS_GLOBAL 0x01U /* not restricted by tty or ppid */
+#define TS_TTY 0x02U /* restricted by tty */
+#define TS_PPID 0x03U /* restricted by ppid */
+#define TS_LOCKEXCL 0x04U /* special lock record */
+
+/* Time stamp flags */
+#define TS_DISABLED 0x01U /* entry disabled */
+#define TS_ANYUID 0x02U /* ignore uid, only valid in the key */
+
+struct timestamp_entry_v1 {
+ unsigned short version; /* version number */
+ unsigned short size; /* entry size */
+ unsigned short type; /* TS_GLOBAL, TS_TTY, TS_PPID */
+ unsigned short flags; /* TS_DISABLED, TS_ANYUID */
+ uid_t auth_uid; /* uid to authenticate as */
+ pid_t sid; /* session ID associated with tty/ppid */
+ struct timespec ts; /* time stamp (CLOCK_MONOTONIC) */
+ union {
+ dev_t ttydev; /* tty device number */
+ pid_t ppid; /* parent pid */
+ } u;
+};
+
+struct timestamp_entry {
+ unsigned short version; /* version number */
+ unsigned short size; /* entry size */
+ unsigned short type; /* TS_GLOBAL, TS_TTY, TS_PPID */
+ unsigned short flags; /* TS_DISABLED, TS_ANYUID */
+ uid_t auth_uid; /* uid to authenticate as */
+ pid_t sid; /* session ID associated with tty/ppid */
+ struct timespec start_time; /* session/ppid start time */
+ struct timespec ts; /* time stamp (CLOCK_MONOTONIC) */
+ union {
+ dev_t ttydev; /* tty device number */
+ pid_t ppid; /* parent pid */
+ } u;
+};
+
+union sudo_defs_val;
+void *timestamp_open(const struct sudoers_context *ctx);
+void timestamp_close(void *vcookie);
+bool timestamp_lock(void *vcookie, struct passwd *pw);
+bool timestamp_update(void *vcookie, struct passwd *pw);
+int timestamp_remove(const struct sudoers_context *ctx, bool unlinkit);
+int timestamp_status(void *vcookie, struct passwd *pw);
+uid_t timestamp_get_uid(void);
+bool cb_timestampowner(struct sudoers_context *ctx, const char *file, int line, int column, const union sudo_defs_val *sd_un, int op);
+int get_starttime(pid_t pid, struct timespec *starttime);
+bool already_lectured(const struct sudoers_context *ctx);
+int set_lectured(const struct sudoers_context *ctx);
+void display_lecture(struct sudo_conv_callback *callback);
+int create_admin_success_flag(const struct sudoers_context *ctx);
+
+#endif /* SUDOERS_TIMESTAMP_H */
diff --git a/plugins/sudoers/timestr.c b/plugins/sudoers/timestr.c
new file mode 100644
index 0000000..2f32b50
--- /dev/null
+++ b/plugins/sudoers/timestr.c
@@ -0,0 +1,50 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999, 2009-2011, 2013-2015, 2017
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <time.h>
+
+#include <sudoers.h>
+
+/*
+ * Return a static buffer with the current date + time.
+ */
+char *
+get_timestr(time_t tstamp, int log_year)
+{
+ static char buf[128];
+ struct tm tm;
+ size_t len;
+
+ if (localtime_r(&tstamp, &tm) != NULL) {
+ /* strftime() does not guarantee to NUL-terminate so we must check. */
+ buf[sizeof(buf) - 1] = '\0';
+ len = strftime(buf, sizeof(buf), log_year ? "%h %e %T %Y" : "%h %e %T",
+ &tm);
+ if (len != 0 && buf[sizeof(buf) - 1] == '\0')
+ return buf;
+ }
+ return NULL;
+}
diff --git a/plugins/sudoers/toke.c b/plugins/sudoers/toke.c
new file mode 100644
index 0000000..a60f632
--- /dev/null
+++ b/plugins/sudoers/toke.c
@@ -0,0 +1,6373 @@
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#line 3 "toke.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define yy_create_buffer sudoers_create_buffer
+#define yy_delete_buffer sudoers_delete_buffer
+#define yy_scan_buffer sudoers_scan_buffer
+#define yy_scan_string sudoers_scan_string
+#define yy_scan_bytes sudoers_scan_bytes
+#define yy_init_buffer sudoers_init_buffer
+#define yy_flush_buffer sudoers_flush_buffer
+#define yy_load_buffer_state sudoers_load_buffer_state
+#define yy_switch_to_buffer sudoers_switch_to_buffer
+#define yypush_buffer_state sudoerspush_buffer_state
+#define yypop_buffer_state sudoerspop_buffer_state
+#define yyensure_buffer_stack sudoersensure_buffer_stack
+#define yy_flex_debug sudoers_flex_debug
+#define yyin sudoersin
+#define yyleng sudoersleng
+#define yylex sudoerslex
+#define yylineno sudoerslineno
+#define yyout sudoersout
+#define yyrestart sudoersrestart
+#define yytext sudoerstext
+#define yywrap sudoerswrap
+#define yyalloc sudoersalloc
+#define yyrealloc sudoersrealloc
+#define yyfree sudoersfree
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 4
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+#ifdef yy_create_buffer
+#define sudoers_create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer sudoers_create_buffer
+#endif
+
+#ifdef yy_delete_buffer
+#define sudoers_delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer sudoers_delete_buffer
+#endif
+
+#ifdef yy_scan_buffer
+#define sudoers_scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer sudoers_scan_buffer
+#endif
+
+#ifdef yy_scan_string
+#define sudoers_scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string sudoers_scan_string
+#endif
+
+#ifdef yy_scan_bytes
+#define sudoers_scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes sudoers_scan_bytes
+#endif
+
+#ifdef yy_init_buffer
+#define sudoers_init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer sudoers_init_buffer
+#endif
+
+#ifdef yy_flush_buffer
+#define sudoers_flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer sudoers_flush_buffer
+#endif
+
+#ifdef yy_load_buffer_state
+#define sudoers_load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state sudoers_load_buffer_state
+#endif
+
+#ifdef yy_switch_to_buffer
+#define sudoers_switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer sudoers_switch_to_buffer
+#endif
+
+#ifdef yypush_buffer_state
+#define sudoerspush_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state sudoerspush_buffer_state
+#endif
+
+#ifdef yypop_buffer_state
+#define sudoerspop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state sudoerspop_buffer_state
+#endif
+
+#ifdef yyensure_buffer_stack
+#define sudoersensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack sudoersensure_buffer_stack
+#endif
+
+#ifdef yylex
+#define sudoerslex_ALREADY_DEFINED
+#else
+#define yylex sudoerslex
+#endif
+
+#ifdef yyrestart
+#define sudoersrestart_ALREADY_DEFINED
+#else
+#define yyrestart sudoersrestart
+#endif
+
+#ifdef yylex_init
+#define sudoerslex_init_ALREADY_DEFINED
+#else
+#define yylex_init sudoerslex_init
+#endif
+
+#ifdef yylex_init_extra
+#define sudoerslex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra sudoerslex_init_extra
+#endif
+
+#ifdef yylex_destroy
+#define sudoerslex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy sudoerslex_destroy
+#endif
+
+#ifdef yyget_debug
+#define sudoersget_debug_ALREADY_DEFINED
+#else
+#define yyget_debug sudoersget_debug
+#endif
+
+#ifdef yyset_debug
+#define sudoersset_debug_ALREADY_DEFINED
+#else
+#define yyset_debug sudoersset_debug
+#endif
+
+#ifdef yyget_extra
+#define sudoersget_extra_ALREADY_DEFINED
+#else
+#define yyget_extra sudoersget_extra
+#endif
+
+#ifdef yyset_extra
+#define sudoersset_extra_ALREADY_DEFINED
+#else
+#define yyset_extra sudoersset_extra
+#endif
+
+#ifdef yyget_in
+#define sudoersget_in_ALREADY_DEFINED
+#else
+#define yyget_in sudoersget_in
+#endif
+
+#ifdef yyset_in
+#define sudoersset_in_ALREADY_DEFINED
+#else
+#define yyset_in sudoersset_in
+#endif
+
+#ifdef yyget_out
+#define sudoersget_out_ALREADY_DEFINED
+#else
+#define yyget_out sudoersget_out
+#endif
+
+#ifdef yyset_out
+#define sudoersset_out_ALREADY_DEFINED
+#else
+#define yyset_out sudoersset_out
+#endif
+
+#ifdef yyget_leng
+#define sudoersget_leng_ALREADY_DEFINED
+#else
+#define yyget_leng sudoersget_leng
+#endif
+
+#ifdef yyget_text
+#define sudoersget_text_ALREADY_DEFINED
+#else
+#define yyget_text sudoersget_text
+#endif
+
+#ifdef yyget_lineno
+#define sudoersget_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno sudoersget_lineno
+#endif
+
+#ifdef yyset_lineno
+#define sudoersset_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno sudoersset_lineno
+#endif
+
+#ifdef yywrap
+#define sudoerswrap_ALREADY_DEFINED
+#else
+#define yywrap sudoerswrap
+#endif
+
+#ifdef yyalloc
+#define sudoersalloc_ALREADY_DEFINED
+#else
+#define yyalloc sudoersalloc
+#endif
+
+#ifdef yyrealloc
+#define sudoersrealloc_ALREADY_DEFINED
+#else
+#define yyrealloc sudoersrealloc
+#endif
+
+#ifdef yyfree
+#define sudoersfree_ALREADY_DEFINED
+#else
+#define yyfree sudoersfree
+#endif
+
+#ifdef yytext
+#define sudoerstext_ALREADY_DEFINED
+#else
+#define yytext sudoerstext
+#endif
+
+#ifdef yyleng
+#define sudoersleng_ALREADY_DEFINED
+#else
+#define yyleng sudoersleng
+#endif
+
+#ifdef yyin
+#define sudoersin_ALREADY_DEFINED
+#else
+#define yyin sudoersin
+#endif
+
+#ifdef yyout
+#define sudoersout_ALREADY_DEFINED
+#else
+#define yyout sudoersout
+#endif
+
+#ifdef yy_flex_debug
+#define sudoers_flex_debug_ALREADY_DEFINED
+#else
+#define yy_flex_debug sudoers_flex_debug
+#endif
+
+#ifdef yylineno
+#define sudoerslineno_ALREADY_DEFINED
+#else
+#define yylineno sudoerslineno
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#ifndef SIZE_MAX
+#define SIZE_MAX (~(size_t)0)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+/* begin standard C++ headers. */
+
+/* TODO: this is always defined, so inline it */
+#define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
+#else
+#define yynoreturn
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an
+ * integer in range [0..255] for use as an array index.
+ */
+#define YY_SC_TO_UI(c) ((YY_CHAR) (c))
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+extern int yyleng;
+
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ #define YY_LESS_LINENO(n)
+ #define YY_LINENO_REWIND_TO(ptr)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = (yy_hold_char); \
+ YY_RESTORE_YY_MORE_OFFSET \
+ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+#define unput(c) yyunput( c, (yytext_ptr) )
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ int yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+ : NULL)
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = NULL;
+static int yy_init = 0; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart ( FILE *input_file );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size );
+void yy_delete_buffer ( YY_BUFFER_STATE b );
+void yy_flush_buffer ( YY_BUFFER_STATE b );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer );
+void yypop_buffer_state ( void );
+
+static void yyensure_buffer_stack ( void );
+static void yy_load_buffer_state ( void );
+static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file );
+#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len );
+
+void *yyalloc ( yy_size_t );
+void *yyrealloc ( void *, yy_size_t );
+void yyfree ( void * );
+
+#define yy_new_buffer yy_create_buffer
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define sudoerswrap() (/*CONSTCOND*/1)
+#define YY_SKIP_YYWRAP
+typedef flex_uint8_t YY_CHAR;
+
+FILE *yyin = NULL, *yyout = NULL;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+int yylineno = 1;
+
+extern char *yytext;
+#ifdef yytext_ptr
+#undef yytext_ptr
+#endif
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state ( void );
+static yy_state_type yy_try_NUL_trans ( yy_state_type current_state );
+static int yy_get_next_buffer ( void );
+static void yynoreturn yy_fatal_error ( const char* msg );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ (yytext_ptr) = yy_bp; \
+ yyleng = (int) (yy_cp - yy_bp); \
+ (yy_hold_char) = *yy_cp; \
+ *yy_cp = '\0'; \
+ (yy_c_buf_p) = yy_cp;
+#define YY_NUM_RULES 89
+#define YY_END_OF_BUFFER 90
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static const flex_int16_t yy_accept[1242] =
+ { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 90, 75, 85, 84, 88, 83, 74, 87, 46, 78,
+ 79, 46, 80, 75, 75, 75, 75, 82, 81, 88,
+ 75, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 88, 75, 75, 75, 85,
+ 87, 64, 64, 64, 64, 64, 2, 88, 1, 75,
+ 64, 64, 64, 64, 75, 75, 17, 16, 16, 17,
+ 16, 16, 88, 21, 21, 19, 19, 21, 19, 20,
+ 88, 87, 88, 3, 9, 8, 9, 4, 9, 5,
+
+ 88, 13, 13, 13, 11, 12, 88, 23, 23, 22,
+ 22, 22, 23, 22, 22, 22, 22, 23, 23, 23,
+ 23, 23, 23, 23, 88, 22, 23, 23, 76, 76,
+ 77, 76, 71, 71, 71, 71, 71, 71, 71, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 88, 71, 71, 71, 75, 0, 85, 84, 83, 87,
+ 87, 0, 0, 75, 48, 0, 46, 0, 47, 0,
+ 72, 72, 0, 75, 75, 0, 75, 75, 75, 75,
+ 0, 51, 75, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+
+ 64, 64, 0, 86, 75, 75, 75, 0, 73, 0,
+ 75, 75, 85, 0, 0, 0, 0, 0, 87, 75,
+ 75, 75, 75, 75, 2, 1, 0, 1, 65, 65,
+ 0, 64, 75, 0, 65, 0, 75, 17, 17, 15,
+ 0, 14, 15, 21, 21, 21, 18, 18, 0, 3,
+ 9, 0, 6, 7, 9, 9, 13, 0, 13, 13,
+ 0, 10, 0, 48, 0, 0, 47, 23, 23, 0,
+ 23, 0, 0, 22, 22, 22, 22, 22, 22, 23,
+ 23, 64, 23, 23, 23, 23, 23, 23, 23, 23,
+ 73, 0, 23, 23, 76, 76, 76, 71, 0, 48,
+
+ 0, 47, 0, 71, 71, 0, 71, 71, 71, 71,
+ 71, 71, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 71, 71, 71, 71, 0, 71, 71,
+ 87, 87, 87, 0, 48, 75, 75, 75, 75, 75,
+ 0, 0, 51, 51, 75, 64, 53, 64, 64, 57,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 73, 75, 75, 75, 0, 0, 0, 0, 0, 87,
+ 75, 75, 75, 75, 75, 75, 0, 65, 0, 65,
+ 75, 75, 10, 0, 0, 0, 22, 22, 22, 23,
+
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 73, 23, 23, 0, 71, 71,
+ 71, 71, 71, 64, 53, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 71,
+ 71, 71, 71, 87, 87, 87, 75, 75, 75, 75,
+ 75, 75, 0, 52, 52, 52, 0, 0, 51, 51,
+ 51, 51, 51, 51, 51, 75, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 59, 64, 64, 60,
+ 75, 75, 75, 75, 0, 0, 0, 0, 0, 0,
+
+ 87, 75, 75, 75, 65, 75, 0, 0, 0, 0,
+ 0, 22, 22, 23, 23, 23, 64, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 71, 71, 71, 71, 71, 71, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 71, 71, 71, 71, 75, 75, 75, 0,
+ 0, 52, 52, 52, 0, 51, 51, 0, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 75,
+ 64, 64, 0, 33, 64, 64, 64, 64, 64, 0,
+ 42, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+
+ 64, 62, 64, 64, 75, 75, 75, 75, 75, 0,
+ 0, 0, 87, 75, 75, 75, 0, 0, 0, 22,
+ 22, 23, 23, 64, 64, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 71,
+ 71, 71, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 71, 71, 71, 71, 71,
+ 75, 75, 75, 75, 75, 0, 52, 0, 51, 51,
+ 51, 0, 0, 0, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 75, 64, 58,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+
+ 64, 64, 64, 64, 64, 64, 64, 66, 67, 68,
+ 69, 75, 0, 0, 87, 75, 75, 75, 0, 0,
+ 0, 0, 0, 23, 23, 64, 64, 23, 23, 23,
+ 64, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 71, 71, 71, 71, 71, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 66,
+ 67, 68, 69, 71, 49, 49, 49, 0, 0, 51,
+ 51, 51, 51, 51, 51, 51, 0, 0, 0, 0,
+ 0, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 75, 64, 0, 44, 64,
+
+ 64, 64, 64, 0, 32, 64, 64, 64, 64, 0,
+ 43, 64, 64, 64, 64, 0, 31, 0, 36, 54,
+ 75, 0, 0, 87, 75, 75, 75, 49, 49, 49,
+ 23, 64, 64, 23, 23, 64, 64, 23, 23, 23,
+ 49, 49, 49, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 71, 75, 49, 49, 49, 49, 0, 51,
+ 0, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 0, 0, 0, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 24, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+
+ 56, 64, 70, 0, 0, 87, 75, 28, 65, 0,
+ 49, 49, 49, 49, 23, 64, 64, 23, 23, 64,
+ 64, 23, 23, 23, 71, 49, 49, 49, 49, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 70, 50,
+ 50, 50, 50, 51, 0, 0, 0, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 0, 0, 0, 0, 0, 51, 51, 51, 51, 51,
+ 51, 51, 51, 75, 64, 64, 64, 64, 64, 0,
+ 45, 64, 64, 64, 0, 30, 0, 37, 55, 0,
+ 28, 26, 87, 29, 0, 75, 50, 50, 50, 50,
+
+ 23, 64, 64, 23, 64, 64, 50, 50, 50, 50,
+ 64, 64, 64, 64, 64, 64, 75, 75, 50, 50,
+ 50, 50, 0, 0, 0, 0, 0, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 75, 64, 0,
+ 34, 63, 0, 40, 64, 64, 64, 64, 29, 26,
+ 26, 26, 26, 87, 28, 0, 0, 0, 0, 0,
+ 28, 0, 0, 0, 50, 50, 50, 50, 64, 23,
+ 64, 64, 71, 71, 50, 50, 50, 50, 64, 64,
+ 64, 64, 75, 75, 75, 0, 0, 0, 51, 51,
+
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 25, 64, 0, 38,
+ 64, 64, 64, 26, 87, 0, 28, 0, 0, 0,
+ 23, 64, 64, 71, 71, 71, 64, 64, 64, 75,
+ 75, 75, 75, 75, 0, 0, 0, 0, 0, 51,
+ 51, 51, 51, 51, 51, 51, 51, 64, 0, 35,
+ 0, 41, 64, 27, 0, 0, 0, 0, 0, 64,
+ 71, 71, 71, 71, 71, 64, 75, 75, 75, 51,
+ 51, 51, 51, 51, 51, 64, 0, 39, 27, 27,
+ 27, 27, 0, 0, 0, 71, 71, 71, 75, 75,
+
+ 75, 75, 75, 51, 51, 51, 51, 51, 64, 27,
+ 0, 0, 0, 0, 0, 71, 71, 71, 71, 71,
+ 49, 49, 49, 64, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 61, 49, 49, 49, 49, 49, 49,
+ 0
+ } ;
+
+static const YY_CHAR yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 4, 4, 5, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 6, 7, 8, 9, 10, 11, 1, 1, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 1, 1,
+ 31, 32, 14, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 43, 44, 45, 46, 47, 48,
+ 43, 49, 50, 51, 52, 53, 54, 55, 56, 43,
+ 14, 57, 14, 58, 59, 1, 60, 61, 62, 63,
+
+ 64, 65, 66, 67, 68, 66, 66, 69, 70, 71,
+ 72, 66, 66, 73, 74, 75, 76, 66, 66, 66,
+ 66, 66, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static const YY_CHAR yy_meta[77] =
+ { 0,
+ 1, 2, 3, 4, 3, 2, 5, 6, 7, 8,
+ 1, 9, 9, 1, 10, 11, 1, 12, 13, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 15,
+ 16, 9, 1, 14, 14, 14, 14, 14, 14, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 18, 1, 19, 20,
+ 20, 20, 20, 20, 20, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21
+ } ;
+
+static const flex_int16_t yy_base[1366] =
+ { 0,
+ 0, 75, 126, 199, 83, 91, 99, 180, 272, 347,
+ 422, 478, 131, 147, 535, 0, 189, 219, 611, 0,
+ 6517, 6458, 76, 9534, 6501, 6471, 9534, 685, 101, 9534,
+ 9534, 6409, 9534, 199, 697, 238, 143, 6428, 9534, 9534,
+ 23, 762, 35, 103, 71, 132, 819, 6411, 76, 6422,
+ 6385, 112, 6373, 6374, 61, 883, 914, 262, 152, 266,
+ 969, 251, 166, 6339, 122, 6336, 197, 338, 123, 369,
+ 6350, 6335, 6334, 6344, 1036, 177, 0, 9534, 6364, 6335,
+ 9534, 0, 1092, 0, 214, 9534, 6338, 6331, 9534, 9534,
+ 236, 1148, 249, 0, 6280, 9534, 239, 9534, 240, 9534,
+
+ 306, 6245, 311, 262, 9534, 320, 172, 1177, 1236, 1281,
+ 363, 349, 1340, 1391, 6257, 86, 254, 1448, 6231, 6215,
+ 6227, 6200, 6212, 6207, 294, 422, 0, 173, 6187, 323,
+ 9534, 397, 6180, 348, 6168, 450, 1496, 444, 373, 1561,
+ 6135, 272, 388, 1618, 6117, 6113, 6125, 6109, 6121, 6114,
+ 1682, 1713, 490, 421, 6089, 737, 304, 9534, 6138, 168,
+ 9534, 6141, 500, 671, 6086, 848, 446, 926, 6085, 971,
+ 893, 6064, 1769, 984, 1784, 6077, 6088, 939, 994, 887,
+ 6075, 422, 243, 1849, 1906, 6050, 6034, 6002, 6013, 5988,
+ 5981, 5972, 5966, 5970, 5967, 1012, 5912, 5905, 5900, 5892,
+
+ 5894, 5885, 496, 9534, 376, 1022, 1970, 449, 5868, 1024,
+ 417, 433, 1033, 5854, 5859, 5849, 5841, 5839, 847, 684,
+ 683, 418, 434, 673, 935, 318, 1089, 454, 1064, 5850,
+ 2026, 1086, 2057, 694, 5842, 1078, 707, 0, 5891, 528,
+ 5894, 9534, 9534, 0, 498, 5862, 9534, 1135, 1134, 0,
+ 5801, 1184, 9534, 9534, 5792, 1140, 5772, 5820, 860, 682,
+ 1177, 750, 5822, 943, 1075, 1250, 5767, 2114, 0, 1377,
+ 2173, 1196, 1196, 2215, 5793, 1250, 1263, 1208, 2266, 2323,
+ 5759, 0, 5764, 5757, 5732, 5726, 5715, 1451, 5705, 5692,
+ 9534, 1021, 5670, 5664, 5669, 891, 721, 5667, 1536, 5655,
+
+ 1725, 5654, 1756, 1660, 5646, 2387, 1679, 2402, 5670, 1769,
+ 1804, 1374, 2467, 2524, 5629, 5634, 5619, 5555, 5550, 5541,
+ 1621, 5532, 5528, 737, 1746, 2588, 5516, 1194, 714, 841,
+ 431, 856, 944, 1926, 1936, 2628, 2668, 2708, 2746, 5552,
+ 5529, 2792, 910, 2839, 866, 2904, 2961, 5517, 5503, 0,
+ 5511, 5489, 5494, 5489, 5436, 5450, 5438, 5445, 5424, 5392,
+ 5404, 5380, 5375, 259, 5361, 5346, 5360, 5359, 5290, 5288,
+ 3025, 3081, 1184, 830, 24, 5240, 5230, 5232, 5238, 1042,
+ 896, 912, 5235, 718, 925, 821, 1979, 9534, 1043, 3137,
+ 3193, 983, 858, 1993, 2023, 2054, 3231, 5269, 3282, 3339,
+
+ 5250, 5241, 5246, 5181, 5195, 5183, 5165, 5154, 5145, 5157,
+ 5156, 5126, 5102, 5106, 1063, 1036, 5071, 2089, 3387, 3427,
+ 3467, 3507, 5079, 3553, 0, 5048, 5027, 5031, 5008, 4998,
+ 4976, 4970, 4935, 4932, 4930, 4929, 4911, 4897, 4883, 3617,
+ 3673, 1480, 1018, 9534, 1086, 1124, 2113, 160, 3713, 3753,
+ 1969, 708, 4889, 4884, 2128, 1239, 4880, 4869, 924, 951,
+ 3793, 2139, 1814, 3840, 2174, 1050, 3905, 1103, 889, 1183,
+ 1056, 1117, 1308, 1508, 1498, 1342, 1208, 1341, 1062, 1449,
+ 1114, 1464, 1109, 1343, 1394, 1215, 4857, 1234, 1137, 4849,
+ 1366, 1008, 1506, 1424, 4818, 4813, 4815, 4786, 4792, 4778,
+
+ 1671, 86, 1516, 1240, 1330, 1472, 2187, 4814, 2199, 2237,
+ 2079, 3962, 4013, 4088, 2006, 2060, 1522, 1716, 2367, 2368,
+ 1973, 2361, 2374, 2404, 2405, 2444, 2562, 1189, 4798, 4793,
+ 4742, 2549, 1536, 4136, 4176, 2603, 1450, 4775, 1850, 4757,
+ 4708, 1628, 2268, 4698, 4691, 4682, 4687, 4676, 4660, 4658,
+ 4654, 4647, 1636, 1682, 1629, 1483, 4216, 4256, 4296, 4625,
+ 4624, 2609, 4605, 4584, 4583, 4575, 969, 2641, 1824, 2651,
+ 2066, 4336, 0, 2592, 4384, 2678, 2688, 4431, 2720, 1494,
+ 1268, 1728, 2442, 9534, 1681, 1717, 1679, 1720, 1810, 2443,
+ 9534, 1724, 1698, 1468, 1966, 1729, 1647, 1686, 1954, 1967,
+
+ 1821, 4534, 1977, 2041, 1759, 1758, 1980, 1517, 1798, 4489,
+ 4446, 4424, 2103, 2053, 2054, 1966, 2732, 2768, 2814, 4460,
+ 4459, 2445, 2877, 4442, 4430, 2880, 2999, 2842, 3000, 3006,
+ 3012, 2879, 3009, 2882, 4448, 4445, 4440, 4441, 4399, 4479,
+ 4519, 4559, 4389, 4389, 4371, 4364, 4333, 4324, 4329, 4287,
+ 4300, 4265, 4274, 4274, 4257, 2037, 2029, 2089, 1916, 1997,
+ 2694, 2050, 4599, 4639, 3043, 4257, 4242, 4240, 4217, 4677,
+ 2097, 2869, 3051, 3081, 2159, 2253, 2336, 3094, 2360, 4725,
+ 0, 3106, 4773, 3134, 3150, 4820, 3158, 2112, 2082, 4202,
+ 2577, 1827, 2199, 2096, 2216, 3014, 2146, 2326, 2226, 3135,
+
+ 1944, 2188, 2334, 2252, 3186, 3187, 2351, 4173, 4135, 4111,
+ 4098, 2314, 4078, 4077, 2577, 2385, 2358, 2401, 3206, 4111,
+ 3218, 3253, 3190, 3284, 3387, 4073, 4055, 3388, 3389, 3390,
+ 2366, 3427, 3428, 3429, 3435, 3436, 0, 0, 0, 0,
+ 4003, 3480, 2125, 4868, 4908, 3456, 3467, 4008, 3997, 3979,
+ 3508, 3973, 3869, 2367, 3509, 3863, 3868, 3510, 3517, 3856,
+ 3854, 3838, 3835, 2498, 4947, 4986, 5025, 3861, 3843, 3821,
+ 3359, 5065, 3528, 3538, 5111, 3575, 3614, 3808, 3632, 3644,
+ 3587, 2537, 2572, 2974, 3030, 3670, 3066, 5159, 0, 3688,
+ 5207, 3699, 3723, 5254, 3731, 2419, 5319, 3759, 9534, 2275,
+
+ 2756, 1190, 2412, 3760, 9534, 2403, 667, 2319, 2592, 3761,
+ 9534, 2406, 2068, 3776, 3758, 3762, 9534, 3794, 9534, 3745,
+ 2524, 3725, 3675, 2759, 2624, 2585, 2776, 3814, 3861, 3983,
+ 5381, 3680, 3668, 2549, 2557, 3669, 3649, 2610, 2634, 3625,
+ 5439, 5478, 5517, 5574, 2752, 3598, 2955, 2691, 1603, 2797,
+ 2980, 2858, 2977, 4075, 2073, 5632, 5671, 4114, 3614, 3601,
+ 4152, 2769, 4162, 2989, 5711, 0, 4188, 5724, 4199, 3763,
+ 5770, 4228, 4240, 4268, 4280, 3021, 3028, 3116, 3269, 4306,
+ 3442, 5818, 0, 4318, 5866, 4356, 3781, 4406, 3029, 5931,
+ 2506, 3089, 2994, 3081, 4479, 2787, 3022, 3139, 4519, 4559,
+
+ 3563, 2812, 3529, 3525, 3492, 3844, 3147, 3864, 3508, 4366,
+ 3502, 4491, 4531, 3994, 5993, 3466, 3416, 3842, 1729, 3415,
+ 3395, 4560, 4561, 0, 4572, 2744, 6051, 6090, 4417, 6147,
+ 3371, 2428, 4600, 3113, 2962, 3347, 4601, 4602, 3314, 6206,
+ 6246, 6286, 6326, 3218, 4506, 4615, 4651, 3192, 3189, 3219,
+ 4661, 3254, 6366, 0, 4699, 6379, 4745, 4120, 6425, 4795,
+ 4755, 3114, 4842, 4880, 4455, 3147, 3270, 3602, 2759, 3178,
+ 6473, 0, 4550, 3364, 3535, 4918, 3347, 4921, 3411, 3906,
+ 9534, 3628, 3412, 3629, 4229, 9534, 4269, 9534, 2995, 2920,
+ 3765, 3421, 3215, 2813, 4936, 4976, 4932, 4974, 4998, 5037,
+
+ 4823, 4726, 2796, 3047, 2772, 2754, 6485, 6525, 6565, 6605,
+ 4911, 5026, 2728, 3392, 3211, 3435, 5085, 3134, 6645, 6685,
+ 5016, 3410, 5095, 2706, 5133, 5181, 5145, 2653, 2613, 3633,
+ 3684, 5227, 3699, 6725, 0, 5276, 6738, 5237, 4625, 6784,
+ 5451, 5462, 5489, 5500, 3880, 2590, 3321, 2863, 3750, 4728,
+ 9534, 2411, 4909, 9534, 5528, 3467, 3970, 3793, 9534, 1934,
+ 4164, 9534, 3367, 4342, 5547, 5660, 5668, 5699, 5540, 5319,
+ 5707, 5906, 5658, 2403, 5747, 5792, 5193, 2359, 4910, 2196,
+ 2137, 1988, 5839, 3588, 6832, 6872, 5852, 3751, 5820, 1948,
+ 1830, 3447, 6912, 6952, 6992, 6063, 6075, 6102, 1787, 1666,
+
+ 4075, 4089, 6112, 4177, 7032, 0, 6218, 7045, 6229, 4966,
+ 6258, 1645, 6269, 6297, 5288, 1558, 1440, 4170, 4916, 9534,
+ 5546, 5904, 4069, 9534, 4481, 6307, 6336, 6348, 6401, 6447,
+ 5910, 5066, 1398, 7093, 7133, 7173, 6514, 6525, 1288, 6512,
+ 3880, 7213, 7253, 6501, 6575, 1183, 6587, 6617, 6413, 1096,
+ 1034, 4640, 1014, 885, 6629, 0, 4323, 3525, 5068, 9534,
+ 5821, 9534, 6618, 4689, 6658, 833, 6670, 6697, 6459, 6147,
+ 6712, 4013, 7293, 7333, 6760, 6784, 7373, 7413, 7453, 6804,
+ 6842, 6852, 699, 0, 514, 3256, 6148, 9534, 3517, 4825,
+ 9534, 3623, 6884, 6896, 6924, 7493, 7533, 7573, 6934, 4073,
+
+ 7613, 7653, 6965, 9534, 6972, 7003, 5698, 9534, 2225, 9534,
+ 7013, 471, 7067, 7105, 6539, 7115, 4074, 7693, 7733, 7146,
+ 7153, 7191, 7229, 3226, 7239, 7267, 7277, 7306, 7316, 7354,
+ 404, 7392, 7164, 316, 9534, 7430, 5757, 179, 7440, 7346,
+ 9534, 7790, 7811, 7832, 7853, 7874, 7895, 7916, 7937, 7958,
+ 7979, 8000, 4595, 8021, 8042, 8063, 8084, 8105, 8126, 3974,
+ 8147, 8168, 8189, 8210, 8231, 8252, 8273, 8294, 8315, 8336,
+ 8357, 8378, 8399, 8420, 8441, 8462, 8483, 8504, 8525, 8546,
+ 4711, 4858, 8555, 8575, 8596, 8617, 8638, 8659, 8680, 8701,
+ 8722, 4195, 8743, 8764, 8785, 8806, 8818, 8839, 5061, 8860,
+
+ 8881, 8902, 8923, 8944, 8965, 8986, 9007, 9028, 9049, 5015,
+ 9058, 9078, 9099, 9120, 9141, 5557, 5566, 5900, 9150, 9158,
+ 9178, 9199, 5062, 6245, 6285, 6325, 9208, 9217, 6365, 6552,
+ 6559, 9225, 9234, 6773, 6777, 9242, 9251, 9271, 5308, 9283,
+ 9304, 6822, 9314, 9322, 9331, 9351, 6561, 9363, 9384, 6868,
+ 9394, 9402, 9411, 9431, 9452, 9473, 6871, 9483, 5651, 6951,
+ 9492, 6988, 5690, 9512, 3664
+ } ;
+
+static const flex_int16_t yy_def[1366] =
+ { 0,
+ 1241, 1, 1, 1, 1242, 1242, 1243, 1243, 1244, 1244,
+ 1245, 1245, 1246, 1246, 1241, 15, 1247, 1247, 1241, 19,
+ 1241, 1248, 1241, 1241, 1241, 1241, 1241, 1249, 1250, 1241,
+ 1241, 1251, 1241, 1252, 1248, 35, 35, 1253, 1241, 1241,
+ 1248, 1241, 42, 42, 42, 42, 42, 47, 47, 47,
+ 47, 47, 47, 47, 47, 1248, 1254, 35, 1248, 1241,
+ 1249, 42, 42, 47, 47, 47, 1241, 1241, 1241, 1255,
+ 42, 47, 47, 47, 1256, 1248, 1257, 1241, 1241, 1257,
+ 1241, 1257, 1241, 1258, 1258, 1241, 1241, 1258, 1241, 1241,
+ 1259, 1249, 1241, 1260, 1261, 1241, 1261, 1241, 1261, 1241,
+
+ 1262, 1263, 1263, 1263, 1241, 1241, 1264, 1265, 1266, 1241,
+ 110, 110, 110, 1241, 114, 114, 114, 114, 118, 118,
+ 118, 118, 118, 118, 1267, 110, 113, 113, 1268, 1268,
+ 1241, 1268, 1269, 1270, 1271, 1272, 1269, 137, 137, 1241,
+ 140, 140, 140, 140, 144, 144, 144, 144, 144, 144,
+ 1269, 1273, 137, 1269, 1274, 1274, 1241, 1241, 1241, 1275,
+ 1241, 1241, 1276, 1241, 1277, 1241, 1264, 1277, 1278, 1278,
+ 1279, 1280, 1274, 1274, 1274, 1281, 175, 175, 175, 175,
+ 1282, 1283, 1274, 1241, 184, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+
+ 185, 185, 1241, 1241, 1274, 1274, 1284, 1285, 1274, 1284,
+ 1274, 1274, 1241, 1241, 1241, 1241, 1241, 1241, 1275, 1274,
+ 175, 1274, 1274, 1274, 1241, 1241, 1241, 1241, 1286, 1287,
+ 1274, 185, 1288, 1289, 1274, 1288, 1274, 1290, 1290, 1241,
+ 1241, 1241, 1241, 1291, 1291, 1291, 1241, 1241, 1276, 1292,
+ 1293, 1293, 1241, 1241, 1293, 1293, 1294, 1241, 1294, 1294,
+ 1241, 1241, 1241, 1264, 1264, 1264, 1295, 1296, 1297, 1295,
+ 1298, 1241, 1241, 1297, 274, 274, 274, 274, 1241, 279,
+ 280, 1299, 280, 280, 280, 280, 280, 280, 280, 280,
+ 1241, 1285, 1297, 1297, 1300, 1300, 1300, 1301, 1301, 1302,
+
+ 1302, 1303, 1303, 1304, 1305, 1301, 1301, 1301, 308, 308,
+ 308, 308, 1241, 313, 314, 314, 314, 314, 314, 314,
+ 314, 314, 314, 1301, 1301, 1306, 1301, 1306, 1301, 1301,
+ 1307, 1307, 1308, 1241, 1241, 1309, 1309, 1309, 1309, 339,
+ 1310, 1241, 1311, 1241, 1309, 1241, 346, 347, 347, 347,
+ 347, 347, 347, 347, 347, 347, 347, 347, 347, 347,
+ 347, 347, 347, 347, 347, 347, 347, 347, 347, 347,
+ 1312, 1312, 1309, 1309, 1241, 1241, 1241, 1241, 1241, 1307,
+ 1309, 1309, 339, 1309, 1309, 1309, 1241, 1241, 1313, 1314,
+ 1314, 1309, 1241, 1241, 1241, 1241, 1297, 397, 1241, 399,
+
+ 400, 400, 400, 400, 400, 400, 400, 400, 400, 400,
+ 400, 400, 400, 400, 1315, 1297, 1297, 1241, 1301, 1301,
+ 1301, 308, 422, 313, 314, 314, 314, 314, 314, 314,
+ 314, 314, 314, 314, 314, 314, 314, 314, 314, 1306,
+ 1306, 1301, 1301, 1241, 1308, 1308, 1309, 1309, 1309, 1309,
+ 1309, 1309, 1316, 1317, 1317, 455, 1318, 1317, 1319, 1320,
+ 1241, 461, 461, 1241, 461, 1309, 1241, 467, 467, 467,
+ 467, 467, 467, 467, 467, 467, 467, 467, 467, 467,
+ 467, 467, 467, 467, 467, 467, 467, 467, 467, 467,
+ 1309, 1309, 1309, 1309, 1241, 1241, 1241, 1241, 1241, 1241,
+
+ 1321, 1309, 1309, 1309, 1322, 1309, 1241, 1241, 1241, 1241,
+ 1241, 1297, 1241, 513, 514, 514, 1323, 514, 514, 514,
+ 514, 514, 514, 514, 514, 514, 514, 1297, 1297, 1297,
+ 1297, 1301, 1301, 1301, 1301, 1301, 1301, 314, 314, 314,
+ 314, 314, 314, 314, 314, 314, 314, 314, 314, 314,
+ 314, 314, 1301, 1301, 1301, 1301, 1309, 1309, 1309, 1241,
+ 1324, 1324, 562, 1324, 1325, 1326, 1327, 1241, 1328, 464,
+ 1328, 1241, 572, 1328, 1241, 575, 575, 1241, 575, 1309,
+ 467, 467, 1241, 1241, 467, 467, 467, 467, 467, 1241,
+ 1241, 467, 467, 467, 467, 467, 467, 467, 467, 467,
+
+ 467, 467, 467, 467, 1309, 1309, 1309, 1309, 1309, 1241,
+ 1241, 1241, 1321, 1309, 1309, 1309, 1241, 1241, 1241, 512,
+ 513, 514, 514, 1323, 1323, 514, 514, 514, 514, 514,
+ 514, 514, 514, 514, 1297, 1297, 1297, 1297, 1297, 1301,
+ 1301, 1301, 314, 314, 314, 314, 314, 314, 314, 314,
+ 314, 314, 314, 314, 314, 1301, 1301, 1301, 1301, 1301,
+ 1309, 1309, 1309, 1309, 1309, 1329, 1329, 1330, 1331, 1241,
+ 1241, 1241, 1241, 1241, 1332, 1332, 1333, 578, 1333, 1241,
+ 680, 1333, 1241, 683, 683, 1241, 683, 1309, 467, 467,
+ 467, 467, 467, 467, 467, 467, 467, 467, 467, 467,
+
+ 467, 467, 467, 467, 467, 467, 467, 1309, 1309, 1309,
+ 1309, 1309, 1241, 1241, 1321, 1309, 1309, 1309, 1241, 1241,
+ 1241, 1241, 1241, 514, 514, 1323, 1323, 514, 514, 514,
+ 1323, 514, 514, 514, 514, 514, 1297, 1297, 1297, 1297,
+ 1297, 1301, 1301, 1301, 1301, 1301, 314, 314, 314, 314,
+ 314, 314, 314, 314, 314, 314, 314, 314, 314, 1301,
+ 1301, 1301, 1301, 1301, 1309, 1309, 1309, 1241, 1334, 1335,
+ 670, 1241, 772, 772, 1241, 772, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1336, 1336, 1337, 686, 1337, 1241, 788, 1337,
+ 1241, 791, 791, 1241, 791, 1309, 1241, 1241, 1241, 797,
+
+ 797, 797, 797, 1241, 1241, 797, 797, 797, 797, 1241,
+ 1241, 797, 797, 797, 797, 1241, 1241, 1241, 1241, 797,
+ 1309, 1241, 1241, 1338, 1309, 1309, 1309, 1241, 1241, 1241,
+ 1241, 1339, 1339, 831, 831, 1339, 1339, 831, 831, 1340,
+ 1341, 1341, 1341, 1241, 844, 844, 844, 844, 844, 844,
+ 844, 844, 1341, 1309, 1309, 1309, 1309, 1309, 1241, 1342,
+ 1241, 1343, 775, 1343, 1343, 865, 1343, 1241, 868, 868,
+ 1241, 868, 1241, 1241, 1241, 1241, 1344, 1344, 1345, 794,
+ 1345, 1241, 882, 1345, 1241, 885, 885, 885, 1309, 1241,
+ 890, 890, 890, 890, 890, 890, 890, 890, 890, 890,
+
+ 890, 890, 1309, 1241, 1241, 1346, 1309, 1309, 1309, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1347, 1347, 915, 915, 1347,
+ 1347, 915, 915, 1348, 1349, 1349, 1349, 1349, 1349, 1241,
+ 930, 930, 930, 930, 930, 930, 930, 930, 1349, 1309,
+ 1309, 1309, 1309, 1241, 1241, 1241, 1241, 1350, 1350, 1351,
+ 871, 1351, 1351, 953, 1351, 1241, 956, 956, 1241, 956,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1352, 1352, 1353, 1353,
+ 1353, 971, 1353, 1309, 890, 890, 890, 890, 890, 1241,
+ 1241, 890, 890, 890, 1241, 1241, 1241, 1241, 890, 1241,
+ 1241, 1354, 1346, 1309, 1355, 1356, 1241, 1241, 1241, 1241,
+
+ 915, 1347, 1347, 915, 1347, 1347, 1349, 1349, 1349, 1349,
+ 930, 930, 930, 930, 930, 930, 1309, 1309, 1309, 1309,
+ 1309, 1309, 1241, 1241, 1241, 1241, 1241, 1241, 1357, 1357,
+ 1358, 959, 1358, 1358, 1034, 1358, 1241, 1037, 1037, 1241,
+ 1037, 1241, 1241, 1241, 1241, 1359, 1359, 1309, 890, 1241,
+ 1241, 890, 1241, 1241, 890, 890, 890, 890, 1241, 1354,
+ 1354, 1241, 1354, 1346, 1355, 1355, 1355, 1355, 1241, 1355,
+ 1356, 1356, 1241, 1241, 1241, 1241, 1241, 1241, 1347, 915,
+ 1347, 1347, 1349, 1349, 1349, 1349, 1349, 1349, 930, 930,
+ 930, 930, 1309, 1309, 1309, 1241, 1241, 1241, 1241, 1360,
+
+ 1360, 1361, 1040, 1361, 1361, 1105, 1361, 1241, 1108, 1108,
+ 1108, 1241, 1241, 1241, 1241, 1241, 1309, 890, 1241, 1241,
+ 890, 890, 890, 1241, 1346, 1241, 1241, 1241, 1241, 1241,
+ 915, 1347, 1347, 1349, 1349, 1349, 930, 930, 930, 1309,
+ 1309, 1309, 1309, 1309, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1362, 1362, 1363, 1363, 1363, 1155, 1155, 890, 1241, 1241,
+ 1241, 1241, 890, 1364, 1241, 1241, 1241, 1241, 1241, 1347,
+ 1349, 1349, 1349, 1349, 1349, 930, 1309, 1309, 1309, 1241,
+ 1241, 1241, 1241, 1365, 1365, 890, 1241, 1241, 1364, 1364,
+ 1241, 1364, 1241, 1241, 1241, 1349, 1349, 1349, 1309, 1309,
+
+ 1309, 1309, 1309, 1241, 1241, 1241, 1241, 1241, 890, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1349, 1349, 1349, 1349, 1349,
+ 1309, 1309, 1309, 890, 1241, 1241, 1241, 1349, 1349, 1349,
+ 1309, 1309, 1309, 890, 1241, 1241, 1241, 1349, 1349, 1349,
+ 0, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241
+ } ;
+
+static const flex_int16_t yy_nxt[9611] =
+ { 0,
+ 22, 23, 24, 22, 25, 23, 26, 27, 28, 22,
+ 29, 30, 31, 22, 32, 33, 22, 22, 34, 35,
+ 36, 37, 35, 35, 35, 35, 35, 35, 35, 38,
+ 39, 40, 41, 42, 43, 44, 43, 45, 46, 47,
+ 47, 48, 47, 49, 50, 51, 47, 52, 53, 54,
+ 55, 47, 47, 47, 47, 47, 56, 57, 22, 58,
+ 58, 58, 58, 58, 58, 22, 22, 22, 22, 22,
+ 22, 22, 22, 59, 22, 22, 60, 157, 185, 156,
+ 60, 157, 185, 61, 23, 78, 495, 79, 23, 80,
+ 183, 81, 23, 78, 496, 79, 23, 80, 81, 81,
+
+ 85, 86, 201, 87, 85, 88, 81, 89, 90, 166,
+ 62, 63, 81, 82, 185, 64, 202, 193, 185, 614,
+ 81, 82, 194, 65, 228, 190, 66, 67, 228, 280,
+ 167, 67, 103, 24, 68, 25, 103, 104, 105, 83,
+ 283, 69, 156, 188, 70, 197, 185, 83, 103, 24,
+ 185, 25, 103, 104, 105, 91, 189, 168, 22, 71,
+ 198, 43, 179, 179, 179, 179, 179, 180, 199, 72,
+ 161, 73, 332, 74, 47, 185, 47, 447, 191, 185,
+ 166, 85, 86, 75, 87, 85, 88, 106, 89, 90,
+ 23, 24, 40, 25, 23, 130, 131, 223, 225, 76,
+
+ 67, 265, 225, 106, 67, 172, 172, 68, 156, 185,
+ 172, 172, 226, 185, 69, 245, 156, 70, 211, 245,
+ 23, 24, 40, 25, 23, 130, 131, 212, 266, 221,
+ 172, 22, 71, 156, 43, 299, 91, 248, 204, 293,
+ 241, 248, 72, 211, 73, 132, 74, 47, 294, 47,
+ 203, 204, 237, 241, 203, 173, 75, 178, 178, 178,
+ 178, 178, 178, 178, 178, 178, 178, 213, 260, 253,
+ 254, 213, 76, 23, 24, 132, 25, 23, 26, 155,
+ 92, 177, 177, 177, 177, 177, 177, 177, 177, 177,
+ 177, 188, 483, 484, 185, 252, 252, 280, 185, 156,
+
+ 284, 214, 215, 291, 189, 157, 216, 256, 204, 157,
+ 241, 256, 259, 345, 217, 314, 259, 218, 258, 228,
+ 220, 261, 262, 228, 263, 261, 316, 257, 93, 297,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 23, 24,
+ 292, 25, 23, 26, 227, 92, 166, 164, 164, 164,
+ 164, 164, 164, 164, 164, 164, 164, 258, 277, 277,
+ 277, 277, 277, 278, 185, 230, 230, 265, 204, 296,
+ 230, 230, 276, 276, 276, 276, 276, 276, 276, 276,
+ 276, 276, 311, 311, 311, 311, 311, 312, 203, 204,
+
+ 230, 241, 203, 93, 301, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+ 94, 94, 94, 23, 24, 231, 25, 23, 26, 96,
+ 92, 314, 156, 161, 317, 332, 97, 98, 99, 1241,
+ 342, 275, 275, 275, 275, 275, 275, 275, 275, 275,
+ 275, 344, 100, 296, 166, 228, 305, 305, 291, 228,
+ 156, 305, 305, 310, 310, 310, 310, 310, 310, 310,
+ 310, 310, 310, 156, 156, 1241, 373, 299, 101, 23,
+ 24, 305, 25, 23, 26, 96, 92, 329, 1211, 156,
+ 156, 384, 97, 98, 99, 374, 330, 203, 204, 245,
+
+ 241, 203, 266, 245, 385, 292, 306, 298, 100, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309, 309, 164,
+ 164, 164, 164, 164, 164, 164, 164, 164, 164, 203,
+ 204, 861, 241, 203, 101, 40, 23, 24, 40, 25,
+ 23, 26, 40, 40, 40, 107, 30, 31, 40, 108,
+ 33, 40, 40, 109, 110, 111, 112, 110, 110, 110,
+ 110, 110, 110, 110, 38, 113, 40, 40, 114, 115,
+ 115, 115, 116, 117, 118, 118, 119, 118, 120, 121,
+ 122, 118, 123, 118, 124, 118, 118, 118, 118, 118,
+ 118, 93, 125, 40, 126, 126, 126, 126, 126, 126,
+
+ 127, 127, 127, 127, 127, 127, 127, 127, 128, 127,
+ 127, 133, 23, 24, 133, 25, 23, 26, 40, 40,
+ 133, 134, 30, 31, 133, 135, 33, 133, 133, 136,
+ 137, 138, 139, 137, 137, 137, 137, 137, 137, 137,
+ 38, 39, 40, 133, 140, 141, 141, 141, 142, 143,
+ 144, 144, 145, 144, 146, 147, 148, 144, 149, 144,
+ 150, 144, 144, 144, 144, 144, 144, 151, 152, 133,
+ 153, 153, 153, 153, 153, 153, 133, 133, 133, 133,
+ 133, 133, 133, 133, 154, 133, 133, 161, 260, 162,
+ 164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
+
+ 155, 163, 896, 388, 164, 164, 164, 164, 164, 164,
+ 164, 164, 164, 164, 174, 185, 175, 175, 175, 175,
+ 175, 175, 175, 175, 175, 175, 176, 297, 1103, 156,
+ 177, 177, 177, 177, 177, 177, 386, 176, 258, 204,
+ 156, 155, 155, 155, 155, 155, 381, 383, 155, 155,
+ 389, 393, 155, 156, 382, 393, 177, 177, 177, 177,
+ 177, 177, 155, 156, 156, 155, 155, 155, 155, 392,
+ 299, 155, 155, 442, 156, 155, 155, 296, 155, 155,
+ 155, 184, 184, 184, 184, 184, 184, 184, 184, 184,
+ 184, 176, 381, 299, 155, 184, 184, 184, 184, 184,
+
+ 184, 185, 185, 185, 185, 186, 185, 185, 185, 187,
+ 185, 185, 185, 185, 185, 185, 185, 185, 156, 155,
+ 185, 177, 177, 177, 177, 177, 177, 155, 155, 155,
+ 155, 155, 155, 155, 155, 155, 155, 155, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 1241, 161,
+ 1165, 332, 185, 185, 185, 185, 185, 185, 444, 393,
+ 332, 259, 185, 393, 334, 259, 185, 335, 335, 335,
+ 335, 335, 335, 335, 335, 335, 335, 156, 155, 155,
+ 155, 155, 155, 155, 203, 204, 156, 205, 206, 155,
+ 155, 155, 295, 381, 155, 155, 295, 299, 155, 172,
+
+ 172, 494, 1241, 443, 172, 172, 340, 340, 340, 340,
+ 340, 340, 155, 155, 155, 208, 258, 380, 1241, 208,
+ 208, 208, 156, 209, 172, 208, 208, 466, 342, 208,
+ 165, 165, 165, 165, 165, 582, 225, 165, 165, 460,
+ 225, 165, 342, 208, 208, 208, 161, 296, 446, 173,
+ 226, 1241, 156, 460, 502, 165, 165, 165, 340, 340,
+ 340, 340, 340, 340, 340, 340, 340, 340, 156, 342,
+ 210, 161, 1241, 162, 381, 169, 169, 169, 169, 169,
+ 464, 156, 169, 169, 504, 163, 169, 342, 164, 164,
+ 164, 164, 164, 164, 164, 164, 164, 164, 460, 266,
+
+ 169, 169, 169, 336, 337, 338, 336, 336, 336, 336,
+ 336, 336, 336, 340, 340, 340, 340, 340, 340, 340,
+ 340, 340, 340, 203, 204, 208, 241, 203, 155, 208,
+ 415, 861, 207, 371, 213, 607, 219, 234, 213, 156,
+ 156, 234, 234, 234, 161, 235, 332, 234, 234, 357,
+ 358, 234, 505, 359, 506, 360, 361, 528, 529, 362,
+ 530, 363, 364, 1103, 156, 234, 234, 234, 214, 215,
+ 230, 230, 291, 216, 299, 230, 230, 292, 156, 234,
+ 372, 217, 155, 166, 218, 1241, 233, 390, 161, 556,
+ 446, 1241, 236, 240, 204, 230, 241, 240, 242, 389,
+
+ 243, 595, 585, 501, 1241, 242, 156, 243, 164, 164,
+ 164, 164, 164, 164, 164, 164, 164, 164, 580, 292,
+ 231, 243, 243, 357, 358, 1032, 444, 359, 446, 360,
+ 361, 266, 1241, 362, 391, 363, 203, 204, 1241, 241,
+ 203, 203, 204, 1241, 241, 203, 1241, 599, 243, 242,
+ 161, 581, 162, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 597, 249, 586, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 267, 261, 262,
+ 267, 263, 261, 604, 583, 251, 267, 267, 583, 251,
+ 267, 251, 251, 267, 267, 208, 252, 172, 298, 251,
+
+ 1145, 172, 326, 440, 172, 491, 492, 269, 493, 267,
+ 635, 172, 584, 636, 251, 394, 395, 396, 394, 394,
+ 394, 394, 394, 394, 394, 172, 172, 398, 398, 398,
+ 398, 398, 398, 270, 267, 267, 172, 1241, 185, 172,
+ 156, 893, 172, 172, 1241, 172, 172, 172, 172, 172,
+ 441, 593, 172, 172, 264, 264, 264, 264, 564, 564,
+ 564, 264, 264, 1241, 602, 264, 269, 172, 172, 398,
+ 398, 398, 398, 398, 398, 398, 398, 398, 398, 603,
+ 264, 264, 398, 398, 398, 398, 398, 398, 398, 398,
+ 398, 398, 272, 172, 172, 269, 156, 1241, 273, 269,
+
+ 274, 274, 274, 274, 274, 274, 274, 274, 274, 274,
+ 176, 269, 689, 381, 275, 275, 275, 275, 275, 275,
+ 269, 269, 269, 269, 269, 269, 269, 269, 269, 269,
+ 269, 269, 269, 269, 269, 269, 269, 1241, 1176, 388,
+ 275, 275, 275, 275, 275, 275, 269, 269, 269, 269,
+ 269, 269, 269, 269, 269, 269, 269, 1241, 587, 269,
+ 269, 269, 269, 269, 269, 269, 269, 269, 269, 1241,
+ 1241, 1241, 1241, 269, 269, 269, 269, 269, 269, 592,
+ 600, 267, 267, 267, 267, 267, 389, 605, 267, 267,
+ 606, 594, 267, 423, 423, 423, 423, 423, 423, 269,
+
+ 269, 269, 269, 269, 269, 269, 267, 267, 267, 269,
+ 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
+ 176, 269, 156, 1241, 279, 279, 279, 279, 279, 279,
+ 280, 280, 280, 280, 281, 280, 280, 280, 280, 280,
+ 280, 280, 280, 280, 280, 280, 280, 601, 1170, 282,
+ 275, 275, 275, 275, 275, 275, 269, 269, 269, 269,
+ 269, 269, 269, 269, 269, 269, 269, 280, 280, 280,
+ 280, 280, 280, 280, 280, 280, 280, 1241, 1241, 176,
+ 156, 280, 280, 280, 280, 280, 280, 609, 406, 407,
+ 596, 280, 408, 1241, 409, 410, 156, 1241, 411, 590,
+
+ 412, 553, 554, 590, 555, 698, 299, 269, 269, 269,
+ 269, 269, 269, 307, 598, 308, 308, 308, 308, 308,
+ 308, 308, 308, 308, 308, 176, 608, 591, 156, 309,
+ 309, 309, 309, 309, 309, 616, 299, 1241, 711, 299,
+ 298, 298, 298, 298, 298, 176, 660, 298, 298, 588,
+ 156, 298, 299, 532, 589, 309, 309, 309, 309, 309,
+ 309, 298, 156, 624, 298, 298, 298, 298, 625, 688,
+ 298, 298, 156, 156, 298, 298, 342, 298, 298, 298,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 176, 615, 299, 298, 313, 313, 313, 313, 313, 313,
+
+ 314, 314, 314, 314, 315, 314, 314, 314, 314, 314,
+ 314, 314, 314, 314, 314, 314, 314, 299, 298, 314,
+ 309, 309, 309, 309, 309, 309, 298, 298, 298, 298,
+ 298, 298, 298, 298, 298, 298, 298, 314, 314, 314,
+ 314, 314, 314, 314, 314, 314, 314, 1241, 935, 659,
+ 314, 314, 314, 314, 314, 314, 314, 656, 431, 432,
+ 657, 314, 433, 342, 434, 435, 305, 305, 436, 645,
+ 437, 305, 305, 161, 646, 332, 1241, 298, 298, 298,
+ 298, 298, 298, 203, 204, 299, 324, 325, 298, 298,
+ 298, 305, 299, 298, 298, 1032, 701, 298, 419, 420,
+
+ 421, 419, 419, 419, 419, 419, 419, 419, 1241, 658,
+ 1241, 298, 298, 298, 208, 1241, 306, 590, 208, 208,
+ 208, 590, 327, 702, 208, 208, 693, 1241, 208, 300,
+ 300, 300, 300, 300, 691, 299, 300, 300, 299, 613,
+ 300, 697, 208, 208, 208, 591, 1241, 203, 204, 1241,
+ 241, 203, 692, 1241, 300, 300, 300, 1241, 1241, 696,
+ 302, 302, 302, 302, 302, 694, 1004, 302, 302, 328,
+ 172, 302, 700, 155, 171, 155, 155, 171, 690, 280,
+ 155, 155, 708, 709, 171, 302, 302, 302, 423, 423,
+ 423, 423, 423, 423, 423, 423, 423, 423, 171, 171,
+
+ 155, 174, 299, 339, 339, 339, 339, 339, 339, 339,
+ 339, 339, 339, 176, 156, 156, 951, 339, 339, 339,
+ 339, 339, 339, 423, 423, 423, 423, 423, 423, 423,
+ 423, 423, 423, 573, 573, 573, 573, 573, 574, 1241,
+ 156, 568, 342, 339, 339, 339, 339, 339, 339, 155,
+ 1241, 583, 155, 570, 156, 583, 1241, 705, 155, 155,
+ 712, 695, 155, 155, 800, 155, 155, 155, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 176, 584,
+ 1138, 155, 346, 346, 346, 346, 346, 346, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+
+ 185, 185, 185, 185, 185, 156, 155, 185, 339, 339,
+ 339, 339, 339, 339, 155, 155, 155, 155, 155, 155,
+ 155, 155, 155, 155, 155, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 1241, 1062, 763, 1063, 185,
+ 185, 185, 185, 185, 185, 335, 335, 335, 335, 335,
+ 335, 335, 335, 335, 335, 335, 335, 335, 335, 335,
+ 335, 335, 335, 335, 335, 155, 155, 155, 155, 155,
+ 155, 208, 299, 1241, 1241, 208, 208, 208, 1241, 209,
+ 230, 208, 208, 1241, 230, 208, 447, 230, 448, 448,
+ 448, 448, 448, 448, 230, 1241, 1241, 812, 1137, 208,
+
+ 208, 208, 1241, 710, 703, 704, 1241, 1241, 230, 230,
+ 507, 1241, 508, 508, 508, 508, 508, 508, 508, 508,
+ 508, 508, 156, 628, 699, 156, 210, 230, 718, 706,
+ 155, 229, 155, 155, 229, 1241, 156, 155, 155, 1133,
+ 507, 229, 509, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 622, 299, 761, 229, 229, 155, 234, 764,
+ 760, 1241, 234, 234, 234, 1241, 235, 661, 234, 234,
+ 1241, 507, 234, 510, 510, 510, 510, 510, 511, 508,
+ 508, 508, 508, 1241, 342, 299, 234, 234, 234, 1241,
+ 305, 854, 707, 299, 305, 570, 507, 305, 508, 508,
+
+ 508, 508, 508, 508, 305, 161, 156, 332, 623, 156,
+ 156, 1241, 762, 236, 267, 342, 185, 267, 305, 305,
+ 900, 716, 717, 267, 267, 1241, 460, 267, 797, 156,
+ 267, 267, 557, 558, 559, 557, 557, 557, 557, 557,
+ 557, 557, 742, 802, 269, 299, 267, 562, 562, 563,
+ 564, 564, 564, 564, 564, 564, 564, 457, 572, 572,
+ 572, 572, 572, 572, 572, 572, 572, 572, 156, 156,
+ 270, 267, 267, 172, 796, 1241, 172, 342, 715, 172,
+ 172, 299, 172, 172, 172, 172, 172, 1132, 570, 172,
+ 172, 1241, 806, 571, 571, 571, 571, 571, 571, 571,
+
+ 571, 571, 571, 269, 172, 172, 617, 618, 619, 617,
+ 617, 617, 617, 617, 617, 617, 507, 1241, 508, 508,
+ 508, 508, 508, 508, 508, 508, 508, 508, 1241, 272,
+ 172, 172, 273, 813, 397, 397, 397, 397, 397, 397,
+ 397, 397, 397, 397, 176, 1241, 1131, 801, 397, 397,
+ 397, 397, 397, 397, 507, 1241, 508, 508, 508, 508,
+ 508, 508, 508, 508, 508, 508, 803, 808, 1224, 590,
+ 568, 342, 809, 590, 397, 397, 397, 397, 397, 397,
+ 269, 1241, 570, 185, 269, 399, 399, 399, 399, 399,
+ 399, 399, 399, 399, 399, 176, 269, 591, 815, 399,
+
+ 399, 399, 399, 399, 399, 280, 280, 280, 280, 280,
+ 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
+ 280, 280, 891, 185, 282, 397, 397, 397, 397, 397,
+ 397, 269, 269, 269, 269, 269, 269, 269, 269, 269,
+ 269, 269, 280, 280, 280, 280, 280, 280, 280, 280,
+ 280, 280, 1241, 568, 342, 1241, 280, 280, 280, 280,
+ 280, 280, 1241, 1241, 897, 678, 1241, 185, 1241, 1241,
+ 156, 814, 1241, 1241, 807, 1241, 1073, 1241, 342, 1241,
+ 1241, 821, 269, 269, 269, 269, 269, 269, 305, 678,
+ 1241, 298, 304, 298, 298, 304, 1241, 1241, 298, 298,
+
+ 629, 820, 304, 1241, 626, 1241, 1241, 836, 849, 1241,
+ 1241, 627, 837, 850, 156, 630, 304, 304, 298, 307,
+ 1073, 422, 422, 422, 422, 422, 422, 422, 422, 422,
+ 422, 176, 826, 1241, 1241, 422, 422, 422, 422, 422,
+ 422, 156, 899, 583, 590, 1241, 1241, 583, 590, 1241,
+ 1241, 185, 825, 631, 185, 632, 895, 156, 299, 894,
+ 185, 422, 422, 422, 422, 422, 422, 298, 827, 185,
+ 298, 584, 591, 1241, 1241, 156, 298, 298, 314, 1013,
+ 298, 298, 889, 298, 298, 298, 424, 424, 424, 424,
+ 424, 424, 424, 424, 424, 424, 176, 633, 724, 298,
+
+ 424, 424, 424, 424, 424, 424, 314, 314, 314, 314,
+ 314, 314, 314, 314, 314, 314, 314, 314, 314, 314,
+ 314, 314, 314, 299, 298, 314, 422, 422, 422, 422,
+ 422, 422, 298, 298, 298, 298, 298, 298, 298, 298,
+ 298, 298, 298, 314, 314, 314, 314, 314, 314, 314,
+ 314, 314, 314, 1241, 299, 342, 976, 314, 314, 314,
+ 314, 314, 314, 1241, 185, 853, 570, 1241, 640, 641,
+ 642, 640, 640, 640, 640, 640, 640, 640, 798, 161,
+ 156, 332, 798, 298, 298, 298, 298, 298, 298, 208,
+ 342, 1241, 919, 208, 208, 208, 280, 327, 903, 208,
+
+ 208, 678, 918, 208, 280, 299, 799, 634, 342, 568,
+ 342, 676, 676, 676, 676, 676, 676, 208, 208, 208,
+ 532, 570, 533, 533, 533, 533, 533, 533, 667, 667,
+ 667, 667, 667, 667, 667, 667, 667, 667, 457, 824,
+ 185, 156, 951, 898, 328, 447, 922, 448, 448, 448,
+ 448, 448, 448, 448, 448, 448, 448, 280, 908, 299,
+ 672, 673, 674, 672, 672, 672, 672, 672, 672, 672,
+ 579, 579, 579, 579, 579, 579, 579, 579, 579, 579,
+ 156, 280, 863, 907, 156, 447, 923, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 680, 680, 680,
+
+ 680, 680, 680, 680, 680, 680, 680, 681, 681, 681,
+ 681, 681, 682, 765, 766, 767, 765, 765, 765, 765,
+ 765, 765, 765, 1023, 156, 447, 934, 450, 450, 450,
+ 450, 450, 451, 448, 448, 448, 448, 1241, 314, 679,
+ 679, 679, 679, 679, 679, 679, 679, 679, 679, 719,
+ 156, 720, 720, 720, 720, 720, 720, 720, 720, 720,
+ 720, 161, 925, 332, 156, 452, 452, 452, 452, 452,
+ 452, 452, 452, 452, 452, 176, 568, 342, 1089, 452,
+ 452, 452, 452, 452, 452, 719, 861, 721, 721, 721,
+ 721, 721, 721, 721, 721, 721, 721, 892, 863, 314,
+
+ 299, 1082, 156, 931, 185, 452, 452, 452, 452, 452,
+ 452, 454, 455, 456, 456, 456, 456, 456, 456, 456,
+ 456, 457, 906, 1081, 982, 458, 458, 458, 458, 458,
+ 458, 719, 156, 722, 722, 722, 722, 722, 723, 720,
+ 720, 720, 720, 1241, 314, 185, 1079, 1241, 936, 989,
+ 909, 458, 458, 458, 458, 458, 458, 342, 461, 462,
+ 463, 461, 461, 461, 461, 461, 461, 461, 464, 156,
+ 185, 1241, 465, 465, 465, 465, 465, 465, 1241, 730,
+ 1241, 1241, 1241, 1241, 1241, 1241, 777, 1241, 778, 778,
+ 778, 778, 778, 778, 778, 778, 778, 778, 465, 465,
+
+ 465, 465, 465, 465, 155, 314, 1241, 155, 1241, 1241,
+ 938, 1241, 725, 155, 155, 728, 734, 155, 155, 156,
+ 155, 155, 155, 467, 467, 467, 467, 467, 467, 467,
+ 467, 467, 467, 176, 736, 1117, 155, 467, 467, 467,
+ 467, 467, 467, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 156, 155, 185, 452, 452, 452, 452, 452, 452, 155,
+ 155, 155, 155, 155, 155, 155, 155, 155, 155, 155,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 1241, 568, 342, 1059, 185, 185, 185, 185, 185, 185,
+
+ 1241, 1241, 314, 678, 1241, 1241, 1241, 1241, 933, 1015,
+ 1241, 1241, 314, 1241, 1241, 804, 937, 1241, 863, 804,
+ 155, 155, 155, 155, 155, 155, 208, 314, 1241, 1241,
+ 208, 208, 208, 299, 209, 1241, 208, 208, 1241, 342,
+ 208, 1241, 729, 805, 978, 735, 342, 568, 342, 732,
+ 678, 939, 185, 185, 208, 208, 208, 786, 731, 786,
+ 661, 733, 662, 662, 662, 662, 662, 662, 777, 983,
+ 779, 779, 779, 779, 779, 779, 779, 779, 779, 779,
+ 185, 210, 208, 1241, 342, 156, 208, 208, 208, 208,
+ 371, 974, 208, 208, 1080, 786, 208, 280, 777, 156,
+
+ 780, 780, 780, 780, 780, 781, 778, 778, 778, 778,
+ 208, 208, 208, 687, 687, 687, 687, 687, 687, 687,
+ 687, 687, 687, 568, 342, 784, 784, 784, 784, 784,
+ 784, 961, 979, 568, 342, 678, 810, 210, 234, 185,
+ 810, 977, 234, 234, 234, 786, 235, 185, 234, 234,
+ 1014, 1017, 234, 788, 788, 788, 788, 788, 788, 788,
+ 788, 788, 788, 314, 811, 342, 234, 234, 234, 789,
+ 789, 789, 789, 789, 790, 1241, 786, 787, 787, 787,
+ 787, 787, 787, 787, 787, 787, 787, 816, 818, 984,
+ 156, 816, 818, 236, 234, 1241, 342, 185, 234, 234,
+
+ 234, 234, 390, 156, 234, 234, 861, 719, 234, 720,
+ 720, 720, 720, 720, 720, 817, 819, 161, 863, 332,
+ 994, 863, 234, 234, 234, 828, 829, 830, 828, 828,
+ 828, 828, 828, 828, 828, 719, 861, 720, 720, 720,
+ 720, 720, 720, 720, 720, 720, 720, 771, 951, 236,
+ 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
+ 176, 314, 1091, 1234, 512, 512, 512, 512, 512, 512,
+ 719, 1241, 720, 720, 720, 720, 720, 720, 720, 720,
+ 720, 720, 1064, 951, 185, 798, 568, 342, 342, 798,
+ 512, 512, 512, 512, 512, 512, 269, 1209, 880, 880,
+
+ 269, 513, 513, 513, 513, 513, 513, 513, 513, 513,
+ 513, 176, 269, 799, 185, 513, 513, 513, 513, 513,
+ 513, 280, 280, 280, 280, 280, 280, 280, 280, 280,
+ 280, 280, 280, 280, 280, 280, 280, 280, 568, 342,
+ 282, 512, 512, 512, 512, 512, 512, 269, 269, 269,
+ 269, 269, 269, 269, 269, 269, 269, 269, 280, 280,
+ 280, 280, 280, 280, 280, 280, 280, 280, 1241, 1124,
+ 299, 1063, 280, 280, 280, 280, 280, 280, 776, 776,
+ 776, 776, 776, 776, 776, 776, 776, 776, 1241, 804,
+ 1241, 1241, 1241, 804, 1241, 1241, 1052, 1016, 269, 269,
+
+ 269, 269, 269, 269, 532, 185, 533, 533, 533, 533,
+ 533, 533, 533, 533, 533, 533, 1241, 805, 1241, 1241,
+ 156, 1012, 1061, 1062, 831, 1063, 1061, 1017, 810, 1241,
+ 1241, 1048, 810, 1241, 1241, 834, 816, 818, 835, 1090,
+ 816, 818, 314, 299, 532, 1006, 534, 534, 534, 534,
+ 534, 534, 534, 534, 534, 534, 811, 1241, 1241, 1241,
+ 342, 1055, 1005, 1057, 817, 819, 156, 1003, 798, 185,
+ 185, 880, 798, 742, 839, 743, 743, 743, 743, 743,
+ 743, 838, 1092, 299, 532, 314, 535, 535, 535, 535,
+ 535, 536, 533, 533, 533, 533, 799, 314, 1139, 841,
+
+ 842, 843, 841, 841, 841, 841, 841, 841, 841, 804,
+ 810, 816, 299, 804, 810, 816, 1002, 1121, 818, 1191,
+ 910, 1192, 818, 299, 298, 185, 537, 537, 537, 537,
+ 537, 537, 537, 537, 537, 537, 299, 805, 811, 817,
+ 537, 537, 537, 537, 537, 537, 819, 865, 865, 865,
+ 865, 865, 865, 865, 865, 865, 865, 866, 866, 866,
+ 866, 866, 867, 1186, 156, 991, 537, 537, 537, 537,
+ 537, 537, 538, 538, 538, 538, 538, 538, 538, 538,
+ 538, 538, 1049, 185, 990, 156, 538, 538, 538, 538,
+ 538, 538, 1241, 185, 864, 864, 864, 864, 864, 864,
+
+ 864, 864, 864, 864, 777, 1083, 778, 778, 778, 778,
+ 778, 778, 537, 537, 537, 537, 537, 537, 208, 568,
+ 342, 185, 208, 208, 208, 1210, 327, 1192, 208, 208,
+ 771, 880, 208, 873, 874, 875, 873, 873, 873, 873,
+ 873, 873, 873, 566, 299, 932, 208, 208, 208, 777,
+ 861, 778, 778, 778, 778, 778, 778, 778, 778, 778,
+ 778, 777, 951, 778, 778, 778, 778, 778, 778, 778,
+ 778, 778, 778, 328, 208, 1056, 1058, 1208, 208, 208,
+ 208, 208, 440, 1208, 208, 208, 185, 185, 208, 795,
+ 795, 795, 795, 795, 795, 795, 795, 795, 795, 924,
+
+ 921, 861, 208, 208, 208, 568, 342, 878, 878, 878,
+ 878, 878, 878, 1032, 920, 917, 1241, 786, 882, 882,
+ 882, 882, 882, 882, 882, 882, 882, 882, 1032, 328,
+ 447, 916, 448, 448, 448, 448, 448, 448, 448, 448,
+ 448, 448, 883, 883, 883, 883, 883, 884, 1241, 905,
+ 881, 881, 881, 881, 881, 881, 881, 881, 881, 881,
+ 798, 804, 810, 816, 798, 804, 810, 816, 1083, 156,
+ 447, 995, 448, 448, 448, 448, 448, 448, 448, 448,
+ 448, 448, 954, 954, 954, 954, 954, 955, 799, 805,
+ 811, 817, 904, 185, 995, 818, 995, 995, 1118, 818,
+
+ 972, 972, 972, 972, 972, 973, 902, 299, 185, 156,
+ 568, 342, 569, 569, 569, 569, 569, 569, 569, 569,
+ 569, 569, 570, 819, 901, 777, 571, 571, 571, 571,
+ 571, 571, 910, 911, 911, 911, 911, 911, 911, 911,
+ 911, 911, 911, 980, 1123, 992, 161, 980, 332, 992,
+ 771, 185, 571, 571, 571, 571, 571, 571, 342, 575,
+ 576, 577, 575, 575, 575, 575, 575, 575, 575, 578,
+ 995, 981, 566, 579, 579, 579, 579, 579, 579, 910,
+ 912, 912, 912, 912, 912, 912, 912, 912, 912, 912,
+ 457, 299, 280, 995, 299, 995, 996, 1140, 342, 579,
+
+ 579, 579, 579, 579, 579, 155, 993, 980, 155, 880,
+ 299, 980, 299, 852, 155, 155, 851, 848, 155, 155,
+ 156, 155, 155, 155, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 176, 981, 156, 155, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 156, 155, 185, 155, 155, 155, 155, 155, 155,
+ 155, 155, 155, 155, 155, 155, 155, 155, 155, 155,
+ 155, 620, 620, 620, 620, 620, 620, 620, 620, 620,
+ 620, 176, 250, 250, 250, 620, 620, 620, 620, 620,
+
+ 620, 910, 913, 913, 913, 913, 913, 914, 911, 911,
+ 911, 911, 910, 911, 911, 911, 911, 911, 911, 847,
+ 1122, 620, 620, 620, 620, 620, 620, 269, 185, 846,
+ 1171, 269, 621, 621, 621, 621, 621, 621, 621, 621,
+ 621, 621, 176, 269, 845, 844, 621, 621, 621, 621,
+ 621, 621, 280, 280, 280, 280, 280, 280, 280, 280,
+ 280, 280, 280, 280, 280, 280, 280, 280, 280, 299,
+ 840, 282, 620, 620, 620, 620, 620, 620, 269, 269,
+ 269, 269, 269, 269, 269, 269, 269, 269, 269, 583,
+ 1199, 1216, 861, 583, 940, 941, 942, 943, 940, 940,
+
+ 940, 940, 940, 940, 1032, 833, 861, 280, 280, 280,
+ 280, 280, 280, 280, 280, 280, 280, 584, 1103, 1163,
+ 832, 280, 280, 280, 280, 280, 280, 185, 719, 156,
+ 299, 156, 854, 855, 855, 855, 855, 855, 855, 1035,
+ 1035, 1035, 1035, 1035, 1036, 823, 822, 269, 269, 269,
+ 269, 269, 269, 532, 156, 533, 533, 533, 533, 533,
+ 533, 533, 533, 533, 533, 1061, 1062, 156, 1063, 1061,
+ 156, 945, 946, 947, 945, 945, 945, 945, 945, 945,
+ 945, 872, 872, 872, 872, 872, 872, 872, 872, 872,
+ 872, 156, 299, 532, 1241, 533, 533, 533, 533, 533,
+
+ 533, 533, 533, 533, 533, 861, 1103, 949, 949, 949,
+ 949, 949, 949, 250, 250, 250, 1158, 863, 953, 953,
+ 953, 953, 953, 953, 953, 953, 953, 953, 185, 156,
+ 985, 1241, 299, 661, 985, 662, 662, 662, 662, 662,
+ 662, 662, 662, 662, 662, 1241, 771, 952, 952, 952,
+ 952, 952, 952, 952, 952, 952, 952, 961, 986, 962,
+ 962, 962, 962, 962, 962, 962, 962, 962, 962, 566,
+ 987, 457, 156, 661, 987, 663, 663, 663, 663, 663,
+ 663, 663, 663, 663, 663, 961, 457, 963, 963, 963,
+ 963, 963, 963, 963, 963, 963, 963, 961, 988, 964,
+
+ 964, 964, 964, 964, 965, 962, 962, 962, 962, 759,
+ 758, 757, 156, 661, 756, 664, 664, 664, 664, 664,
+ 665, 662, 662, 662, 662, 888, 888, 888, 888, 888,
+ 888, 888, 888, 888, 888, 568, 342, 968, 968, 968,
+ 968, 968, 968, 755, 161, 754, 332, 880, 1184, 1184,
+ 1184, 1184, 156, 568, 342, 676, 676, 676, 676, 676,
+ 676, 676, 676, 676, 676, 570, 753, 752, 751, 675,
+ 675, 675, 675, 675, 675, 971, 971, 971, 971, 971,
+ 971, 971, 971, 971, 971, 997, 998, 999, 1000, 997,
+ 997, 997, 997, 997, 997, 675, 675, 675, 675, 675,
+
+ 675, 568, 342, 677, 677, 677, 677, 677, 677, 677,
+ 677, 677, 677, 678, 1125, 750, 749, 679, 679, 679,
+ 679, 679, 679, 1241, 748, 970, 970, 970, 970, 970,
+ 970, 970, 970, 970, 970, 925, 926, 926, 926, 926,
+ 926, 926, 747, 679, 679, 679, 679, 679, 679, 342,
+ 683, 684, 685, 683, 683, 683, 683, 683, 683, 683,
+ 686, 741, 740, 739, 687, 687, 687, 687, 687, 687,
+ 738, 737, 961, 299, 962, 962, 962, 962, 962, 962,
+ 980, 727, 1164, 161, 980, 332, 1164, 726, 1241, 1241,
+ 687, 687, 687, 687, 687, 687, 742, 495, 743, 743,
+
+ 743, 743, 743, 743, 743, 743, 743, 743, 981, 910,
+ 911, 911, 911, 911, 911, 911, 911, 911, 911, 911,
+ 985, 714, 713, 1023, 985, 1024, 1024, 1024, 1024, 1024,
+ 1024, 1024, 1024, 1024, 1024, 299, 742, 185, 744, 744,
+ 744, 744, 744, 744, 744, 744, 744, 744, 986, 910,
+ 911, 911, 911, 911, 911, 911, 911, 911, 911, 911,
+ 987, 985, 987, 1241, 987, 985, 987, 568, 342, 1047,
+ 1047, 1047, 1047, 1047, 1047, 299, 742, 185, 745, 745,
+ 745, 745, 745, 746, 743, 743, 743, 743, 988, 986,
+ 988, 1007, 1008, 1009, 1010, 1007, 1007, 1007, 1007, 1007,
+
+ 1007, 980, 985, 987, 670, 980, 985, 987, 181, 181,
+ 280, 280, 566, 457, 181, 299, 661, 185, 662, 662,
+ 662, 662, 662, 662, 662, 662, 662, 662, 299, 981,
+ 986, 988, 1023, 666, 1025, 1025, 1025, 1025, 1025, 1025,
+ 1025, 1025, 1025, 1025, 1106, 1106, 1106, 1106, 1106, 1107,
+ 314, 314, 314, 457, 182, 156, 661, 861, 662, 662,
+ 662, 662, 662, 662, 662, 662, 662, 662, 1023, 1103,
+ 1026, 1026, 1026, 1026, 1026, 1027, 1024, 1024, 1024, 1024,
+ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960,
+ 1190, 1191, 655, 1192, 1190, 156, 772, 773, 774, 772,
+
+ 772, 772, 772, 772, 772, 772, 775, 654, 653, 652,
+ 776, 776, 776, 776, 776, 776, 861, 651, 1030, 1030,
+ 1030, 1030, 1030, 1030, 181, 181, 650, 1053, 951, 1050,
+ 181, 1053, 649, 1050, 648, 647, 776, 776, 776, 776,
+ 776, 776, 568, 342, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 678, 1054, 644, 1051, 783, 783,
+ 783, 783, 783, 783, 1034, 1034, 1034, 1034, 1034, 1034,
+ 1034, 1034, 1034, 1034, 1042, 1043, 1044, 1042, 1042, 1042,
+ 1042, 1042, 1042, 1042, 783, 783, 783, 783, 783, 783,
+ 568, 342, 785, 785, 785, 785, 785, 785, 785, 785,
+
+ 785, 785, 786, 643, 176, 639, 787, 787, 787, 787,
+ 787, 787, 1241, 638, 1033, 1033, 1033, 1033, 1033, 1033,
+ 1033, 1033, 1033, 1033, 1050, 637, 1190, 1191, 1050, 1192,
+ 1190, 507, 787, 787, 787, 787, 787, 787, 342, 791,
+ 792, 793, 791, 791, 791, 791, 791, 791, 791, 794,
+ 495, 612, 1051, 795, 795, 795, 795, 795, 795, 961,
+ 495, 962, 962, 962, 962, 962, 962, 962, 962, 962,
+ 962, 341, 341, 280, 611, 495, 610, 341, 1241, 795,
+ 795, 795, 795, 795, 795, 742, 1241, 743, 743, 743,
+ 743, 743, 743, 743, 743, 743, 743, 961, 457, 962,
+
+ 962, 962, 962, 962, 962, 962, 962, 962, 962, 566,
+ 1053, 1119, 1050, 457, 1053, 1119, 1050, 1119, 182, 1050,
+ 552, 1119, 1053, 1050, 299, 742, 1053, 743, 743, 743,
+ 743, 743, 743, 743, 743, 743, 743, 1066, 1054, 1120,
+ 1051, 1066, 1067, 1068, 1069, 1120, 551, 1051, 550, 1073,
+ 1054, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074,
+ 1074, 314, 549, 548, 299, 854, 855, 855, 855, 855,
+ 855, 855, 855, 855, 855, 855, 185, 1066, 547, 185,
+ 546, 1066, 1067, 1068, 1069, 1156, 1156, 1156, 1156, 1156,
+ 1157, 1073, 1070, 1075, 1075, 1075, 1075, 1075, 1075, 1075,
+
+ 1075, 1075, 1075, 156, 854, 856, 856, 856, 856, 856,
+ 856, 856, 856, 856, 856, 1073, 545, 1076, 1076, 1076,
+ 1076, 1076, 1077, 1078, 1078, 1078, 1078, 1053, 453, 453,
+ 544, 1053, 1072, 1017, 453, 1018, 1018, 1018, 1018, 1018,
+ 1018, 543, 156, 854, 857, 857, 857, 857, 857, 858,
+ 855, 855, 855, 855, 1073, 1054, 1078, 1078, 1078, 1074,
+ 1074, 1074, 1074, 1074, 1074, 1074, 542, 1161, 541, 1159,
+ 540, 1161, 156, 1159, 282, 282, 314, 282, 282, 282,
+ 282, 156, 861, 539, 862, 862, 862, 862, 862, 862,
+ 862, 862, 862, 862, 863, 1162, 307, 1160, 864, 864,
+
+ 864, 864, 864, 864, 1093, 1094, 1095, 1093, 1093, 1093,
+ 1093, 1093, 1093, 1093, 1096, 1097, 1098, 1096, 1096, 1096,
+ 1096, 1096, 1096, 1096, 864, 864, 864, 864, 864, 864,
+ 868, 869, 870, 868, 868, 868, 868, 868, 868, 868,
+ 871, 156, 531, 527, 872, 872, 872, 872, 872, 872,
+ 1023, 526, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+ 1024, 1024, 1023, 525, 1024, 1024, 1024, 1024, 1024, 1024,
+ 872, 872, 872, 872, 872, 872, 568, 342, 878, 878,
+ 878, 878, 878, 878, 878, 878, 878, 878, 786, 524,
+ 523, 522, 877, 877, 877, 877, 877, 877, 1023, 521,
+
+ 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
+ 1073, 520, 1074, 1074, 1074, 1074, 1074, 1074, 877, 877,
+ 877, 877, 877, 877, 568, 342, 879, 879, 879, 879,
+ 879, 879, 879, 879, 879, 879, 880, 519, 518, 517,
+ 881, 881, 881, 881, 881, 881, 1041, 1041, 1041, 1041,
+ 1041, 1041, 1041, 1041, 1041, 1041, 1105, 1105, 1105, 1105,
+ 1105, 1105, 1105, 1105, 1105, 1105, 881, 881, 881, 881,
+ 881, 881, 342, 885, 886, 887, 885, 885, 885, 885,
+ 885, 885, 885, 516, 515, 514, 273, 888, 888, 888,
+ 888, 888, 888, 861, 503, 1101, 1101, 1101, 1101, 1101,
+
+ 1101, 500, 499, 498, 497, 1032, 342, 1112, 1112, 1112,
+ 1112, 1112, 1112, 888, 888, 888, 888, 888, 888, 155,
+ 1241, 282, 155, 1065, 282, 490, 282, 489, 155, 155,
+ 1065, 1065, 155, 155, 1065, 155, 155, 155, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 1065, 1065,
+ 1065, 155, 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 890, 185, 185,
+ 185, 185, 185, 185, 185, 156, 155, 185, 155, 155,
+ 155, 155, 155, 155, 155, 155, 155, 155, 155, 155,
+ 155, 155, 155, 155, 155, 269, 488, 487, 486, 269,
+
+ 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
+ 485, 269, 482, 481, 280, 280, 280, 280, 280, 280,
+ 280, 280, 280, 280, 280, 280, 280, 280, 915, 280,
+ 280, 280, 280, 280, 280, 280, 280, 480, 479, 282,
+ 269, 269, 269, 269, 269, 269, 269, 269, 269, 269,
+ 269, 269, 269, 269, 269, 269, 269, 925, 926, 926,
+ 926, 926, 926, 926, 926, 926, 926, 926, 1241, 478,
+ 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104, 1104,
+ 342, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112,
+ 1112, 477, 476, 475, 474, 299, 925, 927, 927, 927,
+
+ 927, 927, 927, 927, 927, 927, 927, 342, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 342, 1114,
+ 1114, 1114, 1114, 1114, 1115, 1112, 1112, 1112, 1112, 1119,
+ 473, 472, 471, 1119, 299, 925, 928, 928, 928, 928,
+ 928, 929, 926, 926, 926, 926, 470, 1159, 1241, 469,
+ 468, 1159, 1241, 1241, 1241, 1241, 1126, 1120, 182, 1127,
+ 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 1127, 174,
+ 560, 560, 299, 299, 298, 1160, 560, 298, 439, 561,
+ 561, 438, 430, 298, 298, 561, 185, 298, 298, 429,
+ 298, 298, 298, 314, 314, 314, 314, 314, 314, 314,
+
+ 314, 314, 314, 1070, 185, 428, 298, 314, 314, 314,
+ 314, 314, 314, 314, 314, 314, 314, 314, 314, 314,
+ 314, 930, 314, 314, 314, 314, 314, 314, 314, 314,
+ 299, 298, 314, 298, 298, 298, 298, 298, 298, 298,
+ 298, 298, 298, 298, 298, 298, 298, 298, 298, 298,
+ 854, 855, 855, 855, 855, 855, 855, 855, 855, 855,
+ 855, 1066, 427, 1116, 1116, 1066, 1067, 1068, 1069, 1241,
+ 1116, 426, 425, 1241, 1067, 1068, 1069, 1128, 1129, 1130,
+ 1128, 1128, 1128, 1128, 1128, 1128, 1128, 298, 156, 854,
+ 855, 855, 855, 855, 855, 855, 855, 855, 855, 855,
+
+ 1241, 1184, 418, 1184, 1241, 1241, 1241, 1069, 1241, 1184,
+ 303, 301, 1241, 1241, 1241, 1241, 1070, 1204, 1204, 1204,
+ 1204, 1204, 1204, 299, 1070, 296, 417, 156, 861, 416,
+ 949, 949, 949, 949, 949, 949, 949, 949, 949, 949,
+ 863, 861, 414, 950, 950, 950, 950, 950, 950, 950,
+ 950, 950, 950, 951, 413, 1070, 405, 952, 952, 952,
+ 952, 952, 952, 1072, 1073, 404, 1074, 1074, 1074, 1074,
+ 1074, 1074, 1074, 1074, 1074, 1074, 1235, 1235, 1235, 1235,
+ 1235, 1235, 403, 952, 952, 952, 952, 952, 952, 956,
+ 957, 958, 956, 956, 956, 956, 956, 956, 956, 959,
+
+ 402, 401, 400, 960, 960, 960, 960, 960, 960, 1073,
+ 1241, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074, 1074,
+ 1074, 1119, 1161, 270, 262, 1119, 1161, 257, 258, 960,
+ 960, 960, 960, 960, 960, 568, 342, 968, 968, 968,
+ 968, 968, 968, 968, 968, 968, 968, 880, 252, 1120,
+ 1162, 967, 967, 967, 967, 967, 967, 252, 1134, 1135,
+ 1136, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 246, 1083,
+ 314, 1084, 1084, 1084, 1084, 1084, 1084, 967, 967, 967,
+ 967, 967, 967, 568, 342, 969, 969, 969, 969, 969,
+ 969, 969, 969, 969, 969, 299, 204, 239, 156, 970,
+
+ 970, 970, 970, 970, 970, 1161, 387, 1241, 299, 1161,
+ 1071, 1159, 379, 565, 565, 1159, 378, 1071, 1071, 565,
+ 377, 1071, 376, 375, 156, 970, 970, 970, 970, 970,
+ 970, 155, 370, 1162, 155, 1071, 1071, 1071, 369, 1160,
+ 155, 155, 368, 367, 155, 155, 366, 155, 155, 155,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 280, 365, 185, 155, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 185, 156, 155, 975,
+ 155, 155, 155, 155, 155, 155, 155, 155, 155, 155,
+
+ 155, 155, 155, 155, 155, 155, 155, 269, 356, 355,
+ 354, 269, 280, 280, 280, 280, 280, 280, 280, 280,
+ 280, 280, 353, 269, 352, 351, 280, 280, 280, 280,
+ 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
+ 280, 280, 280, 1001, 280, 280, 280, 280, 280, 350,
+ 349, 282, 269, 269, 269, 269, 269, 269, 269, 269,
+ 269, 269, 269, 269, 269, 269, 269, 269, 269, 925,
+ 926, 926, 926, 926, 926, 926, 926, 926, 926, 926,
+ 1145, 348, 1146, 1146, 1146, 1146, 1146, 1146, 1146, 1146,
+ 1146, 1146, 1145, 347, 1147, 1147, 1147, 1147, 1147, 1147,
+
+ 1147, 1147, 1147, 1147, 182, 155, 182, 299, 925, 926,
+ 926, 926, 926, 926, 926, 926, 926, 926, 926, 1145,
+ 272, 1148, 1148, 1148, 1148, 1148, 1149, 1146, 1146, 1146,
+ 1146, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1111,
+ 1111, 170, 168, 161, 159, 156, 299, 298, 1187, 1187,
+ 298, 323, 1187, 1187, 322, 321, 298, 298, 320, 319,
+ 298, 298, 318, 298, 298, 298, 314, 314, 314, 314,
+ 314, 314, 314, 314, 314, 314, 1188, 1188, 314, 298,
+ 314, 314, 314, 314, 314, 314, 314, 314, 314, 314,
+ 314, 314, 314, 314, 314, 314, 314, 1011, 314, 314,
+
+ 314, 314, 314, 299, 298, 314, 298, 298, 298, 298,
+ 298, 298, 298, 298, 298, 298, 298, 298, 298, 298,
+ 298, 298, 298, 1017, 303, 1018, 1018, 1018, 1018, 1018,
+ 1018, 1018, 1018, 1018, 1018, 861, 299, 1152, 1152, 1152,
+ 1152, 1152, 1152, 296, 290, 289, 288, 1103, 1155, 1155,
+ 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 666, 666,
+ 287, 286, 156, 1017, 666, 1019, 1019, 1019, 1019, 1019,
+ 1019, 1019, 1019, 1019, 1019, 1241, 285, 1154, 1154, 1154,
+ 1154, 1154, 1154, 1154, 1154, 1154, 1154, 342, 1112, 1112,
+ 1112, 1112, 1112, 1112, 1112, 1112, 1112, 1112, 668, 668,
+
+ 280, 258, 156, 1017, 668, 1020, 1020, 1020, 1020, 1020,
+ 1021, 1022, 1022, 1022, 1022, 342, 1112, 1112, 1112, 1112,
+ 1112, 1112, 1112, 1112, 1112, 1112, 1127, 1127, 1127, 1127,
+ 1127, 1127, 1127, 1127, 1127, 1127, 252, 246, 669, 669,
+ 158, 239, 156, 1017, 669, 1022, 1022, 1022, 1018, 1018,
+ 1018, 1018, 1018, 1018, 1018, 1127, 1127, 1127, 1127, 1127,
+ 1127, 1127, 1127, 1127, 1127, 1165, 158, 1166, 1166, 1166,
+ 1166, 1166, 1166, 1166, 1166, 1166, 1166, 197, 768, 768,
+ 232, 194, 156, 861, 768, 1030, 1030, 1030, 1030, 1030,
+ 1030, 1030, 1030, 1030, 1030, 951, 861, 185, 1031, 1031,
+
+ 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1031, 1032, 224,
+ 222, 200, 1033, 1033, 1033, 1033, 1033, 1033, 1165, 199,
+ 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167,
+ 1145, 196, 1146, 1146, 1146, 1146, 1146, 1146, 1033, 1033,
+ 1033, 1033, 1033, 1033, 1037, 1038, 1039, 1037, 1037, 1037,
+ 1037, 1037, 1037, 1037, 1040, 195, 192, 182, 1041, 1041,
+ 1041, 1041, 1041, 1041, 1165, 170, 1168, 1168, 1168, 1168,
+ 1168, 1169, 1166, 1166, 1166, 1166, 1165, 159, 1166, 1166,
+ 1166, 1166, 1166, 1166, 1041, 1041, 1041, 1041, 1041, 1041,
+ 568, 342, 1047, 1047, 1047, 1047, 1047, 1047, 1047, 1047,
+
+ 1047, 1047, 1083, 158, 1084, 1084, 1084, 1084, 1084, 1084,
+ 1084, 1084, 1084, 1084, 156, 1159, 1241, 1241, 1140, 1159,
+ 1141, 1141, 1141, 1141, 1141, 1141, 1161, 1241, 1241, 1241,
+ 1161, 1177, 1178, 1179, 1177, 1177, 1177, 1177, 1177, 1177,
+ 1177, 299, 1083, 1160, 1085, 1085, 1085, 1085, 1085, 1085,
+ 1085, 1085, 1085, 1085, 1162, 1241, 1211, 156, 1212, 1212,
+ 1212, 1212, 1212, 1212, 314, 769, 769, 1241, 156, 1241,
+ 1241, 769, 770, 770, 282, 314, 1241, 282, 770, 282,
+ 1241, 299, 1083, 1241, 1086, 1086, 1086, 1086, 1086, 1087,
+ 1088, 1088, 1088, 1088, 1180, 1181, 1182, 1180, 1180, 1180,
+
+ 1180, 1180, 1180, 1180, 1145, 1241, 1146, 1146, 1146, 1146,
+ 1146, 1146, 1146, 1146, 1146, 1146, 1241, 1241, 1241, 1187,
+ 1241, 299, 1083, 1187, 1088, 1088, 1088, 1084, 1084, 1084,
+ 1084, 1084, 1084, 1084, 1145, 1241, 1146, 1146, 1146, 1146,
+ 1146, 1146, 1146, 1146, 1146, 1146, 861, 1188, 1185, 1185,
+ 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1241, 1241,
+ 1241, 299, 1017, 1241, 1018, 1018, 1018, 1018, 1018, 1018,
+ 1018, 1018, 1018, 1018, 1241, 1241, 185, 1193, 1194, 1195,
+ 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1165, 1241, 1166,
+ 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1241,
+
+ 1241, 156, 1017, 1241, 1018, 1018, 1018, 1018, 1018, 1018,
+ 1018, 1018, 1018, 1018, 1165, 1241, 1166, 1166, 1166, 1166,
+ 1166, 1166, 1166, 1166, 1166, 1166, 1241, 1241, 1241, 1241,
+ 1241, 1196, 1197, 1198, 1196, 1196, 1196, 1196, 1196, 1196,
+ 1196, 156, 861, 1241, 1101, 1101, 1101, 1101, 1101, 1101,
+ 1101, 1101, 1101, 1101, 1032, 861, 1241, 1102, 1102, 1102,
+ 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1103, 299, 1241,
+ 1241, 1104, 1104, 1104, 1104, 1104, 1104, 1171, 1241, 1172,
+ 1172, 1172, 1172, 1172, 1172, 1187, 859, 859, 1241, 1187,
+ 860, 860, 859, 1241, 1241, 1241, 860, 1104, 1104, 1104,
+
+ 1104, 1104, 1104, 1108, 1109, 1110, 1108, 1108, 1108, 1108,
+ 1108, 1108, 1108, 1188, 1241, 1241, 299, 1111, 1111, 1111,
+ 1111, 1111, 1111, 1204, 1204, 1204, 1204, 1204, 1204, 1204,
+ 1204, 1204, 1204, 1241, 314, 944, 944, 1241, 1241, 1241,
+ 1241, 944, 1241, 1111, 1111, 1111, 1111, 1111, 1111, 1083,
+ 1241, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084,
+ 1084, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205,
+ 1205, 1206, 1206, 1206, 1206, 1206, 1207, 1204, 1204, 1204,
+ 1204, 1028, 1028, 1241, 1099, 1099, 1241, 1028, 299, 1083,
+ 1099, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084, 1084,
+
+ 1084, 1211, 1241, 1212, 1212, 1212, 1212, 1212, 1212, 1212,
+ 1212, 1212, 1212, 1211, 1241, 1213, 1213, 1213, 1213, 1213,
+ 1213, 1213, 1213, 1213, 1213, 1241, 1241, 1241, 299, 1140,
+ 1241, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141,
+ 1141, 1211, 1241, 1214, 1214, 1214, 1214, 1214, 1215, 1212,
+ 1212, 1212, 1212, 1221, 1222, 1223, 1221, 1221, 1221, 1221,
+ 1221, 1221, 1221, 1241, 1150, 1150, 1241, 1241, 156, 1140,
+ 1150, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142,
+ 1142, 1241, 1199, 1241, 1200, 1200, 1200, 1200, 1200, 1200,
+ 156, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204,
+
+ 1204, 1183, 1183, 1241, 1241, 1241, 1241, 1183, 156, 1140,
+ 1241, 1143, 1143, 1143, 1143, 1143, 1144, 1141, 1141, 1141,
+ 1141, 156, 1204, 1204, 1204, 1204, 1204, 1204, 1204, 1204,
+ 1204, 1204, 1225, 1226, 1227, 1225, 1225, 1225, 1225, 1225,
+ 1225, 1225, 1241, 1241, 1241, 1241, 1241, 1241, 156, 861,
+ 1241, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152, 1152,
+ 1152, 1103, 861, 1241, 1153, 1153, 1153, 1153, 1153, 1153,
+ 1153, 1153, 1153, 1153, 1241, 1241, 1241, 1241, 1154, 1154,
+ 1154, 1154, 1154, 1154, 1211, 1241, 1212, 1212, 1212, 1212,
+ 1212, 1212, 1212, 1212, 1212, 1212, 1241, 1241, 1241, 1241,
+
+ 1241, 1241, 1241, 1241, 1154, 1154, 1154, 1154, 1154, 1154,
+ 1171, 1241, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172,
+ 1172, 1172, 1211, 1241, 1212, 1212, 1212, 1212, 1212, 1212,
+ 1212, 1212, 1212, 1212, 1228, 1229, 1230, 1228, 1228, 1228,
+ 1228, 1228, 1228, 1228, 1241, 1241, 1241, 1241, 1241, 299,
+ 1171, 1241, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173,
+ 1173, 1173, 1241, 1216, 1241, 1217, 1217, 1217, 1217, 1217,
+ 1217, 299, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231,
+ 1231, 1231, 1241, 1231, 1231, 1231, 1231, 1231, 1231, 299,
+ 1171, 1241, 1174, 1174, 1174, 1174, 1174, 1175, 1172, 1172,
+
+ 1172, 1172, 299, 1241, 1241, 1241, 1241, 1241, 1241, 156,
+ 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221,
+ 156, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 299,
+ 1140, 1241, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141,
+ 1141, 1141, 1241, 1241, 1241, 1241, 1241, 156, 1232, 1232,
+ 1232, 1232, 1232, 1233, 1231, 1231, 1231, 1231, 1235, 1235,
+ 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1241, 156,
+ 1140, 1241, 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141,
+ 1141, 1141, 1241, 1241, 1241, 156, 1225, 1225, 1225, 1225,
+ 1225, 1225, 1225, 1225, 1225, 1225, 1236, 1236, 1236, 1236,
+
+ 1236, 1237, 1235, 1235, 1235, 1235, 1241, 1241, 1241, 156,
+ 1171, 1241, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172,
+ 1172, 1172, 1241, 1241, 1241, 1238, 1238, 1238, 1238, 1238,
+ 1238, 1238, 1238, 1238, 1238, 1228, 1228, 1228, 1228, 1228,
+ 1228, 1228, 1228, 1228, 1228, 1241, 1241, 1241, 1241, 299,
+ 1171, 1241, 1172, 1172, 1172, 1172, 1172, 1172, 1172, 1172,
+ 1172, 1172, 299, 1241, 1241, 1238, 1238, 1238, 1238, 1238,
+ 1238, 1241, 299, 1239, 1239, 1239, 1239, 1239, 1240, 1238,
+ 1238, 1238, 1238, 1241, 1241, 1241, 1241, 1241, 1241, 299,
+ 1199, 1241, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200,
+
+ 1200, 1200, 299, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 299, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231, 1231,
+ 1231, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 156,
+ 1199, 1241, 1201, 1201, 1201, 1201, 1201, 1201, 1201, 1201,
+ 1201, 1201, 1241, 1241, 1241, 1241, 1241, 1241, 156, 1235,
+ 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1235, 1238,
+ 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 1238, 156,
+ 1199, 1241, 1202, 1202, 1202, 1202, 1202, 1203, 1200, 1200,
+ 1200, 1200, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 299, 1241, 1241, 1241,
+
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 156,
+ 1216, 1241, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 299,
+ 1216, 1241, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218,
+ 1218, 1218, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 299,
+ 1216, 1241, 1219, 1219, 1219, 1219, 1219, 1220, 1217, 1217,
+
+ 1217, 1217, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 299,
+ 1199, 1241, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200,
+ 1200, 1200, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 156,
+ 1199, 1241, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200,
+ 1200, 1200, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 156,
+ 1216, 1241, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 299,
+ 1216, 1241, 1217, 1217, 1217, 1217, 1217, 1217, 1217, 1217,
+ 1217, 1217, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 299,
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+ 77, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+ 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+ 84, 84, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 129, 129, 129, 129, 129,
+
+ 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
+ 129, 129, 129, 129, 129, 129, 155, 1241, 1241, 155,
+ 1241, 1241, 1241, 155, 1241, 155, 1241, 155, 155, 155,
+ 1241, 1241, 155, 155, 155, 155, 155, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 165, 1241,
+ 1241, 165, 1241, 1241, 165, 165, 1241, 165, 1241, 165,
+ 165, 165, 165, 1241, 165, 165, 165, 165, 165, 169,
+ 1241, 1241, 169, 1241, 1241, 1241, 169, 1241, 169, 1241,
+ 169, 169, 169, 1241, 1241, 169, 169, 169, 169, 169,
+
+ 171, 1241, 1241, 171, 171, 171, 1241, 171, 171, 171,
+ 1241, 171, 171, 171, 1241, 1241, 171, 171, 171, 171,
+ 171, 207, 207, 1241, 207, 207, 207, 1241, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 229, 1241, 1241, 229, 229, 229, 1241, 229,
+ 229, 229, 1241, 229, 229, 229, 1241, 1241, 229, 229,
+ 229, 229, 229, 233, 233, 1241, 233, 233, 233, 1241,
+ 233, 233, 233, 233, 233, 233, 233, 233, 233, 233,
+ 233, 233, 233, 233, 238, 1241, 1241, 238, 238, 238,
+ 1241, 238, 238, 238, 1241, 238, 238, 238, 1241, 238,
+
+ 238, 1241, 238, 238, 238, 244, 244, 1241, 244, 244,
+ 244, 1241, 1241, 244, 244, 244, 244, 244, 244, 244,
+ 244, 244, 1241, 244, 244, 244, 247, 247, 247, 247,
+ 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
+ 247, 247, 247, 247, 247, 247, 247, 251, 1241, 1241,
+ 251, 251, 1241, 1241, 251, 251, 251, 1241, 251, 251,
+ 251, 251, 1241, 251, 251, 251, 251, 251, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 257,
+ 257, 1241, 257, 257, 1241, 257, 257, 257, 257, 257,
+
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 264, 1241, 1241, 264, 1241, 1241, 264, 264, 1241, 264,
+ 1241, 264, 264, 264, 264, 1241, 264, 264, 264, 264,
+ 264, 268, 1241, 1241, 268, 1241, 1241, 1241, 268, 1241,
+ 268, 1241, 268, 268, 268, 1241, 268, 268, 268, 268,
+ 268, 268, 271, 1241, 1241, 271, 271, 271, 1241, 271,
+ 271, 271, 1241, 271, 271, 271, 1241, 271, 271, 271,
+ 271, 271, 271, 208, 208, 1241, 208, 208, 208, 1241,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 295, 1241, 1241, 1241, 295, 295,
+
+ 295, 295, 295, 295, 295, 295, 295, 295, 295, 295,
+ 295, 295, 295, 295, 295, 298, 1241, 1241, 298, 1241,
+ 1241, 1241, 298, 1241, 298, 1241, 298, 298, 298, 1241,
+ 1241, 298, 298, 298, 298, 298, 300, 1241, 1241, 300,
+ 1241, 1241, 300, 300, 1241, 300, 1241, 300, 300, 300,
+ 300, 1241, 300, 300, 300, 300, 300, 302, 1241, 1241,
+ 302, 1241, 1241, 1241, 302, 1241, 302, 1241, 302, 302,
+ 302, 1241, 1241, 302, 302, 302, 302, 302, 304, 1241,
+ 1241, 304, 304, 304, 1241, 304, 304, 304, 1241, 304,
+ 304, 304, 1241, 1241, 304, 304, 304, 304, 304, 326,
+
+ 326, 1241, 326, 326, 326, 1241, 326, 326, 326, 326,
+ 326, 326, 326, 326, 326, 326, 326, 326, 326, 326,
+ 155, 1241, 1241, 155, 1241, 1241, 1241, 155, 1241, 155,
+ 1241, 155, 155, 155, 1241, 1241, 155, 155, 155, 155,
+ 155, 331, 331, 331, 331, 331, 331, 331, 331, 331,
+ 331, 331, 331, 331, 331, 331, 331, 331, 331, 331,
+ 331, 331, 333, 333, 1241, 333, 333, 333, 333, 333,
+ 333, 333, 333, 333, 333, 333, 333, 333, 333, 333,
+ 333, 333, 333, 165, 1241, 1241, 165, 1241, 1241, 1241,
+ 165, 1241, 165, 1241, 165, 165, 165, 1241, 1241, 165,
+
+ 165, 165, 165, 165, 169, 1241, 1241, 169, 1241, 1241,
+ 1241, 169, 1241, 169, 1241, 169, 169, 169, 1241, 1241,
+ 169, 169, 169, 169, 169, 171, 1241, 1241, 171, 171,
+ 171, 1241, 171, 171, 171, 1241, 171, 171, 171, 1241,
+ 1241, 171, 171, 171, 171, 171, 172, 1241, 1241, 172,
+ 172, 172, 1241, 172, 172, 172, 1241, 172, 172, 172,
+ 1241, 1241, 172, 172, 172, 172, 172, 343, 343, 343,
+ 1241, 1241, 1241, 1241, 343, 207, 207, 1241, 207, 207,
+ 207, 1241, 207, 207, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 208, 208, 1241, 208,
+
+ 208, 208, 1241, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 229, 1241, 1241,
+ 229, 229, 229, 1241, 229, 229, 229, 1241, 229, 229,
+ 229, 1241, 1241, 229, 229, 229, 229, 229, 230, 1241,
+ 1241, 230, 230, 230, 1241, 230, 230, 230, 1241, 230,
+ 230, 230, 1241, 1241, 230, 230, 230, 230, 230, 233,
+ 233, 1241, 233, 233, 233, 1241, 233, 233, 233, 233,
+ 233, 233, 233, 233, 233, 233, 233, 233, 233, 233,
+ 234, 234, 1241, 234, 234, 234, 1241, 234, 234, 234,
+ 234, 234, 234, 234, 234, 234, 234, 234, 234, 234,
+
+ 234, 238, 1241, 1241, 238, 238, 238, 1241, 238, 238,
+ 238, 1241, 238, 238, 238, 1241, 238, 238, 1241, 238,
+ 238, 238, 244, 244, 1241, 244, 244, 244, 1241, 1241,
+ 244, 244, 244, 244, 244, 244, 244, 244, 244, 1241,
+ 244, 244, 244, 251, 1241, 1241, 251, 251, 1241, 1241,
+ 251, 251, 251, 1241, 251, 251, 251, 251, 1241, 251,
+ 251, 251, 251, 251, 257, 257, 1241, 257, 257, 1241,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 267, 1241, 1241, 267, 1241,
+ 1241, 1241, 267, 1241, 267, 1241, 267, 267, 267, 1241,
+
+ 1241, 267, 267, 267, 267, 267, 268, 1241, 1241, 268,
+ 1241, 1241, 1241, 268, 1241, 268, 1241, 268, 268, 268,
+ 1241, 268, 268, 268, 268, 268, 268, 269, 1241, 1241,
+ 269, 269, 1241, 269, 269, 1241, 1241, 269, 269, 271,
+ 1241, 1241, 271, 271, 271, 1241, 271, 271, 271, 1241,
+ 271, 271, 271, 1241, 271, 271, 271, 271, 271, 271,
+ 295, 1241, 1241, 1241, 295, 295, 295, 295, 295, 295,
+ 295, 295, 295, 295, 295, 295, 295, 295, 295, 295,
+ 295, 298, 1241, 1241, 298, 1241, 1241, 1241, 298, 1241,
+ 298, 1241, 298, 298, 298, 1241, 1241, 298, 298, 298,
+
+ 298, 298, 300, 1241, 1241, 300, 1241, 1241, 1241, 300,
+ 1241, 300, 1241, 300, 300, 300, 1241, 1241, 300, 300,
+ 300, 300, 300, 302, 1241, 1241, 302, 1241, 1241, 1241,
+ 302, 1241, 302, 1241, 302, 302, 302, 1241, 1241, 302,
+ 302, 302, 302, 302, 304, 1241, 1241, 304, 304, 304,
+ 1241, 304, 304, 304, 1241, 304, 304, 304, 1241, 1241,
+ 304, 304, 304, 304, 304, 305, 1241, 1241, 305, 305,
+ 305, 1241, 305, 305, 305, 1241, 305, 305, 305, 1241,
+ 1241, 305, 305, 305, 305, 305, 326, 326, 1241, 326,
+ 326, 326, 1241, 326, 326, 326, 326, 326, 326, 326,
+
+ 326, 326, 326, 326, 326, 326, 326, 331, 331, 331,
+ 331, 331, 331, 331, 331, 331, 331, 331, 331, 331,
+ 331, 331, 331, 331, 331, 331, 331, 331, 445, 445,
+ 445, 445, 445, 445, 445, 445, 445, 445, 445, 445,
+ 445, 445, 445, 445, 445, 445, 445, 445, 445, 155,
+ 1241, 1241, 155, 1241, 1241, 1241, 155, 1241, 155, 1241,
+ 155, 155, 155, 1241, 1241, 155, 155, 155, 155, 155,
+ 459, 459, 459, 1241, 1241, 1241, 1241, 459, 207, 207,
+ 1241, 207, 207, 207, 1241, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 207, 234,
+
+ 234, 1241, 234, 234, 234, 234, 234, 234, 234, 234,
+ 234, 234, 234, 234, 234, 234, 234, 234, 234, 234,
+ 233, 233, 1241, 233, 233, 233, 1241, 233, 233, 233,
+ 233, 233, 233, 233, 233, 233, 233, 233, 233, 233,
+ 233, 208, 208, 1241, 208, 208, 208, 1241, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 567, 567, 567, 1241, 1241, 1241, 1241, 567,
+ 465, 465, 465, 1241, 1241, 1241, 1241, 465, 331, 331,
+ 331, 331, 331, 331, 331, 331, 331, 331, 331, 331,
+ 331, 331, 331, 331, 331, 331, 331, 331, 331, 234,
+
+ 234, 1241, 234, 234, 234, 1241, 234, 234, 234, 234,
+ 234, 234, 234, 234, 234, 234, 234, 234, 234, 234,
+ 671, 671, 671, 1241, 1241, 1241, 1241, 671, 675, 675,
+ 675, 675, 1241, 1241, 1241, 1241, 675, 782, 782, 782,
+ 1241, 1241, 1241, 1241, 782, 783, 783, 783, 783, 1241,
+ 1241, 1241, 1241, 783, 876, 876, 876, 1241, 1241, 1241,
+ 1241, 876, 877, 877, 877, 877, 1241, 1241, 1241, 1241,
+ 877, 331, 331, 331, 331, 331, 331, 331, 331, 331,
+ 331, 331, 331, 331, 331, 331, 331, 331, 331, 331,
+ 331, 331, 269, 1241, 1241, 269, 269, 1241, 269, 269,
+
+ 1241, 1241, 269, 269, 298, 1241, 1241, 298, 1241, 1241,
+ 1241, 298, 1241, 298, 1241, 298, 298, 298, 1241, 1241,
+ 298, 298, 298, 298, 298, 948, 1241, 948, 948, 1241,
+ 1241, 1241, 1241, 948, 966, 966, 966, 1241, 1241, 1241,
+ 1241, 966, 967, 967, 967, 967, 1241, 1241, 1241, 1241,
+ 967, 331, 331, 331, 331, 331, 331, 331, 331, 331,
+ 331, 331, 331, 331, 331, 331, 331, 331, 331, 331,
+ 331, 331, 269, 1241, 1241, 269, 269, 1241, 269, 269,
+ 1241, 1241, 269, 269, 298, 1241, 1241, 298, 1241, 1241,
+ 1241, 298, 1241, 298, 1241, 298, 298, 298, 1241, 1241,
+
+ 298, 298, 298, 298, 298, 1029, 1241, 1029, 1029, 1241,
+ 1241, 1241, 1241, 1029, 1045, 1045, 1045, 1241, 1241, 1241,
+ 1241, 1045, 1046, 1046, 1046, 1241, 1241, 1241, 1241, 1241,
+ 1046, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
+ 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
+ 1060, 1060, 1065, 1065, 1241, 1065, 1065, 1065, 1065, 1065,
+ 1241, 1065, 1241, 1065, 1065, 1065, 1241, 1241, 1065, 1065,
+ 1065, 1065, 1065, 1071, 1071, 1241, 1071, 1071, 1071, 1071,
+ 1071, 1241, 1071, 1241, 1071, 1071, 1071, 1241, 1241, 1071,
+ 1071, 1071, 1071, 1071, 1100, 1241, 1100, 1100, 1241, 1241,
+
+ 1241, 1241, 1100, 1151, 1241, 1151, 1151, 1241, 1241, 1241,
+ 1241, 1151, 1189, 1189, 1189, 1189, 1189, 1189, 1189, 1189,
+ 1189, 1189, 1189, 1189, 1189, 1189, 1189, 1189, 1189, 1189,
+ 1189, 1189, 1189, 21, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241
+ } ;
+
+static const flex_int16_t yy_chk[9611] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 2, 23, 43, 41,
+ 2, 23, 43, 2, 5, 5, 375, 5, 5, 5,
+ 41, 5, 6, 6, 375, 6, 6, 6, 5, 6,
+
+ 7, 7, 55, 7, 7, 7, 6, 7, 7, 29,
+ 2, 2, 5, 5, 45, 2, 55, 49, 45, 502,
+ 6, 6, 49, 2, 69, 45, 2, 3, 69, 116,
+ 29, 3, 13, 13, 3, 13, 13, 13, 13, 5,
+ 116, 3, 502, 44, 3, 52, 44, 6, 14, 14,
+ 44, 14, 14, 14, 14, 7, 44, 29, 3, 3,
+ 52, 3, 37, 37, 37, 37, 37, 37, 65, 3,
+ 160, 3, 160, 3, 3, 46, 3, 448, 46, 46,
+ 107, 8, 8, 3, 8, 8, 8, 13, 8, 8,
+ 17, 17, 17, 17, 17, 17, 17, 65, 67, 3,
+
+ 4, 107, 67, 14, 4, 34, 34, 4, 59, 63,
+ 34, 34, 67, 63, 4, 85, 448, 4, 59, 85,
+ 18, 18, 18, 18, 18, 18, 18, 59, 107, 63,
+ 34, 4, 4, 76, 4, 1238, 8, 91, 91, 128,
+ 91, 91, 4, 76, 4, 17, 4, 4, 128, 4,
+ 93, 93, 76, 93, 93, 34, 4, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 60, 104, 97,
+ 99, 60, 4, 9, 9, 18, 9, 9, 9, 58,
+ 9, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 62, 364, 364, 62, 97, 99, 117, 62, 183,
+
+ 117, 60, 60, 125, 62, 157, 60, 101, 101, 157,
+ 101, 101, 103, 183, 60, 142, 103, 60, 104, 226,
+ 62, 106, 106, 226, 106, 106, 142, 106, 9, 130,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 10, 10,
+ 125, 10, 10, 10, 68, 10, 134, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 103, 112, 112,
+ 112, 112, 112, 112, 1234, 70, 70, 134, 205, 130,
+ 70, 70, 111, 111, 111, 111, 111, 111, 111, 111,
+ 111, 111, 139, 139, 139, 139, 139, 139, 132, 132,
+
+ 70, 132, 132, 10, 134, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 11, 11, 70, 11, 11, 11, 11,
+ 11, 143, 205, 331, 143, 331, 11, 11, 11, 126,
+ 182, 126, 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 182, 11, 132, 167, 228, 136, 136, 208, 228,
+ 1231, 136, 136, 138, 138, 138, 138, 138, 138, 138,
+ 138, 138, 138, 211, 222, 167, 211, 154, 11, 12,
+ 12, 136, 12, 12, 12, 12, 12, 154, 1212, 212,
+ 223, 222, 12, 12, 12, 212, 154, 203, 203, 245,
+
+ 203, 203, 167, 245, 223, 208, 136, 153, 12, 153,
+ 153, 153, 153, 153, 153, 153, 153, 153, 153, 163,
+ 163, 163, 163, 163, 163, 163, 163, 163, 163, 240,
+ 240, 1185, 240, 240, 12, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 28, 260, 28,
+ 164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
+
+ 221, 28, 807, 234, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 35, 807, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 297, 1183, 224,
+ 35, 35, 35, 35, 35, 35, 224, 452, 260, 324,
+ 220, 156, 156, 156, 156, 156, 220, 221, 156, 156,
+ 234, 262, 156, 35, 220, 262, 35, 35, 35, 35,
+ 35, 35, 42, 237, 452, 42, 156, 156, 156, 237,
+ 329, 42, 42, 329, 384, 42, 42, 297, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 384, 324, 42, 42, 42, 42, 42, 42,
+
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 219,
+ 1166, 219, 47, 47, 47, 47, 47, 47, 332, 393,
+ 332, 259, 47, 393, 166, 259, 47, 166, 166, 166,
+ 166, 166, 166, 166, 166, 166, 166, 386, 47, 47,
+ 47, 47, 47, 47, 56, 56, 374, 56, 56, 56,
+ 56, 56, 296, 386, 56, 56, 296, 330, 56, 171,
+
+ 171, 374, 1154, 330, 171, 171, 180, 180, 180, 180,
+ 180, 180, 56, 56, 56, 57, 259, 219, 469, 57,
+ 57, 57, 345, 57, 171, 57, 57, 345, 343, 57,
+ 168, 168, 168, 168, 168, 469, 225, 168, 168, 343,
+ 225, 168, 459, 57, 57, 57, 333, 296, 333, 171,
+ 225, 264, 381, 459, 381, 168, 168, 168, 178, 178,
+ 178, 178, 178, 178, 178, 178, 178, 178, 382, 460,
+ 57, 61, 264, 61, 382, 170, 170, 170, 170, 170,
+ 460, 385, 170, 170, 385, 61, 170, 567, 61, 61,
+ 61, 61, 61, 61, 61, 61, 61, 61, 567, 264,
+
+ 170, 170, 170, 174, 174, 174, 174, 174, 174, 174,
+ 174, 174, 174, 179, 179, 179, 179, 179, 179, 179,
+ 179, 179, 179, 206, 206, 210, 206, 206, 210, 292,
+ 292, 1153, 210, 210, 213, 492, 61, 75, 213, 392,
+ 174, 75, 75, 75, 380, 75, 380, 75, 75, 196,
+ 196, 75, 389, 196, 392, 196, 196, 416, 416, 196,
+ 416, 196, 196, 1151, 492, 75, 75, 75, 213, 213,
+ 229, 229, 415, 213, 443, 229, 229, 292, 206, 236,
+ 210, 213, 236, 265, 213, 471, 236, 236, 445, 443,
+ 445, 479, 75, 83, 83, 229, 83, 83, 83, 389,
+
+ 83, 479, 471, 380, 265, 83, 466, 83, 227, 227,
+ 227, 227, 227, 227, 227, 227, 227, 227, 466, 415,
+ 229, 83, 83, 232, 232, 1150, 446, 232, 446, 232,
+ 232, 265, 468, 232, 236, 232, 248, 248, 483, 248,
+ 248, 256, 256, 481, 256, 256, 472, 483, 83, 83,
+ 92, 468, 92, 249, 249, 249, 249, 249, 249, 249,
+ 249, 249, 249, 481, 92, 472, 489, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 108, 261, 261,
+ 108, 261, 261, 489, 470, 252, 108, 108, 470, 252,
+ 108, 252, 252, 108, 108, 328, 256, 272, 328, 252,
+
+ 1146, 272, 328, 328, 272, 373, 373, 108, 373, 108,
+ 528, 272, 470, 528, 252, 273, 273, 273, 273, 273,
+ 273, 273, 273, 273, 273, 272, 272, 278, 278, 278,
+ 278, 278, 278, 108, 108, 108, 109, 477, 802, 109,
+ 373, 802, 109, 109, 486, 109, 109, 109, 109, 109,
+ 328, 477, 109, 109, 266, 266, 266, 266, 456, 456,
+ 456, 266, 266, 488, 486, 266, 109, 109, 109, 276,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 488,
+ 266, 266, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 109, 109, 109, 110, 504, 581, 110, 110,
+
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 581, 504, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 473, 1139, 505,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 113, 473, 113,
+ 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
+ 478, 476, 484, 113, 113, 113, 113, 113, 113, 476,
+ 484, 270, 270, 270, 270, 270, 505, 491, 270, 270,
+ 491, 478, 270, 312, 312, 312, 312, 312, 312, 113,
+
+ 113, 113, 113, 113, 113, 114, 270, 270, 270, 114,
+ 114, 114, 114, 114, 114, 114, 114, 114, 114, 114,
+ 114, 114, 491, 485, 114, 114, 114, 114, 114, 114,
+ 114, 114, 114, 114, 114, 114, 114, 114, 114, 114,
+ 114, 114, 114, 114, 114, 114, 114, 485, 1133, 114,
+ 114, 114, 114, 114, 114, 114, 114, 114, 114, 114,
+ 114, 114, 114, 114, 114, 114, 114, 118, 118, 118,
+ 118, 118, 118, 118, 118, 118, 118, 118, 480, 537,
+ 494, 118, 118, 118, 118, 118, 118, 494, 288, 288,
+ 480, 118, 288, 482, 288, 288, 1117, 594, 288, 475,
+
+ 288, 442, 442, 475, 442, 594, 537, 118, 118, 118,
+ 118, 118, 118, 137, 482, 137, 137, 137, 137, 137,
+ 137, 137, 137, 137, 137, 137, 493, 475, 506, 137,
+ 137, 137, 137, 137, 137, 506, 442, 474, 608, 556,
+ 299, 299, 299, 299, 299, 503, 556, 299, 299, 474,
+ 580, 299, 137, 533, 474, 137, 137, 137, 137, 137,
+ 137, 140, 493, 517, 140, 299, 299, 299, 517, 580,
+ 140, 140, 503, 608, 140, 140, 1116, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 503, 533, 140, 140, 140, 140, 140, 140, 140,
+
+ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 144, 144, 144,
+ 144, 144, 144, 144, 144, 144, 144, 144, 849, 555,
+ 849, 144, 144, 144, 144, 144, 144, 553, 321, 321,
+ 553, 144, 321, 1112, 321, 321, 304, 304, 321, 542,
+ 321, 304, 304, 501, 542, 501, 597, 144, 144, 144,
+ 144, 144, 144, 151, 151, 555, 151, 151, 151, 151,
+ 151, 304, 553, 151, 151, 1100, 597, 151, 307, 307,
+
+ 307, 307, 307, 307, 307, 307, 307, 307, 587, 554,
+ 585, 151, 151, 151, 152, 598, 304, 518, 152, 152,
+ 152, 518, 152, 598, 152, 152, 587, 593, 152, 301,
+ 301, 301, 301, 301, 585, 307, 301, 301, 554, 501,
+ 301, 593, 152, 152, 152, 518, 586, 325, 325, 588,
+ 325, 325, 586, 592, 301, 301, 301, 582, 596, 592,
+ 303, 303, 303, 303, 303, 588, 919, 303, 303, 152,
+ 173, 303, 596, 173, 173, 173, 173, 173, 582, 919,
+ 173, 173, 605, 606, 173, 303, 303, 303, 310, 310,
+ 310, 310, 310, 310, 310, 310, 310, 310, 173, 173,
+
+ 173, 175, 325, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 175, 175, 606, 605, 1099, 175, 175, 175,
+ 175, 175, 175, 311, 311, 311, 311, 311, 311, 311,
+ 311, 311, 311, 463, 463, 463, 463, 463, 463, 589,
+ 175, 569, 569, 175, 175, 175, 175, 175, 175, 184,
+ 601, 539, 184, 569, 609, 539, 692, 601, 184, 184,
+ 609, 589, 184, 184, 692, 184, 184, 184, 184, 184,
+ 184, 184, 184, 184, 184, 184, 184, 184, 184, 539,
+ 1091, 184, 184, 184, 184, 184, 184, 184, 184, 184,
+ 184, 184, 184, 184, 184, 184, 184, 184, 184, 184,
+
+ 184, 184, 184, 184, 184, 184, 184, 184, 184, 184,
+ 184, 184, 184, 184, 184, 184, 184, 184, 184, 184,
+ 184, 184, 184, 184, 184, 185, 185, 185, 185, 185,
+ 185, 185, 185, 185, 185, 185, 1060, 659, 1060, 185,
+ 185, 185, 185, 185, 185, 334, 334, 334, 334, 334,
+ 334, 334, 334, 334, 334, 335, 335, 335, 335, 335,
+ 335, 335, 335, 335, 335, 185, 185, 185, 185, 185,
+ 185, 207, 659, 701, 521, 207, 207, 207, 521, 207,
+ 387, 207, 207, 599, 387, 207, 451, 387, 451, 451,
+ 451, 451, 451, 451, 387, 595, 600, 701, 1090, 207,
+
+ 207, 207, 521, 607, 599, 600, 603, 515, 387, 387,
+ 394, 515, 394, 394, 394, 394, 394, 394, 394, 394,
+ 394, 394, 616, 521, 595, 451, 207, 231, 616, 603,
+ 231, 231, 231, 231, 231, 515, 607, 231, 231, 1082,
+ 395, 231, 395, 395, 395, 395, 395, 395, 395, 395,
+ 395, 395, 515, 660, 657, 231, 231, 231, 233, 660,
+ 656, 516, 233, 233, 233, 516, 233, 662, 233, 233,
+ 604, 396, 233, 396, 396, 396, 396, 396, 396, 396,
+ 396, 396, 396, 571, 571, 657, 233, 233, 233, 516,
+ 418, 855, 604, 656, 418, 571, 511, 418, 511, 511,
+
+ 511, 511, 511, 511, 418, 613, 662, 613, 516, 614,
+ 615, 689, 658, 233, 268, 671, 813, 268, 418, 418,
+ 813, 614, 615, 268, 268, 694, 671, 268, 689, 855,
+ 268, 268, 447, 447, 447, 447, 447, 447, 447, 447,
+ 447, 447, 743, 694, 268, 658, 268, 455, 455, 455,
+ 455, 455, 455, 455, 455, 455, 455, 455, 462, 462,
+ 462, 462, 462, 462, 462, 462, 462, 462, 688, 447,
+ 268, 268, 268, 271, 688, 697, 271, 675, 613, 271,
+ 271, 743, 271, 271, 271, 271, 271, 1081, 675, 271,
+ 271, 465, 697, 465, 465, 465, 465, 465, 465, 465,
+
+ 465, 465, 465, 271, 271, 271, 507, 507, 507, 507,
+ 507, 507, 507, 507, 507, 507, 509, 702, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 509, 693, 271,
+ 271, 271, 274, 702, 274, 274, 274, 274, 274, 274,
+ 274, 274, 274, 274, 274, 695, 1080, 693, 274, 274,
+ 274, 274, 274, 274, 510, 699, 510, 510, 510, 510,
+ 510, 510, 510, 510, 510, 510, 695, 699, 1209, 543,
+ 676, 676, 699, 543, 274, 274, 274, 274, 274, 274,
+ 279, 704, 676, 1209, 279, 279, 279, 279, 279, 279,
+ 279, 279, 279, 279, 279, 279, 279, 543, 704, 279,
+
+ 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
+ 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
+ 279, 279, 800, 800, 279, 279, 279, 279, 279, 279,
+ 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
+ 279, 279, 280, 280, 280, 280, 280, 280, 280, 280,
+ 280, 280, 280, 677, 677, 698, 280, 280, 280, 280,
+ 280, 280, 522, 703, 808, 677, 522, 808, 519, 520,
+ 712, 703, 519, 520, 698, 523, 1078, 679, 679, 523,
+ 707, 712, 280, 280, 280, 280, 280, 280, 306, 679,
+ 522, 306, 306, 306, 306, 306, 519, 520, 306, 306,
+
+ 522, 707, 306, 523, 519, 524, 525, 731, 754, 524,
+ 525, 520, 731, 754, 717, 523, 306, 306, 306, 308,
+ 1074, 308, 308, 308, 308, 308, 308, 308, 308, 308,
+ 308, 308, 717, 524, 525, 308, 308, 308, 308, 308,
+ 308, 716, 812, 583, 590, 526, 622, 583, 590, 526,
+ 622, 806, 716, 524, 812, 525, 806, 718, 308, 803,
+ 803, 308, 308, 308, 308, 308, 308, 313, 718, 1052,
+ 313, 583, 590, 526, 622, 796, 313, 313, 932, 932,
+ 313, 313, 796, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 526, 622, 313,
+
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 313, 313, 313, 313, 313, 313, 313,
+ 313, 313, 313, 314, 314, 314, 314, 314, 314, 314,
+ 314, 314, 314, 314, 764, 782, 891, 314, 314, 314,
+ 314, 314, 314, 527, 891, 764, 782, 527, 532, 532,
+ 532, 532, 532, 532, 532, 532, 532, 532, 691, 715,
+ 821, 715, 691, 314, 314, 314, 314, 314, 314, 326,
+ 783, 527, 835, 326, 326, 326, 834, 326, 821, 326,
+
+ 326, 783, 834, 326, 835, 532, 691, 527, 1046, 574,
+ 574, 574, 574, 574, 574, 574, 574, 326, 326, 326,
+ 536, 574, 536, 536, 536, 536, 536, 536, 562, 562,
+ 562, 562, 562, 562, 562, 562, 562, 562, 562, 715,
+ 809, 826, 1029, 809, 326, 336, 838, 336, 336, 336,
+ 336, 336, 336, 336, 336, 336, 336, 838, 826, 536,
+ 568, 568, 568, 568, 568, 568, 568, 568, 568, 568,
+ 570, 570, 570, 570, 570, 570, 570, 570, 570, 570,
+ 825, 839, 1028, 825, 336, 337, 839, 337, 337, 337,
+ 337, 337, 337, 337, 337, 337, 337, 576, 576, 576,
+
+ 576, 576, 576, 576, 576, 576, 576, 577, 577, 577,
+ 577, 577, 577, 661, 661, 661, 661, 661, 661, 661,
+ 661, 661, 661, 1024, 337, 338, 848, 338, 338, 338,
+ 338, 338, 338, 338, 338, 338, 338, 579, 848, 579,
+ 579, 579, 579, 579, 579, 579, 579, 579, 579, 617,
+ 661, 617, 617, 617, 617, 617, 617, 617, 617, 617,
+ 617, 824, 926, 824, 338, 339, 339, 339, 339, 339,
+ 339, 339, 339, 339, 339, 339, 969, 969, 1013, 339,
+ 339, 339, 339, 339, 339, 618, 862, 618, 618, 618,
+ 618, 618, 618, 618, 618, 618, 618, 801, 862, 845,
+
+ 926, 1006, 339, 845, 801, 339, 339, 339, 339, 339,
+ 339, 342, 342, 342, 342, 342, 342, 342, 342, 342,
+ 342, 342, 824, 1005, 896, 342, 342, 342, 342, 342,
+ 342, 619, 827, 619, 619, 619, 619, 619, 619, 619,
+ 619, 619, 619, 628, 850, 896, 1003, 628, 850, 902,
+ 827, 342, 342, 342, 342, 342, 342, 344, 344, 344,
+ 344, 344, 344, 344, 344, 344, 344, 344, 344, 994,
+ 902, 628, 344, 344, 344, 344, 344, 344, 623, 628,
+ 632, 626, 623, 634, 632, 626, 672, 634, 672, 672,
+ 672, 672, 672, 672, 672, 672, 672, 672, 344, 344,
+
+ 344, 344, 344, 344, 346, 852, 623, 346, 632, 626,
+ 852, 634, 623, 346, 346, 626, 632, 346, 346, 1048,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 634, 1048, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 347, 347, 347, 347, 347, 347, 347, 347, 347, 347,
+ 347, 784, 784, 990, 347, 347, 347, 347, 347, 347,
+
+ 627, 629, 847, 784, 627, 629, 864, 630, 847, 935,
+ 633, 630, 935, 631, 633, 696, 851, 631, 864, 696,
+ 347, 347, 347, 347, 347, 347, 371, 851, 627, 629,
+ 371, 371, 371, 853, 371, 630, 371, 371, 633, 876,
+ 371, 631, 627, 696, 893, 633, 877, 785, 785, 630,
+ 876, 853, 893, 989, 371, 371, 371, 877, 629, 785,
+ 665, 631, 665, 665, 665, 665, 665, 665, 673, 897,
+ 673, 673, 673, 673, 673, 673, 673, 673, 673, 673,
+ 897, 371, 372, 787, 787, 889, 372, 372, 372, 372,
+ 372, 889, 372, 372, 1004, 787, 372, 1004, 674, 665,
+
+ 674, 674, 674, 674, 674, 674, 674, 674, 674, 674,
+ 372, 372, 372, 678, 678, 678, 678, 678, 678, 678,
+ 678, 678, 678, 682, 682, 682, 682, 682, 682, 682,
+ 682, 962, 894, 878, 878, 682, 700, 372, 390, 894,
+ 700, 892, 390, 390, 390, 878, 390, 892, 390, 390,
+ 934, 1018, 390, 684, 684, 684, 684, 684, 684, 684,
+ 684, 684, 684, 934, 700, 966, 390, 390, 390, 685,
+ 685, 685, 685, 685, 685, 687, 966, 687, 687, 687,
+ 687, 687, 687, 687, 687, 687, 687, 705, 706, 898,
+ 1018, 705, 706, 390, 391, 970, 970, 898, 391, 391,
+
+ 391, 391, 391, 907, 391, 391, 949, 723, 391, 723,
+ 723, 723, 723, 723, 723, 705, 706, 993, 949, 993,
+ 907, 948, 391, 391, 391, 719, 719, 719, 719, 719,
+ 719, 719, 719, 719, 719, 721, 950, 721, 721, 721,
+ 721, 721, 721, 721, 721, 721, 721, 944, 950, 391,
+ 397, 397, 397, 397, 397, 397, 397, 397, 397, 397,
+ 397, 1015, 1015, 1224, 397, 397, 397, 397, 397, 397,
+ 722, 952, 722, 722, 722, 722, 722, 722, 722, 722,
+ 722, 722, 993, 952, 1224, 724, 879, 879, 967, 724,
+ 397, 397, 397, 397, 397, 397, 399, 1186, 879, 967,
+
+ 399, 399, 399, 399, 399, 399, 399, 399, 399, 399,
+ 399, 399, 399, 724, 1186, 399, 399, 399, 399, 399,
+ 399, 399, 399, 399, 399, 399, 399, 399, 399, 399,
+ 399, 399, 399, 399, 399, 399, 399, 399, 1047, 1047,
+ 399, 399, 399, 399, 399, 399, 399, 399, 399, 399,
+ 399, 399, 399, 399, 399, 399, 399, 399, 400, 400,
+ 400, 400, 400, 400, 400, 400, 400, 400, 400, 1063,
+ 939, 1063, 400, 400, 400, 400, 400, 400, 771, 771,
+ 771, 771, 771, 771, 771, 771, 771, 771, 725, 728,
+ 729, 730, 725, 728, 729, 730, 977, 936, 400, 400,
+
+ 400, 400, 400, 400, 419, 977, 419, 419, 419, 419,
+ 419, 419, 419, 419, 419, 419, 725, 728, 729, 730,
+ 974, 931, 992, 992, 725, 992, 992, 1022, 732, 733,
+ 734, 974, 732, 733, 734, 729, 735, 736, 730, 1014,
+ 735, 736, 1014, 419, 420, 921, 420, 420, 420, 420,
+ 420, 420, 420, 420, 420, 420, 732, 733, 734, 881,
+ 881, 979, 920, 983, 735, 736, 1022, 917, 747, 979,
+ 983, 881, 747, 746, 734, 746, 746, 746, 746, 746,
+ 746, 733, 1016, 420, 421, 1016, 421, 421, 421, 421,
+ 421, 421, 421, 421, 421, 421, 747, 1092, 1092, 742,
+
+ 742, 742, 742, 742, 742, 742, 742, 742, 742, 751,
+ 755, 758, 746, 751, 755, 758, 916, 1056, 759, 1189,
+ 911, 1189, 759, 421, 422, 1056, 422, 422, 422, 422,
+ 422, 422, 422, 422, 422, 422, 742, 751, 755, 758,
+ 422, 422, 422, 422, 422, 422, 759, 773, 773, 773,
+ 773, 773, 773, 773, 773, 773, 773, 774, 774, 774,
+ 774, 774, 774, 1158, 909, 905, 422, 422, 422, 422,
+ 422, 422, 424, 424, 424, 424, 424, 424, 424, 424,
+ 424, 424, 975, 1158, 904, 903, 424, 424, 424, 424,
+ 424, 424, 776, 975, 776, 776, 776, 776, 776, 776,
+
+ 776, 776, 776, 776, 781, 1084, 781, 781, 781, 781,
+ 781, 781, 424, 424, 424, 424, 424, 424, 440, 968,
+ 968, 901, 440, 440, 440, 1192, 440, 1192, 440, 440,
+ 860, 968, 440, 777, 777, 777, 777, 777, 777, 777,
+ 777, 777, 777, 859, 1084, 846, 440, 440, 440, 779,
+ 1030, 779, 779, 779, 779, 779, 779, 779, 779, 779,
+ 779, 780, 1030, 780, 780, 780, 780, 780, 780, 780,
+ 780, 780, 780, 440, 441, 982, 984, 1365, 441, 441,
+ 441, 441, 441, 1365, 441, 441, 982, 984, 441, 786,
+ 786, 786, 786, 786, 786, 786, 786, 786, 786, 840,
+
+ 837, 1031, 441, 441, 441, 790, 790, 790, 790, 790,
+ 790, 790, 790, 1031, 836, 833, 1033, 790, 792, 792,
+ 792, 792, 792, 792, 792, 792, 792, 792, 1033, 441,
+ 449, 832, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 793, 793, 793, 793, 793, 793, 795, 823,
+ 795, 795, 795, 795, 795, 795, 795, 795, 795, 795,
+ 798, 804, 810, 816, 798, 804, 810, 816, 1088, 449,
+ 450, 991, 450, 450, 450, 450, 450, 450, 450, 450,
+ 450, 450, 870, 870, 870, 870, 870, 870, 798, 804,
+ 810, 816, 822, 820, 991, 818, 991, 991, 1049, 818,
+
+ 887, 887, 887, 887, 887, 887, 815, 1088, 1049, 450,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 818, 814, 778, 461, 461, 461, 461,
+ 461, 461, 828, 828, 828, 828, 828, 828, 828, 828,
+ 828, 828, 828, 918, 1058, 906, 906, 918, 906, 906,
+ 770, 1058, 461, 461, 461, 461, 461, 461, 464, 464,
+ 464, 464, 464, 464, 464, 464, 464, 464, 464, 464,
+ 908, 918, 769, 464, 464, 464, 464, 464, 464, 829,
+ 829, 829, 829, 829, 829, 829, 829, 829, 829, 829,
+ 768, 763, 918, 908, 762, 908, 908, 1141, 1045, 464,
+
+ 464, 464, 464, 464, 464, 467, 906, 980, 467, 1045,
+ 761, 980, 760, 757, 467, 467, 756, 753, 467, 467,
+ 908, 467, 467, 467, 467, 467, 467, 467, 467, 467,
+ 467, 467, 467, 467, 467, 980, 1141, 467, 467, 467,
+ 467, 467, 467, 467, 467, 467, 467, 467, 467, 467,
+ 467, 467, 467, 467, 467, 467, 467, 467, 467, 467,
+ 467, 467, 467, 467, 467, 467, 467, 467, 467, 467,
+ 467, 467, 467, 467, 467, 467, 467, 467, 467, 467,
+ 467, 512, 512, 512, 512, 512, 512, 512, 512, 512,
+ 512, 512, 1260, 1260, 1260, 512, 512, 512, 512, 512,
+
+ 512, 830, 830, 830, 830, 830, 830, 830, 830, 830,
+ 830, 830, 914, 914, 914, 914, 914, 914, 914, 752,
+ 1057, 512, 512, 512, 512, 512, 512, 513, 1057, 750,
+ 1172, 513, 513, 513, 513, 513, 513, 513, 513, 513,
+ 513, 513, 513, 513, 749, 748, 513, 513, 513, 513,
+ 513, 513, 513, 513, 513, 513, 513, 513, 513, 513,
+ 513, 513, 513, 513, 513, 513, 513, 513, 513, 1172,
+ 741, 513, 513, 513, 513, 513, 513, 513, 513, 513,
+ 513, 513, 513, 513, 513, 513, 513, 513, 513, 514,
+ 1200, 1217, 1101, 514, 854, 854, 854, 854, 854, 854,
+
+ 854, 854, 854, 854, 1101, 727, 1102, 514, 514, 514,
+ 514, 514, 514, 514, 514, 514, 514, 514, 1102, 1123,
+ 726, 514, 514, 514, 514, 514, 514, 1123, 720, 1200,
+ 1217, 854, 858, 858, 858, 858, 858, 858, 858, 958,
+ 958, 958, 958, 958, 958, 714, 713, 514, 514, 514,
+ 514, 514, 514, 534, 711, 534, 534, 534, 534, 534,
+ 534, 534, 534, 534, 534, 1061, 1061, 710, 1061, 1061,
+ 858, 861, 861, 861, 861, 861, 861, 861, 861, 861,
+ 861, 863, 863, 863, 863, 863, 863, 863, 863, 863,
+ 863, 709, 534, 535, 1104, 535, 535, 535, 535, 535,
+
+ 535, 535, 535, 535, 535, 867, 1104, 867, 867, 867,
+ 867, 867, 867, 1292, 1292, 1292, 1118, 867, 869, 869,
+ 869, 869, 869, 869, 869, 869, 869, 869, 1118, 708,
+ 985, 690, 535, 557, 985, 557, 557, 557, 557, 557,
+ 557, 557, 557, 557, 557, 872, 669, 872, 872, 872,
+ 872, 872, 872, 872, 872, 872, 872, 873, 985, 873,
+ 873, 873, 873, 873, 873, 873, 873, 873, 873, 668,
+ 987, 667, 557, 558, 987, 558, 558, 558, 558, 558,
+ 558, 558, 558, 558, 558, 874, 666, 874, 874, 874,
+ 874, 874, 874, 874, 874, 874, 874, 875, 987, 875,
+
+ 875, 875, 875, 875, 875, 875, 875, 875, 875, 655,
+ 654, 653, 558, 559, 652, 559, 559, 559, 559, 559,
+ 559, 559, 559, 559, 559, 880, 880, 880, 880, 880,
+ 880, 880, 880, 880, 880, 884, 884, 884, 884, 884,
+ 884, 884, 884, 651, 1064, 650, 1064, 884, 1157, 1157,
+ 1157, 1157, 559, 572, 572, 572, 572, 572, 572, 572,
+ 572, 572, 572, 572, 572, 572, 649, 648, 647, 572,
+ 572, 572, 572, 572, 572, 886, 886, 886, 886, 886,
+ 886, 886, 886, 886, 886, 910, 910, 910, 910, 910,
+ 910, 910, 910, 910, 910, 572, 572, 572, 572, 572,
+
+ 572, 575, 575, 575, 575, 575, 575, 575, 575, 575,
+ 575, 575, 575, 575, 1064, 646, 645, 575, 575, 575,
+ 575, 575, 575, 888, 644, 888, 888, 888, 888, 888,
+ 888, 888, 888, 888, 888, 929, 929, 929, 929, 929,
+ 929, 929, 643, 575, 575, 575, 575, 575, 575, 578,
+ 578, 578, 578, 578, 578, 578, 578, 578, 578, 578,
+ 578, 639, 638, 637, 578, 578, 578, 578, 578, 578,
+ 636, 635, 965, 929, 965, 965, 965, 965, 965, 965,
+ 895, 625, 1125, 1125, 895, 1125, 1125, 624, 621, 620,
+ 578, 578, 578, 578, 578, 578, 640, 612, 640, 640,
+
+ 640, 640, 640, 640, 640, 640, 640, 640, 895, 912,
+ 912, 912, 912, 912, 912, 912, 912, 912, 912, 912,
+ 899, 611, 610, 945, 899, 945, 945, 945, 945, 945,
+ 945, 945, 945, 945, 945, 640, 641, 895, 641, 641,
+ 641, 641, 641, 641, 641, 641, 641, 641, 899, 913,
+ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
+ 900, 922, 923, 602, 900, 922, 923, 973, 973, 973,
+ 973, 973, 973, 973, 973, 641, 642, 899, 642, 642,
+ 642, 642, 642, 642, 642, 642, 642, 642, 900, 922,
+ 923, 925, 925, 925, 925, 925, 925, 925, 925, 925,
+
+ 925, 933, 937, 938, 566, 933, 937, 938, 1253, 1253,
+ 922, 923, 565, 564, 1253, 642, 663, 900, 663, 663,
+ 663, 663, 663, 663, 663, 663, 663, 663, 925, 933,
+ 937, 938, 946, 563, 946, 946, 946, 946, 946, 946,
+ 946, 946, 946, 946, 1039, 1039, 1039, 1039, 1039, 1039,
+ 933, 937, 938, 561, 560, 663, 664, 1152, 664, 664,
+ 664, 664, 664, 664, 664, 664, 664, 664, 947, 1152,
+ 947, 947, 947, 947, 947, 947, 947, 947, 947, 947,
+ 951, 951, 951, 951, 951, 951, 951, 951, 951, 951,
+ 1164, 1164, 552, 1164, 1164, 664, 670, 670, 670, 670,
+
+ 670, 670, 670, 670, 670, 670, 670, 551, 550, 549,
+ 670, 670, 670, 670, 670, 670, 955, 548, 955, 955,
+ 955, 955, 955, 955, 1281, 1281, 547, 1002, 955, 1050,
+ 1281, 1002, 546, 1050, 545, 544, 670, 670, 670, 670,
+ 670, 670, 680, 680, 680, 680, 680, 680, 680, 680,
+ 680, 680, 680, 680, 680, 1002, 541, 1050, 680, 680,
+ 680, 680, 680, 680, 957, 957, 957, 957, 957, 957,
+ 957, 957, 957, 957, 961, 961, 961, 961, 961, 961,
+ 961, 961, 961, 961, 680, 680, 680, 680, 680, 680,
+ 683, 683, 683, 683, 683, 683, 683, 683, 683, 683,
+
+ 683, 683, 683, 540, 538, 531, 683, 683, 683, 683,
+ 683, 683, 960, 530, 960, 960, 960, 960, 960, 960,
+ 960, 960, 960, 960, 1001, 529, 1190, 1190, 1001, 1190,
+ 1190, 508, 683, 683, 683, 683, 683, 683, 686, 686,
+ 686, 686, 686, 686, 686, 686, 686, 686, 686, 686,
+ 500, 499, 1001, 686, 686, 686, 686, 686, 686, 963,
+ 498, 963, 963, 963, 963, 963, 963, 963, 963, 963,
+ 963, 1282, 1282, 1001, 497, 496, 495, 1282, 490, 686,
+ 686, 686, 686, 686, 686, 744, 487, 744, 744, 744,
+ 744, 744, 744, 744, 744, 744, 744, 964, 458, 964,
+
+ 964, 964, 964, 964, 964, 964, 964, 964, 964, 457,
+ 1053, 1079, 1011, 454, 1053, 1079, 1011, 1119, 453, 976,
+ 439, 1119, 978, 976, 744, 745, 978, 745, 745, 745,
+ 745, 745, 745, 745, 745, 745, 745, 995, 1053, 1079,
+ 1011, 995, 995, 995, 995, 1119, 438, 976, 437, 997,
+ 978, 997, 997, 997, 997, 997, 997, 997, 997, 997,
+ 997, 1011, 436, 435, 745, 765, 765, 765, 765, 765,
+ 765, 765, 765, 765, 765, 765, 976, 996, 434, 978,
+ 433, 996, 996, 996, 996, 1110, 1110, 1110, 1110, 1110,
+ 1110, 998, 995, 998, 998, 998, 998, 998, 998, 998,
+
+ 998, 998, 998, 765, 766, 766, 766, 766, 766, 766,
+ 766, 766, 766, 766, 766, 999, 432, 999, 999, 999,
+ 999, 999, 999, 999, 999, 999, 999, 1012, 1310, 1310,
+ 431, 1012, 996, 1021, 1310, 1021, 1021, 1021, 1021, 1021,
+ 1021, 430, 766, 767, 767, 767, 767, 767, 767, 767,
+ 767, 767, 767, 767, 1000, 1012, 1000, 1000, 1000, 1000,
+ 1000, 1000, 1000, 1000, 1000, 1000, 429, 1132, 428, 1159,
+ 427, 1132, 1021, 1159, 1299, 1323, 1012, 1299, 1323, 1299,
+ 1323, 767, 772, 426, 772, 772, 772, 772, 772, 772,
+ 772, 772, 772, 772, 772, 1132, 423, 1159, 772, 772,
+
+ 772, 772, 772, 772, 1017, 1017, 1017, 1017, 1017, 1017,
+ 1017, 1017, 1017, 1017, 1023, 1023, 1023, 1023, 1023, 1023,
+ 1023, 1023, 1023, 1023, 772, 772, 772, 772, 772, 772,
+ 775, 775, 775, 775, 775, 775, 775, 775, 775, 775,
+ 775, 1017, 417, 414, 775, 775, 775, 775, 775, 775,
+ 1025, 413, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025,
+ 1025, 1025, 1027, 412, 1027, 1027, 1027, 1027, 1027, 1027,
+ 775, 775, 775, 775, 775, 775, 788, 788, 788, 788,
+ 788, 788, 788, 788, 788, 788, 788, 788, 788, 411,
+ 410, 409, 788, 788, 788, 788, 788, 788, 1026, 408,
+
+ 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026,
+ 1077, 407, 1077, 1077, 1077, 1077, 1077, 1077, 788, 788,
+ 788, 788, 788, 788, 791, 791, 791, 791, 791, 791,
+ 791, 791, 791, 791, 791, 791, 791, 406, 405, 404,
+ 791, 791, 791, 791, 791, 791, 1032, 1032, 1032, 1032,
+ 1032, 1032, 1032, 1032, 1032, 1032, 1038, 1038, 1038, 1038,
+ 1038, 1038, 1038, 1038, 1038, 1038, 791, 791, 791, 791,
+ 791, 791, 794, 794, 794, 794, 794, 794, 794, 794,
+ 794, 794, 794, 403, 402, 401, 398, 794, 794, 794,
+ 794, 794, 794, 1036, 383, 1036, 1036, 1036, 1036, 1036,
+
+ 1036, 379, 378, 377, 376, 1036, 1115, 1115, 1115, 1115,
+ 1115, 1115, 1115, 794, 794, 794, 794, 794, 794, 797,
+ 1070, 1339, 797, 1070, 1339, 370, 1339, 369, 797, 797,
+ 1070, 1070, 797, 797, 1070, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 797, 797, 797, 1070, 1070,
+ 1070, 797, 797, 797, 797, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 831, 368, 367, 366, 831,
+
+ 831, 831, 831, 831, 831, 831, 831, 831, 831, 831,
+ 365, 831, 363, 362, 831, 831, 831, 831, 831, 831,
+ 831, 831, 831, 831, 831, 831, 831, 831, 831, 831,
+ 831, 831, 831, 831, 831, 831, 831, 361, 360, 831,
+ 831, 831, 831, 831, 831, 831, 831, 831, 831, 831,
+ 831, 831, 831, 831, 831, 831, 831, 841, 841, 841,
+ 841, 841, 841, 841, 841, 841, 841, 841, 1041, 359,
+ 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041, 1041,
+ 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042, 1042,
+ 1042, 358, 357, 356, 355, 841, 842, 842, 842, 842,
+
+ 842, 842, 842, 842, 842, 842, 842, 1043, 1043, 1043,
+ 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1043, 1044, 1044,
+ 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1055,
+ 354, 353, 352, 1055, 842, 843, 843, 843, 843, 843,
+ 843, 843, 843, 843, 843, 843, 351, 1121, 1065, 349,
+ 348, 1121, 1065, 1065, 1065, 1065, 1069, 1055, 341, 1069,
+ 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 1069, 340,
+ 1316, 1316, 327, 843, 844, 1121, 1316, 844, 323, 1317,
+ 1317, 322, 320, 844, 844, 1317, 1055, 844, 844, 319,
+ 844, 844, 844, 844, 844, 844, 844, 844, 844, 844,
+
+ 844, 844, 844, 1065, 1121, 318, 844, 844, 844, 844,
+ 844, 844, 844, 844, 844, 844, 844, 844, 844, 844,
+ 844, 844, 844, 844, 844, 844, 844, 844, 844, 844,
+ 844, 844, 844, 844, 844, 844, 844, 844, 844, 844,
+ 844, 844, 844, 844, 844, 844, 844, 844, 844, 844,
+ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856,
+ 856, 1066, 317, 1359, 1359, 1066, 1066, 1066, 1066, 1067,
+ 1359, 316, 315, 1067, 1067, 1067, 1067, 1073, 1073, 1073,
+ 1073, 1073, 1073, 1073, 1073, 1073, 1073, 309, 856, 857,
+ 857, 857, 857, 857, 857, 857, 857, 857, 857, 857,
+
+ 1068, 1363, 305, 1363, 1068, 1068, 1068, 1068, 1071, 1363,
+ 302, 300, 1071, 1071, 1071, 1071, 1066, 1207, 1207, 1207,
+ 1207, 1207, 1207, 298, 1067, 295, 294, 857, 865, 293,
+ 865, 865, 865, 865, 865, 865, 865, 865, 865, 865,
+ 865, 868, 290, 868, 868, 868, 868, 868, 868, 868,
+ 868, 868, 868, 868, 289, 1068, 287, 868, 868, 868,
+ 868, 868, 868, 1071, 1075, 286, 1075, 1075, 1075, 1075,
+ 1075, 1075, 1075, 1075, 1075, 1075, 1237, 1237, 1237, 1237,
+ 1237, 1237, 285, 868, 868, 868, 868, 868, 868, 871,
+ 871, 871, 871, 871, 871, 871, 871, 871, 871, 871,
+
+ 284, 283, 281, 871, 871, 871, 871, 871, 871, 1076,
+ 275, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076, 1076,
+ 1076, 1089, 1161, 267, 263, 1089, 1161, 258, 257, 871,
+ 871, 871, 871, 871, 871, 882, 882, 882, 882, 882,
+ 882, 882, 882, 882, 882, 882, 882, 882, 255, 1089,
+ 1161, 882, 882, 882, 882, 882, 882, 251, 1083, 1083,
+ 1083, 1083, 1083, 1083, 1083, 1083, 1083, 1083, 246, 1087,
+ 1089, 1087, 1087, 1087, 1087, 1087, 1087, 882, 882, 882,
+ 882, 882, 882, 885, 885, 885, 885, 885, 885, 885,
+ 885, 885, 885, 885, 885, 1083, 241, 239, 235, 885,
+
+ 885, 885, 885, 885, 885, 1122, 230, 1072, 1087, 1122,
+ 1072, 1131, 218, 1318, 1318, 1131, 217, 1072, 1072, 1318,
+ 216, 1072, 215, 214, 209, 885, 885, 885, 885, 885,
+ 885, 890, 202, 1122, 890, 1072, 1072, 1072, 201, 1131,
+ 890, 890, 200, 199, 890, 890, 198, 890, 890, 890,
+ 890, 890, 890, 890, 890, 890, 890, 890, 890, 890,
+ 1131, 197, 1122, 890, 890, 890, 890, 890, 890, 890,
+ 890, 890, 890, 890, 890, 890, 890, 890, 890, 890,
+ 890, 890, 890, 890, 890, 890, 890, 890, 890, 890,
+ 890, 890, 890, 890, 890, 890, 890, 890, 890, 890,
+
+ 890, 890, 890, 890, 890, 890, 890, 915, 195, 194,
+ 193, 915, 915, 915, 915, 915, 915, 915, 915, 915,
+ 915, 915, 192, 915, 191, 190, 915, 915, 915, 915,
+ 915, 915, 915, 915, 915, 915, 915, 915, 915, 915,
+ 915, 915, 915, 915, 915, 915, 915, 915, 915, 189,
+ 188, 915, 915, 915, 915, 915, 915, 915, 915, 915,
+ 915, 915, 915, 915, 915, 915, 915, 915, 915, 927,
+ 927, 927, 927, 927, 927, 927, 927, 927, 927, 927,
+ 1096, 187, 1096, 1096, 1096, 1096, 1096, 1096, 1096, 1096,
+ 1096, 1096, 1097, 186, 1097, 1097, 1097, 1097, 1097, 1097,
+
+ 1097, 1097, 1097, 1097, 181, 177, 176, 927, 928, 928,
+ 928, 928, 928, 928, 928, 928, 928, 928, 928, 1098,
+ 172, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098, 1098,
+ 1098, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103,
+ 1103, 169, 165, 162, 159, 155, 928, 930, 1170, 1187,
+ 930, 150, 1170, 1187, 149, 148, 930, 930, 147, 146,
+ 930, 930, 145, 930, 930, 930, 930, 930, 930, 930,
+ 930, 930, 930, 930, 930, 930, 1170, 1187, 141, 930,
+ 930, 930, 930, 930, 930, 930, 930, 930, 930, 930,
+ 930, 930, 930, 930, 930, 930, 930, 930, 930, 930,
+
+ 930, 930, 930, 930, 930, 930, 930, 930, 930, 930,
+ 930, 930, 930, 930, 930, 930, 930, 930, 930, 930,
+ 930, 930, 930, 940, 135, 940, 940, 940, 940, 940,
+ 940, 940, 940, 940, 940, 1107, 133, 1107, 1107, 1107,
+ 1107, 1107, 1107, 129, 124, 123, 122, 1107, 1109, 1109,
+ 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1324, 1324,
+ 121, 120, 940, 941, 1324, 941, 941, 941, 941, 941,
+ 941, 941, 941, 941, 941, 1111, 119, 1111, 1111, 1111,
+ 1111, 1111, 1111, 1111, 1111, 1111, 1111, 1113, 1113, 1113,
+ 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1113, 1325, 1325,
+
+ 115, 102, 941, 942, 1325, 942, 942, 942, 942, 942,
+ 942, 942, 942, 942, 942, 1114, 1114, 1114, 1114, 1114,
+ 1114, 1114, 1114, 1114, 1114, 1114, 1126, 1126, 1126, 1126,
+ 1126, 1126, 1126, 1126, 1126, 1126, 95, 88, 1326, 1326,
+ 87, 80, 942, 943, 1326, 943, 943, 943, 943, 943,
+ 943, 943, 943, 943, 943, 1127, 1127, 1127, 1127, 1127,
+ 1127, 1127, 1127, 1127, 1127, 1128, 79, 1128, 1128, 1128,
+ 1128, 1128, 1128, 1128, 1128, 1128, 1128, 74, 1329, 1329,
+ 73, 72, 943, 953, 1329, 953, 953, 953, 953, 953,
+ 953, 953, 953, 953, 953, 953, 956, 71, 956, 956,
+
+ 956, 956, 956, 956, 956, 956, 956, 956, 956, 66,
+ 64, 54, 956, 956, 956, 956, 956, 956, 1129, 53,
+ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129,
+ 1149, 51, 1149, 1149, 1149, 1149, 1149, 1149, 956, 956,
+ 956, 956, 956, 956, 959, 959, 959, 959, 959, 959,
+ 959, 959, 959, 959, 959, 50, 48, 38, 959, 959,
+ 959, 959, 959, 959, 1130, 32, 1130, 1130, 1130, 1130,
+ 1130, 1130, 1130, 1130, 1130, 1130, 1169, 26, 1169, 1169,
+ 1169, 1169, 1169, 1169, 959, 959, 959, 959, 959, 959,
+ 971, 971, 971, 971, 971, 971, 971, 971, 971, 971,
+
+ 971, 971, 1007, 25, 1007, 1007, 1007, 1007, 1007, 1007,
+ 1007, 1007, 1007, 1007, 22, 1137, 21, 0, 1144, 1137,
+ 1144, 1144, 1144, 1144, 1144, 1144, 1138, 0, 0, 0,
+ 1138, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140, 1140,
+ 1140, 1007, 1008, 1137, 1008, 1008, 1008, 1008, 1008, 1008,
+ 1008, 1008, 1008, 1008, 1138, 0, 1215, 1144, 1215, 1215,
+ 1215, 1215, 1215, 1215, 1137, 1330, 1330, 0, 1140, 0,
+ 0, 1330, 1331, 1331, 1347, 1138, 0, 1347, 1331, 1347,
+ 0, 1008, 1009, 0, 1009, 1009, 1009, 1009, 1009, 1009,
+ 1009, 1009, 1009, 1009, 1145, 1145, 1145, 1145, 1145, 1145,
+
+ 1145, 1145, 1145, 1145, 1147, 0, 1147, 1147, 1147, 1147,
+ 1147, 1147, 1147, 1147, 1147, 1147, 0, 0, 0, 1163,
+ 0, 1009, 1010, 1163, 1010, 1010, 1010, 1010, 1010, 1010,
+ 1010, 1010, 1010, 1010, 1148, 0, 1148, 1148, 1148, 1148,
+ 1148, 1148, 1148, 1148, 1148, 1148, 1155, 1163, 1155, 1155,
+ 1155, 1155, 1155, 1155, 1155, 1155, 1155, 1155, 0, 0,
+ 0, 1010, 1019, 0, 1019, 1019, 1019, 1019, 1019, 1019,
+ 1019, 1019, 1019, 1019, 0, 0, 1163, 1165, 1165, 1165,
+ 1165, 1165, 1165, 1165, 1165, 1165, 1165, 1167, 0, 1167,
+ 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 1167, 0,
+
+ 0, 1019, 1020, 0, 1020, 1020, 1020, 1020, 1020, 1020,
+ 1020, 1020, 1020, 1020, 1168, 0, 1168, 1168, 1168, 1168,
+ 1168, 1168, 1168, 1168, 1168, 1168, 0, 0, 0, 0,
+ 0, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
+ 1171, 1020, 1034, 0, 1034, 1034, 1034, 1034, 1034, 1034,
+ 1034, 1034, 1034, 1034, 1034, 1037, 0, 1037, 1037, 1037,
+ 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1037, 1171, 0,
+ 0, 1037, 1037, 1037, 1037, 1037, 1037, 1175, 0, 1175,
+ 1175, 1175, 1175, 1175, 1175, 1176, 1334, 1334, 0, 1176,
+ 1335, 1335, 1334, 0, 0, 0, 1335, 1037, 1037, 1037,
+
+ 1037, 1037, 1037, 1040, 1040, 1040, 1040, 1040, 1040, 1040,
+ 1040, 1040, 1040, 1176, 0, 0, 1175, 1040, 1040, 1040,
+ 1040, 1040, 1040, 1180, 1180, 1180, 1180, 1180, 1180, 1180,
+ 1180, 1180, 1180, 0, 1176, 1342, 1342, 0, 0, 0,
+ 0, 1342, 0, 1040, 1040, 1040, 1040, 1040, 1040, 1085,
+ 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085,
+ 1085, 1181, 1181, 1181, 1181, 1181, 1181, 1181, 1181, 1181,
+ 1181, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182, 1182,
+ 1182, 1350, 1350, 0, 1357, 1357, 0, 1350, 1085, 1086,
+ 1357, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086,
+
+ 1086, 1193, 0, 1193, 1193, 1193, 1193, 1193, 1193, 1193,
+ 1193, 1193, 1193, 1194, 0, 1194, 1194, 1194, 1194, 1194,
+ 1194, 1194, 1194, 1194, 1194, 0, 0, 0, 1086, 1093,
+ 0, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+ 1093, 1195, 0, 1195, 1195, 1195, 1195, 1195, 1195, 1195,
+ 1195, 1195, 1195, 1199, 1199, 1199, 1199, 1199, 1199, 1199,
+ 1199, 1199, 1199, 0, 1360, 1360, 0, 0, 1093, 1094,
+ 1360, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094, 1094,
+ 1094, 0, 1203, 0, 1203, 1203, 1203, 1203, 1203, 1203,
+ 1199, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205,
+
+ 1205, 1362, 1362, 0, 0, 0, 0, 1362, 1094, 1095,
+ 0, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095, 1095,
+ 1095, 1203, 1206, 1206, 1206, 1206, 1206, 1206, 1206, 1206,
+ 1206, 1206, 1211, 1211, 1211, 1211, 1211, 1211, 1211, 1211,
+ 1211, 1211, 0, 0, 0, 0, 0, 0, 1095, 1105,
+ 0, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105,
+ 1105, 1105, 1108, 0, 1108, 1108, 1108, 1108, 1108, 1108,
+ 1108, 1108, 1108, 1108, 0, 0, 0, 0, 1108, 1108,
+ 1108, 1108, 1108, 1108, 1213, 0, 1213, 1213, 1213, 1213,
+ 1213, 1213, 1213, 1213, 1213, 1213, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 1108, 1108, 1108, 1108, 1108, 1108,
+ 1134, 0, 1134, 1134, 1134, 1134, 1134, 1134, 1134, 1134,
+ 1134, 1134, 1214, 0, 1214, 1214, 1214, 1214, 1214, 1214,
+ 1214, 1214, 1214, 1214, 1216, 1216, 1216, 1216, 1216, 1216,
+ 1216, 1216, 1216, 1216, 0, 0, 0, 0, 0, 1134,
+ 1135, 0, 1135, 1135, 1135, 1135, 1135, 1135, 1135, 1135,
+ 1135, 1135, 0, 1220, 0, 1220, 1220, 1220, 1220, 1220,
+ 1220, 1216, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221,
+ 1221, 1221, 0, 1233, 1233, 1233, 1233, 1233, 1233, 1135,
+ 1136, 0, 1136, 1136, 1136, 1136, 1136, 1136, 1136, 1136,
+
+ 1136, 1136, 1220, 0, 0, 0, 0, 0, 0, 1221,
+ 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222, 1222,
+ 1233, 0, 0, 0, 0, 0, 0, 0, 0, 1136,
+ 1142, 0, 1142, 1142, 1142, 1142, 1142, 1142, 1142, 1142,
+ 1142, 1142, 0, 0, 0, 0, 0, 1222, 1223, 1223,
+ 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1223, 1225, 1225,
+ 1225, 1225, 1225, 1225, 1225, 1225, 1225, 1225, 0, 1142,
+ 1143, 0, 1143, 1143, 1143, 1143, 1143, 1143, 1143, 1143,
+ 1143, 1143, 0, 0, 0, 1223, 1226, 1226, 1226, 1226,
+ 1226, 1226, 1226, 1226, 1226, 1226, 1227, 1227, 1227, 1227,
+
+ 1227, 1227, 1227, 1227, 1227, 1227, 0, 0, 0, 1143,
+ 1173, 0, 1173, 1173, 1173, 1173, 1173, 1173, 1173, 1173,
+ 1173, 1173, 0, 0, 0, 1228, 1228, 1228, 1228, 1228,
+ 1228, 1228, 1228, 1228, 1228, 1229, 1229, 1229, 1229, 1229,
+ 1229, 1229, 1229, 1229, 1229, 0, 0, 0, 0, 1173,
+ 1174, 0, 1174, 1174, 1174, 1174, 1174, 1174, 1174, 1174,
+ 1174, 1174, 1228, 0, 0, 1240, 1240, 1240, 1240, 1240,
+ 1240, 0, 1229, 1230, 1230, 1230, 1230, 1230, 1230, 1230,
+ 1230, 1230, 1230, 0, 0, 0, 0, 0, 0, 1174,
+ 1177, 0, 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177,
+
+ 1177, 1177, 1240, 0, 0, 0, 0, 0, 0, 0,
+ 1230, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232,
+ 1232, 0, 0, 0, 0, 0, 0, 0, 0, 1177,
+ 1178, 0, 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178,
+ 1178, 1178, 0, 0, 0, 0, 0, 0, 1232, 1236,
+ 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1236, 1239,
+ 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1178,
+ 1179, 0, 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179,
+ 1179, 1179, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1239, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1179,
+ 1196, 0, 1196, 1196, 1196, 1196, 1196, 1196, 1196, 1196,
+ 1196, 1196, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1196,
+ 1197, 0, 1197, 1197, 1197, 1197, 1197, 1197, 1197, 1197,
+ 1197, 1197, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1197,
+ 1198, 0, 1198, 1198, 1198, 1198, 1198, 1198, 1198, 1198,
+
+ 1198, 1198, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1198,
+ 1201, 0, 1201, 1201, 1201, 1201, 1201, 1201, 1201, 1201,
+ 1201, 1201, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1201,
+ 1202, 0, 1202, 1202, 1202, 1202, 1202, 1202, 1202, 1202,
+ 1202, 1202, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1202,
+ 1218, 0, 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1218,
+ 1218, 1218, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1218,
+ 1219, 0, 1219, 1219, 1219, 1219, 1219, 1219, 1219, 1219,
+ 1219, 1219, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1219,
+ 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242,
+
+ 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242,
+ 1242, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243,
+ 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243, 1243,
+ 1243, 1243, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244,
+ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244,
+ 1244, 1244, 1244, 1245, 1245, 1245, 1245, 1245, 1245, 1245,
+ 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245,
+ 1245, 1245, 1245, 1245, 1246, 1246, 1246, 1246, 1246, 1246,
+ 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246,
+ 1246, 1246, 1246, 1246, 1246, 1247, 1247, 1247, 1247, 1247,
+
+ 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247, 1247,
+ 1247, 1247, 1247, 1247, 1247, 1247, 1248, 0, 0, 1248,
+ 0, 0, 0, 1248, 0, 1248, 0, 1248, 1248, 1248,
+ 0, 0, 1248, 1248, 1248, 1248, 1248, 1249, 1249, 1249,
+ 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249,
+ 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1250, 0,
+ 0, 1250, 0, 0, 1250, 1250, 0, 1250, 0, 1250,
+ 1250, 1250, 1250, 0, 1250, 1250, 1250, 1250, 1250, 1251,
+ 0, 0, 1251, 0, 0, 0, 1251, 0, 1251, 0,
+ 1251, 1251, 1251, 0, 0, 1251, 1251, 1251, 1251, 1251,
+
+ 1252, 0, 0, 1252, 1252, 1252, 0, 1252, 1252, 1252,
+ 0, 1252, 1252, 1252, 0, 0, 1252, 1252, 1252, 1252,
+ 1252, 1254, 1254, 0, 1254, 1254, 1254, 0, 1254, 1254,
+ 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254, 1254,
+ 1254, 1254, 1255, 0, 0, 1255, 1255, 1255, 0, 1255,
+ 1255, 1255, 0, 1255, 1255, 1255, 0, 0, 1255, 1255,
+ 1255, 1255, 1255, 1256, 1256, 0, 1256, 1256, 1256, 0,
+ 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256, 1256,
+ 1256, 1256, 1256, 1256, 1257, 0, 0, 1257, 1257, 1257,
+ 0, 1257, 1257, 1257, 0, 1257, 1257, 1257, 0, 1257,
+
+ 1257, 0, 1257, 1257, 1257, 1258, 1258, 0, 1258, 1258,
+ 1258, 0, 0, 1258, 1258, 1258, 1258, 1258, 1258, 1258,
+ 1258, 1258, 0, 1258, 1258, 1258, 1259, 1259, 1259, 1259,
+ 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1259,
+ 1259, 1259, 1259, 1259, 1259, 1259, 1259, 1261, 0, 0,
+ 1261, 1261, 0, 0, 1261, 1261, 1261, 0, 1261, 1261,
+ 1261, 1261, 0, 1261, 1261, 1261, 1261, 1261, 1262, 1262,
+ 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262,
+ 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1262, 1263,
+ 1263, 0, 1263, 1263, 0, 1263, 1263, 1263, 1263, 1263,
+
+ 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
+ 1264, 0, 0, 1264, 0, 0, 1264, 1264, 0, 1264,
+ 0, 1264, 1264, 1264, 1264, 0, 1264, 1264, 1264, 1264,
+ 1264, 1265, 0, 0, 1265, 0, 0, 0, 1265, 0,
+ 1265, 0, 1265, 1265, 1265, 0, 1265, 1265, 1265, 1265,
+ 1265, 1265, 1266, 0, 0, 1266, 1266, 1266, 0, 1266,
+ 1266, 1266, 0, 1266, 1266, 1266, 0, 1266, 1266, 1266,
+ 1266, 1266, 1266, 1267, 1267, 0, 1267, 1267, 1267, 0,
+ 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
+ 1267, 1267, 1267, 1267, 1268, 0, 0, 0, 1268, 1268,
+
+ 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268, 1268,
+ 1268, 1268, 1268, 1268, 1268, 1269, 0, 0, 1269, 0,
+ 0, 0, 1269, 0, 1269, 0, 1269, 1269, 1269, 0,
+ 0, 1269, 1269, 1269, 1269, 1269, 1270, 0, 0, 1270,
+ 0, 0, 1270, 1270, 0, 1270, 0, 1270, 1270, 1270,
+ 1270, 0, 1270, 1270, 1270, 1270, 1270, 1271, 0, 0,
+ 1271, 0, 0, 0, 1271, 0, 1271, 0, 1271, 1271,
+ 1271, 0, 0, 1271, 1271, 1271, 1271, 1271, 1272, 0,
+ 0, 1272, 1272, 1272, 0, 1272, 1272, 1272, 0, 1272,
+ 1272, 1272, 0, 0, 1272, 1272, 1272, 1272, 1272, 1273,
+
+ 1273, 0, 1273, 1273, 1273, 0, 1273, 1273, 1273, 1273,
+ 1273, 1273, 1273, 1273, 1273, 1273, 1273, 1273, 1273, 1273,
+ 1274, 0, 0, 1274, 0, 0, 0, 1274, 0, 1274,
+ 0, 1274, 1274, 1274, 0, 0, 1274, 1274, 1274, 1274,
+ 1274, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
+ 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
+ 1275, 1275, 1276, 1276, 0, 1276, 1276, 1276, 1276, 1276,
+ 1276, 1276, 1276, 1276, 1276, 1276, 1276, 1276, 1276, 1276,
+ 1276, 1276, 1276, 1277, 0, 0, 1277, 0, 0, 0,
+ 1277, 0, 1277, 0, 1277, 1277, 1277, 0, 0, 1277,
+
+ 1277, 1277, 1277, 1277, 1278, 0, 0, 1278, 0, 0,
+ 0, 1278, 0, 1278, 0, 1278, 1278, 1278, 0, 0,
+ 1278, 1278, 1278, 1278, 1278, 1279, 0, 0, 1279, 1279,
+ 1279, 0, 1279, 1279, 1279, 0, 1279, 1279, 1279, 0,
+ 0, 1279, 1279, 1279, 1279, 1279, 1280, 0, 0, 1280,
+ 1280, 1280, 0, 1280, 1280, 1280, 0, 1280, 1280, 1280,
+ 0, 0, 1280, 1280, 1280, 1280, 1280, 1283, 1283, 1283,
+ 0, 0, 0, 0, 1283, 1284, 1284, 0, 1284, 1284,
+ 1284, 0, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284,
+ 1284, 1284, 1284, 1284, 1284, 1284, 1285, 1285, 0, 1285,
+
+ 1285, 1285, 0, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
+ 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1286, 0, 0,
+ 1286, 1286, 1286, 0, 1286, 1286, 1286, 0, 1286, 1286,
+ 1286, 0, 0, 1286, 1286, 1286, 1286, 1286, 1287, 0,
+ 0, 1287, 1287, 1287, 0, 1287, 1287, 1287, 0, 1287,
+ 1287, 1287, 0, 0, 1287, 1287, 1287, 1287, 1287, 1288,
+ 1288, 0, 1288, 1288, 1288, 0, 1288, 1288, 1288, 1288,
+ 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288, 1288,
+ 1289, 1289, 0, 1289, 1289, 1289, 0, 1289, 1289, 1289,
+ 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289, 1289,
+
+ 1289, 1290, 0, 0, 1290, 1290, 1290, 0, 1290, 1290,
+ 1290, 0, 1290, 1290, 1290, 0, 1290, 1290, 0, 1290,
+ 1290, 1290, 1291, 1291, 0, 1291, 1291, 1291, 0, 0,
+ 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 0,
+ 1291, 1291, 1291, 1293, 0, 0, 1293, 1293, 0, 0,
+ 1293, 1293, 1293, 0, 1293, 1293, 1293, 1293, 0, 1293,
+ 1293, 1293, 1293, 1293, 1294, 1294, 0, 1294, 1294, 0,
+ 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294, 1294,
+ 1294, 1294, 1294, 1294, 1294, 1295, 0, 0, 1295, 0,
+ 0, 0, 1295, 0, 1295, 0, 1295, 1295, 1295, 0,
+
+ 0, 1295, 1295, 1295, 1295, 1295, 1296, 0, 0, 1296,
+ 0, 0, 0, 1296, 0, 1296, 0, 1296, 1296, 1296,
+ 0, 1296, 1296, 1296, 1296, 1296, 1296, 1297, 0, 0,
+ 1297, 1297, 0, 1297, 1297, 0, 0, 1297, 1297, 1298,
+ 0, 0, 1298, 1298, 1298, 0, 1298, 1298, 1298, 0,
+ 1298, 1298, 1298, 0, 1298, 1298, 1298, 1298, 1298, 1298,
+ 1300, 0, 0, 0, 1300, 1300, 1300, 1300, 1300, 1300,
+ 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300, 1300,
+ 1300, 1301, 0, 0, 1301, 0, 0, 0, 1301, 0,
+ 1301, 0, 1301, 1301, 1301, 0, 0, 1301, 1301, 1301,
+
+ 1301, 1301, 1302, 0, 0, 1302, 0, 0, 0, 1302,
+ 0, 1302, 0, 1302, 1302, 1302, 0, 0, 1302, 1302,
+ 1302, 1302, 1302, 1303, 0, 0, 1303, 0, 0, 0,
+ 1303, 0, 1303, 0, 1303, 1303, 1303, 0, 0, 1303,
+ 1303, 1303, 1303, 1303, 1304, 0, 0, 1304, 1304, 1304,
+ 0, 1304, 1304, 1304, 0, 1304, 1304, 1304, 0, 0,
+ 1304, 1304, 1304, 1304, 1304, 1305, 0, 0, 1305, 1305,
+ 1305, 0, 1305, 1305, 1305, 0, 1305, 1305, 1305, 0,
+ 0, 1305, 1305, 1305, 1305, 1305, 1306, 1306, 0, 1306,
+ 1306, 1306, 0, 1306, 1306, 1306, 1306, 1306, 1306, 1306,
+
+ 1306, 1306, 1306, 1306, 1306, 1306, 1306, 1307, 1307, 1307,
+ 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
+ 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1308, 1308,
+ 1308, 1308, 1308, 1308, 1308, 1308, 1308, 1308, 1308, 1308,
+ 1308, 1308, 1308, 1308, 1308, 1308, 1308, 1308, 1308, 1309,
+ 0, 0, 1309, 0, 0, 0, 1309, 0, 1309, 0,
+ 1309, 1309, 1309, 0, 0, 1309, 1309, 1309, 1309, 1309,
+ 1311, 1311, 1311, 0, 0, 0, 0, 1311, 1312, 1312,
+ 0, 1312, 1312, 1312, 0, 1312, 1312, 1312, 1312, 1312,
+ 1312, 1312, 1312, 1312, 1312, 1312, 1312, 1312, 1312, 1313,
+
+ 1313, 0, 1313, 1313, 1313, 1313, 1313, 1313, 1313, 1313,
+ 1313, 1313, 1313, 1313, 1313, 1313, 1313, 1313, 1313, 1313,
+ 1314, 1314, 0, 1314, 1314, 1314, 0, 1314, 1314, 1314,
+ 1314, 1314, 1314, 1314, 1314, 1314, 1314, 1314, 1314, 1314,
+ 1314, 1315, 1315, 0, 1315, 1315, 1315, 0, 1315, 1315,
+ 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
+ 1315, 1315, 1319, 1319, 1319, 0, 0, 0, 0, 1319,
+ 1320, 1320, 1320, 0, 0, 0, 0, 1320, 1321, 1321,
+ 1321, 1321, 1321, 1321, 1321, 1321, 1321, 1321, 1321, 1321,
+ 1321, 1321, 1321, 1321, 1321, 1321, 1321, 1321, 1321, 1322,
+
+ 1322, 0, 1322, 1322, 1322, 0, 1322, 1322, 1322, 1322,
+ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
+ 1327, 1327, 1327, 0, 0, 0, 0, 1327, 1328, 1328,
+ 1328, 1328, 0, 0, 0, 0, 1328, 1332, 1332, 1332,
+ 0, 0, 0, 0, 1332, 1333, 1333, 1333, 1333, 0,
+ 0, 0, 0, 1333, 1336, 1336, 1336, 0, 0, 0,
+ 0, 1336, 1337, 1337, 1337, 1337, 0, 0, 0, 0,
+ 1337, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338,
+ 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338,
+ 1338, 1338, 1340, 0, 0, 1340, 1340, 0, 1340, 1340,
+
+ 0, 0, 1340, 1340, 1341, 0, 0, 1341, 0, 0,
+ 0, 1341, 0, 1341, 0, 1341, 1341, 1341, 0, 0,
+ 1341, 1341, 1341, 1341, 1341, 1343, 0, 1343, 1343, 0,
+ 0, 0, 0, 1343, 1344, 1344, 1344, 0, 0, 0,
+ 0, 1344, 1345, 1345, 1345, 1345, 0, 0, 0, 0,
+ 1345, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346,
+ 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346, 1346,
+ 1346, 1346, 1348, 0, 0, 1348, 1348, 0, 1348, 1348,
+ 0, 0, 1348, 1348, 1349, 0, 0, 1349, 0, 0,
+ 0, 1349, 0, 1349, 0, 1349, 1349, 1349, 0, 0,
+
+ 1349, 1349, 1349, 1349, 1349, 1351, 0, 1351, 1351, 0,
+ 0, 0, 0, 1351, 1352, 1352, 1352, 0, 0, 0,
+ 0, 1352, 1353, 1353, 1353, 0, 0, 0, 0, 0,
+ 1353, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354,
+ 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1354,
+ 1354, 1354, 1355, 1355, 0, 1355, 1355, 1355, 1355, 1355,
+ 0, 1355, 0, 1355, 1355, 1355, 0, 0, 1355, 1355,
+ 1355, 1355, 1355, 1356, 1356, 0, 1356, 1356, 1356, 1356,
+ 1356, 0, 1356, 0, 1356, 1356, 1356, 0, 0, 1356,
+ 1356, 1356, 1356, 1356, 1358, 0, 1358, 1358, 0, 0,
+
+ 0, 0, 1358, 1361, 0, 1361, 1361, 0, 0, 0,
+ 0, 1361, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364,
+ 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364, 1364,
+ 1364, 1364, 1364, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241,
+
+ 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241, 1241
+ } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "toke.l"
+#line 2 "toke.l"
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2007-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sudoers.h>
+#include <toke.h>
+#include <gram.h>
+#include <sudo_digest.h>
+#include <sudo_lbuf.h>
+
+#if defined(HAVE_STRUCT_DIRENT_D_NAMLEN) && HAVE_STRUCT_DIRENT_D_NAMLEN
+# define NAMLEN(dirent) (dirent)->d_namlen
+#else
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#endif
+
+// PVS Studio suppression
+// -V::519, 547, 1004, 1037, 1048
+
+int sudolineno; /* current sudoers line number. */
+char *sudoers; /* sudoers file being parsed. */
+char *sudoers_search_path; /* colon-separated path of sudoers files. */
+const char *sudoers_errstr; /* description of last error from lexer. */
+struct sudolinebuf sudolinebuf; /* sudoers line being parsed. */
+
+static bool continued, sawspace;
+static int prev_state;
+static unsigned int digest_type = SUDO_DIGEST_INVALID;
+
+static bool pop_include(void);
+static int sudoers_input(char *buf, yy_size_t max_size);
+
+#ifndef TRACELEXER
+static struct sudo_lbuf trace_lbuf;
+#endif
+
+int (*trace_print)(const char *msg) = sudoers_trace_print;
+
+#define ECHO ignore_result(fwrite(sudoerstext, (size_t)sudoersleng, 1, sudoersout))
+
+#define YY_INPUT(buf, result, max_size) (result) = sudoers_input(buf, (yy_size_t)(max_size))
+
+#define YY_USER_ACTION do { \
+ sudolinebuf.toke_start = sudolinebuf.toke_end; \
+ sudolinebuf.toke_end += (size_t)sudoersleng; \
+} while (0);
+
+#define sudoersless(n) do { \
+ sudolinebuf.toke_end = sudolinebuf.toke_start + (size_t)(n); \
+ yyless((int)n); \
+} while (0);
+
+#line 3344 "toke.c"
+#define YY_NO_INPUT 1
+
+#line 3347 "toke.c"
+
+#define INITIAL 0
+#define GOTDEFS 1
+#define GOTCMND 2
+#define GOTREGEX 3
+#define STARTDEFS 4
+#define INDEFS 5
+#define INSTR 6
+#define WANTDIGEST 7
+#define GOTINC 8
+#define EXPECTPATH 9
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals ( void );
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy ( void );
+
+int yyget_debug ( void );
+
+void yyset_debug ( int debug_flag );
+
+YY_EXTRA_TYPE yyget_extra ( void );
+
+void yyset_extra ( YY_EXTRA_TYPE user_defined );
+
+FILE *yyget_in ( void );
+
+void yyset_in ( FILE * _in_str );
+
+FILE *yyget_out ( void );
+
+void yyset_out ( FILE * _out_str );
+
+ int yyget_leng ( void );
+
+char *yyget_text ( void );
+
+int yyget_lineno ( void );
+
+void yyset_lineno ( int _line_number );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap ( void );
+#else
+extern int yywrap ( void );
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy ( char *, const char *, int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen ( const char * );
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput ( void );
+#else
+static int input ( void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ int n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK /*LINTED*/break;
+#endif
+
+#define YY_RULE_SETUP \
+ if ( yyleng > 0 ) \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+ (yytext[yyleng - 1] == '\n'); \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ int yy_act;
+
+ if ( !(yy_init) )
+ {
+ (yy_init) = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! (yy_start) )
+ (yy_start) = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer( yyin, YY_BUF_SIZE );
+ }
+
+ yy_load_buffer_state( );
+ }
+
+ {
+#line 119 "toke.l"
+
+#line 3576 "toke.c"
+
+ while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = (yy_c_buf_p);
+
+ /* Support of yytext. */
+ *yy_cp = (yy_hold_char);
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = (yy_start);
+ yy_current_state += YY_AT_BOL();
+yy_match:
+ do
+ {
+ YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 1242 )
+ yy_c = yy_meta[yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 9534 );
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = (yy_hold_char);
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 120 "toke.l"
+{
+ LEXTRACE(", ");
+ return ',';
+ } /* return ',' */
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 125 "toke.l"
+BEGIN STARTDEFS;
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 127 "toke.l"
+{
+ BEGIN INDEFS;
+ LEXTRACE("DEFVAR ");
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ return DEFVAR;
+ }
+ YY_BREAK
+
+case 4:
+YY_RULE_SETUP
+#line 136 "toke.l"
+{
+ BEGIN STARTDEFS;
+ LEXTRACE(", ");
+ return ',';
+ } /* return ',' */
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 142 "toke.l"
+{
+ LEXTRACE("= ");
+ return '=';
+ } /* return '=' */
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 147 "toke.l"
+{
+ LEXTRACE("+= ");
+ return '+';
+ } /* return '+' */
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 152 "toke.l"
+{
+ LEXTRACE("-= ");
+ return '-';
+ } /* return '-' */
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 157 "toke.l"
+{
+ LEXTRACE("BEGINSTR ");
+ sudoerslval.string = NULL;
+ prev_state = YY_START;
+ BEGIN INSTR;
+ }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 164 "toke.l"
+{
+ LEXTRACE("WORD(2) ");
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ return WORD;
+ }
+ YY_BREAK
+
+
+case 10:
+/* rule 10 can match eol */
+YY_RULE_SETUP
+#line 173 "toke.l"
+{
+ /* Line continuation char followed by newline. */
+ sudolineno++;
+ continued = true;
+ }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 179 "toke.l"
+{
+ LEXTRACE("ENDSTR ");
+ BEGIN prev_state;
+
+ if (sudoerslval.string == NULL) {
+ sudoers_errstr = N_("empty string");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ if (prev_state == INITIAL || prev_state == GOTDEFS) {
+ switch (sudoerslval.string[0]) {
+ case '%':
+ if (sudoerslval.string[1] == '\0' ||
+ (sudoerslval.string[1] == ':' &&
+ sudoerslval.string[2] == '\0')) {
+ parser_leak_remove(LEAK_PTR, sudoerslval.string);
+ free(sudoerslval.string);
+ sudoers_errstr = N_("empty group");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ LEXTRACE("USERGROUP ");
+ return USERGROUP;
+ case '+':
+ if (sudoerslval.string[1] == '\0') {
+ parser_leak_remove(LEAK_PTR, sudoerslval.string);
+ free(sudoerslval.string);
+ sudoers_errstr = N_("empty netgroup");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ LEXTRACE("NETGROUP ");
+ return NETGROUP;
+ }
+ }
+ LEXTRACE("WORD(4) ");
+ return WORD;
+ }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 218 "toke.l"
+{
+ LEXTRACE("BACKSLASH ");
+ if (!append(sudoerstext, sudoersleng))
+ yyterminate();
+ }
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 224 "toke.l"
+{
+ LEXTRACE("STRBODY ");
+ if (!append(sudoerstext, sudoersleng))
+ yyterminate();
+ }
+ YY_BREAK
+
+
+case 14:
+YY_RULE_SETUP
+#line 232 "toke.l"
+{
+ /* quoted fnmatch glob char, pass verbatim */
+ LEXTRACE("QUOTEDCHAR ");
+ if (!fill_args(sudoerstext, 2, sawspace))
+ yyterminate();
+ sawspace = false;
+ }
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 240 "toke.l"
+{
+ /* quoted sudoers special char, strip backslash */
+ LEXTRACE("QUOTEDCHAR ");
+ if (!fill_args(sudoerstext + 1, 1, sawspace))
+ yyterminate();
+ sawspace = false;
+ }
+ YY_BREAK
+case 16:
+/* rule 16 can match eol */
+YY_RULE_SETUP
+#line 248 "toke.l"
+{
+ BEGIN INITIAL;
+ sudoersless(0);
+ yy_set_bol(0);
+ return COMMAND;
+ } /* end of command line args */
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 255 "toke.l"
+{
+ if (sudoerslval.command.args == NULL && sudoerstext[0] == '^') {
+ LEXTRACE("ARG REGEX ");
+ BEGIN GOTREGEX;
+ sudoersless(0);
+ yy_set_bol(0);
+ } else {
+ LEXTRACE("ARG ");
+ if (!fill_args(sudoerstext, sudoersleng, sawspace))
+ yyterminate();
+ sawspace = false;
+ }
+ } /* a command line arg */
+ YY_BREAK
+
+
+case 18:
+YY_RULE_SETUP
+#line 271 "toke.l"
+{
+ /* quoted character, pass verbatim */
+ LEXTRACE("QUOTEDCHAR ");
+ if (!fill_args(sudoerstext, 2, false))
+ yyterminate();
+ }
+ YY_BREAK
+case 19:
+/* rule 19 can match eol */
+YY_RULE_SETUP
+#line 278 "toke.l"
+{
+ /* Let the parser attempt to recover. */
+ sudoersless(0);
+ yy_set_bol(0);
+ BEGIN INITIAL;
+
+ sudoers_errstr = N_("unterminated regular expression");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ } /* illegal inside regex */
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 289 "toke.l"
+{
+ if (!fill_args("$", 1, false))
+ yyterminate();
+ BEGIN INITIAL;
+ continued = false;
+ if (sudoers_strict()) {
+ if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) {
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ }
+ return COMMAND;
+ }
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 303 "toke.l"
+{
+ if (continued) {
+ /* remove whitespace after line continuation */
+ while (isblank((unsigned char)*sudoerstext)) {
+ sudoerstext++;
+ sudoersleng--;
+ }
+ continued = false;
+ }
+ if (sudoersleng != 0) {
+ if (!fill_args(sudoerstext, sudoersleng, false))
+ yyterminate();
+ }
+ }
+ YY_BREAK
+
+case 22:
+YY_RULE_SETUP
+#line 319 "toke.l"
+{
+ /* Only return DIGEST if the length is correct. */
+ size_t digest_len =
+ sudo_digest_getlen(digest_type);
+ if ((size_t)sudoersleng == digest_len * 2) {
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ BEGIN INITIAL;
+ LEXTRACE("DIGEST ");
+ return DIGEST;
+ }
+ BEGIN INITIAL;
+ sudoersless(sudoersleng);
+ } /* hex digest */
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 334 "toke.l"
+{
+ /* Only return DIGEST if the length is correct. */
+ size_t len, digest_len =
+ sudo_digest_getlen(digest_type);
+ if (sudoerstext[sudoersleng - 1] == '=') {
+ /* use padding */
+ len = 4 * ((digest_len + 2) / 3);
+ } else {
+ /* no padding */
+ len = (4 * digest_len + 2) / 3;
+ }
+ if ((size_t)sudoersleng == len) {
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ BEGIN INITIAL;
+ LEXTRACE("DIGEST ");
+ return DIGEST;
+ }
+ BEGIN INITIAL;
+ sudoersless(sudoersleng);
+ } /* base64 digest */
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 356 "toke.l"
+{
+ if (continued) {
+ sudoers_errstr = N_("invalid line continuation");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+
+ BEGIN GOTINC;
+ LEXTRACE("INCLUDE ");
+ return INCLUDE;
+ }
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 368 "toke.l"
+{
+ if (continued) {
+ sudoers_errstr = N_("invalid line continuation");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+
+ BEGIN GOTINC;
+ LEXTRACE("INCLUDEDIR ");
+ return INCLUDEDIR;
+ }
+ YY_BREAK
+case 26:
+/* rule 26 can match eol */
+YY_RULE_SETUP
+#line 380 "toke.l"
+{
+ if (continued) {
+ sudoers_errstr = N_("invalid line continuation");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+
+ /* only consume #include */
+ sudoersless(sizeof("#include") - 1);
+ yy_set_bol(0);
+
+ BEGIN GOTINC;
+ LEXTRACE("INCLUDE ");
+ return INCLUDE;
+ }
+ YY_BREAK
+case 27:
+/* rule 27 can match eol */
+YY_RULE_SETUP
+#line 396 "toke.l"
+{
+ if (continued) {
+ sudoers_errstr = N_("invalid line continuation");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+
+ /* only consume #includedir */
+ sudoersless(sizeof("#includedir") - 1);
+ yy_set_bol(0);
+
+ BEGIN GOTINC;
+ LEXTRACE("INCLUDEDIR ");
+ return INCLUDEDIR;
+ }
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 412 "toke.l"
+{
+ char deftype;
+ size_t n;
+
+ if (continued) {
+ sudoers_errstr = N_("invalid line continuation");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+
+ for (n = 0; isblank((unsigned char)sudoerstext[n]); n++)
+ continue;
+ n += sizeof("Defaults") - 1;
+ if ((deftype = sudoerstext[n++]) != '\0') {
+ while (isblank((unsigned char)sudoerstext[n]))
+ n++;
+ }
+ BEGIN GOTDEFS;
+ switch (deftype) {
+ case ':':
+ sudoersless(n);
+ LEXTRACE("DEFAULTS_USER ");
+ return DEFAULTS_USER;
+ case '>':
+ sudoersless(n);
+ LEXTRACE("DEFAULTS_RUNAS ");
+ return DEFAULTS_RUNAS;
+ case '@':
+ sudoersless(n);
+ LEXTRACE("DEFAULTS_HOST ");
+ return DEFAULTS_HOST;
+ case '!':
+ sudoersless(n);
+ LEXTRACE("DEFAULTS_CMND ");
+ return DEFAULTS_CMND;
+ default:
+ LEXTRACE("DEFAULTS ");
+ return DEFAULTS;
+ }
+ }
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 453 "toke.l"
+{
+ size_t n;
+
+ if (continued) {
+ sudoers_errstr = N_("invalid line continuation");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+
+ for (n = 0; isblank((unsigned char)sudoerstext[n]); n++)
+ continue;
+ switch (sudoerstext[n]) {
+ case 'H':
+ LEXTRACE("HOSTALIAS ");
+ return HOSTALIAS;
+ case 'C':
+ LEXTRACE("CMNDALIAS ");
+ return CMNDALIAS;
+ case 'U':
+ LEXTRACE("USERALIAS ");
+ return USERALIAS;
+ case 'R':
+ LEXTRACE("RUNASALIAS ");
+ return RUNASALIAS;
+ }
+ }
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 480 "toke.l"
+{
+ /* cmnd does not require passwd for this user */
+ LEXTRACE("NOPASSWD ");
+ return NOPASSWD;
+ }
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 486 "toke.l"
+{
+ /* cmnd requires passwd for this user */
+ LEXTRACE("PASSWD ");
+ return PASSWD;
+ }
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 492 "toke.l"
+{
+ LEXTRACE("NOEXEC ");
+ return NOEXEC;
+ }
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 497 "toke.l"
+{
+ LEXTRACE("EXEC ");
+ return EXEC;
+ }
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 502 "toke.l"
+{
+ LEXTRACE("INTERCEPT ");
+ return INTERCEPT;
+ }
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 507 "toke.l"
+{
+ LEXTRACE("NOINTERCEPT ");
+ return NOINTERCEPT;
+ }
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 512 "toke.l"
+{
+ LEXTRACE("SETENV ");
+ return SETENV;
+ }
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 517 "toke.l"
+{
+ LEXTRACE("NOSETENV ");
+ return NOSETENV;
+ }
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 522 "toke.l"
+{
+ LEXTRACE("LOG_OUTPUT ");
+ return LOG_OUTPUT;
+ }
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 527 "toke.l"
+{
+ LEXTRACE("NOLOG_OUTPUT ");
+ return NOLOG_OUTPUT;
+ }
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 532 "toke.l"
+{
+ LEXTRACE("LOG_INPUT ");
+ return LOG_INPUT;
+ }
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 537 "toke.l"
+{
+ LEXTRACE("NOLOG_INPUT ");
+ return NOLOG_INPUT;
+ }
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 542 "toke.l"
+{
+ LEXTRACE("MAIL ");
+ return MAIL;
+ }
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 547 "toke.l"
+{
+ LEXTRACE("NOMAIL ");
+ return NOMAIL;
+ }
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 552 "toke.l"
+{
+ LEXTRACE("FOLLOW ");
+ return FOLLOWLNK;
+ }
+ YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 557 "toke.l"
+{
+ LEXTRACE("NOFOLLOW ");
+ return NOFOLLOWLNK;
+ }
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 562 "toke.l"
+{
+ if (sudoerstext[0] == '+')
+ sudoers_errstr = N_("empty netgroup");
+ else
+ sudoers_errstr = N_("empty group");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 571 "toke.l"
+{
+ /* netgroup */
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("NETGROUP ");
+ return NETGROUP;
+ }
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 579 "toke.l"
+{
+ /* group */
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("USERGROUP ");
+ return USERGROUP;
+ }
+ YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 587 "toke.l"
+{
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("NTWKADDR ");
+ return NTWKADDR;
+ }
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 594 "toke.l"
+{
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("NTWKADDR ");
+ return NTWKADDR;
+ }
+ YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 601 "toke.l"
+{
+ if (!ipv6_valid(sudoerstext)) {
+ sudoers_errstr = N_("invalid IPv6 address");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("NTWKADDR ");
+ return NTWKADDR;
+ }
+ YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 613 "toke.l"
+{
+ if (!ipv6_valid(sudoerstext)) {
+ sudoers_errstr = N_("invalid IPv6 address");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("NTWKADDR ");
+ return NTWKADDR;
+ }
+ YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 625 "toke.l"
+{
+ LEXTRACE("ALL ");
+ return ALL;
+
+ }
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 631 "toke.l"
+{
+ LEXTRACE("CMND_TIMEOUT ");
+ return CMND_TIMEOUT;
+ }
+ YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 636 "toke.l"
+{
+ LEXTRACE("NOTBEFORE ");
+ return NOTBEFORE;
+ }
+ YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 641 "toke.l"
+{
+ LEXTRACE("NOTAFTER ");
+ return NOTAFTER;
+ }
+ YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 646 "toke.l"
+{
+ LEXTRACE("CWD ");
+ prev_state = YY_START;
+ BEGIN EXPECTPATH;
+ return CWD;
+ }
+ YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 653 "toke.l"
+{
+ LEXTRACE("CHROOT ");
+ prev_state = YY_START;
+ BEGIN EXPECTPATH;
+ return CHROOT;
+ }
+ YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 660 "toke.l"
+{
+#ifdef HAVE_SELINUX
+ LEXTRACE("ROLE ");
+ return ROLE;
+#else
+ goto got_alias;
+#endif
+ }
+ YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 669 "toke.l"
+{
+#ifdef HAVE_SELINUX
+ LEXTRACE("TYPE ");
+ return TYPE;
+#else
+ goto got_alias;
+#endif
+ }
+ YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 677 "toke.l"
+{
+#ifdef HAVE_APPARMOR
+ LEXTRACE("APPARMOR_PROFILE ");
+ return APPARMOR_PROFILE;
+#else
+ goto got_alias;
+#endif
+ }
+ YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 685 "toke.l"
+{
+#ifdef HAVE_PRIV_SET
+ LEXTRACE("PRIVS ");
+ return PRIVS;
+#else
+ goto got_alias;
+#endif
+ }
+ YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 694 "toke.l"
+{
+#ifdef HAVE_PRIV_SET
+ LEXTRACE("LIMITPRIVS ");
+ return LIMITPRIVS;
+#else
+ goto got_alias;
+#endif
+ }
+ YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 703 "toke.l"
+{
+ got_alias:
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("ALIAS ");
+ return ALIAS;
+ }
+ YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 711 "toke.l"
+{
+ /* XXX - no way to specify digest for command */
+ /* no command args allowed for Defaults!/path */
+ if (!fill_cmnd(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("COMMAND ");
+ return COMMAND;
+ }
+ YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 720 "toke.l"
+{
+ digest_type = SUDO_DIGEST_SHA224;
+ BEGIN WANTDIGEST;
+ LEXTRACE("SHA224_TOK ");
+ return SHA224_TOK;
+ }
+ YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 727 "toke.l"
+{
+ digest_type = SUDO_DIGEST_SHA256;
+ BEGIN WANTDIGEST;
+ LEXTRACE("SHA256_TOK ");
+ return SHA256_TOK;
+ }
+ YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 734 "toke.l"
+{
+ digest_type = SUDO_DIGEST_SHA384;
+ BEGIN WANTDIGEST;
+ LEXTRACE("SHA384_TOK ");
+ return SHA384_TOK;
+ }
+ YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 741 "toke.l"
+{
+ digest_type = SUDO_DIGEST_SHA512;
+ BEGIN WANTDIGEST;
+ LEXTRACE("SHA512_TOK ");
+ return SHA512_TOK;
+ }
+ YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 748 "toke.l"
+{
+ BEGIN GOTCMND;
+ LEXTRACE("COMMAND ");
+ if (!fill_cmnd(sudoerstext, sudoersleng))
+ yyterminate();
+ } /* sudo -e */
+ YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 755 "toke.l"
+{
+ BEGIN prev_state;
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("WORD(5) ");
+ return WORD;
+ }
+ YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 763 "toke.l"
+{
+ /* directories can't have args... */
+ if (sudoerstext[sudoersleng - 1] == '/') {
+ LEXTRACE("COMMAND ");
+ if (!fill_cmnd(sudoerstext, sudoersleng))
+ yyterminate();
+ return COMMAND;
+ }
+ BEGIN GOTCMND;
+ LEXTRACE("COMMAND ");
+ if (!fill_cmnd(sudoerstext, sudoersleng))
+ yyterminate();
+ } /* a pathname */
+ YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 777 "toke.l"
+{
+ if (sudoers_strict()) {
+ if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) {
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ }
+ BEGIN GOTCMND;
+ LEXTRACE("COMMAND ");
+ if (!fill_cmnd(sudoerstext, sudoersleng))
+ yyterminate();
+ } /* a regex */
+ YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 790 "toke.l"
+{
+ LEXTRACE("BEGINSTR ");
+ sudoerslval.string = NULL;
+ prev_state = YY_START;
+ BEGIN INSTR;
+ }
+ YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 797 "toke.l"
+{
+ /* a word */
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("WORD(6) ");
+ return WORD;
+ }
+ YY_BREAK
+
+case 76:
+YY_RULE_SETUP
+#line 806 "toke.l"
+{
+ /* include file/directory */
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ BEGIN INITIAL;
+ LEXTRACE("WORD(7) ");
+ return WORD;
+ }
+ YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 815 "toke.l"
+{
+ LEXTRACE("BEGINSTR ");
+ sudoerslval.string = NULL;
+ prev_state = INITIAL;
+ BEGIN INSTR;
+ }
+ YY_BREAK
+
+case 78:
+YY_RULE_SETUP
+#line 823 "toke.l"
+{
+ LEXTRACE("( ");
+ return '(';
+ }
+ YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 828 "toke.l"
+{
+ LEXTRACE(") ");
+ return ')';
+ }
+ YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 833 "toke.l"
+{
+ LEXTRACE(", ");
+ return ',';
+ } /* return ',' */
+ YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 838 "toke.l"
+{
+ LEXTRACE("= ");
+ return '=';
+ } /* return '=' */
+ YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 843 "toke.l"
+{
+ LEXTRACE(": ");
+ return ':';
+ } /* return ':' */
+ YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 848 "toke.l"
+{
+ if (sudoersleng & 1) {
+ LEXTRACE("!");
+ return '!'; /* return '!' */
+ }
+ }
+ YY_BREAK
+case 84:
+/* rule 84 can match eol */
+YY_RULE_SETUP
+#line 855 "toke.l"
+{
+ if (YY_START == INSTR) {
+ /* throw away old string */
+ parser_leak_remove(LEAK_PTR, sudoerslval.string);
+ free(sudoerslval.string);
+ /* re-scan after changing state */
+ BEGIN INITIAL;
+ sudoersless(0);
+ sudoers_errstr = N_("unexpected line break in string");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ BEGIN INITIAL;
+ sudolineno++;
+ continued = false;
+ LEXTRACE("\n");
+ return '\n';
+ } /* return newline */
+ YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 874 "toke.l"
+{ /* throw away space/tabs */
+ sawspace = true; /* but remember for fill_args */
+ }
+ YY_BREAK
+case 86:
+/* rule 86 can match eol */
+YY_RULE_SETUP
+#line 878 "toke.l"
+{
+ sawspace = true; /* remember for fill_args */
+ sudolineno++;
+ continued = true;
+ } /* throw away EOL after \ */
+ YY_BREAK
+case 87:
+/* rule 87 can match eol */
+YY_RULE_SETUP
+#line 884 "toke.l"
+{
+ if (sudoerstext[sudoersleng - 1] == '\n') {
+ /* comment ending in a newline */
+ BEGIN INITIAL;
+ sudolineno++;
+ continued = false;
+ } else if (!feof(sudoersin)) {
+ sudoers_errstr = strerror(errno);
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ LEXTRACE("#\n");
+ return '\n';
+ } /* comment, not uid/gid */
+ YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 899 "toke.l"
+{
+ LEXTRACE("NOMATCH ");
+ return NOMATCH;
+ } /* parse error, no matching token */
+ YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(GOTDEFS):
+case YY_STATE_EOF(GOTCMND):
+case YY_STATE_EOF(GOTREGEX):
+case YY_STATE_EOF(STARTDEFS):
+case YY_STATE_EOF(INDEFS):
+case YY_STATE_EOF(INSTR):
+case YY_STATE_EOF(WANTDIGEST):
+case YY_STATE_EOF(GOTINC):
+case YY_STATE_EOF(EXPECTPATH):
+#line 904 "toke.l"
+{
+ if (!pop_include())
+ yyterminate();
+ }
+ YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 909 "toke.l"
+ECHO;
+ YY_BREAK
+#line 4713 "toke.c"
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = (yy_hold_char);
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++(yy_c_buf_p);
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = (yy_c_buf_p);
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ (yy_did_buffer_switch_on_eof) = 0;
+
+ if ( yywrap( ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) =
+ (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ (yy_c_buf_p) =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+ } /* end of user's declarations */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = (yytext_ptr);
+ int number_to_move, i;
+ int ret_val;
+
+ if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1);
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
+
+ int yy_c_buf_p_offset =
+ (int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yyrealloc( (void *) b->yy_ch_buf,
+ (yy_size_t) (b->yy_buf_size + 2) );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = NULL;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ (yy_n_chars), num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ if ( (yy_n_chars) == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart( yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
+ (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ /* "- 2" to take care of EOB's */
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
+ }
+
+ (yy_n_chars) += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+ (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (void)
+{
+ yy_state_type yy_current_state;
+ char *yy_cp;
+
+ yy_current_state = (yy_start);
+ yy_current_state += YY_AT_BOL();
+
+ for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+ {
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 1242 )
+ yy_c = yy_meta[yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
+{
+ int yy_is_jam;
+ char *yy_cp = (yy_c_buf_p);
+
+ YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 1242 )
+ yy_c = yy_meta[yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+ yy_is_jam = (yy_current_state == 1241);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_UNPUT
+
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (void)
+#else
+ static int input (void)
+#endif
+
+{
+ int c;
+
+ *(yy_c_buf_p) = (yy_hold_char);
+
+ if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ /* This was really a NUL. */
+ *(yy_c_buf_p) = '\0';
+
+ else
+ { /* need more input */
+ int offset = (int) ((yy_c_buf_p) - (yytext_ptr));
+ ++(yy_c_buf_p);
+
+ switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart( yyin );
+
+ FALLTHROUGH;
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap( ) )
+ return 0;
+
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) = (yytext_ptr) + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+ *(yy_c_buf_p) = '\0'; /* preserve yytext */
+ (yy_hold_char) = *++(yy_c_buf_p);
+
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ *
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void yyrestart (FILE * input_file )
+{
+
+ if ( ! YY_CURRENT_BUFFER ){
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer( yyin, YY_BUF_SIZE );
+ }
+
+ yy_init_buffer( YY_CURRENT_BUFFER, input_file );
+ yy_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ *
+ */
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer )
+{
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
+ */
+ yyensure_buffer_stack ();
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ yy_load_buffer_state( );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void yy_load_buffer_state (void)
+{
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ (yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ *
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size )
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer( b, file );
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ *
+ */
+ void yy_delete_buffer (YY_BUFFER_STATE b )
+{
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yyfree( (void *) b->yy_ch_buf );
+
+ yyfree( (void *) b );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file )
+
+{
+ int oerrno = errno;
+
+ yy_flush_buffer( b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ *
+ */
+ void yy_flush_buffer (YY_BUFFER_STATE b )
+{
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ yy_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ *
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+ if (new_buffer == NULL)
+ return;
+
+ yyensure_buffer_stack();
+
+ /* This block is copied from yy_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ (yy_buffer_stack_top)++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ *
+ */
+void yypop_buffer_state (void)
+{
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ yy_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if ((yy_buffer_stack_top) > 0)
+ --(yy_buffer_stack_top);
+
+ if (YY_CURRENT_BUFFER) {
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+ yy_size_t num_to_alloc;
+
+ if (!(yy_buffer_stack)) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ (yy_buffer_stack_max) = num_to_alloc;
+ (yy_buffer_stack_top) = 0;
+ return;
+ }
+
+ if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ yy_size_t grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = (yy_buffer_stack_max) + grow_size;
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+ ((yy_buffer_stack),
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ /* zero only the new slots.*/
+ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+ (yy_buffer_stack_max) = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return NULL;
+
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = NULL;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer( b );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ *
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (const char * yystr )
+{
+
+ return yy_scan_bytes( yystr, (int) strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len )
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = (yy_size_t) (_yybytes_len + 2);
+ buf = (char *) yyalloc( n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer( buf, n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yynoreturn yy_fatal_error (const char* msg )
+{
+ fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = (yy_hold_char); \
+ (yy_c_buf_p) = yytext + yyless_macro_arg; \
+ (yy_hold_char) = *(yy_c_buf_p); \
+ *(yy_c_buf_p) = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ *
+ */
+int yyget_lineno (void)
+{
+
+ return yylineno;
+}
+
+/** Get the input stream.
+ *
+ */
+FILE *yyget_in (void)
+{
+ return yyin;
+}
+
+/** Get the output stream.
+ *
+ */
+FILE *yyget_out (void)
+{
+ return yyout;
+}
+
+/** Get the length of the current token.
+ *
+ */
+int yyget_leng (void)
+{
+ return yyleng;
+}
+
+/** Get the current token.
+ *
+ */
+
+char *yyget_text (void)
+{
+ return yytext;
+}
+
+/** Set the current line number.
+ * @param _line_number line number
+ *
+ */
+void yyset_lineno (int _line_number )
+{
+
+ yylineno = _line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param _in_str A readable stream.
+ *
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE * _in_str )
+{
+ yyin = _in_str ;
+}
+
+void yyset_out (FILE * _out_str )
+{
+ yyout = _out_str ;
+}
+
+int yyget_debug (void)
+{
+ return yy_flex_debug;
+}
+
+void yyset_debug (int _bdebug )
+{
+ yy_flex_debug = _bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from yylex_destroy(), so don't allocate here.
+ */
+
+ (yy_buffer_stack) = NULL;
+ (yy_buffer_stack_top) = 0;
+ (yy_buffer_stack_max) = 0;
+ (yy_c_buf_p) = NULL;
+ (yy_init) = 0;
+ (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
+#else
+ yyin = NULL;
+ yyout = NULL;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * yylex_init()
+ */
+ return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (void)
+{
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ yy_delete_buffer( YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ yypop_buffer_state();
+ }
+
+ /* Destroy the stack itself. */
+ yyfree((yy_buffer_stack) );
+ (yy_buffer_stack) = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * yylex() is called, initialization will occur. */
+ yy_init_globals( );
+
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, const char * s2, int n )
+{
+
+ int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (const char * s )
+{
+ int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *yyalloc (yy_size_t size )
+{
+ return malloc(size);
+}
+
+void *yyrealloc (void * ptr, yy_size_t size )
+{
+
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return realloc(ptr, size);
+}
+
+void yyfree (void * ptr )
+{
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 909 "toke.l"
+
+struct path_list {
+ SLIST_ENTRY(path_list) entries;
+ char *path;
+};
+
+SLIST_HEAD(path_list_head, path_list);
+
+struct include_stack {
+ struct sudolinebuf line;
+ YY_BUFFER_STATE bs;
+ char *path; /* search path */
+ char *file;
+ struct path_list_head more; /* more files in case of includedir */
+ int lineno;
+ bool keepopen;
+};
+
+/*
+ * Compare two struct path_list structs in reverse order.
+ */
+static int
+pl_compare(const void *v1, const void *v2)
+{
+ const struct path_list * const *p1 = v1;
+ const struct path_list * const *p2 = v2;
+
+ return strcmp((*p2)->path, (*p1)->path);
+}
+
+/*
+ * Open dirpath and fill in pathsp with an array of regular files
+ * that do not end in '~' or contain a '.'.
+ * Returns the number of files or SIZE_MAX (-1) on error.
+ * If zero files are found, NULL is stored in pathsp.
+ */
+static size_t
+read_dir_files(const char *dirpath, struct path_list ***pathsp, int verbose)
+{
+ DIR *dir;
+ size_t i, count = 0;
+ size_t max_paths = 32;
+ struct dirent *dent;
+ struct path_list **paths = NULL;
+ const size_t dirlen = strlen(dirpath);
+ debug_decl(read_dir_files, SUDOERS_DEBUG_PARSER);
+
+ /* XXX - fdopendir */
+ dir = opendir(dirpath);
+ if (dir == NULL) {
+ if (errno == ENOENT)
+ goto done;
+ sudo_warn("%s", dirpath);
+ goto bad;
+ }
+ paths = reallocarray(NULL, max_paths, sizeof(*paths));
+ if (paths == NULL)
+ goto oom;
+ while ((dent = readdir(dir)) != NULL) {
+ const size_t namelen = NAMLEN(dent);
+ const char *name = dent->d_name;
+ struct path_list *pl;
+ struct stat sb;
+ size_t len;
+ char *path;
+
+ /* Ignore files that end in '~' or have a '.' in them. */
+ if (namelen == 0 || name[namelen - 1] == '~' || strchr(name, '.') != NULL) {
+ /* Warn about ignored files not starting with '.' if verbose. */
+ if (namelen > 0 && name[0] != '.' && verbose > 1) {
+ if (name[namelen - 1] == '~' ||
+ (namelen > 4 && strcmp(&name[namelen - 4], ".bak") == 0)) {
+ fprintf(stderr, U_("%s/%s: %s"), dirpath, name,
+ U_("ignoring editor backup file"));
+ } else {
+ fprintf(stderr, U_("%s/%s: %s"), dirpath, name,
+ U_("ignoring file name containing '.'"));
+ }
+ fputc('\n', stderr);
+ }
+ continue;
+ }
+ len = dirlen + 1 + namelen;
+ if ((path = sudo_rcstr_alloc(len)) == NULL)
+ goto oom;
+ if ((size_t)snprintf(path, len + 1, "%s/%s", dirpath, name) != len) {
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ sudo_rcstr_delref(path);
+ goto bad;
+ }
+ if (stat(path, &sb) != 0 || !S_ISREG(sb.st_mode)) {
+ sudo_rcstr_delref(path);
+ continue;
+ }
+ pl = malloc(sizeof(*pl));
+ if (pl == NULL) {
+ sudo_rcstr_delref(path);
+ goto oom;
+ }
+ pl->path = path;
+ if (count >= max_paths) {
+ struct path_list **tmp;
+ max_paths <<= 1;
+ tmp = reallocarray(paths, max_paths, sizeof(*paths));
+ if (tmp == NULL) {
+ sudo_rcstr_delref(path);
+ free(pl);
+ goto oom;
+ }
+ paths = tmp;
+ }
+ paths[count++] = pl;
+ }
+ closedir(dir);
+ if (count == 0) {
+ free(paths);
+ paths = NULL;
+ }
+done:
+ *pathsp = paths;
+ debug_return_size_t(count);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+bad:
+ sudoerserror(NULL);
+ if (dir != NULL)
+ closedir(dir);
+ for (i = 0; i < count; i++) {
+ sudo_rcstr_delref(paths[i]->path);
+ free(paths[i]);
+ }
+ free(paths);
+ debug_return_size_t(SIZE_MAX);
+}
+
+/*
+ * Push a list of all files in dirpath onto stack.
+ * Returns the number of files or -1 on error.
+ */
+static size_t
+switch_dir(struct include_stack *stack, char *dirpath, int verbose)
+{
+ struct path_list **paths = NULL;
+ size_t count, i;
+ debug_decl(switch_dir, SUDOERS_DEBUG_PARSER);
+
+ count = read_dir_files(dirpath, &paths, verbose);
+ if (count > 0) {
+ /* Sort the list as an array in reverse order. */
+ qsort(paths, count, sizeof(*paths), pl_compare);
+
+ /* Build up the list in sorted order. */
+ for (i = 0; i < count; i++) {
+ SLIST_INSERT_HEAD(&stack->more, paths[i], entries);
+ }
+ free(paths);
+ }
+
+ debug_return_size_t(count);
+}
+
+#define MAX_SUDOERS_DEPTH 128
+#define SUDOERS_STACK_INCREMENT 16
+
+static size_t istacksize, idepth;
+static struct include_stack *istack;
+static bool keepopen;
+
+void
+init_lexer(void)
+{
+ struct path_list *pl;
+ debug_decl(init_lexer, SUDOERS_DEBUG_PARSER);
+
+#ifndef TRACELEXER
+ free(trace_lbuf.buf);
+ sudo_lbuf_init(&trace_lbuf, NULL, 0, NULL, 0);
+#endif
+
+ while (idepth) {
+ idepth--;
+ while ((pl = SLIST_FIRST(&istack[idepth].more)) != NULL) {
+ SLIST_REMOVE_HEAD(&istack[idepth].more, entries);
+ sudo_rcstr_delref(pl->path);
+ free(pl);
+ }
+ sudo_rcstr_delref(istack[idepth].path);
+ if (idepth && !istack[idepth].keepopen)
+ fclose(istack[idepth].bs->yy_input_file);
+ sudoers_delete_buffer(istack[idepth].bs);
+ free(istack[idepth].line.buf);
+ }
+ free(istack);
+ istack = NULL;
+ istacksize = idepth = 0;
+ free(sudolinebuf.buf);
+ memset(&sudolinebuf, 0, sizeof(sudolinebuf));
+ sudolineno = 1;
+ keepopen = false;
+ sawspace = false;
+ continued = false;
+ digest_type = SUDO_DIGEST_INVALID;
+ prev_state = INITIAL;
+ BEGIN INITIAL;
+
+ debug_return;
+}
+
+/*
+ * Like strlcpy() but expand %h escapes.
+ */
+static size_t
+strlcpy_expand_host(char * restrict dst, const char * restrict src,
+ const char * restrict host, size_t size)
+{
+ size_t len = 0;
+ char ch;
+ debug_decl(strlcpy_expand_host, SUDOERS_DEBUG_PARSER);
+
+ while ((ch = *src++) != '\0') {
+ if (ch == '%' && *src == 'h') {
+ size_t n = strlcpy(dst, host, size);
+ len += n;
+ if (n >= size) {
+ /* truncated */
+ n = size ? size - 1 : 0;
+ }
+ dst += n;
+ size -= n;
+ src++;
+ continue;
+ }
+ if (size > 1) {
+ *dst++ = ch;
+ size--;
+ len++;
+ }
+ }
+ if (size > 0)
+ *dst = '\0';
+
+ debug_return_size_t(len);
+}
+
+/*
+ * Expand any embedded %h (host) escapes in the given path and makes
+ * a relative path fully-qualified based on the current sudoers file.
+ * Returns a reference-counted string on success or NULL on failure.
+ */
+static char *
+expand_include(const char *src, const char *host)
+{
+ const char *path = sudoers_search_path ? sudoers_search_path : sudoers;
+ const char *path_end = path + strlen(path);
+ char *dst, *dst0 = NULL, *dynamic_host = NULL;
+ const char *cp, *ep;
+ size_t dst_size, src_len;
+ size_t nhost = 0;
+ debug_decl(expand_include, SUDOERS_DEBUG_PARSER);
+
+ /* Strip double quotes if present. */
+ src_len = strlen(src);
+ if (src_len > 1 && src[0] == '"' && src[src_len - 1] == '"') {
+ src++;
+ src_len -= 2;
+ }
+ if (src_len == 0)
+ debug_return_ptr(NULL);
+
+ /* Check for %h escapes in src. */
+ cp = src;
+ ep = src + src_len;
+ while (cp < ep) {
+ if (cp[0] == '%' && cp[1] == 'h') {
+ nhost++;
+ cp += 2;
+ continue;
+ }
+ cp++;
+ }
+
+ /* Check for a path separator in the host name, replace with '_'. */
+ if (nhost != 0 && strchr(host, '/') != NULL) {
+ dynamic_host = malloc(strlen(host) + 1);
+ if (dynamic_host == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ for (dst = dynamic_host; *host != '\0'; host++) {
+ if (*host == '/') {
+ *dst++ = '_';
+ continue;
+ }
+ *dst++ = *host;
+ }
+ *dst = '\0';
+ host = dynamic_host;
+ }
+
+ if (*src == '/') {
+ /* Fully-qualified path, make a copy and expand %h escapes. */
+ dst_size = src_len + (nhost * strlen(host)) - (nhost * 2) + 1;
+ dst0 = sudo_rcstr_alloc(dst_size - 1);
+ if (dst0 == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ if (strlcpy_expand_host(dst0, src, host, dst_size) >= dst_size)
+ goto oflow;
+ goto done;
+ }
+
+ /*
+ * Relative paths are located in the same dir as the sudoers file.
+ * If the current sudoers file was opened via a colon-separated path,
+ * use the same path when opening src.
+ */
+ dst_size = 0;
+ for (cp = sudo_strsplit(path, path_end, ":", &ep); cp != NULL;
+ cp = sudo_strsplit(NULL, path_end, ":", &ep)) {
+ char *dirend = memrchr(cp, '/', (size_t)(ep - cp));
+ if (dirend != NULL) {
+ dst_size += (size_t)(dirend - cp) + 1;
+ }
+ /* Includes space for ':' separator and NUL terminator. */
+ dst_size += src_len + (nhost * strlen(host)) - (nhost * 2) + 1;
+ }
+
+ /* Make a copy of the fully-qualified path and return it. */
+ dst = dst0 = sudo_rcstr_alloc(dst_size - 1);
+ if (dst0 == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ for (cp = sudo_strsplit(path, path_end, ":", &ep); cp != NULL;
+ cp = sudo_strsplit(NULL, path_end, ":", &ep)) {
+ size_t len;
+ char *dirend;
+
+ if (cp != path) {
+ if (dst_size < 2)
+ goto oflow;
+ *dst++ = ':';
+ dst_size--;
+ }
+
+ dirend = memrchr(cp, '/', (size_t)(ep - cp));
+ if (dirend != NULL) {
+ len = (size_t)(dirend - cp) + 1;
+ if (len >= dst_size)
+ goto oflow;
+ memcpy(dst, cp, len);
+ dst += len;
+ dst_size -= len;
+ }
+
+ len = strlcpy_expand_host(dst, src, host, dst_size);
+ if (len >= dst_size)
+ goto oflow;
+ dst += len;
+ dst_size -= len;
+ }
+ *dst = '\0';
+
+done:
+ free(dynamic_host);
+ debug_return_str(dst0);
+oflow:
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+bad:
+ sudoerserror(NULL);
+ free(dynamic_host);
+ free(dst0);
+ debug_return_str(NULL);
+}
+
+/*
+ * Open an include file (or file from a directory), push the old
+ * sudoers file buffer and switch to the new one.
+ * A missing or insecure include dir is simply ignored.
+ * Returns false on error, else true.
+ */
+static bool
+push_include_int(const char *opath, const char *host, bool isdir,
+ struct sudoers_parser_config *conf)
+{
+ struct path_list *pl;
+ char *file = NULL, *path;
+ FILE *fp;
+ debug_decl(push_include, SUDOERS_DEBUG_PARSER);
+
+ if ((path = expand_include(opath, host)) == NULL)
+ debug_return_bool(false);
+
+ /* push current state onto stack */
+ if (idepth >= istacksize) {
+ struct include_stack *new_istack;
+
+ if (idepth > MAX_SUDOERS_DEPTH) {
+ if (conf->verbose > 0) {
+ fprintf(stderr, U_("%s: %s"), path,
+ U_("too many levels of includes"));
+ fputc('\n', stderr);
+ }
+ sudoerserror(NULL);
+ sudo_rcstr_delref(path);
+ debug_return_bool(false);
+ }
+ istacksize += SUDOERS_STACK_INCREMENT;
+ new_istack = reallocarray(istack, istacksize, sizeof(*istack));
+ if (new_istack == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ sudoerserror(NULL);
+ sudo_rcstr_delref(path);
+ debug_return_bool(false);
+ }
+ istack = new_istack;
+ }
+ SLIST_INIT(&istack[idepth].more);
+ if (isdir) {
+ struct stat sb;
+ char dname[PATH_MAX];
+ int fd, status;
+ size_t count;
+
+ fd = sudo_open_conf_path(path, dname, sizeof(dname), NULL);
+ if (conf->ignore_perms) {
+ /* Skip sudoers security checks when ignore_perms is set. */
+ if (fd == -1 || fstat(fd, &sb) == -1)
+ status = SUDO_PATH_MISSING;
+ else
+ status = SUDO_PATH_SECURE;
+ } else {
+ status = sudo_secure_fd(fd, S_IFDIR, sudoers_file_uid(),
+ sudoers_file_gid(), &sb);
+ }
+ if (fd != -1)
+ close(fd); /* XXX use in read_dir_files? */
+ if (status != SUDO_PATH_SECURE) {
+ if (conf->verbose > 0) {
+ switch (status) {
+ case SUDO_PATH_BAD_TYPE:
+ errno = ENOTDIR;
+ sudo_warn("%s", path);
+ break;
+ case SUDO_PATH_WRONG_OWNER:
+ sudo_warnx(U_("%s is owned by uid %u, should be %u"),
+ path, (unsigned int) sb.st_uid,
+ (unsigned int) sudoers_file_uid());
+ break;
+ case SUDO_PATH_WORLD_WRITABLE:
+ sudo_warnx(U_("%s is world writable"), path);
+ break;
+ case SUDO_PATH_GROUP_WRITABLE:
+ sudo_warnx(U_("%s is owned by gid %u, should be %u"),
+ path, (unsigned int) sb.st_gid,
+ (unsigned int) sudoers_file_gid());
+ break;
+ default:
+ break;
+ }
+ }
+ /* A missing or insecure include dir is not a fatal error. */
+ sudo_rcstr_delref(path);
+ debug_return_bool(true);
+ }
+ count = switch_dir(&istack[idepth], dname, conf->verbose);
+ switch (count) {
+ case SIZE_MAX:
+ case 0:
+ /* switch_dir() called sudoerserror() for us */
+ sudo_rcstr_delref(path);
+ debug_return_bool(count ? false : true);
+ }
+
+ /* Parse the first dir entry we can open, leave the rest for later. */
+ do {
+ sudo_rcstr_delref(file);
+ sudo_rcstr_delref(path);
+ if ((pl = SLIST_FIRST(&istack[idepth].more)) == NULL) {
+ /* Unable to open any files in include dir, not an error. */
+ debug_return_bool(true);
+ }
+ SLIST_REMOVE_HEAD(&istack[idepth].more, entries);
+ path = pl->path;
+ free(pl);
+ /* The file and path and the same for sudoers.d files. */
+ file = path;
+ sudo_rcstr_addref(file);
+ } while ((fp = open_sudoers(file, NULL, false, &keepopen)) == NULL);
+ } else {
+ if ((fp = open_sudoers(path, &file, true, &keepopen)) == NULL) {
+ /* The error was already printed by open_sudoers() */
+ sudoerserror(NULL);
+ sudo_rcstr_delref(path);
+ debug_return_bool(false);
+ }
+ }
+ /*
+ * Push the old (current) file and open the new one.
+ * We use the existing refs of sudoers and sudoers_search_path.
+ */
+ istack[idepth].file = sudoers;
+ istack[idepth].path = sudoers_search_path;
+ istack[idepth].line = sudolinebuf;
+ istack[idepth].bs = YY_CURRENT_BUFFER;
+ istack[idepth].lineno = sudolineno;
+ istack[idepth].keepopen = keepopen;
+ idepth++;
+ sudolineno = 1;
+ sudoers = file;
+ sudoers_search_path = path;
+ sudoers_switch_to_buffer(sudoers_create_buffer(fp, YY_BUF_SIZE));
+ memset(&sudolinebuf, 0, sizeof(sudolinebuf));
+
+ debug_return_bool(true);
+}
+
+bool
+push_include(const char *opath, const char *host,
+ struct sudoers_parser_config *conf)
+{
+ return push_include_int(opath, host, false, conf);
+}
+
+bool
+push_includedir(const char *opath, const char *host,
+ struct sudoers_parser_config *conf)
+{
+ return push_include_int(opath, host, true, conf);
+}
+
+/*
+ * Restore the previous sudoers file and buffer, or, in the case
+ * of an includedir, switch to the next file in the dir.
+ * Returns false if there is nothing to pop, else true.
+ */
+static bool
+pop_include(void)
+{
+ struct path_list *pl;
+ FILE *fp;
+ debug_decl(pop_include, SUDOERS_DEBUG_PARSER);
+
+ if (idepth == 0 || YY_CURRENT_BUFFER == NULL)
+ debug_return_bool(false);
+
+ if (!keepopen)
+ fclose(YY_CURRENT_BUFFER->yy_input_file);
+ sudoers_delete_buffer(YY_CURRENT_BUFFER);
+ /* If we are in an include dir, move to the next file. */
+ while ((pl = SLIST_FIRST(&istack[idepth - 1].more)) != NULL) {
+ SLIST_REMOVE_HEAD(&istack[idepth - 1].more, entries);
+ fp = open_sudoers(pl->path, NULL, false, &keepopen);
+ if (fp != NULL) {
+ sudolinebuf.len = sudolinebuf.off = 0;
+ sudolinebuf.toke_start = sudolinebuf.toke_end = 0;
+ sudo_rcstr_delref(sudoers);
+ sudo_rcstr_delref(sudoers_search_path);
+ sudoers_search_path = pl->path;
+ sudoers = sudoers_search_path;
+ sudo_rcstr_addref(sudoers);
+ sudolineno = 1;
+ sudoers_switch_to_buffer(sudoers_create_buffer(fp, YY_BUF_SIZE));
+ free(pl);
+ break;
+ }
+ /* Unable to open path in include dir, go to next one. */
+ sudo_rcstr_delref(pl->path);
+ free(pl);
+ }
+ /* If no path list, just pop the last dir on the stack. */
+ if (pl == NULL) {
+ idepth--;
+ sudoers_switch_to_buffer(istack[idepth].bs);
+ free(sudolinebuf.buf);
+ sudolinebuf = istack[idepth].line;
+ sudo_rcstr_delref(sudoers);
+ sudoers = istack[idepth].file;
+ sudo_rcstr_delref(sudoers_search_path);
+ sudoers_search_path = istack[idepth].path;
+ sudolineno = istack[idepth].lineno;
+ keepopen = istack[idepth].keepopen;
+ }
+ debug_return_bool(true);
+}
+
+#ifdef TRACELEXER
+int
+sudoers_trace_print(const char *msg)
+{
+ return fputs(msg, stderr);
+}
+#else
+int
+sudoers_trace_print(const char *msg)
+{
+ debug_decl_vars(sudoers_trace_print, SUDOERS_DEBUG_PARSER);
+
+ if (sudo_debug_needed(SUDO_DEBUG_DEBUG)) {
+ sudo_lbuf_append(&trace_lbuf, "%s", msg);
+ if (strchr(msg, '\n') != NULL)
+ {
+ /* We already parsed the newline so sudolineno is off by one. */
+ sudo_debug_printf2(NULL, NULL, 0,
+ sudo_debug_subsys|SUDO_DEBUG_DEBUG, "sudoerslex: %s:%d: %s",
+ sudoers, sudolineno - 1, trace_lbuf.buf);
+ trace_lbuf.len = 0;
+ }
+ }
+ return 0;
+}
+#endif /* TRACELEXER */
+
+/*
+ * Custom input function that uses getdelim(3) and stores the buffer
+ * where the error functions can access it for better reporting.
+ * On success, buf is guaranteed to end in a newline and not contain
+ * embedded NULs. Calls YY_FATAL_ERROR on error.
+ */
+static int
+sudoers_input(char *buf, yy_size_t max_size)
+{
+ char *cp;
+ size_t avail = sudolinebuf.len - sudolinebuf.off;
+ debug_decl(sudoers_input, SUDOERS_DEBUG_PARSER);
+
+ /* Refill line buffer if needed. */
+ if (avail == 0) {
+ /*
+ * Some getdelim(3) implementations write NUL to buf on EOF.
+ * We peek ahead one char to detect EOF and skip the getdelim() call.
+ * This will preserve the original value of the last line read.
+ */
+ int ch = getc(sudoersin);
+ if (ch == EOF)
+ goto sudoers_eof;
+ ungetc(ch, sudoersin);
+ avail = (size_t)getdelim(&sudolinebuf.buf, &sudolinebuf.size, '\n', sudoersin);
+ if (avail == (size_t)-1) {
+sudoers_eof:
+ /* EOF or error. */
+ if (feof(sudoersin))
+ debug_return_int(0);
+ YY_FATAL_ERROR("input in flex scanner failed");
+ }
+
+ /* getdelim() can return embedded NULs, truncate if we find one. */
+ cp = memchr(sudolinebuf.buf, '\0', avail);
+ if (cp != NULL) {
+ *cp++ = '\n';
+ *cp = '\0';
+ avail = (size_t)(cp - sudolinebuf.buf);
+ }
+
+ /* Add trailing newline if it is missing. */
+ if (sudolinebuf.buf[avail - 1] != '\n') {
+ if (avail + 2 >= sudolinebuf.size) {
+ cp = realloc(sudolinebuf.buf, avail + 2);
+ if (cp == NULL) {
+ YY_FATAL_ERROR("unable to allocate memory");
+ debug_return_int(0);
+ }
+ sudolinebuf.buf = cp;
+ sudolinebuf.size = avail + 2;
+ }
+ sudolinebuf.buf[avail++] = '\n';
+ sudolinebuf.buf[avail] = '\0';
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s:%d: %.*s", sudoers, sudolineno,
+ (int)(avail -1), sudolinebuf.buf);
+
+ sudolinebuf.len = avail;
+ sudolinebuf.off = 0;
+ sudolinebuf.toke_start = sudolinebuf.toke_end = 0;
+ }
+
+ if (avail > max_size)
+ avail = max_size;
+ memcpy(buf, sudolinebuf.buf + sudolinebuf.off, avail);
+ sudolinebuf.off += avail;
+
+ debug_return_int((int)avail);
+}
+
diff --git a/plugins/sudoers/toke.h b/plugins/sudoers/toke.h
new file mode 100644
index 0000000..8b9bfae
--- /dev/null
+++ b/plugins/sudoers/toke.h
@@ -0,0 +1,59 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011-2013, 2015-2016, 2020-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDOERS_TOKE_H
+#define SUDOERS_TOKE_H
+
+struct sudolinebuf {
+ char *buf; /* line buffer */
+ size_t size; /* size of buffer */
+ size_t len; /* used length */
+ size_t off; /* consumed length */
+ size_t toke_start; /* starting column of current token */
+ size_t toke_end; /* ending column of current token */
+};
+
+extern const char *sudoers_errstr;
+extern struct sudolinebuf sudolinebuf;
+extern int sudolineno;
+extern char *sudoers_search_path;
+
+struct sudoers_parser_config;
+bool append(const char *, int);
+bool fill_args(const char *, int, bool);
+bool fill_cmnd(const char *, int);
+bool fill(const char *, int);
+void init_lexer(void);
+bool ipv6_valid(const char *s);
+int sudoers_trace_print(const char *);
+void sudoerserrorf(const char *, ...) sudo_printf0like(1, 2);
+void sudoerserror(const char *);
+bool push_include(const char *, const char *, struct sudoers_parser_config *);
+bool push_includedir(const char *, const char *, struct sudoers_parser_config *);
+
+#ifndef FLEX_SCANNER
+extern int (*trace_print)(const char *msg);
+#endif
+
+#define LEXTRACE(msg) do { \
+ if (trace_print != NULL) \
+ (*trace_print)(msg); \
+} while (0);
+
+#endif /* SUDOERS_TOKE_H */
diff --git a/plugins/sudoers/toke.l b/plugins/sudoers/toke.l
new file mode 100644
index 0000000..1fa9749
--- /dev/null
+++ b/plugins/sudoers/toke.l
@@ -0,0 +1,1593 @@
+%{
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2007-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sudoers.h>
+#include <toke.h>
+#include <gram.h>
+#include <sudo_digest.h>
+#include <sudo_lbuf.h>
+
+#if defined(HAVE_STRUCT_DIRENT_D_NAMLEN) && HAVE_STRUCT_DIRENT_D_NAMLEN
+# define NAMLEN(dirent) (dirent)->d_namlen
+#else
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#endif
+
+// PVS Studio suppression
+// -V::519, 547, 1004, 1037, 1048
+
+int sudolineno; /* current sudoers line number. */
+char *sudoers; /* sudoers file being parsed. */
+char *sudoers_search_path; /* colon-separated path of sudoers files. */
+const char *sudoers_errstr; /* description of last error from lexer. */
+struct sudolinebuf sudolinebuf; /* sudoers line being parsed. */
+
+static bool continued, sawspace;
+static int prev_state;
+static unsigned int digest_type = SUDO_DIGEST_INVALID;
+
+static bool pop_include(void);
+static int sudoers_input(char *buf, yy_size_t max_size);
+
+#ifndef TRACELEXER
+static struct sudo_lbuf trace_lbuf;
+#endif
+
+int (*trace_print)(const char *msg) = sudoers_trace_print;
+
+#define ECHO ignore_result(fwrite(sudoerstext, (size_t)sudoersleng, 1, sudoersout))
+
+#define YY_INPUT(buf, result, max_size) (result) = sudoers_input(buf, (yy_size_t)(max_size))
+
+#define YY_USER_ACTION do { \
+ sudolinebuf.toke_start = sudolinebuf.toke_end; \
+ sudolinebuf.toke_end += (size_t)sudoersleng; \
+} while (0);
+
+#define sudoersless(n) do { \
+ sudolinebuf.toke_end = sudolinebuf.toke_start + (size_t)(n); \
+ yyless((int)n); \
+} while (0);
+
+%}
+
+HEX16 [0-9A-Fa-f]{1,4}
+OCTET (1?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5])
+IPV4ADDR {OCTET}(\.{OCTET}){3}
+IPV6ADDR ({HEX16}?:){2,7}{HEX16}?|({HEX16}?:){2,6}:{IPV4ADDR}
+
+HOSTNAME [[:alnum:]_-]+
+WORD ([^#>!=:,\(\) \t\r\n\\\"]|\\[^\t\n])+
+ID #-?[0-9]+
+PATH \/(\\[\,:= \t#]|[^\,:=\\ \t\r\n#])+
+REGEX \^([^#\r\n\$]|\\[#\$])*\$
+ENVAR ([^#!=, \t\r\n\\\"]|\\[^\r\n])([^#=, \t\r\n\\\"]|\\[^\r\n])*
+DEFVAR [a-z_]+
+
+%option noinput
+%option nounput
+%option noyywrap
+%option prefix="sudoers"
+
+%s GOTDEFS
+%x GOTCMND
+%x GOTREGEX
+%x STARTDEFS
+%x INDEFS
+%x INSTR
+%s WANTDIGEST
+%x GOTINC
+%s EXPECTPATH
+
+%%
+<GOTDEFS>[[:blank:]]*,[[:blank:]]* {
+ LEXTRACE(", ");
+ return ',';
+ } /* return ',' */
+
+<GOTDEFS>[[:blank:]]+ BEGIN STARTDEFS;
+
+<STARTDEFS>{DEFVAR} {
+ BEGIN INDEFS;
+ LEXTRACE("DEFVAR ");
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ return DEFVAR;
+ }
+
+<INDEFS>{
+ , {
+ BEGIN STARTDEFS;
+ LEXTRACE(", ");
+ return ',';
+ } /* return ',' */
+
+ = {
+ LEXTRACE("= ");
+ return '=';
+ } /* return '=' */
+
+ \+= {
+ LEXTRACE("+= ");
+ return '+';
+ } /* return '+' */
+
+ -= {
+ LEXTRACE("-= ");
+ return '-';
+ } /* return '-' */
+
+ \" {
+ LEXTRACE("BEGINSTR ");
+ sudoerslval.string = NULL;
+ prev_state = YY_START;
+ BEGIN INSTR;
+ }
+
+ {ENVAR} {
+ LEXTRACE("WORD(2) ");
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ return WORD;
+ }
+}
+
+<INSTR>{
+ \\[[:blank:]]*\r?\n[[:blank:]]* {
+ /* Line continuation char followed by newline. */
+ sudolineno++;
+ continued = true;
+ }
+
+ \" {
+ LEXTRACE("ENDSTR ");
+ BEGIN prev_state;
+
+ if (sudoerslval.string == NULL) {
+ sudoers_errstr = N_("empty string");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ if (prev_state == INITIAL || prev_state == GOTDEFS) {
+ switch (sudoerslval.string[0]) {
+ case '%':
+ if (sudoerslval.string[1] == '\0' ||
+ (sudoerslval.string[1] == ':' &&
+ sudoerslval.string[2] == '\0')) {
+ parser_leak_remove(LEAK_PTR, sudoerslval.string);
+ free(sudoerslval.string);
+ sudoers_errstr = N_("empty group");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ LEXTRACE("USERGROUP ");
+ return USERGROUP;
+ case '+':
+ if (sudoerslval.string[1] == '\0') {
+ parser_leak_remove(LEAK_PTR, sudoerslval.string);
+ free(sudoerslval.string);
+ sudoers_errstr = N_("empty netgroup");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ LEXTRACE("NETGROUP ");
+ return NETGROUP;
+ }
+ }
+ LEXTRACE("WORD(4) ");
+ return WORD;
+ }
+
+ \\ {
+ LEXTRACE("BACKSLASH ");
+ if (!append(sudoerstext, sudoersleng))
+ yyterminate();
+ }
+
+ ([^\"\r\n\\]|\\\")+ {
+ LEXTRACE("STRBODY ");
+ if (!append(sudoerstext, sudoersleng))
+ yyterminate();
+ }
+}
+
+<GOTCMND>{
+ \\[\*\?\[\]\!^] {
+ /* quoted fnmatch glob char, pass verbatim */
+ LEXTRACE("QUOTEDCHAR ");
+ if (!fill_args(sudoerstext, 2, sawspace))
+ yyterminate();
+ sawspace = false;
+ }
+
+ \\[:\\,= \t#] {
+ /* quoted sudoers special char, strip backslash */
+ LEXTRACE("QUOTEDCHAR ");
+ if (!fill_args(sudoerstext + 1, 1, sawspace))
+ yyterminate();
+ sawspace = false;
+ }
+
+ [#:\,=\r\n] {
+ BEGIN INITIAL;
+ sudoersless(0);
+ yy_set_bol(0);
+ return COMMAND;
+ } /* end of command line args */
+
+ [^#\\:, \t\r\n]+ {
+ if (sudoerslval.command.args == NULL && sudoerstext[0] == '^') {
+ LEXTRACE("ARG REGEX ");
+ BEGIN GOTREGEX;
+ sudoersless(0);
+ yy_set_bol(0);
+ } else {
+ LEXTRACE("ARG ");
+ if (!fill_args(sudoerstext, sudoersleng, sawspace))
+ yyterminate();
+ sawspace = false;
+ }
+ } /* a command line arg */
+}
+
+<GOTREGEX>{
+ \\[^\r\n] {
+ /* quoted character, pass verbatim */
+ LEXTRACE("QUOTEDCHAR ");
+ if (!fill_args(sudoerstext, 2, false))
+ yyterminate();
+ }
+
+ [#\r\n] {
+ /* Let the parser attempt to recover. */
+ sudoersless(0);
+ yy_set_bol(0);
+ BEGIN INITIAL;
+
+ sudoers_errstr = N_("unterminated regular expression");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ } /* illegal inside regex */
+
+ \$ {
+ if (!fill_args("$", 1, false))
+ yyterminate();
+ BEGIN INITIAL;
+ continued = false;
+ if (sudoers_strict()) {
+ if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) {
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ }
+ return COMMAND;
+ }
+
+ [^#\\\r\n$]+ {
+ if (continued) {
+ /* remove whitespace after line continuation */
+ while (isblank((unsigned char)*sudoerstext)) {
+ sudoerstext++;
+ sudoersleng--;
+ }
+ continued = false;
+ }
+ if (sudoersleng != 0) {
+ if (!fill_args(sudoerstext, sudoersleng, false))
+ yyterminate();
+ }
+ }
+}
+
+<WANTDIGEST>[[:xdigit:]]+ {
+ /* Only return DIGEST if the length is correct. */
+ size_t digest_len =
+ sudo_digest_getlen(digest_type);
+ if ((size_t)sudoersleng == digest_len * 2) {
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ BEGIN INITIAL;
+ LEXTRACE("DIGEST ");
+ return DIGEST;
+ }
+ BEGIN INITIAL;
+ sudoersless(sudoersleng);
+ } /* hex digest */
+
+<WANTDIGEST>[A-Za-z0-9\+/=]+ {
+ /* Only return DIGEST if the length is correct. */
+ size_t len, digest_len =
+ sudo_digest_getlen(digest_type);
+ if (sudoerstext[sudoersleng - 1] == '=') {
+ /* use padding */
+ len = 4 * ((digest_len + 2) / 3);
+ } else {
+ /* no padding */
+ len = (4 * digest_len + 2) / 3;
+ }
+ if ((size_t)sudoersleng == len) {
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ BEGIN INITIAL;
+ LEXTRACE("DIGEST ");
+ return DIGEST;
+ }
+ BEGIN INITIAL;
+ sudoersless(sudoersleng);
+ } /* base64 digest */
+
+<INITIAL>@include {
+ if (continued) {
+ sudoers_errstr = N_("invalid line continuation");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+
+ BEGIN GOTINC;
+ LEXTRACE("INCLUDE ");
+ return INCLUDE;
+ }
+
+<INITIAL>@includedir {
+ if (continued) {
+ sudoers_errstr = N_("invalid line continuation");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+
+ BEGIN GOTINC;
+ LEXTRACE("INCLUDEDIR ");
+ return INCLUDEDIR;
+ }
+
+<INITIAL>^#include[[:blank:]]+.*(\r\n|\n)? {
+ if (continued) {
+ sudoers_errstr = N_("invalid line continuation");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+
+ /* only consume #include */
+ sudoersless(sizeof("#include") - 1);
+ yy_set_bol(0);
+
+ BEGIN GOTINC;
+ LEXTRACE("INCLUDE ");
+ return INCLUDE;
+ }
+
+<INITIAL>^#includedir[[:blank:]]+.*(\r\n|\n)? {
+ if (continued) {
+ sudoers_errstr = N_("invalid line continuation");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+
+ /* only consume #includedir */
+ sudoersless(sizeof("#includedir") - 1);
+ yy_set_bol(0);
+
+ BEGIN GOTINC;
+ LEXTRACE("INCLUDEDIR ");
+ return INCLUDEDIR;
+ }
+
+<INITIAL>^[[:blank:]]*Defaults([:@>\!][[:blank:]]*\!*\"?({ID}|{WORD}))? {
+ char deftype;
+ size_t n;
+
+ if (continued) {
+ sudoers_errstr = N_("invalid line continuation");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+
+ for (n = 0; isblank((unsigned char)sudoerstext[n]); n++)
+ continue;
+ n += sizeof("Defaults") - 1;
+ if ((deftype = sudoerstext[n++]) != '\0') {
+ while (isblank((unsigned char)sudoerstext[n]))
+ n++;
+ }
+ BEGIN GOTDEFS;
+ switch (deftype) {
+ case ':':
+ sudoersless(n);
+ LEXTRACE("DEFAULTS_USER ");
+ return DEFAULTS_USER;
+ case '>':
+ sudoersless(n);
+ LEXTRACE("DEFAULTS_RUNAS ");
+ return DEFAULTS_RUNAS;
+ case '@':
+ sudoersless(n);
+ LEXTRACE("DEFAULTS_HOST ");
+ return DEFAULTS_HOST;
+ case '!':
+ sudoersless(n);
+ LEXTRACE("DEFAULTS_CMND ");
+ return DEFAULTS_CMND;
+ default:
+ LEXTRACE("DEFAULTS ");
+ return DEFAULTS;
+ }
+ }
+
+<INITIAL>^[[:blank:]]*(Host|Cmnd|Cmd|User|Runas)_Alias {
+ size_t n;
+
+ if (continued) {
+ sudoers_errstr = N_("invalid line continuation");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+
+ for (n = 0; isblank((unsigned char)sudoerstext[n]); n++)
+ continue;
+ switch (sudoerstext[n]) {
+ case 'H':
+ LEXTRACE("HOSTALIAS ");
+ return HOSTALIAS;
+ case 'C':
+ LEXTRACE("CMNDALIAS ");
+ return CMNDALIAS;
+ case 'U':
+ LEXTRACE("USERALIAS ");
+ return USERALIAS;
+ case 'R':
+ LEXTRACE("RUNASALIAS ");
+ return RUNASALIAS;
+ }
+ }
+
+NOPASSWD[[:blank:]]*: {
+ /* cmnd does not require passwd for this user */
+ LEXTRACE("NOPASSWD ");
+ return NOPASSWD;
+ }
+
+PASSWD[[:blank:]]*: {
+ /* cmnd requires passwd for this user */
+ LEXTRACE("PASSWD ");
+ return PASSWD;
+ }
+
+NOEXEC[[:blank:]]*: {
+ LEXTRACE("NOEXEC ");
+ return NOEXEC;
+ }
+
+EXEC[[:blank:]]*: {
+ LEXTRACE("EXEC ");
+ return EXEC;
+ }
+
+INTERCEPT[[:blank:]]*: {
+ LEXTRACE("INTERCEPT ");
+ return INTERCEPT;
+ }
+
+NOINTERCEPT[[:blank:]]*: {
+ LEXTRACE("NOINTERCEPT ");
+ return NOINTERCEPT;
+ }
+
+SETENV[[:blank:]]*: {
+ LEXTRACE("SETENV ");
+ return SETENV;
+ }
+
+NOSETENV[[:blank:]]*: {
+ LEXTRACE("NOSETENV ");
+ return NOSETENV;
+ }
+
+LOG_OUTPUT[[:blank:]]*: {
+ LEXTRACE("LOG_OUTPUT ");
+ return LOG_OUTPUT;
+ }
+
+NOLOG_OUTPUT[[:blank:]]*: {
+ LEXTRACE("NOLOG_OUTPUT ");
+ return NOLOG_OUTPUT;
+ }
+
+LOG_INPUT[[:blank:]]*: {
+ LEXTRACE("LOG_INPUT ");
+ return LOG_INPUT;
+ }
+
+NOLOG_INPUT[[:blank:]]*: {
+ LEXTRACE("NOLOG_INPUT ");
+ return NOLOG_INPUT;
+ }
+
+MAIL[[:blank:]]*: {
+ LEXTRACE("MAIL ");
+ return MAIL;
+ }
+
+NOMAIL[[:blank:]]*: {
+ LEXTRACE("NOMAIL ");
+ return NOMAIL;
+ }
+
+FOLLOW[[:blank:]]*: {
+ LEXTRACE("FOLLOW ");
+ return FOLLOWLNK;
+ }
+
+NOFOLLOW[[:blank:]]*: {
+ LEXTRACE("NOFOLLOW ");
+ return NOFOLLOWLNK;
+ }
+
+<INITIAL,GOTDEFS>(\+|\%|\%:) {
+ if (sudoerstext[0] == '+')
+ sudoers_errstr = N_("empty netgroup");
+ else
+ sudoers_errstr = N_("empty group");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+
+\+{WORD} {
+ /* netgroup */
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("NETGROUP ");
+ return NETGROUP;
+ }
+
+\%:?({WORD}|{ID}) {
+ /* group */
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("USERGROUP ");
+ return USERGROUP;
+ }
+
+{IPV4ADDR}(\/{IPV4ADDR})? {
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("NTWKADDR ");
+ return NTWKADDR;
+ }
+
+{IPV4ADDR}\/([12]?[0-9]|3[0-2]) {
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("NTWKADDR ");
+ return NTWKADDR;
+ }
+
+{IPV6ADDR}(\/{IPV6ADDR})? {
+ if (!ipv6_valid(sudoerstext)) {
+ sudoers_errstr = N_("invalid IPv6 address");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("NTWKADDR ");
+ return NTWKADDR;
+ }
+
+{IPV6ADDR}\/([0-9]|[1-9][0-9]|1[01][0-9]|12[0-8]) {
+ if (!ipv6_valid(sudoerstext)) {
+ sudoers_errstr = N_("invalid IPv6 address");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("NTWKADDR ");
+ return NTWKADDR;
+ }
+
+ALL {
+ LEXTRACE("ALL ");
+ return ALL;
+
+ }
+
+<INITIAL>TIMEOUT {
+ LEXTRACE("CMND_TIMEOUT ");
+ return CMND_TIMEOUT;
+ }
+
+<INITIAL>NOTBEFORE {
+ LEXTRACE("NOTBEFORE ");
+ return NOTBEFORE;
+ }
+
+<INITIAL>NOTAFTER {
+ LEXTRACE("NOTAFTER ");
+ return NOTAFTER;
+ }
+
+<INITIAL>CWD {
+ LEXTRACE("CWD ");
+ prev_state = YY_START;
+ BEGIN EXPECTPATH;
+ return CWD;
+ }
+
+<INITIAL>CHROOT {
+ LEXTRACE("CHROOT ");
+ prev_state = YY_START;
+ BEGIN EXPECTPATH;
+ return CHROOT;
+ }
+
+<INITIAL>ROLE {
+#ifdef HAVE_SELINUX
+ LEXTRACE("ROLE ");
+ return ROLE;
+#else
+ goto got_alias;
+#endif
+ }
+
+<INITIAL>TYPE {
+#ifdef HAVE_SELINUX
+ LEXTRACE("TYPE ");
+ return TYPE;
+#else
+ goto got_alias;
+#endif
+ }
+<INITIAL>APPARMOR_PROFILE {
+#ifdef HAVE_APPARMOR
+ LEXTRACE("APPARMOR_PROFILE ");
+ return APPARMOR_PROFILE;
+#else
+ goto got_alias;
+#endif
+ }
+<INITIAL>PRIVS {
+#ifdef HAVE_PRIV_SET
+ LEXTRACE("PRIVS ");
+ return PRIVS;
+#else
+ goto got_alias;
+#endif
+ }
+
+<INITIAL>LIMITPRIVS {
+#ifdef HAVE_PRIV_SET
+ LEXTRACE("LIMITPRIVS ");
+ return LIMITPRIVS;
+#else
+ goto got_alias;
+#endif
+ }
+
+[[:upper:]][[:upper:][:digit:]_]* {
+ got_alias:
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("ALIAS ");
+ return ALIAS;
+ }
+
+<GOTDEFS>({PATH}|{REGEX}|sudoedit) {
+ /* XXX - no way to specify digest for command */
+ /* no command args allowed for Defaults!/path */
+ if (!fill_cmnd(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("COMMAND ");
+ return COMMAND;
+ }
+
+sha224 {
+ digest_type = SUDO_DIGEST_SHA224;
+ BEGIN WANTDIGEST;
+ LEXTRACE("SHA224_TOK ");
+ return SHA224_TOK;
+ }
+
+sha256 {
+ digest_type = SUDO_DIGEST_SHA256;
+ BEGIN WANTDIGEST;
+ LEXTRACE("SHA256_TOK ");
+ return SHA256_TOK;
+ }
+
+sha384 {
+ digest_type = SUDO_DIGEST_SHA384;
+ BEGIN WANTDIGEST;
+ LEXTRACE("SHA384_TOK ");
+ return SHA384_TOK;
+ }
+
+sha512 {
+ digest_type = SUDO_DIGEST_SHA512;
+ BEGIN WANTDIGEST;
+ LEXTRACE("SHA512_TOK ");
+ return SHA512_TOK;
+ }
+
+sudoedit {
+ BEGIN GOTCMND;
+ LEXTRACE("COMMAND ");
+ if (!fill_cmnd(sudoerstext, sudoersleng))
+ yyterminate();
+ } /* sudo -e */
+
+<EXPECTPATH>({PATH}|{WORD}) {
+ BEGIN prev_state;
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("WORD(5) ");
+ return WORD;
+ }
+
+{PATH} {
+ /* directories can't have args... */
+ if (sudoerstext[sudoersleng - 1] == '/') {
+ LEXTRACE("COMMAND ");
+ if (!fill_cmnd(sudoerstext, sudoersleng))
+ yyterminate();
+ return COMMAND;
+ }
+ BEGIN GOTCMND;
+ LEXTRACE("COMMAND ");
+ if (!fill_cmnd(sudoerstext, sudoersleng))
+ yyterminate();
+ } /* a pathname */
+
+{REGEX} {
+ if (sudoers_strict()) {
+ if (!sudo_regex_compile(NULL, sudoerstext, &sudoers_errstr)) {
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ }
+ BEGIN GOTCMND;
+ LEXTRACE("COMMAND ");
+ if (!fill_cmnd(sudoerstext, sudoersleng))
+ yyterminate();
+ } /* a regex */
+
+<INITIAL,GOTDEFS>\" {
+ LEXTRACE("BEGINSTR ");
+ sudoerslval.string = NULL;
+ prev_state = YY_START;
+ BEGIN INSTR;
+ }
+
+<INITIAL,GOTDEFS>({ID}|{WORD}) {
+ /* a word */
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ LEXTRACE("WORD(6) ");
+ return WORD;
+ }
+
+<GOTINC>{
+ [^\"[:space:]]([^[:space:]]|\\[[:blank:]])* {
+ /* include file/directory */
+ if (!fill(sudoerstext, sudoersleng))
+ yyterminate();
+ BEGIN INITIAL;
+ LEXTRACE("WORD(7) ");
+ return WORD;
+ }
+
+ \" {
+ LEXTRACE("BEGINSTR ");
+ sudoerslval.string = NULL;
+ prev_state = INITIAL;
+ BEGIN INSTR;
+ }
+}
+
+\( {
+ LEXTRACE("( ");
+ return '(';
+ }
+
+\) {
+ LEXTRACE(") ");
+ return ')';
+ }
+
+, {
+ LEXTRACE(", ");
+ return ',';
+ } /* return ',' */
+
+= {
+ LEXTRACE("= ");
+ return '=';
+ } /* return '=' */
+
+: {
+ LEXTRACE(": ");
+ return ':';
+ } /* return ':' */
+
+<*>!+ {
+ if (sudoersleng & 1) {
+ LEXTRACE("!");
+ return '!'; /* return '!' */
+ }
+ }
+
+<*>\r?\n {
+ if (YY_START == INSTR) {
+ /* throw away old string */
+ parser_leak_remove(LEAK_PTR, sudoerslval.string);
+ free(sudoerslval.string);
+ /* re-scan after changing state */
+ BEGIN INITIAL;
+ sudoersless(0);
+ sudoers_errstr = N_("unexpected line break in string");
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ BEGIN INITIAL;
+ sudolineno++;
+ continued = false;
+ LEXTRACE("\n");
+ return '\n';
+ } /* return newline */
+
+<*>[[:blank:]]+ { /* throw away space/tabs */
+ sawspace = true; /* but remember for fill_args */
+ }
+
+<*>\\[[:blank:]]*\r?\n {
+ sawspace = true; /* remember for fill_args */
+ sudolineno++;
+ continued = true;
+ } /* throw away EOL after \ */
+
+<INITIAL,STARTDEFS,INDEFS>#(-[^\r\n0-9].*|[^\r\n0-9-].*)?(\r\n|\n)? {
+ if (sudoerstext[sudoersleng - 1] == '\n') {
+ /* comment ending in a newline */
+ BEGIN INITIAL;
+ sudolineno++;
+ continued = false;
+ } else if (!feof(sudoersin)) {
+ sudoers_errstr = strerror(errno);
+ LEXTRACE("ERROR ");
+ return ERROR;
+ }
+ LEXTRACE("#\n");
+ return '\n';
+ } /* comment, not uid/gid */
+
+<*>. {
+ LEXTRACE("NOMATCH ");
+ return NOMATCH;
+ } /* parse error, no matching token */
+
+<*><<EOF>> {
+ if (!pop_include())
+ yyterminate();
+ }
+
+%%
+struct path_list {
+ SLIST_ENTRY(path_list) entries;
+ char *path;
+};
+
+SLIST_HEAD(path_list_head, path_list);
+
+struct include_stack {
+ struct sudolinebuf line;
+ YY_BUFFER_STATE bs;
+ char *path; /* search path */
+ char *file;
+ struct path_list_head more; /* more files in case of includedir */
+ int lineno;
+ bool keepopen;
+};
+
+/*
+ * Compare two struct path_list structs in reverse order.
+ */
+static int
+pl_compare(const void *v1, const void *v2)
+{
+ const struct path_list * const *p1 = v1;
+ const struct path_list * const *p2 = v2;
+
+ return strcmp((*p2)->path, (*p1)->path);
+}
+
+/*
+ * Open dirpath and fill in pathsp with an array of regular files
+ * that do not end in '~' or contain a '.'.
+ * Returns the number of files or SIZE_MAX (-1) on error.
+ * If zero files are found, NULL is stored in pathsp.
+ */
+static size_t
+read_dir_files(const char *dirpath, struct path_list ***pathsp, int verbose)
+{
+ DIR *dir;
+ size_t i, count = 0;
+ size_t max_paths = 32;
+ struct dirent *dent;
+ struct path_list **paths = NULL;
+ const size_t dirlen = strlen(dirpath);
+ debug_decl(read_dir_files, SUDOERS_DEBUG_PARSER);
+
+ /* XXX - fdopendir */
+ dir = opendir(dirpath);
+ if (dir == NULL) {
+ if (errno == ENOENT)
+ goto done;
+ sudo_warn("%s", dirpath);
+ goto bad;
+ }
+ paths = reallocarray(NULL, max_paths, sizeof(*paths));
+ if (paths == NULL)
+ goto oom;
+ while ((dent = readdir(dir)) != NULL) {
+ const size_t namelen = NAMLEN(dent);
+ const char *name = dent->d_name;
+ struct path_list *pl;
+ struct stat sb;
+ size_t len;
+ char *path;
+
+ /* Ignore files that end in '~' or have a '.' in them. */
+ if (namelen == 0 || name[namelen - 1] == '~' || strchr(name, '.') != NULL) {
+ /* Warn about ignored files not starting with '.' if verbose. */
+ if (namelen > 0 && name[0] != '.' && verbose > 1) {
+ if (name[namelen - 1] == '~' ||
+ (namelen > 4 && strcmp(&name[namelen - 4], ".bak") == 0)) {
+ fprintf(stderr, U_("%s/%s: %s"), dirpath, name,
+ U_("ignoring editor backup file"));
+ } else {
+ fprintf(stderr, U_("%s/%s: %s"), dirpath, name,
+ U_("ignoring file name containing '.'"));
+ }
+ fputc('\n', stderr);
+ }
+ continue;
+ }
+ len = dirlen + 1 + namelen;
+ if ((path = sudo_rcstr_alloc(len)) == NULL)
+ goto oom;
+ if ((size_t)snprintf(path, len + 1, "%s/%s", dirpath, name) != len) {
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ sudo_rcstr_delref(path);
+ goto bad;
+ }
+ if (stat(path, &sb) != 0 || !S_ISREG(sb.st_mode)) {
+ sudo_rcstr_delref(path);
+ continue;
+ }
+ pl = malloc(sizeof(*pl));
+ if (pl == NULL) {
+ sudo_rcstr_delref(path);
+ goto oom;
+ }
+ pl->path = path;
+ if (count >= max_paths) {
+ struct path_list **tmp;
+ max_paths <<= 1;
+ tmp = reallocarray(paths, max_paths, sizeof(*paths));
+ if (tmp == NULL) {
+ sudo_rcstr_delref(path);
+ free(pl);
+ goto oom;
+ }
+ paths = tmp;
+ }
+ paths[count++] = pl;
+ }
+ closedir(dir);
+ if (count == 0) {
+ free(paths);
+ paths = NULL;
+ }
+done:
+ *pathsp = paths;
+ debug_return_size_t(count);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+bad:
+ sudoerserror(NULL);
+ if (dir != NULL)
+ closedir(dir);
+ for (i = 0; i < count; i++) {
+ sudo_rcstr_delref(paths[i]->path);
+ free(paths[i]);
+ }
+ free(paths);
+ debug_return_size_t(SIZE_MAX);
+}
+
+/*
+ * Push a list of all files in dirpath onto stack.
+ * Returns the number of files or -1 on error.
+ */
+static size_t
+switch_dir(struct include_stack *stack, char *dirpath, int verbose)
+{
+ struct path_list **paths = NULL;
+ size_t count, i;
+ debug_decl(switch_dir, SUDOERS_DEBUG_PARSER);
+
+ count = read_dir_files(dirpath, &paths, verbose);
+ if (count > 0) {
+ /* Sort the list as an array in reverse order. */
+ qsort(paths, count, sizeof(*paths), pl_compare);
+
+ /* Build up the list in sorted order. */
+ for (i = 0; i < count; i++) {
+ SLIST_INSERT_HEAD(&stack->more, paths[i], entries);
+ }
+ free(paths);
+ }
+
+ debug_return_size_t(count);
+}
+
+#define MAX_SUDOERS_DEPTH 128
+#define SUDOERS_STACK_INCREMENT 16
+
+static size_t istacksize, idepth;
+static struct include_stack *istack;
+static bool keepopen;
+
+void
+init_lexer(void)
+{
+ struct path_list *pl;
+ debug_decl(init_lexer, SUDOERS_DEBUG_PARSER);
+
+#ifndef TRACELEXER
+ free(trace_lbuf.buf);
+ sudo_lbuf_init(&trace_lbuf, NULL, 0, NULL, 0);
+#endif
+
+ while (idepth) {
+ idepth--;
+ while ((pl = SLIST_FIRST(&istack[idepth].more)) != NULL) {
+ SLIST_REMOVE_HEAD(&istack[idepth].more, entries);
+ sudo_rcstr_delref(pl->path);
+ free(pl);
+ }
+ sudo_rcstr_delref(istack[idepth].path);
+ if (idepth && !istack[idepth].keepopen)
+ fclose(istack[idepth].bs->yy_input_file);
+ sudoers_delete_buffer(istack[idepth].bs);
+ free(istack[idepth].line.buf);
+ }
+ free(istack);
+ istack = NULL;
+ istacksize = idepth = 0;
+ free(sudolinebuf.buf);
+ memset(&sudolinebuf, 0, sizeof(sudolinebuf));
+ sudolineno = 1;
+ keepopen = false;
+ sawspace = false;
+ continued = false;
+ digest_type = SUDO_DIGEST_INVALID;
+ prev_state = INITIAL;
+ BEGIN INITIAL;
+
+ debug_return;
+}
+
+/*
+ * Like strlcpy() but expand %h escapes.
+ */
+static size_t
+strlcpy_expand_host(char * restrict dst, const char * restrict src,
+ const char * restrict host, size_t size)
+{
+ size_t len = 0;
+ char ch;
+ debug_decl(strlcpy_expand_host, SUDOERS_DEBUG_PARSER);
+
+ while ((ch = *src++) != '\0') {
+ if (ch == '%' && *src == 'h') {
+ size_t n = strlcpy(dst, host, size);
+ len += n;
+ if (n >= size) {
+ /* truncated */
+ n = size ? size - 1 : 0;
+ }
+ dst += n;
+ size -= n;
+ src++;
+ continue;
+ }
+ if (size > 1) {
+ *dst++ = ch;
+ size--;
+ len++;
+ }
+ }
+ if (size > 0)
+ *dst = '\0';
+
+ debug_return_size_t(len);
+}
+
+/*
+ * Expand any embedded %h (host) escapes in the given path and makes
+ * a relative path fully-qualified based on the current sudoers file.
+ * Returns a reference-counted string on success or NULL on failure.
+ */
+static char *
+expand_include(const char *src, const char *host)
+{
+ const char *path = sudoers_search_path ? sudoers_search_path : sudoers;
+ const char *path_end = path + strlen(path);
+ char *dst, *dst0 = NULL, *dynamic_host = NULL;
+ const char *cp, *ep;
+ size_t dst_size, src_len;
+ size_t nhost = 0;
+ debug_decl(expand_include, SUDOERS_DEBUG_PARSER);
+
+ /* Strip double quotes if present. */
+ src_len = strlen(src);
+ if (src_len > 1 && src[0] == '"' && src[src_len - 1] == '"') {
+ src++;
+ src_len -= 2;
+ }
+ if (src_len == 0)
+ debug_return_ptr(NULL);
+
+ /* Check for %h escapes in src. */
+ cp = src;
+ ep = src + src_len;
+ while (cp < ep) {
+ if (cp[0] == '%' && cp[1] == 'h') {
+ nhost++;
+ cp += 2;
+ continue;
+ }
+ cp++;
+ }
+
+ /* Check for a path separator in the host name, replace with '_'. */
+ if (nhost != 0 && strchr(host, '/') != NULL) {
+ dynamic_host = malloc(strlen(host) + 1);
+ if (dynamic_host == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ for (dst = dynamic_host; *host != '\0'; host++) {
+ if (*host == '/') {
+ *dst++ = '_';
+ continue;
+ }
+ *dst++ = *host;
+ }
+ *dst = '\0';
+ host = dynamic_host;
+ }
+
+ if (*src == '/') {
+ /* Fully-qualified path, make a copy and expand %h escapes. */
+ dst_size = src_len + (nhost * strlen(host)) - (nhost * 2) + 1;
+ dst0 = sudo_rcstr_alloc(dst_size - 1);
+ if (dst0 == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ if (strlcpy_expand_host(dst0, src, host, dst_size) >= dst_size)
+ goto oflow;
+ goto done;
+ }
+
+ /*
+ * Relative paths are located in the same dir as the sudoers file.
+ * If the current sudoers file was opened via a colon-separated path,
+ * use the same path when opening src.
+ */
+ dst_size = 0;
+ for (cp = sudo_strsplit(path, path_end, ":", &ep); cp != NULL;
+ cp = sudo_strsplit(NULL, path_end, ":", &ep)) {
+ char *dirend = memrchr(cp, '/', (size_t)(ep - cp));
+ if (dirend != NULL) {
+ dst_size += (size_t)(dirend - cp) + 1;
+ }
+ /* Includes space for ':' separator and NUL terminator. */
+ dst_size += src_len + (nhost * strlen(host)) - (nhost * 2) + 1;
+ }
+
+ /* Make a copy of the fully-qualified path and return it. */
+ dst = dst0 = sudo_rcstr_alloc(dst_size - 1);
+ if (dst0 == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ for (cp = sudo_strsplit(path, path_end, ":", &ep); cp != NULL;
+ cp = sudo_strsplit(NULL, path_end, ":", &ep)) {
+ size_t len;
+ char *dirend;
+
+ if (cp != path) {
+ if (dst_size < 2)
+ goto oflow;
+ *dst++ = ':';
+ dst_size--;
+ }
+
+ dirend = memrchr(cp, '/', (size_t)(ep - cp));
+ if (dirend != NULL) {
+ len = (size_t)(dirend - cp) + 1;
+ if (len >= dst_size)
+ goto oflow;
+ memcpy(dst, cp, len);
+ dst += len;
+ dst_size -= len;
+ }
+
+ len = strlcpy_expand_host(dst, src, host, dst_size);
+ if (len >= dst_size)
+ goto oflow;
+ dst += len;
+ dst_size -= len;
+ }
+ *dst = '\0';
+
+done:
+ free(dynamic_host);
+ debug_return_str(dst0);
+oflow:
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+bad:
+ sudoerserror(NULL);
+ free(dynamic_host);
+ free(dst0);
+ debug_return_str(NULL);
+}
+
+/*
+ * Open an include file (or file from a directory), push the old
+ * sudoers file buffer and switch to the new one.
+ * A missing or insecure include dir is simply ignored.
+ * Returns false on error, else true.
+ */
+static bool
+push_include_int(const char *opath, const char *host, bool isdir,
+ struct sudoers_parser_config *conf)
+{
+ struct path_list *pl;
+ char *file = NULL, *path;
+ FILE *fp;
+ debug_decl(push_include, SUDOERS_DEBUG_PARSER);
+
+ if ((path = expand_include(opath, host)) == NULL)
+ debug_return_bool(false);
+
+ /* push current state onto stack */
+ if (idepth >= istacksize) {
+ struct include_stack *new_istack;
+
+ if (idepth > MAX_SUDOERS_DEPTH) {
+ if (conf->verbose > 0) {
+ fprintf(stderr, U_("%s: %s"), path,
+ U_("too many levels of includes"));
+ fputc('\n', stderr);
+ }
+ sudoerserror(NULL);
+ sudo_rcstr_delref(path);
+ debug_return_bool(false);
+ }
+ istacksize += SUDOERS_STACK_INCREMENT;
+ new_istack = reallocarray(istack, istacksize, sizeof(*istack));
+ if (new_istack == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ sudoerserror(NULL);
+ sudo_rcstr_delref(path);
+ debug_return_bool(false);
+ }
+ istack = new_istack;
+ }
+ SLIST_INIT(&istack[idepth].more);
+ if (isdir) {
+ struct stat sb;
+ char dname[PATH_MAX];
+ int fd, status;
+ size_t count;
+
+ fd = sudo_open_conf_path(path, dname, sizeof(dname), NULL);
+ if (conf->ignore_perms) {
+ /* Skip sudoers security checks when ignore_perms is set. */
+ if (fd == -1 || fstat(fd, &sb) == -1)
+ status = SUDO_PATH_MISSING;
+ else
+ status = SUDO_PATH_SECURE;
+ } else {
+ status = sudo_secure_fd(fd, S_IFDIR, sudoers_file_uid(),
+ sudoers_file_gid(), &sb);
+ }
+ if (fd != -1)
+ close(fd); /* XXX use in read_dir_files? */
+ if (status != SUDO_PATH_SECURE) {
+ if (conf->verbose > 0) {
+ switch (status) {
+ case SUDO_PATH_BAD_TYPE:
+ errno = ENOTDIR;
+ sudo_warn("%s", path);
+ break;
+ case SUDO_PATH_WRONG_OWNER:
+ sudo_warnx(U_("%s is owned by uid %u, should be %u"),
+ path, (unsigned int) sb.st_uid,
+ (unsigned int) sudoers_file_uid());
+ break;
+ case SUDO_PATH_WORLD_WRITABLE:
+ sudo_warnx(U_("%s is world writable"), path);
+ break;
+ case SUDO_PATH_GROUP_WRITABLE:
+ sudo_warnx(U_("%s is owned by gid %u, should be %u"),
+ path, (unsigned int) sb.st_gid,
+ (unsigned int) sudoers_file_gid());
+ break;
+ default:
+ break;
+ }
+ }
+ /* A missing or insecure include dir is not a fatal error. */
+ sudo_rcstr_delref(path);
+ debug_return_bool(true);
+ }
+ count = switch_dir(&istack[idepth], dname, conf->verbose);
+ switch (count) {
+ case SIZE_MAX:
+ case 0:
+ /* switch_dir() called sudoerserror() for us */
+ sudo_rcstr_delref(path);
+ debug_return_bool(count ? false : true);
+ }
+
+ /* Parse the first dir entry we can open, leave the rest for later. */
+ do {
+ sudo_rcstr_delref(file);
+ sudo_rcstr_delref(path);
+ if ((pl = SLIST_FIRST(&istack[idepth].more)) == NULL) {
+ /* Unable to open any files in include dir, not an error. */
+ debug_return_bool(true);
+ }
+ SLIST_REMOVE_HEAD(&istack[idepth].more, entries);
+ path = pl->path;
+ free(pl);
+ /* The file and path and the same for sudoers.d files. */
+ file = path;
+ sudo_rcstr_addref(file);
+ } while ((fp = open_sudoers(file, NULL, false, &keepopen)) == NULL);
+ } else {
+ if ((fp = open_sudoers(path, &file, true, &keepopen)) == NULL) {
+ /* The error was already printed by open_sudoers() */
+ sudoerserror(NULL);
+ sudo_rcstr_delref(path);
+ debug_return_bool(false);
+ }
+ }
+ /*
+ * Push the old (current) file and open the new one.
+ * We use the existing refs of sudoers and sudoers_search_path.
+ */
+ istack[idepth].file = sudoers;
+ istack[idepth].path = sudoers_search_path;
+ istack[idepth].line = sudolinebuf;
+ istack[idepth].bs = YY_CURRENT_BUFFER;
+ istack[idepth].lineno = sudolineno;
+ istack[idepth].keepopen = keepopen;
+ idepth++;
+ sudolineno = 1;
+ sudoers = file;
+ sudoers_search_path = path;
+ sudoers_switch_to_buffer(sudoers_create_buffer(fp, YY_BUF_SIZE));
+ memset(&sudolinebuf, 0, sizeof(sudolinebuf));
+
+ debug_return_bool(true);
+}
+
+bool
+push_include(const char *opath, const char *host,
+ struct sudoers_parser_config *conf)
+{
+ return push_include_int(opath, host, false, conf);
+}
+
+bool
+push_includedir(const char *opath, const char *host,
+ struct sudoers_parser_config *conf)
+{
+ return push_include_int(opath, host, true, conf);
+}
+
+/*
+ * Restore the previous sudoers file and buffer, or, in the case
+ * of an includedir, switch to the next file in the dir.
+ * Returns false if there is nothing to pop, else true.
+ */
+static bool
+pop_include(void)
+{
+ struct path_list *pl;
+ FILE *fp;
+ debug_decl(pop_include, SUDOERS_DEBUG_PARSER);
+
+ if (idepth == 0 || YY_CURRENT_BUFFER == NULL)
+ debug_return_bool(false);
+
+ if (!keepopen)
+ fclose(YY_CURRENT_BUFFER->yy_input_file);
+ sudoers_delete_buffer(YY_CURRENT_BUFFER);
+ /* If we are in an include dir, move to the next file. */
+ while ((pl = SLIST_FIRST(&istack[idepth - 1].more)) != NULL) {
+ SLIST_REMOVE_HEAD(&istack[idepth - 1].more, entries);
+ fp = open_sudoers(pl->path, NULL, false, &keepopen);
+ if (fp != NULL) {
+ sudolinebuf.len = sudolinebuf.off = 0;
+ sudolinebuf.toke_start = sudolinebuf.toke_end = 0;
+ sudo_rcstr_delref(sudoers);
+ sudo_rcstr_delref(sudoers_search_path);
+ sudoers_search_path = pl->path;
+ sudoers = sudoers_search_path;
+ sudo_rcstr_addref(sudoers);
+ sudolineno = 1;
+ sudoers_switch_to_buffer(sudoers_create_buffer(fp, YY_BUF_SIZE));
+ free(pl);
+ break;
+ }
+ /* Unable to open path in include dir, go to next one. */
+ sudo_rcstr_delref(pl->path);
+ free(pl);
+ }
+ /* If no path list, just pop the last dir on the stack. */
+ if (pl == NULL) {
+ idepth--;
+ sudoers_switch_to_buffer(istack[idepth].bs);
+ free(sudolinebuf.buf);
+ sudolinebuf = istack[idepth].line;
+ sudo_rcstr_delref(sudoers);
+ sudoers = istack[idepth].file;
+ sudo_rcstr_delref(sudoers_search_path);
+ sudoers_search_path = istack[idepth].path;
+ sudolineno = istack[idepth].lineno;
+ keepopen = istack[idepth].keepopen;
+ }
+ debug_return_bool(true);
+}
+
+#ifdef TRACELEXER
+int
+sudoers_trace_print(const char *msg)
+{
+ return fputs(msg, stderr);
+}
+#else
+int
+sudoers_trace_print(const char *msg)
+{
+ debug_decl_vars(sudoers_trace_print, SUDOERS_DEBUG_PARSER);
+
+ if (sudo_debug_needed(SUDO_DEBUG_DEBUG)) {
+ sudo_lbuf_append(&trace_lbuf, "%s", msg);
+ if (strchr(msg, '\n') != NULL)
+ {
+ /* We already parsed the newline so sudolineno is off by one. */
+ sudo_debug_printf2(NULL, NULL, 0,
+ sudo_debug_subsys|SUDO_DEBUG_DEBUG, "sudoerslex: %s:%d: %s",
+ sudoers, sudolineno - 1, trace_lbuf.buf);
+ trace_lbuf.len = 0;
+ }
+ }
+ return 0;
+}
+#endif /* TRACELEXER */
+
+/*
+ * Custom input function that uses getdelim(3) and stores the buffer
+ * where the error functions can access it for better reporting.
+ * On success, buf is guaranteed to end in a newline and not contain
+ * embedded NULs. Calls YY_FATAL_ERROR on error.
+ */
+static int
+sudoers_input(char *buf, yy_size_t max_size)
+{
+ char *cp;
+ size_t avail = sudolinebuf.len - sudolinebuf.off;
+ debug_decl(sudoers_input, SUDOERS_DEBUG_PARSER);
+
+ /* Refill line buffer if needed. */
+ if (avail == 0) {
+ /*
+ * Some getdelim(3) implementations write NUL to buf on EOF.
+ * We peek ahead one char to detect EOF and skip the getdelim() call.
+ * This will preserve the original value of the last line read.
+ */
+ int ch = getc(sudoersin);
+ if (ch == EOF)
+ goto sudoers_eof;
+ ungetc(ch, sudoersin);
+ avail = (size_t)getdelim(&sudolinebuf.buf, &sudolinebuf.size, '\n', sudoersin);
+ if (avail == (size_t)-1) {
+sudoers_eof:
+ /* EOF or error. */
+ if (feof(sudoersin))
+ debug_return_int(0);
+ YY_FATAL_ERROR("input in flex scanner failed");
+ }
+
+ /* getdelim() can return embedded NULs, truncate if we find one. */
+ cp = memchr(sudolinebuf.buf, '\0', avail);
+ if (cp != NULL) {
+ *cp++ = '\n';
+ *cp = '\0';
+ avail = (size_t)(cp - sudolinebuf.buf);
+ }
+
+ /* Add trailing newline if it is missing. */
+ if (sudolinebuf.buf[avail - 1] != '\n') {
+ if (avail + 2 >= sudolinebuf.size) {
+ cp = realloc(sudolinebuf.buf, avail + 2);
+ if (cp == NULL) {
+ YY_FATAL_ERROR("unable to allocate memory");
+ debug_return_int(0);
+ }
+ sudolinebuf.buf = cp;
+ sudolinebuf.size = avail + 2;
+ }
+ sudolinebuf.buf[avail++] = '\n';
+ sudolinebuf.buf[avail] = '\0';
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s:%d: %.*s", sudoers, sudolineno,
+ (int)(avail -1), sudolinebuf.buf);
+
+ sudolinebuf.len = avail;
+ sudolinebuf.off = 0;
+ sudolinebuf.toke_start = sudolinebuf.toke_end = 0;
+ }
+
+ if (avail > max_size)
+ avail = max_size;
+ memcpy(buf, sudolinebuf.buf + sudolinebuf.off, avail);
+ sudolinebuf.off += avail;
+
+ debug_return_int((int)avail);
+}
diff --git a/plugins/sudoers/toke_util.c b/plugins/sudoers/toke_util.c
new file mode 100644
index 0000000..7db07f8
--- /dev/null
+++ b/plugins/sudoers/toke_util.c
@@ -0,0 +1,252 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2007-2016
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <regex.h>
+
+#include <sudoers.h>
+#include <toke.h>
+#include <gram.h>
+
+static size_t arg_len = 0;
+static size_t arg_size = 0;
+
+/*
+ * Copy the string and collapse any escaped characters.
+ * Requires that dst have at least len + 1 bytes free.
+ */
+static void
+copy_string(char *dst, const char *src, size_t len)
+{
+ int h;
+
+ while (len--) {
+ if (*src == '\\' && len) {
+ if (src[1] == 'x' && len >= 3 && (h = sudo_hexchar(src + 2)) != -1) {
+ *dst++ = (char)h;
+ src += 4;
+ len -= 3;
+ } else {
+ src++;
+ len--;
+ *dst++ = *src++;
+ }
+ } else {
+ *dst++ = *src++;
+ }
+ }
+ *dst = '\0';
+}
+
+bool
+fill(const char *src, int ilen)
+{
+ const size_t len = (size_t)ilen;
+ char *dst;
+ debug_decl(fill, SUDOERS_DEBUG_PARSER);
+
+ dst = malloc(len + 1);
+ if (dst == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ sudoerserror(NULL);
+ debug_return_bool(false);
+ }
+ parser_leak_add(LEAK_PTR, dst);
+ copy_string(dst, src, len);
+ sudoerslval.string = dst;
+
+ debug_return_bool(true);
+}
+
+bool
+append(const char *src, int ilen)
+{
+ const size_t len = (size_t)ilen;
+ size_t olen = 0;
+ char *dst;
+ debug_decl(append, SUDOERS_DEBUG_PARSER);
+
+ if (sudoerslval.string != NULL) {
+ olen = strlen(sudoerslval.string);
+ parser_leak_remove(LEAK_PTR, sudoerslval.string);
+ }
+
+ dst = realloc(sudoerslval.string, olen + len + 1);
+ if (dst == NULL) {
+ /* realloc failure, avoid leaking original */
+ free(sudoerslval.string);
+ sudoerslval.string = NULL;
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ sudoerserror(NULL);
+ debug_return_bool(false);
+ }
+ parser_leak_add(LEAK_PTR, dst);
+ copy_string(dst + olen, src, len);
+ sudoerslval.string = dst;
+
+ debug_return_bool(true);
+}
+
+#define SPECIAL(c) \
+ ((c) == ',' || (c) == ':' || (c) == '=' || (c) == ' ' || (c) == '\t' || (c) == '#')
+
+bool
+fill_cmnd(const char *src, int ilen)
+{
+ const size_t len = (size_t)ilen;
+ char *dst;
+ size_t i;
+ debug_decl(fill_cmnd, SUDOERS_DEBUG_PARSER);
+
+ arg_len = arg_size = 0;
+
+ dst = sudoerslval.command.cmnd = malloc(len + 1);
+ if (dst == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ sudoerserror(NULL);
+ debug_return_bool(false);
+ }
+ sudoerslval.command.args = NULL;
+
+ if (src[0] == '^') {
+ /* Copy the regular expression, no escaped sudo-specific characters. */
+ memcpy(dst, src, len);
+ dst[len] = '\0';
+ } else {
+ /* Copy the string and collapse any escaped sudo-specific characters. */
+ for (i = 0; i < len; i++) {
+ if (src[i] == '\\' && i != len - 1 && SPECIAL(src[i + 1]))
+ *dst++ = src[++i];
+ else
+ *dst++ = src[i];
+ }
+ *dst = '\0';
+
+ /* Check for sudoedit specified as a fully-qualified path. */
+ if ((dst = strrchr(sudoerslval.command.cmnd, '/')) != NULL) { // -V575
+ if (strcmp(dst, "/sudoedit") == 0) {
+ if (sudoers_strict()) {
+ sudoerserror(
+ N_("sudoedit should not be specified with a path"));
+ }
+ free(sudoerslval.command.cmnd);
+ if ((sudoerslval.command.cmnd = strdup("sudoedit")) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ }
+ }
+ }
+
+ parser_leak_add(LEAK_PTR, sudoerslval.command.cmnd);
+ debug_return_bool(true);
+}
+
+bool
+fill_args(const char *s, int ilen, bool addspace)
+{
+ size_t len = (size_t)ilen;
+ size_t new_len;
+ char *p;
+ debug_decl(fill_args, SUDOERS_DEBUG_PARSER);
+
+ if (arg_size == 0) {
+#ifdef NO_LEAKS
+ if (sudoerslval.command.args != NULL) {
+ sudo_warnx("%s: command.args %p, should be NULL", __func__,
+ sudoerslval.command.args);
+ sudoerslval.command.args = NULL;
+ }
+#endif
+ addspace = 0;
+ new_len = len;
+ } else {
+ new_len = arg_len + len + addspace;
+ }
+
+ if (new_len >= arg_size) {
+ /* Allocate in increments of 128 bytes to avoid excessive realloc(). */
+ arg_size = (new_len + 1 + 127) & ~127U;
+
+ parser_leak_remove(LEAK_PTR, sudoerslval.command.args);
+ p = realloc(sudoerslval.command.args, arg_size);
+ if (p == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ parser_leak_add(LEAK_PTR, p);
+ sudoerslval.command.args = p;
+ }
+
+ /* Efficiently append the arg (with a leading space if needed). */
+ p = sudoerslval.command.args + arg_len;
+ if (addspace)
+ *p++ = ' ';
+ len = arg_size - (size_t)(p - sudoerslval.command.args);
+ if (strlcpy(p, s, len) >= len) {
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ parser_leak_remove(LEAK_PTR, sudoerslval.command.args);
+ goto bad;
+ }
+ arg_len = new_len;
+ debug_return_bool(true);
+bad:
+ sudoerserror(NULL);
+ free(sudoerslval.command.args);
+ sudoerslval.command.args = NULL;
+ arg_len = arg_size = 0;
+ debug_return_bool(false);
+}
+
+/*
+ * Check to make sure an IPv6 address does not contain multiple instances
+ * of the string "::". Assumes strlen(s) >= 1.
+ * Returns true if address is valid else false.
+ */
+bool
+ipv6_valid(const char *s)
+{
+ int nmatch = 0;
+ debug_decl(ipv6_valid, SUDOERS_DEBUG_PARSER);
+
+ for (; *s != '\0'; s++) {
+ if (s[0] == ':' && s[1] == ':') {
+ if (++nmatch > 1)
+ break;
+ }
+ if (s[0] == '/')
+ nmatch = 0; /* reset if we hit netmask */
+ }
+
+ debug_return_bool(nmatch <= 1);
+}
diff --git a/plugins/sudoers/tsdump.c b/plugins/sudoers/tsdump.c
new file mode 100644
index 0000000..0002a48
--- /dev/null
+++ b/plugins/sudoers/tsdump.c
@@ -0,0 +1,311 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2018-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sudoers.h>
+#include <timestamp.h>
+
+struct timestamp_entry_common {
+ unsigned short version; /* version number */
+ unsigned short size; /* entry size */
+ unsigned short type; /* TS_GLOBAL, TS_TTY, TS_PPID */
+ unsigned short flags; /* TS_DISABLED, TS_ANYUID */
+};
+
+union timestamp_entry_storage {
+ struct timestamp_entry_common common;
+ struct timestamp_entry_v1 v1;
+ struct timestamp_entry v2;
+};
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+static void dump_entry(struct timestamp_entry *entry, off_t pos);
+static bool valid_entry(union timestamp_entry_storage *u, off_t pos);
+static bool convert_entry(union timestamp_entry_storage *record, struct timespec *off);
+sudo_noreturn static void usage(void);
+
+/*
+ * tsdump: a simple utility to dump the contents of a time stamp file.
+ * Unlock sudo, does not perform any locking of the time stamp file.
+ */
+
+int
+main(int argc, char *argv[])
+{
+ int ch, fd;
+ const char *user = NULL;
+ char *fname = NULL;
+ union timestamp_entry_storage cur;
+ struct timespec now, timediff;
+ debug_decl(main, SUDOERS_DEBUG_MAIN);
+
+#if defined(SUDO_DEVEL) && defined(__OpenBSD__)
+ malloc_options = "S";
+#endif
+
+ initprogname(argc > 0 ? argv[0] : "tsdump");
+
+ bindtextdomain("sudoers", LOCALEDIR);
+ textdomain("sudoers");
+
+ /* Initialize the debug subsystem. */
+ if (sudo_conf_read(NULL, SUDO_CONF_DEBUG) == -1)
+ return EXIT_FAILURE;
+ sudoers_debug_register(getprogname(), sudo_conf_debug_files(getprogname()));
+
+ while ((ch = getopt(argc, argv, "f:u:")) != -1) {
+ switch (ch) {
+ case 'f':
+ fname = optarg;
+ break;
+ case 'u':
+ user = optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (fname != NULL && user != NULL) {
+ sudo_warnx("the -f and -u flags are mutually exclusive");
+ usage();
+ }
+
+ /* Calculate the difference between real time and mono time. */
+ if (sudo_gettime_real(&now) == -1)
+ sudo_fatal("unable to get current time");
+ if (sudo_gettime_mono(&timediff) == -1)
+ sudo_fatal("unable to read the clock");
+ sudo_timespecsub(&now, &timediff, &timediff);
+
+ if (fname == NULL) {
+ struct passwd *pw;
+
+ if (user == NULL) {
+ if ((pw = getpwuid(geteuid())) == NULL)
+ sudo_fatalx(U_("unknown uid %u"), (unsigned int)geteuid());
+ user = pw->pw_name;
+ }
+ if (asprintf(&fname, "%s/%s", _PATH_SUDO_TIMEDIR, user) == -1)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ }
+
+ fd = open(fname, O_RDONLY);
+ if (fd == -1)
+ sudo_fatal(U_("unable to open %s"), fname);
+
+ for (;;) {
+ off_t pos = lseek(fd, 0, SEEK_CUR);
+ ssize_t nread;
+ bool valid;
+
+ if ((nread = read(fd, &cur, sizeof(cur))) == 0)
+ break;
+ if (nread == -1)
+ sudo_fatal(U_("unable to read %s"), fname);
+
+ valid = valid_entry(&cur, pos);
+ if (cur.common.size != 0 && cur.common.size != sizeof(cur)) {
+ off_t offset = (off_t)cur.common.size - (off_t)sizeof(cur);
+ if (lseek(fd, offset, SEEK_CUR) == -1)
+ sudo_fatal("unable to seek %d bytes", (int)offset);
+ }
+ if (valid) {
+ /* Convert entry to latest version as needed. */
+ if (!convert_entry(&cur, &timediff))
+ continue;
+ dump_entry(&cur.v2, pos);
+ }
+ }
+
+ return 0;
+}
+
+static bool
+valid_entry(union timestamp_entry_storage *u, off_t pos)
+{
+ struct timestamp_entry *entry = (struct timestamp_entry *)u;
+ debug_decl(valid_entry, SUDOERS_DEBUG_UTIL);
+
+ switch (entry->version) {
+ case 1:
+ if (entry->size != sizeof(struct timestamp_entry_v1)) {
+ sudo_warn("wrong sized v1 record @ %lld, got %hu, expected %zu",
+ (long long)pos, entry->size, sizeof(struct timestamp_entry_v1));
+ debug_return_bool(false);
+ }
+ break;
+ case 2:
+ if (entry->size != sizeof(struct timestamp_entry)) {
+ sudo_warn("wrong sized v2 record @ %lld, got %hu, expected %zu",
+ (long long)pos, entry->size, sizeof(struct timestamp_entry));
+ debug_return_bool(false);
+ }
+ break;
+ default:
+ sudo_warn("unknown time stamp entry version %d @ %lld",
+ (int)entry->version, (long long)pos);
+ debug_return_bool(false);
+ break;
+ }
+ debug_return_bool(true);
+}
+
+static const char *
+type2string(int type)
+{
+ static char name[64];
+ debug_decl(type2string, SUDOERS_DEBUG_UTIL);
+
+ switch (type) {
+ case TS_LOCKEXCL:
+ debug_return_const_str("TS_LOCKEXCL");
+ case TS_GLOBAL:
+ debug_return_const_str("TS_GLOBAL");
+ case TS_TTY:
+ debug_return_const_str("TS_TTY");
+ case TS_PPID:
+ debug_return_const_str("TS_PPID");
+ }
+ (void)snprintf(name, sizeof(name), "UNKNOWN (0x%x)", type);
+ debug_return_const_str(name);
+}
+
+static void
+print_flags(unsigned int flags)
+{
+ bool first = true;
+ debug_decl(print_flags, SUDOERS_DEBUG_UTIL);
+
+ printf("flags: ");
+ if (ISSET(flags, TS_DISABLED)) {
+ printf("%sTS_DISABLED", first ? "" : ", ");
+ CLR(flags, TS_DISABLED);
+ first = false;
+ }
+ if (ISSET(flags, TS_ANYUID)) {
+ /* TS_ANYUID should never appear on disk. */
+ printf("%sTS_ANYUID", first ? "" : ", ");
+ CLR(flags, TS_ANYUID);
+ first = false;
+ }
+ if (flags != 0)
+ printf("%s0x%x", first ? "" : ", ", flags);
+ putchar('\n');
+
+ debug_return;
+}
+
+/*
+ * Convert an older entry to current.
+ * Also adjusts time stamps on Linux to be wallclock time.
+ */
+static bool
+convert_entry(union timestamp_entry_storage *record, struct timespec *off)
+{
+ union timestamp_entry_storage orig;
+ debug_decl(convert_entry, SUDOERS_DEBUG_UTIL);
+
+ if (record->common.version != TS_VERSION) {
+ if (record->common.version != 1) {
+ sudo_warnx("unexpected record version %hu", record->common.version);
+ debug_return_bool(false);
+ }
+
+ /* The first four fields are the same regardless of version. */
+ memcpy(&orig, record, sizeof(union timestamp_entry_storage));
+ record->v2.auth_uid = orig.v1.auth_uid;
+ record->v2.sid = orig.v1.sid;
+ sudo_timespecclear(&record->v2.start_time);
+ record->v2.ts = orig.v1.ts;
+ if (record->common.type == TS_TTY)
+ record->v2.u.ttydev = orig.v1.u.ttydev;
+ else if (record->common.type == TS_PPID)
+ record->v2.u.ppid = orig.v1.u.ppid;
+ else
+ memset(&record->v2.u, 0, sizeof(record->v2.u));
+ }
+
+ /* On Linux, start time is relative to boot time, adjust to real time. */
+#ifdef __linux__
+ if (sudo_timespecisset(&record->v2.start_time))
+ sudo_timespecadd(&record->v2.start_time, off, &record->v2.start_time);
+#endif
+
+ /* Adjust time stamp from mono time to real time. */
+ if (sudo_timespecisset(&record->v2.ts))
+ sudo_timespecadd(&record->v2.ts, off, &record->v2.ts);
+
+ debug_return_bool(true);
+}
+
+static void
+dump_entry(struct timestamp_entry *entry, off_t pos)
+{
+ debug_decl(dump_entry, SUDOERS_DEBUG_UTIL);
+
+ printf("position: %lld\n", (long long)pos);
+ printf("version: %hu\n", entry->version);
+ printf("size: %hu\n", entry->size);
+ printf("type: %s\n", type2string(entry->type));
+ print_flags(entry->flags);
+ printf("auth uid: %d\n", (int)entry->auth_uid);
+ printf("session ID: %d\n", (int)entry->sid);
+ if (sudo_timespecisset(&entry->start_time))
+ printf("start time: %s", ctime(&entry->start_time.tv_sec));
+ if (sudo_timespecisset(&entry->ts))
+ printf("time stamp: %s", ctime(&entry->ts.tv_sec));
+ if (entry->type == TS_TTY) {
+ char tty[PATH_MAX];
+ if (sudo_ttyname_dev(entry->u.ttydev, tty, sizeof(tty)) == NULL)
+ printf("terminal: %d\n", (int)entry->u.ttydev);
+ else
+ printf("terminal: %s\n", tty);
+ } else if (entry->type == TS_PPID) {
+ printf("parent pid: %d\n", (int)entry->u.ppid);
+ }
+ fputc('\n', stdout);
+
+ debug_return;
+}
+
+sudo_noreturn static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-f timestamp_file] | [-u username]\n",
+ getprogname());
+ exit(EXIT_FAILURE);
+}
diff --git a/plugins/sudoers/tsgetgrpw.c b/plugins/sudoers/tsgetgrpw.c
new file mode 100644
index 0000000..2a779ba
--- /dev/null
+++ b/plugins/sudoers/tsgetgrpw.c
@@ -0,0 +1,422 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2005, 2008, 2010-2015, 2022
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+/*
+ * Trivial replacements for the libc getgrent() and getpwent() family
+ * of functions for use by testsudoers in the sudo test harness.
+ * We need our own since many platforms don't provide set{pw,gr}file().
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+
+#include <tsgetgrpw.h>
+#include <sudoers.h>
+
+#undef GRMEM_MAX
+#define GRMEM_MAX 200
+
+#ifndef UID_MAX
+# define UID_MAX 0xffffffffU
+#endif
+
+#ifndef GID_MAX
+# define GID_MAX UID_MAX
+#endif
+
+static FILE *pwf;
+static const char *pwfile = "/etc/passwd";
+static int pw_stayopen;
+
+static FILE *grf;
+static const char *grfile = "/etc/group";
+static int gr_stayopen;
+
+void
+testsudoers_setpwfile(const char *file)
+{
+ pwfile = file;
+ if (pwf != NULL)
+ testsudoers_endpwent();
+}
+
+static int
+open_passwd(int reset)
+{
+ if (pwf == NULL) {
+ pwf = fopen(pwfile, "r");
+ if (pwf != NULL) {
+ if (fcntl(fileno(pwf), F_SETFD, FD_CLOEXEC) == -1) {
+ fclose(pwf);
+ pwf = NULL;
+ }
+ }
+ if (pwf == NULL)
+ return 0;
+ } else if (reset) {
+ rewind(pwf);
+ }
+ return 1;
+}
+
+int
+testsudoers_setpassent(int stayopen)
+{
+ if (!open_passwd(1))
+ return 0;
+ pw_stayopen = stayopen;
+ return 1;
+}
+
+void
+testsudoers_setpwent(void)
+{
+ testsudoers_setpassent(0);
+}
+
+void
+testsudoers_endpwent(void)
+{
+ if (pwf != NULL) {
+ fclose(pwf);
+ pwf = NULL;
+ }
+ pw_stayopen = 0;
+}
+
+struct passwd *
+testsudoers_getpwent(void)
+{
+ static struct passwd pw;
+ static char pwbuf[LINE_MAX];
+ size_t len;
+ id_t id;
+ char *cp, *colon;
+ const char *errstr;
+
+ if (!open_passwd(0))
+ return NULL;
+
+next_entry:
+ if ((colon = fgets(pwbuf, sizeof(pwbuf), pwf)) == NULL)
+ return NULL;
+
+ memset(&pw, 0, sizeof(pw));
+ if ((colon = strchr(cp = colon, ':')) == NULL)
+ goto next_entry;
+ *colon++ = '\0';
+ pw.pw_name = cp;
+ if ((colon = strchr(cp = colon, ':')) == NULL)
+ goto next_entry;
+ *colon++ = '\0';
+ pw.pw_passwd = cp;
+ if ((colon = strchr(cp = colon, ':')) == NULL)
+ goto next_entry;
+ *colon++ = '\0';
+ id = sudo_strtoid(cp, &errstr);
+ if (errstr != NULL)
+ goto next_entry;
+ pw.pw_uid = (uid_t)id;
+ if ((colon = strchr(cp = colon, ':')) == NULL)
+ goto next_entry;
+ *colon++ = '\0';
+ id = sudo_strtoid(cp, &errstr);
+ if (errstr != NULL)
+ goto next_entry;
+ pw.pw_gid = (gid_t)id;
+ if ((colon = strchr(cp = colon, ':')) == NULL)
+ goto next_entry;
+ *colon++ = '\0';
+ pw.pw_gecos = cp;
+ if ((colon = strchr(cp = colon, ':')) == NULL)
+ goto next_entry;
+ *colon++ = '\0';
+ pw.pw_dir = cp;
+ pw.pw_shell = colon;
+ len = strlen(colon);
+ if (len > 0 && colon[len - 1] == '\n')
+ colon[len - 1] = '\0';
+ return &pw;
+}
+
+struct passwd *
+testsudoers_getpwnam(const char *name)
+{
+ struct passwd *pw;
+
+ if (!open_passwd(1))
+ return NULL;
+ while ((pw = testsudoers_getpwent()) != NULL) {
+ if (strcmp(pw->pw_name, name) == 0)
+ break;
+ }
+ if (!pw_stayopen) {
+ fclose(pwf);
+ pwf = NULL;
+ }
+ return pw;
+}
+
+struct passwd *
+testsudoers_getpwuid(uid_t uid)
+{
+ struct passwd *pw;
+
+ if (!open_passwd(1))
+ return NULL;
+ while ((pw = testsudoers_getpwent()) != NULL) {
+ if (pw->pw_uid == uid)
+ break;
+ }
+ if (!pw_stayopen) {
+ fclose(pwf);
+ pwf = NULL;
+ }
+ return pw;
+}
+
+void
+testsudoers_setgrfile(const char *file)
+{
+ grfile = file;
+ if (grf != NULL)
+ testsudoers_endgrent();
+}
+
+static int
+open_group(int reset)
+{
+ if (grf == NULL) {
+ grf = fopen(grfile, "r");
+ if (grf != NULL) {
+ if (fcntl(fileno(grf), F_SETFD, FD_CLOEXEC) == -1) {
+ fclose(grf);
+ grf = NULL;
+ }
+ }
+ if (grf == NULL)
+ return 0;
+ } else if (reset) {
+ rewind(grf);
+ }
+ return 1;
+}
+
+int
+testsudoers_setgroupent(int stayopen)
+{
+ if (!open_group(1))
+ return 0;
+ gr_stayopen = stayopen;
+ return 1;
+}
+
+void
+testsudoers_setgrent(void)
+{
+ testsudoers_setgroupent(0);
+}
+
+void
+testsudoers_endgrent(void)
+{
+ if (grf != NULL) {
+ fclose(grf);
+ grf = NULL;
+ }
+ gr_stayopen = 0;
+}
+
+struct group *
+testsudoers_getgrent(void)
+{
+ static struct group gr;
+ static char grbuf[LINE_MAX], *gr_mem[GRMEM_MAX+1];
+ size_t len;
+ id_t id;
+ char *cp, *colon;
+ const char *errstr;
+ int n;
+
+ if (!open_group(0))
+ return NULL;
+
+next_entry:
+ if ((colon = fgets(grbuf, sizeof(grbuf), grf)) == NULL)
+ return NULL;
+
+ memset(&gr, 0, sizeof(gr));
+ if ((colon = strchr(cp = colon, ':')) == NULL)
+ goto next_entry;
+ *colon++ = '\0';
+ gr.gr_name = cp;
+ if ((colon = strchr(cp = colon, ':')) == NULL)
+ goto next_entry;
+ *colon++ = '\0';
+ gr.gr_passwd = cp;
+ if ((colon = strchr(cp = colon, ':')) == NULL)
+ goto next_entry;
+ *colon++ = '\0';
+ id = sudo_strtoid(cp, &errstr);
+ if (errstr != NULL)
+ goto next_entry;
+ gr.gr_gid = (gid_t)id;
+ len = strlen(colon);
+ if (len > 0 && colon[len - 1] == '\n')
+ colon[len - 1] = '\0';
+ if (*colon != '\0') {
+ char *last;
+
+ gr.gr_mem = gr_mem;
+ cp = strtok_r(colon, ",", &last);
+ for (n = 0; cp != NULL && n < GRMEM_MAX; n++) {
+ gr.gr_mem[n] = cp;
+ cp = strtok_r(NULL, ",", &last);
+ }
+ gr.gr_mem[n] = NULL;
+ } else
+ gr.gr_mem = NULL;
+ return &gr;
+}
+
+struct group *
+testsudoers_getgrnam(const char *name)
+{
+ struct group *gr;
+
+ if (!open_group(1))
+ return NULL;
+ while ((gr = testsudoers_getgrent()) != NULL) {
+ if (strcmp(gr->gr_name, name) == 0)
+ break;
+ }
+ if (!gr_stayopen) {
+ fclose(grf);
+ grf = NULL;
+ }
+ return gr;
+}
+
+struct group *
+testsudoers_getgrgid(gid_t gid)
+{
+ struct group *gr;
+
+ if (!open_group(1))
+ return NULL;
+ while ((gr = testsudoers_getgrent()) != NULL) {
+ if (gr->gr_gid == gid)
+ break;
+ }
+ if (!gr_stayopen) {
+ fclose(grf);
+ grf = NULL;
+ }
+ return gr;
+}
+
+/*
+ * Copied from getgrouplist.c
+ */
+int
+testsudoers_getgrouplist2(const char *name, GETGROUPS_T basegid,
+ GETGROUPS_T **groupsp, int *ngroupsp)
+{
+ GETGROUPS_T *groups = *groupsp;
+ int i, ngroups = 1;
+ long grpsize;
+ int ret = -1;
+ struct group *grp;
+
+ if (groups == NULL) {
+ /* Dynamically-sized group vector. */
+ grpsize = sysconf(_SC_NGROUPS_MAX);
+ if (grpsize < 0)
+ grpsize = NGROUPS_MAX;
+ groups = reallocarray(NULL, (size_t)grpsize, 4 * sizeof(*groups));
+ if (groups == NULL)
+ return -1;
+ grpsize <<= 2;
+ } else {
+ /* Static group vector. */
+ if ((grpsize = *ngroupsp) < 1)
+ return -1;
+ }
+
+ /* We support BSD semantics where the first element is the base gid */
+ groups[0] = basegid;
+
+ testsudoers_setgrent();
+ while ((grp = testsudoers_getgrent()) != NULL) {
+ if (grp->gr_gid == basegid || grp->gr_mem == NULL)
+ continue;
+
+ for (i = 0; grp->gr_mem[i] != NULL; i++) {
+ if (strcmp(name, grp->gr_mem[i]) == 0)
+ break;
+ }
+ if (grp->gr_mem[i] == NULL)
+ continue; /* user not found */
+
+ /* Only add if it is not the same as an existing gid */
+ for (i = 0; i < ngroups; i++) {
+ if (grp->gr_gid == groups[i])
+ break;
+ }
+ if (i == ngroups) {
+ if (ngroups == grpsize) {
+ GETGROUPS_T *tmp;
+
+ if (*groupsp != NULL) {
+ /* Static group vector. */
+ goto done;
+ }
+ tmp = reallocarray(groups, (size_t)grpsize, 2 * sizeof(*groups));
+ if (tmp == NULL) {
+ free(groups);
+ groups = NULL;
+ ngroups = 0;
+ goto done;
+ }
+ groups = tmp;
+ grpsize <<= 1;
+ }
+ groups[ngroups++] = grp->gr_gid;
+ }
+ }
+ ret = 0;
+
+done:
+ testsudoers_endgrent();
+ *groupsp = groups;
+ *ngroupsp = ngroups;
+
+ return ret;
+}
diff --git a/plugins/sudoers/tsgetgrpw.h b/plugins/sudoers/tsgetgrpw.h
new file mode 100644
index 0000000..88a232d
--- /dev/null
+++ b/plugins/sudoers/tsgetgrpw.h
@@ -0,0 +1,52 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010, 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Trivial replacements for the libc getgrent() and getpwent() family
+ * of functions for use by testsudoers in the sudo test harness.
+ * We need our own since many platforms don't provide set{pw,gr}file().
+ */
+
+#include <config.h>
+
+#include <pwd.h>
+#include <grp.h>
+
+void testsudoers_setgrfile(const char *);
+void testsudoers_setgrent(void);
+void testsudoers_endgrent(void);
+int testsudoers_setgroupent(int);
+struct group *testsudoers_getgrent(void);
+struct group *testsudoers_getgrnam(const char *);
+struct group *testsudoers_getgrgid(gid_t);
+
+void testsudoers_setpwfile(const char *);
+void testsudoers_setpwent(void);
+void testsudoers_endpwent(void);
+int testsudoers_setpassent(int);
+struct passwd *testsudoers_getpwent(void);
+struct passwd *testsudoers_getpwnam(const char *);
+struct passwd *testsudoers_getpwuid(uid_t);
+
+char *testsudoers_getusershell(void);
+void testsudoers_setusershell(void);
+void testsudoers_endusershell(void);
+void testsudoers_setshellfile(const char *file);
+
+int testsudoers_getgrouplist2(const char *name, GETGROUPS_T basegid,
+ GETGROUPS_T **groupsp, int *ngroupsp);
diff --git a/plugins/sudoers/unesc_str.c b/plugins/sudoers/unesc_str.c
new file mode 100644
index 0000000..cd46794
--- /dev/null
+++ b/plugins/sudoers/unesc_str.c
@@ -0,0 +1,46 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <sudoers.h>
+
+/*
+ * Remove backslash escape chars.
+ */
+void
+unescape_string(char *str)
+{
+ char *cp = str;
+ char *ep = str + strlen(str);
+
+ while ((cp = strchr(cp, '\\')) != NULL) {
+ if (cp[1] == '\0')
+ break;
+ memmove(cp, cp + 1, (size_t)(ep - cp));
+ cp++;
+ ep--;
+ }
+}
diff --git a/plugins/sudoers/visudo.c b/plugins/sudoers/visudo.c
new file mode 100644
index 0000000..735d7af
--- /dev/null
+++ b/plugins/sudoers/visudo.c
@@ -0,0 +1,1352 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2007-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+/*
+ * Lock the sudoers file for safe editing (ala vipw) and check for parse errors.
+ */
+
+#ifdef __TANDEM
+# include <floss.h>
+#endif
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#ifndef __TANDEM
+# include <sys/file.h>
+#endif
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#ifdef HAVE_GETOPT_LONG
+# include <getopt.h>
+# else
+# include <compat/getopt.h>
+#endif /* HAVE_GETOPT_LONG */
+
+#include <sudoers.h>
+#include <interfaces.h>
+#include <redblack.h>
+#include <sudoers_version.h>
+#include <sudo_conf.h>
+#include <gram.h>
+
+struct sudoersfile {
+ TAILQ_ENTRY(sudoersfile) entries;
+ char *opath; /* original path we opened */
+ char *dpath; /* destination path to write to */
+ char *tpath; /* editor temporary file path */
+ bool created; /* true if visudo created a new sudoers file */
+ bool modified; /* true if the user modified the file */
+ bool doedit; /* true when editing (not just checking) sudoers */
+ int fd; /* fd of the original file (if it exists) */
+ int errorline; /* line number when there is a syntax error */
+};
+TAILQ_HEAD(sudoersfile_list, sudoersfile);
+
+/*
+ * Function prototypes
+ */
+static void quit(int);
+static int whatnow(void);
+static char *get_editor(int *editor_argc, char ***editor_argv);
+static bool check_syntax(struct sudoers_context *ctx, const char *, bool, bool);
+static bool edit_sudoers(struct sudoersfile *, char *, int, char **, int);
+static bool install_sudoers(struct sudoersfile *, bool, bool);
+static bool visudo_track_error(const struct sudoers_context *ctx, const char *file, int line, int column, const char * restrict fmt, va_list args);
+static int print_unused(struct sudoers_parse_tree *, struct alias *, void *);
+static bool reparse_sudoers(struct sudoers_context *ctx, char *, int, char **);
+static int run_command(const char *, char *const *);
+static void parse_sudoers_options(struct sudoers_context *ctx);
+static void setup_signals(void);
+static void visudo_cleanup(void);
+sudo_noreturn static void export_sudoers(const char *infile, const char *outfile);
+sudo_noreturn static void help(void);
+sudo_noreturn static void usage(void);
+
+/*
+ * Globals
+ */
+static const char *path_sudoers = _PATH_SUDOERS;
+static struct sudoersfile_list sudoerslist = TAILQ_HEAD_INITIALIZER(sudoerslist);
+static bool checkonly;
+static bool edit_includes = true;
+static unsigned int errors;
+static const char short_opts[] = "cf:hIOPqsVx:";
+static struct option long_opts[] = {
+ { "check", no_argument, NULL, 'c' },
+ { "export", required_argument, NULL, 'x' },
+ { "file", required_argument, NULL, 'f' },
+ { "help", no_argument, NULL, 'h' },
+ { "no-includes", no_argument, NULL, 'I' },
+ { "owner", no_argument, NULL, 'O' },
+ { "perms", no_argument, NULL, 'P' },
+ { "quiet", no_argument, NULL, 'q' },
+ { "strict", no_argument, NULL, 's' },
+ { "version", no_argument, NULL, 'V' },
+ { NULL, no_argument, NULL, '\0' },
+};
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+int
+main(int argc, char *argv[])
+{
+ struct sudoers_context ctx = SUDOERS_CONTEXT_INITIALIZER;
+ struct sudoersfile *sp;
+ char *editor, **editor_argv;
+ const char *export_path = NULL;
+ int ch, oldlocale, editor_argc, exitcode = 0;
+ bool use_perms, use_owner, fflag;
+ debug_decl(main, SUDOERS_DEBUG_MAIN);
+
+#if defined(SUDO_DEVEL) && defined(__OpenBSD__)
+ {
+ extern char *malloc_options;
+ malloc_options = "S";
+ }
+#endif
+
+ initprogname(argc > 0 ? argv[0] : "visudo");
+ if (!sudoers_initlocale(setlocale(LC_ALL, ""), def_sudoers_locale))
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ sudo_warn_set_locale_func(sudoers_warn_setlocale);
+ bindtextdomain("sudoers", LOCALEDIR); /* XXX - should have visudo domain */
+ textdomain("sudoers");
+
+ if (argc < 1)
+ usage();
+
+ /* Register callbacks. */
+ sudo_fatal_callback_register(visudo_cleanup);
+ set_callbacks();
+
+ /* Read debug and plugin sections of sudo.conf. */
+ if (sudo_conf_read(NULL, SUDO_CONF_DEBUG|SUDO_CONF_PLUGINS) == -1)
+ return EXIT_FAILURE;
+
+ /* Initialize the debug subsystem. */
+ if (!sudoers_debug_register(getprogname(), sudo_conf_debug_files(getprogname())))
+ return EXIT_FAILURE;
+
+ /* Parse sudoers plugin options, if any. */
+ parse_sudoers_options(&ctx);
+
+ /*
+ * Arg handling.
+ */
+ fflag = use_owner = use_perms = false;
+ while ((ch = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
+ switch (ch) {
+ case 'V':
+ (void) printf(_("%s version %s\n"), getprogname(),
+ PACKAGE_VERSION);
+ (void) printf(_("%s grammar version %d\n"), getprogname(),
+ SUDOERS_GRAMMAR_VERSION);
+ goto done;
+ case 'c':
+ checkonly = true; /* check mode */
+ break;
+ case 'f':
+ path_sudoers = optarg;
+ fflag = true;
+ break;
+ case 'h':
+ help();
+ /* NOTREACHED */
+ case 'I':
+ edit_includes = false;
+ break;
+ case 'O':
+ use_owner = true; /* check/set owner */
+ break;
+ case 'P':
+ use_perms = true; /* check/set perms */
+ break;
+ case 's':
+ ctx.parser_conf.strict = 2;
+ break;
+ case 'q':
+ ctx.parser_conf.verbose = 0;
+ break;
+ case 'x':
+ export_path = optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* Check for optional sudoers file argument. */
+ switch (argc) {
+ case 0:
+ break;
+ case 1:
+ /* Only accept sudoers file if no -f was specified. */
+ if (!fflag) {
+ path_sudoers = *argv;
+ fflag = true;
+ }
+ break;
+ default:
+ usage();
+ }
+
+ if (fflag) {
+ /* Looser owner/permission checks for an uninstalled sudoers file. */
+ if (!use_owner) {
+ ctx.parser_conf.sudoers_uid = (uid_t)-1;
+ ctx.parser_conf.sudoers_gid = (gid_t)-1;
+ }
+ if (!use_perms)
+ ctx.parser_conf.sudoers_mode |= S_IWUSR;
+ } else {
+ /* Check/set owner and mode for installed sudoers file. */
+ use_owner = true;
+ use_perms = true;
+ }
+
+ if (export_path != NULL) {
+ /* Backward compatibility for the time being. */
+ export_sudoers(path_sudoers, export_path);
+ }
+
+ /* Mock up a fake struct sudoers_user_context. */
+ ctx.user.cmnd = ctx.user.cmnd_base = strdup("true");
+ if (ctx.user.cmnd == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (geteuid() == 0) {
+ const char *user = getenv("SUDO_USER");
+ if (user != NULL && *user != '\0')
+ ctx.user.pw = sudo_getpwnam(user);
+ }
+ if (ctx.user.pw == NULL) {
+ if ((ctx.user.pw = sudo_getpwuid(getuid())) == NULL)
+ sudo_fatalx(U_("you do not exist in the %s database"), "passwd");
+ }
+ if (!sudoers_sethost(&ctx, NULL, NULL))
+ return EXIT_FAILURE;
+
+ /* Hook the sudoers parser to track files with parse errors. */
+ sudoers_error_hook = visudo_track_error;
+
+ /* Setup defaults data structures. */
+ if (!init_defaults())
+ sudo_fatalx("%s", U_("unable to initialize sudoers default values"));
+
+ if (checkonly) {
+ exitcode = check_syntax(&ctx, path_sudoers, use_owner, use_perms)
+ ? 0 : 1;
+ goto done;
+ }
+
+ /*
+ * Parse the existing sudoers file(s) to highlight any existing
+ * errors and to pull in editor and env_editor conf values.
+ */
+ ctx.parser_conf.sudoers_path = path_sudoers;
+ init_parser(&ctx, NULL);
+ if ((sudoersin = open_sudoers(path_sudoers, &sudoers, true, NULL)) == NULL)
+ return EXIT_FAILURE;
+ sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
+ (void) sudoersparse();
+ (void) update_defaults(&ctx, &parsed_policy, NULL,
+ SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER, !ctx.parser_conf.verbose);
+ sudoers_setlocale(oldlocale, NULL);
+
+ editor = get_editor(&editor_argc, &editor_argv);
+
+ /* Install signal handlers to clean up temp files if we are killed. */
+ setup_signals();
+
+ /* Edit the sudoers file(s) */
+ TAILQ_FOREACH(sp, &sudoerslist, entries) {
+ if (!sp->doedit)
+ continue;
+ if (sp != TAILQ_FIRST(&sudoerslist)) {
+ printf(_("press return to edit %s: "), sp->opath);
+ while ((ch = getchar()) != EOF && ch != '\r' && ch != '\n')
+ continue;
+ }
+ edit_sudoers(sp, editor, editor_argc, editor_argv, -1);
+ }
+
+ /*
+ * Check edited files for a parse error, re-edit any that fail
+ * and install the edited files as needed.
+ */
+ if (reparse_sudoers(&ctx, editor, editor_argc, editor_argv)) {
+ TAILQ_FOREACH(sp, &sudoerslist, entries) {
+ if (!install_sudoers(sp, use_owner, use_perms)) {
+ if (sp->tpath != NULL) {
+ sudo_warnx(U_("contents of edit session left in %s"),
+ sp->tpath);
+ free(sp->tpath);
+ sp->tpath = NULL;
+ }
+ exitcode = 1;
+ }
+ }
+ }
+ free(editor);
+
+done:
+ sudoers_ctx_free(&ctx);
+ sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, exitcode);
+ return exitcode;
+}
+
+static bool
+visudo_track_error(const struct sudoers_context *ctx, const char *file,
+ int line, int column, const char * restrict fmt, va_list args)
+{
+ struct sudoersfile *sp;
+ debug_decl(visudo_track_error, SUDOERS_DEBUG_UTIL);
+
+ TAILQ_FOREACH(sp, &sudoerslist, entries) {
+ if (sp->errorline > 0)
+ continue; /* preserve the first error */
+
+ if (strcmp(file, sp->opath) == 0 ||
+ (sp->tpath != NULL && strcmp(file, sp->tpath) == 0)) {
+ sp->errorline = line;
+ break;
+ }
+ }
+ errors++;
+
+ debug_return_bool(true);
+}
+
+static char *
+get_editor(int *editor_argc, char ***editor_argv)
+{
+ char *editor_path = NULL, **allowlist = NULL;
+ const char *env_editor = NULL;
+ static const char *files[] = { "+1", "sudoers" };
+ size_t allowlist_len = 0;
+ debug_decl(get_editor, SUDOERS_DEBUG_UTIL);
+
+ /* Build up editor allowlist from def_editor unless env_editor is set. */
+ if (!def_env_editor) {
+ const char *cp, *ep;
+ const char *def_editor_end = def_editor + strlen(def_editor);
+
+ /* Count number of entries in allowlist and split into a list. */
+ for (cp = sudo_strsplit(def_editor, def_editor_end, ":", &ep);
+ cp != NULL; cp = sudo_strsplit(NULL, def_editor_end, ":", &ep)) {
+ allowlist_len++;
+ }
+ allowlist = reallocarray(NULL, allowlist_len + 1, sizeof(char *));
+ if (allowlist == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ allowlist_len = 0;
+ for (cp = sudo_strsplit(def_editor, def_editor_end, ":", &ep);
+ cp != NULL; cp = sudo_strsplit(NULL, def_editor_end, ":", &ep)) {
+ allowlist[allowlist_len] = strndup(cp, (size_t)(ep - cp));
+ if (allowlist[allowlist_len] == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ allowlist_len++;
+ }
+ allowlist[allowlist_len] = NULL;
+ }
+
+ editor_path = find_editor(2, (char **)files, editor_argc, editor_argv,
+ allowlist, &env_editor);
+ if (editor_path == NULL) {
+ if (def_env_editor && env_editor != NULL) {
+ /* We are honoring $EDITOR so this is a fatal error. */
+ if (errno == ENOENT) {
+ sudo_warnx(U_("specified editor (%s) doesn't exist"),
+ env_editor);
+ }
+ exit(EXIT_FAILURE);
+ }
+ sudo_fatalx(U_("no editor found (editor path = %s)"), def_editor);
+ }
+
+ if (allowlist != NULL) {
+ while (allowlist_len)
+ free(allowlist[--allowlist_len]);
+ free(allowlist);
+ }
+
+ debug_return_str(editor_path);
+}
+
+/*
+ * List of editors that support the "+lineno" command line syntax.
+ * If an entry starts with '*' the tail end of the string is matched.
+ * No other wild cards are supported.
+ */
+static const char *lineno_editors[] = {
+ "*macs",
+ "ee",
+ "elvis",
+ "ex",
+ "joe",
+ "jove",
+ "mg",
+ "nano",
+ "nex",
+ "nvi",
+ "nvim",
+ "o",
+ "pico",
+ "vi",
+ "vile",
+ "vim",
+ "zile",
+ NULL
+};
+
+/*
+ * Check whether or not the specified editor matched lineno_editors[].
+ * Returns true if yes, false if no.
+ */
+static bool
+editor_supports_plus(const char *editor)
+{
+ const char *cp, *editor_base;
+ const char **av;
+ debug_decl(editor_supports_plus, SUDOERS_DEBUG_UTIL);
+
+ editor_base = sudo_basename(editor);
+ if (*editor_base == 'r')
+ editor_base++;
+
+ for (av = lineno_editors; (cp = *av) != NULL; av++) {
+ /* We only handle a leading '*' wildcard. */
+ if (*cp == '*') {
+ size_t blen = strlen(editor_base);
+ size_t clen = strlen(++cp);
+ if (blen >= clen) {
+ if (strcmp(cp, editor_base + blen - clen) == 0)
+ break;
+ }
+ } else if (strcmp(cp, editor_base) == 0)
+ break;
+ }
+ debug_return_bool(cp != NULL);
+}
+
+/*
+ * Edit each sudoers file.
+ * Returns true on success, else false.
+ */
+static bool
+edit_sudoers(struct sudoersfile *sp, char *editor, int editor_argc,
+ char **editor_argv, int lineno)
+{
+ int tfd; /* sudoers temp file descriptor */
+ bool modified; /* was the file modified? */
+ int ac; /* argument count */
+ char linestr[64]; /* string version of lineno */
+ struct timespec ts, times[2]; /* time before and after edit */
+ struct timespec orig_mtim; /* starting mtime of sudoers file */
+ off_t orig_size; /* starting size of sudoers file */
+ struct stat sb; /* stat buffer */
+ bool ret = false; /* return value */
+ debug_decl(edit_sudoers, SUDOERS_DEBUG_UTIL);
+
+ if (fstat(sp->fd, &sb) == -1)
+ sudo_fatal(U_("unable to stat %s"), sp->opath);
+ orig_size = sb.st_size;
+ mtim_get(&sb, orig_mtim);
+
+ /* Create the temp file if needed and set timestamp. */
+ if (sp->tpath == NULL) {
+ if (asprintf(&sp->tpath, "%s.tmp", sp->dpath) == -1)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ tfd = open(sp->tpath, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU|S_IRUSR);
+ if (tfd < 0)
+ sudo_fatal("%s", sp->tpath);
+
+ /* Copy sp->opath -> sp->tpath and reset the mtime. */
+ if (orig_size != 0) {
+ char buf[4096], lastch = '\0';
+ ssize_t nread;
+
+ (void) lseek(sp->fd, (off_t)0, SEEK_SET);
+ while ((nread = read(sp->fd, buf, sizeof(buf))) > 0) {
+ if (write(tfd, buf, (size_t)nread) == -1)
+ sudo_fatal("%s", U_("write error"));
+ lastch = buf[nread - 1];
+ }
+
+ /* Add missing newline at EOF if needed. */
+ if (lastch != '\n') {
+ lastch = '\n';
+ if (write(tfd, &lastch, 1) == -1)
+ sudo_fatal("%s", U_("write error"));
+ }
+ }
+ (void) close(tfd);
+ }
+ times[0].tv_sec = times[1].tv_sec = orig_mtim.tv_sec;
+ times[0].tv_nsec = times[1].tv_nsec = orig_mtim.tv_nsec;
+ (void) utimensat(AT_FDCWD, sp->tpath, times, 0);
+
+ /* Disable +lineno if editor doesn't support it. */
+ if (lineno > 0 && !editor_supports_plus(editor))
+ lineno = -1;
+
+ /*
+ * The last 3 slots in the editor argv are: "-- +1 sudoers"
+ * Replace those placeholders with the real values.
+ */
+ ac = editor_argc - 3;
+ if (lineno > 0) {
+ (void)snprintf(linestr, sizeof(linestr), "+%d", lineno);
+ editor_argv[ac++] = linestr; // -V507
+ }
+ editor_argv[ac++] = (char *)"--";
+ editor_argv[ac++] = sp->tpath;
+ editor_argv[ac] = NULL;
+
+ /*
+ * Do the edit:
+ * We cannot check the editor's exit value against 0 since
+ * XPG4 specifies that vi's exit value is a function of the
+ * number of errors during editing (?!?!).
+ */
+ if (sudo_gettime_real(&times[0]) == -1) {
+ sudo_warn("%s", U_("unable to read the clock"));
+ goto done;
+ }
+
+ if (run_command(editor, editor_argv) != -1) {
+ if (sudo_gettime_real(&times[1]) == -1) {
+ sudo_warn("%s", U_("unable to read the clock"));
+ goto done;
+ }
+ /*
+ * Check for zero length sudoers file.
+ */
+ if (stat(sp->tpath, &sb) == -1) {
+ sudo_warnx(U_("unable to stat temporary file (%s), %s unchanged"),
+ sp->tpath, sp->opath);
+ goto done;
+ }
+ if (sb.st_size == 0 && orig_size != 0) {
+ /* Avoid accidental zeroing of main sudoers file. */
+ if (sp == TAILQ_FIRST(&sudoerslist)) {
+ sudo_warnx(U_("zero length temporary file (%s), %s unchanged"),
+ sp->tpath, sp->opath);
+ goto done;
+ }
+ }
+ } else {
+ sudo_warnx(U_("editor (%s) failed, %s unchanged"), editor, sp->opath);
+ goto done;
+ }
+
+ /* Set modified bit if the user changed the file. */
+ modified = true;
+ mtim_get(&sb, ts);
+ if (orig_size == sb.st_size && sudo_timespeccmp(&orig_mtim, &ts, ==)) {
+ /*
+ * If mtime and size match but the user spent no measurable
+ * time in the editor we can't tell if the file was changed.
+ */
+ if (sudo_timespeccmp(&times[0], &times[1], !=))
+ modified = false;
+ }
+
+ /*
+ * If modified in this edit session, mark as modified.
+ */
+ if (modified) {
+ sp->modified = modified;
+ } else {
+ /*
+ * If visudo created a new, zero-length file that the user did
+ * not modify, remove it as long as it is the main sudoers file.
+ * We must retain new files created via a @include directive
+ * to avoid a parse error, even if they are empty.
+ */
+ if (sp->created && orig_size == 0) {
+ if (sp == TAILQ_FIRST(&sudoerslist))
+ unlink(sp->dpath);
+ }
+ sudo_warnx(U_("%s unchanged"), sp->tpath);
+ }
+
+ ret = true;
+done:
+ debug_return_bool(ret);
+}
+
+/*
+ * Check Defaults and Alias entries.
+ * On error, visudo_track_error() will set the line number in sudoerslist.
+ */
+static void
+check_defaults_and_aliases(struct sudoers_context *ctx)
+{
+ const bool quiet = !ctx->parser_conf.verbose;
+ const bool strict = ctx->parser_conf.strict > 1;
+ debug_decl(check_defaults_and_aliases, SUDOERS_DEBUG_UTIL);
+
+ if (!check_defaults(&parsed_policy, quiet)) {
+ parse_error = true;
+ }
+ if (check_aliases(&parsed_policy, strict, quiet, print_unused) != 0) {
+ parse_error = true;
+ }
+ debug_return;
+}
+
+/*
+ * Parse sudoers after editing and re-edit any ones that caused a parse error.
+ */
+static bool
+reparse_sudoers(struct sudoers_context *ctx, char *editor, int editor_argc,
+ char **editor_argv)
+{
+ struct sudoersfile *sp, *last;
+ FILE *fp;
+ int ch, oldlocale;
+ debug_decl(reparse_sudoers, SUDOERS_DEBUG_UTIL);
+
+ /*
+ * Parse the edited sudoers files.
+ */
+ errors = 0;
+ while ((sp = TAILQ_FIRST(&sudoerslist)) != NULL) {
+ last = TAILQ_LAST(&sudoerslist, sudoersfile_list);
+ fp = fopen(sp->tpath, "r+");
+ if (fp == NULL)
+ sudo_fatalx(U_("unable to re-open temporary file (%s), %s unchanged."),
+ sp->tpath, sp->opath);
+
+ /* Clean slate for each parse */
+ if (!init_defaults())
+ sudo_fatalx("%s", U_("unable to initialize sudoers default values"));
+ init_parser(ctx, sp->opath);
+ sp->errorline = -1;
+
+ /* Parse the sudoers temp file(s) */
+ sudoersrestart(fp);
+ sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
+ if (sudoersparse() && !parse_error) {
+ sudo_warnx(U_("unable to parse temporary file (%s), unknown error"),
+ sp->tpath);
+ parse_error = true;
+ }
+ fclose(sudoersin);
+ if (!parse_error) {
+ parse_error = !update_defaults(ctx, &parsed_policy, NULL,
+ SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER, true);
+ check_defaults_and_aliases(ctx);
+ }
+ sudoers_setlocale(oldlocale, NULL);
+
+ /*
+ * Got an error, prompt the user for what to do now.
+ */
+ if (parse_error) {
+ switch (whatnow()) {
+ case 'Q':
+ parse_error = false; /* ignore parse error */
+ break;
+ case 'x':
+ visudo_cleanup(); /* discard changes */
+ debug_return_bool(false);
+ case 'e':
+ default:
+ /* Edit file with the parse error */
+ TAILQ_FOREACH(sp, &sudoerslist, entries) {
+ if (errors == 0 || sp->errorline > 0) {
+ edit_sudoers(sp, editor, editor_argc, editor_argv,
+ sp->errorline);
+ }
+ }
+ break;
+ }
+ }
+
+ /* If any new #include directives were added, edit them too. */
+ if ((sp = TAILQ_NEXT(last, entries)) != NULL) {
+ bool modified = false;
+ do {
+ printf(_("press return to edit %s: "), sp->opath);
+ while ((ch = getchar()) != EOF && ch != '\r' && ch != '\n')
+ continue;
+ edit_sudoers(sp, editor, editor_argc, editor_argv, -1);
+ if (sp->modified)
+ modified = true;
+ } while ((sp = TAILQ_NEXT(sp, entries)) != NULL);
+
+ /* Reparse sudoers if newly added includes were modified. */
+ if (modified)
+ continue;
+ }
+
+ /* If all sudoers files parsed OK we are done. */
+ if (!parse_error)
+ break;
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Set the owner and mode on a sudoers temp file and
+ * move it into place. Returns true on success, else false.
+ */
+static bool
+install_sudoers(struct sudoersfile *sp, bool set_owner, bool set_mode)
+{
+ struct stat sb;
+ bool ret = false;
+ debug_decl(install_sudoers, SUDOERS_DEBUG_UTIL);
+
+ if (sp->tpath == NULL) {
+ ret = true;
+ goto done;
+ }
+
+ if (!sp->modified) {
+ /*
+ * No changes but fix owner/mode if needed.
+ */
+ (void) unlink(sp->tpath);
+ if (fstat(sp->fd, &sb) == 0) {
+ if (set_owner) {
+ if (sb.st_uid != sudoers_file_uid() || sb.st_gid != sudoers_file_gid()) {
+ if (chown(sp->opath, sudoers_file_uid(), sudoers_file_gid()) != 0) {
+ sudo_warn(U_("unable to set (uid, gid) of %s to (%u, %u)"),
+ sp->opath, (unsigned int)sudoers_file_uid(),
+ (unsigned int)sudoers_file_gid());
+ }
+ }
+ }
+ if (set_mode) {
+ if ((sb.st_mode & ACCESSPERMS) != sudoers_file_mode()) {
+ if (chmod(sp->opath, sudoers_file_mode()) != 0) {
+ sudo_warn(U_("unable to change mode of %s to 0%o"),
+ sp->opath, (unsigned int)sudoers_file_mode());
+ }
+ }
+ }
+ }
+ ret = true;
+ goto done;
+ }
+
+ /*
+ * Change mode and ownership of temp file before moving it into place
+ * to avoid a race condition.
+ */
+ if (!set_owner || !set_mode) {
+ /* Preserve owner/perms of the existing file. */
+ if (fstat(sp->fd, &sb) == -1)
+ sudo_fatal(U_("unable to stat %s"), sp->opath);
+ }
+ if (set_owner) {
+ if (chown(sp->tpath, sudoers_file_uid(), sudoers_file_gid()) != 0) {
+ sudo_warn(U_("unable to set (uid, gid) of %s to (%u, %u)"),
+ sp->tpath, (unsigned int)sudoers_file_uid(),
+ (unsigned int)sudoers_file_gid());
+ goto done;
+ }
+ } else {
+ if (chown(sp->tpath, sb.st_uid, sb.st_gid) != 0) {
+ sudo_warn(U_("unable to set (uid, gid) of %s to (%u, %u)"),
+ sp->tpath, (unsigned int)sb.st_uid, (unsigned int)sb.st_gid);
+ }
+ }
+ if (set_mode) {
+ if (chmod(sp->tpath, sudoers_file_mode()) != 0) {
+ sudo_warn(U_("unable to change mode of %s to 0%o"), sp->tpath,
+ (unsigned int)sudoers_file_mode());
+ goto done;
+ }
+ } else {
+ if (chmod(sp->tpath, sb.st_mode & ACCESSPERMS) != 0) {
+ sudo_warn(U_("unable to change mode of %s to 0%o"), sp->tpath,
+ (unsigned int)(sb.st_mode & ACCESSPERMS));
+ }
+ }
+
+ /*
+ * Now that we know sp->tpath parses correctly, it needs to be
+ * rename(2)'d to sp->dpath. If the rename(2) fails we try using
+ * mv(1) in case sp->tpath and sp->dpath are on different file systems.
+ */
+ if (rename(sp->tpath, sp->dpath) == 0) {
+ free(sp->tpath);
+ sp->tpath = NULL;
+ } else {
+ if (errno == EXDEV) {
+ char *av[4];
+ sudo_warnx(U_("%s and %s not on the same file system, using mv to rename"),
+ sp->tpath, sp->dpath);
+
+ /* Build up argument vector for the command */
+ av[0] = sudo_basename(_PATH_MV);
+ av[1] = sp->tpath;
+ av[2] = sp->dpath;
+ av[3] = NULL;
+
+ /* And run it... */
+ if (run_command(_PATH_MV, av) != 0) {
+ sudo_warnx(U_("command failed: '%s %s %s', %s unchanged"),
+ _PATH_MV, sp->tpath, sp->dpath, sp->opath);
+ goto done;
+ }
+ free(sp->tpath);
+ sp->tpath = NULL;
+ } else {
+ sudo_warn(U_("error renaming %s, %s unchanged"), sp->tpath,
+ sp->opath);
+ goto done;
+ }
+ }
+ ret = true;
+done:
+ debug_return_bool(ret);
+}
+
+/*
+ * Assuming a parse error occurred, prompt the user for what they want
+ * to do now. Returns the first letter of their choice.
+ */
+static int
+whatnow(void)
+{
+ int choice, c;
+ debug_decl(whatnow, SUDOERS_DEBUG_UTIL);
+
+ for (;;) {
+ (void) fputs(_("What now? "), stdout);
+ choice = getchar();
+ for (c = choice; c != '\r' && c != '\n' && c != EOF;)
+ c = getchar();
+
+ switch (choice) {
+ case EOF:
+ choice = 'x';
+ FALLTHROUGH;
+ case 'e':
+ case 'x':
+ case 'Q':
+ debug_return_int(choice);
+ default:
+ (void) puts(_("Options are:\n"
+ " (e)dit sudoers file again\n"
+ " e(x)it without saving changes to sudoers file\n"
+ " (Q)uit and save changes to sudoers file (DANGER!)\n"));
+ }
+ }
+}
+
+/*
+ * Install signal handlers for visudo.
+ */
+static void
+setup_signals(void)
+{
+ struct sigaction sa;
+ debug_decl(setup_signals, SUDOERS_DEBUG_UTIL);
+
+ /*
+ * Setup signal handlers to cleanup nicely.
+ */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = quit;
+ (void) sigaction(SIGTERM, &sa, NULL);
+ (void) sigaction(SIGHUP, &sa, NULL);
+ (void) sigaction(SIGINT, &sa, NULL);
+ (void) sigaction(SIGQUIT, &sa, NULL);
+
+ debug_return;
+}
+
+static int
+run_command(const char *path, char *const *argv)
+{
+ int status;
+ pid_t pid, rv;
+ debug_decl(run_command, SUDOERS_DEBUG_UTIL);
+
+ switch (pid = sudo_debug_fork()) {
+ case -1:
+ sudo_fatal(U_("unable to execute %s"), path);
+ case 0:
+ closefrom(STDERR_FILENO + 1);
+ execv(path, argv);
+ sudo_warn(U_("unable to run %s"), path);
+ _exit(127);
+ }
+
+ for (;;) {
+ rv = waitpid(pid, &status, 0);
+ if (rv == -1 && errno != EINTR)
+ break;
+ if (rv != -1 && !WIFSTOPPED(status))
+ break;
+ }
+
+ if (rv != -1)
+ rv = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
+ debug_return_int(rv);
+}
+
+static bool
+check_file(struct sudoers_context *ctx, const char *path, bool check_owner,
+ bool check_mode)
+{
+ struct stat sb;
+ bool ok = true;
+ debug_decl(check_file, SUDOERS_DEBUG_UTIL);
+
+ if (stat(path, &sb) == 0) {
+ if (check_owner) {
+ if (sb.st_uid != sudoers_file_uid() || sb.st_gid != sudoers_file_gid()) {
+ ok = false;
+ if (ctx->parser_conf.verbose) {
+ fprintf(stderr,
+ _("%s: wrong owner (uid, gid) should be (%u, %u)\n"),
+ path, (unsigned int)sudoers_file_uid(),
+ (unsigned int)sudoers_file_gid());
+ }
+ }
+ }
+ if (check_mode) {
+ if ((sb.st_mode & ALLPERMS) != sudoers_file_mode()) {
+ ok = false;
+ if (ctx->parser_conf.verbose) {
+ fprintf(stderr,
+ _("%s: bad permissions, should be mode 0%o\n"),
+ path, (unsigned int)sudoers_file_mode());
+ }
+ }
+ }
+ }
+ debug_return_bool(ok);
+}
+
+static bool
+check_syntax(struct sudoers_context *ctx, const char *path, bool check_owner,
+ bool check_mode)
+{
+ bool ok = false;
+ int fd, oldlocale;
+ char fname[PATH_MAX];
+ debug_decl(check_syntax, SUDOERS_DEBUG_UTIL);
+
+ if (strcmp(path, "-") == 0) {
+ sudoersin = stdin;
+ (void)strlcpy(fname, "stdin", sizeof(fname));
+ } else {
+ fd = sudo_open_conf_path(path, fname, sizeof(fname), NULL);
+ if (fd == -1 || (sudoersin = fdopen(fd, "r")) == NULL) {
+ if (ctx->parser_conf.verbose)
+ sudo_warn(U_("unable to open %s"), fname);
+ if (fd != -1)
+ close(fd);
+ goto done;
+ }
+ }
+ init_parser(ctx, fname);
+ sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
+ if (sudoersparse() && !parse_error) {
+ if (ctx->parser_conf.verbose)
+ sudo_warnx(U_("failed to parse %s file, unknown error"), fname);
+ parse_error = true;
+ }
+ if (!parse_error) {
+ parse_error = !update_defaults(ctx, &parsed_policy, NULL,
+ SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER, true);
+ check_defaults_and_aliases(ctx);
+ }
+ sudoers_setlocale(oldlocale, NULL);
+ ok = !parse_error;
+
+ if (!parse_error) {
+ struct sudoersfile *sp;
+
+ /* Parsed OK, check mode and owner. */
+ if (check_file(ctx, fname, check_owner, check_mode)) {
+ if (ctx->parser_conf.verbose)
+ (void) printf(_("%s: parsed OK\n"), fname);
+ } else {
+ ok = false;
+ }
+ TAILQ_FOREACH(sp, &sudoerslist, entries) {
+ if (check_file(ctx, sp->opath, check_owner, check_mode)) {
+ if (ctx->parser_conf.verbose)
+ (void) printf(_("%s: parsed OK\n"), sp->opath);
+ } else {
+ ok = false;
+ }
+ }
+ }
+
+done:
+ debug_return_bool(ok);
+}
+
+static bool
+lock_sudoers(struct sudoersfile *entry)
+{
+ int ch;
+ debug_decl(lock_sudoers, SUDOERS_DEBUG_UTIL);
+
+ if (!sudo_lock_file(entry->fd, SUDO_TLOCK)) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ sudo_warnx(U_("%s busy, try again later"), entry->opath);
+ debug_return_bool(false);
+ }
+ sudo_warn(U_("unable to lock %s"), entry->opath);
+ (void) fputs(_("Edit anyway? [y/N]"), stdout);
+ ch = getchar();
+ if (tolower(ch) != 'y')
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+/*
+ * Open (and lock) a new sudoers file.
+ * Returns a new struct sudoersfile on success or NULL on failure.
+ */
+static struct sudoersfile *
+new_sudoers(const char *path, bool doedit)
+{
+ const char *cp, *ep, *path_end;
+ struct sudoersfile *entry;
+ struct stat sb;
+ size_t len;
+ int fd = -1;
+ debug_decl(new_sudoersfile, SUDOERS_DEBUG_UTIL);
+
+ /* We always write to the first file in the colon-separated path. */
+ len = strcspn(path, ":");
+ entry = calloc(1, sizeof(*entry));
+ if (entry == NULL || (entry->dpath = strndup(path, len)) == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ /* Open the first file found in the colon-separated path. */
+ path_end = path + strlen(path);
+ for (cp = sudo_strsplit(path, path_end, ":", &ep);
+ cp != NULL; cp = sudo_strsplit(NULL, path_end, ":", &ep)) {
+
+ char fname[PATH_MAX];
+ len = (size_t)(ep - cp);
+ if (len >= sizeof(fname)) {
+ errno = ENAMETOOLONG;
+ break;
+ }
+ memcpy(fname, cp, len);
+ fname[len] = '\0';
+
+ /* Open in write mode for file locking. */
+ fd = open(fname, checkonly ? O_RDONLY : O_RDWR);
+ if (fd != -1) {
+ /* Store the path we actually opened. */
+ if ((entry->opath = strdup(fname)) == NULL) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ break;
+ }
+
+ /* If the file exists but we can't open it, that is a fatal error. */
+ if (errno != ENOENT) {
+ sudo_warn("%s", fname);
+ goto bad;
+ }
+ }
+ if (fd == -1) {
+ if (!checkonly) {
+ /* No sudoers file, create the destination file for editing. */
+ fd = open(entry->dpath, O_RDWR|O_CREAT, sudoers_file_mode());
+ entry->created = true;
+ }
+ if (fd == -1) {
+ sudo_warn("%s", entry->dpath);
+ goto bad;
+ }
+ entry->opath = entry->dpath;
+ }
+ if (fstat(fd, &sb) == -1) {
+ sudo_warn("%s", entry->opath);
+ goto bad;
+ }
+ if (!S_ISREG(sb.st_mode)) {
+ sudo_warnx(U_("%s is not a regular file"), entry->opath);
+ goto bad;
+ }
+ entry->fd = fd;
+ /* entry->tpath = NULL; */
+ /* entry->modified = false; */
+ entry->doedit = doedit;
+ if (!checkonly && !lock_sudoers(entry))
+ goto bad;
+ debug_return_ptr(entry);
+bad:
+ if (fd != -1)
+ close(fd);
+ if (entry->opath != entry->dpath)
+ free(entry->opath);
+ free(entry->dpath);
+ free(entry);
+ debug_return_ptr(NULL);
+}
+
+/*
+ * Used to open (and lock) the initial sudoers file and to also open
+ * any subsequent files #included via a callback from the parser.
+ */
+FILE *
+open_sudoers(const char *path, char **outfile, bool doedit, bool *keepopen)
+{
+ struct sudoersfile *entry;
+ size_t len;
+ FILE *fp;
+ debug_decl(open_sudoers, SUDOERS_DEBUG_UTIL);
+
+ /* Check for existing entry using the first file in path. */
+ len = strcspn(path, ":");
+ TAILQ_FOREACH(entry, &sudoerslist, entries) {
+ if (strncmp(path, entry->dpath, len) == 0 && entry->dpath[len] == '\0')
+ break;
+ }
+ if (entry == NULL) {
+ if (doedit && !edit_includes) {
+ /* Only edit the main sudoers file. */
+ if (strncmp(path, path_sudoers, len) != 0 ||
+ (path_sudoers[len] != '\0' && path_sudoers[len] != ':'))
+ doedit = false;
+ }
+ if ((entry = new_sudoers(path, doedit)) == NULL)
+ debug_return_ptr(NULL);
+ if ((fp = fdopen(entry->fd, "r")) == NULL)
+ sudo_fatal("%s", entry->opath);
+ TAILQ_INSERT_TAIL(&sudoerslist, entry, entries);
+ } else {
+ /* Already exists, open .tmp version if there is one. */
+ if (entry->tpath != NULL) {
+ if ((fp = fopen(entry->tpath, "r")) == NULL)
+ sudo_fatal("%s", entry->tpath);
+ } else {
+ if ((fp = fdopen(entry->fd, "r")) == NULL)
+ sudo_fatal("%s", entry->opath);
+ rewind(fp);
+ }
+ }
+ if (keepopen != NULL)
+ *keepopen = true;
+ if (outfile != NULL) {
+ *outfile = sudo_rcstr_dup(entry->opath);
+ if (*outfile == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ }
+ debug_return_ptr(fp);
+}
+
+/*
+ * Support "visudo -x" for backwards compatibility.
+ * To be removed in a future version of sudo.
+ */
+static void
+export_sudoers(const char *infile, const char *outfile)
+{
+ char pathbuf[PATH_MAX];
+ int fd;
+ debug_decl(export_sudoers, SUDOERS_DEBUG_UTIL);
+
+ sudo_warnx("%s",
+ U_("the -x option will be removed in a future release"));
+ sudo_warnx("%s",
+ U_("please consider using the cvtsudoers utility instead"));
+
+ /* Export the first sudoers file that exists in the path. */
+ fd = sudo_open_conf_path(infile, pathbuf, sizeof(pathbuf), NULL);
+ if (fd != -1) {
+ close(fd);
+ infile = pathbuf;
+ }
+ execlp("cvtsudoers", "cvtsudoers", "-f", "json", "-o", outfile,
+ infile, (char *)0);
+ sudo_fatal(U_("unable to execute %s"), "cvtsudoers");
+}
+
+/* Display unused aliases from check_aliases(). */
+static int
+print_unused(struct sudoers_parse_tree *parse_tree, struct alias *a, void *v)
+{
+ const bool quiet = *((bool *)v);
+
+ if (!quiet) {
+ fprintf(stderr, U_("Warning: %s:%d:%d: unused %s \"%s\""), a->file,
+ a->line, a->column, alias_type_to_string(a->type), a->name);
+ fputc('\n', stderr);
+ }
+ return 0;
+}
+
+static void
+parse_sudoers_options(struct sudoers_context *ctx)
+{
+ struct plugin_info_list *plugins;
+ debug_decl(parse_sudoers_options, SUDOERS_DEBUG_UTIL);
+
+ plugins = sudo_conf_plugins();
+ if (plugins) {
+ struct plugin_info *info;
+
+ TAILQ_FOREACH(info, plugins, entries) {
+ if (strcmp(info->symbol_name, "sudoers_policy") == 0)
+ break;
+ }
+ if (info != NULL && info->options != NULL) {
+ char * const *cur;
+
+#define MATCHES(s, v) \
+ (strncmp((s), (v), sizeof(v) - 1) == 0 && (s)[sizeof(v) - 1] != '\0')
+
+ for (cur = info->options; *cur != NULL; cur++) {
+ const char *errstr, *p;
+ id_t id;
+ mode_t mode;
+
+ if (MATCHES(*cur, "sudoers_file=")) {
+ path_sudoers = *cur + sizeof("sudoers_file=") - 1;
+ continue;
+ }
+ if (MATCHES(*cur, "sudoers_uid=")) {
+ p = *cur + sizeof("sudoers_uid=") - 1;
+ id = sudo_strtoid(p, &errstr);
+ if (errstr == NULL)
+ ctx->parser_conf.sudoers_uid = (uid_t)id;
+ continue;
+ }
+ if (MATCHES(*cur, "sudoers_gid=")) {
+ p = *cur + sizeof("sudoers_gid=") - 1;
+ id = sudo_strtoid(p, &errstr);
+ if (errstr == NULL)
+ ctx->parser_conf.sudoers_gid = (gid_t)id;
+ continue;
+ }
+ if (MATCHES(*cur, "sudoers_mode=")) {
+ p = *cur + sizeof("sudoers_mode=") - 1;
+ mode = sudo_strtomode(p, &errstr);
+ if (errstr == NULL)
+ ctx->parser_conf.sudoers_mode = mode;
+ continue;
+ }
+ }
+#undef MATCHES
+ }
+ }
+ debug_return;
+}
+
+/*
+ * Unlink any sudoers temp files that remain.
+ */
+static void
+visudo_cleanup(void)
+{
+ struct sudoersfile *sp;
+
+ TAILQ_FOREACH(sp, &sudoerslist, entries) {
+ if (sp->tpath != NULL)
+ (void) unlink(sp->tpath);
+ }
+}
+
+/*
+ * Unlink sudoers temp files (if any) and exit.
+ */
+static void
+quit(int signo)
+{
+ struct iovec iov[4];
+
+ visudo_cleanup();
+
+#define emsg " exiting due to signal: "
+ iov[0].iov_base = (char *)getprogname();
+ iov[0].iov_len = strlen(iov[0].iov_base);
+ iov[1].iov_base = (char *)emsg;
+ iov[1].iov_len = sizeof(emsg) - 1;
+ iov[2].iov_base = strsignal(signo);
+ iov[2].iov_len = strlen(iov[2].iov_base);
+ iov[3].iov_base = (char *)"\n";
+ iov[3].iov_len = 1;
+ ignore_result(writev(STDERR_FILENO, iov, 4));
+ _exit(signo);
+}
+
+#define VISUDO_USAGE "usage: %s [-chqsV] [[-f] sudoers ]\n"
+
+sudo_noreturn static void
+usage(void)
+{
+ (void) fprintf(stderr, VISUDO_USAGE, getprogname());
+ exit(EXIT_FAILURE);
+}
+
+sudo_noreturn static void
+help(void)
+{
+ (void) printf(_("%s - safely edit the sudoers file\n\n"), getprogname());
+ (void) printf(VISUDO_USAGE, getprogname());
+ (void) puts(_("\nOptions:\n"
+ " -c, --check check-only mode\n"
+ " -f, --file=sudoers specify sudoers file location\n"
+ " -h, --help display help message and exit\n"
+ " -I, --no-includes do not edit include files\n"
+ " -q, --quiet less verbose (quiet) syntax error messages\n"
+ " -s, --strict strict syntax checking\n"
+ " -V, --version display version information and exit\n"));
+ exit(EXIT_SUCCESS);
+}
diff --git a/plugins/sudoers/visudo_cb.c b/plugins/sudoers/visudo_cb.c
new file mode 100644
index 0000000..8b6309c
--- /dev/null
+++ b/plugins/sudoers/visudo_cb.c
@@ -0,0 +1,40 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sudoers.h>
+
+/*
+ * Set visudo Defaults callbacks.
+ */
+void
+set_callbacks(void)
+{
+ debug_decl(set_callbacks, SUDOERS_DEBUG_UTIL);
+
+ /* Set locale callback. */
+ sudo_defs_table[I_SUDOERS_LOCALE].callback = sudoers_locale_callback;
+
+ debug_return;
+}
diff --git a/plugins/system_group/Makefile.in b/plugins/system_group/Makefile.in
new file mode 100644
index 0000000..9bdebde
--- /dev/null
+++ b/plugins/system_group/Makefile.in
@@ -0,0 +1,226 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2011-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+devdir = @devdir@
+scriptdir = $(top_srcdir)/scripts
+incdir = $(top_srcdir)/include
+cross_compiling = @CROSS_COMPILING@
+
+# Compiler & tools to use
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+SED = @SED@
+AWK = @AWK@
+
+# Our install program supports extra flags...
+INSTALL = $(SHELL) $(scriptdir)/install-sh -c
+INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
+INSTALL_BACKUP = @INSTALL_BACKUP@
+
+# Libraries
+LT_LIBS = $(top_builddir)/lib/util/libsudo_util.la
+LIBS = $(LT_LIBS)
+
+# C preprocessor flags
+CPPFLAGS = -I$(incdir) -I$(top_builddir) @CPPFLAGS@
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+
+# Flags to pass to the link stage
+LDFLAGS = @LDFLAGS@
+LT_LDFLAGS = @LT_LDFLAGS@ @LT_LDEXPORTS@
+
+# Flags to pass to libtool
+LTFLAGS = --tag=disable-static
+
+# Address sanitizer flags
+ASAN_CFLAGS = @ASAN_CFLAGS@
+ASAN_LDFLAGS = @ASAN_LDFLAGS@
+
+# PIE flags
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+
+# Stack smashing protection flags
+HARDENING_CFLAGS = @HARDENING_CFLAGS@
+HARDENING_LDFLAGS = @HARDENING_LDFLAGS@
+
+# cppcheck options, usually set in the top-level Makefile
+CPPCHECK_OPTS = -q --enable=warning,performance,portability --suppress=constStatement --suppress=compareBoolExpressionWithInt --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
+
+# splint options, usually set in the top-level Makefile
+SPLINT_OPTS = -D__restrict= -checks
+
+# PVS-studio options
+PVS_CFG = $(top_srcdir)/PVS-Studio.cfg
+PVS_IGNORE = 'V707,V011,V002,V536'
+PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
+
+# Where to install things...
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+sysconfdir = @sysconfdir@
+adminconfdir = @adminconfdir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+localstatedir = @localstatedir@
+plugindir = @plugindir@
+
+# File mode and map file to use for shared libraries/objects
+shlib_enable = @SHLIB_ENABLE@
+shlib_mode = @SHLIB_MODE@
+shlib_exp = $(srcdir)/system_group.exp
+shlib_map = system_group.map
+shlib_opt = system_group.opt
+
+# User and group ids the installed files should be "owned" by
+install_uid = 0
+install_gid = 0
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+OBJS = system_group.lo
+
+IOBJS = system_group.i
+
+POBJS = system_group.plog
+
+LIBOBJDIR = $(top_builddir)/@ac_config_libobj_dir@/
+
+VERSION = @PACKAGE_VERSION@
+
+all: system_group.la
+
+depend:
+ $(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
+ --builddir=$(abs_top_builddir) plugins/system_group/Makefile.in
+ cd $(top_builddir) && ./config.status --file plugins/system_group/Makefile
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file plugins/system_group/Makefile
+
+.SUFFIXES: .c .h .i .lo .plog
+
+.c.lo:
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.i:
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+
+.i.plog:
+ ifile=$<; rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $${ifile%i}c --i-file $< --output-file $@
+
+$(shlib_map): $(shlib_exp)
+ @$(AWK) 'BEGIN { print "{\n\tglobal:" } { print "\t\t"$$0";" } END { print "\tlocal:\n\t\t*;\n};" }' $(shlib_exp) > $@
+
+$(shlib_opt): $(shlib_exp)
+ @$(SED) 's/^/+e /' $(shlib_exp) > $@
+
+system_group.la: $(OBJS) $(LT_LIBS) @LT_LDDEP@
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) $(ASAN_LDFLAGS) $(HARDENING_LDFLAGS) $(LT_LDFLAGS) -o $@ $(OBJS) $(LIBS) -module -avoid-version -rpath $(plugindir) -shrext .so
+
+pre-install:
+
+install: install-plugin
+
+install-dirs:
+ $(SHELL) $(scriptdir)/mkinstalldirs $(DESTDIR)$(plugindir)
+
+install-binaries:
+
+install-includes:
+
+install-doc:
+
+install-plugin: install-dirs system_group.la
+ if [ X"$(shlib_enable)" = X"yes" ]; then \
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) $(INSTALL_OWNER) -m $(shlib_mode) system_group.la $(DESTDIR)$(plugindir); \
+ fi
+
+install-fuzzer:
+
+uninstall:
+ -$(LIBTOOL) $(LTFLAGS) --mode=uninstall rm -f $(DESTDIR)$(plugindir)/system_group.la
+ -test -z "$(INSTALL_BACKUP)" || \
+ rm -f $(DESTDIR)$(plugindir)/system_group.so$(INSTALL_BACKUP)
+
+splint:
+ splint $(SPLINT_OPTS) -I$(incdir) -I$(top_builddir) $(srcdir)/*.c
+
+cppcheck:
+ cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) $(srcdir)/*.c
+
+pvs-log-files: $(POBJS)
+
+pvs-studio: $(POBJS)
+ plog-converter $(PVS_LOG_OPTS) $(POBJS)
+
+fuzz:
+
+check-fuzzer:
+
+check: check-fuzzer
+
+check-verbose: check
+
+clean:
+ -$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f *.lo *.o *.la
+ -rm -f *.i *.plog stamp-* core *.core core.*
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile .libs $(shlib_map) $(shlib_opt)
+
+clobber: distclean
+
+realclean: distclean
+ rm -f TAGS tags
+
+cleandir: realclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean
+
+# Autogenerated dependencies, do not modify
+system_group.lo: $(srcdir)/system_group.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_dso.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/system_group.c
+system_group.i: $(srcdir)/system_group.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_dso.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+system_group.plog: system_group.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/system_group.c --i-file $< --output-file $@
diff --git a/plugins/system_group/system_group.c b/plugins/system_group/system_group.c
new file mode 100644
index 0000000..bf877b6
--- /dev/null
+++ b/plugins/system_group/system_group.c
@@ -0,0 +1,144 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2014 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <grp.h>
+
+#include <sudo_compat.h>
+#include <sudo_dso.h>
+#include <sudo_plugin.h>
+#include <sudo_util.h>
+
+/*
+ * Sudoers group plugin that does group name-based lookups using the system
+ * group database functions, similar to how sudo behaved prior to 1.7.3.
+ * This can be used on systems where lookups by group ID are problematic.
+ */
+
+typedef struct group * (*sysgroup_getgrnam_t)(const char *);
+typedef struct group * (*sysgroup_getgrgid_t)(gid_t);
+typedef void (*sysgroup_gr_delref_t)(struct group *);
+
+static sysgroup_getgrnam_t sysgroup_getgrnam;
+static sysgroup_getgrgid_t sysgroup_getgrgid;
+static sysgroup_gr_delref_t sysgroup_gr_delref;
+static bool need_setent;
+
+static int
+sysgroup_init(int version, sudo_printf_t plugin_printf, char *const argv[])
+{
+ void *handle;
+
+ if (SUDO_API_VERSION_GET_MAJOR(version) != GROUP_API_VERSION_MAJOR) {
+ plugin_printf(SUDO_CONV_ERROR_MSG,
+ "sysgroup_group: incompatible major version %d, expected %d\n",
+ SUDO_API_VERSION_GET_MAJOR(version),
+ GROUP_API_VERSION_MAJOR);
+ return -1;
+ }
+
+ /* Share group cache with sudo if possible. */
+ handle = sudo_dso_findsym(SUDO_DSO_DEFAULT, "sudo_getgrnam");
+ if (handle != NULL) {
+ sysgroup_getgrnam = (sysgroup_getgrnam_t)handle;
+ } else {
+ sysgroup_getgrnam = (sysgroup_getgrnam_t)getgrnam;
+ need_setent = true;
+ }
+
+ handle = sudo_dso_findsym(SUDO_DSO_DEFAULT, "sudo_getgrgid");
+ if (handle != NULL) {
+ sysgroup_getgrgid = (sysgroup_getgrgid_t)handle;
+ } else {
+ sysgroup_getgrgid = (sysgroup_getgrgid_t)getgrgid;
+ need_setent = true;
+ }
+
+ handle = sudo_dso_findsym(SUDO_DSO_DEFAULT, "sudo_gr_delref");
+ if (handle != NULL)
+ sysgroup_gr_delref = (sysgroup_gr_delref_t)handle;
+
+ if (need_setent)
+ setgrent();
+
+ return true;
+}
+
+static void
+sysgroup_cleanup(void)
+{
+ if (need_setent)
+ endgrent();
+}
+
+/*
+ * Returns true if "user" is a member of "group", else false.
+ */
+static int
+sysgroup_query(const char *user, const char *group, const struct passwd *pwd)
+{
+ char **member;
+ struct group *grp;
+
+ grp = sysgroup_getgrnam(group);
+ if (grp == NULL && group[0] == '#' && group[1] != '\0') {
+ const char *errstr;
+ gid_t gid = sudo_strtoid(group + 1, &errstr);
+ if (errstr == NULL)
+ grp = sysgroup_getgrgid(gid);
+ }
+ if (grp != NULL) {
+ if (grp->gr_mem != NULL) {
+ for (member = grp->gr_mem; *member != NULL; member++) {
+ if (strcasecmp(user, *member) == 0) {
+ if (sysgroup_gr_delref)
+ sysgroup_gr_delref(grp);
+ return true;
+ }
+ }
+ }
+ if (sysgroup_gr_delref)
+ sysgroup_gr_delref(grp);
+ }
+
+ return false;
+}
+
+sudo_dso_public struct sudoers_group_plugin group_plugin = {
+ GROUP_API_VERSION,
+ sysgroup_init,
+ sysgroup_cleanup,
+ sysgroup_query
+};
diff --git a/plugins/system_group/system_group.exp b/plugins/system_group/system_group.exp
new file mode 100644
index 0000000..a859d6c
--- /dev/null
+++ b/plugins/system_group/system_group.exp
@@ -0,0 +1 @@
+group_plugin
diff --git a/po/README b/po/README
new file mode 100644
index 0000000..cff4d29
--- /dev/null
+++ b/po/README
@@ -0,0 +1,14 @@
+NLS Translations for sudo are coordinated through the Translation
+Project, at https://translationproject.org/
+
+If you would like to contribute a translation for sudo, please join
+a translation team at the Translation Project instead of contributing
+a po file directly. This will avoid duplicated work if there is
+already a translation in progress. If you would like to become a
+member of a translation team, please follow the instructions at
+https://translationproject.org/html/translators.html
+
+The messages in sudo are split into two domains: sudo and sudoers.
+The former is used by the sudo front-end and utility functions.
+The latter is used by the sudoers policy and I/O logging plug-ins
+as well as the sudoers-specific commands visudo and sudoreplay.
diff --git a/po/ast.mo b/po/ast.mo
new file mode 100644
index 0000000..c5b6c74
--- /dev/null
+++ b/po/ast.mo
Binary files differ
diff --git a/po/ast.po b/po/ast.po
new file mode 100644
index 0000000..88ccbe6
--- /dev/null
+++ b/po/ast.po
@@ -0,0 +1,928 @@
+# Asturian translation for sudo
+# Portable object template file for sudo
+# This file is put in the public domain.
+#
+# Todd C. Miller <Todd.Miller@sudo.ws>, 2011-2016.
+# enolp <enolp@softastur.org>, 2018.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.8.26b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2018-10-29 08:31-0600\n"
+"PO-Revision-Date: 2018-11-08 21:35+0100\n"
+"Last-Translator: enolp <enolp@softastur.org>\n"
+"Language-Team: Asturian <alministradores@softastur.org>\n"
+"Language: ast\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Lokalize 2.0\n"
+
+#: lib/util/aix.c:90 lib/util/aix.c:177
+msgid "unable to open userdb"
+msgstr "nun pue abrise userdb"
+
+#: lib/util/aix.c:232
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "nun pue cambiase al rexistru «%s» de %s"
+
+#: lib/util/aix.c:257
+msgid "unable to restore registry"
+msgstr "nun pue restaurase'l rexistru"
+
+#: lib/util/aix.c:280 lib/util/gidlist.c:69 lib/util/gidlist.c:79
+#: lib/util/sudo_conf.c:191 lib/util/sudo_conf.c:277 lib/util/sudo_conf.c:354
+#: lib/util/sudo_conf.c:558 src/conversation.c:82 src/exec_common.c:112
+#: src/exec_common.c:128 src/exec_common.c:137 src/exec_monitor.c:210
+#: src/exec_monitor.c:465 src/exec_monitor.c:471 src/exec_monitor.c:479
+#: src/exec_monitor.c:487 src/exec_monitor.c:494 src/exec_monitor.c:501
+#: src/exec_monitor.c:508 src/exec_monitor.c:515 src/exec_monitor.c:522
+#: src/exec_monitor.c:529 src/exec_monitor.c:536 src/exec_nopty.c:212
+#: src/exec_nopty.c:218 src/exec_nopty.c:227 src/exec_nopty.c:234
+#: src/exec_nopty.c:241 src/exec_nopty.c:248 src/exec_nopty.c:255
+#: src/exec_nopty.c:262 src/exec_nopty.c:269 src/exec_nopty.c:276
+#: src/exec_nopty.c:283 src/exec_nopty.c:290 src/exec_nopty.c:297
+#: src/exec_nopty.c:305 src/exec_nopty.c:467 src/exec_pty.c:778
+#: src/exec_pty.c:787 src/exec_pty.c:844 src/exec_pty.c:994
+#: src/exec_pty.c:1157 src/exec_pty.c:1163 src/exec_pty.c:1172
+#: src/exec_pty.c:1179 src/exec_pty.c:1186 src/exec_pty.c:1193
+#: src/exec_pty.c:1200 src/exec_pty.c:1207 src/exec_pty.c:1214
+#: src/exec_pty.c:1221 src/exec_pty.c:1228 src/exec_pty.c:1235
+#: src/exec_pty.c:1243 src/exec_pty.c:1661 src/load_plugins.c:57
+#: src/load_plugins.c:70 src/load_plugins.c:219 src/load_plugins.c:240
+#: src/load_plugins.c:309 src/load_plugins.c:315 src/load_plugins.c:329
+#: src/load_plugins.c:335 src/parse_args.c:182 src/parse_args.c:203
+#: src/parse_args.c:278 src/parse_args.c:565 src/parse_args.c:587
+#: src/preserve_fds.c:52 src/preserve_fds.c:137 src/selinux.c:89
+#: src/selinux.c:314 src/selinux.c:437 src/selinux.c:446 src/sesh.c:115
+#: src/sudo.c:616 src/sudo.c:676 src/sudo.c:686 src/sudo.c:706 src/sudo.c:725
+#: src/sudo.c:734 src/sudo.c:743 src/sudo.c:760 src/sudo.c:801 src/sudo.c:811
+#: src/sudo.c:834 src/sudo.c:1071 src/sudo.c:1092 src/sudo.c:1266
+#: src/sudo.c:1382 src/sudo_edit.c:256 src/sudo_edit.c:789 src/sudo_edit.c:886
+#: src/sudo_edit.c:1000 src/sudo_edit.c:1020
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:280 lib/util/gidlist.c:69 lib/util/sudo_conf.c:192
+#: lib/util/sudo_conf.c:277 lib/util/sudo_conf.c:354 lib/util/sudo_conf.c:558
+#: src/conversation.c:83 src/exec_common.c:112 src/exec_common.c:129
+#: src/exec_common.c:138 src/exec_monitor.c:465 src/exec_monitor.c:471
+#: src/exec_monitor.c:479 src/exec_monitor.c:487 src/exec_monitor.c:494
+#: src/exec_monitor.c:501 src/exec_monitor.c:508 src/exec_monitor.c:515
+#: src/exec_monitor.c:522 src/exec_monitor.c:529 src/exec_monitor.c:536
+#: src/exec_nopty.c:212 src/exec_nopty.c:218 src/exec_nopty.c:227
+#: src/exec_nopty.c:234 src/exec_nopty.c:241 src/exec_nopty.c:248
+#: src/exec_nopty.c:255 src/exec_nopty.c:262 src/exec_nopty.c:269
+#: src/exec_nopty.c:276 src/exec_nopty.c:283 src/exec_nopty.c:290
+#: src/exec_nopty.c:297 src/exec_nopty.c:305 src/exec_pty.c:778
+#: src/exec_pty.c:787 src/exec_pty.c:844 src/exec_pty.c:1157
+#: src/exec_pty.c:1163 src/exec_pty.c:1172 src/exec_pty.c:1179
+#: src/exec_pty.c:1186 src/exec_pty.c:1193 src/exec_pty.c:1200
+#: src/exec_pty.c:1207 src/exec_pty.c:1214 src/exec_pty.c:1221
+#: src/exec_pty.c:1228 src/exec_pty.c:1235 src/exec_pty.c:1243
+#: src/exec_pty.c:1661 src/load_plugins.c:219 src/load_plugins.c:240
+#: src/load_plugins.c:309 src/load_plugins.c:315 src/load_plugins.c:329
+#: src/load_plugins.c:335 src/parse_args.c:182 src/parse_args.c:204
+#: src/parse_args.c:278 src/parse_args.c:565 src/parse_args.c:587
+#: src/preserve_fds.c:52 src/preserve_fds.c:137 src/selinux.c:89
+#: src/selinux.c:314 src/selinux.c:437 src/selinux.c:446 src/sesh.c:115
+#: src/sudo.c:616 src/sudo.c:834 src/sudo.c:1071 src/sudo.c:1092
+#: src/sudo.c:1266 src/sudo.c:1382 src/sudo_edit.c:256 src/sudo_edit.c:789
+#: src/sudo_edit.c:886 src/sudo_edit.c:1000 src/sudo_edit.c:1020
+msgid "unable to allocate memory"
+msgstr "nun pue allugase memoria"
+
+#: lib/util/strsignal.c:53
+msgid "Unknown signal"
+msgstr "Señal desconocida"
+
+#: lib/util/strtoid.c:82 lib/util/strtoid.c:129 lib/util/strtoid.c:157
+#: lib/util/strtomode.c:54 lib/util/strtonum.c:63 lib/util/strtonum.c:181
+msgid "invalid value"
+msgstr "valor non válidu"
+
+#: lib/util/strtoid.c:89 lib/util/strtoid.c:136 lib/util/strtoid.c:164
+#: lib/util/strtomode.c:60 lib/util/strtonum.c:66 lib/util/strtonum.c:193
+msgid "value too large"
+msgstr "el valor ye pergrande"
+
+#: lib/util/strtoid.c:91 lib/util/strtoid.c:142 lib/util/strtomode.c:60
+#: lib/util/strtonum.c:66 lib/util/strtonum.c:187
+msgid "value too small"
+msgstr "el valor ye perpequeñu"
+
+#: lib/util/sudo_conf.c:210
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "valor non válidu de Path «%s» en %s, llinia %u"
+
+#: lib/util/sudo_conf.c:376 lib/util/sudo_conf.c:429
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "valor non válidu pa %s «%s» en %s, llinia %u"
+
+#: lib/util/sudo_conf.c:397
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "nun se sofita la fonte de grupos «%s» en %s, llinia %u"
+
+#: lib/util/sudo_conf.c:413
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "grupos máximos non válidos «%s» en %s, llinia %u"
+
+#: lib/util/sudo_conf.c:574
+#, c-format
+msgid "unable to stat %s"
+msgstr "nun pue facese stat a %s"
+
+#: lib/util/sudo_conf.c:577
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s nun ye un ficheru regular"
+
+#: lib/util/sudo_conf.c:580
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s ye propiedá del UID %u, debería ser %u"
+
+#: lib/util/sudo_conf.c:584
+#, c-format
+msgid "%s is world writable"
+msgstr "%s ye escribible por tol mundu"
+
+#: lib/util/sudo_conf.c:587
+#, c-format
+msgid "%s is group writable"
+msgstr "%s ye escribible pol grupu"
+
+#: lib/util/sudo_conf.c:597 src/selinux.c:213 src/selinux.c:230 src/sudo.c:360
+#, c-format
+msgid "unable to open %s"
+msgstr "nun pue abrise %s"
+
+#: src/exec.c:165
+#, c-format
+msgid "unknown login class %s"
+msgstr "desconozse la clas d'aniciu de sesión %s"
+
+#: src/exec.c:178
+msgid "unable to set user context"
+msgstr "nun pue afitase'l contestu d'usuariu"
+
+#: src/exec.c:194
+msgid "unable to set process priority"
+msgstr "nun pue afitase la prioridá del procesu"
+
+#: src/exec.c:202
+#, c-format
+msgid "unable to change root to %s"
+msgstr "nun pue camudase root a %s"
+
+#: src/exec.c:215 src/exec.c:221 src/exec.c:228
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "nun pue camudase al UID de runas (%u, %u)"
+
+#: src/exec.c:246
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "nun pue camudase al direutoriu %s"
+
+#: src/exec.c:345 src/exec_monitor.c:574 src/exec_monitor.c:576
+#: src/exec_nopty.c:525 src/exec_pty.c:522 src/exec_pty.c:1329
+#: src/exec_pty.c:1331 src/signal.c:148 src/signal.c:162
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "nun pue afitase'l remanador pa la señal %d"
+
+#: src/exec_common.c:171
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "nun pue desaniciase PRIV_PROC_EXEC de PRIV_LIMIT"
+
+#: src/exec_monitor.c:364
+msgid "error reading from socketpair"
+msgstr "fallu na llectura del socketpair"
+
+#: src/exec_monitor.c:381
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "nun s'esperaba la triba de rempuesta en backchannel: %d"
+
+#: src/exec_monitor.c:473 src/exec_monitor.c:481 src/exec_monitor.c:489
+#: src/exec_monitor.c:496 src/exec_monitor.c:503 src/exec_monitor.c:510
+#: src/exec_monitor.c:517 src/exec_monitor.c:524 src/exec_monitor.c:531
+#: src/exec_monitor.c:538 src/exec_nopty.c:220 src/exec_nopty.c:229
+#: src/exec_nopty.c:236 src/exec_nopty.c:243 src/exec_nopty.c:250
+#: src/exec_nopty.c:257 src/exec_nopty.c:264 src/exec_nopty.c:271
+#: src/exec_nopty.c:278 src/exec_nopty.c:285 src/exec_nopty.c:292
+#: src/exec_nopty.c:299 src/exec_nopty.c:307 src/exec_pty.c:644
+#: src/exec_pty.c:649 src/exec_pty.c:746 src/exec_pty.c:753 src/exec_pty.c:850
+#: src/exec_pty.c:1165 src/exec_pty.c:1174 src/exec_pty.c:1181
+#: src/exec_pty.c:1188 src/exec_pty.c:1195 src/exec_pty.c:1202
+#: src/exec_pty.c:1209 src/exec_pty.c:1216 src/exec_pty.c:1223
+#: src/exec_pty.c:1230 src/exec_pty.c:1237 src/exec_pty.c:1614
+#: src/exec_pty.c:1624 src/exec_pty.c:1669 src/exec_pty.c:1676
+#: src/exec_pty.c:1703
+msgid "unable to add event to queue"
+msgstr "nun pue amestase l'eventu a la cola"
+
+#: src/exec_monitor.c:592
+msgid "unable to set controlling tty"
+msgstr "nun pue afitase la TTY controladora"
+
+#: src/exec_monitor.c:600 src/exec_nopty.c:364 src/exec_pty.c:1408
+#: src/exec_pty.c:1429 src/exec_pty.c:1449 src/tgetpass.c:292
+msgid "unable to create pipe"
+msgstr "nun pue crease la tubería"
+
+#: src/exec_monitor.c:608
+msgid "unable to receive message from parent"
+msgstr "nun pue recibise'l mensaxe del pá"
+
+#: src/exec_monitor.c:614 src/exec_nopty.c:382 src/exec_pty.c:1487
+#: src/tgetpass.c:296
+msgid "unable to fork"
+msgstr "nun pue biforcase"
+
+#: src/exec_monitor.c:628 src/sesh.c:125 src/sudo.c:1130
+#, c-format
+msgid "unable to execute %s"
+msgstr "nun pue executase %s"
+
+#: src/exec_monitor.c:711 src/exec_nopty.c:435
+msgid "unable to restore tty label"
+msgstr "nun pue restaurase la etiqueta de TTY"
+
+#: src/exec_nopty.c:358 src/exec_pty.c:1338
+msgid "policy plugin failed session initialization"
+msgstr "el complementu de polítiques falló l'aniciu de la sesión"
+
+#: src/exec_nopty.c:424 src/exec_pty.c:1574
+msgid "error in event loop"
+msgstr "fallu nel bucle d'eventos"
+
+#: src/exec_nopty.c:533 src/exec_pty.c:557 src/signal.c:110
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "nun pue restaurase'l remanador pa la señal %d"
+
+#: src/exec_pty.c:156
+msgid "unable to allocate pty"
+msgstr "nun pue allguase la PTY"
+
+#: src/exec_pty.c:1318
+msgid "unable to create sockets"
+msgstr "nun puen crease ralures"
+
+#: src/exec_pty.c:1531
+msgid "unable to send message to monitor process"
+msgstr "nun pue unviase'l mensaxe pa supervisar el procesu"
+
+#: src/load_plugins.c:55 src/load_plugins.c:68 src/load_plugins.c:90
+#: src/load_plugins.c:120 src/load_plugins.c:128 src/load_plugins.c:134
+#: src/load_plugins.c:175 src/load_plugins.c:183 src/load_plugins.c:190
+#: src/load_plugins.c:196
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "fallu en %s, llinia %d mentanto se cargaba'l complementu «%s»"
+
+#: src/load_plugins.c:92
+#, c-format
+msgid "%s%s: %s"
+msgstr "%s%s: %s"
+
+#: src/load_plugins.c:130
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s ser propiedá del UID %d"
+
+#: src/load_plugins.c:136
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "%s namái ha editalu'l dueñu"
+
+#: src/load_plugins.c:177
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "nun pue cargase %s: %s"
+
+#: src/load_plugins.c:185
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "nun pue alcontrase'l símbolu «%s» en %s"
+
+#: src/load_plugins.c:192
+#, c-format
+msgid "unknown policy type %d found in %s"
+msgstr "desconozse la triba de política %d alcontrada en %s"
+
+#: src/load_plugins.c:198
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "la versión mayor %d (esperábase la %d) del complementu que s'alcontró en %s ye incompatible"
+
+#: src/load_plugins.c:207
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "inorando'l complementu de polítiques «%s» en %s, llinia %d"
+
+#: src/load_plugins.c:209
+msgid "only a single policy plugin may be specified"
+msgstr "namái podría especificase un complementu de polítiques"
+
+#: src/load_plugins.c:212
+#, c-format
+msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+msgstr "inorando'l complementu de polítiques duplicáu «%s» en %s, llinia %d"
+
+#: src/load_plugins.c:231
+#, c-format
+msgid "ignoring duplicate I/O plugin \"%s\" in %s, line %d"
+msgstr "inorando'l complementu d'E/S duplicáu «%s» en %s, llinia %d"
+
+#: src/load_plugins.c:347
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "el complementu de polítiques %s nun inclúi un métodu check_policy"
+
+#: src/net_ifs.c:180 src/net_ifs.c:197 src/net_ifs.c:342 src/sudo.c:470
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "fallu internu, sobrecarga de %s"
+
+#: src/parse_args.c:224
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "nome non válidu de variable d'entornu: %s"
+
+#: src/parse_args.c:320
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "l'argumentu pa -C ha ser un númberu mayor o iguar que 3"
+
+#: src/parse_args.c:505
+msgid "you may not specify both the `-i' and `-s' options"
+msgstr "nun podríes especificar les opciones «-i» y «-s»"
+
+#: src/parse_args.c:509
+msgid "you may not specify both the `-i' and `-E' options"
+msgstr "nun podríes especificar les opciones «-i» y «-E»"
+
+#: src/parse_args.c:519
+msgid "the `-E' option is not valid in edit mode"
+msgstr "la opción «-E» nun ye válida nel mou edición"
+
+#: src/parse_args.c:521
+msgid "you may not specify environment variables in edit mode"
+msgstr "nun podríes especificar les variables d'entornu nel mou edición"
+
+#: src/parse_args.c:529
+msgid "the `-U' option may only be used with the `-l' option"
+msgstr "la opción «-U» namái podría usase xunto cola opción «-l»"
+
+#: src/parse_args.c:533
+msgid "the `-A' and `-S' options may not be used together"
+msgstr "les opciones «-A» y «-S» nun podríen usase xuntes"
+
+#: src/parse_args.c:609
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit nun se sofita nesta plataforma"
+
+#: src/parse_args.c:682
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Namái podría especificase una de les opciones -e, -h, -i, -K, -l, -s, -v ó -V"
+
+#: src/parse_args.c:696
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - edita ficheros como otru usuariu\n"
+"\n"
+
+#: src/parse_args.c:698
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - executa un comandu como otru usuariu\n"
+"\n"
+
+#: src/parse_args.c:703
+#, c-format
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Opciones:\n"
+
+#: src/parse_args.c:705
+msgid "use a helper program for password prompting"
+msgstr "usa un programa auxiliar pa la introducción de contraseñes"
+
+#: src/parse_args.c:708
+msgid "use specified BSD authentication type"
+msgstr "usa la triba d'autenticación BSD especificada"
+
+#: src/parse_args.c:711
+msgid "run command in the background"
+msgstr "executa'l comandu en segundu planu"
+
+#: src/parse_args.c:713
+msgid "close all file descriptors >= num"
+msgstr "zarra tolos descriptores de ficheru >= num"
+
+#: src/parse_args.c:716
+msgid "run command with the specified BSD login class"
+msgstr "executa'l comandu cola clas d'aniciu de sesión BSD especificada"
+
+#: src/parse_args.c:719
+msgid "preserve user environment when running command"
+msgstr "caltién l'entornu del usuariu al executar el comandu"
+
+#: src/parse_args.c:721
+msgid "preserve specific environment variables"
+msgstr "caltién variables d'entornu específiques"
+
+#: src/parse_args.c:723
+msgid "edit files instead of running a command"
+msgstr "edita ficheros en cuentes d'executar un comandu"
+
+#: src/parse_args.c:725
+msgid "run command as the specified group name or ID"
+msgstr "executa'l comandu como nome o ID de grupu especificaos"
+
+#: src/parse_args.c:727
+msgid "set HOME variable to target user's home dir"
+msgstr "afita la variable HOME al direutoriu d'aniciu del usuariu de destín"
+
+#: src/parse_args.c:729
+msgid "display help message and exit"
+msgstr "amuesa esti mensaxe d'ayuda y cola"
+
+#: src/parse_args.c:731
+msgid "run command on host (if supported by plugin)"
+msgstr "executa'l comandu nel agospiu (si lo sofita'l complementu)"
+
+#: src/parse_args.c:733
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "executa la shell d'aniciu de sesión como l'usuariu de destín. Tamién podría especificase un comandu"
+
+#: src/parse_args.c:735
+msgid "remove timestamp file completely"
+msgstr "desanicia dafechu'l ficheru de marques de tiempu"
+
+#: src/parse_args.c:737
+msgid "invalidate timestamp file"
+msgstr "invalida'l ficheru de marques de tiempu"
+
+#: src/parse_args.c:739
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "llista los privilexos del usuariu o comprueba un comandu específicu, úsalu dos vegaes pa un formatu más llargu"
+
+#: src/parse_args.c:741
+msgid "non-interactive mode, no prompts are used"
+msgstr "mou non interactivu, nun va entrugase nada"
+
+#: src/parse_args.c:743
+msgid "preserve group vector instead of setting to target's"
+msgstr "caltién el vector de grupos en cuentes d'afitar el del destín"
+
+#: src/parse_args.c:745
+msgid "use the specified password prompt"
+msgstr "usa la contraseña que s'especificare"
+
+#: src/parse_args.c:748
+msgid "create SELinux security context with specified role"
+msgstr "crea'l contestu de seguranza de SELinux con rol especificáu"
+
+#: src/parse_args.c:751
+msgid "read password from standard input"
+msgstr "llee la contraseña de magar la entrada estándar"
+
+#: src/parse_args.c:753
+msgid "run shell as the target user; a command may also be specified"
+msgstr "executa la shell como l'usuariu de destín, tamién podría especificase un comandu"
+
+#: src/parse_args.c:756
+msgid "create SELinux security context with specified type"
+msgstr "crea'l contestu de seguranza de SELinux cola triba especificada"
+
+#: src/parse_args.c:759
+msgid "terminate command after the specified time limit"
+msgstr "termina'l comandu tres la llende de tiempu especificada"
+
+#: src/parse_args.c:761
+msgid "in list mode, display privileges for user"
+msgstr "nel mou llista, amuesa los privilexos del usuariu"
+
+#: src/parse_args.c:763
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "executa'l comandu (o edita'l ficheru) como nome o ID d'usuariu especificaos"
+
+#: src/parse_args.c:765
+msgid "display version information and exit"
+msgstr "amuesa la información de la versión y cola"
+
+#: src/parse_args.c:767
+msgid "update user's timestamp without running a command"
+msgstr "anueva la marca de tiempu del usuariu ensin executar un comandu"
+
+#: src/parse_args.c:769
+msgid "stop processing command line arguments"
+msgstr "dexa de procesar los argumentos de la llinia de comandos"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "nun pue abrise'l sistema d'auditoría"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "nun pue unviase'l mensaxe d'auditoría"
+
+#: src/selinux.c:121
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "nun pue facese fgetfilecon a %s"
+
+#: src/selinux.c:126
+#, c-format
+msgid "%s changed labels"
+msgstr "%s camudó les etiquetes"
+
+#: src/selinux.c:131
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "nun pue restaurase'l contestu pa %s"
+
+#: src/selinux.c:172
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "nun pue abrise %s, nun va reetiquetase la TTY"
+
+#: src/selinux.c:176 src/selinux.c:217 src/selinux.c:234
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s nun ye un preséu de caráuteres, nun va reetiquetase la TTY"
+
+#: src/selinux.c:185
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "nun pue consiguise'l contestu actual de la TTY, nun va reetiquetase la TTY"
+
+#: src/selinux.c:192
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "desconozse la clas de seguranza «chr_file», nun va reetiquetase la TTY"
+
+#: src/selinux.c:197
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "nun pue consiguise'l contestu nuevu de la TTY, nun va reetiquetase la TTY"
+
+#: src/selinux.c:204
+msgid "unable to set new tty context"
+msgstr "nun pue afitase un contestu nuevu de TTY"
+
+#: src/selinux.c:278
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "has especificar un rol pa la triba %s"
+
+#: src/selinux.c:284
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "nun pue consiguise la triba predeterminada del rol %s"
+
+#: src/selinux.c:302
+#, c-format
+msgid "failed to set new role %s"
+msgstr "fallu al afitar el rol nuevu %s"
+
+#: src/selinux.c:306
+#, c-format
+msgid "failed to set new type %s"
+msgstr "fallu al afitar la triba nueva %s"
+
+#: src/selinux.c:318
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s nun ta nun contestu válidu"
+
+#: src/selinux.c:353
+msgid "failed to get old_context"
+msgstr "fallu al consiguir old_context"
+
+#: src/selinux.c:359
+msgid "unable to determine enforcing mode."
+msgstr "nun pue determinase'l mou obligatoriu."
+
+#: src/selinux.c:376
+#, c-format
+msgid "unable to set tty context to %s"
+msgstr "nun pue afitase'l contestu de TTY a %s"
+
+#: src/selinux.c:415
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "nun pue afitase'l contestu d'execución a %s"
+
+#: src/selinux.c:422
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "nun pue afitase'l contestu de creación de claves a %s"
+
+#: src/sesh.c:77
+msgid "requires at least one argument"
+msgstr "rique polo menos un argumentu"
+
+#: src/sesh.c:106
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "el númberu del descriptor de ficheru nun ye válidu: %s"
+
+#: src/sesh.c:120
+#, c-format
+msgid "unable to run %s as a login shell"
+msgstr "nun pue executase %s como una shell d'aniciu de sesión"
+
+#: src/signal.c:88
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "nun pue guardase'l remanador pa la señal %d"
+
+#: src/solaris.c:81
+msgid "resource control limit has been reached"
+msgstr "algamóse la llende del control de recursos"
+
+#: src/solaris.c:84
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "l'usuariu «%s» nun ye miembru del proyeutu «%s»"
+
+#: src/solaris.c:88
+msgid "the invoking task is final"
+msgstr "la xera qu'invoca ye final"
+
+#: src/solaris.c:91
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "nun pudo xunise al proyeutu «%s»"
+
+#: src/solaris.c:96
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "nun hai dengún conxuntu de recursos qu'aceute los arreyos predeterminaos del proyeutu «%s»"
+
+#: src/solaris.c:100
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "el conxuntu de recursos especificáu nun esiste pal proyeutu «%s»"
+
+#: src/solaris.c:104
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "nun pue arreyase al conxuntu predetermináu de recursos del proyeutu «%s»"
+
+#: src/solaris.c:110
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "setproject falló pal proyeutu «%s»"
+
+#: src/solaris.c:112
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "alvertencia, falló l'asignación del control de recursos pal proyeutu «%s»"
+
+#: src/sudo.c:201
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Versión %s de Sudo\n"
+
+#: src/sudo.c:203
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Opciones de configuración: %s\n"
+
+#: src/sudo.c:211
+msgid "fatal error, unable to load plugins"
+msgstr "fallu fatal, nun puen cargase los complementos"
+
+#: src/sudo.c:219
+msgid "unable to initialize policy plugin"
+msgstr "nun pue aniciase'l complementu de polítiques"
+
+#: src/sudo.c:263
+msgid "plugin did not return a command to execute"
+msgstr "el complementu nun devolvió un comandu a executar"
+
+#: src/sudo.c:279
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "fallu aniciando'l complementu d'E/S %s"
+
+#: src/sudo.c:302
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "nun s'esperaba'l mou de sudo 0x%x"
+
+#: src/sudo.c:535
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "nun esistes na base de datos %s"
+
+#: src/sudo.c:592
+msgid "unable to determine tty"
+msgstr "nun pue determinase la tty"
+
+#: src/sudo.c:880
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s ha ser propiedá del UID %d y tener afitáu'l bit setuid"
+
+#: src/sudo.c:883
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "l'UID efeutivu nun ye %d, ¿ta %s nun sistema de ficheros cola opción «nosuid» afitada o nun sistema de ficheros NFS ensin privilexos root?"
+
+#: src/sudo.c:889
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "l'UID efeutivu nun ye %d, ¿ta sudo instaláu como setuid root?"
+
+#: src/sudo.c:942
+msgid "unable to set supplementary group IDs"
+msgstr "nun pudierons afitase les IDs de grupu suplementaries"
+
+#: src/sudo.c:949
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "nun pue afitase'l GID efeutivu al GID de runas %u"
+
+#: src/sudo.c:955
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "nun pue afitase'l GID al GID de runas %u"
+
+#: src/sudo.c:1012
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "nun s'esperaba la condición de terminación del fíu: %d"
+
+#: src/sudo.c:1158
+#, c-format
+msgid "policy plugin %s is missing the `check_policy' method"
+msgstr "al complementu de polítiques %s fálta-y el métodu «check_policy»"
+
+#: src/sudo.c:1176
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "el complementu de polítiques %s nun sofita'l llistar privilexos"
+
+#: src/sudo.c:1193
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "el complementu de polítiques %s nun sofita la opción -v"
+
+#: src/sudo.c:1208
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "el complementu de polítiques %s nun sofita les opciones -k/-K"
+
+#: src/sudo_edit.c:219
+msgid "no writable temporary directory found"
+msgstr "nun s'alcontró dengún direutoriu temporal escribible"
+
+#: src/sudo_edit.c:286 src/sudo_edit.c:375
+msgid "unable to restore current working directory"
+msgstr "nun pue restaurase'l direutoriu actual de trabayu"
+
+#: src/sudo_edit.c:592 src/sudo_edit.c:704
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s nun ye un ficheru regular"
+
+#: src/sudo_edit.c:599
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: nun se permite la edición d'enllaces simbólicos"
+
+#: src/sudo_edit.c:602
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: nun se permite la edición de ficheros nun direutoriu escribible"
+
+#: src/sudo_edit.c:635 src/sudo_edit.c:742
+#, c-format
+msgid "%s: short write"
+msgstr "%s: escritura breve"
+
+#: src/sudo_edit.c:705
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s quedó ensin modificar"
+
+#: src/sudo_edit.c:718 src/sudo_edit.c:903
+#, c-format
+msgid "%s unchanged"
+msgstr "%s nun camudó"
+
+#: src/sudo_edit.c:731 src/sudo_edit.c:753
+#, c-format
+msgid "unable to write to %s"
+msgstr "nun pue escribise en %s"
+
+#: src/sudo_edit.c:732 src/sudo_edit.c:751 src/sudo_edit.c:754
+#: src/sudo_edit.c:928 src/sudo_edit.c:932
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "el conteníu de la sesión d'edición quedó en %s"
+
+#: src/sudo_edit.c:750
+msgid "unable to read temporary file"
+msgstr "nun pue lleese'l ficheru temporal"
+
+#: src/sudo_edit.c:833
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: fallu internu: númberu estrañu de caminos"
+
+#: src/sudo_edit.c:835
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: nun puen crease ficheros temporales"
+
+#: src/sudo_edit.c:837 src/sudo_edit.c:935
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: desconozse'l fallu %d"
+
+#: src/sudo_edit.c:927
+msgid "unable to copy temporary files back to their original location"
+msgstr "nun puen copiase los ficheros temporales al so allugamientu orixinal"
+
+#: src/sudo_edit.c:931
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "nun puen copiase dalgunos ficheros temporales al so allugamientu orixinal"
+
+#: src/sudo_edit.c:976
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "nun pue camudase l'UID a root (%u)"
+
+#: src/sudo_edit.c:993
+msgid "plugin error: missing file list for sudoedit"
+msgstr "fallu del complementu: falta la llista de ficheros de sudoedit"
+
+#: src/sudo_edit.c:1034 src/sudo_edit.c:1047
+msgid "unable to read the clock"
+msgstr "nun pue lleese'l reló"
+
+#: src/tgetpass.c:101
+msgid "timed out reading password"
+msgstr "escosó'l tiempu d'espera de la llectura de la contraseña"
+
+#: src/tgetpass.c:104
+msgid "no password was provided"
+msgstr "nun s'apurrió denguna contraseña"
+
+#: src/tgetpass.c:107
+msgid "unable to read password"
+msgstr "nun pue lleese la contraseña"
+
+#: src/tgetpass.c:141
+msgid "no tty present and no askpass program specified"
+msgstr "nun hai denguna TTY presente nin s'especificó dengún programa askpass"
+
+#: src/tgetpass.c:150
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "nun s'especificó dengún programa askpass, tenta d'afitar SUDO_ASKPASS"
+
+#: src/tgetpass.c:307
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "nun pue afitase'l GID a %u"
+
+#: src/tgetpass.c:311
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "nun pue afitase l'UID a %u"
+
+#: src/tgetpass.c:316
+#, c-format
+msgid "unable to run %s"
+msgstr "nun pue executase %s"
+
+#: src/utmp.c:271
+msgid "unable to save stdin"
+msgstr "nun pue guardase stdin"
+
+#: src/utmp.c:273
+msgid "unable to dup2 stdin"
+msgstr "nun pue facese dup2 a stdin"
+
+#: src/utmp.c:276
+msgid "unable to restore stdin"
+msgstr "nun pue resaturase stdin"
diff --git a/po/ca.mo b/po/ca.mo
new file mode 100644
index 0000000..b9a8e78
--- /dev/null
+++ b/po/ca.mo
Binary files differ
diff --git a/po/ca.po b/po/ca.po
new file mode 100644
index 0000000..6873140
--- /dev/null
+++ b/po/ca.po
@@ -0,0 +1,1088 @@
+# translation of sudo to Catalan
+# This file is put in the public domain.
+# Walter Garcia-Fontes <walter.garcia@upf.edu>, 2021.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.6b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2021-01-09 12:59-0700\n"
+"PO-Revision-Date: 2021-04-20 14:35+0200\n"
+"Last-Translator: Walter Garcia-Fontes <walter.garcia@upf.edu>\n"
+"Language-Team: Catalan <ca@dodds.net>\n"
+"Language: ca\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "no s'ha pogut obrir userdb"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "no s'ha pogut passar al registre \"%s\" per a %s"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "no s'ha pogut restaurar el registre"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:54 lib/util/json.c:183 lib/util/sudo_conf.c:198
+#: lib/util/sudo_conf.c:284 lib/util/sudo_conf.c:361 lib/util/sudo_conf.c:647
+#: src/conversation.c:80 src/exec_common.c:106 src/exec_common.c:122
+#: src/exec_common.c:131 src/exec_monitor.c:206 src/exec_monitor.c:455
+#: src/exec_monitor.c:461 src/exec_monitor.c:469 src/exec_monitor.c:477
+#: src/exec_monitor.c:484 src/exec_monitor.c:491 src/exec_monitor.c:498
+#: src/exec_monitor.c:505 src/exec_monitor.c:512 src/exec_monitor.c:519
+#: src/exec_monitor.c:526 src/exec_nopty.c:212 src/exec_nopty.c:221
+#: src/exec_nopty.c:228 src/exec_nopty.c:235 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:299 src/exec_nopty.c:473
+#: src/exec_pty.c:834 src/exec_pty.c:843 src/exec_pty.c:900
+#: src/exec_pty.c:1053 src/exec_pty.c:1225 src/exec_pty.c:1234
+#: src/exec_pty.c:1241 src/exec_pty.c:1248 src/exec_pty.c:1255
+#: src/exec_pty.c:1262 src/exec_pty.c:1269 src/exec_pty.c:1276
+#: src/exec_pty.c:1283 src/exec_pty.c:1290 src/exec_pty.c:1297
+#: src/exec_pty.c:1305 src/exec_pty.c:1747 src/load_plugins.c:52
+#: src/load_plugins.c:65 src/load_plugins.c:163 src/load_plugins.c:188
+#: src/load_plugins.c:223 src/load_plugins.c:455 src/load_plugins.c:461
+#: src/parse_args.c:181 src/parse_args.c:202 src/parse_args.c:275
+#: src/parse_args.c:616 src/parse_args.c:638 src/parse_args.c:663
+#: src/preserve_fds.c:46 src/preserve_fds.c:131 src/selinux.c:90
+#: src/selinux.c:360 src/selinux.c:489 src/selinux.c:498 src/sesh.c:110
+#: src/sesh.c:143 src/sesh.c:149 src/sesh.c:156 src/sesh.c:162 src/sesh.c:407
+#: src/sudo.c:632 src/sudo.c:702 src/sudo.c:712 src/sudo.c:733 src/sudo.c:752
+#: src/sudo.c:761 src/sudo.c:770 src/sudo.c:787 src/sudo.c:829 src/sudo.c:839
+#: src/sudo.c:868 src/sudo.c:1054 src/sudo.c:1076 src/sudo.c:1378
+#: src/sudo.c:1551 src/sudo.c:1776 src/sudo.c:2120 src/sudo_edit.c:89
+#: src/sudo_edit.c:151 src/sudo_edit.c:431 src/sudo_edit.c:440
+#: src/sudo_edit.c:539 src/sudo_edit.c:546 src/sudo_edit.c:682
+#: src/sudo_edit.c:702
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:55
+#: lib/util/json.c:184 lib/util/sudo_conf.c:199 lib/util/sudo_conf.c:284
+#: lib/util/sudo_conf.c:361 lib/util/sudo_conf.c:647 src/conversation.c:81
+#: src/exec_common.c:106 src/exec_common.c:123 src/exec_common.c:132
+#: src/exec_monitor.c:455 src/exec_monitor.c:461 src/exec_monitor.c:469
+#: src/exec_monitor.c:477 src/exec_monitor.c:484 src/exec_monitor.c:491
+#: src/exec_monitor.c:498 src/exec_monitor.c:505 src/exec_monitor.c:512
+#: src/exec_monitor.c:519 src/exec_monitor.c:526 src/exec_nopty.c:212
+#: src/exec_nopty.c:221 src/exec_nopty.c:228 src/exec_nopty.c:235
+#: src/exec_nopty.c:242 src/exec_nopty.c:249 src/exec_nopty.c:256
+#: src/exec_nopty.c:263 src/exec_nopty.c:270 src/exec_nopty.c:277
+#: src/exec_nopty.c:284 src/exec_nopty.c:291 src/exec_nopty.c:299
+#: src/exec_pty.c:834 src/exec_pty.c:843 src/exec_pty.c:900
+#: src/exec_pty.c:1225 src/exec_pty.c:1234 src/exec_pty.c:1241
+#: src/exec_pty.c:1248 src/exec_pty.c:1255 src/exec_pty.c:1262
+#: src/exec_pty.c:1269 src/exec_pty.c:1276 src/exec_pty.c:1283
+#: src/exec_pty.c:1290 src/exec_pty.c:1297 src/exec_pty.c:1305
+#: src/exec_pty.c:1747 src/load_plugins.c:163 src/load_plugins.c:188
+#: src/load_plugins.c:223 src/load_plugins.c:455 src/load_plugins.c:461
+#: src/parse_args.c:181 src/parse_args.c:203 src/parse_args.c:275
+#: src/parse_args.c:616 src/parse_args.c:638 src/parse_args.c:663
+#: src/preserve_fds.c:46 src/preserve_fds.c:131 src/selinux.c:90
+#: src/selinux.c:360 src/selinux.c:489 src/selinux.c:498 src/sesh.c:110
+#: src/sesh.c:408 src/sudo.c:236 src/sudo.c:632 src/sudo.c:868 src/sudo.c:1054
+#: src/sudo.c:1076 src/sudo.c:1378 src/sudo.c:1551 src/sudo.c:1776
+#: src/sudo.c:2120 src/sudo_edit.c:89 src/sudo_edit.c:151 src/sudo_edit.c:431
+#: src/sudo_edit.c:440 src/sudo_edit.c:539 src/sudo_edit.c:546
+#: src/sudo_edit.c:682 src/sudo_edit.c:702
+msgid "unable to allocate memory"
+msgstr "no s'ha pogut assignar memòria"
+
+#: lib/util/mkdir_parents.c:69 lib/util/sudo_conf.c:686 src/selinux.c:234
+#: src/selinux.c:264 src/sudo.c:367 src/sudo_edit.c:496 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "no s'ha pogut obrir %s"
+
+#: lib/util/mkdir_parents.c:84
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "no es pot mkdir %s"
+
+#: lib/util/mkdir_parents.c:93 lib/util/sudo_conf.c:663 src/copy_file.c:150
+#, c-format
+msgid "unable to stat %s"
+msgstr "no es pot obrir %s"
+
+#: lib/util/mkdir_parents.c:98
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s existeix però no és un directori (0%o)"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Senyal desconegut"
+
+#: lib/util/strtoid.c:87 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:143 src/sesh.c:156
+msgid "invalid value"
+msgstr "valor no vàlid"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "valor massa gran"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "valor massa petit"
+
+#: lib/util/sudo_conf.c:217
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "valor Path no vàlid «%s» a %s, línia %u"
+
+#: lib/util/sudo_conf.c:383 lib/util/sudo_conf.c:399 lib/util/sudo_conf.c:452
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "valor no vàlid per a %s «%s» a %s, línia %u"
+
+#: lib/util/sudo_conf.c:420
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "font de grup no suportat «%s» a %s, línia %u"
+
+#: lib/util/sudo_conf.c:436
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "grups «%s» max no vàlids a %s, línia %u"
+
+#: lib/util/sudo_conf.c:666
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s no és un fitxer regular"
+
+#: lib/util/sudo_conf.c:669 src/copy_file.c:162
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s és propietat de l'uid %u, hauria de ser %u"
+
+#: lib/util/sudo_conf.c:673
+#, c-format
+msgid "%s is world writable"
+msgstr "%s és escrivible per tothom"
+
+#: lib/util/sudo_conf.c:676
+#, c-format
+msgid "%s is group writable"
+msgstr "%s és escrivible pel grup"
+
+#: src/copy_file.c:93
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: voleu truncar %s a zero bytes? (y/n) [n] "
+
+#: src/copy_file.c:97
+#, c-format
+msgid "not overwriting %s"
+msgstr "no se sobreescriurà %s"
+
+#: src/copy_file.c:119
+#, c-format
+msgid "unable to read from %s"
+msgstr "no es pot llegir de %s"
+
+#: src/copy_file.c:136 src/sudo_edit.c:322
+#, c-format
+msgid "unable to write to %s"
+msgstr "no s'ha pogut escriure a %s"
+
+#: src/copy_file.c:154 src/sesh.c:215 src/sudo_edit.c:199
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: no és un fitxer regular"
+
+#: src/copy_file.c:158
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: mode de fitxer dolent: 0%o"
+
+#: src/edit_open.c:265
+msgid "unable to restore current working directory"
+msgstr "no s'ha pogut restaurar el directori actual de treball"
+
+#: src/exec.c:128
+#, c-format
+msgid "unknown login class %s"
+msgstr "classe d'inici de sessió %s desconeguda"
+
+#: src/exec.c:140
+msgid "unable to set user context"
+msgstr "no s'ha pogut establir el context d'usuari"
+
+#: src/exec.c:156
+msgid "unable to set process priority"
+msgstr "no s'ha pogut establir la prioritat del procés"
+
+#: src/exec.c:170
+#, c-format
+msgid "unable to change root to %s"
+msgstr "no s'ha pogut canviar l'usuari primari a %s"
+
+#: src/exec.c:183 src/exec.c:189 src/exec.c:196
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "no s'ha pogut canviar a runas uid (%u, %u)"
+
+#: src/exec.c:214
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "no s'ha pogut canviar el directori a %s"
+
+#: src/exec.c:218
+#, c-format
+msgid "starting from %s"
+msgstr "començant des de %s"
+
+#: src/exec.c:300 src/exec_monitor.c:564 src/exec_monitor.c:566
+#: src/exec_nopty.c:531 src/exec_pty.c:575 src/exec_pty.c:1393
+#: src/exec_pty.c:1395 src/signal.c:139 src/signal.c:153
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "no es pot establir el gestor per al senyal %d"
+
+#: src/exec_common.c:165
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "no s'ha pogut remoure PRIV_PROC_EXEC de PRIV_LIMIT"
+
+#: src/exec_monitor.c:360
+msgid "error reading from socketpair"
+msgstr "error en llegir del parell de sòcols"
+
+#: src/exec_monitor.c:377
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "tipus de resposta inesperada al canal posterior: %d"
+
+#: src/exec_monitor.c:463 src/exec_monitor.c:471 src/exec_monitor.c:479
+#: src/exec_monitor.c:486 src/exec_monitor.c:493 src/exec_monitor.c:500
+#: src/exec_monitor.c:507 src/exec_monitor.c:514 src/exec_monitor.c:521
+#: src/exec_monitor.c:528 src/exec_nopty.c:214 src/exec_nopty.c:223
+#: src/exec_nopty.c:230 src/exec_nopty.c:237 src/exec_nopty.c:244
+#: src/exec_nopty.c:251 src/exec_nopty.c:258 src/exec_nopty.c:265
+#: src/exec_nopty.c:272 src/exec_nopty.c:279 src/exec_nopty.c:286
+#: src/exec_nopty.c:293 src/exec_nopty.c:301 src/exec_pty.c:700
+#: src/exec_pty.c:705 src/exec_pty.c:802 src/exec_pty.c:809 src/exec_pty.c:906
+#: src/exec_pty.c:1227 src/exec_pty.c:1236 src/exec_pty.c:1243
+#: src/exec_pty.c:1250 src/exec_pty.c:1257 src/exec_pty.c:1264
+#: src/exec_pty.c:1271 src/exec_pty.c:1278 src/exec_pty.c:1285
+#: src/exec_pty.c:1292 src/exec_pty.c:1299 src/exec_pty.c:1700
+#: src/exec_pty.c:1710 src/exec_pty.c:1755 src/exec_pty.c:1762
+#: src/exec_pty.c:1789
+msgid "unable to add event to queue"
+msgstr "no s'ha pogut afegir un esdeveniment a la cua"
+
+#: src/exec_monitor.c:582
+msgid "unable to set controlling tty"
+msgstr "no s'ha pogut configurar la tty controladora"
+
+#: src/exec_monitor.c:590 src/exec_nopty.c:358 src/exec_pty.c:1472
+#: src/exec_pty.c:1493 src/exec_pty.c:1513 src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr "no s'ha pogut crear un conducte"
+
+#: src/exec_monitor.c:598
+msgid "unable to receive message from parent"
+msgstr "no s'ha pogut enviar el missatge del pare"
+
+#: src/exec_monitor.c:612 src/exec_nopty.c:387 src/exec_pty.c:1551
+#: src/sudo_edit.c:363 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr "no s'ha pogut bifurcar"
+
+#: src/exec_monitor.c:616 src/exec_monitor.c:715 src/exec_nopty.c:441
+msgid "unable to restore tty label"
+msgstr "no s'ha pogut restaurar l'etiqueta tty"
+
+#: src/exec_monitor.c:632 src/sesh.c:120 src/sudo.c:1132
+#, c-format
+msgid "unable to execute %s"
+msgstr "no s'ha pogut executar %s"
+
+#: src/exec_nopty.c:352 src/exec_pty.c:1402
+msgid "policy plugin failed session initialization"
+msgstr "el connector de política ha fallat la inicialització de la sessió"
+
+#: src/exec_nopty.c:429 src/exec_pty.c:1639
+msgid "error in event loop"
+msgstr "error al bucle d'esdeveniment"
+
+#: src/exec_nopty.c:539 src/exec_pty.c:613 src/signal.c:101
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "no s'ha pogut restaurar el gestor per al senyal %d"
+
+#: src/exec_pty.c:152
+msgid "unable to allocate pty"
+msgstr "no s'ha pogut assignar pty"
+
+#: src/exec_pty.c:216 src/exec_pty.c:256 src/exec_pty.c:296 src/exec_pty.c:347
+#: src/exec_pty.c:398
+msgid "I/O plugin error"
+msgstr "error de conector I/O"
+
+#: src/exec_pty.c:220 src/exec_pty.c:260 src/exec_pty.c:300 src/exec_pty.c:351
+#: src/exec_pty.c:402
+msgid "command rejected by I/O plugin"
+msgstr "ordre rebutjada per connector I/O"
+
+#: src/exec_pty.c:449
+msgid "error logging suspend"
+msgstr "error en registrar suspensió"
+
+#: src/exec_pty.c:483
+msgid "error changing window size"
+msgstr "error en canviar la mida de la finestra"
+
+#: src/exec_pty.c:1382
+msgid "unable to create sockets"
+msgstr "no s'ha pogut crear el sòcol"
+
+#: src/exec_pty.c:1594
+msgid "unable to send message to monitor process"
+msgstr "no s'ha pogut enviar el missatge per monitorar el procés"
+
+#: src/load_plugins.c:50 src/load_plugins.c:63 src/load_plugins.c:85
+#: src/load_plugins.c:115 src/load_plugins.c:129 src/load_plugins.c:135
+#: src/load_plugins.c:283 src/load_plugins.c:293 src/load_plugins.c:303
+#: src/load_plugins.c:350
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "error a %s, línia %d quan s'estava carregant el connector «%s»"
+
+#: src/load_plugins.c:87
+#, c-format
+msgid "%s%s: %s"
+msgstr "%s%s: %s"
+
+#: src/load_plugins.c:131
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s ha de ser propietat de l'uid %d"
+
+#: src/load_plugins.c:137
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "%s ha de ser escrivible únicament pel propietari"
+
+#: src/load_plugins.c:247 src/load_plugins.c:318
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "s'ignorarà el connector duplicat «%s» a %s, línia %d"
+
+#: src/load_plugins.c:285
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "no s'ha pogut carregar %s: %s"
+
+#: src/load_plugins.c:295
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "no s'ha pogut trobar el símbol «%s» a %s"
+
+#: src/load_plugins.c:305
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "s'ha trobat una versió major %d incompatible de connector (s'esperava %d) a %s"
+
+#: src/load_plugins.c:323
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "s'ignorarà el connector de política «%s» a %s, línia %d"
+
+#: src/load_plugins.c:326
+msgid "only a single policy plugin may be specified"
+msgstr "sols es pot especificar un únic connector de política"
+
+#: src/load_plugins.c:352
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "tipus desconegut de connector %d trobat a %s"
+
+#: src/load_plugins.c:535
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "el connector de política %s no inclou un mètode check_policy"
+
+#: src/net_ifs.c:179 src/net_ifs.c:197 src/net_ifs.c:343 src/sudo.c:479
+#: src/sudo_edit.c:400 src/sudo_edit.c:408
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "error intern, sobreeiximent de %s"
+
+#: src/parse_args.c:223
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "nom no vàlid de variable d'entorn: %s"
+
+#: src/parse_args.c:325
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "l'argument per a -C ha de ser un número més gran o igual a 3"
+
+#: src/parse_args.c:552
+msgid "you may not specify both the -i and -s options"
+msgstr "no podeu especificar a l'hora les opcions -i i -s"
+
+#: src/parse_args.c:557
+msgid "you may not specify both the -i and -E options"
+msgstr "no podeu especificar a l'hora les opcions -i i -E"
+
+#: src/parse_args.c:567
+msgid "the -E option is not valid in edit mode"
+msgstr "l'opció -E no és vàlida al mode editar"
+
+#: src/parse_args.c:570
+msgid "you may not specify environment variables in edit mode"
+msgstr "no podeu especificar variables d'entorn al mode editar"
+
+#: src/parse_args.c:580
+msgid "the -U option may only be used with the -l option"
+msgstr "l'opció -U sols es pot usar amb l'opció -l"
+
+#: src/parse_args.c:584
+msgid "the -A and -S options may not be used together"
+msgstr "no es poden usar a l'hora les opcions -A i -S"
+
+#: src/parse_args.c:677
+msgid "sudoedit is not supported on this platform"
+msgstr "aquesta plataforma no dóna suport a sudoedit"
+
+#: src/parse_args.c:759
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Sols es pot especificar una de les opcions -e, -h, -i, -K, -l, -s, -v o -V"
+
+#: src/parse_args.c:773
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - edita fitxers com un altre usuari\n"
+"\n"
+
+#: src/parse_args.c:775
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - executa una ordre com un altre usuari\n"
+"\n"
+
+#: src/parse_args.c:780
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Opcions:\n"
+
+#: src/parse_args.c:782
+msgid "use a helper program for password prompting"
+msgstr "usa un programa auxiliar per a la pregunta de la contrasenya"
+
+#: src/parse_args.c:785
+msgid "use specified BSD authentication type"
+msgstr "usa el tipus d'autenticació BSD especificat"
+
+#: src/parse_args.c:788
+msgid "run command in the background"
+msgstr "executa l'ordre en el segon pla"
+
+#: src/parse_args.c:790
+msgid "ring bell when prompting"
+msgstr "fer un avís sonor quan es pregunti"
+
+#: src/parse_args.c:792
+msgid "close all file descriptors >= num"
+msgstr "tanca tots els descriptors de fitxer >= num"
+
+#: src/parse_args.c:795
+msgid "run command with the specified BSD login class"
+msgstr "executa l'ordre amb la classe d'inici de sesssió BSD especificada"
+
+#: src/parse_args.c:798
+msgid "change the working directory before running command"
+msgstr "canvia el directori de treball abans d'executar l'ordre"
+
+#: src/parse_args.c:800
+msgid "preserve user environment when running command"
+msgstr "preserva l'entorn de l'usuari quan s'executi l'ordre"
+
+#: src/parse_args.c:802
+msgid "preserve specific environment variables"
+msgstr "preserva les variables específiques d'entorn"
+
+#: src/parse_args.c:804
+msgid "edit files instead of running a command"
+msgstr "edita els fitxers en comptes d'executar una ordre"
+
+#: src/parse_args.c:806
+msgid "run command as the specified group name or ID"
+msgstr "executa l'ordre com el nom o ID especificats de grup"
+
+#: src/parse_args.c:808
+msgid "set HOME variable to target user's home dir"
+msgstr "estableix la variable HOME per apuntar al directori de l'usuari"
+
+#: src/parse_args.c:810
+msgid "display help message and exit"
+msgstr "mostra el missatge d'ajuda i surt"
+
+#: src/parse_args.c:812
+msgid "run command on host (if supported by plugin)"
+msgstr "executa l'ordre a l'amfitrió (si està suportat pel connector)"
+
+#: src/parse_args.c:814
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "executa l'intèrpret d'ordres de l'inici de sessió com a usuari de destinació; també es pot especificar una ordre"
+
+#: src/parse_args.c:816
+msgid "remove timestamp file completely"
+msgstr "suprimeix completament el fitxer de marca de temps"
+
+#: src/parse_args.c:818
+msgid "invalidate timestamp file"
+msgstr "fitxer de marca de temps no vàlid"
+
+#: src/parse_args.c:820
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "fes una llista dels privilegis de l'usuari o verifica una ordre específica; usueu-lo dues vegades per a formats més llargs"
+
+#: src/parse_args.c:822
+msgid "non-interactive mode, no prompts are used"
+msgstr "mode no interactiu, no es preguntarà res"
+
+#: src/parse_args.c:824
+msgid "preserve group vector instead of setting to target's"
+msgstr "preserva el vector de grup en comptes d'establir-lo d'acord amb la destinació"
+
+#: src/parse_args.c:826
+msgid "use the specified password prompt"
+msgstr "usa la pregunta específica de contrasenya"
+
+#: src/parse_args.c:828
+msgid "change the root directory before running command"
+msgstr "canvia el directori arrel abans d'executar l'ordre"
+
+#: src/parse_args.c:831
+msgid "create SELinux security context with specified role"
+msgstr "crea un context de seguretat SELinux amb el rol especificat"
+
+#: src/parse_args.c:834
+msgid "read password from standard input"
+msgstr "llegeix la contrasenya des de l'entrada estàndard"
+
+#: src/parse_args.c:836
+msgid "run shell as the target user; a command may also be specified"
+msgstr "executa l'intèrpret d'ordres com a usuari de destinació; també es pot especificar una ordre"
+
+#: src/parse_args.c:839
+msgid "create SELinux security context with specified type"
+msgstr "crea el context de seguretat SELinux amb el tipus especificat"
+
+#: src/parse_args.c:842
+msgid "terminate command after the specified time limit"
+msgstr "finalitza l'ordre després del límit especificat de temps"
+
+#: src/parse_args.c:844
+msgid "in list mode, display privileges for user"
+msgstr "en mode llista, mostra els privilegis per a l'usuari"
+
+#: src/parse_args.c:846
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "executa l'ordre (o edita el fitxer) com el nom o ID especificats d'usuari"
+
+#: src/parse_args.c:848
+msgid "display version information and exit"
+msgstr "mostra la informació de versió i surt"
+
+#: src/parse_args.c:850
+msgid "update user's timestamp without running a command"
+msgstr "actualitza la marca de temps de l'usuari sense executar una ordre"
+
+#: src/parse_args.c:852
+msgid "stop processing command line arguments"
+msgstr "deixa de processar els arguments de línia d'ordres"
+
+#: src/selinux.c:84
+msgid "unable to open audit system"
+msgstr "no s'ha pogut obrir el sistema d'auditoria"
+
+#: src/selinux.c:94
+msgid "unable to send audit message"
+msgstr "no s'ha pogut enviar el missatge d'auditoria"
+
+#: src/selinux.c:128
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "no s'ha pogut fgetfilecon %s"
+
+#: src/selinux.c:133
+#, c-format
+msgid "%s changed labels"
+msgstr "%s ha canviat les etiquetes"
+
+#: src/selinux.c:141
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "no s'ha pogut restaurar el context per a %s"
+
+#: src/selinux.c:189
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "no s'ha pogut obrir %s, no es canviaran les etiquetes per a la tty"
+
+#: src/selinux.c:193 src/selinux.c:238 src/selinux.c:268
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s no es un dispositiu de caràcters, no es canviarà l'etiqueta del tty"
+
+#: src/selinux.c:202
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "no s'ha pogut obtenir el context tty actual, no es canviaran les etiquetes per a la tty"
+
+#: src/selinux.c:209
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "classe de seguretat «char_file» desconeguda, no es canviaran les etiquetes de la tty"
+
+#: src/selinux.c:214
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "no s'ha pogut obtenir el nou context tty, no es canviaran les etiquetes tty"
+
+#: src/selinux.c:223
+msgid "unable to set new tty context"
+msgstr "no s'ha pogut establir el nou context tty"
+
+#: src/selinux.c:321
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "heu d'especificar un rol per al tipus %s"
+
+#: src/selinux.c:327
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "no s'ha pogut obtenir un tipus predeterminat per al rol %s"
+
+#: src/selinux.c:339
+msgid "failed to get new context"
+msgstr "no s'ha pogut obtenir el context nou"
+
+#: src/selinux.c:348
+#, c-format
+msgid "failed to set new role %s"
+msgstr "no s'ha pogut establir el nou rol %s"
+
+#: src/selinux.c:352
+#, c-format
+msgid "failed to set new type %s"
+msgstr "no s'ha pogut establir el nou tipus %s"
+
+#: src/selinux.c:364
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s no és un context vàlid"
+
+#: src/selinux.c:396
+msgid "failed to get old context"
+msgstr "no s'ha pogut obtenir el context vell"
+
+#: src/selinux.c:402
+msgid "unable to determine enforcing mode."
+msgstr "no s'ha pogut determinar el mode de fer complir"
+
+#: src/selinux.c:419
+#, c-format
+msgid "unable to set tty context to %s"
+msgstr "no s'ha pogut establir el context tty a %s"
+
+#: src/selinux.c:440
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "no s'ha pogut establir el context exec a %s"
+
+#: src/selinux.c:447
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "no s'ha pogut establir el context de creació de clau a %s"
+
+#: src/sesh.c:72
+msgid "requires at least one argument"
+msgstr "es requereix almenys un argument"
+
+#: src/sesh.c:101
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "número no vàlid de descriptor de fitxer: %s"
+
+#: src/sesh.c:115
+#, c-format
+msgid "unable to run %s as a login shell"
+msgstr "no s'ha pogut executar %s com a intèrpret d'ordres d'inici de sessió"
+
+#: src/sesh.c:197 src/sesh.c:297 src/sudo_edit.c:206
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: no es permet l'edició de enllaços simbòlics"
+
+#: src/sesh.c:200 src/sesh.c:300 src/sudo_edit.c:209
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: no es permet l'edició de fitxers a un directori amb permís d'escriptura"
+
+#: src/sesh.c:284 src/sesh.c:305 src/sesh.c:314 src/sesh.c:322
+#: src/sudo_edit.c:333
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "els continguts de la sessió d'edició s'han deixat a %s"
+
+#: src/sesh.c:412 src/sudo_edit.c:93
+msgid "unable to get group list"
+msgstr "no es pot obtenir la llista de grup"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "no s'ha pogut desar el gestorper al senyal %d"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "s'ha assolit el límit de control de recursos"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "l'usuari \"%s\" no és un membre del projecte \"%s\""
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "la tasca invocant és final"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "no es pot fer la incorporació al projecte \"%s\""
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "no hi ha vinculacions predeterminades d'acceptació de conjunt de recursos per al projecte \"%s\""
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "no existeix el conjunt de recursos especifica per al projecte \"%s\""
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "no s'ha pogut vincular al conjunt de recursos predeterminats per al projecte \"%s\""
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "ha fallat setproject per al projecte \"%s\""
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "advertiment, l'assignació de control de recursos ha fallat per al projecte \"%s\""
+
+#: src/sudo.c:222
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Versió de sudo %s\n"
+
+#: src/sudo.c:224
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Opcions de configuració: %s\n"
+
+#: src/sudo.c:232
+msgid "fatal error, unable to load plugins"
+msgstr "error fatal, no s'han pogut carregar els connectors"
+
+#: src/sudo.c:278
+msgid "plugin did not return a command to execute"
+msgstr "el connector no ha retornat una ordre a executar"
+
+#: src/sudo.c:310
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "mode 0x%x inesperat de sudo"
+
+#: src/sudo.c:546
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "no existiu a la base de dades %s"
+
+#: src/sudo.c:603
+msgid "unable to determine tty"
+msgstr "no s'ha pogut determinar la tty"
+
+#: src/sudo.c:914
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s ha de ser propietat de l'uid %d i tenir el bit setuid establert"
+
+#: src/sudo.c:917
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr ""
+"l'uid efectiu no és %d, és %s a un sistema de fitxers amb l'opció\n"
+"'nosuid' establarta o un sistema de fitxers NFS sense d'usuari primari? "
+
+#: src/sudo.c:923
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "l'uid efectiu no és %d, és el sudo instal·lat com a setuid root?"
+
+#: src/sudo.c:939
+msgid "unable to set supplementary group IDs"
+msgstr "no s'han pogut establir els IDs de grup suplementaris"
+
+#: src/sudo.c:946
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "no s'ha pogut establir el gid efectiu per a runas gid %u"
+
+#: src/sudo.c:952
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "no s'ha pogut establir el gid a runas gid %u"
+
+#: src/sudo.c:995
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "condició de terminació del fill inesperada: %d"
+
+#: src/sudo.c:1104
+msgid "unable to initialize policy plugin"
+msgstr "no s'ha pogut inicialitzar el connector de polítiques"
+
+#: src/sudo.c:1167
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "al connector de política %s li manca el mètoda «check_policy»"
+
+#: src/sudo.c:1182 src/sudo.c:1235 src/sudo.c:1279
+msgid "command rejected by policy"
+msgstr "ordre rebutjada per una política"
+
+#: src/sudo.c:1187 src/sudo.c:1240 src/sudo.c:1284 src/sudo.c:1358
+msgid "policy plugin error"
+msgstr "error de connector de política"
+
+#: src/sudo.c:1221
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "el connector de política %s no dóna suport a llistar privilegis"
+
+#: src/sudo.c:1265
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "el connector de polítiques %s no dóna suport a l'opció -v"
+
+#: src/sudo.c:1303
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "el connector de polítiques %s no dóna suport a les opcions -k/-K"
+
+#: src/sudo.c:1436
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "no se pogut iniciliatzar el connector %s entrada/sortida"
+
+#: src/sudo.c:1590
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "error en inicialitzar el connector d'auditoria %s"
+
+#: src/sudo.c:1668
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: no es pot registra l'esdeveniment d'error%s%s"
+
+#: src/sudo.c:1703
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: no es pot registrar l'esdeveniment d'acceptació%s%s"
+
+#: src/sudo.c:1708 src/sudo.c:1746
+msgid "audit plugin error"
+msgstr "error de connector d'auditoria"
+
+#: src/sudo.c:1741
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: no es pot registrar l'esdeveniment de rebuig%s%s"
+
+#: src/sudo.c:1799
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "error en inicialitzar el connector d'aprovació %s"
+
+#: src/sudo.c:1875
+msgid "command rejected by approver"
+msgstr "ordre rebutjada per l'aprovador"
+
+#: src/sudo.c:1884
+msgid "approval plugin error"
+msgstr "error de connector d'aprovació"
+
+#: src/sudo_edit.c:112
+msgid "no writable temporary directory found"
+msgstr "no s'ha trobat un directori temporari amb permís d'escriptura"
+
+#: src/sudo_edit.c:293
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s s'ha deixat sense modificar"
+
+#: src/sudo_edit.c:306 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s sense canviar"
+
+#: src/sudo_edit.c:483
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: error intern: nombre imparell de camins"
+
+#: src/sudo_edit.c:485
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: no es poden crear fitxers temporal"
+
+#: src/sudo_edit.c:487 src/sudo_edit.c:605
+msgid "sesh: killed by a signal"
+msgstr "sesh: avortat per un senyal"
+
+#: src/sudo_edit.c:489 src/sudo_edit.c:608
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: error desconegut %d"
+
+#: src/sudo_edit.c:598
+msgid "unable to copy temporary files back to their original location"
+msgstr "no es poden copiar els fitxers temporals un altre cop a la seva ubicació original"
+
+#: src/sudo_edit.c:602
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "no es poden copiar alguns dels fitxers temporals un altre cop a la seva ubicació original"
+
+#: src/sudo_edit.c:645
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "no s'ha pogut canviar l'uid a l'usuari primari (%u)"
+
+#: src/sudo_edit.c:666
+msgid "plugin error: missing file list for sudoedit"
+msgstr "error de connector: no hi ha la llista de fitxers per a sudoedit"
+
+#: src/sudo_edit.c:717 src/sudo_edit.c:725
+msgid "unable to read the clock"
+msgstr "no es pot llegir el rellotge"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "s'exhaurit el temps d'espera quan es llegia la contrasenya"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "no s'ha donat una contrasenya"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "no s'ha pogut llegir la contrasenya"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "cal una terminal per llegir la contrasenya; o bé useu l'opció -S per llegir de l'entrada estàndard o configureu un assistent askpass"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "no s'ha especificat un programa askpass, proveu d'establir SUDO_ASKPASS"
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "no s'ha pogut establir el gid a %u"
+
+#: src/tgetpass.c:331
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "no s'ha pogut establir el uid a %u"
+
+#: src/tgetpass.c:336
+#, c-format
+msgid "unable to run %s"
+msgstr "no s'ha pogut executar %s"
+
+#: src/utmp.c:287
+msgid "unable to save stdin"
+msgstr "no s'ha pogut desar el stdin"
+
+#: src/utmp.c:289
+msgid "unable to dup2 stdin"
+msgstr "no s'ha pogut fer dup2 stdin"
+
+#: src/utmp.c:292
+msgid "unable to restore stdin"
+msgstr "no s'ha pogut restaurar stdin"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "s'ignorarà el connector entrada/sortida duplicat «%s» a %s, línia %d"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s: escriptura breu"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "no s'ha pogut llegir el fitxer temporal"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "error en llegir del conducte del senyal"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "uid %u desconegut: qui sou?"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "no hi ha un tty present i no s'ha especificat un programa askpass"
+
+#~ msgid "internal error, tried allocate zero bytes"
+#~ msgstr "error intern, s'han intentat assignar zero bytes"
+
+#~ msgid "%s: %s: %s\n"
+#~ msgstr "%s: %s: %s\n"
+
+#~ msgid "%s: %s\n"
+#~ msgstr "%s: %s\n"
+
+#~ msgid "unable to set terminal to raw mode"
+#~ msgstr "no s'ha pogut configurar la terminal en mode en brut"
+
+#~ msgid "unable to open socket"
+#~ msgstr "no s'ha pogut obrir el sòcol"
+
+#~ msgid "internal error, tried to emalloc2(0)"
+#~ msgstr "error intern, s'ha intentat emalloc2(0)"
+
+#~ msgid "internal error, tried to ecalloc(0)"
+#~ msgstr "error intern, s'ha intentat ecalloc(0)"
+
+#~ msgid "internal error, tried to erealloc(0)"
+#~ msgstr "error intern, s'ha intentat erealloc(0)"
+
+#~ msgid "internal error, tried to erealloc3(0)"
+#~ msgstr "error intern, s'ha intentat erealloc3(0)"
+
+#~ msgid "internal error, tried to erecalloc(0)"
+#~ msgstr "error intern, s'ha intentat erecalloc(0)"
+
+#~ msgid "load_interfaces: overflow detected"
+#~ msgstr "load_interfaces: s'ha detectat un sobreeiximent"
diff --git a/po/cs.mo b/po/cs.mo
new file mode 100644
index 0000000..befc22a
--- /dev/null
+++ b/po/cs.mo
Binary files differ
diff --git a/po/cs.po b/po/cs.po
new file mode 100644
index 0000000..e8bbc0d
--- /dev/null
+++ b/po/cs.po
@@ -0,0 +1,1295 @@
+# Portable object template file for sudo
+# This file is put in the public domain.
+# Todd C. Miller <Todd.Miller@courtesan.com>, 2011-2013
+# Petr Pisar <petr.pisar@atlas.cz>, 2013, 2014, 2015, 2016, 2017, 2018, 2019.
+# Petr Pisar <petr.pisar@atlas.cz>, 2020, 2021, 2022, 2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.14b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-06-07 13:27-0600\n"
+"PO-Revision-Date: 2023-06-08 20:50+02:00\n"
+"Last-Translator: Petr Pisar <petr.pisar@atlas.cz>\n"
+"Language-Team: Czech <translation-team-cs@lists.sourceforge.net>\n"
+"Language: cs\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "nelze otevřít databázi uživatelů"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "nelze se přepnout do registru „%s“ pro %s"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "registr nelze obnovit"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:78 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:171 src/exec_monitor.c:418
+#: src/exec_monitor.c:424 src/exec_monitor.c:432 src/exec_monitor.c:440
+#: src/exec_monitor.c:447 src/exec_monitor.c:454 src/exec_monitor.c:461
+#: src/exec_monitor.c:468 src/exec_monitor.c:475 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:744 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1096
+#: src/exec_ptrace.c:1271 src/exec_ptrace.c:1624 src/exec_ptrace.c:1651
+#: src/exec_ptrace.c:1841 src/exec_pty.c:581 src/exec_pty.c:765
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:193 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:240
+#: src/sesh.c:246 src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:644
+#: src/sudo.c:709 src/sudo.c:719 src/sudo.c:746 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:787 src/sudo.c:805 src/sudo.c:846 src/sudo.c:855 src/sudo.c:865
+#: src/sudo.c:898 src/sudo.c:1127 src/sudo.c:1148 src/sudo.c:1441
+#: src/sudo.c:1610 src/sudo.c:1837 src/sudo.c:2171 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:430 src/sudo_edit.c:439
+#: src/sudo_edit.c:540 src/sudo_edit.c:547 src/sudo_edit.c:692
+#: src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:79 src/exec_intercept.c:111 src/exec_intercept.c:350
+#: src/exec_intercept.c:525 src/exec_intercept.c:589 src/exec_intercept.c:713
+#: src/exec_intercept.c:837 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:418 src/exec_monitor.c:424
+#: src/exec_monitor.c:432 src/exec_monitor.c:440 src/exec_monitor.c:447
+#: src/exec_monitor.c:454 src/exec_monitor.c:461 src/exec_monitor.c:468
+#: src/exec_monitor.c:475 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1651 src/exec_ptrace.c:1842 src/exec_pty.c:581
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:228 src/sudo.c:644 src/sudo.c:898 src/sudo.c:1127
+#: src/sudo.c:1148 src/sudo.c:1441 src/sudo.c:1610 src/sudo.c:1837
+#: src/sudo.c:2171 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:430
+#: src/sudo_edit.c:439 src/sudo_edit.c:540 src/sudo_edit.c:547
+#: src/sudo_edit.c:692 src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "nelze alokovat paměť"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "nelze získat údaje o %.*s"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s existuje, ale nejedná se o adresář (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:664
+#: lib/util/sudo_conf.c:683 lib/util/sudo_conf.c:710 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:495 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "%s nelze otevřít"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "adresář %.*s nelze vytvořit"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "%.*s nelze otevřít"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "regulární výraz je příliš dlouhý"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Neznámý signál"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "neplatná hodnota"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "hodnota je příliš velká"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "hodnota je příliš malá"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "neplatná hodnota Path „%s“ v %s, řádek %u"
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "neplatná hodnota pro %s „%s“ v %s, řádek %u"
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "nepodporovaný zdroj skupin „%s“ v %s, řádek %u"
+
+# This is about maximal GID. English text "max groups" is wrong.
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "neplatné maximum skupin „%s“ v %s, řádek %u"
+
+#: lib/util/sudo_conf.c:686
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s není obyčejný soubor"
+
+#: lib/util/sudo_conf.c:689 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s je vlastněn UID %u, avšak UID by mělo být %u"
+
+#: lib/util/sudo_conf.c:693
+#, c-format
+msgid "%s is world writable"
+msgstr "%s je zapisovatelný pro všechny"
+
+#: lib/util/sudo_conf.c:696
+#, c-format
+msgid "%s is group writable"
+msgstr "%s je zapisovatelný pro skupinu"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "nepodařilo se určit uzavření AppArmoru"
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "profil AppArmoru nelze změnit na %s"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: zkrátit %s na nula bajtů? (y pro ano / n pro ne) [n] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "%s nebude přepsáno"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "z %s nelze číst"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "do %s nelze zapsat"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "nelze získat údaje o %s"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: nejedná se o obyčejný soubor"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: chybná práva souboru: 0%o"
+
+#: src/edit_open.c:333
+msgid "unable to restore current working directory"
+msgstr "současný pracovní adresář nelze obnovit"
+
+# This sets an inhertiable set of Solaris process privileges.
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "nelze nastavit množinu děditelných oprávnění"
+
+# This sets a limit set of Solaris process privileges.
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "nelze nastavit množinu omezující oprávnění"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "neznámá přihlašovací třída %s"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "nelze nastavit kontext uživatele"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "nelze nastavit prioritu procesu"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "kořenový adresář nelze změnit na %s"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "nelze změnit UID na (%u, %u)"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "pracovní adresář nelze změnit na %s"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "začíná se od %s"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:552 src/exec_monitor.c:554
+#: src/exec_pty.c:1122 src/exec_pty.c:1124 src/signal.c:144 src/signal.c:151
+#: src/signal.c:165 src/suspend_parent.c:143
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "obsluhu pro signál %d nelze nastavit"
+
+#: src/exec.c:424
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "režim zachytávání není na tomto systému se selinuxovým RBAC podporován"
+
+#: src/exec.c:429
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "na tomto systému se selinuxovým RBAC nelze zaznamenávat podpříkazy"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "z PRIV_LIMIT nelze odstranit PRIV_PROC_EXEC"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:163 src/exec_iolog.c:173
+#: src/exec_iolog.c:218 src/exec_iolog.c:225 src/exec_iolog.c:252
+#: src/exec_monitor.c:426 src/exec_monitor.c:434 src/exec_monitor.c:442
+#: src/exec_monitor.c:449 src/exec_monitor.c:456 src/exec_monitor.c:463
+#: src/exec_monitor.c:470 src/exec_monitor.c:477 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:457 src/exec_pty.c:432
+#: src/exec_pty.c:537 src/exec_pty.c:587 src/exec_pty.c:965 src/exec_pty.c:974
+#: src/exec_pty.c:981 src/exec_pty.c:988 src/exec_pty.c:995
+#: src/exec_pty.c:1002 src/exec_pty.c:1009 src/exec_pty.c:1016
+#: src/exec_pty.c:1023 src/exec_pty.c:1030 src/exec_pty.c:1037
+#: src/exec_pty.c:1044
+msgid "unable to add event to queue"
+msgstr "událost nelze přidat do fronty"
+
+#: src/exec_intercept.c:323 src/sudo.c:1033
+msgid "command not set by the security policy"
+msgstr "příkaz nenastaven bezpečnostní politikou"
+
+#: src/exec_intercept.c:401 src/exec_intercept.c:441 src/sudo.c:1253
+#: src/sudo.c:1298 src/sudo.c:1342
+msgid "command rejected by policy"
+msgstr "příkaz zamítnut politikou"
+
+#: src/exec_intercept.c:512 src/sudo.c:1940
+msgid "approval plugin error"
+msgstr "chyba schvalovacího modulu"
+
+#: src/exec_intercept.c:537 src/sudo.c:1258 src/sudo.c:1303 src/sudo.c:1347
+#: src/sudo.c:1421
+msgid "policy plugin error"
+msgstr "chyba modulu s politikou"
+
+#: src/exec_intercept.c:566
+msgid "invalid PolicyCheckRequest"
+msgstr "neplatný požadavek PolicyCheckRequest"
+
+#: src/exec_intercept.c:709
+#, c-format
+msgid "client request too large: %zu"
+msgstr "požadavek od klienta je příliš dlouhý: %zu"
+
+#: src/exec_intercept.c:751
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "nelze rozbalit %s o velikosti %zu"
+
+#: src/exec_intercept.c:799
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "nečekaná hodnota type_case %d v %s od %s"
+
+#: src/exec_intercept.c:825
+#, c-format
+msgid "server message too large: %zu"
+msgstr "zpráva serveru je příliš dlouhá: %zu"
+
+#: src/exec_iolog.c:321 src/exec_iolog.c:361 src/exec_iolog.c:401
+#: src/exec_iolog.c:452 src/exec_iolog.c:503
+msgid "I/O plugin error"
+msgstr "chyba vstupně-výstupního modulu"
+
+#: src/exec_iolog.c:325 src/exec_iolog.c:365 src/exec_iolog.c:405
+#: src/exec_iolog.c:456 src/exec_iolog.c:507
+msgid "command rejected by I/O plugin"
+msgstr "příkaz zamítnut vstupně-výstupním modulem"
+
+#: src/exec_iolog.c:555
+msgid "error logging suspend"
+msgstr "chyba pozastavování protokolu"
+
+#: src/exec_iolog.c:590
+msgid "error changing window size"
+msgstr "chyba při měnění velikosti okna"
+
+#: src/exec_monitor.c:328
+msgid "error reading from socketpair"
+msgstr "chyba při čtení z dvojice socketů"
+
+#: src/exec_monitor.c:340
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "neočekávaný druh odpovědi na zpětném kanálu: %d"
+
+#: src/exec_monitor.c:566
+msgid "unable to set controlling tty"
+msgstr "řídicí terminál nelze nastavit"
+
+#: src/exec_monitor.c:574 src/exec_nopty.c:504 src/exec_nopty.c:514
+#: src/exec_nopty.c:524 src/exec_nopty.c:560 src/exec_pty.c:1195
+#: src/exec_pty.c:1222 src/exec_pty.c:1242 src/exec_pty.c:1262
+#: src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr "nelze vytvořit rouru"
+
+#: src/exec_monitor.c:584
+msgid "unable to receive message from parent"
+msgstr "od rodiče nelze přijmout zprávu"
+
+#: src/exec_monitor.c:600 src/exec_nopty.c:603 src/exec_pty.c:1303
+#: src/sudo_edit.c:361 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr "nelze vytvořit potomka"
+
+#: src/exec_monitor.c:604 src/exec_monitor.c:700 src/exec_nopty.c:708
+msgid "unable to restore tty label"
+msgstr "nelze obnovit značku TTY"
+
+#: src/exec_monitor.c:615 src/sesh.c:217 src/sudo.c:1204
+#, c-format
+msgid "unable to execute %s"
+msgstr "%s nelze spustit"
+
+#: src/exec_nopty.c:554 src/exec_pty.c:1131
+msgid "policy plugin failed session initialization"
+msgstr "modul s politikami zrušil inicializaci relace"
+
+#: src/exec_nopty.c:569 src/exec_pty.c:1100 src/exec_pty.c:1109
+msgid "unable to create sockets"
+msgstr "nelze vytvořit sockety"
+
+#: src/exec_nopty.c:696 src/exec_pty.c:1406
+msgid "error in event loop"
+msgstr "chyba ve smyčce s událostmi"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:852 src/sudo.c:488
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "vnitřní chyba, přetečení v %s"
+
+#: src/exec_ptrace.c:1080 src/exec_ptrace.c:1105 src/exec_ptrace.c:1925
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "nelze nastavit registry pro proces %d"
+
+#: src/exec_ptrace.c:1100 src/exec_ptrace.c:1275 src/exec_ptrace.c:1628
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "proces %d nečekaně skončil"
+
+#: src/exec_ptrace.c:1209
+msgid "unable to set seccomp filter"
+msgstr "nelze nastavit filtr seccomp"
+
+#: src/exec_ptrace.c:1406
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "argument interpretru, očekáváno „%s“, obdrženo „%s“"
+
+#: src/exec_ptrace.c:1505
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "cesta neodpovídá, očekáváno „%s“, obdrženo „%s“"
+
+#: src/exec_ptrace.c:1514 src/exec_ptrace.c:1521 src/exec_ptrace.c:1545
+#: src/exec_ptrace.c:1553 src/exec_ptrace.c:1559 src/exec_ptrace.c:1565
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "%s[%d] neodpovídá, očekáváno „%s“, obdrženo „%s“"
+
+#: src/exec_ptrace.c:1632
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "proces %d má nečekaný stav 0x%x"
+
+#: src/exec_ptrace.c:1723
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "nelze získat zprávu o události v procesu %d"
+
+#: src/exec_ptrace.c:1730
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "nelze získat registry procesu %d"
+
+#: src/exec_pty.c:84
+msgid "unable to allocate pty"
+msgstr "nelze alokovat PTY"
+
+#: src/exec_pty.c:131 src/exec_pty.c:284 src/tgetpass.c:251
+msgid "unable to restore terminal settings"
+msgstr "nastavení terminálu nelze obnovit"
+
+#: src/exec_pty.c:243
+msgid "unable to set handler for SIGCONT"
+msgstr "obsluhu pro signál SIGCONT nelze nastavit"
+
+#: src/exec_pty.c:293
+#, c-format
+msgid "unable to set handler for SIG%s"
+msgstr "obsluhu pro signál SIG%s nelze nastavit"
+
+#: src/exec_pty.c:317
+#, c-format
+msgid "unable to restore handler for SIG%s"
+msgstr "nelze obnovit obsluhu signálu SIG%s"
+
+#: src/exec_pty.c:345
+msgid "unable to restore handler for SIGCONT"
+msgstr "nelze obnovit obsluhu signálu SIGCONT"
+
+#: src/exec_pty.c:1353
+msgid "unable to send message to monitor process"
+msgstr "dohlížejícímu procesu nelze odeslat zprávu"
+
+#: src/load_plugins.c:75 src/load_plugins.c:222 src/load_plugins.c:232
+#: src/load_plugins.c:242 src/load_plugins.c:289
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "chyba v %s na řádku %d při zavádění modulu „%s“"
+
+#: src/load_plugins.c:186 src/load_plugins.c:257
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "ignoruje je opakovaný modul „%s“ v %s na řádku %d"
+
+#: src/load_plugins.c:224
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "%s nelze zavést: %s"
+
+#: src/load_plugins.c:234
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "v %s nelze nalézt symbol „%s“"
+
+#: src/load_plugins.c:244
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "neslučitelná hlavní verze modulu %d (očekáváno %d) nalezena v %s"
+
+#: src/load_plugins.c:262
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "ignoruje se modul politiky „%s“ v %s na řádku %d"
+
+#: src/load_plugins.c:265
+msgid "only a single policy plugin may be specified"
+msgstr "lze zadat pouze jeden modul s politikou"
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "v %2$s nalezen neznámý druh modulu %1$d"
+
+#: src/load_plugins.c:474
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "modul s politikou %s neobsahuje metodu check_policy"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "neplatný název proměnné prostředí: %s"
+
+#: src/parse_args.c:319
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "argument u -C musí být číslo větší nebo rovno 3"
+
+#: src/parse_args.c:556
+msgid "you may not specify both the -i and -s options"
+msgstr "nesmíte zadávat přepínače -i a -s spolu"
+
+#: src/parse_args.c:561
+msgid "you may not specify both the -i and -E options"
+msgstr "nesmíte zadávat přepínače -i a -E spolu"
+
+#: src/parse_args.c:571
+msgid "the -E option is not valid in edit mode"
+msgstr "přepínač -E není platný v režimu úprav"
+
+#: src/parse_args.c:574
+msgid "you may not specify environment variables in edit mode"
+msgstr "v režimu úprav nesmíte zadávat proměnné prostředí"
+
+#: src/parse_args.c:584
+msgid "the -U option may only be used with the -l option"
+msgstr "přepínač -U smí být použit jen s přepínačem -l"
+
+#: src/parse_args.c:588
+msgid "the -A and -S options may not be used together"
+msgstr "přepínače -A a -S smí nesmí být použity spolu"
+
+#: src/parse_args.c:686
+msgid "sudoedit is not supported on this platform"
+msgstr "na této platformě není sudoedit podporován"
+
+#: src/parse_args.c:744
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Smí být zadán pouze jeden z přepínačů -e, -h, -i, -K, -l, -s, -v nebo -V"
+
+#: src/parse_args.c:757
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "Smí být zadán pouze jeden z přepínačů -K, -k nebo -N"
+
+#: src/parse_args.c:778
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s – upraví soubory jako jiný uživatel\n"
+"\n"
+
+#: src/parse_args.c:780
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s – vykoná příkaz jako jiný uživatel\n"
+"\n"
+
+#: src/parse_args.c:785
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Přepínače:\n"
+
+#: src/parse_args.c:787
+msgid "use a helper program for password prompting"
+msgstr "dotazuje se na heslo prostřednictvím pomocného programu"
+
+#: src/parse_args.c:790
+msgid "use specified BSD authentication type"
+msgstr "použije zadaný druh BSD autentizace"
+
+#: src/parse_args.c:794
+msgid "run command in the background"
+msgstr "spustí příkaz na pozadí"
+
+#: src/parse_args.c:797
+msgid "ring bell when prompting"
+msgstr "při výzvě vydá zvukové znamení"
+
+#: src/parse_args.c:799
+msgid "close all file descriptors >= num"
+msgstr "uzavře všechny deskriptory souboru >= číslu"
+
+#: src/parse_args.c:802
+msgid "run command with the specified BSD login class"
+msgstr "spustí příkaz se zadanou přihlašovací třídou BSD"
+
+#: src/parse_args.c:805
+msgid "change the working directory before running command"
+msgstr "změní pracovní adresář před spuštěním příkazu"
+
+#: src/parse_args.c:808
+msgid "preserve user environment when running command"
+msgstr "při spuštění příkazu zachová uživatelské prostředí"
+
+#: src/parse_args.c:810
+msgid "preserve specific environment variables"
+msgstr "zachová určité proměnné prostředí"
+
+#: src/parse_args.c:812
+msgid "edit files instead of running a command"
+msgstr "místo spuštění příkazu upraví soubory"
+
+#: src/parse_args.c:815
+msgid "run command as the specified group name or ID"
+msgstr "spustí příkaz jako skupina určení názvem nebo ID"
+
+#: src/parse_args.c:818
+msgid "set HOME variable to target user's home dir"
+msgstr "nastaví proměnnou HOME na domovský adresář uživatele"
+
+#: src/parse_args.c:821
+msgid "display help message and exit"
+msgstr "zobrazí nápovědu a skončí"
+
+#: src/parse_args.c:823
+msgid "run command on host (if supported by plugin)"
+msgstr "spustí příkaz na stroji (je-li podporováno modulem)"
+
+#: src/parse_args.c:826
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "spustí přihlašovací shell jako cílový uživatel; příkaz lze rovněž zadat"
+
+#: src/parse_args.c:828
+msgid "remove timestamp file completely"
+msgstr "úplně odstraní soubor s časovými údaji"
+
+#: src/parse_args.c:831
+msgid "invalidate timestamp file"
+msgstr "zneplatní soubor s časovými údaji"
+
+#: src/parse_args.c:834
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "vypíše oprávnění uživatele nebo zkontroluje určitý příkaz; pro delší výstup použijte dvakrát"
+
+#: src/parse_args.c:837
+msgid "non-interactive mode, no prompts are used"
+msgstr "neinteraktivní režim, nepoužijí se žádné dotazy"
+
+#: src/parse_args.c:840
+msgid "preserve group vector instead of setting to target's"
+msgstr "zachová vektor skupin namísto nastavení na skupiny cíle"
+
+#: src/parse_args.c:843
+msgid "use the specified password prompt"
+msgstr "použije určený dotaz na heslo"
+
+#: src/parse_args.c:845
+msgid "change the root directory before running command"
+msgstr "změní kořenový adresář přes spuštěním příkazu"
+
+#: src/parse_args.c:848
+msgid "create SELinux security context with specified role"
+msgstr "vytvoří selinuxový bezpečnostní kontext se zadanou rolí"
+
+#: src/parse_args.c:851
+msgid "read password from standard input"
+msgstr "načte heslo ze standardní vstupu"
+
+#: src/parse_args.c:854
+msgid "run shell as the target user; a command may also be specified"
+msgstr "spustí shell jako cílový uživatel; příkaz lze rovněž zadat"
+
+#: src/parse_args.c:858
+msgid "create SELinux security context with specified type"
+msgstr "vytvoří selinuxový bezpečnostní kontext se zadaným typem"
+
+#: src/parse_args.c:861
+msgid "terminate command after the specified time limit"
+msgstr "po uplynutí zadaného času ukončí příkaz"
+
+#: src/parse_args.c:864
+msgid "in list mode, display privileges for user"
+msgstr "v režimu výpisu zobrazí oprávnění uživatele"
+
+#: src/parse_args.c:867
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "spustí příkaz (nebo upraví soubor) jako uživatel určený jménem nebo ID"
+
+#: src/parse_args.c:869
+msgid "display version information and exit"
+msgstr "zobrazí údaje o verzi a skončí"
+
+#: src/parse_args.c:872
+msgid "update user's timestamp without running a command"
+msgstr "aktualizuje časové údaje uživatele bez spuštění příkazu"
+
+#: src/parse_args.c:875
+msgid "stop processing command line arguments"
+msgstr "přestane zpracovávat argumenty příkazového řádku"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "nelze otevřít auditní systém"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "nelze odeslat auditní zprávu"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "nelze získat kontext souboru %s pomocí fgetfilecon"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s změnilo značky"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "nelze obnovit kontext %s"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "%s nelze otevřít, TTY nebude značka přepsána"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s není znakové zařízení, TTY nebude značka přepsána"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "nelze získat kontext současného TTY, TTY nebude značka přepsána"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "neznámá bezpečnostní třída „chr_file“, TTY nebude značka přepsána"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "nelze získat nový kontext TTY, TTY nebude značka přepsána"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "nelze nastavit nový kontext TTY"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "pro typ %s musíte zadat roli"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "výchozí typ pro roli %s nelze získat"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "nepodařilo se získat nový kontext"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "nepodařilo se nastavit novou roli %s"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "nepodařilo se nastavit nový typ %s"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s není platný kontext"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "nepodařilo se získat starý kontext"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "nepodařilo se určit režim vynucování SELinuxu."
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "nepodařilo se nastavit kontext pro spuštění na %s"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "nepodařilo se nastavit kontext pro vytváření klíčů na %s"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "Smí být zadán pouze jeden z přepínačů -c nebo -i"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "neplatné číslo deskriptoru souboru: %s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "Přepínač -%c nesmí být použit v režimu úprav."
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "Přepínač -%c smí být použit v režimu úprav."
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: úprava symbolických odkazů není dovolena"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: úprava souborů v adresáři, do kterého lze zapisovat, není dovolena"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "obsah relace s úpravami ponechán v %s"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "nelze získat seznam skupin"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "obsluhu signálu %d nelze uložit"
+
+#: src/signal.c:101 src/suspend_parent.c:149
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "nelze obnovit obsluhu signálu %d"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "omezení z řízení zdrojů bylo dosaženo"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "uživatel „%s“ není členem projektu „%s“"
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "volaná úloha je konečná"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "nebylo možné se připojit k projektu „%s“"
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "pro projekt „%s“ neexistuje žádná množina zdrojů přijímající výchozí vazbu"
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "pro projekt „%s“ neexistuje zadaná množina zdrojů"
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "u projektu „%s“ se nebylo možné navázat na výchozí množinu zdrojů"
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "volání setproject selhalo u projektu „%s“"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "pozor, nepodařilo se přiřadit řízení zdrojů projektu „%s“"
+
+#: src/sudo.c:214
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo verze %s\n"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Přepínače configure: %s\n"
+
+#: src/sudo.c:224
+msgid "fatal error, unable to load plugins"
+msgstr "nepřekonatelná chyba, moduly nelze zavést"
+
+#: src/sudo.c:270
+msgid "plugin did not return a command to execute"
+msgstr "modul nevrátil příkaz k provedení"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "neočekávaný režim programu sudo 0x%x"
+
+#: src/sudo.c:559
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "neexistujete v databázi %s"
+
+#: src/sudo.c:616
+msgid "unable to determine tty"
+msgstr "nelze určit terminál"
+
+#: src/sudo.c:932
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "Je nastaven příznak „žádná další oprávnění“, což brání sudu, aby běželo jako root"
+
+#: src/sudo.c:934
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "Běží-li sudo v kontejneru, můžete potřebovat upravit nastavení kontejneru, aby se tento příznak vypnul."
+
+#: src/sudo.c:968
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s musí být vlastněn UID %d a mít nastaven bit setuid"
+
+#: src/sudo.c:971
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "efektivní UID není %d, nalézá se %s na souborovém systému s nastavenou volbou „nosuid“ nebo na souborovém systému NFS bez práv roota?"
+
+#: src/sudo.c:977
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "efektivní UID není %d, je sudo nainstalované jako setuid vlastněné rootem?"
+
+#: src/sudo.c:993 src/tgetpass.c:332
+msgid "unable to set supplementary group IDs"
+msgstr "nelze nastavit ID doplňkových skupin"
+
+#: src/sudo.c:1000
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "efektivní GID nelze nastavit na %u"
+
+#: src/sudo.c:1006
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "GID nelze nastavit na %u"
+
+#: src/sudo.c:1037
+msgid "argv not set by the security policy"
+msgstr "pole argumentů nenastaveno bezpečnostní politikou"
+
+#: src/sudo.c:1041
+msgid "envp not set by the security policy"
+msgstr "pole proměnných prostředí nenastaveno bezpečnostní politikou"
+
+#: src/sudo.c:1063
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "neočekávaný důvod ukončení potomka: %d"
+
+#: src/sudo.c:1176
+msgid "unable to initialize policy plugin"
+msgstr "modul s politikami nelze inicializovat"
+
+#: src/sudo.c:1238
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "modulu s politikami %s chybí metoda „check_policy“"
+
+#: src/sudo.c:1284
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "modul s politikami %s nepodporuje získání seznamu oprávnění"
+
+#: src/sudo.c:1328
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "modul s politikami %s nepodporuje přepínač -v"
+
+#: src/sudo.c:1366
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "modul s politikami %s nepodporuje přepínače -k/-K"
+
+#: src/sudo.c:1495
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "chyba při inicializaci vstupně-výstupního modulu %s"
+
+#: src/sudo.c:1498
+msgid "error initializing I/O plugin"
+msgstr "chyba při inicializaci vstupně-výstupního modulu"
+
+#: src/sudo.c:1647
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "chyba při inicializaci auditního modulu %s"
+
+#: src/sudo.c:1726
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s nelze zaznamenat chybovou událost%s%s"
+
+#: src/sudo.c:1762
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s nelze zaznamenat přijímací událost%s%s "
+
+#: src/sudo.c:1767 src/sudo.c:1805
+msgid "audit plugin error"
+msgstr "chyba auditního modulu"
+
+#: src/sudo.c:1800
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s nelze zaznamenat zamítací událost%s%s "
+
+#: src/sudo.c:1860
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "chyba při inicializaci schvalovacího modulu %s"
+
+#: src/sudo.c:1930
+msgid "command rejected by approver"
+msgstr "příkaz zamítnut schvalovatelem"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "nenalezen žádný dočasný adresář, do kterého lze zapisovat"
+
+#: src/sudo_edit.c:292
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s ponechán nezměněn"
+
+#: src/sudo_edit.c:305 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s nezměněn"
+
+#: src/sudo_edit.c:482
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: vnitřní chyba: lichý počet cest"
+
+#: src/sudo_edit.c:484
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: nelze vytvořit dočasné soubory"
+
+#: src/sudo_edit.c:486 src/sudo_edit.c:606
+msgid "sesh: killed by a signal"
+msgstr "sesh: zabit signálem"
+
+#: src/sudo_edit.c:488 src/sudo_edit.c:609
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: neznámá chyba %d"
+
+#: src/sudo_edit.c:599
+msgid "unable to copy temporary files back to their original location"
+msgstr "dočasné soubory nelze zkopírovat zpět na jejich původní místo"
+
+#: src/sudo_edit.c:603
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "některé z dočasných souborů nelze zkopírovat zpět na jejich původní místo"
+
+#: src/sudo_edit.c:650
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "UID nelze změnit na roota (%u)"
+
+#: src/sudo_edit.c:664
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "chyba modulu: neplatný seznam souborů pro program sudoedit"
+
+#: src/sudo_edit.c:685
+msgid "plugin error: missing file list for sudoedit"
+msgstr "chyba modulu: chybí seznam souborů pro program sudoedit"
+
+#: src/sudo_edit.c:728 src/sudo_edit.c:743
+msgid "unable to read the clock"
+msgstr "nelze přečíst hodiny"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "zachytávací port nenastaven"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "při čtení hesla vypršel čas"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "žádné heslo nebylo poskytnuto"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "heslo nelze přečíst"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "po terminálu se vyžaduje načtení hesla; buď jej přečtěte ze standardního vstupu pomocí přepínače -S, nebo nastavte pomocný program askpass"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "program pro dotazování se na heslo nebyl zadán, zkuste nastavit SUDO_ASKPASS"
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "GID nelze nastavit na %u"
+
+#: src/tgetpass.c:337
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "UID nelze nastavit na %u"
+
+#: src/tgetpass.c:342
+#, c-format
+msgid "unable to run %s"
+msgstr "%s nelze spustit"
+
+#: src/utmp.c:283
+msgid "unable to save stdin"
+msgstr "standardní vstup nelze uložit"
+
+#: src/utmp.c:285
+msgid "unable to dup2 stdin"
+msgstr "standardní vstup nelze zduplikovat voláním dup2"
+
+#: src/utmp.c:288
+msgid "unable to restore stdin"
+msgstr "standardní vstup nelze obnovit"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s musí být vlastněn UID %d"
+
+#~ msgid "%s must be only be writable by owner"
+#~ msgstr "%s musí být zapisovatelný jen vlastníkem"
+
+#~ msgid "insufficient space for execve arguments"
+#~ msgstr "nedostatek místa pro argumenty volání execve"
+
+#~ msgid "unable to read execve %s for process %d"
+#~ msgstr "nelze přečíst %s volání execve pro proces %d"
+
+#~ msgid "requires at least one argument"
+#~ msgstr "je třeba alespoň jeden argument"
+
+#~ msgid "unable to run %s as a login shell"
+#~ msgstr "%s nelze spustit jako přihlašovací shell"
+
+#~ msgid "unable to dup intercept fd"
+#~ msgstr "zachycený deskriptor souboru nelze zduplikovat"
+
+#~ msgid "%s: missing message header"
+#~ msgstr "%s: chybí hlavička zprávy"
+
+#~ msgid "%s: expected message type %d, got %d"
+#~ msgstr "%s: očekávaný typ zprávy %d, obdržen %d"
+
+#~ msgid "unable to set tty context to %s"
+#~ msgstr "nepodařilo se nastavit kontext TTY na %s"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s: %s"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s: krátký zápis"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "nelze přečíst dočasný soubor"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "ignoruje je opakovaný modul s politikou „%s“ v %s na řádku %d"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "chybí terminál a program pro dotazování se na heslo nebyl zadán"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "neznámé UID %u: kdo jsi?"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "chyba při čtení ze signální roury"
+
+#~ msgid "unable to set terminal to raw mode"
+#~ msgstr "terminál nelze přepnout do syrového režimu"
+
+#~ msgid "internal error, tried allocate zero bytes"
+#~ msgstr "vnitřní chyba, pokus alokovat nula bajtů"
+
+#~ msgid "unable to open socket"
+#~ msgstr "nelze otevřít socket"
+
+#~ msgid "%s: %s: %s\n"
+#~ msgstr "%s: %s: %s\n"
+
+#~ msgid "%s: %s\n"
+#~ msgstr "%s: %s\n"
+
+#~ msgid "internal error, tried to emalloc2(0)"
+#~ msgstr "vnitřní chyba, pokus o emalloc2(0)"
+
+#~ msgid "internal error, tried to ecalloc(0)"
+#~ msgstr "vnitřní chyba, pokus o ecalloc(0)"
+
+#~ msgid "internal error, tried to erealloc(0)"
+#~ msgstr "vnitřní chyba, pokus o erealloc(0)"
+
+#~ msgid "internal error, tried to erealloc3(0)"
+#~ msgstr "vnitřní chyba, pokus o erealloc3(0)"
+
+#~ msgid "internal error, tried to erecalloc(0)"
+#~ msgstr "vnitřní chyba, pokus o erecalloc(0)"
+
+#~ msgid "load_interfaces: overflow detected"
+#~ msgstr "load_interfaces: zjištěno přetečení"
+
+#~ msgid "value out of range"
+#~ msgstr "hodnota je mimo rozsah"
+
+#~ msgid "select failed"
+#~ msgstr "volání select selhalo"
diff --git a/po/da.mo b/po/da.mo
new file mode 100644
index 0000000..3cc335b
--- /dev/null
+++ b/po/da.mo
Binary files differ
diff --git a/po/da.po b/po/da.po
new file mode 100644
index 0000000..541d8fc
--- /dev/null
+++ b/po/da.po
@@ -0,0 +1,946 @@
+# Danish translation of sudo.
+# This file is put in the public domain.
+# Joe Hansen <joedalton2@yahoo.dk>, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019.
+#
+# audit -> overvågning
+# overflow -> overløb
+#
+# projekt bruger konsekvent små bogstaver, og så i starten af sætninger, så
+# dette er også valgt på dansk uanset at der er : som efterfølgende normalt
+# ville have stort begyndelsesbogstav på dansk.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.8.26b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2018-10-29 08:31-0600\n"
+"PO-Revision-Date: 2019-03-08 23:06+0100\n"
+"Last-Translator: Joe Hansen <joedalton2@yahoo.dk>\n"
+"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
+"Language: da\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+
+#: lib/util/aix.c:90 lib/util/aix.c:177
+msgid "unable to open userdb"
+msgstr "kan ikke åbne userdb"
+
+#: lib/util/aix.c:232
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "kan ikke skifte til register »%s« for %s"
+
+#: lib/util/aix.c:257
+msgid "unable to restore registry"
+msgstr "kan ikke gendanne register"
+
+#: lib/util/aix.c:280 lib/util/gidlist.c:69 lib/util/gidlist.c:79
+#: lib/util/sudo_conf.c:191 lib/util/sudo_conf.c:277 lib/util/sudo_conf.c:354
+#: lib/util/sudo_conf.c:558 src/conversation.c:82 src/exec_common.c:112
+#: src/exec_common.c:128 src/exec_common.c:137 src/exec_monitor.c:210
+#: src/exec_monitor.c:465 src/exec_monitor.c:471 src/exec_monitor.c:479
+#: src/exec_monitor.c:487 src/exec_monitor.c:494 src/exec_monitor.c:501
+#: src/exec_monitor.c:508 src/exec_monitor.c:515 src/exec_monitor.c:522
+#: src/exec_monitor.c:529 src/exec_monitor.c:536 src/exec_nopty.c:212
+#: src/exec_nopty.c:218 src/exec_nopty.c:227 src/exec_nopty.c:234
+#: src/exec_nopty.c:241 src/exec_nopty.c:248 src/exec_nopty.c:255
+#: src/exec_nopty.c:262 src/exec_nopty.c:269 src/exec_nopty.c:276
+#: src/exec_nopty.c:283 src/exec_nopty.c:290 src/exec_nopty.c:297
+#: src/exec_nopty.c:305 src/exec_nopty.c:467 src/exec_pty.c:778
+#: src/exec_pty.c:787 src/exec_pty.c:844 src/exec_pty.c:994
+#: src/exec_pty.c:1157 src/exec_pty.c:1163 src/exec_pty.c:1172
+#: src/exec_pty.c:1179 src/exec_pty.c:1186 src/exec_pty.c:1193
+#: src/exec_pty.c:1200 src/exec_pty.c:1207 src/exec_pty.c:1214
+#: src/exec_pty.c:1221 src/exec_pty.c:1228 src/exec_pty.c:1235
+#: src/exec_pty.c:1243 src/exec_pty.c:1661 src/load_plugins.c:57
+#: src/load_plugins.c:70 src/load_plugins.c:219 src/load_plugins.c:240
+#: src/load_plugins.c:309 src/load_plugins.c:315 src/load_plugins.c:329
+#: src/load_plugins.c:335 src/parse_args.c:182 src/parse_args.c:203
+#: src/parse_args.c:278 src/parse_args.c:565 src/parse_args.c:587
+#: src/preserve_fds.c:52 src/preserve_fds.c:137 src/selinux.c:89
+#: src/selinux.c:314 src/selinux.c:437 src/selinux.c:446 src/sesh.c:115
+#: src/sudo.c:616 src/sudo.c:676 src/sudo.c:686 src/sudo.c:706 src/sudo.c:725
+#: src/sudo.c:734 src/sudo.c:743 src/sudo.c:760 src/sudo.c:801 src/sudo.c:811
+#: src/sudo.c:834 src/sudo.c:1071 src/sudo.c:1092 src/sudo.c:1266
+#: src/sudo.c:1382 src/sudo_edit.c:256 src/sudo_edit.c:789 src/sudo_edit.c:886
+#: src/sudo_edit.c:1000 src/sudo_edit.c:1020
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:280 lib/util/gidlist.c:69 lib/util/sudo_conf.c:192
+#: lib/util/sudo_conf.c:277 lib/util/sudo_conf.c:354 lib/util/sudo_conf.c:558
+#: src/conversation.c:83 src/exec_common.c:112 src/exec_common.c:129
+#: src/exec_common.c:138 src/exec_monitor.c:465 src/exec_monitor.c:471
+#: src/exec_monitor.c:479 src/exec_monitor.c:487 src/exec_monitor.c:494
+#: src/exec_monitor.c:501 src/exec_monitor.c:508 src/exec_monitor.c:515
+#: src/exec_monitor.c:522 src/exec_monitor.c:529 src/exec_monitor.c:536
+#: src/exec_nopty.c:212 src/exec_nopty.c:218 src/exec_nopty.c:227
+#: src/exec_nopty.c:234 src/exec_nopty.c:241 src/exec_nopty.c:248
+#: src/exec_nopty.c:255 src/exec_nopty.c:262 src/exec_nopty.c:269
+#: src/exec_nopty.c:276 src/exec_nopty.c:283 src/exec_nopty.c:290
+#: src/exec_nopty.c:297 src/exec_nopty.c:305 src/exec_pty.c:778
+#: src/exec_pty.c:787 src/exec_pty.c:844 src/exec_pty.c:1157
+#: src/exec_pty.c:1163 src/exec_pty.c:1172 src/exec_pty.c:1179
+#: src/exec_pty.c:1186 src/exec_pty.c:1193 src/exec_pty.c:1200
+#: src/exec_pty.c:1207 src/exec_pty.c:1214 src/exec_pty.c:1221
+#: src/exec_pty.c:1228 src/exec_pty.c:1235 src/exec_pty.c:1243
+#: src/exec_pty.c:1661 src/load_plugins.c:219 src/load_plugins.c:240
+#: src/load_plugins.c:309 src/load_plugins.c:315 src/load_plugins.c:329
+#: src/load_plugins.c:335 src/parse_args.c:182 src/parse_args.c:204
+#: src/parse_args.c:278 src/parse_args.c:565 src/parse_args.c:587
+#: src/preserve_fds.c:52 src/preserve_fds.c:137 src/selinux.c:89
+#: src/selinux.c:314 src/selinux.c:437 src/selinux.c:446 src/sesh.c:115
+#: src/sudo.c:616 src/sudo.c:834 src/sudo.c:1071 src/sudo.c:1092
+#: src/sudo.c:1266 src/sudo.c:1382 src/sudo_edit.c:256 src/sudo_edit.c:789
+#: src/sudo_edit.c:886 src/sudo_edit.c:1000 src/sudo_edit.c:1020
+msgid "unable to allocate memory"
+msgstr "kan ikke allokere hukommelse"
+
+#: lib/util/strsignal.c:53
+msgid "Unknown signal"
+msgstr "ukendt signal"
+
+#: lib/util/strtoid.c:82 lib/util/strtoid.c:129 lib/util/strtoid.c:157
+#: lib/util/strtomode.c:54 lib/util/strtonum.c:63 lib/util/strtonum.c:181
+msgid "invalid value"
+msgstr "ugyldig værdi"
+
+#: lib/util/strtoid.c:89 lib/util/strtoid.c:136 lib/util/strtoid.c:164
+#: lib/util/strtomode.c:60 lib/util/strtonum.c:66 lib/util/strtonum.c:193
+msgid "value too large"
+msgstr "værdi for stor"
+
+#: lib/util/strtoid.c:91 lib/util/strtoid.c:142 lib/util/strtomode.c:60
+#: lib/util/strtonum.c:66 lib/util/strtonum.c:187
+msgid "value too small"
+msgstr "værdi for lille"
+
+#: lib/util/sudo_conf.c:210
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "ugyldig stiværdi »%s« i %s, linje %u"
+
+#: lib/util/sudo_conf.c:376 lib/util/sudo_conf.c:429
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "ugyldig værdi for %s »%s« i %s, linje %u"
+
+#: lib/util/sudo_conf.c:397
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "ikke understøttet gruppekilde »%s« i %s, linje %u"
+
+#: lib/util/sudo_conf.c:413
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "ugyldigt maks. for grupper »%s« i %s, linje %u"
+
+#: lib/util/sudo_conf.c:574
+#, c-format
+msgid "unable to stat %s"
+msgstr "kan ikke køre stat %s"
+
+#: lib/util/sudo_conf.c:577
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s er ikke en regulær fil"
+
+#: lib/util/sudo_conf.c:580
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s er ejet af uid %u, burde være %u"
+
+#: lib/util/sudo_conf.c:584
+#, c-format
+msgid "%s is world writable"
+msgstr "%s er skrivbar for alle"
+
+#: lib/util/sudo_conf.c:587
+#, c-format
+msgid "%s is group writable"
+msgstr "%s er skrivbar for gruppe"
+
+#: lib/util/sudo_conf.c:597 src/selinux.c:213 src/selinux.c:230 src/sudo.c:360
+#, c-format
+msgid "unable to open %s"
+msgstr "kan ikke åbne %s"
+
+#: src/exec.c:165
+#, c-format
+msgid "unknown login class %s"
+msgstr "ukendt logindklasse %s"
+
+#: src/exec.c:178
+msgid "unable to set user context"
+msgstr "kan ikke angive brugerkontekst"
+
+#: src/exec.c:194
+msgid "unable to set process priority"
+msgstr "kan ikke angive procesprioritet"
+
+#: src/exec.c:202
+#, c-format
+msgid "unable to change root to %s"
+msgstr "kan ikke ændre administrator (root) til %s"
+
+#: src/exec.c:215 src/exec.c:221 src/exec.c:228
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "kan ikke ændre til runas uid (%u, %u)"
+
+#: src/exec.c:246
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "kan ikke ændre mappe til %s"
+
+#: src/exec.c:345 src/exec_monitor.c:574 src/exec_monitor.c:576
+#: src/exec_nopty.c:525 src/exec_pty.c:522 src/exec_pty.c:1329
+#: src/exec_pty.c:1331 src/signal.c:148 src/signal.c:162
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "kan ikke angive håndtering for signal %d"
+
+#: src/exec_common.c:171
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "kan ikke fjerne PRIV_PROC_EXEC fra PRIV_LIMIT"
+
+#: src/exec_monitor.c:364
+msgid "error reading from socketpair"
+msgstr "fejl ved læsning fra socketpair"
+
+#: src/exec_monitor.c:381
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "uventet svartype på bagkanal (backchannel): %d"
+
+#: src/exec_monitor.c:473 src/exec_monitor.c:481 src/exec_monitor.c:489
+#: src/exec_monitor.c:496 src/exec_monitor.c:503 src/exec_monitor.c:510
+#: src/exec_monitor.c:517 src/exec_monitor.c:524 src/exec_monitor.c:531
+#: src/exec_monitor.c:538 src/exec_nopty.c:220 src/exec_nopty.c:229
+#: src/exec_nopty.c:236 src/exec_nopty.c:243 src/exec_nopty.c:250
+#: src/exec_nopty.c:257 src/exec_nopty.c:264 src/exec_nopty.c:271
+#: src/exec_nopty.c:278 src/exec_nopty.c:285 src/exec_nopty.c:292
+#: src/exec_nopty.c:299 src/exec_nopty.c:307 src/exec_pty.c:644
+#: src/exec_pty.c:649 src/exec_pty.c:746 src/exec_pty.c:753 src/exec_pty.c:850
+#: src/exec_pty.c:1165 src/exec_pty.c:1174 src/exec_pty.c:1181
+#: src/exec_pty.c:1188 src/exec_pty.c:1195 src/exec_pty.c:1202
+#: src/exec_pty.c:1209 src/exec_pty.c:1216 src/exec_pty.c:1223
+#: src/exec_pty.c:1230 src/exec_pty.c:1237 src/exec_pty.c:1614
+#: src/exec_pty.c:1624 src/exec_pty.c:1669 src/exec_pty.c:1676
+#: src/exec_pty.c:1703
+msgid "unable to add event to queue"
+msgstr "kan ikke tilføje hændelse til kø"
+
+#: src/exec_monitor.c:592
+msgid "unable to set controlling tty"
+msgstr "kan ikke angive kontrollerende tty"
+
+#: src/exec_monitor.c:600 src/exec_nopty.c:364 src/exec_pty.c:1408
+#: src/exec_pty.c:1429 src/exec_pty.c:1449 src/tgetpass.c:292
+msgid "unable to create pipe"
+msgstr "kan ikke oprette datakanal (pipe)"
+
+#: src/exec_monitor.c:608
+msgid "unable to receive message from parent"
+msgstr "kan ikke modtage besked fra overproces"
+
+#: src/exec_monitor.c:614 src/exec_nopty.c:382 src/exec_pty.c:1487
+#: src/tgetpass.c:296
+msgid "unable to fork"
+msgstr "kan ikke forgrene"
+
+#: src/exec_monitor.c:628 src/sesh.c:125 src/sudo.c:1130
+#, c-format
+msgid "unable to execute %s"
+msgstr "kan ikke køre %s"
+
+#: src/exec_monitor.c:711 src/exec_nopty.c:435
+msgid "unable to restore tty label"
+msgstr "kan ikke gendanne tty-etiket"
+
+#: src/exec_nopty.c:358 src/exec_pty.c:1338
+msgid "policy plugin failed session initialization"
+msgstr "udvidelsesmodul for politik mislykkedes i sessionsinitialisering"
+
+#: src/exec_nopty.c:424 src/exec_pty.c:1574
+msgid "error in event loop"
+msgstr "fejl i hændelsesloop"
+
+#: src/exec_nopty.c:533 src/exec_pty.c:557 src/signal.c:110
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "kan ikke gendanne håndtering for signal %d"
+
+#: src/exec_pty.c:156
+msgid "unable to allocate pty"
+msgstr "kan ikke allokere pty"
+
+#: src/exec_pty.c:1318
+msgid "unable to create sockets"
+msgstr "kan ikke oprette sokler"
+
+#: src/exec_pty.c:1531
+msgid "unable to send message to monitor process"
+msgstr "kan ikke sende besked til overvågningsproces"
+
+#: src/load_plugins.c:55 src/load_plugins.c:68 src/load_plugins.c:90
+#: src/load_plugins.c:120 src/load_plugins.c:128 src/load_plugins.c:134
+#: src/load_plugins.c:175 src/load_plugins.c:183 src/load_plugins.c:190
+#: src/load_plugins.c:196
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "fejl i %s, linje %d under indlæsning af udvidelsesmodulet »%s«"
+
+#: src/load_plugins.c:92
+#, c-format
+msgid "%s%s: %s"
+msgstr "%s%s: %s"
+
+#: src/load_plugins.c:130
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s skal være ejet af uid %d"
+
+# engelsk fejl be dobbelt?
+#: src/load_plugins.c:136
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "%s må kun være skrivbar for ejeren"
+
+#: src/load_plugins.c:177
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "kan ikke indlæse %s: %s"
+
+#: src/load_plugins.c:185
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "kan ikke finde symbol »%s« i %s"
+
+#: src/load_plugins.c:192
+#, c-format
+msgid "unknown policy type %d found in %s"
+msgstr "ukendt politiktype %d fundet i %s"
+
+#: src/load_plugins.c:198
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "inkompatibelt udvidelsesmodul for hovedversion %d (forventede %d) fundet i %s"
+
+#: src/load_plugins.c:207
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "ignorerer politikudvidelsesmodul »%s« i %s, linje %d"
+
+#: src/load_plugins.c:209
+msgid "only a single policy plugin may be specified"
+msgstr "kun et udvidelsesmodul for politik må være angivet"
+
+#: src/load_plugins.c:212
+#, c-format
+msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+msgstr "ignorerer duplikat politikudvidelsesmodul »%s« i %s, linje %d"
+
+#: src/load_plugins.c:231
+#, c-format
+msgid "ignoring duplicate I/O plugin \"%s\" in %s, line %d"
+msgstr "ignorerer duplikat I/O-udvidelsesmodul »%s« i %s, linje %d"
+
+#: src/load_plugins.c:347
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "politikudvidelsesmodulet %s inkluderer ikke en metode for check_policy"
+
+#: src/net_ifs.c:180 src/net_ifs.c:197 src/net_ifs.c:342 src/sudo.c:470
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "intern fejl, %s-overløb"
+
+#: src/parse_args.c:224
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "ugyldigt miljøvariabelnavn: %s"
+
+#: src/parse_args.c:320
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "argumentet for -C skal være et tal større end eller lig 3"
+
+#: src/parse_args.c:505
+msgid "you may not specify both the `-i' and `-s' options"
+msgstr "du kan ikke samtidig angive tilvalgene »-i« og »-s«"
+
+#: src/parse_args.c:509
+msgid "you may not specify both the `-i' and `-E' options"
+msgstr "du kan ikke samtidig angive tilvalgende »-i« og »-E«"
+
+#: src/parse_args.c:519
+msgid "the `-E' option is not valid in edit mode"
+msgstr "tilvalget »-E« er ikke gyldigt i redigeringstilstand"
+
+#: src/parse_args.c:521
+msgid "you may not specify environment variables in edit mode"
+msgstr "du må ikke angive miljøvariabler i redigeringstilstand"
+
+#: src/parse_args.c:529
+msgid "the `-U' option may only be used with the `-l' option"
+msgstr "tilvalget »-U« må kun bruges med tilvalget »-l«"
+
+#: src/parse_args.c:533
+msgid "the `-A' and `-S' options may not be used together"
+msgstr "tilvalgene »-A« og »-S« må ikke bruges sammen"
+
+#: src/parse_args.c:609
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit er ikke understøttet på denne platform"
+
+#: src/parse_args.c:682
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Kun et af tilvalgene -e, -h, -i, -K, -l, -s, -v eller -V må angives"
+
+#: src/parse_args.c:696
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - rediger filer som en anden bruger\n"
+"\n"
+
+#: src/parse_args.c:698
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - udfør en kommando som en anden bruger\n"
+"\n"
+
+#: src/parse_args.c:703
+#, c-format
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Tilvalg:\n"
+
+#: src/parse_args.c:705
+msgid "use a helper program for password prompting"
+msgstr "brug et hjælpeprogram for indhentelse af adgangskode"
+
+#: src/parse_args.c:708
+msgid "use specified BSD authentication type"
+msgstr "brug angivet BSD-godkendelsestype"
+
+#: src/parse_args.c:711
+msgid "run command in the background"
+msgstr "kør kommando i baggrunden"
+
+#: src/parse_args.c:713
+msgid "close all file descriptors >= num"
+msgstr "luk alle filbeskrivelser >= num"
+
+#: src/parse_args.c:716
+msgid "run command with the specified BSD login class"
+msgstr "kør kommando med angivet BSD-logindklasse"
+
+#: src/parse_args.c:719
+msgid "preserve user environment when running command"
+msgstr "bevar brugermiljø når kommando udføres"
+
+#: src/parse_args.c:721
+msgid "preserve specific environment variables"
+msgstr "bevar specifikke miljøvariabler"
+
+#: src/parse_args.c:723
+msgid "edit files instead of running a command"
+msgstr "rediger filer i stedet for at køre en kommando"
+
+#: src/parse_args.c:725
+msgid "run command as the specified group name or ID"
+msgstr "udfør kommando som det angivne gruppenavn eller ID"
+
+#: src/parse_args.c:727
+msgid "set HOME variable to target user's home dir"
+msgstr "angiv HOME-variabel til målbrugers hjemmemappe"
+
+#: src/parse_args.c:729
+msgid "display help message and exit"
+msgstr "vis hjælpetekst og afslut"
+
+#: src/parse_args.c:731
+msgid "run command on host (if supported by plugin)"
+msgstr "kør kommando på vært (hvis understøttet af udvidelsesmodul)"
+
+#: src/parse_args.c:733
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "kør en logindskal som målbrugeren; en kommando kan også angives"
+
+#: src/parse_args.c:735
+msgid "remove timestamp file completely"
+msgstr "fjern tidsstempelfil fuldstændig"
+
+#: src/parse_args.c:737
+msgid "invalidate timestamp file"
+msgstr "ugyldiggør tidsstempelfil"
+
+#: src/parse_args.c:739
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "vis brugers privilegier eller kontroller en specifik kommando; brug to gange for længere format"
+
+#: src/parse_args.c:741
+msgid "non-interactive mode, no prompts are used"
+msgstr "ikkeinteraktiv tilstand, vil ikke spørge bruger"
+
+#: src/parse_args.c:743
+msgid "preserve group vector instead of setting to target's"
+msgstr "bevar gruppevektor i stedet for at sætte til målets"
+
+#: src/parse_args.c:745
+msgid "use the specified password prompt"
+msgstr "brug angivet logind for adgangskode"
+
+#: src/parse_args.c:748
+msgid "create SELinux security context with specified role"
+msgstr "opret SELinux-sikkerhedskontekt med angivet rolle"
+
+#: src/parse_args.c:751
+msgid "read password from standard input"
+msgstr "læs adgangskode fra standardinddata"
+
+#: src/parse_args.c:753
+msgid "run shell as the target user; a command may also be specified"
+msgstr "kør skal som målbruger; en kommando kan også specificeres"
+
+#: src/parse_args.c:756
+msgid "create SELinux security context with specified type"
+msgstr "opret SELinux-sikkerhedskontekt med angivet type"
+
+#: src/parse_args.c:759
+msgid "terminate command after the specified time limit"
+msgstr "afslut kommando efter den angivne tidsbegrænsning"
+
+#: src/parse_args.c:761
+msgid "in list mode, display privileges for user"
+msgstr "i vis-tilstand, vis privilegier for bruger"
+
+#: src/parse_args.c:763
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "kør kommando (eller rediger fil) som angivet brugernavn eller ID"
+
+#: src/parse_args.c:765
+msgid "display version information and exit"
+msgstr "vis versionsinformation og afslut"
+
+#: src/parse_args.c:767
+msgid "update user's timestamp without running a command"
+msgstr "opdater brugers tidsstempel uden at køre en kommando"
+
+#: src/parse_args.c:769
+msgid "stop processing command line arguments"
+msgstr "stop behandling af parametre for kommandolinjen"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "kan ikke åbne overvågningssystem"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "kan ikke sende overvågningsbesked"
+
+#: src/selinux.c:121
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "kan ikke fgetfilecon %s"
+
+#: src/selinux.c:126
+#, c-format
+msgid "%s changed labels"
+msgstr "%s ændrede etiketter"
+
+#: src/selinux.c:131
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "kan ikke gendanne kontekst for %s"
+
+#: src/selinux.c:172
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "kan ikke åbne %s, giver ikke ny etiket til tty"
+
+#: src/selinux.c:176 src/selinux.c:217 src/selinux.c:234
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s er ikke en tegnenhed, giver ikke ny etiket til tty"
+
+#: src/selinux.c:185
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "kan ikke indhente aktuel tty-kontekst, giver ikke ny etiket til tty"
+
+#: src/selinux.c:192
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "ukendt sikkerhedsklasse »chr_file«, giver ikke ny etiket til tty"
+
+#: src/selinux.c:197
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "kan ikke indhente ny tty-kontekst, giver ikke nyt etiket til tty"
+
+#: src/selinux.c:204
+msgid "unable to set new tty context"
+msgstr "kan ikke angive ny tty-kontekst"
+
+#: src/selinux.c:278
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "du skal angive en rolle for type %s"
+
+#: src/selinux.c:284
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "kan ikke indhente standardtype for rolle %s"
+
+#: src/selinux.c:302
+#, c-format
+msgid "failed to set new role %s"
+msgstr "kunne ikke angive ny rolle %s"
+
+#: src/selinux.c:306
+#, c-format
+msgid "failed to set new type %s"
+msgstr "kunne ikke angive ny type %s"
+
+#: src/selinux.c:318
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s er ikke en gyldig kontekst"
+
+#: src/selinux.c:353
+msgid "failed to get old_context"
+msgstr "kunne ikke indhente gammel_kontekst (old_context)"
+
+#: src/selinux.c:359
+msgid "unable to determine enforcing mode."
+msgstr "kan ikke bestemme tilstanden gennemtving (enforcing)."
+
+#: src/selinux.c:376
+#, c-format
+msgid "unable to set tty context to %s"
+msgstr "kan ikke angive tty-kontekst for %s"
+
+#: src/selinux.c:415
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "kan ikke angive kørselskontekt til %s"
+
+# engelsk: mangler vist lidt info her tast eller nøgle. mon ikke det er nøgle
+#: src/selinux.c:422
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "kan ikke angive nøgleoprettelseskontekst til %s"
+
+#: src/sesh.c:77
+msgid "requires at least one argument"
+msgstr "kræver mindst et argument"
+
+# eller antal?
+#: src/sesh.c:106
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "ugyldigt filbeskrivelsesnummer: %s"
+
+#: src/sesh.c:120
+#, c-format
+msgid "unable to run %s as a login shell"
+msgstr "kan ikke køre %s som en indlogningsskal"
+
+#: src/signal.c:88
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "kan ikke gemme håndtering for signal %d"
+
+#: src/solaris.c:81
+msgid "resource control limit has been reached"
+msgstr "grænse for ressourcekontrol er nået"
+
+#: src/solaris.c:84
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "bruger »%s« er ikke medlem af projektet »%s«"
+
+#: src/solaris.c:88
+msgid "the invoking task is final"
+msgstr "start af opgave er færdig"
+
+#: src/solaris.c:91
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "kunne ikke slutte til projekt »%s«"
+
+#: src/solaris.c:96
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "ingen ressourcekø som accepterer standardbindinger findes for projekt »%s«"
+
+#: src/solaris.c:100
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "angivet ressourcekø findes ikke for projekt »%s«"
+
+#: src/solaris.c:104
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "kunne ikke binde til standardressourcekø for projekt »%s«"
+
+#: src/solaris.c:110
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "setproject fejlede for projekt »%s«"
+
+#: src/solaris.c:112
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "advarsel, ressourcekontroltildeling fejlede for projekt »%s«"
+
+#: src/sudo.c:201
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo version %s\n"
+
+#: src/sudo.c:203
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Konfigurationsindstillinger: %s\n"
+
+#: src/sudo.c:211
+msgid "fatal error, unable to load plugins"
+msgstr "fatal fejl, kan ikke indlæse udvidelsesmoduler"
+
+#: src/sudo.c:219
+msgid "unable to initialize policy plugin"
+msgstr "kan ikke initialisere udvidelsesmodul for politik"
+
+#: src/sudo.c:263
+msgid "plugin did not return a command to execute"
+msgstr "udvidelsesmodul returnerede ikke en kommando til afvikling"
+
+#: src/sudo.c:279
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "fejl under initialisering af I/O-udvidelsesmodulet %s"
+
+#: src/sudo.c:302
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "uventet sudo-tilstand 0x%x"
+
+#: src/sudo.c:535
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "du findes ikke i %s-databasen"
+
+#: src/sudo.c:592
+msgid "unable to determine tty"
+msgstr "kan ikke bestemme tty"
+
+#: src/sudo.c:880
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s skal være ejet af uid %d og have setuid bit angivet"
+
+#: src/sudo.c:883
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "effektiv uid er ikke %d, er %s på et filsystem med indstillingen »nosuid« angivet eller et NFS-filsytsem uden administratorprivilegier (root)?"
+
+#: src/sudo.c:889
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "effektiv uid er ikke %d, er sudo installeret setuid root?"
+
+#: src/sudo.c:942
+msgid "unable to set supplementary group IDs"
+msgstr "kan ikke angive supplerende gruppe-id'er"
+
+#: src/sudo.c:949
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "kan ikke angive effektiv gid til runas gid %u"
+
+#: src/sudo.c:955
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "kan ikke angive gid til runas gid %u"
+
+#: src/sudo.c:1012
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "uventet underbetingelse for terminering: %d"
+
+#: src/sudo.c:1158
+#, c-format
+msgid "policy plugin %s is missing the `check_policy' method"
+msgstr "politikudvidelsesmodulet %s mangler i metoden »check_policy«"
+
+#: src/sudo.c:1176
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "politikudvidelsesmodul %s understøter ikke listning af privilegier"
+
+#: src/sudo.c:1193
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "politikudvidelsesmodul %s understøtter ikke tilvalget -v"
+
+#: src/sudo.c:1208
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "politikudvidelsesmodul %s understøtter ikke tilvalget -k/-K"
+
+#: src/sudo_edit.c:219
+msgid "no writable temporary directory found"
+msgstr "ingen skrivbar midlertidig mappe fundet"
+
+#: src/sudo_edit.c:286 src/sudo_edit.c:375
+msgid "unable to restore current working directory"
+msgstr "kan ikke gendanne nuværende arbejdsmappe"
+
+#: src/sudo_edit.c:592 src/sudo_edit.c:704
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: ikke en regulær fil"
+
+#: src/sudo_edit.c:599
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: redigering af symbolske henvisninger er ikke tilladt"
+
+#: src/sudo_edit.c:602
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: redigering af filer i en skrivbar mappe er ikke tilladt"
+
+#: src/sudo_edit.c:635 src/sudo_edit.c:742
+#, c-format
+msgid "%s: short write"
+msgstr "%s: kort skrivning"
+
+#: src/sudo_edit.c:705
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s tilbage uændrede"
+
+#: src/sudo_edit.c:718 src/sudo_edit.c:903
+#, c-format
+msgid "%s unchanged"
+msgstr "%s uændrede"
+
+#: src/sudo_edit.c:731 src/sudo_edit.c:753
+#, c-format
+msgid "unable to write to %s"
+msgstr "kan ikke skrive til %s"
+
+#: src/sudo_edit.c:732 src/sudo_edit.c:751 src/sudo_edit.c:754
+#: src/sudo_edit.c:928 src/sudo_edit.c:932
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "indhold fra redigeringssession tilbage i %s"
+
+#: src/sudo_edit.c:750
+msgid "unable to read temporary file"
+msgstr "kan ikke læse midlertidig fil"
+
+#: src/sudo_edit.c:833
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: intern fejl: forkert antal stier"
+
+#: src/sudo_edit.c:835
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: kan ikke oprette midlertidige filer"
+
+#: src/sudo_edit.c:837 src/sudo_edit.c:935
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: ukendt fejl %d"
+
+#: src/sudo_edit.c:927
+msgid "unable to copy temporary files back to their original location"
+msgstr "kan ikke kopiere midlertidige filer tilbage til deres originale placering"
+
+#: src/sudo_edit.c:931
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "kan ikke kopiere nogle af de midlertidige filer tilbage til deres originale placering"
+
+#: src/sudo_edit.c:976
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "kan ikke ændre uid til root (%u)"
+
+#: src/sudo_edit.c:993
+msgid "plugin error: missing file list for sudoedit"
+msgstr "fejl i udvidelsesmodul: mangler filliste for sudoedit"
+
+#: src/sudo_edit.c:1034 src/sudo_edit.c:1047
+msgid "unable to read the clock"
+msgstr "kan ikke læse uret"
+
+#: src/tgetpass.c:101
+msgid "timed out reading password"
+msgstr "fik tidsudløb under forsøg på at læse adgangskoden"
+
+#: src/tgetpass.c:104
+msgid "no password was provided"
+msgstr "ingen adgangskode blev angivet"
+
+#: src/tgetpass.c:107
+msgid "unable to read password"
+msgstr "kan ikke læse adgangskoden"
+
+#: src/tgetpass.c:141
+msgid "no tty present and no askpass program specified"
+msgstr "ingen tty til stede og intet askpass-program angivet"
+
+#: src/tgetpass.c:150
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "intet askpass-program angivet, forsøg at angive SUDO_ASKPASS"
+
+#: src/tgetpass.c:307
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "kan ikke angive gid til %u"
+
+#: src/tgetpass.c:311
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "kan ikke angive uid til %u"
+
+#: src/tgetpass.c:316
+#, c-format
+msgid "unable to run %s"
+msgstr "kan ikke køre %s"
+
+#: src/utmp.c:271
+msgid "unable to save stdin"
+msgstr "kan ikke gemme til stdin"
+
+#: src/utmp.c:273
+msgid "unable to dup2 stdin"
+msgstr "kan ikke dup2 stdin"
+
+#: src/utmp.c:276
+msgid "unable to restore stdin"
+msgstr "kan ikke gendanne stdin"
+
+#~ msgid "unable to get group vector"
+#~ msgstr "kan ikke indhente gruppevektor"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "ukendt uid %u: hvem er du?"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "fejl under læsning fra signaldatakanal"
+
+#~ msgid "error reading from pipe"
+#~ msgstr "fejl ved læsning fra datakanal"
diff --git a/po/de.mo b/po/de.mo
new file mode 100644
index 0000000..611b3d2
--- /dev/null
+++ b/po/de.mo
Binary files differ
diff --git a/po/de.po b/po/de.po
new file mode 100644
index 0000000..b2edc36
--- /dev/null
+++ b/po/de.po
@@ -0,0 +1,1212 @@
+# German translation for sudo.
+# This file is distributed under the same license as the sudo package.
+# Jakob Kramer <jakob.kramer@gmx.de>, 2012, 2013-2014.
+# Mario Blättermann <mario.blaettermann@gmail.com>, 2012, 2014-2017, 2019-2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.14b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-06-07 13:27-0600\n"
+"PO-Revision-Date: 2023-06-08 20:27+0200\n"
+"Last-Translator: Mario Blättermann <mario.blaettermann@gmail.com>\n"
+"Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Lokalize 23.04.1\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "Benutzerdatenbank konnte nicht geöffnet werden"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "Es konnte nicht zur Registrierungsdatenbank »%s« von %s gewechselt werden"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "Registrierungsdatenbank konnte nicht wiederhergestellt werden"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:78 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:171 src/exec_monitor.c:418
+#: src/exec_monitor.c:424 src/exec_monitor.c:432 src/exec_monitor.c:440
+#: src/exec_monitor.c:447 src/exec_monitor.c:454 src/exec_monitor.c:461
+#: src/exec_monitor.c:468 src/exec_monitor.c:475 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:744 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1096
+#: src/exec_ptrace.c:1271 src/exec_ptrace.c:1624 src/exec_ptrace.c:1651
+#: src/exec_ptrace.c:1841 src/exec_pty.c:581 src/exec_pty.c:765
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:193 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:240
+#: src/sesh.c:246 src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:644
+#: src/sudo.c:709 src/sudo.c:719 src/sudo.c:746 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:787 src/sudo.c:805 src/sudo.c:846 src/sudo.c:855 src/sudo.c:865
+#: src/sudo.c:898 src/sudo.c:1127 src/sudo.c:1148 src/sudo.c:1441
+#: src/sudo.c:1610 src/sudo.c:1837 src/sudo.c:2171 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:430 src/sudo_edit.c:439
+#: src/sudo_edit.c:540 src/sudo_edit.c:547 src/sudo_edit.c:692
+#: src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:79 src/exec_intercept.c:111 src/exec_intercept.c:350
+#: src/exec_intercept.c:525 src/exec_intercept.c:589 src/exec_intercept.c:713
+#: src/exec_intercept.c:837 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:418 src/exec_monitor.c:424
+#: src/exec_monitor.c:432 src/exec_monitor.c:440 src/exec_monitor.c:447
+#: src/exec_monitor.c:454 src/exec_monitor.c:461 src/exec_monitor.c:468
+#: src/exec_monitor.c:475 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1651 src/exec_ptrace.c:1842 src/exec_pty.c:581
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:228 src/sudo.c:644 src/sudo.c:898 src/sudo.c:1127
+#: src/sudo.c:1148 src/sudo.c:1441 src/sudo.c:1610 src/sudo.c:1837
+#: src/sudo.c:2171 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:430
+#: src/sudo_edit.c:439 src/sudo_edit.c:540 src/sudo_edit.c:547
+#: src/sudo_edit.c:692 src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "Speicher konnte nicht zugewiesen werden"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "stat konnte nicht auf %.*s angewendet werden"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s existiert, aber ist kein Verzeichnis (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:664
+#: lib/util/sudo_conf.c:683 lib/util/sudo_conf.c:710 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:495 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "%s konnte nicht geöffnet werden"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "Verzeichnis %.*s konnte nicht erstellt werden"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "%.*s konnte nicht geöffnet werden"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "regulärer Ausdruck ist zu groß"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Unbekanntes Signal"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "ungültiger Wert"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "Wert zu groß"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "Wert zu klein"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "Ungültiger Pfad-Wert »%s« in %s, Zeile %u"
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "Ungültiger Wert für %s »%s« in %s, Zeile %u"
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "Nicht unterstützte Gruppenquelle »%s« in %s, Zeile %u"
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "Ungültige Maximalzahl an Gruppen »%s« in %s, Zeile %u"
+
+#: lib/util/sudo_conf.c:686
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s ist keine reguläre Datei"
+
+#: lib/util/sudo_conf.c:689 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s gehört Benutzer mit UID %u, sollte allerdings %u gehören"
+
+#: lib/util/sudo_conf.c:693
+#, c-format
+msgid "%s is world writable"
+msgstr "%s kann von allen verändert werden"
+
+#: lib/util/sudo_conf.c:696
+#, c-format
+msgid "%s is group writable"
+msgstr "%s kann von der Gruppe verändert werden"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "AppArmor-Zugriffskontrolle konnte nicht bestimmt werden."
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "AppArmor-Profil konnte nicht zu %s geändert werden"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: %s auf null Byte kürzen? (y/n) [n] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "%s wird nicht überschrieben"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "Aus %s konnte nicht gelesen werden"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "%s konnte nicht beschrieben werden"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "stat konnte nicht auf %s angewendet werden"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: Keine reguläre Datei"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: falscher Dateimodus: 0%o"
+
+#: src/edit_open.c:333
+msgid "unable to restore current working directory"
+msgstr "Aktueller Arbeitsordner konnte nicht wiederhergestellt werden"
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "Privilegien konnten nicht gesetzt werden"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "Privilegien konnten nicht eingeschränkt werden"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "Unbekannte Anmeldungsklasse %s"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "Benutzerkontext konnte nicht gesetzt werden"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "Prozesspriorität konnte nicht gesetzt werden"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "Wurzelverzeichnis konnte nicht zu %s geändert werden"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "Es konnte nicht zu »runas«-GID gewechselt werden (%u, %u)"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "In Verzeichnis »%s« konnte nicht gewechselt werden"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "beginnend mit %s"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:552 src/exec_monitor.c:554
+#: src/exec_pty.c:1122 src/exec_pty.c:1124 src/signal.c:144 src/signal.c:151
+#: src/signal.c:165 src/suspend_parent.c:143
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "Handler für Signal %d konnte nicht gesetzt werden"
+
+#: src/exec.c:424
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "Abfangmodus wird mit SELinux RBAC auf diesem System nicht unterstützt"
+
+#: src/exec.c:429
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "Unterbefehle können mit SELinux RBAC auf diesem System nicht protokolliert werden"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "PRIV_PROC_EXEC konnte nicht von PRIV_LIMIT entfernt werden"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:163 src/exec_iolog.c:173
+#: src/exec_iolog.c:218 src/exec_iolog.c:225 src/exec_iolog.c:252
+#: src/exec_monitor.c:426 src/exec_monitor.c:434 src/exec_monitor.c:442
+#: src/exec_monitor.c:449 src/exec_monitor.c:456 src/exec_monitor.c:463
+#: src/exec_monitor.c:470 src/exec_monitor.c:477 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:457 src/exec_pty.c:432
+#: src/exec_pty.c:537 src/exec_pty.c:587 src/exec_pty.c:965 src/exec_pty.c:974
+#: src/exec_pty.c:981 src/exec_pty.c:988 src/exec_pty.c:995
+#: src/exec_pty.c:1002 src/exec_pty.c:1009 src/exec_pty.c:1016
+#: src/exec_pty.c:1023 src/exec_pty.c:1030 src/exec_pty.c:1037
+#: src/exec_pty.c:1044
+msgid "unable to add event to queue"
+msgstr "Ereignis konnte nicht zur Warteschlange hinzugefügt werden"
+
+#: src/exec_intercept.c:323 src/sudo.c:1033
+msgid "command not set by the security policy"
+msgstr "Befehl wurde durch Sicherheitsregelwerk nicht gesetzt"
+
+#: src/exec_intercept.c:401 src/exec_intercept.c:441 src/sudo.c:1253
+#: src/sudo.c:1298 src/sudo.c:1342
+msgid "command rejected by policy"
+msgstr "Befehl wurde durch Regelwerk abgewiesen"
+
+#: src/exec_intercept.c:512 src/sudo.c:1940
+msgid "approval plugin error"
+msgstr "Genehmigungs-Plugin-Fehler"
+
+#: src/exec_intercept.c:537 src/sudo.c:1258 src/sudo.c:1303 src/sudo.c:1347
+#: src/sudo.c:1421
+msgid "policy plugin error"
+msgstr "Regelwerk-Plugin-Fehler"
+
+#: src/exec_intercept.c:566
+msgid "invalid PolicyCheckRequest"
+msgstr "ungültige PolicyCheckRequest"
+
+#: src/exec_intercept.c:709
+#, c-format
+msgid "client request too large: %zu"
+msgstr "Client-Anfrage ist zu groß: %zu"
+
+#: src/exec_intercept.c:751
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "%s, Größe %zu, kann nicht entpackt werden"
+
+#: src/exec_intercept.c:799
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "unerwarteter Wert %d für type_case in %s aus %s"
+
+#: src/exec_intercept.c:825
+#, c-format
+msgid "server message too large: %zu"
+msgstr "Server-Meldung ist zu groß: %zu"
+
+#: src/exec_iolog.c:321 src/exec_iolog.c:361 src/exec_iolog.c:401
+#: src/exec_iolog.c:452 src/exec_iolog.c:503
+msgid "I/O plugin error"
+msgstr "E/A-Pluginfehler"
+
+#: src/exec_iolog.c:325 src/exec_iolog.c:365 src/exec_iolog.c:405
+#: src/exec_iolog.c:456 src/exec_iolog.c:507
+msgid "command rejected by I/O plugin"
+msgstr "Befehl wurde vom E/A-Plugin abgewiesen"
+
+#: src/exec_iolog.c:555
+msgid "error logging suspend"
+msgstr "Fehler bei der Aussetzung der Protokollierung"
+
+#: src/exec_iolog.c:590
+msgid "error changing window size"
+msgstr "Fehler beim Ändern der Fenstergröße"
+
+#: src/exec_monitor.c:328
+msgid "error reading from socketpair"
+msgstr "Fehler beim Lesen des Socket-Paars"
+
+#: src/exec_monitor.c:340
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "Unerwarteter Antworttyp auf Rückmeldungskanal: %d"
+
+#: src/exec_monitor.c:566
+msgid "unable to set controlling tty"
+msgstr "Kontrollierendes TTY konnte nicht gesetzt werden"
+
+#: src/exec_monitor.c:574 src/exec_nopty.c:504 src/exec_nopty.c:514
+#: src/exec_nopty.c:524 src/exec_nopty.c:560 src/exec_pty.c:1195
+#: src/exec_pty.c:1222 src/exec_pty.c:1242 src/exec_pty.c:1262
+#: src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr "Weiterleitung konnte nicht erstellt werden"
+
+#: src/exec_monitor.c:584
+msgid "unable to receive message from parent"
+msgstr "Die Nachricht konnte nicht empfangen werden"
+
+#: src/exec_monitor.c:600 src/exec_nopty.c:603 src/exec_pty.c:1303
+#: src/sudo_edit.c:361 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr "Es konnte nicht geforkt werden"
+
+#: src/exec_monitor.c:604 src/exec_monitor.c:700 src/exec_nopty.c:708
+msgid "unable to restore tty label"
+msgstr "TTY-Kennzeichnung konnte nicht wiederhergestellt werden"
+
+#: src/exec_monitor.c:615 src/sesh.c:217 src/sudo.c:1204
+#, c-format
+msgid "unable to execute %s"
+msgstr "%s konnte nicht ausgeführt werden"
+
+#: src/exec_nopty.c:554 src/exec_pty.c:1131
+msgid "policy plugin failed session initialization"
+msgstr "Regelwerks-Plugin konnte Sitzung nicht initialisieren"
+
+#: src/exec_nopty.c:569 src/exec_pty.c:1100 src/exec_pty.c:1109
+msgid "unable to create sockets"
+msgstr "Sockets konnten nicht hergestellt werden"
+
+#: src/exec_nopty.c:696 src/exec_pty.c:1406
+msgid "error in event loop"
+msgstr "Fehler in Ereignisschleife"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:852 src/sudo.c:488
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "Interner Fehler: %s-Überlauf"
+
+#: src/exec_ptrace.c:1080 src/exec_ptrace.c:1105 src/exec_ptrace.c:1925
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "Register konnten für Prozess %d nicht gesetzt werden"
+
+#: src/exec_ptrace.c:1100 src/exec_ptrace.c:1275 src/exec_ptrace.c:1628
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "Prozess %d wurde unerwartet beendet"
+
+#: src/exec_ptrace.c:1209
+msgid "unable to set seccomp filter"
+msgstr "seccomp-Filter konnte nicht gesetzt werden"
+
+#: src/exec_ptrace.c:1406
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "Interpreter-Argument: »%s« wurde erwartet, »%s« erhalten"
+
+#: src/exec_ptrace.c:1505
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "Pfadname passt nicht, »%s« wurde erwartet, »%s« erhalten"
+
+#: src/exec_ptrace.c:1514 src/exec_ptrace.c:1521 src/exec_ptrace.c:1545
+#: src/exec_ptrace.c:1553 src/exec_ptrace.c:1559 src/exec_ptrace.c:1565
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "%s[%d] passt nicht, »%s« wurde erwartet, »%s« erhalten"
+
+#: src/exec_ptrace.c:1632
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "Prozess %d hat den unerwarteten Status 0x%x"
+
+#: src/exec_ptrace.c:1723
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "Ereignismeldung für Prozess %d konnte nicht erhalten werden"
+
+#: src/exec_ptrace.c:1730
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "Register konnten für Prozess %d nicht erhalten werden"
+
+#: src/exec_pty.c:84
+msgid "unable to allocate pty"
+msgstr "PTY konnte nicht vergeben werden"
+
+#: src/exec_pty.c:131 src/exec_pty.c:284 src/tgetpass.c:251
+msgid "unable to restore terminal settings"
+msgstr "Terminaleinstellungen konnten nicht wiederhergestellt werden"
+
+#: src/exec_pty.c:243
+msgid "unable to set handler for SIGCONT"
+msgstr "Handler für SIGCONT konnte nicht gesetzt werden"
+
+#: src/exec_pty.c:293
+#, c-format
+msgid "unable to set handler for SIG%s"
+msgstr "Handler für SIG%s konnte nicht gesetzt werden"
+
+#: src/exec_pty.c:317
+#, c-format
+msgid "unable to restore handler for SIG%s"
+msgstr "Handler für SIG%s konnte nicht wiederhergestellt werden"
+
+#: src/exec_pty.c:345
+msgid "unable to restore handler for SIGCONT"
+msgstr "Handler für SIGCONT konnte nicht wiederhergestellt werden"
+
+#: src/exec_pty.c:1353
+msgid "unable to send message to monitor process"
+msgstr "Die Nachricht konnte nicht an den überwachenden Prozess verschickt werden"
+
+#: src/load_plugins.c:75 src/load_plugins.c:222 src/load_plugins.c:232
+#: src/load_plugins.c:242 src/load_plugins.c:289
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "Fehler in %s, Zeile %d, während Plugin »%s« geladen wurde"
+
+#: src/load_plugins.c:186 src/load_plugins.c:257
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "Doppelt vorhandenes Plugin »%s« in %s, Zeile %d, wird ignoriert"
+
+#: src/load_plugins.c:224
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "»%s« konnte nicht geladen werden: %s"
+
+#: src/load_plugins.c:234
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "Symbol »%s« konnte in %s nicht gefunden werden"
+
+#: src/load_plugins.c:244
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "Inkompatible Hauptversion %d des Regelwerks (%d erwartet) wurde in %s gefunden"
+
+#: src/load_plugins.c:262
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "Regelwerks-Plugin »%s« in %s, Zeile %d, wird ignoriert"
+
+#: src/load_plugins.c:265
+msgid "only a single policy plugin may be specified"
+msgstr "Nur ein einziges Regelwerks-Plugin kann geladen werden"
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "Unbekannter Plugintyp %d wurde in %s gefunden"
+
+#: src/load_plugins.c:474
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "Das Regelwerks-Plugin %s enthält keine check_policy-Methode"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "Unzulässiger Name der Umgebungsvariable: %s"
+
+#: src/parse_args.c:319
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "Das Argument für -C muss eine Zahl größer oder gleich 3 sein"
+
+#: src/parse_args.c:556
+msgid "you may not specify both the -i and -s options"
+msgstr "Die Optionen -i und -s können nicht gemeinsam benutzt werden"
+
+#: src/parse_args.c:561
+msgid "you may not specify both the -i and -E options"
+msgstr "Die Optionen -i und -E können nicht gemeinsam benutzt werden"
+
+#: src/parse_args.c:571
+msgid "the -E option is not valid in edit mode"
+msgstr "Die Option -E ist im Bearbeiten-Modus ungültig"
+
+#: src/parse_args.c:574
+msgid "you may not specify environment variables in edit mode"
+msgstr "Im Bearbeiten-Modus können keine Umgebungsvariablen gesetzt werden"
+
+#: src/parse_args.c:584
+msgid "the -U option may only be used with the -l option"
+msgstr "Die Option -U kann nur zusammen mit -l benutzt werden"
+
+#: src/parse_args.c:588
+msgid "the -A and -S options may not be used together"
+msgstr "Die Optionen -A und -S können nicht gemeinsam benutzt werden"
+
+#: src/parse_args.c:686
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit ist auf dieser Plattform nicht verfügbar"
+
+#: src/parse_args.c:744
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Nur eine der Optionen -e, -h, -i, -K, -l, -s, -v oder -V darf angegeben werden"
+
+#: src/parse_args.c:757
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "Nur eine der Optionen -K, -k oder -N darf angegeben werden"
+
+#: src/parse_args.c:778
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - Dateien als anderer Benutzer verändern\n"
+"\n"
+
+#: src/parse_args.c:780
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - Einen Befehl als anderer Benutzer ausführen\n"
+"\n"
+
+#: src/parse_args.c:785
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Optionen:\n"
+
+#: src/parse_args.c:787
+msgid "use a helper program for password prompting"
+msgstr "Hilfsprogramm zum Eingeben des Passworts verwenden"
+
+#: src/parse_args.c:790
+msgid "use specified BSD authentication type"
+msgstr "Angegebenen BSD-Legitimierungstypen verwenden"
+
+#: src/parse_args.c:794
+msgid "run command in the background"
+msgstr "Befehl im Hintergrund ausführen"
+
+#: src/parse_args.c:797
+msgid "ring bell when prompting"
+msgstr "Bei Eingabeaufforderung Systemklang abspielen"
+
+#: src/parse_args.c:799
+msgid "close all file descriptors >= num"
+msgstr "Alle Dateideskriptoren >= num schließen"
+
+#: src/parse_args.c:802
+msgid "run command with the specified BSD login class"
+msgstr "Befehl unter angegebener Login-Klasse ausführen"
+
+#: src/parse_args.c:805
+msgid "change the working directory before running command"
+msgstr "Arbeitsverzeichnis vor der Ausführung des Befehls wechseln"
+
+#: src/parse_args.c:808
+msgid "preserve user environment when running command"
+msgstr "Benutzerumgebung beim Starten des Befehls beibehalten"
+
+#: src/parse_args.c:810
+msgid "preserve specific environment variables"
+msgstr "Spezifische Umgebungsvariablen beibehalten"
+
+#: src/parse_args.c:812
+msgid "edit files instead of running a command"
+msgstr "Dateien bearbeiten, statt einen Befehl auszuführen"
+
+#: src/parse_args.c:815
+msgid "run command as the specified group name or ID"
+msgstr "Befehl unter angegebenem Gruppennamen oder Gruppen-ID ausführen"
+
+#: src/parse_args.c:818
+msgid "set HOME variable to target user's home dir"
+msgstr "HOME-Variable als Home-Verzeichnis des Zielbenutzers setzen"
+
+#: src/parse_args.c:821
+msgid "display help message and exit"
+msgstr "Hilfe ausgeben und beenden"
+
+#: src/parse_args.c:823
+msgid "run command on host (if supported by plugin)"
+msgstr "Befehl auf entferntem System ausführen (falls vom Plugin unterstützt)"
+
+#: src/parse_args.c:826
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "Anmeldeshell als Zielbenutzer starten; es kann auch ein Befehl angegeben werden"
+
+#: src/parse_args.c:828
+msgid "remove timestamp file completely"
+msgstr "Zeitstempeldateien komplett entfernen"
+
+#: src/parse_args.c:831
+msgid "invalidate timestamp file"
+msgstr "Zeitstempeldatei ungültig machen"
+
+#: src/parse_args.c:834
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "Benutzerrechte aufzählen oder einen bestimmten Befehl testen; für ein längeres Format zweimal angeben"
+
+#: src/parse_args.c:837
+msgid "non-interactive mode, no prompts are used"
+msgstr "Nicht-interaktiver Modus, es werden keine Eingabeaufforderungen verwendet"
+
+#: src/parse_args.c:840
+msgid "preserve group vector instead of setting to target's"
+msgstr "Gruppen-Vektor beibehalten, statt auf den des Zielbenutzers zu setzen"
+
+#: src/parse_args.c:843
+msgid "use the specified password prompt"
+msgstr "Angegebene Passwort-Eingabeaufforderung benutzen"
+
+#: src/parse_args.c:845
+msgid "change the root directory before running command"
+msgstr "Wurzelverzeichnis vor der Ausführung des Befehls wechseln"
+
+#: src/parse_args.c:848
+msgid "create SELinux security context with specified role"
+msgstr "SELinux-Sicherheitskontext mit angegebener Funktion erstellen"
+
+#: src/parse_args.c:851
+msgid "read password from standard input"
+msgstr "Passwort von der Standardeingabe lesen"
+
+#: src/parse_args.c:854
+msgid "run shell as the target user; a command may also be specified"
+msgstr "Shell als Zielbenutzer ausführen; es kann auch ein Befehl angegeben werden"
+
+#: src/parse_args.c:858
+msgid "create SELinux security context with specified type"
+msgstr "SELinux-Sicherheitskontext mit angegebenem Typ erstellen"
+
+#: src/parse_args.c:861
+msgid "terminate command after the specified time limit"
+msgstr "Befehlausführung nach der angegebenen Zeitbegrenzung abbrechen"
+
+#: src/parse_args.c:864
+msgid "in list mode, display privileges for user"
+msgstr "im Aufzählungsmodus, Rechte des Benutzers anzeigen"
+
+#: src/parse_args.c:867
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "Befehl oder Datei unter angegebenem Benutzernamen oder Benutzer-ID ausführen bzw. ändern"
+
+#: src/parse_args.c:869
+msgid "display version information and exit"
+msgstr "Versionsinformation anzeigen und beenden"
+
+#: src/parse_args.c:872
+msgid "update user's timestamp without running a command"
+msgstr "Den Zeitstempel des Benutzers erneuern, ohne einen Befehl auszuführen"
+
+#: src/parse_args.c:875
+msgid "stop processing command line arguments"
+msgstr "Aufhören, die Befehlszeilenargumente zu verarbeiten"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "Das Audit-System konnte nicht geöffnet werden"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "Die Audit-Nachricht konnte nicht verschickt werden"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "»fgetfilecon« konnte nicht auf %s angewendet werden"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s änderte die Kennzeichnung"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "Der Kontext für %s konnte nicht wiederhergestellt werden"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "%s konnte nicht geöffnet werden, TTY wird nicht neu gekennzeichnet"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s ist kein zeichenorientiertes Gerät, TTY wird nicht neu gekennzeichnet."
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr ""
+"Aktueller TTY-Kontext konnte nicht festgestellt werden, TTY wird nicht neu\n"
+"gekennzeichnet."
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "Unbekannte Sicherheitsklasse »chr_file«, TTY wird nicht neu gekennzeichnet."
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr ""
+"Neuer TTY-Kontext konnte nicht festgestellt werden, TTY wird nicht neu\n"
+"gekennzeichnet."
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "Neuer TTY-Kontext konnte nicht festgestellt werden"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "Für den Typen %s muss eine Funktion angegeben werden"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "Standardtyp für Funktion %s konnte nicht ermittelt werden"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "»new_context« konnte nicht geholt werden"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "Neue Funktion %s konnte nicht festgelegt werden"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "Neuer Typ %s konnte nicht festgelegt werden"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s ist kein gültiger Kontext"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "»old_context« konnte nicht geholt werden"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "»Enforcing«-Modus konnte nicht bestimmt werden."
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "Ausführungskontext konnte nicht auf »%s« gesetzt werden"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "Kontext der Schüsselerstellung konnte nicht auf %s festgelegt werden."
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "Nur eine der Optionen -c oder -i darf angegeben werden"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "Unzulässige Dateideskriptornummer: %s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "Die Option -%c darf im Bearbeiten-Modus nicht verwendet werden."
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "Die Option -%c darf nur im Bearbeiten-Modus verwendet werden."
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: Bearbeiten symbolischer Links ist nicht erlaubt"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: Bearbeiten von Dateien in einem beschreibbaren Ordner ist nicht erlaubt"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "Bearbeitungssitzung wurden in %s gelassen"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "Gruppenliste konnte nicht geholt werden"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "Handler für Signal %d konnte nicht gespeichert werden"
+
+#: src/signal.c:101 src/suspend_parent.c:149
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "Handler für Signal %d konnte nicht wiederhergestellt werden"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "Limit der Ressourcenkontrolle wurde erreicht"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "Benutzer »%s« ist kein Mitglied des Projekts »%s«"
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "Der aufrufende Prozess ist fertig"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "Projekt »%s« konnte nicht beigetreten werden"
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "Für Projekt »%s« gibt es keinen Ressourcen-Pool, der die Standardanbindungen unterstützt."
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "Den angegebenen Ressourcen-Pool gibt es für das Projekt »%s« nicht"
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "Es konnte nicht zum Standard-Ressourcen-Pool für Projekt »%s« verbunden werden."
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "»setproject« schlug für Projekt »%s« fehl"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "Warnung: Ressourcenkontrolle von Projekt »%s« konnte nicht zugewiesen werden"
+
+#: src/sudo.c:214
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo-Version %s\n"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Optionen für »configure«: %s\n"
+
+#: src/sudo.c:224
+msgid "fatal error, unable to load plugins"
+msgstr "Schwerwiegender Fehler, Plugins konnten nicht geladen werden"
+
+#: src/sudo.c:270
+msgid "plugin did not return a command to execute"
+msgstr "Plugin gab keinen auszuführenden Befehl zurück"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "Unerwarteter sudo-Modus 0x%x"
+
+#: src/sudo.c:559
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "Sie sind in der %s-Datenbank nicht enthalten"
+
+#: src/sudo.c:616
+msgid "unable to determine tty"
+msgstr "TTY konnte nicht ermittelt werden"
+
+#: src/sudo.c:932
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "Der Schalter »no new privileges« ist gesetzt, welcher sudo daran hindert, als Root ausgeführt zu werden."
+
+#: src/sudo.c:934
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "Falls sudo in einem Container ausgeführt wird, könnte es nötig sein, die Containerkonfiguration anzupassen, um diesen Schalter zu deaktivieren."
+
+#: src/sudo.c:968
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s muss dem Benutzer mit UID %d gehören und das »setuid«-Bit gesetzt haben"
+
+#: src/sudo.c:971
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "Effektive UID ist nicht %d. Liegt %s auf einem Dateisystem mit gesetzter »nosuid«-Option oder auf einem NFS-Dateisystem ohne Root-Rechte?"
+
+#: src/sudo.c:977
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "Effektive UID ist nicht %d. Wurde sudo mit »setuid root« installiert?"
+
+#: src/sudo.c:993 src/tgetpass.c:332
+msgid "unable to set supplementary group IDs"
+msgstr "Zusätzliche Gruppenkennungen konnten nicht gesetzt werden"
+
+#: src/sudo.c:1000
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "Effektive GID konnte nicht auf »runas«-GID %u gesetzt werden"
+
+#: src/sudo.c:1006
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "GID konnte nicht auf »runas«-GID %u gesetzt werden"
+
+#: src/sudo.c:1037
+msgid "argv not set by the security policy"
+msgstr "argv wurde durch Sicherheitsregelwerk nicht gesetzt"
+
+#: src/sudo.c:1041
+msgid "envp not set by the security policy"
+msgstr "envp wurde durch Sicherheitsregelwerk nicht gesetzt"
+
+#: src/sudo.c:1063
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "Unerwartete Abbruchbedingung eines Unterprozesses: %d"
+
+#: src/sudo.c:1176
+msgid "unable to initialize policy plugin"
+msgstr "Regelwerks-Plugin konnte nicht initialisiert werden"
+
+#: src/sudo.c:1238
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "Dem Regelwerks-Plugin %s fehlt die »check_policy«-Methode"
+
+#: src/sudo.c:1284
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "Regelwerks-Plugin %s unterstützt das Auflisten von Privilegien nicht"
+
+#: src/sudo.c:1328
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "Regelwerks-Plugin %s unterstützt die Option -v nicht"
+
+#: src/sudo.c:1366
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "Regelwerks-Plugin %s unterstützt die Optionen -k und -K nicht"
+
+#: src/sudo.c:1495
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "E/A-Plugin %s konnte nicht initialisiert werden"
+
+#: src/sudo.c:1498
+msgid "error initializing I/O plugin"
+msgstr "E/A-Plugin konnte nicht initialisiert werden"
+
+#: src/sudo.c:1647
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "Audit-Plugin %s konnte nicht initialisiert werden"
+
+#: src/sudo.c:1726
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: Fehlerereignis%s%s konnte nicht protokolliert werden"
+
+#: src/sudo.c:1762
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: Ereignis%s%s konnte für das Protokoll nicht akzeptiert werden"
+
+#: src/sudo.c:1767 src/sudo.c:1805
+msgid "audit plugin error"
+msgstr "Audit-Pluginfehler"
+
+#: src/sudo.c:1800
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: Ereignis%s%s wurde vom Protokoll abgewiesen"
+
+#: src/sudo.c:1860
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "Genehmigungs-Plugin %s konnte nicht initialisiert werden"
+
+#: src/sudo.c:1930
+msgid "command rejected by approver"
+msgstr "Befehl wurde vom Genehmigenden abgewiesen"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "Kein beschreibbares temporäres Verzeichnis gefunden"
+
+#: src/sudo_edit.c:292
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s blieb unverändert"
+
+#: src/sudo_edit.c:305 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s unverändert"
+
+#: src/sudo_edit.c:482
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: interner Fehler: seltsame Anzahl an Pfaden"
+
+#: src/sudo_edit.c:484
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: Temporäre Dateien konnten nicht angelegt werden"
+
+#: src/sudo_edit.c:486 src/sudo_edit.c:606
+msgid "sesh: killed by a signal"
+msgstr "sesh: von einem Signal getötet"
+
+#: src/sudo_edit.c:488 src/sudo_edit.c:609
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: unbekannter Fehler %d"
+
+#: src/sudo_edit.c:599
+msgid "unable to copy temporary files back to their original location"
+msgstr "Temporäre Dateien konnten nicht an ihre ursprünglichen Orte zurück kopiert werden"
+
+#: src/sudo_edit.c:603
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "Einige der temporären Dateien konnten nicht an ihre ursprünglichen Orte zurück kopiert werden"
+
+#: src/sudo_edit.c:650
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "UID konnte nicht zu Root (%u) geändert werden"
+
+#: src/sudo_edit.c:664
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "Plugin-Fehler: ungültige Dateiliste für sudoedit"
+
+#: src/sudo_edit.c:685
+msgid "plugin error: missing file list for sudoedit"
+msgstr "Plugin-Fehler: Fehlende Dateiliste für sudoedit"
+
+#: src/sudo_edit.c:728 src/sudo_edit.c:743
+msgid "unable to read the clock"
+msgstr "Die Uhr konnte nicht gelesen werden"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "Intercept-Port ist nicht gesetzt"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "Zeitüberschreitung beim Lesen des Passworts"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "Es wurde kein Passwort angegeben"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "Passwort konnte nicht gelesen werden"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "Zum Lesen des Passworts ist ein Terminal erforderlich; verwenden Sie entweder die Option -S, um aus der Standardeingabe zu lesen oder richten Sie das Askpass-Hilfsprogramm ein"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "Kein »askpass«-Programm angegeben, es wird versucht, SUDO_ASKPASS zu setzen"
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "GID konnte nicht als %u festgelegt werden"
+
+#: src/tgetpass.c:337
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "UID konnte nicht als %u festgelegt werden"
+
+#: src/tgetpass.c:342
+#, c-format
+msgid "unable to run %s"
+msgstr "%s konnte nicht ausgeführt werden"
+
+#: src/utmp.c:283
+msgid "unable to save stdin"
+msgstr "Standardeingabe konnte nicht gespeichert werden"
+
+#: src/utmp.c:285
+msgid "unable to dup2 stdin"
+msgstr "dup2 konnte nicht auf die Standardeingabe angewendet werden"
+
+#: src/utmp.c:288
+msgid "unable to restore stdin"
+msgstr "Standardeingabe konnte nicht wiederhergestellt werden"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s muss Benutzer mit UID %d gehören"
+
+#~ msgid "%s must be only be writable by owner"
+#~ msgstr "%s darf nur vom Besitzer beschreibbar sein"
diff --git a/po/eo.mo b/po/eo.mo
new file mode 100644
index 0000000..f4efc79
--- /dev/null
+++ b/po/eo.mo
Binary files differ
diff --git a/po/eo.po b/po/eo.po
new file mode 100644
index 0000000..28df82c
--- /dev/null
+++ b/po/eo.po
@@ -0,0 +1,1203 @@
+# Esperanto translations for sudo package.
+# This file is distributed under the same license as the sudo package.
+# Keith Bowes <zooplah@gmail.com>, 2012, 2020-2023
+# Felipe Castro <fefcas@gmail.com>, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.14b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-06-07 13:27-0600\n"
+"PO-Revision-Date: 2023-06-11 19:33-0400\n"
+"Last-Translator: Keith Bowes <zooplah@gmail.com>\n"
+"Language-Team: Esperanto <translation-team-eo@lists.sourceforge.net>\n"
+"Language: eo\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 2.2.1\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "ne eblas malfermi la uzanto-datumbazon"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "ne eblas ŝanĝiĝi al registrejo \"%s\" por %s"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "ne eblas restarigi registrejon"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:78 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:171 src/exec_monitor.c:418
+#: src/exec_monitor.c:424 src/exec_monitor.c:432 src/exec_monitor.c:440
+#: src/exec_monitor.c:447 src/exec_monitor.c:454 src/exec_monitor.c:461
+#: src/exec_monitor.c:468 src/exec_monitor.c:475 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:744 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1096
+#: src/exec_ptrace.c:1271 src/exec_ptrace.c:1624 src/exec_ptrace.c:1651
+#: src/exec_ptrace.c:1841 src/exec_pty.c:581 src/exec_pty.c:765
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:193 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:240
+#: src/sesh.c:246 src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:644
+#: src/sudo.c:709 src/sudo.c:719 src/sudo.c:746 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:787 src/sudo.c:805 src/sudo.c:846 src/sudo.c:855 src/sudo.c:865
+#: src/sudo.c:898 src/sudo.c:1127 src/sudo.c:1148 src/sudo.c:1441
+#: src/sudo.c:1610 src/sudo.c:1837 src/sudo.c:2171 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:430 src/sudo_edit.c:439
+#: src/sudo_edit.c:540 src/sudo_edit.c:547 src/sudo_edit.c:692
+#: src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:79 src/exec_intercept.c:111 src/exec_intercept.c:350
+#: src/exec_intercept.c:525 src/exec_intercept.c:589 src/exec_intercept.c:713
+#: src/exec_intercept.c:837 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:418 src/exec_monitor.c:424
+#: src/exec_monitor.c:432 src/exec_monitor.c:440 src/exec_monitor.c:447
+#: src/exec_monitor.c:454 src/exec_monitor.c:461 src/exec_monitor.c:468
+#: src/exec_monitor.c:475 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1651 src/exec_ptrace.c:1842 src/exec_pty.c:581
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:228 src/sudo.c:644 src/sudo.c:898 src/sudo.c:1127
+#: src/sudo.c:1148 src/sudo.c:1441 src/sudo.c:1610 src/sudo.c:1837
+#: src/sudo.c:2171 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:430
+#: src/sudo_edit.c:439 src/sudo_edit.c:540 src/sudo_edit.c:547
+#: src/sudo_edit.c:692 src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "ne eblas generi memoron"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "ne eblas apliki stat al %.*s"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s ekzistas sed ne estas dosierujo (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:664
+#: lib/util/sudo_conf.c:683 lib/util/sudo_conf.c:710 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:495 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "ne eblas malfermi %s"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "ne eblas apliki mkdir al %.*s"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "ne eblas malfermi %.*s"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "regulesprimo tra grandas"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Nekonata signalo"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "nevalida valoro"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "valoro tro grandas"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "valoro tro malgrandas"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "nevalida voja valoro \"%s\" en %s, linio %u"
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "nevalida valoro por %s \"%s\" en %s, linio %u"
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "nekomprenata grupa fonto \"%s\" en %s, linio %u"
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "nevalidaj maksimumaj grupoj \"%s\" en %s, linio %u"
+
+#: lib/util/sudo_conf.c:686
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s estas ne regula dosiero"
+
+#: lib/util/sudo_conf.c:689 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s estas estrata de uid %u, devas esti %u"
+
+#: lib/util/sudo_conf.c:693
+#, c-format
+msgid "%s is world writable"
+msgstr "%s estas skribebla de ĉiuj"
+
+#: lib/util/sudo_conf.c:696
+#, c-format
+msgid "%s is group writable"
+msgstr "%s estas skribebla de la tuta grupo"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "ne povas determini AppArmon-enfermon."
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "ne eblas ŝanĝi AppArmor-profilon al %s"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: ĉu distranĉi %s ĝis nul bajto? (y/n) [n]"
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "ne anstataŭigos je %s"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "ne eblas legi ell %s"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "ne eblas skribi al %s"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "ne eblas apliki stat al %s"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: ne regula dosiero"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: malbona dosiera reĝimo: 0%o"
+
+#: src/edit_open.c:333
+msgid "unable to restore current working directory"
+msgstr "ne eblas restarigi nune kurantan dosierujon"
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "ne eblas agordi rajtojn"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "ne eblas limigi rajtojn"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "nekonata ensaluta klaso %s"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "ne eblas elekti uzanto-kuntekston"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "ne eblas elekti procezan prioritaton"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "ne eblas ŝanĝi ĉefuzanton al %s"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "ne eblas ŝanĝi al plenumigkiela uid (%u, %u)"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "ne eblas ŝanĝi dosierujon al %s"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "komenciĝas de %s"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:552 src/exec_monitor.c:554
+#: src/exec_pty.c:1122 src/exec_pty.c:1124 src/signal.c:144 src/signal.c:151
+#: src/signal.c:165 src/suspend_parent.c:143
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "ne eblas difini traktilon por la signalo %d"
+
+#: src/exec.c:424
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "interkapta reĝo ne estas regata kun SELinux-RABC en ĉi tiu sistemo"
+
+#: src/exec.c:429
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "ne eblas protokoli subkomandojn kun SELinux-RBAC en ĉi tiu sistemo"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "ne eblas forigi PRIV_PROC_EXEC-on de PRIV_LIMIT"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:163 src/exec_iolog.c:173
+#: src/exec_iolog.c:218 src/exec_iolog.c:225 src/exec_iolog.c:252
+#: src/exec_monitor.c:426 src/exec_monitor.c:434 src/exec_monitor.c:442
+#: src/exec_monitor.c:449 src/exec_monitor.c:456 src/exec_monitor.c:463
+#: src/exec_monitor.c:470 src/exec_monitor.c:477 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:457 src/exec_pty.c:432
+#: src/exec_pty.c:537 src/exec_pty.c:587 src/exec_pty.c:965 src/exec_pty.c:974
+#: src/exec_pty.c:981 src/exec_pty.c:988 src/exec_pty.c:995
+#: src/exec_pty.c:1002 src/exec_pty.c:1009 src/exec_pty.c:1016
+#: src/exec_pty.c:1023 src/exec_pty.c:1030 src/exec_pty.c:1037
+#: src/exec_pty.c:1044
+msgid "unable to add event to queue"
+msgstr "ne eblas aldoni al la atendovico eventon"
+
+#: src/exec_intercept.c:323 src/sudo.c:1033
+msgid "command not set by the security policy"
+msgstr "komando ne agordita per la sekureco-regularo"
+
+#: src/exec_intercept.c:401 src/exec_intercept.c:441 src/sudo.c:1253
+#: src/sudo.c:1298 src/sudo.c:1342
+msgid "command rejected by policy"
+msgstr "komando rifuzita pro konduto-regularo"
+
+#: src/exec_intercept.c:512 src/sudo.c:1940
+msgid "approval plugin error"
+msgstr "eraro de aproba kromprogramo"
+
+#: src/exec_intercept.c:537 src/sudo.c:1258 src/sudo.c:1303 src/sudo.c:1347
+#: src/sudo.c:1421
+msgid "policy plugin error"
+msgstr "eraro de konduta kromprogramo"
+
+#: src/exec_intercept.c:566
+msgid "invalid PolicyCheckRequest"
+msgstr "nevalida PolicyCheckRequest"
+
+#: src/exec_intercept.c:709
+#, c-format
+msgid "client request too large: %zu"
+msgstr "klienta peto tro granda: %zu"
+
+#: src/exec_intercept.c:751
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "ne eblas malpaki %s, grando %zu"
+
+#: src/exec_intercept.c:799
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "neatendita valoro %d de type_case en %s el %s"
+
+#: src/exec_intercept.c:825
+#, c-format
+msgid "server message too large: %zu"
+msgstr "servila mesaĝo tro granda: %zu"
+
+#: src/exec_iolog.c:321 src/exec_iolog.c:361 src/exec_iolog.c:401
+#: src/exec_iolog.c:452 src/exec_iolog.c:503
+msgid "I/O plugin error"
+msgstr "En/eliga kromprograma eraro"
+
+#: src/exec_iolog.c:325 src/exec_iolog.c:365 src/exec_iolog.c:405
+#: src/exec_iolog.c:456 src/exec_iolog.c:507
+msgid "command rejected by I/O plugin"
+msgstr "komando rifuzita de en/eliga kromprogramo"
+
+#: src/exec_iolog.c:555
+msgid "error logging suspend"
+msgstr "ni paŭzas la protokoladon de eraroj"
+
+#: src/exec_iolog.c:590
+msgid "error changing window size"
+msgstr "eraro dum ŝanĝo de fenestro-grando"
+
+#: src/exec_monitor.c:328
+msgid "error reading from socketpair"
+msgstr "eraro dum legi la konektingan paron"
+
+#: src/exec_monitor.c:340
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "neatendita respondotipo ĉe la postkanalo: %d"
+
+#: src/exec_monitor.c:566
+msgid "unable to set controlling tty"
+msgstr "ne eblas elekti la regan tty-on"
+
+#: src/exec_monitor.c:574 src/exec_nopty.c:504 src/exec_nopty.c:514
+#: src/exec_nopty.c:524 src/exec_nopty.c:560 src/exec_pty.c:1195
+#: src/exec_pty.c:1222 src/exec_pty.c:1242 src/exec_pty.c:1262
+#: src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr "ne eblas krei tubon"
+
+#: src/exec_monitor.c:584
+msgid "unable to receive message from parent"
+msgstr "ne eblas ricevi mesaĝon el supre"
+
+#: src/exec_monitor.c:600 src/exec_nopty.c:603 src/exec_pty.c:1303
+#: src/sudo_edit.c:361 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr "ne eblas forki"
+
+#: src/exec_monitor.c:604 src/exec_monitor.c:700 src/exec_nopty.c:708
+msgid "unable to restore tty label"
+msgstr "ne eblis reatingi tty-etikedon"
+
+#: src/exec_monitor.c:615 src/sesh.c:217 src/sudo.c:1204
+#, c-format
+msgid "unable to execute %s"
+msgstr "ne eblas plenumigi: %s"
+
+#: src/exec_nopty.c:554 src/exec_pty.c:1131
+msgid "policy plugin failed session initialization"
+msgstr "konduta kromprogramo fiaskis dum seanca komenciĝo"
+
+#: src/exec_nopty.c:569 src/exec_pty.c:1100 src/exec_pty.c:1109
+msgid "unable to create sockets"
+msgstr "ne eblas krei konektingojn"
+
+#: src/exec_nopty.c:696 src/exec_pty.c:1406
+msgid "error in event loop"
+msgstr "eraro en la eventa iteracio"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:852 src/sudo.c:488
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "interna eraro, superfluo en %s"
+
+#: src/exec_ptrace.c:1080 src/exec_ptrace.c:1105 src/exec_ptrace.c:1925
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "ne eblas ŝanĝi registrejojn por procezo %d"
+
+#: src/exec_ptrace.c:1100 src/exec_ptrace.c:1275 src/exec_ptrace.c:1628
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "procezo %d neatendite finiĝis"
+
+#: src/exec_ptrace.c:1209
+msgid "unable to set seccomp filter"
+msgstr "ne eblas elekti seccomp-filtrilon"
+
+#: src/exec_ptrace.c:1406
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "interpretila argumento , atendita \"%s\", ricevita \"%s\""
+
+#: src/exec_ptrace.c:1505
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "vojnomo malkongruaĵo, atendita \"%s\", ricevita \"%s\""
+
+#: src/exec_ptrace.c:1514 src/exec_ptrace.c:1521 src/exec_ptrace.c:1545
+#: src/exec_ptrace.c:1553 src/exec_ptrace.c:1559 src/exec_ptrace.c:1565
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "%s[%d] malkongruaĵo, atendita \"%s\", ricevita \"%s\""
+
+#: src/exec_ptrace.c:1632
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "procezo %d neatendita stato 0x%x"
+
+#: src/exec_ptrace.c:1723
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "ne eblas atingi eventan mesaĝon por procezo %d"
+
+#: src/exec_ptrace.c:1730
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "ne eblas atingi registrejojn por procezo %d"
+
+#: src/exec_pty.c:84
+msgid "unable to allocate pty"
+msgstr "ne eblis generi pty-on"
+
+#: src/exec_pty.c:131 src/exec_pty.c:284 src/tgetpass.c:251
+msgid "unable to restore terminal settings"
+msgstr "ne eblas restarigi terminalan agordon"
+
+#: src/exec_pty.c:243
+msgid "unable to set handler for SIGCONT"
+msgstr "ne eblas difini traktilon por la signalo SIGCONT"
+
+#: src/exec_pty.c:293
+#, c-format
+msgid "unable to set handler for SIG%s"
+msgstr "ne eblas difini traktilon por la signalo SIG%s"
+
+#: src/exec_pty.c:317
+#, c-format
+msgid "unable to restore handler for SIG%s"
+msgstr "ne eblas restarigi traktilon por la signalo SIG%s"
+
+#: src/exec_pty.c:345
+msgid "unable to restore handler for SIGCONT"
+msgstr "ne eblas restarigi traktilon por la signalo SIGCONT"
+
+#: src/exec_pty.c:1353
+msgid "unable to send message to monitor process"
+msgstr "ne eblas sendi mesaĝon al observa procezo"
+
+#: src/load_plugins.c:75 src/load_plugins.c:222 src/load_plugins.c:232
+#: src/load_plugins.c:242 src/load_plugins.c:289
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "eraro en %s, linio %d dum ŝargi kromprogramon \"%s\""
+
+#: src/load_plugins.c:186 src/load_plugins.c:257
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "ni malatentas duobligitan kromprogramon \"%s\" en %s, linio %d"
+
+#: src/load_plugins.c:224
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "maleblas ŝarĝi je %s: %s"
+
+#: src/load_plugins.c:234
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "ne eblas trovi simbolon \"%s\" en %s"
+
+#: src/load_plugins.c:244
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "malkongrua granda versio %d de kromprogramo (atendite %d) trovita en %s"
+
+#: src/load_plugins.c:262
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "ni malatentas kondutan kromprogramon \"%s\" en %s, linio %d"
+
+#: src/load_plugins.c:265
+msgid "only a single policy plugin may be specified"
+msgstr "nur unu konduta kromprogramo povas esti indikata"
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "nekonata kromprograma tipo %d trovita en %s"
+
+#: src/load_plugins.c:474
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "konduta kromprogramo %s ne inkluzivas la metodon check_policy"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "malvalida medivariabla nomo: %s"
+
+#: src/parse_args.c:319
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "la parametro de -C devas esti nombron almenaŭ 3"
+
+#: src/parse_args.c:556
+msgid "you may not specify both the -i and -s options"
+msgstr "vi ne rajtas specifi ambaŭ parametrojn -i kaj -s"
+
+#: src/parse_args.c:561
+msgid "you may not specify both the -i and -E options"
+msgstr "vi ne rajtas specifi ambaŭ parametrojn -i kaj -E"
+
+#: src/parse_args.c:571
+msgid "the -E option is not valid in edit mode"
+msgstr "la parametro -E ne validas en redakta reĝimo"
+
+#: src/parse_args.c:574
+msgid "you may not specify environment variables in edit mode"
+msgstr "vi ne rajtas specifi medivariablojn en redakta reĝimo"
+
+#: src/parse_args.c:584
+msgid "the -U option may only be used with the -l option"
+msgstr "la parametro '-U' nur povas esti uzata kun '-l'"
+
+#: src/parse_args.c:588
+msgid "the -A and -S options may not be used together"
+msgstr "vi ne rajtas kune uzi la parametrojn '-A' kaj '-S'"
+
+#: src/parse_args.c:686
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit ne estas havebla en ĉi tiu platformon"
+
+#: src/parse_args.c:744
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Vi rajtas specifi nur unu el -e, -h, -i, -K, -l, -s, -v aŭ -V"
+
+#: src/parse_args.c:757
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "Vi rajtas specifi nur unu el -K, -k aŭ -N"
+
+#: src/parse_args.c:778
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - redakti dosierojn kiel alia uzanto\n"
+"\n"
+
+#: src/parse_args.c:780
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - plenumigi komandon kiel alia uzanto\n"
+"\n"
+
+#: src/parse_args.c:785
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Parametroj:\n"
+
+#: src/parse_args.c:787
+msgid "use a helper program for password prompting"
+msgstr "uzi helpoprogrogramon por pasvortilo"
+
+#: src/parse_args.c:790
+msgid "use specified BSD authentication type"
+msgstr "uzi specifitan BSD-konstatan tipon"
+
+#: src/parse_args.c:794
+msgid "run command in the background"
+msgstr "plenumigi komandon fone"
+
+#: src/parse_args.c:797
+msgid "ring bell when prompting"
+msgstr "sonigi pepon kiam invitanta"
+
+#: src/parse_args.c:799
+msgid "close all file descriptors >= num"
+msgstr "fermi ĉiujn dosierpriskribilojn >= numeron"
+
+#: src/parse_args.c:802
+msgid "run command with the specified BSD login class"
+msgstr "plenumigi komandon per specifita BSD-ensaluta klaso"
+
+#: src/parse_args.c:805
+msgid "change the working directory before running command"
+msgstr "ŝanĝu la kurantan dosierujon antaŭ plenumi komandon"
+
+#: src/parse_args.c:808
+msgid "preserve user environment when running command"
+msgstr "konservi uzanto-medivariablojn dum plenumigi komandon"
+
+#: src/parse_args.c:810
+msgid "preserve specific environment variables"
+msgstr "konservi specifajn medivariablojn"
+
+#: src/parse_args.c:812
+msgid "edit files instead of running a command"
+msgstr "redakti dosierojn anstataŭ plenumigi komandon"
+
+#: src/parse_args.c:815
+msgid "run command as the specified group name or ID"
+msgstr "plenumigi komandon kiel la specifitan grupnomon aŭ identigilon"
+
+#: src/parse_args.c:818
+msgid "set HOME variable to target user's home dir"
+msgstr "valorizi medivariablon HOME je la hejma dosierujo de la cela uzanto"
+
+#: src/parse_args.c:821
+msgid "display help message and exit"
+msgstr "elmontri helpan mesaĝon kaj eliri"
+
+#: src/parse_args.c:823
+msgid "run command on host (if supported by plugin)"
+msgstr "plenumigi komandon en gastiganto (se permesata de kromprogramo)"
+
+#: src/parse_args.c:826
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "plenumigi ensalutan ŝelon kiel celan uzanton; komando ankaŭ enmeteblas"
+
+#: src/parse_args.c:828
+msgid "remove timestamp file completely"
+msgstr "tute forigi tempo-indikilan dosieron"
+
+#: src/parse_args.c:831
+msgid "invalidate timestamp file"
+msgstr "eksvalidigi tempo-indikilan dosieron"
+
+#: src/parse_args.c:834
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "listigi privilegiojn de la uzanto aŭ kontroli specifan komandon; uzu dufoje por pli longa formato"
+
+#: src/parse_args.c:837
+msgid "non-interactive mode, no prompts are used"
+msgstr "neinteraga reĝimo, ne demandos al uzanto"
+
+#: src/parse_args.c:840
+msgid "preserve group vector instead of setting to target's"
+msgstr "konservi grupan vektoron anstataŭ elekti celan"
+
+#: src/parse_args.c:843
+msgid "use the specified password prompt"
+msgstr "uzi specifitan pasvortilon"
+
+#: src/parse_args.c:845
+msgid "change the root directory before running command"
+msgstr "ŝanĝu la radikan dosierujon antaŭ ol plenumigi komandon"
+
+#: src/parse_args.c:848
+msgid "create SELinux security context with specified role"
+msgstr "krei SELinux-sekurecan kuntekston kun specifita rolo"
+
+#: src/parse_args.c:851
+msgid "read password from standard input"
+msgstr "legi pasvorton el norma enigo"
+
+#: src/parse_args.c:854
+msgid "run shell as the target user; a command may also be specified"
+msgstr "plenumigi ŝelon kiel cela uzanto; komando ankaŭ specifebla"
+
+#: src/parse_args.c:858
+msgid "create SELinux security context with specified type"
+msgstr "krei SELinux-sekurecan kuntekston kun specifita rolo"
+
+#: src/parse_args.c:861
+msgid "terminate command after the specified time limit"
+msgstr "finigi la komandon post la specifita tempolimo"
+
+#: src/parse_args.c:864
+msgid "in list mode, display privileges for user"
+msgstr "en lista reĝimo elmontri privilegiojn por uzanto"
+
+#: src/parse_args.c:867
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "plenumigi komandon (aŭ redakti dosieron) kiel specifita uzanto"
+
+#: src/parse_args.c:869
+msgid "display version information and exit"
+msgstr "elmontri eldonan informon kaj eliri"
+
+#: src/parse_args.c:872
+msgid "update user's timestamp without running a command"
+msgstr "ĝisdatigi la tempo-indikilon de la uzanto, sed ne plenumigi komandon"
+
+#: src/parse_args.c:875
+msgid "stop processing command line arguments"
+msgstr "ĉesigi procedi komandliniajn parametrojn"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "ne eblas malfermi aŭdan sistemon"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "ne eblas sendi aŭdan mesaĝon"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "ne eblas voki fgetfilecon %s"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s ŝanĝis etikedojn"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "ne eblas restarigi kuntekston por %s"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "ne eblas malfermi %s, ne remarkanta tty-on"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s ne estas signo-aparato, ni ne remarkas tty"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "ne eblas akiri aktualan tty-kuntekston, ne remarkanta"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "nekonata sekurecan klason \"chr_file\", ni ne remarkas tty"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "ne eblas akiri novan tty-kuntekston, ni ne remarkas tty"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "ne eblas elekti novan tty-kuntekston"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "vi devas specifi rolon por tipo %s"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "ne eblas akiri aŭtomatan tipon por rolo %s"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "malsukcesis akiri novan kuntekston"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "malsukcesis elekti novan rolon %s"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "malsukcesis elekti novan tipon %s"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s ne estas valida kunteksto"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "malsukcesis akiri malnovan kuntekston"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "ne povas determini eldevigan reĝimon."
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "ne eblas elekti exec-kuntekston al %s"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "ne eblas elekti kuntekston de kreo de ŝlosilo al %s"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "Vi rajtas specifi nur unu el -c aŭ -i"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "malvalida dosierpriskribila numero: %s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "La parametron -%c oni ne rajtas uzi en redakto-reĝimo."
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "La parametron -%c oni ne rajtas uzi nur en redakto-reĝimon."
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: redakto de simbolaj ligoj ne estas permesata"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: redakto de dosieroj en skribebla dosierujo ne estas permesata"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "enhavo de redakta seanco restas en %s"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "ne eblas atingi grupan liston"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "ne eblas konservi traktilon por la signalo %d"
+
+#: src/signal.c:101 src/suspend_parent.c:149
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "ne eblas restarigi traktilon por la signalo %d"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "rimedo-rega limigo estis atingita"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "uzanto \"%s\" ne estas ano de projekto \"%s\""
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "la voka tasko estas nenuligebla"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "ne eblis aliĝi al projekto \"%s\""
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "neniu rimedujo akceptanta aŭtomatajn bindaĵojn ekzistas por projekto \"%s\""
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "specifita rimedujo ne ekzistas por projekto \"%s\""
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "ne eblis bindi al aprioran rimedujo por projekto \"%s\""
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "setproject malsukcesis por projekto \"%s\""
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "averto, rimedo-rega asigno malsukcesis por projekto \"%s\""
+
+#: src/sudo.c:214
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo: eldono %s\n"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Muntaj parametroj: %s\n"
+
+#: src/sudo.c:224
+msgid "fatal error, unable to load plugins"
+msgstr "ĉesiga eraro: ne eblas ŝargi kromprogramojn"
+
+#: src/sudo.c:270
+msgid "plugin did not return a command to execute"
+msgstr "kromprogramo ne liveris komandon por plenumi"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "neatendita sudo-reĝimon 0x%x"
+
+#: src/sudo.c:559
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "vi ne ekzistas en la datumbazo %s"
+
+#: src/sudo.c:616
+msgid "unable to determine tty"
+msgstr "ne eblas determini tty-on"
+
+#: src/sudo.c:932
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "La flago \"neniuj novaj privilegioj\" estas agordita. Tio malhelpas al sudo plenumigi kiel la ĉefuzanto."
+
+#: src/sudo.c:934
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "Se sudo plenumiĝas en ujo, vi eble devas alĝustigi la ujan agordo por malŝalti la flagon."
+
+#: src/sudo.c:968
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s devas esti posedata de uid %d kaj la setuid-bito devas esti markita"
+
+#: src/sudo.c:971
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "efektiva uid ne estas %d; ĉu %s estas en dosiersistemo kun la elekto 'nosuid' aŭ reta dosiersistemo sen ĉefuzanto-privilegioj?"
+
+#: src/sudo.c:977
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "efektiva uid ne estas %d; ĉu sudo estas instalita kiel setuid-radiko?"
+
+#: src/sudo.c:993 src/tgetpass.c:332
+msgid "unable to set supplementary group IDs"
+msgstr "ne eblas elekti suplementajn grupajn identigilojn"
+
+#: src/sudo.c:1000
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "ne eblas elekti efikan gid-on al plenumigkiela gid %u"
+
+#: src/sudo.c:1006
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "ne eblas elekti gid-on kiel plenumigkielan gid-on %u"
+
+#: src/sudo.c:1037
+msgid "argv not set by the security policy"
+msgstr "argv ne agordita per la sekureco-regularo"
+
+#: src/sudo.c:1041
+msgid "envp not set by the security policy"
+msgstr "envp ne agordita per la sekureco-regularo"
+
+#: src/sudo.c:1063
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "neatendita ido finiĝis laŭ la kondiĉo: %d"
+
+#: src/sudo.c:1176
+msgid "unable to initialize policy plugin"
+msgstr "ne eblas komenci konduktan kromprogramon"
+
+#: src/sudo.c:1238
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "konduta kromprogramo %s ne inkluzivas la metodon \"check_policy\""
+
+#: src/sudo.c:1284
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "konduta kromprogramo %s ne komprenas listigon de privilegioj"
+
+#: src/sudo.c:1328
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "konduta kromprogramo %s ne komprenas la parametron -v"
+
+#: src/sudo.c:1366
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "konduta kromprogramo %s ne komprenas la parametrojn -k kaj -K"
+
+#: src/sudo.c:1495
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "eraro dum lanĉo de eneliga kromprogramo %s"
+
+#: src/sudo.c:1498
+msgid "error initializing I/O plugin"
+msgstr "eraro dum lanĉo de eneliga kromprogramo"
+
+#: src/sudo.c:1647
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "eraro dum lanĉo de ekzamena kromprogramo %s"
+
+#: src/sudo.c:1726
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%smaleblas protokoli eraro-eventon%s%s"
+
+#: src/sudo.c:1762
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: maleblas protokoli akcepto-eventon%s%s"
+
+#: src/sudo.c:1767 src/sudo.c:1805
+msgid "audit plugin error"
+msgstr "Kontrolo-kromprograma eraro"
+
+#: src/sudo.c:1800
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: neeblas protokoli malakcepto-eventon%s%s"
+
+#: src/sudo.c:1860
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "eraro dum lanĉo de aproba kromprogramo %s"
+
+#: src/sudo.c:1930
+msgid "command rejected by approver"
+msgstr "komando rifuzita de aprobanto"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "neniu skribebla provizora dosierujo estis trovata"
+
+#: src/sudo_edit.c:292
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s restas ne modifita"
+
+#: src/sudo_edit.c:305 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s ne ŝanĝita"
+
+#: src/sudo_edit.c:482
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: interna eraro: malpara nombro da vojoj"
+
+#: src/sudo_edit.c:484
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: ne eblas krei provizorajn dosierojn"
+
+#: src/sudo_edit.c:486 src/sudo_edit.c:606
+msgid "sesh: killed by a signal"
+msgstr "sesh: mortigita de signalo"
+
+#: src/sudo_edit.c:488 src/sudo_edit.c:609
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: nekonata eraro %d"
+
+#: src/sudo_edit.c:599
+msgid "unable to copy temporary files back to their original location"
+msgstr "ne eblas retrokopii provizorajn dosierojn al ilia originala loko"
+
+#: src/sudo_edit.c:603
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "ne eblas retrokopii kelkajn el la provizoraj dosieroj al ilia originala loko"
+
+#: src/sudo_edit.c:650
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "ne eblas ŝanĝi uid-on al ĉefuzanto (%u)"
+
+#: src/sudo_edit.c:664
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "kromprograma eraro: malvalida dosieran liston por sudoedit"
+
+#: src/sudo_edit.c:685
+msgid "plugin error: missing file list for sudoedit"
+msgstr "kromprograma eraro: malhavas dosieran liston por sudoedit"
+
+#: src/sudo_edit.c:728 src/sudo_edit.c:743
+msgid "unable to read the clock"
+msgstr "ne eblas legi la horloĝon"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "interkapta pordo ne agordita"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "tro da tempo por kapti pasvorton"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "neniu pasvorto estis provizata"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "ne eblas legi pasvorton"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "terminalo estas postulata por legi la pasvorton; uzu la parametron -S por legi el norma enigo aŭ agordu helpanton askpass"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "neniu programo askpass indikita, provu difini SUDO_ASKPASS"
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "ne eblas elekti gid-on al %u"
+
+#: src/tgetpass.c:337
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "ne eblas elekti uid-on al %u"
+
+#: src/tgetpass.c:342
+#, c-format
+msgid "unable to run %s"
+msgstr "ne eblas plenumigi: %s"
+
+#: src/utmp.c:283
+msgid "unable to save stdin"
+msgstr "ne eblas konservi norman enigon"
+
+#: src/utmp.c:285
+msgid "unable to dup2 stdin"
+msgstr "ne eblas dup2 el norma enigo"
+
+#: src/utmp.c:288
+msgid "unable to restore stdin"
+msgstr "ne eblas restarigi norman enigon"
diff --git a/po/es.mo b/po/es.mo
new file mode 100644
index 0000000..9f3fbe1
--- /dev/null
+++ b/po/es.mo
Binary files differ
diff --git a/po/es.po b/po/es.po
new file mode 100644
index 0000000..5e238a1
--- /dev/null
+++ b/po/es.po
@@ -0,0 +1,1002 @@
+# traducción al español de sudo.
+# This file is distributed under the same license as the sudo package.
+#
+# Abel Sendón <abelnicolas1976@gmail.com>, 2012.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.8.26b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2018-10-29 08:31-0600\n"
+"PO-Revision-Date: 2019-02-25 18:22-0300\n"
+"Last-Translator: Abel Sendón <abelnicolas1976@gmail.com>\n"
+"Language-Team: Spanish <es@tp.org.es>\n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 2.0.6\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+
+#: lib/util/aix.c:90 lib/util/aix.c:177
+msgid "unable to open userdb"
+msgstr "no se puede abrir userdb"
+
+#: lib/util/aix.c:232
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "no se puede cambiar al registro \"%s\" para %s"
+
+#: lib/util/aix.c:257
+msgid "unable to restore registry"
+msgstr "no se puede restaurar el registro"
+
+#: lib/util/aix.c:280 lib/util/gidlist.c:69 lib/util/gidlist.c:79
+#: lib/util/sudo_conf.c:191 lib/util/sudo_conf.c:277 lib/util/sudo_conf.c:354
+#: lib/util/sudo_conf.c:558 src/conversation.c:82 src/exec_common.c:112
+#: src/exec_common.c:128 src/exec_common.c:137 src/exec_monitor.c:210
+#: src/exec_monitor.c:465 src/exec_monitor.c:471 src/exec_monitor.c:479
+#: src/exec_monitor.c:487 src/exec_monitor.c:494 src/exec_monitor.c:501
+#: src/exec_monitor.c:508 src/exec_monitor.c:515 src/exec_monitor.c:522
+#: src/exec_monitor.c:529 src/exec_monitor.c:536 src/exec_nopty.c:212
+#: src/exec_nopty.c:218 src/exec_nopty.c:227 src/exec_nopty.c:234
+#: src/exec_nopty.c:241 src/exec_nopty.c:248 src/exec_nopty.c:255
+#: src/exec_nopty.c:262 src/exec_nopty.c:269 src/exec_nopty.c:276
+#: src/exec_nopty.c:283 src/exec_nopty.c:290 src/exec_nopty.c:297
+#: src/exec_nopty.c:305 src/exec_nopty.c:467 src/exec_pty.c:778
+#: src/exec_pty.c:787 src/exec_pty.c:844 src/exec_pty.c:994
+#: src/exec_pty.c:1157 src/exec_pty.c:1163 src/exec_pty.c:1172
+#: src/exec_pty.c:1179 src/exec_pty.c:1186 src/exec_pty.c:1193
+#: src/exec_pty.c:1200 src/exec_pty.c:1207 src/exec_pty.c:1214
+#: src/exec_pty.c:1221 src/exec_pty.c:1228 src/exec_pty.c:1235
+#: src/exec_pty.c:1243 src/exec_pty.c:1661 src/load_plugins.c:57
+#: src/load_plugins.c:70 src/load_plugins.c:219 src/load_plugins.c:240
+#: src/load_plugins.c:309 src/load_plugins.c:315 src/load_plugins.c:329
+#: src/load_plugins.c:335 src/parse_args.c:182 src/parse_args.c:203
+#: src/parse_args.c:278 src/parse_args.c:565 src/parse_args.c:587
+#: src/preserve_fds.c:52 src/preserve_fds.c:137 src/selinux.c:89
+#: src/selinux.c:314 src/selinux.c:437 src/selinux.c:446 src/sesh.c:115
+#: src/sudo.c:616 src/sudo.c:676 src/sudo.c:686 src/sudo.c:706 src/sudo.c:725
+#: src/sudo.c:734 src/sudo.c:743 src/sudo.c:760 src/sudo.c:801 src/sudo.c:811
+#: src/sudo.c:834 src/sudo.c:1071 src/sudo.c:1092 src/sudo.c:1266
+#: src/sudo.c:1382 src/sudo_edit.c:256 src/sudo_edit.c:789 src/sudo_edit.c:886
+#: src/sudo_edit.c:1000 src/sudo_edit.c:1020
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:280 lib/util/gidlist.c:69 lib/util/sudo_conf.c:192
+#: lib/util/sudo_conf.c:277 lib/util/sudo_conf.c:354 lib/util/sudo_conf.c:558
+#: src/conversation.c:83 src/exec_common.c:112 src/exec_common.c:129
+#: src/exec_common.c:138 src/exec_monitor.c:465 src/exec_monitor.c:471
+#: src/exec_monitor.c:479 src/exec_monitor.c:487 src/exec_monitor.c:494
+#: src/exec_monitor.c:501 src/exec_monitor.c:508 src/exec_monitor.c:515
+#: src/exec_monitor.c:522 src/exec_monitor.c:529 src/exec_monitor.c:536
+#: src/exec_nopty.c:212 src/exec_nopty.c:218 src/exec_nopty.c:227
+#: src/exec_nopty.c:234 src/exec_nopty.c:241 src/exec_nopty.c:248
+#: src/exec_nopty.c:255 src/exec_nopty.c:262 src/exec_nopty.c:269
+#: src/exec_nopty.c:276 src/exec_nopty.c:283 src/exec_nopty.c:290
+#: src/exec_nopty.c:297 src/exec_nopty.c:305 src/exec_pty.c:778
+#: src/exec_pty.c:787 src/exec_pty.c:844 src/exec_pty.c:1157
+#: src/exec_pty.c:1163 src/exec_pty.c:1172 src/exec_pty.c:1179
+#: src/exec_pty.c:1186 src/exec_pty.c:1193 src/exec_pty.c:1200
+#: src/exec_pty.c:1207 src/exec_pty.c:1214 src/exec_pty.c:1221
+#: src/exec_pty.c:1228 src/exec_pty.c:1235 src/exec_pty.c:1243
+#: src/exec_pty.c:1661 src/load_plugins.c:219 src/load_plugins.c:240
+#: src/load_plugins.c:309 src/load_plugins.c:315 src/load_plugins.c:329
+#: src/load_plugins.c:335 src/parse_args.c:182 src/parse_args.c:204
+#: src/parse_args.c:278 src/parse_args.c:565 src/parse_args.c:587
+#: src/preserve_fds.c:52 src/preserve_fds.c:137 src/selinux.c:89
+#: src/selinux.c:314 src/selinux.c:437 src/selinux.c:446 src/sesh.c:115
+#: src/sudo.c:616 src/sudo.c:834 src/sudo.c:1071 src/sudo.c:1092
+#: src/sudo.c:1266 src/sudo.c:1382 src/sudo_edit.c:256 src/sudo_edit.c:789
+#: src/sudo_edit.c:886 src/sudo_edit.c:1000 src/sudo_edit.c:1020
+msgid "unable to allocate memory"
+msgstr "no se puede de asignar memoria"
+
+#: lib/util/strsignal.c:53
+msgid "Unknown signal"
+msgstr "Señal desconocida"
+
+#: lib/util/strtoid.c:82 lib/util/strtoid.c:129 lib/util/strtoid.c:157
+#: lib/util/strtomode.c:54 lib/util/strtonum.c:63 lib/util/strtonum.c:181
+msgid "invalid value"
+msgstr "valor inválido"
+
+#: lib/util/strtoid.c:89 lib/util/strtoid.c:136 lib/util/strtoid.c:164
+#: lib/util/strtomode.c:60 lib/util/strtonum.c:66 lib/util/strtonum.c:193
+msgid "value too large"
+msgstr "valor muy grande"
+
+#: lib/util/strtoid.c:91 lib/util/strtoid.c:142 lib/util/strtomode.c:60
+#: lib/util/strtonum.c:66 lib/util/strtonum.c:187
+msgid "value too small"
+msgstr "valor muy pequeño"
+
+#: lib/util/sudo_conf.c:210
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "valor de ruta inválido \"%s\" en %s, línea %u"
+
+#: lib/util/sudo_conf.c:376 lib/util/sudo_conf.c:429
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "valor inválido para %s \"%s\" en %s, línea %u"
+
+#: lib/util/sudo_conf.c:397
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "fuente de grupo no soportada \"%s\" en %s, línea %u"
+
+#: lib/util/sudo_conf.c:413
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "máximo de grupos inválido \"%s\" en %s, línea %u"
+
+#: lib/util/sudo_conf.c:574
+#, c-format
+msgid "unable to stat %s"
+msgstr "no se puede stat en %s"
+
+#: lib/util/sudo_conf.c:577
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s no es un archivo regular"
+
+#: lib/util/sudo_conf.c:580
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s es adueñado por uid %u, sería %u"
+
+#: lib/util/sudo_conf.c:584
+#, c-format
+msgid "%s is world writable"
+msgstr "%s es escribible por todos"
+
+#: lib/util/sudo_conf.c:587
+#, c-format
+msgid "%s is group writable"
+msgstr "%s es escribible por el grupo"
+
+#: lib/util/sudo_conf.c:597 src/selinux.c:213 src/selinux.c:230 src/sudo.c:360
+#, c-format
+msgid "unable to open %s"
+msgstr "no se pudo abrir %s"
+
+#: src/exec.c:165
+#, c-format
+msgid "unknown login class %s"
+msgstr "clase de inicio de sesión desconocida %s"
+
+#: src/exec.c:178
+msgid "unable to set user context"
+msgstr "no se puede establecer el contexto del usuario"
+
+#: src/exec.c:194
+msgid "unable to set process priority"
+msgstr "no se puede establecer la prioridad de proceso"
+
+#: src/exec.c:202
+#, c-format
+msgid "unable to change root to %s"
+msgstr "no se puede cambiar de root a %s"
+
+#: src/exec.c:215 src/exec.c:221 src/exec.c:228
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "no se puede cambiar a runas uid (%u, %u)"
+
+#: src/exec.c:246
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "no se puede cambiar al directorio %s"
+
+#: src/exec.c:345 src/exec_monitor.c:574 src/exec_monitor.c:576
+#: src/exec_nopty.c:525 src/exec_pty.c:522 src/exec_pty.c:1329
+#: src/exec_pty.c:1331 src/signal.c:148 src/signal.c:162
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "no se puede establecer el manejador para señal %d"
+
+#: src/exec_common.c:171
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "no se puede remover PRIV_PROC_EXEC desde PRIV_LIMIT"
+
+#: src/exec_monitor.c:364
+msgid "error reading from socketpair"
+msgstr "error leyendo de socketpair"
+
+#: src/exec_monitor.c:381
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "tipo de respuesta inesperada en canales alternos %d"
+
+#: src/exec_monitor.c:473 src/exec_monitor.c:481 src/exec_monitor.c:489
+#: src/exec_monitor.c:496 src/exec_monitor.c:503 src/exec_monitor.c:510
+#: src/exec_monitor.c:517 src/exec_monitor.c:524 src/exec_monitor.c:531
+#: src/exec_monitor.c:538 src/exec_nopty.c:220 src/exec_nopty.c:229
+#: src/exec_nopty.c:236 src/exec_nopty.c:243 src/exec_nopty.c:250
+#: src/exec_nopty.c:257 src/exec_nopty.c:264 src/exec_nopty.c:271
+#: src/exec_nopty.c:278 src/exec_nopty.c:285 src/exec_nopty.c:292
+#: src/exec_nopty.c:299 src/exec_nopty.c:307 src/exec_pty.c:644
+#: src/exec_pty.c:649 src/exec_pty.c:746 src/exec_pty.c:753 src/exec_pty.c:850
+#: src/exec_pty.c:1165 src/exec_pty.c:1174 src/exec_pty.c:1181
+#: src/exec_pty.c:1188 src/exec_pty.c:1195 src/exec_pty.c:1202
+#: src/exec_pty.c:1209 src/exec_pty.c:1216 src/exec_pty.c:1223
+#: src/exec_pty.c:1230 src/exec_pty.c:1237 src/exec_pty.c:1614
+#: src/exec_pty.c:1624 src/exec_pty.c:1669 src/exec_pty.c:1676
+#: src/exec_pty.c:1703
+msgid "unable to add event to queue"
+msgstr "no se puede agregar evento a la cola"
+
+#: src/exec_monitor.c:592
+msgid "unable to set controlling tty"
+msgstr "no se puede establecer el controlador tty"
+
+#: src/exec_monitor.c:600 src/exec_nopty.c:364 src/exec_pty.c:1408
+#: src/exec_pty.c:1429 src/exec_pty.c:1449 src/tgetpass.c:292
+msgid "unable to create pipe"
+msgstr "no se puede crear tubería"
+
+#: src/exec_monitor.c:608
+msgid "unable to receive message from parent"
+msgstr "no se puede recibir mensaje desde el padre"
+
+#: src/exec_monitor.c:614 src/exec_nopty.c:382 src/exec_pty.c:1487
+#: src/tgetpass.c:296
+msgid "unable to fork"
+msgstr "no se puede bifurcar"
+
+#: src/exec_monitor.c:628 src/sesh.c:125 src/sudo.c:1130
+#, c-format
+msgid "unable to execute %s"
+msgstr "no se puede ejecutar %s"
+
+#: src/exec_monitor.c:711 src/exec_nopty.c:435
+msgid "unable to restore tty label"
+msgstr "no se puede restaurar la etiqueta tty "
+
+#: src/exec_nopty.c:358 src/exec_pty.c:1338
+msgid "policy plugin failed session initialization"
+msgstr "la política de plugin falló en la inicialización de sesión "
+
+#: src/exec_nopty.c:424 src/exec_pty.c:1574
+msgid "error in event loop"
+msgstr "error en loop de evento"
+
+#: src/exec_nopty.c:533 src/exec_pty.c:557 src/signal.c:110
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "no se puede restaurar el manejador para señal %d"
+
+#: src/exec_pty.c:156
+msgid "unable to allocate pty"
+msgstr "no se puede asignar pty"
+
+#: src/exec_pty.c:1318
+msgid "unable to create sockets"
+msgstr "no se puede crear sockets"
+
+#: src/exec_pty.c:1531
+msgid "unable to send message to monitor process"
+msgstr "no se puede enviar mensaje al monitor de procesos"
+
+#: src/load_plugins.c:55 src/load_plugins.c:68 src/load_plugins.c:90
+#: src/load_plugins.c:120 src/load_plugins.c:128 src/load_plugins.c:134
+#: src/load_plugins.c:175 src/load_plugins.c:183 src/load_plugins.c:190
+#: src/load_plugins.c:196
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "error en %s, línea %d mientras se carga el plugin \"%s\""
+
+#: src/load_plugins.c:92
+#, c-format
+msgid "%s%s: %s"
+msgstr "%s%s: %s"
+
+#: src/load_plugins.c:130
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s debe ser propiedad del uid %d"
+
+#: src/load_plugins.c:136
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "%s sólo tener permisos de escritura por el propietario"
+
+#: src/load_plugins.c:177
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "no se puede cargar %s: %s"
+
+#: src/load_plugins.c:185
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "no se puede de encontrar el símbolo \"%s\" en %s"
+
+#: src/load_plugins.c:192
+#, c-format
+msgid "unknown policy type %d found in %s"
+msgstr "tipo de política desconocido %d encontrado en %s"
+
+#: src/load_plugins.c:198
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "incompatible la versión principal de la política de plugin %d (se esperaba %d) encontrada in %s"
+
+#: src/load_plugins.c:207
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "Ignorando política de plugin \"%s\" en %s, linea %d"
+
+#: src/load_plugins.c:209
+msgid "only a single policy plugin may be specified"
+msgstr "sólo una política de plugin puede ser especificada"
+
+#: src/load_plugins.c:212
+#, c-format
+msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+msgstr "Ignorando política de plugin duplicada \"%s\" en %s, línea %d"
+
+#: src/load_plugins.c:231
+#, c-format
+msgid "ignoring duplicate I/O plugin \"%s\" in %s, line %d"
+msgstr "Ignorando E/S de plugin duplicada \"%s\" en %s, linea %d"
+
+#: src/load_plugins.c:347
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "la política del plugin %s no incluye un método check_policy"
+
+#: src/net_ifs.c:180 src/net_ifs.c:197 src/net_ifs.c:342 src/sudo.c:470
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "error interno: desbordamiento de %s"
+
+#: src/parse_args.c:224
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "nombre de variable de entorno inválido: %s"
+
+#: src/parse_args.c:320
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "el argumento -C debe ser un número mayor o igual a 3"
+
+#: src/parse_args.c:505
+msgid "you may not specify both the `-i' and `-s' options"
+msgstr "no se deben especificar las opciones '-i' y '-s' simultáneamente"
+
+#: src/parse_args.c:509
+msgid "you may not specify both the `-i' and `-E' options"
+msgstr "no se deben especificar las opciones '-i' y '-E' simultáneamente"
+
+#: src/parse_args.c:519
+msgid "the `-E' option is not valid in edit mode"
+msgstr "la opción '-E' no es válida en el modo edición"
+
+#: src/parse_args.c:521
+msgid "you may not specify environment variables in edit mode"
+msgstr "no se debe especificar variables de entorno en el modo edición"
+
+#: src/parse_args.c:529
+msgid "the `-U' option may only be used with the `-l' option"
+msgstr "la opción '-U' sólo se puede usar con la opcion '-l'"
+
+#: src/parse_args.c:533
+msgid "the `-A' and `-S' options may not be used together"
+msgstr "las opciones '-A' y '-S' no se pueden utilizar conjuntamente"
+
+#: src/parse_args.c:609
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit no está soportado en ésta plataforma"
+
+#: src/parse_args.c:682
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "puede ser especificada sólo una de las opciones -e, -h, -i, -K, -l, -s, -v o -V"
+
+#: src/parse_args.c:696
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - edita archivos como otro usuario\n"
+"\n"
+
+#: src/parse_args.c:698
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - ejecuta un comando como otro usuario\n"
+"\n"
+
+#: src/parse_args.c:703
+#, c-format
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Opciones:\n"
+
+#: src/parse_args.c:705
+msgid "use a helper program for password prompting"
+msgstr "utiliza un programa auxiliar para la solicitud de contraseña"
+
+#: src/parse_args.c:708
+msgid "use specified BSD authentication type"
+msgstr "utiliza tipo de autentificación especificado en BSD"
+
+#: src/parse_args.c:711
+msgid "run command in the background"
+msgstr "ejecuta un comando en segundo plano"
+
+#: src/parse_args.c:713
+msgid "close all file descriptors >= num"
+msgstr "cierra todos los descriptores de archivo >= num"
+
+#: src/parse_args.c:716
+msgid "run command with the specified BSD login class"
+msgstr "ejecuta un comando con la clase especificada de inicio de sesión BSD"
+
+#: src/parse_args.c:719
+msgid "preserve user environment when running command"
+msgstr "preserva entorno del usuario cuando está ejecutando un comando"
+
+#: src/parse_args.c:721
+msgid "preserve specific environment variables"
+msgstr "preserva variables de entorno específicas"
+
+#: src/parse_args.c:723
+msgid "edit files instead of running a command"
+msgstr "edita archivos en vez de ejecutar un comando"
+
+#: src/parse_args.c:725
+msgid "run command as the specified group name or ID"
+msgstr "ejecuta un comando como el ID o grupo especificado"
+
+#: src/parse_args.c:727
+msgid "set HOME variable to target user's home dir"
+msgstr "asigna la variable HOME al directorio de inicio del usuario"
+
+#: src/parse_args.c:729
+msgid "display help message and exit"
+msgstr "muestra este mensaje de ayuda y sale"
+
+#: src/parse_args.c:731
+msgid "run command on host (if supported by plugin)"
+msgstr "ejecuta comando en host (si está soportado por plugin)"
+
+#: src/parse_args.c:733
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "ejecuta un intérprete de comandos como un determinado usuario, un comando también puede ser especificado"
+
+#: src/parse_args.c:735
+msgid "remove timestamp file completely"
+msgstr "remueve un archivo de marca completamente"
+
+#: src/parse_args.c:737
+msgid "invalidate timestamp file"
+msgstr "archivo de marca inválido"
+
+#: src/parse_args.c:739
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "lista privilegios de usuario o chequea un comando especifico; usar dos veces para formato extenso"
+
+#: src/parse_args.c:741
+msgid "non-interactive mode, no prompts are used"
+msgstr "modo no-interactivo, no se pedirá usuario"
+
+#: src/parse_args.c:743
+msgid "preserve group vector instead of setting to target's"
+msgstr "preserva el vector de grupos en vez de establecer al objetivo"
+
+#: src/parse_args.c:745
+msgid "use the specified password prompt"
+msgstr "usa la contraseña especificada"
+
+#: src/parse_args.c:748
+msgid "create SELinux security context with specified role"
+msgstr "crea el contexto de seguridad SELinux con la regla especificada"
+
+#: src/parse_args.c:751
+msgid "read password from standard input"
+msgstr "lee la contraseña desde la entrada estandar"
+
+#: src/parse_args.c:753
+msgid "run shell as the target user; a command may also be specified"
+msgstr "ejecuta un intérprete de comandos como un determinado usuario, un comando también puede ser especificado"
+
+#: src/parse_args.c:756
+msgid "create SELinux security context with specified type"
+msgstr "crea el contexto de seguridad SELinux con el tipo especificado"
+
+#: src/parse_args.c:759
+msgid "terminate command after the specified time limit"
+msgstr "termina un comando luego de un límite de tiempo especificado"
+
+#: src/parse_args.c:761
+msgid "in list mode, display privileges for user"
+msgstr "en modo lista, muestra los privilegios para el usuario"
+
+#: src/parse_args.c:763
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "ejecuta un comando (o edita un archivo) como un ID o usuario específico"
+
+#: src/parse_args.c:765
+msgid "display version information and exit"
+msgstr "muestra la información de la versión y sale"
+
+#: src/parse_args.c:767
+msgid "update user's timestamp without running a command"
+msgstr "actualiza la marca del usuario sin ejecutar un comando"
+
+#: src/parse_args.c:769
+msgid "stop processing command line arguments"
+msgstr "detiene el proceso de argumentos de la línea de comandos"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "no se puede de abrir el sistema de auditoría"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "no se puede enviar mensaje de auditoría"
+
+#: src/selinux.c:121
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "no se puede fgetfilecon %s"
+
+#: src/selinux.c:126
+#, c-format
+msgid "%s changed labels"
+msgstr "%s etiquetas cambiadas"
+
+#: src/selinux.c:131
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "no se puede restaurar el contexto para %s"
+
+#: src/selinux.c:172
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "no se puede abrir %s, no volver a etiquetar tty"
+
+#: src/selinux.c:176 src/selinux.c:217 src/selinux.c:234
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s no es un dispositivo de caracter, no se reetiqueta tty"
+
+#: src/selinux.c:185
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "no se puede obtener el actual contexto tty, no volver a etiquetar tty"
+
+#: src/selinux.c:192
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "clase de seguridad desconocida \"chr_file\", tty no reetiquetada"
+
+#: src/selinux.c:197
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "no se puede obtener el nuevo contexto tty, no volver a etiquetar tty"
+
+#: src/selinux.c:204
+msgid "unable to set new tty context"
+msgstr "no se puede establecer nuevo contexto tty"
+
+#: src/selinux.c:278
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "se debe especificar una regla por tipo %s"
+
+#: src/selinux.c:284
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "no se puede obtener el tipo de regla predeterminada %s"
+
+#: src/selinux.c:302
+#, c-format
+msgid "failed to set new role %s"
+msgstr "falló al establecer nueva regla %s"
+
+#: src/selinux.c:306
+#, c-format
+msgid "failed to set new type %s"
+msgstr "falló al establecer nuevo tipo %s"
+
+#: src/selinux.c:318
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s no es un contexto válido"
+
+#: src/selinux.c:353
+msgid "failed to get old_context"
+msgstr "falló al obtener old_context"
+
+#: src/selinux.c:359
+msgid "unable to determine enforcing mode."
+msgstr "no se puede determinar el modo de forzado"
+
+#: src/selinux.c:376
+#, c-format
+msgid "unable to set tty context to %s"
+msgstr "no se puede establecer el contexto tty a %s"
+
+#: src/selinux.c:415
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "no se puede establecer el contexto de ejecución a %s"
+
+#: src/selinux.c:422
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "no se puede establecer la clave de creación de contexto a %s"
+
+#: src/sesh.c:77
+msgid "requires at least one argument"
+msgstr "requiere al menos un argumento"
+
+#: src/sesh.c:106
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "número de descriptor de archivo no válido: %s"
+
+#: src/sesh.c:120
+#, c-format
+msgid "unable to run %s as a login shell"
+msgstr "no se puede ejecutar %s como un login"
+
+#: src/signal.c:88
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "no se puede guardar el manejador para la señal %d"
+
+#: src/solaris.c:81
+msgid "resource control limit has been reached"
+msgstr "el límite de control de recursos ha sido alcanzado"
+
+#: src/solaris.c:84
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "el usuario \"%s\" no es miembro del proyecto \"%s\""
+
+#: src/solaris.c:88
+msgid "the invoking task is final"
+msgstr "la tarea que invoca es definitiva"
+
+#: src/solaris.c:91
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "no podría unirse al proyecto \"%s\""
+
+#: src/solaris.c:96
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "no hay fondo de recursos aceptando las asignaciones existentes para el proyecto \"%s\""
+
+#: src/solaris.c:100
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "el fondo de recursos especificado no existe para el proyecto \"%s\""
+
+#: src/solaris.c:104
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "no se podría enlazar al fondo de recursos predeterminado para el proyecto \"%s\" "
+
+#: src/solaris.c:110
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "configuración del proyecto fallida \"%s\" "
+
+#: src/solaris.c:112
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "aviso, el control de asignación de recursos falló para el proyecto \"%s\""
+
+#: src/sudo.c:201
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo versión %s\n"
+
+#: src/sudo.c:203
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Opciones de configuración: %s\n"
+
+#: src/sudo.c:211
+msgid "fatal error, unable to load plugins"
+msgstr "error fatal, no se puede cargar los plugins"
+
+#: src/sudo.c:219
+msgid "unable to initialize policy plugin"
+msgstr "no se puede inicializar la política de plugin"
+
+#: src/sudo.c:263
+msgid "plugin did not return a command to execute"
+msgstr "el plugin no devolvió un comando para ejecutar"
+
+#: src/sudo.c:279
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "error al inicializar los plugins de E/S %s"
+
+#: src/sudo.c:302
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "inesperado modo sudo 0x%x"
+
+#: src/sudo.c:535
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr ""
+
+#: src/sudo.c:592
+msgid "unable to determine tty"
+msgstr "no se puede deterrminar tty"
+
+#: src/sudo.c:880
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s debe ser propiedad del uid %d y tener el bit setuid establecido"
+
+#: src/sudo.c:883
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "el uid no es %d, es %s en un sistema de archivos con la opción 'nosuid' establecida o un sistema de archivos NFS sin privilegios de root?"
+
+#: src/sudo.c:889
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "el uid efectivo no es %d, sudo está instalado con setuid root?"
+
+#: src/sudo.c:942
+msgid "unable to set supplementary group IDs"
+msgstr "no se puede establecer el grupo suplementario de IDs"
+
+#: src/sudo.c:949
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "no se puede establecer el gid efectivo para ejecutar como gid %u"
+
+#: src/sudo.c:955
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "no se puede establecer el gid para ejecutar como gid %u"
+
+#: src/sudo.c:1012
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "inesperada terminación de condición hija: %d"
+
+#: src/sudo.c:1158
+#, c-format
+msgid "policy plugin %s is missing the `check_policy' method"
+msgstr "la política del plugin %s no incluye el método `check_policy' "
+
+#: src/sudo.c:1176
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "la política del plugin %s no soporta listado de privilegios"
+
+#: src/sudo.c:1193
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "la política del plugin %s no soporta la opción -v"
+
+#: src/sudo.c:1208
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "la política del plugin %s no soporta las opciones -k/-K"
+
+#: src/sudo_edit.c:219
+msgid "no writable temporary directory found"
+msgstr "no se ha encontrado directorio temporal para escritura"
+
+#: src/sudo_edit.c:286 src/sudo_edit.c:375
+msgid "unable to restore current working directory"
+msgstr "no se puede restaurar el actual directorio de trabajo"
+
+#: src/sudo_edit.c:592 src/sudo_edit.c:704
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: no es un archivo regular"
+
+#: src/sudo_edit.c:599
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: edición de enlaces simbólicos no está permitida"
+
+#: src/sudo_edit.c:602
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: no se permite la edición de archivos en un directorio con permisos de escritura"
+
+#: src/sudo_edit.c:635 src/sudo_edit.c:742
+#, c-format
+msgid "%s: short write"
+msgstr "%s: escritura corta"
+
+#: src/sudo_edit.c:705
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s sin modificar"
+
+#: src/sudo_edit.c:718 src/sudo_edit.c:903
+#, c-format
+msgid "%s unchanged"
+msgstr "%s sin cambios"
+
+#: src/sudo_edit.c:731 src/sudo_edit.c:753
+#, c-format
+msgid "unable to write to %s"
+msgstr "no se puede escribir en %s"
+
+#: src/sudo_edit.c:732 src/sudo_edit.c:751 src/sudo_edit.c:754
+#: src/sudo_edit.c:928 src/sudo_edit.c:932
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "los contenidos de edición de sesión se dejan en %s"
+
+#: src/sudo_edit.c:750
+msgid "unable to read temporary file"
+msgstr "no se puede leer el archivo temporal"
+
+#: src/sudo_edit.c:833
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: error interno: número de rutas impar"
+
+#: src/sudo_edit.c:835
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: no se puede crear archivos temporales"
+
+#: src/sudo_edit.c:837 src/sudo_edit.c:935
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: error desconocido %d"
+
+#: src/sudo_edit.c:927
+msgid "unable to copy temporary files back to their original location"
+msgstr "no se puede copiar los archivos temporales nuevamente a su ubicación original"
+
+#: src/sudo_edit.c:931
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "no se puede copiar algunos de los archivos temporales nuevamente a su ubicación original"
+
+#: src/sudo_edit.c:976
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "no se puede cambiar uid a root (%u)"
+
+#: src/sudo_edit.c:993
+msgid "plugin error: missing file list for sudoedit"
+msgstr "error de plugin: falta la lista de archivos para sudoedit"
+
+#: src/sudo_edit.c:1034 src/sudo_edit.c:1047
+msgid "unable to read the clock"
+msgstr "no se leer el reloj"
+
+#: src/tgetpass.c:101
+msgid "timed out reading password"
+msgstr ""
+
+#: src/tgetpass.c:104
+msgid "no password was provided"
+msgstr ""
+
+#: src/tgetpass.c:107
+msgid "unable to read password"
+msgstr "incapaz de leer la contraseña"
+
+#: src/tgetpass.c:141
+msgid "no tty present and no askpass program specified"
+msgstr "sin tty presente y no hay programa askpass especificado"
+
+#: src/tgetpass.c:150
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "no hay programa askpass especificado, intente establecer SUDO_ASKPASS"
+
+#: src/tgetpass.c:307
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "no se puede establecer el gid a %u"
+
+#: src/tgetpass.c:311
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "no se puede establecer el uid a %u"
+
+#: src/tgetpass.c:316
+#, c-format
+msgid "unable to run %s"
+msgstr "no se puede ejecutar %s"
+
+#: src/utmp.c:271
+msgid "unable to save stdin"
+msgstr "no se puede guardar stdin"
+
+#: src/utmp.c:273
+msgid "unable to dup2 stdin"
+msgstr "no se puede hacer dup2 stdin"
+
+#: src/utmp.c:276
+msgid "unable to restore stdin"
+msgstr "no se puede restaurar stdin"
+
+#~ msgid "unable to get group vector"
+#~ msgstr "no se puede obtener el vector de grupo"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "uid desconocido %u: quién es usted?"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "error al leer desde la tubería de la señal"
+
+#~ msgid "error reading from pipe"
+#~ msgstr "error al leer de la tubería"
+
+#~ msgid "unable to set terminal to raw mode"
+#~ msgstr "no se puede establecer la terminal en modo directo"
+
+#~ msgid "internal error, tried to emalloc(0)"
+#~ msgstr "error interno: trató emalloc(0)"
+
+#~ msgid "internal error, tried to emalloc2(0)"
+#~ msgstr "error interno: trató emalloc2(0)"
+
+#~ msgid "internal error, tried to ecalloc(0)"
+#~ msgstr "error interno: trató ecalloc(0)"
+
+#~ msgid "internal error, tried to erealloc(0)"
+#~ msgstr "error interno: trató erealloc(0)"
+
+#~ msgid "internal error, tried to erealloc3(0)"
+#~ msgstr "error interno: trató erealloc3(0)"
+
+#~ msgid "internal error, tried to erecalloc(0)"
+#~ msgstr "error interno: trató erecalloc(0)"
+
+#~ msgid "%s: %s: %s\n"
+#~ msgstr "%s:%s: %s\n"
+
+#~ msgid "%s: %s\n"
+#~ msgstr "%s: %s\n"
+
+#~ msgid "select failed"
+#~ msgstr "selección fallida"
+
+#~ msgid "load_interfaces: overflow detected"
+#~ msgstr "load_interfaces: desbordamiento detectado"
+
+#~ msgid "unable to open socket"
+#~ msgstr "no se puede de abrir socket"
+
+#~ msgid "list user's available commands\n"
+#~ msgstr "lista los comandos del usuario disponibles\n"
+
+#~ msgid "run a shell as target user\n"
+#~ msgstr "ejecuta un intérprete de comandos como un determinado usuario\n"
+
+#~ msgid "when listing, list specified user's privileges\n"
+#~ msgstr "cuando está listando, lista los privilegios del usuario especificado\n"
+
+#~ msgid ": "
+#~ msgstr ": "
+
+#~ msgid "%s: at least one policy plugin must be specified"
+#~ msgstr "%s: debe ser especificada al menos una política de plugin"
+
+#~ msgid "internal error, emalloc2() overflow"
+#~ msgstr "error interno: desbordamiento en emalloc2()"
+
+#~ msgid "internal error, erealloc3() overflow"
+#~ msgstr "error interno: desbordamiento de erealloc3()"
+
+#~ msgid "must be setuid root"
+#~ msgstr "debe ser setuid root"
+
+#~ msgid "the argument to -D must be between 1 and 9 inclusive"
+#~ msgstr "el argumento -D debe estar entre 1 y 9 inclusive"
diff --git a/po/eu.mo b/po/eu.mo
new file mode 100644
index 0000000..e50c8ff
--- /dev/null
+++ b/po/eu.mo
Binary files differ
diff --git a/po/eu.po b/po/eu.po
new file mode 100644
index 0000000..f36b0db
--- /dev/null
+++ b/po/eu.po
@@ -0,0 +1,742 @@
+# Basque translation of sudo.
+# Copyright (C) 2011 Free Software Foundation, Inc.
+# This file is distributed under the same license as the sudo package.
+# Mikel Olasagasti Uranga <mikel@olasagasti.info>, 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.8.2rc2\n"
+"Report-Msgid-Bugs-To: http://www.sudo.ws/bugs\n"
+"POT-Creation-Date: 2011-06-04 18:27-0400\n"
+"PO-Revision-Date: 2011-06-06 18:28+0100\n"
+"Last-Translator: Mikel Olasagasti Uranga <mikel@olasagasti.info>\n"
+"Language-Team: Basque <translation-team-eu@lists.sourceforge.net>\n"
+"Language: eu\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"\n"
+
+#: src/error.c:82 src/error.c:86
+msgid ": "
+msgstr ":"
+
+#: src/exec.c:125 src/exec_pty.c:573 src/exec_pty.c:880 src/tgetpass.c:224
+#, c-format
+msgid "unable to fork"
+msgstr "ezin da fork egin"
+
+#: src/exec.c:246
+#, c-format
+msgid "unable to create sockets"
+msgstr "ezin da socketik sortu"
+
+#: src/exec.c:253 src/exec_pty.c:526 src/exec_pty.c:534 src/exec_pty.c:541
+#: src/exec_pty.c:826 src/exec_pty.c:877 src/tgetpass.c:221
+#, c-format
+msgid "unable to create pipe"
+msgstr "ezin da pipe bat sortu"
+
+#: src/exec.c:319 src/exec_pty.c:944 src/exec_pty.c:1077
+#, c-format
+msgid "select failed"
+msgstr "select-ek huts egin du"
+
+#: src/exec.c:387
+#, c-format
+msgid "unable to restore tty label"
+msgstr ""
+
+#: src/exec_pty.c:136
+#, c-format
+msgid "unable to allocate pty"
+msgstr ""
+
+#: src/exec_pty.c:566
+#, c-format
+msgid "unable to set terminal to raw mode"
+msgstr ""
+
+#: src/exec_pty.c:858
+#, c-format
+msgid "unable to set controlling tty"
+msgstr ""
+
+#: src/exec_pty.c:952
+#, c-format
+msgid "error reading from signal pipe"
+msgstr "errorea seinale hoditik irakurtzean"
+
+#: src/exec_pty.c:971
+#, c-format
+msgid "error reading from pipe"
+msgstr "errorea hoditik irakurtzean"
+
+#: src/exec_pty.c:987
+#, c-format
+msgid "error reading from socketpair"
+msgstr "errorea socketpair-etik irakurtzean"
+
+#: src/exec_pty.c:991
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "espero ez zen erantzun moeta backchannel-ean: %d"
+
+#: src/load_plugins.c:154
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: src/load_plugins.c:160
+#, c-format
+msgid "%s%s: %s"
+msgstr "%s%s: %s"
+
+#: src/load_plugins.c:170
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s-(r)en jabeak %d uid-a behar du"
+
+#: src/load_plugins.c:174
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "%s jabeak bakarrik idazteko moduan behar du"
+
+#: src/load_plugins.c:181
+#, c-format
+msgid "unable to dlopen %s: %s"
+msgstr "ezin da %s-(r)engan dlopen egin: %s"
+
+#: src/load_plugins.c:186
+#, c-format
+msgid "%s: unable to find symbol %s"
+msgstr "%s: ezin da %s sinboloa aurkitu"
+
+#: src/load_plugins.c:192
+#, c-format
+msgid "%s: unknown policy type %d"
+msgstr "%s: %d arau moeta ezezaguna"
+
+#: src/load_plugins.c:196
+#, c-format
+msgid "%s: incompatible policy major version %d, expected %d"
+msgstr ""
+
+#: src/load_plugins.c:203
+#, c-format
+msgid "%s: only a single policy plugin may be loaded"
+msgstr ""
+
+#: src/load_plugins.c:221
+#, c-format
+msgid "%s: at least one policy plugin must be specified"
+msgstr ""
+
+#: src/load_plugins.c:226
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr ""
+
+#: src/net_ifs.c:155 src/net_ifs.c:164 src/net_ifs.c:176 src/net_ifs.c:185
+#: src/net_ifs.c:295 src/net_ifs.c:319
+#, c-format
+msgid "load_interfaces: overflow detected"
+msgstr "load_interfaces: overflow-a atzeman da"
+
+#: src/net_ifs.c:224
+#, c-format
+msgid "unable to open socket"
+msgstr "ezin da socket-a ireki"
+
+#: src/parse_args.c:180
+#, c-format
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "-C argumentuak 3 edo zenbaki altuagoa behar du"
+
+#: src/parse_args.c:192
+#, c-format
+msgid "the argument to -D must be between 1 and 9 inclusive"
+msgstr "-D argumentua 1 eta 9 bitartean behar du, biak barne"
+
+#: src/parse_args.c:273
+#, c-format
+msgid "unknown user: %s"
+msgstr "erabiltzaile ezezaguna: %s"
+
+#: src/parse_args.c:332
+#, c-format
+msgid "you may not specify both the `-i' and `-s' options"
+msgstr "ez zenituzke `-i' eta `-s' aukerak batera erabili behar"
+
+#: src/parse_args.c:336
+#, c-format
+msgid "you may not specify both the `-i' and `-E' options"
+msgstr "ez zenitzuke `-i' eta `-E' aukerak batera erabili behar"
+
+#: src/parse_args.c:346
+#, c-format
+msgid "the `-E' option is not valid in edit mode"
+msgstr "`-E' aukera ez da onartzen edizio moduan"
+
+#: src/parse_args.c:348
+#, c-format
+msgid "you may not specify environment variables in edit mode"
+msgstr "ez zenuke ingurune aldagairik zehaztu beharko edizio moduan"
+
+#: src/parse_args.c:356
+#, c-format
+msgid "the `-U' option may only be used with the `-l' option"
+msgstr "`-U' aukera `-l' aukerarekin erabili beharko zenuke soilik"
+
+#: src/parse_args.c:360
+#, c-format
+msgid "the `-A' and `-S' options may not be used together"
+msgstr "`-A' eta `-S' aukerak ez lirateke batera erabili beharko"
+
+#: src/parse_args.c:418 src/sudo.c:398 src/sudo.c:418 src/sudo.c:426
+#: src/sudo.c:436 common/alloc.c:85 common/alloc.c:105 common/alloc.c:123
+#: common/alloc.c:145 common/alloc.c:203 common/alloc.c:217
+#, c-format
+msgid "unable to allocate memory"
+msgstr "ezin da memoria esleitu"
+
+#: src/parse_args.c:431
+#, c-format
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit-ek ez du euskarririk plataforma hontan"
+
+#: src/parse_args.c:502
+#, c-format
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Soilik -e, -h, -i, -K, -l, -s, -v edo -V aukeretako bat definitu beharko litzateke"
+
+#: src/parse_args.c:515
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - editatu fitxategia beste erabiltzaile bat bezala\n"
+"\n"
+
+#: src/parse_args.c:517
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - exekutatu komandu bat beste erabiltzaile bat bezala\n"
+"\n"
+
+#: src/parse_args.c:522
+#, c-format
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Aukerak:\n"
+
+#: src/parse_args.c:525
+msgid "use helper program for password prompting\n"
+msgstr ""
+
+#: src/parse_args.c:528
+msgid "use specified BSD authentication type\n"
+msgstr ""
+
+#: src/parse_args.c:530
+msgid "run command in the background\n"
+msgstr ""
+
+#: src/parse_args.c:532
+msgid "close all file descriptors >= fd\n"
+msgstr ""
+
+#: src/parse_args.c:535
+msgid "run command with specified login class\n"
+msgstr ""
+
+#: src/parse_args.c:538
+msgid "preserve user environment when executing command\n"
+msgstr ""
+
+#: src/parse_args.c:540
+msgid "edit files instead of running a command\n"
+msgstr ""
+
+#: src/parse_args.c:542
+msgid "execute command as the specified group\n"
+msgstr ""
+
+#: src/parse_args.c:544
+msgid "set HOME variable to target user's home dir.\n"
+msgstr ""
+
+#: src/parse_args.c:546
+msgid "display help message and exit\n"
+msgstr "laguntza mezua erakutsi eta irten\n"
+
+#: src/parse_args.c:548
+msgid "run a login shell as target user\n"
+msgstr "abiarazi login shell bat helburua den erabiltzaile moduan\n"
+
+#: src/parse_args.c:550
+msgid "remove timestamp file completely\n"
+msgstr "ezabatu guztiz data-zigilu fitxategia\n"
+
+#: src/parse_args.c:552
+msgid "invalidate timestamp file\n"
+msgstr "baliogabetu data-zigilu fitxategia\n"
+
+#: src/parse_args.c:554
+msgid "list user's available commands\n"
+msgstr "zerrendatu erabiltzaileak eskuragarri dituen komandoak\n"
+
+#: src/parse_args.c:556
+msgid "non-interactive mode, will not prompt user\n"
+msgstr ""
+
+#: src/parse_args.c:558
+msgid "preserve group vector instead of setting to target's\n"
+msgstr ""
+
+#: src/parse_args.c:560
+msgid "use specified password prompt\n"
+msgstr ""
+
+#: src/parse_args.c:563 src/parse_args.c:571
+msgid "create SELinux security context with specified role\n"
+msgstr ""
+
+#: src/parse_args.c:566
+msgid "read password from standard input\n"
+msgstr ""
+
+#: src/parse_args.c:568
+msgid "run a shell as target user\n"
+msgstr ""
+
+#: src/parse_args.c:574
+msgid "when listing, list specified user's privileges\n"
+msgstr ""
+
+#: src/parse_args.c:576
+msgid "run command (or edit file) as specified user\n"
+msgstr ""
+
+#: src/parse_args.c:578
+msgid "display version information and exit\n"
+msgstr ""
+
+#: src/parse_args.c:580
+msgid "update user's timestamp without running a command\n"
+msgstr ""
+
+#: src/parse_args.c:582
+msgid "stop processing command line arguments\n"
+msgstr ""
+
+#: src/selinux.c:75
+#, c-format
+msgid "unable to open audit system"
+msgstr ""
+
+#: src/selinux.c:85
+#, c-format
+msgid "unable to send audit message"
+msgstr ""
+
+#: src/selinux.c:112
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "ezin da %s-(r)engan fgetfilecon egin"
+
+#: src/selinux.c:117
+#, c-format
+msgid "%s changed labels"
+msgstr ""
+
+#: src/selinux.c:122
+#, c-format
+msgid "unable to restore context for %s"
+msgstr ""
+
+#: src/selinux.c:161
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:170
+#, c-format
+msgid "unable to get current tty context, not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:177
+#, c-format
+msgid "unable to get new tty context, not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:184
+#, c-format
+msgid "unable to set new tty context"
+msgstr ""
+
+#: src/selinux.c:194 src/selinux.c:207 src/sudo.c:330
+#, c-format
+msgid "unable to open %s"
+msgstr ""
+
+#: src/selinux.c:249
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr ""
+
+#: src/selinux.c:255
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr ""
+
+#: src/selinux.c:273
+#, c-format
+msgid "failed to set new role %s"
+msgstr ""
+
+#: src/selinux.c:277
+#, c-format
+msgid "failed to set new type %s"
+msgstr ""
+
+#: src/selinux.c:286
+#, c-format
+msgid "%s is not a valid context"
+msgstr ""
+
+#: src/selinux.c:320
+#, c-format
+msgid "failed to get old_context"
+msgstr ""
+
+#: src/selinux.c:326
+#, c-format
+msgid "unable to determine enforcing mode."
+msgstr ""
+
+#: src/selinux.c:338
+#, c-format
+msgid "unable to setup tty context for %s"
+msgstr ""
+
+#: src/selinux.c:367
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr ""
+
+#: src/selinux.c:374
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr ""
+
+#: src/sesh.c:48
+msgid "requires at least one argument"
+msgstr "gutxienez argumentu bat behar du"
+
+#: src/sesh.c:64
+#, c-format
+msgid "unable to execute %s"
+msgstr "ezin da %s exekutatu"
+
+#: src/sudo.c:192
+#, c-format
+msgid "must be setuid root"
+msgstr "root setuid-a behar du"
+
+#: src/sudo.c:210
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "%s sudo bertsioa\n"
+
+#: src/sudo.c:212
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Konfigurazio aukerak: %s\n"
+
+#: src/sudo.c:217
+#, c-format
+msgid "fatal error, unable to load plugins"
+msgstr "errore larria, ezin dira gehigarriak gehitu"
+
+#: src/sudo.c:225
+#, c-format
+msgid "unable to initialize policy plugin"
+msgstr ""
+
+#: src/sudo.c:280
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "errorea %s I/O plugina abiaraztean"
+
+#: src/sudo.c:307
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr ""
+
+#: src/sudo.c:356
+#, c-format
+msgid "unable to get group vector"
+msgstr ""
+
+#: src/sudo.c:394
+#, c-format
+msgid "unknown uid %u: who are you?"
+msgstr ""
+
+#: src/sudo.c:734
+#, c-format
+msgid "resource control limit has been reached"
+msgstr ""
+
+#: src/sudo.c:737
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr ""
+
+#: src/sudo.c:741
+#, c-format
+msgid "the invoking task is final"
+msgstr ""
+
+#: src/sudo.c:744
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "ezin izan da \"%s\" proiektura batu"
+
+#: src/sudo.c:749
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr ""
+
+#: src/sudo.c:753
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr ""
+
+#: src/sudo.c:757
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr ""
+
+#: src/sudo.c:763
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "setproject-ek huts egin du \"%s\" proiektuarentzat"
+
+#: src/sudo.c:765
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr ""
+
+#: src/sudo.c:791
+#, c-format
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr ""
+
+#: src/sudo.c:895
+#, c-format
+msgid "unknown login class %s"
+msgstr ""
+
+#: src/sudo.c:902 src/sudo.c:905
+#, c-format
+msgid "unable to set user context"
+msgstr ""
+
+#: src/sudo.c:916
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr ""
+
+#: src/sudo.c:921
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr ""
+
+#: src/sudo.c:929 src/sudo.c:935
+#, c-format
+msgid "unable to set supplementary group IDs"
+msgstr ""
+
+#: src/sudo.c:943
+#, c-format
+msgid "unable to set process priority"
+msgstr ""
+
+#: src/sudo.c:951
+#, c-format
+msgid "unable to change root to %s"
+msgstr ""
+
+#: src/sudo.c:961 src/sudo.c:967 src/sudo.c:973
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr ""
+
+#: src/sudo.c:987
+#, c-format
+msgid "unable to change directory to %s"
+msgstr ""
+
+#: src/sudo.c:1078
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr ""
+
+#: src/sudo.c:1118
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr ""
+
+#: src/sudo.c:1129
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr ""
+
+#: src/sudo.c:1140
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr ""
+
+#: src/sudo_edit.c:108
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "ezin da uid-a root-era aldatu (%u)"
+
+#: src/sudo_edit.c:140
+#, c-format
+msgid "plugin error: missing file list for sudoedit"
+msgstr ""
+
+#: src/sudo_edit.c:172 src/sudo_edit.c:280
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: ez da fitxategi normala"
+
+#: src/sudo_edit.c:206 src/sudo_edit.c:316
+#, c-format
+msgid "%s: short write"
+msgstr ""
+
+#: src/sudo_edit.c:281
+#, c-format
+msgid "%s left unmodified"
+msgstr ""
+
+#: src/sudo_edit.c:294
+#, c-format
+msgid "%s unchanged"
+msgstr "%s aldatugabea"
+
+#: src/sudo_edit.c:306 src/sudo_edit.c:327
+#, c-format
+msgid "unable to write to %s"
+msgstr "ezin da %s-(e)ra idatzi"
+
+#: src/sudo_edit.c:307 src/sudo_edit.c:325 src/sudo_edit.c:328
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr ""
+
+#: src/sudo_edit.c:324
+#, c-format
+msgid "unable to read temporary file"
+msgstr "ezin da aldi baterako fitxategia irakurri"
+
+#: src/tgetpass.c:95
+#, c-format
+msgid "no tty present and no askpass program specified"
+msgstr "ez dago tty-rik eta askpass aplikazioa zehaztu gabe"
+
+#: src/tgetpass.c:104
+#, c-format
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "ez da askpass aplikaziorik zehaztu, saiatu SUDO_ASKPASS ezartzen"
+
+#: src/tgetpass.c:234
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "ezin da %u gid-a ezarri"
+
+#: src/tgetpass.c:238
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "ezin da %u uid-a ezarri"
+
+#: src/tgetpass.c:243
+#, c-format
+msgid "unable to run %s"
+msgstr "ezin da %s exekutatu"
+
+#: src/utmp.c:263
+#, c-format
+msgid "unable to save stdin"
+msgstr "ezin da stdin-era gorde"
+
+#: src/utmp.c:265
+#, c-format
+msgid "unable to dup2 stdin"
+msgstr "ezin da stdin-era dup2 egin"
+
+#: src/utmp.c:268
+#, c-format
+msgid "unable to restore stdin"
+msgstr "ezin da stdin-era leheneratu"
+
+#: common/aix.c:144
+#, c-format
+msgid "unable to open userdb"
+msgstr "ezin da userdb-a ireki"
+
+#: common/aix.c:147
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "ezin da \"%s\" erregistrora aldatu %s-(r)entzat"
+
+#: common/aix.c:161
+#, c-format
+msgid "unable to restore registry"
+msgstr "ezin da erregistroa leheneratu"
+
+#: common/alloc.c:82
+#, c-format
+msgid "internal error, tried to emalloc(0)"
+msgstr "barne errorea, emalloc(0) egiteko saiakera egon da"
+
+#: common/alloc.c:99
+#, c-format
+msgid "internal error, tried to emalloc2(0)"
+msgstr "barne errorea, emalloc2(0) egiteko saiakera egon da"
+
+#: common/alloc.c:101
+#, c-format
+msgid "internal error, emalloc2() overflow"
+msgstr "barne errorea, emalloc2() overflow-a"
+
+#: common/alloc.c:119
+#, c-format
+msgid "internal error, tried to erealloc(0)"
+msgstr "barne errorea, erealloc(0) egiteko saiakera egon da"
+
+#: common/alloc.c:138
+#, c-format
+msgid "internal error, tried to erealloc3(0)"
+msgstr "barne errorea, erealloc3(0) egiteko saiakera egon da"
+
+#: common/alloc.c:140
+#, c-format
+msgid "internal error, erealloc3() overflow"
+msgstr "barne errorea, erealloc3(0) overflow-a"
+
+#: compat/strsignal.c:47
+msgid "Unknown signal"
+msgstr "Seinale ezezaguna"
diff --git a/po/fa.mo b/po/fa.mo
new file mode 100644
index 0000000..7adde20
--- /dev/null
+++ b/po/fa.mo
Binary files differ
diff --git a/po/fa.po b/po/fa.po
new file mode 100644
index 0000000..f4836ab
--- /dev/null
+++ b/po/fa.po
@@ -0,0 +1,1085 @@
+# Portable object template file for sudo
+# This file is put in the public domain.
+# Todd C. Miller <Todd.Miller@sudo.ws>, 2011-2018
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.8b2\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2021-08-16 10:46-0600\n"
+"PO-Revision-Date: 2021-12-01 18:40+0330\n"
+"Last-Translator: eshagh <eshagh094@gmail.com>\n"
+"Language-Team: Persian <translation-team-fa@lists.sourceforge.net>\n"
+"Language: fa\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 3.0\n"
+"Plural-Forms: nplurals=2; plural=(n==0 || n==1);\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "نمی‌توان پایگاه دادهٔ کاربر را گشود"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "نمی‌توان ریجستری را به «%s» برای %s تعویض کرد"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "نمی‌توان ریجستری را بازگرداند"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:54 lib/util/json.c:183 lib/util/sudo_conf.c:211
+#: lib/util/sudo_conf.c:297 lib/util/sudo_conf.c:374 lib/util/sudo_conf.c:658
+#: src/conversation.c:80 src/exec_monitor.c:206 src/exec_monitor.c:456
+#: src/exec_monitor.c:462 src/exec_monitor.c:470 src/exec_monitor.c:478
+#: src/exec_monitor.c:485 src/exec_monitor.c:492 src/exec_monitor.c:499
+#: src/exec_monitor.c:506 src/exec_monitor.c:513 src/exec_monitor.c:520
+#: src/exec_monitor.c:527 src/exec_nopty.c:225 src/exec_nopty.c:235
+#: src/exec_nopty.c:245 src/exec_nopty.c:252 src/exec_nopty.c:259
+#: src/exec_nopty.c:266 src/exec_nopty.c:273 src/exec_nopty.c:280
+#: src/exec_nopty.c:287 src/exec_nopty.c:294 src/exec_nopty.c:301
+#: src/exec_nopty.c:308 src/exec_nopty.c:315 src/exec_nopty.c:323
+#: src/exec_nopty.c:511 src/exec_preload.c:143 src/exec_preload.c:203
+#: src/exec_pty.c:844 src/exec_pty.c:853 src/exec_pty.c:910
+#: src/exec_pty.c:1063 src/exec_pty.c:1237 src/exec_pty.c:1247
+#: src/exec_pty.c:1257 src/exec_pty.c:1264 src/exec_pty.c:1271
+#: src/exec_pty.c:1278 src/exec_pty.c:1285 src/exec_pty.c:1292
+#: src/exec_pty.c:1299 src/exec_pty.c:1306 src/exec_pty.c:1313
+#: src/exec_pty.c:1320 src/exec_pty.c:1328 src/exec_pty.c:1782
+#: src/load_plugins.c:156 src/load_plugins.c:181 src/load_plugins.c:217
+#: src/load_plugins.c:449 src/load_plugins.c:455 src/parse_args.c:190
+#: src/parse_args.c:211 src/parse_args.c:285 src/parse_args.c:630
+#: src/parse_args.c:652 src/parse_args.c:677 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:90 src/selinux.c:360 src/selinux.c:489
+#: src/selinux.c:498 src/sesh.c:113 src/sesh.c:146 src/sesh.c:152
+#: src/sesh.c:159 src/sesh.c:165 src/sesh.c:410 src/sudo.c:636 src/sudo.c:706
+#: src/sudo.c:716 src/sudo.c:741 src/sudo.c:760 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:795 src/sudo.c:837 src/sudo.c:847 src/sudo.c:876 src/sudo.c:1061
+#: src/sudo.c:1082 src/sudo.c:1374 src/sudo.c:1543 src/sudo.c:1770
+#: src/sudo.c:2104 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:429
+#: src/sudo_edit.c:438 src/sudo_edit.c:539 src/sudo_edit.c:546
+#: src/sudo_edit.c:686 src/sudo_edit.c:706 src/sudo_intercept_common.c:160
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:55
+#: lib/util/json.c:184 lib/util/sudo_conf.c:212 lib/util/sudo_conf.c:297
+#: lib/util/sudo_conf.c:374 lib/util/sudo_conf.c:658 src/conversation.c:81
+#: src/exec_intercept.c:154 src/exec_intercept.c:181 src/exec_intercept.c:204
+#: src/exec_intercept.c:225 src/exec_intercept.c:231 src/exec_intercept.c:240
+#: src/exec_intercept.c:246 src/exec_intercept.c:312 src/exec_intercept.c:407
+#: src/exec_intercept.c:627 src/exec_monitor.c:456 src/exec_monitor.c:462
+#: src/exec_monitor.c:470 src/exec_monitor.c:478 src/exec_monitor.c:485
+#: src/exec_monitor.c:492 src/exec_monitor.c:499 src/exec_monitor.c:506
+#: src/exec_monitor.c:513 src/exec_monitor.c:520 src/exec_monitor.c:527
+#: src/exec_nopty.c:225 src/exec_nopty.c:235 src/exec_nopty.c:245
+#: src/exec_nopty.c:252 src/exec_nopty.c:259 src/exec_nopty.c:266
+#: src/exec_nopty.c:273 src/exec_nopty.c:280 src/exec_nopty.c:287
+#: src/exec_nopty.c:294 src/exec_nopty.c:301 src/exec_nopty.c:308
+#: src/exec_nopty.c:315 src/exec_nopty.c:323 src/exec_preload.c:143
+#: src/exec_preload.c:203 src/exec_pty.c:844 src/exec_pty.c:853
+#: src/exec_pty.c:910 src/exec_pty.c:1237 src/exec_pty.c:1247
+#: src/exec_pty.c:1257 src/exec_pty.c:1264 src/exec_pty.c:1271
+#: src/exec_pty.c:1278 src/exec_pty.c:1285 src/exec_pty.c:1292
+#: src/exec_pty.c:1299 src/exec_pty.c:1306 src/exec_pty.c:1313
+#: src/exec_pty.c:1320 src/exec_pty.c:1328 src/exec_pty.c:1782
+#: src/load_plugins.c:156 src/load_plugins.c:181 src/load_plugins.c:217
+#: src/load_plugins.c:449 src/load_plugins.c:455 src/parse_args.c:190
+#: src/parse_args.c:212 src/parse_args.c:285 src/parse_args.c:630
+#: src/parse_args.c:652 src/parse_args.c:677 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:90 src/selinux.c:360 src/selinux.c:489
+#: src/selinux.c:498 src/sesh.c:113 src/sesh.c:411 src/sudo.c:227
+#: src/sudo.c:636 src/sudo.c:876 src/sudo.c:1061 src/sudo.c:1082
+#: src/sudo.c:1374 src/sudo.c:1543 src/sudo.c:1770 src/sudo.c:2104
+#: src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:429
+#: src/sudo_edit.c:438 src/sudo_edit.c:539 src/sudo_edit.c:546
+#: src/sudo_edit.c:686 src/sudo_edit.c:706 src/sudo_intercept_common.c:160
+msgid "unable to allocate memory"
+msgstr "نمی‌توان حافظه را تخصیص داد"
+
+#: lib/util/mkdir_parents.c:69 lib/util/sudo_conf.c:697 src/selinux.c:234
+#: src/selinux.c:264 src/sudo.c:368 src/sudo_edit.c:494 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "نمی‌توان %s را گشود"
+
+#: lib/util/mkdir_parents.c:84
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "نمی‌توان شاخهٔ %s را ایجاد کرد"
+
+#: lib/util/mkdir_parents.c:93 lib/util/sudo_conf.c:674 src/copy_file.c:150
+#, fuzzy, c-format
+msgid "unable to stat %s"
+msgstr "ناتوان در وضعیت %s"
+
+#: lib/util/mkdir_parents.c:98
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s وجود دارد ولی یک شاخه نیست (0%o)"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "سیگنال ناشناخته"
+
+#: lib/util/strtoid.c:87 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:146 src/sesh.c:159
+msgid "invalid value"
+msgstr "مقدار نامعتبر"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "مقدار بسیار بزرگ است"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "مقدار بسیار کوچک است"
+
+#: lib/util/sudo_conf.c:230
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "مقدار مسیر نامعتبر «%s» در %s، خط %u"
+
+#: lib/util/sudo_conf.c:396 lib/util/sudo_conf.c:412 lib/util/sudo_conf.c:465
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "مقدار نامعتبر برای %s «%s» در %s، خط %u"
+
+#: lib/util/sudo_conf.c:433
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "گروه منبع پشتیبانی نشدهٔ «%s» در %s، خط %u"
+
+#: lib/util/sudo_conf.c:449
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "بیشینهٔ گروه‌های نامعتبر «%s» در %s، خط %u"
+
+#: lib/util/sudo_conf.c:677
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s یک پروندهٔ معمولی نیست"
+
+#: lib/util/sudo_conf.c:680 src/copy_file.c:163
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr ""
+
+#: lib/util/sudo_conf.c:684
+#, c-format
+msgid "%s is world writable"
+msgstr "مورد %s توسط همه قابل نوشتن است"
+
+#: lib/util/sudo_conf.c:687
+#, c-format
+msgid "%s is group writable"
+msgstr "مورد %s توسط گروه قابل نوشتن است"
+
+# در این رشته از نویسه ایزوله اولین نویسهٔ قوی استفاده شده است
+#: src/copy_file.c:93
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: پروندهٔ ⁨%s⁩ به صفر بایت کوتاه شود؟ (y/n) [n] "
+
+# در این رشته از نویسه ایزوله اولین نویسهٔ قوی استفاده شده است
+#: src/copy_file.c:97
+#, c-format
+msgid "not overwriting %s"
+msgstr "پروندهٔ ⁨%s⁩ بازنویسی نشد"
+
+#: src/copy_file.c:119
+#, c-format
+msgid "unable to read from %s"
+msgstr "خواندن از %s ممکن نیست"
+
+#: src/copy_file.c:136 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "نوشتن به %s ممکن نیست"
+
+#: src/copy_file.c:154 src/sesh.c:218 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: یک پرونده معمولی نیست"
+
+# در این رشته از نویسه ایزوله چپ‌به‌راست استفاده شده است
+#: src/copy_file.c:158
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: حالت پرونده بد: ⁦0%o⁩"
+
+#: src/edit_open.c:265
+msgid "unable to restore current working directory"
+msgstr "نمی‌توان شاخه کاری فعلی را بازگرداند"
+
+#: src/exec.c:130
+#, c-format
+msgid "unknown login class %s"
+msgstr "کلاس ورود ناشناختهٔ %s"
+
+#: src/exec.c:142
+msgid "unable to set user context"
+msgstr "نمی‌توان مفاد کاربر را تنظیم کرد"
+
+#: src/exec.c:158
+msgid "unable to set process priority"
+msgstr ""
+
+#: src/exec.c:172
+#, c-format
+msgid "unable to change root to %s"
+msgstr "نمی‌توان روت را به %s تغییر داد"
+
+#: src/exec.c:185 src/exec.c:191 src/exec.c:198
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr ""
+
+#: src/exec.c:216
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "نمی‌توان شاخه را به %s تغییر داد"
+
+#: src/exec.c:220
+#, c-format
+msgid "starting from %s"
+msgstr "شروع از %s"
+
+#: src/exec.c:302 src/exec_monitor.c:565 src/exec_monitor.c:567
+#: src/exec_nopty.c:569 src/exec_pty.c:585 src/exec_pty.c:1425
+#: src/exec_pty.c:1427 src/signal.c:144 src/signal.c:151 src/signal.c:165
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr ""
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr ""
+
+#: src/exec_common.c:85
+msgid "unable to dup intercept fd"
+msgstr ""
+
+#: src/exec_intercept.c:138
+msgid "invalid PolicyCheckRequest"
+msgstr ""
+
+#: src/exec_intercept.c:191 src/sudo.c:1187 src/sudo.c:1232 src/sudo.c:1276
+msgid "command rejected by policy"
+msgstr "دستور توسط خط‌مشی رد شد"
+
+#: src/exec_intercept.c:272 src/sudo.c:1192 src/sudo.c:1237 src/sudo.c:1281
+#: src/sudo.c:1355
+msgid "policy plugin error"
+msgstr "خطای افزایهٔ خط‌مشی"
+
+#: src/exec_intercept.c:304
+#, c-format
+msgid "client message too large: %zu"
+msgstr "پیام کارخواه بسیار بزرگ: %zu"
+
+#: src/exec_intercept.c:340
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr ""
+
+#: src/exec_intercept.c:367 src/exec_intercept.c:371 src/exec_intercept.c:634
+#: src/exec_intercept.c:638 src/exec_monitor.c:464 src/exec_monitor.c:472
+#: src/exec_monitor.c:480 src/exec_monitor.c:487 src/exec_monitor.c:494
+#: src/exec_monitor.c:501 src/exec_monitor.c:508 src/exec_monitor.c:515
+#: src/exec_monitor.c:522 src/exec_monitor.c:529 src/exec_nopty.c:227
+#: src/exec_nopty.c:237 src/exec_nopty.c:247 src/exec_nopty.c:254
+#: src/exec_nopty.c:261 src/exec_nopty.c:268 src/exec_nopty.c:275
+#: src/exec_nopty.c:282 src/exec_nopty.c:289 src/exec_nopty.c:296
+#: src/exec_nopty.c:303 src/exec_nopty.c:310 src/exec_nopty.c:317
+#: src/exec_nopty.c:325 src/exec_pty.c:710 src/exec_pty.c:715
+#: src/exec_pty.c:812 src/exec_pty.c:819 src/exec_pty.c:916
+#: src/exec_pty.c:1239 src/exec_pty.c:1249 src/exec_pty.c:1259
+#: src/exec_pty.c:1266 src/exec_pty.c:1273 src/exec_pty.c:1280
+#: src/exec_pty.c:1287 src/exec_pty.c:1294 src/exec_pty.c:1301
+#: src/exec_pty.c:1308 src/exec_pty.c:1315 src/exec_pty.c:1322
+#: src/exec_pty.c:1735 src/exec_pty.c:1745 src/exec_pty.c:1790
+#: src/exec_pty.c:1797 src/exec_pty.c:1824
+msgid "unable to add event to queue"
+msgstr "نمی‌توان رویداد را به صف افزود"
+
+#: src/exec_intercept.c:395
+#, c-format
+msgid "server message too large: %zu"
+msgstr "پیام کارساز بسیار بزرگ: %zu"
+
+#: src/exec_intercept.c:608 src/exec_intercept.c:620
+#, c-format
+msgid "%s: missing message header"
+msgstr "%s: سرایند پیام گمشده"
+
+#: src/exec_intercept.c:613
+#, c-format
+msgid "%s: expected message type %d, got %d"
+msgstr ""
+
+#: src/exec_monitor.c:360
+msgid "error reading from socketpair"
+msgstr ""
+
+#: src/exec_monitor.c:377
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr ""
+
+#: src/exec_monitor.c:583
+msgid "unable to set controlling tty"
+msgstr ""
+
+#: src/exec_monitor.c:591 src/exec_nopty.c:383 src/exec_pty.c:1504
+#: src/exec_pty.c:1525 src/exec_pty.c:1545 src/tgetpass.c:307
+msgid "unable to create pipe"
+msgstr "نمی‌توان لوله را ایجاد کرد"
+
+#: src/exec_monitor.c:601
+msgid "unable to receive message from parent"
+msgstr "نمی‌توان پیام را از والد گرفت"
+
+#: src/exec_monitor.c:617 src/exec_nopty.c:421 src/exec_pty.c:1583
+#: src/sudo_edit.c:361 src/tgetpass.c:311
+msgid "unable to fork"
+msgstr "نمی‌توان فورک کرد"
+
+#: src/exec_monitor.c:621 src/exec_monitor.c:722 src/exec_nopty.c:479
+msgid "unable to restore tty label"
+msgstr ""
+
+#: src/exec_monitor.c:637 src/sesh.c:123 src/sudo.c:1138
+#, c-format
+msgid "unable to execute %s"
+msgstr "نمی‌توان %s را اجرا کرد"
+
+#: src/exec_nopty.c:377 src/exec_pty.c:1434
+msgid "policy plugin failed session initialization"
+msgstr ""
+
+#: src/exec_nopty.c:391 src/exec_pty.c:1405 src/exec_pty.c:1413
+msgid "unable to create sockets"
+msgstr "نمی‌توان سوکت‌ها را ایجاد کرد"
+
+#: src/exec_nopty.c:467 src/exec_pty.c:1674
+msgid "error in event loop"
+msgstr "خطایی در حلقهٔ رویداد رخ داد"
+
+#: src/exec_nopty.c:577 src/exec_pty.c:623 src/signal.c:101
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr ""
+
+#: src/exec_pty.c:162
+msgid "unable to allocate pty"
+msgstr ""
+
+#: src/exec_pty.c:226 src/exec_pty.c:266 src/exec_pty.c:306 src/exec_pty.c:357
+#: src/exec_pty.c:408
+msgid "I/O plugin error"
+msgstr "خطای افزایهٔ ورودی/خروجی"
+
+#: src/exec_pty.c:230 src/exec_pty.c:270 src/exec_pty.c:310 src/exec_pty.c:361
+#: src/exec_pty.c:412
+msgid "command rejected by I/O plugin"
+msgstr "دستور توسط افزایهٔ ورودی/خروجی رد شد"
+
+#: src/exec_pty.c:459
+msgid "error logging suspend"
+msgstr ""
+
+#: src/exec_pty.c:493
+msgid "error changing window size"
+msgstr "هنگام تغییر اندازهٔ پنجره خطایی رخ داد"
+
+#: src/exec_pty.c:1629
+msgid "unable to send message to monitor process"
+msgstr ""
+
+#: src/load_plugins.c:108 src/load_plugins.c:122 src/load_plugins.c:128
+#: src/load_plugins.c:277 src/load_plugins.c:287 src/load_plugins.c:297
+#: src/load_plugins.c:344
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr ""
+
+#: src/load_plugins.c:124
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "مالک %s باید شناسهٔ کاربری %d باشد"
+
+#: src/load_plugins.c:130
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "%s باید فقط توسط مالک قابل نوشتن باشد"
+
+#: src/load_plugins.c:241 src/load_plugins.c:312
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr ""
+
+#: src/load_plugins.c:279
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "نمی‌توان %s را بار کرد: %s"
+
+#: src/load_plugins.c:289
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "نمی‌توان نماد «%s» را در %s یافت"
+
+#: src/load_plugins.c:299
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr ""
+
+#: src/load_plugins.c:317
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr ""
+
+#: src/load_plugins.c:320
+msgid "only a single policy plugin may be specified"
+msgstr ""
+
+#: src/load_plugins.c:346
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "گونهٔ افزایهٔ ناشناختهٔ %d در %s یافت شد"
+
+#: src/load_plugins.c:529
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr ""
+
+#: src/net_ifs.c:210 src/net_ifs.c:376 src/net_ifs.c:437 src/net_ifs.c:624
+#: src/net_ifs.c:855 src/sudo.c:483 src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr ""
+
+#: src/parse_args.c:232
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "نام متغیر محیطی نامعتبر: %s"
+
+# در این رشته از نویسه LRM استفاده شده است
+#: src/parse_args.c:335
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "آرگومان ‎-C باید عددی بزرگ‌تر یا مساوی ۳ باشد"
+
+# در این رشته از نویسه LRM استفاده شده است
+#: src/parse_args.c:566
+msgid "you may not specify both the -i and -s options"
+msgstr "شما نباید هر دو گزینهٔ ‎-i و ‎-s را مشخص کنید"
+
+# در این رشته از نویسه LRM استفاده شده است
+#: src/parse_args.c:571
+msgid "you may not specify both the -i and -E options"
+msgstr "شما نباید هر دو گزینهٔ ‎-i و ‎-E را مشخص کنید"
+
+# در این رشته از نویسه LRM استفاده شده است
+#: src/parse_args.c:581
+msgid "the -E option is not valid in edit mode"
+msgstr "گزینهٔ ‎-E در حالت ویرایش معتبر نیست"
+
+#: src/parse_args.c:584
+msgid "you may not specify environment variables in edit mode"
+msgstr "شما نباید متغیرهای محیطی را در حالت ویرایش مشخص کنید"
+
+# در این رشته از نویسه LRM استفاده شده است
+#: src/parse_args.c:594
+msgid "the -U option may only be used with the -l option"
+msgstr "گزینهٔ ‎-U باید فقط همراه گزینهٔ ‎-l استفاده شود"
+
+# در این رشته از نویسه LRM استفاده شده است
+#: src/parse_args.c:598
+msgid "the -A and -S options may not be used together"
+msgstr "گزینه‌های ‎-A و ‎-S نباید با یکدیگر استفاده شوند"
+
+#: src/parse_args.c:691
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit در این بن‌سازه پشتیبانی نمی‌شود"
+
+# در این رشته از نویسه LRM استفاده شده است
+#: src/parse_args.c:774
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "فقط یکی از گزینه‌های ‎-e, -h, -i, -K, -l, -s, -v یا ‎-V باید مشخص شود"
+
+#: src/parse_args.c:790
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - پرونده‌ها را به عنوان کاربری دیگر ویرایش کنید\n"
+"\n"
+
+#: src/parse_args.c:792
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - دستوری را به عنوان کاربری دیگر اجرا کنید\n"
+"\n"
+
+#: src/parse_args.c:798
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"گزینه‌ها:\n"
+
+#: src/parse_args.c:800
+msgid "use a helper program for password prompting"
+msgstr "از یک برنامهٔ کمکی برای اعلان گذرواژه استفاده می‌کند"
+
+#: src/parse_args.c:803
+msgid "use specified BSD authentication type"
+msgstr ""
+
+#: src/parse_args.c:807
+msgid "run command in the background"
+msgstr "دستور را در پس‌زمینه اجرا می‌کند"
+
+#: src/parse_args.c:810
+msgid "ring bell when prompting"
+msgstr "هنگام اعلان صدای زنگ پخش می‌کند"
+
+#: src/parse_args.c:812
+msgid "close all file descriptors >= num"
+msgstr "همهٔ توصیف‌گرهای پرونده >= num را می‌بندد"
+
+#: src/parse_args.c:815
+msgid "run command with the specified BSD login class"
+msgstr "دستور را همراه کلاس ورود بی‌اس‌دی مشخص‌شده اجرا می‌کند"
+
+#: src/parse_args.c:818
+msgid "change the working directory before running command"
+msgstr "پیش از اجرای دستور شاخهٔ کار را تغییر می‌دهد"
+
+#: src/parse_args.c:821
+msgid "preserve user environment when running command"
+msgstr "هنگام اجرای دستور محیط کاربر را حفظ می‌کند"
+
+#: src/parse_args.c:823
+msgid "preserve specific environment variables"
+msgstr "متغیرهای محیطی مشخص‌شده را حفظ می‌کند"
+
+#: src/parse_args.c:825
+msgid "edit files instead of running a command"
+msgstr "به‌جای اجرای یک دستور، پرونده‌ها را ویرایش می‌کند"
+
+#: src/parse_args.c:828
+msgid "run command as the specified group name or ID"
+msgstr "دستور به عنوان نام گروه یا شناسهٔ مشخص‌شده اجرا می‌شود"
+
+#: src/parse_args.c:831
+msgid "set HOME variable to target user's home dir"
+msgstr "متغیر HOME را به عنوان شاخهٔ خانهٔ کاربر هدف تنظیم می‌کند"
+
+#: src/parse_args.c:834
+msgid "display help message and exit"
+msgstr "پیام راهنما را نمایش و خارج می‌شود"
+
+#: src/parse_args.c:836
+msgid "run command on host (if supported by plugin)"
+msgstr "دستور را در میزبان اجرا می‌کند (اگر توسط افزایه پشتیبانی شود)"
+
+#: src/parse_args.c:839
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "پوسته ورود به عنوان کاربر هدف اجرا می‌شود؛ یک دستور نیز می‌تواند مشخص شود"
+
+#: src/parse_args.c:841
+msgid "remove timestamp file completely"
+msgstr "پروندهٔ مهر زمانی را به طور کامل برمی‌دارد"
+
+#: src/parse_args.c:844
+msgid "invalidate timestamp file"
+msgstr "پروندهٔ مهر زمانی را باطل می‌کند"
+
+#: src/parse_args.c:847
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "امتیازات کاربر را فهرست یا دستور مشخصی را بررسی می‌کند؛ برای قالب طولانی‌تر دو مرتبه استفاده‌اش کنید"
+
+#: src/parse_args.c:850
+msgid "non-interactive mode, no prompts are used"
+msgstr "حالت غیرتعاملی، هیچ اعلانی استفاده نمی‌شود"
+
+#: src/parse_args.c:853
+msgid "preserve group vector instead of setting to target's"
+msgstr ""
+
+#: src/parse_args.c:856
+msgid "use the specified password prompt"
+msgstr "از اعلان گذرواژهٔ مشخص‌شده استفاده می‌کند"
+
+#: src/parse_args.c:858
+msgid "change the root directory before running command"
+msgstr "پیش از اجرای دستور شاخهٔ روت را تغییر می‌دهد"
+
+#: src/parse_args.c:861
+msgid "create SELinux security context with specified role"
+msgstr ""
+
+#: src/parse_args.c:864
+msgid "read password from standard input"
+msgstr "گذرواژه را از ورودی استاندارد می‌خواند"
+
+#: src/parse_args.c:867
+msgid "run shell as the target user; a command may also be specified"
+msgstr "پوسته به عنوان کاربر هدف اجرا می‌شود؛ یک دستور نیز می‌تواند مشخص شود"
+
+#: src/parse_args.c:871
+msgid "create SELinux security context with specified type"
+msgstr ""
+
+#: src/parse_args.c:874
+msgid "terminate command after the specified time limit"
+msgstr "دستور پس از زمان مشخص‌شده خاتمه داده می‌شود"
+
+#: src/parse_args.c:877
+msgid "in list mode, display privileges for user"
+msgstr "در حالت فهرست، امتیازات کاربر نمایش داده می‌شود"
+
+#: src/parse_args.c:880
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "دستور به عنوان نام کاربر یا شناسهٔ مشخص‌شده اجرا می‌شود (یا پرونده ویرایش می‌شود)"
+
+#: src/parse_args.c:882
+msgid "display version information and exit"
+msgstr "اطّلاعات نگارش را نمایش می‌دهد و خارج می‌شود"
+
+#: src/parse_args.c:885
+msgid "update user's timestamp without running a command"
+msgstr "بدون اجرای دستوری مهر زمانی کاربر را به‌روز رسانی می‌کند"
+
+#: src/parse_args.c:888
+msgid "stop processing command line arguments"
+msgstr "پردازش آرگومان‌های خط فرمان را متوقّف می‌کند"
+
+#: src/selinux.c:84
+msgid "unable to open audit system"
+msgstr ""
+
+#: src/selinux.c:94
+msgid "unable to send audit message"
+msgstr ""
+
+#: src/selinux.c:128
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr ""
+
+#: src/selinux.c:133
+#, c-format
+msgid "%s changed labels"
+msgstr ""
+
+#: src/selinux.c:141
+#, c-format
+msgid "unable to restore context for %s"
+msgstr ""
+
+#: src/selinux.c:189
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:193 src/selinux.c:238 src/selinux.c:268
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:202
+msgid "unable to get current tty context, not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:209
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:214
+msgid "unable to get new tty context, not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:223
+msgid "unable to set new tty context"
+msgstr ""
+
+#: src/selinux.c:321
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr ""
+
+#: src/selinux.c:327
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr ""
+
+#: src/selinux.c:339
+msgid "failed to get new context"
+msgstr ""
+
+#: src/selinux.c:348
+#, c-format
+msgid "failed to set new role %s"
+msgstr ""
+
+#: src/selinux.c:352
+#, c-format
+msgid "failed to set new type %s"
+msgstr ""
+
+#: src/selinux.c:364
+#, c-format
+msgid "%s is not a valid context"
+msgstr ""
+
+#: src/selinux.c:396
+msgid "failed to get old context"
+msgstr ""
+
+#: src/selinux.c:402
+msgid "unable to determine enforcing mode."
+msgstr ""
+
+#: src/selinux.c:419
+#, c-format
+msgid "unable to set tty context to %s"
+msgstr ""
+
+#: src/selinux.c:440
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr ""
+
+#: src/selinux.c:447
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr ""
+
+#: src/sesh.c:72
+msgid "requires at least one argument"
+msgstr "حداقل به یک آرگومان نیاز است"
+
+#: src/sesh.c:104
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "شمارهٔ توصیف‌گر پرونده نامعتبر: %s"
+
+#: src/sesh.c:118
+#, c-format
+msgid "unable to run %s as a login shell"
+msgstr "اجرای %s به عنوان یک پوستهٔ ورود، ممکن نیست"
+
+#: src/sesh.c:200 src/sesh.c:300 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: ویرایش پیوندهای نمادین مجاز نیست"
+
+#: src/sesh.c:203 src/sesh.c:303 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: ویرایش پرونده‌ها در یک شاخهٔ قابل نوشتن مجاز نیست"
+
+#: src/sesh.c:287 src/sesh.c:308 src/sesh.c:317 src/sesh.c:325
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr ""
+
+#: src/sesh.c:416 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "ناتوان در دریافت فهرست گروه"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr ""
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr ""
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "کاربر «%s» عضوی از پروژهٔ «%s» نیست"
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr ""
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr ""
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr ""
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr ""
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr ""
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr ""
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr ""
+
+#: src/sudo.c:213
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "نگارش Sudo %s\n"
+
+#: src/sudo.c:215
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "گزینه‌های پیکربندی: %s\n"
+
+#: src/sudo.c:223
+msgid "fatal error, unable to load plugins"
+msgstr "خطای مرگبار، بار کردن افزایه‌ها ممکن نیست"
+
+#: src/sudo.c:269
+msgid "plugin did not return a command to execute"
+msgstr "افزایه دستوری برای اجرا برنگرداند"
+
+#: src/sudo.c:302
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr ""
+
+#: src/sudo.c:550
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "شما در پایگاه دادهٔ %s وجود ندارید"
+
+#: src/sudo.c:607
+msgid "unable to determine tty"
+msgstr ""
+
+#: src/sudo.c:922
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "مالک %s باید شناسهٔ کاربری %d باشد و بیت setuid نیز تنظیم شده باشد"
+
+#: src/sudo.c:925
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr ""
+
+#: src/sudo.c:931
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr ""
+
+#: src/sudo.c:947 src/tgetpass.c:333
+msgid "unable to set supplementary group IDs"
+msgstr ""
+
+#: src/sudo.c:954
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr ""
+
+#: src/sudo.c:960
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr ""
+
+#: src/sudo.c:1003
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr ""
+
+#: src/sudo.c:1110
+msgid "unable to initialize policy plugin"
+msgstr ""
+
+#: src/sudo.c:1172
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr ""
+
+#: src/sudo.c:1218
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr ""
+
+#: src/sudo.c:1262
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr ""
+
+#: src/sudo.c:1300
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr ""
+
+#: src/sudo.c:1428
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr ""
+
+#: src/sudo.c:1431
+msgid "error initializing I/O plugin"
+msgstr ""
+
+#: src/sudo.c:1580
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr ""
+
+#: src/sudo.c:1659
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr ""
+
+#: src/sudo.c:1695
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr ""
+
+#: src/sudo.c:1700 src/sudo.c:1738
+msgid "audit plugin error"
+msgstr ""
+
+#: src/sudo.c:1733
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr ""
+
+#: src/sudo.c:1793
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr ""
+
+#: src/sudo.c:1863
+msgid "command rejected by approver"
+msgstr ""
+
+#: src/sudo.c:1873
+msgid "approval plugin error"
+msgstr ""
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "هیچ شاخهٔ موقّتی قابل نوشتنی یافت نشد"
+
+#: src/sudo_edit.c:291
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s بدون تغییر باقی‌ماند"
+
+#: src/sudo_edit.c:304 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s تغییر نکرد"
+
+#: src/sudo_edit.c:481
+msgid "sesh: internal error: odd number of paths"
+msgstr ""
+
+#: src/sudo_edit.c:483
+msgid "sesh: unable to create temporary files"
+msgstr ""
+
+#: src/sudo_edit.c:485 src/sudo_edit.c:609
+msgid "sesh: killed by a signal"
+msgstr ""
+
+#: src/sudo_edit.c:487 src/sudo_edit.c:612
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr ""
+
+#: src/sudo_edit.c:602
+msgid "unable to copy temporary files back to their original location"
+msgstr "ناتوان در رونویسی پرونده‌های موقّتی به مکان اصلی‌شان"
+
+#: src/sudo_edit.c:606
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "ناتوان در رونویسی بعضی از پرونده‌های موقّتی به مکان اصلی‌شان"
+
+#: src/sudo_edit.c:649
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "ناتوان در تنظیم uid به روت (%u)"
+
+#: src/sudo_edit.c:670
+msgid "plugin error: missing file list for sudoedit"
+msgstr ""
+
+#: src/sudo_edit.c:722 src/sudo_edit.c:732
+msgid "unable to read the clock"
+msgstr "ناتوان در خواندن ساعت"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "زمان خواندن گذرواژه تمام شده است"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "هیچ گذرواژه‌ای ارائه نشده است"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "ناتوان در خواندن گذرواژه"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr ""
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr ""
+
+#: src/tgetpass.c:328
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "ناتوان در تنظیم gid به %u"
+
+#: src/tgetpass.c:338
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "ناتوان در تنظیم uid به %u"
+
+#: src/tgetpass.c:343
+#, c-format
+msgid "unable to run %s"
+msgstr "ناتوان در اجرای %s"
+
+#: src/utmp.c:288
+msgid "unable to save stdin"
+msgstr ""
+
+#: src/utmp.c:290
+msgid "unable to dup2 stdin"
+msgstr ""
+
+#: src/utmp.c:293
+msgid "unable to restore stdin"
+msgstr ""
diff --git a/po/fi.mo b/po/fi.mo
new file mode 100644
index 0000000..2293862
--- /dev/null
+++ b/po/fi.mo
Binary files differ
diff --git a/po/fi.po b/po/fi.po
new file mode 100644
index 0000000..89f41e6
--- /dev/null
+++ b/po/fi.po
@@ -0,0 +1,1196 @@
+# Finnish messages for sudo.
+# This file is put in the public domain.
+# This file is distributed under the same license as the sudo package.
+# Jorma Karvonen <karvonen.jorma@gmail.com>, 2011-2017.
+# Lauri Nurmi <lanurmi@iki.fi>, 2019-2021.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.10b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2022-02-12 09:31-0700\n"
+"PO-Revision-Date: 2022-02-14 20:09+0200\n"
+"Last-Translator: Lauri Nurmi <lanurmi@iki.fi>\n"
+"Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\n"
+"Language: fi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 3.0.1\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "käyttäjätietokannan avaaminen epäonnistui"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "vaihtaminen rekisteriin ”%s” epäonnistui %s-käyttäjälle"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "rekisterin palautus epäonnistui"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:54 lib/util/json.c:183 lib/util/sudo_conf.c:218
+#: lib/util/sudo_conf.c:304 lib/util/sudo_conf.c:381 lib/util/sudo_conf.c:665
+#: src/conversation.c:80 src/exec_monitor.c:206 src/exec_monitor.c:456
+#: src/exec_monitor.c:462 src/exec_monitor.c:470 src/exec_monitor.c:478
+#: src/exec_monitor.c:485 src/exec_monitor.c:492 src/exec_monitor.c:499
+#: src/exec_monitor.c:506 src/exec_monitor.c:513 src/exec_monitor.c:520
+#: src/exec_monitor.c:527 src/exec_nopty.c:219 src/exec_nopty.c:228
+#: src/exec_nopty.c:235 src/exec_nopty.c:242 src/exec_nopty.c:249
+#: src/exec_nopty.c:256 src/exec_nopty.c:263 src/exec_nopty.c:270
+#: src/exec_nopty.c:277 src/exec_nopty.c:284 src/exec_nopty.c:291
+#: src/exec_nopty.c:298 src/exec_nopty.c:306 src/exec_nopty.c:503
+#: src/exec_preload.c:143 src/exec_preload.c:204 src/exec_pty.c:840
+#: src/exec_pty.c:849 src/exec_pty.c:906 src/exec_pty.c:1059
+#: src/exec_pty.c:1231 src/exec_pty.c:1240 src/exec_pty.c:1247
+#: src/exec_pty.c:1254 src/exec_pty.c:1261 src/exec_pty.c:1268
+#: src/exec_pty.c:1275 src/exec_pty.c:1282 src/exec_pty.c:1289
+#: src/exec_pty.c:1296 src/exec_pty.c:1303 src/exec_pty.c:1311
+#: src/exec_pty.c:1774 src/load_plugins.c:156 src/load_plugins.c:181
+#: src/load_plugins.c:217 src/load_plugins.c:449 src/load_plugins.c:455
+#: src/parse_args.c:192 src/parse_args.c:213 src/parse_args.c:287
+#: src/parse_args.c:632 src/parse_args.c:654 src/parse_args.c:679
+#: src/preserve_fds.c:46 src/preserve_fds.c:131 src/selinux.c:89
+#: src/selinux.c:362 src/selinux.c:474 src/selinux.c:483 src/sesh.c:113
+#: src/sesh.c:146 src/sesh.c:152 src/sesh.c:159 src/sesh.c:165 src/sesh.c:410
+#: src/sudo.c:639 src/sudo.c:709 src/sudo.c:719 src/sudo.c:744 src/sudo.c:767
+#: src/sudo.c:776 src/sudo.c:785 src/sudo.c:802 src/sudo.c:844 src/sudo.c:854
+#: src/sudo.c:883 src/sudo.c:1083 src/sudo.c:1104 src/sudo.c:1397
+#: src/sudo.c:1566 src/sudo.c:1793 src/sudo.c:2127 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:429 src/sudo_edit.c:438
+#: src/sudo_edit.c:539 src/sudo_edit.c:546 src/sudo_edit.c:677
+#: src/sudo_edit.c:697 src/sudo_intercept_common.c:113
+#: src/sudo_intercept_common.c:317
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:55
+#: lib/util/json.c:184 lib/util/regex.c:113 lib/util/regex.c:121
+#: lib/util/sudo_conf.c:219 lib/util/sudo_conf.c:304 lib/util/sudo_conf.c:381
+#: lib/util/sudo_conf.c:665 src/conversation.c:81 src/exec_intercept.c:100
+#: src/exec_intercept.c:330 src/exec_intercept.c:354 src/exec_intercept.c:377
+#: src/exec_intercept.c:385 src/exec_intercept.c:410 src/exec_intercept.c:416
+#: src/exec_intercept.c:425 src/exec_intercept.c:431 src/exec_intercept.c:565
+#: src/exec_intercept.c:706 src/exec_monitor.c:456 src/exec_monitor.c:462
+#: src/exec_monitor.c:470 src/exec_monitor.c:478 src/exec_monitor.c:485
+#: src/exec_monitor.c:492 src/exec_monitor.c:499 src/exec_monitor.c:506
+#: src/exec_monitor.c:513 src/exec_monitor.c:520 src/exec_monitor.c:527
+#: src/exec_nopty.c:219 src/exec_nopty.c:228 src/exec_nopty.c:235
+#: src/exec_nopty.c:242 src/exec_nopty.c:249 src/exec_nopty.c:256
+#: src/exec_nopty.c:263 src/exec_nopty.c:270 src/exec_nopty.c:277
+#: src/exec_nopty.c:284 src/exec_nopty.c:291 src/exec_nopty.c:298
+#: src/exec_nopty.c:306 src/exec_preload.c:143 src/exec_preload.c:204
+#: src/exec_pty.c:840 src/exec_pty.c:849 src/exec_pty.c:906
+#: src/exec_pty.c:1231 src/exec_pty.c:1240 src/exec_pty.c:1247
+#: src/exec_pty.c:1254 src/exec_pty.c:1261 src/exec_pty.c:1268
+#: src/exec_pty.c:1275 src/exec_pty.c:1282 src/exec_pty.c:1289
+#: src/exec_pty.c:1296 src/exec_pty.c:1303 src/exec_pty.c:1311
+#: src/exec_pty.c:1774 src/load_plugins.c:156 src/load_plugins.c:181
+#: src/load_plugins.c:217 src/load_plugins.c:449 src/load_plugins.c:455
+#: src/parse_args.c:192 src/parse_args.c:214 src/parse_args.c:287
+#: src/parse_args.c:632 src/parse_args.c:654 src/parse_args.c:679
+#: src/preserve_fds.c:46 src/preserve_fds.c:131 src/selinux.c:89
+#: src/selinux.c:362 src/selinux.c:474 src/selinux.c:483 src/sesh.c:113
+#: src/sesh.c:411 src/sudo.c:230 src/sudo.c:639 src/sudo.c:883 src/sudo.c:1083
+#: src/sudo.c:1104 src/sudo.c:1397 src/sudo.c:1566 src/sudo.c:1793
+#: src/sudo.c:2127 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:429
+#: src/sudo_edit.c:438 src/sudo_edit.c:539 src/sudo_edit.c:546
+#: src/sudo_edit.c:677 src/sudo_edit.c:697 src/sudo_intercept_common.c:113
+#: src/sudo_intercept_common.c:317
+msgid "unable to allocate memory"
+msgstr "muistin varaaminen epäonnistui"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "stat-kutsu epäonnistui tiedostolle %.*s"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s on olemassa, mutta ei ole hakemisto (0%o)"
+
+#: lib/util/mkdir_parents.c:102 lib/util/sudo_conf.c:704 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:371 src/sudo_edit.c:494 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "%s: avaaminen epäonnistui"
+
+#: lib/util/mkdir_parents.c:119 lib/util/mkdir_parents.c:127
+#: lib/util/mkdir_parents.c:136
+#, c-format
+msgid "unable to open %.*s"
+msgstr "tiedoston %.*s avaaminen epäonnistui"
+
+#: lib/util/mkdir_parents.c:157
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "hakemiston %.*s luominen epäonnistui"
+
+#: lib/util/regex.c:103
+msgid "regular expression too large"
+msgstr "säännöllinen lauseke liian suuri"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Tuntematon signaali"
+
+#: lib/util/strtoid.c:87 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:146 src/sesh.c:159
+msgid "invalid value"
+msgstr "virheellinen arvo"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "arvo on liian suuri"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "arvo on liian pieni"
+
+#: lib/util/sudo_conf.c:237
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "virheellinen Path-arvo ”%s” tiedostossa %s, rivillä %u"
+
+#: lib/util/sudo_conf.c:403 lib/util/sudo_conf.c:419 lib/util/sudo_conf.c:472
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "virheellinen %s-arvo ”%s” tiedostossa %s, rivillä %u"
+
+#: lib/util/sudo_conf.c:440
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "tukematon ryhmälähde ”%s” tiedostossa %s, rivillä %u"
+
+#: lib/util/sudo_conf.c:456
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "virheellinen ryhmien enimmäismäärä ”%s” tiedostossa %s, rivillä %u"
+
+#: lib/util/sudo_conf.c:681 src/copy_file.c:150
+#, c-format
+msgid "unable to stat %s"
+msgstr "stat-kutsu epäonnistui tiedostolle %s"
+
+#: lib/util/sudo_conf.c:684
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s ei ole tavallinen tiedosto"
+
+# ensimmäinen parametri on path
+#: lib/util/sudo_conf.c:687 src/copy_file.c:163
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "polun %s omistaa uid %u, tulisi olla %u"
+
+#: lib/util/sudo_conf.c:691
+#, c-format
+msgid "%s is world writable"
+msgstr "%s on yleiskirjoitettava"
+
+#: lib/util/sudo_conf.c:694
+#, c-format
+msgid "%s is group writable"
+msgstr "%s on ryhmäkirjoitettava"
+
+#: src/copy_file.c:93
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: katkaistaanko %s nollaan tavuun? (y/n) [n] "
+
+#: src/copy_file.c:97
+#, c-format
+msgid "not overwriting %s"
+msgstr "jätetään ylikirjoittamatta %s"
+
+#: src/copy_file.c:119
+#, c-format
+msgid "unable to read from %s"
+msgstr "tiedostosta %s lukeminen epäonnistui"
+
+#: src/copy_file.c:136 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "tiedostoon %s kirjoittaminen epäonnistui"
+
+#: src/copy_file.c:154 src/sesh.c:218 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: ei ole tavallinen tiedosto"
+
+#: src/copy_file.c:158
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: virheellinen tiedostotila: 0%o"
+
+#: src/edit_open.c:331
+msgid "unable to restore current working directory"
+msgstr "nykyisen työhakemiston palauttaminen epäonnistui"
+
+#: src/exec.c:130
+#, c-format
+msgid "unknown login class %s"
+msgstr "tuntematon kirjautumisluokka %s"
+
+#: src/exec.c:142
+msgid "unable to set user context"
+msgstr "käyttäjäkontekstin asettaminen epäonnistui"
+
+#: src/exec.c:158
+msgid "unable to set process priority"
+msgstr "prosessiprioriteetin asettaminen epäonnistui"
+
+#: src/exec.c:175
+#, c-format
+msgid "unable to change root to %s"
+msgstr "root-käyttäjän vaihtaminen käyttäjäksi %s epäonnistui"
+
+#: src/exec.c:188 src/exec.c:194 src/exec.c:201
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "vaihtaminen runas-uid:ksi (%u, %u) epäonnistui"
+
+#: src/exec.c:219
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "vaihtaminen hakemistoksi %s epäonnistui"
+
+#: src/exec.c:223
+#, c-format
+msgid "starting from %s"
+msgstr "aloitetaan hakemistosta %s"
+
+#: src/exec.c:305 src/exec_monitor.c:565 src/exec_monitor.c:567
+#: src/exec_nopty.c:561 src/exec_pty.c:581 src/exec_pty.c:1411
+#: src/exec_pty.c:1413 src/signal.c:144 src/signal.c:151 src/signal.c:165
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "käsittelijän asettaminen signaalille %d epäonnistui"
+
+# Solaris privileges, remove PRIV_PROC_EXEC post-execve.
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "PRIV_PROC_EXEC-määreen poistaminen PRIV_LIMITiltä epäonnistui"
+
+#: src/exec_intercept.c:112 src/exec_intercept.c:116 src/exec_intercept.c:667
+#: src/exec_intercept.c:671 src/exec_intercept.c:857 src/exec_intercept.c:861
+#: src/exec_intercept.c:872 src/exec_intercept.c:876 src/exec_monitor.c:464
+#: src/exec_monitor.c:472 src/exec_monitor.c:480 src/exec_monitor.c:487
+#: src/exec_monitor.c:494 src/exec_monitor.c:501 src/exec_monitor.c:508
+#: src/exec_monitor.c:515 src/exec_monitor.c:522 src/exec_monitor.c:529
+#: src/exec_nopty.c:221 src/exec_nopty.c:230 src/exec_nopty.c:237
+#: src/exec_nopty.c:244 src/exec_nopty.c:251 src/exec_nopty.c:258
+#: src/exec_nopty.c:265 src/exec_nopty.c:272 src/exec_nopty.c:279
+#: src/exec_nopty.c:286 src/exec_nopty.c:293 src/exec_nopty.c:300
+#: src/exec_nopty.c:308 src/exec_pty.c:706 src/exec_pty.c:711
+#: src/exec_pty.c:808 src/exec_pty.c:815 src/exec_pty.c:912
+#: src/exec_pty.c:1233 src/exec_pty.c:1242 src/exec_pty.c:1249
+#: src/exec_pty.c:1256 src/exec_pty.c:1263 src/exec_pty.c:1270
+#: src/exec_pty.c:1277 src/exec_pty.c:1284 src/exec_pty.c:1291
+#: src/exec_pty.c:1298 src/exec_pty.c:1305 src/exec_pty.c:1727
+#: src/exec_pty.c:1737 src/exec_pty.c:1782 src/exec_pty.c:1789
+#: src/exec_pty.c:1816
+msgid "unable to add event to queue"
+msgstr "tapahtuman lisääminen jonoon epäonnistui"
+
+#: src/exec_intercept.c:314
+msgid "invalid PolicyCheckRequest"
+msgstr "virheellinen PolicyCheckRequest"
+
+#: src/exec_intercept.c:362 src/sudo.c:1209 src/sudo.c:1254 src/sudo.c:1298
+msgid "command rejected by policy"
+msgstr "käytäntö hylkäsi komennon"
+
+#: src/exec_intercept.c:455 src/sudo.c:1214 src/sudo.c:1259 src/sudo.c:1303
+#: src/sudo.c:1377
+msgid "policy plugin error"
+msgstr "käytäntölisäosan virhe"
+
+#: src/exec_intercept.c:561
+#, c-format
+msgid "client request too large: %zu"
+msgstr "asiakaspyyntö on liian suuri: %zu"
+
+#: src/exec_intercept.c:659
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "odottamaton type_case-arvo %d (%s) kirjastosta %s"
+
+#: src/exec_intercept.c:694
+#, c-format
+msgid "server message too large: %zu"
+msgstr "palvelinsanoma on liian suuri: %zu"
+
+#: src/exec_monitor.c:360
+msgid "error reading from socketpair"
+msgstr "virhe luettaessa sokettiparista"
+
+#: src/exec_monitor.c:377
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "odottamaton vastaustyyppi paluukanavalla: %d"
+
+# Istunnolla voi olla ohjaava tty. Istunnon yksi prosessiryhmä voi olla edustaprosessiryhmä ja toimia siten ohjaavana tty:nä, joka vastaanottaa tty-syötteen ja -signaalit.
+#: src/exec_monitor.c:583
+msgid "unable to set controlling tty"
+msgstr "ohjaavan tty:n asettaminen epäonnistui"
+
+#: src/exec_monitor.c:591 src/exec_nopty.c:369 src/exec_pty.c:1490
+#: src/exec_pty.c:1511 src/exec_pty.c:1531 src/tgetpass.c:307
+msgid "unable to create pipe"
+msgstr "putken luominen epäonnistui"
+
+#: src/exec_monitor.c:601
+msgid "unable to receive message from parent"
+msgstr "viestin vastaanotto vanhemmalta epäonnistui"
+
+#: src/exec_monitor.c:617 src/exec_nopty.c:407 src/exec_pty.c:1569
+#: src/sudo_edit.c:361 src/tgetpass.c:311
+msgid "unable to fork"
+msgstr "fork-kutsu epäonnistui"
+
+#: src/exec_monitor.c:621 src/exec_monitor.c:722 src/exec_nopty.c:471
+msgid "unable to restore tty label"
+msgstr "tty-nimiön palauttaminen epäonnistui"
+
+#: src/exec_monitor.c:637 src/sesh.c:123 src/sudo.c:1160
+#, c-format
+msgid "unable to execute %s"
+msgstr "%s: suorittaminen epäonnistui"
+
+#: src/exec_nopty.c:363 src/exec_pty.c:1420
+msgid "policy plugin failed session initialization"
+msgstr "käytäntölisäosa epäonnistui istunnon alustamisessa"
+
+#: src/exec_nopty.c:377 src/exec_pty.c:1391 src/exec_pty.c:1399
+msgid "unable to create sockets"
+msgstr "sokettien luominen epäonnistui"
+
+#: src/exec_nopty.c:459 src/exec_pty.c:1666
+msgid "error in event loop"
+msgstr "virhe tapahtumasilmukassa"
+
+#: src/exec_nopty.c:569 src/exec_pty.c:619 src/signal.c:101
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "käsittelijän palauttaminen signaalille %d epäonnistui"
+
+#: src/exec_pty.c:158
+msgid "unable to allocate pty"
+msgstr "pty:n varaaminen epäonnistui"
+
+#: src/exec_pty.c:222 src/exec_pty.c:262 src/exec_pty.c:302 src/exec_pty.c:353
+#: src/exec_pty.c:404
+msgid "I/O plugin error"
+msgstr "siirräntälisäosan virhe"
+
+#: src/exec_pty.c:226 src/exec_pty.c:266 src/exec_pty.c:306 src/exec_pty.c:357
+#: src/exec_pty.c:408
+msgid "command rejected by I/O plugin"
+msgstr "siirräntälisäosa hylkäsi komennon"
+
+#: src/exec_pty.c:455
+msgid "error logging suspend"
+msgstr "virhe suspend-toiminnon lokiin kirjaamisessa"
+
+#: src/exec_pty.c:489
+msgid "error changing window size"
+msgstr "virhe ikkunan koon muuttamisessa"
+
+#: src/exec_pty.c:1615
+msgid "unable to send message to monitor process"
+msgstr "viestin lähettäminen prosessien valvomiseksi epäonnistui"
+
+#: src/load_plugins.c:108 src/load_plugins.c:122 src/load_plugins.c:128
+#: src/load_plugins.c:277 src/load_plugins.c:287 src/load_plugins.c:297
+#: src/load_plugins.c:344
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "virhe tiedostossa %s, rivillä %d alustettaessa lisäosaa ”%s”"
+
+# ensimmäinen parametri on path
+#: src/load_plugins.c:124
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "polun %s omistajan on oltava uid %d"
+
+# parametri on path
+#: src/load_plugins.c:130
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "polun %s on oltava vain omistajan kirjoitettavissa"
+
+#: src/load_plugins.c:241 src/load_plugins.c:312
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "ohitetaan lisäosan ”%s” kaksoiskappale tiedostossa %s, rivillä %d"
+
+#: src/load_plugins.c:279
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "%s: lataaminen epäonnistui: %s"
+
+#: src/load_plugins.c:289
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "symbolia ”%s” ei löytynyt kohteesta %s"
+
+#: src/load_plugins.c:299
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "löydettiin yhteensopimaton lisäosan pääversio %d (odotettiin %d) kohteesta %s"
+
+#: src/load_plugins.c:317
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "ohitetaan käytäntölisäosa ”%s” tiedostossa %s, rivillä %d"
+
+#: src/load_plugins.c:320
+msgid "only a single policy plugin may be specified"
+msgstr "vain yksi käytäntölisäosa voidaan määritellä"
+
+#: src/load_plugins.c:346
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "tuntematon lisäosatyyppi %d löytyi kohteesta %s"
+
+#: src/load_plugins.c:529
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "käytäntölisäosa %s ei sisällä check_policy-metodia"
+
+#: src/net_ifs.c:210 src/net_ifs.c:376 src/net_ifs.c:437 src/net_ifs.c:624
+#: src/net_ifs.c:855 src/sudo.c:486 src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "sisäinen virhe, %s-ylivuoto"
+
+#: src/parse_args.c:234
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "virheellinen ympäristömuuttujan nimi: %s"
+
+#: src/parse_args.c:337
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "argumentin valitsimelle -C on oltava vähintään 3"
+
+#: src/parse_args.c:568
+msgid "you may not specify both the -i and -s options"
+msgstr "valitsimia -i ja -s ei voi käyttää yhdessä"
+
+#: src/parse_args.c:573
+msgid "you may not specify both the -i and -E options"
+msgstr "valitsimia -i ja -E ei voi käyttää yhdessä"
+
+#: src/parse_args.c:583
+msgid "the -E option is not valid in edit mode"
+msgstr "valitsin -E ei kelpaa muokkaustilassa"
+
+#: src/parse_args.c:586
+msgid "you may not specify environment variables in edit mode"
+msgstr "ympäristömuuttujia ei voi määritellä muokkaustilassa"
+
+#: src/parse_args.c:596
+msgid "the -U option may only be used with the -l option"
+msgstr "valitsinta -U voi käyttää vain valitsimen -l kanssa"
+
+#: src/parse_args.c:600
+msgid "the -A and -S options may not be used together"
+msgstr "valitsimia -A ja -S ei voi käyttää yhdessä"
+
+#: src/parse_args.c:693
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit ei ole tuettu tällä alustalla"
+
+#: src/parse_args.c:776
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Vain yhtä valitsimista -e, -h, -i, -K, -l, -s, -v tai -V voidaan käyttää"
+
+#: src/parse_args.c:792
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - muokkaa tiedostoja toisena käyttäjänä\n"
+"\n"
+
+#: src/parse_args.c:794
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - suorita komentoja toisena käyttäjänä\n"
+"\n"
+
+#: src/parse_args.c:800
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Valitsimet:\n"
+
+#: src/parse_args.c:802
+msgid "use a helper program for password prompting"
+msgstr "käytä apuohjelmaa salasanakyselyyn"
+
+#: src/parse_args.c:805
+msgid "use specified BSD authentication type"
+msgstr "käytä määriteltyä BSD-todennustyyppiä"
+
+#: src/parse_args.c:809
+msgid "run command in the background"
+msgstr "suorita komento taustalla"
+
+#: src/parse_args.c:812
+msgid "ring bell when prompting"
+msgstr "soita kelloa kehotteissa"
+
+#: src/parse_args.c:814
+msgid "close all file descriptors >= num"
+msgstr "sulje kaikki tiedostokahvat >= num"
+
+#: src/parse_args.c:817
+msgid "run command with the specified BSD login class"
+msgstr "suorita komento määritellyllä BSD-kirjautumisluokalla"
+
+#: src/parse_args.c:820
+msgid "change the working directory before running command"
+msgstr "muuta työhakemisto ennen komennon suorittamista"
+
+#: src/parse_args.c:823
+msgid "preserve user environment when running command"
+msgstr "säilytä käyttäjäympäristö komentoa suoritettaessa"
+
+#: src/parse_args.c:825
+msgid "preserve specific environment variables"
+msgstr "säilytä tietyt ympäristömuuttujat"
+
+#: src/parse_args.c:827
+msgid "edit files instead of running a command"
+msgstr "muokkaa tiedostoja komennon suorittamisen sijasta"
+
+# tämä viittaa runas_group-määritelyyn
+#: src/parse_args.c:830
+msgid "run command as the specified group name or ID"
+msgstr "suorita komento määriteltynä ryhmänimenä tai -ID:nä"
+
+#: src/parse_args.c:833
+msgid "set HOME variable to target user's home dir"
+msgstr "aseta HOME-muuttuja osoittamaan kohdekäyttäjän kotihakemistoon"
+
+#: src/parse_args.c:836
+msgid "display help message and exit"
+msgstr "näytä opasteviesti ja poistu"
+
+#: src/parse_args.c:838
+msgid "run command on host (if supported by plugin)"
+msgstr "suorita komento etäkoneella (jos lisäosa tukee)"
+
+#: src/parse_args.c:841
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "suorita kirjautumiskuori kohdekäyttäjänä; voidaan myös antaa komento"
+
+#: src/parse_args.c:843
+msgid "remove timestamp file completely"
+msgstr "poista aikaleimatiedosto kokonaan"
+
+#: src/parse_args.c:846
+msgid "invalidate timestamp file"
+msgstr "mitätöi aikaleimatiedosto"
+
+#: src/parse_args.c:849
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "luettele käyttäjän käyttöoikeudet tai tarkasta tietty komento; kahdesti käyttämällä pidempi muoto"
+
+#: src/parse_args.c:852
+msgid "non-interactive mode, no prompts are used"
+msgstr "ei-vuorovaikutteinen tila, ei kehotteita"
+
+#: src/parse_args.c:855
+msgid "preserve group vector instead of setting to target's"
+msgstr "säilytä ryhmävektori kohteen vektorin asettamisen sijasta"
+
+#: src/parse_args.c:858
+msgid "use the specified password prompt"
+msgstr "käytä annettua salasanakehotetta"
+
+#: src/parse_args.c:860
+msgid "change the root directory before running command"
+msgstr "muuta juurihakemisto ennen komennon suorittamista"
+
+#: src/parse_args.c:863
+msgid "create SELinux security context with specified role"
+msgstr "luo SELinux-turvakonteksti määritellyllä roolilla"
+
+#: src/parse_args.c:866
+msgid "read password from standard input"
+msgstr "lue salasana vakiosyötteestä"
+
+#: src/parse_args.c:869
+msgid "run shell as the target user; a command may also be specified"
+msgstr "suorita kuori kohdekäyttäjänä; voidaan myös antaa komento"
+
+#: src/parse_args.c:873
+msgid "create SELinux security context with specified type"
+msgstr "luo SELinux-turvakonteksti määritellyllä roolilla"
+
+#: src/parse_args.c:876
+msgid "terminate command after the specified time limit"
+msgstr "päätä komento määrätyn aikarajan jälkeen"
+
+#: src/parse_args.c:879
+msgid "in list mode, display privileges for user"
+msgstr "näytä luettelotilassa käyttäjän oikeudet"
+
+#: src/parse_args.c:882
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "suorita komento (tai muokkaa tiedostoa) määriteltynä käyttäjänimenä tai -ID:nä"
+
+#: src/parse_args.c:884
+msgid "display version information and exit"
+msgstr "näytä versiotiedot ja poistu"
+
+#: src/parse_args.c:887
+msgid "update user's timestamp without running a command"
+msgstr "päivitä käyttäjän aikaleima suorittamatta komentoa"
+
+#: src/parse_args.c:890
+msgid "stop processing command line arguments"
+msgstr "lopeta komentoriviargumenttien käsittely"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "audit-järjestelmän avaaminen epäonnistui"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "audit-viestin lähettäminen epäonnistui"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "fgetfilecon %s -kutsu epäonnistui"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s muutti nimiöitä"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "kontekstin palauttaminen kohteelle %s epäonnistui"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "%s: avaaminen epäonnistui, ei uudelleennimiöidä tty:tä"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s ei ole merkkilaite, ei uudelleennimiöidä tty:tä"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "nykyisen tty-kontekstin noutaminen epäonnistui, ei uudelleennimiöidä tty:tä"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "tuntematon turvaluokka ”chr_file”, ei uudelleennimiöidä tty:tä"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "uuden tty-kontekstin noutaminen epäonnistui, ei uudelleennimiöidä tty:tä"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "uuden tty-kontekstin asettaminen epäonnistui"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "%s-tyypille on määriteltävä rooli"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "oletustyypin hakeminen %s-roolille epäonnistui"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "uuden kontekstin noutaminen epäonnistui"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "uuden roolin %s asettaminen epäonnistui"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "uuden tyypin %s asettaminen epäonnistui"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s ei ole kelvollinen konteksti"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "vanhan kontekstin noutaminen epäonnistui"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "pakotustilan päättely epäonnistui."
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "exec-kontekstin asetus arvoon %s epäonnistui"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "avaimenluontikontekstin asetus arvoon %s epäonnistui"
+
+#: src/sesh.c:72
+msgid "requires at least one argument"
+msgstr "vaatii vähintään yhden argumentin"
+
+#: src/sesh.c:104
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "virheellinen tiedostokahvanumero: %s"
+
+#: src/sesh.c:118
+#, c-format
+msgid "unable to run %s as a login shell"
+msgstr "yritys ajaa %s kirjautumiskuorena epäonnistui"
+
+#: src/sesh.c:200 src/sesh.c:300 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: symbolisten linkkien muokkaus ei ole sallittua"
+
+#: src/sesh.c:203 src/sesh.c:303 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: tiedostojen muokkaus kirjoitettavassa hakemistossa ei ole sallittua"
+
+#: src/sesh.c:287 src/sesh.c:308 src/sesh.c:317 src/sesh.c:325
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "muokkausistunnon sisältö jätetty kohteeseen %s"
+
+#: src/sesh.c:416 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "ryhmälistan noutaminen epäonnistui"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "signaalin %d käsittelijän tallentaminen epäonnistui"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "resurssivalvontaraja saavutettu"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "käyttäjä ”%s” ei ole ”%s”-hankkeen jäsen"
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "kutsuva tehtävä on final-tyyppinen"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "”%s”-hankkeeseen liittyminen epäonnistui"
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "”%s”-hankkeelle ei ole oletusyhteydet hyväksyvää resurssivarantoa"
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "määriteltyä resurssivarantoa ei ole olemassa ”%s”-hankkeelle"
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "”%s”-hanketta ei voitu sitoa oletusresurssivarantoon"
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "setproject-kutsu ”%s”-hankkeelle epäonnistui"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "varoitus, ”%s”-hankkeen resurssivalvontaosoitus epäonnistui"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo-versio %s\n"
+
+#: src/sudo.c:218
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Asetusvalitsimet: %s\n"
+
+#: src/sudo.c:226
+msgid "fatal error, unable to load plugins"
+msgstr "vakava virhe, lisäosien lataaminen epäonnistui"
+
+#: src/sudo.c:272
+msgid "plugin did not return a command to execute"
+msgstr "lisäosa ei palauttanut suoritettavaa komentoa"
+
+#: src/sudo.c:305
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "odottamaton sudo-tila 0x%x"
+
+#: src/sudo.c:553
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "sinua ei ole olemassa %s-tietokannassa"
+
+#: src/sudo.c:610
+msgid "unable to determine tty"
+msgstr "tty:n päätteleminen epäonnistui"
+
+#: src/sudo.c:908
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "”Ei uusia oikeuksia” -lippu on asetettu, mikä estää sudon suorittamiseen root-käyttäjänä."
+
+#: src/sudo.c:910
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "Jos sudoa käytetään kontissa, kontin asetuksia on ehkä muutettava lipun kytkemiseksi pois käytöstä."
+
+# ensimmäinen parametri on path
+#: src/sudo.c:944
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "polun %s omistajan on oltava uid %d ja setuid-bitin on oltava asetettu"
+
+#: src/sudo.c:947
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "vallitseva käyttäjä-id ei ole %d, sijaitseeko %s ”nosuid”-valintaa käyttävällä tiedostojärjestelmällä, vai onko tämä NFS-tiedostojärjestelmä ilman root-käyttöoikeuksia?"
+
+#: src/sudo.c:953
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "vallitseva käyttäjä-id ei ole %d, onko sudo asennettu setuid root -käyttöoikeuksilla?"
+
+#: src/sudo.c:969 src/tgetpass.c:333
+msgid "unable to set supplementary group IDs"
+msgstr "täydentävien ryhmä-ID:iden asettaminen epäonnistui"
+
+# tämän ymmärrän niin, että käyttöjärjestelmäydin luo tiedoston ja antaa tälle tavallaan tilapäisen effective gid-tunnisteen, joka vaihdetaan suorittamisen yhteydessä prosessin omistajan suoritettavaksi ryhmätunnisteeksi.
+#: src/sudo.c:976
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "vallitsevan ryhmä-ID:n asettaminen runas-ryhmä-ID:ksi %u epäonnistui"
+
+#: src/sudo.c:982
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "ryhmä-ID:n asettaminen runas-ryhmä-ID:ksi %u epäonnistui"
+
+#: src/sudo.c:1025
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "lapsiprosessin odottamaton päättymisehto: %d"
+
+#: src/sudo.c:1132
+msgid "unable to initialize policy plugin"
+msgstr "käytäntölisäosan alustaminen epäonnistui"
+
+#: src/sudo.c:1194
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "käytäntölisäosalta %s puuttuu ”check_policy”-metodi"
+
+#: src/sudo.c:1240
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "käytäntölisäosa %s ei tue käyttöoikeuksien luettelua"
+
+#: src/sudo.c:1284
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "käytäntölisäosa %s ei tue valitsinta -v"
+
+#: src/sudo.c:1322
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "käytäntölisäosa %s ei tue valitsimia -k/-K"
+
+#: src/sudo.c:1451
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "virhe alustettaessa siirräntälisäosaa %s"
+
+#: src/sudo.c:1454
+msgid "error initializing I/O plugin"
+msgstr "virhe alustettaessa siirräntälisäosaa"
+
+#: src/sudo.c:1603
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "audit-lisäosan %s alustaminen epäonnistui"
+
+#: src/sudo.c:1682
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: virhetapahtuman kirjaaminen lokiin epäonnistui%s%s"
+
+#: src/sudo.c:1718
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: hyväksyntätapahtuman kirjaaminen lokiin epäonnistui%s%s"
+
+#: src/sudo.c:1723 src/sudo.c:1761
+msgid "audit plugin error"
+msgstr "audit-lisäosan virhe"
+
+#: src/sudo.c:1756
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: hylkäystapahtuman kirjaaminen lokiin epäonnistui%s%s"
+
+#: src/sudo.c:1816
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "hyväksyntälisäosan %s alustaminen epäonnistui"
+
+#: src/sudo.c:1886
+msgid "command rejected by approver"
+msgstr "hyväksyjä hylkäsi komennon"
+
+#: src/sudo.c:1896
+msgid "approval plugin error"
+msgstr "hyväksyntälisäosan virhe"
+
+# parametrina on CWD- eli Change Working Directory- komennolla palautettava hakemisto
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "kirjoitettavaa väliaikaishakemistoa ei löytynyt"
+
+#: src/sudo_edit.c:291
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s jätetty muuttamattomaksi"
+
+#: src/sudo_edit.c:304 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s muuttamaton"
+
+#: src/sudo_edit.c:481
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: sisäinen virhe: polkujen pariton määrä"
+
+#: src/sudo_edit.c:483
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: väliaikaistiedostojen luominen epäonnistui"
+
+#: src/sudo_edit.c:485 src/sudo_edit.c:609
+msgid "sesh: killed by a signal"
+msgstr "sesh: signaali tappoi"
+
+#: src/sudo_edit.c:487 src/sudo_edit.c:612
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: tuntematon virhe %d"
+
+#: src/sudo_edit.c:602
+msgid "unable to copy temporary files back to their original location"
+msgstr "väliaikaistiedostojen kopioiminen takaisin niiden alkuperäiseen sijaintiin epäonnistui"
+
+#: src/sudo_edit.c:606
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "joidenkin väliaikaistiedostojen kopioiminen takaisin niiden alkuperäiseen sijaintiin epäonnistui"
+
+#: src/sudo_edit.c:649
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "käyttäjä-ID:n vaihtaminen rootiksi (%u) epäonnistui"
+
+#: src/sudo_edit.c:670
+msgid "plugin error: missing file list for sudoedit"
+msgstr "lisäosavirhe: puuttuu sudoedit-tiedostoluettelo"
+
+#: src/sudo_edit.c:713 src/sudo_edit.c:727
+msgid "unable to read the clock"
+msgstr "kellon lukeminen epäonnistui"
+
+#: src/sudo_intercept_common.c:341
+msgid "intercept port not set"
+msgstr "sieppausporttia ei ole asetettu"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "aikakatkaisu salasanaa luettaessa"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "salasanaa ei annettu"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "salasanan lukeminen epäonnistui"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "salasanan lukemiseksi vaaditaan pääte; käytä joko valitsinta -S vakiosyötteen lukemiseksi tai aseta salasanakyselin"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "salasanakyselin on määrittelemättä, yritä asettaa SUDO_ASKPASS"
+
+#: src/tgetpass.c:328
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "ryhmä-ID:n asettaminen arvoon %u epäonnistui"
+
+#: src/tgetpass.c:338
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "käyttäjä-ID:n asettaminen arvoon %u epäonnistui"
+
+#: src/tgetpass.c:343
+#, c-format
+msgid "unable to run %s"
+msgstr "salasanakyselimen %s suorittaminen epäonnistui"
+
+#: src/utmp.c:288
+msgid "unable to save stdin"
+msgstr "vakiosyötteeseen tallentaminen epäonnistui"
+
+#: src/utmp.c:290
+msgid "unable to dup2 stdin"
+msgstr "dup2-kutsu vakiosyötteelle epäonnistui"
+
+#: src/utmp.c:293
+msgid "unable to restore stdin"
+msgstr "vakiosyötteen palauttaminen epäonnistui"
+
+#~ msgid "unable to dup intercept fd"
+#~ msgstr "dup-kutsu siepatulle kahvalle epäonnistui"
+
+#~ msgid "%s: missing message header"
+#~ msgstr "%s: puuttuva sanoman otsikko"
+
+#~ msgid "%s: expected message type %d, got %d"
+#~ msgstr "%s: odotettu sanomatyyppi %d, saatiin %d"
+
+#~ msgid "unable to set tty context to %s"
+#~ msgstr "tty-kontekstin asetus arvoon %s epäonnistui"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s: %s"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s: vaillinainen kirjoitus"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "väliaikaistiedoston lukeminen epäonnistui"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "ohitetaan käytäntölisäosan ”%s” kaksoiskappale tiedostossa %s, rivillä %d"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "tuntematon uid-käyttäjätunniste %u: kuka olet?"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "ei tty:tä käytettävissä eikä salasanan kyselyohjelmaa määriteltynä"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "virhe luettaessa signaaliputkesta"
+
+#~ msgid "internal error, tried allocate zero bytes"
+#~ msgstr "sisäinen virhe, yritettiin varata nolla tavua"
+
+#~ msgid "unable to set terminal to raw mode"
+#~ msgstr "pääteikkunan asentaminen raakatilaan epäonnistui"
+
+#~ msgid "unable to open socket"
+#~ msgstr "vastakkeen avaaminen epäonnistui"
+
+#~ msgid "%s: %s: %s\n"
+#~ msgstr "%s: %s: %s\n"
+
+#~ msgid "%s: %s\n"
+#~ msgstr "%s: %s\n"
+
+#~ msgid "internal error, tried to emalloc2(0)"
+#~ msgstr "sisäinen virhe, yritettiin suorittaa emalloc2(0)"
+
+#~ msgid "internal error, tried to ecalloc(0)"
+#~ msgstr "sisäinen virhe, yritettiin suorittaa ecalloc(0)"
+
+#~ msgid "internal error, tried to erealloc(0)"
+#~ msgstr "sisäinen virhe, yritettiin suorittaa erealloc(0)"
+
+#~ msgid "internal error, tried to erealloc3(0)"
+#~ msgstr "sisäinen virhe, yritettiin suorittaa erealloc3(0)"
+
+#~ msgid "internal error, tried to erecalloc(0)"
+#~ msgstr "sisäinen virhe, yritettiin suorittaa erecalloc(0)"
+
+#~ msgid "load_interfaces: overflow detected"
+#~ msgstr "load_interfaces: ylivuoto havaittu"
+
+#~ msgid "value out of range"
+#~ msgstr "arvo lukualueen ulkopuolella"
+
+#~ msgid "select failed"
+#~ msgstr "select-funktio epäonnistui"
+
+#~ msgid "list user's available commands\n"
+#~ msgstr "luettele käyttäjän käytettävissä olevat komennot\n"
+
+#~ msgid "run a shell as target user\n"
+#~ msgstr "suorita komentotulkki kohdekäyttäjänä\n"
+
+#~ msgid "when listing, list specified user's privileges\n"
+#~ msgstr "luetteloitaessa luettele määritellyn käyttäjän käyttöoikeudet\n"
+
+#~ msgid ": "
+#~ msgstr ": "
+
+#~ msgid "internal error, emalloc2() overflow"
+#~ msgstr "sisäinen virhe, emalloc2() -ylivuoto"
+
+#~ msgid "internal error, erealloc3() overflow"
+#~ msgstr "sisäinen virhe, erealloc3() -ylivuoto"
+
+#~ msgid "%s: at least one policy plugin must be specified"
+#~ msgstr "%s: vähintään yksi menettelytapalisäosa on määriteltävä"
+
+#~ msgid "must be setuid root"
+#~ msgstr "on oltava setuid root"
+
+#~ msgid "the argument to -D must be between 1 and 9 inclusive"
+#~ msgstr "valitsimen -D argumentin on oltava alueella 1 - 9"
diff --git a/po/fr.mo b/po/fr.mo
new file mode 100644
index 0000000..a61a690
--- /dev/null
+++ b/po/fr.mo
Binary files differ
diff --git a/po/fr.po b/po/fr.po
new file mode 100644
index 0000000..a5182e6
--- /dev/null
+++ b/po/fr.po
@@ -0,0 +1,1293 @@
+# Messages français pour sudo.
+# Copyright (C) 2023 Free Software Foundation, Inc.
+# This file is put in the public domain.
+# Todd C. Miller <Todd.Miller@courtesan.com>, 2011-2013
+# Frédéric Marchal <fmarchal@perso.be>, 2023
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.14b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-06-07 13:27-0600\n"
+"PO-Revision-Date: 2023-06-08 21:12+0200\n"
+"Last-Translator: Frédéric Marchal <fmarchal@perso.be>\n"
+"Language-Team: French <traduc@traduc.org>\n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=(n >= 2);\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "impossible d'ouvrir la base de données utilisateurs"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "impossible de basculer vers le registre « %s » pour %s"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "impossible de rétablir le registre"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:78 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:171 src/exec_monitor.c:418
+#: src/exec_monitor.c:424 src/exec_monitor.c:432 src/exec_monitor.c:440
+#: src/exec_monitor.c:447 src/exec_monitor.c:454 src/exec_monitor.c:461
+#: src/exec_monitor.c:468 src/exec_monitor.c:475 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:744 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1096
+#: src/exec_ptrace.c:1271 src/exec_ptrace.c:1624 src/exec_ptrace.c:1651
+#: src/exec_ptrace.c:1841 src/exec_pty.c:581 src/exec_pty.c:765
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:193 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:240
+#: src/sesh.c:246 src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:644
+#: src/sudo.c:709 src/sudo.c:719 src/sudo.c:746 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:787 src/sudo.c:805 src/sudo.c:846 src/sudo.c:855 src/sudo.c:865
+#: src/sudo.c:898 src/sudo.c:1127 src/sudo.c:1148 src/sudo.c:1441
+#: src/sudo.c:1610 src/sudo.c:1837 src/sudo.c:2171 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:430 src/sudo_edit.c:439
+#: src/sudo_edit.c:540 src/sudo_edit.c:547 src/sudo_edit.c:692
+#: src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:79 src/exec_intercept.c:111 src/exec_intercept.c:350
+#: src/exec_intercept.c:525 src/exec_intercept.c:589 src/exec_intercept.c:713
+#: src/exec_intercept.c:837 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:418 src/exec_monitor.c:424
+#: src/exec_monitor.c:432 src/exec_monitor.c:440 src/exec_monitor.c:447
+#: src/exec_monitor.c:454 src/exec_monitor.c:461 src/exec_monitor.c:468
+#: src/exec_monitor.c:475 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1651 src/exec_ptrace.c:1842 src/exec_pty.c:581
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:228 src/sudo.c:644 src/sudo.c:898 src/sudo.c:1127
+#: src/sudo.c:1148 src/sudo.c:1441 src/sudo.c:1610 src/sudo.c:1837
+#: src/sudo.c:2171 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:430
+#: src/sudo_edit.c:439 src/sudo_edit.c:540 src/sudo_edit.c:547
+#: src/sudo_edit.c:692 src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "impossible d'allouer la mémoire"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "impossible d'évaluer par stat() %.*s"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s existe mais il n'est pas un répertoire (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:664
+#: lib/util/sudo_conf.c:683 lib/util/sudo_conf.c:710 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:495 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "impossible d'ouvrir %s"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "impossible d'exécuter mkdir %.*s"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "impossible d'ouvrir %.*s"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "l'expression régulière est trop grande"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Signal inconnu"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "valeur incorrecte"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "valeur trop grande"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "valeur trop petite"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "valeur de chemin « %s » incorrecte dans %s, ligne %u"
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "valeur « %2$s » incorrecte pour %1$s dans %3$s, ligne %4$u"
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "source de groupe « %s » non supportée dans %s, ligne %u"
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "groupes max « %s » incorrects dans %s, ligne %u"
+
+#: lib/util/sudo_conf.c:686
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s n'est pas un fichier régulier"
+
+#: lib/util/sudo_conf.c:689 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s est la propriété du uid %u alors que ça devrait être %u"
+
+#: lib/util/sudo_conf.c:693
+#, c-format
+msgid "%s is world writable"
+msgstr "%s peut être écrit par tout le monde"
+
+#: lib/util/sudo_conf.c:696
+#, c-format
+msgid "%s is group writable"
+msgstr "%s peut être écrit par le groupe"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "impossible de déterminer le confinement de AppArmor"
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "impossible de changer le profil de AppArmor en %s"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: tronquer %s à zéro octets ? (y/n) [n] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "n'écrase pas %s"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "impossible de lire depuis %s"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "impossible d'écrire dans %s"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "impossible d'évaluer par stat() %s"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: pas un fichier régulier"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: mauvais mode de fichier : 0%o"
+
+#: src/edit_open.c:333
+msgid "unable to restore current working directory"
+msgstr "impossible de rétablir le répertoire de travail actuel"
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "impossible de définir les privilèges"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "impossible de définir la limite des privilèges"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "classe de login %s inconnue"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "impossible de changer le contexte utilisateur"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "impossible de changer la priorité du processus"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "impossible de changer root en %s"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "impossible de changer vers runas uid (%u, %u)"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "impossible de changer le répertoire vers %s"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "au départ de %s"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:552 src/exec_monitor.c:554
+#: src/exec_pty.c:1122 src/exec_pty.c:1124 src/signal.c:144 src/signal.c:151
+#: src/signal.c:165 src/suspend_parent.c:143
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "impossible de spécifier le gestionnaire pour le signal %d"
+
+#: src/exec.c:424
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "le mode d'interception n'est pas supporté avec SELinux RBAC sur ce système"
+
+#: src/exec.c:429
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "impossible d'écrire les sous-commandes dans le journal avec SELinux RBAC sur ce système"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "impossible de supprimer PRIV_PROC_EXEC de PRIV_LIMIT"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:163 src/exec_iolog.c:173
+#: src/exec_iolog.c:218 src/exec_iolog.c:225 src/exec_iolog.c:252
+#: src/exec_monitor.c:426 src/exec_monitor.c:434 src/exec_monitor.c:442
+#: src/exec_monitor.c:449 src/exec_monitor.c:456 src/exec_monitor.c:463
+#: src/exec_monitor.c:470 src/exec_monitor.c:477 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:457 src/exec_pty.c:432
+#: src/exec_pty.c:537 src/exec_pty.c:587 src/exec_pty.c:965 src/exec_pty.c:974
+#: src/exec_pty.c:981 src/exec_pty.c:988 src/exec_pty.c:995
+#: src/exec_pty.c:1002 src/exec_pty.c:1009 src/exec_pty.c:1016
+#: src/exec_pty.c:1023 src/exec_pty.c:1030 src/exec_pty.c:1037
+#: src/exec_pty.c:1044
+msgid "unable to add event to queue"
+msgstr "impossible d'ajouter l'événement à la queue"
+
+#: src/exec_intercept.c:323 src/sudo.c:1033
+msgid "command not set by the security policy"
+msgstr "commande pas définie par la politique de sécurité"
+
+#: src/exec_intercept.c:401 src/exec_intercept.c:441 src/sudo.c:1253
+#: src/sudo.c:1298 src/sudo.c:1342
+msgid "command rejected by policy"
+msgstr "commande rejetée par la politique"
+
+#: src/exec_intercept.c:512 src/sudo.c:1940
+msgid "approval plugin error"
+msgstr "erreur du greffon d'approbation"
+
+#: src/exec_intercept.c:537 src/sudo.c:1258 src/sudo.c:1303 src/sudo.c:1347
+#: src/sudo.c:1421
+msgid "policy plugin error"
+msgstr "erreur du greffon de politique"
+
+#: src/exec_intercept.c:566
+msgid "invalid PolicyCheckRequest"
+msgstr "PolicyCheckRequest invalide"
+
+#: src/exec_intercept.c:709
+#, c-format
+msgid "client request too large: %zu"
+msgstr "demande client trop grand : %zu"
+
+#: src/exec_intercept.c:751
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "impossible de décompresser %s avec une taille de %zu"
+
+#: src/exec_intercept.c:799
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "valeur %d inattendue pour type_case dans %s de %s"
+
+#: src/exec_intercept.c:825
+#, c-format
+msgid "server message too large: %zu"
+msgstr "message serveur trop grand : %zu"
+
+#: src/exec_iolog.c:321 src/exec_iolog.c:361 src/exec_iolog.c:401
+#: src/exec_iolog.c:452 src/exec_iolog.c:503
+msgid "I/O plugin error"
+msgstr "erreur du greffon d'E/S"
+
+#: src/exec_iolog.c:325 src/exec_iolog.c:365 src/exec_iolog.c:405
+#: src/exec_iolog.c:456 src/exec_iolog.c:507
+msgid "command rejected by I/O plugin"
+msgstr "commande rejetée par le greffon d'E/S"
+
+#: src/exec_iolog.c:555
+msgid "error logging suspend"
+msgstr "l'enregistrement des erreurs est suspendu"
+
+#: src/exec_iolog.c:590
+msgid "error changing window size"
+msgstr "erreur lors du changement de la taille de la fenêtre"
+
+#: src/exec_monitor.c:328
+msgid "error reading from socketpair"
+msgstr "erreur de lecture sur la paire de sockets"
+
+#: src/exec_monitor.c:340
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "réponse inattendue sur le backchannel : %d"
+
+#: src/exec_monitor.c:566
+msgid "unable to set controlling tty"
+msgstr "impossible de choisir le tty de contrôle"
+
+#: src/exec_monitor.c:574 src/exec_nopty.c:504 src/exec_nopty.c:514
+#: src/exec_nopty.c:524 src/exec_nopty.c:560 src/exec_pty.c:1195
+#: src/exec_pty.c:1222 src/exec_pty.c:1242 src/exec_pty.c:1262
+#: src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr "impossible de créer le tube"
+
+#: src/exec_monitor.c:584
+msgid "unable to receive message from parent"
+msgstr "impossible de recevoir un message du parent"
+
+#: src/exec_monitor.c:600 src/exec_nopty.c:603 src/exec_pty.c:1303
+#: src/sudo_edit.c:361 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr "erreur de fork"
+
+#: src/exec_monitor.c:604 src/exec_monitor.c:700 src/exec_nopty.c:708
+msgid "unable to restore tty label"
+msgstr "impossible de rétablir l'étiquette du tty"
+
+#: src/exec_monitor.c:615 src/sesh.c:217 src/sudo.c:1204
+#, c-format
+msgid "unable to execute %s"
+msgstr "impossible d'exécuter %s"
+
+#: src/exec_nopty.c:554 src/exec_pty.c:1131
+msgid "policy plugin failed session initialization"
+msgstr "le greffon de règles a échoué lors de l'initialisation de la session"
+
+#: src/exec_nopty.c:569 src/exec_pty.c:1100 src/exec_pty.c:1109
+msgid "unable to create sockets"
+msgstr "impossible de créer des sockets"
+
+#: src/exec_nopty.c:696 src/exec_pty.c:1406
+msgid "error in event loop"
+msgstr "erreur dans la boucle des événements"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:852 src/sudo.c:488
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "erreur interne, débordement %s"
+
+#: src/exec_ptrace.c:1080 src/exec_ptrace.c:1105 src/exec_ptrace.c:1925
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "impossible de définir les registres pour le processus %d"
+
+#: src/exec_ptrace.c:1100 src/exec_ptrace.c:1275 src/exec_ptrace.c:1628
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "le processus %d s'est terminé de manière inattendue"
+
+#: src/exec_ptrace.c:1209
+msgid "unable to set seccomp filter"
+msgstr "impossible de définir le filtre seccomp"
+
+#: src/exec_ptrace.c:1406
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "interpréteur d'argument, « %s » attendu, « %s » obtenu"
+
+#: src/exec_ptrace.c:1505
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "désaccord dans le nom du chemin, « %s » attendu, « %s » obtenu"
+
+#: src/exec_ptrace.c:1514 src/exec_ptrace.c:1521 src/exec_ptrace.c:1545
+#: src/exec_ptrace.c:1553 src/exec_ptrace.c:1559 src/exec_ptrace.c:1565
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "désaccord dans %s[%d], « %s » attendu, « %s » obtenu"
+
+#: src/exec_ptrace.c:1632
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "le processus %d a retourné le statut inattendu 0x%x"
+
+#: src/exec_ptrace.c:1723
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "impossible d'obtenir le message de l'événement pour le processus %d"
+
+#: src/exec_ptrace.c:1730
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "impossible d'obtenir les registres pour le processus %d"
+
+#: src/exec_pty.c:84
+msgid "unable to allocate pty"
+msgstr "impossible d'allouer le pty"
+
+#: src/exec_pty.c:131 src/exec_pty.c:284 src/tgetpass.c:251
+msgid "unable to restore terminal settings"
+msgstr "impossible de rétablir les paramètres du terminal"
+
+#: src/exec_pty.c:243
+msgid "unable to set handler for SIGCONT"
+msgstr "impossible de spécifier le gestionnaire pour SIGCONT"
+
+#: src/exec_pty.c:293
+#, c-format
+msgid "unable to set handler for SIG%s"
+msgstr "impossible de spécifier le gestionnaire pour SIG%s"
+
+#: src/exec_pty.c:317
+#, c-format
+msgid "unable to restore handler for SIG%s"
+msgstr "impossible de rétablir le gestionnaire pour SIG%s"
+
+#: src/exec_pty.c:345
+msgid "unable to restore handler for SIGCONT"
+msgstr "impossible de rétablir le gestionnaire pour SIGCONT"
+
+#: src/exec_pty.c:1353
+msgid "unable to send message to monitor process"
+msgstr "impossible d'envoyer le message au processus de monitoring"
+
+#: src/load_plugins.c:75 src/load_plugins.c:222 src/load_plugins.c:232
+#: src/load_plugins.c:242 src/load_plugins.c:289
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "erreur dans %s, ligne %d lors du chargement du greffon « %s »"
+
+#: src/load_plugins.c:186 src/load_plugins.c:257
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "ignore le greffon en double « %s » dans %s, ligne %d"
+
+#: src/load_plugins.c:224
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "impossible de charger %s : %s"
+
+#: src/load_plugins.c:234
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "impossible de trouver le symbole « %s » dans %s"
+
+#: src/load_plugins.c:244
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "greffon à la version majeure %d incompatible (%d attendu) trouvé dans %s"
+
+#: src/load_plugins.c:262
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "ignore le greffon de règles « %s » dans %s, ligne %d"
+
+#: src/load_plugins.c:265
+msgid "only a single policy plugin may be specified"
+msgstr "un seul greffon de règles peut être spécifié"
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "type de greffon %d inconnu dans %s"
+
+#: src/load_plugins.c:474
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "le greffon de règles %s ne contient pas de méthode check_policy"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "nom de variable d'environnement invalide: %s"
+
+#: src/parse_args.c:319
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "l'argument à -C doit être un nombre plus grand ou égal à 3"
+
+#: src/parse_args.c:556
+msgid "you may not specify both the -i and -s options"
+msgstr "vous ne pouvez pas spécifier les options -i et -s en même temps"
+
+#: src/parse_args.c:561
+msgid "you may not specify both the -i and -E options"
+msgstr "vous ne pouvez pas spécifier les options -i et -E en même temps"
+
+#: src/parse_args.c:571
+msgid "the -E option is not valid in edit mode"
+msgstr "l'option -E n'est pas valable en mode édition"
+
+#: src/parse_args.c:574
+msgid "you may not specify environment variables in edit mode"
+msgstr "vous ne pouvez pas spécifier de variable d'environnement en mode édition"
+
+#: src/parse_args.c:584
+msgid "the -U option may only be used with the -l option"
+msgstr "l'option -U ne peut être utilisée qu'avec l'option -l"
+
+#: src/parse_args.c:588
+msgid "the -A and -S options may not be used together"
+msgstr "les options -A et -S ne peuvent pas être utilisées ensemble"
+
+#: src/parse_args.c:686
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit n'est pas pris en charge sur cette plate-forme"
+
+#: src/parse_args.c:744
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Seule une des options -e, -h, -i, -K, -l, -s, -v ou -V peut être spécifiée"
+
+#: src/parse_args.c:757
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "Seule une des options -K, -k ou -N peut être spécifiée"
+
+#: src/parse_args.c:778
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s – édite les fichiers en tant qu'un autre utilisateur\n"
+"\n"
+
+#: src/parse_args.c:780
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s – exécute une commande en tant qu'un autre utilisateur\n"
+"\n"
+
+#: src/parse_args.c:785
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Options:\n"
+
+#: src/parse_args.c:787
+msgid "use a helper program for password prompting"
+msgstr "utiliser un programme adjoint pour demander le mot de passe"
+
+#: src/parse_args.c:790
+msgid "use specified BSD authentication type"
+msgstr "utiliser le type d'authentification BSD spécifié"
+
+#: src/parse_args.c:794
+msgid "run command in the background"
+msgstr "exécuter la commande en arrière-plan"
+
+#: src/parse_args.c:797
+msgid "ring bell when prompting"
+msgstr "émettre un signal sonore lors d'une demande"
+
+#: src/parse_args.c:799
+msgid "close all file descriptors >= num"
+msgstr "fermer tous les descripteurs de fichiers >= n°"
+
+#: src/parse_args.c:802
+msgid "run command with the specified BSD login class"
+msgstr "exécuter la commande avec la classe de login BSD"
+
+#: src/parse_args.c:805
+msgid "change the working directory before running command"
+msgstr "changer le répertoire de travail avant d'exécuter la commande"
+
+#: src/parse_args.c:808
+msgid "preserve user environment when running command"
+msgstr "préserver l'environnement de l'utilisateur en exécutant la commande"
+
+#: src/parse_args.c:810
+msgid "preserve specific environment variables"
+msgstr "préserver les variables d'environnement spécifiques"
+
+#: src/parse_args.c:812
+msgid "edit files instead of running a command"
+msgstr "éditer les fichiers au lieu d'exécuter une commande"
+
+#: src/parse_args.c:815
+msgid "run command as the specified group name or ID"
+msgstr "exécuter la commande en tant que le nom ou ID de groupe spécifié"
+
+#: src/parse_args.c:818
+msgid "set HOME variable to target user's home dir"
+msgstr "assigner à la variable HOME le répertoire personnel de l'utilisateur cible"
+
+#: src/parse_args.c:821
+msgid "display help message and exit"
+msgstr "afficher le message d'aide et terminer"
+
+#: src/parse_args.c:823
+msgid "run command on host (if supported by plugin)"
+msgstr "exécuter la commande sur l'hôte (si supporté par le greffon)"
+
+#: src/parse_args.c:826
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "exécuter le shell de login comme l'utilisateur cible. Une commande peut aussi être spécifiée"
+
+#: src/parse_args.c:828
+msgid "remove timestamp file completely"
+msgstr "supprime complètement le fichier d'horodatage"
+
+#: src/parse_args.c:831
+msgid "invalidate timestamp file"
+msgstr "invalide le fichier d'horodatage"
+
+#: src/parse_args.c:834
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "afficher les privilèges de l'utilisateur ou vérifie une commande spécifique. Utilisez deux fois pour une forme plus longue"
+
+#: src/parse_args.c:837
+msgid "non-interactive mode, no prompts are used"
+msgstr "mode non interactif, aucune invite utilisée"
+
+#: src/parse_args.c:840
+msgid "preserve group vector instead of setting to target's"
+msgstr "préserve le vecteur des groupes au lieu de le changer en celui de la cible"
+
+#: src/parse_args.c:843
+msgid "use the specified password prompt"
+msgstr "utiliser l'invite de mot de passe spécifié"
+
+#: src/parse_args.c:845
+msgid "change the root directory before running command"
+msgstr "changer le répertoire racine avant d'exécuter la commande"
+
+#: src/parse_args.c:848
+msgid "create SELinux security context with specified role"
+msgstr "créer le contexte de sécurité SELinux avec le rôle spécifié"
+
+#: src/parse_args.c:851
+msgid "read password from standard input"
+msgstr "lire le mot de passe depuis l'entrée standard"
+
+#: src/parse_args.c:854
+msgid "run shell as the target user; a command may also be specified"
+msgstr "exécuter le shell en tant que l'utilisateur cible. Une commande peut aussi être spécifiée"
+
+#: src/parse_args.c:858
+msgid "create SELinux security context with specified type"
+msgstr "créer le contexte de sécurité SELinux avec le type spécifié"
+
+#: src/parse_args.c:861
+msgid "terminate command after the specified time limit"
+msgstr "terminer la commande après la limite de temps spécifiée"
+
+#: src/parse_args.c:864
+msgid "in list mode, display privileges for user"
+msgstr "en mode liste, afficher les privilèges de l'utilisateur"
+
+#: src/parse_args.c:867
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "exécuter la commande (ou éditer le fichier) sous le nom d'utilisateur ou le ID spécifié"
+
+#: src/parse_args.c:869
+msgid "display version information and exit"
+msgstr "afficher les informations de version et terminer"
+
+#: src/parse_args.c:872
+msgid "update user's timestamp without running a command"
+msgstr "mettre à jour l'horodatage de l'utilisateur sans exécuter de commande"
+
+#: src/parse_args.c:875
+msgid "stop processing command line arguments"
+msgstr "arrêter de traiter les arguments en ligne de commande"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "impossible d'ouvrir le système d'audit"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "impossible d'envoyer le message d'audit"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "impossible d'exécuter fgetfilecon %s"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s à changé des étiquettes"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "impossible de rétablir le contexte de %s"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "impossible d'ouvrir %s, le tty n'est pas ré-étiqueté"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s n'est pas un périphérique caractères, le tty n'est pas ré-étiqueté"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "impossible d'obtenir le contexte actuel du tty, le tty n'est pas ré-étiqueté"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "classe de sécurité « chr_file » inconnue, le tty n'est pas ré-étiqueté"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "impossible d'obtenir le nouveau contexte du tty, le tty n'est pas ré-étiqueté"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "impossible de changer le nouveau contexte du tty"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "vous devez spécifier un rôle pour le type %s"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "impossible d'obtenir le type par défaut pour le rôle %s"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "échec de l'obtention du nouveau contexte"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "échec lors du changement du nouveau rôle %s"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "échec lors du changement du nouveau type %s"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s n'est pas un contexte valide"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "échec de l'obtention de l'ancien contexte"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "impossible de déterminer le mode de contrainte"
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "impossible de changer le contexte exec en %s"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "impossible de changer le contexte de création de clé en %s"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "Seule une des options -c ou -i peut être spécifiée"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "numéro de descripteur de fichier invalide: %s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "L'option -%c n'est pas valable en mode édition."
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "L'option -%c ne peut être utilisée qu'en mode édition."
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: l'édition de liens symboliques n'est pas permise"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: l'édition de fichiers dans un répertoire accessible en écriture n'est pas permis"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "contenu de la session d'édition laissé dans %s"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "impossible d'obtenir la liste des groupes"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "impossible de sauvegarder le gestionnaire du signal %d"
+
+#: src/signal.c:101 src/suspend_parent.c:149
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "impossible de rétablir le gestionnaire pour le signal %d"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "la limite de contrôle de la ressource a été atteinte"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "l'utilisateur « %s » n'est pas un membre du projet « %s »"
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "la tâche appelante est « final »"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "impossible de joindre le projet « %s »"
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "aucun pool de ressources acceptant les liaisons par défaut existe pour le projet « %s »"
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "le pool de ressources spécifié n'existe pas pour le projet « %s »"
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "impossible de se lier au pool de ressources par défaut du projet « %s »"
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "setproject a échoué pour le projet « %s »"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "attention, l'assignement du contrôle de ressources a échoue pour le projet « %s »"
+
+#: src/sudo.c:214
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo version %s\n"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Options de configuration : %s\n"
+
+#: src/sudo.c:224
+msgid "fatal error, unable to load plugins"
+msgstr "erreur fatale, impossible de charger les greffons"
+
+#: src/sudo.c:270
+msgid "plugin did not return a command to execute"
+msgstr "le greffon n'a pas retourné une commande à exécuter"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "mode sudo 0x%x inattendu"
+
+#: src/sudo.c:559
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "vous n'existez pas dans la base de données %s"
+
+#: src/sudo.c:616
+msgid "unable to determine tty"
+msgstr "impossible de déterminer le tty"
+
+#: src/sudo.c:932
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "Le fanion « no new privileges » (« pas de nouveau privilèges ») est défini. Il empêche sudo de s'exécuter en tant que root."
+
+#: src/sudo.c:934
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "Si sudo est exécuté dans un conteneur, vous devrez ajuster la configuration du conteneur pour désactiver ce fanion."
+
+#: src/sudo.c:968
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s doit être la propriété du uid %d et avoir le bit setuid mis"
+
+#: src/sudo.c:971
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "le uid effectif n'est pas %d. Est-ce que %s est sur un système de fichiers avec l'option « nosuid » ou un système de fichiers NFS sans privilèges root ?"
+
+#: src/sudo.c:977
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "le uid effectif n'est pas %d. Est-ce que sudo est installé setuid root ?"
+
+#: src/sudo.c:993 src/tgetpass.c:332
+msgid "unable to set supplementary group IDs"
+msgstr "impossible d'attribuer les ID de groupe supplémentaires"
+
+#: src/sudo.c:1000
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "impossible de changer le gid effectif à runas gid %u"
+
+#: src/sudo.c:1006
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "impossible de changer le gid à runas gid %u"
+
+#: src/sudo.c:1037
+msgid "argv not set by the security policy"
+msgstr "argv pas défini par la politique de sécurité"
+
+#: src/sudo.c:1041
+msgid "envp not set by the security policy"
+msgstr "envp pas défini par la politique de sécurité"
+
+#: src/sudo.c:1063
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "condition de fin de l'enfant inconnue: %d"
+
+#: src/sudo.c:1176
+msgid "unable to initialize policy plugin"
+msgstr "impossible d'initialiser le greffon de règles"
+
+#: src/sudo.c:1238
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "le greffon de règles %s n'a pas de méthode « check_policy »"
+
+#: src/sudo.c:1284
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "le greffon de règles %s ne supporte pas les privilèges de listage"
+
+#: src/sudo.c:1328
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "le greffon de règles %s ne supporte pas l'option -v"
+
+#: src/sudo.c:1366
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "le greffon de règles %s ne supporte pas les options -k/-K"
+
+#: src/sudo.c:1495
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "erreur à l'initialisation du greffon E/S %s"
+
+#: src/sudo.c:1498
+msgid "error initializing I/O plugin"
+msgstr "erreur à l'initialisation du greffon E/S"
+
+#: src/sudo.c:1647
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "erreur à l'initialisation du greffon d'audit %s"
+
+#: src/sudo.c:1726
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: impossible d'enregistrer dans le journal l'événement d'erreur%s%s"
+
+#: src/sudo.c:1762
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: impossible d'enregistrer dans le journal l'événement d'acceptation%s%s"
+
+#: src/sudo.c:1767 src/sudo.c:1805
+msgid "audit plugin error"
+msgstr "erreur du greffon d'audit"
+
+#: src/sudo.c:1800
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: impossible d'enregistrer dans le journal l'événement de rejet%s%s"
+
+#: src/sudo.c:1860
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "erreur à l'initialisation du greffon d'approbation %s"
+
+#: src/sudo.c:1930
+msgid "command rejected by approver"
+msgstr "commande rejetée par l'approbateur"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "aucun répertoire temporaire est disponible en écriture"
+
+#: src/sudo_edit.c:292
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s laissé tel quel"
+
+#: src/sudo_edit.c:305 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s non modifié"
+
+#: src/sudo_edit.c:482
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: erreur interne: nombre impaire de chemins"
+
+#: src/sudo_edit.c:484
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: impossible de créer des fichiers temporaires"
+
+#: src/sudo_edit.c:486 src/sudo_edit.c:606
+msgid "sesh: killed by a signal"
+msgstr "sesh: tué par un signal"
+
+#: src/sudo_edit.c:488 src/sudo_edit.c:609
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: erreur %d inconnue"
+
+#: src/sudo_edit.c:599
+msgid "unable to copy temporary files back to their original location"
+msgstr "impossible de copier les fichiers temporaires à leurs emplacements d'origine"
+
+#: src/sudo_edit.c:603
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "impossible de copier quelques fichiers temporaires à leurs emplacements d'origine"
+
+#: src/sudo_edit.c:650
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "impossible de changer le uid en root (%u)"
+
+#: src/sudo_edit.c:664
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "erreur de greffon : liste de fichiers invalide pour sudoedit"
+
+#: src/sudo_edit.c:685
+msgid "plugin error: missing file list for sudoedit"
+msgstr "erreur de greffon : liste de fichiers manquantes pour sudoedit"
+
+#: src/sudo_edit.c:728 src/sudo_edit.c:743
+msgid "unable to read the clock"
+msgstr "impossible de lire l'horloge"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "port d'interception non défini"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "délai d'attente dépassé durant la lecture du mot de passe"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "aucun mot de passe fourni"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "impossible de lire le mot de passe"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "un terminal est requis pour lire le mot de passe; utilisez soit l'option -S pour lire depuis l'entrée standard ou configurez un outil askpass de demande de mot de passe"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "pas de programme askpass spécifié, essayez avec SUDO_ASKPASS"
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "impossible de changer le gid en %u"
+
+#: src/tgetpass.c:337
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "impossible de changer le uid en %u"
+
+#: src/tgetpass.c:342
+#, c-format
+msgid "unable to run %s"
+msgstr "impossible d'exécuter %s"
+
+#: src/utmp.c:283
+msgid "unable to save stdin"
+msgstr "impossible de sauvegarder stdin"
+
+#: src/utmp.c:285
+msgid "unable to dup2 stdin"
+msgstr "impossible d'exécuter dup2 sur stdin"
+
+#: src/utmp.c:288
+msgid "unable to restore stdin"
+msgstr "impossible de rétablir stdin"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s doit être la propriété du uid %d"
+
+#~ msgid "%s must be only be writable by owner"
+#~ msgstr "seul le propriétaire doit pouvoir écrire dans %s"
+
+#~ msgid "insufficient space for execve arguments"
+#~ msgstr "espace insuffisant pour les arguments de execve"
+
+#~ msgid "unable to read execve %s for process %d"
+#~ msgstr "impossible de lire execve %s pour le processus %d"
+
+#~ msgid "requires at least one argument"
+#~ msgstr "exige au moins un argument"
+
+#~ msgid "unable to run %s as a login shell"
+#~ msgstr "impossible d'exécuter %s comme un shell de login"
+
+#~ msgid "unable to dup intercept fd"
+#~ msgstr "impossible de dupliquer le fd intercepté"
+
+#~ msgid "%s: missing message header"
+#~ msgstr "%s: en-tête de message manquant"
+
+#~ msgid "%s: expected message type %d, got %d"
+#~ msgstr "%s: type de message %d attendu, %d obtenu"
+
+#~ msgid "unable to set tty context to %s"
+#~ msgstr "impossible de changer le contexte du tty en %s"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s: %s"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s: écriture trop courte"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "impossible de lire le fichier temporaire"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "ignore le greffon de règles en double « %s » dans %s, ligne %d"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "pas de tty présent et pas de programme askpass spécifié"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "uid %u inconnu : qui êtes-vous ?"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "erreur lors de la lecture du tube signal"
+
+#~ msgid "unable to set terminal to raw mode"
+#~ msgstr "impossible de mettre le terminal en mode brut"
+
+#~ msgid "internal error, tried allocate zero bytes"
+#~ msgstr "erreur interne, a tenté d'allouer zéro octets"
+
+#~ msgid "unable to open socket"
+#~ msgstr "impossible d'ouvrir la socket"
+
+#~ msgid "internal error, tried to emalloc2(0)"
+#~ msgstr "erreur interne, emalloc2(0) a été tenté"
+
+#~ msgid "internal error, tried to ecalloc(0)"
+#~ msgstr "erreur interne, ecalloc(0) a été tenté"
+
+#~ msgid "internal error, tried to erealloc(0)"
+#~ msgstr "erreur interne, erealloc(0) a été tenté"
+
+#~ msgid "internal error, tried to erealloc3(0)"
+#~ msgstr "erreur interne, erealloc3(0) a été tenté"
+
+#~ msgid "internal error, tried to erecalloc(0)"
+#~ msgstr "erreur interne, erecalloc(0) a été tenté"
+
+#~ msgid "value out of range"
+#~ msgstr "valeur hors limites"
+
+#~ msgid "%s: %s: %s\n"
+#~ msgstr "%s: %s: %s\n"
+
+#~ msgid "%s: %s\n"
+#~ msgstr "%s: %s\n"
+
+#~ msgid "select failed"
+#~ msgstr "select a échoué"
+
+#~ msgid "load_interfaces: overflow detected"
+#~ msgstr "load_interfaces: débordement détecté"
diff --git a/po/fur.mo b/po/fur.mo
new file mode 100644
index 0000000..80dfd81
--- /dev/null
+++ b/po/fur.mo
Binary files differ
diff --git a/po/fur.po b/po/fur.po
new file mode 100644
index 0000000..eacd795
--- /dev/null
+++ b/po/fur.po
@@ -0,0 +1,1212 @@
+# Friulian translations for sudo package
+# This file is put in the public domain.
+# Fabio Tomat <f.t.public@gmail.com>, 2023
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo-1.9.13b2\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-01-24 13:11-0700\n"
+"PO-Revision-Date: 2023-02-01 16:47+0000\n"
+"Last-Translator: Fabio T. <f.t.public@gmail.com>\n"
+"Language-Team: Friulian <f.t.public@gmail.com>\n"
+"Language: fur\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Editor: HaiPO 1.4 beta\n"
+"X-Generator: Poedit 1.8.12\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "impussibil vierzi userdb"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "impussibil passâ al regjistri \"%s\" par %s"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "impussibil ripristinâ il regjistri"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:646
+#: src/conversation.c:80 src/exec_iolog.c:124 src/exec_iolog.c:135
+#: src/exec_iolog.c:212 src/exec_monitor.c:205 src/exec_monitor.c:460
+#: src/exec_monitor.c:466 src/exec_monitor.c:474 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_monitor.c:496 src/exec_monitor.c:503
+#: src/exec_monitor.c:510 src/exec_monitor.c:517 src/exec_monitor.c:524
+#: src/exec_monitor.c:531 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:736 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1095
+#: src/exec_ptrace.c:1270 src/exec_ptrace.c:1612 src/exec_ptrace.c:1639
+#: src/exec_pty.c:511 src/exec_pty.c:692 src/exec_pty.c:882 src/exec_pty.c:891
+#: src/exec_pty.c:898 src/exec_pty.c:905 src/exec_pty.c:912 src/exec_pty.c:919
+#: src/exec_pty.c:926 src/exec_pty.c:933 src/exec_pty.c:940 src/exec_pty.c:947
+#: src/exec_pty.c:954 src/exec_pty.c:962 src/load_plugins.c:98
+#: src/load_plugins.c:123 src/load_plugins.c:159 src/load_plugins.c:392
+#: src/load_plugins.c:398 src/parse_args.c:172 src/parse_args.c:193
+#: src/parse_args.c:267 src/parse_args.c:623 src/parse_args.c:645
+#: src/parse_args.c:670 src/preserve_fds.c:46 src/preserve_fds.c:131
+#: src/selinux.c:89 src/selinux.c:362 src/selinux.c:472 src/selinux.c:489
+#: src/selinux.c:496 src/sesh.c:206 src/sesh.c:240 src/sesh.c:246
+#: src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:641 src/sudo.c:706
+#: src/sudo.c:716 src/sudo.c:743 src/sudo.c:766 src/sudo.c:775 src/sudo.c:784
+#: src/sudo.c:801 src/sudo.c:842 src/sudo.c:851 src/sudo.c:861 src/sudo.c:894
+#: src/sudo.c:1122 src/sudo.c:1143 src/sudo.c:1436 src/sudo.c:1605
+#: src/sudo.c:1832 src/sudo.c:2166 src/sudo_edit.c:89 src/sudo_edit.c:149
+#: src/sudo_edit.c:429 src/sudo_edit.c:438 src/sudo_edit.c:538
+#: src/sudo_edit.c:545 src/sudo_edit.c:688 src/sudo_edit.c:708
+#: src/sudo_intercept_common.c:115 src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:646
+#: src/conversation.c:81 src/exec_intercept.c:111 src/exec_intercept.c:344
+#: src/exec_intercept.c:518 src/exec_intercept.c:582 src/exec_intercept.c:706
+#: src/exec_intercept.c:830 src/exec_iolog.c:124 src/exec_iolog.c:135
+#: src/exec_iolog.c:212 src/exec_monitor.c:460 src/exec_monitor.c:466
+#: src/exec_monitor.c:474 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_monitor.c:496 src/exec_monitor.c:503 src/exec_monitor.c:510
+#: src/exec_monitor.c:517 src/exec_monitor.c:524 src/exec_monitor.c:531
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1639 src/exec_pty.c:511 src/exec_pty.c:882
+#: src/exec_pty.c:891 src/exec_pty.c:898 src/exec_pty.c:905 src/exec_pty.c:912
+#: src/exec_pty.c:919 src/exec_pty.c:926 src/exec_pty.c:933 src/exec_pty.c:940
+#: src/exec_pty.c:947 src/exec_pty.c:954 src/exec_pty.c:962
+#: src/load_plugins.c:98 src/load_plugins.c:123 src/load_plugins.c:159
+#: src/load_plugins.c:392 src/load_plugins.c:398 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:267 src/parse_args.c:623
+#: src/parse_args.c:645 src/parse_args.c:670 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:230 src/sudo.c:641 src/sudo.c:894 src/sudo.c:1122
+#: src/sudo.c:1143 src/sudo.c:1436 src/sudo.c:1605 src/sudo.c:1832
+#: src/sudo.c:2166 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:429
+#: src/sudo_edit.c:438 src/sudo_edit.c:538 src/sudo_edit.c:545
+#: src/sudo_edit.c:688 src/sudo_edit.c:708 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "impussibil assegnâ memorie"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "impussibil eseguî stat %.*s"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s al esist ma no je une cartele (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:666
+#: lib/util/sudo_conf.c:696 lib/util/sudo_conf.c:703 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:494 src/sudo_edit.c:557
+#, c-format
+msgid "unable to open %s"
+msgstr "impussibil vierzi %s"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "impussibil eseguî mkdir %.*s"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "impussibil vierzi %.*s"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "espression regolâr masse grande"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Segnâl no cognossût"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "valôr no valit"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "valôr masse grant"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "valôr masse piçul"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "il valôr percors \"%s\" no valit in %s, rie %u"
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "valôr no valit par %s \"%s\" in %s, rie %u"
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "sorzint di grup \"%s\" no supuartade in %s, rie %u"
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "grups massims \"%s\" no valits in %s, rie %u"
+
+#: lib/util/sudo_conf.c:669
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s nol è un file regolâr"
+
+#: lib/util/sudo_conf.c:672 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s al è dal uid %u, al varès di jessi di %u"
+
+#: lib/util/sudo_conf.c:676
+#, c-format
+msgid "%s is world writable"
+msgstr "ducj a puedin scrivi su %s"
+
+#: lib/util/sudo_conf.c:679
+#, c-format
+msgid "%s is group writable"
+msgstr "il grup al pues scrivi su %s"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "impussibil determinâ il confinament di AppArmor"
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "impussibil cambiâ il profîl AppArmor a %s"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: cjonçâ %s a zero bytes? (y/n) [n] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "no si larà a sorescrivi %s"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "impussibil lei di %s"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "impussibil scrivi su %s"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "impussibil eseguî stat su %s"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: nol è un file regolâr."
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: modalitât file sbaliade: 0%o"
+
+#: src/edit_open.c:331
+msgid "unable to restore current working directory"
+msgstr "impussibil ripristinâ la cartele di lavôr atuâl"
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "impussibil configurâ i privileçs"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "impussibil configurâ i privileçs di limit"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "classe di acès %s no cognossude"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "impussibil stabilî il contest utent"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "impussibil stabilî la prioritât dal procès"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "impussibil cambiâ root a %s"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "impussibil passâ a un diviers uid (%u, %u)"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "impussibil passâ ae cartele a %s"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "daûr a scomençâ di %s"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:569 src/exec_monitor.c:571
+#: src/exec_pty.c:225 src/exec_pty.c:1026 src/exec_pty.c:1028 src/signal.c:144
+#: src/signal.c:151 src/signal.c:165 src/suspend_nopty.c:93
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "impussibil stabilî il gjestôr pal segnâl %d"
+
+#: src/exec.c:422
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "la modalitât di intercetazion no je supuartade cun SELinux RBAC su chest sisteme"
+
+#: src/exec.c:427
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "impussibil regjistrâ i sot-comants cun SELinux RBAC su chest sisteme"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "impussibil gjavâ PRIV_PROC_EXEC dal PRIV_LIMIT"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:165 src/exec_iolog.c:175
+#: src/exec_iolog.c:220 src/exec_iolog.c:227 src/exec_iolog.c:254
+#: src/exec_monitor.c:468 src/exec_monitor.c:476 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_monitor.c:498 src/exec_monitor.c:505
+#: src/exec_monitor.c:512 src/exec_monitor.c:519 src/exec_monitor.c:526
+#: src/exec_monitor.c:533 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:453 src/exec_pty.c:360
+#: src/exec_pty.c:462 src/exec_pty.c:517 src/exec_pty.c:884 src/exec_pty.c:893
+#: src/exec_pty.c:900 src/exec_pty.c:907 src/exec_pty.c:914 src/exec_pty.c:921
+#: src/exec_pty.c:928 src/exec_pty.c:935 src/exec_pty.c:942 src/exec_pty.c:949
+#: src/exec_pty.c:956
+msgid "unable to add event to queue"
+msgstr "impussibil zontâ l'event ae code"
+
+#: src/exec_intercept.c:317 src/sudo.c:1028
+msgid "command not set by the security policy"
+msgstr "comant no configurât de politiche di sigurece"
+
+#: src/exec_intercept.c:395 src/exec_intercept.c:435 src/sudo.c:1248
+#: src/sudo.c:1293 src/sudo.c:1337
+msgid "command rejected by policy"
+msgstr "comant refudât de politiche"
+
+#: src/exec_intercept.c:505 src/sudo.c:1935
+msgid "approval plugin error"
+msgstr "erôr dal plugin di aprovazion"
+
+#: src/exec_intercept.c:530 src/sudo.c:1253 src/sudo.c:1298 src/sudo.c:1342
+#: src/sudo.c:1416
+msgid "policy plugin error"
+msgstr "erôr dal plugin de politiche"
+
+#: src/exec_intercept.c:559
+msgid "invalid PolicyCheckRequest"
+msgstr "PolicyCheckRequest no valit"
+
+#: src/exec_intercept.c:702
+#, c-format
+msgid "client request too large: %zu"
+msgstr "richieste dal client masse grande: %zu"
+
+#: src/exec_intercept.c:744
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "impussibil decomprimi %s cun dimension di %zu"
+
+#: src/exec_intercept.c:792
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "valôr di type_case %d inspietât in %s di %s"
+
+#: src/exec_intercept.c:818
+#, c-format
+msgid "server message too large: %zu"
+msgstr "messaç dal servidôr masse grant: %zu"
+
+#: src/exec_iolog.c:323 src/exec_iolog.c:363 src/exec_iolog.c:403
+#: src/exec_iolog.c:454 src/exec_iolog.c:505
+msgid "I/O plugin error"
+msgstr "erôr dal plugin di I/O"
+
+#: src/exec_iolog.c:327 src/exec_iolog.c:367 src/exec_iolog.c:407
+#: src/exec_iolog.c:458 src/exec_iolog.c:509
+msgid "command rejected by I/O plugin"
+msgstr "comant refudât dal plugin di I/O"
+
+#: src/exec_iolog.c:556
+msgid "error logging suspend"
+msgstr "regjistrazion erôrs sospindude"
+
+#: src/exec_iolog.c:591
+msgid "error changing window size"
+msgstr "erôr tal cambiâ la dimension dal barcon"
+
+#: src/exec_monitor.c:362
+msgid "error reading from socketpair"
+msgstr "erôr tal lei dal socketpair"
+
+#: src/exec_monitor.c:379
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "gjenar di rispueste inspietade sul backchannel: %d"
+
+#: src/exec_monitor.c:587
+msgid "unable to set controlling tty"
+msgstr "impussibil stabilî il tty di control"
+
+#: src/exec_monitor.c:595 src/exec_nopty.c:498 src/exec_nopty.c:508
+#: src/exec_nopty.c:518 src/exec_nopty.c:552 src/exec_pty.c:1097
+#: src/exec_pty.c:1118 src/exec_pty.c:1138 src/tgetpass.c:305
+msgid "unable to create pipe"
+msgstr "impussibil creâ il condot (pipe)"
+
+#: src/exec_monitor.c:605
+msgid "unable to receive message from parent"
+msgstr "impussibil ricevi il messaç dal gjenitôr"
+
+#: src/exec_monitor.c:621 src/exec_nopty.c:595 src/exec_pty.c:1176
+#: src/sudo_edit.c:361 src/tgetpass.c:309
+msgid "unable to fork"
+msgstr "impussibil inglovâ (fâ il fork)"
+
+#: src/exec_monitor.c:625 src/exec_monitor.c:723 src/exec_nopty.c:700
+msgid "unable to restore tty label"
+msgstr "impussibil ripristinâ la etichete tty"
+
+#: src/exec_monitor.c:638 src/sesh.c:217 src/sudo.c:1199
+#, c-format
+msgid "unable to execute %s"
+msgstr "impussibil eseguî %s"
+
+#: src/exec_nopty.c:546 src/exec_pty.c:1035
+msgid "policy plugin failed session initialization"
+msgstr "il plugin di politche nol è rivât a inizializâ la session"
+
+#: src/exec_nopty.c:561 src/exec_pty.c:1004 src/exec_pty.c:1013
+msgid "unable to create sockets"
+msgstr "impussibil creâ sockets"
+
+#: src/exec_nopty.c:688 src/exec_pty.c:1274
+msgid "error in event loop"
+msgstr "erôr tal cicli dal event"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:851 src/sudo.c:488
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "erôr interni, %s overflow (stranfât)"
+
+#: src/exec_ptrace.c:1079 src/exec_ptrace.c:1104 src/exec_ptrace.c:1900
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "impussibil configurâ i regjistris pal procès %d"
+
+#: src/exec_ptrace.c:1099 src/exec_ptrace.c:1274 src/exec_ptrace.c:1616
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "il procès %d al è jessût in maniere inspietade"
+
+#: src/exec_ptrace.c:1208
+msgid "unable to set seccomp filter"
+msgstr "impussibil configurâ il filtri seccomp"
+
+#: src/exec_ptrace.c:1405
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "argoment dal interprete, si spietave \"%s\", si à vût \"%s\""
+
+#: src/exec_ptrace.c:1504
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "mancjade corispondence cul non dal percors, si spietave \"%s\", si à vût \"%s\""
+
+#: src/exec_ptrace.c:1513 src/exec_ptrace.c:1520 src/exec_ptrace.c:1533
+#: src/exec_ptrace.c:1541 src/exec_ptrace.c:1547 src/exec_ptrace.c:1553
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "mancjade corispondence %s[%d], si spietave \"%s\", si à vût \"%s\""
+
+#: src/exec_ptrace.c:1620
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "il procès %d al à tornât il stât inspietât 0x%x"
+
+#: src/exec_ptrace.c:1711
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "impussibil otignî il messaç dal event pal procès %d"
+
+#: src/exec_ptrace.c:1718
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "impussibil otignî i regjistris pal procès %d"
+
+#: src/exec_pty.c:103
+msgid "unable to allocate pty"
+msgstr "impussibil assegnâ pty"
+
+#: src/exec_pty.c:268 src/signal.c:101 src/suspend_nopty.c:99
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "impussibil ripristinâ il gjestôr pal segnâl %d"
+
+#: src/exec_pty.c:1222
+msgid "unable to send message to monitor process"
+msgstr "impussibil inviâ il messaç par monitorâ il procès"
+
+#: src/load_plugins.c:73 src/load_plugins.c:220 src/load_plugins.c:230
+#: src/load_plugins.c:240 src/load_plugins.c:287
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "erôr in %s, rie %d intant che si cjariave il plugin \"%s\""
+
+#: src/load_plugins.c:184 src/load_plugins.c:255
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "si ignore il plugin duplicât \"%s\" in %s, rie %d"
+
+#: src/load_plugins.c:222
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "impussibil cjariâ %s: %s"
+
+#: src/load_plugins.c:232
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "impussibil cjatâ il simbul \"%s\" in %s"
+
+#: src/load_plugins.c:242
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "numar principâl di version dal plugin %d no compatibil (si spietave %d) cjatât in %s"
+
+#: src/load_plugins.c:260
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "si ignore il plugin di politiche \"%s\" in %s, rie %d"
+
+#: src/load_plugins.c:263
+msgid "only a single policy plugin may be specified"
+msgstr "dome un singul plugin di politiche al podarès jessi specificât"
+
+#: src/load_plugins.c:289
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "gjenar di plugin %d no cognossût, cjatât in %s"
+
+#: src/load_plugins.c:472
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "il plugin di politiche %s nol inclût un metodi check_policy"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "non de variabile di ambient no valit: %s"
+
+#: src/parse_args.c:317
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "l'argoment di -C al scugne jessi un numar plui grant o compagn a 3"
+
+#: src/parse_args.c:554
+msgid "you may not specify both the -i and -s options"
+msgstr "no tu puedis specificâ dutis dôs lis opzions -i e -s"
+
+#: src/parse_args.c:559
+msgid "you may not specify both the -i and -E options"
+msgstr "no tu puedis specificâ dutis dôs lis opzions -i e -E"
+
+#: src/parse_args.c:569
+msgid "the -E option is not valid in edit mode"
+msgstr "la opzion -E no je valide te modalitât di modifiche"
+
+#: src/parse_args.c:572
+msgid "you may not specify environment variables in edit mode"
+msgstr "no si podarès specificâ lis variabilis di ambient inte modalitât di modifiche"
+
+#: src/parse_args.c:582
+msgid "the -U option may only be used with the -l option"
+msgstr "al è pussibil doprâ la opzion -U dome cu la opzion -l"
+
+#: src/parse_args.c:586
+msgid "the -A and -S options may not be used together"
+msgstr "nol è pussibil doprâ adun lis opzions -A e -S"
+
+#: src/parse_args.c:684
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit nol è supuartât su cheste plateforme"
+
+#: src/parse_args.c:767
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Dome une des opzions -e, -h, -i, -K, -l, -s, -v o -V e podarès jessi specificade"
+
+#: src/parse_args.c:780
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "Al è pussibil specificâ dome une des opzions -K, -k, -N"
+
+#: src/parse_args.c:796
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - modifiche i file come altri utent\n"
+"\n"
+
+#: src/parse_args.c:798
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - eseguìs un comant come altri utent\n"
+"\n"
+
+#: src/parse_args.c:804
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Opzions:\n"
+
+#: src/parse_args.c:806
+msgid "use a helper program for password prompting"
+msgstr "Dopre un program di jutori par domandâ la password"
+
+#: src/parse_args.c:809
+msgid "use specified BSD authentication type"
+msgstr "dopre il gjenar di autenticazion BSD specificât"
+
+#: src/parse_args.c:813
+msgid "run command in the background"
+msgstr "eseguìs il comant in background"
+
+#: src/parse_args.c:816
+msgid "ring bell when prompting"
+msgstr "sune la campanele cuant che e ven domandade une rispueste"
+
+#: src/parse_args.c:818
+msgid "close all file descriptors >= num"
+msgstr "siere ducj i descritôrs di file >= num"
+
+#: src/parse_args.c:821
+msgid "run command with the specified BSD login class"
+msgstr "eseguìs il comant cun la classe di acès BSD specificade"
+
+#: src/parse_args.c:824
+msgid "change the working directory before running command"
+msgstr "cambie la cartele di lavôr prime di eseguî il comant"
+
+#: src/parse_args.c:827
+msgid "preserve user environment when running command"
+msgstr "preserve l'ambient utent cuant che si eseguìs un comant"
+
+#: src/parse_args.c:829
+msgid "preserve specific environment variables"
+msgstr "preserve lis specifichis variabilis di ambient"
+
+#: src/parse_args.c:831
+msgid "edit files instead of running a command"
+msgstr "modifiche i file invezit di eseguî un comant"
+
+#: src/parse_args.c:834
+msgid "run command as the specified group name or ID"
+msgstr "eseguìs il comant come il ID o il non dal grup specificât"
+
+#: src/parse_args.c:837
+msgid "set HOME variable to target user's home dir"
+msgstr "stabilìs la variabile HOME ae cartele home dal utent di destinazion"
+
+#: src/parse_args.c:840
+msgid "display help message and exit"
+msgstr "mostre il messaç di jutori e jes"
+
+#: src/parse_args.c:842
+msgid "run command on host (if supported by plugin)"
+msgstr "eseguìs il comant sul host (se supuartât dal plugin)"
+
+#: src/parse_args.c:845
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "eseguìs une shell di acès come utent di destinazion; si podarès ancje specificâ un comant"
+
+#: src/parse_args.c:847
+msgid "remove timestamp file completely"
+msgstr "gjave dal dut il file de marche temporâl"
+
+#: src/parse_args.c:850
+msgid "invalidate timestamp file"
+msgstr "invalide il file de marche temporâl"
+
+#: src/parse_args.c:853
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "liste i privileçs dal utent o verifiche un comant specific; doprâ dôs voltis pal formât plui lunc"
+
+#: src/parse_args.c:856
+msgid "non-interactive mode, no prompts are used"
+msgstr "modalitât no interative, nissune richieste e ven presentade"
+
+#: src/parse_args.c:859
+msgid "preserve group vector instead of setting to target's"
+msgstr "preserve il vetôr dal grup invezit di metilu a chel de destinazion"
+
+#: src/parse_args.c:862
+msgid "use the specified password prompt"
+msgstr "dopre la richieste de password specificade"
+
+#: src/parse_args.c:864
+msgid "change the root directory before running command"
+msgstr "cambie la cartele lidrîs prime di eseguî il comant"
+
+#: src/parse_args.c:867
+msgid "create SELinux security context with specified role"
+msgstr "cree il contest di sigurece SELinux cul rûl specificât"
+
+#: src/parse_args.c:870
+msgid "read password from standard input"
+msgstr "lei la passwrod dal standard input"
+
+#: src/parse_args.c:873
+msgid "run shell as the target user; a command may also be specified"
+msgstr "eseguìs la shell come l'utent di destinazion; si podarès ancje specificâ un comant"
+
+#: src/parse_args.c:877
+msgid "create SELinux security context with specified type"
+msgstr "cree il contest di sigurece SELinux cul gjenar specificât"
+
+#: src/parse_args.c:880
+msgid "terminate command after the specified time limit"
+msgstr "termine il comant dopo il limit di timp specificât"
+
+#: src/parse_args.c:883
+msgid "in list mode, display privileges for user"
+msgstr "in modalitât liste, mostre i privileçs dal utent"
+
+#: src/parse_args.c:886
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "eseguìs il comant (o modifiche il file) come non utent o ID specificât"
+
+#: src/parse_args.c:888
+msgid "display version information and exit"
+msgstr "mostre informazions di version e jes"
+
+#: src/parse_args.c:891
+msgid "update user's timestamp without running a command"
+msgstr "inzorne la marche temporâl dal utent cence eseguî un comant"
+
+#: src/parse_args.c:894
+msgid "stop processing command line arguments"
+msgstr "ferme la elaborazion dai argoments a rie di comant"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "impussibil vierzi il sisteme di audit"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "impussibil inviâ il messaç di audit"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "impussibil eseguî fgetfilecon %s"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s al à modificâts lis etichetis"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "impussibil ripristinâ il contest par %s"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "impussibil vierzi %s, no si torne a etichetâ tty"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s nol è un dispositîf a caratars, no si torne a etichetâ tty"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "impussibil otignî il contest tty atuâl, no si torne a etichetâ tty"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "classe di sigurece \"chr_file\" no cognossude, no si torne a etichetâ tty"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "impussibil otignî il gnûf contest tty, no si torne a etichetâ tty"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "impussibil stabilî un gnûf contest tty"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "si scugne specificâ un rûl pal gjenar %s"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "impussibil otignî il gjenar predefinît pal rûl %s"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "impussibil otignî un gnûf contest"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "no si è rivâts a stabilî il gnûf rûl %s"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "no si è rivâts a stabilî il gnûf gjenar %s"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s nol è un contest valit"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "impussibil otignî il contest vecjo"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "impussibil determinâ la modalitât di costrizion."
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "impussibil meti il contest di exec a %s"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "impussibil meti il contest de creazion de clâf a %s"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "Al è pussibil specificâ dome une des opzions -c o -i"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "numar descritôr file no valit: %s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "Nol è pussibil doprâ la opzion -%c te modalitât di modifiche"
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "Al è pussibil doprâ la opzion -%c dome te modalitât di modifiche."
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: la modifiche dai colegaments simbolics no je permetude"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: la modifiche dai file intune cartele cun acès in scriture no je permetude"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "contignûts de session di modifiche lassâts in %s"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "impussibil otignî la liste dai grups"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "impussibil salvâ il gjestôr pal segnâl %d"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "si è rivâts al limit di control de risorse"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "l'utent \"%s\" nol è un membri dal progjet \"%s\""
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "la ativitât di invocazion e je definitive"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "impussibil unîsi al progjet \"%s\""
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "nissun font di risorsis pal progjet \"%s\" che al aceti i vincui predefinîts"
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "il font di risorsis specificât nol esist pal progjet \"%s\""
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "impussibil vincolâ al font di risorsis predefinît pal progjet \"%s\""
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "setproject al à falît pal progjet \"%s\""
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "avertiment, faliment de assegnazion dal control de risorse pal progjet \"%s\""
+
+#: src/sudo.c:216
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Version di sudo: %s\n"
+
+#: src/sudo.c:218
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Opzions di configurazion: %s\n"
+
+#: src/sudo.c:226
+msgid "fatal error, unable to load plugins"
+msgstr "erôr fatâl, impussibil cjariâ i plugin"
+
+#: src/sudo.c:272
+msgid "plugin did not return a command to execute"
+msgstr "il plugin nol à tornât un comant di eseguî"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "modalitât 0x%x di sudo inspietade"
+
+#: src/sudo.c:555
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "no tu esistis te base di dâts %s"
+
+#: src/sudo.c:612
+msgid "unable to determine tty"
+msgstr "impussibil determinâ tty"
+
+#: src/sudo.c:928
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "La opzion (flag) \"no new privileges\" (nissun gnûf privileç) e je definide. Chest al impedìs a sudo di zirâ come root."
+
+#: src/sudo.c:930
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "Se sudo al ven eseguît intun contignidôr, tu varessis di justâ la configurazion dal contignidôr par disabilitâ la flag (opzion)."
+
+#: src/sudo.c:964
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s al scugne jessi di proprietât dal uid %d e vê stabilît il bit setuid"
+
+#: src/sudo.c:967
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "il uid efetîf nol è %d, %s isal suntun filesystem cun stabilide la opzion 'nosuid' o un filesystem NFS cence privileçs di root?"
+
+#: src/sudo.c:973
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "il uid efetîf nol è %d, sudo isal instalât cun setuid root?"
+
+#: src/sudo.c:989 src/tgetpass.c:331
+msgid "unable to set supplementary group IDs"
+msgstr "impussibil stabilî il ID di grup suplementâr"
+
+#: src/sudo.c:996
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "impussibil stabilî il gid efetîf par eseguî come gid %u"
+
+#: src/sudo.c:1002
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "impussibil stabilî il gid par eseguî come gid %u"
+
+#: src/sudo.c:1032
+msgid "argv not set by the security policy"
+msgstr "argv nol è stabilît de politiche di sigurece"
+
+#: src/sudo.c:1036
+msgid "envp not set by the security policy"
+msgstr "envp nol è stabilît de politiche di sigurece"
+
+#: src/sudo.c:1058
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "condizion di jessude dal fi inspietade: %d"
+
+#: src/sudo.c:1171
+msgid "unable to initialize policy plugin"
+msgstr "impussibil inizializâ il plugin de politiche"
+
+#: src/sudo.c:1233
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "il plugin de politiche %s al mancje dal metodi \"check_policy\""
+
+#: src/sudo.c:1279
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "il plugin di politiche %s nol supuarte il listâ dai privileçs"
+
+#: src/sudo.c:1323
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "il plugin di politiche %s nol supuarte la opzion -v"
+
+#: src/sudo.c:1361
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "il plugin di politiche %s nol supuarte lis opzions -k/-K"
+
+#: src/sudo.c:1490
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "erôr tal inizializâ il plugin I/O %s"
+
+#: src/sudo.c:1493
+msgid "error initializing I/O plugin"
+msgstr "erôr tal inizializâ il plugin I/O"
+
+#: src/sudo.c:1642
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "erôr tal inizializâ il plugin di audit %s"
+
+#: src/sudo.c:1721
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: impussibil regjistrâ l'event di erôr%s%s"
+
+#: src/sudo.c:1757
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: impussibil regjistrâ l'event di acetazion%s%s"
+
+#: src/sudo.c:1762 src/sudo.c:1800
+msgid "audit plugin error"
+msgstr "erôr dal plugin di audit"
+
+#: src/sudo.c:1795
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: impussibil regjistrâ l'event di refudament%s%s"
+
+#: src/sudo.c:1855
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "erôr tal inizializâ il plugin di aprovazion %s"
+
+#: src/sudo.c:1925
+msgid "command rejected by approver"
+msgstr "comant refudât da cui che al aprove"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "nissune cartele temporanie scrivibile cjatade"
+
+#: src/sudo_edit.c:291
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s lassât no modificât"
+
+#: src/sudo_edit.c:304 src/sudo_edit.c:569
+#, c-format
+msgid "%s unchanged"
+msgstr "%s no modificât"
+
+#: src/sudo_edit.c:481
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: erôr interni: strani numar di percors"
+
+#: src/sudo_edit.c:483
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: impussibil creâ file temporanis"
+
+#: src/sudo_edit.c:485 src/sudo_edit.c:604
+msgid "sesh: killed by a signal"
+msgstr "sesh: copât di un segnâl"
+
+#: src/sudo_edit.c:487 src/sudo_edit.c:607
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: erôr %d no cognossût"
+
+#: src/sudo_edit.c:597
+msgid "unable to copy temporary files back to their original location"
+msgstr "impussibil tornâ a copiâ i file temporanis te lôr posizion origjinarie"
+
+#: src/sudo_edit.c:601
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "impussibil tornâ a copiâ cualchidun dai file temporanis te lôr posizion origjinarie"
+
+#: src/sudo_edit.c:646
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "impussibil cambiâ il uid a root (%u)"
+
+#: src/sudo_edit.c:660
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "erôr di plugin: liste di files par sudoedit no valide"
+
+#: src/sudo_edit.c:681
+msgid "plugin error: missing file list for sudoedit"
+msgstr "erôr di plugin: e mancje la liste file par sudoedit"
+
+#: src/sudo_edit.c:724 src/sudo_edit.c:739
+msgid "unable to read the clock"
+msgstr "impussibil lei l'orloi"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "puarte di intercetazion no stabilide"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "timp scjadût tal lei la password"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "no je stade furnide nissune password"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "impussibil lei la password"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "al è necessari un terminâl par lei la password; o tu dopris la opzion -S par lei dal standard input opûr configure un aiût askpass"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "nissun program pe richieste password specificât, cîr di stabilî SUDO_ASKPASS"
+
+#: src/tgetpass.c:326
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "impussibil stabilî il gid a %u"
+
+#: src/tgetpass.c:336
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "impussibil stabilî il uid a %u"
+
+#: src/tgetpass.c:341
+#, c-format
+msgid "unable to run %s"
+msgstr "impussibil eseguî %s"
+
+#: src/utmp.c:288
+msgid "unable to save stdin"
+msgstr "impussibil salvâ stdin"
+
+#: src/utmp.c:290
+msgid "unable to dup2 stdin"
+msgstr "impussibil esguî dup2 su stdin"
+
+#: src/utmp.c:293
+msgid "unable to restore stdin"
+msgstr "impussibil ripristinâ stdin"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "erôr tal lei dal condot (pipe) dal segnâl"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s: %s"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s al scugne jessi di proprietât dal uid %d"
+
+#~ msgid "%s must be only be writable by owner"
+#~ msgstr "%s al scugne jessi scrivibil dome dal proprietari"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "si ignore il plugin di politiche duplicât \"%s\" in %s, rie %d"
+
+#~ msgid "unable to set tty context to %s"
+#~ msgstr "impussibil meti il contest di tty a %s"
+
+#~ msgid "requires at least one argument"
+#~ msgstr "al domande almancul un argoment"
+
+#~ msgid "unable to run %s as a login shell"
+#~ msgstr "impussibil eseguî %s come une shell di acès"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "uid %u no cognossût: cui sêstu?"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s: scriture curte"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "impussibil lei il file temporani"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "nissun tty presint e nissun program specificât pe richieste password"
diff --git a/po/gl.mo b/po/gl.mo
new file mode 100644
index 0000000..30c6e2c
--- /dev/null
+++ b/po/gl.mo
Binary files differ
diff --git a/po/gl.po b/po/gl.po
new file mode 100644
index 0000000..f84eb0e
--- /dev/null
+++ b/po/gl.po
@@ -0,0 +1,898 @@
+# Galician translations for sudo package.
+# This file is put in the public domain.
+# Fran Dieguez <frandieguez@gnome.org>, 2012.
+# Francisco Diéguez <frandieguez@ubuntu.com>, 2012.
+# Leandro Regueiro <leandro.regueiro@gmail.com>, 2012-2015.
+# Proxecto Trasno - Adaptación do software libre á lingua galega: Se desexas
+# colaborar connosco, podes atopar máis información en <http://www.trasno.net>
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.8.15b1\n"
+"Report-Msgid-Bugs-To: http://www.sudo.ws/bugs\n"
+"POT-Creation-Date: 2015-09-10 14:28-0600\n"
+"PO-Revision-Date: 2015-09-15 10:41+0100\n"
+"Last-Translator: Leandro Regueiro <leandro.regueiro@gmail.com>\n"
+"Language-Team: Galician <proxecto@trasno.net>\n"
+"Language: gl\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 1.5.4\n"
+
+#: lib/util/aix.c:85 lib/util/aix.c:155
+msgid "unable to open userdb"
+msgstr "non foi posíbel abrir userdb"
+
+#: lib/util/aix.c:160
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "non foi posíbel ir ao rexistro «%s» para %s"
+
+#: lib/util/aix.c:185
+msgid "unable to restore registry"
+msgstr "non foi posíbel restaurar o rexistro"
+
+#: lib/util/aix.c:204 lib/util/gidlist.c:64 lib/util/gidlist.c:74
+#: lib/util/sudo_conf.c:185 lib/util/sudo_conf.c:265 lib/util/sudo_conf.c:342
+#: lib/util/sudo_conf.c:544 src/conversation.c:72 src/exec.c:864
+#: src/exec_common.c:96 src/exec_common.c:108 src/exec_common.c:115
+#: src/exec_pty.c:684 src/exec_pty.c:692 src/load_plugins.c:52
+#: src/load_plugins.c:65 src/load_plugins.c:208 src/load_plugins.c:231
+#: src/load_plugins.c:296 src/load_plugins.c:311 src/parse_args.c:180
+#: src/parse_args.c:202 src/parse_args.c:370 src/parse_args.c:466
+#: src/parse_args.c:485 src/preserve_fds.c:47 src/preserve_fds.c:130
+#: src/selinux.c:84 src/selinux.c:291 src/selinux.c:414 src/sesh.c:102
+#: src/sudo.c:182 src/sudo.c:359 src/sudo.c:378 src/sudo.c:442 src/sudo.c:596
+#: src/sudo.c:615 src/sudo.c:642 src/sudo.c:651 src/sudo.c:660 src/sudo.c:677
+#: src/sudo.c:729 src/sudo.c:739 src/sudo.c:763 src/sudo.c:1146
+#: src/sudo.c:1148 src/sudo.c:1154 src/sudo.c:1162 src/sudo_edit.c:150
+#: src/sudo_edit.c:425 src/sudo_edit.c:522 src/sudo_edit.c:634
+#: src/sudo_edit.c:654
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:204 lib/util/gidlist.c:64 lib/util/sudo_conf.c:185
+#: lib/util/sudo_conf.c:265 lib/util/sudo_conf.c:342 lib/util/sudo_conf.c:544
+#: src/conversation.c:73 src/exec.c:864 src/exec_common.c:96
+#: src/exec_common.c:108 src/exec_common.c:115 src/exec_pty.c:684
+#: src/exec_pty.c:692 src/load_plugins.c:208 src/load_plugins.c:231
+#: src/load_plugins.c:296 src/load_plugins.c:311 src/parse_args.c:180
+#: src/parse_args.c:202 src/parse_args.c:370 src/parse_args.c:466
+#: src/parse_args.c:485 src/preserve_fds.c:47 src/preserve_fds.c:130
+#: src/selinux.c:84 src/selinux.c:291 src/selinux.c:414 src/sesh.c:102
+#: src/sudo.c:182 src/sudo.c:359 src/sudo.c:378 src/sudo.c:442 src/sudo.c:763
+#: src/sudo.c:1146 src/sudo.c:1148 src/sudo.c:1154 src/sudo.c:1162
+#: src/sudo_edit.c:150 src/sudo_edit.c:425 src/sudo_edit.c:522
+#: src/sudo_edit.c:634 src/sudo_edit.c:654
+msgid "unable to allocate memory"
+msgstr "non foi posíbel asignar memoria"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Sinal descoñecido"
+
+#: lib/util/strtoid.c:76 lib/util/strtoid.c:104 lib/util/strtomode.c:48
+#: lib/util/strtonum.c:58 lib/util/strtonum.c:176
+msgid "invalid value"
+msgstr "valor non válido"
+
+#: lib/util/strtoid.c:83 lib/util/strtoid.c:111 lib/util/strtomode.c:54
+#: lib/util/strtonum.c:61 lib/util/strtonum.c:188
+msgid "value too large"
+msgstr "valor demasiado grande"
+
+#: lib/util/strtoid.c:89 lib/util/strtomode.c:54 lib/util/strtonum.c:61
+#: lib/util/strtonum.c:182
+msgid "value too small"
+msgstr "valor demasiado pequeno"
+
+#: lib/util/sudo_conf.c:198
+#, c-format
+msgid "invalid Path value `%s' in %s, line %u"
+msgstr ""
+
+#: lib/util/sudo_conf.c:364 lib/util/sudo_conf.c:417
+#, c-format
+msgid "invalid value for %s `%s' in %s, line %u"
+msgstr "valor non válido para %s `%s' en %s, liña %u"
+
+#: lib/util/sudo_conf.c:385
+#, c-format
+msgid "unsupported group source `%s' in %s, line %u"
+msgstr ""
+
+#: lib/util/sudo_conf.c:401
+#, c-format
+msgid "invalid max groups `%s' in %s, line %u"
+msgstr ""
+
+#: lib/util/sudo_conf.c:560
+#, c-format
+msgid "unable to stat %s"
+msgstr "non foi posíbel executar stat en %s"
+
+#: lib/util/sudo_conf.c:563
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s non é un ficheiro normal"
+
+#: lib/util/sudo_conf.c:566
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s é propiedade de uid %u, pero debería ser %u"
+
+#: lib/util/sudo_conf.c:570
+#, c-format
+msgid "%s is world writable"
+msgstr "%s é escribíbel por todo o mundo"
+
+#: lib/util/sudo_conf.c:573
+#, c-format
+msgid "%s is group writable"
+msgstr "%s é escribíbel polo grupo"
+
+#: lib/util/sudo_conf.c:583 src/selinux.c:199 src/selinux.c:212 src/sudo.c:328
+#, c-format
+msgid "unable to open %s"
+msgstr "non foi posíbel abrir %s"
+
+#: src/exec.c:114 src/exec.c:116 src/exec.c:121 src/exec.c:409 src/exec.c:411
+#: src/exec.c:413 src/exec.c:415 src/exec.c:417 src/exec.c:420 src/exec.c:437
+#: src/exec.c:439 src/exec.c:441 src/exec.c:596 src/exec.c:791
+#: src/exec_pty.c:466 src/exec_pty.c:722 src/exec_pty.c:792 src/exec_pty.c:794
+#: src/exec_pty.c:806 src/exec_pty.c:808 src/exec_pty.c:1285
+#: src/exec_pty.c:1287 src/exec_pty.c:1292 src/exec_pty.c:1294
+#: src/exec_pty.c:1308 src/exec_pty.c:1319 src/exec_pty.c:1321
+#: src/exec_pty.c:1323 src/exec_pty.c:1325 src/exec_pty.c:1327
+#: src/exec_pty.c:1329 src/exec_pty.c:1331 src/signal.c:147
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "non foi posíbel definir o manexador para o sinal %d"
+
+#: src/exec.c:126 src/exec_pty.c:838 src/exec_pty.c:1369 src/tgetpass.c:265
+msgid "unable to fork"
+msgstr "non é posíbel realizar fork"
+
+#: src/exec.c:304 src/exec.c:312 src/exec.c:869 src/exec_pty.c:604
+#: src/exec_pty.c:611 src/exec_pty.c:654 src/exec_pty.c:659 src/exec_pty.c:942
+#: src/exec_pty.c:952 src/exec_pty.c:997 src/exec_pty.c:1004
+#: src/exec_pty.c:1434 src/exec_pty.c:1441 src/exec_pty.c:1448
+msgid "unable to add event to queue"
+msgstr "non foi posíbel engadir o evento á cola"
+
+#: src/exec.c:392
+msgid "unable to create sockets"
+msgstr "non foi posíbel crear sockets"
+
+#: src/exec.c:448
+msgid "policy plugin failed session initialization"
+msgstr "produciuse un erro durante a inicialización de sesión do engadido de política"
+
+#: src/exec.c:493
+msgid "error in event loop"
+msgstr "erro no bucle de eventos"
+
+#: src/exec.c:511
+msgid "unable to restore tty label"
+msgstr "non foi posíbel restaurar a etiqueta tty"
+
+#: src/exec.c:604 src/exec_pty.c:498 src/signal.c:86
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "non foi posíbel restaurar o manexador para o sinal %d"
+
+#: src/exec.c:722 src/exec_pty.c:1176
+msgid "error reading from signal pipe"
+msgstr "produciuse un erro ao ler desde a tubería do sinal"
+
+#: src/exec_common.c:64
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "non foi posíbel retirar PRIV_PROC_EXEC desde PRIV_LIMIT"
+
+#: src/exec_pty.c:188
+msgid "unable to allocate pty"
+msgstr "non foi posíbel asignar pty"
+
+#: src/exec_pty.c:766 src/exec_pty.c:775 src/exec_pty.c:783
+#: src/exec_pty.c:1277 src/exec_pty.c:1366 src/signal.c:128 src/tgetpass.c:261
+msgid "unable to create pipe"
+msgstr "non foi psosíbel crear tubería"
+
+#: src/exec_pty.c:1209
+msgid "error reading from pipe"
+msgstr "produciuse un erro ao ler da tubería"
+
+#: src/exec_pty.c:1234
+msgid "error reading from socketpair"
+msgstr "produciuse un erro ao ler de socketpair"
+
+#: src/exec_pty.c:1243
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "tipo de resposta inesperada en canles alternos %d"
+
+#: src/exec_pty.c:1345
+msgid "unable to set controlling tty"
+msgstr "non foi posíebl estabelecer o controlador tty"
+
+#: src/load_plugins.c:50 src/load_plugins.c:63 src/load_plugins.c:80
+#: src/load_plugins.c:110 src/load_plugins.c:116 src/load_plugins.c:122
+#: src/load_plugins.c:163 src/load_plugins.c:171 src/load_plugins.c:178
+#: src/load_plugins.c:184
+#, c-format
+msgid "error in %s, line %d while loading plugin `%s'"
+msgstr "produciuse un erro en %s, liña %d ao cargar o engadido «%s»"
+
+#: src/load_plugins.c:82
+#, c-format
+msgid "%s%s: %s"
+msgstr "%s%s: %s"
+
+#: src/load_plugins.c:118
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s debe ser propiedade do uid %d"
+
+#: src/load_plugins.c:124
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "%s só debe ter permisos de escritura polo propietario"
+
+#: src/load_plugins.c:165
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "non foi posíbel cargar %s: %s"
+
+#: src/load_plugins.c:173
+#, c-format
+msgid "unable to find symbol `%s' in %s"
+msgstr " non foi posíbel atopar o símbolo «%s» en %s"
+
+#: src/load_plugins.c:180
+#, c-format
+msgid "unknown policy type %d found in %s"
+msgstr "tipo de política descoñecida %d atopado en %s"
+
+#: src/load_plugins.c:186
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "versión principal %d do engadido incompatíbel (agardábase %d) atopouse en %s"
+
+#: src/load_plugins.c:195
+#, c-format
+msgid "ignoring policy plugin `%s' in %s, line %d"
+msgstr ""
+
+#: src/load_plugins.c:197
+msgid "only a single policy plugin may be specified"
+msgstr "só se pode especificar unha política de engadido"
+
+#: src/load_plugins.c:200
+#, c-format
+msgid "ignoring duplicate policy plugin `%s' in %s, line %d"
+msgstr ""
+
+#: src/load_plugins.c:221
+#, c-format
+msgid "ignoring duplicate I/O plugin `%s' in %s, line %d"
+msgstr ""
+
+#: src/load_plugins.c:324
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "a política do engadido %s non inclúe un método check_policy"
+
+#: src/net_ifs.c:173 src/net_ifs.c:190 src/net_ifs.c:335 src/sudo.c:437
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "erro interno, desbordamento en %s"
+
+#: src/parse_args.c:239
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "o agumento -C debe ser un número maior ou igual a 3"
+
+#: src/parse_args.c:406
+msgid "you may not specify both the `-i' and `-s' options"
+msgstr "non se deben especificar as opcións «-i» e «-s» simultáneamente"
+
+#: src/parse_args.c:410
+msgid "you may not specify both the `-i' and `-E' options"
+msgstr "non se deben especificar as opcións «-i» e «-E» simultáneamente"
+
+#: src/parse_args.c:420
+msgid "the `-E' option is not valid in edit mode"
+msgstr "a opción «-E» non é válida no modo edición"
+
+#: src/parse_args.c:422
+msgid "you may not specify environment variables in edit mode"
+msgstr "non se deben especificar variábeis de ambiente no modo edición"
+
+#: src/parse_args.c:430
+msgid "the `-U' option may only be used with the `-l' option"
+msgstr "a opción «-U» só se pode usar coa opción «-l»"
+
+#: src/parse_args.c:434
+msgid "the `-A' and `-S' options may not be used together"
+msgstr "as opcións «-A» e «-S» non se poden empregar conxuntamente"
+
+#: src/parse_args.c:504
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit non se admite nesta plataforma"
+
+#: src/parse_args.c:577
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Só pode especificar unha das opcións -e, -h, -i, -K, -l, -s, -v ou -V"
+
+#: src/parse_args.c:591
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - edita ficheiros como outro usuario\n"
+"\n"
+
+#: src/parse_args.c:593
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - executa unha orde como outro usuario\n"
+"\n"
+
+#: src/parse_args.c:598
+#, c-format
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Opcións:\n"
+
+#: src/parse_args.c:600
+msgid "use a helper program for password prompting"
+msgstr "usar un programa auxiliar para a solicitude de contrasinal"
+
+#: src/parse_args.c:603
+msgid "use specified BSD authentication type"
+msgstr "usar tipo de autenticación especificado en BSD"
+
+#: src/parse_args.c:606
+msgid "run command in the background"
+msgstr "executa unha orde en segundo plano"
+
+#: src/parse_args.c:608
+msgid "close all file descriptors >= num"
+msgstr "pecha todos os descritores de ficheiro >= num"
+
+#: src/parse_args.c:611
+msgid "run command with the specified BSD login class"
+msgstr "executa unha orde coa clase de inicio de sesión especificada"
+
+#: src/parse_args.c:614
+msgid "preserve user environment when running command"
+msgstr "conserva o ambiente de usuario ao executar unha orde"
+
+#: src/parse_args.c:616
+msgid "edit files instead of running a command"
+msgstr "edita ficheiros no lugar de executar unha orde"
+
+#: src/parse_args.c:618
+msgid "run command as the specified group name or ID"
+msgstr "executa unha orde como o nome ou ID de grupo especificado"
+
+#: src/parse_args.c:620
+msgid "set HOME variable to target user's home dir"
+msgstr "define a variábel HOME como o cartafol de inicio do usuario"
+
+#: src/parse_args.c:622
+msgid "display help message and exit"
+msgstr "mostra esta mensaxe de axuda e sae"
+
+#: src/parse_args.c:624
+msgid "run command on host (if supported by plugin)"
+msgstr ""
+
+#: src/parse_args.c:626
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "executar un intérprete de ordes de inicio como o usuario destino; tamén se pode especificar unha orde"
+
+#: src/parse_args.c:628
+msgid "remove timestamp file completely"
+msgstr "retira completamente un ficheiro de marca de tempo"
+
+#: src/parse_args.c:630
+msgid "invalidate timestamp file"
+msgstr "invalidar o ficheiro de marca de tempo"
+
+#: src/parse_args.c:632
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "listar os privilexios do usuario ou comprobar unha orde específica; usar dúas veces para un formato máis longo"
+
+#: src/parse_args.c:634
+msgid "non-interactive mode, no prompts are used"
+msgstr "modo non interactivo, non se preguntará ao usuario"
+
+#: src/parse_args.c:636
+#, fuzzy
+msgid "preserve group vector instead of setting to target's"
+msgstr "conserva o vector de grupos en vez de definilo ao obxectivo"
+
+#: src/parse_args.c:638
+msgid "use the specified password prompt"
+msgstr "usa o contrasinal especificado"
+
+#: src/parse_args.c:641
+msgid "create SELinux security context with specified role"
+msgstr "crea un contexto de seguranza SELinux co rol especificado"
+
+#: src/parse_args.c:644
+msgid "read password from standard input"
+msgstr "le o contrasinal desde a entrada estándar"
+
+#: src/parse_args.c:646
+msgid "run shell as the target user; a command may also be specified"
+msgstr "executar o intérprete de ordes como o usuario destino; tamén se pode especificar unha orde"
+
+#: src/parse_args.c:649
+msgid "create SELinux security context with specified type"
+msgstr "crea un contexto de seguranza SELinux co tipo especificado"
+
+#: src/parse_args.c:652
+msgid "in list mode, display privileges for user"
+msgstr "en modo lista, mostrar os privilexios do usuario"
+
+#: src/parse_args.c:654
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "executa unha orde (ou edita un ficheiro) como o nome ou ID de usuario especificado"
+
+#: src/parse_args.c:656
+msgid "display version information and exit"
+msgstr "mostra a información da versión e sae"
+
+#: src/parse_args.c:658
+msgid "update user's timestamp without running a command"
+msgstr "actualiza a marca de tempo do usuario sen executar ningunha orde"
+
+#: src/parse_args.c:660
+msgid "stop processing command line arguments"
+msgstr "detén o proceso de argumentos da liña de ordes"
+
+#: src/selinux.c:78
+msgid "unable to open audit system"
+msgstr "non foi posíbel abrir o sistema de auditoría"
+
+#: src/selinux.c:88
+msgid "unable to send audit message"
+msgstr "non foi posíbel enviar a mensaxe de auditoría"
+
+#: src/selinux.c:116
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "non foi posíbel executar fgetfilecon %s"
+
+#: src/selinux.c:121
+#, c-format
+msgid "%s changed labels"
+msgstr "%s etiquetas cambiadas"
+
+#: src/selinux.c:126
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "non foi posíbel restaurar o contexto para %s"
+
+#: src/selinux.c:166
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "non foi posíbel abrir %s, non volver a etiquetar tty"
+
+#: src/selinux.c:175
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "non foi posíbel obter o contexto actual de tty, non se volve etiquetar tty"
+
+#: src/selinux.c:182
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "non foi posíbel obter o novo contexto tty, non volver a etiquetar tty"
+
+#: src/selinux.c:189
+msgid "unable to set new tty context"
+msgstr "non foi posíbel estabelecer o novo contexto tty"
+
+#: src/selinux.c:255
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "débese especificar unha regra por tipo %s"
+
+#: src/selinux.c:261
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "non foi posíbel obter o tipo de regra predeterminada %s"
+
+#: src/selinux.c:279
+#, c-format
+msgid "failed to set new role %s"
+msgstr "produciuse un erro ao definir a nova regra %s"
+
+#: src/selinux.c:283
+#, c-format
+msgid "failed to set new type %s"
+msgstr "produciuse un erro ao definir o novo tipo %s"
+
+#: src/selinux.c:295
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s non é un contexto válido"
+
+#: src/selinux.c:330
+msgid "failed to get old_context"
+msgstr "produciuse un erro ao obter old_context"
+
+#: src/selinux.c:336
+msgid "unable to determine enforcing mode."
+msgstr "non foi posíbel determinar o método de forzado"
+
+#: src/selinux.c:353
+#, c-format
+msgid "unable to set tty context to %s"
+msgstr "non foi posíbel definir o contexto tty para %s"
+
+#: src/selinux.c:392
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "non foi posíbel o contexto de execución a %s"
+
+#: src/selinux.c:399
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "non foi posíbel estabelecer a chave de creación de contexto a %s"
+
+#: src/sesh.c:77
+msgid "requires at least one argument"
+msgstr "require cando menos un argumento"
+
+#: src/sesh.c:107
+#, c-format
+msgid "unable to run %s as a login shell"
+msgstr "non foi posíbel executar %s como shell de inicio de sesión"
+
+#: src/sesh.c:112 src/sudo.c:1217
+#, c-format
+msgid "unable to execute %s"
+msgstr "non é posíbel executar %s"
+
+#: src/signal.c:68
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "non foi posíbel gardar o manexador para o sinal %d"
+
+#: src/solaris.c:76
+msgid "resource control limit has been reached"
+msgstr "acadouse o límite de control de recursos"
+
+#: src/solaris.c:79
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "o usuario «%s» non é membro do grupo «%s»"
+
+#: src/solaris.c:83
+msgid "the invoking task is final"
+msgstr "a tarefa que invoca é definitiva"
+
+#: src/solaris.c:86
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "non é posíbel unirse ao proxecto «%s»"
+
+#: src/solaris.c:91
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "non hai fondo de recursos aceptando as asignacións existentes par ao proxecto «%s»"
+
+#: src/solaris.c:95
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "o fondo de recursos especificado non existe para o proxecto «%s»"
+
+#: src/solaris.c:99
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "non é posíbel ligar ao fondo de recursos predeterminado para o proxecto «%s»"
+
+#: src/solaris.c:105
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "configuración do proxecto fallada «%s»"
+
+#: src/solaris.c:107
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "aviso, o control de asignación de recuros fallou para o proxecto «%s»"
+
+#: src/sudo.c:193
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo versión %s\n"
+
+#: src/sudo.c:195
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Opcións de configuración: %s\n"
+
+#: src/sudo.c:203
+msgid "fatal error, unable to load plugins"
+msgstr "erro fatal, non foi posíbel cargar os engadidos"
+
+#: src/sudo.c:211
+msgid "unable to initialize policy plugin"
+msgstr "non foi posíbel inicializar a normativa do engadido"
+
+#: src/sudo.c:267
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "erro ao inicializar os engadidos de E/S %s"
+
+#: src/sudo.c:293
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "modo sudo 0x%x non agardado"
+
+#: src/sudo.c:422
+msgid "unable to get group vector"
+msgstr "non é posíbel obter o vector de grupo"
+
+#: src/sudo.c:485
+#, c-format
+msgid "unknown uid %u: who are you?"
+msgstr "uid descoñecido %u: quen é vostede?"
+
+#: src/sudo.c:812
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s debe ser propiedade do uid %d e debe ter definido o bit setuid"
+
+#: src/sudo.c:815
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "o uid efectivo non é %d, é %s nun sistema de ficheiros coa opción «nosuid» definida ou nun sistema de ficheiros NFS sen privilexios de root?"
+
+#: src/sudo.c:821
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "o uid efectivo non é %d, está sudo instalado con setuid de root?"
+
+#: src/sudo.c:952
+#, c-format
+msgid "unknown login class %s"
+msgstr "clase de inicio de sesión descoñecida %s"
+
+#: src/sudo.c:965
+msgid "unable to set user context"
+msgstr "non foi posíbel estabelecer o contexto do usuario"
+
+#: src/sudo.c:979
+msgid "unable to set supplementary group IDs"
+msgstr "non foi posíbel estabelecer o grupo suplementario de IDs"
+
+#: src/sudo.c:986
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "non foi posíbel estabelcer o gid efectivo para executar como gid %u"
+
+#: src/sudo.c:992
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "non foi posíbel estabelcer o gid para executar como gid %u"
+
+#: src/sudo.c:999
+msgid "unable to set process priority"
+msgstr "non foi posíbel estabelecer a prioridade de proceso"
+
+#: src/sudo.c:1007
+#, c-format
+msgid "unable to change root to %s"
+msgstr "non foi posíbel cambiar de root a %s"
+
+#: src/sudo.c:1020 src/sudo.c:1026 src/sudo.c:1033
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "non foi posíbel cambiar as runas uid (%u, %u)"
+
+#: src/sudo.c:1051
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "non foi posíbel cambiar ao cartafol %s"
+
+#: src/sudo.c:1112
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "terminación de condición filla non agardada: %d"
+
+#: src/sudo.c:1245
+#, c-format
+msgid "policy plugin %s is missing the `check_policy' method"
+msgstr "a política do engadido %s non inclúe ningún método «check_policy»"
+
+#: src/sudo.c:1263
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "a política do engadido %s non admite listar os privilexios"
+
+#: src/sudo.c:1280
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "a política do engadido %s non admite a opción -v"
+
+#: src/sudo.c:1295
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "a normativa do engadido %s non admite as opcións -k/-K"
+
+#: src/sudo_edit.c:238 src/sudo_edit.c:339
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: non é un ficheiro regular"
+
+#: src/sudo_edit.c:245
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: a edición de ligazóns simbólicas non está permitida"
+
+#: src/sudo_edit.c:276 src/sudo_edit.c:378
+#, c-format
+msgid "%s: short write"
+msgstr "%s: escritura curta"
+
+#: src/sudo_edit.c:340
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s sen modificar"
+
+#: src/sudo_edit.c:353 src/sudo_edit.c:539
+#, c-format
+msgid "%s unchanged"
+msgstr "%s sen cambios"
+
+#: src/sudo_edit.c:367 src/sudo_edit.c:389
+#, c-format
+msgid "unable to write to %s"
+msgstr "non foi posíbel escribir en %s"
+
+#: src/sudo_edit.c:368 src/sudo_edit.c:387 src/sudo_edit.c:390
+#: src/sudo_edit.c:564 src/sudo_edit.c:568
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "os contidos de edición de sesión déixanse en %s"
+
+#: src/sudo_edit.c:386
+msgid "unable to read temporary file"
+msgstr "non é posíbel ler o ficheiro temporal"
+
+#: src/sudo_edit.c:469
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: erro interno: número impar de rutas"
+
+#: src/sudo_edit.c:471
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: non é posíbel crear ficheiros temporais"
+
+#: src/sudo_edit.c:473 src/sudo_edit.c:571
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: erro descoñecido %d"
+
+#: src/sudo_edit.c:563
+msgid "unable to copy temporary files back to their original location"
+msgstr "non foi posíbel copiar os ficheiros temporais de volta á súa localización orixinal"
+
+#: src/sudo_edit.c:567
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "non foi posíbel copiar algúns ficheiros temporais de volta á súa localización orixinal"
+
+#: src/sudo_edit.c:610
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "non foi posíbel cambiar uid a root (%u)"
+
+#: src/sudo_edit.c:627
+msgid "plugin error: missing file list for sudoedit"
+msgstr "erro do engadido: falta a lista de ficheiros para sudoedit"
+
+#: src/sudo_edit.c:668 src/sudo_edit.c:681
+msgid "unable to read the clock"
+msgstr "non foi posíbel ler o reloxo"
+
+#: src/tgetpass.c:107
+msgid "no tty present and no askpass program specified"
+msgstr "sen tty presente e non se especificou un programa askpass"
+
+#: src/tgetpass.c:116
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "non hai programa askpass especificado, tente estabelecer SUDO_ASKPASS"
+
+#: src/tgetpass.c:276
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "non foi posíbel estabelecer o gid a %u"
+
+#: src/tgetpass.c:280
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "non foi posíbel estabelecer o uid a %u"
+
+#: src/tgetpass.c:285
+#, c-format
+msgid "unable to run %s"
+msgstr "non foi posíbel executar %s"
+
+#: src/utmp.c:266
+msgid "unable to save stdin"
+msgstr "non foi posíbel gardar stdin"
+
+#: src/utmp.c:268
+msgid "unable to dup2 stdin"
+msgstr "non foi posíbel facer dup2 stdin"
+
+#: src/utmp.c:271
+msgid "unable to restore stdin"
+msgstr "non foi posíbel restaurar stdin"
+
+#~ msgid "internal error, tried to emalloc(0)"
+#~ msgstr "erro interno: tentou emalloc(0)"
+
+#~ msgid "internal error, tried to emalloc2(0)"
+#~ msgstr "erro interno: tentou emalloc2(0)"
+
+#~ msgid "internal error, tried to ecalloc(0)"
+#~ msgstr "erro interno, tentou ecalloc(0)"
+
+#~ msgid "internal error, tried to erealloc(0)"
+#~ msgstr "erro interno, tentou erealloc(0)"
+
+#~ msgid "internal error, tried to erealloc3(0)"
+#~ msgstr "erro interno, tentou erealloc3(0)"
+
+#~ msgid "internal error, tried to erecalloc(0)"
+#~ msgstr "erro interno, tentou erealloc(0)"
+
+#~ msgid "%s: %s: %s\n"
+#~ msgstr "%s: %s: %s\n"
+
+#~ msgid "%s: %s\n"
+#~ msgstr "%s: %s\n"
+
+#~ msgid "unable to set terminal to raw mode"
+#~ msgstr "non foi posíbel estabelcer a terminal en modo directo"
+
+#~ msgid "load_interfaces: overflow detected"
+#~ msgstr "load_interfaces: desbordamento detectado"
+
+#~ msgid "unable to open socket"
+#~ msgstr "non foi posíbel abrir o socket"
+
+#~ msgid ": "
+#~ msgstr ": "
+
+#~ msgid "select failed"
+#~ msgstr "selección fallada"
+
+#~ msgid "list user's available commands\n"
+#~ msgstr "lista de ordes do usuario dispoñíbeis\n"
+
+#~ msgid "run a shell as target user\n"
+#~ msgstr "executa un intérprete de ordes como un determinado usuario\n"
+
+#~ msgid "when listing, list specified user's privileges\n"
+#~ msgstr "cando está na lista, mostra os privilexios do usuario especificado\n"
+
+#~ msgid "%s: at least one policy plugin must be specified"
+#~ msgstr "%s: debe ser especificada cando menos unha política de engadido"
+
+#~ msgid "must be setuid root"
+#~ msgstr "debe ser setuid root"
+
+#~ msgid "internal error, erealloc3() overflow"
+#~ msgstr "erro interno: desbordamento de erealloc3(0)"
diff --git a/po/hr.mo b/po/hr.mo
new file mode 100644
index 0000000..9f0f515
--- /dev/null
+++ b/po/hr.mo
Binary files differ
diff --git a/po/hr.po b/po/hr.po
new file mode 100644
index 0000000..97dae9f
--- /dev/null
+++ b/po/hr.po
@@ -0,0 +1,1319 @@
+# Translation of sudo to Croatian.
+# This file is put in the public domain.
+# Tomislav Krznar <tomislav.krznar@gmail.com>, 2012, 2013.
+# Božidar Putanec <bozidarp@yahoo.com>, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo-1.9.14b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-06-07 13:27-0600\n"
+"PO-Revision-Date: 2023-06-08 12:20-0700\n"
+"Last-Translator: Božidar Putanec <bozidarp@yahoo.com>\n"
+"Language-Team: Croatian <lokalizacija@linux.hr>\n"
+"Language: hr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 3.2.2\n"
+"X-Poedit-Basepath: sources/sudo-1.8.26b1\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+"X-Poedit-SearchPath-0: .\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "nije moguće otvoriti userdb (korisničku baza podataka)"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "nije moguće prebaciti se u registar „%s“ za %s"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "nije moguće obnoviti registar"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:78 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:171 src/exec_monitor.c:418
+#: src/exec_monitor.c:424 src/exec_monitor.c:432 src/exec_monitor.c:440
+#: src/exec_monitor.c:447 src/exec_monitor.c:454 src/exec_monitor.c:461
+#: src/exec_monitor.c:468 src/exec_monitor.c:475 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:744 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1096
+#: src/exec_ptrace.c:1271 src/exec_ptrace.c:1624 src/exec_ptrace.c:1651
+#: src/exec_ptrace.c:1841 src/exec_pty.c:581 src/exec_pty.c:765
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:193 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:240
+#: src/sesh.c:246 src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:644
+#: src/sudo.c:709 src/sudo.c:719 src/sudo.c:746 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:787 src/sudo.c:805 src/sudo.c:846 src/sudo.c:855 src/sudo.c:865
+#: src/sudo.c:898 src/sudo.c:1127 src/sudo.c:1148 src/sudo.c:1441
+#: src/sudo.c:1610 src/sudo.c:1837 src/sudo.c:2171 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:430 src/sudo_edit.c:439
+#: src/sudo_edit.c:540 src/sudo_edit.c:547 src/sudo_edit.c:692
+#: src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:79 src/exec_intercept.c:111 src/exec_intercept.c:350
+#: src/exec_intercept.c:525 src/exec_intercept.c:589 src/exec_intercept.c:713
+#: src/exec_intercept.c:837 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:418 src/exec_monitor.c:424
+#: src/exec_monitor.c:432 src/exec_monitor.c:440 src/exec_monitor.c:447
+#: src/exec_monitor.c:454 src/exec_monitor.c:461 src/exec_monitor.c:468
+#: src/exec_monitor.c:475 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1651 src/exec_ptrace.c:1842 src/exec_pty.c:581
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:228 src/sudo.c:644 src/sudo.c:898 src/sudo.c:1127
+#: src/sudo.c:1148 src/sudo.c:1441 src/sudo.c:1610 src/sudo.c:1837
+#: src/sudo.c:2171 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:430
+#: src/sudo_edit.c:439 src/sudo_edit.c:540 src/sudo_edit.c:547
+#: src/sudo_edit.c:692 src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "nije moguće dodijeliti memoriju"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "nije moguće stat (dobiti status datoteke) %.*s"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s postoji ali nije direktorij (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:664
+#: lib/util/sudo_conf.c:683 lib/util/sudo_conf.c:710 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:495 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "nije moguće otvoriti %s"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "nije moguće mkdir %.*s"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "nije moguće otvoriti %.*s"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "regularni izraz je prevelik"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Nepoznati signal"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "nevaljana vrijednost"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "veličina je prevelika"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "veličina je premala"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "nevaljana Path vrijednost „%s“ u %s, redak %u"
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "nevaljana vrijednost za %s „%s“ u %s, redak %u"
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "nepodržani izvor grupe „%s“ u %s, redak %u"
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "nevaljani maksimalni broj grupa „%s“ u %s, redak %u"
+
+#: lib/util/sudo_conf.c:686
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s nije obična datoteka"
+
+#: lib/util/sudo_conf.c:689 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "vlasnik %s je UID %u, a treba biti %u"
+
+#: lib/util/sudo_conf.c:693
+#, c-format
+msgid "%s is world writable"
+msgstr "%s može svatko mijenjati/pisati"
+
+#: lib/util/sudo_conf.c:696
+#, c-format
+msgid "%s is group writable"
+msgstr "%s može svaki član grupe mijenjati/pisati"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "nije uspjelo utvrditi AppArmor ograničenje"
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "nije moguće promijeniti AppArmor profil na %s"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: skratiti %s na nula bajtova? (y/n) [n] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "ne piše preko %s"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "nije moguće pročitati %s"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "nije moguće pisati u %s"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "nije moguće dobiti status od %s"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: nije obična datoteka"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: loš datotečni način: 0%o"
+
+#: src/edit_open.c:333
+msgid "unable to restore current working directory"
+msgstr "nije moguće obnoviti trenutni radni direktorij"
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "nije moguće postaviti privilegije"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "nije moguće postaviti ograničenja na privilegije"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "nepoznata prijavnička klasa %s"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "nije moguće uspostaviti korisnički kontekst"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "nije moguće uspostaviti prioritet procesa"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "nije moguće promijeniti root na %s"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "nije moguće promijeniti na runas UID (%u, %u)"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "nije moguće promijeniti direktorij na %s"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "počevši od %s"
+
+# Handler, an asynchronous callback (computer programming) subroutine in computing
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:552 src/exec_monitor.c:554
+#: src/exec_pty.c:1122 src/exec_pty.c:1124 src/signal.c:144 src/signal.c:151
+#: src/signal.c:165 src/suspend_parent.c:143
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "nije moguće postaviti rukovatelja za signal %d"
+
+#: src/exec.c:424
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "presretanje nije podržano s SELinux RBAC na ovom sustavu"
+
+#: src/exec.c:429
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "nije moguće bilježiti podkomande s SELinux RBAC na ovom sustavu"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "nije moguće ukloniti PRIV_PROC_EXEC iz PRIV_LIMIT"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:163 src/exec_iolog.c:173
+#: src/exec_iolog.c:218 src/exec_iolog.c:225 src/exec_iolog.c:252
+#: src/exec_monitor.c:426 src/exec_monitor.c:434 src/exec_monitor.c:442
+#: src/exec_monitor.c:449 src/exec_monitor.c:456 src/exec_monitor.c:463
+#: src/exec_monitor.c:470 src/exec_monitor.c:477 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:457 src/exec_pty.c:432
+#: src/exec_pty.c:537 src/exec_pty.c:587 src/exec_pty.c:965 src/exec_pty.c:974
+#: src/exec_pty.c:981 src/exec_pty.c:988 src/exec_pty.c:995
+#: src/exec_pty.c:1002 src/exec_pty.c:1009 src/exec_pty.c:1016
+#: src/exec_pty.c:1023 src/exec_pty.c:1030 src/exec_pty.c:1037
+#: src/exec_pty.c:1044
+msgid "unable to add event to queue"
+msgstr "nije moguće dodati događaj u red čekanja"
+
+#: src/exec_intercept.c:323 src/sudo.c:1033
+msgid "command not set by the security policy"
+msgstr "naredba nije postavljena po sigurnosnim pravilima"
+
+#: src/exec_intercept.c:401 src/exec_intercept.c:441 src/sudo.c:1253
+#: src/sudo.c:1298 src/sudo.c:1342
+msgid "command rejected by policy"
+msgstr "pravilnik (policy) je odbio izvršiti naredbu"
+
+#: src/exec_intercept.c:512 src/sudo.c:1940
+msgid "approval plugin error"
+msgstr "greška plugina za odobravanje"
+
+#: src/exec_intercept.c:537 src/sudo.c:1258 src/sudo.c:1303 src/sudo.c:1347
+#: src/sudo.c:1421
+msgid "policy plugin error"
+msgstr "greška plugina s pravilima (policy plugin)"
+
+#: src/exec_intercept.c:566
+msgid "invalid PolicyCheckRequest"
+msgstr "nevaljani PolicyCheckRequest"
+
+#: src/exec_intercept.c:709
+#, c-format
+msgid "client request too large: %zu"
+msgstr "zahtjev klijenta je prevelik: %zu"
+
+#: src/exec_intercept.c:751
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "nije moguće raspakirati %s veličinu %zu"
+
+#: src/exec_intercept.c:799
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "neočekivana vrijednost type_case %d in %s od %s"
+
+#: src/exec_intercept.c:825
+#, c-format
+msgid "server message too large: %zu"
+msgstr "poruka servera je prevelika: %zu"
+
+#: src/exec_iolog.c:321 src/exec_iolog.c:361 src/exec_iolog.c:401
+#: src/exec_iolog.c:452 src/exec_iolog.c:503
+msgid "I/O plugin error"
+msgstr "greška U/I plugina (I/O plugin)"
+
+#: src/exec_iolog.c:325 src/exec_iolog.c:365 src/exec_iolog.c:405
+#: src/exec_iolog.c:456 src/exec_iolog.c:507
+msgid "command rejected by I/O plugin"
+msgstr "U/I plugin je odbio izvršiti naredbu"
+
+#: src/exec_iolog.c:555
+msgid "error logging suspend"
+msgstr "obustava evidentiranja greški"
+
+#: src/exec_iolog.c:590
+msgid "error changing window size"
+msgstr "pogreška pri mijenjanju veličine prozora"
+
+#: src/exec_monitor.c:328
+msgid "error reading from socketpair"
+msgstr "greška pri čitanju iz para utičnica"
+
+#: src/exec_monitor.c:340
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "neočekivani tip odgovora na povratnom kanalu: %d"
+
+#: src/exec_monitor.c:566
+msgid "unable to set controlling tty"
+msgstr "nije moguće uspostaviti upravljački TTY"
+
+#: src/exec_monitor.c:574 src/exec_nopty.c:504 src/exec_nopty.c:514
+#: src/exec_nopty.c:524 src/exec_nopty.c:560 src/exec_pty.c:1195
+#: src/exec_pty.c:1222 src/exec_pty.c:1242 src/exec_pty.c:1262
+#: src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr "nije moguće napraviti cijev"
+
+#: src/exec_monitor.c:584
+msgid "unable to receive message from parent"
+msgstr "nije moguće primiti poruku od pretka (roditelja)"
+
+#: src/exec_monitor.c:600 src/exec_nopty.c:603 src/exec_pty.c:1303
+#: src/sudo_edit.c:361 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr "nije moguće stvoriti novi proces (greška u fork())"
+
+#: src/exec_monitor.c:604 src/exec_monitor.c:700 src/exec_nopty.c:708
+msgid "unable to restore tty label"
+msgstr "nije moguće obnoviti TTY etiketu"
+
+#: src/exec_monitor.c:615 src/sesh.c:217 src/sudo.c:1204
+#, c-format
+msgid "unable to execute %s"
+msgstr "nije moguće izvršiti %s"
+
+# initialization > inicirati > dati/davati inicijativu, pobudu; pokrenuti/pokretati, započeti/započinjati
+#: src/exec_nopty.c:554 src/exec_pty.c:1131
+msgid "policy plugin failed session initialization"
+msgstr "plugin s pravilima nije uspio pokrenuti inicijalizaciju sesije"
+
+#: src/exec_nopty.c:569 src/exec_pty.c:1100 src/exec_pty.c:1109
+msgid "unable to create sockets"
+msgstr "nije moguće napraviti utičnice"
+
+#: src/exec_nopty.c:696 src/exec_pty.c:1406
+msgid "error in event loop"
+msgstr "greška u petlji događaja"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:852 src/sudo.c:488
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "**interna greška**, %s prekoračenje"
+
+#: src/exec_ptrace.c:1080 src/exec_ptrace.c:1105 src/exec_ptrace.c:1925
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "nije moguće postaviti registre za proces %d"
+
+#: src/exec_ptrace.c:1100 src/exec_ptrace.c:1275 src/exec_ptrace.c:1628
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "%d proces završio je neočekivano"
+
+#: src/exec_ptrace.c:1209
+msgid "unable to set seccomp filter"
+msgstr "nije moguće postaviti seccomp filtar"
+
+#: src/exec_ptrace.c:1406
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "argument interpretera, očekivano „%s“, a dobiveno je „%s“"
+
+#: src/exec_ptrace.c:1505
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "nepodudaranje imena staza, očekivano „%s“, a dobiveno je „%s“"
+
+#: src/exec_ptrace.c:1514 src/exec_ptrace.c:1521 src/exec_ptrace.c:1545
+#: src/exec_ptrace.c:1553 src/exec_ptrace.c:1559 src/exec_ptrace.c:1565
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "nepodudaranje %s[%d], očekivano „%s“, a dobiveno je „%s“"
+
+#: src/exec_ptrace.c:1632
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "proces %d neočekivani status 0x%x"
+
+#: src/exec_ptrace.c:1723
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "nije moguće dobiti poruku od događaja za proces %d"
+
+#: src/exec_ptrace.c:1730
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "nije moguće dobiti registre za proces %d"
+
+#: src/exec_pty.c:84
+msgid "unable to allocate pty"
+msgstr "nije moguće dodijeliti PTY"
+
+#: src/exec_pty.c:131 src/exec_pty.c:284 src/tgetpass.c:251
+msgid "unable to restore terminal settings"
+msgstr "nije moguće vratiti postavke terminala"
+
+# Handler, an asynchronous callback (computer programming) subroutine in computing
+#: src/exec_pty.c:243
+msgid "unable to set handler for SIGCONT"
+msgstr "nije moguće postaviti rukovatelja SIGCONT"
+
+# Handler, an asynchronous callback (computer programming) subroutine in computing
+#: src/exec_pty.c:293
+#, c-format
+msgid "unable to set handler for SIG%s"
+msgstr "nije moguće postaviti rukovatelja za SIG%s"
+
+#: src/exec_pty.c:317
+#, c-format
+msgid "unable to restore handler for SIG%s"
+msgstr "nije moguće vratiti rukovatelja za SIG%s"
+
+#: src/exec_pty.c:345
+msgid "unable to restore handler for SIGCONT"
+msgstr "nije moguće obnoviti rukovatelja za SIGCONT"
+
+#: src/exec_pty.c:1353
+msgid "unable to send message to monitor process"
+msgstr "nije moguće poslati poruku za praćenje procesa"
+
+#: src/load_plugins.c:75 src/load_plugins.c:222 src/load_plugins.c:232
+#: src/load_plugins.c:242 src/load_plugins.c:289
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "greška u %s, redak %d pri učitavanju plugina „%s“"
+
+#: src/load_plugins.c:186 src/load_plugins.c:257
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "zanemareni duplikat plugina „%s“ u %s, redak %d"
+
+#: src/load_plugins.c:224
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "nije moguće učitati %s: %s"
+
+#: src/load_plugins.c:234
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "nije moguće pronaći simbol „%s“ u %s"
+
+#: src/load_plugins.c:244
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "nekompatibilni plugin inačica %d (očekivana %d) pronađen u %s"
+
+#: src/load_plugins.c:262
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "zanemareni plugin s pravilima „%s“ u %s, redak %d"
+
+#: src/load_plugins.c:265
+msgid "only a single policy plugin may be specified"
+msgstr "smije se navesti samo jedan plugin s pravilima"
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "nepoznati tip %d plugina pronađena u %s"
+
+#: src/load_plugins.c:474
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "plugin s pravilima %s ne sadrži metodu check_policy"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "nevaljano ime varijable okoline: %s"
+
+#: src/parse_args.c:319
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "argument za -C mora biti broj veći ili jednak 3"
+
+#: src/parse_args.c:556
+msgid "you may not specify both the -i and -s options"
+msgstr "ne smijete navesti istovremeno opcije -i i -s"
+
+#: src/parse_args.c:561
+msgid "you may not specify both the -i and -E options"
+msgstr "ne smijete navesti istovremeno opcije -i i -E"
+
+#: src/parse_args.c:571
+msgid "the -E option is not valid in edit mode"
+msgstr "opcija -E nije valjana kad se redigira (in edit mode)"
+
+#: src/parse_args.c:574
+msgid "you may not specify environment variables in edit mode"
+msgstr "ne smijete specificirati varijable okoline kad se redigira (in edit mode)"
+
+#: src/parse_args.c:584
+msgid "the -U option may only be used with the -l option"
+msgstr "Opciju -U smijete koristiti samo uz -l opciju."
+
+#: src/parse_args.c:588
+msgid "the -A and -S options may not be used together"
+msgstr "opcije -A i -S ne smiju se koristiti zajedno"
+
+#: src/parse_args.c:686
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit nije podržan na ovoj platformi"
+
+#: src/parse_args.c:744
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Smije se navesti samo jedna od opcija -e, -h, -i, -K, -l, -s, -v i -V"
+
+#: src/parse_args.c:757
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "Smije se navesti samo jedna od opcija -K, -k ili -N"
+
+#: src/parse_args.c:778
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - redigira datoteku kao neki drugi korisnik\n"
+"\n"
+
+#: src/parse_args.c:780
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - izvrši naredbu kao neki drugi korisnik\n"
+"\n"
+
+#: src/parse_args.c:785
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Opcije:\n"
+
+#: src/parse_args.c:787
+msgid "use a helper program for password prompting"
+msgstr "zahtjev za lozinku koristi pomoćni program"
+
+#: src/parse_args.c:790
+msgid "use specified BSD authentication type"
+msgstr "rabi navedeni tip BSD autentifikacija"
+
+#: src/parse_args.c:794
+msgid "run command in the background"
+msgstr "pokrene naredbu u pozadini"
+
+#: src/parse_args.c:797
+msgid "ring bell when prompting"
+msgstr "pozvoni kad treba ulaz ili kad nešto pita"
+
+#: src/parse_args.c:799
+msgid "close all file descriptors >= num"
+msgstr "zatvara sve deskriptore datoteka >= num"
+
+#: src/parse_args.c:802
+msgid "run command with the specified BSD login class"
+msgstr "pokrene naredbu s navedenom BSD klasom prijave"
+
+#: src/parse_args.c:805
+msgid "change the working directory before running command"
+msgstr "promijenite radni direktorij prije pokretanja naredbe"
+
+#: src/parse_args.c:808
+msgid "preserve user environment when running command"
+msgstr "sačuva okolinu korisnika pri izvršenju naredbe"
+
+#: src/parse_args.c:810
+msgid "preserve specific environment variables"
+msgstr "sačuva specifične varijable okoline"
+
+#: src/parse_args.c:812
+msgid "edit files instead of running a command"
+msgstr "redigira datoteke umjesto pokretanja naredbe"
+
+#: src/parse_args.c:815
+msgid "run command as the specified group name or ID"
+msgstr "izvrši naredbu kao navedeno group ime ili ID"
+
+#: src/parse_args.c:818
+msgid "set HOME variable to target user's home dir"
+msgstr "var HOME postavi na osobni direktorij korisnika"
+
+#: src/parse_args.c:821
+msgid "display help message and exit"
+msgstr "pokaže ovu pomoć i iziđe"
+
+#: src/parse_args.c:823
+msgid "run command on host (if supported by plugin)"
+msgstr "pokrene naredbu na host računalu (ako to plugin podržava)"
+
+#: src/parse_args.c:826
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "pokrene prijavnu ljusku kao ciljani korisnik; može se navesti i naredba"
+
+#: src/parse_args.c:828
+msgid "remove timestamp file completely"
+msgstr "sasvim ukloni datoteku s vremenskim oznakama"
+
+#: src/parse_args.c:831
+msgid "invalidate timestamp file"
+msgstr "poništi datoteku s vremenskim oznakama"
+
+#: src/parse_args.c:834
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "privilegije korisnika ili test specifične naredbe; rabite -ll za duži popis"
+
+#: src/parse_args.c:837
+msgid "non-interactive mode, no prompts are used"
+msgstr "ne-interaktivni mȏd; bez prompta"
+
+#: src/parse_args.c:840
+msgid "preserve group vector instead of setting to target's"
+msgstr "sačuva grupni vektor umjesto postavljanja na ciljanu grupu"
+
+#: src/parse_args.c:843
+msgid "use the specified password prompt"
+msgstr "koristi navedeni prompt za unos lozinke"
+
+#: src/parse_args.c:845
+msgid "change the root directory before running command"
+msgstr "promijenite root direktorij prije pokretanja naredbe"
+
+#: src/parse_args.c:848
+msgid "create SELinux security context with specified role"
+msgstr "stvori SELinux sigurnosni kontekst s navedenom role ulogom"
+
+#: src/parse_args.c:851
+msgid "read password from standard input"
+msgstr "čita lozinku iz standardnog ulaza"
+
+#: src/parse_args.c:854
+msgid "run shell as the target user; a command may also be specified"
+msgstr "pokrene ljusku kao ciljani korisnik; može se navesti i naredba"
+
+#: src/parse_args.c:858
+msgid "create SELinux security context with specified type"
+msgstr "stvori SELinux sigurnosni kontekst specificiranog tipa"
+
+#: src/parse_args.c:861
+msgid "terminate command after the specified time limit"
+msgstr "naredba završi nakon navedenog vremenskog ograničenja"
+
+#: src/parse_args.c:864
+msgid "in list mode, display privileges for user"
+msgstr "izlista popis privilegija user korisnika"
+
+#: src/parse_args.c:867
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "pokreni naredbu (ili redigira datoteku) kao navedeni user korisnik"
+
+#: src/parse_args.c:869
+msgid "display version information and exit"
+msgstr "informira o inačici ovog programa i iziđe"
+
+#: src/parse_args.c:872
+msgid "update user's timestamp without running a command"
+msgstr "obnovi vremensku oznaku korisnika bez pokretanja naredbe"
+
+#: src/parse_args.c:875
+msgid "stop processing command line arguments"
+msgstr "prestane s obradom argumenata na naredbenom retku"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "nije moguće otvoriti revizijski sustav"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "nije moguće poslati revizijsku poruku"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "neuspješna fgetfilecon() %s"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s je promijenio etikete"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "nije moguće obnoviti kontekst za %s"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "nije moguće otvoriti %s, oznaka TTY se ne mijenja"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s nije znakovni uređaj (c-device), oznaka TTY se me mijenja"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "nije moguće dobiti trenutni TTY kontekst, oznaka TTY se me mijenja"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "nepoznata sigurnosna klasa „chr_file“, oznaka TTY se me mijenja"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "nije moguće dobiti novi TTY kontekst, oznaka TTY se me mijenja"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "nije moguće uspostaviti novi TTY kontekst"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "morate navesti ulogu za tip %s"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "nije moguće dobiti zadani tip za ulogu %s"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "nije uspjelo dobiti novi kontekst"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "nije uspjelo postaviti novu ulogu %s"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "nije uspjelo postaviti novi tip %s"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s nije valjani kontekst"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "nije uspjelo dobiti stari kontekst"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "nije moguće odrediti način provedbe."
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "nije moguće postaviti exec kontekst na %s"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "nije moguće postaviti kontekst stvaranja ključa na %s"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "Smije se navesti samo jedna od opcija -c ili -i"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "nevaljani broj deskriptora datoteke: %s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "opcija -%c ne smije se koristiti kad se redigira (in edit mode)"
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "Opciju -%c smijete koristiti samo za redigiranje (in edit mode)."
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: simboličke poveznice nije dopušteno redigirati"
+
+# writable> zapisiv, upisiv, u kojem je dopušteno pisati
+# http://hjp.znanje.hr/ > upisiv > koji se može upisati, koji ispunjava uvjete upisa
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: datoteke nije dopušteno redigirati u direktoriju koji dopušta pisanje"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "sadržaj sesije redigiranja je ostavljen u %s"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "nije moguće dobiti popis grupa"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "nije moguće sačuvati rukovatelja za signal %d"
+
+#: src/signal.c:101 src/suspend_parent.c:149
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "nije moguće obnoviti rukovatelja za signal %d"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "dosegnuta je granica upravljanja resursima"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "korisnik „%s“ nije član projekta „%s“"
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "pozvani zadatak je zadnji -- svršetak"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "nije bilo moguće pridružiti se projektu „%s“"
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "ne postoji skup resursa koji prihvaća zadane poveznice za projekt „%s“"
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "ne postoji navedeni skup resursa za projekt „%s“"
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "nije bilo moguće povezati se na zadani skup resursa za projekt „%s“"
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "neuspješna setproject() za projekt „%s“"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "upozorenje: nije uspjelo dodijeliti upravljanje resursima projekta „%s“"
+
+#: src/sudo.c:214
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo inačica %s\n"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Konfiguracijske opcije: %s\n"
+
+#: src/sudo.c:224
+msgid "fatal error, unable to load plugins"
+msgstr "kobna greška, nije moguće učitati plugine"
+
+#: src/sudo.c:270
+msgid "plugin did not return a command to execute"
+msgstr "plugin nije uzvratio naredbu za izvršiti"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "neočekivani sudo mȏd 0x%x"
+
+#: src/sudo.c:559
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "vas nema u %s bazi podataka"
+
+#: src/sudo.c:616
+msgid "unable to determine tty"
+msgstr "nije moguće odrediti TTY"
+
+#: src/sudo.c:932
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "Flag „no new privileges“ je podignut, i to sprečava da sudo postane root."
+
+#: src/sudo.c:934
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "Ako se sudo pokrene u kanistru (container), možda ćete morati podesiti konfiguraciju kanistra kako biste onemogućili flag."
+
+#: src/sudo.c:968
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "vlasnik %s mora biti UID %d i mora imati postavljeni setuid bit"
+
+#: src/sudo.c:971
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "efektivni UID nije %d; je li %s na datotečnom sustavu s postavljenom opcijom „nosuid“ ili NFS datotečnom sustavu bez root privilegija?"
+
+#: src/sudo.c:977
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "efektivni UID nije %d; je li sudo instaliran sa setuid root?"
+
+#: src/sudo.c:993 src/tgetpass.c:332
+msgid "unable to set supplementary group IDs"
+msgstr "nije moguće postaviti ID dodatnih grupa"
+
+#: src/sudo.c:1000
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "nije moguće postaviti efektivni GID na runas GID %u"
+
+#: src/sudo.c:1006
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "nije moguće postaviti GID na runas GID %u"
+
+#: src/sudo.c:1037
+msgid "argv not set by the security policy"
+msgstr "argv nije postavljen po sigurnosnim pravilima"
+
+#: src/sudo.c:1041
+msgid "envp not set by the security policy"
+msgstr "envp nije postavljen po sigurnosnim pravilima"
+
+#: src/sudo.c:1063
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "neočekivano stanje završetka potomka (dijete-procesa) : %d"
+
+#: src/sudo.c:1176
+msgid "unable to initialize policy plugin"
+msgstr "nije moguće inicijalizirati plugin s pravilima"
+
+#: src/sudo.c:1238
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "pluginu s pravilima %s nedostaje metoda „check_policy“"
+
+#: src/sudo.c:1284
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "plugin s pravilima %s ne podržava ispis ovlasti"
+
+#: src/sudo.c:1328
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "plugin s pravilima %s ne podržava opciju -v"
+
+#: src/sudo.c:1366
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "plugin s pravilima %s ne podržava -k/-K opcije"
+
+#: src/sudo.c:1495
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "greška pri inicijalizaciji U/I plugina %s"
+
+#: src/sudo.c:1498
+msgid "error initializing I/O plugin"
+msgstr "greška pri inicijalizaciji U/I plugina"
+
+#: src/sudo.c:1647
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "greška pri inicijalizaciji plugina za reviziju %s"
+
+#: src/sudo.c:1726
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: nije uspjelo zabilježiti pogrešku događaja%s%s"
+
+#: src/sudo.c:1762
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: nije uspjelo zabilježiti događaj prihvaćanja%s%s"
+
+#: src/sudo.c:1767 src/sudo.c:1805
+msgid "audit plugin error"
+msgstr "pogreška u pluginu za reviziju"
+
+#: src/sudo.c:1800
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: nije uspjelo zabilježiti događaj odbijanja%s%s"
+
+#: src/sudo.c:1860
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "greška pri inicijalizaciji plugina za odobrenje %s"
+
+#: src/sudo.c:1930
+msgid "command rejected by approver"
+msgstr "odobravatelj je odbio izvršiti naredbu"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "nije pronađen privremeni direktorij u koji je moguće pisati"
+
+#: src/sudo_edit.c:292
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s nije izmijenjeno"
+
+#: src/sudo_edit.c:305 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s nije promijenjeno"
+
+#: src/sudo_edit.c:482
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: interna greška: neparni broj staza"
+
+#: src/sudo_edit.c:484
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: nije moguće čitati privremenu datoteku"
+
+#: src/sudo_edit.c:486 src/sudo_edit.c:606
+msgid "sesh: killed by a signal"
+msgstr "sesh: ubijen signalom"
+
+#: src/sudo_edit.c:488 src/sudo_edit.c:609
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: nepoznata greška: %d"
+
+#: src/sudo_edit.c:599
+msgid "unable to copy temporary files back to their original location"
+msgstr "nije moguće kopirati privremene datoteke u njihovu originalnu lokaciju"
+
+#: src/sudo_edit.c:603
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "nije moguće kopirati neke od privremenih datoteka u njihovu originalnu lokaciju"
+
+#: src/sudo_edit.c:650
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "nije moguće promijeniti UID na root (%u)"
+
+#: src/sudo_edit.c:664
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "greška plugina: nevaljani popis datoteka za sudoedit"
+
+#: src/sudo_edit.c:685
+msgid "plugin error: missing file list for sudoedit"
+msgstr "greška plugina: nedostaje popis datoteka za sudoedit"
+
+#: src/sudo_edit.c:728 src/sudo_edit.c:743
+msgid "unable to read the clock"
+msgstr "nije moguće pročitati vrijeme (clock)"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "port za presretanje nije postavljen"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "vrijeme za čitanje lozinke je isteklo"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "nema lozinke (nije unesena)"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "nije moguće pročitati lozinku"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "za čitanje lozinke trebate terminal; rabite opciju -S za čitanje sa standardnog ulaza ili konfigurirajte askpass pomoćnika (pomoćni program)"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "nije specificiran askpass program, pokušajte postaviti SUDO_ASKPASS"
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "nije moguće postaviti GID na %u"
+
+#: src/tgetpass.c:337
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "nije moguće postaviti UID na %u"
+
+#: src/tgetpass.c:342
+#, c-format
+msgid "unable to run %s"
+msgstr "nije moguće pokrenuti %s"
+
+#: src/utmp.c:283
+msgid "unable to save stdin"
+msgstr "nije moguće sačuvati stdin"
+
+#: src/utmp.c:285
+msgid "unable to dup2 stdin"
+msgstr "dup2 nije moguće primijeniti na stdin"
+
+#: src/utmp.c:288
+msgid "unable to restore stdin"
+msgstr "nije moguće obnoviti stdin"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "vlasnik %s mora biti UID %d"
+
+#~ msgid "%s must be only be writable by owner"
+#~ msgstr "%s za pisanje mora biti dostupan samo vlasniku"
+
+#~ msgid "insufficient space for execve arguments"
+#~ msgstr "nema dovoljno mjesta za execve argumente"
+
+#~ msgid "unable to read execve %s for process %d"
+#~ msgstr "nije moguće pročitati execve %s za proces %d"
+
+#~ msgid "requires at least one argument"
+#~ msgstr "zahtijeva barem jedan argument"
+
+#~ msgid "unable to run %s as a login shell"
+#~ msgstr "nije moguće pokrenuti %s kao prijavnu ljusku"
+
+#~ msgid "unable to dup intercept fd"
+#~ msgstr "nije uspjelo duplicirati deskriptor presrele datoteke"
+
+#~ msgid "%s: missing message header"
+#~ msgstr "%s: poruci nedostaje zaglavlje"
+
+#~ msgid "%s: expected message type %d, got %d"
+#~ msgstr "%s: očekivana je poruka vrste %d, a dobivena je %d"
+
+#~ msgid "unable to set tty context to %s"
+#~ msgstr "nije moguće postaviti TTY kontekst za %s"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s: %s"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s: nepotpuni zapis"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "nije moguće čitati privremenu datoteku"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "ignorira se duplikat plugina s pravilima „%s“ u %s, redak %d"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "nema TTY i nije specificiran askpass program"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "nepoznat UID %u: tko ste vi?"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "greška pri čitanju iz signalne cijevi"
+
+#~ msgid "internal error, tried to emalloc(0)"
+#~ msgstr "interna greška, pokušao sam emalloc(0)"
+
+#~ msgid "internal error, tried to emalloc2(0)"
+#~ msgstr "interna greška, pokušao sam emalloc2(0)"
+
+#~ msgid "internal error, tried to ecalloc(0)"
+#~ msgstr "interna greška, pokušao sam ecalloc(0)"
+
+#~ msgid "internal error, tried to erealloc(0)"
+#~ msgstr "interna greška, pokušao sam erealloc(0)"
+
+#~ msgid "internal error, tried to erealloc3(0)"
+#~ msgstr "interna greška, pokušao sam erealloc3(0)"
+
+#~ msgid "internal error, tried to erecalloc(0)"
+#~ msgstr "interna greška, pokušao sam erecalloc(0)"
+
+#~ msgid "%s: %s: %s\n"
+#~ msgstr "%s: %s: %s\n"
+
+#~ msgid "%s: %s\n"
+#~ msgstr "%s: %s\n"
+
+#~ msgid "select failed"
+#~ msgstr "odabir nije uspio"
+
+#~ msgid "unable to set terminal to raw mode"
+#~ msgstr "ne mogu postaviti terminal u sirovi način"
+
+#~ msgid "load_interfaces: overflow detected"
+#~ msgstr "load_interfaces: otkriven preljev"
+
+#~ msgid "unable to open socket"
+#~ msgstr "ne mogu otvoriti utičnicu"
+
+#~ msgid "list user's available commands\n"
+#~ msgstr "ispiši dostupne korisničke naredbe\n"
+
+#~ msgid "run a shell as target user\n"
+#~ msgstr "pokreni ljusku kao odredišni korisnik\n"
+
+#~ msgid "when listing, list specified user's privileges\n"
+#~ msgstr "pri ispisu, ispiši navedene korisničke ovlasti\n"
+
+#~ msgid ": "
+#~ msgstr ": "
+
+#~ msgid "internal error, emalloc2() overflow"
+#~ msgstr "interna greška, emalloc2() preljev"
+
+#~ msgid "internal error, erealloc3() overflow"
+#~ msgstr "interna greška, erealloc3() preljev"
+
+#~ msgid "%s: at least one policy plugin must be specified"
+#~ msgstr "%s: mora biti naveden barem jedan priključak police"
diff --git a/po/hu.mo b/po/hu.mo
new file mode 100644
index 0000000..18d2282
--- /dev/null
+++ b/po/hu.mo
Binary files differ
diff --git a/po/hu.po b/po/hu.po
new file mode 100644
index 0000000..4a66835
--- /dev/null
+++ b/po/hu.po
@@ -0,0 +1,883 @@
+# Hungarian translation for sudo.
+# Copyright (C) 2016, 2017, 2018 Free Software Foundation, Inc.
+# This file is distributed under the same license as the sudo package.
+#
+# Gabor Kelemen <kelemeng@gnome.hu>, 2016.
+# Balázs Úr <urbalazs@gmail.com>, 2017, 2018.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.8.21b2\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2017-08-03 10:04-0600\n"
+"PO-Revision-Date: 2018-01-20 13:53+0100\n"
+"Last-Translator: Balázs Úr <urbalazs@gmail.com>\n"
+"Language-Team: Hungarian <translation-team-hu@lists.sourceforge.net>\n"
+"Language: hu\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Launchpad-Export-Date: 2016-01-03 00:40+0000\n"
+"X-Generator: Lokalize 1.2\n"
+
+#: lib/util/aix.c:85 lib/util/aix.c:172
+msgid "unable to open userdb"
+msgstr "userdb megnyitása sikertelen"
+
+#: lib/util/aix.c:227
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "a(z) „%s” regisztrációs adatbázisra váltás sikertelen ennél: %s"
+
+#: lib/util/aix.c:252
+msgid "unable to restore registry"
+msgstr "a rendszerleíró visszaállítása sikertelen"
+
+#: lib/util/aix.c:275 lib/util/gidlist.c:64 lib/util/gidlist.c:74
+#: lib/util/sudo_conf.c:186 lib/util/sudo_conf.c:272 lib/util/sudo_conf.c:349
+#: lib/util/sudo_conf.c:553 src/conversation.c:75 src/exec_common.c:107
+#: src/exec_common.c:123 src/exec_common.c:132 src/exec_monitor.c:167
+#: src/exec_nopty.c:462 src/exec_pty.c:667 src/exec_pty.c:676
+#: src/exec_pty.c:738 src/exec_pty.c:867 src/load_plugins.c:52
+#: src/load_plugins.c:65 src/load_plugins.c:215 src/load_plugins.c:238
+#: src/load_plugins.c:303 src/load_plugins.c:318 src/parse_args.c:177
+#: src/parse_args.c:198 src/parse_args.c:273 src/parse_args.c:540
+#: src/parse_args.c:562 src/preserve_fds.c:47 src/preserve_fds.c:130
+#: src/selinux.c:84 src/selinux.c:309 src/selinux.c:432 src/selinux.c:441
+#: src/sesh.c:115 src/sudo.c:389 src/sudo.c:416 src/sudo.c:481 src/sudo.c:603
+#: src/sudo.c:663 src/sudo.c:673 src/sudo.c:693 src/sudo.c:712 src/sudo.c:721
+#: src/sudo.c:730 src/sudo.c:747 src/sudo.c:788 src/sudo.c:798 src/sudo.c:818
+#: src/sudo.c:1058 src/sudo.c:1079 src/sudo.c:1253 src/sudo.c:1351
+#: src/sudo_edit.c:148 src/sudo_edit.c:771 src/sudo_edit.c:868
+#: src/sudo_edit.c:982 src/sudo_edit.c:1002
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:275 lib/util/gidlist.c:64 lib/util/sudo_conf.c:187
+#: lib/util/sudo_conf.c:272 lib/util/sudo_conf.c:349 lib/util/sudo_conf.c:553
+#: src/conversation.c:76 src/exec_common.c:107 src/exec_common.c:124
+#: src/exec_common.c:133 src/exec_pty.c:667 src/exec_pty.c:676
+#: src/exec_pty.c:738 src/load_plugins.c:215 src/load_plugins.c:238
+#: src/load_plugins.c:303 src/load_plugins.c:318 src/parse_args.c:177
+#: src/parse_args.c:199 src/parse_args.c:273 src/parse_args.c:540
+#: src/parse_args.c:562 src/preserve_fds.c:47 src/preserve_fds.c:130
+#: src/selinux.c:84 src/selinux.c:309 src/selinux.c:432 src/selinux.c:441
+#: src/sesh.c:115 src/sudo.c:389 src/sudo.c:416 src/sudo.c:481 src/sudo.c:603
+#: src/sudo.c:818 src/sudo.c:1058 src/sudo.c:1079 src/sudo.c:1253
+#: src/sudo.c:1351 src/sudo_edit.c:148 src/sudo_edit.c:771 src/sudo_edit.c:868
+#: src/sudo_edit.c:982 src/sudo_edit.c:1002
+msgid "unable to allocate memory"
+msgstr "a memóriafoglalás sikertelen"
+
+#: lib/util/strsignal.c:48
+msgid "Unknown signal"
+msgstr "Ismeretlen szignál"
+
+#: lib/util/strtoid.c:77 lib/util/strtoid.c:124 lib/util/strtoid.c:152
+#: lib/util/strtomode.c:49 lib/util/strtonum.c:58 lib/util/strtonum.c:176
+msgid "invalid value"
+msgstr "érvénytelen érték"
+
+#: lib/util/strtoid.c:84 lib/util/strtoid.c:131 lib/util/strtoid.c:159
+#: lib/util/strtomode.c:55 lib/util/strtonum.c:61 lib/util/strtonum.c:188
+msgid "value too large"
+msgstr "túl magas érték"
+
+#: lib/util/strtoid.c:86 lib/util/strtoid.c:137 lib/util/strtomode.c:55
+#: lib/util/strtonum.c:61 lib/util/strtonum.c:182
+msgid "value too small"
+msgstr "túl alacsony érték"
+
+#: lib/util/sudo_conf.c:205
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "érvénytelen „%s” útvonal érték a(z) %s, %u. sorában"
+
+#: lib/util/sudo_conf.c:371 lib/util/sudo_conf.c:424
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "a(z) %s értéke („%s”) érvénytelen a(z) %s, %u. sorában"
+
+#: lib/util/sudo_conf.c:392
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "nem támogatott „%s” csoportforrás a(z) %s, %u. sorában"
+
+#: lib/util/sudo_conf.c:408
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "érvénytelen legnagyobb csoportok („%s”) a(z) %s, %u. sorában"
+
+#: lib/util/sudo_conf.c:569
+#, c-format
+msgid "unable to stat %s"
+msgstr "%s nem érhető el"
+
+#: lib/util/sudo_conf.c:572
+#, c-format
+msgid "%s is not a regular file"
+msgstr "a(z) %s nem szabályos fájl"
+
+#: lib/util/sudo_conf.c:575
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s a(z) %u uid tulajdona, ennek kellene lennie: %u"
+
+#: lib/util/sudo_conf.c:579
+#, c-format
+msgid "%s is world writable"
+msgstr "%s bárki számára írható"
+
+#: lib/util/sudo_conf.c:582
+#, c-format
+msgid "%s is group writable"
+msgstr "%s a csoport számára írható"
+
+#: lib/util/sudo_conf.c:592 src/selinux.c:208 src/selinux.c:225 src/sudo.c:357
+#, c-format
+msgid "unable to open %s"
+msgstr "%s nem nyitható meg"
+
+#: src/exec.c:160
+#, c-format
+msgid "unknown login class %s"
+msgstr "ismeretlen %s logikai osztály"
+
+#: src/exec.c:173
+msgid "unable to set user context"
+msgstr "a felhasználói környezet beállítása sikertelen"
+
+#: src/exec.c:189
+msgid "unable to set process priority"
+msgstr "a folyamat prioritásának beállítása sikertelen"
+
+#: src/exec.c:197
+#, c-format
+msgid "unable to change root to %s"
+msgstr "a gyökér megváltoztatása sikertelen erre: %s"
+
+#: src/exec.c:210 src/exec.c:216 src/exec.c:223
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "a runas uid értékre (%u, %u) váltás sikertelen"
+
+#: src/exec.c:241
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "a könyvtárváltás sikertelen erre: %s"
+
+#: src/exec.c:337 src/exec_monitor.c:526 src/exec_monitor.c:528
+#: src/exec_nopty.c:520 src/exec_pty.c:472 src/exec_pty.c:1184
+#: src/exec_pty.c:1186 src/signal.c:139 src/signal.c:153
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "%d szignál kezelőjének beállítása sikertelen"
+
+#: src/exec_common.c:166
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "a PRIV_PROC_EXEC eltávolítása sikertelen a PRIV_LIMIT-ből"
+
+#: src/exec_monitor.c:326
+msgid "error reading from socketpair"
+msgstr "hiba a foglalatpárból való olvasáskor"
+
+#: src/exec_monitor.c:338
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "váratlan választípus a visszcsatornán: %d"
+
+#: src/exec_monitor.c:423 src/exec_monitor.c:431 src/exec_monitor.c:439
+#: src/exec_monitor.c:446 src/exec_monitor.c:453 src/exec_monitor.c:460
+#: src/exec_monitor.c:467 src/exec_monitor.c:474 src/exec_monitor.c:481
+#: src/exec_monitor.c:488 src/exec_nopty.c:215 src/exec_nopty.c:224
+#: src/exec_nopty.c:231 src/exec_nopty.c:238 src/exec_nopty.c:245
+#: src/exec_nopty.c:252 src/exec_nopty.c:259 src/exec_nopty.c:266
+#: src/exec_nopty.c:273 src/exec_nopty.c:280 src/exec_nopty.c:287
+#: src/exec_nopty.c:294 src/exec_nopty.c:302 src/exec_pty.c:563
+#: src/exec_pty.c:568 src/exec_pty.c:635 src/exec_pty.c:642 src/exec_pty.c:743
+#: src/exec_pty.c:1029 src/exec_pty.c:1038 src/exec_pty.c:1045
+#: src/exec_pty.c:1052 src/exec_pty.c:1059 src/exec_pty.c:1066
+#: src/exec_pty.c:1073 src/exec_pty.c:1080 src/exec_pty.c:1087
+#: src/exec_pty.c:1094 src/exec_pty.c:1101 src/exec_pty.c:1446
+#: src/exec_pty.c:1456 src/exec_pty.c:1501 src/exec_pty.c:1508
+#: src/exec_pty.c:1533
+msgid "unable to add event to queue"
+msgstr "az esemény hozzáadása a sorhoz sikertelen"
+
+#: src/exec_monitor.c:540
+msgid "unable to set controlling tty"
+msgstr "a vezérlő tty beállítása sikertelen"
+
+#: src/exec_monitor.c:548 src/exec_nopty.c:359 src/exec_pty.c:1261
+#: src/exec_pty.c:1280 src/exec_pty.c:1298 src/tgetpass.c:246
+msgid "unable to create pipe"
+msgstr "adatcsatorna létrehozása sikertelen"
+
+#: src/exec_monitor.c:553 src/exec_nopty.c:377 src/exec_pty.c:1335
+#: src/tgetpass.c:250
+msgid "unable to fork"
+msgstr "az elágaztatás sikertelen"
+
+#: src/exec_monitor.c:639 src/exec_nopty.c:430
+msgid "unable to restore tty label"
+msgstr "a tty címke visszaállítása sikertelen"
+
+#: src/exec_nopty.c:353 src/exec_pty.c:1193
+msgid "policy plugin failed session initialization"
+msgstr "a házirendbővítménynek nem sikerült a munkamenet előkészítése"
+
+#: src/exec_nopty.c:419 src/exec_pty.c:1404
+msgid "error in event loop"
+msgstr "hiba az eseményhurokban"
+
+#: src/exec_nopty.c:528 src/exec_pty.c:504 src/signal.c:101
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "%d szignál kezelőjének visszaállítása sikertelen"
+
+#: src/exec_pty.c:143
+msgid "unable to allocate pty"
+msgstr "a pty lefoglalása sikertelen"
+
+#: src/exec_pty.c:1173
+msgid "unable to create sockets"
+msgstr "a foglalatok létrehozása sikertelen"
+
+#: src/load_plugins.c:50 src/load_plugins.c:63 src/load_plugins.c:85
+#: src/load_plugins.c:115 src/load_plugins.c:123 src/load_plugins.c:129
+#: src/load_plugins.c:170 src/load_plugins.c:178 src/load_plugins.c:185
+#: src/load_plugins.c:191
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "hiba a(z) %s, %d. sorában a(z) „%s” bővítmény betöltése közben"
+
+#: src/load_plugins.c:87
+#, c-format
+msgid "%s%s: %s"
+msgstr "%s%s: %s"
+
+#: src/load_plugins.c:125
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s a(z) %d uid tulajdona kell legyen"
+
+#: src/load_plugins.c:131
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "%s csak a tulajdonos által írható lehet"
+
+#: src/load_plugins.c:172
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "a(z) %s nem tölthető be: %s"
+
+#: src/load_plugins.c:180
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "a(z) „%s” szimbólum nem található ebben: %s"
+
+#: src/load_plugins.c:187
+#, c-format
+msgid "unknown policy type %d found in %s"
+msgstr "ismeretlen %d házirendtípus található ebben: %s"
+
+#: src/load_plugins.c:193
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "összeférhetetlen %d bővítmény főverzió (várt: %d) található ebben: %s"
+
+#: src/load_plugins.c:202
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "a(z) „%s” házirendbővítmény mellőzése a(z) %s, %d. sorában"
+
+#: src/load_plugins.c:204
+msgid "only a single policy plugin may be specified"
+msgstr "csak egyetlen házirendbővítmény határozható meg"
+
+#: src/load_plugins.c:207
+#, c-format
+msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+msgstr "kettőzött „%s” házirendbővítmény mellőzése a(z) %s, %d. sorában"
+
+#: src/load_plugins.c:228
+#, c-format
+msgid "ignoring duplicate I/O plugin \"%s\" in %s, line %d"
+msgstr "kettőzött „%s” I/O bővítmény mellőzése a(z) %s, %d. sorában"
+
+#: src/load_plugins.c:331
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "a(z) %s házirendbővítmény nem tartalmazza a „check_policy” metódust"
+
+#: src/net_ifs.c:173 src/net_ifs.c:190 src/net_ifs.c:335 src/sudo.c:476
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "belső hiba, %s túlcsordul"
+
+#: src/parse_args.c:219
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "érvénytelen környezeti változó név: %s"
+
+#: src/parse_args.c:313
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "a -C kapcsoló argumentuma legyen 3, vagy ennél nagyobb szám"
+
+#: src/parse_args.c:480
+msgid "you may not specify both the `-i' and `-s' options"
+msgstr "az „-i” és „-s” kapcsoló egyszerre nem használható"
+
+#: src/parse_args.c:484
+msgid "you may not specify both the `-i' and `-E' options"
+msgstr "az „-i” és „-E” kapcsoló egyszerre nem használható"
+
+#: src/parse_args.c:494
+msgid "the `-E' option is not valid in edit mode"
+msgstr "az „-E” kapcsoló nem használható szerkesztő módban"
+
+#: src/parse_args.c:496
+msgid "you may not specify environment variables in edit mode"
+msgstr "nem használhat környezeti változókat szerkesztő módban"
+
+#: src/parse_args.c:504
+msgid "the `-U' option may only be used with the `-l' option"
+msgstr "az „-U” kapcsoló csak a „-l” kapcsolóval együtt használható"
+
+#: src/parse_args.c:508
+msgid "the `-A' and `-S' options may not be used together"
+msgstr "az „-A” és „-S” kapcsoló együtt nem használható"
+
+#: src/parse_args.c:584
+msgid "sudoedit is not supported on this platform"
+msgstr "a „sudoedit” nem támogatott ezen a rendszeren"
+
+#: src/parse_args.c:657
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Kizárólag az -e, -h, -i, -K, -l, -s, -v vagy -V kapcsolók egyike használható"
+
+#: src/parse_args.c:671
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - fájlok szerkesztése más felhasználóként\n"
+"\n"
+
+#: src/parse_args.c:673
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - parancs végrehajtása más felhasználóként\n"
+"\n"
+
+#: src/parse_args.c:678
+#, c-format
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Kapcsolók:\n"
+
+#: src/parse_args.c:680
+msgid "use a helper program for password prompting"
+msgstr "segédprogram használata a jelszóbekérésre"
+
+#: src/parse_args.c:683
+msgid "use specified BSD authentication type"
+msgstr "megadott BSD hitelesítési típus használata"
+
+#: src/parse_args.c:686
+msgid "run command in the background"
+msgstr "parancs futtatása a háttérben"
+
+#: src/parse_args.c:688
+msgid "close all file descriptors >= num"
+msgstr "minden fájlleíró lezárása, ami >= num"
+
+#: src/parse_args.c:691
+msgid "run command with the specified BSD login class"
+msgstr "parancs futtatása a megadott BSD bejelentkezési osztállyal"
+
+#: src/parse_args.c:694
+msgid "preserve user environment when running command"
+msgstr "felhasználói környezet megőrzése parancsfuttatáskor"
+
+#: src/parse_args.c:696
+msgid "preserve specific environment variables"
+msgstr "bizonyos környezeti változók megőrzése"
+
+#: src/parse_args.c:698
+msgid "edit files instead of running a command"
+msgstr "fájlok szerkesztése parancs futtatása helyett"
+
+#: src/parse_args.c:700
+msgid "run command as the specified group name or ID"
+msgstr "parancs futtatása megadott csoportnévként vagy -azonosítóként"
+
+#: src/parse_args.c:702
+msgid "set HOME variable to target user's home dir"
+msgstr "a HOME változó beállítása a célfelhasználó saját könyvtárára"
+
+#: src/parse_args.c:704
+msgid "display help message and exit"
+msgstr "súgóüzenet megjelenítése és kilépés"
+
+#: src/parse_args.c:706
+msgid "run command on host (if supported by plugin)"
+msgstr "parancs futtatása a gépen (ha a bővítmény támogatja)"
+
+#: src/parse_args.c:708
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "bejelentkezési parancsértelmező futtatása a célfelhasználóként; egy parancs is megadható"
+
+#: src/parse_args.c:710
+msgid "remove timestamp file completely"
+msgstr "időbélyeg fájl teljes eltávolítása"
+
+#: src/parse_args.c:712
+msgid "invalidate timestamp file"
+msgstr "időbélyeg fájl érvénytelenítése"
+
+#: src/parse_args.c:714
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "felhasználó jogosultságainak felsorolása, vagy adott parancs ellenőrzése, kétszer megadva hosszabb formátumban"
+
+#: src/parse_args.c:716
+msgid "non-interactive mode, no prompts are used"
+msgstr "nem interaktív mód, kérdések nélkül"
+
+#: src/parse_args.c:718
+msgid "preserve group vector instead of setting to target's"
+msgstr "csoportvektor megőrzése a céléra beállítás helyett"
+
+#: src/parse_args.c:720
+msgid "use the specified password prompt"
+msgstr "a megadott jelszóbekérés használata"
+
+#: src/parse_args.c:723
+msgid "create SELinux security context with specified role"
+msgstr "SELinux biztonsági környezet létrehozása a megadott szereppel"
+
+#: src/parse_args.c:726
+msgid "read password from standard input"
+msgstr "jelszó olvasása a szabványos bemenetről"
+
+#: src/parse_args.c:728
+msgid "run shell as the target user; a command may also be specified"
+msgstr "parancsértelmező futtatása a célfelhasználóként; egy parancs is megadható"
+
+#: src/parse_args.c:731
+msgid "create SELinux security context with specified type"
+msgstr "SELinux biztonsági környezet létrehozása a megadott típussal"
+
+#: src/parse_args.c:734
+msgid "terminate command after the specified time limit"
+msgstr "parancs megszakítása a megadott időkorlát után"
+
+#: src/parse_args.c:736
+msgid "in list mode, display privileges for user"
+msgstr "lista módban a felhasználó jogosultságainak megjelenítése"
+
+#: src/parse_args.c:738
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "parancs futtatása (vagy fájl szerkesztése) a megadott nevű vagy azonosítójú felhasználóként"
+
+#: src/parse_args.c:740
+msgid "display version information and exit"
+msgstr "verzióinformáció kiírása és kilépés"
+
+#: src/parse_args.c:742
+msgid "update user's timestamp without running a command"
+msgstr "felhasználó időbélyegének frissítése parancs futtatása nélkül"
+
+#: src/parse_args.c:744
+msgid "stop processing command line arguments"
+msgstr "parancssori argumentumok feldolgozásának befejezése"
+
+#: src/selinux.c:78
+msgid "unable to open audit system"
+msgstr "a felülvizsgálati rendszer megnyitása sikertelen"
+
+#: src/selinux.c:88
+msgid "unable to send audit message"
+msgstr "a felülvizsgálati üzenet küldése sikertelen"
+
+#: src/selinux.c:116
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "az fgetfilecon %s futtatása sikertelen"
+
+#: src/selinux.c:121
+#, c-format
+msgid "%s changed labels"
+msgstr "%s megváltoztatta a címkéket"
+
+#: src/selinux.c:126
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "%s környezetének visszaállítása sikertelen"
+
+#: src/selinux.c:167
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "%s nem nyitható meg, a tty nem címkézhető újra"
+
+#: src/selinux.c:171 src/selinux.c:212 src/selinux.c:229
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "a(z) %s nem karakteres eszköz, a tty nem címkézhető újra"
+
+#: src/selinux.c:180
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "a jelenlegi tty környezet lekérése sikertelen, a tty nem címkézhető újra"
+
+#: src/selinux.c:187
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "ismeretlen „chr_file” biztonsági osztály, a tty nem címkézhető újra"
+
+#: src/selinux.c:192
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "az új tty környezet lekérése sikertelen, a tty nem címkézhető újra"
+
+#: src/selinux.c:199
+msgid "unable to set new tty context"
+msgstr "az új tty környezet beállítása sikertelen"
+
+#: src/selinux.c:273
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "meg kell adnia egy szerepet a(z) %s típushoz"
+
+#: src/selinux.c:279
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "az alapértelmezett típus lekérése sikertelen a(z) %s szerepnél"
+
+#: src/selinux.c:297
+#, c-format
+msgid "failed to set new role %s"
+msgstr "%s új szerep beállítása nem sikerült"
+
+#: src/selinux.c:301
+#, c-format
+msgid "failed to set new type %s"
+msgstr "%s új típus beállítása nem sikerült"
+
+#: src/selinux.c:313
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s nem érvényes környezet"
+
+#: src/selinux.c:348
+msgid "failed to get old_context"
+msgstr "az old_context lekérése nem sikerült"
+
+#: src/selinux.c:354
+msgid "unable to determine enforcing mode."
+msgstr "a kényszerítő mód meghatározása sikertelen."
+
+#: src/selinux.c:371
+#, c-format
+msgid "unable to set tty context to %s"
+msgstr "a tty környezet beállítása sikertelen erre: %s"
+
+#: src/selinux.c:410
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "a végrehajtási környezet beállítása sikertelen erre: %s"
+
+#: src/selinux.c:417
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "a kulcslétrehozási környezet beállítása sikertelen erre: %s"
+
+#: src/sesh.c:77
+msgid "requires at least one argument"
+msgstr "legalább egy argumentum szükséges"
+
+#: src/sesh.c:106
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "érvénytelen fájlleíró szám: %s"
+
+#: src/sesh.c:120
+#, c-format
+msgid "unable to run %s as a login shell"
+msgstr "%s futtatása bejelentkezési parancsértelmezőként sikertelen"
+
+#: src/sesh.c:125 src/sudo.c:1117
+#, c-format
+msgid "unable to execute %s"
+msgstr "%s nem hajtható végre"
+
+#: src/signal.c:83
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "%d szignál kezelőjének mentése sikertelen"
+
+#: src/solaris.c:76
+msgid "resource control limit has been reached"
+msgstr "az erőforrás-vezérlési korlát elérve"
+
+#: src/solaris.c:79
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "„%s” felhasználó nem tagja ennek a projektnek: „%s”"
+
+#: src/solaris.c:83
+msgid "the invoking task is final"
+msgstr "a meghívó feladat végső"
+
+#: src/solaris.c:86
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "nem sikerült a(z) „%s” projekthez csatlakozás"
+
+#: src/solaris.c:91
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "nem létezik alapértelmezett kötéseket elfogadó erőforrás-tároló a(z) „%s” projektnél"
+
+#: src/solaris.c:95
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "a megadott erőforrás-tároló nem létezik a(z) „%s” projektnél"
+
+#: src/solaris.c:99
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "nem sikerült hozzákötni az alapértelmezett erőforrás-tárolóhoz a(z) „%s” projektnél"
+
+#: src/solaris.c:105
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "a projekt beállítása nem sikerült a(z) „%s” projektnél"
+
+#: src/solaris.c:107
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "figyelmeztetés: az erőforrás-vezérlés hozzárendelése nem sikerült a(z) „%s” projektnél"
+
+#: src/sudo.c:198
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo %s verzió\n"
+
+#: src/sudo.c:200
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Configure kapcsolói: %s\n"
+
+#: src/sudo.c:208
+msgid "fatal error, unable to load plugins"
+msgstr "végzetes hiba: a bővítmények betöltése sikertelen"
+
+#: src/sudo.c:216
+msgid "unable to initialize policy plugin"
+msgstr "a házirendbővítmény előkészítése sikertelen"
+
+#: src/sudo.c:260
+msgid "plugin did not return a command to execute"
+msgstr "a bővítmény nem tért vissza végrehajtandó paranccsal"
+
+#: src/sudo.c:276
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "hiba a(z) %s I/O bővítmény előkészítésekor"
+
+#: src/sudo.c:299
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "váratatlan 0x%x sudo mód"
+
+#: src/sudo.c:461
+msgid "unable to get group vector"
+msgstr "a csoportvektor lekérése sikertelen"
+
+#: src/sudo.c:523
+#, c-format
+msgid "unknown uid %u: who are you?"
+msgstr "ismeretlen %u uid: kicsoda Ön?"
+
+#: src/sudo.c:579
+msgid "unable to determine tty"
+msgstr "a tty meghatározása sikertelen"
+
+#: src/sudo.c:867
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s a(z) %d uid tulajdona kell legyen, és a setuid bitnek beállítva kell lennie"
+
+#: src/sudo.c:870
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "a tényleges uid nem %d, a(z) %s a „nosuid” kapcsolóval beállított fájlrendszeren vagy rendszergazda jogosultságok nélküli NFS fájlrendszeren van?"
+
+#: src/sudo.c:876
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "a tényleges uid nem %d, a sudo telepítette a setuid gyökeret?"
+
+#: src/sudo.c:929
+msgid "unable to set supplementary group IDs"
+msgstr "a kiegészítő csoportazonosítók beállítása sikertelen"
+
+#: src/sudo.c:936
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "a tényleges gid beállítása a runas gid %u értékre sikertelen"
+
+#: src/sudo.c:942
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "a gid beállítása a runas gid %u értékre sikertelen"
+
+#: src/sudo.c:999
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "váratlan gyermekmegszakítási feltétel: %d"
+
+#: src/sudo.c:1145
+#, c-format
+msgid "policy plugin %s is missing the `check_policy' method"
+msgstr "a(z) %s házirendbővítményből hiányzik a „check_policy” metódus"
+
+#: src/sudo.c:1163
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "a(z) %s házirendbővítmény nem támogatja a jogosultságok felsorolását"
+
+#: src/sudo.c:1180
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "a(z) %s házirendbővítmény nem támogatja a -v kapcsolót"
+
+#: src/sudo.c:1195
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "a(z) %s házirendbővítmény nem támogatja a -k/-K kapcsolókat"
+
+#: src/sudo_edit.c:178 src/sudo_edit.c:267
+msgid "unable to restore current working directory"
+msgstr "az aktuális munkakönyvtár visszaállítása sikertelen"
+
+#: src/sudo_edit.c:574 src/sudo_edit.c:686
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: nem szabályos fájl"
+
+#: src/sudo_edit.c:581
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: szimbolikus linkek szerkesztése nem engedélyezett"
+
+#: src/sudo_edit.c:584
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: fájlok szerkesztése egy írható könyvtárban nem engedélyezett"
+
+#: src/sudo_edit.c:617 src/sudo_edit.c:724
+#, c-format
+msgid "%s: short write"
+msgstr "%s: rövid írás"
+
+#: src/sudo_edit.c:687
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s módosítatlanul hagyva"
+
+#: src/sudo_edit.c:700 src/sudo_edit.c:885
+#, c-format
+msgid "%s unchanged"
+msgstr "%s változatlan"
+
+#: src/sudo_edit.c:713 src/sudo_edit.c:735
+#, c-format
+msgid "unable to write to %s"
+msgstr "az írás sikertelen ebbe: %s"
+
+#: src/sudo_edit.c:714 src/sudo_edit.c:733 src/sudo_edit.c:736
+#: src/sudo_edit.c:910 src/sudo_edit.c:914
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "a szerkesztési munkamenet tartalma ebben maradt: %s"
+
+#: src/sudo_edit.c:732
+msgid "unable to read temporary file"
+msgstr "az átmeneti fájl olvasása sikertelen"
+
+#: src/sudo_edit.c:815
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: belső hiba: útvonalak páratlan száma"
+
+#: src/sudo_edit.c:817
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: átmeneti fájlok létrehozása sikertelen"
+
+#: src/sudo_edit.c:819 src/sudo_edit.c:917
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: ismeretlen hiba: %d"
+
+#: src/sudo_edit.c:909
+msgid "unable to copy temporary files back to their original location"
+msgstr "az átmeneti fájlok visszamásolása az eredeti helyükre sikertelen"
+
+#: src/sudo_edit.c:913
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "néhány átmeneti fájl visszamásolása az eredeti helyükre sikertelen"
+
+#: src/sudo_edit.c:958
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "az uid megváltoztatása rendszergazdára (%u) sikertelen"
+
+#: src/sudo_edit.c:975
+msgid "plugin error: missing file list for sudoedit"
+msgstr "bővítményhiba: hiányzó fájllista a sudoedit programnál"
+
+#: src/sudo_edit.c:1016 src/sudo_edit.c:1029
+msgid "unable to read the clock"
+msgstr "az óra olvasása sikertelen"
+
+#: src/tgetpass.c:107
+msgid "no tty present and no askpass program specified"
+msgstr "nincs tty jelen, és nincs askpass program megadva"
+
+#: src/tgetpass.c:116
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "nincs askpass program megadva, SUDO_ASKPASS beállításának kísérlete"
+
+#: src/tgetpass.c:261
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "a gid beállítása %u értékre sikertelen"
+
+#: src/tgetpass.c:265
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "az uid beállítása %u értékre sikertelen"
+
+#: src/tgetpass.c:270
+#, c-format
+msgid "unable to run %s"
+msgstr "%s futtatása sikertelen"
+
+#: src/utmp.c:268
+msgid "unable to save stdin"
+msgstr "a szabványos bemenet mentése sikertelen"
+
+#: src/utmp.c:270
+msgid "unable to dup2 stdin"
+msgstr "a szabványos bemenet dup2 futtatása sikertelen"
+
+#: src/utmp.c:273
+msgid "unable to restore stdin"
+msgstr "a szabványos bemenet visszaállítása sikertelen"
diff --git a/po/id.mo b/po/id.mo
new file mode 100644
index 0000000..24bb65f
--- /dev/null
+++ b/po/id.mo
Binary files differ
diff --git a/po/id.po b/po/id.po
new file mode 100644
index 0000000..87290e9
--- /dev/null
+++ b/po/id.po
@@ -0,0 +1,1201 @@
+# Portable object template file for sudo
+# This file is put in the public domain.
+# Todd C. Miller <Todd.Miller@sudo.ws>, 2011-2018
+# Andika Triwidada <andika@gmail.com>, 2023
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.14b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-06-07 13:27-0600\n"
+"PO-Revision-Date: 2023-10-20 12:49+0700\n"
+"Last-Translator: Andika Triwidada <andika@gmail.com>\n"
+"Language-Team: Indonesian <translation-team-id@lists.sourceforge.net>\n"
+"Language: id\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 3.4\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "tidak bisa membuka userdb"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "tidak bisa beralih ke registry \"%s\" untuk %s"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "tidak bisa memulihkan registry"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:78 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:171 src/exec_monitor.c:418
+#: src/exec_monitor.c:424 src/exec_monitor.c:432 src/exec_monitor.c:440
+#: src/exec_monitor.c:447 src/exec_monitor.c:454 src/exec_monitor.c:461
+#: src/exec_monitor.c:468 src/exec_monitor.c:475 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:744 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1096
+#: src/exec_ptrace.c:1271 src/exec_ptrace.c:1624 src/exec_ptrace.c:1651
+#: src/exec_ptrace.c:1841 src/exec_pty.c:581 src/exec_pty.c:765
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:193 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:240
+#: src/sesh.c:246 src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:644
+#: src/sudo.c:709 src/sudo.c:719 src/sudo.c:746 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:787 src/sudo.c:805 src/sudo.c:846 src/sudo.c:855 src/sudo.c:865
+#: src/sudo.c:898 src/sudo.c:1127 src/sudo.c:1148 src/sudo.c:1441
+#: src/sudo.c:1610 src/sudo.c:1837 src/sudo.c:2171 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:430 src/sudo_edit.c:439
+#: src/sudo_edit.c:540 src/sudo_edit.c:547 src/sudo_edit.c:692
+#: src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:79 src/exec_intercept.c:111 src/exec_intercept.c:350
+#: src/exec_intercept.c:525 src/exec_intercept.c:589 src/exec_intercept.c:713
+#: src/exec_intercept.c:837 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:418 src/exec_monitor.c:424
+#: src/exec_monitor.c:432 src/exec_monitor.c:440 src/exec_monitor.c:447
+#: src/exec_monitor.c:454 src/exec_monitor.c:461 src/exec_monitor.c:468
+#: src/exec_monitor.c:475 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1651 src/exec_ptrace.c:1842 src/exec_pty.c:581
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:228 src/sudo.c:644 src/sudo.c:898 src/sudo.c:1127 src/sudo.c:1148
+#: src/sudo.c:1441 src/sudo.c:1610 src/sudo.c:1837 src/sudo.c:2171
+#: src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:430
+#: src/sudo_edit.c:439 src/sudo_edit.c:540 src/sudo_edit.c:547
+#: src/sudo_edit.c:692 src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "tidak bisa mengalokasikan memori"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "tidak bisa men-stat %.*s"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s ada tapi bukan suatu direktori (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:664
+#: lib/util/sudo_conf.c:683 lib/util/sudo_conf.c:710 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:495 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "tidak bisa membuka %s"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "tidak bisa mkdir %.*s"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "tidak bisa membuka %.*s"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "ekspresi reguler terlalu besar"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Sinyal yang tidak dikenal"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "nilai tidak valid"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "nilai terlalu besar"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "nilai terlalu kecil"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "nilai Path \"%s\" tidak valid dalam %s, baris %u"
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "nilai tidak valid untuk %s \"%s\" dalam %s, baris %u"
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "sumber grup \"%s\" dalam %s tidak didukung, baris %u"
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "grup maks \"%s\" dalam %s tidak valid, baris %u"
+
+#: lib/util/sudo_conf.c:686
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s bukan suatu berkas reguler"
+
+#: lib/util/sudo_conf.c:689 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s hanya dimiliki oleh uid %u, mestinya %u"
+
+#: lib/util/sudo_conf.c:693
+#, c-format
+msgid "%s is world writable"
+msgstr "%s dapat ditulisi oleh siapa pun"
+
+#: lib/util/sudo_conf.c:696
+#, c-format
+msgid "%s is group writable"
+msgstr "%s dapat ditulisi oleh grup"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "gagal menentukan pengurungan AppArmor"
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "tidak bisa mengubah profil AppArmor ke %s"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: penggal %s ke nol byte? (y/t) [t] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "tidak menimpa %s"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "tidak bisa membaca dari %s"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "tidak bisa menulis ke %s"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "tidak bisa men-stat %s"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: bukan suatu berkas reguler"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: mode berkas buruk: 0%o"
+
+#: src/edit_open.c:333
+msgid "unable to restore current working directory"
+msgstr "tidak bisa memulihkan direktori kerja kini"
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "tidak bisa menata privilese"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "tidak bisa menata pembatasan privilese"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "kelas log masuk yang tidak dikenal %s"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "tidak bisa menata konteks pengguna"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "tidak bisa menata prioritas proses"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "tidak bisa mengubah root ke %s"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "tidak bisa mengubah ke uid runas (%u, %u)"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "tidak bisa mengubah direktori ke %s"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "memulai dari %s"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:552 src/exec_monitor.c:554
+#: src/exec_pty.c:1122 src/exec_pty.c:1124 src/signal.c:144 src/signal.c:151
+#: src/signal.c:165 src/suspend_parent.c:143
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "tidak bisa menata penangan bagi sinyal %d"
+
+#: src/exec.c:424
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "mode intersepsi tidak didukung dengan RBAC SELinux pada sistem ini"
+
+#: src/exec.c:429
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "tidak bisa mencatat log sub perintah dengan RBAC SELinux pada sistem ini"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "tidak bisa menghapus PRIV_PROC_EXEC dari PRIV_LIMIT"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:163 src/exec_iolog.c:173
+#: src/exec_iolog.c:218 src/exec_iolog.c:225 src/exec_iolog.c:252
+#: src/exec_monitor.c:426 src/exec_monitor.c:434 src/exec_monitor.c:442
+#: src/exec_monitor.c:449 src/exec_monitor.c:456 src/exec_monitor.c:463
+#: src/exec_monitor.c:470 src/exec_monitor.c:477 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:457 src/exec_pty.c:432
+#: src/exec_pty.c:537 src/exec_pty.c:587 src/exec_pty.c:965 src/exec_pty.c:974
+#: src/exec_pty.c:981 src/exec_pty.c:988 src/exec_pty.c:995 src/exec_pty.c:1002
+#: src/exec_pty.c:1009 src/exec_pty.c:1016 src/exec_pty.c:1023
+#: src/exec_pty.c:1030 src/exec_pty.c:1037 src/exec_pty.c:1044
+msgid "unable to add event to queue"
+msgstr "tidak bisa menambah kejadian ke antrian"
+
+#: src/exec_intercept.c:323 src/sudo.c:1033
+msgid "command not set by the security policy"
+msgstr "perintah tidak ditata oleh kebijakan keamanan"
+
+#: src/exec_intercept.c:401 src/exec_intercept.c:441 src/sudo.c:1253
+#: src/sudo.c:1298 src/sudo.c:1342
+msgid "command rejected by policy"
+msgstr "perintah ditolak oleh kebijakan"
+
+#: src/exec_intercept.c:512 src/sudo.c:1940
+msgid "approval plugin error"
+msgstr "galat pengaya persetujuan"
+
+#: src/exec_intercept.c:537 src/sudo.c:1258 src/sudo.c:1303 src/sudo.c:1347
+#: src/sudo.c:1421
+msgid "policy plugin error"
+msgstr "galat pengaya kebijakan"
+
+#: src/exec_intercept.c:566
+msgid "invalid PolicyCheckRequest"
+msgstr "PolicyCheckRequest tidak valid"
+
+#: src/exec_intercept.c:709
+#, c-format
+msgid "client request too large: %zu"
+msgstr "permintaan klien terlalu besar: %zu"
+
+#: src/exec_intercept.c:751
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "tidak bisa membongkar paket %s ukuran %zu"
+
+#: src/exec_intercept.c:799
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "nilai type_case %d yang tidak diharapkan dalam %s dari %s"
+
+#: src/exec_intercept.c:825
+#, c-format
+msgid "server message too large: %zu"
+msgstr "pesan server terlalu besar: %zu"
+
+#: src/exec_iolog.c:321 src/exec_iolog.c:361 src/exec_iolog.c:401
+#: src/exec_iolog.c:452 src/exec_iolog.c:503
+msgid "I/O plugin error"
+msgstr "galat pengaya I/O"
+
+#: src/exec_iolog.c:325 src/exec_iolog.c:365 src/exec_iolog.c:405
+#: src/exec_iolog.c:456 src/exec_iolog.c:507
+msgid "command rejected by I/O plugin"
+msgstr "perintah ditolak oleh pengaya I/O"
+
+#: src/exec_iolog.c:555
+msgid "error logging suspend"
+msgstr "galat saat mencatat log suspensi"
+
+#: src/exec_iolog.c:590
+msgid "error changing window size"
+msgstr "galat saat mengubah ukuran jendela"
+
+#: src/exec_monitor.c:328
+msgid "error reading from socketpair"
+msgstr "galat saat membaca dari socketpair"
+
+#: src/exec_monitor.c:340
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "tipe jawaban yang tidak diharapkan pada backchannel: %d"
+
+#: src/exec_monitor.c:566
+msgid "unable to set controlling tty"
+msgstr "tidak bisa menata tty pengendali"
+
+#: src/exec_monitor.c:574 src/exec_nopty.c:504 src/exec_nopty.c:514
+#: src/exec_nopty.c:524 src/exec_nopty.c:560 src/exec_pty.c:1195
+#: src/exec_pty.c:1222 src/exec_pty.c:1242 src/exec_pty.c:1262
+#: src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr "tidak bisa menata pipa"
+
+#: src/exec_monitor.c:584
+msgid "unable to receive message from parent"
+msgstr "tidak bisa menerima pesan dari induk"
+
+#: src/exec_monitor.c:600 src/exec_nopty.c:603 src/exec_pty.c:1303
+#: src/sudo_edit.c:361 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr "tidak bisa mem-fork"
+
+#: src/exec_monitor.c:604 src/exec_monitor.c:700 src/exec_nopty.c:708
+msgid "unable to restore tty label"
+msgstr "tidak bisa memulihkan label tty"
+
+#: src/exec_monitor.c:615 src/sesh.c:217 src/sudo.c:1204
+#, c-format
+msgid "unable to execute %s"
+msgstr "tidak bisa mengeksekusi %s"
+
+#: src/exec_nopty.c:554 src/exec_pty.c:1131
+msgid "policy plugin failed session initialization"
+msgstr "pengaya kebijakan gagal menginisialisasi sesi"
+
+#: src/exec_nopty.c:569 src/exec_pty.c:1100 src/exec_pty.c:1109
+msgid "unable to create sockets"
+msgstr "tidak bisa membuat soket"
+
+#: src/exec_nopty.c:696 src/exec_pty.c:1406
+msgid "error in event loop"
+msgstr "galat dalam loop kejadian"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372 src/net_ifs.c:433
+#: src/net_ifs.c:620 src/net_ifs.c:852 src/sudo.c:488 src/sudo_edit.c:398
+#: src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "galat internal, %s overflow"
+
+#: src/exec_ptrace.c:1080 src/exec_ptrace.c:1105 src/exec_ptrace.c:1925
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "tidak bisa menata register untuk proses %d"
+
+#: src/exec_ptrace.c:1100 src/exec_ptrace.c:1275 src/exec_ptrace.c:1628
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "proses %d keluar secara tak terduga"
+
+#: src/exec_ptrace.c:1209
+msgid "unable to set seccomp filter"
+msgstr "tidak bisa menata filter seccomp"
+
+#: src/exec_ptrace.c:1406
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "argumen interpreter, diharapkan \"%s\", diperoleh \"%s\""
+
+#: src/exec_ptrace.c:1505
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "nama path tidak cocok, diharapkan \"%s\", diperoleh \"%s\""
+
+#: src/exec_ptrace.c:1514 src/exec_ptrace.c:1521 src/exec_ptrace.c:1545
+#: src/exec_ptrace.c:1553 src/exec_ptrace.c:1559 src/exec_ptrace.c:1565
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "%s[%d] tidak cocok, diharapkan \"%s\", diperoleh \"%s\""
+
+#: src/exec_ptrace.c:1632
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "proses %d status tidak diharapkan 0x%x"
+
+#: src/exec_ptrace.c:1723
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "tidak bisa mendapatkan pesan kejadian untuk proses %d"
+
+#: src/exec_ptrace.c:1730
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "tidak bisa mendapat register-register untuk proses %d"
+
+#: src/exec_pty.c:84
+msgid "unable to allocate pty"
+msgstr "tidak bisa mengalokasikan pty"
+
+#: src/exec_pty.c:131 src/exec_pty.c:284 src/tgetpass.c:251
+msgid "unable to restore terminal settings"
+msgstr "tidak bisa memulihkan pengaturan terminal"
+
+#: src/exec_pty.c:243
+msgid "unable to set handler for SIGCONT"
+msgstr "tidak bisa menata penangan bagi SIGCONT"
+
+#: src/exec_pty.c:293
+#, c-format
+msgid "unable to set handler for SIG%s"
+msgstr "tidak bisa menata penangan bagi SIG%s"
+
+#: src/exec_pty.c:317
+#, c-format
+msgid "unable to restore handler for SIG%s"
+msgstr "tidak bisa memulihkan penangan bagi SIG%s"
+
+#: src/exec_pty.c:345
+msgid "unable to restore handler for SIGCONT"
+msgstr "tidak bisa memulihkan penangan bagi SIGCONT"
+
+#: src/exec_pty.c:1353
+msgid "unable to send message to monitor process"
+msgstr "tidak bisa mengirim pesan ke proses pantau"
+
+#: src/load_plugins.c:75 src/load_plugins.c:222 src/load_plugins.c:232
+#: src/load_plugins.c:242 src/load_plugins.c:289
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "galat dalam %s, bari %d ketika memuat pengaya \"%s\""
+
+#: src/load_plugins.c:186 src/load_plugins.c:257
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "mengabaikan pengaya duplikan \"%s\" dalam %s, baris %d"
+
+#: src/load_plugins.c:224
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "tidak bisa memuat %s: %s"
+
+#: src/load_plugins.c:234
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "tidak bisa menemukan simbol \"%s\" dalam %s"
+
+#: src/load_plugins.c:244
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "versi mayor pengaya %d tidak kompatibel (diharapkan %d) ditemukan di %s"
+
+#: src/load_plugins.c:262
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "mengabaikan pengaya kebijakan \"%s\" dalam %s, baris %d"
+
+#: src/load_plugins.c:265
+msgid "only a single policy plugin may be specified"
+msgstr "hanya satu pengaya kebijakan yang boleh dinyatakan"
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "tipe pengaya tak dikenal %d ditemukan di %s"
+
+#: src/load_plugins.c:474
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "pengaya kebijakan %s tidak menyertakan suatu metode check_policy"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "nama variabel lingkungan tidak valid: %s"
+
+#: src/parse_args.c:319
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "argumen ke -C mesti berupa suatu angka lebih dari atau sama dengan 3"
+
+#: src/parse_args.c:556
+msgid "you may not specify both the -i and -s options"
+msgstr "Anda tidak boleh menyatakan sekaligus opsi -i dan -s"
+
+#: src/parse_args.c:561
+msgid "you may not specify both the -i and -E options"
+msgstr "Anda tidak boleh menyatakan sekaligus opsi -i dan -E"
+
+#: src/parse_args.c:571
+msgid "the -E option is not valid in edit mode"
+msgstr "opsi -E tidak valid dalam mode sunting"
+
+#: src/parse_args.c:574
+msgid "you may not specify environment variables in edit mode"
+msgstr "Anda tidak boleh menyatakan variabel lingkungan dalam mode sunting"
+
+#: src/parse_args.c:584
+msgid "the -U option may only be used with the -l option"
+msgstr "opsi -U hanya boleh dipakai dengan opsi -l"
+
+#: src/parse_args.c:588
+msgid "the -A and -S options may not be used together"
+msgstr "opsi -A dan -S tidak boleh dipakai bersama"
+
+#: src/parse_args.c:686
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit tidak didukung pada platform ini"
+
+#: src/parse_args.c:744
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Hanya satu dari opsi -e, -h, -i, -K, -l, -s, -v, atau -V yang boleh dinyatakan"
+
+#: src/parse_args.c:757
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "Hanya satu dari opsi -K, -k, atau -N yang boleh dinyatakan"
+
+#: src/parse_args.c:778
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - menyunting berkas sebagai pengguna lain\n"
+"\n"
+
+#: src/parse_args.c:780
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - menjalankan suatu perintah sebagai pengguna lain\n"
+"\n"
+
+#: src/parse_args.c:785
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Opsi:\n"
+
+#: src/parse_args.c:787
+msgid "use a helper program for password prompting"
+msgstr "gunakan suatu program bantu untuk meminta kata sandi"
+
+#: src/parse_args.c:790
+msgid "use specified BSD authentication type"
+msgstr "gunakan tipe otentikasi BSD yang dinyatakan"
+
+#: src/parse_args.c:794
+msgid "run command in the background"
+msgstr "jalankan perintah di latar belakang"
+
+#: src/parse_args.c:797
+msgid "ring bell when prompting"
+msgstr "bunyikan bel saat meminta masukan"
+
+#: src/parse_args.c:799
+msgid "close all file descriptors >= num"
+msgstr "tutup semua deskriptor berkas >= num"
+
+#: src/parse_args.c:802
+msgid "run command with the specified BSD login class"
+msgstr "jalankan perintah dengan kelas log masuk BSD yang dinyatakan"
+
+#: src/parse_args.c:805
+msgid "change the working directory before running command"
+msgstr "ubah direktori kerja sebelum menjalankan perintah"
+
+#: src/parse_args.c:808
+msgid "preserve user environment when running command"
+msgstr "pertahankan lingkungan pengguna ketika menjalankan perintah"
+
+#: src/parse_args.c:810
+msgid "preserve specific environment variables"
+msgstr "pertahankan variabel lingkungan spesifik"
+
+#: src/parse_args.c:812
+msgid "edit files instead of running a command"
+msgstr "sunting berkas alih-alih menjalankan suatu perintah"
+
+#: src/parse_args.c:815
+msgid "run command as the specified group name or ID"
+msgstr "jalankan perintah sebagai ID atau nama grup yang dinyatakan"
+
+#: src/parse_args.c:818
+msgid "set HOME variable to target user's home dir"
+msgstr "tata variabel HOME ke dir home pengguna target"
+
+#: src/parse_args.c:821
+msgid "display help message and exit"
+msgstr "tampilkan pesan bantuan dan keluar"
+
+#: src/parse_args.c:823
+msgid "run command on host (if supported by plugin)"
+msgstr "jalankan perintah pada host (bila didukung oleh pengaya)"
+
+#: src/parse_args.c:826
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "jalankan shell log masuk sebagai pengguna target; suatu perintah juga dapat dinyatakan"
+
+#: src/parse_args.c:828
+msgid "remove timestamp file completely"
+msgstr "hapus berkas stempel waktu sepenuhnya"
+
+#: src/parse_args.c:831
+msgid "invalidate timestamp file"
+msgstr "jadikan tak valid berkas stempel waktu"
+
+#: src/parse_args.c:834
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "cantumkan daftar privilese pengguna atau periksa suatu perintah tertentu; gunakan dua kali untuk format yang lebih panjang"
+
+#: src/parse_args.c:837
+msgid "non-interactive mode, no prompts are used"
+msgstr "mode non interaktif, tidak ada pertanyaan yang dipakai"
+
+#: src/parse_args.c:840
+msgid "preserve group vector instead of setting to target's"
+msgstr "pertahankan vektor grup alih-alih menata ke milik target"
+
+#: src/parse_args.c:843
+msgid "use the specified password prompt"
+msgstr "gunakan sapaan permintaan kata sandi yang dinyatakan"
+
+#: src/parse_args.c:845
+msgid "change the root directory before running command"
+msgstr "ubah direktori root sebelum menjalankan perintah"
+
+#: src/parse_args.c:848
+msgid "create SELinux security context with specified role"
+msgstr "buat konteks keamanan SELinux dengan peran yang dinyatakan"
+
+#: src/parse_args.c:851
+msgid "read password from standard input"
+msgstr "baca kata sandi dari masukan standar"
+
+#: src/parse_args.c:854
+msgid "run shell as the target user; a command may also be specified"
+msgstr "jalankan shell sebagai pengguna target; suatu perintah juga dapat dinyatakan"
+
+#: src/parse_args.c:858
+msgid "create SELinux security context with specified type"
+msgstr "buat konteks keamanan SELinux dengan tipe yang dinyatakan"
+
+#: src/parse_args.c:861
+msgid "terminate command after the specified time limit"
+msgstr "akhiri perintah setelah batas waktu yang dinyatakan"
+
+#: src/parse_args.c:864
+msgid "in list mode, display privileges for user"
+msgstr "dalam mode daftar, tampilkan privilese bagi pengguna"
+
+#: src/parse_args.c:867
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "jalankan perintah (atau sunting berkas) sebagai ID atau nama pengguna yang dinyatakan"
+
+#: src/parse_args.c:869
+msgid "display version information and exit"
+msgstr "tampilkan informasi versi dan keluar"
+
+#: src/parse_args.c:872
+msgid "update user's timestamp without running a command"
+msgstr "perbarui stempel waktu pengguna tanpa menjalankan suatu perintah"
+
+#: src/parse_args.c:875
+msgid "stop processing command line arguments"
+msgstr "berhenti memroses argumen baris perintah"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "tidak bisa membuka sistem audit"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "tidak bisa mengirim pesan audit"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "tidak bisa mem-fgetfilecon %s"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s mengubah label"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "tidak bisa memulihkan konteks bagi %s"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "tidak bisa membuka %s, tidak melabeli ulang tty"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s bukan suatu perangkat karakter, tidak melabeli ulang tty"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "tidak bisa mendapatkan konteks tty saat ini, tidak melabeli ulang tty"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "kelas keamanan tidak dikenal \"chr_file\", tidak melabeli ulang tty"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "tidak bisa mendapatkan konteks tty baru, tidak melabeli ulang tty"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "tidak bisa menata konteks tty baru"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "Anda mesti menyatakan suatu peran bagi tipe %s"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "tidak bisa mendapat tipe baku bagi peran %s"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "gagal mendapatkan konteks baru"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "gagal menata peran baru %s"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "gagal menata tipe baru %s"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s bukan suatu konteks yang valid"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "gagal mendapatkan konteks lama"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "tidak bisa menentukan mode penegakan."
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "tidak bisa menata konteks exec ke %s"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "tidak bisa menata konteks penciptaan kunci ke %s"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "Hanya satu dari opsi -c atau -i yang boleh dinyatakan"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "nomor deskriptor berkas tidak valid: %s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "Opsi -%c tidak boleh dipakai dalam mode sunting."
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "Opsi -%c hanya boleh dipakai dalam mode sunting."
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: menyunting taut simbolis tidak diizinkan"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: menyunting berkas-berkas dalam direktori yang dapat ditulisi tidak diizinkan"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "konten sesi sunting ditinggalkan dalam %s"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "tidak bisa mendapat daftar grup"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "tidak bisa menyimpan penangan bagi sinyal %d"
+
+#: src/signal.c:101 src/suspend_parent.c:149
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "tidak bisa memulihkan penangan bagi sinyal %d"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "batas kendali sumber daya telah dicapai"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "pengguna \"%s' bukan anggota dari proyek \"%s\""
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "tugas yang memanggil adalah final"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "tidak bisa bergabung ke proyek \"%s\""
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "tidak ada pool sumber daya yang menerima pengikatan baku yang ada untuk proyek \"%s\""
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "pool sumber daya yang dinyatakan tidak ada untuk proyek \"%s\""
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "tidak bisa mengikat pool sumber daya baku bagi proyek \"%s\""
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "setproject gagal untuk proyek \"%s\""
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "peringatan, penugasan kendali sumber daya gagal untuk proyek \"%s\""
+
+#: src/sudo.c:214
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo versi %s\n"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Opsi konfigurasi: %s\n"
+
+#: src/sudo.c:224
+msgid "fatal error, unable to load plugins"
+msgstr "galat fatal, tidak bisa memuat pengaya"
+
+#: src/sudo.c:270
+msgid "plugin did not return a command to execute"
+msgstr "pengaya tidak mengembalikan suatu perintah yang akan dieksekusi"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "mode sudo 0x%x yang tidak diharapkan"
+
+#: src/sudo.c:559
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "Anda tidak ada dalam basis data %s"
+
+#: src/sudo.c:616
+msgid "unable to determine tty"
+msgstr "tidak bisa menentukan tty"
+
+#: src/sudo.c:932
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "Flag \"tidak ada privilese baru\" ditata, yang mencegah sudo berjalan sebagai root."
+
+#: src/sudo.c:934
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "Bila sudo berjalan dalam suatu kontainer, Anda mungkin perlu menyetel konfigurasi kontainer untuk menonaktifkan flag."
+
+#: src/sudo.c:968
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s mesti dimiliki oleh uid %d dan bit setuid-nya ditata"
+
+#: src/sudo.c:971
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "uid efektif bukan %d, apakah %s ada pada suatu sistem berkas dengan opsi 'nosuid' ditata atau suatu sistem berkas NFS tanpa privilese root?"
+
+#: src/sudo.c:977
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "uid efektif bukan %d, apakah sudo dipasang dengan setuid root?"
+
+#: src/sudo.c:993 src/tgetpass.c:332
+msgid "unable to set supplementary group IDs"
+msgstr "tidak bisa menata ID grup suplementer"
+
+#: src/sudo.c:1000
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "tidak bisa menata gid efektif untuk runas gid %u"
+
+#: src/sudo.c:1006
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "tidak bisa menata gid to runas gid %u"
+
+#: src/sudo.c:1037
+msgid "argv not set by the security policy"
+msgstr "argv tidak ditata oleh kebijakan keamanan"
+
+#: src/sudo.c:1041
+msgid "envp not set by the security policy"
+msgstr "envp tidak ditata oleh kebijakan keamanan"
+
+#: src/sudo.c:1063
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "kondisi terminasi anak yang tidak diharapkan: %d"
+
+#: src/sudo.c:1176
+msgid "unable to initialize policy plugin"
+msgstr "tidak bisa menginisialisasi pengaya kebijakan"
+
+#: src/sudo.c:1238
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "pengaya kebijakan %s kurang metode \"check_policy\""
+
+#: src/sudo.c:1284
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "pengaya kebijakan %s tidak mendukung mencantumkan daftar privilese"
+
+#: src/sudo.c:1328
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "pengaya kebijakan %s tidak mendukung opsi -v"
+
+#: src/sudo.c:1366
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "pengaya kebijakan %s tidak mendukung opsi -k/-K"
+
+#: src/sudo.c:1495
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "galat saat menginisialisasi pengaya I/O %s"
+
+#: src/sudo.c:1498
+msgid "error initializing I/O plugin"
+msgstr "galat saat menginisialisasi pengaya I/O"
+
+#: src/sudo.c:1647
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "galat saat menginisialisasi pengaya audit %s"
+
+#: src/sudo.c:1726
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: tidak bisa mencatat galat kejadian%s%s"
+
+#: src/sudo.c:1762
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: tidak bisa mencatat setujui kejadian%s%s"
+
+#: src/sudo.c:1767 src/sudo.c:1805
+msgid "audit plugin error"
+msgstr "galat pengaya audit"
+
+#: src/sudo.c:1800
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: tidak bisa mencatat tolak kejadian%s%s"
+
+#: src/sudo.c:1860
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "galat saat menginisialisasi pengaya persetujuan %s"
+
+#: src/sudo.c:1930
+msgid "command rejected by approver"
+msgstr "perintah ditolak oleh pemberi persetujuan"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "tidak ditemukan direktori temporer yang dapat ditulisi"
+
+#: src/sudo_edit.c:292
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s dibiarkan tak berubah"
+
+#: src/sudo_edit.c:305 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s tidak diubah"
+
+#: src/sudo_edit.c:482
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: galat internal: cacah path aneh"
+
+#: src/sudo_edit.c:484
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: tidak bisa membuat berkas temporer"
+
+#: src/sudo_edit.c:486 src/sudo_edit.c:606
+msgid "sesh: killed by a signal"
+msgstr "sesh: di-kill oleh suatu sinyal"
+
+#: src/sudo_edit.c:488 src/sudo_edit.c:609
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: galat tak dikenal %d"
+
+#: src/sudo_edit.c:599
+msgid "unable to copy temporary files back to their original location"
+msgstr "tidak bisa menyalin berkas temporer kembali ke lokasi asli mereka"
+
+#: src/sudo_edit.c:603
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "tidak bisa menyalin beberapa dari berkas temporer kembali ke lokasi asli mereka"
+
+#: src/sudo_edit.c:650
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "tidak bisa mengubah uid ke root (%u)"
+
+#: src/sudo_edit.c:664
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "galat pengaya: daftar berkas tidak valid untuk sudoedit"
+
+#: src/sudo_edit.c:685
+msgid "plugin error: missing file list for sudoedit"
+msgstr "galat pengaya: daftar berkas hilang untuk sudoedit"
+
+#: src/sudo_edit.c:728 src/sudo_edit.c:743
+msgid "unable to read the clock"
+msgstr "tidak bisa membaca jam"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "port intersepsi tidak ditata"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "kehabisan waktu saat membaca kata sandi"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "tidak ada kata sandi yang diberikan"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "tidak bisa membaca kata sandi"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "suatu terminal diperlukan untuk membaca kata sandi; gunakan opsi -S untuk membaca dari masukan standar atau konfigurasikan suatu pembantu askpass"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "tidak ada program askpass yang dinyatakan, cobalah menata SUDO_ASKPASS"
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "tidak bisa menata gid menjadi %u"
+
+#: src/tgetpass.c:337
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "tidak bisa menata uid menjadi %u"
+
+#: src/tgetpass.c:342
+#, c-format
+msgid "unable to run %s"
+msgstr "tidak bisa menjalankan %s"
+
+#: src/utmp.c:283
+msgid "unable to save stdin"
+msgstr "tidak bisa menyimpan stdin"
+
+#: src/utmp.c:285
+msgid "unable to dup2 stdin"
+msgstr "tidak bisa men-dup2 stdin"
+
+#: src/utmp.c:288
+msgid "unable to restore stdin"
+msgstr "tidak bisa memulihkan stdin"
diff --git a/po/it.mo b/po/it.mo
new file mode 100644
index 0000000..38964ba
--- /dev/null
+++ b/po/it.mo
Binary files differ
diff --git a/po/it.po b/po/it.po
new file mode 100644
index 0000000..190cb3b
--- /dev/null
+++ b/po/it.po
@@ -0,0 +1,1038 @@
+# Italian translations for sudo package
+# This file is put in the public domain.
+# Milo Casagrande <milo@milo.name>, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo-1.9.6b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2021-01-09 12:59-0700\n"
+"PO-Revision-Date: 2021-03-15 17:58+0100\n"
+"Last-Translator: Milo Casagrande <milo@milo.name>\n"
+"Language-Team: Italian <tp@lists.linux.it>\n"
+"Language: it\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n"
+"X-Generator: Poedit 2.4.2\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "impossibile aprire lo userdb"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "impossibile passare al registro \"%s\" per %s"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "impossibile ripristinare il registro"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:54 lib/util/json.c:183 lib/util/sudo_conf.c:198
+#: lib/util/sudo_conf.c:284 lib/util/sudo_conf.c:361 lib/util/sudo_conf.c:647
+#: src/conversation.c:80 src/exec_common.c:106 src/exec_common.c:122
+#: src/exec_common.c:131 src/exec_monitor.c:206 src/exec_monitor.c:455
+#: src/exec_monitor.c:461 src/exec_monitor.c:469 src/exec_monitor.c:477
+#: src/exec_monitor.c:484 src/exec_monitor.c:491 src/exec_monitor.c:498
+#: src/exec_monitor.c:505 src/exec_monitor.c:512 src/exec_monitor.c:519
+#: src/exec_monitor.c:526 src/exec_nopty.c:212 src/exec_nopty.c:221
+#: src/exec_nopty.c:228 src/exec_nopty.c:235 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:299 src/exec_nopty.c:473
+#: src/exec_pty.c:834 src/exec_pty.c:843 src/exec_pty.c:900
+#: src/exec_pty.c:1053 src/exec_pty.c:1225 src/exec_pty.c:1234
+#: src/exec_pty.c:1241 src/exec_pty.c:1248 src/exec_pty.c:1255
+#: src/exec_pty.c:1262 src/exec_pty.c:1269 src/exec_pty.c:1276
+#: src/exec_pty.c:1283 src/exec_pty.c:1290 src/exec_pty.c:1297
+#: src/exec_pty.c:1305 src/exec_pty.c:1747 src/load_plugins.c:52
+#: src/load_plugins.c:65 src/load_plugins.c:163 src/load_plugins.c:188
+#: src/load_plugins.c:223 src/load_plugins.c:455 src/load_plugins.c:461
+#: src/parse_args.c:181 src/parse_args.c:202 src/parse_args.c:275
+#: src/parse_args.c:616 src/parse_args.c:638 src/parse_args.c:663
+#: src/preserve_fds.c:46 src/preserve_fds.c:131 src/selinux.c:90
+#: src/selinux.c:360 src/selinux.c:489 src/selinux.c:498 src/sesh.c:110
+#: src/sesh.c:143 src/sesh.c:149 src/sesh.c:156 src/sesh.c:162 src/sesh.c:407
+#: src/sudo.c:632 src/sudo.c:702 src/sudo.c:712 src/sudo.c:733 src/sudo.c:752
+#: src/sudo.c:761 src/sudo.c:770 src/sudo.c:787 src/sudo.c:829 src/sudo.c:839
+#: src/sudo.c:868 src/sudo.c:1054 src/sudo.c:1076 src/sudo.c:1378
+#: src/sudo.c:1551 src/sudo.c:1776 src/sudo.c:2120 src/sudo_edit.c:89
+#: src/sudo_edit.c:151 src/sudo_edit.c:431 src/sudo_edit.c:440
+#: src/sudo_edit.c:539 src/sudo_edit.c:546 src/sudo_edit.c:682
+#: src/sudo_edit.c:702
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:55
+#: lib/util/json.c:184 lib/util/sudo_conf.c:199 lib/util/sudo_conf.c:284
+#: lib/util/sudo_conf.c:361 lib/util/sudo_conf.c:647 src/conversation.c:81
+#: src/exec_common.c:106 src/exec_common.c:123 src/exec_common.c:132
+#: src/exec_monitor.c:455 src/exec_monitor.c:461 src/exec_monitor.c:469
+#: src/exec_monitor.c:477 src/exec_monitor.c:484 src/exec_monitor.c:491
+#: src/exec_monitor.c:498 src/exec_monitor.c:505 src/exec_monitor.c:512
+#: src/exec_monitor.c:519 src/exec_monitor.c:526 src/exec_nopty.c:212
+#: src/exec_nopty.c:221 src/exec_nopty.c:228 src/exec_nopty.c:235
+#: src/exec_nopty.c:242 src/exec_nopty.c:249 src/exec_nopty.c:256
+#: src/exec_nopty.c:263 src/exec_nopty.c:270 src/exec_nopty.c:277
+#: src/exec_nopty.c:284 src/exec_nopty.c:291 src/exec_nopty.c:299
+#: src/exec_pty.c:834 src/exec_pty.c:843 src/exec_pty.c:900
+#: src/exec_pty.c:1225 src/exec_pty.c:1234 src/exec_pty.c:1241
+#: src/exec_pty.c:1248 src/exec_pty.c:1255 src/exec_pty.c:1262
+#: src/exec_pty.c:1269 src/exec_pty.c:1276 src/exec_pty.c:1283
+#: src/exec_pty.c:1290 src/exec_pty.c:1297 src/exec_pty.c:1305
+#: src/exec_pty.c:1747 src/load_plugins.c:163 src/load_plugins.c:188
+#: src/load_plugins.c:223 src/load_plugins.c:455 src/load_plugins.c:461
+#: src/parse_args.c:181 src/parse_args.c:203 src/parse_args.c:275
+#: src/parse_args.c:616 src/parse_args.c:638 src/parse_args.c:663
+#: src/preserve_fds.c:46 src/preserve_fds.c:131 src/selinux.c:90
+#: src/selinux.c:360 src/selinux.c:489 src/selinux.c:498 src/sesh.c:110
+#: src/sesh.c:408 src/sudo.c:236 src/sudo.c:632 src/sudo.c:868 src/sudo.c:1054
+#: src/sudo.c:1076 src/sudo.c:1378 src/sudo.c:1551 src/sudo.c:1776
+#: src/sudo.c:2120 src/sudo_edit.c:89 src/sudo_edit.c:151 src/sudo_edit.c:431
+#: src/sudo_edit.c:440 src/sudo_edit.c:539 src/sudo_edit.c:546
+#: src/sudo_edit.c:682 src/sudo_edit.c:702
+msgid "unable to allocate memory"
+msgstr "impossibile allocare memoria"
+
+#: lib/util/mkdir_parents.c:69 lib/util/sudo_conf.c:686 src/selinux.c:234
+#: src/selinux.c:264 src/sudo.c:367 src/sudo_edit.c:496 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "impossibile aprire %s"
+
+#: lib/util/mkdir_parents.c:84
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "impossibile creare la directory %s"
+
+#: lib/util/mkdir_parents.c:93 lib/util/sudo_conf.c:663 src/copy_file.c:150
+#, c-format
+msgid "unable to stat %s"
+msgstr "impossibile eseguire stat su %s"
+
+#: lib/util/mkdir_parents.c:98
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s esiste, ma non è una directory (0%o)"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Segnale sconosciuto"
+
+#: lib/util/strtoid.c:87 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:143 src/sesh.c:156
+msgid "invalid value"
+msgstr "valore non valido"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "valore troppo grande"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "valore troppo piccolo"
+
+#: lib/util/sudo_conf.c:217
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "valore percorso \"%s\" non valido in %s, riga %u"
+
+#: lib/util/sudo_conf.c:383 lib/util/sudo_conf.c:399 lib/util/sudo_conf.c:452
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "valore %s \"%s\" non valido in %s, riga %u"
+
+#: lib/util/sudo_conf.c:420
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "gruppo sorgente \"%s\" non supportato in %s, riga %u"
+
+#: lib/util/sudo_conf.c:436
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "gruppi massimi \"%s\" non validi in %s, riga %u"
+
+#: lib/util/sudo_conf.c:666
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s non è un file regolare"
+
+#: lib/util/sudo_conf.c:669 src/copy_file.c:162
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s è di proprietà dello uid %u, dovrebbe essere di %u"
+
+#: lib/util/sudo_conf.c:673
+#, c-format
+msgid "%s is world writable"
+msgstr "%s è scrivibile da tutti"
+
+#: lib/util/sudo_conf.c:676
+#, c-format
+msgid "%s is group writable"
+msgstr "%s è scrivibile dal gruppo"
+
+#: src/copy_file.c:93
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: troncare %s a zero byte? (s/n) [n]"
+
+#: src/copy_file.c:97
+#, c-format
+msgid "not overwriting %s"
+msgstr "%s non viene sovrascritto"
+
+#: src/copy_file.c:119
+#, c-format
+msgid "unable to read from %s"
+msgstr "impossibile leggere da %s"
+
+#: src/copy_file.c:136 src/sudo_edit.c:322
+#, c-format
+msgid "unable to write to %s"
+msgstr "impossibile scrivere su %s"
+
+#: src/copy_file.c:154 src/sesh.c:215 src/sudo_edit.c:199
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: non è un file regolare"
+
+#: src/copy_file.c:158
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: modalità file errata: 0%o"
+
+#: src/edit_open.c:265
+msgid "unable to restore current working directory"
+msgstr "impossibile ripristinare la directory di lavoro attuale"
+
+#: src/exec.c:128
+#, c-format
+msgid "unknown login class %s"
+msgstr "classe di accesso %s sconosciuta"
+
+#: src/exec.c:140
+msgid "unable to set user context"
+msgstr "impossibile impostare il contesto utente"
+
+#: src/exec.c:156
+msgid "unable to set process priority"
+msgstr "impossibile impostare la priorità del processo"
+
+#: src/exec.c:170
+#, c-format
+msgid "unable to change root to %s"
+msgstr "impossibile modificare root a %s"
+
+#: src/exec.c:183 src/exec.c:189 src/exec.c:196
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "impossibile passare a un diverso uid (%u, %u)"
+
+#: src/exec.c:214
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "impossibile passare alla directory %s"
+
+#: src/exec.c:218
+#, c-format
+msgid "starting from %s"
+msgstr "inizio da %s"
+
+#: src/exec.c:300 src/exec_monitor.c:564 src/exec_monitor.c:566
+#: src/exec_nopty.c:531 src/exec_pty.c:575 src/exec_pty.c:1393
+#: src/exec_pty.c:1395 src/signal.c:139 src/signal.c:153
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "impossibile impostare il gestore per il segnale %d"
+
+#: src/exec_common.c:165
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "impossibile rimuovere PRIV_PROC_EXEC da PRIV_LIMIT"
+
+#: src/exec_monitor.c:360
+msgid "error reading from socketpair"
+msgstr "errore nel leggere dal socketpair"
+
+#: src/exec_monitor.c:377
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "tipologia di risposta inattesa sul backchannel: %d"
+
+#: src/exec_monitor.c:463 src/exec_monitor.c:471 src/exec_monitor.c:479
+#: src/exec_monitor.c:486 src/exec_monitor.c:493 src/exec_monitor.c:500
+#: src/exec_monitor.c:507 src/exec_monitor.c:514 src/exec_monitor.c:521
+#: src/exec_monitor.c:528 src/exec_nopty.c:214 src/exec_nopty.c:223
+#: src/exec_nopty.c:230 src/exec_nopty.c:237 src/exec_nopty.c:244
+#: src/exec_nopty.c:251 src/exec_nopty.c:258 src/exec_nopty.c:265
+#: src/exec_nopty.c:272 src/exec_nopty.c:279 src/exec_nopty.c:286
+#: src/exec_nopty.c:293 src/exec_nopty.c:301 src/exec_pty.c:700
+#: src/exec_pty.c:705 src/exec_pty.c:802 src/exec_pty.c:809 src/exec_pty.c:906
+#: src/exec_pty.c:1227 src/exec_pty.c:1236 src/exec_pty.c:1243
+#: src/exec_pty.c:1250 src/exec_pty.c:1257 src/exec_pty.c:1264
+#: src/exec_pty.c:1271 src/exec_pty.c:1278 src/exec_pty.c:1285
+#: src/exec_pty.c:1292 src/exec_pty.c:1299 src/exec_pty.c:1700
+#: src/exec_pty.c:1710 src/exec_pty.c:1755 src/exec_pty.c:1762
+#: src/exec_pty.c:1789
+msgid "unable to add event to queue"
+msgstr "impossibile aggiungere l'evento alla coda"
+
+#: src/exec_monitor.c:582
+msgid "unable to set controlling tty"
+msgstr "impossibile impostare il tty di controllo"
+
+#: src/exec_monitor.c:590 src/exec_nopty.c:358 src/exec_pty.c:1472
+#: src/exec_pty.c:1493 src/exec_pty.c:1513 src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr "impossibile creare una pipe"
+
+#: src/exec_monitor.c:598
+msgid "unable to receive message from parent"
+msgstr "impossibile ricevere il messaggio dal genitore"
+
+#: src/exec_monitor.c:612 src/exec_nopty.c:387 src/exec_pty.c:1551
+#: src/sudo_edit.c:363 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr "impossibile eseguire fork"
+
+#: src/exec_monitor.c:616 src/exec_monitor.c:715 src/exec_nopty.c:441
+msgid "unable to restore tty label"
+msgstr "impossibile ripristinare l'etichetta tty"
+
+#: src/exec_monitor.c:632 src/sesh.c:120 src/sudo.c:1132
+#, c-format
+msgid "unable to execute %s"
+msgstr "impossibile eseguire %s"
+
+#: src/exec_nopty.c:352 src/exec_pty.c:1402
+msgid "policy plugin failed session initialization"
+msgstr "inizializzazione della sessione non riuscita da parte del plugin della politica"
+
+#: src/exec_nopty.c:429 src/exec_pty.c:1639
+msgid "error in event loop"
+msgstr "errore nel ciclo dell'evento"
+
+#: src/exec_nopty.c:539 src/exec_pty.c:613 src/signal.c:101
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "impossibile ripristinare il gestore per il segnale %d"
+
+#: src/exec_pty.c:152
+msgid "unable to allocate pty"
+msgstr "impossibile allocare pty"
+
+#: src/exec_pty.c:216 src/exec_pty.c:256 src/exec_pty.c:296 src/exec_pty.c:347
+#: src/exec_pty.c:398
+msgid "I/O plugin error"
+msgstr "errore del plugin I/O"
+
+#: src/exec_pty.c:220 src/exec_pty.c:260 src/exec_pty.c:300 src/exec_pty.c:351
+#: src/exec_pty.c:402
+msgid "command rejected by I/O plugin"
+msgstr "comando rifiutato dal plugin I/O"
+
+#: src/exec_pty.c:449
+msgid "error logging suspend"
+msgstr "sospensione della registrazione degli errori"
+
+#: src/exec_pty.c:483
+msgid "error changing window size"
+msgstr "errore nel modificare le dimensioni della finestra"
+
+#: src/exec_pty.c:1382
+msgid "unable to create sockets"
+msgstr "impossibile creare socket"
+
+#: src/exec_pty.c:1594
+msgid "unable to send message to monitor process"
+msgstr "impossibile inviare il messaggio per controllare il processo"
+
+#: src/load_plugins.c:50 src/load_plugins.c:63 src/load_plugins.c:85
+#: src/load_plugins.c:115 src/load_plugins.c:129 src/load_plugins.c:135
+#: src/load_plugins.c:283 src/load_plugins.c:293 src/load_plugins.c:303
+#: src/load_plugins.c:350
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "errore in %s, riga %d, durante il caricamento del plugin \"%s\""
+
+#: src/load_plugins.c:87
+#, c-format
+msgid "%s%s: %s"
+msgstr "%s%s: %s"
+
+#: src/load_plugins.c:131
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s deve essere di proprietà dello uid %d"
+
+#: src/load_plugins.c:137
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "%s deve essere scrivibile solo dal proprietario"
+
+#: src/load_plugins.c:247 src/load_plugins.c:318
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "viene ignorato il plugin duplicato \"%s\" in %s, riga %d"
+
+#: src/load_plugins.c:285
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "impossibile caricare %s: %s"
+
+#: src/load_plugins.c:295
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "impossibile trovare il simbolo \"%s\" in %s"
+
+#: src/load_plugins.c:305
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "numero principale di versione del plugin %d non compatibile (atteso %d) trovato in %s"
+
+#: src/load_plugins.c:323
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "viene ignorato il plugin di politica \"%s\" in %s, riga %d"
+
+#: src/load_plugins.c:326
+msgid "only a single policy plugin may be specified"
+msgstr "solo un plugin di politica può essere specificato"
+
+#: src/load_plugins.c:352
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "tipo di plugin %d sconosciuto trovato in %s"
+
+#: src/load_plugins.c:535
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "il plugin di politica %s non include un metodo check_policy"
+
+#: src/net_ifs.c:179 src/net_ifs.c:197 src/net_ifs.c:343 src/sudo.c:479
+#: src/sudo_edit.c:400 src/sudo_edit.c:408
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "errore interno, overflow di %s"
+
+#: src/parse_args.c:223
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "nome della variabile d'ambiente non valido: %s"
+
+#: src/parse_args.c:325
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "l'argomento di -C deve essere un numero maggiore o uguale a 3"
+
+#: src/parse_args.c:552
+msgid "you may not specify both the -i and -s options"
+msgstr "non è possibile specificare entrambe le opzioni -i e -s"
+
+#: src/parse_args.c:557
+msgid "you may not specify both the -i and -E options"
+msgstr "non è possibile specificare entrambe le opzioni -i ed -E"
+
+#: src/parse_args.c:567
+msgid "the -E option is not valid in edit mode"
+msgstr "l'opzione -E non è valida in modalità di modifica"
+
+#: src/parse_args.c:570
+msgid "you may not specify environment variables in edit mode"
+msgstr "non è possibile specificare variabili d'ambiente in modalità di modifica"
+
+#: src/parse_args.c:580
+msgid "the -U option may only be used with the -l option"
+msgstr "l'opzione -U può essere usata solo con l'opzione -l"
+
+#: src/parse_args.c:584
+msgid "the -A and -S options may not be used together"
+msgstr "non è possibile usare assieme le opzioni -A e -S"
+
+#: src/parse_args.c:677
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit non è supportato su questa piattaforma"
+
+#: src/parse_args.c:759
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Solo una delle opzioni -e, -h, -i, -K, -l, -s, -v o -V può essere specificata"
+
+#: src/parse_args.c:773
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - modifica file come un altro utente\n"
+"\n"
+
+#: src/parse_args.c:775
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - esegue un comando come un altro utente\n"
+"\n"
+
+#: src/parse_args.c:780
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Opzioni:\n"
+
+#: src/parse_args.c:782
+msgid "use a helper program for password prompting"
+msgstr "Utilizza un programma d'aiuto per richiedere la password"
+
+#: src/parse_args.c:785
+msgid "use specified BSD authentication type"
+msgstr "Utilizza la tipologia di autenticazione BSD specificata"
+
+#: src/parse_args.c:788
+msgid "run command in the background"
+msgstr "Esegue il comando in background"
+
+#: src/parse_args.c:790
+msgid "ring bell when prompting"
+msgstr "Suona la campanella con le richieste"
+
+#: src/parse_args.c:792
+msgid "close all file descriptors >= num"
+msgstr "Chiude tutti i descrittori di file >= num"
+
+#: src/parse_args.c:795
+msgid "run command with the specified BSD login class"
+msgstr "Esegue il comando con la classe di accesso BSD specificata"
+
+#: src/parse_args.c:798
+msgid "change the working directory before running command"
+msgstr "Cambia la directory di lavoro prima di eseguire il comando"
+
+#: src/parse_args.c:800
+msgid "preserve user environment when running command"
+msgstr "Mantiene l'ambiente dell'utente quando viene eseguito il comando"
+
+#: src/parse_args.c:802
+msgid "preserve specific environment variables"
+msgstr "Mantiene delle variabile d'ambiente specifiche"
+
+#: src/parse_args.c:804
+msgid "edit files instead of running a command"
+msgstr "Modifica i file invece di eseguire un comando"
+
+#: src/parse_args.c:806
+msgid "run command as the specified group name or ID"
+msgstr "Esegue il comando come il gruppo o l'ID specificato"
+
+#: src/parse_args.c:808
+msgid "set HOME variable to target user's home dir"
+msgstr "Imposta la variabile HOME alla directory dell'utente finale"
+
+#: src/parse_args.c:810
+msgid "display help message and exit"
+msgstr "Visualizza il messaggio di aiuto ed esce"
+
+#: src/parse_args.c:812
+msgid "run command on host (if supported by plugin)"
+msgstr "Esegue il comando sull'host (se supportato dal plugin)"
+
+#: src/parse_args.c:814
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "Esegue una shell di login come l'utente finale; può essere specificato un comando"
+
+#: src/parse_args.c:816
+msgid "remove timestamp file completely"
+msgstr "Rimuove completamente il file temporale"
+
+#: src/parse_args.c:818
+msgid "invalidate timestamp file"
+msgstr "Invalida il file temporale"
+
+#: src/parse_args.c:820
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "Elenca i privilegi dell'utente o verifica un comando specifico; usare due volte per il formato più lungo"
+
+#: src/parse_args.c:822
+msgid "non-interactive mode, no prompts are used"
+msgstr "Modalità non interattiva, non richiede nulla all'utente"
+
+#: src/parse_args.c:824
+msgid "preserve group vector instead of setting to target's"
+msgstr "Mantiene il vettore di gruppo invece di impostarlo a quello dell'obiettivo"
+
+#: src/parse_args.c:826
+msgid "use the specified password prompt"
+msgstr "Utilizza la richiesta della password specificata"
+
+#: src/parse_args.c:828
+msgid "change the root directory before running command"
+msgstr "Cambia la directory root prima di eseguire il comando"
+
+#: src/parse_args.c:831
+msgid "create SELinux security context with specified role"
+msgstr "Crea il contesto di sicurezza SELinux con il ruolo specificato"
+
+#: src/parse_args.c:834
+msgid "read password from standard input"
+msgstr "Legge la password dallo standard input"
+
+#: src/parse_args.c:836
+msgid "run shell as the target user; a command may also be specified"
+msgstr "Esegue la shell come l'utente finale; può essere specificato un comando"
+
+#: src/parse_args.c:839
+msgid "create SELinux security context with specified type"
+msgstr "Crea il contesto di sicurezza SELinux con il tipo specificato"
+
+#: src/parse_args.c:842
+msgid "terminate command after the specified time limit"
+msgstr "Termina il comando allo trascorrere del limite temporale specificato"
+
+#: src/parse_args.c:844
+msgid "in list mode, display privileges for user"
+msgstr "In modalità elenco, visualizza i privilegi dell'utente"
+
+#: src/parse_args.c:846
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "Esegue un comando (o modifica un file) come il nome utente o l'ID specificato"
+
+#: src/parse_args.c:848
+msgid "display version information and exit"
+msgstr "Visualizza le informazioni sulla versione ed esce"
+
+#: src/parse_args.c:850
+msgid "update user's timestamp without running a command"
+msgstr "Aggiorna il timestamp dell'utente senza eseguire un comando"
+
+#: src/parse_args.c:852
+msgid "stop processing command line arguments"
+msgstr "Ferma l'elaborazione degli argomenti a riga di comando"
+
+#: src/selinux.c:84
+msgid "unable to open audit system"
+msgstr "impossibile aprire il sistema di audit"
+
+#: src/selinux.c:94
+msgid "unable to send audit message"
+msgstr "impossibile inviare il messaggio di audit"
+
+#: src/selinux.c:128
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "impossibile eseguire fgetfilecon %s"
+
+#: src/selinux.c:133
+#, c-format
+msgid "%s changed labels"
+msgstr "%s ha modificato le etichette"
+
+#: src/selinux.c:141
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "impossibile ripristinare il contesto per %s"
+
+#: src/selinux.c:189
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "impossibile aprire %s, tty non viene ri-etichettato"
+
+#: src/selinux.c:193 src/selinux.c:238 src/selinux.c:268
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s non è un dispositivo a caratteri, tty non viene ri-etichettato"
+
+#: src/selinux.c:202
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "impossibile ottenere il contesto tty attuale, tty non viene ri-etichettato"
+
+#: src/selinux.c:209
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "classe di sicurezza \"chr_file\" sconosciuta, tty non viene ri-etichettato"
+
+#: src/selinux.c:214
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "impossibile ottenere il nuovo contesto tty, tty non viene ri-etichettato"
+
+#: src/selinux.c:223
+msgid "unable to set new tty context"
+msgstr "impossibile impostare il nuovo contesto tty"
+
+#: src/selinux.c:321
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "è necessario specificare un ruolo per la tipologia %s"
+
+#: src/selinux.c:327
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "impossibile ottenere la tipologia predefinita per il ruolo %s"
+
+#: src/selinux.c:339
+msgid "failed to get new context"
+msgstr "recupero del nuovo contesto non riuscito"
+
+#: src/selinux.c:348
+#, c-format
+msgid "failed to set new role %s"
+msgstr "impossibile impostare il nuovo ruolo %s"
+
+#: src/selinux.c:352
+#, c-format
+msgid "failed to set new type %s"
+msgstr "impossibile impostare la nuova tipologia %s"
+
+#: src/selinux.c:364
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s non è un contesto valido"
+
+#: src/selinux.c:396
+msgid "failed to get old context"
+msgstr "recupero del vecchio contesto non riuscito"
+
+#: src/selinux.c:402
+msgid "unable to determine enforcing mode."
+msgstr "impossibile determinare la modalità di rispetto."
+
+#: src/selinux.c:419
+#, c-format
+msgid "unable to set tty context to %s"
+msgstr "impossibile impostare il contesto tty a %s"
+
+#: src/selinux.c:440
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "impossibile impostare il contesto exec a %s"
+
+#: src/selinux.c:447
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "impossibile impostare il contesto di creazione della chiave a %s"
+
+#: src/sesh.c:72
+msgid "requires at least one argument"
+msgstr "richiede almeno un argomento"
+
+#: src/sesh.c:101
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "numero descrittore file non valido: %s"
+
+#: src/sesh.c:115
+#, c-format
+msgid "unable to run %s as a login shell"
+msgstr "impossibile eseguire %s come shell di login"
+
+#: src/sesh.c:197 src/sesh.c:297 src/sudo_edit.c:206
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: la modifica di collegamenti simbolici non è consentita"
+
+#: src/sesh.c:200 src/sesh.c:300 src/sudo_edit.c:209
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: la modifica di file in una directory con accesso in scrittura non è consentita"
+
+#: src/sesh.c:284 src/sesh.c:305 src/sesh.c:314 src/sesh.c:322
+#: src/sudo_edit.c:333
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "contenuto della sessione di modifica lasciato in %s"
+
+#: src/sesh.c:412 src/sudo_edit.c:93
+msgid "unable to get group list"
+msgstr "Impossibile ottenere l'elenco dei gruppi"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "impossibile salvare il gestore per il segnale %d"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "raggiunto il limite di controllo delle risorse"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "l'utente \"%s\" non fa parte del progetto \"%s\""
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "il task chiamante è definitivo"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "impossibile unirsi al progetto \"%s\""
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "non esiste alcun pool di risorse per il progetto \"%s\" che accetti binding predefiniti"
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "il pool di risorse specificato non esiste per il progetto \"%s\""
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "impossibile unirsi al pool di risorse predefinito per il progetto \"%s\""
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "setproject per il progetto \"%s\" non riuscita"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "attenzione, assegnazione della risorsa di controllo per il progetto \"%s\" non riuscita"
+
+#: src/sudo.c:222
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Versione di sudo: %s\n"
+
+#: src/sudo.c:224
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Opzioni di configurazione: %s\n"
+
+#: src/sudo.c:232
+msgid "fatal error, unable to load plugins"
+msgstr "errore irreversibile, impossibile caricare i plugin"
+
+#: src/sudo.c:278
+msgid "plugin did not return a command to execute"
+msgstr "il plug-in non ha restituito un comando da eseguire"
+
+#: src/sudo.c:310
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "modalità 0x%x di sudo non attesa"
+
+#: src/sudo.c:546
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "l'utente attuale non esiste nel database %s"
+
+#: src/sudo.c:603
+msgid "unable to determine tty"
+msgstr "impossibile impostare il tty"
+
+#: src/sudo.c:914
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s deve essere di proprietà dello uid %d e avere il bit setuid impostato"
+
+#: src/sudo.c:917
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "lo uid effettivo non è %d. %s si trova su un file system con l'opzione \"nosuid\" impostata o su un file system NFS senza privilegi di root?"
+
+#: src/sudo.c:923
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "lo uid effettivo non è %d. Il programma sudo è installato con setuid root?"
+
+#: src/sudo.c:939
+msgid "unable to set supplementary group IDs"
+msgstr "impossibile impostare ID di gruppo supplementari"
+
+#: src/sudo.c:946
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "impossibile impostare il gid effettivo per eseguire come %u"
+
+#: src/sudo.c:952
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "impossibile impostare il gid per eseguire come gid %u"
+
+#: src/sudo.c:995
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "condizione di uscita del figlio inattesa: %d"
+
+#: src/sudo.c:1104
+msgid "unable to initialize policy plugin"
+msgstr "impossibile inizializzare il plugin delle politiche"
+
+#: src/sudo.c:1167
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "il plugin di politica %s non include il metodo \"check_policy\""
+
+#: src/sudo.c:1182 src/sudo.c:1235 src/sudo.c:1279
+msgid "command rejected by policy"
+msgstr "comando rifiutato dalla politica"
+
+#: src/sudo.c:1187 src/sudo.c:1240 src/sudo.c:1284 src/sudo.c:1358
+msgid "policy plugin error"
+msgstr "errore plugin di politica"
+
+#: src/sudo.c:1221
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "il plugin di politica %s non supporta l'elencazione dei privilegi"
+
+#: src/sudo.c:1265
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "il plugin di politica %s non supporta l'opzione -v"
+
+#: src/sudo.c:1303
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "il plugin di politica %s non supporta le opzioni -k/-K"
+
+#: src/sudo.c:1436
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "errore nell'inizializzare il plugin di I/O %s"
+
+#: src/sudo.c:1590
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "errore nell'inizializzare il plugin di audit %s"
+
+#: src/sudo.c:1668
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: impossibile registrare l'evento error%s%s"
+
+#: src/sudo.c:1703
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: impossibile registrare l'evento accept%s%s"
+
+#: src/sudo.c:1708 src/sudo.c:1746
+msgid "audit plugin error"
+msgstr "errore plugin di controllo"
+
+#: src/sudo.c:1741
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: impossibile registrare l'evento reject%s%s"
+
+#: src/sudo.c:1799
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "errore nell'inizializzare il plugin di approvazione %s"
+
+#: src/sudo.c:1875
+msgid "command rejected by approver"
+msgstr "comando rifiutato dall'approvatore"
+
+#: src/sudo.c:1884
+msgid "approval plugin error"
+msgstr "errore plugin di approvazione"
+
+#: src/sudo_edit.c:112
+msgid "no writable temporary directory found"
+msgstr "nessuna directory temporanea scrivibile trovata"
+
+#: src/sudo_edit.c:293
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s lasciato non modificato"
+
+#: src/sudo_edit.c:306 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s non modificato"
+
+#: src/sudo_edit.c:483
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: errore interno: strano numero numero di percorsi"
+
+#: src/sudo_edit.c:485
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: impossibile creare file temporanei"
+
+#: src/sudo_edit.c:487 src/sudo_edit.c:605
+msgid "sesh: killed by a signal"
+msgstr "sesh: ucciso da un segnale"
+
+#: src/sudo_edit.c:489 src/sudo_edit.c:608
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: errore %d sconosciuto"
+
+#: src/sudo_edit.c:598
+msgid "unable to copy temporary files back to their original location"
+msgstr "impossibile copiare i file temporanei nella loro posizione originale"
+
+#: src/sudo_edit.c:602
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "impossibile copiare alcuni dei file temporanei nella loro posizione originale"
+
+#: src/sudo_edit.c:645
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "impossibile modificare lo uid a root (%u)"
+
+#: src/sudo_edit.c:666
+msgid "plugin error: missing file list for sudoedit"
+msgstr "errore di plugin: elenco file mancante per sudoedit"
+
+#: src/sudo_edit.c:717 src/sudo_edit.c:725
+msgid "unable to read the clock"
+msgstr "impossibile leggere l'orologio"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "tempo esaurito durante la lettura della password"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "nessuna password fornita"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "impossibile leggere la password"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "è richiesto un terminale per leggere la password; utilizzare l'opzione -S per leggere dall'input standard o configurare uno strumento askpass"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "nessun programma di richiesta password specificato, impostare SUDO_ASKPASS"
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "impossibile impostare il gid a %u"
+
+#: src/tgetpass.c:331
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "impossibile impostare lo uid a %u"
+
+#: src/tgetpass.c:336
+#, c-format
+msgid "unable to run %s"
+msgstr "impossibile eseguire %s"
+
+#: src/utmp.c:287
+msgid "unable to save stdin"
+msgstr "impossibile salvare lo stdin"
+
+#: src/utmp.c:289
+msgid "unable to dup2 stdin"
+msgstr "impossibile eseguire dup2 sullo stdin"
+
+#: src/utmp.c:292
+msgid "unable to restore stdin"
+msgstr "impossibile ripristinare lo stdin"
diff --git a/po/ja.mo b/po/ja.mo
new file mode 100644
index 0000000..61130e7
--- /dev/null
+++ b/po/ja.mo
Binary files differ
diff --git a/po/ja.po b/po/ja.po
new file mode 100644
index 0000000..e1640a8
--- /dev/null
+++ b/po/ja.po
@@ -0,0 +1,1313 @@
+# Japanese messages for sudo
+# This file is put in the public domain.
+# Yasuaki Taniguchi <yasuakit@gmail.com>, 2011.
+# Takeshi Hamasaki <hmatrjp@users.sourceforge.jp>, 2012, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.14b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-06-07 13:27-0600\n"
+"PO-Revision-Date: 2023-06-30 22:30+0900\n"
+"Last-Translator: Takeshi Hamasaki <hmatrjp@users.sourceforge.jp>\n"
+"Language-Team: Japanese <translation-team-ja@lists.sourceforge.net>\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Poedit 2.4.2\n"
+"X-Poedit-Basepath: sudo-1.9.12b2\n"
+"X-Poedit-SearchPath-0: .\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "ユーザーデータベースを開くことができません"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "%s 用のレジストリー \"%s\" へ切り替えることができません"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "レジストリーを復元できません"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:78 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:171 src/exec_monitor.c:418
+#: src/exec_monitor.c:424 src/exec_monitor.c:432 src/exec_monitor.c:440
+#: src/exec_monitor.c:447 src/exec_monitor.c:454 src/exec_monitor.c:461
+#: src/exec_monitor.c:468 src/exec_monitor.c:475 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:744 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1096
+#: src/exec_ptrace.c:1271 src/exec_ptrace.c:1624 src/exec_ptrace.c:1651
+#: src/exec_ptrace.c:1841 src/exec_pty.c:581 src/exec_pty.c:765
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:193 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:240
+#: src/sesh.c:246 src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:644
+#: src/sudo.c:709 src/sudo.c:719 src/sudo.c:746 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:787 src/sudo.c:805 src/sudo.c:846 src/sudo.c:855 src/sudo.c:865
+#: src/sudo.c:898 src/sudo.c:1127 src/sudo.c:1148 src/sudo.c:1441
+#: src/sudo.c:1610 src/sudo.c:1837 src/sudo.c:2171 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:430 src/sudo_edit.c:439
+#: src/sudo_edit.c:540 src/sudo_edit.c:547 src/sudo_edit.c:692
+#: src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:79 src/exec_intercept.c:111 src/exec_intercept.c:350
+#: src/exec_intercept.c:525 src/exec_intercept.c:589 src/exec_intercept.c:713
+#: src/exec_intercept.c:837 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:418 src/exec_monitor.c:424
+#: src/exec_monitor.c:432 src/exec_monitor.c:440 src/exec_monitor.c:447
+#: src/exec_monitor.c:454 src/exec_monitor.c:461 src/exec_monitor.c:468
+#: src/exec_monitor.c:475 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1651 src/exec_ptrace.c:1842 src/exec_pty.c:581
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:228 src/sudo.c:644 src/sudo.c:898 src/sudo.c:1127
+#: src/sudo.c:1148 src/sudo.c:1441 src/sudo.c:1610 src/sudo.c:1837
+#: src/sudo.c:2171 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:430
+#: src/sudo_edit.c:439 src/sudo_edit.c:540 src/sudo_edit.c:547
+#: src/sudo_edit.c:692 src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "メモリ割り当てを行えませんでした"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "%.*s の状態取得 (stat) ができません"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s は存在しますが、ディレクトリではありません (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:664
+#: lib/util/sudo_conf.c:683 lib/util/sudo_conf.c:710 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:495 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "%s を開けません"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "%.*s を mkdir できません"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "%.*s を開けません"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "正規表現が長すぎます。"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "不明なシグナルです"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "無効な値"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "値が大き過ぎます"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "値が小さ過ぎます"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "無効な Path の値 \"%s\" が %s の %u 行目 にあります"
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "無効な %s の値 \"%s\" が %s の %u 行目 にあります"
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "サポートしていないグループソース \"%s\" が %s の %u 行目で指定されています"
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "無効な最大グループの値 \"%s\" が %s の %u 行目 にあります"
+
+#: lib/util/sudo_conf.c:686
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s は通常ファイルではありません"
+
+#: lib/util/sudo_conf.c:689 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s はユーザーID %u によって所有されています。これは %u であるべきです"
+
+#: lib/util/sudo_conf.c:693
+#, c-format
+msgid "%s is world writable"
+msgstr "%s は誰でも書き込み可能です"
+
+#: lib/util/sudo_conf.c:696
+#, c-format
+msgid "%s is group writable"
+msgstr "%s はグループのメンバーによる書き込みが可能です"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "AppArmor の制限を決定することができません。"
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "AppArmor のプロファイルを %s へ変更できません"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: %s をゼロバイトに切り詰めますか? (y/n) [n] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "%s を上書きしません"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "%s から読み込むことができません"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "%s へ書き込むことができません"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "%s の状態取得 (stat) ができません"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: 通常ファイルではありません"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: ファイルのモードが異常です: 0%o"
+
+#: src/edit_open.c:333
+msgid "unable to restore current working directory"
+msgstr "カレントディレクトリを復元できません"
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "権限を設定できません"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "制限した権限を設定できません"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "不明なログインクラス %s です"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "ユーザーコンテキストを設定できません"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "プロセス優先度を設定できません"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "root を %s へ変更できません"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "実行時のユーザーID (uid) (%u, %u) へ変更できません"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "ディレクトリーを %s に変更できません"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "%s から始めます"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:552 src/exec_monitor.c:554
+#: src/exec_pty.c:1122 src/exec_pty.c:1124 src/signal.c:144 src/signal.c:151
+#: src/signal.c:165 src/suspend_parent.c:143
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "シグナル %d のハンドラを設定できません"
+
+#: src/exec.c:424
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "SELinux RBAC でのインターセプトモードはこのシステムではサポートされていません"
+
+#: src/exec.c:429
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "SELinux RBAC でのサブコマンドログはこのシステムではサポートされていません"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "PRIV_LIMIT から PRIV_PROC_EXEC を取り除くことができません"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:163 src/exec_iolog.c:173
+#: src/exec_iolog.c:218 src/exec_iolog.c:225 src/exec_iolog.c:252
+#: src/exec_monitor.c:426 src/exec_monitor.c:434 src/exec_monitor.c:442
+#: src/exec_monitor.c:449 src/exec_monitor.c:456 src/exec_monitor.c:463
+#: src/exec_monitor.c:470 src/exec_monitor.c:477 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:457 src/exec_pty.c:432
+#: src/exec_pty.c:537 src/exec_pty.c:587 src/exec_pty.c:965 src/exec_pty.c:974
+#: src/exec_pty.c:981 src/exec_pty.c:988 src/exec_pty.c:995
+#: src/exec_pty.c:1002 src/exec_pty.c:1009 src/exec_pty.c:1016
+#: src/exec_pty.c:1023 src/exec_pty.c:1030 src/exec_pty.c:1037
+#: src/exec_pty.c:1044
+msgid "unable to add event to queue"
+msgstr "キューにイベントを追加できません"
+
+#: src/exec_intercept.c:323 src/sudo.c:1033
+msgid "command not set by the security policy"
+msgstr "セキュリティーポリシーによりコマンドが設定されていません"
+
+#: src/exec_intercept.c:401 src/exec_intercept.c:441 src/sudo.c:1253
+#: src/sudo.c:1298 src/sudo.c:1342
+msgid "command rejected by policy"
+msgstr "ポリシーによりコマンドが拒否されました"
+
+#: src/exec_intercept.c:512 src/sudo.c:1940
+msgid "approval plugin error"
+msgstr "承認プラグイン エラー"
+
+#: src/exec_intercept.c:537 src/sudo.c:1258 src/sudo.c:1303 src/sudo.c:1347
+#: src/sudo.c:1421
+msgid "policy plugin error"
+msgstr "ポリシープラグインエラー"
+
+#: src/exec_intercept.c:566
+msgid "invalid PolicyCheckRequest"
+msgstr "無効な PolicyCheckRequest"
+
+#: src/exec_intercept.c:709
+#, c-format
+msgid "client request too large: %zu"
+msgstr "クライアントリクエストが大き過ぎます: %zu"
+
+#: src/exec_intercept.c:751
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "%s を伸長できません (長さ %zu )"
+
+#: src/exec_intercept.c:799
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "予期しない type_case の値 %d が %s の中にあります、 %s から出てきたものです。"
+
+#: src/exec_intercept.c:825
+#, c-format
+msgid "server message too large: %zu"
+msgstr "サーバーメッセージが大き過ぎます: %zu"
+
+#: src/exec_iolog.c:321 src/exec_iolog.c:361 src/exec_iolog.c:401
+#: src/exec_iolog.c:452 src/exec_iolog.c:503
+msgid "I/O plugin error"
+msgstr "I/O プラグインエラー"
+
+#: src/exec_iolog.c:325 src/exec_iolog.c:365 src/exec_iolog.c:405
+#: src/exec_iolog.c:456 src/exec_iolog.c:507
+msgid "command rejected by I/O plugin"
+msgstr "I/O プラグインによりコマンドが拒否されました"
+
+#: src/exec_iolog.c:555
+msgid "error logging suspend"
+msgstr "エラーの記録が一時中断しています"
+
+#: src/exec_iolog.c:590
+msgid "error changing window size"
+msgstr "ウィンドウサイズの変更でエラー"
+
+#: src/exec_monitor.c:328
+msgid "error reading from socketpair"
+msgstr "ソケットペアからの読み込み中にエラーが発生しました"
+
+#: src/exec_monitor.c:340
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "バックチャンネルに関する予期しないリプレイタイプです: %d"
+
+#: src/exec_monitor.c:566
+msgid "unable to set controlling tty"
+msgstr "tty の制御設定ができません"
+
+#: src/exec_monitor.c:574 src/exec_nopty.c:504 src/exec_nopty.c:514
+#: src/exec_nopty.c:524 src/exec_nopty.c:560 src/exec_pty.c:1195
+#: src/exec_pty.c:1222 src/exec_pty.c:1242 src/exec_pty.c:1262
+#: src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr "パイプを作成できません"
+
+#: src/exec_monitor.c:584
+msgid "unable to receive message from parent"
+msgstr "親からのメッセージを受け取ることができません"
+
+#: src/exec_monitor.c:600 src/exec_nopty.c:603 src/exec_pty.c:1303
+#: src/sudo_edit.c:361 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr "fork できません"
+
+#: src/exec_monitor.c:604 src/exec_monitor.c:700 src/exec_nopty.c:708
+msgid "unable to restore tty label"
+msgstr "tty ラベルを復旧できません"
+
+#: src/exec_monitor.c:615 src/sesh.c:217 src/sudo.c:1204
+#, c-format
+msgid "unable to execute %s"
+msgstr "%s を実行できません"
+
+#: src/exec_nopty.c:554 src/exec_pty.c:1131
+msgid "policy plugin failed session initialization"
+msgstr "ポリシープラグインがセッションの初期化に失敗しました"
+
+#: src/exec_nopty.c:569 src/exec_pty.c:1100 src/exec_pty.c:1109
+msgid "unable to create sockets"
+msgstr "ソケットを作成できません"
+
+#: src/exec_nopty.c:696 src/exec_pty.c:1406
+msgid "error in event loop"
+msgstr "イベントループでエラーが発生しました"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:852 src/sudo.c:488
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "内部エラー、 %s がオーバーフローしました"
+
+#: src/exec_ptrace.c:1080 src/exec_ptrace.c:1105 src/exec_ptrace.c:1925
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "プロセス %d のレジスターを設定できません"
+
+#: src/exec_ptrace.c:1100 src/exec_ptrace.c:1275 src/exec_ptrace.c:1628
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "プロセス %d が予期せぬ終了をしました"
+
+#: src/exec_ptrace.c:1209
+msgid "unable to set seccomp filter"
+msgstr "seccomp フィルターを設定できません"
+
+#: src/exec_ptrace.c:1406
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "インタープリターの引数は、 \"%s\" のはずですが、\"%s\" です"
+
+#: src/exec_ptrace.c:1505
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "パス名が一致しません、 \"%s\" のはずですが、\"%s\" です"
+
+#: src/exec_ptrace.c:1514 src/exec_ptrace.c:1521 src/exec_ptrace.c:1545
+#: src/exec_ptrace.c:1553 src/exec_ptrace.c:1559 src/exec_ptrace.c:1565
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "%s[%d] が一致しません、 \"%s\" のはずですが、\"%s\" です"
+
+#: src/exec_ptrace.c:1632
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "プロセス %d が予期せぬ終了ステータス 0x %x を返しました"
+
+#: src/exec_ptrace.c:1723
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "プロセス %d のイベントメッセージを取得できません"
+
+#: src/exec_ptrace.c:1730
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "プロセス %d のレジスターを取得できません"
+
+#: src/exec_pty.c:84
+msgid "unable to allocate pty"
+msgstr "pty を割り当てられません"
+
+#: src/exec_pty.c:131 src/exec_pty.c:284 src/tgetpass.c:251
+msgid "unable to restore terminal settings"
+msgstr "端末の設定を復元できません"
+
+#: src/exec_pty.c:243
+msgid "unable to set handler for SIGCONT"
+msgstr "SIGCONT のハンドラを設定できません"
+
+#: src/exec_pty.c:293
+#, c-format
+msgid "unable to set handler for SIG%s"
+msgstr "SIG%s のハンドラを設定できません"
+
+#: src/exec_pty.c:317
+#, c-format
+msgid "unable to restore handler for SIG%s"
+msgstr "SIG%s のハンドラを復元できません"
+
+#: src/exec_pty.c:345
+msgid "unable to restore handler for SIGCONT"
+msgstr "SIGCONT のハンドラを復元できません"
+
+#: src/exec_pty.c:1353
+msgid "unable to send message to monitor process"
+msgstr "監視プロセスへメッセージを送ることができません"
+
+#: src/load_plugins.c:75 src/load_plugins.c:222 src/load_plugins.c:232
+#: src/load_plugins.c:242 src/load_plugins.c:289
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "%s, %d 行目 プラグイン \"%s\" をロード中にエラーが発生しました"
+
+#: src/load_plugins.c:186 src/load_plugins.c:257
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "重複しているプラグイン \"%s\" を無視します。%s の %d 行目"
+
+#: src/load_plugins.c:224
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "%s をロードできません: %s"
+
+#: src/load_plugins.c:234
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "シンボル \"%s\" が %s に見つかりません"
+
+#: src/load_plugins.c:244
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "互換性の無いポリシーメジャーバージョン %d (予期されるのは %d)が %s で見つかりました"
+
+#: src/load_plugins.c:262
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "ポリシープラグイン \"%s\" を無視します。%s の %d 行目"
+
+#: src/load_plugins.c:265
+msgid "only a single policy plugin may be specified"
+msgstr "1つのポリシープラグインのみ指定できます"
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "不明なプラグインタイプ %d が %s で見つかりました"
+
+#: src/load_plugins.c:474
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "ポリシープラグイン %s には check_policy メソッドが含まれていません"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "無効な環境変数名です: %s"
+
+#: src/parse_args.c:319
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "-C の引数は 3 以上の数値でなければいけません"
+
+#: src/parse_args.c:556
+msgid "you may not specify both the -i and -s options"
+msgstr "-i と -s オプションを同時に指定することはできません"
+
+#: src/parse_args.c:561
+msgid "you may not specify both the -i and -E options"
+msgstr "-i と -E オプションを同時に指定することはできません"
+
+#: src/parse_args.c:571
+msgid "the -E option is not valid in edit mode"
+msgstr "-E オプションは編集モードでは無効です"
+
+#: src/parse_args.c:574
+msgid "you may not specify environment variables in edit mode"
+msgstr "編集モードでは環境変数を指定できません"
+
+#: src/parse_args.c:584
+msgid "the -U option may only be used with the -l option"
+msgstr "-U オプションを使うには -l オプションも必要です"
+
+#: src/parse_args.c:588
+msgid "the -A and -S options may not be used together"
+msgstr "-A と -S オプションは同時に指定できません"
+
+#: src/parse_args.c:686
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit はこのプラットフォームではサポートされていません"
+
+#: src/parse_args.c:744
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "-e, -h, -i, -K, -l, -s, -v または -V のうち一つのみ指定できます"
+
+#: src/parse_args.c:757
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "-K, -k または -N のうち一つのみ指定できます"
+
+#: src/parse_args.c:778
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - 別のユーザーとしてファイルを編集します\n"
+"\n"
+
+#: src/parse_args.c:780
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - 別のユーザーとしてコマンドを実行します\n"
+"\n"
+
+#: src/parse_args.c:785
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"オプション:\n"
+
+#: src/parse_args.c:787
+msgid "use a helper program for password prompting"
+msgstr "パスワード要求のために補助プログラムを使用する"
+
+#: src/parse_args.c:790
+msgid "use specified BSD authentication type"
+msgstr "指定した BSD 認証タイプを使用する"
+
+#: src/parse_args.c:794
+msgid "run command in the background"
+msgstr "コマンドをバックグラウンドで実行する"
+
+#: src/parse_args.c:797
+msgid "ring bell when prompting"
+msgstr "プロンプトと同時にベルを鳴らす"
+
+#: src/parse_args.c:799
+msgid "close all file descriptors >= num"
+msgstr "num 以上のすべてのファイル記述子を閉じる"
+
+#: src/parse_args.c:802
+msgid "run command with the specified BSD login class"
+msgstr "指定した BSD ログインクラスでコマンドを実行する"
+
+#: src/parse_args.c:805
+msgid "change the working directory before running command"
+msgstr "コマンド実行前に作業ディレクトリを変更する"
+
+#: src/parse_args.c:808
+msgid "preserve user environment when running command"
+msgstr "コマンドを実行する時にユーザーの環境変数を維持する"
+
+#: src/parse_args.c:810
+msgid "preserve specific environment variables"
+msgstr "指定の環境変数を維持する"
+
+#: src/parse_args.c:812
+msgid "edit files instead of running a command"
+msgstr "コマンドを実行するのではなくファイルを編集する"
+
+#: src/parse_args.c:815
+msgid "run command as the specified group name or ID"
+msgstr "指定したグループ名またはグループIDでコマンドを実行する"
+
+#: src/parse_args.c:818
+msgid "set HOME variable to target user's home dir"
+msgstr "HOME 変数を変更先となるユーザーのホームディレクトリに設定する"
+
+#: src/parse_args.c:821
+msgid "display help message and exit"
+msgstr "このヘルプを表示して終了する"
+
+#: src/parse_args.c:823
+msgid "run command on host (if supported by plugin)"
+msgstr "host でコマンドを実行する(プラグインがサポートしている場合)"
+
+#: src/parse_args.c:826
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "変更先のユーザーとしてログインシェルを実行する; コマンドを指定することもできます"
+
+#: src/parse_args.c:828
+msgid "remove timestamp file completely"
+msgstr "タイムスタンプファイルを完全に削除する"
+
+#: src/parse_args.c:831
+msgid "invalidate timestamp file"
+msgstr "無効なタイムスタンプファイルです"
+
+#: src/parse_args.c:834
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "ユーザーの権限を一覧表示するまたは指定したコマンドについて確認する ;長い表示にするには2回指定すること"
+
+#: src/parse_args.c:837
+msgid "non-interactive mode, no prompts are used"
+msgstr "非対話モードで実行し、ユーザーに入力を求めない"
+
+#: src/parse_args.c:840
+msgid "preserve group vector instead of setting to target's"
+msgstr "グループベクトルを保護する (変更先のユーザーのものに設定しない)"
+
+#: src/parse_args.c:843
+msgid "use the specified password prompt"
+msgstr "指定したパスワードプロンプトを使用する"
+
+#: src/parse_args.c:845
+msgid "change the root directory before running command"
+msgstr "コマンド実行前にルートディレクトリを変更する"
+
+#: src/parse_args.c:848
+msgid "create SELinux security context with specified role"
+msgstr "指定した役割で SELinux セキュリティーコンテキストを作成する"
+
+#: src/parse_args.c:851
+msgid "read password from standard input"
+msgstr "標準入力からパスワードを読み込む"
+
+#: src/parse_args.c:854
+msgid "run shell as the target user; a command may also be specified"
+msgstr "変更先のユーザーとしてシェルを実行する; コマンドを指定することもできます"
+
+#: src/parse_args.c:858
+msgid "create SELinux security context with specified type"
+msgstr "指定したタイプで SELinux セキュリティーコンテキストを作成する"
+
+#: src/parse_args.c:861
+msgid "terminate command after the specified time limit"
+msgstr "指定した制限時間でコマンドの実行を中止する"
+
+#: src/parse_args.c:864
+msgid "in list mode, display privileges for user"
+msgstr "リストモードで、ユーザーの権限を表示する"
+
+#: src/parse_args.c:867
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "指定したユーザー名またはユーザーIDでコマンドを実行する (またはファイルを編集する)"
+
+#: src/parse_args.c:869
+msgid "display version information and exit"
+msgstr "バージョン情報を表示して終了する"
+
+#: src/parse_args.c:872
+msgid "update user's timestamp without running a command"
+msgstr "コマンドを実行せずにユーザーのタイムスタンプを更新する"
+
+#: src/parse_args.c:875
+msgid "stop processing command line arguments"
+msgstr "コマンドライン引数の処理を終了する"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "監査システムを開くことができません"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "監査メッセージを送ることができません"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "fgetfilecon %s を行うことができません"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s はラベルを変更しました"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "%s 用のコンテキストを復元することができません"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "%s を開くことができません。tty の再ラベル付けを行いません"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s はキャラクターデバイスではありません、tty の再ラベル付けを行いません"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "現在の tty コンテキストを取得できません。tty の再ラベル付けを行いません"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "\"chr_file\" は未知のセキュリティクラスです。tty の再ラベル付けを行いません"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "新しい tty コンテキストを取得できません。tty の再ラベル付けを行いません"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "新しい tty コンテキストを設定できません"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "タイプ %s 用の役割を指定しなければいけません"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "役割 %s 用のデフォルトのタイプを取得できません"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "新しいコンテキストの取得に失敗しました"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "新しい役割 %s の設定に失敗しました"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "新しいタイプ %s の設定に失敗しました"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s は有効なコンテキストではありません"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "古いコンテキストの取得に失敗しました"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "強制モードを決定することができません。"
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "実行コンテキストを %s に設定できません"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "キー作成コンテキストを %s へ設定できません"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "-c または -i のうち一つのみ指定できます"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "無効なファイル記述子の番号: %s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "-%c オプションは編集モードでは無効です。"
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "-%c オプションは編集モードでのみ有効です。"
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: シンボリックリンクの編集は許可されていません"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: 書き込み可能なディレクトリ内のファイルの編集は許可されていません"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "編集セッションの内容が %s 内に残っています"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "グループリストを取得できません"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "シグナル %d のハンドラを保存できません"
+
+#: src/signal.c:101 src/suspend_parent.c:149
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "シグナル %d のハンドラを復元できません"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "資源制御の制限の最大値に達しました"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "ユーザー \"%s\" はプロジェクト \"%s\" のメンバーではありません"
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "起動しているタスクは最後 (final) です"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "プロジェクト \"%s\" に参加できません"
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "プロジェクト \"%s\" 用にはデフォルト割り当てとして受け付けられる資源プールがありません"
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "プロジェクト \"%s\" 用として指定した資源プールは存在しません"
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "プロジェクト \"%s\" 用にデフォルト資源プールを割り当てられませんでした"
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "プロジェクト\"%s\" への setproject に失敗しました"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "警告、プロジェクト \"%s\" への資源制御割り当てに失敗しました"
+
+#: src/sudo.c:214
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo バージョン %s\n"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "configure オプション: %s\n"
+
+#: src/sudo.c:224
+msgid "fatal error, unable to load plugins"
+msgstr "致命的エラー、プラグインをロードできません"
+
+#: src/sudo.c:270
+msgid "plugin did not return a command to execute"
+msgstr "プラグインが実行するべきコマンドを返しませんでした"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "予期しない sudo のモード 0x%x です"
+
+#: src/sudo.c:559
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "あなたは %s データベースに存在しません"
+
+#: src/sudo.c:616
+msgid "unable to determine tty"
+msgstr "tty を特定できません"
+
+#: src/sudo.c:932
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "権限変更不可フラグがセットされていて、sudo を root として実行できません。"
+
+#: src/sudo.c:934
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "sudo をコンテナーで実行しているなら、コンテナーの構成でフラグを無効にする必要があるかもしれません。"
+
+#: src/sudo.c:968
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s は所有者が uid %d である必要があり、かつ setuid が設定されている必要があります"
+
+#: src/sudo.c:971
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "実効 uid が %d ではありません、%s は 'nosuid' が設定されたファイルシステムにあるか、root 権限のないNFSファイルシステムにあるのでは?"
+
+#: src/sudo.c:977
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "実効 uid が %d ではありません、sudo は setuid root を設定してインストールされていますか?"
+
+#: src/sudo.c:993 src/tgetpass.c:332
+msgid "unable to set supplementary group IDs"
+msgstr "追加のグループIDを設定できません"
+
+#: src/sudo.c:1000
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "実行時のグループID (gid) %u を実効グループIDに設定できません"
+
+#: src/sudo.c:1006
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "実行時のグループID (gid) %u をグループIDに設定できません"
+
+#: src/sudo.c:1037
+msgid "argv not set by the security policy"
+msgstr "セキュリティーポリシーにより argv が設定されていません"
+
+#: src/sudo.c:1041
+msgid "envp not set by the security policy"
+msgstr "セキュリティーポリシーにより envp が設定されていません"
+
+#: src/sudo.c:1063
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "予期しない子プロセスの終了コードです: %d"
+
+#: src/sudo.c:1176
+msgid "unable to initialize policy plugin"
+msgstr "ポリシープラグインを初期化できません"
+
+#: src/sudo.c:1238
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "ポリシープラグイン %s には check_policy メソッドが含まれていません"
+
+#: src/sudo.c:1284
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "ポリシープラグイン %s は権限の一覧表示をサポートしていません"
+
+#: src/sudo.c:1328
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "ポリシープラグイン %s は -v オプションをサポートしません"
+
+#: src/sudo.c:1366
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "ポリシープラグイン %s は -k/-K オプションをサポートしません"
+
+#: src/sudo.c:1495
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "I/O プラグイン %s を初期化中にエラーが発生しました"
+
+#: src/sudo.c:1498
+msgid "error initializing I/O plugin"
+msgstr "I/O プラグインを初期化中にエラーが発生しました"
+
+#: src/sudo.c:1647
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "認証プラグイン %s を初期化中にエラーが発生しました"
+
+#: src/sudo.c:1726
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: ログにエラーイベントを書き込むことができません%s%s"
+
+#: src/sudo.c:1762
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: ログに accept イベントを書き込むことができません%s%s"
+
+#: src/sudo.c:1767 src/sudo.c:1805
+msgid "audit plugin error"
+msgstr "認証プラグインエラー"
+
+#: src/sudo.c:1800
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: ログに reject イベントを書き込むことができません%s%s"
+
+#: src/sudo.c:1860
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "承認プラグイン %s を初期化中にエラーが発生しました"
+
+#: src/sudo.c:1930
+msgid "command rejected by approver"
+msgstr "承認者によりコマンドが拒否されました"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "書き込み可能な一時ディレクトリが見つかりません"
+
+#: src/sudo_edit.c:292
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s を修正しないままにします"
+
+#: src/sudo_edit.c:305 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s を変更しません"
+
+#: src/sudo_edit.c:482
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: 内部エラー: パスの数がおかしいです"
+
+#: src/sudo_edit.c:484
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: 一時ファイルを作成することができません"
+
+#: src/sudo_edit.c:486 src/sudo_edit.c:606
+msgid "sesh: killed by a signal"
+msgstr "sesh: シグナルにより kill されました"
+
+#: src/sudo_edit.c:488 src/sudo_edit.c:609
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: 不明なエラー %d"
+
+#: src/sudo_edit.c:599
+msgid "unable to copy temporary files back to their original location"
+msgstr "一時ファイルを元の場所に戻すことができません"
+
+#: src/sudo_edit.c:603
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "一時ファイルのいくつかを元の場所に戻すことができません"
+
+#: src/sudo_edit.c:650
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "ユーザーID (uid) を root (%u) に変更できません"
+
+#: src/sudo_edit.c:664
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "プラグインエラー: sudoedit 用のファイル一覧が無効です"
+
+#: src/sudo_edit.c:685
+msgid "plugin error: missing file list for sudoedit"
+msgstr "プラグインエラー: sudoedit 用のファイル一覧がありません"
+
+#: src/sudo_edit.c:728 src/sudo_edit.c:743
+msgid "unable to read the clock"
+msgstr "時刻を読み込むことができません"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "傍受ポートが設定されていません"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "パスワードの読み込みがタイムしました"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "パスワードが与えられませんでした"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "パスワードを読み込むことができません"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "パスワードを読み取るために端末が必要です。 -S オプションを利用して標準入力から読み取るか、askpass ヘルパーを使うよう設定してください"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "パスワードを尋ねる (askpass) プログラムが指定されていません。 SUDO_ASKPASS を設定し、やり直してください"
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "グループIDを %u に設定できません"
+
+#: src/tgetpass.c:337
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "ユーザーIDを %u に設定できません"
+
+#: src/tgetpass.c:342
+#, c-format
+msgid "unable to run %s"
+msgstr "%s を実行できません"
+
+#: src/utmp.c:283
+msgid "unable to save stdin"
+msgstr "標準入力を保存できません"
+
+#: src/utmp.c:285
+msgid "unable to dup2 stdin"
+msgstr "標準入力へ dup2 を実行できません"
+
+#: src/utmp.c:288
+msgid "unable to restore stdin"
+msgstr "標準入力を復元できません"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s の所有者は uid %d でなければいけません"
+
+#~ msgid "%s must be only be writable by owner"
+#~ msgstr "%s は所有者のみ書き込み可能で無ければいけません"
+
+#~ msgid "insufficient space for execve arguments"
+#~ msgstr "execve の引数のためのスペースが足りません"
+
+#~ msgid "unable to read execve %s for process %d"
+#~ msgstr "execve の %s を読み取れません(プロセス %d)"
+
+#~ msgid "requires at least one argument"
+#~ msgstr "最低でも一つ以上おの引数が必要です"
+
+#~ msgid "unable to run %s as a login shell"
+#~ msgstr "%s をログインシェルとして実行できません"
+
+#~ msgid "unable to dup intercept fd"
+#~ msgstr "傍受fdの dup を実行できません"
+
+#~ msgid "%s: missing message header"
+#~ msgstr "%s: メッセージヘッダーがありません"
+
+#~ msgid "%s: expected message type %d, got %d"
+#~ msgstr "%s: 予期した メッセージタイプは %d, 実際は %d"
+
+#~ msgid "unable to set tty context to %s"
+#~ msgstr "新しい tty コンテキストを %s に設定できません"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s: %s"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s: 短い書き込みです"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "一時ファイルを読み込むことができません"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "重複しているポリシープラグイン \"%s\" を無視します。%s の %d 行目"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "端末 (tty) が存在せず、パスワードを尋ねる (askpass) プログラムが指定されていません"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "不明なユーザーID %u です: 誰ですか?"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "シグナルパイプからの読み込み中にエラーが発生しました"
+
+#~ msgid "internal error, tried allocate zero bytes"
+#~ msgstr "内部エラー、0バイトの確保を試みました"
+
+#~ msgid "unable to set terminal to raw mode"
+#~ msgstr "端末を raw モードに設定できません"
+
+#~ msgid "unable to open socket"
+#~ msgstr "ソケットを開くことができません"
+
+#~ msgid "internal error, tried to emalloc2(0)"
+#~ msgstr "内部エラー、 emalloc2(0) を試みました"
+
+#~ msgid "internal error, tried to ecalloc(0)"
+#~ msgstr "内部エラー、ecalloc(0) を試みました"
+
+#~ msgid "internal error, tried to erealloc(0)"
+#~ msgstr "内部エラー、 erealloc(0) を試みました"
+
+#~ msgid "internal error, tried to erealloc3(0)"
+#~ msgstr "内部エラー、 erealloc3(0) を試みました"
+
+#~ msgid "internal error, tried to erecalloc(0)"
+#~ msgstr "内部エラー、 erecalloc(0) を試みました"
+
+#~ msgid ": "
+#~ msgstr ": "
+
+#~ msgid "select failed"
+#~ msgstr "select に失敗しました"
+
+#~ msgid "load_interfaces: overflow detected"
+#~ msgstr "load_interfaces: オーバーフローが検出されました"
+
+#~ msgid "list user's available commands\n"
+#~ msgstr "ユーザーが使用可能なコマンドを一覧表示する\n"
+
+#~ msgid "run a shell as target user\n"
+#~ msgstr "変更先のユーザーとしてシェルを実行する\n"
+
+#~ msgid "when listing, list specified user's privileges\n"
+#~ msgstr "一覧表示する時に、指定したユーザーの権限を一覧表示する\n"
+
+#~ msgid "internal error, emalloc2() overflow"
+#~ msgstr "内部エラー、 emalloc2() がオーバーフローしました"
+
+#~ msgid "internal error, erealloc3() overflow"
+#~ msgstr "内部エラー、 erealloc3() がオーバーフローしました"
+
+#~ msgid "%s: at least one policy plugin must be specified"
+#~ msgstr "%s: 最低でも一つ以上のポリシープラグインを指定しなければいけません"
+
+#~ msgid "must be setuid root"
+#~ msgstr "setuid root されていなければいけません"
+
+#~ msgid "the argument to -D must be between 1 and 9 inclusive"
+#~ msgstr "-D の引数は 1 から 9 の間でなければいけません"
diff --git a/po/ka.mo b/po/ka.mo
new file mode 100644
index 0000000..d88c221
--- /dev/null
+++ b/po/ka.mo
Binary files differ
diff --git a/po/ka.po b/po/ka.po
new file mode 100644
index 0000000..d48f5e9
--- /dev/null
+++ b/po/ka.po
@@ -0,0 +1,1180 @@
+# Portable object template file for sudo
+# This file is put in the public domain.
+# Todd C. Miller <Todd.Miller@sudo.ws>, 2011-2018
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.12b2\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2022-10-09 09:48-0600\n"
+"PO-Revision-Date: 2022-10-17 09:43+0200\n"
+"Last-Translator: Temuri Doghonadze <temuri.doghonadze@gmail.com>\n"
+"Language-Team: Georgian <(nothing)>\n"
+"Language: ka\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 3.1.1\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "userdb-ის გახსნის შეცდომა"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "რეესტრზე(\"%s\") გადართვის შეცდომა %s-თვის"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "რეესტრის აღდგენის შედომა"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:54 lib/util/json.c:183 lib/util/sudo_conf.c:219
+#: lib/util/sudo_conf.c:305 lib/util/sudo_conf.c:382 lib/util/sudo_conf.c:666
+#: src/conversation.c:80 src/exec_iolog.c:124 src/exec_iolog.c:135
+#: src/exec_iolog.c:212 src/exec_monitor.c:205 src/exec_monitor.c:458
+#: src/exec_monitor.c:464 src/exec_monitor.c:472 src/exec_monitor.c:480
+#: src/exec_monitor.c:487 src/exec_monitor.c:494 src/exec_monitor.c:501
+#: src/exec_monitor.c:508 src/exec_monitor.c:515 src/exec_monitor.c:522
+#: src/exec_monitor.c:529 src/exec_nopty.c:227 src/exec_nopty.c:236
+#: src/exec_nopty.c:243 src/exec_nopty.c:250 src/exec_nopty.c:257
+#: src/exec_nopty.c:264 src/exec_nopty.c:271 src/exec_nopty.c:278
+#: src/exec_nopty.c:285 src/exec_nopty.c:292 src/exec_nopty.c:299
+#: src/exec_nopty.c:306 src/exec_nopty.c:314 src/exec_nopty.c:322
+#: src/exec_nopty.c:732 src/exec_preload.c:341 src/exec_ptrace.c:474
+#: src/exec_ptrace.c:767 src/exec_ptrace.c:982 src/exec_ptrace.c:1094
+#: src/exec_ptrace.c:1269 src/exec_ptrace.c:1611 src/exec_ptrace.c:1638
+#: src/exec_pty.c:506 src/exec_pty.c:687 src/exec_pty.c:873 src/exec_pty.c:882
+#: src/exec_pty.c:889 src/exec_pty.c:896 src/exec_pty.c:903 src/exec_pty.c:910
+#: src/exec_pty.c:917 src/exec_pty.c:924 src/exec_pty.c:931 src/exec_pty.c:938
+#: src/exec_pty.c:945 src/exec_pty.c:953 src/load_plugins.c:157
+#: src/load_plugins.c:182 src/load_plugins.c:218 src/load_plugins.c:451
+#: src/load_plugins.c:457 src/parse_args.c:172 src/parse_args.c:193
+#: src/parse_args.c:267 src/parse_args.c:623 src/parse_args.c:645
+#: src/parse_args.c:670 src/preserve_fds.c:46 src/preserve_fds.c:131
+#: src/selinux.c:89 src/selinux.c:362 src/selinux.c:472 src/selinux.c:489
+#: src/selinux.c:496 src/sesh.c:206 src/sesh.c:240 src/sesh.c:246
+#: src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:639 src/sudo.c:704
+#: src/sudo.c:714 src/sudo.c:741 src/sudo.c:764 src/sudo.c:773 src/sudo.c:782
+#: src/sudo.c:799 src/sudo.c:841 src/sudo.c:851 src/sudo.c:884 src/sudo.c:1112
+#: src/sudo.c:1133 src/sudo.c:1426 src/sudo.c:1595 src/sudo.c:1822
+#: src/sudo.c:2156 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:429
+#: src/sudo_edit.c:438 src/sudo_edit.c:538 src/sudo_edit.c:545
+#: src/sudo_edit.c:673 src/sudo_edit.c:693 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:55
+#: lib/util/json.c:184 lib/util/regex.c:113 lib/util/regex.c:121
+#: lib/util/sudo_conf.c:220 lib/util/sudo_conf.c:305 lib/util/sudo_conf.c:382
+#: lib/util/sudo_conf.c:666 src/conversation.c:81 src/exec_intercept.c:111
+#: src/exec_intercept.c:344 src/exec_intercept.c:504 src/exec_intercept.c:566
+#: src/exec_intercept.c:682 src/exec_intercept.c:806 src/exec_iolog.c:124
+#: src/exec_iolog.c:135 src/exec_iolog.c:212 src/exec_monitor.c:458
+#: src/exec_monitor.c:464 src/exec_monitor.c:472 src/exec_monitor.c:480
+#: src/exec_monitor.c:487 src/exec_monitor.c:494 src/exec_monitor.c:501
+#: src/exec_monitor.c:508 src/exec_monitor.c:515 src/exec_monitor.c:522
+#: src/exec_monitor.c:529 src/exec_nopty.c:227 src/exec_nopty.c:236
+#: src/exec_nopty.c:243 src/exec_nopty.c:250 src/exec_nopty.c:257
+#: src/exec_nopty.c:264 src/exec_nopty.c:271 src/exec_nopty.c:278
+#: src/exec_nopty.c:285 src/exec_nopty.c:292 src/exec_nopty.c:299
+#: src/exec_nopty.c:306 src/exec_nopty.c:314 src/exec_nopty.c:322
+#: src/exec_preload.c:341 src/exec_ptrace.c:474 src/exec_ptrace.c:767
+#: src/exec_ptrace.c:982 src/exec_ptrace.c:1638 src/exec_pty.c:506
+#: src/exec_pty.c:873 src/exec_pty.c:882 src/exec_pty.c:889 src/exec_pty.c:896
+#: src/exec_pty.c:903 src/exec_pty.c:910 src/exec_pty.c:917 src/exec_pty.c:924
+#: src/exec_pty.c:931 src/exec_pty.c:938 src/exec_pty.c:945 src/exec_pty.c:953
+#: src/load_plugins.c:157 src/load_plugins.c:182 src/load_plugins.c:218
+#: src/load_plugins.c:451 src/load_plugins.c:457 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:267 src/parse_args.c:623
+#: src/parse_args.c:645 src/parse_args.c:670 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:230 src/sudo.c:639 src/sudo.c:884 src/sudo.c:1112
+#: src/sudo.c:1133 src/sudo.c:1426 src/sudo.c:1595 src/sudo.c:1822
+#: src/sudo.c:2156 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:429
+#: src/sudo_edit.c:438 src/sudo_edit.c:538 src/sudo_edit.c:545
+#: src/sudo_edit.c:673 src/sudo_edit.c:693 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "მეხსიერების გამოყოფის შეცდომა"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "%.*s-ის აღმოჩენის შეცდომა"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s არსებობს, მაგრამ საქაღალდე არაა (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:677
+#: lib/util/sudo_conf.c:689 lib/util/sudo_conf.c:715 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:371 src/sudo_edit.c:494 src/sudo_edit.c:557
+#, c-format
+msgid "unable to open %s"
+msgstr "%s-ის გახსნის შეცდომა"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "%.*s-ის mkdir-ის შეცდომა"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "%.*s-ის გახსნის შეცდომა"
+
+#: lib/util/regex.c:103
+msgid "regular expression too large"
+msgstr "რეგულარული გამოსახულება ძალიან გრძელია"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "უცნობი სიგნალი"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "არასწორი მნიშვნელობა"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "მნიშვნელობა ძალიან გრძელია"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "მნიშვნელობა ძალიან პატარაა"
+
+#: lib/util/sudo_conf.c:238
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "ბილიკის არასწორი მისამართი (\"%s\") %s-ში, %u ხაზზე"
+
+#: lib/util/sudo_conf.c:404 lib/util/sudo_conf.c:420 lib/util/sudo_conf.c:473
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "%s -ის არასწორი მნიშვნელობა \"%s\", %s-ში, %u-ე ხაზზე"
+
+#: lib/util/sudo_conf.c:441
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "ჯგუფის მხარდაუჭერელი წყარო \"%s\" %s-ში, %u-ე ხაზზე"
+
+#: lib/util/sudo_conf.c:457
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "არასწორი მაქს. ჯგუფები \"%s\" %s-ში, %u-ე ხაზზე"
+
+#: lib/util/sudo_conf.c:692
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s: არ წარმოადგენს ჩვეულებრივ ფაილს"
+
+#: lib/util/sudo_conf.c:695 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s-ის მფლობლის UID-ია %u. უნდა იყოს %u"
+
+#: lib/util/sudo_conf.c:699
+#, c-format
+msgid "%s is world writable"
+msgstr "%s ყველას მიერ ჩაწერადია"
+
+#: lib/util/sudo_conf.c:702
+#, c-format
+msgid "%s is group writable"
+msgstr "%s ჯგუფის მიერ ჩაწერადია"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "შეცდომა AppArmor-ის ჩაკეტილობის დადგენისას"
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "შეცდომა AppArmor-ის პროფილის %s -ზე შეცვლისას"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: შევკვეცო %s ნულ ბაიტამდე? (y/n) [n] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "არ გადავაწერ %s-ს"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "%s-დან წაკითხვა შეუძლებელია"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "%s-ში ჩაწერა შეუძლებელია"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "%s-ის აღმოჩენის შეცდომა"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: არ წარმოადგენს ჩვეულებრივ ფაილს"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: ფაილის არასწორი რეჟიმი: 0%o"
+
+#: src/edit_open.c:331
+msgid "unable to restore current working directory"
+msgstr "მიმდინარე სამუშაო საქაღალდის აღდგენა შეუძლებელია"
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "პრივილეგიების დაყენების შეცდომა"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "შეზღუდული პრივილეგიების დაყენების შეცდომა"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "შესვლის უცნობი კლასი: %s"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "მომხმარებლის კონტექსტის დაყენების შეცდომა"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "პროცესის პრიორიტეტის დაყენების შეცდომა"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "root საქაღალდის %s-ზე გადართვის"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "გამშვებ UID-ზე (%u, %u) გადართვის შეცდომა"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "საქაღალდის შეცვლის შეცდომა: %s"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "%s-დან დაწყებული"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:567 src/exec_monitor.c:569
+#: src/exec_pty.c:225 src/exec_pty.c:1017 src/exec_pty.c:1019 src/signal.c:144
+#: src/signal.c:151 src/signal.c:165 src/suspend_nopty.c:93
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "სიგნაგლისთვის (%d) სახელურის დაყენების შეცდომა"
+
+#: src/exec.c:422
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "ამ სისტემაზე SELinux RBAC-ის გამოყენებისას გადაჭერის რეჟიმი მხარდაუჭერელია"
+
+#: src/exec.c:427
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "ამ სისტემაზე SELinux RBAC-თან ერთად ქვებრძანებების ჟურნალში ჩაწერა შეუძლებელია"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "pRIV_LIMIT-დან PRIV_PROC_EXEC-ის წაშლის შეცდომა"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:165 src/exec_iolog.c:175
+#: src/exec_iolog.c:220 src/exec_iolog.c:227 src/exec_iolog.c:254
+#: src/exec_monitor.c:466 src/exec_monitor.c:474 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_monitor.c:496 src/exec_monitor.c:503
+#: src/exec_monitor.c:510 src/exec_monitor.c:517 src/exec_monitor.c:524
+#: src/exec_monitor.c:531 src/exec_nopty.c:229 src/exec_nopty.c:238
+#: src/exec_nopty.c:245 src/exec_nopty.c:252 src/exec_nopty.c:259
+#: src/exec_nopty.c:266 src/exec_nopty.c:273 src/exec_nopty.c:280
+#: src/exec_nopty.c:287 src/exec_nopty.c:294 src/exec_nopty.c:301
+#: src/exec_nopty.c:308 src/exec_nopty.c:316 src/exec_nopty.c:324
+#: src/exec_nopty.c:383 src/exec_nopty.c:449 src/exec_pty.c:355
+#: src/exec_pty.c:457 src/exec_pty.c:512 src/exec_pty.c:875 src/exec_pty.c:884
+#: src/exec_pty.c:891 src/exec_pty.c:898 src/exec_pty.c:905 src/exec_pty.c:912
+#: src/exec_pty.c:919 src/exec_pty.c:926 src/exec_pty.c:933 src/exec_pty.c:940
+#: src/exec_pty.c:947
+msgid "unable to add event to queue"
+msgstr "რიგში მოვლენის ჩამატების შეცდომა"
+
+#: src/exec_intercept.c:317 src/sudo.c:1018
+msgid "command not set by the security policy"
+msgstr "უსაფრთხოების პოლიტიკის მიერ ბრძანება დაყენებული არაა"
+
+#: src/exec_intercept.c:393 src/exec_intercept.c:421 src/sudo.c:1238
+#: src/sudo.c:1283 src/sudo.c:1327
+msgid "command rejected by policy"
+msgstr "ბრძანება უარყოფილია წესის მიერ"
+
+#: src/exec_intercept.c:491 src/sudo.c:1925
+msgid "approval plugin error"
+msgstr "ნებადამრთველი დამატების შეცდომა"
+
+#: src/exec_intercept.c:508 src/sudo.c:1243 src/sudo.c:1288 src/sudo.c:1332
+#: src/sudo.c:1406
+msgid "policy plugin error"
+msgstr "წესის დამატების შეცდომა"
+
+#: src/exec_intercept.c:543
+msgid "invalid PolicyCheckRequest"
+msgstr "არასწორი PolicyCheckRequest"
+
+#: src/exec_intercept.c:678
+#, c-format
+msgid "client request too large: %zu"
+msgstr "კლიენტის მოთხოვნა ძალიან დიდია: %zu"
+
+#: src/exec_intercept.c:720
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "შეცდომა %s -ის გაშლისას ზომა %zu"
+
+#: src/exec_intercept.c:768
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "type_case-ის მოულოდნელი მნიშვნელობა %d %s-ში %s-დან"
+
+#: src/exec_intercept.c:794
+#, c-format
+msgid "server message too large: %zu"
+msgstr "სერვერის შეტყობინება ძალიან დიდია: %zu"
+
+#: src/exec_iolog.c:323 src/exec_iolog.c:363 src/exec_iolog.c:403
+#: src/exec_iolog.c:454 src/exec_iolog.c:505
+msgid "I/O plugin error"
+msgstr "I/O დამატების შეცდომა"
+
+#: src/exec_iolog.c:327 src/exec_iolog.c:367 src/exec_iolog.c:407
+#: src/exec_iolog.c:458 src/exec_iolog.c:509
+msgid "command rejected by I/O plugin"
+msgstr "ბრძანება უარყოფილია I/O დამატების მიერ"
+
+#: src/exec_iolog.c:556
+msgid "error logging suspend"
+msgstr "ჟურნალში ჩაწერის შეჩერება შეუძლებელია"
+
+#: src/exec_iolog.c:591
+msgid "error changing window size"
+msgstr "ფანჯრის ზომის შეცვლა შეუძლებელია"
+
+#: src/exec_monitor.c:360
+msgid "error reading from socketpair"
+msgstr "socketpair-დან წაკითხვის შეცდომა"
+
+#: src/exec_monitor.c:377
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "blackchannel-ის პასუხის მოულოდნელი ტიპი: %d"
+
+#: src/exec_monitor.c:585
+msgid "unable to set controlling tty"
+msgstr "საკონტროლო tty-ის დაყენების შეცდომა"
+
+#: src/exec_monitor.c:593 src/exec_nopty.c:494 src/exec_nopty.c:504
+#: src/exec_nopty.c:514 src/exec_nopty.c:548 src/exec_pty.c:1088
+#: src/exec_pty.c:1109 src/exec_pty.c:1129 src/tgetpass.c:305
+msgid "unable to create pipe"
+msgstr "ფაიფის შექმნის შეცდომა"
+
+#: src/exec_monitor.c:603
+msgid "unable to receive message from parent"
+msgstr "მშობლისგან შეტყობინების მიღების შეცდომა"
+
+#: src/exec_monitor.c:619 src/exec_nopty.c:591 src/exec_pty.c:1167
+#: src/sudo_edit.c:361 src/tgetpass.c:309
+msgid "unable to fork"
+msgstr "პროცესის განტოტვის შეცდომა"
+
+#: src/exec_monitor.c:623 src/exec_monitor.c:721 src/exec_nopty.c:696
+msgid "unable to restore tty label"
+msgstr "tty-ის ჭდის აღდგენის შეცდომა"
+
+#: src/exec_monitor.c:636 src/sesh.c:217 src/sudo.c:1189
+#, c-format
+msgid "unable to execute %s"
+msgstr "%s-ის გაშვების შეცდომა"
+
+#: src/exec_nopty.c:542 src/exec_pty.c:1026
+msgid "policy plugin failed session initialization"
+msgstr "წესების დამატების შეცდომა სესიის ინიციალიზაციისას"
+
+#: src/exec_nopty.c:557 src/exec_pty.c:995 src/exec_pty.c:1004
+msgid "unable to create sockets"
+msgstr "სოკეტების შექმნის შეცდომა"
+
+#: src/exec_nopty.c:684 src/exec_pty.c:1265
+msgid "error in event loop"
+msgstr "მოვლენების მარყუჟის შეცდომა"
+
+#: src/exec_preload.c:165 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:851 src/sudo.c:486
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "შიდა შეცდომა: %s-ის გადავსება"
+
+#: src/exec_ptrace.c:1078 src/exec_ptrace.c:1103 src/exec_ptrace.c:1909
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "პროცესისთვის (%d) რეგისტრების დაყენება შეუძლებელია"
+
+#: src/exec_ptrace.c:1098 src/exec_ptrace.c:1273 src/exec_ptrace.c:1615
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "პროცესი %d მოულოდნელად დასრულდა"
+
+#: src/exec_ptrace.c:1207
+msgid "unable to set seccomp filter"
+msgstr "seccomp ფილტრის დაყენების შეცდომა"
+
+#: src/exec_ptrace.c:1404
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "ინტერპრეტატორის არგუმენტი. მოველოდი \"%s\", მივიღე \"%s\""
+
+#: src/exec_ptrace.c:1503
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "ბილიკი არ ემთხვევა. მოველოდი \"%s\", მივიღე \"%s\""
+
+#: src/exec_ptrace.c:1512 src/exec_ptrace.c:1519 src/exec_ptrace.c:1532
+#: src/exec_ptrace.c:1540 src/exec_ptrace.c:1546 src/exec_ptrace.c:1552
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "%s[%d] არ ემთხვევა. მოველოდი \"%s\", მივიღე \"%s\""
+
+#: src/exec_ptrace.c:1619
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "პროცესის %d მოულოდნელი სტატუსი 0x%x"
+
+#: src/exec_ptrace.c:1711
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "მოვლენის შეტყობინების მიღების შეცდომა პროცესისთვის %d"
+
+#: src/exec_ptrace.c:1718
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "პროცესისთვის (%d) რეგისტრების მიღება შეუძლებელია"
+
+#: src/exec_pty.c:103
+msgid "unable to allocate pty"
+msgstr "pty-ის გამოყოფის შეცდომა"
+
+#: src/exec_pty.c:263 src/signal.c:101 src/suspend_nopty.c:99
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "სიგნალისთვის სახელურის აღდგენის შეცდომა: %d"
+
+#: src/exec_pty.c:1213
+msgid "unable to send message to monitor process"
+msgstr "მაყურებელი პროცესისთვის შეტყობინების გაგზავნა შეუძლებელია"
+
+#: src/load_plugins.c:109 src/load_plugins.c:123 src/load_plugins.c:129
+#: src/load_plugins.c:279 src/load_plugins.c:289 src/load_plugins.c:299
+#: src/load_plugins.c:346
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "%s-ის შეცდომა %d ხაზზე \"%s\"დამატების ჩატვირთვისას"
+
+#: src/load_plugins.c:125
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s-ის მფლობლის UID %d უნდა იყოს"
+
+#: src/load_plugins.c:131
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "%s ჩაწერადი მხოლოდ მფლობლის მიერ უნდა იყოს"
+
+#: src/load_plugins.c:243 src/load_plugins.c:314
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "ორჯერ აღწერილი დამატება \"%s\", \"%s\"-ში, %d-ე ხაზზე"
+
+#: src/load_plugins.c:281
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "%s-ის ჩატვირთვის შეცდომა: %s"
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "სიმბოლო \"%s\"-ის %s-ში პოვნა შეუძლებელია"
+
+#: src/load_plugins.c:301
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "დამატების შეუთავსებელი ძირითადი ვერსია: %d (ველოდებოდით %d-ს), რომელიც ნაპოვნია %s-ში"
+
+#: src/load_plugins.c:319
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "წესებს დამატების (\"%s\") იგნორი %s-ში, %d-ე ხაზზე"
+
+#: src/load_plugins.c:322
+msgid "only a single policy plugin may be specified"
+msgstr "დაშვებულია წესების მხოლოდ ერთი დამატების მითითება"
+
+#: src/load_plugins.c:348
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "დამატების ტიპი (%d) უცნობია. ნაპოვნია %s-ში"
+
+#: src/load_plugins.c:531
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "წესების დამატება %s არ შეიცავს check_policy მეთოდს"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "გარემოს ცვლადის არასწორი სახელი: %s"
+
+#: src/parse_args.c:317
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "-C -ის არგუმენტი რიცხვი უნდა იყოს, 3 ან მეტი"
+
+#: src/parse_args.c:554
+msgid "you may not specify both the -i and -s options"
+msgstr "-i და -s პარამეტრების ერთად მითითება აკრძალულია"
+
+#: src/parse_args.c:559
+msgid "you may not specify both the -i and -E options"
+msgstr "-i და -E პარამეტრების ერთად მითითება აკრძალულია"
+
+#: src/parse_args.c:569
+msgid "the -E option is not valid in edit mode"
+msgstr "ჩასწორების რეჟიმში -E-ის მითითება აკრძალულია"
+
+#: src/parse_args.c:572
+msgid "you may not specify environment variables in edit mode"
+msgstr "ჩასწორების რეჟიმში გარემოს ცვლადების მითითება არ შეგიძლიათ"
+
+#: src/parse_args.c:582
+msgid "the -U option may only be used with the -l option"
+msgstr "პარამეტრები -U და -I შეუთავსებლებია"
+
+#: src/parse_args.c:586
+msgid "the -A and -S options may not be used together"
+msgstr "პარამეტრები -A და -S შეუთავსებლებია"
+
+#: src/parse_args.c:684
+msgid "sudoedit is not supported on this platform"
+msgstr "ამ პლატფორმაზე sudoedit-ი მხარდაუჭერელია"
+
+#: src/parse_args.c:767
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "შესაძლო პარამეტრებია -e, -h, -I, -K, -l, -s, -v, -V"
+
+#: src/parse_args.c:780
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "-K, -k და -N -დან მხოლოდ ერთ ერთი პარამეტრის მითითებაა შესაძლებელი"
+
+#: src/parse_args.c:796
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - ფაილების სხვა მომხმარებლით ჩასწორება\n"
+"\n"
+
+#: src/parse_args.c:798
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr "%s - sსხვ\n"
+
+#: src/parse_args.c:804
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"პარამეტრები\n"
+
+#: src/parse_args.c:806
+msgid "use a helper program for password prompting"
+msgstr "პაროლის მოსათხოვნად დამხმარე პროგრამის გამოყენება"
+
+#: src/parse_args.c:809
+msgid "use specified BSD authentication type"
+msgstr "bsd ავთენტიკაციის მოთხოვნილი ტიპის გამოყენება"
+
+#: src/parse_args.c:813
+msgid "run command in the background"
+msgstr "ბრძანების ფონურ რეჟიმში გაშვება"
+
+#: src/parse_args.c:816
+msgid "ring bell when prompting"
+msgstr "მოთხოვნისას ზარის დარეკვა"
+
+#: src/parse_args.c:818
+msgid "close all file descriptors >= num"
+msgstr "ყველა იმ ფაილის დესკრიპტორის დახურვა, რომლის ნომერიც >= რიცხვზე"
+
+#: src/parse_args.c:821
+msgid "run command with the specified BSD login class"
+msgstr "ბრძანების BSD-ის მითითებული კლასით გაშვება"
+
+#: src/parse_args.c:824
+msgid "change the working directory before running command"
+msgstr "ბრძანების გაშვებამდე სამუშაო საქაღალდის შეცვლა"
+
+#: src/parse_args.c:827
+msgid "preserve user environment when running command"
+msgstr "ბრძანების გაშვებისას მომხმარებლის გარემოს შენარჩუნება"
+
+#: src/parse_args.c:829
+msgid "preserve specific environment variables"
+msgstr "გარემოს მითითებული ცვლადების შენარჩუნება"
+
+#: src/parse_args.c:831
+msgid "edit files instead of running a command"
+msgstr "ბრძანების გაშვების მაგიერ ფაილების ჩასწორება"
+
+#: src/parse_args.c:834
+msgid "run command as the specified group name or ID"
+msgstr "ბრძანების მითითებული ჯგუფის სახელით ან ID-ით გაშვება"
+
+#: src/parse_args.c:837
+msgid "set HOME variable to target user's home dir"
+msgstr "გარემოს ცვლადის HOME მომხმარებლის საწყის საქაღალდეზე დაყენება"
+
+#: src/parse_args.c:840
+msgid "display help message and exit"
+msgstr "დახმარების გამოტანა და გამოსვლა"
+
+#: src/parse_args.c:842
+msgid "run command on host (if supported by plugin)"
+msgstr "ჰოსტზე ბრძანების გაშვება (თუ მხარდაჭერილია დამატების მიერ)"
+
+#: src/parse_args.c:845
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "შესვლის გარსის სამიზნე მომხმარებლით გაშვება; ასევე შეიძლება მიეთითოს ბრძანებაც"
+
+#: src/parse_args.c:847
+msgid "remove timestamp file completely"
+msgstr "timestamp ფაილის სრულად წაშლა"
+
+#: src/parse_args.c:850
+msgid "invalidate timestamp file"
+msgstr "timestamp ფაილის არასწორად გამოცხადება"
+
+#: src/parse_args.c:853
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "მომხმარებლის პრივილეგიების სიის ან მითითებული ბრძანების გამოტანა; მეტი ინფორმაციისთვის მიუთითეთ ორჯერ"
+
+#: src/parse_args.c:856
+msgid "non-interactive mode, no prompts are used"
+msgstr "არაინტერაქტიური რეჟიმი. შეყვანა მოთხვნილი არ იქნება"
+
+#: src/parse_args.c:859
+msgid "preserve group vector instead of setting to target's"
+msgstr "სამიზნის დაყენების მაგიერ ჯგუფის ვექტორის შენარჩუნება"
+
+#: src/parse_args.c:862
+msgid "use the specified password prompt"
+msgstr "პაროლის მითითებული ტიპის მოთხოვნის გამოყენება"
+
+#: src/parse_args.c:864
+msgid "change the root directory before running command"
+msgstr "ბრძანების გაშვებამდე root საქაღალდის შეცვლა"
+
+#: src/parse_args.c:867
+msgid "create SELinux security context with specified role"
+msgstr "მითითებული როლით SELinux-ის საუფრთხოების კონტექსტის შექმნა"
+
+#: src/parse_args.c:870
+msgid "read password from standard input"
+msgstr "პაროლის სტანდარტული შეტანის მექანიზმიდან წაკითხვა"
+
+#: src/parse_args.c:873
+msgid "run shell as the target user; a command may also be specified"
+msgstr "გარსის სამიზნე მომხმარებლით გაშვება; ასევე შეიძლება მიეთითოს ბრძანებაც"
+
+#: src/parse_args.c:877
+msgid "create SELinux security context with specified type"
+msgstr "მითითებული ტიპის SELinux-ის უსაფრთხოების კონტექსტის შექმნა"
+
+#: src/parse_args.c:880
+msgid "terminate command after the specified time limit"
+msgstr "ბრძანების შესრულების მითითებული დროის შემდეგ შეწყვეტა"
+
+#: src/parse_args.c:883
+msgid "in list mode, display privileges for user"
+msgstr "სიის რეჟიმის დროს მომხმარებლის პრივილეგიების ჩვენება"
+
+#: src/parse_args.c:886
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "ბრძანების მითითებული სახელით ან ID-ით გაშვება (ან ფაილის ჩასწორება)"
+
+#: src/parse_args.c:888
+msgid "display version information and exit"
+msgstr "ვერსიის ჩვენება და გასვლა"
+
+#: src/parse_args.c:891
+msgid "update user's timestamp without running a command"
+msgstr "მომხმარებლის timestamp-ის ბრძანების გაშვების გარეშე განახლება"
+
+#: src/parse_args.c:894
+msgid "stop processing command line arguments"
+msgstr "ბრძანების სტრიქონიდან ჩაწოდებული არგუმენტების დამუშავების შეწყვეტა"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "აუდიტის სისტემის გახსნის შეცდომა"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "აუდიტის შეტყობინების გაგზავნის შეცდომა"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "fgetfilecon %s-ის შეცდომა"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s-ის ჭდეები შეცვლილია"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "%s-ის კონტექსტის აღდგენა შეუძლებელია"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "%s-ის გახსნის შეცდომა. tty-ზე ჭდე თავიდან არ დაედება"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s არ წარმოადგენს სერიულ მოწყობილობას. tty-ზე ჭდე თავიდან არ დაედება"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "tty-ის მიმდინარე კონტექსტის მიღება შეუძლებელია. tty-ზე ჭდე თავიდან არ დაედება"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "უსაფრთხოების არასწორი კლასი: \"chr_file\". tty-ზე ჭდე თავიდან არ დაედება"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "tty-ის ახალი კონტექსტის მიღება შეუძლებელია. tty-ზე ჭდე თავიდან არ დაედება"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "tty-ის ახალი კონტექსტის დაყენება შეუძლებელია"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "გთხოვთ მიუთითოთ %s-ის ტიპის როლი"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "%s-ის ტიპის როლის მიღება შეუძლებელია"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "ახალი კონტექსტის მიღების შეცდომა"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "ახალი როლის (%s) დაყენების შეცდომა"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "ახალი ტიპის (%s) დაყენების შეცდომა"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "არასწორი კონტექსტი: %s"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "ძველი კონტექსტის მიღების შეცდომა"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "selinux-ის რეჟიმის დადგენის შეცდომა."
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "%s-ზე გაშვების კონტექსტის დაყენების შეცდომა"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "%s-ზე გასაღების შექმნის კონტექსტის დაყენების შეცდომა"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "-c და -i -დან მხოლოდ ერთ ერთი პარამეტრის მითითებაა შესაძლებელი"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "ფაილის დესკრიპტორის არასწორი ნომერი: %s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "-%c პარამეტრის გამოყენება ჩასწორების რეჟიმში შეუძლებელია."
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "-%c პარამეტრის გამოყენება მხოლოდ ჩასწორების რეჟიმშია შესაძლებელი."
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: სიმბმულების ჩასწორება შეუძლებელია"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: ჩაწერად საქაღალდეში ფაილების ჩასწორება აკრძალულია"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "ნაპოვნია ჩასწორების სესიის ნარჩენი შემცველობა: %s"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "ჯგუფების სიის მიღების შეცდომა"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "სახელურის შენახვის შეცდომა სიგნალისთვის \"%d\""
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "მიღწეულია რესურსების კონტროლის ლიმიტი"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "მომხმარებელი \"%s\" არ წარმოადგენს ჯგუფ \"%s\"-ის წევრს"
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "ჩაწოდების ამოცანა საბოლოოა"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "პროექტში შეერთების შეცდომა: \"%s\""
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "რესურსების პული, რომელიც ეთანხმება ნაგულისხმებ ბმებს, არ არსებობს პროექტისთვის: \"%s\""
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "რესურსების სპეციალური პული არ არსებობს პროექტისთვის: \"%s\""
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "ნაგულისხმებ რესურსების პულთან მიბმის შეცდომა პროექტისთვის: %s"
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "setproject-ის შეცდომა პროექტისთვის: \"%s\""
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "ყურადღებით. რესურსების კონტროლის მინიჭების შეცდომა პროექტისთვის \"%s\""
+
+#: src/sudo.c:216
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "SUDO-ის ვერსიაა %s\n"
+
+#: src/sudo.c:218
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "მორგების პარამეტრები: %s\n"
+
+#: src/sudo.c:226
+msgid "fatal error, unable to load plugins"
+msgstr "ფატალური შეცდომა. დამატებების ჩატვირთვა შეუძლებელია"
+
+#: src/sudo.c:272
+msgid "plugin did not return a command to execute"
+msgstr "დამატებას შესასრულებელი ბრძანება არ დაუბრუნებია"
+
+#: src/sudo.c:305
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "sudo-ის მოულოდნელი რეჟიმი: 0x%x"
+
+#: src/sudo.c:553
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "ბაზაში \"%s\" თქვენ არ არსებობთ"
+
+#: src/sudo.c:610
+msgid "unable to determine tty"
+msgstr "tty-ის დადგენა შეუძლებელია"
+
+#: src/sudo.c:918
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "დაყენებულია ალამი \"ახალი პრივილეგიების გარეშე\", რომელიც sudo-ს საშუალებას არ აძლევს, root-ით გაეშვას."
+
+#: src/sudo.c:920
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "თუ sudo კონტეინერში ეშვება, ალმის გასათიშად შეიძლება კონტეინერის კონფიგურაციი ცვლილება დაგჭირდეთ."
+
+#: src/sudo.c:954
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s-ის მფლობელი UID %d უნდა იყოს. ასევე დაყენებული უნდა ჰქონდეს setuid ბიტი"
+
+#: src/sudo.c:957
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "მიმდინარე uid არ უდრის %d-ს, არამედ %s-ს, ფაილურ სისტემაზე, რომელსაც პარამეტრად \"nosuid\" აქვს მითითებული.თუ ეს NFS ფაილური სისტემაა root პრივილეგიების გარეშე?"
+
+#: src/sudo.c:963
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "მიმდინარე uid %d-ს არ უდრის. შეამოწმეთ, აქვს sudo-ს setuid ბიტი მინიჭებული?"
+
+#: src/sudo.c:979 src/tgetpass.c:331
+msgid "unable to set supplementary group IDs"
+msgstr "ჯგუფის დამატებითი ID-ების დაყენების შეცდომა"
+
+#: src/sudo.c:986
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "მიმდინარე gid-ის შესრულებად gid(%u)-ად დაყენების შეცდომა"
+
+#: src/sudo.c:992
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "gid-ის შესრულებად gid(%u)-ად დაყენების შეცდომა"
+
+#: src/sudo.c:1022
+msgid "argv not set by the security policy"
+msgstr "უსაფრთხოების პოლიტიკის მიერ argv დაყენებული არაა"
+
+#: src/sudo.c:1026
+msgid "envp not set by the security policy"
+msgstr "უსაფრთხოების პოლიტიკის მიერ envp დაყენებული არაა"
+
+#: src/sudo.c:1048
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "შვილეული პროცესის დასრულების მოულოდნელი პირობა: %d"
+
+#: src/sudo.c:1161
+msgid "unable to initialize policy plugin"
+msgstr "წესების დამატების ინიციაცლიზაციის შეცდომა"
+
+#: src/sudo.c:1223
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "წესების დამატება %s არ შეიცავს check_policy მეთოდს"
+
+#: src/sudo.c:1269
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "წესების დამატება %s-ს პრივილეგიების ჩამოთვლის მხარდაჭერა არ გააჩნია"
+
+#: src/sudo.c:1313
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "წესების დამატება %s-ს -v პარამეტრის მხარდაჭერა არ გააჩნია"
+
+#: src/sudo.c:1351
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "წესების დამატება %s-ს -k/-K პარამეტრების მხარდაჭერა არ გააჩნია"
+
+#: src/sudo.c:1480
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "i/o დამატების (%s) ინიციალიზაციის შეცდომა"
+
+#: src/sudo.c:1483
+msgid "error initializing I/O plugin"
+msgstr "i/o დამატების ინიციალიზაციის შეცდომა"
+
+#: src/sudo.c:1632
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "აუდიტის დამატების (%s) ინიციალიზაციის შეცდომა"
+
+#: src/sudo.c:1711
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: ჟურნალში შეცდომის მოვლენის ჩასწერის შეცდომა (%s%s)"
+
+#: src/sudo.c:1747
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: ჟურნალში თანხმობის მოვლენის ჩასწერის შეცდომა (%s%s)"
+
+#: src/sudo.c:1752 src/sudo.c:1790
+msgid "audit plugin error"
+msgstr "აუდიტის დამატების შეცდომა"
+
+#: src/sudo.c:1785
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: ჟურნალში უარყოფის მოვლენის ჩასწერის შეცდომა (%s%s)"
+
+#: src/sudo.c:1845
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "ნებადამრთველი დამატების (%s)"
+
+#: src/sudo.c:1915
+msgid "command rejected by approver"
+msgstr "ბრძანება უარყოფილია ნებადამრთველის მიერ"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "არცერთი დროებითი საქაღალდე ჩაწერადი არაა"
+
+#: src/sudo_edit.c:291
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s არ შეცვლილა"
+
+#: src/sudo_edit.c:304 src/sudo_edit.c:569
+#, c-format
+msgid "%s unchanged"
+msgstr "%s შეუცვლელია"
+
+#: src/sudo_edit.c:481
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: შიდა შეცდომა: ბილიკების კენტი რიცხვი"
+
+#: src/sudo_edit.c:483
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: დროებითი ფაილების შექმნის შეცდომა"
+
+#: src/sudo_edit.c:485 src/sudo_edit.c:604
+msgid "sesh: killed by a signal"
+msgstr "sesh: გარდაიცვალა სიგნალით"
+
+#: src/sudo_edit.c:487 src/sudo_edit.c:607
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: უცნობი შეცდომა (%d)"
+
+#: src/sudo_edit.c:597
+msgid "unable to copy temporary files back to their original location"
+msgstr "დროებითი ფაილების თავიანთ პირველად მდებარეობაზე კოპირების შეცდომა"
+
+#: src/sudo_edit.c:601
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "ზოგიერთი დროებითი ფაილის პირველად მდებარეობაზე კოპირების შეცდომა"
+
+#: src/sudo_edit.c:645
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "uid-ის root-ზე(%u) გადართვის შეცდომა"
+
+#: src/sudo_edit.c:666
+msgid "plugin error: missing file list for sudoedit"
+msgstr "დამატების შეცდომა: sudoedit-ს ფაილების სია ესაჭიროება"
+
+#: src/sudo_edit.c:709 src/sudo_edit.c:723
+msgid "unable to read the clock"
+msgstr "საათის წაკითხვის შეცდომა"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "გადაჭერის პორტი დაყენებული არაა"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "პაროლის წაკითხვის ვადა გავიდა"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "პაროლი მითითებული არაა"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "პაროლის წაკითხვის შეცდომა"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "პაროლის წასაკითხად აუცილებელია ტერმინალი; ან გამოიყენეთ -S პარამეტრი, ან askpass-ის ტიპის დამხმარე მოირგეთ"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "askpass-ის ტიპის პროგრამა მითითებული არაა. სცადეთ დააყენოთ SUDO_ASKPASS"
+
+#: src/tgetpass.c:326
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "gid-ის %u-ზე დაყენების შეცდომა"
+
+#: src/tgetpass.c:336
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "uid-ის %u-ზე დაყენების შეცდომა"
+
+#: src/tgetpass.c:341
+#, c-format
+msgid "unable to run %s"
+msgstr "%s-ის გაშვების შეცდომა"
+
+#: src/utmp.c:288
+msgid "unable to save stdin"
+msgstr "stdin-ის შენახვის შეცდომა"
+
+#: src/utmp.c:290
+msgid "unable to dup2 stdin"
+msgstr "stdin-ის dup2-ის შეცდომა"
+
+#: src/utmp.c:293
+msgid "unable to restore stdin"
+msgstr "stdin-ის აღდგენის შეცდომა"
diff --git a/po/ko.mo b/po/ko.mo
new file mode 100644
index 0000000..4d08cd5
--- /dev/null
+++ b/po/ko.mo
Binary files differ
diff --git a/po/ko.po b/po/ko.po
new file mode 100644
index 0000000..bdca1b2
--- /dev/null
+++ b/po/ko.po
@@ -0,0 +1,1255 @@
+# Korean translation for sudo
+# This file is distributed under the same license as the sudo package.
+# Todd C. Miller <Todd.Miller@courtesan.com>, 2011-2015
+# Seong-ho Cho <darkcircle.0426@gmail.com>, 2016-2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.14b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-06-07 13:27-0600\n"
+"PO-Revision-Date: 2023-06-09 11:34+0900\n"
+"Last-Translator: Seong-ho Cho <darkcircle.0426@gmail.com>\n"
+"Language-Team: Korean <translation-team-ko@googlegroups.com>\n"
+"Language: ko\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 3.0.1\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "사용자 DB를 열 수 없습니다"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "%2$s의 \"%1$s\" 레지스트리로 전환할 수 없습니다"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "레지스트리를 복원할 수 없습니다"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:78 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:171 src/exec_monitor.c:418
+#: src/exec_monitor.c:424 src/exec_monitor.c:432 src/exec_monitor.c:440
+#: src/exec_monitor.c:447 src/exec_monitor.c:454 src/exec_monitor.c:461
+#: src/exec_monitor.c:468 src/exec_monitor.c:475 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:744 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1096
+#: src/exec_ptrace.c:1271 src/exec_ptrace.c:1624 src/exec_ptrace.c:1651
+#: src/exec_ptrace.c:1841 src/exec_pty.c:581 src/exec_pty.c:765
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:193 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:240
+#: src/sesh.c:246 src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:644
+#: src/sudo.c:709 src/sudo.c:719 src/sudo.c:746 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:787 src/sudo.c:805 src/sudo.c:846 src/sudo.c:855 src/sudo.c:865
+#: src/sudo.c:898 src/sudo.c:1127 src/sudo.c:1148 src/sudo.c:1441
+#: src/sudo.c:1610 src/sudo.c:1837 src/sudo.c:2171 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:430 src/sudo_edit.c:439
+#: src/sudo_edit.c:540 src/sudo_edit.c:547 src/sudo_edit.c:692
+#: src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:79 src/exec_intercept.c:111 src/exec_intercept.c:350
+#: src/exec_intercept.c:525 src/exec_intercept.c:589 src/exec_intercept.c:713
+#: src/exec_intercept.c:837 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:418 src/exec_monitor.c:424
+#: src/exec_monitor.c:432 src/exec_monitor.c:440 src/exec_monitor.c:447
+#: src/exec_monitor.c:454 src/exec_monitor.c:461 src/exec_monitor.c:468
+#: src/exec_monitor.c:475 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1651 src/exec_ptrace.c:1842 src/exec_pty.c:581
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:228 src/sudo.c:644 src/sudo.c:898 src/sudo.c:1127
+#: src/sudo.c:1148 src/sudo.c:1441 src/sudo.c:1610 src/sudo.c:1837
+#: src/sudo.c:2171 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:430
+#: src/sudo_edit.c:439 src/sudo_edit.c:540 src/sudo_edit.c:547
+#: src/sudo_edit.c:692 src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "메모리를 할당할 수 없습니다"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "%.*s의 상태를 가져올 수 없습니다"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s(이)가 있지만 디렉터리는 아닙니다 (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:664
+#: lib/util/sudo_conf.c:683 lib/util/sudo_conf.c:710 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:495 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "%s을(를) 열 수 없습니다"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "%.*s 디렉터리를 새로 만들 수 없습니다"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "%.*s을(를) 열 수 없습니다"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "정규 표현식이 너무 깁니다"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "알 수 없는 시그널"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "부적절한 값"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "값이 너무 큽니다"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "값이 너무 작습니다"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "%2$s의 %3$u번째 줄에 부적절한 경로 값 \"%1$s\""
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "%3$s의 %4$u번째 줄에 %1$s의 부적절한 값 \"%2$s\""
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "%2$s의 %3$u번째 줄에 지원하지 않는 그룹 원본 \"%1$s\""
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "%2$s의 %3$u번째 줄에 부적절한 최대 그룹 값 \"%1$s\""
+
+#: lib/util/sudo_conf.c:686
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s은(는) 일반 파일이 아닙니다"
+
+#: lib/util/sudo_conf.c:689 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s은(는) %u uid에서 소유하고 있지만 %u uid가 소유해야 합니다"
+
+#: lib/util/sudo_conf.c:693
+#, c-format
+msgid "%s is world writable"
+msgstr "%s에 모두가 기록할 수 있습니다"
+
+#: lib/util/sudo_conf.c:696
+#, c-format
+msgid "%s is group writable"
+msgstr "%s에 그룹 구성원이 기록할 수 있습니다"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "AppArmor 격리 여부를 알 수 없습니다"
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "AppArmor 프로파일을 %s(으)로 바꿀 수 없습니다"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: %s 문자열을 0 바이트로 자릅니까? (y/n) [n] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "%s 덮어쓰지 않음"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "%s을(를) 읽을 수 없습니다"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "%s에 기록할 수 없습니다"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "%s의 상태를 가져올 수 없습니다"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: 일반 파일 아님"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: 잘못된 파일 모드: 0%o"
+
+#: src/edit_open.c:333
+msgid "unable to restore current working directory"
+msgstr "현재 작업 디렉터리를 복원할 수 없습니다"
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "권한을 설정할 수 없습니다"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "권한 한계를 설정할 수 없습니다"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "알 수 없는 로그인 클래스 %s"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "사용자 컨텍스트를 설정할 수 없습니다"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "프로세스 우선순위를 설정할 수 없습니다"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "루트를 %s(으)로 바꿀 수 없습니다"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "실행 uid로 바꿀 수 없습니다 (%u, %u)"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "%s 디렉터리로 바꿀 수 없습니다"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "%s에서 시작 중"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:552 src/exec_monitor.c:554
+#: src/exec_pty.c:1122 src/exec_pty.c:1124 src/signal.c:144 src/signal.c:151
+#: src/signal.c:165 src/suspend_parent.c:143
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "%d 시그널의 핸들러를 설정할 수 없습니다"
+
+#: src/exec.c:424
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "이 시스템의 SELinux RBAC에서는 가로채기 모드를 지원하지 않습니다"
+
+#: src/exec.c:429
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "이 시스템의 SELinux RBAC에서는 하위 명령을 기록할 수 없습니다"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "PRIV_LIMIT에서 PRIV_PROC_EXEC를 제거할 수 없습니다"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:163 src/exec_iolog.c:173
+#: src/exec_iolog.c:218 src/exec_iolog.c:225 src/exec_iolog.c:252
+#: src/exec_monitor.c:426 src/exec_monitor.c:434 src/exec_monitor.c:442
+#: src/exec_monitor.c:449 src/exec_monitor.c:456 src/exec_monitor.c:463
+#: src/exec_monitor.c:470 src/exec_monitor.c:477 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:457 src/exec_pty.c:432
+#: src/exec_pty.c:537 src/exec_pty.c:587 src/exec_pty.c:965 src/exec_pty.c:974
+#: src/exec_pty.c:981 src/exec_pty.c:988 src/exec_pty.c:995
+#: src/exec_pty.c:1002 src/exec_pty.c:1009 src/exec_pty.c:1016
+#: src/exec_pty.c:1023 src/exec_pty.c:1030 src/exec_pty.c:1037
+#: src/exec_pty.c:1044
+msgid "unable to add event to queue"
+msgstr "큐에 이벤트를 추가할 수 없습니다"
+
+#: src/exec_intercept.c:323 src/sudo.c:1033
+msgid "command not set by the security policy"
+msgstr "보안 정책에 따라 명령을 설정하지 않았습니다"
+
+#: src/exec_intercept.c:401 src/exec_intercept.c:441 src/sudo.c:1253
+#: src/sudo.c:1298 src/sudo.c:1342
+msgid "command rejected by policy"
+msgstr "정책을 통해 명령을 거부 했습니다"
+
+#: src/exec_intercept.c:512 src/sudo.c:1940
+msgid "approval plugin error"
+msgstr "승인 플러그인 오류"
+
+#: src/exec_intercept.c:537 src/sudo.c:1258 src/sudo.c:1303 src/sudo.c:1347
+#: src/sudo.c:1421
+msgid "policy plugin error"
+msgstr "정책 플러그인 오류"
+
+#: src/exec_intercept.c:566
+msgid "invalid PolicyCheckRequest"
+msgstr "부적절한 PolicyCheckRequest"
+
+#: src/exec_intercept.c:709
+#, c-format
+msgid "client request too large: %zu"
+msgstr "클라이언트 요청이 너무 깁니다: %zu"
+
+#: src/exec_intercept.c:751
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "%2$zu 크기의 %1$s을(를) 언팩할 수 없습니다"
+
+#: src/exec_intercept.c:799
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "%3$s의 %2$s에서 예기치 못한 type_case 값 %1$d번"
+
+#: src/exec_intercept.c:825
+#, c-format
+msgid "server message too large: %zu"
+msgstr "서버 메시지 길이가 너무 깁니다: %zu"
+
+#: src/exec_iolog.c:321 src/exec_iolog.c:361 src/exec_iolog.c:401
+#: src/exec_iolog.c:452 src/exec_iolog.c:503
+msgid "I/O plugin error"
+msgstr "입출력 플러그인 오류"
+
+#: src/exec_iolog.c:325 src/exec_iolog.c:365 src/exec_iolog.c:405
+#: src/exec_iolog.c:456 src/exec_iolog.c:507
+msgid "command rejected by I/O plugin"
+msgstr "입출력 플러그인에서 명령을 거부했습니다"
+
+#: src/exec_iolog.c:555
+msgid "error logging suspend"
+msgstr "오류 로깅 대기"
+
+#: src/exec_iolog.c:590
+msgid "error changing window size"
+msgstr "윈도우 크기 변경 오류"
+
+#: src/exec_monitor.c:328
+msgid "error reading from socketpair"
+msgstr "소켓쌍 읽기 오류"
+
+#: src/exec_monitor.c:340
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "백 채널에 잘못된 응답 형식: %d"
+
+#: src/exec_monitor.c:566
+msgid "unable to set controlling tty"
+msgstr "처리 tty를 설정할 수 없습니다"
+
+#: src/exec_monitor.c:574 src/exec_nopty.c:504 src/exec_nopty.c:514
+#: src/exec_nopty.c:524 src/exec_nopty.c:560 src/exec_pty.c:1195
+#: src/exec_pty.c:1222 src/exec_pty.c:1242 src/exec_pty.c:1262
+#: src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr "파이프를 만들 수 없습니다"
+
+# parent가 정확히 무슨 의미인지 알 수 없음
+#: src/exec_monitor.c:584
+msgid "unable to receive message from parent"
+msgstr "상위로부터 메시지를 받을 수 없습니다"
+
+#: src/exec_monitor.c:600 src/exec_nopty.c:603 src/exec_pty.c:1303
+#: src/sudo_edit.c:361 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr "포킹할 수 없습니다"
+
+#: src/exec_monitor.c:604 src/exec_monitor.c:700 src/exec_nopty.c:708
+msgid "unable to restore tty label"
+msgstr "tty 레이블을 복원할 수 없습니다"
+
+#: src/exec_monitor.c:615 src/sesh.c:217 src/sudo.c:1204
+#, c-format
+msgid "unable to execute %s"
+msgstr "%s을(를) 실행할 수 없습니다"
+
+#: src/exec_nopty.c:554 src/exec_pty.c:1131
+msgid "policy plugin failed session initialization"
+msgstr "정책 플러그인에서 세션 초기화에 실패했습니다"
+
+#: src/exec_nopty.c:569 src/exec_pty.c:1100 src/exec_pty.c:1109
+msgid "unable to create sockets"
+msgstr "소켓을 만들 수 없습니다"
+
+#: src/exec_nopty.c:696 src/exec_pty.c:1406
+msgid "error in event loop"
+msgstr "이벤트 루프에 오류"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:852 src/sudo.c:488
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "내부 오류, %s 오버플로우"
+
+#: src/exec_ptrace.c:1080 src/exec_ptrace.c:1105 src/exec_ptrace.c:1925
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "프로세스 %d번의 레지스터를 설정할 수 없습니다"
+
+#: src/exec_ptrace.c:1100 src/exec_ptrace.c:1275 src/exec_ptrace.c:1628
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "프로세스 %d번이 갑자기 끝났습니다"
+
+#: src/exec_ptrace.c:1209
+msgid "unable to set seccomp filter"
+msgstr "seccomp 필터를 설정할 수 없습니다"
+
+#: src/exec_ptrace.c:1406
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "해석기 인자에서 \"%s\"이(가) 필요하지만 \"%s\"을(를) 지정했습니다"
+
+#: src/exec_ptrace.c:1505
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "경로 이름이 일치하지 않습니다. \"%s\"을(를) 예상했지만, \"%s\"이(가) 나왔습니다"
+
+#: src/exec_ptrace.c:1514 src/exec_ptrace.c:1521 src/exec_ptrace.c:1545
+#: src/exec_ptrace.c:1553 src/exec_ptrace.c:1559 src/exec_ptrace.c:1565
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "%s[%d]이(가) 일치하지 않습니다. \"%s\"을(를) 예상했지만, \"%s\"이(가) 나왔습니다"
+
+#: src/exec_ptrace.c:1632
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "프로세스 %d번이 갑자기 0x%x 상태를 나타냈습니다"
+
+#: src/exec_ptrace.c:1723
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "프로세스 %d번의 이벤트 메시지를 가져올 수 없습니다"
+
+#: src/exec_ptrace.c:1730
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "프로세스 %d번의 레지스터를 가져올 수 없습니다"
+
+#: src/exec_pty.c:84
+msgid "unable to allocate pty"
+msgstr "pty를 할당할 수 없습니다"
+
+#: src/exec_pty.c:131 src/exec_pty.c:284 src/tgetpass.c:251
+msgid "unable to restore terminal settings"
+msgstr "터미널 설정을 복원할 수 없습니다"
+
+#: src/exec_pty.c:243
+msgid "unable to set handler for SIGCONT"
+msgstr "SIGCONT 시그널의 핸들러를 설정할 수 없습니다"
+
+#: src/exec_pty.c:293
+#, c-format
+msgid "unable to set handler for SIG%s"
+msgstr "SIG%s 시그널의 핸들러를 설정할 수 없습니다"
+
+#: src/exec_pty.c:317
+#, c-format
+msgid "unable to restore handler for SIG%s"
+msgstr "SIG%s 시그널의 핸들러를 복원할 수 없습니다"
+
+#: src/exec_pty.c:345
+msgid "unable to restore handler for SIGCONT"
+msgstr "SIGCONT 시그널의 핸들러를 복원할 수 없습니다"
+
+#: src/exec_pty.c:1353
+msgid "unable to send message to monitor process"
+msgstr "감사 프로세스에 메시지를 보낼 수 없습니다"
+
+#: src/load_plugins.c:75 src/load_plugins.c:222 src/load_plugins.c:232
+#: src/load_plugins.c:242 src/load_plugins.c:289
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "%s의 %d번째 줄에서 \"%s\" 플러그인을 불러오는 중 오류"
+
+#: src/load_plugins.c:186 src/load_plugins.c:257
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "%2$s의 %3$d번째 줄에서 \"%1$s\" 중복 플러그인 무시"
+
+#: src/load_plugins.c:224
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "%s을(를) 불러올 수 없습니다: %s"
+
+#: src/load_plugins.c:234
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "%2$s에서 \"%1$s\" 심볼을 찾을 수 없습니다"
+
+#: src/load_plugins.c:244
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "%3$s에 주 버전이(%2$d을(를) 기대했지만) %1$d인 비호환 플러그인이 있습니다"
+
+#: src/load_plugins.c:262
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "%2$s의 %3$d번째 줄에서 \"%1$s\" 정책 플러그인 무시"
+
+#: src/load_plugins.c:265
+msgid "only a single policy plugin may be specified"
+msgstr "단일 정책 플러그인을 지정하십시오"
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "%2$s에 알 수 없는 정책 유형 %1$d이(가) 있습니다"
+
+#: src/load_plugins.c:474
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "%s 정책 플러그인에 check_policy 메서드가 없습니다"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "부적절한 환경 변수 이름: %s"
+
+#: src/parse_args.c:319
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "-C의 인자 값은 3보다 크거나 같아야 합니다"
+
+#: src/parse_args.c:556
+msgid "you may not specify both the -i and -s options"
+msgstr "-i 옵션과 -s 옵션을 함께 지정할 수 없습니다"
+
+#: src/parse_args.c:561
+msgid "you may not specify both the -i and -E options"
+msgstr "-i 옵션과 -E 옵션을 함께 지정할 수 없습니다"
+
+#: src/parse_args.c:571
+msgid "the -E option is not valid in edit mode"
+msgstr "-E 옵션은 편집 모드에서 유효하지 않습니다"
+
+#: src/parse_args.c:574
+msgid "you may not specify environment variables in edit mode"
+msgstr "편집 모드에서 환경 변수를 지정할 수 없습니다"
+
+#: src/parse_args.c:584
+msgid "the -U option may only be used with the -l option"
+msgstr "-U 옵션에는 -l 옵션만 함께 쓸 수 있습니다"
+
+#: src/parse_args.c:588
+msgid "the -A and -S options may not be used together"
+msgstr "-A 옵션과 -S 옵션을 함께 쓸 수 없습니다"
+
+#: src/parse_args.c:686
+msgid "sudoedit is not supported on this platform"
+msgstr "이 플랫폼에서 sudoedit를 지원하지 않습니다"
+
+#: src/parse_args.c:744
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "-e, -h, -i, -K, -l, -s, -v, -V 옵션 중 하나를 지정해야 합니다"
+
+#: src/parse_args.c:757
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "-K, -k, -N 옵션 중 하나만 지정해야합니다"
+
+#: src/parse_args.c:778
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - 다른 사용자 권한으로 파일을 편집합니다\n"
+"\n"
+
+#: src/parse_args.c:780
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - 다른 사용자 권한으로 명령을 실행합니다\n"
+"\n"
+
+#: src/parse_args.c:785
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"옵션:\n"
+
+#: src/parse_args.c:787
+msgid "use a helper program for password prompting"
+msgstr "암호 질문에 보조 프로그램 활용"
+
+#: src/parse_args.c:790
+msgid "use specified BSD authentication type"
+msgstr "지정 BSD 인증 형식 활용"
+
+#: src/parse_args.c:794
+msgid "run command in the background"
+msgstr "백그라운드에서 명령 실행"
+
+#: src/parse_args.c:797
+msgid "ring bell when prompting"
+msgstr "프롬프트를 띄울 때 알림 소리를 냅니다"
+
+#: src/parse_args.c:799
+msgid "close all file descriptors >= num"
+msgstr "num 보다 크거나 같은 모든 파일 서술자를 닫습니다"
+
+#: src/parse_args.c:802
+msgid "run command with the specified BSD login class"
+msgstr "지정 BSD 로그인 클래스로 명령을 실행합니다"
+
+#: src/parse_args.c:805
+msgid "change the working directory before running command"
+msgstr "명령 실행 전 작업 디렉터리를 바꿉니다"
+
+#: src/parse_args.c:808
+msgid "preserve user environment when running command"
+msgstr "명령을 실행할 때 사용자 환경을 유지합니다"
+
+#: src/parse_args.c:810
+msgid "preserve specific environment variables"
+msgstr "지정 환경 변수 값을 유지합니다"
+
+#: src/parse_args.c:812
+msgid "edit files instead of running a command"
+msgstr "명령을 실행하는 대신 파일을 편집합니다"
+
+#: src/parse_args.c:815
+msgid "run command as the specified group name or ID"
+msgstr "지정 그룹 이름 또는 ID로 명령을 실행합니다"
+
+#: src/parse_args.c:818
+msgid "set HOME variable to target user's home dir"
+msgstr "대상 사용자의 내 폴더에 HOME 변수를 지정합니다"
+
+#: src/parse_args.c:821
+msgid "display help message and exit"
+msgstr "도움말을 보여주고 빠져나갑니다"
+
+#: src/parse_args.c:823
+msgid "run command on host (if supported by plugin)"
+msgstr "(플러그인에서 지원한다면)호스트에서 명령을 실행합니다"
+
+#: src/parse_args.c:826
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "대상 사용자 자격으로 셸에 로그인하며 명령을 지정할 수 있습니다"
+
+#: src/parse_args.c:828
+msgid "remove timestamp file completely"
+msgstr "타임스탬프 파일을 완전히 제거합니다"
+
+#: src/parse_args.c:831
+msgid "invalidate timestamp file"
+msgstr "타임스탬프 파일을 초기화합니다"
+
+#: src/parse_args.c:834
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "사용자 권한을 보여주거나 지정 명령을 확인합니다. 긴 형식으로 보려면 옵션을 두 번 사용하십시오"
+
+#: src/parse_args.c:837
+msgid "non-interactive mode, no prompts are used"
+msgstr "비대화형 모드. 프롬프트를 사용하지 않습니다"
+
+#: src/parse_args.c:840
+msgid "preserve group vector instead of setting to target's"
+msgstr "대상을 설정하는 대신 그룹 벡터를 유지합니다"
+
+#: src/parse_args.c:843
+msgid "use the specified password prompt"
+msgstr "지정 암호 프롬프트를 활용합니다"
+
+#: src/parse_args.c:845
+msgid "change the root directory before running command"
+msgstr "명령 실행 전 루트 디렉터리를 바꿉니다"
+
+#: src/parse_args.c:848
+msgid "create SELinux security context with specified role"
+msgstr "지정 역할을 지닌 SELinux 보안 컨텍스트를 만듭니다"
+
+#: src/parse_args.c:851
+msgid "read password from standard input"
+msgstr "표준 입력으로 암호를 입력 받습니다"
+
+#: src/parse_args.c:854
+msgid "run shell as the target user; a command may also be specified"
+msgstr "셸을 대상 사용자 명의로 실행하며 명령을 지정할 수 있습니다"
+
+#: src/parse_args.c:858
+msgid "create SELinux security context with specified type"
+msgstr "지정 유형의 SELinux 보안 컨텍스트를 만듭니다"
+
+#: src/parse_args.c:861
+msgid "terminate command after the specified time limit"
+msgstr "지정 제한 시간 이후로 명령 실행을 멈춥니다"
+
+#: src/parse_args.c:864
+msgid "in list mode, display privileges for user"
+msgstr "목록 모드에서 사용자 권한을 보여줍니다"
+
+#: src/parse_args.c:867
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "지정한 사용자 이름 또는 ID로 명령을 실행(또는 파일 편집)"
+
+#: src/parse_args.c:869
+msgid "display version information and exit"
+msgstr "버전 정보를 보여주고 나갑니다"
+
+#: src/parse_args.c:872
+msgid "update user's timestamp without running a command"
+msgstr "명령을 실행하지 않고 사용자 타임스탬프를 업데이트합니다"
+
+#: src/parse_args.c:875
+msgid "stop processing command line arguments"
+msgstr "명령행 인자 처리를 멈춥니다"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "감사 시스템을 열 수 없습니다"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "감사 메시지를 보낼 수 없습니다"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "%s에 fgetfilecon을 실행할 수 없습니다"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s에서 레이블을 바꾸었습니다"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "%s의 컨텍스트를 복원할 수 없습니다"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "%s을(를) 열 수 없어 tty의 레이블을 다시 지정하지 않습니다"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s은(는) 문자 장치가 아니어서 tty에 레이블링을 다시 하지 않습니다"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "현재 tty 컨텍스트를 가져올 수 없어 tty의 레이블을 다시 지정하지 않습니다"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "\"chr_file\"의 보안 등급을 알 수 없어, tty의 레이블을 다시 지정하지 않습니다"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "새 tty 컨텍스트를 가져올 수 없습니다"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "새 tty 컨텍스트를 설정할 수 없습니다"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "%s 유형의 역할을 지정해야 합니다"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "%s 역할의 기본 유형을 가져올 수 없습니다"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "새 컨텍스트 가져오기에 실패했습니다"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "새 %s 역할 설정에 실패했습니다"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "새 %s 유형 설정에 실패했습니다"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "올바르지 않은 %s 컨텍스트 입니다"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "오래된 컨텍스트 가져오기에 실패했습니다"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "강제 모드로 지정할 수 없습니다."
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "exec 컨텍스트를 %s(으)로 설정할 수 없습니다"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "키 생성 컨텍스트를 %s(으)로 설정할 수 없습니다"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "-c, -i 옵션 중 하나만 지정해야합니다"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "부적절한 파일 서술자 번호: %s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "-%c 옵션은 편집 모드에서 사용하면 안됩니다."
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "-%c 옵션은 편집 모드에서만 사용해야합니다."
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: 심볼릭 링크 편집을 허용하지 않습니다"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: 기록 가능한 디렉터리에서 파일 편집을 허용하지 않습니다"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "%s에 편집 세션 내용 남음"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "그룹 목록을 가져올 수 없습니다"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "%d 시그널의 핸들러를 저장할 수 없습니다"
+
+#: src/signal.c:101 src/suspend_parent.c:149
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "%d 시그널의 핸들러를 복원할 수 없습니다"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "자원 처리 한계에 도달했습니다"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "\"%s\" 사용자는 \"%s\" 프로젝트의 구성원이 아닙니다"
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "실행 작업이 마지막입니다"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "\"%s\" 프로젝트에 참여할 수 없습니다"
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "어떤 자원 풀에서도 \"%s\" 프로젝트에 있는 기본 바인딩을 수용하지 않습니다"
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "\"%s\" 프로젝트에 지정한 자원 풀이 없습니다"
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "\"%s\" 프로젝트에 기본 자원 풀을 바인딩할 수 없습니다"
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "\"%s\" 프로젝트에서 setproject에 실패했습니다"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "경고! \"%s\" 프로젝트에 자원 처리 할당에 실패했습니다"
+
+#: src/sudo.c:214
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "sudo 버전 %s\n"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "설정 옵션: %s\n"
+
+#: src/sudo.c:224
+msgid "fatal error, unable to load plugins"
+msgstr "치명적인 오류. 플러그인을 불러올 수 없습니다"
+
+#: src/sudo.c:270
+msgid "plugin did not return a command to execute"
+msgstr "플러그인에서 실행할 명령을 반환하지 않았습니다"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "예상치 못한 sudo 모드 0x%x"
+
+#: src/sudo.c:559
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "%s 데이터베이스에 없는 사용자입니다"
+
+#: src/sudo.c:616
+msgid "unable to determine tty"
+msgstr "tty를 지정할 수 없습니다"
+
+#: src/sudo.c:932
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "sudo를 루트 권한으로 실행하지 못하게 하는 \"no new privileges\" 플래그를 설정했습니다."
+
+#: src/sudo.c:934
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "컨테이너에서 sudo를 실행할 때, 플래그를 끄는 컨테이너 설정이 필요할 수 있습니다."
+
+#: src/sudo.c:968
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s은(는) %d uid를 소유해야 하며 setuid 비트를 설정해야 합니다"
+
+#: src/sudo.c:971
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "%d은(는) 유효한 uid가 아닙니다. %s은(는) 'nosuid' 옵션을 설정한 파일 시스템이거나 루트 권한이 없는 NFS 파일 시스템입니까?"
+
+#: src/sudo.c:977
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "%d은(는) 유효한 uid가 아닙니다. sudo에 setuid root를 설치했습니까?"
+
+#: src/sudo.c:993 src/tgetpass.c:332
+msgid "unable to set supplementary group IDs"
+msgstr "추가 그룹 ID를 설정할 수 없습니다"
+
+#: src/sudo.c:1000
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "유효한 gid를 %u 실행 gid로 설정할 수 없습니다"
+
+#: src/sudo.c:1006
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "gid를 실행 gid %u(으)로 설정할 수 없습니다"
+
+#: src/sudo.c:1037
+msgid "argv not set by the security policy"
+msgstr "보안 정책에 따라 argv를 설정하지 않았습니다"
+
+#: src/sudo.c:1041
+msgid "envp not set by the security policy"
+msgstr "보안 정책에 따라 envp를 설정하지 않았습니다"
+
+#: src/sudo.c:1063
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "예상치 못한 하위 프로세스 중단 상태: %d"
+
+#: src/sudo.c:1176
+msgid "unable to initialize policy plugin"
+msgstr "정책 플러그인을 초기화할 수 없습니다"
+
+#: src/sudo.c:1238
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "%s 정책 플러그인에 \"check_policy\" 메서드가 빠졌습니다"
+
+#: src/sudo.c:1284
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "%s 정책 플러그인에서 권한 조회를 지원하지 않습니다"
+
+#: src/sudo.c:1328
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "%s 정책 플러그인에서 -v 옵션을 지원하지 않습니다"
+
+#: src/sudo.c:1366
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "%s 정책 플러그인에서 -k/-K 옵션을 지원하지 않습니다"
+
+#: src/sudo.c:1495
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "%s 입출력 플러그인 초기화 오류"
+
+#: src/sudo.c:1498
+msgid "error initializing I/O plugin"
+msgstr "입출력 플러그인 초기화 오류"
+
+#: src/sudo.c:1647
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "%s 감사 플러그인 초기화 오류"
+
+#: src/sudo.c:1726
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: %s%s 오류 이벤트를 기록할 수 없습니다"
+
+#: src/sudo.c:1762
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: %s%s 허용 이벤트를 기록할 수 없습니다"
+
+#: src/sudo.c:1767 src/sudo.c:1805
+msgid "audit plugin error"
+msgstr "감사 플러그인 오류"
+
+#: src/sudo.c:1800
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: %s%s 거부 이벤트를 기록할 수 없습니다"
+
+#: src/sudo.c:1860
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "%s 승인 플러그인 초기화 오류"
+
+#: src/sudo.c:1930
+msgid "command rejected by approver"
+msgstr "승인자가 명령을 거부했습니다"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "기록 가능한 임시 디렉터리를 찾을 수 없습니다"
+
+#: src/sudo_edit.c:292
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s 수정하지 않은 상태로 남음"
+
+#: src/sudo_edit.c:305 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s 바꾸지 않음"
+
+#: src/sudo_edit.c:482
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: 내부 오류: 경로에 잘못된 파일"
+
+#: src/sudo_edit.c:484
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: 임시 파일을 만들 수 없습니다"
+
+#: src/sudo_edit.c:486 src/sudo_edit.c:606
+msgid "sesh: killed by a signal"
+msgstr "sesh: 시그널을 받아 죽음"
+
+#: src/sudo_edit.c:488 src/sudo_edit.c:609
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: 잘못된 오류 %d"
+
+#: src/sudo_edit.c:599
+msgid "unable to copy temporary files back to their original location"
+msgstr "원위치에 임시 파일을 복사할 수 없습니다"
+
+#: src/sudo_edit.c:603
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "원 위치에 임시 파일 일부를 복사할 수 없습니다"
+
+#: src/sudo_edit.c:650
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "uid를 루트로 바꿀 수 없습니다(%u)"
+
+#: src/sudo_edit.c:664
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "플러그인 오류: sudoedit의 파일 목록이 잘못됨"
+
+#: src/sudo_edit.c:685
+msgid "plugin error: missing file list for sudoedit"
+msgstr "플러그인 오류: sudoedit의 파일 목록이 빠짐"
+
+#: src/sudo_edit.c:728 src/sudo_edit.c:743
+msgid "unable to read the clock"
+msgstr "클록을 읽을 수 없습니다"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "차단 포트를 설정하지 않았습니다"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "암호 읽기 시간 초과"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "암호를 입력하지 않았습니다"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "암호를 읽을 수 없습니다"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "암호를 읽으려면 터미널이 필요합니다. -S 옵션을 사용하여 표준 입력으로 암호를 받거나 askpass 도우미를 설정하십시오"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "askpass 프로그램을 지정하지 않았습니다. SUDO_ASKPASS를 설정해보십시오"
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "gid를 %u(으)로 설정할 수 없습니다"
+
+#: src/tgetpass.c:337
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "uid를 %u(으)로 설정할 수 없습니다"
+
+#: src/tgetpass.c:342
+#, c-format
+msgid "unable to run %s"
+msgstr "%s을(를) 실행할 수 없습니다"
+
+#: src/utmp.c:283
+msgid "unable to save stdin"
+msgstr "표준 입력을 저장할 수 없습니다"
+
+#: src/utmp.c:285
+msgid "unable to dup2 stdin"
+msgstr "표준 입력을 dup2 처리할 수 없습니다"
+
+#: src/utmp.c:288
+msgid "unable to restore stdin"
+msgstr "표준 입력을 복원할 수 없습니다"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s은(는) uid %d에서 소유해야 합니다"
+
+#~ msgid "%s must be only be writable by owner"
+#~ msgstr "%s은(는) 소유자만 기록할 수 있어야 합니다"
+
+#~ msgid "insufficient space for execve arguments"
+#~ msgstr "execve 인자 공간이 부족합니다"
+
+#~ msgid "unable to read execve %s for process %d"
+#~ msgstr "프로세스 %2$d번의 %1$s execve를 읽을 수 없습니다"
+
+#~ msgid "requires at least one argument"
+#~ msgstr "최소한 하나의 인자가 필요합니다"
+
+#~ msgid "unable to run %s as a login shell"
+#~ msgstr "%s(을)를 로그인 쉘로 실행할 수 없습니다"
+
+#~ msgid "unable to dup intercept fd"
+#~ msgstr "가로채기 파일 서술자를 복제할 수 없습니다"
+
+#~ msgid "%s: missing message header"
+#~ msgstr "%s: 메시지 헤더가 빠졌습니다"
+
+#~ msgid "%s: expected message type %d, got %d"
+#~ msgstr "%s: 메시지 형식 %d번을 기대했으나, %d번이 나타났습니다"
+
+#~ msgid "unable to set tty context to %s"
+#~ msgstr "tty 컨텍스트를 %s(으)로 설정할 수 없습니다"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s: %s"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "%2$s의 %3$d번째 줄에서 \"%1$s\" 중복 정책 플러그인 무시"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s: 기록 내용이 짧습니다"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "임시 파일을 읽을 수 없습니다"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "존재하는 tty가 없으며 askpass 프로그램을 지정하지 않았습니다"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "시그널 파이프 읽기 오류"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "알 수 없는 %u: 누구일까요?"
diff --git a/po/nb.mo b/po/nb.mo
new file mode 100644
index 0000000..066e7e5
--- /dev/null
+++ b/po/nb.mo
Binary files differ
diff --git a/po/nb.po b/po/nb.po
new file mode 100644
index 0000000..4a3c129
--- /dev/null
+++ b/po/nb.po
@@ -0,0 +1,1035 @@
+# Norwegian bokmål translation of sudo.
+# This file is distributed under the same license as the sudo package.
+# Copyright (C) 2017 Free Software Foundation, Inc.
+# Todd C. Miller <Todd.Miller@courtesan.com>, 2011-2013.
+# Åka Sikrom <a4@hush.com>, 2014-2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo-1.9.0b4\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2020-03-12 17:39-0600\n"
+"PO-Revision-Date: 2020-03-16 07:31+0100\n"
+"Last-Translator: Åka Sikrom <a4@hush.com>\n"
+"Language-Team: Norwegian Bokmaal <i18n-nb@lister.ping.uio.no>\n"
+"Language: nb\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 2.0.6\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: lib/util/aix.c:92 lib/util/aix.c:172
+msgid "unable to open userdb"
+msgstr "klarte ikke å åpne brukerdatabase"
+
+#: lib/util/aix.c:227
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "klarte ikke å skifte til registeret «%s» for %s"
+
+#: lib/util/aix.c:252
+msgid "unable to restore registry"
+msgstr "klarte ikke å gjenopprette register"
+
+#: lib/util/aix.c:275 lib/util/gidlist.c:71 lib/util/gidlist.c:81
+#: lib/util/json.c:66 lib/util/json.c:192 lib/util/sudo_conf.c:191
+#: lib/util/sudo_conf.c:277 lib/util/sudo_conf.c:354 lib/util/sudo_conf.c:580
+#: src/conversation.c:86 src/exec_common.c:114 src/exec_common.c:130
+#: src/exec_common.c:139 src/exec_monitor.c:211 src/exec_monitor.c:460
+#: src/exec_monitor.c:466 src/exec_monitor.c:474 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_monitor.c:496 src/exec_monitor.c:503
+#: src/exec_monitor.c:510 src/exec_monitor.c:517 src/exec_monitor.c:524
+#: src/exec_monitor.c:531 src/exec_nopty.c:218 src/exec_nopty.c:227
+#: src/exec_nopty.c:234 src/exec_nopty.c:241 src/exec_nopty.c:248
+#: src/exec_nopty.c:255 src/exec_nopty.c:262 src/exec_nopty.c:269
+#: src/exec_nopty.c:276 src/exec_nopty.c:283 src/exec_nopty.c:290
+#: src/exec_nopty.c:297 src/exec_nopty.c:305 src/exec_nopty.c:479
+#: src/exec_pty.c:822 src/exec_pty.c:831 src/exec_pty.c:888
+#: src/exec_pty.c:1038 src/exec_pty.c:1206 src/exec_pty.c:1215
+#: src/exec_pty.c:1222 src/exec_pty.c:1229 src/exec_pty.c:1236
+#: src/exec_pty.c:1243 src/exec_pty.c:1250 src/exec_pty.c:1257
+#: src/exec_pty.c:1264 src/exec_pty.c:1271 src/exec_pty.c:1278
+#: src/exec_pty.c:1286 src/exec_pty.c:1709 src/load_plugins.c:59
+#: src/load_plugins.c:72 src/load_plugins.c:170 src/load_plugins.c:195
+#: src/load_plugins.c:230 src/load_plugins.c:470 src/load_plugins.c:476
+#: src/load_plugins.c:491 src/load_plugins.c:497 src/parse_args.c:186
+#: src/parse_args.c:207 src/parse_args.c:282 src/parse_args.c:584
+#: src/parse_args.c:606 src/parse_args.c:631 src/preserve_fds.c:54
+#: src/preserve_fds.c:139 src/selinux.c:91 src/selinux.c:361 src/selinux.c:474
+#: src/selinux.c:483 src/sesh.c:117 src/sudo.c:625 src/sudo.c:685
+#: src/sudo.c:695 src/sudo.c:716 src/sudo.c:735 src/sudo.c:744 src/sudo.c:753
+#: src/sudo.c:770 src/sudo.c:811 src/sudo.c:821 src/sudo.c:847 src/sudo.c:1037
+#: src/sudo.c:1059 src/sudo.c:1355 src/sudo.c:1528 src/sudo.c:1722
+#: src/sudo.c:2066 src/sudo_edit.c:270 src/sudo_edit.c:775 src/sudo_edit.c:872
+#: src/sudo_edit.c:986 src/sudo_edit.c:1006
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:275 lib/util/gidlist.c:71 lib/util/json.c:67
+#: lib/util/json.c:193 lib/util/sudo_conf.c:192 lib/util/sudo_conf.c:277
+#: lib/util/sudo_conf.c:354 lib/util/sudo_conf.c:580 src/conversation.c:87
+#: src/exec_common.c:114 src/exec_common.c:131 src/exec_common.c:140
+#: src/exec_monitor.c:460 src/exec_monitor.c:466 src/exec_monitor.c:474
+#: src/exec_monitor.c:482 src/exec_monitor.c:489 src/exec_monitor.c:496
+#: src/exec_monitor.c:503 src/exec_monitor.c:510 src/exec_monitor.c:517
+#: src/exec_monitor.c:524 src/exec_monitor.c:531 src/exec_nopty.c:218
+#: src/exec_nopty.c:227 src/exec_nopty.c:234 src/exec_nopty.c:241
+#: src/exec_nopty.c:248 src/exec_nopty.c:255 src/exec_nopty.c:262
+#: src/exec_nopty.c:269 src/exec_nopty.c:276 src/exec_nopty.c:283
+#: src/exec_nopty.c:290 src/exec_nopty.c:297 src/exec_nopty.c:305
+#: src/exec_pty.c:822 src/exec_pty.c:831 src/exec_pty.c:888
+#: src/exec_pty.c:1206 src/exec_pty.c:1215 src/exec_pty.c:1222
+#: src/exec_pty.c:1229 src/exec_pty.c:1236 src/exec_pty.c:1243
+#: src/exec_pty.c:1250 src/exec_pty.c:1257 src/exec_pty.c:1264
+#: src/exec_pty.c:1271 src/exec_pty.c:1278 src/exec_pty.c:1286
+#: src/exec_pty.c:1709 src/load_plugins.c:170 src/load_plugins.c:195
+#: src/load_plugins.c:230 src/load_plugins.c:470 src/load_plugins.c:476
+#: src/load_plugins.c:491 src/load_plugins.c:497 src/parse_args.c:186
+#: src/parse_args.c:208 src/parse_args.c:282 src/parse_args.c:584
+#: src/parse_args.c:606 src/parse_args.c:631 src/preserve_fds.c:54
+#: src/preserve_fds.c:139 src/selinux.c:91 src/selinux.c:361 src/selinux.c:474
+#: src/selinux.c:483 src/sesh.c:117 src/sudo.c:239 src/sudo.c:625
+#: src/sudo.c:847 src/sudo.c:1037 src/sudo.c:1059 src/sudo.c:1355
+#: src/sudo.c:1528 src/sudo.c:1722 src/sudo.c:2066 src/sudo_edit.c:270
+#: src/sudo_edit.c:775 src/sudo_edit.c:872 src/sudo_edit.c:986
+#: src/sudo_edit.c:1006
+msgid "unable to allocate memory"
+msgstr "klarte ikke å tildele minne"
+
+#: lib/util/mkdir_parents.c:79 lib/util/sudo_conf.c:619 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:368
+#, c-format
+msgid "unable to open %s"
+msgstr "klarte ikke å åpne %s"
+
+#: lib/util/mkdir_parents.c:94
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "klarte ikke å opprette mappe %s"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:596
+#, c-format
+msgid "unable to stat %s"
+msgstr "klarte ikke å lage statistikk av %s"
+
+#: lib/util/mkdir_parents.c:108
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s finnes, men er ikke en mappe (0%o)"
+
+#: lib/util/strsignal.c:55
+msgid "Unknown signal"
+msgstr "Ukjent signal"
+
+#: lib/util/strtoid.c:96 lib/util/strtomode.c:56 lib/util/strtonum.c:161
+#: lib/util/strtonum.c:200
+msgid "invalid value"
+msgstr "ugyldig verdi"
+
+#: lib/util/strtomode.c:62 lib/util/strtonum.c:173
+msgid "value too large"
+msgstr "verdien er for stor"
+
+#: lib/util/strtomode.c:62 lib/util/strtonum.c:167
+msgid "value too small"
+msgstr "verdien er for liten"
+
+#: lib/util/sudo_conf.c:210
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "«%s» er en ugyldig Path-verdi i %s, linje %u"
+
+#: lib/util/sudo_conf.c:376 lib/util/sudo_conf.c:392 lib/util/sudo_conf.c:445
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "«%2$s» er en ugyldig verdi for %1$s i %3$s, linje %4$u"
+
+#: lib/util/sudo_conf.c:413
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "gruppekilden «%s» (i %s, linje %u) støttes ikke"
+
+#: lib/util/sudo_conf.c:429
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "«%s» er et ugyldig maskimalt antall grupper i %s, linje %u"
+
+#: lib/util/sudo_conf.c:599
+#, c-format
+msgid "%s is not a regular file"
+msgstr "«%s» er ikke en vanlig fil"
+
+#: lib/util/sudo_conf.c:602
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "«%s» eies av uid %u, som skulle vært %u"
+
+#: lib/util/sudo_conf.c:606
+#, c-format
+msgid "%s is world writable"
+msgstr "«%s» kan overskrives av alle"
+
+#: lib/util/sudo_conf.c:609
+#, c-format
+msgid "%s is group writable"
+msgstr "«%s» kan overskrives av eiergruppa"
+
+#: src/exec.c:135
+#, c-format
+msgid "unknown login class %s"
+msgstr "innloggingsklassen «%s» er ukjent"
+
+#: src/exec.c:147
+msgid "unable to set user context"
+msgstr "klarte ikke å velge brukerkontekst"
+
+#: src/exec.c:163
+msgid "unable to set process priority"
+msgstr "klarte ikke å velge prosessprioritet"
+
+#: src/exec.c:177
+#, c-format
+msgid "unable to change root to %s"
+msgstr "klarte ikke å endre rot til «%s»"
+
+#: src/exec.c:190 src/exec.c:196 src/exec.c:203
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "klarte ikke å endre til runas uid (%u, %u)"
+
+#: src/exec.c:221
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "klarte ikke å endre mappe til «%s»"
+
+#: src/exec.c:304 src/exec_monitor.c:569 src/exec_monitor.c:571
+#: src/exec_nopty.c:537 src/exec_pty.c:566 src/exec_pty.c:1373
+#: src/exec_pty.c:1375 src/signal.c:150 src/signal.c:164
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "klarte ikke å velge håndtering av signal %d"
+
+#: src/exec_common.c:173
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "klarte ikke å fjerne PRIV_PROC_EXEC fra PRIV_LIMIT"
+
+#: src/exec_monitor.c:365
+msgid "error reading from socketpair"
+msgstr "feil under lesing fra sokkelpar"
+
+#: src/exec_monitor.c:382
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "uforventet responstype i bak-kanalen: %d"
+
+#: src/exec_monitor.c:468 src/exec_monitor.c:476 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_monitor.c:498 src/exec_monitor.c:505
+#: src/exec_monitor.c:512 src/exec_monitor.c:519 src/exec_monitor.c:526
+#: src/exec_monitor.c:533 src/exec_nopty.c:220 src/exec_nopty.c:229
+#: src/exec_nopty.c:236 src/exec_nopty.c:243 src/exec_nopty.c:250
+#: src/exec_nopty.c:257 src/exec_nopty.c:264 src/exec_nopty.c:271
+#: src/exec_nopty.c:278 src/exec_nopty.c:285 src/exec_nopty.c:292
+#: src/exec_nopty.c:299 src/exec_nopty.c:307 src/exec_pty.c:688
+#: src/exec_pty.c:693 src/exec_pty.c:790 src/exec_pty.c:797 src/exec_pty.c:894
+#: src/exec_pty.c:1208 src/exec_pty.c:1217 src/exec_pty.c:1224
+#: src/exec_pty.c:1231 src/exec_pty.c:1238 src/exec_pty.c:1245
+#: src/exec_pty.c:1252 src/exec_pty.c:1259 src/exec_pty.c:1266
+#: src/exec_pty.c:1273 src/exec_pty.c:1280 src/exec_pty.c:1662
+#: src/exec_pty.c:1672 src/exec_pty.c:1717 src/exec_pty.c:1724
+#: src/exec_pty.c:1751
+msgid "unable to add event to queue"
+msgstr "klarte ikke å legge hendelse i kø"
+
+#: src/exec_monitor.c:587
+msgid "unable to set controlling tty"
+msgstr "klarte ikke å velge styrende tty"
+
+#: src/exec_monitor.c:595 src/exec_nopty.c:364 src/exec_pty.c:1452
+#: src/exec_pty.c:1473 src/exec_pty.c:1493 src/tgetpass.c:311
+msgid "unable to create pipe"
+msgstr "klarte ikke å lage datarør"
+
+#: src/exec_monitor.c:603
+msgid "unable to receive message from parent"
+msgstr "klarte ikke å motta melding fra forelder"
+
+#: src/exec_monitor.c:617 src/exec_nopty.c:393 src/exec_pty.c:1531
+#: src/tgetpass.c:315
+msgid "unable to fork"
+msgstr "klarte ikke å lage kopi av prosess"
+
+#: src/exec_monitor.c:621 src/exec_monitor.c:720 src/exec_nopty.c:447
+msgid "unable to restore tty label"
+msgstr "klarte ikke å gjenopprette tty-etikett"
+
+#: src/exec_monitor.c:637 src/sesh.c:127 src/sudo.c:1114
+#, c-format
+msgid "unable to execute %s"
+msgstr "klarte ikke å kjøre «%s»"
+
+#: src/exec_nopty.c:358 src/exec_pty.c:1382
+msgid "policy plugin failed session initialization"
+msgstr "regeltillegg klarte ikke å starte økt"
+
+#: src/exec_nopty.c:435 src/exec_pty.c:1617
+msgid "error in event loop"
+msgstr "feil i hendelsesløkke"
+
+#: src/exec_nopty.c:545 src/exec_pty.c:601 src/signal.c:112
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "klarte ikke å gjenopprette håndtering av signal %d"
+
+#: src/exec_pty.c:157
+msgid "unable to allocate pty"
+msgstr "klarte ikke å tildele pty"
+
+#: src/exec_pty.c:221 src/exec_pty.c:260 src/exec_pty.c:299 src/exec_pty.c:349
+#: src/exec_pty.c:399
+msgid "I/O plugin error"
+msgstr "Feil med I/O-tillegg"
+
+#: src/exec_pty.c:224 src/exec_pty.c:263 src/exec_pty.c:302 src/exec_pty.c:352
+#: src/exec_pty.c:402
+msgid "command rejected by I/O plugin"
+msgstr "kommando avvist av I/O-tillegg"
+
+#: src/exec_pty.c:449
+msgid "error logging suspend"
+msgstr "feil under loggføring av hvilemodus"
+
+#: src/exec_pty.c:482
+msgid "error changing window size"
+msgstr "feil under endring av vindustørrelse"
+
+#: src/exec_pty.c:1362
+msgid "unable to create sockets"
+msgstr "klarte ikke å lage sokkel"
+
+#: src/exec_pty.c:1574
+msgid "unable to send message to monitor process"
+msgstr "klarte ikke å sende melding til overvåkningsprosess"
+
+#: src/load_plugins.c:57 src/load_plugins.c:70 src/load_plugins.c:92
+#: src/load_plugins.c:122 src/load_plugins.c:136 src/load_plugins.c:142
+#: src/load_plugins.c:293 src/load_plugins.c:301 src/load_plugins.c:308
+#: src/load_plugins.c:348
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "feil i «%s» linje %d under innlasting av tillegg «%s»"
+
+#: src/load_plugins.c:94
+#, c-format
+msgid "%s%s: %s"
+msgstr "%s%s: %s"
+
+#: src/load_plugins.c:138
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "«%s» må eies av uid %d"
+
+#: src/load_plugins.c:144
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "«%s» kan ikke være overskrivbar for andre enn eier"
+
+#: src/load_plugins.c:254 src/load_plugins.c:321
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "duplikattillegg «%s» for inn- og utdata i «%s» linje %d blir ignorert"
+
+#: src/load_plugins.c:295
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "klarte ikke å laste inn «%s». %s"
+
+#: src/load_plugins.c:303
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "fant ikke symbol «%s» i %s"
+
+#: src/load_plugins.c:310
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "ukompatibel versjon av programtillegg %d (forventet %d) ble funnet i «%s»"
+
+#: src/load_plugins.c:324
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "regeltillegg «%s» i «%s» linje %d blir ignorert"
+
+#: src/load_plugins.c:326
+msgid "only a single policy plugin may be specified"
+msgstr "du kan bare velge ett regeltillegg"
+
+#: src/load_plugins.c:350
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "tilleggstype «%d» som ble funnet i «%s» er ukjent"
+
+#: src/load_plugins.c:511
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "regeltillegg «%s» inneholder ikke en «check_policy»-metode"
+
+#: src/net_ifs.c:183 src/net_ifs.c:200 src/net_ifs.c:345 src/sudo.c:478
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "intern feil: %s er full"
+
+#: src/parse_args.c:228
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "%s er et ugyldig miljøvariabel-navn"
+
+#: src/parse_args.c:329
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "«-C» må brukes med et tallargument med en verdi på minst 3"
+
+#: src/parse_args.c:524
+msgid "you may not specify both the `-i' and `-s' options"
+msgstr "du kan ikke velge både «-i» og «-s»"
+
+#: src/parse_args.c:528
+msgid "you may not specify both the `-i' and `-E' options"
+msgstr "du kan ikke velge både «-i» og «-E»"
+
+#: src/parse_args.c:538
+msgid "the `-E' option is not valid in edit mode"
+msgstr "valget «-E» er ugyldig i redigeringsmodus"
+
+#: src/parse_args.c:540
+msgid "you may not specify environment variables in edit mode"
+msgstr "du kan ikke velge miljøvariabler i redigeringsmodus"
+
+#: src/parse_args.c:548
+msgid "the `-U' option may only be used with the `-l' option"
+msgstr "valget «-U» kan ikke brukes uten «-l»"
+
+#: src/parse_args.c:552
+msgid "the `-A' and `-S' options may not be used together"
+msgstr "valgene «-A» og «-S» kan ikke brukes samtidig"
+
+#: src/parse_args.c:645
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit støttes ikke på denne plattformen"
+
+#: src/parse_args.c:726
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Du kan bare velge ett av valgene -e, -h, -i, -K, -l, -s, -v eller -V"
+
+#: src/parse_args.c:740
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - rediger filer som om du var en annen bruker\n"
+"\n"
+
+#: src/parse_args.c:742
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - kjør en kommando som om du var en annen bruker\n"
+"\n"
+
+#: src/parse_args.c:747
+#, c-format
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Valg:\n"
+
+#: src/parse_args.c:749
+msgid "use a helper program for password prompting"
+msgstr "bruk et hjelpeprogram for å oppgi passord"
+
+#: src/parse_args.c:752
+msgid "use specified BSD authentication type"
+msgstr "bruk valgt BSD-autentiseringsmetode"
+
+#: src/parse_args.c:755
+msgid "run command in the background"
+msgstr "kjør kommando i bakgrunnen"
+
+#: src/parse_args.c:757
+msgid "ring bell when prompting"
+msgstr "lag varsellyd ved spørrende ledetekst"
+
+#: src/parse_args.c:759
+msgid "close all file descriptors >= num"
+msgstr "lukk alle fildeskriptorer >= num"
+
+#: src/parse_args.c:762
+msgid "run command with the specified BSD login class"
+msgstr "kjør kommando med valgt BSD-innloggingsklasse"
+
+#: src/parse_args.c:765
+msgid "preserve user environment when running command"
+msgstr "behold gjeldende brukermiljø når kommandoen kjøres"
+
+#: src/parse_args.c:767
+msgid "preserve specific environment variables"
+msgstr "behold bestemte miljøvariabler"
+
+#: src/parse_args.c:769
+msgid "edit files instead of running a command"
+msgstr "rediger filer i stedet for å kjøre en kommando"
+
+#: src/parse_args.c:771
+msgid "run command as the specified group name or ID"
+msgstr "kjør kommando som om du var en del av valgt gruppe (-navn eller -ID)"
+
+#: src/parse_args.c:773
+msgid "set HOME variable to target user's home dir"
+msgstr "bruk valgt brukers hjemmemappe som HOME-miljøvariabel"
+
+#: src/parse_args.c:775
+msgid "display help message and exit"
+msgstr "vis hjelpetekst og avslutt"
+
+#: src/parse_args.c:777
+msgid "run command on host (if supported by plugin)"
+msgstr "kjør kommando på verten (hvis programtillegget støtter det)"
+
+#: src/parse_args.c:779
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "kjør innloggingsskall som om du var den valgte brukeren (du kan også oppgi en kommando her)"
+
+#: src/parse_args.c:781
+msgid "remove timestamp file completely"
+msgstr "fjern tidsstempel-fil skikkelig"
+
+#: src/parse_args.c:783
+msgid "invalidate timestamp file"
+msgstr "gjør tidsstempel-fil ugyldig"
+
+#: src/parse_args.c:785
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "vis brukerens privilegier, eller sjekk om det fungerer å kjøre en bestemt kommando (bruk to ganger for å se et lengre format)"
+
+#: src/parse_args.c:787
+msgid "non-interactive mode, no prompts are used"
+msgstr "stillemodus (ingen ledetekst vises)"
+
+#: src/parse_args.c:789
+msgid "preserve group vector instead of setting to target's"
+msgstr "behold gruppevektor, i stedet for å bruke den som gjelder for målet"
+
+#: src/parse_args.c:791
+msgid "use the specified password prompt"
+msgstr "bruk valgt passord-ledetekst"
+
+#: src/parse_args.c:794
+msgid "create SELinux security context with specified role"
+msgstr "lag SELinux-sikkerhetskontekst med valgt rolle"
+
+#: src/parse_args.c:797
+msgid "read password from standard input"
+msgstr "les passord fra standard inndata"
+
+#: src/parse_args.c:799
+msgid "run shell as the target user; a command may also be specified"
+msgstr "kjør skall som valgt bruker (du kan også oppgi en kommando her)"
+
+#: src/parse_args.c:802
+msgid "create SELinux security context with specified type"
+msgstr "lag SELinux-sikkerhetskontekst med valgt type"
+
+#: src/parse_args.c:805
+msgid "terminate command after the specified time limit"
+msgstr "avslutt kommando etter valgt tidsfrist"
+
+#: src/parse_args.c:807
+msgid "in list mode, display privileges for user"
+msgstr "vis brukerprivilegier (i listemodus)"
+
+#: src/parse_args.c:809
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "kjør kommando (eller rediger fil) som valgt brukernavn eller bruker-ID"
+
+#: src/parse_args.c:811
+msgid "display version information and exit"
+msgstr "vis programversjon og avslutt"
+
+#: src/parse_args.c:813
+msgid "update user's timestamp without running a command"
+msgstr "oppdater brukerens tidsstempel uten å kjøre en kommando"
+
+#: src/parse_args.c:815
+msgid "stop processing command line arguments"
+msgstr "slutt å behandle kommandolinje-argumenter"
+
+#: src/selinux.c:85
+msgid "unable to open audit system"
+msgstr "klarte ikke å åpne revisjonssystemet"
+
+#: src/selinux.c:95
+msgid "unable to send audit message"
+msgstr "klarte ikke å sende revisjonsmelding"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "klarte ikke å utføre fgetfilecon %s"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s endret etiketter"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "klarte ikke å gjenopprette kontekst for «%s»"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "klarte ikke å åpne «%s». tty får ikke ny etikett"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s er ikke en tegnenhet. tty får ikke ny etikett"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "klarte ikke å hente gjeldende tty-kontekst. tty får ikke ny etikett"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "«chr_file» er ugyldig sikkerhetsklasse. tty får ikke ny etikett"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "klrate ikke å hente ny tty-kontekst. tty får ikke ny etikett"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "klarte ikke å velge ny tty-kontekst"
+
+#: src/selinux.c:322
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "du må velge en rolle for typen «%s»"
+
+#: src/selinux.c:328
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "klarte ikke å hente standardtype for rollen «%s»"
+
+#: src/selinux.c:340
+msgid "failed to get new context"
+msgstr "klarte ikke å hente ny kontekst"
+
+#: src/selinux.c:349
+#, c-format
+msgid "failed to set new role %s"
+msgstr "klarte ikke å velge den nye rollen «%s»"
+
+#: src/selinux.c:353
+#, c-format
+msgid "failed to set new type %s"
+msgstr "klarte ikke å velge den nye typen «%s»"
+
+#: src/selinux.c:365
+#, c-format
+msgid "%s is not a valid context"
+msgstr "«%s» er en ugyldig kontekst"
+
+#: src/selinux.c:397
+msgid "failed to get old context"
+msgstr "klarte ikke å hente gammel kontekst"
+
+#: src/selinux.c:403
+msgid "unable to determine enforcing mode."
+msgstr "klarte ikke å finne håndhevelsesmodus."
+
+#: src/selinux.c:420
+#, c-format
+msgid "unable to set tty context to %s"
+msgstr "klarte ikke å velge «%s» som tty-kontekst"
+
+#: src/selinux.c:452
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "klarte ikke å velge «%s» som kjørekontekst"
+
+#: src/selinux.c:459
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "klarte ikke å velge «%s» som nøkkelkontekst"
+
+#: src/sesh.c:79
+msgid "requires at least one argument"
+msgstr "krever at du bruker minst ett argument"
+
+#: src/sesh.c:108
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "ugyldig fildeskriptor-tall: %s"
+
+#: src/sesh.c:122
+#, c-format
+msgid "unable to run %s as a login shell"
+msgstr "klarte ikke å kjøre %s som et innloggingsskall"
+
+#: src/signal.c:90
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "klarte ikke å lagre håndtering av signal %d"
+
+#: src/solaris.c:83
+msgid "resource control limit has been reached"
+msgstr "kontrollgrensen for ressurser er nådd"
+
+#: src/solaris.c:86
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "brukeren «%s» er ikke medlem av prosjektet «%s»"
+
+#: src/solaris.c:90
+msgid "the invoking task is final"
+msgstr "den kallende oppgaven er endelig"
+
+#: src/solaris.c:93
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "klarte ikke å bli med i prosjektet «%s»"
+
+#: src/solaris.c:98
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "det er ingen ressursgrunnlag som godtar standardtildelinger for prosjektet «%s»"
+
+#: src/solaris.c:102
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "fant ikke valgt ressursgrunnlag for prosjetet «%s»"
+
+#: src/solaris.c:106
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "klarte ikke å tildele standard ressursgrunnlag for prosjektet «%s»"
+
+#: src/solaris.c:112
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "klarte ikke å utføre «setproject» på «%s»"
+
+#: src/solaris.c:114
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "advarsel: noe gikk galt ved tildeling av ressurskontroll for prosjektet «%s»"
+
+#: src/sudo.c:224
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo versjon %s\n"
+
+#: src/sudo.c:226
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Velg innstillinger: %s\n"
+
+#: src/sudo.c:235
+msgid "fatal error, unable to load plugins"
+msgstr "kritisk feil: klarte ikke å laste inn tilleggsprogrammer"
+
+#: src/sudo.c:280
+msgid "plugin did not return a command to execute"
+msgstr "tillegget sendte ikke en kjørbar kommando"
+
+#: src/sudo.c:311
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "uforventet sudo-modus 0x%x"
+
+#: src/sudo.c:544
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "du finnes ikke i databasen %s"
+
+#: src/sudo.c:601
+msgid "unable to determine tty"
+msgstr "fant ikke gjeldende tty"
+
+#: src/sudo.c:893
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "«%s» må eies av uid %d, og setuid-biten må være valgt"
+
+#: src/sudo.c:896
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "effektiv uid er ikke %d. Er «%s» på et filsystem hvor «nosuid» er valgt, eller på et NFS-filsystem uten rot-rettigheter?"
+
+#: src/sudo.c:902
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "effektiv uid er ikke %d. Er sudo installert med «setuid root»?"
+
+#: src/sudo.c:918
+msgid "unable to set supplementary group IDs"
+msgstr "klarte ikke å velge ekstra grruppe-id-er"
+
+#: src/sudo.c:925
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "klarte ikke å velge «runas gid %u» som effektiv gid"
+
+#: src/sudo.c:931
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "klarte ikke å velge «runas gid %u» som gid"
+
+#: src/sudo.c:978
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "uforventet årsak for avslutning av underprosess: %d"
+
+#: src/sudo.c:1087
+msgid "unable to initialize policy plugin"
+msgstr "klarte ikke å starte opp regeltillegg"
+
+#: src/sudo.c:1148
+#, c-format
+msgid "policy plugin %s is missing the `check_policy' method"
+msgstr "regeltillegg «%s» mangler «check_policy»-metoden"
+
+#: src/sudo.c:1163 src/sudo.c:1216 src/sudo.c:1260
+msgid "command rejected by policy"
+msgstr "kommando avvist av regelsett"
+
+#: src/sudo.c:1168 src/sudo.c:1221 src/sudo.c:1265
+msgid "policy plugin error"
+msgstr "feil med regelsett-tillegg"
+
+#: src/sudo.c:1202
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "regeltillegg «%s» støtter ikke listetillatelser"
+
+#: src/sudo.c:1246
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "regeltillegg «%s» støtter ikke valget «-v»"
+
+#: src/sudo.c:1284
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "regeltillegg «%s» støtter ikke valgene «-k» og «-K»"
+
+#: src/sudo.c:1413
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "feil under klargjøring av inn-/utdatatillegg «%s»"
+
+#: src/sudo.c:1567
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "feil under klargjøring av revisjonstillegg «%s»"
+
+#: src/sudo.c:1745
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "feil under klargjøring av godkjenningstillegg «%s»"
+
+#: src/sudo.c:1821
+msgid "command rejected by approver"
+msgstr "kommando avvist av godkjenner"
+
+#: src/sudo.c:1830
+msgid "approval plugin error"
+msgstr "feil med godkjenningstillegg"
+
+#: src/sudo_edit.c:233
+msgid "no writable temporary directory found"
+msgstr "fant ingen midlertidig mappe med skrivetillatelse"
+
+#: src/sudo_edit.c:358
+msgid "unable to restore current working directory"
+msgstr "klarte ikke å gjenopprette gjeldende arbeidsmappe"
+
+#: src/sudo_edit.c:575 src/sudo_edit.c:688
+#, c-format
+msgid "%s: not a regular file"
+msgstr "«%s» er ikke en vanlig fil"
+
+#: src/sudo_edit.c:582
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: redigering av symbolske lenker tillates ikke"
+
+#: src/sudo_edit.c:585
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: redigering av filer i en mappe med skrivetilgang tillates ikke"
+
+#: src/sudo_edit.c:618 src/sudo_edit.c:728
+#, c-format
+msgid "%s: short write"
+msgstr "«%s» har kort skriving"
+
+#: src/sudo_edit.c:689
+#, c-format
+msgid "%s left unmodified"
+msgstr "«%s» ble uendret"
+
+#: src/sudo_edit.c:702 src/sudo_edit.c:889
+#, c-format
+msgid "%s unchanged"
+msgstr "«%s» er uendret"
+
+#: src/sudo_edit.c:717 src/sudo_edit.c:739
+#, c-format
+msgid "unable to write to %s"
+msgstr "klarte ikke å skrive til «%s»"
+
+#: src/sudo_edit.c:718 src/sudo_edit.c:737 src/sudo_edit.c:740
+#: src/sudo_edit.c:914 src/sudo_edit.c:918
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "innhold fra redigeringsøkt ligger igjen i «%s»"
+
+#: src/sudo_edit.c:736
+msgid "unable to read temporary file"
+msgstr "klarte ikke å lese midlertidig fil"
+
+#: src/sudo_edit.c:819
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: intern feil: for høyt antall stier"
+
+#: src/sudo_edit.c:821
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: klarte ikke å lage midlertidige filer"
+
+#: src/sudo_edit.c:823 src/sudo_edit.c:921
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: ukjent feil (%d)"
+
+#: src/sudo_edit.c:913
+msgid "unable to copy temporary files back to their original location"
+msgstr "klarte ikke å kopiere midlertidige filer tilbake til opprinnelig plassering"
+
+#: src/sudo_edit.c:917
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "klarte ikke å kopiere enkelte midlertidige filer tilbake til opprinnelig plassering"
+
+#: src/sudo_edit.c:962
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "klarte ikke å endre uid til root (%u)"
+
+#: src/sudo_edit.c:979
+msgid "plugin error: missing file list for sudoedit"
+msgstr "feil med tillegg: sudoedit mangler filliste"
+
+#: src/sudo_edit.c:1020 src/sudo_edit.c:1033
+msgid "unable to read the clock"
+msgstr "klarte ikke å lese klokka"
+
+#: src/tgetpass.c:102
+msgid "timed out reading password"
+msgstr "tidsavbrudd under lesing av passord"
+
+#: src/tgetpass.c:105
+msgid "no password was provided"
+msgstr "du skrev ikke inn passord"
+
+#: src/tgetpass.c:108
+msgid "unable to read password"
+msgstr "klarte ikke å lese passord"
+
+#: src/tgetpass.c:147
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "du trenger en terminal for å lese passordet. Bruk enten valget «-S» for å lese fra standard inndata eller sett opp et askpass-hjelpeprogram"
+
+#: src/tgetpass.c:157
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "intet program for passord-etterspørsel er valgt. Prøv å velge «SUDO_ASKPASS»"
+
+#: src/tgetpass.c:332
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "klarte ikke å velge %u som gid"
+
+#: src/tgetpass.c:336
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "klarte ikke å velge %u som uid"
+
+#: src/tgetpass.c:341
+#, c-format
+msgid "unable to run %s"
+msgstr "klarte ikke å kjøre «%s»"
+
+#: src/utmp.c:295
+msgid "unable to save stdin"
+msgstr "klarte ikke å lagre standard innkanal"
+
+#: src/utmp.c:297
+msgid "unable to dup2 stdin"
+msgstr "klarte ikke å utføre «dup2 stdin»"
+
+#: src/utmp.c:300
+msgid "unable to restore stdin"
+msgstr "klarte ikke å gjenopprette standard innkanal"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "duplikattillegg «%s» i «%s» linje %d blir ignorert"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "ingen tty er tilgjengelig, og intet program for passord-etterspørsel er valgt"
+
+#~ msgid "unable to get group vector"
+#~ msgstr "klarte ikke å hente gruppevektor"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "UID %u er ukjent. Hvem er du?"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "feil under lesing fra signalrør"
+
+#~ msgid "unable to set terminal to raw mode"
+#~ msgstr "klarte ikke å sette terminal i råmodus"
+
+#~ msgid "internal error, tried allocate zero bytes"
+#~ msgstr "intern feil: prøvde å tildele tomme byte"
+
+#~ msgid "unable to open socket"
+#~ msgstr "klarte ikke å åpne sokkelen"
+
+#~ msgid "%s: %s: %s\n"
+#~ msgstr "%s: %s: %s\n"
+
+#~ msgid "%s: %s\n"
+#~ msgstr "%s: %s\n"
+
+#~ msgid "internal error, tried to emalloc2(0)"
+#~ msgstr "intern feil: prøvde emalloc2(0)"
+
+#~ msgid "internal error, tried to ecalloc(0)"
+#~ msgstr "intern feil: prøvde ecalloc(0)"
+
+#~ msgid "internal error, tried to erealloc(0)"
+#~ msgstr "intern feil: prøvde erealloc(0)"
+
+#~ msgid "internal error, tried to erealloc3(0)"
+#~ msgstr "intern feil: prøvde erealloc3(0)"
+
+#~ msgid "internal error, tried to erecalloc(0)"
+#~ msgstr "intern feil: prøvde erecalloc(0)"
+
+#~ msgid "load_interfaces: overflow detected"
+#~ msgstr "load_interfaces: overbelastet"
diff --git a/po/nl.mo b/po/nl.mo
new file mode 100644
index 0000000..38603ce
--- /dev/null
+++ b/po/nl.mo
Binary files differ
diff --git a/po/nl.po b/po/nl.po
new file mode 100644
index 0000000..9f816df
--- /dev/null
+++ b/po/nl.po
@@ -0,0 +1,856 @@
+# Dutch translation for sudo.
+# Copyright (C) 2013 P. Hamming
+# This file is distributed under the same license as the sudo package.
+# P. Hamming <peterhamming@gmail.com>, 2013
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.8.12b1\n"
+"Report-Msgid-Bugs-To: http://www.sudo.ws/bugs\n"
+"POT-Creation-Date: 2014-10-27 12:35-0600\n"
+"PO-Revision-Date: 2015-01-14 02:50+0100\n"
+"Last-Translator: P. Hamming <peterhamming@gmail.com>\n"
+"Language-Team: Dutch <vertaling@vrijschrift.org>\n"
+"Language: nl\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: lib/util/aix.c:92 lib/util/aix.c:151
+msgid "unable to open userdb"
+msgstr "kan userdb niet openen"
+
+#: lib/util/aix.c:156
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "kan niet wijzigen naar register \"%s\" voor %s"
+
+#: lib/util/aix.c:175
+msgid "unable to restore registry"
+msgstr "kan register niet herstellen"
+
+#: lib/util/alloc.c:68 lib/util/alloc.c:85 lib/util/alloc.c:106
+#: lib/util/alloc.c:128 lib/util/alloc.c:147 lib/util/alloc.c:170
+msgid "internal error, tried allocate zero bytes"
+msgstr "interne fout, heb geprobeerd om zero bytes te alloceren"
+
+#: lib/util/alloc.c:87 lib/util/alloc.c:109 lib/util/alloc.c:149
+#: lib/util/alloc.c:172 src/net_ifs.c:174 src/net_ifs.c:191 src/net_ifs.c:325
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "interne fout, %s overloop"
+
+#: lib/util/gidlist.c:78 src/load_plugins.c:61 src/load_plugins.c:74
+#: src/sudo.c:572 src/sudo.c:591 src/sudo.c:618 src/sudo.c:627 src/sudo.c:636
+#: src/sudo.c:653 src/sudo.c:700 src/sudo.c:710
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Onbekend signaal"
+
+#: lib/util/strtoid.c:83 lib/util/strtoid.c:111 lib/util/strtomode.c:55
+#: lib/util/strtonum.c:65 lib/util/strtonum.c:183
+msgid "invalid value"
+msgstr "ongeldige waarde"
+
+#: lib/util/strtoid.c:90 lib/util/strtoid.c:118 lib/util/strtomode.c:61
+#: lib/util/strtonum.c:68 lib/util/strtonum.c:195
+msgid "value too large"
+msgstr "waarde te groot"
+
+#: lib/util/strtoid.c:96 lib/util/strtomode.c:61 lib/util/strtonum.c:68
+#: lib/util/strtonum.c:189
+msgid "value too small"
+msgstr "waarde te klein"
+
+#: lib/util/sudo_conf.c:181
+#, c-format
+msgid "invalid Path value `%s' in %s, line %u"
+msgstr "ongeldige lokatie '%s' in %s, regel %u"
+
+#: lib/util/sudo_conf.c:335 lib/util/sudo_conf.c:388
+#, c-format
+msgid "invalid value for %s `%s' in %s, line %u"
+msgstr "ongeldige waarde voor %s '%s' in %s, regel %u"
+
+#: lib/util/sudo_conf.c:356
+#, c-format
+msgid "unsupported group source `%s' in %s, line %u"
+msgstr "niet-ondersteunde brongroup '%s' in %s, regel %u"
+
+#: lib/util/sudo_conf.c:372
+#, c-format
+msgid "invalid max groups `%s' in %s, line %u"
+msgstr "ongeldig maximaal aantal groepen '%s' in %s, regel %u"
+
+#: lib/util/sudo_conf.c:522
+#, c-format
+msgid "unable to stat %s"
+msgstr "kan status niet opvragen van %s"
+
+#: lib/util/sudo_conf.c:525
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s geen regulier bestand"
+
+#: lib/util/sudo_conf.c:528
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s is eigendom van %u, moet gebruikersnummer %u zijn"
+
+#: lib/util/sudo_conf.c:532
+#, c-format
+msgid "%s is world writable"
+msgstr "%s kan door iedereen worden geschreven"
+
+#: lib/util/sudo_conf.c:535
+#, c-format
+msgid "%s is group writable"
+msgstr "%s kan door groep worden geschreven"
+
+#: lib/util/sudo_conf.c:545 src/selinux.c:196 src/selinux.c:209 src/sudo.c:341
+#, c-format
+msgid "unable to open %s"
+msgstr "kan %s niet openen"
+
+#: src/exec.c:123 src/exec.c:128 src/exec.c:423 src/exec.c:425 src/exec.c:427
+#: src/exec.c:429 src/exec.c:431 src/exec.c:433 src/exec.c:436 src/exec.c:453
+#: src/exec.c:455 src/exec.c:457 src/exec.c:605 src/exec.c:800
+#: src/exec_pty.c:480 src/exec_pty.c:736 src/exec_pty.c:806 src/exec_pty.c:808
+#: src/exec_pty.c:820 src/exec_pty.c:1308 src/exec_pty.c:1310
+#: src/exec_pty.c:1315 src/exec_pty.c:1317 src/exec_pty.c:1331
+#: src/exec_pty.c:1342 src/exec_pty.c:1344 src/exec_pty.c:1346
+#: src/exec_pty.c:1348 src/exec_pty.c:1350 src/exec_pty.c:1352
+#: src/exec_pty.c:1354 src/signal.c:156
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "instellen van handler voor signal %d is niet mogelijk"
+
+#: src/exec.c:135 src/exec_pty.c:845
+msgid "policy plugin failed session initialization"
+msgstr "beleidsplugin kon sessie niet initialiseren"
+
+#: src/exec.c:140 src/exec_pty.c:861 src/exec_pty.c:1392 src/tgetpass.c:221
+msgid "unable to fork"
+msgstr "kan geen nieuw proces starten"
+
+#: src/exec.c:318 src/exec.c:326 src/exec.c:877 src/exec_pty.c:604
+#: src/exec_pty.c:609 src/exec_pty.c:667 src/exec_pty.c:674 src/exec_pty.c:965
+#: src/exec_pty.c:975 src/exec_pty.c:1020 src/exec_pty.c:1027
+#: src/exec_pty.c:1457 src/exec_pty.c:1464 src/exec_pty.c:1471
+msgid "unable to add event to queue"
+msgstr "kan event niet toevoegen aan de wachtrij"
+
+#: src/exec.c:406
+msgid "unable to create sockets"
+msgstr "kan geen sockets maken"
+
+#: src/exec.c:502
+msgid "error in event loop"
+msgstr "fout in eventloop"
+
+#: src/exec.c:520
+msgid "unable to restore tty label"
+msgstr "kan terminallabel niet herstellen"
+
+#: src/exec.c:613 src/exec_pty.c:514 src/signal.c:95
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "kan handler voor signal %d niet herstellen"
+
+#: src/exec.c:731 src/exec_pty.c:1199
+msgid "error reading from signal pipe"
+msgstr "fout met het lezen van signaalpijp"
+
+#: src/exec_common.c:73
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "kan PRIV_PROC_EXEC niet verwijderen van PRIV_LIMIT"
+
+#: src/exec_pty.c:200
+msgid "unable to allocate pty"
+msgstr "kan geen virtuele terminal reserveren"
+
+#: src/exec_pty.c:780 src/exec_pty.c:789 src/exec_pty.c:797
+#: src/exec_pty.c:1300 src/exec_pty.c:1389 src/signal.c:137 src/tgetpass.c:218
+msgid "unable to create pipe"
+msgstr "kan geen pijp maken"
+
+#: src/exec_pty.c:836
+msgid "unable to set terminal to raw mode"
+msgstr "kan de terminal niet op de raw-modus instellen"
+
+#: src/exec_pty.c:1232
+msgid "error reading from pipe"
+msgstr "fout met lezen van pijp"
+
+#: src/exec_pty.c:1257
+msgid "error reading from socketpair"
+msgstr "fout met lezen van socketpaar"
+
+#: src/exec_pty.c:1266
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "onverwachte soort beantwoording van het achterkanaal: %d"
+
+#: src/exec_pty.c:1368
+msgid "unable to set controlling tty"
+msgstr "kan geen controlerende terminal instellen"
+
+#: src/load_plugins.c:59 src/load_plugins.c:72 src/load_plugins.c:89
+#: src/load_plugins.c:142 src/load_plugins.c:148 src/load_plugins.c:154
+#: src/load_plugins.c:195 src/load_plugins.c:202 src/load_plugins.c:209
+#: src/load_plugins.c:215
+#, c-format
+msgid "error in %s, line %d while loading plugin `%s'"
+msgstr "fout in %s, regel %d bij het initialiseren-I/O plug-in %s"
+
+#: src/load_plugins.c:91
+#, c-format
+msgid "%s%s: %s"
+msgstr "%s%s: %s"
+
+#: src/load_plugins.c:150
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "eigenaar van %s moet uid %d zijn"
+
+#: src/load_plugins.c:156
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "%s mag alleen schrijfbaar zijn voor de eigenaar"
+
+#: src/load_plugins.c:197
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "kan %s niet laden: %s"
+
+#: src/load_plugins.c:204
+#, c-format
+msgid "unable to find symbol `%s' in %s"
+msgstr "kan symbool %s niet vinden in %s"
+
+#: src/load_plugins.c:211
+#, c-format
+msgid "unknown policy type %d found in %s"
+msgstr "onbekende beleidssoort %d gevonden in %s"
+
+#: src/load_plugins.c:217
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "niet-compatibel hoofdbeleidsversie %d, (verwachtte %d) gevonden in %s voor plugins"
+
+#: src/load_plugins.c:226
+#, c-format
+msgid "ignoring policy plugin `%s' in %s, line %d"
+msgstr "beleidsplugin '%s' in %s, regel %d wordt genegeerd"
+
+#: src/load_plugins.c:228
+msgid "only a single policy plugin may be specified"
+msgstr "slechts een beleidsplug-in mag geladen worden"
+
+#: src/load_plugins.c:231
+#, c-format
+msgid "ignoring duplicate policy plugin `%s' in %s, line %d"
+msgstr "dubbele beleidsplugin '%s' in %s, regel %d wordt genegeerd"
+
+#: src/load_plugins.c:249
+#, c-format
+msgid "ignoring duplicate I/O plugin `%s' in %s, line %d"
+msgstr "dubbele I/O-plugin '%s' in %s, regel %d wordt genegeerd"
+
+#: src/load_plugins.c:338
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "beleidsplug-in %s heeft geen check_policy methode"
+
+#: src/net_ifs.c:236
+msgid "unable to open socket"
+msgstr "kan geen socket openen"
+
+#: src/parse_args.c:241
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "het argument van -C moet een getal zijn dat groter dan of gelijk aan 3 is"
+
+#: src/parse_args.c:403
+msgid "you may not specify both the `-i' and `-s' options"
+msgstr "u mag de opties '-i' en '-s' niet tegelijk opgeven"
+
+#: src/parse_args.c:407
+msgid "you may not specify both the `-i' and `-E' options"
+msgstr "u mag de opties '-i' en '-E' niet tegelijk opgeven"
+
+#: src/parse_args.c:417
+msgid "the `-E' option is not valid in edit mode"
+msgstr "optie '-E' is niet geldig in bewerkingsmodus"
+
+#: src/parse_args.c:419
+msgid "you may not specify environment variables in edit mode"
+msgstr "u mag geen omgevingsvariabelen opgeven in de bewerkingsmodus"
+
+#: src/parse_args.c:427
+msgid "the `-U' option may only be used with the `-l' option"
+msgstr "optie '-U' mag alleen worden gebruikt samen met optie '-l'"
+
+#: src/parse_args.c:431
+msgid "the `-A' and `-S' options may not be used together"
+msgstr "de opties '-A' en '-S' mogen niet tegelijk worden gebruikt"
+
+#: src/parse_args.c:497
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit wordt niet ondersteund op dit platform"
+
+#: src/parse_args.c:570
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Slechts een van de volgende opties mag worden gebruikt: -e, -h, -i, -K, -l, -s, -v of -V"
+
+#: src/parse_args.c:584
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - bewerk bestanden als een andere gebruiker\n"
+"\n"
+
+#: src/parse_args.c:586
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - voer een opdracht uit als een andere gebruiker\n"
+"\n"
+
+#: src/parse_args.c:591
+#, c-format
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Opties:\n"
+
+#: src/parse_args.c:593
+msgid "use a helper program for password prompting"
+msgstr "gebruik een hulpprogramma voor het vragen van wachtwoord"
+
+#: src/parse_args.c:596
+msgid "use specified BSD authentication type"
+msgstr "gebruik opgegeven BSD-verificatietype"
+
+#: src/parse_args.c:599
+msgid "run command in the background"
+msgstr "voer opdracht op de achtergrond uit"
+
+#: src/parse_args.c:601
+msgid "close all file descriptors >= num"
+msgstr "sluit alle file descriptors >= num"
+
+#: src/parse_args.c:604
+msgid "run command with the specified BSD login class"
+msgstr "voer opdracht uit met gespecificeerde BSD-inlogklasse"
+
+#: src/parse_args.c:607
+msgid "preserve user environment when running command"
+msgstr "behoud gebruikersomgeving bij uitvoeren van opdracht"
+
+#: src/parse_args.c:609
+msgid "edit files instead of running a command"
+msgstr "bewerk bestanden in plaats van uitvoeren van een opdracht"
+
+#: src/parse_args.c:611
+msgid "run command as the specified group name or ID"
+msgstr "voer opdracht uit als de opgegeven groep"
+
+#: src/parse_args.c:613
+msgid "set HOME variable to target user's home dir"
+msgstr "stel HOME variabele in om naar persoonlijke map van gebruiker te verwijzen"
+
+#: src/parse_args.c:615
+msgid "display help message and exit"
+msgstr "hulptekst tonen en stoppen"
+
+#: src/parse_args.c:617
+msgid "run command on host (if supported by plugin)"
+msgstr "voer opdracht uit op computer (enkel als plugin dit ondersteund)"
+
+#: src/parse_args.c:619
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "voer een inlogshell uit als beoogd gebruiker; een opdracht mag ook worden opgegeven"
+
+#: src/parse_args.c:621
+msgid "remove timestamp file completely"
+msgstr "verwijder tijdbestand volledig"
+
+#: src/parse_args.c:623
+msgid "invalidate timestamp file"
+msgstr "maak tijdbestand ongeldig"
+
+#: src/parse_args.c:625
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "geef privileges van gebruiker weer of controleer specifieke opdracht; gebuik twee keer voor uitgebreidere opmaak"
+
+#: src/parse_args.c:627
+msgid "non-interactive mode, no prompts are used"
+msgstr "niet-interactieve modus, geen interactie met gebruiker"
+
+#: src/parse_args.c:629
+msgid "preserve group vector instead of setting to target's"
+msgstr "behoud groepsvector in plaats van die van het doel in te stellen"
+
+#: src/parse_args.c:631
+msgid "use the specified password prompt"
+msgstr "gebruik gespecifeerde wachtwoordvraag"
+
+#: src/parse_args.c:634
+msgid "create SELinux security context with specified role"
+msgstr "maak SELinux beveiligingscontext met gespecificeerde rol aan"
+
+#: src/parse_args.c:637
+msgid "read password from standard input"
+msgstr "lees wachtwoord van standaardinvoer"
+
+#: src/parse_args.c:639
+msgid "run shell as the target user; a command may also be specified"
+msgstr "voer shell uit als doelgebruiker; een opdracht mag ook worden opgegeven"
+
+#: src/parse_args.c:642
+msgid "create SELinux security context with specified type"
+msgstr "maak SELinux beveiligingscontext met gespecificeerde type aan"
+
+#: src/parse_args.c:645
+msgid "in list mode, display privileges for user"
+msgstr "in lijstmodus, geef privileges voor gebruiker weer"
+
+#: src/parse_args.c:647
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "voer opdracht uit (of bewerk bestand) als gespecificeerde gebruiker"
+
+#: src/parse_args.c:649
+msgid "display version information and exit"
+msgstr "versie-informatie tonen en stoppen"
+
+#: src/parse_args.c:651
+msgid "update user's timestamp without running a command"
+msgstr "werk tijd van gebruiker bij zonder opdracht uit te voeren"
+
+#: src/parse_args.c:653
+msgid "stop processing command line arguments"
+msgstr "stop verwerken opdrachtregelargumenten"
+
+#: src/selinux.c:77
+msgid "unable to open audit system"
+msgstr "kan audit-systeem niet openen"
+
+#: src/selinux.c:85
+msgid "unable to send audit message"
+msgstr "kan audit-melding niet verzenden"
+
+#: src/selinux.c:113
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "fgetfilecon %s mislukt"
+
+#: src/selinux.c:118
+#, c-format
+msgid "%s changed labels"
+msgstr "%s gewijzigde labels"
+
+#: src/selinux.c:123
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "kan context voor %s niet herstellen"
+
+#: src/selinux.c:163
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "kan %s niet openen, terminaltitel wordt niet opnieuw ingesteld"
+
+#: src/selinux.c:172
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "kan huidige terminalcontext niet verkrijgen, terminaltitel wordt niet opniew ingesteld"
+
+#: src/selinux.c:179
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "kan geen nieuwe terminalcontext verkrijgen, terminaltitel wordt niet opnieuw ingesteld"
+
+#: src/selinux.c:186
+msgid "unable to set new tty context"
+msgstr "kan nieuwe terminalcontext niet instellen"
+
+#: src/selinux.c:252
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "u moet een rol kiezen voor type %s"
+
+#: src/selinux.c:258
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "kan standaard-type niet verkrijgen voor rol %s"
+
+#: src/selinux.c:276
+#, c-format
+msgid "failed to set new role %s"
+msgstr "instellen van nieuwe rol %s mislukt"
+
+#: src/selinux.c:280
+#, c-format
+msgid "failed to set new type %s"
+msgstr "instellen van nieuw type %s mislukt"
+
+#: src/selinux.c:289
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s is geen geldige context"
+
+#: src/selinux.c:324
+msgid "failed to get old_context"
+msgstr "verkrijgen old_context mislukt"
+
+#: src/selinux.c:330
+msgid "unable to determine enforcing mode."
+msgstr "kan afdwingende modus niet vinden."
+
+#: src/selinux.c:347
+#, c-format
+msgid "unable to set tty context to %s"
+msgstr "kan terminalcontext niet instellen voor %s"
+
+#: src/selinux.c:386
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "kan uitvoeringscontext niet instellen op %s"
+
+#: src/selinux.c:393
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "kan context voor aanmaak van sleutels niet instellen op %s"
+
+#: src/sesh.c:80
+msgid "requires at least one argument"
+msgstr "tenminste één argument vereist"
+
+#: src/sesh.c:109
+#, c-format
+msgid "unable to run %s as a login shell"
+msgstr "kan %s niet uitvoeren als een loginshell"
+
+#: src/sesh.c:114 src/sudo.c:1186
+#, c-format
+msgid "unable to execute %s"
+msgstr "kan %s niet uitvoeren"
+
+#: src/signal.c:77
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "kan handler niet opslaan naar signaal %d"
+
+#: src/solaris.c:88
+msgid "resource control limit has been reached"
+msgstr "hulpbroncontrolelimiet is bereikt"
+
+#: src/solaris.c:91
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "gebruiker \"%s\" is geen lid van project \"%s\""
+
+#: src/solaris.c:95
+msgid "the invoking task is final"
+msgstr "de aanroepende taak is klaar"
+
+#: src/solaris.c:98
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "kan project \"%s\" niet samenvoegen"
+
+#: src/solaris.c:103
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "er bestaat geen hulpbronnengroep voor project \"%s\" die de standaardbindingen accepteert"
+
+#: src/solaris.c:107
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "er bestaat geen hulpbronnengroep voor project \"%s\" die de standaardbindingen accepteert"
+
+#: src/solaris.c:111
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "kan niet verbinden met standaard hulpbronnen voor project \"%s\""
+
+#: src/solaris.c:117
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "setproject mislukt voor project \"%s\""
+
+#: src/solaris.c:119
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "waarschuwing, hulpbrontoewijzingscontrole mislukt voor project \"%s\""
+
+#: src/sudo.c:209
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo versie %s\n"
+
+#: src/sudo.c:211
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Configuratieopties: %s\n"
+
+#: src/sudo.c:216
+msgid "fatal error, unable to load plugins"
+msgstr "fatale fout, kan geen plug-ins laden"
+
+#: src/sudo.c:224
+msgid "unable to initialize policy plugin"
+msgstr "kan beleidsplug-in niet instellen"
+
+#: src/sudo.c:280
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "fout bij initialiseren-I/O plug-in %s"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "onverwachte sudo modus 0x%x"
+
+#: src/sudo.c:426
+msgid "unable to get group vector"
+msgstr "kan groepsvector niet verkrijgen"
+
+#: src/sudo.c:478
+#, c-format
+msgid "unknown uid %u: who are you?"
+msgstr "onbekende uid %u: wie bent u?"
+
+#: src/sudo.c:785
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "eigenaar van %s moet gebruikersnummer %d zijn en de setuid bit ingesteld"
+
+#: src/sudo.c:788
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "gebruikt gebruikersnummer is niet %d, is %s op een bestandssysteem met de 'nosuid' optie ingesteld of een NFS bestandssysteem zonder rootrechten?"
+
+#: src/sudo.c:794
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "gebruikt gebruikersnummer is niet %d, is sudo geinstalleerd met setuid root?"
+
+#: src/sudo.c:923
+#, c-format
+msgid "unknown login class %s"
+msgstr "onbekende inlog-klasse %s"
+
+#: src/sudo.c:936
+msgid "unable to set user context"
+msgstr "kan gebruikerscontext niet instellen"
+
+#: src/sudo.c:950
+msgid "unable to set supplementary group IDs"
+msgstr "kan aanvullende groeps-ID's niet instellen"
+
+#: src/sudo.c:957
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "kan effectieve gid niet instellen op runas-gid %u"
+
+#: src/sudo.c:963
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "kan gid niet instellen op runas-gid %u"
+
+#: src/sudo.c:970
+msgid "unable to set process priority"
+msgstr "kan taakprioriteit niet instellen"
+
+#: src/sudo.c:978
+#, c-format
+msgid "unable to change root to %s"
+msgstr "kan root niet wijzigen naar %s"
+
+#: src/sudo.c:991 src/sudo.c:997 src/sudo.c:1003
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "kan niet wijzigen naar runas uid (%u, %u)"
+
+#: src/sudo.c:1021
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "kan map niet wijzigen naar %s"
+
+#: src/sudo.c:1082
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "onverwachte dochter-afsluitvoorwaarde: %d"
+
+#: src/sudo.c:1214
+#, c-format
+msgid "policy plugin %s is missing the `check_policy' method"
+msgstr "beleidsplug-in %s heeft geen check_policy methode"
+
+#: src/sudo.c:1232
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "beleidsplug-in %s ondersteunt niet het tonen van privileges"
+
+#: src/sudo.c:1249
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "beleidsplug-in %s ondersteunt niet de -v optie"
+
+#: src/sudo.c:1264
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "beleidsplug-in %s ondersteunt niet de -k/-K opties"
+
+#: src/sudo_edit.c:203 src/sudo_edit.c:294
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: geen regulier bestand"
+
+#: src/sudo_edit.c:230 src/sudo_edit.c:332
+#, c-format
+msgid "%s: short write"
+msgstr "%s: te weinig geschreven"
+
+#: src/sudo_edit.c:295
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s ongewijzigd gelaten"
+
+#: src/sudo_edit.c:308 src/sudo_edit.c:483
+#, c-format
+msgid "%s unchanged"
+msgstr "%s ongewijzigd"
+
+#: src/sudo_edit.c:321 src/sudo_edit.c:343
+#, c-format
+msgid "unable to write to %s"
+msgstr "kan niet schrijven naar %s"
+
+#: src/sudo_edit.c:322 src/sudo_edit.c:341 src/sudo_edit.c:344
+#: src/sudo_edit.c:508 src/sudo_edit.c:512
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "inhoud van bewerkingssessie achtergelaten in %s"
+
+#: src/sudo_edit.c:340
+msgid "unable to read temporary file"
+msgstr "kan tijdelijk bestand niet lezen"
+
+#: src/sudo_edit.c:417
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: interne fout: oneven aantal paden"
+
+#: src/sudo_edit.c:419
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: kan geen tijdelijke bestanden aanmaken "
+
+#: src/sudo_edit.c:421 src/sudo_edit.c:515
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: onbekende fout %d"
+
+#: src/sudo_edit.c:507
+msgid "unable to copy temporary files back to their original location"
+msgstr "kan tijdelijke bestanden niet terugzetten naar de oorsprongelijke lokatie"
+
+#: src/sudo_edit.c:511
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "kan sommige tijdelijke bestanden niet terugzetten naar de oorsprongelijke lokatie"
+
+#: src/sudo_edit.c:554
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "kan uid niet wijzigen naar root (%u)"
+
+#: src/sudo_edit.c:571
+msgid "plugin error: missing file list for sudoedit"
+msgstr "plug-infout: missende bestandslijst voor sudoedit"
+
+#: src/tgetpass.c:90
+msgid "no tty present and no askpass program specified"
+msgstr "geen terminal aanwezig en geen wachtwoordvraag(askpass)-programma opgegeven"
+
+#: src/tgetpass.c:99
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "geen wachtwoordvraag(askpass)-programma opgegeven, probeer SUDO_ASKPASS in te stellen"
+
+#: src/tgetpass.c:232
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "kan gid niet instellen op %u"
+
+#: src/tgetpass.c:236
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "kan uid niet instellen op %u"
+
+#: src/tgetpass.c:241
+#, c-format
+msgid "unable to run %s"
+msgstr "kan %s niet uitvoeren"
+
+#: src/utmp.c:278
+msgid "unable to save stdin"
+msgstr "kan niet opslaan naar stdin"
+
+#: src/utmp.c:280
+msgid "unable to dup2 stdin"
+msgstr "kan dup2 niet uitvoeren op standaardinvoer"
+
+#: src/utmp.c:283
+msgid "unable to restore stdin"
+msgstr "kan stdin niet herstellen"
+
+#~ msgid "internal error, tried to emalloc2(0)"
+#~ msgstr "interne fout, probeerde emalloc2(0)"
+
+#~ msgid "internal error, tried to ecalloc(0)"
+#~ msgstr "interne fout, probeerde ecalloc(0)"
+
+#~ msgid "internal error, tried to erealloc(0)"
+#~ msgstr "interne fout, probeerde erealloc(0)"
+
+#~ msgid "internal error, tried to erealloc3(0)"
+#~ msgstr "interne fout, probeerde erealloc3(0)"
+
+#~ msgid "internal error, tried to erecalloc(0)"
+#~ msgstr "interne fout, probeerde erecalloc(0)"
+
+#~ msgid "value out of range"
+#~ msgstr "waarde buiten bereik"
+
+#~ msgid "%s: %s: %s\n"
+#~ msgstr "%s: %s: %s\n"
+
+#~ msgid "%s: %s\n"
+#~ msgstr "%s: %s\n"
+
+#~ msgid "select failed"
+#~ msgstr "selecteren mislukt"
+
+#~ msgid "load_interfaces: overflow detected"
+#~ msgstr "load_interfaces: overloop gevonden"
+
+#~ msgid "unable to allocate memory"
+#~ msgstr "kan geen geheugen reserveren"
+
+#~ msgid ": "
+#~ msgstr ": "
+
+#~ msgid "list user's available commands\n"
+#~ msgstr "geef voor gebruiker beschikbare opdrachten weer\n"
+
+#~ msgid "run a shell as target user\n"
+#~ msgstr "voer een shell uit als doel-gebruiker\n"
+
+#~ msgid "when listing, list specified user's privileges\n"
+#~ msgstr "bij listing, toon privileges van gespecificeerde gebruiker\n"
diff --git a/po/nn.mo b/po/nn.mo
new file mode 100644
index 0000000..40a0091
--- /dev/null
+++ b/po/nn.mo
Binary files differ
diff --git a/po/nn.po b/po/nn.po
new file mode 100644
index 0000000..14a8045
--- /dev/null
+++ b/po/nn.po
@@ -0,0 +1,934 @@
+# Norwegian Nynorsk translation of sudo.
+# This file is distributed under the same license as the sudo package.
+#
+# Karl Ove Hufthammer <karl@huftis.org>, 2016.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.8.18b4\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2016-08-31 05:48-0600\n"
+"PO-Revision-Date: 2016-09-04 19:09+0100\n"
+"Last-Translator: Karl Ove Hufthammer <karl@huftis.org>\n"
+"Language-Team: Norwegian Nynorsk <i18n-nn@lister.ping.uio.no>\n"
+"Language: nn\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Lokalize 2.0\n"
+
+#: lib/util/aix.c:85 lib/util/aix.c:172
+msgid "unable to open userdb"
+msgstr "klarte ikkje opna brukardatabase"
+
+#: lib/util/aix.c:227
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "klarte ikkje byta til registeret «%s» for %s"
+
+#: lib/util/aix.c:252
+msgid "unable to restore registry"
+msgstr "klarte ikkje gjenoppretta register"
+
+#: lib/util/aix.c:275 lib/util/gidlist.c:64 lib/util/gidlist.c:74
+#: lib/util/sudo_conf.c:207 lib/util/sudo_conf.c:290 lib/util/sudo_conf.c:367
+#: lib/util/sudo_conf.c:569 src/conversation.c:75 src/exec.c:868
+#: src/exec_common.c:107 src/exec_common.c:123 src/exec_common.c:132
+#: src/exec_pty.c:692 src/exec_pty.c:700 src/exec_pty.c:1163
+#: src/load_plugins.c:52 src/load_plugins.c:65 src/load_plugins.c:215
+#: src/load_plugins.c:238 src/load_plugins.c:303 src/load_plugins.c:318
+#: src/parse_args.c:180 src/parse_args.c:202 src/parse_args.c:370
+#: src/parse_args.c:466 src/parse_args.c:485 src/preserve_fds.c:47
+#: src/preserve_fds.c:130 src/selinux.c:83 src/selinux.c:292 src/selinux.c:415
+#: src/selinux.c:424 src/sesh.c:115 src/sudo.c:399 src/sudo.c:418
+#: src/sudo.c:482 src/sudo.c:600 src/sudo.c:660 src/sudo.c:670 src/sudo.c:690
+#: src/sudo.c:709 src/sudo.c:718 src/sudo.c:727 src/sudo.c:744 src/sudo.c:785
+#: src/sudo.c:795 src/sudo.c:815 src/sudo.c:1236 src/sudo.c:1257
+#: src/sudo.c:1431 src/sudo.c:1525 src/sudo_edit.c:151 src/sudo_edit.c:773
+#: src/sudo_edit.c:870 src/sudo_edit.c:983 src/sudo_edit.c:1003
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:275 lib/util/gidlist.c:64 lib/util/sudo_conf.c:208
+#: lib/util/sudo_conf.c:290 lib/util/sudo_conf.c:367 lib/util/sudo_conf.c:569
+#: src/conversation.c:76 src/exec.c:868 src/exec_common.c:107
+#: src/exec_common.c:124 src/exec_common.c:133 src/exec_pty.c:692
+#: src/exec_pty.c:700 src/load_plugins.c:215 src/load_plugins.c:238
+#: src/load_plugins.c:303 src/load_plugins.c:318 src/parse_args.c:180
+#: src/parse_args.c:202 src/parse_args.c:370 src/parse_args.c:466
+#: src/parse_args.c:485 src/preserve_fds.c:47 src/preserve_fds.c:130
+#: src/selinux.c:83 src/selinux.c:292 src/selinux.c:415 src/selinux.c:424
+#: src/sesh.c:115 src/sudo.c:399 src/sudo.c:418 src/sudo.c:482 src/sudo.c:600
+#: src/sudo.c:815 src/sudo.c:1236 src/sudo.c:1257 src/sudo.c:1431
+#: src/sudo.c:1525 src/sudo_edit.c:151 src/sudo_edit.c:773 src/sudo_edit.c:870
+#: src/sudo_edit.c:983 src/sudo_edit.c:1003
+msgid "unable to allocate memory"
+msgstr "klarte ikkje tildela minne"
+
+#: lib/util/strsignal.c:48
+msgid "Unknown signal"
+msgstr "Ukjent signal"
+
+#: lib/util/strtoid.c:76 lib/util/strtoid.c:104 lib/util/strtomode.c:48
+#: lib/util/strtonum.c:58 lib/util/strtonum.c:176
+msgid "invalid value"
+msgstr "ugyldig verdi"
+
+#: lib/util/strtoid.c:83 lib/util/strtoid.c:111 lib/util/strtomode.c:54
+#: lib/util/strtonum.c:61 lib/util/strtonum.c:188
+msgid "value too large"
+msgstr "verdien er for stor"
+
+#: lib/util/strtoid.c:89 lib/util/strtomode.c:54 lib/util/strtonum.c:61
+#: lib/util/strtonum.c:182
+msgid "value too small"
+msgstr "verdien er for liten"
+
+#: lib/util/sudo_conf.c:223
+#, fuzzy, c-format
+msgid "invalid Path value `%s' in %s, line %u"
+msgstr "«%s» er ein ugyldig Path-verdi i %s, linje %u"
+
+#: lib/util/sudo_conf.c:389 lib/util/sudo_conf.c:442
+#, fuzzy, c-format
+msgid "invalid value for %s `%s' in %s, line %u"
+msgstr "«%2$s» er ein ugyldig verdi for %1$s i %3$s, linje %4$u"
+
+#: lib/util/sudo_conf.c:410
+#, c-format
+msgid "unsupported group source `%s' in %s, line %u"
+msgstr "gruppekjelda «%s» (i %s, linje %u) er ikkje støtta"
+
+#: lib/util/sudo_conf.c:426
+#, fuzzy, c-format
+msgid "invalid max groups `%s' in %s, line %u"
+msgstr "«%s» er eit ugyldig maskimalt mengd grupper i %s, linje %u"
+
+#: lib/util/sudo_conf.c:585
+#, fuzzy, c-format
+msgid "unable to stat %s"
+msgstr "klarte ikkje laga statistikk av %s"
+
+#: lib/util/sudo_conf.c:588
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s er ikkje ei vanleg fil"
+
+#: lib/util/sudo_conf.c:591
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "«%s» er eigd av uid %u, som skulle vore %u"
+
+#: lib/util/sudo_conf.c:595
+#, c-format
+msgid "%s is world writable"
+msgstr "%s er skrivbar for alle"
+
+#: lib/util/sudo_conf.c:598
+#, c-format
+msgid "%s is group writable"
+msgstr "%s er skrivbar for eigargruppa"
+
+#: lib/util/sudo_conf.c:608 src/selinux.c:201 src/selinux.c:213 src/sudo.c:368
+#, c-format
+msgid "unable to open %s"
+msgstr "klarte ikkje opna %s"
+
+#: src/exec.c:115 src/exec.c:117 src/exec.c:122 src/exec.c:408 src/exec.c:410
+#: src/exec.c:412 src/exec.c:414 src/exec.c:416 src/exec.c:418 src/exec.c:421
+#: src/exec.c:437 src/exec.c:439 src/exec.c:600 src/exec.c:795
+#: src/exec_pty.c:464 src/exec_pty.c:730 src/exec_pty.c:800 src/exec_pty.c:802
+#: src/exec_pty.c:814 src/exec_pty.c:816 src/exec_pty.c:1346
+#: src/exec_pty.c:1348 src/exec_pty.c:1353 src/exec_pty.c:1355
+#: src/exec_pty.c:1369 src/exec_pty.c:1380 src/exec_pty.c:1382
+#: src/exec_pty.c:1384 src/exec_pty.c:1386 src/exec_pty.c:1388
+#: src/exec_pty.c:1390 src/exec_pty.c:1392 src/signal.c:148 src/signal.c:162
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "klarte ikkje velja handtering av signal %d"
+
+#: src/exec.c:127 src/exec_pty.c:846 src/exec_pty.c:1430 src/tgetpass.c:259
+#, fuzzy
+msgid "unable to fork"
+msgstr "klarte ikkje laga kopi av prosess"
+
+#: src/exec.c:303 src/exec.c:311 src/exec.c:873 src/exec_pty.c:585
+#: src/exec_pty.c:590 src/exec_pty.c:660 src/exec_pty.c:667 src/exec_pty.c:954
+#: src/exec_pty.c:964 src/exec_pty.c:1009 src/exec_pty.c:1016
+#: src/exec_pty.c:1041 src/exec_pty.c:1495 src/exec_pty.c:1502
+#: src/exec_pty.c:1509
+msgid "unable to add event to queue"
+msgstr "klarte ikkje leggja hending i kø"
+
+#: src/exec.c:391
+msgid "unable to create sockets"
+msgstr "klarte ikkje laga socket-ar"
+
+#: src/exec.c:446
+#, fuzzy
+msgid "policy plugin failed session initialization"
+msgstr "regeltillegg klarte ikkje starta økt"
+
+#: src/exec.c:491
+msgid "error in event loop"
+msgstr "feil i hendingslykkje"
+
+#: src/exec.c:509
+msgid "unable to restore tty label"
+msgstr "klarte ikkje gjenoppretta tty-etikett"
+
+#: src/exec.c:608 src/exec_pty.c:496 src/signal.c:87
+#, fuzzy, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "klarte ikkje retta opp igjen handtering av signal %d"
+
+#: src/exec.c:726 src/exec_pty.c:1235
+msgid "error reading from signal pipe"
+msgstr "feil ved lesing frå signalrøyr"
+
+#: src/exec_common.c:166
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "klarte ikkje fjerna PRIV_PROC_EXEC frå PRIV_LIMIT"
+
+#: src/exec_pty.c:188
+msgid "unable to allocate pty"
+msgstr "klarte ikkje tildela pty"
+
+#: src/exec_pty.c:774 src/exec_pty.c:783 src/exec_pty.c:791
+#: src/exec_pty.c:1338 src/exec_pty.c:1427 src/signal.c:129 src/tgetpass.c:255
+msgid "unable to create pipe"
+msgstr "klarte ikkje laga datarøyr"
+
+#: src/exec_pty.c:1268
+msgid "error reading from pipe"
+msgstr "feil ved lesing frå datarøyr"
+
+#: src/exec_pty.c:1295
+msgid "error reading from socketpair"
+msgstr "feil ved lesing frå socketpar"
+
+#: src/exec_pty.c:1304
+#, fuzzy, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "uventa responstype i bak-kanalen: %d"
+
+#: src/exec_pty.c:1406
+msgid "unable to set controlling tty"
+msgstr "klarte ikkje velja styrande tty"
+
+#: src/load_plugins.c:50 src/load_plugins.c:63 src/load_plugins.c:85
+#: src/load_plugins.c:115 src/load_plugins.c:123 src/load_plugins.c:129
+#: src/load_plugins.c:170 src/load_plugins.c:178 src/load_plugins.c:185
+#: src/load_plugins.c:191
+#, c-format
+msgid "error in %s, line %d while loading plugin `%s'"
+msgstr "feil i %s, linje %d ved lasting av tillegget «%s»"
+
+#: src/load_plugins.c:87
+#, c-format
+msgid "%s%s: %s"
+msgstr "%s%s: %s"
+
+#: src/load_plugins.c:125
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s må eigast av uid %d"
+
+#: src/load_plugins.c:131
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "%s kan ikkje vera skrivbar for andre enn eigar"
+
+#: src/load_plugins.c:172
+#, fuzzy, c-format
+msgid "unable to load %s: %s"
+msgstr "klarte ikkje lasta inn «%s». %s"
+
+#: src/load_plugins.c:180
+#, fuzzy, c-format
+msgid "unable to find symbol `%s' in %s"
+msgstr "fann ikkje symbolet «%s» i %s"
+
+#: src/load_plugins.c:187
+#, fuzzy, c-format
+msgid "unknown policy type %d found in %s"
+msgstr "regeltypen «%d», som vart funne i «%s», er ukjent"
+
+#: src/load_plugins.c:193
+#, fuzzy, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "ukompatibel versjon av programtillegg %d (forventa %d) vart funnen i «%s»"
+
+#: src/load_plugins.c:202
+#, fuzzy, c-format
+msgid "ignoring policy plugin `%s' in %s, line %d"
+msgstr "regeltillegg «%s» i «%s» linje %d vert ignorert"
+
+#: src/load_plugins.c:204
+#, fuzzy
+msgid "only a single policy plugin may be specified"
+msgstr "du kan berre velja eitt regeltillegg"
+
+#: src/load_plugins.c:207
+#, fuzzy, c-format
+msgid "ignoring duplicate policy plugin `%s' in %s, line %d"
+msgstr "duplikattillegget «%s» i «%s» linje %d vert ignorert"
+
+#: src/load_plugins.c:228
+#, fuzzy, c-format
+msgid "ignoring duplicate I/O plugin `%s' in %s, line %d"
+msgstr "duplikattillegget «%s» for inn- og utdata i «%s» line %d vert ignorert"
+
+#: src/load_plugins.c:331
+#, fuzzy, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "regeltillegget «%s» inneheld ikkje ein «check_policy»-metode"
+
+#: src/net_ifs.c:173 src/net_ifs.c:190 src/net_ifs.c:335 src/sudo.c:477
+#, fuzzy, c-format
+msgid "internal error, %s overflow"
+msgstr "intern feil: %s er full"
+
+#: src/parse_args.c:239
+#, fuzzy
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "«-C» må brukast med eit talargument med ein verdi på minst 3"
+
+#: src/parse_args.c:406
+#, fuzzy
+msgid "you may not specify both the `-i' and `-s' options"
+msgstr "du kan ikkje velja både «-i» og «-s»"
+
+#: src/parse_args.c:410
+#, fuzzy
+msgid "you may not specify both the `-i' and `-E' options"
+msgstr "du kan ikkje velja både «-i» og «-E»"
+
+#: src/parse_args.c:420
+#, fuzzy
+msgid "the `-E' option is not valid in edit mode"
+msgstr "valet «-E» er ugyldig i redigeringsmodus"
+
+#: src/parse_args.c:422
+#, fuzzy
+msgid "you may not specify environment variables in edit mode"
+msgstr "du kan ikkje velja miljøvariablar i redigeringsmodus"
+
+#: src/parse_args.c:430
+#, fuzzy
+msgid "the `-U' option may only be used with the `-l' option"
+msgstr "valet «-U» kan ikkje brukast utan «-l»"
+
+#: src/parse_args.c:434
+#, fuzzy
+msgid "the `-A' and `-S' options may not be used together"
+msgstr "vala «-A» og «-S» kan ikkje verta samstundes brukt"
+
+#: src/parse_args.c:504
+#, fuzzy
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit vert ikkje støtta på denne plattforma"
+
+#: src/parse_args.c:577
+#, fuzzy
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Du kan berre velja eitt av vala -e, -h, -i, -K, -l, -s, -v eller -V"
+
+#: src/parse_args.c:591
+#, fuzzy, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - rediger filer som om du var ein annan nytter\n"
+"\n"
+
+#: src/parse_args.c:593
+#, fuzzy, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - køyr ein kommando som om du var ein annan nytter\n"
+"\n"
+
+#: src/parse_args.c:598
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Val:\n"
+
+#: src/parse_args.c:600
+#, fuzzy
+msgid "use a helper program for password prompting"
+msgstr "nytte eit hjelpeprogram for å oppgje passord"
+
+#: src/parse_args.c:603
+#, fuzzy
+msgid "use specified BSD authentication type"
+msgstr "nytte valt BSD-autentiseringsmetode"
+
+#: src/parse_args.c:606
+#, fuzzy
+msgid "run command in the background"
+msgstr "køyr kommando i bakgrunnen"
+
+#: src/parse_args.c:608
+#, fuzzy
+msgid "close all file descriptors >= num"
+msgstr "lukk alle fildeskriptorer >= num"
+
+#: src/parse_args.c:611
+#, fuzzy
+msgid "run command with the specified BSD login class"
+msgstr "køyr kommando med valt BSD-innloggingsklasse"
+
+#: src/parse_args.c:614
+#, fuzzy
+msgid "preserve user environment when running command"
+msgstr "hald på gjeldande brukarmiljø når kommandoen vert køyrt"
+
+#: src/parse_args.c:616
+#, fuzzy
+msgid "edit files instead of running a command"
+msgstr "rediger filer i staden for å køyra ein kommando"
+
+#: src/parse_args.c:618
+#, fuzzy
+msgid "run command as the specified group name or ID"
+msgstr "køyr kommando som om du var ein del av vald gruppe (-namn eller -ID)"
+
+#: src/parse_args.c:620
+#, fuzzy
+msgid "set HOME variable to target user's home dir"
+msgstr "nytte vald nytter sine hjemmemappe som HOME-miljøvariabel"
+
+#: src/parse_args.c:622
+#, fuzzy
+msgid "display help message and exit"
+msgstr "vis hjelpetekst og avslutt"
+
+#: src/parse_args.c:624
+#, fuzzy
+msgid "run command on host (if supported by plugin)"
+msgstr "køyr kommando på verten (viss programtillegget støttar det)"
+
+#: src/parse_args.c:626
+#, fuzzy
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "køyr innloggingsskall som om du var den valde brukaren (du kan òg oppgje ein kommando her)"
+
+#: src/parse_args.c:628
+#, fuzzy
+msgid "remove timestamp file completely"
+msgstr "fjern tidsstempel-fil skikkeleg"
+
+#: src/parse_args.c:630
+#, fuzzy
+msgid "invalidate timestamp file"
+msgstr "gjer tidsstempel-fil ugyldig"
+
+#: src/parse_args.c:632
+#, fuzzy
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "privilegia til vise brukaren, eller sjekk om det fungerer å køyra ein bestemd kommando (nytte to gonger for å sjå eit lengre format)"
+
+#: src/parse_args.c:634
+#, fuzzy
+msgid "non-interactive mode, no prompts are used"
+msgstr "stillemodus (ingen ledetekst vert vist)"
+
+#: src/parse_args.c:636
+#, fuzzy
+msgid "preserve group vector instead of setting to target's"
+msgstr "hald på gruppevektor, i staden for å bruka han som gjeld for målet"
+
+#: src/parse_args.c:638
+#, fuzzy
+msgid "use the specified password prompt"
+msgstr "nytte valt passord-ledetekst"
+
+#: src/parse_args.c:641
+#, fuzzy
+msgid "create SELinux security context with specified role"
+msgstr "lag SELinux-tryggleikskontekst med vald rolle"
+
+#: src/parse_args.c:644
+#, fuzzy
+msgid "read password from standard input"
+msgstr "les passord frå standard inndata"
+
+#: src/parse_args.c:646
+#, fuzzy
+msgid "run shell as the target user; a command may also be specified"
+msgstr "køyr skal som vald brukar (du kan òg oppgje ein kommando her)"
+
+#: src/parse_args.c:649
+#, fuzzy
+msgid "create SELinux security context with specified type"
+msgstr "lag SELinux-tryggleikskontekst med vald type"
+
+#: src/parse_args.c:652
+#, fuzzy
+msgid "in list mode, display privileges for user"
+msgstr "vis brukarprivilegium (i listemodus)"
+
+#: src/parse_args.c:654
+#, fuzzy
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "køyr kommando (eller rediger fil) som valt brukarnamn eller nytter-ID"
+
+#: src/parse_args.c:656
+#, fuzzy
+msgid "display version information and exit"
+msgstr "vis programversjon og avslutt"
+
+#: src/parse_args.c:658
+#, fuzzy
+msgid "update user's timestamp without running a command"
+msgstr "oppdater brukaren sin tidsstempel utan å køyra ein kommando"
+
+#: src/parse_args.c:660
+#, fuzzy
+msgid "stop processing command line arguments"
+msgstr "slutt å handsama kommandolinje-argument"
+
+#: src/selinux.c:77
+#, fuzzy
+msgid "unable to open audit system"
+msgstr "klarte ikkje opna revisjonssystemet"
+
+#: src/selinux.c:87
+#, fuzzy
+msgid "unable to send audit message"
+msgstr "klarte ikkje senda revisjonsmelding"
+
+#: src/selinux.c:115
+#, fuzzy, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "klarte ikkje utføra fgetfilecon %s"
+
+#: src/selinux.c:120
+#, fuzzy, c-format
+msgid "%s changed labels"
+msgstr "%s endra etikettar"
+
+#: src/selinux.c:125
+#, fuzzy, c-format
+msgid "unable to restore context for %s"
+msgstr "klarte ikkje retta opp igjen kontekst for «%s»"
+
+#: src/selinux.c:165
+#, fuzzy, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "klarte ikkje opna «%s». tty får ikkje ny etikett"
+
+#: src/selinux.c:173
+#, fuzzy
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "klarte ikkje henta gjeldande tty-kontekst. tty får ikkje ny etikett"
+
+#: src/selinux.c:180
+#, fuzzy
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "«chr_file» er ugyldig tryggleiksklasse. tty får ikkje ny etikett"
+
+#: src/selinux.c:185
+#, fuzzy
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "klrate ikkje henta ny tty-kontekst. tty får ikkje ny etikett"
+
+#: src/selinux.c:192
+#, fuzzy
+msgid "unable to set new tty context"
+msgstr "klarte ikkje velja ny tty-kontekst"
+
+#: src/selinux.c:256
+#, fuzzy, c-format
+msgid "you must specify a role for type %s"
+msgstr "du må velja ei rolle for typen «%s»"
+
+#: src/selinux.c:262
+#, fuzzy, c-format
+msgid "unable to get default type for role %s"
+msgstr "klarte ikkje henta standardtype for rollen «%s»"
+
+#: src/selinux.c:280
+#, fuzzy, c-format
+msgid "failed to set new role %s"
+msgstr "klarte ikkje velja den nye rollen «%s»"
+
+#: src/selinux.c:284
+#, fuzzy, c-format
+msgid "failed to set new type %s"
+msgstr "klarte ikkje velja den nye typen «%s»"
+
+#: src/selinux.c:296
+#, fuzzy, c-format
+msgid "%s is not a valid context"
+msgstr "«%s» er ein ugyldig kontekst"
+
+#: src/selinux.c:331
+#, fuzzy
+msgid "failed to get old_context"
+msgstr "klarte ikkje henta «old_context»"
+
+#: src/selinux.c:337
+#, fuzzy
+msgid "unable to determine enforcing mode."
+msgstr "klarte ikkje finna håndhevelsesmodus."
+
+#: src/selinux.c:354
+#, fuzzy, c-format
+msgid "unable to set tty context to %s"
+msgstr "klarte ikkje velja «%s» som tty-kontekst"
+
+#: src/selinux.c:393
+#, fuzzy, c-format
+msgid "unable to set exec context to %s"
+msgstr "klarte ikkje velja «%s» som kjørekontekst"
+
+#: src/selinux.c:400
+#, fuzzy, c-format
+msgid "unable to set key creation context to %s"
+msgstr "klarte ikkje velja «%s» som nøkkelkontekst"
+
+#: src/sesh.c:77
+#, fuzzy
+msgid "requires at least one argument"
+msgstr "krev at du brukar minst eitt argument"
+
+#: src/sesh.c:106
+#, fuzzy, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "ugyldig fildeskriptor-tal: %s"
+
+#: src/sesh.c:120
+#, fuzzy, c-format
+msgid "unable to run %s as a login shell"
+msgstr "klarte ikkje køyra %s som eit innloggingsskall"
+
+#: src/sesh.c:125 src/sudo.c:1295
+#, fuzzy, c-format
+msgid "unable to execute %s"
+msgstr "klarte ikkje køyra «%s»"
+
+#: src/signal.c:69
+#, fuzzy, c-format
+msgid "unable to save handler for signal %d"
+msgstr "klarte ikkje lagra handtering av signal %d"
+
+#: src/solaris.c:76
+#, fuzzy
+msgid "resource control limit has been reached"
+msgstr "kontrollgrensa for ressursar er nådd"
+
+#: src/solaris.c:79
+#, fuzzy, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "brukaren «%s» er ikkje medlem av prosjektet «%s»"
+
+#: src/solaris.c:83
+#, fuzzy
+msgid "the invoking task is final"
+msgstr "den kallande oppgåva er endeleg"
+
+#: src/solaris.c:86
+#, fuzzy, c-format
+msgid "could not join project \"%s\""
+msgstr "klarte ikkje verta med i prosjektet «%s»"
+
+#: src/solaris.c:91
+#, fuzzy, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "det er ingen ressursgrunnlag som godtek standardtildelinger for prosjektet «%s»"
+
+#: src/solaris.c:95
+#, fuzzy, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "fann ikkje valt ressursgrunnlag for prosjetet «%s»"
+
+#: src/solaris.c:99
+#, fuzzy, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "klarte ikkje tildela standard ressursgrunnlag for prosjektet «%s»"
+
+#: src/solaris.c:105
+#, fuzzy, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "klarte ikkje utføra «setproject» på «%s»"
+
+#: src/solaris.c:107
+#, fuzzy, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "åtvaring: noko gjekk gale ved tildeling av ressurskontroll for prosjektet «%s»"
+
+#: src/sudo.c:215
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo versjon %s\n"
+
+#: src/sudo.c:217
+#, fuzzy, c-format
+msgid "Configure options: %s\n"
+msgstr "Vel innstillingar: %s\n"
+
+#: src/sudo.c:225
+#, fuzzy
+msgid "fatal error, unable to load plugins"
+msgstr "kritisk feil: klarte ikkje lasta inn tilleggsprogram"
+
+#: src/sudo.c:233
+#, fuzzy
+msgid "unable to initialize policy plugin"
+msgstr "klarte ikkje starta opp regeltillegg"
+
+#: src/sudo.c:277
+#, fuzzy
+msgid "plugin did not return a command to execute"
+msgstr "tillegget sende ikkje ein kjørbar kommando"
+
+#: src/sudo.c:293
+#, fuzzy, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "feil under klargjøring av inn-/utdatatillegget «%s»"
+
+#: src/sudo.c:319
+#, fuzzy, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "uforventet sudo-modus 0x%x"
+
+#: src/sudo.c:462
+#, fuzzy
+msgid "unable to get group vector"
+msgstr "klarte ikkje henta gruppevektor"
+
+#: src/sudo.c:523
+#, fuzzy, c-format
+msgid "unknown uid %u: who are you?"
+msgstr "UID %u er ukjend. Kven er du?"
+
+#: src/sudo.c:574
+msgid "unable to determine tty"
+msgstr ""
+
+#: src/sudo.c:864
+#, fuzzy, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "«%s» må eigast av uid %d, og setuid-biten må veljast"
+
+#: src/sudo.c:867
+#, fuzzy, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "effektiv uid er ikkje %d. Er «%s» på eit filsystem der «nosuid» er valt, eller på eit NFS-filsystem utan rot-rettar?"
+
+#: src/sudo.c:873
+#, fuzzy, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "effektiv uid er ikkje %d. Er sudo installert med «setuid root»?"
+
+#: src/sudo.c:954
+#, fuzzy
+msgid "unable to set supplementary group IDs"
+msgstr "klarte ikkje velja ekstra grruppe-id-er"
+
+#: src/sudo.c:961
+#, fuzzy, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "klarte ikkje velja «runa si gjev %u» som effektiv gjev"
+
+#: src/sudo.c:967
+#, fuzzy, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "klarte ikkje velja «runa si gjev %u» som gjev"
+
+#: src/sudo.c:1038
+#, fuzzy, c-format
+msgid "unknown login class %s"
+msgstr "innloggingsklassen «%s» er ukjend"
+
+#: src/sudo.c:1051
+#, fuzzy
+msgid "unable to set user context"
+msgstr "klarte ikkje velja brukarkontekst"
+
+#: src/sudo.c:1067
+#, fuzzy
+msgid "unable to set process priority"
+msgstr "klarte ikkje velja prosessprioritet"
+
+#: src/sudo.c:1075
+#, fuzzy, c-format
+msgid "unable to change root to %s"
+msgstr "klarte ikkje endra rot til «%s»"
+
+#: src/sudo.c:1088 src/sudo.c:1094 src/sudo.c:1101
+#, fuzzy, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "klarte ikkje endra til runa sine uid (%u, %u)"
+
+#: src/sudo.c:1119
+#, fuzzy, c-format
+msgid "unable to change directory to %s"
+msgstr "klarte ikkje endra mappe til «%s»"
+
+#: src/sudo.c:1177
+#, fuzzy, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "uforventet årsak for avslutning av underprosess: %d"
+
+#: src/sudo.c:1323
+#, fuzzy, c-format
+msgid "policy plugin %s is missing the `check_policy' method"
+msgstr "regeltillegget «%s» manglar «check_policy»-metoden"
+
+#: src/sudo.c:1341
+#, fuzzy, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "regeltillegget «%s» støttar ikkje listeløyve"
+
+#: src/sudo.c:1358
+#, fuzzy, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "regeltillegget «%s» støttar ikkje valet «-v»"
+
+#: src/sudo.c:1373
+#, fuzzy, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "regeltillegget «%s» støttar ikkje vala «-k» og «-K»"
+
+#: src/sudo_edit.c:181 src/sudo_edit.c:270
+#, fuzzy
+msgid "unable to restore current working directory"
+msgstr "klarte ikkje retta opp igjen gjeldande arbeidsmappe"
+
+#: src/sudo_edit.c:576 src/sudo_edit.c:687
+#, fuzzy, c-format
+msgid "%s: not a regular file"
+msgstr "«%s» er ikkje ei vanleg fil"
+
+#: src/sudo_edit.c:583
+#, fuzzy, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: redigering av symbolske lenkjer vert ikkje tillate"
+
+#: src/sudo_edit.c:586
+#, fuzzy, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: redigering av filer i ei mappe med skrivetilgang vert ikkje tillate"
+
+#: src/sudo_edit.c:619 src/sudo_edit.c:726
+#, fuzzy, c-format
+msgid "%s: short write"
+msgstr "«%s» har kort skriving"
+
+#: src/sudo_edit.c:688
+#, fuzzy, c-format
+msgid "%s left unmodified"
+msgstr "«%s» vart uendra"
+
+#: src/sudo_edit.c:701 src/sudo_edit.c:887
+#, fuzzy, c-format
+msgid "%s unchanged"
+msgstr "«%s» er uendra"
+
+#: src/sudo_edit.c:715 src/sudo_edit.c:737
+#, fuzzy, c-format
+msgid "unable to write to %s"
+msgstr "klarte ikkje skriva til «%s»"
+
+#: src/sudo_edit.c:716 src/sudo_edit.c:735 src/sudo_edit.c:738
+#: src/sudo_edit.c:912 src/sudo_edit.c:916
+#, fuzzy, c-format
+msgid "contents of edit session left in %s"
+msgstr "innhald frå redigeringsøkt ligg igjen i «%s»"
+
+#: src/sudo_edit.c:734
+#, fuzzy
+msgid "unable to read temporary file"
+msgstr "klarte ikkje lesa mellombels fil"
+
+#: src/sudo_edit.c:817
+#, fuzzy
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: intern feil: for høgt mengd stiar"
+
+#: src/sudo_edit.c:819
+#, fuzzy
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: klarte ikkje laga mellombelse filer"
+
+#: src/sudo_edit.c:821 src/sudo_edit.c:919
+#, fuzzy, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: ukjend feil (%d)"
+
+#: src/sudo_edit.c:911
+#, fuzzy
+msgid "unable to copy temporary files back to their original location"
+msgstr "klarte ikkje kopiera mellombelse filer tilbake til opphavleg plassering"
+
+#: src/sudo_edit.c:915
+#, fuzzy
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "klarte ikkje kopiera enkelte mellombelse filer tilbake til opphavleg plassering"
+
+#: src/sudo_edit.c:959
+#, fuzzy, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "klarte ikkje endra uid til root (%u)"
+
+#: src/sudo_edit.c:976
+#, fuzzy
+msgid "plugin error: missing file list for sudoedit"
+msgstr "feil med tillegg: sudoedit manglar filliste"
+
+#: src/sudo_edit.c:1017 src/sudo_edit.c:1030
+#, fuzzy
+msgid "unable to read the clock"
+msgstr "klarte ikkje lesa klokka"
+
+#: src/tgetpass.c:107
+#, fuzzy
+msgid "no tty present and no askpass program specified"
+msgstr "ingen tty er tilgjengeleg, og inkje program for passord-etterspurnad er vald"
+
+#: src/tgetpass.c:116
+#, fuzzy
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "inkje program for passord-etterspurnad er vald. Prøv å velja «SUDO_ASKPASS»"
+
+#: src/tgetpass.c:270
+#, fuzzy, c-format
+msgid "unable to set gid to %u"
+msgstr "klarte ikkje velja %u som gjev"
+
+#: src/tgetpass.c:274
+#, fuzzy, c-format
+msgid "unable to set uid to %u"
+msgstr "klarte ikkje velja %u som uid"
+
+#: src/tgetpass.c:279
+#, fuzzy, c-format
+msgid "unable to run %s"
+msgstr "klarte ikkje køyra «%s»"
+
+#: src/utmp.c:268
+#, fuzzy
+msgid "unable to save stdin"
+msgstr "klarte ikkje lagra standard innkanal"
+
+#: src/utmp.c:270
+#, fuzzy
+msgid "unable to dup2 stdin"
+msgstr "klarte ikkje utføra «dup2 stdin»"
+
+#: src/utmp.c:273
+#, fuzzy
+msgid "unable to restore stdin"
+msgstr "klarte ikkje retta opp igjen standard innkanal"
diff --git a/po/pl.mo b/po/pl.mo
new file mode 100644
index 0000000..f336f38
--- /dev/null
+++ b/po/pl.mo
Binary files differ
diff --git a/po/pl.po b/po/pl.po
new file mode 100644
index 0000000..f4d3cc3
--- /dev/null
+++ b/po/pl.po
@@ -0,0 +1,1200 @@
+# Polish translation for sudo.
+# This file is put in the public domain.
+# Jakub Bogusz <qboosh@pld-linux.org>, 2011-2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.14b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-06-07 13:27-0600\n"
+"PO-Revision-Date: 2023-06-13 16:45+0200\n"
+"Last-Translator: Jakub Bogusz <qboosh@pld-linux.org>\n"
+"Language-Team: Polish <translation-team-pl@lists.sourceforge.net>\n"
+"Language: pl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "nie udało się otworzyć userdb"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "nie udało się przełączyć na rejestr \"%s\" dla %s"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "nie udało się odtworzyć rejestru"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:78 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:171 src/exec_monitor.c:418
+#: src/exec_monitor.c:424 src/exec_monitor.c:432 src/exec_monitor.c:440
+#: src/exec_monitor.c:447 src/exec_monitor.c:454 src/exec_monitor.c:461
+#: src/exec_monitor.c:468 src/exec_monitor.c:475 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:744 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1096
+#: src/exec_ptrace.c:1271 src/exec_ptrace.c:1624 src/exec_ptrace.c:1651
+#: src/exec_ptrace.c:1841 src/exec_pty.c:581 src/exec_pty.c:765
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:193 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:240
+#: src/sesh.c:246 src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:644
+#: src/sudo.c:709 src/sudo.c:719 src/sudo.c:746 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:787 src/sudo.c:805 src/sudo.c:846 src/sudo.c:855 src/sudo.c:865
+#: src/sudo.c:898 src/sudo.c:1127 src/sudo.c:1148 src/sudo.c:1441
+#: src/sudo.c:1610 src/sudo.c:1837 src/sudo.c:2171 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:430 src/sudo_edit.c:439
+#: src/sudo_edit.c:540 src/sudo_edit.c:547 src/sudo_edit.c:692
+#: src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:79 src/exec_intercept.c:111 src/exec_intercept.c:350
+#: src/exec_intercept.c:525 src/exec_intercept.c:589 src/exec_intercept.c:713
+#: src/exec_intercept.c:837 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:418 src/exec_monitor.c:424
+#: src/exec_monitor.c:432 src/exec_monitor.c:440 src/exec_monitor.c:447
+#: src/exec_monitor.c:454 src/exec_monitor.c:461 src/exec_monitor.c:468
+#: src/exec_monitor.c:475 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1651 src/exec_ptrace.c:1842 src/exec_pty.c:581
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:228 src/sudo.c:644 src/sudo.c:898 src/sudo.c:1127
+#: src/sudo.c:1148 src/sudo.c:1441 src/sudo.c:1610 src/sudo.c:1837
+#: src/sudo.c:2171 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:430
+#: src/sudo_edit.c:439 src/sudo_edit.c:540 src/sudo_edit.c:547
+#: src/sudo_edit.c:692 src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "nie udało się przydzielić pamięci"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "nie udało się wykonać stat na %.*s"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s istnieje, ale nie jest katalogiem (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:664
+#: lib/util/sudo_conf.c:683 lib/util/sudo_conf.c:710 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:495 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "nie udało się otworzyć %s"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "nie udało się utworzyć katalogu %.*s"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "nie udało się otworzyć %.*s"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "wyrażenie regularne zbyt długie"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Nieznany sygnał"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "błędna wartość"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "wartość zbyt duża"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "wartość zbyt mała"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "błędna wartość Path \"%s\" w %s, w linii %u"
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "błędna wartość opcji %s \"%s\" w %s, w linii %u"
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "nieobsługiwane źródło grup \"%s\" w %s, w linii %u"
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "błędna maksymalna liczba grup \"%s\" w %s, w linii %u"
+
+#: lib/util/sudo_conf.c:686
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s nie jest zwykłym plikiem"
+
+#: lib/util/sudo_conf.c:689 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "właścicielem %s jest uid %u, powinien być %u"
+
+#: lib/util/sudo_conf.c:693
+#, c-format
+msgid "%s is world writable"
+msgstr "%s jest zapisywalny dla świata"
+
+#: lib/util/sudo_conf.c:696
+#, c-format
+msgid "%s is group writable"
+msgstr "%s jest zapisywalny dla grupy"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "nie udało się określić ograniczeń AppArmor"
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "nie udało się zmienić profilu AppArmor na %s"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: uciąć %s to zera bajtów? (y/n) [n] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "bez nadpisywania %s"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "nie można czytać z %s"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "nie można pisać do %s"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "nie udało się wykonać stat na %s"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: nie jest zwykłym plikiem"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: błędny tryb pliku: 0%o"
+
+#: src/edit_open.c:333
+msgid "unable to restore current working directory"
+msgstr "nie udało się odtworzyć bieżącego kartalogu roboczego"
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "nie udało się ustawić uprawnień"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "nie udało się ustawić ograniczonych uprawnień"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "nieznana klasa logowania %s"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "nie udało się ustawić kontekstu użytkownika"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "nie udało się ustawić priorytetu procesu"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "nie udało się zmienić katalogu głównego na %s"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "nie udało się zmienić uid-ów, aby działać jako (%u, %u)"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "nie udało się zmienić katalogu na %s"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "zaczynając od %s"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:552 src/exec_monitor.c:554
+#: src/exec_pty.c:1122 src/exec_pty.c:1124 src/signal.c:144 src/signal.c:151
+#: src/signal.c:165 src/suspend_parent.c:143
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "nie udało się ustawić procedury obsługi dla sygnału %d"
+
+#: src/exec.c:424
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "tryb przechwytywania nie jest obsługiwany z RBAC SELinux na tym systemie"
+
+#: src/exec.c:429
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "nie można logować podpoleceń z RBAC SELinux na tym systemie"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "nie udało się usunąć PRIV_PROC_EXEC z PRIV_LIMIT"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:163 src/exec_iolog.c:173
+#: src/exec_iolog.c:218 src/exec_iolog.c:225 src/exec_iolog.c:252
+#: src/exec_monitor.c:426 src/exec_monitor.c:434 src/exec_monitor.c:442
+#: src/exec_monitor.c:449 src/exec_monitor.c:456 src/exec_monitor.c:463
+#: src/exec_monitor.c:470 src/exec_monitor.c:477 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:457 src/exec_pty.c:432
+#: src/exec_pty.c:537 src/exec_pty.c:587 src/exec_pty.c:965 src/exec_pty.c:974
+#: src/exec_pty.c:981 src/exec_pty.c:988 src/exec_pty.c:995
+#: src/exec_pty.c:1002 src/exec_pty.c:1009 src/exec_pty.c:1016
+#: src/exec_pty.c:1023 src/exec_pty.c:1030 src/exec_pty.c:1037
+#: src/exec_pty.c:1044
+msgid "unable to add event to queue"
+msgstr "nie udało się dodać zdarzenia do kolejki"
+
+#: src/exec_intercept.c:323 src/sudo.c:1033
+msgid "command not set by the security policy"
+msgstr "polecenie nie ustawione przez politykę bezpieczeństwa"
+
+#: src/exec_intercept.c:401 src/exec_intercept.c:441 src/sudo.c:1253
+#: src/sudo.c:1298 src/sudo.c:1342
+msgid "command rejected by policy"
+msgstr "polecenie odrzucone przez politykę"
+
+#: src/exec_intercept.c:512 src/sudo.c:1940
+msgid "approval plugin error"
+msgstr "błąd wtyczki zgody"
+
+#: src/exec_intercept.c:537 src/sudo.c:1258 src/sudo.c:1303 src/sudo.c:1347
+#: src/sudo.c:1421
+msgid "policy plugin error"
+msgstr "błąd wtyczki polityki"
+
+#: src/exec_intercept.c:566
+msgid "invalid PolicyCheckRequest"
+msgstr "błędne żądanie PolicyCheckRequest"
+
+#: src/exec_intercept.c:709
+#, c-format
+msgid "client request too large: %zu"
+msgstr "żądanie klienta zbyt duże: %zu"
+
+#: src/exec_intercept.c:751
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "nie udało się rozpakować %s, rozmiar %zu"
+
+#: src/exec_intercept.c:799
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "nieoczekiwana wartość type_case %d w %s od %s"
+
+#: src/exec_intercept.c:825
+#, c-format
+msgid "server message too large: %zu"
+msgstr "komunikat serwera zbyt duży: %zu"
+
+#: src/exec_iolog.c:321 src/exec_iolog.c:361 src/exec_iolog.c:401
+#: src/exec_iolog.c:452 src/exec_iolog.c:503
+msgid "I/O plugin error"
+msgstr "błąd wtyczki we/wy"
+
+#: src/exec_iolog.c:325 src/exec_iolog.c:365 src/exec_iolog.c:405
+#: src/exec_iolog.c:456 src/exec_iolog.c:507
+msgid "command rejected by I/O plugin"
+msgstr "polecenie odrzucone przez wtyczkę we/wy"
+
+#: src/exec_iolog.c:555
+msgid "error logging suspend"
+msgstr "błąd logowania odroczenia"
+
+#: src/exec_iolog.c:590
+msgid "error changing window size"
+msgstr "błąd zmiany rozmiaru okna"
+
+#: src/exec_monitor.c:328
+msgid "error reading from socketpair"
+msgstr "błąd odczytu z pary gniazd"
+
+#: src/exec_monitor.c:340
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "nieoczekiwany typ odpowiedzi z kanału zwrotnego: %d"
+
+#: src/exec_monitor.c:566
+msgid "unable to set controlling tty"
+msgstr "nie udało się ustawić sterującego tty"
+
+#: src/exec_monitor.c:574 src/exec_nopty.c:504 src/exec_nopty.c:514
+#: src/exec_nopty.c:524 src/exec_nopty.c:560 src/exec_pty.c:1195
+#: src/exec_pty.c:1222 src/exec_pty.c:1242 src/exec_pty.c:1262
+#: src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr "nie udało się utworzyć potoku"
+
+#: src/exec_monitor.c:584
+msgid "unable to receive message from parent"
+msgstr "nie udało się odebrać komunikatu od rodzica"
+
+#: src/exec_monitor.c:600 src/exec_nopty.c:603 src/exec_pty.c:1303
+#: src/sudo_edit.c:361 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr "nie udało się wykonać fork"
+
+#: src/exec_monitor.c:604 src/exec_monitor.c:700 src/exec_nopty.c:708
+msgid "unable to restore tty label"
+msgstr "nie udało się przywrócić etykiety tty"
+
+#: src/exec_monitor.c:615 src/sesh.c:217 src/sudo.c:1204
+#, c-format
+msgid "unable to execute %s"
+msgstr "nie udało się wykonać %s"
+
+#: src/exec_nopty.c:554 src/exec_pty.c:1131
+msgid "policy plugin failed session initialization"
+msgstr "nie udało się zainicjować sesji przez wtyczkę polityki"
+
+#: src/exec_nopty.c:569 src/exec_pty.c:1100 src/exec_pty.c:1109
+msgid "unable to create sockets"
+msgstr "nie udało się utworzyć gniazd"
+
+#: src/exec_nopty.c:696 src/exec_pty.c:1406
+msgid "error in event loop"
+msgstr "błąd w pętli zdarzeń"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:852 src/sudo.c:488
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "błąd wewnętrzny, przepełnienie %s"
+
+#: src/exec_ptrace.c:1080 src/exec_ptrace.c:1105 src/exec_ptrace.c:1925
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "nie udało się ustawić rejestrów dla procesu %d"
+
+#: src/exec_ptrace.c:1100 src/exec_ptrace.c:1275 src/exec_ptrace.c:1628
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "proces %d nieoczekiwanie zakończył się"
+
+#: src/exec_ptrace.c:1209
+msgid "unable to set seccomp filter"
+msgstr "nie udało się ustawić filtra seccomp"
+
+#: src/exec_ptrace.c:1406
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "argument interpretera - oczekiwano \"%s\", napotkano \"%s\""
+
+#: src/exec_ptrace.c:1505
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "niezgodność ścieżki, oczekiwano \"%s\", napotkano \"%s\""
+
+#: src/exec_ptrace.c:1514 src/exec_ptrace.c:1521 src/exec_ptrace.c:1545
+#: src/exec_ptrace.c:1553 src/exec_ptrace.c:1559 src/exec_ptrace.c:1565
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "niezgodność %s[%d], oczekiwano \"%s\", napotkano \"%s\""
+
+#: src/exec_ptrace.c:1632
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "proces %d nieoczekiwany status 0x%x"
+
+#: src/exec_ptrace.c:1723
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "nie udało się pobrać komunikatu zdarzenia dla procesu %d"
+
+#: src/exec_ptrace.c:1730
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "nie udało się pobrać rejestrów dla procesu %d"
+
+#: src/exec_pty.c:84
+msgid "unable to allocate pty"
+msgstr "nie udało się przydzielić pty"
+
+#: src/exec_pty.c:131 src/exec_pty.c:284 src/tgetpass.c:251
+msgid "unable to restore terminal settings"
+msgstr "nie udało się przywrócić ustawień terminala"
+
+#: src/exec_pty.c:243
+msgid "unable to set handler for SIGCONT"
+msgstr "nie udało się ustawić procedury obsługi dla SIGCONT"
+
+#: src/exec_pty.c:293
+#, c-format
+msgid "unable to set handler for SIG%s"
+msgstr "nie udało się ustawić procedury obsługi dla SIG%s"
+
+#: src/exec_pty.c:317
+#, c-format
+msgid "unable to restore handler for SIG%s"
+msgstr "nie udało się przywrócić procedury obsługi dla SIG%s"
+
+#: src/exec_pty.c:345
+msgid "unable to restore handler for SIGCONT"
+msgstr "nie udało się przywrócić procedury obsługi dla SIGCONT"
+
+#: src/exec_pty.c:1353
+msgid "unable to send message to monitor process"
+msgstr "nie udało się wysłać komunikatu do procesu monitorującego"
+
+#: src/load_plugins.c:75 src/load_plugins.c:222 src/load_plugins.c:232
+#: src/load_plugins.c:242 src/load_plugins.c:289
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "błąd w %s, w linii %d podczas wczytywania wtyczki \"%s\""
+
+#: src/load_plugins.c:186 src/load_plugins.c:257
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "zignotowano powtórzoną wtyczkę \"%s\" w %s, w linii %d"
+
+#: src/load_plugins.c:224
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "nie udało się załadować %s: %s"
+
+#: src/load_plugins.c:234
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "nie udało się odnaleźć symbolu \"%s\" w %s"
+
+#: src/load_plugins.c:244
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "niezgodna główna wersja polityki %d (zamiast oczekiwanej %d) napotkana w %s"
+
+#: src/load_plugins.c:262
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "zignorowano wtyczkę polityki \"%s\" w %s, w linii %d"
+
+#: src/load_plugins.c:265
+msgid "only a single policy plugin may be specified"
+msgstr "może być podana tylko jedna wtyczka polityki"
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "nieznany typ wtyczki %d napotkany w %s"
+
+#: src/load_plugins.c:474
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "wtyczka polityki %s nie zawiera metody check_policy"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "błędna nazwa zmiennej środowiskowej: %s"
+
+#: src/parse_args.c:319
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "argument opcji -C musi być większy lub równy 3"
+
+#: src/parse_args.c:556
+msgid "you may not specify both the -i and -s options"
+msgstr "nie można podać jednocześnie opcji -i oraz -s"
+
+#: src/parse_args.c:561
+msgid "you may not specify both the -i and -E options"
+msgstr "nie można podać jednocześnie opcji -i oraz -E"
+
+#: src/parse_args.c:571
+msgid "the -E option is not valid in edit mode"
+msgstr "opcja -E nie jest poprawna w trybie edycji"
+
+#: src/parse_args.c:574
+msgid "you may not specify environment variables in edit mode"
+msgstr "w trybie edycji nie można przekazywać zmiennych środowiskowych"
+
+#: src/parse_args.c:584
+msgid "the -U option may only be used with the -l option"
+msgstr "opcji -U można używać tylko wraz z opcją -l"
+
+#: src/parse_args.c:588
+msgid "the -A and -S options may not be used together"
+msgstr "opcji -A oraz -S nie można używać jednocześnie"
+
+#: src/parse_args.c:686
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit nie jest obsługiwane na tej platformie"
+
+#: src/parse_args.c:744
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Można podać tylko jedną z opcji -e, -h, -i, -K, -l, -s, -v lub -V"
+
+#: src/parse_args.c:757
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "Można podać tylko jedną z opcji -K, -k lub -N"
+
+#: src/parse_args.c:778
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - modyfikowanie plików jako inny użytkownik\n"
+"\n"
+
+#: src/parse_args.c:780
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - wykonywanie poleceń jako inny użytkownik\n"
+"\n"
+
+#: src/parse_args.c:785
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Opcje:\n"
+
+#: src/parse_args.c:787
+msgid "use a helper program for password prompting"
+msgstr "użycie programu pomocniczego do pytań o hasło"
+
+#: src/parse_args.c:790
+msgid "use specified BSD authentication type"
+msgstr "użycie podanego rodzaju uwierzytelnienia BSD"
+
+#: src/parse_args.c:794
+msgid "run command in the background"
+msgstr "uruchomienie polecenia w tle"
+
+#: src/parse_args.c:797
+msgid "ring bell when prompting"
+msgstr "dzwonek przy zapytaniu"
+
+#: src/parse_args.c:799
+msgid "close all file descriptors >= num"
+msgstr "zamknięcie wszystkich deskryptorów >= fd"
+
+#: src/parse_args.c:802
+msgid "run command with the specified BSD login class"
+msgstr "uruchomienie polecenia z podaną klasą logowania BSD"
+
+#: src/parse_args.c:805
+msgid "change the working directory before running command"
+msgstr "zmiana katalogu roboczego przed uruchomieniem polecenia"
+
+#: src/parse_args.c:808
+msgid "preserve user environment when running command"
+msgstr "zachowanie środowiska użytkownika przy uruchamianiu polecenia"
+
+#: src/parse_args.c:810
+msgid "preserve specific environment variables"
+msgstr "zachowanie określonych zmiennych środowiskowych"
+
+#: src/parse_args.c:812
+msgid "edit files instead of running a command"
+msgstr "modyfikowanie plików zamiast uruchomienia polecenia"
+
+#: src/parse_args.c:815
+msgid "run command as the specified group name or ID"
+msgstr "wywołanie polecenia jako określona grupa lub ID"
+
+#: src/parse_args.c:818
+msgid "set HOME variable to target user's home dir"
+msgstr "ustawienie zmiennej HOME na katalog domowy użytkownika docelowego"
+
+#: src/parse_args.c:821
+msgid "display help message and exit"
+msgstr "wyświetlenie opisu i zakończenie"
+
+#: src/parse_args.c:823
+msgid "run command on host (if supported by plugin)"
+msgstr "uruchomienie polecenia na hoście (jeśli obsługiwane przez wtyczkę)"
+
+#: src/parse_args.c:826
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "uruchomienie powłoki logowania jako użytkownik docelowy; można także podać polecenie"
+
+#: src/parse_args.c:828
+msgid "remove timestamp file completely"
+msgstr "całkowite usunięcie pliku znacznika czasu"
+
+#: src/parse_args.c:831
+msgid "invalidate timestamp file"
+msgstr "unieważnienie pliku znacznika czasu"
+
+#: src/parse_args.c:834
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "wypisanie uprawnień użytkownika lub sprawdzenie określonego polecenia; dwukrotne użycie to dłuższy format"
+
+#: src/parse_args.c:837
+msgid "non-interactive mode, no prompts are used"
+msgstr "tryb nieinteraktywny, bez pytań"
+
+#: src/parse_args.c:840
+msgid "preserve group vector instead of setting to target's"
+msgstr "zachowanie wektora grup zamiast ustawiania docelowych"
+
+#: src/parse_args.c:843
+msgid "use the specified password prompt"
+msgstr "użycie podanego pytania o hasło"
+
+#: src/parse_args.c:845
+msgid "change the root directory before running command"
+msgstr "zmiana katalogu głównego przed uruchomieniem polecenia"
+
+#: src/parse_args.c:848
+msgid "create SELinux security context with specified role"
+msgstr "utworzenie kontekstu bezpieczeństwa SELinuksa z podaną rolą"
+
+#: src/parse_args.c:851
+msgid "read password from standard input"
+msgstr "odczyt hasła ze standardowego wejścia"
+
+#: src/parse_args.c:854
+msgid "run shell as the target user; a command may also be specified"
+msgstr "uruchomienie powłoki jako użytkownik docelowy; można także podać polecenie"
+
+#: src/parse_args.c:858
+msgid "create SELinux security context with specified type"
+msgstr "utworzenie kontekstu bezpieczeństwa SELinuksa z podanym typem"
+
+#: src/parse_args.c:861
+msgid "terminate command after the specified time limit"
+msgstr "zakończenie polecenia po zadanym limicie czasu"
+
+#: src/parse_args.c:864
+msgid "in list mode, display privileges for user"
+msgstr "w trybie listy - wyświetlenie uprawnień użytkownika"
+
+#: src/parse_args.c:867
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "uruchomienie polecenia (lub modyfikowanie pliku) jako podany użytkownik lub ID"
+
+#: src/parse_args.c:869
+msgid "display version information and exit"
+msgstr "wyświetlenie informacji o wersji i zakończenie"
+
+#: src/parse_args.c:872
+msgid "update user's timestamp without running a command"
+msgstr "uaktualnienie znacznika czasu użytkownika bez uruchamiania polecenia"
+
+#: src/parse_args.c:875
+msgid "stop processing command line arguments"
+msgstr "zakończenie przetwarzania argumentów linii poleceń"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "nie udało się otworzyć systemu audytu"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "nie udało się wysłać komunikatu audytowego"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "nie udało się wykonać fgetfilecon %s"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "zmienionych etykiet: %s"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "nie udało się przywrócić kontekstu %s"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "nie udało się otworzyć %s, bez zmiany etykiety tty"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s nie jest urządzeniem znakowym, bez ponownego etykietowania tty"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "nie udało się uzyskać bieżącego kontekstu tty, bez zmiany etykiety tty"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "nieznana klasa bezpieczeństwa \"chr_file\", bez ponownego etykietowania tty"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "nie udało się uzyskać nowego kontekstu tty, bez zmiany etykiety tty"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "nie udało się ustawić nowego kontekstu tty"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "należy podać rolę dla typu %s"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "nie udało się uzyskać domyślnego typu dla roli %s"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "nie udało się uzyskać nowego kontekstu"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "nie udało się ustawić nowej roli %s"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "nie udało się ustawić nowego typu %s"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s nie jest poprawnym kontekstem"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "nie udało się uzyskać starego kontekstu"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "nie udało się określić trybu wymuszenia."
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "nie udało się ustawić kontekstu wykonywania na %s"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "nie udało się ustawić kontekstu tworzenia klucza na %s"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "Można podać tylko jedną z opcji -c lub -i"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "błędny numer deskryptora pliku: %s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "Opcja -%c nie może być użyta w trybie edycji."
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "Opcji -%c można używać tylko w trybie edycji."
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: edycja dowiązań symbolicznych nie jest dozwolona"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: edycja plików w katalogu zapisywalnym nie jest dozwolona"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "zawartość sesji edycji pozostawiono w %s"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "nie udało się uzyskać listy grup"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "nie udało się zapisać procedury obsługi dla sygnału %d"
+
+#: src/signal.c:101 src/suspend_parent.c:149
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "nie udało się przywrócić procedury obsługi dla sygnału %d"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "osiągnięto limit kontroli zasobów"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "użytkownik \"%s\" nie jest członkiem projektu \"%s\""
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "zadanie uruchamiające jest ostatnim"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "nie udało się dołączyć do projektu \"%s\""
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "nie istnieje pula zasobów akceptująca domyślne przypisania dla projektu \"%s\""
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "podana pula zasobów nie istnieje w projekcie \"%s\""
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "nie można przypisać do domyślnej puli zasobów w projekcie \"%s\""
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "setproject dla projektu \"%s\" nie powiodło się"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "uwaga: przypisanie kontroli zasobów dla projektu \"%s\" nie powiodło się"
+
+#: src/sudo.c:214
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo wersja %s\n"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Opcje konfiguracji: %s\n"
+
+#: src/sudo.c:224
+msgid "fatal error, unable to load plugins"
+msgstr "błąd krytyczny, nie udało się załadować wtyczek"
+
+#: src/sudo.c:270
+msgid "plugin did not return a command to execute"
+msgstr "wtyczka nie zwróciła polecenia do wykonania"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "nieoczekiwany tryb sudo 0x%x"
+
+#: src/sudo.c:559
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "nie istniejesz w bazie danych %s"
+
+#: src/sudo.c:616
+msgid "unable to determine tty"
+msgstr "nie udało się określić tty"
+
+#: src/sudo.c:932
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "Ustawiona jest flaga \"bez nowych uprawnień\", która nie pozwala na uruchamianie sudo jako root."
+
+#: src/sudo.c:934
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "Jeśli sudo jest uruchomione w kontenerze, może być potrzebne dostosowanie konfiguracji kontenera w celu wyłączenia flagi."
+
+#: src/sudo.c:968
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s musi mieć uid %d jako właściciela oraz ustawiony bit setuid"
+
+#: src/sudo.c:971
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "efektywny uid nie wynosi %d, czy %s jest na systemie plików z opcją 'nosuid' albo systemie plików NFS bez uprawnień roota?"
+
+#: src/sudo.c:977
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "efektywny uid nie wynosi %d, czy sudo jest zainstalowane z setuid root?"
+
+#: src/sudo.c:993 src/tgetpass.c:332
+msgid "unable to set supplementary group IDs"
+msgstr "nie udało się ustawić ID dodatkowych grup"
+
+#: src/sudo.c:1000
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "nie udało się ustawić efektywnego gid-a w celu działania jako gid %u"
+
+#: src/sudo.c:1006
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "nie udało się ustawić gid-a w celu działania jako gid %u"
+
+#: src/sudo.c:1037
+msgid "argv not set by the security policy"
+msgstr "argv nie ustawione przez politykę bezpieczeństwa"
+
+#: src/sudo.c:1041
+msgid "envp not set by the security policy"
+msgstr "envp nie ustawione przez politykę bezpieczeństwa"
+
+#: src/sudo.c:1063
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "nieoczekiwane zakończenie procesu potomnego: %d"
+
+#: src/sudo.c:1176
+msgid "unable to initialize policy plugin"
+msgstr "nie udało się zainicjować wtyczki polityki"
+
+#: src/sudo.c:1238
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "wtyczka polityki %s nie zawiera metody \"check_policy\""
+
+#: src/sudo.c:1284
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "wtyczka polityki %s nie obsługuje wypisywania uprawnień"
+
+#: src/sudo.c:1328
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "wtyczka polityki %s nie obsługuje opcji -v"
+
+#: src/sudo.c:1366
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "wtyczka polityki %s nie obsługuje opcji -k/-K"
+
+#: src/sudo.c:1495
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "błąd inicjalizacji wtyczki we/wy %s"
+
+#: src/sudo.c:1498
+msgid "error initializing I/O plugin"
+msgstr "błąd inicjowania wtyczki we/wy"
+
+#: src/sudo.c:1647
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "błąd inicjowania wtyczki audytu %s"
+
+#: src/sudo.c:1726
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: nie udało się zalogować zdarzenia błędu%s%s"
+
+#: src/sudo.c:1762
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: nie udało się zalogować zdarzenia akceptacji%s%s"
+
+#: src/sudo.c:1767 src/sudo.c:1805
+msgid "audit plugin error"
+msgstr "błąd wtyczki audytu"
+
+#: src/sudo.c:1800
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: nie udało się zalogować zdarzenia odrzucenia%s%s"
+
+#: src/sudo.c:1860
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "błąd inicjowania wtyczki zgody %s"
+
+#: src/sudo.c:1930
+msgid "command rejected by approver"
+msgstr "polecenie odrzucone przez wtyczkę zgody"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "nie znaleziono katalogu tymczasowego z prawem zapisu"
+
+#: src/sudo_edit.c:292
+#, c-format
+msgid "%s left unmodified"
+msgstr "pozostawiono bez zmian: %s"
+
+#: src/sudo_edit.c:305 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "nie zmieniono: %s"
+
+#: src/sudo_edit.c:482
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: błąd wewnętrzny: nieparzysta liczba ścieżek"
+
+#: src/sudo_edit.c:484
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: nie udało się utworzyć plików tymczasowych"
+
+#: src/sudo_edit.c:486 src/sudo_edit.c:606
+msgid "sesh: killed by a signal"
+msgstr "sesh: zabito sygnałem"
+
+#: src/sudo_edit.c:488 src/sudo_edit.c:609
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: nieznany błąd %d"
+
+#: src/sudo_edit.c:599
+msgid "unable to copy temporary files back to their original location"
+msgstr "nie udało się skopiować plików tymczasowych z powrotem w ich oryginalne miejsce"
+
+#: src/sudo_edit.c:603
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "nie udało się skopiować części plików tymczasowych z powrotem w ich oryginalne miejsce"
+
+#: src/sudo_edit.c:650
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "nie udało się zmienić uid-a na roota (%u)"
+
+#: src/sudo_edit.c:664
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "błąd wtyczki: błędna lista plików dla sudoedit"
+
+#: src/sudo_edit.c:685
+msgid "plugin error: missing file list for sudoedit"
+msgstr "błąd wtyczki: brak listy plików dla sudoedit"
+
+#: src/sudo_edit.c:728 src/sudo_edit.c:743
+msgid "unable to read the clock"
+msgstr "nie udało się odczytać zegara"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "port przechwytywania nie ustawiony"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "przekroczony limit czasu przy czytaniu hasła"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "nie podano hasła"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "nie udało się odczytać hasła"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "do odczytu hasła wymagany jest terminal; należy użyć opcji -S, aby czytać ze standardowego wejścia, lub skonfigurować program pytający o hasło"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "nie podano programu pytającego o hasło, proszę spróbować ustawić SUDO_ASKPASS"
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "nie udało się ustawić gid-a na %u"
+
+#: src/tgetpass.c:337
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "nie udało się ustawić uid-a na %u"
+
+#: src/tgetpass.c:342
+#, c-format
+msgid "unable to run %s"
+msgstr "nie udało się uruchomić %s"
+
+#: src/utmp.c:283
+msgid "unable to save stdin"
+msgstr "nie udało się zapisać standardowego wejścia"
+
+#: src/utmp.c:285
+msgid "unable to dup2 stdin"
+msgstr "nie udało się wykonać dup2 na standardowym wejściu"
+
+#: src/utmp.c:288
+msgid "unable to restore stdin"
+msgstr "nie udało się przywrócić standardowego wejścia"
diff --git a/po/pt.mo b/po/pt.mo
new file mode 100644
index 0000000..c85b1e5
--- /dev/null
+++ b/po/pt.mo
Binary files differ
diff --git a/po/pt.po b/po/pt.po
new file mode 100644
index 0000000..a4ff211
--- /dev/null
+++ b/po/pt.po
@@ -0,0 +1,1094 @@
+# Portuguese (Portugal) translations for the sudo package
+# This file is distributed under the same license as the sudo package.
+# Todd C. Miller <Todd.Miller@sudo.ws>, 2011-2016
+# Pedro Albuquerque <pmra@protonmail.com>, 2018, 2019, 2020, 2021.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo-1.9.8b2\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2021-08-16 10:46-0600\n"
+"PO-Revision-Date: 2021-08-22 06:55+0100\n"
+"Last-Translator: Pedro Albuquerque <pmra@protonmail.com>\n"
+"Language-Team: Portuguese <translation-team-pt@lists.sourceforge.net>\n"
+"Language: pt\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 2.3\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "impossível abrir userdb"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "impossível mudar para o registo \"%s\" para %s"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "impossível restaurar o registo"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:54 lib/util/json.c:183 lib/util/sudo_conf.c:211
+#: lib/util/sudo_conf.c:297 lib/util/sudo_conf.c:374 lib/util/sudo_conf.c:658
+#: src/conversation.c:80 src/exec_monitor.c:206 src/exec_monitor.c:456
+#: src/exec_monitor.c:462 src/exec_monitor.c:470 src/exec_monitor.c:478
+#: src/exec_monitor.c:485 src/exec_monitor.c:492 src/exec_monitor.c:499
+#: src/exec_monitor.c:506 src/exec_monitor.c:513 src/exec_monitor.c:520
+#: src/exec_monitor.c:527 src/exec_nopty.c:225 src/exec_nopty.c:235
+#: src/exec_nopty.c:245 src/exec_nopty.c:252 src/exec_nopty.c:259
+#: src/exec_nopty.c:266 src/exec_nopty.c:273 src/exec_nopty.c:280
+#: src/exec_nopty.c:287 src/exec_nopty.c:294 src/exec_nopty.c:301
+#: src/exec_nopty.c:308 src/exec_nopty.c:315 src/exec_nopty.c:323
+#: src/exec_nopty.c:511 src/exec_preload.c:143 src/exec_preload.c:203
+#: src/exec_pty.c:844 src/exec_pty.c:853 src/exec_pty.c:910
+#: src/exec_pty.c:1063 src/exec_pty.c:1237 src/exec_pty.c:1247
+#: src/exec_pty.c:1257 src/exec_pty.c:1264 src/exec_pty.c:1271
+#: src/exec_pty.c:1278 src/exec_pty.c:1285 src/exec_pty.c:1292
+#: src/exec_pty.c:1299 src/exec_pty.c:1306 src/exec_pty.c:1313
+#: src/exec_pty.c:1320 src/exec_pty.c:1328 src/exec_pty.c:1782
+#: src/load_plugins.c:156 src/load_plugins.c:181 src/load_plugins.c:217
+#: src/load_plugins.c:449 src/load_plugins.c:455 src/parse_args.c:190
+#: src/parse_args.c:211 src/parse_args.c:285 src/parse_args.c:630
+#: src/parse_args.c:652 src/parse_args.c:677 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:90 src/selinux.c:360 src/selinux.c:489
+#: src/selinux.c:498 src/sesh.c:113 src/sesh.c:146 src/sesh.c:152
+#: src/sesh.c:159 src/sesh.c:165 src/sesh.c:410 src/sudo.c:636 src/sudo.c:706
+#: src/sudo.c:716 src/sudo.c:741 src/sudo.c:760 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:795 src/sudo.c:837 src/sudo.c:847 src/sudo.c:876 src/sudo.c:1061
+#: src/sudo.c:1082 src/sudo.c:1374 src/sudo.c:1543 src/sudo.c:1770
+#: src/sudo.c:2104 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:429
+#: src/sudo_edit.c:438 src/sudo_edit.c:539 src/sudo_edit.c:546
+#: src/sudo_edit.c:686 src/sudo_edit.c:706 src/sudo_intercept_common.c:160
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:55
+#: lib/util/json.c:184 lib/util/sudo_conf.c:212 lib/util/sudo_conf.c:297
+#: lib/util/sudo_conf.c:374 lib/util/sudo_conf.c:658 src/conversation.c:81
+#: src/exec_intercept.c:154 src/exec_intercept.c:181 src/exec_intercept.c:204
+#: src/exec_intercept.c:225 src/exec_intercept.c:231 src/exec_intercept.c:240
+#: src/exec_intercept.c:246 src/exec_intercept.c:312 src/exec_intercept.c:407
+#: src/exec_intercept.c:627 src/exec_monitor.c:456 src/exec_monitor.c:462
+#: src/exec_monitor.c:470 src/exec_monitor.c:478 src/exec_monitor.c:485
+#: src/exec_monitor.c:492 src/exec_monitor.c:499 src/exec_monitor.c:506
+#: src/exec_monitor.c:513 src/exec_monitor.c:520 src/exec_monitor.c:527
+#: src/exec_nopty.c:225 src/exec_nopty.c:235 src/exec_nopty.c:245
+#: src/exec_nopty.c:252 src/exec_nopty.c:259 src/exec_nopty.c:266
+#: src/exec_nopty.c:273 src/exec_nopty.c:280 src/exec_nopty.c:287
+#: src/exec_nopty.c:294 src/exec_nopty.c:301 src/exec_nopty.c:308
+#: src/exec_nopty.c:315 src/exec_nopty.c:323 src/exec_preload.c:143
+#: src/exec_preload.c:203 src/exec_pty.c:844 src/exec_pty.c:853
+#: src/exec_pty.c:910 src/exec_pty.c:1237 src/exec_pty.c:1247
+#: src/exec_pty.c:1257 src/exec_pty.c:1264 src/exec_pty.c:1271
+#: src/exec_pty.c:1278 src/exec_pty.c:1285 src/exec_pty.c:1292
+#: src/exec_pty.c:1299 src/exec_pty.c:1306 src/exec_pty.c:1313
+#: src/exec_pty.c:1320 src/exec_pty.c:1328 src/exec_pty.c:1782
+#: src/load_plugins.c:156 src/load_plugins.c:181 src/load_plugins.c:217
+#: src/load_plugins.c:449 src/load_plugins.c:455 src/parse_args.c:190
+#: src/parse_args.c:212 src/parse_args.c:285 src/parse_args.c:630
+#: src/parse_args.c:652 src/parse_args.c:677 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:90 src/selinux.c:360 src/selinux.c:489
+#: src/selinux.c:498 src/sesh.c:113 src/sesh.c:411 src/sudo.c:227
+#: src/sudo.c:636 src/sudo.c:876 src/sudo.c:1061 src/sudo.c:1082
+#: src/sudo.c:1374 src/sudo.c:1543 src/sudo.c:1770 src/sudo.c:2104
+#: src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:429
+#: src/sudo_edit.c:438 src/sudo_edit.c:539 src/sudo_edit.c:546
+#: src/sudo_edit.c:686 src/sudo_edit.c:706 src/sudo_intercept_common.c:160
+msgid "unable to allocate memory"
+msgstr "impossível alocar memória"
+
+#: lib/util/mkdir_parents.c:69 lib/util/sudo_conf.c:697 src/selinux.c:234
+#: src/selinux.c:264 src/sudo.c:368 src/sudo_edit.c:494 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "impossível abrir %s"
+
+#: lib/util/mkdir_parents.c:84
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "impossível executar mkdir %s"
+
+#: lib/util/mkdir_parents.c:93 lib/util/sudo_conf.c:674 src/copy_file.c:150
+#, c-format
+msgid "unable to stat %s"
+msgstr "impossível obter informações de %s"
+
+#: lib/util/mkdir_parents.c:98
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s existe, mas não é uma pasta (0%o)"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Sinal desconhecido"
+
+#: lib/util/strtoid.c:87 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:146 src/sesh.c:159
+msgid "invalid value"
+msgstr "valor inválido"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "valor muito grande"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "valor muito pequeno"
+
+#: lib/util/sudo_conf.c:230
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "valor de caminho inválido \"%s\" em %s, linha %u"
+
+#: lib/util/sudo_conf.c:396 lib/util/sudo_conf.c:412 lib/util/sudo_conf.c:465
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "valor inválido %s \"%s\" em %s, linha %u"
+
+#: lib/util/sudo_conf.c:433
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "fonte de grupo não suportada \"%s\" em %s, linna %u"
+
+#: lib/util/sudo_conf.c:449
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "máximo de grupos inválido \"%s\" em %s, linha %u"
+
+#: lib/util/sudo_conf.c:677
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s não é um ficheiro normal"
+
+#: lib/util/sudo_conf.c:680 src/copy_file.c:163
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s é propriedade de uid %u, deveria ser %u"
+
+#: lib/util/sudo_conf.c:684
+#, c-format
+msgid "%s is world writable"
+msgstr "%s é escrito universalmente"
+
+#: lib/util/sudo_conf.c:687
+#, c-format
+msgid "%s is group writable"
+msgstr "%s é escrito pelo grupo"
+
+#: src/copy_file.c:93
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: truncar %s para zero bytes? (y/n) [n] "
+
+#: src/copy_file.c:97
+#, c-format
+msgid "not overwriting %s"
+msgstr "não sobrescrever %s"
+
+#: src/copy_file.c:119
+#, c-format
+msgid "unable to read from %s"
+msgstr "impossível ler de %s"
+
+#: src/copy_file.c:136 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "impossível escrever em %s"
+
+#: src/copy_file.c:154 src/sesh.c:218 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s não é um ficheiro normal"
+
+#: src/copy_file.c:158
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: modo de ficheiro errado: 0%o"
+
+#: src/edit_open.c:265
+msgid "unable to restore current working directory"
+msgstr "impossível restaurar pasta de trabalho actual"
+
+#: src/exec.c:130
+#, c-format
+msgid "unknown login class %s"
+msgstr "classe de sessão %s desconhecida"
+
+#: src/exec.c:142
+msgid "unable to set user context"
+msgstr "impossível definir contexto de utilizador"
+
+#: src/exec.c:158
+msgid "unable to set process priority"
+msgstr "impossível processar prioridade"
+
+#: src/exec.c:172
+#, c-format
+msgid "unable to change root to %s"
+msgstr "impossível alterar root para %s"
+
+#: src/exec.c:185 src/exec.c:191 src/exec.c:198
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "impossível alterar para runas uid (%u, %u)"
+
+#: src/exec.c:216
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "impossível alterar pasta para %s"
+
+#: src/exec.c:220
+#, c-format
+msgid "starting from %s"
+msgstr "começando em %s"
+
+#: src/exec.c:302 src/exec_monitor.c:565 src/exec_monitor.c:567
+#: src/exec_nopty.c:569 src/exec_pty.c:585 src/exec_pty.c:1425
+#: src/exec_pty.c:1427 src/signal.c:144 src/signal.c:151 src/signal.c:165
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "impossível definir gestor para sinal %d"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "impossível remover PRIV_PROC_EXEC de PRIV_LIMIT"
+
+#: src/exec_common.c:85
+msgid "unable to dup intercept fd"
+msgstr "impossível dup interceptar fd"
+
+#: src/exec_intercept.c:138
+msgid "invalid PolicyCheckRequest"
+msgstr "PolicyCheckRequest inválido"
+
+#: src/exec_intercept.c:191 src/sudo.c:1187 src/sudo.c:1232 src/sudo.c:1276
+msgid "command rejected by policy"
+msgstr "cpmando rejeitado pela política"
+
+#: src/exec_intercept.c:272 src/sudo.c:1192 src/sudo.c:1237 src/sudo.c:1281
+#: src/sudo.c:1355
+msgid "policy plugin error"
+msgstr "erro da extensão de política"
+
+#: src/exec_intercept.c:304
+#, c-format
+msgid "client message too large: %zu"
+msgstr "mensagem do cliente muito grande: %zu"
+
+#: src/exec_intercept.c:340
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "valor type_case %d inesperado em %s de %s"
+
+#: src/exec_intercept.c:367 src/exec_intercept.c:371 src/exec_intercept.c:634
+#: src/exec_intercept.c:638 src/exec_monitor.c:464 src/exec_monitor.c:472
+#: src/exec_monitor.c:480 src/exec_monitor.c:487 src/exec_monitor.c:494
+#: src/exec_monitor.c:501 src/exec_monitor.c:508 src/exec_monitor.c:515
+#: src/exec_monitor.c:522 src/exec_monitor.c:529 src/exec_nopty.c:227
+#: src/exec_nopty.c:237 src/exec_nopty.c:247 src/exec_nopty.c:254
+#: src/exec_nopty.c:261 src/exec_nopty.c:268 src/exec_nopty.c:275
+#: src/exec_nopty.c:282 src/exec_nopty.c:289 src/exec_nopty.c:296
+#: src/exec_nopty.c:303 src/exec_nopty.c:310 src/exec_nopty.c:317
+#: src/exec_nopty.c:325 src/exec_pty.c:710 src/exec_pty.c:715
+#: src/exec_pty.c:812 src/exec_pty.c:819 src/exec_pty.c:916
+#: src/exec_pty.c:1239 src/exec_pty.c:1249 src/exec_pty.c:1259
+#: src/exec_pty.c:1266 src/exec_pty.c:1273 src/exec_pty.c:1280
+#: src/exec_pty.c:1287 src/exec_pty.c:1294 src/exec_pty.c:1301
+#: src/exec_pty.c:1308 src/exec_pty.c:1315 src/exec_pty.c:1322
+#: src/exec_pty.c:1735 src/exec_pty.c:1745 src/exec_pty.c:1790
+#: src/exec_pty.c:1797 src/exec_pty.c:1824
+msgid "unable to add event to queue"
+msgstr "impossível adicionar evento à fila"
+
+#: src/exec_intercept.c:395
+#, c-format
+msgid "server message too large: %zu"
+msgstr "mensagem do servidor muito grande: %zu"
+
+#: src/exec_intercept.c:608 src/exec_intercept.c:620
+#, c-format
+msgid "%s: missing message header"
+msgstr "%s: cabeçalho da mensagem em falta"
+
+#: src/exec_intercept.c:613
+#, c-format
+msgid "%s: expected message type %d, got %d"
+msgstr "%s: esperado tipo de mensagem %d, obtido %d"
+
+#: src/exec_monitor.c:360
+msgid "error reading from socketpair"
+msgstr "erro ao ler de socketpair"
+
+#: src/exec_monitor.c:377
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "tipo de resposta inesperada no canal secundário: %d"
+
+#: src/exec_monitor.c:583
+msgid "unable to set controlling tty"
+msgstr "impossível definir tty de controlo"
+
+#: src/exec_monitor.c:591 src/exec_nopty.c:383 src/exec_pty.c:1504
+#: src/exec_pty.c:1525 src/exec_pty.c:1545 src/tgetpass.c:307
+msgid "unable to create pipe"
+msgstr "impossível criar túnel"
+
+#: src/exec_monitor.c:601
+msgid "unable to receive message from parent"
+msgstr "impossível receber mensagem de pai"
+
+#: src/exec_monitor.c:617 src/exec_nopty.c:421 src/exec_pty.c:1583
+#: src/sudo_edit.c:361 src/tgetpass.c:311
+msgid "unable to fork"
+msgstr "impossível bifurcar"
+
+#: src/exec_monitor.c:621 src/exec_monitor.c:722 src/exec_nopty.c:479
+msgid "unable to restore tty label"
+msgstr "impossível restaurar rótulo tty"
+
+#: src/exec_monitor.c:637 src/sesh.c:123 src/sudo.c:1138
+#, c-format
+msgid "unable to execute %s"
+msgstr "impossível executar %s"
+
+#: src/exec_nopty.c:377 src/exec_pty.c:1434
+msgid "policy plugin failed session initialization"
+msgstr "a extensão de política falhou a inicialização de sessão"
+
+#: src/exec_nopty.c:391 src/exec_pty.c:1405 src/exec_pty.c:1413
+msgid "unable to create sockets"
+msgstr "impossível criar sockets"
+
+#: src/exec_nopty.c:467 src/exec_pty.c:1674
+msgid "error in event loop"
+msgstr "erro em ciclo de evento"
+
+#: src/exec_nopty.c:577 src/exec_pty.c:623 src/signal.c:101
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "impossível restaurar gestor para o sinal %d"
+
+#: src/exec_pty.c:162
+msgid "unable to allocate pty"
+msgstr "impossível alocar pty"
+
+#: src/exec_pty.c:226 src/exec_pty.c:266 src/exec_pty.c:306 src/exec_pty.c:357
+#: src/exec_pty.c:408
+msgid "I/O plugin error"
+msgstr "Erro da extensão E/S"
+
+#: src/exec_pty.c:230 src/exec_pty.c:270 src/exec_pty.c:310 src/exec_pty.c:361
+#: src/exec_pty.c:412
+msgid "command rejected by I/O plugin"
+msgstr "comando rejeitado pela extensão E/S"
+
+#: src/exec_pty.c:459
+msgid "error logging suspend"
+msgstr "erro ao registar suspensão"
+
+#: src/exec_pty.c:493
+msgid "error changing window size"
+msgstr "erro ao alterar o tamanho da janela"
+
+#: src/exec_pty.c:1629
+msgid "unable to send message to monitor process"
+msgstr "impossível enviar mensagem para monitorizar processo"
+
+#: src/load_plugins.c:108 src/load_plugins.c:122 src/load_plugins.c:128
+#: src/load_plugins.c:277 src/load_plugins.c:287 src/load_plugins.c:297
+#: src/load_plugins.c:344
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "erro em %s, linha %d ao carregar a extensão \"%s\""
+
+#: src/load_plugins.c:124
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s tem de ser propriedade de uid %d"
+
+#: src/load_plugins.c:130
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "%s só pode ter permissão de escrita para o dono"
+
+#: src/load_plugins.c:241 src/load_plugins.c:312
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "a ignorar extensão duplicada \"%s\" em %s, linha %d"
+
+#: src/load_plugins.c:279
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "impossível carregar %s: %s"
+
+#: src/load_plugins.c:289
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "impossível encontrar símbolo \"%s\" em %s"
+
+#: src/load_plugins.c:299
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "versão principal de extensão %d incompatível (esperada %d) encontrada em %s"
+
+#: src/load_plugins.c:317
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "a ignorar extensão de política \"%s\" em %s, linha %d"
+
+#: src/load_plugins.c:320
+msgid "only a single policy plugin may be specified"
+msgstr "só pode especificar um tipo de extensão de política"
+
+#: src/load_plugins.c:346
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "tipo de extensão %d desconhecida encontrada em %s"
+
+#: src/load_plugins.c:529
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "extensão de política %s não inclui um método check_policy"
+
+#: src/net_ifs.c:210 src/net_ifs.c:376 src/net_ifs.c:437 src/net_ifs.c:624
+#: src/net_ifs.c:855 src/sudo.c:483 src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "erro interno, transporte %s"
+
+#: src/parse_args.c:232
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "nome de variável de ambiente inválido: %s"
+
+#: src/parse_args.c:335
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "o argumento para -C tem de ser um número maior ou igual a 3"
+
+#: src/parse_args.c:566
+msgid "you may not specify both the -i and -s options"
+msgstr "não pode especificar ambas as opções \"-i\" e \"-s\""
+
+#: src/parse_args.c:571
+msgid "you may not specify both the -i and -E options"
+msgstr "não pode especificar ambas as opções \"-i\" e \"-E\""
+
+#: src/parse_args.c:581
+msgid "the -E option is not valid in edit mode"
+msgstr "a opção \"-E\" não é válida em modo de edição"
+
+#: src/parse_args.c:584
+msgid "you may not specify environment variables in edit mode"
+msgstr "não pode especificar variáveis de ambiente em modo de edição"
+
+#: src/parse_args.c:594
+msgid "the -U option may only be used with the -l option"
+msgstr "a opção \"-U\" só pode ser usada com a opção \"-l\""
+
+#: src/parse_args.c:598
+msgid "the -A and -S options may not be used together"
+msgstr "não pode especificar ambas as opções \"-A\" e \"-S\""
+
+#: src/parse_args.c:691
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit não é suportado nesta plataforma"
+
+#: src/parse_args.c:774
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Só uma das opções -e, -h, -i, -K, -l, -s, -v ou -V pode ser especificada"
+
+#: src/parse_args.c:790
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - edita ficheiros como outro utilizador\n"
+"\n"
+
+#: src/parse_args.c:792
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - executa um comando como outro utilizador\n"
+"\n"
+
+#: src/parse_args.c:798
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Opções:\n"
+
+#: src/parse_args.c:800
+msgid "use a helper program for password prompting"
+msgstr "usa um programa de ajuda para pedir a senha"
+
+#: src/parse_args.c:803
+msgid "use specified BSD authentication type"
+msgstr "usa um tipo de autenticação BSD especificado"
+
+#: src/parse_args.c:807
+msgid "run command in the background"
+msgstr "executa o comando em 2º plano"
+
+#: src/parse_args.c:810
+msgid "ring bell when prompting"
+msgstr "tocar campainha ao pedir"
+
+#: src/parse_args.c:812
+msgid "close all file descriptors >= num"
+msgstr "fecha todos os descritores de ficheiros >= num"
+
+#: src/parse_args.c:815
+msgid "run command with the specified BSD login class"
+msgstr "executa o comando com a classe de sessão BSD especificada"
+
+#: src/parse_args.c:818
+msgid "change the working directory before running command"
+msgstr "alterar a pasta de trabalho antes de executar o comando"
+
+#: src/parse_args.c:821
+msgid "preserve user environment when running command"
+msgstr "preserva o ambiente de utilizador ao executar o comando"
+
+#: src/parse_args.c:823
+msgid "preserve specific environment variables"
+msgstr "preserva variáveis de ambiente específicas"
+
+#: src/parse_args.c:825
+msgid "edit files instead of running a command"
+msgstr "edita ficheiros em vez de executar um comando"
+
+#: src/parse_args.c:828
+msgid "run command as the specified group name or ID"
+msgstr "executa o comando como nome de grupo ou ID especificados"
+
+#: src/parse_args.c:831
+msgid "set HOME variable to target user's home dir"
+msgstr "define a variável HOME para a pasta home do utilizador alvo"
+
+#: src/parse_args.c:834
+msgid "display help message and exit"
+msgstr "mostra a ajuda e sai"
+
+#: src/parse_args.c:836
+msgid "run command on host (if supported by plugin)"
+msgstr "executa o comando no anfitrião (se suportado pela extensão)"
+
+#: src/parse_args.c:839
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "executa a shell de sessão como utilizador alvo; também pode especificar um comando"
+
+#: src/parse_args.c:841
+msgid "remove timestamp file completely"
+msgstr "remove completamente o ficheiro de datação"
+
+#: src/parse_args.c:844
+msgid "invalidate timestamp file"
+msgstr "invalida o ficheiro de datação"
+
+#: src/parse_args.c:847
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "lista privilégios do utilizador ou verifica um comando específico; use duas vezes para formato mais longo"
+
+#: src/parse_args.c:850
+msgid "non-interactive mode, no prompts are used"
+msgstr "modo não-interactivo, não usa prompts"
+
+#: src/parse_args.c:853
+msgid "preserve group vector instead of setting to target's"
+msgstr "preserva vector de grupo em vez de o definir para o do alvo"
+
+#: src/parse_args.c:856
+msgid "use the specified password prompt"
+msgstr "usa o pedido de senha especificado"
+
+#: src/parse_args.c:858
+msgid "change the root directory before running command"
+msgstr "alterar a pasta raiz antes de executar o comando"
+
+#: src/parse_args.c:861
+msgid "create SELinux security context with specified role"
+msgstr "cria contexto de segurnaça SELinux com o papel especificado"
+
+#: src/parse_args.c:864
+msgid "read password from standard input"
+msgstr "lê a senha da entrada padrão"
+
+#: src/parse_args.c:867
+msgid "run shell as the target user; a command may also be specified"
+msgstr "executa a shell como utilizador alvo; também pode especificar um comando"
+
+#: src/parse_args.c:871
+msgid "create SELinux security context with specified type"
+msgstr "cria contexto de segurnaça SELinux com o tipo especificado"
+
+#: src/parse_args.c:874
+msgid "terminate command after the specified time limit"
+msgstr "termina o comando após o tempo limite especificado"
+
+#: src/parse_args.c:877
+msgid "in list mode, display privileges for user"
+msgstr "em modo Lista, mostra os privilégios do utilizador"
+
+#: src/parse_args.c:880
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "executa o comando (ou edita o ficheiro) como nome ou ID de utilizador especificados"
+
+#: src/parse_args.c:882
+msgid "display version information and exit"
+msgstr "mostra informação da versão e sai"
+
+#: src/parse_args.c:885
+msgid "update user's timestamp without running a command"
+msgstr "actualiza datação do utilizador sem executar um comando"
+
+#: src/parse_args.c:888
+msgid "stop processing command line arguments"
+msgstr "pára o processamento de argumentos da linha de comandos"
+
+#: src/selinux.c:84
+msgid "unable to open audit system"
+msgstr "impossível abrir o sistema de auditoria"
+
+#: src/selinux.c:94
+msgid "unable to send audit message"
+msgstr "impossível enviar mensagem de auditoria"
+
+#: src/selinux.c:128
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "impossível fgetfilecon %s"
+
+#: src/selinux.c:133
+#, c-format
+msgid "%s changed labels"
+msgstr "%s rótulos alterados"
+
+#: src/selinux.c:141
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "impossível restaurar contexto para %s"
+
+#: src/selinux.c:189
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "impossível abrir %s, sem re-rotular tty"
+
+#: src/selinux.c:193 src/selinux.c:238 src/selinux.c:268
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s não é um dispositivo carácter, sem re-rotular tty"
+
+#: src/selinux.c:202
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "impossível obter contexto tty actual, sem re-rotular tty"
+
+#: src/selinux.c:209
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "classe de segurança \"chr_file\" desconhecida, sem re-rotular tty"
+
+#: src/selinux.c:214
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "impossível obter novo contexto tty, sem re-rotular tty"
+
+#: src/selinux.c:223
+msgid "unable to set new tty context"
+msgstr "impossível definir novo contexto tty"
+
+#: src/selinux.c:321
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "tem de especificar um papel para o tipo %s"
+
+#: src/selinux.c:327
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "impossível obter o tipo predefinido para o papel %s"
+
+#: src/selinux.c:339
+msgid "failed to get new context"
+msgstr "falha ao obter novo contexto"
+
+#: src/selinux.c:348
+#, c-format
+msgid "failed to set new role %s"
+msgstr "falha ao definir novo papel %s"
+
+#: src/selinux.c:352
+#, c-format
+msgid "failed to set new type %s"
+msgstr "falha ao definir novo tipo %s"
+
+#: src/selinux.c:364
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s não é um contexto válido"
+
+#: src/selinux.c:396
+msgid "failed to get old context"
+msgstr "falha ao obter contexto antigo"
+
+#: src/selinux.c:402
+msgid "unable to determine enforcing mode."
+msgstr "impossível determinar modo de imposição."
+
+#: src/selinux.c:419
+#, c-format
+msgid "unable to set tty context to %s"
+msgstr "impossível definir contexto tty para %s"
+
+#: src/selinux.c:440
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "impossível definir contexto exec para %s"
+
+#: src/selinux.c:447
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "impossível definir contexto de criação de chave para %s"
+
+#: src/sesh.c:72
+msgid "requires at least one argument"
+msgstr "requer pelo menos um argumento"
+
+#: src/sesh.c:104
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "número de descritor de ficheiro inválido: %s"
+
+#: src/sesh.c:118
+#, c-format
+msgid "unable to run %s as a login shell"
+msgstr "impossível executar %s como shell de sessão"
+
+#: src/sesh.c:200 src/sesh.c:300 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: não é permitido editar ligações simbólicas"
+
+#: src/sesh.c:203 src/sesh.c:303 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: não é permitido editar ficheiros numa pasta onde se pode escrever"
+
+#: src/sesh.c:287 src/sesh.c:308 src/sesh.c:317 src/sesh.c:325
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "conteúdo da sessão de edição deixados em %s"
+
+#: src/sesh.c:416 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "impossível obter lista de grupo"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "impossível gravar gestor para o sinal %d"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "atingido o limite de controlo de recursos"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "o utilizador \"%s\" não é membro do projecto \"%s\""
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "a tarefa chamadora é final"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "impossível participar no projecto \"%s\""
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "não existe nenhum conjunto de recursos que aceite associações predefinidas para o projeto \"%s\""
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "o conjunto de recursos especificado não existe para o projecto \"%s\""
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "impossível associar ao conjunto de recursos predefinido do projecto \"%s\""
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "falha setproject para o projecto \"%s\""
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "aviso: falha na atribuição de controlo de recursos para o projecto \"%s\""
+
+#: src/sudo.c:213
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo versão %s\n"
+
+#: src/sudo.c:215
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Opções de configuração: %s\n"
+
+#: src/sudo.c:223
+msgid "fatal error, unable to load plugins"
+msgstr "erro fatal, impossível carregar extensões"
+
+#: src/sudo.c:269
+msgid "plugin did not return a command to execute"
+msgstr "a extensão não devolveu um comando a executar"
+
+#: src/sudo.c:302
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "modo sudo 0x%x inesperado"
+
+#: src/sudo.c:550
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "utilizador não existente na base de dados %s"
+
+#: src/sudo.c:607
+msgid "unable to determine tty"
+msgstr "impossível determinar tty"
+
+#: src/sudo.c:922
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s tem ser propriedade de uid %d e ter o bit setuid definido"
+
+#: src/sudo.c:925
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "a uid efectiva não é %d, é %s num sistema de ficheiros com a opção 'nosuid' definida ou um sistema de ficheiros NFS sem privilégios root?"
+
+#: src/sudo.c:931
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "a uid efectiva não é %d, tem sudo instalado com setuid root?"
+
+#: src/sudo.c:947 src/tgetpass.c:333
+msgid "unable to set supplementary group IDs"
+msgstr "impossível definir IDs de grupo suplementares"
+
+#: src/sudo.c:954
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "impossível definir gid efectiva para gid runas %u"
+
+#: src/sudo.c:960
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "impossível definir gid para gid runas %u"
+
+#: src/sudo.c:1003
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "condição de terminação de filho inesperada: %d"
+
+#: src/sudo.c:1110
+msgid "unable to initialize policy plugin"
+msgstr "impossível inicializar a extensão de política"
+
+#: src/sudo.c:1172
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "a extensão de política %s tem o método \"check_policy\" em falta"
+
+#: src/sudo.c:1218
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "a extensão de política %s não suporta privilégios de listagem"
+
+#: src/sudo.c:1262
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "a extensão de política %s não suporta a opção -v"
+
+#: src/sudo.c:1300
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "a extensão de política %s não suporta as opções -k/-K"
+
+#: src/sudo.c:1428
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "erro ao inicializar a extensão E/S %s"
+
+#: src/sudo.c:1431
+msgid "error initializing I/O plugin"
+msgstr "erro ao inicializar a extensão E/S"
+
+#: src/sudo.c:1580
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "erro ao inicializar a extensão de auditoria %s"
+
+#: src/sudo.c:1659
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: impossível registar evento%s%s de erro"
+
+#: src/sudo.c:1695
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: impossível registar evento%s%s de aceitação"
+
+#: src/sudo.c:1700 src/sudo.c:1738
+msgid "audit plugin error"
+msgstr "erro da extensão de auditoria"
+
+#: src/sudo.c:1733
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: impossível registar evento%s%s de rejeição"
+
+#: src/sudo.c:1793
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "erro ao inicializar a extensão de aprovação %s"
+
+#: src/sudo.c:1863
+msgid "command rejected by approver"
+msgstr "comando rejeitado pelo aprovador"
+
+#: src/sudo.c:1873
+msgid "approval plugin error"
+msgstr "erro da extensão de aprovação"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "sem pasta temporária onde possa escrever"
+
+#: src/sudo_edit.c:291
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s deixado sem alterações"
+
+#: src/sudo_edit.c:304 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s não alterado"
+
+#: src/sudo_edit.c:481
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: erro interno: número de caminhos ímpar"
+
+#: src/sudo_edit.c:483
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: impossível criar ficheiros temporários"
+
+#: src/sudo_edit.c:485 src/sudo_edit.c:609
+msgid "sesh: killed by a signal"
+msgstr "sesh: morto por um sinal"
+
+#: src/sudo_edit.c:487 src/sudo_edit.c:612
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: erro %d desconhecido"
+
+#: src/sudo_edit.c:602
+msgid "unable to copy temporary files back to their original location"
+msgstr "impossível copiar ficheiros temporários de volta à localização original"
+
+#: src/sudo_edit.c:606
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "impossível copiar alguns ficheiros temporários de volta à localização original"
+
+#: src/sudo_edit.c:649
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "impossível alterar uid para root (%u)"
+
+#: src/sudo_edit.c:670
+msgid "plugin error: missing file list for sudoedit"
+msgstr "erro de extensão: lista de ficheiros para sudoedit em falta"
+
+#: src/sudo_edit.c:722 src/sudo_edit.c:732
+msgid "unable to read the clock"
+msgstr "impossível ler o relógio"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "tempo expirado ao ler senha"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "não foi fornecida uma senha"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "impossível ler senha"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "é necessário um terminal para ler a senha; use a opção -S para ler da entrada padrão ou configure um ajudante de pedido de senha (askpass)"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "sem programa askpass especificado, tente definir SUDO_ASKPASS"
+
+#: src/tgetpass.c:328
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "impossível definir gid para %u"
+
+#: src/tgetpass.c:338
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "impossível definir uid para %u"
+
+#: src/tgetpass.c:343
+#, c-format
+msgid "unable to run %s"
+msgstr "impossível executar %s"
+
+#: src/utmp.c:288
+msgid "unable to save stdin"
+msgstr "impossível gravar stdin"
+
+#: src/utmp.c:290
+msgid "unable to dup2 stdin"
+msgstr "impossível dup2 stdin"
+
+#: src/utmp.c:293
+msgid "unable to restore stdin"
+msgstr "impossível restaurar stdin"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s: %s"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s: escrita curta"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "impossível ler ficheiro temporário"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "a ignorar extensão de política duplicada \"%s\" em %s, linha %d"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "sem tty presente e sem programa askpass especificado"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "uid %u desconhecida: quem é?"
diff --git a/po/pt_BR.mo b/po/pt_BR.mo
new file mode 100644
index 0000000..aba8c2d
--- /dev/null
+++ b/po/pt_BR.mo
Binary files differ
diff --git a/po/pt_BR.po b/po/pt_BR.po
new file mode 100644
index 0000000..7891d04
--- /dev/null
+++ b/po/pt_BR.po
@@ -0,0 +1,1147 @@
+# Brazilian Portuguese translation for sudo package.
+# Traduções em português brasileiro para o pacote sudo.
+# Copyright (C) 2021 Free Software Foundation, Inc.
+# This file is distributed under the same license as the sudo package.
+# Rafael Fontenelle <rafaelff@gnome.org>, 2013-2021.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.8b2\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2021-08-16 10:46-0600\n"
+"PO-Revision-Date: 2021-08-22 09:59-0300\n"
+"Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n"
+"Language-Team: Brazilian Portuguese <ldpbr-translation@lists.sourceforge.net>\n"
+"Language: pt_BR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1)\n"
+"X-Generator: Gtranslator 40.0\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "não foi possível abrir o userdb"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "não foi possível alterar para registro \"%s\" para %s"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "não foi possível restaurar registro"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:54 lib/util/json.c:183 lib/util/sudo_conf.c:211
+#: lib/util/sudo_conf.c:297 lib/util/sudo_conf.c:374 lib/util/sudo_conf.c:658
+#: src/conversation.c:80 src/exec_monitor.c:206 src/exec_monitor.c:456
+#: src/exec_monitor.c:462 src/exec_monitor.c:470 src/exec_monitor.c:478
+#: src/exec_monitor.c:485 src/exec_monitor.c:492 src/exec_monitor.c:499
+#: src/exec_monitor.c:506 src/exec_monitor.c:513 src/exec_monitor.c:520
+#: src/exec_monitor.c:527 src/exec_nopty.c:225 src/exec_nopty.c:235
+#: src/exec_nopty.c:245 src/exec_nopty.c:252 src/exec_nopty.c:259
+#: src/exec_nopty.c:266 src/exec_nopty.c:273 src/exec_nopty.c:280
+#: src/exec_nopty.c:287 src/exec_nopty.c:294 src/exec_nopty.c:301
+#: src/exec_nopty.c:308 src/exec_nopty.c:315 src/exec_nopty.c:323
+#: src/exec_nopty.c:511 src/exec_preload.c:143 src/exec_preload.c:203
+#: src/exec_pty.c:844 src/exec_pty.c:853 src/exec_pty.c:910
+#: src/exec_pty.c:1063 src/exec_pty.c:1237 src/exec_pty.c:1247
+#: src/exec_pty.c:1257 src/exec_pty.c:1264 src/exec_pty.c:1271
+#: src/exec_pty.c:1278 src/exec_pty.c:1285 src/exec_pty.c:1292
+#: src/exec_pty.c:1299 src/exec_pty.c:1306 src/exec_pty.c:1313
+#: src/exec_pty.c:1320 src/exec_pty.c:1328 src/exec_pty.c:1782
+#: src/load_plugins.c:156 src/load_plugins.c:181 src/load_plugins.c:217
+#: src/load_plugins.c:449 src/load_plugins.c:455 src/parse_args.c:190
+#: src/parse_args.c:211 src/parse_args.c:285 src/parse_args.c:630
+#: src/parse_args.c:652 src/parse_args.c:677 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:90 src/selinux.c:360 src/selinux.c:489
+#: src/selinux.c:498 src/sesh.c:113 src/sesh.c:146 src/sesh.c:152
+#: src/sesh.c:159 src/sesh.c:165 src/sesh.c:410 src/sudo.c:636 src/sudo.c:706
+#: src/sudo.c:716 src/sudo.c:741 src/sudo.c:760 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:795 src/sudo.c:837 src/sudo.c:847 src/sudo.c:876 src/sudo.c:1061
+#: src/sudo.c:1082 src/sudo.c:1374 src/sudo.c:1543 src/sudo.c:1770
+#: src/sudo.c:2104 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:429
+#: src/sudo_edit.c:438 src/sudo_edit.c:539 src/sudo_edit.c:546
+#: src/sudo_edit.c:686 src/sudo_edit.c:706 src/sudo_intercept_common.c:160
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:55
+#: lib/util/json.c:184 lib/util/sudo_conf.c:212 lib/util/sudo_conf.c:297
+#: lib/util/sudo_conf.c:374 lib/util/sudo_conf.c:658 src/conversation.c:81
+#: src/exec_intercept.c:154 src/exec_intercept.c:181 src/exec_intercept.c:204
+#: src/exec_intercept.c:225 src/exec_intercept.c:231 src/exec_intercept.c:240
+#: src/exec_intercept.c:246 src/exec_intercept.c:312 src/exec_intercept.c:407
+#: src/exec_intercept.c:627 src/exec_monitor.c:456 src/exec_monitor.c:462
+#: src/exec_monitor.c:470 src/exec_monitor.c:478 src/exec_monitor.c:485
+#: src/exec_monitor.c:492 src/exec_monitor.c:499 src/exec_monitor.c:506
+#: src/exec_monitor.c:513 src/exec_monitor.c:520 src/exec_monitor.c:527
+#: src/exec_nopty.c:225 src/exec_nopty.c:235 src/exec_nopty.c:245
+#: src/exec_nopty.c:252 src/exec_nopty.c:259 src/exec_nopty.c:266
+#: src/exec_nopty.c:273 src/exec_nopty.c:280 src/exec_nopty.c:287
+#: src/exec_nopty.c:294 src/exec_nopty.c:301 src/exec_nopty.c:308
+#: src/exec_nopty.c:315 src/exec_nopty.c:323 src/exec_preload.c:143
+#: src/exec_preload.c:203 src/exec_pty.c:844 src/exec_pty.c:853
+#: src/exec_pty.c:910 src/exec_pty.c:1237 src/exec_pty.c:1247
+#: src/exec_pty.c:1257 src/exec_pty.c:1264 src/exec_pty.c:1271
+#: src/exec_pty.c:1278 src/exec_pty.c:1285 src/exec_pty.c:1292
+#: src/exec_pty.c:1299 src/exec_pty.c:1306 src/exec_pty.c:1313
+#: src/exec_pty.c:1320 src/exec_pty.c:1328 src/exec_pty.c:1782
+#: src/load_plugins.c:156 src/load_plugins.c:181 src/load_plugins.c:217
+#: src/load_plugins.c:449 src/load_plugins.c:455 src/parse_args.c:190
+#: src/parse_args.c:212 src/parse_args.c:285 src/parse_args.c:630
+#: src/parse_args.c:652 src/parse_args.c:677 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:90 src/selinux.c:360 src/selinux.c:489
+#: src/selinux.c:498 src/sesh.c:113 src/sesh.c:411 src/sudo.c:227
+#: src/sudo.c:636 src/sudo.c:876 src/sudo.c:1061 src/sudo.c:1082
+#: src/sudo.c:1374 src/sudo.c:1543 src/sudo.c:1770 src/sudo.c:2104
+#: src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:429
+#: src/sudo_edit.c:438 src/sudo_edit.c:539 src/sudo_edit.c:546
+#: src/sudo_edit.c:686 src/sudo_edit.c:706 src/sudo_intercept_common.c:160
+msgid "unable to allocate memory"
+msgstr "não foi possível alocar memória"
+
+#: lib/util/mkdir_parents.c:69 lib/util/sudo_conf.c:697 src/selinux.c:234
+#: src/selinux.c:264 src/sudo.c:368 src/sudo_edit.c:494 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "não foi possível abrir %s"
+
+#: lib/util/mkdir_parents.c:84
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "não foi possível criar diretório %s"
+
+#: lib/util/mkdir_parents.c:93 lib/util/sudo_conf.c:674 src/copy_file.c:150
+#, c-format
+msgid "unable to stat %s"
+msgstr "não foi possível obter o estado de %s"
+
+#: lib/util/mkdir_parents.c:98
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s existe, mas não é um diretório (0%o)"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Sinal desconhecido"
+
+#: lib/util/strtoid.c:87 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:146 src/sesh.c:159
+msgid "invalid value"
+msgstr "valor inválido"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "valor grande demais"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "valor pequeno demais"
+
+#: lib/util/sudo_conf.c:230
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "Path inválido com valor \"%s\" em %s, linha %u"
+
+#: lib/util/sudo_conf.c:396 lib/util/sudo_conf.c:412 lib/util/sudo_conf.c:465
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "Valor inválido para %s \"%s\" em %s, linha %u"
+
+#: lib/util/sudo_conf.c:433
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "fonte de grupo sem suporte \"%s\" em %s, linha %u"
+
+#: lib/util/sudo_conf.c:449
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "máximo de grupos inválido \"%s\" em %s, linha %u"
+
+#: lib/util/sudo_conf.c:677
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s não é um arquivo comum"
+
+#: lib/util/sudo_conf.c:680 src/copy_file.c:163
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s tem como dono o uid %u, deveria ser %u"
+
+#: lib/util/sudo_conf.c:684
+#, c-format
+msgid "%s is world writable"
+msgstr "%s é gravável globalmente"
+
+#: lib/util/sudo_conf.c:687
+#, c-format
+msgid "%s is group writable"
+msgstr "%s é gravável pelo grupo"
+
+#: src/copy_file.c:93
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: truncar %s para zero bytes? (y/n) [n] "
+
+#: src/copy_file.c:97
+#, c-format
+msgid "not overwriting %s"
+msgstr "não vou sobrescrever %s"
+
+#: src/copy_file.c:119
+#, c-format
+msgid "unable to read from %s"
+msgstr "não foi possível ler de %s"
+
+#: src/copy_file.c:136 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "não foi possível gravar em %s"
+
+#: src/copy_file.c:154 src/sesh.c:218 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: não é um arquivo comum"
+
+#: src/copy_file.c:158
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: mode inválido de arquivo: 0%o"
+
+#: src/edit_open.c:265
+msgid "unable to restore current working directory"
+msgstr "não foi possível restaurar o diretório de trabalho atual"
+
+#: src/exec.c:130
+#, c-format
+msgid "unknown login class %s"
+msgstr "classe de login desconhecida %s"
+
+#: src/exec.c:142
+msgid "unable to set user context"
+msgstr "não foi possível definir contexto de usuário"
+
+#: src/exec.c:158
+msgid "unable to set process priority"
+msgstr "não foi possível definir prioridade do processo"
+
+#: src/exec.c:172
+#, c-format
+msgid "unable to change root to %s"
+msgstr "não foi possível alterar a raiz para %s"
+
+#: src/exec.c:185 src/exec.c:191 src/exec.c:198
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "não foi possível alterar para uid de \"runas\" (%u, %u)"
+
+#: src/exec.c:216
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "não foi possível alterar diretório para %s"
+
+#: src/exec.c:220
+#, c-format
+msgid "starting from %s"
+msgstr "iniciando a partir de %s"
+
+#: src/exec.c:302 src/exec_monitor.c:565 src/exec_monitor.c:567
+#: src/exec_nopty.c:569 src/exec_pty.c:585 src/exec_pty.c:1425
+#: src/exec_pty.c:1427 src/signal.c:144 src/signal.c:151 src/signal.c:165
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "não foi possível definir manipulador para sinal %d"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "não foi possível remover PRIV_PROC_EXEC de PRIV_LIMIT"
+
+#: src/exec_common.c:85
+msgid "unable to dup intercept fd"
+msgstr "não foi possível realizar dup de interceptação de fd"
+
+#: src/exec_intercept.c:138
+msgid "invalid PolicyCheckRequest"
+msgstr "PolicyCheckRequest inválida"
+
+#: src/exec_intercept.c:191 src/sudo.c:1187 src/sudo.c:1232 src/sudo.c:1276
+msgid "command rejected by policy"
+msgstr "comando rejeitado pela política"
+
+#: src/exec_intercept.c:272 src/sudo.c:1192 src/sudo.c:1237 src/sudo.c:1281
+#: src/sudo.c:1355
+msgid "policy plugin error"
+msgstr "erro de plug-in de política"
+
+#: src/exec_intercept.c:304
+#, c-format
+msgid "client message too large: %zu"
+msgstr "mensagem do cliente grande demais: %zu"
+
+#: src/exec_intercept.c:340
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "type_case com valor inesperado %d em %s de %s"
+
+#: src/exec_intercept.c:367 src/exec_intercept.c:371 src/exec_intercept.c:634
+#: src/exec_intercept.c:638 src/exec_monitor.c:464 src/exec_monitor.c:472
+#: src/exec_monitor.c:480 src/exec_monitor.c:487 src/exec_monitor.c:494
+#: src/exec_monitor.c:501 src/exec_monitor.c:508 src/exec_monitor.c:515
+#: src/exec_monitor.c:522 src/exec_monitor.c:529 src/exec_nopty.c:227
+#: src/exec_nopty.c:237 src/exec_nopty.c:247 src/exec_nopty.c:254
+#: src/exec_nopty.c:261 src/exec_nopty.c:268 src/exec_nopty.c:275
+#: src/exec_nopty.c:282 src/exec_nopty.c:289 src/exec_nopty.c:296
+#: src/exec_nopty.c:303 src/exec_nopty.c:310 src/exec_nopty.c:317
+#: src/exec_nopty.c:325 src/exec_pty.c:710 src/exec_pty.c:715
+#: src/exec_pty.c:812 src/exec_pty.c:819 src/exec_pty.c:916
+#: src/exec_pty.c:1239 src/exec_pty.c:1249 src/exec_pty.c:1259
+#: src/exec_pty.c:1266 src/exec_pty.c:1273 src/exec_pty.c:1280
+#: src/exec_pty.c:1287 src/exec_pty.c:1294 src/exec_pty.c:1301
+#: src/exec_pty.c:1308 src/exec_pty.c:1315 src/exec_pty.c:1322
+#: src/exec_pty.c:1735 src/exec_pty.c:1745 src/exec_pty.c:1790
+#: src/exec_pty.c:1797 src/exec_pty.c:1824
+msgid "unable to add event to queue"
+msgstr "não foi possível adicionar um evento à fila"
+
+#: src/exec_intercept.c:395
+#, c-format
+msgid "server message too large: %zu"
+msgstr "mensagem do servidor grande demais: %zu"
+
+#: src/exec_intercept.c:608 src/exec_intercept.c:620
+#, c-format
+msgid "%s: missing message header"
+msgstr "%s: faltando o cabeçalho de mensagens"
+
+#: src/exec_intercept.c:613
+#, c-format
+msgid "%s: expected message type %d, got %d"
+msgstr "%s: esperava mensagem do tipo %d, obteve %d"
+
+#: src/exec_monitor.c:360
+msgid "error reading from socketpair"
+msgstr "erro ao ler do par de soquetes"
+
+#: src/exec_monitor.c:377
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "tipo de resposta inesperada no canal de retorno: %d"
+
+#: src/exec_monitor.c:583
+msgid "unable to set controlling tty"
+msgstr "não foi possível definir tty de controle"
+
+#: src/exec_monitor.c:591 src/exec_nopty.c:383 src/exec_pty.c:1504
+#: src/exec_pty.c:1525 src/exec_pty.c:1545 src/tgetpass.c:307
+msgid "unable to create pipe"
+msgstr "não foi possível criar um encadeamento (pipe)"
+
+#: src/exec_monitor.c:601
+msgid "unable to receive message from parent"
+msgstr "não foi possível receber mensagem de pai"
+
+#: src/exec_monitor.c:617 src/exec_nopty.c:421 src/exec_pty.c:1583
+#: src/sudo_edit.c:361 src/tgetpass.c:311
+msgid "unable to fork"
+msgstr "não foi possível fazer fork"
+
+#: src/exec_monitor.c:621 src/exec_monitor.c:722 src/exec_nopty.c:479
+msgid "unable to restore tty label"
+msgstr "não foi possível restaurar rótulo de tty"
+
+#: src/exec_monitor.c:637 src/sesh.c:123 src/sudo.c:1138
+#, c-format
+msgid "unable to execute %s"
+msgstr "não foi possível executar %s"
+
+#: src/exec_nopty.c:377 src/exec_pty.c:1434
+msgid "policy plugin failed session initialization"
+msgstr "plug-in de política falhou ao inicializar da sessão"
+
+#: src/exec_nopty.c:391 src/exec_pty.c:1405 src/exec_pty.c:1413
+msgid "unable to create sockets"
+msgstr "não foi possível criar soquetes"
+
+#: src/exec_nopty.c:467 src/exec_pty.c:1674
+msgid "error in event loop"
+msgstr "erro em loop de evento"
+
+#: src/exec_nopty.c:577 src/exec_pty.c:623 src/signal.c:101
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "não foi possível restaurar manipulador para sinal %d"
+
+#: src/exec_pty.c:162
+msgid "unable to allocate pty"
+msgstr "não foi possível alocar pty"
+
+#: src/exec_pty.c:226 src/exec_pty.c:266 src/exec_pty.c:306 src/exec_pty.c:357
+#: src/exec_pty.c:408
+msgid "I/O plugin error"
+msgstr "erro no plug-in de E/S"
+
+#: src/exec_pty.c:230 src/exec_pty.c:270 src/exec_pty.c:310 src/exec_pty.c:361
+#: src/exec_pty.c:412
+msgid "command rejected by I/O plugin"
+msgstr "comando rejeitado pelo plug-in de E/S"
+
+#: src/exec_pty.c:459
+msgid "error logging suspend"
+msgstr "erro a registrar a suspensão"
+
+#: src/exec_pty.c:493
+msgid "error changing window size"
+msgstr "erro ao alterar o tamanho da janela"
+
+#: src/exec_pty.c:1629
+msgid "unable to send message to monitor process"
+msgstr "não foi possível enviar mensagem para monitorar processo"
+
+#: src/load_plugins.c:108 src/load_plugins.c:122 src/load_plugins.c:128
+#: src/load_plugins.c:277 src/load_plugins.c:287 src/load_plugins.c:297
+#: src/load_plugins.c:344
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "erro em %s, linha %d ao carregar plug-in \"%s\""
+
+#: src/load_plugins.c:124
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s deve ter como dono o uid %d"
+
+#: src/load_plugins.c:130
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "%s deve ser gravável apenas pelo dono"
+
+#: src/load_plugins.c:241 src/load_plugins.c:312
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "ignorando plug-in \"%s\" duplicado em %s, linha %d"
+
+#: src/load_plugins.c:279
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "não foi possível carregar %s: %s"
+
+#: src/load_plugins.c:289
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "não foi possível localizar símbolo \"%s\" em %s"
+
+#: src/load_plugins.c:299
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "versão maior %d do plug-in incompatível (esperava %d) localizada em %s"
+
+#: src/load_plugins.c:317
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "ignorando plug-in de política \"%s\" em %s, linha %d"
+
+#: src/load_plugins.c:320
+msgid "only a single policy plugin may be specified"
+msgstr "apenas um plug-in de política pode ser especificado"
+
+#: src/load_plugins.c:346
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "tipo de plug-in %d desconhecido localizado em %s"
+
+#: src/load_plugins.c:529
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "plug-in de política %s não inclui um método de check_policy"
+
+#: src/net_ifs.c:210 src/net_ifs.c:376 src/net_ifs.c:437 src/net_ifs.c:624
+#: src/net_ifs.c:855 src/sudo.c:483 src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "erro interno, estouro de pilha de %s"
+
+#: src/parse_args.c:232
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "nome de variável de ambiente inválida: %s"
+
+#: src/parse_args.c:335
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "o argumento do -C deve ser um número maior ou igual a 3"
+
+#: src/parse_args.c:566
+msgid "you may not specify both the -i and -s options"
+msgstr "você não pode especificar as opções -i e -s ao mesmo tempo"
+
+#: src/parse_args.c:571
+msgid "you may not specify both the -i and -E options"
+msgstr "você não pode especificar as opções -i e -E ao mesmo tempo"
+
+#: src/parse_args.c:581
+msgid "the -E option is not valid in edit mode"
+msgstr "a opção -E não é válida no modo de edição"
+
+#: src/parse_args.c:584
+msgid "you may not specify environment variables in edit mode"
+msgstr "você não pode especificar variáveis de ambiente no modo de edição"
+
+#: src/parse_args.c:594
+msgid "the -U option may only be used with the -l option"
+msgstr "a opção -U pode ser usada apenas com a opção -l"
+
+#: src/parse_args.c:598
+msgid "the -A and -S options may not be used together"
+msgstr "as opções -A e -S não podem ser usadas ao mesmo tempo"
+
+#: src/parse_args.c:691
+msgid "sudoedit is not supported on this platform"
+msgstr "não há suporte a sudoedit nesta plataforma"
+
+#: src/parse_args.c:774
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Apenas uma das opções -e, -h, -i, -K, -l, -s, -v ou -V pode ser especificada"
+
+#: src/parse_args.c:790
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - edita arquivos como outro usuário\n"
+"\n"
+
+#: src/parse_args.c:792
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - executa um comando como outro usuário\n"
+"\n"
+
+# Deixei minúsculo para seguir o padrão das demais linhas do "sudo -h"
+#: src/parse_args.c:798
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"opções:\n"
+
+#: src/parse_args.c:800
+msgid "use a helper program for password prompting"
+msgstr "usa um programa auxiliar para pedir senha"
+
+#: src/parse_args.c:803
+msgid "use specified BSD authentication type"
+msgstr "usa o tipo de autenticação BSD especificado"
+
+#: src/parse_args.c:807
+msgid "run command in the background"
+msgstr "executa um comando em plano de fundo"
+
+#: src/parse_args.c:810
+msgid "ring bell when prompting"
+msgstr "toca campainha ao solicitar senha"
+
+#: src/parse_args.c:812
+msgid "close all file descriptors >= num"
+msgstr "fecha todos os descritores, de arquivos, >= num"
+
+#: src/parse_args.c:815
+msgid "run command with the specified BSD login class"
+msgstr "executa um comando com uma classe de login BSD especificada"
+
+#: src/parse_args.c:818
+msgid "change the working directory before running command"
+msgstr "altera o diretório de trabalho antes de executar o comando"
+
+#: src/parse_args.c:821
+msgid "preserve user environment when running command"
+msgstr "preserva um ambiente de usuário ao executar um comando"
+
+#: src/parse_args.c:823
+msgid "preserve specific environment variables"
+msgstr "preserva variáveis de ambiente específicas"
+
+#: src/parse_args.c:825
+msgid "edit files instead of running a command"
+msgstr "edita arquivos em vez de executar um comando"
+
+#: src/parse_args.c:828
+msgid "run command as the specified group name or ID"
+msgstr "executa um comando como o ID ou nome de grupo especificado"
+
+#: src/parse_args.c:831
+msgid "set HOME variable to target user's home dir"
+msgstr "define a variável HOME para a pasta pessoal do usuário alvo"
+
+#: src/parse_args.c:834
+msgid "display help message and exit"
+msgstr "exibe uma mensagem de ajuda e sai"
+
+#: src/parse_args.c:836
+msgid "run command on host (if supported by plugin)"
+msgstr "executa o comando na máquina (se houver suporte pelo plug-in)"
+
+#: src/parse_args.c:839
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "executa um shell de login como usuário alvo; um comando também pode ser especificado"
+
+#: src/parse_args.c:841
+msgid "remove timestamp file completely"
+msgstr "remove arquivo de marca de tempo completamente"
+
+#: src/parse_args.c:844
+msgid "invalidate timestamp file"
+msgstr "invalida arquivo de marca de tempo"
+
+#: src/parse_args.c:847
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "lista os privilégios do usuário ou verifica um comando específico; use duas vezes para um formato maior"
+
+#: src/parse_args.c:850
+msgid "non-interactive mode, no prompts are used"
+msgstr "modo não interativo, não pergunta para o usuário"
+
+#: src/parse_args.c:853
+msgid "preserve group vector instead of setting to target's"
+msgstr "preserva vetor de grupos ao invés de definir para o do alvo"
+
+#: src/parse_args.c:856
+msgid "use the specified password prompt"
+msgstr "usa a senha especificada"
+
+#: src/parse_args.c:858
+msgid "change the root directory before running command"
+msgstr "altera o diretório raiz antes de executar o comando"
+
+#: src/parse_args.c:861
+msgid "create SELinux security context with specified role"
+msgstr "cria um contexto de segurança SELinux com o papel especificado"
+
+#: src/parse_args.c:864
+msgid "read password from standard input"
+msgstr "lê a senha da entrada padrão"
+
+#: src/parse_args.c:867
+msgid "run shell as the target user; a command may also be specified"
+msgstr "executa o shell como o usuário alvo; um comando também pode ser especificado"
+
+#: src/parse_args.c:871
+msgid "create SELinux security context with specified type"
+msgstr "cria um contexto de segurança SELinux com o tipo especificado"
+
+#: src/parse_args.c:874
+msgid "terminate command after the specified time limit"
+msgstr "termina o comando após o tempo limite especificado"
+
+#: src/parse_args.c:877
+msgid "in list mode, display privileges for user"
+msgstr "no modo lista, exibe os privilégios por usuário"
+
+#: src/parse_args.c:880
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "executa um comando (ou edita um arquivo) como o nome ou ID do usuário especificado"
+
+#: src/parse_args.c:882
+msgid "display version information and exit"
+msgstr "exibe as informações de versão e sai"
+
+#: src/parse_args.c:885
+msgid "update user's timestamp without running a command"
+msgstr "atualiza a marca de tempo do usuário sem executar um comando"
+
+#: src/parse_args.c:888
+msgid "stop processing command line arguments"
+msgstr "interrompe processamento de argumentos de linha de comando"
+
+#: src/selinux.c:84
+msgid "unable to open audit system"
+msgstr "não foi possível abrir o sistema de auditoria"
+
+#: src/selinux.c:94
+msgid "unable to send audit message"
+msgstr "não foi possível enviar mensagem de auditoria"
+
+#: src/selinux.c:128
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "não foi possível fazer fgetfilecon de %s"
+
+#: src/selinux.c:133
+#, c-format
+msgid "%s changed labels"
+msgstr "%s mudou de rótulo"
+
+#: src/selinux.c:141
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "não foi possível restaurar contexto de %s"
+
+#: src/selinux.c:189
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "não foi possível abrir %s, não re-rotulando o tty"
+
+#: src/selinux.c:193 src/selinux.c:238 src/selinux.c:268
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s não é um dispositivo de caractere, não re-rotulando o tty"
+
+#: src/selinux.c:202
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "não foi possível obter contexto de tty atual, não re-rotulando o tty"
+
+#: src/selinux.c:209
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "classe de segurança \"chr_file\" desconhecida, não re-rotulando o tty"
+
+#: src/selinux.c:214
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "não foi possível obter novo contexto de tty, não re-rotulando o tty"
+
+#: src/selinux.c:223
+msgid "unable to set new tty context"
+msgstr "não foi possível definir um novo contexto de tty"
+
+#: src/selinux.c:321
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "você deve especificar um papel para o tipo %s"
+
+#: src/selinux.c:327
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "não foi possível obter tipo padrão para o papel %s"
+
+#: src/selinux.c:339
+msgid "failed to get new context"
+msgstr "falha ao obter novo contexto"
+
+#: src/selinux.c:348
+#, c-format
+msgid "failed to set new role %s"
+msgstr "falha ao definir novo papel %s"
+
+#: src/selinux.c:352
+#, c-format
+msgid "failed to set new type %s"
+msgstr "falha ao definir novo tipo %s"
+
+#: src/selinux.c:364
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s não é um contexto válido"
+
+#: src/selinux.c:396
+msgid "failed to get old context"
+msgstr "falha ao obter contexto antigo"
+
+#: src/selinux.c:402
+msgid "unable to determine enforcing mode."
+msgstr "não foi possível determinar modo de aplicação."
+
+#: src/selinux.c:419
+#, c-format
+msgid "unable to set tty context to %s"
+msgstr "não foi possível definir contexto de tty de %s"
+
+#: src/selinux.c:440
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "não foi possível definir contexto de exec de %s"
+
+#: src/selinux.c:447
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "não foi possível definir contexto de criação de chave para %s"
+
+#: src/sesh.c:72
+msgid "requires at least one argument"
+msgstr "requer ao menos um argumento"
+
+#: src/sesh.c:104
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "número de descritor de arquivos inválido: %s"
+
+#: src/sesh.c:118
+#, c-format
+msgid "unable to run %s as a login shell"
+msgstr "não foi possível executar %s como shell de login"
+
+#: src/sesh.c:200 src/sesh.c:300 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: edição de links simbólicos não é permitida"
+
+#: src/sesh.c:203 src/sesh.c:303 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: edição de arquivos em um diretório gravável não é permitida"
+
+#: src/sesh.c:287 src/sesh.c:308 src/sesh.c:317 src/sesh.c:325
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "conteúdo da sessão de edição deixado em %s"
+
+#: src/sesh.c:416 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "não foi possível obter lista de grupos"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "não foi possível salvar manipulador para sinal %d"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "limite de controle de recurso foi atingido"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "usuário \"%s\" não é um membro do projeto \"%s\""
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "a tarefa de chamada é final"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "não foi possível participar do projeto \"%s\""
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "nenhuma pool de recursos aceitando vinculações padrões existe para o projeto \"%s\""
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "pool de recursos especificados não existe para o projeto \"%s\""
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "não foi possível vincular ao pool de recursos padrão para o projeto \"%s\""
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "setproject falhou para o projeto \"%s\""
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "aviso, atribuição de controle de recursos falhou para o projeto \"%s\""
+
+#: src/sudo.c:213
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo versão %s\n"
+
+#: src/sudo.c:215
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Opções de configuração: %s\n"
+
+#: src/sudo.c:223
+msgid "fatal error, unable to load plugins"
+msgstr "erro fatal, não foi possível carregar os plug-ins"
+
+#: src/sudo.c:269
+msgid "plugin did not return a command to execute"
+msgstr "o plug-in não retornou um comando para ser executado"
+
+#: src/sudo.c:302
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "modo de sudo inesperado 0x%x"
+
+#: src/sudo.c:550
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "você não existe no banco de dados %s"
+
+#: src/sudo.c:607
+msgid "unable to determine tty"
+msgstr "não foi possível determinar o tty"
+
+#: src/sudo.c:922
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s deve ter como dono o uid %d e tem definido o bit setuid"
+
+#: src/sudo.c:925
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "uid efetivo não é %d, é %s em um sistema de arquivos com a opção \"nosuid\" defina ou um sistema de arquivos NFS sem privilégios de root?"
+
+#: src/sudo.c:931
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "uid efetivo não é %d, sudo está instalado em uma raiz com setuid?"
+
+#: src/sudo.c:947 src/tgetpass.c:333
+msgid "unable to set supplementary group IDs"
+msgstr "não foi possível definir IDs de grupo suplementares"
+
+#: src/sudo.c:954
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "não foi possível definir gid efetivo para executar como gid %u"
+
+#: src/sudo.c:960
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "não foi possível definir gid para executar como gid %u"
+
+#: src/sudo.c:1003
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "condição inesperada de término de filho: %d"
+
+#: src/sudo.c:1110
+msgid "unable to initialize policy plugin"
+msgstr "não foi possível inicializar plug-in de política"
+
+#: src/sudo.c:1172
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "plug-in de política %s é sem o método \"check_policy\""
+
+#: src/sudo.c:1218
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "plug-in de política %s não tem suporte a listagem de privilégios"
+
+#: src/sudo.c:1262
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "plug-in de política %s não tem suporte à opção -v"
+
+#: src/sudo.c:1300
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "plug-in de política %s não tem suporte às opções -k/-K"
+
+#: src/sudo.c:1428
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "erro ao inicializar o plug-in de E/S %s"
+
+#: src/sudo.c:1431
+msgid "error initializing I/O plugin"
+msgstr "erro ao inicializar o plug-in de E/S"
+
+#: src/sudo.c:1580
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "erro ao inicializar o plug-in de auditoria %s"
+
+#: src/sudo.c:1659
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: não foi possível registrar evento de erro%s%s"
+
+#: src/sudo.c:1695
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: não foi possível registrar evento de aceite%s%s"
+
+#: src/sudo.c:1700 src/sudo.c:1738
+msgid "audit plugin error"
+msgstr "erro no plug-in de auditoria"
+
+#: src/sudo.c:1733
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: não foi possível registrar evento de rejeição%s%s"
+
+#: src/sudo.c:1793
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "erro ao inicializar o plug-in de aprovação %s"
+
+#: src/sudo.c:1863
+msgid "command rejected by approver"
+msgstr "comando rejeitado pelo aprovador"
+
+#: src/sudo.c:1873
+msgid "approval plugin error"
+msgstr "erro no plug-in de aprovação"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "nenhum diretório temporário gravável encontrado"
+
+#: src/sudo_edit.c:291
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s não foi modificado"
+
+#: src/sudo_edit.c:304 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s sem alteração"
+
+#: src/sudo_edit.c:481
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: erro interno: número ímpar de caminhos"
+
+#: src/sudo_edit.c:483
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: não foi possível criar arquivos temporários"
+
+#: src/sudo_edit.c:485 src/sudo_edit.c:609
+msgid "sesh: killed by a signal"
+msgstr "sesh: morto por um sinal"
+
+#: src/sudo_edit.c:487 src/sudo_edit.c:612
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: erro desconhecido: %d"
+
+#: src/sudo_edit.c:602
+msgid "unable to copy temporary files back to their original location"
+msgstr "não foi possível copiar arquivos temporários de volta para sua localização original"
+
+#: src/sudo_edit.c:606
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "não foi possível copiar alguns dos arquivos temporários de volta para sua localização original"
+
+#: src/sudo_edit.c:649
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "não foi possível alterar uid de root (%u)"
+
+#: src/sudo_edit.c:670
+msgid "plugin error: missing file list for sudoedit"
+msgstr "erro no plug-in: faltando lista de arquivo para sudoedit"
+
+#: src/sudo_edit.c:722 src/sudo_edit.c:732
+msgid "unable to read the clock"
+msgstr "não foi possível ler o relógio"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "tempo limite esgotado lendo senha"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "nenhuma senha foi fornecida"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "não foi possível ler a senha"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "um terminal é necessário para ler a senha; use a opção -S para ler a entrada padrão ou configure um auxiliar de askpass"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "nenhum programa de askpass especificado, tente definir SUDO_ASKPASS"
+
+#: src/tgetpass.c:328
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "não foi possível definir gid para %u"
+
+#: src/tgetpass.c:338
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "não foi possível definir uid para %u"
+
+#: src/tgetpass.c:343
+#, c-format
+msgid "unable to run %s"
+msgstr "não foi possível executar %s"
+
+#: src/utmp.c:288
+msgid "unable to save stdin"
+msgstr "não foi possível salvar a entrada padrão"
+
+#: src/utmp.c:290
+msgid "unable to dup2 stdin"
+msgstr "não foi possível realizar dup2 da entrada padrão"
+
+#: src/utmp.c:293
+msgid "unable to restore stdin"
+msgstr "não foi possível restaurar a entrada padrão"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s: %s"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s: escrita curta"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "não foi possível ler arquivo temporário"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "ignorando plug-in de política duplicada \"%s\" em %s, linha %d"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "nenhum tty presente e nenhum programa de askpass especificado"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "uid desconhecido %u: quem é você?"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "erro ao ler do sinal de encadeamento (pipe)"
+
+#~ msgid "internal error, tried allocate zero bytes"
+#~ msgstr "erro interno, tentou alocar zero bytes"
+
+#~ msgid "unable to set terminal to raw mode"
+#~ msgstr "não foi possível definir o terminal para modo raw"
+
+#~ msgid "unable to open socket"
+#~ msgstr "não foi possível abrir soquete"
+
+#~ msgid "%s: %s: %s\n"
+#~ msgstr "%s: %s: %s\n"
+
+#~ msgid "%s: %s\n"
+#~ msgstr "%s: %s\n"
+
+#~ msgid "internal error, tried to emalloc2(0)"
+#~ msgstr "erro interno, tentou fazer emalloc2(0)"
+
+#~ msgid "internal error, tried to ecalloc(0)"
+#~ msgstr "erro interno, tentou fazer ecalloc(0)"
+
+#~ msgid "internal error, tried to erealloc(0)"
+#~ msgstr "erro interno, tentou fazer erealloc(0)"
+
+#~ msgid "internal error, tried to erealloc3(0)"
+#~ msgstr "erro interno, tentou fazer erealloc3(0)"
+
+#~ msgid "internal error, tried to erecalloc(0)"
+#~ msgstr "erro interno, tentou fazer erecalloc(0)"
+
+#~ msgid "load_interfaces: overflow detected"
+#~ msgstr "load_interfaces: estouro de pilha detectado"
+
+#~ msgid "value out of range"
+#~ msgstr "valor fora de faixa"
+
+#~ msgid "select failed"
+#~ msgstr "seleção falhou"
+
+#~ msgid "list user's available commands\n"
+#~ msgstr "lista comandos disponíveis do usuário\n"
+
+#~ msgid "run a shell as target user\n"
+#~ msgstr "executa um shell como usuário alvo\n"
+
+#~ msgid "when listing, list specified user's privileges\n"
+#~ msgstr "ao listar, lista os privilégios do usuário especificado\n"
diff --git a/po/ro.mo b/po/ro.mo
new file mode 100644
index 0000000..a88473d
--- /dev/null
+++ b/po/ro.mo
Binary files differ
diff --git a/po/ro.po b/po/ro.po
new file mode 100644
index 0000000..eac96fa
--- /dev/null
+++ b/po/ro.po
@@ -0,0 +1,1362 @@
+# Portable object template file for sudo
+# This file is put in the public domain.
+# Todd C. Miller <Todd.Miller@sudo.ws>, 2011-2018
+# This file is distributed under the same license as the sudo package.
+#
+# Florentina Mușat <florentina.musat.28@gmail.com>, 2020.
+# Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>, 2022, 2023.
+#
+# Cronologia traducerii fișierului „sudo”:
+# Traducera inițială, făcută de FM, pentru versiunea sudoers 1.9.2rc1.
+# Actualizare a algoritmului formelor de plural (de la „trei-vechi” la „trei-nou”).
+# Actualizare a traducerii pentru versiunea 1.9.9b1, făcută de R-GC, ian-2022.
+# Actualizare a traducerii pentru versiunea 1.9.10b1, făcută de R-GC, feb-2022.
+# Actualizare a traducerii pentru versiunea 1.9.11b1, făcută de R-GC, mai-2022.
+# Actualizare a traducerii pentru versiunea 1.9.12b2, făcută de R-GC, oct-2022.
+# Actualizare a traducerii pentru versiunea 1.9.13b2, făcută de R-GC, ian-2023.
+# Actualizare a traducerii pentru versiunea 1.9.14b1, făcută de R-GC, iun-2023.
+# Actualizare a traducerii pentru versiunea Y, făcută de X, Z(luna-anul).
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.14b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-06-07 13:27-0600\n"
+"PO-Revision-Date: 2023-06-09 13:10+0200\n"
+"Last-Translator: Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>\n"
+"Language-Team: Romanian <translation-team-ro@lists.sourceforge.net>\n"
+"Language: ro\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2);\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 3.2.2\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "nu se poate deschide userdb"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "nu se poate comuta la registrul „%s” pentru %s"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "nu se poate restaura registrul"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:78 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:171 src/exec_monitor.c:418
+#: src/exec_monitor.c:424 src/exec_monitor.c:432 src/exec_monitor.c:440
+#: src/exec_monitor.c:447 src/exec_monitor.c:454 src/exec_monitor.c:461
+#: src/exec_monitor.c:468 src/exec_monitor.c:475 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:744 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1096
+#: src/exec_ptrace.c:1271 src/exec_ptrace.c:1624 src/exec_ptrace.c:1651
+#: src/exec_ptrace.c:1841 src/exec_pty.c:581 src/exec_pty.c:765
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:193 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:240
+#: src/sesh.c:246 src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:644
+#: src/sudo.c:709 src/sudo.c:719 src/sudo.c:746 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:787 src/sudo.c:805 src/sudo.c:846 src/sudo.c:855 src/sudo.c:865
+#: src/sudo.c:898 src/sudo.c:1127 src/sudo.c:1148 src/sudo.c:1441
+#: src/sudo.c:1610 src/sudo.c:1837 src/sudo.c:2171 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:430 src/sudo_edit.c:439
+#: src/sudo_edit.c:540 src/sudo_edit.c:547 src/sudo_edit.c:692
+#: src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:79 src/exec_intercept.c:111 src/exec_intercept.c:350
+#: src/exec_intercept.c:525 src/exec_intercept.c:589 src/exec_intercept.c:713
+#: src/exec_intercept.c:837 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:418 src/exec_monitor.c:424
+#: src/exec_monitor.c:432 src/exec_monitor.c:440 src/exec_monitor.c:447
+#: src/exec_monitor.c:454 src/exec_monitor.c:461 src/exec_monitor.c:468
+#: src/exec_monitor.c:475 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1651 src/exec_ptrace.c:1842 src/exec_pty.c:581
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:228 src/sudo.c:644 src/sudo.c:898 src/sudo.c:1127
+#: src/sudo.c:1148 src/sudo.c:1441 src/sudo.c:1610 src/sudo.c:1837
+#: src/sudo.c:2171 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:430
+#: src/sudo_edit.c:439 src/sudo_edit.c:540 src/sudo_edit.c:547
+#: src/sudo_edit.c:692 src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "nu se poate aloca memoria"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "nu se poate stabili starea lui %.*s"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s există, dar nu este un director (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:664
+#: lib/util/sudo_conf.c:683 lib/util/sudo_conf.c:710 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:495 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "nu se poate deschide %s"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "nu se poate executa mkdir %.*s"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "nu se poate deschide %.*s"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "expresia regulată este prea lungă"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Semnal necunoscut"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "valoare nevalidă"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "valoare prea mare"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "valoare prea mică"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "valoare de rută(path) nevalidă „%s” în %s, linia %u"
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "valoare nevalidă pentru %s „%s” în %s, linia %u"
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "sursă de grup nesuportată „%s” în %s, linia %u"
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "grupuri maxime nevalide „%s” în %s, linia %u"
+
+#: lib/util/sudo_conf.c:686
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s nu este un fișier regulat"
+
+#: lib/util/sudo_conf.c:689 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s este deținut de uid-ul %u, ar trebui să fie %u"
+
+# Corectare:
+# de la „inscriptibilă”,
+# la „inscriptibil”
+# - 1. pentru a fi =n consonanță cu celelalte mesaje
+# - 2. referința este pentru fișier, și nu pentru conținutul său
+#: lib/util/sudo_conf.c:693
+#, c-format
+msgid "%s is world writable"
+msgstr "%s este inscriptibil global"
+
+# Modificare:
+# de la: „este inscriptibil pe grup”
+# la:„este inscriptibil de către grup”
+#: lib/util/sudo_conf.c:696
+#, c-format
+msgid "%s is group writable"
+msgstr "%s este inscriptibil de către grup"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "nu s-a reușit să se determine confinarea (izolarea) AppArmor"
+
+# Modificat, de la:
+# „nu se poate schimba de root la”, la:
+# „nu se poate schimba directorul rădăcină la”
+# ***
+# asta, cînd mesajul în engleză, era:
+# „unable to change root to %s”
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "nu se poate schimba profilul AppArmor la %s"
+
+# Notă:
+# de întrebat băieții de la sudo, dacă se poate traduce (y/n) precum (d/n) sau nu...
+# și bineînțeles..., ca programul să răspundă cu
+# normalitate la schimbarea făcută
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: se trunchiază %s la zero octeți? (y/n) [n] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "nu se suprascrie %s"
+
+# Corectare:
+# de la „scrie” la „citi”
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "nu se poate citi de la %s"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "nu se poate scrie la %s"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "nu se poate stat %s"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: nu este un fișier regulat"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: mod de fișier defectuos: 0%o"
+
+#: src/edit_open.c:333
+msgid "unable to restore current working directory"
+msgstr "nu se poate restaura directorul de lucru curent"
+
+# Schimbat de la: 1linia de asamblare”
+# la: „tubul conector”
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "nu se pot stabili privilegiile"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "nu se poate stabili limita privilegiilor"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "clasă de autentificare necunoscută %s"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "nu se poate stabili contextul utilizatorului"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "nu se poate stabili prioritatea procesului"
+
+# Modificat, de la:
+# „nu se poate schimba de root la”, la:
+# „nu se poate schimba directorul rădăcină la”
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "nu se poate schimba directorul rădăcină la %s"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "nu se poate schimba la uid-ul run_as (%u, %u)"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "nu se poate schimba directorul la %s"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "începând de la %s"
+
+# Modificare:
+# de la: „nu se poate stabili mânerul pentru semnalul”
+# la: „nu se poate stabili manipulantul pentru semnalul”
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:552 src/exec_monitor.c:554
+#: src/exec_pty.c:1122 src/exec_pty.c:1124 src/signal.c:144 src/signal.c:151
+#: src/signal.c:165 src/suspend_parent.c:143
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "nu se poate stabili manipulantul pentru semnalul %d"
+
+#: src/exec.c:424
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "modul de interceptare nu este acceptat cu SELinux RBAC pe acest sistem"
+
+#: src/exec.c:429
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "nu se pot înregistra sub-comenzi cu SELinux RBAC pe acest sistem"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "nu se poate elimina PRIV_PROC_EXEC de la PRIV_LIMIT"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:163 src/exec_iolog.c:173
+#: src/exec_iolog.c:218 src/exec_iolog.c:225 src/exec_iolog.c:252
+#: src/exec_monitor.c:426 src/exec_monitor.c:434 src/exec_monitor.c:442
+#: src/exec_monitor.c:449 src/exec_monitor.c:456 src/exec_monitor.c:463
+#: src/exec_monitor.c:470 src/exec_monitor.c:477 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:457 src/exec_pty.c:432
+#: src/exec_pty.c:537 src/exec_pty.c:587 src/exec_pty.c:965 src/exec_pty.c:974
+#: src/exec_pty.c:981 src/exec_pty.c:988 src/exec_pty.c:995
+#: src/exec_pty.c:1002 src/exec_pty.c:1009 src/exec_pty.c:1016
+#: src/exec_pty.c:1023 src/exec_pty.c:1030 src/exec_pty.c:1037
+#: src/exec_pty.c:1044
+msgid "unable to add event to queue"
+msgstr "nu se poate adăuga evenimentul la coadă"
+
+#: src/exec_intercept.c:323 src/sudo.c:1033
+msgid "command not set by the security policy"
+msgstr "comanda nu este stabilită de politica de securitate"
+
+#: src/exec_intercept.c:401 src/exec_intercept.c:441 src/sudo.c:1253
+#: src/sudo.c:1298 src/sudo.c:1342
+msgid "command rejected by policy"
+msgstr "comandă respinsă de politică"
+
+#: src/exec_intercept.c:512 src/sudo.c:1940
+msgid "approval plugin error"
+msgstr "eroare la modulul de aprobare"
+
+#: src/exec_intercept.c:537 src/sudo.c:1258 src/sudo.c:1303 src/sudo.c:1347
+#: src/sudo.c:1421
+msgid "policy plugin error"
+msgstr "eroare de modul de politică"
+
+#: src/exec_intercept.c:566
+msgid "invalid PolicyCheckRequest"
+msgstr "PolicyCheckRequest nevalid"
+
+# Notă:
+# am tradus mesajul ca:
+# „cererea clientului este prea mare”
+# e posibil ca traducerea corectă să fie:
+# „cererea către client este prea mare”
+# Reacțiile/opiniile utilizatorilor ar fi utile...
+# Eu, unul n-am posibilitatea de-a verifica în practică, toate mesajele...
+# Acesta pare să fie un mesaj pentru LDAP..., iar
+# eu nu utilizez LDAP
+#: src/exec_intercept.c:709
+#, c-format
+msgid "client request too large: %zu"
+msgstr "cererea clientului este prea mare: %zu"
+
+#: src/exec_intercept.c:751
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "nu se poate despacheta %s cu dimensiunea %zu"
+
+# Am tradus:
+# „type_case cu o valoare neașteptată %d în %s de la %s”
+# poate suna/era mai bine:
+# „valoare (a) type_case neașteptată %d, în %s de la %s”
+#: src/exec_intercept.c:799
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "type_case cu o valoare neașteptată %d în %s de la %s"
+
+#: src/exec_intercept.c:825
+#, c-format
+msgid "server message too large: %zu"
+msgstr "mesaj de la server prea mare: %zu"
+
+# Modificare de la:
+# „Eroare de plugin I/O”
+# la: „Eroare a modulului In/Ieș(I/O)”
+# Pentru coerență cu restul traducerii, și nu numai...
+#: src/exec_iolog.c:321 src/exec_iolog.c:361 src/exec_iolog.c:401
+#: src/exec_iolog.c:452 src/exec_iolog.c:503
+msgid "I/O plugin error"
+msgstr "Eroare a modulului In/Ieș(I/O)"
+
+#: src/exec_iolog.c:325 src/exec_iolog.c:365 src/exec_iolog.c:405
+#: src/exec_iolog.c:456 src/exec_iolog.c:507
+msgid "command rejected by I/O plugin"
+msgstr "comandă respinsă de modulul In/Ieș/(I/O)"
+
+#: src/exec_iolog.c:555
+msgid "error logging suspend"
+msgstr "eroare la suspendarea jurnalizării"
+
+#: src/exec_iolog.c:590
+msgid "error changing window size"
+msgstr "eroare la schimbarea dimensiunii ferestrei"
+
+#: src/exec_monitor.c:328
+msgid "error reading from socketpair"
+msgstr "eroare la citirea de la socketpair"
+
+# Notă:
+# backchannel se poate traduce ca:
+# canal adiacent
+# canal de răspuns
+# canal secundar
+# canal posterior
+# canal din spate
+#: src/exec_monitor.c:340
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "tip de răspuns neașteptat pe backchannel: %d"
+
+#: src/exec_monitor.c:566
+msgid "unable to set controlling tty"
+msgstr "nu se poate stabili tty de control"
+
+# Schimbat de la: „linia de asamblare”
+# la: „tubul conector”
+#: src/exec_monitor.c:574 src/exec_nopty.c:504 src/exec_nopty.c:514
+#: src/exec_nopty.c:524 src/exec_nopty.c:560 src/exec_pty.c:1195
+#: src/exec_pty.c:1222 src/exec_pty.c:1242 src/exec_pty.c:1262
+#: src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr "nu se poate crea „tubul conector”(pipe)"
+
+# Modificat de la: „de la superior”
+# la: „de la procesul părinte”
+#: src/exec_monitor.c:584
+msgid "unable to receive message from parent"
+msgstr "nu se poate primi mesajul de la procesul părinte"
+
+# Modificat de la:
+# „nu se poate da fork”
+# la: „nu se poate bifurca”
+#: src/exec_monitor.c:600 src/exec_nopty.c:603 src/exec_pty.c:1303
+#: src/sudo_edit.c:361 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr "nu se poate bifurca"
+
+#: src/exec_monitor.c:604 src/exec_monitor.c:700 src/exec_nopty.c:708
+msgid "unable to restore tty label"
+msgstr "nu se poate restaura eticheta tty"
+
+#: src/exec_monitor.c:615 src/sesh.c:217 src/sudo.c:1204
+#, c-format
+msgid "unable to execute %s"
+msgstr "nu se poate executa %s"
+
+#: src/exec_nopty.c:554 src/exec_pty.c:1131
+msgid "policy plugin failed session initialization"
+msgstr "modulul de politică a eșuat la inițializarea sesiunii"
+
+#: src/exec_nopty.c:569 src/exec_pty.c:1100 src/exec_pty.c:1109
+msgid "unable to create sockets"
+msgstr "nu se pot crea socluri"
+
+#: src/exec_nopty.c:696 src/exec_pty.c:1406
+msgid "error in event loop"
+msgstr "eroare în bucla de eveniment"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:852 src/sudo.c:488
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "eroare internă, supraplin %s"
+
+#: src/exec_ptrace.c:1080 src/exec_ptrace.c:1105 src/exec_ptrace.c:1925
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "nu se pot configura registrele pentru procesul %d"
+
+#: src/exec_ptrace.c:1100 src/exec_ptrace.c:1275 src/exec_ptrace.c:1628
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "procesul %d a ieșit în mod neașteptat"
+
+#: src/exec_ptrace.c:1209
+msgid "unable to set seccomp filter"
+msgstr "nu se poate configura filtrul seccomp"
+
+#: src/exec_ptrace.c:1406
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "argument interpret, era așteptat „%s”, s-a primit „%s”"
+
+#: src/exec_ptrace.c:1505
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "nepotrivire în numele de rută, era așteptat „%s”, s-a primit „%s”"
+
+#: src/exec_ptrace.c:1514 src/exec_ptrace.c:1521 src/exec_ptrace.c:1545
+#: src/exec_ptrace.c:1553 src/exec_ptrace.c:1559 src/exec_ptrace.c:1565
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "nepotrivire în %s[%d], era așteptat „%s”, s-a primit „%s”"
+
+#: src/exec_ptrace.c:1632
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "stare neașteptată a procesului %d: 0x%x"
+
+#: src/exec_ptrace.c:1723
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "nu s-a putut obține mesajul de eveniment pentru procesul %d"
+
+#: src/exec_ptrace.c:1730
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "nu se pot obține registrele pentru procesul %d"
+
+#: src/exec_pty.c:84
+msgid "unable to allocate pty"
+msgstr "nu se poate aloca pty"
+
+#: src/exec_pty.c:131 src/exec_pty.c:284 src/tgetpass.c:251
+msgid "unable to restore terminal settings"
+msgstr "nu se pot restaura configurările terminalului"
+
+# Modificare:
+# de la: „nu se poate stabili mânerul pentru semnalul”
+# la: „nu se poate stabili manipulantul pentru semnalul”
+#: src/exec_pty.c:243
+msgid "unable to set handler for SIGCONT"
+msgstr "nu se poate stabili gestionarul pentru semnalul SIGCONT"
+
+# Modificare:
+# de la: „nu se poate stabili mânerul pentru semnalul”
+# la: „nu se poate stabili manipulantul pentru semnalul”
+#: src/exec_pty.c:293
+#, c-format
+msgid "unable to set handler for SIG%s"
+msgstr "nu se poate stabili gestionarul pentru semnalul SIG%s"
+
+# Modificare:
+# de la: „nu se poate stabili mânerul pentru semnalul”
+# la: „nu se poate stabili manipulantul pentru semnalul”
+#: src/exec_pty.c:317
+#, c-format
+msgid "unable to restore handler for SIG%s"
+msgstr "nu se poate restaura gestionarul pentru semnalul SIG%s"
+
+# Modificare:
+# de la: „nu se poate stabili mânerul pentru semnalul”
+# la: „nu se poate stabili manipulantul pentru semnalul”
+#: src/exec_pty.c:345
+msgid "unable to restore handler for SIGCONT"
+msgstr "nu se poate restaura gestionarul pentru semnalul SIGCONT"
+
+#: src/exec_pty.c:1353
+msgid "unable to send message to monitor process"
+msgstr "nu se poate trimite mesajul la procesul de monitorizare"
+
+#: src/load_plugins.c:75 src/load_plugins.c:222 src/load_plugins.c:232
+#: src/load_plugins.c:242 src/load_plugins.c:289
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "eroare în %s, linia %d în timpul încărcării modulului „%s”"
+
+#: src/load_plugins.c:186 src/load_plugins.c:257
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "se ignoră modulul duplicat „%s” în %s, linia %d"
+
+#: src/load_plugins.c:224
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "nu se poate încărca %s: %s"
+
+#: src/load_plugins.c:234
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "nu se poate găsi simbolul „%s” în %s"
+
+# Corectat:
+# de la: „versiune majoră a modulului incompatibilă %d (s-a așteptat %d) găsită în %s”
+# la: „versiune majoră a modulului incompatibilă %d (se aștepta %d) găsită în %s"
+# Observație:
+# e posibil ca poziția corectă a primei variabile, „%d”;
+# să fie:
+# „versiune majoră a modulului %d incompatibilă”
+#: src/load_plugins.c:244
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "versiune majoră a modulului incompatibilă %d (se aștepta %d) găsită în %s"
+
+#: src/load_plugins.c:262
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "se ignoră modulul de politică „%s” în %s, linia %d"
+
+#: src/load_plugins.c:265
+msgid "only a single policy plugin may be specified"
+msgstr "doar un singur modul de politică poate fi specificat"
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "tip de modul necunoscut %d găsit în %s"
+
+#: src/load_plugins.c:474
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "modulul de politică %s nu include o metodă check_policy"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "nume de variabilă de mediu nevalid: %s"
+
+# Modificat de la: „mai mare decît sau egal cu 3”
+# la: „mai mare sau egal cu 3”
+#: src/parse_args.c:319
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "argumentul la -C trebuie să fie un număr mai mare sau egal cu 3"
+
+# Modificat de la: „trebuie să specificați amândouă opțiunile -i și -s”
+# la: „nu puteți specifica ambele opțiuni, -i și -s”
+# ATENȚIE, și la traducerea următoare, mesajul de tradus este aproape identic acestuia, traducerea nu chiar...
+#: src/parse_args.c:556
+msgid "you may not specify both the -i and -s options"
+msgstr "nu puteți specifica ambele opțiuni, -i și -s"
+
+#: src/parse_args.c:561
+msgid "you may not specify both the -i and -E options"
+msgstr "nu puteți specifica amândouă opțiunile -i și -E"
+
+#: src/parse_args.c:571
+msgid "the -E option is not valid in edit mode"
+msgstr "opțiunea -E nu este validă în modul editare"
+
+#: src/parse_args.c:574
+msgid "you may not specify environment variables in edit mode"
+msgstr "nu puteți specifica variabile de mediu în modul editare"
+
+#: src/parse_args.c:584
+msgid "the -U option may only be used with the -l option"
+msgstr "opțiunea -U poate fi utilizată doar cu opțiunea -l"
+
+#: src/parse_args.c:588
+msgid "the -A and -S options may not be used together"
+msgstr "opțiunile -A și -S nu pot fi utilizate împreună"
+
+#: src/parse_args.c:686
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit nu este suportat pe această platformă"
+
+#: src/parse_args.c:744
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Doar una dintre opțiunile -e, -h, -i, -K, -l, -s, -v sau -V poate fi specificată"
+
+#: src/parse_args.c:757
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "Doar una dintre opțiunile -K, -k sau -N poate fi specificată"
+
+#: src/parse_args.c:778
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - editează fișiere ca alt utilizator\n"
+"\n"
+
+#: src/parse_args.c:780
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - execută o comandă ca alt utilizator\n"
+"\n"
+
+#: src/parse_args.c:785
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Opțiuni:\n"
+
+# Întrebare: cum sună mai bine?
+# - „utilizează un program de ajutor pentru solicitarea parolei”
+# sau:
+# - „utilizează un program auxiliar pentru solicitarea parolei”
+# Recenzie, Daniel Șegărceanu: a doua variantă, sună mai bine.
+# Am aplicat-o, în fond era și impresia mea, dar nu vroiam să modific prea mult fișierul...
+#: src/parse_args.c:787
+msgid "use a helper program for password prompting"
+msgstr "utilizează un program auxiliar pentru solicitarea parolei"
+
+#: src/parse_args.c:790
+msgid "use specified BSD authentication type"
+msgstr "utilizează un tip de autentificare BSD specificat"
+
+#: src/parse_args.c:794
+msgid "run command in the background"
+msgstr "rulează comanda în fundal"
+
+#: src/parse_args.c:797
+msgid "ring bell when prompting"
+msgstr "sună din clopoțel atunci când se solicită"
+
+#: src/parse_args.c:799
+msgid "close all file descriptors >= num"
+msgstr "închide toți descriptorii de fișier >= num"
+
+#: src/parse_args.c:802
+msgid "run command with the specified BSD login class"
+msgstr "rulează comanda cu clasa de autentificare BSD specificată"
+
+#: src/parse_args.c:805
+msgid "change the working directory before running command"
+msgstr "schimbă directorul de lucru înainte de-a executa comanda"
+
+#: src/parse_args.c:808
+msgid "preserve user environment when running command"
+msgstr "păstrează mediul utilizatorului atunci când se rulează comanda"
+
+#: src/parse_args.c:810
+msgid "preserve specific environment variables"
+msgstr "păstrează variabile de mediu specifice"
+
+#: src/parse_args.c:812
+msgid "edit files instead of running a command"
+msgstr "editează fișiere în locul rulării unei comenzi"
+
+# Modificat de la: „rulează comanda ca numele sau ID-ul de grup specificat"
+# la:
+# „rulează comanda ca grupul cu numele sau ID-ul specificat”
+#: src/parse_args.c:815
+msgid "run command as the specified group name or ID"
+msgstr "rulează comanda ca grupul cu numele sau ID-ul specificat"
+
+#: src/parse_args.c:818
+msgid "set HOME variable to target user's home dir"
+msgstr "stabilește variabila HOME să țintească spre directorul personal al utilizatorului"
+
+#: src/parse_args.c:821
+msgid "display help message and exit"
+msgstr "afișează mesajul de ajutor și iese"
+
+#: src/parse_args.c:823
+msgid "run command on host (if supported by plugin)"
+msgstr "rulează comanda pe gazdă (dacă este suportat de modul)"
+
+#: src/parse_args.c:826
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "rulează shell-ul de autentificare ca utilizatorul țintă; o comandă poate fi, de asemenea, specificată"
+
+#: src/parse_args.c:828
+msgid "remove timestamp file completely"
+msgstr "elimină complet fișierul de datare"
+
+#: src/parse_args.c:831
+msgid "invalidate timestamp file"
+msgstr "invalidează fișierul de datare"
+
+#: src/parse_args.c:834
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "listează privilegiile utilizatorului sau verifică o comandă specifică; utilizează de două ori pentru formatul mai lung"
+
+#: src/parse_args.c:837
+msgid "non-interactive mode, no prompts are used"
+msgstr "mod neinteractiv, nu sunt utilizate solicitări"
+
+#: src/parse_args.c:840
+msgid "preserve group vector instead of setting to target's"
+msgstr "păstrează vectorul grupului în loc să configurați pe cel al țintei"
+
+#: src/parse_args.c:843
+msgid "use the specified password prompt"
+msgstr "utilizează solicitarea de parolă specificată"
+
+#: src/parse_args.c:845
+msgid "change the root directory before running command"
+msgstr "schimbă la directorul rădăcină, înainte de a rula comanda"
+
+#: src/parse_args.c:848
+msgid "create SELinux security context with specified role"
+msgstr "creează contextul de securitate SELinux cu rolul specificat"
+
+#: src/parse_args.c:851
+msgid "read password from standard input"
+msgstr "citește parola de la intrarea standard"
+
+#: src/parse_args.c:854
+msgid "run shell as the target user; a command may also be specified"
+msgstr "rulează shell-ul ca utilizatorul țintă; o comandă poate fi, de asemenea, specificată"
+
+#: src/parse_args.c:858
+msgid "create SELinux security context with specified type"
+msgstr "creează contextul de securitate SELinux cu tipul specificat"
+
+#: src/parse_args.c:861
+msgid "terminate command after the specified time limit"
+msgstr "termină comanda după limita de timp specificată"
+
+#: src/parse_args.c:864
+msgid "in list mode, display privileges for user"
+msgstr "în modul listă, afișează privilegiile pentru utilizator"
+
+# Modificat de la:
+# „rulează comanda (sau fișierul de editare) ca nume specificat sau ID de utilizator”
+# la:
+# „rulează comanda (sau editează fișierul) ca utilizator cu numele sau ID-ul specificat”
+#: src/parse_args.c:867
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "rulează comanda (sau editează fișierul) ca utilizator cu numele sau ID-ul specificat"
+
+#: src/parse_args.c:869
+msgid "display version information and exit"
+msgstr "afișează informațiile de versiune și iese"
+
+#: src/parse_args.c:872
+msgid "update user's timestamp without running a command"
+msgstr "actualizează datarea utilizatorului fără să se ruleze o comandă"
+
+#: src/parse_args.c:875
+msgid "stop processing command line arguments"
+msgstr "oprește procesarea argumentelor în linia de comandă"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "nu se poate deschide sistemul auditare"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "nu se poate trimite mesajul de auditare"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "nu se poate fgetfilecon %s"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "etichete modificate %s"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "nu se poate restaura contextul pentru %s"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "nu se poate deschide %s, nu se etichetează din nou tty"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s nu este un dispozitiv de caracter, nu se etichetează din nou tty"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "nu se poate obține contextul tty curent, nu se etichetează din nou tty"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "clasă de securitate necunoscută „chr_file”, nu se etichetează din nou tty"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "nu se poate obține contextul tty nou, nu se etichetează din nou tty"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "nu se poate stabili contextul tty nou"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "trebuie să specificați un rol pentru tipul %s"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "nu se poate obține tipul implicit pentru rolul %s"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "nu s-a putut obține contextul nou"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "nu s-a putut stabili rolul nou %s"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "nu s-a putut stabili tipul nou %s"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s nu este un context valid"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "nu s-a putut obține contextul vechi"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "nu se poate determina modul de impunere."
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "nu se poate stabili contextul exec la %s"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "nu se poate stabili contextul de creare a cheii la %s"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "Doar una dintre opțiunile -c sau -i poate fi specificată"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "număr de descriptor de fișier nevalid: %s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "Opțiunea -%c nu poate fi utilizată în modul de editare."
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "Opțiunea -%c poate fi utilizată numai în modul de editare."
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: editarea legăturilor simbolice nu este permisă"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: editarea fișierelor într-un director inscriptibil nu este permisă"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "conținutul sesiunii de editare rămase în %s"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "nu se poate obține lista de grup %s"
+
+# Modificare:
+# de la: „nu se poate stabili mânerul pentru semnalul”
+# la: „nu se poate stabili manipulantul pentru semnalul”
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "nu se poate salva manipulantul pentru semnalul %d"
+
+# Modificare:
+# de la: „nu se poate stabili mânerul pentru semnalul”
+# la: „nu se poate stabili manipulantul pentru semnalul”
+#: src/signal.c:101 src/suspend_parent.c:149
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "nu se poate restaura manipulantul pentru semnalul %d"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "limita de control al resursei a fost atinsă"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "utilizatorul „%s” nu este un membru al proiectului „%s”"
+
+# sarcina de invocare este finală
+# sau:
+# sarcina de invocare este definitivă
+# NOTĂ. mesajul este pentru un sistem „Solaris”, așa că în curând e posibil să dispară din «repertoar»
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "sarcina de invocare este finală"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "nu s-a putut alătura proiectului „%s”"
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "nu există un grup de resurse care acceptă legături implicite pentru proiectul „%s”"
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "nu există grupul de resurse specificat pentru proiectul „%s”"
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "nu s-a putut lega la grupul de resurse implicit pentru proiectul „%s”"
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "setproject a eșuat pentru proiectul „%s”"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "avertizare, alocarea controlului de resurse a eșuat pentru proiectul „%s”"
+
+#: src/sudo.c:214
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Versiune sudo %s\n"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Configurează opțiunile: %s\n"
+
+#: src/sudo.c:224
+msgid "fatal error, unable to load plugins"
+msgstr "eroare fatală, nu se pot încărca modulele"
+
+#: src/sudo.c:270
+msgid "plugin did not return a command to execute"
+msgstr "modulul nu a întors o comandă de executat"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "mod sudo neașteptat 0x%x"
+
+#: src/sudo.c:559
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "nu existați în baza de date %s"
+
+#: src/sudo.c:616
+msgid "unable to determine tty"
+msgstr "nu se poate determina tty"
+
+#: src/sudo.c:932
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "Este setat indicatorul „fără privilegii noi”, ceea ce împiedică rularea «sudo» ca root."
+
+#: src/sudo.c:934
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "Dacă «sudo» rulează într-un container, poate fi necesar să ajustați configurația containerului pentru a dezactiva indicatorul."
+
+#: src/sudo.c:968
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s trebuie să fie deținut de uid-ul %d și să aibă bitul setuid stabilit"
+
+# Notă: eficient -> efectiv
+#: src/sudo.c:971
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "uid-ul efectiv nu este %d, este %s pe un sistem de fișiere cu opțiunea „nosuid” stabilită sau un sistem de fișiere NFS fără privilegii de root?"
+
+#: src/sudo.c:977
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "uid-ul efectiv nu este %d, este sudo instalat root setuid?"
+
+#: src/sudo.c:993 src/tgetpass.c:332
+msgid "unable to set supplementary group IDs"
+msgstr "nu se pot stabili ID-urile de grup suplimentare"
+
+# Notă: eficiente -> efective
+#: src/sudo.c:1000
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "nu se pot stabili gid-uri efective către gid-uri run_as %u"
+
+#: src/sudo.c:1006
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "nu se poate stabili gid-ul către gid-ul run_as %u"
+
+#: src/sudo.c:1037
+msgid "argv not set by the security policy"
+msgstr "argv nu este stabilit de politica de securitate"
+
+#: src/sudo.c:1041
+msgid "envp not set by the security policy"
+msgstr "envp nu este stabilit de politica de securitate"
+
+#: src/sudo.c:1063
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "condiție de terminare a procesului copil neașteptată: %d"
+
+#: src/sudo.c:1176
+msgid "unable to initialize policy plugin"
+msgstr "nu se poate inițializa modulul de politică"
+
+#: src/sudo.c:1238
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "modulului de politică %s îi lipsește metoda „check_policy”"
+
+#: src/sudo.c:1284
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "modulul de politică %s nu suportă listarea privilegiilor"
+
+#: src/sudo.c:1328
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "modulul de politică %s nu suportă opțiunea -v"
+
+#: src/sudo.c:1366
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "modulul de politică %s nu suportă opțiunile -k/-K"
+
+#: src/sudo.c:1495
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "eroare la inițializarea modulului In/Ieș(I/O) %s"
+
+#: src/sudo.c:1498
+msgid "error initializing I/O plugin"
+msgstr "eroare la inițializarea modulului In/Ieș(I/O)"
+
+#: src/sudo.c:1647
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "eroare la inițializarea modulului auditare %s"
+
+#: src/sudo.c:1726
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: nu se poate înregistra evenimentul de eroare%s%s"
+
+#: src/sudo.c:1762
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: nu se poate înregistra evenimentul de acceptare%s%s"
+
+#: src/sudo.c:1767 src/sudo.c:1805
+msgid "audit plugin error"
+msgstr "eroare a modulului de auditare"
+
+#: src/sudo.c:1800
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: nu se poate înregistra evenimentul de respingere%s%s"
+
+#: src/sudo.c:1860
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "eroare la inițializarea modulului de aprobare %s"
+
+#: src/sudo.c:1930
+msgid "command rejected by approver"
+msgstr "comandă respinsă de aprobator"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "nu s-a găsit niciun director temporar inscriptibil"
+
+#: src/sudo_edit.c:292
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s lăsat nemodificat"
+
+#: src/sudo_edit.c:305 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s neschimbat"
+
+#: src/sudo_edit.c:482
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: eroare internă: număr impar de rute(paths)"
+
+#: src/sudo_edit.c:484
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: nu se pot crea fișierele temporare"
+
+#: src/sudo_edit.c:486 src/sudo_edit.c:606
+msgid "sesh: killed by a signal"
+msgstr "sesh: omorât de un semnal"
+
+#: src/sudo_edit.c:488 src/sudo_edit.c:609
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: eroare necunoscută %d"
+
+#: src/sudo_edit.c:599
+msgid "unable to copy temporary files back to their original location"
+msgstr "nu se pot copia fișierele temporare înapoi la locația lor originală"
+
+#: src/sudo_edit.c:603
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "nu se pot copia o parte din fișierele temporare înapoi la locația lor originală"
+
+#: src/sudo_edit.c:650
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "nu se poate schimba uid-ul la root (%u)"
+
+#: src/sudo_edit.c:664
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "eroare de modul: lista de fișiere pentru sudoedit nu este validă"
+
+#: src/sudo_edit.c:685
+msgid "plugin error: missing file list for sudoedit"
+msgstr "eroare de modul: lipsește lista de fișiere pentru sudoedit"
+
+#: src/sudo_edit.c:728 src/sudo_edit.c:743
+msgid "unable to read the clock"
+msgstr "nu se poate citi ceasul"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "portul de interceptare nu este definit"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "limită de timp atinsă pentru citirea parolei"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "nu a fost furnizată nicio parolă"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "nu se poate citi parola"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "un terminal este necesar pentru a citit parola; ori utilizați opțiunea -S pentru a citi de la intrarea standard ori configurați un ajutor askpass"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "nu s-a specificat niciun program askpass, încercați să stabiliți SUDO_ASKPASS"
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "nu se poate stabili gid-ul la %u"
+
+#: src/tgetpass.c:337
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "nu se poate stabili uid-ul la %u"
+
+#: src/tgetpass.c:342
+#, c-format
+msgid "unable to run %s"
+msgstr "nu se poate rula %s"
+
+#: src/utmp.c:283
+msgid "unable to save stdin"
+msgstr "nu se poate salva stdin"
+
+#: src/utmp.c:285
+msgid "unable to dup2 stdin"
+msgstr "nu se poate dup2 stdin"
+
+#: src/utmp.c:288
+msgid "unable to restore stdin"
+msgstr "nu se poate restaura stdin"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s trebuie să fie deținut de uid-ul %d"
+
+# Modificat de la: „deținător”
+# la: „proprietar”
+# Explicația:
+# proprietarul poate, și deobicei este deasemeni deținător (de ceva)
+# în schimb, deținătorul decît deține ceva, deobicei este vremelnic(sau pe un timp determinat)
+# Exp:
+# arendașul, deține un teren(deobicei agricol, deci e un deținător de teren) drept pentru care se poate folosi de acel teren pe timpul și în condițiile financiare stabilite de proprietarul acelui teren(care este singurul care are drepturi depline asupra acelui teren.
+#~ msgid "%s must be only be writable by owner"
+#~ msgstr "%s trebuie să fie inscriptibil doar de proprietar"
+
+#~ msgid "insufficient space for execve arguments"
+#~ msgstr "spațiu insuficient pentru argumentele de execve"
+
+#~ msgid "unable to read execve %s for process %d"
+#~ msgstr "nu se poate citi execve %s pentru procesul %d"
+
+#~ msgid "requires at least one argument"
+#~ msgstr "necesită cel puțin un argument"
+
+#~ msgid "unable to run %s as a login shell"
+#~ msgstr "nu se poate rula %s ca shell de autentificare"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s: %s"
+
+#~ msgid "unable to set tty context to %s"
+#~ msgstr "nu se poate stabili contextul tty la %s"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s: scris scurt"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "nu se poate citi fișierul temporar"
diff --git a/po/ru.mo b/po/ru.mo
new file mode 100644
index 0000000..e337ab8
--- /dev/null
+++ b/po/ru.mo
Binary files differ
diff --git a/po/ru.po b/po/ru.po
new file mode 100644
index 0000000..a1f2db4
--- /dev/null
+++ b/po/ru.po
@@ -0,0 +1,1307 @@
+# Transation of sudo messages to Russian.
+# This file is put in the public domain.
+# This file is distributed under the same license as the sudo package.
+#
+# Pavel Maryanov <acid@jack.kiev.ua>, 2011.
+# Yuri Kozlov <yuray@komyakino.ru>, 2011, 2012, 2013, 2014, 2016.
+# Kirill Isakov <k@isakov.net>, 2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.14b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-06-07 13:27-0600\n"
+"PO-Revision-Date: 2023-06-09 00:22+0600\n"
+"Last-Translator: Kirill Isakov <k@isakov.net>\n"
+"Language-Team: Russian <gnu@d07.ru>\n"
+"Language: ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: Poedit 3.3.1\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "не удаётся открыть userdb"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "не удаётся переключиться на реестр «%s» для %s"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "не удаётся восстановить реестр"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:78 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:171 src/exec_monitor.c:418
+#: src/exec_monitor.c:424 src/exec_monitor.c:432 src/exec_monitor.c:440
+#: src/exec_monitor.c:447 src/exec_monitor.c:454 src/exec_monitor.c:461
+#: src/exec_monitor.c:468 src/exec_monitor.c:475 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:744 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1096
+#: src/exec_ptrace.c:1271 src/exec_ptrace.c:1624 src/exec_ptrace.c:1651
+#: src/exec_ptrace.c:1841 src/exec_pty.c:581 src/exec_pty.c:765
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:193 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:240
+#: src/sesh.c:246 src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:644
+#: src/sudo.c:709 src/sudo.c:719 src/sudo.c:746 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:787 src/sudo.c:805 src/sudo.c:846 src/sudo.c:855 src/sudo.c:865
+#: src/sudo.c:898 src/sudo.c:1127 src/sudo.c:1148 src/sudo.c:1441
+#: src/sudo.c:1610 src/sudo.c:1837 src/sudo.c:2171 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:430 src/sudo_edit.c:439
+#: src/sudo_edit.c:540 src/sudo_edit.c:547 src/sudo_edit.c:692
+#: src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:79 src/exec_intercept.c:111 src/exec_intercept.c:350
+#: src/exec_intercept.c:525 src/exec_intercept.c:589 src/exec_intercept.c:713
+#: src/exec_intercept.c:837 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:418 src/exec_monitor.c:424
+#: src/exec_monitor.c:432 src/exec_monitor.c:440 src/exec_monitor.c:447
+#: src/exec_monitor.c:454 src/exec_monitor.c:461 src/exec_monitor.c:468
+#: src/exec_monitor.c:475 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1651 src/exec_ptrace.c:1842 src/exec_pty.c:581
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:228 src/sudo.c:644 src/sudo.c:898 src/sudo.c:1127
+#: src/sudo.c:1148 src/sudo.c:1441 src/sudo.c:1610 src/sudo.c:1837
+#: src/sudo.c:2171 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:430
+#: src/sudo_edit.c:439 src/sudo_edit.c:540 src/sudo_edit.c:547
+#: src/sudo_edit.c:692 src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "не удаётся выделить память"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "не удаётся выполнить вызов stat %.*s"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s существует, но не является каталогом (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:664
+#: lib/util/sudo_conf.c:683 lib/util/sudo_conf.c:710 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:495 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "не удаётся открыть %s"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "не удаётся выполнить %.*s"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "не удаётся открыть %.*s"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "регулярное выражение слишком велико"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Неизвестный сигнал"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "недопустимое значение"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "значение слишком велико"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "значение слишком мало"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "некорректное значение Path «%s» в %s, строка %u"
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "некорректное значение для %s «%s» в %s, строка %u"
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "неподдерживаемый групповой источник «%s» в %s, строка %u"
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "некорректное максимальное значение для групп «%s» в %s, строка %u"
+
+#: lib/util/sudo_conf.c:686
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s не является обычным файлом"
+
+#: lib/util/sudo_conf.c:689 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s принадлежит uid %u, должно быть %u"
+
+#: lib/util/sudo_conf.c:693
+#, c-format
+msgid "%s is world writable"
+msgstr "доступ на запись в %s разрешена всем"
+
+#: lib/util/sudo_conf.c:696
+#, c-format
+msgid "%s is group writable"
+msgstr "доступ на запись в %s разрешена группе"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "не удаётся определить контейнер AppArmor"
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "не удаётся изменить профиль AppArmor на %s"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: обрезать %s до нуля байт? (y/n) [n] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "не перезаписываю %s"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "не удаётся прочитать из %s"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "не удаётся записать в %s"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "не удаётся выполнить stat для %s"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: не обычный файл"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: некорректный режим доступа к файлу: 0%o"
+
+#: src/edit_open.c:333
+msgid "unable to restore current working directory"
+msgstr "не удаётся восстановить текущий рабочий каталог"
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "не удаётся назначить привилегии"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "не удаётся назначить привилегии по ограничению"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "неизвестный класс входа %s"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "не удаётся назначить контекст пользователя"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "не удаётся назначить приоритет процесса"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "не удаётся изменить root на %s"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "не удаётся изменить на runas uid (%u, %u)"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "не удаётся сменить каталог на %s"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "начинаю с %s"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:552 src/exec_monitor.c:554
+#: src/exec_pty.c:1122 src/exec_pty.c:1124 src/signal.c:144 src/signal.c:151
+#: src/signal.c:165 src/suspend_parent.c:143
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "не удаётся установить обработчик сигнала %d"
+
+#: src/exec.c:424
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "режим перехвата не поддерживается SELinux на этой системе"
+
+#: src/exec.c:429
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "не удаётся записать в журнал подкоманды SELinux на этой системе"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "не удаётся удалить PRIV_PROC_EXEC из PRIV_LIMIT"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:163 src/exec_iolog.c:173
+#: src/exec_iolog.c:218 src/exec_iolog.c:225 src/exec_iolog.c:252
+#: src/exec_monitor.c:426 src/exec_monitor.c:434 src/exec_monitor.c:442
+#: src/exec_monitor.c:449 src/exec_monitor.c:456 src/exec_monitor.c:463
+#: src/exec_monitor.c:470 src/exec_monitor.c:477 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:457 src/exec_pty.c:432
+#: src/exec_pty.c:537 src/exec_pty.c:587 src/exec_pty.c:965 src/exec_pty.c:974
+#: src/exec_pty.c:981 src/exec_pty.c:988 src/exec_pty.c:995
+#: src/exec_pty.c:1002 src/exec_pty.c:1009 src/exec_pty.c:1016
+#: src/exec_pty.c:1023 src/exec_pty.c:1030 src/exec_pty.c:1037
+#: src/exec_pty.c:1044
+msgid "unable to add event to queue"
+msgstr "не удаётся добавить событие в очередь"
+
+#: src/exec_intercept.c:323 src/sudo.c:1033
+msgid "command not set by the security policy"
+msgstr "команда не назначена политикой безопасности"
+
+#: src/exec_intercept.c:401 src/exec_intercept.c:441 src/sudo.c:1253
+#: src/sudo.c:1298 src/sudo.c:1342
+msgid "command rejected by policy"
+msgstr "команда отклонена политикой"
+
+#: src/exec_intercept.c:512 src/sudo.c:1940
+msgid "approval plugin error"
+msgstr "ошибка в модуле подтверждения"
+
+#: src/exec_intercept.c:537 src/sudo.c:1258 src/sudo.c:1303 src/sudo.c:1347
+#: src/sudo.c:1421
+msgid "policy plugin error"
+msgstr "ошибка в модуле политики"
+
+#: src/exec_intercept.c:566
+msgid "invalid PolicyCheckRequest"
+msgstr "некорректный PolicyCheckRequest"
+
+#: src/exec_intercept.c:709
+#, c-format
+msgid "client request too large: %zu"
+msgstr "запрос клиента слишком велик: %zu"
+
+#: src/exec_intercept.c:751
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "не удаётся распаковать %s, размер %zu"
+
+#: src/exec_intercept.c:799
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "неожиданное значение type_case %d в %s из %s"
+
+#: src/exec_intercept.c:825
+#, c-format
+msgid "server message too large: %zu"
+msgstr "сообщение сервера слишком велико: %zu"
+
+#: src/exec_iolog.c:321 src/exec_iolog.c:361 src/exec_iolog.c:401
+#: src/exec_iolog.c:452 src/exec_iolog.c:503
+msgid "I/O plugin error"
+msgstr "Ошибка в модуле ввода/вывода"
+
+#: src/exec_iolog.c:325 src/exec_iolog.c:365 src/exec_iolog.c:405
+#: src/exec_iolog.c:456 src/exec_iolog.c:507
+msgid "command rejected by I/O plugin"
+msgstr "команда отклонена модулем ввода/вывода"
+
+#: src/exec_iolog.c:555
+msgid "error logging suspend"
+msgstr "ошибка при приостановке записи в журнал"
+
+#: src/exec_iolog.c:590
+msgid "error changing window size"
+msgstr "ошибка изменения размера окна"
+
+#: src/exec_monitor.c:328
+msgid "error reading from socketpair"
+msgstr "ошибка чтения из пары сокетов"
+
+#: src/exec_monitor.c:340
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "неожиданный тип ответа в резервном канале: %d"
+
+#: src/exec_monitor.c:566
+msgid "unable to set controlling tty"
+msgstr "не удаётся установить управляющий tty"
+
+#: src/exec_monitor.c:574 src/exec_nopty.c:504 src/exec_nopty.c:514
+#: src/exec_nopty.c:524 src/exec_nopty.c:560 src/exec_pty.c:1195
+#: src/exec_pty.c:1222 src/exec_pty.c:1242 src/exec_pty.c:1262
+#: src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr "не удаётся создать канал"
+
+#: src/exec_monitor.c:584
+msgid "unable to receive message from parent"
+msgstr "не удаётся получить сообщение от родительского процесса"
+
+#: src/exec_monitor.c:600 src/exec_nopty.c:603 src/exec_pty.c:1303
+#: src/sudo_edit.c:361 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr "не удаётся создать дочерний процесс"
+
+#: src/exec_monitor.c:604 src/exec_monitor.c:700 src/exec_nopty.c:708
+msgid "unable to restore tty label"
+msgstr "не удаётся создать восстановить метку tty"
+
+#: src/exec_monitor.c:615 src/sesh.c:217 src/sudo.c:1204
+#, c-format
+msgid "unable to execute %s"
+msgstr "не удаётся выполнить %s"
+
+#: src/exec_nopty.c:554 src/exec_pty.c:1131
+msgid "policy plugin failed session initialization"
+msgstr "модулю политик не удаётся инициализировать сеанс"
+
+#: src/exec_nopty.c:569 src/exec_pty.c:1100 src/exec_pty.c:1109
+msgid "unable to create sockets"
+msgstr "не удаётся создать сокеты"
+
+#: src/exec_nopty.c:696 src/exec_pty.c:1406
+msgid "error in event loop"
+msgstr "ошибка в событийном цикле"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:852 src/sudo.c:488
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "внутренняя ошибка, переполнение %s"
+
+#: src/exec_ptrace.c:1080 src/exec_ptrace.c:1105 src/exec_ptrace.c:1925
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "не удаётся назначить реестры для процесса %d"
+
+#: src/exec_ptrace.c:1100 src/exec_ptrace.c:1275 src/exec_ptrace.c:1628
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "процесс %d неожиданно завершился"
+
+#: src/exec_ptrace.c:1209
+msgid "unable to set seccomp filter"
+msgstr "не удаётся установить фильтр seccomp"
+
+#: src/exec_ptrace.c:1406
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "аргумент интерпретатора , ожидалось \"%s\", получено \"%s\""
+
+#: src/exec_ptrace.c:1505
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "несоответствие путей, ожидалось \"%s\", получено \"%s\""
+
+#: src/exec_ptrace.c:1514 src/exec_ptrace.c:1521 src/exec_ptrace.c:1545
+#: src/exec_ptrace.c:1553 src/exec_ptrace.c:1559 src/exec_ptrace.c:1565
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "несоответствие %s[%d], ожидалось \"%s\", получено \"%s\""
+
+#: src/exec_ptrace.c:1632
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "неожиданный статус процесса %d: 0x%x"
+
+#: src/exec_ptrace.c:1723
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "не удаётся получить сообщение события для процесса %d"
+
+#: src/exec_ptrace.c:1730
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "не удаётся получить реестры для процесса %d"
+
+#: src/exec_pty.c:84
+msgid "unable to allocate pty"
+msgstr "не удаётся выделить pty"
+
+#: src/exec_pty.c:131 src/exec_pty.c:284 src/tgetpass.c:251
+msgid "unable to restore terminal settings"
+msgstr "не удаётся восстановить настройки терминала"
+
+#: src/exec_pty.c:243
+msgid "unable to set handler for SIGCONT"
+msgstr "не удаётся установить обработчик сигнала SIGCONT"
+
+#: src/exec_pty.c:293
+#, c-format
+msgid "unable to set handler for SIG%s"
+msgstr "не удаётся установить обработчик сигнала SIG%s"
+
+#: src/exec_pty.c:317
+#, c-format
+msgid "unable to restore handler for SIG%s"
+msgstr "не удаётся восстановить обработчик сигнала SIG%s"
+
+#: src/exec_pty.c:345
+msgid "unable to restore handler for SIGCONT"
+msgstr "не удаётся восстановить обработчик сигнала SIGCONT"
+
+#: src/exec_pty.c:1353
+msgid "unable to send message to monitor process"
+msgstr "не удаётся отправить сообщение процессу аудита"
+
+#: src/load_plugins.c:75 src/load_plugins.c:222 src/load_plugins.c:232
+#: src/load_plugins.c:242 src/load_plugins.c:289
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "ошибка в %s, строка %d, при загрузке модуля «%s»"
+
+#: src/load_plugins.c:186 src/load_plugins.c:257
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "игнорируется повторный модуль ввода-вывода «%s» в %s, строка %d"
+
+#: src/load_plugins.c:224
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "не удаётся загрузить %s: %s"
+
+#: src/load_plugins.c:234
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "не удаётся найти символ «%s» в %s"
+
+#: src/load_plugins.c:244
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "найдена несовместимая основная версия модуля %d (ожидалась %d) в %s"
+
+#: src/load_plugins.c:262
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "игнорируется модуль политики «%s» в %s, строка %d"
+
+#: src/load_plugins.c:265
+msgid "only a single policy plugin may be specified"
+msgstr "может быть задан только один модуль политики"
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "найден неизвестный тип модуля %d в %s"
+
+#: src/load_plugins.c:474
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "модуль политики %s не содержит метод check_policy"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "некорректное имя переменной окружения: %s"
+
+#: src/parse_args.c:319
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "аргумент для -C должен быть числом, которое больше или равно 3"
+
+#: src/parse_args.c:556
+msgid "you may not specify both the -i and -s options"
+msgstr "параметры -i и -s являются взаимоисключающими"
+
+#: src/parse_args.c:561
+msgid "you may not specify both the -i and -E options"
+msgstr "параметры -i и -E являются взаимоисключающими"
+
+#: src/parse_args.c:571
+msgid "the -E option is not valid in edit mode"
+msgstr "параметр -E не действует в режиме редактирования"
+
+#: src/parse_args.c:574
+msgid "you may not specify environment variables in edit mode"
+msgstr "переменные окружения нельзя определять в режиме редактирования"
+
+#: src/parse_args.c:584
+msgid "the -U option may only be used with the -l option"
+msgstr "параметр -U можно использовать только с параметром -l"
+
+#: src/parse_args.c:588
+msgid "the -A and -S options may not be used together"
+msgstr "параметры -A и -S являются взаимоисключающими"
+
+#: src/parse_args.c:686
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit не поддерживается на этой платформе"
+
+#: src/parse_args.c:744
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Можно указать только параметры -e, -h, -i, -K, -l, -s, -v или -V"
+
+#: src/parse_args.c:757
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "Можно указать только один из параметров -K, -k, или -N"
+
+#: src/parse_args.c:778
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s — редактирование файлов от имени другого пользователя\n"
+"\n"
+
+#: src/parse_args.c:780
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s — выполнение команд от имени другого пользователя\n"
+"\n"
+
+#: src/parse_args.c:785
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Параметры:\n"
+
+#: src/parse_args.c:787
+msgid "use a helper program for password prompting"
+msgstr "использовать вспомогательную программу для ввода пароля"
+
+#: src/parse_args.c:790
+msgid "use specified BSD authentication type"
+msgstr "использовать указанный тип проверки подлинности BSD"
+
+#: src/parse_args.c:794
+msgid "run command in the background"
+msgstr "выполнить команду в фоновом режиме"
+
+#: src/parse_args.c:797
+msgid "ring bell when prompting"
+msgstr "звонок при запросе ввода"
+
+#: src/parse_args.c:799
+msgid "close all file descriptors >= num"
+msgstr "закрыть все дескрипторы файлов >= num"
+
+#: src/parse_args.c:802
+msgid "run command with the specified BSD login class"
+msgstr "выполнить команду с указанным классом входа BSD в систему"
+
+#: src/parse_args.c:805
+msgid "change the working directory before running command"
+msgstr "изменить рабочий каталог перед выполнением команды"
+
+#: src/parse_args.c:808
+msgid "preserve user environment when running command"
+msgstr "сохранить пользовательское окружение при выполнении команды"
+
+#: src/parse_args.c:810
+msgid "preserve specific environment variables"
+msgstr "сохранить определённые переменные окружения"
+
+#: src/parse_args.c:812
+msgid "edit files instead of running a command"
+msgstr "редактировать файлы вместо выполнения команды"
+
+#: src/parse_args.c:815
+msgid "run command as the specified group name or ID"
+msgstr "выполнить команду от имени или ID указанной группы"
+
+#: src/parse_args.c:818
+msgid "set HOME variable to target user's home dir"
+msgstr "установить для переменной HOME домашний каталог указанного пользователя"
+
+#: src/parse_args.c:821
+msgid "display help message and exit"
+msgstr "показать справку и выйти"
+
+#: src/parse_args.c:823
+msgid "run command on host (if supported by plugin)"
+msgstr "выполнить команду на узле (если поддерживается модулем)"
+
+#: src/parse_args.c:826
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "запустить оболочку входа в систему от имени указанного пользователя; также можно задать команду"
+
+#: src/parse_args.c:828
+msgid "remove timestamp file completely"
+msgstr "полностью удалить файл меток времени"
+
+#: src/parse_args.c:831
+msgid "invalidate timestamp file"
+msgstr "объявить недействительным файл меток времени"
+
+#: src/parse_args.c:834
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "показать список прав пользователя или проверить заданную команду; в длинном формате используется дважды"
+
+#: src/parse_args.c:837
+msgid "non-interactive mode, no prompts are used"
+msgstr "автономный режим без вывода запросов пользователю"
+
+#: src/parse_args.c:840
+msgid "preserve group vector instead of setting to target's"
+msgstr "сохранить вектор группы вместо установки целевой группы"
+
+#: src/parse_args.c:843
+msgid "use the specified password prompt"
+msgstr "использовать указанный запрос пароля"
+
+#: src/parse_args.c:845
+msgid "change the root directory before running command"
+msgstr "изменить корневой каталог перед выполнением команды"
+
+#: src/parse_args.c:848
+msgid "create SELinux security context with specified role"
+msgstr "создать контекст безопасности SELinux с указанной ролью"
+
+#: src/parse_args.c:851
+msgid "read password from standard input"
+msgstr "читать пароль из стандартного ввода"
+
+#: src/parse_args.c:854
+msgid "run shell as the target user; a command may also be specified"
+msgstr "запустить оболочку от имени указанного пользователя; также можно задать команду"
+
+#: src/parse_args.c:858
+msgid "create SELinux security context with specified type"
+msgstr "создать контекст безопасности SELinux указанного типа"
+
+#: src/parse_args.c:861
+msgid "terminate command after the specified time limit"
+msgstr "завершить команду по истечению указанного времени"
+
+#: src/parse_args.c:864
+msgid "in list mode, display privileges for user"
+msgstr "в режиме списка показывать права пользователя"
+
+#: src/parse_args.c:867
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "выполнить команду (или редактировать файл) от имени или ID указанного пользователя"
+
+#: src/parse_args.c:869
+msgid "display version information and exit"
+msgstr "показать информацию о версии и выйти"
+
+#: src/parse_args.c:872
+msgid "update user's timestamp without running a command"
+msgstr "обновить временную метку пользователя без выполнения команды"
+
+#: src/parse_args.c:875
+msgid "stop processing command line arguments"
+msgstr "прекратить обработку аргументов командной строки"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "не удаётся открыть систему аудита"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "не удаётся отправить сообщение аудита"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "не удаётся выполнить fgetfilecon %s"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "изменено меток: %s"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "не удаётся восстановить контекст для %s"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "не удаётся открыть %s, tty без возможности переименования"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s не является символьным устройством, tty без возможности переименования"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "не удаётся получить контекст текущего tty, tty без возможности переименования"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "неизвестный класс безопасности «chr_file», tty без возможности переименования"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "не удаётся получить новый контекст tty, tty без возможности переименования"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "не удаётся установить новый контекст tty"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "необходимо указать роль для типа %s"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "не удаётся получить тип по умолчанию для роли %s"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "не удаётся получить новый контекст"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "не удаётся установить новую роль %s"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "не удаётся установить новый тип %s"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s не является допустимым контекстом"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "не удаётся получить прошлый контекст"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "не удаётся определить принудительный режим."
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "не удаётся установить для контекста exec значение %s"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "не удаётся установить для контекста создания ключа значение %s"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "Может использоваться только один из параметров -c или -i"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "неверный номер файлового дескриптора: %s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "Параметр -%c не может использоваться в режиме редактирования."
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "Параметр -%c может использоваться только в режиме редактирования."
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: изменение символических ссылок не допускается"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: изменение файлов в каталоге, доступном на запись, не допускается"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "данные сеанса редактирования оставлены в %s"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "не удаётся получить список групп"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "не удаётся сохранить обработчик сигнала %d"
+
+#: src/signal.c:101 src/suspend_parent.c:149
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "не удаётся восстановить обработчик сигнала %d"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "достигнут лимит управления ресурсами"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "пользователь «%s» не является членом проекта «%s»"
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "вызывающее задание — последнее"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "не удаётся присоединиться к проекту «%s»"
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "для проекта «%s» не существует пула ресурсов, принимающих привязки по умолчанию"
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "у проекта «%s» нет указанного пула ресурсов"
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "не удаётся подключиться к пулу ресурсов по умолчанию проекта «%s»"
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "setproject завершилась с ошибкой для проекта «%s»"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "предупреждение: назначение контроля за ресурсами завершилось с ошибкой для проекта «%s»"
+
+#: src/sudo.c:214
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo версии %s\n"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Параметры настройки: %s\n"
+
+#: src/sudo.c:224
+msgid "fatal error, unable to load plugins"
+msgstr "фатальная ошибка, не удаётся загрузить модули"
+
+#: src/sudo.c:270
+msgid "plugin did not return a command to execute"
+msgstr "модуль не вернул команду для выполнения"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "неожиданный режим sudo: 0x%x"
+
+#: src/sudo.c:559
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "вы не существуете в базе данных %s"
+
+#: src/sudo.c:616
+msgid "unable to determine tty"
+msgstr "не удаётся установить tty"
+
+#: src/sudo.c:932
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "Установлен флаг «без новых привилегий», блокирующий запуск sudo от имени root."
+
+#: src/sudo.c:934
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "Если sudo запущен внутри контейнера, может понадобиться изменение настроек контейнера для отключения флага."
+
+#: src/sudo.c:968
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s должен принадлежать пользователю с uid %d и иметь бит setuid"
+
+#: src/sudo.c:971
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "эффективный uid не равен %d, возможно, %s находится в файловой системе, смонтированной с битом «nosuid» или в файловой системе NFS без прав суперпользователя?"
+
+#: src/sudo.c:977
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "эффективный uid не равен %d, программа sudo установлена с битом setuid и принадлежит root?"
+
+#: src/sudo.c:993 src/tgetpass.c:332
+msgid "unable to set supplementary group IDs"
+msgstr "не удаётся назначить дополнительные идентификаторы групп"
+
+#: src/sudo.c:1000
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "не удаётся назначить эффективный gid на runas gid %u"
+
+#: src/sudo.c:1006
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "не удаётся назначить gid на runas gid %u"
+
+#: src/sudo.c:1037
+msgid "argv not set by the security policy"
+msgstr "argv не установлен политикой безопасности"
+
+#: src/sudo.c:1041
+msgid "envp not set by the security policy"
+msgstr "envp не установлен политикой безопасности"
+
+#: src/sudo.c:1063
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "неожиданное условие завершения потомка: %d"
+
+#: src/sudo.c:1176
+msgid "unable to initialize policy plugin"
+msgstr "не удаётся инициализировать модуль политики"
+
+#: src/sudo.c:1238
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "модуль политики %s не содержит метод «check_policy»"
+
+#: src/sudo.c:1284
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "модуль политики %s не поддерживает списка прав"
+
+#: src/sudo.c:1328
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "модуль политики %s не поддерживает параметр -v"
+
+#: src/sudo.c:1366
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "модуль политики %s не поддерживает параметры -k/-K"
+
+#: src/sudo.c:1495
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "ошибка инициализации модуля ввода-вывода %s"
+
+#: src/sudo.c:1498
+msgid "error initializing I/O plugin"
+msgstr "ошибка инициализации модуля ввода-вывода"
+
+#: src/sudo.c:1647
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "ошибка инициализации модуля аудита %s"
+
+#: src/sudo.c:1726
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: не удаётся записать в журнал событие ошибки%s%s"
+
+#: src/sudo.c:1762
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: не удаётся записать в журнал событие принятия%s%s"
+
+#: src/sudo.c:1767 src/sudo.c:1805
+msgid "audit plugin error"
+msgstr "ошибка модуля аудита"
+
+#: src/sudo.c:1800
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: не удаётся записать в журнал событие отказа%s%s"
+
+#: src/sudo.c:1860
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "ошибка инициализации модуля подтверждения %s"
+
+#: src/sudo.c:1930
+msgid "command rejected by approver"
+msgstr "команда отклонена средством подтверждения"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "не найден временный каталог с доступом на запись"
+
+#: src/sudo_edit.c:292
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s осталось неизменным"
+
+#: src/sudo_edit.c:305 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s не изменён"
+
+#: src/sudo_edit.c:482
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: внутренняя ошибка: нечётное количество путей"
+
+#: src/sudo_edit.c:484
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: не удаётся создать временные файлы"
+
+#: src/sudo_edit.c:486 src/sudo_edit.c:606
+msgid "sesh: killed by a signal"
+msgstr "sesh: завершён сигналом"
+
+#: src/sudo_edit.c:488 src/sudo_edit.c:609
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: неизвестная ошибка %d"
+
+#: src/sudo_edit.c:599
+msgid "unable to copy temporary files back to their original location"
+msgstr "не удаётся скопировать временные файлы обратно в изначальное положение"
+
+#: src/sudo_edit.c:603
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "не удаётся скопировать некоторые из временных файлов обратно в изначальное положение"
+
+#: src/sudo_edit.c:650
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "не удаётся изменить uid на root (%u)"
+
+#: src/sudo_edit.c:664
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "ошибка модуля: некорректный список файлов для sudoedit"
+
+#: src/sudo_edit.c:685
+msgid "plugin error: missing file list for sudoedit"
+msgstr "ошибка модуля: отсутствует список файлов для sudoedit"
+
+#: src/sudo_edit.c:728 src/sudo_edit.c:743
+msgid "unable to read the clock"
+msgstr "не удаётся прочитать время"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "порт перехвата не назначен"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "превышено время ожидания при чтении пароля"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "пароль не предоставлен"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "не удаётся прочитать пароль"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "для ввода пароля требуется терминал; добавьте параметр -S, чтобы прочитать пароль из стандартного ввода, либо используйте вспомогательную программу askpass"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "не указана программа askpass, попробуйте задать значение в SUDO_ASKPASS"
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "не удаётся назначить gid равным %u"
+
+#: src/tgetpass.c:337
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "не удаётся назначить uid равным %u"
+
+#: src/tgetpass.c:342
+#, c-format
+msgid "unable to run %s"
+msgstr "не удаётся запустить %s"
+
+#: src/utmp.c:283
+msgid "unable to save stdin"
+msgstr "не удаётся сохранить стандартный ввод"
+
+#: src/utmp.c:285
+msgid "unable to dup2 stdin"
+msgstr "не удаётся выполнить dup2 для стандартного ввода"
+
+#: src/utmp.c:288
+msgid "unable to restore stdin"
+msgstr "не удаётся восстановить стандартный ввод"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "ошибка чтения из сигнального канала"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s: %s"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s должен принадлежать пользователю с uid %d"
+
+#~ msgid "%s must be only be writable by owner"
+#~ msgstr "%s должен быть доступен на запись только владельцу"
+
+#~ msgid "ignoring duplicate policy plugin `%s' in %s, line %d"
+#~ msgstr "игнорируется повторный модуль политики «%s» в %s, строка %d"
+
+#~ msgid "unable to set tty context to %s"
+#~ msgstr "не удаётся задать контекст tty для %s"
+
+#~ msgid "requires at least one argument"
+#~ msgstr "укажите не менее одного аргумента"
+
+#~ msgid "unable to run %s as a login shell"
+#~ msgstr "не удаётся выполнить %s в качестве регистрационной оболочки"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "неизвестный uid %u: кто вы?"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s: неполная запись"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "не удаётся прочитать временный файл"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "нет tty и не указана программа askpass"
+
+#~ msgid "internal error, tried allocate zero bytes"
+#~ msgstr "внутренняя ошибка, попытка выделить 0 байт"
+
+#~ msgid "unable to set terminal to raw mode"
+#~ msgstr "не удаётся перевести терминал в «сырой» режим"
+
+#~ msgid "unable to open socket"
+#~ msgstr "не удаётся открыть сокет"
+
+#~ msgid "%s: %s: %s\n"
+#~ msgstr "%s: %s: %s\n"
+
+#~ msgid "%s: %s\n"
+#~ msgstr "%s: %s\n"
+
+#~ msgid "internal error, tried to emalloc2(0)"
+#~ msgstr "внутренняя ошибка, попытка выполнить emalloc2(0)"
+
+#~ msgid "internal error, tried to ecalloc(0)"
+#~ msgstr "внутренняя ошибка, попытка выполнить ecalloc(0)"
+
+#~ msgid "internal error, tried to erealloc(0)"
+#~ msgstr "внутренняя ошибка, попытка выполнить erealloc(0)"
+
+#~ msgid "internal error, tried to erealloc3(0)"
+#~ msgstr "внутренняя ошибка, попытка выполнить erealloc3(0)"
+
+#~ msgid "internal error, tried to erecalloc(0)"
+#~ msgstr "внутренняя ошибка, попытка выполнить ereсalloc(0)"
+
+#~ msgid "load_interfaces: overflow detected"
+#~ msgstr "load_interfaces: обнаружено переполнение"
+
+#~ msgid "value out of range"
+#~ msgstr "значение за пределами диапазона"
+
+#~ msgid "select failed"
+#~ msgstr "ошибка select"
+
+#~ msgid "list user's available commands\n"
+#~ msgstr "вывести список команд, доступных пользователю\n"
+
+#~ msgid "run a shell as target user\n"
+#~ msgstr "запустить оболочку от имени указанного пользователя\n"
+
+#~ msgid "when listing, list specified user's privileges\n"
+#~ msgstr "при выводе списка показать привилегии пользователя\n"
+
+#~ msgid ": "
+#~ msgstr ": "
+
+#~ msgid "internal error, emalloc2() overflow"
+#~ msgstr "внутренняя ошибка, переполнение emalloc2()"
+
+#~ msgid "internal error, erealloc3() overflow"
+#~ msgstr "внутренняя ошибка, переполнение erealloc3()"
+
+#~ msgid "%s: at least one policy plugin must be specified"
+#~ msgstr "%s: необходимо указать не менее одного модуля политики"
+
+#~ msgid "must be setuid root"
+#~ msgstr "требуется setuid пользователя root"
+
+#~ msgid "the argument to -D must be between 1 and 9 inclusive"
+#~ msgstr "аргумент для -D должен быть в диапазоне от 1 до 9 включительно"
diff --git a/po/sk.mo b/po/sk.mo
new file mode 100644
index 0000000..a8d4cef
--- /dev/null
+++ b/po/sk.mo
Binary files differ
diff --git a/po/sk.po b/po/sk.po
new file mode 100644
index 0000000..2c00dbb
--- /dev/null
+++ b/po/sk.po
@@ -0,0 +1,858 @@
+# Portable object template file for sudo
+# This file is put in the public domain.
+# Todd C. Miller <Todd.Miller@courtesan.com>, 2011-2015
+# Dušan Kazik <prescott66@gmail.com>, 2015-2016
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.8.16b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2016-02-19 15:48-0700\n"
+"PO-Revision-Date: 2016-03-20 10:56+0100\n"
+"Last-Translator: Dušan Kazik <prescott66@gmail.com>\n"
+"Language-Team: Slovak <sk-i18n@lists.linux.sk>\n"
+"Language: sk\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.8.7\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+"X-Poedit-Basepath: .\n"
+"X-Poedit-SearchPath-0: .\n"
+
+#: lib/util/aix.c:85 lib/util/aix.c:164
+msgid "unable to open userdb"
+msgstr "nie je možné otvoriť userdb"
+
+#: lib/util/aix.c:219
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "nie je možné prepnúť na register „%s“ pre %s"
+
+#: lib/util/aix.c:244
+msgid "unable to restore registry"
+msgstr "nie je možné obnoviť register"
+
+#: lib/util/aix.c:267 lib/util/gidlist.c:64 lib/util/gidlist.c:74
+#: lib/util/sudo_conf.c:207 lib/util/sudo_conf.c:290 lib/util/sudo_conf.c:367
+#: lib/util/sudo_conf.c:569 src/conversation.c:75 src/exec.c:863
+#: src/exec_common.c:107 src/exec_common.c:123 src/exec_common.c:132
+#: src/exec_pty.c:684 src/exec_pty.c:692 src/load_plugins.c:52
+#: src/load_plugins.c:65 src/load_plugins.c:215 src/load_plugins.c:238
+#: src/load_plugins.c:303 src/load_plugins.c:318 src/parse_args.c:180
+#: src/parse_args.c:202 src/parse_args.c:370 src/parse_args.c:466
+#: src/parse_args.c:485 src/preserve_fds.c:47 src/preserve_fds.c:130
+#: src/selinux.c:84 src/selinux.c:291 src/selinux.c:416 src/selinux.c:425
+#: src/sesh.c:115 src/sudo.c:201 src/sudo.c:398 src/sudo.c:417 src/sudo.c:481
+#: src/sudo.c:655 src/sudo.c:665 src/sudo.c:685 src/sudo.c:704 src/sudo.c:713
+#: src/sudo.c:722 src/sudo.c:739 src/sudo.c:780 src/sudo.c:790 src/sudo.c:810
+#: src/sudo.c:1215 src/sudo.c:1236 src/sudo.c:1398 src/sudo.c:1492
+#: src/sudo_edit.c:151 src/sudo_edit.c:716 src/sudo_edit.c:813
+#: src/sudo_edit.c:925 src/sudo_edit.c:945
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:267 lib/util/gidlist.c:64 lib/util/sudo_conf.c:208
+#: lib/util/sudo_conf.c:290 lib/util/sudo_conf.c:367 lib/util/sudo_conf.c:569
+#: src/conversation.c:76 src/exec.c:863 src/exec_common.c:107
+#: src/exec_common.c:124 src/exec_common.c:133 src/exec_pty.c:684
+#: src/exec_pty.c:692 src/load_plugins.c:215 src/load_plugins.c:238
+#: src/load_plugins.c:303 src/load_plugins.c:318 src/parse_args.c:180
+#: src/parse_args.c:202 src/parse_args.c:370 src/parse_args.c:466
+#: src/parse_args.c:485 src/preserve_fds.c:47 src/preserve_fds.c:130
+#: src/selinux.c:84 src/selinux.c:291 src/selinux.c:416 src/selinux.c:425
+#: src/sesh.c:115 src/sudo.c:201 src/sudo.c:398 src/sudo.c:417 src/sudo.c:481
+#: src/sudo.c:810 src/sudo.c:1215 src/sudo.c:1236 src/sudo.c:1398
+#: src/sudo.c:1492 src/sudo_edit.c:151 src/sudo_edit.c:716 src/sudo_edit.c:813
+#: src/sudo_edit.c:925 src/sudo_edit.c:945
+msgid "unable to allocate memory"
+msgstr "nie je možné alokovať pamäť"
+
+#: lib/util/strsignal.c:48
+msgid "Unknown signal"
+msgstr "Neznámy signál"
+
+#: lib/util/strtoid.c:76 lib/util/strtoid.c:104 lib/util/strtomode.c:48
+#: lib/util/strtonum.c:58 lib/util/strtonum.c:176
+msgid "invalid value"
+msgstr "neplatná hodnota"
+
+#: lib/util/strtoid.c:83 lib/util/strtoid.c:111 lib/util/strtomode.c:54
+#: lib/util/strtonum.c:61 lib/util/strtonum.c:188
+msgid "value too large"
+msgstr "hodnota je príliš veľká"
+
+#: lib/util/strtoid.c:89 lib/util/strtomode.c:54 lib/util/strtonum.c:61
+#: lib/util/strtonum.c:182
+msgid "value too small"
+msgstr "hodnota je príliš malá"
+
+#: lib/util/sudo_conf.c:223
+#, c-format
+msgid "invalid Path value `%s' in %s, line %u"
+msgstr "neplatná hodnota pre cestu „%s“ v %s, riadok %u"
+
+#: lib/util/sudo_conf.c:389 lib/util/sudo_conf.c:442
+#, c-format
+msgid "invalid value for %s `%s' in %s, line %u"
+msgstr "neplatná hodnota pre %s „%s“ v %s, riadok %u"
+
+#: lib/util/sudo_conf.c:410
+#, c-format
+msgid "unsupported group source `%s' in %s, line %u"
+msgstr "nepodporovaný zdroj skupiny „%s“ v %s, riadok %u"
+
+#: lib/util/sudo_conf.c:426
+#, c-format
+msgid "invalid max groups `%s' in %s, line %u"
+msgstr ""
+
+#: lib/util/sudo_conf.c:585
+#, c-format
+msgid "unable to stat %s"
+msgstr ""
+
+#: lib/util/sudo_conf.c:588
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s nie je regulárny súbor"
+
+#: lib/util/sudo_conf.c:591
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s je vlastnený identifikátorom uid %u a mal by byť vlastnený %u"
+
+#: lib/util/sudo_conf.c:595
+#, c-format
+msgid "%s is world writable"
+msgstr ""
+
+#: lib/util/sudo_conf.c:598
+#, c-format
+msgid "%s is group writable"
+msgstr ""
+
+#: lib/util/sudo_conf.c:608 src/selinux.c:199 src/selinux.c:212 src/sudo.c:367
+#, c-format
+msgid "unable to open %s"
+msgstr "nie je možné otvoriť %s"
+
+#: src/exec.c:114 src/exec.c:116 src/exec.c:121 src/exec.c:409 src/exec.c:411
+#: src/exec.c:413 src/exec.c:415 src/exec.c:417 src/exec.c:419 src/exec.c:422
+#: src/exec.c:438 src/exec.c:440 src/exec.c:595 src/exec.c:790
+#: src/exec_pty.c:466 src/exec_pty.c:722 src/exec_pty.c:792 src/exec_pty.c:794
+#: src/exec_pty.c:806 src/exec_pty.c:808 src/exec_pty.c:1289
+#: src/exec_pty.c:1291 src/exec_pty.c:1296 src/exec_pty.c:1298
+#: src/exec_pty.c:1312 src/exec_pty.c:1323 src/exec_pty.c:1325
+#: src/exec_pty.c:1327 src/exec_pty.c:1329 src/exec_pty.c:1331
+#: src/exec_pty.c:1333 src/exec_pty.c:1335 src/signal.c:147
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr ""
+
+#: src/exec.c:126 src/exec_pty.c:838 src/exec_pty.c:1373 src/tgetpass.c:265
+msgid "unable to fork"
+msgstr ""
+
+#: src/exec.c:304 src/exec.c:312 src/exec.c:868 src/exec_pty.c:604
+#: src/exec_pty.c:611 src/exec_pty.c:654 src/exec_pty.c:659 src/exec_pty.c:946
+#: src/exec_pty.c:956 src/exec_pty.c:1001 src/exec_pty.c:1008
+#: src/exec_pty.c:1438 src/exec_pty.c:1445 src/exec_pty.c:1452
+msgid "unable to add event to queue"
+msgstr ""
+
+#: src/exec.c:392
+msgid "unable to create sockets"
+msgstr "nie je možné vytvoriť sokety"
+
+#: src/exec.c:447
+msgid "policy plugin failed session initialization"
+msgstr ""
+
+#: src/exec.c:492
+msgid "error in event loop"
+msgstr ""
+
+#: src/exec.c:510
+msgid "unable to restore tty label"
+msgstr "nie je možné obnoviť menovku rozhrania tty"
+
+#: src/exec.c:603 src/exec_pty.c:498 src/signal.c:86
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr ""
+
+#: src/exec.c:721 src/exec_pty.c:1180
+msgid "error reading from signal pipe"
+msgstr "chyba pri čítaní zo zreťazenia signálov"
+
+#: src/exec_common.c:166
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "nie je možné odstrániť PRIV_PROC_EXEC z PRIV_LIMIT"
+
+#: src/exec_pty.c:188
+msgid "unable to allocate pty"
+msgstr "nie je možné alokovať pty"
+
+#: src/exec_pty.c:766 src/exec_pty.c:775 src/exec_pty.c:783
+#: src/exec_pty.c:1281 src/exec_pty.c:1370 src/signal.c:128 src/tgetpass.c:261
+msgid "unable to create pipe"
+msgstr "nie je možné vytvoriť zreťazenie"
+
+#: src/exec_pty.c:1213
+msgid "error reading from pipe"
+msgstr "chyba pri čítaní zo zreťazenia"
+
+#: src/exec_pty.c:1238
+msgid "error reading from socketpair"
+msgstr ""
+
+#: src/exec_pty.c:1247
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "neočakávaný typ odpovede na zadnom kanále: %d"
+
+#: src/exec_pty.c:1349
+msgid "unable to set controlling tty"
+msgstr "nie je možné nastaviť ovládacie rozhranie tty"
+
+#: src/load_plugins.c:50 src/load_plugins.c:63 src/load_plugins.c:85
+#: src/load_plugins.c:115 src/load_plugins.c:123 src/load_plugins.c:129
+#: src/load_plugins.c:170 src/load_plugins.c:178 src/load_plugins.c:185
+#: src/load_plugins.c:191
+#, c-format
+msgid "error in %s, line %d while loading plugin `%s'"
+msgstr "chyba v %s, riadok%d počas načítania zásuvného modulu „%s“"
+
+#: src/load_plugins.c:87
+#, c-format
+msgid "%s%s: %s"
+msgstr "%s%s: %s"
+
+#: src/load_plugins.c:125
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s musí byť vlastnený identifikátorom uid %d"
+
+#: src/load_plugins.c:131
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "%s musí byť zapisovateľný iba vlastníkom"
+
+#: src/load_plugins.c:172
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "nie je možné načítať %s:%s"
+
+#: src/load_plugins.c:180
+#, c-format
+msgid "unable to find symbol `%s' in %s"
+msgstr "nie je možné nájsť symbol „%s“ v %s"
+
+#: src/load_plugins.c:187
+#, c-format
+msgid "unknown policy type %d found in %s"
+msgstr "našiel sa neplatný typ politiky %d v %s"
+
+#: src/load_plugins.c:193
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "nekompatibilná hlavná verzia zásuvného modulu %d (očakávala sa %d) nájdená v %s"
+
+#: src/load_plugins.c:202
+#, c-format
+msgid "ignoring policy plugin `%s' in %s, line %d"
+msgstr "ignoruje sa zásuvný modul politiky „%s“ v %s, riadok %d"
+
+#: src/load_plugins.c:204
+msgid "only a single policy plugin may be specified"
+msgstr "môže byť určený iba jeden zásuvný modul politiky"
+
+#: src/load_plugins.c:207
+#, c-format
+msgid "ignoring duplicate policy plugin `%s' in %s, line %d"
+msgstr "ignoruje sa zdvojený zásuvný modul politiky „%s“ v %s, riadok %d"
+
+#: src/load_plugins.c:228
+#, c-format
+msgid "ignoring duplicate I/O plugin `%s' in %s, line %d"
+msgstr "ignoruje sa zdvojený vstupno-výstupný zásuvný modul „%s“ v %s, riadok %d"
+
+#: src/load_plugins.c:331
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "zásuvný modul politiky %s nezahŕňa spôsob check_policy"
+
+#: src/net_ifs.c:173 src/net_ifs.c:190 src/net_ifs.c:335 src/sudo.c:476
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "vnútorná chyba, %s pretečenie"
+
+#: src/parse_args.c:239
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "parameter pre -C musí byť číslo väčšie alebo rovné 3"
+
+#: src/parse_args.c:406
+msgid "you may not specify both the `-i' and `-s' options"
+msgstr "nemôžete určiť naraz voľby „-i“ a „-s“"
+
+#: src/parse_args.c:410
+msgid "you may not specify both the `-i' and `-E' options"
+msgstr "nemôžete určiť naraz voľby „-i“ a „-E“"
+
+#: src/parse_args.c:420
+msgid "the `-E' option is not valid in edit mode"
+msgstr "voľba „-E“ nie je platná v režime úprav"
+
+#: src/parse_args.c:422
+msgid "you may not specify environment variables in edit mode"
+msgstr "nemôžete určiť premenné prostredia v režim úprav"
+
+#: src/parse_args.c:430
+msgid "the `-U' option may only be used with the `-l' option"
+msgstr "voľba „-U“ môže byť použitá iba s voľbou „-l“"
+
+#: src/parse_args.c:434
+msgid "the `-A' and `-S' options may not be used together"
+msgstr "voľby „-A“ a „-S“ nemôžu byť použité zároveň"
+
+#: src/parse_args.c:504
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit nie je podporovaný na tejto platforme"
+
+#: src/parse_args.c:577
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Môže byť určená iba jedna z volieb -e, -h, -i, -K, -l, -s, -v alebo -V"
+
+#: src/parse_args.c:591
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - upravuje súbory ako iný používateľ\n"
+"\n"
+
+#: src/parse_args.c:593
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - vykonáva príkaz ako iný používateľ\n"
+"\n"
+
+#: src/parse_args.c:598
+#, c-format
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Voľby:\n"
+
+#: src/parse_args.c:600
+msgid "use a helper program for password prompting"
+msgstr "použije pomocný program na pýtanie hesla "
+
+#: src/parse_args.c:603
+msgid "use specified BSD authentication type"
+msgstr ""
+
+#: src/parse_args.c:606
+msgid "run command in the background"
+msgstr "spustí príkaz na pozadí"
+
+#: src/parse_args.c:608
+msgid "close all file descriptors >= num"
+msgstr "zavrie všetky popisovače súborov >= číslo"
+
+#: src/parse_args.c:611
+msgid "run command with the specified BSD login class"
+msgstr "spustí príkaz s určenou triedou prihlásenia BSD"
+
+#: src/parse_args.c:614
+msgid "preserve user environment when running command"
+msgstr "zachová rozhranie používateľa, keď sa spúšťa príkaz"
+
+#: src/parse_args.c:616
+msgid "edit files instead of running a command"
+msgstr "upraví súbory namiesto spustenia príkazu"
+
+#: src/parse_args.c:618
+msgid "run command as the specified group name or ID"
+msgstr "spustí príkaz ako určený názov skupiny alebo ID"
+
+#: src/parse_args.c:620
+msgid "set HOME variable to target user's home dir"
+msgstr "nastaví premennú HOME do domovského adresára cieľového používateľa"
+
+#: src/parse_args.c:622
+msgid "display help message and exit"
+msgstr "zobrazí správu pomocníka a skončí"
+
+#: src/parse_args.c:624
+msgid "run command on host (if supported by plugin)"
+msgstr "spustí príkaz na hostiteľovi (ak je podporované zásuvným modulom)"
+
+#: src/parse_args.c:626
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "spustí príkazový riadok prihlásenia, príkaz môže byť tiež určený"
+
+#: src/parse_args.c:628
+msgid "remove timestamp file completely"
+msgstr "úplne odstráni súbor časovej značky"
+
+#: src/parse_args.c:630
+msgid "invalidate timestamp file"
+msgstr "urobí súbor časovej značky neplatným"
+
+#: src/parse_args.c:632
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "vypíše právomoci používateľa, alebo skontroluje určený príkaz; použite dvakrát pre dlhší formát"
+
+#: src/parse_args.c:634
+msgid "non-interactive mode, no prompts are used"
+msgstr "neinteraktívny režim, nebudú použité žiadne výzvy"
+
+#: src/parse_args.c:636
+msgid "preserve group vector instead of setting to target's"
+msgstr ""
+
+#: src/parse_args.c:638
+msgid "use the specified password prompt"
+msgstr "použije určenú výzvu na heslo"
+
+#: src/parse_args.c:641
+msgid "create SELinux security context with specified role"
+msgstr "vytvorí bezpečnostný kontext systému SELinux s určenou rolou"
+
+#: src/parse_args.c:644
+msgid "read password from standard input"
+msgstr "bude čítať heslo zo štandardného vstupu"
+
+#: src/parse_args.c:646
+msgid "run shell as the target user; a command may also be specified"
+msgstr ""
+
+#: src/parse_args.c:649
+msgid "create SELinux security context with specified type"
+msgstr "vytvorí bezpečnostný kontext systému SELinux s určeným typom"
+
+#: src/parse_args.c:652
+msgid "in list mode, display privileges for user"
+msgstr "v režime výpisu, zobrazí právomoci používateľa"
+
+#: src/parse_args.c:654
+msgid "run command (or edit file) as specified user name or ID"
+msgstr ""
+
+#: src/parse_args.c:656
+msgid "display version information and exit"
+msgstr "zobrazí informácie o verzii a skončí"
+
+#: src/parse_args.c:658
+msgid "update user's timestamp without running a command"
+msgstr ""
+
+#: src/parse_args.c:660
+msgid "stop processing command line arguments"
+msgstr "zastaví spracovávanie parametrov príkazového riadku"
+
+#: src/selinux.c:78
+msgid "unable to open audit system"
+msgstr "nie je možné otvoriť systém auditu"
+
+#: src/selinux.c:88
+msgid "unable to send audit message"
+msgstr "nie je možné odoslať správu auditu"
+
+#: src/selinux.c:116
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "nie je možné vykonať funkciu fgetfilecon na %s"
+
+#: src/selinux.c:121
+#, c-format
+msgid "%s changed labels"
+msgstr ""
+
+#: src/selinux.c:126
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "nie je možné obnoviť kontext pre %s"
+
+#: src/selinux.c:166
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "nie je možné otvoriť %s, rozhranie tty nebude mať zmenenú menovku"
+
+#: src/selinux.c:175
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "nie je možné získať aktuálny kontext rozhrania tty, rozhranie tty nebude mať zmenenú menovku"
+
+#: src/selinux.c:182
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "nie je možné získať nový kontext tty, rozhranie tty nebude mať zmenenú menovku"
+
+#: src/selinux.c:189
+msgid "unable to set new tty context"
+msgstr "nie je možné nastaviť nový kontext rozhrania tty"
+
+#: src/selinux.c:255
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "musíte určiť typ roly pre %s"
+
+#: src/selinux.c:261
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "nie je možné získať predvolený typ roly %s"
+
+#: src/selinux.c:279
+#, c-format
+msgid "failed to set new role %s"
+msgstr "zlyhalo nastavenie novej roly %s"
+
+#: src/selinux.c:283
+#, c-format
+msgid "failed to set new type %s"
+msgstr "zlyhalo nastavenie nového typu %s"
+
+#: src/selinux.c:295
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s nie je platný kontext"
+
+#: src/selinux.c:330
+msgid "failed to get old_context"
+msgstr "zlyhalo získanie old_context"
+
+#: src/selinux.c:336
+msgid "unable to determine enforcing mode."
+msgstr ""
+
+#: src/selinux.c:353
+#, c-format
+msgid "unable to set tty context to %s"
+msgstr "nie je možné nastaviť kontext rozhrania tty na %s"
+
+#: src/selinux.c:392
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "nie je možné nastaviť kontext exec na %s"
+
+#: src/selinux.c:399
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "nie je možné nastaviť kontext tvorby kľúča na %s"
+
+#: src/sesh.c:77
+msgid "requires at least one argument"
+msgstr "vyžaduje aspoň jeden parameter"
+
+#: src/sesh.c:106
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "neplatné číslo popisovača súboru: %s"
+
+#: src/sesh.c:120
+#, c-format
+msgid "unable to run %s as a login shell"
+msgstr "nie je možné spustiť %s ako terminál prihlásenia"
+
+#: src/sesh.c:125 src/sudo.c:1274
+#, c-format
+msgid "unable to execute %s"
+msgstr "nie je možné vykonať %s"
+
+#: src/signal.c:68
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr ""
+
+#: src/solaris.c:76
+msgid "resource control limit has been reached"
+msgstr "bol dosiahnutý limit ovládania prostriedkov"
+
+#: src/solaris.c:79
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "používateľ „%s“ nie je členom projektu „%s“"
+
+#: src/solaris.c:83
+msgid "the invoking task is final"
+msgstr "vyvolávajúca úloha je konečná"
+
+#: src/solaris.c:86
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "nepodarilo sa vstúpiť do projektu „%s“"
+
+#: src/solaris.c:91
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr ""
+
+#: src/solaris.c:95
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr ""
+
+#: src/solaris.c:99
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr ""
+
+#: src/solaris.c:105
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "funkcia setproject zlyhala pre projekt „%s“"
+
+#: src/solaris.c:107
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "upozornenie, zlyhalo priradenie ovládania prostriedkov pre projekt „%s“"
+
+#: src/sudo.c:212
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Verzia programu sudo %s\n"
+
+#: src/sudo.c:214
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Voľby konfigurácie: %s\n"
+
+#: src/sudo.c:222
+msgid "fatal error, unable to load plugins"
+msgstr "závažná chyba, nie je možné načítať zásuvné moduly"
+
+#: src/sudo.c:230
+msgid "unable to initialize policy plugin"
+msgstr "nie je možné inicializovať zásuvný modul politiky"
+
+#: src/sudo.c:276
+msgid "plugin did not return a command to execute"
+msgstr ""
+
+#: src/sudo.c:292
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "chyba pri inicializácii vstupno-výstupného zásuvného modulu %s"
+
+#: src/sudo.c:318
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "neočakávaný režim sudo 0x%x"
+
+#: src/sudo.c:461
+msgid "unable to get group vector"
+msgstr "nie je možné získať vektor skupiny"
+
+#: src/sudo.c:522
+#, c-format
+msgid "unknown uid %u: who are you?"
+msgstr "neznámy identifikátor uid %u: kto ste?"
+
+#: src/sudo.c:859
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s musí byť vlastnený identifikátorom uid %d a musí mať nastavený bit setuid"
+
+#: src/sudo.c:862
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "efektívny identifikátor uid nie je %d, je %s na systéme súborov s nastavenou voľbou „nosuid“, alebo na systéme súborov NFS bez právomocí administrátora?"
+
+#: src/sudo.c:868
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr ""
+
+#: src/sudo.c:999
+#, c-format
+msgid "unknown login class %s"
+msgstr "neznáma trieda prihlásenia %s"
+
+#: src/sudo.c:1012
+msgid "unable to set user context"
+msgstr "nie je možné nastaviť kontext používateľa"
+
+#: src/sudo.c:1026
+msgid "unable to set supplementary group IDs"
+msgstr ""
+
+#: src/sudo.c:1033
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr ""
+
+#: src/sudo.c:1039
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr ""
+
+#: src/sudo.c:1046
+msgid "unable to set process priority"
+msgstr "nie je možné nastaviť prioritu procesu"
+
+#: src/sudo.c:1054
+#, c-format
+msgid "unable to change root to %s"
+msgstr "nie je možné zmeniť administrátora na %s"
+
+#: src/sudo.c:1067 src/sudo.c:1073 src/sudo.c:1080
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr ""
+
+#: src/sudo.c:1098
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "nie je možné zmeniť adresár na %s"
+
+#: src/sudo.c:1156
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "neočakávaná podmienka prerušenia potomka: %d"
+
+#: src/sudo.c:1302
+#, c-format
+msgid "policy plugin %s is missing the `check_policy' method"
+msgstr "zásuvnému modulu politiky %s chýba spôsob „check_policy“"
+
+#: src/sudo.c:1320
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "zásuvný modul politiky %s nepodporuje výpis právomocí"
+
+#: src/sudo.c:1337
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr ""
+
+#: src/sudo.c:1352
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr ""
+
+#: src/sudo_edit.c:181
+msgid "unable to restore current working directory"
+msgstr "nie je možné obnoviť aktuálny pracovný adresár"
+
+#: src/sudo_edit.c:526 src/sudo_edit.c:630
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: nie je regulárny súbor"
+
+#: src/sudo_edit.c:533
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: upravovanie symbolických odkazov nie je dovolené"
+
+#: src/sudo_edit.c:536
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: upravovanie súborov v zapisovateľnom adresári nie je dovolené"
+
+#: src/sudo_edit.c:567 src/sudo_edit.c:669
+#, c-format
+msgid "%s: short write"
+msgstr "%s: krátky zápis"
+
+#: src/sudo_edit.c:631
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s zostal nezmenený"
+
+#: src/sudo_edit.c:644 src/sudo_edit.c:830
+#, c-format
+msgid "%s unchanged"
+msgstr "%s nezmenený"
+
+#: src/sudo_edit.c:658 src/sudo_edit.c:680
+#, c-format
+msgid "unable to write to %s"
+msgstr "nie je možné zapísať do %s"
+
+#: src/sudo_edit.c:659 src/sudo_edit.c:678 src/sudo_edit.c:681
+#: src/sudo_edit.c:855 src/sudo_edit.c:859
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "obsah upravovanej relácie zostal v %s"
+
+#: src/sudo_edit.c:677
+msgid "unable to read temporary file"
+msgstr "nie je možné čítať dočasný súbor"
+
+#: src/sudo_edit.c:760
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: vnútorná chyba: nepárne čísla ciest"
+
+#: src/sudo_edit.c:762
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: nie je možné vytvoriť dočasné súbory"
+
+#: src/sudo_edit.c:764 src/sudo_edit.c:862
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: neznáma chyba %d"
+
+#: src/sudo_edit.c:854
+msgid "unable to copy temporary files back to their original location"
+msgstr "nie je možné skopírovať dočasné súbory späť do ich pôvodného umiestnenia"
+
+#: src/sudo_edit.c:858
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "nie je možné skopírovať niektoré z dočasných súborov späť do ich pôvodného umiestnenia"
+
+#: src/sudo_edit.c:901
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "nie je možné zmeniť identifikátor uid na administrátora (%u)"
+
+#: src/sudo_edit.c:918
+msgid "plugin error: missing file list for sudoedit"
+msgstr "chyba zásuvného modulu: chýba zoznam súborov pre sudoedit"
+
+#: src/sudo_edit.c:959 src/sudo_edit.c:972
+msgid "unable to read the clock"
+msgstr "nie je možné čítať hodiny"
+
+#: src/tgetpass.c:107
+msgid "no tty present and no askpass program specified"
+msgstr ""
+
+#: src/tgetpass.c:116
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr ""
+
+#: src/tgetpass.c:276
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "nie je možné nastaviť identifikátor gid na %u"
+
+#: src/tgetpass.c:280
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "nie je možné nastaviť identifikátor uid na %u"
+
+#: src/tgetpass.c:285
+#, c-format
+msgid "unable to run %s"
+msgstr "nie je možné spustiť %s"
+
+#: src/utmp.c:266
+msgid "unable to save stdin"
+msgstr "nie je možné uložiť štandardný vstup stdin"
+
+#: src/utmp.c:268
+msgid "unable to dup2 stdin"
+msgstr ""
+
+#: src/utmp.c:271
+msgid "unable to restore stdin"
+msgstr "nie je možné obnoviť štandardný vstup stdin"
diff --git a/po/sl.mo b/po/sl.mo
new file mode 100644
index 0000000..22725f0
--- /dev/null
+++ b/po/sl.mo
Binary files differ
diff --git a/po/sl.po b/po/sl.po
new file mode 100644
index 0000000..ef8df67
--- /dev/null
+++ b/po/sl.po
@@ -0,0 +1,810 @@
+# Slovenian translation of sudo.
+# This file is put in the public domain.
+# This file is distributed under the same license as the sudo package.
+#
+# Damir Jerovšek <damir.jerovsek@gmail.com>, 2012.
+# Klemen Košir <klemen.kosir@gmx.com>, 2012 - 2013.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.8.7b1\n"
+"Report-Msgid-Bugs-To: http://www.sudo.ws/bugs\n"
+"POT-Creation-Date: 2013-04-02 10:40-0400\n"
+"PO-Revision-Date: 2013-04-06 09:33+0100\n"
+"Last-Translator: Klemen Košir <klemen913@gmail.com>\n"
+"Language-Team: Slovenian <translation-team-sl@lists.sourceforge.net>\n"
+"Language: sl\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.5.5\n"
+
+#: common/aix.c:150
+#, c-format
+msgid "unable to open userdb"
+msgstr "ni mogoče odpreti userdb"
+
+#: common/aix.c:153
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "ni mogoče preklopiti na vpisnik \"%s\" za %s"
+
+#: common/aix.c:170
+#, c-format
+msgid "unable to restore registry"
+msgstr "ni mogoče obnoviti vpisnika"
+
+#: common/alloc.c:82
+msgid "internal error, tried to emalloc(0)"
+msgstr "notranja napaka, poskus uporabe emalloc(0)"
+
+#: common/alloc.c:99
+msgid "internal error, tried to emalloc2(0)"
+msgstr "notranja napaka, poskus uporabe emalloc2(0)"
+
+#: common/alloc.c:101 common/alloc.c:123 common/alloc.c:163 common/alloc.c:187
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "notranja napaka, prekoračitev funkcije %s"
+
+#: common/alloc.c:120
+msgid "internal error, tried to ecalloc(0)"
+msgstr "notranja napaka med izvajanjem funkcije ecalloc(0)"
+
+#: common/alloc.c:142
+msgid "internal error, tried to erealloc(0)"
+msgstr "notranja napaka, poskus uporabe erealloc(0)"
+
+#: common/alloc.c:161
+msgid "internal error, tried to erealloc3(0)"
+msgstr "notranja napaka, poskus uporabe erealloc3(0)"
+
+#: common/alloc.c:185
+msgid "internal error, tried to erecalloc(0)"
+msgstr "notranja napaka, poskus uporabe erealloc(0)"
+
+#: common/error.c:154
+#, c-format
+msgid "%s: %s: %s\n"
+msgstr "%s: %s: %s\n"
+
+#: common/error.c:157 common/error.c:161
+#, c-format
+msgid "%s: %s\n"
+msgstr "%s: %s\n"
+
+#: common/sudo_conf.c:172
+#, c-format
+msgid "unsupported group source `%s' in %s, line %d"
+msgstr "nepodprt vir skupine %s v datoteki %s v %d. vrstici"
+
+#: common/sudo_conf.c:186
+#, c-format
+msgid "invalid max groups `%s' in %s, line %d"
+msgstr "neveljavna največja skupina %s v datoteki %s v %d. vrstici"
+
+#: common/sudo_conf.c:382
+#, c-format
+msgid "unable to stat %s"
+msgstr "stanja datoteke %s ni mogoče izpisati"
+
+#: common/sudo_conf.c:385
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s ni običajna datoteka"
+
+#: common/sudo_conf.c:388
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s je v lasti uporabnika z ID-jem %u, moral bi biti %u"
+
+#: common/sudo_conf.c:392
+#, c-format
+msgid "%s is world writable"
+msgstr "v datoteko %s lahko zapisujejo vsi uporabniki"
+
+#: common/sudo_conf.c:395
+#, c-format
+msgid "%s is group writable"
+msgstr "%s"
+
+#: common/sudo_conf.c:405 src/selinux.c:196 src/selinux.c:209 src/sudo.c:328
+#, c-format
+msgid "unable to open %s"
+msgstr "ni mogoče odpreti %s"
+
+#: compat/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Neznan signal"
+
+#: src/exec.c:127 src/exec_pty.c:685
+#, c-format
+msgid "policy plugin failed session initialization"
+msgstr "vstavek za pravilnik ni mogel zagnati seje"
+
+#: src/exec.c:132 src/exec_pty.c:701 src/exec_pty.c:1066 src/tgetpass.c:220
+#, c-format
+msgid "unable to fork"
+msgstr "ni mogoče razvejiti"
+
+#: src/exec.c:259
+#, c-format
+msgid "unable to create sockets"
+msgstr "ni mogoče ustvariti vtičev"
+
+#: src/exec.c:347 src/exec_pty.c:1130 src/exec_pty.c:1268
+#, c-format
+msgid "select failed"
+msgstr "izbira je spodletela"
+
+#: src/exec.c:449
+#, c-format
+msgid "unable to restore tty label"
+msgstr "ni mogoče obnoviti oznake tty"
+
+#: src/exec_common.c:70
+#, c-format
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "ni mogoče odstraniti PRIV_PROC_EXEC iz PRIV_LIMIT"
+
+#: src/exec_pty.c:183
+#, c-format
+msgid "unable to allocate pty"
+msgstr "ni mogoče dodeliti pty"
+
+#: src/exec_pty.c:623 src/exec_pty.c:632 src/exec_pty.c:640 src/exec_pty.c:986
+#: src/exec_pty.c:1063 src/signal.c:126 src/tgetpass.c:217
+#, c-format
+msgid "unable to create pipe"
+msgstr "ni mogoče ustvariti cevi"
+
+#: src/exec_pty.c:676
+#, c-format
+msgid "unable to set terminal to raw mode"
+msgstr "ni mogoče postaviti terminala v surov način"
+
+#: src/exec_pty.c:1042
+#, c-format
+msgid "unable to set controlling tty"
+msgstr "ni mogoče nastaviti nadzora tty"
+
+#: src/exec_pty.c:1139
+#, c-format
+msgid "error reading from signal pipe"
+msgstr "napaka med branjem iz cevi signala"
+
+#: src/exec_pty.c:1160
+#, c-format
+msgid "error reading from pipe"
+msgstr "napaka med branjem iz cevovoda"
+
+#: src/exec_pty.c:1176
+#, c-format
+msgid "error reading from socketpair"
+msgstr "napaka med branjem iz para vtičev"
+
+#: src/exec_pty.c:1180
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "nepričakovana vrsta odgovora na ozadnem kanalu: %d"
+
+#: src/load_plugins.c:70 src/load_plugins.c:79 src/load_plugins.c:132
+#: src/load_plugins.c:138 src/load_plugins.c:144 src/load_plugins.c:185
+#: src/load_plugins.c:192 src/load_plugins.c:199 src/load_plugins.c:205
+#, c-format
+msgid "error in %s, line %d while loading plugin `%s'"
+msgstr "v datoteki %s (vrstica %d) je prišlo do napake med nalaganjem vstavka %s"
+
+#: src/load_plugins.c:72
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: src/load_plugins.c:81
+#, c-format
+msgid "%s%s: %s"
+msgstr "%s%s: %s"
+
+#: src/load_plugins.c:140
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s mora biti v lasti ID-ja uporabnika %d"
+
+#: src/load_plugins.c:146
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "%s mora biti zapisljiv samo za lastnika"
+
+#: src/load_plugins.c:187
+#, c-format
+msgid "unable to dlopen %s: %s"
+msgstr "ni mogoče uporabiti dlopen %s: %s"
+
+#: src/load_plugins.c:194
+#, c-format
+msgid "unable to find symbol `%s' in %s"
+msgstr "ni mogoče najti simbola '%s' v %s"
+
+#: src/load_plugins.c:201
+#, c-format
+msgid "unknown policy type %d found in %s"
+msgstr "neznana vrsta pravilnika %d v %s"
+
+#: src/load_plugins.c:207
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "nezdružljiva različica vstavka %d (pričakovana %d) v %s"
+
+#: src/load_plugins.c:216
+#, c-format
+msgid "ignoring policy plugin `%s' in %s, line %d"
+msgstr "vstavek pravilnika %s v datoteki %s v %d. vrstici bo prezrt"
+
+#: src/load_plugins.c:218
+#, c-format
+msgid "only a single policy plugin may be specified"
+msgstr "naložen je lahko le en vstavek pravilnika"
+
+#: src/load_plugins.c:221
+#, c-format
+msgid "ignoring duplicate policy plugin `%s' in %s, line %d"
+msgstr "podvojeni vstavek pravilnika %s v datoteki %s v %d. vrstici bo prezrt"
+
+#: src/load_plugins.c:236
+#, c-format
+msgid "ignoring duplicate I/O plugin `%s' in %s, line %d"
+msgstr "podvojeni vstavek I/O %s v datoteki %s v %d. vrstici bo prezrt"
+
+#: src/load_plugins.c:313
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "vstavek pravilnika %s ne vključuje načina check_policy"
+
+#: src/net_ifs.c:156 src/net_ifs.c:165 src/net_ifs.c:177 src/net_ifs.c:186
+#: src/net_ifs.c:297 src/net_ifs.c:321
+#, c-format
+msgid "load_interfaces: overflow detected"
+msgstr "load_interfaces: zaznana je bila prekoračitev"
+
+#: src/net_ifs.c:226
+#, c-format
+msgid "unable to open socket"
+msgstr "ni mogoče odpreti vtiča"
+
+#: src/parse_args.c:197
+#, c-format
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "argument k -C mora biti številka, večja kot ali enaka 3"
+
+#: src/parse_args.c:286
+#, c-format
+msgid "unknown user: %s"
+msgstr "neznan uporabnik: %s"
+
+#: src/parse_args.c:345
+#, c-format
+msgid "you may not specify both the `-i' and `-s' options"
+msgstr "možnosti `-i' in `-s' ne smeta biti navedeni hkrati"
+
+#: src/parse_args.c:349
+#, c-format
+msgid "you may not specify both the `-i' and `-E' options"
+msgstr "možnosti `-i' in `-E' ne smeta biti navedeni hkrati"
+
+#: src/parse_args.c:359
+#, c-format
+msgid "the `-E' option is not valid in edit mode"
+msgstr "možnost `-E' ni veljavna v načinu urejanja"
+
+#: src/parse_args.c:361
+#, c-format
+msgid "you may not specify environment variables in edit mode"
+msgstr "v načinu urejanja se ne sme podati spremenljivk okolja"
+
+#: src/parse_args.c:369
+#, c-format
+msgid "the `-U' option may only be used with the `-l' option"
+msgstr "možnost `-U' se lahko uporabi samo z možnostjo `-l'"
+
+#: src/parse_args.c:373
+#, c-format
+msgid "the `-A' and `-S' options may not be used together"
+msgstr "možnosti `-A' in `-S' se ne smeta uporabljati hkrati"
+
+#: src/parse_args.c:456
+#, c-format
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit ni podprt v tem okolju"
+
+#: src/parse_args.c:529
+#, c-format
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Od -e, -h, -i, -K, -l, -s, -v ali -V je lahko navedena samo ena možnost"
+
+#: src/parse_args.c:543
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - urejaj datoteke kot drug uporabnik\n"
+"\n"
+
+#: src/parse_args.c:545
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - izvedi ukaz kot drug uporabnik\n"
+"\n"
+
+#: src/parse_args.c:550
+#, c-format
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Možnosti:\n"
+
+#: src/parse_args.c:552
+msgid "use helper program for password prompting\n"
+msgstr "uporabi program pomagalnik za pozive za vnos gesla\n"
+
+#: src/parse_args.c:555
+msgid "use specified BSD authentication type\n"
+msgstr "uporabi navedeno vrsto urejanja BSD\n"
+
+#: src/parse_args.c:558
+msgid "run command in the background\n"
+msgstr "zaženi ukaz v ozadju\n"
+
+#: src/parse_args.c:560
+msgid "close all file descriptors >= fd\n"
+msgstr "zapri vse opisnike datotek >= fd\n"
+
+#: src/parse_args.c:563
+msgid "run command with specified login class\n"
+msgstr "zaženi ukaz z navedenim prijavnim razredom\n"
+
+#: src/parse_args.c:566
+msgid "preserve user environment when executing command\n"
+msgstr "ohrani okolje uporabnika, kadar se izvajajo ukazi\n"
+
+#: src/parse_args.c:568
+msgid "edit files instead of running a command\n"
+msgstr "namesto izvedbe ukaza uredi datoteke\n"
+
+#: src/parse_args.c:570
+msgid "execute command as the specified group\n"
+msgstr "izvedi ukaz kot navedena skupina\n"
+
+#: src/parse_args.c:572
+msgid "set HOME variable to target user's home dir.\n"
+msgstr "nastavi spremenljivko HOME kot cilj v domači mapi uporabnika\n"
+
+#: src/parse_args.c:574
+msgid "display help message and exit\n"
+msgstr "prikaži sporočilo pomoči in končaj\n"
+
+#: src/parse_args.c:576
+msgid "run a login shell as target user\n"
+msgstr "zaženi lupino prijave kot ciljni uporabnik\n"
+
+#: src/parse_args.c:578
+msgid "remove timestamp file completely\n"
+msgstr "popolnoma odstrani datoteko s časovnimi žigi\n"
+
+#: src/parse_args.c:580
+msgid "invalidate timestamp file\n"
+msgstr "razveljavi veljavnost datoteke s časovnimi žigi\n"
+
+#: src/parse_args.c:582
+msgid "list user's available commands\n"
+msgstr "prikaži razpoložljive ukaze uporabnika\n"
+
+#: src/parse_args.c:584
+msgid "non-interactive mode, will not prompt user\n"
+msgstr "nevzajemni način, ne bo poziva uporabnika\n"
+
+#: src/parse_args.c:586
+msgid "preserve group vector instead of setting to target's\n"
+msgstr "ohrani vektor skupine namesto nastavitve tarči\n"
+
+#: src/parse_args.c:588
+msgid "use specified password prompt\n"
+msgstr "uporabi določen poziv za vnos gesla\n"
+
+#: src/parse_args.c:591 src/parse_args.c:599
+msgid "create SELinux security context with specified role\n"
+msgstr "ustvari varnostno vsebino SELinux z določeno vlogo\n"
+
+#: src/parse_args.c:594
+msgid "read password from standard input\n"
+msgstr "preberi geslo s standardnega vnosa\n"
+
+#: src/parse_args.c:596
+msgid "run a shell as target user\n"
+msgstr "zaženi lupino kot ciljni uporabnik\n"
+
+#: src/parse_args.c:602
+msgid "when listing, list specified user's privileges\n"
+msgstr "med naštevanjem prikaži določena dovoljenja uporabnika\n"
+
+#: src/parse_args.c:604
+msgid "run command (or edit file) as specified user\n"
+msgstr "zaženi ukaz (ali uredi datoteko) kot določen uporabnik\n"
+
+#: src/parse_args.c:606
+msgid "display version information and exit\n"
+msgstr "prikaži podrobnosti različice in končaj\n"
+
+#: src/parse_args.c:608
+msgid "update user's timestamp without running a command\n"
+msgstr "posodobi časovni žig uporabnika brez izvajanja ukaza\n"
+
+#: src/parse_args.c:610
+msgid "stop processing command line arguments\n"
+msgstr "zaustavi obdelovanje argumentov ukazne vrstice\n"
+
+#: src/selinux.c:77
+#, c-format
+msgid "unable to open audit system"
+msgstr "ni mogoče odpreti nadzornega sistema"
+
+#: src/selinux.c:85
+#, c-format
+msgid "unable to send audit message"
+msgstr "ni mogoče poslati nadzornega sporočila"
+
+#: src/selinux.c:113
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "ni mogoče uporabiti fgetfilecon %s"
+
+#: src/selinux.c:118
+#, c-format
+msgid "%s changed labels"
+msgstr "%s spremenjenih oznak"
+
+#: src/selinux.c:123
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "ni mogoče obnoviti vsebine za %s"
+
+#: src/selinux.c:163
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "ni mogoče odpreti %s, brez ponovnega označevanja tty"
+
+#: src/selinux.c:172
+#, c-format
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "ni mogoče pridobiti trenutne vsebine tty, brez ponovnega označevanja tty"
+
+#: src/selinux.c:179
+#, c-format
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "ni mogoče pridobiti nove vsebine tty, brez ponovnega označevanja tty"
+
+#: src/selinux.c:186
+#, c-format
+msgid "unable to set new tty context"
+msgstr "ni mogoče nastaviti nove vsebine tty"
+
+#: src/selinux.c:252
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "podati morate vlogo za vrsto %s"
+
+#: src/selinux.c:258
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "ni mogoče pridobiti privzete vrste za vlogo %s"
+
+#: src/selinux.c:276
+#, c-format
+msgid "failed to set new role %s"
+msgstr "nastavitev nove vloge %s ni uspela"
+
+#: src/selinux.c:280
+#, c-format
+msgid "failed to set new type %s"
+msgstr "nastavitev nove vrste %s ni uspela"
+
+#: src/selinux.c:289
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s ni veljavna vsebina"
+
+#: src/selinux.c:324
+#, c-format
+msgid "failed to get old_context"
+msgstr "pridobitev stare_vsebine je spodletela"
+
+#: src/selinux.c:330
+#, c-format
+msgid "unable to determine enforcing mode."
+msgstr "ni mogoče določiti načina vsiljenja"
+
+#: src/selinux.c:342
+#, c-format
+msgid "unable to setup tty context for %s"
+msgstr "ni mogoče nastaviti vsebine tty za %s"
+
+#: src/selinux.c:381
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "ni mogoče nastavite izvedene vsebine k %s"
+
+#: src/selinux.c:388
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "ni mogoče nastaviti vsebine ustvarjenja ključa k %s"
+
+#: src/sesh.c:57
+#, c-format
+msgid "requires at least one argument"
+msgstr "zahteva vsaj en argument"
+
+#: src/sesh.c:78 src/sudo.c:1126
+#, c-format
+msgid "unable to execute %s"
+msgstr "ni mogoče izvršiti %s"
+
+#: src/solaris.c:88
+#, c-format
+msgid "resource control limit has been reached"
+msgstr "meja omejitve virov je bila dosežena"
+
+#: src/solaris.c:91
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "uporabnik \"%s\" ni član projekta \"%s\""
+
+#: src/solaris.c:95
+#, c-format
+msgid "the invoking task is final"
+msgstr "priklicana naloga je končna"
+
+#: src/solaris.c:98
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "ni mogoče pridružiti projekta \"%s\""
+
+#: src/solaris.c:103
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "nobene zaloge virov, ki sprejemajo privzete vezi, ne obstajajo za projekt \"% s\""
+
+#: src/solaris.c:107
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "določen vir zalog ne obstaja za projekt \"%s\""
+
+#: src/solaris.c:111
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "ni mogoče vezati na privzet vir zalog za projekt \"%s\""
+
+#: src/solaris.c:117
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "setproject je spodletel za projekt \"%s\""
+
+#: src/solaris.c:119
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "opozorilo, naloga nadzora virov je spodletela za projekt \"%s\""
+
+#: src/sudo.c:196
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo različica %s\n"
+
+#: src/sudo.c:198
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Nastavitev možnosti: %s\n"
+
+#: src/sudo.c:203
+#, c-format
+msgid "fatal error, unable to load plugins"
+msgstr "usodna napaka, ni mogoče naložiti vstavka"
+
+#: src/sudo.c:211
+#, c-format
+msgid "unable to initialize policy plugin"
+msgstr "ni mogoče začenjati vstavka pravilnika"
+
+#: src/sudo.c:268
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "napaka med začenjanjem I/O vstavka %s"
+
+#: src/sudo.c:293
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "nepričakovan način sudo 0x%x"
+
+#: src/sudo.c:413
+#, c-format
+msgid "unable to get group vector"
+msgstr "ni mogoče pridobiti vektorja skupine"
+
+#: src/sudo.c:465
+#, c-format
+msgid "unknown uid %u: who are you?"
+msgstr "neznan ID uporabnika %u: kdo ste?"
+
+#: src/sudo.c:802
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s si mora lastiti uporabnik z ID-jem %d and mora imeti nastavljen bit setuid"
+
+#: src/sudo.c:805
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "trenutni ID uporabnika ni %d. Ali je %s na datotečnem sistemu z nastavljeno možnostjo \"nosuid\" ali datotečnem sistemu NFS brez dovoljenj skrbnika?"
+
+#: src/sudo.c:811
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "trenutni uid ni %d. Ali je sudo pravilno nameščen?"
+
+#: src/sudo.c:915
+#, c-format
+msgid "unknown login class %s"
+msgstr "neznan razred prijave %s"
+
+#: src/sudo.c:929 src/sudo.c:932
+#, c-format
+msgid "unable to set user context"
+msgstr "ni mogoče nastaviti vsebine uporabnika"
+
+#: src/sudo.c:944
+#, c-format
+msgid "unable to set supplementary group IDs"
+msgstr "ni mogoče nastaviti dopolnilnih ID-jev skupin"
+
+#: src/sudo.c:951
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "ni mogoče nastaviti učinkovitega ID-ja skupine, da se zažene kot ID skupine %u"
+
+#: src/sudo.c:957
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "ni mogoče nastaviti ID-ja skupine, da se zažene kot ID skupine %u"
+
+#: src/sudo.c:964
+#, c-format
+msgid "unable to set process priority"
+msgstr "ni mogoče nastaviti prednosti opravil"
+
+#: src/sudo.c:972
+#, c-format
+msgid "unable to change root to %s"
+msgstr "ni mogoče spremeniti skrbnika v %s"
+
+#: src/sudo.c:979 src/sudo.c:985 src/sudo.c:991
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "ni mogoče spremeniti ID uporabnika zaženi kot (%u, %u)"
+
+#: src/sudo.c:1005
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "ni mogoče spremeniti mape v %s"
+
+#: src/sudo.c:1089
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "nepričakovan pogoj uničenja podrejenega opravila: %d"
+
+#: src/sudo.c:1146
+#, c-format
+msgid "policy plugin %s is missing the `check_policy' method"
+msgstr "vstavek pravilnika %s ne vključuje načina check_policy"
+
+#: src/sudo.c:1159
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "vstavek pravilnika %s ne podpira navajanja dovoljenj"
+
+#: src/sudo.c:1171
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "vstavek pravilnika %s ne podpira možnosti -v"
+
+#: src/sudo.c:1183
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "vstavek pravilnika %s ne podpira možnosti -k/-K"
+
+#: src/sudo_edit.c:110
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "ni mogoče spremeniti ID-ja uporabnika v skrbnika (%u)"
+
+#: src/sudo_edit.c:142
+#, c-format
+msgid "plugin error: missing file list for sudoedit"
+msgstr "napaka vstavka: manjka seznam datotek za sudoedit"
+
+#: src/sudo_edit.c:170 src/sudo_edit.c:270
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: ni običajna datoteka"
+
+#: src/sudo_edit.c:204 src/sudo_edit.c:306
+#, c-format
+msgid "%s: short write"
+msgstr "%s: kratko pisanje"
+
+#: src/sudo_edit.c:271
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s je ostalo nespremenjeno"
+
+#: src/sudo_edit.c:284
+#, c-format
+msgid "%s unchanged"
+msgstr "%s nespremenjeno"
+
+#: src/sudo_edit.c:296 src/sudo_edit.c:317
+#, c-format
+msgid "unable to write to %s"
+msgstr "ni mogoče pisati v %s"
+
+#: src/sudo_edit.c:297 src/sudo_edit.c:315 src/sudo_edit.c:318
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "vsebina seje urejanja je ostala v %s"
+
+#: src/sudo_edit.c:314
+#, c-format
+msgid "unable to read temporary file"
+msgstr "ni mogoče brati začasne datoteke"
+
+#: src/tgetpass.c:89
+#, c-format
+msgid "no tty present and no askpass program specified"
+msgstr "prisotnega ni nobenega tty in določen ni noben program askpass"
+
+#: src/tgetpass.c:98
+#, c-format
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "določenega ni nobenega programa askpass, poskusite nastaviti SUDO_ASKPASS"
+
+#: src/tgetpass.c:230
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "ni mogoče nastaviti ID skupine v %u"
+
+#: src/tgetpass.c:234
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "ni mogoče nastaviti ID uporabnika v %u"
+
+#: src/tgetpass.c:239
+#, c-format
+msgid "unable to run %s"
+msgstr "ni mogoče zagnati %s"
+
+#: src/utmp.c:278
+#, c-format
+msgid "unable to save stdin"
+msgstr "ni mogoče shraniti stdin"
+
+#: src/utmp.c:280
+#, c-format
+msgid "unable to dup2 stdin"
+msgstr "ni mogoče uporabiti dup2 za stdin"
+
+#: src/utmp.c:283
+#, c-format
+msgid "unable to restore stdin"
+msgstr "ni mogoče obnoviti stdin"
diff --git a/po/sq.mo b/po/sq.mo
new file mode 100644
index 0000000..7fa2e4c
--- /dev/null
+++ b/po/sq.mo
Binary files differ
diff --git a/po/sq.po b/po/sq.po
new file mode 100644
index 0000000..c83176e
--- /dev/null
+++ b/po/sq.po
@@ -0,0 +1,1179 @@
+# Portable object template file for sudo
+# This file is put in the public domain.
+#
+# Todd C. Miller <Todd.Miller@sudo.ws>, 2011-2018.
+# Agron Selimaj <as9902613@gmail.com>, 2022.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.12b2\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2022-10-09 09:48-0600\n"
+"PO-Revision-Date: 2022-11-01 22:26-0400\n"
+"Last-Translator: Agron Selimaj <as9902613@gmail.com>\n"
+"Language-Team: Albanian <translation-team-sq@lists.sourceforge.net>\n"
+"Language: sq\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Lokalize 22.08.1\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "hapja e userdb e pamundur"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "aktivizimi i regjistrit \"%s\" për %s i pamundur"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "rivendosja e regjistrit e pamundur"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:54 lib/util/json.c:183 lib/util/sudo_conf.c:219
+#: lib/util/sudo_conf.c:305 lib/util/sudo_conf.c:382 lib/util/sudo_conf.c:666
+#: src/conversation.c:80 src/exec_iolog.c:124 src/exec_iolog.c:135
+#: src/exec_iolog.c:212 src/exec_monitor.c:205 src/exec_monitor.c:458
+#: src/exec_monitor.c:464 src/exec_monitor.c:472 src/exec_monitor.c:480
+#: src/exec_monitor.c:487 src/exec_monitor.c:494 src/exec_monitor.c:501
+#: src/exec_monitor.c:508 src/exec_monitor.c:515 src/exec_monitor.c:522
+#: src/exec_monitor.c:529 src/exec_nopty.c:227 src/exec_nopty.c:236
+#: src/exec_nopty.c:243 src/exec_nopty.c:250 src/exec_nopty.c:257
+#: src/exec_nopty.c:264 src/exec_nopty.c:271 src/exec_nopty.c:278
+#: src/exec_nopty.c:285 src/exec_nopty.c:292 src/exec_nopty.c:299
+#: src/exec_nopty.c:306 src/exec_nopty.c:314 src/exec_nopty.c:322
+#: src/exec_nopty.c:732 src/exec_preload.c:341 src/exec_ptrace.c:474
+#: src/exec_ptrace.c:767 src/exec_ptrace.c:982 src/exec_ptrace.c:1094
+#: src/exec_ptrace.c:1269 src/exec_ptrace.c:1611 src/exec_ptrace.c:1638
+#: src/exec_pty.c:506 src/exec_pty.c:687 src/exec_pty.c:873 src/exec_pty.c:882
+#: src/exec_pty.c:889 src/exec_pty.c:896 src/exec_pty.c:903 src/exec_pty.c:910
+#: src/exec_pty.c:917 src/exec_pty.c:924 src/exec_pty.c:931 src/exec_pty.c:938
+#: src/exec_pty.c:945 src/exec_pty.c:953 src/load_plugins.c:157
+#: src/load_plugins.c:182 src/load_plugins.c:218 src/load_plugins.c:451
+#: src/load_plugins.c:457 src/parse_args.c:172 src/parse_args.c:193
+#: src/parse_args.c:267 src/parse_args.c:623 src/parse_args.c:645
+#: src/parse_args.c:670 src/preserve_fds.c:46 src/preserve_fds.c:131
+#: src/selinux.c:89 src/selinux.c:362 src/selinux.c:472 src/selinux.c:489
+#: src/selinux.c:496 src/sesh.c:206 src/sesh.c:240 src/sesh.c:246
+#: src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:639 src/sudo.c:704
+#: src/sudo.c:714 src/sudo.c:741 src/sudo.c:764 src/sudo.c:773 src/sudo.c:782
+#: src/sudo.c:799 src/sudo.c:841 src/sudo.c:851 src/sudo.c:884 src/sudo.c:1112
+#: src/sudo.c:1133 src/sudo.c:1426 src/sudo.c:1595 src/sudo.c:1822
+#: src/sudo.c:2156 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:429
+#: src/sudo_edit.c:438 src/sudo_edit.c:538 src/sudo_edit.c:545
+#: src/sudo_edit.c:673 src/sudo_edit.c:693 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:55
+#: lib/util/json.c:184 lib/util/regex.c:113 lib/util/regex.c:121
+#: lib/util/sudo_conf.c:220 lib/util/sudo_conf.c:305 lib/util/sudo_conf.c:382
+#: lib/util/sudo_conf.c:666 src/conversation.c:81 src/exec_intercept.c:111
+#: src/exec_intercept.c:344 src/exec_intercept.c:504 src/exec_intercept.c:566
+#: src/exec_intercept.c:682 src/exec_intercept.c:806 src/exec_iolog.c:124
+#: src/exec_iolog.c:135 src/exec_iolog.c:212 src/exec_monitor.c:458
+#: src/exec_monitor.c:464 src/exec_monitor.c:472 src/exec_monitor.c:480
+#: src/exec_monitor.c:487 src/exec_monitor.c:494 src/exec_monitor.c:501
+#: src/exec_monitor.c:508 src/exec_monitor.c:515 src/exec_monitor.c:522
+#: src/exec_monitor.c:529 src/exec_nopty.c:227 src/exec_nopty.c:236
+#: src/exec_nopty.c:243 src/exec_nopty.c:250 src/exec_nopty.c:257
+#: src/exec_nopty.c:264 src/exec_nopty.c:271 src/exec_nopty.c:278
+#: src/exec_nopty.c:285 src/exec_nopty.c:292 src/exec_nopty.c:299
+#: src/exec_nopty.c:306 src/exec_nopty.c:314 src/exec_nopty.c:322
+#: src/exec_preload.c:341 src/exec_ptrace.c:474 src/exec_ptrace.c:767
+#: src/exec_ptrace.c:982 src/exec_ptrace.c:1638 src/exec_pty.c:506
+#: src/exec_pty.c:873 src/exec_pty.c:882 src/exec_pty.c:889 src/exec_pty.c:896
+#: src/exec_pty.c:903 src/exec_pty.c:910 src/exec_pty.c:917 src/exec_pty.c:924
+#: src/exec_pty.c:931 src/exec_pty.c:938 src/exec_pty.c:945 src/exec_pty.c:953
+#: src/load_plugins.c:157 src/load_plugins.c:182 src/load_plugins.c:218
+#: src/load_plugins.c:451 src/load_plugins.c:457 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:267 src/parse_args.c:623
+#: src/parse_args.c:645 src/parse_args.c:670 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:230 src/sudo.c:639 src/sudo.c:884 src/sudo.c:1112
+#: src/sudo.c:1133 src/sudo.c:1426 src/sudo.c:1595 src/sudo.c:1822
+#: src/sudo.c:2156 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:429
+#: src/sudo_edit.c:438 src/sudo_edit.c:538 src/sudo_edit.c:545
+#: src/sudo_edit.c:673 src/sudo_edit.c:693 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "rezervimi i kujtesës i pamundur"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "e pamundur të stat-ohet %.*s"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s egzistojnë por nuk është skedarë (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:677
+#: lib/util/sudo_conf.c:689 lib/util/sudo_conf.c:715 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:371 src/sudo_edit.c:494 src/sudo_edit.c:557
+#, c-format
+msgid "unable to open %s"
+msgstr "hapja e %s e pamundur"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "krijimi i skedarit %.*s me mkdir i pamundur"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "hapja e %.*s e pamundur"
+
+#: lib/util/regex.c:103
+msgid "regular expression too large"
+msgstr "shprehja e rregult (regex) shumë e madhe"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Sinjal i panjohur"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "vlerë invalide"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "vlera shumë e madhe"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "vlera shumë e vogël"
+
+#: lib/util/sudo_conf.c:238
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "vlera e shtegut \"%s\" në %s, në rreshtin %u është invalide"
+
+#: lib/util/sudo_conf.c:404 lib/util/sudo_conf.c:420 lib/util/sudo_conf.c:473
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "vlera për %s \"%s\" në %s, në rreshtin %u është invalide"
+
+#: lib/util/sudo_conf.c:441
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr ""
+
+#: lib/util/sudo_conf.c:457
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr ""
+
+#: lib/util/sudo_conf.c:692
+#, c-format
+msgid "%s is not a regular file"
+msgstr ""
+
+#: lib/util/sudo_conf.c:695 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr ""
+
+#: lib/util/sudo_conf.c:699
+#, c-format
+msgid "%s is world writable"
+msgstr ""
+
+#: lib/util/sudo_conf.c:702
+#, c-format
+msgid "%s is group writable"
+msgstr ""
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr ""
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr ""
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr ""
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr ""
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr ""
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr ""
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "e pamundur të stat-ohet %s"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr ""
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr ""
+
+#: src/edit_open.c:331
+msgid "unable to restore current working directory"
+msgstr ""
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr ""
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr ""
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr ""
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr ""
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr ""
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr ""
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr ""
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr ""
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "duke filluar nga %s"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:567 src/exec_monitor.c:569
+#: src/exec_pty.c:225 src/exec_pty.c:1017 src/exec_pty.c:1019 src/signal.c:144
+#: src/signal.c:151 src/signal.c:165 src/suspend_nopty.c:93
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr ""
+
+#: src/exec.c:422
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr ""
+
+#: src/exec.c:427
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr ""
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr ""
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:165 src/exec_iolog.c:175
+#: src/exec_iolog.c:220 src/exec_iolog.c:227 src/exec_iolog.c:254
+#: src/exec_monitor.c:466 src/exec_monitor.c:474 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_monitor.c:496 src/exec_monitor.c:503
+#: src/exec_monitor.c:510 src/exec_monitor.c:517 src/exec_monitor.c:524
+#: src/exec_monitor.c:531 src/exec_nopty.c:229 src/exec_nopty.c:238
+#: src/exec_nopty.c:245 src/exec_nopty.c:252 src/exec_nopty.c:259
+#: src/exec_nopty.c:266 src/exec_nopty.c:273 src/exec_nopty.c:280
+#: src/exec_nopty.c:287 src/exec_nopty.c:294 src/exec_nopty.c:301
+#: src/exec_nopty.c:308 src/exec_nopty.c:316 src/exec_nopty.c:324
+#: src/exec_nopty.c:383 src/exec_nopty.c:449 src/exec_pty.c:355
+#: src/exec_pty.c:457 src/exec_pty.c:512 src/exec_pty.c:875 src/exec_pty.c:884
+#: src/exec_pty.c:891 src/exec_pty.c:898 src/exec_pty.c:905 src/exec_pty.c:912
+#: src/exec_pty.c:919 src/exec_pty.c:926 src/exec_pty.c:933 src/exec_pty.c:940
+#: src/exec_pty.c:947
+msgid "unable to add event to queue"
+msgstr ""
+
+#: src/exec_intercept.c:317 src/sudo.c:1018
+msgid "command not set by the security policy"
+msgstr ""
+
+#: src/exec_intercept.c:393 src/exec_intercept.c:421 src/sudo.c:1238
+#: src/sudo.c:1283 src/sudo.c:1327
+msgid "command rejected by policy"
+msgstr ""
+
+#: src/exec_intercept.c:491 src/sudo.c:1925
+msgid "approval plugin error"
+msgstr ""
+
+#: src/exec_intercept.c:508 src/sudo.c:1243 src/sudo.c:1288 src/sudo.c:1332
+#: src/sudo.c:1406
+msgid "policy plugin error"
+msgstr ""
+
+#: src/exec_intercept.c:543
+msgid "invalid PolicyCheckRequest"
+msgstr ""
+
+#: src/exec_intercept.c:678
+#, c-format
+msgid "client request too large: %zu"
+msgstr ""
+
+#: src/exec_intercept.c:720
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr ""
+
+#: src/exec_intercept.c:768
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr ""
+
+#: src/exec_intercept.c:794
+#, c-format
+msgid "server message too large: %zu"
+msgstr ""
+
+#: src/exec_iolog.c:323 src/exec_iolog.c:363 src/exec_iolog.c:403
+#: src/exec_iolog.c:454 src/exec_iolog.c:505
+msgid "I/O plugin error"
+msgstr ""
+
+#: src/exec_iolog.c:327 src/exec_iolog.c:367 src/exec_iolog.c:407
+#: src/exec_iolog.c:458 src/exec_iolog.c:509
+msgid "command rejected by I/O plugin"
+msgstr ""
+
+#: src/exec_iolog.c:556
+msgid "error logging suspend"
+msgstr ""
+
+#: src/exec_iolog.c:591
+msgid "error changing window size"
+msgstr ""
+
+#: src/exec_monitor.c:360
+msgid "error reading from socketpair"
+msgstr ""
+
+#: src/exec_monitor.c:377
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr ""
+
+#: src/exec_monitor.c:585
+msgid "unable to set controlling tty"
+msgstr ""
+
+#: src/exec_monitor.c:593 src/exec_nopty.c:494 src/exec_nopty.c:504
+#: src/exec_nopty.c:514 src/exec_nopty.c:548 src/exec_pty.c:1088
+#: src/exec_pty.c:1109 src/exec_pty.c:1129 src/tgetpass.c:305
+msgid "unable to create pipe"
+msgstr ""
+
+#: src/exec_monitor.c:603
+msgid "unable to receive message from parent"
+msgstr ""
+
+#: src/exec_monitor.c:619 src/exec_nopty.c:591 src/exec_pty.c:1167
+#: src/sudo_edit.c:361 src/tgetpass.c:309
+msgid "unable to fork"
+msgstr "e pamundur të kopjohet procesi"
+
+#: src/exec_monitor.c:623 src/exec_monitor.c:721 src/exec_nopty.c:696
+msgid "unable to restore tty label"
+msgstr ""
+
+#: src/exec_monitor.c:636 src/sesh.c:217 src/sudo.c:1189
+#, c-format
+msgid "unable to execute %s"
+msgstr ""
+
+#: src/exec_nopty.c:542 src/exec_pty.c:1026
+msgid "policy plugin failed session initialization"
+msgstr ""
+
+#: src/exec_nopty.c:557 src/exec_pty.c:995 src/exec_pty.c:1004
+msgid "unable to create sockets"
+msgstr ""
+
+#: src/exec_nopty.c:684 src/exec_pty.c:1265
+msgid "error in event loop"
+msgstr ""
+
+#: src/exec_preload.c:165 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:851 src/sudo.c:486
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr ""
+
+#: src/exec_ptrace.c:1078 src/exec_ptrace.c:1103 src/exec_ptrace.c:1909
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr ""
+
+#: src/exec_ptrace.c:1098 src/exec_ptrace.c:1273 src/exec_ptrace.c:1615
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr ""
+
+#: src/exec_ptrace.c:1207
+msgid "unable to set seccomp filter"
+msgstr ""
+
+#: src/exec_ptrace.c:1404
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr ""
+
+#: src/exec_ptrace.c:1503
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr ""
+
+#: src/exec_ptrace.c:1512 src/exec_ptrace.c:1519 src/exec_ptrace.c:1532
+#: src/exec_ptrace.c:1540 src/exec_ptrace.c:1546 src/exec_ptrace.c:1552
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr ""
+
+#: src/exec_ptrace.c:1619
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr ""
+
+#: src/exec_ptrace.c:1711
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr ""
+
+#: src/exec_ptrace.c:1718
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr ""
+
+#: src/exec_pty.c:103
+msgid "unable to allocate pty"
+msgstr ""
+
+#: src/exec_pty.c:263 src/signal.c:101 src/suspend_nopty.c:99
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr ""
+
+#: src/exec_pty.c:1213
+msgid "unable to send message to monitor process"
+msgstr ""
+
+#: src/load_plugins.c:109 src/load_plugins.c:123 src/load_plugins.c:129
+#: src/load_plugins.c:279 src/load_plugins.c:289 src/load_plugins.c:299
+#: src/load_plugins.c:346
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr ""
+
+#: src/load_plugins.c:125
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr ""
+
+#: src/load_plugins.c:131
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr ""
+
+#: src/load_plugins.c:243 src/load_plugins.c:314
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr ""
+
+#: src/load_plugins.c:281
+#, c-format
+msgid "unable to load %s: %s"
+msgstr ""
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr ""
+
+#: src/load_plugins.c:301
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr ""
+
+#: src/load_plugins.c:319
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr ""
+
+#: src/load_plugins.c:322
+msgid "only a single policy plugin may be specified"
+msgstr ""
+
+#: src/load_plugins.c:348
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr ""
+
+#: src/load_plugins.c:531
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr ""
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr ""
+
+#: src/parse_args.c:317
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr ""
+
+#: src/parse_args.c:554
+msgid "you may not specify both the -i and -s options"
+msgstr ""
+
+#: src/parse_args.c:559
+msgid "you may not specify both the -i and -E options"
+msgstr ""
+
+#: src/parse_args.c:569
+msgid "the -E option is not valid in edit mode"
+msgstr ""
+
+#: src/parse_args.c:572
+msgid "you may not specify environment variables in edit mode"
+msgstr ""
+
+#: src/parse_args.c:582
+msgid "the -U option may only be used with the -l option"
+msgstr ""
+
+#: src/parse_args.c:586
+msgid "the -A and -S options may not be used together"
+msgstr ""
+
+#: src/parse_args.c:684
+msgid "sudoedit is not supported on this platform"
+msgstr ""
+
+#: src/parse_args.c:767
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr ""
+
+#: src/parse_args.c:780
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr ""
+
+#: src/parse_args.c:796
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+
+#: src/parse_args.c:798
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+
+#: src/parse_args.c:804
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Opsionet:\n"
+
+#: src/parse_args.c:806
+msgid "use a helper program for password prompting"
+msgstr ""
+
+#: src/parse_args.c:809
+msgid "use specified BSD authentication type"
+msgstr ""
+
+#: src/parse_args.c:813
+msgid "run command in the background"
+msgstr "egzekutoje komandën në prapavi"
+
+#: src/parse_args.c:816
+msgid "ring bell when prompting"
+msgstr ""
+
+#: src/parse_args.c:818
+msgid "close all file descriptors >= num"
+msgstr ""
+
+#: src/parse_args.c:821
+msgid "run command with the specified BSD login class"
+msgstr ""
+
+#: src/parse_args.c:824
+msgid "change the working directory before running command"
+msgstr ""
+
+#: src/parse_args.c:827
+msgid "preserve user environment when running command"
+msgstr ""
+
+#: src/parse_args.c:829
+msgid "preserve specific environment variables"
+msgstr ""
+
+#: src/parse_args.c:831
+msgid "edit files instead of running a command"
+msgstr ""
+
+#: src/parse_args.c:834
+msgid "run command as the specified group name or ID"
+msgstr ""
+
+#: src/parse_args.c:837
+msgid "set HOME variable to target user's home dir"
+msgstr ""
+
+#: src/parse_args.c:840
+msgid "display help message and exit"
+msgstr ""
+
+#: src/parse_args.c:842
+msgid "run command on host (if supported by plugin)"
+msgstr ""
+
+#: src/parse_args.c:845
+msgid "run login shell as the target user; a command may also be specified"
+msgstr ""
+
+#: src/parse_args.c:847
+msgid "remove timestamp file completely"
+msgstr ""
+
+#: src/parse_args.c:850
+msgid "invalidate timestamp file"
+msgstr ""
+
+#: src/parse_args.c:853
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr ""
+
+#: src/parse_args.c:856
+msgid "non-interactive mode, no prompts are used"
+msgstr ""
+
+#: src/parse_args.c:859
+msgid "preserve group vector instead of setting to target's"
+msgstr ""
+
+#: src/parse_args.c:862
+msgid "use the specified password prompt"
+msgstr ""
+
+#: src/parse_args.c:864
+msgid "change the root directory before running command"
+msgstr ""
+
+#: src/parse_args.c:867
+msgid "create SELinux security context with specified role"
+msgstr ""
+
+#: src/parse_args.c:870
+msgid "read password from standard input"
+msgstr ""
+
+#: src/parse_args.c:873
+msgid "run shell as the target user; a command may also be specified"
+msgstr ""
+
+#: src/parse_args.c:877
+msgid "create SELinux security context with specified type"
+msgstr ""
+
+#: src/parse_args.c:880
+msgid "terminate command after the specified time limit"
+msgstr ""
+
+#: src/parse_args.c:883
+msgid "in list mode, display privileges for user"
+msgstr ""
+
+#: src/parse_args.c:886
+msgid "run command (or edit file) as specified user name or ID"
+msgstr ""
+
+#: src/parse_args.c:888
+msgid "display version information and exit"
+msgstr ""
+
+#: src/parse_args.c:891
+msgid "update user's timestamp without running a command"
+msgstr ""
+
+#: src/parse_args.c:894
+msgid "stop processing command line arguments"
+msgstr ""
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr ""
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr ""
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr ""
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s ndryshoi etiketat"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr ""
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr ""
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr ""
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr ""
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr ""
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr ""
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr ""
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr ""
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr ""
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr ""
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr ""
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr ""
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr ""
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr ""
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr ""
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr ""
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr ""
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr ""
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr ""
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr ""
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr ""
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr ""
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr ""
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr ""
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr ""
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr ""
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr ""
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr ""
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr ""
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr ""
+
+#: src/sudo.c:216
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Verzioni i Sudo-s %s\n"
+
+#: src/sudo.c:218
+#, c-format
+msgid "Configure options: %s\n"
+msgstr ""
+
+#: src/sudo.c:226
+msgid "fatal error, unable to load plugins"
+msgstr ""
+
+#: src/sudo.c:272
+msgid "plugin did not return a command to execute"
+msgstr ""
+
+#: src/sudo.c:305
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr ""
+
+#: src/sudo.c:553
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr ""
+
+#: src/sudo.c:610
+msgid "unable to determine tty"
+msgstr ""
+
+#: src/sudo.c:918
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr ""
+
+#: src/sudo.c:920
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr ""
+
+#: src/sudo.c:954
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr ""
+
+#: src/sudo.c:957
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr ""
+
+#: src/sudo.c:963
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr ""
+
+#: src/sudo.c:979 src/tgetpass.c:331
+msgid "unable to set supplementary group IDs"
+msgstr ""
+
+#: src/sudo.c:986
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr ""
+
+#: src/sudo.c:992
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr ""
+
+#: src/sudo.c:1022
+msgid "argv not set by the security policy"
+msgstr ""
+
+#: src/sudo.c:1026
+msgid "envp not set by the security policy"
+msgstr ""
+
+#: src/sudo.c:1048
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr ""
+
+#: src/sudo.c:1161
+msgid "unable to initialize policy plugin"
+msgstr ""
+
+#: src/sudo.c:1223
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr ""
+
+#: src/sudo.c:1269
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr ""
+
+#: src/sudo.c:1313
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr ""
+
+#: src/sudo.c:1351
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr ""
+
+#: src/sudo.c:1480
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr ""
+
+#: src/sudo.c:1483
+msgid "error initializing I/O plugin"
+msgstr ""
+
+#: src/sudo.c:1632
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr ""
+
+#: src/sudo.c:1711
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr ""
+
+#: src/sudo.c:1747
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr ""
+
+#: src/sudo.c:1752 src/sudo.c:1790
+msgid "audit plugin error"
+msgstr ""
+
+#: src/sudo.c:1785
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr ""
+
+#: src/sudo.c:1845
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr ""
+
+#: src/sudo.c:1915
+msgid "command rejected by approver"
+msgstr "komanda u refuzua nga aprovuesi"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr ""
+
+#: src/sudo_edit.c:291
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s ka mbetur e pandryshuar"
+
+#: src/sudo_edit.c:304 src/sudo_edit.c:569
+#, c-format
+msgid "%s unchanged"
+msgstr "%s e pandryshuar"
+
+#: src/sudo_edit.c:481
+msgid "sesh: internal error: odd number of paths"
+msgstr ""
+
+#: src/sudo_edit.c:483
+msgid "sesh: unable to create temporary files"
+msgstr ""
+
+#: src/sudo_edit.c:485 src/sudo_edit.c:604
+msgid "sesh: killed by a signal"
+msgstr "sesh: u vra nga një sinjal"
+
+#: src/sudo_edit.c:487 src/sudo_edit.c:607
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: gabim i panjohur %d"
+
+#: src/sudo_edit.c:597
+msgid "unable to copy temporary files back to their original location"
+msgstr ""
+
+#: src/sudo_edit.c:601
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr ""
+
+#: src/sudo_edit.c:645
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr ""
+
+#: src/sudo_edit.c:666
+msgid "plugin error: missing file list for sudoedit"
+msgstr ""
+
+#: src/sudo_edit.c:709 src/sudo_edit.c:723
+msgid "unable to read the clock"
+msgstr "e pamundur të lexohet ora"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "porti i ndërhyrhjes nuk është përcaktuar"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "skadoi koha duke lexuar shifrën"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "shifra nuk ishte dhënë"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "e pamundur të lexohet shifra"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr ""
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr ""
+
+#: src/tgetpass.c:326
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "e pamundur ti vendoset gid %u"
+
+#: src/tgetpass.c:336
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "e pamundur ti vendoset uid %u"
+
+#: src/tgetpass.c:341
+#, c-format
+msgid "unable to run %s"
+msgstr "e pamundur të egzekutohet %s"
+
+#: src/utmp.c:288
+msgid "unable to save stdin"
+msgstr "e pamundur të ruhet stdin"
+
+#: src/utmp.c:290
+msgid "unable to dup2 stdin"
+msgstr "e pamundur të dup2 stdin"
+
+#: src/utmp.c:293
+msgid "unable to restore stdin"
+msgstr "e pamundur të rivendoset stdin"
diff --git a/po/sr.mo b/po/sr.mo
new file mode 100644
index 0000000..84dfe80
--- /dev/null
+++ b/po/sr.mo
Binary files differ
diff --git a/po/sr.po b/po/sr.po
new file mode 100644
index 0000000..1cfefc3
--- /dev/null
+++ b/po/sr.po
@@ -0,0 +1,1292 @@
+# Serbian translations for sudo package.
+# This file is put in the public domain.
+# Мирослав Николић <miroslavnikolic@rocketmail.com>, 2011-2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo-1.9.14b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-06-07 13:27-0600\n"
+"PO-Revision-Date: 2023-07-21 08:00+0200\n"
+"Last-Translator: Мирослав Николић <miroslavnikolic@rocketmail.com>\n"
+"Language-Team: Serbian <(nothing)>\n"
+"Language: sr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Gtranslator 41.0\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "не могу да отворим корисничку базу података"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "не могу да се пребацим на регистар „%s“ за %s"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "не могу да повратим регистар"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:78 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:171 src/exec_monitor.c:418
+#: src/exec_monitor.c:424 src/exec_monitor.c:432 src/exec_monitor.c:440
+#: src/exec_monitor.c:447 src/exec_monitor.c:454 src/exec_monitor.c:461
+#: src/exec_monitor.c:468 src/exec_monitor.c:475 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:744 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1096
+#: src/exec_ptrace.c:1271 src/exec_ptrace.c:1624 src/exec_ptrace.c:1651
+#: src/exec_ptrace.c:1841 src/exec_pty.c:581 src/exec_pty.c:765
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:193 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:240
+#: src/sesh.c:246 src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:644
+#: src/sudo.c:709 src/sudo.c:719 src/sudo.c:746 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:787 src/sudo.c:805 src/sudo.c:846 src/sudo.c:855 src/sudo.c:865
+#: src/sudo.c:898 src/sudo.c:1127 src/sudo.c:1148 src/sudo.c:1441
+#: src/sudo.c:1610 src/sudo.c:1837 src/sudo.c:2171 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:430 src/sudo_edit.c:439
+#: src/sudo_edit.c:540 src/sudo_edit.c:547 src/sudo_edit.c:692
+#: src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:79 src/exec_intercept.c:111 src/exec_intercept.c:350
+#: src/exec_intercept.c:525 src/exec_intercept.c:589 src/exec_intercept.c:713
+#: src/exec_intercept.c:837 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:418 src/exec_monitor.c:424
+#: src/exec_monitor.c:432 src/exec_monitor.c:440 src/exec_monitor.c:447
+#: src/exec_monitor.c:454 src/exec_monitor.c:461 src/exec_monitor.c:468
+#: src/exec_monitor.c:475 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1651 src/exec_ptrace.c:1842 src/exec_pty.c:581
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:228 src/sudo.c:644 src/sudo.c:898 src/sudo.c:1127
+#: src/sudo.c:1148 src/sudo.c:1441 src/sudo.c:1610 src/sudo.c:1837
+#: src/sudo.c:2171 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:430
+#: src/sudo_edit.c:439 src/sudo_edit.c:540 src/sudo_edit.c:547
+#: src/sudo_edit.c:692 src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "не могу да доделим меморију"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "не могу да добијем податке о „%.*s“"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "„%.*s“ постоји али није директоријум (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:664
+#: lib/util/sudo_conf.c:683 lib/util/sudo_conf.c:710 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:495 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "не могу да отворим %s"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "не могу да направим директоријум „%.*s“"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "не могу да отворим „%.*s“"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "регуларни израз је превелик"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Непознати сигнал"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "неисправна вредност"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "вредност је превелика"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "вредност је премала"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "неисправна вредност путање „%s“ у „%s“, %u. ред"
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "неисправна вредност за %s „%s“ у „%s“, %u. ред"
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "неподржани извор групе „%s“ у „%s“, %u. ред"
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "неисправне највеће групе „%s“ у „%s“, %u. ред"
+
+#: lib/util/sudo_conf.c:686
+#, c-format
+msgid "%s is not a regular file"
+msgstr "„%s“ није обична датотека"
+
+#: lib/util/sudo_conf.c:689 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s је у власништву уиб-а %u, а треба бити %u"
+
+#: lib/util/sudo_conf.c:693
+#, c-format
+msgid "%s is world writable"
+msgstr "%s је светски уписив"
+
+#: lib/util/sudo_conf.c:696
+#, c-format
+msgid "%s is group writable"
+msgstr "%s је групно уписив"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "нисам успео да одредим оивичење АпАрмора"
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "не могу да променим АпАрмор профил на „%s“"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: да скратим „%s“ на нула бајта? (y/n) [n] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "не преписујем „%s“"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "не могу да читам из „%s“"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "не могу да упишем у %s"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "не могу да добијем податке о „%s“"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: није обична датотека"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: лош режим датотеке: 0%o"
+
+#: src/edit_open.c:333
+msgid "unable to restore current working directory"
+msgstr "не могу да повратим текући радни директоријум"
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "не могу да поставим привилегије"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "не могу да поставим привилегије ограничења"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "непозната класа пријаве %s"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "не могу да подесим кориснички контекст"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "не могу да подесим приоритет процеса"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "не могу да променим администратора на %s"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "не могу да се пребацим у покрени_као уид (%u, %u)"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "не могу да променим директоријум у %s"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "почевши од „%s“"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:552 src/exec_monitor.c:554
+#: src/exec_pty.c:1122 src/exec_pty.c:1124 src/signal.c:144 src/signal.c:151
+#: src/signal.c:165 src/suspend_parent.c:143
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "не могу да подесим руковаоца за сигнал „%d“"
+
+#: src/exec.c:424
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "режим пресретања није подржан са СЕЛинукс РБАЦ-ом на овом систему"
+
+#: src/exec.c:429
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "не могу да забележим садржане наредбе са СЕЛинукс РБАЦ-ом на овом систему"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "не могу да уклоним PRIV_PROC_EXEC из PRIV_LIMIT"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:163 src/exec_iolog.c:173
+#: src/exec_iolog.c:218 src/exec_iolog.c:225 src/exec_iolog.c:252
+#: src/exec_monitor.c:426 src/exec_monitor.c:434 src/exec_monitor.c:442
+#: src/exec_monitor.c:449 src/exec_monitor.c:456 src/exec_monitor.c:463
+#: src/exec_monitor.c:470 src/exec_monitor.c:477 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:457 src/exec_pty.c:432
+#: src/exec_pty.c:537 src/exec_pty.c:587 src/exec_pty.c:965 src/exec_pty.c:974
+#: src/exec_pty.c:981 src/exec_pty.c:988 src/exec_pty.c:995
+#: src/exec_pty.c:1002 src/exec_pty.c:1009 src/exec_pty.c:1016
+#: src/exec_pty.c:1023 src/exec_pty.c:1030 src/exec_pty.c:1037
+#: src/exec_pty.c:1044
+msgid "unable to add event to queue"
+msgstr "не могу да додам догађај у ред"
+
+#: src/exec_intercept.c:323 src/sudo.c:1033
+msgid "command not set by the security policy"
+msgstr "наредба није постављена политиком безбедности"
+
+#: src/exec_intercept.c:401 src/exec_intercept.c:441 src/sudo.c:1253
+#: src/sudo.c:1298 src/sudo.c:1342
+msgid "command rejected by policy"
+msgstr "наредба је одбачена политиком"
+
+#: src/exec_intercept.c:512 src/sudo.c:1940
+msgid "approval plugin error"
+msgstr "грешка прикључка одобравања"
+
+#: src/exec_intercept.c:537 src/sudo.c:1258 src/sudo.c:1303 src/sudo.c:1347
+#: src/sudo.c:1421
+msgid "policy plugin error"
+msgstr "грешка прикључка политике"
+
+#: src/exec_intercept.c:566
+msgid "invalid PolicyCheckRequest"
+msgstr "неисправан захтев провере политике"
+
+#: src/exec_intercept.c:709
+#, c-format
+msgid "client request too large: %zu"
+msgstr "захтев клијента је превелик: %zu"
+
+#: src/exec_intercept.c:751
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "не могу да распакујем „%s“ величине %zu"
+
+#: src/exec_intercept.c:799
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "неочекивана вредност врсте_слова %d у „%s“ из „%s“"
+
+#: src/exec_intercept.c:825
+#, c-format
+msgid "server message too large: %zu"
+msgstr "порука сервера је превелика: %zu"
+
+#: src/exec_iolog.c:321 src/exec_iolog.c:361 src/exec_iolog.c:401
+#: src/exec_iolog.c:452 src/exec_iolog.c:503
+msgid "I/O plugin error"
+msgstr "грешка У/И прикључка"
+
+#: src/exec_iolog.c:325 src/exec_iolog.c:365 src/exec_iolog.c:405
+#: src/exec_iolog.c:456 src/exec_iolog.c:507
+msgid "command rejected by I/O plugin"
+msgstr "наредбу је одбацио У/И прикључак"
+
+#: src/exec_iolog.c:555
+msgid "error logging suspend"
+msgstr "грешка обуставе писања дневника"
+
+#: src/exec_iolog.c:590
+msgid "error changing window size"
+msgstr "грешка промене величине прозора"
+
+#: src/exec_monitor.c:328
+msgid "error reading from socketpair"
+msgstr "грешка у читању из пара прикључка"
+
+#: src/exec_monitor.c:340
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "неочекивана врста одговора на повратном каналу: %d"
+
+#: src/exec_monitor.c:566
+msgid "unable to set controlling tty"
+msgstr "не могу да подесим контролисање tty"
+
+#: src/exec_monitor.c:574 src/exec_nopty.c:504 src/exec_nopty.c:514
+#: src/exec_nopty.c:524 src/exec_nopty.c:560 src/exec_pty.c:1195
+#: src/exec_pty.c:1222 src/exec_pty.c:1242 src/exec_pty.c:1262
+#: src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr "не могу да направим спојку"
+
+#: src/exec_monitor.c:584
+msgid "unable to receive message from parent"
+msgstr "не могу да примим поруку од родитеља"
+
+#: src/exec_monitor.c:600 src/exec_nopty.c:603 src/exec_pty.c:1303
+#: src/sudo_edit.c:361 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr "не могу да поделим"
+
+#: src/exec_monitor.c:604 src/exec_monitor.c:700 src/exec_nopty.c:708
+msgid "unable to restore tty label"
+msgstr "не могу да повратим tty натпис"
+
+#: src/exec_monitor.c:615 src/sesh.c:217 src/sudo.c:1204
+#, c-format
+msgid "unable to execute %s"
+msgstr "не могу да извршим %s"
+
+#: src/exec_nopty.c:554 src/exec_pty.c:1131
+msgid "policy plugin failed session initialization"
+msgstr "није успело покретање сесије прикључка политике"
+
+#: src/exec_nopty.c:569 src/exec_pty.c:1100 src/exec_pty.c:1109
+msgid "unable to create sockets"
+msgstr "не могу да направим утичнице"
+
+#: src/exec_nopty.c:696 src/exec_pty.c:1406
+msgid "error in event loop"
+msgstr "грешка у петљи догађаја"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:852 src/sudo.c:488
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "унутрашња грешка, прекорачење функције „%s“"
+
+#: src/exec_ptrace.c:1080 src/exec_ptrace.c:1105 src/exec_ptrace.c:1925
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "не могу да поставим регистре за процес %d"
+
+#: src/exec_ptrace.c:1100 src/exec_ptrace.c:1275 src/exec_ptrace.c:1628
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "процес %d је изашао неочекивано"
+
+#: src/exec_ptrace.c:1209
+msgid "unable to set seccomp filter"
+msgstr "не могу да поставим „seccomp“ филтер"
+
+#: src/exec_ptrace.c:1406
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "аргумент тумача, очекивах „%s“, добих „%s“"
+
+#: src/exec_ptrace.c:1505
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "назив путање не одговара, очекивах „%s“, добих „%s“"
+
+#: src/exec_ptrace.c:1514 src/exec_ptrace.c:1521 src/exec_ptrace.c:1545
+#: src/exec_ptrace.c:1553 src/exec_ptrace.c:1559 src/exec_ptrace.c:1565
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "%s[%d] не одговара, очекивах „%s“, добих „%s“"
+
+#: src/exec_ptrace.c:1632
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "процес %d неочекиваног статуса 0x%x"
+
+#: src/exec_ptrace.c:1723
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "не могу да добавим поруку догађаја за процес %d"
+
+#: src/exec_ptrace.c:1730
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "не могу да добавим регистре за процес %d"
+
+#: src/exec_pty.c:84
+msgid "unable to allocate pty"
+msgstr "не могу да доделим pty"
+
+#: src/exec_pty.c:131 src/exec_pty.c:284 src/tgetpass.c:251
+msgid "unable to restore terminal settings"
+msgstr "не могу да повратим поставке терминала"
+
+#: src/exec_pty.c:243
+msgid "unable to set handler for SIGCONT"
+msgstr "не могу да подесим руковаоца за „SIGCONT“"
+
+#: src/exec_pty.c:293
+#, c-format
+msgid "unable to set handler for SIG%s"
+msgstr "не могу да подесим руковаоца за „SIG%s“"
+
+#: src/exec_pty.c:317
+#, c-format
+msgid "unable to restore handler for SIG%s"
+msgstr "не могу да повратим руковаоца за „SIG%s“"
+
+#: src/exec_pty.c:345
+msgid "unable to restore handler for SIGCONT"
+msgstr "не могу да повратим руковаоца за „SIGCONT“"
+
+#: src/exec_pty.c:1353
+msgid "unable to send message to monitor process"
+msgstr "не могу да пошаљем поруку процесу праћења"
+
+#: src/load_plugins.c:75 src/load_plugins.c:222 src/load_plugins.c:232
+#: src/load_plugins.c:242 src/load_plugins.c:289
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "грешка у „%s“, %d. ред приликом учитавања прикључка „%s“"
+
+#: src/load_plugins.c:186 src/load_plugins.c:257
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "занемарујем удвостручени „%s“ прикључак у %s, %d. ред"
+
+#: src/load_plugins.c:224
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "не могу да учитам %s: %s"
+
+#: src/load_plugins.c:234
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "не могу да пронађем симбол „%s“ у %s"
+
+#: src/load_plugins.c:244
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "пронађено је несагласно главно издање прикључка %d (очекивано је %d) у „%s“"
+
+#: src/load_plugins.c:262
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "занемарујем прикључак сигурности „%s“ у %s, %d. ред"
+
+#: src/load_plugins.c:265
+msgid "only a single policy plugin may be specified"
+msgstr "може бити наведен само један прикључак сигурности"
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "нађох непознату врсту прикључка %d у „%s“"
+
+#: src/load_plugins.c:474
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "прикључак сигурности %s не садржи метод провере_сигурности"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "неисправан назив променљиве окружења: %s"
+
+#: src/parse_args.c:319
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "аргумент уз -C мора бити број већи или једнак 3"
+
+#: src/parse_args.c:556
+msgid "you may not specify both the -i and -s options"
+msgstr "не можете да наведете обе опције „-i“ и „-s“"
+
+#: src/parse_args.c:561
+msgid "you may not specify both the -i and -E options"
+msgstr "не можете да наведете обе опције „-i“ и „-E“"
+
+#: src/parse_args.c:571
+msgid "the -E option is not valid in edit mode"
+msgstr "опција „-E“ није исправна у режиму уређивања"
+
+#: src/parse_args.c:574
+msgid "you may not specify environment variables in edit mode"
+msgstr "не можете да одредите променљиве окружења у режиму уређивања"
+
+#: src/parse_args.c:584
+msgid "the -U option may only be used with the -l option"
+msgstr "опција „-U“ може бити коришћена само са опцијом „-l“"
+
+#: src/parse_args.c:588
+msgid "the -A and -S options may not be used together"
+msgstr "опције „-A“ и „-S“ не могу бити коришћене заједно"
+
+#: src/parse_args.c:686
+msgid "sudoedit is not supported on this platform"
+msgstr "„sudoedit“ није подржано на овој платформи"
+
+#: src/parse_args.c:744
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Само једна од опција -e, -h, -i, -K, -l, -s, -v или -V може бити наведена"
+
+#: src/parse_args.c:757
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "Само једна од опција „-K“, „-k“ или „-N“ може бити наведена"
+
+#: src/parse_args.c:778
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s — уредите датотеке као други корисник\n"
+"\n"
+
+#: src/parse_args.c:780
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s — извршите наредбу као други корисник\n"
+"\n"
+
+#: src/parse_args.c:785
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Опције:\n"
+
+#: src/parse_args.c:787
+msgid "use a helper program for password prompting"
+msgstr "користи програм испомоћи за упит лозинке"
+
+#: src/parse_args.c:790
+msgid "use specified BSD authentication type"
+msgstr "користи наведену врсту БСД потврде идентитета"
+
+#: src/parse_args.c:794
+msgid "run command in the background"
+msgstr "покреће наредбу у позадини"
+
+#: src/parse_args.c:797
+msgid "ring bell when prompting"
+msgstr "звони приликом постављања упита"
+
+#: src/parse_args.c:799
+msgid "close all file descriptors >= num"
+msgstr "затвара све описнике датотеке >= fd"
+
+#: src/parse_args.c:802
+msgid "run command with the specified BSD login class"
+msgstr "покреће наредбу са наведеним разредом БСД пријаве"
+
+#: src/parse_args.c:805
+msgid "change the working directory before running command"
+msgstr "мења радни директоријум пре покретања наредбе"
+
+#: src/parse_args.c:808
+msgid "preserve user environment when running command"
+msgstr "чува корисничко окружење приликом покретања наредбе"
+
+#: src/parse_args.c:810
+msgid "preserve specific environment variables"
+msgstr "чува нарочите променљиве окружења"
+
+#: src/parse_args.c:812
+msgid "edit files instead of running a command"
+msgstr "уређује датотеке уместо да изврши наредбу"
+
+#: src/parse_args.c:815
+msgid "run command as the specified group name or ID"
+msgstr "извршава наредбу као наведени назив групе или ИБ"
+
+#: src/parse_args.c:818
+msgid "set HOME variable to target user's home dir"
+msgstr "подешава променљиву ЛИЧНО у циљну корисничку личну фасциклу"
+
+#: src/parse_args.c:821
+msgid "display help message and exit"
+msgstr "приказује поруку помоћи и излази"
+
+#: src/parse_args.c:823
+msgid "run command on host (if supported by plugin)"
+msgstr "покреће наредбу на домаћину (ако је подржано прикључком)"
+
+#: src/parse_args.c:826
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "покреће љуску пријаве као крајњи корисник; наредба може такође бити наведена"
+
+#: src/parse_args.c:828
+msgid "remove timestamp file completely"
+msgstr "потпуно уклања датотеку записа датума и времена"
+
+#: src/parse_args.c:831
+msgid "invalidate timestamp file"
+msgstr "чини неисправном датотеку датума и времена"
+
+#: src/parse_args.c:834
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "исписује привилегије корисника или проверава посебну наредбу; користи се двапута за дуже записе"
+
+#: src/parse_args.c:837
+msgid "non-interactive mode, no prompts are used"
+msgstr "немеђудејствени режим, не користи упите"
+
+#: src/parse_args.c:840
+msgid "preserve group vector instead of setting to target's"
+msgstr "чува вектор групе уместо да подеси на циљеве"
+
+#: src/parse_args.c:843
+msgid "use the specified password prompt"
+msgstr "користи упит наведене лозинке"
+
+#: src/parse_args.c:845
+msgid "change the root directory before running command"
+msgstr "мења корени директоријум пре покретања наредбе"
+
+#: src/parse_args.c:848
+msgid "create SELinux security context with specified role"
+msgstr "ствара СЕЛинукс сигурносни контекст са наведеном улогом"
+
+#: src/parse_args.c:851
+msgid "read password from standard input"
+msgstr "чита лозинку са стандардног улаза"
+
+#: src/parse_args.c:854
+msgid "run shell as the target user; a command may also be specified"
+msgstr "покреће љуску као крајњи корисник; наредба такође може бити наведена"
+
+#: src/parse_args.c:858
+msgid "create SELinux security context with specified type"
+msgstr "ствара СЕЛинукс сигурносни контекст са наведеном улогом"
+
+#: src/parse_args.c:861
+msgid "terminate command after the specified time limit"
+msgstr "окончава наредбу након наведеног временског ограничења"
+
+#: src/parse_args.c:864
+msgid "in list mode, display privileges for user"
+msgstr "у режиму списка, приказује привилегије за корисника"
+
+#: src/parse_args.c:867
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "покреће наредбу (или уређује датотеку) као наведени корисник"
+
+#: src/parse_args.c:869
+msgid "display version information and exit"
+msgstr "приказује податке о издању и излази"
+
+#: src/parse_args.c:872
+msgid "update user's timestamp without running a command"
+msgstr "освежава кориснички запис датума и времена без покретања наредбе"
+
+#: src/parse_args.c:875
+msgid "stop processing command line arguments"
+msgstr "зауставља обрађивање аргумената линије наредби"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "не могу да отворим аудит систем"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "не могу да пошаљем аудит поруку"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "не могу да добавим контекст отворене датотеке %s"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s измењена натписа"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "не могу да повратим контекст за %s"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "не могу да отворим %s, није тту за поновно натписивање"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "„%s“ није знаковни уређај, није конзола за поновно натписивање"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "не могу да добавим текући тту контекст, није тту за поновно натписивање"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "непознат разред безбедности „chr_file“, није тту за поновно натписивање"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "не могу да добавим нови тту контекст, није тту за поновно натписивање"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "не могу да подесим нови тту контекст"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "морате да наведете улогу за врсту %s"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "не могу да добавим основну врсту за улогу %s"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "нисам успео да добавим нови контекст"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "нисам успео да подесим нову улогу %s"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "нисам успео да подесим нову врсту %s"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s није исправан контекст"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "нисам успео да добавим стари контекст"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "не могу да одредим режим присиљавања."
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "не могу да подесим извршни контекст за %s"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "не могу да подесим контекст стварања кључа за %s"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "Само једна од опција „-c“ или „-i“ може бити наведена"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "неисправан број описника датотеке: %s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "Опција „-%c“ се не може користити у режиму уређивања."
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "Опција „-%c“ може бити коришћена само у режиму уређивања."
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: уређивање симболичких веза није допуштено"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: уређивање датотека у уписивом директоријуму није допуштено"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "садржај сесије уређивања је остао у %s"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "не могу да добавим списак групе"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "не могу да сачувам руковаоца за сигнал „%d“"
+
+#: src/signal.c:101 src/suspend_parent.c:149
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "не могу да повратим руковаоца за сигнал „%d“"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "ограничење контроле ресурса је достигнуто"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "корисник „%s“ није члан пројекта „%s“"
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "задатак призивања је завршни"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "не могу да приступим пројекту „%s“"
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "не постоји депо извора који прихвата основне пречице за пројекат „%s“"
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "наведени депо извора не постоји за пројекат „%s“"
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "не могу да се повежем са основним депоом извора за пројекат „%s“"
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "подешавање пројекта није успело за пројекат „%s“"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "упозорење, није успело додељивање контроле ресурса за пројекат „%s“"
+
+#: src/sudo.c:214
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Судо издање %s\n"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Опције подешавања: %s\n"
+
+#: src/sudo.c:224
+msgid "fatal error, unable to load plugins"
+msgstr "кобна грешка, не могу да учитам прикључке"
+
+#: src/sudo.c:270
+msgid "plugin did not return a command to execute"
+msgstr "прикључак није вратио наредбу за извршавање"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "неочекивани судо режим 0x%x"
+
+#: src/sudo.c:559
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "не постојите у „%s“ бази података"
+
+#: src/sudo.c:616
+msgid "unable to determine tty"
+msgstr "не могу да одредим конзолу"
+
+#: src/sudo.c:932
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "Опција „no new privileges“ је постављена, што спречава „sudo“-а да ради као администратор."
+
+#: src/sudo.c:934
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "Ако судо ради у садржаоцу, треба да прилагодите подешавање садржаоца да искључи опцију."
+
+#: src/sudo.c:968
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s мора бити власништвo уида %d и треба да има подешен бит „setuid“"
+
+#: src/sudo.c:971
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "стварни уид није %d, већ %s на систему датотека са подешеном опцијом „nosuid“ или је НФС систем датотека без администраторских привилегија?"
+
+#: src/sudo.c:977
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "стварни уид није %d, већ сетуид администратор инсталиран судоом?"
+
+#: src/sudo.c:993 src/tgetpass.c:332
+msgid "unable to set supplementary group IDs"
+msgstr "не могу да подесим додатне ИБ-ове групе"
+
+#: src/sudo.c:1000
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "не могу да подесим ефективан гид да се покрене_као гид %u"
+
+#: src/sudo.c:1006
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "не могу да подесим гид да се покрене као гид %u"
+
+#: src/sudo.c:1037
+msgid "argv not set by the security policy"
+msgstr "„argv“ није постављено политиком безбедности"
+
+#: src/sudo.c:1041
+msgid "envp not set by the security policy"
+msgstr "„envp“ није постављено политиком безбедности"
+
+#: src/sudo.c:1063
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "неочекивани услов завршетка потпроцеса: %d"
+
+#: src/sudo.c:1176
+msgid "unable to initialize policy plugin"
+msgstr "не могу да започнем прикључак сигурности"
+
+#: src/sudo.c:1238
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "прикључак сигурности %s не садржи метод „check_policy“"
+
+#: src/sudo.c:1284
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "прикључак сигурности %s не подржава привилегије исписивања"
+
+#: src/sudo.c:1328
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "прикључак сигурности %s не подржава опцију -v"
+
+#: src/sudo.c:1366
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "прикључак сигурности %s не подржава опције -k/-K"
+
+#: src/sudo.c:1495
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "грешка приликом покретања У/И прикључка %s"
+
+#: src/sudo.c:1498
+msgid "error initializing I/O plugin"
+msgstr "грешка приликом покретања У/И прикључка"
+
+#: src/sudo.c:1647
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "грешка покретања аудит прикључка „%s“"
+
+#: src/sudo.c:1726
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: не могу да забележим догађај грешке%s%s"
+
+#: src/sudo.c:1762
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: не могу да забележим догађај прихватања%s%s"
+
+#: src/sudo.c:1767 src/sudo.c:1805
+msgid "audit plugin error"
+msgstr "грешка аудит прикључка"
+
+#: src/sudo.c:1800
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: не могу да забележим догађај одбијања%s%s"
+
+#: src/sudo.c:1860
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "грешка покретања прикључка одобравања „%s“"
+
+#: src/sudo.c:1930
+msgid "command rejected by approver"
+msgstr "наредбу је одбацио одобравач"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "нисам нашао уписиви привремени директоријум"
+
+#: src/sudo_edit.c:292
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s је остао неизмењен"
+
+#: src/sudo_edit.c:305 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s је непромењен"
+
+#: src/sudo_edit.c:482
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: унутрашња грешка: непарн број путања"
+
+#: src/sudo_edit.c:484
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: не могу да направим привремене датотеке"
+
+#: src/sudo_edit.c:486 src/sudo_edit.c:606
+msgid "sesh: killed by a signal"
+msgstr "sesh: убијено сигналом"
+
+#: src/sudo_edit.c:488 src/sudo_edit.c:609
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: непозната грешка „%d“"
+
+#: src/sudo_edit.c:599
+msgid "unable to copy temporary files back to their original location"
+msgstr "не могу да умножим привремене датотеке назад на њихова првобитна места"
+
+#: src/sudo_edit.c:603
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "не могу да умножим неке од привремених датотека назад на њихова првобитна места"
+
+#: src/sudo_edit.c:650
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "не могу да променим уид у администратора (%u)"
+
+#: src/sudo_edit.c:664
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "грешка прикључка: неисправан списак датотеке за уређивање судоа"
+
+#: src/sudo_edit.c:685
+msgid "plugin error: missing file list for sudoedit"
+msgstr "грешка прикључка: недостаје датотеа списка за уређивање судоа"
+
+#: src/sudo_edit.c:728 src/sudo_edit.c:743
+msgid "unable to read the clock"
+msgstr "не могу да прочитам сат"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "прикључник пресретања није постављен"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "истече време при читању лозинке"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "лозинка није достављена"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "не могу да прочитам лозинку"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "терминал је потребан за читање лозинке; или користите опцију „-S“ да читате из стандардног улаза или подесите помоћника тражиоца пролаза"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "није наведен програм за пропуштање, покушајте да подесите SUDO_ASKPASS"
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "не могу да подесим гид у %u"
+
+#: src/tgetpass.c:337
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "не могу да подесим уид у %u"
+
+#: src/tgetpass.c:342
+#, c-format
+msgid "unable to run %s"
+msgstr "не могу да покренем %s"
+
+#: src/utmp.c:283
+msgid "unable to save stdin"
+msgstr "не могу да сачувам стандардни улаз"
+
+#: src/utmp.c:285
+msgid "unable to dup2 stdin"
+msgstr "не могу да дуп2 стандардни улаз"
+
+#: src/utmp.c:288
+msgid "unable to restore stdin"
+msgstr "не могу да повратим стандардни улаз"
+
+#~ msgid "insufficient space for execve arguments"
+#~ msgstr "недовољно простора за „execve“ аргументе"
+
+#~ msgid "unable to read execve %s for process %d"
+#~ msgstr "не могу да прочитам „execve %s“ за процес %d"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s мора бити у власништву уида %d"
+
+#~ msgid "%s must be only be writable by owner"
+#~ msgstr "%s мора бити уписив само од стране власника"
+
+#~ msgid "requires at least one argument"
+#~ msgstr "захтева барем један аргумент"
+
+#~ msgid "unable to run %s as a login shell"
+#~ msgstr "не могу да покренем „%s“ као шкољку пријављивања"
+
+#~ msgid "unable to dup intercept fd"
+#~ msgstr "не могу да дуп пресретнем описника датотека"
+
+#~ msgid "%s: missing message header"
+#~ msgstr "%s: недостаје заглавље поруке"
+
+#~ msgid "%s: expected message type %d, got %d"
+#~ msgstr "%s: очекивах врсту поруке %d, добих %d"
+
+#~ msgid "unable to set tty context to %s"
+#~ msgstr "не могу да подесим тту контекст на %s"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s: %s"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s: кратак упис"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "не могу да прочитам привремену датотеку"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "занемарујем удвостручен прикључак сигурности „%s“ у %s, %d. ред"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "непознати уид %u: ко сте ви?"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "тту не постоји и није наведен програм за пропуштање"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "грешка у читању из спојке сигнала"
+
+#~ msgid "internal error, tried allocate zero bytes"
+#~ msgstr "унутрашња грешка, покушах да доделим нула бајта"
+
+#~ msgid "unable to set terminal to raw mode"
+#~ msgstr "не могу да подесим терминал у сирови режим"
+
+#~ msgid "unable to open socket"
+#~ msgstr "не могу да отворим утичницу"
+
+#~ msgid "%s: %s: %s\n"
+#~ msgstr "%s: %s: %s\n"
+
+#~ msgid "%s: %s\n"
+#~ msgstr "%s: %s\n"
+
+#~ msgid "internal error, tried to emalloc2(0)"
+#~ msgstr "унутрашња грешка, покушах да обавим „emalloc2(0)“"
+
+#~ msgid "internal error, tried to ecalloc(0)"
+#~ msgstr "унутрашња грешка, покушах „ecalloc(0)“"
+
+#~ msgid "internal error, tried to erealloc(0)"
+#~ msgstr "унутрашња грешка, покушах да обавим „erealloc(0)“"
+
+#~ msgid "internal error, tried to erealloc3(0)"
+#~ msgstr "унутрашња грешка, покушах да обавим „erealloc3(0)“"
+
+#~ msgid "internal error, tried to erecalloc(0)"
+#~ msgstr "унутрашња грешка, покушах да обавим „erecalloc(0)“"
+
+#~ msgid "load_interfaces: overflow detected"
+#~ msgstr "учитај_сучеља: откривено је прекорачење"
+
+#~ msgid "value out of range"
+#~ msgstr "вредност је изван опсега"
+
+#~ msgid "select failed"
+#~ msgstr "избор није успео"
diff --git a/po/sudo.pot b/po/sudo.pot
new file mode 100644
index 0000000..5e1e03e
--- /dev/null
+++ b/po/sudo.pot
@@ -0,0 +1,1206 @@
+# Portable object template file for sudo
+# This file is put in the public domain.
+# Todd C. Miller <Todd.Miller@sudo.ws>, 2011-2018
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.15\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-10-19 10:02-0600\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr ""
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr ""
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr ""
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:81 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:171 src/exec_monitor.c:428
+#: src/exec_monitor.c:434 src/exec_monitor.c:442 src/exec_monitor.c:450
+#: src/exec_monitor.c:457 src/exec_monitor.c:464 src/exec_monitor.c:471
+#: src/exec_monitor.c:478 src/exec_monitor.c:485 src/exec_monitor.c:492
+#: src/exec_monitor.c:499 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:748 src/exec_preload.c:347 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:984 src/exec_ptrace.c:1097
+#: src/exec_ptrace.c:1272 src/exec_ptrace.c:1625 src/exec_ptrace.c:1652
+#: src/exec_ptrace.c:1844 src/exec_pty.c:554 src/exec_pty.c:738
+#: src/exec_pty.c:936 src/exec_pty.c:945 src/exec_pty.c:952 src/exec_pty.c:959
+#: src/exec_pty.c:966 src/exec_pty.c:973 src/exec_pty.c:980 src/exec_pty.c:987
+#: src/exec_pty.c:994 src/exec_pty.c:1001 src/exec_pty.c:1008
+#: src/exec_pty.c:1015 src/exec_pty.c:1023 src/load_plugins.c:100
+#: src/load_plugins.c:125 src/load_plugins.c:161 src/load_plugins.c:394
+#: src/load_plugins.c:400 src/parse_args.c:172 src/parse_args.c:193
+#: src/parse_args.c:269 src/parse_args.c:625 src/parse_args.c:647
+#: src/parse_args.c:672 src/preserve_fds.c:46 src/preserve_fds.c:131
+#: src/selinux.c:89 src/selinux.c:362 src/selinux.c:472 src/selinux.c:489
+#: src/selinux.c:496 src/sesh.c:206 src/sesh.c:240 src/sesh.c:246
+#: src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:579 src/sudo.c:605
+#: src/sudo.c:655 src/sudo.c:721 src/sudo.c:732 src/sudo.c:759 src/sudo.c:782
+#: src/sudo.c:791 src/sudo.c:800 src/sudo.c:813 src/sudo.c:822 src/sudo.c:863
+#: src/sudo.c:873 src/sudo.c:883 src/sudo.c:916 src/sudo.c:918 src/sudo.c:1145
+#: src/sudo.c:1166 src/sudo.c:1457 src/sudo.c:1626 src/sudo.c:1853
+#: src/sudo.c:2186 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:430
+#: src/sudo_edit.c:439 src/sudo_edit.c:540 src/sudo_edit.c:547
+#: src/sudo_edit.c:692 src/sudo_edit.c:712 src/sudo_intercept_common.c:122
+#: src/sudo_intercept_common.c:347
+#, c-format
+msgid "%s: %s"
+msgstr ""
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:82 src/exec_intercept.c:112 src/exec_intercept.c:351
+#: src/exec_intercept.c:527 src/exec_intercept.c:591 src/exec_intercept.c:715
+#: src/exec_intercept.c:839 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:428 src/exec_monitor.c:434
+#: src/exec_monitor.c:442 src/exec_monitor.c:450 src/exec_monitor.c:457
+#: src/exec_monitor.c:464 src/exec_monitor.c:471 src/exec_monitor.c:478
+#: src/exec_monitor.c:485 src/exec_monitor.c:492 src/exec_monitor.c:499
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:347
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:984
+#: src/exec_ptrace.c:1652 src/exec_ptrace.c:1845 src/exec_pty.c:554
+#: src/exec_pty.c:936 src/exec_pty.c:945 src/exec_pty.c:952 src/exec_pty.c:959
+#: src/exec_pty.c:966 src/exec_pty.c:973 src/exec_pty.c:980 src/exec_pty.c:987
+#: src/exec_pty.c:994 src/exec_pty.c:1001 src/exec_pty.c:1008
+#: src/exec_pty.c:1015 src/exec_pty.c:1023 src/load_plugins.c:100
+#: src/load_plugins.c:125 src/load_plugins.c:161 src/load_plugins.c:394
+#: src/load_plugins.c:400 src/parse_args.c:172 src/parse_args.c:194
+#: src/parse_args.c:269 src/parse_args.c:625 src/parse_args.c:647
+#: src/parse_args.c:672 src/preserve_fds.c:46 src/preserve_fds.c:131
+#: src/selinux.c:89 src/selinux.c:362 src/selinux.c:472 src/selinux.c:489
+#: src/selinux.c:496 src/sesh.c:206 src/sesh.c:471 src/sudo.c:229
+#: src/sudo.c:579 src/sudo.c:605 src/sudo.c:655 src/sudo.c:814 src/sudo.c:916
+#: src/sudo.c:918 src/sudo.c:1145 src/sudo.c:1166 src/sudo.c:1457
+#: src/sudo.c:1626 src/sudo.c:1853 src/sudo.c:2186 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:430 src/sudo_edit.c:439
+#: src/sudo_edit.c:540 src/sudo_edit.c:547 src/sudo_edit.c:692
+#: src/sudo_edit.c:712 src/sudo_intercept_common.c:122
+#: src/sudo_intercept_common.c:347
+msgid "unable to allocate memory"
+msgstr ""
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr ""
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr ""
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:664
+#: lib/util/sudo_conf.c:683 lib/util/sudo_conf.c:710 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:374 src/sudo_edit.c:495 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr ""
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr ""
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr ""
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr ""
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr ""
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:147
+#: lib/util/strtonum.c:186 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr ""
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:159
+msgid "value too large"
+msgstr ""
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:153
+msgid "value too small"
+msgstr ""
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr ""
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr ""
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr ""
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr ""
+
+#: lib/util/sudo_conf.c:686
+#, c-format
+msgid "%s is not a regular file"
+msgstr ""
+
+#: lib/util/sudo_conf.c:689 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr ""
+
+#: lib/util/sudo_conf.c:693
+#, c-format
+msgid "%s is world writable"
+msgstr ""
+
+#: lib/util/sudo_conf.c:696
+#, c-format
+msgid "%s is group writable"
+msgstr ""
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr ""
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr ""
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr ""
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr ""
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr ""
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr ""
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr ""
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr ""
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr ""
+
+#: src/edit_open.c:333
+msgid "unable to restore current working directory"
+msgstr ""
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr ""
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr ""
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr ""
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr ""
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr ""
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr ""
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr ""
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr ""
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr ""
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:562 src/exec_monitor.c:564
+#: src/exec_pty.c:1094 src/exec_pty.c:1096 src/signal.c:144 src/signal.c:151
+#: src/signal.c:165 src/suspend_parent.c:143
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr ""
+
+#: src/exec.c:447
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr ""
+
+#: src/exec.c:452
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr ""
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr ""
+
+#: src/exec_intercept.c:71 src/exec_iolog.c:163 src/exec_iolog.c:173
+#: src/exec_iolog.c:218 src/exec_iolog.c:225 src/exec_iolog.c:252
+#: src/exec_monitor.c:436 src/exec_monitor.c:444 src/exec_monitor.c:452
+#: src/exec_monitor.c:459 src/exec_monitor.c:466 src/exec_monitor.c:473
+#: src/exec_monitor.c:480 src/exec_monitor.c:487 src/exec_monitor.c:494
+#: src/exec_monitor.c:501 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:457 src/exec_pty.c:405
+#: src/exec_pty.c:510 src/exec_pty.c:560 src/exec_pty.c:938 src/exec_pty.c:947
+#: src/exec_pty.c:954 src/exec_pty.c:961 src/exec_pty.c:968 src/exec_pty.c:975
+#: src/exec_pty.c:982 src/exec_pty.c:989 src/exec_pty.c:996 src/exec_pty.c:1003
+#: src/exec_pty.c:1010 src/exec_pty.c:1017
+msgid "unable to add event to queue"
+msgstr ""
+
+#: src/exec_intercept.c:324 src/sudo.c:1051
+msgid "command not set by the security policy"
+msgstr ""
+
+#: src/exec_intercept.c:403 src/exec_intercept.c:443 src/sudo.c:1269
+#: src/sudo.c:1314 src/sudo.c:1358
+msgid "command rejected by policy"
+msgstr ""
+
+#: src/exec_intercept.c:514 src/sudo.c:1956
+msgid "approval plugin error"
+msgstr ""
+
+#: src/exec_intercept.c:539 src/sudo.c:1274 src/sudo.c:1319 src/sudo.c:1363
+#: src/sudo.c:1437
+msgid "policy plugin error"
+msgstr ""
+
+#: src/exec_intercept.c:568
+msgid "invalid PolicyCheckRequest"
+msgstr ""
+
+#: src/exec_intercept.c:711
+#, c-format
+msgid "client request too large: %zu"
+msgstr ""
+
+#: src/exec_intercept.c:753
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr ""
+
+#: src/exec_intercept.c:801
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr ""
+
+#: src/exec_intercept.c:827
+#, c-format
+msgid "server message too large: %zu"
+msgstr ""
+
+#: src/exec_iolog.c:321 src/exec_iolog.c:361 src/exec_iolog.c:401
+#: src/exec_iolog.c:452 src/exec_iolog.c:503
+msgid "I/O plugin error"
+msgstr ""
+
+#: src/exec_iolog.c:325 src/exec_iolog.c:365 src/exec_iolog.c:405
+#: src/exec_iolog.c:456 src/exec_iolog.c:507
+msgid "command rejected by I/O plugin"
+msgstr ""
+
+#: src/exec_iolog.c:555
+msgid "error logging suspend"
+msgstr ""
+
+#: src/exec_iolog.c:590
+msgid "error changing window size"
+msgstr ""
+
+#: src/exec_monitor.c:328
+msgid "error reading from socketpair"
+msgstr ""
+
+#: src/exec_monitor.c:340
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr ""
+
+#: src/exec_monitor.c:576
+msgid "unable to set controlling tty"
+msgstr ""
+
+#: src/exec_monitor.c:588 src/exec_nopty.c:572 src/exec_pty.c:1072
+#: src/exec_pty.c:1081
+msgid "unable to create sockets"
+msgstr ""
+
+#: src/exec_monitor.c:597
+msgid "unable to receive message from parent"
+msgstr ""
+
+#: src/exec_monitor.c:612 src/exec_nopty.c:606 src/exec_pty.c:1282
+#: src/sudo_edit.c:361 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr ""
+
+#: src/exec_monitor.c:616 src/exec_monitor.c:718 src/exec_nopty.c:712
+msgid "unable to restore tty label"
+msgstr ""
+
+#: src/exec_monitor.c:627 src/exec_monitor.c:676 src/sesh.c:217 src/sudo.c:1220
+#, c-format
+msgid "unable to execute %s"
+msgstr ""
+
+#: src/exec_nopty.c:507 src/exec_nopty.c:517 src/exec_nopty.c:527
+#: src/exec_nopty.c:563 src/exec_pty.c:1170 src/exec_pty.c:1197
+#: src/exec_pty.c:1220 src/exec_pty.c:1238 src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr ""
+
+#: src/exec_nopty.c:557 src/exec_pty.c:1103
+msgid "policy plugin failed session initialization"
+msgstr ""
+
+#: src/exec_nopty.c:700 src/exec_pty.c:1383
+msgid "error in event loop"
+msgstr ""
+
+#: src/exec_preload.c:168 src/net_ifs.c:206 src/net_ifs.c:372 src/net_ifs.c:433
+#: src/net_ifs.c:620 src/net_ifs.c:852 src/sudo.c:493 src/sudo_edit.c:398
+#: src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr ""
+
+#: src/exec_ptrace.c:1081 src/exec_ptrace.c:1106 src/exec_ptrace.c:1929
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr ""
+
+#: src/exec_ptrace.c:1101 src/exec_ptrace.c:1276 src/exec_ptrace.c:1629
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr ""
+
+#: src/exec_ptrace.c:1210
+msgid "unable to set seccomp filter"
+msgstr ""
+
+#: src/exec_ptrace.c:1407
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr ""
+
+#: src/exec_ptrace.c:1505
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr ""
+
+#: src/exec_ptrace.c:1514 src/exec_ptrace.c:1521 src/exec_ptrace.c:1545
+#: src/exec_ptrace.c:1553 src/exec_ptrace.c:1559 src/exec_ptrace.c:1565
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr ""
+
+#: src/exec_ptrace.c:1633
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr ""
+
+#: src/exec_ptrace.c:1726
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr ""
+
+#: src/exec_ptrace.c:1733
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr ""
+
+#: src/exec_pty.c:86
+msgid "unable to allocate pty"
+msgstr ""
+
+#: src/exec_pty.c:117 src/exec_pty.c:256 src/tgetpass.c:251
+msgid "unable to restore terminal settings"
+msgstr ""
+
+#: src/exec_pty.c:217
+msgid "unable to set handler for SIGCONT"
+msgstr ""
+
+#: src/exec_pty.c:266
+#, c-format
+msgid "unable to set handler for SIG%s"
+msgstr ""
+
+#: src/exec_pty.c:290
+#, c-format
+msgid "unable to restore handler for SIG%s"
+msgstr ""
+
+#: src/exec_pty.c:318
+msgid "unable to restore handler for SIGCONT"
+msgstr ""
+
+#: src/exec_pty.c:1331
+msgid "unable to send message to monitor process"
+msgstr ""
+
+#: src/load_plugins.c:75 src/load_plugins.c:222 src/load_plugins.c:232
+#: src/load_plugins.c:242 src/load_plugins.c:289
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr ""
+
+#: src/load_plugins.c:186 src/load_plugins.c:257
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr ""
+
+#: src/load_plugins.c:224
+#, c-format
+msgid "unable to load %s: %s"
+msgstr ""
+
+#: src/load_plugins.c:234
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr ""
+
+#: src/load_plugins.c:244
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr ""
+
+#: src/load_plugins.c:262
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr ""
+
+#: src/load_plugins.c:265
+msgid "only a single policy plugin may be specified"
+msgstr ""
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr ""
+
+#: src/load_plugins.c:474
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr ""
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr ""
+
+#: src/parse_args.c:319
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr ""
+
+#: src/parse_args.c:556
+msgid "you may not specify both the -i and -s options"
+msgstr ""
+
+#: src/parse_args.c:561
+msgid "you may not specify both the -i and -E options"
+msgstr ""
+
+#: src/parse_args.c:571
+msgid "the -E option is not valid in edit mode"
+msgstr ""
+
+#: src/parse_args.c:574
+msgid "you may not specify environment variables in edit mode"
+msgstr ""
+
+#: src/parse_args.c:584
+msgid "the -U option may only be used with the -l option"
+msgstr ""
+
+#: src/parse_args.c:588
+msgid "the -A and -S options may not be used together"
+msgstr ""
+
+#: src/parse_args.c:686
+msgid "sudoedit is not supported on this platform"
+msgstr ""
+
+#: src/parse_args.c:745
+msgid ""
+"Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr ""
+
+#: src/parse_args.c:758
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr ""
+
+#: src/parse_args.c:779
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+
+#: src/parse_args.c:781
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+
+#: src/parse_args.c:786
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+
+#: src/parse_args.c:788
+msgid "use a helper program for password prompting"
+msgstr ""
+
+#: src/parse_args.c:791
+msgid "use specified BSD authentication type"
+msgstr ""
+
+#: src/parse_args.c:795
+msgid "run command in the background"
+msgstr ""
+
+#: src/parse_args.c:798
+msgid "ring bell when prompting"
+msgstr ""
+
+#: src/parse_args.c:800
+msgid "close all file descriptors >= num"
+msgstr ""
+
+#: src/parse_args.c:803
+msgid "run command with the specified BSD login class"
+msgstr ""
+
+#: src/parse_args.c:806
+msgid "change the working directory before running command"
+msgstr ""
+
+#: src/parse_args.c:809
+msgid "preserve user environment when running command"
+msgstr ""
+
+#: src/parse_args.c:811
+msgid "preserve specific environment variables"
+msgstr ""
+
+#: src/parse_args.c:813
+msgid "edit files instead of running a command"
+msgstr ""
+
+#: src/parse_args.c:816
+msgid "run command as the specified group name or ID"
+msgstr ""
+
+#: src/parse_args.c:819
+msgid "set HOME variable to target user's home dir"
+msgstr ""
+
+#: src/parse_args.c:822
+msgid "display help message and exit"
+msgstr ""
+
+#: src/parse_args.c:824
+msgid "run command on host (if supported by plugin)"
+msgstr ""
+
+#: src/parse_args.c:827
+msgid "run login shell as the target user; a command may also be specified"
+msgstr ""
+
+#: src/parse_args.c:829
+msgid "remove timestamp file completely"
+msgstr ""
+
+#: src/parse_args.c:832
+msgid "invalidate timestamp file"
+msgstr ""
+
+#: src/parse_args.c:835
+msgid ""
+"list user's privileges or check a specific command; use twice for longer "
+"format"
+msgstr ""
+
+#: src/parse_args.c:838
+msgid "non-interactive mode, no prompts are used"
+msgstr ""
+
+#: src/parse_args.c:841
+msgid "preserve group vector instead of setting to target's"
+msgstr ""
+
+#: src/parse_args.c:844
+msgid "use the specified password prompt"
+msgstr ""
+
+#: src/parse_args.c:846
+msgid "change the root directory before running command"
+msgstr ""
+
+#: src/parse_args.c:849
+msgid "create SELinux security context with specified role"
+msgstr ""
+
+#: src/parse_args.c:852
+msgid "read password from standard input"
+msgstr ""
+
+#: src/parse_args.c:855
+msgid "run shell as the target user; a command may also be specified"
+msgstr ""
+
+#: src/parse_args.c:859
+msgid "create SELinux security context with specified type"
+msgstr ""
+
+#: src/parse_args.c:862
+msgid "terminate command after the specified time limit"
+msgstr ""
+
+#: src/parse_args.c:865
+msgid "in list mode, display privileges for user"
+msgstr ""
+
+#: src/parse_args.c:868
+msgid "run command (or edit file) as specified user name or ID"
+msgstr ""
+
+#: src/parse_args.c:870
+msgid "display version information and exit"
+msgstr ""
+
+#: src/parse_args.c:873
+msgid "update user's timestamp without running a command"
+msgstr ""
+
+#: src/parse_args.c:876
+msgid "stop processing command line arguments"
+msgstr ""
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr ""
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr ""
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr ""
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr ""
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr ""
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr ""
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr ""
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr ""
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr ""
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr ""
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr ""
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr ""
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr ""
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr ""
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr ""
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr ""
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr ""
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr ""
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr ""
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr ""
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr ""
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr ""
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr ""
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr ""
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr ""
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr ""
+
+#: src/signal.c:101 src/suspend_parent.c:149
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr ""
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr ""
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr ""
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr ""
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr ""
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr ""
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr ""
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr ""
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr ""
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr ""
+
+#: src/sudo.c:215
+#, c-format
+msgid "Sudo version %s\n"
+msgstr ""
+
+#: src/sudo.c:217
+#, c-format
+msgid "Configure options: %s\n"
+msgstr ""
+
+#: src/sudo.c:225
+msgid "fatal error, unable to load plugins"
+msgstr ""
+
+#: src/sudo.c:271
+msgid "plugin did not return a command to execute"
+msgstr ""
+
+#: src/sudo.c:307
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr ""
+
+#: src/sudo.c:565
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr ""
+
+#: src/sudo.c:627
+msgid "unable to determine tty"
+msgstr ""
+
+#: src/sudo.c:950
+msgid ""
+"The \"no new privileges\" flag is set, which prevents sudo from running as "
+"root."
+msgstr ""
+
+#: src/sudo.c:952
+msgid ""
+"If sudo is running in a container, you may need to adjust the container "
+"configuration to disable the flag."
+msgstr ""
+
+#: src/sudo.c:986
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr ""
+
+#: src/sudo.c:989
+#, c-format
+msgid ""
+"effective uid is not %d, is %s on a file system with the 'nosuid' option set "
+"or an NFS file system without root privileges?"
+msgstr ""
+
+#: src/sudo.c:995
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr ""
+
+#: src/sudo.c:1011 src/tgetpass.c:332
+msgid "unable to set supplementary group IDs"
+msgstr ""
+
+#: src/sudo.c:1018
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr ""
+
+#: src/sudo.c:1024
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr ""
+
+#: src/sudo.c:1055
+msgid "argv not set by the security policy"
+msgstr ""
+
+#: src/sudo.c:1059
+msgid "envp not set by the security policy"
+msgstr ""
+
+#: src/sudo.c:1081
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr ""
+
+#: src/sudo.c:1193
+msgid "unable to initialize policy plugin"
+msgstr ""
+
+#: src/sudo.c:1254
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr ""
+
+#: src/sudo.c:1300
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr ""
+
+#: src/sudo.c:1344
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr ""
+
+#: src/sudo.c:1382
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr ""
+
+#: src/sudo.c:1511
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr ""
+
+#: src/sudo.c:1514
+msgid "error initializing I/O plugin"
+msgstr ""
+
+#: src/sudo.c:1663
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr ""
+
+#: src/sudo.c:1742
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr ""
+
+#: src/sudo.c:1778
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr ""
+
+#: src/sudo.c:1783 src/sudo.c:1821
+msgid "audit plugin error"
+msgstr ""
+
+#: src/sudo.c:1816
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr ""
+
+#: src/sudo.c:1876
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr ""
+
+#: src/sudo.c:1946
+msgid "command rejected by approver"
+msgstr ""
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr ""
+
+#: src/sudo_edit.c:292
+#, c-format
+msgid "%s left unmodified"
+msgstr ""
+
+#: src/sudo_edit.c:305 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr ""
+
+#: src/sudo_edit.c:482
+msgid "sesh: internal error: odd number of paths"
+msgstr ""
+
+#: src/sudo_edit.c:484
+msgid "sesh: unable to create temporary files"
+msgstr ""
+
+#: src/sudo_edit.c:486 src/sudo_edit.c:606
+msgid "sesh: killed by a signal"
+msgstr ""
+
+#: src/sudo_edit.c:488 src/sudo_edit.c:609
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr ""
+
+#: src/sudo_edit.c:599
+msgid "unable to copy temporary files back to their original location"
+msgstr ""
+
+#: src/sudo_edit.c:603
+msgid ""
+"unable to copy some of the temporary files back to their original location"
+msgstr ""
+
+#: src/sudo_edit.c:650
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr ""
+
+#: src/sudo_edit.c:664
+msgid "plugin error: invalid file list for sudoedit"
+msgstr ""
+
+#: src/sudo_edit.c:685
+msgid "plugin error: missing file list for sudoedit"
+msgstr ""
+
+#: src/sudo_edit.c:728 src/sudo_edit.c:743
+msgid "unable to read the clock"
+msgstr ""
+
+#: src/sudo_intercept_common.c:372
+msgid "intercept port not set"
+msgstr ""
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr ""
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr ""
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr ""
+
+#: src/tgetpass.c:141
+msgid ""
+"a terminal is required to read the password; either use the -S option to "
+"read from standard input or configure an askpass helper"
+msgstr ""
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr ""
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr ""
+
+#: src/tgetpass.c:337
+#, c-format
+msgid "unable to set uid to %u"
+msgstr ""
+
+#: src/tgetpass.c:342
+#, c-format
+msgid "unable to run %s"
+msgstr ""
+
+#: src/utmp.c:283
+msgid "unable to save stdin"
+msgstr ""
+
+#: src/utmp.c:285
+msgid "unable to dup2 stdin"
+msgstr ""
+
+#: src/utmp.c:288
+msgid "unable to restore stdin"
+msgstr ""
diff --git a/po/sv.mo b/po/sv.mo
new file mode 100644
index 0000000..d8e011c
--- /dev/null
+++ b/po/sv.mo
Binary files differ
diff --git a/po/sv.po b/po/sv.po
new file mode 100644
index 0000000..79c230d
--- /dev/null
+++ b/po/sv.po
@@ -0,0 +1,1247 @@
+# Swedish translation for sudo.
+# Copyright © 2012, 2016, 2017, 2018, 2019, 2020, 2022, 2023 Free Software Foundation, Inc.
+# This file is put in the public domain.
+# Daniel Nylander <po@danielnylander.se>, 2012.
+# Sebastian Rasmussen <sebras@gmail.com>, 2016, 2017, 2018, 2019, 2020, 2022, 2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.13b2\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-01-24 13:11-0700\n"
+"PO-Revision-Date: 2023-01-26 13:18+0100\n"
+"Last-Translator: Sebastian Rasmussen <sebras@gmail.com>\n"
+"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
+"Language: sv\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 3.2.2\n"
+"X-Poedit-Bookmarks: -1,0,-1,-1,-1,-1,-1,-1,-1,-1\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "kunde inte öppna användardatabasen"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "kunde inte växla till registret ”%s” för %s"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "kunde inte återställa registret"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:646
+#: src/conversation.c:80 src/exec_iolog.c:124 src/exec_iolog.c:135
+#: src/exec_iolog.c:212 src/exec_monitor.c:205 src/exec_monitor.c:460
+#: src/exec_monitor.c:466 src/exec_monitor.c:474 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_monitor.c:496 src/exec_monitor.c:503
+#: src/exec_monitor.c:510 src/exec_monitor.c:517 src/exec_monitor.c:524
+#: src/exec_monitor.c:531 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:736 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1095
+#: src/exec_ptrace.c:1270 src/exec_ptrace.c:1612 src/exec_ptrace.c:1639
+#: src/exec_pty.c:511 src/exec_pty.c:692 src/exec_pty.c:882 src/exec_pty.c:891
+#: src/exec_pty.c:898 src/exec_pty.c:905 src/exec_pty.c:912 src/exec_pty.c:919
+#: src/exec_pty.c:926 src/exec_pty.c:933 src/exec_pty.c:940 src/exec_pty.c:947
+#: src/exec_pty.c:954 src/exec_pty.c:962 src/load_plugins.c:98
+#: src/load_plugins.c:123 src/load_plugins.c:159 src/load_plugins.c:392
+#: src/load_plugins.c:398 src/parse_args.c:172 src/parse_args.c:193
+#: src/parse_args.c:267 src/parse_args.c:623 src/parse_args.c:645
+#: src/parse_args.c:670 src/preserve_fds.c:46 src/preserve_fds.c:131
+#: src/selinux.c:89 src/selinux.c:362 src/selinux.c:472 src/selinux.c:489
+#: src/selinux.c:496 src/sesh.c:206 src/sesh.c:240 src/sesh.c:246
+#: src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:641 src/sudo.c:706
+#: src/sudo.c:716 src/sudo.c:743 src/sudo.c:766 src/sudo.c:775 src/sudo.c:784
+#: src/sudo.c:801 src/sudo.c:842 src/sudo.c:851 src/sudo.c:861 src/sudo.c:894
+#: src/sudo.c:1122 src/sudo.c:1143 src/sudo.c:1436 src/sudo.c:1605
+#: src/sudo.c:1832 src/sudo.c:2166 src/sudo_edit.c:89 src/sudo_edit.c:149
+#: src/sudo_edit.c:429 src/sudo_edit.c:438 src/sudo_edit.c:538
+#: src/sudo_edit.c:545 src/sudo_edit.c:688 src/sudo_edit.c:708
+#: src/sudo_intercept_common.c:115 src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:646
+#: src/conversation.c:81 src/exec_intercept.c:111 src/exec_intercept.c:344
+#: src/exec_intercept.c:518 src/exec_intercept.c:582 src/exec_intercept.c:706
+#: src/exec_intercept.c:830 src/exec_iolog.c:124 src/exec_iolog.c:135
+#: src/exec_iolog.c:212 src/exec_monitor.c:460 src/exec_monitor.c:466
+#: src/exec_monitor.c:474 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_monitor.c:496 src/exec_monitor.c:503 src/exec_monitor.c:510
+#: src/exec_monitor.c:517 src/exec_monitor.c:524 src/exec_monitor.c:531
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1639 src/exec_pty.c:511 src/exec_pty.c:882
+#: src/exec_pty.c:891 src/exec_pty.c:898 src/exec_pty.c:905 src/exec_pty.c:912
+#: src/exec_pty.c:919 src/exec_pty.c:926 src/exec_pty.c:933 src/exec_pty.c:940
+#: src/exec_pty.c:947 src/exec_pty.c:954 src/exec_pty.c:962
+#: src/load_plugins.c:98 src/load_plugins.c:123 src/load_plugins.c:159
+#: src/load_plugins.c:392 src/load_plugins.c:398 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:267 src/parse_args.c:623
+#: src/parse_args.c:645 src/parse_args.c:670 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:230 src/sudo.c:641 src/sudo.c:894 src/sudo.c:1122
+#: src/sudo.c:1143 src/sudo.c:1436 src/sudo.c:1605 src/sudo.c:1832
+#: src/sudo.c:2166 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:429
+#: src/sudo_edit.c:438 src/sudo_edit.c:538 src/sudo_edit.c:545
+#: src/sudo_edit.c:688 src/sudo_edit.c:708 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "kunde inte allokera minne"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "kunde inte ta status på %.*s"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s existerar men är inte en katalog (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:666
+#: lib/util/sudo_conf.c:696 lib/util/sudo_conf.c:703 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:494 src/sudo_edit.c:557
+#, c-format
+msgid "unable to open %s"
+msgstr "kunde inte öppna %s"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "kunde inte köra mkdir %.*s"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "kunde inte öppna %.*s"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "reguljärt uttryck för stort"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Okänd signal"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "ogiltigt värde"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "värde för stort"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "värde för litet"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "ogiltigt Path-värde ”%s” i %s, rad %u"
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "ogiltigt värde för %s ”%s” i %s, rad %u"
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "gruppkälla ”%s” stöds ej i %s, rad %u"
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "ogiltigt största antal grupper ”%s” i %s, rad %u"
+
+#: lib/util/sudo_conf.c:669
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s är inte en vanlig fil"
+
+#: lib/util/sudo_conf.c:672 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s ägs av uid %u, ska vara %u"
+
+#: lib/util/sudo_conf.c:676
+#, c-format
+msgid "%s is world writable"
+msgstr "%s är skrivbar för alla"
+
+#: lib/util/sudo_conf.c:679
+#, c-format
+msgid "%s is group writable"
+msgstr "%s är skrivbar för gruppen"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "kunde inte fastställa AppArmor- läge."
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "kan inte ändra AppArmor-profil till %s"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: trunkera %s till noll byte? (y för ja/n för nej) [n] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "skriver inte över %s"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "kunde inte läsa från %s"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "kunde inte skriva till %s"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "kunde inte ta status på %s"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: inte en vanlig fil"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: felaktigt filläge: 0%o"
+
+#: src/edit_open.c:331
+msgid "unable to restore current working directory"
+msgstr "kunde inte återställa aktuell arbetskatalog"
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "kan inte sätta privilegier"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "kan inte sätta begränsning av privilegier"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "okänd inloggningsklass %s"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "kunde inte ställa in användarens kontext"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "kunde inte ställa in processprioritet"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "kunde inte ändra rot till %s"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "kunde inte ändra till runas uid (%u, %u)"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "kunde inte ändra katalog till %s"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "börjar från %s"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:569 src/exec_monitor.c:571
+#: src/exec_pty.c:225 src/exec_pty.c:1026 src/exec_pty.c:1028 src/signal.c:144
+#: src/signal.c:151 src/signal.c:165 src/suspend_nopty.c:93
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "kunde inte ställa in hanterare för signal %d"
+
+#: src/exec.c:422
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "infångningsläge stöds in med SELinux RBAC på detta system"
+
+#: src/exec.c:427
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "kan inte logga underkommandon med SELinux RBAC på detta system"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "kan inte ta bort PRIV_PROC_EXEC från PRIV_LIMIT"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:165 src/exec_iolog.c:175
+#: src/exec_iolog.c:220 src/exec_iolog.c:227 src/exec_iolog.c:254
+#: src/exec_monitor.c:468 src/exec_monitor.c:476 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_monitor.c:498 src/exec_monitor.c:505
+#: src/exec_monitor.c:512 src/exec_monitor.c:519 src/exec_monitor.c:526
+#: src/exec_monitor.c:533 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:453 src/exec_pty.c:360
+#: src/exec_pty.c:462 src/exec_pty.c:517 src/exec_pty.c:884 src/exec_pty.c:893
+#: src/exec_pty.c:900 src/exec_pty.c:907 src/exec_pty.c:914 src/exec_pty.c:921
+#: src/exec_pty.c:928 src/exec_pty.c:935 src/exec_pty.c:942 src/exec_pty.c:949
+#: src/exec_pty.c:956
+msgid "unable to add event to queue"
+msgstr "kunde inte lägga till händelse till kö"
+
+#: src/exec_intercept.c:317 src/sudo.c:1028
+msgid "command not set by the security policy"
+msgstr "kommando inte satt enligt säkerhetspolicyn"
+
+#: src/exec_intercept.c:395 src/exec_intercept.c:435 src/sudo.c:1248
+#: src/sudo.c:1293 src/sudo.c:1337
+msgid "command rejected by policy"
+msgstr "kommando avböjt enligt policy"
+
+#: src/exec_intercept.c:505 src/sudo.c:1935
+msgid "approval plugin error"
+msgstr "fel i godkänningsinsticksmodul"
+
+#: src/exec_intercept.c:530 src/sudo.c:1253 src/sudo.c:1298 src/sudo.c:1342
+#: src/sudo.c:1416
+msgid "policy plugin error"
+msgstr "fel i policyinsticksmodul"
+
+#: src/exec_intercept.c:559
+msgid "invalid PolicyCheckRequest"
+msgstr "ogiltig PolicyCheckRequest"
+
+#: src/exec_intercept.c:702
+#, c-format
+msgid "client request too large: %zu"
+msgstr "klientbegäran för stor: %zu"
+
+#: src/exec_intercept.c:744
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "kunde inte packa upp %s storlek %zu"
+
+#: src/exec_intercept.c:792
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "oväntat type_case-värde %d i %s från %s"
+
+#: src/exec_intercept.c:818
+#, c-format
+msgid "server message too large: %zu"
+msgstr "servermeddelande för stort: %zu"
+
+#: src/exec_iolog.c:323 src/exec_iolog.c:363 src/exec_iolog.c:403
+#: src/exec_iolog.c:454 src/exec_iolog.c:505
+msgid "I/O plugin error"
+msgstr "fel i I/O-insticksmodul"
+
+#: src/exec_iolog.c:327 src/exec_iolog.c:367 src/exec_iolog.c:407
+#: src/exec_iolog.c:458 src/exec_iolog.c:509
+msgid "command rejected by I/O plugin"
+msgstr "kommando avböjt av I/O-insticksmodul"
+
+#: src/exec_iolog.c:556
+msgid "error logging suspend"
+msgstr "felloggning avstängd"
+
+#: src/exec_iolog.c:591
+msgid "error changing window size"
+msgstr "fel vid ändring av fönsterstorlek"
+
+#: src/exec_monitor.c:362
+msgid "error reading from socketpair"
+msgstr "fel vid läsning från uttagspar"
+
+#: src/exec_monitor.c:379
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "oväntad svarstyp i bakkanal: %d"
+
+#: src/exec_monitor.c:587
+msgid "unable to set controlling tty"
+msgstr "kan inte ställa in kontrollerande tty"
+
+#: src/exec_monitor.c:595 src/exec_nopty.c:498 src/exec_nopty.c:508
+#: src/exec_nopty.c:518 src/exec_nopty.c:552 src/exec_pty.c:1097
+#: src/exec_pty.c:1118 src/exec_pty.c:1138 src/tgetpass.c:305
+msgid "unable to create pipe"
+msgstr "kunde inte skapa rör"
+
+#: src/exec_monitor.c:605
+msgid "unable to receive message from parent"
+msgstr "kan inte ta emot meddelande från förälder"
+
+#: src/exec_monitor.c:621 src/exec_nopty.c:595 src/exec_pty.c:1176
+#: src/sudo_edit.c:361 src/tgetpass.c:309
+msgid "unable to fork"
+msgstr "kunde inte grena process"
+
+#: src/exec_monitor.c:625 src/exec_monitor.c:723 src/exec_nopty.c:700
+msgid "unable to restore tty label"
+msgstr "kan inte återställa tty-etikett"
+
+#: src/exec_monitor.c:638 src/sesh.c:217 src/sudo.c:1199
+#, c-format
+msgid "unable to execute %s"
+msgstr "kunde inte köra %s"
+
+#: src/exec_nopty.c:546 src/exec_pty.c:1035
+msgid "policy plugin failed session initialization"
+msgstr "policyinsticksmodul misslyckades att initiera session"
+
+#: src/exec_nopty.c:561 src/exec_pty.c:1004 src/exec_pty.c:1013
+msgid "unable to create sockets"
+msgstr "kunde inte skapa uttag"
+
+#: src/exec_nopty.c:688 src/exec_pty.c:1274
+msgid "error in event loop"
+msgstr "fel i händelseslinga"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:851 src/sudo.c:488
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "internt fel, %s spill"
+
+#: src/exec_ptrace.c:1079 src/exec_ptrace.c:1104 src/exec_ptrace.c:1900
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "kunde inte sätta register för process %d"
+
+#: src/exec_ptrace.c:1099 src/exec_ptrace.c:1274 src/exec_ptrace.c:1616
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "process %d avslutades oväntat"
+
+#: src/exec_ptrace.c:1208
+msgid "unable to set seccomp filter"
+msgstr "kan inte sätta seccomp-filter"
+
+#: src/exec_ptrace.c:1405
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "tolkargument , förväntade \"%s\", fick \"%s\""
+
+#: src/exec_ptrace.c:1504
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "felmatchning i söknamn, förväntade \"%s\", fick \"%s\""
+
+#: src/exec_ptrace.c:1513 src/exec_ptrace.c:1520 src/exec_ptrace.c:1533
+#: src/exec_ptrace.c:1541 src/exec_ptrace.c:1547 src/exec_ptrace.c:1553
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "%s[%d] felmatchade, förväntade \"%s\", fick \"%s\""
+
+#: src/exec_ptrace.c:1620
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "process %d oväntad status 0x%x"
+
+#: src/exec_ptrace.c:1711
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "kan inte hämta händelsemeddelande för process %d"
+
+#: src/exec_ptrace.c:1718
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "kan inte hämta register för process %d"
+
+#: src/exec_pty.c:103
+msgid "unable to allocate pty"
+msgstr "kunde inte allokera pty"
+
+#: src/exec_pty.c:268 src/signal.c:101 src/suspend_nopty.c:99
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "kunde inte återställa hanterare för signal %d"
+
+#: src/exec_pty.c:1222
+msgid "unable to send message to monitor process"
+msgstr "kan inte skicka meddelande till övervakningsprocess"
+
+#: src/load_plugins.c:73 src/load_plugins.c:220 src/load_plugins.c:230
+#: src/load_plugins.c:240 src/load_plugins.c:287
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "fel i %s, rad %d under inläsning av insticksmodul ”%s”"
+
+#: src/load_plugins.c:184 src/load_plugins.c:255
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "ignorerar dubblerad insticksmodul ”%s” i %s, rad %d"
+
+#: src/load_plugins.c:222
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "kunde inte läsa in %s: %s"
+
+#: src/load_plugins.c:232
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "kunde inte hitta symbol ”%s” i %s"
+
+#: src/load_plugins.c:242
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "inkompatibel huvudversion %d för insticksmodul (%d förväntades) hittad i %s"
+
+#: src/load_plugins.c:260
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "ignorerar policyinsticksmodul ”%s” i %s, rad %d"
+
+#: src/load_plugins.c:263
+msgid "only a single policy plugin may be specified"
+msgstr "bara en policyinsticksmodul kan anges"
+
+#: src/load_plugins.c:289
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "okänd insticksmodulstyp %d hittad i %s"
+
+#: src/load_plugins.c:472
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "policyinsticksmodul %s inkluderar inte en check_policy-metod"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "ogiltigt namn på miljövariabel: %s"
+
+#: src/parse_args.c:317
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "argumentet till -C måste vara ett tal större än eller lika med 3"
+
+#: src/parse_args.c:554
+msgid "you may not specify both the -i and -s options"
+msgstr "du får inte ange flaggorna -i och -s samtidigt"
+
+#: src/parse_args.c:559
+msgid "you may not specify both the -i and -E options"
+msgstr "du får inte ange flaggorna -i och -E samtidigt"
+
+#: src/parse_args.c:569
+msgid "the -E option is not valid in edit mode"
+msgstr "flaggan -E är inte giltig i redigeringsläget"
+
+#: src/parse_args.c:572
+msgid "you may not specify environment variables in edit mode"
+msgstr "du får inte ange miljövariabler i redigeringsläget"
+
+#: src/parse_args.c:582
+msgid "the -U option may only be used with the -l option"
+msgstr "flaggan -U får bara användas med flaggan -l"
+
+#: src/parse_args.c:586
+msgid "the -A and -S options may not be used together"
+msgstr "flaggorna -A och -S får inte användas tillsammans"
+
+#: src/parse_args.c:684
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit stöds inte på denna plattform"
+
+#: src/parse_args.c:767
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Endast en av flaggorna -e, -h, -i, -K, -l, -s, -v eller -V får anges"
+
+#: src/parse_args.c:780
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "Endast en av flaggorna -K, -k eller -N får anges"
+
+#: src/parse_args.c:796
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - redigera filer som en annan användare\n"
+"\n"
+
+#: src/parse_args.c:798
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - kör ett kommando som en annan användare\n"
+"\n"
+
+#: src/parse_args.c:804
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Flaggor:\n"
+
+#: src/parse_args.c:806
+msgid "use a helper program for password prompting"
+msgstr "använd hjälpprogram för att fråga efter lösenord"
+
+#: src/parse_args.c:809
+msgid "use specified BSD authentication type"
+msgstr "använd angiven BSD-autentiseringstyp"
+
+#: src/parse_args.c:813
+msgid "run command in the background"
+msgstr "kör kommando i bakgrunden"
+
+#: src/parse_args.c:816
+msgid "ring bell when prompting"
+msgstr "ring i klockan vid fråga"
+
+#: src/parse_args.c:818
+msgid "close all file descriptors >= num"
+msgstr "stäng alla fildeskriptorer >= num"
+
+#: src/parse_args.c:821
+msgid "run command with the specified BSD login class"
+msgstr "kör kommando med den angivna BSD-inloggningsklassen"
+
+#: src/parse_args.c:824
+msgid "change the working directory before running command"
+msgstr "ändra arbetskatalog innan kommando körs"
+
+#: src/parse_args.c:827
+msgid "preserve user environment when running command"
+msgstr "bevara användarens miljö när kommandot körs"
+
+#: src/parse_args.c:829
+msgid "preserve specific environment variables"
+msgstr "bevara specifika miljövariabler"
+
+#: src/parse_args.c:831
+msgid "edit files instead of running a command"
+msgstr "redigera filer istället för att köra ett kommando"
+
+#: src/parse_args.c:834
+msgid "run command as the specified group name or ID"
+msgstr "kör kommando som angivet gruppnamn eller ID"
+
+#: src/parse_args.c:837
+msgid "set HOME variable to target user's home dir"
+msgstr "ställ in HOME-variabeln till målanvändarens hemkatalog"
+
+#: src/parse_args.c:840
+msgid "display help message and exit"
+msgstr "visa hjälpmeddelande och avsluta"
+
+#: src/parse_args.c:842
+msgid "run command on host (if supported by plugin)"
+msgstr "kör kommando på värd (om det stöds av instick)"
+
+#: src/parse_args.c:845
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "kör ett inloggningsskal som målanvändaren; ett kommando kan också anges"
+
+#: src/parse_args.c:847
+msgid "remove timestamp file completely"
+msgstr "ta bort tidsstämpelfil helt"
+
+#: src/parse_args.c:850
+msgid "invalidate timestamp file"
+msgstr "ogiltigförklara tidsstämpelfil"
+
+#: src/parse_args.c:853
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "lista användarens rättigheter eller kontrollera ett specifikt kommando; använd två gånger för längre format"
+
+#: src/parse_args.c:856
+msgid "non-interactive mode, no prompts are used"
+msgstr "icke-interaktivt läge, inga frågor ställs"
+
+#: src/parse_args.c:859
+msgid "preserve group vector instead of setting to target's"
+msgstr "behåll gruppvektor istället för att ställa in den till målets"
+
+#: src/parse_args.c:862
+msgid "use the specified password prompt"
+msgstr "använd angiven lösenordsprompt"
+
+#: src/parse_args.c:864
+msgid "change the root directory before running command"
+msgstr "ändra rotkatalog innan kommando körs"
+
+#: src/parse_args.c:867
+msgid "create SELinux security context with specified role"
+msgstr "skapa SELinux-säkerhetskontext med angiven roll"
+
+#: src/parse_args.c:870
+msgid "read password from standard input"
+msgstr "läs lösenord från standard in"
+
+#: src/parse_args.c:873
+msgid "run shell as the target user; a command may also be specified"
+msgstr "kör skal som målanvändaren; ett kommando kan också anges"
+
+#: src/parse_args.c:877
+msgid "create SELinux security context with specified type"
+msgstr "skapa SELinux-säkerhetskontext med angiven typ"
+
+#: src/parse_args.c:880
+msgid "terminate command after the specified time limit"
+msgstr "avsluta kommando efter den angivna tidsgränsen"
+
+#: src/parse_args.c:883
+msgid "in list mode, display privileges for user"
+msgstr "i listläge, visa rättigheter för användaren"
+
+#: src/parse_args.c:886
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "kör kommando (eller redigera fil) som angivet användarnamn eller ID"
+
+#: src/parse_args.c:888
+msgid "display version information and exit"
+msgstr "visa versionsinformation och avsluta"
+
+#: src/parse_args.c:891
+msgid "update user's timestamp without running a command"
+msgstr "uppdatera användarens tidsstämpel utan att köra ett kommando"
+
+#: src/parse_args.c:894
+msgid "stop processing command line arguments"
+msgstr "sluta behandla kommandoradsargument"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "kan inte öppna granskningssystem"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "kan inte skicka granskningsmeddelande"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "kan inte köra fgetfilecon på %s"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s ändrade etiketter"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "kan inte återställa kontext för %s"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "kan inte öppna %s, ometiketterar inte tty"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s är inte en teckenenhet, ometiketterar inte tty"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "kan inte hämta aktuell tty-kontext, ometiketterar inte tty"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "okänd säkerhetsklass ”chr_file”, ometiketterar inte tty"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "kan inte hämta ny tty-kontext, ometiketterar inte tty"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "kan inte ställa in ny tty-kontext"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "du måste ange en roll för typen %s"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "kunde inte få tag på standardtyp för rollen %s"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "misslyckades med att få tag på ny kontext"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "misslyckades med att ställa in nya rollen %s"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "misslyckades med att ställa in nya typen %s"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s är inte en giltig kontext"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "misslyckades med att få tag på gammal kontext"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "kan inte fastställa påtvingande läge."
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "kunde inte ställa in körkontext till %s"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "kan inte ställa in kontext för nyckelskapande till %s"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "Endast en av flaggorna -c eller -i får anges"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "ogiltigt fildeskriptornummer: %s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "Flaggan -%c kan inte användas i redigeringsläge."
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "Flaggan -%c får bara användas i redigeringsläge."
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: att redigera symboliska länkar är inte tillåtet"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: att redigera filer i en skrivbar katalog är inte tillåtet"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "innehåll av redigeringssession finns kvar i %s"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "kan inte hämta grupplista"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "kunde inte spara hanterare för signal %d"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "begränsning för resurskontroll uppnådd"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "användaren ”%s” är inte medlem av projekt ”%s”"
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "den startande uppgiften är den sista"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "kunde inte gå med i projekt ”%s”"
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "ingen resurspool som accepterar standardbindningar existerar för projekt ”%s”"
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "angiven resurspool finns inte för projekt ”%s”"
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "kunde inte binda till standardresurspool för projekt ”%s”"
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "setproject misslyckades för projekt ”%s”"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "varning, tilldelning av resurskontroll misslyckades för projekt ”%s”"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo version %s\n"
+
+#: src/sudo.c:218
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Konfigurationsflaggor: %s\n"
+
+#: src/sudo.c:226
+msgid "fatal error, unable to load plugins"
+msgstr "ödesdigert fel, kunde inte läsa in insticksmoduler"
+
+#: src/sudo.c:272
+msgid "plugin did not return a command to execute"
+msgstr "insticksmodul returnerade ett kommando att exekvera"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "oväntat sudo-läge 0x%x"
+
+#: src/sudo.c:555
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "du existerar inte i %s-databasen"
+
+#: src/sudo.c:612
+msgid "unable to determine tty"
+msgstr "kan inte detektera tty"
+
+#: src/sudo.c:928
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "Flaggan \"inga nya privilegier\" är satt, vilket förhindrar sudo från att köra som root."
+
+#: src/sudo.c:930
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "Om sudo kör i en behållare, kan du behöva justera behållarkonfigurationen för att inaktivera flaggan."
+
+#: src/sudo.c:964
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s måste ägas av uid %d och ha setuid-biten inställd"
+
+#: src/sudo.c:967
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "effektivt uid är inte %d, är %s på ett filsystem med flaggan ”nosuid” inställd eller ett NFS-filsystem utan root-rättigheter?"
+
+#: src/sudo.c:973
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "effektivt uid är inte %d, har sudo installerats som setuid root?"
+
+#: src/sudo.c:989 src/tgetpass.c:331
+msgid "unable to set supplementary group IDs"
+msgstr "kan inte ställa in kompletterande grupp-ID:n"
+
+#: src/sudo.c:996
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "kunde inte ställa in effektiv gid till runas gid %u"
+
+#: src/sudo.c:1002
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "kunde inte ställa in gid för runas gid %u"
+
+#: src/sudo.c:1032
+msgid "argv not set by the security policy"
+msgstr "argv inte satt enligt säkerhetspolicyn"
+
+#: src/sudo.c:1036
+msgid "envp not set by the security policy"
+msgstr "envp inte satt enligt säkerhetspolicyn"
+
+#: src/sudo.c:1058
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "oväntat barnavslutsvillkor: %d"
+
+#: src/sudo.c:1171
+msgid "unable to initialize policy plugin"
+msgstr "kan inte initiera policy-instick"
+
+#: src/sudo.c:1233
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "policyinsticksmodul %s saknar metoden ”check_policy”"
+
+#: src/sudo.c:1279
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "policyinsticksmodul %s har inte stöd för att lista rättigheter"
+
+#: src/sudo.c:1323
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "policyinsticksmodul %s har inte stöd för flaggan -v"
+
+#: src/sudo.c:1361
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "policyinsticksmodul %s har inte stöd för flaggorna -k/-K"
+
+#: src/sudo.c:1490
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "fel vid initiering av I/O-insticksmodul %s"
+
+#: src/sudo.c:1493
+msgid "error initializing I/O plugin"
+msgstr "fel vid initiering av I/O-insticksmodul"
+
+#: src/sudo.c:1642
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "fel vid initiering av granskningsinsticksmodul %s"
+
+#: src/sudo.c:1721
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: kunde inte logga felhändelse%s%s"
+
+#: src/sudo.c:1757
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: kunde inte logga acceptanshändelse%s%s"
+
+#: src/sudo.c:1762 src/sudo.c:1800
+msgid "audit plugin error"
+msgstr "fel i audit-insticksmodul"
+
+#: src/sudo.c:1795
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: kunde inte logga avböjningshändelse%s%s"
+
+#: src/sudo.c:1855
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "fel vid initiering av godkänningsinsticksmodul %s"
+
+#: src/sudo.c:1925
+msgid "command rejected by approver"
+msgstr "kommando avböjt av godkännare"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "ingen skrivbar temporärkatalog hittad"
+
+#: src/sudo_edit.c:291
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s lämnad oförändrad"
+
+#: src/sudo_edit.c:304 src/sudo_edit.c:569
+#, c-format
+msgid "%s unchanged"
+msgstr "%s oförändrad"
+
+#: src/sudo_edit.c:481
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: internt fel: udda antal sökvägar"
+
+#: src/sudo_edit.c:483
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: kunde inte skapa temporärfiler"
+
+#: src/sudo_edit.c:485 src/sudo_edit.c:604
+msgid "sesh: killed by a signal"
+msgstr "sesh: dödad av en signal"
+
+#: src/sudo_edit.c:487 src/sudo_edit.c:607
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: okänt fel %d"
+
+#: src/sudo_edit.c:597
+msgid "unable to copy temporary files back to their original location"
+msgstr "kan inte kopiera temporära filer tillbaka till deras originalplats"
+
+#: src/sudo_edit.c:601
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "kan inte kopiera vissa av de temporära filerna tillbaka till deras originalplats"
+
+#: src/sudo_edit.c:646
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "kunde inte ändra uid till root (%u)"
+
+#: src/sudo_edit.c:660
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "insticksfel: felaktig fillista för sudoedit"
+
+#: src/sudo_edit.c:681
+msgid "plugin error: missing file list for sudoedit"
+msgstr "insticksfel: fillista för sudoedit saknas"
+
+#: src/sudo_edit.c:724 src/sudo_edit.c:739
+msgid "unable to read the clock"
+msgstr "kunde inte läsa klockan"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "infångningsport inte satt"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "tidsgräns löpte ut vid lösenordsinläsning"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "inget lösenord angavs"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "kan inte läsa lösenord"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "en terminal krävs för att läsa lösenordet; använd antingen flaggan -S för att läsa från standard in, eller konfigurera en askpass-hjälpare"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "inget askpass-program angivet, prova att ställ in SUDO_ASKPASS"
+
+#: src/tgetpass.c:326
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "kunde inte ställa in gid till %u"
+
+#: src/tgetpass.c:336
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "kunde inte ställa in uid till %u"
+
+#: src/tgetpass.c:341
+#, c-format
+msgid "unable to run %s"
+msgstr "kunde inte köra %s"
+
+#: src/utmp.c:288
+msgid "unable to save stdin"
+msgstr "kunde inte spara standard in"
+
+#: src/utmp.c:290
+msgid "unable to dup2 stdin"
+msgstr "kan inte köra dup2 på standard in"
+
+#: src/utmp.c:293
+msgid "unable to restore stdin"
+msgstr "kan inte återställa standard in"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s måste ägas av uid %d"
+
+#~ msgid "%s must be only be writable by owner"
+#~ msgstr "%s får endast vara skrivbar av ägaren"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s: %s"
+
+#~ msgid "unable to set tty context to %s"
+#~ msgstr "kunde inte ställa in tty-kontext till %s"
+
+#~ msgid "requires at least one argument"
+#~ msgstr "kräver minst ett argument"
+
+#~ msgid "unable to run %s as a login shell"
+#~ msgstr "kunde inte köra %s som ett inloggningsskal"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s: kort skrivning"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "kunde inte läsa temporärfil"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "ignorerar dubblerad policyinsticksmodul ”%s” i %s, rad %d"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "ingen tty finns tillgänglig och inget askpass-program angivet"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "okänt uid %u: vem är du?"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "fel vid läsning från signalrör"
+
+#~ msgid ": "
+#~ msgstr ": "
+
+#~ msgid "load_interfaces: overflow detected"
+#~ msgstr "load_interfaces: stackspill upptäcktes"
+
+#~ msgid "unable to open socket"
+#~ msgstr "kunde inte öppna uttag"
+
+#~ msgid "list user's available commands\n"
+#~ msgstr "lista användarens tillgängliga kommandon\n"
+
+#~ msgid "run a shell as target user\n"
+#~ msgstr "kör ett skal som målanvändaren\n"
+
+#~ msgid "must be setuid root"
+#~ msgstr "måste vara setuid root"
+
+#~ msgid "internal error, tried to emalloc(0)"
+#~ msgstr "internt fel, försökte med emalloc(0)"
+
+#~ msgid "internal error, tried to emalloc2(0)"
+#~ msgstr "internt fel, försökte med emalloc2(0)"
+
+#~ msgid "internal error, tried to erealloc(0)"
+#~ msgstr "internt fel, försökte med erealloc(0)"
+
+#~ msgid "internal error, tried to erealloc3(0)"
+#~ msgstr "internt fel, försökte med erealloc3(0)"
+
+#~ msgid "internal error, erealloc3() overflow"
+#~ msgstr "internt fel, stackspill i erealloc3()"
diff --git a/po/tr.mo b/po/tr.mo
new file mode 100644
index 0000000..b447fc2
--- /dev/null
+++ b/po/tr.mo
Binary files differ
diff --git a/po/tr.po b/po/tr.po
new file mode 100644
index 0000000..63217d5
--- /dev/null
+++ b/po/tr.po
@@ -0,0 +1,1143 @@
+# This file is put in the public domain.
+# This file is distributed under the same license as the sudo package.
+# Volkan Gezer <vlkngzr@gmail.com>, 2013, 2015.
+# Mehmet Kececi <mkececi@mehmetkececi.com>, 2016, 2017, 2018, 2019, 2020, 2021.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.9b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2021-12-08 10:19-0700\n"
+"PO-Revision-Date: 2021-12-17 11:59+0300\n"
+"Last-Translator: Mehmet Kececi <mkececi@mehmetkececi.com>\n"
+"Language-Team: Turkish <gnome-turk@gnome.org>\n"
+"Language: tr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Poedit 3.0.1\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "userdb açılamıyor"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "\"%s\" kaydına %s için geçiş yapılamıyor"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "kayıt geri yüklenemiyor"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:54 lib/util/json.c:183 lib/util/sudo_conf.c:218
+#: lib/util/sudo_conf.c:304 lib/util/sudo_conf.c:381 lib/util/sudo_conf.c:665
+#: src/conversation.c:80 src/exec_monitor.c:206 src/exec_monitor.c:456
+#: src/exec_monitor.c:462 src/exec_monitor.c:470 src/exec_monitor.c:478
+#: src/exec_monitor.c:485 src/exec_monitor.c:492 src/exec_monitor.c:499
+#: src/exec_monitor.c:506 src/exec_monitor.c:513 src/exec_monitor.c:520
+#: src/exec_monitor.c:527 src/exec_nopty.c:219 src/exec_nopty.c:228
+#: src/exec_nopty.c:235 src/exec_nopty.c:242 src/exec_nopty.c:249
+#: src/exec_nopty.c:256 src/exec_nopty.c:263 src/exec_nopty.c:270
+#: src/exec_nopty.c:277 src/exec_nopty.c:284 src/exec_nopty.c:291
+#: src/exec_nopty.c:298 src/exec_nopty.c:306 src/exec_nopty.c:503
+#: src/exec_preload.c:143 src/exec_preload.c:204 src/exec_pty.c:840
+#: src/exec_pty.c:849 src/exec_pty.c:906 src/exec_pty.c:1059
+#: src/exec_pty.c:1231 src/exec_pty.c:1240 src/exec_pty.c:1247
+#: src/exec_pty.c:1254 src/exec_pty.c:1261 src/exec_pty.c:1268
+#: src/exec_pty.c:1275 src/exec_pty.c:1282 src/exec_pty.c:1289
+#: src/exec_pty.c:1296 src/exec_pty.c:1303 src/exec_pty.c:1311
+#: src/exec_pty.c:1774 src/load_plugins.c:156 src/load_plugins.c:181
+#: src/load_plugins.c:217 src/load_plugins.c:449 src/load_plugins.c:455
+#: src/parse_args.c:190 src/parse_args.c:211 src/parse_args.c:285
+#: src/parse_args.c:630 src/parse_args.c:652 src/parse_args.c:677
+#: src/preserve_fds.c:46 src/preserve_fds.c:131 src/selinux.c:89
+#: src/selinux.c:369 src/selinux.c:489 src/selinux.c:498 src/sesh.c:113
+#: src/sesh.c:146 src/sesh.c:152 src/sesh.c:159 src/sesh.c:165 src/sesh.c:410
+#: src/sudo.c:636 src/sudo.c:706 src/sudo.c:716 src/sudo.c:741 src/sudo.c:764
+#: src/sudo.c:773 src/sudo.c:782 src/sudo.c:799 src/sudo.c:849 src/sudo.c:859
+#: src/sudo.c:888 src/sudo.c:1087 src/sudo.c:1108 src/sudo.c:1401
+#: src/sudo.c:1570 src/sudo.c:1797 src/sudo.c:2131 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:429 src/sudo_edit.c:438
+#: src/sudo_edit.c:539 src/sudo_edit.c:546 src/sudo_edit.c:677
+#: src/sudo_edit.c:697 src/sudo_intercept_common.c:113
+#: src/sudo_intercept_common.c:317
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:55
+#: lib/util/json.c:184 lib/util/sudo_conf.c:219 lib/util/sudo_conf.c:304
+#: lib/util/sudo_conf.c:381 lib/util/sudo_conf.c:665 src/conversation.c:81
+#: src/exec_intercept.c:100 src/exec_intercept.c:330 src/exec_intercept.c:354
+#: src/exec_intercept.c:377 src/exec_intercept.c:385 src/exec_intercept.c:410
+#: src/exec_intercept.c:416 src/exec_intercept.c:425 src/exec_intercept.c:431
+#: src/exec_intercept.c:565 src/exec_intercept.c:706 src/exec_monitor.c:456
+#: src/exec_monitor.c:462 src/exec_monitor.c:470 src/exec_monitor.c:478
+#: src/exec_monitor.c:485 src/exec_monitor.c:492 src/exec_monitor.c:499
+#: src/exec_monitor.c:506 src/exec_monitor.c:513 src/exec_monitor.c:520
+#: src/exec_monitor.c:527 src/exec_nopty.c:219 src/exec_nopty.c:228
+#: src/exec_nopty.c:235 src/exec_nopty.c:242 src/exec_nopty.c:249
+#: src/exec_nopty.c:256 src/exec_nopty.c:263 src/exec_nopty.c:270
+#: src/exec_nopty.c:277 src/exec_nopty.c:284 src/exec_nopty.c:291
+#: src/exec_nopty.c:298 src/exec_nopty.c:306 src/exec_preload.c:143
+#: src/exec_preload.c:204 src/exec_pty.c:840 src/exec_pty.c:849
+#: src/exec_pty.c:906 src/exec_pty.c:1231 src/exec_pty.c:1240
+#: src/exec_pty.c:1247 src/exec_pty.c:1254 src/exec_pty.c:1261
+#: src/exec_pty.c:1268 src/exec_pty.c:1275 src/exec_pty.c:1282
+#: src/exec_pty.c:1289 src/exec_pty.c:1296 src/exec_pty.c:1303
+#: src/exec_pty.c:1311 src/exec_pty.c:1774 src/load_plugins.c:156
+#: src/load_plugins.c:181 src/load_plugins.c:217 src/load_plugins.c:449
+#: src/load_plugins.c:455 src/parse_args.c:190 src/parse_args.c:212
+#: src/parse_args.c:285 src/parse_args.c:630 src/parse_args.c:652
+#: src/parse_args.c:677 src/preserve_fds.c:46 src/preserve_fds.c:131
+#: src/selinux.c:89 src/selinux.c:369 src/selinux.c:489 src/selinux.c:498
+#: src/sesh.c:113 src/sesh.c:411 src/sudo.c:227 src/sudo.c:636 src/sudo.c:888
+#: src/sudo.c:1087 src/sudo.c:1108 src/sudo.c:1401 src/sudo.c:1570
+#: src/sudo.c:1797 src/sudo.c:2131 src/sudo_edit.c:89 src/sudo_edit.c:149
+#: src/sudo_edit.c:429 src/sudo_edit.c:438 src/sudo_edit.c:539
+#: src/sudo_edit.c:546 src/sudo_edit.c:677 src/sudo_edit.c:697
+#: src/sudo_intercept_common.c:113 src/sudo_intercept_common.c:317
+msgid "unable to allocate memory"
+msgstr "bellek ayırma başarısız"
+
+#: lib/util/mkdir_parents.c:68 lib/util/sudo_conf.c:704 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:368 src/sudo_edit.c:494 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "%s açılamıyor"
+
+#: lib/util/mkdir_parents.c:83
+#, c-format
+msgid "unable to mkdir %s"
+msgstr "mkdir %s için olanaksız"
+
+#: lib/util/mkdir_parents.c:92 lib/util/sudo_conf.c:681 src/copy_file.c:150
+#, c-format
+msgid "unable to stat %s"
+msgstr "%s durumlanamıyor"
+
+#: lib/util/mkdir_parents.c:97
+#, c-format
+msgid "%s exists but is not a directory (0%o)"
+msgstr "%s var ancak bir dizin değil (0%o)"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Bilinmeyen sinyal"
+
+#: lib/util/strtoid.c:87 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:146 src/sesh.c:159
+msgid "invalid value"
+msgstr "geçersiz değer"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "değer çok büyük"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "değer çok küçük"
+
+#: lib/util/sudo_conf.c:237
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "geçersiz Yol değeri %s içinde \"%s\", satır %u"
+
+#: lib/util/sudo_conf.c:403 lib/util/sudo_conf.c:419 lib/util/sudo_conf.c:472
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "%s \"%s\" için geçersiz değer, %s içinde, satır %u"
+
+#: lib/util/sudo_conf.c:440
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "\"%s\" desteklenmeyen grup kaynağı, %s içinde, satır %u"
+
+#: lib/util/sudo_conf.c:456
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "`\"%s\" geçersiz azami grubu, %s içinde, satır %u"
+
+#: lib/util/sudo_conf.c:684
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s düzenli bir dosya değil"
+
+#: lib/util/sudo_conf.c:687 src/copy_file.c:163
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s, %u kullanıcı kimliği tarafından sahiplenmiş, %u olmalı"
+
+#: lib/util/sudo_conf.c:691
+#, c-format
+msgid "%s is world writable"
+msgstr "%s genel yazılabilir"
+
+#: lib/util/sudo_conf.c:694
+#, c-format
+msgid "%s is group writable"
+msgstr "%s grup yazılabilir"
+
+#: src/copy_file.c:93
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: %s sıfır bayta indirilsin mi? (e/h) [h] "
+
+#: src/copy_file.c:97
+#, c-format
+msgid "not overwriting %s"
+msgstr "%s üzerine yazılmıyor"
+
+#: src/copy_file.c:119
+#, c-format
+msgid "unable to read from %s"
+msgstr "%s öğesinden okunamıyor"
+
+#: src/copy_file.c:136 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "%s dosyasına yazılamıyor"
+
+#: src/copy_file.c:154 src/sesh.c:218 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: düzenli bir dosya değil"
+
+#: src/copy_file.c:158
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: bozuk dosya modu: 0%o"
+
+#: src/edit_open.c:331
+msgid "unable to restore current working directory"
+msgstr "geçerli çalışma klasörü geri yüklenemiyor"
+
+#: src/exec.c:130
+#, c-format
+msgid "unknown login class %s"
+msgstr "bilinmeyen %s oturum sınıfı"
+
+#: src/exec.c:142
+msgid "unable to set user context"
+msgstr "kullanıcı bağlamı ayarlama başarısız"
+
+#: src/exec.c:158
+msgid "unable to set process priority"
+msgstr "süreç önceliği ayarlanamıyor"
+
+#: src/exec.c:175
+#, c-format
+msgid "unable to change root to %s"
+msgstr "kök %s olarak değiştirilemiyor"
+
+#: src/exec.c:188 src/exec.c:194 src/exec.c:201
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "runas uid (%u, %u) olarak değiştirilemiyor"
+
+#: src/exec.c:219
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "%s dizinine değiştirilemiyor"
+
+#: src/exec.c:223
+#, c-format
+msgid "starting from %s"
+msgstr "%s'den başlayarak"
+
+#: src/exec.c:305 src/exec_monitor.c:565 src/exec_monitor.c:567
+#: src/exec_nopty.c:561 src/exec_pty.c:581 src/exec_pty.c:1411
+#: src/exec_pty.c:1413 src/signal.c:144 src/signal.c:151 src/signal.c:165
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "sinyal %d için işleyici ayarlanamıyor"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "kaynak PRIV_LIMIT'dan PRIV_PROC_EXEC kaldırılamıyor"
+
+#: src/exec_intercept.c:112 src/exec_intercept.c:116 src/exec_intercept.c:667
+#: src/exec_intercept.c:671 src/exec_intercept.c:857 src/exec_intercept.c:861
+#: src/exec_intercept.c:872 src/exec_intercept.c:876 src/exec_monitor.c:464
+#: src/exec_monitor.c:472 src/exec_monitor.c:480 src/exec_monitor.c:487
+#: src/exec_monitor.c:494 src/exec_monitor.c:501 src/exec_monitor.c:508
+#: src/exec_monitor.c:515 src/exec_monitor.c:522 src/exec_monitor.c:529
+#: src/exec_nopty.c:221 src/exec_nopty.c:230 src/exec_nopty.c:237
+#: src/exec_nopty.c:244 src/exec_nopty.c:251 src/exec_nopty.c:258
+#: src/exec_nopty.c:265 src/exec_nopty.c:272 src/exec_nopty.c:279
+#: src/exec_nopty.c:286 src/exec_nopty.c:293 src/exec_nopty.c:300
+#: src/exec_nopty.c:308 src/exec_pty.c:706 src/exec_pty.c:711
+#: src/exec_pty.c:808 src/exec_pty.c:815 src/exec_pty.c:912
+#: src/exec_pty.c:1233 src/exec_pty.c:1242 src/exec_pty.c:1249
+#: src/exec_pty.c:1256 src/exec_pty.c:1263 src/exec_pty.c:1270
+#: src/exec_pty.c:1277 src/exec_pty.c:1284 src/exec_pty.c:1291
+#: src/exec_pty.c:1298 src/exec_pty.c:1305 src/exec_pty.c:1727
+#: src/exec_pty.c:1737 src/exec_pty.c:1782 src/exec_pty.c:1789
+#: src/exec_pty.c:1816
+msgid "unable to add event to queue"
+msgstr "olay kuyruğa eklenemedi"
+
+#: src/exec_intercept.c:314
+msgid "invalid PolicyCheckRequest"
+msgstr "geçersiz PolicyCheckRequest"
+
+#: src/exec_intercept.c:362 src/sudo.c:1213 src/sudo.c:1258 src/sudo.c:1302
+msgid "command rejected by policy"
+msgstr "komut politika tarafından reddedildi"
+
+#: src/exec_intercept.c:455 src/sudo.c:1218 src/sudo.c:1263 src/sudo.c:1307
+#: src/sudo.c:1381
+msgid "policy plugin error"
+msgstr "politika eklentisi hatası"
+
+#: src/exec_intercept.c:561
+#, c-format
+msgid "client request too large: %zu"
+msgstr "iistemci isteği çok büyük: %zu"
+
+#: src/exec_intercept.c:659
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "type_case değeri %d %s içinde %s öğesinden beklenmeyen"
+
+#: src/exec_intercept.c:694
+#, c-format
+msgid "server message too large: %zu"
+msgstr "sunucu iletisi çok büyük: %zu"
+
+#: src/exec_monitor.c:360
+msgid "error reading from socketpair"
+msgstr "sockerpair'den okuma hatası"
+
+#: src/exec_monitor.c:377
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "backchannel'da beklenmeyen yanıt türü: %d"
+
+#: src/exec_monitor.c:583
+msgid "unable to set controlling tty"
+msgstr "tty denetleme ayarlaması başarısız"
+
+#: src/exec_monitor.c:591 src/exec_nopty.c:369 src/exec_pty.c:1490
+#: src/exec_pty.c:1511 src/exec_pty.c:1531 src/tgetpass.c:307
+msgid "unable to create pipe"
+msgstr "iletişim tüneli oluşturulamıyor"
+
+#: src/exec_monitor.c:601
+msgid "unable to receive message from parent"
+msgstr "ebeveynden mesaj alamıyor"
+
+#: src/exec_monitor.c:617 src/exec_nopty.c:407 src/exec_pty.c:1569
+#: src/sudo_edit.c:361 src/tgetpass.c:311
+msgid "unable to fork"
+msgstr "çatallanamıyor"
+
+#: src/exec_monitor.c:621 src/exec_monitor.c:722 src/exec_nopty.c:471
+msgid "unable to restore tty label"
+msgstr "tty etiketi geri yüklenemiyor"
+
+#: src/exec_monitor.c:637 src/sesh.c:123 src/sudo.c:1164
+#, c-format
+msgid "unable to execute %s"
+msgstr "%s çalıştırılamıyor"
+
+#: src/exec_nopty.c:363 src/exec_pty.c:1420
+msgid "policy plugin failed session initialization"
+msgstr "oturum başlatma için ilke eklentisi başarısız"
+
+#: src/exec_nopty.c:377 src/exec_pty.c:1391 src/exec_pty.c:1399
+msgid "unable to create sockets"
+msgstr "soket oluşturulamıyor"
+
+#: src/exec_nopty.c:459 src/exec_pty.c:1666
+msgid "error in event loop"
+msgstr "olay döngüsünde hata"
+
+#: src/exec_nopty.c:569 src/exec_pty.c:619 src/signal.c:101
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "sinyal %d için işleyici geri yüklenemiyor"
+
+#: src/exec_pty.c:158
+msgid "unable to allocate pty"
+msgstr "pty ayırma başarısız"
+
+#: src/exec_pty.c:222 src/exec_pty.c:262 src/exec_pty.c:302 src/exec_pty.c:353
+#: src/exec_pty.c:404
+msgid "I/O plugin error"
+msgstr "G/Ç eklenti hatası"
+
+#: src/exec_pty.c:226 src/exec_pty.c:266 src/exec_pty.c:306 src/exec_pty.c:357
+#: src/exec_pty.c:408
+msgid "command rejected by I/O plugin"
+msgstr "komut G/Ç eklentisi tarafından reddedildi"
+
+#: src/exec_pty.c:455
+msgid "error logging suspend"
+msgstr "günlüğü askıya alma hatası"
+
+#: src/exec_pty.c:489
+msgid "error changing window size"
+msgstr "pencere boyutunu değiştirme hatası"
+
+#: src/exec_pty.c:1615
+msgid "unable to send message to monitor process"
+msgstr "süreci izlemek için mesaj gönderilemiyor"
+
+#: src/load_plugins.c:108 src/load_plugins.c:122 src/load_plugins.c:128
+#: src/load_plugins.c:277 src/load_plugins.c:287 src/load_plugins.c:297
+#: src/load_plugins.c:344
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "\"%s\" eklentisi yüklenirken satır %d, %s içerisinde hata"
+
+#: src/load_plugins.c:124
+#, c-format
+msgid "%s must be owned by uid %d"
+msgstr "%s, %d kullanıcı kimliği tarafından sahiplenmeli"
+
+#: src/load_plugins.c:130
+#, c-format
+msgid "%s must be only be writable by owner"
+msgstr "%s sadece sahibi tarafından yazılabilir olmalı"
+
+#: src/load_plugins.c:241 src/load_plugins.c:312
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "%s içinde \"%s\" yinelenen eklentisini yok sayılıyor, %d satırı"
+
+#: src/load_plugins.c:279
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "%s yüklenemedi: %s"
+
+#: src/load_plugins.c:289
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "%s içerisinde \"%s\" sembolü bulunamıyor"
+
+#: src/load_plugins.c:299
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "uyumsuz temel ilke sürümü %d bulundu (beklenen %d) %s içerisinde"
+
+#: src/load_plugins.c:317
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "\"%s\" ilke eklentisi ihmal ediliyor, %s içinde, satır %d"
+
+#: src/load_plugins.c:320
+msgid "only a single policy plugin may be specified"
+msgstr "sadece tek ilke eklentisi belirtilebilir"
+
+#: src/load_plugins.c:346
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "bilinmeyen eklenti türü %d %s içinde bulundu"
+
+#: src/load_plugins.c:529
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "%s ilke eklentisi, bir check_policy yöntemi içermiyor"
+
+#: src/net_ifs.c:210 src/net_ifs.c:376 src/net_ifs.c:437 src/net_ifs.c:624
+#: src/net_ifs.c:855 src/sudo.c:483 src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "dahili hata, %s taşması"
+
+#: src/parse_args.c:232
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "geçersiz çevre değişken adı: %s"
+
+#: src/parse_args.c:335
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "-C argümanı 3 veya daha büyük bir sayı olmalıdır"
+
+#: src/parse_args.c:566
+msgid "you may not specify both the -i and -s options"
+msgstr "-i ve -s seçeneklerini aynı anda belirtemezsiniz"
+
+#: src/parse_args.c:571
+msgid "you may not specify both the -i and -E options"
+msgstr "-i ve -E seçeneklerini aynı anda belirtemezsiniz"
+
+#: src/parse_args.c:581
+msgid "the -E option is not valid in edit mode"
+msgstr "düzenleme kipinde -E seçeneği geçerli değil"
+
+#: src/parse_args.c:584
+msgid "you may not specify environment variables in edit mode"
+msgstr "düzenleme kipinde ortam değişkenlerini belirtemezsiniz"
+
+#: src/parse_args.c:594
+msgid "the -U option may only be used with the -l option"
+msgstr "-U seçeneği sadece -l seçeneği ile kullanılabilir"
+
+#: src/parse_args.c:598
+msgid "the -A and -S options may not be used together"
+msgstr "-A ve -S seçenekleri birlikte kullanılamaz"
+
+#: src/parse_args.c:691
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit bu platformda desteklenmiyor"
+
+#: src/parse_args.c:774
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "-e, -h, -i, -K, -l, -s, -v veya -V seçeneklerinden sadece biri belirtilebilir"
+
+#: src/parse_args.c:790
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - dosyaları farklı kullanıcı olarak düzenle\n"
+"\n"
+
+#: src/parse_args.c:792
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - bir komutu farklı kullanıcı olarak çalıştır\n"
+"\n"
+
+#: src/parse_args.c:798
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Seçenekler:\n"
+
+#: src/parse_args.c:800
+msgid "use a helper program for password prompting"
+msgstr "parola sorgulaması için bir yardımcı program kullan"
+
+#: src/parse_args.c:803
+msgid "use specified BSD authentication type"
+msgstr "belirtilen BSD kimlik doğrulama türünü kullan"
+
+#: src/parse_args.c:807
+msgid "run command in the background"
+msgstr "arkaalanda komutu çalıştır"
+
+#: src/parse_args.c:810
+msgid "ring bell when prompting"
+msgstr "istendiğinde zili çal"
+
+#: src/parse_args.c:812
+msgid "close all file descriptors >= num"
+msgstr ">= sayı olan tüm dosya tanımlayıcılarını kapat"
+
+#: src/parse_args.c:815
+msgid "run command with the specified BSD login class"
+msgstr "komutu belirtilen BSD oturum sınıfı ile çalıştır"
+
+#: src/parse_args.c:818
+msgid "change the working directory before running command"
+msgstr "komutu çalıştırmadan önce çalışma dizinini değiştirin"
+
+#: src/parse_args.c:821
+msgid "preserve user environment when running command"
+msgstr "komut çalıştırılırken kullanıcı ortamını koru"
+
+#: src/parse_args.c:823
+msgid "preserve specific environment variables"
+msgstr "özel çevre değişkenlerini koru"
+
+#: src/parse_args.c:825
+msgid "edit files instead of running a command"
+msgstr "komut çalıştırmak yerine dosyaları düzenleyiniz"
+
+#: src/parse_args.c:828
+msgid "run command as the specified group name or ID"
+msgstr "grup adı veya ID olarak tanımlanan komutu çalıştır"
+
+#: src/parse_args.c:831
+msgid "set HOME variable to target user's home dir"
+msgstr "kullanıcının HOME değişkenini ana dizinini hedefleyecek şekilde ayarlama"
+
+#: src/parse_args.c:834
+msgid "display help message and exit"
+msgstr "yardım mesajını görüntüle ve çık"
+
+#: src/parse_args.c:836
+msgid "run command on host (if supported by plugin)"
+msgstr "komutunuzu hostta çalıştırın (eğer plugin tarafından destekleniyorsa)"
+
+#: src/parse_args.c:839
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "oturum kabuğunu hedef kullanıcı olarak çalıştır; bir komut da belirtilebilir"
+
+#: src/parse_args.c:841
+msgid "remove timestamp file completely"
+msgstr "zaman damgası dosyasını kalıcı olarak kaldır"
+
+#: src/parse_args.c:844
+msgid "invalidate timestamp file"
+msgstr "zaman damgası dosyasının geçerliliğini kaldır"
+
+#: src/parse_args.c:847
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "kullanıcı yetkilerini listele veya özel bir komut denetle; daha uzun biçim için iki kez kullanın"
+
+#: src/parse_args.c:850
+msgid "non-interactive mode, no prompts are used"
+msgstr "etkileşimsiz kip, sorgu yapılmaz"
+
+#: src/parse_args.c:853
+msgid "preserve group vector instead of setting to target's"
+msgstr "hedefe atamak yerine grup vektörünü koru"
+
+#: src/parse_args.c:856
+msgid "use the specified password prompt"
+msgstr "belirtilen parola sorgusunu kullan"
+
+#: src/parse_args.c:858
+msgid "change the root directory before running command"
+msgstr "komutu çalıştırmadan önce kök dizini değiştirin"
+
+#: src/parse_args.c:861
+msgid "create SELinux security context with specified role"
+msgstr "belirtilen rolle SELinux güvenlik bağlamı oluşturma"
+
+#: src/parse_args.c:864
+msgid "read password from standard input"
+msgstr "standart girdiden şifreyi okuyun"
+
+#: src/parse_args.c:867
+msgid "run shell as the target user; a command may also be specified"
+msgstr "kabuğu hedef kullanıcı olarak çalıştır; bir komut da belirtilebilir"
+
+#: src/parse_args.c:871
+msgid "create SELinux security context with specified type"
+msgstr "belirtilen türde SELinux güvenlik bağlamı oluşturma"
+
+#: src/parse_args.c:874
+msgid "terminate command after the specified time limit"
+msgstr "belirtilen süre sonunda komutu sonlandır"
+
+#: src/parse_args.c:877
+msgid "in list mode, display privileges for user"
+msgstr "liste modunda, kullanıcıların ayrıcalıklarını görüntüle"
+
+#: src/parse_args.c:880
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "belirtilen kullanıcı adı veya ID ile komutu çalıştırın (veya dosyayı düzenleyin)"
+
+#: src/parse_args.c:882
+msgid "display version information and exit"
+msgstr "sürüm bilgisini göster ve çık"
+
+#: src/parse_args.c:885
+msgid "update user's timestamp without running a command"
+msgstr "kullanıcı zaman damgasını bir komut çalıştırmadan güncelle"
+
+#: src/parse_args.c:888
+msgid "stop processing command line arguments"
+msgstr "komut satırı argümanlarını işlemeyi durdur"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "denetim sistemi açılamıyor"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "denetim iletisi gönderilemiyor"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "fgetfilecon %s yapılamıyor"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s değişmiş etiket"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "%s için bağlam geri yüklenemiyor"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "%s açılamadı, tty yeniden etiketlenemiyor"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s bir karakter aygıtı değildir, tty yeniden etiketlenemiyor"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "geçerli tty bağlamı alınamadı, tty yeniden etiketlenemiyor"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "bilinmeyen güvenlik sınıfı \"chr_file\", tty yeniden etiketlenemiyor"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "yeni tty bağlamı alınamadı, tty yeniden etiketlenemiyor"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "yeni tty bağlamı alınamıyor"
+
+#: src/selinux.c:327
+msgid "failed to get new context"
+msgstr "yeni bağlam alınamadı"
+
+#: src/selinux.c:345
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "%s görevi için öntanımlı tür alınamıyor"
+
+#: src/selinux.c:357
+#, c-format
+msgid "failed to set new role %s"
+msgstr "%s yeni görevi atanamadı"
+
+#: src/selinux.c:361
+#, c-format
+msgid "failed to set new type %s"
+msgstr "yeni tür %s atanamadı"
+
+#: src/selinux.c:373
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s geçerli bir bağlam değil"
+
+#: src/selinux.c:402
+msgid "failed to get old context"
+msgstr "eski bağlam alınamadı"
+
+#: src/selinux.c:408
+msgid "unable to determine enforcing mode."
+msgstr "zorlama kipini belirleme başarısız."
+
+#: src/selinux.c:440
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "%s için exec bağlamı ayarlanamıyor"
+
+#: src/selinux.c:447
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "%s için anahtar oluşturma bağlamı ayarlanamıyor"
+
+#: src/sesh.c:72
+msgid "requires at least one argument"
+msgstr "en az bir argüman gerektirir"
+
+#: src/sesh.c:104
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "geçersiz dosya tanımlayıcı sayısı: %s"
+
+#: src/sesh.c:118
+#, c-format
+msgid "unable to run %s as a login shell"
+msgstr "bir oturum açma kabuğu gibi %s çalıştırılamıyor"
+
+#: src/sesh.c:200 src/sesh.c:300 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: sembolik bağlantı düzenlemesine izin verilmemiştir"
+
+#: src/sesh.c:203 src/sesh.c:303 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: yazılabilir klasördeki düzenleme dosyalarına izin verilmemiştir"
+
+#: src/sesh.c:287 src/sesh.c:308 src/sesh.c:317 src/sesh.c:325
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "düzenleme oturumu içerikleri %s içinde bırakıldı"
+
+#: src/sesh.c:416 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "grup listesi alınamıyor"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "%d için işleyici kaydedilemiyor"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "kaynak denetim sınırına ulaşıldı"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "\"%s\", bir \"%s\" projesi üyesi değil"
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "çağırılan görev son"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "\"%s\" projesine katılamadı"
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "\"%s\" projesi için hiçbir kaynak havuzu varsayılan atamaları kabul etmiyor"
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "belirtilen kaynak havuzu \"%s\" projesi için mevcut değil"
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "\"%s\" projesi için öntanımlı kaynak havuzu atanamadı"
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "\"%s\" projesi için setproject başarısız"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "uyarı, \"%s\" projesi için kaynak denetim ataması başarısız"
+
+#: src/sudo.c:213
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo sürüm %s\n"
+
+#: src/sudo.c:215
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Yapılandırma seçenekleri: %s\n"
+
+#: src/sudo.c:223
+msgid "fatal error, unable to load plugins"
+msgstr "ölümcül hata, eklentiler yüklenemiyor"
+
+#: src/sudo.c:269
+msgid "plugin did not return a command to execute"
+msgstr "eklenti çalıştırmak için bir komut döndürmedi"
+
+#: src/sudo.c:302
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "beklenmeyen 0x%x sudo kipi"
+
+#: src/sudo.c:550
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "sen %s veritabanında yoksun"
+
+#: src/sudo.c:607
+msgid "unable to determine tty"
+msgstr "tty belirlenemiyor"
+
+#: src/sudo.c:948
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s, %d kullanıcı kimliği tarafından sahiplenmeli ve setuid biti ayarlanmış olmalı"
+
+#: src/sudo.c:951
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "etkin kullanıcı kimliği %d değil, %s 'nosuid' seçeneği ayarlanmış bir dosya sisteminde veya yetkisiz haklara sahip bir NFS dosya sisteminde mi?"
+
+#: src/sudo.c:957
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "etkin kullanıcı kimliği %d değil, sudo setuid root ile mi yüklendi?"
+
+#: src/sudo.c:973 src/tgetpass.c:333
+msgid "unable to set supplementary group IDs"
+msgstr "ek grup kimlikleri ayarlanamıyor"
+
+#: src/sudo.c:980
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "etkin grup kimliği, runas gid %u olarak ayarlanamıyor"
+
+#: src/sudo.c:986
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "grup kimliği, runas gid %u olarak ayarlanamıyor"
+
+#: src/sudo.c:1029
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "beklenmeyen alt sonlandırma şartı: %d"
+
+#: src/sudo.c:1136
+msgid "unable to initialize policy plugin"
+msgstr "ilke eklentisi başlatılamıyor"
+
+#: src/sudo.c:1198
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "%s ilke eklentisi, bir \"check_policy\" yöntemi içermiyor"
+
+#: src/sudo.c:1244
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "%s ilke eklentisi listeleme yetkilerini desteklemiyor"
+
+#: src/sudo.c:1288
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "%s ilke eklentisi -v seçeneğini desteklemiyor"
+
+#: src/sudo.c:1326
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "%s ilke eklentisi -k/-K seçeneklerini desteklemiyor"
+
+#: src/sudo.c:1455
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "başlatma hatası G/Ç eklentisi %s"
+
+#: src/sudo.c:1458
+msgid "error initializing I/O plugin"
+msgstr "eklenti I/O başlatırken hata oluştu"
+
+#: src/sudo.c:1607
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "başlatma hatası I/O eklentisi %s"
+
+#: src/sudo.c:1686
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: hata etkinlik kaydı yüklenemiyor%s%s"
+
+#: src/sudo.c:1722
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: kabul etkinlik kaydı yüklenemiyor%s%s"
+
+#: src/sudo.c:1727 src/sudo.c:1765
+msgid "audit plugin error"
+msgstr "denetim eklentisi hatası"
+
+#: src/sudo.c:1760
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: reddetme etkinlik kaydı yüklenemiyor%s%s"
+
+#: src/sudo.c:1820
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "onay eklentisini %s başlatma hatası"
+
+#: src/sudo.c:1890
+msgid "command rejected by approver"
+msgstr "onaylayan tarafından komut reddedildi"
+
+#: src/sudo.c:1900
+msgid "approval plugin error"
+msgstr "onay eklentisi hatası"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "yazılabilir geçici dizin bulunamadı"
+
+#: src/sudo_edit.c:291
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s düzenlenmemiş olarak bırakıldı"
+
+#: src/sudo_edit.c:304 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s değiştirilmemiş"
+
+#: src/sudo_edit.c:481
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: iç hata: yolların tek sayısı"
+
+#: src/sudo_edit.c:483
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: geçici dosyalar oluşturulamıyor"
+
+#: src/sudo_edit.c:485 src/sudo_edit.c:609
+msgid "sesh: killed by a signal"
+msgstr "sesh: bir sinyal tarafından ortadan kaldırıldı"
+
+#: src/sudo_edit.c:487 src/sudo_edit.c:612
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: bilinmeyen hata %d"
+
+#: src/sudo_edit.c:602
+msgid "unable to copy temporary files back to their original location"
+msgstr "geçici dosyalar onların özgün konumlarına kopyalanamıyor"
+
+#: src/sudo_edit.c:606
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "bazı geçici dosyalar onların özgün konumlarına kopyalanamıyor"
+
+#: src/sudo_edit.c:649
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "kullanıcı kimliği yetkili (%u) olarak değiştirilemiyor"
+
+#: src/sudo_edit.c:670
+msgid "plugin error: missing file list for sudoedit"
+msgstr "eklenti hatası: sudoedit için eksik dosya listesi"
+
+#: src/sudo_edit.c:713 src/sudo_edit.c:727
+msgid "unable to read the clock"
+msgstr "saat okunamıyor"
+
+#: src/sudo_intercept_common.c:341
+msgid "intercept port not set"
+msgstr "kesme bağlantı portu ayarlı değil"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "şifre okuma zaman aşımına uğradı"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "şifre sağlanmadı"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "parola okunamıyor"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "şifreyi okumak için bir terminal gereklidir; ya standart girdiden okumak için -S seçeneğini kullanın ya da bir askpass yardımcısı yapılandırın"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "askpass programı belirtilmemiş, SUDO_ASKPASS ayarlamayı deneyin"
+
+#: src/tgetpass.c:328
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "grup kimliği %u olarak ayarlanamıyor"
+
+#: src/tgetpass.c:338
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "kullanıcı kimliği %u olarak ayarlanamıyor"
+
+#: src/tgetpass.c:343
+#, c-format
+msgid "unable to run %s"
+msgstr "%s çalıştırılamıyor"
+
+#: src/utmp.c:288
+msgid "unable to save stdin"
+msgstr "stdin kaydedilemiyor"
+
+#: src/utmp.c:290
+msgid "unable to dup2 stdin"
+msgstr "dup2 stdin yapılamıyor"
+
+#: src/utmp.c:293
+msgid "unable to restore stdin"
+msgstr "stdin geri yüklenemiyor"
+
+#~ msgid "unable to dup intercept fd"
+#~ msgstr "dup fd'yi engelleyemiyor"
+
+#~ msgid "%s: missing message header"
+#~ msgstr "%s: ileti üstbilgisi eksik"
+
+#~ msgid "%s: expected message type %d, got %d"
+#~ msgstr "%s: %d beklenen ileti türü, %d alındı"
+
+#~ msgid "you must specify a role for type %s"
+#~ msgstr "%s türü için bir görev belirtmelisiniz"
+
+#~ msgid "unable to set tty context to %s"
+#~ msgstr "tty bağlamı %s olarak ayarlanamadı"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s: %s"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s: kısa yazım"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "geçici dosya okunamıyor"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "yinelenmiş \"%s\" ilke eklentisi ihmal ediliyor, %s içinde, satır %d"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "tty bulunmuyor ve askpass programı belirtilmemiş"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "bilinmeyen kullanıcı kimliği %u: kimsiniz?"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "sinyal tünelinden okuma hatası"
+
+#, fuzzy
+#~| msgid "internal error, tried to emalloc(0)"
+#~ msgid "internal error, tried allocate zero bytes"
+#~ msgstr "dahili hata, emalloc(0) denendi"
+
+#~ msgid "unable to set terminal to raw mode"
+#~ msgstr "uçbirim ham kipine ayarlanamıyor"
+
+#~ msgid "unable to open socket"
+#~ msgstr "soket açılamıyor"
+
+#~ msgid "internal error, tried to emalloc2(0)"
+#~ msgstr "dahili hata, emalloc2(0) denendi"
+
+#~ msgid "internal error, tried to ecalloc(0)"
+#~ msgstr "dahili hata, ecalloc() denendi"
+
+#~ msgid "internal error, tried to erealloc(0)"
+#~ msgstr "dahili hata, erealloc() denendi"
+
+#~ msgid "internal error, tried to erealloc3(0)"
+#~ msgstr "dahili hata, erealloc3() denendi"
+
+#~ msgid "internal error, tried to erecalloc(0)"
+#~ msgstr "dahili hata, erecalloc() denendi"
+
+#~ msgid "%s: %s: %s\n"
+#~ msgstr "%s: %s: %s\n"
+
+#~ msgid "%s: %s\n"
+#~ msgstr "%s: %s\n"
+
+#~ msgid "select failed"
+#~ msgstr "seçim başarısız"
+
+#~ msgid "load_interfaces: overflow detected"
+#~ msgstr "load_interfaces: taşma tespit edildi"
+
+#~ msgid "list user's available commands\n"
+#~ msgstr "kullanıcının kullanılabilir komutlarını listele\n"
+
+#~ msgid "run a shell as target user\n"
+#~ msgstr "hedef kullanıcı olarak bir kabuk çalıştır\n"
+
+#~ msgid "when listing, list specified user's privileges\n"
+#~ msgstr "listelerken, belirtilen kullanıcının haklarını listele\n"
+
+#~ msgid ": "
+#~ msgstr ": "
diff --git a/po/uk.mo b/po/uk.mo
new file mode 100644
index 0000000..3ad763a
--- /dev/null
+++ b/po/uk.mo
Binary files differ
diff --git a/po/uk.po b/po/uk.po
new file mode 100644
index 0000000..cf305c3
--- /dev/null
+++ b/po/uk.po
@@ -0,0 +1,1247 @@
+# Ukrainian translation for sudo.
+# This file is put in the public domain.
+#
+# Yuri Chornoivan <yurchor@ukr.net>, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.14b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-06-07 13:27-0600\n"
+"PO-Revision-Date: 2023-06-08 19:29+0300\n"
+"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
+"Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\n"
+"Language: uk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Lokalize 20.12.0\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "не вдалося відкрити userdb"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "не вдалося перемкнутися на регістр «%s» для %s"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "не вдалося відновити регістр"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:78 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:171 src/exec_monitor.c:418
+#: src/exec_monitor.c:424 src/exec_monitor.c:432 src/exec_monitor.c:440
+#: src/exec_monitor.c:447 src/exec_monitor.c:454 src/exec_monitor.c:461
+#: src/exec_monitor.c:468 src/exec_monitor.c:475 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:744 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1096
+#: src/exec_ptrace.c:1271 src/exec_ptrace.c:1624 src/exec_ptrace.c:1651
+#: src/exec_ptrace.c:1841 src/exec_pty.c:581 src/exec_pty.c:765
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:193 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:240
+#: src/sesh.c:246 src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:644
+#: src/sudo.c:709 src/sudo.c:719 src/sudo.c:746 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:787 src/sudo.c:805 src/sudo.c:846 src/sudo.c:855 src/sudo.c:865
+#: src/sudo.c:898 src/sudo.c:1127 src/sudo.c:1148 src/sudo.c:1441
+#: src/sudo.c:1610 src/sudo.c:1837 src/sudo.c:2171 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:430 src/sudo_edit.c:439
+#: src/sudo_edit.c:540 src/sudo_edit.c:547 src/sudo_edit.c:692
+#: src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:79 src/exec_intercept.c:111 src/exec_intercept.c:350
+#: src/exec_intercept.c:525 src/exec_intercept.c:589 src/exec_intercept.c:713
+#: src/exec_intercept.c:837 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:418 src/exec_monitor.c:424
+#: src/exec_monitor.c:432 src/exec_monitor.c:440 src/exec_monitor.c:447
+#: src/exec_monitor.c:454 src/exec_monitor.c:461 src/exec_monitor.c:468
+#: src/exec_monitor.c:475 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1651 src/exec_ptrace.c:1842 src/exec_pty.c:581
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:228 src/sudo.c:644 src/sudo.c:898 src/sudo.c:1127
+#: src/sudo.c:1148 src/sudo.c:1441 src/sudo.c:1610 src/sudo.c:1837
+#: src/sudo.c:2171 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:430
+#: src/sudo_edit.c:439 src/sudo_edit.c:540 src/sudo_edit.c:547
+#: src/sudo_edit.c:692 src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "не вдалося отримати потрібний об’єм пам’яті"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "не вдалося виконати stat для %.*s"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s існує, але не є каталогом (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:664
+#: lib/util/sudo_conf.c:683 lib/util/sudo_conf.c:710 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:495 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "не вдалося відкрити %s"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "не вдалося створити каталог %.*s"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "не вдалося відкрити %.*s"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "задовгий формальний вираз"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Невідомий сигнал"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "некоректне значення"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "надто велике значення"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "надто мале значення"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "некоректне значення Path, «%s», у %s, рядок %u"
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "некоректне значення %s, «%s», у %s, рядок %u"
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "непідтримуване джерело групи, «%s», у %s, рядок %u"
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "некоректна максимальна кількість груп, «%s», у %s, рядок %u"
+
+#: lib/util/sudo_conf.c:686
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s не є звичайним файлом"
+
+#: lib/util/sudo_conf.c:689 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s належить uid %u, має належати %u"
+
+#: lib/util/sudo_conf.c:693
+#, c-format
+msgid "%s is world writable"
+msgstr "Запис до «%s» можливий для довільного користувача"
+
+#: lib/util/sudo_conf.c:696
+#, c-format
+msgid "%s is group writable"
+msgstr "Запис до «%s» може здійснювати будь-який користувач з групи"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "не вдалося визначити контейнер AppArmor"
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "не вдалося змінити профіль AppArmor на %s"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: обрізати %s до нуля байтів? (y/n) [n] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "не перезаписуємо %s"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "не вдалося виконати читання з %s"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "не вдалося виконати запис до %s"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "не вдалося виконати stat для %s"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: не є звичайним файлом"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: помилковий режим доступу до файла: 0%o"
+
+#: src/edit_open.c:333
+msgid "unable to restore current working directory"
+msgstr "не вдалося відновити поточний робочий каталог"
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "не вдалося встановити привілеї"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "не вдалося встановити привілеї щодо обмеження"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "невідомий клас входу %s"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "не вдалося встановити контекст користувача"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "не вдалося встановити пріоритет процесу"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "не вдалося змінити root на %s"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "не вдалося змінити uid користувача, від імені якого відбувається виконання (%u, %u)"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "не вдалося змінити каталог на %s"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "починаючи з %s"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:552 src/exec_monitor.c:554
+#: src/exec_pty.c:1122 src/exec_pty.c:1124 src/signal.c:144 src/signal.c:151
+#: src/signal.c:165 src/suspend_parent.c:143
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "не вдалося встановити обробник для сигналу %d"
+
+#: src/exec.c:424
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "у цій системі з RBAC SELinux не передбачено підтримки режиму перехоплення"
+
+#: src/exec.c:429
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "у цій системі неможливо записувати до журналу підкоманди з RBAC SELinux"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "не вдалося вилучити PRIV_PROC_EXEC з PRIV_LIMIT"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:163 src/exec_iolog.c:173
+#: src/exec_iolog.c:218 src/exec_iolog.c:225 src/exec_iolog.c:252
+#: src/exec_monitor.c:426 src/exec_monitor.c:434 src/exec_monitor.c:442
+#: src/exec_monitor.c:449 src/exec_monitor.c:456 src/exec_monitor.c:463
+#: src/exec_monitor.c:470 src/exec_monitor.c:477 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:457 src/exec_pty.c:432
+#: src/exec_pty.c:537 src/exec_pty.c:587 src/exec_pty.c:965 src/exec_pty.c:974
+#: src/exec_pty.c:981 src/exec_pty.c:988 src/exec_pty.c:995
+#: src/exec_pty.c:1002 src/exec_pty.c:1009 src/exec_pty.c:1016
+#: src/exec_pty.c:1023 src/exec_pty.c:1030 src/exec_pty.c:1037
+#: src/exec_pty.c:1044
+msgid "unable to add event to queue"
+msgstr "не вдалося додати подію до черги обробки"
+
+#: src/exec_intercept.c:323 src/sudo.c:1033
+msgid "command not set by the security policy"
+msgstr "команду не встановлено правилами захисту"
+
+#: src/exec_intercept.c:401 src/exec_intercept.c:441 src/sudo.c:1253
+#: src/sudo.c:1298 src/sudo.c:1342
+msgid "command rejected by policy"
+msgstr "у виконанні команди відмовлено згідно правил"
+
+#: src/exec_intercept.c:512 src/sudo.c:1940
+msgid "approval plugin error"
+msgstr "помилка у додатку підтвердження"
+
+#: src/exec_intercept.c:537 src/sudo.c:1258 src/sudo.c:1303 src/sudo.c:1347
+#: src/sudo.c:1421
+msgid "policy plugin error"
+msgstr "помилка у додатку правил"
+
+#: src/exec_intercept.c:566
+msgid "invalid PolicyCheckRequest"
+msgstr "некоректне значення PolicyCheckRequest"
+
+#: src/exec_intercept.c:709
+#, c-format
+msgid "client request too large: %zu"
+msgstr "надто великий запит клієнта: %zu"
+
+#: src/exec_intercept.c:751
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "не вдалося розпакувати %s, розмір %zu"
+
+#: src/exec_intercept.c:799
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "неочікуване значення type_case %d у %s від %s"
+
+#: src/exec_intercept.c:825
+#, c-format
+msgid "server message too large: %zu"
+msgstr "надто велике повідомлення сервера: %zu"
+
+#: src/exec_iolog.c:321 src/exec_iolog.c:361 src/exec_iolog.c:401
+#: src/exec_iolog.c:452 src/exec_iolog.c:503
+msgid "I/O plugin error"
+msgstr "Помилка у додатку введення-виведення"
+
+#: src/exec_iolog.c:325 src/exec_iolog.c:365 src/exec_iolog.c:405
+#: src/exec_iolog.c:456 src/exec_iolog.c:507
+msgid "command rejected by I/O plugin"
+msgstr "відмова у виконання команди від додатка введення-виведення"
+
+#: src/exec_iolog.c:555
+msgid "error logging suspend"
+msgstr "помилка під час призупинення ведення журналу"
+
+#: src/exec_iolog.c:590
+msgid "error changing window size"
+msgstr "помилка під час зміни розмірів вікна"
+
+#: src/exec_monitor.c:328
+msgid "error reading from socketpair"
+msgstr "помилка під час спроби читання з пари сокетів"
+
+#: src/exec_monitor.c:340
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "неочікуваний тип відповіді на зворотному каналі: %d"
+
+#: src/exec_monitor.c:566
+msgid "unable to set controlling tty"
+msgstr "не вдалося встановити tty для керування"
+
+#: src/exec_monitor.c:574 src/exec_nopty.c:504 src/exec_nopty.c:514
+#: src/exec_nopty.c:524 src/exec_nopty.c:560 src/exec_pty.c:1195
+#: src/exec_pty.c:1222 src/exec_pty.c:1242 src/exec_pty.c:1262
+#: src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr "не вдалося створити канал"
+
+#: src/exec_monitor.c:584
+msgid "unable to receive message from parent"
+msgstr "не вдалося отримати повідомлення від батьківського процесу"
+
+#: src/exec_monitor.c:600 src/exec_nopty.c:603 src/exec_pty.c:1303
+#: src/sudo_edit.c:361 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr "не вдалося створити відгалуження"
+
+#: src/exec_monitor.c:604 src/exec_monitor.c:700 src/exec_nopty.c:708
+msgid "unable to restore tty label"
+msgstr "не вдалося відновити позначку tty"
+
+#: src/exec_monitor.c:615 src/sesh.c:217 src/sudo.c:1204
+#, c-format
+msgid "unable to execute %s"
+msgstr "не вдалося виконати %s"
+
+#: src/exec_nopty.c:554 src/exec_pty.c:1131
+msgid "policy plugin failed session initialization"
+msgstr "не вдалося виконати ініціалізацію сеансу через додаток правил"
+
+#: src/exec_nopty.c:569 src/exec_pty.c:1100 src/exec_pty.c:1109
+msgid "unable to create sockets"
+msgstr "не вдалося створити сокети"
+
+#: src/exec_nopty.c:696 src/exec_pty.c:1406
+msgid "error in event loop"
+msgstr "помилка у циклі обробки подій"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:852 src/sudo.c:488
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "внутрішня помилка, переповнення %s"
+
+#: src/exec_ptrace.c:1080 src/exec_ptrace.c:1105 src/exec_ptrace.c:1925
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "не вдалося встановити регістри для процесу %d"
+
+#: src/exec_ptrace.c:1100 src/exec_ptrace.c:1275 src/exec_ptrace.c:1628
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "процес %d неочікувано завершив роботу"
+
+#: src/exec_ptrace.c:1209
+msgid "unable to set seccomp filter"
+msgstr "не вдалося встановити фільтр seccomp"
+
+#: src/exec_ptrace.c:1406
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "аргумент інтерпретатора , мало бути «%s», маємо «%s»"
+
+#: src/exec_ptrace.c:1505
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "невідповідність шляхів: мало бути «%s», маємо «%s»"
+
+#: src/exec_ptrace.c:1514 src/exec_ptrace.c:1521 src/exec_ptrace.c:1545
+#: src/exec_ptrace.c:1553 src/exec_ptrace.c:1559 src/exec_ptrace.c:1565
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "невідповідність %s[%d]: мало бути «%s», маємо «%s»"
+
+#: src/exec_ptrace.c:1632
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "неочікуваний стан процесу %d: 0x%x"
+
+#: src/exec_ptrace.c:1723
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "не вдалося отримати повідомлення події для процесу %d"
+
+#: src/exec_ptrace.c:1730
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "не вдалося отримати регістри для процесу %d"
+
+#: src/exec_pty.c:84
+msgid "unable to allocate pty"
+msgstr "не вдалося розмістити pty"
+
+#: src/exec_pty.c:131 src/exec_pty.c:284 src/tgetpass.c:251
+msgid "unable to restore terminal settings"
+msgstr "не вдалося відновити параметри термінала"
+
+#: src/exec_pty.c:243
+msgid "unable to set handler for SIGCONT"
+msgstr "не вдалося встановити обробник для SIGCONT"
+
+#: src/exec_pty.c:293
+#, c-format
+msgid "unable to set handler for SIG%s"
+msgstr "не вдалося встановити обробник для SIG%s"
+
+#: src/exec_pty.c:317
+#, c-format
+msgid "unable to restore handler for SIG%s"
+msgstr "не вдалося відновити обробник для SIG%s"
+
+#: src/exec_pty.c:345
+msgid "unable to restore handler for SIGCONT"
+msgstr "не вдалося відновити обробник для SIGCONT"
+
+#: src/exec_pty.c:1353
+msgid "unable to send message to monitor process"
+msgstr "не вдалося надіслати повідомлення до процесу аудиту"
+
+#: src/load_plugins.c:75 src/load_plugins.c:222 src/load_plugins.c:232
+#: src/load_plugins.c:242 src/load_plugins.c:289
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "помилка у %s, рядок %d під час спроби завантаження додатка «%s»"
+
+#: src/load_plugins.c:186 src/load_plugins.c:257
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "ігноруємо повторний запис додатка, «%s», у %s, рядок %d"
+
+#: src/load_plugins.c:224
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "не вдалося завантажити %s: %s"
+
+#: src/load_plugins.c:234
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "не вдалося знайти символ «%s» у %s"
+
+#: src/load_plugins.c:244
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "несумісна основна версія додатка, %d, (мало бути %d) у %s"
+
+#: src/load_plugins.c:262
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "ігноруємо додаток правил, «%s», у %s, рядок %d"
+
+#: src/load_plugins.c:265
+msgid "only a single policy plugin may be specified"
+msgstr "можна визначати лише один додаток обробки правил"
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "у %2$s виявлено невідомий тип додатка, %1$d"
+
+#: src/load_plugins.c:474
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "до додатка правил %s не включено метод check_policy"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "некоректна назва змінної середовища: %s"
+
+#: src/parse_args.c:319
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "аргументом параметра -C mмає бути число не менше за 3"
+
+#: src/parse_args.c:556
+msgid "you may not specify both the -i and -s options"
+msgstr "не можна одночасно вказувати параметри -i і -s"
+
+#: src/parse_args.c:561
+msgid "you may not specify both the -i and -E options"
+msgstr "не можна одночасно вказувати параметри -i і -E"
+
+#: src/parse_args.c:571
+msgid "the -E option is not valid in edit mode"
+msgstr "не можна використовувати -E у режимі редагування"
+
+#: src/parse_args.c:574
+msgid "you may not specify environment variables in edit mode"
+msgstr "не можна вказувати змінні середовища у режимі редагування"
+
+#: src/parse_args.c:584
+msgid "the -U option may only be used with the -l option"
+msgstr "параметр -U можна використовувати лише разом з параметром -l"
+
+#: src/parse_args.c:588
+msgid "the -A and -S options may not be used together"
+msgstr "параметри -A і -S не можна використовувати одночасно"
+
+#: src/parse_args.c:686
+msgid "sudoedit is not supported on this platform"
+msgstr "підтримки sudoedit для цієї платформи не передбачено"
+
+#: src/parse_args.c:744
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Можна використовувати лише такі параметри: -e, -h, -i, -K, -l, -s, -v та -V"
+
+#: src/parse_args.c:757
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "Може бути вказано лише один параметр з набору -K, -k і -N"
+
+#: src/parse_args.c:778
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s — редагувати файли від імені іншого користувача\n"
+"\n"
+
+#: src/parse_args.c:780
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s — виконати команду від імені іншого користувача\n"
+"\n"
+
+#: src/parse_args.c:785
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Параметри:\n"
+
+#: src/parse_args.c:787
+msgid "use a helper program for password prompting"
+msgstr "використовувати допоміжну програму для запитів щодо пароля"
+
+#: src/parse_args.c:790
+msgid "use specified BSD authentication type"
+msgstr "використовувати вказаний тип розпізнавання BSD"
+
+#: src/parse_args.c:794
+msgid "run command in the background"
+msgstr "виконати команду у фоновому режимі"
+
+#: src/parse_args.c:797
+msgid "ring bell when prompting"
+msgstr "звук дзвінка під час запиту"
+
+#: src/parse_args.c:799
+msgid "close all file descriptors >= num"
+msgstr "закрити всі дескриптори файлів >= num"
+
+#: src/parse_args.c:802
+msgid "run command with the specified BSD login class"
+msgstr "виконати команду з вказаним класом доступу BSD"
+
+#: src/parse_args.c:805
+msgid "change the working directory before running command"
+msgstr "змінити робочий каталог перед виконанням команди"
+
+#: src/parse_args.c:808
+msgid "preserve user environment when running command"
+msgstr "зберегти середовище користувача на час виконання команди"
+
+#: src/parse_args.c:810
+msgid "preserve specific environment variables"
+msgstr "зберегти вказані змінні середовища"
+
+#: src/parse_args.c:812
+msgid "edit files instead of running a command"
+msgstr "редагувати файли замість виконання команди"
+
+#: src/parse_args.c:815
+msgid "run command as the specified group name or ID"
+msgstr "виконати команду від імені групи користувачів, вказаної за назвою або ідентифікатором"
+
+#: src/parse_args.c:818
+msgid "set HOME variable to target user's home dir"
+msgstr "встановити для змінної HOME значення домашнього каталогу вказаного користувача."
+
+#: src/parse_args.c:821
+msgid "display help message and exit"
+msgstr "показати довідкове повідомлення і завершити роботу"
+
+#: src/parse_args.c:823
+msgid "run command on host (if supported by plugin)"
+msgstr "виконати команду на комп’ютері (якщо підтримується додатком)"
+
+#: src/parse_args.c:826
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "запустити оболонку для входу до системи від імені вказаного користувача; слід вказати команду запуску"
+
+#: src/parse_args.c:828
+msgid "remove timestamp file completely"
+msgstr "повністю вилучити файл часової позначки"
+
+#: src/parse_args.c:831
+msgid "invalidate timestamp file"
+msgstr "позбавити чинності файл часової позначки"
+
+#: src/parse_args.c:834
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "показати список прав доступу користувача або перевірити певну команду; подвоєння параметра призводить до виведення додаткових даних"
+
+#: src/parse_args.c:837
+msgid "non-interactive mode, no prompts are used"
+msgstr "неінтерактивний режим, не просити користувача відповідати на питання"
+
+#: src/parse_args.c:840
+msgid "preserve group vector instead of setting to target's"
+msgstr "зберегти вектор групи, не встановлювати вектор вказаного користувача"
+
+#: src/parse_args.c:843
+msgid "use the specified password prompt"
+msgstr "використовувати вказаний інструмент отримання паролів"
+
+#: src/parse_args.c:845
+msgid "change the root directory before running command"
+msgstr "змінити кореневий каталог перед виконанням команди"
+
+#: src/parse_args.c:848
+msgid "create SELinux security context with specified role"
+msgstr "створити контекст захисту SELinux з вказаною роллю"
+
+#: src/parse_args.c:851
+msgid "read password from standard input"
+msgstr "прочитати пароль зі стандартного джерела вхідних даних"
+
+#: src/parse_args.c:854
+msgid "run shell as the target user; a command may also be specified"
+msgstr "виконати командну оболонку від імені вказаного користувача; слід також вказати команду"
+
+#: src/parse_args.c:858
+msgid "create SELinux security context with specified type"
+msgstr "створити контекст захисту SELinux вказаного типу"
+
+#: src/parse_args.c:861
+msgid "terminate command after the specified time limit"
+msgstr "перервати виконання команди щойно буде перевищено вказане обмеження за часом"
+
+#: src/parse_args.c:864
+msgid "in list mode, display privileges for user"
+msgstr "у режимі списку, показати права доступу користувача"
+
+#: src/parse_args.c:867
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "виконати команду (або редагувати файл) від імені користувача, вказаного за іменем або ідентифікатором"
+
+#: src/parse_args.c:869
+msgid "display version information and exit"
+msgstr "показати дані щодо версії і завершити роботу"
+
+#: src/parse_args.c:872
+msgid "update user's timestamp without running a command"
+msgstr "оновити штамп часу користувача без виконання команди"
+
+#: src/parse_args.c:875
+msgid "stop processing command line arguments"
+msgstr "зупинити обробку аргументів командного рядка"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "не вдалося відкрити систему аудиту"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "не вдалося надіслати повідомлення аудиту"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "не вдалося виконати fgetfilecon %s"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s змінено позначки"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "не вдалося відновити контекст %s"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "не вдалося відкрити %s, не змінюємо позначки tty"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s не є символьним пристроєм, не змінюємо мітки tty"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "не вдалося отримати поточний контекст tty, не змінюємо позначки tty"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "невідомий клас захисту «chr_file», не змінюємо позначки tty"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "не вдалося отримати новий контекст tty, не змінюємо позначки tty"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "не вдалося встановити новий контекст tty"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "вам слід вказати роль для типу %s"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "не вдалося отримати типовий тип для ролі %s"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "не вдалося отримати новий контекст"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "не вдалося встановити нову роль %s"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "не вдалося встановити новий тип %s"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s не є коректним контекстом"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "не вдалося отримати старий контекст"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "не вдалося визначити режим примушення."
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "не вдалося встановити контекст виконання у значення %s"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "не вдалося встановити контекст ключа створення у значення %s"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "Може бути вказано лише один параметр, -c або -i"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "некоректний номер дескриптора файла: %s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "Параметром -%c не можна користуватися у режимі редагування."
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "Параметром -%c можна скористатися лише у режимі редагування."
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: не можна редагувати символічні посилання"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: не можна редагувати файли у непридатному до запису каталозі"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "дані сеансу редагування залишилися у %s"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "не вдалося отримати список груп"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "не вдалося зберегти обробник для сигналу %d"
+
+#: src/signal.c:101 src/suspend_parent.c:149
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "не вдалося відновити обробник для сигналу %d"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "перевищено обмеження керування ресурсами"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "користувач «%s» не є учасником проекту «%s»"
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "викликане завдання є завершальним"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "не вдалося приєднатися до проекту «%s»"
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "для проекту «%s» не існує сховища ресурсів, яке приймає типові прив’язки"
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "у проекті «%s» не існує вказаного сховища ресурсів"
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "не вдалося виконати прив’язку до типового сховища ресурсів проекту «%s»"
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "помилка під час виконання setproject для проекту «%s»"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "попередження, помилка призначення керування ресурсами проекту «%s»"
+
+#: src/sudo.c:214
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Версія sudo %s\n"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Параметри налаштування: %s\n"
+
+#: src/sudo.c:224
+msgid "fatal error, unable to load plugins"
+msgstr "критична помилка, не вдалося завантажити додатки"
+
+#: src/sudo.c:270
+msgid "plugin did not return a command to execute"
+msgstr "додатком не повернуто команди, яку слід виконати"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "неочікуваний режим sudo 0x%x"
+
+#: src/sudo.c:559
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "вас немає у базі даних %s"
+
+#: src/sudo.c:616
+msgid "unable to determine tty"
+msgstr "не вдалося визначити tty"
+
+#: src/sudo.c:932
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "Встановлено прапорець «без нових привілеїв», який забороняє запуск sudo від імені користувача root."
+
+#: src/sudo.c:934
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "Якщо sudo запущено у контейнері, вам, можливо, слід скоригувати налаштування контейнера, щоб вимкнути цей прапорець."
+
+#: src/sudo.c:968
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s має належати користувачеві з uid %d, крім того, має бути встановлено біт setuid"
+
+#: src/sudo.c:971
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "поточним uid не є %d. Можливо %s зберігається у файловій системі зі встановленим параметром «nosuid» або у файловій системі NFS без прав доступу root?"
+
+#: src/sudo.c:977
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "поточним uid не є %d, sudo встановлено з ідентифікатором користувача root?"
+
+#: src/sudo.c:993 src/tgetpass.c:332
+msgid "unable to set supplementary group IDs"
+msgstr "не вдалося встановити ідентифікатори додаткових груп"
+
+#: src/sudo.c:1000
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "не вдалося встановити ефективний ідентифікатор групи для ідентифікатора групи запуску %u"
+
+#: src/sudo.c:1006
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "не вдалося встановити ідентифікатор групи для ідентифікатора групи запуску %u"
+
+#: src/sudo.c:1037
+msgid "argv not set by the security policy"
+msgstr "argv не встановлено правилами захисту"
+
+#: src/sudo.c:1041
+msgid "envp not set by the security policy"
+msgstr "envp не встановлено правилами захисту"
+
+#: src/sudo.c:1063
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "неочікувана умова переривання дочірнього процесу: %d"
+
+#: src/sudo.c:1176
+msgid "unable to initialize policy plugin"
+msgstr "не вдалося ініціалізувати додаток правил"
+
+#: src/sudo.c:1238
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "до додатка правил %s не включено метод check_policy"
+
+#: src/sudo.c:1284
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "у додатку правил %s не передбачено підтримки побудови списку прав доступу"
+
+#: src/sudo.c:1328
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "у додатку правил %s не передбачено підтримки параметра -v"
+
+#: src/sudo.c:1366
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "у додатку правил %s не передбачено підтримки параметрів -k/-K"
+
+#: src/sudo.c:1495
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "помилка під час спроби ініціалізації додатка введення/виведення даних %s"
+
+#: src/sudo.c:1498
+msgid "error initializing I/O plugin"
+msgstr "помилка під час спроби ініціалізації додатка введення/виведення даних"
+
+#: src/sudo.c:1647
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "помилка під час спроби ініціалізації додатка аудиту %s"
+
+#: src/sudo.c:1726
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: не вдалося записати до журналу подію помилки%s%s"
+
+#: src/sudo.c:1762
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: не вдалося записати до журналу подію прийняття%s%s"
+
+#: src/sudo.c:1767 src/sudo.c:1805
+msgid "audit plugin error"
+msgstr "помилка у додатку аудиту"
+
+#: src/sudo.c:1800
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: не вдалося записати до журналу подію відмови%s%s"
+
+#: src/sudo.c:1860
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "помилка під час спроби ініціалізації додатка підтвердження %s"
+
+#: src/sudo.c:1930
+msgid "command rejected by approver"
+msgstr "у виконанні команди відмовлено засобом підтвердження"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "не знайдено придатного до запису тимчасового каталогу"
+
+#: src/sudo_edit.c:292
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s залишено без змін"
+
+#: src/sudo_edit.c:305 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s не змінено"
+
+#: src/sudo_edit.c:482
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: внутрішня помилка: непарна кількість шляхів"
+
+#: src/sudo_edit.c:484
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: не вдалося створити тимчасові файли"
+
+#: src/sudo_edit.c:486 src/sudo_edit.c:606
+msgid "sesh: killed by a signal"
+msgstr "sesh: завершено надсиланням сигналу"
+
+#: src/sudo_edit.c:488 src/sudo_edit.c:609
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: невідома помилка %d"
+
+#: src/sudo_edit.c:599
+msgid "unable to copy temporary files back to their original location"
+msgstr "не вдалося скопіювати тимчасові файли назад до початкового місця зберігання"
+
+#: src/sudo_edit.c:603
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "не вдалося скопіювати деякі з тимчасових файлів назад до початкового місця зберігання"
+
+#: src/sudo_edit.c:650
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "не вдалося змінити значення uid на значення root (%u)"
+
+#: src/sudo_edit.c:664
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "помилка додатка: некоректний список файлів для sudoedit"
+
+#: src/sudo_edit.c:685
+msgid "plugin error: missing file list for sudoedit"
+msgstr "помилка додатка: не вистачає списку файлів для sudoedit"
+
+#: src/sudo_edit.c:728 src/sudo_edit.c:743
+msgid "unable to read the clock"
+msgstr "не вдалося прочитати час на годиннику"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "порт перехоплення не встановлено"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "перевищено граничний час очікування на пароль"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "пароль не надано"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "не вдалося прочитати пароль"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "у терміналі слід прочитати пароль; або скористайтеся параметром -S, щоб виконати читання зі стандартного джерела даних, або налаштуйте допоміжний засіб askpass"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "не вказано програми askpass, спробуйте встановити значення змінної SUDO_ASKPASS"
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "не вдалося встановити gid у значення %u"
+
+#: src/tgetpass.c:337
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "не вдалося встановити uid у значення %u"
+
+#: src/tgetpass.c:342
+#, c-format
+msgid "unable to run %s"
+msgstr "не вдалося виконати %s"
+
+#: src/utmp.c:283
+msgid "unable to save stdin"
+msgstr "не вдалося зберегти stdin"
+
+#: src/utmp.c:285
+msgid "unable to dup2 stdin"
+msgstr "не вдалося виконати dup2 для stdin"
+
+#: src/utmp.c:288
+msgid "unable to restore stdin"
+msgstr "не вдалося відновити stdin"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s має належати користувачеві з uid %d"
+
+#~ msgid "%s must be only be writable by owner"
+#~ msgstr "%s має бути доступним до запису лише для власника"
+
+#~ msgid "insufficient space for execve arguments"
+#~ msgstr "недостатньо місця для аргументів execve"
+
+#~ msgid "unable to read execve %s for process %d"
+#~ msgstr "не вдалося прочитати %s execve для процесу %d"
+
+#~ msgid "requires at least one argument"
+#~ msgstr "потребує принаймні одного аргументу"
+
+#~ msgid "unable to run %s as a login shell"
+#~ msgstr "%s не можна працювати як оболонка для входу"
+
+#~ msgid "unable to dup intercept fd"
+#~ msgstr "не вдалося здублювати перехоплений дескриптор файла"
+
+#~ msgid "%s: missing message header"
+#~ msgstr "%s: не вистачає заголовка повідомлення"
+
+#~ msgid "%s: expected message type %d, got %d"
+#~ msgstr "%s: очікуваний тип повідомлення — %d, маємо — %d"
+
+#~ msgid "unable to set tty context to %s"
+#~ msgstr "не вдалося встановити контекст tty у значення %s"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s: %s"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s: короткий запис"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "не вдалося виконати читання з файла тимчасових даних"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "ігноруємо повторний запис додатка правил, «%s», у %s, рядок %d"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "не виявлено tty і не вказано програми askpass"
diff --git a/po/vi.mo b/po/vi.mo
new file mode 100644
index 0000000..2893cbc
--- /dev/null
+++ b/po/vi.mo
Binary files differ
diff --git a/po/vi.po b/po/vi.po
new file mode 100644
index 0000000..223883f
--- /dev/null
+++ b/po/vi.po
@@ -0,0 +1,1307 @@
+# Vietnamese translation for sudo.
+# Bản dịch tiếng Việt dành cho sudo.
+# This file is put in the public domain.
+# Trần Ngọc Quân <vnwildman@gmail.com>, 2012-2018, 2020, 2022-2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.14b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-06-07 13:27-0600\n"
+"PO-Revision-Date: 2023-06-10 10:22+0700\n"
+"Last-Translator: Trần Ngọc Quân <vnwildman@gmail.com>\n"
+"Language-Team: Vietnamese <translation-team-vi@lists.sourceforge.net>\n"
+"Language: vi\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "không thể mở cơ sở dữ liệu người dùng userdb"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "không thể chuyển đến sổ đăng ký “%s” cho %s"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "không thể phục hồi sổ đăng ký"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:78 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:171 src/exec_monitor.c:418
+#: src/exec_monitor.c:424 src/exec_monitor.c:432 src/exec_monitor.c:440
+#: src/exec_monitor.c:447 src/exec_monitor.c:454 src/exec_monitor.c:461
+#: src/exec_monitor.c:468 src/exec_monitor.c:475 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:744 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1096
+#: src/exec_ptrace.c:1271 src/exec_ptrace.c:1624 src/exec_ptrace.c:1651
+#: src/exec_ptrace.c:1841 src/exec_pty.c:581 src/exec_pty.c:765
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:193 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:240
+#: src/sesh.c:246 src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:644
+#: src/sudo.c:709 src/sudo.c:719 src/sudo.c:746 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:787 src/sudo.c:805 src/sudo.c:846 src/sudo.c:855 src/sudo.c:865
+#: src/sudo.c:898 src/sudo.c:1127 src/sudo.c:1148 src/sudo.c:1441
+#: src/sudo.c:1610 src/sudo.c:1837 src/sudo.c:2171 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:430 src/sudo_edit.c:439
+#: src/sudo_edit.c:540 src/sudo_edit.c:547 src/sudo_edit.c:692
+#: src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:79 src/exec_intercept.c:111 src/exec_intercept.c:350
+#: src/exec_intercept.c:525 src/exec_intercept.c:589 src/exec_intercept.c:713
+#: src/exec_intercept.c:837 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:418 src/exec_monitor.c:424
+#: src/exec_monitor.c:432 src/exec_monitor.c:440 src/exec_monitor.c:447
+#: src/exec_monitor.c:454 src/exec_monitor.c:461 src/exec_monitor.c:468
+#: src/exec_monitor.c:475 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1651 src/exec_ptrace.c:1842 src/exec_pty.c:581
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:228 src/sudo.c:644 src/sudo.c:898 src/sudo.c:1127
+#: src/sudo.c:1148 src/sudo.c:1441 src/sudo.c:1610 src/sudo.c:1837
+#: src/sudo.c:2171 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:430
+#: src/sudo_edit.c:439 src/sudo_edit.c:540 src/sudo_edit.c:547
+#: src/sudo_edit.c:692 src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "không thể cấp phát bộ nhớ"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "không thể lấy thống kê về %.*s"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s có tồn tại nhưng nó không phải là một thư mục (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:664
+#: lib/util/sudo_conf.c:683 lib/util/sudo_conf.c:710 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:495 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "không thể mở “%s”"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "không thể tạo thư mục %.*s"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "không thể mở “%.*s”"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "biểu thức chính quy quá lớn"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "Không hiểu tín hiệu"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "giá trị không hợp lệ"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "giá trị quá lớn"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "giá trị quá nhỏ"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "đường dẫn không hợp lệ “%s” trong %s, dòng %u"
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "giá trị không hợp lệ cho %s “%s” trong %s, dòng %u"
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "nguồn nhóm không được hỗ trợ “%s” trong %s, dòng %u"
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "nhóm tối đa không hợp lệ “%s” trong %s, dòng %u"
+
+#: lib/util/sudo_conf.c:686
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s không phải tập tin thường"
+
+#: lib/util/sudo_conf.c:689 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s được sở hữu bởi uid %u, nên là %u"
+
+#: lib/util/sudo_conf.c:693
+#, c-format
+msgid "%s is world writable"
+msgstr "%s là ai ghi cũng được"
+
+#: lib/util/sudo_conf.c:696
+#, c-format
+msgid "%s is group writable"
+msgstr "%s là nhóm có thể ghi"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "gặp lỗi khi xác định hạn chế AppArmor"
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "không thể thay đổi hồ sơ AppArmor thành %s"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s: cắt cụt %s thành không byte? (y/n) [n] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "không ghi đè lên “%s”"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "không thể đọc từ “%s”"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "không thể ghi vào %s"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "không thể lấy thống kê về %s"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s: không phải là tập tin thường"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s: sai chế độ tập tin: 0%o"
+
+#: src/edit_open.c:333
+msgid "unable to restore current working directory"
+msgstr "không thể phục hồi thư mục làm việc hiện tại"
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "không thể đặt đặc quyền"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "không thể đặt giới hạn đặc quyền"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "không hiểu lớp đăng nhập %s"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "không thể đặt ngữ cảnh người dùng"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "không thể đặt ưu tiên cho quá trình"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "không thể chuyển đổi thư mục gốc thành %s"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "không thể thay đổi thành chạy như là mã người dùng này (%u, %u)"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "không thể thay đổi thư mục thành %s"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "đang bắt đầu từ %s"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:552 src/exec_monitor.c:554
+#: src/exec_pty.c:1122 src/exec_pty.c:1124 src/signal.c:144 src/signal.c:151
+#: src/signal.c:165 src/suspend_parent.c:143
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "không thể đặt bộ tiếp hợp cho tín hiệu %d"
+
+#: src/exec.c:424
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "chế độ chặn không được hỗ trợ với SELinux RBAC trên hệ thống này"
+
+#: src/exec.c:429
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "không thể ghi nhật ký lệnh con với SELinux RBAC trên hệ thống này"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "không thể xóa bỏ PRIV_PROC_EXEC từ PRIV_LIMIT"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:163 src/exec_iolog.c:173
+#: src/exec_iolog.c:218 src/exec_iolog.c:225 src/exec_iolog.c:252
+#: src/exec_monitor.c:426 src/exec_monitor.c:434 src/exec_monitor.c:442
+#: src/exec_monitor.c:449 src/exec_monitor.c:456 src/exec_monitor.c:463
+#: src/exec_monitor.c:470 src/exec_monitor.c:477 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:457 src/exec_pty.c:432
+#: src/exec_pty.c:537 src/exec_pty.c:587 src/exec_pty.c:965 src/exec_pty.c:974
+#: src/exec_pty.c:981 src/exec_pty.c:988 src/exec_pty.c:995
+#: src/exec_pty.c:1002 src/exec_pty.c:1009 src/exec_pty.c:1016
+#: src/exec_pty.c:1023 src/exec_pty.c:1030 src/exec_pty.c:1037
+#: src/exec_pty.c:1044
+msgid "unable to add event to queue"
+msgstr "không thể thêm sự kiện vào hàng đợi"
+
+#: src/exec_intercept.c:323 src/sudo.c:1033
+msgid "command not set by the security policy"
+msgstr "lệnh bị từ chối do chính sách an ninh"
+
+#: src/exec_intercept.c:401 src/exec_intercept.c:441 src/sudo.c:1253
+#: src/sudo.c:1298 src/sudo.c:1342
+msgid "command rejected by policy"
+msgstr "lệnh bị từ chối do chính sách"
+
+#: src/exec_intercept.c:512 src/sudo.c:1940
+msgid "approval plugin error"
+msgstr "lỗi trình cắm chấp thuận"
+
+#: src/exec_intercept.c:537 src/sudo.c:1258 src/sudo.c:1303 src/sudo.c:1347
+#: src/sudo.c:1421
+msgid "policy plugin error"
+msgstr "lỗi trình cắm chính sách"
+
+#: src/exec_intercept.c:566
+msgid "invalid PolicyCheckRequest"
+msgstr "PolicyCheckRequest không hợp lệ"
+
+#: src/exec_intercept.c:709
+#, c-format
+msgid "client request too large: %zu"
+msgstr "yêu cầu từ máy khách là quá lớn: %zu"
+
+#: src/exec_intercept.c:751
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "không thể giải nén %s kích cỡ %zu"
+
+#: src/exec_intercept.c:799
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "gặp giá trị type_case không cần %d trong %s từ %s"
+
+#: src/exec_intercept.c:825
+#, c-format
+msgid "server message too large: %zu"
+msgstr "thông điệp từ máy chủ là quá lớn: %zu"
+
+#: src/exec_iolog.c:321 src/exec_iolog.c:361 src/exec_iolog.c:401
+#: src/exec_iolog.c:452 src/exec_iolog.c:503
+msgid "I/O plugin error"
+msgstr "Lỗi trình cắm V/R"
+
+#: src/exec_iolog.c:325 src/exec_iolog.c:365 src/exec_iolog.c:405
+#: src/exec_iolog.c:456 src/exec_iolog.c:507
+msgid "command rejected by I/O plugin"
+msgstr "lệnh bị từ chối bởi trình cắm V/R"
+
+#: src/exec_iolog.c:555
+msgid "error logging suspend"
+msgstr "lỗi cấm ghi nhật ký"
+
+#: src/exec_iolog.c:590
+msgid "error changing window size"
+msgstr "gặp lỗi khi thay đổi cỡ của cửa sổ"
+
+#: src/exec_monitor.c:328
+msgid "error reading from socketpair"
+msgstr "gặp lỗi khi đọc từ socketpair"
+
+#: src/exec_monitor.c:340
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "kiểu trả về không như mong đợi từ backchannel: %d"
+
+#: src/exec_monitor.c:566
+msgid "unable to set controlling tty"
+msgstr "không thể đặt điều khiển cho tty"
+
+#: src/exec_monitor.c:574 src/exec_nopty.c:504 src/exec_nopty.c:514
+#: src/exec_nopty.c:524 src/exec_nopty.c:560 src/exec_pty.c:1195
+#: src/exec_pty.c:1222 src/exec_pty.c:1242 src/exec_pty.c:1262
+#: src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr "không tạo được đường ống pipe"
+
+#: src/exec_monitor.c:584
+msgid "unable to receive message from parent"
+msgstr "không thể nhận tin nhắn từ cha mẹ"
+
+#: src/exec_monitor.c:600 src/exec_nopty.c:603 src/exec_pty.c:1303
+#: src/sudo_edit.c:361 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr "không thể tạo tiến trình con"
+
+#: src/exec_monitor.c:604 src/exec_monitor.c:700 src/exec_nopty.c:708
+msgid "unable to restore tty label"
+msgstr "không thể phục hồi nhãn cho tty"
+
+#: src/exec_monitor.c:615 src/sesh.c:217 src/sudo.c:1204
+#, c-format
+msgid "unable to execute %s"
+msgstr "không thể thực thi %s"
+
+#: src/exec_nopty.c:554 src/exec_pty.c:1131
+msgid "policy plugin failed session initialization"
+msgstr "phần bổ sung chính sách gặp lỗi khi khởi tạo phiên"
+
+#: src/exec_nopty.c:569 src/exec_pty.c:1100 src/exec_pty.c:1109
+msgid "unable to create sockets"
+msgstr "không thể tạo các ổ cắm mạng"
+
+#: src/exec_nopty.c:696 src/exec_pty.c:1406
+msgid "error in event loop"
+msgstr "có lỗi trong vòng lặp sự kiện"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:852 src/sudo.c:488
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "lỗi nội bộ, %s bị tràn"
+
+#: src/exec_ptrace.c:1080 src/exec_ptrace.c:1105 src/exec_ptrace.c:1925
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "không thể đặt đăng ký cho tiến trình %d"
+
+#: src/exec_ptrace.c:1100 src/exec_ptrace.c:1275 src/exec_ptrace.c:1628
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "tiến trình %d đã thoát bất thường"
+
+#: src/exec_ptrace.c:1209
+msgid "unable to set seccomp filter"
+msgstr "không thể đặt bộ lọc seccomp"
+
+#: src/exec_ptrace.c:1406
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "đối số bộ phiên dịch, cần \"%s\", nhưng lại nhận được \"%s\""
+
+#: src/exec_ptrace.c:1505
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "tên đường dẫn không khớp, cần \"%s\", nhưng lại nhận được \"%s\""
+
+#: src/exec_ptrace.c:1514 src/exec_ptrace.c:1521 src/exec_ptrace.c:1545
+#: src/exec_ptrace.c:1553 src/exec_ptrace.c:1559 src/exec_ptrace.c:1565
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "%s[%d] không khớp, cần \"%s\", nhưng lại nhận được \"%s\""
+
+#: src/exec_ptrace.c:1632
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "tiến trình %d có trạng thái thoát bất thường 0x%x"
+
+#: src/exec_ptrace.c:1723
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "không thể lấy tin nhắn sự kiện cho tiến trình %d"
+
+#: src/exec_ptrace.c:1730
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "không thể lấy đăng ký cho tiến trình %d"
+
+#: src/exec_pty.c:84
+msgid "unable to allocate pty"
+msgstr "không thể phân bổ pty"
+
+#: src/exec_pty.c:131 src/exec_pty.c:284 src/tgetpass.c:251
+msgid "unable to restore terminal settings"
+msgstr "không thể phục hồi các cài đặt thiết bị đầu cuối"
+
+#: src/exec_pty.c:243
+msgid "unable to set handler for SIGCONT"
+msgstr "không thể đặt bộ xử lý cho tín hiệu SIGCONT"
+
+#: src/exec_pty.c:293
+#, c-format
+msgid "unable to set handler for SIG%s"
+msgstr "không thể đặt bộ xử lý cho tín hiệu SIG%s"
+
+#: src/exec_pty.c:317
+#, c-format
+msgid "unable to restore handler for SIG%s"
+msgstr "không thể phục hồi bộ xử lý cho tín hiệu SIG%s"
+
+#: src/exec_pty.c:345
+msgid "unable to restore handler for SIGCONT"
+msgstr "không thể khôi phục trình xử lý cho tín hiệu SIGCONT"
+
+#: src/exec_pty.c:1353
+msgid "unable to send message to monitor process"
+msgstr "không thể gửi tin đến tiến trình theo dõi"
+
+#: src/load_plugins.c:75 src/load_plugins.c:222 src/load_plugins.c:232
+#: src/load_plugins.c:242 src/load_plugins.c:289
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "lỗi trong %s, dòng %d, trong khi tải phần bổ sung “%s”"
+
+#: src/load_plugins.c:186 src/load_plugins.c:257
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "bỏ qua phần bổ sung trùng lặp “%s” trong %s, dòng %d"
+
+#: src/load_plugins.c:224
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "không thể tải %s: %s"
+
+#: src/load_plugins.c:234
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "không tìm thấy ký hiệu “%s” trong %s"
+
+#: src/load_plugins.c:244
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "không tương thích số hiệu phiên bản lớn %d (cần %d) tìm thấy trong %s"
+
+#: src/load_plugins.c:262
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "lờ đi phần bổ sung chính sách “%s” trong %s, dòng %d"
+
+#: src/load_plugins.c:265
+msgid "only a single policy plugin may be specified"
+msgstr "chỉ được phép chỉ định một phần bổ sung chính sách"
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "không hiểu kiểu trình cắm %d tìm thấy trong %s"
+
+#: src/load_plugins.c:474
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "phần bổ sung chính sách %s không bao gồm phương thức kiểm tra chính sách"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "tên biến môi trường không hợp lệ: %s"
+
+#: src/parse_args.c:319
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "đối số cho -C phải là một số lớn hơn hoặc bằng 3"
+
+#: src/parse_args.c:556
+msgid "you may not specify both the -i and -s options"
+msgstr "bạn không nên chỉ định đồng thời cả hai tùy chọn “-i” và “-s”"
+
+#: src/parse_args.c:561
+msgid "you may not specify both the -i and -E options"
+msgstr "bạn không nên chỉ định cả hai tùy chọn “-i” và “-E”"
+
+#: src/parse_args.c:571
+msgid "the -E option is not valid in edit mode"
+msgstr "tùy chọn “-E” không hợp lệ trong chế độ chỉnh sửa"
+
+#: src/parse_args.c:574
+msgid "you may not specify environment variables in edit mode"
+msgstr "bạn có lẽ không được chỉ định biến môi trường trong chế độ soạn thảo"
+
+#: src/parse_args.c:584
+msgid "the -U option may only be used with the -l option"
+msgstr "tùy chọn “-U” chỉ nên sử dụng cùng với tùy chọn “-l”"
+
+#: src/parse_args.c:588
+msgid "the -A and -S options may not be used together"
+msgstr "tùy chọn “-A” và “-S” không nên dùng cùng một lúc với nhau"
+
+#: src/parse_args.c:686
+msgid "sudoedit is not supported on this platform"
+msgstr "sudoedit không được hỗ trợ trên nền tảng này"
+
+#: src/parse_args.c:744
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "Chỉ được phép chỉ định một trong số các tùy chọn -e, -h, -i, -K, -l, -s, -v hay -V"
+
+#: src/parse_args.c:757
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "Chỉ được phép chỉ định một trong số các tùy chọn -K, -k, hay -N"
+
+#: src/parse_args.c:778
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - sửa chữa các tập tin trên danh nghĩa người dùng khác\n"
+"\n"
+
+#: src/parse_args.c:780
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - thực hiện câu lệnh trên danh nghĩa người dùng khác\n"
+"\n"
+
+#: src/parse_args.c:785
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"Tùy chọn:\n"
+
+#: src/parse_args.c:787
+msgid "use a helper program for password prompting"
+msgstr "sử dụng chương trình trợ giúp cho hỏi đáp mật khẩu"
+
+#: src/parse_args.c:790
+msgid "use specified BSD authentication type"
+msgstr "sử dụng kiểu xác thực BSD được chỉ ra"
+
+#: src/parse_args.c:794
+msgid "run command in the background"
+msgstr "chạy lệnh ở chế độ nền"
+
+#: src/parse_args.c:797
+msgid "ring bell when prompting"
+msgstr "reo chuông khi nhắc"
+
+#: src/parse_args.c:799
+msgid "close all file descriptors >= num"
+msgstr "đóng tất cả các mô tả của tập tin >= số"
+
+#: src/parse_args.c:802
+msgid "run command with the specified BSD login class"
+msgstr "chạy lệnh với một lớp đăng nhập BSD được chỉ ra"
+
+#: src/parse_args.c:805
+msgid "change the working directory before running command"
+msgstr "thay đổi thư mục làm việc trước khi chạy lệnh"
+
+#: src/parse_args.c:808
+msgid "preserve user environment when running command"
+msgstr "bảo tồn môi trường người dùng khi thi hành lệnh"
+
+#: src/parse_args.c:810
+msgid "preserve specific environment variables"
+msgstr "bảo tôn các biến môi trường chuyên biệt"
+
+#: src/parse_args.c:812
+msgid "edit files instead of running a command"
+msgstr "chỉnh sửa các tập tin thay vì chạy lệnh"
+
+#: src/parse_args.c:815
+msgid "run command as the specified group name or ID"
+msgstr "thực hiện câu lệnh với tư cách là tên hay ID của nhóm được chỉ định"
+
+#: src/parse_args.c:818
+msgid "set HOME variable to target user's home dir"
+msgstr "đặt biến HOME cho thư mục riêng của người dùng đích"
+
+#: src/parse_args.c:821
+msgid "display help message and exit"
+msgstr "hiển thị trợ giúp này rồi thoát"
+
+#: src/parse_args.c:823
+msgid "run command on host (if supported by plugin)"
+msgstr "chạy câu lệnh trên máy chủ (nếu được hỗ trợ bởi phần bổ sung)"
+
+#: src/parse_args.c:826
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "chạy shell đăng nhập như là người dùng đích; có thể đồng thời chỉ định một câu lệnh"
+
+#: src/parse_args.c:828
+msgid "remove timestamp file completely"
+msgstr "gỡ bỏ hoàn toàn dấu vết thời gian của tập tin"
+
+#: src/parse_args.c:831
+msgid "invalidate timestamp file"
+msgstr "làm mất hiệu lực dấu vết thời gian (timestamp) của tập tin"
+
+#: src/parse_args.c:834
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "liệt kê đặc quyền của người dùng hay kiểm tra câu lệnh xác định; dùng hai lần cho định dạng dài"
+
+#: src/parse_args.c:837
+msgid "non-interactive mode, no prompts are used"
+msgstr "chế độ không-tương-tác, sẽ không hỏi tên người dùng"
+
+#: src/parse_args.c:840
+msgid "preserve group vector instead of setting to target's"
+msgstr "bảo tồn véc-tơ nhóm thay vì các cài đặt cho đích"
+
+#: src/parse_args.c:843
+msgid "use the specified password prompt"
+msgstr "sử dụng nhắc nhập mật khẩu đã chỉ ra"
+
+#: src/parse_args.c:845
+msgid "change the root directory before running command"
+msgstr "thay đổi thư mục gốc trước khi chạy lệnh"
+
+#: src/parse_args.c:848
+msgid "create SELinux security context with specified role"
+msgstr "tạo ngữ cảnh an ninh SELinux với vai trò đã chỉ ra"
+
+#: src/parse_args.c:851
+msgid "read password from standard input"
+msgstr "đọc mật khẩu từ đầu vào tiêu chuẩn"
+
+#: src/parse_args.c:854
+msgid "run shell as the target user; a command may also be specified"
+msgstr "chạy hệ vỏ dưới danh nghĩa người dùng đích; cũng có thể chỉ định thêm câu lệnh"
+
+#: src/parse_args.c:858
+msgid "create SELinux security context with specified type"
+msgstr "tạo ngữ cảnh an ninh SELinux với kiểu đã chỉ ra"
+
+#: src/parse_args.c:861
+msgid "terminate command after the specified time limit"
+msgstr "chấm dứt lệnh sau một thời hạn giới hạn được chỉ định"
+
+#: src/parse_args.c:864
+msgid "in list mode, display privileges for user"
+msgstr "ở chế độ liệt kê, hiển thị đặc quyền cho người dùng"
+
+#: src/parse_args.c:867
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "chạy lệnh (hay sửa chữa tập tin) trên tư cách của người dùng hay ID đã chỉ ra"
+
+#: src/parse_args.c:869
+msgid "display version information and exit"
+msgstr "hiển thị thông tin phiên bản rồi thoát"
+
+#: src/parse_args.c:872
+msgid "update user's timestamp without running a command"
+msgstr "cập nhật dấu vết thời gian (timestamp) của người dùng mà không chạy một lệnh"
+
+#: src/parse_args.c:875
+msgid "stop processing command line arguments"
+msgstr "dừng việc xử lý đối số dòng lệnh"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "không thể mở hệ thống audit"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "không thể gửi thông tin audit"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "không thể fgetfilecon %s"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s nhãn đã thay đổi"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "không thể phục hồi ngữ cảnh cho %s"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "không thể mở %s, không phải là tty dán nhãn lại"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s không phải là một thiết bị ký tự, không phải là tty dán nhãn lại"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "không thể lấy ngữ cảnh tty hiện hành, không phải là tty dán nhãn lại"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "không hiểu lớp an ninh \"chr_file\", không phải là tty dán nhãn lại"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "không thể lấy ngữ cảnh tty mới, không phải là tty dán nhãn lại"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "không thể đặt ngữ cảnh tty mới"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "bạn phải chỉ định một kiểu vai trò cho %s"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "không thể lấy kiểu mặc định cho vai trò %s"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "gặp lỗi khi lấy ngữ cảnh mới"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "gặp lỗi khi đặt đặt vai trò mới %s"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "gặp lỗi khi đặt kiểu mới %s"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s không phải là một ngữ cảnh hợp lệ"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "gặp lỗi khi lấy ngữ cảnh cũ"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "không thể xác định rõ chế độ ép buộc."
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "không thể đặt ngữ cảnh bảo thực thi thành %s"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "không thể đặt ngữ cảnh tạo khóa thành %s"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "Chỉ được phép chỉ định một trong số các tùy chọn -c, hay -i"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "số mô tả của tập tin không hợp lệ: %s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "Tùy chọn “-%c” không hợp lệ trong chế độ chỉnh sửa."
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "Tùy chọn “-%c” chỉ có thể sử dụng trong chế độ chỉnh sửa."
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s: sửa các liên kết mềm là không được phép"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s: sửa các tập tin trong thư mục ghi được là là không được phép"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "nội dung của phiên chỉnh sửa chỉ còn %s"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "không thể lấy danh sách nhóm"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "không thể ghi lại bộ tiếp hợp cho tín hiệu %d"
+
+#: src/signal.c:101 src/suspend_parent.c:149
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "không thể phục hồi bộ tiếp hợp cho tín hiệu %d"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "giới hạn điều khiển tài nguyên đã tới hạn"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "người dùng “%s” không phải là thành viên của dự án “%s”"
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "tác vụ được gọi là cuối cùng"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "không thể gia nhập dự án “%s”"
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "không kho tài nguyên chung nào được thừa nhận ràng buộc đã tồn tại sẵn cho dự án “%s”"
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "nguồn tài nguyên chung được chỉ ra chưa tồn tại cho dự án “%s”"
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "không thể buộc phần tài nguyên chung mặc định cho dự án “%s”"
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "đặt dự án cho dự án “%s” gặp lỗi"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "cảnh báo, nguồn điều khiển gán gặp lỗi cho dự án “%s”"
+
+#: src/sudo.c:214
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo phiên bản %s\n"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "Các tùy chọn cấu hình: %s\n"
+
+#: src/sudo.c:224
+msgid "fatal error, unable to load plugins"
+msgstr "lỗi nghiêm trọng, không thể tải các phần bổ sung"
+
+#: src/sudo.c:270
+msgid "plugin did not return a command to execute"
+msgstr "phần bổ sung không trả về một lệnh để thực thi"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "không mong đợi chế độ sudo 0x%x"
+
+#: src/sudo.c:559
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "bạn không tồn tại trong cơ sở dữ liệu %s"
+
+#: src/sudo.c:616
+msgid "unable to determine tty"
+msgstr "không thể dò tìm tty"
+
+#: src/sudo.c:932
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "Chưa đặt cờ \"đặc quyền mới\" nào, việc này sẽ ngăn cản sudo chạy với tư cách root."
+
+#: src/sudo.c:934
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "Nếu sudo được chạy trong một container, bạn có lẽ cần chỉnh cấu hình container để tắt cờ."
+
+#: src/sudo.c:968
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s phải được sở hữu bởi uid %d và bít setuid phải được đặt"
+
+#: src/sudo.c:971
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "uid chịu tác động hiện tại không phải là %d, có phải là %s trên hệ thống tập tin với tùy chọn “nosuid” được đặt, hay một hệ thống tập tin NFS không có đặc quyền của root không?"
+
+#: src/sudo.c:977
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "uid chịu tác động hiện tại không phải là %d, chương trình sudo có được cài với setuid root không?"
+
+#: src/sudo.c:993 src/tgetpass.c:332
+msgid "unable to set supplementary group IDs"
+msgstr "không thể đặt nhóm phụ IDs"
+
+#: src/sudo.c:1000
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "không thể đặt hiệu ứng gid chạy như là gid %u"
+
+#: src/sudo.c:1006
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "không thể thay đổi gid thành runas gid %u"
+
+#: src/sudo.c:1037
+msgid "argv not set by the security policy"
+msgstr "argv không được đặt bởi chính sách an ninh"
+
+#: src/sudo.c:1041
+msgid "envp not set by the security policy"
+msgstr "envp không được đặt bởi chính sách an ninh"
+
+#: src/sudo.c:1063
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "biểu thức điều kiện con kết thúc không như mong đợi: %d"
+
+#: src/sudo.c:1176
+msgid "unable to initialize policy plugin"
+msgstr "không thể khởi tạo phần bổ sung chính sách"
+
+#: src/sudo.c:1238
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "phần bổ sung chính sách %s bị thiếu phương thức kiểm tra chính sách “check_policy”"
+
+#: src/sudo.c:1284
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "phần bổ sung chính sách %s không hỗ trợ liệt kê đặc quyền"
+
+#: src/sudo.c:1328
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "phần bổ sung chính sách %s không hỗ trợ tùy chọn -v"
+
+#: src/sudo.c:1366
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "phần bổ sung chính sách %s không hỗ trợ tùy chọn -k/-K"
+
+#: src/sudo.c:1495
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "gặp lỗi khi khởi tạo phần bổ sung I/O %s"
+
+#: src/sudo.c:1498
+msgid "error initializing I/O plugin"
+msgstr "gặp lỗi khi khởi tạo phần bổ sung V/R"
+
+#: src/sudo.c:1647
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "gặp lỗi khi khởi tạo phần bổ sung audit %s"
+
+#: src/sudo.c:1726
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s: không thể ghi nhật ký sự kiện lỗi%s%s"
+
+#: src/sudo.c:1762
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s: không thể ghi nhật ký sự kiện chấp thuận%s%s"
+
+#: src/sudo.c:1767 src/sudo.c:1805
+msgid "audit plugin error"
+msgstr "lỗi trình cắm audit"
+
+#: src/sudo.c:1800
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s: không thể ghi nhật ký sự kiện từ chối%s%s"
+
+#: src/sudo.c:1860
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "gặp lỗi khi khởi tạo phần bổ sung chấp thuận %s"
+
+#: src/sudo.c:1930
+msgid "command rejected by approver"
+msgstr "lệnh bị từ chối do bộ chấp thuận"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "không thể tìm thấy thư mục tạm ghi được nào"
+
+#: src/sudo_edit.c:292
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s còn lại chưa thay đổi"
+
+#: src/sudo_edit.c:305 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s không thay đổi"
+
+#: src/sudo_edit.c:482
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh: lỗi nội tại: số cũ của đường dẫn"
+
+#: src/sudo_edit.c:484
+msgid "sesh: unable to create temporary files"
+msgstr "sesh: không thể tạo tập tin tạm thời"
+
+#: src/sudo_edit.c:486 src/sudo_edit.c:606
+msgid "sesh: killed by a signal"
+msgstr "sesh: bị giết bởi một tín hiệu"
+
+#: src/sudo_edit.c:488 src/sudo_edit.c:609
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh: không hiểu lỗi %d"
+
+#: src/sudo_edit.c:599
+msgid "unable to copy temporary files back to their original location"
+msgstr "không thể chép các tập tin tạm trở lại vị trí gốc của chúng"
+
+#: src/sudo_edit.c:603
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "không thể chép một số tập tin tạm trở lại vị trí gốc của chúng"
+
+#: src/sudo_edit.c:650
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "không thể thay đổi uid thành root (%u)"
+
+#: src/sudo_edit.c:664
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "lỗi phần bổ sung: danh sách tập tin không hợp lệ cho sudoedit"
+
+#: src/sudo_edit.c:685
+msgid "plugin error: missing file list for sudoedit"
+msgstr "lỗi phần bổ sung: thiếu danh sách tập tin cho sudoedit"
+
+#: src/sudo_edit.c:728 src/sudo_edit.c:743
+msgid "unable to read the clock"
+msgstr "không thể đọc khóa"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "chưa đặt cổng chắn"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "quá thời hạn chờ đọc mật khẩu"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "chưa đưa ra mật khẩu"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "không thể đọc mật khẩu"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "một thiết bị đầu cuối là cần thiết để đọc mật khẩu; hoặc sử dụng tùy chọn -S để đọc từ đầu vào tiêu chuẩn hoặc cấu hình một chương trình hỗ trợ nhắc hỏi mật khẩu (askpass)"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "không có chương trình hỏi mật khẩu nào được chỉ ra, hãy thử đặt SUDO_ASKPASS"
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "không thể đặt mã số nhóm thành %u"
+
+#: src/tgetpass.c:337
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "không thể đặt mã số người dùng thành %u"
+
+#: src/tgetpass.c:342
+#, c-format
+msgid "unable to run %s"
+msgstr "không thể chạy %s"
+
+#: src/utmp.c:283
+msgid "unable to save stdin"
+msgstr "không thể ghi lại đầu vào tiêu chuẩn"
+
+#: src/utmp.c:285
+msgid "unable to dup2 stdin"
+msgstr "không thể dup2 (nhân đôi) đầu vào tiêu chuẩn"
+
+#: src/utmp.c:288
+msgid "unable to restore stdin"
+msgstr "không thể phục hồi đầu vào tiêu chuẩn"
+
+#~ msgid "insufficient space for execve arguments"
+#~ msgstr "không gian thiếu cho các tham số execve"
+
+#~ msgid "unable to read execve %s for process %d"
+#~ msgstr "không thể đọc execve %s cho tiến trình %d"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s phải được sở hữu bởi uid %d"
+
+#~ msgid "%s must be only be writable by owner"
+#~ msgstr "%s phải là những thứ chỉ có thể ghi bởi chủ sở hữu"
+
+#~ msgid "requires at least one argument"
+#~ msgstr "cần thiết ít nhất một đối số"
+
+#~ msgid "unable to run %s as a login shell"
+#~ msgstr "không thể chạy %s như là hệ vỏ đăng nhập"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s: %s"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "lờ đi phần bổ sung chính sách bị trùng lặp “%s” trong %s, dòng %d"
+
+#~ msgid "unable to set tty context to %s"
+#~ msgstr "không thể cài đặt ngữ cảnh tty mới cho %s"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s: ghi ngắn"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "không thể đọc tập tin tạm thời"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "không có tty hiện diện và không có chương trình hỏi mật khẩu nào được chỉ ra"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "không hiểu mã số người dùng %u: bạn là ai?"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "lỗi khi đọc từ đường ống dẫn tín hiệu"
+
+#~ msgid "internal error, tried allocate zero bytes"
+#~ msgstr "lỗi nội bộ, đã phân bổ 0 byte bộ nhớ"
+
+#~ msgid "unable to set terminal to raw mode"
+#~ msgstr "không thể đặt thiết bị cuối sang chế độ thô"
+
+#~ msgid "unable to open socket"
+#~ msgstr "không mở được socket"
+
+#~ msgid "%s: %s: %s\n"
+#~ msgstr "%s: %s: %s\n"
+
+#~ msgid "%s: %s\n"
+#~ msgstr "%s: %s\n"
+
+#~ msgid "internal error, tried to emalloc2(0)"
+#~ msgstr "lỗi nội bộ, đã dùng erealloc2(0)"
+
+#~ msgid "internal error, tried to ecalloc(0)"
+#~ msgstr "lỗi nội bộ, đã dùng ecalloc(0)"
+
+#~ msgid "internal error, tried to erealloc(0)"
+#~ msgstr "lỗi nội bộ, đã dùng erealloc(0)"
+
+#~ msgid "internal error, tried to erealloc3(0)"
+#~ msgstr "lỗi nội bộ, đã dùng erealloc3(0)"
+
+#~ msgid "internal error, tried to erecalloc(0)"
+#~ msgstr "lỗi nội bộ, đã dùng erecalloc(0)"
+
+#~ msgid "load_interfaces: overflow detected"
+#~ msgstr "load_interfaces: đã có chỗ bị tràn"
+
+#~ msgid "value out of range"
+#~ msgstr "giá trị nằm ngoài phạm vi"
+
+#~ msgid "select failed"
+#~ msgstr "lựa chọn gặp lỗi"
+
+#~ msgid "list user's available commands\n"
+#~ msgstr "Danh sách các biến câu lệnh người dùng có thể sử dụng\n"
+
+#~ msgid "run a shell as target user\n"
+#~ msgstr "chạy shell như là người dùng đích\n"
+
+#~ msgid "when listing, list specified user's privileges\n"
+#~ msgstr "khi liệt kê, liệt kê các đặc quyền của người dùng\n"
+
+#~ msgid ": "
+#~ msgstr ": "
+
+#~ msgid "internal error, emalloc2() overflow"
+#~ msgstr "lỗi nội bộ, erealloc2() bị tràn"
+
+#~ msgid "internal error, erealloc3() overflow"
+#~ msgstr "lỗi nội bộ, erealloc3() bị tràn"
+
+#~ msgid "%s: at least one policy plugin must be specified"
+#~ msgstr "%s: phải xác định ít nhất một phần bổ sung chính sách"
+
+#~ msgid "must be setuid root"
+#~ msgstr "phải được đặt setuid của root"
diff --git a/po/zh_CN.mo b/po/zh_CN.mo
new file mode 100644
index 0000000..5d41aa1
--- /dev/null
+++ b/po/zh_CN.mo
Binary files differ
diff --git a/po/zh_CN.po b/po/zh_CN.po
new file mode 100644
index 0000000..2361109
--- /dev/null
+++ b/po/zh_CN.po
@@ -0,0 +1,1310 @@
+# Chinese simplified translation for sudo.
+# sudo 的简体中文翻译。
+# This file is put in the public domain.
+# Wylmer Wang <wantinghard@gmail.com>, 2011, 2012, 2013, 2014, 2015, 2016, 2018.
+# Boyuan Yang <073plan@gmail.com>, 2019, 2020, 2021, 2022.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo-1.9.14b1\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-06-07 13:27-0600\n"
+"PO-Revision-Date: 2023-10-22 09:31-0400\n"
+"Last-Translator: Boyuan Yang <073plan@gmail.com>\n"
+"Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
+"Language: zh_CN\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 2.4.3\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "无法打开 userdb"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "无法为 %2$s 切换到注册表“%1$s”"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "无法恢复注册表"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:78 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:171 src/exec_monitor.c:418
+#: src/exec_monitor.c:424 src/exec_monitor.c:432 src/exec_monitor.c:440
+#: src/exec_monitor.c:447 src/exec_monitor.c:454 src/exec_monitor.c:461
+#: src/exec_monitor.c:468 src/exec_monitor.c:475 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:744 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1096
+#: src/exec_ptrace.c:1271 src/exec_ptrace.c:1624 src/exec_ptrace.c:1651
+#: src/exec_ptrace.c:1841 src/exec_pty.c:581 src/exec_pty.c:765
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:193 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:240
+#: src/sesh.c:246 src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:644
+#: src/sudo.c:709 src/sudo.c:719 src/sudo.c:746 src/sudo.c:769 src/sudo.c:778
+#: src/sudo.c:787 src/sudo.c:805 src/sudo.c:846 src/sudo.c:855 src/sudo.c:865
+#: src/sudo.c:898 src/sudo.c:1127 src/sudo.c:1148 src/sudo.c:1441
+#: src/sudo.c:1610 src/sudo.c:1837 src/sudo.c:2171 src/sudo_edit.c:89
+#: src/sudo_edit.c:149 src/sudo_edit.c:430 src/sudo_edit.c:439
+#: src/sudo_edit.c:540 src/sudo_edit.c:547 src/sudo_edit.c:692
+#: src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s:%s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:647
+#: src/conversation.c:79 src/exec_intercept.c:111 src/exec_intercept.c:350
+#: src/exec_intercept.c:525 src/exec_intercept.c:589 src/exec_intercept.c:713
+#: src/exec_intercept.c:837 src/exec_iolog.c:122 src/exec_iolog.c:133
+#: src/exec_iolog.c:210 src/exec_monitor.c:418 src/exec_monitor.c:424
+#: src/exec_monitor.c:432 src/exec_monitor.c:440 src/exec_monitor.c:447
+#: src/exec_monitor.c:454 src/exec_monitor.c:461 src/exec_monitor.c:468
+#: src/exec_monitor.c:475 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1651 src/exec_ptrace.c:1842 src/exec_pty.c:581
+#: src/exec_pty.c:963 src/exec_pty.c:972 src/exec_pty.c:979 src/exec_pty.c:986
+#: src/exec_pty.c:993 src/exec_pty.c:1000 src/exec_pty.c:1007
+#: src/exec_pty.c:1014 src/exec_pty.c:1021 src/exec_pty.c:1028
+#: src/exec_pty.c:1035 src/exec_pty.c:1042 src/exec_pty.c:1050
+#: src/load_plugins.c:100 src/load_plugins.c:125 src/load_plugins.c:161
+#: src/load_plugins.c:394 src/load_plugins.c:400 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:269 src/parse_args.c:625
+#: src/parse_args.c:647 src/parse_args.c:672 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:228 src/sudo.c:644 src/sudo.c:898 src/sudo.c:1127 src/sudo.c:1148
+#: src/sudo.c:1441 src/sudo.c:1610 src/sudo.c:1837 src/sudo.c:2171
+#: src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:430
+#: src/sudo_edit.c:439 src/sudo_edit.c:540 src/sudo_edit.c:547
+#: src/sudo_edit.c:692 src/sudo_edit.c:712 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "无法分配内存"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "无法 stat %.*s"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s 存在但不是目录(0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:664
+#: lib/util/sudo_conf.c:683 lib/util/sudo_conf.c:710 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:495 src/sudo_edit.c:559
+#, c-format
+msgid "unable to open %s"
+msgstr "无法打开 %s"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "无法创建目录 %.*s"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "无法打开 %.*s"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "正则表达式太大"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "未知信号"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "值无效"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "值过大"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "值过小"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "%2$s 第 %3$u 行的路径值“%1$s”无效"
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "%3$s 第 %4$u 行的 %1$s 的值“%2$s”无效"
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "不支持 %2$s 第 %3$u 行的组来源“%1$s”"
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "%2$s 第 %3$u 行的最大组数“%1$s”无效"
+
+#: lib/util/sudo_conf.c:686
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s 不是常规文件"
+
+#: lib/util/sudo_conf.c:689 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s 属于用户 ID %u,应为 %u"
+
+#: lib/util/sudo_conf.c:693
+#, c-format
+msgid "%s is world writable"
+msgstr "%s 可被任何人写"
+
+#: lib/util/sudo_conf.c:696
+#, c-format
+msgid "%s is group writable"
+msgstr "%s 可被用户组写"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "无法确定 AppArmor 限制"
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "无法将 AppArmor 配置文件更改为 %s"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s:截断 %s 至零字节? (y/n) [n] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "不覆盖 %s"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "无法读取 %s"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "无法写入 %s"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "无法 stat %s"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s:不是常规文件"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s:不正确的文件模式:0%o"
+
+#: src/edit_open.c:333
+msgid "unable to restore current working directory"
+msgstr "无法恢复当前工作目录"
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "无法设置特权"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "无法设置限制特权"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "未知的登录类别 %s"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "无法设置用户环境"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "无法设置进程优先级"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "无法从 root 切换到 %s"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "无法切换到以用户 ID(%u,%u)运行"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "无法将目录切换到 %s"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "起始于 %s"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:552 src/exec_monitor.c:554
+#: src/exec_pty.c:1122 src/exec_pty.c:1124 src/signal.c:144 src/signal.c:151
+#: src/signal.c:165 src/suspend_parent.c:143
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "无法设置 %d 信号的处理程序"
+
+#: src/exec.c:424
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "本系统上的 SELinux RBAC 不支持拦截模式"
+
+#: src/exec.c:429
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "本系统上的 SELinux RBAC 无法记录子命令"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "无法从 PRIV_LIMIT 中移除 PRIV_PROC_EXEC"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:163 src/exec_iolog.c:173
+#: src/exec_iolog.c:218 src/exec_iolog.c:225 src/exec_iolog.c:252
+#: src/exec_monitor.c:426 src/exec_monitor.c:434 src/exec_monitor.c:442
+#: src/exec_monitor.c:449 src/exec_monitor.c:456 src/exec_monitor.c:463
+#: src/exec_monitor.c:470 src/exec_monitor.c:477 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:457 src/exec_pty.c:432
+#: src/exec_pty.c:537 src/exec_pty.c:587 src/exec_pty.c:965 src/exec_pty.c:974
+#: src/exec_pty.c:981 src/exec_pty.c:988 src/exec_pty.c:995 src/exec_pty.c:1002
+#: src/exec_pty.c:1009 src/exec_pty.c:1016 src/exec_pty.c:1023
+#: src/exec_pty.c:1030 src/exec_pty.c:1037 src/exec_pty.c:1044
+msgid "unable to add event to queue"
+msgstr "无法将事件添加到队列"
+
+#: src/exec_intercept.c:323 src/sudo.c:1033
+msgid "command not set by the security policy"
+msgstr "命令因安全策略未设置"
+
+#: src/exec_intercept.c:401 src/exec_intercept.c:441 src/sudo.c:1253
+#: src/sudo.c:1298 src/sudo.c:1342
+msgid "command rejected by policy"
+msgstr "命令被策略拒绝"
+
+#: src/exec_intercept.c:512 src/sudo.c:1940
+msgid "approval plugin error"
+msgstr "批准插件出错"
+
+#: src/exec_intercept.c:537 src/sudo.c:1258 src/sudo.c:1303 src/sudo.c:1347
+#: src/sudo.c:1421
+msgid "policy plugin error"
+msgstr "策略插件错误"
+
+#: src/exec_intercept.c:566
+msgid "invalid PolicyCheckRequest"
+msgstr "无效的 PolicyCheckRequest"
+
+#: src/exec_intercept.c:709
+#, c-format
+msgid "client request too large: %zu"
+msgstr "客户端请求过大:%zu"
+
+#: src/exec_intercept.c:751
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "无法解包 %s(大小 %zu)"
+
+#: src/exec_intercept.c:799
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "未预期的 type_case 值 %d,位于 %s,来自 %s"
+
+#: src/exec_intercept.c:825
+#, c-format
+msgid "server message too large: %zu"
+msgstr "服务器消息过大:%zu"
+
+#: src/exec_iolog.c:321 src/exec_iolog.c:361 src/exec_iolog.c:401
+#: src/exec_iolog.c:452 src/exec_iolog.c:503
+msgid "I/O plugin error"
+msgstr "I/O 插件错误"
+
+#: src/exec_iolog.c:325 src/exec_iolog.c:365 src/exec_iolog.c:405
+#: src/exec_iolog.c:456 src/exec_iolog.c:507
+msgid "command rejected by I/O plugin"
+msgstr "命令被 I/O 插件拒绝"
+
+#: src/exec_iolog.c:555
+msgid "error logging suspend"
+msgstr "记录挂起事件时出错"
+
+#: src/exec_iolog.c:590
+msgid "error changing window size"
+msgstr "变更窗口大小出错"
+
+#: src/exec_monitor.c:328
+msgid "error reading from socketpair"
+msgstr "从套接字对读取出错"
+
+#: src/exec_monitor.c:340
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "联络通道的回应类型异常:%d"
+
+#: src/exec_monitor.c:566
+msgid "unable to set controlling tty"
+msgstr "无法设置控制终端"
+
+#: src/exec_monitor.c:574 src/exec_nopty.c:504 src/exec_nopty.c:514
+#: src/exec_nopty.c:524 src/exec_nopty.c:560 src/exec_pty.c:1195
+#: src/exec_pty.c:1222 src/exec_pty.c:1242 src/exec_pty.c:1262
+#: src/tgetpass.c:306
+msgid "unable to create pipe"
+msgstr "无法创建管道"
+
+#: src/exec_monitor.c:584
+msgid "unable to receive message from parent"
+msgstr "无法从父(进程)接收消息"
+
+#: src/exec_monitor.c:600 src/exec_nopty.c:603 src/exec_pty.c:1303
+#: src/sudo_edit.c:361 src/tgetpass.c:310
+msgid "unable to fork"
+msgstr "无法执行 fork"
+
+#: src/exec_monitor.c:604 src/exec_monitor.c:700 src/exec_nopty.c:708
+msgid "unable to restore tty label"
+msgstr "无法恢复终端标签"
+
+#: src/exec_monitor.c:615 src/sesh.c:217 src/sudo.c:1204
+#, c-format
+msgid "unable to execute %s"
+msgstr "无法执行 %s"
+
+#: src/exec_nopty.c:554 src/exec_pty.c:1131
+msgid "policy plugin failed session initialization"
+msgstr "策略插件会话初始化失败"
+
+#: src/exec_nopty.c:569 src/exec_pty.c:1100 src/exec_pty.c:1109
+msgid "unable to create sockets"
+msgstr "无法创建套接字"
+
+#: src/exec_nopty.c:696 src/exec_pty.c:1406
+msgid "error in event loop"
+msgstr "事件循环中有错误"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372 src/net_ifs.c:433
+#: src/net_ifs.c:620 src/net_ifs.c:852 src/sudo.c:488 src/sudo_edit.c:398
+#: src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "内部错误,%s 溢出"
+
+#: src/exec_ptrace.c:1080 src/exec_ptrace.c:1105 src/exec_ptrace.c:1925
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "无法设置进程 %d 的寄存器"
+
+#: src/exec_ptrace.c:1100 src/exec_ptrace.c:1275 src/exec_ptrace.c:1628
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "进程 %d 未预期地退出"
+
+#: src/exec_ptrace.c:1209
+msgid "unable to set seccomp filter"
+msgstr "无法设置 seccomp 过滤器"
+
+#: src/exec_ptrace.c:1406
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "解释器参数,期望为“%s”,得到了“%s”"
+
+#: src/exec_ptrace.c:1505
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "路径名不匹配,期望为“%s”,得到了“%s”"
+
+#: src/exec_ptrace.c:1514 src/exec_ptrace.c:1521 src/exec_ptrace.c:1545
+#: src/exec_ptrace.c:1553 src/exec_ptrace.c:1559 src/exec_ptrace.c:1565
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "%s[%d] 不匹配,期望为“%s”,得到了“%s”"
+
+#: src/exec_ptrace.c:1632
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "进程 %d 未预期的状态 0x%x"
+
+#: src/exec_ptrace.c:1723
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "无法获取进程 %d 的事件消息"
+
+#: src/exec_ptrace.c:1730
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "无法获取进程 %d 的寄存器"
+
+#: src/exec_pty.c:84
+msgid "unable to allocate pty"
+msgstr "无法分配伪终端"
+
+#: src/exec_pty.c:131 src/exec_pty.c:284 src/tgetpass.c:251
+msgid "unable to restore terminal settings"
+msgstr "无法恢复终端设置"
+
+#: src/exec_pty.c:243
+msgid "unable to set handler for SIGCONT"
+msgstr "无法设置 SIGCONT 信号的处理程序"
+
+#: src/exec_pty.c:293
+#, c-format
+msgid "unable to set handler for SIG%s"
+msgstr "无法设置 SIG%s 信号的处理程序"
+
+#: src/exec_pty.c:317
+#, c-format
+msgid "unable to restore handler for SIG%s"
+msgstr "无法恢复 SIG%s 信号的处理程序"
+
+#: src/exec_pty.c:345
+msgid "unable to restore handler for SIGCONT"
+msgstr "无法恢复 SIGCONT 信号的处理程序"
+
+#: src/exec_pty.c:1353
+msgid "unable to send message to monitor process"
+msgstr "无法向监视进程发送消息"
+
+#: src/load_plugins.c:75 src/load_plugins.c:222 src/load_plugins.c:232
+#: src/load_plugins.c:242 src/load_plugins.c:289
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "在加载插件“%3$s”时在 %1$s 第 %2$d 行出错"
+
+#: src/load_plugins.c:186 src/load_plugins.c:257
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "忽略位于 %2$s 第 %3$d 行的重复插件“%1$s”"
+
+#: src/load_plugins.c:224
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "无法加载 %s:%s"
+
+#: src/load_plugins.c:234
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "在 %2$s 中找不到符号“%1$s”"
+
+#: src/load_plugins.c:244
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "%3$s 中发现不兼容的插件主版本号 %1$d(应为 %2$d)"
+
+#: src/load_plugins.c:262
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "忽略位于 %2$s 第 %3$d 行的策略插件“%1$s”"
+
+#: src/load_plugins.c:265
+msgid "only a single policy plugin may be specified"
+msgstr "只能指定一个策略插件"
+
+#: src/load_plugins.c:291
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "未知的插件类型 %d,在 %s"
+
+#: src/load_plugins.c:474
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "策略插件 %s 不包含 check_policy 方法"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "无效的环境变量名:%s"
+
+#: src/parse_args.c:319
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "-C 选项的参数必须是一个大于等于 3 的数字"
+
+#: src/parse_args.c:556
+msgid "you may not specify both the -i and -s options"
+msgstr "您不能同时指定 -i 和 -s 选项"
+
+#: src/parse_args.c:561
+msgid "you may not specify both the -i and -E options"
+msgstr "您不能同时指定 -i 和 -E 选项"
+
+#: src/parse_args.c:571
+msgid "the -E option is not valid in edit mode"
+msgstr "-E 选项在编辑模式中无效"
+
+#: src/parse_args.c:574
+msgid "you may not specify environment variables in edit mode"
+msgstr "在编辑模式中您不能指定环境变量"
+
+#: src/parse_args.c:584
+msgid "the -U option may only be used with the -l option"
+msgstr "-U 选项只能与 -l 选项一起使用"
+
+#: src/parse_args.c:588
+msgid "the -A and -S options may not be used together"
+msgstr "-A 和 -S 选项不可同时使用"
+
+#: src/parse_args.c:686
+msgid "sudoedit is not supported on this platform"
+msgstr "此平台不支持 sudoedit"
+
+#: src/parse_args.c:744
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "只能指定 -e、-h、-i、-K、-l、-s、-v 或 -V 选项中的一个"
+
+#: src/parse_args.c:757
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "只能指定 -K, -k 或 -N 选项中的一个"
+
+#: src/parse_args.c:778
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - 以其他用户身份编辑文件\n"
+"\n"
+
+#: src/parse_args.c:780
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - 以其他用户身份执行一条命令\n"
+"\n"
+
+#: src/parse_args.c:785
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"选项:\n"
+
+#: src/parse_args.c:787
+msgid "use a helper program for password prompting"
+msgstr "使用助手程序进行密码提示"
+
+#: src/parse_args.c:790
+msgid "use specified BSD authentication type"
+msgstr "使用指定的 BSD 认证类型"
+
+#: src/parse_args.c:794
+msgid "run command in the background"
+msgstr "在后台运行命令"
+
+#: src/parse_args.c:797
+msgid "ring bell when prompting"
+msgstr "提示时响铃"
+
+#: src/parse_args.c:799
+msgid "close all file descriptors >= num"
+msgstr "关闭所有 >= num 的文件描述符"
+
+#: src/parse_args.c:802
+msgid "run command with the specified BSD login class"
+msgstr "以指定的 BSD 登录类别运行命令"
+
+#: src/parse_args.c:805
+msgid "change the working directory before running command"
+msgstr "运行命令前改变工作目录"
+
+#: src/parse_args.c:808
+msgid "preserve user environment when running command"
+msgstr "在执行命令时保留用户环境"
+
+#: src/parse_args.c:810
+msgid "preserve specific environment variables"
+msgstr "保留特定的环境变量"
+
+#: src/parse_args.c:812
+msgid "edit files instead of running a command"
+msgstr "编辑文件而非执行命令"
+
+#: src/parse_args.c:815
+msgid "run command as the specified group name or ID"
+msgstr "以指定的用户组或 ID 执行命令"
+
+#: src/parse_args.c:818
+msgid "set HOME variable to target user's home dir"
+msgstr "将 HOME 变量设为目标用户的主目录"
+
+#: src/parse_args.c:821
+msgid "display help message and exit"
+msgstr "显示帮助消息并退出"
+
+#: src/parse_args.c:823
+msgid "run command on host (if supported by plugin)"
+msgstr "在主机上运行命令(如果插件支持)"
+
+#: src/parse_args.c:826
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "以目标用户身份运行一个登录 shell;可同时指定一条命令"
+
+#: src/parse_args.c:828
+msgid "remove timestamp file completely"
+msgstr "完全移除时间戳文件"
+
+#: src/parse_args.c:831
+msgid "invalidate timestamp file"
+msgstr "无效的时间戳文件"
+
+#: src/parse_args.c:834
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "列出用户权限或检查某个特定命令;对于长格式,使用两次"
+
+#: src/parse_args.c:837
+msgid "non-interactive mode, no prompts are used"
+msgstr "非交互模式,不提示"
+
+#: src/parse_args.c:840
+msgid "preserve group vector instead of setting to target's"
+msgstr "保留组向量,而非设置为目标的组向量"
+
+#: src/parse_args.c:843
+msgid "use the specified password prompt"
+msgstr "使用指定的密码提示"
+
+#: src/parse_args.c:845
+msgid "change the root directory before running command"
+msgstr "运行命令前改变根目录"
+
+#: src/parse_args.c:848
+msgid "create SELinux security context with specified role"
+msgstr "以指定的角色创建 SELinux 安全环境"
+
+#: src/parse_args.c:851
+msgid "read password from standard input"
+msgstr "从标准输入读取密码"
+
+#: src/parse_args.c:854
+msgid "run shell as the target user; a command may also be specified"
+msgstr "以目标用户运行 shell;可同时指定一条命令"
+
+#: src/parse_args.c:858
+msgid "create SELinux security context with specified type"
+msgstr "以指定的类型创建 SELinux 安全环境"
+
+#: src/parse_args.c:861
+msgid "terminate command after the specified time limit"
+msgstr "在达到指定时间限制后终止命令"
+
+#: src/parse_args.c:864
+msgid "in list mode, display privileges for user"
+msgstr "在列表模式中显示用户的权限"
+
+#: src/parse_args.c:867
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "以指定用户或 ID 运行命令(或编辑文件)"
+
+#: src/parse_args.c:869
+msgid "display version information and exit"
+msgstr "显示版本信息并退出"
+
+#: src/parse_args.c:872
+msgid "update user's timestamp without running a command"
+msgstr "更新用户的时间戳而不执行命令"
+
+#: src/parse_args.c:875
+msgid "stop processing command line arguments"
+msgstr "停止处理命令行参数"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "无法打开审查系统"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "无法发送审查消息"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "无法 fgetfilecon %s"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s 修改了标签"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "无法恢复 %s 的环境"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "无法打开 %s,将不重新标记终端"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s 不是字符型设备,将不重新标记终端"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "无法获取当前终端的环境,将不重新标记终端"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "未知的安全类“chr_file”,将不重新标记终端"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "无法获取新终端的环境,将不重新标记终端"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "无法设置新终端的环境"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "您必须为 %s 类型指定一个角色"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "无法获取 %s 角色的默认类型"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "获取新环境失败"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "设置新角色 %s 失败"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "设置新类型 %s 失败"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s 不是有效的环境"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "获取旧环境失败"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "无法确定强制模式。"
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "无法向 %s 设置 exec 环境"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "无法向 %s 设置键创建环境"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "只能指定 -c 或 -i 选项中的一个"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "无效的文件描述符数字:%s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "-%c 选项在编辑模式中不可用。"
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "-%c 选项只能在编辑模式中使用。"
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s:不允许编辑符号链接"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s:不允许编辑可写目录中的文件"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "编辑会话的内容留在了 %s 中"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "无法获取组列表"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "无法保存 %d 信号的处理程序"
+
+#: src/signal.c:101 src/suspend_parent.c:149
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "无法恢复 %d 信号的处理程序"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "达到了资源控制限制"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "用户“%s”不是项目“%s”的成员"
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "调用的任务是最终的(final)"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "无法加入项目“%s”"
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "不存在对应于项目“%s”的、接受默认绑定的资源池"
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "指定的对应于项目“%s”的资源池不存在"
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "无法为项目“%s”绑定到默认的资源池"
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "对项目“%s”执行 setproject 失败"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "警告,对项目“%s”的资源控制分配失败"
+
+#: src/sudo.c:214
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo 版本 %s\n"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "当前选项:%s\n"
+
+#: src/sudo.c:224
+msgid "fatal error, unable to load plugins"
+msgstr "致命错误,无法加载插件"
+
+#: src/sudo.c:270
+msgid "plugin did not return a command to execute"
+msgstr "插件未返回能执行的命令"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "异常的 sudo 模式 0x%x"
+
+#: src/sudo.c:559
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "%s 数据库中没有您"
+
+#: src/sudo.c:616
+msgid "unable to determine tty"
+msgstr "无法确定终端"
+
+#: src/sudo.c:932
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "已设置“no new privileges”标志,它阻止 sudo 以 root 身份运行。"
+
+#: src/sudo.c:934
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "如果 sudo 正在容器中运行,您可能需要调整容器配置以禁用该标志。"
+
+#: src/sudo.c:968
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s 必须属于用户 ID %d(的用户)并且设置 setuid 位"
+
+#: src/sudo.c:971
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "有效用户 ID 不是 %d,%s 位于一个设置了“nosuid”选项的文件系统或没有 root 权限的 NFS 文件系统中吗?"
+
+#: src/sudo.c:977
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "有效用户 ID 不是 %d,sudo 属于 root 并设置了 setuid 位吗?"
+
+#: src/sudo.c:993 src/tgetpass.c:332
+msgid "unable to set supplementary group IDs"
+msgstr "无法设置补充组 ID"
+
+#: src/sudo.c:1000
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "无法设置有效组 ID 来以组 ID %u 运行"
+
+#: src/sudo.c:1006
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "无法设置组 ID 来以组 ID %u 运行"
+
+#: src/sudo.c:1037
+msgid "argv not set by the security policy"
+msgstr "因安全策略,argv 未设置"
+
+#: src/sudo.c:1041
+msgid "envp not set by the security policy"
+msgstr "因安全策略,envp 未设置"
+
+#: src/sudo.c:1063
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "异常的子进程终止条件:%d"
+
+#: src/sudo.c:1176
+msgid "unable to initialize policy plugin"
+msgstr "无法初始化策略插件"
+
+#: src/sudo.c:1238
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "check_policy 方法中缺少策略插件 %s"
+
+#: src/sudo.c:1284
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "策略插件 %s 不支持列出权限"
+
+#: src/sudo.c:1328
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "策略插件 %s不支持 -v 选项"
+
+#: src/sudo.c:1366
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "策略插件 %s 不支持 -k/-K 选项"
+
+#: src/sudo.c:1495
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "初始化 I/O 插件 %s 出错"
+
+#: src/sudo.c:1498
+msgid "error initializing I/O plugin"
+msgstr "初始化 I/O 插件出错"
+
+#: src/sudo.c:1647
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "初始化审计插件 %s 出错"
+
+#: src/sudo.c:1726
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s:无法记录错误事件%s%s"
+
+#: src/sudo.c:1762
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s:无法记录接受事件%s%s"
+
+#: src/sudo.c:1767 src/sudo.c:1805
+msgid "audit plugin error"
+msgstr "审计插件错误"
+
+#: src/sudo.c:1800
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s:无法记录拒绝事件%s%s"
+
+#: src/sudo.c:1860
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "初始化批准插件 %s 出错"
+
+#: src/sudo.c:1930
+msgid "command rejected by approver"
+msgstr "命令被批准者拒绝"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "未找到可写的临时目录"
+
+#: src/sudo_edit.c:292
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s 并未修改"
+
+#: src/sudo_edit.c:305 src/sudo_edit.c:571
+#, c-format
+msgid "%s unchanged"
+msgstr "%s 未更改"
+
+#: src/sudo_edit.c:482
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh:内部错误:路径数量异常"
+
+#: src/sudo_edit.c:484
+msgid "sesh: unable to create temporary files"
+msgstr "sesh:无法创建临时文件"
+
+#: src/sudo_edit.c:486 src/sudo_edit.c:606
+msgid "sesh: killed by a signal"
+msgstr "sesh:被信号杀死"
+
+#: src/sudo_edit.c:488 src/sudo_edit.c:609
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh:未知错误 %d"
+
+#: src/sudo_edit.c:599
+msgid "unable to copy temporary files back to their original location"
+msgstr "无法将临时文件复制回其原位置"
+
+#: src/sudo_edit.c:603
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "无法将某些临时文件复制回其原位置"
+
+#: src/sudo_edit.c:650
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "无法将用户 ID 切换到 root(%u)"
+
+#: src/sudo_edit.c:664
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "插件错误:sudoedit 的文件列表无效"
+
+#: src/sudo_edit.c:685
+msgid "plugin error: missing file list for sudoedit"
+msgstr "插件错误:缺少 sudoedit 的文件列表"
+
+#: src/sudo_edit.c:728 src/sudo_edit.c:743
+msgid "unable to read the clock"
+msgstr "无法读取时钟"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "未设置侦听端口"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "读密码超时"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "未提供密码"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "无法读取密码"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "读取密码需要一个终端;请使用 -S 选项以从标准输入进行读取,或者配置一个 askpass 助手程序"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "没有指定 askpass 程序,尝试设置 SUDO_ASKPASS"
+
+#: src/tgetpass.c:327
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "无法将组 ID 设为 %u"
+
+#: src/tgetpass.c:337
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "无法将用户 ID 设为 %u"
+
+#: src/tgetpass.c:342
+#, c-format
+msgid "unable to run %s"
+msgstr "无法执行 %s"
+
+#: src/utmp.c:283
+msgid "unable to save stdin"
+msgstr "无法保存 stdin"
+
+#: src/utmp.c:285
+msgid "unable to dup2 stdin"
+msgstr "无法 dup2 stdin"
+
+#: src/utmp.c:288
+msgid "unable to restore stdin"
+msgstr "无法恢复 stdin"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s 必须属于用户 ID %d(的用户)"
+
+#~ msgid "%s must be only be writable by owner"
+#~ msgstr "%s 必须只对其所有者可写"
+
+#~ msgid "requires at least one argument"
+#~ msgstr "要求至少有一个参数"
+
+#~ msgid "unable to run %s as a login shell"
+#~ msgstr "无法以登录 shell 执行 %s"
+
+#~ msgid "%s: missing message header"
+#~ msgstr "%s:缺失消息头"
+
+#~ msgid "%s: expected message type %d, got %d"
+#~ msgstr "%s:期望的消息类型是 %d,但得到了 %d"
+
+#~ msgid "unable to set tty context to %s"
+#~ msgstr "无法将终端环境设置为 %s"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s:%s"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "忽略位于 %2$s 第 %3$d 行的重复策略插件“%1$s”"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s:截短写入"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "无法读取临时文件"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "没有终端存在,且未指定 askpass 程序"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "未知的用户 ID %u:您是?"
+
+#~ msgid "error reading from signal pipe"
+#~ msgstr "从单管道读取出错"
+
+#~ msgid "internal error, tried allocate zero bytes"
+#~ msgstr "内部错误,试图分配 0 个字节"
+
+#~ msgid "unable to set terminal to raw mode"
+#~ msgstr "无法将终端设为原始模式"
+
+#~ msgid "unable to open socket"
+#~ msgstr "无法打开套接字"
+
+#~ msgid "%s: %s: %s\n"
+#~ msgstr "%s:%s:%s\n"
+
+#~ msgid "%s: %s\n"
+#~ msgstr "%s:%s\n"
+
+#~ msgid "internal error, tried to emalloc2(0)"
+#~ msgstr "内部错误,试图 emalloc2(0)"
+
+#~ msgid "internal error, tried to ecalloc(0)"
+#~ msgstr "内部错误,试图 ecalloc(0)"
+
+#~ msgid "internal error, tried to erealloc(0)"
+#~ msgstr "内部错误,试图 erealloc(0)"
+
+#~ msgid "internal error, tried to erealloc3(0)"
+#~ msgstr "内部错误,试图 erealloc3(0)"
+
+#~ msgid "internal error, tried to erecalloc(0)"
+#~ msgstr "内部错误,试图 erecalloc(0)"
+
+#~ msgid "load_interfaces: overflow detected"
+#~ msgstr "load_interfaces:检测到溢出"
+
+#~ msgid "value out of range"
+#~ msgstr "值超出范围"
+
+#~ msgid "select failed"
+#~ msgstr "select 失败"
+
+#~ msgid "list user's available commands\n"
+#~ msgstr "列出用户能执行的命令\n"
+
+#~ msgid "run a shell as target user\n"
+#~ msgstr "以目标用户身份运行 shell\n"
+
+#~ msgid "when listing, list specified user's privileges\n"
+#~ msgstr "在列表时,列出指定用户的权限\n"
+
+#~ msgid ": "
+#~ msgstr ":"
+
+#~ msgid "internal error, emalloc2() overflow"
+#~ msgstr "内部错误,emalloc2() 溢出"
+
+#~ msgid "internal error, erealloc3() overflow"
+#~ msgstr "内部错误,erealloc3() 错误"
+
+#~ msgid "%s: at least one policy plugin must be specified"
+#~ msgstr "%s:至少要指定一个策略插件"
+
+#~ msgid "must be setuid root"
+#~ msgstr "必须为 setuid root"
+
+#~ msgid "the argument to -D must be between 1 and 9 inclusive"
+#~ msgstr "-D 选项的参数必须介于 1 到 9(含 1 和 9)"
diff --git a/po/zh_TW.mo b/po/zh_TW.mo
new file mode 100644
index 0000000..726b3b5
--- /dev/null
+++ b/po/zh_TW.mo
Binary files differ
diff --git a/po/zh_TW.po b/po/zh_TW.po
new file mode 100644
index 0000000..d1c4a50
--- /dev/null
+++ b/po/zh_TW.po
@@ -0,0 +1,1218 @@
+# Chinese(Taiwan) translation for sudo.
+# This file is put in the public domain.
+#
+# 林博仁 (Buo-ren, Lin) <Buo.Ren.Lin@gmail.com>, 2018.
+# Yi-Jyun Pan <pan93412@gmail.com>, 2019, 2020, 2021.
+msgid ""
+msgstr ""
+"Project-Id-Version: sudo 1.9.13b2\n"
+"Report-Msgid-Bugs-To: https://bugzilla.sudo.ws\n"
+"POT-Creation-Date: 2023-01-24 13:11-0700\n"
+"PO-Revision-Date: 2023-02-03 00:51+0800\n"
+"Last-Translator: Yi-Jyun Pan <pan93412@gmail.com>\n"
+"Language-Team: Chinese (traditional) <zh-l10n@lists.linux.org.tw>\n"
+"Language: zh_TW\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 3.2.2\n"
+
+#: lib/util/aix.c:89 lib/util/aix.c:169
+msgid "unable to open userdb"
+msgstr "無法開啟使用者資料庫"
+
+#: lib/util/aix.c:224
+#, c-format
+msgid "unable to switch to registry \"%s\" for %s"
+msgstr "無法將 %2$s 切換至「%1$s」登錄表"
+
+#: lib/util/aix.c:249
+msgid "unable to restore registry"
+msgstr "無法還原登錄表"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/gidlist.c:76
+#: lib/util/json.c:55 lib/util/json.c:197 lib/util/sudo_conf.c:215
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:646
+#: src/conversation.c:80 src/exec_iolog.c:124 src/exec_iolog.c:135
+#: src/exec_iolog.c:212 src/exec_monitor.c:205 src/exec_monitor.c:460
+#: src/exec_monitor.c:466 src/exec_monitor.c:474 src/exec_monitor.c:482
+#: src/exec_monitor.c:489 src/exec_monitor.c:496 src/exec_monitor.c:503
+#: src/exec_monitor.c:510 src/exec_monitor.c:517 src/exec_monitor.c:524
+#: src/exec_monitor.c:531 src/exec_nopty.c:231 src/exec_nopty.c:240
+#: src/exec_nopty.c:247 src/exec_nopty.c:254 src/exec_nopty.c:261
+#: src/exec_nopty.c:268 src/exec_nopty.c:275 src/exec_nopty.c:282
+#: src/exec_nopty.c:289 src/exec_nopty.c:296 src/exec_nopty.c:303
+#: src/exec_nopty.c:310 src/exec_nopty.c:318 src/exec_nopty.c:326
+#: src/exec_nopty.c:736 src/exec_preload.c:343 src/exec_ptrace.c:475
+#: src/exec_ptrace.c:768 src/exec_ptrace.c:983 src/exec_ptrace.c:1095
+#: src/exec_ptrace.c:1270 src/exec_ptrace.c:1612 src/exec_ptrace.c:1639
+#: src/exec_pty.c:511 src/exec_pty.c:692 src/exec_pty.c:882 src/exec_pty.c:891
+#: src/exec_pty.c:898 src/exec_pty.c:905 src/exec_pty.c:912 src/exec_pty.c:919
+#: src/exec_pty.c:926 src/exec_pty.c:933 src/exec_pty.c:940 src/exec_pty.c:947
+#: src/exec_pty.c:954 src/exec_pty.c:962 src/load_plugins.c:98
+#: src/load_plugins.c:123 src/load_plugins.c:159 src/load_plugins.c:392
+#: src/load_plugins.c:398 src/parse_args.c:172 src/parse_args.c:193
+#: src/parse_args.c:267 src/parse_args.c:623 src/parse_args.c:645
+#: src/parse_args.c:670 src/preserve_fds.c:46 src/preserve_fds.c:131
+#: src/selinux.c:89 src/selinux.c:362 src/selinux.c:472 src/selinux.c:489
+#: src/selinux.c:496 src/sesh.c:206 src/sesh.c:240 src/sesh.c:246
+#: src/sesh.c:253 src/sesh.c:259 src/sesh.c:470 src/sudo.c:641 src/sudo.c:706
+#: src/sudo.c:716 src/sudo.c:743 src/sudo.c:766 src/sudo.c:775 src/sudo.c:784
+#: src/sudo.c:801 src/sudo.c:842 src/sudo.c:851 src/sudo.c:861 src/sudo.c:894
+#: src/sudo.c:1122 src/sudo.c:1143 src/sudo.c:1436 src/sudo.c:1605
+#: src/sudo.c:1832 src/sudo.c:2166 src/sudo_edit.c:89 src/sudo_edit.c:149
+#: src/sudo_edit.c:429 src/sudo_edit.c:438 src/sudo_edit.c:538
+#: src/sudo_edit.c:545 src/sudo_edit.c:688 src/sudo_edit.c:708
+#: src/sudo_intercept_common.c:115 src/sudo_intercept_common.c:340
+#, c-format
+msgid "%s: %s"
+msgstr "%s:%s"
+
+#: lib/util/aix.c:272 lib/util/gidlist.c:66 lib/util/json.c:56
+#: lib/util/json.c:198 lib/util/regex.c:173 lib/util/sudo_conf.c:216
+#: lib/util/sudo_conf.c:301 lib/util/sudo_conf.c:378 lib/util/sudo_conf.c:646
+#: src/conversation.c:81 src/exec_intercept.c:111 src/exec_intercept.c:344
+#: src/exec_intercept.c:518 src/exec_intercept.c:582 src/exec_intercept.c:706
+#: src/exec_intercept.c:830 src/exec_iolog.c:124 src/exec_iolog.c:135
+#: src/exec_iolog.c:212 src/exec_monitor.c:460 src/exec_monitor.c:466
+#: src/exec_monitor.c:474 src/exec_monitor.c:482 src/exec_monitor.c:489
+#: src/exec_monitor.c:496 src/exec_monitor.c:503 src/exec_monitor.c:510
+#: src/exec_monitor.c:517 src/exec_monitor.c:524 src/exec_monitor.c:531
+#: src/exec_nopty.c:231 src/exec_nopty.c:240 src/exec_nopty.c:247
+#: src/exec_nopty.c:254 src/exec_nopty.c:261 src/exec_nopty.c:268
+#: src/exec_nopty.c:275 src/exec_nopty.c:282 src/exec_nopty.c:289
+#: src/exec_nopty.c:296 src/exec_nopty.c:303 src/exec_nopty.c:310
+#: src/exec_nopty.c:318 src/exec_nopty.c:326 src/exec_preload.c:343
+#: src/exec_ptrace.c:475 src/exec_ptrace.c:768 src/exec_ptrace.c:983
+#: src/exec_ptrace.c:1639 src/exec_pty.c:511 src/exec_pty.c:882
+#: src/exec_pty.c:891 src/exec_pty.c:898 src/exec_pty.c:905 src/exec_pty.c:912
+#: src/exec_pty.c:919 src/exec_pty.c:926 src/exec_pty.c:933 src/exec_pty.c:940
+#: src/exec_pty.c:947 src/exec_pty.c:954 src/exec_pty.c:962
+#: src/load_plugins.c:98 src/load_plugins.c:123 src/load_plugins.c:159
+#: src/load_plugins.c:392 src/load_plugins.c:398 src/parse_args.c:172
+#: src/parse_args.c:194 src/parse_args.c:267 src/parse_args.c:623
+#: src/parse_args.c:645 src/parse_args.c:670 src/preserve_fds.c:46
+#: src/preserve_fds.c:131 src/selinux.c:89 src/selinux.c:362 src/selinux.c:472
+#: src/selinux.c:489 src/selinux.c:496 src/sesh.c:206 src/sesh.c:471
+#: src/sudo.c:230 src/sudo.c:641 src/sudo.c:894 src/sudo.c:1122
+#: src/sudo.c:1143 src/sudo.c:1436 src/sudo.c:1605 src/sudo.c:1832
+#: src/sudo.c:2166 src/sudo_edit.c:89 src/sudo_edit.c:149 src/sudo_edit.c:429
+#: src/sudo_edit.c:438 src/sudo_edit.c:538 src/sudo_edit.c:545
+#: src/sudo_edit.c:688 src/sudo_edit.c:708 src/sudo_intercept_common.c:115
+#: src/sudo_intercept_common.c:340
+msgid "unable to allocate memory"
+msgstr "無法分配記憶體"
+
+#: lib/util/mkdir_parents.c:63
+#, c-format
+msgid "unable to stat %.*s"
+msgstr "無法 stat %.*s"
+
+#: lib/util/mkdir_parents.c:69
+#, c-format
+msgid "%.*s exists but is not a directory (0%o)"
+msgstr "%.*s 存在,但不是目錄 (0%o)"
+
+#: lib/util/mkdir_parents.c:103 lib/util/sudo_conf.c:666
+#: lib/util/sudo_conf.c:696 lib/util/sudo_conf.c:703 src/selinux.c:235
+#: src/selinux.c:265 src/sudo.c:373 src/sudo_edit.c:494 src/sudo_edit.c:557
+#, c-format
+msgid "unable to open %s"
+msgstr "無法開啟 %s"
+
+#: lib/util/mkdir_parents.c:120 lib/util/mkdir_parents.c:160
+#, c-format
+msgid "unable to mkdir %.*s"
+msgstr "無法建立 %.*s 目錄"
+
+#: lib/util/mkdir_parents.c:130 lib/util/mkdir_parents.c:139
+#, c-format
+msgid "unable to open %.*s"
+msgstr "無法開啟 %.*s"
+
+#: lib/util/regex.c:163
+msgid "regular expression too large"
+msgstr "正規表達式太長"
+
+#: lib/util/strsignal.c:50
+msgid "Unknown signal"
+msgstr "訊號未知"
+
+#: lib/util/strtoid.c:84 lib/util/strtomode.c:52 lib/util/strtonum.c:148
+#: lib/util/strtonum.c:187 src/sesh.c:240 src/sesh.c:253
+msgid "invalid value"
+msgstr "數值無效"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:160
+msgid "value too large"
+msgstr "數值過大"
+
+#: lib/util/strtomode.c:58 lib/util/strtonum.c:154
+msgid "value too small"
+msgstr "數值過小"
+
+#: lib/util/sudo_conf.c:234
+#, c-format
+msgid "invalid Path value \"%s\" in %s, line %u"
+msgstr "於 %2$s 第 %3$u 行發現無效的 Path 值「%1$s」"
+
+#: lib/util/sudo_conf.c:400 lib/util/sudo_conf.c:453
+#, c-format
+msgid "invalid value for %s \"%s\" in %s, line %u"
+msgstr "於 %3$s 中第 %4$u 行發現用於 %1$s 的「%2$s」無效數值"
+
+#: lib/util/sudo_conf.c:421
+#, c-format
+msgid "unsupported group source \"%s\" in %s, line %u"
+msgstr "於「%2$s」第 %3$u 行發現不支援的「%1$s」群組來源"
+
+#: lib/util/sudo_conf.c:437
+#, c-format
+msgid "invalid max groups \"%s\" in %s, line %u"
+msgstr "於 %2$s 第 %3$u 行發現無效的「%1$s」最大群組"
+
+#: lib/util/sudo_conf.c:669
+#, c-format
+msgid "%s is not a regular file"
+msgstr "%s 非一般檔案"
+
+#: lib/util/sudo_conf.c:672 src/copy_file.c:164
+#, c-format
+msgid "%s is owned by uid %u, should be %u"
+msgstr "%s 不應由使用者 ID 為 %u 的使用者所擁有,應為 %u"
+
+#: lib/util/sudo_conf.c:676
+#, c-format
+msgid "%s is world writable"
+msgstr "%s 允許所有使用者寫入"
+
+#: lib/util/sudo_conf.c:679
+#, c-format
+msgid "%s is group writable"
+msgstr "%s 允許群組寫入"
+
+#: src/apparmor.c:85
+msgid "failed to determine AppArmor confinement"
+msgstr "無法判斷 AppArmor 的監禁規則"
+
+#: src/apparmor.c:93
+#, c-format
+msgid "unable to change AppArmor profile to %s"
+msgstr "無法將 AppArmor 設定檔更改為 %s"
+
+#: src/copy_file.c:94
+#, c-format
+msgid "%s: truncate %s to zero bytes? (y/n) [n] "
+msgstr "%s:將 %s 截斷至 0 位元組?(y/n) [n] "
+
+#: src/copy_file.c:98
+#, c-format
+msgid "not overwriting %s"
+msgstr "不覆寫 %s"
+
+#: src/copy_file.c:120
+#, c-format
+msgid "unable to read from %s"
+msgstr "無法從 %s 讀取"
+
+#: src/copy_file.c:137 src/sudo_edit.c:320
+#, c-format
+msgid "unable to write to %s"
+msgstr "無法寫入「%s」"
+
+#: src/copy_file.c:151
+#, c-format
+msgid "unable to stat %s"
+msgstr "無法取得 %s 檔案的資訊"
+
+#: src/copy_file.c:155 src/sesh.c:312 src/sudo_edit.c:197
+#, c-format
+msgid "%s: not a regular file"
+msgstr "%s:非一般檔案"
+
+#: src/copy_file.c:159
+#, c-format
+msgid "%s: bad file mode: 0%o"
+msgstr "%s:檔案模式無效:0%o"
+
+#: src/edit_open.c:331
+msgid "unable to restore current working directory"
+msgstr "無法還原目前的工作目錄"
+
+#: src/exec.c:111
+msgid "unable to set privileges"
+msgstr "無法設定權限"
+
+#: src/exec.c:117 src/exec.c:122
+msgid "unable to set limit privileges"
+msgstr "無法設定限制權限"
+
+#: src/exec.c:145
+#, c-format
+msgid "unknown login class %s"
+msgstr "未知的 %s 登入類別"
+
+#: src/exec.c:157
+msgid "unable to set user context"
+msgstr "無法設定使用者上下文"
+
+#: src/exec.c:173
+msgid "unable to set process priority"
+msgstr "無法設定行程優先層級"
+
+#: src/exec.c:190
+#, c-format
+msgid "unable to change root to %s"
+msgstr "無法切換根目錄至 %s"
+
+#: src/exec.c:203 src/exec.c:209 src/exec.c:216
+#, c-format
+msgid "unable to change to runas uid (%u, %u)"
+msgstr "無法變更至 runas 使用者 ID (%u, %u)"
+
+#: src/exec.c:238 src/sesh.c:199
+#, c-format
+msgid "unable to change directory to %s"
+msgstr "無法變更目錄至 %s"
+
+#: src/exec.c:243
+#, c-format
+msgid "starting from %s"
+msgstr "從 %s 啟動"
+
+#: src/exec.c:278 src/exec.c:351 src/exec_monitor.c:569 src/exec_monitor.c:571
+#: src/exec_pty.c:225 src/exec_pty.c:1026 src/exec_pty.c:1028 src/signal.c:144
+#: src/signal.c:151 src/signal.c:165 src/suspend_nopty.c:93
+#, c-format
+msgid "unable to set handler for signal %d"
+msgstr "無法設定用於處理 %d 訊號的程式"
+
+#: src/exec.c:422
+msgid "intercept mode is not supported with SELinux RBAC on this system"
+msgstr "本系統的 SELinux RBAC 不支援攔截模式"
+
+#: src/exec.c:427
+msgid "unable to log sub-commands with SELinux RBAC on this system"
+msgstr "無法記錄本系統上 SELinux RBAC 的子命令"
+
+#: src/exec_common.c:56
+msgid "unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"
+msgstr "無法自 PRIV_LIMIT 移除 PRIV_PROC_EXEC"
+
+#: src/exec_intercept.c:70 src/exec_iolog.c:165 src/exec_iolog.c:175
+#: src/exec_iolog.c:220 src/exec_iolog.c:227 src/exec_iolog.c:254
+#: src/exec_monitor.c:468 src/exec_monitor.c:476 src/exec_monitor.c:484
+#: src/exec_monitor.c:491 src/exec_monitor.c:498 src/exec_monitor.c:505
+#: src/exec_monitor.c:512 src/exec_monitor.c:519 src/exec_monitor.c:526
+#: src/exec_monitor.c:533 src/exec_nopty.c:233 src/exec_nopty.c:242
+#: src/exec_nopty.c:249 src/exec_nopty.c:256 src/exec_nopty.c:263
+#: src/exec_nopty.c:270 src/exec_nopty.c:277 src/exec_nopty.c:284
+#: src/exec_nopty.c:291 src/exec_nopty.c:298 src/exec_nopty.c:305
+#: src/exec_nopty.c:312 src/exec_nopty.c:320 src/exec_nopty.c:328
+#: src/exec_nopty.c:387 src/exec_nopty.c:453 src/exec_pty.c:360
+#: src/exec_pty.c:462 src/exec_pty.c:517 src/exec_pty.c:884 src/exec_pty.c:893
+#: src/exec_pty.c:900 src/exec_pty.c:907 src/exec_pty.c:914 src/exec_pty.c:921
+#: src/exec_pty.c:928 src/exec_pty.c:935 src/exec_pty.c:942 src/exec_pty.c:949
+#: src/exec_pty.c:956
+msgid "unable to add event to queue"
+msgstr "無法新增事件至佇列中"
+
+#: src/exec_intercept.c:317 src/sudo.c:1028
+msgid "command not set by the security policy"
+msgstr "根據安全性策略,不設定命令"
+
+#: src/exec_intercept.c:395 src/exec_intercept.c:435 src/sudo.c:1248
+#: src/sudo.c:1293 src/sudo.c:1337
+msgid "command rejected by policy"
+msgstr "命令被策略拒絕"
+
+#: src/exec_intercept.c:505 src/sudo.c:1935
+msgid "approval plugin error"
+msgstr "核准外掛程式發生錯誤"
+
+#: src/exec_intercept.c:530 src/sudo.c:1253 src/sudo.c:1298 src/sudo.c:1342
+#: src/sudo.c:1416
+msgid "policy plugin error"
+msgstr "策略外掛程式發生錯誤"
+
+#: src/exec_intercept.c:559
+msgid "invalid PolicyCheckRequest"
+msgstr "無效的 PolicyCheckRequest"
+
+#: src/exec_intercept.c:702
+#, c-format
+msgid "client request too large: %zu"
+msgstr "用戶端請求過長:%zu"
+
+#: src/exec_intercept.c:744
+#, c-format
+msgid "unable to unpack %s size %zu"
+msgstr "無法解包 %s(大小 %zu)"
+
+#: src/exec_intercept.c:792
+#, c-format
+msgid "unexpected type_case value %d in %s from %s"
+msgstr "從 %3$s 收到的 %2$s 中有個非預期的 type_case 數值 %1$d"
+
+#: src/exec_intercept.c:818
+#, c-format
+msgid "server message too large: %zu"
+msgstr "伺服器訊息過長:%zu"
+
+#: src/exec_iolog.c:323 src/exec_iolog.c:363 src/exec_iolog.c:403
+#: src/exec_iolog.c:454 src/exec_iolog.c:505
+msgid "I/O plugin error"
+msgstr "I/O 外掛程式錯誤"
+
+#: src/exec_iolog.c:327 src/exec_iolog.c:367 src/exec_iolog.c:407
+#: src/exec_iolog.c:458 src/exec_iolog.c:509
+msgid "command rejected by I/O plugin"
+msgstr "命令被 I/O 外掛程式拒絕"
+
+#: src/exec_iolog.c:556
+msgid "error logging suspend"
+msgstr "記錄暫停時發生錯誤"
+
+#: src/exec_iolog.c:591
+msgid "error changing window size"
+msgstr "變更視窗大小時發生錯誤"
+
+#: src/exec_monitor.c:362
+msgid "error reading from socketpair"
+msgstr "自 socketpair 讀取資料時發生錯誤"
+
+#: src/exec_monitor.c:379
+#, c-format
+msgid "unexpected reply type on backchannel: %d"
+msgstr "未預期的 backchannel 回應類型:%d"
+
+#: src/exec_monitor.c:587
+msgid "unable to set controlling tty"
+msgstr "無法設定控制終端"
+
+#: src/exec_monitor.c:595 src/exec_nopty.c:498 src/exec_nopty.c:508
+#: src/exec_nopty.c:518 src/exec_nopty.c:552 src/exec_pty.c:1097
+#: src/exec_pty.c:1118 src/exec_pty.c:1138 src/tgetpass.c:305
+msgid "unable to create pipe"
+msgstr "無法建立管線"
+
+#: src/exec_monitor.c:605
+msgid "unable to receive message from parent"
+msgstr "無法自上層接收訊息"
+
+#: src/exec_monitor.c:621 src/exec_nopty.c:595 src/exec_pty.c:1176
+#: src/sudo_edit.c:361 src/tgetpass.c:309
+msgid "unable to fork"
+msgstr "無法複製 (fork) 出新行程"
+
+#: src/exec_monitor.c:625 src/exec_monitor.c:723 src/exec_nopty.c:700
+msgid "unable to restore tty label"
+msgstr "無法還原終端標籤 (tty label)"
+
+#: src/exec_monitor.c:638 src/sesh.c:217 src/sudo.c:1199
+#, c-format
+msgid "unable to execute %s"
+msgstr "無法執行 %s"
+
+#: src/exec_nopty.c:546 src/exec_pty.c:1035
+msgid "policy plugin failed session initialization"
+msgstr "政策外掛程式初始化工作階段失敗"
+
+#: src/exec_nopty.c:561 src/exec_pty.c:1004 src/exec_pty.c:1013
+msgid "unable to create sockets"
+msgstr "無法建立 socket 檔案"
+
+#: src/exec_nopty.c:688 src/exec_pty.c:1274
+msgid "error in event loop"
+msgstr "在事件處理迴圈中發生錯誤"
+
+#: src/exec_preload.c:167 src/net_ifs.c:206 src/net_ifs.c:372
+#: src/net_ifs.c:433 src/net_ifs.c:620 src/net_ifs.c:851 src/sudo.c:488
+#: src/sudo_edit.c:398 src/sudo_edit.c:406
+#, c-format
+msgid "internal error, %s overflow"
+msgstr "內部錯誤,%s 溢位"
+
+#: src/exec_ptrace.c:1079 src/exec_ptrace.c:1104 src/exec_ptrace.c:1900
+#, c-format
+msgid "unable to set registers for process %d"
+msgstr "無法設定處理程序 %d 的寄存器"
+
+#: src/exec_ptrace.c:1099 src/exec_ptrace.c:1274 src/exec_ptrace.c:1616
+#, c-format
+msgid "process %d exited unexpectedly"
+msgstr "處理程序 %d 非預期離開"
+
+#: src/exec_ptrace.c:1208
+msgid "unable to set seccomp filter"
+msgstr "無法設定 seccomp 過濾器"
+
+#: src/exec_ptrace.c:1405
+#, c-format
+msgid "interpreter argument , expected \"%s\", got \"%s\""
+msgstr "解釋器引數:預期「%s」卻收到「%s」"
+
+#: src/exec_ptrace.c:1504
+#, c-format
+msgid "pathname mismatch, expected \"%s\", got \"%s\""
+msgstr "路徑名稱不符:預期「%s」卻收到「%s」"
+
+#: src/exec_ptrace.c:1513 src/exec_ptrace.c:1520 src/exec_ptrace.c:1533
+#: src/exec_ptrace.c:1541 src/exec_ptrace.c:1547 src/exec_ptrace.c:1553
+#, c-format
+msgid "%s[%d] mismatch, expected \"%s\", got \"%s\""
+msgstr "%s[%d] 不符:預期「%s」卻收到「%s」"
+
+#: src/exec_ptrace.c:1620
+#, c-format
+msgid "process %d unexpected status 0x%x"
+msgstr "處理程序 %d 的狀態 0x%x 不在預期之內"
+
+#: src/exec_ptrace.c:1711
+#, c-format
+msgid "unable to get event message for process %d"
+msgstr "無法取得處理程序 %d 的事件訊息"
+
+#: src/exec_ptrace.c:1718
+#, c-format
+msgid "unable to get registers for process %d"
+msgstr "無法取得處理程序 %d 的寄存器"
+
+#: src/exec_pty.c:103
+msgid "unable to allocate pty"
+msgstr "無法分配虛擬終端機"
+
+#: src/exec_pty.c:268 src/signal.c:101 src/suspend_nopty.c:99
+#, c-format
+msgid "unable to restore handler for signal %d"
+msgstr "無法還原用於處理 %d 訊號的程序"
+
+#: src/exec_pty.c:1222
+msgid "unable to send message to monitor process"
+msgstr "無法傳送訊息至監控程序"
+
+#: src/load_plugins.c:73 src/load_plugins.c:220 src/load_plugins.c:230
+#: src/load_plugins.c:240 src/load_plugins.c:287
+#, c-format
+msgid "error in %s, line %d while loading plugin \"%s\""
+msgstr "載入「%3$s」外掛程式時,發現 %1$s 中的第 %2$d 行有錯誤"
+
+#: src/load_plugins.c:184 src/load_plugins.c:255
+#, c-format
+msgid "ignoring duplicate plugin \"%s\" in %s, line %d"
+msgstr "忽略第 %3$d 行 %2$s 中的重複外掛程式「%1$s」"
+
+#: src/load_plugins.c:222
+#, c-format
+msgid "unable to load %s: %s"
+msgstr "無法載入 %s:%s"
+
+#: src/load_plugins.c:232
+#, c-format
+msgid "unable to find symbol \"%s\" in %s"
+msgstr "無法在 %s 中找到「%s」符號"
+
+#: src/load_plugins.c:242
+#, c-format
+msgid "incompatible plugin major version %d (expected %d) found in %s"
+msgstr "在 %3$s 中發現不相容的外掛程式主版本號 %1$d(預期應為 %2$d)"
+
+#: src/load_plugins.c:260
+#, c-format
+msgid "ignoring policy plugin \"%s\" in %s, line %d"
+msgstr "無視 %2$s 中第 %3$d 行的「%1$s」sudo 政策外掛程式"
+
+#: src/load_plugins.c:263
+msgid "only a single policy plugin may be specified"
+msgstr "只能指定一個 Sudo 政策外掛程式"
+
+#: src/load_plugins.c:289
+#, c-format
+msgid "unknown plugin type %d found in %s"
+msgstr "在 %2$s 發現未知的外掛程式類型 %1$d"
+
+#: src/load_plugins.c:472
+#, c-format
+msgid "policy plugin %s does not include a check_policy method"
+msgstr "%s 政策外掛程式未包含 check_policy 方法"
+
+#: src/parse_args.c:214
+#, c-format
+msgid "invalid environment variable name: %s"
+msgstr "無效的環境變數名稱:%s"
+
+#: src/parse_args.c:317
+msgid "the argument to -C must be a number greater than or equal to 3"
+msgstr "傳入 -C 的參數數字應該要等於或大於 3"
+
+#: src/parse_args.c:554
+msgid "you may not specify both the -i and -s options"
+msgstr "不能同時指定 -i 跟 -s 指令列選項"
+
+#: src/parse_args.c:559
+msgid "you may not specify both the -i and -E options"
+msgstr "不能同時指定 -i 跟 -E 指令列選項"
+
+#: src/parse_args.c:569
+msgid "the -E option is not valid in edit mode"
+msgstr "-E 指令列選項在編輯模式中無效"
+
+#: src/parse_args.c:572
+msgid "you may not specify environment variables in edit mode"
+msgstr "不能在編輯模式中指定環境變數"
+
+#: src/parse_args.c:582
+msgid "the -U option may only be used with the -l option"
+msgstr "-U 指令列選項只能跟 -l 選項一起使用"
+
+#: src/parse_args.c:586
+msgid "the -A and -S options may not be used together"
+msgstr "不能同時使用 -A 跟 -S 指令列選項"
+
+#: src/parse_args.c:684
+msgid "sudoedit is not supported on this platform"
+msgstr "此平台不支援 sudoedit"
+
+#: src/parse_args.c:767
+msgid "Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"
+msgstr "只能指定其中一個下述選項:-e、-h、-i、-K、-l、-s、-v、-V"
+
+#: src/parse_args.c:780
+msgid "Only one of the -K, -k or -N options may be specified"
+msgstr "只能指定 -K、-k 或 -N 選項其中一個"
+
+#: src/parse_args.c:796
+#, c-format
+msgid ""
+"%s - edit files as another user\n"
+"\n"
+msgstr ""
+"%s - 以另一個使用者的身份編輯檔案\n"
+"\n"
+
+#: src/parse_args.c:798
+#, c-format
+msgid ""
+"%s - execute a command as another user\n"
+"\n"
+msgstr ""
+"%s - 以另一個使用者的身份執行指令\n"
+"\n"
+
+#: src/parse_args.c:804
+msgid ""
+"\n"
+"Options:\n"
+msgstr ""
+"\n"
+"指令列選項:\n"
+
+#: src/parse_args.c:806
+msgid "use a helper program for password prompting"
+msgstr "使用助手程式詢問密碼"
+
+#: src/parse_args.c:809
+msgid "use specified BSD authentication type"
+msgstr "使用指定的 BSD 身份驗證類型"
+
+#: src/parse_args.c:813
+msgid "run command in the background"
+msgstr "在背景中執行指令"
+
+#: src/parse_args.c:816
+msgid "ring bell when prompting"
+msgstr "提示時響鈴"
+
+#: src/parse_args.c:818
+msgid "close all file descriptors >= num"
+msgstr "關閉所有 >= num 的檔案描述元"
+
+#: src/parse_args.c:821
+msgid "run command with the specified BSD login class"
+msgstr "以指定的 BSD 登入類型執行指令"
+
+#: src/parse_args.c:824
+msgid "change the working directory before running command"
+msgstr "執行命令前,先變更工作目錄"
+
+#: src/parse_args.c:827
+msgid "preserve user environment when running command"
+msgstr "在執行指令時保留使用者的環境"
+
+#: src/parse_args.c:829
+msgid "preserve specific environment variables"
+msgstr "保留指定的環境變數"
+
+#: src/parse_args.c:831
+msgid "edit files instead of running a command"
+msgstr "編輯檔案而非執行指令"
+
+#: src/parse_args.c:834
+msgid "run command as the specified group name or ID"
+msgstr "以指定的群組名稱或 ID 執行指令"
+
+#: src/parse_args.c:837
+msgid "set HOME variable to target user's home dir"
+msgstr "設定 HOME 環境變數為目標使用者的家目錄"
+
+#: src/parse_args.c:840
+msgid "display help message and exit"
+msgstr "顯示說明訊息並退出"
+
+#: src/parse_args.c:842
+msgid "run command on host (if supported by plugin)"
+msgstr "在指定的主機上執行指令(若外掛程式支援)"
+
+#: src/parse_args.c:845
+msgid "run login shell as the target user; a command may also be specified"
+msgstr "以目標使用者的身份執行登入 shell;亦可同時指定一個指令"
+
+#: src/parse_args.c:847
+msgid "remove timestamp file completely"
+msgstr "完全地移除時間戳記檔案"
+
+#: src/parse_args.c:850
+msgid "invalidate timestamp file"
+msgstr "使時間戳檔案無效化"
+
+#: src/parse_args.c:853
+msgid "list user's privileges or check a specific command; use twice for longer format"
+msgstr "列出使用者的權限或是檢查特定的指令;指定兩次以用更長的格式輸出"
+
+#: src/parse_args.c:856
+msgid "non-interactive mode, no prompts are used"
+msgstr "非互動式模式,不使用任何提示文字"
+
+#: src/parse_args.c:859
+msgid "preserve group vector instead of setting to target's"
+msgstr "保留目前的群組集合而非設定為目標的群組集合"
+
+#: src/parse_args.c:862
+msgid "use the specified password prompt"
+msgstr "使用指定的密碼提示文字"
+
+#: src/parse_args.c:864
+msgid "change the root directory before running command"
+msgstr "執行命令前,先變更根目錄"
+
+#: src/parse_args.c:867
+msgid "create SELinux security context with specified role"
+msgstr "使用指定的角色建立 SELinux 安全上下文"
+
+#: src/parse_args.c:870
+msgid "read password from standard input"
+msgstr "自標準輸入讀取密碼"
+
+#: src/parse_args.c:873
+msgid "run shell as the target user; a command may also be specified"
+msgstr "以目標使用者的身份執行 shell;一個指令亦可同時被指定"
+
+#: src/parse_args.c:877
+msgid "create SELinux security context with specified type"
+msgstr "使用指定的類型建立 SELinux 安全上下文"
+
+#: src/parse_args.c:880
+msgid "terminate command after the specified time limit"
+msgstr "在指定的時間限制過後中止指令"
+
+#: src/parse_args.c:883
+msgid "in list mode, display privileges for user"
+msgstr "在清單模式中顯示使用者的權限"
+
+#: src/parse_args.c:886
+msgid "run command (or edit file) as specified user name or ID"
+msgstr "以指定的使用者名稱或 ID 來執行指令(或編輯檔案)"
+
+#: src/parse_args.c:888
+msgid "display version information and exit"
+msgstr "顯示版本資訊並離開"
+
+#: src/parse_args.c:891
+msgid "update user's timestamp without running a command"
+msgstr "更新使用者時間戳記而不執行指令"
+
+#: src/parse_args.c:894
+msgid "stop processing command line arguments"
+msgstr "停止處理指令列引數"
+
+#: src/selinux.c:83
+msgid "unable to open audit system"
+msgstr "無法開啟稽核系統"
+
+#: src/selinux.c:93
+msgid "unable to send audit message"
+msgstr "無法傳送稽核訊息"
+
+#: src/selinux.c:129
+#, c-format
+msgid "unable to fgetfilecon %s"
+msgstr "無法對 %s 進行 fgetfilecon"
+
+#: src/selinux.c:134
+#, c-format
+msgid "%s changed labels"
+msgstr "%s 個變更的標籤"
+
+#: src/selinux.c:142
+#, c-format
+msgid "unable to restore context for %s"
+msgstr "無法還原「%s」的 SELinux 上下文"
+
+#: src/selinux.c:190
+#, c-format
+msgid "unable to open %s, not relabeling tty"
+msgstr "無法開啟 %s,將不重加終端機的標籤"
+
+#: src/selinux.c:194 src/selinux.c:239 src/selinux.c:269
+#, c-format
+msgid "%s is not a character device, not relabeling tty"
+msgstr "%s 不是一個字元裝置,將不重加終端機的標籤"
+
+#: src/selinux.c:203
+msgid "unable to get current tty context, not relabeling tty"
+msgstr "無法取得目前的終端機內文,將不重加終端機的標籤"
+
+#: src/selinux.c:210
+msgid "unknown security class \"chr_file\", not relabeling tty"
+msgstr "未知的安全類別「chr_file」,將不重加終端機的標籤"
+
+#: src/selinux.c:215
+msgid "unable to get new tty context, not relabeling tty"
+msgstr "無法取得新的終端機上下文,將不重加終端機的標籤"
+
+#: src/selinux.c:224
+msgid "unable to set new tty context"
+msgstr "無法設定新的終端機上下文"
+
+#: src/selinux.c:323
+#, c-format
+msgid "you must specify a role for type %s"
+msgstr "你必須對 %s 類別指定一個角色"
+
+#: src/selinux.c:329
+#, c-format
+msgid "unable to get default type for role %s"
+msgstr "無法取得 %s 角色的預設分類"
+
+#: src/selinux.c:341
+msgid "failed to get new context"
+msgstr "無法取得新上下文"
+
+#: src/selinux.c:350
+#, c-format
+msgid "failed to set new role %s"
+msgstr "無法設定新的角色 %s"
+
+#: src/selinux.c:354
+#, c-format
+msgid "failed to set new type %s"
+msgstr "無法設定新的類別 %s"
+
+#: src/selinux.c:366
+#, c-format
+msgid "%s is not a valid context"
+msgstr "%s 不是有效的 SELinux 上下文"
+
+#: src/selinux.c:394
+msgid "failed to get old context"
+msgstr "無法取得舊上下文"
+
+#: src/selinux.c:400
+msgid "unable to determine enforcing mode."
+msgstr "無法判斷 SELinux 行使模式。"
+
+#: src/selinux.c:425
+#, c-format
+msgid "unable to set exec context to %s"
+msgstr "無法設定執行上下文為 %s"
+
+#: src/selinux.c:432
+#, c-format
+msgid "unable to set key creation context to %s"
+msgstr "無法設定金鑰建立上下文為 %s"
+
+#: src/sesh.c:114 src/sesh.c:134
+msgid "Only one of the -c or -i options may be specified"
+msgstr "只能指定 -c 或 -i 選項其中一個"
+
+#: src/sesh.c:129
+#, c-format
+msgid "invalid file descriptor number: %s"
+msgstr "無效的檔案描述元:%s"
+
+#: src/sesh.c:167 src/sesh.c:171 src/sesh.c:175
+#, c-format
+msgid "The -%c option may not be used in edit mode."
+msgstr "-%c 選項不應在編輯模式中使用。"
+
+#: src/sesh.c:184 src/sesh.c:189
+#, c-format
+msgid "The -%c option may only be used in edit mode."
+msgstr "-%c 選項只應在編輯模式中使用。"
+
+#: src/sesh.c:294 src/sesh.c:394 src/sudo_edit.c:204
+#, c-format
+msgid "%s: editing symbolic links is not permitted"
+msgstr "%s:不允許編輯符號連結"
+
+#: src/sesh.c:297 src/sesh.c:397 src/sudo_edit.c:207
+#, c-format
+msgid "%s: editing files in a writable directory is not permitted"
+msgstr "%s:不允許在可寫目錄編輯檔案"
+
+#: src/sesh.c:381 src/sesh.c:402 src/sesh.c:411 src/sesh.c:419
+#: src/sudo_edit.c:331
+#, c-format
+msgid "contents of edit session left in %s"
+msgstr "編輯階段的內容被留在 %s"
+
+#: src/sesh.c:476 src/sudo_edit.c:94
+msgid "unable to get group list"
+msgstr "無法取得群組清單"
+
+#: src/signal.c:79
+#, c-format
+msgid "unable to save handler for signal %d"
+msgstr "無法儲存用於 %d 訊號的處理程式"
+
+#: src/solaris.c:72
+msgid "resource control limit has been reached"
+msgstr "已達到資源控制的上限"
+
+#: src/solaris.c:75
+#, c-format
+msgid "user \"%s\" is not a member of project \"%s\""
+msgstr "「%s」使用者不是「%s」專案的成員"
+
+#: src/solaris.c:79
+msgid "the invoking task is final"
+msgstr "觸發的作業已經完成 (final)"
+
+#: src/solaris.c:82
+#, c-format
+msgid "could not join project \"%s\""
+msgstr "無法加入「%s」專案"
+
+#: src/solaris.c:89
+#, c-format
+msgid "no resource pool accepting default bindings exists for project \"%s\""
+msgstr "專案「%s」不存在接受預設繫結的資源集區"
+
+#: src/solaris.c:93
+#, c-format
+msgid "specified resource pool does not exist for project \"%s\""
+msgstr "專案「%s」不存在指定的資源集區"
+
+#: src/solaris.c:97
+#, c-format
+msgid "could not bind to default resource pool for project \"%s\""
+msgstr "無法將專案「%s」繫結到預設資源集區"
+
+#: src/solaris.c:104
+#, c-format
+msgid "setproject failed for project \"%s\""
+msgstr "對專案「%s」進行專案設定程序 (setproject) 失敗"
+
+#: src/solaris.c:106
+#, c-format
+msgid "warning, resource control assignment failed for project \"%s\""
+msgstr "警告:對專案「%s」執行資源控制指派失敗"
+
+#: src/sudo.c:216
+#, c-format
+msgid "Sudo version %s\n"
+msgstr "Sudo 版本 %s\n"
+
+#: src/sudo.c:218
+#, c-format
+msgid "Configure options: %s\n"
+msgstr "設定選項:%s\n"
+
+#: src/sudo.c:226
+msgid "fatal error, unable to load plugins"
+msgstr "致命錯誤:無法載入外掛程式"
+
+#: src/sudo.c:272
+msgid "plugin did not return a command to execute"
+msgstr "外掛程式沒有回傳要執行的指令"
+
+#: src/sudo.c:306
+#, c-format
+msgid "unexpected sudo mode 0x%x"
+msgstr "未預期的 0x%x sudo 模式"
+
+#: src/sudo.c:555
+#, c-format
+msgid "you do not exist in the %s database"
+msgstr "您不在 %s 資料庫中"
+
+#: src/sudo.c:612
+msgid "unable to determine tty"
+msgstr "無法判斷終端機"
+
+#: src/sudo.c:928
+msgid "The \"no new privileges\" flag is set, which prevents sudo from running as root."
+msgstr "已設定「無新特權 (no new privileges)」旗標,防止 sudo 以 root 身份執行。"
+
+#: src/sudo.c:930
+msgid "If sudo is running in a container, you may need to adjust the container configuration to disable the flag."
+msgstr "如果 sudo 是在容器中執行,您可能需要調整容器設定,停用這個旗標。"
+
+#: src/sudo.c:964
+#, c-format
+msgid "%s must be owned by uid %d and have the setuid bit set"
+msgstr "%s 必須由使用者 ID 為 %d 的使用者所擁有,且必須設定 setuid 位元"
+
+#: src/sudo.c:967
+#, c-format
+msgid "effective uid is not %d, is %s on a file system with the 'nosuid' option set or an NFS file system without root privileges?"
+msgstr "有效的使用者 ID 不是 %d,請問「%s」是存在於設定「nosuid」掛載選項的檔案系統中,還是存在於沒有 root 權限的 NFS 檔案系統?"
+
+#: src/sudo.c:973
+#, c-format
+msgid "effective uid is not %d, is sudo installed setuid root?"
+msgstr "有效的使用者 ID 不是 %d,sudo 是否已經安裝 setuid root?"
+
+#: src/sudo.c:989 src/tgetpass.c:331
+msgid "unable to set supplementary group IDs"
+msgstr "無法設定增補群組 ID"
+
+#: src/sudo.c:996
+#, c-format
+msgid "unable to set effective gid to runas gid %u"
+msgstr "無法將有效群組 ID 設定為 runas 群組 ID %u"
+
+#: src/sudo.c:1002
+#, c-format
+msgid "unable to set gid to runas gid %u"
+msgstr "無法將群組 ID 設定為 runas 群組 ID %u"
+
+#: src/sudo.c:1032
+msgid "argv not set by the security policy"
+msgstr "根據安全性策略,不設定 argv"
+
+#: src/sudo.c:1036
+msgid "envp not set by the security policy"
+msgstr "根據安全性策略,不設定 envp"
+
+#: src/sudo.c:1058
+#, c-format
+msgid "unexpected child termination condition: %d"
+msgstr "未預期之子行程中止狀況:%d"
+
+#: src/sudo.c:1171
+msgid "unable to initialize policy plugin"
+msgstr "無法初始化 Sudo 政策外掛程式"
+
+#: src/sudo.c:1233
+#, c-format
+msgid "policy plugin %s is missing the \"check_policy\" method"
+msgstr "%s 政策外掛程式缺少 \"check_policy\" 方法"
+
+#: src/sudo.c:1279
+#, c-format
+msgid "policy plugin %s does not support listing privileges"
+msgstr "%s 政策外掛程式不支援權限"
+
+#: src/sudo.c:1323
+#, c-format
+msgid "policy plugin %s does not support the -v option"
+msgstr "%s 政策外掛程式不支援 -v 指令列選項"
+
+#: src/sudo.c:1361
+#, c-format
+msgid "policy plugin %s does not support the -k/-K options"
+msgstr "%s 政策外掛程式不支援 -k/-K 指令列選項"
+
+#: src/sudo.c:1490
+#, c-format
+msgid "error initializing I/O plugin %s"
+msgstr "初始化「%s」I/O 外掛程式時發生錯誤"
+
+#: src/sudo.c:1493
+msgid "error initializing I/O plugin"
+msgstr "初始化 I/O 外掛程式時發生錯誤"
+
+#: src/sudo.c:1642
+#, c-format
+msgid "error initializing audit plugin %s"
+msgstr "初始化稽核外掛程式 %s 時發生錯誤"
+
+#: src/sudo.c:1721
+#, c-format
+msgid "%s: unable to log error event%s%s"
+msgstr "%s:無法記錄錯誤事件%s%s"
+
+#: src/sudo.c:1757
+#, c-format
+msgid "%s: unable to log accept event%s%s"
+msgstr "%s:無法記錄接受事件%s%s"
+
+#: src/sudo.c:1762 src/sudo.c:1800
+msgid "audit plugin error"
+msgstr "稽核外掛程式發生錯誤"
+
+#: src/sudo.c:1795
+#, c-format
+msgid "%s: unable to log reject event%s%s"
+msgstr "%s:無法記錄拒絕事件%s%s"
+
+#: src/sudo.c:1855
+#, c-format
+msgid "error initializing approval plugin %s"
+msgstr "初始化核准外掛程式 %s 時發生錯誤"
+
+#: src/sudo.c:1925
+msgid "command rejected by approver"
+msgstr "命令被核准人拒絕"
+
+#: src/sudo_edit.c:113
+msgid "no writable temporary directory found"
+msgstr "沒有找到可寫入的暫存目錄"
+
+#: src/sudo_edit.c:291
+#, c-format
+msgid "%s left unmodified"
+msgstr "%s 保持未變更狀態"
+
+#: src/sudo_edit.c:304 src/sudo_edit.c:569
+#, c-format
+msgid "%s unchanged"
+msgstr "%s 未變更"
+
+#: src/sudo_edit.c:481
+msgid "sesh: internal error: odd number of paths"
+msgstr "sesh:內部錯誤:只有奇數個路徑"
+
+#: src/sudo_edit.c:483
+msgid "sesh: unable to create temporary files"
+msgstr "sesh:無法建立暫存檔案"
+
+#: src/sudo_edit.c:485 src/sudo_edit.c:604
+msgid "sesh: killed by a signal"
+msgstr "sesh:被信號中止"
+
+#: src/sudo_edit.c:487 src/sudo_edit.c:607
+#, c-format
+msgid "sesh: unknown error %d"
+msgstr "sesh:未知錯誤代碼 %d"
+
+#: src/sudo_edit.c:597
+msgid "unable to copy temporary files back to their original location"
+msgstr "無法將暫存檔複製回暫存檔的原始位置"
+
+#: src/sudo_edit.c:601
+msgid "unable to copy some of the temporary files back to their original location"
+msgstr "無法將部份的暫存檔複製回其原始位置"
+
+#: src/sudo_edit.c:646
+#, c-format
+msgid "unable to change uid to root (%u)"
+msgstr "無法將使用者 ID 變更為 root (%u)"
+
+#: src/sudo_edit.c:660
+msgid "plugin error: invalid file list for sudoedit"
+msgstr "外掛程式錯誤:用於 sudoedit 的檔案清單無效"
+
+#: src/sudo_edit.c:681
+msgid "plugin error: missing file list for sudoedit"
+msgstr "外掛程式錯誤:缺少可用於 sudoedit 的檔案清單"
+
+#: src/sudo_edit.c:724 src/sudo_edit.c:739
+msgid "unable to read the clock"
+msgstr "無法讀取時間"
+
+#: src/sudo_intercept_common.c:365
+msgid "intercept port not set"
+msgstr "未設定攔截用連線埠"
+
+#: src/tgetpass.c:95
+msgid "timed out reading password"
+msgstr "讀取密碼逾時"
+
+#: src/tgetpass.c:98
+msgid "no password was provided"
+msgstr "未提供密碼"
+
+#: src/tgetpass.c:101
+msgid "unable to read password"
+msgstr "無法讀取密碼"
+
+#: src/tgetpass.c:141
+msgid "a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"
+msgstr "需要終端器才能讀取密碼;可以使用 -S 選項,從標準輸入讀取,或是設定 askpass 協助工具"
+
+#: src/tgetpass.c:152
+msgid "no askpass program specified, try setting SUDO_ASKPASS"
+msgstr "沒有指定 askpass 程式,將嘗試設定 SUDO_ASKPASS 環境變數"
+
+#: src/tgetpass.c:326
+#, c-format
+msgid "unable to set gid to %u"
+msgstr "無法將群組 ID 設定為 %u"
+
+#: src/tgetpass.c:336
+#, c-format
+msgid "unable to set uid to %u"
+msgstr "無法將使用者 ID 設定為 %u"
+
+#: src/tgetpass.c:341
+#, c-format
+msgid "unable to run %s"
+msgstr "無法執行 %s"
+
+#: src/utmp.c:288
+msgid "unable to save stdin"
+msgstr "無法儲存標準輸入"
+
+#: src/utmp.c:290
+msgid "unable to dup2 stdin"
+msgstr "無法對標準輸入執行 dup2 操作"
+
+#: src/utmp.c:293
+msgid "unable to restore stdin"
+msgstr "無法復原標準輸入"
+
+#~ msgid "%s must be owned by uid %d"
+#~ msgstr "%s 必須由使用者 ID 為 %d 的使用者所擁有"
+
+#~ msgid "%s must be only be writable by owner"
+#~ msgstr "%s 必須只能被其所有者可寫"
+
+#~ msgid "requires at least one argument"
+#~ msgstr "至少需要至少一個指令列引數"
+
+#~ msgid "unable to run %s as a login shell"
+#~ msgstr "無法以登入 shell 執行 %s"
+
+#~ msgid "unable to dup intercept fd"
+#~ msgstr "無法 dup intercept fd"
+
+#~ msgid "%s: missing message header"
+#~ msgstr "%s:缺少訊息標頭"
+
+#~ msgid "%s: expected message type %d, got %d"
+#~ msgstr "%s:期望的訊息類型是 %d 卻收到 %d"
+
+#~ msgid "unable to set tty context to %s"
+#~ msgstr "無法設定 tty 上下文為 %s"
+
+#~ msgid "%s%s: %s"
+#~ msgstr "%s%s: %s"
+
+#~ msgid "%s: short write"
+#~ msgstr "%s:過短寫入"
+
+#~ msgid "unable to read temporary file"
+#~ msgstr "無法讀取暫存檔案"
+
+#~ msgid "ignoring duplicate policy plugin \"%s\" in %s, line %d"
+#~ msgstr "無視 %2$s 中 %3$d 行的重複「%1$s」Sudo 政策外掛程式"
+
+#~ msgid "no tty present and no askpass program specified"
+#~ msgstr "未提供終端機且沒有指定 askpass 程式"
+
+#~ msgid "unknown uid %u: who are you?"
+#~ msgstr "未知的 %u 使用者識別碼:你是哪位啊?"
diff --git a/scripts/config.guess b/scripts/config.guess
new file mode 100755
index 0000000..69188da
--- /dev/null
+++ b/scripts/config.guess
@@ -0,0 +1,1774 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright 1992-2023 Free Software Foundation, Inc.
+
+# shellcheck disable=SC2006,SC2268 # see below for rationale
+
+timestamp='2023-01-01'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
+#
+# You can get the latest version of this script from:
+# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
+#
+# Please send patches to <config-patches@gnu.org>.
+
+
+# The "shellcheck disable" line above the timestamp inhibits complaints
+# about features and limitations of the classic Bourne shell that were
+# superseded or lifted in POSIX. However, this script identifies a wide
+# variety of pre-POSIX systems that do not have POSIX shells at all, and
+# even some reasonably current systems (Solaris 10 as case-in-point) still
+# have a pre-POSIX /bin/sh.
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Options:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2023 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+# Just in case it came from the environment.
+GUESS=
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+tmp=
+# shellcheck disable=SC2172
+trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
+
+set_cc_for_build() {
+ # prevent multiple calls if $tmp is already set
+ test "$tmp" && return 0
+ : "${TMPDIR=/tmp}"
+ # shellcheck disable=SC2039,SC3028
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
+ dummy=$tmp/dummy
+ case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
+ ,,) echo "int x;" > "$dummy.c"
+ for driver in cc gcc c89 c99 ; do
+ if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
+ CC_FOR_BUILD=$driver
+ break
+ fi
+ done
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+ esac
+}
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if test -f /.attbin/uname ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case $UNAME_SYSTEM in
+Linux|GNU|GNU/*)
+ LIBC=unknown
+
+ set_cc_for_build
+ cat <<-EOF > "$dummy.c"
+ #include <features.h>
+ #if defined(__UCLIBC__)
+ LIBC=uclibc
+ #elif defined(__dietlibc__)
+ LIBC=dietlibc
+ #elif defined(__GLIBC__)
+ LIBC=gnu
+ #else
+ #include <stdarg.h>
+ /* First heuristic to detect musl libc. */
+ #ifdef __DEFINED_va_list
+ LIBC=musl
+ #endif
+ #endif
+ EOF
+ cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ eval "$cc_set_libc"
+
+ # Second heuristic to detect musl libc.
+ if [ "$LIBC" = unknown ] &&
+ command -v ldd >/dev/null &&
+ ldd --version 2>&1 | grep -q ^musl; then
+ LIBC=musl
+ fi
+
+ # If the system lacks a compiler, then just pick glibc.
+ # We could probably try harder.
+ if [ "$LIBC" = unknown ]; then
+ LIBC=gnu
+ fi
+ ;;
+esac
+
+# Note: order is significant - the case branches are not exclusive.
+
+case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+ /sbin/sysctl -n hw.machine_arch 2>/dev/null || \
+ /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
+ echo unknown)`
+ case $UNAME_MACHINE_ARCH in
+ aarch64eb) machine=aarch64_be-unknown ;;
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ earmv*)
+ arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
+ machine=${arch}${endian}-unknown
+ ;;
+ *) machine=$UNAME_MACHINE_ARCH-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently (or will in the future) and ABI.
+ case $UNAME_MACHINE_ARCH in
+ earm*)
+ os=netbsdelf
+ ;;
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ELF__
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # Determine ABI tags.
+ case $UNAME_MACHINE_ARCH in
+ earm*)
+ expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+ abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case $UNAME_VERSION in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ GUESS=$machine-${os}${release}${abi-}
+ ;;
+ *:Bitrig:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE
+ ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE
+ ;;
+ *:SecBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE
+ ;;
+ *:LibertyBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE
+ ;;
+ *:MidnightBSD:*:*)
+ GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE
+ ;;
+ *:ekkoBSD:*:*)
+ GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE
+ ;;
+ *:SolidBSD:*:*)
+ GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE
+ ;;
+ *:OS108:*:*)
+ GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE
+ ;;
+ macppc:MirBSD:*:*)
+ GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE
+ ;;
+ *:MirBSD:*:*)
+ GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE
+ ;;
+ *:Sortix:*:*)
+ GUESS=$UNAME_MACHINE-unknown-sortix
+ ;;
+ *:Twizzler:*:*)
+ GUESS=$UNAME_MACHINE-unknown-twizzler
+ ;;
+ *:Redox:*:*)
+ GUESS=$UNAME_MACHINE-unknown-redox
+ ;;
+ mips:OSF1:*.*)
+ GUESS=mips-dec-osf1
+ ;;
+ alpha:OSF1:*:*)
+ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+ trap '' 0
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case $ALPHA_CPU_TYPE in
+ "EV4 (21064)")
+ UNAME_MACHINE=alpha ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE=alpha ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE=alpha ;;
+ "EV5 (21164)")
+ UNAME_MACHINE=alphaev5 ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE=alphaev56 ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE=alphapca56 ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE=alphapca57 ;;
+ "EV6 (21264)")
+ UNAME_MACHINE=alphaev6 ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE=alphaev67 ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE=alphaev69 ;;
+ "EV7 (21364)")
+ UNAME_MACHINE=alphaev7 ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE=alphaev79 ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ GUESS=$UNAME_MACHINE-dec-osf$OSF_REL
+ ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ GUESS=m68k-unknown-sysv4
+ ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ GUESS=$UNAME_MACHINE-unknown-amigaos
+ ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ GUESS=$UNAME_MACHINE-unknown-morphos
+ ;;
+ *:OS/390:*:*)
+ GUESS=i370-ibm-openedition
+ ;;
+ *:z/VM:*:*)
+ GUESS=s390-ibm-zvmoe
+ ;;
+ *:OS400:*:*)
+ GUESS=powerpc-ibm-os400
+ ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ GUESS=arm-acorn-riscix$UNAME_RELEASE
+ ;;
+ arm*:riscos:*:*|arm*:RISCOS:*:*)
+ GUESS=arm-unknown-riscos
+ ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ GUESS=hppa1.1-hitachi-hiuxmpp
+ ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ case `(/bin/universe) 2>/dev/null` in
+ att) GUESS=pyramid-pyramid-sysv3 ;;
+ *) GUESS=pyramid-pyramid-bsd ;;
+ esac
+ ;;
+ NILE*:*:*:dcosx)
+ GUESS=pyramid-pyramid-svr4
+ ;;
+ DRS?6000:unix:4.0:6*)
+ GUESS=sparc-icl-nx6
+ ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) GUESS=sparc-icl-nx7 ;;
+ esac
+ ;;
+ s390x:SunOS:*:*)
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL
+ ;;
+ sun4H:SunOS:5.*:*)
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-hal-solaris2$SUN_REL
+ ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-sun-solaris2$SUN_REL
+ ;;
+ i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+ GUESS=i386-pc-auroraux$UNAME_RELEASE
+ ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ set_cc_for_build
+ SUN_ARCH=i386
+ # If there is a compiler, see if it is configured for 64-bit objects.
+ # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+ # This test works for both compilers.
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ SUN_ARCH=x86_64
+ fi
+ fi
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=$SUN_ARCH-pc-solaris2$SUN_REL
+ ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-sun-solaris3$SUN_REL
+ ;;
+ sun4*:SunOS:*:*)
+ case `/usr/bin/arch -k` in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
+ GUESS=sparc-sun-sunos$SUN_REL
+ ;;
+ sun3*:SunOS:*:*)
+ GUESS=m68k-sun-sunos$UNAME_RELEASE
+ ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
+ case `/bin/arch` in
+ sun3)
+ GUESS=m68k-sun-sunos$UNAME_RELEASE
+ ;;
+ sun4)
+ GUESS=sparc-sun-sunos$UNAME_RELEASE
+ ;;
+ esac
+ ;;
+ aushp:SunOS:*:*)
+ GUESS=sparc-auspex-sunos$UNAME_RELEASE
+ ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ GUESS=m68k-milan-mint$UNAME_RELEASE
+ ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ GUESS=m68k-hades-mint$UNAME_RELEASE
+ ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ GUESS=m68k-unknown-mint$UNAME_RELEASE
+ ;;
+ m68k:machten:*:*)
+ GUESS=m68k-apple-machten$UNAME_RELEASE
+ ;;
+ powerpc:machten:*:*)
+ GUESS=powerpc-apple-machten$UNAME_RELEASE
+ ;;
+ RISC*:Mach:*:*)
+ GUESS=mips-dec-mach_bsd4.3
+ ;;
+ RISC*:ULTRIX:*:*)
+ GUESS=mips-dec-ultrix$UNAME_RELEASE
+ ;;
+ VAX*:ULTRIX*:*:*)
+ GUESS=vax-dec-ultrix$UNAME_RELEASE
+ ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ GUESS=clipper-intergraph-clix$UNAME_RELEASE
+ ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
+ dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ GUESS=mips-mips-riscos$UNAME_RELEASE
+ ;;
+ Motorola:PowerMAX_OS:*:*)
+ GUESS=powerpc-motorola-powermax
+ ;;
+ Motorola:*:4.3:PL8-*)
+ GUESS=powerpc-harris-powermax
+ ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ GUESS=powerpc-harris-powermax
+ ;;
+ Night_Hawk:Power_UNIX:*:*)
+ GUESS=powerpc-harris-powerunix
+ ;;
+ m88k:CX/UX:7*:*)
+ GUESS=m88k-harris-cxux7
+ ;;
+ m88k:*:4*:R4*)
+ GUESS=m88k-motorola-sysv4
+ ;;
+ m88k:*:3*:R3*)
+ GUESS=m88k-motorola-sysv3
+ ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
+ then
+ if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
+ test "$TARGET_BINARY_INTERFACE"x = x
+ then
+ GUESS=m88k-dg-dgux$UNAME_RELEASE
+ else
+ GUESS=m88k-dg-dguxbcs$UNAME_RELEASE
+ fi
+ else
+ GUESS=i586-dg-dgux$UNAME_RELEASE
+ fi
+ ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ GUESS=m88k-dolphin-sysv3
+ ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ GUESS=m88k-motorola-sysv3
+ ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ GUESS=m88k-tektronix-sysv3
+ ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ GUESS=m68k-tektronix-bsd
+ ;;
+ *:IRIX*:*:*)
+ IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'`
+ GUESS=mips-sgi-irix$IRIX_REL
+ ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ GUESS=i386-ibm-aix
+ ;;
+ ia64:AIX:*:*)
+ if test -x /usr/bin/oslevel ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
+ fi
+ GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV
+ ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
+ then
+ GUESS=$SYSTEM_NAME
+ else
+ GUESS=rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ GUESS=rs6000-ibm-aix3.2.4
+ else
+ GUESS=rs6000-ibm-aix3.2
+ fi
+ ;;
+ *:AIX:*:[4567])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if test -x /usr/bin/lslpp ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \
+ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
+ else
+ IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
+ fi
+ GUESS=$IBM_ARCH-ibm-aix$IBM_REV
+ ;;
+ *:AIX:*:*)
+ GUESS=rs6000-ibm-aix
+ ;;
+ ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
+ GUESS=romp-ibm-bsd4.4
+ ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to
+ ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ GUESS=rs6000-bull-bosx
+ ;;
+ DPX/2?00:B.O.S.:*:*)
+ GUESS=m68k-bull-sysv3
+ ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ GUESS=m68k-hp-bsd
+ ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ GUESS=m68k-hp-bsd4.4
+ ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
+ case $UNAME_MACHINE in
+ 9000/31?) HP_ARCH=m68000 ;;
+ 9000/[34]??) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if test -x /usr/bin/getconf; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case $sc_cpu_version in
+ 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case $sc_kernel_bits in
+ 32) HP_ARCH=hppa2.0n ;;
+ 64) HP_ARCH=hppa2.0w ;;
+ '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if test "$HP_ARCH" = ""; then
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if test "$HP_ARCH" = hppa2.0w
+ then
+ set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep -q __LP64__
+ then
+ HP_ARCH=hppa2.0w
+ else
+ HP_ARCH=hppa64
+ fi
+ fi
+ GUESS=$HP_ARCH-hp-hpux$HPUX_REV
+ ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
+ GUESS=ia64-hp-hpux$HPUX_REV
+ ;;
+ 3050*:HI-UX:*:*)
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ GUESS=unknown-hitachi-hiuxwe2
+ ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
+ GUESS=hppa1.1-hp-bsd
+ ;;
+ 9000/8??:4.3bsd:*:*)
+ GUESS=hppa1.0-hp-bsd
+ ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ GUESS=hppa1.0-hp-mpeix
+ ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
+ GUESS=hppa1.1-hp-osf
+ ;;
+ hp8??:OSF1:*:*)
+ GUESS=hppa1.0-hp-osf
+ ;;
+ i*86:OSF1:*:*)
+ if test -x /usr/sbin/sysversion ; then
+ GUESS=$UNAME_MACHINE-unknown-osf1mk
+ else
+ GUESS=$UNAME_MACHINE-unknown-osf1
+ fi
+ ;;
+ parisc*:Lites*:*:*)
+ GUESS=hppa1.1-hp-lites
+ ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ GUESS=c1-convex-bsd
+ ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ GUESS=c34-convex-bsd
+ ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ GUESS=c38-convex-bsd
+ ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ GUESS=c4-convex-bsd
+ ;;
+ CRAY*Y-MP:*:*:*)
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=ymp-cray-unicos$CRAY_REL
+ ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=t90-cray-unicos$CRAY_REL
+ ;;
+ CRAY*T3E:*:*:*)
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=alphaev5-cray-unicosmk$CRAY_REL
+ ;;
+ CRAY*SV1:*:*:*)
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=sv1-cray-unicos$CRAY_REL
+ ;;
+ *:UNICOS/mp:*:*)
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=craynv-cray-unicosmp$CRAY_REL
+ ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
+ GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
+ ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+ GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
+ ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE
+ ;;
+ sparc*:BSD/OS:*:*)
+ GUESS=sparc-unknown-bsdi$UNAME_RELEASE
+ ;;
+ *:BSD/OS:*:*)
+ GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE
+ ;;
+ arm:FreeBSD:*:*)
+ UNAME_PROCESSOR=`uname -p`
+ set_cc_for_build
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi
+ else
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf
+ fi
+ ;;
+ *:FreeBSD:*:*)
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ case $UNAME_PROCESSOR in
+ amd64)
+ UNAME_PROCESSOR=x86_64 ;;
+ i386)
+ UNAME_PROCESSOR=i586 ;;
+ esac
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL
+ ;;
+ i*:CYGWIN*:*)
+ GUESS=$UNAME_MACHINE-pc-cygwin
+ ;;
+ *:MINGW64*:*)
+ GUESS=$UNAME_MACHINE-pc-mingw64
+ ;;
+ *:MINGW*:*)
+ GUESS=$UNAME_MACHINE-pc-mingw32
+ ;;
+ *:MSYS*:*)
+ GUESS=$UNAME_MACHINE-pc-msys
+ ;;
+ i*:PW*:*)
+ GUESS=$UNAME_MACHINE-pc-pw32
+ ;;
+ *:SerenityOS:*:*)
+ GUESS=$UNAME_MACHINE-pc-serenity
+ ;;
+ *:Interix*:*)
+ case $UNAME_MACHINE in
+ x86)
+ GUESS=i586-pc-interix$UNAME_RELEASE
+ ;;
+ authenticamd | genuineintel | EM64T)
+ GUESS=x86_64-unknown-interix$UNAME_RELEASE
+ ;;
+ IA64)
+ GUESS=ia64-unknown-interix$UNAME_RELEASE
+ ;;
+ esac ;;
+ i*:UWIN*:*)
+ GUESS=$UNAME_MACHINE-pc-uwin
+ ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ GUESS=x86_64-pc-cygwin
+ ;;
+ prep*:SunOS:5.*:*)
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=powerpcle-unknown-solaris2$SUN_REL
+ ;;
+ *:GNU:*:*)
+ # the GNU system
+ GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'`
+ GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'`
+ GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL
+ ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"`
+ GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC
+ ;;
+ x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*)
+ GUESS="$UNAME_MACHINE-pc-managarm-mlibc"
+ ;;
+ *:[Mm]anagarm:*:*)
+ GUESS="$UNAME_MACHINE-unknown-managarm-mlibc"
+ ;;
+ *:Minix:*:*)
+ GUESS=$UNAME_MACHINE-unknown-minix
+ ;;
+ aarch64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ aarch64_be:Linux:*:*)
+ UNAME_MACHINE=aarch64_be
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep -q ld.so.1
+ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ arm*:Linux:*:*)
+ set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ else
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi
+ else
+ GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf
+ fi
+ fi
+ ;;
+ avr32*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ cris:Linux:*:*)
+ GUESS=$UNAME_MACHINE-axis-linux-$LIBC
+ ;;
+ crisv32:Linux:*:*)
+ GUESS=$UNAME_MACHINE-axis-linux-$LIBC
+ ;;
+ e2k:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ frv:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ hexagon:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ i*86:Linux:*:*)
+ GUESS=$UNAME_MACHINE-pc-linux-$LIBC
+ ;;
+ ia64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ k1om:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ loongarch32:Linux:*:* | loongarch64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ m32r*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ m68*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ mips:Linux:*:* | mips64:Linux:*:*)
+ set_cc_for_build
+ IS_GLIBC=0
+ test x"${LIBC}" = xgnu && IS_GLIBC=1
+ sed 's/^ //' << EOF > "$dummy.c"
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #undef mips64
+ #undef mips64el
+ #if ${IS_GLIBC} && defined(_ABI64)
+ LIBCABI=gnuabi64
+ #else
+ #if ${IS_GLIBC} && defined(_ABIN32)
+ LIBCABI=gnuabin32
+ #else
+ LIBCABI=${LIBC}
+ #endif
+ #endif
+
+ #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+ CPU=mipsisa64r6
+ #else
+ #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+ CPU=mipsisa32r6
+ #else
+ #if defined(__mips64)
+ CPU=mips64
+ #else
+ CPU=mips
+ #endif
+ #endif
+ #endif
+
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ MIPS_ENDIAN=el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ MIPS_ENDIAN=
+ #else
+ MIPS_ENDIAN=
+ #endif
+ #endif
+EOF
+ cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`
+ eval "$cc_set_vars"
+ test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
+ ;;
+ mips64el:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ openrisc*:Linux:*:*)
+ GUESS=or1k-unknown-linux-$LIBC
+ ;;
+ or32:Linux:*:* | or1k*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ padre:Linux:*:*)
+ GUESS=sparc-unknown-linux-$LIBC
+ ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ GUESS=hppa64-unknown-linux-$LIBC
+ ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;;
+ PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;;
+ *) GUESS=hppa-unknown-linux-$LIBC ;;
+ esac
+ ;;
+ ppc64:Linux:*:*)
+ GUESS=powerpc64-unknown-linux-$LIBC
+ ;;
+ ppc:Linux:*:*)
+ GUESS=powerpc-unknown-linux-$LIBC
+ ;;
+ ppc64le:Linux:*:*)
+ GUESS=powerpc64le-unknown-linux-$LIBC
+ ;;
+ ppcle:Linux:*:*)
+ GUESS=powerpcle-unknown-linux-$LIBC
+ ;;
+ riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ GUESS=$UNAME_MACHINE-ibm-linux-$LIBC
+ ;;
+ sh64*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ sh*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ tile*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ vax:Linux:*:*)
+ GUESS=$UNAME_MACHINE-dec-linux-$LIBC
+ ;;
+ x86_64:Linux:*:*)
+ set_cc_for_build
+ CPU=$UNAME_MACHINE
+ LIBCABI=$LIBC
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ ABI=64
+ sed 's/^ //' << EOF > "$dummy.c"
+ #ifdef __i386__
+ ABI=x86
+ #else
+ #ifdef __ILP32__
+ ABI=x32
+ #endif
+ #endif
+EOF
+ cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
+ eval "$cc_set_abi"
+ case $ABI in
+ x86) CPU=i686 ;;
+ x32) LIBCABI=${LIBC}x32 ;;
+ esac
+ fi
+ GUESS=$CPU-pc-linux-$LIBCABI
+ ;;
+ xtensa*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ GUESS=i386-sequent-sysv4
+ ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
+ ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ GUESS=$UNAME_MACHINE-pc-os2-emx
+ ;;
+ i*86:XTS-300:*:STOP)
+ GUESS=$UNAME_MACHINE-unknown-stop
+ ;;
+ i*86:atheos:*:*)
+ GUESS=$UNAME_MACHINE-unknown-atheos
+ ;;
+ i*86:syllable:*:*)
+ GUESS=$UNAME_MACHINE-pc-syllable
+ ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+ GUESS=i386-unknown-lynxos$UNAME_RELEASE
+ ;;
+ i*86:*DOS:*:*)
+ GUESS=$UNAME_MACHINE-pc-msdosdjgpp
+ ;;
+ i*86:*:4.*:*)
+ UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL
+ else
+ GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL
+ fi
+ ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ GUESS=$UNAME_MACHINE-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL
+ else
+ GUESS=$UNAME_MACHINE-pc-sysv32
+ fi
+ ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configure will decide that
+ # this is a cross-build.
+ GUESS=i586-pc-msdosdjgpp
+ ;;
+ Intel:Mach:3*:*)
+ GUESS=i386-pc-mach3
+ ;;
+ paragon:*:*:*)
+ GUESS=i860-intel-osf1
+ ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4
+ fi
+ ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ GUESS=m68010-convergent-sysv
+ ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ GUESS=m68k-convergent-sysv
+ ;;
+ M680?0:D-NIX:5.3:*)
+ GUESS=m68k-diab-dnix
+ ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ GUESS=m68k-unknown-lynxos$UNAME_RELEASE
+ ;;
+ mc68030:UNIX_System_V:4.*:*)
+ GUESS=m68k-atari-sysv4
+ ;;
+ TSUNAMI:LynxOS:2.*:*)
+ GUESS=sparc-unknown-lynxos$UNAME_RELEASE
+ ;;
+ rs6000:LynxOS:2.*:*)
+ GUESS=rs6000-unknown-lynxos$UNAME_RELEASE
+ ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+ GUESS=powerpc-unknown-lynxos$UNAME_RELEASE
+ ;;
+ SM[BE]S:UNIX_SV:*:*)
+ GUESS=mips-dde-sysv$UNAME_RELEASE
+ ;;
+ RM*:ReliantUNIX-*:*:*)
+ GUESS=mips-sni-sysv4
+ ;;
+ RM*:SINIX-*:*:*)
+ GUESS=mips-sni-sysv4
+ ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ GUESS=$UNAME_MACHINE-sni-sysv4
+ else
+ GUESS=ns32k-sni-sysv
+ fi
+ ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ GUESS=i586-unisys-sysv4
+ ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ GUESS=hppa1.1-stratus-sysv4
+ ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ GUESS=i860-stratus-sysv4
+ ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ GUESS=$UNAME_MACHINE-stratus-vos
+ ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ GUESS=hppa1.1-stratus-vos
+ ;;
+ mc68*:A/UX:*:*)
+ GUESS=m68k-apple-aux$UNAME_RELEASE
+ ;;
+ news*:NEWS-OS:6*:*)
+ GUESS=mips-sony-newsos6
+ ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if test -d /usr/nec; then
+ GUESS=mips-nec-sysv$UNAME_RELEASE
+ else
+ GUESS=mips-unknown-sysv$UNAME_RELEASE
+ fi
+ ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ GUESS=powerpc-be-beos
+ ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ GUESS=powerpc-apple-beos
+ ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ GUESS=i586-pc-beos
+ ;;
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ GUESS=i586-pc-haiku
+ ;;
+ ppc:Haiku:*:*) # Haiku running on Apple PowerPC
+ GUESS=powerpc-apple-haiku
+ ;;
+ *:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat)
+ GUESS=$UNAME_MACHINE-unknown-haiku
+ ;;
+ SX-4:SUPER-UX:*:*)
+ GUESS=sx4-nec-superux$UNAME_RELEASE
+ ;;
+ SX-5:SUPER-UX:*:*)
+ GUESS=sx5-nec-superux$UNAME_RELEASE
+ ;;
+ SX-6:SUPER-UX:*:*)
+ GUESS=sx6-nec-superux$UNAME_RELEASE
+ ;;
+ SX-7:SUPER-UX:*:*)
+ GUESS=sx7-nec-superux$UNAME_RELEASE
+ ;;
+ SX-8:SUPER-UX:*:*)
+ GUESS=sx8-nec-superux$UNAME_RELEASE
+ ;;
+ SX-8R:SUPER-UX:*:*)
+ GUESS=sx8r-nec-superux$UNAME_RELEASE
+ ;;
+ SX-ACE:SUPER-UX:*:*)
+ GUESS=sxace-nec-superux$UNAME_RELEASE
+ ;;
+ Power*:Rhapsody:*:*)
+ GUESS=powerpc-apple-rhapsody$UNAME_RELEASE
+ ;;
+ *:Rhapsody:*:*)
+ GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE
+ ;;
+ arm64:Darwin:*:*)
+ GUESS=aarch64-apple-darwin$UNAME_RELEASE
+ ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p`
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ if command -v xcode-select > /dev/null 2> /dev/null && \
+ ! xcode-select --print-path > /dev/null 2> /dev/null ; then
+ # Avoid executing cc if there is no toolchain installed as
+ # cc will be a stub that puts up a graphical alert
+ # prompting the user to install developer tools.
+ CC_FOR_BUILD=no_compiler_found
+ else
+ set_cc_for_build
+ fi
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+ if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_PPC >/dev/null
+ then
+ UNAME_PROCESSOR=powerpc
+ fi
+ elif test "$UNAME_PROCESSOR" = i386 ; then
+ # uname -m returns i386 or x86_64
+ UNAME_PROCESSOR=$UNAME_MACHINE
+ fi
+ GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE
+ ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = x86; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE
+ ;;
+ *:QNX:*:4*)
+ GUESS=i386-pc-qnx
+ ;;
+ NEO-*:NONSTOP_KERNEL:*:*)
+ GUESS=neo-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSE-*:NONSTOP_KERNEL:*:*)
+ GUESS=nse-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSR-*:NONSTOP_KERNEL:*:*)
+ GUESS=nsr-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSV-*:NONSTOP_KERNEL:*:*)
+ GUESS=nsv-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSX-*:NONSTOP_KERNEL:*:*)
+ GUESS=nsx-tandem-nsk$UNAME_RELEASE
+ ;;
+ *:NonStop-UX:*:*)
+ GUESS=mips-compaq-nonstopux
+ ;;
+ BS2000:POSIX*:*:*)
+ GUESS=bs2000-siemens-sysv
+ ;;
+ DS/*:UNIX_System_V:*:*)
+ GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE
+ ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "${cputype-}" = 386; then
+ UNAME_MACHINE=i386
+ elif test "x${cputype-}" != x; then
+ UNAME_MACHINE=$cputype
+ fi
+ GUESS=$UNAME_MACHINE-unknown-plan9
+ ;;
+ *:TOPS-10:*:*)
+ GUESS=pdp10-unknown-tops10
+ ;;
+ *:TENEX:*:*)
+ GUESS=pdp10-unknown-tenex
+ ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ GUESS=pdp10-dec-tops20
+ ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ GUESS=pdp10-xkl-tops20
+ ;;
+ *:TOPS-20:*:*)
+ GUESS=pdp10-unknown-tops20
+ ;;
+ *:ITS:*:*)
+ GUESS=pdp10-unknown-its
+ ;;
+ SEI:*:*:SEIUX)
+ GUESS=mips-sei-seiux$UNAME_RELEASE
+ ;;
+ *:DragonFly:*:*)
+ DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL
+ ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case $UNAME_MACHINE in
+ A*) GUESS=alpha-dec-vms ;;
+ I*) GUESS=ia64-dec-vms ;;
+ V*) GUESS=vax-dec-vms ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ GUESS=i386-pc-xenix
+ ;;
+ i*86:skyos:*:*)
+ SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`
+ GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL
+ ;;
+ i*86:rdos:*:*)
+ GUESS=$UNAME_MACHINE-pc-rdos
+ ;;
+ i*86:Fiwix:*:*)
+ GUESS=$UNAME_MACHINE-pc-fiwix
+ ;;
+ *:AROS:*:*)
+ GUESS=$UNAME_MACHINE-unknown-aros
+ ;;
+ x86_64:VMkernel:*:*)
+ GUESS=$UNAME_MACHINE-unknown-esx
+ ;;
+ amd64:Isilon\ OneFS:*:*)
+ GUESS=x86_64-unknown-onefs
+ ;;
+ *:Unleashed:*:*)
+ GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
+ ;;
+esac
+
+# Do we have a guess based on uname results?
+if test "x$GUESS" != x; then
+ echo "$GUESS"
+ exit
+fi
+
+# No uname command or uname output not recognized.
+set_cc_for_build
+cat > "$dummy.c" <<EOF
+#ifdef _SEQUENT_
+#include <sys/types.h>
+#include <sys/utsname.h>
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#include <signal.h>
+#if defined(_SIZE_T_) || defined(SIGLOST)
+#include <sys/utsname.h>
+#endif
+#endif
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+#include <sys/param.h>
+#if defined (BSD)
+#if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+#else
+#if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#else
+ printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#endif
+#else
+ printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#else
+#if defined(_SIZE_T_) || defined(SIGLOST)
+ struct utsname un;
+ uname (&un);
+ printf ("vax-dec-ultrix%s\n", un.release); exit (0);
+#else
+ printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#if defined(_SIZE_T_) || defined(SIGLOST)
+ struct utsname *un;
+ uname (&un);
+ printf ("mips-dec-ultrix%s\n", un.release); exit (0);
+#else
+ printf ("mips-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
+
+echo "$0: unable to guess system type" >&2
+
+case $UNAME_MACHINE:$UNAME_SYSTEM in
+ mips:Linux | mips64:Linux)
+ # If we got here on MIPS GNU/Linux, output extra information.
+ cat >&2 <<EOF
+
+NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
+the system type. Please install a C compiler and try again.
+EOF
+ ;;
+esac
+
+cat >&2 <<EOF
+
+This script (version $timestamp), has failed to recognize the
+operating system you are using. If your script is old, overwrite *all*
+copies of config.guess and config.sub with the latest versions from:
+
+ https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
+and
+ https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
+EOF
+
+our_year=`echo $timestamp | sed 's,-.*,,'`
+thisyear=`date +%Y`
+# shellcheck disable=SC2003
+script_age=`expr "$thisyear" - "$our_year"`
+if test "$script_age" -lt 3 ; then
+ cat >&2 <<EOF
+
+If $0 has already been updated, send the following data and any
+information you think might be pertinent to config-patches@gnu.org to
+provide the necessary information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = "$UNAME_MACHINE"
+UNAME_RELEASE = "$UNAME_RELEASE"
+UNAME_SYSTEM = "$UNAME_SYSTEM"
+UNAME_VERSION = "$UNAME_VERSION"
+EOF
+fi
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/scripts/config.sub b/scripts/config.sub
new file mode 100755
index 0000000..de4259e
--- /dev/null
+++ b/scripts/config.sub
@@ -0,0 +1,1907 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright 1992-2023 Free Software Foundation, Inc.
+
+# shellcheck disable=SC2006,SC2268 # see below for rationale
+
+timestamp='2023-01-21'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+# The "shellcheck disable" line above the timestamp inhibits complaints
+# about features and limitations of the classic Bourne shell that were
+# superseded or lifted in POSIX. However, this script identifies a wide
+# variety of pre-POSIX systems that do not have POSIX shells at all, and
+# even some reasonably current systems (Solaris 10 as case-in-point) still
+# have a pre-POSIX /bin/sh.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
+
+Canonicalize a configuration name.
+
+Options:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2023 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo "$1"
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Split fields of configuration type
+# shellcheck disable=SC2162
+saved_IFS=$IFS
+IFS="-" read field1 field2 field3 field4 <<EOF
+$1
+EOF
+IFS=$saved_IFS
+
+# Separate into logical components for further validation
+case $1 in
+ *-*-*-*-*)
+ echo Invalid configuration \`"$1"\': more than four components >&2
+ exit 1
+ ;;
+ *-*-*-*)
+ basic_machine=$field1-$field2
+ basic_os=$field3-$field4
+ ;;
+ *-*-*)
+ # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
+ # parts
+ maybe_os=$field2-$field3
+ case $maybe_os in
+ nto-qnx* | linux-* | uclinux-uclibc* \
+ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
+ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
+ | storm-chaos* | os2-emx* | rtmk-nova* | managarm-*)
+ basic_machine=$field1
+ basic_os=$maybe_os
+ ;;
+ android-linux)
+ basic_machine=$field1-unknown
+ basic_os=linux-android
+ ;;
+ *)
+ basic_machine=$field1-$field2
+ basic_os=$field3
+ ;;
+ esac
+ ;;
+ *-*)
+ # A lone config we happen to match not fitting any pattern
+ case $field1-$field2 in
+ decstation-3100)
+ basic_machine=mips-dec
+ basic_os=
+ ;;
+ *-*)
+ # Second component is usually, but not always the OS
+ case $field2 in
+ # Prevent following clause from handling this valid os
+ sun*os*)
+ basic_machine=$field1
+ basic_os=$field2
+ ;;
+ zephyr*)
+ basic_machine=$field1-unknown
+ basic_os=$field2
+ ;;
+ # Manufacturers
+ dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
+ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
+ | unicom* | ibm* | next | hp | isi* | apollo | altos* \
+ | convergent* | ncr* | news | 32* | 3600* | 3100* \
+ | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \
+ | ultra | tti* | harris | dolphin | highlevel | gould \
+ | cbm | ns | masscomp | apple | axis | knuth | cray \
+ | microblaze* | sim | cisco \
+ | oki | wec | wrs | winbond)
+ basic_machine=$field1-$field2
+ basic_os=
+ ;;
+ *)
+ basic_machine=$field1
+ basic_os=$field2
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *)
+ # Convert single-component short-hands not valid as part of
+ # multi-component configurations.
+ case $field1 in
+ 386bsd)
+ basic_machine=i386-pc
+ basic_os=bsd
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ basic_os=scout
+ ;;
+ alliant)
+ basic_machine=fx80-alliant
+ basic_os=
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ basic_os=
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ basic_os=bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ basic_os=sysv
+ ;;
+ amiga)
+ basic_machine=m68k-unknown
+ basic_os=
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ basic_os=amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ basic_os=sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ basic_os=sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ basic_os=bsd
+ ;;
+ aros)
+ basic_machine=i386-pc
+ basic_os=aros
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ basic_os=aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ basic_os=dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ basic_os=linux
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ basic_os=cegcc
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ basic_os=bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ basic_os=bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ basic_os=bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ basic_os=bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ basic_os=bsd
+ ;;
+ cray)
+ basic_machine=j90-cray
+ basic_os=unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ basic_os=
+ ;;
+ da30)
+ basic_machine=m68k-da30
+ basic_os=
+ ;;
+ decstation | pmax | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ basic_os=
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ basic_os=sysv3
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ basic_os=dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ basic_os=msdosdjgpp
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ basic_os=ebmon
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ basic_os=ose
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ basic_os=sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ basic_os=go32
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ basic_os=hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ basic_os=xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ basic_os=hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ basic_os=sysv3
+ ;;
+ hp300 | hp300hpux)
+ basic_machine=m68k-hp
+ basic_os=hpux
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ basic_os=bsd
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ basic_os=osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ basic_os=proelf
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ basic_os=mach
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ basic_os=sysv
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ basic_os=linux
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ basic_os=sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ basic_os=sysv
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ basic_os=mingw64
+ ;;
+ mingw32)
+ basic_machine=i686-pc
+ basic_os=mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ basic_os=mingw32ce
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ basic_os=coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ basic_os=morphos
+ ;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ basic_os=moxiebox
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ basic_os=msdos
+ ;;
+ msys)
+ basic_machine=i686-pc
+ basic_os=msys
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ basic_os=mvs
+ ;;
+ nacl)
+ basic_machine=le32-unknown
+ basic_os=nacl
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ basic_os=sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-pc
+ basic_os=netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ basic_os=linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ basic_os=newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ basic_os=newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ basic_os=sysv
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ basic_os=cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ basic_os=cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ basic_os=nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ basic_os=mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ basic_os=nonstopux
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ basic_os=os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ basic_os=ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ basic_os=os68k
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ basic_os=osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ basic_os=linux
+ ;;
+ psp)
+ basic_machine=mipsallegrexel-sony
+ basic_os=psp
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ basic_os=pw32
+ ;;
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ basic_os=rdos
+ ;;
+ rdos32)
+ basic_machine=i386-pc
+ basic_os=rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ basic_os=coff
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ sei)
+ basic_machine=mips-sei
+ basic_os=seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ basic_os=
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ basic_os=sysv2
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ basic_os=
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ basic_os=sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ basic_os=
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ basic_os=sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ basic_os=sunos4
+ ;;
+ sun3)
+ basic_machine=m68k-sun
+ basic_os=
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ basic_os=sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ basic_os=sunos4
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ basic_os=
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ basic_os=sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ basic_os=sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ basic_os=solaris2
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ basic_os=
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ basic_os=unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ basic_os=dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ basic_os=unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ basic_os=unicos
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ basic_os=tops20
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ basic_os=tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ basic_os=sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ basic_os=none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ basic_os=sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ basic_os=vms
+ ;;
+ vsta)
+ basic_machine=i386-pc
+ basic_os=vsta
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ basic_os=vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ basic_os=vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ basic_os=vxworks
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ basic_os=mingw32
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ basic_os=unicos
+ ;;
+ *)
+ basic_machine=$1
+ basic_os=
+ ;;
+ esac
+ ;;
+esac
+
+# Decode 1-component or ad-hoc basic machines
+case $basic_machine in
+ # Here we handle the default manufacturer of certain CPU types. It is in
+ # some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ cpu=hppa1.1
+ vendor=winbond
+ ;;
+ op50n)
+ cpu=hppa1.1
+ vendor=oki
+ ;;
+ op60c)
+ cpu=hppa1.1
+ vendor=oki
+ ;;
+ ibm*)
+ cpu=i370
+ vendor=ibm
+ ;;
+ orion105)
+ cpu=clipper
+ vendor=highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ cpu=m68k
+ vendor=apple
+ ;;
+ pmac | pmac-mpw)
+ cpu=powerpc
+ vendor=apple
+ ;;
+
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ cpu=m68000
+ vendor=att
+ ;;
+ 3b*)
+ cpu=we32k
+ vendor=att
+ ;;
+ bluegene*)
+ cpu=powerpc
+ vendor=ibm
+ basic_os=cnk
+ ;;
+ decsystem10* | dec10*)
+ cpu=pdp10
+ vendor=dec
+ basic_os=tops10
+ ;;
+ decsystem20* | dec20*)
+ cpu=pdp10
+ vendor=dec
+ basic_os=tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ cpu=m68k
+ vendor=motorola
+ ;;
+ dpx2*)
+ cpu=m68k
+ vendor=bull
+ basic_os=sysv3
+ ;;
+ encore | umax | mmax)
+ cpu=ns32k
+ vendor=encore
+ ;;
+ elxsi)
+ cpu=elxsi
+ vendor=elxsi
+ basic_os=${basic_os:-bsd}
+ ;;
+ fx2800)
+ cpu=i860
+ vendor=alliant
+ ;;
+ genix)
+ cpu=ns32k
+ vendor=ns
+ ;;
+ h3050r* | hiux*)
+ cpu=hppa1.1
+ vendor=hitachi
+ basic_os=hiuxwe2
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ cpu=hppa1.0
+ vendor=hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ cpu=m68000
+ vendor=hp
+ ;;
+ hp9k3[2-9][0-9])
+ cpu=m68k
+ vendor=hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ cpu=hppa1.0
+ vendor=hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ cpu=hppa1.1
+ vendor=hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ cpu=hppa1.1
+ vendor=hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ cpu=hppa1.1
+ vendor=hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ cpu=hppa1.1
+ vendor=hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ cpu=hppa1.0
+ vendor=hp
+ ;;
+ i*86v32)
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv32
+ ;;
+ i*86v4*)
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv4
+ ;;
+ i*86v)
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv
+ ;;
+ i*86sol2)
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=solaris2
+ ;;
+ j90 | j90-cray)
+ cpu=j90
+ vendor=cray
+ basic_os=${basic_os:-unicos}
+ ;;
+ iris | iris4d)
+ cpu=mips
+ vendor=sgi
+ case $basic_os in
+ irix*)
+ ;;
+ *)
+ basic_os=irix4
+ ;;
+ esac
+ ;;
+ miniframe)
+ cpu=m68000
+ vendor=convergent
+ ;;
+ *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ cpu=m68k
+ vendor=atari
+ basic_os=mint
+ ;;
+ news-3600 | risc-news)
+ cpu=mips
+ vendor=sony
+ basic_os=newsos
+ ;;
+ next | m*-next)
+ cpu=m68k
+ vendor=next
+ case $basic_os in
+ openstep*)
+ ;;
+ nextstep*)
+ ;;
+ ns2*)
+ basic_os=nextstep2
+ ;;
+ *)
+ basic_os=nextstep3
+ ;;
+ esac
+ ;;
+ np1)
+ cpu=np1
+ vendor=gould
+ ;;
+ op50n-* | op60c-*)
+ cpu=hppa1.1
+ vendor=oki
+ basic_os=proelf
+ ;;
+ pa-hitachi)
+ cpu=hppa1.1
+ vendor=hitachi
+ basic_os=hiuxwe2
+ ;;
+ pbd)
+ cpu=sparc
+ vendor=tti
+ ;;
+ pbb)
+ cpu=m68k
+ vendor=tti
+ ;;
+ pc532)
+ cpu=ns32k
+ vendor=pc532
+ ;;
+ pn)
+ cpu=pn
+ vendor=gould
+ ;;
+ power)
+ cpu=power
+ vendor=ibm
+ ;;
+ ps2)
+ cpu=i386
+ vendor=ibm
+ ;;
+ rm[46]00)
+ cpu=mips
+ vendor=siemens
+ ;;
+ rtpc | rtpc-*)
+ cpu=romp
+ vendor=ibm
+ ;;
+ sde)
+ cpu=mipsisa32
+ vendor=sde
+ basic_os=${basic_os:-elf}
+ ;;
+ simso-wrs)
+ cpu=sparclite
+ vendor=wrs
+ basic_os=vxworks
+ ;;
+ tower | tower-32)
+ cpu=m68k
+ vendor=ncr
+ ;;
+ vpp*|vx|vx-*)
+ cpu=f301
+ vendor=fujitsu
+ ;;
+ w65)
+ cpu=w65
+ vendor=wdc
+ ;;
+ w89k-*)
+ cpu=hppa1.1
+ vendor=winbond
+ basic_os=proelf
+ ;;
+ none)
+ cpu=none
+ vendor=none
+ ;;
+ leon|leon[3-9])
+ cpu=sparc
+ vendor=$basic_machine
+ ;;
+ leon-*|leon[3-9]-*)
+ cpu=sparc
+ vendor=`echo "$basic_machine" | sed 's/-.*//'`
+ ;;
+
+ *-*)
+ # shellcheck disable=SC2162
+ saved_IFS=$IFS
+ IFS="-" read cpu vendor <<EOF
+$basic_machine
+EOF
+ IFS=$saved_IFS
+ ;;
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ cpu=$basic_machine
+ vendor=pc
+ ;;
+ # These rules are duplicated from below for sake of the special case above;
+ # i.e. things that normalized to x86 arches should also default to "pc"
+ pc98)
+ cpu=i386
+ vendor=pc
+ ;;
+ x64 | amd64)
+ cpu=x86_64
+ vendor=pc
+ ;;
+ # Recognize the basic CPU types without company name.
+ *)
+ cpu=$basic_machine
+ vendor=unknown
+ ;;
+esac
+
+unset -v basic_machine
+
+# Decode basic machines in the full and proper CPU-Company form.
+case $cpu-$vendor in
+ # Here we handle the default manufacturer of certain CPU types in canonical form. It is in
+ # some cases the only manufacturer, in others, it is the most popular.
+ craynv-unknown)
+ vendor=cray
+ basic_os=${basic_os:-unicosmp}
+ ;;
+ c90-unknown | c90-cray)
+ vendor=cray
+ basic_os=${Basic_os:-unicos}
+ ;;
+ fx80-unknown)
+ vendor=alliant
+ ;;
+ romp-unknown)
+ vendor=ibm
+ ;;
+ mmix-unknown)
+ vendor=knuth
+ ;;
+ microblaze-unknown | microblazeel-unknown)
+ vendor=xilinx
+ ;;
+ rs6000-unknown)
+ vendor=ibm
+ ;;
+ vax-unknown)
+ vendor=dec
+ ;;
+ pdp11-unknown)
+ vendor=dec
+ ;;
+ we32k-unknown)
+ vendor=att
+ ;;
+ cydra-unknown)
+ vendor=cydrome
+ ;;
+ i370-ibm*)
+ vendor=ibm
+ ;;
+ orion-unknown)
+ vendor=highlevel
+ ;;
+ xps-unknown | xps100-unknown)
+ cpu=xps100
+ vendor=honeywell
+ ;;
+
+ # Here we normalize CPU types with a missing or matching vendor
+ armh-unknown | armh-alt)
+ cpu=armv7l
+ vendor=alt
+ basic_os=${basic_os:-linux-gnueabihf}
+ ;;
+ dpx20-unknown | dpx20-bull)
+ cpu=rs6000
+ vendor=bull
+ basic_os=${basic_os:-bosx}
+ ;;
+
+ # Here we normalize CPU types irrespective of the vendor
+ amd64-*)
+ cpu=x86_64
+ ;;
+ blackfin-*)
+ cpu=bfin
+ basic_os=linux
+ ;;
+ c54x-*)
+ cpu=tic54x
+ ;;
+ c55x-*)
+ cpu=tic55x
+ ;;
+ c6x-*)
+ cpu=tic6x
+ ;;
+ e500v[12]-*)
+ cpu=powerpc
+ basic_os=${basic_os}"spe"
+ ;;
+ mips3*-*)
+ cpu=mips64
+ ;;
+ ms1-*)
+ cpu=mt
+ ;;
+ m68knommu-*)
+ cpu=m68k
+ basic_os=linux
+ ;;
+ m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)
+ cpu=s12z
+ ;;
+ openrisc-*)
+ cpu=or32
+ ;;
+ parisc-*)
+ cpu=hppa
+ basic_os=linux
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ cpu=i586
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-* | athlon_*-*)
+ cpu=i686
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ cpu=i686
+ ;;
+ pentium4-*)
+ cpu=i786
+ ;;
+ pc98-*)
+ cpu=i386
+ ;;
+ ppc-* | ppcbe-*)
+ cpu=powerpc
+ ;;
+ ppcle-* | powerpclittle-*)
+ cpu=powerpcle
+ ;;
+ ppc64-*)
+ cpu=powerpc64
+ ;;
+ ppc64le-* | powerpc64little-*)
+ cpu=powerpc64le
+ ;;
+ sb1-*)
+ cpu=mipsisa64sb1
+ ;;
+ sb1el-*)
+ cpu=mipsisa64sb1el
+ ;;
+ sh5e[lb]-*)
+ cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'`
+ ;;
+ spur-*)
+ cpu=spur
+ ;;
+ strongarm-* | thumb-*)
+ cpu=arm
+ ;;
+ tx39-*)
+ cpu=mipstx39
+ ;;
+ tx39el-*)
+ cpu=mipstx39el
+ ;;
+ x64-*)
+ cpu=x86_64
+ ;;
+ xscale-* | xscalee[bl]-*)
+ cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
+ ;;
+ arm64-* | aarch64le-*)
+ cpu=aarch64
+ ;;
+
+ # Recognize the canonical CPU Types that limit and/or modify the
+ # company names they are paired with.
+ cr16-*)
+ basic_os=${basic_os:-elf}
+ ;;
+ crisv32-* | etraxfs*-*)
+ cpu=crisv32
+ vendor=axis
+ ;;
+ cris-* | etrax*-*)
+ cpu=cris
+ vendor=axis
+ ;;
+ crx-*)
+ basic_os=${basic_os:-elf}
+ ;;
+ neo-tandem)
+ cpu=neo
+ vendor=tandem
+ ;;
+ nse-tandem)
+ cpu=nse
+ vendor=tandem
+ ;;
+ nsr-tandem)
+ cpu=nsr
+ vendor=tandem
+ ;;
+ nsv-tandem)
+ cpu=nsv
+ vendor=tandem
+ ;;
+ nsx-tandem)
+ cpu=nsx
+ vendor=tandem
+ ;;
+ mipsallegrexel-sony)
+ cpu=mipsallegrexel
+ vendor=sony
+ ;;
+ tile*-*)
+ basic_os=${basic_os:-linux-gnu}
+ ;;
+
+ *)
+ # Recognize the canonical CPU types that are allowed with any
+ # company name.
+ case $cpu in
+ 1750a | 580 \
+ | a29k \
+ | aarch64 | aarch64_be \
+ | abacus \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
+ | alphapca5[67] | alpha64pca5[67] \
+ | am33_2.0 \
+ | amdgcn \
+ | arc | arceb | arc32 | arc64 \
+ | arm | arm[lb]e | arme[lb] | armv* \
+ | avr | avr32 \
+ | asmjs \
+ | ba \
+ | be32 | be64 \
+ | bfin | bpf | bs2000 \
+ | c[123]* | c30 | [cjt]90 | c4x \
+ | c8051 | clipper | craynv | csky | cydra \
+ | d10v | d30v | dlx | dsp16xx \
+ | e2k | elxsi | epiphany \
+ | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
+ | h8300 | h8500 \
+ | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
+ | i370 | i*86 | i860 | i960 | ia16 | ia64 \
+ | ip2k | iq2000 \
+ | k1om \
+ | le32 | le64 \
+ | lm32 \
+ | loongarch32 | loongarch64 \
+ | m32c | m32r | m32rle \
+ | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
+ | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
+ | m88110 | m88k | maxq | mb | mcore | mep | metag \
+ | microblaze | microblazeel \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64eb | mips64el \
+ | mips64octeon | mips64octeonel \
+ | mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa32r3 | mipsisa32r3el \
+ | mipsisa32r5 | mipsisa32r5el \
+ | mipsisa32r6 | mipsisa32r6el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64r3 | mipsisa64r3el \
+ | mipsisa64r5 | mipsisa64r5el \
+ | mipsisa64r6 | mipsisa64r6el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
+ | mipstx39 | mipstx39el \
+ | mmix \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nds32 | nds32le | nds32be \
+ | nfp \
+ | nios | nios2 | nios2eb | nios2el \
+ | none | np1 | ns16k | ns32k | nvptx \
+ | open8 \
+ | or1k* \
+ | or32 \
+ | orion \
+ | picochip \
+ | pdp10 | pdp11 | pj | pjl | pn | power \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
+ | pru \
+ | pyramid \
+ | riscv | riscv32 | riscv32be | riscv64 | riscv64be \
+ | rl78 | romp | rs6000 | rx \
+ | s390 | s390x \
+ | score \
+ | sh | shl \
+ | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \
+ | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \
+ | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
+ | spu \
+ | tahoe \
+ | thumbv7* \
+ | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
+ | tron \
+ | ubicom32 \
+ | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
+ | vax \
+ | visium \
+ | w65 \
+ | wasm32 | wasm64 \
+ | we32k \
+ | x86 | x86_64 | xc16x | xgate | xps100 \
+ | xstormy16 | xtensa* \
+ | ymp \
+ | z8k | z80)
+ ;;
+
+ *)
+ echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $vendor in
+ digital*)
+ vendor=dec
+ ;;
+ commodore*)
+ vendor=cbm
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if test x$basic_os != x
+then
+
+# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just
+# set os.
+case $basic_os in
+ gnu/linux*)
+ kernel=linux
+ os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'`
+ ;;
+ os2-emx)
+ kernel=os2
+ os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'`
+ ;;
+ nto-qnx*)
+ kernel=nto
+ os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'`
+ ;;
+ *-*)
+ # shellcheck disable=SC2162
+ saved_IFS=$IFS
+ IFS="-" read kernel os <<EOF
+$basic_os
+EOF
+ IFS=$saved_IFS
+ ;;
+ # Default OS when just kernel was specified
+ nto*)
+ kernel=nto
+ os=`echo "$basic_os" | sed -e 's|nto|qnx|'`
+ ;;
+ linux*)
+ kernel=linux
+ os=`echo "$basic_os" | sed -e 's|linux|gnu|'`
+ ;;
+ managarm*)
+ kernel=managarm
+ os=`echo "$basic_os" | sed -e 's|managarm|mlibc|'`
+ ;;
+ *)
+ kernel=
+ os=$basic_os
+ ;;
+esac
+
+# Now, normalize the OS (knowing we just have one component, it's not a kernel,
+# etc.)
+case $os in
+ # First match some system type aliases that might get confused
+ # with valid system types.
+ # solaris* is a basic system type, with this one exception.
+ auroraux)
+ os=auroraux
+ ;;
+ bluegene*)
+ os=cnk
+ ;;
+ solaris1 | solaris1.*)
+ os=`echo "$os" | sed -e 's|solaris1|sunos4|'`
+ ;;
+ solaris)
+ os=solaris2
+ ;;
+ unixware*)
+ os=sysv4.2uw
+ ;;
+ # es1800 is here to avoid being matched by es* (a different OS)
+ es1800*)
+ os=ose
+ ;;
+ # Some version numbers need modification
+ chorusos*)
+ os=chorusos
+ ;;
+ isc)
+ os=isc2.2
+ ;;
+ sco6)
+ os=sco5v6
+ ;;
+ sco5)
+ os=sco3.2v5
+ ;;
+ sco4)
+ os=sco3.2v4
+ ;;
+ sco3.2.[4-9]*)
+ os=`echo "$os" | sed -e 's/sco3.2./sco3.2v/'`
+ ;;
+ sco*v* | scout)
+ # Don't match below
+ ;;
+ sco*)
+ os=sco3.2v2
+ ;;
+ psos*)
+ os=psos
+ ;;
+ qnx*)
+ os=qnx
+ ;;
+ hiux*)
+ os=hiuxwe2
+ ;;
+ lynx*178)
+ os=lynxos178
+ ;;
+ lynx*5)
+ os=lynxos5
+ ;;
+ lynxos*)
+ # don't get caught up in next wildcard
+ ;;
+ lynx*)
+ os=lynxos
+ ;;
+ mac[0-9]*)
+ os=`echo "$os" | sed -e 's|mac|macos|'`
+ ;;
+ opened*)
+ os=openedition
+ ;;
+ os400*)
+ os=os400
+ ;;
+ sunos5*)
+ os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
+ ;;
+ sunos6*)
+ os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
+ ;;
+ wince*)
+ os=wince
+ ;;
+ utek*)
+ os=bsd
+ ;;
+ dynix*)
+ os=bsd
+ ;;
+ acis*)
+ os=aos
+ ;;
+ atheos*)
+ os=atheos
+ ;;
+ syllable*)
+ os=syllable
+ ;;
+ 386bsd)
+ os=bsd
+ ;;
+ ctix* | uts*)
+ os=sysv
+ ;;
+ nova*)
+ os=rtmk-nova
+ ;;
+ ns2)
+ os=nextstep2
+ ;;
+ # Preserve the version number of sinix5.
+ sinix5.*)
+ os=`echo "$os" | sed -e 's|sinix|sysv|'`
+ ;;
+ sinix*)
+ os=sysv4
+ ;;
+ tpf*)
+ os=tpf
+ ;;
+ triton*)
+ os=sysv3
+ ;;
+ oss*)
+ os=sysv3
+ ;;
+ svr4*)
+ os=sysv4
+ ;;
+ svr3)
+ os=sysv3
+ ;;
+ sysvr4)
+ os=sysv4
+ ;;
+ ose*)
+ os=ose
+ ;;
+ *mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
+ os=mint
+ ;;
+ dicos*)
+ os=dicos
+ ;;
+ pikeos*)
+ # Until real need of OS specific support for
+ # particular features comes up, bare metal
+ # configurations are quite functional.
+ case $cpu in
+ arm*)
+ os=eabi
+ ;;
+ *)
+ os=elf
+ ;;
+ esac
+ ;;
+ *)
+ # No normalization, but not necessarily accepted, that comes below.
+ ;;
+esac
+
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+kernel=
+case $cpu-$vendor in
+ score-*)
+ os=elf
+ ;;
+ spu-*)
+ os=elf
+ ;;
+ *-acorn)
+ os=riscix1.2
+ ;;
+ arm*-rebel)
+ kernel=linux
+ os=gnu
+ ;;
+ arm*-semi)
+ os=aout
+ ;;
+ c4x-* | tic4x-*)
+ os=coff
+ ;;
+ c8051-*)
+ os=elf
+ ;;
+ clipper-intergraph)
+ os=clix
+ ;;
+ hexagon-*)
+ os=elf
+ ;;
+ tic54x-*)
+ os=coff
+ ;;
+ tic55x-*)
+ os=coff
+ ;;
+ tic6x-*)
+ os=coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=tops20
+ ;;
+ pdp11-*)
+ os=none
+ ;;
+ *-dec | vax-*)
+ os=ultrix4.2
+ ;;
+ m68*-apollo)
+ os=domain
+ ;;
+ i386-sun)
+ os=sunos4.0.2
+ ;;
+ m68000-sun)
+ os=sunos3
+ ;;
+ m68*-cisco)
+ os=aout
+ ;;
+ mep-*)
+ os=elf
+ ;;
+ mips*-cisco)
+ os=elf
+ ;;
+ mips*-*)
+ os=elf
+ ;;
+ or32-*)
+ os=coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=sysv3
+ ;;
+ sparc-* | *-sun)
+ os=sunos4.1.1
+ ;;
+ pru-*)
+ os=elf
+ ;;
+ *-be)
+ os=beos
+ ;;
+ *-ibm)
+ os=aix
+ ;;
+ *-knuth)
+ os=mmixware
+ ;;
+ *-wec)
+ os=proelf
+ ;;
+ *-winbond)
+ os=proelf
+ ;;
+ *-oki)
+ os=proelf
+ ;;
+ *-hp)
+ os=hpux
+ ;;
+ *-hitachi)
+ os=hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=sysv
+ ;;
+ *-cbm)
+ os=amigaos
+ ;;
+ *-dg)
+ os=dgux
+ ;;
+ *-dolphin)
+ os=sysv3
+ ;;
+ m68k-ccur)
+ os=rtu
+ ;;
+ m88k-omron*)
+ os=luna
+ ;;
+ *-next)
+ os=nextstep
+ ;;
+ *-sequent)
+ os=ptx
+ ;;
+ *-crds)
+ os=unos
+ ;;
+ *-ns)
+ os=genix
+ ;;
+ i370-*)
+ os=mvs
+ ;;
+ *-gould)
+ os=sysv
+ ;;
+ *-highlevel)
+ os=bsd
+ ;;
+ *-encore)
+ os=bsd
+ ;;
+ *-sgi)
+ os=irix
+ ;;
+ *-siemens)
+ os=sysv4
+ ;;
+ *-masscomp)
+ os=rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=uxpv
+ ;;
+ *-rom68k)
+ os=coff
+ ;;
+ *-*bug)
+ os=coff
+ ;;
+ *-apple)
+ os=macos
+ ;;
+ *-atari*)
+ os=mint
+ ;;
+ *-wrs)
+ os=vxworks
+ ;;
+ *)
+ os=none
+ ;;
+esac
+
+fi
+
+# Now, validate our (potentially fixed-up) OS.
+case $os in
+ # Sometimes we do "kernel-libc", so those need to count as OSes.
+ musl* | newlib* | relibc* | uclibc*)
+ ;;
+ # Likewise for "kernel-abi"
+ eabi* | gnueabi*)
+ ;;
+ # VxWorks passes extra cpu info in the 4th filed.
+ simlinux | simwindows | spe)
+ ;;
+ # Now accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST end in a * to match a version number.
+ gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
+ | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \
+ | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
+ | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \
+ | hiux* | abug | nacl* | netware* | windows* \
+ | os9* | macos* | osx* | ios* \
+ | mpw* | magic* | mmixware* | mon960* | lnews* \
+ | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
+ | aos* | aros* | cloudabi* | sortix* | twizzler* \
+ | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
+ | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
+ | mirbsd* | netbsd* | dicos* | openedition* | ose* \
+ | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \
+ | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
+ | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
+ | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
+ | udi* | lites* | ieee* | go32* | aux* | hcos* \
+ | chorusrdb* | cegcc* | glidix* | serenity* \
+ | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
+ | midipix* | mingw32* | mingw64* | mint* \
+ | uxpv* | beos* | mpeix* | udk* | moxiebox* \
+ | interix* | uwin* | mks* | rhapsody* | darwin* \
+ | openstep* | oskit* | conix* | pw32* | nonstopux* \
+ | storm-chaos* | tops10* | tenex* | tops20* | its* \
+ | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \
+ | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \
+ | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
+ | skyos* | haiku* | rdos* | toppers* | drops* | es* \
+ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
+ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
+ | fiwix* | mlibc* )
+ ;;
+ # This one is extra strict with allowed versions
+ sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ ;;
+ none)
+ ;;
+ kernel* )
+ # Restricted further below
+ ;;
+ *)
+ echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# As a final step for OS-related things, validate the OS-kernel combination
+# (given a valid OS), if there is a kernel.
+case $kernel-$os in
+ linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
+ | linux-musl* | linux-relibc* | linux-uclibc* | linux-mlibc* )
+ ;;
+ uclinux-uclibc* )
+ ;;
+ managarm-mlibc* | managarm-kernel* )
+ ;;
+ -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* | -mlibc* )
+ # These are just libc implementations, not actual OSes, and thus
+ # require a kernel.
+ echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
+ exit 1
+ ;;
+ -kernel* )
+ echo "Invalid configuration \`$1': \`$os' needs explicit kernel." 1>&2
+ exit 1
+ ;;
+ *-kernel* )
+ echo "Invalid configuration \`$1': \`$kernel' does not support \`$os'." 1>&2
+ exit 1
+ ;;
+ kfreebsd*-gnu* | kopensolaris*-gnu*)
+ ;;
+ vxworks-simlinux | vxworks-simwindows | vxworks-spe)
+ ;;
+ nto-qnx*)
+ ;;
+ os2-emx)
+ ;;
+ *-eabi* | *-gnueabi*)
+ ;;
+ -*)
+ # Blank kernel with real OS is always fine.
+ ;;
+ *-*)
+ echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+case $vendor in
+ unknown)
+ case $cpu-$os in
+ *-riscix*)
+ vendor=acorn
+ ;;
+ *-sunos*)
+ vendor=sun
+ ;;
+ *-cnk* | *-aix*)
+ vendor=ibm
+ ;;
+ *-beos*)
+ vendor=be
+ ;;
+ *-hpux*)
+ vendor=hp
+ ;;
+ *-mpeix*)
+ vendor=hp
+ ;;
+ *-hiux*)
+ vendor=hitachi
+ ;;
+ *-unos*)
+ vendor=crds
+ ;;
+ *-dgux*)
+ vendor=dg
+ ;;
+ *-luna*)
+ vendor=omron
+ ;;
+ *-genix*)
+ vendor=ns
+ ;;
+ *-clix*)
+ vendor=intergraph
+ ;;
+ *-mvs* | *-opened*)
+ vendor=ibm
+ ;;
+ *-os400*)
+ vendor=ibm
+ ;;
+ s390-* | s390x-*)
+ vendor=ibm
+ ;;
+ *-ptx*)
+ vendor=sequent
+ ;;
+ *-tpf*)
+ vendor=ibm
+ ;;
+ *-vxsim* | *-vxworks* | *-windiss*)
+ vendor=wrs
+ ;;
+ *-aux*)
+ vendor=apple
+ ;;
+ *-hms*)
+ vendor=hitachi
+ ;;
+ *-mpw* | *-macos*)
+ vendor=apple
+ ;;
+ *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)
+ vendor=atari
+ ;;
+ *-vos*)
+ vendor=stratus
+ ;;
+ esac
+ ;;
+esac
+
+echo "$cpu-$vendor-${kernel:+$kernel-}$os"
+exit
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/scripts/generate_test_coverage.sh b/scripts/generate_test_coverage.sh
new file mode 100755
index 0000000..a27cdba
--- /dev/null
+++ b/scripts/generate_test_coverage.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# This script is meant as an example on how to generate test coverage
+# information. It is meant to be executed from an empty build directory.
+#
+# Usage: <path to the script>/generate_test_coverage.sh [configure options]
+#
+# Example:
+# mkdir -p build
+# cd build
+# ../scripts/generate_test_coverage.sh --enable-python
+
+srcdir=$(dirname "$0")
+srcdir=${srcdir%%"/scripts"}
+CONFIGURE=${CONFIGURE:-${srcdir}/configure}
+LCOV=${LCOV:-lcov}
+GENHTML=${GENHTML:-genhtml}
+
+echo "Using configure: $CONFIGURE (Override with CONFIGURE environment variable)"
+echo "Extra configure options: $@ (Override with script arguments)"
+echo "Using lcov: $LCOV (Override with LCOV environment variable)"
+echo "Using genhtml: $GENHTML (Override with GENHTML environment variable)"
+echo
+
+"$CONFIGURE" "$@" CFLAGS="--coverage -fprofile-arcs -ftest-coverage -O0" LDFLAGS="-lgcov"
+make || exit 1
+make check
+"${LCOV}" -c --directory . --output-file coverage.info --rc "geninfo_adjust_src_path = $PWD => $srcdir"
+"${GENHTML}" coverage.info --output-directory test_coverage
+echo "Test coverage can be found at: test_coverage/index.html"
diff --git a/scripts/install-sh b/scripts/install-sh
new file mode 100755
index 0000000..228a0b1
--- /dev/null
+++ b/scripts/install-sh
@@ -0,0 +1,239 @@
+#! /bin/sh
+
+## (From INN-1.4, written by Rich Salz)
+## $Revision$
+## A script to install files and directories.
+
+PROGNAME=`basename $0`
+
+## Paths to programs. CHOWN, STRIP and WHOAMI are checked below.
+CHOWN=chown
+CHGRP=chgrp
+CHMOD=chmod
+CP=cp
+LN=ln
+MKDIR=mkdir
+MV=mv
+RM=rm
+STRIP=strip
+WHOAMI="echo root"
+
+## Some systems don't support -x, so we have to use -f.
+for d in /sbin /etc /usr/sbin /usr/etc; do
+ if [ -f $d/chown ]; then
+ CHOWN=${d}/chown
+ break
+ fi
+done
+
+for d in /usr/bin /bin /usr/ucb /usr/bsd; do
+ if [ -f $d/whoami ]; then
+ WHOAMI=${d}/whoami
+ break
+ elif [ -f $d/id ]; then
+ WHOAMI=${d}/id | sed -n 's/^[^(]*(\([^)]*\)).*/\1/p'
+ fi
+done
+
+for d in /usr/ccs/bin /usr/bin /bin; do
+ if [ -f $d/strip ]; then
+ STRIP=${d}/strip
+ break
+ fi
+done
+
+## Defaults.
+CHOWNIT=false
+CHGROUPIT=false
+CHMODIT=false
+STRIPIT=false
+BACKIT=false
+TOUCHIT=true
+DIRMODE=false
+
+# INSTALL_BACKUP is like -b but for use with libtool
+if test X"${INSTALL_BACKUP}" != X""; then
+ BACKIT=true
+ BACKUP="${INSTALL_BACKUP}"
+fi
+
+case `${WHOAMI}` in
+root)
+ ROOT=true
+ ;;
+*)
+ ROOT=false
+ ;;
+esac
+
+## Process JCL.
+MORETODO=true
+while ${MORETODO} ; do
+ case X"$1" in
+ X-b)
+ BACKIT=true
+ BACKUP="$2"
+ shift
+ ;;
+ X-b*)
+ BACKIT=true
+ BACKUP="`echo \"$1\" | sed 's/^..//'`"
+ ;;
+ X-c)
+ # backward compatibility
+ ;;
+ X-d)
+ DIRMODE=true
+ ;;
+ X-g)
+ GROUP="$2"
+ CHGROUPIT=true
+ shift
+ ;;
+ X-g*)
+ GROUP="`echo \"$1\" | sed 's/^..//'`"
+ CHGROUPIT=true
+ ;;
+ X-G)
+ GROUP="$2"
+ shift
+ ${ROOT} && CHGROUPIT=true
+ ;;
+ X-G*)
+ if ${ROOT} ; then
+ GROUP="`echo \"$1\" | sed 's/^..//'`"
+ CHGROUPIT=true
+ fi
+ ;;
+ X-m)
+ MODE="$2"
+ CHMODIT=true
+ shift
+ ;;
+ X-m*)
+ MODE="`echo \"$1\" | sed 's/^..//'`"
+ CHMODIT=true
+ ;;
+ X-M)
+ MODE="$2"
+ ${ROOT} && CHMODIT=true
+ shift
+ ;;
+ X-M*)
+ MODE="`echo \"$1\" | sed 's/^..//'`"
+ ${ROOT} && CHMODIT=true
+ ;;
+ X-n)
+ TOUCHIT=false
+ ;;
+ X-o)
+ OWNER="$2"
+ CHOWNIT=true
+ shift
+ ;;
+ X-o*)
+ OWNER="`echo \"$1\" | sed 's/^..//'`"
+ CHOWNIT=true
+ ;;
+ X-O)
+ OWNER="$2"
+ shift
+ ${ROOT} && CHOWNIT=true
+ ;;
+ X-O*)
+ if ${ROOT} ; then
+ OWNER="`echo \"$1\" | sed 's/^..//'`"
+ CHOWNIT=true
+ fi
+ ;;
+ X-s)
+ STRIPIT=true
+ ;;
+ X--)
+ shift
+ MORETODO=false
+ ;;
+ X-*)
+ echo "${PROGNAME}: Unknown flag $1" 1>&2
+ exit 1
+ ;;
+ *)
+ MORETODO=false
+ ;;
+ esac
+ ${MORETODO} && shift
+done
+
+## Making a directory?
+if ${DIRMODE} ; then
+ while test $# != 0; do
+ DEST="$1"
+ if [ ! -d "${DEST}" ] ; then
+ ${MKDIR} "${DEST}" || exit 1
+ fi
+ if ${CHOWNIT} ; then
+ ${CHOWN} "${OWNER}" "${DEST}" || exit 1
+ fi
+ if ${CHGROUPIT} ; then
+ ${CHGRP} "${GROUP}" "${DEST}" || exit 1
+ fi
+ if ${CHMODIT} ; then
+ ${CHMOD} "${MODE}" "${DEST}" || exit 1
+ fi
+ shift;
+ done
+ exit 0
+fi
+
+## Process arguments.
+if [ $# -ne 2 ] ; then
+ echo "Usage: ${PROGNAME} [flags] source destination"
+ exit 1
+fi
+
+## Get the destination and a temp file in the destination directory.
+if [ -d "$2" ] ; then
+ DEST="$2/`basename $1`"
+ TEMP="$2/$$.tmp"
+else
+ DEST="$2"
+ TEMP="`expr "$2" : '\(.*\)/.*'`/$$.tmp"
+fi
+
+## If not given the same name, we must try to copy.
+if [ X"$1" != X"$2" ] ; then
+ if cmp -s "$1" "${DEST}" ; then
+ ## Files are same; touch or not.
+ ${TOUCHIT} && touch "${DEST}"
+ else
+ ## If destination exists and we wish to backup, link to backup.
+ if [ -f "${DEST}" ] ; then
+ if ${BACKIT} ; then
+ ${RM} -f "${DEST}${BACKUP}"
+ ${LN} "${DEST}" "${DEST}${BACKUP}"
+ fi
+ fi
+ ## Copy source to the right dir, then move to right spot.
+ ## Done in two parts so we can hope for atomicity.
+ ## We need to rm DEST due to bugs in "mv -f" on some systems.
+ ${RM} -f "${TEMP}" || exit 1
+ ${CP} "$1" "${TEMP}" || exit 1
+ ${RM} -f "${DEST}" || exit 1
+ ${MV} -f "${TEMP}" "${DEST}" || exit 1
+ fi
+fi
+
+## Strip and set the owner/mode.
+if ${STRIPIT} ; then
+ ${STRIP} "${DEST}" || exit 1
+fi
+if ${CHOWNIT} ; then
+ ${CHOWN} "${OWNER}" "${DEST}" || exit 1
+fi
+if ${CHGROUPIT} ; then
+ ${CHGRP} "${GROUP}" "${DEST}" || exit 1
+fi
+if ${CHMODIT} ; then
+ ${CHMOD} "${MODE}" "${DEST}" || exit 1
+fi
+exit 0
diff --git a/scripts/log2cl.pl b/scripts/log2cl.pl
new file mode 100755
index 0000000..a20cd22
--- /dev/null
+++ b/scripts/log2cl.pl
@@ -0,0 +1,115 @@
+#!/usr/bin/env perl
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2017, 2020 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# Simple script to massage "git log" output into a GNU style ChangeLog.
+# The goal is to emulate "hg log --template=changelog" via perl format.
+
+use Getopt::Std;
+use Text::Wrap;
+use strict;
+use warnings;
+
+# Git log format: author date, author name, author email
+# abbreviated commit hash
+# raw commit body
+my $format="%ad %aN <%aE>%n%h%n%B%n";
+
+# Parse options and build up "git log" command
+my @cmd = ( "git" );
+my %opts;
+getopts('b:R:', \%opts);
+push(@cmd, "-b", $opts{"b"}) if exists $opts{"b"};
+push(@cmd, "--git-dir", $opts{"R"}) if exists $opts{"R"};
+push(@cmd, "log", "--log-size", "--name-only", "--date=short", "--format=$format", @ARGV);
+
+open(LOG, '-|', @cmd) || die "$0: unable to run git log: $!";
+
+my $hash;
+my $body;
+my @files;
+my $key_date = "";
+my $log_size = 0;
+my @lines;
+
+# Wrap like "hg log --template=changelog"
+$Text::Wrap::columns = 77;
+
+while (<LOG>) {
+ chomp;
+ if (/^log size (\d+)$/) {
+ $log_size = $1;
+
+ # Print previous entry if there is one
+ print_entry($hash, $body, @files) if defined($hash);
+
+ # Init new entry
+ undef $hash;
+ undef $body;
+ undef @files;
+ undef @lines;
+
+ # Read entry and split on newlines
+ read(LOG, my $buf, $log_size) ||
+ die "$0: unable to read $log_size bytes: $!\n";
+ @lines = split(/\r?\n/, $buf);
+
+ # Check for continued entry (duplicate Date + Author)
+ $_ = shift(@lines);
+ if ($_ ne $key_date) {
+ # New entry
+ print "$_\n\n";
+ $key_date = $_;
+ }
+
+ # Hash comes first
+ $hash = shift(@lines);
+
+ # Commit message body (multi-line)
+ my $sep = "";
+ foreach (@lines) {
+ last if $_ eq "--HG--";
+ if ($_ eq "") {
+ $sep = "\n\n";
+ next;
+ }
+ s/^\s+//;
+ s/\s+$//;
+ $body .= ${sep} . $_;
+ $sep = " ";
+ }
+ } else {
+ # Not a log entry, must be the file list
+ push(@files, $_) unless $_ eq "";
+ }
+}
+
+# Print the last entry
+print_entry($hash, $body, @files) if defined($hash);
+
+exit(0);
+
+sub print_entry
+{
+ my $hash = shift;
+ my $body = shift;
+ my $files = "* " . join(", ", @_) . ":";
+
+ print wrap("\t", "\t", $files) . "\n";
+ print wrap("\t", "\t", $body) . "\n";
+ print "\t[$hash]\n\n";
+}
diff --git a/scripts/ltmain.sh b/scripts/ltmain.sh
new file mode 100644
index 0000000..a7e63a5
--- /dev/null
+++ b/scripts/ltmain.sh
@@ -0,0 +1,11453 @@
+#! /usr/bin/env sh
+## DO NOT EDIT - This file generated from ./build-aux/ltmain.in
+## by inline-source v2019-02-19.15
+
+# libtool (GNU libtool) 2.4.7
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+
+# Copyright (C) 1996-2019, 2021-2022 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions. There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+PROGRAM=libtool
+PACKAGE=libtool
+VERSION=2.4.7
+package_revision=2.4.7
+
+
+## ------ ##
+## Usage. ##
+## ------ ##
+
+# Run './libtool --help' for help with using this script from the
+# command line.
+
+
+## ------------------------------- ##
+## User overridable command paths. ##
+## ------------------------------- ##
+
+# After configure completes, it has a better idea of some of the
+# shell tools we need than the defaults used by the functions shared
+# with bootstrap, so set those here where they can still be over-
+# ridden by the user, but otherwise take precedence.
+
+: ${AUTOCONF="autoconf"}
+: ${AUTOMAKE="automake"}
+
+
+## -------------------------- ##
+## Source external libraries. ##
+## -------------------------- ##
+
+# Much of our low-level functionality needs to be sourced from external
+# libraries, which are installed to $pkgauxdir.
+
+# Set a version string for this script.
+scriptversion=2019-02-19.15; # UTC
+
+# General shell script boiler plate, and helper functions.
+# Written by Gary V. Vaughan, 2004
+
+# This is free software. There is NO warranty; not even for
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Copyright (C) 2004-2019, 2021 Bootstrap Authors
+#
+# This file is dual licensed under the terms of the MIT license
+# <https://opensource.org/license/MIT>, and GPL version 2 or later
+# <http://www.gnu.org/licenses/gpl-2.0.html>. You must apply one of
+# these licenses when using or redistributing this software or any of
+# the files within it. See the URLs above, or the file `LICENSE`
+# included in the Bootstrap distribution for the full license texts.
+
+# Please report bugs or propose patches to:
+# <https://github.com/gnulib-modules/bootstrap/issues>
+
+
+## ------ ##
+## Usage. ##
+## ------ ##
+
+# Evaluate this file near the top of your script to gain access to
+# the functions and variables defined here:
+#
+# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh
+#
+# If you need to override any of the default environment variable
+# settings, do that before evaluating this file.
+
+
+## -------------------- ##
+## Shell normalisation. ##
+## -------------------- ##
+
+# Some shells need a little help to be as Bourne compatible as possible.
+# Before doing anything else, make sure all that help has been provided!
+
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac
+fi
+
+# NLS nuisances: We save the old values in case they are required later.
+_G_user_locale=
+_G_safe_locale=
+for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+ eval "if test set = \"\${$_G_var+set}\"; then
+ save_$_G_var=\$$_G_var
+ $_G_var=C
+ export $_G_var
+ _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\"
+ _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\"
+ fi"
+done
+# These NLS vars are set unconditionally (bootstrap issue #24). Unset those
+# in case the environment reset is needed later and the $save_* variant is not
+# defined (see the code above).
+LC_ALL=C
+LANGUAGE=C
+export LANGUAGE LC_ALL
+
+# Make sure IFS has a sensible default
+sp=' '
+nl='
+'
+IFS="$sp $nl"
+
+# There are apparently some retarded systems that use ';' as a PATH separator!
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# func_unset VAR
+# --------------
+# Portably unset VAR.
+# In some shells, an 'unset VAR' statement leaves a non-zero return
+# status if VAR is already unset, which might be problematic if the
+# statement is used at the end of a function (thus poisoning its return
+# value) or when 'set -e' is active (causing even a spurious abort of
+# the script in this case).
+func_unset ()
+{
+ { eval $1=; (eval unset $1) >/dev/null 2>&1 && eval unset $1 || : ; }
+}
+
+
+# Make sure CDPATH doesn't cause `cd` commands to output the target dir.
+func_unset CDPATH
+
+# Make sure ${,E,F}GREP behave sanely.
+func_unset GREP_OPTIONS
+
+
+## ------------------------- ##
+## Locate command utilities. ##
+## ------------------------- ##
+
+
+# func_executable_p FILE
+# ----------------------
+# Check that FILE is an executable regular file.
+func_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+}
+
+
+# func_path_progs PROGS_LIST CHECK_FUNC [PATH]
+# --------------------------------------------
+# Search for either a program that responds to --version with output
+# containing "GNU", or else returned by CHECK_FUNC otherwise, by
+# trying all the directories in PATH with each of the elements of
+# PROGS_LIST.
+#
+# CHECK_FUNC should accept the path to a candidate program, and
+# set $func_check_prog_result if it truncates its output less than
+# $_G_path_prog_max characters.
+func_path_progs ()
+{
+ _G_progs_list=$1
+ _G_check_func=$2
+ _G_PATH=${3-"$PATH"}
+
+ _G_path_prog_max=0
+ _G_path_prog_found=false
+ _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:}
+ for _G_dir in $_G_PATH; do
+ IFS=$_G_save_IFS
+ test -z "$_G_dir" && _G_dir=.
+ for _G_prog_name in $_G_progs_list; do
+ for _exeext in '' .EXE; do
+ _G_path_prog=$_G_dir/$_G_prog_name$_exeext
+ func_executable_p "$_G_path_prog" || continue
+ case `"$_G_path_prog" --version 2>&1` in
+ *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;;
+ *) $_G_check_func $_G_path_prog
+ func_path_progs_result=$func_check_prog_result
+ ;;
+ esac
+ $_G_path_prog_found && break 3
+ done
+ done
+ done
+ IFS=$_G_save_IFS
+ test -z "$func_path_progs_result" && {
+ echo "no acceptable sed could be found in \$PATH" >&2
+ exit 1
+ }
+}
+
+
+# We want to be able to use the functions in this file before configure
+# has figured out where the best binaries are kept, which means we have
+# to search for them ourselves - except when the results are already set
+# where we skip the searches.
+
+# Unless the user overrides by setting SED, search the path for either GNU
+# sed, or the sed that truncates its output the least.
+test -z "$SED" && {
+ _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+ for _G_i in 1 2 3 4 5 6 7; do
+ _G_sed_script=$_G_sed_script$nl$_G_sed_script
+ done
+ echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed
+ _G_sed_script=
+
+ func_check_prog_sed ()
+ {
+ _G_path_prog=$1
+
+ _G_count=0
+ printf 0123456789 >conftest.in
+ while :
+ do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo '' >> conftest.nl
+ "$_G_path_prog" -f conftest.sed <conftest.nl >conftest.out 2>/dev/null || break
+ diff conftest.out conftest.nl >/dev/null 2>&1 || break
+ _G_count=`expr $_G_count + 1`
+ if test "$_G_count" -gt "$_G_path_prog_max"; then
+ # Best one so far, save it but keep looking for a better one
+ func_check_prog_result=$_G_path_prog
+ _G_path_prog_max=$_G_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test 10 -lt "$_G_count" && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out
+ }
+
+ func_path_progs "sed gsed" func_check_prog_sed "$PATH:/usr/xpg4/bin"
+ rm -f conftest.sed
+ SED=$func_path_progs_result
+}
+
+
+# Unless the user overrides by setting GREP, search the path for either GNU
+# grep, or the grep that truncates its output the least.
+test -z "$GREP" && {
+ func_check_prog_grep ()
+ {
+ _G_path_prog=$1
+
+ _G_count=0
+ _G_path_prog_max=0
+ printf 0123456789 >conftest.in
+ while :
+ do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo 'GREP' >> conftest.nl
+ "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' <conftest.nl >conftest.out 2>/dev/null || break
+ diff conftest.out conftest.nl >/dev/null 2>&1 || break
+ _G_count=`expr $_G_count + 1`
+ if test "$_G_count" -gt "$_G_path_prog_max"; then
+ # Best one so far, save it but keep looking for a better one
+ func_check_prog_result=$_G_path_prog
+ _G_path_prog_max=$_G_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test 10 -lt "$_G_count" && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out
+ }
+
+ func_path_progs "grep ggrep" func_check_prog_grep "$PATH:/usr/xpg4/bin"
+ GREP=$func_path_progs_result
+}
+
+
+## ------------------------------- ##
+## User overridable command paths. ##
+## ------------------------------- ##
+
+# All uppercase variable names are used for environment variables. These
+# variables can be overridden by the user before calling a script that
+# uses them if a suitable command of that name is not already available
+# in the command search PATH.
+
+: ${CP="cp -f"}
+: ${ECHO="printf %s\n"}
+: ${EGREP="$GREP -E"}
+: ${FGREP="$GREP -F"}
+: ${LN_S="ln -s"}
+: ${MAKE="make"}
+: ${MKDIR="mkdir"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
+
+
+## -------------------- ##
+## Useful sed snippets. ##
+## -------------------- ##
+
+sed_dirname='s|/[^/]*$||'
+sed_basename='s|^.*/||'
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s|\([`"$\\]\)|\\\1|g'
+
+# Same as above, but do not quote variable references.
+sed_double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution that turns a string into a regex matching for the
+# string literally.
+sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g'
+
+# Sed substitution that converts a w32 file name or path
+# that contains forward slashes, into one that contains
+# (escaped) backslashes. A very naive implementation.
+sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+
+# Re-'\' parameter expansions in output of sed_double_quote_subst that
+# were '\'-ed in input to the same. If an odd number of '\' preceded a
+# '$' in input to sed_double_quote_subst, that '$' was protected from
+# expansion. Since each input '\' is now two '\'s, look for any number
+# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'.
+_G_bs='\\'
+_G_bs2='\\\\'
+_G_bs4='\\\\\\\\'
+_G_dollar='\$'
+sed_double_backslash="\
+ s/$_G_bs4/&\\
+/g
+ s/^$_G_bs2$_G_dollar/$_G_bs&/
+ s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g
+ s/\n//g"
+
+# require_check_ifs_backslash
+# ---------------------------
+# Check if we can use backslash as IFS='\' separator, and set
+# $check_ifs_backshlash_broken to ':' or 'false'.
+require_check_ifs_backslash=func_require_check_ifs_backslash
+func_require_check_ifs_backslash ()
+{
+ _G_save_IFS=$IFS
+ IFS='\'
+ _G_check_ifs_backshlash='a\\b'
+ for _G_i in $_G_check_ifs_backshlash
+ do
+ case $_G_i in
+ a)
+ check_ifs_backshlash_broken=false
+ ;;
+ '')
+ break
+ ;;
+ *)
+ check_ifs_backshlash_broken=:
+ break
+ ;;
+ esac
+ done
+ IFS=$_G_save_IFS
+ require_check_ifs_backslash=:
+}
+
+
+## ----------------- ##
+## Global variables. ##
+## ----------------- ##
+
+# Except for the global variables explicitly listed below, the following
+# functions in the '^func_' namespace, and the '^require_' namespace
+# variables initialised in the 'Resource management' section, sourcing
+# this file will not pollute your global namespace with anything
+# else. There's no portable way to scope variables in Bourne shell
+# though, so actually running these functions will sometimes place
+# results into a variable named after the function, and often use
+# temporary variables in the '^_G_' namespace. If you are careful to
+# avoid using those namespaces casually in your sourcing script, things
+# should continue to work as you expect. And, of course, you can freely
+# overwrite any of the functions or variables defined here before
+# calling anything to customize them.
+
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing.
+EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake.
+
+# Allow overriding, eg assuming that you follow the convention of
+# putting '$debug_cmd' at the start of all your functions, you can get
+# bash to show function call trace with:
+#
+# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name
+debug_cmd=${debug_cmd-":"}
+exit_cmd=:
+
+# By convention, finish your script with:
+#
+# exit $exit_status
+#
+# so that you can set exit_status to non-zero if you want to indicate
+# something went wrong during execution without actually bailing out at
+# the point of failure.
+exit_status=$EXIT_SUCCESS
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath=$0
+
+# The name of this program.
+progname=`$ECHO "$progpath" |$SED "$sed_basename"`
+
+# Make sure we have an absolute progpath for reexecution:
+case $progpath in
+ [\\/]*|[A-Za-z]:\\*) ;;
+ *[\\/]*)
+ progdir=`$ECHO "$progpath" |$SED "$sed_dirname"`
+ progdir=`cd "$progdir" && pwd`
+ progpath=$progdir/$progname
+ ;;
+ *)
+ _G_IFS=$IFS
+ IFS=${PATH_SEPARATOR-:}
+ for progdir in $PATH; do
+ IFS=$_G_IFS
+ test -x "$progdir/$progname" && break
+ done
+ IFS=$_G_IFS
+ test -n "$progdir" || progdir=`pwd`
+ progpath=$progdir/$progname
+ ;;
+esac
+
+
+## ----------------- ##
+## Standard options. ##
+## ----------------- ##
+
+# The following options affect the operation of the functions defined
+# below, and should be set appropriately depending on run-time para-
+# meters passed on the command line.
+
+opt_dry_run=false
+opt_quiet=false
+opt_verbose=false
+
+# Categories 'all' and 'none' are always available. Append any others
+# you will pass as the first argument to func_warning from your own
+# code.
+warning_categories=
+
+# By default, display warnings according to 'opt_warning_types'. Set
+# 'warning_func' to ':' to elide all warnings, or func_fatal_error to
+# treat the next displayed warning as a fatal error.
+warning_func=func_warn_and_continue
+
+# Set to 'all' to display all warnings, 'none' to suppress all
+# warnings, or a space delimited list of some subset of
+# 'warning_categories' to display only the listed warnings.
+opt_warning_types=all
+
+
+## -------------------- ##
+## Resource management. ##
+## -------------------- ##
+
+# This section contains definitions for functions that each ensure a
+# particular resource (a file, or a non-empty configuration variable for
+# example) is available, and if appropriate to extract default values
+# from pertinent package files. Call them using their associated
+# 'require_*' variable to ensure that they are executed, at most, once.
+#
+# It's entirely deliberate that calling these functions can set
+# variables that don't obey the namespace limitations obeyed by the rest
+# of this file, in order that that they be as useful as possible to
+# callers.
+
+
+# require_term_colors
+# -------------------
+# Allow display of bold text on terminals that support it.
+require_term_colors=func_require_term_colors
+func_require_term_colors ()
+{
+ $debug_cmd
+
+ test -t 1 && {
+ # COLORTERM and USE_ANSI_COLORS environment variables take
+ # precedence, because most terminfo databases neglect to describe
+ # whether color sequences are supported.
+ test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"}
+
+ if test 1 = "$USE_ANSI_COLORS"; then
+ # Standard ANSI escape sequences
+ tc_reset=''
+ tc_bold=''; tc_standout=''
+ tc_red=''; tc_green=''
+ tc_blue=''; tc_cyan=''
+ else
+ # Otherwise trust the terminfo database after all.
+ test -n "`tput sgr0 2>/dev/null`" && {
+ tc_reset=`tput sgr0`
+ test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold`
+ tc_standout=$tc_bold
+ test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso`
+ test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1`
+ test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2`
+ test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4`
+ test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5`
+ }
+ fi
+ }
+
+ require_term_colors=:
+}
+
+
+## ----------------- ##
+## Function library. ##
+## ----------------- ##
+
+# This section contains a variety of useful functions to call in your
+# scripts. Take note of the portable wrappers for features provided by
+# some modern shells, which will fall back to slower equivalents on
+# less featureful shells.
+
+
+# func_append VAR VALUE
+# ---------------------
+# Append VALUE onto the existing contents of VAR.
+
+ # We should try to minimise forks, especially on Windows where they are
+ # unreasonably slow, so skip the feature probes when bash or zsh are
+ # being used:
+ if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then
+ : ${_G_HAVE_ARITH_OP="yes"}
+ : ${_G_HAVE_XSI_OPS="yes"}
+ # The += operator was introduced in bash 3.1
+ case $BASH_VERSION in
+ [12].* | 3.0 | 3.0*) ;;
+ *)
+ : ${_G_HAVE_PLUSEQ_OP="yes"}
+ ;;
+ esac
+ fi
+
+ # _G_HAVE_PLUSEQ_OP
+ # Can be empty, in which case the shell is probed, "yes" if += is
+ # useable or anything else if it does not work.
+ test -z "$_G_HAVE_PLUSEQ_OP" \
+ && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \
+ && _G_HAVE_PLUSEQ_OP=yes
+
+if test yes = "$_G_HAVE_PLUSEQ_OP"
+then
+ # This is an XSI compatible shell, allowing a faster implementation...
+ eval 'func_append ()
+ {
+ $debug_cmd
+
+ eval "$1+=\$2"
+ }'
+else
+ # ...otherwise fall back to using expr, which is often a shell builtin.
+ func_append ()
+ {
+ $debug_cmd
+
+ eval "$1=\$$1\$2"
+ }
+fi
+
+
+# func_append_quoted VAR VALUE
+# ----------------------------
+# Quote VALUE and append to the end of shell variable VAR, separated
+# by a space.
+if test yes = "$_G_HAVE_PLUSEQ_OP"; then
+ eval 'func_append_quoted ()
+ {
+ $debug_cmd
+
+ func_quote_arg pretty "$2"
+ eval "$1+=\\ \$func_quote_arg_result"
+ }'
+else
+ func_append_quoted ()
+ {
+ $debug_cmd
+
+ func_quote_arg pretty "$2"
+ eval "$1=\$$1\\ \$func_quote_arg_result"
+ }
+fi
+
+
+# func_append_uniq VAR VALUE
+# --------------------------
+# Append unique VALUE onto the existing contents of VAR, assuming
+# entries are delimited by the first character of VALUE. For example:
+#
+# func_append_uniq options " --another-option option-argument"
+#
+# will only append to $options if " --another-option option-argument "
+# is not already present somewhere in $options already (note spaces at
+# each end implied by leading space in second argument).
+func_append_uniq ()
+{
+ $debug_cmd
+
+ eval _G_current_value='`$ECHO $'$1'`'
+ _G_delim=`expr "$2" : '\(.\)'`
+
+ case $_G_delim$_G_current_value$_G_delim in
+ *"$2$_G_delim"*) ;;
+ *) func_append "$@" ;;
+ esac
+}
+
+
+# func_arith TERM...
+# ------------------
+# Set func_arith_result to the result of evaluating TERMs.
+ test -z "$_G_HAVE_ARITH_OP" \
+ && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \
+ && _G_HAVE_ARITH_OP=yes
+
+if test yes = "$_G_HAVE_ARITH_OP"; then
+ eval 'func_arith ()
+ {
+ $debug_cmd
+
+ func_arith_result=$(( $* ))
+ }'
+else
+ func_arith ()
+ {
+ $debug_cmd
+
+ func_arith_result=`expr "$@"`
+ }
+fi
+
+
+# func_basename FILE
+# ------------------
+# Set func_basename_result to FILE with everything up to and including
+# the last / stripped.
+if test yes = "$_G_HAVE_XSI_OPS"; then
+ # If this shell supports suffix pattern removal, then use it to avoid
+ # forking. Hide the definitions single quotes in case the shell chokes
+ # on unsupported syntax...
+ _b='func_basename_result=${1##*/}'
+ _d='case $1 in
+ */*) func_dirname_result=${1%/*}$2 ;;
+ * ) func_dirname_result=$3 ;;
+ esac'
+
+else
+ # ...otherwise fall back to using sed.
+ _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`'
+ _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"`
+ if test "X$func_dirname_result" = "X$1"; then
+ func_dirname_result=$3
+ else
+ func_append func_dirname_result "$2"
+ fi'
+fi
+
+eval 'func_basename ()
+{
+ $debug_cmd
+
+ '"$_b"'
+}'
+
+
+# func_dirname FILE APPEND NONDIR_REPLACEMENT
+# -------------------------------------------
+# Compute the dirname of FILE. If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+eval 'func_dirname ()
+{
+ $debug_cmd
+
+ '"$_d"'
+}'
+
+
+# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT
+# --------------------------------------------------------
+# Perform func_basename and func_dirname in a single function
+# call:
+# dirname: Compute the dirname of FILE. If nonempty,
+# add APPEND to the result, otherwise set result
+# to NONDIR_REPLACEMENT.
+# value returned in "$func_dirname_result"
+# basename: Compute filename of FILE.
+# value retuned in "$func_basename_result"
+# For efficiency, we do not delegate to the functions above but instead
+# duplicate the functionality here.
+eval 'func_dirname_and_basename ()
+{
+ $debug_cmd
+
+ '"$_b"'
+ '"$_d"'
+}'
+
+
+# func_echo ARG...
+# ----------------
+# Echo program name prefixed message.
+func_echo ()
+{
+ $debug_cmd
+
+ _G_message=$*
+
+ func_echo_IFS=$IFS
+ IFS=$nl
+ for _G_line in $_G_message; do
+ IFS=$func_echo_IFS
+ $ECHO "$progname: $_G_line"
+ done
+ IFS=$func_echo_IFS
+}
+
+
+# func_echo_all ARG...
+# --------------------
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+ $ECHO "$*"
+}
+
+
+# func_echo_infix_1 INFIX ARG...
+# ------------------------------
+# Echo program name, followed by INFIX on the first line, with any
+# additional lines not showing INFIX.
+func_echo_infix_1 ()
+{
+ $debug_cmd
+
+ $require_term_colors
+
+ _G_infix=$1; shift
+ _G_indent=$_G_infix
+ _G_prefix="$progname: $_G_infix: "
+ _G_message=$*
+
+ # Strip color escape sequences before counting printable length
+ for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan"
+ do
+ test -n "$_G_tc" && {
+ _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"`
+ _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"`
+ }
+ done
+ _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes
+
+ func_echo_infix_1_IFS=$IFS
+ IFS=$nl
+ for _G_line in $_G_message; do
+ IFS=$func_echo_infix_1_IFS
+ $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2
+ _G_prefix=$_G_indent
+ done
+ IFS=$func_echo_infix_1_IFS
+}
+
+
+# func_error ARG...
+# -----------------
+# Echo program name prefixed message to standard error.
+func_error ()
+{
+ $debug_cmd
+
+ $require_term_colors
+
+ func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2
+}
+
+
+# func_fatal_error ARG...
+# -----------------------
+# Echo program name prefixed message to standard error, and exit.
+func_fatal_error ()
+{
+ $debug_cmd
+
+ func_error "$*"
+ exit $EXIT_FAILURE
+}
+
+
+# func_grep EXPRESSION FILENAME
+# -----------------------------
+# Check whether EXPRESSION matches any line of FILENAME, without output.
+func_grep ()
+{
+ $debug_cmd
+
+ $GREP "$1" "$2" >/dev/null 2>&1
+}
+
+
+# func_len STRING
+# ---------------
+# Set func_len_result to the length of STRING. STRING may not
+# start with a hyphen.
+ test -z "$_G_HAVE_XSI_OPS" \
+ && (eval 'x=a/b/c;
+ test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \
+ && _G_HAVE_XSI_OPS=yes
+
+if test yes = "$_G_HAVE_XSI_OPS"; then
+ eval 'func_len ()
+ {
+ $debug_cmd
+
+ func_len_result=${#1}
+ }'
+else
+ func_len ()
+ {
+ $debug_cmd
+
+ func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
+ }
+fi
+
+
+# func_mkdir_p DIRECTORY-PATH
+# ---------------------------
+# Make sure the entire path to DIRECTORY-PATH is available.
+func_mkdir_p ()
+{
+ $debug_cmd
+
+ _G_directory_path=$1
+ _G_dir_list=
+
+ if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then
+
+ # Protect directory names starting with '-'
+ case $_G_directory_path in
+ -*) _G_directory_path=./$_G_directory_path ;;
+ esac
+
+ # While some portion of DIR does not yet exist...
+ while test ! -d "$_G_directory_path"; do
+ # ...make a list in topmost first order. Use a colon delimited
+ # list incase some portion of path contains whitespace.
+ _G_dir_list=$_G_directory_path:$_G_dir_list
+
+ # If the last portion added has no slash in it, the list is done
+ case $_G_directory_path in */*) ;; *) break ;; esac
+
+ # ...otherwise throw away the child directory and loop
+ _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"`
+ done
+ _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'`
+
+ func_mkdir_p_IFS=$IFS; IFS=:
+ for _G_dir in $_G_dir_list; do
+ IFS=$func_mkdir_p_IFS
+ # mkdir can fail with a 'File exist' error if two processes
+ # try to create one of the directories concurrently. Don't
+ # stop in that case!
+ $MKDIR "$_G_dir" 2>/dev/null || :
+ done
+ IFS=$func_mkdir_p_IFS
+
+ # Bail out if we (or some other process) failed to create a directory.
+ test -d "$_G_directory_path" || \
+ func_fatal_error "Failed to create '$1'"
+ fi
+}
+
+
+# func_mktempdir [BASENAME]
+# -------------------------
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible. If
+# given, BASENAME is the basename for that directory.
+func_mktempdir ()
+{
+ $debug_cmd
+
+ _G_template=${TMPDIR-/tmp}/${1-$progname}
+
+ if test : = "$opt_dry_run"; then
+ # Return a directory name, but don't create it in dry-run mode
+ _G_tmpdir=$_G_template-$$
+ else
+
+ # If mktemp works, use that first and foremost
+ _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null`
+
+ if test ! -d "$_G_tmpdir"; then
+ # Failing that, at least try and use $RANDOM to avoid a race
+ _G_tmpdir=$_G_template-${RANDOM-0}$$
+
+ func_mktempdir_umask=`umask`
+ umask 0077
+ $MKDIR "$_G_tmpdir"
+ umask $func_mktempdir_umask
+ fi
+
+ # If we're not in dry-run mode, bomb out on failure
+ test -d "$_G_tmpdir" || \
+ func_fatal_error "cannot create temporary directory '$_G_tmpdir'"
+ fi
+
+ $ECHO "$_G_tmpdir"
+}
+
+
+# func_normal_abspath PATH
+# ------------------------
+# Remove doubled-up and trailing slashes, "." path components,
+# and cancel out any ".." path components in PATH after making
+# it an absolute path.
+func_normal_abspath ()
+{
+ $debug_cmd
+
+ # These SED scripts presuppose an absolute path with a trailing slash.
+ _G_pathcar='s|^/\([^/]*\).*$|\1|'
+ _G_pathcdr='s|^/[^/]*||'
+ _G_removedotparts=':dotsl
+ s|/\./|/|g
+ t dotsl
+ s|/\.$|/|'
+ _G_collapseslashes='s|/\{1,\}|/|g'
+ _G_finalslash='s|/*$|/|'
+
+ # Start from root dir and reassemble the path.
+ func_normal_abspath_result=
+ func_normal_abspath_tpath=$1
+ func_normal_abspath_altnamespace=
+ case $func_normal_abspath_tpath in
+ "")
+ # Empty path, that just means $cwd.
+ func_stripname '' '/' "`pwd`"
+ func_normal_abspath_result=$func_stripname_result
+ return
+ ;;
+ # The next three entries are used to spot a run of precisely
+ # two leading slashes without using negated character classes;
+ # we take advantage of case's first-match behaviour.
+ ///*)
+ # Unusual form of absolute path, do nothing.
+ ;;
+ //*)
+ # Not necessarily an ordinary path; POSIX reserves leading '//'
+ # and for example Cygwin uses it to access remote file shares
+ # over CIFS/SMB, so we conserve a leading double slash if found.
+ func_normal_abspath_altnamespace=/
+ ;;
+ /*)
+ # Absolute path, do nothing.
+ ;;
+ *)
+ # Relative path, prepend $cwd.
+ func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath
+ ;;
+ esac
+
+ # Cancel out all the simple stuff to save iterations. We also want
+ # the path to end with a slash for ease of parsing, so make sure
+ # there is one (and only one) here.
+ func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+ -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"`
+ while :; do
+ # Processed it all yet?
+ if test / = "$func_normal_abspath_tpath"; then
+ # If we ascended to the root using ".." the result may be empty now.
+ if test -z "$func_normal_abspath_result"; then
+ func_normal_abspath_result=/
+ fi
+ break
+ fi
+ func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \
+ -e "$_G_pathcar"`
+ func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+ -e "$_G_pathcdr"`
+ # Figure out what to do with it
+ case $func_normal_abspath_tcomponent in
+ "")
+ # Trailing empty path component, ignore it.
+ ;;
+ ..)
+ # Parent dir; strip last assembled component from result.
+ func_dirname "$func_normal_abspath_result"
+ func_normal_abspath_result=$func_dirname_result
+ ;;
+ *)
+ # Actual path component, append it.
+ func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent"
+ ;;
+ esac
+ done
+ # Restore leading double-slash if one was found on entry.
+ func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result
+}
+
+
+# func_notquiet ARG...
+# --------------------
+# Echo program name prefixed message only when not in quiet mode.
+func_notquiet ()
+{
+ $debug_cmd
+
+ $opt_quiet || func_echo ${1+"$@"}
+
+ # A bug in bash halts the script if the last line of a function
+ # fails when set -e is in force, so we need another command to
+ # work around that:
+ :
+}
+
+
+# func_relative_path SRCDIR DSTDIR
+# --------------------------------
+# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR.
+func_relative_path ()
+{
+ $debug_cmd
+
+ func_relative_path_result=
+ func_normal_abspath "$1"
+ func_relative_path_tlibdir=$func_normal_abspath_result
+ func_normal_abspath "$2"
+ func_relative_path_tbindir=$func_normal_abspath_result
+
+ # Ascend the tree starting from libdir
+ while :; do
+ # check if we have found a prefix of bindir
+ case $func_relative_path_tbindir in
+ $func_relative_path_tlibdir)
+ # found an exact match
+ func_relative_path_tcancelled=
+ break
+ ;;
+ $func_relative_path_tlibdir*)
+ # found a matching prefix
+ func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir"
+ func_relative_path_tcancelled=$func_stripname_result
+ if test -z "$func_relative_path_result"; then
+ func_relative_path_result=.
+ fi
+ break
+ ;;
+ *)
+ func_dirname $func_relative_path_tlibdir
+ func_relative_path_tlibdir=$func_dirname_result
+ if test -z "$func_relative_path_tlibdir"; then
+ # Have to descend all the way to the root!
+ func_relative_path_result=../$func_relative_path_result
+ func_relative_path_tcancelled=$func_relative_path_tbindir
+ break
+ fi
+ func_relative_path_result=../$func_relative_path_result
+ ;;
+ esac
+ done
+
+ # Now calculate path; take care to avoid doubling-up slashes.
+ func_stripname '' '/' "$func_relative_path_result"
+ func_relative_path_result=$func_stripname_result
+ func_stripname '/' '/' "$func_relative_path_tcancelled"
+ if test -n "$func_stripname_result"; then
+ func_append func_relative_path_result "/$func_stripname_result"
+ fi
+
+ # Normalisation. If bindir is libdir, return '.' else relative path.
+ if test -n "$func_relative_path_result"; then
+ func_stripname './' '' "$func_relative_path_result"
+ func_relative_path_result=$func_stripname_result
+ fi
+
+ test -n "$func_relative_path_result" || func_relative_path_result=.
+
+ :
+}
+
+
+# func_quote_portable EVAL ARG
+# ----------------------------
+# Internal function to portably implement func_quote_arg. Note that we still
+# keep attention to performance here so we as much as possible try to avoid
+# calling sed binary (so far O(N) complexity as long as func_append is O(1)).
+func_quote_portable ()
+{
+ $debug_cmd
+
+ $require_check_ifs_backslash
+
+ func_quote_portable_result=$2
+
+ # one-time-loop (easy break)
+ while true
+ do
+ if $1; then
+ func_quote_portable_result=`$ECHO "$2" | $SED \
+ -e "$sed_double_quote_subst" -e "$sed_double_backslash"`
+ break
+ fi
+
+ # Quote for eval.
+ case $func_quote_portable_result in
+ *[\\\`\"\$]*)
+ # Fallback to sed for $func_check_bs_ifs_broken=:, or when the string
+ # contains the shell wildcard characters.
+ case $check_ifs_backshlash_broken$func_quote_portable_result in
+ :*|*[\[\*\?]*)
+ func_quote_portable_result=`$ECHO "$func_quote_portable_result" \
+ | $SED "$sed_quote_subst"`
+ break
+ ;;
+ esac
+
+ func_quote_portable_old_IFS=$IFS
+ for _G_char in '\' '`' '"' '$'
+ do
+ # STATE($1) PREV($2) SEPARATOR($3)
+ set start "" ""
+ func_quote_portable_result=dummy"$_G_char$func_quote_portable_result$_G_char"dummy
+ IFS=$_G_char
+ for _G_part in $func_quote_portable_result
+ do
+ case $1 in
+ quote)
+ func_append func_quote_portable_result "$3$2"
+ set quote "$_G_part" "\\$_G_char"
+ ;;
+ start)
+ set first "" ""
+ func_quote_portable_result=
+ ;;
+ first)
+ set quote "$_G_part" ""
+ ;;
+ esac
+ done
+ done
+ IFS=$func_quote_portable_old_IFS
+ ;;
+ *) ;;
+ esac
+ break
+ done
+
+ func_quote_portable_unquoted_result=$func_quote_portable_result
+ case $func_quote_portable_result in
+ # double-quote args containing shell metacharacters to delay
+ # word splitting, command substitution and variable expansion
+ # for a subsequent eval.
+ # many bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ func_quote_portable_result=\"$func_quote_portable_result\"
+ ;;
+ esac
+}
+
+
+# func_quotefast_eval ARG
+# -----------------------
+# Quote one ARG (internal). This is equivalent to 'func_quote_arg eval ARG',
+# but optimized for speed. Result is stored in $func_quotefast_eval.
+if test xyes = `(x=; printf -v x %q yes; echo x"$x") 2>/dev/null`; then
+ printf -v _GL_test_printf_tilde %q '~'
+ if test '\~' = "$_GL_test_printf_tilde"; then
+ func_quotefast_eval ()
+ {
+ printf -v func_quotefast_eval_result %q "$1"
+ }
+ else
+ # Broken older Bash implementations. Make those faster too if possible.
+ func_quotefast_eval ()
+ {
+ case $1 in
+ '~'*)
+ func_quote_portable false "$1"
+ func_quotefast_eval_result=$func_quote_portable_result
+ ;;
+ *)
+ printf -v func_quotefast_eval_result %q "$1"
+ ;;
+ esac
+ }
+ fi
+else
+ func_quotefast_eval ()
+ {
+ func_quote_portable false "$1"
+ func_quotefast_eval_result=$func_quote_portable_result
+ }
+fi
+
+
+# func_quote_arg MODEs ARG
+# ------------------------
+# Quote one ARG to be evaled later. MODEs argument may contain zero or more
+# specifiers listed below separated by ',' character. This function returns two
+# values:
+# i) func_quote_arg_result
+# double-quoted (when needed), suitable for a subsequent eval
+# ii) func_quote_arg_unquoted_result
+# has all characters that are still active within double
+# quotes backslashified. Available only if 'unquoted' is specified.
+#
+# Available modes:
+# ----------------
+# 'eval' (default)
+# - escape shell special characters
+# 'expand'
+# - the same as 'eval'; but do not quote variable references
+# 'pretty'
+# - request aesthetic output, i.e. '"a b"' instead of 'a\ b'. This might
+# be used later in func_quote to get output like: 'echo "a b"' instead
+# of 'echo a\ b'. This is slower than default on some shells.
+# 'unquoted'
+# - produce also $func_quote_arg_unquoted_result which does not contain
+# wrapping double-quotes.
+#
+# Examples for 'func_quote_arg pretty,unquoted string':
+#
+# string | *_result | *_unquoted_result
+# ------------+-----------------------+-------------------
+# " | \" | \"
+# a b | "a b" | a b
+# "a b" | "\"a b\"" | \"a b\"
+# * | "*" | *
+# z="${x-$y}" | "z=\"\${x-\$y}\"" | z=\"\${x-\$y}\"
+#
+# Examples for 'func_quote_arg pretty,unquoted,expand string':
+#
+# string | *_result | *_unquoted_result
+# --------------+---------------------+--------------------
+# z="${x-$y}" | "z=\"${x-$y}\"" | z=\"${x-$y}\"
+func_quote_arg ()
+{
+ _G_quote_expand=false
+ case ,$1, in
+ *,expand,*)
+ _G_quote_expand=:
+ ;;
+ esac
+
+ case ,$1, in
+ *,pretty,*|*,expand,*|*,unquoted,*)
+ func_quote_portable $_G_quote_expand "$2"
+ func_quote_arg_result=$func_quote_portable_result
+ func_quote_arg_unquoted_result=$func_quote_portable_unquoted_result
+ ;;
+ *)
+ # Faster quote-for-eval for some shells.
+ func_quotefast_eval "$2"
+ func_quote_arg_result=$func_quotefast_eval_result
+ ;;
+ esac
+}
+
+
+# func_quote MODEs ARGs...
+# ------------------------
+# Quote all ARGs to be evaled later and join them into single command. See
+# func_quote_arg's description for more info.
+func_quote ()
+{
+ $debug_cmd
+ _G_func_quote_mode=$1 ; shift
+ func_quote_result=
+ while test 0 -lt $#; do
+ func_quote_arg "$_G_func_quote_mode" "$1"
+ if test -n "$func_quote_result"; then
+ func_append func_quote_result " $func_quote_arg_result"
+ else
+ func_append func_quote_result "$func_quote_arg_result"
+ fi
+ shift
+ done
+}
+
+
+# func_stripname PREFIX SUFFIX NAME
+# ---------------------------------
+# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+if test yes = "$_G_HAVE_XSI_OPS"; then
+ eval 'func_stripname ()
+ {
+ $debug_cmd
+
+ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+ # positional parameters, so assign one to ordinary variable first.
+ func_stripname_result=$3
+ func_stripname_result=${func_stripname_result#"$1"}
+ func_stripname_result=${func_stripname_result%"$2"}
+ }'
+else
+ func_stripname ()
+ {
+ $debug_cmd
+
+ case $2 in
+ .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;;
+ *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;;
+ esac
+ }
+fi
+
+
+# func_show_eval CMD [FAIL_EXP]
+# -----------------------------
+# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is
+# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.
+func_show_eval ()
+{
+ $debug_cmd
+
+ _G_cmd=$1
+ _G_fail_exp=${2-':'}
+
+ func_quote_arg pretty,expand "$_G_cmd"
+ eval "func_notquiet $func_quote_arg_result"
+
+ $opt_dry_run || {
+ eval "$_G_cmd"
+ _G_status=$?
+ if test 0 -ne "$_G_status"; then
+ eval "(exit $_G_status); $_G_fail_exp"
+ fi
+ }
+}
+
+
+# func_show_eval_locale CMD [FAIL_EXP]
+# ------------------------------------
+# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is
+# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it. Use the saved locale for evaluation.
+func_show_eval_locale ()
+{
+ $debug_cmd
+
+ _G_cmd=$1
+ _G_fail_exp=${2-':'}
+
+ $opt_quiet || {
+ func_quote_arg expand,pretty "$_G_cmd"
+ eval "func_echo $func_quote_arg_result"
+ }
+
+ $opt_dry_run || {
+ eval "$_G_user_locale
+ $_G_cmd"
+ _G_status=$?
+ eval "$_G_safe_locale"
+ if test 0 -ne "$_G_status"; then
+ eval "(exit $_G_status); $_G_fail_exp"
+ fi
+ }
+}
+
+
+# func_tr_sh
+# ----------
+# Turn $1 into a string suitable for a shell variable name.
+# Result is stored in $func_tr_sh_result. All characters
+# not in the set a-zA-Z0-9_ are replaced with '_'. Further,
+# if $1 begins with a digit, a '_' is prepended as well.
+func_tr_sh ()
+{
+ $debug_cmd
+
+ case $1 in
+ [0-9]* | *[!a-zA-Z0-9_]*)
+ func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'`
+ ;;
+ * )
+ func_tr_sh_result=$1
+ ;;
+ esac
+}
+
+
+# func_verbose ARG...
+# -------------------
+# Echo program name prefixed message in verbose mode only.
+func_verbose ()
+{
+ $debug_cmd
+
+ $opt_verbose && func_echo "$*"
+
+ :
+}
+
+
+# func_warn_and_continue ARG...
+# -----------------------------
+# Echo program name prefixed warning message to standard error.
+func_warn_and_continue ()
+{
+ $debug_cmd
+
+ $require_term_colors
+
+ func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2
+}
+
+
+# func_warning CATEGORY ARG...
+# ----------------------------
+# Echo program name prefixed warning message to standard error. Warning
+# messages can be filtered according to CATEGORY, where this function
+# elides messages where CATEGORY is not listed in the global variable
+# 'opt_warning_types'.
+func_warning ()
+{
+ $debug_cmd
+
+ # CATEGORY must be in the warning_categories list!
+ case " $warning_categories " in
+ *" $1 "*) ;;
+ *) func_internal_error "invalid warning category '$1'" ;;
+ esac
+
+ _G_category=$1
+ shift
+
+ case " $opt_warning_types " in
+ *" $_G_category "*) $warning_func ${1+"$@"} ;;
+ esac
+}
+
+
+# func_sort_ver VER1 VER2
+# -----------------------
+# 'sort -V' is not generally available.
+# Note this deviates from the version comparison in automake
+# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a
+# but this should suffice as we won't be specifying old
+# version formats or redundant trailing .0 in bootstrap.conf.
+# If we did want full compatibility then we should probably
+# use m4_version_compare from autoconf.
+func_sort_ver ()
+{
+ $debug_cmd
+
+ printf '%s\n%s\n' "$1" "$2" \
+ | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n
+}
+
+# func_lt_ver PREV CURR
+# ---------------------
+# Return true if PREV and CURR are in the correct order according to
+# func_sort_ver, otherwise false. Use it like this:
+#
+# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..."
+func_lt_ver ()
+{
+ $debug_cmd
+
+ test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q`
+}
+
+
+# Local variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC"
+# time-stamp-time-zone: "UTC"
+# End:
+#! /bin/sh
+
+# A portable, pluggable option parser for Bourne shell.
+# Written by Gary V. Vaughan, 2010
+
+# This is free software. There is NO warranty; not even for
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Copyright (C) 2010-2019, 2021 Bootstrap Authors
+#
+# This file is dual licensed under the terms of the MIT license
+# <https://opensource.org/license/MIT>, and GPL version 2 or later
+# <http://www.gnu.org/licenses/gpl-2.0.html>. You must apply one of
+# these licenses when using or redistributing this software or any of
+# the files within it. See the URLs above, or the file `LICENSE`
+# included in the Bootstrap distribution for the full license texts.
+
+# Please report bugs or propose patches to:
+# <https://github.com/gnulib-modules/bootstrap/issues>
+
+# Set a version string for this script.
+scriptversion=2019-02-19.15; # UTC
+
+
+## ------ ##
+## Usage. ##
+## ------ ##
+
+# This file is a library for parsing options in your shell scripts along
+# with assorted other useful supporting features that you can make use
+# of too.
+#
+# For the simplest scripts you might need only:
+#
+# #!/bin/sh
+# . relative/path/to/funclib.sh
+# . relative/path/to/options-parser
+# scriptversion=1.0
+# func_options ${1+"$@"}
+# eval set dummy "$func_options_result"; shift
+# ...rest of your script...
+#
+# In order for the '--version' option to work, you will need to have a
+# suitably formatted comment like the one at the top of this file
+# starting with '# Written by ' and ending with '# Copyright'.
+#
+# For '-h' and '--help' to work, you will also need a one line
+# description of your script's purpose in a comment directly above the
+# '# Written by ' line, like the one at the top of this file.
+#
+# The default options also support '--debug', which will turn on shell
+# execution tracing (see the comment above debug_cmd below for another
+# use), and '--verbose' and the func_verbose function to allow your script
+# to display verbose messages only when your user has specified
+# '--verbose'.
+#
+# After sourcing this file, you can plug in processing for additional
+# options by amending the variables from the 'Configuration' section
+# below, and following the instructions in the 'Option parsing'
+# section further down.
+
+## -------------- ##
+## Configuration. ##
+## -------------- ##
+
+# You should override these variables in your script after sourcing this
+# file so that they reflect the customisations you have added to the
+# option parser.
+
+# The usage line for option parsing errors and the start of '-h' and
+# '--help' output messages. You can embed shell variables for delayed
+# expansion at the time the message is displayed, but you will need to
+# quote other shell meta-characters carefully to prevent them being
+# expanded when the contents are evaled.
+usage='$progpath [OPTION]...'
+
+# Short help message in response to '-h' and '--help'. Add to this or
+# override it after sourcing this library to reflect the full set of
+# options your script accepts.
+usage_message="\
+ --debug enable verbose shell tracing
+ -W, --warnings=CATEGORY
+ report the warnings falling in CATEGORY [all]
+ -v, --verbose verbosely report processing
+ --version print version information and exit
+ -h, --help print short or long help message and exit
+"
+
+# Additional text appended to 'usage_message' in response to '--help'.
+long_help_message="
+Warning categories include:
+ 'all' show all warnings
+ 'none' turn off all the warnings
+ 'error' warnings are treated as fatal errors"
+
+# Help message printed before fatal option parsing errors.
+fatal_help="Try '\$progname --help' for more information."
+
+
+
+## ------------------------- ##
+## Hook function management. ##
+## ------------------------- ##
+
+# This section contains functions for adding, removing, and running hooks
+# in the main code. A hook is just a list of function names that can be
+# run in order later on.
+
+# func_hookable FUNC_NAME
+# -----------------------
+# Declare that FUNC_NAME will run hooks added with
+# 'func_add_hook FUNC_NAME ...'.
+func_hookable ()
+{
+ $debug_cmd
+
+ func_append hookable_fns " $1"
+}
+
+
+# func_add_hook FUNC_NAME HOOK_FUNC
+# ---------------------------------
+# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must
+# first have been declared "hookable" by a call to 'func_hookable'.
+func_add_hook ()
+{
+ $debug_cmd
+
+ case " $hookable_fns " in
+ *" $1 "*) ;;
+ *) func_fatal_error "'$1' does not accept hook functions." ;;
+ esac
+
+ eval func_append ${1}_hooks '" $2"'
+}
+
+
+# func_remove_hook FUNC_NAME HOOK_FUNC
+# ------------------------------------
+# Remove HOOK_FUNC from the list of hook functions to be called by
+# FUNC_NAME.
+func_remove_hook ()
+{
+ $debug_cmd
+
+ eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`'
+}
+
+
+# func_propagate_result FUNC_NAME_A FUNC_NAME_B
+# ---------------------------------------------
+# If the *_result variable of FUNC_NAME_A _is set_, assign its value to
+# *_result variable of FUNC_NAME_B.
+func_propagate_result ()
+{
+ $debug_cmd
+
+ func_propagate_result_result=:
+ if eval "test \"\${${1}_result+set}\" = set"
+ then
+ eval "${2}_result=\$${1}_result"
+ else
+ func_propagate_result_result=false
+ fi
+}
+
+
+# func_run_hooks FUNC_NAME [ARG]...
+# ---------------------------------
+# Run all hook functions registered to FUNC_NAME.
+# It's assumed that the list of hook functions contains nothing more
+# than a whitespace-delimited list of legal shell function names, and
+# no effort is wasted trying to catch shell meta-characters or preserve
+# whitespace.
+func_run_hooks ()
+{
+ $debug_cmd
+
+ case " $hookable_fns " in
+ *" $1 "*) ;;
+ *) func_fatal_error "'$1' does not support hook functions." ;;
+ esac
+
+ eval _G_hook_fns=\$$1_hooks; shift
+
+ for _G_hook in $_G_hook_fns; do
+ func_unset "${_G_hook}_result"
+ eval $_G_hook '${1+"$@"}'
+ func_propagate_result $_G_hook func_run_hooks
+ if $func_propagate_result_result; then
+ eval set dummy "$func_run_hooks_result"; shift
+ fi
+ done
+}
+
+
+
+## --------------- ##
+## Option parsing. ##
+## --------------- ##
+
+# In order to add your own option parsing hooks, you must accept the
+# full positional parameter list from your hook function. You may remove
+# or edit any options that you action, and then pass back the remaining
+# unprocessed options in '<hooked_function_name>_result', escaped
+# suitably for 'eval'.
+#
+# The '<hooked_function_name>_result' variable is automatically unset
+# before your hook gets called; for best performance, only set the
+# *_result variable when necessary (i.e. don't call the 'func_quote'
+# function unnecessarily because it can be an expensive operation on some
+# machines).
+#
+# Like this:
+#
+# my_options_prep ()
+# {
+# $debug_cmd
+#
+# # Extend the existing usage message.
+# usage_message=$usage_message'
+# -s, --silent don'\''t print informational messages
+# '
+# # No change in '$@' (ignored completely by this hook). Leave
+# # my_options_prep_result variable intact.
+# }
+# func_add_hook func_options_prep my_options_prep
+#
+#
+# my_silent_option ()
+# {
+# $debug_cmd
+#
+# args_changed=false
+#
+# # Note that, for efficiency, we parse as many options as we can
+# # recognise in a loop before passing the remainder back to the
+# # caller on the first unrecognised argument we encounter.
+# while test $# -gt 0; do
+# opt=$1; shift
+# case $opt in
+# --silent|-s) opt_silent=:
+# args_changed=:
+# ;;
+# # Separate non-argument short options:
+# -s*) func_split_short_opt "$_G_opt"
+# set dummy "$func_split_short_opt_name" \
+# "-$func_split_short_opt_arg" ${1+"$@"}
+# shift
+# args_changed=:
+# ;;
+# *) # Make sure the first unrecognised option "$_G_opt"
+# # is added back to "$@" in case we need it later,
+# # if $args_changed was set to 'true'.
+# set dummy "$_G_opt" ${1+"$@"}; shift; break ;;
+# esac
+# done
+#
+# # Only call 'func_quote' here if we processed at least one argument.
+# if $args_changed; then
+# func_quote eval ${1+"$@"}
+# my_silent_option_result=$func_quote_result
+# fi
+# }
+# func_add_hook func_parse_options my_silent_option
+#
+#
+# my_option_validation ()
+# {
+# $debug_cmd
+#
+# $opt_silent && $opt_verbose && func_fatal_help "\
+# '--silent' and '--verbose' options are mutually exclusive."
+# }
+# func_add_hook func_validate_options my_option_validation
+#
+# You'll also need to manually amend $usage_message to reflect the extra
+# options you parse. It's preferable to append if you can, so that
+# multiple option parsing hooks can be added safely.
+
+
+# func_options_finish [ARG]...
+# ----------------------------
+# Finishing the option parse loop (call 'func_options' hooks ATM).
+func_options_finish ()
+{
+ $debug_cmd
+
+ func_run_hooks func_options ${1+"$@"}
+ func_propagate_result func_run_hooks func_options_finish
+}
+
+
+# func_options [ARG]...
+# ---------------------
+# All the functions called inside func_options are hookable. See the
+# individual implementations for details.
+func_hookable func_options
+func_options ()
+{
+ $debug_cmd
+
+ _G_options_quoted=false
+
+ for my_func in options_prep parse_options validate_options options_finish
+ do
+ func_unset func_${my_func}_result
+ func_unset func_run_hooks_result
+ eval func_$my_func '${1+"$@"}'
+ func_propagate_result func_$my_func func_options
+ if $func_propagate_result_result; then
+ eval set dummy "$func_options_result"; shift
+ _G_options_quoted=:
+ fi
+ done
+
+ $_G_options_quoted || {
+ # As we (func_options) are top-level options-parser function and
+ # nobody quoted "$@" for us yet, we need to do it explicitly for
+ # caller.
+ func_quote eval ${1+"$@"}
+ func_options_result=$func_quote_result
+ }
+}
+
+
+# func_options_prep [ARG]...
+# --------------------------
+# All initialisations required before starting the option parse loop.
+# Note that when calling hook functions, we pass through the list of
+# positional parameters. If a hook function modifies that list, and
+# needs to propagate that back to rest of this script, then the complete
+# modified list must be put in 'func_run_hooks_result' before returning.
+func_hookable func_options_prep
+func_options_prep ()
+{
+ $debug_cmd
+
+ # Option defaults:
+ opt_verbose=false
+ opt_warning_types=
+
+ func_run_hooks func_options_prep ${1+"$@"}
+ func_propagate_result func_run_hooks func_options_prep
+}
+
+
+# func_parse_options [ARG]...
+# ---------------------------
+# The main option parsing loop.
+func_hookable func_parse_options
+func_parse_options ()
+{
+ $debug_cmd
+
+ _G_parse_options_requote=false
+ # this just eases exit handling
+ while test $# -gt 0; do
+ # Defer to hook functions for initial option parsing, so they
+ # get priority in the event of reusing an option name.
+ func_run_hooks func_parse_options ${1+"$@"}
+ func_propagate_result func_run_hooks func_parse_options
+ if $func_propagate_result_result; then
+ eval set dummy "$func_parse_options_result"; shift
+ # Even though we may have changed "$@", we passed the "$@" array
+ # down into the hook and it quoted it for us (because we are in
+ # this if-branch). No need to quote it again.
+ _G_parse_options_requote=false
+ fi
+
+ # Break out of the loop if we already parsed every option.
+ test $# -gt 0 || break
+
+ # We expect that one of the options parsed in this function matches
+ # and thus we remove _G_opt from "$@" and need to re-quote.
+ _G_match_parse_options=:
+ _G_opt=$1
+ shift
+ case $_G_opt in
+ --debug|-x) debug_cmd='set -x'
+ func_echo "enabling shell trace mode" >&2
+ $debug_cmd
+ ;;
+
+ --no-warnings|--no-warning|--no-warn)
+ set dummy --warnings none ${1+"$@"}
+ shift
+ ;;
+
+ --warnings|--warning|-W)
+ if test $# = 0 && func_missing_arg $_G_opt; then
+ _G_parse_options_requote=:
+ break
+ fi
+ case " $warning_categories $1" in
+ *" $1 "*)
+ # trailing space prevents matching last $1 above
+ func_append_uniq opt_warning_types " $1"
+ ;;
+ *all)
+ opt_warning_types=$warning_categories
+ ;;
+ *none)
+ opt_warning_types=none
+ warning_func=:
+ ;;
+ *error)
+ opt_warning_types=$warning_categories
+ warning_func=func_fatal_error
+ ;;
+ *)
+ func_fatal_error \
+ "unsupported warning category: '$1'"
+ ;;
+ esac
+ shift
+ ;;
+
+ --verbose|-v) opt_verbose=: ;;
+ --version) func_version ;;
+ -\?|-h) func_usage ;;
+ --help) func_help ;;
+
+ # Separate optargs to long options (plugins may need this):
+ --*=*) func_split_equals "$_G_opt"
+ set dummy "$func_split_equals_lhs" \
+ "$func_split_equals_rhs" ${1+"$@"}
+ shift
+ ;;
+
+ # Separate optargs to short options:
+ -W*)
+ func_split_short_opt "$_G_opt"
+ set dummy "$func_split_short_opt_name" \
+ "$func_split_short_opt_arg" ${1+"$@"}
+ shift
+ ;;
+
+ # Separate non-argument short options:
+ -\?*|-h*|-v*|-x*)
+ func_split_short_opt "$_G_opt"
+ set dummy "$func_split_short_opt_name" \
+ "-$func_split_short_opt_arg" ${1+"$@"}
+ shift
+ ;;
+
+ --) _G_parse_options_requote=: ; break ;;
+ -*) func_fatal_help "unrecognised option: '$_G_opt'" ;;
+ *) set dummy "$_G_opt" ${1+"$@"}; shift
+ _G_match_parse_options=false
+ break
+ ;;
+ esac
+
+ if $_G_match_parse_options; then
+ _G_parse_options_requote=:
+ fi
+ done
+
+ if $_G_parse_options_requote; then
+ # save modified positional parameters for caller
+ func_quote eval ${1+"$@"}
+ func_parse_options_result=$func_quote_result
+ fi
+}
+
+
+# func_validate_options [ARG]...
+# ------------------------------
+# Perform any sanity checks on option settings and/or unconsumed
+# arguments.
+func_hookable func_validate_options
+func_validate_options ()
+{
+ $debug_cmd
+
+ # Display all warnings if -W was not given.
+ test -n "$opt_warning_types" || opt_warning_types=" $warning_categories"
+
+ func_run_hooks func_validate_options ${1+"$@"}
+ func_propagate_result func_run_hooks func_validate_options
+
+ # Bail if the options were screwed!
+ $exit_cmd $EXIT_FAILURE
+}
+
+
+
+## ----------------- ##
+## Helper functions. ##
+## ----------------- ##
+
+# This section contains the helper functions used by the rest of the
+# hookable option parser framework in ascii-betical order.
+
+
+# func_fatal_help ARG...
+# ----------------------
+# Echo program name prefixed message to standard error, followed by
+# a help hint, and exit.
+func_fatal_help ()
+{
+ $debug_cmd
+
+ eval \$ECHO \""Usage: $usage"\"
+ eval \$ECHO \""$fatal_help"\"
+ func_error ${1+"$@"}
+ exit $EXIT_FAILURE
+}
+
+
+# func_help
+# ---------
+# Echo long help message to standard output and exit.
+func_help ()
+{
+ $debug_cmd
+
+ func_usage_message
+ $ECHO "$long_help_message"
+ exit 0
+}
+
+
+# func_missing_arg ARGNAME
+# ------------------------
+# Echo program name prefixed message to standard error and set global
+# exit_cmd.
+func_missing_arg ()
+{
+ $debug_cmd
+
+ func_error "Missing argument for '$1'."
+ exit_cmd=exit
+}
+
+
+# func_split_equals STRING
+# ------------------------
+# Set func_split_equals_lhs and func_split_equals_rhs shell variables
+# after splitting STRING at the '=' sign.
+test -z "$_G_HAVE_XSI_OPS" \
+ && (eval 'x=a/b/c;
+ test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \
+ && _G_HAVE_XSI_OPS=yes
+
+if test yes = "$_G_HAVE_XSI_OPS"
+then
+ # This is an XSI compatible shell, allowing a faster implementation...
+ eval 'func_split_equals ()
+ {
+ $debug_cmd
+
+ func_split_equals_lhs=${1%%=*}
+ func_split_equals_rhs=${1#*=}
+ if test "x$func_split_equals_lhs" = "x$1"; then
+ func_split_equals_rhs=
+ fi
+ }'
+else
+ # ...otherwise fall back to using expr, which is often a shell builtin.
+ func_split_equals ()
+ {
+ $debug_cmd
+
+ func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'`
+ func_split_equals_rhs=
+ test "x$func_split_equals_lhs=" = "x$1" \
+ || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'`
+ }
+fi #func_split_equals
+
+
+# func_split_short_opt SHORTOPT
+# -----------------------------
+# Set func_split_short_opt_name and func_split_short_opt_arg shell
+# variables after splitting SHORTOPT after the 2nd character.
+if test yes = "$_G_HAVE_XSI_OPS"
+then
+ # This is an XSI compatible shell, allowing a faster implementation...
+ eval 'func_split_short_opt ()
+ {
+ $debug_cmd
+
+ func_split_short_opt_arg=${1#??}
+ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}
+ }'
+else
+ # ...otherwise fall back to using expr, which is often a shell builtin.
+ func_split_short_opt ()
+ {
+ $debug_cmd
+
+ func_split_short_opt_name=`expr "x$1" : 'x\(-.\)'`
+ func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'`
+ }
+fi #func_split_short_opt
+
+
+# func_usage
+# ----------
+# Echo short help message to standard output and exit.
+func_usage ()
+{
+ $debug_cmd
+
+ func_usage_message
+ $ECHO "Run '$progname --help |${PAGER-more}' for full usage"
+ exit 0
+}
+
+
+# func_usage_message
+# ------------------
+# Echo short help message to standard output.
+func_usage_message ()
+{
+ $debug_cmd
+
+ eval \$ECHO \""Usage: $usage"\"
+ echo
+ $SED -n 's|^# ||
+ /^Written by/{
+ x;p;x
+ }
+ h
+ /^Written by/q' < "$progpath"
+ echo
+ eval \$ECHO \""$usage_message"\"
+}
+
+
+# func_version
+# ------------
+# Echo version message to standard output and exit.
+# The version message is extracted from the calling file's header
+# comments, with leading '# ' stripped:
+# 1. First display the progname and version
+# 2. Followed by the header comment line matching /^# Written by /
+# 3. Then a blank line followed by the first following line matching
+# /^# Copyright /
+# 4. Immediately followed by any lines between the previous matches,
+# except lines preceding the intervening completely blank line.
+# For example, see the header comments of this file.
+func_version ()
+{
+ $debug_cmd
+
+ printf '%s\n' "$progname $scriptversion"
+ $SED -n '
+ /^# Written by /!b
+ s|^# ||; p; n
+
+ :fwd2blnk
+ /./ {
+ n
+ b fwd2blnk
+ }
+ p; n
+
+ :holdwrnt
+ s|^# ||
+ s|^# *$||
+ /^Copyright /!{
+ /./H
+ n
+ b holdwrnt
+ }
+
+ s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2|
+ G
+ s|\(\n\)\n*|\1|g
+ p; q' < "$progpath"
+
+ exit $?
+}
+
+
+# Local variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-pattern: "30/scriptversion=%:y-%02m-%02d.%02H; # UTC"
+# time-stamp-time-zone: "UTC"
+# End:
+
+# Set a version string.
+scriptversion='(GNU libtool) 2.4.7'
+
+
+# func_echo ARG...
+# ----------------
+# Libtool also displays the current mode in messages, so override
+# funclib.sh func_echo with this custom definition.
+func_echo ()
+{
+ $debug_cmd
+
+ _G_message=$*
+
+ func_echo_IFS=$IFS
+ IFS=$nl
+ for _G_line in $_G_message; do
+ IFS=$func_echo_IFS
+ $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line"
+ done
+ IFS=$func_echo_IFS
+}
+
+
+# func_warning ARG...
+# -------------------
+# Libtool warnings are not categorized, so override funclib.sh
+# func_warning with this simpler definition.
+func_warning ()
+{
+ $debug_cmd
+
+ $warning_func ${1+"$@"}
+}
+
+
+## ---------------- ##
+## Options parsing. ##
+## ---------------- ##
+
+# Hook in the functions to make sure our own options are parsed during
+# the option parsing loop.
+
+usage='$progpath [OPTION]... [MODE-ARG]...'
+
+# Short help message in response to '-h'.
+usage_message="Options:
+ --config show all configuration variables
+ --debug enable verbose shell tracing
+ -n, --dry-run display commands without modifying any files
+ --features display basic configuration information and exit
+ --mode=MODE use operation mode MODE
+ --no-warnings equivalent to '-Wnone'
+ --preserve-dup-deps don't remove duplicate dependency libraries
+ --quiet, --silent don't print informational messages
+ --tag=TAG use configuration variables from tag TAG
+ -v, --verbose print more informational messages than default
+ --version print version information
+ -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all]
+ -h, --help, --help-all print short, long, or detailed help message
+"
+
+# Additional text appended to 'usage_message' in response to '--help'.
+func_help ()
+{
+ $debug_cmd
+
+ func_usage_message
+ $ECHO "$long_help_message
+
+MODE must be one of the following:
+
+ clean remove files from the build directory
+ compile compile a source file into a libtool object
+ execute automatically set library path, then run a program
+ finish complete the installation of libtool libraries
+ install install libraries or executables
+ link create a library or an executable
+ uninstall remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE. When passed as first option,
+'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that.
+Try '$progname --help --mode=MODE' for a more detailed description of MODE.
+
+When reporting a bug, please describe a test case to reproduce it and
+include the following information:
+
+ host-triplet: $host
+ shell: $SHELL
+ compiler: $LTCC
+ compiler flags: $LTCFLAGS
+ linker: $LD (gnu? $with_gnu_ld)
+ version: $progname (GNU libtool) 2.4.7
+ automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
+ autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q`
+
+Report bugs to <bug-libtool@gnu.org>.
+GNU libtool home page: <https://www.gnu.org/software/libtool/>.
+General help using GNU software: <http://www.gnu.org/gethelp/>."
+ exit 0
+}
+
+
+# func_lo2o OBJECT-NAME
+# ---------------------
+# Transform OBJECT-NAME from a '.lo' suffix to the platform specific
+# object suffix.
+
+lo2o=s/\\.lo\$/.$objext/
+o2lo=s/\\.$objext\$/.lo/
+
+if test yes = "$_G_HAVE_XSI_OPS"; then
+ eval 'func_lo2o ()
+ {
+ case $1 in
+ *.lo) func_lo2o_result=${1%.lo}.$objext ;;
+ * ) func_lo2o_result=$1 ;;
+ esac
+ }'
+
+ # func_xform LIBOBJ-OR-SOURCE
+ # ---------------------------
+ # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise)
+ # suffix to a '.lo' libtool-object suffix.
+ eval 'func_xform ()
+ {
+ func_xform_result=${1%.*}.lo
+ }'
+else
+ # ...otherwise fall back to using sed.
+ func_lo2o ()
+ {
+ func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"`
+ }
+
+ func_xform ()
+ {
+ func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'`
+ }
+fi
+
+
+# func_fatal_configuration ARG...
+# -------------------------------
+# Echo program name prefixed message to standard error, followed by
+# a configuration failure hint, and exit.
+func_fatal_configuration ()
+{
+ func_fatal_error ${1+"$@"} \
+ "See the $PACKAGE documentation for more information." \
+ "Fatal configuration error."
+}
+
+
+# func_config
+# -----------
+# Display the configuration for all the tags in this script.
+func_config ()
+{
+ re_begincf='^# ### BEGIN LIBTOOL'
+ re_endcf='^# ### END LIBTOOL'
+
+ # Default configuration.
+ $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"
+
+ # Now print the configurations for the tags.
+ for tagname in $taglist; do
+ $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
+ done
+
+ exit $?
+}
+
+
+# func_features
+# -------------
+# Display the features supported by this script.
+func_features ()
+{
+ echo "host: $host"
+ if test yes = "$build_libtool_libs"; then
+ echo "enable shared libraries"
+ else
+ echo "disable shared libraries"
+ fi
+ if test yes = "$build_old_libs"; then
+ echo "enable static libraries"
+ else
+ echo "disable static libraries"
+ fi
+
+ exit $?
+}
+
+
+# func_enable_tag TAGNAME
+# -----------------------
+# Verify that TAGNAME is valid, and either flag an error and exit, or
+# enable the TAGNAME tag. We also add TAGNAME to the global $taglist
+# variable here.
+func_enable_tag ()
+{
+ # Global variable:
+ tagname=$1
+
+ re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
+ re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
+ sed_extractcf=/$re_begincf/,/$re_endcf/p
+
+ # Validate tagname.
+ case $tagname in
+ *[!-_A-Za-z0-9,/]*)
+ func_fatal_error "invalid tag name: $tagname"
+ ;;
+ esac
+
+ # Don't test for the "default" C tag, as we know it's
+ # there but not specially marked.
+ case $tagname in
+ CC) ;;
+ *)
+ if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
+ taglist="$taglist $tagname"
+
+ # Evaluate the configuration. Be careful to quote the path
+ # and the sed script, to avoid splitting on whitespace, but
+ # also don't use non-portable quotes within backquotes within
+ # quotes we have to do it in 2 steps:
+ extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
+ eval "$extractedcf"
+ else
+ func_error "ignoring unknown tag $tagname"
+ fi
+ ;;
+ esac
+}
+
+
+# func_check_version_match
+# ------------------------
+# Ensure that we are using m4 macros, and libtool script from the same
+# release of libtool.
+func_check_version_match ()
+{
+ if test "$package_revision" != "$macro_revision"; then
+ if test "$VERSION" != "$macro_version"; then
+ if test -z "$macro_version"; then
+ cat >&2 <<_LT_EOF
+$progname: Version mismatch error. This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from an older release.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+ else
+ cat >&2 <<_LT_EOF
+$progname: Version mismatch error. This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+ fi
+ else
+ cat >&2 <<_LT_EOF
+$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision,
+$progname: but the definition of this LT_INIT comes from revision $macro_revision.
+$progname: You should recreate aclocal.m4 with macros from revision $package_revision
+$progname: of $PACKAGE $VERSION and run autoconf again.
+_LT_EOF
+ fi
+
+ exit $EXIT_MISMATCH
+ fi
+}
+
+
+# libtool_options_prep [ARG]...
+# -----------------------------
+# Preparation for options parsed by libtool.
+libtool_options_prep ()
+{
+ $debug_mode
+
+ # Option defaults:
+ opt_config=false
+ opt_dlopen=
+ opt_dry_run=false
+ opt_help=false
+ opt_mode=
+ opt_preserve_dup_deps=false
+ opt_quiet=false
+
+ nonopt=
+ preserve_args=
+
+ _G_rc_lt_options_prep=:
+
+ # Shorthand for --mode=foo, only valid as the first argument
+ case $1 in
+ clean|clea|cle|cl)
+ shift; set dummy --mode clean ${1+"$@"}; shift
+ ;;
+ compile|compil|compi|comp|com|co|c)
+ shift; set dummy --mode compile ${1+"$@"}; shift
+ ;;
+ execute|execut|execu|exec|exe|ex|e)
+ shift; set dummy --mode execute ${1+"$@"}; shift
+ ;;
+ finish|finis|fini|fin|fi|f)
+ shift; set dummy --mode finish ${1+"$@"}; shift
+ ;;
+ install|instal|insta|inst|ins|in|i)
+ shift; set dummy --mode install ${1+"$@"}; shift
+ ;;
+ link|lin|li|l)
+ shift; set dummy --mode link ${1+"$@"}; shift
+ ;;
+ uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
+ shift; set dummy --mode uninstall ${1+"$@"}; shift
+ ;;
+ *)
+ _G_rc_lt_options_prep=false
+ ;;
+ esac
+
+ if $_G_rc_lt_options_prep; then
+ # Pass back the list of options.
+ func_quote eval ${1+"$@"}
+ libtool_options_prep_result=$func_quote_result
+ fi
+}
+func_add_hook func_options_prep libtool_options_prep
+
+
+# libtool_parse_options [ARG]...
+# ---------------------------------
+# Provide handling for libtool specific options.
+libtool_parse_options ()
+{
+ $debug_cmd
+
+ _G_rc_lt_parse_options=false
+
+ # Perform our own loop to consume as many options as possible in
+ # each iteration.
+ while test $# -gt 0; do
+ _G_match_lt_parse_options=:
+ _G_opt=$1
+ shift
+ case $_G_opt in
+ --dry-run|--dryrun|-n)
+ opt_dry_run=:
+ ;;
+
+ --config) func_config ;;
+
+ --dlopen|-dlopen)
+ opt_dlopen="${opt_dlopen+$opt_dlopen
+}$1"
+ shift
+ ;;
+
+ --preserve-dup-deps)
+ opt_preserve_dup_deps=: ;;
+
+ --features) func_features ;;
+
+ --finish) set dummy --mode finish ${1+"$@"}; shift ;;
+
+ --help) opt_help=: ;;
+
+ --help-all) opt_help=': help-all' ;;
+
+ --mode) test $# = 0 && func_missing_arg $_G_opt && break
+ opt_mode=$1
+ case $1 in
+ # Valid mode arguments:
+ clean|compile|execute|finish|install|link|relink|uninstall) ;;
+
+ # Catch anything else as an error
+ *) func_error "invalid argument for $_G_opt"
+ exit_cmd=exit
+ break
+ ;;
+ esac
+ shift
+ ;;
+
+ --no-silent|--no-quiet)
+ opt_quiet=false
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ --no-warnings|--no-warning|--no-warn)
+ opt_warning=false
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ --no-verbose)
+ opt_verbose=false
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ --silent|--quiet)
+ opt_quiet=:
+ opt_verbose=false
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ --tag) test $# = 0 && func_missing_arg $_G_opt && break
+ opt_tag=$1
+ func_append preserve_args " $_G_opt $1"
+ func_enable_tag "$1"
+ shift
+ ;;
+
+ --verbose|-v) opt_quiet=false
+ opt_verbose=:
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ # An option not handled by this hook function:
+ *) set dummy "$_G_opt" ${1+"$@"} ; shift
+ _G_match_lt_parse_options=false
+ break
+ ;;
+ esac
+ $_G_match_lt_parse_options && _G_rc_lt_parse_options=:
+ done
+
+ if $_G_rc_lt_parse_options; then
+ # save modified positional parameters for caller
+ func_quote eval ${1+"$@"}
+ libtool_parse_options_result=$func_quote_result
+ fi
+}
+func_add_hook func_parse_options libtool_parse_options
+
+
+
+# libtool_validate_options [ARG]...
+# ---------------------------------
+# Perform any sanity checks on option settings and/or unconsumed
+# arguments.
+libtool_validate_options ()
+{
+ # save first non-option argument
+ if test 0 -lt $#; then
+ nonopt=$1
+ shift
+ fi
+
+ # preserve --debug
+ test : = "$debug_cmd" || func_append preserve_args " --debug"
+
+ case $host in
+ # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452
+ # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788
+ *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*)
+ # don't eliminate duplications in $postdeps and $predeps
+ opt_duplicate_compiler_generated_deps=:
+ ;;
+ *)
+ opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps
+ ;;
+ esac
+
+ $opt_help || {
+ # Sanity checks first:
+ func_check_version_match
+
+ test yes != "$build_libtool_libs" \
+ && test yes != "$build_old_libs" \
+ && func_fatal_configuration "not configured to build any kind of library"
+
+ # Darwin sucks
+ eval std_shrext=\"$shrext_cmds\"
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$opt_dlopen" && test execute != "$opt_mode"; then
+ func_error "unrecognized option '-dlopen'"
+ $ECHO "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Change the help message to a mode-specific one.
+ generic_help=$help
+ help="Try '$progname --help --mode=$opt_mode' for more information."
+ }
+
+ # Pass back the unparsed argument list
+ func_quote eval ${1+"$@"}
+ libtool_validate_options_result=$func_quote_result
+}
+func_add_hook func_validate_options libtool_validate_options
+
+
+# Process options as early as possible so that --help and --version
+# can return quickly.
+func_options ${1+"$@"}
+eval set dummy "$func_options_result"; shift
+
+
+
+## ----------- ##
+## Main. ##
+## ----------- ##
+
+magic='%%%MAGIC variable%%%'
+magic_exe='%%%MAGIC EXE variable%%%'
+
+# Global variables.
+extracted_archives=
+extracted_serial=0
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end. This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+
+# func_generated_by_libtool
+# True iff stdin has been generated by Libtool. This function is only
+# a basic sanity check; it will hardly flush out determined imposters.
+func_generated_by_libtool_p ()
+{
+ $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
+}
+
+# func_lalib_p file
+# True iff FILE is a libtool '.la' library or '.lo' object file.
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_lalib_p ()
+{
+ test -f "$1" &&
+ $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p
+}
+
+# func_lalib_unsafe_p file
+# True iff FILE is a libtool '.la' library or '.lo' object file.
+# This function implements the same check as func_lalib_p without
+# resorting to external programs. To this end, it redirects stdin and
+# closes it afterwards, without saving the original file descriptor.
+# As a safety measure, use it only where a negative result would be
+# fatal anyway. Works if 'file' does not exist.
+func_lalib_unsafe_p ()
+{
+ lalib_p=no
+ if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then
+ for lalib_p_l in 1 2 3 4
+ do
+ read lalib_p_line
+ case $lalib_p_line in
+ \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
+ esac
+ done
+ exec 0<&5 5<&-
+ fi
+ test yes = "$lalib_p"
+}
+
+# func_ltwrapper_script_p file
+# True iff FILE is a libtool wrapper script
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_script_p ()
+{
+ test -f "$1" &&
+ $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p
+}
+
+# func_ltwrapper_executable_p file
+# True iff FILE is a libtool wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_executable_p ()
+{
+ func_ltwrapper_exec_suffix=
+ case $1 in
+ *.exe) ;;
+ *) func_ltwrapper_exec_suffix=.exe ;;
+ esac
+ $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
+}
+
+# func_ltwrapper_scriptname file
+# Assumes file is an ltwrapper_executable
+# uses $file to determine the appropriate filename for a
+# temporary ltwrapper_script.
+func_ltwrapper_scriptname ()
+{
+ func_dirname_and_basename "$1" "" "."
+ func_stripname '' '.exe' "$func_basename_result"
+ func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper
+}
+
+# func_ltwrapper_p file
+# True iff FILE is a libtool wrapper script or wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_p ()
+{
+ func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
+}
+
+
+# func_execute_cmds commands fail_cmd
+# Execute tilde-delimited COMMANDS.
+# If FAIL_CMD is given, eval that upon failure.
+# FAIL_CMD may read-access the current command in variable CMD!
+func_execute_cmds ()
+{
+ $debug_cmd
+
+ save_ifs=$IFS; IFS='~'
+ for cmd in $1; do
+ IFS=$sp$nl
+ eval cmd=\"$cmd\"
+ IFS=$save_ifs
+ func_show_eval "$cmd" "${2-:}"
+ done
+ IFS=$save_ifs
+}
+
+
+# func_source file
+# Source FILE, adding directory component if necessary.
+# Note that it is not necessary on cygwin/mingw to append a dot to
+# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
+# behavior happens only for exec(3), not for open(2)! Also, sourcing
+# 'FILE.' does not work on cygwin managed mounts.
+func_source ()
+{
+ $debug_cmd
+
+ case $1 in
+ */* | *\\*) . "$1" ;;
+ *) . "./$1" ;;
+ esac
+}
+
+
+# func_resolve_sysroot PATH
+# Replace a leading = in PATH with a sysroot. Store the result into
+# func_resolve_sysroot_result
+func_resolve_sysroot ()
+{
+ func_resolve_sysroot_result=$1
+ case $func_resolve_sysroot_result in
+ =*)
+ func_stripname '=' '' "$func_resolve_sysroot_result"
+ func_resolve_sysroot_result=$lt_sysroot$func_stripname_result
+ ;;
+ esac
+}
+
+# func_replace_sysroot PATH
+# If PATH begins with the sysroot, replace it with = and
+# store the result into func_replace_sysroot_result.
+func_replace_sysroot ()
+{
+ case $lt_sysroot:$1 in
+ ?*:"$lt_sysroot"*)
+ func_stripname "$lt_sysroot" '' "$1"
+ func_replace_sysroot_result='='$func_stripname_result
+ ;;
+ *)
+ # Including no sysroot.
+ func_replace_sysroot_result=$1
+ ;;
+ esac
+}
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+ $debug_cmd
+
+ if test -n "$available_tags" && test -z "$tagname"; then
+ CC_quoted=
+ for arg in $CC; do
+ func_append_quoted CC_quoted "$arg"
+ done
+ CC_expanded=`func_echo_all $CC`
+ CC_quoted_expanded=`func_echo_all $CC_quoted`
+ case $@ in
+ # Blanks in the command may have been stripped by the calling shell,
+ # but not from the CC environment variable when configure was run.
+ " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;;
+ # Blanks at the start of $base_compile will cause this to fail
+ # if we don't check for them as well.
+ *)
+ for z in $available_tags; do
+ if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+ # Evaluate the configuration.
+ eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+ CC_quoted=
+ for arg in $CC; do
+ # Double-quote args containing other shell metacharacters.
+ func_append_quoted CC_quoted "$arg"
+ done
+ CC_expanded=`func_echo_all $CC`
+ CC_quoted_expanded=`func_echo_all $CC_quoted`
+ case "$@ " in
+ " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*)
+ # The compiler in the base compile command matches
+ # the one in the tagged configuration.
+ # Assume this is the tagged configuration we want.
+ tagname=$z
+ break
+ ;;
+ esac
+ fi
+ done
+ # If $tagname still isn't set, then no tagged configuration
+ # was found and let the user know that the "--tag" command
+ # line option must be used.
+ if test -z "$tagname"; then
+ func_echo "unable to infer tagged configuration"
+ func_fatal_error "specify a tag with '--tag'"
+# else
+# func_verbose "using $tagname tagged configuration"
+ fi
+ ;;
+ esac
+ fi
+}
+
+
+
+# func_write_libtool_object output_name pic_name nonpic_name
+# Create a libtool object file (analogous to a ".la" file),
+# but don't create it if we're doing a dry run.
+func_write_libtool_object ()
+{
+ write_libobj=$1
+ if test yes = "$build_libtool_libs"; then
+ write_lobj=\'$2\'
+ else
+ write_lobj=none
+ fi
+
+ if test yes = "$build_old_libs"; then
+ write_oldobj=\'$3\'
+ else
+ write_oldobj=none
+ fi
+
+ $opt_dry_run || {
+ cat >${write_libobj}T <<EOF
+# $write_libobj - a libtool object file
+# Generated by $PROGRAM (GNU $PACKAGE) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object=$write_lobj
+
+# Name of the non-PIC object
+non_pic_object=$write_oldobj
+
+EOF
+ $MV "${write_libobj}T" "$write_libobj"
+ }
+}
+
+
+##################################################
+# FILE NAME AND PATH CONVERSION HELPER FUNCTIONS #
+##################################################
+
+# func_convert_core_file_wine_to_w32 ARG
+# Helper function used by file name conversion functions when $build is *nix,
+# and $host is mingw, cygwin, or some other w32 environment. Relies on a
+# correctly configured wine environment available, with the winepath program
+# in $build's $PATH.
+#
+# ARG is the $build file name to be converted to w32 format.
+# Result is available in $func_convert_core_file_wine_to_w32_result, and will
+# be empty on error (or when ARG is empty)
+func_convert_core_file_wine_to_w32 ()
+{
+ $debug_cmd
+
+ func_convert_core_file_wine_to_w32_result=$1
+ if test -n "$1"; then
+ # Unfortunately, winepath does not exit with a non-zero error code, so we
+ # are forced to check the contents of stdout. On the other hand, if the
+ # command is not found, the shell will set an exit code of 127 and print
+ # *an error message* to stdout. So we must check for both error code of
+ # zero AND non-empty stdout, which explains the odd construction:
+ func_convert_core_file_wine_to_w32_tmp=`winepath -w "$1" 2>/dev/null`
+ if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then
+ func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" |
+ $SED -e "$sed_naive_backslashify"`
+ else
+ func_convert_core_file_wine_to_w32_result=
+ fi
+ fi
+}
+# end: func_convert_core_file_wine_to_w32
+
+
+# func_convert_core_path_wine_to_w32 ARG
+# Helper function used by path conversion functions when $build is *nix, and
+# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly
+# configured wine environment available, with the winepath program in $build's
+# $PATH. Assumes ARG has no leading or trailing path separator characters.
+#
+# ARG is path to be converted from $build format to win32.
+# Result is available in $func_convert_core_path_wine_to_w32_result.
+# Unconvertible file (directory) names in ARG are skipped; if no directory names
+# are convertible, then the result may be empty.
+func_convert_core_path_wine_to_w32 ()
+{
+ $debug_cmd
+
+ # unfortunately, winepath doesn't convert paths, only file names
+ func_convert_core_path_wine_to_w32_result=
+ if test -n "$1"; then
+ oldIFS=$IFS
+ IFS=:
+ for func_convert_core_path_wine_to_w32_f in $1; do
+ IFS=$oldIFS
+ func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f"
+ if test -n "$func_convert_core_file_wine_to_w32_result"; then
+ if test -z "$func_convert_core_path_wine_to_w32_result"; then
+ func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result
+ else
+ func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result"
+ fi
+ fi
+ done
+ IFS=$oldIFS
+ fi
+}
+# end: func_convert_core_path_wine_to_w32
+
+
+# func_cygpath ARGS...
+# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when
+# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2)
+# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or
+# (2), returns the Cygwin file name or path in func_cygpath_result (input
+# file name or path is assumed to be in w32 format, as previously converted
+# from $build's *nix or MSYS format). In case (3), returns the w32 file name
+# or path in func_cygpath_result (input file name or path is assumed to be in
+# Cygwin format). Returns an empty string on error.
+#
+# ARGS are passed to cygpath, with the last one being the file name or path to
+# be converted.
+#
+# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH
+# environment variable; do not put it in $PATH.
+func_cygpath ()
+{
+ $debug_cmd
+
+ if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then
+ func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null`
+ if test "$?" -ne 0; then
+ # on failure, ensure result is empty
+ func_cygpath_result=
+ fi
+ else
+ func_cygpath_result=
+ func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'"
+ fi
+}
+#end: func_cygpath
+
+
+# func_convert_core_msys_to_w32 ARG
+# Convert file name or path ARG from MSYS format to w32 format. Return
+# result in func_convert_core_msys_to_w32_result.
+func_convert_core_msys_to_w32 ()
+{
+ $debug_cmd
+
+ # awkward: cmd appends spaces to result
+ func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null |
+ $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"`
+}
+#end: func_convert_core_msys_to_w32
+
+
+# func_convert_file_check ARG1 ARG2
+# Verify that ARG1 (a file name in $build format) was converted to $host
+# format in ARG2. Otherwise, emit an error message, but continue (resetting
+# func_to_host_file_result to ARG1).
+func_convert_file_check ()
+{
+ $debug_cmd
+
+ if test -z "$2" && test -n "$1"; then
+ func_error "Could not determine host file name corresponding to"
+ func_error " '$1'"
+ func_error "Continuing, but uninstalled executables may not work."
+ # Fallback:
+ func_to_host_file_result=$1
+ fi
+}
+# end func_convert_file_check
+
+
+# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH
+# Verify that FROM_PATH (a path in $build format) was converted to $host
+# format in TO_PATH. Otherwise, emit an error message, but continue, resetting
+# func_to_host_file_result to a simplistic fallback value (see below).
+func_convert_path_check ()
+{
+ $debug_cmd
+
+ if test -z "$4" && test -n "$3"; then
+ func_error "Could not determine the host path corresponding to"
+ func_error " '$3'"
+ func_error "Continuing, but uninstalled executables may not work."
+ # Fallback. This is a deliberately simplistic "conversion" and
+ # should not be "improved". See libtool.info.
+ if test "x$1" != "x$2"; then
+ lt_replace_pathsep_chars="s|$1|$2|g"
+ func_to_host_path_result=`echo "$3" |
+ $SED -e "$lt_replace_pathsep_chars"`
+ else
+ func_to_host_path_result=$3
+ fi
+ fi
+}
+# end func_convert_path_check
+
+
+# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG
+# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT
+# and appending REPL if ORIG matches BACKPAT.
+func_convert_path_front_back_pathsep ()
+{
+ $debug_cmd
+
+ case $4 in
+ $1 ) func_to_host_path_result=$3$func_to_host_path_result
+ ;;
+ esac
+ case $4 in
+ $2 ) func_append func_to_host_path_result "$3"
+ ;;
+ esac
+}
+# end func_convert_path_front_back_pathsep
+
+
+##################################################
+# $build to $host FILE NAME CONVERSION FUNCTIONS #
+##################################################
+# invoked via '$to_host_file_cmd ARG'
+#
+# In each case, ARG is the path to be converted from $build to $host format.
+# Result will be available in $func_to_host_file_result.
+
+
+# func_to_host_file ARG
+# Converts the file name ARG from $build format to $host format. Return result
+# in func_to_host_file_result.
+func_to_host_file ()
+{
+ $debug_cmd
+
+ $to_host_file_cmd "$1"
+}
+# end func_to_host_file
+
+
+# func_to_tool_file ARG LAZY
+# converts the file name ARG from $build format to toolchain format. Return
+# result in func_to_tool_file_result. If the conversion in use is listed
+# in (the comma separated) LAZY, no conversion takes place.
+func_to_tool_file ()
+{
+ $debug_cmd
+
+ case ,$2, in
+ *,"$to_tool_file_cmd",*)
+ func_to_tool_file_result=$1
+ ;;
+ *)
+ $to_tool_file_cmd "$1"
+ func_to_tool_file_result=$func_to_host_file_result
+ ;;
+ esac
+}
+# end func_to_tool_file
+
+
+# func_convert_file_noop ARG
+# Copy ARG to func_to_host_file_result.
+func_convert_file_noop ()
+{
+ func_to_host_file_result=$1
+}
+# end func_convert_file_noop
+
+
+# func_convert_file_msys_to_w32 ARG
+# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic
+# conversion to w32 is not available inside the cwrapper. Returns result in
+# func_to_host_file_result.
+func_convert_file_msys_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_file_result=$1
+ if test -n "$1"; then
+ func_convert_core_msys_to_w32 "$1"
+ func_to_host_file_result=$func_convert_core_msys_to_w32_result
+ fi
+ func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_msys_to_w32
+
+
+# func_convert_file_cygwin_to_w32 ARG
+# Convert file name ARG from Cygwin to w32 format. Returns result in
+# func_to_host_file_result.
+func_convert_file_cygwin_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_file_result=$1
+ if test -n "$1"; then
+ # because $build is cygwin, we call "the" cygpath in $PATH; no need to use
+ # LT_CYGPATH in this case.
+ func_to_host_file_result=`cygpath -m "$1"`
+ fi
+ func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_cygwin_to_w32
+
+
+# func_convert_file_nix_to_w32 ARG
+# Convert file name ARG from *nix to w32 format. Requires a wine environment
+# and a working winepath. Returns result in func_to_host_file_result.
+func_convert_file_nix_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_file_result=$1
+ if test -n "$1"; then
+ func_convert_core_file_wine_to_w32 "$1"
+ func_to_host_file_result=$func_convert_core_file_wine_to_w32_result
+ fi
+ func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_nix_to_w32
+
+
+# func_convert_file_msys_to_cygwin ARG
+# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set.
+# Returns result in func_to_host_file_result.
+func_convert_file_msys_to_cygwin ()
+{
+ $debug_cmd
+
+ func_to_host_file_result=$1
+ if test -n "$1"; then
+ func_convert_core_msys_to_w32 "$1"
+ func_cygpath -u "$func_convert_core_msys_to_w32_result"
+ func_to_host_file_result=$func_cygpath_result
+ fi
+ func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_msys_to_cygwin
+
+
+# func_convert_file_nix_to_cygwin ARG
+# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed
+# in a wine environment, working winepath, and LT_CYGPATH set. Returns result
+# in func_to_host_file_result.
+func_convert_file_nix_to_cygwin ()
+{
+ $debug_cmd
+
+ func_to_host_file_result=$1
+ if test -n "$1"; then
+ # convert from *nix to w32, then use cygpath to convert from w32 to cygwin.
+ func_convert_core_file_wine_to_w32 "$1"
+ func_cygpath -u "$func_convert_core_file_wine_to_w32_result"
+ func_to_host_file_result=$func_cygpath_result
+ fi
+ func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_nix_to_cygwin
+
+
+#############################################
+# $build to $host PATH CONVERSION FUNCTIONS #
+#############################################
+# invoked via '$to_host_path_cmd ARG'
+#
+# In each case, ARG is the path to be converted from $build to $host format.
+# The result will be available in $func_to_host_path_result.
+#
+# Path separators are also converted from $build format to $host format. If
+# ARG begins or ends with a path separator character, it is preserved (but
+# converted to $host format) on output.
+#
+# All path conversion functions are named using the following convention:
+# file name conversion function : func_convert_file_X_to_Y ()
+# path conversion function : func_convert_path_X_to_Y ()
+# where, for any given $build/$host combination the 'X_to_Y' value is the
+# same. If conversion functions are added for new $build/$host combinations,
+# the two new functions must follow this pattern, or func_init_to_host_path_cmd
+# will break.
+
+
+# func_init_to_host_path_cmd
+# Ensures that function "pointer" variable $to_host_path_cmd is set to the
+# appropriate value, based on the value of $to_host_file_cmd.
+to_host_path_cmd=
+func_init_to_host_path_cmd ()
+{
+ $debug_cmd
+
+ if test -z "$to_host_path_cmd"; then
+ func_stripname 'func_convert_file_' '' "$to_host_file_cmd"
+ to_host_path_cmd=func_convert_path_$func_stripname_result
+ fi
+}
+
+
+# func_to_host_path ARG
+# Converts the path ARG from $build format to $host format. Return result
+# in func_to_host_path_result.
+func_to_host_path ()
+{
+ $debug_cmd
+
+ func_init_to_host_path_cmd
+ $to_host_path_cmd "$1"
+}
+# end func_to_host_path
+
+
+# func_convert_path_noop ARG
+# Copy ARG to func_to_host_path_result.
+func_convert_path_noop ()
+{
+ func_to_host_path_result=$1
+}
+# end func_convert_path_noop
+
+
+# func_convert_path_msys_to_w32 ARG
+# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic
+# conversion to w32 is not available inside the cwrapper. Returns result in
+# func_to_host_path_result.
+func_convert_path_msys_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_path_result=$1
+ if test -n "$1"; then
+ # Remove leading and trailing path separator characters from ARG. MSYS
+ # behavior is inconsistent here; cygpath turns them into '.;' and ';.';
+ # and winepath ignores them completely.
+ func_stripname : : "$1"
+ func_to_host_path_tmp1=$func_stripname_result
+ func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
+ func_to_host_path_result=$func_convert_core_msys_to_w32_result
+ func_convert_path_check : ";" \
+ "$func_to_host_path_tmp1" "$func_to_host_path_result"
+ func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+ fi
+}
+# end func_convert_path_msys_to_w32
+
+
+# func_convert_path_cygwin_to_w32 ARG
+# Convert path ARG from Cygwin to w32 format. Returns result in
+# func_to_host_file_result.
+func_convert_path_cygwin_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_path_result=$1
+ if test -n "$1"; then
+ # See func_convert_path_msys_to_w32:
+ func_stripname : : "$1"
+ func_to_host_path_tmp1=$func_stripname_result
+ func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"`
+ func_convert_path_check : ";" \
+ "$func_to_host_path_tmp1" "$func_to_host_path_result"
+ func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+ fi
+}
+# end func_convert_path_cygwin_to_w32
+
+
+# func_convert_path_nix_to_w32 ARG
+# Convert path ARG from *nix to w32 format. Requires a wine environment and
+# a working winepath. Returns result in func_to_host_file_result.
+func_convert_path_nix_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_path_result=$1
+ if test -n "$1"; then
+ # See func_convert_path_msys_to_w32:
+ func_stripname : : "$1"
+ func_to_host_path_tmp1=$func_stripname_result
+ func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
+ func_to_host_path_result=$func_convert_core_path_wine_to_w32_result
+ func_convert_path_check : ";" \
+ "$func_to_host_path_tmp1" "$func_to_host_path_result"
+ func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+ fi
+}
+# end func_convert_path_nix_to_w32
+
+
+# func_convert_path_msys_to_cygwin ARG
+# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set.
+# Returns result in func_to_host_file_result.
+func_convert_path_msys_to_cygwin ()
+{
+ $debug_cmd
+
+ func_to_host_path_result=$1
+ if test -n "$1"; then
+ # See func_convert_path_msys_to_w32:
+ func_stripname : : "$1"
+ func_to_host_path_tmp1=$func_stripname_result
+ func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
+ func_cygpath -u -p "$func_convert_core_msys_to_w32_result"
+ func_to_host_path_result=$func_cygpath_result
+ func_convert_path_check : : \
+ "$func_to_host_path_tmp1" "$func_to_host_path_result"
+ func_convert_path_front_back_pathsep ":*" "*:" : "$1"
+ fi
+}
+# end func_convert_path_msys_to_cygwin
+
+
+# func_convert_path_nix_to_cygwin ARG
+# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a
+# a wine environment, working winepath, and LT_CYGPATH set. Returns result in
+# func_to_host_file_result.
+func_convert_path_nix_to_cygwin ()
+{
+ $debug_cmd
+
+ func_to_host_path_result=$1
+ if test -n "$1"; then
+ # Remove leading and trailing path separator characters from
+ # ARG. msys behavior is inconsistent here, cygpath turns them
+ # into '.;' and ';.', and winepath ignores them completely.
+ func_stripname : : "$1"
+ func_to_host_path_tmp1=$func_stripname_result
+ func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
+ func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result"
+ func_to_host_path_result=$func_cygpath_result
+ func_convert_path_check : : \
+ "$func_to_host_path_tmp1" "$func_to_host_path_result"
+ func_convert_path_front_back_pathsep ":*" "*:" : "$1"
+ fi
+}
+# end func_convert_path_nix_to_cygwin
+
+
+# func_dll_def_p FILE
+# True iff FILE is a Windows DLL '.def' file.
+# Keep in sync with _LT_DLL_DEF_P in libtool.m4
+func_dll_def_p ()
+{
+ $debug_cmd
+
+ func_dll_def_p_tmp=`$SED -n \
+ -e 's/^[ ]*//' \
+ -e '/^\(;.*\)*$/d' \
+ -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \
+ -e q \
+ "$1"`
+ test DEF = "$func_dll_def_p_tmp"
+}
+
+
+# func_mode_compile arg...
+func_mode_compile ()
+{
+ $debug_cmd
+
+ # Get the compilation command and the source file.
+ base_compile=
+ srcfile=$nonopt # always keep a non-empty value in "srcfile"
+ suppress_opt=yes
+ suppress_output=
+ arg_mode=normal
+ libobj=
+ later=
+ pie_flag=
+
+ for arg
+ do
+ case $arg_mode in
+ arg )
+ # do not "continue". Instead, add this to base_compile
+ lastarg=$arg
+ arg_mode=normal
+ ;;
+
+ target )
+ libobj=$arg
+ arg_mode=normal
+ continue
+ ;;
+
+ normal )
+ # Accept any command-line options.
+ case $arg in
+ -o)
+ test -n "$libobj" && \
+ func_fatal_error "you cannot specify '-o' more than once"
+ arg_mode=target
+ continue
+ ;;
+
+ -pie | -fpie | -fPIE)
+ func_append pie_flag " $arg"
+ continue
+ ;;
+
+ -shared | -static | -prefer-pic | -prefer-non-pic)
+ func_append later " $arg"
+ continue
+ ;;
+
+ -no-suppress)
+ suppress_opt=no
+ continue
+ ;;
+
+ -Xcompiler)
+ arg_mode=arg # the next one goes into the "base_compile" arg list
+ continue # The current "srcfile" will either be retained or
+ ;; # replaced later. I would guess that would be a bug.
+
+ -Wc,*)
+ func_stripname '-Wc,' '' "$arg"
+ args=$func_stripname_result
+ lastarg=
+ save_ifs=$IFS; IFS=,
+ for arg in $args; do
+ IFS=$save_ifs
+ func_append_quoted lastarg "$arg"
+ done
+ IFS=$save_ifs
+ func_stripname ' ' '' "$lastarg"
+ lastarg=$func_stripname_result
+
+ # Add the arguments to base_compile.
+ func_append base_compile " $lastarg"
+ continue
+ ;;
+
+ *)
+ # Accept the current argument as the source file.
+ # The previous "srcfile" becomes the current argument.
+ #
+ lastarg=$srcfile
+ srcfile=$arg
+ ;;
+ esac # case $arg
+ ;;
+ esac # case $arg_mode
+
+ # Aesthetically quote the previous argument.
+ func_append_quoted base_compile "$lastarg"
+ done # for arg
+
+ case $arg_mode in
+ arg)
+ func_fatal_error "you must specify an argument for -Xcompile"
+ ;;
+ target)
+ func_fatal_error "you must specify a target with '-o'"
+ ;;
+ *)
+ # Get the name of the library object.
+ test -z "$libobj" && {
+ func_basename "$srcfile"
+ libobj=$func_basename_result
+ }
+ ;;
+ esac
+
+ # Recognize several different file suffixes.
+ # If the user specifies -o file.o, it is replaced with file.lo
+ case $libobj in
+ *.[cCFSifmso] | \
+ *.ada | *.adb | *.ads | *.asm | \
+ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
+ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup)
+ func_xform "$libobj"
+ libobj=$func_xform_result
+ ;;
+ esac
+
+ case $libobj in
+ *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
+ *)
+ func_fatal_error "cannot determine name of library object from '$libobj'"
+ ;;
+ esac
+
+ func_infer_tag $base_compile
+
+ for arg in $later; do
+ case $arg in
+ -shared)
+ test yes = "$build_libtool_libs" \
+ || func_fatal_configuration "cannot build a shared library"
+ build_old_libs=no
+ continue
+ ;;
+
+ -static)
+ build_libtool_libs=no
+ build_old_libs=yes
+ continue
+ ;;
+
+ -prefer-pic)
+ pic_mode=yes
+ continue
+ ;;
+
+ -prefer-non-pic)
+ pic_mode=no
+ continue
+ ;;
+ esac
+ done
+
+ func_quote_arg pretty "$libobj"
+ test "X$libobj" != "X$func_quote_arg_result" \
+ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \
+ && func_warning "libobj name '$libobj' may not contain shell special characters."
+ func_dirname_and_basename "$obj" "/" ""
+ objname=$func_basename_result
+ xdir=$func_dirname_result
+ lobj=$xdir$objdir/$objname
+
+ test -z "$base_compile" && \
+ func_fatal_help "you must specify a compilation command"
+
+ # Delete any leftover library objects.
+ if test yes = "$build_old_libs"; then
+ removelist="$obj $lobj $libobj ${libobj}T"
+ else
+ removelist="$lobj $libobj ${libobj}T"
+ fi
+
+ # On Cygwin there's no "real" PIC flag so we must build both object types
+ case $host_os in
+ cygwin* | mingw* | pw32* | os2* | cegcc*)
+ pic_mode=default
+ ;;
+ esac
+ if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then
+ # non-PIC code in shared libraries is not supported
+ pic_mode=default
+ fi
+
+ # Calculate the filename of the output object if compiler does
+ # not support -o with -c
+ if test no = "$compiler_c_o"; then
+ output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext
+ lockfile=$output_obj.lock
+ else
+ output_obj=
+ need_locks=no
+ lockfile=
+ fi
+
+ # Lock this critical section if it is needed
+ # We use this script file to make the link, it avoids creating a new file
+ if test yes = "$need_locks"; then
+ until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+ func_echo "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ elif test warn = "$need_locks"; then
+ if test -f "$lockfile"; then
+ $ECHO "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support '-c' and '-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $opt_dry_run || $RM $removelist
+ exit $EXIT_FAILURE
+ fi
+ func_append removelist " $output_obj"
+ $ECHO "$srcfile" > "$lockfile"
+ fi
+
+ $opt_dry_run || $RM $removelist
+ func_append removelist " $lockfile"
+ trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
+
+ func_to_tool_file "$srcfile" func_convert_file_msys_to_w32
+ srcfile=$func_to_tool_file_result
+ func_quote_arg pretty "$srcfile"
+ qsrcfile=$func_quote_arg_result
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test yes = "$build_libtool_libs"; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ if test no != "$pic_mode"; then
+ command="$base_compile $qsrcfile $pic_flag"
+ else
+ # Don't build PIC code
+ command="$base_compile $qsrcfile"
+ fi
+
+ func_mkdir_p "$xdir$objdir"
+
+ if test -z "$output_obj"; then
+ # Place PIC objects in $objdir
+ func_append command " -o $lobj"
+ fi
+
+ func_show_eval_locale "$command" \
+ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
+
+ if test warn = "$need_locks" &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support '-c' and '-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $opt_dry_run || $RM $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed, then go on to compile the next one
+ if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+ func_show_eval '$MV "$output_obj" "$lobj"' \
+ 'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+ fi
+
+ # Allow error messages only from the first compilation.
+ if test yes = "$suppress_opt"; then
+ suppress_output=' >/dev/null 2>&1'
+ fi
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test yes = "$build_old_libs"; then
+ if test yes != "$pic_mode"; then
+ # Don't build PIC code
+ command="$base_compile $qsrcfile$pie_flag"
+ else
+ command="$base_compile $qsrcfile $pic_flag"
+ fi
+ if test yes = "$compiler_c_o"; then
+ func_append command " -o $obj"
+ fi
+
+ # Suppress compiler output if we already did a PIC compilation.
+ func_append command "$suppress_output"
+ func_show_eval_locale "$command" \
+ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
+
+ if test warn = "$need_locks" &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support '-c' and '-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $opt_dry_run || $RM $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed
+ if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+ func_show_eval '$MV "$output_obj" "$obj"' \
+ 'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+ fi
+ fi
+
+ $opt_dry_run || {
+ func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
+
+ # Unlock the critical section if it was locked
+ if test no != "$need_locks"; then
+ removelist=$lockfile
+ $RM "$lockfile"
+ fi
+ }
+
+ exit $EXIT_SUCCESS
+}
+
+$opt_help || {
+ test compile = "$opt_mode" && func_mode_compile ${1+"$@"}
+}
+
+func_mode_help ()
+{
+ # We need to display help for each of the modes.
+ case $opt_mode in
+ "")
+ # Generic help is extracted from the usage comments
+ # at the start of this file.
+ func_help
+ ;;
+
+ clean)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+ compile)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+ -o OUTPUT-FILE set the output file name to OUTPUT-FILE
+ -no-suppress do not suppress compiler output for multiple passes
+ -prefer-pic try to build PIC objects only
+ -prefer-non-pic try to build non-PIC objects only
+ -shared do not build a '.o' file suitable for static linking
+ -static only build a '.o' file suitable for static linking
+ -Wc,FLAG
+ -Xcompiler FLAG pass FLAG directly to the compiler
+
+COMPILE-COMMAND is a command to be used in creating a 'standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix '.c' with the
+library object suffix, '.lo'."
+ ;;
+
+ execute)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+ -dlopen FILE add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to '-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+ ;;
+
+ finish)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges. Use
+the '--dry-run' option if you just want to see what would be executed."
+ ;;
+
+ install)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command. The first component should be
+either the 'install' or 'cp' program.
+
+The following components of INSTALL-COMMAND are treated specially:
+
+ -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+ ;;
+
+ link)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+ -all-static do not do any dynamic linking at all
+ -avoid-version do not add a version suffix if possible
+ -bindir BINDIR specify path to binaries directory (for systems where
+ libraries must be found in the PATH setting at runtime)
+ -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime
+ -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
+ -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+ -export-symbols SYMFILE
+ try to export only the symbols listed in SYMFILE
+ -export-symbols-regex REGEX
+ try to export only the symbols matching REGEX
+ -LLIBDIR search LIBDIR for required installed libraries
+ -lNAME OUTPUT-FILE requires the installed library libNAME
+ -module build a library that can dlopened
+ -no-fast-install disable the fast-install mode
+ -no-install link a not-installable executable
+ -no-undefined declare that a library does not refer to external symbols
+ -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
+ -objectlist FILE use a list of object files found in FILE to specify objects
+ -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes)
+ -precious-files-regex REGEX
+ don't remove output files matching REGEX
+ -release RELEASE specify package release information
+ -rpath LIBDIR the created library will eventually be installed in LIBDIR
+ -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
+ -shared only do dynamic linking of libtool libraries
+ -shrext SUFFIX override the standard shared library file extension
+ -static do not do any dynamic linking of uninstalled libtool libraries
+ -static-libtool-libs
+ do not do any dynamic linking of libtool libraries
+ -version-info CURRENT[:REVISION[:AGE]]
+ specify library version info [each variable defaults to 0]
+ -weak LIBNAME declare that the target provides the LIBNAME interface
+ -Wc,FLAG
+ -Xcompiler FLAG pass linker-specific FLAG directly to the compiler
+ -Wa,FLAG
+ -Xassembler FLAG pass linker-specific FLAG directly to the assembler
+ -Wl,FLAG
+ -Xlinker FLAG pass linker-specific FLAG directly to the linker
+ -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC)
+
+All other options (arguments beginning with '-') are ignored.
+
+Every other argument is treated as a filename. Files ending in '.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in '.la', then a libtool library is created,
+only library objects ('.lo' files) may be specified, and '-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created
+using 'ar' and 'ranlib', or on Windows using 'lib'.
+
+If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file
+is created, otherwise an executable program is created."
+ ;;
+
+ uninstall)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+ *)
+ func_fatal_help "invalid operation mode '$opt_mode'"
+ ;;
+ esac
+
+ echo
+ $ECHO "Try '$progname --help' for more information about other modes."
+}
+
+# Now that we've collected a possible --mode arg, show help if necessary
+if $opt_help; then
+ if test : = "$opt_help"; then
+ func_mode_help
+ else
+ {
+ func_help noexit
+ for opt_mode in compile link execute install finish uninstall clean; do
+ func_mode_help
+ done
+ } | $SED -n '1p; 2,$s/^Usage:/ or: /p'
+ {
+ func_help noexit
+ for opt_mode in compile link execute install finish uninstall clean; do
+ echo
+ func_mode_help
+ done
+ } |
+ $SED '1d
+ /^When reporting/,/^Report/{
+ H
+ d
+ }
+ $x
+ /information about other modes/d
+ /more detailed .*MODE/d
+ s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/'
+ fi
+ exit $?
+fi
+
+
+# func_mode_execute arg...
+func_mode_execute ()
+{
+ $debug_cmd
+
+ # The first argument is the command name.
+ cmd=$nonopt
+ test -z "$cmd" && \
+ func_fatal_help "you must specify a COMMAND"
+
+ # Handle -dlopen flags immediately.
+ for file in $opt_dlopen; do
+ test -f "$file" \
+ || func_fatal_help "'$file' is not a file"
+
+ dir=
+ case $file in
+ *.la)
+ func_resolve_sysroot "$file"
+ file=$func_resolve_sysroot_result
+
+ # Check to see that this really is a libtool archive.
+ func_lalib_unsafe_p "$file" \
+ || func_fatal_help "'$lib' is not a valid libtool archive"
+
+ # Read the libtool library.
+ dlname=
+ library_names=
+ func_source "$file"
+
+ # Skip this library if it cannot be dlopened.
+ if test -z "$dlname"; then
+ # Warn if it was a shared library.
+ test -n "$library_names" && \
+ func_warning "'$file' was not linked with '-export-dynamic'"
+ continue
+ fi
+
+ func_dirname "$file" "" "."
+ dir=$func_dirname_result
+
+ if test -f "$dir/$objdir/$dlname"; then
+ func_append dir "/$objdir"
+ else
+ if test ! -f "$dir/$dlname"; then
+ func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'"
+ fi
+ fi
+ ;;
+
+ *.lo)
+ # Just add the directory containing the .lo file.
+ func_dirname "$file" "" "."
+ dir=$func_dirname_result
+ ;;
+
+ *)
+ func_warning "'-dlopen' is ignored for non-libtool libraries and objects"
+ continue
+ ;;
+ esac
+
+ # Get the absolute pathname.
+ absdir=`cd "$dir" && pwd`
+ test -n "$absdir" && dir=$absdir
+
+ # Now add the directory to shlibpath_var.
+ if eval "test -z \"\$$shlibpath_var\""; then
+ eval "$shlibpath_var=\"\$dir\""
+ else
+ eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+ fi
+ done
+
+ # This variable tells wrapper scripts just to set shlibpath_var
+ # rather than running their programs.
+ libtool_execute_magic=$magic
+
+ # Check if any of the arguments is a wrapper script.
+ args=
+ for file
+ do
+ case $file in
+ -* | *.la | *.lo ) ;;
+ *)
+ # Do a test to see if this is really a libtool program.
+ if func_ltwrapper_script_p "$file"; then
+ func_source "$file"
+ # Transform arg to wrapped name.
+ file=$progdir/$program
+ elif func_ltwrapper_executable_p "$file"; then
+ func_ltwrapper_scriptname "$file"
+ func_source "$func_ltwrapper_scriptname_result"
+ # Transform arg to wrapped name.
+ file=$progdir/$program
+ fi
+ ;;
+ esac
+ # Quote arguments (to preserve shell metacharacters).
+ func_append_quoted args "$file"
+ done
+
+ if $opt_dry_run; then
+ # Display what would be done.
+ if test -n "$shlibpath_var"; then
+ eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
+ echo "export $shlibpath_var"
+ fi
+ $ECHO "$cmd$args"
+ exit $EXIT_SUCCESS
+ else
+ if test -n "$shlibpath_var"; then
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
+ fi
+
+ # Restore saved environment variables
+ for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+ do
+ eval "if test \"\${save_$lt_var+set}\" = set; then
+ $lt_var=\$save_$lt_var; export $lt_var
+ else
+ $lt_unset $lt_var
+ fi"
+ done
+
+ # Now prepare to actually exec the command.
+ exec_cmd=\$cmd$args
+ fi
+}
+
+test execute = "$opt_mode" && func_mode_execute ${1+"$@"}
+
+
+# func_mode_finish arg...
+func_mode_finish ()
+{
+ $debug_cmd
+
+ libs=
+ libdirs=
+ admincmds=
+
+ for opt in "$nonopt" ${1+"$@"}
+ do
+ if test -d "$opt"; then
+ func_append libdirs " $opt"
+
+ elif test -f "$opt"; then
+ if func_lalib_unsafe_p "$opt"; then
+ func_append libs " $opt"
+ else
+ func_warning "'$opt' is not a valid libtool archive"
+ fi
+
+ else
+ func_fatal_error "invalid argument '$opt'"
+ fi
+ done
+
+ if test -n "$libs"; then
+ if test -n "$lt_sysroot"; then
+ sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"`
+ sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;"
+ else
+ sysroot_cmd=
+ fi
+
+ # Remove sysroot references
+ if $opt_dry_run; then
+ for lib in $libs; do
+ echo "removing references to $lt_sysroot and '=' prefixes from $lib"
+ done
+ else
+ tmpdir=`func_mktempdir`
+ for lib in $libs; do
+ $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \
+ > $tmpdir/tmp-la
+ mv -f $tmpdir/tmp-la $lib
+ done
+ ${RM}r "$tmpdir"
+ fi
+ fi
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ for libdir in $libdirs; do
+ if test -n "$finish_cmds"; then
+ # Do each command in the finish commands.
+ func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
+'"$cmd"'"'
+ fi
+ if test -n "$finish_eval"; then
+ # Do the single finish_eval.
+ eval cmds=\"$finish_eval\"
+ $opt_dry_run || eval "$cmds" || func_append admincmds "
+ $cmds"
+ fi
+ done
+ fi
+
+ # Exit here if they wanted silent mode.
+ $opt_quiet && exit $EXIT_SUCCESS
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ echo "----------------------------------------------------------------------"
+ echo "Libraries have been installed in:"
+ for libdir in $libdirs; do
+ $ECHO " $libdir"
+ done
+ echo
+ echo "If you ever happen to want to link against installed libraries"
+ echo "in a given directory, LIBDIR, you must either use libtool, and"
+ echo "specify the full pathname of the library, or use the '-LLIBDIR'"
+ echo "flag during linking and do at least one of the following:"
+ if test -n "$shlibpath_var"; then
+ echo " - add LIBDIR to the '$shlibpath_var' environment variable"
+ echo " during execution"
+ fi
+ if test -n "$runpath_var"; then
+ echo " - add LIBDIR to the '$runpath_var' environment variable"
+ echo " during linking"
+ fi
+ if test -n "$hardcode_libdir_flag_spec"; then
+ libdir=LIBDIR
+ eval flag=\"$hardcode_libdir_flag_spec\"
+
+ $ECHO " - use the '$flag' linker flag"
+ fi
+ if test -n "$admincmds"; then
+ $ECHO " - have your system administrator run these commands:$admincmds"
+ fi
+ if test -f /etc/ld.so.conf; then
+ echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'"
+ fi
+ echo
+
+ echo "See any operating system documentation about shared libraries for"
+ case $host in
+ solaris2.[6789]|solaris2.1[0-9])
+ echo "more information, such as the ld(1), crle(1) and ld.so(8) manual"
+ echo "pages."
+ ;;
+ *)
+ echo "more information, such as the ld(1) and ld.so(8) manual pages."
+ ;;
+ esac
+ echo "----------------------------------------------------------------------"
+ fi
+ exit $EXIT_SUCCESS
+}
+
+test finish = "$opt_mode" && func_mode_finish ${1+"$@"}
+
+
+# func_mode_install arg...
+func_mode_install ()
+{
+ $debug_cmd
+
+ # There may be an optional sh(1) argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" ||
+ # Allow the use of GNU shtool's install command.
+ case $nonopt in *shtool*) :;; *) false;; esac
+ then
+ # Aesthetically quote it.
+ func_quote_arg pretty "$nonopt"
+ install_prog="$func_quote_arg_result "
+ arg=$1
+ shift
+ else
+ install_prog=
+ arg=$nonopt
+ fi
+
+ # The real first argument should be the name of the installation program.
+ # Aesthetically quote it.
+ func_quote_arg pretty "$arg"
+ func_append install_prog "$func_quote_arg_result"
+ install_shared_prog=$install_prog
+ case " $install_prog " in
+ *[\\\ /]cp\ *) install_cp=: ;;
+ *) install_cp=false ;;
+ esac
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=false
+ stripme=
+ no_mode=:
+ for arg
+ do
+ arg2=
+ if test -n "$dest"; then
+ func_append files " $dest"
+ dest=$arg
+ continue
+ fi
+
+ case $arg in
+ -d) isdir=: ;;
+ -f)
+ if $install_cp; then :; else
+ prev=$arg
+ fi
+ ;;
+ -g | -m | -o)
+ prev=$arg
+ ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*)
+ ;;
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ if test X-m = "X$prev" && test -n "$install_override_mode"; then
+ arg2=$install_override_mode
+ no_mode=false
+ fi
+ prev=
+ else
+ dest=$arg
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ func_quote_arg pretty "$arg"
+ func_append install_prog " $func_quote_arg_result"
+ if test -n "$arg2"; then
+ func_quote_arg pretty "$arg2"
+ fi
+ func_append install_shared_prog " $func_quote_arg_result"
+ done
+
+ test -z "$install_prog" && \
+ func_fatal_help "you must specify an install program"
+
+ test -n "$prev" && \
+ func_fatal_help "the '$prev' option requires an argument"
+
+ if test -n "$install_override_mode" && $no_mode; then
+ if $install_cp; then :; else
+ func_quote_arg pretty "$install_override_mode"
+ func_append install_shared_prog " -m $func_quote_arg_result"
+ fi
+ fi
+
+ if test -z "$files"; then
+ if test -z "$dest"; then
+ func_fatal_help "no file or destination specified"
+ else
+ func_fatal_help "you must specify a destination"
+ fi
+ fi
+
+ # Strip any trailing slash from the destination.
+ func_stripname '' '/' "$dest"
+ dest=$func_stripname_result
+
+ # Check to see that the destination is a directory.
+ test -d "$dest" && isdir=:
+ if $isdir; then
+ destdir=$dest
+ destname=
+ else
+ func_dirname_and_basename "$dest" "" "."
+ destdir=$func_dirname_result
+ destname=$func_basename_result
+
+ # Not a directory, so check to see that there is only one file specified.
+ set dummy $files; shift
+ test "$#" -gt 1 && \
+ func_fatal_help "'$dest' is not a directory"
+ fi
+ case $destdir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ for file in $files; do
+ case $file in
+ *.lo) ;;
+ *)
+ func_fatal_help "'$destdir' must be an absolute directory name"
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic=$magic
+
+ staticlibs=
+ future_libdirs=
+ current_libdirs=
+ for file in $files; do
+
+ # Do each installation.
+ case $file in
+ *.$libext)
+ # Do the static libraries later.
+ func_append staticlibs " $file"
+ ;;
+
+ *.la)
+ func_resolve_sysroot "$file"
+ file=$func_resolve_sysroot_result
+
+ # Check to see that this really is a libtool archive.
+ func_lalib_unsafe_p "$file" \
+ || func_fatal_help "'$file' is not a valid libtool archive"
+
+ library_names=
+ old_library=
+ relink_command=
+ func_source "$file"
+
+ # Add the libdir to current_libdirs if it is the destination.
+ if test "X$destdir" = "X$libdir"; then
+ case "$current_libdirs " in
+ *" $libdir "*) ;;
+ *) func_append current_libdirs " $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) func_append future_libdirs " $libdir" ;;
+ esac
+ fi
+
+ func_dirname "$file" "/" ""
+ dir=$func_dirname_result
+ func_append dir "$objdir"
+
+ if test -n "$relink_command"; then
+ # Determine the prefix the user has applied to our future dir.
+ inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"`
+
+ # Don't allow the user to place us outside of our expected
+ # location b/c this prevents finding dependent libraries that
+ # are installed to the same prefix.
+ # At present, this check doesn't affect windows .dll's that
+ # are installed into $libdir/../bin (currently, that works fine)
+ # but it's something to keep an eye on.
+ test "$inst_prefix_dir" = "$destdir" && \
+ func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir"
+
+ if test -n "$inst_prefix_dir"; then
+ # Stick the inst_prefix_dir data into the link command.
+ relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+ else
+ relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+ fi
+
+ func_warning "relinking '$file'"
+ func_show_eval "$relink_command" \
+ 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"'
+ fi
+
+ # See the names of the shared library.
+ set dummy $library_names; shift
+ if test -n "$1"; then
+ realname=$1
+ shift
+
+ srcname=$realname
+ test -n "$relink_command" && srcname=${realname}T
+
+ # Install the shared library and build the symlinks.
+ func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \
+ 'exit $?'
+ tstripme=$stripme
+ case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ case $realname in
+ *.dll.a)
+ tstripme=
+ ;;
+ esac
+ ;;
+ os2*)
+ case $realname in
+ *_dll.a)
+ tstripme=
+ ;;
+ esac
+ ;;
+ esac
+ if test -n "$tstripme" && test -n "$striplib"; then
+ func_show_eval "$striplib $destdir/$realname" 'exit $?'
+ fi
+
+ if test "$#" -gt 0; then
+ # Delete the old symlinks, and create new ones.
+ # Try 'ln -sf' first, because the 'ln' binary might depend on
+ # the symlink we replace! Solaris /bin/ln does not understand -f,
+ # so we also need to try rm && ln -s.
+ for linkname
+ do
+ test "$linkname" != "$realname" \
+ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
+ done
+ fi
+
+ # Do each command in the postinstall commands.
+ lib=$destdir/$realname
+ func_execute_cmds "$postinstall_cmds" 'exit $?'
+ fi
+
+ # Install the pseudo-library for information purposes.
+ func_basename "$file"
+ name=$func_basename_result
+ instname=$dir/${name}i
+ func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
+
+ # Maybe install the static library, too.
+ test -n "$old_library" && func_append staticlibs " $dir/$old_library"
+ ;;
+
+ *.lo)
+ # Install (i.e. copy) a libtool object.
+
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile=$destdir/$destname
+ else
+ func_basename "$file"
+ destfile=$func_basename_result
+ destfile=$destdir/$destfile
+ fi
+
+ # Deduce the name of the destination old-style object file.
+ case $destfile in
+ *.lo)
+ func_lo2o "$destfile"
+ staticdest=$func_lo2o_result
+ ;;
+ *.$objext)
+ staticdest=$destfile
+ destfile=
+ ;;
+ *)
+ func_fatal_help "cannot copy a libtool object to '$destfile'"
+ ;;
+ esac
+
+ # Install the libtool object if requested.
+ test -n "$destfile" && \
+ func_show_eval "$install_prog $file $destfile" 'exit $?'
+
+ # Install the old object if enabled.
+ if test yes = "$build_old_libs"; then
+ # Deduce the name of the old-style object file.
+ func_lo2o "$file"
+ staticobj=$func_lo2o_result
+ func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
+ fi
+ exit $EXIT_SUCCESS
+ ;;
+
+ *)
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile=$destdir/$destname
+ else
+ func_basename "$file"
+ destfile=$func_basename_result
+ destfile=$destdir/$destfile
+ fi
+
+ # If the file is missing, and there is a .exe on the end, strip it
+ # because it is most likely a libtool script we actually want to
+ # install
+ stripped_ext=
+ case $file in
+ *.exe)
+ if test ! -f "$file"; then
+ func_stripname '' '.exe' "$file"
+ file=$func_stripname_result
+ stripped_ext=.exe
+ fi
+ ;;
+ esac
+
+ # Do a test to see if this is really a libtool program.
+ case $host in
+ *cygwin* | *mingw*)
+ if func_ltwrapper_executable_p "$file"; then
+ func_ltwrapper_scriptname "$file"
+ wrapper=$func_ltwrapper_scriptname_result
+ else
+ func_stripname '' '.exe' "$file"
+ wrapper=$func_stripname_result
+ fi
+ ;;
+ *)
+ wrapper=$file
+ ;;
+ esac
+ if func_ltwrapper_script_p "$wrapper"; then
+ notinst_deplibs=
+ relink_command=
+
+ func_source "$wrapper"
+
+ # Check the variables that should have been set.
+ test -z "$generated_by_libtool_version" && \
+ func_fatal_error "invalid libtool wrapper script '$wrapper'"
+
+ finalize=:
+ for lib in $notinst_deplibs; do
+ # Check to see that each library is installed.
+ libdir=
+ if test -f "$lib"; then
+ func_source "$lib"
+ fi
+ libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'`
+ if test -n "$libdir" && test ! -f "$libfile"; then
+ func_warning "'$lib' has not been installed in '$libdir'"
+ finalize=false
+ fi
+ done
+
+ relink_command=
+ func_source "$wrapper"
+
+ outputname=
+ if test no = "$fast_install" && test -n "$relink_command"; then
+ $opt_dry_run || {
+ if $finalize; then
+ tmpdir=`func_mktempdir`
+ func_basename "$file$stripped_ext"
+ file=$func_basename_result
+ outputname=$tmpdir/$file
+ # Replace the output file specification.
+ relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'`
+
+ $opt_quiet || {
+ func_quote_arg expand,pretty "$relink_command"
+ eval "func_echo $func_quote_arg_result"
+ }
+ if eval "$relink_command"; then :
+ else
+ func_error "error: relink '$file' with the above command before installing it"
+ $opt_dry_run || ${RM}r "$tmpdir"
+ continue
+ fi
+ file=$outputname
+ else
+ func_warning "cannot relink '$file'"
+ fi
+ }
+ else
+ # Install the binary that we compiled earlier.
+ file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"`
+ fi
+ fi
+
+ # remove .exe since cygwin /usr/bin/install will append another
+ # one anyway
+ case $install_prog,$host in
+ */usr/bin/install*,*cygwin*)
+ case $file:$destfile in
+ *.exe:*.exe)
+ # this is ok
+ ;;
+ *.exe:*)
+ destfile=$destfile.exe
+ ;;
+ *:*.exe)
+ func_stripname '' '.exe' "$destfile"
+ destfile=$func_stripname_result
+ ;;
+ esac
+ ;;
+ esac
+ func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
+ $opt_dry_run || if test -n "$outputname"; then
+ ${RM}r "$tmpdir"
+ fi
+ ;;
+ esac
+ done
+
+ for file in $staticlibs; do
+ func_basename "$file"
+ name=$func_basename_result
+
+ # Set up the ranlib parameters.
+ oldlib=$destdir/$name
+ func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
+ tool_oldlib=$func_to_tool_file_result
+
+ func_show_eval "$install_prog \$file \$oldlib" 'exit $?'
+
+ if test -n "$stripme" && test -n "$old_striplib"; then
+ func_show_eval "$old_striplib $tool_oldlib" 'exit $?'
+ fi
+
+ # Do each command in the postinstall commands.
+ func_execute_cmds "$old_postinstall_cmds" 'exit $?'
+ done
+
+ test -n "$future_libdirs" && \
+ func_warning "remember to run '$progname --finish$future_libdirs'"
+
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ $opt_dry_run && current_libdirs=" -n$current_libdirs"
+ exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs'
+ else
+ exit $EXIT_SUCCESS
+ fi
+}
+
+test install = "$opt_mode" && func_mode_install ${1+"$@"}
+
+
+# func_generate_dlsyms outputname originator pic_p
+# Extract symbols from dlprefiles and create ${outputname}S.o with
+# a dlpreopen symbol table.
+func_generate_dlsyms ()
+{
+ $debug_cmd
+
+ my_outputname=$1
+ my_originator=$2
+ my_pic_p=${3-false}
+ my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'`
+ my_dlsyms=
+
+ if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
+ if test -n "$NM" && test -n "$global_symbol_pipe"; then
+ my_dlsyms=${my_outputname}S.c
+ else
+ func_error "not configured to extract global symbols from dlpreopened files"
+ fi
+ fi
+
+ if test -n "$my_dlsyms"; then
+ case $my_dlsyms in
+ "") ;;
+ *.c)
+ # Discover the nlist of each of the dlfiles.
+ nlist=$output_objdir/$my_outputname.nm
+
+ func_show_eval "$RM $nlist ${nlist}S ${nlist}T"
+
+ # Parse the name list into a source file.
+ func_verbose "creating $output_objdir/$my_dlsyms"
+
+ $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
+/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */
+/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4))
+#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
+#endif
+
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */
+#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
+/* DATA imports from DLLs on WIN32 can't be const, because runtime
+ relocations are performed -- see ld's documentation on pseudo-relocs. */
+# define LT_DLSYM_CONST
+#elif defined __osf__
+/* This system does not cope well with relocations in const data. */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
+#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0)
+
+/* External symbol declarations for the compiler. */\
+"
+
+ if test yes = "$dlself"; then
+ func_verbose "generating symbol list for '$output'"
+
+ $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
+
+ # Add our own program objects to the symbol list.
+ progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+ for progfile in $progfiles; do
+ func_to_tool_file "$progfile" func_convert_file_msys_to_w32
+ func_verbose "extracting global C symbols from '$func_to_tool_file_result'"
+ $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -n "$exclude_expsyms"; then
+ $opt_dry_run || {
+ eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+ eval '$MV "$nlist"T "$nlist"'
+ }
+ fi
+
+ if test -n "$export_symbols_regex"; then
+ $opt_dry_run || {
+ eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+ eval '$MV "$nlist"T "$nlist"'
+ }
+ fi
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ export_symbols=$output_objdir/$outputname.exp
+ $opt_dry_run || {
+ $RM $export_symbols
+ eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ case $host in
+ *cygwin* | *mingw* | *cegcc* )
+ eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
+ }
+ else
+ $opt_dry_run || {
+ eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+ eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+ eval '$MV "$nlist"T "$nlist"'
+ case $host in
+ *cygwin* | *mingw* | *cegcc* )
+ eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
+ }
+ fi
+ fi
+
+ for dlprefile in $dlprefiles; do
+ func_verbose "extracting global C symbols from '$dlprefile'"
+ func_basename "$dlprefile"
+ name=$func_basename_result
+ case $host in
+ *cygwin* | *mingw* | *cegcc* )
+ # if an import library, we need to obtain dlname
+ if func_win32_import_lib_p "$dlprefile"; then
+ func_tr_sh "$dlprefile"
+ eval "curr_lafile=\$libfile_$func_tr_sh_result"
+ dlprefile_dlbasename=
+ if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then
+ # Use subshell, to avoid clobbering current variable values
+ dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"`
+ if test -n "$dlprefile_dlname"; then
+ func_basename "$dlprefile_dlname"
+ dlprefile_dlbasename=$func_basename_result
+ else
+ # no lafile. user explicitly requested -dlpreopen <import library>.
+ $sharedlib_from_linklib_cmd "$dlprefile"
+ dlprefile_dlbasename=$sharedlib_from_linklib_result
+ fi
+ fi
+ $opt_dry_run || {
+ if test -n "$dlprefile_dlbasename"; then
+ eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"'
+ else
+ func_warning "Could not compute DLL name from $name"
+ eval '$ECHO ": $name " >> "$nlist"'
+ fi
+ func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+ eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe |
+ $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'"
+ }
+ else # not an import lib
+ $opt_dry_run || {
+ eval '$ECHO ": $name " >> "$nlist"'
+ func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+ eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+ }
+ fi
+ ;;
+ *)
+ $opt_dry_run || {
+ eval '$ECHO ": $name " >> "$nlist"'
+ func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+ eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+ }
+ ;;
+ esac
+ done
+
+ $opt_dry_run || {
+ # Make sure we have at least an empty file.
+ test -f "$nlist" || : > "$nlist"
+
+ if test -n "$exclude_expsyms"; then
+ $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+ $MV "$nlist"T "$nlist"
+ fi
+
+ # Try sorting and uniquifying the output.
+ if $GREP -v "^: " < "$nlist" |
+ if sort -k 3 </dev/null >/dev/null 2>&1; then
+ sort -k 3
+ else
+ sort +2
+ fi |
+ uniq > "$nlist"S; then
+ :
+ else
+ $GREP -v "^: " < "$nlist" > "$nlist"S
+ fi
+
+ if test -f "$nlist"S; then
+ eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
+ else
+ echo '/* NONE */' >> "$output_objdir/$my_dlsyms"
+ fi
+
+ func_show_eval '$RM "${nlist}I"'
+ if test -n "$global_symbol_to_import"; then
+ eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I'
+ fi
+
+ echo >> "$output_objdir/$my_dlsyms" "\
+
+/* The mapping between symbol names and symbols. */
+typedef struct {
+ const char *name;
+ void *address;
+} lt_dlsymlist;
+extern LT_DLSYM_CONST lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[];\
+"
+
+ if test -s "$nlist"I; then
+ echo >> "$output_objdir/$my_dlsyms" "\
+static void lt_syminit(void)
+{
+ LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols;
+ for (; symbol->name; ++symbol)
+ {"
+ $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms"
+ echo >> "$output_objdir/$my_dlsyms" "\
+ }
+}"
+ fi
+ echo >> "$output_objdir/$my_dlsyms" "\
+LT_DLSYM_CONST lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[] =
+{ {\"$my_originator\", (void *) 0},"
+
+ if test -s "$nlist"I; then
+ echo >> "$output_objdir/$my_dlsyms" "\
+ {\"@INIT@\", (void *) &lt_syminit},"
+ fi
+
+ case $need_lib_prefix in
+ no)
+ eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
+ ;;
+ *)
+ eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
+ ;;
+ esac
+ echo >> "$output_objdir/$my_dlsyms" "\
+ {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt_${my_prefix}_LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+ } # !$opt_dry_run
+
+ pic_flag_for_symtable=
+ case "$compile_command " in
+ *" -static "*) ;;
+ *)
+ case $host in
+ # compiling the symbol table file with pic_flag works around
+ # a FreeBSD bug that causes programs to crash when -lm is
+ # linked before any other PIC object. But we must not use
+ # pic_flag when linking with -static. The problem exists in
+ # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+ *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+ pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
+ *-*-hpux*)
+ pic_flag_for_symtable=" $pic_flag" ;;
+ *)
+ $my_pic_p && pic_flag_for_symtable=" $pic_flag"
+ ;;
+ esac
+ ;;
+ esac
+ symtab_cflags=
+ for arg in $LTCFLAGS; do
+ case $arg in
+ -pie | -fpie | -fPIE) ;;
+ *) func_append symtab_cflags " $arg" ;;
+ esac
+ done
+
+ # Now compile the dynamic symbol file.
+ func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
+
+ # Clean up the generated files.
+ func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"'
+
+ # Transform the symbol file into the correct name.
+ symfileobj=$output_objdir/${my_outputname}S.$objext
+ case $host in
+ *cygwin* | *mingw* | *cegcc* )
+ if test -f "$output_objdir/$my_outputname.def"; then
+ compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+ finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+ else
+ compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+ finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+ fi
+ ;;
+ *)
+ compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+ finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+ ;;
+ esac
+ ;;
+ *)
+ func_fatal_error "unknown suffix for '$my_dlsyms'"
+ ;;
+ esac
+ else
+ # We keep going just in case the user didn't refer to
+ # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
+ # really was required.
+
+ # Nullify the symbol file.
+ compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"`
+ finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"`
+ fi
+}
+
+# func_cygming_gnu_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is a GNU/binutils-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_gnu_implib_p ()
+{
+ $debug_cmd
+
+ func_to_tool_file "$1" func_convert_file_msys_to_w32
+ func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'`
+ test -n "$func_cygming_gnu_implib_tmp"
+}
+
+# func_cygming_ms_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is an MS-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_ms_implib_p ()
+{
+ $debug_cmd
+
+ func_to_tool_file "$1" func_convert_file_msys_to_w32
+ func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'`
+ test -n "$func_cygming_ms_implib_tmp"
+}
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+# Despite the name, also deal with 64 bit binaries.
+func_win32_libid ()
+{
+ $debug_cmd
+
+ win32_libid_type=unknown
+ win32_fileres=`file -L $1 2>/dev/null`
+ case $win32_fileres in
+ *ar\ archive\ import\ library*) # definitely import
+ win32_libid_type="x86 archive import"
+ ;;
+ *ar\ archive*) # could be an import, or static
+ # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD.
+ if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
+ $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then
+ case $nm_interface in
+ "MS dumpbin")
+ if func_cygming_ms_implib_p "$1" ||
+ func_cygming_gnu_implib_p "$1"
+ then
+ win32_nmres=import
+ else
+ win32_nmres=
+ fi
+ ;;
+ *)
+ func_to_tool_file "$1" func_convert_file_msys_to_w32
+ win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" |
+ $SED -n -e '
+ 1,100{
+ / I /{
+ s|.*|import|
+ p
+ q
+ }
+ }'`
+ ;;
+ esac
+ case $win32_nmres in
+ import*) win32_libid_type="x86 archive import";;
+ *) win32_libid_type="x86 archive static";;
+ esac
+ fi
+ ;;
+ *DLL*)
+ win32_libid_type="x86 DLL"
+ ;;
+ *executable*) # but shell scripts are "executable" too...
+ case $win32_fileres in
+ *MS\ Windows\ PE\ Intel*)
+ win32_libid_type="x86 DLL"
+ ;;
+ esac
+ ;;
+ esac
+ $ECHO "$win32_libid_type"
+}
+
+# func_cygming_dll_for_implib ARG
+#
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+# Invoked by eval'ing the libtool variable
+# $sharedlib_from_linklib_cmd
+# Result is available in the variable
+# $sharedlib_from_linklib_result
+func_cygming_dll_for_implib ()
+{
+ $debug_cmd
+
+ sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"`
+}
+
+# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs
+#
+# The is the core of a fallback implementation of a
+# platform-specific function to extract the name of the
+# DLL associated with the specified import library LIBNAME.
+#
+# SECTION_NAME is either .idata$6 or .idata$7, depending
+# on the platform and compiler that created the implib.
+#
+# Echos the name of the DLL associated with the
+# specified import library.
+func_cygming_dll_for_implib_fallback_core ()
+{
+ $debug_cmd
+
+ match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"`
+ $OBJDUMP -s --section "$1" "$2" 2>/dev/null |
+ $SED '/^Contents of section '"$match_literal"':/{
+ # Place marker at beginning of archive member dllname section
+ s/.*/====MARK====/
+ p
+ d
+ }
+ # These lines can sometimes be longer than 43 characters, but
+ # are always uninteresting
+ /:[ ]*file format pe[i]\{,1\}-/d
+ /^In archive [^:]*:/d
+ # Ensure marker is printed
+ /^====MARK====/p
+ # Remove all lines with less than 43 characters
+ /^.\{43\}/!d
+ # From remaining lines, remove first 43 characters
+ s/^.\{43\}//' |
+ $SED -n '
+ # Join marker and all lines until next marker into a single line
+ /^====MARK====/ b para
+ H
+ $ b para
+ b
+ :para
+ x
+ s/\n//g
+ # Remove the marker
+ s/^====MARK====//
+ # Remove trailing dots and whitespace
+ s/[\. \t]*$//
+ # Print
+ /./p' |
+ # we now have a list, one entry per line, of the stringified
+ # contents of the appropriate section of all members of the
+ # archive that possess that section. Heuristic: eliminate
+ # all those that have a first or second character that is
+ # a '.' (that is, objdump's representation of an unprintable
+ # character.) This should work for all archives with less than
+ # 0x302f exports -- but will fail for DLLs whose name actually
+ # begins with a literal '.' or a single character followed by
+ # a '.'.
+ #
+ # Of those that remain, print the first one.
+ $SED -e '/^\./d;/^.\./d;q'
+}
+
+# func_cygming_dll_for_implib_fallback ARG
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+#
+# This fallback implementation is for use when $DLLTOOL
+# does not support the --identify-strict option.
+# Invoked by eval'ing the libtool variable
+# $sharedlib_from_linklib_cmd
+# Result is available in the variable
+# $sharedlib_from_linklib_result
+func_cygming_dll_for_implib_fallback ()
+{
+ $debug_cmd
+
+ if func_cygming_gnu_implib_p "$1"; then
+ # binutils import library
+ sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"`
+ elif func_cygming_ms_implib_p "$1"; then
+ # ms-generated import library
+ sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"`
+ else
+ # unknown
+ sharedlib_from_linklib_result=
+ fi
+}
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+ $debug_cmd
+
+ f_ex_an_ar_dir=$1; shift
+ f_ex_an_ar_oldlib=$1
+ if test yes = "$lock_old_archive_extraction"; then
+ lockfile=$f_ex_an_ar_oldlib.lock
+ until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+ func_echo "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ fi
+ func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \
+ 'stat=$?; rm -f "$lockfile"; exit $stat'
+ if test yes = "$lock_old_archive_extraction"; then
+ $opt_dry_run || rm -f "$lockfile"
+ fi
+ if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
+ fi
+}
+
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+ $debug_cmd
+
+ my_gentop=$1; shift
+ my_oldlibs=${1+"$@"}
+ my_oldobjs=
+ my_xlib=
+ my_xabs=
+ my_xdir=
+
+ for my_xlib in $my_oldlibs; do
+ # Extract the objects.
+ case $my_xlib in
+ [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;;
+ *) my_xabs=`pwd`"/$my_xlib" ;;
+ esac
+ func_basename "$my_xlib"
+ my_xlib=$func_basename_result
+ my_xlib_u=$my_xlib
+ while :; do
+ case " $extracted_archives " in
+ *" $my_xlib_u "*)
+ func_arith $extracted_serial + 1
+ extracted_serial=$func_arith_result
+ my_xlib_u=lt$extracted_serial-$my_xlib ;;
+ *) break ;;
+ esac
+ done
+ extracted_archives="$extracted_archives $my_xlib_u"
+ my_xdir=$my_gentop/$my_xlib_u
+
+ func_mkdir_p "$my_xdir"
+
+ case $host in
+ *-darwin*)
+ func_verbose "Extracting $my_xabs"
+ # Do not bother doing anything if just a dry run
+ $opt_dry_run || {
+ darwin_orig_dir=`pwd`
+ cd $my_xdir || exit $?
+ darwin_archive=$my_xabs
+ darwin_curdir=`pwd`
+ func_basename "$darwin_archive"
+ darwin_base_archive=$func_basename_result
+ darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
+ if test -n "$darwin_arches"; then
+ darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
+ darwin_arch=
+ func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
+ for darwin_arch in $darwin_arches; do
+ func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch"
+ $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive"
+ cd "unfat-$$/$darwin_base_archive-$darwin_arch"
+ func_extract_an_archive "`pwd`" "$darwin_base_archive"
+ cd "$darwin_curdir"
+ $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive"
+ done # $darwin_arches
+ ## Okay now we've a bunch of thin objects, gotta fatten them up :)
+ darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u`
+ darwin_file=
+ darwin_files=
+ for darwin_file in $darwin_filelist; do
+ darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP`
+ $LIPO -create -output "$darwin_file" $darwin_files
+ done # $darwin_filelist
+ $RM -rf unfat-$$
+ cd "$darwin_orig_dir"
+ else
+ cd $darwin_orig_dir
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ fi # $darwin_arches
+ } # !$opt_dry_run
+ ;;
+ *)
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ ;;
+ esac
+ my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP`
+ done
+
+ func_extract_archives_result=$my_oldobjs
+}
+
+
+# func_emit_wrapper [arg=no]
+#
+# Emit a libtool wrapper script on stdout.
+# Don't directly open a file because we may want to
+# incorporate the script contents within a cygwin/mingw
+# wrapper executable. Must ONLY be called from within
+# func_mode_link because it depends on a number of variables
+# set therein.
+#
+# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
+# variable will take. If 'yes', then the emitted script
+# will assume that the directory where it is stored is
+# the $objdir directory. This is a cygwin/mingw-specific
+# behavior.
+func_emit_wrapper ()
+{
+ func_emit_wrapper_arg1=${1-no}
+
+ $ECHO "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM (GNU $PACKAGE) $VERSION
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='$sed_quote_subst'
+
+# Be Bourne compatible
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+ # install mode needs the following variables:
+ generated_by_libtool_version='$macro_version'
+ notinst_deplibs='$notinst_deplibs'
+else
+ # When we are sourced in execute mode, \$file and \$ECHO are already set.
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ file=\"\$0\""
+
+ func_quote_arg pretty "$ECHO"
+ qECHO=$func_quote_arg_result
+ $ECHO "\
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+ ECHO=$qECHO
+ fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ that is used only on
+# windows platforms, and (c) all begin with the string "--lt-"
+# (application programs are unlikely to have options that match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's $0 value, followed by "$@".
+lt_option_debug=
+func_parse_lt_options ()
+{
+ lt_script_arg0=\$0
+ shift
+ for lt_opt
+ do
+ case \"\$lt_opt\" in
+ --lt-debug) lt_option_debug=1 ;;
+ --lt-dump-script)
+ lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\`
+ test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=.
+ lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\`
+ cat \"\$lt_dump_D/\$lt_dump_F\"
+ exit 0
+ ;;
+ --lt-*)
+ \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+
+ # Print the debug banner immediately:
+ if test -n \"\$lt_option_debug\"; then
+ echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2
+ fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+ lt_dump_args_N=1;
+ for lt_arg
+ do
+ \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\"
+ lt_dump_args_N=\`expr \$lt_dump_args_N + 1\`
+ done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+"
+ case $host in
+ # Backslashes separate directories on plain windows
+ *-*-mingw | *-*-os2* | *-cegcc*)
+ $ECHO "\
+ if test -n \"\$lt_option_debug\"; then
+ \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2
+ func_lt_dump_args \${1+\"\$@\"} 1>&2
+ fi
+ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+ ;;
+
+ *)
+ $ECHO "\
+ if test -n \"\$lt_option_debug\"; then
+ \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2
+ func_lt_dump_args \${1+\"\$@\"} 1>&2
+ fi
+ exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+ ;;
+ esac
+ $ECHO "\
+ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
+ exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from \$@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+ case \" \$* \" in
+ *\\ --lt-*)
+ for lt_wr_arg
+ do
+ case \$lt_wr_arg in
+ --lt-*) ;;
+ *) set x \"\$@\" \"\$lt_wr_arg\"; shift;;
+ esac
+ shift
+ done ;;
+ esac
+ func_exec_program_core \${1+\"\$@\"}
+}
+
+ # Parse options
+ func_parse_lt_options \"\$0\" \${1+\"\$@\"}
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\`
+ test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\`
+ while test -n \"\$file\"; do
+ destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\`
+
+ # If there was a directory component, then change thisdir.
+ if test \"x\$destdir\" != \"x\$file\"; then
+ case \"\$destdir\" in
+ [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+ *) thisdir=\"\$thisdir/\$destdir\" ;;
+ esac
+ fi
+
+ file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\`
+ file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\`
+ done
+
+ # Usually 'no', except on cygwin/mingw when embedded into
+ # the cwrapper.
+ WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1
+ if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
+ # special case for '.'
+ if test \"\$thisdir\" = \".\"; then
+ thisdir=\`pwd\`
+ fi
+ # remove .libs from thisdir
+ case \"\$thisdir\" in
+ *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;;
+ $objdir ) thisdir=. ;;
+ esac
+ fi
+
+ # Try to get the absolute directory name.
+ absdir=\`cd \"\$thisdir\" && pwd\`
+ test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+ if test yes = "$fast_install"; then
+ $ECHO "\
+ program=lt-'$outputname'$exeext
+ progdir=\"\$thisdir/$objdir\"
+
+ if test ! -f \"\$progdir/\$program\" ||
+ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\
+ test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+ file=\"\$\$-\$program\"
+
+ if test ! -d \"\$progdir\"; then
+ $MKDIR \"\$progdir\"
+ else
+ $RM \"\$progdir/\$file\"
+ fi"
+
+ $ECHO "\
+
+ # relink executable if necessary
+ if test -n \"\$relink_command\"; then
+ if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+ else
+ \$ECHO \"\$relink_command_output\" >&2
+ $RM \"\$progdir/\$file\"
+ exit 1
+ fi
+ fi
+
+ $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+ { $RM \"\$progdir/\$program\";
+ $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+ $RM \"\$progdir/\$file\"
+ fi"
+ else
+ $ECHO "\
+ program='$outputname'
+ progdir=\"\$thisdir/$objdir\"
+"
+ fi
+
+ $ECHO "\
+
+ if test -f \"\$progdir/\$program\"; then"
+
+ # fixup the dll searchpath if we need to.
+ #
+ # Fix the DLL searchpath if we need to. Do this before prepending
+ # to shlibpath, because on Windows, both are PATH and uninstalled
+ # libraries must come first.
+ if test -n "$dllsearchpath"; then
+ $ECHO "\
+ # Add the dll search path components to the executable PATH
+ PATH=$dllsearchpath:\$PATH
+"
+ fi
+
+ # Export our shlibpath_var if we have one.
+ if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ $ECHO "\
+ # Add our own library path to $shlibpath_var
+ $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+ # The second colon is a workaround for a bug in BeOS R4 sed
+ $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\`
+
+ export $shlibpath_var
+"
+ fi
+
+ $ECHO "\
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ # Run the actual program with our arguments.
+ func_exec_program \${1+\"\$@\"}
+ fi
+ else
+ # The program doesn't exist.
+ \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2
+ \$ECHO \"This script is just a wrapper for \$program.\" 1>&2
+ \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
+ exit 1
+ fi
+fi\
+"
+}
+
+
+# func_emit_cwrapperexe_src
+# emit the source code for a wrapper executable on stdout
+# Must ONLY be called from within func_mode_link because
+# it depends on a number of variable set therein.
+func_emit_cwrapperexe_src ()
+{
+ cat <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+ Generated by $PROGRAM (GNU $PACKAGE) $VERSION
+
+ The $output program cannot be directly executed until all the libtool
+ libraries that it depends on are installed.
+
+ This wrapper executable should never be moved out of the build directory.
+ If it is, it will not operate correctly.
+*/
+EOF
+ cat <<"EOF"
+#ifdef _MSC_VER
+# define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _MSC_VER
+# include <direct.h>
+# include <process.h>
+# include <io.h>
+#else
+# include <unistd.h>
+# include <stdint.h>
+# ifdef __CYGWIN__
+# include <io.h>
+# endif
+#endif
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0)
+
+/* declarations of non-ANSI functions */
+#if defined __MINGW32__
+# ifdef __STRICT_ANSI__
+int _putenv (const char *);
+# endif
+#elif defined __CYGWIN__
+# ifdef __STRICT_ANSI__
+char *realpath (const char *, char *);
+int putenv (char *);
+int setenv (const char *, const char *, int);
+# endif
+/* #elif defined other_platform || defined ... */
+#endif
+
+/* portability defines, excluding path handling macros */
+#if defined _MSC_VER
+# define setmode _setmode
+# define stat _stat
+# define chmod _chmod
+# define getcwd _getcwd
+# define putenv _putenv
+# define S_IXUSR _S_IEXEC
+#elif defined __MINGW32__
+# define setmode _setmode
+# define stat _stat
+# define chmod _chmod
+# define getcwd _getcwd
+# define putenv _putenv
+#elif defined __CYGWIN__
+# define HAVE_SETENV
+# define FOPEN_WB "wb"
+/* #elif defined other platforms ... */
+#endif
+
+#if defined PATH_MAX
+# define LT_PATHMAX PATH_MAX
+#elif defined MAXPATHLEN
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef S_IXOTH
+# define S_IXOTH 0
+#endif
+#ifndef S_IXGRP
+# define S_IXGRP 0
+#endif
+
+/* path handling portability macros */
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \
+ defined __OS2__
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# define FOPEN_WB "wb"
+# ifndef DIR_SEPARATOR_2
+# define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+# define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#ifndef FOPEN_WB
+# define FOPEN_WB "w"
+#endif
+#ifndef _O_BINARY
+# define _O_BINARY 0
+#endif
+
+#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+ if (stale) { free (stale); stale = 0; } \
+} while (0)
+
+#if defined LT_DEBUGWRAPPER
+static int lt_debug = 1;
+#else
+static int lt_debug = 0;
+#endif
+
+const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */
+
+void *xmalloc (size_t num);
+char *xstrdup (const char *string);
+const char *base_name (const char *name);
+char *find_executable (const char *wrapper);
+char *chase_symlinks (const char *pathspec);
+int make_executable (const char *path);
+int check_executable (const char *path);
+char *strendzap (char *str, const char *pat);
+void lt_debugprintf (const char *file, int line, const char *fmt, ...);
+void lt_fatal (const char *file, int line, const char *message, ...);
+static const char *nonnull (const char *s);
+static const char *nonempty (const char *s);
+void lt_setenv (const char *name, const char *value);
+char *lt_extend_str (const char *orig_value, const char *add, int to_end);
+void lt_update_exe_path (const char *name, const char *value);
+void lt_update_lib_path (const char *name, const char *value);
+char **prepare_spawn (char **argv);
+void lt_dump_script (FILE *f);
+EOF
+
+ cat <<EOF
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5)
+# define externally_visible volatile
+#else
+# define externally_visible __attribute__((externally_visible)) volatile
+#endif
+externally_visible const char * MAGIC_EXE = "$magic_exe";
+const char * LIB_PATH_VARNAME = "$shlibpath_var";
+EOF
+
+ if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ func_to_host_path "$temp_rpath"
+ cat <<EOF
+const char * LIB_PATH_VALUE = "$func_to_host_path_result";
+EOF
+ else
+ cat <<"EOF"
+const char * LIB_PATH_VALUE = "";
+EOF
+ fi
+
+ if test -n "$dllsearchpath"; then
+ func_to_host_path "$dllsearchpath:"
+ cat <<EOF
+const char * EXE_PATH_VARNAME = "PATH";
+const char * EXE_PATH_VALUE = "$func_to_host_path_result";
+EOF
+ else
+ cat <<"EOF"
+const char * EXE_PATH_VARNAME = "";
+const char * EXE_PATH_VALUE = "";
+EOF
+ fi
+
+ if test yes = "$fast_install"; then
+ cat <<EOF
+const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */
+EOF
+ else
+ cat <<EOF
+const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */
+EOF
+ fi
+
+
+ cat <<"EOF"
+
+#define LTWRAPPER_OPTION_PREFIX "--lt-"
+
+static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;
+static const char *dumpscript_opt = LTWRAPPER_OPTION_PREFIX "dump-script";
+static const char *debug_opt = LTWRAPPER_OPTION_PREFIX "debug";
+
+int
+main (int argc, char *argv[])
+{
+ char **newargz;
+ int newargc;
+ char *tmp_pathspec;
+ char *actual_cwrapper_path;
+ char *actual_cwrapper_name;
+ char *target_name;
+ char *lt_argv_zero;
+ int rval = 127;
+
+ int i;
+
+ program_name = (char *) xstrdup (base_name (argv[0]));
+ newargz = XMALLOC (char *, (size_t) argc + 1);
+
+ /* very simple arg parsing; don't want to rely on getopt
+ * also, copy all non cwrapper options to newargz, except
+ * argz[0], which is handled differently
+ */
+ newargc=0;
+ for (i = 1; i < argc; i++)
+ {
+ if (STREQ (argv[i], dumpscript_opt))
+ {
+EOF
+ case $host in
+ *mingw* | *cygwin* )
+ # make stdout use "unix" line endings
+ echo " setmode(1,_O_BINARY);"
+ ;;
+ esac
+
+ cat <<"EOF"
+ lt_dump_script (stdout);
+ return 0;
+ }
+ if (STREQ (argv[i], debug_opt))
+ {
+ lt_debug = 1;
+ continue;
+ }
+ if (STREQ (argv[i], ltwrapper_option_prefix))
+ {
+ /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
+ namespace, but it is not one of the ones we know about and
+ have already dealt with, above (inluding dump-script), then
+ report an error. Otherwise, targets might begin to believe
+ they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
+ namespace. The first time any user complains about this, we'll
+ need to make LTWRAPPER_OPTION_PREFIX a configure-time option
+ or a configure.ac-settable value.
+ */
+ lt_fatal (__FILE__, __LINE__,
+ "unrecognized %s option: '%s'",
+ ltwrapper_option_prefix, argv[i]);
+ }
+ /* otherwise ... */
+ newargz[++newargc] = xstrdup (argv[i]);
+ }
+ newargz[++newargc] = NULL;
+
+EOF
+ cat <<EOF
+ /* The GNU banner must be the first non-error debug message */
+ lt_debugprintf (__FILE__, __LINE__, "libtool wrapper (GNU $PACKAGE) $VERSION\n");
+EOF
+ cat <<"EOF"
+ lt_debugprintf (__FILE__, __LINE__, "(main) argv[0]: %s\n", argv[0]);
+ lt_debugprintf (__FILE__, __LINE__, "(main) program_name: %s\n", program_name);
+
+ tmp_pathspec = find_executable (argv[0]);
+ if (tmp_pathspec == NULL)
+ lt_fatal (__FILE__, __LINE__, "couldn't find %s", argv[0]);
+ lt_debugprintf (__FILE__, __LINE__,
+ "(main) found exe (before symlink chase) at: %s\n",
+ tmp_pathspec);
+
+ actual_cwrapper_path = chase_symlinks (tmp_pathspec);
+ lt_debugprintf (__FILE__, __LINE__,
+ "(main) found exe (after symlink chase) at: %s\n",
+ actual_cwrapper_path);
+ XFREE (tmp_pathspec);
+
+ actual_cwrapper_name = xstrdup (base_name (actual_cwrapper_path));
+ strendzap (actual_cwrapper_path, actual_cwrapper_name);
+
+ /* wrapper name transforms */
+ strendzap (actual_cwrapper_name, ".exe");
+ tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1);
+ XFREE (actual_cwrapper_name);
+ actual_cwrapper_name = tmp_pathspec;
+ tmp_pathspec = 0;
+
+ /* target_name transforms -- use actual target program name; might have lt- prefix */
+ target_name = xstrdup (base_name (TARGET_PROGRAM_NAME));
+ strendzap (target_name, ".exe");
+ tmp_pathspec = lt_extend_str (target_name, ".exe", 1);
+ XFREE (target_name);
+ target_name = tmp_pathspec;
+ tmp_pathspec = 0;
+
+ lt_debugprintf (__FILE__, __LINE__,
+ "(main) libtool target name: %s\n",
+ target_name);
+EOF
+
+ cat <<EOF
+ newargz[0] =
+ XMALLOC (char, (strlen (actual_cwrapper_path) +
+ strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1));
+ strcpy (newargz[0], actual_cwrapper_path);
+ strcat (newargz[0], "$objdir");
+ strcat (newargz[0], "/");
+EOF
+
+ cat <<"EOF"
+ /* stop here, and copy so we don't have to do this twice */
+ tmp_pathspec = xstrdup (newargz[0]);
+
+ /* do NOT want the lt- prefix here, so use actual_cwrapper_name */
+ strcat (newargz[0], actual_cwrapper_name);
+
+ /* DO want the lt- prefix here if it exists, so use target_name */
+ lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1);
+ XFREE (tmp_pathspec);
+ tmp_pathspec = NULL;
+EOF
+
+ case $host_os in
+ mingw*)
+ cat <<"EOF"
+ {
+ char* p;
+ while ((p = strchr (newargz[0], '\\')) != NULL)
+ {
+ *p = '/';
+ }
+ while ((p = strchr (lt_argv_zero, '\\')) != NULL)
+ {
+ *p = '/';
+ }
+ }
+EOF
+ ;;
+ esac
+
+ cat <<"EOF"
+ XFREE (target_name);
+ XFREE (actual_cwrapper_path);
+ XFREE (actual_cwrapper_name);
+
+ lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
+ lt_setenv ("DUALCASE", "1"); /* for MSK sh */
+ /* Update the DLL searchpath. EXE_PATH_VALUE ($dllsearchpath) must
+ be prepended before (that is, appear after) LIB_PATH_VALUE ($temp_rpath)
+ because on Windows, both *_VARNAMEs are PATH but uninstalled
+ libraries must come first. */
+ lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
+ lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
+
+ lt_debugprintf (__FILE__, __LINE__, "(main) lt_argv_zero: %s\n",
+ nonnull (lt_argv_zero));
+ for (i = 0; i < newargc; i++)
+ {
+ lt_debugprintf (__FILE__, __LINE__, "(main) newargz[%d]: %s\n",
+ i, nonnull (newargz[i]));
+ }
+
+EOF
+
+ case $host_os in
+ mingw*)
+ cat <<"EOF"
+ /* execv doesn't actually work on mingw as expected on unix */
+ newargz = prepare_spawn (newargz);
+ rval = (int) _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);
+ if (rval == -1)
+ {
+ /* failed to start process */
+ lt_debugprintf (__FILE__, __LINE__,
+ "(main) failed to launch target \"%s\": %s\n",
+ lt_argv_zero, nonnull (strerror (errno)));
+ return 127;
+ }
+ return rval;
+EOF
+ ;;
+ *)
+ cat <<"EOF"
+ execv (lt_argv_zero, newargz);
+ return rval; /* =127, but avoids unused variable warning */
+EOF
+ ;;
+ esac
+
+ cat <<"EOF"
+}
+
+void *
+xmalloc (size_t num)
+{
+ void *p = (void *) malloc (num);
+ if (!p)
+ lt_fatal (__FILE__, __LINE__, "memory exhausted");
+
+ return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+ return string ? strcpy ((char *) xmalloc (strlen (string) + 1),
+ string) : NULL;
+}
+
+const char *
+base_name (const char *name)
+{
+ const char *base;
+
+#if defined HAVE_DOS_BASED_FILE_SYSTEM
+ /* Skip over the disk name in MSDOS pathnames. */
+ if (isalpha ((unsigned char) name[0]) && name[1] == ':')
+ name += 2;
+#endif
+
+ for (base = name; *name; name++)
+ if (IS_DIR_SEPARATOR (*name))
+ base = name + 1;
+ return base;
+}
+
+int
+check_executable (const char *path)
+{
+ struct stat st;
+
+ lt_debugprintf (__FILE__, __LINE__, "(check_executable): %s\n",
+ nonempty (path));
+ if ((!path) || (!*path))
+ return 0;
+
+ if ((stat (path, &st) >= 0)
+ && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+ return 1;
+ else
+ return 0;
+}
+
+int
+make_executable (const char *path)
+{
+ int rval = 0;
+ struct stat st;
+
+ lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n",
+ nonempty (path));
+ if ((!path) || (!*path))
+ return 0;
+
+ if (stat (path, &st) >= 0)
+ {
+ rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
+ }
+ return rval;
+}
+
+/* Searches for the full path of the wrapper. Returns
+ newly allocated full path name if found, NULL otherwise
+ Does not chase symlinks, even on platforms that support them.
+*/
+char *
+find_executable (const char *wrapper)
+{
+ int has_slash = 0;
+ const char *p;
+ const char *p_next;
+ /* static buffer for getcwd */
+ char tmp[LT_PATHMAX + 1];
+ size_t tmp_len;
+ char *concat_name;
+
+ lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n",
+ nonempty (wrapper));
+
+ if ((wrapper == NULL) || (*wrapper == '\0'))
+ return NULL;
+
+ /* Absolute path? */
+#if defined HAVE_DOS_BASED_FILE_SYSTEM
+ if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable (concat_name))
+ return concat_name;
+ XFREE (concat_name);
+ }
+ else
+ {
+#endif
+ if (IS_DIR_SEPARATOR (wrapper[0]))
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable (concat_name))
+ return concat_name;
+ XFREE (concat_name);
+ }
+#if defined HAVE_DOS_BASED_FILE_SYSTEM
+ }
+#endif
+
+ for (p = wrapper; *p; p++)
+ if (*p == '/')
+ {
+ has_slash = 1;
+ break;
+ }
+ if (!has_slash)
+ {
+ /* no slashes; search PATH */
+ const char *path = getenv ("PATH");
+ if (path != NULL)
+ {
+ for (p = path; *p; p = p_next)
+ {
+ const char *q;
+ size_t p_len;
+ for (q = p; *q; q++)
+ if (IS_PATH_SEPARATOR (*q))
+ break;
+ p_len = (size_t) (q - p);
+ p_next = (*q == '\0' ? q : q + 1);
+ if (p_len == 0)
+ {
+ /* empty path: current directory */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
+ nonnull (strerror (errno)));
+ tmp_len = strlen (tmp);
+ concat_name =
+ XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+ }
+ else
+ {
+ concat_name =
+ XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
+ memcpy (concat_name, p, p_len);
+ concat_name[p_len] = '/';
+ strcpy (concat_name + p_len + 1, wrapper);
+ }
+ if (check_executable (concat_name))
+ return concat_name;
+ XFREE (concat_name);
+ }
+ }
+ /* not found in PATH; assume curdir */
+ }
+ /* Relative path | not found in path: prepend cwd */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
+ nonnull (strerror (errno)));
+ tmp_len = strlen (tmp);
+ concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+
+ if (check_executable (concat_name))
+ return concat_name;
+ XFREE (concat_name);
+ return NULL;
+}
+
+char *
+chase_symlinks (const char *pathspec)
+{
+#ifndef S_ISLNK
+ return xstrdup (pathspec);
+#else
+ char buf[LT_PATHMAX];
+ struct stat s;
+ char *tmp_pathspec = xstrdup (pathspec);
+ char *p;
+ int has_symlinks = 0;
+ while (strlen (tmp_pathspec) && !has_symlinks)
+ {
+ lt_debugprintf (__FILE__, __LINE__,
+ "checking path component for symlinks: %s\n",
+ tmp_pathspec);
+ if (lstat (tmp_pathspec, &s) == 0)
+ {
+ if (S_ISLNK (s.st_mode) != 0)
+ {
+ has_symlinks = 1;
+ break;
+ }
+
+ /* search backwards for last DIR_SEPARATOR */
+ p = tmp_pathspec + strlen (tmp_pathspec) - 1;
+ while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+ p--;
+ if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+ {
+ /* no more DIR_SEPARATORS left */
+ break;
+ }
+ *p = '\0';
+ }
+ else
+ {
+ lt_fatal (__FILE__, __LINE__,
+ "error accessing file \"%s\": %s",
+ tmp_pathspec, nonnull (strerror (errno)));
+ }
+ }
+ XFREE (tmp_pathspec);
+
+ if (!has_symlinks)
+ {
+ return xstrdup (pathspec);
+ }
+
+ tmp_pathspec = realpath (pathspec, buf);
+ if (tmp_pathspec == 0)
+ {
+ lt_fatal (__FILE__, __LINE__,
+ "could not follow symlinks for %s", pathspec);
+ }
+ return xstrdup (tmp_pathspec);
+#endif
+}
+
+char *
+strendzap (char *str, const char *pat)
+{
+ size_t len, patlen;
+
+ assert (str != NULL);
+ assert (pat != NULL);
+
+ len = strlen (str);
+ patlen = strlen (pat);
+
+ if (patlen <= len)
+ {
+ str += len - patlen;
+ if (STREQ (str, pat))
+ *str = '\0';
+ }
+ return str;
+}
+
+void
+lt_debugprintf (const char *file, int line, const char *fmt, ...)
+{
+ va_list args;
+ if (lt_debug)
+ {
+ (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line);
+ va_start (args, fmt);
+ (void) vfprintf (stderr, fmt, args);
+ va_end (args);
+ }
+}
+
+static void
+lt_error_core (int exit_status, const char *file,
+ int line, const char *mode,
+ const char *message, va_list ap)
+{
+ fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode);
+ vfprintf (stderr, message, ap);
+ fprintf (stderr, ".\n");
+
+ if (exit_status >= 0)
+ exit (exit_status);
+}
+
+void
+lt_fatal (const char *file, int line, const char *message, ...)
+{
+ va_list ap;
+ va_start (ap, message);
+ lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap);
+ va_end (ap);
+}
+
+static const char *
+nonnull (const char *s)
+{
+ return s ? s : "(null)";
+}
+
+static const char *
+nonempty (const char *s)
+{
+ return (s && !*s) ? "(empty)" : nonnull (s);
+}
+
+void
+lt_setenv (const char *name, const char *value)
+{
+ lt_debugprintf (__FILE__, __LINE__,
+ "(lt_setenv) setting '%s' to '%s'\n",
+ nonnull (name), nonnull (value));
+ {
+#ifdef HAVE_SETENV
+ /* always make a copy, for consistency with !HAVE_SETENV */
+ char *str = xstrdup (value);
+ setenv (name, str, 1);
+#else
+ size_t len = strlen (name) + 1 + strlen (value) + 1;
+ char *str = XMALLOC (char, len);
+ sprintf (str, "%s=%s", name, value);
+ if (putenv (str) != EXIT_SUCCESS)
+ {
+ XFREE (str);
+ }
+#endif
+ }
+}
+
+char *
+lt_extend_str (const char *orig_value, const char *add, int to_end)
+{
+ char *new_value;
+ if (orig_value && *orig_value)
+ {
+ size_t orig_value_len = strlen (orig_value);
+ size_t add_len = strlen (add);
+ new_value = XMALLOC (char, add_len + orig_value_len + 1);
+ if (to_end)
+ {
+ strcpy (new_value, orig_value);
+ strcpy (new_value + orig_value_len, add);
+ }
+ else
+ {
+ strcpy (new_value, add);
+ strcpy (new_value + add_len, orig_value);
+ }
+ }
+ else
+ {
+ new_value = xstrdup (add);
+ }
+ return new_value;
+}
+
+void
+lt_update_exe_path (const char *name, const char *value)
+{
+ lt_debugprintf (__FILE__, __LINE__,
+ "(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
+ nonnull (name), nonnull (value));
+
+ if (name && *name && value && *value)
+ {
+ char *new_value = lt_extend_str (getenv (name), value, 0);
+ /* some systems can't cope with a ':'-terminated path #' */
+ size_t len = strlen (new_value);
+ while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
+ {
+ new_value[--len] = '\0';
+ }
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ }
+}
+
+void
+lt_update_lib_path (const char *name, const char *value)
+{
+ lt_debugprintf (__FILE__, __LINE__,
+ "(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
+ nonnull (name), nonnull (value));
+
+ if (name && *name && value && *value)
+ {
+ char *new_value = lt_extend_str (getenv (name), value, 0);
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ }
+}
+
+EOF
+ case $host_os in
+ mingw*)
+ cat <<"EOF"
+
+/* Prepares an argument vector before calling spawn().
+ Note that spawn() does not by itself call the command interpreter
+ (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
+ ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&v);
+ v.dwPlatformId == VER_PLATFORM_WIN32_NT;
+ }) ? "cmd.exe" : "command.com").
+ Instead it simply concatenates the arguments, separated by ' ', and calls
+ CreateProcess(). We must quote the arguments since Win32 CreateProcess()
+ interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
+ special way:
+ - Space and tab are interpreted as delimiters. They are not treated as
+ delimiters if they are surrounded by double quotes: "...".
+ - Unescaped double quotes are removed from the input. Their only effect is
+ that within double quotes, space and tab are treated like normal
+ characters.
+ - Backslashes not followed by double quotes are not special.
+ - But 2*n+1 backslashes followed by a double quote become
+ n backslashes followed by a double quote (n >= 0):
+ \" -> "
+ \\\" -> \"
+ \\\\\" -> \\"
+ */
+#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+char **
+prepare_spawn (char **argv)
+{
+ size_t argc;
+ char **new_argv;
+ size_t i;
+
+ /* Count number of arguments. */
+ for (argc = 0; argv[argc] != NULL; argc++)
+ ;
+
+ /* Allocate new argument vector. */
+ new_argv = XMALLOC (char *, argc + 1);
+
+ /* Put quoted arguments into the new argument vector. */
+ for (i = 0; i < argc; i++)
+ {
+ const char *string = argv[i];
+
+ if (string[0] == '\0')
+ new_argv[i] = xstrdup ("\"\"");
+ else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
+ {
+ int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
+ size_t length;
+ unsigned int backslashes;
+ const char *s;
+ char *quoted_string;
+ char *p;
+
+ length = 0;
+ backslashes = 0;
+ if (quote_around)
+ length++;
+ for (s = string; *s != '\0'; s++)
+ {
+ char c = *s;
+ if (c == '"')
+ length += backslashes + 1;
+ length++;
+ if (c == '\\')
+ backslashes++;
+ else
+ backslashes = 0;
+ }
+ if (quote_around)
+ length += backslashes + 1;
+
+ quoted_string = XMALLOC (char, length + 1);
+
+ p = quoted_string;
+ backslashes = 0;
+ if (quote_around)
+ *p++ = '"';
+ for (s = string; *s != '\0'; s++)
+ {
+ char c = *s;
+ if (c == '"')
+ {
+ unsigned int j;
+ for (j = backslashes + 1; j > 0; j--)
+ *p++ = '\\';
+ }
+ *p++ = c;
+ if (c == '\\')
+ backslashes++;
+ else
+ backslashes = 0;
+ }
+ if (quote_around)
+ {
+ unsigned int j;
+ for (j = backslashes; j > 0; j--)
+ *p++ = '\\';
+ *p++ = '"';
+ }
+ *p = '\0';
+
+ new_argv[i] = quoted_string;
+ }
+ else
+ new_argv[i] = (char *) string;
+ }
+ new_argv[argc] = NULL;
+
+ return new_argv;
+}
+EOF
+ ;;
+ esac
+
+ cat <<"EOF"
+void lt_dump_script (FILE* f)
+{
+EOF
+ func_emit_wrapper yes |
+ $SED -n -e '
+s/^\(.\{79\}\)\(..*\)/\1\
+\2/
+h
+s/\([\\"]\)/\\\1/g
+s/$/\\n/
+s/\([^\n]*\).*/ fputs ("\1", f);/p
+g
+D'
+ cat <<"EOF"
+}
+EOF
+}
+# end: func_emit_cwrapperexe_src
+
+# func_win32_import_lib_p ARG
+# True if ARG is an import lib, as indicated by $file_magic_cmd
+func_win32_import_lib_p ()
+{
+ $debug_cmd
+
+ case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in
+ *import*) : ;;
+ *) false ;;
+ esac
+}
+
+# func_suncc_cstd_abi
+# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!!
+# Several compiler flags select an ABI that is incompatible with the
+# Cstd library. Avoid specifying it if any are in CXXFLAGS.
+func_suncc_cstd_abi ()
+{
+ $debug_cmd
+
+ case " $compile_command " in
+ *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*)
+ suncc_use_cstd_abi=no
+ ;;
+ *)
+ suncc_use_cstd_abi=yes
+ ;;
+ esac
+}
+
+# func_mode_link arg...
+func_mode_link ()
+{
+ $debug_cmd
+
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+ # It is impossible to link a dll without this setting, and
+ # we shouldn't force the makefile maintainer to figure out
+ # what system we are compiling for in order to pass an extra
+ # flag for every libtool invocation.
+ # allow_undefined=no
+
+ # FIXME: Unfortunately, there are problems with the above when trying
+ # to make a dll that has undefined symbols, in which case not
+ # even a static library is built. For now, we need to specify
+ # -no-undefined on the libtool link line when we can be certain
+ # that all symbols are satisfied, otherwise we get a static library.
+ allow_undefined=yes
+ ;;
+ *)
+ allow_undefined=yes
+ ;;
+ esac
+ libtool_args=$nonopt
+ base_compile="$nonopt $@"
+ compile_command=$nonopt
+ finalize_command=$nonopt
+
+ compile_rpath=
+ finalize_rpath=
+ compile_shlibpath=
+ finalize_shlibpath=
+ convenience=
+ old_convenience=
+ deplibs=
+ old_deplibs=
+ compiler_flags=
+ linker_flags=
+ dllsearchpath=
+ lib_search_path=`pwd`
+ inst_prefix_dir=
+ new_inherited_linker_flags=
+ fix_hardcoded_libdir_flag=
+ fix_hardcoded_libdir_flag_ld=
+
+ avoid_version=no
+ bindir=
+ dlfiles=
+ dlprefiles=
+ dlself=no
+ export_dynamic=no
+ export_symbols=
+ export_symbols_regex=
+ generated=
+ libobjs=
+ ltlibs=
+ module=no
+ no_install=no
+ objs=
+ os2dllname=
+ non_pic_objects=
+ precious_files_regex=
+ prefer_static_libs=no
+ preload=false
+ prev=
+ prevarg=
+ release=
+ rpath=
+ xrpath=
+ perm_rpath=
+ temp_rpath=
+ thread_safe=no
+ vinfo=
+ vinfo_number=no
+ weak_libs=
+ single_module=$wl-single_module
+ func_infer_tag $base_compile
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case $arg in
+ -shared)
+ test yes != "$build_libtool_libs" \
+ && func_fatal_configuration "cannot build a shared library"
+ build_old_libs=no
+ break
+ ;;
+ -all-static | -static | -static-libtool-libs)
+ case $arg in
+ -all-static)
+ if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then
+ func_warning "complete static linking is impossible in this configuration"
+ fi
+ if test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=yes
+ ;;
+ -static)
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=built
+ ;;
+ -static-libtool-libs)
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=yes
+ ;;
+ esac
+ build_libtool_libs=no
+ build_old_libs=yes
+ break
+ ;;
+ esac
+ done
+
+ # See if our shared archives depend on static archives.
+ test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+ # Go through the arguments, transforming them on the way.
+ while test "$#" -gt 0; do
+ arg=$1
+ shift
+ func_quote_arg pretty,unquoted "$arg"
+ qarg=$func_quote_arg_unquoted_result
+ func_append libtool_args " $func_quote_arg_result"
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ output)
+ func_append compile_command " @OUTPUT@"
+ func_append finalize_command " @OUTPUT@"
+ ;;
+ esac
+
+ case $prev in
+ bindir)
+ bindir=$arg
+ prev=
+ continue
+ ;;
+ dlfiles|dlprefiles)
+ $preload || {
+ # Add the symbol object into the linking commands.
+ func_append compile_command " @SYMFILE@"
+ func_append finalize_command " @SYMFILE@"
+ preload=:
+ }
+ case $arg in
+ *.la | *.lo) ;; # We handle these cases below.
+ force)
+ if test no = "$dlself"; then
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ self)
+ if test dlprefiles = "$prev"; then
+ dlself=yes
+ elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then
+ dlself=yes
+ else
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ if test dlfiles = "$prev"; then
+ func_append dlfiles " $arg"
+ else
+ func_append dlprefiles " $arg"
+ fi
+ prev=
+ continue
+ ;;
+ esac
+ ;;
+ expsyms)
+ export_symbols=$arg
+ test -f "$arg" \
+ || func_fatal_error "symbol file '$arg' does not exist"
+ prev=
+ continue
+ ;;
+ expsyms_regex)
+ export_symbols_regex=$arg
+ prev=
+ continue
+ ;;
+ framework)
+ case $host in
+ *-*-darwin*)
+ case "$deplibs " in
+ *" $qarg.ltframework "*) ;;
+ *) func_append deplibs " $qarg.ltframework" # this is fixed later
+ ;;
+ esac
+ ;;
+ esac
+ prev=
+ continue
+ ;;
+ inst_prefix)
+ inst_prefix_dir=$arg
+ prev=
+ continue
+ ;;
+ mllvm)
+ # Clang does not use LLVM to link, so we can simply discard any
+ # '-mllvm $arg' options when doing the link step.
+ prev=
+ continue
+ ;;
+ objectlist)
+ if test -f "$arg"; then
+ save_arg=$arg
+ moreargs=
+ for fil in `cat "$save_arg"`
+ do
+# func_append moreargs " $fil"
+ arg=$fil
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if func_lalib_unsafe_p "$arg"; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ func_source "$arg"
+
+ if test -z "$pic_object" ||
+ test -z "$non_pic_object" ||
+ test none = "$pic_object" &&
+ test none = "$non_pic_object"; then
+ func_fatal_error "cannot find name of object for '$arg'"
+ fi
+
+ # Extract subdirectory from the argument.
+ func_dirname "$arg" "/" ""
+ xdir=$func_dirname_result
+
+ if test none != "$pic_object"; then
+ # Prepend the subdirectory the object is found in.
+ pic_object=$xdir$pic_object
+
+ if test dlfiles = "$prev"; then
+ if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then
+ func_append dlfiles " $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test dlprefiles = "$prev"; then
+ # Preload the old-style object.
+ func_append dlprefiles " $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ func_append libobjs " $pic_object"
+ arg=$pic_object
+ fi
+
+ # Non-PIC object.
+ if test none != "$non_pic_object"; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object=$xdir$non_pic_object
+
+ # A standard non-PIC object
+ func_append non_pic_objects " $non_pic_object"
+ if test -z "$pic_object" || test none = "$pic_object"; then
+ arg=$non_pic_object
+ fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object=$pic_object
+ func_append non_pic_objects " $non_pic_object"
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if $opt_dry_run; then
+ # Extract subdirectory from the argument.
+ func_dirname "$arg" "/" ""
+ xdir=$func_dirname_result
+
+ func_lo2o "$arg"
+ pic_object=$xdir$objdir/$func_lo2o_result
+ non_pic_object=$xdir$func_lo2o_result
+ func_append libobjs " $pic_object"
+ func_append non_pic_objects " $non_pic_object"
+ else
+ func_fatal_error "'$arg' is not a valid libtool object"
+ fi
+ fi
+ done
+ else
+ func_fatal_error "link input file '$arg' does not exist"
+ fi
+ arg=$save_arg
+ prev=
+ continue
+ ;;
+ os2dllname)
+ os2dllname=$arg
+ prev=
+ continue
+ ;;
+ precious_regex)
+ precious_files_regex=$arg
+ prev=
+ continue
+ ;;
+ release)
+ release=-$arg
+ prev=
+ continue
+ ;;
+ rpath | xrpath)
+ # We need an absolute path.
+ case $arg in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ func_fatal_error "only absolute run-paths are allowed"
+ ;;
+ esac
+ if test rpath = "$prev"; then
+ case "$rpath " in
+ *" $arg "*) ;;
+ *) func_append rpath " $arg" ;;
+ esac
+ else
+ case "$xrpath " in
+ *" $arg "*) ;;
+ *) func_append xrpath " $arg" ;;
+ esac
+ fi
+ prev=
+ continue
+ ;;
+ shrext)
+ shrext_cmds=$arg
+ prev=
+ continue
+ ;;
+ weak)
+ func_append weak_libs " $arg"
+ prev=
+ continue
+ ;;
+ xassembler)
+ func_append compiler_flags " -Xassembler $qarg"
+ prev=
+ func_append compile_command " -Xassembler $qarg"
+ func_append finalize_command " -Xassembler $qarg"
+ continue
+ ;;
+ xcclinker)
+ func_append linker_flags " $qarg"
+ func_append compiler_flags " $qarg"
+ prev=
+ func_append compile_command " $qarg"
+ func_append finalize_command " $qarg"
+ continue
+ ;;
+ xcompiler)
+ func_append compiler_flags " $qarg"
+ prev=
+ func_append compile_command " $qarg"
+ func_append finalize_command " $qarg"
+ continue
+ ;;
+ xlinker)
+ func_append linker_flags " $qarg"
+ func_append compiler_flags " $wl$qarg"
+ prev=
+ func_append compile_command " $wl$qarg"
+ func_append finalize_command " $wl$qarg"
+ continue
+ ;;
+ *)
+ eval "$prev=\"\$arg\""
+ prev=
+ continue
+ ;;
+ esac
+ fi # test -n "$prev"
+
+ prevarg=$arg
+
+ case $arg in
+ -all-static)
+ if test -n "$link_static_flag"; then
+ # See comment for -static flag below, for more details.
+ func_append compile_command " $link_static_flag"
+ func_append finalize_command " $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -allow-undefined)
+ # FIXME: remove this flag sometime in the future.
+ func_fatal_error "'-allow-undefined' must not be used because it is the default"
+ ;;
+
+ -avoid-version)
+ avoid_version=yes
+ continue
+ ;;
+
+ -bindir)
+ prev=bindir
+ continue
+ ;;
+
+ -dlopen)
+ prev=dlfiles
+ continue
+ ;;
+
+ -dlpreopen)
+ prev=dlprefiles
+ continue
+ ;;
+
+ -export-dynamic)
+ export_dynamic=yes
+ continue
+ ;;
+
+ -export-symbols | -export-symbols-regex)
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ func_fatal_error "more than one -exported-symbols argument is not allowed"
+ fi
+ if test X-export-symbols = "X$arg"; then
+ prev=expsyms
+ else
+ prev=expsyms_regex
+ fi
+ continue
+ ;;
+
+ -framework)
+ prev=framework
+ continue
+ ;;
+
+ -inst-prefix-dir)
+ prev=inst_prefix
+ continue
+ ;;
+
+ # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+ # so, if we see these flags be careful not to treat them like -L
+ -L[A-Z][A-Z]*:*)
+ case $with_gcc/$host in
+ no/*-*-irix* | /*-*-irix*)
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ ;;
+ esac
+ continue
+ ;;
+
+ -L*)
+ func_stripname "-L" '' "$arg"
+ if test -z "$func_stripname_result"; then
+ if test "$#" -gt 0; then
+ func_fatal_error "require no space between '-L' and '$1'"
+ else
+ func_fatal_error "need path for '-L' option"
+ fi
+ fi
+ func_resolve_sysroot "$func_stripname_result"
+ dir=$func_resolve_sysroot_result
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ test -z "$absdir" && \
+ func_fatal_error "cannot determine absolute directory name of '$dir'"
+ dir=$absdir
+ ;;
+ esac
+ case "$deplibs " in
+ *" -L$dir "* | *" $arg "*)
+ # Will only happen for absolute or sysroot arguments
+ ;;
+ *)
+ # Preserve sysroot, but never include relative directories
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;;
+ *) func_append deplibs " -L$dir" ;;
+ esac
+ func_append lib_search_path " $dir"
+ ;;
+ esac
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+ testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'`
+ case :$dllsearchpath: in
+ *":$dir:"*) ;;
+ ::) dllsearchpath=$dir;;
+ *) func_append dllsearchpath ":$dir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ ::) dllsearchpath=$testbindir;;
+ *) func_append dllsearchpath ":$testbindir";;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+
+ -l*)
+ if test X-lc = "X$arg" || test X-lm = "X$arg"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*)
+ # These systems don't actually have a C or math library (as such)
+ continue
+ ;;
+ *-*-os2*)
+ # These systems don't actually have a C library (as such)
+ test X-lc = "X$arg" && continue
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig* | *-*-midnightbsd*)
+ # Do not include libc due to us having libc/libc_r.
+ test X-lc = "X$arg" && continue
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C and math libraries are in the System framework
+ func_append deplibs " System.ltframework"
+ continue
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ test X-lc = "X$arg" && continue
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ test X-lc = "X$arg" && continue
+ ;;
+ esac
+ elif test X-lc_r = "X$arg"; then
+ case $host in
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig* | *-*-midnightbsd*)
+ # Do not include libc_r directly, use -pthread flag.
+ continue
+ ;;
+ esac
+ fi
+ func_append deplibs " $arg"
+ continue
+ ;;
+
+ -mllvm)
+ prev=mllvm
+ continue
+ ;;
+
+ -module)
+ module=yes
+ continue
+ ;;
+
+ # Tru64 UNIX uses -model [arg] to determine the layout of C++
+ # classes, name mangling, and exception handling.
+ # Darwin uses the -arch flag to determine output architecture.
+ -model|-arch|-isysroot|--sysroot)
+ func_append compiler_flags " $arg"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ prev=xcompiler
+ continue
+ ;;
+ # Solaris ld rejects as of 11.4. Refer to Oracle bug 22985199.
+ -pthread)
+ case $host in
+ *solaris2*) ;;
+ *)
+ case "$new_inherited_linker_flags " in
+ *" $arg "*) ;;
+ * ) func_append new_inherited_linker_flags " $arg" ;;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+ -mt|-mthreads|-kthread|-Kthread|-pthreads|--thread-safe \
+ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
+ func_append compiler_flags " $arg"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ case "$new_inherited_linker_flags " in
+ *" $arg "*) ;;
+ * ) func_append new_inherited_linker_flags " $arg" ;;
+ esac
+ continue
+ ;;
+
+ -multi_module)
+ single_module=$wl-multi_module
+ continue
+ ;;
+
+ -no-fast-install)
+ fast_install=no
+ continue
+ ;;
+
+ -no-install)
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)
+ # The PATH hackery in wrapper scripts is required on Windows
+ # and Darwin in order for the loader to find any dlls it needs.
+ func_warning "'-no-install' is ignored for $host"
+ func_warning "assuming '-no-fast-install' instead"
+ fast_install=no
+ ;;
+ *) no_install=yes ;;
+ esac
+ continue
+ ;;
+
+ -no-undefined)
+ allow_undefined=no
+ continue
+ ;;
+
+ -objectlist)
+ prev=objectlist
+ continue
+ ;;
+
+ -os2dllname)
+ prev=os2dllname
+ continue
+ ;;
+
+ -o) prev=output ;;
+
+ -precious-files-regex)
+ prev=precious_regex
+ continue
+ ;;
+
+ -release)
+ prev=release
+ continue
+ ;;
+
+ -rpath)
+ prev=rpath
+ continue
+ ;;
+
+ -R)
+ prev=xrpath
+ continue
+ ;;
+
+ -R*)
+ func_stripname '-R' '' "$arg"
+ dir=$func_stripname_result
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ =*)
+ func_stripname '=' '' "$dir"
+ dir=$lt_sysroot$func_stripname_result
+ ;;
+ *)
+ func_fatal_error "only absolute run-paths are allowed"
+ ;;
+ esac
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) func_append xrpath " $dir" ;;
+ esac
+ continue
+ ;;
+
+ -shared)
+ # The effects of -shared are defined in a previous loop.
+ continue
+ ;;
+
+ -shrext)
+ prev=shrext
+ continue
+ ;;
+
+ -static | -static-libtool-libs)
+ # The effects of -static are defined in a previous loop.
+ # We used to do the same as -all-static on platforms that
+ # didn't have a PIC flag, but the assumption that the effects
+ # would be equivalent was wrong. It would break on at least
+ # Digital Unix and AIX.
+ continue
+ ;;
+
+ -thread-safe)
+ thread_safe=yes
+ continue
+ ;;
+
+ -version-info)
+ prev=vinfo
+ continue
+ ;;
+
+ -version-number)
+ prev=vinfo
+ vinfo_number=yes
+ continue
+ ;;
+
+ -weak)
+ prev=weak
+ continue
+ ;;
+
+ -Wc,*)
+ func_stripname '-Wc,' '' "$arg"
+ args=$func_stripname_result
+ arg=
+ save_ifs=$IFS; IFS=,
+ for flag in $args; do
+ IFS=$save_ifs
+ func_quote_arg pretty "$flag"
+ func_append arg " $func_quote_arg_result"
+ func_append compiler_flags " $func_quote_arg_result"
+ done
+ IFS=$save_ifs
+ func_stripname ' ' '' "$arg"
+ arg=$func_stripname_result
+ ;;
+
+ -Wl,*)
+ func_stripname '-Wl,' '' "$arg"
+ args=$func_stripname_result
+ arg=
+ save_ifs=$IFS; IFS=,
+ for flag in $args; do
+ IFS=$save_ifs
+ func_quote_arg pretty "$flag"
+ func_append arg " $wl$func_quote_arg_result"
+ func_append compiler_flags " $wl$func_quote_arg_result"
+ func_append linker_flags " $func_quote_arg_result"
+ done
+ IFS=$save_ifs
+ func_stripname ' ' '' "$arg"
+ arg=$func_stripname_result
+ ;;
+
+ -Xassembler)
+ prev=xassembler
+ continue
+ ;;
+
+ -Xcompiler)
+ prev=xcompiler
+ continue
+ ;;
+
+ -Xlinker)
+ prev=xlinker
+ continue
+ ;;
+
+ -XCClinker)
+ prev=xcclinker
+ continue
+ ;;
+
+ # -msg_* for osf cc
+ -msg_*)
+ func_quote_arg pretty "$arg"
+ arg=$func_quote_arg_result
+ ;;
+
+ # Flags to be passed through unchanged, with rationale:
+ # -64, -mips[0-9] enable 64-bit mode for the SGI compiler
+ # -r[0-9][0-9]* specify processor for the SGI compiler
+ # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler
+ # +DA*, +DD* enable 64-bit mode for the HP compiler
+ # -q* compiler args for the IBM compiler
+ # -m*, -t[45]*, -txscale* architecture-specific flags for GCC
+ # -F/path path to uninstalled frameworks, gcc on darwin
+ # -p, -pg, --coverage, -fprofile-* profiling flags for GCC
+ # -fstack-protector* stack protector flags for GCC
+ # @file GCC response files
+ # -tp=* Portland pgcc target processor selection
+ # --sysroot=* for sysroot support
+ # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
+ # -specs=* GCC specs files
+ # -stdlib=* select c++ std lib with clang
+ # -fsanitize=* Clang/GCC memory and address sanitizer
+ # -fuse-ld=* Linker select flags for GCC
+ # -Wa,* Pass flags directly to the assembler
+ -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
+ -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \
+ -specs=*|-fsanitize=*|-fuse-ld=*|-Wa,*)
+ func_quote_arg pretty "$arg"
+ arg=$func_quote_arg_result
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ func_append compiler_flags " $arg"
+ continue
+ ;;
+
+ -Z*)
+ if test os2 = "`expr $host : '.*\(os2\)'`"; then
+ # OS/2 uses -Zxxx to specify OS/2-specific options
+ compiler_flags="$compiler_flags $arg"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ case $arg in
+ -Zlinker | -Zstack)
+ prev=xcompiler
+ ;;
+ esac
+ continue
+ else
+ # Otherwise treat like 'Some other compiler flag' below
+ func_quote_arg pretty "$arg"
+ arg=$func_quote_arg_result
+ fi
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ func_quote_arg pretty "$arg"
+ arg=$func_quote_arg_result
+ ;;
+
+ *.$objext)
+ # A standard object.
+ func_append objs " $arg"
+ ;;
+
+ *.lo)
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if func_lalib_unsafe_p "$arg"; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ func_source "$arg"
+
+ if test -z "$pic_object" ||
+ test -z "$non_pic_object" ||
+ test none = "$pic_object" &&
+ test none = "$non_pic_object"; then
+ func_fatal_error "cannot find name of object for '$arg'"
+ fi
+
+ # Extract subdirectory from the argument.
+ func_dirname "$arg" "/" ""
+ xdir=$func_dirname_result
+
+ test none = "$pic_object" || {
+ # Prepend the subdirectory the object is found in.
+ pic_object=$xdir$pic_object
+
+ if test dlfiles = "$prev"; then
+ if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then
+ func_append dlfiles " $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test dlprefiles = "$prev"; then
+ # Preload the old-style object.
+ func_append dlprefiles " $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ func_append libobjs " $pic_object"
+ arg=$pic_object
+ }
+
+ # Non-PIC object.
+ if test none != "$non_pic_object"; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object=$xdir$non_pic_object
+
+ # A standard non-PIC object
+ func_append non_pic_objects " $non_pic_object"
+ if test -z "$pic_object" || test none = "$pic_object"; then
+ arg=$non_pic_object
+ fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object=$pic_object
+ func_append non_pic_objects " $non_pic_object"
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if $opt_dry_run; then
+ # Extract subdirectory from the argument.
+ func_dirname "$arg" "/" ""
+ xdir=$func_dirname_result
+
+ func_lo2o "$arg"
+ pic_object=$xdir$objdir/$func_lo2o_result
+ non_pic_object=$xdir$func_lo2o_result
+ func_append libobjs " $pic_object"
+ func_append non_pic_objects " $non_pic_object"
+ else
+ func_fatal_error "'$arg' is not a valid libtool object"
+ fi
+ fi
+ ;;
+
+ *.$libext)
+ # An archive.
+ func_append deplibs " $arg"
+ func_append old_deplibs " $arg"
+ continue
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ func_resolve_sysroot "$arg"
+ if test dlfiles = "$prev"; then
+ # This library was specified with -dlopen.
+ func_append dlfiles " $func_resolve_sysroot_result"
+ prev=
+ elif test dlprefiles = "$prev"; then
+ # The library was specified with -dlpreopen.
+ func_append dlprefiles " $func_resolve_sysroot_result"
+ prev=
+ else
+ func_append deplibs " $func_resolve_sysroot_result"
+ fi
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ func_quote_arg pretty "$arg"
+ arg=$func_quote_arg_result
+ ;;
+ esac # arg
+
+ # Now actually substitute the argument into the commands.
+ if test -n "$arg"; then
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ fi
+ done # argument parsing loop
+
+ test -n "$prev" && \
+ func_fatal_help "the '$prevarg' option requires an argument"
+
+ if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then
+ eval arg=\"$export_dynamic_flag_spec\"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ fi
+
+ oldlibs=
+ # calculate the name of the file, without its directory
+ func_basename "$output"
+ outputname=$func_basename_result
+ libobjs_save=$libobjs
+
+ if test -n "$shlibpath_var"; then
+ # get the directories listed in $shlibpath_var
+ eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\`
+ else
+ shlib_search_path=
+ fi
+ eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+ eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+ # Definition is injected by LT_CONFIG during libtool generation.
+ func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH"
+
+ func_dirname "$output" "/" ""
+ output_objdir=$func_dirname_result$objdir
+ func_to_tool_file "$output_objdir/"
+ tool_output_objdir=$func_to_tool_file_result
+ # Create the object directory.
+ func_mkdir_p "$output_objdir"
+
+ # Determine the type of output
+ case $output in
+ "")
+ func_fatal_help "you must specify an output file"
+ ;;
+ *.$libext) linkmode=oldlib ;;
+ *.lo | *.$objext) linkmode=obj ;;
+ *.la) linkmode=lib ;;
+ *) linkmode=prog ;; # Anything else should be a program.
+ esac
+
+ specialdeplibs=
+
+ libs=
+ # Find all interdependent deplibs by searching for libraries
+ # that are linked more than once (e.g. -la -lb -la)
+ for deplib in $deplibs; do
+ if $opt_preserve_dup_deps; then
+ case "$libs " in
+ *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+ esac
+ fi
+ func_append libs " $deplib"
+ done
+
+ if test lib = "$linkmode"; then
+ libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+ # Compute libraries that are listed more than once in $predeps
+ # $postdeps and mark them as special (i.e., whose duplicates are
+ # not to be eliminated).
+ pre_post_deps=
+ if $opt_duplicate_compiler_generated_deps; then
+ for pre_post_dep in $predeps $postdeps; do
+ case "$pre_post_deps " in
+ *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;;
+ esac
+ func_append pre_post_deps " $pre_post_dep"
+ done
+ fi
+ pre_post_deps=
+ fi
+
+ deplibs=
+ newdependency_libs=
+ newlib_search_path=
+ need_relink=no # whether we're linking any uninstalled libtool libraries
+ notinst_deplibs= # not-installed libtool libraries
+ notinst_path= # paths that contain not-installed libtool libraries
+
+ case $linkmode in
+ lib)
+ passes="conv dlpreopen link"
+ for file in $dlfiles $dlprefiles; do
+ case $file in
+ *.la) ;;
+ *)
+ func_fatal_help "libraries can '-dlopen' only libtool libraries: $file"
+ ;;
+ esac
+ done
+ ;;
+ prog)
+ compile_deplibs=
+ finalize_deplibs=
+ alldeplibs=false
+ newdlfiles=
+ newdlprefiles=
+ passes="conv scan dlopen dlpreopen link"
+ ;;
+ *) passes="conv"
+ ;;
+ esac
+
+ for pass in $passes; do
+ # The preopen pass in lib mode reverses $deplibs; put it back here
+ # so that -L comes before libs that need it for instance...
+ if test lib,link = "$linkmode,$pass"; then
+ ## FIXME: Find the place where the list is rebuilt in the wrong
+ ## order, and fix it there properly
+ tmp_deplibs=
+ for deplib in $deplibs; do
+ tmp_deplibs="$deplib $tmp_deplibs"
+ done
+ deplibs=$tmp_deplibs
+ fi
+
+ if test lib,link = "$linkmode,$pass" ||
+ test prog,scan = "$linkmode,$pass"; then
+ libs=$deplibs
+ deplibs=
+ fi
+ if test prog = "$linkmode"; then
+ case $pass in
+ dlopen) libs=$dlfiles ;;
+ dlpreopen) libs=$dlprefiles ;;
+ link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+ esac
+ fi
+ if test lib,dlpreopen = "$linkmode,$pass"; then
+ # Collect and forward deplibs of preopened libtool libs
+ for lib in $dlprefiles; do
+ # Ignore non-libtool-libs
+ dependency_libs=
+ func_resolve_sysroot "$lib"
+ case $lib in
+ *.la) func_source "$func_resolve_sysroot_result" ;;
+ esac
+
+ # Collect preopened libtool deplibs, except any this library
+ # has declared as weak libs
+ for deplib in $dependency_libs; do
+ func_basename "$deplib"
+ deplib_base=$func_basename_result
+ case " $weak_libs " in
+ *" $deplib_base "*) ;;
+ *) func_append deplibs " $deplib" ;;
+ esac
+ done
+ done
+ libs=$dlprefiles
+ fi
+ if test dlopen = "$pass"; then
+ # Collect dlpreopened libraries
+ save_deplibs=$deplibs
+ deplibs=
+ fi
+
+ for deplib in $libs; do
+ lib=
+ found=false
+ case $deplib in
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
+ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
+ if test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ func_append compiler_flags " $deplib"
+ if test lib = "$linkmode"; then
+ case "$new_inherited_linker_flags " in
+ *" $deplib "*) ;;
+ * ) func_append new_inherited_linker_flags " $deplib" ;;
+ esac
+ fi
+ fi
+ continue
+ ;;
+ -l*)
+ if test lib != "$linkmode" && test prog != "$linkmode"; then
+ func_warning "'-l' is ignored for archives/objects"
+ continue
+ fi
+ func_stripname '-l' '' "$deplib"
+ name=$func_stripname_result
+ if test lib = "$linkmode"; then
+ searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
+ else
+ searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
+ fi
+ for searchdir in $searchdirs; do
+ for search_ext in .la $std_shrext .so .a; do
+ # Search the libtool library
+ lib=$searchdir/lib$name$search_ext
+ if test -f "$lib"; then
+ if test .la = "$search_ext"; then
+ found=:
+ else
+ found=false
+ fi
+ break 2
+ fi
+ done
+ done
+ if $found; then
+ # deplib is a libtool library
+ # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+ # We need to do some special things here, and not later.
+ if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+ case " $predeps $postdeps " in
+ *" $deplib "*)
+ if func_lalib_p "$lib"; then
+ library_names=
+ old_library=
+ func_source "$lib"
+ for l in $old_library $library_names; do
+ ll=$l
+ done
+ if test "X$ll" = "X$old_library"; then # only static version available
+ found=false
+ func_dirname "$lib" "" "."
+ ladir=$func_dirname_result
+ lib=$ladir/$old_library
+ if test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ fi
+ ;;
+ *) ;;
+ esac
+ fi
+ else
+ # deplib doesn't seem to be a libtool library
+ if test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ ;; # -l
+ *.ltframework)
+ if test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ if test lib = "$linkmode"; then
+ case "$new_inherited_linker_flags " in
+ *" $deplib "*) ;;
+ * ) func_append new_inherited_linker_flags " $deplib" ;;
+ esac
+ fi
+ fi
+ continue
+ ;;
+ -L*)
+ case $linkmode in
+ lib)
+ deplibs="$deplib $deplibs"
+ test conv = "$pass" && continue
+ newdependency_libs="$deplib $newdependency_libs"
+ func_stripname '-L' '' "$deplib"
+ func_resolve_sysroot "$func_stripname_result"
+ func_append newlib_search_path " $func_resolve_sysroot_result"
+ ;;
+ prog)
+ if test conv = "$pass"; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ if test scan = "$pass"; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ func_stripname '-L' '' "$deplib"
+ func_resolve_sysroot "$func_stripname_result"
+ func_append newlib_search_path " $func_resolve_sysroot_result"
+ ;;
+ *)
+ func_warning "'-L' is ignored for archives/objects"
+ ;;
+ esac # linkmode
+ continue
+ ;; # -L
+ -R*)
+ if test link = "$pass"; then
+ func_stripname '-R' '' "$deplib"
+ func_resolve_sysroot "$func_stripname_result"
+ dir=$func_resolve_sysroot_result
+ # Make sure the xrpath contains only unique directories.
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) func_append xrpath " $dir" ;;
+ esac
+ fi
+ deplibs="$deplib $deplibs"
+ continue
+ ;;
+ *.la)
+ func_resolve_sysroot "$deplib"
+ lib=$func_resolve_sysroot_result
+ ;;
+ *.$libext)
+ if test conv = "$pass"; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ case $linkmode in
+ lib)
+ # Linking convenience modules into shared libraries is allowed,
+ # but linking other static libraries is non-portable.
+ case " $dlpreconveniencelibs " in
+ *" $deplib "*) ;;
+ *)
+ valid_a_lib=false
+ case $deplibs_check_method in
+ match_pattern*)
+ set dummy $deplibs_check_method; shift
+ match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+ if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ valid_a_lib=:
+ fi
+ ;;
+ pass_all)
+ valid_a_lib=:
+ ;;
+ esac
+ if $valid_a_lib; then
+ echo
+ $ECHO "*** Warning: Linking the shared library $output against the"
+ $ECHO "*** static library $deplib is not portable!"
+ deplibs="$deplib $deplibs"
+ else
+ echo
+ $ECHO "*** Warning: Trying to link with static lib archive $deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have"
+ echo "*** because the file extensions .$libext of this argument makes me believe"
+ echo "*** that it is just a static archive that I should not use here."
+ fi
+ ;;
+ esac
+ continue
+ ;;
+ prog)
+ if test link != "$pass"; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ continue
+ ;;
+ esac # linkmode
+ ;; # *.$libext
+ *.lo | *.$objext)
+ if test conv = "$pass"; then
+ deplibs="$deplib $deplibs"
+ elif test prog = "$linkmode"; then
+ if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then
+ # If there is no dlopen support or we're linking statically,
+ # we need to preload.
+ func_append newdlprefiles " $deplib"
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ func_append newdlfiles " $deplib"
+ fi
+ fi
+ continue
+ ;;
+ %DEPLIBS%)
+ alldeplibs=:
+ continue
+ ;;
+ esac # case $deplib
+
+ $found || test -f "$lib" \
+ || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'"
+
+ # Check to see that this really is a libtool archive.
+ func_lalib_unsafe_p "$lib" \
+ || func_fatal_error "'$lib' is not a valid libtool archive"
+
+ func_dirname "$lib" "" "."
+ ladir=$func_dirname_result
+
+ dlname=
+ dlopen=
+ dlpreopen=
+ libdir=
+ library_names=
+ old_library=
+ inherited_linker_flags=
+ # If the library was installed with an old release of libtool,
+ # it will not redefine variables installed, or shouldnotlink
+ installed=yes
+ shouldnotlink=no
+ avoidtemprpath=
+
+
+ # Read the .la file
+ func_source "$lib"
+
+ # Convert "-framework foo" to "foo.ltframework"
+ if test -n "$inherited_linker_flags"; then
+ tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'`
+ for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
+ case " $new_inherited_linker_flags " in
+ *" $tmp_inherited_linker_flag "*) ;;
+ *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";;
+ esac
+ done
+ fi
+ dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ if test lib,link = "$linkmode,$pass" ||
+ test prog,scan = "$linkmode,$pass" ||
+ { test prog != "$linkmode" && test lib != "$linkmode"; }; then
+ test -n "$dlopen" && func_append dlfiles " $dlopen"
+ test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen"
+ fi
+
+ if test conv = "$pass"; then
+ # Only check for convenience libraries
+ deplibs="$lib $deplibs"
+ if test -z "$libdir"; then
+ if test -z "$old_library"; then
+ func_fatal_error "cannot find name of link library for '$lib'"
+ fi
+ # It is a libtool convenience library, so add in its objects.
+ func_append convenience " $ladir/$objdir/$old_library"
+ func_append old_convenience " $ladir/$objdir/$old_library"
+ elif test prog != "$linkmode" && test lib != "$linkmode"; then
+ func_fatal_error "'$lib' is not a convenience library"
+ fi
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ deplibs="$deplib $deplibs"
+ if $opt_preserve_dup_deps; then
+ case "$tmp_libs " in
+ *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+ esac
+ fi
+ func_append tmp_libs " $deplib"
+ done
+ continue
+ fi # $pass = conv
+
+
+ # Get the name of the library we link against.
+ linklib=
+ if test -n "$old_library" &&
+ { test yes = "$prefer_static_libs" ||
+ test built,no = "$prefer_static_libs,$installed"; }; then
+ linklib=$old_library
+ else
+ for l in $old_library $library_names; do
+ linklib=$l
+ done
+ fi
+ if test -z "$linklib"; then
+ func_fatal_error "cannot find name of link library for '$lib'"
+ fi
+
+ # This library was specified with -dlopen.
+ if test dlopen = "$pass"; then
+ test -z "$libdir" \
+ && func_fatal_error "cannot -dlopen a convenience library: '$lib'"
+ if test -z "$dlname" ||
+ test yes != "$dlopen_support" ||
+ test no = "$build_libtool_libs"
+ then
+ # If there is no dlname, no dlopen support or we're linking
+ # statically, we need to preload. We also need to preload any
+ # dependent libraries so libltdl's deplib preloader doesn't
+ # bomb out in the load deplibs phase.
+ func_append dlprefiles " $lib $dependency_libs"
+ else
+ func_append newdlfiles " $lib"
+ fi
+ continue
+ fi # $pass = dlopen
+
+ # We need an absolute path.
+ case $ladir in
+ [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;;
+ *)
+ abs_ladir=`cd "$ladir" && pwd`
+ if test -z "$abs_ladir"; then
+ func_warning "cannot determine absolute directory name of '$ladir'"
+ func_warning "passing it literally to the linker, although it might fail"
+ abs_ladir=$ladir
+ fi
+ ;;
+ esac
+ func_basename "$lib"
+ laname=$func_basename_result
+
+ # Find the relevant object directory and library name.
+ if test yes = "$installed"; then
+ if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ func_warning "library '$lib' was moved."
+ dir=$ladir
+ absdir=$abs_ladir
+ libdir=$abs_ladir
+ else
+ dir=$lt_sysroot$libdir
+ absdir=$lt_sysroot$libdir
+ fi
+ test yes = "$hardcode_automatic" && avoidtemprpath=yes
+ else
+ if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ dir=$ladir
+ absdir=$abs_ladir
+ # Remove this search path later
+ func_append notinst_path " $abs_ladir"
+ else
+ dir=$ladir/$objdir
+ absdir=$abs_ladir/$objdir
+ # Remove this search path later
+ func_append notinst_path " $abs_ladir"
+ fi
+ fi # $installed = yes
+ func_stripname 'lib' '.la' "$laname"
+ name=$func_stripname_result
+
+ # This library was specified with -dlpreopen.
+ if test dlpreopen = "$pass"; then
+ if test -z "$libdir" && test prog = "$linkmode"; then
+ func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'"
+ fi
+ case $host in
+ # special handling for platforms with PE-DLLs.
+ *cygwin* | *mingw* | *cegcc* )
+ # Linker will automatically link against shared library if both
+ # static and shared are present. Therefore, ensure we extract
+ # symbols from the import library if a shared library is present
+ # (otherwise, the dlopen module name will be incorrect). We do
+ # this by putting the import library name into $newdlprefiles.
+ # We recover the dlopen module name by 'saving' the la file
+ # name in a special purpose variable, and (later) extracting the
+ # dlname from the la file.
+ if test -n "$dlname"; then
+ func_tr_sh "$dir/$linklib"
+ eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname"
+ func_append newdlprefiles " $dir/$linklib"
+ else
+ func_append newdlprefiles " $dir/$old_library"
+ # Keep a list of preopened convenience libraries to check
+ # that they are being used correctly in the link pass.
+ test -z "$libdir" && \
+ func_append dlpreconveniencelibs " $dir/$old_library"
+ fi
+ ;;
+ * )
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ func_append newdlprefiles " $dir/$old_library"
+ # Keep a list of preopened convenience libraries to check
+ # that they are being used correctly in the link pass.
+ test -z "$libdir" && \
+ func_append dlpreconveniencelibs " $dir/$old_library"
+ # Otherwise, use the dlname, so that lt_dlopen finds it.
+ elif test -n "$dlname"; then
+ func_append newdlprefiles " $dir/$dlname"
+ else
+ func_append newdlprefiles " $dir/$linklib"
+ fi
+ ;;
+ esac
+ fi # $pass = dlpreopen
+
+ if test -z "$libdir"; then
+ # Link the convenience library
+ if test lib = "$linkmode"; then
+ deplibs="$dir/$old_library $deplibs"
+ elif test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$dir/$old_library $compile_deplibs"
+ finalize_deplibs="$dir/$old_library $finalize_deplibs"
+ else
+ deplibs="$lib $deplibs" # used for prog,scan pass
+ fi
+ continue
+ fi
+
+
+ if test prog = "$linkmode" && test link != "$pass"; then
+ func_append newlib_search_path " $ladir"
+ deplibs="$lib $deplibs"
+
+ linkalldeplibs=false
+ if test no != "$link_all_deplibs" || test -z "$library_names" ||
+ test no = "$build_libtool_libs"; then
+ linkalldeplibs=:
+ fi
+
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) func_stripname '-L' '' "$deplib"
+ func_resolve_sysroot "$func_stripname_result"
+ func_append newlib_search_path " $func_resolve_sysroot_result"
+ ;;
+ esac
+ # Need to link against all dependency_libs?
+ if $linkalldeplibs; then
+ deplibs="$deplib $deplibs"
+ else
+ # Need to hardcode shared library paths
+ # or/and link against static libraries
+ newdependency_libs="$deplib $newdependency_libs"
+ fi
+ if $opt_preserve_dup_deps; then
+ case "$tmp_libs " in
+ *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+ esac
+ fi
+ func_append tmp_libs " $deplib"
+ done # for deplib
+ continue
+ fi # $linkmode = prog...
+
+ if test prog,link = "$linkmode,$pass"; then
+ if test -n "$library_names" &&
+ { { test no = "$prefer_static_libs" ||
+ test built,yes = "$prefer_static_libs,$installed"; } ||
+ test -z "$old_library"; }; then
+ # We need to hardcode the library path
+ if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then
+ # Make sure the rpath contains only unique directories.
+ case $temp_rpath: in
+ *"$absdir:"*) ;;
+ *) func_append temp_rpath "$absdir:" ;;
+ esac
+ fi
+
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) func_append compile_rpath " $absdir" ;;
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) func_append finalize_rpath " $libdir" ;;
+ esac
+ ;;
+ esac
+ fi # $linkmode,$pass = prog,link...
+
+ if $alldeplibs &&
+ { test pass_all = "$deplibs_check_method" ||
+ { test yes = "$build_libtool_libs" &&
+ test -n "$library_names"; }; }; then
+ # We only need to search for static libraries
+ continue
+ fi
+ fi
+
+ link_static=no # Whether the deplib will be linked statically
+ use_static_libs=$prefer_static_libs
+ if test built = "$use_static_libs" && test yes = "$installed"; then
+ use_static_libs=no
+ fi
+ if test -n "$library_names" &&
+ { test no = "$use_static_libs" || test -z "$old_library"; }; then
+ case $host in
+ *cygwin* | *mingw* | *cegcc* | *os2*)
+ # No point in relinking DLLs because paths are not encoded
+ func_append notinst_deplibs " $lib"
+ need_relink=no
+ ;;
+ *)
+ if test no = "$installed"; then
+ func_append notinst_deplibs " $lib"
+ need_relink=yes
+ fi
+ ;;
+ esac
+ # This is a shared library
+
+ # Warn about portability, can't link against -module's on some
+ # systems (darwin). Don't bleat about dlopened modules though!
+ dlopenmodule=
+ for dlpremoduletest in $dlprefiles; do
+ if test "X$dlpremoduletest" = "X$lib"; then
+ dlopenmodule=$dlpremoduletest
+ break
+ fi
+ done
+ if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then
+ echo
+ if test prog = "$linkmode"; then
+ $ECHO "*** Warning: Linking the executable $output against the loadable module"
+ else
+ $ECHO "*** Warning: Linking the shared library $output against the loadable module"
+ fi
+ $ECHO "*** $linklib is not portable!"
+ fi
+ if test lib = "$linkmode" &&
+ test yes = "$hardcode_into_libs"; then
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) func_append compile_rpath " $absdir" ;;
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) func_append finalize_rpath " $libdir" ;;
+ esac
+ ;;
+ esac
+ fi
+
+ if test -n "$old_archive_from_expsyms_cmds"; then
+ # figure out the soname
+ set dummy $library_names
+ shift
+ realname=$1
+ shift
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ # use dlname if we got it. it's perfectly good, no?
+ if test -n "$dlname"; then
+ soname=$dlname
+ elif test -n "$soname_spec"; then
+ # bleh windows
+ case $host in
+ *cygwin* | mingw* | *cegcc* | *os2*)
+ func_arith $current - $age
+ major=$func_arith_result
+ versuffix=-$major
+ ;;
+ esac
+ eval soname=\"$soname_spec\"
+ else
+ soname=$realname
+ fi
+
+ # Make a new name for the extract_expsyms_cmds to use
+ soroot=$soname
+ func_basename "$soroot"
+ soname=$func_basename_result
+ func_stripname 'lib' '.dll' "$soname"
+ newlib=libimp-$func_stripname_result.a
+
+ # If the library has no export list, then create one now
+ if test -f "$output_objdir/$soname-def"; then :
+ else
+ func_verbose "extracting exported symbol list from '$soname'"
+ func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
+ fi
+
+ # Create $newlib
+ if test -f "$output_objdir/$newlib"; then :; else
+ func_verbose "generating import library for '$soname'"
+ func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
+ fi
+ # make sure the library variables are pointing to the new library
+ dir=$output_objdir
+ linklib=$newlib
+ fi # test -n "$old_archive_from_expsyms_cmds"
+
+ if test prog = "$linkmode" || test relink != "$opt_mode"; then
+ add_shlibpath=
+ add_dir=
+ add=
+ lib_linked=yes
+ case $hardcode_action in
+ immediate | unsupported)
+ if test no = "$hardcode_direct"; then
+ add=$dir/$linklib
+ case $host in
+ *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;;
+ *-*-sysv4*uw2*) add_dir=-L$dir ;;
+ *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+ *-*-unixware7*) add_dir=-L$dir ;;
+ *-*-darwin* )
+ # if the lib is a (non-dlopened) module then we cannot
+ # link against it, someone is ignoring the earlier warnings
+ if /usr/bin/file -L $add 2> /dev/null |
+ $GREP ": [^:]* bundle" >/dev/null; then
+ if test "X$dlopenmodule" != "X$lib"; then
+ $ECHO "*** Warning: lib $linklib is a module, not a shared library"
+ if test -z "$old_library"; then
+ echo
+ echo "*** And there doesn't seem to be a static archive available"
+ echo "*** The link will probably fail, sorry"
+ else
+ add=$dir/$old_library
+ fi
+ elif test -n "$old_library"; then
+ add=$dir/$old_library
+ fi
+ fi
+ esac
+ elif test no = "$hardcode_minus_L"; then
+ case $host in
+ *-*-sunos*) add_shlibpath=$dir ;;
+ esac
+ add_dir=-L$dir
+ add=-l$name
+ elif test no = "$hardcode_shlibpath_var"; then
+ add_shlibpath=$dir
+ add=-l$name
+ elif test -n "$fix_hardcoded_libdir_flag_spec"; then
+ add_dir="-L${absdir}"
+ add="-l$name"
+ if test "${linkmode}" = prog && test "X${absdir}" != "X${libdir}"; then
+ linkdir=$absdir
+ eval "fix_hardcoded_libdir_flag=\"\${fix_hardcoded_libdir_flag} ${fix_hardcoded_libdir_flag_spec}\""
+ # fix_hardcoded_libdir_flag_ld not needed, programs are linked with $CC
+ $lt_unset linkdir
+ fi
+ else
+ lib_linked=no
+ fi
+ ;;
+ relink)
+ if test yes = "$hardcode_direct" &&
+ test no = "$hardcode_direct_absolute"; then
+ add=$dir/$linklib
+ elif test yes = "$hardcode_minus_L"; then
+ add_dir=-L$absdir
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+ [\\/]*)
+ func_append add_dir " -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add=-l$name
+ elif test yes = "$hardcode_shlibpath_var"; then
+ add_shlibpath=$dir
+ add=-l$name
+ else
+ lib_linked=no
+ fi
+ ;;
+ *) lib_linked=no ;;
+ esac
+
+ if test yes != "$lib_linked"; then
+ func_fatal_configuration "unsupported hardcode properties"
+ fi
+
+ if test -n "$add_shlibpath"; then
+ case :$compile_shlibpath: in
+ *":$add_shlibpath:"*) ;;
+ *) func_append compile_shlibpath "$add_shlibpath:" ;;
+ esac
+ fi
+ if test prog = "$linkmode"; then
+ test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+ test -n "$add" && compile_deplibs="$add $compile_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ if test yes != "$hardcode_direct" &&
+ test yes != "$hardcode_minus_L" &&
+ test yes = "$hardcode_shlibpath_var"; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) func_append finalize_shlibpath "$libdir:" ;;
+ esac
+ fi
+ fi
+ fi
+
+ if test prog = "$linkmode" || test relink = "$opt_mode"; then
+ add_shlibpath=
+ add_dir=
+ add=
+ # Finalize command for both is simple: just hardcode it.
+ if test yes = "$hardcode_direct" &&
+ test no = "$hardcode_direct_absolute"; then
+ add=$libdir/$linklib
+ elif test yes = "$hardcode_minus_L"; then
+ add_dir=-L$libdir
+ add=-l$name
+ if test -n "$inst_prefix_dir" &&
+ test -f "$inst_prefix_dir$libdir/$linklib" &&
+ test -n "${fix_hardcoded_libdir_flag_spec}"; then
+ linkdir="$inst_prefix_dir$libdir"
+ add_dir="-L$linkdir"
+ eval "fix_hardcoded_libdir_flag=\"\${fix_hardcoded_libdir_flag} ${fix_hardcoded_libdir_flag_spec}\""
+ eval "fix_hardcoded_libdir_flag_ld=\"\${fix_hardcoded_libdir_flag_ld} ${fix_hardcoded_libdir_flag_spec_ld}\""
+ $lt_unset linkdir
+ fi
+ elif test yes = "$hardcode_shlibpath_var"; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) func_append finalize_shlibpath "$libdir:" ;;
+ esac
+ add=-l$name
+ elif test yes = "$hardcode_automatic"; then
+ if test -n "$inst_prefix_dir" &&
+ test -f "$inst_prefix_dir$libdir/$linklib"; then
+ add=$inst_prefix_dir$libdir/$linklib
+ else
+ add=$libdir/$linklib
+ fi
+ else
+ # We cannot seem to hardcode it, guess we'll fake it.
+ add_dir=-L$libdir
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+ [\\/]*)
+ func_append add_dir " -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add=-l$name
+ fi
+
+ if test prog = "$linkmode"; then
+ test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+ test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ fi
+ fi
+ elif test prog = "$linkmode"; then
+ # Here we assume that one of hardcode_direct or hardcode_minus_L
+ # is not unsupported. This is valid on all known static and
+ # shared platforms.
+ if test unsupported != "$hardcode_direct"; then
+ test -n "$old_library" && linklib=$old_library
+ compile_deplibs="$dir/$linklib $compile_deplibs"
+ finalize_deplibs="$dir/$linklib $finalize_deplibs"
+ else
+ compile_deplibs="-l$name -L$dir $compile_deplibs"
+ finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+ fi
+ elif test yes = "$build_libtool_libs"; then
+ # Not a shared library
+ if test pass_all != "$deplibs_check_method"; then
+ # We're trying link a shared library against a static one
+ # but the system doesn't support it.
+
+ # Just print a warning and add the library to dependency_libs so
+ # that the program can be linked against the static library.
+ echo
+ $ECHO "*** Warning: This system cannot link to static lib archive $lib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ if test yes = "$module"; then
+ echo "*** But as you try to build a module library, libtool will still create "
+ echo "*** a static module, that should work as long as the dlopening application"
+ echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+ if test -z "$global_symbol_pipe"; then
+ echo
+ echo "*** However, this would only work if libtool was able to extract symbol"
+ echo "*** lists from a program, using 'nm' or equivalent, but libtool could"
+ echo "*** not find such a program. So, this module is probably useless."
+ echo "*** 'nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test no = "$build_old_libs"; then
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ else
+ deplibs="$dir/$old_library $deplibs"
+ link_static=yes
+ fi
+ fi # link shared/static library?
+
+ if test lib = "$linkmode"; then
+ if test -n "$dependency_libs" &&
+ { test yes != "$hardcode_into_libs" ||
+ test yes = "$build_old_libs" ||
+ test yes = "$link_static"; }; then
+ # Extract -R from dependency_libs
+ temp_deplibs=
+ for libdir in $dependency_libs; do
+ case $libdir in
+ -R*) func_stripname '-R' '' "$libdir"
+ temp_xrpath=$func_stripname_result
+ case " $xrpath " in
+ *" $temp_xrpath "*) ;;
+ *) func_append xrpath " $temp_xrpath";;
+ esac;;
+ *) func_append temp_deplibs " $libdir";;
+ esac
+ done
+ dependency_libs=$temp_deplibs
+ fi
+
+ func_append newlib_search_path " $absdir"
+ # Link against this library
+ test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+ # ... and its dependency_libs
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ newdependency_libs="$deplib $newdependency_libs"
+ case $deplib in
+ -L*) func_stripname '-L' '' "$deplib"
+ func_resolve_sysroot "$func_stripname_result";;
+ *) func_resolve_sysroot "$deplib" ;;
+ esac
+ if $opt_preserve_dup_deps; then
+ case "$tmp_libs " in
+ *" $func_resolve_sysroot_result "*)
+ func_append specialdeplibs " $func_resolve_sysroot_result" ;;
+ esac
+ fi
+ func_append tmp_libs " $func_resolve_sysroot_result"
+ done
+
+ if test no != "$link_all_deplibs"; then
+ # Add the search paths of all dependency libraries
+ for deplib in $dependency_libs; do
+ path=
+ case $deplib in
+ -L*) path=$deplib ;;
+ *.la)
+ func_resolve_sysroot "$deplib"
+ deplib=$func_resolve_sysroot_result
+ func_dirname "$deplib" "" "."
+ dir=$func_dirname_result
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ func_warning "cannot determine absolute directory name of '$dir'"
+ absdir=$dir
+ fi
+ ;;
+ esac
+ if $GREP "^installed=no" $deplib > /dev/null; then
+ case $host in
+ *-*-darwin*)
+ depdepl=
+ eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+ if test -n "$deplibrary_names"; then
+ for tmp in $deplibrary_names; do
+ depdepl=$tmp
+ done
+ if test -f "$absdir/$objdir/$depdepl"; then
+ depdepl=$absdir/$objdir/$depdepl
+ darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
+ if test -z "$darwin_install_name"; then
+ darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
+ fi
+ func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl"
+ func_append linker_flags " -dylib_file $darwin_install_name:$depdepl"
+ path=
+ fi
+ fi
+ ;;
+ *)
+ path=-L$absdir/$objdir
+ ;;
+ esac
+ else
+ eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ test -z "$libdir" && \
+ func_fatal_error "'$deplib' is not a valid libtool archive"
+ test "$absdir" != "$libdir" && \
+ func_warning "'$deplib' seems to be moved"
+
+ path=-L$absdir
+ fi
+ ;;
+ esac
+ case " $deplibs " in
+ *" $path "*) ;;
+ *) deplibs="$path $deplibs" ;;
+ esac
+ done
+ fi # link_all_deplibs != no
+ fi # linkmode = lib
+ done # for deplib in $libs
+ if test link = "$pass"; then
+ if test prog = "$linkmode"; then
+ compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
+ finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
+ else
+ compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ fi
+ fi
+ dependency_libs=$newdependency_libs
+ if test dlpreopen = "$pass"; then
+ # Link the dlpreopened libraries before other libraries
+ for deplib in $save_deplibs; do
+ deplibs="$deplib $deplibs"
+ done
+ fi
+ if test dlopen != "$pass"; then
+ test conv = "$pass" || {
+ # Make sure lib_search_path contains only unique directories.
+ lib_search_path=
+ for dir in $newlib_search_path; do
+ case "$lib_search_path " in
+ *" $dir "*) ;;
+ *) func_append lib_search_path " $dir" ;;
+ esac
+ done
+ newlib_search_path=
+ }
+
+ if test prog,link = "$linkmode,$pass"; then
+ vars="compile_deplibs finalize_deplibs"
+ else
+ vars=deplibs
+ fi
+ for var in $vars dependency_libs; do
+ # Add libraries to $var in reverse order
+ eval tmp_libs=\"\$$var\"
+ new_libs=
+ for deplib in $tmp_libs; do
+ # FIXME: Pedantically, this is the right thing to do, so
+ # that some nasty dependency loop isn't accidentally
+ # broken:
+ #new_libs="$deplib $new_libs"
+ # Pragmatically, this seems to cause very few problems in
+ # practice:
+ case $deplib in
+ -L*) new_libs="$deplib $new_libs" ;;
+ -R*) ;;
+ *)
+ # And here is the reason: when a library appears more
+ # than once as an explicit dependence of a library, or
+ # is implicitly linked in more than once by the
+ # compiler, it is considered special, and multiple
+ # occurrences thereof are not removed. Compare this
+ # with having the same library being listed as a
+ # dependency of multiple other libraries: in this case,
+ # we know (pedantically, we assume) the library does not
+ # need to be listed more than once, so we keep only the
+ # last copy. This is not always right, but it is rare
+ # enough that we require users that really mean to play
+ # such unportable linking tricks to link the library
+ # using -Wl,-lname, so that libtool does not consider it
+ # for duplicate removal.
+ case " $specialdeplibs " in
+ *" $deplib "*) new_libs="$deplib $new_libs" ;;
+ *)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$deplib $new_libs" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ tmp_libs=
+ for deplib in $new_libs; do
+ case $deplib in
+ -L*)
+ case " $tmp_libs " in
+ *" $deplib "*) ;;
+ *) func_append tmp_libs " $deplib" ;;
+ esac
+ ;;
+ *) func_append tmp_libs " $deplib" ;;
+ esac
+ done
+ eval $var=\"$tmp_libs\"
+ done # for var
+ fi
+
+ # Add Sun CC postdeps if required:
+ test CXX = "$tagname" && {
+ case $host_os in
+ linux*)
+ case `$CC -V 2>&1 | $SED 5q` in
+ *Sun\ C*) # Sun C++ 5.9
+ func_suncc_cstd_abi
+
+ if test no != "$suncc_use_cstd_abi"; then
+ func_append postdeps ' -library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+
+ solaris*)
+ func_cc_basename "$CC"
+ case $func_cc_basename_result in
+ CC* | sunCC*)
+ func_suncc_cstd_abi
+
+ if test no != "$suncc_use_cstd_abi"; then
+ func_append postdeps ' -library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ }
+
+ # Last step: remove runtime libs from dependency_libs
+ # (they stay in deplibs)
+ tmp_libs=
+ for i in $dependency_libs; do
+ case " $predeps $postdeps $compiler_lib_search_path " in
+ *" $i "*)
+ i=
+ ;;
+ esac
+ if test -n "$i"; then
+ func_append tmp_libs " $i"
+ fi
+ done
+ dependency_libs=$tmp_libs
+ done # for pass
+ if test prog = "$linkmode"; then
+ dlfiles=$newdlfiles
+ fi
+ if test prog = "$linkmode" || test lib = "$linkmode"; then
+ dlprefiles=$newdlprefiles
+ fi
+
+ case $linkmode in
+ oldlib)
+ if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
+ func_warning "'-dlopen' is ignored for archives"
+ fi
+
+ case " $deplibs" in
+ *\ -l* | *\ -L*)
+ func_warning "'-l' and '-L' are ignored for archives" ;;
+ esac
+
+ test -n "$rpath" && \
+ func_warning "'-rpath' is ignored for archives"
+
+ test -n "$xrpath" && \
+ func_warning "'-R' is ignored for archives"
+
+ test -n "$vinfo" && \
+ func_warning "'-version-info/-version-number' is ignored for archives"
+
+ test -n "$release" && \
+ func_warning "'-release' is ignored for archives"
+
+ test -n "$export_symbols$export_symbols_regex" && \
+ func_warning "'-export-symbols' is ignored for archives"
+
+ # Now set the variables for building old libraries.
+ build_libtool_libs=no
+ oldlibs=$output
+ func_append objs "$old_deplibs"
+ ;;
+
+ lib)
+ # Make sure we only generate libraries of the form 'libNAME.la'.
+ case $outputname in
+ lib*)
+ func_stripname 'lib' '.la' "$outputname"
+ name=$func_stripname_result
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ ;;
+ *)
+ if test no != "$need_lib_prefix"; then
+ # Add the "lib" prefix for modules if required
+ func_stripname '' '.la' "$outputname"
+ name=$func_stripname_result
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ else
+ func_stripname '' '.la' "$outputname"
+ libname=$func_stripname_result
+ fi
+ ;;
+ esac
+
+ if test -n "$objs"; then
+ if test pass_all != "$deplibs_check_method"; then
+ func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs"
+ else
+ echo
+ $ECHO "*** Warning: Linking the shared library $output against the non-libtool"
+ $ECHO "*** objects $objs is not portable!"
+ func_append libobjs " $objs"
+ fi
+ fi
+
+ test no = "$dlself" \
+ || func_warning "'-dlopen self' is ignored for libtool libraries"
+
+ set dummy $rpath
+ shift
+ test 1 -lt "$#" \
+ && func_warning "ignoring multiple '-rpath's for a libtool library"
+
+ install_libdir=$1
+
+ oldlibs=
+ if test -z "$rpath"; then
+ if test yes = "$build_libtool_libs"; then
+ # Building a libtool convenience library.
+ # Some compilers have problems with a '.al' extension so
+ # convenience libraries should have the same extension an
+ # archive normally would.
+ oldlibs="$output_objdir/$libname.$libext $oldlibs"
+ build_libtool_libs=convenience
+ build_old_libs=yes
+ fi
+
+ test -n "$vinfo" && \
+ func_warning "'-version-info/-version-number' is ignored for convenience libraries"
+
+ test -n "$release" && \
+ func_warning "'-release' is ignored for convenience libraries"
+ else
+
+ # Parse the version information argument.
+ save_ifs=$IFS; IFS=:
+ set dummy $vinfo 0 0 0
+ shift
+ IFS=$save_ifs
+
+ test -n "$7" && \
+ func_fatal_help "too many parameters to '-version-info'"
+
+ # convert absolute version numbers to libtool ages
+ # this retains compatibility with .la files and attempts
+ # to make the code below a bit more comprehensible
+
+ case $vinfo_number in
+ yes)
+ number_major=$1
+ number_minor=$2
+ number_revision=$3
+ #
+ # There are really only two kinds -- those that
+ # use the current revision as the major version
+ # and those that subtract age and use age as
+ # a minor version. But, then there is irix
+ # that has an extra 1 added just for fun
+ #
+ case $version_type in
+ # correct linux to gnu/linux during the next big refactor
+ darwin|freebsd-elf|linux|midnightbsd-elf|osf|windows|none)
+ func_arith $number_major + $number_minor
+ current=$func_arith_result
+ age=$number_minor
+ revision=$number_revision
+ ;;
+ freebsd-aout|qnx|sco|sunos)
+ current=$number_major
+ revision=$number_minor
+ age=0
+ ;;
+ irix|nonstopux)
+ func_arith $number_major + $number_minor
+ current=$func_arith_result
+ age=$number_minor
+ revision=$number_minor
+ lt_irix_increment=no
+ ;;
+ esac
+ ;;
+ no)
+ current=$1
+ revision=$2
+ age=$3
+ ;;
+ esac
+
+ # Check that each of the things are valid numbers.
+ case $current in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ func_error "CURRENT '$current' must be a nonnegative integer"
+ func_fatal_error "'$vinfo' is not valid version information"
+ ;;
+ esac
+
+ case $revision in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ func_error "REVISION '$revision' must be a nonnegative integer"
+ func_fatal_error "'$vinfo' is not valid version information"
+ ;;
+ esac
+
+ case $age in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ func_error "AGE '$age' must be a nonnegative integer"
+ func_fatal_error "'$vinfo' is not valid version information"
+ ;;
+ esac
+
+ if test "$age" -gt "$current"; then
+ func_error "AGE '$age' is greater than the current interface number '$current'"
+ func_fatal_error "'$vinfo' is not valid version information"
+ fi
+
+ # Calculate the version variables.
+ major=
+ versuffix=
+ verstring=
+ case $version_type in
+ none) ;;
+
+ darwin)
+ # Like Linux, but with the current version available in
+ # verstring for coding it into the library header
+ func_arith $current - $age
+ major=.$func_arith_result
+ versuffix=$major.$age.$revision
+ # Darwin ld doesn't like 0 for these options...
+ func_arith $current + 1
+ minor_current=$func_arith_result
+ xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision"
+ verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+ # On Darwin other compilers
+ case $CC in
+ nagfor*)
+ verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision"
+ ;;
+ *)
+ verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+ ;;
+ esac
+ ;;
+
+ freebsd-aout)
+ major=.$current
+ versuffix=.$current.$revision
+ ;;
+
+ freebsd-elf | midnightbsd-elf)
+ func_arith $current - $age
+ major=.$func_arith_result
+ versuffix=$major.$age.$revision
+ ;;
+
+ irix | nonstopux)
+ if test no = "$lt_irix_increment"; then
+ func_arith $current - $age
+ else
+ func_arith $current - $age + 1
+ fi
+ major=$func_arith_result
+
+ case $version_type in
+ nonstopux) verstring_prefix=nonstopux ;;
+ *) verstring_prefix=sgi ;;
+ esac
+ verstring=$verstring_prefix$major.$revision
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$revision
+ while test 0 -ne "$loop"; do
+ func_arith $revision - $loop
+ iface=$func_arith_result
+ func_arith $loop - 1
+ loop=$func_arith_result
+ verstring=$verstring_prefix$major.$iface:$verstring
+ done
+
+ # Before this point, $major must not contain '.'.
+ major=.$major
+ versuffix=$major.$revision
+ ;;
+
+ linux) # correct to gnu/linux during the next big refactor
+ func_arith $current - $age
+ major=.$func_arith_result
+ versuffix=$major.$age.$revision
+ ;;
+
+ osf)
+ func_arith $current - $age
+ major=.$func_arith_result
+ versuffix=.$current.$age.$revision
+ verstring=$current.$age.$revision
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$age
+ while test 0 -ne "$loop"; do
+ func_arith $current - $loop
+ iface=$func_arith_result
+ func_arith $loop - 1
+ loop=$func_arith_result
+ verstring=$verstring:$iface.0
+ done
+
+ # Make executables depend on our current version.
+ func_append verstring ":$current.0"
+ ;;
+
+ qnx)
+ major=.$current
+ versuffix=.$current
+ ;;
+
+ sco)
+ major=.$current
+ versuffix=.$current
+ ;;
+
+ sunos)
+ major=.$current
+ versuffix=.$current.$revision
+ ;;
+
+ windows)
+ # Use '-' rather than '.', since we only want one
+ # extension on DOS 8.3 file systems.
+ func_arith $current - $age
+ major=$func_arith_result
+ versuffix=-$major
+ ;;
+
+ *)
+ func_fatal_configuration "unknown library version type '$version_type'"
+ ;;
+ esac
+
+ # Clear the version info if we defaulted, and they specified a release.
+ if test -z "$vinfo" && test -n "$release"; then
+ major=
+ case $version_type in
+ darwin)
+ # we can't check for "0.0" in archive_cmds due to quoting
+ # problems, so we reset it completely
+ verstring=
+ ;;
+ *)
+ verstring=0.0
+ ;;
+ esac
+ if test no = "$need_version"; then
+ versuffix=
+ else
+ versuffix=.0.0
+ fi
+ fi
+
+ # Remove version info from name if versioning should be avoided
+ if test yes,no = "$avoid_version,$need_version"; then
+ major=
+ versuffix=
+ verstring=
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test yes = "$allow_undefined"; then
+ if test unsupported = "$allow_undefined_flag"; then
+ if test yes = "$build_old_libs"; then
+ func_warning "undefined symbols not allowed in $host shared libraries; building static only"
+ build_libtool_libs=no
+ else
+ func_fatal_error "can't build $host shared library unless -no-undefined is specified"
+ fi
+ fi
+ else
+ # Don't allow undefined symbols.
+ allow_undefined_flag=$no_undefined_flag
+ fi
+
+ fi
+
+ func_generate_dlsyms "$libname" "$libname" :
+ func_append libobjs " $symfileobj"
+ test " " = "$libobjs" && libobjs=
+
+ if test relink != "$opt_mode"; then
+ # Remove our outputs, but don't remove object files since they
+ # may have been created when compiling PIC objects.
+ removelist=
+ tempremovelist=`$ECHO "$output_objdir/*"`
+ for p in $tempremovelist; do
+ case $p in
+ *.$objext | *.gcno)
+ ;;
+ $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*)
+ if test -n "$precious_files_regex"; then
+ if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+ then
+ continue
+ fi
+ fi
+ func_append removelist " $p"
+ ;;
+ *) ;;
+ esac
+ done
+ test -n "$removelist" && \
+ func_show_eval "${RM}r \$removelist"
+ fi
+
+ # Now set the variables for building old libraries.
+ if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then
+ func_append oldlibs " $output_objdir/$libname.$libext"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP`
+ fi
+
+ # Eliminate all temporary directories.
+ #for path in $notinst_path; do
+ # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"`
+ # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"`
+ # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"`
+ #done
+
+ if test -n "$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ temp_xrpath=
+ for libdir in $xrpath; do
+ func_replace_sysroot "$libdir"
+ func_append temp_xrpath " -R$func_replace_sysroot_result"
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) func_append finalize_rpath " $libdir" ;;
+ esac
+ done
+ if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then
+ dependency_libs="$temp_xrpath $dependency_libs"
+ fi
+ fi
+
+ # Make sure dlfiles contains only unique files that won't be dlpreopened
+ old_dlfiles=$dlfiles
+ dlfiles=
+ for lib in $old_dlfiles; do
+ case " $dlprefiles $dlfiles " in
+ *" $lib "*) ;;
+ *) func_append dlfiles " $lib" ;;
+ esac
+ done
+
+ # Make sure dlprefiles contains only unique files
+ old_dlprefiles=$dlprefiles
+ dlprefiles=
+ for lib in $old_dlprefiles; do
+ case "$dlprefiles " in
+ *" $lib "*) ;;
+ *) func_append dlprefiles " $lib" ;;
+ esac
+ done
+
+ if test yes = "$build_libtool_libs"; then
+ if test -n "$rpath"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*)
+ # these systems don't actually have a c library (as such)!
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C library is in the System framework
+ func_append deplibs " System.ltframework"
+ ;;
+ *-*-netbsd*)
+ # Don't link with libc until the a.out ld.so is fixed.
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-midnightbsd*)
+ # Do not include libc due to us having libc/libc_r.
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ ;;
+ *)
+ # Add libc to deplibs on all other systems if necessary.
+ if test yes = "$build_libtool_need_lc"; then
+ func_append deplibs " -lc"
+ fi
+ ;;
+ esac
+ fi
+
+ # Transform deplibs into only deplibs that can be linked in shared.
+ name_save=$name
+ libname_save=$libname
+ release_save=$release
+ versuffix_save=$versuffix
+ major_save=$major
+ # I'm not sure if I'm treating the release correctly. I think
+ # release should show up in the -l (ie -lgmp5) so we don't want to
+ # add it in twice. Is that correct?
+ release=
+ versuffix=
+ major=
+ newdeplibs=
+ droppeddeps=no
+ case $deplibs_check_method in
+ pass_all)
+ # Don't check for shared/static. Everything works.
+ # This might be a little naive. We might want to check
+ # whether the library exists or not. But this is on
+ # osf3 & osf4 and I'm not really sure... Just
+ # implementing what was already the behavior.
+ newdeplibs=$deplibs
+ ;;
+ test_compile)
+ # This code stresses the "libraries are programs" paradigm to its
+ # limits. Maybe even breaks it. We compile a program, linking it
+ # against the deplibs as a proxy for the library. Then we can check
+ # whether they linked in statically or dynamically with ldd.
+ $opt_dry_run || $RM conftest.c
+ cat > conftest.c <<EOF
+ int main() { return 0; }
+EOF
+ $opt_dry_run || $RM conftest
+ if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+ ldd_output=`ldd conftest`
+ for i in $deplibs; do
+ case $i in
+ -l*)
+ func_stripname -l '' "$i"
+ name=$func_stripname_result
+ if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ func_append newdeplibs " $i"
+ i=
+ ;;
+ esac
+ fi
+ if test -n "$i"; then
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+ set dummy $deplib_matches; shift
+ deplib_match=$1
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then
+ func_append newdeplibs " $i"
+ else
+ droppeddeps=yes
+ echo
+ $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which I believe you do not have"
+ echo "*** because a test_compile did reveal that the linker did not use it for"
+ echo "*** its dynamic dependency list that programs get resolved with at runtime."
+ fi
+ fi
+ ;;
+ *)
+ func_append newdeplibs " $i"
+ ;;
+ esac
+ done
+ else
+ # Error occurred in the first compile. Let's try to salvage
+ # the situation: Compile a separate program for each library.
+ for i in $deplibs; do
+ case $i in
+ -l*)
+ func_stripname -l '' "$i"
+ name=$func_stripname_result
+ $opt_dry_run || $RM conftest
+ if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+ ldd_output=`ldd conftest`
+ if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ func_append newdeplibs " $i"
+ i=
+ ;;
+ esac
+ fi
+ if test -n "$i"; then
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+ set dummy $deplib_matches; shift
+ deplib_match=$1
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then
+ func_append newdeplibs " $i"
+ else
+ droppeddeps=yes
+ echo
+ $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have"
+ echo "*** because a test_compile did reveal that the linker did not use this one"
+ echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+ fi
+ fi
+ else
+ droppeddeps=yes
+ echo
+ $ECHO "*** Warning! Library $i is needed by this library but I was not able to"
+ echo "*** make it link in! You will probably need to install it or some"
+ echo "*** library that it depends on before this library will be fully"
+ echo "*** functional. Installing it before continuing would be even better."
+ fi
+ ;;
+ *)
+ func_append newdeplibs " $i"
+ ;;
+ esac
+ done
+ fi
+ ;;
+ file_magic*)
+ set dummy $deplibs_check_method; shift
+ file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+ for a_deplib in $deplibs; do
+ case $a_deplib in
+ -l*)
+ func_stripname -l '' "$a_deplib"
+ name=$func_stripname_result
+ if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ func_append newdeplibs " $a_deplib"
+ a_deplib=
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib"; then
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ if test -n "$file_magic_glob"; then
+ libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob`
+ else
+ libnameglob=$libname
+ fi
+ test yes = "$want_nocaseglob" && nocaseglob=`shopt -p nocaseglob`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ if test yes = "$want_nocaseglob"; then
+ shopt -s nocaseglob
+ potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
+ $nocaseglob
+ else
+ potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
+ fi
+ for potent_lib in $potential_libs; do
+ # Follow soft links.
+ if ls -lLd "$potent_lib" 2>/dev/null |
+ $GREP " -> " >/dev/null; then
+ continue
+ fi
+ # The statement above tries to avoid entering an
+ # endless loop below, in case of cyclic links.
+ # We might still enter an endless loop, since a link
+ # loop can be closed while we follow links,
+ # but so what?
+ potlib=$potent_lib
+ while test -h "$potlib" 2>/dev/null; do
+ potliblink=`ls -ld $potlib | $SED 's/.* -> //'`
+ case $potliblink in
+ [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;;
+ *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";;
+ esac
+ done
+ if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
+ $SED -e 10q |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ func_append newdeplibs " $a_deplib"
+ a_deplib=
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib"; then
+ droppeddeps=yes
+ echo
+ $ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have"
+ echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib"; then
+ $ECHO "*** with $libname but no candidates were found. (...for file magic test)"
+ else
+ $ECHO "*** with $libname and none of the candidates passed a file format test"
+ $ECHO "*** using a file magic. Last file checked: $potlib"
+ fi
+ fi
+ ;;
+ *)
+ # Add a -L argument.
+ func_append newdeplibs " $a_deplib"
+ ;;
+ esac
+ done # Gone through all deplibs.
+ ;;
+ match_pattern*)
+ set dummy $deplibs_check_method; shift
+ match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+ for a_deplib in $deplibs; do
+ case $a_deplib in
+ -l*)
+ func_stripname -l '' "$a_deplib"
+ name=$func_stripname_result
+ if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ func_append newdeplibs " $a_deplib"
+ a_deplib=
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib"; then
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ potlib=$potent_lib # see symlink-check above in file_magic test
+ if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \
+ $EGREP "$match_pattern_regex" > /dev/null; then
+ func_append newdeplibs " $a_deplib"
+ a_deplib=
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib"; then
+ droppeddeps=yes
+ echo
+ $ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have"
+ echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib"; then
+ $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
+ else
+ $ECHO "*** with $libname and none of the candidates passed a file format test"
+ $ECHO "*** using a regex pattern. Last file checked: $potlib"
+ fi
+ fi
+ ;;
+ *)
+ # Add a -L argument.
+ func_append newdeplibs " $a_deplib"
+ ;;
+ esac
+ done # Gone through all deplibs.
+ ;;
+ none | unknown | *)
+ newdeplibs=
+ tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'`
+ if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+ for i in $predeps $postdeps; do
+ # can't use Xsed below, because $i might contain '/'
+ tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"`
+ done
+ fi
+ case $tmp_deplibs in
+ *[!\ \ ]*)
+ echo
+ if test none = "$deplibs_check_method"; then
+ echo "*** Warning: inter-library dependencies are not supported in this platform."
+ else
+ echo "*** Warning: inter-library dependencies are not known to be supported."
+ fi
+ echo "*** All declared inter-library dependencies are being dropped."
+ droppeddeps=yes
+ ;;
+ esac
+ ;;
+ esac
+ versuffix=$versuffix_save
+ major=$major_save
+ release=$release_save
+ libname=$libname_save
+ name=$name_save
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library with the System framework
+ newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'`
+ ;;
+ esac
+
+ if test yes = "$droppeddeps"; then
+ if test yes = "$module"; then
+ echo
+ echo "*** Warning: libtool could not satisfy all declared inter-library"
+ $ECHO "*** dependencies of module $libname. Therefore, libtool will create"
+ echo "*** a static module, that should work as long as the dlopening"
+ echo "*** application is linked with the -dlopen flag."
+ if test -z "$global_symbol_pipe"; then
+ echo
+ echo "*** However, this would only work if libtool was able to extract symbol"
+ echo "*** lists from a program, using 'nm' or equivalent, but libtool could"
+ echo "*** not find such a program. So, this module is probably useless."
+ echo "*** 'nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test no = "$build_old_libs"; then
+ oldlibs=$output_objdir/$libname.$libext
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ else
+ echo "*** The inter-library dependencies that have been dropped here will be"
+ echo "*** automatically added whenever a program is linked with this library"
+ echo "*** or is declared to -dlopen it."
+
+ if test no = "$allow_undefined"; then
+ echo
+ echo "*** Since this library must not contain undefined symbols,"
+ echo "*** because either the platform does not support them or"
+ echo "*** it was explicitly requested with -no-undefined,"
+ echo "*** libtool will only create a static version of it."
+ if test no = "$build_old_libs"; then
+ oldlibs=$output_objdir/$libname.$libext
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ fi
+ fi
+ # Done checking deplibs!
+ deplibs=$newdeplibs
+ fi
+ # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+ case $host in
+ *-*-darwin*)
+ newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ ;;
+ esac
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $deplibs " in
+ *" -L$path/$objdir "*)
+ func_append new_libs " -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) func_append new_libs " $deplib" ;;
+ esac
+ ;;
+ *) func_append new_libs " $deplib" ;;
+ esac
+ done
+ deplibs=$new_libs
+
+ # All the library-specific variables (install_libdir is set above).
+ library_names=
+ old_library=
+ dlname=
+
+ # Test again, we may have decided not to build it any more
+ if test yes = "$build_libtool_libs"; then
+ # Remove $wl instances when linking with ld.
+ # FIXME: should test the right _cmds variable.
+ case $archive_cmds in
+ *\$LD\ *) wl= ;;
+ esac
+ if test yes = "$hardcode_into_libs"; then
+ # Hardcode the library paths
+ hardcode_libdirs=
+ dep_rpath=
+ rpath=$finalize_rpath
+ test relink = "$opt_mode" || rpath=$compile_rpath$rpath
+ for libdir in $rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ func_replace_sysroot "$libdir"
+ libdir=$func_replace_sysroot_result
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs=$libdir
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ func_append dep_rpath " $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) func_append perm_rpath " $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir=$hardcode_libdirs
+ eval "dep_rpath=\"$hardcode_libdir_flag_spec\""
+ fi
+ if test -n "$runpath_var" && test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ func_append rpath "$dir:"
+ done
+ eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+ fi
+ test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+ fi
+
+ shlibpath=$finalize_shlibpath
+ test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath
+ if test -n "$shlibpath"; then
+ eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+ fi
+
+ # Get the real and link names of the library.
+ eval shared_ext=\"$shrext_cmds\"
+ eval library_names=\"$library_names_spec\"
+ set dummy $library_names
+ shift
+ realname=$1
+ shift
+
+ if test -n "$soname_spec"; then
+ eval soname=\"$soname_spec\"
+ else
+ soname=$realname
+ fi
+ if test -z "$dlname"; then
+ dlname=$soname
+ fi
+
+ lib=$output_objdir/$realname
+ linknames=
+ for link
+ do
+ func_append linknames " $link"
+ done
+
+ # Use standard objects if they are pic
+ test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+ test "X$libobjs" = "X " && libobjs=
+
+ delfiles=
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
+ export_symbols=$output_objdir/$libname.uexp
+ func_append delfiles " $export_symbols"
+ fi
+
+ orig_export_symbols=
+ case $host_os in
+ cygwin* | mingw* | cegcc*)
+ if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
+ # exporting using user supplied symfile
+ func_dll_def_p "$export_symbols" || {
+ # and it's NOT already a .def file. Must figure out
+ # which of the given symbols are data symbols and tag
+ # them as such. So, trigger use of export_symbols_cmds.
+ # export_symbols gets reassigned inside the "prepare
+ # the list of exported symbols" if statement, so the
+ # include_expsyms logic still works.
+ orig_export_symbols=$export_symbols
+ export_symbols=
+ always_export_symbols=yes
+ }
+ fi
+ ;;
+ esac
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then
+ func_verbose "generating symbol list for '$libname.la'"
+ export_symbols=$output_objdir/$libname.exp
+ $opt_dry_run || $RM $export_symbols
+ cmds=$export_symbols_cmds
+ save_ifs=$IFS; IFS='~'
+ for cmd1 in $cmds; do
+ IFS=$save_ifs
+ # Take the normal branch if the nm_file_list_spec branch
+ # doesn't work or if tool conversion is not needed.
+ case $nm_file_list_spec~$to_tool_file_cmd in
+ *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*)
+ try_normal_branch=yes
+ eval cmd=\"$cmd1\"
+ func_len " $cmd"
+ len=$func_len_result
+ ;;
+ *)
+ try_normal_branch=no
+ ;;
+ esac
+ if test yes = "$try_normal_branch" \
+ && { test "$len" -lt "$max_cmd_len" \
+ || test "$max_cmd_len" -le -1; }
+ then
+ func_show_eval "$cmd" 'exit $?'
+ skipped_export=false
+ elif test -n "$nm_file_list_spec"; then
+ func_basename "$output"
+ output_la=$func_basename_result
+ save_libobjs=$libobjs
+ save_output=$output
+ output=$output_objdir/$output_la.nm
+ func_to_tool_file "$output"
+ libobjs=$nm_file_list_spec$func_to_tool_file_result
+ func_append delfiles " $output"
+ func_verbose "creating $NM input file list: $output"
+ for obj in $save_libobjs; do
+ func_to_tool_file "$obj"
+ $ECHO "$func_to_tool_file_result"
+ done > "$output"
+ eval cmd=\"$cmd1\"
+ func_show_eval "$cmd" 'exit $?'
+ output=$save_output
+ libobjs=$save_libobjs
+ skipped_export=false
+ else
+ # The command line is too long to execute in one step.
+ func_verbose "using reloadable object file for export list..."
+ skipped_export=:
+ # Break out early, otherwise skipped_export may be
+ # set to false by a later but shorter cmd.
+ break
+ fi
+ done
+ IFS=$save_ifs
+ if test -n "$export_symbols_regex" && test : != "$skipped_export"; then
+ func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+ fi
+
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ tmp_export_symbols=$export_symbols
+ test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols
+ $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
+ fi
+
+ if test : != "$skipped_export" && test -n "$orig_export_symbols"; then
+ # The given exports_symbols file has to be filtered, so filter it.
+ func_verbose "filter symbol list for '$libname.la' to tag DATA exports"
+ # FIXME: $output_objdir/$libname.filter potentially contains lots of
+ # 's' commands, which not all seds can handle. GNU sed should be fine
+ # though. Also, the filter scales superlinearly with the number of
+ # global variables. join(1) would be nice here, but unfortunately
+ # isn't a blessed tool.
+ $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+ func_append delfiles " $export_symbols $output_objdir/$libname.filter"
+ export_symbols=$output_objdir/$libname.def
+ $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+ fi
+
+ tmp_deplibs=
+ for test_deplib in $deplibs; do
+ case " $convenience " in
+ *" $test_deplib "*) ;;
+ *)
+ func_append tmp_deplibs " $test_deplib"
+ ;;
+ esac
+ done
+ deplibs=$tmp_deplibs
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec" &&
+ test yes = "$compiler_needs_object" &&
+ test -z "$libobjs"; then
+ # extract the archives, so we have objects to list.
+ # TODO: could optimize this to just extract one archive.
+ whole_archive_flag_spec=
+ fi
+ if test -n "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ test "X$libobjs" = "X " && libobjs=
+ else
+ gentop=$output_objdir/${outputname}x
+ func_append generated " $gentop"
+
+ func_extract_archives $gentop $convenience
+ func_append libobjs " $func_extract_archives_result"
+ test "X$libobjs" = "X " && libobjs=
+ fi
+ fi
+
+ if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then
+ eval flag=\"$thread_safe_flag_spec\"
+ func_append linker_flags " $flag"
+ fi
+
+ # Make a backup of the uninstalled library when relinking
+ if test relink = "$opt_mode"; then
+ $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $?
+ fi
+
+ # Do each of the archive commands.
+ if test yes = "$module" && test -n "$module_cmds"; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ eval test_cmds=\"$module_expsym_cmds\"
+ cmds=$module_expsym_cmds
+ else
+ eval test_cmds=\"$module_cmds\"
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval test_cmds=\"$archive_expsym_cmds\"
+ cmds=$archive_expsym_cmds
+ else
+ eval test_cmds=\"$archive_cmds\"
+ cmds=$archive_cmds
+ fi
+ fi
+
+ if test : != "$skipped_export" &&
+ func_len " $test_cmds" &&
+ len=$func_len_result &&
+ test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ :
+ else
+ # The command line is too long to link in one step, link piecewise
+ # or, if using GNU ld and skipped_export is not :, use a linker
+ # script.
+
+ # Save the value of $output and $libobjs because we want to
+ # use them later. If we have whole_archive_flag_spec, we
+ # want to use save_libobjs as it was before
+ # whole_archive_flag_spec was expanded, because we can't
+ # assume the linker understands whole_archive_flag_spec.
+ # This may have to be revisited, in case too many
+ # convenience libraries get linked in and end up exceeding
+ # the spec.
+ if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ fi
+ save_output=$output
+ func_basename "$output"
+ output_la=$func_basename_result
+
+ # Clear the reloadable object creation command queue and
+ # initialize k to one.
+ test_cmds=
+ concat_cmds=
+ objlist=
+ last_robj=
+ k=1
+
+ if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then
+ output=$output_objdir/$output_la.lnkscript
+ func_verbose "creating GNU ld script: $output"
+ echo 'INPUT (' > $output
+ for obj in $save_libobjs
+ do
+ func_to_tool_file "$obj"
+ $ECHO "$func_to_tool_file_result" >> $output
+ done
+ echo ')' >> $output
+ func_append delfiles " $output"
+ func_to_tool_file "$output"
+ output=$func_to_tool_file_result
+ elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then
+ output=$output_objdir/$output_la.lnk
+ func_verbose "creating linker input file list: $output"
+ : > $output
+ set x $save_libobjs
+ shift
+ firstobj=
+ if test yes = "$compiler_needs_object"; then
+ firstobj="$1 "
+ shift
+ fi
+ for obj
+ do
+ func_to_tool_file "$obj"
+ $ECHO "$func_to_tool_file_result" >> $output
+ done
+ func_append delfiles " $output"
+ func_to_tool_file "$output"
+ output=$firstobj\"$file_list_spec$func_to_tool_file_result\"
+ else
+ if test -n "$save_libobjs"; then
+ func_verbose "creating reloadable object files..."
+ output=$output_objdir/$output_la-$k.$objext
+ eval test_cmds=\"$reload_cmds\"
+ func_len " $test_cmds"
+ len0=$func_len_result
+ len=$len0
+
+ # Loop over the list of objects to be linked.
+ for obj in $save_libobjs
+ do
+ func_len " $obj"
+ func_arith $len + $func_len_result
+ len=$func_arith_result
+ if test -z "$objlist" ||
+ test "$len" -lt "$max_cmd_len"; then
+ func_append objlist " $obj"
+ else
+ # The command $test_cmds is almost too long, add a
+ # command to the queue.
+ if test 1 -eq "$k"; then
+ # The first file doesn't have a previous command to add.
+ reload_objs=$objlist
+ eval concat_cmds=\"$reload_cmds\"
+ else
+ # All subsequent reloadable object files will link in
+ # the last one created.
+ reload_objs="$objlist $last_robj"
+ eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\"
+ fi
+ last_robj=$output_objdir/$output_la-$k.$objext
+ func_arith $k + 1
+ k=$func_arith_result
+ output=$output_objdir/$output_la-$k.$objext
+ objlist=" $obj"
+ func_len " $last_robj"
+ func_arith $len0 + $func_len_result
+ len=$func_arith_result
+ fi
+ done
+ # Handle the remaining objects by creating one last
+ # reloadable object file. All subsequent reloadable object
+ # files will link in the last one created.
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ reload_objs="$objlist $last_robj"
+ eval concat_cmds=\"\$concat_cmds$reload_cmds\"
+ if test -n "$last_robj"; then
+ eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
+ fi
+ func_append delfiles " $output"
+
+ else
+ output=
+ fi
+
+ ${skipped_export-false} && {
+ func_verbose "generating symbol list for '$libname.la'"
+ export_symbols=$output_objdir/$libname.exp
+ $opt_dry_run || $RM $export_symbols
+ libobjs=$output
+ # Append the command to create the export file.
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\"
+ if test -n "$last_robj"; then
+ eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
+ fi
+ }
+
+ test -n "$save_libobjs" &&
+ func_verbose "creating a temporary reloadable object file: $output"
+
+ # Loop through the commands generated above and execute them.
+ save_ifs=$IFS; IFS='~'
+ for cmd in $concat_cmds; do
+ IFS=$save_ifs
+ $opt_quiet || {
+ func_quote_arg expand,pretty "$cmd"
+ eval "func_echo $func_quote_arg_result"
+ }
+ $opt_dry_run || eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test relink = "$opt_mode"; then
+ ( cd "$output_objdir" && \
+ $RM "${realname}T" && \
+ $MV "${realname}U" "$realname" )
+ fi
+
+ exit $lt_exit
+ }
+ done
+ IFS=$save_ifs
+
+ if test -n "$export_symbols_regex" && ${skipped_export-false}; then
+ func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+
+ ${skipped_export-false} && {
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ tmp_export_symbols=$export_symbols
+ test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols
+ $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
+ fi
+
+ if test -n "$orig_export_symbols"; then
+ # The given exports_symbols file has to be filtered, so filter it.
+ func_verbose "filter symbol list for '$libname.la' to tag DATA exports"
+ # FIXME: $output_objdir/$libname.filter potentially contains lots of
+ # 's' commands, which not all seds can handle. GNU sed should be fine
+ # though. Also, the filter scales superlinearly with the number of
+ # global variables. join(1) would be nice here, but unfortunately
+ # isn't a blessed tool.
+ $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+ func_append delfiles " $export_symbols $output_objdir/$libname.filter"
+ export_symbols=$output_objdir/$libname.def
+ $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+ fi
+ }
+
+ libobjs=$output
+ # Restore the value of output.
+ output=$save_output
+
+ if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ test "X$libobjs" = "X " && libobjs=
+ fi
+ # Expand the library linking commands again to reset the
+ # value of $libobjs for piecewise linking.
+
+ # Do each of the archive commands.
+ if test yes = "$module" && test -n "$module_cmds"; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ cmds=$module_expsym_cmds
+ else
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ cmds=$archive_expsym_cmds
+ else
+ cmds=$archive_cmds
+ fi
+ fi
+ fi
+
+ if test -n "$delfiles"; then
+ # Append the command to remove temporary files to $cmds.
+ eval cmds=\"\$cmds~\$RM $delfiles\"
+ fi
+
+ # Add any objects from preloaded convenience libraries
+ if test -n "$dlprefiles"; then
+ gentop=$output_objdir/${outputname}x
+ func_append generated " $gentop"
+
+ func_extract_archives $gentop $dlprefiles
+ func_append libobjs " $func_extract_archives_result"
+ test "X$libobjs" = "X " && libobjs=
+ fi
+
+ save_ifs=$IFS; IFS='~'
+ for cmd in $cmds; do
+ IFS=$sp$nl
+ eval cmd=\"$cmd\"
+ IFS=$save_ifs
+ $opt_quiet || {
+ func_quote_arg expand,pretty "$cmd"
+ eval "func_echo $func_quote_arg_result"
+ }
+ $opt_dry_run || eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test relink = "$opt_mode"; then
+ ( cd "$output_objdir" && \
+ $RM "${realname}T" && \
+ $MV "${realname}U" "$realname" )
+ fi
+
+ exit $lt_exit
+ }
+ done
+ IFS=$save_ifs
+
+ # Restore the uninstalled library and exit
+ if test relink = "$opt_mode"; then
+ $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $?
+
+ if test -n "$convenience"; then
+ if test -z "$whole_archive_flag_spec"; then
+ func_show_eval '${RM}r "$gentop"'
+ fi
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ # Create links to the real library.
+ for linkname in $linknames; do
+ if test "$realname" != "$linkname"; then
+ func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
+ fi
+ done
+
+ # If -module or -export-dynamic was specified, set the dlname.
+ if test yes = "$module" || test yes = "$export_dynamic"; then
+ # On all known operating systems, these are identical.
+ dlname=$soname
+ fi
+ fi
+ ;;
+
+ obj)
+ if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
+ func_warning "'-dlopen' is ignored for objects"
+ fi
+
+ case " $deplibs" in
+ *\ -l* | *\ -L*)
+ func_warning "'-l' and '-L' are ignored for objects" ;;
+ esac
+
+ test -n "$rpath" && \
+ func_warning "'-rpath' is ignored for objects"
+
+ test -n "$xrpath" && \
+ func_warning "'-R' is ignored for objects"
+
+ test -n "$vinfo" && \
+ func_warning "'-version-info' is ignored for objects"
+
+ test -n "$release" && \
+ func_warning "'-release' is ignored for objects"
+
+ case $output in
+ *.lo)
+ test -n "$objs$old_deplibs" && \
+ func_fatal_error "cannot build library object '$output' from non-libtool objects"
+
+ libobj=$output
+ func_lo2o "$libobj"
+ obj=$func_lo2o_result
+ ;;
+ *)
+ libobj=
+ obj=$output
+ ;;
+ esac
+
+ # Delete the old objects.
+ $opt_dry_run || $RM $obj $libobj
+
+ # Objects from convenience libraries. This assumes
+ # single-version convenience libraries. Whenever we create
+ # different ones for PIC/non-PIC, this we'll have to duplicate
+ # the extraction.
+ reload_conv_objs=
+ gentop=
+ # if reload_cmds runs $LD directly, get rid of -Wl from
+ # whole_archive_flag_spec and hope we can get by with turning comma
+ # into space.
+ case $reload_cmds in
+ *\$LD[\ \$]*) wl= ;;
+ esac
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+ test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'`
+ reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags
+ else
+ gentop=$output_objdir/${obj}x
+ func_append generated " $gentop"
+
+ func_extract_archives $gentop $convenience
+ reload_conv_objs="$reload_objs $func_extract_archives_result"
+ fi
+ fi
+
+ # If we're not building shared, we need to use non_pic_objs
+ test yes = "$build_libtool_libs" || libobjs=$non_pic_objects
+
+ # Create the old-style object.
+ reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs
+
+ output=$obj
+ func_execute_cmds "$reload_cmds" 'exit $?'
+
+ # Exit if we aren't doing a library object file.
+ if test -z "$libobj"; then
+ if test -n "$gentop"; then
+ func_show_eval '${RM}r "$gentop"'
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ test yes = "$build_libtool_libs" || {
+ if test -n "$gentop"; then
+ func_show_eval '${RM}r "$gentop"'
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we don't
+ # accidentally link it into a program.
+ # $show "echo timestamp > $libobj"
+ # $opt_dry_run || eval "echo timestamp > $libobj" || exit $?
+ exit $EXIT_SUCCESS
+ }
+
+ if test -n "$pic_flag" || test default != "$pic_mode"; then
+ # Only do commands if we really have different PIC objects.
+ reload_objs="$libobjs $reload_conv_objs"
+ output=$libobj
+ func_execute_cmds "$reload_cmds" 'exit $?'
+ fi
+
+ if test -n "$gentop"; then
+ func_show_eval '${RM}r "$gentop"'
+ fi
+
+ exit $EXIT_SUCCESS
+ ;;
+
+ prog)
+ case $host in
+ *cygwin*) func_stripname '' '.exe' "$output"
+ output=$func_stripname_result.exe;;
+ esac
+ test -n "$vinfo" && \
+ func_warning "'-version-info' is ignored for programs"
+
+ test -n "$release" && \
+ func_warning "'-release' is ignored for programs"
+
+ $preload \
+ && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \
+ && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support."
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'`
+ finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'`
+ ;;
+ esac
+
+ case $host in
+ *-*-darwin*)
+ # Don't allow lazy linking, it breaks C++ global constructors
+ # But is supposedly fixed on 10.4 or later (yay!).
+ if test CXX = "$tagname"; then
+ case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
+ 10.[0123])
+ func_append compile_command " $wl-bind_at_load"
+ func_append finalize_command " $wl-bind_at_load"
+ ;;
+ esac
+ fi
+ # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+ compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ ;;
+ esac
+
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $compile_deplibs " in
+ *" -L$path/$objdir "*)
+ func_append new_libs " -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $compile_deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) func_append new_libs " $deplib" ;;
+ esac
+ ;;
+ *) func_append new_libs " $deplib" ;;
+ esac
+ done
+ compile_deplibs=$new_libs
+
+
+ func_append compile_command " $compile_deplibs"
+ func_append finalize_command " $finalize_deplibs"
+
+ if test -n "$rpath$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ for libdir in $rpath $xrpath; do
+ # This is the magic to use -rpath.
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) func_append finalize_rpath " $libdir" ;;
+ esac
+ done
+ fi
+
+ # Now hardcode the library paths
+ rpath=
+ hardcode_libdirs=
+ for libdir in $compile_rpath $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs=$libdir
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ func_append rpath " $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) func_append perm_rpath " $libdir" ;;
+ esac
+ fi
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+ testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'`
+ case :$dllsearchpath: in
+ *":$libdir:"*) ;;
+ ::) dllsearchpath=$libdir;;
+ *) func_append dllsearchpath ":$libdir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ ::) dllsearchpath=$testbindir;;
+ *) func_append dllsearchpath ":$testbindir";;
+ esac
+ ;;
+ esac
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir=$hardcode_libdirs
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ compile_rpath=$rpath
+
+ rpath=
+ hardcode_libdirs=
+ for libdir in $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs=$libdir
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ func_append rpath " $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$finalize_perm_rpath " in
+ *" $libdir "*) ;;
+ *) func_append finalize_perm_rpath " $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir=$hardcode_libdirs
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ finalize_rpath=$rpath
+
+ if test -n "$libobjs" && test yes = "$build_old_libs"; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+ finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+ fi
+
+ func_generate_dlsyms "$outputname" "@PROGRAM@" false
+
+ # template prelinking step
+ if test -n "$prelink_cmds"; then
+ func_execute_cmds "$prelink_cmds" 'exit $?'
+ fi
+
+ wrappers_required=:
+ case $host in
+ *cegcc* | *mingw32ce*)
+ # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway.
+ wrappers_required=false
+ ;;
+ *cygwin* | *mingw* )
+ test yes = "$build_libtool_libs" || wrappers_required=false
+ ;;
+ *)
+ if test no = "$need_relink" || test yes != "$build_libtool_libs"; then
+ wrappers_required=false
+ fi
+ ;;
+ esac
+ $wrappers_required || {
+ # Replace the output file specification.
+ compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+ link_command=$compile_command$compile_rpath
+
+ # We have no uninstalled library dependencies, so finalize right now.
+ exit_status=0
+ func_show_eval "$link_command" 'exit_status=$?'
+
+ if test -n "$postlink_cmds"; then
+ func_to_tool_file "$output"
+ postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+ func_execute_cmds "$postlink_cmds" 'exit $?'
+ fi
+
+ # Delete the generated files.
+ if test -f "$output_objdir/${outputname}S.$objext"; then
+ func_show_eval '$RM "$output_objdir/${outputname}S.$objext"'
+ fi
+
+ exit $exit_status
+ }
+
+ if test -n "$compile_shlibpath$finalize_shlibpath"; then
+ compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+ fi
+ if test -n "$finalize_shlibpath"; then
+ finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+ fi
+
+ compile_var=
+ finalize_var=
+ if test -n "$runpath_var"; then
+ if test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ func_append rpath "$dir:"
+ done
+ compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ if test -n "$finalize_perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $finalize_perm_rpath; do
+ func_append rpath "$dir:"
+ done
+ finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ fi
+
+ if test yes = "$no_install"; then
+ # We don't need to create a wrapper script.
+ link_command=$compile_var$compile_command$compile_rpath
+ # Replace the output file specification.
+ link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+ # Delete the old output file.
+ $opt_dry_run || $RM $output
+ # Link the executable and exit
+ func_show_eval "$link_command" 'exit $?'
+
+ if test -n "$postlink_cmds"; then
+ func_to_tool_file "$output"
+ postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+ func_execute_cmds "$postlink_cmds" 'exit $?'
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ case $hardcode_action,$fast_install in
+ relink,*)
+ # Fast installation is not supported
+ link_command=$compile_var$compile_command$compile_rpath
+ relink_command=$finalize_var$finalize_command$finalize_rpath
+
+ func_warning "this platform does not like uninstalled shared libraries"
+ func_warning "'$output' will be relinked during installation"
+ ;;
+ *,yes)
+ link_command=$finalize_var$compile_command$finalize_rpath
+ relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'`
+ ;;
+ *,no)
+ link_command=$compile_var$compile_command$compile_rpath
+ relink_command=$finalize_var$finalize_command$finalize_rpath
+ ;;
+ *,needless)
+ link_command=$finalize_var$compile_command$finalize_rpath
+ relink_command=
+ ;;
+ esac
+
+ # Replace the output file specification.
+ link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+ # Delete the old output files.
+ $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+ func_show_eval "$link_command" 'exit $?'
+
+ if test -n "$postlink_cmds"; then
+ func_to_tool_file "$output_objdir/$outputname"
+ postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+ func_execute_cmds "$postlink_cmds" 'exit $?'
+ fi
+
+ # Now create the wrapper script.
+ func_verbose "creating $output"
+
+ # Quote the relink command for shipping.
+ if test -n "$relink_command"; then
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ func_quote_arg pretty "$var_value"
+ relink_command="$var=$func_quote_arg_result; export $var; $relink_command"
+ fi
+ done
+ func_quote eval cd "`pwd`"
+ func_quote_arg pretty,unquoted "($func_quote_result; $relink_command)"
+ relink_command=$func_quote_arg_unquoted_result
+ fi
+
+ # Only actually do things if not in dry run mode.
+ $opt_dry_run || {
+ # win32 will think the script is a binary if it has
+ # a .exe suffix, so we strip it off here.
+ case $output in
+ *.exe) func_stripname '' '.exe' "$output"
+ output=$func_stripname_result ;;
+ esac
+ # test for cygwin because mv fails w/o .exe extensions
+ case $host in
+ *cygwin*)
+ exeext=.exe
+ func_stripname '' '.exe' "$outputname"
+ outputname=$func_stripname_result ;;
+ *) exeext= ;;
+ esac
+ case $host in
+ *cygwin* | *mingw* )
+ func_dirname_and_basename "$output" "" "."
+ output_name=$func_basename_result
+ output_path=$func_dirname_result
+ cwrappersource=$output_path/$objdir/lt-$output_name.c
+ cwrapper=$output_path/$output_name.exe
+ $RM $cwrappersource $cwrapper
+ trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+ func_emit_cwrapperexe_src > $cwrappersource
+
+ # The wrapper executable is built using the $host compiler,
+ # because it contains $host paths and files. If cross-
+ # compiling, it, like the target executable, must be
+ # executed on the $host or under an emulation environment.
+ $opt_dry_run || {
+ $LTCC $LTCFLAGS -o $cwrapper $cwrappersource
+ $STRIP $cwrapper
+ }
+
+ # Now, create the wrapper script for func_source use:
+ func_ltwrapper_scriptname $cwrapper
+ $RM $func_ltwrapper_scriptname_result
+ trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
+ $opt_dry_run || {
+ # note: this script will not be executed, so do not chmod.
+ if test "x$build" = "x$host"; then
+ $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
+ else
+ func_emit_wrapper no > $func_ltwrapper_scriptname_result
+ fi
+ }
+ ;;
+ * )
+ $RM $output
+ trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
+
+ func_emit_wrapper no > $output
+ chmod +x $output
+ ;;
+ esac
+ }
+ exit $EXIT_SUCCESS
+ ;;
+ esac
+
+ # See if we need to build an old-fashioned archive.
+ for oldlib in $oldlibs; do
+
+ case $build_libtool_libs in
+ convenience)
+ oldobjs="$libobjs_save $symfileobj"
+ addlibs=$convenience
+ build_libtool_libs=no
+ ;;
+ module)
+ oldobjs=$libobjs_save
+ addlibs=$old_convenience
+ build_libtool_libs=no
+ ;;
+ *)
+ oldobjs="$old_deplibs $non_pic_objects"
+ $preload && test -f "$symfileobj" \
+ && func_append oldobjs " $symfileobj"
+ addlibs=$old_convenience
+ ;;
+ esac
+
+ if test -n "$addlibs"; then
+ gentop=$output_objdir/${outputname}x
+ func_append generated " $gentop"
+
+ func_extract_archives $gentop $addlibs
+ func_append oldobjs " $func_extract_archives_result"
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then
+ cmds=$old_archive_from_new_cmds
+ else
+
+ # Add any objects from preloaded convenience libraries
+ if test -n "$dlprefiles"; then
+ gentop=$output_objdir/${outputname}x
+ func_append generated " $gentop"
+
+ func_extract_archives $gentop $dlprefiles
+ func_append oldobjs " $func_extract_archives_result"
+ fi
+
+ # POSIX demands no paths to be encoded in archives. We have
+ # to avoid creating archives with duplicate basenames if we
+ # might have to extract them afterwards, e.g., when creating a
+ # static archive out of a convenience library, or when linking
+ # the entirety of a libtool archive into another (currently
+ # not supported by libtool).
+ if (for obj in $oldobjs
+ do
+ func_basename "$obj"
+ $ECHO "$func_basename_result"
+ done | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ echo "copying selected object files to avoid basename conflicts..."
+ gentop=$output_objdir/${outputname}x
+ func_append generated " $gentop"
+ func_mkdir_p "$gentop"
+ save_oldobjs=$oldobjs
+ oldobjs=
+ counter=1
+ for obj in $save_oldobjs
+ do
+ func_basename "$obj"
+ objbase=$func_basename_result
+ case " $oldobjs " in
+ " ") oldobjs=$obj ;;
+ *[\ /]"$objbase "*)
+ while :; do
+ # Make sure we don't pick an alternate name that also
+ # overlaps.
+ newobj=lt$counter-$objbase
+ func_arith $counter + 1
+ counter=$func_arith_result
+ case " $oldobjs " in
+ *[\ /]"$newobj "*) ;;
+ *) if test ! -f "$gentop/$newobj"; then break; fi ;;
+ esac
+ done
+ func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+ func_append oldobjs " $gentop/$newobj"
+ ;;
+ *) func_append oldobjs " $obj" ;;
+ esac
+ done
+ fi
+ func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
+ tool_oldlib=$func_to_tool_file_result
+ eval cmds=\"$old_archive_cmds\"
+
+ func_len " $cmds"
+ len=$func_len_result
+ if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ cmds=$old_archive_cmds
+ elif test -n "$archiver_list_spec"; then
+ func_verbose "using command file archive linking..."
+ for obj in $oldobjs
+ do
+ func_to_tool_file "$obj"
+ $ECHO "$func_to_tool_file_result"
+ done > $output_objdir/$libname.libcmd
+ func_to_tool_file "$output_objdir/$libname.libcmd"
+ oldobjs=" $archiver_list_spec$func_to_tool_file_result"
+ cmds=$old_archive_cmds
+ else
+ # the command line is too long to link in one step, link in parts
+ func_verbose "using piecewise archive linking..."
+ save_RANLIB=$RANLIB
+ RANLIB=:
+ objlist=
+ concat_cmds=
+ save_oldobjs=$oldobjs
+ oldobjs=
+ # Is there a better way of finding the last object in the list?
+ for obj in $save_oldobjs
+ do
+ last_oldobj=$obj
+ done
+ eval test_cmds=\"$old_archive_cmds\"
+ func_len " $test_cmds"
+ len0=$func_len_result
+ len=$len0
+ for obj in $save_oldobjs
+ do
+ func_len " $obj"
+ func_arith $len + $func_len_result
+ len=$func_arith_result
+ func_append objlist " $obj"
+ if test "$len" -lt "$max_cmd_len"; then
+ :
+ else
+ # the above command should be used before it gets too long
+ oldobjs=$objlist
+ if test "$obj" = "$last_oldobj"; then
+ RANLIB=$save_RANLIB
+ fi
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\$concat_cmds$old_archive_cmds\"
+ objlist=
+ len=$len0
+ fi
+ done
+ RANLIB=$save_RANLIB
+ oldobjs=$objlist
+ if test -z "$oldobjs"; then
+ eval cmds=\"\$concat_cmds\"
+ else
+ eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+ fi
+ fi
+ fi
+ func_execute_cmds "$cmds" 'exit $?'
+ done
+
+ test -n "$generated" && \
+ func_show_eval "${RM}r$generated"
+
+ # Now create the libtool archive.
+ case $output in
+ *.la)
+ old_library=
+ test yes = "$build_old_libs" && old_library=$libname.$libext
+ func_verbose "creating $output"
+
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ func_quote_arg pretty,unquoted "$var_value"
+ relink_command="$var=$func_quote_arg_unquoted_result; export $var; $relink_command"
+ fi
+ done
+ # Quote the link command for shipping.
+ func_quote eval cd "`pwd`"
+ relink_command="($func_quote_result; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+ func_quote_arg pretty,unquoted "$relink_command"
+ relink_command=$func_quote_arg_unquoted_result
+ if test yes = "$hardcode_automatic"; then
+ relink_command=
+ fi
+
+ # Only create the output if not a dry run.
+ $opt_dry_run || {
+ for installed in no yes; do
+ if test yes = "$installed"; then
+ if test -z "$install_libdir"; then
+ break
+ fi
+ output=$output_objdir/${outputname}i
+ # Replace all uninstalled libtool libraries with the installed ones
+ newdependency_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ *.la)
+ func_basename "$deplib"
+ name=$func_basename_result
+ func_resolve_sysroot "$deplib"
+ eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result`
+ test -z "$libdir" && \
+ func_fatal_error "'$deplib' is not a valid libtool archive"
+ func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name"
+ ;;
+ -L*)
+ func_stripname -L '' "$deplib"
+ func_replace_sysroot "$func_stripname_result"
+ func_append newdependency_libs " -L$func_replace_sysroot_result"
+ ;;
+ -R*)
+ func_stripname -R '' "$deplib"
+ func_replace_sysroot "$func_stripname_result"
+ func_append newdependency_libs " -R$func_replace_sysroot_result"
+ ;;
+ *) func_append newdependency_libs " $deplib" ;;
+ esac
+ done
+ dependency_libs=$newdependency_libs
+ newdlfiles=
+
+ for lib in $dlfiles; do
+ case $lib in
+ *.la)
+ func_basename "$lib"
+ name=$func_basename_result
+ eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ test -z "$libdir" && \
+ func_fatal_error "'$lib' is not a valid libtool archive"
+ func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name"
+ ;;
+ *) func_append newdlfiles " $lib" ;;
+ esac
+ done
+ dlfiles=$newdlfiles
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ case $lib in
+ *.la)
+ # Only pass preopened files to the pseudo-archive (for
+ # eventual linking with the app. that links it) if we
+ # didn't already link the preopened objects directly into
+ # the library:
+ func_basename "$lib"
+ name=$func_basename_result
+ eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ test -z "$libdir" && \
+ func_fatal_error "'$lib' is not a valid libtool archive"
+ func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name"
+ ;;
+ esac
+ done
+ dlprefiles=$newdlprefiles
+ else
+ newdlfiles=
+ for lib in $dlfiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ func_append newdlfiles " $abs"
+ done
+ dlfiles=$newdlfiles
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ func_append newdlprefiles " $abs"
+ done
+ dlprefiles=$newdlprefiles
+ fi
+ $RM $output
+ # place dlname in correct position for cygwin
+ # In fact, it would be nice if we could use this code for all target
+ # systems that can't hard-code library paths into their executables
+ # and that have no shared library path variable independent of PATH,
+ # but it turns out we can't easily determine that from inspecting
+ # libtool variables, so we have to hard-code the OSs to which it
+ # applies here; at the moment, that means platforms that use the PE
+ # object format with DLL files. See the long comment at the top of
+ # tests/bindir.at for full details.
+ tdlname=$dlname
+ case $host,$output,$installed,$module,$dlname in
+ *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll)
+ # If a -bindir argument was supplied, place the dll there.
+ if test -n "$bindir"; then
+ func_relative_path "$install_libdir" "$bindir"
+ tdlname=$func_relative_path_result/$dlname
+ else
+ # Otherwise fall back on heuristic.
+ tdlname=../bin/$dlname
+ fi
+ ;;
+ esac
+ $ECHO > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM (GNU $PACKAGE) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Linker flags that cannot go in dependency_libs.
+inherited_linker_flags='$new_inherited_linker_flags'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Names of additional weak libraries provided by this library
+weak_library_names='$weak_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+ if test no,yes = "$installed,$need_relink"; then
+ $ECHO >> $output "\
+relink_command=\"$relink_command\""
+ fi
+ done
+ }
+
+ # Do a symbolic link so that the libtool archive can be found in
+ # LD_LIBRARY_PATH before the program is installed.
+ func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
+ ;;
+ esac
+ exit $EXIT_SUCCESS
+}
+
+if test link = "$opt_mode" || test relink = "$opt_mode"; then
+ func_mode_link ${1+"$@"}
+fi
+
+
+# func_mode_uninstall arg...
+func_mode_uninstall ()
+{
+ $debug_cmd
+
+ RM=$nonopt
+ files=
+ rmforce=false
+ exit_status=0
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic=$magic
+
+ for arg
+ do
+ case $arg in
+ -f) func_append RM " $arg"; rmforce=: ;;
+ -*) func_append RM " $arg" ;;
+ *) func_append files " $arg" ;;
+ esac
+ done
+
+ test -z "$RM" && \
+ func_fatal_help "you must specify an RM program"
+
+ rmdirs=
+
+ for file in $files; do
+ func_dirname "$file" "" "."
+ dir=$func_dirname_result
+ if test . = "$dir"; then
+ odir=$objdir
+ else
+ odir=$dir/$objdir
+ fi
+ func_basename "$file"
+ name=$func_basename_result
+ test uninstall = "$opt_mode" && odir=$dir
+
+ # Remember odir for removal later, being careful to avoid duplicates
+ if test clean = "$opt_mode"; then
+ case " $rmdirs " in
+ *" $odir "*) ;;
+ *) func_append rmdirs " $odir" ;;
+ esac
+ fi
+
+ # Don't error if the file doesn't exist and rm -f was used.
+ if { test -L "$file"; } >/dev/null 2>&1 ||
+ { test -h "$file"; } >/dev/null 2>&1 ||
+ test -f "$file"; then
+ :
+ elif test -d "$file"; then
+ exit_status=1
+ continue
+ elif $rmforce; then
+ continue
+ fi
+
+ rmfiles=$file
+
+ case $name in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+ if func_lalib_p "$file"; then
+ func_source $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+ for n in $library_names; do
+ func_append rmfiles " $odir/$n"
+ done
+ test -n "$old_library" && func_append rmfiles " $odir/$old_library"
+
+ case $opt_mode in
+ clean)
+ case " $library_names " in
+ *" $dlname "*) ;;
+ *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;;
+ esac
+ test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i"
+ ;;
+ uninstall)
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1'
+ fi
+
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1'
+ fi
+ # FIXME: should reinstall the best remaining shared library.
+ ;;
+ esac
+ fi
+ ;;
+
+ *.lo)
+ # Possibly a libtool object, so verify it.
+ if func_lalib_p "$file"; then
+
+ # Read the .lo file
+ func_source $dir/$name
+
+ # Add PIC object to the list of files to remove.
+ if test -n "$pic_object" && test none != "$pic_object"; then
+ func_append rmfiles " $dir/$pic_object"
+ fi
+
+ # Add non-PIC object to the list of files to remove.
+ if test -n "$non_pic_object" && test none != "$non_pic_object"; then
+ func_append rmfiles " $dir/$non_pic_object"
+ fi
+ fi
+ ;;
+
+ *)
+ if test clean = "$opt_mode"; then
+ noexename=$name
+ case $file in
+ *.exe)
+ func_stripname '' '.exe' "$file"
+ file=$func_stripname_result
+ func_stripname '' '.exe' "$name"
+ noexename=$func_stripname_result
+ # $file with .exe has already been added to rmfiles,
+ # add $file without .exe
+ func_append rmfiles " $file"
+ ;;
+ esac
+ # Do a test to see if this is a libtool program.
+ if func_ltwrapper_p "$file"; then
+ if func_ltwrapper_executable_p "$file"; then
+ func_ltwrapper_scriptname "$file"
+ relink_command=
+ func_source $func_ltwrapper_scriptname_result
+ func_append rmfiles " $func_ltwrapper_scriptname_result"
+ else
+ relink_command=
+ func_source $dir/$noexename
+ fi
+
+ # note $name still contains .exe if it was in $file originally
+ # as does the version of $file that was added into $rmfiles
+ func_append rmfiles " $odir/$name $odir/${name}S.$objext"
+ if test yes = "$fast_install" && test -n "$relink_command"; then
+ func_append rmfiles " $odir/lt-$name"
+ fi
+ if test "X$noexename" != "X$name"; then
+ func_append rmfiles " $odir/lt-$noexename.c"
+ fi
+ fi
+ fi
+ ;;
+ esac
+ func_show_eval "$RM $rmfiles" 'exit_status=1'
+ done
+
+ # Try to remove the $objdir's in the directories where we deleted files
+ for dir in $rmdirs; do
+ if test -d "$dir"; then
+ func_show_eval "rmdir $dir >/dev/null 2>&1"
+ fi
+ done
+
+ exit $exit_status
+}
+
+if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then
+ func_mode_uninstall ${1+"$@"}
+fi
+
+test -z "$opt_mode" && {
+ help=$generic_help
+ func_fatal_help "you must specify a MODE"
+}
+
+test -z "$exec_cmd" && \
+ func_fatal_help "invalid operation mode '$opt_mode'"
+
+if test -n "$exec_cmd"; then
+ eval exec "$exec_cmd"
+ exit $EXIT_FAILURE
+fi
+
+exit $exit_status
+
+
+# The TAGs below are defined such that we never get into a situation
+# where we disable both kinds of libraries. Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them. This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration. But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+build_libtool_libs=no
+build_old_libs=yes
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/scripts/mkdep.pl b/scripts/mkdep.pl
new file mode 100755
index 0000000..ebd9860
--- /dev/null
+++ b/scripts/mkdep.pl
@@ -0,0 +1,328 @@
+#!/usr/bin/env perl
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2011-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+use File::Temp qw/ :mktemp /;
+use Fcntl;
+use warnings;
+
+die "usage: $0 [--builddir=dir] [--srcdir=dir] Makefile.in ...\n" unless $#ARGV >= 0;
+
+my @incpaths;
+my %dir_vars;
+my %implicit;
+my %generated;
+my $top_builddir = ".";
+my $top_srcdir;
+
+# Check for srcdir and/or builddir, if present
+while ($ARGV[0] =~ /^--(src|build)dir=(.*)/) {
+ if ($1 eq 'src') {
+ $top_srcdir = $2;
+ } else {
+ $top_builddir = $2;
+ }
+ shift @ARGV;
+}
+chdir($top_srcdir) if defined($top_srcdir);
+
+# Read in MANIFEST or fail if not present
+my %manifest;
+die "unable to open MANIFEST: $!\n" unless open(MANIFEST, "<MANIFEST");
+while (<MANIFEST>) {
+ chomp;
+ next unless /([^\/]+\.[cly])$/;
+ $manifest{$1} = $_;
+}
+
+foreach (@ARGV) {
+ mkdep($_);
+}
+
+sub fmt_depend {
+ my ($obj, $src) = @_;
+ my $ret;
+
+ my $deps = sprintf("%s: %s %s", $obj, $src,
+ join(' ', find_depends($src)));
+ if (length($deps) > 80) {
+ my $off = 0;
+ my $indent = length($obj) + 2;
+ while (length($deps) - $off > 80 - $indent) {
+ my $pos;
+ if ($off != 0) {
+ $ret .= ' ' x $indent;
+ $pos = rindex($deps, ' ', $off + 80 - $indent - 2);
+ if ($pos <= $off) {
+ # No space found within 78 columns, check beyond
+ $pos = index($deps, ' ', $off + 80 - $indent - 2);
+ }
+ } else {
+ $pos = rindex($deps, ' ', 78);
+ }
+ $ret .= substr($deps, $off, $pos - $off) . " \\\n";
+ $off = $pos + 1;
+ }
+ $ret .= ' ' x $indent;
+ $ret .= substr($deps, $off) . "\n";
+ } else {
+ $ret = "$deps\n";
+ }
+
+ $ret;
+}
+
+sub mkdep {
+ my $file = $_[0];
+ $file =~ s:^\./+::; # strip off leading ./
+ $file =~ m:^(.*)/[^/]+$:;
+ my $srcdir = $1; # parent dir of Makefile
+
+ my $makefile;
+ if (open(MF, "<$file")) {
+ local $/; # enable "slurp" mode
+ $makefile = <MF>;
+ } else {
+ warn "$0: $file: $!\n";
+ return undef;
+ }
+ close(MF);
+
+ # New makefile, minus the autogenerated dependencies
+ my $separator = "# Autogenerated dependencies, do not modify";
+ my $new_makefile = $makefile;
+ $new_makefile =~ s/${separator}.*$//s;
+ $new_makefile .= "$separator\n";
+
+ # Old makefile, join lines with continuation characters
+ $makefile =~ s/\\\n//mg;
+
+ # Expand some configure bits
+ $makefile =~ s:\@DEV\@::g;
+ $makefile =~ s:\@COMMON_OBJS\@:aix.lo event_poll.lo event_select.lo:;
+ $makefile =~ s:\@SUDO_OBJS\@:intercept.pb-c.o openbsd.o preload.o apparmor.o selinux.o sesh.o solaris.o:;
+ $makefile =~ s:\@SUDOERS_OBJS\@:bsm_audit.lo linux_audit.lo ldap.lo ldap_util.lo ldap_conf.lo ldap_innetgr.lo solaris_audit.lo sssd.lo:;
+ # XXX - fill in AUTH_OBJS from contents of the auth dir instead
+ $makefile =~ s:\@AUTH_OBJS\@:afs.lo aix_auth.lo bsdauth.lo dce.lo fwtk.lo getspwuid.lo kerb5.lo pam.lo passwd.lo rfc1938.lo secureware.lo securid5.lo sia.lo:;
+ $makefile =~ s:\@DIGEST\@:digest.lo digest_openssl.lo digest_gcrypt.lo:;
+ $makefile =~ s:\@LTLIBOBJS\@:arc4random.lo arc4random_buf.lo arc4random_uniform.lo cfmakeraw.lo closefrom.lo dup3.lo explicit_bzero.lo fchmodat.lo fchownat.lo freezero.lo fstatat.lo fnmatch.lo getaddrinfo.lo getentropy.lo getgrouplist.lo getdelim.lo getopt_long.lo getusershell.lo glob.lo gmtime_r.lo inet_ntop_lo inet_pton.lo isblank.lo localtime_r.lo memrchr.lo mkdirat.lo mksiglist.lo mksigname.lo mktemp.lo nanosleep.lo openat.lo pipe2.lo pread.lo pwrite.lo pw_dup.lo reallocarray.lo realpath.lo sha2.lo sig2str.lo siglist.lo signame.lo snprintf.lo str2sig.lo strlcat.lo strlcpy.lo strndup.lo strnlen.lo strsignal.lo timegm.lo unlinkat.lo utimens.lo:;
+
+ # Parse OBJS lines
+ my %objs;
+ while ($makefile =~ /^[A-Z0-9_]*OBJS\s*=\s*(.*)/mg) {
+ foreach (split/\s+/, $1) {
+ next if /^\$[\(\{].*[\)\}]$/; # skip included vars for now
+ $objs{$_} = 1;
+ }
+ }
+
+ # Find include paths
+ @incpaths = ();
+ while ($makefile =~ /-I(\S+)/mg) {
+ push(@incpaths, $1) unless $1 eq ".";
+ }
+
+ # Check for generated files
+ if ($makefile =~ /GENERATED\s*=\s*(.+)$/m) {
+ foreach (split(/\s+/, $1)) {
+ $generated{$_} = 1;
+ }
+ }
+
+ # Values of srcdir, top_srcdir, top_builddir, incdir
+ %dir_vars = ();
+ $file =~ m:^(.*)/+[^/]+:;
+ $dir_vars{'srcdir'} = $1 || '.';
+ $dir_vars{'devdir'} = $dir_vars{'srcdir'};
+ $dir_vars{'authdir'} = $dir_vars{'srcdir'} . "/auth";
+ $dir_vars{'builddir'} = $top_builddir . "/" . $dir_vars{'srcdir'};
+ $dir_vars{'top_srcdir'} = $top_srcdir;
+ $dir_vars{'sudoers_srcdir'} = $top_srcdir . "/plugins/sudoers";
+ #$dir_vars{'top_builddir'} = '.';
+ $dir_vars{'incdir'} = 'include';
+
+ # Find implicit rules for generated .o and .lo files
+ %implicit = ();
+ while ($makefile =~ /^\.[ci]\.(l?o|i|plog):\s*\n\t+(.*)$/mg) {
+ $implicit{$1} = $2;
+ }
+
+ # Find existing .o and .lo dependencies
+ my %old_deps;
+ while ($makefile =~ /^(\w+\.l?o):\s*(\S+\.c)/mg) {
+ $old_deps{$1} = $2;
+ }
+
+ # Check whether static objs are disabled for .lo files
+ my $disable_static;
+ if ($makefile =~ /LTFLAGS\s*=\s*(.+)$/m) {
+ my $ltflags = $1;
+ $_ = $implicit{"lo"};
+ if (defined($_)) {
+ s/\$[\(\{]LTFLAGS[\)\}]/$ltflags/;
+ $disable_static = /--tag=disable-static/;
+ }
+ }
+
+ # Sort files so we do .lo files first
+ foreach my $obj (sort keys %objs) {
+ next unless $obj =~ /(\S+)\.(l?o)$/;
+ if (!$disable_static && $2 eq "o" && exists($objs{"$1.lo"})) {
+ # We have both .lo and .o files, only the .lo should be used
+ warn "$file: $obj should be $1.lo\n";
+ } else {
+ # Use old dependencies when mapping objects to their source.
+ # If no old dependency, use the MANIFEST file to find the source.
+ my $base = $1;
+ my $ext = $2;
+ my $src = $base . '.c';
+ if (exists $old_deps{$obj}) {
+ $src = $old_deps{$obj};
+ } elsif (exists $manifest{$src}) {
+ $src = $manifest{$src};
+ foreach (sort { length($b) <=> length($a) } keys %dir_vars) {
+ next if $_ eq "devdir";
+ last if $src =~ s:^\Q$dir_vars{$_}/\E:\$\($_\)/:;
+ }
+ } else {
+ warn "$file: unable to find source for $obj ($src) in MANIFEST\n";
+ if (-f "$srcdir/$src") {
+ $src = '$(srcdir)/' . $src;
+ }
+ }
+ my $imp = $implicit{$ext};
+ $imp =~ s/\$</$src/g;
+
+ my $deps = fmt_depend($obj, $src);
+ $new_makefile .= $deps;
+ $new_makefile .= "\t$imp\n";
+
+ # PVS Studio files (.i and .plog) but only do them once.
+ if ($ext ne "o" || !exists($objs{"$base.lo"})) {
+ $imp = $implicit{"i"};
+ if (exists $implicit{"i"} && exists $implicit{"plog"}) {
+ if ($src =~ /\.pb-c.c$/) {
+ # Do not check protobuf-c generated files
+ $obj =~ /(.*)\.[a-z]+$/;
+ $new_makefile .= "${1}.plog: ${src}\n";
+ $new_makefile .= "\ttouch \$@\n";
+ } else {
+ $imp = $implicit{"i"};
+ $deps =~ s/\.l?o/.i/;
+ $new_makefile .= $deps;
+ $new_makefile .= "\t$imp\n";
+
+ $imp = $implicit{"plog"};
+ $imp =~ s/ifile=\$<; *//;
+ $imp =~ s/\$\$\{ifile\%i\}c/$src/;
+ $obj =~ /(.*)\.[a-z]+$/;
+ $new_makefile .= "${1}.plog: ${1}.i\n";
+ $new_makefile .= "\t$imp\n";
+ }
+ }
+ }
+ }
+ }
+
+ my $newfile = $file . ".new";
+ if (!open(MF, ">$newfile")) {
+ warn("cannot open $newfile: $!\n");
+ } else {
+ print MF $new_makefile || warn("cannot write $newfile: $!\n");
+ close(MF) || warn("cannot close $newfile: $!\n");;
+ rename($newfile, $file);
+ }
+}
+
+exit(0);
+
+sub find_depends {
+ my $src = $_[0];
+ my ($deps, $code, %headers);
+
+ if ($src !~ /\//) {
+ # generated file, local to build dir
+ $src = "$dir_vars{'builddir'}/$src";
+ }
+
+ # resolve $(srcdir) etc.
+ foreach (keys %dir_vars) {
+ $src =~ s/\$[\(\{]$_[\)\}]/$dir_vars{$_}/g;
+ }
+
+ # find open source file and find headers used by it
+ if (!open(FILE, "<$src")) {
+ warn "unable to open $src\n";
+ return "";
+ }
+ local $/; # enable "slurp" mode
+ $code = <FILE>;
+ close(FILE);
+
+ # find all headers
+ while ($code =~ /^\s*#\s*include\s+["<](\S+)[">]/mg) {
+ my ($hdr, $hdr_path) = find_header($src, $1);
+ if (defined($hdr)) {
+ $headers{$hdr} = 1;
+ # Look for other includes in the .h file
+ foreach (find_depends($hdr_path)) {
+ $headers{$_} = 1;
+ }
+ }
+ }
+
+ sort keys %headers;
+}
+
+# find the path to a header file
+# returns path or undef if not found
+sub find_header {
+ my $src = $_[0];
+ my $hdr = $_[1];
+
+ # Look for .h.in files in top_builddir and build dir
+ return ("\$(top_builddir\)/$hdr", "./${hdr}.in") if -r "./${hdr}.in";
+ return ("./$hdr", "$dir_vars{'srcdir'}/${hdr}.in") if -r "$dir_vars{'srcdir'}/${hdr}.in";
+
+ if (exists $generated{$hdr}) {
+ my $hdr_path = $dir_vars{'devdir'} . '/' . $hdr;
+ return ('$(devdir)/' . $hdr, $hdr_path) if -r $hdr_path;
+ }
+ foreach my $inc (@incpaths) {
+ my $hdr_path = "$inc/$hdr";
+ # resolve variables in include path
+ foreach (keys %dir_vars) {
+ next if $_ eq "devdir";
+ $hdr_path =~ s/\$[\(\{]$_[\)\}]/$dir_vars{$_}/g;
+ }
+ return ("$inc/$hdr", $hdr_path) if -r $hdr_path;
+ }
+ # Check path relative to src dir (XXX - should be for "include" only)
+ if ($src =~ m#^(.*)/[^/]+$# && -r "$1/$hdr") {
+ my $hdr_path = "$1/$hdr";
+ $hdr_path =~ s#/[^/]+/\.\.##g; # resolve ..
+ my $hdr_pretty = $hdr_path;
+ foreach (sort { length($dir_vars{$b}) <=> length($dir_vars{$a}) } keys %dir_vars) {
+ next if $_ eq "devdir";
+ $hdr_pretty =~ s/$dir_vars{$_}/\$($_)/;
+ }
+ return ($hdr_pretty, $hdr_path);
+ }
+
+ undef;
+}
diff --git a/scripts/mkinstalldirs b/scripts/mkinstalldirs
new file mode 100755
index 0000000..0330343
--- /dev/null
+++ b/scripts/mkinstalldirs
@@ -0,0 +1,84 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+umask 022
+errstatus=0
+dirmode=""
+
+usage="\
+Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
+
+# process command line arguments
+while test $# -gt 0 ; do
+ case $1 in
+ -h | --help | --h*) # -h for help
+ echo "$usage" 1>&2
+ exit 0
+ ;;
+ -m) # -m PERM arg
+ shift
+ test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
+ dirmode=$1
+ shift
+ ;;
+ --) # stop option processing
+ shift
+ break
+ ;;
+ -*) # unknown option
+ echo "$usage" 1>&2
+ exit 1
+ ;;
+ *) # first non-opt arg
+ break
+ ;;
+ esac
+done
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case $pathcomp in
+ -*) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ else
+ if test ! -z "$dirmode"; then
+ echo "chmod $dirmode $pathcomp"
+ lasterr=""
+ chmod "$dirmode" "$pathcomp" || lasterr=$?
+
+ if test ! -z "$lasterr"; then
+ errstatus=$lasterr
+ fi
+ fi
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# End:
+# mkinstalldirs ends here
diff --git a/scripts/mkpkg b/scripts/mkpkg
new file mode 100755
index 0000000..5871dc8
--- /dev/null
+++ b/scripts/mkpkg
@@ -0,0 +1,591 @@
+#!/bin/sh
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2010-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# Build a binary package using polypkg
+# Usage: mkpkg [--build-only] [--configure-only] [--debug] [--flavor flavor]
+# [--platform platform] [--osversion ver]
+#
+
+# Make sure IFS is set to space, tab, newline in that order.
+space=' '
+tab=' '
+nl='
+'
+IFS=" $nl"
+
+# Parse arguments
+usage="usage: mkpkg [--build-only] [--configure-only] [--debug] [--flavor flavor] [--platform platform] [--osversion ver]"
+debug=0
+flavor=vanilla
+crossbuild=false
+build_packages=true;
+build_sudo=true;
+while test $# -gt 0; do
+ case "$1" in
+ --debug)
+ set -x
+ debug=1
+ PPFLAGS="--debug${PPFLAGS+$space}${PPFLAGS}"
+ ;;
+ --flavor=?*)
+ flavor=`echo "$1" | sed -n 's/^--flavor=\(.*\)/\1/p'`
+ PPVARS="${PPVARS}${PPVARS+$space}flavor=$flavor"
+ ;;
+ --flavor)
+ if [ $# -lt 2 ]; then
+ echo "$usage" 1>&2
+ exit 1
+ fi
+ flavor="$2"
+ PPVARS="${PPVARS}${PPVARS+$space}flavor=$flavor"
+ shift
+ ;;
+ --platform=?*)
+ arg=`echo "$1" | sed -n 's/^--platform=\(.*\)/\1/p'`
+ PPFLAGS="${PPFLAGS}${PPFLAGS+$space}--platform $arg"
+ ;;
+ --platform)
+ if [ $# -lt 2 ]; then
+ echo "$usage" 1>&2
+ exit 1
+ fi
+ PPFLAGS="${PPFLAGS}${PPFLAGS+$space}--platform $2"
+ shift
+ ;;
+ --osversion=?*)
+ arg=`echo "$1" | sed -n 's/^--osversion=\(.*\)/\1/p'`
+ osversion="$arg"
+ ;;
+ --osversion)
+ if [ $# -lt 2 ]; then
+ echo "$usage" 1>&2
+ exit 1
+ fi
+ osversion="$2"
+ shift
+ ;;
+ --build|--host)
+ crossbuild=true
+ configure_opts="${configure_opts}${configure_opts+$tab}$1"
+ ;;
+ --build-only)
+ build_packages=false
+ ;;
+ --configure-only)
+ build_sudo=false
+ ;;
+ *)
+ # Pass unknown options to configure
+ configure_opts="${configure_opts}${configure_opts+$tab}$1"
+ ;;
+ esac
+ shift
+done
+
+scriptdir=`dirname $0`
+configure="${scriptdir}/../configure"
+
+: ${osversion="`$scriptdir/pp --probe 2>/dev/null || echo unknown`"}
+osrelease=`echo "$osversion" | sed -e 's/^[^0-9]*//' -e 's/-.*$//'`
+: ${MAKE=make}
+
+if [ $build_packages = true -a "$osversion" = "unknown" ]; then
+ echo "unable to determine platform" 1>&2
+ exit 1
+fi
+
+# If using GNU make, set number of jobs
+if ${MAKE} --version 2>&1 | grep GNU >/dev/null; then
+ NJOBS=0
+ case "`uname`" in
+ Darwin)
+ # macOS
+ NJOBS=`sysctl -n hw.ncpu`
+ ;;
+ Linux)
+ if [ -x /usr/bin/nproc ]; then
+ NJOBS=`/usr/bin/nproc`
+ elif [ -r /proc/cpuinfo ]; then
+ NJOBS=`grep ^processor /proc/cpuinfo | wc -l`
+ fi
+ ;;
+ SunOS)
+ # Solaris
+ if [ -x /usr/sbin/psrinfo ]; then
+ NJOBS=`/usr/sbin/psrinfo | wc -l`
+ fi
+ ;;
+ HP-UX)
+ NJOBS=`sar -Mu 1 1 | awk 'END {print NR-5}'`
+ ;;
+ AIX)
+ NJOBS=`bindprocessor -q | awk '{print NF-4}'`
+ ;;
+ esac
+ if [ $NJOBS -gt 1 ]; then
+ if [ $NJOBS -gt 16 ]; then
+ NJOBS=16
+ fi
+ make_opts="-j$NJOBS"
+ fi
+fi
+
+# Choose compiler options by osversion if not cross-compiling.
+if [ "$crossbuild" = "false" ]; then
+ case "$osversion" in
+ FreeBSD*|macos*)
+ # Use clang, not gcc, on FreeBSD and macOS
+ if [ -z "$CC" ]; then
+ CC=clang; export CC
+ fi
+ ;;
+ esac
+fi
+
+# Give configure a hint that we are building a package.
+# Some libc functions are only available on certain OS revisions.
+configure_opts="${configure_opts}${configure_opts+$tab}--enable-package-build"
+
+# Some systems don't have a recent enough OpenSSL for the I/O log server.
+with_openssl=false
+
+# Not all systems have Python 3.
+with_python=false
+
+# Choose configure options by osversion.
+# We use the same configure options as vendor packages when possible.
+case "$osversion" in
+ centos*|rhel*|f[0-9]*)
+ case "$osversion" in
+ centos*|rhel*)
+ osmajor=`sed -n -e 's/^.*release \([0-9][0-9]*\).*$/\1/p' /etc/redhat-release`
+ if [ $osmajor -ge 4 ]; then
+ # RHEL 4 and up support SELinux
+ with_selinux=true
+ if [ $osmajor -ge 5 ]; then
+ # RHEL 5 and up has audit support and uses a
+ # separate PAM config file for "sudo -i".
+ with_linux_audit=true
+ with_pam_login=true
+ if [ $osmajor -ge 6 ]; then
+ # RHEL 6 and above builds sudo with SSSD support
+ with_sssd=true
+ # RHEL 6 and above use /etc/sudo-ldap.conf
+ with_sudo_ldap_conf=true
+ # Encrypted remote I/O log support.
+ with_openssl=true
+ fi
+ if [ $osmajor -ge 6 ]; then
+ # Python plugins
+ with_python=true
+ fi
+ fi
+ fi
+ ;;
+ f[0-9]*)
+ # XXX - investigate which features were in which fedora version
+ with_selinux=true
+ with_linux_audit=true
+ with_pam_login=true
+ with_sssd=true
+ with_openssl=true
+ with_python=true
+ ;;
+ esac
+
+ if [ X"$with_selinux" = X"true" ]; then
+ configure_opts="${configure_opts}${configure_opts+$tab}--with-selinux"
+ fi
+ if [ X"$with_linux_audit" = X"true" ]; then
+ configure_opts="${configure_opts}${configure_opts+$tab}--with-linux-audit"
+ PPVARS="${PPVARS}${PPVARS+$space}linux_audit=1.4.0"
+ fi
+ if [ X"$with_pam_login" = X"true" ]; then
+ configure_opts="${configure_opts}${configure_opts+$tab}--with-pam-login"
+ fi
+ if [ X"$with_sssd" = X"true" ]; then
+ configure_opts="${configure_opts}${configure_opts+$tab}--with-sssd"
+ if [ "`getconf LONG_BIT`" = "64" ]; then
+ # SSSD backend needs to know where to find the sssd lib
+ configure_opts="${configure_opts}${configure_opts+$tab}--with-sssd-lib=/usr/lib64"
+ fi
+ fi
+ if [ X"$with_sudo_ldap_conf" = X"true" ]; then
+ configure_opts="${configure_opts}${configure_opts+$tab}--with-ldap-conf-file=/etc/sudo-ldap.conf"
+ fi
+ # Note, must indent with tabs, not spaces due to IFS trickery
+ configure_opts="--prefix=/usr
+ --with-logging=syslog
+ --with-logfac=authpriv
+ --with-pam
+ --enable-zlib=system
+ --with-editor=/bin/vi
+ --with-env-editor
+ --with-ignore-dot
+ --with-ldap
+ --with-passprompt=[sudo] password for %p:
+ --with-sendmail=/usr/sbin/sendmail
+ $configure_opts"
+ ;;
+ sles*)
+ if [ $osrelease -ge 10 ]; then
+ if [ $osrelease -ge 11 ]; then
+ # SLES 11 and higher have SELinux
+ configure_opts="${configure_opts}${configure_opts+$tab}--with-selinux"
+ fi
+ if [ $osrelease -ge 12 ]; then
+ # Encrypted remote I/O log support.
+ with_openssl=true
+ # Python plugins
+ with_python=true
+ fi
+ fi
+ # SuSE doesn't have /usr/libexec
+ libexec=lib
+ case "$osversion" in
+ *64*) gcc -v 2>&1 | grep "with-cpu=[^ ]*32" >/dev/null || libexec=lib64
+ ;;
+ esac
+ # Note, must indent with tabs, not spaces due to IFS trickery
+ # XXX - SuSE uses secure path but only for env_reset
+ configure_opts="--prefix=/usr
+ --libexecdir=/usr/$libexec
+ --with-logging=syslog
+ --with-logfac=auth
+ --with-all-insults
+ --with-ignore-dot
+ --enable-shell-sets-home
+ --with-sudoers-mode=0440
+ --with-pam
+ --enable-zlib=system
+ --with-ldap
+ --with-env-editor
+ --with-passprompt=%p\'s password:
+ --with-sendmail=/usr/sbin/sendmail
+ $configure_opts"
+
+ make_opts="${make_opts}${make_opts+ }"'docdir=$(datarootdir)/doc/packages/$(PACKAGE_TARNAME)'
+ ;;
+ deb*|ubu*)
+ # Sudo-specific executables moved to /usr/libexec/sudo starting in
+ # Debian: Debian 12 (Bookworm)
+ # Ubuntu: Ubuntu 22.04 (Jammy Jellyfish)
+ # Previously, they were stored in /usr/lib/sudo.
+ libexec=lib
+
+ # AppArmor is enabled by default starting in
+ # Debian: Debian 10 (Buster)
+ # Ubuntu: Ubuntu 12.04 (Precise Pangolin)
+ osmajor=`sed -n -e 's/^VERSION_ID=\"\([0-9]*\).*$/\1/p' /etc/os-release`
+ case "$osversion" in
+ deb*)
+ if [ -z $osmajor ] || [ $osmajor -ge 10 ]; then
+ with_apparmor=true
+ fi
+ if [ -z $osmajor ] || [ $osmajor -ge 12 ]; then
+ libexec=libexec
+ fi
+ ;;
+ ubu*)
+ if [ -z $osmajor ] || [ $osmajor -ge 14 ]; then
+ with_apparmor=true
+ fi
+ if [ -z $osmajor ] || [ $osmajor -ge 22 ]; then
+ libexec=libexec
+ fi
+ ;;
+ esac
+
+ # Encrypted remote I/O log support.
+ with_openssl=true
+ # Python plugins
+ with_python=true
+ # Man pages should be compressed in .deb files
+ export MANCOMPRESS='gzip -9'
+ export MANCOMPRESSEXT='.gz'
+ # If Ubuntu, add --enable-admin-flag
+ case "$osversion" in
+ ubu*)
+ configure_opts="${configure_opts}${configure_opts+$tab}--enable-admin-flag${tab}--without-lecture"
+ ;;
+ esac
+ # Newer Debian uses arch-specific lib dirs
+ MULTIARCH=`dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null`
+ # Note, must indent with tabs, not spaces due to IFS trickery
+ if [ "$flavor" = "ldap" ]; then
+ configure_opts="${configure_opts}${configure_opts+$tab}--with-ldap
+ --with-ldap-conf-file=/etc/sudo-ldap.conf"
+ else
+ configure_opts="${configure_opts}${configure_opts+$tab}--with-sssd"
+ if [ -n "$MULTIARCH" ]; then
+ # SSSD backend needs to know where to find the sssd lib
+ configure_opts="${configure_opts}${configure_opts+$tab}--with-sssd-lib=/usr/lib/$MULTIARCH"
+ fi
+ fi
+ if [ X"$with_apparmor" = X"true" ]; then
+ configure_opts="${configure_opts}${configure_opts+$tab}--with-apparmor"
+ fi
+ configure_opts="--prefix=/usr
+ --with-all-insults
+ --with-pam
+ --enable-zlib=system
+ --with-fqdn
+ --with-logging=syslog
+ --with-logfac=authpriv
+ --with-env-editor
+ --with-editor=/usr/bin/editor
+ --with-timeout=15
+ --with-password-timeout=0
+ --with-passprompt=[sudo] password for %p:
+ --disable-root-mailer
+ --with-sendmail=/usr/sbin/sendmail
+ --mandir=/usr/share/man
+ --libexecdir=/usr/$libexec
+ --with-linux-audit
+ $configure_opts"
+ # Use correct libaudit dependency
+ for f in /lib/${MULTIARCH}${MULTIARCH:+/}libaudit.so.[0-9]* /lib/libaudit.so.[0-9]*; do
+ if [ -f "$f" ]; then
+ linux_audit=`dpkg-query -S "$f" 2>/dev/null | sed -n 's/:.*//p'`
+ test -n "$linux_audit" && break
+ fi
+ done
+ if [ -z "$linux_audit" ]; then
+ echo "unable to determine package for libaudit" 1>&2
+ exit 1
+ fi
+ PPVARS="${PPVARS}${PPVARS+$space}linux_audit=$linux_audit"
+ # Use correct libssl dependency
+ libssl_dep=`dpkg-query -S /usr/lib/${MULTIARCH}${MULTIARCH:+/}libssl.so.[1-9]* /lib/${MULTIARCH}${MULTIARCH:+/}libssl.so.[1-9]* 2>/dev/null | sort -rn | awk -F: '{ print $1; exit }'`
+ if [ -z "$libssl_dep" ]; then
+ echo "unable to determine package for libssl" 1>&2
+ exit 1
+ fi
+ PPVARS="${PPVARS}${PPVARS+$space}libssl_dep=$libssl_dep"
+ ;;
+ macos*)
+ # TODO: openssl (homebrew?)
+ case "$osversion" in
+ macos10[0-6]-i386|macos10[0-6]-x86_64)
+ # Build intel universal binaries for 10.6 and below
+ : ${ARCH_FLAGS="-arch i386 -arch x86_64"}
+ ;;
+ macos1[1-9]*)
+ # Build arm64/x86_64 universal binaries for macOS 11
+ : ${ARCH_FLAGS="-arch arm64 -arch x86_64"}
+ ;;
+ esac
+ if [ "${osversion}" != "`$scriptdir/pp --probe`" ]; then
+ sdkvers=`echo "${osversion}" | sed -e 's/^macos\([0-9][0-9]\)\([0-9]*\)-.*$/\1.\2/' -e 's/\.$//'`
+ # SDKs may be under Xcode.app or CommandLineTools (for non-Xcode)
+ if [ -d "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs" ]; then
+ SDKS="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
+ elif [ -d "/Library/Developer/CommandLineTools/SDKs" ]; then
+ SDKS="/Library/Developer/CommandLineTools/SDKs"
+ else
+ echo "unable to find macOS SDKs directory" 1>&2
+ exit 1
+ fi
+ while :; do
+ SDK_DIR="${SDKS}/MacOSX${sdkvers}.sdk"
+ if [ -d "${SDK_DIR}" ]; then
+ SDK_FLAGS="-isysroot ${SDK_DIR} -mmacosx-version-min=${sdkvers}"
+ break
+ fi
+ case "$sdkvers" in
+ *.00)
+ # Try MacOSXMM.0.sdk
+ sdkvers=${sdkvers%0}
+ ;;
+ *.0)
+ # Try MacOSXMM.sdk
+ sdkvers=${sdkvers%.0}
+ ;;
+ *)
+ echo "missing $SDK_DIR" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+ fi
+ export CFLAGS="-O2 -g $ARCH_FLAGS $SDK_FLAGS"
+ export LDFLAGS="$ARCH_FLAGS $SDK_FLAGS"
+ # Note, must indent with tabs, not spaces due to IFS trickery
+ configure_opts="--with-pam
+ --with-bsm-audit
+ --with-password-timeout=0
+ --enable-zlib=system
+ --with-ldap
+ --with-insults=disabled
+ --with-logging=syslog
+ --with-logfac=authpriv
+ --with-editor=/usr/bin/vim
+ --with-env-editor
+ $configure_opts"
+ ;;
+ aix*)
+ # TODO: openssl (AIX freeware?)
+ # Use -gxcoff with gcc instead of -g for dbx-style debugging symbols.
+ if test -z "$CC" && gcc -v >/dev/null 2>&1; then
+ CFLAGS="-O2 -gxcoff"; export CFLAGS
+ fi
+ # Note, must indent with tabs, not spaces due to IFS trickery
+ # Note: we include our own zlib instead of relying on the
+ # AIX freeware version being installed.
+ configure_opts="
+ --prefix=/opt/freeware
+ --mandir=/opt/freeware/man
+ --with-insults=disabled
+ --with-logging=syslog
+ --with-logfac=auth
+ --with-editor=/usr/bin/vi
+ --with-env-editor
+ --enable-zlib=builtin
+ --disable-nls
+ --with-sendmail=/usr/sbin/sendmail
+ $configure_opts"
+ PPVARS="${PPVARS}${PPVARS+$space}aix_freeware=true"
+ ;;
+ FreeBSD*|DragonFly*)
+ # Encrypted remote I/O log support.
+ with_openssl=true
+
+ # Python plugins
+ with_python=true
+
+ configure_opts="
+ --sysconfdir=/usr/local/etc
+ --with-ignore-dot
+ --with-tty-tickets
+ --with-env-editor
+ --with-logincap
+ --with-long-otp-prompt
+ --with-rundir=/var/run/sudo
+ --enable-zlib=system
+ --disable-nls
+ $configure_opts"
+ ;;
+ *)
+ # For Solaris, add project support and use let configure choose zlib.
+ # For all others, use the builtin zlib and disable NLS support.
+ case "$osversion" in
+ sol*)
+ configure_opts="${configure_opts}${configure_opts+$tab}--with-project"
+
+ if [ $osrelease -ge 11 ]; then
+ # Build 64-bit binaries on Solaris 11 and above.
+ case "${CC}${CFLAGS}" in
+ *-m32*|*-m64*)
+ # User specified memory model flags
+ ;;
+ *)
+ CFLAGS="${CFLAGS:--O2 -g} -m64"; export CFLAGS
+ LDFLAGS="-m64${LDFLAGS:+ }${LDFLAGS}"; export LDFLAGS
+ ;;
+ esac
+ # Solaris audit is not supported by Illumos
+ if [ X"`uname -o 2>/dev/null`" = X"illumos" ]; then
+ configure_opts="${configure_opts}${configure_opts+$tab}--with-bsm-audit"
+ else
+ configure_opts="${configure_opts}${configure_opts+$tab}--with-solaris-audit"
+ fi
+ # Encrypted remote I/O log support.
+ with_openssl=true
+ # Python plugins
+ with_python=true
+
+ # We prefer the system version of python3 to the
+ # csw one (which may be 32-bit)
+ if [ -z "$PYTHON" ]; then
+ if [ -x /usr/bin/python3 ]; then
+ PYTHON="/usr/bin/python3"; export PYTHON
+ else
+ # Sometimes the /usr/bin/python3 is missing
+ for f in /usr/bin/python3.11 /usr/bin/python3.10 /usr/bin/python3.9 /usr/bin/python3.8 /usr/bin/python3.7 /usr/bin/python3.6 /usr/bin/python3.5 /usr/bin/python3.4; do
+ if [ -x $f ]; then
+ PYTHON="$f"; export PYTHON
+ break
+ fi
+ done
+ fi
+ fi
+ fi
+ ;;
+ hpux*-ia64)
+ # Build 64-bit binaries on HP-UX ia64
+ if test -z "$CC" && gcc -v >/dev/null 2>&1; then
+ CC="gcc -mlp64"; export CC
+ fi
+ # TODO: openssl
+ configure_opts="${configure_opts}${configure_opts+$tab}--enable-zlib=builtin${tab}--disable-nls"
+ ;;
+ *)
+ # TODO: openssl
+ configure_opts="${configure_opts}${configure_opts+$tab}--enable-zlib=builtin${tab}--disable-nls"
+ ;;
+ esac
+ if [ "$flavor" = "ldap" ]; then
+ configure_opts="${configure_opts}${configure_opts+$tab}--with-ldap"
+ fi
+ # Note, must indent with tabs, not spaces due to IFS trickery
+ configure_opts="
+ --with-insults=disabled
+ --with-logging=syslog
+ --with-logfac=auth
+ --with-editor=/usr/bin/vim:/usr/bin/vi:/bin/vi
+ --with-env-editor
+ $configure_opts"
+ ;;
+esac
+
+# Don't enable OpenSSL or python if disabled by the user.
+case "$configure_opts" in
+ *--disable-openssl*) with_openssl=false;;
+esac
+case "$configure_opts" in
+ *--disable-python*) with_python=false;;
+esac
+if [ X"$with_openssl" = X"true" ]; then
+ configure_opts="${configure_opts}${configure_opts+$tab}--enable-openssl"
+fi
+if [ X"$with_python" = X"true" ]; then
+ configure_opts="${configure_opts}${configure_opts+$tab}--enable-python"
+fi
+
+# The postinstall script will create tmpfiles.d/sudo.conf for us
+configure_opts="${configure_opts}${configure_opts+$tab}--disable-tmpfiles.d"
+
+# Remove spaces from IFS when setting $@ so that passprompt may include them
+OIFS="$IFS"
+IFS=" $nl"
+set -- $configure_opts $extra_opts
+IFS="$OIFS"
+if [ -r Makefile ]; then
+ ${MAKE} $make_opts distclean
+fi
+${configure} "$@" || exit $?
+if [ $build_sudo = true ]; then
+ ${MAKE} $make_opts || exit $?
+ if [ $build_packages = true ]; then
+ ${MAKE} $make_opts PPFLAGS="$PPFLAGS" PPVARS="$PPVARS" package
+ fi
+fi
+exitval=$?
+test $debug -eq 0 && rm -rf destdir
+
+exit $exitval
diff --git a/scripts/pp b/scripts/pp
new file mode 100755
index 0000000..2a9413f
--- /dev/null
+++ b/scripts/pp
@@ -0,0 +1,9142 @@
+#!/bin/sh
+# Copyright 2023 One Identity LLC. ALL RIGHTS RESERVED
+pp_revision="20231108"
+ # Copyright 2018 One Identity LLC. ALL RIGHTS RESERVED.
+ #
+ # Redistribution and use in source and binary forms, with or without
+ # modification, are permitted provided that the following conditions
+ # are met:
+ #
+ # 1. Redistributions of source code must retain the above copyright
+ # notice, this list of conditions and the following disclaimer.
+ # 2. Redistributions in binary form must reproduce the above copyright
+ # notice, this list of conditions and the following disclaimer in the
+ # documentation and/or other materials provided with the distribution.
+ # 3. Neither the name of One Identity LLC. nor the names of its
+ # contributors may be used to endorse or promote products derived from
+ # this software without specific prior written permission.
+ #
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ # Please see <http://rc.quest.com/topics/polypkg/> for more information
+
+pp_version="1.0.0.$pp_revision"
+pp_copyright="Copyright 2018, One Identity LLC. ALL RIGHTS RESERVED."
+
+pp_opt_debug=false
+pp_opt_destdir="$DESTDIR"
+pp_opt_install_script=
+pp_opt_list=false
+pp_opt_no_clean=false
+pp_opt_no_package=false
+pp_opt_only_front=false
+pp_opt_platform=
+pp_opt_probe=false
+pp_opt_strip=false
+pp_opt_save_unstripped=false
+pp_opt_vas_platforms=false
+pp_opt_wrkdir="`pwd`/pp.work.$$"
+pp_opt_verbose=false
+pp_opt_version=false
+pp_opt_input="-"
+pp_opt_init_vars=""
+pp_opt_eval=
+
+test -n "$PP_NO_CLEAN" && pp_opt_no_clean=true
+test -n "$PP_DEBUG" && pp_opt_debug=true
+test -n "$PP_VERBOSE" && pp_opt_verbose=true
+
+pp_main_cleanup () {
+ pp_debug "main_cleanup"
+ pp_remove_later_now
+ if $pp_opt_no_clean || test x"$pp_platform" = x"unknown"; then
+ : no cleanup
+ else
+ pp_backend_${pp_platform}_cleanup
+ $pp_errors && pp_die "Errors during cleanup"
+ if test -d "$pp_wrkdir"; then
+ if $pp_opt_debug; then
+ pp_debug "not removing $pp_wrkdir"
+ else
+ pp_verbose rm -rf "$pp_wrkdir"
+ fi
+ fi
+ fi
+}
+
+pp_parseopts () {
+ typeset a n _var _val
+ while test $# -gt 0; do
+
+ # convert -[dilpv] to --long-options
+ case "$1" in
+ --?*=?*) n=`echo "$1" | sed -ne 's/^--\([^=]*\)=.*/\1/p'`
+ a=`echo "$1" | sed -ne 's/^--[^=]*=\(.*\)/\1/p'`
+ shift
+ set -- "--$n" "$a" "$@";;
+ --?*) : ;;
+
+ -d) shift; set -- "--debug" "$@";;
+ -d*) a=`echo "$1" | sed -ne 's/^-.//'`
+ shift; set -- "--debug" "$@";;
+
+ -i) shift; set -- "--install-script" "$@";;
+ -i*) a=`echo "$1" | sed -ne 's/^-.//'`
+ shift; set -- "--install-script" "$a" "$@";;
+
+ -l) shift; set -- "--list" "$@";;
+ -l*) a=`echo "$1" | sed -ne 's/^-.//'`
+ shift; set -- "--list" "$@";;
+
+ -p) shift; set -- "--platform" "$@";;
+ -p*) a=`echo "$1" | sed -ne 's/^-.//'`
+ shift; set -- "--platform" "$a" "$@";;
+
+ -v) shift; set -- "--verbose" "$@";;
+ -v*) a=`echo "$1" | sed -ne 's/^-.//'`
+ shift; set -- "--verbose" "$@";;
+
+ -\?) shift; set -- "--help" "$@";;
+ -\?*) a=`echo "$1" | sed -ne 's/^-.//'`
+ shift; set -- "--help" "$@";;
+ esac
+
+ case "$1" in
+ --destdir|--eval|--install-script|--platform|--wrkdir)
+ test $# -ge 2 || pp_error "missing argument to $1";;
+ esac
+
+ case "$1" in
+ --) shift;break;;
+ --debug) pp_opt_debug=true; shift;;
+ --destdir) pp_opt_destdir="$2"; shift;shift;;
+ --eval) pp_opt_eval="$2"; shift;shift;; # undoc
+ --install-script) pp_opt_install_script="$2"; shift;shift;;
+ --list) pp_opt_list=true; shift;;
+ --no-clean) pp_opt_no_clean=true; shift;;
+ --no-package) pp_opt_no_package=true; shift;;
+ --only-front) pp_opt_only_front=true; shift;;
+ --platform) pp_opt_platform="$2"; shift;shift;;
+ --probe) pp_opt_probe=true; shift;;
+ --strip) pp_opt_strip=true; shift;;
+ --save-unstripped) pp_opt_save_unstripped=true; shift;;
+ --wrkdir) pp_opt_wrkdir="$2"; shift;shift;;
+ --vas-platforms) pp_opt_vas_platforms=true; shift;;
+ --verbose) pp_opt_verbose=true; shift;;
+ --version) pp_opt_version=true; shift;;
+ --help) pp_errors=true; shift;;
+ -) break;;
+ -*) pp_error "unknown option $1"; shift;;
+ *) break;;
+ esac
+
+ done
+
+ pp_opt_input=-
+ if test $# -gt 0; then
+ pp_opt_input="$1"
+ shift
+ fi
+
+ #-- extra arguments of the form Foo=bar alter *global* vars
+ while test $# -gt 0; do
+ case "$1" in
+ -*) pp_error "unexpected option '$1'"
+ shift;;
+ *=*) _val="${1#*=}"
+ _var=${1%="$_val"}
+ _val=`echo "$_val"|sed -e 's/[$"\\]/\\&/g'`
+ pp_debug "setting $_var = \"$_val\""
+ pp_opt_init_vars="$pp_opt_init_vars$_var=\"$_val\";"
+ shift;;
+ *) pp_error "unexpected argument $1'"
+ shift;;
+ esac
+ done
+
+ test $# -gt 0 &&
+ pp_error "unknown argument $1"
+
+ if $pp_errors; then
+ cat <<. >&2
+polypkg $pp_version $pp_copyright
+usage: $0 [options] [input.pp] [var=value ...]
+ -d --debug -- write copious info to stderr
+ --destdir=path -- file root, defaults to \$DESTDIR
+ -? --help -- display this information
+ -i --install-script=path -- create an install helper script
+ -l --list -- write package filenames to stdout
+ --no-clean -- don't remove temporary files
+ --no-package -- do everything but create packages
+ --only-front -- only perform front-end actions
+ -p --platform=platform -- defaults to local platform
+ --probe -- print local system identifier, then exit
+ --strip -- strip debug symbols from binaries before
+ packaging (modifies files in destdir)
+ --save-unstripped -- save unstripped binaries to
+ \$name-\$version-unstripped.tar.gz
+ --wrkdir=path -- defaults to subdirectory of \$TMPDIR or /tmp
+ -v --verbose -- write info to stderr
+ --version -- display version and quit
+.
+ exit 1
+ fi
+}
+
+pp_drive () {
+ # initialise the front and back ends
+ pp_model_init
+ pp_frontend_init
+ $pp_opt_only_front || pp_backend_init
+
+ # run the front-end to generate the intermediate files
+ # set $pp_input_dir to be the 'include dir' if needed
+ pp_debug "calling frontend on $pp_opt_input"
+ case "$pp_opt_input" in
+ -) pp_input_dir=.
+ test -t 1<&0 &&
+ pp_warn "reading directives from standard input"
+ pp_frontend
+ ;;
+ */*) pp_input_dir=${pp_opt_input%/*}
+ pp_frontend <"$pp_opt_input"
+ ;;
+ *) pp_input_dir=.
+ pp_frontend <"$pp_opt_input"
+ ;;
+ esac
+
+ pp_files_ignore_others
+ pp_service_scan_groups
+
+ # some sanity checks after front-end processing
+ if test x"$pp_platform" != x"null"; then
+ pp_debug "sanity checks"
+ test -n "$pp_components" || pp_error "No components?"
+ pp_check_var_is_defined "name"
+ pp_check_var_is_defined "version"
+ pp_files_check_duplicates
+ pp_files_check_coverage
+ pp_die_if_errors "Errors during sanity checks"
+ fi
+
+ # stop now if we're only running the front
+ $pp_opt_only_front && return
+
+ if test x"$pp_opt_strip" = x"true"; then
+ pp_strip_binaries
+ fi
+
+ # run the back-end to generate the package
+ pp_debug "calling backend"
+ pp_backend
+ pp_die_if_errors "Errors during backend processing"
+
+ # copy the resulting package files to PP_PKGDESTDIR or .
+ for f in `pp_backend_names` -; do
+ test x"$f" = x"-" && continue
+ pp_debug "copying: $f to `pwd`"
+ if pp_verbose cp -r $pp_wrkdir/$f ${PP_PKGDESTDIR:-.}; then
+ echo "${PP_PKGDESTDIR:+$PP_PKGDESTDIR/}$f"
+ else
+ pp_error "$f: missing package"
+ fi
+ done
+ pp_die_if_errors "Errors during package copying"
+}
+
+pp_install_script () {
+ pp_debug "writing install script to $pp_opt_install_script"
+ rm -f $pp_opt_install_script
+ pp_backend_install_script > $pp_opt_install_script
+ pp_die_if_errors "Errors during package install script"
+ chmod +x $pp_opt_install_script
+}
+
+pp_main () {
+ # If PP_DEV_PATH is set, then jump to that script.
+ # (Useful when working on polypkg source that isn't installed)
+ if test -n "$PP_DEV_PATH" -a x"$PP_DEV_PATH" != x"$0"; then
+ pp_warn "switching from $0 to $PP_DEV_PATH ..."
+ exec "$PP_DEV_PATH" "$@" || exit 1
+ fi
+
+ pp_set_expand_converter_or_reexec "$@"
+ pp_parseopts "$@"
+
+ if $pp_opt_version; then
+ #-- print version and exit
+ echo "polypkg $pp_version"
+ exit 0
+ fi
+
+ pp_set_platform
+
+ trap 'pp_main_cleanup' 0
+
+ pp_wrkdir="$pp_opt_wrkdir"
+ pp_debug "pp_wrkdir = $pp_wrkdir"
+ rm -rf "$pp_wrkdir"
+ mkdir -p "$pp_wrkdir"
+
+ pp_destdir="$pp_opt_destdir"
+ pp_debug "pp_destdir = $pp_destdir"
+
+ if $pp_opt_probe; then
+ pp_backend_init
+ pp_backend_probe
+ elif $pp_opt_vas_platforms; then
+ pp_backend_init
+ pp_backend_vas_platforms
+ elif test -n "$pp_opt_eval"; then
+ #-- execute a shell command
+ eval "$pp_opt_eval" || exit
+ else
+ pp_drive
+ if test -n "$pp_opt_install_script"; then
+ pp_install_script
+ fi
+ fi
+
+ exit 0
+}
+
+
+pp_errors=false
+
+if test -n "$TERM" -a -t 1 && (tput op) >/dev/null 2>/dev/null; then
+ pp_col_redfg=`tput setf 4` 2>/dev/null
+ pp_col_bluefg=`tput setf 1` 2>/dev/null
+ pp_col_reset=`tput op` 2>/dev/null
+else
+ pp_col_redfg='['
+ pp_col_bluefg='['
+ pp_col_reset=']'
+fi
+
+pp__warn () {
+ if test x"" = x"$pp_lineno"; then
+ echo "$1 $2" >&2
+ else
+ echo "$1 line $pp_lineno: $2" >&2
+ fi
+}
+
+pp_warn () {
+ pp__warn "pp: ${pp_col_redfg}warning${pp_col_reset}" "$*"
+}
+
+pp_error () {
+ pp__warn "pp: ${pp_col_redfg}error${pp_col_reset}" "$*"
+ pp_errors=true
+}
+
+pp_die () {
+ pp_error "$@"
+ exit 1
+}
+
+pp_die_if_errors () {
+ $pp_errors && pp_die "$@"
+}
+
+pp_debug () {
+ $pp_opt_debug && echo "${pp_col_bluefg}debug${pp_col_reset} $*" >&2
+}
+
+pp_verbose () {
+ $pp_opt_verbose && echo "pp: ${pp_col_bluefg}info${pp_col_reset} $*" >&2
+ "$@";
+}
+
+pp_substitute () {
+ sed -e 's,%(\([^)]*\)),`\1`,g' \
+ -e 's,%{\([^}]*\)},${\1},g' \
+ -e 's,$,,' |
+ tr '' '\012' |
+ sed -e '/^[^]/s/["$`\\]/\\&/g' \
+ -e 's/^//' \
+ -e '1s/^/echo "/' \
+ -e '$s,$,",' \
+ -e 's,,"echo ",g' |
+ tr -d '\012' |
+ tr '' '\012'
+ echo
+}
+
+pp_incr () {
+ eval "$1=\`expr \$$1 + 1\`"
+}
+
+pp_decr () {
+ eval "$1=\`expr \$$1 - 1\`"
+}
+
+pp_check_var_is_defined () {
+ if eval test -z "\"\$$1\""; then
+ pp_error "\$$1: not set"
+ eval "$1=undefined"
+ fi
+}
+
+pp_contains () {
+ case " $1 " in
+ *" $2 "*) return 0;;
+ *) return 1;;
+ esac
+}
+
+pp_contains_all () {
+ typeset _s _c
+ _l="$1"; shift
+ for _w
+ do
+ pp_contains "$_l" "$_w" || return 1
+ done
+ return 0
+}
+
+pp_contains_any () {
+ typeset _s _c
+ _l="$1"; shift
+ for _w
+ do
+ pp_contains "$_l" "$_w" && return 0
+ done
+ return 1
+}
+
+pp_add_to_list () {
+ if eval test -z \"\$$1\"; then
+ eval $1='"$2"'
+ elif eval pp_contains '"$'$1'"' '"$2"'; then
+ : already there
+ else
+ eval $1='"$'$1' $2"'
+ fi
+}
+
+pp_unique () {
+ typeset result element
+ result=
+ for element
+ do
+ pp_add_to_list result $element
+ done
+ echo $result
+}
+
+pp_mode_strip_altaccess () {
+ case "$1" in
+ ??????????[+.])
+ echo `echo "$1" | cut -b -10`;;
+ *)
+ echo "$1";;
+ esac
+}
+
+pp_mode_from_ls () {
+ typeset umode gmode omode smode
+
+ set -- `pp_mode_strip_altaccess "$1"`
+
+ case "$1" in
+ ?--[-X]??????) umode=0;;
+ ?--[xs]??????) umode=1;;
+ ?-w[-X]??????) umode=2;;
+ ?-w[xs]??????) umode=3;;
+ ?r-[-X]??????) umode=4;;
+ ?r-[xs]??????) umode=5;;
+ ?rw[-X]??????) umode=6;;
+ ?rw[xs]??????) umode=7;;
+ *) pp_error "bad user mode $1";;
+ esac
+
+ case "$1" in
+ ????--[-S]???) gmode=0;;
+ ????--[xs]???) gmode=1;;
+ ????-w[-S]???) gmode=2;;
+ ????-w[xs]???) gmode=3;;
+ ????r-[-X]???) gmode=4;;
+ ????r-[xs]???) gmode=5;;
+ ????rw[-X]???) gmode=6;;
+ ????rw[xs]???) gmode=7;;
+ *) pp_error "bad group mode $1";;
+ esac
+
+ case "$1" in
+ ???????--[-T]) omode=0;;
+ ???????--[xt]) omode=1;;
+ ???????-w[-T]) omode=2;;
+ ???????-w[xt]) omode=3;;
+ ???????r-[-T]) omode=4;;
+ ???????r-[xt]) omode=5;;
+ ???????rw[-T]) omode=6;;
+ ???????rw[xt]) omode=7;;
+ *) pp_error "bad other mode $1";;
+ esac
+
+ case "$1" in
+ ???[-x]??[-x]??[-x]) smode=;;
+ ???[-x]??[-x]??[tT]) smode=1;;
+ ???[-x]??[Ss]??[-x]) smode=2;;
+ ???[-x]??[Ss]??[tT]) smode=3;;
+ ???[Ss]??[-x]??[-x]) smode=4;;
+ ???[Ss]??[-x]??[tT]) smode=5;;
+ ???[Ss]??[Ss]??[-x]) smode=6;;
+ ???[Ss]??[Ss]??[tT]) smode=7;;
+ *) pp_error "bad set-id mode $1";;
+ esac
+
+ echo "$smode$umode$gmode$omode"
+}
+
+pp_find_recurse () {
+ pp_debug "find: ${1#$pp_destdir}/"
+ for f in "$1"/.* "$1"/*; do
+ case "$f" in */.|*/..) continue;; esac # should never happen!
+ if test -d "$f" -o -f "$f" -o -h "$f"; then
+ if test -d "$f" -a ! -h "$f"; then
+ echo "${f#$pp_destdir}/"
+ pp_find_recurse "$f"
+ else
+ echo "${f#$pp_destdir}"
+ fi
+ fi
+ done
+}
+
+pp_prepend () {
+ #test -t && pp_warn "pp_prepend: stdin is a tty?"
+ if test -f $1; then
+ pp_debug "prepending to $1"
+ mv $1 $1._prepend
+ cat - $1._prepend >$1
+ rm -f $1._prepend
+ else
+ pp_debug "prepend: creating $1"
+ cat >$1
+ fi
+}
+
+pp_note_file_used() {
+ echo "$1" >> $pp_wrkdir/all.files
+}
+
+pp_create_dir_if_missing () {
+ case "$1" in
+ */) pp_error "pp_create_dir_if_missing: trailing / forbidden";;
+ "") return 0;;
+ *) if test ! -d "$pp_destdir$1"; then
+ pp_debug "fabricating directory $1/"
+ pp_create_dir_if_missing "${1%/*}"
+ mkdir "$pp_destdir$1" &&
+ pp_note_file_used "$1/"
+ pp_remove_later "$1" &&
+ chmod ${2:-755} "$pp_destdir$1"
+ fi;;
+ esac
+}
+
+pp_add_file_if_missing () {
+ typeset dir
+ #-- check that the file isn't already declared in the component
+ if test -s $pp_wrkdir/%files.${2:-run}; then
+ awk "\$6 == \"$1\" {exit 1}" < $pp_wrkdir/%files.${2:-run} || return 1
+ fi
+
+ pp_create_dir_if_missing "${1%/*}"
+ pp_debug "fabricating file $1"
+ echo "f ${3:-755} - - ${4:--} $1" >> $pp_wrkdir/%files.${2:-run}
+ pp_note_file_used "$1"
+ pp_remove_later "$1"
+ return 0
+}
+
+pp_add_transient_file () {
+ test -f "$pp_destdir$1" && pp_die "$pp_destdir$1: exists"
+ pp_create_dir_if_missing "${1%/*}"
+ pp_debug "transient file $1"
+ pp_note_file_used "$1"
+ pp_remove_later "$1"
+}
+
+pp_remove_later () {
+ {
+ echo "$1"
+ test -s $pp_wrkdir/pp_cleanup && cat $pp_wrkdir/pp_cleanup
+ } > $pp_wrkdir/pp_cleanup.new
+ mv $pp_wrkdir/pp_cleanup.new $pp_wrkdir/pp_cleanup
+}
+
+pp_ls_readlink () {
+ if test -h "$1"; then
+ ls -1ld "$1" | sed -ne 's,.* -> ,,p'
+ else
+ echo "$1: not a symbolic link" >&2
+ return 1
+ fi
+}
+
+pp_remove_later_now () {
+ typeset f
+ if test -s $pp_wrkdir/pp_cleanup; then
+ pp_debug "pp_remove_later_now"
+ while read f; do
+ pp_debug "removing $pp_destdir$f"
+ if test -d $pp_destdir$f; then
+ rmdir $pp_destdir$f
+ else
+ rm $pp_destdir$f
+ fi
+ done < $pp_wrkdir/pp_cleanup
+ rm $pp_wrkdir/pp_cleanup
+ fi
+}
+
+pp_readlink() {
+
+pp_debug "&& pp_readlink_fn=$pp_readlink_fn"
+
+ if test -n "$pp_readlink_fn"; then
+pp_debug "&& calling $pp_readlink_fn $*"
+ "$pp_readlink_fn" "$@"
+ else
+ readlink "$@"
+ fi
+}
+
+
+pp_install_script_common () {
+ cat <<-.
+
+ # Automatically generated for
+ # $name $version ($pp_platform)
+ # by PolyPackage $pp_version
+
+ usage () {
+ case "$1" in
+ "list-services")
+ echo "usage: \$0 list-services" ;;
+ "list-components")
+ echo "usage: \$0 list-components" ;;
+ "list-files")
+ echo "usage: \$0 list-files {cpt...|all}" ;;
+ "install")
+ echo "usage: \$0 install {cpt...|all}" ;;
+ "uninstall")
+ echo "usage: \$0 uninstall {cpt...|all}" ;;
+ "start")
+ echo "usage: \$0 start {svc...}" ;;
+ "stop")
+ echo "usage: \$0 stop {svc...}" ;;
+ "print-platform")
+ echo "usage: \$0 print-platform" ;;
+ *)
+ echo "usage: \$0 [-q] command [args]"
+ echo " list-services"
+ echo " list-components"
+ echo " list-files {cpt...|all}"
+ echo " install {cpt...|all}"
+ echo " uninstall {cpt...|all}"
+ echo " start {svc...}"
+ echo " stop {svc...}"
+ echo " print-platform"
+ ;;
+ esac >&2
+ exit 1
+ }
+
+ if test x"\$1" = x"-q"; then
+ shift
+ verbose () { "\$@"; }
+ verbosemsg () { : ; }
+ else
+ verbose () { echo "+ \$*"; "\$@"; }
+ verbosemsg () { echo "\$*"; }
+ fi
+.
+}
+
+
+pp_functions () {
+ typeset func deps allfuncs
+ allfuncs=
+ while test $# -gt 0; do
+ pp_add_to_list allfuncs "$1"
+ deps=`pp_backend_function "$1:depends"`
+ shift
+ set -- `pp_unique "$@" $deps`
+ done
+
+ for func in $allfuncs
+ do
+ pp_debug "generating function code for '$1'"
+ echo ""
+ echo "$func () {"
+ case "$func" in
+ pp_mkgroup|pp_mkuser|pp_havelib) echo <<.;;
+ if test \$# -lt 1; then
+ echo "$func: not enough arguments" >&2
+ return 1
+ fi
+.
+ esac
+ pp_backend_function "$func" || cat <<.
+ echo "$func: not implemented" >&2
+ return 1
+.
+ echo "}"
+ done
+}
+
+pp_function () {
+ pp_functions "$1"
+}
+
+pp_makevar () {
+ #-- convert all non alpha/digits to underscores
+ echo "$*" | tr -c '[a-z][A-Z][0-9]\012' '[_*]'
+}
+
+pp_getpwuid () {
+ awk -F: '$3 == uid { if (!found) print $1; found=1; } END { if (!found) exit 1; }' uid="$1" \
+ < /etc/passwd || pp_error "no local username for uid $1"
+}
+
+pp_getgrgid () {
+ awk -F: '$3 == gid { if (!found) print $1; found=1; } END { if (!found) exit 1; }' gid="$1" \
+ < /etc/group || pp_error "no local group for gid $1"
+}
+
+pp_backend_function_getopt () {
+ cat <<'..'
+pp_getopt () {
+ _pp_optstring="$1"; shift; eval `_pp_getopt "$_pp_optstring"`
+}
+_pp_getopt_meta=s,[\\\\\"\'\`\$\&\;\(\)\{\}\#\%\ \ ],\\\\\&,g
+_pp_protect () {
+ sed "$_pp_getopt_meta" <<. | tr '\012' ' '
+$*
+.
+}
+_pp_protect2 () {
+ sed "s,^..,,$pp_getopt_meta" <<. | tr '\012' ' '
+$*
+.
+}
+_pp_nonl () {
+ tr '\012' ' ' <<.
+$*
+.
+}
+_pp_getopt () {
+ _pp_nonl '_pp_nonl set --; while test $# -gt 0; do case "$1" in "--") shift; break;;'
+ sed 's/\([^: ]:*\)/<@<\1>@>/g;
+ s/<@<\(.\):>@>/"-\1") _pp_nonl -"\1"; _pp_protect "$2"; shift; shift;; "-\1"*) _pp_nonl -"\1"; _pp_protect2 "$1"; shift;;/g;s/<@<\(.\)>@>/ "-\1") _pp_nonl -"\1"; shift;; "-\1"*) _pp_nonl -"\1"; _pp_tmp="$1"; shift; set -- -`_pp_protect2 "$_pp_tmp"` "$@";;/g' <<.
+$1
+.
+ _pp_nonl '-*) echo "$1: unknown option">&2; return 1;; *) break;; esac; done; _pp_nonl --; while test $# -gt 0; do _pp_nonl "$1"; shift; done; echo'
+ echo
+}
+..
+}
+
+pp_copy_unstripped () {
+ typeset filedir realdir
+ filedir="`dirname ${1#$pp_destdir}`"
+ realdir="$pp_wrkdir/unstripped/$filedir"
+
+ mkdir -p "$realdir"
+ # Can't use hardlinks because `strip` modifies the original file in-place
+ cp "$1" "$realdir"
+}
+
+pp_package_stripped_binaries () {
+ (cd "$pp_wrkdir/unstripped" && tar -c .) \
+ | gzip > "$name-dbg-$version.tar.gz"
+ rm -rf "$pp_wrkdir/unstripped"
+}
+
+pp_strip_binaries () {
+ if test x"$pp_opt_save_unstripped" = x"true"; then
+ rm -rf "$pp_wrkdir/unstripped"
+ mkdir "$pp_wrkdir/unstripped"
+ fi
+
+ for f in `find "$pp_destdir" -type f`; do
+ if file "$f" | awk '{print $2}' | grep ^ELF >/dev/null 2>&1; then
+ if test x"$pp_opt_save_unstripped" = x"true"; then
+ if file "$f" | LC_MESSAGES=C grep 'not stripped' >/dev/null 2>&1; then
+ pp_debug "Saving unstripped binary $f"
+ pp_copy_unstripped "$f"
+ else
+ pp_debug "$f is already stripped; not saving a copy"
+ fi
+ fi
+ pp_debug "Stripping unnecessary symbols from $f"
+ strip "$f"
+ fi
+ done
+
+ if test x"$pp_opt_save_unstripped" = x"true"; then
+ pp_package_stripped_binaries
+ fi
+}
+
+pp_is_version_greater () {
+ smaller_version="$(echo -e "$1\n$2" | sort -V | head -1)"
+ test x"$smaller_version" = x"$1"
+}
+
+pp_if_true=0
+pp_if_false=0
+
+pp_frontend_init () {
+ name=
+ version=
+ build_number=
+ summary="no summary"
+ description="No description"
+ copyright="Copyright 2018 One Identity LLC. ALL RIGHTS RESERVED."
+
+ #-- if the user supplied extra arguments on the command line
+ # then load them now.
+ pp_debug "pp_opt_init_vars=$pp_opt_init_vars"
+ test -n "$pp_opt_init_vars" && eval "$pp_opt_init_vars"
+}
+
+pp_is_qualifier () {
+ typeset ret
+
+ case "$1" in
+ "["*"]") ret=true;;
+ *) ret=false;;
+ esac
+ pp_debug "is_qualifier: $* -> $ret"
+ test $ret = true
+}
+
+pp_eval_qualifier () {
+ typeset ret
+
+ case "$1" in
+ "[!$pp_platform]"| \
+ "[!"*",$pp_platform]"| \
+ "[!$pp_platform,"*"]"| \
+ "[!"*",$pp_platform,"*"]") ret=false;;
+ "[!"*"]") ret=true;;
+ "[$pp_platform]"| \
+ "["*",$pp_platform]"| \
+ "[$pp_platform,"*"]"| \
+ "["*",$pp_platform,"*"]") ret=true;;
+ "["*"]") ret=false;;
+ *) pp_die "pp_eval_qualifier: bad qualifier '$1'"
+ esac
+ pp_debug "eval: $* -> $ret"
+ test true = $ret
+}
+
+pp_frontend_if () {
+ typeset ifcmd ifret
+ ifcmd="$1";
+ shift
+ case "$ifcmd" in
+ %if) if test 0 = $pp_if_false; then
+ case "$*" in
+ true |1) pp_incr pp_if_true;;
+ false|0) pp_incr pp_if_false;;
+ *)
+ ifret=true
+ if pp_is_qualifier "$*"; then
+ pp_eval_qualifier "$*" || ifret=false
+ else
+ eval test "$@" || ifret=false
+ pp_debug "evaluating test $* -> $ifret"
+ fi
+ pp_incr pp_if_$ifret
+ ;;
+ esac
+ else
+ pp_incr pp_if_false
+ fi;;
+ %else) test $# = 0 || pp_warn "ignoring argument to %else"
+ if test $pp_if_false -gt 1; then
+ : no change
+ elif test $pp_if_false = 1; then
+ pp_incr pp_if_true
+ pp_decr pp_if_false
+ elif test $pp_if_true = 0; then
+ pp_die "unmatched %else"
+ else
+ pp_incr pp_if_false
+ pp_decr pp_if_true
+ fi;;
+ %endif) test $# = 0 || pp_warn "ignoring argument to %endif"
+ if test $pp_if_false -gt 0; then
+ pp_decr pp_if_false
+ elif test $pp_if_true -gt 0; then
+ pp_decr pp_if_true
+ else
+ pp_die "unmatched %endif"
+ fi;;
+ *) pp_die "frontend_if: unknown cmd $ifcmd";;
+ esac
+}
+
+
+pp_frontend () {
+ typeset section newsection sed_word sed_ws line cpt svc
+ typeset section_enabled newsection_enabled s sed sed_candidate
+
+ section='%_initial'
+ newsection='%_initial'
+ section_enabled=:
+ newsection_enabled=:
+ sed_word="[a-zA-Z_][a-zA-Z_0-9]*"
+ sed_ws="[ ]"
+
+ #-- not all seds are created equal
+ sed=
+ for sed_candidate in ${PP_SED:-sed} /usr/xpg4/bin/sed; do
+ if echo 'foo' | $sed_candidate -ne '/^\(x\)*foo/p' | grep foo > /dev/null
+ then
+ sed="$sed_candidate"
+ break
+ fi
+ done
+ test -z "$sed" &&
+ pp_die "sed is broken on this system"
+
+ pp_lineno=0
+
+ #-- Note: this sed script should perform similar to pp_eval_qualifier()
+ $sed -e "/^#/s/.*//" \
+ -e "/^\\[!\\($sed_word,\\)*$pp_platform\\(,$sed_word\\)*\\]/s/.*//" \
+ -e "s/^\\[\\($sed_word,\\)*$pp_platform\\(,$sed_word\\)*\\]$sed_ws*//" \
+ -e "s/^\\[!\\($sed_word,\\)*$sed_word\\]$sed_ws*//" \
+ -e "/^\\[\\($sed_word,\\)*$sed_word\\]/s/.*//" \
+ -e "s/^%$sed_ws*/%/" \
+ -e "s/^$sed_ws/%\\\\&/" \
+ > $pp_wrkdir/frontend.tmp
+
+ #-- add an ignore section at the end to force section completion
+ echo '%ignore' >> $pp_wrkdir/frontend.tmp
+ echo >> $pp_wrkdir/frontend.tmp
+
+ exec 0<$pp_wrkdir/frontend.tmp
+ : > $pp_wrkdir/tmp
+ : > $pp_wrkdir/%fixup
+ while read -r line; do
+ #-- Convert leading double-% to single-%, or switch sections
+ pp_incr pp_lineno
+
+ pp_debug "line $pp_lineno: $line"
+ set -f
+ set -- $line
+ set +f
+ #pp_debug "line $pp_lineno: $*"
+
+ case "$line" in %*)
+ case "$1" in
+ %if|%else|%endif)
+ pp_debug "processing if directive $1"
+ pp_frontend_if "$@"
+ continue;;
+ esac
+ test 0 -ne $pp_if_false && continue # ignore lines %if'd out
+
+ case "$1" in
+ %set|%fixup|%ignore)
+ pp_debug "processing new section $1"
+ newsection="$1"; shift
+ newsection_enabled=:
+ if pp_is_qualifier "$1"; then
+ pp_eval_qualifier "$1" || newsection_enabled=false
+ shift
+ fi
+ test $# -eq 0 || pp_warn "ignoring extra arguments: $line"
+ continue;;
+ %pre|%post|%preun|%postup|%preup|%postun|%files|%depend|%check|%conflict)
+ pp_debug "processing new component section $*"
+ s="$1"; shift
+ if test $# -eq 0 || pp_is_qualifier "$1"; then
+ cpt=run
+ else
+ cpt="$1"
+ shift
+ fi
+ newsection="$s.$cpt"
+ newsection_enabled=:
+ if test $# -gt 0 && pp_is_qualifier "$1"; then
+ pp_eval_qualifier "$1" || newsection_enabled=false
+ shift
+ fi
+ test $# -eq 0 ||
+ pp_warn "ignoring extra arguments: $line"
+ case "$cpt" in
+ run|dbg|doc|dev)
+ $newsection_enabled && pp_add_component "$cpt";;
+ x-*) :;; # useful for discarding stuff
+ *) pp_error "unknown component: $1 $cpt";;
+ esac
+ continue;;
+ %pp)
+ newsection="%ignore"; shift
+ if test $# -gt 0; then
+ pp_set_api_version "$1"
+ shift
+ else
+ pp_error "%pp: missing version"
+ fi
+ test $# -gt 0 &&
+ pp_error "%pp: too many arguments"
+ continue;;
+ %service)
+ pp_debug "processing new service section $1 $2"
+ s="$1"; shift
+ if test $# -eq 0 || pp_is_qualifier "$1"; then
+ pp_error "$s: service name required"
+ svc=unknown
+ else
+ svc="$1"; shift
+ fi
+
+ newsection="$s.$svc"
+ newsection_enabled=:
+ if test $# -gt 0 && pp_is_qualifier "$1"; then
+ pp_eval_qualifier "$1" || newsection_enabled=false
+ shift
+ fi
+ test $# -eq 0 ||
+ pp_warn "ignoring extra arguments: $line"
+ $newsection_enabled && pp_add_service "$svc"
+ continue;;
+ %\\*)
+ pp_debug "removing leading %\\"
+ line="${line#??}"
+ pp_debug " result is <$line>"
+ set -f
+ set -- $line
+ set +f
+ ;;
+ %%*)
+ pp_debug "removing leading %"
+ line="${line#%}"
+ set -f
+ set -- $line
+ set +f
+ ;;
+ %*)
+ pp_error "unknown section $1"
+ newsection='%ignore'
+ newsection_enabled=:
+ continue;;
+ esac;;
+ esac
+
+ test 0 != $pp_if_false && continue # ignore lines %if'd out
+
+ pp_debug "section=$section (enabled=$section_enabled) newsection=$newsection (enabled=$newsection_enabled)"
+
+ #-- finish processing a previous section
+ if test x"$newsection" != x""; then
+ $section_enabled && case "$section" in
+ %ignore|%_initial)
+ pp_debug "leaving ignored section $section"
+ : ignore # guaranteed to be the last section
+ ;;
+ %set)
+ pp_debug "leaving $section: sourcing $pp_wrkdir/tmp"
+ $pp_opt_debug && cat $pp_wrkdir/tmp >&2
+ . $pp_wrkdir/tmp
+ : > $pp_wrkdir/tmp
+ ;;
+ %pre.*|%preun.*|%post.*|%postup.*|%preup.*|%postun.*|%depend.*|%check.*|%conflict.*|%service.*|%fixup)
+ pp_debug "leaving $section: substituting $pp_wrkdir/tmp"
+ # cat $pp_wrkdir/tmp >&2 # debugging
+ $pp_opt_debug && pp_substitute < $pp_wrkdir/tmp >&2
+ pp_substitute < $pp_wrkdir/tmp > $pp_wrkdir/tmp.sh
+ . $pp_wrkdir/tmp.sh >> $pp_wrkdir/$section ||
+ pp_error "shell error in $section"
+ rm -f $pp_wrkdir/tmp.sh
+ : > $pp_wrkdir/tmp
+ ;;
+ esac
+ section="$newsection"
+ section_enabled="$newsection_enabled"
+ newsection=
+ fi
+
+ #-- ignore section content that is disabled
+ $section_enabled || continue
+
+ #-- process some lines in-place
+ case "$section" in
+ %_initial)
+ case "$line" in "") continue;; esac # ignore non-section blanks
+ pp_die "Ignoring text before % section introducer";;
+ %set|%pre.*|%preun.*|%post.*|%postup.*|%preup.*|%postun.*|%check.*|%service.*|%fixup)
+ pp_debug "appending line to \$pp_wrkdir/tmp"
+ echo "$line" >> $pp_wrkdir/tmp
+ ;;
+ %files.*)
+ test $# -eq 0 && continue;
+ pp_files_expand "$@" >> $pp_wrkdir/$section
+ ;;
+ %depend.*)
+ pp_debug "Adding explicit dependency $@ to $cpt"
+ echo "$@" >> $pp_wrkdir/%depend.$cpt
+ ;;
+ %conflict.*)
+ pp_debug "Adding explicit conflict $@ to $cpt"
+ echo "$@" >> $pp_wrkdir/%conflict.$cpt
+ ;;
+ esac
+ done
+ exec <&-
+
+ if test $pp_if_true != 0 -o $pp_if_false != 0; then
+ pp_die "missing %endif at end of file"
+ fi
+
+ pp_lineno=
+
+ pp_debug " name = $name"
+ pp_debug " version = $version"
+ pp_debug " summary = $summary"
+ pp_debug " description = $description"
+ pp_debug " copyright = $copyright"
+ pp_debug ""
+ pp_debug "\$pp_components: $pp_components"
+ pp_debug "\$pp_services: $pp_services"
+}
+
+pp_set_api_version() {
+ case "$1" in
+ 1.0) : ;;
+ *) pp_error "This version of polypackage is too old";;
+ esac
+}
+
+pp_platform=
+
+pp_set_platform () {
+ if test -n "$pp_opt_platform"; then
+ pp_contains "$pp_platforms" "$pp_opt_platform" ||
+ pp_die "$pp_opt_platform: unknown platform"
+ pp_platform="$pp_opt_platform"
+ else
+ uname_s=`uname -s 2>/dev/null`
+ pp_platform=
+ for p in $pp_platforms; do
+ pp_debug "probing for platform $p"
+ if eval pp_backend_${p}_detect "$uname_s"; then
+ pp_platform="$p"
+ break;
+ fi
+ done
+ test -z "$pp_platform" &&
+ pp_die "cannot detect platform (supported: $pp_platforms)"
+ fi
+ pp_debug "pp_platform = $pp_platform"
+}
+
+pp_expand_path=
+
+pp_expand_test_usr_bin () {
+ awk '$1 == "/usr" || $2 == "/usr" {usr++}
+ $1 == "/bin" || $2 == "/bin" {bin++}
+ END { if (usr == 1 && bin == 1) exit(0); else exit(1); }'
+}
+
+pp_set_expand_converter_or_reexec () {
+ test -d /usr -a -d /bin ||
+ pp_die "missing /usr or /bin"
+ echo /usr /bin | pp_expand_test_usr_bin || pp_die "pp_expand_test_usr_bin?"
+ if (eval "echo /{usr,bin}" | pp_expand_test_usr_bin) 2>/dev/null; then
+ pp_expand_path=pp_expand_path_brace
+ elif (eval "echo /@(usr|bin)" | pp_expand_test_usr_bin) 2>/dev/null; then
+ pp_expand_path=pp_expand_path_at
+ else
+ test x"$pp_expand_rexec" != x"true" ||
+ pp_die "problem finding shell that can do brace expansion"
+ for shell in bash ksh ksh93; do
+ if ($shell -c 'echo /{usr,bin}' |
+ pp_expand_test_usr_bin) 2>/dev/null ||
+ ($shell -c 'echo /@(usr|bin)' |
+ pp_expand_test_usr_bin) 2>/dev/null
+ then
+ pp_debug "switching to shell $shell"
+ pp_expand_rexec=true exec $shell "$0" "$@"
+ fi
+ done
+ pp_die "cannot find a shell that does brace expansion"
+ fi
+}
+
+pp_expand_path_brace () {
+ typeset f
+ eval "for f in $1; do echo \"\$f\"; done|sort -u"
+}
+
+pp_expand_path_at () {
+ typeset f
+ eval "for f in `
+ echo "$1" | sed -e 's/{/@(/g' -e 's/}/)/g' -e 's/,/|/g'
+ `; do echo \"\$f\"; done|sort -u"
+}
+
+pp_shlib_suffix='.so*'
+
+pp_model_init () {
+ #@ $pp_components: whitespace-delimited list of components seen in %files
+ pp_components=
+ #@ $pp_services: whitespace-delimited list of %service seen
+ pp_services=
+
+ rm -f $pp_wrkdir/%files.* \
+ $pp_wrkdir/%post.* \
+ $pp_wrkdir/%pre.* \
+ $pp_wrkdir/%preun.* \
+ $pp_wrkdir/%postup.* \
+ $pp_wrkdir/%postun.* \
+ $pp_wrkdir/%service.* \
+ $pp_wrkdir/%set \
+ $pp_wrkdir/%fixup
+}
+
+
+pp_have_component () {
+ pp_contains "$pp_components" "$1"
+}
+
+pp_have_all_components () {
+ pp_contains_all "$pp_components" "$@"
+}
+
+pp_add_component () {
+ pp_add_to_list 'pp_components' "$1"
+}
+
+pp_add_service () {
+ pp_add_to_list 'pp_services' "$1"
+}
+
+pp_service_init_vars () {
+ cmd=
+ pidfile=
+ stop_signal=15 # SIGTERM
+ user=root
+ group=
+ enable=yes # make it so the service starts on boot
+ optional=no # Whether installing this service is optional
+ pp_backend_init_svc_vars
+}
+
+pp_service_check_vars () {
+ test -n "$cmd" ||
+ pp_error "%service $1: cmd not defined"
+ case "$enable" in
+ yes|no) : ;;
+ *) pp_error "%service $1: \$enable must be set to yes or no";;
+ esac
+}
+
+pp_load_service_vars () {
+ pp_service_init_vars
+ . "$pp_wrkdir/%service.$1"
+ pp_service_check_vars "$1"
+}
+
+pp_files_expand () {
+ typeset _p _mode _group _owner _flags _path _optional _has_target _tree
+ typeset _target _file _tgt _m _o _g _f _type _lm _ll _lo _lg _ls _lx
+ typeset _ignore _a
+
+ test $# -eq 0 && return
+
+ pp_debug "pp_files_expand: path is: $1"
+
+ case "$1" in "#"*) return;; esac
+ _p="$1"; shift
+
+ pp_debug "pp_files_expand: other arguments: $*"
+
+ #-- the mode must be an octal number of at least three digits
+ _mode="="
+ _a=`eval echo \"$1\"`
+ case "$_a" in
+ *:*) :;;
+ -|=|[01234567][01234567][01234567]*) _mode="$_a"; shift;;
+ esac
+
+ #-- the owner:group field may have optional parts
+ _a=`eval echo \"$1\"`
+ case "$_a" in
+ *:*) _group=${_a#*:}; _owner=${_a%:*}; shift;;
+ =|-) _group=$_a; _owner=$_a; shift;;
+ *) _group=; _owner=;;
+ esac
+
+ #-- process the flags argument
+ _flags=
+ _target=
+ _optional=false
+ _has_target=false
+ _ignore=false
+ if test $# -gt 0; then
+ _a=`eval echo \"$1\"`
+ case ",$_a," in *,volatile,*) _flags="${_flags}v";; esac
+ case ",$_a," in *,missingok,*) _flags="${_flags}m";; esac
+ case ",$_a," in *,optional,*) _optional=true;; esac
+ case ",$_a," in *,symlink,*) _has_target=true;; esac
+ case ",$_a," in *,ignore-others,*) _flags="${_flags}i";; esac
+ case ",$_a," in *,ignore,*) _ignore=true;; esac
+ shift
+ fi
+
+ #-- process the target argument
+ if $_has_target; then
+ test $# -ne 0 || pp_error "$_p: missing target"
+ _a=`eval echo \"$1\"`
+ _target="$_a"
+ shift
+ fi
+
+ pp_debug "pp_files_expand: $_mode|$_owner:$_group|$_flags|$_target|$*"
+
+ test $# -eq 0 || pp_error "$_p: too many arguments"
+
+ #-- process speciall suffixes
+ tree=
+ case "$_p" in
+ *"/**") _p="${_p%"/**"}"; tree="**";;
+ *".%so") _p="${_p%".%so"}$pp_shlib_suffix";;
+ esac
+
+ #-- expand the path using the shell glob
+ pp_debug "expanding .$_p ... with $pp_expand_path"
+ (cd ${pp_destdir} && $pp_expand_path ".$_p") > $pp_wrkdir/tmp.files.exp
+
+ #-- expand path/** by rewriting the glob output file
+ case "$tree" in
+ "") : ;;
+ "**")
+ pp_debug "expanding /** tree ..."
+ while read _path; do
+ _path="${_path#.}"
+ pp_find_recurse "$pp_destdir${_path%/}"
+ done < $pp_wrkdir/tmp.files.exp |
+ sort -u > $pp_wrkdir/tmp.files.exp2
+ mv $pp_wrkdir/tmp.files.exp2 $pp_wrkdir/tmp.files.exp
+ ;;
+ esac
+
+ while read _path; do
+ _path="${_path#.}"
+ _file="${pp_destdir}${_path}"
+ _tgt=
+ _m="$_mode"
+ _o="${_owner:--}"
+ _g="${_group:--}"
+ _f="$_flags"
+
+ case "$_path" in
+ /*) :;;
+ *) pp_warn "$_path: inserting leading /"
+ _path="/$_path";; # ensure leading /
+ esac
+
+ #-- sanity checks
+ case "$_path" in
+ */../*|*/..) pp_error "$_path: invalid .. in path";;
+ */./*|*/.) pp_warn "$_path: invalid component . in path";;
+ *//*) pp_warn "$_path: redundant / in path";;
+ esac
+
+ #-- set the type based on the real file's type
+ if $_ignore; then
+ _type=f _m=_ _o=_ _g=_
+ elif test -h "$_file"; then
+ case "$_path" in
+ */) pp_warn "$_path (symlink $_file): removing trailing /"
+ _path="${_path%/}"
+ ;;
+ esac
+ _type=s
+ if test x"$_target" != x"=" -a -n "$_target"; then
+ _tgt="$_target"
+pp_debug "symlink target is $_tgt"
+ else
+ _tgt=`pp_readlink "$_file"`;
+ test -z "$_tgt" && pp_error "can't readlink $_file"
+ case "$_tgt" in
+ ${pp_destdir}/*)
+ pp_warn "stripped \$destdir from symlink ($_path)"
+ _tgt="${_tgt#$pp_destdir}";;
+ esac
+ fi
+ _m=777
+ elif test -d "$_file"; then
+ #-- display a warning if the user forgot the trailing /
+ case "$_path" in
+ */) :;;
+ *) pp_warn "$_path (matching $_file): adding trailing /"
+ _path="$_path/";;
+ esac
+ _type=d
+ $_has_target && pp_error "$_file: not a symlink"
+ elif test -f "$_file"; then
+ case "$_path" in
+ */) pp_warn "$_path (matching $_file): removing trailing /"
+ _path="${_path%/}"
+ ;;
+ esac
+ _type=f
+ $_has_target && pp_error "$_file: not a symlink"
+ else
+ $_optional && continue
+ pp_error "$_file: missing"
+ _type=f
+ fi
+
+ #-- convert '=' shortcuts into mode/owner/group from ls
+ case ":$_m:$_o:$_g:" in *:=:*)
+ if LS_OPTIONS=--color=never /bin/ls -ld "$_file" \
+ > $pp_wrkdir/ls.tmp
+ then
+ read _lm _ll _lo _lg _ls _lx < $pp_wrkdir/ls.tmp
+ test x"$_m" = x"=" && _m=`pp_mode_from_ls "$_lm"`
+ test x"$_o" = x"=" && _o="$_lo"
+ test x"$_g" = x"=" && _g="$_lg"
+ else
+ pp_error "cannot read $_file"
+ test x"$_m" = x"=" && _m=-
+ test x"$_o" = x"=" && _o=-
+ test x"$_g" = x"=" && _g=-
+ fi
+ ;;
+ esac
+
+ test -n "$_f" || _f=-
+
+ #-- sanity checks
+ test -n "$_type" || pp_die "_type empty"
+ test -n "$_path" || pp_die "_path empty"
+ test -n "$_m" || pp_die "_m empty"
+ test -n "$_o" || pp_die "_o empty"
+ test -n "$_g" || pp_die "_g empty"
+
+ #-- setuid/gid files must be given an explicit owner/group (or =)
+ case "$_o:$_g:$_m" in
+ -:*:[4657][1357]??|-:*:[4657]?[1357]?|-:*:[4657]??[1357])
+ pp_error "$_path: setuid file ($_m) missing explicit owner";;
+ *:-:[2367][1357]??|*:-:[2367]?[1357]?|*:-:[2367]??[1357])
+ pp_error "$_path: setgid file ($_m) missing explicit group";;
+ esac
+
+ # convert numeric uids into usernames; only works for /etc/passwd
+ case "$_o" in [0-9]*) _o=`pp_getpwuid $_o`;; esac
+ case "$_g" in [0-9]*) _g=`pp_getgrgid $_g`;; esac
+
+ pp_debug "$_type $_m $_o $_g $_f $_path" $_tgt
+ $_ignore || echo "$_type $_m $_o $_g $_f $_path" $_tgt
+ pp_note_file_used "$_path"
+ case "$_f" in *i*) echo "$_path" >> $pp_wrkdir/ign.files;; esac
+ done < $pp_wrkdir/tmp.files.exp
+}
+
+pp_files_check_duplicates () {
+ typeset _path
+ if test -s $pp_wrkdir/all.files; then
+ sort < $pp_wrkdir/all.files | uniq -d > $pp_wrkdir/duplicate.files
+ if test -f $pp_wrkdir/ign.awk; then
+ # Remove ignored files
+ mv $pp_wrkdir/duplicate.files $pp_wrkdir/duplicate.files.ign
+ sed -e 's/^/_ _ _ _ _ /' < $pp_wrkdir/duplicate.files.ign |
+ awk -f $pp_wrkdir/ign.awk |
+ sed -e 's/^_ _ _ _ _ //' > $pp_wrkdir/duplicate.files
+ fi
+ while read _path; do
+ pp_warn "$_path: file declared more than once"
+ done <$pp_wrkdir/duplicate.files
+ fi
+}
+
+pp_files_check_coverage () {
+ pp_find_recurse "$pp_destdir" | sort > $pp_wrkdir/coverage.avail
+ if test -s $pp_wrkdir/all.files; then
+ sort -u < $pp_wrkdir/all.files
+ else
+ :
+ fi > $pp_wrkdir/coverage.used
+ join -v1 $pp_wrkdir/coverage.avail $pp_wrkdir/coverage.used \
+ > $pp_wrkdir/coverage.not-packaged
+ if test -s $pp_wrkdir/coverage.not-packaged; then
+ pp_warn "The following files/directories were found but not packaged:"
+ sed -e 's,^, ,' < $pp_wrkdir/coverage.not-packaged >&2
+ fi
+ join -v2 $pp_wrkdir/coverage.avail $pp_wrkdir/coverage.used \
+ > $pp_wrkdir/coverage.not-avail
+ if test -s $pp_wrkdir/coverage.not-avail; then
+ pp_warn "The following files/directories were named but not found:"
+ sed -e 's,^, ,' < $pp_wrkdir/coverage.not-avail >&2
+ fi
+}
+
+pp_files_ignore_others () {
+ typeset p f
+
+ test -s $pp_wrkdir/ign.files || return
+
+ #-- for each file in ign.files, we remove it from all the
+ # other %files.* lists, except where it has an i flag.
+ # rather than scan each list multiple times, we build
+ # an awk script
+
+ pp_debug "stripping ignore files"
+
+ while read p; do
+ echo '$6 == "'"$p"'" && $5 !~ /i/ { next }'
+ done < $pp_wrkdir/ign.files > $pp_wrkdir/ign.awk
+ echo '{ print }' >> $pp_wrkdir/ign.awk
+
+ $pp_opt_debug && cat $pp_wrkdir/ign.awk
+
+ for f in $pp_wrkdir/%files.*; do
+ mv $f $f.ign
+ awk -f $pp_wrkdir/ign.awk < $f.ign > $f || pp_error "awk"
+ done
+}
+
+pp_service_scan_groups () {
+ typeset svc
+
+ #-- scan for "group" commands, and build a list of groups
+ pp_service_groups=
+ if test -n "$pp_services"; then
+ for svc in $pp_services; do
+ group=
+ . $pp_wrkdir/%service.$svc
+ if test -n "$group"; then
+ pp_contains "$pp_services" "$group" && pp_error \
+ "%service $svc: group name $group in use by a service"
+ pp_add_to_list 'pp_service_groups' "$group"
+ echo "$svc" >> $pp_wrkdir/%svcgrp.$group
+ fi
+ done
+ fi
+}
+
+pp_service_get_svc_group () {
+ (tr '\012' ' ' < $pp_wrkdir/%svcgrp.$1 ; echo) | sed -e 's/ $//'
+}
+
+for _sufx in _init '' _names _cleanup _install_script \
+ _init_svc_vars _function _probe _vas_platforms
+do
+ eval "pp_backend$_sufx () { pp_debug pp_backend$_sufx; pp_backend_\${pp_platform}$_sufx \"\$@\"; }"
+done
+
+
+pp_platforms="$pp_platforms aix"
+
+pp_backend_aix_detect () {
+ test x"$1" = x"AIX"
+}
+
+pp_backend_aix_init () {
+ pp_aix_detect_arch
+ pp_aix_detect_os
+
+ pp_aix_bosboot= # components that need bosboot
+ pp_aix_lang=en_US
+ pp_aix_copyright=
+ pp_aix_start_services_after_install=false
+ pp_aix_init_services_after_install=true
+
+ pp_aix_sudo=sudo # AIX package tools must run as root
+
+ case "$pp_aix_os" in
+ *) pp_readlink_fn=pp_ls_readlink;; # XXX
+ esac
+
+ pp_aix_abis_seen=
+}
+
+pp_aix_detect_arch () {
+ pp_aix_arch_p=`uname -p 2>/dev/null`
+ case "$pp_aix_arch_p" in
+ "") pp_debug "can't get processor type from uname -p"
+ pp_aix_arch_p=powerpc
+ pp_aix_arch=R;; # guess (lsattr -l proc0 ??)
+ powerpc) pp_aix_arch=R;;
+ *) pp_aix_arch_p=intel
+ pp_aix_arch=I;; # XXX? verify
+ esac
+
+ case "`/usr/sbin/lsattr -El proc0 -a type -F value`" in
+ PowerPC_POWER*) pp_aix_arch_std=ppc64;;
+ PowerPC*) pp_aix_arch_std=ppc;;
+ *) pp_aix_arch_std=unknown;;
+ esac
+}
+
+pp_aix_detect_os () {
+ typeset r v
+
+ r=`uname -r`
+ v=`uname -v`
+ pp_aix_os=aix$v$r
+}
+
+pp_aix_version_fix () {
+ typeset v
+ v=`echo $1 | sed 's/[-+]/./' | tr -c -d '[0-9].\012' | awk -F"." '{ printf "%d.%d.%d.%.4s\n", $1, $2, $3, $4 }' | sed 's/[.]*$//g'`
+ if test x"$v" != x"$1"; then
+ pp_warn "stripped version '$1' to '$v'"
+ fi
+ case $v in
+ ""|*..*|.*|*.) pp_error "malformed '$1'"
+ echo "0.0.0.0";;
+ *.*.*.*.*)
+ # 5 components are only valid for fileset updates, not base
+ # filesets (full packages). We trim 5+ components down to 4.
+ pp_warn "version '$1' has too many dots for AIX, truncating"
+ echo "$v" | cut -d. -f1-4;;
+ *.*.*.*) echo "$v";;
+ *.*.*) echo "$v.0";;
+ *.*) echo "$v.0.0";;
+ *) echo "$v.0.0.0";;
+ esac
+}
+
+pp_aix_select () {
+ case "$1" in
+ -user) op="!";;
+ -root) op="";;
+ *) pp_die "pp_aix_select: bad argument";;
+ esac
+ awk $op'($6 ~ /^\/(dev|etc|sbin|var)\//) { print }'
+}
+
+pp_aix_copy_root () {
+ typeset t m o g f p st target
+ while read t m o g f p st; do
+ case "$t" in
+ d) pp_create_dir_if_missing "$1${p%/}";;
+ f) pp_add_transient_file "$1$p"
+ pp_verbose ln "$pp_destdir$p" "$pp_destdir$1$p" ||
+ pp_error "can't link $p into $1";;
+ *) pp_warn "pp_aix_copy_root: filetype $t not handled";;
+ esac
+ done
+}
+
+pp_aix_size () {
+ typeset prefix t m o g f p st
+
+ prefix="$1"
+ while read t m o g f p st; do
+ case "$t" in f) du -a "$pp_destdir$p";; esac
+ done | sed -e 's!/[^/]*$!!' | sort +1 |
+ awk '{ if ($2 != d)
+ { if (sz) print d,sz;
+ d=$2; sz=0 }
+ sz += $1; }
+ END { if (sz) print d,sz }' |
+ sed -n -e "s!^$pp_destdir!$prefix!p"
+}
+
+pp_aix_list () {
+ awk '{ print "." pfx $6; }' pfx="$1"
+}
+
+pp_aix_make_liblpp () {
+ typeset out dn fl f
+
+ out="$1"; shift
+ dn=`dirname "$2"`
+ fl=
+ for f
+ do
+ case "$f" in "$dn/"*) fl="$fl `basename $f`" ;;
+ *) pp_die "liblpp name $f not in $dn/";; esac
+ done
+ (cd "$dn" && pp_verbose ar -c -g -r "$out" $fl) || pp_error "ar error"
+}
+
+pp_aix_make_script () {
+ rm -f "$1"
+ echo "#!/bin/sh" > "$1"
+ cat >> "$1"
+ echo "exit 0" >> "$1"
+ chmod +x "$1"
+}
+
+pp_aix_inventory () {
+ typeset fileset t m o g f p st type
+
+ fileset="$1"
+ while read t m o g f p st; do
+ case "$p" in *:*) pp_error "path $p contains colon";; esac
+ echo "$p:"
+ case "$t" in
+ f) type=FILE; defm=644 ;;
+ s) type=SYMLINK; defm=777 ;;
+ d) type=DIRECTORY; defm=755 ;;
+ esac
+ echo " type = $type"
+ echo " class = inventory,apply,$fileset"
+ if test x"$m" = x"-"; then m="$defm"; fi
+ if test x"$o" = x"-"; then o="root"; fi
+ if test x"$g" = x"-"; then g="system"; fi
+ echo " owner = $o"
+ echo " group = $g"
+
+ case "$m" in ????)
+ m=`echo $m|sed -e 's/^1/TCB,/' \
+ -e 's/^[23]/TCB,SGID,/' \
+ -e 's/^[45]/TCB,SUID,/' \
+ -e 's/^[67]/TCB,SUID,SGID,/'`;; # vtx bit ignored
+ esac
+ echo " mode = $m"
+ case "$t" in
+ f) if test ! -f "$pp_destdir$p"; then
+ pp_error "$p: missing file"
+ fi
+ case "$flags" in
+ *v*)
+ echo " size = VOLATILE"
+ echo " checksum = VOLATILE"
+ ;;
+ *)
+ if test -r "$pp_destdir$p"; then
+ echo " size = $size"
+ pp_verbose sum -r < "$pp_destdir$p" |
+ sed -e 's/.*/ checksum = "&"/'
+ fi
+ ;;
+ esac;;
+ s)
+ echo " target = $st"
+ ;;
+ esac
+
+ #-- Record ABI types seen
+ case "$t" in
+ f) if test -r "$pp_destdir$p"; then
+ case "`file "$pp_destdir$p"`" in
+ *"executable (RISC System/6000)"*) abi=ppc;;
+ *"64-bit XCOFF executable"*) abi=ppc64;;
+ *) abi=;;
+ esac
+ if test -n "$abi"; then
+ pp_add_to_list pp_aix_abis_seen $abi
+ fi
+ fi;;
+ esac
+
+ done
+}
+
+pp_aix_depend ()
+{
+ if test -s "$1"; then
+ pp_warn "aix dependencies not implemented"
+ fi
+}
+
+pp_aix_add_service () {
+ typeset svc cmd_cmd cmd_arg f
+ svc="$1"
+
+ pp_load_service_vars $svc
+
+ set -- $cmd
+ cmd_cmd="$1"; shift
+ cmd_arg="${pp_aix_mkssys_cmd_args:-$*}";
+
+ case "$stop_signal" in
+ HUP) stop_signal=1;;
+ INT) stop_signal=2;;
+ QUIT) stop_signal=3;;
+ KILL) stop_signal=9;;
+ TERM) stop_signal=15;;
+ USR1) stop_signal=30;;
+ USR2) stop_signal=31;;
+ "")
+ pp_error "%service $svc: stop_signal not set";;
+ [a-zA-Z]*)
+ pp_error "%service $svc: bad stop_signal ($stop_signal)";;
+ esac
+
+ test -z "$pidfile" || pp_error "aix requires empty pidfile (non daemon)"
+
+ pp_add_component run
+ if test "$user" = "root"; then
+ uid=0
+ else
+ uid="\"\`/usr/bin/id -u $user\`\""
+ fi
+
+
+ #-- add command text to create/remove the service
+ cat <<-. >> $pp_wrkdir/%post.$svc
+svc=$svc
+uid=0
+cmd_cmd="$cmd_cmd"
+cmd_arg="$cmd_arg"
+stop_signal=$stop_signal
+force_signal=9
+srcgroup="$pp_aix_mkssys_group"
+instances_allowed=${pp_aix_mkssys_instances_allowed:--Q}
+
+lssrc -s \$svc > /dev/null 2>&1
+if [ \$? -eq 0 ]; then
+ lssrc -s \$svc | grep "active" > /dev/null 2>&1
+ if [ \$? -eq 0 ]; then
+ stopsrc -s \$svc > /dev/null 2>&1
+ fi
+ rmsys -s \$svc > /dev/null 2>&1
+fi
+
+mkssys -s \$svc -u \$uid -p "\$cmd_cmd" \${cmd_arg:+-a "\$cmd_arg"} -S -n \$stop_signal -f 9 ${pp_aix_mkssys_args} \${srcgroup:+-G \$srcgroup} \$instances_allowed
+.
+
+ #-- add code to start the service on reboot
+ ${pp_aix_init_services_after_install} &&
+ cat <<-. >> $pp_wrkdir/%post.$svc
+id=\`echo "\$svc" | cut -c1-14\`
+mkitab "\$id:2:once:/usr/bin/startsrc -s \$svc" > /dev/null 2>&1
+.
+
+ ${pp_aix_start_services_after_install} &&
+ cat <<-. >> $pp_wrkdir/%post.$svc
+startsrc -s \$svc
+.
+
+if [ -f "$pp_wrkdir/%post.run" ];then
+ cat $pp_wrkdir/%post.run >> $pp_wrkdir/%post.$svc
+fi
+mv $pp_wrkdir/%post.$svc $pp_wrkdir/%post.run
+
+
+ ${pp_aix_init_services_after_install} &&
+ pp_prepend $pp_wrkdir/%preun.$svc <<-.
+rmitab `echo "$svc" | cut -c1-14` > /dev/null 2>&1
+.
+ pp_prepend $pp_wrkdir/%preun.$svc <<-.
+stopsrc -s $svc >/dev/null 2>&1
+rmssys -s $svc
+.
+
+if [ -f "$pp_wrkdir/%preun.run" ];then
+ cat $pp_wrkdir/%preun.run >> $pp_wrkdir/%preun.$svc
+fi
+mv $pp_wrkdir/%preun.$svc $pp_wrkdir/%preun.run
+}
+
+pp_backend_aix () {
+ typeset briefex instuser instroot svc cmp outbff
+ typeset user_wrkdir root_wrkdir
+ typeset user_files root_files
+
+ test -n "$pp_destdir" ||
+ pp_error "AIX backend requires the '--destdir' option"
+
+ instuser="/usr/lpp/$name"
+ instroot="$instuser/inst_root"
+ pp_aix_bff_name=${pp_aix_bff_name:-$name}
+
+ # Here is the component mapping:
+ # run -> $pp_aix_bff_name.rte ('Run time environment')
+ # doc -> $pp_aix_bff_name.doc (non-standard)
+ # dev -> $pp_aix_bff_name.adt ('Application developer toolkit')
+ # dbg -> $pp_aix_bff_name.diag ('Diagnostics')
+
+ test `echo "$summary" | wc -c ` -gt 40 && pp_error "\$summary too long"
+
+ user_wrkdir=$pp_wrkdir/u
+ root_wrkdir=$pp_wrkdir/r
+ pp_verbose rm -rf $user_wrkdir $root_wrkdir
+ pp_verbose mkdir -p $user_wrkdir $root_wrkdir
+
+ for svc in $pp_services .; do
+ test . = "$svc" && continue
+ pp_aix_add_service $svc
+ done
+
+ {
+ echo "4 $pp_aix_arch I $name {"
+
+ for cmp in $pp_components; do
+ case "$cmp" in
+ run) ex=rte briefex="runtime";;
+ doc) ex=doc briefex="documentation";;
+ dev) ex=adt briefex="developer toolkit";;
+ dbg) ex=diag briefex="diagnostics";;
+ esac
+
+ user_files=$pp_wrkdir/%files.$cmp.u
+ root_files=$pp_wrkdir/%files.$cmp.r
+
+ pp_aix_select -user < $pp_wrkdir/%files.$cmp > $user_files
+ pp_aix_select -root < $pp_wrkdir/%files.$cmp > $root_files
+
+ # Default to USR only unless there are root files,
+ # or a post/pre/check script associated
+ content=U
+ if test -s $root_files \
+ -o -s $pp_wrkdir/%pre.$cmp \
+ -o -s $pp_wrkdir/%post.$cmp \
+ -o -s $pp_wrkdir/%preun.$cmp \
+ -o -s $pp_wrkdir/%postun.$cmp \
+ -o -s $pp_wrkdir/%check.$cmp
+ then
+ content=B
+ fi
+
+ if $pp_opt_debug; then
+ echo "$cmp USER %files:"
+ cat $user_files
+ echo "$cmp ROOT %files:"
+ cat $root_files
+ fi >&2
+
+ bosboot=N; pp_contains_any "$pp_aix_bosboot" $cmp && bosboot=b
+
+ echo $pp_aix_bff_name.$ex \
+ `[ $pp_aix_version ] && pp_aix_version_fix $pp_aix_version || pp_aix_version_fix "$version"` \
+ 1 $bosboot $content \
+ $pp_aix_lang "$summary $briefex"
+ echo "["
+
+ pp_aix_depend $pp_wrkdir/%depend.$cmp
+
+ echo "%"
+
+ # generate per-directory size information
+ pp_aix_size < $user_files
+ pp_aix_size $instroot < $root_files
+
+ pp_aix_list < $user_files > $user_wrkdir/$pp_aix_bff_name.$ex.al
+ pp_aix_list $instroot < $root_files >> $user_wrkdir/$pp_aix_bff_name.$ex.al
+ pp_aix_list < $root_files > $root_wrkdir/$pp_aix_bff_name.$ex.al
+
+ if $pp_opt_debug; then
+ echo "$cmp USER $pp_aix_bff_name.$ex.al:"
+ cat $user_wrkdir/$pp_aix_bff_name.$ex.al
+ echo "$cmp ROOT $pp_aix_bff_name.$ex.al:"
+ cat $root_wrkdir/$pp_aix_bff_name.$ex.al
+ fi >&2
+
+ pp_aix_inventory $pp_aix_bff_name.$ex < $user_files \
+ > $user_wrkdir/$pp_aix_bff_name.$ex.inventory
+ pp_aix_inventory $pp_aix_bff_name.$ex < $root_files \
+ > $root_wrkdir/$pp_aix_bff_name.$ex.inventory
+
+ if $pp_opt_debug; then
+ pp_debug "$cmp USER $pp_aix_bff_name.$ex.inventory:"
+ cat $user_wrkdir/$pp_aix_bff_name.$ex.inventory
+ pp_debug "$cmp ROOT $pp_aix_bff_name.$ex.inventory:"
+ cat $root_wrkdir/$pp_aix_bff_name.$ex.inventory
+ fi >&2
+
+ for fileset in ${pp_aix_deprecated_filesets}; do
+ echo "$fileset"
+ done >$user_wrkdir/$pp_aix_bff_name.$ex.namelist
+
+ if test x"" != x"${pp_aix_copyright:-$copyright}"; then
+ echo "${pp_aix_copyright:-$copyright}" > $user_wrkdir/$pp_aix_bff_name.$ex.copyright
+ echo "${pp_aix_copyright:-$copyright}" > $root_wrkdir/$pp_aix_bff_name.$ex.copyright
+ fi
+
+ #-- assume that post/pre uninstall scripts only make
+ # sense when installed in a root context
+
+ if test -r $pp_wrkdir/%pre.$cmp; then
+ pp_aix_make_script $user_wrkdir/$pp_aix_bff_name.$ex.pre_i \
+ < $pp_wrkdir/%pre.$cmp
+ fi
+
+ if test -r $pp_wrkdir/%post.$cmp; then
+ pp_aix_make_script $root_wrkdir/$pp_aix_bff_name.$ex.post_i \
+ < $pp_wrkdir/%post.$cmp
+ fi
+
+ if test -r $pp_wrkdir/%preun.$cmp; then
+ pp_aix_make_script $root_wrkdir/$pp_aix_bff_name.$ex.unpost_i \
+ < $pp_wrkdir/%preun.$cmp
+ fi
+
+ if test -r $pp_wrkdir/%postun.$cmp; then
+ pp_aix_make_script $root_wrkdir/$pp_aix_bff_name.$ex.unpre_i \
+ < $pp_wrkdir/%postun.$cmp
+ fi
+
+ # remove empty files
+ for f in $user_wrkdir/$pp_aix_bff_name.$ex.* $root_wrkdir/$pp_aix_bff_name.$ex.*; do
+ if test ! -s "$f"; then
+ pp_debug "removing empty $f"
+ rm -f "$f"
+ fi
+ done
+
+ # copy/link the root files so we can do an easy backup later
+ pp_aix_copy_root $instroot < $root_files
+
+ echo "%"
+ echo "]"
+ done
+ echo "}"
+ } > $pp_wrkdir/lpp_name
+
+ if $pp_opt_debug; then
+ echo "/lpp_name :"
+ cat $pp_wrkdir/lpp_name
+ fi >&2
+
+ #-- copy the /lpp_name file to the destdir
+ pp_add_transient_file /lpp_name
+ cp $pp_wrkdir/lpp_name $pp_destdir/lpp_name
+
+ #-- copy the liblpp.a files under destdir for packaging
+ (cd $user_wrkdir && pp_verbose ar -c -g -r liblpp.a $name.*) ||
+ pp_error "ar error"
+ if test -s $user_wrkdir/liblpp.a; then
+ pp_add_transient_file $instuser/liblpp.a
+ pp_verbose cp $user_wrkdir/liblpp.a $pp_destdir$instuser/liblpp.a ||
+ pp_error "cannot create user liblpp.a"
+ fi
+ (cd $root_wrkdir && pp_verbose ar -c -g -r liblpp.a $name.*) ||
+ pp_error "ar error"
+ if test -s $root_wrkdir/liblpp.a; then
+ pp_add_transient_file $instroot/liblpp.a
+ pp_verbose cp $root_wrkdir/liblpp.a $pp_destdir$instroot/liblpp.a ||
+ pp_error "cannot create root liblpp.a"
+ fi
+
+ { echo ./lpp_name
+ test -s $user_wrkdir/liblpp.a && echo .$instuser/liblpp.a
+ test -s $root_wrkdir/liblpp.a && echo .$instroot/liblpp.a
+ cat $user_wrkdir/$name.*.al # includes the relocated root files!
+ } > $pp_wrkdir/bff.list
+
+ if test -n "$pp_aix_abis_seen" -a x"$pp_aix_arch_std" = x"auto"; then
+ case "$pp_aix_abis_seen" in
+ "ppc ppc64"|"ppc64 ppc")
+ pp_aix_arch_std=ppc64
+ ;;
+ ppc|ppc64)
+ pp_aix_arch_std=$pp_aix_abis_seen
+ ;;
+ *" "*)
+ pp_warn "multiple architectures detected: $pp_aix_abis_seen"
+ pp_aix_arch_std=unknown
+ ;;
+ "")
+ pp_warn "no binary executables detected; using noarch"
+ pp_aix_arch_std=noarch
+ ;;
+ *)
+ pp_warn "unknown architecture detected $pp_aix_abis_seen"
+ pp_aix_arch_std=$pp_aix_abis_seen
+ ;;
+ esac
+ fi
+
+ . $pp_wrkdir/%fixup
+
+ outbff=`pp_backend_aix_names`
+ pp_debug "creating: $pp_wrkdir/$outbff"
+ (cd $pp_destdir && pp_verbose /usr/sbin/backup -i -q -p -f -) \
+ < $pp_wrkdir/bff.list \
+ > $pp_wrkdir/$outbff || pp_error "backup failed"
+ if test -n "$pp_aix_sudo" -o -x /usr/sbin/installp; then
+ $pp_aix_sudo /usr/sbin/installp -l -d $pp_wrkdir/$outbff
+ fi
+}
+
+pp_backend_aix_cleanup () {
+ :
+}
+
+pp_backend_aix_names () {
+ echo "$name.`[ $pp_aix_version ] && pp_aix_version_fix $pp_aix_version || pp_aix_version_fix "$version"`.bff"
+}
+
+pp_backend_aix_install_script () {
+ typeset pkgname platform
+ #
+ # The script should take a first argument being the
+ # operation; further arguments refer to components or services
+ #
+ # list-components -- lists components in the pkg
+ # install component... -- installs the components
+ # uninstall component... -- uninstalles the components
+ # list-services -- lists the services in the pkg
+ # start service... -- starts the name service
+ # stop service... -- stops the named services
+ # print-platform -- prints the platform group
+ #
+ pkgname="`pp_backend_aix_names`"
+ platform="`pp_backend_aix_probe`" # XXX should be derived from files
+
+ fsets=
+ for cmp in $pp_components; do
+ case "$cmp" in
+ run) ex=rte;;
+ doc) ex=doc;;
+ dev) ex=adt;;
+ dbg) ex=diag;;
+ esac
+ fsets="$fsets $name.$ex"
+ done
+
+ echo '#!/bin/sh'
+ pp_install_script_common
+
+ cat <<-.
+
+ cpt_to_fileset () {
+ test x"\$*" = x"all" &&
+ set -- $pp_components
+ for cpt
+ do
+ case "\$cpt" in
+ run) echo "$name.rte";;
+ doc) echo "$name.doc";;
+ dev) echo "$name.adt";;
+ dbg) echo "$name.diag";;
+ *) usage;;
+ esac
+ done
+ }
+
+ test \$# -eq 0 && usage
+ op="\$1"; shift
+
+ case "\$op" in
+ list-components)
+ test \$# -eq 0 || usage \$op
+ echo "$pp_components"
+ ;;
+ list-services)
+ test \$# -eq 0 || usage \$op
+ echo "$pp_services"
+ ;;
+ list-files)
+ test \$# -ge 1 || usage \$op
+ echo \${PP_PKGDESTDIR:-.}/$pkgname
+ ;;
+ install)
+ test \$# -ge 1 || usage \$op
+ verbose /usr/sbin/installp -acX -V0 -F \
+ -d \${PP_PKGDESTDIR:-.}/$pkgname \
+ \`cpt_to_fileset "\$@"\`
+ ;;
+ uninstall)
+ test \$# -ge 1 || usage \$op
+ verbose /usr/sbin/installp -u -e/dev/null \
+ -V0 \`cpt_to_fileset "\$@"\`
+ ;;
+ start|stop)
+ test \$# -ge 1 || usage \$op
+ ec=0
+ for svc
+ do
+ verbose \${op}src -s \$svc || ec=1
+ done
+ exit \$ec
+ ;;
+ print-platform)
+ echo "$platform"
+ ;;
+ *)
+ usage;;
+ esac
+.
+}
+
+pp_backend_aix_init_svc_vars () {
+ :
+}
+
+pp_backend_aix_probe () {
+ echo "${pp_aix_os}-${pp_aix_arch_std}"
+}
+
+pp_backend_aix_vas_platforms () {
+ case "${pp_aix_arch_std}" in
+ ppc*) :;;
+ *) pp_die "unknown architecture ${pp_aix_arch_std}";;
+ esac
+ case "${pp_aix_os}" in
+ aix43) echo "aix-43";;
+ aix51) echo "aix-51 aix-43";;
+ aix52) echo "aix-51 aix-43";;
+ aix53) echo "aix-53 aix-51 aix-43";;
+ aix61) echo "aix-53 aix-51 aix-43";;
+ *) pp_die "unknown system ${pp_aix_os}";;
+ esac
+}
+pp_backend_aix_function () {
+ case "$1" in
+ pp_mkgroup) cat <<'.';;
+ /usr/sbin/lsgroup "$1" >/dev/null &&
+ return 0
+ echo "Creating group $1"
+ /usr/bin/mkgroup -A "$1"
+.
+ pp_mkuser:depends) echo pp_mkgroup;;
+ pp_mkuser) cat <<'.';;
+ /usr/sbin/lsuser "$1" >/dev/null &&
+ return 0
+ pp_mkgroup "${2:-$1}" || return 1
+ echo "Creating user $1"
+ /usr/bin/mkuser \
+ login=false \
+ rlogin=false \
+ account_locked=true \
+ home="${3:-/nohome.$1}" \
+ pgrp="${2:-$1}" \
+ "$1"
+.
+ pp_havelib) cat <<'.';;
+ case "$2" in
+ "") pp_tmp_name="lib$1.so";;
+ *.*.*) pp_tmp_name="lib$1.so.$2";;
+ *.*) pp_tmp_name="lib$1.so.$2.0";;
+ *) pp_tmp_name="lib$1.so.$2";;
+ esac
+ for pp_tmp_dir in `echo "/usr/lib:/lib${3:+:$3}" | tr : ' '`; do
+ test -r "$pp_tmp_dir/$pp_tmp_name" -a \
+ -r "$pp_tmp_dir/lib$1.so" && return 0
+ done
+ return 1
+.
+ *) false;;
+ esac
+}
+
+pp_platforms="$pp_platforms sd"
+
+pp_backend_sd_detect () {
+ test x"$1" = x"HP-UX"
+}
+
+pp_backend_sd_init () {
+ pp_sd_sudo=sudo
+ pp_sd_startlevels=2
+ pp_sd_stoplevels=auto
+ pp_sd_config_file=
+ pp_sd_vendor=
+ pp_sd_vendor_tag=OneIdentity
+ pp_sd_default_start=1 # config_file default start value
+
+ pp_readlink_fn=pp_ls_readlink # HPUX has no readlink
+ pp_shlib_suffix='.sl' # .so on most other platforms
+
+ pp_sd_detect_os
+}
+
+pp_sd_detect_os () {
+ typeset revision
+
+ revision=`uname -r`
+ pp_sd_os="${revision#?.}"
+ test -z "$pp_sd_os" &&
+ pp_warn "cannot detect OS version"
+ pp_sd_os_std="hpux`echo $pp_sd_os | tr -d .`"
+
+ case "`uname -m`" in
+ 9000/[678]??) pp_sd_arch_std=hppa;;
+ ia64) pp_sd_arch_std=ia64;;
+ *) pp_sd_arch_std=unknown;;
+ esac
+}
+
+pp_sd_write_files () {
+ typeset t m o g f p st line dm
+ while read t m o g f p st; do
+ line=" file"
+ case "$f" in *v*) line="$line -v";; esac # FIXME for uninstall
+ case ${pp_sd_os} in
+ 10.*)
+ case $t in
+ f) dm=644;;
+ d) p=${p%/}; dm=755;;
+ esac
+ ;;
+ *)
+ case $t in
+ f) dm=644;;
+ d) line="$line -t d"; p=${p%/}; dm=755;;
+ s) line="$line -t s";;
+ esac
+ ;;
+ esac
+
+ test x"$o" = x"-" && o=root
+ test x"$g" = x"-" && g=sys
+ test x"$m" = x"-" && m=$dm
+
+ case $t in
+ s)
+ # swpackage will make unqualified links relative to the
+ # current working (source) directory, not the destination;
+ # we need to qualify them to prevent this.
+ case "$st" in
+ [!/]*) st="`dirname \"$p\"`/$st";;
+ esac
+ echo "$line -o $o -g $g -m $m $st $p"
+ ;;
+ *)
+ echo "$line -o $o -g $g -m $m $pp_destdir$p $p"
+ ;;
+ esac
+
+ done
+}
+
+pp_sd_service_group_script () {
+ typeset grp svcs scriptpath out
+ grp="$1"
+ svcs="$2"
+ scriptpath="/sbin/init.d/$grp"
+ out="$pp_destdir$scriptpath"
+
+ pp_add_file_if_missing $scriptpath run 755 || return 0
+
+ cat <<-. > $out
+ #!/sbin/sh
+ # generated by pp $pp_version
+ svcs="$svcs"
+.
+
+ cat <<-'.' >> $out
+ #-- starts services in order.. stops them all if any break
+ pp_start () {
+ undo=
+ for svc in \$svcs; do
+ /sbin/init.d/\$svc start
+ case \$? in
+ 0|4)
+ undo="\$svc \$undo"
+ ;;
+ *)
+ if test -n "\$undo"; then
+ for svc in \$undo; do
+ /sbin/init.d/\$svc stop
+ done
+ return 1
+ fi
+ ;;
+ esac
+ done
+ return 0
+ }
+
+ #-- stops services in reverse
+ pp_stop () {
+ reverse=
+ for svc in \$svcs; do
+ reverse="\$svc \$reverse"
+ done
+ rc=0
+ for svc in \$reverse; do
+ /sbin/init.d/\$svc stop || rc=\$?
+ done
+ return \$rc
+ }
+
+ case \$1 in
+ start_msg) echo "Starting \$svcs";;
+ stop_msg) echo "Stopping \$svcs";;
+ start) pp_start;;
+ stop) pp_stop;;
+ *) echo "usage: \$0 {start|stop|start_msg|stop_msg}"
+ exit 1;;
+ esac
+.
+}
+
+pp_sd_service_script () {
+ typeset svc config_file config_value scriptpath out
+
+ svc="$1"
+ scriptpath="/sbin/init.d/$svc"
+
+ config_file=${pp_sd_config_file:-/etc/rc.config.d/$svc}
+ sd_config_var=`echo run-$svc | tr '[a-z]-' '[A-Z]_'`
+ sd_config_value=${pp_sd_default_start:-0}
+ pp_load_service_vars "$svc"
+
+ test -n "$user" -a x"$user" != x"root" &&
+ cmd="SHELL=/usr/bin/sh /usr/bin/su $user -c \"exec `echo $cmd | sed -e 's,[$\\\`],\\&,g'`\""
+ if test -z "$pidfile"; then
+ pidfile="/var/run/$svc.pid"
+ cmd="$cmd & echo \$! > \$pidfile"
+ fi
+
+ pp_debug "config file is $config_file"
+
+ pp_add_file_if_missing $scriptpath run 755
+ pp_add_file_if_missing $config_file run 644 v
+
+ cat <<-. >> $pp_destdir$config_file
+
+ # Controls whether the $svc service is started
+ $sd_config_var=$sd_config_value
+.
+
+ if test ! -f $pp_destdir$scriptpath; then
+ cat <<-. > $pp_destdir$scriptpath
+ #!/sbin/sh
+ # generated by pp $pp_version
+
+ svc="$svc"
+ pidfile="$pidfile"
+ config_file="$config_file"
+
+ pp_start () {
+ $cmd
+ }
+
+ pp_disabled () {
+ test \${$sd_config_var:-0} -eq 0
+ }
+
+ pp_stop () {
+ if test ! -s "\$pidfile"; then
+ echo "Unable to stop \$svc (no pid file)"
+ return 1
+ else
+ read pid < "\$pidfile"
+ if kill -0 "\$pid" 2>/dev/null; then
+ if kill -${stop_signal:-TERM} "\$pid"; then
+ rm -f "\$pidfile"
+ return 0
+ else
+ echo "Unable to stop \$svc"
+ return 1
+ fi
+ else
+ rm -f "\$pidfile"
+ return 0
+ fi
+ fi
+ }
+
+ pp_running () {
+ if test -s "\$pidfile"; then
+ read pid < "\$pidfile" 2>/dev/null
+ if test \${pid:-0} -gt 1 && kill -0 "\$pid" 2>/dev/null; then
+ # make sure command name matches
+ c="\`echo $cmd | sed -e 's: .*::' -e 's:^.*/::'\`"
+ pid="\`ps -p \$pid 2>/dev/null | sed -n \"s/^ *\(\$pid\) .*\$c *\$/\1/p\"\`"
+ if test -n "\$pid"; then
+ return 0
+ fi
+ fi
+ fi
+ return 1
+ }
+
+ case \$1 in
+ start_msg) echo "Starting the \$svc service";;
+ stop_msg) echo "Stopping the \$svc service";;
+ start)
+ if test -f "\$config_file"; then
+ . \$config_file
+ fi
+ if pp_disabled; then
+ exit 2
+ elif pp_running; then
+ echo "\$svc already running";
+ exit 0
+ elif pp_start; then
+ echo "\$svc started";
+ # rc(1M) says we should exit 4, but nobody expects it!
+ exit 0
+ else
+ exit 1
+ fi;;
+ stop) if pp_stop; then
+ echo "\$svc stopped";
+ exit 0
+ else
+ exit 1
+ fi;;
+ *) echo "usage: \$0 {start|stop|start_msg|stop_msg}"
+ exit 1;;
+ esac
+.
+ fi
+}
+
+pp_sd_make_service () {
+ typeset level startpriority stoppriority startlevels stoplevels
+ typeset svc svcvar symtype
+
+ svc="$1"
+ svcvar=`pp_makevar $svc`
+
+ case ${pp_sd_os} in
+ 10.*) symtype="file";;
+ *) symtype="file -t s";;
+ esac
+
+ # TODO: Figure out why this check is here
+ #-- don't do anything if the script exists
+ #if test -s "$pp_destdir/sbin/init.d/$svc"; then
+ # pp_error "$pp_destdir/sbin/init.d/$svc exists"
+ # return
+ #fi
+
+ # symlink the script, depending on the priorities chosen
+ eval startpriority='${pp_sd_startpriority_'$svcvar'}'
+ eval stoppriority='${pp_sd_stoppriority_'$svcvar'}'
+ test -z "$startpriority" && startpriority="${pp_sd_startpriority:-50}"
+ test -z "$stoppriority" && stoppriority="${pp_sd_stoppriority:-50}"
+
+ eval startlevels='${pp_sd_startlevels_'$svcvar'}'
+ test -z "$startlevels" && startlevels="$pp_sd_startlevels"
+
+ eval stoplevels='${pp_sd_stoplevels_'$svcvar'}'
+ test -z "$stoplevels" && stoplevels="$pp_sd_stoplevels"
+
+ # create the script and config file
+ pp_sd_service_script $svc
+
+ # fix the priority up
+ case "$startpriority" in
+ ???) :;;
+ ??) startpriority=0$startpriority;;
+ ?) startpriority=00$startpriority;;
+ esac
+ case "$stoppriority" in
+ ???) :;;
+ ??) stoppriority=0$stoppriority;;
+ ?) stoppriority=00$stoppriority;;
+ esac
+
+ if test x"$stoplevels" = x"auto"; then
+ stoplevels=
+ test -z "$startlevels" || for level in $startlevels; do
+ stoplevels="$stoplevels `expr $level - 1`"
+ done
+ fi
+
+ # create the symlinks
+ test -z "$startlevels" || for level in $startlevels; do
+ echo " ${symtype}" \
+ "/sbin/init.d/$svc" \
+ "/sbin/rc$level.d/S$startpriority$svc"
+ done
+ test -z "$stoplevels" || for level in $stoplevels; do
+ echo " ${symtype}" \
+ "/sbin/init.d/$svc" \
+ "/sbin/rc$level.d/K$stoppriority$svc"
+ done
+}
+
+pp_sd_control () {
+ typeset ctrl script
+ typeset cpt
+
+ ctrl="$1"; shift
+ cpt="$1"; shift
+ script="$pp_wrkdir/control.$ctrl.$cpt"
+ cat <<. >$script
+.
+ cat "$@" >> $script
+ echo "exit 0" >> $script
+ /usr/bin/chmod +x $script
+ echo " $ctrl $script"
+}
+
+pp_sd_depend () {
+ typeset _name _vers
+ while read _name _vers; do
+ case "$_name" in ""| "#"*) continue ;; esac
+ echo " prerequisites $_name ${_vers:+r>= $_vers}"
+ done
+}
+
+pp_sd_conflict () {
+ typeset _name _vers
+ while read _name _vers; do
+ case "$_name" in ""| "#"*) continue ;; esac
+ echo " exrequisites $_name ${_vers:+r>= $_vers}"
+ done
+}
+
+pp_backend_sd () {
+ typeset psf cpt svc outfile release swp_flags
+
+ psf=$pp_wrkdir/psf
+ release="?.${pp_sd_os%.[0-9][0-9]}.*"
+
+ echo "depot" > $psf
+ echo "layout_version 1.0" >>$psf
+
+ #-- vendor
+ cat <<. >>$psf
+ vendor
+ tag $pp_sd_vendor_tag
+ title "${pp_sd_vendor:-$vendor}"
+ end
+
+ product
+ tag $name
+ revision $version
+ vendor_tag $pp_sd_vendor_tag
+ is_patch false
+ title "$summary"
+ copyright "$copyright"
+ machine_type *
+ os_name HP-UX
+ os_release $release
+ os_version ?
+ directory /
+ is_locatable false
+.
+ test -n "$description" \
+ && echo $description > $pp_wrkdir/description \
+ && cat <<. >> $psf
+ description < $pp_wrkdir/description
+.
+
+ # make convenience service groups
+ if test -n "$pp_service_groups"; then
+ for grp in $pp_service_groups; do
+ pp_sd_service_group_script \
+ $grp "`pp_service_get_svc_group $grp`"
+ done
+ fi
+
+ for cpt in $pp_components; do
+ cat <<. >>$psf
+ fileset
+ tag ${pp_sd_fileset_tag:-$cpt}
+ title "${summary:-cpt}"
+ revision $version
+.
+ test -s $pp_wrkdir/%depend.$cpt &&
+ pp_sd_depend < $pp_wrkdir/%depend.$cpt >> $psf
+ test -s $pp_wrkdir/%conflict.$cpt &&
+ pp_sd_conflict < $pp_wrkdir/%conflict.$cpt >> $psf
+
+ #-- make sure services are shut down during uninstall
+ if test $cpt = run -a -n "$pp_services"; then
+ for svc in $pp_services; do
+ pp_prepend $pp_wrkdir/%preun.$cpt <<-.
+ /sbin/init.d/$svc stop
+.
+ done
+ fi
+
+ #-- we put the post/preun code into configure/unconfigure
+ # and not postinstall/preremove, because configure/unconfigure
+ # scripts are run on the hosts where the package is installed,
+ # not loaded (a subtle difference).
+ test -s $pp_wrkdir/%pre.$cpt &&
+ pp_sd_control checkinstall $cpt $pp_wrkdir/%pre.$cpt >> $psf
+ test -s $pp_wrkdir/%post.$cpt &&
+ pp_sd_control configure $cpt $pp_wrkdir/%post.$cpt >> $psf
+ test -s $pp_wrkdir/%preun.$cpt &&
+ pp_sd_control unconfigure $cpt $pp_wrkdir/%preun.$cpt >> $psf
+ test -s $pp_wrkdir/%postun.$cpt &&
+ pp_sd_control postremove $cpt $pp_wrkdir/%postun.$cpt >> $psf
+ test -s $pp_wrkdir/%check.$cpt &&
+ pp_sd_control checkinstall $cpt $pp_wrkdir/%check.$cpt >> $psf
+
+ if test $cpt = run -a -n "$pp_services"; then
+ for svc in $pp_services; do
+ #-- service names are 10 chars max on hpux
+ case "$svc" in ???????????*)
+ pp_warn "service name '$svc' is too long for hpux";;
+ esac
+ pp_sd_make_service $svc >> $psf
+ done
+ #pp_sd_make_service_config
+ fi
+
+ pp_sd_write_files < $pp_wrkdir/%files.$cpt >> $psf
+
+ #-- end fileset clause
+ cat <<. >>$psf
+ end
+.
+
+ done
+
+ #-- end product clause
+ cat <<. >>$psf
+ end
+.
+
+ $pp_opt_debug && cat $psf >&2
+
+ test -s $pp_wrkdir/%fixup && . $pp_wrkdir/%fixup
+
+ outfile=`pp_backend_sd_names`
+ case ${pp_sd_os} in
+ 10.*)
+ swp_flags="-x target_type=tape"
+ ;;
+ *)
+ swp_flags="-x media_type=tape"
+ ;;
+ esac
+ if pp_verbose ${pp_sd_sudo} /usr/sbin/swpackage -s $psf $swp_flags \
+ @ $pp_wrkdir/$outfile
+ then
+ pp_verbose ${pp_sd_sudo} /usr/sbin/swlist -l file -s $pp_wrkdir/$outfile
+ else
+ pp_error "swpackage failed"
+ fi
+}
+
+pp_backend_sd_cleanup () {
+ :
+}
+
+pp_backend_sd_names () {
+ echo "$name-$version.$pp_sd_arch_std.depot"
+}
+
+pp_backend_sd_install_script () {
+ typeset pkgname platform
+
+ pkgname=`pp_backend_sd_names`
+ platform="`pp_backend_sd_probe`"
+
+ echo "#!/bin/sh"
+ pp_install_script_common
+ cat <<.
+
+ cpt_to_tags () {
+ test x"\$*" = x"all" && set -- $pp_components
+ for cpt
+ do
+ echo "$name.\$cpt"
+ done
+ }
+
+ test \$# -eq 0 && usage
+ op="\$1"; shift
+
+ case "\$op" in
+ list-components)
+ test \$# -eq 0 || usage \$op
+ echo "$pp_components"
+ ;;
+ list-services)
+ test \$# -eq 0 || usage \$op
+ echo "$pp_services"
+ ;;
+ list-files)
+ test \$# -ge 1 || usage \$op
+ echo \${PP_PKGDESTDIR:-.}/$pkgname
+ ;;
+ install)
+ test \$# -ge 1 || usage \$op
+ verbose /usr/sbin/swinstall -x verbose=0 \
+ -s \${PP_PKGDESTDIR:-\`pwd\`}/$pkgname \
+ \`cpt_to_tags "\$@"\`
+ ;;
+ uninstall)
+ test \$# -ge 1 || usage \$op
+ verbose /usr/sbin/swremove -x verbose=0 \
+ \`cpt_to_tags "\$@"\`
+ ;;
+ start|stop)
+ test \$# -ge 1 || usage \$op
+ ec=0
+ for svc
+ do
+ verbose /sbin/init.d/\$svc \$op
+ [ \$? -eq 4 -o \$? -eq 0 ] || ec=1
+ done
+ exit \$ec
+ ;;
+ print-platform)
+ echo "$platform"
+ ;;
+ *)
+ usage
+ ;;
+ esac
+.
+}
+
+pp_backend_sd_probe () {
+ echo "${pp_sd_os_std}-${pp_sd_arch_std}"
+}
+
+pp_backend_sd_vas_platforms () {
+ case "`pp_backend_sd_probe`" in
+ hpux*-hppa) echo hpux-pa;;
+ hpux*-ia64) echo hpux-ia64 hpux-pa;;
+ *) pp_die "unknown system `pp_backend_sd_probe`";;
+ esac
+}
+
+pp_backend_sd_init_svc_vars () {
+ :
+}
+pp_backend_sd_function () {
+ case "$1" in
+ pp_mkgroup) cat <<'.';;
+ /usr/sbin/groupmod "$1" 2>/dev/null ||
+ /usr/sbin/groupadd "$1"
+.
+ pp_mkuser:depends) echo pp_mkgroup;;
+ pp_mkuser) cat <<'.';;
+ pp_mkgroup "${2:-$1}" || return 1
+ /usr/sbin/useradd \
+ -g "${2:-$1}" \
+ -d "${3:-/nonexistent}" \
+ -s "${4:-/bin/false}" \
+ "$1"
+.
+ pp_havelib) cat <<'.';;
+ for pp_tmp_dir in `echo /usr/lib${3:+:$3} | tr : ' '`; do
+ test -r "$pp_tmp_dir/lib$1${2:+.$2}.sl" && return 0
+ done
+ return 1
+.
+ *) false;;
+ esac
+}
+
+pp_platforms="$pp_platforms solaris"
+
+pp_backend_solaris_detect () {
+ test x"$1" = x"SunOS"
+}
+
+pp_backend_solaris_init () {
+ pp_solaris_category=
+ pp_solaris_istates="s S 1 2 3" # run-states when install is ok
+ pp_solaris_rstates="s S 1 2 3" # run-states when remove is ok
+ pp_solaris_maxinst=
+ pp_solaris_vendor=
+ pp_solaris_pstamp=
+ pp_solaris_copyright=
+ pp_solaris_name=
+ pp_solaris_desc=
+ pp_solaris_package_arch=auto
+
+ pp_solaris_detect_os
+ pp_solaris_detect_arch
+
+ pp_solaris_init_svc
+
+ #-- readlink not reliably available on Solaris
+ pp_readlink_fn=pp_ls_readlink
+}
+
+pp_solaris_detect_os () {
+ typeset osrel
+
+ osrel=`/usr/bin/uname -r`
+ case "$osrel" in
+ 5.[0-6]) pp_solaris_os="sol2${osrel#5.}";;
+ 5.*) pp_solaris_os="sol${osrel#5.}";;
+ esac
+ test -z "$pp_solaris_os" &&
+ pp_warn "can't determine OS suffix from uname -r"
+
+}
+
+pp_solaris_detect_arch () {
+ if [ -x /usr/bin/isainfo ]; then
+ pp_solaris_arch=`/usr/bin/isainfo -n`
+ else
+ pp_solaris_arch=`/usr/bin/optisa amd64 sparcv9 i386 sparc`
+ fi
+ [ -z "$pp_solaris_arch" ] &&
+ pp_error "can't determine processor architecture"
+ case "$pp_solaris_arch" in
+ amd64) pp_solaris_arch_std=x86_64;;
+ i386) pp_solaris_arch_std=i386;;
+ sparcv9) pp_solaris_arch_std=sparc64;;
+ sparc) pp_solaris_arch_std=sparc;;
+ *) pp_solaris_arch_std=unknown;;
+ esac
+}
+
+pp_solaris_is_request_script_necessary () {
+ typeset has_optional_services
+
+ has_optional_services=no
+ for _svc in $pp_services; do
+ pp_load_service_vars $_svc
+ if test "$optional" = "yes"; then
+ has_optional_services=yes
+ fi
+ done
+
+ # If the package has no optional services and only one component, don't
+ # create a request script at all.
+ if test "$has_optional_services" = "no" &&
+ test `echo $pp_components | wc -w` -eq 1; then
+ return 1 # no
+ fi
+
+ return 0 # yes
+}
+
+pp_solaris_request () {
+ typeset _cmp _svc
+
+ #-- The common part of the request script contains the ask() function
+ # and resets the CLASSES list to empty
+ cat <<'.'
+ trap 'exit 3' 15
+ ask () {
+ ans=`ckyorn -d "$1" \
+ -p "Do you want to $2"` \
+ || exit $?
+ case "$ans" in y*|Y*) return 0;; *) return 1;; esac
+ }
+ CLASSES=
+.
+ #-- each of our components adds itself to the CLASSES list
+ for _cmp in $pp_components; do
+ case "$_cmp" in
+ run) :;;
+ doc) echo 'ask y "install the documentation files" &&';;
+ dev) echo 'ask y "install the development files" &&';;
+ dbg) echo 'ask n "install the diagnostic files" &&';;
+ esac
+ echo ' CLASSES="$CLASSES '$_cmp'"'
+ done
+
+ #-- the request script writes the CLASSES var to its output
+ cat <<'.'
+ echo "CLASSES=$CLASSES" > $1
+.
+
+ if test -n "$pp_services"; then
+ echo 'SERVICES='
+ for _svc in $pp_services; do
+ pp_load_service_vars $_svc
+ if test "$enable" = "yes"; then
+ _default_prompt=y
+ else
+ _default_prompt=n
+ fi
+ if test "$optional" = "yes"; then
+ echo 'ask '$_default_prompt' "install '$_svc' service" &&'
+ fi
+ echo ' SERVICES="$SERVICES '$_svc'"'
+ done
+ echo 'echo "SERVICES=$SERVICES" >> $1'
+ fi
+
+}
+
+pp_solaris_procedure () {
+ cat <<.
+
+ #-- $2 for $1 component of $name
+ case " \$CLASSES " in *" $1 "*)
+.
+ cat
+ cat <<.
+ ;; esac
+.
+}
+
+pp_solaris_depend () {
+ typeset _name _vers
+ while read _name _vers; do
+ if test -n "$_name"; then
+ echo "P $_name $_name"
+ test -n "$_vers" && echo " $_vers"
+ fi
+ done
+}
+
+pp_solaris_conflict () {
+ typeset _name _vers
+ while read _name _vers; do
+ if test -n "$_name"; then
+ echo "I $_name $_name"
+ test -n "$_vers" && echo " $_vers"
+ fi
+ done
+}
+
+pp_solaris_space() {
+ echo "$2:$3:$1" >> $pp_wrkdir/space.cumulative
+}
+
+pp_solaris_sum_space () {
+ if test -s $pp_wrkdir/space.cumulative; then
+ sort -t: +2 < $pp_wrkdir/space.cumulative |
+ awk -F: 'NR==1{n=$3}{if($3==n){b+=$1;i+=$2}else{print n" "b" "i;b=$1;i=$2;n=$3}}END{print n" "b" "i}' > $pp_wrkdir/space
+ fi
+}
+
+pp_solaris_proto () {
+ typeset t m o g f p st
+ typeset abi
+
+ while read t m o g f p st; do
+ # Use Solaris default mode, owner and group if all unspecified
+ if test x"$m$o$g" = x"---"; then
+ m="?"; o="?"; g="?"
+ fi
+ test x"$o" = x"-" && o="root"
+ case "$t" in
+ f) test x"$g" = x"-" && g="bin"
+ test x"$m" = x"-" && m=444
+ case "$f" in
+ *v*) echo "v $1 $p=$pp_destdir$p $m $o $g";;
+ *) echo "f $1 $p=$pp_destdir$p $m $o $g";;
+ esac
+ if test -r "$pp_destdir$p"; then
+ #-- Use file to record ABI types seen
+ case "`file "$pp_destdir$p"`" in
+ *"ELF 32"*80386*) abi=i386;;
+ *"ELF 64"*AMD*) abi=x86_64;;
+ *"ELF 32"*SPARC*) abi=sparc;;
+ *"ELF 64"*SPARC*) abi=sparc64;;
+ *) abi=;;
+ esac
+ if test -n "$abi"; then
+ pp_add_to_list pp_solaris_abis_seen $abi
+ fi
+ fi
+ ;;
+ d) test x"$g" = x"-" && g="sys"
+ test x"$m" = x"-" && m=555
+ echo "d $1 $p $m $o $g"
+ ;;
+ s) test x"$g" = x"-" && g="bin"
+ test x"$m" = x"-" && m=777
+ if test x"$m" != x"777" -a x"$m" != x"?"; then
+ pp_warn "$p: invalid mode $m for symlink, should be 777 or -"
+ fi
+ echo "s $1 $p=$st $m $o $g"
+ ;;
+ esac
+ done
+}
+
+pp_backend_solaris () {
+ typeset _cmp _svc _grp
+
+ prototype=$pp_wrkdir/prototype
+ : > $prototype
+
+ pkginfo=$pp_wrkdir/pkginfo
+ : > $pkginfo
+ echo "i pkginfo=$pkginfo" >> $prototype
+
+ case "${pp_solaris_name:-$name}" in
+ [0-9]*)
+ pp_error "Package name '${pp_solaris_name:-$name}'" \
+ "cannot start with a number"
+ ;;
+ ???????????????*)
+ pp_warn "Package name '${pp_solaris_name:-$name}'" \
+ "too long for Solaris 2.6 or 2.7 (max 9 characters)"
+ ;;
+ ??????????*)
+ pp_warn "Package name '${pp_solaris_name:-$name}'" \
+ "too long for 2.7 Solaris (max 9 characters)"
+ ;;
+ esac
+
+ #-- generate the package info file
+ echo "VERSION=$version" >> $pkginfo
+ echo "PKG=${pp_solaris_name:-$name}" >> $pkginfo
+ echo "CLASSES=$pp_components" >> $pkginfo
+ echo "BASEDIR=/" >> $pkginfo
+ echo "NAME=$name $version" >> $pkginfo
+ echo "CATEGORY=${pp_solaris_category:-application}" >> $pkginfo
+
+ desc="${pp_solaris_desc:-$description}"
+ test -n "$desc" &&
+ echo "DESC=$desc" >> $pkginfo
+
+ test -n "$pp_solaris_rstates" &&
+ echo "RSTATES=$pp_solaris_rstates" >> $pkginfo
+ test -n "$pp_solaris_istates" &&
+ echo "ISTATES=$pp_solaris_istates" >> $pkginfo
+ test -n "$pp_solaris_maxinst" &&
+ echo "MAXINST=$pp_solaris_maxinst" >> $pkginfo
+ test -n "${pp_solaris_vendor:-$vendor}" &&
+ echo "VENDOR=${pp_solaris_vendor:-$vendor}" >> $pkginfo
+ test -n "$pp_solaris_pstamp" &&
+ echo "PSTAMP=$pp_solaris_pstamp" >> $pkginfo
+
+ if test -n "${pp_solaris_copyright:-$copyright}"; then
+ echo "${pp_solaris_copyright:-$copyright}" > $pp_wrkdir/copyright
+ echo "i copyright=$pp_wrkdir/copyright" >> $prototype
+ fi
+
+ #-- scripts to run before and after install
+ : > $pp_wrkdir/postinstall
+ : > $pp_wrkdir/preremove
+ : > $pp_wrkdir/postremove
+ for _cmp in $pp_components; do
+ #-- add the preinstall scripts in definition order
+ if test -s $pp_wrkdir/%pre.$_cmp; then
+ pp_solaris_procedure $_cmp preinst < $pp_wrkdir/%pre.$_cmp \
+ >> $pp_wrkdir/preinstall
+ fi
+ #-- add the postinstall scripts in definition order
+ if test -s $pp_wrkdir/%post.$_cmp; then
+ pp_solaris_procedure $_cmp postinst < $pp_wrkdir/%post.$_cmp \
+ >> $pp_wrkdir/postinstall
+ fi
+ #-- add the preremove rules in reverse definition order
+ if test -s $pp_wrkdir/%preun.$_cmp; then
+ pp_solaris_procedure $_cmp preremove < $pp_wrkdir/%preun.$_cmp |
+ pp_prepend $pp_wrkdir/preremove
+ fi
+ #-- add the postremove scripts in definition order
+ if test -s $pp_wrkdir/%postun.$_cmp; then
+ pp_solaris_procedure $_cmp postremove < $pp_wrkdir/%postun.$_cmp \
+ >> $pp_wrkdir/postremove
+ fi
+ #-- Add the check script in definition order
+ if test -s $pp_wrkdir/%check.$_cmp; then
+ pp_solaris_procedure $_cmp checkinstall \
+ < $pp_wrkdir/%check.$_cmp \
+ >> $pp_wrkdir/checkinstall
+ fi
+ #-- All dependencies and conflicts are merged together for Solaris pkgs
+ test -s $pp_wrkdir/%depend.$_cmp &&
+ pp_solaris_depend < $pp_wrkdir/%depend.$_cmp >> $pp_wrkdir/depend
+ test -s $pp_wrkdir/%conflict.$_cmp &&
+ pp_solaris_conflict < $pp_wrkdir/%conflict.$_cmp >> $pp_wrkdir/depend
+ done
+
+
+ if pp_solaris_is_request_script_necessary; then
+ pp_solaris_request > $pp_wrkdir/request
+ fi
+
+ test -n "$pp_services" &&
+ for _svc in $pp_services; do
+ pp_load_service_vars $_svc
+ pp_solaris_smf $_svc
+ pp_solaris_make_service $_svc
+ pp_solaris_install_service $_svc | pp_prepend $pp_wrkdir/postinstall
+ pp_solaris_remove_service $_svc | pp_prepend $pp_wrkdir/preremove
+ pp_solaris_remove_service $_svc | pp_prepend $pp_wrkdir/postremove
+ unset pp_svc_xml_file
+ done
+
+ test -n "$pp_service_groups" &&
+ for _grp in $pp_service_groups; do
+ pp_solaris_make_service_group \
+ $_grp "`pp_service_get_svc_group $_grp`"
+ done
+
+ #-- if installf was used; we need to indicate a termination
+ grep installf $pp_wrkdir/postinstall >/dev/null &&
+ echo 'installf -f $PKGINST' >> $pp_wrkdir/postinstall
+
+ pp_solaris_sum_space
+
+ # NB: pkginfo and copyright are added earlier
+ for f in compver depend space checkinstall \
+ preinstall request postinstall \
+ preremove postremove; do
+ if test -s $pp_wrkdir/$f; then
+ case $f in
+ *install|*remove|request)
+ # turn scripts into a proper shell scripts
+ mv $pp_wrkdir/$f $pp_wrkdir/$f.tmp
+ { echo "#!/bin/sh";
+ echo "# $f script for ${pp_solaris_name:-$name}-$version"
+ cat $pp_wrkdir/$f.tmp
+ echo "exit 0"; } > $pp_wrkdir/$f
+ chmod +x $pp_wrkdir/$f
+ rm -f $pp_wrkdir/$f.tmp
+ ;;
+ esac
+ if $pp_opt_debug; then
+ pp_debug "contents of $f:"
+ cat $pp_wrkdir/$f >&2
+ fi
+ echo "i $f=$pp_wrkdir/$f" >> $prototype
+ fi
+ done
+
+ #-- create the prototype file which lists the files to install
+ # do this as late as possible because files could be added
+ pp_solaris_abis_seen=
+ for _cmp in $pp_components; do
+ pp_solaris_proto $_cmp < $pp_wrkdir/%files.$_cmp
+ done >> $prototype
+
+ if test x"$pp_solaris_package_arch" = x"auto"; then
+ if pp_contains "$pp_solaris_abis_seen" sparc64; then
+ pp_solaris_package_arch_std="sparc64"
+ echo "ARCH=sparcv9" >> $pkginfo
+ elif pp_contains "$pp_solaris_abis_seen" sparc; then
+ pp_solaris_package_arch_std="sparc"
+ echo "ARCH=sparc" >> $pkginfo
+ elif pp_contains "$pp_solaris_abis_seen" x86_64; then
+ pp_solaris_package_arch_std="x86_64"
+ echo "ARCH=amd64" >> $pkginfo
+ elif pp_contains "$pp_solaris_abis_seen" i386; then
+ pp_solaris_package_arch_std="i386"
+ echo "ARCH=i386" >> $pkginfo
+ else
+ pp_warn "No ELF files found: not supplying an ARCH type"
+ pp_solaris_package_arch_std="noarch"
+ fi
+ else
+ pp_solaris_package_arch_std="$pp_solaris_package_arch"
+ echo "ARCH=$pp_solaris_package_arch" >> $pkginfo
+ fi
+
+ mkdir $pp_wrkdir/pkg
+
+ . $pp_wrkdir/%fixup
+
+if $pp_opt_debug; then
+ echo "$pkginfo::"; cat $pkginfo
+ echo "$prototype::"; cat $prototype
+fi >&2
+
+ pkgmk -d $pp_wrkdir/pkg -f $prototype \
+ || { error "pkgmk failed"; return; }
+ pkgtrans -s $pp_wrkdir/pkg \
+ $pp_wrkdir/`pp_backend_solaris_names` \
+ ${pp_solaris_name:-$name} \
+ || { error "pkgtrans failed"; return; }
+}
+
+pp_backend_solaris_cleanup () {
+ :
+}
+
+pp_backend_solaris_names () {
+ echo ${pp_solaris_name:-$name}-$version-${pp_solaris_package_arch_std:-$pp_solaris_arch}.pkg
+}
+
+pp_backend_solaris_install_script () {
+ typeset pkgname platform
+
+ platform="${pp_solaris_os:-solaris}-${pp_solaris_package_arch_std:-$pp_solaris_arch}"
+
+ echo "#! /sbin/sh"
+ pp_install_script_common
+ pkgname=`pp_backend_solaris_names`
+
+ cat <<.
+ tmpnocheck=/tmp/nocheck\$\$
+ tmpresponse=/tmp/response\$\$
+ trap 'rm -f \$tmpnocheck \$tmpresponse' 0
+
+ make_tmpfiles () {
+ cat <<-.. > \$tmpresponse
+ CLASSES=\$*
+ SERVICES=$pp_services
+..
+ cat <<-.. > \$tmpnocheck
+ mail=
+ instance=overwrite
+ partial=nocheck
+ runlevel=nocheck
+ idepend=nocheck
+ rdepend=nocheck
+ space=nocheck
+ setuid=nocheck
+ conflict=nocheck
+ action=nocheck
+ basedir=default
+..
+ }
+
+ test \$# -eq 0 && usage
+ op="\$1"; shift
+
+ case "\$op" in
+ list-components)
+ test \$# -eq 0 || usage \$op
+ echo "$pp_components"
+ ;;
+ list-services)
+ test \$# -eq 0 || usage \$op
+ echo "$pp_services"
+ ;;
+ list-files)
+ test \$# -ge 1 || usage \$op
+ echo \${PP_PKGDESTDIR:-.}/$pkgname
+ ;;
+ install)
+ test \$# -ge 1 || usage \$op
+ make_tmpfiles "\$@"
+ verbose /usr/sbin/pkgadd -n -d \${PP_PKGDESTDIR:-.}/$pkgname \
+ -r \$tmpresponse \
+ -a \$tmpnocheck \
+ ${pp_solaris_name:-$name}
+ ;;
+ uninstall)
+ test \$# -ge 1 || usage \$op
+ make_tmpfiles "\$@"
+ verbose /usr/sbin/pkgrm -n \
+ -a \$tmpnocheck \
+ ${pp_solaris_name:-$name}
+ ;;
+ start|stop)
+ test \$# -ge 1 || usage \$op
+ ec=0
+ for svc
+ do
+ verbose /etc/init.d/\$svc \$op || ec=1
+ done
+ exit \$ec
+ ;;
+ print-platform)
+ echo "$platform"
+ ;;
+ *)
+ usage
+ ;;
+ esac
+.
+}
+
+pp_solaris_dynlib_depend () {
+ xargs ldd 2>/dev/null |
+ sed -e '/^[^ ]*:$/d' -e 's,.*=>[ ]*,,' -e 's,^[ ]*,,' |
+ sort -u |
+ grep -v '^/usr/platform/' | (
+ set -- ""; shift
+ while read p; do
+ set -- "$@" -p "$p"
+ if [ $# -gt 32 ]; then
+ echo "$# is $#" >&2
+ pkgchk -l "$@"
+ set -- ""; shift
+ fi
+ done
+ [ $# -gt 0 ] && pkgchk -l "$@"
+ )|
+ awk '/^Current status:/{p=0} p==1 {print $1} /^Referenced by/ {p=1}' |
+ sort -u |
+ xargs -l32 pkginfo -x |
+ awk 'NR % 2 == 1 { name=$1; } NR%2 == 0 { print name, $2 }'
+}
+
+pp_solaris_add_dynlib_depends () {
+ typeset tmp
+ tmp=$pp_wrkdir/tmp.dynlib
+
+ for _cmp in $pp_components; do
+ awk '{print destdir $6}' destdir="$pp_destdir" \
+ < $pp_wrkdir/%files.$_cmp |
+ pp_solaris_dynlib_depend > $tmp
+ if test -s $tmp; then
+ cat $tmp >> $pp_wrkdir/%depend.$_cmp
+ fi
+ rm -f $tmp
+ done
+}
+
+pp_backend_solaris_probe () {
+ echo "${pp_solaris_os}-${pp_solaris_arch_std}"
+}
+
+pp_backend_solaris_vas_platforms () {
+ case `pp_backend_solaris_probe` in
+ sol10-sparc* | sol9-sparc* | sol8-sparc*)
+ echo solaris8-sparc solaris7-sparc solaris26-sparc;;
+ sol7-sparc*) echo solaris7-sparc solaris26-sparc;;
+ sol26-sparc*) echo solaris26-sparc;;
+ sol8-*86) echo solaris8-x86;;
+ sol10-*86 | sol10-x86_64)
+ echo solaris10-x64 solaris8-x86;;
+ *) pp_die "unknown system `pp_backend_solaris_probe`";;
+ esac
+}
+pp_backend_solaris_function() {
+ case "$1" in
+ pp_mkgroup) cat<<'.';;
+ /usr/sbin/groupmod "$1" 2>/dev/null && return 0
+ /usr/sbin/groupadd "$1"
+.
+ pp_mkuser:depends) echo pp_mkgroup;;
+ pp_mkuser) cat<<'.';;
+ id "$1" >/dev/null 2>/dev/null && return 0
+ pp_mkgroup "${2:-$1}" || return 1
+ /usr/sbin/useradd \
+ -g "${2:-$1}" \
+ -d "${3:-/nonexistent}" \
+ -s "${4:-/bin/false}" \
+ "$1"
+.
+ *) false;;
+ esac
+}
+
+pp_backend_solaris_init_svc_vars () {
+ _smf_category=${pp_solaris_smf_category:-application}
+ _smf_method_envvar_name=${smf_method_envvar_name:-"PP_SMF_SERVICE"}
+ pp_solaris_service_shell=/sbin/sh
+}
+
+pp_solaris_init_svc () {
+ smf_version=1
+ smf_type=service
+ solaris_user=
+ solaris_stop_signal=
+ solaris_sysv_init_start=S70 # invocation order for start scripts
+ solaris_sysv_init_kill=K30 # invocation order for kill scripts
+ solaris_sysv_init_start_states="2" # states to install start link
+ solaris_sysv_init_kill_states="S 0 1" # states to install kill link
+
+ #
+ # To have the service be installed to start automatically,
+ # %service foo
+ # solaris_sysv_init_start_states="S 0 1 2"
+ #
+}
+
+pp_solaris_smf () {
+ typeset f _pp_solaris_service_script svc _pp_solaris_manpage
+
+ pp_solaris_name=${pp_solaris_name:-$name}
+ pp_solaris_manpath=${pp_solaris_manpath:-"/usr/share/man"}
+ pp_solaris_mansect=${pp_solaris_mansect:-1}
+ smf_start_timeout=${smf_start_timeout:-60}
+ smf_stop_timeout=${smf_stop_timeout:-60}
+ smf_restart_timeout=${smf_restart_timeout:-60}
+
+ svc=${pp_solaris_smf_service_name:-$1}
+ _pp_solaris_service_script=${pp_solaris_service_script:-"/etc/init.d/${pp_solaris_service_script_name:-$svc}"}
+ _pp_solaris_manpage=${pp_solaris_manpage:-$svc}
+
+ if [ -z $pp_svc_xml_file ]; then
+ pp_svc_xml_file="/var/svc/manifest/$_smf_category/$svc.xml"
+ echo "## Generating the smf service manifest file for $pp_svc_xml_file"
+ else
+ echo "## SMF service manifest file already defined at $pp_svc_xml_file"
+ if [ -z $pp_solaris_smf_service_name ] || [ -z $pp_solaris_smf_category ] || [ -z $pp_solaris_service_script ] || [ -z $smf_method_envvar_name ]; then
+ pp_error "All required variables are not set.\n"\
+ "When using a custom manifest file all of the following variables must be set:\n"\
+ "pp_solaris_smf_service_name, pp_solaris_smf_category, pp_solaris_service_script and smf_method_envvar_name.\n\n"\
+ "Example:\n"\
+ " \$pp_solaris_smf_category=application\n"\
+ " \$pp_solaris_smf_service_name=pp\n\n"\
+ " <service name='application/pp' type='service' version='1'>\n\n"\
+ "Example:\n"\
+ " \$pp_solaris_service_script=/etc/init.d/pp\n\n"\
+ " <exec_method type='method' name='start' exec='/etc/init.d/pp' />\n\n"\
+ "Example:\n"\
+ " \$smf_method_envvar_name=PP_SMF_SERVICE\n\n"\
+ " <method_environment>\n"\
+ " <envvar name='PP_SMF_SERVICE' value='1'/>\n"\
+ " </method_environment>\n"
+
+ return 1
+ fi
+ return 0
+ fi
+
+ f=$pp_svc_xml_file
+ pp_add_file_if_missing $f ||
+ return 0
+ pp_solaris_add_parent_dirs "$f"
+
+ _pp_solaris_smf_dependencies="
+ <dependency name='pp_local_filesystems'
+ grouping='require_all'
+ restart_on='none'
+ type='service'>
+ <service_fmri value='svc:/system/filesystem/local'/>
+ </dependency>
+
+ <dependency name='pp_single-user'
+ grouping='require_all'
+ restart_on='none'
+ type='service'>
+ <service_fmri value='svc:/milestone/single-user' />
+ </dependency>
+"
+ _pp_solaris_smf_dependencies=${pp_solaris_smf_dependencies:-$_pp_solaris_smf_dependencies}
+
+ cat <<-. >$pp_destdir$f
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
+<!--
+ $copyright
+ Generated by PolyPackage $pp_version
+-->
+
+ <service_bundle type='manifest' name='${pp_solaris_name}:${svc}' >
+ <service name='$_smf_category/$svc'
+ type='$smf_type'
+ version='$smf_version'>
+
+ <create_default_instance enabled='false'/>
+
+ <single_instance />
+
+ $_pp_solaris_smf_dependencies
+
+ $pp_solaris_smf_additional_dependencies
+
+ <method_context>
+ <method_credential user='${solaris_user:-$user}' />
+ <method_environment>
+ <envvar name='$_smf_method_envvar_name' value='1'/>
+ </method_environment>
+ </method_context>
+
+ <exec_method type='method' name='start'
+ exec='$_pp_solaris_service_script start'
+ timeout_seconds='$smf_start_timeout' />
+
+ <exec_method type='method' name='stop'
+ exec='$_pp_solaris_service_script stop'
+ timeout_seconds='$smf_stop_timeout' />
+
+ <exec_method type='method' name='restart'
+ exec='$_pp_solaris_service_script restart'
+ timeout_seconds='$smf_restart_timeout' />
+
+ $pp_solaris_smf_property_groups
+
+ <template>
+ <common_name>
+ <loctext xml:lang='C'>$description</loctext>
+ </common_name>
+ <documentation>
+ <manpage title='$pp_solaris_manpage' section='$pp_solaris_mansect' manpath='$pp_solaris_manpath'/>
+ </documentation>
+ </template>
+ </service>
+ </service_bundle>
+.
+}
+
+pp_solaris_make_service_group () {
+ typeset group out file svcs svc
+
+ group="$1"
+ svcs="$2"
+ file="/etc/init.d/$group"
+ out="$pp_destdir$file"
+
+ #-- return if the script is supplied already
+ pp_add_file_if_missing "$file" run 755 || return 0
+ pp_solaris_add_parent_dirs "$file"
+
+ echo "#! /sbin/sh" > $out
+ echo "# polypkg service group script for these services:" >> $out
+ echo "svcs=\"$svcs\"" >> $out
+
+ cat <<'.' >>$out
+
+ #-- starts services in order.. stops them all if any break
+ pp_start () {
+ undo=
+ for svc in $svcs; do
+ if /etc/init.d/$svc start; then
+ undo="$svc $undo"
+ else
+ if test -n "$undo"; then
+ for svc in $undo; do
+ /etc/init.d/$svc stop
+ done
+ return 1
+ fi
+ fi
+ done
+ return 0
+ }
+
+ #-- stops services in reverse
+ pp_stop () {
+ reverse=
+ for svc in $svcs; do
+ reverse="$svc $reverse"
+ done
+ rc=0
+ for svc in $reverse; do
+ /etc/init.d/$svc stop || rc=$?
+ done
+ return $rc
+ }
+
+ #-- returns true only if all services return true status
+ pp_status () {
+ rc=0
+ for svc in $svcs; do
+ /etc/init.d/$svc status || rc=$?
+ done
+ return $rc
+ }
+
+ case "$1" in
+ start) pp_start;;
+ stop) pp_stop;;
+ status) pp_status;;
+ restart) pp_stop && pp_start;;
+ *) echo "usage: $0 {start|stop|restart|status}" >&2; exit 1;;
+ esac
+.
+}
+
+pp_solaris_make_service () {
+ typeset file out svc
+
+ svc="${pp_solaris_smf_service_name:-$1}"
+ file=${pp_solaris_service_script:-"/etc/init.d/${pp_solaris_service_script_name:-$svc}"}
+ out="$pp_destdir$file"
+
+ #-- return if we don't need to create the init script
+ pp_add_file_if_missing "$file" run 755 ||
+ return 0
+ pp_solaris_add_parent_dirs "$file"
+
+ echo "#! /sbin/sh" >$out
+ echo "#-- This service init file generated by polypkg" >>$out
+
+ #-- Start SMF integration.
+ if [ -n "$pp_svc_xml_file" ] ; then
+ cat <<_EOF >>$out
+if [ -x /usr/sbin/svcadm ] && [ "x\$1" != "xstatus" ] && [ "t\$$_smf_method_envvar_name" = "t" ] ; then
+ case "\$1" in
+ start)
+ echo "starting $svc"
+ /usr/sbin/svcadm clear svc:/$_smf_category/$svc:default >/dev/null 2>&1
+ /usr/sbin/svcadm enable -s $_smf_category/$svc
+ RESULT=\$?
+ if [ "\$RESULT" -ne 0 ] ; then
+ echo "Error \$RESULT starting $svc" >&2
+ fi
+ ;;
+ stop)
+ echo "stopping $svc"
+ /usr/sbin/svcadm disable -ts $_smf_category/$svc
+ RESULT=0
+ ;;
+ restart)
+ echo "restarting $svc"
+ /usr/sbin/svcadm disable -ts $_smf_category/$svc
+ /usr/sbin/svcadm clear svc:/$_smf_category/$svc:default >/dev/null 2>&1
+ /usr/sbin/svcadm enable -s $_smf_category/$svc
+ RESULT=\$?
+ if [ "\$RESULT" -ne 0 ] ; then
+ echo "Error \$RESULT starting $svc" >&2
+ fi
+ ;;
+ *)
+ echo "Usage: $file {start|stop|restart|status}" >&2
+ RESULT=1
+ esac
+ exit $RESULT
+fi
+_EOF
+ fi
+
+ #-- Construct a start command that builds a pid file as needed
+ # and forks the daemon. Services started by smf may not fork.
+ if test -z "$pidfile"; then
+ # The service does not define a pidfile, so we have to make
+ # our own up. On Solaris systems where there is no /var/run
+ # we must use /tmp to guarantee the pid files are removed after
+ # a system crash.
+ if test -z "$pp_piddir"; then
+ pp_piddir="/var/run"
+ fi
+ cat <<. >>$out
+ pp_isdaemon=0
+ pp_piddirs="${pp_piddir}${pp_piddir+ }/var/run /tmp"
+ for pp_piddir in \$pp_piddirs; do
+ test -d "\$pp_piddir/." && break
+ done
+ pidfile="\$pp_piddir/$svc.pid"
+.
+ else
+ # The service is able to write its own PID file
+ cat <<. >>$out
+ pp_isdaemon=1
+ pidfile="$pidfile"
+.
+ fi
+
+ pp_su=
+ if test "${user:-root}" != "root"; then
+ pp_su="su $user -c exec "
+ fi
+
+ cat <<. >>$out
+ stop_signal="${stop_signal:-TERM}"
+ svc="${svc}"
+
+ # generated command to run $svc as a service
+ pp_exec () {
+ if [ \$pp_isdaemon -ne 1 ]; then
+ if [ "t\$PP_SMF_SERVICE" = "t" ]; then
+ ${pp_su}$cmd &
+ echo \$! > \$pidfile
+ else
+ echo "via exec."
+ echo \$$ > \$pidfile
+ exec ${pp_su}$cmd
+ return 1
+ fi
+ else
+ ${pp_su}$cmd
+ fi
+ }
+.
+
+ #-- write the invariant section of the init script
+ cat <<'.' >>$out
+
+ # returns true if $svc is running
+ pp_running () {
+ if test -s "$pidfile"; then
+ read pid < "$pidfile" 2>/dev/null
+ if test ${pid:-0} -gt 1 && kill -0 "$pid" 2>/dev/null; then
+ # make sure command name matches up to the first 8 chars
+ c="`echo $cmd | sed -e 's: .*::' -e 's:^.*/::' -e 's/^\(........\).*$/\1/'`"
+ pid="`ps -p $pid 2>/dev/null | sed -n \"s/^ *\($pid\) .*$c *$/\1/p\"`"
+ if test -n "$pid"; then
+ return 0
+ fi
+ fi
+ fi
+ return 1
+ }
+
+ # prints a message describing $svc's running state
+ pp_status () {
+ if pp_running; then
+ echo "service $svc is running (pid $pid)"
+ return 0
+ elif test -f "$pidfile"; then
+ echo "service $svc is not running, but pid file exists"
+ return 2
+ else
+ echo "service $svc is not running"
+ return 1
+ fi
+ }
+
+ # starts $svc
+ pp_start () {
+ if pp_running; then
+ echo "service $svc already running" >&2
+ return 0
+ fi
+ echo "starting $svc... \c"
+ if pp_exec; then
+ echo "done."
+ else
+ echo "ERROR."
+ exit 1
+ fi
+ }
+
+ # stops $svc
+ pp_stop () {
+ if pp_running; then
+ echo "stopping $svc... \c"
+ if kill -$stop_signal $pid; then
+ rm -f "$pidfile"
+ echo "done."
+ else
+ echo "ERROR."
+ return 1
+ fi
+ else
+ echo "service $svc already stopped" >&2
+ return 0
+ fi
+ }
+
+ umask 022
+ case "$1" in
+ start) pp_start;;
+ stop) pp_stop;;
+ status) pp_status;;
+ restart) pp_stop && pp_start;;
+ *) echo "usage: $0 {start|stop|restart|status}" >&2; exit 1;;
+ esac
+.
+}
+
+pp_solaris_remove_service () {
+ typeset file svc
+
+ svc="${pp_solaris_smf_service_name:-$1}"
+ file=${pp_solaris_service_script:-"/etc/init.d/${pp_solaris_service_script_name:-$svc}"}
+
+ echo '
+if [ "x${PKG_INSTALL_ROOT}" = 'x' ]; then
+ if [ -x /usr/sbin/svcadm ] ; then
+ /usr/sbin/svcadm disable -s '$svc' 2>/dev/null
+ if [ `uname -r` = 5.10 ] || [ "'${pp_svc_xml_file%/*/*}'" != "/var/svc/manifest" ]; then
+ /usr/sbin/svccfg delete '$svc' 2>/dev/null
+ else
+ /usr/sbin/svcadm restart manifest-import 2>/dev/null
+ fi
+ else
+ '$file' stop >/dev/null 2>/dev/null
+ fi
+fi
+ '
+}
+
+pp_solaris_install_service () {
+ typeset s k l file svc
+
+ svc="${pp_solaris_smf_service_name:-$1}"
+ file=${pp_solaris_service_script:-"/etc/init.d/${pp_solaris_service_script_name:-$svc}"}
+
+ s="${solaris_sysv_init_start}$svc"
+ k="${solaris_sysv_init_kill}$svc"
+
+ echo '
+if [ "x${PKG_INSTALL_ROOT}" != "x" ]; then
+ if [ -x ${PKG_INSTALL_ROOT}/usr/sbin/svcadm ]; then
+ if [ `uname -r` = 5.10 ] || [ "'${pp_svc_xml_file%/*/*}'" != "/var/svc/manifest" ]; then
+ echo "/usr/sbin/svccfg import '$pp_svc_xml_file' 2>/dev/null" >> ${PKG_INSTALL_ROOT}/var/svc/profile/upgrade
+ else
+ echo "/usr/sbin/svcadm restart manifest-import 2>/dev/null" >> ${PKG_INSTALL_ROOT}/var/svc/profile/upgrade
+ fi
+ else'
+ test -n "${solaris_sysv_init_start_states}" &&
+ for state in ${solaris_sysv_init_start_states}; do
+ l="/etc/rc$state.d/$s"
+ echo "echo '$l'"
+ echo "installf -c run \$PKGINST \$PKG_INSTALL_ROOT$l=$file s"
+ pp_solaris_space /etc/rc$state.d 0 1
+ done
+ test -n "${solaris_sysv_init_kill_states}" &&
+ for state in ${solaris_sysv_init_kill_states}; do
+ l="/etc/rc$state.d/$k"
+ echo "echo '$l'"
+ echo "installf -c run \$PKGINST \$PKG_INSTALL_ROOT$l=$file s"
+ pp_solaris_space /etc/rc$state.d 0 1
+ done
+ echo '
+ fi
+else
+ if [ -x /usr/sbin/svcadm ]; then
+ echo "Registering '$svc' with SMF"
+ /usr/sbin/svcadm disable -s '$svc' 2>/dev/null
+ if [ `uname -r` = 5.10 ] || [ "'${pp_svc_xml_file%/*/*}'" != "/var/svc/manifest" ]; then
+ /usr/sbin/svccfg delete '$svc' 2>/dev/null
+ /usr/sbin/svccfg import '$pp_svc_xml_file'
+ else
+ /usr/sbin/svcadm restart manifest-import
+ # Wait for import to complete, otherwise it will not know
+ # about our service until after we try to start it
+ echo Waiting for manifest-import...
+ typeset waited
+ waited=0
+ while [ $waited -lt 15 ] && ! /usr/bin/svcs -l '$svc' >/dev/null 2>&1; do
+ sleep 1
+ waited=`expr $waited + 1`
+ done
+ if /usr/bin/svcs -l '$svc' >/dev/null 2>&1; then
+ echo OK
+ else
+ echo manifest-import took to long, you might have to control '$svc' manually.
+ fi
+ fi
+ else'
+ test -n "${solaris_sysv_init_start_states}" &&
+ for state in ${solaris_sysv_init_start_states}; do
+ l="/etc/rc$state.d/$s"
+ echo "echo '$l'"
+ echo "installf -c run \$PKGINST \$PKG_INSTALL_ROOT$l=$file s"
+ pp_solaris_space /etc/rc$state.d 0 1
+ done
+ test -n "${solaris_sysv_init_kill_states}" &&
+ for state in ${solaris_sysv_init_kill_states}; do
+ l="/etc/rc$state.d/$k"
+ echo "echo '$l'"
+ echo "installf -c run \$PKGINST \$PKG_INSTALL_ROOT$l=$file s"
+ pp_solaris_space /etc/rc$state.d 0 1
+ done
+ echo '
+ fi
+fi'
+}
+
+pp_solaris_add_parent_dirs () {
+ typeset dir
+
+ dir=${1%/*}
+ while test -n "$dir"; do
+ if awk "\$6 == \"$dir/\" {exit 1}" < $pp_wrkdir/%files.run; then
+ echo "d - - - - $dir/" >> $pp_wrkdir/%files.run
+ fi
+ dir=${dir%/*}
+ done
+}
+
+pp_platforms="$pp_platforms deb"
+
+pp_backend_deb_detect () {
+ test -f /etc/debian_version
+}
+
+pp_deb_cmp_full_name () {
+ local prefix
+ prefix="${pp_deb_name:-$name}"
+ case "$1" in
+ run) echo "${prefix}" ;;
+ dbg) echo "${prefix}-${pp_deb_dbg_pkgname}";;
+ dev) echo "${prefix}-${pp_deb_dev_pkgname}";;
+ doc) echo "${prefix}-${pp_deb_doc_pkgname}";;
+ *) pp_error "unknown component '$1'";
+ esac
+}
+
+pp_backend_deb_init () {
+ pp_deb_dpkg_version="2.0"
+ pp_deb_name=
+ pp_deb_version=
+ pp_deb_release=
+ pp_deb_arch=
+ pp_deb_arch_std=
+ pp_deb_maintainer="One Identity LLC <support@oneidentity.com>"
+ pp_deb_copyright=
+ pp_deb_distro=
+ pp_deb_control_description=
+ pp_deb_summary=
+ pp_deb_description=
+ pp_deb_dbg_pkgname="dbg"
+ pp_deb_dev_pkgname="dev"
+ pp_deb_doc_pkgname="doc"
+ pp_deb_section=contrib # Free software that depends on non-free software
+
+ # Detect the host architecture
+ pp_deb_detect_arch
+
+ # Make sure any programs we require are installed
+ pp_deb_check_required_programs
+}
+
+pp_deb_check_required_programs () {
+ local p needed notfound ok
+ needed= notfound=
+ for prog in dpkg dpkg-deb install md5sum fakeroot
+ do
+ if command -v $prog 2>/dev/null >/dev/null; then
+ pp_debug "$prog: found"
+ else
+ pp_debug "$prog: not found"
+ case "$prog" in
+ dpkg|dpkg-deb) p=dpkg;;
+ install|md5sum) p=coreutils;;
+ fakeroot) p=fakeroot;;
+ *) pp_die "unexpected dpkg tool $prog";;
+ esac
+ notfound="$notfound $prog"
+ pp_contains "$needed" "$p" || needed="$needed $p"
+ fi
+ done
+ if [ -n "$notfound" ]; then
+ pp_error "cannot find these programs: $notfound"
+ pp_error "please install these packages: $needed"
+ fi
+}
+
+pp_deb_munge_description () {
+ # Insert a leading space on each line, replace blank lines with a
+ #space followed by a full-stop.
+ pp_deb_control_description="`echo ${pp_deb_description:-$description} | \
+ sed 's,^\(.*\)$, \1, ' | sed 's,^[ \t]*$, .,g' | fmt -w 80`"
+}
+
+pp_deb_detect_arch () {
+ pp_deb_arch=`dpkg-architecture -qDEB_HOST_ARCH`
+ pp_deb_arch_std=`uname -m`
+}
+
+pp_deb_sanitize_version() {
+ echo "$@" | tr -d -c '[:alnum:].+-:~'
+}
+
+pp_deb_version_final() {
+ if test -n "$pp_deb_version"; then
+ # Don't sanitize; assume the user is sane (hah!)
+ echo "$pp_deb_version"
+ else
+ pp_deb_sanitize_version "$version"
+ fi
+}
+
+pp_deb_conflict () {
+ local _name _vers _conflicts
+
+ _conflicts="Conflicts:"
+ while read _name _vers; do
+ case "$_name" in ""| "#"*) continue ;; esac
+ _conflicts="$_conflicts $_name"
+ test -n "$_vers" && _conflicts="$_conflicts $_name (>= $vers)"
+ _conflicts="${_conflicts},"
+ done
+ echo "${_conflicts%,}"
+}
+
+pp_deb_make_control() {
+ local cmp="$1"
+ local installed_size
+
+ # compute the installed size
+ installed_size=`pp_deb_files_size < $pp_wrkdir/%files.$cmp`
+
+ package_name=`pp_deb_cmp_full_name "$cmp"`
+ cat <<-.
+ Package: ${package_name}
+ Version: `pp_deb_version_final`-${pp_deb_release:-1}
+ Section: ${pp_deb_section:-contrib}
+ Priority: optional
+ Architecture: ${pp_deb_arch}
+ Maintainer: ${pp_deb_maintainer:-$maintainer}
+ Description: ${pp_deb_summary:-$summary}
+ ${pp_deb_control_description}
+ Installed-Size: ${installed_size}
+.
+ if test -s $pp_wrkdir/%depend."$cmp"; then
+ sed -ne '/^[ ]*$/!s/^[ ]*/Depends: /p' \
+ < $pp_wrkdir/%depend."$cmp"
+ fi
+ if test -s $pp_wrkdir/%conflict."$cmp"; then
+ pp_deb_conflict < $pp_wrkdir/%conflict."$cmp"
+ fi
+}
+
+pp_deb_make_md5sums() {
+ local cmp="$1"; shift
+ local pkg_dir
+
+ pkg_dir=$pp_wrkdir/`pp_deb_cmp_full_name $cmp`
+ (cd $pkg_dir && md5sum "$@") > $pkg_dir/DEBIAN/md5sums ||
+ pp_error "cannot make md5sums"
+}
+
+pp_deb_make_package_maintainer_script() {
+ local output="$1"
+ local source="$2"
+ local desc="$3"
+
+ # See if we need to create this script at all
+ if [ -s "$source" ]
+ then
+
+ # Create header
+ cat <<-. >$output || pp_error "Cannot create $output"
+ #!/bin/sh
+ # $desc
+ # Generated by PolyPackage $pp_version
+
+.
+
+ cat $source >> "$output" || pp_error "Cannot append to $output"
+
+ # Set perms
+ chmod 755 "$output" || pp_error "Cannot chmod $output"
+ fi
+}
+
+pp_deb_handle_services() {
+ local svc
+
+ #-- add service start/stop code
+ if test -n "$pp_services"; then
+ #-- append common %post install code
+ pp_systemd_service_install_common >> $pp_wrkdir/%post.run
+
+ #-- record the uninstall commands in reverse order
+ for svc in $pp_services; do
+ pp_load_service_vars $svc
+
+ # Create init script and systemd service file (unless they exists)
+ pp_deb_service_make_service_files $svc ||
+ pp_error "could not create service files for $svc"
+
+ #-- append %post code to install the svc
+ test x"yes" = x"$enable" &&
+ cat<<-. >> $pp_wrkdir/%post.run
+
+ case "\$1" in
+ configure)
+ # Install the service links
+ _pp_systemd_init
+ if test -n "\$systemctl_cmd"; then
+ _pp_systemd_install $svc
+ _pp_systemd_enable $svc
+ else
+ update-rc.d $svc defaults
+ fi
+ ;;
+ esac
+.
+
+ #-- prepend %preun code to stop svc
+ cat<<-. | pp_prepend $pp_wrkdir/%preun.run
+
+ case "\$1" in
+ remove|deconfigure|upgrade)
+ # Stop the $svc service
+ invoke-rc.d $svc stop
+ _pp_systemd_disable $svc
+ ;;
+ esac
+.
+
+ #-- prepend %postun code to remove service
+ cat<<-. | pp_prepend $pp_wrkdir/%postun.run
+
+ case "\$1" in
+ purge)
+ # Remove the service links
+ update-rc.d $svc remove
+ _pp_systemd_remove $svc
+ ;;
+ esac
+.
+ done
+
+ pp_systemd_service_remove_common | pp_prepend $pp_wrkdir/%preun.run
+ #pp_deb_service_remove_common | pp_prepend $pp_wrkdir/%preun.run
+
+ # Actual systemd service removal is done in %postun.
+ # Otherwise, systemd may pick up the init.d script if it exists.
+ pp_systemd_service_remove_common | pp_prepend $pp_wrkdir/%postun.run
+ fi
+
+}
+pp_deb_fakeroot () {
+ if test -s $pp_wrkdir/fakeroot.save; then
+ fakeroot -i $pp_wrkdir/fakeroot.save -s $pp_wrkdir/fakeroot.save "$@"
+ else
+ fakeroot -s $pp_wrkdir/fakeroot.save "$@"
+ fi
+}
+
+pp_deb_files_size () {
+ local t m o g f p st
+ while read t m o g f p st; do
+ case $t in
+ f|s) du -k "${pp_destdir}$p";;
+ d) echo 4;;
+ esac
+ done | awk '{n+=$1} END {print n}'
+}
+
+pp_deb_make_DEBIAN() {
+ local cmp="${1:-run}"
+ local data cmp_full_name
+ local old_umask
+
+ old_umask=`umask`
+ umask 0022
+ cmp_full_name=`pp_deb_cmp_full_name $cmp`
+ data=$pp_wrkdir/$cmp_full_name
+
+ # Create DEBIAN dir $data/DEBIAN
+ mkdir -p $data/DEBIAN
+
+ # Create control file
+ pp_deb_make_control $cmp > $data/DEBIAN/control
+
+ # Copy in conffiles
+ if test -f $pp_wrkdir/%conffiles.$cmp; then
+ cp $pp_wrkdir/%conffiles.$cmp $data/DEBIAN/conffiles
+ fi
+
+ # Create preinst
+ pp_deb_make_package_maintainer_script "$data/DEBIAN/preinst" \
+ "$pp_wrkdir/%pre.$cmp" "Pre-install script for $cmp_full_name"\
+ || exit $?
+
+ # Create postinst
+ pp_deb_make_package_maintainer_script "$data/DEBIAN/postinst" \
+ "$pp_wrkdir/%post.$cmp" "Post-install script for $cmp_full_name"\
+ || exit $?
+
+ # Create prerm
+ pp_deb_make_package_maintainer_script "$data/DEBIAN/prerm" \
+ "$pp_wrkdir/%preun.$cmp" "Pre-uninstall script for $cmp_full_name"\
+ || exit $?
+
+ # Create postrm
+ pp_deb_make_package_maintainer_script "$data/DEBIAN/postrm" \
+ "$pp_wrkdir/%postun.$cmp" "Post-uninstall script for $cmp_full_name"\
+ || exit $?
+
+ umask $old_umask
+}
+
+pp_deb_make_data() {
+ local _l t m o g f p st data
+ local data share_doc owner group
+ cmp=$1
+ data=$pp_wrkdir/`pp_deb_cmp_full_name $cmp`
+ cat $pp_wrkdir/%files.${cmp} | while read t m o g f p st; do
+ if test x"$m" = x"-"; then
+ case "$t" in
+ d) m=755;;
+ f) m=644;;
+ esac
+ fi
+ test x"$o" = x"-" && o=root
+ test x"$g" = x"-" && g=root
+ case "$t" in
+ f) # Files
+ pp_deb_fakeroot install -D -o $o -g $g -m ${m} $pp_destdir/$p $data/$p;
+ case "$f" in
+ *v*)
+ # File marked as "volatile". Assume this means it's a conffile
+ # TODO: check this as admins like modified conffiles to be left
+ # behind
+ echo "$p" >> $pp_wrkdir/%conffiles.$cmp
+ ;;
+ esac
+ ;;
+
+ d) # Directories
+ pp_deb_fakeroot install -m ${m} -o $o -g $g -d $data/$p;;
+
+ s) # Symlinks
+ # Remove leading / from vars
+ rel_p=`echo $p | sed s,^/,,`
+ rel_st=`echo $st | sed s,^/,,`
+ # TODO: we are always doing absolute links here. We should follow
+ # the debian policy of relative links when in the same top-level
+ # directory
+ (cd $data; ln -sf $st $rel_p);;
+ *) pp_error "Unsupported data file type: $t";;
+ esac
+ done
+
+ # If no copyright file is present add one. This is a debian requirement.
+ share_doc="/usr/share/doc/`pp_deb_cmp_full_name $cmp`"
+ if [ ! -f "$data/$share_doc/copyright" ]
+ then
+ echo "${pp_deb_copyright:-$copyright}" > "$pp_wrkdir/copyright"
+ install -D -m 644 "$pp_wrkdir/copyright" "$data/$share_doc/copyright"
+ fi
+
+}
+
+pp_deb_makedeb () {
+ local cmp
+ local package_build_dir
+
+ cmp="$1"
+
+ package_build_dir=$pp_wrkdir/`pp_deb_cmp_full_name $cmp`
+
+ # Create package dir
+ mkdir -p $package_build_dir
+
+ # Copy in data
+ pp_deb_make_data $cmp ||
+ pp_die "Could not make DEBIAN data files for $cmp"
+
+ # Make control files
+ # must be done after copying data so conffiles are found
+ pp_deb_make_DEBIAN $cmp ||
+ pp_die "Could not make DEBIAN control files for $cmp"
+
+ # Create md5sums
+ pp_deb_make_md5sums $cmp `(cd $package_build_dir;
+ find . -name DEBIAN -prune -o -type f -print | sed "s,^\./,,")` ||
+ pp_die "Could not make DEBIAN md5sums for $cmp"
+}
+
+pp_backend_deb () {
+ local debname
+
+ # Munge description for control file inclusion
+ pp_deb_munge_description
+
+ # Handle services
+ pp_deb_handle_services $cmp
+
+ for cmp in $pp_components
+ do
+ debname=`pp_deb_name $cmp`
+ pp_deb_makedeb $cmp
+ done
+
+ . $pp_wrkdir/%fixup
+
+ for cmp in $pp_components
+ do
+ debname=`pp_deb_name $cmp`
+ # Create debian package
+ pp_debug "Building `pp_deb_cmp_full_name $cmp` -> $output"
+ pp_deb_fakeroot dpkg-deb \
+ --build $pp_wrkdir/`pp_deb_cmp_full_name $cmp` \
+ $pp_wrkdir/$debname ||
+ pp_error "failed to create $cmp package"
+ done
+}
+
+pp_backend_deb_cleanup () {
+ # rm -rf $pp_wrkdir
+ :
+}
+
+pp_deb_name () {
+ local cmp="${1:-run}"
+ echo `pp_deb_cmp_full_name $cmp`"_"`pp_deb_version_final`"-${pp_deb_release:-1}_${pp_deb_arch}.deb"
+}
+pp_backend_deb_names () {
+ for cmp in $pp_components
+ do
+ pp_deb_name $cmp
+ done
+}
+
+pp_backend_deb_install_script () {
+ local cmp _cmp_full_name
+
+ echo "#!/bin/sh"
+ pp_install_script_common
+
+ cat <<.
+
+ cmp_to_pkgname () {
+ test x"\$*" = x"all" &&
+ set -- $pp_components
+ for cmp
+ do
+ case \$cmp in
+.
+ for cmp in $pp_components; do
+ echo "$cmp) echo '`pp_deb_cmp_full_name $cmp`';;"
+ done
+ cat <<.
+ *) usage;;
+ esac
+ done
+ }
+
+
+ cmp_to_pathname () {
+ test x"\$*" = x"all" &&
+ set -- $pp_components
+ for cmp
+ do
+ case \$cmp in
+.
+ for cmp in $pp_components; do
+ echo "$cmp) echo \${PP_PKGDESTDIR:-.}/'`pp_deb_name $cmp`';;"
+ done
+ cat <<.
+ *) usage;;
+ esac
+ done
+ }
+
+ test \$# -eq 0 && usage
+ op="\$1"; shift
+ case "\$op" in
+ list-components)
+ test \$# -eq 0 || usage \$op
+ echo $pp_components
+ ;;
+ list-services)
+ test \$# -eq 0 || usage \$op
+ echo $pp_services
+ ;;
+ list-files)
+ test \$# -ge 1 || usage \$op
+ cmp_to_pathname "\$@"
+ ;;
+ install)
+ test \$# -ge 1 || usage \$op
+ dpkg --install \`cmp_to_pathname "\$@"\`
+ ;;
+ uninstall)
+ test \$# -ge 1 || usage \$op
+ dpkg --remove \`cmp_to_pkgname "\$@"\`; :
+ ;;
+ start|stop)
+ test \$# -ge 1 || usage \$op
+ ec=0
+ for svc
+ do
+ /etc/init.d/\$svc \$op || ec=1
+ done
+ exit \$ec
+ ;;
+ print-platform)
+ test \$# -eq 0 || usage \$op
+ echo "linux-${pp_deb_arch}"
+ ;;
+ *)
+ usage
+ ;;
+ esac
+.
+}
+
+pp_backend_deb_probe() {
+ local arch distro release
+
+ pp_deb_detect_arch
+
+ # /etc/debian_version exists on Debian & Ubuntu, so it's no use
+ # to us. Use lsb_release instead.
+
+ case `(lsb_release -is || echo no-lsb) 2>/dev/null` in
+ Debian)
+ distro=deb
+ ;;
+ Ubuntu)
+ distro=ubu
+ ;;
+ no-lsb)
+ echo unknown-$pp_deb_arch_std
+ return 0
+ ;;
+ *)
+ distro=unknown
+ ;;
+ esac
+
+ release=`lsb_release -rs`
+
+ # If release is not numeric, use the codename
+ case $release in
+ *[!.0-9r]*)
+ release=`lsb_release -cs`
+ case $release in
+ buzz)
+ release="11"
+ ;;
+ rex)
+ release="12"
+ ;;
+ bo)
+ release="13"
+ ;;
+ hamm)
+ release="20"
+ ;;
+ slink)
+ release="21"
+ ;;
+ potato)
+ release="22"
+ ;;
+ woody)
+ release="30"
+ ;;
+ sarge)
+ release="31"
+ ;;
+ etch)
+ release="40"
+ ;;
+ lenny)
+ release="50"
+ ;;
+ squeeze)
+ release="60"
+ ;;
+ wheezy)
+ release="70"
+ ;;
+ jessie)
+ release="80"
+ ;;
+ stretch)
+ release="90"
+ ;;
+ esac
+ ;;
+ *)
+ # Remove trailing revision number and any dots
+ release=`echo $release | cut -dr -f1 | tr -d .`
+ ;;
+ esac
+
+ echo $distro$release-$pp_deb_arch_std
+}
+
+pp_backend_deb_vas_platforms () {
+ case "$pp_deb_arch_std" in
+ x86_64) echo "linux-x86_64.deb";; # DO NOT add linux-x86.deb here!!
+ *86) echo "linux-x86.deb";;
+ *) pp_die "unknown architecture ${pp_deb_arch_std}";;
+ esac
+}
+pp_backend_deb_init_svc_vars () {
+
+ reload_signal=
+ start_runlevels=${pp_deb_default_start_runlevels-"2 3 4 5"} # == lsb default-start
+ stop_runlevels=${pp_deb_default_stop_runlevels-"0 1 6"} # == lsb default-stop
+ svc_description="${pp_deb_default_svc_description}" # == lsb short descr
+ svc_process=
+ svc_init_filename="${pp_deb_svc_init_filename}" # == $svc.init
+ svc_init_filepath="${pp_deb_svc_init_filepath}" # == /etc/init.d/ by default
+
+ lsb_required_start='$local_fs $network'
+ lsb_should_start=
+ lsb_required_stop='$local_fs'
+ lsb_description=
+
+ start_priority=50
+ stop_priority=50 #-- stop_priority = 100 - start_priority
+}
+
+pp_deb_service_make_service_files () {
+ local svc=${svc_init_filename:-$1}
+ local script="${svc_init_filepath:-"/etc/init.d"}/$svc"
+ local out=$pp_destdir$script
+ local _process _cmd
+
+ pp_add_file_if_missing $script run 755 v || return 0
+
+ #-- start out as an empty shell script
+ cat <<-'.' >$out
+ #!/bin/sh
+.
+
+ #-- determine the process name from $cmd unless $svc_process is given
+ set -- $cmd
+ #_process=${svc_process:-"$1"} --? WTF
+
+ #-- construct a start command that builds a pid file if needed
+ #-- the command name in /proc/[pid]/stat is limited to 15 characters
+ _cmd="$cmd";
+ _cmd_path=`echo $cmd | cut -d" " -f1`
+ _cmd_name=`basename $_cmd_path | cut -c1-15`
+ _cmd_args=`echo $cmd | cut -d" " -f2-`
+ test x"$_cmd_path" != x"$_cmd_args" || _cmd_args=
+
+ #-- generate the LSB init info
+ cat <<-. >>$out
+ ### BEGIN INIT INFO
+ # Provides: ${svc}
+ # Required-Start: ${lsb_required_start}
+ # Should-Start: ${lsb_should_start}
+ # Required-Stop: ${lsb_required_stop}
+ # Default-Start: ${start_runlevels}
+ # Default-Stop: ${stop_runlevels}
+ # Short-Description: ${svc_description:-no description}
+ ### END INIT INFO
+ # Generated by PolyPackage ${pp_version}
+ # ${copyright}
+
+.
+
+ if test x"${svc_description}" = x"${pp_deb_default_svc_description}"; then
+ svc_description=
+ fi
+
+ #-- write service-specific definitions
+ cat <<. >>$out
+NAME="${_cmd_name}"
+DESC="${svc_description:-$svc service}"
+USER="${user}"
+GROUP="${group}"
+PIDFILE="${pidfile}"
+STOP_SIGNAL="${stop_signal}"
+RELOAD_SIGNAL="${reload_signal}"
+CMD="${_cmd}"
+DAEMON="${_cmd_path}"
+DAEMON_ARGS="${_cmd_args}"
+SCRIPTNAME=${script}
+.
+
+ #-- write the generic part of the init script
+ cat <<'.' >>$out
+
+[ -x "$DAEMON" ] || exit 0
+
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+[ -f /etc/default/rcS ] && . /etc/default/rcS
+
+. /lib/lsb/init-functions
+
+do_start()
+{
+ # Return
+ # 0 if daemon has been started
+ # 1 if daemon was already running
+ # 2 if daemon could not be started
+ if [ -n "$PIDFILE" ]
+ then
+ pidfile_opt="--pidfile $PIDFILE"
+ else
+ pidfile_opt="--make-pidfile --background --pidfile /var/run/$NAME.pid"
+ fi
+ if [ -n "$USER" ]
+ then
+ user_opt="--user $USER"
+ fi
+ if [ -n "$GROUP" ]
+ then
+ group_opt="--group $GROUP"
+ fi
+
+ start-stop-daemon --start --quiet $pidfile_opt $user_opt --exec $DAEMON --test > /dev/null \
+ || return 1
+
+ # Note: there seems to be no way to tell whether the daemon will fork itself or not, so pass
+ # --background for now
+ start-stop-daemon --start --quiet $pidfile_opt $user_opt --exec $DAEMON -- \
+ $DAEMON_ARGS \
+ || return 2
+}
+
+do_stop()
+{
+ # Return
+ # 0 if daemon has been stopped
+ # 1 if daemon was already stopped
+ # 2 if daemon could not be stopped
+ # other if a failure occurred
+ if [ -n "$PIDFILE" ]
+ then
+ pidfile_opt="--pidfile $PIDFILE"
+ else
+ pidfile_opt="--pidfile /var/run/$NAME.pid"
+ fi
+ if [ -n "$USER" ]
+ then
+ user_opt="--user $USER"
+ fi
+ if [ -n $STOP_SIGNAL ]
+ then
+ signal_opt="--signal $STOP_SIGNAL"
+ fi
+ start-stop-daemon --stop --quiet $signal_opt --retry=TERM/30/KILL/5 $pidfile_opt --name $NAME
+ RETVAL="$?"
+ [ "$RETVAL" = 2 ] && return 2
+ # Wait for children to finish too if this is a daemon that forks
+ # and if the daemon is only ever run from this initscript.
+ # If the above conditions are not satisfied then add some other code
+ # that waits for the process to drop all resources that could be
+ # needed by services started subsequently. A last resort is to
+ # sleep for some time.
+ start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
+ [ "$?" = 2 ] && return 2
+ # Many daemons don't delete their pidfiles when they exit.
+ test -z $PIDFILE || rm -f $PIDFILE
+ return "$RETVAL"
+}
+
+do_reload() {
+ #
+ # If the daemon can reload its configuration without
+ # restarting (for example, when it is sent a SIGHUP),
+ # then implement that here.
+ #
+ if [ -n "$PIDFILE" ]
+ then
+ pidfile_opt="--pidfile $PIDFILE"
+ else
+ pidfile_opt="--pidfile /var/run/$NAME.pid"
+ fi
+ if [ -n "$RELOAD_SIGNAL" ]
+ then
+ start-stop-daemon --stop --signal $RELOAD_SIGNAL --quiet $pidfile_opt --name $NAME
+ fi
+ return 0
+}
+
+case "$1" in
+ start)
+ [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+ do_start
+ case "$?" in
+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+ esac
+ ;;
+ stop)
+ [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+ do_stop
+ case "$?" in
+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+ esac
+ ;;
+ reload|force-reload)
+ if [ -n "$RELOAD_SIGNAL" ]
+ then
+ log_daemon_msg "Reloading $DESC" "$NAME"
+ do_reload
+ log_end_msg $?
+ else
+ # Do a restart instead
+ "$0" restart
+ fi
+ ;;
+ restart)
+ #
+ # If the "reload" option is implemented then remove the
+ # 'force-reload' alias
+ #
+ log_daemon_msg "Restarting $DESC" "$NAME"
+ do_stop
+ case "$?" in
+ 0|1)
+ do_start
+ case "$?" in
+ 0) log_end_msg 0 ;;
+ 1) log_end_msg 1 ;; # Old process is still running
+ *) log_end_msg 1 ;; # Failed to start
+ esac
+ ;;
+ *)
+ # Failed to stop
+ log_end_msg 1
+ ;;
+ esac
+ ;;
+ *)
+ #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+ echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
+ exit 3
+ ;;
+esac
+
+:
+.
+ chmod 755 $out
+
+ # Create systemd service file
+ pp_systemd_make_service_file $svc
+}
+pp_backend_deb_function() {
+ case "$1" in
+ pp_mkgroup) cat<<'.';;
+ /usr/sbin/groupmod "$1" 2>/dev/null && return 0
+ /usr/sbin/groupadd "$1"
+.
+ pp_mkuser:depends) echo pp_mkgroup;;
+ pp_mkuser) cat<<'.';;
+ pp_tmp_system=
+ id -u "$1" >/dev/null 2>/dev/null && return 0
+ # deb 3.1's useradd changed API in 4.0. Gah!
+ /usr/sbin/useradd --help 2>&1 | /bin/grep -q .--system &&
+ pp_tmp_system=--system
+ pp_mkgroup "${2:-$1}" || return 1
+ /usr/sbin/useradd \
+ -g "${2:-$1}" \
+ -d "${3:-/nonexistent}" \
+ -s "${4:-/bin/false}" \
+ $pp_tmp_system \
+ "$1"
+.
+ pp_havelib) cat<<'.';;
+ for pp_tmp_dir in `echo "/usr/lib:/lib${3:+:$3}" | tr : ' '`; do
+ test -r "$pp_tmp_dir/lib$1.so{$2:+.$2}" && return 0
+ done
+ return 1
+.
+ *) false;;
+ esac
+}
+
+pp_platforms="$pp_platforms kit"
+
+pp_backend_kit_detect () {
+ test x"$1" = x"OSF1"
+}
+
+pp_backend_kit_init () {
+ pp_kit_name=
+ pp_kit_package=
+ pp_kit_desc=
+ pp_kit_version=
+ pp_kit_subset=
+ pp_readlink_fn=pp_ls_readlink
+ pp_kit_startlevels="2 3"
+ pp_kit_stoplevels="0 2 3"
+}
+
+pp_backend_kit () {
+ typeset mi_file k_file svc outfile
+ typeset desc
+
+ pp_backend_kit_names > /dev/null
+
+ if test -z "$pp_kit_desc"; then
+ pp_kit_desc="$description"
+ fi
+
+ mi_file="$pp_wrkdir/$pp_kit_subset.mi"
+ k_file="$pp_wrkdir/$pp_kit_subset.k"
+ scp_file="$pp_wrkdir/$pp_kit_subset.scp"
+
+ desc="${pp_kit_desc:-$description}"
+
+ cat <<-. >> $k_file
+ NAME='$name'
+ CODE=$pp_kit_name
+ VERS=$pp_kit_version
+ MI=$mi_file
+ COMPRESS=0
+ %%
+ $pp_kit_subset . 0 '$desc'
+.
+
+ if test -n "$pp_services"; then
+ for svc in $pp_services; do
+ pp_kit_make_service $svc
+ pp_prepend $pp_wrkdir/%preun.run <<-.
+ /sbin/init.d/$svc stop
+.
+ done
+ fi
+
+ pp_backend_kit_make_mi "$mi_file"
+ pp_backend_kit_make_scp
+ #rm -rf $pp_wrkdir/kit_dest
+ mkdir -p $pp_wrkdir/kit_dest
+ pp_backend_kit_kits $k_file $pp_opt_destdir $pp_wrkdir/kit_dest
+ tar cvf $pp_wrkdir/$pp_kit_subset.tar -C $pp_wrkdir/kit_dest .
+ gzip -c $pp_wrkdir/$pp_kit_subset.tar > $pp_wrkdir/$pp_kit_subset.tar.gz
+ #rm -rf $pp_wrkdir/$pp_kit_subset.tar $pp_wrkdir/scps
+}
+
+pp_backend_kit_make_mi () {
+ # XXX this information should go into the .inv files
+ typeset t m o g f p st line dm
+ while read t m o g f p st; do
+ case $t in
+ f|d)
+ echo "0 .$p $pp_kit_subset"
+ echo " chmod $m $p" >> $pp_wrkdir/%post.run
+ if [ x"$o" = x"-" ] ; then
+ echo " chown root $p" >> $pp_wrkdir/%post.run
+ else
+ echo " chown $o $p" >> $pp_wrkdir/%post.run
+ fi
+ if [ x"$g" = x"-" ] ; then
+ echo " chgrp 0 $p" >> $pp_wrkdir/%post.run
+ else
+ echo " chgrp $g $p" >> $pp_wrkdir/%post.run
+ fi
+ ;;
+ s)
+ echo " ln -s $st $p" >> $pp_wrkdir/%post.run
+ echo " rm -f $p" >> $pp_wrkdir/%preun.run
+ ;;
+ esac
+ done < $pp_wrkdir/%files.run | sort -k3 |uniq > $1
+}
+
+
+pp_backend_kit_make_scp () {
+ scpdir="$pp_wrkdir/scps"
+ mkdir "$scpdir" && touch "$scpdir"/$pp_kit_subset.scp
+ cat <<EOF >"$scpdir"/$pp_kit_subset.scp
+
+ . /usr/share/lib/shell/libscp
+
+ case "\$ACT" in
+ PRE_L)
+ STL_ScpInit
+
+
+
+ ;;
+ POST_L)
+ STL_ScpInit
+ STL_LinkCreate
+EOF
+
+ cat $pp_wrkdir/%post.run >>"$scpdir"/$pp_kit_subset.scp
+ cat >>"$scpdir"/$pp_kit_subset.scp <<EOF
+ ;;
+ PRE_D)
+ STL_ScpInit
+ STL_LinkRemove
+EOF
+ cat $pp_wrkdir/%preun.run >>"$scpdir"/$pp_kit_subset.scp
+ cat >>"$scpdir"/$pp_kit_subset.scp <<EOF
+ ;;
+ POST_D)
+
+ ;;
+ C)
+ STL_ScpInit
+
+ case "\$1" in
+ INSTALL)
+ echo "Installation of the \$_DESC (\$_SUB) subset is complete."
+ ;;
+ DELETE)
+ ;;
+ esac
+
+ ;;
+ V)
+
+ ;;
+ esac
+
+ exit 0
+EOF
+ chmod 744 "$scpdir"/$pp_kit_subset.scp
+}
+
+
+pp_backend_kit_cleanup () {
+ :
+}
+
+pp_backend_kit_names () {
+ if test -z "$pp_kit_name"; then
+ pp_warn "pp_kit_name not specified, using XXX"
+ pp_kit_name=XXX
+ fi
+ case "$pp_kit_name" in
+ ???) : ok;;
+ *) pp_error "\$pp_kit_name $pp_kit_name must be three characters";;
+ esac
+ if test -z "$pp_kit_package"; then
+ pp_warn "pp_kit_package not specified, using YYYY"
+ pp_kit_package=YYYY
+ fi
+ if test -z "$pp_kit_version"; then
+ pp_kit_version=`echo $version|tr -d '.a-zA-Z'`
+ fi
+ case "$pp_kit_version" in
+ [0-9]) pp_kit_version="${pp_kit_version}00";;
+ [0-9][0-9]) pp_kit_version="${pp_kit_version}0";;
+ [0-9][0-9][0-9]) : ok;;
+ *) pp_error "\$pp_kit_version $pp_kit_version must be three digits, ";;
+ esac
+ if test -z "$pp_kit_subset"; then
+ pp_kit_subset="$pp_kit_name$pp_kit_package$pp_kit_version"
+ fi
+ echo "$pp_kit_subset.tar.gz"
+}
+
+pp_backend_kit_install_script () {
+ typeset pkgname platform
+
+ pkgname=`pp_backend_kit_names`
+ platform="`pp_backend_kit_probe`"
+
+ echo "#!/bin/sh"
+ pp_install_script_common
+ cat <<.
+
+ cpt_to_tags () {
+ test x"\$*" = x"all" && set -- $pp_components
+ for cpt
+ do
+ echo "$name.\$cpt"
+ done
+ }
+
+ test \$# -eq 0 && usage
+ op="\$1"; shift
+
+ case "\$op" in
+ list-components)
+ test \$# -eq 0 || usage \$op
+ echo "$pp_components"
+ ;;
+ list-services)
+ test \$# -eq 0 || usage \$op
+ echo "$pp_services"
+ ;;
+ list-files)
+ test \$# -ge 1 || usage \$op
+ echo \${PP_PKGDESTDIR:-.}/$pkgname
+ ;;
+ install)
+ test \$# -ge 1 || usage \$op
+ verbose echo \${PP_PKGDESTDIR:-\`pwd\`}/$pkgname \`cpt_to_tags "\$@"\`
+ #verbose swinstall -x verbose=0 -s \${PP_PKGDESTDIR:-\`pwd\`}/$pkgname \`cpt_to_tags "\$@"\`
+ ;;
+ uninstall)
+ test \$# -ge 1 || usage \$op
+ verbose echo \`cpt_to_tags "\$@"\`
+ #verbose swremove -x verbose=0 \`cpt_to_tags "\$@"\`
+ ;;
+ start|stop)
+ test \$# -ge 1 || usage \$op
+ ec=0
+ for svc
+ do
+ verbose /sbin/init.d/\$svc \$op
+ [ \$? -eq 4 -o \$? -eq 0 ] || ec=1
+ done
+ exit \$ec
+ ;;
+ print-platform)
+ echo "$platform"
+ ;;
+ *)
+ usage
+ ;;
+ esac
+.
+}
+
+pp_backend_kit_function () {
+ case "$1" in
+ pp_mkgroup) cat <<'.';;
+ grep "^$1:" /etc/group >/dev/null ||
+ /usr/sbin/groupadd $1
+.
+ pp_mkuser) cat <<'.';;
+ eval user=\$$#
+ grep "^$user:" /etc/passwd >/dev/null ||
+ /usr/sbin/useradd -s /usr/bin/false "$@"
+.
+ pp_havelib) cat <<'.';;
+ for dir in `echo /usr/lib${3+:$3} | tr : ' '`; do
+ test -r "$dir/lib$1.${2-sl}" && return 0
+ done
+ return 1
+.
+ *) pp_error "unknown function request: $1";;
+ esac
+}
+
+pp_backend_kit_init_svc_vars () {
+ :
+}
+
+pp_backend_kit_probe () {
+ echo tru64-`uname -r | sed 's/V\([0-9]*\)\.\([0-9]*\)/\1\2/'`
+}
+
+pp_kit_service_group_script () {
+ typeset grp svcs scriptpath out
+ grp="$1"
+ svcs="$2"
+ scriptpath="/sbin/init.d/$grp"
+ out="$pp_destdir$scriptpath"
+
+ pp_add_file_if_missing $scriptpath run 755 || return 0
+
+ cat <<-. > $out
+ #!/sbin/sh
+ # generated by pp $pp_version
+ svcs="$svcs"
+.
+
+cat <<-'.' >> $out
+ #-- starts services in order.. stops them all if any break
+ pp_start () {
+ undo=
+ for svc in $svcs; do
+ /sbin/init.d/$svc start
+ case $? in
+ 0|4)
+ undo="$svc $undo"
+ ;;
+ *)
+ if test -n "$undo"; then
+ for svc in $undo; do
+ /sbin/init.d/$svc stop
+ done
+ return 1
+ fi
+ ;;
+ esac
+ done
+ return 0
+ }
+
+ #-- stops services in reverse
+ pp_stop () {
+ reverse=
+ for svc in $svcs; do
+ reverse="$svc $reverse"
+ done
+ rc=0
+ for svc in $reverse; do
+ /sbin/init.d/$svc stop || rc=$?
+ done
+ return $rc
+ }
+
+ case "$1" in
+ start_msg) echo "Starting $svcs";;
+ stop_msg) echo "Stopping $svcs";;
+ start) pp_start;;
+ stop) pp_stop;;
+ *) echo "usage: $0 {start|stop|start_msg|stop_msg}"
+ exit 1;;
+ esac
+.
+}
+
+pp_kit_service_script () {
+ typeset svc scriptpath out
+
+ svc="$1"
+ scriptpath="/sbin/init.d/$svc"
+
+ pp_load_service_vars "$svc"
+
+ test -n "$user" -a x"$user" != x"root" &&
+ cmd="SHELL=/usr/bin/sh /usr/bin/su $user -c \"exec `echo $cmd | sed -e 's,[$\\\`],\\&,g'`\""
+ if test -z "$pidfile"; then
+ pidfile="/var/run/$svc.pid"
+ cmd="$cmd & echo \$! > \$pidfile"
+ fi
+
+ pp_add_file_if_missing $scriptpath run 755
+
+ cat <<-. > $pp_destdir$scriptpath
+ svc="$svc"
+ pidfile="$pidfile"
+
+ pp_start () {
+ $cmd
+ }
+.
+ cat <<-'.' >>$pp_destdir$scriptpath
+ pp_stop () {
+ if test ! -s "$pidfile"; then
+ echo "Unable to stop $svc (no pid file)"
+ return 1
+ else
+ read pid < "$pidfile"
+ if kill -0 "$pid" 2>/dev/null; then
+ if kill -${stop_signal:-TERM} "$pid"; then
+ rm -f "$pidfile"
+ return 0
+ else
+ echo "Unable to stop $svc"
+ return 1
+ fi
+ else
+ rm -f "$pidfile"
+ return 0
+ fi
+ fi
+ }
+
+ pp_running () {
+ if test ! -s "$pidfile"; then
+ return 1
+ else
+ read pid < "$pidfile"
+ kill -0 "$pid" 2>/dev/null
+ fi
+ }
+ case "$1" in
+ start_msg) echo "Starting the $svc service";;
+ stop_msg) echo "Stopping the $svc service";;
+ start)
+ if pp_running; then
+ echo "$svc already running";
+ exit 0
+ elif pp_start; then
+ echo "$svc started";
+ # rc(1M) says we should exit 4, but nobody expects it!
+ exit 0
+ else
+ exit 1
+ fi
+ ;;
+ stop)
+ if pp_stop; then
+ echo "$svc stopped";
+ exit 0
+ else
+ exit 1
+ fi
+ ;;
+ *) echo "usage: $0 {start|stop|start_msg|stop_msg}"
+ exit 1
+ ;;
+ esac
+.
+}
+
+pp_kit_make_service () {
+ typeset level priority startlevels stoplevels
+ typeset svc svcvar
+
+ svc="$1"
+ svcvar=`pp_makevar $svc`
+
+ #-- don't do anything if the script exists
+ if test -s "$pp_destdir/sbin/init.d/$svc"; then
+ pp_error "$pp_destdir/sbin/init.d/$svc exists"
+ return
+ fi
+
+ # symlink the script, depending on the priorities chosen
+ eval priority='${pp_kit_priority_'$svcvar'}'
+ test -z "$priority" && priority="${pp_kit_priority:-50}"
+
+ eval startlevels='${pp_kit_startlevels_'$svcvar'}'
+ test -z "$startlevels" && startlevels="$pp_kit_startlevels"
+
+ eval stoplevels='${pp_kit_stoplevels_'$svcvar'}'
+ test -z "$stoplevels" && stoplevels="$pp_kit_stoplevels"
+
+ # create the script and config file
+ pp_kit_service_script $svc
+
+ # fix the priority up
+ case "$priority" in
+ ???) :;;
+ ??) priority=0$priority;;
+ ?) priority=00$priority;;
+ esac
+
+ if test x"$stoplevels" = x"auto"; then
+ stoplevels=
+ test -z "$startlevels" || for level in $startlevels; do
+ stoplevels="$stoplevels `expr $level - 1`"
+ done
+ fi
+
+ # create the symlinks
+ test -z "$startlevels" || for level in $startlevels; do
+ echo " ln -s /sbin/init.d/$svc /sbin/rc$level.d/S$priority$svc" >>$pp_wrkdir/%post.run
+ echo " rm /sbin/rc$level.d/S$priority$svc" >>$pp_wrkdir/%preun.run
+ done
+ test -z "$stoplevels" || for level in $stoplevels; do
+ echo " ln -s /sbin/init.d/$svc /sbin/rc$level.d/K$priority$svc" >>$pp_wrkdir/%post.run
+ echo " rm -f /sbin/rc$level.d/K$priority$svc" >>$pp_wrkdir/%preun.run
+ done
+}
+
+
+
+
+pp_backend_kit_sizes () {
+ awk '
+ BEGIN { root = usr = var = 0; }
+ {
+ if (substr($9, 1, 1) != "l")
+ if (substr($10, 1, 6) == "./var/")
+ var += $2;
+ else if (substr($10, 1, 10) == "./usr/var/")
+ var += $2
+ else if (substr($10, 1, 6) == "./usr/")
+ usr += $2
+ else
+ root += $2
+ }
+ END { printf "%d\t%d\t%d", root, usr, var }
+ ' "$@"
+}
+
+pp_kit_kits_global () {
+ line=`sed -n '/^%%/q;/^'$2'=/{s/^'$2'=//p;q;}' <"$1"`
+ test -z "$line" && return 1
+ eval "echo $line"
+ :
+}
+
+pp_backend_kit_kits () {
+ typeset KITFILE FROMDIR TODIR
+ typeset SCPDIR
+
+ SCPDIR="$pp_wrkdir/scps"
+
+ PATH="/usr/lbin:/usr/bin:/etc:/usr/ucb:$PATH"; export PATH # XXX
+ #umask 2 # XXX
+
+ test $# -ge 3 || pp_die "pp_backend_kit_kits: too few arguments"
+ KITFILE="$1"; shift
+ FROMDIR="$1"; shift
+ TODIR="$1"; shift
+
+ test -f "$KITFILE" || pp_die "$KITFILE not found"
+ test -d "$FROMDIR" || pp_die "$FROMDIR not found"
+ test -d "$TODIR" || pp_die "$TODIR not found"
+
+ INSTCTRL="$TODIR/instctrl"
+ mkdir -p "$INSTCTRL" || pp_die "cannot create instctrl directory"
+ chmod 775 "$INSTCTRL"
+
+ grep "%%" $KITFILE > /dev/null || pp_die "no %% in $KITFILE"
+
+ typeset NAME CODE VERS MI ROOT COMPRESS
+ typeset S_LIST ALLSUBS
+
+ NAME=`pp_kit_kits_global "$KITFILE" NAME` || pp_die "no NAME in $KITFILE"
+ CODE=`pp_kit_kits_global "$KITFILE" CODE` || pp_die "no CODE in $KITFILE"
+ VERS=`pp_kit_kits_global "$KITFILE" VERS` || pp_die "no VERS in $KITFILE"
+ MI=`pp_kit_kits_global "$KITFILE" MI` || pp_die "no MI in $KITFILE"
+ ROOT=`pp_kit_kits_global "$KITFILE" ROOT`
+ COMPRESS=`pp_kit_kits_global "$KITFILE" COMPRESS`
+
+ test -f "$MI" || pp_die "Inventory file $MI not found"
+
+ case "$ROOT" in
+ *ROOT)
+ test -f "$TODIR/$ROOT" ||
+ pp_die "Root image $ROOT not found in $TODIR" ;;
+ esac
+
+ ALLSUBS=`awk 'insub==1 {print $1} /^%%/ {insub=1}' <"$KITFILE"`
+ test $# -eq 0 && set -- $ALLSUBS
+
+ pp_debug "Creating $# $NAME subsets."
+ pp_debug "ALLSUBS=<$ALLSUBS>"
+
+ if test x"$COMPRESS" = x"1"; then
+ COMPRESS=:
+ else
+ COMPRESS=false
+ fi
+
+ #rm -f *.ctrl Volume*
+
+ for SUB
+ do
+ test -z "$SUB" && pp_die "SUB is empty"
+
+ typeset INV CTRL ROOTSIZE USRSIZE VARSIZE TSSUB
+ #rm -f Volume*
+ case $SUB in
+ .*) :;;
+ *) pp_verbose rm -f "$TODIR/$SUB"* "$INSTCTRL/$SUB"*;;
+ esac
+
+ TSSUB="$pp_wrkdir/ts.$SUB"
+
+ pp_debug "kits: Subset $SUB"
+
+ INV="$SUB.inv"
+ CTRL="$SUB.ctrl"
+ pp_debug "kits: Generating media creation information..."
+
+ # Invcutter takes as input
+ # SUB dir/path
+ # and generates stl_inv(4) files, like this
+ # f 0 00000 0 0 100644 2/11/09 010 f dir/path none SUB
+ grep " $SUB\$" "$MI" |
+ pp_verbose /usr/lbin/invcutter \
+ -v "$VERS" -f "$FROMDIR" > "$INSTCTRL/$INV" ||
+ pp_die "failed to create $INSTCTRL/$INV"
+ chmod 664 "$INSTCTRL/$INV"
+
+ pp_backend_kit_sizes "$INSTCTRL/$INV" > "$pp_wrkdir/kit.sizes"
+ read ROOTSIZE USRSIZE VARSIZE < "$pp_wrkdir/kit.sizes"
+
+ # Prefix each line with $FROMDIR. This will be stripped
+ awk '$1 != "d" {print from $10}' from="$FROMDIR/" \
+ > "$TSSUB" < "$INSTCTRL/$INV" ||
+ pp_die "failed"
+
+ NVOLS=0
+
+ pp_debug "kits: Creating $SUB control file..."
+
+ sed '1,/^%%/d;/^'"$SUB"'/{p;q;}' < "$KITFILE" > "$pp_wrkdir/kit.line"
+ read _SUB _IGNOR DEPS FLAGS DESC < "$pp_wrkdir/kit.line"
+ if test -z "$_SUB"; then
+ pp_warn "No such subset $SUB in $KITFILE"
+ continue
+ fi
+ DEPS=`echo $DEPS | tr '|' ' '`
+ case $FLAGS in
+ FLGEXP*) pp_verbose FLAGS='"${'"$FLAGS"'}"' ;;
+ esac
+ case $DESC in
+ *%*) DESC=`echo $DESC|awk -F% '{printf "%-36s%%%s\n", $1, $2}'`;;
+ esac
+
+ cat > "$INSTCTRL/$CTRL" <<-.
+ NAME='$NAME $SUB'
+ DESC=$DESC
+ ROOTSIZE=$ROOTSIZE
+ USRSIZE=$USRSIZE
+ VARSIZE=$VARSIZE
+ NVOLS=1:$NVOLS
+ MTLOC=1:$TLOC
+ DEPS="$DEPS"
+ FLAGS=$FLAGS
+.
+ chmod 664 "$INSTCTRL/$CTRL"
+
+ pp_debug "kits: Making tar image"
+
+ pp_verbose tar cfPR "$TODIR/$SUB" "$FROMDIR/" "$TSSUB" ||
+ pp_error "problem creating kit file"
+
+ if $COMPRESS; then
+ pp_debug "kits: Compressing"
+ (cd "$TODIR" && compress -f -v "$SUB") ||
+ pp_die "problem compressing $TODIR/$SUB"
+ SPC=`expr $SUB : '\(...\).*'` # first three characters
+ SVC=`expr $SUB : '.*\(...\)'` # last three characters
+ : > "$INSTCTRL/$SPC$SVC.comp"
+ chmod 664 "$INSTCTRL/$SPC$SVC.comp"
+ pp_debug "kits: Padding compressed file to 10kB" # wtf?
+ rm -f "$TODIR/$SUB"
+ pp_verbose \
+ dd if="$TODIR/$SUB.Z" of="$TODIR/$SUB" bs=10k conv=sync ||
+ pp_die "problem moving compressed file"
+ rm -f "$TODIR/$SUB.Z"
+ fi
+ chmod 664 "$TODIR/$SUB"
+
+ if test -f "$SCPDIR/$SUB.scp"; then
+ cp "$SCPDIR/$SUB.scp" "$INSTCTRL/$SUB.scp"
+ chmod 755 "$INSTCTRL/$SUB.scp"
+ else
+ pp_debug "kits: null subset control program for $SUB"
+ : > "$INSTCTRL/$SUB.scp"
+ chmod 744 "$INSTCTRL/$SUB.scp"
+ fi
+
+ pp_debug "kits: Finished creating media image for $SUB"
+ done
+
+ pp_debug "kits: Creating $CODE.image"
+
+ case "$ROOT" in
+ *ROOT) ALLSUBS="$ROOT $ALLSUBS"
+ ;;
+ esac
+
+ (cd "$TODIR" && sum $ALLSUBS) > "$INSTCTRL/$CODE.image"
+ chmod 664 "$INSTTRL/$CODE.image"
+ pp_debug "kits: Creating INSTCTRL"
+ (cd "$INSTCTRL" && tar cpvf - *) > "$TODIR/INSTCTRL"
+ chmod 664 "$TODIR/INSTCTRL"
+ cp "$INSTCTRL/$CODE.image" "$TODIR/$CODE.image"
+ chmod 664 "$TODIR/$CODE.image"
+
+ pp_debug "kits: Media image production complete"
+}
+
+pp_platforms="$pp_platforms rpm"
+
+pp_backend_rpm_detect () {
+ test x"$1" = x"Linux" -a ! -f /etc/debian_version
+}
+
+pp_backend_rpm_init () {
+
+ pp_rpm_version=
+ pp_rpm_summary=
+ pp_rpm_description=
+ pp_rpm_group="Applications/Internet"
+ pp_rpm_license="Unspecified"
+ pp_rpm_vendor=
+ pp_rpm_url=
+ pp_rpm_packager=
+ pp_rpm_provides=
+ pp_rpm_requires=
+ pp_rpm_requires_pre=
+ pp_rpm_requires_post=
+ pp_rpm_requires_preun=
+ pp_rpm_requires_postun=
+ pp_rpm_release=
+ pp_rpm_epoch=
+ pp_rpm_dev_group="Development/Libraries"
+ pp_rpm_dbg_group="Development/Tools"
+ pp_rpm_doc_group="Documentation"
+ pp_rpm_dev_description=
+ pp_rpm_dbg_description=
+ pp_rpm_doc_description=
+ pp_rpm_dev_requires=
+ pp_rpm_dev_requires_pre=
+ pp_rpm_dev_requires_post=
+ pp_rpm_dev_requires_preun=
+ pp_rpm_dev_requires_postun=
+ pp_rpm_dbg_requires=
+ pp_rpm_dbg_requires_pre=
+ pp_rpm_dbg_requires_post=
+ pp_rpm_dbg_requires_preun=
+ pp_rpm_dbg_requires_postun=
+ pp_rpm_doc_requires=
+ pp_rpm_doc_requires_pre=
+ pp_rpm_doc_requires_post=
+ pp_rpm_doc_requires_preun=
+ pp_rpm_doc_requires_postun=
+ pp_rpm_dev_provides=
+ pp_rpm_dbg_provides=
+ pp_rpm_doc_provides=
+
+ pp_rpm_autoprov=
+ pp_rpm_autoreq=
+ pp_rpm_autoreqprov=
+
+ pp_rpm_dbg_pkgname=debug
+ pp_rpm_dev_pkgname=devel
+ pp_rpm_doc_pkgname=doc
+
+ pp_rpm_defattr_uid=root
+ pp_rpm_defattr_gid=root
+
+ pp_rpm_detect_arch
+ pp_rpm_detect_distro
+ pp_rpm_rpmbuild=`pp_rpm_detect_rpmbuild`
+
+ # SLES8 doesn't always come with readlink
+ test -x /usr/bin/readlink -o -x /bin/readlink ||
+ pp_readlink_fn=pp_ls_readlink
+}
+
+pp_rpm_detect_arch () {
+ pp_rpm_arch=auto
+
+ #-- Find the default native architecture that RPM is configured to use
+ cat <<-. >$pp_wrkdir/dummy.spec
+ Name: dummy
+ Version: 1
+ Release: 1
+ Summary: dummy
+ Group: ${pp_rpm_group}
+ License: ${pp_rpm_license}
+ %description
+ dummy
+.
+ $pp_opt_debug && cat $pp_wrkdir/dummy.spec
+ pp_rpm_arch_local=`rpm -q --qf '%{arch}\n' --specfile $pp_wrkdir/dummy.spec`
+ rm $pp_wrkdir/dummy.spec
+
+ #-- Ask the kernel what machine architecture is in use
+ local arch
+ for arch in "`uname -m`" "`uname -p`"; do
+ case "$arch" in
+ i?86)
+ pp_rpm_arch_std=i386
+ break
+ ;;
+ x86_64|ppc|ppc64|ppc64le|ia64|s390|s390x)
+ pp_rpm_arch_std="$arch"
+ break
+ ;;
+ powerpc)
+ # Probably AIX
+ case "`/usr/sbin/lsattr -El proc0 -a type -F value`" in
+ PowerPC_POWER*) pp_rpm_arch_std=ppc64;;
+ *) pp_rpm_arch_std=ppc;;
+ esac
+ break
+ ;;
+ *) pp_rpm_arch_std=unknown
+ ;;
+ esac
+ done
+
+ #-- Later on, when files are processed, we use 'file' to determine
+ # what platform ABIs are used. This is used when pp_rpm_arch == auto
+ pp_rpm_arch_seen=
+}
+
+pp_rpm_detect_distro () {
+ pp_rpm_distro=
+ if test -f /etc/whitebox-release; then
+ pp_rpm_distro=`awk '
+ /^White Box Enterprise Linux release/ { print "wbel" $6; exit; }
+ ' /etc/whitebox-release`
+ elif test -f /etc/mandrakelinux-release; then
+ pp_rpm_distro=`awk '
+ /^Mandrakelinux release/ { print "mand" $3; exit; }
+ ' /etc/mandrake-release`
+ elif test -f /etc/mandrake-release; then
+ pp_rpm_distro=`awk '
+ /^Linux Mandrake release/ { print "mand" $4; exit; }
+ /^Mandrake Linux release/ { print "mand" $4; exit; }
+ ' /etc/mandrake-release`
+ elif test -f /etc/fedora-release; then
+ pp_rpm_distro=`awk '
+ /^Fedora Core release/ { print "fc" $4; exit; }
+ /^Fedora release/ { print "f" $3; exit; }
+ ' /etc/fedora-release`
+ elif test -f /etc/redhat-release; then
+ pp_rpm_distro=`sed -n \
+ -e 's/^Red Hat Linux.*release \([0-9][0-9\.]*\).*/rh\1/p' \
+ -e 's/^Red Hat Enterprise Linux.*release \([0-9][0-9\.]*\).*/rhel\1/p' \
+ -e 's/^Rocky Linux.*release \([0-9][0-9\.]*\).*/rhel\1/p' \
+ -e 's/^AlmaLinux.*release \([0-9][0-9\.]*\).*/rhel\1/p' \
+ -e 's/^CentOS.*release \([0-9][0-9\.]*\).*/centos\1/p' \
+ /etc/redhat-release`
+ elif test -f /etc/SuSE-release; then
+ pp_rpm_distro=`awk '
+ /^SuSE Linux [0-9]/ { print "suse" $3; exit; }
+ /^SUSE LINUX [0-9]/ { print "suse" $3; exit; }
+ /^openSUSE [0-9]/ { print "suse" $2; exit; }
+ /^S[uU]SE Linux Enterprise Server [0-9]/ { print "sles" $5; exit; }
+ /^S[uU]SE LINUX Enterprise Server [0-9]/ { print "sles" $5; exit; }
+ /^SuSE SLES-[0-9]/ { print "sles" substr($2,6); exit; }
+ ' /etc/SuSE-release`
+ elif test -f /etc/os-release; then
+ pp_rpm_distro="`. /etc/os-release && echo \$ID\$VERSION`"
+ elif test -f /etc/pld-release; then
+ pp_rpm_distro=`awk '
+ /^[^ ]* PLD Linux/ { print "pld" $1; exit; }
+ ' /etc/pld-release`
+ elif test X"`uname -s 2>/dev/null`" = X"AIX"; then
+ local r v
+ r=`uname -r`
+ v=`uname -v`
+ pp_rpm_distro="aix$v$r"
+ fi
+ pp_rpm_distro=`echo $pp_rpm_distro | tr -d .`
+ test -z "$pp_rpm_distro" &&
+ pp_warn "unknown distro"
+}
+
+pp_rpm_detect_rpmbuild () {
+ local cmd
+ for cmd in rpmbuild rpm; do
+ if command -v $cmd > /dev/null 2>&1; then
+ echo $cmd
+ return 0
+ fi
+ done
+
+ pp_error "Could not find rpmbuild"
+ # Default to `rpmbuild` in case it magically appears
+ echo rpmbuild
+ return 1
+}
+
+pp_rpm_label () {
+ local label arg
+ label="$1"; shift
+ for arg
+ do
+ test -z "$arg" || echo "$label: $arg"
+ done
+}
+
+pp_rpm_writefiles () {
+ local _l t m o g f p st fo farch
+ while read t m o g f p st; do
+ _l="$p"
+ test $t = d && _l="%dir ${_l%/}/"
+ if test $t = s; then
+ # rpm warns if %attr contains a mode for symlinks
+ m=-
+ elif test x"$m" = x"-"; then
+ case "$t" in
+ d) m=755;;
+ f) m=644;;
+ esac
+ fi
+ test x"$o" = x"-" && o="${pp_rpm_defattr_uid:-root}"
+ test x"$g" = x"-" && g="${pp_rpm_defattr_gid:-root}"
+ _l="%attr($m,$o,$g) $_l"
+
+ if test "$t" = "f" -a x"$pp_rpm_arch" = x"auto"; then
+ fo=`file "${pp_destdir}$p" 2>/dev/null`
+ #NB: The following should match executables and shared objects,
+ #relocatable objects. It will not match .a files however.
+ case "$fo" in
+ *": ELF 32-bit LSB "*", Intel 80386"*)
+ farch=i386;;
+ *": ELF 64-bit LSB "*", AMD x86-64"*|\
+ *": ELF 64-bit LSB "*", x86-64"*)
+ farch=x86_64;;
+ *": ELF 32-bit MSB "*", PowerPC"*)
+ farch=ppc;;
+ *": ELF 64-bit LSB "*", 64-bit PowerPC"*)
+ farch=ppc64le;;
+ *": ELF 64-bit MSB "*", 64-bit PowerPC"*)
+ farch=ppc64;;
+ *": ELF 64-bit LSB "*", IA-64"*)
+ farch=ia64;;
+ *": ELF 32-bit MSB "*", IBM S/390"*)
+ farch=s390;;
+ *": ELF 64-bit MSB "*", IBM S/390"*)
+ farch=s390x;;
+ *"executable (RISC System/6000)"*)
+ farch=ppc;;
+ *"64-bit XCOFF executable"*)
+ farch=ppc64;;
+ *": ELF 64-bit LSB "*", ARM aarch64"*)
+ farch=aarch64;;
+ *" ELF "*)
+ farch=ELF;;
+ *)
+ farch=noarch;;
+ esac
+ # If file(1) doesn't provide enough info, try readelf(1)
+ if test "$farch" = "ELF"; then
+ fo=`readelf -h "${pp_destdir}$p" | awk '{if ($1 == "Class:") {class=$2} else if ($1 == "Machine:") {machine=$0; sub(/^ *Machine: */, "", machine)}} END {print class " " machine}' 2>/dev/null`
+ case "$fo" in
+ "ELF32 Intel 80386")
+ farch=i386;;
+ "ELF64 "*[xX]"86-64")
+ farch=x86_64;;
+ "ELF32 PowerPC")
+ farch=ppc;;
+ "ELF64 PowerPC"*)
+ farch=ppc64;;
+ "ELF64 IA-64")
+ farch=ia64;;
+ "ELF32 IBM S/390")
+ farch=s390;;
+ "ELF64 IBM S/390")
+ farch=s390x;;
+ "ELF64 AArch64")
+ farch=aarch64;;
+ *)
+ farch=noarch;;
+ esac
+ fi
+ pp_debug "file: $fo -> $farch"
+ test x"$farch" = x"noarch" || pp_add_to_list pp_rpm_arch_seen $farch
+ fi
+
+ case $f in
+ *v*) _l="%config(noreplace) $_l";;
+ *m*) _l="%config(missingok) $_l";;
+ esac
+ echo "$_l"
+ done
+ echo
+}
+
+pp_rpm_subname () {
+ case "$1" in
+ run) : ;;
+ dbg) echo "${2}${pp_rpm_dbg_pkgname}";;
+ dev) echo "${2}${pp_rpm_dev_pkgname}";;
+ doc) echo "${2}${pp_rpm_doc_pkgname}";;
+ *) pp_error "unknown component '$1'";
+ esac
+}
+
+pp_rpm_depend () {
+ local _name _vers
+ while read _name _vers; do
+ case "$_name" in ""| "#"*) continue ;; esac
+ echo "Requires: $_name ${_vers:+>= $_vers}"
+ done
+}
+
+pp_rpm_conflict () {
+ local _name _vers
+ while read _name _vers; do
+ case "$_name" in ""| "#"*) continue ;; esac
+ echo "Conflicts: $_name ${_vers:+>= $_vers}"
+ done
+}
+
+pp_rpm_override_requires () {
+ local orig_find_requires
+
+ if test -z "$pp_rpm_depend_filter_cmd"; then
+ return 0
+ fi
+
+ orig_find_requires=`rpm --eval '%{__find_requires}'`
+ cat << EOF > "$pp_wrkdir/filtered-find-requires"
+$orig_find_requires \$@ | $pp_rpm_depend_filter_cmd
+EOF
+ chmod +x "$pp_wrkdir/filtered-find-requires"
+ echo "%define __find_requires $pp_wrkdir/filtered-find-requires"
+ # Might be necessary for old versions of RPM? Not for 4.4.2.
+ #echo "%define _use_internal_dependency_generator 0"
+}
+
+pp_backend_rpm () {
+ local cmp specfile _summary _group _desc _pkg _subname svc _script
+
+ specfile=$pp_wrkdir/$name.spec
+ : > $specfile
+
+ #-- force existence of a 'run' component
+ pp_add_component run
+ : >> $pp_wrkdir/%files.run
+
+ if test -z "$pp_rpm_arch"; then
+ pp_error "Unknown RPM architecture"
+ return 1
+ fi
+
+ #-- Write the header components of the RPM spec file
+ cat <<-. >>$specfile
+ Name: ${pp_rpm_name:-$name}
+ Version: ${pp_rpm_version:-$version}
+ Release: ${pp_rpm_release:-1}
+ Summary: ${pp_rpm_summary:-$summary}
+ Group: ${pp_rpm_group}
+ License: ${pp_rpm_license}
+.
+ pp_rpm_label "URL" "$pp_rpm_url" >>$specfile
+ pp_rpm_label "Vendor" "${pp_rpm_vendor:-$vendor}" >>$specfile
+ pp_rpm_label "Packager" "$pp_rpm_packager" >>$specfile
+ pp_rpm_label "Provides" "$pp_rpm_provides" >>$specfile
+ pp_rpm_label "Requires(pre)" "$pp_rpm_requires_pre" >>$specfile
+ pp_rpm_label "Requires(post)" "$pp_rpm_requires_post" >>$specfile
+ pp_rpm_label "Requires(preun)" "$pp_rpm_requires_preun" >>$specfile
+ pp_rpm_label "Requires(postun)" "$pp_rpm_requires_postun" >>$specfile
+ pp_rpm_label "AutoProv" "$pp_rpm_autoprov" >>$specfile
+ pp_rpm_label "AutoReq" "$pp_rpm_autoreq" >>$specfile
+ pp_rpm_label "AutoReqProv" "$pp_rpm_autoreqprov" >>$specfile
+
+ test -n "$pp_rpm_serial" && pp_warn "pp_rpm_serial deprecated"
+ if test -n "$pp_rpm_epoch"; then
+ #-- Epoch was introduced in RPM 2.5.6
+ case `$pp_rpm_rpmbuild --version 2>/dev/null` in
+ 1.*|2.[0-5].*|2.5.[0-5])
+ pp_rpm_label "Serial" $pp_rpm_epoch >>$specfile;;
+ *)
+ pp_rpm_label "Epoch" $pp_rpm_epoch >>$specfile;;
+ esac
+ fi
+
+ if test -n "$pp_rpm_requires"; then
+ pp_rpm_label "Requires" "$pp_rpm_requires" >>$specfile
+ elif test -s $pp_wrkdir/%depend.run; then
+ pp_rpm_depend < $pp_wrkdir/%depend.run >> $specfile
+ fi
+ if test -s $pp_wrkdir/%conflict.run; then
+ pp_rpm_conflict < $pp_wrkdir/%conflict.run >> $specfile
+ fi
+
+ pp_rpm_override_requires >> $specfile
+
+ cat <<-. >>$specfile
+
+ %description
+ ${pp_rpm_description:-$description}
+.
+
+ for cmp in $pp_components; do
+ case $cmp in
+ run) continue;;
+ dev) _summary="development tools for $pp_rpm_summary"
+ _group="$pp_rpm_dev_group"
+ _desc="${pp_rpm_dev_description:-Development libraries for $name. $pp_rpm_description.}"
+ ;;
+ doc) _summary="documentation for $pp_rpm_summary"
+ _group="$pp_rpm_doc_group"
+ _desc="${pp_rpm_doc_description:-Documentation for $name. $pp_rpm_description.}"
+ ;;
+ dbg) _summary="diagnostic tools for $pp_rpm_summary"
+ _group="$pp_rpm_dbg_group"
+ _desc="${pp_rpm_dbg_description:-Diagnostic tools for $name.}"
+ ;;
+ esac
+
+ _subname=`pp_rpm_subname $cmp`
+ cat <<-.
+
+ %package $_subname
+ Summary: $name $_summary
+ Group: $_group
+.
+ for _script in pre post preun postun; do
+ eval '_pkg="$pp_rpm_'$cmp'_requires_'$_script'"'
+ if test -n "$_pkg"; then
+ eval pp_rpm_label "Requires($_script)" $_pkg
+ fi
+ done
+ eval '_pkg="$pp_rpm_'$cmp'_requires"'
+ if test -n "$_pkg"; then
+ eval pp_rpm_label Requires ${pp_rpm_name:-$name} $_pkg
+ elif test -s $pp_wrkdir/%depend.$cmp; then
+ pp_rpm_depend < $pp_wrkdir/%depend.$cmp >> $specfile
+ fi
+ if test -s $pp_wrkdir/%conflict.$cmp; then
+ pp_rpm_conflict < $pp_wrkdir/%conflict.$cmp >> $specfile
+ fi
+
+ eval '_pkg="$pp_rpm_'$cmp'_provides"'
+ eval pp_rpm_label Provides $_pkg
+
+ cat <<-.
+
+ %description $_subname
+ $_desc
+.
+ done >>$specfile
+
+ #-- NB: we do not put any %prep, %build or %install RPM sections
+ # into the spec file.
+
+ #-- add service start/stop code
+ if test -n "$pp_services"; then
+ pp_rpm_service_install_common >> $pp_wrkdir/%post.run
+
+ #-- record the uninstall commands in reverse order
+ for svc in $pp_services; do
+ pp_load_service_vars $svc
+
+ pp_rpm_service_make_service_files $svc ||
+ pp_error "could not create service files for $svc"
+
+ #-- append %post code to install the svc
+ pp_rpm_service_install $svc >> $pp_wrkdir/%post.run
+
+ #-- prepend %preun code to uninstall svc
+ # (use files in case vars are modified)
+ pp_rpm_service_remove $svc | pp_prepend $pp_wrkdir/%preun.run
+ done
+
+ pp_rpm_service_remove_common | pp_prepend $pp_wrkdir/%preun.run
+ fi
+
+ # make convenience service groups
+ if test -n "$pp_service_groups"; then
+ for grp in $pp_service_groups; do
+ pp_rpm_service_group_make_init_script \
+ $grp "`pp_service_get_svc_group $grp`"
+ done
+ fi
+
+ #-- Write the RPM %file sections
+ # (do this after services, since services adds to %files.run)
+ for cmp in $pp_components; do
+ _subname=`pp_rpm_subname $cmp`
+
+ if test -s $pp_wrkdir/%check.$cmp; then
+ echo ""
+ echo "%pre $_subname"
+ cat $pp_wrkdir/%check.$cmp
+ echo : # causes script to exit true by default
+ fi
+
+ if test -s $pp_wrkdir/%files.$cmp; then
+ echo ""
+ echo "%files $_subname"
+ pp_rpm_writefiles < $pp_wrkdir/%files.$cmp
+ fi
+
+ if test -n "$pp_rpm_ghost"; then
+ for ghost in $pp_rpm_ghost; do
+ echo "%ghost $ghost"
+ done
+ fi
+
+ if test -s $pp_wrkdir/%pre.$cmp; then
+ echo ""
+ echo "%pre $_subname"
+ cat $pp_wrkdir/%pre.$cmp
+ echo : # causes script to exit true
+ fi
+
+ if test -s $pp_wrkdir/%post.$cmp; then
+ echo ""
+ echo "%post $_subname"
+ cat $pp_wrkdir/%post.$cmp
+ echo : # causes script to exit true
+ fi
+
+ if test -s $pp_wrkdir/%preun.$cmp; then
+ echo ""
+ echo "%preun $_subname"
+ cat $pp_wrkdir/%preun.$cmp
+ echo : # causes script to exit true
+ fi
+
+ if test -s $pp_wrkdir/%postun.$cmp; then
+ echo ""
+ echo "%postun $_subname"
+ cat $pp_wrkdir/%postun.$cmp
+ echo : # causes script to exit true
+ fi
+ done >>$specfile
+
+ #-- create a suitable work area for rpmbuild
+ cat <<-. >$pp_wrkdir/.rpmmacros
+ %_topdir $pp_wrkdir
+ # XXX Note escaped %% for use in headerSprintf
+ %_rpmfilename %%{ARCH}/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm
+ .
+ mkdir $pp_wrkdir/RPMS
+ mkdir $pp_wrkdir/BUILD
+
+ if test x"$pp_rpm_arch" = x"auto"; then
+ #-- Reduce the arch_seen list to exactly one item
+ case "$pp_rpm_arch_seen" in
+ "i386 x86_64"|"x86_64 i386")
+ pp_rpm_arch_seen=x86_64;;
+ *"s390 s390x"* | *"s390x s390"* )
+ pp_rpm_arch_seen=s390x;;
+ *"aarch64"* )
+ pp_rpm_arch_seen=aarch64;;
+ *" "*)
+ pp_error "detected multiple targets: $pp_rpm_arch_seen"
+ pp_rpm_arch_seen=unknown;; # not detected
+ "")
+ pp_warn "detected no binaries: using target noarch"
+ pp_rpm_arch_seen=noarch;;
+ *)
+ pp_debug "detected architecture $pp_rpm_arch_seen"
+ esac
+ pp_rpm_arch="$pp_rpm_arch_seen"
+ fi
+
+ . $pp_wrkdir/%fixup
+
+$pp_opt_debug && cat $specfile
+
+ pp_debug "creating: `pp_backend_rpm_names`"
+
+pp_debug "pp_rpm_arch_seen = <${pp_rpm_arch_seen}>"
+pp_debug "pp_rpm_arch = <${pp_rpm_arch}>"
+
+ HOME=$pp_wrkdir \
+ pp_verbose \
+ $pp_rpm_rpmbuild -bb \
+ --buildroot="$pp_destdir/" \
+ --target="${pp_rpm_arch}" \
+ --define='_unpackaged_files_terminate_build 0' \
+ --define='_use_internal_dependency_generator 0' \
+ `$pp_opt_debug && echo --verbose || echo --quiet` \
+ $pp_rpm_rpmbuild_extra_flags \
+ $specfile ||
+ pp_error "Problem creating RPM packages"
+
+ for f in `pp_backend_rpm_names`; do
+ # The package might be in an arch-specific subdir
+ pkgfile=not-found
+ for dir in $pp_wrkdir/RPMS/${pp_rpm_arch} $pp_wrkdir/RPMS; do
+ if test -f $dir/$f; then
+ pkgfile=$dir/$f
+ fi
+ done
+ if test x"$pkgfile" = x"not-found"; then
+ pp_error "Problem predicting RPM filename: $f"
+ else
+ ln $pkgfile $pp_wrkdir/$f
+ fi
+ done
+}
+
+pp_rpm_output_name () {
+ echo "${pp_rpm_name:-$name}`pp_rpm_subname "$1" -`-${pp_rpm_version:-$version}-${pp_rpm_release:-1}.${pp_rpm_arch}.rpm"
+}
+
+pp_backend_rpm_names () {
+ local cmp _subname
+ for cmp in $pp_components; do
+ pp_rpm_output_name $cmp
+ done
+}
+
+pp_backend_rpm_cleanup () {
+ :
+}
+
+pp_rpm_print_requires () {
+ local _subname _name
+
+ echo "CPU:$pp_rpm_arch"
+ ## XXX should be lines of the form (from file/ldd/objdump)
+ # EXEC:/bin/sh
+ # RTLD:libc.so.4:open
+ rpm -q --requires -p $pp_wrkdir/`pp_rpm_output_name $1` |sed -e '/^rpmlib(/d;s/ //g;s/^/RPM:/' | sort -u
+}
+
+pp_backend_rpm_install_script () {
+ local cmp _subname
+
+ echo "#!/bin/sh"
+ pp_install_script_common
+
+ cat <<.
+
+ cmp_to_pkgname () {
+ local oi name
+ if test x"\$1" = x"--only-installed"; then
+ #-- only print if installation detected
+ oi=false
+ shift
+ else
+ oi=true
+ fi
+ test x"\$*" = x"all" &&
+ set -- $pp_components
+ for cmp
+ do
+ case \$cmp in
+.
+ for cmp in $pp_components; do
+ _subname=`pp_rpm_subname $cmp -`
+ echo "$cmp) name=${pp_rpm_name:-$name}${_subname};;"
+ done
+ cat <<.
+ *) usage;;
+ esac
+ if \$oi || rpm -q "\$name" >/dev/null 2>/dev/null; then
+ echo "\$name"
+ fi
+ done
+ }
+
+
+ cmp_to_pathname () {
+ test x"\$*" = x"all" &&
+ set -- $pp_components
+ for cmp
+ do
+ case \$cmp in
+.
+ for cmp in $pp_components; do
+ echo "$cmp) echo \${PP_PKGDESTDIR:-.}/`pp_rpm_output_name $cmp` ;;"
+ done
+ cat <<.
+ *) usage;;
+ esac
+ done
+ }
+
+ print_requires () {
+ test x"\$*" = x"all" &&
+ set -- $pp_components
+ for cmp
+ do
+ case \$cmp in
+.
+ for cmp in $pp_components; do
+ echo "$cmp) cat <<'._end'"
+ pp_rpm_print_requires $cmp
+ echo "._end"; echo ';;'
+ done
+ cat <<.
+ *) usage;;
+ esac
+ done
+ }
+
+ test \$# -eq 0 && usage
+ op="\$1"; shift
+ case "\$op" in
+ list-components)
+ test \$# -eq 0 || usage \$op
+ echo $pp_components
+ ;;
+ list-services)
+ test \$# -eq 0 || usage \$op
+ echo $pp_services
+ ;;
+ list-files)
+ test \$# -ge 1 || usage \$op
+ cmp_to_pathname "\$@"
+ ;;
+ install)
+ test \$# -ge 1 || usage \$op
+ verbose rpm -U --replacepkgs --oldpackage \
+ \`cmp_to_pathname "\$@"\`
+ ;;
+ uninstall)
+ test \$# -ge 1 || usage \$op
+ pkgs=\`cmp_to_pkgname --only-installed "\$@"\`
+ if test -z "\$pkgs"; then
+ verbosemsg "nothing to uninstall"
+ else
+ verbose rpm -e \$pkgs
+ fi
+ ;;
+ start|stop)
+ test \$# -ge 1 || usage \$op
+ ec=0
+ for svc
+ do
+ verbose /etc/init.d/\$svc \$op || ec=1
+ done
+ exit \$ec
+ ;;
+ print-platform)
+ test \$# -eq 0 || usage \$op
+ echo "linux-${pp_rpm_arch}"
+ ;;
+ print-requires)
+ test \$# -ge 1 || usage \$op
+ print_requires "\$@"
+ ;;
+ *)
+ usage
+ ;;
+ esac
+.
+
+}
+
+pp_backend_rpm_probe () {
+ echo "${pp_rpm_distro}-${pp_rpm_arch_std}"
+}
+
+pp_backend_rpm_vas_platforms () {
+ case "$pp_rpm_arch_std" in
+ x86_64) echo "linux-x86_64.rpm linux-x86.rpm";;
+ *86) echo "linux-x86.rpm";;
+ s390) echo "linux-s390";;
+ s390x) echo "linux-s390x";;
+ ppc*) echo "linux-glibc23-ppc64 linux-glibc22-ppc64";;
+ ia64) echo "linux-ia64";;
+ *) pp_die "unknown architecture $pp_rpm_arch_std";;
+ esac
+}
+
+pp_rpm_service_install_common () {
+ cat <<-'.'
+
+ _pp_install_service () {
+ local svc level
+ svc="$1"
+ if [ -x /usr/lib/lsb/install_initd -a ! -r /etc/redhat-release ]
+ then
+ # LSB-style install
+ /usr/lib/lsb/install_initd /etc/init.d/$svc &> /dev/null
+ elif [ -x /sbin/chkconfig ]; then
+ # Red Hat/chkconfig-style install
+ /sbin/chkconfig --add $svc &> /dev/null
+ /sbin/chkconfig $svc off &> /dev/null
+ else
+ : # manual links under /etc/init.d
+ fi
+ }
+
+ _pp_enable_service () {
+ local svc level
+ svc="$1"
+ if [ -x /usr/lib/lsb/install_initd -a ! -r /etc/redhat-release ]
+ then
+ # LSB-style install
+ : # not sure how to enable
+ elif [ -x /sbin/chkconfig ]; then
+ # Red Hat/chkconfig-style install
+ /sbin/chkconfig $svc on &> /dev/null
+ else
+ # manual install
+ set -- `sed -n -e 's/^# Default-Start://p' /etc/init.d/$svc`
+ start_priority=`sed -n -e 's/^# X-Quest-Start-Priority:[[:space:]]*//p' /etc/init.d/$svc`
+ stop_priority=`sed -n -e 's/^# X-Quest-Stop-Priority:[[:space:]]*//p' /etc/init.d/$svc`
+
+ # Provide default start & stop priorities of 20 & 80 in
+ # accordance with Debian update-rc.d defaults
+ if [ -z "$start_priority" ]; then
+ start_priority=20
+ fi
+ if [ -z "$stop_priority" ]; then
+ stop_priority=80
+ fi
+
+ if [ -d "/etc/rc.d" ];then
+ rcdir=/etc/rc.d
+ else
+ rcdir=/etc
+ fi
+
+ for level
+ do ln -sf /etc/init.d/$svc $rcdir/rc$level.d/S$start_priority$svc; done
+ set -- `sed -n -e 's/^# Default-Stop://p' /etc/init.d/$svc`
+ for level
+ do ln -sf /etc/init.d/$svc $rcdir/rc$level.d/K$stop_priority$svc; done
+ fi
+ }
+.
+ pp_systemd_service_install_common
+}
+
+pp_rpm_service_remove_common () {
+ cat <<-'.'
+
+ _pp_remove_service () {
+ local svc
+ svc="$1"
+ /etc/init.d/$svc stop >/dev/null 2>&1
+ if [ -x /usr/lib/lsb/remove_initd -a ! -r /etc/redhat-release ]
+ then
+ /usr/lib/lsb/remove_initd /etc/init.d/$svc &> /dev/null
+ elif [ -x /sbin/chkconfig ]; then
+ /sbin/chkconfig --del $svc &> /dev/null
+ else
+ if [ -d "/etc/rc.d" ];then
+ rcdir=/etc/rc.d
+ else
+ rcdir=/etc
+ fi
+
+ rm -f $rcdir/rc?.d/[SK]??$svc
+ fi
+ }
+.
+ pp_systemd_service_remove_common
+}
+
+pp_rpm_service_install () {
+ echo ""
+ echo "_pp_systemd_init"
+ echo 'if test -n "$systemctl_cmd"; then'
+ echo " _pp_systemd_install $1"
+ test $enable = yes && echo " _pp_systemd_enable $1"
+ echo "else"
+ echo " _pp_install_service $1"
+ test $enable = yes && echo " _pp_enable_service $1"
+ echo "fi"
+}
+
+pp_rpm_service_remove () {
+ cat <<-.
+
+ if [ "\$1" = "remove" -o "\$1" = "0" ]; then
+ # only remove the service if not upgrade
+ _pp_remove_service $1
+ _pp_systemd_disable $1
+ _pp_systemd_remove $1
+ fi
+.
+}
+
+
+pp_backend_rpm_init_svc_vars () {
+
+ reload_signal=
+ start_runlevels=${pp_rpm_default_start_runlevels-"2 3 4 5"} # == lsb default-start
+ stop_runlevels=${pp_rpm_default_stop_runlevels-"0 1 6"} # == lsb default-stop
+ svc_description="${pp_rpm_default_svc_description}" # == lsb short descr
+ svc_process=
+ svc_init_filename="${pp_rpm_svc_init_filename}" # == $svc.init
+ svc_init_filepath="${pp_rpm_svc_init_filepath}" # == /etc/init.d/ by default
+
+ lsb_required_start='$local_fs $network'
+ lsb_should_start=
+ lsb_required_stop=
+ lsb_description=
+
+ start_priority=50
+ stop_priority=50 #-- stop_priority = 100 - start_priority
+}
+
+pp_rpm_service_group_make_init_script () {
+ local grp=$1
+ local svcs="$2"
+ local script=/etc/init.d/$grp
+ local out=$pp_destdir$script
+
+ pp_add_file_if_missing $script run 755 m || return 0
+
+ cat <<-. >>$out
+ #!/bin/sh
+ svcs="$svcs"
+.
+
+ cat <<-'.' >>$out
+
+ #-- prints usage message
+ pp_usage () {
+ echo "usage: $0 {start|stop|status|restart|reload|condrestart|try-restart|force-reload}" >&2
+ return 2
+ }
+
+ #-- starts services in order.. stops them all if any break
+ pp_start () {
+ undo=
+ for svc in $svcs; do
+ if /etc/init.d/$svc start; then
+ undo="$svc $undo"
+ else
+ if test -n "$undo"; then
+ for svc in $undo; do
+ /etc/init.d/$svc stop
+ done
+ return 1
+ fi
+ fi
+ done
+ return 0
+ }
+
+ #-- stops services in reverse
+ pp_stop () {
+ reverse=
+ for svc in $svcs; do
+ reverse="$svc $reverse"
+ done
+ rc=0
+ for svc in $reverse; do
+ /etc/init.d/$svc stop || rc=$?
+ done
+ return $rc
+ }
+
+ #-- returns true only if all services return true status
+ pp_status () {
+ rc=0
+ for svc in $svcs; do
+ /etc/init.d/$svc status || rc=$?
+ done
+ return $rc
+ }
+
+ pp_reload () {
+ rc=0
+ for svc in $svcs; do
+ /etc/init.d/$svc reload || rc=$?
+ done
+ return $rc
+ }
+
+ case "$1" in
+ start) pp_start;;
+ stop) pp_stop;;
+ restart) pp_stop; pp_start;;
+ status) pp_status;;
+ try-restart|condrestart)
+ if pp_status >/dev/null; then
+ pp_restart
+ fi;;
+ reload) pp_reload;;
+ force-reload) if pp_status >/dev/null; then
+ pp_reload
+ else
+ pp_restart
+ fi;;
+ *) pp_usage;;
+ esac
+.
+ chmod 755 $out
+}
+
+pp_rpm_service_make_service_files () {
+ local svc=${svc_init_filename:-$1}
+ local script="${svc_init_filepath:-"/etc/init.d"}/$svc"
+ local out=$pp_destdir$script
+ local _process _cmd _rpmlevels
+
+ pp_add_file_if_missing $script run 755 m || return 0
+
+ #-- start out as an empty shell script
+ cat <<-'.' >$out
+ #!/bin/sh
+.
+
+ #-- determine the process name from $cmd unless $svc_process is given
+ set -- $cmd
+ _process=${svc_process:-"$1"}
+
+ #-- construct a start command that builds a pid file if needed
+ _cmd="$cmd";
+ if test -z "$pidfile"; then
+ pidfile=/var/run/$svc.pid
+ _cmd="$cmd & echo \$! > \$pidfile"
+ fi
+ if test "$user" != "root"; then
+ _cmd="su $user -c exec $_cmd";
+ fi
+
+ #-- generate the Red Hat chkconfig headers
+ _rpmlevels=`echo $start_runlevels | tr -d ' '`
+ cat <<-. >>$out
+ # chkconfig: ${_rpmlevels:--} ${start_priority:-50} ${stop_priority:-50}
+ # description: ${svc_description:-no description}
+ # processname: ${_process}
+ # pidfile: ${pidfile}
+.
+
+ #-- generate the LSB init info
+ cat <<-. >>$out
+ ### BEGIN INIT INFO
+ # Provides: ${svc}
+ # Required-Start: ${lsb_required_start}
+ # Should-Start: ${lsb_should_start}
+ # Required-Stop: ${lsb_required_stop}
+ # Default-Start: ${start_runlevels}
+ # Default-Stop: ${stop_runlevels}
+ # Short-Description: ${svc_description}
+ ### END INIT INFO
+ # Generated by PolyPackage ${pp_version}
+ # ${copyright}
+
+ prog="`echo $cmd | sed -e 's: .*::' -e 's:^.*/::'`"
+
+.
+
+ if test x"${svc_description}" = x"${pp_rpm_default_svc_description}"; then
+ svc_description=
+ fi
+
+ #-- write service-specific definitions
+ cat <<. >>$out
+ #-- definitions specific to service ${svc}
+ svc_name="${svc_description:-$svc service}"
+ user="${user}"
+ pidfile="${pidfile}"
+ stop_signal="${stop_signal}"
+ reload_signal="${reload_signal}"
+ pp_exec_cmd () { $_cmd; }
+.
+
+ #-- write the generic part of the init script
+ cat <<'.' >>$out
+
+ #-- use system message logging, if available
+ if [ -f /lib/lsb/init-functions -a ! -r /etc/redhat-release ]; then
+ . /lib/lsb/init-functions
+ pp_success_msg () { log_success_msg "$@"; }
+ pp_failure_msg () { log_failure_msg "$@"; }
+ pp_warning_msg () { log_warning_msg "$@"; }
+ elif [ -f /etc/init.d/functions ]; then
+ . /etc/init.d/functions
+ pp_success_msg () { echo -n "$*"; success "$@"; echo; }
+ pp_failure_msg () { echo -n "$*"; failure "$@"; echo; }
+ pp_warning_msg () { echo -n "$*"; warning "$@"; echo; }
+ else
+ pp_success_msg () { echo ${1:+"$*:"} OK; }
+ pp_failure_msg () { echo ${1:+"$*:"} FAIL; }
+ pp_warning_msg () { echo ${1:+"$*:"} WARNING; }
+ fi
+
+ #-- prints a status message
+ pp_msg () { echo -n "$*: "; }
+
+ #-- prints usage message
+ pp_usage () {
+ echo "usage: $0 {start|stop|status|restart|reload|condrestart|try-restart|force-reload}" >&2
+ return 2
+ }
+
+ #-- reloads the service, if possible
+ # returns 0=success 1=failure 3=unimplemented
+ pp_reload () {
+ test -n "$reload_signal" || return 3 # unimplemented
+ pp_msg "Reloading ${svc_name}"
+ if pp_signal -${reload_signal}; then
+ pp_success_msg
+ return 0
+ else
+ pp_failure_msg "not running"
+ return 1
+ fi
+ }
+
+ #-- delivers signal $1 to the pidfile
+ # returns 0=success 1=failure
+ pp_signal () {
+ if test -s "$pidfile"; then
+ read pid < "$pidfile" 2>/dev/null
+ kill "$@" "$pid" 2>/dev/null
+ else
+ return 1
+ fi
+ }
+
+ #-- verifies that ${svc_name} is running
+ # returns 0=success 1=failure
+ pp_running () {
+ if test -s "$pidfile"; then
+ read pid < "$pidfile" 2>/dev/null
+ if test ${pid:-0} -gt 1 && kill -0 "$pid" 2>/dev/null; then
+ # make sure name matches
+ pid="`ps -p $pid 2>/dev/null | sed -n \"s/^ *\($pid\) .*$prog *$/\1/p\"`"
+ if test -n "$pid"; then
+ return 0
+ fi
+ fi
+ fi
+ return 1
+ }
+
+ #-- prints information about the service status
+ # returns 0=running 1=crashed 3=stopped
+ pp_status () {
+ pp_msg "Checking for ${svc_name}"
+ if pp_running; then
+ pp_success_msg "running"
+ return 0
+ elif test -s "$pidfile"; then
+ pp_failure_msg "not running (crashed)"
+ return 1
+ else
+ pp_failure_msg "not running"
+ return 3
+ fi
+ }
+
+ #-- starts the service
+ # returns 0=success 1=failure
+ pp_start () {
+ pp_msg "Starting ${svc_name}"
+ if pp_status >/dev/null; then
+ pp_warning_msg "already started"
+ return 0
+ elif pp_exec_cmd; then
+ pp_success_msg
+ return 0
+ else
+ pp_failure_msg "cannot start"
+ return 1
+ fi
+ }
+
+ #-- stops the service
+ # returns 0=success (always)
+ pp_stop () {
+ pp_msg "Stopping ${svc_name}"
+ if pp_signal -${stop_signal}; then
+ pp_success_msg
+ else
+ pp_success_msg "already stopped"
+ fi
+ rm -f "$pidfile"
+ return 0
+ }
+
+ #-- stops and starts the service
+ pp_restart () {
+ pp_stop
+ pp_start
+ }
+
+ case "$1" in
+ start) pp_start;;
+ stop) pp_stop;;
+ restart) pp_restart;;
+ status) pp_status;;
+ try-restart|condrestart)
+ if pp_status >/dev/null; then
+ pp_restart
+ fi;;
+ reload) pp_reload;;
+ force-reload) if pp_status >/dev/null; then
+ pp_reload
+ else
+ pp_restart
+ fi;;
+ *) pp_usage;;
+ esac
+
+.
+ chmod 755 $out
+
+ # Create systemd service file
+ pp_systemd_make_service_file $svc
+}
+pp_backend_rpm_function () {
+ case "$1" in
+ pp_mkgroup) cat<<'.';;
+ /usr/sbin/groupadd -f -r "$1"
+.
+ pp_mkuser:depends) echo pp_mkgroup;;
+ pp_mkuser) cat<<'.';;
+ pp_mkgroup "${2:-$1}" || return 1
+ /usr/sbin/useradd \
+ -g "${2:-$1}" \
+ -M -d "${3:-/nonexistent}" \
+ -s "${4:-/bin/false}" \
+ -r "$1"
+.
+ pp_havelib) cat<<'.';;
+ for pp_tmp_dir in `echo "/usr/lib:/lib${3:+:$3}" | tr : ' '`; do
+ test -r "$pp_tmp_dir/lib$1.so{$2:+.$2}" && return 0
+ done
+ return 1
+.
+ *) false;;
+ esac
+}
+
+: NOTES <<.
+
+ # creating a dmg file for publishing on the web
+ hdiutil create -srcfolder /path/foo foo.dmg
+ hdiutil internet-enable -yes /path/foo.dmg
+ # Layout for packages
+ <name>-<cpy>/component/<file>
+ <name>-<cpt>/extras/postinstall
+ <name>-<cpt>/extras/postupgrade
+ # /Developer/usr/bin/packagemaker (man packagemaker)
+
+ Make a bunch of packages, and then build a 'distribution'
+ which is only understood by macos>10.4
+
+ # Message files in the resource path used are
+ Welcome.{rtf,html,rtfd,txt} - limited text shown in Intro
+ ReadMe.{rtf,html,rtfd,txt} - scrollable/printable, after Intro
+ License.{rtf,html,rtfd,txt} - ditto, user must click 'Accept'
+ background.{jpg,tif,gif,pict,eps,pdf} 620x418 background image
+
+ # These scripts looked for in the resource path
+ InstallationCheck $pkgpath $defaultloc $targetvol
+ 0:ok 32:warn 32+x:warn[1] 64:stop 96+x:stop[2]
+ VolumeCheck $volpath
+ 0:ok 32:failure 32+x:failure[3]
+ preflight $pkgpath $targetloc $targetvol [priv]
+ preinstall $pkgpath $targetloc $targetvol [priv]
+ preupgrade $pkgpath $targetloc $targetvol [priv]
+ postinstall $pkgpath $targetloc $targetvol [priv]
+ postupgrade $pkgpath $targetloc $targetvol [priv]
+ postflight $pkgpath $targetloc $targetvol [priv]
+ 0:ok else fail (for all scripts)
+
+ A detailed reason is deduced by finding an index x (16..31)
+ in the file InstallationCheck.strings or VolumeCheck.strings.
+
+ Scripts marked [priv] are executed with root privileges.
+ None of the [priv] scripts are used by metapackages.
+
+ # Default permissions
+ Permissions of existing directories should match those
+ of a clean install of the OS; typically root:admin 0775
+ New directories or files should be 0775 or 0664 with the
+ appropriate user:group.
+ Exceptions:
+ /etc root:admin 0755
+ /var root:admin 0755
+
+ <http://mirror.informatimago.com/next/developer.apple.com/documentation/DeveloperTools/Conceptual/SoftwareDistribution/Concepts/sd_pkg_flags.html>
+ Info.plist = {
+ CFBundleGetInfoString: "1.2.3, One Identity LLC.",
+ CFBundleIdentifier: "com.quest.rc.openssh",
+ CFBundleShortVersionString: "1.2.3",
+ IFMajorVersion: 1,
+ IFMinorVersion: 2,
+ IFPkgFlagAllowBackRev: false,
+ IFPkgFlagAuthorizationAction: "AdminAuthorization",
+ IFPkgFlagDefaultLocation: "/",
+ IFPkgFlagFollowLinks: true,
+ IFPkgFlagInstallFat: false,
+ IFPkgFlagInstalledSize: <integer>, # this is added by packagemaker
+ IFPkgFlagIsRequired: false,
+ IFPkgFlagOverwritePermissions: false,
+ IFPkgFlagRelocatable: false,
+ IFPkgFlagRestartAction: "NoRestart",
+ IFPkgFlagRootVolumeOnly: false,
+ IFPkgFlagUpdateInstalledLanguages: false,
+ IFPkgFormatVersion= 0.10000000149011612,
+ IFRequirementDicts: [ {
+ Level = "requires",
+ SpecArgument = "/opt/quest/lib/libvas.4.2.0.dylib",
+ SpecType = "file",
+ TestObject = true,
+ TestOperator = "eq", } ]
+ }
+
+ Description.plist = {
+ IFPkgDescriptionDescription = "this is the description text",
+ IFPkgDescriptionTitle = "quest-openssh"
+ }
+
+ # Startup scripts
+ 'launchd' is a kind of combined inetd and rc/init.d system.
+ <https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/DesigningDaemons.html>
+ Create a /Library/LaunchDaemons/$daemonname.plist file
+ Examples found in /System/Library/LaunchDaemons/
+ See manual page launchd.plist(5) for details:
+
+ { Label: "com.quest.rc.foo", # required
+ Program: "/sbin/program",
+ ProgramArguments: [ "/sbin/program", "arg1", "arg2" ], # required
+ RunAtLoad: true,
+ WatchPaths: [ "/etc/crontab" ],
+ QueueDirectories: [ "/var/cron/tabs" ],
+ inetdCompatibility: { Wait: false }, # inetd-only
+ OnDemand: false, # recommended
+ SessionCreate: true,
+ UserName: "nobody",
+ InitGroups: true,
+ Sockets: { # inetd only
+ Listeners: {
+ SockServiceName: "ssh",
+ Bonjour: ["ssh", "sftp-ssh"], } },
+ Disabled: false,
+ StandardErrorPath: "/dev/null",
+ }
+
+
+ How to add a new user
+ dscl . -create /Users/$user
+ dscl . -create /Users/$user UserShell /bin/bash
+ dscl . -create /Users/$user RealName "$user"
+ dscl . -create /Users/$user UniqueID $uid
+ dscl . -create /Users/$user PrimaryGroupID $gid
+ dscl . -create /Users/$user NFSHomeDirectory /Users/$user
+ dscl . -passwd /Users/$user "$passwd"
+ mkdir /Users/$user
+ chown $uid.$gid /Users/$user
+
+.
+
+
+pp_platforms="$pp_platforms macos"
+
+pp_backend_macos_detect () {
+ [ x"$1" = x"Darwin" ]
+}
+
+pp_backend_macos_init () {
+ pp_macos_default_bundle_id_prefix="com.quest.rc."
+ pp_macos_bundle_id=
+ pp_macos_bundle_vendor=
+ pp_macos_bundle_version=
+ pp_macos_bundle_info_string=
+ pp_macos_pkg_type=bundle
+ pp_macos_pkg_background=
+ pp_macos_pkg_background_dark=
+ pp_macos_pkg_license=
+ pp_macos_pkg_readme=
+ pp_macos_pkg_welcome=
+ pp_macos_sudo=sudo
+ pp_macos_installer_plugin=
+ # OS X puts the library version *before* the .dylib extension
+ pp_shlib_suffix='*.dylib'
+}
+
+pp_macos_plist () {
+ typeset in
+ in=""
+ while test $# -gt 0; do
+ case "$1" in
+
+ start-plist) cat <<-.; in=" "; shift ;;
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+ <plist version="1.0">
+.
+ end-plist) echo "</plist>"; in=; shift;;
+
+ '[') echo "$in<array>"; in="$in "; shift;;
+ ']') echo "$in</array>"; in="${in# }"; shift;;
+ '{') echo "<dict>"; in="$in "; shift;;
+ '}') echo "</dict>"; in="${in# }"; shift;;
+ key) shift; echo "$in<key>$1</key>"; shift;;
+ string) shift;
+ echo "$1" | sed -e 's/&/&amp;/g;s/</\&lt;/g;s/>/\&gt;/g;' \
+ -e 's/^/'"$in"'<string>/;s/$/<\/string>/';
+ shift;;
+ true) echo "$in<true/>"; shift;;
+ false) echo "$in<false/>"; shift;;
+ real) shift; echo "$in<real>$1</real>"; shift;;
+ integer) shift; echo "$in<integer>$1</integer>"; shift;;
+ date) shift; echo "$in<date>$1</date>"; shift;; # ISO 8601 format
+ data) shift; echo "$in<data>$1</data>"; shift;; # base64 encoded
+ *) pp_error "pp_macos_plist: bad argument '$1'"; shift;;
+ esac
+ done
+}
+
+pp_macos_rewrite_cpio () {
+ typeset script
+ script=$pp_wrkdir/cpio-rewrite.pl
+ cat <<-'.' >$script
+ #!/usr/bin/perl
+ #
+ # Filter a cpio file, applying the user/group/mode specified in %files
+ #
+ # A CPIO header block has octal fields at the following offset/lengths:
+ # 0 6 magic
+ # 6 6 dev
+ # 12 6 ino
+ # 18 6 mode
+ # 24 6 uid
+ # 30 6 gid
+ # 36 6 nlink
+ # 42 6 rdev
+ # 48 11 mtime
+ # 59 6 namesize (including NUL terminator)
+ # 65 11 filesize
+ # 76 --
+ #
+ use strict;
+ use warnings;
+ no strict 'subs';
+
+ # set %uid, %gid, %mode based on %files
+ my (%uid, %gid, %mode, %users, %groups);
+ my %type_map = ( d => 0040000, f => 0100000, s => 0120000 );
+ while (<DATA>) {
+ my ($type,$mode,$uid,$gid,$flags,$name) =
+ m/^(.) (\S+) (\S+) (\S+) (\S+) (\S+)/;
+ $mode = $type eq "f" ? "0644" : "0755" if $mode eq "-";
+ $uid = 0 if $uid eq "-";
+ $gid = 0 if $gid eq "-";
+ if ($uid ne "=" and $uid =~ m/\D/) {
+ unless (exists $users{$uid}) {
+ my @pw = getpwnam($uid) or die "bad username '$uid'";
+ $users{$uid} = $pw[2];
+ }
+ $uid = $users{$uid};
+ }
+ if ($gid ne "=" and $gid =~ m/\D/) {
+ unless (exists $groups{$gid}) {
+ my @gr = getgrnam($gid) or die "bad group'$gid'";
+ $groups{$gid} = $gr[2];
+ }
+ $gid = $groups{$gid};
+ }
+ $name =~ s:/$:: if $type eq "d";
+ $name = ".".$name."\0";
+ $uid{$name} = sprintf("%06o",int($uid)) unless $uid eq "=";
+ $gid{$name} = sprintf("%06o",int($gid)) unless $gid eq "=";
+ $mode{$name} = sprintf("%06o",oct($mode)|$type_map{$type}) unless $mode eq "=";
+ }
+ undef %users;
+ undef %groups;
+ # parse the cpio file
+ my $hdrlen = 76;
+ while (read(STDIN, my $header, $hdrlen)) {
+ my ($name, $namesize, $filesize);
+ my $filepad = 0;
+ if ($header =~ m/^07070[12]/) {
+ # SVR4 ASCII format, convert to ODC
+ if ($hdrlen == 76) {
+ # Read in rest of header and update header len for SVR4
+ read(STDIN, $header, 110 - 76, 76);
+ $hdrlen = 110;
+ }
+ my $ino = hex(substr($header, 6, 8)) & 0x3ffff;
+ my $mode = hex(substr($header, 14, 8)) & 0x3ffff;
+ my $uid = hex(substr($header, 22, 8)) & 0x3ffff;
+ my $gid = hex(substr($header, 30, 8)) & 0x3ffff;
+ my $nlink = hex(substr($header, 38, 8)) & 0x3ffff;
+ my $mtime = hex(substr($header, 46, 8)) & 0xffffffff;
+ $filesize = hex(substr($header, 54, 8)) & 0xffffffff;
+ my $dev_maj = hex(substr($header, 62, 8));
+ my $dev_min = hex(substr($header, 70, 8));
+ my $dev = &makedev($dev_maj, $dev_min) & 0x3ffff;
+ my $rdev_maj = hex(substr($header, 78, 8));
+ my $rdev_min = hex(substr($header, 86, 8));
+ my $rdev = &makedev($rdev_maj, $rdev_min) & 0x3ffff;
+ $namesize = hex(substr($header, 94, 8)) & 0x3ffff;
+ read(STDIN, $name, $namesize);
+ # Header + name is padded to a multiple of 4 bytes
+ my $namepad = (($hdrlen + $namesize + 3) & 0xfffffffc) - ($hdrlen + $namesize);
+ read(STDIN, my $padding, $namepad) if ($namepad);
+ # File data is padded to be a multiple of 4 bytes
+ $filepad = (($filesize + 3) & 0xfffffffc) - $filesize;
+
+ my $new_header = sprintf("070707%06o%06o%06o%06o%06o%06o%06o%011o%06o%011o", $dev, $ino, $mode, $uid, $gid, $nlink, $rdev, $mtime, $namesize, $filesize);
+ $header = $new_header;
+ } elsif ($header =~ m/^070707/) {
+ # POSIX Portable ASCII Format
+ $namesize = oct(substr($header, 59, 6));
+ $filesize = oct(substr($header, 65, 11));
+ read(STDIN, $name, $namesize);
+ } else {
+ die "bad magic";
+ }
+ # update uid, gid and mode (already in octal)
+ substr($header, 24, 6) = $uid{$name} if exists $uid{$name};
+ substr($header, 30, 6) = $gid{$name} if exists $gid{$name};
+ substr($header, 18, 6) = $mode{$name} if exists $mode{$name};
+ print($header, $name);
+ # check for trailer at EOF
+ last if $filesize == 0 && $name =~ /^TRAILER!!!\0/;
+ # copy-through the file data
+ while ($filesize > 0) {
+ my $seg = 8192;
+ $seg = $filesize if $filesize < $seg;
+ read(STDIN, my $data, $seg);
+ print $data;
+ $filesize -= $seg;
+ }
+ # If file data is padded, skip it
+ read(STDIN, my $padding, $filepad) if ($filepad);
+ }
+ # pass through any padding at the end (blocksize-dependent)
+ for (;;) {
+ my $numread = read(STDIN, my $data, 8192);
+ last unless $numread;
+ print $data;
+ }
+ exit(0);
+
+ sub makedev {
+ (((($_[0] & 0xff)) << 24) | ($_[1] & 0xffffff));
+ }
+ __DATA__
+.
+ # Append to the script the %files data
+ cat "$@" </dev/null >> $script
+ /usr/bin/perl $script || pp_error "pp_macos_rewrite_cpio error";
+}
+
+pp_macos_files_bom () {
+ typeset _l t m o g f p st owner
+ while read t m o g f p st; do
+ # make sure that $m is padded up to 4 digits long
+ case "$m" in
+ ?) m="000$m";;
+ ??) m="00$m";;
+ ???) m="0$m";;
+ ?????*) pp_error "pp_macos_writebom: mode '$m' too long";;
+ esac
+
+ # convert owner,group into owner/group in octal
+ case $o in -) o=0;; esac
+ case $g in -) g=0;; esac
+ owner=`pp_d2o $o`/`pp_d2o $g`
+
+ case $t in
+ f)
+ test x"$m" = x"000-" && m=0644
+ echo ".$p 10$m $owner `
+ /usr/bin/cksum < "${pp_destdir}$p" |
+ awk '{print $2 " " $1}'`"
+ ;;
+ d)
+ test x"$m" = x"000-" && m=0755
+ echo ".${p%/} 4$m $owner"
+ ;;
+ s)
+ test x"$m" = x"000-" && m=0755
+ rl=`/usr/bin/readlink "${pp_destdir}$p"`
+ #test x"$rl" = x"$st" ||
+ # pp_error "symlink mismatch $rl != $st"
+ echo ".$p 12$m $owner `
+ /usr/bin/readlink -n "${pp_destdir}$p" |
+ /usr/bin/cksum |
+ awk '{print $2 " " $1}'` $st"
+ ;;
+ esac
+ done
+}
+
+pp_macos_bom_fix_parents () {
+ perl -pe '
+ sub dirname { my $d=shift; $d=~s,/[^/]*$,,; $d; }
+ sub chk { my $d=shift;
+ &chk(&dirname($d)) if $d =~ m,/,;
+ unless ($seen{$d}++) {
+ # Make sure we do not override system directories
+ if ($d =~ m:^\./(etc|var)$:) {
+ my $tgt = "private/$1";
+ my ($sum, $len) = split(/\s+/, `/usr/bin/printf "$tgt" | /usr/bin/cksum /dev/stdin`);
+ print "$d\t120755\t0/0\t$len\t$sum\t$tgt\n";
+ } elsif ($d eq "." || $d eq "./Library") {
+ print "$d\t41775\t0/80\n";
+ } elsif ($d eq "./Applications" || $d eq "./Developer") {
+ print "$d\t40775\t0/80\n";
+ } else {
+ print "$d\t40755\t0/0\n";
+ }
+ }
+ }
+ m/^(\S+)\s+(\d+)/;
+ if (oct($2) & 040000) {
+ $seen{$1}++; # directory
+ }
+ &chk(&dirname($1));'
+}
+
+pp_macos_files_size () {
+ typeset _l t m o g f p st owner
+ while read t m o g f p st; do
+ case $t in
+ f) wc -c < "${pp_destdir}$p";;
+ s) echo 4095;;
+ d) ;; # always seems to be zero
+ esac
+ done | awk '{n+=1+int($1/4096)} END {print n*4}'
+}
+
+pp_o2d () {
+ awk 'BEGIN { x=0; '`echo "$1" |
+ sed -e 's/./x=x*8+&;/g'`'print x;}' </dev/null
+}
+pp_d2o () {
+ case "$1" in
+ [0-7]) echo $1;;
+ *) awk 'BEGIN { printf("%o\n", 0+('"$1"'));}' < /dev/null;;
+ esac
+}
+
+pp_macos_mkbom () {
+ #/usr/bin/mkbom -i $1 $2
+ typeset path mode ugid size cksum linkpath
+ typeset bomstage
+
+ # Use mkbom if it understands -i (avoids a copy)
+ if /usr/bin/mkbom -i /dev/null "$2" 2>/dev/null; then
+ rm -f "$2"
+ /usr/bin/mkbom -i "$1" "$2"
+ return
+ fi
+
+ # On 10.4 we have this nonsense.
+ pp_warn "mkbom workaround: copying source files to staging area"
+
+ bomstage=$pp_wrkdir/bom_stage
+ $pp_macos_sudo /bin/mkdir "$bomstage"
+ while IFS=' ' read path mode ugid size cksumi linkpath; do
+ if test -h "$pp_destdir/$path"; then
+ $pp_macos_sudo /bin/ln -s "$linkpath" "$bomstage/$path"
+ else
+ if test -d "$pp_destdir/$path"; then
+ $pp_macos_sudo /bin/mkdir -p "$bomstage/$path"
+ else
+ $pp_macos_sudo /bin/cp "$pp_destdir/$path" "$bomstage/$path"
+ fi
+ $pp_macos_sudo /bin/chmod $mode "$bomstage/$path"
+ $pp_macos_sudo /usr/sbin/chown `echo $ugid| tr / :` "$bomstage/$path"
+ fi
+ done <"$1"
+ (cd $bomstage && $pp_macos_sudo mkbom . $pp_wrkdir/bom_stage.bom) ||
+ pp_error "mkbom failed"
+ $pp_macos_sudo mv $pp_wrkdir/bom_stage.bom "$2"
+}
+
+pp_backend_macos () {
+ : ${pp_macos_bundle_id:=$pp_macos_default_bundle_id_prefix$name}
+ case "$pp_macos_pkg_type" in
+ bundle) pp_backend_macos_bundle;;
+ flat) pp_backend_macos_flat;;
+ *) pp_error "unsupported package type $pp_macos_pkg_type";;
+ esac
+}
+
+pp_backend_macos_bundle () {
+ typeset pkgdir Contents Resources lprojdir svc
+ typeset Info_plist Description_plist
+ typeset bundle_vendor bundle_version size cmp filelists
+
+ mac_version=`sw_vers -productVersion`
+ bundle_vendor=${pp_macos_bundle_vendor:-$vendor}
+
+ if test -z "$pp_macos_bundle_version"; then
+ bundle_version=`echo "$version.0.0.0" | sed -n -e 's/[^0-9.]//g' \
+ -e 's/^\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/p'`
+ else
+ bundle_version="$pp_macos_bundle_version"
+ fi
+ source_version=`echo $version | sed 's/.*\.//'`
+
+ # build the package layout
+ pkgdir=$pp_wrkdir/$name.pkg
+ Contents=$pkgdir/Contents
+ Resources=$Contents/Resources
+ lprojdir=$Resources/en.lproj
+ mkdir $pkgdir $Contents $Resources $lprojdir ||
+ pp_error "Can't make package temporary directories"
+
+ echo "major: 1" > $Resources/package_version
+ echo "minor: 0" >> $Resources/package_version
+ echo "pmkrpkg1" > $Contents/PkgInfo
+ case $mac_version in
+ "10.6"*)
+ xattr -w "com.apple.TextEncoding" "macintosh;0" "$Resources/package_version"
+ xattr -w "com.apple.TextEncoding" "macintosh;0" "$Contents/PkgInfo"
+ ;;
+ esac
+
+ # Copy welcome file/dir for display at package install time.
+ if test -n "$pp_macos_pkg_welcome"; then
+ typeset sfx
+ sfx=`echo "$pp_macos_pkg_welcome"|sed 's/^.*\.\([^\.]*\)$/\1/'`
+ case "$sfx" in
+ rtf|html|rtfd|txt) ;;
+ *) sfx=txt;;
+ esac
+ cp -R ${pp_macos_pkg_welcome} $Resources/Welcome.$sfx
+ fi
+
+ # Copy readme file/dir for display at package install time.
+ if test -n "$pp_macos_pkg_readme"; then
+ typeset sfx
+ sfx=`echo "$pp_macos_pkg_readme"|sed 's/^.*\.\([^\.]*\)$/\1/'`
+ case "$sfx" in
+ rtf|html|rtfd|txt) ;;
+ *) sfx=txt;;
+ esac
+ cp -R ${pp_macos_pkg_readme} $Resources/ReadMe.$sfx
+ fi
+
+ # Copy license file/dir for display at package install time.
+ if test -n "$pp_macos_pkg_license"; then
+ typeset sfx
+ sfx=`echo "$pp_macos_pkg_license"|sed 's/^.*\.\([^\.]*\)$/\1/'`
+ case "$sfx" in
+ rtf|html|rtfd|txt) ;;
+ *) sfx=txt;;
+ esac
+ cp -R ${pp_macos_pkg_license} $Resources/License.$sfx
+ fi
+
+ # Add services (may modify %files)
+ for svc in $pp_services .; do
+ test . = "$svc" && continue
+ pp_macos_add_service $svc
+ done
+
+ # Find file lists (%files.* includes ignore files)
+ for cmp in $pp_components; do
+ test -f $pp_wrkdir/%files.$cmp && filelists="$filelists${filelists:+ }$pp_wrkdir/%files.$cmp"
+ done
+
+ # compute the installed size
+ size=`cat $filelists | pp_macos_files_size`
+
+ #-- Create Info.plist
+ Info_plist=$Contents/Info.plist
+ pp_macos_plist \
+ start-plist \{ \
+ key CFBundleGetInfoString string \
+ "${pp_macos_bundle_info_string:-$version $bundle_vendor}" \
+ key CFBundleIdentifier string \
+ "${pp_macos_bundle_id}" \
+ key CFBundleName string "$name" \
+ key CFBundleShortVersionString string "$bundle_version.$source_version" \
+ key IFMajorVersion integer 1 \
+ key IFMinorVersion integer 0 \
+ key IFPkgFlagAllowBackRev false \
+ key IFPkgFlagAuthorizationAction string "RootAuthorization" \
+ key IFPkgFlagDefaultLocation string "/" \
+ key IFPkgFlagFollowLinks true \
+ key IFPkgFlagInstallFat true \
+ key IFPkgFlagInstalledSize integer $size \
+ key IFPkgFlagIsRequired false \
+ key IFPkgFlagOverwritePermissions true \
+ key IFPkgFlagRelocatable false \
+ key IFPkgFlagRestartAction string "NoRestart" \
+ key IFPkgFlagRootVolumeOnly true \
+ key IFPkgFlagUpdateInstalledLanguages false \
+ key IFPkgFlagUseUserMask false \
+ key IFPkgFormatVersion real 0.10000000149011612 \
+ key SourceVersion string $source_version \
+ \} end-plist> $Info_plist
+
+ # write en.lproj/Description.plist
+ Description_plist=$lprojdir/Description.plist
+ pp_macos_plist \
+ start-plist \{ \
+ key IFPkgDescriptionDeleteWarning string "" \
+ key IFPkgDescriptionDescription string "$pp_macos_bundle_info_string" \
+ key IFPkgDescriptionTitle string "$name" \
+ key IFPkgDescriptionVersion string "$bundle_version.$source_version" \
+ \} end-plist > $Description_plist
+
+ # write Resources/files
+ awk '{print $6}' $filelists > $Resources/files
+
+ # write package size file
+ printf \
+"NumFiles 0
+InstalledSize $size
+CompressedSize 0
+" > $Resources/$name.sizes
+
+ # write Resources/preinstall
+ for cmp in $pp_components; do
+ if test -s $pp_wrkdir/%pre.$cmp; then
+ if test ! -s $Resources/preinstall; then
+ echo "#!/bin/sh" > $Resources/preinstall
+ chmod +x $Resources/preinstall
+ fi
+ cat $pp_wrkdir/%pre.$cmp >> $Resources/preinstall
+ echo : >> $Resources/preinstall
+ fi
+ done
+
+ # write Resources/postinstall
+ for cmp in $pp_components; do
+ if test -s $pp_wrkdir/%post.$cmp; then
+ if test ! -s $Resources/postinstall; then
+ echo "#!/bin/sh" > $Resources/postinstall
+ chmod +x $Resources/postinstall
+ fi
+ cat $pp_wrkdir/%post.$cmp >> $Resources/postinstall
+ echo : >> $Resources/postinstall
+ fi
+ done
+
+ # write Resources/postupgrade
+ for cmp in $pp_components; do
+ if test -s $pp_wrkdir/%postup.$cmp; then
+ if test ! -s $Resources/postupgrade; then
+ echo "#!/bin/sh" > $Resources/postupgrade
+ chmod +x $Resources/postupgrade
+ fi
+ cat $pp_wrkdir/%postup.$cmp >> $Resources/postupgrade
+ echo : >> $Resources/postupgrade
+ fi
+ done
+
+ # write Resources/preremove
+ for cmp in $pp_components; do
+ if test -s $pp_wrkdir/%preun.$cmp; then
+ if test ! -s $Resources/preremove; then
+ echo "#!/bin/sh" > $Resources/preremove
+ chmod +x $Resources/preremove
+ fi
+ cat $pp_wrkdir/%preun.$cmp >> $Resources/preremove
+ echo : >> $Resources/preremove
+ fi
+ done
+
+ # write Resources/postremove
+ for cmp in $pp_components; do
+ if test -s $pp_wrkdir/%postun.$cmp; then
+ if test ! -s $Resources/postremove; then
+ echo "#!/bin/sh" > $Resources/postremove
+ chmod +x $Resources/postremove
+ fi
+ cat $pp_wrkdir/%postun.$cmp >> $Resources/postremove
+ echo : >> $Resources/postremove
+ fi
+ done
+
+ # write uninstall info
+ echo "version=$version" > $Resources/uninstall
+ if [ -n "$pp_macos_requires" ];then
+ echo "requires=$pp_macos_requires" >> $Resources/uninstall
+ fi
+
+ . $pp_wrkdir/%fixup
+
+ # Create the bill-of-materials (Archive.bom)
+ cat $filelists | pp_macos_files_bom | sort |
+ pp_macos_bom_fix_parents > $pp_wrkdir/tmp.bomls
+
+ pp_macos_mkbom $pp_wrkdir/tmp.bomls $Contents/Archive.bom
+
+ # Create the cpio archive (Archive.pax.gz)
+ (
+ cd $pp_destdir &&
+ awk '{ print "." $6 }' $filelists | sed 's:/$::' | sort | /usr/bin/cpio -o | pp_macos_rewrite_cpio $filelists | gzip -9f -c > $Contents/Archive.pax.gz
+ )
+
+ # Copy installer plugins if any
+ if test -n "$pp_macos_installer_plugin"; then
+ if test ! -f "$pp_macos_installer_plugin/InstallerSections.plist"; then
+ pp_error "Missing InstallerSections.plist file in $pp_macos_installer_plugin"
+ fi
+ mkdir -p $pkgdir/Plugins
+ cp -R "$pp_macos_installer_plugin"/* $pkgdir/Plugins
+ fi
+
+ test -d $pp_wrkdir/bom_stage && $pp_macos_sudo rm -rf $pp_wrkdir/bom_stage
+
+ rm -f ${name}-${version}.dmg
+ hdiutil create -fs HFS+ -srcfolder $pkgdir -volname $name ${name}-${version}.dmg
+}
+
+pp_backend_macos_flat () {
+ typeset pkgdir bundledir Resources lprojdir svc
+ typeset Info_plist Description_plist
+ typeset bundle_vendor bundle_version size numfiles cmp filelists
+
+ mac_version=`sw_vers -productVersion`
+ bundle_vendor=${pp_macos_bundle_vendor:-$vendor}
+
+ if test -z "$pp_macos_bundle_version"; then
+ bundle_version=`echo "$version.0.0.0" | sed -n -e 's/[^0-9.]//g' \
+ -e 's/^\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/p'`
+ else
+ bundle_version="$pp_macos_bundle_version"
+ fi
+ source_version=`echo $version | sed 's/.*\.//'`
+
+ # build the flat package layout
+ pkgdir=$pp_wrkdir/pkg
+ pkgfile=$name-$version.pkg
+ bundledir=$pp_wrkdir/pkg/$pkgfile
+ Resources=$pkgdir/Resources
+ lprojdir=$Resources/en.lproj
+ mkdir $pkgdir $bundledir $Resources $lprojdir ||
+ pp_error "Can't make package temporary directories"
+
+ # Add services (may modify %files)
+ for svc in $pp_services .; do
+ test . = "$svc" && continue
+ pp_macos_add_service $svc
+ done
+
+ # Find file lists (%files.* includes ignore files)
+ for cmp in $pp_components; do
+ test -f $pp_wrkdir/%files.$cmp && filelists="$filelists${filelists:+ }$pp_wrkdir/%files.$cmp"
+ done
+
+ # compute the installed size and number of files/dirs
+ size=`cat $filelists | pp_macos_files_size`
+ numfiles=`cat $filelists | wc -l`
+ numfiles="${numfiles##* }"
+
+ # Write Distribution file
+ cat <<-. >$pkgdir/Distribution
+ <?xml version="1.0" encoding="UTF-8"?>
+ <installer-gui-script minSpecVersion="1">
+ <title>$name $version</title>
+ <options customize="never" allow-external-scripts="no"/>
+ <domains enable_localSystem="true"/>
+.
+ if test -n "$pp_macos_pkg_welcome"; then
+ cp -R "${pp_macos_pkg_welcome}" $Resources
+ echo " <welcome file=\"${pp_macos_pkg_welcome##*/}\"/>" >>$pkgdir/Distribution
+ fi
+ if test -n "$pp_macos_pkg_readme"; then
+ cp -R "${pp_macos_pkg_readme}" $Resources
+ echo " <readme file=\"${pp_macos_pkg_readme##*/}\"/>" >>$pkgdir/Distribution
+ fi
+ if test -n "$pp_macos_pkg_license"; then
+ cp -R "${pp_macos_pkg_license}" $Resources
+ echo " <license file=\"${pp_macos_pkg_license##*/}\"/>" >>$pkgdir/Distribution
+ fi
+ if test -n "$pp_macos_pkg_background"; then
+ cp -R "${pp_macos_pkg_background}" $Resources
+ echo " <background file=\"${pp_macos_pkg_background##*/}\" scaling=\"proportional\" alignment=\"left\"/>" >>$pkgdir/Distribution
+ fi
+ if test -n "$pp_macos_pkg_background_dark"; then
+ cp -R "${pp_macos_pkg_background_dark}" $Resources
+ echo " <background-darkAqua file=\"${pp_macos_pkg_background_dark##*/}\" scaling=\"proportional\" alignment=\"left\"/>" >>$pkgdir/Distribution
+ fi
+ cat <<-. >>$pkgdir/Distribution
+ <choices-outline>
+ <line choice="choice0"/>
+ </choices-outline>
+ <choice id="choice0" title="$name $version">
+ <pkg-ref id="${pp_macos_bundle_id}"/>
+ </choice>
+ <pkg-ref id="${pp_macos_bundle_id}" installKBytes="$size" version="$version" auth="Root">#$pkgfile</pkg-ref>
+ </installer-gui-script>
+.
+
+ # write scripts archive
+ # XXX - missing preupgrade, preflight, postflight
+ mkdir $pp_wrkdir/scripts
+ for cmp in $pp_components; do
+ if test -s $pp_wrkdir/%pre.$cmp; then
+ if test ! -s $pp_wrkdir/scripts/preinstall; then
+ echo "#!/bin/sh" > $pp_wrkdir/scripts/preinstall
+ chmod +x $pp_wrkdir/scripts/preinstall
+ fi
+ cat $pp_wrkdir/%pre.$cmp >> $pp_wrkdir/scripts/preinstall
+ echo : >> $pp_wrkdir/scripts/preinstall
+ fi
+ if test -s $pp_wrkdir/%post.$cmp; then
+ if test ! -s $pp_wrkdir/scripts/postinstall; then
+ echo "#!/bin/sh" > $pp_wrkdir/scripts/postinstall
+ chmod +x $pp_wrkdir/scripts/postinstall
+ fi
+ cat $pp_wrkdir/%post.$cmp >> $pp_wrkdir/scripts/postinstall
+ echo : >> $pp_wrkdir/scripts/postinstall
+ fi
+ if test -s $pp_wrkdir/%postup.$cmp; then
+ if test ! -s $pp_wrkdir/scripts/postupgrade; then
+ echo "#!/bin/sh" > $pp_wrkdir/scripts/postupgrade
+ chmod +x $pp_wrkdir/scripts/postupgrade
+ fi
+ cat $pp_wrkdir/%postup.$cmp >> $pp_wrkdir/scripts/postupgrade
+ echo : >> $pp_wrkdir/scripts/postupgrade
+ fi
+ # XXX - not supported
+ if test -s $pp_wrkdir/%preun.$cmp; then
+ if test ! -s $pp_wrkdir/scripts/preremove; then
+ echo "#!/bin/sh" > $pp_wrkdir/scripts/preremove
+ chmod +x $pp_wrkdir/scripts/preremove
+ fi
+ cat $pp_wrkdir/%preun.$cmp >> $pp_wrkdir/scripts/preremove
+ echo : >> $pp_wrkdir/scripts/preremove
+ fi
+ # XXX - not supported
+ if test -s $pp_wrkdir/%postun.$cmp; then
+ if test ! -s $pp_wrkdir/scripts/postremove; then
+ echo "#!/bin/sh" > $pp_wrkdir/scripts/postremove
+ chmod +x $pp_wrkdir/scripts/postremove
+ fi
+ cat $pp_wrkdir/%postun.$cmp >> $pp_wrkdir/scripts/postremove
+ echo : >> $pp_wrkdir/scripts/postremove
+ fi
+ done
+ if test "`echo $pp_wrkdir/scripts/*`" != "$pp_wrkdir/scripts/*"; then
+ # write scripts archive, scripts are mode 0755 uid/gid 0/0
+ # resetting the owner and mode is not strictly required
+ (
+ cd $pp_wrkdir/scripts || pp_error "Can't cd to $pp_wrkdir/scripts"
+ rm -f $pp_wrkdir/tmp.files.scripts
+ for s in *; do
+ echo "f 0755 0 0 - ./$s" >>$pp_wrkdir/tmp.files.scripts
+ done
+ find . -type f | /usr/bin/cpio -o | pp_macos_rewrite_cpio $pp_wrkdir/tmp.files.scripts | gzip -9f -c > $bundledir/Scripts
+ )
+ fi
+
+ # Write PackageInfo file
+ cat <<-. >$bundledir/PackageInfo
+ <?xml version="1.0" encoding="UTF-8"?>
+ <pkg-info format-version="2" identifier="${pp_macos_bundle_id}" version="$version" install-location="/" relocatable="false" overwrite-permissions="true" followSymLinks="true" auth="root">
+ <payload installKBytes="$size" numberOfFiles="$numfiles"/>
+.
+ if test -s $bundledir/Scripts; then
+ echo " <scripts>" >>$bundledir/PackageInfo
+ for s in preflight postflight preinstall postinstall preupgrade postupgrade; do
+ if test -s "$pp_wrkdir/scripts/$s"; then
+ echo " <$s file=\"$s\"/>" >>$bundledir/PackageInfo
+ fi
+ done
+ echo " </scripts>" >>$bundledir/PackageInfo
+ fi
+ cat <<-. >>$bundledir/PackageInfo
+ </pkg-info>
+.
+
+ . $pp_wrkdir/%fixup
+
+ # Create the bill-of-materials (Bom)
+ cat $filelists | pp_macos_files_bom | sort |
+ pp_macos_bom_fix_parents > $pp_wrkdir/tmp.bomls
+ pp_macos_mkbom $pp_wrkdir/tmp.bomls $bundledir/Bom
+
+ # Create the cpio payload
+ (
+ cd $pp_destdir || pp_error "Can't cd to $pp_destdir"
+ awk '{ print "." $6 }' $filelists | sed 's:/$::' | sort | /usr/bin/cpio -o | pp_macos_rewrite_cpio $filelists | gzip -9f -c > $bundledir/Payload
+ )
+ awk '{print $6}' $filelists > $name.files
+
+ # Copy installer plugins if any
+ if test -n "$pp_macos_installer_plugin"; then
+ if test ! -f "$pp_macos_installer_plugin/InstallerSections.plist"; then
+ pp_error "Missing InstallerSections.plist file in $pp_macos_installer_plugin"
+ fi
+ mkdir -p $pkgdir/Plugins
+ cp -R "$pp_macos_installer_plugin"/* $pkgdir/Plugins
+ fi
+
+ test -d $pp_wrkdir/bom_stage && $pp_macos_sudo rm -rf $pp_wrkdir/bom_stage
+
+ # Create the flat package with xar (like pkgutil --flatten does)
+ # Note that --distribution is only supported by macOS 10.6 and above
+ xar_flags="--compression=bzip2 --no-compress Scripts --no-compress Payload"
+ case $mac_version in
+ "10.5"*) ;;
+ *) xar_flags="$xar_flags --distribution";;
+ esac
+ (cd $pkgdir && /usr/bin/xar $xar_flags -cf "../$pkgfile" *)
+
+ echo "version=$version" > $name.uninstall
+}
+
+pp_backend_macos_cleanup () {
+ :
+}
+
+pp_backend_macos_names () {
+ case "$pp_macos_pkg_type" in
+ bundle) echo ${name}.pkg;;
+ flat) echo ${name}-${version}.pkg;;
+ *) pp_error "unsupported package type $pp_macos_pkg_type";;
+ esac
+}
+
+pp_backend_macos_install_script () {
+ echo '#!/bin/sh'
+ typeset pkgname platform
+
+ pkgname="`pp_backend_macos_names`"
+ platform="`pp_backend_macos_probe`"
+ pp_install_script_common
+
+ cat <<.
+ test \$# -eq 0 && usage
+ op="\$1"; shift
+
+ case "\$op" in
+ list-components)
+ test \$# -eq 0 || usage \$op
+ echo "$pp_components"
+ ;;
+ list-services)
+ test \$# -eq 0 || usage \$op
+ echo "$pp_services"
+ ;;
+ list-files)
+ test \$# -ge 1 || usage \$op
+ echo \${PP_PKGDESTDIR:-.}/"$pkgname"
+ ;;
+ install)
+ test \$# -ge 1 || usage \$op
+ vol=/Volumes/pp\$\$
+ pkg=\$vol/${name}-${version}.pkg
+ hdiutil attach -readonly -mountpoint \$vol \
+ \${PP_PKGDESTDIR:-.}/"$pkgname"
+ trap "hdiutil detach \$vol" 0
+ installer -pkginfo -pkg \$pkg
+ installer -verbose -pkg \$pkg -target /
+ ;;
+ uninstall)
+ test \$# -ge 1 || usage \$op
+ # XXX
+ echo "Uninstall not implemented" >&2
+ exit 1;;
+ start|stop)
+ test \$# -ge 1 || usage \$op
+ ec=0
+ for svc
+ do
+ # XXX
+ echo "\${op} not implemented" >&2
+ ec=1
+ done
+ exit \$ec
+ ;;
+ print-platform)
+ echo "$platform"
+ ;;
+ *)
+ usage;;
+ esac
+.
+}
+
+pp_backend_macos_init_svc_vars () {
+ pp_macos_start_services_after_install=true
+ pp_macos_service_name=
+ pp_macos_default_service_id_prefix="com.quest.rc."
+ pp_macos_service_id=
+ pp_macos_service_user=
+ pp_macos_service_group=
+ pp_macos_service_initgroups=
+ pp_macos_service_umask=
+ pp_macos_service_cwd=
+ pp_macos_service_nice=
+ pp_macos_svc_plist_file=
+}
+
+pp_macos_launchd_plist () {
+ typeset svc svc_id
+
+ svc="$1"
+ svc_id="$2"
+
+ set -- $cmd
+
+ if [ -n "$pp_macos_svc_plist_file" ]; then
+ echo "## Launchd plist file already defined at $pp_macos_svc_plist_file"
+ return
+ fi
+
+ echo "## Generating the launchd plist file for $svc"
+ pp_macos_svc_plist_file="$pp_wrkdir/$svc.plist"
+ cat <<-. > $pp_macos_svc_plist_file
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN
+ http://www.apple.com/DTDs/PropertyList-1.0.dtd >
+ <plist version="1.0">
+ <dict>
+ <key>Label</key>
+ <string>$svc_id</string>
+ <key>ProgramArguments</key>
+ <array>
+.
+ while test $# != 0; do
+ printf " <string>$1</string>\n" >> $pp_macos_svc_plist_file
+ shift
+ done
+ cat <<-. >> $pp_macos_svc_plist_file
+ </array>
+ <key>KeepAlive</key>
+ <true/>
+.
+ if test -n "$pp_macos_service_user"; then
+ printf " <key>UserName</key>\n" >> $pp_macos_svc_plist_file
+ printf " <string>$pp_macos_service_user</string>\n" >> $pp_macos_svc_plist_file
+ fi
+ if test -n "$pp_macos_service_group"; then
+ printf " <key>GroupName</key>\n" >> $pp_macos_svc_plist_file
+ printf " <string>$pp_macos_service_group</string>\n" >> $pp_macos_svc_plist_file
+ fi
+ if test -n "$pp_macos_service_initgroups"; then
+ printf " <key>InitGroups</key>\n" >> $pp_macos_svc_plist_file
+ printf " <string>$pp_macos_service_initgroups</string>\n" >> $pp_macos_svc_plist_file
+ fi
+ if test -n "$pp_macos_service_umask"; then
+ printf " <key>Umask</key>\n" >> $pp_macos_svc_plist_file
+ printf " <string>$pp_macos_service_umask</string>\n" >> $pp_macos_svc_plist_file
+ fi
+ if test -n "$pp_macos_service_cwd"; then
+ printf " <key>WorkingDirectory</key>\n" >> $pp_macos_svc_plist_file
+ printf " <string>$pp_macos_service_cwd</string>\n" >> $pp_macos_svc_plist_file
+ fi
+ if test -n "$pp_macos_service_nice"; then
+ printf " <key>Nice</key>\n" >> $pp_macos_svc_plist_file
+ printf " <string>$pp_macos_service_nice</string>\n" >> $pp_macos_svc_plist_file
+ fi
+ cat <<-. >> $pp_macos_svc_plist_file
+ </dict>
+ </plist>
+.
+}
+
+pp_macos_add_service () {
+ typeset svc svc_id plist_file plist_dir
+
+ pp_load_service_vars "$1"
+ svc=${pp_macos_service_name:-$1}
+ svc_id=${pp_macos_service_id:-$pp_macos_default_service_id_prefix$svc}
+
+ #-- create a plist file for svc
+ pp_macos_launchd_plist "$svc" "$svc_id"
+
+ #-- copy the plist file into place and add to %files
+ plist_dir="/Library/LaunchDaemons"
+ plist_file="$plist_dir/$svc_id.plist"
+ mkdir -p "$pp_destdir/$plist_dir"
+ cp "$pp_macos_svc_plist_file" "$pp_destdir/$plist_file"
+ pp_add_file_if_missing "$plist_file"
+
+ #-- add code to start the service on install & upgrade
+ ${pp_macos_start_services_after_install} && <<-. >> $pp_wrkdir/%post.$svc
+ # start service '$svc' automatically after install
+ launchctl load "$plist_file"
+.
+ ${pp_macos_start_services_after_install} && <<-. >> $pp_wrkdir/%postup.$svc
+ # start service '$svc' automatically after upgrade
+ # This is necessary if the service is new since the previous version.
+ # XXX: Does launchd automatically reload an service if its binary
+ # is replaced?
+ launchctl load "$plist_file"
+.
+}
+
+pp_backend_macos_probe () {
+ typeset name vers arch
+ case `sw_vers -productName` in
+ "macOS") name="macos";;
+ "Mac OS X") name="macos";;
+ *) name="unknown";;
+ esac
+ vers=`sw_vers -productVersion | awk -F. '{ printf "%d%02d\n", $1, $2 }'`
+ arch=`arch`
+ echo "$name$vers-$arch"
+}
+
+pp_backend_macos_vas_platforms () {
+ echo "osx" # XXX non-really sure what they do.. it should be "macos"
+}
+pp_backend_macos_function () {
+ case "$1" in
+ _pp_macos_search_unused) cat<<'.';;
+ # Find an unused value in the given path
+ # args: path attribute minid [maxid]
+ pp_tmp_val=$3
+ while :; do
+ test $pp_tmp_val -ge ${4:-999999} && return 1
+ /usr/bin/dscl . -search "$1" "$2" $pp_tmp_val |
+ grep . > /dev/null || break
+ pp_tmp_val=`expr $pp_tmp_val + 1`
+ done
+ echo $pp_tmp_val
+.
+ pp_mkgroup:depends) echo _pp_macos_search_unused;;
+ pp_mkgroup) cat<<'.';;
+ set -e
+ /usr/bin/dscl . -read /Groups/"$1" >/dev/null 2>&1 && return
+ pp_tmp_gid=`_pp_macos_search_unused /Groups PrimaryGroupID 100`
+ /usr/bin/dscl . -create /Groups/"$1"
+ /usr/bin/dscl . -create /Groups/"$1" PrimaryGroupID $pp_tmp_gid
+ /usr/bin/dscl . -create /Groups/"$1" RealName "Group $1"
+ /usr/bin/dscl . -create /Groups/"$1" GroupMembership ""
+ /usr/bin/dscl . -create /Groups/"$1" Password '*'
+.
+ pp_mkuser:depends) echo pp_mkgroup _pp_macos_search_unused;;
+ pp_mkuser) cat<<'.';;
+ set -e
+ /usr/bin/dscl . -read /Users/"$1" >/dev/null 2>&1 && return
+ pp_tmp_uid=`_pp_macos_search_unused /Users UniqueID 100`
+ pp_mkgroup "${2:-$1}"
+ pp_tmp_gid=`/usr/bin/dscl . -read /Groups/"${2:-$1}" \
+ PrimaryGroupID | awk '{print $2}'`
+ /usr/bin/dscl . -create /Users/"$1"
+ /usr/bin/dscl . -create /Users/"$1" PrimaryGroupID $pp_tmp_gid
+ /usr/bin/dscl . -create /Users/"$1" NFSHomeDirectory \
+ "${3:-/var/empty}"
+ /usr/bin/dscl . -create /Users/"$1" UserShell \
+ "${4:-/usr/bin/false}"
+ /usr/bin/dscl . -create /Users/"$1" RealName "$1"
+ /usr/bin/dscl . -create /Users/"$1" UniqueID $pp_tmp_uid
+ /usr/bin/dscl . -create /Users/"$1" Password '*'
+.
+ pp_havelib) cat<<'.';;
+ # (use otool -L to find dependent libraries)
+ for pp_tmp_dir in `echo "${3:+$3:}/usr/local/lib:/lib:/usr/lib" |
+ tr : ' '`; do
+ test -r "$pp_tmp_dir/lib$1{$2:+.$2}.dylib" && return 0
+ done
+ return 1
+.
+ *) false;;
+ esac
+}
+
+pp_platforms="$pp_platforms inst"
+
+pp_backend_inst_detect () {
+ case "$1" in
+ IRIX*) return 0;;
+ *) return 1;;
+ esac
+}
+
+pp_backend_inst_init () {
+ pp_readlink_fn=pp_ls_readlink
+}
+
+pp_backend_inst_create_idb()
+{
+ typeset t m o g f p st
+
+ while read t m o g f p st; do
+ if test x"$o" = x"-"; then
+ o="root"
+ fi
+ if test x"$g" = x"-"; then
+ g="sys"
+ fi
+ case "$t" in
+ f) test x"$m" = x"-" && m=444
+ echo "f 0$m $o $g $p $p $name.sw.base"
+ ;;
+ d) test x"$m" = x"-" && m=555
+ echo "d 0$m $o $g $p $p $name.sw.base"
+ ;;
+ s) test x"$m" = x"-" && m=777
+ test x"$m" = x"777" ||
+ pp_warn "$p: invalid mode $m for symlink, should be 777 or -"
+ echo "l 0$m $o $g $p $p $name.sw.base symval($st)"
+ ;;
+ esac
+ done
+}
+
+pp_backend_inst_create_spec()
+{
+ echo "product $name"
+ echo " id \"${summary}. Version: ${version}\""
+ echo " image sw"
+ echo " id \"Software\""
+ echo " version $version"
+ echo " order 9999"
+ echo " subsys base"
+ echo " id \"Base Software\""
+ echo " replaces self"
+ echo " exp $name.sw.base"
+ echo " endsubsys"
+ echo " endimage"
+ echo "endproduct"
+}
+
+pp_backend_inst () {
+ curdir=`pwd`
+
+ cd "$pp_opt_wrkdir"
+
+ # initialize
+ pp_inst_tardist=tardist
+ pp_inst_spec=${name}.spec
+ pp_inst_idb=${name}.idb
+
+ rm -rf $pp_inst_tardist $pp_inst_spec $pp_inst_idb
+ mkdir -p $pp_inst_tardist
+
+ # Create idb file
+ (for _cmp in $pp_components; do
+ cat %files.$_cmp | sort +4u -6 | pp_backend_inst_create_idb
+ done) >> $pp_inst_idb
+
+ pp_backend_inst_create_spec >> $pp_inst_spec
+
+ # Generate tardist
+ gendist -verbose -all -root / -source $pp_opt_destdir -idb $pp_inst_idb -spec $pp_inst_spec -dist $pp_inst_tardist $name
+ tar -cvf `pp_backend_inst_names` $pp_inst_tardist
+
+ cd "$curdir"
+}
+
+pp_backend_inst_cleanup () {
+ :
+}
+
+pp_backend_inst_names () {
+ echo ${name}-${version}.tardist
+}
+
+pp_backend_inst_install_script () {
+ :
+}
+
+pp_backend_inst_function () {
+ echo false
+}
+
+pp_backend_inst_init_svc_vars () {
+ :
+}
+
+pp_backend_inst_probe () {
+ cpu=`hinv|sed -n '/^CPU/{s/000 /k /;s/^CPU: //;s/ Process.*//;s/^MIPS //;p;q;}'|tr A-Z a-z`
+ echo irix`uname -r`-$cpu
+}
+
+pp_backend_inst_vas_platforms () {
+ echo "irix-65"
+}
+
+pp_platforms="$pp_platforms null"
+
+pp_backend_null_detect () {
+ ! :
+}
+
+pp_backend_null_init () {
+ :
+}
+
+
+pp_backend_null () {
+ :
+}
+
+pp_backend_null_cleanup () {
+ :
+}
+
+pp_backend_null_names () {
+ :
+}
+
+pp_backend_null_install_script () {
+ :
+}
+
+pp_backend_null_function () {
+ echo false
+}
+
+pp_backend_null_init_svc_vars () {
+ :
+}
+
+pp_backend_null_probe () {
+ echo unknown-unknown
+}
+
+pp_backend_null_vas_platforms () {
+:
+}
+
+pp_platforms="$pp_platforms bsd"
+
+pp_bsd_munge_text () {
+ # Insert a leading space on each line, replace blank lines with a
+ #space followed by a full-stop.
+ test -z "$1" && pp_die "pp_bsd_munge_text requires a parameter"
+ echo ${1} | sed "s,^\(.*\)$, \1, " | sed "s,^[ \t]*$, .,g"
+}
+
+pp_backend_bsd_detect () {
+ test x"$1" = x"FreeBSD" -o x"$1" = x"DragonFly"
+}
+
+pp_backend_bsd_init () {
+
+ # Get the OS revision
+ pp_bsd_detect_os
+
+ # Get the arch (i386/x86_64)
+ pp_bsd_detect_arch
+
+ pp_bsd_name=
+ pp_bsd_version=
+ pp_bsd_origin=
+ pp_bsd_comment=
+ pp_bsd_arch=
+ pp_bsd_abi=
+ pp_bsd_www=
+ pp_bsd_maintainer=
+ pp_bsd_prefix="/usr/local/"
+ pp_bsd_desc=
+ pp_bsd_message=
+
+ # Newer "pkg" (>=1.17.0) generates package.pkg, before that package.txz.
+ if pp_is_version_greater 1.17.0 "$(pkg --version)"; then
+ pp_bsd_pkg_sfx=pkg
+ else
+ pp_bsd_pkg_sfx=txz
+ fi
+
+ # pp_bsd_category must be in array format comma separated
+ # pp_bsd_category=[security,network]
+ pp_bsd_category=
+
+ # pp_bsd_licenselogic can be one of the following: single, and, or unset
+ pp_bsd_licenselogic=
+
+ # pp_bsd_licenses must be in array format comma separated
+ # pp_bsd_licenses=[GPLv2,MIT]
+ pp_bsd_licenses=
+
+ # pp_bsd_annotations. These can be any key: value pair
+ # key must be separated by a :
+ # keyvalue pairs must be comma separated
+ # pp_bsd_annotations="repo_type: binary, somekey: somevalue"
+ # since all packages created by PolyPackage will be of type binary
+ # let's just set it now.
+ pp_bsd_annotations="repo_type: binary"
+
+ pp_bsd_dbg_pkgname="debug"
+ pp_bsd_dev_pkgname="devel"
+ pp_bsd_doc_pkgname="doc"
+
+ # Make sure any programs we require are installed
+ pp_bsd_check_required_programs
+
+}
+
+pp_bsd_cmp_full_name () {
+ typeset prefix
+ prefix="${pp_bsd_name:-$name}"
+ case "$1" in
+ run) echo "${prefix}" ;;
+ dbg) echo "${prefix}-${pp_bsd_dbg_pkgname}";;
+ dev) echo "${prefix}-${pp_bsd_dev_pkgname}";;
+ doc) echo "${prefix}-${pp_bsd_doc_pkgname}";;
+ *) pp_error "unknown component '$1'";
+ esac
+}
+
+pp_bsd_check_required_programs () {
+ local p needed notfound ok
+ needed= notfound=
+
+ # list of programs FreeBSD needs in order to create a binary package
+ for prog in ${pp_bsd_required_programs:-"pkg"}
+ do
+ if command -v $prog 2>&1 > /dev/null; then
+ pp_debug "$prog: found"
+ else
+ pp_debug "$prog: not found"
+ case "$prog" in
+ pkg) p=pkg;;
+ *) pp_die "Unexpected pkg tool $prog";;
+ esac
+ notfound="$notfound $prod"
+ pp_contains "$needed" "$p" || needed="$needed $p"
+ fi
+ done
+ if [ -n "$notfound" ]; then
+ pp_error "cannot find these programs: $notfound"
+ pp_error "please install these packages: $needed"
+ fi
+}
+
+pp_bsd_detect_os () {
+ typeset revision
+
+ pp_bsd_os=`uname -s`
+ revision=`uname -r`
+ pp_bsd_os_rev=`echo $revision | awk -F '-' '{print $1}'`
+}
+
+pp_bsd_detect_arch() {
+ pp_bsd_platform="`uname -m`"
+ case $pp_bsd_platform in
+ amd64|x86_64) pp_bsd_platform_std=x86_64;;
+ i386) pp_bsd_platform_std=i386;;
+ *) pp_bsd_platform_std=unknown;;
+ esac
+}
+
+pp_bsd_label () {
+ local label arg
+ label="$1"; shift
+ for arg
+ do
+ test -z "$arg" || echo "$label: $arg"
+ done
+}
+
+pp_bsd_make_annotations () {
+
+ test -z $1 && pp_die "pp_bsd_make_annotations requires a parameter"
+ manifest=$1
+
+ # Add annotations. These can be any key: value pair
+ # key must be separated by a :
+ # key:value pairs must be comma separated.
+ if test -n "$pp_bsd_annotations"; then
+ pp_debug "Processing annotations:"
+ pp_bsd_label "annotations" "{" >> $manifest
+
+ SAVEIFS=$IFS
+ IFS=,
+ for annotate in $pp_bsd_annotations; do
+ # Remove any spaces at the start of the line
+ annotate=`echo $annotate | sed 's/^ *//'`
+ pp_debug " $annotate"
+ echo " $annotate" >> $manifest
+ done
+ IFS=$SAVEIFS
+ echo "}" >> $manifest
+ fi
+}
+
+pp_bsd_make_depends() {
+ typeset package origin version
+ cmp=$1
+ manifest=$2
+
+ if test -s $pp_wrkdir/%depend.${cmp}; then
+ echo "deps: {" >> $manifest
+ cat $pp_wrkdir/%depend.${cmp} | while read package origin version; do
+ if test x != x$package; then
+ pp_debug "Processing dependency: $package"
+ if test x != x$origin -a x != x$version; then
+ pp_debug " $package: {origin: \"$origin\", version: \"$version\"}"
+ echo " $package: {origin: \"$origin\", version: \"$version\"}" >> $manifest
+ else
+ pp_warn "Dependency $package is missing origin or version or both"
+ fi
+ fi
+ done
+ echo "}" >> $manifest
+ fi
+}
+
+pp_bsd_make_messages () {
+ test -z $1 && pp_die "pp_bsd_make_messages requires a parameter"
+ manifest=$1
+
+ pp_debug "Processing messages"
+
+ # Empty messages: [ ] is OK in the manifest
+ pp_bsd_label "messages" "[" >> $manifest
+ # Look for a single message in the variable pp_bsd_message
+ if test -n "$pp_bsd_message"; then
+ echo " { message: \"`pp_bsd_munge_text "$pp_bsd_message"`\" }," >> $manifest
+ fi
+ local a=1
+ # Look for messages in the variables pp_bsd_message_[1..n]
+ var="pp_bsd_messages_1"
+ while [ -n "${!var}" ]; do
+ echo " { message: \"`pp_bsd_munge_text "${!var}"`\" }," >> $manifest
+ a=`expr $a + 1`
+ var="pp_bsd_messages_$a"
+ done
+ echo "]" >> $manifest
+}
+
+pp_bsd_make_manifest() {
+ local cmp manifest
+
+ cmp="$1"
+ manifest="$2"
+
+ package_name=`pp_bsd_cmp_full_name $cmp`
+
+ # Required for pkg +MANIFEST
+ cat <<-. >> $manifest
+ name: "${package_name}"
+ version: "${pp_bsd_version:-$version}"
+ origin: "${pp_bsd_origin}"
+ www: "${pp_bsd_www}"
+ desc: "`pp_bsd_munge_text "${pp_bsd_desc:-$description}"`"
+ comment: "${pp_bsd_comment:-$summary}"
+ maintainer: "${pp_bsd_maintainer}"
+ prefix: "${pp_bsd_prefix}"
+.
+
+ # Optional, so if they are not included in the pkg-product.pp file then do not create the label
+ pp_bsd_label "categories" "${pp_bsd_categories}" >> $manifest
+ pp_bsd_label "arch" "${pp_bsd_arch}" >> $manifest
+ pp_bsd_label "abi" "${pp_bsd_abi}" >> $manifest
+ pp_bsd_label "licenselogic" "${pp_bsd_licenselogic}" >> $manifest
+ pp_bsd_label "licenses" "${pp_bsd_licenses}" >> $manifest
+
+ pp_bsd_make_annotations $manifest
+ pp_bsd_make_depends $cmp $manifest
+
+ pp_bsd_make_messages $manifest
+}
+
+pp_bsd_fakeroot () {
+ if test -s $pp_wrkdir/fakeroot.save; then
+ fakeroot -i $pp_wrkdir/fakeroot.save -s $pp_wrkdir/fakeroot.save "$@"
+ else
+ fakeroot -s $pp_wrkdir/fakeroot.save "$@"
+ fi
+}
+
+pp_bsd_make_data() {
+ # t = file type
+ # m = file mode
+ # o = file owner
+ # g = file group
+ # f = ?
+ # p = file path
+ # st = file link
+ #
+ # EXAMPLE: f 755 root httpd v /usr/bin/hello goodbye
+ # -> /usr/bin/hello: {uname: root, gname: httpd, perm: 755 } goodbye
+ typeset _l t m o g f p st datadir
+ cmp=$1
+ datadir=$pp_wrkdir/`pp_bsd_cmp_full_name $cmp`
+ local path
+
+ outfilelist="$pp_wrkdir/files.list.$cmp"
+ outdirslist="$pp_wrkdir/dirs.list.$cmp"
+
+ pp_debug "Processing $pp_wrkdir/%file.${cmp}"
+
+ echo "files: {" > $outfilelist
+ echo "directories: {" > $outdirslist
+
+ cat $pp_wrkdir/%files.${cmp} | while read t m o g f p st; do
+ test x"$o" = x"-" && o="${pp_bsd_defattr_uid:-root}"
+ test x"$g" = x"-" && g="${pp_bsd_defattr_gid:-wheel}"
+ if test x"$m" = x"-"; then
+ case "$t" in
+ d) m=755;;
+ f) m=644;;
+ esac
+ fi
+ path=$p
+ case "$t" in
+ f) # Files
+ case "$f" in
+ *v*)
+ # For now just skip the file if it is volatile, we
+ # will need to remove it in the pre uninstall script
+ pp_warn "file $path was marked as volatile, skipping"
+ ;;
+ *)
+ # If the directory doesn't exist where we are going to copy this file, then create it first
+ if [ ! -d `dirname "$datadir$path"` ]; then
+ pp_debug "creating directory `dirname "$datadir$path"`"
+ mkdir -p `dirname "$datadir$path"`
+ fi
+
+ pp_debug "install -D $datadir -o $o -g $g -m ${m} -v $pp_destdir$p $datadir$path"
+ pp_bsd_fakeroot install -D $datadir -o $o -g $g -m ${m} -v $pp_destdir$p $datadir$path
+ echo " \"$path\": \"-\", \"$path\": {uname: $o, gname: $g, perm: ${m}}" >> $outfilelist
+ ;;
+ esac
+ ;;
+ d) # Directories
+ pp_debug "install -D $datadir -o $o -g $g -m ${m} -d -v $datadir$path";
+ pp_bsd_fakeroot install -D $datadir -o $o -g $g -m ${m} -d -v $datadir$path;
+ echo " \"$path\": \"-\", \"$path\": {uname: $o, gname: $g, perm: ${m}}" >> $outdirslist;
+ ;;
+ s) # Symlinks
+ pp_debug "Found symlink: $datadir$path";
+ # Remove leading /
+ rel_p=`echo $p | sed s,^/,,`
+ (cd $datadir; ln -sf $st $rel_p);
+ # Do we care if the file doesn't exist? Just symnlink it regardless and throw a warning? This will be important in the case
+ # where we depend on other packages to be installed and will be using the libs from that package.
+ if [ ! -e "$datadir$path" ]; then
+ pp_warn "$datadir$path does not exist"
+ fi
+ echo " \"$path\": \"$st\"" >> $outfilelist;
+ ;;
+ *) pp_error "Unsupported data file type: %t";;
+ esac
+ done
+
+ echo "}" >> $outfilelist
+ echo "}" >> $outdirslist
+ cat $outfilelist >> $manifest
+ cat $outdirslist >> $manifest
+
+ pp_debug "Finished processing $pp_wrkdir/%file.${cmp}"
+}
+
+pp_bsd_makebsd() {
+ typeset cmp
+ typeset package_build_dir
+ local manifest postinstall preinstall preuninstall postuninstall preupgrade postupgrade
+
+ cmp="$1"
+
+ if test -z "$pp_bsd_platform"; then
+ pp_error "Unknown BSD architecture"
+ return 1
+ fi
+
+ _subname=`pp_bsd_cmp_full_name $cmp`
+ package_build_dir=$pp_wrkdir/$_subname
+
+ manifest="$package_build_dir/+MANIFEST"
+ postinstall="$package_build_dir/+POST_INSTALL"
+ preinstall="$package_build_dir/+PRE_INSTALL"
+ preuninstall="$package_build_dir/+PRE_DEINSTALL"
+ postuninstall="$package_build_dir/+POST_DEINSTALL"
+ preupgrade="$package_build_dir/+PRE_UPGRADE"
+ postupgrade="$package_build_dir/+POST_UPGRADE"
+
+ # Create package dir
+ mkdir -p $package_build_dir
+
+ pp_bsd_make_manifest $cmp $manifest
+ pp_bsd_make_data $cmp
+
+ pp_debug "Processing pre/post install scripts"
+
+ if test -s $pp_wrkdir/%pre.$cmp; then
+ pp_debug "Found %pre.$cmp"
+ {
+ cat "$pp_wrkdir/%pre.$cmp"
+ } > $preinstall
+ pp_debug "Created $preinstall"
+ fi
+
+ if test -s $pp_wrkdir/%post.$cmp; then
+ pp_debug "Found %post.$cmp"
+ {
+ echo "# Post install script for "
+ cat "$pp_wrkdir/%post.$cmp"
+ } > $postinstall
+ pp_debug "Created $postinstall"
+ fi
+
+ pp_debug "Processing pre/post uninstall scripts"
+
+ if test -s $pp_wrkdir/%preun.$cmp; then
+ pp_debug "Found %preun.$cmp"
+ {
+ echo "# Pre uninstall script for ${pp_bsd_name:-$name}"
+ cat "$pp_wrkdir/%preun.$cmp"
+ } > $preuninstall
+ pp_debug "Created pkg $preuninstall"
+ fi
+
+ if test -s $pp_wrkdir/%postun.$cmp; then
+ pp_debug "Found %postun.$cmp"
+ {
+ echo "# Post uninstall script for ${pp_bsd_name:-$name}"
+ cat "$pp_wrkdir/%postun.$cmp"
+ } > $postuninstall
+ pp_debug "Created $postuninstall"
+ fi
+
+ if test -s $pp_wrkdir/%preup.$cmp; then
+ pp_debug "Found %preup.$cmp"
+ {
+ echo "# Pre upgrade script for ${pp_bsd_name:-$name}"
+ cat "$pp_wrkdir/%preup.$cmp"
+ } > $preupgrade
+ pp_debug "Created pkg $preupgrade"
+ fi
+
+ if test -s $pp_wrkdir/%postup.$cmp; then
+ pp_debug "Found %postup.$cmp"
+ {
+ echo "# Post upgrade script for ${pp_bsd_name:-$name}"
+ cat "$pp_wrkdir/%postup.$cmp"
+ } > $postupgrade
+ pp_debug "Created $postupgrade"
+ fi
+}
+
+pp_backend_bsd() {
+ #get-files-dir-entries
+ #create-manifest
+ #create-preuninstall
+ #create-postinstall
+ #create-package
+ #
+ pp_bsd_handle_services
+
+ for cmp in $pp_components
+ do
+ _subname=`pp_bsd_cmp_full_name $cmp`
+ pp_debug "Generating packaging specific files for $_subname"
+ pp_bsd_makebsd $cmp
+ done
+
+ # call this to fixup any files before creating the actual packages
+ . $pp_wrkdir/%fixup
+
+ for cmp in $pp_components
+ do
+ _subname=`pp_bsd_cmp_full_name $cmp`
+ package_build_dir=$pp_wrkdir/$_subname
+ # Build the actual packages now
+ pp_debug "Building FreeBSD $_subname"
+ pp_debug "Running package create command: pkg create -m $package_build_dir -r $pp_wrkdir/`pp_bsd_cmp_full_name $cmp` -o $pp_wrkdir"
+ pp_bsd_fakeroot pkg create -m $package_build_dir -r $pp_wrkdir/`pp_bsd_cmp_full_name $cmp` -o $pp_wrkdir -v
+ done
+
+}
+
+pp_bsd_name () {
+ typeset cmp="${1:-run}"
+ echo `pp_bsd_cmp_full_name $cmp`"-${pp_bsd_version:-$version}.${pp_bsd_pkg_sfx}"
+}
+
+pp_backend_bsd_names () {
+ for cmp in $pp_components; do
+ echo `pp_bsd_cmp_full_name $cmp`"-${pp_bsd_version:-$version}.${pp_bsd_pkg_sfx}"
+ done
+}
+
+pp_backend_bsd_cleanup () {
+ :
+}
+
+pp_backend_bsd_probe () {
+ echo "${pp_bsd_os}-${pp_bsd_platform_std}"
+ echo "${pp_bsd_os}${pp_bsd_os_rev}-${pp_bsd_platform_std}"
+}
+
+
+pp_backend_bsd_vas_platforms() {
+ case "${pp_bsd_platform_std}" in
+ x86_64) echo "FreeBSD-x86_64.${pp_bsd_pkg_sfx} FreeBSD-i386.${pp_bsd_pkg_sfx}";;
+ i386) echo "FreeBSD-i386.${pp_bsd_pkg_sfx}";;
+ *) pp_die "unknown architecture $pp_bsd_platform_std";;
+ esac
+}
+
+
+pp_backend_bsd_install_script () {
+ typeset cmp _cmp_full_name
+
+ echo "#!/bin/sh"
+ pp_install_script_common
+
+ cat <<.
+
+ cmp_to_pkgname () {
+ test x"\$*" = x"all" && set -- $pp_components
+ for cmp
+ do
+ case \$cmp in
+.
+ for cmp in $pp_components; do
+ echo " $cmp) echo '`pp_bsd_cmp_full_name $cmp`';;"
+ done
+
+ cat <<.
+ *) usage;;
+ esac
+ done
+ }
+
+ cmp_to_pathname () {
+ test x"\$*" = x"all" &&
+ set -- $pp_components
+ for cmp
+ do
+ case \$cmp in
+.
+ for cmp in $pp_components; do
+ echo " $cmp) echo \${PP_PKGDESTDIR:-.}/'`pp_bsd_name $cmp`';;"
+ done
+
+ cat <<.
+ *) usage;;
+ esac
+ done
+ }
+
+ test \$# -eq 0 && usage
+ op="\$1"; shift
+ case "\$op" in
+ list-components)
+ test \$# -eq 0 || usage \$op
+ echo $pp_components
+ ;;
+ list-services)
+ test \$# -eq 0 || usage \$op
+ echo $pp_services
+ ;;
+ list-files)
+ test \$# -ge 1 || usage \$op
+ cmp_to_pathname "\$@"
+ ;;
+ install)
+ test \$# -ge 1 || usage \$op
+ pkg add \`cmp_to_pathname "\$@"\`
+ ;;
+ uninstall)
+ test \$# -ge 1 || usage \$op
+ pkg remove \`cmp_to_pkgname "\$@"\`; :
+ ;;
+ start|stop)
+ test \$# -ge 1 || usage \$op
+ ec=0
+ for svc
+ do
+ /etc/rc.d/\$svc \$op || ec=1
+ done
+ exit \$ec
+ ;;
+ print-platform)
+ test \$# -eq 0 || usage \$op
+ echo "${pp_bsd_os}-${pp_bsd_platform}"
+ echo '`pp_backend_bsd_probe`'
+ ;;
+ *)
+ usage
+ ;;
+ esac
+.
+}
+pp_backend_bsd_init_svc_vars () {
+ svc_process_regex="${pp_bsd_svc_process_regex}"
+ svc_description=$summary
+ svc_init_prefix="${pp_bsd_prefix}"
+ svc_init_filename="${pp_bsd_svc_init_filename}" # == $svc
+ svc_init_filepath="${pp_bsd_svc_init_filepath}" # == $pp_bsd_prefix/etc/rc.d/ by default
+
+ bsd_svc_before="${pp_bsd_svc_before}"
+ bsd_svc_require="${pp_bsd_svc_require}"
+ bsd_svc_keyword="${pp_bsd_svc_keyword}"
+
+}
+
+pp_bsd_service_make_init_info() {
+ local svc=$1
+ local out=$2
+ cat <<-. >$out
+ #!/bin/sh
+ #
+ # FreeBSD Script Header Detail
+ #
+ # PROVIDE: $svc
+.
+
+ if [ ! -z "$bsd_svc_before" ]; then
+ cat <<-. >>$out
+ # BEFORE: $bsd_svc_before
+.
+ fi
+
+ if [ ! -z "$bsd_svc_require" ]; then
+ cat <<-. >>$out
+ # REQUIRE: $bsd_svc_require
+.
+ fi
+
+ if [ ! -z "$bsd_svc_keyword" ]; then
+ cat <<-. >>$out
+ # KEYWORD: $bsd_svc_keyword
+.
+ fi
+
+ cat <<-'.' >>$out
+ ### END INIT INFO
+
+.
+
+}
+
+pp_bsd_service_make_init_set_vars() {
+ local svc=$1
+ local out=$2
+
+ svc_command="$cmd"
+ svc_pre_command="${pp_bsd_svc_pre_command}"
+ svc_pre_command_args="${pp_bsd_svc_pre_command_args}"
+
+ local run_command="${svc_pre_command:-$svc_command}"
+ local run_pre_command_args="${svc_pre_command:+"${svc_pre_command_args}"}"
+ local run_post_command_args="${svc_command:+"${svc_command_args}"}"
+ local run_post_command_without_pre_command="${svc_pre_command:+"$svc_command"}"
+ local run_post_command_with_args="${run_post_command_without_pre_command}${run_post_command_args:+" $run_post_command_args"}"
+ local run_command_args="${run_pre_command_args:+"$run_pre_command_args"}${run_post_command_with_args:+" $run_post_command_with_args"}"
+
+ # https://www.freebsd.org/cgi/man.cgi?query=rc.subr
+ cat <<-. >>$out
+ # FreeBSD rc subroutines
+ . /etc/rc.subr
+
+ # 0: Not running.
+ # 1: Running normally
+ # 2: Running, but no PID file.
+ # 3: Running, but PID file doesn't match running processes.
+ # If the PID file is found but no process, the file is removed and 0 is returned.
+ DAEMON_RUNNING=0
+
+ name="$svc"
+ desc="${svc_description:-\$name}"
+
+ start_cmd="\${name}_start"
+ status_cmd="\${name}_status"
+ stop_cmd="\${name}_stop"
+
+ # Loads any variables set in /etc/rc.conf.d/\$name
+ load_rc_config \$name
+
+ : \${${svc}_enable:="Yes"}
+ : \${${svc}_pidfile:="${pidfile:-/var/run/\${name\}.pid}"}
+ : \${${svc}_args:="$run_command_args"}
+ : \${${svc}_cmd:="$run_command"}
+
+ # Regex used in the pp_check_daemon_running ps check to find our running processe(s)
+ # If it's set in /etc/rc.conf.d/\$name this will be used first
+ # then check if pp_bsd_svc_process_regex is set, finally set to the \${name}_cmd
+ # When set to \${name}_cmd pp_check_daemon_running will only find the parent process pid
+ : \${${svc}_process_regex:="${pp_bsd_svc_process_regex:-${cmd}}"}
+
+ # For additional information about the rc.subr see:
+ # https://www.freebsd.org/cgi/man.cgi?query=rc.subr
+ rcvar="\${name}_enable"
+
+ pidfile=\${${svc}_pidfile}
+
+ command="\$${svc}_cmd"
+ command_args="\$${svc}_args"
+
+.
+
+}
+
+pp_bsd_service_make_init_body() {
+ local svc=$1
+ local out=$2
+
+ cat<<-'.' >>$out
+ pp_exec_cmd() { (eval $command $command_args) }
+
+ pp_success_msg () { echo ${1:+"$*:"} OK; }
+ pp_failure_msg () { echo ${1:+"$*:"} FAIL; }
+ pp_warning_msg () { echo ${1:+"$*:"} WARNING; }
+
+ #-- prints a status message
+ pp_msg () { echo -n "$*: "; }
+
+ # Kills process $1.
+ # First a sigterm, then wait up to 10 seconds
+ # before issuing a sig kill.
+ pp_signal () {
+ # Kill the processes the nice way first
+ if [ -z "$1" ]; then
+ # No pid file. Use the list from pp_check_daemon_running
+ kill $PROCESSES 2>/dev/null
+ else
+ kill $1 2>/dev/null
+ fi
+ count=1
+
+ #Check to make sure the processes died, if not kill them the hard way
+ while [ $count -le 10 ]; do
+ sleep 1
+ pp_check_daemon_running
+ if [ $DAEMON_RUNNING -eq 0 ]; then
+ break;
+ fi
+ if [ $count -eq 1 ]; then
+ # We tried killing the pid associated to the pidfile, now try the ones we found from pp_check_daemon_running
+ kill $PROCESSES 2>/dev/null
+ fi
+ count=`expr $count + 1`
+ done
+ # Check one more time to make sure we got them all
+ if [ $DAEMON_RUNNING -ne 0 ]; then
+ # These guys don't want to go down the nice way, now just kill them
+ kill -9 $PROCESSES 2>/dev/null
+ fi
+ # make sure to remove the pidfile
+ rm -f $pidfile
+ }
+
+ # Check to see if the daemon process is running
+ # Sets the PROCESSES global variable with all pids that match
+ # ${name}_process_regex
+ # Sets global variable DAEMON_RUNNING to one of the following:
+ # 0: Not Running
+ # 1: Running normally
+ # 2: Running, but no PID file
+ # 3: Running, but PID file doesn't match running processes.
+ #
+ pp_check_daemon_running()
+ {
+ DAEMON_RUNNING=0
+.
+ cat<<-. >>$out
+
+ PROCESSES="\`eval ps -axo pid,args | grep "\${${svc}_process_regex}" | grep -v grep | awk '{print \$1}'\`"
+
+.
+ cat<<-'.' >>$out
+ if [ -f $pidfile ]; then
+ if [ ! -z "$PROCESSES" ]; then
+ PARENT_PID=`cat $pidfile 2>/dev/null`
+ PPROCESS=`echo $PROCESSES | grep "${PARENT_PID:-"NOPID"}"`
+ if [ $? -eq 0 ]; then
+ DAEMON_RUNNING=1
+ else
+ DAEMON_RUNNING=3
+ fi
+ else
+ rm -r $pidfile
+ fi
+ else
+ if [ ! -z "$PROCESSES" ]; then
+ DAEMON_RUNNING=2
+ fi
+ fi
+ }
+.
+ cat <<-. >>$out
+
+ # starts the service
+ ${svc}_start()
+.
+ cat <<-'.' >>$out
+ {
+ pp_msg "Starting ${desc}"
+ pp_check_daemon_running
+
+ if [ $DAEMON_RUNNING -eq 0 ]; then
+ pp_exec_cmd
+ RETVAL=$?
+ if [ $RETVAL -eq 0 ]; then
+ pp_success_msg
+ else
+ pp_failure_msg "cannot start"
+ fi
+ else
+ if [ $DAEMON_RUNNING -eq 1 ]; then
+ pp_success_msg "${name} appears to be running already"
+ else
+ pp_warning_msg "${name} is already running but without a pid file"
+ fi
+ fi
+ }
+
+.
+
+ cat <<-. >>$out
+ # stops the service
+ ${svc}_stop()
+.
+
+ cat <<-'.' >>$out
+ {
+ pp_msg "Stopping ${desc}"
+ pp_check_daemon_running
+
+ if [ $DAEMON_RUNNING -ne 0 ]; then
+ pp_signal `cat $pidfile 2>/dev/null`
+ if [ -n "$pidfile" ]; then
+ loop_cnt=1
+ while [ -e ${pidfile} ]; do
+ sleep 1
+ loop_cnt=`expr $loop_cnt + 1`
+ if [ $loop_cnt -eq 10 ]; then
+ break
+ fi
+ done
+ fi
+ rm -f $pidfile
+
+ pp_success_msg
+ else
+ pp_failure_msg
+ echo -n "$desc does not appear to be running."
+ echo
+ fi
+ }
+.
+
+ cat <<-. >>$out
+ # prints information about the service status
+ # returns:
+ # 0=running
+ # 1=Not running
+ # 2=Running without pidfile
+ # 3=Running with pid that doesn't match pidfile
+ ${svc}_status()
+.
+
+ cat <<-'.' >>$out
+ {
+ pp_msg "Checking ${desc}"
+ pp_check_daemon_running
+ if [ $DAEMON_RUNNING -eq 1 ]; then
+ pp_success_msg "PID $PARENT_PID: running"
+ return 0
+ else
+ if [ $DAEMON_RUNNING -eq 0 ]; then
+ pp_failure_msg "not running"
+ return 1
+ elif [ $DAEMON_RUNNING -eq 2 ]; then
+ pp_warning_msg "running without a pid file"
+ return 2
+ else
+ pp_warning_msg "running but pid file doesn't match running processe()"
+ return 3
+ fi
+ fi
+ }
+
+ run_rc_command "$1"
+.
+}
+
+pp_bsd_service_make_init_script () {
+ local svc=${svc_init_filename:-$1}
+ local script="${svc_init_filepath:-"${svc_init_prefix}/etc/rc.d"}/$svc"
+ script=`echo $script | sed 's://*:/:g'`
+ local out=$pp_destdir$script
+
+ pp_add_file_if_missing $script run 755 || return 0
+
+ pp_bsd_service_make_init_info "$svc" "$out"
+ pp_bsd_service_make_init_set_vars "$svc" "$out"
+ pp_bsd_service_make_init_body "$svc" "$out"
+
+ chmod 755 $out
+
+}
+
+pp_bsd_handle_services () {
+ if test -n "$pp_services"; then
+ for svc in $pp_services; do
+ pp_load_service_vars $svc
+ # Append some code to %post to install the svc TODO: Figure out why/what
+ pp_bsd_service_make_init_script $svc
+ # prepend some code to %preun to uninstall svc TODO: Figure out why/what
+ done
+ fi
+}
+pp_backend_bsd_function() {
+ case "$1" in
+ pp_mkgroup) cat<<'.';;
+ /usr/sbin/pw group show "$1" 2>/dev/null && return 0
+ /usr/sbin/pw group add "$1"
+.
+ pp_mkuser:depends) echo pp_mkgroup;;
+ pp_mkuser) cat<<'.';;
+ #Check if user exists
+ /usr/sbin/pw user show "$1" 2>/dev/null && return 0
+ pp_mkgroup "${2:-$1}" || return 1
+ echo "Creating user $1"
+ /usr/sbin/pw user add \
+ -n "$1" \
+ -d "${3:-/nonexistent}" \
+ -g "${2:-$1}" \
+ -s "${4:-/bin/false}"
+.
+ pp_havelib) cat<<'.';;
+ for pp_tmp_dir in `echo "/usr/local/lib:/usr/lib:/lib${3:+:$3}" | tr : ' '`; do
+ test -r "$pp_tmp_dir/lib$1.so{$2:+.$2}" && return 0
+ done
+ return 1
+.
+ *) false;;
+ esac
+}
+pp_systemd_make_service_file() {
+ local svc f
+
+ if [ "${pp_systemd_disabled:-false}" = "true" ]; then
+ return
+ fi
+
+ svc="$1"
+ f="${pp_systemd_service_dir:-/opt/quest/libexec/vas}/$svc.service"
+ pp_add_file_if_missing $f run 644 v || return 0
+
+ cat <<. >$pp_destdir$f
+
+[Unit]
+Description=${pp_systemd_service_description:-"systemd service file for $svc"}
+${pp_systemd_service_man:+"Documentation=$pp_systemd_service_man"}
+${pp_systemd_service_documentation:+"Documentation=$pp_systemd_service_documentation"}
+${pp_systemd_service_requires:+"Requires=$pp_systemd_service_requires"}
+After=${pp_systemd_service_after:-"syslog.target network.target auditd.service"}
+${pp_systemd_service_before:+"Before=$pp_systemd_service_before"}
+${pp_systemd_service_wants:+"Wants=$pp_systemd_service_wants"}
+${pp_systemd_service_conflicts:+"Conflicts=$pp_systemd_service_conflicts"}
+
+[Service]
+ExecStart=${pp_systemd_service_exec:-"/opt/quest/sbin/$svc"} ${pp_systemd_service_exec_args}
+KillMode=${pp_systemd_service_killmode:-process}
+Type=${pp_systemd_service_type:-forking}
+${pp_systemd_service_pidfile:+"PIDFile=$pp_systemd_service_pidfile"}
+
+[Install]
+WantedBy=${pp_systemd_system_target:-"multi-user.target"}
+.
+}
+
+pp_systemd_service_init_common () {
+ cat <<.
+
+ _pp_systemd_init () {
+ systemd_service_dir=${pp_systemd_service_dir:-/opt/quest/libexec/vas}
+ systemd_target=${pp_systemd_system_target:-"multi-user.target"}
+ systemd_target_wants="\${systemd_target}.wants"
+
+ pkg_config_cmd=${pp_systemd_pkg_config_cmd:-"\$(command -v pkg-config)"}
+ systemctl_cmd=${pp_systemd_systemctl_cmd:-"\$(command -v systemctl)"}
+
+ # See if pkg-config is installed to get the default locations for this OS, if not installed then just use what we hard code.
+ # So far works on Debian 8, OpenSuse12.3, Ubuntu 16.04, RHEL 7.3
+ # See systemd wiki for more OS interactions https://en.wikipedia.org/wiki/Systemd
+ if [ -x "\$pkg_config_cmd" ]; then
+ systemd_system_unit_dir="\$(pkg-config systemd --variable=systemdsystemunitdir)"
+ systemd_system_conf_dir="\$(pkg-config systemd --variable=systemdsystemconfdir)"
+ fi
+
+ #if pkg-config does not exist or if the \$pkg_config_cmd command returns nothing
+ if test -z "\$systemd_system_unit_dir"; then
+ systemdsystemunitdirs="/lib/systemd/system /usr/lib/systemd/system"
+ for dir in \$systemdsystemunitdirs; do
+ if [ -d "\$dir/\$systemd_target_wants" ]; then
+ systemd_system_unit_dir="\$dir"
+ break
+ fi
+ done
+ fi
+
+ # In the case where \$systemd_system_conf_dir is empty hard code the path
+ if test -z "\$systemd_system_conf_dir"; then
+ systemd_system_conf_dir="/etc/systemd/system"
+ fi
+
+ # if the \$svc.pp file defines the systemd unit dir then use it.
+ ${pp_systemd_system_unit_dir:+"# systemd_system_unit_dir defined by variable pp_systemd_system_unit_dir from the \$svc.pp file"}
+ systemd_system_unit_dir="${pp_systemd_system_unit_dir:-"\$systemd_system_unit_dir"}"
+
+ # if the \$svc.pp file defines the systemd conf dir then use it.
+ ${pp_systemd_system_conf_dir:+"# systemd_system_conf_dir defined by variable pp_systemd_system_conf_dir from the \$svc.pp file"}
+ systemd_system_conf_dir="${pp_systemd_system_conf_dir:-"\$systemd_system_conf_dir"}"
+ }
+.
+}
+
+pp_systemd_service_install_common () {
+ if [ "${pp_systemd_disabled:-false}" = "true" ]; then
+ cat<<'.'
+
+ # systemd support disabled
+ _pp_systemd_init () {
+ return
+ }
+
+ _pp_systemd_install () {
+ return
+ }
+
+ _pp_systemd_enable () {
+ return
+ }
+.
+ return
+ fi
+
+ pp_systemd_service_init_common
+
+ cat<<'.'
+
+ _pp_systemd_install () {
+ local svc="$1"
+
+ # If $systemctl_cmd is not set, then call _pp_systemd_init. If still not
+ # set, we do not know where the systemctl command is so do nothing;
+ # systemd must not be on this system.
+ if test -z "$systemctl_cmd"; then
+ _pp_systemd_init
+ fi
+
+ if test -x "$systemctl_cmd" && test -d "$systemd_system_conf_dir/$systemd_target_wants"; then
+ # If our service file still exists (upgrade) remove the link/file and systemctl
+ # will recreate it if/when we enable the $svc service.
+ rm -f "$systemd_system_conf_dir/$systemd_target_wants/$svc.service"
+
+ # Copy the $svc.service file to the correct systemd_system_unit_dir location
+ if [ "x$systemd_service_dir" != "x$systemd_system_unit_dir" ]; then
+ cp -f "$systemd_service_dir/$svc.service" "$systemd_system_unit_dir/$svc.service"
+ chmod 644 "$systemd_system_unit_dir/$svc.service"
+ fi
+ fi
+ }
+
+ _pp_systemd_enable () {
+ local svc="$1"
+ local RUNNING
+
+ # If $systemctl_cmd is not set, then call _pp_systemd_init. If still not
+ # set, we do not know where the systemctl command is so do nothing;
+ # systemd must not be on this system.
+ if test -z "$systemctl_cmd"; then
+ _pp_systemd_init
+ fi
+
+ if test -x "$systemctl_cmd" && test -f "$systemd_system_unit_dir/$svc.service"; then
+ # stop the daemon using the old init script before enabling systemd for the service
+ # we do this so we do not "orphan" the process. Because init started it and if we enable systemd
+ # it will not know about this process and will not be able to stop it.
+ if [ -x "/etc/init.d/$svc" ]; then
+ output="$(/etc/init.d/$svc status 2>&1)"
+ RUNNING=$?
+ if [ $RUNNING -eq 0 ]; then
+ case "$output" in
+ *"not running"*)
+ # systemd is reporting the status (compatibility package is installed)
+ RUNNING=1
+ ;;
+ *) # it is really running
+ /etc/init.d/$svc stop > /dev/null 2>&1
+ ;;
+ esac
+ fi
+ fi
+
+ # If the service is not running according to its sysv script (eg. systemd service
+ # is not using a pidfile the sysv script needs), or its sysv script is not present any more,
+ # check how systemd thinks.
+ # We also try to restart the service in case something went wrong with it.
+ if $systemctl_cmd is-active "$svc" >/dev/null 2>&1 || $systemctl_cmd is-failed "$svc" >/dev/null 2>&1; then
+ $systemctl_cmd stop "$svc" >/dev/null 2>&1
+ RUNNING=0
+ fi
+
+ # Enable the $svc.service
+ $systemctl_cmd daemon-reload >/dev/null 2>&1
+
+ # We do not need the init.d script any more, and it causes problems on SLES
+ # where systemd sysv compatibility is enforced and broken on default installs
+ rm -f "/etc/init.d/$svc"
+
+ $systemctl_cmd enable $svc.service >/dev/null 2>&1
+
+ # Now that the service has been enabled, start it again if it was running before.
+ if [ $RUNNING -eq 0 ]; then
+ $systemctl_cmd start $svc.service >/dev/null 2>&1
+ fi
+ fi
+ }
+.
+}
+
+pp_systemd_service_remove_common () {
+ if [ "${pp_systemd_disabled:-false}" = "true" ]; then
+ cat<<'.'
+
+ # systemd support disabled
+ _pp_systemd_init () {
+ return
+ }
+
+ _pp_systemd_disable () {
+ return
+ }
+
+ _pp_systemd_remove () {
+ return
+ }
+.
+ return
+ fi
+
+ pp_systemd_service_init_common
+
+ cat<<'.'
+
+ _pp_systemd_disable () {
+ local svc="$1"
+
+ # If $systemctl_cmd is not set, then call _pp_systemd_init.
+ # If still not set, we do not know where the systemctl command
+ # is so do nothing; systemd must not be on this system.
+ if test -z "$systemctl_cmd"; then
+ _pp_systemd_init
+ fi
+
+ systemd_service_file="$systemd_system_conf_dir/$systemd_target_wants/$svc.service"
+
+ # Remove systemd symlink (enabled) unit service file
+ if test -e $systemd_service_file; then
+ # Disable the $svc service
+ if test -x "$systemctl_cmd"; then
+ $systemctl_cmd disable $svc.service > /dev/null 2>&1
+ else
+ # For some reason systemctl is not install but our service file exists
+ # Just delete the symlink then
+ rm -f "$systemd_service_file"
+ fi
+ fi
+ }
+
+ _pp_systemd_remove () {
+ local svc="$1"
+
+ # If $systemctl_cmd is not set, then call _pp_systemd_init.
+ # If still not set, we do not know where the systemctl command
+ # is so do nothing; systemd must not be on this system.
+ if test -z "$systemctl_cmd"; then
+ _pp_systemd_init
+ fi
+
+ $systemctl_cmd stop $svc.service > /dev/null 2>&1
+
+ # Remove the systemd unit service file
+ if [ "x$systemd_service_dir" != "x$systemd_system_unit_dir" ]; then
+ rm -f "$systemd_system_unit_dir/$svc.service"
+ fi
+
+ if test -x "$systemctl_cmd"; then
+ $systemctl_cmd daemon-reload
+ $systemctl_cmd reset-failed $svc.service >/dev/null 2>&1 || true
+ fi
+ }
+.
+}
+
+
+quest_require_vas () {
+ typeset v d
+
+ if test $# -ne 1; then
+ return
+ fi
+ set -- `echo "$1" | tr . ' '` 0 0 0
+
+ for d
+ do
+ echo $d | grep '^[0-9][0-9]*$' > /dev/null ||
+ pp_error "quest_require_vas: Bad version component $d"
+ done
+
+ test $# -lt 4 &&
+ pp_error "quest_require_vas: missing version number"
+
+ case "$1.$2.$3.$4" in
+ *.0.0.0) v=$1;;
+ *.*.0.0) v=$1.$2;;
+ *.*.*.0) v=$1.$2.$3;;
+ *) v=$1.$2.$3.$4;;
+ esac
+
+ cat <<.
+ if test -x /opt/quest/bin/vastool &&
+ /opt/quest/bin/vastool -v |
+ awk 'NR == 1 {print \$4}' |
+ awk -F. '{ if (\$1<$1 || \$1==$1 && ( \
+ \$2<$2 || \$2==$2 && ( \
+ \$3<$3 || \$2==$3 && ( \
+ \$4<$4 )))) exit(1); }'
+ then
+ exit 0
+ else
+ echo "Requires VAS $v or later"
+ exit 1
+ fi
+.
+}
+pp_main ${1+"$@"}
diff --git a/scripts/unanon b/scripts/unanon
new file mode 100755
index 0000000..2bbb3c8
--- /dev/null
+++ b/scripts/unanon
@@ -0,0 +1,50 @@
+#!/usr/bin/env perl
+#
+# Post-process files generated by protoc-c to remove anonymous unions.
+# Works on the generated files but probably little else.
+
+use warnings;
+use strict;
+
+sub unanon {
+ my $hfile = shift;
+ my $cfile = shift;
+ my ($fh, $content);
+ my %members;
+
+ open $fh, "<", $hfile or die $!;
+ local $/; # enable localized slurp mode
+ $content = <$fh>;
+ close $fh;
+
+ # Detect and replace anonymous unions in .h file.
+ # Assumes there is only one anonymous union in scope.
+ while ($content =~ s/^(struct\s+(\w+)[^}]+)(union\s+{([^}]+)}\s*);/$1$3 u;/sm) {
+ my $s = $2;
+ my $u = $4;
+ $u =~ s:/\*((?!\*/).)*\*/::sg;
+ foreach (split(/\n+/, $u)) {
+ if (/^.*\s+\**([^;]+);/) {
+ $members{$1} = $s;
+ }
+ }
+ }
+ open $fh, ">", $hfile or die $!;
+ print $fh $content;
+ close $fh;
+
+ # Replace anonymous union access in generated .c file.
+ open $fh, "<", $cfile or die $!;
+ $content = <$fh>;
+ close $fh;
+
+ while (my ($key, $val) = each %members) {
+ # We only support access via offsetof()
+ $content =~ s/offsetof\($val, $key\)/offsetof($val, u.$key)/g;
+ }
+ open $fh, ">", $cfile or die $!;
+ print $fh $content;
+ close $fh;
+}
+
+unanon(@ARGV);
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..e2ff919
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,1099 @@
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2010-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+# @configure_input@
+#
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+abs_srcdir = @abs_srcdir@
+top_srcdir = @top_srcdir@
+abs_top_srcdir = @abs_top_srcdir@
+top_builddir = @top_builddir@
+abs_top_builddir = @abs_top_builddir@
+devdir = @devdir@
+scriptdir = $(top_srcdir)/scripts
+incdir = $(top_srcdir)/include
+rundir = @rundir@
+cross_compiling = @CROSS_COMPILING@
+
+# Compiler & tools to use
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+EGREP = @EGREP@
+SED = @SED@
+AWK = @AWK@
+
+# Our install program supports extra flags...
+INSTALL = $(SHELL) $(scriptdir)/install-sh -c
+INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
+INSTALL_BACKUP = @INSTALL_BACKUP@
+
+# Libraries
+LIBPROTOBUF_C = $(top_builddir)/lib/protobuf-c/libprotobuf-c.la
+LIBUTIL = $(top_builddir)/lib/util/libsudo_util.la
+LT_LIBS = $(LIBUTIL) $(LIBPROTOBUF_C)
+LIBS = @LIBS@ @SUDO_LIBS@ @GETGROUPS_LIB@ @NET_LIBS@ $(LT_LIBS)
+
+# C preprocessor defines
+CPPDEFS = -D_PATH_SUDO_CONF=\"@sudo_conf@\" \
+ -DLOCALEDIR=\"$(localedir)\"
+
+# C preprocessor flags
+CPPFLAGS = -I$(incdir) -I$(top_builddir) -I. -I$(srcdir) $(CPPDEFS) @CPPFLAGS@
+
+# Usually -O and/or -g
+CFLAGS = @CFLAGS@
+
+# Flags to pass to the link stage
+LDFLAGS = @LDFLAGS@
+SUDO_LDFLAGS = $(LDFLAGS) @SUDO_LDFLAGS@
+INTERCEPT_LDFLAGS = @LT_LDFLAGS@ @LT_LDEXPORTS@
+NOEXEC_LDFLAGS = @LT_LDFLAGS@
+
+# Flags to pass to libtool
+LTFLAGS = --tag=disable-static
+
+# Flag to build sudo_module.so and sudo_noexec.so as modules instead of
+# shared libs (except on macOS)
+PRELOAD_MODULE = @PRELOAD_MODULE@
+
+# Address sanitizer flags
+ASAN_CFLAGS = @ASAN_CFLAGS@
+ASAN_LDFLAGS = @ASAN_LDFLAGS@
+
+# PIE flags
+PIE_CFLAGS = @PIE_CFLAGS@
+PIE_LDFLAGS = @PIE_LDFLAGS@
+
+# Stack smashing protection flags
+HARDENING_CFLAGS = @HARDENING_CFLAGS@
+HARDENING_LDFLAGS = @HARDENING_LDFLAGS@
+
+# cppcheck options, usually set in the top-level Makefile
+CPPCHECK_OPTS = -q --enable=warning,performance,portability --suppress=constStatement --suppress=compareBoolExpressionWithInt --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
+
+# splint options, usually set in the top-level Makefile
+SPLINT_OPTS = -D__restrict= -checks
+
+# PVS-studio options
+PVS_CFG = $(top_srcdir)/PVS-Studio.cfg
+PVS_IGNORE = 'V707,V011,V002,V536'
+PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
+
+# Where to install things...
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+sysconfdir = @sysconfdir@
+adminconfdir = @adminconfdir@
+libexecdir = @libexecdir@
+datarootdir = @datarootdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+interceptfile = @INTERCEPTFILE@
+interceptdir = @INTERCEPTDIR@
+noexecfile = @NOEXECFILE@
+noexecdir = @NOEXECDIR@
+tmpfiles_d = @TMPFILES_D@
+
+# User and group ids the installed files should be "owned" by
+install_uid = 0
+install_gid = 0
+
+# File extension, mode and map file to use for shared libraries/objects
+shlib_enable = @SHLIB_ENABLE@
+shlib_mode = @SHLIB_MODE@
+shlib_exp = ./intercept.exp
+shlib_map = intercept.map
+shlib_opt = intercept.opt
+
+# Optional init script and rc.d link
+INIT_DIR=@INIT_DIR@
+INIT_SCRIPT=@INIT_SCRIPT@
+RC_LINK=@RC_LINK@
+
+TEST_PROGS = check_net_ifs check_noexec check_ttyname
+TEST_LIBS = @LIBS@ $(LT_LIBS)
+TEST_LDFLAGS = @LDFLAGS@
+TEST_VERBOSE =
+
+# Set to non-empty for development mode
+DEVEL = @DEVEL@
+
+#### End of system configuration section. ####
+
+SHELL = @SHELL@
+
+PROGS = @PROGS@
+
+OBJS = conversation.o copy_file.o edit_open.o env_hooks.o exec.o \
+ exec_common.o exec_intercept.o exec_iolog.o exec_monitor.o \
+ exec_nopty.o exec_preload.o exec_ptrace.o exec_pty.o get_pty.o \
+ hooks.o limits.o load_plugins.o net_ifs.o parse_args.o preserve_fds.o \
+ signal.o sudo.o sudo_edit.o suspend_parent.o tgetpass.o ttyname.o \
+ utmp.o @SUDO_OBJS@
+
+IOBJS = $(OBJS:.o=.i) sesh.i sudo_intercept.i sudo_intercept_common.i
+
+POBJS = $(IOBJS:.i=.plog)
+
+SESH_OBJS = copy_file.o edit_open.o exec_common.o exec_preload.o sesh.o
+
+INTERCEPT_OBJS = exec_preload.lo sudo_intercept.lo sudo_intercept_common.lo \
+ intercept.pb-c.lo
+
+CHECK_NET_IFS_OBJS = check_net_ifs.o net_ifs.o
+
+CHECK_NOEXEC_OBJS = check_noexec.o exec_common.o exec_preload.o
+
+CHECK_TTYNAME_OBJS = check_ttyname.o ttyname.o
+
+TEST_PTRACE_OBJS = suspend_parent.o test_ptrace.o
+
+LIBOBJDIR = $(top_builddir)/@ac_config_libobj_dir@/
+
+VERSION = @PACKAGE_VERSION@
+
+GENERATED = intercept.pb-c.h intercept.pb-c.c
+
+all: $(PROGS)
+
+depend:
+ $(scriptdir)/mkdep.pl --srcdir=$(abs_top_srcdir) \
+ --builddir=$(abs_top_builddir) src/Makefile.in
+ cd $(top_builddir) && ./config.status --file src/Makefile
+
+Makefile: $(srcdir)/Makefile.in
+ cd $(top_builddir) && ./config.status --file src/Makefile
+
+./sudo_usage.h: $(srcdir)/sudo_usage.h.in
+ cd $(top_builddir) && ./config.status --file src/sudo_usage.h
+
+.SUFFIXES: .c .h .i .lo .o .plog
+
+.c.o:
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.lo:
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $<
+
+.c.i:
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+
+.i.plog:
+ ifile=$<; rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $${ifile%i}c --i-file $< --output-file $@
+
+$(devdir)/intercept.pb-c.c: $(srcdir)/intercept.proto
+ @if [ -n "$(DEVEL)" ]; then \
+ cmd='protoc-c --c_out=$(devdir) --proto_path=$(srcdir) $(srcdir)/intercept.proto'; \
+ echo "$$cmd"; eval $$cmd; \
+ cmd='$(scriptdir)/unanon $(devdir)/intercept.pb-c.h $(devdir)/intercept.pb-c.c'; \
+ echo "$$cmd"; eval $$cmd; \
+ if [ "$(devdir)" == "$(srcdir)" ]; then \
+ cmd='mv -f $(devdir)/intercept.pb-c.h $(incdir)/intercept.pb-c.h'; \
+ else \
+ cmd='mv -f $(devdir)/intercept.pb-c.h $(top_builddir)/intercept.pb-c.h'; \
+ fi; \
+ echo "$$cmd"; eval $$cmd; \
+ fi
+
+sudo: $(OBJS) $(LT_LIBS) @STATIC_SUDOERS@
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(OBJS) $(SUDO_LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS) @STATIC_SUDOERS@
+
+$(shlib_map): $(shlib_exp)
+ @$(AWK) 'BEGIN { print "{\n\tglobal:" } { print "\t\t"$$0";" } END { print "\tlocal:\n\t\t*;\n};" }' $(shlib_exp) > $@
+
+$(shlib_opt): $(shlib_exp)
+ @$(SED) 's/^/+e /' $(shlib_exp) > $@
+
+sudo_intercept.la: $(INTERCEPT_OBJS) @LT_LDDEP@
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) $(INTERCEPT_LDFLAGS) $(ASAN_LDFLAGS) $(HARDENING_LDFLAGS) $(LT_LIBS) @LIBDL@ -o $@ $(INTERCEPT_OBJS) $(PRELOAD_MODULE) -avoid-version -rpath $(interceptdir) -shrext .so
+
+sudo_noexec.la: sudo_noexec.lo
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) $(NOEXEC_LDFLAGS) $(HARDENING_LDFLAGS) @LIBDL@ -o $@ sudo_noexec.lo $(PRELOAD_MODULE) -avoid-version -rpath $(noexecdir) -shrext .so
+
+sesh: $(SESH_OBJS) $(LT_LIBS)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(SESH_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(LIBS)
+
+check_net_ifs: $(CHECK_NET_IFS_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_NET_IFS_OBJS) $(TEST_LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LIBS)
+
+check_noexec: $(CHECK_NOEXEC_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_NOEXEC_OBJS) $(TEST_LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LIBS)
+
+check_ttyname: $(CHECK_TTYNAME_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_TTYNAME_OBJS) $(TEST_LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LIBS)
+
+test_ptrace: $(TEST_PTRACE_OBJS) $(LIBUTIL)
+ $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(TEST_PTRACE_OBJS) $(TEST_LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(HARDENING_LDFLAGS) $(TEST_LIBS)
+
+pre-install:
+
+install: install-binaries install-rc @INSTALL_INTERCEPT@ @INSTALL_NOEXEC@
+
+install-dirs:
+ # We only create the rc.d dir when installing to the actual system dir
+ $(SHELL) $(scriptdir)/mkinstalldirs $(DESTDIR)$(bindir) \
+ $(DESTDIR)$(libexecdir)/sudo $(DESTDIR)$(noexecdir) \
+ $(DESTDIR)$(interceptdir)
+ if test -n "$(INIT_SCRIPT)"; then \
+ $(SHELL) $(scriptdir)/mkinstalldirs $(DESTDIR)$(INIT_DIR); \
+ if test -z "$(DESTDIR)"; then \
+ $(SHELL) $(scriptdir)/mkinstalldirs \
+ `echo $(RC_LINK) | $(SED) 's,/[^/]*$$,,'`; \
+ fi; \
+ elif test -n "$(tmpfiles_d)"; then \
+ $(SHELL) $(scriptdir)/mkinstalldirs $(DESTDIR)$(tmpfiles_d); \
+ fi
+
+install-rc: install-dirs
+ # We only create the rc.d link when installing to the actual system dir
+ if [ -n "$(INIT_SCRIPT)" ]; then \
+ $(INSTALL) $(INSTALL_OWNER) -m 0755 $(top_builddir)/etc/init.d/$(INIT_SCRIPT) $(DESTDIR)$(INIT_DIR)/sudo; \
+ if test -z "$(DESTDIR)"; then \
+ rm -f $(RC_LINK); \
+ ln -s $(INIT_DIR)/sudo $(RC_LINK); \
+ fi; \
+ elif test -n "$(tmpfiles_d)"; then \
+ $(INSTALL) $(INSTALL_OWNER) -m 0644 $(top_builddir)/etc/init.d/sudo.conf $(DESTDIR)$(tmpfiles_d)/sudo.conf; \
+ fi
+
+install-binaries: install-dirs $(PROGS)
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) $(INSTALL_OWNER) -m 04755 sudo $(DESTDIR)$(bindir)/sudo
+ rm -f $(DESTDIR)$(bindir)/sudoedit
+ ln -s sudo $(DESTDIR)$(bindir)/sudoedit
+ if [ -f sesh ]; then \
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) $(INSTALL_OWNER) -m 0755 sesh $(DESTDIR)$(libexecdir)/sudo/sesh; \
+ fi
+
+install-doc:
+
+install-includes:
+
+install-intercept: install-dirs sudo_intercept.la
+ if [ X"$(shlib_enable)" = X"yes" ]; then \
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) $(INSTALL_OWNER) -m $(shlib_mode) sudo_intercept.la $(DESTDIR)$(interceptdir); \
+ fi
+
+install-noexec: install-dirs sudo_noexec.la
+ if [ X"$(shlib_enable)" = X"yes" ]; then \
+ INSTALL_BACKUP='$(INSTALL_BACKUP)' $(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) $(INSTALL_OWNER) -m $(shlib_mode) sudo_noexec.la $(DESTDIR)$(noexecdir); \
+ fi
+
+install-plugin:
+
+install-fuzzer:
+
+uninstall:
+ -$(LIBTOOL) $(LTFLAGS) --mode=uninstall \
+ rm -f $(DESTDIR)$(interceptdir)/sudo_intercept.la \
+ $(DESTDIR)$(noexecdir)/sudo_noexec.la
+ -rm -f $(DESTDIR)$(bindir)/sudo \
+ $(DESTDIR)$(bindir)/sudoedit \
+ $(DESTDIR)$(libexecdir)/sudo/sesh \
+ $(DESTDIR)/usr/lib/tmpfiles.d/sudo.conf
+ -test -z "$(INSTALL_BACKUP)" || \
+ rm -f $(DESTDIR)$(bindir)/sudo$(INSTALL_BACKUP) \
+ $(DESTDIR)$(libexecdir)/sudo/sesh$(INSTALL_BACKUP) \
+ $(DESTDIR)$(interceptdir)/sudo_intercept.so$(INSTALL_BACKUP) \
+ $(DESTDIR)$(noexecdir)/sudo_noexec.so$(INSTALL_BACKUP)
+ -test -z "$(INIT_SCRIPT)" || \
+ rm -f $(DESTDIR)$(RC_LINK) $(DESTDIR)$(INIT_DIR)/sudo
+
+splint:
+ splint $(SPLINT_OPTS) -I$(incdir) -I$(top_builddir) -I. -I$(srcdir) $(srcdir)/*.c
+
+cppcheck:
+ cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) -I. -I$(srcdir) $(srcdir)/*.c
+
+pvs-log-files: $(POBJS)
+
+pvs-studio: $(POBJS)
+ plog-converter $(PVS_LOG_OPTS) $(POBJS)
+
+fuzz:
+
+check-fuzzer:
+
+check: $(TEST_PROGS) check-fuzzer
+ @if test X"$(cross_compiling)" != X"yes"; then \
+ l=`locale -a 2>&1 | $(EGREP) -i '^C\.UTF-?8$$' | $(SED) 1q` || true; \
+ test -n "$$l" || l="C"; \
+ LC_ALL="$$l"; export LC_ALL; \
+ unset LANG || LANG=; \
+ unset LANGUAGE || LANGUAGE=; \
+ MALLOC_OPTIONS=S; export MALLOC_OPTIONS; \
+ MALLOC_CONF="abort:true,junk:true"; export MALLOC_CONF; \
+ ./check_net_ifs $(TEST_VERBOSE); \
+ if [ -f .libs/$(noexecfile) ]; then \
+ ./check_noexec $(TEST_VERBOSE) .libs/$(noexecfile); \
+ fi; \
+ ./check_ttyname $(TEST_VERBOSE); \
+ fi
+
+check-verbose:
+ exec $(MAKE) $(MFLAGS) TEST_VERBOSE=-v FUZZ_VERBOSE=-verbosity=1 check
+
+clean:
+ -$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f $(PROGS) $(TEST_PROGS) \
+ *.lo *.o *.la
+ -rm -f *.i *.plog stamp-* core *.core core.*
+
+mostlyclean: clean
+
+distclean: clean
+ -rm -rf Makefile intercept.exp sudo_usage.h \
+ .libs $(shlib_map) $(shlib_opt)
+ @if [ -n "$(DEVEL)" -a "$(devdir)" != "$(srcdir)" ]; then \
+ cmd='rm -rf $(GENERATED)'; \
+ echo "$$cmd"; eval $$cmd; \
+ fi
+
+clobber: distclean
+
+realclean: distclean
+ rm -f TAGS tags
+
+cleandir: realclean
+
+.PHONY: clean mostlyclean distclean cleandir clobber realclean
+
+# *Not* auto-generated to avoid building with ASAN
+sudo_noexec.lo: $(srcdir)/sudo_noexec.c $(incdir)/sudo_compat.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudo_noexec.c
+
+# Autogenerated dependencies, do not modify
+apparmor.o: $(srcdir)/apparmor.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/apparmor.c
+apparmor.i: $(srcdir)/apparmor.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+apparmor.plog: apparmor.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/apparmor.c --i-file $< --output-file $@
+check_net_ifs.o: $(srcdir)/regress/net_ifs/check_net_ifs.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/net_ifs/check_net_ifs.c
+check_net_ifs.i: $(srcdir)/regress/net_ifs/check_net_ifs.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_net_ifs.plog: check_net_ifs.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/net_ifs/check_net_ifs.c --i-file $< --output-file $@
+check_noexec.o: $(srcdir)/regress/noexec/check_noexec.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/sudo_exec.h $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/noexec/check_noexec.c
+check_noexec.i: $(srcdir)/regress/noexec/check_noexec.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/sudo_exec.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_noexec.plog: check_noexec.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/noexec/check_noexec.c --i-file $< --output-file $@
+check_ttyname.o: $(srcdir)/regress/ttyname/check_ttyname.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/ttyname/check_ttyname.c
+check_ttyname.i: $(srcdir)/regress/ttyname/check_ttyname.c \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+check_ttyname.plog: check_ttyname.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/ttyname/check_ttyname.c --i-file $< --output-file $@
+conversation.o: $(srcdir)/conversation.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h \
+ $(srcdir)/sudo_plugin_int.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/conversation.c
+conversation.i: $(srcdir)/conversation.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h \
+ $(srcdir)/sudo_plugin_int.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+conversation.plog: conversation.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/conversation.c --i-file $< --output-file $@
+copy_file.o: $(srcdir)/copy_file.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_edit.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/copy_file.c
+copy_file.i: $(srcdir)/copy_file.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_edit.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+copy_file.plog: copy_file.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/copy_file.c --i-file $< --output-file $@
+edit_open.o: $(srcdir)/edit_open.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_edit.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/edit_open.c
+edit_open.i: $(srcdir)/edit_open.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_edit.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+edit_open.plog: edit_open.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/edit_open.c --i-file $< --output-file $@
+env_hooks.o: $(srcdir)/env_hooks.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_dso.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/sudo.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/env_hooks.c
+env_hooks.i: $(srcdir)/env_hooks.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_dso.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/sudo.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+env_hooks.plog: env_hooks.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/env_hooks.c --i-file $< --output-file $@
+exec.o: $(srcdir)/exec.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/sudo.h $(srcdir)/sudo_exec.h $(srcdir)/sudo_plugin_int.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/exec.c
+exec.i: $(srcdir)/exec.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/sudo.h $(srcdir)/sudo_exec.h $(srcdir)/sudo_plugin_int.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+exec.plog: exec.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/exec.c --i-file $< --output-file $@
+exec_common.o: $(srcdir)/exec_common.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/exec_common.c
+exec_common.i: $(srcdir)/exec_common.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+exec_common.plog: exec_common.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/exec_common.c --i-file $< --output-file $@
+exec_intercept.o: $(srcdir)/exec_intercept.c $(incdir)/compat/stdbool.h \
+ $(incdir)/intercept.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_rand.h $(incdir)/sudo_util.h \
+ $(srcdir)/exec_intercept.h $(srcdir)/sudo.h \
+ $(srcdir)/sudo_exec.h $(srcdir)/sudo_plugin_int.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/exec_intercept.c
+exec_intercept.i: $(srcdir)/exec_intercept.c $(incdir)/compat/stdbool.h \
+ $(incdir)/intercept.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_rand.h $(incdir)/sudo_util.h \
+ $(srcdir)/exec_intercept.h $(srcdir)/sudo.h \
+ $(srcdir)/sudo_exec.h $(srcdir)/sudo_plugin_int.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+exec_intercept.plog: exec_intercept.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/exec_intercept.c --i-file $< --output-file $@
+exec_iolog.o: $(srcdir)/exec_iolog.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
+ $(srcdir)/sudo_plugin_int.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/exec_iolog.c
+exec_iolog.i: $(srcdir)/exec_iolog.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
+ $(srcdir)/sudo_plugin_int.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+exec_iolog.plog: exec_iolog.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/exec_iolog.c --i-file $< --output-file $@
+exec_monitor.o: $(srcdir)/exec_monitor.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
+ $(srcdir)/sudo_plugin_int.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/exec_monitor.c
+exec_monitor.i: $(srcdir)/exec_monitor.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
+ $(srcdir)/sudo_plugin_int.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+exec_monitor.plog: exec_monitor.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/exec_monitor.c --i-file $< --output-file $@
+exec_nopty.o: $(srcdir)/exec_nopty.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
+ $(srcdir)/sudo_plugin_int.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/exec_nopty.c
+exec_nopty.i: $(srcdir)/exec_nopty.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
+ $(srcdir)/sudo_plugin_int.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+exec_nopty.plog: exec_nopty.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/exec_nopty.c --i-file $< --output-file $@
+exec_preload.lo: $(srcdir)/exec_preload.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/exec_preload.c
+exec_preload.i: $(srcdir)/exec_preload.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+exec_preload.plog: exec_preload.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/exec_preload.c --i-file $< --output-file $@
+exec_preload.o: $(srcdir)/exec_preload.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/exec_preload.c
+exec_ptrace.o: $(srcdir)/exec_ptrace.c $(incdir)/compat/endian.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/exec_intercept.h $(srcdir)/exec_ptrace.h \
+ $(srcdir)/sudo.h $(srcdir)/sudo_exec.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/exec_ptrace.c
+exec_ptrace.i: $(srcdir)/exec_ptrace.c $(incdir)/compat/endian.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/exec_intercept.h $(srcdir)/exec_ptrace.h \
+ $(srcdir)/sudo.h $(srcdir)/sudo_exec.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+exec_ptrace.plog: exec_ptrace.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/exec_ptrace.c --i-file $< --output-file $@
+exec_pty.o: $(srcdir)/exec_pty.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
+ $(srcdir)/sudo_plugin_int.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/exec_pty.c
+exec_pty.i: $(srcdir)/exec_pty.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
+ $(srcdir)/sudo_plugin_int.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+exec_pty.plog: exec_pty.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/exec_pty.c --i-file $< --output-file $@
+get_pty.o: $(srcdir)/get_pty.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/get_pty.c
+get_pty.i: $(srcdir)/get_pty.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+get_pty.plog: get_pty.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/get_pty.c --i-file $< --output-file $@
+hooks.o: $(srcdir)/hooks.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/sudo.h $(srcdir)/sudo_plugin_int.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/hooks.c
+hooks.i: $(srcdir)/hooks.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/sudo.h $(srcdir)/sudo_plugin_int.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+hooks.plog: hooks.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/hooks.c --i-file $< --output-file $@
+intercept.pb-c.lo: $(srcdir)/intercept.pb-c.c $(incdir)/intercept.pb-c.h \
+ $(incdir)/protobuf-c/protobuf-c.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/intercept.pb-c.c
+intercept.pb-c.plog: $(srcdir)/intercept.pb-c.c
+ touch $@
+intercept.pb-c.o: $(srcdir)/intercept.pb-c.c $(incdir)/intercept.pb-c.h \
+ $(incdir)/protobuf-c/protobuf-c.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/intercept.pb-c.c
+limits.o: $(srcdir)/limits.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/sudo.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/limits.c
+limits.i: $(srcdir)/limits.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/sudo.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+limits.plog: limits.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/limits.c --i-file $< --output-file $@
+load_plugins.o: $(srcdir)/load_plugins.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_dso.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/sudo.h \
+ $(srcdir)/sudo_plugin_int.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/load_plugins.c
+load_plugins.i: $(srcdir)/load_plugins.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_dso.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/sudo.h \
+ $(srcdir)/sudo_plugin_int.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+load_plugins.plog: load_plugins.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/load_plugins.c --i-file $< --output-file $@
+net_ifs.o: $(srcdir)/net_ifs.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/net_ifs.c
+net_ifs.i: $(srcdir)/net_ifs.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+net_ifs.plog: net_ifs.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/net_ifs.c --i-file $< --output-file $@
+openbsd.o: $(srcdir)/openbsd.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/openbsd.c
+openbsd.i: $(srcdir)/openbsd.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+openbsd.plog: openbsd.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/openbsd.c --i-file $< --output-file $@
+parse_args.o: $(srcdir)/parse_args.c $(incdir)/compat/getopt.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h ./sudo_usage.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/parse_args.c
+parse_args.i: $(srcdir)/parse_args.c $(incdir)/compat/getopt.h \
+ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_lbuf.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h ./sudo_usage.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+parse_args.plog: parse_args.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/parse_args.c --i-file $< --output-file $@
+preload.o: $(srcdir)/preload.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_dso.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/preload.c
+preload.i: $(srcdir)/preload.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_dso.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+preload.plog: preload.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/preload.c --i-file $< --output-file $@
+preserve_fds.o: $(srcdir)/preserve_fds.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/preserve_fds.c
+preserve_fds.i: $(srcdir)/preserve_fds.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+preserve_fds.plog: preserve_fds.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/preserve_fds.c --i-file $< --output-file $@
+selinux.o: $(srcdir)/selinux.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/selinux.c
+selinux.i: $(srcdir)/selinux.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+selinux.plog: selinux.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/selinux.c --i-file $< --output-file $@
+sesh.o: $(srcdir)/sesh.c $(incdir)/compat/getopt.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/sudo.h $(srcdir)/sudo_edit.h $(srcdir)/sudo_exec.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sesh.c
+sesh.i: $(srcdir)/sesh.c $(incdir)/compat/getopt.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/sudo.h $(srcdir)/sudo_edit.h $(srcdir)/sudo_exec.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sesh.plog: sesh.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sesh.c --i-file $< --output-file $@
+signal.o: $(srcdir)/signal.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/sudo.h \
+ $(srcdir)/sudo_exec.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/signal.c
+signal.i: $(srcdir)/signal.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/sudo.h \
+ $(srcdir)/sudo_exec.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+signal.plog: signal.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/signal.c --i-file $< --output-file $@
+solaris.o: $(srcdir)/solaris.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_dso.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/solaris.c
+solaris.i: $(srcdir)/solaris.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_dso.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+solaris.plog: solaris.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/solaris.c --i-file $< --output-file $@
+sudo.o: $(srcdir)/sudo.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/sudo.h $(srcdir)/sudo_plugin_int.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudo.c
+sudo.i: $(srcdir)/sudo.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/sudo.h $(srcdir)/sudo_plugin_int.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudo.plog: sudo.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo.c --i-file $< --output-file $@
+sudo_edit.o: $(srcdir)/sudo_edit.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_edit.h \
+ $(srcdir)/sudo_exec.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudo_edit.c
+sudo_edit.i: $(srcdir)/sudo_edit.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_edit.h \
+ $(srcdir)/sudo_exec.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudo_edit.plog: sudo_edit.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_edit.c --i-file $< --output-file $@
+sudo_intercept.lo: $(srcdir)/sudo_intercept.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudo_intercept.c
+sudo_intercept.i: $(srcdir)/sudo_intercept.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudo_intercept.plog: sudo_intercept.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_intercept.c --i-file $< --output-file $@
+sudo_intercept_common.lo: $(srcdir)/sudo_intercept_common.c \
+ $(incdir)/compat/stdbool.h \
+ $(incdir)/intercept.pb-c.h \
+ $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/sudo_exec.h $(top_builddir)/config.h
+ $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudo_intercept_common.c
+sudo_intercept_common.i: $(srcdir)/sudo_intercept_common.c \
+ $(incdir)/compat/stdbool.h \
+ $(incdir)/intercept.pb-c.h \
+ $(incdir)/protobuf-c/protobuf-c.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/sudo_exec.h $(top_builddir)/config.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+sudo_intercept_common.plog: sudo_intercept_common.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_intercept_common.c --i-file $< --output-file $@
+suspend_parent.o: $(srcdir)/suspend_parent.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/sudo_exec.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/suspend_parent.c
+suspend_parent.i: $(srcdir)/suspend_parent.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
+ $(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
+ $(incdir)/sudo_queue.h $(srcdir)/sudo_exec.h \
+ $(top_builddir)/config.h $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+suspend_parent.plog: suspend_parent.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/suspend_parent.c --i-file $< --output-file $@
+test_ptrace.o: $(srcdir)/regress/intercept/test_ptrace.c \
+ $(incdir)/compat/endian.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/exec_intercept.h \
+ $(srcdir)/exec_ptrace.c $(srcdir)/exec_ptrace.h \
+ $(srcdir)/sudo.h $(srcdir)/sudo_exec.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/regress/intercept/test_ptrace.c
+test_ptrace.i: $(srcdir)/regress/intercept/test_ptrace.c \
+ $(incdir)/compat/endian.h $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/exec_intercept.h \
+ $(srcdir)/exec_ptrace.c $(srcdir)/exec_ptrace.h \
+ $(srcdir)/sudo.h $(srcdir)/sudo_exec.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+test_ptrace.plog: test_ptrace.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/intercept/test_ptrace.c --i-file $< --output-file $@
+tgetpass.o: $(srcdir)/tgetpass.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/tgetpass.c
+tgetpass.i: $(srcdir)/tgetpass.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+tgetpass.plog: tgetpass.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/tgetpass.c --i-file $< --output-file $@
+ttyname.o: $(srcdir)/ttyname.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/ttyname.c
+ttyname.i: $(srcdir)/ttyname.c $(incdir)/compat/stdbool.h \
+ $(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
+ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
+ $(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+ttyname.plog: ttyname.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/ttyname.c --i-file $< --output-file $@
+utmp.o: $(srcdir)/utmp.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/sudo.h $(srcdir)/sudo_exec.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/utmp.c
+utmp.i: $(srcdir)/utmp.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
+ $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
+ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
+ $(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
+ $(srcdir)/sudo.h $(srcdir)/sudo_exec.h $(top_builddir)/config.h \
+ $(top_builddir)/pathnames.h
+ $(CC) -E -o $@ $(CPPFLAGS) $<
+utmp.plog: utmp.i
+ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/utmp.c --i-file $< --output-file $@
diff --git a/src/apparmor.c b/src/apparmor.c
new file mode 100644
index 0000000..8ec7a85
--- /dev/null
+++ b/src/apparmor.c
@@ -0,0 +1,118 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2022 Will Shand <wss2ec@virginia.edu>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_APPARMOR
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <sys/apparmor.h>
+
+# include <sudo.h>
+# include <sudo_debug.h>
+
+/**
+ * @brief Check whether AppArmor is enabled.
+ *
+ * @return 1 if AppArmor is enabled, 0 otherwise.
+ */
+int
+apparmor_is_enabled(void)
+{
+ int ret;
+ FILE *fd;
+ debug_decl(apparmor_is_enabled, SUDO_DEBUG_APPARMOR);
+
+ /*
+ * Check whether AppArmor is enabled by reading
+ * /sys/module/apparmor/parameters/enabled
+ *
+ * When this file exists and its contents are equal to "Y", AppArmor
+ * is enabled. This is a little more reliable than using
+ * aa_is_enabled(2), which performs an additional check on securityfs
+ * that will fail in settings where securityfs isn't available
+ * (e.g. inside a container).
+ */
+
+ fd = fopen("/sys/module/apparmor/parameters/enabled", "r");
+ if (fd == NULL)
+ debug_return_int(0);
+
+ ret = (fgetc(fd) == 'Y');
+
+ fclose(fd);
+ debug_return_int(ret);
+}
+
+/**
+ * @brief Prepare to transition into a new AppArmor profile.
+ *
+ * @param new_profile The AppArmor profile to transition into on the
+ * next exec.
+ *
+ * @return 0 on success, and a nonzero value on failure.
+ */
+int
+apparmor_prepare(const char *new_profile)
+{
+ int ret;
+ char *mode, *old_profile;
+ debug_decl(apparmor_prepare, SUDO_DEBUG_APPARMOR);
+
+ /* Determine the current AppArmor confinement status */
+ if ((ret = aa_getcon(&old_profile, &mode)) == -1) {
+ sudo_warn("%s", U_("failed to determine AppArmor confinement"));
+ old_profile = NULL;
+ goto done;
+ }
+
+ /* Tell AppArmor to transition into the new profile on the
+ * next exec */
+ if ((ret = aa_change_onexec(new_profile)) != 0) {
+ sudo_warn(U_("unable to change AppArmor profile to %s"), new_profile);
+ goto done;
+ }
+
+ if (mode == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: changing AppArmor profile: %s -> %s", __func__,
+ old_profile, new_profile ? new_profile : "?");
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: changing AppArmor profile: %s (%s) -> %s", __func__,
+ old_profile, mode, new_profile ? new_profile : "?");
+ }
+
+done:
+ /*
+ * The profile string returned by aa_getcon must be free'd, while the
+ * mode string must _not_ be free'd.
+ */
+ if (old_profile != NULL)
+ free(old_profile);
+
+ debug_return_int(ret);
+}
+
+#endif /* HAVE_APPARMOR */
diff --git a/src/conversation.c b/src/conversation.c
new file mode 100644
index 0000000..ea2469f
--- /dev/null
+++ b/src/conversation.c
@@ -0,0 +1,239 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999-2005, 2007-2012 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sudo.h>
+#include <sudo_plugin.h>
+#include <sudo_plugin_int.h>
+
+/*
+ * Sudo conversation function.
+ */
+int
+sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
+{
+ const int conv_debug_instance = sudo_debug_get_active_instance();
+ char *pass;
+ int n;
+
+ sudo_debug_set_active_instance(sudo_debug_instance);
+
+ for (n = 0; n < num_msgs; n++) {
+ const struct sudo_conv_message *msg = &msgs[n];
+ unsigned int flags = tgetpass_flags;
+ FILE *fp = stdout;
+
+ if (replies != NULL)
+ replies[n].reply = NULL;
+
+ switch (msg->msg_type & 0xff) {
+ case SUDO_CONV_PROMPT_ECHO_ON:
+ SET(flags, TGP_ECHO);
+ goto read_pass;
+ case SUDO_CONV_PROMPT_MASK:
+ SET(flags, TGP_MASK);
+ FALLTHROUGH;
+ case SUDO_CONV_PROMPT_ECHO_OFF:
+ if (ISSET(msg->msg_type, SUDO_CONV_PROMPT_ECHO_OK))
+ SET(flags, TGP_NOECHO_TRY);
+ read_pass:
+ /* Read the password unless interrupted. */
+ if (replies == NULL)
+ goto err;
+ pass = tgetpass(msg->msg, msg->timeout, flags, callback);
+ if (pass == NULL)
+ goto err;
+ replies[n].reply = strdup(pass);
+ if (replies[n].reply == NULL) {
+ sudo_fatalx_nodebug(U_("%s: %s"), "sudo_conversation",
+ U_("unable to allocate memory"));
+ }
+ explicit_bzero(pass, strlen(pass));
+ break;
+ case SUDO_CONV_ERROR_MSG:
+ fp = stderr;
+ FALLTHROUGH;
+ case SUDO_CONV_INFO_MSG:
+ if (msg->msg != NULL) {
+ size_t len = strlen(msg->msg);
+ const char *crnl = NULL;
+ bool written = false;
+ int ttyfd = -1;
+ bool raw_tty = false;
+
+ if (ISSET(msg->msg_type, SUDO_CONV_PREFER_TTY) &&
+ !ISSET(flags, TGP_STDIN)) {
+ ttyfd = open(_PATH_TTY, O_WRONLY);
+ if (ttyfd != -1)
+ raw_tty = sudo_term_is_raw(ttyfd);
+ } else {
+ raw_tty = sudo_term_is_raw(fileno(fp));
+ }
+ if (len != 0 && raw_tty) {
+ /* Convert nl -> cr nl in case tty is in raw mode. */
+ if (msg->msg[len - 1] == '\n') {
+ if (len == 1 || msg->msg[len - 2] != '\r') {
+ len--;
+ crnl = "\r\n";
+ }
+ }
+ }
+ if (ttyfd != -1) {
+ /* Try writing to tty but fall back to fp on error. */
+ if ((len == 0 || write(ttyfd, msg->msg, len) != -1) &&
+ (crnl == NULL || write(ttyfd, crnl, 2) != -1)) {
+ written = true;
+ }
+ close(ttyfd);
+ }
+ if (!written) {
+ if (len != 0 && fwrite(msg->msg, 1, len, fp) == 0)
+ goto err;
+ if (crnl != NULL && fwrite(crnl, 1, 2, fp) == 0)
+ goto err;
+ }
+ }
+ break;
+ default:
+ goto err;
+ }
+ }
+
+ sudo_debug_set_active_instance(conv_debug_instance);
+ return 0;
+
+err:
+ /* Zero and free allocated memory and return an error. */
+ if (replies != NULL) {
+ do {
+ struct sudo_conv_reply *repl = &replies[n];
+ if (repl->reply == NULL)
+ continue;
+ freezero(repl->reply, strlen(repl->reply));
+ repl->reply = NULL;
+ } while (n-- > 0);
+ }
+
+ sudo_debug_set_active_instance(conv_debug_instance);
+ return -1;
+}
+
+int
+sudo_conversation_1_7(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[])
+{
+ return sudo_conversation(num_msgs, msgs, replies, NULL);
+}
+
+int
+sudo_conversation_printf(int msg_type, const char * restrict fmt, ...)
+{
+ FILE *ttyfp = NULL;
+ FILE *fp = stdout;
+ char fmt2[1024];
+ char sbuf[8192];
+ char *buf = sbuf;
+ va_list ap;
+ int len;
+ const int conv_debug_instance = sudo_debug_get_active_instance();
+
+ sudo_debug_set_active_instance(sudo_debug_instance);
+
+ if (ISSET(msg_type, SUDO_CONV_PREFER_TTY) &&
+ !ISSET(tgetpass_flags, TGP_STDIN)) {
+ /* Try writing to /dev/tty first. */
+ ttyfp = fopen(_PATH_TTY, "w");
+ }
+
+ switch (msg_type & 0xff) {
+ case SUDO_CONV_ERROR_MSG:
+ fp = stderr;
+ FALLTHROUGH;
+ case SUDO_CONV_INFO_MSG:
+ /* Convert nl -> cr nl in case tty is in raw mode. */
+ if (sudo_term_is_raw(fileno(ttyfp ? ttyfp : fp))) {
+ size_t fmtlen = strlen(fmt);
+ if (fmtlen < sizeof(fmt2) - 1 && fmtlen && fmt[fmtlen - 1] == '\n') {
+ if (fmtlen == 1) {
+ /* Convert bare newline -> \r\n. */
+ len = (int)fwrite("\r\n", 1, 2, ttyfp ? ttyfp : fp);
+ if (len != 2)
+ len = -1;
+ break;
+ }
+ if (fmt[fmtlen - 2] != '\r') {
+ /* Convert trailing \n -> \r\n. */
+ memcpy(fmt2, fmt, fmtlen - 1);
+ fmt2[fmtlen - 1] = '\r';
+ fmt2[fmtlen ] = '\n';
+ fmt2[fmtlen + 1] = '\0';
+ fmt = fmt2;
+ }
+ }
+ }
+ /*
+ * We use vsnprintf() instead of vfprintf() here to avoid
+ * problems on systems where the system printf(3) is not
+ * C99-compliant. We use our own snprintf() on such systems.
+ */
+ va_start(ap, fmt);
+ len = vsnprintf(sbuf, sizeof(sbuf), fmt, ap);
+ va_end(ap);
+ if (len < 0 || len >= ssizeof(sbuf)) {
+ /* Try again with a dynamically-sized buffer. */
+ va_start(ap, fmt);
+ len = vasprintf(&buf, fmt, ap);
+ va_end(ap);
+ }
+ if (len != -1) {
+ if (fwrite(buf, 1, len, ttyfp ? ttyfp : fp) == 0)
+ len = -1;
+ if (buf != sbuf)
+ free(buf);
+ }
+ break;
+ default:
+ len = -1;
+ errno = EINVAL;
+ break;
+ }
+
+ if (ttyfp != NULL)
+ fclose(ttyfp);
+
+ sudo_debug_set_active_instance(conv_debug_instance);
+ return len;
+}
diff --git a/src/copy_file.c b/src/copy_file.c
new file mode 100644
index 0000000..b9b5d1d
--- /dev/null
+++ b/src/copy_file.c
@@ -0,0 +1,169 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2020-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sudo.h>
+#include <sudo_edit.h>
+
+/*
+ * Extend the given fd to the specified size in bytes.
+ * We do this to allocate disk space up-front before overwriting
+ * the original file with the temporary. Otherwise, we could
+ * run out of disk space after truncating the original file.
+ */
+static int
+sudo_extend_file(int fd, const char *name, off_t new_size)
+{
+ off_t old_size, size;
+ ssize_t nwritten;
+ char zeroes[BUFSIZ] = { '\0' };
+ debug_decl(sudo_extend_file, SUDO_DEBUG_UTIL);
+
+ if ((old_size = lseek(fd, 0, SEEK_END)) == -1) {
+ sudo_warn("lseek");
+ debug_return_int(-1);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: extending %s from %lld to %lld",
+ __func__, name, (long long)old_size, (long long)new_size);
+
+ for (size = old_size; size < new_size; size += nwritten) {
+ off_t len = new_size - size;
+ if (len > ssizeof(zeroes))
+ len = ssizeof(zeroes);
+ nwritten = write(fd, zeroes, (size_t)len);
+ if (nwritten == -1) {
+ int serrno = errno;
+ if (ftruncate(fd, old_size) == -1) {
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to truncate %s to %lld", name, (long long)old_size);
+ }
+ errno = serrno;
+ debug_return_int(-1);
+ }
+ }
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ sudo_warn("lseek");
+ debug_return_int(-1);
+ }
+
+ debug_return_int(0);
+}
+
+/*
+ * Copy the contents of src_fd into dst_fd.
+ * Returns 0 on success or -1 on error.
+ */
+int
+sudo_copy_file(const char *src, int src_fd, off_t src_len, const char *dst,
+ int dst_fd, off_t dst_len)
+{
+ char buf[BUFSIZ];
+ ssize_t nwritten, nread;
+ debug_decl(sudo_copy_file, SUDO_DEBUG_UTIL);
+
+ /* Prompt the user before zeroing out an existing file. */
+ if (dst_len > 0 && src_len == 0) {
+ fprintf(stderr, U_("%s: truncate %s to zero bytes? (y/n) [n] "),
+ getprogname(), dst);
+ if (fgets(buf, sizeof(buf), stdin) == NULL ||
+ (buf[0] != 'y' && buf[0] != 'Y')) {
+ sudo_warnx(U_("not overwriting %s"), dst);
+ debug_return_int(0);
+ }
+ }
+
+ /* Extend the file to the new size if larger before copying. */
+ if (dst_len > 0 && src_len > dst_len) {
+ if (sudo_extend_file(dst_fd, dst, src_len) == -1)
+ goto write_error;
+ }
+
+ /* Overwrite the old file with the new contents. */
+ while ((nread = read(src_fd, buf, sizeof(buf))) > 0) {
+ ssize_t off = 0;
+ do {
+ nwritten = write(dst_fd, buf + off, (size_t)(nread - off));
+ if (nwritten == -1)
+ goto write_error;
+ off += nwritten;
+ } while (nread > off);
+ }
+ if (nread == -1) {
+ sudo_warn(U_("unable to read from %s"), src);
+ debug_return_int(-1);
+ }
+
+ /* Did the file shrink? */
+ if (src_len < dst_len) {
+ /* We don't open with O_TRUNC so must truncate manually. */
+ if (ftruncate(dst_fd, src_len) == -1) {
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to truncate %s to %lld", dst, (long long)src_len);
+ goto write_error;
+ }
+ }
+
+ debug_return_int(0);
+write_error:
+ sudo_warn(U_("unable to write to %s"), dst);
+ debug_return_int(-1);
+}
+
+bool
+sudo_check_temp_file(int tfd, const char *tfile, uid_t uid, struct stat *sb)
+{
+ struct stat sbuf;
+ debug_decl(sudo_check_temp_file, SUDO_DEBUG_UTIL);
+
+ if (sb == NULL)
+ sb = &sbuf;
+
+ if (fstat(tfd, sb) == -1) {
+ sudo_warn(U_("unable to stat %s"), tfile);
+ debug_return_bool(false);
+ }
+ if (!S_ISREG(sb->st_mode)) {
+ sudo_warnx(U_("%s: not a regular file"), tfile);
+ debug_return_bool(false);
+ }
+ if ((sb->st_mode & ALLPERMS) != (S_IRUSR|S_IWUSR)) {
+ sudo_warnx(U_("%s: bad file mode: 0%o"), tfile,
+ (unsigned int)(sb->st_mode & ALLPERMS));
+ debug_return_bool(false);
+ }
+ if (sb->st_uid != uid) {
+ sudo_warnx(U_("%s is owned by uid %u, should be %u"),
+ tfile, (unsigned int)sb->st_uid, (unsigned int)uid);
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
diff --git a/src/edit_open.c b/src/edit_open.c
new file mode 100644
index 0000000..2fa58f5
--- /dev/null
+++ b/src/edit_open.c
@@ -0,0 +1,538 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2015-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <fcntl.h>
+
+#include <sudo.h>
+#include <sudo_edit.h>
+
+#if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID)
+
+static int
+switch_user_int(uid_t euid, gid_t egid, int ngroups, GETGROUPS_T *groups,
+ bool nonfatal)
+{
+ int serrno = errno;
+ int ret = -1;
+ debug_decl(switch_user, SUDO_DEBUG_EDIT);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "set uid:gid to %u:%u(%u)", (unsigned int)euid, (unsigned int)egid,
+ ngroups > 0 ? (unsigned int)groups[0] : (unsigned int)egid);
+
+ /* When restoring root, change euid first; otherwise change it last. */
+ if (euid == ROOT_UID) {
+ if (seteuid(ROOT_UID) != 0) {
+ if (nonfatal)
+ goto done;
+ sudo_fatal("seteuid(ROOT_UID)");
+ }
+ }
+ if (setegid(egid) != 0) {
+ if (nonfatal)
+ goto done;
+ sudo_fatal("setegid(%d)", (int)egid);
+ }
+ if (ngroups != -1) {
+ if (sudo_setgroups(ngroups, groups) != 0) {
+ if (nonfatal)
+ goto done;
+ sudo_fatal("setgroups");
+ }
+ }
+ if (euid != ROOT_UID) {
+ if (seteuid(euid) != 0) {
+ if (nonfatal)
+ goto done;
+ sudo_fatal("seteuid(%u)", (unsigned int)euid);
+ }
+ }
+ ret = 0;
+
+done:
+ errno = serrno;
+ debug_return_int(ret);
+}
+
+#if defined(HAVE_FACCESSAT) && defined(AT_EACCESS)
+static int
+switch_user_nonfatal(uid_t euid, gid_t egid, int ngroups, GETGROUPS_T *groups)
+{
+ return switch_user_int(euid, egid, ngroups, groups, true);
+}
+#endif
+
+void
+switch_user(uid_t euid, gid_t egid, int ngroups, GETGROUPS_T *groups)
+{
+ (void)switch_user_int(euid, egid, ngroups, groups, false);
+}
+
+static bool
+group_matches(gid_t target, const struct sudo_cred *cred)
+{
+ int i;
+ debug_decl(group_matches, SUDO_DEBUG_EDIT);
+
+ if (target == cred->gid) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "user gid %u matches directory gid %u", (unsigned int)cred->gid,
+ (unsigned int)target);
+ debug_return_bool(true);
+ }
+ for (i = 0; i < cred->ngroups; i++) {
+ if (target == cred->groups[i]) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "user gid %u matches directory gid %u",
+ (unsigned int)cred->groups[i], (unsigned int)target);
+ debug_return_bool(true);
+ }
+ }
+ debug_return_bool(false);
+}
+
+static bool
+is_writable(const struct sudo_cred *user_cred, struct stat *sb)
+{
+ debug_decl(is_writable, SUDO_DEBUG_EDIT);
+
+ /* Other writable? */
+ if (ISSET(sb->st_mode, S_IWOTH)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "directory is writable by other");
+ debug_return_int(true);
+ }
+
+ /* Group writable? */
+ if (ISSET(sb->st_mode, S_IWGRP)) {
+ if (group_matches(sb->st_gid, user_cred)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "directory is writable by one of the user's groups");
+ debug_return_int(true);
+ }
+ }
+
+ errno = EACCES;
+ debug_return_int(false);
+}
+
+#if defined(HAVE_FACCESSAT) && defined(AT_EACCESS)
+/*
+ * Checks whether the open directory dfd is owned or writable by the user.
+ * Returns true if writable, false if not, or -1 on error.
+ */
+int
+dir_is_writable(int dfd, const struct sudo_cred *user_cred,
+ const struct sudo_cred *cur_cred)
+{
+ struct stat sb;
+ int rc;
+ debug_decl(dir_is_writable, SUDO_DEBUG_EDIT);
+
+ if (fstat(dfd, &sb) == -1)
+ debug_return_int(-1);
+
+ /* If the user owns the dir we always consider it writable. */
+ if (sb.st_uid == user_cred->uid) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "user uid %u matches directory uid %u",
+ (unsigned int)user_cred->uid, (unsigned int)sb.st_uid);
+ debug_return_int(true);
+ }
+
+ /* Change uid/gid/groups to invoking user, usually needs root perms. */
+ if (cur_cred->euid != ROOT_UID) {
+ if (seteuid(ROOT_UID) != 0) {
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "seteuid(ROOT_UID)");
+ goto fallback;
+ }
+ }
+ if (switch_user_nonfatal(user_cred->uid, user_cred->gid, user_cred->ngroups,
+ user_cred->groups) == -1) {
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to switch to user_cred");
+ goto fallback;
+ }
+
+ /* Access checks are done using the euid/egid and group vector. */
+ rc = faccessat(dfd, ".", W_OK, AT_EACCESS);
+
+ /* Restore uid/gid/groups, may need root perms. */
+ if (user_cred->uid != ROOT_UID) {
+ if (seteuid(ROOT_UID) != 0)
+ sudo_fatal("seteuid(ROOT_UID)");
+ }
+ switch_user(cur_cred->euid, cur_cred->egid, cur_cred->ngroups,
+ cur_cred->groups);
+
+ if (rc == 0)
+ debug_return_int(true);
+ if (errno == EACCES || errno == EPERM || errno == EROFS)
+ debug_return_int(false);
+ debug_return_int(-1);
+
+fallback:
+ debug_return_int(is_writable(user_cred, &sb));
+}
+#endif /* HAVE_FACCESSAT && AT_EACCESS */
+
+#if !defined(HAVE_FACCESSAT) || !defined(AT_EACCESS)
+/*
+ * Checks whether the open directory dfd is owned or writable by the user.
+ * Returns true if writable, false if not, or -1 on error.
+ */
+int
+dir_is_writable(int dfd, const struct sudo_cred *user_cred,
+ const struct sudo_cred *cur_cred)
+{
+ struct stat sb;
+ debug_decl(dir_is_writable, SUDO_DEBUG_EDIT);
+
+ if (fstat(dfd, &sb) == -1)
+ debug_return_int(-1);
+
+ /* If the user owns the dir we always consider it writable. */
+ if (sb.st_uid == user_cred->uid) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "user uid %u matches directory uid %u",
+ (unsigned int)user_cred->uid, (unsigned int)sb.st_uid);
+ debug_return_int(true);
+ }
+
+ debug_return_int(is_writable(user_cred, &sb));
+}
+#endif /* HAVE_FACCESSAT && AT_EACCESS */
+
+#ifdef O_NOFOLLOW
+static int
+sudo_edit_openat_nofollow(int dfd, char *path, int oflags, mode_t mode)
+{
+ int fd;
+ debug_decl(sudo_edit_openat_nofollow, SUDO_DEBUG_EDIT);
+
+ fd = openat(dfd, path, oflags|O_NOFOLLOW, mode);
+ if (fd == -1) {
+ /* Handle non-standard O_NOFOLLOW errno values. */
+ if (errno == EMLINK)
+ errno = ELOOP; /* FreeBSD */
+#ifdef EFTYPE
+ else if (errno == EFTYPE)
+ errno = ELOOP; /* NetBSD */
+#endif
+ }
+
+ debug_return_int(fd);
+}
+#else
+/*
+ * Returns true if fd and path don't match or path is a symlink.
+ * Used on older systems without O_NOFOLLOW.
+ */
+static bool
+sudo_edit_is_symlink(int fd, char *path)
+{
+ struct stat sb1, sb2;
+ debug_decl(sudo_edit_is_symlink, SUDO_DEBUG_EDIT);
+
+ /*
+ * Treat [fl]stat() failure like there was a symlink.
+ */
+ if (fstat(fd, &sb1) == -1 || lstat(path, &sb2) == -1)
+ debug_return_bool(true);
+
+ /*
+ * Make sure we did not open a link and that what we opened
+ * matches what is currently on the file system.
+ */
+ if (S_ISLNK(sb2.st_mode) ||
+ sb1.st_dev != sb2.st_dev || sb1.st_ino != sb2.st_ino) {
+ debug_return_bool(true);
+ }
+
+ debug_return_bool(false);
+}
+
+static int
+sudo_edit_openat_nofollow(int dfd, char *path, int oflags, mode_t mode)
+{
+ int fd = -1, odfd = -1;
+ struct stat sb;
+ debug_decl(sudo_edit_openat_nofollow, SUDO_DEBUG_EDIT);
+
+ /* Save cwd and chdir to dfd */
+ if ((odfd = open(".", O_RDONLY)) == -1)
+ debug_return_int(-1);
+ if (fchdir(dfd) == -1) {
+ close(odfd);
+ debug_return_int(-1);
+ }
+
+ /*
+ * Check if path is a symlink. This is racey but we detect whether
+ * we lost the race in sudo_edit_is_symlink() after the open.
+ */
+ if (lstat(path, &sb) == -1 && errno != ENOENT)
+ goto done;
+ if (S_ISLNK(sb.st_mode)) {
+ errno = ELOOP;
+ goto done;
+ }
+
+ fd = open(path, oflags, mode);
+ if (fd == -1)
+ goto done;
+
+ /*
+ * Post-open symlink check. This will leave a zero-length file if
+ * O_CREAT was specified but it is too dangerous to try and remove it.
+ */
+ if (sudo_edit_is_symlink(fd, path)) {
+ close(fd);
+ fd = -1;
+ errno = ELOOP;
+ }
+
+done:
+ /* Restore cwd */
+ if (odfd != -1) {
+ if (fchdir(odfd) == -1)
+ sudo_fatal("%s", U_("unable to restore current working directory"));
+ close(odfd);
+ }
+
+ debug_return_int(fd);
+}
+#endif /* O_NOFOLLOW */
+
+static int
+sudo_edit_open_nonwritable(char *path, int oflags, mode_t mode,
+ const struct sudo_cred *user_cred, const struct sudo_cred *cur_cred)
+{
+ const int dflags = DIR_OPEN_FLAGS;
+ int dfd, fd, writable;
+ debug_decl(sudo_edit_open_nonwritable, SUDO_DEBUG_EDIT);
+
+ if (path[0] == '/') {
+ dfd = open("/", dflags);
+ path++;
+ } else {
+ dfd = open(".", dflags);
+ if (path[0] == '.' && path[1] == '/')
+ path += 2;
+ }
+ if (dfd == -1)
+ debug_return_int(-1);
+
+ for (;;) {
+ char *slash;
+ int subdfd;
+
+ /*
+ * Look up one component at a time, avoiding symbolic links in
+ * writable directories.
+ */
+ writable = dir_is_writable(dfd, user_cred, cur_cred);
+ if (writable == -1) {
+ close(dfd);
+ debug_return_int(-1);
+ }
+
+ path += strspn(path, "/");
+ slash = strchr(path, '/');
+ if (slash == NULL)
+ break;
+ *slash = '\0';
+ if (writable)
+ subdfd = sudo_edit_openat_nofollow(dfd, path, dflags, 0);
+ else
+ subdfd = openat(dfd, path, dflags, 0);
+ *slash = '/'; /* restore path */
+ close(dfd);
+ if (subdfd == -1)
+ debug_return_int(-1);
+ path = slash + 1;
+ dfd = subdfd;
+ }
+
+ if (writable) {
+ close(dfd);
+ errno = EISDIR;
+ debug_return_int(-1);
+ }
+
+ /*
+ * For "sudoedit /" we will receive ENOENT from openat() and sudoedit
+ * will try to create a file with an empty name. We treat an empty
+ * path as the cwd so sudoedit can give a sensible error message.
+ */
+ fd = openat(dfd, *path ? path : ".", oflags, mode);
+ close(dfd);
+ debug_return_int(fd);
+}
+
+#ifdef O_NOFOLLOW
+int
+sudo_edit_open(char *path, int oflags, mode_t mode, unsigned int sflags,
+ const struct sudo_cred *user_cred, const struct sudo_cred *cur_cred)
+{
+ int fd;
+ debug_decl(sudo_edit_open, SUDO_DEBUG_EDIT);
+
+ if (!ISSET(sflags, CD_SUDOEDIT_FOLLOW))
+ oflags |= O_NOFOLLOW;
+ if (ISSET(sflags, CD_SUDOEDIT_CHECKDIR) && user_cred->uid != ROOT_UID) {
+ fd = sudo_edit_open_nonwritable(path, oflags|O_NONBLOCK, mode,
+ user_cred, cur_cred);
+ } else {
+ fd = open(path, oflags|O_NONBLOCK, mode);
+ }
+ if (fd == -1 && ISSET(oflags, O_NOFOLLOW)) {
+ /* Handle non-standard O_NOFOLLOW errno values. */
+ if (errno == EMLINK)
+ errno = ELOOP; /* FreeBSD */
+#ifdef EFTYPE
+ else if (errno == EFTYPE)
+ errno = ELOOP; /* NetBSD */
+#endif
+ }
+ if (fd != -1 && !ISSET(oflags, O_NONBLOCK))
+ (void) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
+ debug_return_int(fd);
+}
+#else
+int
+sudo_edit_open(char *path, int oflags, mode_t mode, unsigned int sflags,
+ const struct sudo_cred *user_cred, const struct sudo_cred *cur_cred)
+{
+ struct stat sb;
+ int fd;
+ debug_decl(sudo_edit_open, SUDO_DEBUG_EDIT);
+
+ /*
+ * Check if path is a symlink. This is racey but we detect whether
+ * we lost the race in sudo_edit_is_symlink() after the file is opened.
+ */
+ if (!ISSET(sflags, CD_SUDOEDIT_FOLLOW)) {
+ if (lstat(path, &sb) == -1 && errno != ENOENT)
+ debug_return_int(-1);
+ if (S_ISLNK(sb.st_mode)) {
+ errno = ELOOP;
+ debug_return_int(-1);
+ }
+ }
+
+ if (ISSET(sflags, CD_SUDOEDIT_CHECKDIR) && user_cred->uid != ROOT_UID) {
+ fd = sudo_edit_open_nonwritable(path, oflags|O_NONBLOCK, mode,
+ user_cred, cur_cred);
+ } else {
+ fd = open(path, oflags|O_NONBLOCK, mode);
+ }
+ if (fd == -1)
+ debug_return_int(-1);
+ if (!ISSET(oflags, O_NONBLOCK))
+ (void) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
+
+ /*
+ * Post-open symlink check. This will leave a zero-length file if
+ * O_CREAT was specified but it is too dangerous to try and remove it.
+ */
+ if (!ISSET(sflags, CD_SUDOEDIT_FOLLOW) && sudo_edit_is_symlink(fd, path)) {
+ close(fd);
+ fd = -1;
+ errno = ELOOP;
+ }
+
+ debug_return_int(fd);
+}
+#endif /* O_NOFOLLOW */
+
+/*
+ * Verify that the parent dir of a new file exists and is not writable
+ * by the user. This fails early so the user knows ahead of time if the
+ * edit won't succeed. Additional checks are performed when copying the
+ * temporary file back to the origin so there are no TOCTOU issues.
+ * Does not modify the value of errno.
+ */
+bool
+sudo_edit_parent_valid(char *path, unsigned int sflags,
+ const struct sudo_cred *user_cred, const struct sudo_cred *cur_cred)
+{
+ const int serrno = errno;
+ struct stat sb;
+ bool ret = false;
+ char *slash;
+ char pathbuf[2];
+ int dfd;
+ debug_decl(sudo_edit_parent_valid, SUDO_DEBUG_EDIT);
+
+ /* Get dirname of path (the slash is restored later). */
+ slash = strrchr(path, '/');
+ if (slash == NULL) {
+ /* cwd */
+ pathbuf[0] = '.';
+ pathbuf[1] = '\0';
+ path = pathbuf;
+ } else if (slash == path) {
+ pathbuf[0] = '/';
+ pathbuf[1] = '\0';
+ path = pathbuf;
+ slash = NULL;
+ } else {
+ *slash = '\0';
+ }
+
+ /*
+ * The parent directory is allowed to be a symbolic link unless
+ * *its* parent is writable and CD_SUDOEDIT_CHECK is set.
+ */
+ dfd = sudo_edit_open(path, DIR_OPEN_FLAGS, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
+ sflags|CD_SUDOEDIT_FOLLOW, user_cred, cur_cred);
+ if (dfd != -1) {
+ if (fstat(dfd, &sb) == 0 && S_ISDIR(sb.st_mode))
+ ret = true;
+ close(dfd);
+ }
+ if (slash != NULL)
+ *slash = '/';
+
+ /* Restore errno. */
+ errno = serrno;
+
+ debug_return_bool(ret);
+}
+
+#endif /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */
diff --git a/src/env_hooks.c b/src/env_hooks.c
new file mode 100644
index 0000000..e840c78
--- /dev/null
+++ b/src/env_hooks.c
@@ -0,0 +1,315 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010, 2012-2016 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sudo.h>
+#include <sudo_plugin.h>
+#include <sudo_dso.h>
+
+extern char **environ; /* global environment pointer */
+static char **priv_environ; /* private environment pointer */
+
+/*
+ * NOTE: we don't use dlsym() to find the libc getenv()
+ * since this may allocate memory on some systems (glibc)
+ * which leads to a hang if malloc() calls getenv (jemalloc).
+ */
+char *
+getenv_unhooked(const char *name)
+{
+ char **ep, *val = NULL;
+ size_t namelen = 0;
+
+ /* For BSD compatibility, treat '=' in name like end of string. */
+ while (name[namelen] != '\0' && name[namelen] != '=')
+ namelen++;
+ for (ep = environ; *ep != NULL; ep++) {
+ if (strncmp(*ep, name, namelen) == 0 && (*ep)[namelen] == '=') {
+ val = *ep + namelen + 1;
+ break;
+ }
+ }
+ return val;
+}
+
+sudo_dso_public char *getenv(const char *name);
+
+char *
+getenv(const char *name)
+{
+ char *val = NULL;
+
+ switch (process_hooks_getenv(name, &val)) {
+ case SUDO_HOOK_RET_STOP:
+ return val;
+ case SUDO_HOOK_RET_ERROR:
+ return NULL;
+ default:
+ return getenv_unhooked(name);
+ }
+}
+
+static int
+rpl_putenv(PUTENV_CONST char *string)
+{
+ char **ep;
+ const char *equal;
+ size_t len;
+ bool found = false;
+
+ /* Some putenv(3) implementations check for NULL. */
+ if (string == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* The string must contain a '=' char but not start with one. */
+ equal = strchr(string, '=');
+ if (equal == NULL || equal == string) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Look for existing entry. */
+ len = (size_t)(equal - string) + 1;
+ for (ep = environ; *ep != NULL; ep++) {
+ if (strncmp(string, *ep, len) == 0) {
+ *ep = (char *)string;
+ found = true;
+ break;
+ }
+ }
+ /* Prune out duplicate variables. */
+ if (found) {
+ while (*ep != NULL) {
+ if (strncmp(string, *ep, len) == 0) {
+ char **cur = ep;
+ while ((*cur = *(cur + 1)) != NULL)
+ cur++;
+ } else {
+ ep++;
+ }
+ }
+ }
+
+ /* Append at the end if not already found. */
+ if (!found) {
+ size_t env_len = (size_t)(ep - environ);
+ char **envp = reallocarray(priv_environ, env_len + 2, sizeof(char *));
+ if (envp == NULL)
+ return -1;
+ if (environ != priv_environ)
+ memcpy(envp, environ, env_len * sizeof(char *));
+ envp[env_len++] = (char *)string;
+ envp[env_len] = NULL;
+ priv_environ = environ = envp;
+ }
+ return 0;
+}
+
+typedef int (*sudo_fn_putenv_t)(PUTENV_CONST char *);
+
+static int
+putenv_unhooked(PUTENV_CONST char *string)
+{
+ sudo_fn_putenv_t fn;
+
+ fn = (sudo_fn_putenv_t)sudo_dso_findsym(SUDO_DSO_NEXT, "putenv");
+ if (fn != NULL)
+ return fn(string);
+ return rpl_putenv(string);
+}
+
+sudo_dso_public int putenv(PUTENV_CONST char *string);
+
+int
+putenv(PUTENV_CONST char *string)
+{
+ switch (process_hooks_putenv((char *)string)) {
+ case SUDO_HOOK_RET_STOP:
+ return 0;
+ case SUDO_HOOK_RET_ERROR:
+ return -1;
+ default:
+ return putenv_unhooked(string);
+ }
+}
+
+static int
+rpl_setenv(const char *var, const char *val, int overwrite)
+{
+ char *envstr, *dst;
+ const char *src;
+ size_t esize;
+
+ if (!var || *var == '\0') {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * POSIX says a var name with '=' is an error but BSD
+ * just ignores the '=' and anything after it.
+ */
+ for (src = var; *src != '\0' && *src != '='; src++)
+ continue;
+ esize = (size_t)(src - var) + 2;
+ if (val) {
+ esize += strlen(val); /* glibc treats a NULL val as "" */
+ }
+
+ /* Allocate and fill in envstr. */
+ if ((envstr = malloc(esize)) == NULL)
+ return -1;
+ for (src = var, dst = envstr; *src != '\0' && *src != '=';)
+ *dst++ = *src++;
+ *dst++ = '=';
+ if (val) {
+ for (src = val; *src != '\0';)
+ *dst++ = *src++;
+ }
+ *dst = '\0';
+
+ if (!overwrite && getenv(var) != NULL) {
+ free(envstr);
+ return 0;
+ }
+ if (rpl_putenv(envstr) == -1) {
+ free(envstr);
+ return -1;
+ }
+ return 0;
+}
+
+typedef int (*sudo_fn_setenv_t)(const char *, const char *, int);
+
+static int
+setenv_unhooked(const char *var, const char *val, int overwrite)
+{
+ sudo_fn_setenv_t fn;
+
+ fn = (sudo_fn_setenv_t)sudo_dso_findsym(SUDO_DSO_NEXT, "setenv");
+ if (fn != NULL)
+ return fn(var, val, overwrite);
+ return rpl_setenv(var, val, overwrite);
+}
+
+sudo_dso_public int setenv(const char *var, const char *val, int overwrite);
+
+int
+setenv(const char *var, const char *val, int overwrite)
+{
+ switch (process_hooks_setenv(var, val, overwrite)) {
+ case SUDO_HOOK_RET_STOP:
+ return 0;
+ case SUDO_HOOK_RET_ERROR:
+ return -1;
+ default:
+ return setenv_unhooked(var, val, overwrite);
+ }
+}
+
+static int
+rpl_unsetenv(const char *var)
+{
+ char **ep = environ;
+ size_t len;
+
+ if (var == NULL || *var == '\0' || strchr(var, '=') != NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ len = strlen(var);
+ while (*ep != NULL) {
+ if (strncmp(var, *ep, len) == 0 && (*ep)[len] == '=') {
+ /* Found it; shift remainder + NULL over by one. */
+ char **cur = ep;
+ while ((*cur = *(cur + 1)) != NULL)
+ cur++;
+ /* Keep going, could be multiple instances of the var. */
+ } else {
+ ep++;
+ }
+ }
+ return 0;
+}
+
+#ifdef UNSETENV_VOID
+typedef void (*sudo_fn_unsetenv_t)(const char *);
+#else
+typedef int (*sudo_fn_unsetenv_t)(const char *);
+#endif
+
+static int
+unsetenv_unhooked(const char *var)
+{
+ int ret = 0;
+ sudo_fn_unsetenv_t fn;
+
+ fn = (sudo_fn_unsetenv_t)sudo_dso_findsym(SUDO_DSO_NEXT, "unsetenv");
+ if (fn != NULL) {
+# ifdef UNSETENV_VOID
+ fn(var);
+# else
+ ret = fn(var);
+# endif
+ } else {
+ ret = rpl_unsetenv(var);
+ }
+ return ret;
+}
+
+#ifdef UNSETENV_VOID
+# define UNSETENV_RTYPE void
+#else
+# define UNSETENV_RTYPE int
+#endif
+
+sudo_dso_public UNSETENV_RTYPE unsetenv(const char *var);
+
+UNSETENV_RTYPE
+unsetenv(const char *var)
+{
+ int ret;
+
+ switch (process_hooks_unsetenv(var)) {
+ case SUDO_HOOK_RET_STOP:
+ ret = 0;
+ break;
+ case SUDO_HOOK_RET_ERROR:
+ ret = -1;
+ break;
+ default:
+ ret = unsetenv_unhooked(var);
+ break;
+ }
+#ifndef UNSETENV_VOID
+ return ret;
+#endif
+}
diff --git a/src/exec.c b/src/exec.c
new file mode 100644
index 0000000..46fc8bc
--- /dev/null
+++ b/src/exec.c
@@ -0,0 +1,586 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <signal.h>
+#ifdef HAVE_LOGIN_CAP_H
+# include <login_cap.h>
+# ifndef LOGIN_SETENV
+# define LOGIN_SETENV 0
+# endif
+#endif
+#ifdef HAVE_PROJECT_H
+# include <project.h>
+# include <sys/task.h>
+#endif
+
+#include <sudo.h>
+#include <sudo_exec.h>
+#include <sudo_plugin.h>
+#include <sudo_plugin_int.h>
+
+#ifdef HAVE_PTRACE_INTERCEPT
+static void
+handler(int signo)
+{
+ /* just return */
+}
+#endif /* HAVE_PTRACE_INTERCEPT */
+
+static void
+close_fds(struct command_details *details, int errfd, int intercept_fd)
+{
+ int fd, maxfd;
+ unsigned char *debug_fds;
+ debug_decl(close_fds, SUDO_DEBUG_EXEC);
+
+ if (details->closefrom < 0)
+ debug_return;
+
+ /* Preserve debug fds and error pipe as needed. */
+ maxfd = sudo_debug_get_fds(&debug_fds);
+ for (fd = 0; fd <= maxfd; fd++) {
+ if (sudo_isset(debug_fds, fd))
+ add_preserved_fd(&details->preserved_fds, fd);
+ }
+ if (errfd != -1)
+ add_preserved_fd(&details->preserved_fds, errfd);
+ if (intercept_fd != -1)
+ add_preserved_fd(&details->preserved_fds, intercept_fd);
+
+ /* Close all fds except those explicitly preserved. */
+ closefrom_except(details->closefrom, &details->preserved_fds);
+
+ debug_return;
+}
+
+/*
+ * Setup the execution environment immediately prior to the call to execve().
+ * Group setup is performed by policy_init_session(), called earlier.
+ * Returns true on success and false on failure.
+ */
+static bool
+exec_setup(struct command_details *details, int intercept_fd, int errfd)
+{
+ bool ret = false;
+ debug_decl(exec_setup, SUDO_DEBUG_EXEC);
+
+#ifdef HAVE_PTRACE_INTERCEPT
+ if (ISSET(details->flags, CD_USE_PTRACE)) {
+ if (!set_exec_filter())
+ goto done;
+ }
+#endif /* HAVE_PTRACE_INTERCEPT */
+
+ if (details->pw != NULL) {
+#ifdef HAVE_PROJECT_H
+ set_project(details->pw);
+#endif
+#ifdef HAVE_PRIV_SET
+ if (details->privs != NULL) {
+ if (setppriv(PRIV_SET, PRIV_INHERITABLE, details->privs) != 0) {
+ sudo_warn("%s", U_("unable to set privileges"));
+ goto done;
+ }
+ }
+ if (details->limitprivs != NULL) {
+ if (setppriv(PRIV_SET, PRIV_LIMIT, details->limitprivs) != 0) {
+ sudo_warn("%s", U_("unable to set limit privileges"));
+ goto done;
+ }
+ } else if (details->privs != NULL) {
+ if (setppriv(PRIV_SET, PRIV_LIMIT, details->privs) != 0) {
+ sudo_warn("%s", U_("unable to set limit privileges"));
+ goto done;
+ }
+ }
+#endif /* HAVE_PRIV_SET */
+
+#ifdef HAVE_GETUSERATTR
+ if (aix_prep_user(details->pw->pw_name, details->tty) != 0) {
+ /* error message displayed by aix_prep_user */
+ goto done;
+ }
+#endif
+#ifdef HAVE_LOGIN_CAP_H
+ if (details->login_class) {
+ unsigned int flags;
+ login_cap_t *lc;
+
+ /*
+ * We only use setusercontext() to set the nice value, rlimits
+ * and umask unless this is a login shell (sudo -i).
+ */
+ lc = login_getclass((char *)details->login_class);
+ if (!lc) {
+ sudo_warnx(U_("unknown login class %s"), details->login_class);
+ errno = ENOENT;
+ goto done;
+ }
+ if (ISSET(details->flags, CD_LOGIN_SHELL)) {
+ /* Set everything except user, group and login name. */
+ flags = LOGIN_SETALL;
+ CLR(flags, LOGIN_SETGROUP|LOGIN_SETLOGIN|LOGIN_SETUSER|LOGIN_SETENV|LOGIN_SETPATH);
+ } else {
+ flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY|LOGIN_SETUMASK;
+ }
+ if (setusercontext(lc, details->pw, details->pw->pw_uid, flags)) {
+ sudo_warn("%s", U_("unable to set user context"));
+ if (details->pw->pw_uid != ROOT_UID)
+ goto done;
+ }
+ }
+#endif /* HAVE_LOGIN_CAP_H */
+ }
+
+ if (ISSET(details->flags, CD_SET_GROUPS)) {
+ /* set_user_groups() prints error message on failure. */
+ if (!set_user_groups(details))
+ goto done;
+ }
+
+ if (ISSET(details->flags, CD_SET_PRIORITY)) {
+ if (setpriority(PRIO_PROCESS, 0, details->priority) != 0) {
+ sudo_warn("%s", U_("unable to set process priority"));
+ goto done;
+ }
+ }
+
+ /* Policy may override umask in PAM or login.conf. */
+ if (ISSET(details->flags, CD_OVERRIDE_UMASK))
+ (void) umask(details->umask);
+
+ /* Apply resource limits specified by the policy, if any. */
+ set_policy_rlimits();
+
+ /* Close fds before chroot (need /dev) or uid change (prlimit on Linux). */
+ close_fds(details, errfd, intercept_fd);
+
+ if (details->chroot) {
+ if (chroot(details->chroot) != 0 || chdir("/") != 0) {
+ sudo_warn(U_("unable to change root to %s"), details->chroot);
+ goto done;
+ }
+ }
+
+ /*
+ * Unlimit the number of processes since Linux's setuid() will
+ * return EAGAIN if RLIMIT_NPROC would be exceeded by the uid switch.
+ */
+ unlimit_nproc();
+
+#if defined(HAVE_SETRESUID)
+ if (setresuid(details->cred.uid, details->cred.euid, details->cred.euid) != 0) {
+ sudo_warn(U_("unable to change to runas uid (%u, %u)"),
+ (unsigned int)details->cred.uid, (unsigned int)details->cred.euid);
+ goto done;
+ }
+#elif defined(HAVE_SETREUID)
+ if (setreuid(details->cred.uid, details->cred.euid) != 0) {
+ sudo_warn(U_("unable to change to runas uid (%u, %u)"),
+ (unsigned int)details->cred.uid, (unsigned int)details->cred.euid);
+ goto done;
+ }
+#else
+ /* Cannot support real user-ID that is different from effective user-ID. */
+ if (setuid(details->cred.euid) != 0) {
+ sudo_warn(U_("unable to change to runas uid (%u, %u)"),
+ (unsigned int)details->cred.euid, (unsigned int)details->cred.euid);
+ goto done;
+ }
+#endif /* !HAVE_SETRESUID && !HAVE_SETREUID */
+
+ /* Restore previous value of RLIMIT_NPROC. */
+ restore_nproc();
+
+ /*
+ * Only change cwd if we have chroot()ed or the policy modules
+ * specifies a different cwd. Must be done after uid change.
+ */
+ if (details->runcwd != NULL) {
+ if (details->chroot != NULL || details->submitcwd == NULL ||
+ strcmp(details->runcwd, details->submitcwd) != 0) {
+ if (ISSET(details->flags, CD_RBAC_ENABLED)) {
+ /* For SELinux, chdir(2) in sesh after the context change. */
+ SET(details->flags, CD_RBAC_SET_CWD);
+ } else {
+ /* Note: runcwd is relative to the new root, if any. */
+ if (chdir(details->runcwd) == -1) {
+ sudo_warn(U_("unable to change directory to %s"),
+ details->runcwd);
+ if (!ISSET(details->flags, CD_CWD_OPTIONAL))
+ goto done;
+ if (details->chroot != NULL)
+ sudo_warnx(U_("starting from %s"), "/");
+ }
+ }
+ }
+ }
+
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+/*
+ * Setup the execution environment and execute the command.
+ * If SELinux is enabled, run the command via sesh, otherwise
+ * execute it directly.
+ * If the exec fails, cstat is filled in with the value of errno.
+ */
+void
+exec_cmnd(struct command_details *details, sigset_t *mask,
+ int intercept_fd, int errfd)
+{
+ debug_decl(exec_cmnd, SUDO_DEBUG_EXEC);
+
+#ifdef HAVE_PTRACE_INTERCEPT
+ if (ISSET(details->flags, CD_USE_PTRACE)) {
+ struct sigaction sa;
+ sigset_t set;
+
+ /* Tracer will send us SIGUSR1 when it is time to proceed. */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = handler;
+ if (sudo_sigaction(SIGUSR1, &sa, NULL) != 0) {
+ sudo_warn(U_("unable to set handler for signal %d"),
+ SIGUSR1);
+ }
+
+ /* Suspend child until tracer seizes control and sends SIGUSR1. */
+ sigfillset(&set);
+ sigdelset(&set, SIGUSR1);
+ sigsuspend(&set);
+ }
+#endif /* HAVE_PTRACE_INTERCEPT */
+
+ if (mask != NULL)
+ sigprocmask(SIG_SETMASK, mask, NULL);
+ restore_signals();
+ if (exec_setup(details, intercept_fd, errfd) == true) {
+ /* headed for execve() */
+#ifdef HAVE_SELINUX
+ if (ISSET(details->flags, CD_RBAC_ENABLED)) {
+ selinux_execve(details->execfd, details->command, details->argv,
+ details->envp, details->runcwd, details->flags);
+ } else
+#endif
+ {
+ sudo_execve(details->execfd, details->command, details->argv,
+ details->envp, intercept_fd, details->flags);
+ }
+ }
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to exec %s: %s",
+ details->command, strerror(errno));
+ debug_return;
+}
+
+/*
+ * Check for caught signals sent to sudo before command execution.
+ * Also suspends the process if SIGTSTP was caught.
+ * Returns true if we should terminate, else false.
+ */
+bool
+sudo_terminated(struct command_status *cstat)
+{
+ int signo;
+ bool sigtstp = false;
+ debug_decl(sudo_terminated, SUDO_DEBUG_EXEC);
+
+ for (signo = 0; signo < NSIG; signo++) {
+ if (signal_pending(signo)) {
+ switch (signo) {
+ case SIGCHLD:
+ /* Ignore. */
+ break;
+ case SIGTSTP:
+ /* Suspend below if not terminated. */
+ sigtstp = true;
+ break;
+ default:
+ /* Terminal signal, do not exec command. */
+ cstat->type = CMD_WSTATUS;
+ cstat->val = signo + 128;
+ debug_return_bool(true);
+ break;
+ }
+ }
+ }
+ if (sigtstp) {
+ struct sigaction sa;
+ sigset_t set, oset;
+
+ /* Send SIGTSTP to ourselves, unblocking it if needed. */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = SIG_DFL;
+ if (sudo_sigaction(SIGTSTP, &sa, NULL) != 0)
+ sudo_warn(U_("unable to set handler for signal %d"), SIGTSTP);
+ sigemptyset(&set);
+ sigaddset(&set, SIGTSTP);
+ sigprocmask(SIG_UNBLOCK, &set, &oset);
+ if (kill(getpid(), SIGTSTP) != 0)
+ sudo_warn("kill(%d, SIGTSTP)", (int)getpid());
+ sigprocmask(SIG_SETMASK, &oset, NULL);
+ /* No need to restore old SIGTSTP handler. */
+ }
+ debug_return_bool(false);
+}
+
+static bool
+sudo_needs_pty(const struct command_details *details)
+{
+ struct plugin_container *plugin;
+
+ if (ISSET(details->flags, CD_USE_PTY))
+ return true;
+
+ TAILQ_FOREACH(plugin, &io_plugins, entries) {
+ if (plugin->u.io->log_ttyin != NULL ||
+ plugin->u.io->log_ttyout != NULL)
+ return true;
+ }
+ return false;
+}
+
+/*
+ * Check whether the specified fd matches the device file that
+ * corresponds to tty_sb. If tty_sb is NULL, just check whether
+ * fd is a tty. Always fills in fd_sb (zeroed on error).
+ * Returns true on match, else false.
+ */
+bool
+fd_matches_tty(int fd, struct stat *tty_sb, struct stat *fd_sb)
+{
+ debug_decl(fd_is_user_tty, SUDO_DEBUG_EXEC);
+
+ if (fstat(fd, fd_sb) == -1) {
+ /* Always initialize fd_sb. */
+ memset(fd_sb, 0, sizeof(*fd_sb));
+ debug_return_bool(false);
+ }
+ if (!S_ISCHR(fd_sb->st_mode))
+ debug_return_bool(false);
+
+ /* Compare with tty_sb if available, else just check that fd is a tty. */
+ debug_return_bool(tty_sb ? tty_sb->st_rdev == fd_sb->st_rdev : isatty(fd));
+}
+
+/*
+ * If we are not running the command in a pty, we were not invoked as
+ * sudoedit, there is no command timeout and there is no close function,
+ * sudo can exec the command directly (and not wait).
+ */
+static bool
+direct_exec_allowed(const struct command_details *details)
+{
+ struct plugin_container *plugin;
+ debug_decl(direct_exec_allowed, SUDO_DEBUG_EXEC);
+
+ /* Assumes sudo_needs_pty() was already checked. */
+ if (ISSET(details->flags, CD_RBAC_ENABLED|CD_SET_TIMEOUT|CD_SUDOEDIT) ||
+ policy_plugin.u.policy->close != NULL)
+ debug_return_bool(false);
+
+ TAILQ_FOREACH(plugin, &audit_plugins, entries) {
+ if (plugin->u.audit->close != NULL)
+ debug_return_bool(false);
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Execute a command, potentially in a pty with I/O logging, and
+ * wait for it to finish.
+ * This is a little bit tricky due to how POSIX job control works and
+ * we fact that we have two different controlling terminals to deal with.
+ */
+int
+sudo_execute(struct command_details *details,
+ const struct user_details *user_details,
+ struct sudo_event_base *evbase, struct command_status *cstat)
+{
+ debug_decl(sudo_execute, SUDO_DEBUG_EXEC);
+
+#if defined(HAVE_SELINUX) && !defined(HAVE_PTRACE_INTERCEPT)
+ /*
+ * SELinux prevents LD_PRELOAD from functioning so we must use
+ * ptrace-based intercept mode.
+ */
+ if (details->selinux_role != NULL || details->selinux_type != NULL) {
+ if (ISSET(details->flags, CD_INTERCEPT)) {
+ sudo_warnx("%s",
+ U_("intercept mode is not supported with SELinux RBAC on this system"));
+ CLR(details->flags, CD_INTERCEPT);
+ }
+ if (ISSET(details->flags, CD_LOG_SUBCMDS)) {
+ sudo_warnx("%s",
+ U_("unable to log sub-commands with SELinux RBAC on this system"));
+ CLR(details->flags, CD_LOG_SUBCMDS);
+ }
+ }
+#endif /* HAVE_SELINUX && !HAVE_PTRACE_INTERCEPT */
+
+ /* If running in background mode, fork and exit. */
+ if (ISSET(details->flags, CD_BACKGROUND)) {
+ switch (sudo_debug_fork()) {
+ case -1:
+ cstat->type = CMD_ERRNO;
+ cstat->val = errno;
+ debug_return_int(-1);
+ case 0:
+ /*
+ * Child continues in an orphaned process group.
+ * Reads from the terminal fail with EIO.
+ * Writes succeed unless tostop is set on the terminal.
+ */
+ (void)setpgid(0, 0);
+ break;
+ default:
+ /* parent exits (but does not flush buffers) */
+ sudo_debug_exit_int(__func__, __FILE__, __LINE__,
+ sudo_debug_subsys, 0);
+ _exit(EXIT_SUCCESS);
+ }
+ }
+
+ /*
+ * Restore resource limits before running.
+ * We must do this *before* calling the PAM session module.
+ */
+ restore_limits();
+
+ /*
+ * Run the command in a new pty if there is an I/O plugin or the policy
+ * has requested a pty. If /dev/tty is unavailable and no I/O plugin
+ * is configured, this returns false and we run the command without a pty.
+ */
+ if (sudo_needs_pty(details)) {
+ if (exec_pty(details, user_details, evbase, cstat))
+ goto done;
+ }
+
+ /*
+ * If we are not running the command in a pty, we may be able to
+ * exec directly, depending on the plugins used.
+ */
+ if (direct_exec_allowed(details)) {
+ if (!sudo_terminated(cstat)) {
+ exec_cmnd(details, NULL, -1, -1);
+ cstat->type = CMD_ERRNO;
+ cstat->val = errno;
+ }
+ goto done;
+ }
+
+ /*
+ * Run the command in the existing tty (if any) and wait for it to finish.
+ */
+ exec_nopty(details, user_details, evbase, cstat);
+
+done:
+ /* The caller will run any plugin close functions. */
+ debug_return_int(cstat->type == CMD_ERRNO ? -1 : 0);
+}
+
+/*
+ * Kill command with increasing urgency.
+ */
+void
+terminate_command(pid_t pid, bool use_pgrp)
+{
+ debug_decl(terminate_command, SUDO_DEBUG_EXEC);
+
+ /* Avoid killing more than a single process or process group. */
+ if (pid <= 0)
+ debug_return;
+
+ /*
+ * Note that SIGCHLD will interrupt the sleep()
+ */
+ if (use_pgrp) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "killpg %d SIGHUP", (int)pid);
+ killpg(pid, SIGHUP);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "killpg %d SIGTERM", (int)pid);
+ killpg(pid, SIGTERM);
+ sleep(2);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "killpg %d SIGKILL", (int)pid);
+ killpg(pid, SIGKILL);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "kill %d SIGHUP", (int)pid);
+ kill(pid, SIGHUP);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "kill %d SIGTERM", (int)pid);
+ kill(pid, SIGTERM);
+ sleep(2);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "kill %d SIGKILL", (int)pid);
+ kill(pid, SIGKILL);
+ }
+
+ debug_return;
+}
+
+/*
+ * Free the dynamically-allocated contents of the exec closure.
+ */
+void
+free_exec_closure(struct exec_closure *ec)
+{
+ debug_decl(free_exec_closure, SUDO_DEBUG_EXEC);
+
+ /* Free any remaining intercept resources. */
+ intercept_cleanup(ec);
+
+ sudo_ev_base_free(ec->evbase);
+ sudo_ev_free(ec->backchannel_event);
+ sudo_ev_free(ec->fwdchannel_event);
+ sudo_ev_free(ec->sigint_event);
+ sudo_ev_free(ec->sigquit_event);
+ sudo_ev_free(ec->sigtstp_event);
+ sudo_ev_free(ec->sigterm_event);
+ sudo_ev_free(ec->sighup_event);
+ sudo_ev_free(ec->sigalrm_event);
+ sudo_ev_free(ec->sigpipe_event);
+ sudo_ev_free(ec->sigusr1_event);
+ sudo_ev_free(ec->sigusr2_event);
+ sudo_ev_free(ec->sigchld_event);
+ sudo_ev_free(ec->sigcont_event);
+ sudo_ev_free(ec->siginfo_event);
+ sudo_ev_free(ec->sigwinch_event);
+ free(ec->ptyname);
+
+ debug_return;
+}
diff --git a/src/exec_common.c b/src/exec_common.c
new file mode 100644
index 0000000..9e2d954
--- /dev/null
+++ b/src/exec_common.c
@@ -0,0 +1,136 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_PRIV_SET
+# include <priv.h>
+#endif
+#include <errno.h>
+
+#include <sudo.h>
+#include <sudo_exec.h>
+
+/*
+ * Disable execution of child processes in the command we are about
+ * to run. On systems with privilege sets, we can remove the exec
+ * privilege. On other systems we use LD_PRELOAD and the like.
+ */
+char **
+disable_execute(char *envp[], const char *dso)
+{
+ debug_decl(disable_execute, SUDO_DEBUG_UTIL);
+
+#ifdef HAVE_PRIV_SET
+ /* Solaris privileges, remove PRIV_PROC_EXEC post-execve. */
+ (void)priv_set(PRIV_ON, PRIV_INHERITABLE, "PRIV_FILE_DAC_READ", NULL);
+ (void)priv_set(PRIV_ON, PRIV_INHERITABLE, "PRIV_FILE_DAC_WRITE", NULL);
+ (void)priv_set(PRIV_ON, PRIV_INHERITABLE, "PRIV_FILE_DAC_SEARCH", NULL);
+ if (priv_set(PRIV_OFF, PRIV_LIMIT, "PRIV_PROC_EXEC", NULL) == 0)
+ debug_return_ptr(envp);
+ sudo_warn("%s", U_("unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"));
+#endif /* HAVE_PRIV_SET */
+
+#ifdef RTLD_PRELOAD_VAR
+ if (dso != NULL)
+ envp = sudo_preload_dso(envp, dso, -1);
+#endif /* RTLD_PRELOAD_VAR */
+
+ debug_return_ptr(envp);
+}
+
+/*
+ * Trap execution of child processes in the command we are about to run.
+ * Uses LD_PRELOAD and the like to perform a policy check on child commands.
+ */
+static char **
+enable_intercept(char *envp[], const char *dso, int intercept_fd)
+{
+ debug_decl(enable_intercept, SUDO_DEBUG_UTIL);
+
+ if (dso != NULL) {
+#ifdef RTLD_PRELOAD_VAR
+ if (intercept_fd == -1)
+ sudo_fatalx("%s: no intercept fd", __func__);
+
+ envp = sudo_preload_dso(envp, dso, intercept_fd);
+#else
+ /* Intercept not supported, envp unchanged. */
+ if (intercept_fd != -1)
+ close(intercept_fd);
+#endif /* RTLD_PRELOAD_VAR */
+ }
+
+ debug_return_ptr(envp);
+}
+
+/*
+ * Like execve(2) but falls back to running through /bin/sh
+ * ala execvp(3) if we get ENOEXEC.
+ */
+int
+sudo_execve(int fd, const char *path, char *const argv[], char *envp[],
+ int intercept_fd, unsigned int flags)
+{
+ debug_decl(sudo_execve, SUDO_DEBUG_UTIL);
+
+ sudo_debug_execve(SUDO_DEBUG_INFO, path, argv, envp);
+
+ /* Modify the environment as needed to trap execve(). */
+ if (ISSET(flags, CD_NOEXEC))
+ envp = disable_execute(envp, sudo_conf_noexec_path());
+ if (ISSET(flags, CD_INTERCEPT|CD_LOG_SUBCMDS)) {
+ if (!ISSET(flags, CD_USE_PTRACE)) {
+ envp = enable_intercept(envp, sudo_conf_intercept_path(),
+ intercept_fd);
+ }
+ }
+
+#ifdef HAVE_FEXECVE
+ if (fd != -1)
+ fexecve(fd, argv, envp);
+ else
+#endif
+ execve(path, argv, envp);
+ if (fd == -1 && errno == ENOEXEC) {
+ int argc;
+ const char **nargv;
+
+ for (argc = 0; argv[argc] != NULL; argc++)
+ continue;
+ nargv = reallocarray(NULL, (size_t)argc + 2, sizeof(char *));
+ if (nargv != NULL) {
+ nargv[0] = "sh";
+ nargv[1] = path;
+ memcpy(nargv + 2, argv + 1, (size_t)argc * sizeof(char *));
+ execve(_PATH_SUDO_BSHELL, (char **)nargv, envp);
+ free(nargv);
+ }
+ }
+ debug_return_int(-1);
+}
diff --git a/src/exec_intercept.c b/src/exec_intercept.c
new file mode 100644
index 0000000..de9d894
--- /dev/null
+++ b/src/exec_intercept.c
@@ -0,0 +1,1109 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#include <sudo.h>
+#include <sudo_exec.h>
+#include <sudo_plugin.h>
+#include <sudo_plugin_int.h>
+#include <sudo_rand.h>
+#include <intercept.pb-c.h>
+#include <exec_intercept.h>
+
+#ifdef _PATH_SUDO_INTERCEPT
+static union sudo_token_un intercept_token;
+static in_port_t intercept_listen_port;
+static struct intercept_closure *accept_closure;
+static void intercept_accept_cb(int fd, int what, void *v);
+static void intercept_cb(int fd, int what, void *v);
+
+/*
+ * Enable the closure->ev event with the specified events and callback,
+ * and set the connection state to new_state if it is valid.
+ * Returns true on success, else false.
+ */
+static bool
+intercept_enable_event(int fd, short events, enum intercept_state new_state,
+ sudo_ev_callback_t callback, struct intercept_closure *closure)
+{
+ int rc;
+ debug_decl(intercept_enable_event, SUDO_DEBUG_EXEC);
+
+ rc = sudo_ev_set(&closure->ev, fd, events, callback, closure);
+ if (rc == -1 || sudo_ev_add(NULL, &closure->ev, NULL, false) == -1) {
+ sudo_warn("%s", U_("unable to add event to queue"));
+ debug_return_bool(false);
+ }
+ if (new_state != INVALID_STATE)
+ closure->state = new_state;
+ debug_return_bool(true);
+}
+
+static bool
+enable_read_event(int fd, enum intercept_state new_state,
+ sudo_ev_callback_t callback, struct intercept_closure *closure)
+{
+ return intercept_enable_event(fd, SUDO_EV_READ|SUDO_EV_PERSIST,
+ new_state, callback, closure);
+}
+
+static bool
+enable_write_event(int fd, sudo_ev_callback_t callback,
+ struct intercept_closure *closure)
+{
+ return intercept_enable_event(fd, SUDO_EV_WRITE|SUDO_EV_PERSIST,
+ INVALID_STATE, callback, closure);
+}
+
+/*
+ * Create an intercept closure.
+ * Returns an opaque pointer to the closure, which is also
+ * passed to the event callback when not using ptrace(2).
+ */
+void *
+intercept_setup(int fd, struct sudo_event_base *evbase,
+ const struct command_details *details)
+{
+ struct intercept_closure *closure;
+ debug_decl(intercept_setup, SUDO_DEBUG_EXEC);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "intercept fd %d\n", fd);
+
+ closure = calloc(1, sizeof(*closure));
+ if (closure == NULL) {
+ sudo_warnx("%s", U_("unable to allocate memory"));
+ goto bad;
+ }
+ closure->details = details;
+ closure->listen_sock = -1;
+ sudo_ev_set_base(&closure->ev, evbase);
+
+ if (ISSET(details->flags, CD_USE_PTRACE)) {
+ /*
+ * We can perform a policy check immediately using ptrace(2)
+ * but should ignore the execve(2) of the initial command
+ * (and sesh for SELinux RBAC).
+ */
+ closure->state = RECV_POLICY_CHECK;
+ closure->initial_command = 1;
+ if (ISSET(details->flags, CD_RBAC_ENABLED))
+ closure->initial_command++;
+ } else {
+ /*
+ * Not using ptrace(2), use LD_PRELOAD (or its equivalent). If
+ * we've already seen an InterceptHello, expect a policy check first.
+ */
+ const int new_state = sudo_token_isset(intercept_token) ?
+ RECV_SECRET : RECV_HELLO_INITIAL;
+ if (!enable_read_event(fd, new_state, intercept_cb, closure))
+ goto bad;
+ }
+
+ debug_return_ptr(closure);
+
+bad:
+ free(closure);
+ debug_return_ptr(NULL);
+}
+
+/*
+ * Reset intercept_closure so it can be re-used.
+ */
+void
+intercept_closure_reset(struct intercept_closure *closure)
+{
+ size_t n;
+ debug_decl(intercept_closure_reset, SUDO_DEBUG_EXEC);
+
+ if (closure->listen_sock != -1) {
+ close(closure->listen_sock);
+ closure->listen_sock = -1;
+ }
+ free(closure->buf);
+ free(closure->command);
+ if (closure->run_argv != NULL) {
+ for (n = 0; closure->run_argv[n] != NULL; n++)
+ free(closure->run_argv[n]);
+ free(closure->run_argv);
+ }
+ if (closure->run_envp != NULL) {
+ for (n = 0; closure->run_envp[n] != NULL; n++)
+ free(closure->run_envp[n]);
+ free(closure->run_envp);
+ }
+ closure->errstr = NULL;
+ closure->command = NULL;
+ closure->run_argv = NULL;
+ closure->run_envp = NULL;
+ closure->buf = NULL;
+ closure->len = 0;
+ closure->off = 0;
+ /* Does not currently reset token. */
+
+ debug_return;
+}
+
+/*
+ * Close intercept socket and free closure when we are done with
+ * the connection.
+ */
+static void
+intercept_connection_close(struct intercept_closure *closure)
+{
+ const int fd = sudo_ev_get_fd(&closure->ev);
+ debug_decl(intercept_connection_close, SUDO_DEBUG_EXEC);
+
+ sudo_ev_del(NULL, &closure->ev);
+ close(fd);
+ intercept_closure_reset(closure);
+ free(closure);
+
+ debug_return;
+}
+
+void
+intercept_cleanup(struct exec_closure *ec)
+{
+ debug_decl(intercept_cleanup, SUDO_DEBUG_EXEC);
+
+ if (accept_closure != NULL) {
+ /* DSO-based intercept. */
+ intercept_connection_close(accept_closure);
+ accept_closure = NULL;
+ } else if (ec->intercept != NULL) {
+ /* ptrace-based intercept. */
+ intercept_closure_reset(ec->intercept);
+ free(ec->intercept);
+ ec->intercept = NULL;
+ }
+
+ debug_return;
+}
+
+/*
+ * Prepare to listen on localhost using an ephemeral port.
+ * Sets intercept_token and intercept_listen_port as side effects.
+ */
+static bool
+prepare_listener(struct intercept_closure *closure)
+{
+ struct sockaddr_in sin4;
+ socklen_t sin4_len = sizeof(sin4);
+ int sock;
+ debug_decl(prepare_listener, SUDO_DEBUG_EXEC);
+
+ /* Generate a random token. */
+ do {
+ arc4random_buf(&intercept_token, sizeof(intercept_token));
+ } while (!sudo_token_isset(intercept_token));
+
+ /* Create localhost listener socket (currently AF_INET only). */
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock == -1) {
+ sudo_warn("socket");
+ goto bad;
+ }
+ memset(&sin4, 0, sizeof(sin4));
+ sin4.sin_family = AF_INET;
+ sin4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ sin4.sin_port = 0;
+ if (bind(sock, (struct sockaddr *)&sin4, sizeof(sin4)) == -1) {
+ sudo_warn("bind");
+ goto bad;
+ }
+ if (getsockname(sock, (struct sockaddr *)&sin4, &sin4_len) == -1) {
+ sudo_warn("getsockname");
+ goto bad;
+ }
+ if (listen(sock, SOMAXCONN) == -1) {
+ sudo_warn("listen");
+ goto bad;
+ }
+
+ closure->listen_sock = sock;
+ intercept_listen_port = ntohs(sin4.sin_port);
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "%s: listening on port %hu", __func__, intercept_listen_port);
+
+ debug_return_bool(true);
+
+bad:
+ if (sock != -1)
+ close(sock);
+ debug_return_bool(false);
+}
+
+/*
+ * Allocate a new command_info[] and update command and runcwd in it.
+ * Fills in cmnd_out with a copy of the command if not NULL.
+ * Returns the new command_info[] which the caller must free.
+ */
+static char **
+update_command_info(char * const *old_command_info, const char *cmnd,
+ const char *runcwd, char **cmnd_out, struct intercept_closure *closure)
+{
+ char **command_info;
+ char * const *oci;
+ size_t n;
+ debug_decl(update_command_info, SUDO_DEBUG_EXEC);
+
+ /* Rebuild command_info[] with new command and add a runcwd. */
+ for (n = 0; old_command_info[n] != NULL; n++)
+ continue;
+ command_info = reallocarray(NULL, n + 3, sizeof(char *));
+ if (command_info == NULL) {
+ goto bad;
+ }
+ for (oci = old_command_info, n = 0; *oci != NULL; oci++) {
+ const char *cp = *oci;
+ switch (*cp) {
+ case 'c':
+ if (strncmp(cp, "command=", sizeof("command=") - 1) == 0) {
+ if (cmnd == NULL) {
+ /* No new command specified, use old value. */
+ cmnd = cp + sizeof("command=") - 1;
+ }
+ /* Filled in at the end. */
+ continue;
+ }
+ break;
+ case 'r':
+ if (strncmp(cp, "runcwd=", sizeof("runcwd=") - 1) == 0) {
+ /* Filled in at the end. */
+ continue;
+ }
+ break;
+ }
+ command_info[n] = strdup(cp);
+ if (command_info[n] == NULL) {
+ goto bad;
+ }
+ n++;
+ }
+
+ /* Append new command. */
+ if (cmnd == NULL) {
+ closure->errstr = N_("command not set by the security policy");
+ goto bad;
+ }
+ command_info[n] = sudo_new_key_val("command", cmnd);
+ if (command_info[n] == NULL) {
+ goto oom;
+ }
+ n++;
+
+ /* Append actual runcwd. */
+ command_info[n] = sudo_new_key_val("runcwd", runcwd ? runcwd : "unknown");
+ if (command_info[n] == NULL) {
+ goto oom;
+ }
+ n++;
+
+ command_info[n] = NULL;
+
+ if (cmnd_out != NULL) {
+ *cmnd_out = strdup(cmnd);
+ if (*cmnd_out == NULL) {
+ goto oom;
+ }
+ }
+ debug_return_ptr(command_info);
+
+oom:
+ closure->errstr = N_("unable to allocate memory");
+
+bad:
+ if (command_info != NULL) {
+ for (n = 0; command_info[n] != NULL; n++) {
+ free(command_info[n]);
+ }
+ free(command_info);
+ }
+ debug_return_ptr(NULL);
+}
+
+/*
+ * Perform a policy check for the given command.
+ * While argv must be NULL-terminated, envp need not be.
+ * Sets closure->state to the result of the policy check before returning.
+ * Return false on error, else true.
+ */
+bool
+intercept_check_policy(const char *command, int argc, char **argv, int envc,
+ char **envp, const char *runcwd, int *oldcwd, void *v)
+{
+ struct intercept_closure *closure = v;
+ char **command_info = NULL;
+ char **command_info_copy = NULL;
+ char **user_env_out = NULL;
+ char **run_argv = NULL;
+ int rc, saved_dir = -1;
+ size_t i;
+ bool ret = true;
+ struct stat sb;
+ debug_decl(intercept_check_policy, SUDO_DEBUG_EXEC);
+
+ /* Change to runcwd before the policy check if necessary. */
+ if (*command != '/') {
+ if (runcwd == NULL || (saved_dir = open(".", O_RDONLY)) == -1 ||
+ chdir(runcwd) == -1) {
+ if (runcwd == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "relative command path but no runcwd specified");
+ } else if (saved_dir == -1) {
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to open current directory for reading");
+ } else {
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to chdir for %s", runcwd);
+ }
+ if (ISSET(closure->details->flags, CD_INTERCEPT)) {
+ /* Inability to change cwd is fatal in intercept mode. */
+ if (closure->errstr == NULL)
+ closure->errstr = N_("command rejected by policy");
+ audit_reject(policy_plugin.name, SUDO_POLICY_PLUGIN,
+ closure->errstr, closure->details->info);
+ closure->state = POLICY_REJECT;
+ goto done;
+ }
+ }
+ }
+
+ /*
+ * Short-circuit the policy check if the command doesn't exist.
+ * Otherwise, both sudo and the shell will report the error.
+ */
+ if (stat(command, &sb) == -1) {
+ closure->errstr = NULL;
+ closure->state = POLICY_ERROR;
+ goto done;
+ }
+
+ if (ISSET(closure->details->flags, CD_INTERCEPT)) {
+ /* We don't currently have a good way to validate the environment. */
+ sudo_debug_set_active_instance(policy_plugin.debug_instance);
+ rc = policy_plugin.u.policy->check_policy(argc, argv, NULL,
+ &command_info, &run_argv, &user_env_out, &closure->errstr);
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "check_policy returns %d", rc);
+
+ switch (rc) {
+ case 1:
+ /* Rebuild command_info[] with runcwd and extract command. */
+ command_info_copy = update_command_info(command_info, NULL,
+ runcwd, &closure->command, closure);
+ if (command_info_copy == NULL)
+ goto oom;
+ command_info = command_info_copy;
+ closure->state = POLICY_ACCEPT;
+ break;
+ case 0:
+ if (closure->errstr == NULL)
+ closure->errstr = N_("command rejected by policy");
+ audit_reject(policy_plugin.name, SUDO_POLICY_PLUGIN,
+ closure->errstr, command_info);
+ closure->state = POLICY_REJECT;
+ goto done;
+ default:
+ /* Plugin error? */
+ goto bad;
+ }
+ } else {
+ /* No actual policy check, just logging child processes. */
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "not checking policy, audit only");
+ closure->command = strdup(command);
+ if (closure->command == NULL)
+ goto oom;
+
+ /* Rebuild command_info[] with new command and runcwd. */
+ command_info_copy = update_command_info(closure->details->info,
+ command, runcwd, NULL, closure);
+ if (command_info_copy == NULL)
+ goto oom;
+ command_info = command_info_copy;
+ closure->state = POLICY_ACCEPT;
+ run_argv = argv;
+ }
+
+ if (sudo_debug_needed(SUDO_DEBUG_INFO)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "run_command: %s", closure->command);
+ for (i = 0; command_info[i] != NULL; i++) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "command_info[%zu]: %s", i, command_info[i]);
+ }
+ for (i = 0; run_argv[i] != NULL; i++) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "run_argv[%zu]: %s", i, run_argv[i]);
+ }
+ }
+
+ /* Make a copy of run_argv, it may share contents of argv. */
+ for (i = 0; run_argv[i] != NULL; i++)
+ continue;
+ closure->run_argv = reallocarray(NULL, i + 1, sizeof(char *));
+ if (closure->run_argv == NULL)
+ goto oom;
+ for (i = 0; run_argv[i] != NULL; i++) {
+ closure->run_argv[i] = strdup(run_argv[i]);
+ if (closure->run_argv[i] == NULL)
+ goto oom;
+ }
+ closure->run_argv[i] = NULL;
+
+ /* Make a copy of envp, which may not be NULL-terminated. */
+ closure->run_envp = reallocarray(NULL, (size_t)envc + 1, sizeof(char *));
+ if (closure->run_envp == NULL)
+ goto oom;
+ for (i = 0; i < (size_t)envc; i++) {
+ closure->run_envp[i] = strdup(envp[i]);
+ if (closure->run_envp[i] == NULL)
+ goto oom;
+ }
+ closure->run_envp[i] = NULL;
+
+ if (ISSET(closure->details->flags, CD_INTERCEPT)) {
+ audit_accept(policy_plugin.name, SUDO_POLICY_PLUGIN, command_info,
+ closure->run_argv, closure->run_envp);
+
+ /* Call approval plugins and audit the result. */
+ if (!approval_check(command_info, closure->run_argv, closure->run_envp)) {
+ if (closure->errstr == NULL)
+ closure->errstr = N_("approval plugin error");
+ closure->state = POLICY_REJECT;
+ goto done;
+ }
+ }
+
+ /* Audit the event again for the sudo front-end. */
+ audit_accept("sudo", SUDO_FRONT_END, command_info, closure->run_argv,
+ closure->run_envp);
+
+ goto done;
+
+oom:
+ closure->errstr = N_("unable to allocate memory");
+
+bad:
+ if (saved_dir != -1) {
+ if (fchdir(saved_dir) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to restore saved cwd", __func__);
+ }
+ close(saved_dir);
+ saved_dir = -1;
+ }
+ if (closure->errstr == NULL)
+ closure->errstr = N_("policy plugin error");
+ audit_error(policy_plugin.name, SUDO_POLICY_PLUGIN, closure->errstr,
+ command_info ? command_info : closure->details->info);
+ closure->state = POLICY_ERROR;
+ ret = false;
+
+done:
+ if (command_info_copy != NULL) {
+ for (i = 0; command_info_copy[i] != NULL; i++) {
+ free(command_info_copy[i]);
+ }
+ free(command_info_copy);
+ }
+ *oldcwd = saved_dir;
+
+ debug_return_bool(ret);
+}
+
+static bool
+intercept_check_policy_req(PolicyCheckRequest *req,
+ struct intercept_closure *closure)
+{
+ char **argv = NULL;
+ bool ret = false;
+ int oldcwd = -1;
+ size_t n;
+ debug_decl(intercept_check_policy_req, SUDO_DEBUG_EXEC);
+
+ if (req->command == NULL || req->n_argv > INT_MAX || req->n_envp > INT_MAX) {
+ closure->errstr = N_("invalid PolicyCheckRequest");
+ goto done;
+ }
+
+ if (sudo_debug_needed(SUDO_DEBUG_INFO)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "req_command: %s", req->command);
+ for (n = 0; n < req->n_argv; n++) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "req_argv[%zu]: %s", n, req->argv[n]);
+ }
+ }
+
+ /* If argv is empty, reserve an extra slot for the command. */
+ if (req->n_argv == 0)
+ req->n_argv = 1;
+
+ /*
+ * Rebuild argv from PolicyCheckReq so it is NULL-terminated.
+ * The plugin API requires us to pass the pathname to exec in argv[0].
+ */
+ argv = reallocarray(NULL, req->n_argv + 1, sizeof(char *));
+ if (argv == NULL) {
+ closure->errstr = N_("unable to allocate memory");
+ goto done;
+ }
+ argv[0] = req->command;
+ for (n = 1; n < req->n_argv; n++) {
+ argv[n] = req->argv[n];
+ }
+ argv[n] = NULL;
+
+ ret = intercept_check_policy(req->command, (int)req->n_argv, argv,
+ (int)req->n_envp, req->envp, req->cwd, &oldcwd, closure);
+
+done:
+ if (oldcwd != -1) {
+ if (fchdir(oldcwd) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to restore saved cwd", __func__);
+ }
+ close(oldcwd);
+ }
+
+ free(argv);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Read token from sudo_intercept.so and verify w/ intercept_token.
+ * Returns true on success, false on mismatch and -1 on error.
+ */
+static int
+intercept_verify_token(int fd, struct intercept_closure *closure)
+{
+ ssize_t nread;
+ debug_decl(intercept_verify_token, SUDO_DEBUG_EXEC);
+
+ nread = recv(fd, closure->token.u8 + closure->off,
+ sizeof(closure->token) - closure->off, 0);
+ switch (nread) {
+ case 0:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "EOF reading token");
+ debug_return_int(false);
+ case -1:
+ debug_return_int(-1);
+ default:
+ if (nread + closure->off == sizeof(closure->token))
+ break;
+ /* partial read, update offset and try again */
+ closure->off += (uint32_t)nread;
+ errno = EAGAIN;
+ debug_return_int(-1);
+ }
+
+ closure->off = 0;
+ if (memcmp(&closure->token, &intercept_token, sizeof(closure->token)) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "token mismatch: got 0x%8x%8x%8x%8x, expected 0x%8x%8x%8x%8x",
+ closure->token.u32[3], closure->token.u32[2],
+ closure->token.u32[1], closure->token.u32[0],
+ intercept_token.u32[3], intercept_token.u32[2],
+ intercept_token.u32[1], intercept_token.u32[0]);
+ debug_return_int(false);
+ }
+ debug_return_int(true);
+}
+
+/*
+ * Read a message from sudo_intercept.so and act on it.
+ */
+static bool
+intercept_read(int fd, struct intercept_closure *closure)
+{
+ InterceptRequest *req = NULL;
+ bool ret = false;
+ ssize_t nread;
+ debug_decl(intercept_read, SUDO_DEBUG_EXEC);
+
+ if (closure->state == RECV_SECRET) {
+ switch (intercept_verify_token(fd, closure)) {
+ case true:
+ closure->state = RECV_POLICY_CHECK;
+ break;
+ case false:
+ goto done;
+ default:
+ if (errno == EINTR || errno == EAGAIN) {
+ sudo_debug_printf(
+ SUDO_DEBUG_WARN|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "reading intercept token");
+ debug_return_bool(true);
+ }
+ sudo_warn("recv");
+ goto done;
+ }
+ }
+
+ if (closure->len == 0) {
+ uint32_t req_len;
+
+ /* Read message size (uint32_t in host byte order). */
+ nread = recv(fd, &req_len, sizeof(req_len), 0);
+ if (nread != sizeof(req_len)) {
+ if (nread == -1) {
+ if (errno == EINTR || errno == EAGAIN) {
+ sudo_debug_printf(
+ SUDO_DEBUG_WARN|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "reading intercept message size");
+ debug_return_bool(true);
+ }
+ sudo_warn("recv");
+ }
+ goto done;
+ }
+
+ if (req_len == 0) {
+ /* zero-length message is possible */
+ goto unpack;
+ }
+ if (req_len > MESSAGE_SIZE_MAX) {
+ sudo_warnx(U_("client request too large: %zu"), (size_t)req_len);
+ goto done;
+ }
+ if ((closure->buf = malloc(req_len)) == NULL) {
+ sudo_warnx("%s", U_("unable to allocate memory"));
+ goto done;
+ }
+ closure->len = req_len;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: expecting %u bytes from client",
+ __func__, closure->len);
+ }
+
+ nread = recv(fd, closure->buf + closure->off, closure->len - closure->off,
+ 0);
+ switch (nread) {
+ case 0:
+ /* EOF, other side must have exited. */
+ goto done;
+ case -1:
+ if (errno == EINTR || errno == EAGAIN) {
+ sudo_debug_printf(
+ SUDO_DEBUG_WARN|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "reading intercept message");
+ debug_return_bool(true);
+ }
+ sudo_warn("recv");
+ goto done;
+ default:
+ closure->off += (uint32_t)nread;
+ break;
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: received %zd bytes from client",
+ __func__, nread);
+
+ if (closure->off != closure->len) {
+ /* Partial read. */
+ debug_return_bool(true);
+ }
+
+unpack:
+ req = intercept_request__unpack(NULL, closure->len, closure->buf);
+ if (req == NULL) {
+ sudo_warnx(U_("unable to unpack %s size %zu"), "InterceptRequest",
+ (size_t)closure->len);
+ goto done;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: finished receiving %u bytes from client", __func__, closure->len);
+ sudo_ev_del(NULL, &closure->ev);
+ free(closure->buf);
+ closure->buf = NULL;
+ closure->len = 0;
+ closure->off = 0;
+
+ switch (req->type_case) {
+ case INTERCEPT_REQUEST__TYPE_POLICY_CHECK_REQ:
+ if (closure->state != RECV_POLICY_CHECK) {
+ /* Only a single policy check request is allowed. */
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "state mismatch, expected RECV_POLICY_CHECK (%d), got %d",
+ RECV_POLICY_CHECK, closure->state);
+ goto done;
+ }
+
+ ret = intercept_check_policy_req(req->u.policy_check_req, closure);
+ if (!ret)
+ goto done;
+ if (!ISSET(closure->details->flags, CD_INTERCEPT)) {
+ /* Just logging, re-use event to read next InterceptHello. */
+ ret = enable_read_event(fd, RECV_HELLO, intercept_cb, closure);
+ goto done;
+ }
+ break;
+ case INTERCEPT_REQUEST__TYPE_HELLO:
+ switch (closure->state) {
+ case RECV_HELLO_INITIAL:
+ if (!prepare_listener(closure))
+ goto done;
+ break;
+ case RECV_HELLO:
+ break;
+ default:
+ /* Only accept hello on a socket with an accepted command. */
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "got InterceptHello without an accepted command");
+ goto done;
+ }
+ break;
+ default:
+ sudo_warnx(U_("unexpected type_case value %d in %s from %s"),
+ req->type_case, "InterceptRequest", "sudo_intercept.so");
+ goto done;
+ }
+
+ /* Switch event to write mode for the reply. */
+ if (!enable_write_event(fd, intercept_cb, closure))
+ goto done;
+
+ ret = true;
+
+done:
+ intercept_request__free_unpacked(req, NULL);
+ debug_return_bool(ret);
+}
+
+static bool
+fmt_intercept_response(InterceptResponse *resp,
+ struct intercept_closure *closure)
+{
+ uint32_t resp_len;
+ bool ret = false;
+ debug_decl(fmt_intercept_response, SUDO_DEBUG_EXEC);
+
+ closure->len = (uint32_t)intercept_response__get_packed_size(resp);
+ if (closure->len > MESSAGE_SIZE_MAX) {
+ sudo_warnx(U_("server message too large: %zu"), (size_t)closure->len);
+ goto done;
+ }
+
+ /* Wire message size is used for length encoding, precedes message. */
+ resp_len = closure->len;
+ closure->len += sizeof(resp_len);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "size + InterceptResponse %zu bytes", (size_t)closure->len);
+
+ if ((closure->buf = malloc(closure->len)) == NULL) {
+ sudo_warnx("%s", U_("unable to allocate memory"));
+ goto done;
+ }
+ memcpy(closure->buf, &resp_len, sizeof(resp_len));
+ intercept_response__pack(resp, closure->buf + sizeof(resp_len));
+
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+static bool
+fmt_hello_response(struct intercept_closure *closure)
+{
+ HelloResponse hello_resp = HELLO_RESPONSE__INIT;
+ InterceptResponse resp = INTERCEPT_RESPONSE__INIT;
+ debug_decl(fmt_hello_response, SUDO_DEBUG_EXEC);
+
+ hello_resp.portno = intercept_listen_port;
+ hello_resp.token_lo = intercept_token.u64[0];
+ hello_resp.token_hi = intercept_token.u64[1];
+ hello_resp.log_only = !ISSET(closure->details->flags, CD_INTERCEPT);
+
+ resp.u.hello_resp = &hello_resp;
+ resp.type_case = INTERCEPT_RESPONSE__TYPE_HELLO_RESP;
+
+ debug_return_bool(fmt_intercept_response(&resp, closure));
+}
+
+static bool
+fmt_accept_message(struct intercept_closure *closure)
+{
+ PolicyAcceptMessage msg = POLICY_ACCEPT_MESSAGE__INIT;
+ InterceptResponse resp = INTERCEPT_RESPONSE__INIT;
+ size_t n;
+ debug_decl(fmt_accept_message, SUDO_DEBUG_EXEC);
+
+ msg.run_command = closure->command;
+ msg.run_argv = closure->run_argv;
+ for (n = 0; closure->run_argv[n] != NULL; n++)
+ continue;
+ msg.n_run_argv = n;
+ msg.run_envp = closure->run_envp;
+ for (n = 0; closure->run_envp[n] != NULL; n++)
+ continue;
+ msg.n_run_envp = n;
+
+ resp.u.accept_msg = &msg;
+ resp.type_case = INTERCEPT_RESPONSE__TYPE_ACCEPT_MSG;
+
+ debug_return_bool(fmt_intercept_response(&resp, closure));
+}
+
+static bool
+fmt_reject_message(struct intercept_closure *closure)
+{
+ PolicyRejectMessage msg = POLICY_REJECT_MESSAGE__INIT;
+ InterceptResponse resp = INTERCEPT_RESPONSE__INIT;
+ debug_decl(fmt_reject_message, SUDO_DEBUG_EXEC);
+
+ msg.reject_message = (char *)closure->errstr;
+
+ resp.u.reject_msg = &msg;
+ resp.type_case = INTERCEPT_RESPONSE__TYPE_REJECT_MSG;
+
+ debug_return_bool(fmt_intercept_response(&resp, closure));
+}
+
+static bool
+fmt_error_message(struct intercept_closure *closure)
+{
+ PolicyErrorMessage msg = POLICY_ERROR_MESSAGE__INIT;
+ InterceptResponse resp = INTERCEPT_RESPONSE__INIT;
+ debug_decl(fmt_error_message, SUDO_DEBUG_EXEC);
+
+ msg.error_message = (char *)closure->errstr;
+
+ resp.u.error_msg = &msg;
+ resp.type_case = INTERCEPT_RESPONSE__TYPE_ERROR_MSG;
+
+ debug_return_bool(fmt_intercept_response(&resp, closure));
+}
+
+/*
+ * Write a response to sudo_intercept.so.
+ */
+static bool
+intercept_write(int fd, struct intercept_closure *closure)
+{
+ bool ret = false;
+ ssize_t nwritten;
+ debug_decl(intercept_write, SUDO_DEBUG_EXEC);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, "state %d",
+ closure->state);
+
+ if (closure->len == 0) {
+ /* Format new message. */
+ switch (closure->state) {
+ case RECV_HELLO_INITIAL:
+ case RECV_HELLO:
+ if (!fmt_hello_response(closure))
+ goto done;
+ break;
+ case POLICY_ACCEPT:
+ if (!fmt_accept_message(closure))
+ goto done;
+ break;
+ case POLICY_REJECT:
+ if (!fmt_reject_message(closure))
+ goto done;
+ break;
+ default:
+ if (!fmt_error_message(closure))
+ goto done;
+ break;
+ }
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: sending %u bytes to client",
+ __func__, closure->len - closure->off);
+ nwritten = send(fd, closure->buf + closure->off,
+ closure->len - closure->off, 0);
+ if (nwritten == -1) {
+ if (errno == EINTR || errno == EAGAIN) {
+ sudo_debug_printf(
+ SUDO_DEBUG_WARN|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
+ "writing intercept message");
+ debug_return_bool(true);
+ }
+ sudo_warn("send");
+ goto done;
+ }
+ closure->off += (uint32_t)nwritten;
+
+ if (closure->off != closure->len) {
+ /* Partial write. */
+ debug_return_bool(true);
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: sent %u bytes to client", __func__, closure->len);
+ sudo_ev_del(NULL, &closure->ev);
+ free(closure->buf);
+ closure->buf = NULL;
+ closure->len = 0;
+ closure->off = 0;
+
+ switch (closure->state) {
+ case RECV_HELLO_INITIAL:
+ /* Re-use the listener event. */
+ close(fd);
+ if (!enable_read_event(closure->listen_sock, RECV_CONNECTION,
+ intercept_accept_cb, closure))
+ goto done;
+ closure->listen_sock = -1;
+ closure->state = RECV_CONNECTION;
+ accept_closure = closure;
+ break;
+ case POLICY_ACCEPT:
+ /* Re-use event to read InterceptHello from sudo_intercept.so ctor. */
+ if (!enable_read_event(fd, RECV_HELLO, intercept_cb, closure))
+ goto done;
+ break;
+ default:
+ /* Done with this connection. */
+ intercept_connection_close(closure);
+ }
+
+ ret = true;
+
+done:
+ debug_return_bool(ret);
+}
+
+static void
+intercept_cb(int fd, int what, void *v)
+{
+ struct intercept_closure *closure = v;
+ bool success = false;
+ debug_decl(intercept_cb, SUDO_DEBUG_EXEC);
+
+ switch (what) {
+ case SUDO_EV_READ:
+ success = intercept_read(fd, closure);
+ break;
+ case SUDO_EV_WRITE:
+ success = intercept_write(fd, closure);
+ break;
+ default:
+ sudo_warnx("%s: unexpected event type %d", __func__, what);
+ break;
+ }
+
+ if (!success)
+ intercept_connection_close(closure);
+
+ debug_return;
+}
+
+/*
+ * Accept a new connection from the client register a new event for it.
+ */
+static void
+intercept_accept_cb(int fd, int what, void *v)
+{
+ struct intercept_closure *closure = v;
+ struct sudo_event_base *evbase = sudo_ev_get_base(&closure->ev);
+ struct sockaddr_in sin4;
+ socklen_t sin4_len = sizeof(sin4);
+ int client_sock, flags, on = 1;
+ debug_decl(intercept_accept_cb, SUDO_DEBUG_EXEC);
+
+ if (closure->state != RECV_CONNECTION) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "state mismatch, expected RECV_CONNECTION (%d), got %d",
+ RECV_CONNECTION, closure->state);
+ intercept_connection_close(closure);
+ accept_closure = NULL;
+ debug_return;
+ }
+
+ client_sock = accept(fd, (struct sockaddr *)&sin4, &sin4_len);
+ if (client_sock == -1) {
+ sudo_warn("accept");
+ goto bad;
+ }
+ flags = fcntl(client_sock, F_GETFL, 0);
+ if (flags != -1)
+ (void)fcntl(client_sock, F_SETFL, flags | O_NONBLOCK);
+
+ /* Send data immediately, we need low latency IPC. */
+ (void)setsockopt(client_sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
+
+ /*
+ * Create a new intercept closure and register an event for client_sock.
+ */
+ if (intercept_setup(client_sock, evbase, closure->details) == NULL) {
+ goto bad;
+ }
+
+ debug_return;
+
+bad:
+ if (client_sock != -1)
+ close(client_sock);
+ debug_return;
+}
+#else /* _PATH_SUDO_INTERCEPT */
+void *
+intercept_setup(int fd, struct sudo_event_base *evbase,
+ const struct command_details *details)
+{
+ debug_decl(intercept_setup, SUDO_DEBUG_EXEC);
+
+ /* Intercept support not compiled in. */
+
+ debug_return_ptr(NULL);
+}
+
+void
+intercept_cleanup(struct exec_closure *ec)
+{
+ debug_decl(intercept_cleanup, SUDO_DEBUG_EXEC);
+
+ /* Intercept support not compiled in. */
+
+ debug_return;
+}
+#endif /* _PATH_SUDO_INTERCEPT */
diff --git a/src/exec_intercept.h b/src/exec_intercept.h
new file mode 100644
index 0000000..e7f1732
--- /dev/null
+++ b/src/exec_intercept.h
@@ -0,0 +1,55 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_EXEC_INTERCEPT_H
+#define SUDO_EXEC_INTERCEPT_H
+
+enum intercept_state {
+ INVALID_STATE,
+ RECV_HELLO_INITIAL,
+ RECV_HELLO,
+ RECV_SECRET,
+ RECV_POLICY_CHECK,
+ RECV_CONNECTION,
+ POLICY_ACCEPT,
+ POLICY_REJECT,
+ POLICY_TEST,
+ POLICY_ERROR
+};
+
+/* Closure for intercept_cb() */
+struct intercept_closure {
+ union sudo_token_un token;
+ const struct command_details *details;
+ struct sudo_event ev;
+ const char *errstr;
+ char *command; /* dynamically allocated */
+ char **run_argv; /* owned by plugin */
+ char **run_envp; /* dynamically allocated */
+ uint8_t *buf; /* dynamically allocated */
+ uint32_t len;
+ uint32_t off;
+ int listen_sock;
+ enum intercept_state state;
+ int initial_command;
+};
+
+void intercept_closure_reset(struct intercept_closure *closure);
+bool intercept_check_policy(const char *command, int argc, char **argv, int envc, char **envp, const char *runcwd, int *oldcwd, void *closure);
+
+#endif /* SUDO_EXEC_INTERCEPT_H */
diff --git a/src/exec_iolog.c b/src/exec_iolog.c
new file mode 100644
index 0000000..239fc41
--- /dev/null
+++ b/src/exec_iolog.c
@@ -0,0 +1,612 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include <sudo.h>
+#include <sudo_exec.h>
+#include <sudo_plugin.h>
+#include <sudo_plugin_int.h>
+
+int io_fds[6] = { -1, -1, -1, -1, -1, -1 };
+
+static struct io_buffer_list iobufs = SLIST_HEAD_INITIALIZER(&iobufs);
+
+static sigset_t ttyblock;
+
+/*
+ * Remove and free any events associated with the specified
+ * file descriptor present in the I/O buffers list.
+ */
+void
+ev_free_by_fd(struct sudo_event_base *evbase, int fd)
+{
+ struct io_buffer *iob;
+ debug_decl(ev_free_by_fd, SUDO_DEBUG_EXEC);
+
+ /* Deschedule any users of the fd and free up the events. */
+ SLIST_FOREACH(iob, &iobufs, entries) {
+ if (iob->revent != NULL) {
+ if (sudo_ev_get_fd(iob->revent) == fd) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: deleting and freeing revent %p with fd %d",
+ __func__, iob->revent, fd);
+ sudo_ev_free(iob->revent);
+ iob->revent = NULL;
+ }
+ }
+ if (iob->wevent != NULL) {
+ if (sudo_ev_get_fd(iob->wevent) == fd) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: deleting and freeing wevent %p with fd %d",
+ __func__, iob->wevent, fd);
+ sudo_ev_free(iob->wevent);
+ iob->wevent = NULL;
+ }
+ }
+ }
+ debug_return;
+}
+
+/*
+ * Only close the fd if it is not /dev/tty or std{in,out,err}.
+ * Return value is the same as close(2).
+ */
+int
+safe_close(int fd)
+{
+ debug_decl(safe_close, SUDO_DEBUG_EXEC);
+
+ /* Avoid closing /dev/tty or std{in,out,err}. */
+ if (fd < 3 || fd == io_fds[SFD_USERTTY]) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: not closing fd %d (%s)", __func__, fd, _PATH_TTY);
+ errno = EINVAL;
+ debug_return_int(-1);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: closing fd %d", __func__, fd);
+ debug_return_int(close(fd));
+}
+
+/*
+ * Allocate a new I/O buffer and associated read/write events.
+ */
+void
+io_buf_new(int rfd, int wfd,
+ bool (*action)(const char *, unsigned int, struct io_buffer *),
+ void (*read_cb)(int fd, int what, void *v),
+ void (*write_cb)(int fd, int what, void *v), struct exec_closure *ec)
+{
+ int n;
+ struct io_buffer *iob;
+ debug_decl(io_buf_new, SUDO_DEBUG_EXEC);
+
+ /* Set non-blocking mode. */
+ n = fcntl(rfd, F_GETFL, 0);
+ if (n != -1 && !ISSET(n, O_NONBLOCK))
+ (void) fcntl(rfd, F_SETFL, n | O_NONBLOCK);
+ n = fcntl(wfd, F_GETFL, 0);
+ if (n != -1 && !ISSET(n, O_NONBLOCK))
+ (void) fcntl(wfd, F_SETFL, n | O_NONBLOCK);
+
+ /* Allocate and add to head of list. */
+ if ((iob = malloc(sizeof(*iob))) == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ iob->ec = ec;
+ iob->revent = sudo_ev_alloc(rfd, SUDO_EV_READ|SUDO_EV_PERSIST,
+ read_cb, iob);
+ iob->wevent = sudo_ev_alloc(wfd, SUDO_EV_WRITE|SUDO_EV_PERSIST,
+ write_cb, iob);
+ iob->len = 0;
+ iob->off = 0;
+ iob->action = action;
+ iob->buf[0] = '\0';
+ if (iob->revent == NULL || iob->wevent == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ SLIST_INSERT_HEAD(&iobufs, iob, entries);
+
+ debug_return;
+}
+
+/*
+ * Schedule I/O events before starting the main event loop or
+ * resuming from suspend.
+ */
+void
+add_io_events(struct exec_closure *ec)
+{
+ struct io_buffer *iob;
+ debug_decl(add_io_events, SUDO_DEBUG_EXEC);
+
+ /*
+ * Schedule all readers as long as the buffer is not full.
+ * Schedule writers that contain buffered data.
+ * Normally, write buffers are added on demand when data is read.
+ */
+ SLIST_FOREACH(iob, &iobufs, entries) {
+ /* Don't read from /dev/tty if we are not in the foreground. */
+ if (iob->revent != NULL &&
+ (ec->term_raw || !USERTTY_EVENT(iob->revent))) {
+ if (iob->len != sizeof(iob->buf)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "added I/O revent %p, fd %d, events %d",
+ iob->revent, iob->revent->fd, iob->revent->events);
+ if (sudo_ev_add(ec->evbase, iob->revent, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+ }
+ }
+ if (iob->wevent != NULL) {
+ /* Enable writer if buffer is not empty. */
+ if (iob->len > iob->off) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "added I/O wevent %p, fd %d, events %d",
+ iob->wevent, iob->wevent->fd, iob->wevent->events);
+ if (sudo_ev_add(ec->evbase, iob->wevent, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+ }
+ }
+ }
+ debug_return;
+}
+
+/*
+ * Flush any output buffered in iobufs or readable from fds other
+ * than /dev/tty. Removes I/O events from the event base when done.
+ */
+void
+del_io_events(bool nonblocking)
+{
+ struct io_buffer *iob;
+ struct sudo_event_base *evbase;
+ debug_decl(del_io_events, SUDO_DEBUG_EXEC);
+
+ /* Remove iobufs from existing event base. */
+ SLIST_FOREACH(iob, &iobufs, entries) {
+ if (iob->revent != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "deleted I/O revent %p, fd %d, events %d",
+ iob->revent, iob->revent->fd, iob->revent->events);
+ sudo_ev_del(NULL, iob->revent);
+ }
+ if (iob->wevent != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "deleted I/O wevent %p, fd %d, events %d",
+ iob->wevent, iob->wevent->fd, iob->wevent->events);
+ sudo_ev_del(NULL, iob->wevent);
+ }
+ }
+
+ /* Create temporary event base for flushing. */
+ evbase = sudo_ev_base_alloc();
+ if (evbase == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ /* Avoid reading from /dev/tty, just flush existing data. */
+ SLIST_FOREACH(iob, &iobufs, entries) {
+ /* Don't read from /dev/tty while flushing. */
+ if (iob->revent != NULL && !USERTTY_EVENT(iob->revent)) {
+ if (iob->len != sizeof(iob->buf)) {
+ if (sudo_ev_add(evbase, iob->revent, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+ }
+ }
+ /* Flush any write buffers with data in them. */
+ if (iob->wevent != NULL) {
+ if (iob->len > iob->off) {
+ if (sudo_ev_add(evbase, iob->wevent, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+ }
+ }
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: flushing remaining I/O buffers (nonblocking)", __func__);
+ (void) sudo_ev_loop(evbase, SUDO_EVLOOP_NONBLOCK);
+
+ /*
+ * If not in non-blocking mode, make sure we flush write buffers.
+ * We don't want to read from the pty or stdin since that might block
+ * and the command is no longer running anyway.
+ */
+ if (!nonblocking) {
+ /* Clear out iobufs from event base. */
+ SLIST_FOREACH(iob, &iobufs, entries) {
+ if (iob->revent != NULL && !USERTTY_EVENT(iob->revent))
+ sudo_ev_del(evbase, iob->revent);
+ if (iob->wevent != NULL)
+ sudo_ev_del(evbase, iob->wevent);
+ }
+
+ SLIST_FOREACH(iob, &iobufs, entries) {
+ /* Flush any write buffers with data in them. */
+ if (iob->wevent != NULL) {
+ if (iob->len > iob->off) {
+ if (sudo_ev_add(evbase, iob->wevent, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+ }
+ }
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: flushing remaining write buffers (blocking)", __func__);
+ (void) sudo_ev_dispatch(evbase);
+
+ /* We should now have flushed all write buffers. */
+ SLIST_FOREACH(iob, &iobufs, entries) {
+ if (iob->wevent != NULL) {
+ if (iob->len > iob->off) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "unflushed data: wevent %p, fd %d, events %d",
+ iob->wevent, iob->wevent->fd, iob->wevent->events);
+ }
+ }
+ }
+ }
+
+ /* Free temporary event base, removing its events. */
+ sudo_ev_base_free(evbase);
+
+ debug_return;
+}
+
+/*
+ * Free the contents of the I/O buffers queue.
+ */
+void
+free_io_bufs(void)
+{
+ struct io_buffer *iob;
+ debug_decl(free_io_bufs, SUDO_DEBUG_EXEC);
+
+ while ((iob = SLIST_FIRST(&iobufs)) != NULL) {
+ SLIST_REMOVE_HEAD(&iobufs, entries);
+ if (iob->revent != NULL)
+ sudo_ev_free(iob->revent);
+ if (iob->wevent != NULL)
+ sudo_ev_free(iob->wevent);
+ free(iob);
+ }
+
+ debug_return;
+}
+
+/* Call I/O plugin tty input log method. */
+bool
+log_ttyin(const char *buf, unsigned int n, struct io_buffer *iob)
+{
+ struct plugin_container *plugin;
+ const char *errstr = NULL;
+ sigset_t omask;
+ bool ret = true;
+ debug_decl(log_ttyin, SUDO_DEBUG_EXEC);
+
+ sigprocmask(SIG_BLOCK, &ttyblock, &omask);
+ TAILQ_FOREACH(plugin, &io_plugins, entries) {
+ if (plugin->u.io->log_ttyin) {
+ int rc;
+
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ rc = plugin->u.io->log_ttyin(buf, n, &errstr);
+ if (rc <= 0) {
+ if (rc < 0) {
+ /* Error: disable plugin's I/O function. */
+ plugin->u.io->log_ttyin = NULL;
+ audit_error(plugin->name, SUDO_IO_PLUGIN,
+ errstr ? errstr : _("I/O plugin error"),
+ iob->ec->details->info);
+ } else {
+ audit_reject(plugin->name, SUDO_IO_PLUGIN,
+ errstr ? errstr : _("command rejected by I/O plugin"),
+ iob->ec->details->info);
+ }
+ ret = false;
+ break;
+ }
+ }
+ }
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+
+ debug_return_bool(ret);
+}
+
+/* Call I/O plugin stdin log method. */
+bool
+log_stdin(const char *buf, unsigned int n, struct io_buffer *iob)
+{
+ struct plugin_container *plugin;
+ const char *errstr = NULL;
+ sigset_t omask;
+ bool ret = true;
+ debug_decl(log_stdin, SUDO_DEBUG_EXEC);
+
+ sigprocmask(SIG_BLOCK, &ttyblock, &omask);
+ TAILQ_FOREACH(plugin, &io_plugins, entries) {
+ if (plugin->u.io->log_stdin) {
+ int rc;
+
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ rc = plugin->u.io->log_stdin(buf, n, &errstr);
+ if (rc <= 0) {
+ if (rc < 0) {
+ /* Error: disable plugin's I/O function. */
+ plugin->u.io->log_stdin = NULL;
+ audit_error(plugin->name, SUDO_IO_PLUGIN,
+ errstr ? errstr : _("I/O plugin error"),
+ iob->ec->details->info);
+ } else {
+ audit_reject(plugin->name, SUDO_IO_PLUGIN,
+ errstr ? errstr : _("command rejected by I/O plugin"),
+ iob->ec->details->info);
+ }
+ ret = false;
+ break;
+ }
+ }
+ }
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+
+ debug_return_bool(ret);
+}
+
+/* Call I/O plugin tty output log method. */
+bool
+log_ttyout(const char *buf, unsigned int n, struct io_buffer *iob)
+{
+ struct plugin_container *plugin;
+ const char *errstr = NULL;
+ sigset_t omask;
+ bool ret = true;
+ debug_decl(log_ttyout, SUDO_DEBUG_EXEC);
+
+ sigprocmask(SIG_BLOCK, &ttyblock, &omask);
+ TAILQ_FOREACH(plugin, &io_plugins, entries) {
+ if (plugin->u.io->log_ttyout) {
+ int rc;
+
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ rc = plugin->u.io->log_ttyout(buf, n, &errstr);
+ if (rc <= 0) {
+ if (rc < 0) {
+ /* Error: disable plugin's I/O function. */
+ plugin->u.io->log_ttyout = NULL;
+ audit_error(plugin->name, SUDO_IO_PLUGIN,
+ errstr ? errstr : _("I/O plugin error"),
+ iob->ec->details->info);
+ } else {
+ audit_reject(plugin->name, SUDO_IO_PLUGIN,
+ errstr ? errstr : _("command rejected by I/O plugin"),
+ iob->ec->details->info);
+ }
+ ret = false;
+ break;
+ }
+ }
+ }
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ if (!ret) {
+ /*
+ * I/O plugin rejected the output, delete the write event
+ * (user's tty) so we do not display the rejected output.
+ */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: deleting and freeing devtty wevent %p", __func__, iob->wevent);
+ sudo_ev_free(iob->wevent);
+ iob->wevent = NULL;
+ iob->off = iob->len = 0;
+ }
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+
+ debug_return_bool(ret);
+}
+
+/* Call I/O plugin stdout log method. */
+bool
+log_stdout(const char *buf, unsigned int n, struct io_buffer *iob)
+{
+ struct plugin_container *plugin;
+ const char *errstr = NULL;
+ sigset_t omask;
+ bool ret = true;
+ debug_decl(log_stdout, SUDO_DEBUG_EXEC);
+
+ sigprocmask(SIG_BLOCK, &ttyblock, &omask);
+ TAILQ_FOREACH(plugin, &io_plugins, entries) {
+ if (plugin->u.io->log_stdout) {
+ int rc;
+
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ rc = plugin->u.io->log_stdout(buf, n, &errstr);
+ if (rc <= 0) {
+ if (rc < 0) {
+ /* Error: disable plugin's I/O function. */
+ plugin->u.io->log_stdout = NULL;
+ audit_error(plugin->name, SUDO_IO_PLUGIN,
+ errstr ? errstr : _("I/O plugin error"),
+ iob->ec->details->info);
+ } else {
+ audit_reject(plugin->name, SUDO_IO_PLUGIN,
+ errstr ? errstr : _("command rejected by I/O plugin"),
+ iob->ec->details->info);
+ }
+ ret = false;
+ break;
+ }
+ }
+ }
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ if (!ret) {
+ /*
+ * I/O plugin rejected the output, delete the write event
+ * (user's stdout) so we do not display the rejected output.
+ */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: deleting and freeing stdout wevent %p", __func__, iob->wevent);
+ sudo_ev_free(iob->wevent);
+ iob->wevent = NULL;
+ iob->off = iob->len = 0;
+ }
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+
+ debug_return_bool(ret);
+}
+
+/* Call I/O plugin stderr log method. */
+bool
+log_stderr(const char *buf, unsigned int n, struct io_buffer *iob)
+{
+ struct plugin_container *plugin;
+ const char *errstr = NULL;
+ sigset_t omask;
+ bool ret = true;
+ debug_decl(log_stderr, SUDO_DEBUG_EXEC);
+
+ sigprocmask(SIG_BLOCK, &ttyblock, &omask);
+ TAILQ_FOREACH(plugin, &io_plugins, entries) {
+ if (plugin->u.io->log_stderr) {
+ int rc;
+
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ rc = plugin->u.io->log_stderr(buf, n, &errstr);
+ if (rc <= 0) {
+ if (rc < 0) {
+ /* Error: disable plugin's I/O function. */
+ plugin->u.io->log_stderr = NULL;
+ audit_error(plugin->name, SUDO_IO_PLUGIN,
+ errstr ? errstr : _("I/O plugin error"),
+ iob->ec->details->info);
+ } else {
+ audit_reject(plugin->name, SUDO_IO_PLUGIN,
+ errstr ? errstr : _("command rejected by I/O plugin"),
+ iob->ec->details->info);
+ }
+ ret = false;
+ break;
+ }
+ }
+ }
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ if (!ret) {
+ /*
+ * I/O plugin rejected the output, delete the write event
+ * (user's stderr) so we do not display the rejected output.
+ */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: deleting and freeing stderr wevent %p", __func__, iob->wevent);
+ sudo_ev_free(iob->wevent);
+ iob->wevent = NULL;
+ iob->off = iob->len = 0;
+ }
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+
+ debug_return_bool(ret);
+}
+
+/* Call I/O plugin suspend log method. */
+void
+log_suspend(void *v, int signo)
+{
+ struct exec_closure *ec = v;
+ struct plugin_container *plugin;
+ const char *errstr = NULL;
+ sigset_t omask;
+ debug_decl(log_suspend, SUDO_DEBUG_EXEC);
+
+ sigprocmask(SIG_BLOCK, &ttyblock, &omask);
+ TAILQ_FOREACH(plugin, &io_plugins, entries) {
+ if (plugin->u.io->version < SUDO_API_MKVERSION(1, 13))
+ continue;
+ if (plugin->u.io->log_suspend) {
+ int rc;
+
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ rc = plugin->u.io->log_suspend(signo, &errstr);
+ if (rc <= 0) {
+ /* Error: disable plugin's I/O function. */
+ plugin->u.io->log_suspend = NULL;
+ audit_error(plugin->name, SUDO_IO_PLUGIN,
+ errstr ? errstr : _("error logging suspend"),
+ ec->details->info);
+ break;
+ }
+ }
+ }
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+
+ debug_return;
+}
+
+/* Call I/O plugin window change log method. */
+void
+log_winchange(struct exec_closure *ec, unsigned int rows,
+ unsigned int cols)
+{
+ struct plugin_container *plugin;
+ const char *errstr = NULL;
+ sigset_t omask;
+ debug_decl(log_winchange, SUDO_DEBUG_EXEC);
+
+ sigprocmask(SIG_BLOCK, &ttyblock, &omask);
+ TAILQ_FOREACH(plugin, &io_plugins, entries) {
+ if (plugin->u.io->version < SUDO_API_MKVERSION(1, 12))
+ continue;
+ if (plugin->u.io->change_winsize) {
+ int rc;
+
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ rc = plugin->u.io->change_winsize(rows, cols, &errstr);
+ if (rc <= 0) {
+ /* Error: disable plugin's I/O function. */
+ plugin->u.io->change_winsize = NULL;
+ audit_error(plugin->name, SUDO_IO_PLUGIN,
+ errstr ? errstr : _("error changing window size"),
+ ec->details->info);
+ break;
+ }
+ }
+ }
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+
+ debug_return;
+}
+
+void
+init_ttyblock(void)
+{
+ /* So we can block tty-generated signals */
+ sigemptyset(&ttyblock);
+ sigaddset(&ttyblock, SIGINT);
+ sigaddset(&ttyblock, SIGQUIT);
+ sigaddset(&ttyblock, SIGTSTP);
+ sigaddset(&ttyblock, SIGTTIN);
+ sigaddset(&ttyblock, SIGTTOU);
+}
diff --git a/src/exec_monitor.c b/src/exec_monitor.c
new file mode 100644
index 0000000..9681e56
--- /dev/null
+++ b/src/exec_monitor.c
@@ -0,0 +1,727 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include <sudo.h>
+#include <sudo_exec.h>
+#include <sudo_plugin.h>
+#include <sudo_plugin_int.h>
+
+struct monitor_closure {
+ const struct command_details *details;
+ struct sudo_event_base *evbase;
+ struct sudo_event *errsock_event;
+ struct sudo_event *backchannel_event;
+ struct sudo_event *sigint_event;
+ struct sudo_event *sigquit_event;
+ struct sudo_event *sigtstp_event;
+ struct sudo_event *sigterm_event;
+ struct sudo_event *sighup_event;
+ struct sudo_event *sigusr1_event;
+ struct sudo_event *sigusr2_event;
+ struct sudo_event *sigchld_event;
+ struct command_status *cstat;
+ pid_t cmnd_pid;
+ pid_t cmnd_pgrp;
+ pid_t mon_pgrp;
+ int backchannel;
+};
+
+/*
+ * Deliver a signal to the running command.
+ * The signal was either forwarded to us by the parent sudo process
+ * or was received by the monitor itself.
+ *
+ * There are two "special" signals, SIGCONT_FG and SIGCONT_BG that
+ * also specify whether the command should have the controlling tty.
+ */
+static void
+deliver_signal(struct monitor_closure *mc, int signo, bool from_parent)
+{
+ debug_decl(deliver_signal, SUDO_DEBUG_EXEC);
+
+ /* Avoid killing more than a single process or process group. */
+ if (mc->cmnd_pid <= 0)
+ debug_return;
+
+ if (sudo_debug_needed(SUDO_DEBUG_INFO)) {
+ char signame[SIG2STR_MAX];
+ if (signo == SIGCONT_FG)
+ (void)strlcpy(signame, "CONT_FG", sizeof(signame));
+ else if (signo == SIGCONT_BG)
+ (void)strlcpy(signame, "CONT_BG", sizeof(signame));
+ else if (sig2str(signo, signame) == -1)
+ (void)snprintf(signame, sizeof(signame), "%d", signo);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "received SIG%s%s",
+ signame, from_parent ? " from parent" : "");
+ }
+
+ /* Handle signal from parent or monitor. */
+ switch (signo) {
+ case SIGALRM:
+ terminate_command(mc->cmnd_pid, true);
+ break;
+ case SIGCONT_FG:
+ /* Continue in foreground, grant it controlling tty. */
+ if (tcsetpgrp(io_fds[SFD_FOLLOWER], mc->cmnd_pgrp) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to set foreground pgrp to %d (command)",
+ __func__, (int)mc->cmnd_pgrp);
+ }
+ killpg(mc->cmnd_pid, SIGCONT);
+ break;
+ case SIGCONT_BG:
+ /* Continue in background, I take controlling tty. */
+ if (tcsetpgrp(io_fds[SFD_FOLLOWER], mc->mon_pgrp) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to set foreground pgrp to %d (monitor)",
+ __func__, (int)mc->mon_pgrp);
+ }
+ killpg(mc->cmnd_pid, SIGCONT);
+ break;
+ case SIGKILL:
+ _exit(EXIT_FAILURE); /* XXX */
+ /* NOTREACHED */
+ default:
+ /* Relay signal to command. */
+ killpg(mc->cmnd_pid, signo);
+ break;
+ }
+ debug_return;
+}
+
+/*
+ * Send status to parent over socketpair.
+ * Return value is the same as send(2).
+ */
+static ssize_t
+send_status(int fd, struct command_status *cstat)
+{
+ ssize_t n = -1;
+ debug_decl(send_status, SUDO_DEBUG_EXEC);
+
+ if (cstat->type != CMD_INVALID) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "sending status message to parent: [%d, %d]",
+ cstat->type, cstat->val);
+ n = send(fd, cstat, sizeof(*cstat), 0);
+ if (n != ssizeof(*cstat)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to send status to parent", __func__);
+ }
+ cstat->type = CMD_INVALID; /* prevent re-sending */
+ }
+ debug_return_ssize_t(n);
+}
+
+/*
+ * Wait for command status after receiving SIGCHLD.
+ * If the command was stopped, the status is send back to the parent.
+ * Otherwise, cstat is filled in but not sent.
+ */
+static void
+mon_handle_sigchld(struct monitor_closure *mc)
+{
+ char signame[SIG2STR_MAX];
+ int status;
+ pid_t pid;
+ debug_decl(mon_handle_sigchld, SUDO_DEBUG_EXEC);
+
+ /* Read command status. */
+ do {
+ pid = waitpid(mc->cmnd_pid, &status, WUNTRACED|WNOHANG);
+ } while (pid == -1 && errno == EINTR);
+ switch (pid) {
+ case -1:
+ if (errno != ECHILD) {
+ sudo_warn(U_("%s: %s"), __func__, "waitpid");
+ debug_return;
+ }
+ FALLTHROUGH;
+ case 0:
+ /* Nothing to wait for. */
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: no process to wait for",
+ __func__);
+ debug_return;
+ }
+
+ if (WIFSTOPPED(status)) {
+ if (sig2str(WSTOPSIG(status), signame) == -1)
+ (void)snprintf(signame, sizeof(signame), "%d", WSTOPSIG(status));
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: command (%d) stopped, SIG%s",
+ __func__, (int)mc->cmnd_pid, signame);
+ } else if (WIFSIGNALED(status)) {
+ if (sig2str(WTERMSIG(status), signame) == -1)
+ (void)snprintf(signame, sizeof(signame), "%d", WTERMSIG(status));
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: command (%d) killed, SIG%s",
+ __func__, (int)mc->cmnd_pid, signame);
+ mc->cmnd_pid = -1;
+ } else if (WIFEXITED(status)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: command (%d) exited: %d",
+ __func__, (int)mc->cmnd_pid, WEXITSTATUS(status));
+ mc->cmnd_pid = -1;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN,
+ "%s: unexpected wait status 0x%x for command (%d)",
+ __func__, status, (int)mc->cmnd_pid);
+ }
+
+ /* Don't overwrite execve() failure with child exit status. */
+ if (mc->cstat->type == CMD_INVALID) {
+ /*
+ * Store wait status in cstat and forward to parent if stopped.
+ */
+ mc->cstat->type = CMD_WSTATUS;
+ mc->cstat->val = status;
+ if (WIFSTOPPED(status)) {
+ /* Save the foreground pgid so we can restore it later. */
+ pid = tcgetpgrp(io_fds[SFD_FOLLOWER]);
+ if (pid != mc->mon_pgrp)
+ mc->cmnd_pgrp = pid;
+ send_status(mc->backchannel, mc->cstat);
+ }
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN,
+ "%s: not overwriting command status %d,%d with %d,%d",
+ __func__, mc->cstat->type, mc->cstat->val, CMD_WSTATUS, status);
+ }
+
+ debug_return;
+}
+
+static void
+mon_signal_cb(int signo, int what, void *v)
+{
+ struct sudo_ev_siginfo_container *sc = v;
+ struct monitor_closure *mc = sc->closure;
+ debug_decl(mon_signal_cb, SUDO_DEBUG_EXEC);
+
+ /*
+ * Handle SIGCHLD specially and deliver other signals
+ * directly to the command.
+ */
+ if (signo == SIGCHLD) {
+ mon_handle_sigchld(mc);
+ if (mc->cmnd_pid == -1) {
+ /* Command exited or was killed, exit event loop. */
+ sudo_ev_loopexit(mc->evbase);
+ }
+ } else {
+ /*
+ * If the signal came from the process group of the command we ran,
+ * do not forward it as we don't want the child to indirectly kill
+ * itself. This can happen with, e.g., BSD-derived versions of
+ * reboot that call kill(-1, SIGTERM) to kill all other processes.
+ */
+ if (USER_SIGNALED(sc->siginfo) && sc->siginfo->si_pid != 0) {
+ pid_t si_pgrp;
+
+ if (sc->siginfo->si_pid == mc->cmnd_pid)
+ debug_return;
+ si_pgrp = getpgid(sc->siginfo->si_pid);
+ if (si_pgrp != -1) {
+ if (si_pgrp == mc->cmnd_pgrp)
+ debug_return;
+ }
+ }
+ deliver_signal(mc, signo, false);
+ }
+ debug_return;
+}
+
+/* This is essentially the same as errpipe_cb() in exec_nopty.c */
+static void
+mon_errsock_cb(int fd, int what, void *v)
+{
+ struct monitor_closure *mc = v;
+ ssize_t nread;
+ int errval;
+ debug_decl(mon_errsock_cb, SUDO_DEBUG_EXEC);
+
+ /*
+ * Read errno from child or EOF when command is executed.
+ * Note that the error socket is *blocking*.
+ */
+ nread = read(fd, &errval, sizeof(errval));
+ switch (nread) {
+ case -1:
+ if (errno != EAGAIN && errno != EINTR) {
+ if (mc->cstat->val == CMD_INVALID) {
+ /* XXX - need a way to distinguish non-exec error. */
+ mc->cstat->type = CMD_ERRNO;
+ mc->cstat->val = errno;
+ }
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: failed to read error socket", __func__);
+ sudo_ev_loopbreak(mc->evbase);
+ }
+ break;
+ default:
+ if (nread == 0) {
+ /* The error socket closes when the command is executed. */
+ sudo_debug_printf(SUDO_DEBUG_INFO, "EOF on error socket");
+ } else {
+ /* Errno value when child is unable to execute command. */
+ sudo_debug_printf(SUDO_DEBUG_INFO, "errno from child: %s",
+ strerror(errval));
+ mc->cstat->type = CMD_ERRNO;
+ mc->cstat->val = errval;
+ }
+ sudo_ev_del(mc->evbase, mc->errsock_event);
+ close(fd);
+ break;
+ }
+ debug_return;
+}
+
+static void
+mon_backchannel_cb(int fd, int what, void *v)
+{
+ struct monitor_closure *mc = v;
+ struct command_status cstmp;
+ ssize_t n;
+ debug_decl(mon_backchannel_cb, SUDO_DEBUG_EXEC);
+
+ /*
+ * Read command from backchannel, should be a signal.
+ * Note that the backchannel is a *blocking* socket.
+ */
+ n = recv(fd, &cstmp, sizeof(cstmp), MSG_WAITALL);
+ if (n != ssizeof(cstmp)) {
+ if (n == -1) {
+ if (errno == EINTR || errno == EAGAIN)
+ debug_return;
+ sudo_warn("%s", U_("error reading from socketpair"));
+ } else {
+ /* short read or EOF, parent process died? */
+ }
+ /* XXX - need a way to distinguish non-exec error. */
+ mc->cstat->type = CMD_ERRNO;
+ mc->cstat->val = n ? EIO : ECONNRESET;
+ sudo_ev_loopbreak(mc->evbase);
+ } else {
+ if (cstmp.type == CMD_SIGNO) {
+ deliver_signal(mc, cstmp.val, true);
+ } else {
+ sudo_warnx(U_("unexpected reply type on backchannel: %d"),
+ cstmp.type);
+ }
+ }
+ debug_return;
+}
+
+/*
+ * Sets up std{in,out,err} and executes the actual command.
+ * Returns only if execve() fails.
+ */
+static void
+exec_cmnd_pty(struct command_details *details, sigset_t *mask,
+ bool foreground, int intercept_fd, int errfd)
+{
+ volatile pid_t self = getpid();
+ debug_decl(exec_cmnd_pty, SUDO_DEBUG_EXEC);
+
+ /* Set command process group here too to avoid a race. */
+ setpgid(0, self);
+
+ /* Wire up standard fds, note that stdout/stderr may be pipes. */
+ if (dup3(io_fds[SFD_STDIN], STDIN_FILENO, 0) == -1)
+ sudo_fatal("dup3");
+ if (io_fds[SFD_STDIN] != io_fds[SFD_FOLLOWER])
+ close(io_fds[SFD_STDIN]);
+ if (dup3(io_fds[SFD_STDOUT], STDOUT_FILENO, 0) == -1)
+ sudo_fatal("dup3");
+ if (io_fds[SFD_STDOUT] != io_fds[SFD_FOLLOWER])
+ close(io_fds[SFD_STDOUT]);
+ if (dup3(io_fds[SFD_STDERR], STDERR_FILENO, 0) == -1)
+ sudo_fatal("dup3");
+ if (io_fds[SFD_STDERR] != io_fds[SFD_FOLLOWER])
+ close(io_fds[SFD_STDERR]);
+
+ /* Wait for parent to grant us the tty if we are foreground. */
+ if (foreground) {
+ char ch;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: waiting for controlling tty",
+ __func__);
+ if (recv(errfd, &ch, sizeof(ch), 0) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to receive message from parent", __func__);
+ debug_return;
+ }
+ if (tcgetpgrp(io_fds[SFD_FOLLOWER]) == self) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: got controlling tty",
+ __func__);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: unable to get controlling tty", __func__);
+ foreground = false;
+ }
+ }
+
+ /* Done with the pty follower, don't leak it. */
+ if (io_fds[SFD_FOLLOWER] != -1)
+ close(io_fds[SFD_FOLLOWER]);
+
+ /* Execute command; only returns on error. */
+ sudo_debug_printf(SUDO_DEBUG_INFO, "executing %s in the %s",
+ details->command, foreground ? "foreground" : "background");
+ exec_cmnd(details, mask, intercept_fd, errfd);
+
+ debug_return;
+}
+
+/*
+ * Fill in the monitor closure and setup initial events.
+ * Allocates read events for the signal pipe, error pipe and backchannel.
+ */
+static void
+fill_exec_closure_monitor(struct monitor_closure *mc,
+ const struct command_details *details, struct command_status *cstat,
+ int errfd, int backchannel)
+{
+ debug_decl(fill_exec_closure_monitor, SUDO_DEBUG_EXEC);
+
+ /* Fill in the non-event part of the closure. */
+ mc->details = details;
+ mc->cstat = cstat;
+ mc->backchannel = backchannel;
+ mc->mon_pgrp = getpgrp();
+
+ /* Setup event base and events. */
+ mc->evbase = sudo_ev_base_alloc();
+ if (mc->evbase == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ /* Event for command status via errfd. */
+ mc->errsock_event = sudo_ev_alloc(errfd,
+ SUDO_EV_READ|SUDO_EV_PERSIST, mon_errsock_cb, mc);
+ if (mc->errsock_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(mc->evbase, mc->errsock_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ /* Event for forwarded signals via backchannel. */
+ mc->backchannel_event = sudo_ev_alloc(backchannel,
+ SUDO_EV_READ|SUDO_EV_PERSIST, mon_backchannel_cb, mc);
+ if (mc->backchannel_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(mc->evbase, mc->backchannel_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ /* Events for local signals. */
+ mc->sigint_event = sudo_ev_alloc(SIGINT,
+ SUDO_EV_SIGINFO, mon_signal_cb, mc);
+ if (mc->sigint_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(mc->evbase, mc->sigint_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ mc->sigquit_event = sudo_ev_alloc(SIGQUIT,
+ SUDO_EV_SIGINFO, mon_signal_cb, mc);
+ if (mc->sigquit_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(mc->evbase, mc->sigquit_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ mc->sigtstp_event = sudo_ev_alloc(SIGTSTP,
+ SUDO_EV_SIGINFO, mon_signal_cb, mc);
+ if (mc->sigtstp_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(mc->evbase, mc->sigtstp_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ mc->sigterm_event = sudo_ev_alloc(SIGTERM,
+ SUDO_EV_SIGINFO, mon_signal_cb, mc);
+ if (mc->sigterm_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(mc->evbase, mc->sigterm_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ mc->sighup_event = sudo_ev_alloc(SIGHUP,
+ SUDO_EV_SIGINFO, mon_signal_cb, mc);
+ if (mc->sighup_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(mc->evbase, mc->sighup_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ mc->sigusr1_event = sudo_ev_alloc(SIGUSR1,
+ SUDO_EV_SIGINFO, mon_signal_cb, mc);
+ if (mc->sigusr1_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(mc->evbase, mc->sigusr1_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ mc->sigusr2_event = sudo_ev_alloc(SIGUSR2,
+ SUDO_EV_SIGINFO, mon_signal_cb, mc);
+ if (mc->sigusr2_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(mc->evbase, mc->sigusr2_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ mc->sigchld_event = sudo_ev_alloc(SIGCHLD,
+ SUDO_EV_SIGINFO, mon_signal_cb, mc);
+ if (mc->sigchld_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(mc->evbase, mc->sigchld_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ /* Clear the default event base. */
+ sudo_ev_base_setdef(NULL);
+
+ debug_return;
+}
+
+/*
+ * Make the tty follower the controlling tty.
+ */
+static bool
+pty_make_controlling(const char *follower)
+{
+ debug_decl(pty_make_controlling, SUDO_DEBUG_EXEC);
+
+ if (io_fds[SFD_FOLLOWER] != -1) {
+#ifdef TIOCSCTTY
+ if (ioctl(io_fds[SFD_FOLLOWER], TIOCSCTTY, NULL) != 0)
+ debug_return_bool(false);
+#else
+ /* Set controlling tty by reopening pty follower. */
+ int fd = open(follower, O_RDWR);
+ if (fd == -1)
+ debug_return_bool(false);
+ close(fd);
+#endif
+ }
+ debug_return_bool(true);
+}
+
+/*
+ * Monitor process that creates a new session with the controlling tty,
+ * resets signal handlers and forks a child to call exec_cmnd_pty().
+ * Waits for status changes from the command and relays them to the
+ * parent and relays signals from the parent to the command.
+ * Must be called with signals blocked and the old signal mask in oset.
+ * Returns an error if fork(2) fails, else calls _exit(2).
+ */
+int
+exec_monitor(struct command_details *details, sigset_t *oset,
+ bool foreground, int backchannel, int intercept_fd)
+{
+ struct monitor_closure mc = { 0 };
+ struct command_status cstat;
+ struct sigaction sa;
+ int errsock[2];
+ debug_decl(exec_monitor, SUDO_DEBUG_EXEC);
+
+ /* Close fds the monitor doesn't use. */
+ if (io_fds[SFD_LEADER] != -1)
+ close(io_fds[SFD_LEADER]);
+ if (io_fds[SFD_USERTTY] != -1)
+ close(io_fds[SFD_USERTTY]);
+
+ /* Ignore any SIGTTIN or SIGTTOU we receive (shouldn't be possible). */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = SIG_IGN;
+ if (sudo_sigaction(SIGTTIN, &sa, NULL) != 0)
+ sudo_warn(U_("unable to set handler for signal %d"), SIGTTIN);
+ if (sudo_sigaction(SIGTTOU, &sa, NULL) != 0)
+ sudo_warn(U_("unable to set handler for signal %d"), SIGTTOU);
+
+ /*
+ * Start a new session with the parent as the session leader
+ * and the follower device as the controlling terminal.
+ * This allows us to be notified when the command has been suspended.
+ */
+ if (setsid() == -1) {
+ sudo_warn("setsid");
+ goto bad;
+ }
+ if (!pty_make_controlling(details->tty)) {
+ sudo_warn("%s", U_("unable to set controlling tty"));
+ goto bad;
+ }
+
+ /*
+ * The child waits on the other end of a socketpair for the
+ * parent to set the controlling terminal. It also writes
+ * error to the socket on execve(2) failure.
+ */
+ if (socketpair(PF_UNIX, SOCK_STREAM, 0, errsock) == -1 ||
+ fcntl(errsock[0], F_SETFD, FD_CLOEXEC) == -1 ||
+ fcntl(errsock[1], F_SETFD, FD_CLOEXEC) == -1) {
+ sudo_warn("%s", U_("unable to create sockets"));
+ goto bad;
+ }
+
+ /*
+ * Before forking, wait for the main sudo process to tell us to go.
+ * Avoids race conditions when the command exits quickly.
+ */
+ if (recv(backchannel, &cstat, sizeof(cstat), MSG_WAITALL) == -1) {
+ sudo_warn("%s", U_("unable to receive message from parent"));
+ goto bad;
+ }
+
+#ifdef HAVE_SELINUX
+ if (ISSET(details->flags, CD_RBAC_ENABLED)) {
+ if (selinux_relabel_tty(details->tty, io_fds[SFD_FOLLOWER]) == -1)
+ goto bad;
+ selinux_audit_role_change();
+ }
+#endif
+
+ mc.cmnd_pid = sudo_debug_fork();
+ switch (mc.cmnd_pid) {
+ case -1:
+ sudo_warn("%s", U_("unable to fork"));
+#ifdef HAVE_SELINUX
+ if (ISSET(details->flags, CD_RBAC_ENABLED)) {
+ if (selinux_restore_tty() != 0)
+ sudo_warnx("%s", U_("unable to restore tty label"));
+ }
+#endif
+ goto bad;
+ case 0:
+ /* child */
+ close(backchannel);
+ close(errsock[0]);
+ /* setup tty and exec command */
+ exec_cmnd_pty(details, oset, foreground, intercept_fd, errsock[1]);
+ if (send(errsock[1], &errno, sizeof(int), 0) == -1)
+ sudo_warn(U_("unable to execute %s"), details->command);
+ _exit(EXIT_FAILURE);
+ /* NOTREACHED */
+ }
+ close(errsock[1]);
+ if (intercept_fd != -1)
+ close(intercept_fd);
+
+ /* No longer need execfd. */
+ if (details->execfd != -1) {
+ close(details->execfd);
+ details->execfd = -1;
+ }
+
+ /* Send the command's pid to main sudo process. */
+ cstat.type = CMD_PID;
+ cstat.val = mc.cmnd_pid;
+ send_status(backchannel, &cstat);
+
+ /*
+ * Create new event base and register read events for the
+ * signal pipe, error pipe, and backchannel.
+ */
+ fill_exec_closure_monitor(&mc, details, &cstat, errsock[0], backchannel);
+
+ /* Restore signal mask now that signal handlers are setup. */
+ sigprocmask(SIG_SETMASK, oset, NULL);
+
+ /* If any of stdin/stdout/stderr are pipes, close them in parent. */
+ if (io_fds[SFD_STDIN] != io_fds[SFD_FOLLOWER])
+ close(io_fds[SFD_STDIN]);
+ if (io_fds[SFD_STDOUT] != io_fds[SFD_FOLLOWER])
+ close(io_fds[SFD_STDOUT]);
+ if (io_fds[SFD_STDERR] != io_fds[SFD_FOLLOWER])
+ close(io_fds[SFD_STDERR]);
+
+ /* Put command in its own process group. */
+ mc.cmnd_pgrp = mc.cmnd_pid;
+ setpgid(mc.cmnd_pid, mc.cmnd_pgrp);
+
+ /* Make the command the foreground process for the pty follower. */
+ if (foreground) {
+ if (tcsetpgrp(io_fds[SFD_FOLLOWER], mc.cmnd_pgrp) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to set foreground pgrp to %d (command)",
+ __func__, (int)mc.cmnd_pgrp);
+ }
+ /* Tell the child to go ahead now that it is the foreground pgrp. */
+ if (send(errsock[0], "", 1, 0) == -1) {
+ sudo_warn(U_("unable to execute %s"), details->command);
+ terminate_command(mc.cmnd_pid, true);
+ }
+ }
+
+ /*
+ * Wait for errno on pipe, signal on backchannel or for SIGCHLD.
+ * The event loop ends when the child is no longer running and
+ * the error pipe is closed.
+ */
+ cstat.type = CMD_INVALID;
+ cstat.val = 0;
+ (void) sudo_ev_dispatch(mc.evbase);
+ if (mc.cmnd_pid != -1) {
+ pid_t pid;
+
+ /* Command still running, did the parent die? */
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "Command still running after event loop exit, terminating");
+ terminate_command(mc.cmnd_pid, true);
+ do {
+ pid = waitpid(mc.cmnd_pid, NULL, 0);
+ } while (pid == -1 && errno == EINTR);
+ /* XXX - update cstat with wait status? */
+ }
+
+ /*
+ * Take the controlling tty. This prevents processes spawned by the
+ * command from receiving SIGHUP when the session leader (us) exits.
+ */
+ if (tcsetpgrp(io_fds[SFD_FOLLOWER], mc.mon_pgrp) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to set foreground pgrp to %d (monitor)",
+ __func__, (int)mc.mon_pgrp);
+ }
+
+ /* Send parent status. */
+ send_status(backchannel, &cstat);
+
+#ifdef HAVE_SELINUX
+ if (ISSET(details->flags, CD_RBAC_ENABLED)) {
+ if (selinux_restore_tty() != 0)
+ sudo_warnx("%s", U_("unable to restore tty label"));
+ }
+#endif
+ sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, 1);
+ _exit(EXIT_FAILURE);
+ /* NOTREACHED */
+
+bad:
+ debug_return_int(-1);
+}
diff --git a/src/exec_nopty.c b/src/exec_nopty.c
new file mode 100644
index 0000000..1b1ae6d
--- /dev/null
+++ b/src/exec_nopty.c
@@ -0,0 +1,812 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <termios.h> /* for struct winsize on HP-UX */
+
+#include <sudo.h>
+#include <sudo_exec.h>
+#include <sudo_plugin.h>
+#include <sudo_plugin_int.h>
+
+static void handle_sigchld_nopty(struct exec_closure *ec);
+
+/*
+ * Handle window size change events.
+ */
+static void
+handle_sigwinch(struct exec_closure *ec, int fd)
+{
+ struct winsize wsize;
+ debug_decl(handle_sigwinch, SUDO_DEBUG_EXEC);
+
+ if (fd != -1 && ioctl(fd, TIOCGWINSZ, &wsize) == 0) {
+ if (wsize.ws_row != ec->rows || wsize.ws_col != ec->cols) {
+ /* Log window change event. */
+ log_winchange(ec, wsize.ws_row, wsize.ws_col);
+
+ /* Update rows/cols. */
+ ec->rows = wsize.ws_row;
+ ec->cols = wsize.ws_col;
+ }
+ }
+}
+
+/* Note: this is basically the same as mon_errpipe_cb() in exec_monitor.c */
+static void
+errpipe_cb(int fd, int what, void *v)
+{
+ struct exec_closure *ec = v;
+ ssize_t nread;
+ int errval;
+ debug_decl(errpipe_cb, SUDO_DEBUG_EXEC);
+
+ /*
+ * Read errno from child or EOF when command is executed.
+ * Note that the error pipe is *blocking*.
+ */
+ nread = read(fd, &errval, sizeof(errval));
+ switch (nread) {
+ case -1:
+ if (errno != EAGAIN && errno != EINTR) {
+ if (ec->cstat->val == CMD_INVALID) {
+ /* XXX - need a way to distinguish non-exec error. */
+ ec->cstat->type = CMD_ERRNO;
+ ec->cstat->val = errno;
+ }
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: failed to read error pipe", __func__);
+ sudo_ev_loopbreak(ec->evbase);
+ }
+ break;
+ default:
+ if (nread == 0) {
+ /* The error pipe closes when the command is executed. */
+ sudo_debug_printf(SUDO_DEBUG_INFO, "EOF on error pipe");
+ } else {
+ /* Errno value when child is unable to execute command. */
+ sudo_debug_printf(SUDO_DEBUG_INFO, "errno from child: %s",
+ strerror(errval));
+ ec->cstat->type = CMD_ERRNO;
+ ec->cstat->val = errval;
+ }
+ sudo_ev_del(ec->evbase, ec->backchannel_event);
+ close(fd);
+ break;
+ }
+ debug_return;
+}
+
+/* Signal callback */
+static void
+signal_cb_nopty(int signo, int what, void *v)
+{
+ struct sudo_ev_siginfo_container *sc = v;
+ struct exec_closure *ec = sc->closure;
+ char signame[SIG2STR_MAX];
+ pid_t si_pgrp;
+ debug_decl(signal_cb_nopty, SUDO_DEBUG_EXEC);
+
+ if (ec->cmnd_pid == -1)
+ debug_return;
+
+ if (sig2str(signo, signame) == -1)
+ (void)snprintf(signame, sizeof(signame), "%d", signo);
+ sudo_debug_printf(SUDO_DEBUG_DIAG,
+ "%s: evbase %p, command: %d, signo %s(%d), cstat %p",
+ __func__, ec->evbase, (int)ec->cmnd_pid, signame, signo, ec->cstat);
+
+ switch (signo) {
+ case SIGCHLD:
+ handle_sigchld_nopty(ec);
+ if (ec->cmnd_pid == -1) {
+ /* Command exited or was killed, exit event loop. */
+ sudo_ev_loopexit(ec->evbase);
+ }
+ debug_return;
+ case SIGWINCH:
+ handle_sigwinch(ec, io_fds[SFD_USERTTY]);
+ FALLTHROUGH;
+#ifdef SIGINFO
+ case SIGINFO:
+#endif
+ case SIGINT:
+ case SIGQUIT:
+ case SIGTSTP:
+ /*
+ * Only forward user-generated signals not sent by a process other than
+ * the command itself or a member of the command's process group (but
+ * only when either sudo or the command is the process group leader).
+ * Signals sent by the kernel may include SIGTSTP when the user presses
+ * ^Z. Curses programs often trap ^Z and send SIGTSTP to their own
+ * process group, so we don't want to send an extra SIGTSTP.
+ */
+ if (!USER_SIGNALED(sc->siginfo))
+ debug_return;
+ if (sc->siginfo->si_pid != 0) {
+ if (sc->siginfo->si_pid == ec->cmnd_pid)
+ debug_return;
+ si_pgrp = getpgid(sc->siginfo->si_pid);
+ if (si_pgrp != -1) {
+ if (si_pgrp == ec->cmnd_pid || si_pgrp == ec->sudo_pid)
+ debug_return;
+ }
+ }
+ break;
+ default:
+ /*
+ * Do not forward signals sent by the command itself or a member of the
+ * command's process group (but only when either sudo or the command is
+ * the process group leader). We don't want the command to indirectly
+ * kill itself. For example, this can happen with some versions of
+ * reboot that call kill(-1, SIGTERM) to kill all other processes.
+ */
+ if (USER_SIGNALED(sc->siginfo) && sc->siginfo->si_pid != 0) {
+ if (sc->siginfo->si_pid == ec->cmnd_pid)
+ debug_return;
+ si_pgrp = getpgid(sc->siginfo->si_pid);
+ if (si_pgrp != -1) {
+ if (si_pgrp == ec->cmnd_pid || si_pgrp == ec->sudo_pid)
+ debug_return;
+ }
+ }
+ break;
+ }
+
+ /* Send signal to command. */
+ if (signo == SIGALRM) {
+ terminate_command(ec->cmnd_pid, false);
+ } else if (kill(ec->cmnd_pid, signo) != 0) {
+ sudo_warn("kill(%d, SIG%s)", (int)ec->cmnd_pid, signame);
+ }
+
+ debug_return;
+}
+
+
+/*
+ * Fill in the exec closure and setup initial exec events.
+ * Allocates events for the signal pipe and error pipe.
+ */
+static void
+fill_exec_closure(struct exec_closure *ec, struct command_status *cstat,
+ struct command_details *details, const struct user_details *user_details,
+ struct sudo_event_base *evbase, int errfd)
+{
+ debug_decl(fill_exec_closure, SUDO_DEBUG_EXEC);
+
+ /* Fill in the non-event part of the closure. */
+ ec->sudo_pid = getpid();
+ ec->ppgrp = getpgrp();
+ ec->cstat = cstat;
+ ec->details = details;
+ ec->rows = user_details->ts_rows;
+ ec->cols = user_details->ts_cols;
+
+ /* Setup event base and events. */
+ ec->evbase = evbase;
+
+ /* Event for command status via errfd. */
+ ec->backchannel_event = sudo_ev_alloc(errfd,
+ SUDO_EV_READ|SUDO_EV_PERSIST, errpipe_cb, ec);
+ if (ec->backchannel_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->backchannel_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+ sudo_debug_printf(SUDO_DEBUG_INFO, "error pipe fd %d\n", errfd);
+
+ /* Events for local signals. */
+ ec->sigint_event = sudo_ev_alloc(SIGINT,
+ SUDO_EV_SIGINFO, signal_cb_nopty, ec);
+ if (ec->sigint_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigint_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigquit_event = sudo_ev_alloc(SIGQUIT,
+ SUDO_EV_SIGINFO, signal_cb_nopty, ec);
+ if (ec->sigquit_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigquit_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigtstp_event = sudo_ev_alloc(SIGTSTP,
+ SUDO_EV_SIGINFO, signal_cb_nopty, ec);
+ if (ec->sigtstp_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigtstp_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigterm_event = sudo_ev_alloc(SIGTERM,
+ SUDO_EV_SIGINFO, signal_cb_nopty, ec);
+ if (ec->sigterm_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigterm_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sighup_event = sudo_ev_alloc(SIGHUP,
+ SUDO_EV_SIGINFO, signal_cb_nopty, ec);
+ if (ec->sighup_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sighup_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigalrm_event = sudo_ev_alloc(SIGALRM,
+ SUDO_EV_SIGINFO, signal_cb_nopty, ec);
+ if (ec->sigalrm_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigalrm_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigpipe_event = sudo_ev_alloc(SIGPIPE,
+ SUDO_EV_SIGINFO, signal_cb_nopty, ec);
+ if (ec->sigpipe_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigpipe_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigusr1_event = sudo_ev_alloc(SIGUSR1,
+ SUDO_EV_SIGINFO, signal_cb_nopty, ec);
+ if (ec->sigusr1_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigusr1_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigusr2_event = sudo_ev_alloc(SIGUSR2,
+ SUDO_EV_SIGINFO, signal_cb_nopty, ec);
+ if (ec->sigusr2_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigusr2_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigchld_event = sudo_ev_alloc(SIGCHLD,
+ SUDO_EV_SIGINFO, signal_cb_nopty, ec);
+ if (ec->sigchld_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigchld_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigcont_event = sudo_ev_alloc(SIGCONT,
+ SUDO_EV_SIGINFO, signal_cb_nopty, ec);
+ if (ec->sigcont_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigcont_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+#ifdef SIGINFO
+ ec->siginfo_event = sudo_ev_alloc(SIGINFO,
+ SUDO_EV_SIGINFO, signal_cb_nopty, ec);
+ if (ec->siginfo_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->siginfo_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+#endif
+
+ ec->sigwinch_event = sudo_ev_alloc(SIGWINCH,
+ SUDO_EV_SIGINFO, signal_cb_nopty, ec);
+ if (ec->sigwinch_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigwinch_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ /* Set the default event base. */
+ sudo_ev_base_setdef(ec->evbase);
+
+ debug_return;
+}
+
+/*
+ * Read an iobuf that is ready.
+ */
+static void
+read_callback(int fd, int what, void *v)
+{
+ struct io_buffer *iob = v;
+ struct sudo_event_base *evbase = sudo_ev_get_base(iob->revent);
+ ssize_t n;
+ debug_decl(read_callback, SUDO_DEBUG_EXEC);
+
+ n = read(fd, iob->buf + iob->len, sizeof(iob->buf) - iob->len);
+ switch (n) {
+ case -1:
+ if (errno == EAGAIN || errno == EINTR) {
+ /* Not an error, retry later. */
+ break;
+ }
+ /* Treat read error as fatal and close the fd. */
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "error reading fd %d: %s", fd, strerror(errno));
+ FALLTHROUGH;
+ case 0:
+ /* got EOF */
+ if (n == 0) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "read EOF from fd %d", fd);
+ }
+ safe_close(fd);
+ ev_free_by_fd(evbase, fd);
+ /* If writer already consumed the buffer, close it too. */
+ if (iob->wevent != NULL && iob->off == iob->len) {
+ safe_close(sudo_ev_get_fd(iob->wevent));
+ ev_free_by_fd(evbase, sudo_ev_get_fd(iob->wevent));
+ iob->off = iob->len = 0;
+ }
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "read %zd bytes from fd %d", n, fd);
+ if (!iob->action(iob->buf + iob->len, (unsigned int)n, iob)) {
+ terminate_command(iob->ec->cmnd_pid, false);
+ iob->ec->cmnd_pid = -1;
+ }
+ iob->len += (unsigned int)n;
+ /* Disable reader if buffer is full. */
+ if (iob->len == sizeof(iob->buf))
+ sudo_ev_del(evbase, iob->revent);
+ /* Enable writer now that there is new data in the buffer. */
+ if (iob->wevent != NULL) {
+ if (sudo_ev_add(evbase, iob->wevent, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+ }
+ break;
+ }
+
+ debug_return;
+}
+
+/*
+ * Write an iobuf that is ready.
+ */
+static void
+write_callback(int fd, int what, void *v)
+{
+ struct io_buffer *iob = v;
+ struct sudo_event_base *evbase = sudo_ev_get_base(iob->wevent);
+ ssize_t n;
+ debug_decl(write_callback, SUDO_DEBUG_EXEC);
+
+ n = write(fd, iob->buf + iob->off, iob->len - iob->off);
+ if (n == -1) {
+ switch (errno) {
+ case EPIPE:
+ case EBADF:
+ /* other end of pipe closed */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "unable to write %u bytes to fd %d",
+ iob->len - iob->off, fd);
+ /* Close reader if there is one. */
+ if (iob->revent != NULL) {
+ safe_close(sudo_ev_get_fd(iob->revent));
+ ev_free_by_fd(evbase, sudo_ev_get_fd(iob->revent));
+ }
+ safe_close(fd);
+ ev_free_by_fd(evbase, fd);
+ break;
+ case EINTR:
+ case EAGAIN:
+ /* Not an error, retry later. */
+ break;
+ default:
+ /* XXX - need a way to distinguish non-exec error. */
+ iob->ec->cstat->type = CMD_ERRNO;
+ iob->ec->cstat->val = errno;
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "error writing fd %d: %s", fd, strerror(errno));
+ sudo_ev_loopbreak(evbase);
+ break;
+ }
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "wrote %zd bytes to fd %d", n, fd);
+ iob->off += (unsigned int)n;
+ /* Disable writer and reset the buffer if fully consumed. */
+ if (iob->off == iob->len) {
+ iob->off = iob->len = 0;
+ sudo_ev_del(evbase, iob->wevent);
+ /* Forward the EOF from reader to writer. */
+ if (iob->revent == NULL) {
+ safe_close(fd);
+ ev_free_by_fd(evbase, fd);
+ }
+ }
+ /*
+ * Enable reader if buffer is not full but avoid reading
+ * /dev/tty if the command is no longer running.
+ */
+ if (iob->revent != NULL && iob->len != sizeof(iob->buf)) {
+ if (!USERTTY_EVENT(iob->revent) || iob->ec->cmnd_pid != -1) {
+ if (sudo_ev_add(evbase, iob->revent, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+ }
+ }
+ }
+
+ debug_return;
+}
+
+/*
+ * If std{in,out,err} are not connected to a terminal, interpose
+ * ourselves using a pipe. Fills in io_pipe[][].
+ */
+static void
+interpose_pipes(struct exec_closure *ec, const char *tty, int io_pipe[3][2])
+{
+ bool interpose[3] = { false, false, false };
+ struct stat sb, tty_sbuf, *tty_sb = NULL;
+ struct plugin_container *plugin;
+ bool want_winch = false;
+ debug_decl(interpose_pipes, SUDO_DEBUG_EXEC);
+
+ /*
+ * Determine whether any of std{in,out,err} or window size changes
+ * should be logged.
+ */
+ TAILQ_FOREACH(plugin, &io_plugins, entries) {
+ if (plugin->u.io->log_stdin)
+ interpose[STDIN_FILENO] = true;
+ if (plugin->u.io->log_stdout)
+ interpose[STDOUT_FILENO] = true;
+ if (plugin->u.io->log_stderr)
+ interpose[STDERR_FILENO] = true;
+ if (plugin->u.io->version >= SUDO_API_MKVERSION(1, 12)) {
+ if (plugin->u.io->change_winsize)
+ want_winch = true;
+ }
+ }
+
+ /*
+ * If stdin, stdout or stderr is not the user's tty and logging is
+ * enabled, use a pipe to interpose ourselves.
+ */
+ if (tty != NULL && stat(tty, &tty_sbuf) != -1)
+ tty_sb = &tty_sbuf;
+
+ if (interpose[STDIN_FILENO]) {
+ if (!fd_matches_tty(STDIN_FILENO, tty_sb, &sb)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "stdin not user's tty, creating a pipe");
+ if (pipe2(io_pipe[STDIN_FILENO], O_CLOEXEC) != 0)
+ sudo_fatal("%s", U_("unable to create pipe"));
+ io_buf_new(STDIN_FILENO, io_pipe[STDIN_FILENO][1],
+ log_stdin, read_callback, write_callback, ec);
+ }
+ }
+ if (interpose[STDOUT_FILENO]) {
+ if (!fd_matches_tty(STDOUT_FILENO, tty_sb, &sb)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "stdout not user's tty, creating a pipe");
+ if (pipe2(io_pipe[STDOUT_FILENO], O_CLOEXEC) != 0)
+ sudo_fatal("%s", U_("unable to create pipe"));
+ io_buf_new(io_pipe[STDOUT_FILENO][0], STDOUT_FILENO,
+ log_stdout, read_callback, write_callback, ec);
+ }
+ }
+ if (interpose[STDERR_FILENO]) {
+ if (!fd_matches_tty(STDERR_FILENO, tty_sb, &sb)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "stderr not user's tty, creating a pipe");
+ if (pipe2(io_pipe[STDERR_FILENO], O_CLOEXEC) != 0)
+ sudo_fatal("%s", U_("unable to create pipe"));
+ io_buf_new(io_pipe[STDERR_FILENO][0], STDERR_FILENO,
+ log_stderr, read_callback, write_callback, ec);
+ }
+ }
+ if (want_winch) {
+ /* Need /dev/tty for SIGWINCH handling. */
+ io_fds[SFD_USERTTY] = open(_PATH_TTY, O_RDWR);
+ }
+}
+
+/*
+ * Execute a command and wait for it to finish.
+ */
+void
+exec_nopty(struct command_details *details,
+ const struct user_details *user_details,
+ struct sudo_event_base *evbase, struct command_status *cstat)
+{
+ int io_pipe[3][2] = { { -1, -1 }, { -1, -1 }, { -1, -1 } };
+ int errpipe[2], intercept_sv[2] = { -1, -1 };
+ struct exec_closure ec = { 0 };
+ sigset_t set, oset;
+ debug_decl(exec_nopty, SUDO_DEBUG_EXEC);
+
+ /*
+ * The policy plugin's session init must be run before we fork
+ * or certain pam modules won't be able to track their state.
+ */
+ if (policy_init_session(details) != true)
+ sudo_fatalx("%s", U_("policy plugin failed session initialization"));
+
+ /*
+ * We use a pipe to get errno if execve(2) fails in the child.
+ */
+ if (pipe2(errpipe, O_CLOEXEC) != 0)
+ sudo_fatal("%s", U_("unable to create pipe"));
+
+ if (ISSET(details->flags, CD_INTERCEPT|CD_LOG_SUBCMDS)) {
+ if (!ISSET(details->flags, CD_USE_PTRACE)) {
+ /*
+ * Allocate a socketpair for communicating with sudo_intercept.so.
+ * This must be inherited across exec, hence no FD_CLOEXEC.
+ */
+ if (socketpair(PF_UNIX, SOCK_STREAM, 0, intercept_sv) == -1)
+ sudo_fatal("%s", U_("unable to create sockets"));
+ }
+ }
+
+ /* Interpose std{in,out,err} with pipes if logging I/O. */
+ interpose_pipes(&ec, user_details->tty, io_pipe);
+
+ /*
+ * Block signals until we have our handlers setup in the parent so
+ * we don't miss SIGCHLD if the command exits immediately.
+ */
+ sigfillset(&set);
+ sigprocmask(SIG_BLOCK, &set, &oset);
+
+ /* Check for early termination or suspend signals before we fork. */
+ if (sudo_terminated(cstat)) {
+ sigprocmask(SIG_SETMASK, &oset, NULL);
+ debug_return;
+ }
+
+#ifdef HAVE_SELINUX
+ if (ISSET(details->flags, CD_RBAC_ENABLED)) {
+ if (selinux_relabel_tty(details->tty, -1) == -1) {
+ cstat->type = CMD_ERRNO;
+ cstat->val = errno;
+ debug_return;
+ }
+ selinux_audit_role_change();
+ }
+#endif
+
+ ec.cmnd_pid = sudo_debug_fork();
+ switch (ec.cmnd_pid) {
+ case -1:
+ sudo_fatal("%s", U_("unable to fork"));
+ break;
+ case 0:
+ /* child */
+ close(errpipe[0]);
+ if (intercept_sv[0] != -1)
+ close(intercept_sv[0]);
+ /* Replace stdin/stdout/stderr with pipes as needed and exec. */
+ if (io_pipe[STDIN_FILENO][0] != -1) {
+ if (dup3(io_pipe[STDIN_FILENO][0], STDIN_FILENO, 0) == -1)
+ sudo_fatal("dup3");
+ close(io_pipe[STDIN_FILENO][0]);
+ close(io_pipe[STDIN_FILENO][1]);
+ }
+ if (io_pipe[STDOUT_FILENO][0] != -1) {
+ if (dup3(io_pipe[STDOUT_FILENO][1], STDOUT_FILENO, 0) == -1)
+ sudo_fatal("dup3");
+ close(io_pipe[STDOUT_FILENO][0]);
+ close(io_pipe[STDOUT_FILENO][1]);
+ }
+ if (io_pipe[STDERR_FILENO][0] != -1) {
+ if (dup3(io_pipe[STDERR_FILENO][1], STDERR_FILENO, 0) == -1)
+ sudo_fatal("dup3");
+ close(io_pipe[STDERR_FILENO][0]);
+ close(io_pipe[STDERR_FILENO][1]);
+ }
+ exec_cmnd(details, &oset, intercept_sv[1], errpipe[1]);
+ while (write(errpipe[1], &errno, sizeof(int)) == -1) {
+ if (errno != EINTR)
+ break;
+ }
+ sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, 1);
+ _exit(EXIT_FAILURE);
+ /* NOTREACHED */
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "executed %s, pid %d", details->command,
+ (int)ec.cmnd_pid);
+ /* Close the other end of the pipes and socketpairs. */
+ if (io_pipe[STDIN_FILENO][0] != -1)
+ close(io_pipe[STDIN_FILENO][0]);
+ if (io_pipe[STDOUT_FILENO][1] != -1)
+ close(io_pipe[STDOUT_FILENO][1]);
+ if (io_pipe[STDERR_FILENO][1] != -1)
+ close(io_pipe[STDERR_FILENO][1]);
+ close(errpipe[1]);
+ if (intercept_sv[1] != -1)
+ close(intercept_sv[1]);
+
+ /* No longer need execfd. */
+ if (details->execfd != -1) {
+ close(details->execfd);
+ details->execfd = -1;
+ }
+
+ /* Set command timeout if specified. */
+ if (ISSET(details->flags, CD_SET_TIMEOUT))
+ alarm(details->timeout);
+
+ /*
+ * Fill in exec closure, allocate event base, signal events and
+ * the error pipe event.
+ */
+ fill_exec_closure(&ec, cstat, details, user_details, evbase, errpipe[0]);
+
+ if (ISSET(details->flags, CD_INTERCEPT|CD_LOG_SUBCMDS)) {
+ int rc = 1;
+
+ /* Create event and closure for intercept mode. */
+ ec.intercept = intercept_setup(intercept_sv[0], ec.evbase, details);
+ if (ec.intercept == NULL) {
+ rc = -1;
+ } else if (ISSET(details->flags, CD_USE_PTRACE)) {
+ /* Try to seize control of the command using ptrace(2). */
+ rc = exec_ptrace_seize(ec.cmnd_pid);
+ if (rc == 0) {
+ /* There is another tracer present. */
+ CLR(details->flags, CD_INTERCEPT|CD_LOG_SUBCMDS|CD_USE_PTRACE);
+ }
+ }
+ if (rc == -1)
+ terminate_command(ec.cmnd_pid, false);
+ }
+
+ /* Enable any I/O log events. */
+ add_io_events(&ec);
+
+ /* Restore signal mask now that signal handlers are setup. */
+ sigprocmask(SIG_SETMASK, &oset, NULL);
+
+ /*
+ * Non-pty event loop.
+ * Wait for command to exit, handles signals and the error pipe.
+ */
+ if (sudo_ev_dispatch(ec.evbase) == -1)
+ sudo_warn("%s", U_("error in event loop"));
+ if (sudo_ev_got_break(ec.evbase)) {
+ /* error from callback */
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "event loop exited prematurely");
+ /* kill command */
+ terminate_command(ec.cmnd_pid, false);
+ ec.cmnd_pid = -1;
+ }
+
+#ifdef HAVE_SELINUX
+ if (ISSET(details->flags, CD_RBAC_ENABLED)) {
+ if (selinux_restore_tty() != 0)
+ sudo_warnx("%s", U_("unable to restore tty label"));
+ }
+#endif
+
+ /* Flush any remaining output. */
+ del_io_events(true);
+
+ /* Free things up. */
+ free_io_bufs();
+ free_exec_closure(&ec);
+
+ debug_return;
+}
+
+/*
+ * Wait for command status after receiving SIGCHLD.
+ * If the command exits, fill in cstat and stop the event loop.
+ * If the command stops, save the tty pgrp, suspend sudo, then restore
+ * the tty pgrp when sudo resumes.
+ */
+static void
+handle_sigchld_nopty(struct exec_closure *ec)
+{
+ pid_t pid;
+ int status;
+ char signame[SIG2STR_MAX];
+ debug_decl(handle_sigchld_nopty, SUDO_DEBUG_EXEC);
+
+ /* There may be multiple children in intercept mode. */
+ for (;;) {
+ do {
+ pid = waitpid(-1, &status, __WALL|WUNTRACED|WNOHANG);
+ } while (pid == -1 && errno == EINTR);
+ switch (pid) {
+ case -1:
+ if (errno != ECHILD) {
+ sudo_warn(U_("%s: %s"), __func__, "waitpid");
+ debug_return;
+ }
+ FALLTHROUGH;
+ case 0:
+ /* Nothing left to wait for. */
+ debug_return;
+ }
+
+ if (WIFSTOPPED(status)) {
+ const int signo = WSTOPSIG(status);
+
+ if (sig2str(signo, signame) == -1)
+ (void)snprintf(signame, sizeof(signame), "%d", signo);
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: process %d stopped, SIG%s", __func__, (int)pid, signame);
+
+ if (ISSET(ec->details->flags, CD_USE_PTRACE)) {
+ /* If not a group-stop signal, just continue. */
+ if (!exec_ptrace_stopped(pid, status, ec->intercept))
+ continue;
+ }
+
+ /* If the main command is suspended, suspend sudo too. */
+ if (pid == ec->cmnd_pid) {
+ sudo_suspend_parent(signo, ec->sudo_pid, ec->ppgrp,
+ ec->cmnd_pid, ec, log_suspend);
+ }
+ } else {
+ if (WIFSIGNALED(status)) {
+ if (sig2str(WTERMSIG(status), signame) == -1) {
+ (void)snprintf(signame, sizeof(signame), "%d",
+ WTERMSIG(status));
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: process %d killed, SIG%s", __func__,
+ (int)pid, signame);
+ } else if (WIFEXITED(status)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: process %d exited: %d", __func__,
+ (int)pid, WEXITSTATUS(status));
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN,
+ "%s: unexpected wait status 0x%x for process %d",
+ __func__, status, (int)pid);
+ }
+
+ /* Only store exit status of the main command. */
+ if (pid != ec->cmnd_pid)
+ continue;
+
+ /* Don't overwrite execve() failure with command exit status. */
+ if (ec->cstat->type == CMD_INVALID) {
+ ec->cstat->type = CMD_WSTATUS;
+ ec->cstat->val = status;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN,
+ "%s: not overwriting command status %d,%d with %d,%d",
+ __func__, ec->cstat->type, ec->cstat->val,
+ CMD_WSTATUS, status);
+ }
+ ec->cmnd_pid = -1;
+ }
+ }
+}
diff --git a/src/exec_preload.c b/src/exec_preload.c
new file mode 100644
index 0000000..f463716
--- /dev/null
+++ b/src/exec_preload.c
@@ -0,0 +1,419 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sudo.h>
+#include <sudo_exec.h>
+#include <sudo_util.h>
+
+#ifdef RTLD_PRELOAD_VAR
+typedef void * (*sudo_alloc_fn_t)(size_t, size_t);
+typedef void (*sudo_free_fn_t)(void *);
+
+static void *
+sudo_allocarray(size_t nmemb, size_t size)
+{
+ return reallocarray(NULL, nmemb, size);
+}
+
+/*
+ * Allocate space for the string described by fmt and return it,
+ * or NULL on error.
+ * Currently only supports %%, %c, %d, and %s escapes.
+ */
+static char *
+fmtstr(sudo_alloc_fn_t alloc_fn, sudo_free_fn_t free_fn, const char * restrict ofmt, ...)
+{
+ char *cp, *cur, *newstr = NULL;
+ size_t len, size = 1;
+ const char *fmt;
+ va_list ap;
+ debug_decl(fmtstr, SUDO_DEBUG_UTIL);
+
+ /* Determine size. */
+ va_start(ap, ofmt);
+ for (fmt = ofmt; *fmt != '\0'; ) {
+ if (fmt[0] == '%') {
+ switch (fmt[1]) {
+ case 'c':
+ (void)va_arg(ap, int);
+ FALLTHROUGH;
+ case '%':
+ size++;
+ fmt += 2;
+ continue;
+ case 's':
+ cp = va_arg(ap, char *);
+ size += strlen(cp ? cp : "(NULL)");
+ fmt += 2;
+ continue;
+ case 'd': {
+ char numbuf[STRLEN_MAX_SIGNED(int) + 1];
+ len = (size_t)snprintf(numbuf, sizeof(numbuf), "%d",
+ va_arg(ap, int));
+ if (len >= sizeof(numbuf)) {
+ goto oflow;
+ }
+ size += len;
+ fmt += 2;
+ continue;
+ }
+ default:
+ /* Treat as literal. */
+ break;
+ }
+ }
+ size++;
+ fmt++;
+ }
+ va_end(ap);
+
+ newstr = alloc_fn(1, size);
+ if (newstr == NULL)
+ debug_return_str(NULL);
+
+ /* Format/copy data. */
+ cur = newstr;
+ va_start(ap, ofmt);
+ for (fmt = ofmt; *fmt != '\0'; ) {
+ if (fmt[0] == '%') {
+ switch (fmt[1]) {
+ case '%':
+ if (size < 2) {
+ goto oflow;
+ }
+ *cur++ = '%';
+ size--;
+ fmt += 2;
+ continue;
+ case 'c':
+ if (size < 2) {
+ goto oflow;
+ }
+ *cur++ = (char )va_arg(ap, int);
+ size--;
+ fmt += 2;
+ continue;
+ case 's':
+ cp = va_arg(ap, char *);
+ len = strlcpy(cur, cp ? cp : "(NULL)", size);
+ if (len >= size) {
+ goto oflow;
+ }
+ cur += len;
+ size -= len;
+ fmt += 2;
+ continue;
+ case 'd':
+ len = (size_t)snprintf(cur, size, "%d", va_arg(ap, int));
+ if (len >= size) {
+ goto oflow;
+ }
+ cur += len;
+ size -= len;
+ fmt += 2;
+ continue;
+ default:
+ /* Treat as literal. */
+ break;
+ }
+ }
+ if (size < 2) {
+ goto oflow;
+ }
+ *cur++ = *fmt++;
+ size++;
+ }
+
+ if (size < 1) {
+ goto oflow;
+ }
+ *cur = '\0';
+ va_end(ap);
+
+ debug_return_str(newstr);
+
+oflow:
+ /* We pre-allocate enough space, so this should never happen. */
+ va_end(ap);
+ free_fn(newstr);
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ debug_return_str(NULL);
+}
+
+/*
+ * Add a DSO file to LD_PRELOAD or the system equivalent.
+ */
+static char **
+sudo_preload_dso_alloc(char *const envp[], const char *preload_var,
+ const char *dso_file, int intercept_fd,
+ sudo_alloc_fn_t alloc_fn, sudo_free_fn_t free_fn)
+{
+ const size_t preload_var_len = strlen(preload_var);
+ char *preload = NULL;
+ char **nep, **nenvp = NULL;
+ char *const *ep;
+ char **preload_ptr = NULL;
+ char **intercept_ptr = NULL;
+ char *const empty[1] = { NULL };
+ bool fd_present = false;
+ bool dso_present = false;
+# ifdef RTLD_PRELOAD_ENABLE_VAR
+ bool dso_enabled = false;
+# else
+ const bool dso_enabled = true;
+# endif
+# ifdef _PATH_ASAN_LIB
+ char *dso_buf = NULL;
+# endif
+ size_t env_size;
+ debug_decl(sudo_preload_dso_alloc, SUDO_DEBUG_UTIL);
+
+# ifdef _PATH_ASAN_LIB
+ /*
+ * The address sanitizer DSO needs to be first in the list.
+ */
+ dso_buf = fmtstr(alloc_fn, free_fn, "%s%c%s", _PATH_ASAN_LIB,
+ RTLD_PRELOAD_DELIM, dso_file);
+ if (dso_buf == NULL) {
+ goto oom;
+ }
+ dso_file = dso_buf;
+# endif
+
+ /*
+ * Preload a DSO file. For a list of LD_PRELOAD-alikes, see
+ * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
+ * XXX - need to support 32-bit and 64-bit variants
+ */
+
+ /* Treat a NULL envp as empty, thanks Linux. */
+ if (envp == NULL)
+ envp = empty;
+
+ /* Determine max size for new envp. */
+ for (env_size = 0; envp[env_size] != NULL; env_size++)
+ continue;
+ if (!dso_enabled)
+ env_size++;
+ if (intercept_fd != -1)
+ env_size++;
+ env_size += 2; /* dso_file + terminating NULL */
+
+ /* Allocate new envp. */
+ nenvp = alloc_fn(env_size, sizeof(*nenvp));
+ if (nenvp == NULL)
+ goto oom;
+
+ /*
+ * Shallow copy envp, with special handling for preload_var,
+ * RTLD_PRELOAD_ENABLE_VAR and SUDO_INTERCEPT_FD.
+ */
+ for (ep = envp, nep = nenvp; *ep != NULL; ep++) {
+ if (strncmp(*ep, preload_var, preload_var_len) == 0 &&
+ (*ep)[preload_var_len] == '=') {
+ const char *cp = *ep + preload_var_len + 1;
+ const size_t dso_len = strlen(dso_file);
+
+ /* Skip duplicates. */
+ if (preload_ptr != NULL)
+ continue;
+
+ /*
+ * Check to see if dso_file is already first in the list.
+ * We don't bother checking for it later in the list.
+ */
+ if (strncmp(cp, dso_file, dso_len) == 0) {
+ if (cp[dso_len] == '\0' || cp[dso_len] == RTLD_PRELOAD_DELIM)
+ dso_present = true;
+ }
+
+ /* Save pointer to LD_PRELOAD variable. */
+ preload_ptr = nep;
+
+ goto copy;
+ }
+ if (intercept_fd != -1 && strncmp(*ep, "SUDO_INTERCEPT_FD=",
+ sizeof("SUDO_INTERCEPT_FD=") - 1) == 0) {
+ const char *cp = *ep + sizeof("SUDO_INTERCEPT_FD=") - 1;
+ const char *errstr;
+ int fd;
+
+ /* Skip duplicates. */
+ if (intercept_ptr != NULL)
+ continue;
+
+ fd = (int)sudo_strtonum(cp, 0, INT_MAX, &errstr);
+ if (fd == intercept_fd && errstr == NULL)
+ fd_present = true;
+
+ /* Save pointer to SUDO_INTERCEPT_FD variable. */
+ intercept_ptr = nep;
+
+ goto copy;
+ }
+# ifdef RTLD_PRELOAD_ENABLE_VAR
+ if (strncmp(*ep, RTLD_PRELOAD_ENABLE_VAR "=",
+ sizeof(RTLD_PRELOAD_ENABLE_VAR)) == 0) {
+ dso_enabled = true;
+ }
+# endif
+copy:
+ *nep++ = *ep; /* shallow copy */
+ }
+
+ /* Prepend our LD_PRELOAD to existing value or add new entry at the end. */
+ if (!dso_present) {
+ if (preload_ptr == NULL) {
+# ifdef RTLD_PRELOAD_DEFAULT
+ preload = fmtstr(alloc_fn, free_fn, "%s=%s%c%s", preload_var,
+ dso_file, RTLD_PRELOAD_DELIM, RTLD_PRELOAD_DEFAULT);
+ if (preload == NULL) {
+ goto oom;
+ }
+# else
+ preload = fmtstr(alloc_fn, free_fn, "%s=%s", preload_var,
+ dso_file);
+ if (preload == NULL) {
+ goto oom;
+ }
+# endif
+ *nep++ = preload;
+ } else {
+ const char *old_val = *preload_ptr + preload_var_len + 1;
+ preload = fmtstr(alloc_fn, free_fn, "%s=%s%c%s", preload_var,
+ dso_file, RTLD_PRELOAD_DELIM, old_val);
+ if (preload == NULL) {
+ goto oom;
+ }
+ *preload_ptr = preload;
+ }
+ }
+# ifdef RTLD_PRELOAD_ENABLE_VAR
+ if (!dso_enabled) {
+ *nenvp++ = RTLD_PRELOAD_ENABLE_VAR "=";
+ }
+# endif
+ if (!fd_present && intercept_fd != -1) {
+ char *fdstr = fmtstr(alloc_fn, free_fn, "SUDO_INTERCEPT_FD=%d",
+ intercept_fd);
+ if (fdstr == NULL) {
+ goto oom;
+ }
+ if (intercept_ptr != NULL) {
+ *intercept_ptr = fdstr;
+ } else {
+ *nep++ = fdstr;
+ }
+ }
+
+ /* NULL terminate nenvp at last. */
+ *nep = NULL;
+
+# ifdef _PATH_ASAN_LIB
+ free_fn(dso_buf);
+# endif
+
+ debug_return_ptr(nenvp);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+# ifdef _PATH_ASAN_LIB
+ free_fn(dso_buf);
+# endif
+ free_fn(preload);
+ free_fn(nenvp);
+ debug_return_ptr(NULL);
+}
+
+static char **
+sudo_preload_dso_path(char *const envp[], const char *dso_file,
+ int intercept_fd, sudo_alloc_fn_t alloc_fn, sudo_free_fn_t free_fn)
+{
+ char **ret = NULL;
+ const char *ep;
+ debug_decl(sudo_preload_dso_path, SUDO_DEBUG_UTIL);
+
+ ep = strchr(dso_file, ':');
+ if (ep == NULL) {
+ /* Use default LD_PRELOAD */
+ return sudo_preload_dso_alloc(envp, RTLD_PRELOAD_VAR, dso_file,
+ intercept_fd, alloc_fn, free_fn);
+ }
+
+ /* Add 32-bit LD_PRELOAD if present. */
+ if (ep != dso_file) {
+#ifdef RTLD_PRELOAD_VAR_32
+ const size_t len = (size_t)(ep - dso_file);
+ char name[PATH_MAX];
+
+ if (len >= sizeof(name)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%.*s: path too long", (int)len, dso_file);
+ } else {
+ memcpy(name, dso_file, len);
+ name[len] = '\0';
+ ret = sudo_preload_dso_alloc(envp, RTLD_PRELOAD_VAR_32, name,
+ intercept_fd, alloc_fn, free_fn);
+ envp = ret;
+ }
+#endif /* RTLD_PRELOAD_VAR_32 */
+ dso_file = ep + 1;
+ }
+
+#ifdef RTLD_PRELOAD_VAR_64
+ /* Add 64-bit LD_PRELOAD if present. */
+ if (*dso_file != '\0') {
+ char **new_envp = sudo_preload_dso_alloc(envp, RTLD_PRELOAD_VAR_64,
+ dso_file, intercept_fd, alloc_fn, free_fn);
+ free_fn(ret);
+ ret = new_envp;
+ }
+#endif /* RTLD_PRELOAD_VAR_64 */
+
+ debug_return_ptr(ret);
+}
+
+char **
+sudo_preload_dso_mmap(char *const envp[], const char *dso_file,
+ int intercept_fd)
+{
+ return sudo_preload_dso_path(envp, dso_file, intercept_fd,
+ sudo_mmap_allocarray_v1, sudo_mmap_free_v1);
+}
+
+char **
+sudo_preload_dso(char *const envp[], const char *dso_file,
+ int intercept_fd)
+{
+ return sudo_preload_dso_path(envp, dso_file, intercept_fd,
+ sudo_allocarray, free);
+}
+#endif /* RTLD_PRELOAD_VAR */
diff --git a/src/exec_ptrace.c b/src/exec_ptrace.c
new file mode 100644
index 0000000..b8a0789
--- /dev/null
+++ b/src/exec_ptrace.c
@@ -0,0 +1,2135 @@
+/*
+ * Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#if defined(HAVE_ENDIAN_H)
+# include <endian.h>
+#elif defined(HAVE_SYS_ENDIAN_H)
+# include <sys/endian.h>
+#elif defined(HAVE_MACHINE_ENDIAN_H)
+# include <machine/endian.h>
+#else
+# include <compat/endian.h>
+#endif
+
+#include <sudo.h>
+#include <sudo_exec.h>
+
+#ifdef HAVE_PTRACE_INTERCEPT
+# include <exec_intercept.h>
+# include <exec_ptrace.h>
+
+/* We need to take care when ptracing 32-bit binaries on 64-bit kernels. */
+# ifdef __LP64__
+# define COMPAT_FLAG 0x01
+# else
+# define COMPAT_FLAG 0x00
+# endif
+
+static int seccomp_trap_supported = -1;
+#ifdef HAVE_PROCESS_VM_READV
+static size_t page_size;
+#endif
+static size_t arg_max;
+
+/* Register getters and setters. */
+# ifdef SECCOMP_AUDIT_ARCH_COMPAT
+static inline unsigned long
+get_stack_pointer(struct sudo_ptrace_regs *regs)
+{
+ if (regs->compat) {
+ return compat_reg_sp(regs->u.compat);
+ } else {
+ return reg_sp(regs->u.native);
+ }
+}
+
+static inline void
+set_sc_retval(struct sudo_ptrace_regs *regs, int retval)
+{
+ if (regs->compat) {
+ compat_reg_set_retval(regs->u.compat, retval);
+ } else {
+ reg_set_retval(regs->u.native, retval);
+ }
+}
+
+static inline int
+get_syscallno(struct sudo_ptrace_regs *regs)
+{
+ if (regs->compat) {
+ return compat_reg_syscall(regs->u.compat);
+ } else {
+ return reg_syscall(regs->u.native);
+ }
+}
+
+static inline void
+set_syscallno(pid_t pid, struct sudo_ptrace_regs *regs, int syscallno)
+{
+ if (regs->compat) {
+ compat_reg_set_syscall(regs->u.compat, syscallno);
+ } else {
+ reg_set_syscall(regs->u.native, syscallno);
+ }
+}
+
+static inline unsigned long
+get_sc_arg1(struct sudo_ptrace_regs *regs)
+{
+ if (regs->compat) {
+ return compat_reg_arg1(regs->u.compat);
+ } else {
+ return reg_arg1(regs->u.native);
+ }
+}
+
+static inline void
+set_sc_arg1(struct sudo_ptrace_regs *regs, unsigned long addr)
+{
+ if (regs->compat) {
+ compat_reg_set_arg1(regs->u.compat, addr);
+ } else {
+ reg_set_arg1(regs->u.native, addr);
+ }
+}
+
+static inline unsigned long
+get_sc_arg2(struct sudo_ptrace_regs *regs)
+{
+ if (regs->compat) {
+ return compat_reg_arg2(regs->u.compat);
+ } else {
+ return reg_arg2(regs->u.native);
+ }
+}
+
+static inline void
+set_sc_arg2(struct sudo_ptrace_regs *regs, unsigned long addr)
+{
+ if (regs->compat) {
+ compat_reg_set_arg2(regs->u.compat, addr);
+ } else {
+ reg_set_arg2(regs->u.native, addr);
+ }
+}
+
+static inline unsigned long
+get_sc_arg3(struct sudo_ptrace_regs *regs)
+{
+ if (regs->compat) {
+ return compat_reg_arg3(regs->u.compat);
+ } else {
+ return reg_arg3(regs->u.native);
+ }
+}
+
+# ifdef notyet
+static inline void
+set_sc_arg3(struct sudo_ptrace_regs *regs, unsigned long addr)
+{
+ if (regs->compat) {
+ compat_reg_set_arg3(regs->u.compat, addr);
+ } else {
+ reg_set_arg3(regs->u.native, addr);
+ }
+}
+
+static inline unsigned long
+get_sc_arg4(struct sudo_ptrace_regs *regs)
+{
+ if (regs->compat) {
+ return compat_reg_arg4(regs->u.compat);
+ } else {
+ return reg_arg4(regs->u.native);
+ }
+}
+
+static inline void
+set_sc_arg4(struct sudo_ptrace_regs *regs, unsigned long addr)
+{
+ if (regs->compat) {
+ compat_reg_set_arg4(regs->u.compat, addr);
+ } else {
+ reg_set_arg4(regs->u.native, addr);
+ }
+}
+# endif /* notyet */
+
+# else /* SECCOMP_AUDIT_ARCH_COMPAT */
+
+static inline unsigned long
+get_stack_pointer(struct sudo_ptrace_regs *regs)
+{
+ return reg_sp(regs->u.native);
+}
+
+static inline void
+set_sc_retval(struct sudo_ptrace_regs *regs, int retval)
+{
+ reg_set_retval(regs->u.native, retval);
+}
+
+static inline int
+get_syscallno(struct sudo_ptrace_regs *regs)
+{
+ return reg_syscall(regs->u.native);
+}
+
+static inline void
+set_syscallno(pid_t pid, struct sudo_ptrace_regs *regs, int syscallno)
+{
+ reg_set_syscall(regs->u.native, syscallno);
+}
+
+static inline unsigned long
+get_sc_arg1(struct sudo_ptrace_regs *regs)
+{
+ return reg_arg1(regs->u.native);
+}
+
+static inline void
+set_sc_arg1(struct sudo_ptrace_regs *regs, unsigned long addr)
+{
+ reg_set_arg1(regs->u.native, addr);
+}
+
+static inline unsigned long
+get_sc_arg2(struct sudo_ptrace_regs *regs)
+{
+ return reg_arg2(regs->u.native);
+}
+
+static inline void
+set_sc_arg2(struct sudo_ptrace_regs *regs, unsigned long addr)
+{
+ reg_set_arg2(regs->u.native, addr);
+}
+
+static inline unsigned long
+get_sc_arg3(struct sudo_ptrace_regs *regs)
+{
+ return reg_arg3(regs->u.native);
+}
+
+# ifdef notyet
+static inline void
+set_sc_arg3(struct sudo_ptrace_regs *regs, unsigned long addr)
+{
+ reg_set_arg3(regs->u.native, addr);
+}
+
+static inline unsigned long
+get_sc_arg4(struct sudo_ptrace_regs *regs)
+{
+ return reg_arg4(regs->u.native);
+}
+
+static inline void
+set_sc_arg4(struct sudo_ptrace_regs *regs, unsigned long addr)
+{
+ reg_set_arg4(regs->u.native, addr);
+}
+# endif /* notyet */
+# endif /* SECCOMP_AUDIT_ARCH_COMPAT */
+
+/*
+ * Get the registers for the given process and store in regs, which
+ * must be large enough. If the compat flag is set, pid is expected
+ * to refer to a 32-bit process and the md parameters will be filled
+ * in accordingly.
+ * Returns true on success, else false.
+ */
+static bool
+ptrace_getregs(int pid, struct sudo_ptrace_regs *regs, int compat)
+{
+ struct iovec iov;
+ debug_decl(ptrace_getregs, SUDO_DEBUG_EXEC);
+
+ iov.iov_base = &regs->u;
+ iov.iov_len = sizeof(regs->u);
+
+# ifdef __mips__
+ /* PTRACE_GETREGSET has bugs with the MIPS o32 ABI at least. */
+ if (ptrace(PTRACE_GETREGS, pid, NULL, iov.iov_base) == -1)
+ debug_return_bool(false);
+# else
+ if (ptrace(PTRACE_GETREGSET, pid, (void *)NT_PRSTATUS, &iov) == -1)
+ debug_return_bool(false);
+# endif /* __mips__ */
+ if (compat == -1) {
+# ifdef SECCOMP_AUDIT_ARCH_COMPAT
+ if (sizeof(regs->u.native) != sizeof(regs->u.compat)) {
+ /* Guess compat based on size of register struct returned. */
+ compat = iov.iov_len != sizeof(regs->u.native);
+ } else {
+ /* Assume a 64-bit executable will have a 64-bit stack pointer. */
+ compat = reg_sp(regs->u.native) < 0xffffffff;
+ }
+# else
+ compat = false;
+# endif /* SECCOMP_AUDIT_ARCH_COMPAT */
+ }
+
+ /* Machine-dependent parameters to support compat binaries. */
+ if (compat) {
+ regs->compat = true;
+ regs->wordsize = sizeof(int);
+ } else {
+ regs->compat = false;
+ regs->wordsize = sizeof(long);
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Set the registers, specified by regs, for the given process.
+ * Returns true on success, else false.
+ */
+static bool
+ptrace_setregs(int pid, struct sudo_ptrace_regs *regs)
+{
+ debug_decl(ptrace_setregs, SUDO_DEBUG_EXEC);
+
+# ifdef __mips__
+ /* PTRACE_SETREGSET has bugs with the MIPS o32 ABI at least. */
+ if (ptrace(PTRACE_SETREGS, pid, NULL, &regs->u) == -1)
+ debug_return_bool(false);
+# else
+ struct iovec iov;
+ iov.iov_base = &regs->u;
+ iov.iov_len = sizeof(regs->u);
+ if (ptrace(PTRACE_SETREGSET, pid, (void *)NT_PRSTATUS, &iov) == -1)
+ debug_return_bool(false);
+# endif /* __mips__ */
+
+ debug_return_bool(true);
+}
+
+#ifdef HAVE_PROCESS_VM_READV
+/*
+ * Read the string at addr and store in buf using process_vm_readv(2).
+ * Returns the number of bytes stored, including the NUL.
+ */
+static ssize_t
+ptrace_readv_string(pid_t pid, unsigned long addr, char *buf, size_t bufsize)
+{
+ const char *cp, *buf0 = buf;
+ struct iovec local, remote;
+ ssize_t nread;
+ debug_decl(ptrace_read_string, SUDO_DEBUG_EXEC);
+
+ /*
+ * Read the string via process_vm_readv(2) one page at a time.
+ * We could do larger reads but since we don't know the length
+ * of the string, going one page at a time is simplest.
+ */
+ for (;;) {
+ if (bufsize == 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: %d: out of space reading string", __func__, (int)pid);
+ errno = ENOSPC;
+ debug_return_ssize_t(-1);
+ }
+
+ local.iov_base = buf;
+ local.iov_len = bufsize;
+ remote.iov_base = (void *)addr;
+ remote.iov_len = MIN(bufsize, page_size);
+
+ nread = process_vm_readv(pid, &local, 1, &remote, 1, 0);
+ switch (nread) {
+ case -1:
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "process_vm_readv(%d, [0x%lx, %zu], 1, [0x%lx, %zu], 1, 0)",
+ (int)pid, (unsigned long)local.iov_base, local.iov_len,
+ (unsigned long)remote.iov_base, remote.iov_len);
+ debug_return_ssize_t(-1);
+ case 0:
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "process_vm_readv(%d, [0x%lx, %zu], 1, [0x%lx, %zu], 1, 0): %s",
+ (int)pid, (unsigned long)local.iov_base, local.iov_len,
+ (unsigned long)remote.iov_base, remote.iov_len, "premature EOF");
+ debug_return_ssize_t(-1);
+ default:
+ /* Check for NUL terminator in page. */
+ cp = memchr(buf, '\0', (size_t)nread);
+ if (cp != NULL)
+ debug_return_ssize_t((cp - buf0) + 1); /* includes NUL */
+ buf += nread;
+ bufsize -= (size_t)nread;
+ addr += sizeof(unsigned long);
+ break;
+ }
+ }
+ debug_return_ssize_t(-1);
+}
+#endif /* HAVE_PROCESS_VM_READV */
+
+/*
+ * Read the string at addr and store in buf using ptrace(2).
+ * Returns the number of bytes stored, including the NUL.
+ */
+static ssize_t
+ptrace_read_string(pid_t pid, unsigned long addr, char *buf, size_t bufsize)
+{
+ const char *cp, *buf0 = buf;
+ unsigned long word;
+ size_t i;
+ debug_decl(ptrace_read_string, SUDO_DEBUG_EXEC);
+
+#ifdef HAVE_PROCESS_VM_READV
+ ssize_t nread = ptrace_readv_string(pid, addr, buf, bufsize);
+ if (nread != -1 || errno != ENOSYS)
+ debug_return_ssize_t(nread);
+#endif /* HAVE_PROCESS_VM_READV */
+
+ /*
+ * Read the string via ptrace(2) one (native) word at a time.
+ * We use the native word size even in compat mode because that
+ * is the unit ptrace(2) uses.
+ */
+ for (;;) {
+ word = ptrace(PTRACE_PEEKDATA, pid, addr, NULL);
+ if (word == (unsigned long)-1) {
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "ptrace(PTRACE_PEEKDATA, %d, 0x%lx, NULL)", (int)pid, addr);
+ debug_return_ssize_t(-1);
+ }
+
+ cp = (char *)&word;
+ for (i = 0; i < sizeof(unsigned long); i++) {
+ if (bufsize == 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: %d: out of space reading string", __func__, (int)pid);
+ errno = ENOSPC;
+ debug_return_ssize_t(-1);
+ }
+ *buf = cp[i];
+ if (*buf++ == '\0')
+ debug_return_ssize_t(buf - buf0);
+ bufsize--;
+ }
+ addr += sizeof(unsigned long);
+ }
+}
+
+/*
+ * Expand buf by doubling its size.
+ * Updates bufp and bufsizep and recalculates curp and remp if non-NULL.
+ * Returns true on success, else false.
+ */
+static bool
+growbuf(char **bufp, size_t *bufsizep, char **curp, size_t *remp)
+{
+ const size_t oldsize = *bufsizep;
+ char *newbuf;
+ debug_decl(growbuf, SUDO_DEBUG_EXEC);
+
+ /* Double the size of the buffer. */
+ newbuf = reallocarray(*bufp, 2, oldsize);
+ if (newbuf == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ if (curp != NULL)
+ *curp = newbuf + (*curp - *bufp);
+ if (remp != NULL)
+ *remp += oldsize;
+ *bufp = newbuf;
+ *bufsizep = 2 * oldsize;
+ debug_return_bool(true);
+}
+
+/*
+ * Build a NULL-terminated string vector from a string table.
+ * On success, returns number of bytes used for the vector and sets
+ * vecp to the start of the vector and countp to the number of elements
+ * (not including the NULL). The buffer is resized as needed.
+ * Both vecp and its elements are stored as offsets into buf, not pointers.
+ * However, NULL is still stored as NULL.
+ * Returns (size_t)-1 on failure.
+ */
+static ssize_t
+strtab_to_vec(char *strtab, size_t strtab_len, int *countp, char ***vecp,
+ char **bufp, size_t *bufsizep, size_t remainder)
+{
+ char *strend = strtab + strtab_len;
+ char **vec, **vp;
+ int count = 0;
+ debug_decl(strtab_to_vec, SUDO_DEBUG_EXEC);
+
+ /* Store vector in buf after string table and make it aligned. */
+ while (remainder < 2 * sizeof(char *)) {
+ if (!growbuf(bufp, bufsizep, &strtab, &remainder))
+ debug_return_ssize_t(-1);
+ strend = strtab + strtab_len;
+ }
+ vec = (char **)LONGALIGN(strend);
+ remainder -= (size_t)((char *)vec - strend);
+
+ /* Fill in vector with the strings we read. */
+ for (vp = vec; strtab < strend; ) {
+ while (remainder < 2 * sizeof(char *)) {
+ if (!growbuf(bufp, bufsizep, &strtab, &remainder))
+ debug_return_ssize_t(-1);
+ strend = strtab + strtab_len;
+ vec = (char **)LONGALIGN(strend);
+ vp = vec + count;
+ }
+ /* Store offset into buf (not a pointer) in case of realloc(). */
+ *vp++ = (char *)(strtab - *bufp);
+ remainder -= sizeof(char *);
+ strtab = memchr(strtab, '\0', (size_t)(strend - strtab));
+ if (strtab == NULL)
+ break;
+ strtab++;
+ count++;
+ }
+ *vp++ = NULL; /* we always leave room for NULL */
+
+ *countp = count;
+ *vecp = (char **)((char *)vec - *bufp);
+
+ debug_return_ssize_t((char *)vp - strend);
+}
+
+/*
+ * Read the string vector at addr and store it in bufp, which
+ * is reallocated as needed. The actual vector is returned in vecp.
+ * The count stored in countp does not include the terminating NULL pointer.
+ * The vecp and its contents are _offsets_, not pointers, in case the buffer
+ * gets reallocated later. The caller is responsible for converting the
+ * offsets into pointers based on the buffer before using.
+ * Returns the number of bytes in buf consumed (including NULs).
+ */
+static ssize_t
+ptrace_read_vec(pid_t pid, struct sudo_ptrace_regs *regs, unsigned long addr,
+ int *countp, char ***vecp, char **bufp, size_t *bufsizep, size_t off)
+{
+# ifdef SECCOMP_AUDIT_ARCH_COMPAT
+ unsigned long next_word = (unsigned long)-1;
+# endif
+ size_t strtab_len, remainder = *bufsizep - off;
+ char *strtab = *bufp + off;
+ unsigned long word;
+ ssize_t len;
+ debug_decl(ptrace_read_vec, SUDO_DEBUG_EXEC);
+
+ /* Treat a NULL vector as empty, thanks Linux. */
+ if (addr == 0) {
+ char **vp;
+
+ while (remainder < 2 * sizeof(char *)) {
+ if (!growbuf(bufp, bufsizep, &strtab, &remainder))
+ debug_return_ssize_t(-1);
+ }
+ vp = (char **)LONGALIGN(strtab);
+ *vecp = (char **)((char *)vp - *bufp);
+ *countp = 0;
+ *vp++ = NULL;
+ debug_return_ssize_t((char *)vp - strtab);
+ }
+
+ /* Fill in string table. */
+ do {
+# ifdef SECCOMP_AUDIT_ARCH_COMPAT
+ if (next_word == (unsigned long)-1) {
+ word = ptrace(PTRACE_PEEKDATA, pid, addr, NULL);
+ if (regs->compat) {
+ /* Stash the next compat word in next_word. */
+# if BYTE_ORDER == BIG_ENDIAN
+ next_word = word & 0xffffffffU;
+ word >>= 32;
+# else
+ next_word = word >> 32;
+ word &= 0xffffffffU;
+# endif
+ }
+ } else {
+ /* Use the stashed value of the next word. */
+ word = next_word;
+ next_word = (unsigned long)-1;
+ }
+# else /* SECCOMP_AUDIT_ARCH_COMPAT */
+ word = ptrace(PTRACE_PEEKDATA, pid, addr, NULL);
+# endif /* SECCOMP_AUDIT_ARCH_COMPAT */
+ switch (word) {
+ case -1:
+ sudo_warn("%s: ptrace(PTRACE_PEEKDATA, %d, 0x%lx, NULL)",
+ __func__, (int)pid, addr);
+ debug_return_ssize_t(-1);
+ case 0:
+ /* NULL terminator */
+ break;
+ default:
+ for (;;) {
+ len = ptrace_read_string(pid, word, strtab, remainder);
+ if (len != -1)
+ break;
+ if (errno != ENOSPC)
+ debug_return_ssize_t(-1);
+ if (!growbuf(bufp, bufsizep, &strtab, &remainder))
+ debug_return_ssize_t(-1);
+ }
+ strtab += len;
+ remainder -= (size_t)len;
+ addr += regs->wordsize;
+ continue;
+ }
+ } while (word != 0);
+
+ /* Store strings in a vector after the string table. */
+ strtab_len = (size_t)(strtab - (*bufp + off));
+ strtab = *bufp + off;
+ len = strtab_to_vec(strtab, strtab_len, countp, vecp, bufp, bufsizep,
+ remainder);
+ if (len == -1)
+ debug_return_ssize_t(-1);
+
+ debug_return_ssize_t((ssize_t)strtab_len + len);
+}
+
+#ifdef HAVE_PROCESS_VM_READV
+/*
+ * Write the NUL-terminated string str to addr in the tracee using
+ * process_vm_writev(2).
+ * Returns the number of bytes written, including trailing NUL.
+ */
+static ssize_t
+ptrace_writev_string(pid_t pid, unsigned long addr, const char *str0)
+{
+ const char *str = str0;
+ size_t len = strlen(str) + 1;
+ debug_decl(ptrace_writev_string, SUDO_DEBUG_EXEC);
+
+ /*
+ * Write the string via process_vm_writev(2), handling partial writes.
+ */
+ for (;;) {
+ struct iovec local, remote;
+ ssize_t nwritten;
+
+ local.iov_base = (void *)str;
+ local.iov_len = len;
+ remote.iov_base = (void *)addr;
+ remote.iov_len = len;
+
+ nwritten = process_vm_writev(pid, &local, 1, &remote, 1, 0);
+ switch (nwritten) {
+ case -1:
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "process_vm_writev(%d, [0x%lx, %zu], 1, [0x%lx, %zu], 1, 0)",
+ (int)pid, (unsigned long)local.iov_base, local.iov_len,
+ (unsigned long)remote.iov_base, remote.iov_len);
+ debug_return_ssize_t(-1);
+ case 0:
+ /* Should not be possible. */
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "process_vm_writev(%d, [0x%lx, %zu], 1, [0x%lx, %zu], 1, 0): %s",
+ (int)pid, (unsigned long)local.iov_base, local.iov_len,
+ (unsigned long)remote.iov_base, remote.iov_len,
+ "zero bytes written");
+ debug_return_ssize_t(-1);
+ default:
+ str += nwritten;
+ len -= (size_t)nwritten;
+ addr += (size_t)nwritten;
+ if (len == 0)
+ debug_return_ssize_t(str - str0); /* includes NUL */
+ break;
+ }
+ }
+ debug_return_ssize_t(-1);
+}
+#endif /* HAVE_PROCESS_VM_READV */
+
+/*
+ * Write the NUL-terminated string str to addr in the tracee using ptrace(2).
+ * Returns the number of bytes written, including trailing NUL.
+ */
+static ssize_t
+ptrace_write_string(pid_t pid, unsigned long addr, const char *str)
+{
+ const char *str0 = str;
+ size_t i;
+ union {
+ unsigned long word;
+ char buf[sizeof(unsigned long)];
+ } u;
+ debug_decl(ptrace_write_string, SUDO_DEBUG_EXEC);
+
+#ifdef HAVE_PROCESS_VM_READV
+ ssize_t nwritten = ptrace_writev_string(pid, addr, str);
+ if (nwritten != -1 || errno != ENOSYS)
+ debug_return_ssize_t(nwritten);
+#endif /* HAVE_PROCESS_VM_READV */
+
+ /*
+ * Write the string via ptrace(2) one (native) word at a time.
+ * We use the native word size even in compat mode because that
+ * is the unit ptrace(2) writes in terms of.
+ */
+ for (;;) {
+ for (i = 0; i < sizeof(u.buf); i++) {
+ if (*str == '\0') {
+ /* NUL-pad buf to sizeof(unsigned long). */
+ u.buf[i] = '\0';
+ continue;
+ }
+ u.buf[i] = *str++;
+ }
+ if (ptrace(PTRACE_POKEDATA, pid, addr, u.word) == -1) {
+ sudo_warn("%s: ptrace(PTRACE_POKEDATA, %d, 0x%lx, %.*s)",
+ __func__, (int)pid, addr, (int)sizeof(u.buf), u.buf);
+ debug_return_ssize_t(-1);
+ }
+ if ((u.word & 0xff) == 0) {
+ /* If the last byte we wrote is a NUL we are done. */
+ debug_return_ssize_t(str - str0 + 1);
+ }
+ addr += sizeof(unsigned long);
+ }
+}
+
+#ifdef HAVE_PROCESS_VM_READV
+/*
+ * Write the string vector vec to addr in the tracee which must have
+ * sufficient space. Strings are written to strtab.
+ * Returns the number of bytes used in strtab (including NULs).
+ * process_vm_writev() version.
+ */
+static ssize_t
+ptrace_writev_vec(pid_t pid, struct sudo_ptrace_regs *regs, char **vec,
+ unsigned long addr, unsigned long strtab)
+{
+ const unsigned long addr0 = addr;
+ const unsigned long strtab0 = strtab;
+ unsigned long *addrbuf = NULL;
+ struct iovec *local, *remote;
+ struct iovec local_addrs, remote_addrs;
+ size_t i, j, len, off = 0;
+ ssize_t expected = -1, nwritten, total_written = 0;
+ debug_decl(ptrace_writev_vec, SUDO_DEBUG_EXEC);
+
+ /* Build up local and remote iovecs for process_vm_writev(2). */
+ for (len = 0; vec[len] != NULL; len++)
+ continue;
+ local = reallocarray(NULL, len, sizeof(struct iovec));
+ remote = reallocarray(NULL, len, sizeof(struct iovec));
+ j = regs->compat && (len & 1) != 0; /* pad for final NULL in compat */
+ addrbuf = reallocarray(NULL, len + 1 + j, regs->wordsize);
+ if (local == NULL || remote == NULL || addrbuf == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ for (i = 0, j = 0; i < len; i++) {
+ unsigned long word = strtab;
+
+ /* Store remote string. */
+ const size_t size = strlen(vec[i]) + 1;
+ local[i].iov_base = vec[i];
+ local[i].iov_len = size;
+ remote[i].iov_base = (void *)strtab;
+ remote[i].iov_len = size;
+ strtab += size;
+
+ /* Store address of remote string. */
+# ifdef SECCOMP_AUDIT_ARCH_COMPAT
+ if (regs->compat) {
+ /*
+ * For compat binaries we need to pack two 32-bit string addresses
+ * into a single 64-bit word. If this is the last string, NULL
+ * will be written as the second 32-bit address.
+ */
+ if ((i & 1) == 1) {
+ /* Wrote this string address last iteration. */
+ continue;
+ }
+# if BYTE_ORDER == BIG_ENDIAN
+ word <<= 32;
+ if (vec[i + 1] != NULL)
+ word |= strtab;
+# else
+ if (vec[i + 1] != NULL)
+ word |= strtab << 32;
+# endif
+ }
+# endif
+ addrbuf[j++] = word;
+ addr += sizeof(unsigned long);
+ }
+ if (!regs->compat || (len & 1) == 0) {
+ addrbuf[j] = 0;
+ }
+
+ /* Write strings addresses to addr0 on remote. */
+ local_addrs.iov_base = addrbuf;
+ local_addrs.iov_len = (len + 1) * regs->wordsize;
+ remote_addrs.iov_base = (void *)addr0;
+ remote_addrs.iov_len = local_addrs.iov_len;
+ if (process_vm_writev(pid, &local_addrs, 1, &remote_addrs, 1, 0) == -1)
+ goto done;
+
+ /* Copy the strings to the (remote) string table. */
+ expected = (ssize_t)(strtab - strtab0);
+ for (;;) {
+ nwritten = process_vm_writev(pid, local + off, len - off,
+ remote + off, len - off, 0);
+ switch (nwritten) {
+ case -1:
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "process_vm_writev(%d, 0x%lx, %zu, 0x%lx, %zu, 0)",
+ (int)pid, (unsigned long)local + off, len - off,
+ (unsigned long)remote + off, len - off);
+ goto done;
+ case 0:
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "process_vm_writev(%d, 0x%lx, %zu, 0x%lx, %zu, 0): %s",
+ (int)pid, (unsigned long)local + off, len - off,
+ (unsigned long)remote + off, len - off,
+ "zero bytes written");
+ goto done;
+ default:
+ total_written += nwritten;
+ if (total_written >= expected)
+ goto done;
+
+ /* Adjust offset for partial write (doesn't cross iov boundary). */
+ while (off < len) {
+ nwritten -= (ssize_t)local[off].iov_len;
+ off++;
+ if (nwritten <= 0)
+ break;
+ }
+ if (off == len) {
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "overflow while resuming process_vm_writev()");
+ goto done;
+ }
+ break;
+ }
+ }
+done:
+ free(local);
+ free(remote);
+ free(addrbuf);
+ if (total_written == expected)
+ debug_return_ssize_t(total_written);
+ debug_return_ssize_t(-1);
+}
+#endif /* HAVE_PROCESS_VM_READV */
+
+/*
+ * Write the string vector vec to addr in the tracee which must have
+ * sufficient space. Strings are written to strtab.
+ * Returns the number of bytes used in strtab (including NULs).
+ */
+static ssize_t
+ptrace_write_vec(pid_t pid, struct sudo_ptrace_regs *regs, char **vec,
+ unsigned long addr, unsigned long strtab)
+{
+ const unsigned long strtab0 = strtab;
+ size_t i;
+ debug_decl(ptrace_write_vec, SUDO_DEBUG_EXEC);
+
+#ifdef HAVE_PROCESS_VM_READV
+ ssize_t nwritten = ptrace_writev_vec(pid, regs, vec, addr, strtab);
+ if (nwritten != -1 || errno != ENOSYS)
+ debug_return_ssize_t(nwritten);
+#endif /* HAVE_PROCESS_VM_READV */
+
+ /* Copy string vector into tracee one word at a time. */
+ for (i = 0; vec[i] != NULL; i++) {
+ unsigned long word = strtab;
+
+ /* First write the actual string to tracee's string table. */
+ nwritten = ptrace_write_string(pid, strtab, vec[i]);
+ if (nwritten == -1)
+ debug_return_ssize_t(-1);
+ strtab += (size_t)nwritten;
+
+# ifdef SECCOMP_AUDIT_ARCH_COMPAT
+ if (regs->compat) {
+ /*
+ * For compat binaries we need to pack two 32-bit string addresses
+ * into a single 64-bit word. If this is the last string, NULL
+ * will be written as the second 32-bit address.
+ */
+ if ((i & 1) == 1) {
+ /* Wrote this string address last iteration. */
+ continue;
+ }
+# if BYTE_ORDER == BIG_ENDIAN
+ word <<= 32;
+ if (vec[i + 1] != NULL)
+ word |= strtab;
+# else
+ if (vec[i + 1] != NULL)
+ word |= strtab << 32;
+# endif
+ }
+# endif
+ /* Next write the string address to tracee at addr. */
+ if (ptrace(PTRACE_POKEDATA, pid, addr, word) == -1) {
+ sudo_warn("%s: ptrace(PTRACE_POKEDATA, %d, 0x%lx, 0x%lx)",
+ __func__, (int)pid, addr, word);
+ debug_return_ssize_t(-1);
+ }
+ addr += sizeof(unsigned long);
+ }
+
+ /* Finally, write the terminating NULL to tracee if needed. */
+ if (!regs->compat || (i & 1) == 0) {
+ if (ptrace(PTRACE_POKEDATA, pid, addr, NULL) == -1) {
+ sudo_warn("%s: ptrace(PTRACE_POKEDATA, %d, 0x%lx, NULL)",
+ __func__, (int)pid, addr);
+ debug_return_ssize_t(-1);
+ }
+ }
+
+ debug_return_ssize_t((ssize_t)(strtab - strtab0));
+}
+
+/*
+ * Read a link from /proc/PID and store the result in buf.
+ * Used to read the cwd and exe links in /proc/PID.
+ * Returns true on success, else false.
+ */
+static bool
+proc_read_link(pid_t pid, const char *name, char *buf, size_t bufsize)
+{
+ ssize_t len;
+ char path[PATH_MAX];
+ debug_decl(proc_read_link, SUDO_DEBUG_EXEC);
+
+ len = snprintf(path, sizeof(path), "/proc/%d/%s", (int)pid, name);
+ if (len > 0 && len < ssizeof(path)) {
+ len = readlink(path, buf, bufsize - 1);
+ if (len != -1) {
+ /* readlink(2) does not add the NUL for us. */
+ buf[len] = '\0';
+ debug_return_bool(true);
+ }
+ }
+ debug_return_bool(false);
+}
+
+/*
+ * Read the filename, argv and envp of the execve(2) system call.
+ * Returns a dynamically allocated buffer the parent is responsible for.
+ */
+static char *
+get_execve_info(pid_t pid, struct sudo_ptrace_regs *regs, char **pathname_out,
+ int *argc_out, char ***argv_out, int *envc_out, char ***envp_out)
+{
+ char *argbuf, **argv, **envp, *pathname = NULL;
+ unsigned long argv_addr, envp_addr, path_addr;
+ size_t bufsize, off = 0;
+ int i, argc, envc = 0;
+ ssize_t nread;
+ debug_decl(get_execve_info, SUDO_DEBUG_EXEC);
+
+ bufsize = PATH_MAX + arg_max;
+ argbuf = malloc(bufsize);
+ if (argbuf == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+
+ /* execve(2) takes three arguments: pathname, argv, envp. */
+ path_addr = get_sc_arg1(regs);
+ argv_addr = get_sc_arg2(regs);
+ envp_addr = get_sc_arg3(regs);
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: %d: path 0x%lx, argv 0x%lx, envp 0x%lx", __func__,
+ (int)pid, path_addr, argv_addr, envp_addr);
+
+ /* Read the pathname, if not NULL. */
+ if (path_addr != 0) {
+ nread = ptrace_read_string(pid, path_addr, argbuf, bufsize);
+ if (nread == -1) {
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to read execve pathname for process %d", (int)pid);
+ goto bad;
+ }
+ /* Defer setting pathname until after all reallocations are done. */
+ off = (size_t)nread;
+ }
+
+ /* Read argv */
+ nread = ptrace_read_vec(pid, regs, argv_addr, &argc, &argv, &argbuf,
+ &bufsize, off);
+ if (nread == -1) {
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to read execve argv for process %d", (int)pid);
+ goto bad;
+ }
+ off += (size_t)nread;
+
+ if (argc == 0) {
+ /* Reserve an extra slot so we can store argv[0]. */
+ while (bufsize - off < sizeof(char *)) {
+ if (!growbuf(&argbuf, &bufsize, NULL, NULL))
+ goto bad;
+ }
+ off += sizeof(char *);
+ }
+
+ /* Read envp */
+ nread = ptrace_read_vec(pid, regs, envp_addr, &envc, &envp, &argbuf,
+ &bufsize, off);
+ if (nread == -1) {
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to read execve envp for process %d", (int)pid);
+ goto bad;
+ }
+
+ /* Set pathname now that argbuf has been fully allocated. */
+ if (path_addr != 0)
+ pathname = argbuf;
+
+ /* Convert offsets in argv and envp to pointers. */
+ argv = (char **)(argbuf + (unsigned long)argv);
+ for (i = 0; i < argc; i++) {
+ argv[i] = argbuf + (unsigned long)argv[i];
+ }
+ envp = (char **)(argbuf + (unsigned long)envp);
+ for (i = 0; i < envc; i++) {
+ envp[i] = argbuf + (unsigned long)envp[i];
+ }
+
+ sudo_debug_execve(SUDO_DEBUG_DIAG, pathname, argv, envp);
+
+ *pathname_out = pathname;
+ *argc_out = argc;
+ *argv_out = argv;
+ *envc_out = envc;
+ *envp_out = envp;
+
+ debug_return_ptr(argbuf);
+bad:
+ free(argbuf);
+ debug_return_ptr(NULL);
+}
+
+/*
+ * Cause the current syscall to fail and set the error value to ecode.
+ */
+static bool
+ptrace_fail_syscall(pid_t pid, struct sudo_ptrace_regs *regs, int ecode)
+{
+ sigset_t chldmask;
+ bool ret = false;
+ int status;
+ debug_decl(ptrace_fail_syscall, SUDO_DEBUG_EXEC);
+
+ /* Cause the syscall to fail by changing its number to -1. */
+ set_syscallno(pid, regs, -1);
+ if (!ptrace_setregs(pid, regs)) {
+ sudo_warn(U_("unable to set registers for process %d"), (int)pid);
+ debug_return_bool(false);
+ }
+
+ /* Block SIGCHLD for the critical section (waitpid). */
+ sigemptyset(&chldmask);
+ sigaddset(&chldmask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &chldmask, NULL);
+
+ /* Allow the syscall to continue and change return value to ecode. */
+ ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
+ for (;;) {
+ if (waitpid(pid, &status, __WALL) != -1)
+ break;
+ if (errno == EINTR)
+ continue;
+ sudo_warn(U_("%s: %s"), __func__, "waitpid");
+ goto done;
+ }
+ if (!WIFSTOPPED(status)) {
+ sudo_warnx(U_("process %d exited unexpectedly"), (int)pid);
+ goto done;
+ }
+ set_sc_retval(regs, -ecode);
+ if (!ptrace_setregs(pid, regs)) {
+ sudo_warn(U_("unable to set registers for process %d"), (int)pid);
+ goto done;
+ }
+
+ ret = true;
+
+done:
+ sigprocmask(SIG_UNBLOCK, &chldmask, NULL);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Check whether seccomp(2) filtering supports ptrace(2) traps.
+ * Only supported by Linux 4.14 and higher.
+ */
+static bool
+have_seccomp_action(const char *action)
+{
+ char line[LINE_MAX];
+ bool ret = false;
+ FILE *fp;
+ debug_decl(have_seccomp_action, SUDO_DEBUG_EXEC);
+
+ fp = fopen("/proc/sys/kernel/seccomp/actions_avail", "r");
+ if (fp != NULL) {
+ if (fgets(line, sizeof(line), fp) != NULL) {
+ char *cp, *last;
+
+ for ((cp = strtok_r(line, " \t\n", &last)); cp != NULL;
+ (cp = strtok_r(NULL, " \t\n", &last))) {
+ if (strcmp(cp, action) == 0) {
+ ret = true;
+ break;
+ }
+ }
+ }
+ fclose(fp);
+ }
+ debug_return_bool(ret);
+}
+
+/*
+ * Intercept execve(2) and execveat(2) using seccomp(2) and ptrace(2).
+ * If no tracer is present, execve(2) and execveat(2) will fail with ENOSYS.
+ * Must be called with CAP_SYS_ADMIN, before privs are dropped.
+ */
+bool
+set_exec_filter(void)
+{
+ struct sock_filter exec_filter[] = {
+ /* Load architecture value (AUDIT_ARCH_*) into the accumulator. */
+ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, arch)),
+# ifdef SECCOMP_AUDIT_ARCH_COMPAT2
+ /* Match on the compat2 architecture or jump to the compat check. */
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SECCOMP_AUDIT_ARCH_COMPAT2, 0, 4),
+ /* Load syscall number into the accumulator. */
+ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),
+ /* Jump to trace for compat2 execve(2)/execveat(2), else allow. */
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, COMPAT2_execve, 1, 0),
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, COMPAT2_execveat, 0, 13),
+ /* Trace execve(2)/execveat(2) syscalls (w/ compat flag) */
+ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRACE | COMPAT_FLAG),
+# endif /* SECCOMP_AUDIT_ARCH_COMPAT2 */
+# ifdef SECCOMP_AUDIT_ARCH_COMPAT
+ /* Match on the compat architecture or jump to the native arch check. */
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SECCOMP_AUDIT_ARCH_COMPAT, 0, 4),
+ /* Load syscall number into the accumulator. */
+ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),
+ /* Jump to trace for compat execve(2)/execveat(2), else allow. */
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, COMPAT_execve, 1, 0),
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, COMPAT_execveat, 0, 8),
+ /* Trace execve(2)/execveat(2) syscalls (w/ compat flag) */
+ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRACE | COMPAT_FLAG),
+# endif /* SECCOMP_AUDIT_ARCH_COMPAT */
+ /* Jump to the end unless the architecture matches. */
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SECCOMP_AUDIT_ARCH, 0, 6),
+ /* Load syscall number into the accumulator. */
+ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),
+ /* Jump to trace for execve(2)/execveat(2), else allow. */
+# ifdef X32_execve
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, X32_execve, 3, 0),
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, X32_execveat, 2, 0),
+# else
+ /* No x32 support, check native system call numbers. */
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_execve, 3, 0),
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_execveat, 2, 3),
+# endif /* X32_execve */
+ /* If no x32 support, these two instructions are never reached. */
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_execve, 1, 0),
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_execveat, 0, 1),
+ /* Trace execve(2)/execveat(2) syscalls */
+ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRACE),
+ /* Allow non-matching syscalls */
+ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)
+ };
+ const struct sock_fprog exec_fprog = {
+ nitems(exec_filter),
+ exec_filter
+ };
+ debug_decl(set_exec_filter, SUDO_DEBUG_EXEC);
+
+ /* We must set SECCOMP_MODE_FILTER before dropping privileges. */
+ if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &exec_fprog) == -1) {
+ sudo_warn("%s", U_("unable to set seccomp filter"));
+ debug_return_bool(false);
+ }
+ debug_return_bool(true);
+}
+
+/*
+ * Seize control of the specified child process which must be in
+ * ptrace wait. Returns true on success, false if child is already
+ * being traced and -1 on error.
+ */
+int
+exec_ptrace_seize(pid_t child)
+{
+ const long ptrace_opts = PTRACE_O_TRACESECCOMP|PTRACE_O_TRACECLONE|
+ PTRACE_O_TRACEFORK|PTRACE_O_TRACEVFORK|
+ PTRACE_O_TRACEEXEC;
+ int ret = -1;
+ int status;
+ debug_decl(exec_ptrace_seize, SUDO_DEBUG_EXEC);
+
+#ifdef HAVE_PROCESS_VM_READV
+ page_size = (size_t)sysconf(_SC_PAGESIZE);
+ if (page_size == (size_t)-1)
+ page_size = 4096;
+#endif
+ arg_max = (size_t)sysconf(_SC_ARG_MAX);
+ if (arg_max == (size_t)-1)
+ arg_max = 128 * 1024;
+
+ /* Seize control of the child process. */
+ if (ptrace(PTRACE_SEIZE, child, NULL, ptrace_opts) == -1) {
+ /*
+ * If the process is already being traced, we will get EPERM.
+ * We don't treat that as a fatal error since we want it to be
+ * possible to run sudo inside a sudo shell with intercept enabled.
+ */
+ if (errno != EPERM) {
+ sudo_warn("%s: ptrace(PTRACE_SEIZE, %d, NULL, 0x%lx)",
+ __func__, (int)child, ptrace_opts);
+ goto done;
+ }
+ sudo_debug_printf(SUDO_DEBUG_WARN,
+ "%s: unable to trace process %d, already being traced?",
+ __func__, (int)child);
+ ret = false;
+ }
+
+ /* The child is suspended waiting for SIGUSR1, wake it up. */
+ if (kill(child, SIGUSR1) == -1) {
+ sudo_warn("kill(%d, SIGUSR1)", (int)child);
+ goto done;
+ }
+ if (!ret)
+ goto done;
+
+ /* Wait for the child to enter trace stop and continue it. */
+ for (;;) {
+ if (waitpid(child, &status, __WALL) != -1)
+ break;
+ if (errno == EINTR)
+ continue;
+ sudo_warn(U_("%s: %s"), __func__, "waitpid");
+ goto done;
+ }
+ if (!WIFSTOPPED(status)) {
+ sudo_warnx(U_("process %d exited unexpectedly"), (int)child);
+ goto done;
+ }
+ if (ptrace(PTRACE_CONT, child, NULL, (void *)SIGUSR1) == -1) {
+ sudo_warn("%s: ptrace(PTRACE_CONT, %d, NULL, SIGUSR1)",
+ __func__, (int)child);
+ goto done;
+ }
+
+ ret = true;
+
+done:
+ debug_return_int(ret);
+}
+
+/*
+ * Compare two pathnames. If do_stat is true, fall back to stat(2)ing
+ * the paths for a dev/inode match if the strings don't match.
+ * Returns true on match, else false.
+ */
+static bool
+pathname_matches(const char *path1, const char *path2, bool do_stat)
+{
+ struct stat sb1, sb2;
+ debug_decl(pathname_matches, SUDO_DEBUG_EXEC);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: compare %s to %s", __func__,
+ path1 ? path1 : "(NULL)", path2 ? path2 : "(NULL)");
+
+ if (path1 == NULL || path2 == NULL)
+ debug_return_bool(false);
+
+ if (strcmp(path1, path2) == 0)
+ debug_return_bool(true);
+
+ if (do_stat && stat(path1, &sb1) == 0 && stat(path2, &sb2) == 0) {
+ if (sb1.st_dev == sb2.st_dev && sb1.st_ino == sb2.st_ino)
+ debug_return_bool(true);
+ }
+
+ debug_return_bool(false);
+}
+
+/*
+ * Open script and check for '#!' magic number followed by an interpreter.
+ * If present, check the interpreter against execpath, and argument string
+ * (if any) against argv[1].
+ * Returns number of argv entries to skip on success, else 0.
+ */
+static int
+script_matches(const char *script, const char *execpath, int argc,
+ char * const *argv)
+{
+ char * const *orig_argv = argv;
+ size_t linesize = 0;
+ char *interp, *interp_args, *line = NULL;
+ char magic[2];
+ int count;
+ FILE *fp = NULL;
+ ssize_t len;
+ debug_decl(get_interpreter, SUDO_DEBUG_EXEC);
+
+ /* Linux allows up to 4 nested interpreters. */
+ for (count = 0; count < 4; count++) {
+ if (fp != NULL)
+ fclose(fp);
+ fp = fopen(script, "r");
+ if (fp == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_ERRNO,
+ "%s: unable to open %s for reading", __func__, script);
+ goto done;
+ }
+
+ if (fread(magic, 1, 2, fp) != 2 || memcmp(magic, "#!", 2) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: %s: not a script",
+ __func__, script);
+ goto done;
+ }
+
+ /* Check interpreter, skipping the shebang and trim trailing space. */
+ len = getdelim(&line, &linesize, '\n', fp);
+ if (len == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "%s: %s: can't get interpreter",
+ __func__, script);
+ goto done;
+ }
+ while (len > 0 && isspace((unsigned char)line[len - 1])) {
+ len--;
+ line[len] = '\0';
+ }
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: %s: shebang line \"%s\"",
+ __func__, script, line);
+
+ /*
+ * Split line into interpreter and args.
+ * Whitespace is not supported in the interpreter path.
+ */
+ for (interp = line; isspace((unsigned char)*interp); interp++)
+ continue;
+ interp_args = strpbrk(interp, " \t");
+ if (interp_args != NULL) {
+ *interp_args++ = '\0';
+ while (isspace((unsigned char)*interp_args))
+ interp_args++;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: interpreter %s, args \"%s\"",
+ __func__, interp, interp_args ? interp_args : "");
+
+ /* Match interpreter. */
+ if (!pathname_matches(execpath, interp, true)) {
+ /* It is possible for the interpreter to be a script too. */
+ if (argv > 0 && strcmp(interp, argv[1]) == 0) {
+ /* Interpreter args must match for *this* interpreter. */
+ if (interp_args == NULL ||
+ (argc > 1 && strcmp(interp_args, argv[2]) == 0)) {
+ script = interp;
+ argv++;
+ argc--;
+ if (interp_args != NULL) {
+ argv++;
+ argc--;
+ }
+ /* Check whether interp is itself a script. */
+ continue;
+ }
+ }
+ }
+ if (argc > 0 && interp_args != NULL) {
+ if (strcmp(interp_args, argv[1]) != 0) {
+ sudo_warnx(
+ U_("interpreter argument , expected \"%s\", got \"%s\""),
+ interp_args, argc > 1 ? argv[1] : "(NULL)");
+ goto done;
+ }
+ argv++;
+ }
+ argv++;
+ break;
+ }
+
+done:
+ free(line);
+ if (fp != NULL)
+ fclose(fp);
+ debug_return_int((int)(argv - orig_argv));
+}
+
+static ssize_t
+proc_read_vec(pid_t pid, const char *name, int *countp, char ***vecp,
+ char **bufp, size_t *bufsizep, size_t off)
+{
+ size_t strtab_len, remainder = *bufsizep - off;
+ char path[PATH_MAX], *strtab = *bufp + off;
+ ssize_t len, nread;
+ int fd;
+ debug_decl(proc_read_vec, SUDO_DEBUG_EXEC);
+
+ len = snprintf(path, sizeof(path), "/proc/%d/%s", (int)pid, name);
+ if (len >= ssizeof(path))
+ debug_return_ssize_t(-1);
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ debug_return_ssize_t(-1);
+
+ /* Read in strings until EOF. */
+ do {
+ nread = read(fd, strtab, remainder);
+ if (nread == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to read %s", __func__, path);
+ close(fd);
+ debug_return_ssize_t(-1);
+ }
+ strtab += nread;
+ remainder -= (size_t)nread;
+ if (remainder < sizeof(char *)) {
+ while (!growbuf(bufp, bufsizep, &strtab, &remainder)) {
+ close(fd);
+ debug_return_ssize_t(-1);
+ }
+ }
+ } while (nread != 0);
+ close(fd);
+
+ /* Trim off the extra NUL byte at the end of the string table. */
+ if (strtab - *bufp >= 2 && strtab[-1] == '\0' && strtab[-2] == '\0') {
+ strtab--;
+ remainder++;
+ }
+
+ /* Store strings in a vector after the string table. */
+ strtab_len = (size_t)(strtab - (*bufp + off));
+ strtab = *bufp + off;
+ len = strtab_to_vec(strtab, strtab_len, countp, vecp, bufp, bufsizep,
+ remainder);
+ if (len == -1)
+ debug_return_ssize_t(-1);
+
+ debug_return_ssize_t((ssize_t)strtab_len + len);
+}
+
+/*
+ * Check if the execve(2) arguments match the contents of closure.
+ * Returns true if they match, else false.
+ */
+static bool
+execve_args_match(const char *pathname, int argc, char * const *argv,
+ int envc, char * const *envp, bool do_stat,
+ struct intercept_closure *closure)
+{
+ bool ret = true;
+ int i;
+ debug_decl(execve_args_match, SUDO_DEBUG_EXEC);
+
+ if (!pathname_matches(pathname, closure->command, do_stat)) {
+ /* For scripts, pathname will refer to the interpreter instead. */
+ if (do_stat) {
+ int skip = script_matches(closure->command, pathname,
+ argc, argv);
+ if (skip != 0) {
+ /* Skip interpreter (and args) in argv. */
+ argv += skip;
+ argc -= skip;
+ goto check_argv;
+ }
+ }
+ sudo_warnx(
+ U_("pathname mismatch, expected \"%s\", got \"%s\""),
+ closure->command, pathname ? pathname : "(NULL)");
+ ret = false;
+ }
+check_argv:
+ for (i = 0; i < argc; i++) {
+ if (closure->run_argv[i] == NULL) {
+ ret = false;
+ sudo_warnx(
+ U_("%s[%d] mismatch, expected \"%s\", got \"%s\""),
+ "argv", i, "(NULL)", argv[i] ? argv[i] : "(NULL)");
+ break;
+ }
+ if (argv[i] == NULL) {
+ ret = false;
+ sudo_warnx(
+ U_("%s[%d] mismatch, expected \"%s\", got \"%s\""),
+ "argv", i, closure->run_argv[i], "(NULL)");
+ break;
+ }
+ if (strcmp(argv[i], closure->run_argv[i]) != 0) {
+ if (i == 0) {
+ /* Special case for argv[0] which may contain the basename. */
+ const char *base;
+ if (argv[0][0] == '/') {
+ if (closure->run_argv[0][0] != '/') {
+ base = sudo_basename(argv[0]);
+ if (strcmp(base, closure->run_argv[0]) == 0)
+ continue;
+ }
+ } else {
+ if (closure->run_argv[0][0] == '/') {
+ base = sudo_basename(closure->run_argv[0]);
+ if (strcmp(argv[0], base) == 0)
+ continue;
+ }
+ }
+ }
+ ret = false;
+ sudo_warnx(
+ U_("%s[%d] mismatch, expected \"%s\", got \"%s\""),
+ "argv", i, closure->run_argv[i], argv[i]);
+ }
+ }
+ for (i = 0; i < envc; i++) {
+ if (closure->run_envp[i] == NULL) {
+ ret = false;
+ sudo_warnx(
+ U_("%s[%d] mismatch, expected \"%s\", got \"%s\""),
+ "envp", i, "(NULL)", envp[i] ? envp[i] : "(NULL)");
+ break;
+ } else if (envp[i] == NULL) {
+ ret = false;
+ sudo_warnx(
+ U_("%s[%d] mismatch, expected \"%s\", got \"%s\""),
+ "envp", i, closure->run_envp[i], "(NULL)");
+ break;
+ } else if (strcmp(envp[i], closure->run_envp[i]) != 0) {
+ ret = false;
+ sudo_warnx(
+ U_("%s[%d] mismatch, expected \"%s\", got \"%s\""),
+ "envp", i, closure->run_envp[i], envp[i]);
+ }
+ }
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Verify that the execve(2) argument we wrote match the contents of closure.
+ * Returns true if they match, else false.
+ */
+static bool
+verify_execve_args(pid_t pid, struct sudo_ptrace_regs *regs,
+ struct intercept_closure *closure)
+{
+ char *pathname, **argv, **envp, *buf;
+ int argc, envc;
+ bool ret = false;
+ debug_decl(verify_execve_args, SUDO_DEBUG_EXEC);
+
+ buf = get_execve_info(pid, regs, &pathname, &argc, &argv,
+ &envc, &envp);
+ if (buf != NULL) {
+ ret = execve_args_match(pathname, argc, argv, envc, envp, false, closure);
+ free(buf);
+ }
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Verify that the command executed matches the arguments we checked.
+ * Returns true on success and false on error.
+ */
+static bool
+ptrace_verify_post_exec(pid_t pid, struct sudo_ptrace_regs *regs,
+ struct intercept_closure *closure)
+{
+ char **argv, **envp, *argbuf = NULL;
+ char pathname[PATH_MAX];
+ sigset_t chldmask;
+ bool ret = false;
+ int argc, envc, i, status;
+ size_t bufsize;
+ ssize_t len;
+ debug_decl(ptrace_verify_post_exec, SUDO_DEBUG_EXEC);
+
+ /* Block SIGCHLD for the critical section (waitpid). */
+ sigemptyset(&chldmask);
+ sigaddset(&chldmask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &chldmask, NULL);
+
+ /* Allow execve(2) to continue and wait for PTRACE_EVENT_EXEC. */
+ ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
+ for (;;) {
+ if (waitpid(pid, &status, __WALL) != -1)
+ break;
+ if (errno == EINTR)
+ continue;
+ sudo_warn(U_("%s: %s"), __func__, "waitpid");
+ goto done;
+ }
+ if (!WIFSTOPPED(status)) {
+ sudo_warnx(U_("process %d exited unexpectedly"), (int)pid);
+ goto done;
+ }
+ if (status >> 8 != (SIGTRAP | (PTRACE_EVENT_EXEC << 8))) {
+ sudo_warnx(U_("process %d unexpected status 0x%x"), (int)pid, status);
+ goto done;
+ }
+
+ /* Get the executable path. */
+ if (!proc_read_link(pid, "exe", pathname, sizeof(pathname))) {
+ /* Missing /proc file system is not a fatal error. */
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "%s: unable to read /proc/%d/exe",
+ __func__, (int)pid);
+ ret = true;
+ goto done;
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: %d: verify %s", __func__,
+ (int)pid, pathname);
+
+ /* Allocate a single buffer for argv, envp and their strings. */
+ bufsize = arg_max;
+ argbuf = malloc(bufsize);
+ if (argbuf == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+
+ len = proc_read_vec(pid, "cmdline", &argc, &argv, &argbuf, &bufsize, 0);
+ if (len == -1) {
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to read execve argv for process %d", (int)pid);
+ goto done;
+ }
+
+ len = proc_read_vec(pid, "environ", &envc, &envp, &argbuf, &bufsize,
+ (size_t)len);
+ if (len == -1) {
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to read execve envp for process %d", (int)pid);
+ goto done;
+ }
+
+ /* Convert offsets in argv and envp to pointers. */
+ argv = (char **)(argbuf + (unsigned long)argv);
+ for (i = 0; i < argc; i++) {
+ argv[i] = argbuf + (unsigned long)argv[i];
+ }
+ envp = (char **)(argbuf + (unsigned long)envp);
+ for (i = 0; i < envc; i++) {
+ envp[i] = argbuf + (unsigned long)envp[i];
+ }
+
+ ret = execve_args_match(pathname, argc, argv, envc, envp, true, closure);
+ if (!ret) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: %d new execve args don't match closure", __func__, (int)pid);
+ }
+
+done:
+ free(argbuf);
+ sigprocmask(SIG_UNBLOCK, &chldmask, NULL);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Intercept execve(2) and perform a policy check.
+ * Reads current registers and execve(2) arguments.
+ * If the command is not allowed by policy, fail with EACCES.
+ * If the command is allowed, update argv if needed before continuing.
+ * Returns true on success and false on error.
+ */
+static bool
+ptrace_intercept_execve(pid_t pid, struct intercept_closure *closure)
+{
+ char *pathname, **argv, **envp, *buf;
+ const unsigned int flags = closure->details->flags;
+ int argc, envc, syscallno;
+ struct sudo_ptrace_regs regs;
+ bool path_mismatch = false;
+ bool argv_mismatch = false;
+ char cwd[PATH_MAX], *orig_argv0;
+ unsigned long msg;
+ bool ret = false;
+ int i, oldcwd = -1;
+ debug_decl(ptrace_intercept_execve, SUDO_DEBUG_EXEC);
+
+ /* Do not check the policy if we are executing the initial command. */
+ if (closure->initial_command != 0) {
+ closure->initial_command--;
+ debug_return_bool(true);
+ }
+
+ /* Get compat flag. */
+ if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, &msg) == -1) {
+ sudo_warn(U_("unable to get event message for process %d"), (int)pid);
+ debug_return_bool(false);
+ }
+
+ /* Get the registers. */
+ memset(&regs, 0, sizeof(regs));
+ if (!ptrace_getregs(pid, &regs, msg)) {
+ sudo_warn(U_("unable to get registers for process %d"), (int)pid);
+ debug_return_bool(false);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: %d: compat: %s, wordsize: %u",
+ __func__, (int)pid, regs.compat ? "true" : "false", regs.wordsize);
+
+# ifdef SECCOMP_AUDIT_ARCH_COMPAT
+ if (regs.compat) {
+ syscallno = get_syscallno(&regs);
+ switch (syscallno) {
+ case COMPAT_execve:
+ /* Handled below. */
+ break;
+ case COMPAT_execveat:
+ /* We don't currently check execveat(2). */
+ debug_return_bool(true);
+ break;
+ default:
+ sudo_warnx("%s: unexpected compat system call %d",
+ __func__, syscallno);
+ debug_return_bool(false);
+ }
+ } else
+# endif /* SECCOMP_AUDIT_ARCH_COMPAT */
+ {
+ syscallno = get_syscallno(&regs);
+ switch (syscallno) {
+# ifdef X32_execve
+ case X32_execve:
+# endif
+ case __NR_execve:
+ /* Handled below. */
+ break;
+# ifdef X32_execveat
+ case X32_execveat:
+# endif
+ case __NR_execveat:
+ /* We don't currently check execveat(2). */
+ debug_return_bool(true);
+ break;
+ default:
+ sudo_warnx("%s: unexpected system call %d", __func__, syscallno);
+ debug_return_bool(false);
+ }
+ }
+
+ /* Get the current working directory and execve info. */
+ if (!proc_read_link(pid, "cwd", cwd, sizeof(cwd)))
+ (void)strlcpy(cwd, "unknown", sizeof(cwd));
+ buf = get_execve_info(pid, &regs, &pathname, &argc, &argv,
+ &envc, &envp);
+ if (buf == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: %d: unable to get execve info", __func__, (int)pid);
+ /* EIO from ptrace is like EFAULT from the kernel. */
+ if (errno == EIO)
+ errno = EFAULT;
+ ptrace_fail_syscall(pid, &regs, errno);
+ goto done;
+ }
+
+ /* Must have a pathname. */
+ if (pathname == NULL) {
+ ptrace_fail_syscall(pid, &regs, EINVAL);
+ goto done;
+ }
+
+ /* We can only pass the pathname to exececute via argv[0] (plugin API). */
+ orig_argv0 = argv[0] ? argv[0] : (char *)"";
+ argv[0] = pathname;
+ if (argc == 0) {
+ /* Rewrite an empty argv[] with the path to execute. */
+ argv[1] = NULL;
+ argc = 1;
+ argv_mismatch = true;
+ }
+
+ /* Perform a policy check. */
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: %d: checking policy for %s",
+ __func__, (int)pid, pathname);
+ if (!intercept_check_policy(pathname, argc, argv, envc, envp, cwd,
+ &oldcwd, closure)) {
+ if (closure->errstr != NULL)
+ sudo_warnx("%s", U_(closure->errstr));
+ }
+
+ switch (closure->state) {
+ case POLICY_TEST:
+ path_mismatch = true;
+ argv_mismatch = true;
+ if (closure->command == NULL)
+ closure->command = pathname;
+ if (closure->run_argv == NULL)
+ closure->run_argv = argv;
+ if (closure->run_envp == NULL)
+ closure->run_envp = envp;
+ FALLTHROUGH;
+ case POLICY_ACCEPT:
+ /*
+ * Update pathname and argv if the policy modified it.
+ * We don't currently ever modify envp.
+ */
+ if (strcmp(pathname, closure->command) != 0)
+ path_mismatch = true;
+ if (!path_mismatch) {
+ /* Path unchanged, restore original argv[0]. */
+ if (strcmp(argv[0], orig_argv0) != 0) {
+ argv[0] = orig_argv0;
+ free(closure->run_argv[0]);
+ closure->run_argv[0] = strdup(orig_argv0);
+ if (closure->run_argv[0] == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ }
+ }
+ for (i = 0; closure->run_argv[i] != NULL && argv[i] != NULL; i++) {
+ if (strcmp(closure->run_argv[i], argv[i]) != 0) {
+ argv_mismatch = true;
+ break;
+ }
+ }
+ if (closure->run_argv[i] != NULL || argv[i] != NULL)
+ argv_mismatch = true;
+
+ if (path_mismatch || argv_mismatch) {
+ /*
+ * Need to rewrite pathname and/or argv.
+ * We can use space below the stack pointer to store the data.
+ * On amd64 there is a 128 byte red zone that must be avoided.
+ * Note: on pa-risc the stack grows up, not down.
+ */
+ unsigned long sp = get_stack_pointer(&regs) - 128;
+ unsigned long strtab;
+ size_t space = 0;
+ ssize_t nwritten;
+
+ sudo_debug_execve(SUDO_DEBUG_DIAG, closure->command,
+ closure->run_argv, envp);
+
+ /*
+ * Calculate the amount of space required for pointers + strings.
+ * Since ptrace(2) always writes in sizeof(long) increments we
+ * need to be careful to avoid overwriting what we have already
+ * written for compat binaries (where the word size doesn't match).
+ *
+ * This is mostly a problem for the string table since we do
+ * interleaved writes of the argument vector pointers and the
+ * strings they refer to. For native binaries, it is sufficient
+ * to align the string table on a word boundary. For compat
+ * binaries, if argc is odd, writing the last pointer will overlap
+ * the first string so leave an extra word in between them.
+ */
+ if (argv_mismatch) {
+ /* argv pointers */
+ space += ((size_t)argc + 1 + regs.compat) * regs.wordsize;
+
+ /* argv strings */
+ for (argc = 0; closure->run_argv[argc] != NULL; argc++) {
+ space += strlen(closure->run_argv[argc]) + 1;
+ }
+ }
+ if (path_mismatch) {
+ /* pathname string */
+ space += strlen(closure->command) + 1;
+ }
+
+ /* Reserve stack space for path, argv (w/ NULL) and its strings. */
+ sp -= WORDALIGN(space, regs);
+ strtab = sp;
+
+ if (argv_mismatch) {
+ /* Update argv address in the tracee to our new value. */
+ set_sc_arg2(&regs, sp);
+
+ /* Skip over argv pointers (plus NULL) for string table. */
+ strtab += ((size_t)argc + 1 + regs.compat) * regs.wordsize;
+
+ nwritten = ptrace_write_vec(pid, &regs, closure->run_argv,
+ sp, strtab);
+ if (nwritten == -1)
+ goto done;
+ strtab += (unsigned long)nwritten;
+ }
+ if (path_mismatch) {
+ /* Update pathname address in the tracee to our new value. */
+ set_sc_arg1(&regs, strtab);
+
+ /* Write pathname to the string table. */
+ nwritten = ptrace_write_string(pid, strtab, closure->command);
+ if (nwritten == -1)
+ goto done;
+ }
+
+ /* Update args in the tracee to the new values. */
+ if (!ptrace_setregs(pid, &regs)) {
+ sudo_warn(U_("unable to set registers for process %d"),
+ (int)pid);
+ goto done;
+ }
+
+ if (closure->state == POLICY_TEST) {
+ /* Verify the contents of what we just wrote. */
+ if (!verify_execve_args(pid, &regs, closure)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: new execve args don't match closure", __func__);
+ }
+ }
+ }
+ if (closure->state == POLICY_ACCEPT && ISSET(flags, CD_INTERCEPT)) {
+ if (ISSET(flags, CD_INTERCEPT_VERIFY)) {
+ /* Verify execve(2) args post-exec. */
+ if (!ptrace_verify_post_exec(pid, &regs, closure)) {
+ if (errno != ESRCH)
+ kill(pid, SIGKILL);
+ }
+ }
+ }
+ break;
+ case POLICY_REJECT:
+ /* If rejected, fake the syscall and set return to EACCES */
+ errno = EACCES;
+ FALLTHROUGH;
+ default:
+ ptrace_fail_syscall(pid, &regs, errno);
+ break;
+ }
+
+ ret = true;
+
+done:
+ if (oldcwd != -1) {
+ if (fchdir(oldcwd) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to restore saved cwd", __func__);
+ }
+ close(oldcwd);
+ }
+ free(buf);
+ intercept_closure_reset(closure);
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Handle a process stopped due to ptrace.
+ * Restarts the tracee with PTRACE_LISTEN (for a group-stop)
+ * or PTRACE_CONT (for signal-delivery-stop).
+ * Returns true if stopped by a group-stop, else false.
+ */
+bool
+exec_ptrace_stopped(pid_t pid, int status, void *intercept)
+{
+ struct intercept_closure *closure = intercept;
+ const int stopsig = WSTOPSIG(status);
+ const int sigtrap = status >> 8;
+ long signo = 0;
+ bool group_stop = false;
+ debug_decl(exec_ptrace_stopped, SUDO_DEBUG_EXEC);
+
+ if (sigtrap == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8))) {
+ if (!ptrace_intercept_execve(pid, closure)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: %d failed to intercept execve", __func__, (int)pid);
+ }
+ } else if (sigtrap == (SIGTRAP | (PTRACE_EVENT_EXEC << 8))) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: %d PTRACE_EVENT_EXEC", __func__, (int)pid);
+ } else if (sigtrap == (SIGTRAP | (PTRACE_EVENT_CLONE << 8)) ||
+ sigtrap == (SIGTRAP | (PTRACE_EVENT_VFORK << 8)) ||
+ sigtrap == (SIGTRAP | (PTRACE_EVENT_FORK << 8))) {
+ unsigned long new_pid;
+
+ /* New child process, it will inherit the parent's trace flags. */
+ if (sudo_debug_needed(SUDO_DEBUG_INFO)) {
+ if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, &new_pid) != -1) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: %d forked new child %lu", __func__, (int)pid, new_pid);
+ } else {
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "ptrace(PTRACE_GETEVENTMSG, %d, NULL, %p)", (int)pid,
+ &new_pid);
+ }
+ }
+ } else {
+ switch (stopsig) {
+ case SIGSTOP:
+ case SIGTSTP:
+ case SIGTTIN:
+ case SIGTTOU:
+ /* Is this a group-stop? */
+ if (status >> 16 == PTRACE_EVENT_STOP) {
+ /* Group-stop, do not deliver signal. */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: %d: group-stop signal %d",
+ __func__, (int)pid, stopsig);
+ group_stop = true;
+ break;
+ }
+ FALLTHROUGH;
+ default:
+ /* Signal-delivery-stop, deliver signal. */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: %d: signal-delivery-stop signal %d",
+ __func__, (int)pid, stopsig);
+ signo = stopsig;
+ break;
+ }
+ }
+
+ if (group_stop) {
+ /*
+ * Restart child but prevent it from executing
+ * until SIGCONT is received (simulate SIGSTOP, etc).
+ */
+ if (ptrace(PTRACE_LISTEN, pid, NULL, 0L) == -1 && errno != ESRCH)
+ sudo_warn("%s: ptrace(PTRACE_LISTEN, %d, NULL, 0L)",
+ __func__, (int)pid);
+ } else {
+ /* Restart child immediately. */
+ if (ptrace(PTRACE_CONT, pid, NULL, signo) == -1 && errno != ESRCH)
+ sudo_warn("%s: ptrace(PTRACE_CONT, %d, NULL, %ld)",
+ __func__, (int)pid, signo);
+ }
+
+ debug_return_bool(group_stop);
+}
+
+bool
+exec_ptrace_intercept_supported(void)
+{
+# ifdef __mips__
+ /* MIPS doesn't support changing the syscall return value. */
+ return false;
+# else
+ if (seccomp_trap_supported == -1)
+ seccomp_trap_supported = have_seccomp_action("trap");
+
+ return seccomp_trap_supported == true;
+# endif
+}
+
+bool
+exec_ptrace_subcmds_supported(void)
+{
+ if (seccomp_trap_supported == -1)
+ seccomp_trap_supported = have_seccomp_action("trap");
+
+ return seccomp_trap_supported == true;
+}
+#else
+/* STUB */
+bool
+exec_ptrace_stopped(pid_t pid, int status, void *intercept)
+{
+ return true;
+}
+
+/* STUB */
+int
+exec_ptrace_seize(pid_t child)
+{
+ return true;
+}
+
+/* STUB */
+bool
+exec_ptrace_intercept_supported(void)
+{
+ return false;
+}
+
+/* STUB */
+bool
+exec_ptrace_subcmds_supported(void)
+{
+ return false;
+}
+#endif /* HAVE_PTRACE_INTERCEPT */
+
+/*
+ * Adjust flags based on the availability of ptrace support.
+ */
+void
+exec_ptrace_fix_flags(struct command_details *details)
+{
+ debug_decl(exec_ptrace_fix_flags, SUDO_DEBUG_EXEC);
+
+ if (ISSET(details->flags, CD_USE_PTRACE)) {
+ /* If both CD_INTERCEPT and CD_LOG_SUBCMDS set, CD_INTERCEPT wins. */
+ if (ISSET(details->flags, CD_INTERCEPT)) {
+ if (!exec_ptrace_intercept_supported())
+ CLR(details->flags, CD_USE_PTRACE);
+ } else if (ISSET(details->flags, CD_LOG_SUBCMDS)) {
+ if (!exec_ptrace_subcmds_supported())
+ CLR(details->flags, CD_USE_PTRACE);
+ } else {
+ CLR(details->flags, CD_USE_PTRACE);
+ }
+ }
+ debug_return;
+}
diff --git a/src/exec_ptrace.h b/src/exec_ptrace.h
new file mode 100644
index 0000000..f75f2e5
--- /dev/null
+++ b/src/exec_ptrace.h
@@ -0,0 +1,532 @@
+/*
+ * Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_EXEC_PTRACE_H
+#define SUDO_EXEC_PTRACE_H
+
+#include <sys/prctl.h>
+#include <sys/ptrace.h>
+#include <sys/user.h>
+#include <asm/unistd.h>
+#include <linux/audit.h>
+#include <linux/ptrace.h>
+#include <linux/seccomp.h>
+#include <linux/filter.h>
+
+/* Older kernel headers may be missing some EM_* defines in linux/elf.h. */
+#include <elf.h>
+
+/* Older systems may not support execveat(2). */
+#ifndef __NR_execveat
+# define __NR_execveat -1
+#endif
+
+/* In case userland elf.h doesn't define NT_ARM_SYSTEM_CALL. */
+#if defined(__aarch64__) && !defined(NT_ARM_SYSTEM_CALL)
+# define NT_ARM_SYSTEM_CALL 0x404
+#endif
+
+/* In case userland doesn't define __X32_SYSCALL_BIT. */
+#if defined(__x86_64__) && !defined(__X32_SYSCALL_BIT)
+# define __X32_SYSCALL_BIT 0x40000000
+#endif
+
+#ifdef __mips__
+# ifndef __NR_O32_Linux
+# define __NR_O32_Linux 4000
+# endif
+# ifndef __NR_N32_Linux
+# define __NR_N32_Linux 6000
+# endif
+#endif
+
+/* Align address to a (compat) word boundary. */
+#define WORDALIGN(_a, _r) \
+ (((_a) + ((unsigned long)(_r).wordsize - 1UL)) & ~((unsigned long)(_r).wordsize - 1UL))
+
+/* Align pointer to a native word boundary. */
+#define LONGALIGN(_p) \
+ (((unsigned long)(_p) + (sizeof(unsigned long) - 1UL)) & ~(sizeof(unsigned long) - 1UL))
+
+/*
+ * See syscall(2) for a list of registers used in system calls.
+ * For example code, see tools/testing/selftests/seccomp/seccomp_bpf.c
+ *
+ * The structs and registers vary among the different platforms.
+ * We define user_regs_struct as the struct to use for gettings
+ * and setting the general registers and define accessor
+ * macros to get/set the individual struct members.
+ *
+ * The value of SECCOMP_AUDIT_ARCH is used when matching the architecture
+ * in the seccomp(2) filter.
+ */
+#if defined(__x86_64__)
+# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_X86_64
+# ifndef __ILP32__
+# define X32_execve __X32_SYSCALL_BIT + 520
+# define X32_execveat __X32_SYSCALL_BIT + 545
+# endif
+# define sudo_pt_regs struct user_regs_struct
+# define reg_syscall(x) (x).orig_rax
+# define reg_retval(x) (x).rax
+# define reg_sp(x) (x).rsp
+# define reg_arg1(x) (x).rdi
+# define reg_arg2(x) (x).rsi
+# define reg_arg3(x) (x).rdx
+# define reg_arg4(x) (x).r10
+#elif defined(__aarch64__)
+# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_AARCH64
+# define sudo_pt_regs struct user_pt_regs
+# define reg_syscall(x) (x).regs[8] /* w8 */
+# define reg_retval(x) (x).regs[0] /* x0 */
+# define reg_sp(x) (x).sp /* sp */
+# define reg_arg1(x) (x).regs[0] /* x0 */
+# define reg_arg2(x) (x).regs[1] /* x1 */
+# define reg_arg3(x) (x).regs[2] /* x2 */
+# define reg_arg4(x) (x).regs[3] /* x3 */
+# define reg_set_syscall(_r, _nr) do { \
+ struct iovec _iov; \
+ long _syscallno = (_nr); \
+ _iov.iov_base = &_syscallno; \
+ _iov.iov_len = sizeof(_syscallno); \
+ ptrace(PTRACE_SETREGSET, pid, NT_ARM_SYSTEM_CALL, &_iov); \
+} while (0)
+#elif defined(__arm__)
+/* Note: assumes arm EABI, not OABI */
+# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_ARM
+# define sudo_pt_regs struct pt_regs
+# define reg_syscall(x) (x).ARM_r7
+# define reg_retval(x) (x).ARM_r0
+# define reg_sp(x) (x).ARM_sp
+# define reg_arg1(x) (x).ARM_r0
+# define reg_arg2(x) (x).ARM_r1
+# define reg_arg3(x) (x).ARM_r2
+# define reg_arg4(x) (x).ARM_r3
+# define reg_set_syscall(_r, _nr) do { \
+ ptrace(PTRACE_SET_SYSCALL, pid, NULL, _nr); \
+} while (0)
+#elif defined (__hppa__)
+/* Untested (should also support hppa64) */
+# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_PARISC
+# define sudo_pt_regs struct user_regs_struct
+# define reg_syscall(x) (x).gr[20] /* r20 */
+# define reg_retval(x) (x).gr[28] /* r28 */
+# define reg_sp(x) (x).gr[30] /* r30 */
+# define reg_arg1(x) (x).gr[26] /* r26 */
+# define reg_arg2(x) (x).gr[25] /* r25 */
+# define reg_arg3(x) (x).gr[24] /* r24 */
+# define reg_arg4(x) (x).gr[23] /* r23 */
+#elif defined(__i386__)
+# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_I386
+# define sudo_pt_regs struct user_regs_struct
+# define reg_syscall(x) (x).orig_eax
+# define reg_retval(x) (x).eax
+# define reg_sp(x) (x).esp
+# define reg_arg1(x) (x).ebx
+# define reg_arg2(x) (x).ecx
+# define reg_arg3(x) (x).edx
+# define reg_arg4(x) (x).esi
+#elif defined(__mips__)
+# if _MIPS_SIM == _MIPS_SIM_ABI32
+# /* Linux o32 style syscalls, 4000-4999. */
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPSEL
+# else
+# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPS
+# endif
+# elif _MIPS_SIM == _MIPS_SIM_ABI64
+# /* Linux 64-bit syscalls, 5000-5999. */
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPSEL64
+# else
+# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPS64
+# endif
+# elif _MIPS_SIM == _MIPS_SIM_NABI32
+# /* Linux N32 syscalls, 6000-6999. */
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPSEL64N32
+# else
+# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPS64N32
+# endif
+# else
+# error "Unsupported MIPS ABI"
+# endif
+/*
+ * If called via syscall(__NR_###), v0 holds __NR_O32_Linux and the real
+ * syscall is in the first arg (a0). The actual args are shifted by one.
+ * MIPS does not support setting the syscall return value via ptrace.
+ */
+# define sudo_pt_regs struct pt_regs
+# define reg_syscall(_r) ({ \
+ __u64 _nr; \
+ if ((_r).regs[2] == __NR_O32_Linux) \
+ _nr = (_r).regs[4]; /* a0 */ \
+ else \
+ _nr = (_r).regs[2]; /* v0 */ \
+ _nr; \
+})
+# define reg_retval(x) (x).regs[2] /* v0 */
+# define reg_sp(x) (x).regs[29] /* sp */
+# define reg_arg1(x) \
+ ((x).regs[2] == __NR_O32_Linux ? (x).regs[5] : (x).regs[4])
+# define reg_set_arg1(_r, _v) do { \
+ if ((_r).regs[2] == __NR_O32_Linux) \
+ (_r).regs[5] = _v; /* a1 */ \
+ else \
+ (_r).regs[4] = _v; /* a0 */ \
+} while (0)
+# define reg_arg2(x) \
+ ((x).regs[2] == __NR_O32_Linux ? (x).regs[6] : (x).regs[5])
+# define reg_set_arg2(_r, _v) do { \
+ if ((_r).regs[2] == __NR_O32_Linux) \
+ (_r).regs[6] = _v; /* a2 */ \
+ else \
+ (_r).regs[5] = _v; /* a1 */ \
+} while (0)
+# define reg_arg3(x) \
+ ((x).regs[2] == __NR_O32_Linux ? (x).regs[7] : (x).regs[6])
+# define reg_set_arg3(_r, _v) do { \
+ if ((_r).regs[2] == __NR_O32_Linux) \
+ (_r).regs[7] = _v; /* a3 */ \
+ else \
+ (_r).regs[6] = _v; /* a2 */ \
+} while (0)
+/* XXX - reg_arg4 probably wrong for syscall() type calls on 032. */
+# define reg_arg4(x) \
+ ((x).regs[2] == __NR_O32_Linux ? (x).regs[8] : (x).regs[7])
+# define reg_set_arg4(_r, _v) do { \
+ if ((_r).regs[2] == __NR_O32_Linux) \
+ (_r).regs[8] = _v; /* a4 */ \
+ else \
+ (_r).regs[7] = _v; /* a3 */ \
+} while (0)
+# define reg_set_syscall(_r, _nr) do { \
+ if ((_r).regs[2] == __NR_O32_Linux) \
+ (_r).regs[4] = _nr; /* a0 */ \
+ else \
+ (_r).regs[2] = _nr; /* v0 */ \
+} while (0)
+#elif defined(__powerpc__)
+# if defined(__powerpc64__)
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_PPC64LE
+# else
+# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_PPC64
+# endif
+# else
+# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_PPC
+# endif
+# define sudo_pt_regs struct pt_regs
+# define reg_syscall(x) (x).gpr[0] /* r0 */
+# define reg_retval(x) (x).gpr[3] /* r3 */
+# define reg_sp(x) (x).gpr[1] /* r1 */
+# define reg_arg1(x) (x).orig_gpr3 /* r3 */
+# define reg_arg2(x) (x).gpr[4] /* r4 */
+# define reg_arg3(x) (x).gpr[5] /* r5 */
+# define reg_arg4(x) (x).gpr[6] /* r6 */
+# define reg_set_retval(_r, _v) do { \
+ if (((_r).trap & 0xfff0) == 0x3000) { \
+ /* scv 0 system call, uses negative error code for result. */ \
+ reg_retval(_r) = (_v); \
+ } else { \
+ /* \
+ * Set CR0 SO bit to indicate a syscall error, which is stored \
+ * as a positive error code. \
+ */ \
+ reg_retval(_r) = -(_v); \
+ (_r).ccr |= 0x10000000; \
+ } \
+} while (0)
+#elif defined(__riscv) && __riscv_xlen == 64
+# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_RISCV64
+# define sudo_pt_regs struct user_regs_struct
+# define reg_syscall(x) (x).a7
+# define reg_retval(x) (x).a0
+# define reg_sp(x) (x).sp
+# define reg_arg1(x) (x).a0
+# define reg_arg2(x) (x).a1
+# define reg_arg3(x) (x).a2
+# define reg_arg4(x) (x).a3
+#elif defined(__s390__)
+/*
+ * Both the syscall number and return value are stored in r2 for
+ * the s390 ptrace API. The first argument is stored in orig_gpr2.
+ */
+# if defined(__s390x__)
+# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_S390X
+# else
+# define SECCOMP_AUDIT_ARCH AUDIT_ARCH_S390
+# endif
+# define sudo_pt_regs s390_regs
+# define reg_syscall(x) (x).gprs[2] /* r2 */
+# define reg_retval(x) (x).gprs[2] /* r2 */
+# define reg_sp(x) (x).gprs[15] /* r15 */
+# define reg_arg1(x) (x).orig_gpr2 /* r2 */
+# define reg_arg2(x) (x).gprs[3] /* r3 */
+# define reg_arg3(x) (x).gprs[4] /* r4 */
+# define reg_arg4(x) (x).gprs[5] /* r6 */
+#else
+# error "Do not know how to find your architecture's registers"
+#endif
+
+/*
+ * Compat definitions for running 32-bit binaries on 64-bit platforms.
+ * We must define the register struct too since there is no way to
+ * get it directly from the system headers.
+ *
+ * The value of SECCOMP_AUDIT_ARCH_COMPAT is used when matching the
+ * architecture in the seccomp(2) filter. We can tell when the compat
+ * arch matched by inspecting the message returned by PTRACE_GETEVENTMSG.
+ */
+#if defined(__x86_64__)
+struct i386_user_regs_struct {
+ unsigned int ebx;
+ unsigned int ecx;
+ unsigned int edx;
+ unsigned int esi;
+ unsigned int edi;
+ unsigned int ebp;
+ unsigned int eax;
+ unsigned int xds;
+ unsigned int xes;
+ unsigned int xfs;
+ unsigned int xgs;
+ unsigned int orig_eax;
+ unsigned int eip;
+ unsigned int xcs;
+ unsigned int eflags;
+ unsigned int esp;
+ unsigned int xss;
+};
+# define SECCOMP_AUDIT_ARCH_COMPAT AUDIT_ARCH_I386
+# define COMPAT_execve 11
+# define COMPAT_execveat 358
+# define compat_sudo_pt_regs struct i386_user_regs_struct
+# define compat_reg_syscall(x) (x).orig_eax
+# define compat_reg_retval(x) (x).eax
+# define compat_reg_sp(x) (x).esp
+# define compat_reg_arg1(x) (x).ebx
+# define compat_reg_arg2(x) (x).ecx
+# define compat_reg_arg3(x) (x).edx
+# define compat_reg_arg4(x) (x).esi
+#elif defined(__aarch64__)
+struct arm_pt_regs {
+ unsigned int uregs[18];
+};
+# define SECCOMP_AUDIT_ARCH_COMPAT AUDIT_ARCH_ARM
+# define COMPAT_execve 11
+# define COMPAT_execveat 387
+# define compat_sudo_pt_regs struct arm_pt_regs
+# define compat_reg_syscall(x) (x).uregs[7] /* r7 */
+# define compat_reg_retval(x) (x).uregs[0] /* r0 */
+# define compat_reg_sp(x) (x).uregs[13] /* r13 */
+# define compat_reg_arg1(x) (x).uregs[0] /* r0 */
+# define compat_reg_arg2(x) (x).uregs[1] /* r1 */
+# define compat_reg_arg3(x) (x).uregs[2] /* r2 */
+# define compat_reg_arg4(x) (x).uregs[3] /* r3 */
+# define compat_reg_set_syscall(_r, _nr) reg_set_syscall(_r, _nr)
+#elif defined(__mips__)
+# if _MIPS_SIM == _MIPS_SIM_ABI64
+/* MIPS o32/n32 binary compatibility on a mips64 system. */
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define SECCOMP_AUDIT_ARCH_COMPAT AUDIT_ARCH_MIPSEL
+# define SECCOMP_AUDIT_ARCH_COMPAT2 AUDIT_ARCH_MIPSEL64N32
+# else
+# define SECCOMP_AUDIT_ARCH_COMPAT AUDIT_ARCH_MIPS
+# define SECCOMP_AUDIT_ARCH_COMPAT2 AUDIT_ARCH_MIPS64N32
+# endif
+# define COMPAT_execve __NR_O32_Linux + 11
+# define COMPAT_execveat __NR_O32_Linux + 356
+# define COMPAT2_execve __NR_N32_Linux + 57
+# define COMPAT2_execveat __NR_N32_Linux + 320
+# elif _MIPS_SIM == _MIPS_SIM_NABI32
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define SECCOMP_AUDIT_ARCH_COMPAT AUDIT_ARCH_MIPSEL
+# else
+# define SECCOMP_AUDIT_ARCH_COMPAT AUDIT_ARCH_MIPS
+# endif
+# define COMPAT_execve __NR_O32_Linux + 11
+# define COMPAT_execveat __NR_O32_Linux + 356
+# endif /* _MIPS_SIM_ABI64 */
+/* MIPS ABIs use a common ptrace interface. */
+# define compat_sudo_pt_regs struct pt_regs
+# define compat_reg_syscall(x) reg_syscall(x)
+# define compat_reg_retval(x) reg_retval(x)
+# define compat_reg_sp(x) reg_sp(x)
+# define compat_reg_arg1(x) reg_arg1(x)
+# define compat_reg_set_arg1(_r, _v) reg_set_arg1(_r, _v)
+# define compat_reg_arg2(x) reg_arg2(x)
+# define compat_reg_set_arg2(_r, _v) reg_set_arg2(_r, _v)
+# define compat_reg_arg3(x) reg_arg3(x)
+# define compat_reg_set_arg3(_r, _v) reg_set_arg3(_r, _v)
+# define compat_reg_arg4(x) reg_arg4(x)
+# define compat_reg_set_arg4(_r, _v) reg_set_arg4(_r, _v)
+# define compat_reg_set_syscall(_r, _nr) reg_set_syscall(_r, _nr)
+#elif defined(__powerpc64__)
+struct ppc_pt_regs {
+ unsigned int gpr[32];
+ unsigned int nip;
+ unsigned int msr;
+ unsigned int orig_gpr3;
+ unsigned int ctr;
+ unsigned int link;
+ unsigned int xer;
+ unsigned int ccr;
+ unsigned int mq;
+ unsigned int trap;
+ unsigned int dar;
+ unsigned int dsisr;
+ unsigned int result;
+};
+# if BYTE_ORDER == LITTLE_ENDIAN
+/* There is no AUDIT_ARCH_PPCLE define. */
+# define SECCOMP_AUDIT_ARCH_COMPAT (AUDIT_ARCH_PPC|__AUDIT_ARCH_LE)
+# else
+# define SECCOMP_AUDIT_ARCH_COMPAT AUDIT_ARCH_PPC
+# endif
+# define COMPAT_execve __NR_execve
+# define COMPAT_execveat __NR_execveat
+# define compat_sudo_pt_regs struct ppc_pt_regs
+# define compat_reg_syscall(x) (x).gpr[0] /* r0 */
+# define compat_reg_retval(x) (x).gpr[3] /* r3 */
+# define compat_reg_sp(x) (x).gpr[1] /* r1 */
+# define compat_reg_arg1(x) (x).orig_gpr3 /* r3 */
+# define compat_reg_arg2(x) (x).gpr[4] /* r4 */
+# define compat_reg_arg3(x) (x).gpr[5] /* r5 */
+# define compat_reg_arg4(x) (x).gpr[6] /* r6 */
+# define compat_reg_set_retval(_r, _v) reg_set_retval(_r, _v)
+#endif
+
+/* Set the syscall number the "normal" way by default. */
+#ifndef reg_set_syscall
+# define reg_set_syscall(_r, _nr) do { \
+ reg_syscall(_r) = (_nr); \
+} while (0)
+#endif
+#ifndef compat_reg_set_syscall
+# define compat_reg_set_syscall(_r, _nr) do { \
+ compat_reg_syscall(_r) = (_nr); \
+} while (0)
+#endif
+
+/* Set the syscall return value the "normal" way by default. */
+#ifndef reg_set_retval
+# define reg_set_retval(_r, _v) do { \
+ reg_retval(_r) = (_v); \
+} while (0)
+#endif
+#ifndef compat_reg_set_retval
+# define compat_reg_set_retval(_r, _v) do { \
+ compat_reg_retval(_r) = (_v); \
+} while (0)
+#endif
+
+/* Set the syscall arguments the "normal" way by default. */
+#ifndef reg_set_arg1
+# define reg_set_arg1(_r, _v) do { \
+ reg_arg1(_r) = (_v); \
+} while (0)
+#endif
+#ifndef compat_reg_set_arg1
+# define compat_reg_set_arg1(_r, _v) do { \
+ compat_reg_arg1(_r) = (_v); \
+} while (0)
+#endif
+#ifndef reg_set_arg2
+# define reg_set_arg2(_r, _v) do { \
+ reg_arg2(_r) = (_v); \
+} while (0)
+#endif
+#ifndef compat_reg_set_arg2
+# define compat_reg_set_arg2(_r, _v) do { \
+ compat_reg_arg2(_r) = (_v); \
+} while (0)
+#endif
+#ifndef reg_set_arg3
+# define reg_set_arg3(_r, _v) do { \
+ reg_arg3(_r) = (_v); \
+} while (0)
+#endif
+#ifndef compat_reg_set_arg3
+# define compat_reg_set_arg3(_r, _v) do { \
+ compat_reg_arg3(_r) = (_v); \
+} while (0)
+#endif
+#ifndef reg_set_arg4
+# define reg_set_arg4(_r, _v) do { \
+ reg_arg4(_r) = (_v); \
+} while (0)
+#endif
+#ifndef compat_reg_set_arg4
+# define compat_reg_set_arg4(_r, _v) do { \
+ compat_reg_arg4(_r) = (_v); \
+} while (0)
+#endif
+
+/* Set the syscall arguments the "normal" way by default. */
+#ifndef reg_set_arg1
+# define reg_set_arg1(_r, _v) do { \
+ reg_arg1(_r) = (_v); \
+} while (0)
+#endif
+#ifndef compat_reg_set_arg1
+# define compat_reg_set_arg1(_r, _v) do { \
+ compat_reg_arg1(_r) = (_v); \
+} while (0)
+#endif
+#ifndef reg_set_arg2
+# define reg_set_arg2(_r, _v) do { \
+ reg_arg2(_r) = (_v); \
+} while (0)
+#endif
+#ifndef compat_reg_set_arg2
+# define compat_reg_set_arg2(_r, _v) do { \
+ compat_reg_arg2(_r) = (_v); \
+} while (0)
+#endif
+#ifndef reg_set_arg3
+# define reg_set_arg3(_r, _v) do { \
+ reg_arg3(_r) = (_v); \
+} while (0)
+#endif
+#ifndef compat_reg_set_arg3
+# define compat_reg_set_arg3(_r, _v) do { \
+ compat_reg_arg3(_r) = (_v); \
+} while (0)
+#endif
+#ifndef reg_set_arg4
+# define reg_set_arg4(_r, _v) do { \
+ reg_arg4(_r) = (_v); \
+} while (0)
+#endif
+#ifndef compat_reg_set_arg4
+# define compat_reg_set_arg4(_r, _v) do { \
+ compat_reg_arg4(_r) = (_v); \
+} while (0)
+#endif
+
+struct sudo_ptrace_regs {
+ union {
+ sudo_pt_regs native;
+#ifdef SECCOMP_AUDIT_ARCH_COMPAT
+ compat_sudo_pt_regs compat;
+#endif
+ } u;
+ unsigned int wordsize;
+ bool compat;
+};
+
+#endif /* SUDO_EXEC_PTRACE_H */
diff --git a/src/exec_pty.c b/src/exec_pty.c
new file mode 100644
index 0000000..1b4bc0e
--- /dev/null
+++ b/src/exec_pty.c
@@ -0,0 +1,1452 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <termios.h> /* for struct winsize on HP-UX */
+
+#include <sudo.h>
+#include <sudo_exec.h>
+#include <sudo_plugin.h>
+#include <sudo_plugin_int.h>
+
+/* Tail queue of messages to send to the monitor. */
+struct monitor_message {
+ TAILQ_ENTRY(monitor_message) entries;
+ struct command_status cstat;
+};
+TAILQ_HEAD(monitor_message_list, monitor_message);
+static struct monitor_message_list monitor_messages =
+ TAILQ_HEAD_INITIALIZER(monitor_messages);
+static unsigned int term_raw_flags;
+static struct exec_closure pty_ec;
+
+static void sync_ttysize(struct exec_closure *ec);
+static void schedule_signal(struct exec_closure *ec, int signo);
+
+/*
+ * Allocate a pty if /dev/tty is a tty.
+ * Fills in io_fds[SFD_USERTTY], io_fds[SFD_LEADER] and io_fds[SFD_FOLLOWER].
+ * Returns the dyamically allocated pty name on success, NULL on failure.
+ */
+static char *
+pty_setup(struct command_details *details)
+{
+ char *ptyname = NULL;
+ debug_decl(pty_setup, SUDO_DEBUG_EXEC);
+
+ io_fds[SFD_USERTTY] = open(_PATH_TTY, O_RDWR);
+ if (io_fds[SFD_USERTTY] == -1) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: no %s, not allocating a pty",
+ __func__, _PATH_TTY);
+ debug_return_ptr(NULL);
+ }
+
+ ptyname = get_pty(&io_fds[SFD_LEADER], &io_fds[SFD_FOLLOWER],
+ details->cred.euid);
+ if (ptyname == NULL)
+ sudo_fatal("%s", U_("unable to allocate pty"));
+
+ /* Add entry to utmp/utmpx? */
+ if (ISSET(details->flags, CD_SET_UTMP))
+ utmp_login(details->tty, ptyname, io_fds[SFD_FOLLOWER], details->utmp_user);
+
+ /* Update tty name in command details (used by monitor, SELinux, AIX). */
+ details->tty = ptyname;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: %s fd %d, pty leader fd %d, pty follower fd %d",
+ __func__, _PATH_TTY, io_fds[SFD_USERTTY], io_fds[SFD_LEADER],
+ io_fds[SFD_FOLLOWER]);
+
+ debug_return_str(ptyname);
+}
+
+/*
+ * Restore user's terminal settings and update utmp, as needed.
+ */
+static void
+pty_cleanup(struct exec_closure *ec, int wstatus)
+{
+ debug_decl(pty_cleanup, SUDO_DEBUG_EXEC);
+
+ /* Restore terminal settings. */
+ if (ec->term_raw) {
+ /* Only restore the terminal if sudo is the foreground process. */
+ const pid_t tcpgrp = tcgetpgrp(io_fds[SFD_USERTTY]);
+ if (tcpgrp == ec->ppgrp) {
+ if (!sudo_term_restore(io_fds[SFD_USERTTY], false))
+ sudo_warn("%s", U_("unable to restore terminal settings"));
+ ec->term_raw = false;
+ }
+ }
+
+ /* Update utmp */
+ if (ISSET(ec->details->flags, CD_SET_UTMP) && ec->ptyname != NULL)
+ utmp_logout(ec->ptyname, wstatus);
+
+ debug_return;
+}
+
+/*
+ * Cleanup hook for sudo_fatal()/sudo_fatalx()
+ */
+static void
+pty_cleanup_hook(void)
+{
+ pty_cleanup(&pty_ec, 0);
+}
+
+/*
+ * Check whether sudo is running in the foreground.
+ * Updates the foreground flag in the closure.
+ * Returns 0 if there is no tty, the foreground process group ID
+ * on success, or -1 on failure (tty revoked).
+ */
+static pid_t
+check_foreground(struct exec_closure *ec)
+{
+ int ret = 0;
+ debug_decl(check_foreground, SUDO_DEBUG_EXEC);
+
+ if (io_fds[SFD_USERTTY] != -1) {
+ if ((ret = tcgetpgrp(io_fds[SFD_USERTTY])) != -1) {
+ ec->foreground = ret == ec->ppgrp;
+ }
+ }
+ debug_return_int(ret);
+}
+
+/*
+ * Restore the terminal when sudo is resumed in response to SIGCONT.
+ */
+static bool
+resume_terminal(struct exec_closure *ec)
+{
+ debug_decl(resume_terminal, SUDO_DEBUG_EXEC);
+
+ if (check_foreground(ec) == -1) {
+ /* User's tty was revoked. */
+ debug_return_bool(false);
+ }
+
+ /* Update the pty settings based on the user's terminal. */
+ if (!sudo_term_copy(io_fds[SFD_USERTTY], io_fds[SFD_LEADER])) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to copy terminal settings to pty", __func__);
+ debug_return_bool(false);
+ }
+ sync_ttysize(ec);
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "parent is in %s (%s -> %s)",
+ ec->foreground ? "foreground" : "background",
+ ec->term_raw ? "raw" : "cooked",
+ ec->foreground ? "raw" : "cooked");
+
+ if (ec->foreground) {
+ /* Foreground process, set tty to raw mode. */
+ ec->term_raw = sudo_term_raw(io_fds[SFD_USERTTY], term_raw_flags);
+ } else {
+ /* Background process, no access to tty. */
+ ec->term_raw = false;
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Suspend sudo if the underlying command is suspended.
+ * Returns SIGCONT_FG if the command should be resumed in the
+ * foreground or SIGCONT_BG if it is a background process.
+ */
+static int
+suspend_sudo_pty(struct exec_closure *ec, int signo)
+{
+ char signame[SIG2STR_MAX];
+ struct sigaction sa, osa, saved_sigcont;
+ int ret = 0;
+ debug_decl(suspend_sudo_pty, SUDO_DEBUG_EXEC);
+
+ /*
+ * Ignore SIGCONT when we suspend to avoid calling resume_terminal()
+ * multiple times.
+ */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = SIG_DFL;
+ if (sudo_sigaction(SIGCONT, &sa, &saved_sigcont) != 0)
+ sudo_warn("%s", U_("unable to set handler for SIGCONT"));
+
+ if (sig2str(signo, signame) == -1)
+ (void)snprintf(signame, sizeof(signame), "%d", signo);
+
+ switch (signo) {
+ case SIGTTOU:
+ case SIGTTIN:
+ /*
+ * If sudo is already the foreground process, just resume the command
+ * in the foreground. If not, we'll suspend sudo and resume later.
+ */
+ if (!ec->foreground) {
+ if (check_foreground(ec) == -1) {
+ /* User's tty was revoked. */
+ break;
+ }
+ }
+ if (ec->foreground) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: command received SIG%s, parent running in the foregound",
+ __func__, signame);
+ if (!ec->term_raw) {
+ if (sudo_term_raw(io_fds[SFD_USERTTY], term_raw_flags))
+ ec->term_raw = true;
+ }
+ ret = SIGCONT_FG; /* resume command in foreground */
+ break;
+ }
+ FALLTHROUGH;
+ case SIGSTOP:
+ case SIGTSTP:
+ default:
+ /* Flush any remaining output and deschedule I/O events. */
+ del_io_events(true);
+
+ /* Restore original tty mode before suspending. */
+ if (ec->term_raw) {
+ if (!sudo_term_restore(io_fds[SFD_USERTTY], false))
+ sudo_warn("%s", U_("unable to restore terminal settings"));
+ ec->term_raw = false;
+ }
+
+ /* Log the suspend event. */
+ log_suspend(ec, signo);
+
+ /* Suspend self and continue command when we resume. */
+ if (signo != SIGSTOP) {
+ if (sudo_sigaction(signo, &sa, &osa) != 0)
+ sudo_warn(U_("unable to set handler for SIG%s"), signame);
+ }
+
+ /*
+ * We stop sudo's process group, even if sudo is not the process
+ * group leader. If we only send the signal to sudo itself,
+ * the shell will not notice if it is not in monitor mode.
+ * This can happen when sudo is run from a shell script, for
+ * example. In this case we need to signal the shell itself.
+ * If the process group leader is no longer present, we must kill
+ * the command since there will be no one to resume us.
+ */
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: killpg(%d, SIG%s) [parent]",
+ __func__, (int)ec->ppgrp, signame);
+ if ((ec->ppgrp != ec->sudo_pid && kill(ec->ppgrp, 0) == -1) ||
+ killpg(ec->ppgrp, signo) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: no parent to suspend, terminating command.", __func__);
+ terminate_command(ec->cmnd_pid, true);
+ ec->cmnd_pid = -1;
+ }
+
+ if (signo != SIGSTOP) {
+ if (sudo_sigaction(signo, &osa, NULL) != 0)
+ sudo_warn(U_("unable to restore handler for SIG%s"), signame);
+ }
+
+ /* If we failed to suspend, the command is no longer running. */
+ if (ec->cmnd_pid == -1)
+ break;
+
+ /* Log the resume event. */
+ log_suspend(ec, SIGCONT);
+
+ /* Update the pty's terminal settings and restore /dev/tty settings. */
+ if (!resume_terminal(ec))
+ break;
+
+ /*
+ * We always resume the command in the foreground if sudo itself
+ * is the foreground process (and we were able to set /dev/tty to
+ * raw mode). This helps work around poorly behaved programs that
+ * catch SIGTTOU/SIGTTIN but suspend themselves with SIGSTOP. At
+ * worst, sudo will go into the background but upon resume the
+ * command will be runnable. Otherwise, we can get into a
+ * situation where the command will immediately suspend itself.
+ */
+ ret = ec->term_raw ? SIGCONT_FG : SIGCONT_BG;
+ break;
+ }
+
+ if (sudo_sigaction(SIGCONT, &saved_sigcont, NULL) != 0)
+ sudo_warn("%s", U_("unable to restore handler for SIGCONT"));
+
+ debug_return_int(ret);
+}
+
+/*
+ * SIGTTIN signal handler for read_callback that just sets a flag.
+ */
+static volatile sig_atomic_t got_sigttin;
+
+static void
+sigttin(int signo)
+{
+ got_sigttin = 1;
+}
+
+/*
+ * Read an iobuf that is ready.
+ */
+static void
+read_callback(int fd, int what, void *v)
+{
+ struct io_buffer *iob = v;
+ struct sudo_event_base *evbase = sudo_ev_get_base(iob->revent);
+ struct sigaction sa, osa;
+ int saved_errno;
+ ssize_t n;
+ debug_decl(read_callback, SUDO_DEBUG_EXEC);
+
+ /*
+ * We ignore SIGTTIN by default but we need to handle it when reading
+ * from the terminal. A signal event won't work here because the
+ * read() would be restarted, preventing the callback from running.
+ */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = sigttin;
+ got_sigttin = 0;
+ sigaction(SIGTTIN, &sa, &osa);
+ n = read(fd, iob->buf + iob->len, sizeof(iob->buf) - iob->len);
+ saved_errno = errno;
+ sigaction(SIGTTIN, &osa, NULL);
+ errno = saved_errno;
+
+ switch (n) {
+ case -1:
+ if (got_sigttin) {
+ /* Schedule SIGTTIN to be forwarded to the command. */
+ schedule_signal(iob->ec, SIGTTIN);
+ }
+ if (errno == EAGAIN || errno == EINTR) {
+ /* Not an error, retry later. */
+ break;
+ }
+ /* Treat read error as fatal and close the fd. */
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "error reading fd %d: %s", fd, strerror(errno));
+ FALLTHROUGH;
+ case 0:
+ /* got EOF or pty has gone away */
+ if (n == 0) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "read EOF from fd %d", fd);
+ }
+ safe_close(fd);
+ ev_free_by_fd(evbase, fd);
+ /* If writer already consumed the buffer, close it too. */
+ if (iob->wevent != NULL && iob->off == iob->len) {
+ safe_close(sudo_ev_get_fd(iob->wevent));
+ ev_free_by_fd(evbase, sudo_ev_get_fd(iob->wevent));
+ iob->off = iob->len = 0;
+ }
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "read %zd bytes from fd %d", n, fd);
+ if (!iob->action(iob->buf + iob->len, (unsigned int)n, iob)) {
+ terminate_command(iob->ec->cmnd_pid, true);
+ iob->ec->cmnd_pid = -1;
+ }
+ iob->len += (unsigned int)n;
+ /* Disable reader if buffer is full. */
+ if (iob->len == sizeof(iob->buf))
+ sudo_ev_del(evbase, iob->revent);
+ /* Enable writer now that there is new data in the buffer. */
+ if (iob->wevent != NULL) {
+ if (sudo_ev_add(evbase, iob->wevent, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+ }
+ break;
+ }
+
+ debug_return;
+}
+
+/*
+ * SIGTTOU signal handler for write_callback that just sets a flag.
+ */
+static volatile sig_atomic_t got_sigttou;
+
+static void
+sigttou(int signo)
+{
+ got_sigttou = 1;
+}
+
+/*
+ * Write an iobuf that is ready.
+ */
+static void
+write_callback(int fd, int what, void *v)
+{
+ struct io_buffer *iob = v;
+ struct sudo_event_base *evbase = sudo_ev_get_base(iob->wevent);
+ struct sigaction sa, osa;
+ int saved_errno;
+ ssize_t n;
+ debug_decl(write_callback, SUDO_DEBUG_EXEC);
+
+ /*
+ * We ignore SIGTTOU by default but we need to handle it when writing
+ * to the terminal. A signal event won't work here because the
+ * write() would be restarted, preventing the callback from running.
+ */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = sigttou;
+ got_sigttou = 0;
+ sigaction(SIGTTOU, &sa, &osa);
+ n = write(fd, iob->buf + iob->off, iob->len - iob->off);
+ saved_errno = errno;
+ sigaction(SIGTTOU, &osa, NULL);
+ errno = saved_errno;
+
+ if (n == -1) {
+ switch (errno) {
+ case EPIPE:
+ case ENXIO:
+ case EIO:
+ case EBADF:
+ /* other end of pipe closed or pty revoked */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "unable to write %u bytes to fd %d",
+ iob->len - iob->off, fd);
+ /* Close reader if there is one. */
+ if (iob->revent != NULL) {
+ safe_close(sudo_ev_get_fd(iob->revent));
+ ev_free_by_fd(evbase, sudo_ev_get_fd(iob->revent));
+ }
+ safe_close(fd);
+ ev_free_by_fd(evbase, fd);
+ break;
+ case EINTR:
+ if (got_sigttou) {
+ /* Schedule SIGTTOU to be forwarded to the command. */
+ schedule_signal(iob->ec, SIGTTOU);
+ }
+ FALLTHROUGH;
+ case EAGAIN:
+ /* Not an error, retry later. */
+ break;
+ default:
+ /* XXX - need a way to distinguish non-exec error. */
+ iob->ec->cstat->type = CMD_ERRNO;
+ iob->ec->cstat->val = errno;
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "error writing fd %d: %s", fd, strerror(errno));
+ sudo_ev_loopbreak(evbase);
+ break;
+ }
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "wrote %zd of %u bytes to fd %d", n, iob->len - iob->off, fd);
+ iob->off += (unsigned int)n;
+ /* Disable writer and reset the buffer if fully consumed. */
+ if (iob->off == iob->len) {
+ iob->off = iob->len = 0;
+ sudo_ev_del(evbase, iob->wevent);
+ /* Forward the EOF from reader to writer. */
+ if (iob->revent == NULL) {
+ safe_close(fd);
+ ev_free_by_fd(evbase, fd);
+ }
+ }
+ /*
+ * Enable reader if buffer is not full but avoid reading /dev/tty
+ * if not in raw mode or the command is no longer running.
+ */
+ if (iob->revent != NULL && iob->len != sizeof(iob->buf)) {
+ if (!USERTTY_EVENT(iob->revent) ||
+ (iob->ec->term_raw && iob->ec->cmnd_pid != -1)) {
+ if (sudo_ev_add(evbase, iob->revent, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+ }
+ }
+ }
+
+ debug_return;
+}
+
+/*
+ * We already closed the follower so reads from the leader will not block.
+ */
+static void
+pty_finish(struct exec_closure *ec, struct command_status *cstat)
+{
+ int flags;
+ debug_decl(pty_finish, SUDO_DEBUG_EXEC);
+
+ /* Flush any remaining output (the plugin already got it) and free bufs. */
+ if (io_fds[SFD_USERTTY] != -1) {
+ flags = fcntl(io_fds[SFD_USERTTY], F_GETFL, 0);
+ if (flags != -1 && ISSET(flags, O_NONBLOCK)) {
+ CLR(flags, O_NONBLOCK);
+ (void) fcntl(io_fds[SFD_USERTTY], F_SETFL, flags);
+ }
+ }
+ del_io_events(false);
+ free_io_bufs();
+
+ /* Restore terminal settings and update utmp. */
+ pty_cleanup(ec, cstat->type == CMD_WSTATUS ? cstat->val : 0);
+
+ debug_return;
+}
+
+/*
+ * Send command status to the monitor (currently just signal forwarding).
+ */
+static void
+send_command_status(struct exec_closure *ec, int type, int val)
+{
+ struct monitor_message *msg;
+ debug_decl(send_command_status, SUDO_DEBUG_EXEC);
+
+ if ((msg = calloc(1, sizeof(*msg))) == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ msg->cstat.type = type;
+ msg->cstat.val = val;
+ TAILQ_INSERT_TAIL(&monitor_messages, msg, entries);
+
+ if (sudo_ev_add(ec->evbase, ec->fwdchannel_event, NULL, true) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ /* Restart event loop to send the command immediately. */
+ sudo_ev_loopcontinue(ec->evbase);
+
+ debug_return;
+}
+
+/*
+ * Schedule a signal to be forwarded.
+ */
+static void
+schedule_signal(struct exec_closure *ec, int signo)
+{
+ debug_decl(schedule_signal, SUDO_DEBUG_EXEC);
+
+ if (signo == 0)
+ debug_return;
+
+ if (sudo_debug_needed(SUDO_DEBUG_DIAG)) {
+ char signame[SIG2STR_MAX];
+ if (signo == SIGCONT_FG)
+ strlcpy(signame, "CONT_FG", sizeof(signame));
+ else if (signo == SIGCONT_BG)
+ strlcpy(signame, "CONT_BG", sizeof(signame));
+ else if (sig2str(signo, signame) == -1)
+ (void)snprintf(signame, sizeof(signame), "%d", signo);
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "scheduled SIG%s for command",
+ signame);
+ }
+
+ send_command_status(ec, CMD_SIGNO, signo);
+
+ debug_return;
+}
+
+/*
+ * Free any remaining monitor messages in the queue.
+ */
+static void
+flush_monitor_messages(void)
+{
+ struct monitor_message *msg;
+ debug_decl(flush_monitor_messages, SUDO_DEBUG_EXEC);
+
+ while ((msg = TAILQ_FIRST(&monitor_messages)) != NULL) {
+ TAILQ_REMOVE(&monitor_messages, msg, entries);
+ free(msg);
+ }
+
+ debug_return;
+}
+
+static void
+backchannel_cb(int fd, int what, void *v)
+{
+ struct exec_closure *ec = v;
+ struct command_status cstat;
+ ssize_t nread;
+ debug_decl(backchannel_cb, SUDO_DEBUG_EXEC);
+
+ /*
+ * Read command status from the monitor.
+ * Note that the backchannel is a *blocking* socket.
+ */
+ nread = recv(fd, &cstat, sizeof(cstat), MSG_WAITALL);
+ switch (nread) {
+ case -1:
+ switch (errno) {
+ case EINTR:
+ case EAGAIN:
+ /* Nothing ready. */
+ break;
+ default:
+ if (ec->cstat->val == CMD_INVALID) {
+ ec->cstat->type = CMD_ERRNO;
+ ec->cstat->val = errno;
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: failed to read command status: %s",
+ __func__, strerror(errno));
+ sudo_ev_loopbreak(ec->evbase);
+ }
+ break;
+ }
+ break;
+ case 0:
+ /* EOF, monitor exited or was killed. */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "EOF on backchannel, monitor dead?");
+ if (ec->cstat->type == CMD_INVALID) {
+ /* XXX - need new CMD_ type for monitor errors. */
+ ec->cstat->type = CMD_ERRNO;
+ ec->cstat->val = ECONNRESET;
+ }
+ sudo_ev_loopexit(ec->evbase);
+ break;
+ case sizeof(cstat):
+ /* Check command status. */
+ switch (cstat.type) {
+ case CMD_PID:
+ ec->cmnd_pid = cstat.val;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "executed %s, pid %d",
+ ec->details->command, (int)ec->cmnd_pid);
+ if (ISSET(ec->details->flags, CD_USE_PTRACE)) {
+ /* Try to seize control of the command using ptrace(2). */
+ int rc = exec_ptrace_seize(ec->cmnd_pid);
+ if (rc == 0) {
+ /* There is another tracer present. */
+ CLR(ec->details->flags, CD_INTERCEPT|CD_LOG_SUBCMDS|CD_USE_PTRACE);
+ } else if (rc == -1) {
+ if (ec->cstat->type == CMD_INVALID) {
+ ec->cstat->type = CMD_ERRNO;
+ ec->cstat->val = errno;
+ }
+ sudo_ev_loopbreak(ec->evbase);
+ }
+ }
+ break;
+ case CMD_WSTATUS:
+ if (WIFSTOPPED(cstat.val)) {
+ int signo;
+
+ /* Suspend parent and tell monitor how to resume on return. */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "command stopped, suspending parent");
+ signo = suspend_sudo_pty(ec, WSTOPSIG(cstat.val));
+ schedule_signal(ec, signo);
+ /* Re-enable I/O events */
+ add_io_events(ec);
+ } else {
+ /* Command exited or was killed, either way we are done. */
+ sudo_debug_printf(SUDO_DEBUG_INFO, "command exited or was killed");
+ sudo_ev_loopexit(ec->evbase);
+ *ec->cstat = cstat;
+ }
+ break;
+ case CMD_ERRNO:
+ /* Monitor was unable to execute command or broken pipe. */
+ sudo_debug_printf(SUDO_DEBUG_INFO, "errno from monitor: %s",
+ strerror(cstat.val));
+ sudo_ev_loopbreak(ec->evbase);
+ *ec->cstat = cstat;
+ break;
+ }
+ /* Keep reading command status messages until EAGAIN or EOF. */
+ break;
+ default:
+ /* Short read, should not happen. */
+ if (ec->cstat->val == CMD_INVALID) {
+ ec->cstat->type = CMD_ERRNO;
+ ec->cstat->val = EIO;
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: failed to read command status: short read", __func__);
+ sudo_ev_loopbreak(ec->evbase);
+ }
+ break;
+ }
+ debug_return;
+}
+
+/*
+ * Handle changes to the monitors's status (SIGCHLD).
+ */
+static void
+handle_sigchld_pty(struct exec_closure *ec)
+{
+ int n, status;
+ pid_t pid;
+ debug_decl(handle_sigchld_pty, SUDO_DEBUG_EXEC);
+
+ /* There may be multiple children in intercept mode. */
+ for (;;) {
+ do {
+ pid = waitpid(-1, &status, __WALL|WUNTRACED|WNOHANG);
+ } while (pid == -1 && errno == EINTR);
+ switch (pid) {
+ case -1:
+ if (errno != ECHILD) {
+ sudo_warn(U_("%s: %s"), __func__, "waitpid");
+ debug_return;
+ }
+ FALLTHROUGH;
+ case 0:
+ /* Nothing left to wait for. */
+ debug_return;
+ }
+
+ if (WIFEXITED(status)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: process %d exited: %d",
+ __func__, (int)pid, WEXITSTATUS(status));
+ if (pid == ec->monitor_pid)
+ ec->monitor_pid = -1;
+ } else if (WIFSIGNALED(status)) {
+ if (sudo_debug_needed(SUDO_DEBUG_INFO)) {
+ char signame[SIG2STR_MAX];
+ if (sig2str(WTERMSIG(status), signame) == -1) {
+ (void)snprintf(signame, sizeof(signame), "%d",
+ WTERMSIG(status));
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: process %d killed, SIG%s",
+ __func__, (int)pid, signame);
+ }
+ if (pid == ec->monitor_pid)
+ ec->monitor_pid = -1;
+ } else if (WIFSTOPPED(status)) {
+ if (pid != ec->monitor_pid) {
+ if (ISSET(ec->details->flags, CD_USE_PTRACE))
+ exec_ptrace_stopped(pid, status, ec->intercept);
+ continue;
+ }
+
+ /*
+ * If the monitor dies we get notified via backchannel_cb().
+ * If it was stopped, we should stop too (the command keeps
+ * running in its pty) and continue it when we come back.
+ */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "monitor stopped, suspending sudo");
+ n = suspend_sudo_pty(ec, WSTOPSIG(status));
+ kill(pid, SIGCONT);
+ schedule_signal(ec, n);
+ /* Re-enable I/O events */
+ add_io_events(ec);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN,
+ "%s: unexpected wait status 0x%x for process (%d)",
+ __func__, status, (int)pid);
+ }
+ }
+}
+
+/* Signal callback */
+static void
+signal_cb_pty(int signo, int what, void *v)
+{
+ struct sudo_ev_siginfo_container *sc = v;
+ struct exec_closure *ec = sc->closure;
+ debug_decl(signal_cb_pty, SUDO_DEBUG_EXEC);
+
+ if (ec->monitor_pid == -1)
+ debug_return;
+
+ if (sudo_debug_needed(SUDO_DEBUG_DIAG)) {
+ char signame[SIG2STR_MAX];
+ if (sig2str(signo, signame) == -1)
+ (void)snprintf(signame, sizeof(signame), "%d", signo);
+ sudo_debug_printf(SUDO_DEBUG_DIAG,
+ "%s: evbase %p, monitor: %d, signo %s(%d), cstat %p", __func__,
+ ec->evbase, (int)ec->monitor_pid, signame, signo, ec->cstat);
+ }
+
+ switch (signo) {
+ case SIGCHLD:
+ handle_sigchld_pty(ec);
+ break;
+ case SIGCONT:
+ resume_terminal(ec);
+ break;
+ case SIGWINCH:
+ sync_ttysize(ec);
+ break;
+ default:
+ /*
+ * Do not forward signals sent by the command itself or a member of the
+ * command's process group (but only when either sudo or the command is
+ * the process group leader). We don't want the command to indirectly
+ * kill itself. For example, this can happen with some versions of
+ * reboot that call kill(-1, SIGTERM) to kill all other processes.
+ */
+ if (USER_SIGNALED(sc->siginfo) && sc->siginfo->si_pid != 0) {
+ pid_t si_pgrp;
+
+ if (sc->siginfo->si_pid == ec->cmnd_pid)
+ debug_return;
+ si_pgrp = getpgid(sc->siginfo->si_pid);
+ if (si_pgrp != -1) {
+ if (si_pgrp == ec->cmnd_pid || si_pgrp == ec->sudo_pid)
+ debug_return;
+ }
+ }
+ /* Schedule signal to be forwarded to the command. */
+ schedule_signal(ec, signo);
+ break;
+ }
+
+ debug_return;
+}
+
+/*
+ * Forward signals in monitor_messages to the monitor so it can
+ * deliver them to the command.
+ */
+static void
+fwdchannel_cb(int sock, int what, void *v)
+{
+ struct exec_closure *ec = v;
+ struct monitor_message *msg;
+ ssize_t nsent;
+ debug_decl(fwdchannel_cb, SUDO_DEBUG_EXEC);
+
+ while ((msg = TAILQ_FIRST(&monitor_messages)) != NULL) {
+ switch (msg->cstat.type) {
+ case CMD_SIGNO:
+ if (sudo_debug_needed(SUDO_DEBUG_INFO)) {
+ char signame[SIG2STR_MAX];
+ if (msg->cstat.val == SIGCONT_FG)
+ strlcpy(signame, "CONT_FG", sizeof(signame));
+ else if (msg->cstat.val == SIGCONT_BG)
+ strlcpy(signame, "CONT_BG", sizeof(signame));
+ else if (sig2str(msg->cstat.val, signame) == -1) {
+ (void)snprintf(signame, sizeof(signame), "%d",
+ msg->cstat.val);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "sending SIG%s to monitor over backchannel", signame);
+ }
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "sending cstat type %d, value %d to monitor over backchannel",
+ msg->cstat.type, msg->cstat.val);
+ break;
+ }
+ TAILQ_REMOVE(&monitor_messages, msg, entries);
+ nsent = send(sock, &msg->cstat, sizeof(msg->cstat), 0);
+ if (nsent != sizeof(msg->cstat)) {
+ if (errno == EPIPE) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "broken pipe writing to monitor over backchannel");
+ /* Other end of socket gone, empty out monitor_messages. */
+ free(msg);
+ flush_monitor_messages();
+ /* XXX - need new CMD_ type for monitor errors. */
+ ec->cstat->type = CMD_ERRNO;
+ ec->cstat->val = errno;
+ sudo_ev_loopbreak(ec->evbase);
+ }
+ break;
+ }
+ free(msg);
+ }
+}
+
+/*
+ * Fill in the exec closure and setup initial exec events.
+ * Allocates events for the signal pipe and backchannel.
+ * Forwarded signals on the backchannel are enabled on demand.
+ */
+static void
+fill_exec_closure(struct exec_closure *ec, struct command_status *cstat,
+ struct command_details *details, const struct user_details *user_details,
+ struct sudo_event_base *evbase, pid_t sudo_pid, pid_t ppgrp, int backchannel)
+{
+ debug_decl(fill_exec_closure, SUDO_DEBUG_EXEC);
+
+ /* Fill in the non-event part of the closure. */
+ ec->sudo_pid = sudo_pid;
+ ec->ppgrp = ppgrp;
+ ec->cmnd_pid = -1;
+ ec->cstat = cstat;
+ ec->details = details;
+ ec->rows = user_details->ts_rows;
+ ec->cols = user_details->ts_cols;
+
+ /* Reset cstat for running the command. */
+ cstat->type = CMD_INVALID;
+ cstat->val = 0;
+
+ /* Setup event base and events. */
+ ec->evbase = evbase;
+
+ /* Event for command status via backchannel. */
+ ec->backchannel_event = sudo_ev_alloc(backchannel,
+ SUDO_EV_READ|SUDO_EV_PERSIST, backchannel_cb, ec);
+ if (ec->backchannel_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->backchannel_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+ sudo_debug_printf(SUDO_DEBUG_INFO, "backchannel fd %d\n", backchannel);
+
+ /* Events for local signals. */
+ ec->sigint_event = sudo_ev_alloc(SIGINT,
+ SUDO_EV_SIGINFO, signal_cb_pty, ec);
+ if (ec->sigint_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigint_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigquit_event = sudo_ev_alloc(SIGQUIT,
+ SUDO_EV_SIGINFO, signal_cb_pty, ec);
+ if (ec->sigquit_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigquit_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigtstp_event = sudo_ev_alloc(SIGTSTP,
+ SUDO_EV_SIGINFO, signal_cb_pty, ec);
+ if (ec->sigtstp_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigtstp_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigterm_event = sudo_ev_alloc(SIGTERM,
+ SUDO_EV_SIGINFO, signal_cb_pty, ec);
+ if (ec->sigterm_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigterm_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sighup_event = sudo_ev_alloc(SIGHUP,
+ SUDO_EV_SIGINFO, signal_cb_pty, ec);
+ if (ec->sighup_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sighup_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigalrm_event = sudo_ev_alloc(SIGALRM,
+ SUDO_EV_SIGINFO, signal_cb_pty, ec);
+ if (ec->sigalrm_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigalrm_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigusr1_event = sudo_ev_alloc(SIGUSR1,
+ SUDO_EV_SIGINFO, signal_cb_pty, ec);
+ if (ec->sigusr1_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigusr1_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigusr2_event = sudo_ev_alloc(SIGUSR2,
+ SUDO_EV_SIGINFO, signal_cb_pty, ec);
+ if (ec->sigusr2_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigusr2_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigchld_event = sudo_ev_alloc(SIGCHLD,
+ SUDO_EV_SIGINFO, signal_cb_pty, ec);
+ if (ec->sigchld_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigchld_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigcont_event = sudo_ev_alloc(SIGCONT,
+ SUDO_EV_SIGINFO, signal_cb_pty, ec);
+ if (ec->sigcont_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigcont_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ ec->sigwinch_event = sudo_ev_alloc(SIGWINCH,
+ SUDO_EV_SIGINFO, signal_cb_pty, ec);
+ if (ec->sigwinch_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (sudo_ev_add(ec->evbase, ec->sigwinch_event, NULL, false) == -1)
+ sudo_fatal("%s", U_("unable to add event to queue"));
+
+ /* The signal forwarding event gets added on demand. */
+ ec->fwdchannel_event = sudo_ev_alloc(backchannel,
+ SUDO_EV_WRITE, fwdchannel_cb, ec);
+ if (ec->fwdchannel_event == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ /* Set the default event base. */
+ sudo_ev_base_setdef(ec->evbase);
+
+ debug_return;
+}
+
+/*
+ * Execute a command in a pty, potentially with I/O logging, and
+ * wait for it to finish.
+ * This is a little bit tricky due to how POSIX job control works and
+ * we fact that we have two different controlling terminals to deal with.
+ */
+bool
+exec_pty(struct command_details *details,
+ const struct user_details *user_details, struct sudo_event_base *evbase,
+ struct command_status *cstat)
+{
+ int io_pipe[3][2] = { { -1, -1 }, { -1, -1 }, { -1, -1 } };
+ bool interpose[3] = { false, false, false };
+ struct stat sb, tty_sbuf, *tty_sb = NULL;
+ int sv[2], intercept_sv[2] = { -1, -1 };
+ struct exec_closure *ec = &pty_ec;
+ struct plugin_container *plugin;
+ int evloop_retries = -1;
+ bool cmnd_foreground;
+ sigset_t set, oset;
+ struct sigaction sa;
+ pid_t ppgrp, sudo_pid;
+ debug_decl(exec_pty, SUDO_DEBUG_EXEC);
+
+ /*
+ * Allocate a pty if sudo is running in a terminal.
+ */
+ ec->ptyname = pty_setup(details);
+ if (ec->ptyname == NULL)
+ debug_return_bool(false);
+
+ /* Register cleanup function */
+ sudo_fatal_callback_register(pty_cleanup_hook);
+
+ /*
+ * We communicate with the monitor over a bi-directional pair of sockets.
+ * Parent sends signal info to monitor and monitor sends back wait status.
+ */
+ if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1 ||
+ fcntl(sv[0], F_SETFD, FD_CLOEXEC) == -1 ||
+ fcntl(sv[1], F_SETFD, FD_CLOEXEC) == -1)
+ sudo_fatal("%s", U_("unable to create sockets"));
+
+ if (ISSET(details->flags, CD_INTERCEPT|CD_LOG_SUBCMDS)) {
+ if (!ISSET(details->flags, CD_USE_PTRACE)) {
+ /*
+ * Allocate a socketpair for communicating with sudo_intercept.so.
+ * This must be inherited across exec, hence no FD_CLOEXEC.
+ */
+ if (socketpair(PF_UNIX, SOCK_STREAM, 0, intercept_sv) == -1)
+ sudo_fatal("%s", U_("unable to create sockets"));
+ }
+ }
+
+ /*
+ * We don't want to receive SIGTTIN/SIGTTOU.
+ * XXX - this affects tcsetattr() and tcsetpgrp() too.
+ */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = SIG_IGN;
+ if (sudo_sigaction(SIGTTIN, &sa, NULL) != 0)
+ sudo_warn(U_("unable to set handler for signal %d"), SIGTTIN);
+ if (sudo_sigaction(SIGTTOU, &sa, NULL) != 0)
+ sudo_warn(U_("unable to set handler for signal %d"), SIGTTOU);
+
+ /*
+ * The policy plugin's session init must be run before we fork
+ * or certain pam modules won't be able to track their state.
+ */
+ if (policy_init_session(details) != true)
+ sudo_fatalx("%s", U_("policy plugin failed session initialization"));
+
+ /*
+ * Child will run the command in the pty, parent will pass data
+ * to and from pty.
+ */
+ init_ttyblock();
+ ppgrp = getpgrp(); /* parent's pgrp, so child can signal us */
+ sudo_pid = getpid();
+
+ /* Determine whether any of std{in,out,err} should be logged. */
+ TAILQ_FOREACH(plugin, &io_plugins, entries) {
+ if (plugin->u.io->log_stdin)
+ interpose[STDIN_FILENO] = true;
+ if (plugin->u.io->log_stdout)
+ interpose[STDOUT_FILENO] = true;
+ if (plugin->u.io->log_stderr)
+ interpose[STDERR_FILENO] = true;
+ }
+
+ /*
+ * Setup stdin/stdout/stderr for command, to be duped after forking.
+ */
+ io_fds[SFD_STDIN] = io_fds[SFD_FOLLOWER];
+ io_fds[SFD_STDOUT] = io_fds[SFD_FOLLOWER];
+ io_fds[SFD_STDERR] = io_fds[SFD_FOLLOWER];
+
+ if (io_fds[SFD_USERTTY] != -1) {
+ /* Read from /dev/tty, write to pty leader */
+ if (!ISSET(details->flags, CD_BACKGROUND)) {
+ io_buf_new(io_fds[SFD_USERTTY], io_fds[SFD_LEADER],
+ log_ttyin, read_callback, write_callback, ec);
+ }
+
+ /* Read from pty leader, write to /dev/tty */
+ io_buf_new(io_fds[SFD_LEADER], io_fds[SFD_USERTTY],
+ log_ttyout, read_callback, write_callback, ec);
+
+ /* Are we the foreground process? */
+ ec->foreground = tcgetpgrp(io_fds[SFD_USERTTY]) == ppgrp;
+ sudo_debug_printf(SUDO_DEBUG_INFO, "sudo is running in the %s",
+ ec->foreground ? "foreground" : "background");
+ }
+
+ /*
+ * If stdin, stdout or stderr is not the user's tty and logging is
+ * enabled, use a pipe to interpose ourselves instead of using the
+ * pty fd. We always use a pipe for stdin when in background mode.
+ */
+ if (user_details->tty != NULL && stat(user_details->tty, &tty_sbuf) != -1)
+ tty_sb = &tty_sbuf;
+
+ if (!fd_matches_tty(STDIN_FILENO, tty_sb, &sb)) {
+ if (!interpose[STDIN_FILENO]) {
+ /* Not logging stdin, do not interpose. */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "stdin not user's tty, not logging");
+ if (S_ISFIFO(sb.st_mode))
+ SET(details->flags, CD_EXEC_BG);
+ io_fds[SFD_STDIN] = dup(STDIN_FILENO);
+ if (io_fds[SFD_STDIN] == -1)
+ sudo_fatal("dup");
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "stdin not user's tty, creating a pipe");
+ SET(details->flags, CD_EXEC_BG);
+ if (pipe2(io_pipe[STDIN_FILENO], O_CLOEXEC) != 0)
+ sudo_fatal("%s", U_("unable to create pipe"));
+ io_buf_new(STDIN_FILENO, io_pipe[STDIN_FILENO][1],
+ log_stdin, read_callback, write_callback, ec);
+ io_fds[SFD_STDIN] = io_pipe[STDIN_FILENO][0];
+ }
+
+ if (ec->foreground && ppgrp != sudo_pid) {
+ /*
+ * If sudo is not the process group leader and stdin is not
+ * a tty we may be running as a background job via a shell
+ * script. Start the command in the background to avoid
+ * changing the terminal mode from a background process.
+ */
+ SET(details->flags, CD_EXEC_BG);
+ }
+ } else if (ISSET(details->flags, CD_BACKGROUND)) {
+ /*
+ * Running in background (sudo -b), no access to terminal input.
+ * In non-pty mode, the command runs in an orphaned process
+ * group and reads from the controlling terminal fail with EIO.
+ * We cannot do the same while running in a pty but if we set
+ * stdin to a half-closed pipe, reads from it will get EOF.
+ */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "terminal input not available, creating empty pipe");
+ SET(details->flags, CD_EXEC_BG);
+ if (pipe2(io_pipe[STDIN_FILENO], O_CLOEXEC) != 0)
+ sudo_fatal("%s", U_("unable to create pipe"));
+ io_fds[SFD_STDIN] = io_pipe[STDIN_FILENO][0];
+ close(io_pipe[STDIN_FILENO][1]);
+ io_pipe[STDIN_FILENO][1] = -1;
+ }
+ if (!fd_matches_tty(STDOUT_FILENO, tty_sb, &sb)) {
+ if (!interpose[STDOUT_FILENO]) {
+ /* Not logging stdout, do not interpose. */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "stdout not user's tty, not logging");
+ if (S_ISFIFO(sb.st_mode)) {
+ SET(details->flags, CD_EXEC_BG);
+ term_raw_flags = SUDO_TERM_OFLAG;
+ }
+ io_fds[SFD_STDOUT] = dup(STDOUT_FILENO);
+ if (io_fds[SFD_STDOUT] == -1)
+ sudo_fatal("dup");
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "stdout not user's tty, creating a pipe");
+ SET(details->flags, CD_EXEC_BG);
+ term_raw_flags = SUDO_TERM_OFLAG;
+ if (pipe2(io_pipe[STDOUT_FILENO], O_CLOEXEC) != 0)
+ sudo_fatal("%s", U_("unable to create pipe"));
+ io_buf_new(io_pipe[STDOUT_FILENO][0], STDOUT_FILENO,
+ log_stdout, read_callback, write_callback, ec);
+ io_fds[SFD_STDOUT] = io_pipe[STDOUT_FILENO][1];
+ }
+ }
+ if (!fd_matches_tty(STDERR_FILENO, tty_sb, &sb)) {
+ if (!interpose[STDERR_FILENO]) {
+ /* Not logging stderr, do not interpose. */
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "stderr not user's tty, not logging");
+ io_fds[SFD_STDERR] = dup(STDERR_FILENO);
+ if (io_fds[SFD_STDERR] == -1)
+ sudo_fatal("dup");
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "stderr /dev/tty, creating a pipe");
+ if (pipe2(io_pipe[STDERR_FILENO], O_CLOEXEC) != 0)
+ sudo_fatal("%s", U_("unable to create pipe"));
+ io_buf_new(io_pipe[STDERR_FILENO][0], STDERR_FILENO,
+ log_stderr, read_callback, write_callback, ec);
+ io_fds[SFD_STDERR] = io_pipe[STDERR_FILENO][1];
+ }
+ }
+
+ /*
+ * Copy terminal settings from user tty -> pty. If sudo is a
+ * background process, we'll re-init the pty when foregrounded.
+ */
+ if (!sudo_term_copy(io_fds[SFD_USERTTY], io_fds[SFD_LEADER])) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to copy terminal settings to pty", __func__);
+ ec->foreground = false;
+ }
+ /* Start in raw mode unless the command will run in the background. */
+ cmnd_foreground = ec->foreground && !ISSET(details->flags, CD_EXEC_BG);
+ if (cmnd_foreground) {
+ if (sudo_term_raw(io_fds[SFD_USERTTY], 0))
+ ec->term_raw = true;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: follower: %d, stdin: %d, stdout: %d, stderr: %d", __func__,
+ io_fds[SFD_FOLLOWER], io_fds[SFD_STDIN], io_fds[SFD_STDOUT],
+ io_fds[SFD_STDERR]);
+
+ /*
+ * Block signals until we have our handlers setup in the parent so
+ * we don't miss SIGCHLD if the command exits immediately.
+ */
+ sigfillset(&set);
+ sigprocmask(SIG_BLOCK, &set, &oset);
+
+ /* Check for early termination or suspend signals before we fork. */
+ if (sudo_terminated(cstat)) {
+ sigprocmask(SIG_SETMASK, &oset, NULL);
+ debug_return_bool(true);
+ }
+
+ ec->monitor_pid = sudo_debug_fork();
+ switch (ec->monitor_pid) {
+ case -1:
+ sudo_fatal("%s", U_("unable to fork"));
+ break;
+ case 0:
+ /* child */
+ close(sv[0]);
+ if (intercept_sv[0] != -1)
+ close(intercept_sv[0]);
+ /* Close the other end of the stdin/stdout/stderr pipes and exec. */
+ if (io_pipe[STDIN_FILENO][1] != -1)
+ close(io_pipe[STDIN_FILENO][1]);
+ if (io_pipe[STDOUT_FILENO][0] != -1)
+ close(io_pipe[STDOUT_FILENO][0]);
+ if (io_pipe[STDERR_FILENO][0] != -1)
+ close(io_pipe[STDERR_FILENO][0]);
+
+ /* Only run the cleanup hook in the parent. */
+ sudo_fatal_callback_deregister(pty_cleanup_hook);
+
+ /*
+ * If stdin/stdout is not the user's tty, start the command in
+ * the background since it might be part of a pipeline that reads
+ * from /dev/tty. In this case, we rely on the command receiving
+ * SIGTTOU or SIGTTIN when it needs access to the controlling tty.
+ */
+ exec_monitor(details, &oset, cmnd_foreground, sv[1], intercept_sv[1]);
+ cstat->type = CMD_ERRNO;
+ cstat->val = errno;
+ if (send(sv[1], cstat, sizeof(*cstat), 0) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to send status to parent", __func__);
+ }
+ _exit(EXIT_FAILURE);
+ /* NOTREACHED */
+ }
+
+ /*
+ * We close the pty follower so only the monitor and command have a
+ * reference to it. This ensures that we can don't block reading
+ * from the leader when the command and monitor have exited.
+ */
+ if (io_fds[SFD_FOLLOWER] != -1) {
+ close(io_fds[SFD_FOLLOWER]);
+ io_fds[SFD_FOLLOWER] = -1;
+ }
+
+ /* Tell the monitor to continue now that the follower is closed. */
+ cstat->type = CMD_SIGNO;
+ cstat->val = 0;
+ if (send(sv[0], cstat, sizeof(*cstat), 0) == -1)
+ sudo_fatal("%s", U_("unable to send message to monitor process"));
+
+ /* Close the other end of the stdin/stdout/stderr pipes and socketpair. */
+ if (io_pipe[STDIN_FILENO][0] != -1)
+ close(io_pipe[STDIN_FILENO][0]);
+ if (io_pipe[STDOUT_FILENO][1] != -1)
+ close(io_pipe[STDOUT_FILENO][1]);
+ if (io_pipe[STDERR_FILENO][1] != -1)
+ close(io_pipe[STDERR_FILENO][1]);
+ close(sv[1]);
+
+ /* No longer need execfd. */
+ if (details->execfd != -1) {
+ close(details->execfd);
+ details->execfd = -1;
+ }
+
+ /* Set command timeout if specified. */
+ if (ISSET(details->flags, CD_SET_TIMEOUT))
+ alarm(details->timeout);
+
+ /*
+ * Fill in exec closure, allocate event base, signal events and
+ * the backchannel event.
+ */
+ fill_exec_closure(ec, cstat, details, user_details, evbase,
+ sudo_pid, ppgrp, sv[0]);
+
+ /* Create event and closure for intercept mode. */
+ if (ISSET(details->flags, CD_INTERCEPT|CD_LOG_SUBCMDS)) {
+ ec->intercept = intercept_setup(intercept_sv[0], ec->evbase, details);
+ if (ec->intercept == NULL)
+ terminate_command(ec->cmnd_pid, true);
+ }
+
+ /* Restore signal mask now that signal handlers are setup. */
+ sigprocmask(SIG_SETMASK, &oset, NULL);
+
+ /*
+ * I/O logging must be in the C locale for floating point numbers
+ * to be logged consistently.
+ */
+ setlocale(LC_ALL, "C");
+
+ /*
+ * In the event loop we pass input from user tty to leader
+ * and pass output from leader to stdout and IO plugin.
+ * Try to recover on ENXIO, it means the tty was revoked.
+ */
+ add_io_events(ec);
+ do {
+ if (sudo_ev_dispatch(ec->evbase) == -1)
+ sudo_warn("%s", U_("error in event loop"));
+ if (sudo_ev_got_break(ec->evbase)) {
+ /* error from callback or monitor died */
+ sudo_debug_printf(SUDO_DEBUG_ERROR, "event loop exited prematurely");
+ /* XXX: no good way to know if we should terminate the command. */
+ if (cstat->val == CMD_INVALID && ec->cmnd_pid != -1) {
+ /* no status message, kill command */
+ terminate_command(ec->cmnd_pid, true);
+ ec->cmnd_pid = -1;
+ /* TODO: need way to pass an error to the sudo front end */
+ cstat->type = CMD_WSTATUS;
+ cstat->val = W_EXITCODE(1, SIGKILL);
+ }
+ } else if (!sudo_ev_got_exit(ec->evbase)) {
+ switch (errno) {
+ case ENXIO:
+ case EIO:
+ case EBADF:
+ /* /dev/tty was revoked, remove tty events and retry (once) */
+ if (evloop_retries == -1 && io_fds[SFD_USERTTY] != -1) {
+ ev_free_by_fd(ec->evbase, io_fds[SFD_USERTTY]);
+ evloop_retries = 1;
+ }
+ break;
+ }
+ }
+ } while (evloop_retries-- > 0);
+
+ /* De-register cleanup hook, the pty is going away. */
+ sudo_fatal_callback_deregister(pty_cleanup_hook);
+
+ /* Flush any remaining output, free I/O bufs and events, do logout. */
+ pty_finish(ec, cstat);
+
+ /* Free things up. */
+ free_exec_closure(ec);
+
+ debug_return_bool(true);
+}
+
+/*
+ * Propagate tty size change to pty being used by the command, pass
+ * new window size to I/O plugins and deliver SIGWINCH to the command.
+ */
+static void
+sync_ttysize(struct exec_closure *ec)
+{
+ struct winsize wsize;
+ debug_decl(sync_ttysize, SUDO_DEBUG_EXEC);
+
+ if (ioctl(io_fds[SFD_USERTTY], TIOCGWINSZ, &wsize) == 0) {
+ if (wsize.ws_row != ec->rows || wsize.ws_col != ec->cols) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: %d x %d -> %hd x %hd",
+ __func__, ec->rows, ec->cols, wsize.ws_row, wsize.ws_col);
+
+ /* Log window change event. */
+ log_winchange(ec, wsize.ws_row, wsize.ws_col);
+
+ /* Update pty window size and send command SIGWINCH. */
+ (void)ioctl(io_fds[SFD_LEADER], IOCTL_REQ_CAST TIOCSWINSZ, &wsize);
+ killpg(ec->cmnd_pid, SIGWINCH);
+
+ /* Update rows/cols. */
+ ec->rows = wsize.ws_row;
+ ec->cols = wsize.ws_col;
+ }
+ }
+
+ debug_return;
+}
diff --git a/src/get_pty.c b/src/get_pty.c
new file mode 100644
index 0000000..666a295
--- /dev/null
+++ b/src/get_pty.c
@@ -0,0 +1,189 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2012, 2014-2016
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_STROPTS_H
+#include <sys/stropts.h>
+#endif /* HAVE_SYS_STROPTS_H */
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+
+#if defined(HAVE_OPENPTY)
+# if defined(HAVE_LIBUTIL_H)
+# include <libutil.h> /* *BSD */
+# elif defined(HAVE_UTIL_H)
+# include <util.h> /* macOS */
+# elif defined(HAVE_PTY_H)
+# include <pty.h> /* Linux */
+# else
+# include <termios.h> /* Solaris */
+# endif
+#endif
+
+#include <sudo.h>
+
+#if defined(HAVE_OPENPTY)
+char *
+get_pty(int *leader, int *follower, uid_t ttyuid)
+{
+ struct group *gr;
+ gid_t ttygid = (gid_t)-1;
+ char name[PATH_MAX];
+ char *ret = NULL;
+ debug_decl(get_pty, SUDO_DEBUG_PTY);
+
+ if ((gr = getgrnam("tty")) != NULL)
+ ttygid = gr->gr_gid;
+
+ if (openpty(leader, follower, name, NULL, NULL) == 0) {
+ if (chown(name, ttyuid, ttygid) == 0)
+ ret = strdup(name);
+ }
+
+ debug_return_str(ret);
+}
+
+#elif defined(HAVE__GETPTY)
+char *
+get_pty(int *leader, int *follower, uid_t ttyuid)
+{
+ char *line;
+ char *ret = NULL;
+ debug_decl(get_pty, SUDO_DEBUG_PTY);
+
+ /* IRIX-style dynamic ptys (may fork) */
+ line = _getpty(leader, O_RDWR, S_IRUSR|S_IWUSR|S_IWGRP, 0);
+ if (line != NULL) {
+ *follower = open(line, O_RDWR|O_NOCTTY, 0);
+ if (*follower != -1) {
+ (void) chown(line, ttyuid, -1);
+ ret = strdup(line);
+ } else {
+ close(*leader);
+ *leader = -1;
+ }
+ }
+ debug_return_str(ret);
+}
+#elif defined(HAVE_GRANTPT)
+# ifndef HAVE_POSIX_OPENPT
+static int
+posix_openpt(int oflag)
+{
+ int fd;
+
+# ifdef _AIX
+ fd = open(_PATH_DEV "ptc", oflag);
+# else
+ fd = open(_PATH_DEV "ptmx", oflag);
+# endif
+ return fd;
+}
+# endif /* HAVE_POSIX_OPENPT */
+
+char *
+get_pty(int *leader, int *follower, uid_t ttyuid)
+{
+ char *line, *ret = NULL;
+ debug_decl(get_pty, SUDO_DEBUG_PTY);
+
+ *leader = posix_openpt(O_RDWR|O_NOCTTY);
+ if (*leader != -1) {
+ (void) grantpt(*leader); /* may fork */
+ if (unlockpt(*leader) != 0) {
+ close(*leader);
+ goto done;
+ }
+ line = ptsname(*leader);
+ if (line == NULL) {
+ close(*leader);
+ goto done;
+ }
+ *follower = open(line, O_RDWR|O_NOCTTY, 0);
+ if (*follower == -1) {
+ close(*leader);
+ goto done;
+ }
+# if defined(I_PUSH) && !defined(_AIX)
+ ioctl(*follower, I_PUSH, "ptem"); /* pseudo tty emulation module */
+ ioctl(*follower, I_PUSH, "ldterm"); /* line discipline module */
+# endif
+ (void) chown(line, ttyuid, -1);
+ ret = strdup(line);
+ }
+done:
+ debug_return_str(ret);
+}
+
+#else /* Old-style BSD ptys */
+
+static char line[] = _PATH_DEV "ptyXX";
+
+char *
+get_pty(int *leader, int *follower, uid_t ttyuid)
+{
+ char *bank, *cp;
+ struct group *gr;
+ gid_t ttygid = -1;
+ char *ret = NULL;
+ debug_decl(get_pty, SUDO_DEBUG_PTY);
+
+ if ((gr = getgrnam("tty")) != NULL)
+ ttygid = gr->gr_gid;
+
+ for (bank = "pqrs"; *bank != '\0'; bank++) {
+ line[sizeof(_PATH_DEV "ptyX") - 2] = *bank;
+ for (cp = "0123456789abcdef"; *cp != '\0'; cp++) {
+ line[sizeof(_PATH_DEV "ptyXX") - 2] = *cp;
+ *leader = open(line, O_RDWR|O_NOCTTY, 0);
+ if (*leader == -1) {
+ if (errno == ENOENT)
+ goto done; /* out of ptys */
+ continue; /* already in use */
+ }
+ line[sizeof(_PATH_DEV "p") - 2] = 't';
+ (void) chown(line, ttyuid, ttygid);
+ (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
+# ifdef HAVE_REVOKE
+ (void) revoke(line);
+# endif
+ *follower = open(line, O_RDWR|O_NOCTTY, 0);
+ if (*follower != -1) {
+ ret = strdup(line);
+ goto done;
+ }
+ (void) close(*leader);
+ }
+ }
+done:
+ debug_return_str(ret);
+}
+#endif /* HAVE_OPENPTY */
diff --git a/src/hooks.c b/src/hooks.c
new file mode 100644
index 0000000..8ef3e93
--- /dev/null
+++ b/src/hooks.c
@@ -0,0 +1,245 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2012-2016 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sudo.h>
+#include <sudo_plugin.h>
+#include <sudo_plugin_int.h>
+
+/* Singly linked hook list. */
+struct sudo_hook_entry {
+ SLIST_ENTRY(sudo_hook_entry) entries;
+ union {
+ sudo_hook_fn_t generic_fn;
+ sudo_hook_fn_setenv_t setenv_fn;
+ sudo_hook_fn_unsetenv_t unsetenv_fn;
+ sudo_hook_fn_getenv_t getenv_fn;
+ sudo_hook_fn_putenv_t putenv_fn;
+ } u;
+ void *closure;
+};
+SLIST_HEAD(sudo_hook_list, sudo_hook_entry);
+
+/* Each hook type gets own hook list. */
+static struct sudo_hook_list sudo_hook_setenv_list =
+ SLIST_HEAD_INITIALIZER(sudo_hook_setenv_list);
+static struct sudo_hook_list sudo_hook_unsetenv_list =
+ SLIST_HEAD_INITIALIZER(sudo_hook_unsetenv_list);
+static struct sudo_hook_list sudo_hook_getenv_list =
+ SLIST_HEAD_INITIALIZER(sudo_hook_getenv_list);
+static struct sudo_hook_list sudo_hook_putenv_list =
+ SLIST_HEAD_INITIALIZER(sudo_hook_putenv_list);
+
+/* NOTE: must not anything that might call setenv() */
+int
+process_hooks_setenv(const char *name, const char *value, int overwrite)
+{
+ struct sudo_hook_entry *hook;
+ int rc = SUDO_HOOK_RET_NEXT;
+
+ /* First process the hooks. */
+ SLIST_FOREACH(hook, &sudo_hook_setenv_list, entries) {
+ rc = hook->u.setenv_fn(name, value, overwrite, hook->closure);
+ if (rc == SUDO_HOOK_RET_STOP || rc == SUDO_HOOK_RET_ERROR)
+ break;
+ }
+ return rc;
+}
+
+/* NOTE: must not anything that might call putenv() */
+int
+process_hooks_putenv(char *string)
+{
+ struct sudo_hook_entry *hook;
+ int rc = SUDO_HOOK_RET_NEXT;
+
+ /* First process the hooks. */
+ SLIST_FOREACH(hook, &sudo_hook_putenv_list, entries) {
+ rc = hook->u.putenv_fn(string, hook->closure);
+ if (rc == SUDO_HOOK_RET_STOP || rc == SUDO_HOOK_RET_ERROR)
+ break;
+ }
+ return rc;
+}
+
+/* NOTE: must not anything that might call getenv() */
+int
+process_hooks_getenv(const char *name, char **value)
+{
+ struct sudo_hook_entry *hook;
+ char *val = NULL;
+ int rc = SUDO_HOOK_RET_NEXT;
+
+ /* First process the hooks. */
+ SLIST_FOREACH(hook, &sudo_hook_getenv_list, entries) {
+ rc = hook->u.getenv_fn(name, &val, hook->closure);
+ if (rc == SUDO_HOOK_RET_STOP || rc == SUDO_HOOK_RET_ERROR)
+ break;
+ }
+ if (val != NULL)
+ *value = val;
+ return rc;
+}
+
+/* NOTE: must not anything that might call unsetenv() */
+int
+process_hooks_unsetenv(const char *name)
+{
+ struct sudo_hook_entry *hook;
+ int rc = SUDO_HOOK_RET_NEXT;
+
+ /* First process the hooks. */
+ SLIST_FOREACH(hook, &sudo_hook_unsetenv_list, entries) {
+ rc = hook->u.unsetenv_fn(name, hook->closure);
+ if (rc == SUDO_HOOK_RET_STOP || rc == SUDO_HOOK_RET_ERROR)
+ break;
+ }
+ return rc;
+}
+
+/* Hook registration internals. */
+static int
+register_hook_internal(struct sudo_hook_list *head,
+ int (*hook_fn)(), void *closure)
+{
+ struct sudo_hook_entry *hook;
+ debug_decl(register_hook_internal, SUDO_DEBUG_HOOKS);
+
+ if ((hook = calloc(1, sizeof(*hook))) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ debug_return_int(-1);
+ }
+ hook->u.generic_fn = hook_fn;
+ hook->closure = closure;
+ SLIST_INSERT_HEAD(head, hook, entries);
+
+ debug_return_int(0);
+}
+
+/* Register the specified hook. */
+int
+register_hook(struct sudo_hook *hook)
+{
+ int ret;
+ debug_decl(register_hook, SUDO_DEBUG_HOOKS);
+
+ if (SUDO_API_VERSION_GET_MAJOR(hook->hook_version) != SUDO_HOOK_VERSION_MAJOR) {
+ /* Major versions must match. */
+ errno = EINVAL;
+ ret = -1;
+ } else {
+ switch (hook->hook_type) {
+ case SUDO_HOOK_GETENV:
+ ret = register_hook_internal(&sudo_hook_getenv_list,
+ hook->hook_fn, hook->closure);
+ break;
+ case SUDO_HOOK_PUTENV:
+ ret = register_hook_internal(&sudo_hook_putenv_list,
+ hook->hook_fn, hook->closure);
+ break;
+ case SUDO_HOOK_SETENV:
+ ret = register_hook_internal(&sudo_hook_setenv_list,
+ hook->hook_fn, hook->closure);
+ break;
+ case SUDO_HOOK_UNSETENV:
+ ret = register_hook_internal(&sudo_hook_unsetenv_list,
+ hook->hook_fn, hook->closure);
+ break;
+ default:
+ /* XXX - use define for unknown value */
+ errno = ENOTSUP;
+ ret = 1;
+ break;
+ }
+ }
+
+ debug_return_int(ret);
+}
+
+/* Hook deregistration internals. */
+static void
+deregister_hook_internal(struct sudo_hook_list *head,
+ int (*hook_fn)(), void *closure)
+{
+ struct sudo_hook_entry *hook, *prev = NULL;
+ debug_decl(deregister_hook_internal, SUDO_DEBUG_HOOKS);
+
+ SLIST_FOREACH(hook, head, entries) {
+ if (hook->u.generic_fn == hook_fn && hook->closure == closure) {
+ /* Remove from list and free. */
+ if (prev == NULL)
+ SLIST_REMOVE_HEAD(head, entries);
+ else
+ SLIST_REMOVE_AFTER(prev, entries);
+ free(hook);
+ break;
+ }
+ prev = hook;
+ }
+
+ debug_return;
+}
+
+/* Deregister the specified hook. */
+int
+deregister_hook(struct sudo_hook *hook)
+{
+ int ret = 0;
+ debug_decl(deregister_hook, SUDO_DEBUG_HOOKS);
+
+ if (SUDO_API_VERSION_GET_MAJOR(hook->hook_version) != SUDO_HOOK_VERSION_MAJOR) {
+ /* Major versions must match. */
+ ret = -1;
+ } else {
+ switch (hook->hook_type) {
+ case SUDO_HOOK_GETENV:
+ deregister_hook_internal(&sudo_hook_getenv_list, hook->hook_fn,
+ hook->closure);
+ break;
+ case SUDO_HOOK_PUTENV:
+ deregister_hook_internal(&sudo_hook_putenv_list, hook->hook_fn,
+ hook->closure);
+ break;
+ case SUDO_HOOK_SETENV:
+ deregister_hook_internal(&sudo_hook_setenv_list, hook->hook_fn,
+ hook->closure);
+ break;
+ case SUDO_HOOK_UNSETENV:
+ deregister_hook_internal(&sudo_hook_unsetenv_list, hook->hook_fn,
+ hook->closure);
+ break;
+ default:
+ /* XXX - use define for unknown value */
+ ret = 1;
+ break;
+ }
+ }
+
+ debug_return_int(ret);
+}
diff --git a/src/intercept.exp.in b/src/intercept.exp.in
new file mode 100644
index 0000000..cb22c8a
--- /dev/null
+++ b/src/intercept.exp.in
@@ -0,0 +1,7 @@
+@INTERCEPT_EXP@execl
+execle
+execlp
+execv
+execve
+execvp
+system
diff --git a/src/intercept.pb-c.c b/src/intercept.pb-c.c
new file mode 100644
index 0000000..2c58e69
--- /dev/null
+++ b/src/intercept.pb-c.c
@@ -0,0 +1,842 @@
+/* Generated by the protocol buffer compiler. DO NOT EDIT! */
+/* Generated from: intercept.proto */
+
+/* Do not generate deprecated warnings for self */
+#ifndef PROTOBUF_C__NO_DEPRECATED
+#define PROTOBUF_C__NO_DEPRECATED
+#endif
+
+#include <intercept.pb-c.h>
+void intercept_request__init
+ (InterceptRequest *message)
+{
+ static const InterceptRequest init_value = INTERCEPT_REQUEST__INIT;
+ *message = init_value;
+}
+size_t intercept_request__get_packed_size
+ (const InterceptRequest *message)
+{
+ assert(message->base.descriptor == &intercept_request__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t intercept_request__pack
+ (const InterceptRequest *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &intercept_request__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t intercept_request__pack_to_buffer
+ (const InterceptRequest *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &intercept_request__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+InterceptRequest *
+ intercept_request__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (InterceptRequest *)
+ protobuf_c_message_unpack (&intercept_request__descriptor,
+ allocator, len, data);
+}
+void intercept_request__free_unpacked
+ (InterceptRequest *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &intercept_request__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void intercept_hello__init
+ (InterceptHello *message)
+{
+ static const InterceptHello init_value = INTERCEPT_HELLO__INIT;
+ *message = init_value;
+}
+size_t intercept_hello__get_packed_size
+ (const InterceptHello *message)
+{
+ assert(message->base.descriptor == &intercept_hello__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t intercept_hello__pack
+ (const InterceptHello *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &intercept_hello__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t intercept_hello__pack_to_buffer
+ (const InterceptHello *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &intercept_hello__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+InterceptHello *
+ intercept_hello__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (InterceptHello *)
+ protobuf_c_message_unpack (&intercept_hello__descriptor,
+ allocator, len, data);
+}
+void intercept_hello__free_unpacked
+ (InterceptHello *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &intercept_hello__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void hello_response__init
+ (HelloResponse *message)
+{
+ static const HelloResponse init_value = HELLO_RESPONSE__INIT;
+ *message = init_value;
+}
+size_t hello_response__get_packed_size
+ (const HelloResponse *message)
+{
+ assert(message->base.descriptor == &hello_response__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t hello_response__pack
+ (const HelloResponse *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &hello_response__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t hello_response__pack_to_buffer
+ (const HelloResponse *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &hello_response__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+HelloResponse *
+ hello_response__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (HelloResponse *)
+ protobuf_c_message_unpack (&hello_response__descriptor,
+ allocator, len, data);
+}
+void hello_response__free_unpacked
+ (HelloResponse *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &hello_response__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void policy_check_request__init
+ (PolicyCheckRequest *message)
+{
+ static const PolicyCheckRequest init_value = POLICY_CHECK_REQUEST__INIT;
+ *message = init_value;
+}
+size_t policy_check_request__get_packed_size
+ (const PolicyCheckRequest *message)
+{
+ assert(message->base.descriptor == &policy_check_request__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t policy_check_request__pack
+ (const PolicyCheckRequest *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &policy_check_request__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t policy_check_request__pack_to_buffer
+ (const PolicyCheckRequest *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &policy_check_request__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+PolicyCheckRequest *
+ policy_check_request__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (PolicyCheckRequest *)
+ protobuf_c_message_unpack (&policy_check_request__descriptor,
+ allocator, len, data);
+}
+void policy_check_request__free_unpacked
+ (PolicyCheckRequest *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &policy_check_request__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void policy_accept_message__init
+ (PolicyAcceptMessage *message)
+{
+ static const PolicyAcceptMessage init_value = POLICY_ACCEPT_MESSAGE__INIT;
+ *message = init_value;
+}
+size_t policy_accept_message__get_packed_size
+ (const PolicyAcceptMessage *message)
+{
+ assert(message->base.descriptor == &policy_accept_message__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t policy_accept_message__pack
+ (const PolicyAcceptMessage *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &policy_accept_message__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t policy_accept_message__pack_to_buffer
+ (const PolicyAcceptMessage *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &policy_accept_message__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+PolicyAcceptMessage *
+ policy_accept_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (PolicyAcceptMessage *)
+ protobuf_c_message_unpack (&policy_accept_message__descriptor,
+ allocator, len, data);
+}
+void policy_accept_message__free_unpacked
+ (PolicyAcceptMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &policy_accept_message__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void policy_reject_message__init
+ (PolicyRejectMessage *message)
+{
+ static const PolicyRejectMessage init_value = POLICY_REJECT_MESSAGE__INIT;
+ *message = init_value;
+}
+size_t policy_reject_message__get_packed_size
+ (const PolicyRejectMessage *message)
+{
+ assert(message->base.descriptor == &policy_reject_message__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t policy_reject_message__pack
+ (const PolicyRejectMessage *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &policy_reject_message__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t policy_reject_message__pack_to_buffer
+ (const PolicyRejectMessage *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &policy_reject_message__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+PolicyRejectMessage *
+ policy_reject_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (PolicyRejectMessage *)
+ protobuf_c_message_unpack (&policy_reject_message__descriptor,
+ allocator, len, data);
+}
+void policy_reject_message__free_unpacked
+ (PolicyRejectMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &policy_reject_message__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void policy_error_message__init
+ (PolicyErrorMessage *message)
+{
+ static const PolicyErrorMessage init_value = POLICY_ERROR_MESSAGE__INIT;
+ *message = init_value;
+}
+size_t policy_error_message__get_packed_size
+ (const PolicyErrorMessage *message)
+{
+ assert(message->base.descriptor == &policy_error_message__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t policy_error_message__pack
+ (const PolicyErrorMessage *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &policy_error_message__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t policy_error_message__pack_to_buffer
+ (const PolicyErrorMessage *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &policy_error_message__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+PolicyErrorMessage *
+ policy_error_message__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (PolicyErrorMessage *)
+ protobuf_c_message_unpack (&policy_error_message__descriptor,
+ allocator, len, data);
+}
+void policy_error_message__free_unpacked
+ (PolicyErrorMessage *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &policy_error_message__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+void intercept_response__init
+ (InterceptResponse *message)
+{
+ static const InterceptResponse init_value = INTERCEPT_RESPONSE__INIT;
+ *message = init_value;
+}
+size_t intercept_response__get_packed_size
+ (const InterceptResponse *message)
+{
+ assert(message->base.descriptor == &intercept_response__descriptor);
+ return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
+}
+size_t intercept_response__pack
+ (const InterceptResponse *message,
+ uint8_t *out)
+{
+ assert(message->base.descriptor == &intercept_response__descriptor);
+ return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
+}
+size_t intercept_response__pack_to_buffer
+ (const InterceptResponse *message,
+ ProtobufCBuffer *buffer)
+{
+ assert(message->base.descriptor == &intercept_response__descriptor);
+ return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
+}
+InterceptResponse *
+ intercept_response__unpack
+ (ProtobufCAllocator *allocator,
+ size_t len,
+ const uint8_t *data)
+{
+ return (InterceptResponse *)
+ protobuf_c_message_unpack (&intercept_response__descriptor,
+ allocator, len, data);
+}
+void intercept_response__free_unpacked
+ (InterceptResponse *message,
+ ProtobufCAllocator *allocator)
+{
+ if(!message)
+ return;
+ assert(message->base.descriptor == &intercept_response__descriptor);
+ protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
+}
+static const ProtobufCFieldDescriptor intercept_request__field_descriptors[2] =
+{
+ {
+ "policy_check_req",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(InterceptRequest, type_case),
+ offsetof(InterceptRequest, u.policy_check_req),
+ &policy_check_request__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "hello",
+ 2,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(InterceptRequest, type_case),
+ offsetof(InterceptRequest, u.hello),
+ &intercept_hello__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned intercept_request__field_indices_by_name[] = {
+ 1, /* field[1] = hello */
+ 0, /* field[0] = policy_check_req */
+};
+static const ProtobufCIntRange intercept_request__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 2 }
+};
+const ProtobufCMessageDescriptor intercept_request__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "InterceptRequest",
+ "InterceptRequest",
+ "InterceptRequest",
+ "",
+ sizeof(InterceptRequest),
+ 2,
+ intercept_request__field_descriptors,
+ intercept_request__field_indices_by_name,
+ 1, intercept_request__number_ranges,
+ (ProtobufCMessageInit) intercept_request__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor intercept_hello__field_descriptors[1] =
+{
+ {
+ "pid",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_INT32,
+ 0, /* quantifier_offset */
+ offsetof(InterceptHello, pid),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned intercept_hello__field_indices_by_name[] = {
+ 0, /* field[0] = pid */
+};
+static const ProtobufCIntRange intercept_hello__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 1 }
+};
+const ProtobufCMessageDescriptor intercept_hello__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "InterceptHello",
+ "InterceptHello",
+ "InterceptHello",
+ "",
+ sizeof(InterceptHello),
+ 1,
+ intercept_hello__field_descriptors,
+ intercept_hello__field_indices_by_name,
+ 1, intercept_hello__number_ranges,
+ (ProtobufCMessageInit) intercept_hello__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor hello_response__field_descriptors[4] =
+{
+ {
+ "token_lo",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_FIXED64,
+ 0, /* quantifier_offset */
+ offsetof(HelloResponse, token_lo),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "token_hi",
+ 2,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_FIXED64,
+ 0, /* quantifier_offset */
+ offsetof(HelloResponse, token_hi),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "portno",
+ 3,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_INT32,
+ 0, /* quantifier_offset */
+ offsetof(HelloResponse, portno),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "log_only",
+ 4,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_BOOL,
+ 0, /* quantifier_offset */
+ offsetof(HelloResponse, log_only),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned hello_response__field_indices_by_name[] = {
+ 3, /* field[3] = log_only */
+ 2, /* field[2] = portno */
+ 1, /* field[1] = token_hi */
+ 0, /* field[0] = token_lo */
+};
+static const ProtobufCIntRange hello_response__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 4 }
+};
+const ProtobufCMessageDescriptor hello_response__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "HelloResponse",
+ "HelloResponse",
+ "HelloResponse",
+ "",
+ sizeof(HelloResponse),
+ 4,
+ hello_response__field_descriptors,
+ hello_response__field_indices_by_name,
+ 1, hello_response__number_ranges,
+ (ProtobufCMessageInit) hello_response__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor policy_check_request__field_descriptors[5] =
+{
+ {
+ "command",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(PolicyCheckRequest, command),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "cwd",
+ 2,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(PolicyCheckRequest, cwd),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "argv",
+ 3,
+ PROTOBUF_C_LABEL_REPEATED,
+ PROTOBUF_C_TYPE_STRING,
+ offsetof(PolicyCheckRequest, n_argv),
+ offsetof(PolicyCheckRequest, argv),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "envp",
+ 4,
+ PROTOBUF_C_LABEL_REPEATED,
+ PROTOBUF_C_TYPE_STRING,
+ offsetof(PolicyCheckRequest, n_envp),
+ offsetof(PolicyCheckRequest, envp),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "intercept_fd",
+ 5,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_INT32,
+ 0, /* quantifier_offset */
+ offsetof(PolicyCheckRequest, intercept_fd),
+ NULL,
+ NULL,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned policy_check_request__field_indices_by_name[] = {
+ 2, /* field[2] = argv */
+ 0, /* field[0] = command */
+ 1, /* field[1] = cwd */
+ 3, /* field[3] = envp */
+ 4, /* field[4] = intercept_fd */
+};
+static const ProtobufCIntRange policy_check_request__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 5 }
+};
+const ProtobufCMessageDescriptor policy_check_request__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "PolicyCheckRequest",
+ "PolicyCheckRequest",
+ "PolicyCheckRequest",
+ "",
+ sizeof(PolicyCheckRequest),
+ 5,
+ policy_check_request__field_descriptors,
+ policy_check_request__field_indices_by_name,
+ 1, policy_check_request__number_ranges,
+ (ProtobufCMessageInit) policy_check_request__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor policy_accept_message__field_descriptors[3] =
+{
+ {
+ "run_command",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(PolicyAcceptMessage, run_command),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "run_argv",
+ 2,
+ PROTOBUF_C_LABEL_REPEATED,
+ PROTOBUF_C_TYPE_STRING,
+ offsetof(PolicyAcceptMessage, n_run_argv),
+ offsetof(PolicyAcceptMessage, run_argv),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "run_envp",
+ 3,
+ PROTOBUF_C_LABEL_REPEATED,
+ PROTOBUF_C_TYPE_STRING,
+ offsetof(PolicyAcceptMessage, n_run_envp),
+ offsetof(PolicyAcceptMessage, run_envp),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned policy_accept_message__field_indices_by_name[] = {
+ 1, /* field[1] = run_argv */
+ 0, /* field[0] = run_command */
+ 2, /* field[2] = run_envp */
+};
+static const ProtobufCIntRange policy_accept_message__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 3 }
+};
+const ProtobufCMessageDescriptor policy_accept_message__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "PolicyAcceptMessage",
+ "PolicyAcceptMessage",
+ "PolicyAcceptMessage",
+ "",
+ sizeof(PolicyAcceptMessage),
+ 3,
+ policy_accept_message__field_descriptors,
+ policy_accept_message__field_indices_by_name,
+ 1, policy_accept_message__number_ranges,
+ (ProtobufCMessageInit) policy_accept_message__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor policy_reject_message__field_descriptors[1] =
+{
+ {
+ "reject_message",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(PolicyRejectMessage, reject_message),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned policy_reject_message__field_indices_by_name[] = {
+ 0, /* field[0] = reject_message */
+};
+static const ProtobufCIntRange policy_reject_message__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 1 }
+};
+const ProtobufCMessageDescriptor policy_reject_message__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "PolicyRejectMessage",
+ "PolicyRejectMessage",
+ "PolicyRejectMessage",
+ "",
+ sizeof(PolicyRejectMessage),
+ 1,
+ policy_reject_message__field_descriptors,
+ policy_reject_message__field_indices_by_name,
+ 1, policy_reject_message__number_ranges,
+ (ProtobufCMessageInit) policy_reject_message__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor policy_error_message__field_descriptors[1] =
+{
+ {
+ "error_message",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_STRING,
+ 0, /* quantifier_offset */
+ offsetof(PolicyErrorMessage, error_message),
+ NULL,
+ &protobuf_c_empty_string,
+ 0, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned policy_error_message__field_indices_by_name[] = {
+ 0, /* field[0] = error_message */
+};
+static const ProtobufCIntRange policy_error_message__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 1 }
+};
+const ProtobufCMessageDescriptor policy_error_message__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "PolicyErrorMessage",
+ "PolicyErrorMessage",
+ "PolicyErrorMessage",
+ "",
+ sizeof(PolicyErrorMessage),
+ 1,
+ policy_error_message__field_descriptors,
+ policy_error_message__field_indices_by_name,
+ 1, policy_error_message__number_ranges,
+ (ProtobufCMessageInit) policy_error_message__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
+static const ProtobufCFieldDescriptor intercept_response__field_descriptors[4] =
+{
+ {
+ "hello_resp",
+ 1,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(InterceptResponse, type_case),
+ offsetof(InterceptResponse, u.hello_resp),
+ &hello_response__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "accept_msg",
+ 2,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(InterceptResponse, type_case),
+ offsetof(InterceptResponse, u.accept_msg),
+ &policy_accept_message__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "reject_msg",
+ 3,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(InterceptResponse, type_case),
+ offsetof(InterceptResponse, u.reject_msg),
+ &policy_reject_message__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+ {
+ "error_msg",
+ 4,
+ PROTOBUF_C_LABEL_NONE,
+ PROTOBUF_C_TYPE_MESSAGE,
+ offsetof(InterceptResponse, type_case),
+ offsetof(InterceptResponse, u.error_msg),
+ &policy_error_message__descriptor,
+ NULL,
+ 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
+ 0,NULL,NULL /* reserved1,reserved2, etc */
+ },
+};
+static const unsigned intercept_response__field_indices_by_name[] = {
+ 1, /* field[1] = accept_msg */
+ 3, /* field[3] = error_msg */
+ 0, /* field[0] = hello_resp */
+ 2, /* field[2] = reject_msg */
+};
+static const ProtobufCIntRange intercept_response__number_ranges[1 + 1] =
+{
+ { 1, 0 },
+ { 0, 4 }
+};
+const ProtobufCMessageDescriptor intercept_response__descriptor =
+{
+ PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
+ "InterceptResponse",
+ "InterceptResponse",
+ "InterceptResponse",
+ "",
+ sizeof(InterceptResponse),
+ 4,
+ intercept_response__field_descriptors,
+ intercept_response__field_indices_by_name,
+ 1, intercept_response__number_ranges,
+ (ProtobufCMessageInit) intercept_response__init,
+ NULL,NULL,NULL /* reserved[123] */
+};
diff --git a/src/intercept.proto b/src/intercept.proto
new file mode 100644
index 0000000..53a068a
--- /dev/null
+++ b/src/intercept.proto
@@ -0,0 +1,71 @@
+syntax = "proto3";
+
+/*
+ * Intercept message from sudo_intercept.so. Messages on the
+ * wire are prefixed with a 32-bit size in network byte order.
+ */
+message InterceptRequest {
+ oneof type {
+ PolicyCheckRequest policy_check_req = 1;
+ InterceptHello hello = 2;
+ }
+}
+
+/*
+ * Hello message from sudo_intercept.so to main sudo process.
+ * Sudo sends back the token and localhost port number.
+ */
+message InterceptHello {
+ int32 pid = 1;
+}
+
+/*
+ * Sudo response to an InterceptHello from sudo_intercept.so.
+ * The client uses the port number and token to connect back to sudo.
+ * If log_only is set there is no InterceptResponse to a PolicyCheckRequest.
+ */
+message HelloResponse {
+ fixed64 token_lo = 1;
+ fixed64 token_hi = 2;
+ int32 portno = 3;
+ bool log_only = 4;
+}
+
+/*
+ * Policy check request from sudo_intercept.so.
+ * Note that the plugin API only currently supports passing
+ * the new environment in to the open() function.
+ */
+message PolicyCheckRequest {
+ string command = 1;
+ string cwd = 2;
+ repeated string argv = 3;
+ repeated string envp = 4;
+ int32 intercept_fd = 5;
+}
+
+message PolicyAcceptMessage {
+ string run_command = 1;
+ repeated string run_argv = 2;
+ repeated string run_envp = 3;
+}
+
+message PolicyRejectMessage {
+ string reject_message = 1;
+}
+
+message PolicyErrorMessage {
+ string error_message = 1;
+}
+
+/*
+ * Response sent back to sudo_intercept.so.
+ */
+message InterceptResponse {
+ oneof type {
+ HelloResponse hello_resp = 1;
+ PolicyAcceptMessage accept_msg = 2;
+ PolicyRejectMessage reject_msg = 3;
+ PolicyErrorMessage error_msg = 4;
+ }
+}
diff --git a/src/limits.c b/src/limits.c
new file mode 100644
index 0000000..2ed69c3
--- /dev/null
+++ b/src/limits.c
@@ -0,0 +1,714 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1999-2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/resource.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef __linux__
+# include <sys/prctl.h>
+#endif
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <sudo.h>
+
+/*
+ * Avoid using RLIM_INFINITY for the nofile soft limit to prevent
+ * closefrom_fallback() from closing too many file descriptors.
+ */
+#if defined(OPEN_MAX) && OPEN_MAX > 256
+# define SUDO_OPEN_MAX OPEN_MAX
+#else
+# define SUDO_OPEN_MAX 256
+#endif
+
+#ifdef __LP64__
+# define SUDO_STACK_MIN (4 * 1024 * 1024)
+#else
+# define SUDO_STACK_MIN (2 * 1024 * 1024)
+#endif
+
+#ifdef HAVE_SETRLIMIT64
+# define getrlimit(a, b) getrlimit64((a), (b))
+# define setrlimit(a, b) setrlimit64((a), (b))
+# define rlimit rlimit64
+# define rlim_t rlim64_t
+# undef RLIM_INFINITY
+# define RLIM_INFINITY RLIM64_INFINITY
+#endif /* HAVE_SETRLIMIT64 */
+
+/* Older BSD systems have RLIMIT_VMEM, not RLIMIT_AS. */
+#if !defined(RLIMIT_AS) && defined(RLIMIT_VMEM)
+# define RLIMIT_AS RLIMIT_VMEM
+#endif
+
+/*
+ * macOS doesn't allow nofile soft limit to be infinite or
+ * the stack hard limit to be infinite.
+ * Linux containers have a problem with an infinite stack soft limit.
+ */
+static struct rlimit stack_fallback = { SUDO_STACK_MIN, 65532 * 1024 };
+
+static struct saved_limit {
+ const char *name; /* rlimit_foo in lower case */
+ int resource; /* RLIMIT_FOO definition */
+ bool override; /* override limit while sudo executes? */
+ bool saved; /* true if we were able to get the value */
+ bool policy; /* true if policy specified an rlimit */
+ bool preserve; /* true if policy says to preserve user limit */
+ rlim_t minlimit; /* only modify limit if less than this value */
+ struct rlimit *fallback; /* fallback if we fail to set to newlimit */
+ struct rlimit newlimit; /* new limit to use if override is true */
+ struct rlimit oldlimit; /* original limit, valid if saved is true */
+ struct rlimit policylimit; /* limit from policy, valid if policy is true */
+} saved_limits[] = {
+#ifdef RLIMIT_AS
+ {
+ "rlimit_as",
+ RLIMIT_AS,
+ true, /* override */
+ false, /* saved */
+ false, /* policy */
+ false, /* preserve */
+ 1 * 1024 * 1024 * 1024, /* minlimit */
+ NULL, /* fallback */
+ { RLIM_INFINITY, RLIM_INFINITY } /* newlimit */
+ },
+#endif
+ {
+ "rlimit_core",
+ RLIMIT_CORE,
+ false /* override */
+ },
+ {
+ "rlimit_cpu",
+ RLIMIT_CPU,
+ true, /* override */
+ false, /* saved */
+ false, /* policy */
+ false, /* preserve */
+ RLIM_INFINITY, /* minlimit */
+ NULL,
+ { RLIM_INFINITY, RLIM_INFINITY }
+ },
+ {
+ "rlimit_data",
+ RLIMIT_DATA,
+ true, /* override */
+ false, /* saved */
+ false, /* policy */
+ false, /* preserve */
+ 1 * 1024 * 1024 * 1024, /* minlimit */
+ NULL,
+ { RLIM_INFINITY, RLIM_INFINITY }
+ },
+ {
+ "rlimit_fsize",
+ RLIMIT_FSIZE,
+ true, /* override */
+ false, /* saved */
+ false, /* policy */
+ false, /* preserve */
+ RLIM_INFINITY, /* minlimit */
+ NULL,
+ { RLIM_INFINITY, RLIM_INFINITY }
+ },
+#ifdef RLIMIT_LOCKS
+ {
+ "rlimit_locks",
+ RLIMIT_LOCKS,
+ false /* override */
+ },
+#endif
+#ifdef RLIMIT_MEMLOCK
+ {
+ "rlimit_memlock",
+ RLIMIT_MEMLOCK,
+ false /* override */
+ },
+#endif
+ {
+ "rlimit_nofile",
+ RLIMIT_NOFILE,
+ true, /* override */
+ false, /* saved */
+ false, /* policy */
+ false, /* preserve */
+ SUDO_OPEN_MAX, /* minlimit */
+ NULL,
+ { SUDO_OPEN_MAX, RLIM_INFINITY }
+ },
+#ifdef RLIMIT_NPROC
+ {
+ "rlimit_nproc",
+ RLIMIT_NPROC,
+ true, /* override */
+ false, /* saved */
+ false, /* policy */
+ false, /* preserve */
+ RLIM_INFINITY, /* minlimit */
+ NULL,
+ { RLIM_INFINITY, RLIM_INFINITY }
+ },
+#endif
+#ifdef RLIMIT_RSS
+ {
+ "rlimit_rss",
+ RLIMIT_RSS,
+ true, /* override */
+ false, /* saved */
+ false, /* policy */
+ false, /* preserve */
+ RLIM_INFINITY, /* minlimit */
+ NULL,
+ { RLIM_INFINITY, RLIM_INFINITY }
+ },
+#endif
+ {
+ "rlimit_stack",
+ RLIMIT_STACK,
+ true, /* override */
+ false, /* saved */
+ false, /* policy */
+ false, /* preserve */
+ SUDO_STACK_MIN, /* minlimit */
+ &stack_fallback,
+ { SUDO_STACK_MIN, RLIM_INFINITY }
+ }
+};
+
+static struct rlimit corelimit;
+static bool coredump_disabled;
+#ifdef __linux__
+static struct rlimit nproclimit;
+static int dumpflag;
+#endif
+
+/*
+ * Disable core dumps to avoid dropping a core with user password in it.
+ * Not all operating systems disable core dumps for setuid processes.
+ */
+void
+disable_coredump(void)
+{
+ debug_decl(disable_coredump, SUDO_DEBUG_UTIL);
+
+ if (getrlimit(RLIMIT_CORE, &corelimit) == 0) {
+ /*
+ * Set the soft limit to 0 but leave the existing hard limit.
+ * On Linux, we need CAP_SYS_RESOURCE to raise the hard limit
+ * which may not be the case in, e.g. an unprivileged container.
+ */
+ struct rlimit rl = corelimit;
+ rl.rlim_cur = 0;
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "RLIMIT_CORE [%lld, %lld] -> [%lld, %lld]",
+ (long long)corelimit.rlim_cur, (long long)corelimit.rlim_max,
+ (long long)rl.rlim_cur, (long long)rl.rlim_max);
+ if (setrlimit(RLIMIT_CORE, &rl) == -1) {
+ sudo_warn("setrlimit(RLIMIT_CORE)");
+ } else {
+ coredump_disabled = true;
+#ifdef __linux__
+ /* On Linux, also set PR_SET_DUMPABLE to zero (reset by execve). */
+ if ((dumpflag = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)");
+ dumpflag = 0;
+ }
+ if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "prctl(PR_SET_DUMPABLE, 0, 0, 0, 0)");
+ }
+#endif /* __linux__ */
+ }
+ } else {
+ sudo_warn("getrlimit(RLIMIT_CORE)");
+ }
+
+ debug_return;
+}
+
+/*
+ * Restore core resource limit before executing the command.
+ */
+static void
+restore_coredump(void)
+{
+ debug_decl(restore_coredump, SUDO_DEBUG_UTIL);
+
+ if (coredump_disabled) {
+ /*
+ * Do not warn about a failure to restore the core dump size limit.
+ * This is mostly harmless and should not happen in practice.
+ */
+ if (setrlimit(RLIMIT_CORE, &corelimit) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "setrlimit(RLIMIT_CORE, [%lld, %lld])",
+ (long long)corelimit.rlim_cur, (long long)corelimit.rlim_max);
+ }
+#ifdef __linux__
+ if (prctl(PR_SET_DUMPABLE, dumpflag, 0, 0, 0) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "prctl(PR_SET_DUMPABLE, %d, 0, 0, 0)", dumpflag);
+ }
+#endif /* __linux__ */
+ }
+ debug_return;
+}
+
+/*
+ * Unlimit the number of processes since Linux's setuid() will
+ * apply resource limits when changing uid and return EAGAIN if
+ * nproc would be exceeded by the uid switch.
+ *
+ * This function is called *after* session setup and before the
+ * final setuid() call.
+ */
+void
+unlimit_nproc(void)
+{
+#ifdef __linux__
+ struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
+ debug_decl(unlimit_nproc, SUDO_DEBUG_UTIL);
+
+ if (getrlimit(RLIMIT_NPROC, &nproclimit) != 0)
+ sudo_warn("getrlimit(RLIMIT_NPROC)");
+ sudo_debug_printf(SUDO_DEBUG_INFO, "RLIMIT_NPROC [%lld, %lld] -> [inf, inf]",
+ (long long)nproclimit.rlim_cur, (long long)nproclimit.rlim_max);
+ if (setrlimit(RLIMIT_NPROC, &rl) == -1) {
+ rl.rlim_cur = rl.rlim_max = nproclimit.rlim_max;
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "RLIMIT_NPROC [%lld, %lld] -> [%lld, %lld]",
+ (long long)nproclimit.rlim_cur, (long long)nproclimit.rlim_max,
+ (long long)rl.rlim_cur, (long long)rl.rlim_max);
+ if (setrlimit(RLIMIT_NPROC, &rl) != 0)
+ sudo_warn("setrlimit(RLIMIT_NPROC)");
+ }
+ debug_return;
+#endif /* __linux__ */
+}
+
+/*
+ * Restore saved value of RLIMIT_NPROC before execve().
+ */
+void
+restore_nproc(void)
+{
+#ifdef __linux__
+ debug_decl(restore_nproc, SUDO_DEBUG_UTIL);
+
+ if (setrlimit(RLIMIT_NPROC, &nproclimit) != 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "setrlimit(RLIMIT_NPROC, [%lld, %lld])",
+ (long long)nproclimit.rlim_cur, (long long)nproclimit.rlim_max);
+ }
+
+ debug_return;
+#endif /* __linux__ */
+}
+
+/*
+ * Unlimit resource limits so sudo is not limited by, e.g.
+ * stack, data or file table sizes.
+ */
+void
+unlimit_sudo(void)
+{
+ unsigned int idx;
+ int pass, rc;
+ debug_decl(unlimit_sudo, SUDO_DEBUG_UTIL);
+
+ /* Set resource limits to unlimited and stash the old values. */
+ for (idx = 0; idx < nitems(saved_limits); idx++) {
+ struct saved_limit *lim = &saved_limits[idx];
+ if (getrlimit(lim->resource, &lim->oldlimit) == -1)
+ continue;
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "getrlimit(%s) -> [%lld, %lld]", lim->name,
+ (long long)lim->oldlimit.rlim_cur,
+ (long long)lim->oldlimit.rlim_max);
+ lim->saved = true;
+
+ /* Only override the existing limit if it is smaller than minlimit. */
+ if (lim->minlimit != RLIM_INFINITY) {
+ if (lim->oldlimit.rlim_cur >= lim->minlimit)
+ lim->override = false;
+ }
+ if (!lim->override)
+ continue;
+
+ for (pass = 0; pass < 2; pass++) {
+ if (lim->newlimit.rlim_cur != RLIM_INFINITY) {
+ /* Don't reduce the soft resource limit. */
+ if (lim->oldlimit.rlim_cur == RLIM_INFINITY ||
+ lim->oldlimit.rlim_cur > lim->newlimit.rlim_cur)
+ lim->newlimit.rlim_cur = lim->oldlimit.rlim_cur;
+ }
+ if (lim->newlimit.rlim_max != RLIM_INFINITY) {
+ /* Don't reduce the hard resource limit. */
+ if (lim->oldlimit.rlim_max == RLIM_INFINITY ||
+ lim->oldlimit.rlim_max > lim->newlimit.rlim_max)
+ lim->newlimit.rlim_max = lim->oldlimit.rlim_max;
+ }
+ if ((rc = setrlimit(lim->resource, &lim->newlimit)) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "setrlimit(%s, [%lld, %lld])", lim->name,
+ (long long)lim->newlimit.rlim_cur,
+ (long long)lim->newlimit.rlim_max);
+ if (pass == 0 && lim->fallback != NULL) {
+ /* Try again using fallback values. */
+ lim->newlimit.rlim_cur = lim->fallback->rlim_cur;
+ lim->newlimit.rlim_max = lim->fallback->rlim_max;
+ continue;
+ }
+ }
+ break;
+ }
+ if (rc == -1) {
+ /* Try setting new rlim_cur to old rlim_max. */
+ lim->newlimit.rlim_cur = lim->oldlimit.rlim_max;
+ lim->newlimit.rlim_max = lim->oldlimit.rlim_max;
+ if ((rc = setrlimit(lim->resource, &lim->newlimit)) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "setrlimit(%s, [%lld, %lld])", lim->name,
+ (long long)lim->newlimit.rlim_cur,
+ (long long)lim->newlimit.rlim_max);
+ }
+ }
+ if (rc == -1)
+ sudo_warn("setrlimit(%s)", lim->name);
+ }
+
+ debug_return;
+}
+
+/*
+ * Restore resource limits modified by unlimit_sudo() and disable_coredump().
+ */
+void
+restore_limits(void)
+{
+ unsigned int idx;
+ debug_decl(restore_limits, SUDO_DEBUG_UTIL);
+
+ /* Restore resource limits to saved values. */
+ for (idx = 0; idx < nitems(saved_limits); idx++) {
+ struct saved_limit *lim = &saved_limits[idx];
+ if (lim->override && lim->saved) {
+ struct rlimit rl = lim->oldlimit;
+ int i, rc;
+
+ for (i = 0; i < 10; i++) {
+ rc = setrlimit(lim->resource, &rl);
+ if (rc != -1 || errno != EINVAL)
+ break;
+
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "setrlimit(%s, [%lld, %lld])", lim->name,
+ (long long)rl.rlim_cur, (long long)rl.rlim_max);
+
+ /*
+ * Soft limit could be lower than current resource usage.
+ * This can be an issue on NetBSD with RLIMIT_STACK and ASLR.
+ */
+ if (rl.rlim_cur > LLONG_MAX / 2)
+ break;
+ rl.rlim_cur *= 2;
+ if (lim->newlimit.rlim_cur != RLIM_INFINITY &&
+ rl.rlim_cur > lim->newlimit.rlim_cur) {
+ rl.rlim_cur = lim->newlimit.rlim_cur;
+ }
+ if (rl.rlim_max != RLIM_INFINITY &&
+ rl.rlim_cur > rl.rlim_max) {
+ rl.rlim_max = rl.rlim_cur;
+ }
+ rc = setrlimit(lim->resource, &rl);
+ if (rc != -1 || errno != EINVAL)
+ break;
+ }
+ if (rc == -1)
+ sudo_warn("setrlimit(%s)", lim->name);
+ }
+ }
+ restore_coredump();
+
+ debug_return;
+}
+
+static bool
+store_rlimit(const char *str, rlim_t *val, bool soft)
+{
+ const size_t inflen = sizeof("infinity") - 1;
+ debug_decl(store_rlimit, SUDO_DEBUG_UTIL);
+
+ if (isdigit((unsigned char)*str)) {
+ unsigned long long ullval = 0;
+ char *ep;
+
+ errno = 0;
+#ifdef HAVE_STRTOULL
+ ullval = strtoull(str, &ep, 10);
+ if (str == ep || (errno == ERANGE && ullval == ULLONG_MAX))
+ debug_return_bool(false);
+#else
+ ullval = strtoul(str, &ep, 10);
+ if (str == ep || (errno == ERANGE && ullval == ULONG_MAX))
+ debug_return_bool(false);
+#endif
+ if (*ep == '\0' || (soft && *ep == ',')) {
+ *val = ullval;
+ debug_return_bool(true);
+ }
+ goto done;
+ }
+ if (strncmp(str, "infinity", inflen) == 0) {
+ if (str[inflen] == '\0' || (soft && str[inflen] == ',')) {
+ *val = RLIM_INFINITY;
+ debug_return_bool(true);
+ }
+ }
+done:
+ debug_return_bool(false);
+}
+
+static bool
+set_policy_rlimit(int resource, const char *val)
+{
+ unsigned int idx;
+ debug_decl(set_policy_rlimit, SUDO_DEBUG_UTIL);
+
+ for (idx = 0; idx < nitems(saved_limits); idx++) {
+ struct saved_limit *lim = &saved_limits[idx];
+ const char *hard, *soft = val;
+
+ if (lim->resource != resource)
+ continue;
+
+ if (strcmp(val, "default") == 0) {
+ /* Use system-assigned limit set by begin_session(). */
+ lim->policy = false;
+ lim->preserve = false;
+ debug_return_bool(true);
+ }
+ if (strcmp(val, "user") == 0) {
+ /* Preserve invoking user's limit. */
+ lim->policy = false;
+ lim->preserve = true;
+ debug_return_bool(true);
+ }
+
+ /*
+ * Expect limit in the form "soft,hard" or "limit" (both soft+hard).
+ */
+ hard = strchr(val, ',');
+ if (hard != NULL)
+ hard++;
+ else
+ hard = soft;
+
+ if (store_rlimit(soft, &lim->policylimit.rlim_cur, true) &&
+ store_rlimit(hard, &lim->policylimit.rlim_max, false)) {
+ lim->policy = true;
+ lim->preserve = false;
+ debug_return_bool(true);
+ }
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: invalid rlimit: %s", lim->name, val);
+ debug_return_bool(false);
+ }
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "invalid resource limit: %d", resource);
+ debug_return_bool(false);
+}
+
+bool
+parse_policy_rlimit(const char *str)
+{
+ bool ret = false;
+ debug_decl(parse_policy_rlimit, SUDO_DEBUG_UTIL);
+
+#ifdef RLIMIT_AS
+ if (strncmp(str, "as=", sizeof("as=") - 1) == 0) {
+ str += sizeof("as=") - 1;
+ ret = set_policy_rlimit(RLIMIT_AS, str);
+ } else
+#endif
+#ifdef RLIMIT_CORE
+ if (strncmp(str, "core=", sizeof("core=") - 1) == 0) {
+ str += sizeof("core=") - 1;
+ ret = set_policy_rlimit(RLIMIT_CORE, str);
+ } else
+#endif
+#ifdef RLIMIT_CPU
+ if (strncmp(str, "cpu=", sizeof("cpu=") - 1) == 0) {
+ str += sizeof("cpu=") - 1;
+ ret = set_policy_rlimit(RLIMIT_CPU, str);
+ } else
+#endif
+#ifdef RLIMIT_DATA
+ if (strncmp(str, "data=", sizeof("data=") - 1) == 0) {
+ str += sizeof("data=") - 1;
+ ret = set_policy_rlimit(RLIMIT_DATA, str);
+ } else
+#endif
+#ifdef RLIMIT_FSIZE
+ if (strncmp(str, "fsize=", sizeof("fsize=") - 1) == 0) {
+ str += sizeof("fsize=") - 1;
+ ret = set_policy_rlimit(RLIMIT_FSIZE, str);
+ } else
+#endif
+#ifdef RLIMIT_LOCKS
+ if (strncmp(str, "locks=", sizeof("locks=") - 1) == 0) {
+ str += sizeof("locks=") - 1;
+ ret = set_policy_rlimit(RLIMIT_LOCKS, str);
+ } else
+#endif
+#ifdef RLIMIT_MEMLOCK
+ if (strncmp(str, "memlock=", sizeof("memlock=") - 1) == 0) {
+ str += sizeof("memlock=") - 1;
+ ret = set_policy_rlimit(RLIMIT_MEMLOCK, str);
+ } else
+#endif
+#ifdef RLIMIT_NOFILE
+ if (strncmp(str, "nofile=", sizeof("nofile=") - 1) == 0) {
+ str += sizeof("nofile=") - 1;
+ ret = set_policy_rlimit(RLIMIT_NOFILE, str);
+ } else
+#endif
+#ifdef RLIMIT_NPROC
+ if (strncmp(str, "nproc=", sizeof("nproc=") - 1) == 0) {
+ str += sizeof("nproc=") - 1;
+ ret = set_policy_rlimit(RLIMIT_NPROC, str);
+ } else
+#endif
+#ifdef RLIMIT_RSS
+ if (strncmp(str, "rss=", sizeof("rss=") - 1) == 0) {
+ str += sizeof("rss=") - 1;
+ ret = set_policy_rlimit(RLIMIT_RSS, str);
+ } else
+#endif
+#ifdef RLIMIT_STACK
+ if (strncmp(str, "stack=", sizeof("stack=") - 1) == 0) {
+ str += sizeof("stack=") - 1;
+ ret = set_policy_rlimit(RLIMIT_STACK, str);
+ }
+#endif
+ debug_return_bool(ret);
+}
+
+/*
+ * Set resource limits as specified by the security policy (if any).
+ * This should be run as part of the session setup but after PAM,
+ * login.conf, etc.
+ */
+void
+set_policy_rlimits(void)
+{
+ unsigned int idx;
+ debug_decl(set_policy_rlimits, SUDO_DEBUG_UTIL);
+
+ for (idx = 0; idx < nitems(saved_limits); idx++) {
+ struct saved_limit *lim = &saved_limits[idx];
+ struct rlimit *rl;
+ int rc;
+
+ if (!lim->policy && (!lim->preserve || !lim->saved))
+ continue;
+
+ rl = lim->preserve ? &lim->oldlimit : &lim->policylimit;
+ if ((rc = setrlimit(lim->resource, rl)) == 0) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "setrlimit(%s, [%lld, %lld])", lim->name,
+ (long long)rl->rlim_cur, (long long)rl->rlim_max);
+ continue;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "setrlimit(%s, [%lld, %lld])", lim->name,
+ (long long)rl->rlim_cur, (long long)rl->rlim_max);
+
+ if (rl->rlim_cur > lim->oldlimit.rlim_max || rl->rlim_max > lim->oldlimit.rlim_max) {
+ /* Try setting policy rlim_cur to old rlim_max. */
+ if (rl->rlim_cur > lim->oldlimit.rlim_max)
+ rl->rlim_cur = lim->oldlimit.rlim_max;
+ if (rl->rlim_max > lim->oldlimit.rlim_max)
+ rl->rlim_max = lim->oldlimit.rlim_max;
+ if ((rc = setrlimit(lim->resource, rl)) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "setrlimit(%s, [%lld, %lld])", lim->name,
+ (long long)rl->rlim_cur, (long long)rl->rlim_max);
+ }
+ }
+ if (rc == -1)
+ sudo_warn("setrlimit(%s)", lim->name);
+ }
+
+ debug_return;
+}
+
+size_t
+serialize_rlimits(char **info, size_t info_max)
+{
+ char *str;
+ size_t idx, nstored = 0;
+ debug_decl(serialize_rlimits, SUDO_DEBUG_UTIL);
+
+ for (idx = 0; idx < nitems(saved_limits); idx++) {
+ const struct saved_limit *lim = &saved_limits[idx];
+ const struct rlimit *rl = &lim->oldlimit;
+ char curlim[STRLEN_MAX_UNSIGNED(unsigned long long) + 1];
+ char maxlim[STRLEN_MAX_UNSIGNED(unsigned long long) + 1];
+
+ if (!lim->saved)
+ continue;
+
+ if (nstored == info_max)
+ goto oom;
+
+ if (rl->rlim_cur == RLIM_INFINITY) {
+ strlcpy(curlim, "infinity", sizeof(curlim));
+ } else {
+ snprintf(curlim, sizeof(curlim), "%llu",
+ (unsigned long long)rl->rlim_cur);
+ }
+ if (rl->rlim_max == RLIM_INFINITY) {
+ strlcpy(maxlim, "infinity", sizeof(maxlim));
+ } else {
+ snprintf(maxlim, sizeof(maxlim), "%llu",
+ (unsigned long long)rl->rlim_max);
+ }
+ if (asprintf(&str, "%s=%s,%s", lim->name, curlim, maxlim) == -1)
+ goto oom;
+ info[nstored++] = str;
+ }
+ debug_return_size_t(nstored);
+oom:
+ while (nstored)
+ free(info[--nstored]);
+ debug_return_size_t((size_t)-1);
+}
diff --git a/src/load_plugins.c b/src/load_plugins.c
new file mode 100644
index 0000000..df08b95
--- /dev/null
+++ b/src/load_plugins.c
@@ -0,0 +1,488 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sudo.h>
+#include <sudo_plugin.h>
+#include <sudo_plugin_int.h>
+#include <sudo_dso.h>
+
+#ifdef ENABLE_SUDO_PLUGIN_API
+static bool
+sudo_qualify_plugin(struct plugin_info *info, char *fullpath, size_t pathsize)
+{
+ const char *plugin_dir = sudo_conf_plugin_dir_path();
+ int len;
+ debug_decl(sudo_stat_plugin, SUDO_DEBUG_PLUGIN);
+
+ if (info->path[0] == '/') {
+ if (strlcpy(fullpath, info->path, pathsize) >= pathsize) {
+ errno = ENAMETOOLONG;
+ goto bad;
+ }
+ } else {
+#ifdef STATIC_SUDOERS_PLUGIN
+ /* Check static symbols. */
+ if (strcmp(info->path, _PATH_SUDOERS_PLUGIN) == 0) {
+ if (strlcpy(fullpath, info->path, pathsize) >= pathsize) {
+ errno = ENAMETOOLONG;
+ goto bad;
+ }
+ /* Plugin is static, do not fully-qualify. */
+ debug_return_bool(true);
+ }
+#endif /* STATIC_SUDOERS_PLUGIN */
+
+ if (plugin_dir == NULL) {
+ errno = ENOENT;
+ goto bad;
+ }
+ len = snprintf(fullpath, pathsize, "%s%s", plugin_dir, info->path);
+ if (len < 0 || (size_t)len >= pathsize) {
+ errno = ENAMETOOLONG;
+ goto bad;
+ }
+ }
+ debug_return_bool(true);
+bad:
+ sudo_warnx(U_("error in %s, line %d while loading plugin \"%s\""),
+ _PATH_SUDO_CONF, info->lineno, info->symbol_name);
+ if (info->path[0] != '/' && plugin_dir != NULL)
+ sudo_warn("%s%s", plugin_dir, info->path);
+ else
+ sudo_warn("%s", info->path);
+ debug_return_bool(false);
+}
+#else
+static bool
+sudo_qualify_plugin(struct plugin_info *info, char *fullpath, size_t pathsize)
+{
+ debug_decl(sudo_qualify_plugin, SUDO_DEBUG_PLUGIN);
+ (void)strlcpy(fullpath, info->path, pathsize);
+ debug_return_bool(true);
+}
+#endif /* ENABLE_SUDO_PLUGIN_API */
+
+static bool
+fill_container(struct plugin_container *container, void *handle,
+ const char *path, struct generic_plugin *plugin, struct plugin_info *info)
+{
+ debug_decl(fill_container, SUDO_DEBUG_PLUGIN);
+
+ if ((container->path = strdup(path)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ container->handle = handle;
+ container->name = info->symbol_name;
+ container->options = info->options;
+ container->debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
+ container->u.generic = plugin;
+ container->debug_files = sudo_conf_debug_files(path);
+
+ /* Zero out info strings that the container now owns. */
+ info->symbol_name = NULL;
+ info->options = NULL;
+
+ debug_return_bool(true);
+}
+
+static struct plugin_container *
+new_container(void *handle, const char *path, struct generic_plugin *plugin,
+ struct plugin_info *info)
+{
+ struct plugin_container *container;
+ debug_decl(new_container, SUDO_DEBUG_PLUGIN);
+
+ if ((container = calloc(1, sizeof(*container))) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto bad;
+ }
+ if (!fill_container(container, handle, path, plugin, info))
+ goto bad;
+
+ debug_return_ptr(container);
+bad:
+ free(container);
+ debug_return_ptr(NULL);
+}
+
+static bool
+plugin_exists(struct plugin_container_list *plugins, const char *symbol_name)
+{
+ struct plugin_container *container;
+ debug_decl(plugin_exists, SUDO_DEBUG_PLUGIN);
+
+ TAILQ_FOREACH(container, plugins, entries) {
+ if (strcmp(container->name, symbol_name) == 0)
+ debug_return_bool(true);
+ }
+ debug_return_bool(false);
+}
+
+typedef struct generic_plugin * (plugin_clone_func)(void);
+
+static struct generic_plugin *
+sudo_plugin_try_to_clone(void *so_handle, const char *symbol_name)
+{
+ debug_decl(sudo_plugin_try_to_clone, SUDO_DEBUG_PLUGIN);
+ struct generic_plugin *plugin = NULL;
+ plugin_clone_func *clone_func;
+ char *clone_func_name = NULL;
+
+ if (asprintf(&clone_func_name, "%s_clone", symbol_name) < 0) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto cleanup;
+ }
+
+ clone_func = (plugin_clone_func *)sudo_dso_findsym(so_handle,
+ clone_func_name);
+ if (clone_func) {
+ plugin = (*clone_func)();
+ }
+
+cleanup:
+ free(clone_func_name);
+ debug_return_ptr(plugin);
+}
+
+static bool
+sudo_insert_plugin(struct plugin_container_list *plugin_list, void *handle,
+ const char *path, struct generic_plugin *plugin, struct plugin_info *info)
+{
+ struct plugin_container *container;
+ debug_decl(sudo_insert_plugin, SUDO_DEBUG_PLUGIN);
+
+ if (plugin_exists(plugin_list, info->symbol_name)) {
+ plugin = sudo_plugin_try_to_clone(handle, info->symbol_name);
+ if (plugin == NULL) {
+ sudo_warnx(U_("ignoring duplicate plugin \"%s\" in %s, line %d"),
+ info->symbol_name, _PATH_SUDO_CONF, info->lineno);
+ sudo_dso_unload(handle);
+ goto done;
+ }
+ }
+
+ if ((container = new_container(handle, path, plugin, info)) == NULL)
+ debug_return_bool(false);
+ TAILQ_INSERT_TAIL(plugin_list, container, entries);
+
+done:
+ debug_return_bool(true);
+}
+
+/*
+ * Load the plugin specified by "info".
+ */
+static bool
+sudo_load_plugin(struct plugin_info *info, bool quiet)
+{
+ struct generic_plugin *plugin;
+ char path[PATH_MAX];
+ void *handle = NULL;
+ bool ret = false;
+ debug_decl(sudo_load_plugin, SUDO_DEBUG_PLUGIN);
+
+ /* Fill in path from info and plugin dir. */
+ if (!sudo_qualify_plugin(info, path, sizeof(path)))
+ goto done;
+
+ /* Open plugin and map in symbol */
+ handle = sudo_dso_load(path, SUDO_DSO_LAZY|SUDO_DSO_GLOBAL);
+ if (!handle) {
+ if (!quiet) {
+ const char *errstr = sudo_dso_strerror();
+ sudo_warnx(U_("error in %s, line %d while loading plugin \"%s\""),
+ _PATH_SUDO_CONF, info->lineno, info->symbol_name);
+ sudo_warnx(U_("unable to load %s: %s"), path,
+ errstr ? errstr : "unknown error");
+ }
+ goto done;
+ }
+ plugin = sudo_dso_findsym(handle, info->symbol_name);
+ if (!plugin) {
+ if (!quiet) {
+ sudo_warnx(U_("error in %s, line %d while loading plugin \"%s\""),
+ _PATH_SUDO_CONF, info->lineno, info->symbol_name);
+ sudo_warnx(U_("unable to find symbol \"%s\" in %s"),
+ info->symbol_name, path);
+ }
+ goto done;
+ }
+
+ if (SUDO_API_VERSION_GET_MAJOR(plugin->version) != SUDO_API_VERSION_MAJOR) {
+ if (!quiet) {
+ sudo_warnx(U_("error in %s, line %d while loading plugin \"%s\""),
+ _PATH_SUDO_CONF, info->lineno, info->symbol_name);
+ sudo_warnx(U_("incompatible plugin major version %d (expected %d) found in %s"),
+ SUDO_API_VERSION_GET_MAJOR(plugin->version),
+ SUDO_API_VERSION_MAJOR, path);
+ }
+ goto done;
+ }
+
+ switch (plugin->type) {
+ case SUDO_POLICY_PLUGIN:
+ if (policy_plugin.handle != NULL) {
+ /* Ignore duplicate entries. */
+ if (strcmp(policy_plugin.name, info->symbol_name) == 0) {
+ if (!quiet) {
+ sudo_warnx(U_("ignoring duplicate plugin \"%s\" in %s, line %d"),
+ info->symbol_name, _PATH_SUDO_CONF, info->lineno);
+ }
+ } else {
+ if (!quiet) {
+ sudo_warnx(U_("ignoring policy plugin \"%s\" in %s, line %d"),
+ info->symbol_name, _PATH_SUDO_CONF, info->lineno);
+ sudo_warnx("%s",
+ U_("only a single policy plugin may be specified"));
+ }
+ goto done;
+ }
+ ret = true;
+ goto done;
+ }
+ if (!fill_container(&policy_plugin, handle, path, plugin, info))
+ goto done;
+ break;
+ case SUDO_IO_PLUGIN:
+ if (!sudo_insert_plugin(&io_plugins, handle, path, plugin, info))
+ goto done;
+ break;
+ case SUDO_AUDIT_PLUGIN:
+ if (!sudo_insert_plugin(&audit_plugins, handle, path, plugin, info))
+ goto done;
+ break;
+ case SUDO_APPROVAL_PLUGIN:
+ if (!sudo_insert_plugin(&approval_plugins, handle, path, plugin, info))
+ goto done;
+ break;
+ default:
+ if (!quiet) {
+ sudo_warnx(U_("error in %s, line %d while loading plugin \"%s\""),
+ _PATH_SUDO_CONF, info->lineno, info->symbol_name);
+ sudo_warnx(U_("unknown plugin type %d found in %s"), plugin->type, path);
+ }
+ goto done;
+ }
+
+ /* Handle is either in use or has been closed. */
+ handle = NULL;
+
+ ret = true;
+
+done:
+ if (handle != NULL)
+ sudo_dso_unload(handle);
+ debug_return_bool(ret);
+}
+
+static void
+free_plugin_info(struct plugin_info *info)
+{
+ free(info->path);
+ free(info->symbol_name);
+ if (info->options != NULL) {
+ int i = 0;
+ while (info->options[i] != NULL)
+ free(info->options[i++]);
+ free(info->options);
+ }
+ free(info);
+}
+
+static void
+sudo_register_hooks(void)
+{
+ struct plugin_container *container;
+ debug_decl(sudo_register_hooks, SUDO_DEBUG_PLUGIN);
+
+ if (policy_plugin.u.policy->version >= SUDO_API_MKVERSION(1, 2)) {
+ if (policy_plugin.u.policy->register_hooks != NULL) {
+ sudo_debug_set_active_instance(policy_plugin.debug_instance);
+ policy_plugin.u.policy->register_hooks(SUDO_HOOK_VERSION,
+ register_hook);
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ }
+ }
+
+ TAILQ_FOREACH(container, &io_plugins, entries) {
+ if (container->u.io->version >= SUDO_API_MKVERSION(1, 2)) {
+ if (container->u.io->register_hooks != NULL) {
+ sudo_debug_set_active_instance(container->debug_instance);
+ container->u.io->register_hooks(SUDO_HOOK_VERSION,
+ register_hook);
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ }
+ }
+ }
+
+ TAILQ_FOREACH(container, &audit_plugins, entries) {
+ if (container->u.audit->register_hooks != NULL) {
+ sudo_debug_set_active_instance(container->debug_instance);
+ container->u.audit->register_hooks(SUDO_HOOK_VERSION,
+ register_hook);
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ }
+ }
+
+ debug_return;
+}
+
+static void
+sudo_init_event_alloc(void)
+{
+ struct plugin_container *container;
+ debug_decl(sudo_init_event_alloc, SUDO_DEBUG_PLUGIN);
+
+ if (policy_plugin.u.policy->version >= SUDO_API_MKVERSION(1, 15))
+ policy_plugin.u.policy->event_alloc = sudo_plugin_event_alloc;
+
+ TAILQ_FOREACH(container, &io_plugins, entries) {
+ if (container->u.io->version >= SUDO_API_MKVERSION(1, 15))
+ container->u.io->event_alloc = sudo_plugin_event_alloc;
+ }
+ TAILQ_FOREACH(container, &audit_plugins, entries) {
+ if (container->u.audit->version >= SUDO_API_MKVERSION(1, 17))
+ container->u.audit->event_alloc = sudo_plugin_event_alloc;
+ }
+
+ debug_return;
+}
+
+/*
+ * Load the specified symbol from the sudoers plugin.
+ * Used to provide a default plugin when none are specified in sudo.conf.
+ */
+static bool
+sudo_load_sudoers_plugin(const char *symbol_name, bool optional)
+{
+ struct plugin_info *info;
+ bool ret = false;
+ debug_decl(sudo_load_sudoers_plugin, SUDO_DEBUG_PLUGIN);
+
+ /* Default policy plugin */
+ info = calloc(1, sizeof(*info));
+ if (info == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ info->symbol_name = strdup(symbol_name);
+ info->path = strdup(_PATH_SUDOERS_PLUGIN);
+ if (info->symbol_name == NULL || info->path == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ free_plugin_info(info);
+ goto done;
+ }
+ /* info->options = NULL; */
+ ret = sudo_load_plugin(info, optional);
+ free_plugin_info(info);
+
+done:
+ debug_return_bool(ret);
+}
+
+/*
+ * Load the plugins listed in sudo.conf.
+ */
+bool
+sudo_load_plugins(void)
+{
+ struct plugin_info_list *plugins;
+ struct plugin_info *info, *next;
+ bool ret = false;
+ debug_decl(sudo_load_plugins, SUDO_DEBUG_PLUGIN);
+
+ /* Walk the plugin list from sudo.conf, if any and free it. */
+ plugins = sudo_conf_plugins();
+ TAILQ_FOREACH_SAFE(info, plugins, entries, next) {
+ ret = sudo_load_plugin(info, false);
+ if (!ret)
+ goto done;
+ free_plugin_info(info);
+ }
+ TAILQ_INIT(plugins);
+
+ /*
+ * If no policy plugin, fall back to the default (sudoers).
+ * If there is also no I/O log plugin, use sudoers for that too.
+ */
+ if (policy_plugin.handle == NULL) {
+ /* Default policy plugin */
+ ret = sudo_load_sudoers_plugin("sudoers_policy", false);
+ if (!ret)
+ goto done;
+
+ /* Default audit plugin, optional (sudoers < 1.9.1 lack this) */
+ (void)sudo_load_sudoers_plugin("sudoers_audit", true);
+
+ /* Default I/O plugin */
+ if (TAILQ_EMPTY(&io_plugins)) {
+ ret = sudo_load_sudoers_plugin("sudoers_io", false);
+ if (!ret)
+ goto done;
+ }
+ } else if (strcmp(policy_plugin.name, "sudoers_policy") == 0) {
+ /*
+ * If policy plugin is sudoers_policy but there is no sudoers_audit
+ * loaded, load it too, if possible.
+ */
+ if (!plugin_exists(&audit_plugins, "sudoers_audit")) {
+ if (sudo_load_sudoers_plugin("sudoers_audit", true)) {
+ /*
+ * Move the plugin options from sudoers_policy to sudoers_audit
+ * since the audit module is now what actually opens sudoers.
+ */
+ if (policy_plugin.options != NULL) {
+ TAILQ_LAST(&audit_plugins, plugin_container_list)->options =
+ policy_plugin.options;
+ policy_plugin.options = NULL;
+ }
+ }
+ }
+ }
+
+ /* TODO: check all plugins for open function too */
+ if (policy_plugin.u.policy->check_policy == NULL) {
+ sudo_warnx(U_("policy plugin %s does not include a check_policy method"),
+ policy_plugin.name);
+ ret = false;
+ goto done;
+ }
+
+ /* Set event_alloc() in plugins. */
+ sudo_init_event_alloc();
+
+ /* Install hooks (XXX - later, after open). */
+ sudo_register_hooks();
+
+done:
+ debug_return_bool(ret);
+}
diff --git a/src/net_ifs.c b/src/net_ifs.c
new file mode 100644
index 0000000..678730f
--- /dev/null
+++ b/src/net_ifs.c
@@ -0,0 +1,876 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2007-2015, 2018-2021
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+/*
+ * Suppress a warning w/ gcc on Digital UN*X.
+ * The system headers should really do this....
+ */
+#if defined(__osf__) && !defined(__cplusplus)
+struct mbuf;
+struct rtentry;
+#endif
+
+/* Avoid a compilation problem with gcc and machine/sys/getppdp.h */
+#define _MACHINE_SYS_GETPPDP_INCLUDED
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#if defined(HAVE_SYS_SOCKIO_H) && !defined(SIOCGIFCONF)
+# include <sys/sockio.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#ifdef NEED_RESOLV_H
+# include <arpa/nameser.h>
+# include <resolv.h>
+#endif /* NEED_RESOLV_H */
+#include <net/if.h>
+#ifdef HAVE_GETIFADDRS
+# include <ifaddrs.h>
+#endif
+
+#define NEED_INET_NTOP /* to expose sudo_inet_ntop in sudo_compat.h */
+
+#define DEFAULT_TEXT_DOMAIN "sudo"
+
+#include "sudo.h"
+
+/* Minix apparently lacks IFF_LOOPBACK */
+#ifndef IFF_LOOPBACK
+# define IFF_LOOPBACK 0
+#endif
+
+#ifndef INET6_ADDRSTRLEN
+# define INET6_ADDRSTRLEN 46
+#endif
+
+#ifndef INADDR_NONE
+# define INADDR_NONE 0xffffffffU
+#endif
+
+#if defined(STUB_LOAD_INTERFACES) || \
+ !(defined(HAVE_GETIFADDRS) || defined(SIOCGIFCONF) || defined(SIOCGLIFCONF))
+
+/*
+ * Stub function for those without SIOCGIFCONF or getifaddrs()
+ */
+int
+get_net_ifs(char **addrinfo_out)
+{
+ debug_decl(get_net_ifs, SUDO_DEBUG_NETIF);
+ debug_return_int(0);
+}
+
+#elif defined(HAVE_GETIFADDRS)
+
+/*
+ * Fill in the interfaces string with the machine's ip addresses and netmasks
+ * and return the number of interfaces found. Returns -1 on error.
+ */
+int
+get_net_ifs(char **addrinfo_out)
+{
+ struct ifaddrs *ifa, *ifaddrs;
+ struct sockaddr_in *sin4;
+# ifdef HAVE_STRUCT_IN6_ADDR
+ struct sockaddr_in6 *sin6;
+# endif
+ char addrstr[INET6_ADDRSTRLEN], maskstr[INET6_ADDRSTRLEN];
+ char *addrinfo = NULL;
+ int len, num_interfaces = 0;
+ size_t ailen;
+ char *cp;
+ debug_decl(get_net_ifs, SUDO_DEBUG_NETIF);
+
+ if (!sudo_conf_probe_interfaces())
+ debug_return_int(0);
+
+ if (getifaddrs(&ifaddrs) == -1)
+ debug_return_int(-1);
+
+ /* Allocate space for the interfaces info string. */
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ /* Skip interfaces marked "down" and "loopback". */
+ if (ifa->ifa_addr == NULL || ifa->ifa_netmask == NULL ||
+ !ISSET(ifa->ifa_flags, IFF_UP) || ISSET(ifa->ifa_flags, IFF_LOOPBACK))
+ continue;
+
+ switch (ifa->ifa_addr->sa_family) {
+ case AF_INET:
+# ifdef HAVE_STRUCT_IN6_ADDR
+ case AF_INET6:
+# endif
+ num_interfaces++;
+ break;
+ }
+ }
+ if (num_interfaces == 0)
+ goto done;
+ ailen = (size_t)num_interfaces * 2 * INET6_ADDRSTRLEN;
+ if ((cp = malloc(ailen)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ goto bad;
+ }
+ addrinfo = cp;
+
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ /* Skip interfaces marked "down" and "loopback". */
+ if (ifa->ifa_addr == NULL || ifa->ifa_netmask == NULL ||
+ !ISSET(ifa->ifa_flags, IFF_UP) || ISSET(ifa->ifa_flags, IFF_LOOPBACK))
+ continue;
+
+ switch (ifa->ifa_addr->sa_family) {
+ case AF_INET:
+ sin4 = (struct sockaddr_in *)ifa->ifa_addr;
+ if (sin4->sin_addr.s_addr == INADDR_ANY || sin4->sin_addr.s_addr == INADDR_NONE) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring unspecified AF_INET addr for %s", ifa->ifa_name);
+ continue;
+ }
+ if (inet_ntop(AF_INET, &sin4->sin_addr, addrstr, sizeof(addrstr)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring bad AF_INET addr for %s", ifa->ifa_name);
+ continue;
+ }
+ sin4 = (struct sockaddr_in *)ifa->ifa_netmask;
+ if (inet_ntop(AF_INET, &sin4->sin_addr, maskstr, sizeof(maskstr)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring bad AF_INET mask for %s", ifa->ifa_name);
+ continue;
+ }
+ break;
+# ifdef HAVE_STRUCT_IN6_ADDR
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring unspecified AF_INET6 addr for %s", ifa->ifa_name);
+ continue;
+ }
+ if (inet_ntop(AF_INET6, &sin6->sin6_addr, addrstr, sizeof(addrstr)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring bad AF_INET6 addr for %s", ifa->ifa_name);
+ continue;
+ }
+ sin6 = (struct sockaddr_in6 *)ifa->ifa_netmask;
+ if (inet_ntop(AF_INET6, &sin6->sin6_addr, maskstr, sizeof(maskstr)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring bad AF_INET6 mask for %s", ifa->ifa_name);
+ continue;
+ }
+ break;
+# endif /* HAVE_STRUCT_IN6_ADDR */
+ default:
+ continue;
+ }
+
+ /* Store the IP addr/netmask pairs. */
+ len = snprintf(cp, ailen, "%s%s/%s",
+ cp == addrinfo ? "" : " ", addrstr, maskstr);
+ if (len < 0 || (size_t)len >= ailen) {
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ goto bad;
+ }
+ cp += len;
+ ailen -= (size_t)len;
+ }
+ *addrinfo_out = addrinfo;
+ goto done;
+
+bad:
+ free(addrinfo);
+ num_interfaces = -1;
+done:
+# ifdef HAVE_FREEIFADDRS
+ freeifaddrs(ifaddrs);
+# else
+ free(ifaddrs);
+# endif
+ debug_return_int(num_interfaces);
+}
+
+#elif defined(SIOCGLIFCONF)
+
+# if defined(__hpux)
+
+/*
+ * Fill in the interfaces string with the machine's ip addresses and netmasks
+ * and return the number of interfaces found. Returns -1 on error.
+ * HP-UX has incompatible SIOCGLIFNUM and SIOCGLIFCONF ioctls.
+ */
+int
+get_net_ifs(char **addrinfo_out)
+{
+ struct if_laddrconf laddrconf;
+ struct ifconf ifconf;
+ char addrstr[INET6_ADDRSTRLEN], maskstr[INET6_ADDRSTRLEN];
+ char *addrinfo = NULL;
+ int i, n, sock4, sock6 = -1;
+ int num_interfaces = 0;
+ size_t ailen;
+ char *cp;
+ debug_decl(get_net_ifs, SUDO_DEBUG_NETIF);
+
+ if (!sudo_conf_probe_interfaces())
+ debug_return_int(0);
+
+ memset(&ifconf, 0, sizeof(ifconf));
+ memset(&laddrconf, 0, sizeof(laddrconf));
+
+ /* Allocate and fill in the IPv4 interface list. */
+ sock4 = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock4 != -1 && ioctl(sock4, SIOCGIFNUM, &n) != -1) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "SIOCGIFNUM reports %d interfaces", n);
+ n += 4; /* in case new interfaces come up */
+
+ ifconf.ifc_len = n * sizeof(struct ifreq);
+ ifconf.ifc_buf = malloc(ifconf.ifc_len);
+ if (ifconf.ifc_buf == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ goto bad;
+ }
+
+ if (ioctl(sock4, SIOCGIFCONF, &ifconf) < 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to get interface list (SIOCGIFCONF)");
+ goto bad;
+ }
+ }
+
+ /* Allocate and fill in the IPv6 interface list. */
+ sock6 = socket(AF_INET6, SOCK_DGRAM, 0);
+ if (sock6 != -1 && ioctl(sock6, SIOCGLIFNUM, &n) != -1) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "SIOCGLIFNUM reports %d interfaces", n);
+ n += 4; /* in case new interfaces come up */
+
+ laddrconf.iflc_len = n * sizeof(struct if_laddrreq);
+ laddrconf.iflc_buf = malloc(laddrconf.iflc_len);
+ if (laddrconf.iflc_buf == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ goto bad;
+ }
+
+ if (ioctl(sock4, SIOCGLIFCONF, &laddrconf) < 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to get interface list (SIOCGLIFCONF)");
+ goto bad;
+ }
+ }
+
+ /* Allocate space for the maximum number of interfaces that could exist. */
+ n = ifconf.ifc_len / sizeof(struct ifconf) +
+ laddrconf.iflc_len / sizeof(struct if_laddrreq);
+ if (n == 0)
+ goto done;
+ ailen = n * 2 * INET6_ADDRSTRLEN;
+ if ((cp = malloc(ailen)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ goto bad;
+ }
+ addrinfo = cp;
+
+ /*
+ * For each interface, store the ip address and netmask.
+ * Keep a copy of the address family, else it will be overwritten.
+ */
+ for (i = 0; i < ifconf.ifc_len; ) {
+ struct ifreq *ifr = (struct ifreq *)&ifconf.ifc_buf[i];
+ struct sockaddr_in *sin4;
+
+ /* Set i to the subscript of the next interface (no sa_len). */
+ i += sizeof(struct ifreq);
+
+ /* IPv4 only. */
+ if (ifr->ifr_addr.sa_family != AF_INET) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unexpected address family %d for %s",
+ ifr->ifr_addr.sa_family, ifr->ifr_name);
+ continue;
+ }
+
+ /* Store the address. */
+ sin4 = (struct sockaddr_in *)&ifr->ifr_addr;
+ if (sin4->sin_addr.s_addr == INADDR_ANY || sin4->sin_addr.s_addr == INADDR_NONE) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring unspecified AF_INET addr for %s", ifr->ifr_name);
+ continue;
+ }
+ if (inet_ntop(AF_INET, &sin4->sin_addr, addrstr, sizeof(addrstr)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring bad AF_INET addr for %s", ifr->ifr_name);
+ continue;
+ }
+
+ /* Skip interfaces marked "down" and "loopback". */
+ if (ioctl(sock4, SIOCGIFFLAGS, ifr) < 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "SIOCGLIFFLAGS for %s", ifr->ifr_name);
+ continue;
+ }
+ if (!ISSET(ifr->ifr_flags, IFF_UP) ||
+ ISSET(ifr->ifr_flags, IFF_LOOPBACK))
+ continue;
+
+ /* Fetch and store the netmask. */
+ if (ioctl(sock4, SIOCGIFNETMASK, ifr) < 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "SIOCGLIFNETMASK for %s", ifr->ifr_name);
+ continue;
+ }
+
+ /* Convert the mask to string form. */
+ sin4 = (struct sockaddr_in *)&ifr->ifr_addr;
+ if (inet_ntop(AF_INET, &sin4->sin_addr, maskstr, sizeof(maskstr)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring bad AF_INET mask for %s", ifr->ifr_name);
+ continue;
+ }
+
+ n = snprintf(cp, ailen, "%s%s/%s",
+ cp == addrinfo ? "" : " ", addrstr, maskstr);
+ if (n < 0 || (size_t)n >= ailen) {
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ goto bad;
+ }
+ cp += n;
+ ailen -= n;
+
+ num_interfaces++;
+ }
+ for (i = 0; i < laddrconf.iflc_len; ) {
+ struct if_laddrreq *lreq = (struct if_laddrreq *)&laddrconf.iflc_buf[i];
+ struct sockaddr_in6 *sin6;
+
+ /* Set i to the subscript of the next interface (no sa_len). */
+ i += sizeof(struct if_laddrreq);
+
+ /* IPv6 only. */
+ if (lreq->iflr_addr.sa_family != AF_INET6) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unexpected address family %d for %s",
+ lreq->iflr_addr.sa_family, lreq->iflr_name);
+ continue;
+ }
+
+ sin6 = (struct sockaddr_in6 *)&lreq->iflr_addr;
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring unspecified AF_INET6 addr for %s", lreq->iflr_name);
+ continue;
+ }
+ if (inet_ntop(AF_INET6, &sin6->sin6_addr, addrstr, sizeof(addrstr)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring bad AF_INET6 addr for %s", lreq->iflr_name);
+ continue;
+ }
+
+ /* Skip interfaces marked "down" and "loopback". */
+ if (ioctl(sock6, SIOCGLIFFLAGS, lreq) < 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "SIOCGLIFFLAGS for %s", lreq->iflr_name);
+ continue;
+ }
+ if (!ISSET(lreq->iflr_flags, IFF_UP) ||
+ ISSET(lreq->iflr_flags, IFF_LOOPBACK))
+ continue;
+
+ /* Fetch and store the netmask. */
+ if (ioctl(sock6, SIOCGLIFNETMASK, lreq) < 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "SIOCGLIFNETMASK for %s", lreq->iflr_name);
+ continue;
+ }
+ sin6 = (struct sockaddr_in6 *)&lreq->iflr_addr;
+ if (inet_ntop(AF_INET6, &sin6->sin6_addr, maskstr, sizeof(maskstr)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring bad AF_INET6 mask for %s", lreq->iflr_name);
+ continue;
+ }
+
+ n = snprintf(cp, ailen, "%s%s/%s",
+ cp == addrinfo ? "" : " ", addrstr, maskstr);
+ if (n < 0 || (size_t)n >= ailen) {
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ goto bad;
+ }
+ cp += n;
+ ailen -= n;
+
+ num_interfaces++;
+ }
+ *addrinfo_out = addrinfo;
+ goto done;
+
+bad:
+ free(addrinfo);
+ num_interfaces = -1;
+done:
+ free(ifconf.ifc_buf);
+ free(laddrconf.iflc_buf);
+ if (sock4 != -1)
+ close(sock4);
+ if (sock6 != -1)
+ close(sock6);
+
+ debug_return_int(num_interfaces);
+}
+
+# else
+
+/*
+ * Fill in the interfaces string with the machine's ip addresses and netmasks
+ * and return the number of interfaces found. Returns -1 on error.
+ * SIOCGLIFCONF version (IPv6 compatible).
+ */
+int
+get_net_ifs(char **addrinfo_out)
+{
+ struct lifconf lifconf;
+ struct lifnum lifn;
+ struct sockaddr_in *sin4;
+ struct sockaddr_in6 *sin6;
+ char addrstr[INET6_ADDRSTRLEN], maskstr[INET6_ADDRSTRLEN];
+ char *addrinfo = NULL;
+ int i, n, sock, sock4, sock6 = -1;
+ int num_interfaces = 0;
+ size_t ailen;
+ char *cp;
+ debug_decl(get_net_ifs, SUDO_DEBUG_NETIF);
+
+ if (!sudo_conf_probe_interfaces())
+ debug_return_int(0);
+
+ /* We need both INET4 and INET6 sockets to get flags and netmask. */
+ sock4 = socket(AF_INET, SOCK_DGRAM, 0);
+ sock6 = socket(AF_INET6, SOCK_DGRAM, 0);
+ if (sock4 == -1 && sock6 == -1)
+ debug_return_int(-1);
+
+ /* Use INET6 socket with SIOCGLIFCONF if possible (may not matter). */
+ sock = sock6 != -1 ? sock6 : sock4;
+
+ /* Get number of interfaces if possible. */
+ memset(&lifn, 0, sizeof(lifn));
+ if (ioctl(sock, SIOCGLIFNUM, &lifn) != -1) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "SIOCGLIFNUM reports %d interfaces", lifn.lifn_count);
+ lifn.lifn_count += 4; /* in case new interfaces come up */
+ } else {
+ lifn.lifn_count = 512;
+ }
+
+ /* Allocate and fill in the interface buffer. */
+ memset(&lifconf, 0, sizeof(lifconf));
+ lifconf.lifc_len = lifn.lifn_count * sizeof(struct lifreq);
+ lifconf.lifc_buf = malloc(lifconf.lifc_len);
+ if (lifconf.lifc_buf == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ goto bad;
+ }
+ if (ioctl(sock, SIOCGLIFCONF, &lifconf) < 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to get interface list (SIOCGLIFCONF)");
+ goto bad;
+ }
+
+ /* Allocate space for the maximum number of interfaces that could exist. */
+ n = lifconf.lifc_len / sizeof(struct lifreq);
+ if (n == 0)
+ goto done;
+ ailen = n * 2 * INET6_ADDRSTRLEN;
+ if ((cp = malloc(ailen)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ goto bad;
+ }
+ addrinfo = cp;
+
+ /*
+ * For each interface, store the ip address and netmask.
+ * Keep a copy of the address family, else it will be overwritten.
+ */
+ for (i = 0; i < lifconf.lifc_len; ) {
+ struct lifreq *lifr = (struct lifreq *)&lifconf.lifc_buf[i];
+ const int family = lifr->lifr_addr.ss_family;
+
+ /* Set i to the subscript of the next interface (no sa_len). */
+ i += sizeof(struct lifreq);
+
+ /* Store the address. */
+ switch (family) {
+ case AF_INET:
+ sin4 = (struct sockaddr_in *)&lifr->lifr_addr;
+ if (sin4->sin_addr.s_addr == INADDR_ANY || sin4->sin_addr.s_addr == INADDR_NONE) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring unspecified AF_INET addr for %s", lifr->lifr_name);
+ continue;
+ }
+ if (inet_ntop(AF_INET, &sin4->sin_addr, addrstr, sizeof(addrstr)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring bad AF_INET addr for %s", lifr->lifr_name);
+ continue;
+ }
+ sock = sock4;
+ break;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)&lifr->lifr_addr;
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring unspecified AF_INET6 addr for %s", lifr->lifr_name);
+ continue;
+ }
+ if (inet_ntop(AF_INET6, &sin6->sin6_addr, addrstr, sizeof(addrstr)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring bad AF_INET6 addr for %s", lifr->lifr_name);
+ continue;
+ }
+ sock = sock6;
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "ignoring address with family %d for %s",
+ family, lifr->lifr_name);
+ continue;
+ }
+
+ /* Skip interfaces marked "down" and "loopback". */
+ if (ioctl(sock, SIOCGLIFFLAGS, lifr) < 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "SIOCGLIFFLAGS for %s", lifr->lifr_name);
+ continue;
+ }
+ if (!ISSET(lifr->lifr_flags, IFF_UP) ||
+ ISSET(lifr->lifr_flags, IFF_LOOPBACK))
+ continue;
+
+ /* Fetch and store the netmask. */
+ if (ioctl(sock, SIOCGLIFNETMASK, lifr) < 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "SIOCGLIFNETMASK for %s", lifr->lifr_name);
+ continue;
+ }
+ switch (family) {
+ case AF_INET:
+ sin4 = (struct sockaddr_in *)&lifr->lifr_addr;
+ if (inet_ntop(AF_INET, &sin4->sin_addr, maskstr, sizeof(maskstr)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring bad AF_INET mask for %s", lifr->lifr_name);
+ continue;
+ }
+ break;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)&lifr->lifr_addr;
+ if (inet_ntop(AF_INET6, &sin6->sin6_addr, maskstr, sizeof(maskstr)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring bad AF_INET6 mask for %s", lifr->lifr_name);
+ continue;
+ }
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unexpected address family %d for %s",
+ family, lifr->lifr_name);
+ continue;
+ }
+
+ n = snprintf(cp, ailen, "%s%s/%s",
+ cp == addrinfo ? "" : " ", addrstr, maskstr);
+ if (n < 0 || (size_t)n >= ailen) {
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ goto bad;
+ }
+ cp += n;
+ ailen -= n;
+
+ num_interfaces++;
+ }
+ *addrinfo_out = addrinfo;
+ goto done;
+
+bad:
+ free(addrinfo);
+ num_interfaces = -1;
+done:
+ free(lifconf.lifc_buf);
+ if (sock4 != -1)
+ close(sock4);
+ if (sock6 != -1)
+ close(sock6);
+
+ debug_return_int(num_interfaces);
+}
+# endif /* !__hpux */
+
+#elif defined(SIOCGIFCONF)
+
+/*
+ * Fill in the interfaces string with the machine's ip addresses and netmasks
+ * and return the number of interfaces found. Returns -1 on error.
+ * SIOCGIFCONF version.
+ */
+int
+get_net_ifs(char **addrinfo_out)
+{
+ struct ifconf ifconf;
+ struct ifreq *ifr;
+ struct sockaddr_in *sin4;
+# ifdef HAVE_STRUCT_IN6_ADDR
+ struct sockaddr_in6 *sin6;
+# endif
+ char addrstr[INET6_ADDRSTRLEN], maskstr[INET6_ADDRSTRLEN];
+ char *addrinfo = NULL;
+ int i, n, sock, sock4, sock6 = -1;
+ int num_interfaces = 0;
+ size_t ailen, buflen;
+ char *cp, *ifconf_buf = NULL;
+ debug_decl(get_net_ifs, SUDO_DEBUG_NETIF);
+
+ if (!sudo_conf_probe_interfaces())
+ debug_return_int(0);
+
+ sock4 = socket(AF_INET, SOCK_DGRAM, 0);
+# ifdef HAVE_STRUCT_IN6_ADDR
+ sock6 = socket(AF_INET6, SOCK_DGRAM, 0);
+# endif
+ if (sock4 == -1 && sock6 == -1)
+ debug_return_int(-1);
+
+ /* Use INET6 socket with SIOCGIFCONF if possible (may not matter). */
+ sock = sock6 != -1 ? sock6 : sock4;
+
+ /*
+ * Get the size of the interface buffer (if possible).
+ * We over-allocate a bit in case interfaces come up afterward.
+ */
+ i = 0;
+# if defined(SIOCGSIZIFCONF)
+ /* AIX */
+ if (ioctl(sock, SIOCGSIZIFCONF, &i) != -1) {
+ buflen = i + (sizeof(struct ifreq) * 4);
+ } else
+# elif defined(SIOCGIFANUM)
+ /* SCO OpenServer 5/6 */
+ if (ioctl(sock, SIOCGIFANUM, &i) != -1) {
+ buflen = (i + 4) * sizeof(struct ifreq);
+ } else
+# elif defined(SIOCGIFNUM)
+ /* HP-UX, Solaris, others? */
+ if (ioctl(sock, SIOCGIFNUM, &i) != -1) {
+ buflen = (i + 4) * sizeof(struct ifreq);
+ } else
+# endif
+ {
+ buflen = 256 * sizeof(struct ifreq);
+ }
+
+ /* Get interface configuration. */
+ memset(&ifconf, 0, sizeof(ifconf));
+ for (i = 0; i < 4; i++) {
+ ifconf.ifc_len = buflen;
+ ifconf.ifc_buf = malloc(buflen);
+ if (ifconf.ifc_buf == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ goto bad;
+ }
+
+ /* Note that some kernels return EINVAL if the buffer is too small */
+ if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0 && errno != EINVAL)
+ goto bad;
+
+ /* Break out of loop if we have a big enough buffer. */
+ if (ifconf.ifc_len + sizeof(struct ifreq) < buflen)
+ break;
+ buflen *= 2;
+ free(ifconf.ifc_buf);
+ }
+
+ /*
+ * Allocate space for the maximum number of interfaces that could exist.
+ * We walk the list for systems with sa_len in struct sockaddr.
+ */
+ for (i = 0, n = 0; i < ifconf.ifc_len; n++) {
+ /* Set i to the subscript of the next interface. */
+ i += sizeof(struct ifreq);
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ ifr = (struct ifreq *)&ifconf.ifc_buf[i];
+ if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_addr))
+ i += ifr->ifr_addr.sa_len - sizeof(struct sockaddr);
+#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+ }
+ if (n == 0)
+ goto done;
+ ailen = n * 2 * INET6_ADDRSTRLEN;
+ if ((cp = malloc(ailen)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to allocate memory");
+ goto bad;
+ }
+ addrinfo = cp;
+
+ /*
+ * For each interface, store the ip address and netmask.
+ * Keep a copy of the address family, else it will be overwritten.
+ */
+ for (i = 0; i < ifconf.ifc_len; ) {
+ int family;
+
+ ifr = (struct ifreq *)&ifconf.ifc_buf[i];
+ family = ifr->ifr_addr.sa_family;
+
+ /* Set i to the subscript of the next interface. */
+ i += sizeof(struct ifreq);
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_addr))
+ i += ifr->ifr_addr.sa_len - sizeof(struct sockaddr);
+#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+
+ /* Store the address. */
+ switch (family) {
+ case AF_INET:
+ sin4 = (struct sockaddr_in *)&ifr->ifr_addr;
+ if (sin4->sin_addr.s_addr == INADDR_ANY || sin4->sin_addr.s_addr == INADDR_NONE) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring unspecified AF_INET addr for %s", ifr->ifr_name);
+ continue;
+ }
+ if (inet_ntop(AF_INET, &sin4->sin_addr, addrstr, sizeof(addrstr)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring bad AF_INET addr for %s", ifr->ifr_name);
+ continue;
+ }
+ sock = sock4;
+ break;
+# ifdef HAVE_STRUCT_IN6_ADDR
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)&ifr->ifr_addr;
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring unspecified AF_INET6 addr for %s", ifr->ifr_name);
+ continue;
+ }
+ if (inet_ntop(AF_INET6, &sin6->sin6_addr, addrstr, sizeof(addrstr)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring bad AF_INET6 addr for %s", ifr->ifr_name);
+ continue;
+ }
+ sock = sock6;
+ break;
+# endif /* HAVE_STRUCT_IN6_ADDR */
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unexpected address family %d for %s",
+ family, ifr->ifr_name);
+ continue;
+ }
+
+ /* Skip interfaces marked "down" and "loopback". */
+ if (ioctl(sock, SIOCGIFFLAGS, ifr) < 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "SIOCGLIFFLAGS for %s", ifr->ifr_name);
+ continue;
+ }
+ if (!ISSET(ifr->ifr_flags, IFF_UP) ||
+ ISSET(ifr->ifr_flags, IFF_LOOPBACK))
+ continue;
+
+ /* Fetch and store the netmask. */
+ if (ioctl(sock, SIOCGIFNETMASK, ifr) < 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "SIOCGLIFNETMASK for %s", ifr->ifr_name);
+ continue;
+ }
+
+ /* Convert the mask to string form. */
+ switch (family) {
+ case AF_INET:
+ sin4 = (struct sockaddr_in *)&ifr->ifr_addr;
+ if (inet_ntop(AF_INET, &sin4->sin_addr, maskstr, sizeof(maskstr)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring bad AF_INET mask for %s", ifr->ifr_name);
+ continue;
+ }
+ break;
+# ifdef HAVE_STRUCT_IN6_ADDR
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)&ifr->ifr_addr;
+ if (inet_ntop(AF_INET6, &sin6->sin6_addr, maskstr, sizeof(maskstr)) == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "ignoring bad AF_INET6 mask for %s", ifr->ifr_name);
+ continue;
+ }
+ break;
+# endif /* HAVE_STRUCT_IN6_ADDR */
+ default:
+ continue;
+ }
+
+ n = snprintf(cp, ailen, "%s%s/%s",
+ cp == addrinfo ? "" : " ", addrstr, maskstr);
+ if (n < 0 || (size_t)n >= ailen) {
+ sudo_warnx(U_("internal error, %s overflow"), __func__);
+ goto bad;
+ }
+ cp += n;
+ ailen -= n;
+
+ num_interfaces++;
+ }
+ *addrinfo_out = addrinfo;
+ goto done;
+
+bad:
+ free(addrinfo);
+ num_interfaces = -1;
+done:
+ free(ifconf_buf);
+ if (sock4 != -1)
+ close(sock4);
+ if (sock6 != -1)
+ close(sock6);
+
+ debug_return_int(num_interfaces);
+}
+
+#endif /* SIOCGIFCONF */
diff --git a/src/openbsd.c b/src/openbsd.c
new file mode 100644
index 0000000..72d4374
--- /dev/null
+++ b/src/openbsd.c
@@ -0,0 +1,36 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2012 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sudo.h>
+
+int
+os_init(int argc, char *argv[], char *envp[])
+{
+#ifdef SUDO_DEVEL
+ extern char *malloc_options;
+ malloc_options = "S";
+#endif
+ return os_init_common(argc, argv, envp);
+}
diff --git a/src/parse_args.c b/src/parse_args.c
new file mode 100644
index 0000000..f74738f
--- /dev/null
+++ b/src/parse_args.c
@@ -0,0 +1,881 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1993-1996, 1998-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#ifdef HAVE_GETOPT_LONG
+# include <getopt.h>
+# else
+# include <compat/getopt.h>
+#endif /* HAVE_GETOPT_LONG */
+
+#include <sudo_usage.h>
+#include <sudo.h>
+#include <sudo_lbuf.h>
+
+unsigned int tgetpass_flags;
+
+/*
+ * Local functions.
+ */
+sudo_noreturn static void help(void);
+sudo_noreturn static void usage_excl(void);
+sudo_noreturn static void usage_excl_ticket(void);
+
+/*
+ * Mapping of command line options to name/value settings.
+ * Do not reorder, indexes must match ARG_ defines in sudo.h.
+ */
+static struct sudo_settings sudo_settings[] = {
+ { "bsdauth_type" },
+ { "login_class" },
+ { "preserve_environment" },
+ { "runas_group" },
+ { "set_home" },
+ { "run_shell" },
+ { "login_shell" },
+ { "ignore_ticket" },
+ { "update_ticket" },
+ { "prompt" },
+ { "selinux_role" },
+ { "selinux_type" },
+ { "runas_user" },
+ { "progname" },
+ { "implied_shell" },
+ { "preserve_groups" },
+ { "noninteractive" },
+ { "sudoedit" },
+ { "closefrom" },
+ { "network_addrs" },
+ { "max_groups" },
+ { "plugin_dir" },
+ { "remote_host" },
+ { "timeout" },
+ { "cmnd_chroot" },
+ { "cmnd_cwd" },
+ { "askpass" },
+ { "intercept_setid" },
+ { "intercept_ptrace" },
+ { "apparmor_profile" },
+ { NULL }
+};
+
+struct environment {
+ char **envp; /* pointer to the new environment */
+ size_t env_size; /* size of new_environ in char **'s */
+ size_t env_len; /* number of slots used, not counting NULL */
+};
+
+/*
+ * Default flags allowed when running a command.
+ */
+#define DEFAULT_VALID_FLAGS (MODE_BACKGROUND|MODE_PRESERVE_ENV|MODE_RESET_HOME|MODE_LOGIN_SHELL|MODE_NONINTERACTIVE|MODE_PRESERVE_GROUPS|MODE_SHELL)
+#define EDIT_VALID_FLAGS MODE_NONINTERACTIVE
+#define LIST_VALID_FLAGS (MODE_NONINTERACTIVE|MODE_LONG_LIST)
+#define VALIDATE_VALID_FLAGS MODE_NONINTERACTIVE
+
+/* Option number for the --host long option due to ambiguity of the -h flag. */
+#define OPT_HOSTNAME 256
+
+/*
+ * Available command line options, both short and long.
+ * Note that we must disable arg permutation to support setting environment
+ * variables and to better support the optional arg of the -h flag.
+ * There is a more limited set of options for sudoedit (the sudo-specific
+ * long options are listed first).
+ */
+static const char sudo_short_opts[] = "+Aa:BbC:c:D:Eeg:Hh::iKklNnPp:R:r:SsT:t:U:u:Vv";
+static const char edit_short_opts[] = "+Aa:BC:c:D:g:h::KkNnp:R:r:ST:t:u:V";
+static struct option sudo_long_opts[] = {
+ /* sudo-specific long options */
+ { "background", no_argument, NULL, 'b' },
+ { "preserve-env", optional_argument, NULL, 'E' },
+ { "edit", no_argument, NULL, 'e' },
+ { "set-home", no_argument, NULL, 'H' },
+ { "login", no_argument, NULL, 'i' },
+ { "remove-timestamp", no_argument, NULL, 'K' },
+ { "list", no_argument, NULL, 'l' },
+ { "preserve-groups", no_argument, NULL, 'P' },
+ { "shell", no_argument, NULL, 's' },
+ { "other-user", required_argument, NULL, 'U' },
+ { "validate", no_argument, NULL, 'v' },
+ /* common long options */
+ { "askpass", no_argument, NULL, 'A' },
+ { "auth-type", required_argument, NULL, 'a' },
+ { "bell", no_argument, NULL, 'B' },
+ { "close-from", required_argument, NULL, 'C' },
+ { "login-class", required_argument, NULL, 'c' },
+ { "chdir", required_argument, NULL, 'D' },
+ { "group", required_argument, NULL, 'g' },
+ { "help", no_argument, NULL, 'h' },
+ { "host", required_argument, NULL, OPT_HOSTNAME },
+ { "reset-timestamp", no_argument, NULL, 'k' },
+ { "no-update", no_argument, NULL, 'N' },
+ { "non-interactive", no_argument, NULL, 'n' },
+ { "prompt", required_argument, NULL, 'p' },
+ { "chroot", required_argument, NULL, 'R' },
+ { "role", required_argument, NULL, 'r' },
+ { "stdin", no_argument, NULL, 'S' },
+ { "command-timeout",required_argument, NULL, 'T' },
+ { "type", required_argument, NULL, 't' },
+ { "user", required_argument, NULL, 'u' },
+ { "version", no_argument, NULL, 'V' },
+ { NULL, no_argument, NULL, '\0' },
+};
+static struct option *edit_long_opts = &sudo_long_opts[11];
+
+/*
+ * Insert a key=value pair into the specified environment.
+ */
+static void
+env_insert(struct environment *e, char *pair)
+{
+ debug_decl(env_insert, SUDO_DEBUG_ARGS);
+
+ /* Make sure we have at least two slots free (one for NULL). */
+ if (e->env_len + 1 >= e->env_size) {
+ char **tmp;
+
+ if (e->env_size == 0)
+ e->env_size = 16;
+ tmp = reallocarray(e->envp, e->env_size, 2 * sizeof(char *));
+ if (tmp == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ e->envp = tmp;
+ e->env_size *= 2;
+ }
+ e->envp[e->env_len++] = pair;
+ e->envp[e->env_len] = NULL;
+
+ debug_return;
+}
+
+/*
+ * Format as var=val and insert into the specified environment.
+ */
+static void
+env_set(struct environment *e, char *var, char *val)
+{
+ char *pair;
+ debug_decl(env_set, SUDO_DEBUG_ARGS);
+
+ pair = sudo_new_key_val(var, val);
+ if (pair == NULL) {
+ sudo_fatalx(U_("%s: %s"),
+ __func__, U_("unable to allocate memory"));
+ }
+ env_insert(e, pair);
+
+ debug_return;
+}
+
+/*
+ * Parse a comma-separated list of env vars and add to the
+ * specified environment.
+ */
+static void
+parse_env_list(struct environment *e, char *list)
+{
+ char *cp, *last, *val;
+ debug_decl(parse_env_list, SUDO_DEBUG_ARGS);
+
+ for ((cp = strtok_r(list, ",", &last)); cp != NULL;
+ (cp = strtok_r(NULL, ",", &last))) {
+ if (strchr(cp, '=') != NULL) {
+ sudo_warnx(U_("invalid environment variable name: %s"), cp);
+ usage();
+ }
+ if ((val = getenv(cp)) != NULL)
+ env_set(e, cp, val);
+ }
+ debug_return;
+}
+
+/*
+ * Command line argument parsing.
+ * Sets nargc and nargv which corresponds to the argc/argv we'll use
+ * for the command to be run (if we are running one).
+ */
+unsigned int
+parse_args(int argc, char **argv, const char *shell, int *old_optind,
+ int *nargc, char ***nargv, struct sudo_settings **settingsp,
+ char ***env_addp, const char **list_userp)
+{
+ const char *progname, *short_opts = sudo_short_opts;
+ struct option *long_opts = sudo_long_opts;
+ struct environment extra_env;
+ const char *list_user = NULL;
+ unsigned int mode = 0; /* what mode is sudo to be run in? */
+ unsigned int flags = 0; /* mode flags */
+ unsigned int valid_flags = DEFAULT_VALID_FLAGS;
+ int ch, i;
+ char *cp;
+ debug_decl(parse_args, SUDO_DEBUG_ARGS);
+
+ /* Is someone trying something funny? */
+ if (argc <= 0)
+ usage();
+
+ /* The plugin API includes the program name (either sudo or sudoedit). */
+ progname = getprogname();
+ sudo_settings[ARG_PROGNAME].value = progname;
+
+ /* First, check to see if we were invoked as "sudoedit". */
+ if (strcmp(progname, "sudoedit") == 0) {
+ mode = MODE_EDIT;
+ sudo_settings[ARG_SUDOEDIT].value = "true";
+ valid_flags = EDIT_VALID_FLAGS;
+ short_opts = edit_short_opts;
+ long_opts = edit_long_opts;
+ }
+
+ /* Load local IP addresses and masks. */
+ if (get_net_ifs(&cp) > 0)
+ sudo_settings[ARG_NET_ADDRS].value = cp;
+
+ /* Set max_groups from sudo.conf. */
+ i = sudo_conf_max_groups();
+ if (i != -1) {
+ if (asprintf(&cp, "%d", i) == -1)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ sudo_settings[ARG_MAX_GROUPS].value = cp;
+ }
+
+ /* Returns true if the last option string was "-h" */
+#define got_host_flag (optind > 1 && argv[optind - 1][0] == '-' && \
+ argv[optind - 1][1] == 'h' && argv[optind - 1][2] == '\0')
+
+ /* Returns true if the last option string was "--" */
+#define got_end_of_args (optind > 1 && argv[optind - 1][0] == '-' && \
+ argv[optind - 1][1] == '-' && argv[optind - 1][2] == '\0')
+
+ /* Returns true if next option is an environment variable */
+#define is_envar (optind < argc && argv[optind][0] != '/' && \
+ argv[optind][0] != '=' && strchr(argv[optind], '=') != NULL)
+
+ /* Space for environment variables is lazy allocated. */
+ memset(&extra_env, 0, sizeof(extra_env));
+
+ for (;;) {
+ /*
+ * Some trickiness is required to allow environment variables
+ * to be interspersed with command line options.
+ */
+ if ((ch = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
+ switch (ch) {
+ case 'A':
+ SET(tgetpass_flags, TGP_ASKPASS);
+ sudo_settings[ARG_ASKPASS].value = "true";
+ break;
+#ifdef HAVE_BSD_AUTH_H
+ case 'a':
+ assert(optarg != NULL);
+ if (*optarg == '\0')
+ usage();
+ if (sudo_settings[ARG_BSDAUTH_TYPE].value != NULL)
+ usage();
+ sudo_settings[ARG_BSDAUTH_TYPE].value = optarg;
+ break;
+#endif
+ case 'b':
+ SET(flags, MODE_BACKGROUND);
+ break;
+ case 'B':
+ SET(tgetpass_flags, TGP_BELL);
+ break;
+ case 'C':
+ assert(optarg != NULL);
+ if (sudo_strtonum(optarg, 3, INT_MAX, NULL) == 0) {
+ sudo_warnx("%s",
+ U_("the argument to -C must be a number greater than or equal to 3"));
+ usage();
+ }
+ if (sudo_settings[ARG_CLOSEFROM].value != NULL)
+ usage();
+ sudo_settings[ARG_CLOSEFROM].value = optarg;
+ break;
+#ifdef HAVE_LOGIN_CAP_H
+ case 'c':
+ assert(optarg != NULL);
+ if (*optarg == '\0')
+ usage();
+ if (sudo_settings[ARG_LOGIN_CLASS].value != NULL)
+ usage();
+ sudo_settings[ARG_LOGIN_CLASS].value = optarg;
+ break;
+#endif
+ case 'D':
+ assert(optarg != NULL);
+ if (*optarg == '\0')
+ usage();
+ if (sudo_settings[ARG_CWD].value != NULL)
+ usage();
+ sudo_settings[ARG_CWD].value = optarg;
+ break;
+ case 'E':
+ /*
+ * Optional argument is a comma-separated list of
+ * environment variables to preserve.
+ * If not present, preserve everything.
+ */
+ if (optarg == NULL) {
+ sudo_settings[ARG_PRESERVE_ENVIRONMENT].value = "true";
+ SET(flags, MODE_PRESERVE_ENV);
+ } else {
+ parse_env_list(&extra_env, optarg);
+ }
+ break;
+ case 'e':
+ if (mode && mode != MODE_EDIT)
+ usage_excl();
+ mode = MODE_EDIT;
+ sudo_settings[ARG_SUDOEDIT].value = "true";
+ valid_flags = EDIT_VALID_FLAGS;
+ break;
+ case 'g':
+ assert(optarg != NULL);
+ if (*optarg == '\0')
+ usage();
+ if (sudo_settings[ARG_RUNAS_GROUP].value != NULL)
+ usage();
+ sudo_settings[ARG_RUNAS_GROUP].value = optarg;
+ break;
+ case 'H':
+ sudo_settings[ARG_SET_HOME].value = "true";
+ SET(flags, MODE_RESET_HOME);
+ break;
+ case 'h':
+ if (optarg == NULL) {
+ /*
+ * Optional args support -hhostname, not -h hostname.
+ * If we see a non-option after the -h flag, treat as
+ * remote host and bump optind to skip over it.
+ */
+ if (got_host_flag && argv[optind] != NULL &&
+ argv[optind][0] != '-' && !is_envar) {
+ if (sudo_settings[ARG_REMOTE_HOST].value != NULL)
+ usage();
+ sudo_settings[ARG_REMOTE_HOST].value = argv[optind++];
+ continue;
+ }
+ if (mode && mode != MODE_HELP) {
+ if (strcmp(progname, "sudoedit") != 0)
+ usage_excl();
+ }
+ mode = MODE_HELP;
+ valid_flags = 0;
+ break;
+ }
+ FALLTHROUGH;
+ case OPT_HOSTNAME:
+ assert(optarg != NULL);
+ if (*optarg == '\0')
+ usage();
+ if (sudo_settings[ARG_REMOTE_HOST].value != NULL)
+ usage();
+ sudo_settings[ARG_REMOTE_HOST].value = optarg;
+ break;
+ case 'i':
+ sudo_settings[ARG_LOGIN_SHELL].value = "true";
+ SET(flags, MODE_LOGIN_SHELL);
+ break;
+ case 'K':
+ if (mode && mode != MODE_KILL)
+ usage_excl();
+ mode = MODE_KILL;
+ valid_flags = 0;
+ FALLTHROUGH;
+ case 'k':
+ if (sudo_settings[ARG_UPDATE_TICKET].value != NULL)
+ usage_excl_ticket();
+ sudo_settings[ARG_IGNORE_TICKET].value = "true";
+ break;
+ case 'l':
+ if (mode) {
+ if (mode == MODE_LIST)
+ SET(flags, MODE_LONG_LIST);
+ else
+ usage_excl();
+ }
+ mode = MODE_LIST;
+ valid_flags = LIST_VALID_FLAGS;
+ break;
+ case 'N':
+ if (sudo_settings[ARG_IGNORE_TICKET].value != NULL)
+ usage_excl_ticket();
+ sudo_settings[ARG_UPDATE_TICKET].value = "false";
+ break;
+ case 'n':
+ SET(flags, MODE_NONINTERACTIVE);
+ sudo_settings[ARG_NONINTERACTIVE].value = "true";
+ break;
+ case 'P':
+ sudo_settings[ARG_PRESERVE_GROUPS].value = "true";
+ SET(flags, MODE_PRESERVE_GROUPS);
+ break;
+ case 'p':
+ /* An empty prompt is allowed. */
+ assert(optarg != NULL);
+ if (sudo_settings[ARG_PROMPT].value != NULL)
+ usage();
+ sudo_settings[ARG_PROMPT].value = optarg;
+ break;
+ case 'R':
+ assert(optarg != NULL);
+ if (*optarg == '\0')
+ usage();
+ if (sudo_settings[ARG_CHROOT].value != NULL)
+ usage();
+ sudo_settings[ARG_CHROOT].value = optarg;
+ break;
+#ifdef HAVE_SELINUX
+ case 'r':
+ assert(optarg != NULL);
+ if (*optarg == '\0')
+ usage();
+ if (sudo_settings[ARG_SELINUX_ROLE].value != NULL)
+ usage();
+ sudo_settings[ARG_SELINUX_ROLE].value = optarg;
+ break;
+ case 't':
+ assert(optarg != NULL);
+ if (*optarg == '\0')
+ usage();
+ if (sudo_settings[ARG_SELINUX_TYPE].value != NULL)
+ usage();
+ sudo_settings[ARG_SELINUX_TYPE].value = optarg;
+ break;
+#endif
+ case 'T':
+ /* Plugin determines whether empty timeout is allowed. */
+ assert(optarg != NULL);
+ if (sudo_settings[ARG_TIMEOUT].value != NULL)
+ usage();
+ sudo_settings[ARG_TIMEOUT].value = optarg;
+ break;
+ case 'S':
+ SET(tgetpass_flags, TGP_STDIN);
+ break;
+ case 's':
+ sudo_settings[ARG_USER_SHELL].value = "true";
+ SET(flags, MODE_SHELL);
+ break;
+ case 'U':
+ assert(optarg != NULL);
+ if (list_user != NULL || *optarg == '\0')
+ usage();
+ list_user = optarg;
+ break;
+ case 'u':
+ assert(optarg != NULL);
+ if (*optarg == '\0')
+ usage();
+ if (sudo_settings[ARG_RUNAS_USER].value != NULL)
+ usage();
+ sudo_settings[ARG_RUNAS_USER].value = optarg;
+ break;
+ case 'v':
+ if (mode && mode != MODE_VALIDATE)
+ usage_excl();
+ mode = MODE_VALIDATE;
+ valid_flags = VALIDATE_VALID_FLAGS;
+ break;
+ case 'V':
+ if (mode && mode != MODE_VERSION) {
+ if (strcmp(progname, "sudoedit") != 0)
+ usage_excl();
+ }
+ mode = MODE_VERSION;
+ valid_flags = 0;
+ break;
+ default:
+ usage();
+ }
+ } else if (!got_end_of_args && is_envar) {
+ /* Insert key=value pair, crank optind and resume getopt. */
+ env_insert(&extra_env, argv[optind]);
+ optind++;
+ } else {
+ /* Not an option or an environment variable -- we're done. */
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ *old_optind = optind;
+
+ if (!mode) {
+ /* Defer -k mode setting until we know whether it is a flag or not */
+ if (sudo_settings[ARG_IGNORE_TICKET].value != NULL) {
+ if (argc == 0 && !ISSET(flags, MODE_SHELL|MODE_LOGIN_SHELL)) {
+ mode = MODE_INVALIDATE; /* -k by itself */
+ sudo_settings[ARG_IGNORE_TICKET].value = NULL;
+ valid_flags = 0;
+ }
+ }
+ if (!mode)
+ mode = MODE_RUN; /* running a command */
+ }
+
+ if (argc > 0 && mode == MODE_LIST)
+ mode = MODE_CHECK;
+
+ if (ISSET(flags, MODE_LOGIN_SHELL)) {
+ if (ISSET(flags, MODE_SHELL)) {
+ sudo_warnx("%s",
+ U_("you may not specify both the -i and -s options"));
+ usage();
+ }
+ if (ISSET(flags, MODE_PRESERVE_ENV)) {
+ sudo_warnx("%s",
+ U_("you may not specify both the -i and -E options"));
+ usage();
+ }
+ SET(flags, MODE_SHELL);
+ }
+ if ((flags & valid_flags) != flags)
+ usage();
+ if (mode == MODE_EDIT &&
+ (ISSET(flags, MODE_PRESERVE_ENV) || extra_env.env_len != 0)) {
+ if (ISSET(mode, MODE_PRESERVE_ENV))
+ sudo_warnx("%s", U_("the -E option is not valid in edit mode"));
+ if (extra_env.env_len != 0)
+ sudo_warnx("%s",
+ U_("you may not specify environment variables in edit mode"));
+ usage();
+ }
+ if ((sudo_settings[ARG_RUNAS_USER].value != NULL ||
+ sudo_settings[ARG_RUNAS_GROUP].value != NULL) &&
+ !ISSET(mode, MODE_EDIT | MODE_RUN | MODE_CHECK | MODE_VALIDATE)) {
+ usage();
+ }
+ if (list_user != NULL && mode != MODE_LIST && mode != MODE_CHECK) {
+ sudo_warnx("%s",
+ U_("the -U option may only be used with the -l option"));
+ usage();
+ }
+ if (ISSET(tgetpass_flags, TGP_STDIN) && ISSET(tgetpass_flags, TGP_ASKPASS)) {
+ sudo_warnx("%s", U_("the -A and -S options may not be used together"));
+ usage();
+ }
+ if ((argc == 0 && mode == MODE_EDIT) ||
+ (argc > 0 && !ISSET(mode, MODE_RUN | MODE_EDIT | MODE_CHECK)))
+ usage();
+ if (argc == 0 && mode == MODE_RUN && !ISSET(flags, MODE_SHELL)) {
+ SET(flags, (MODE_IMPLIED_SHELL | MODE_SHELL));
+ sudo_settings[ARG_IMPLIED_SHELL].value = "true";
+ }
+#ifdef ENABLE_SUDO_PLUGIN_API
+ sudo_settings[ARG_PLUGIN_DIR].value = sudo_conf_plugin_dir_path();
+#endif
+ if (exec_ptrace_intercept_supported())
+ sudo_settings[ARG_INTERCEPT_SETID].value = "true";
+ if (exec_ptrace_subcmds_supported())
+ sudo_settings[ARG_INTERCEPT_PTRACE].value = "true";
+
+ if (mode == MODE_HELP)
+ help();
+
+ /*
+ * For shell mode we need to rewrite argv
+ * TODO: move this to the policy plugin and make escaping configurable
+ */
+ if (ISSET(flags, MODE_SHELL|MODE_LOGIN_SHELL) && ISSET(mode, MODE_RUN)) {
+ char **av, *cmnd = NULL;
+ int ac = 1;
+
+ if (argc != 0) {
+ /* shell -c "command" */
+ char *src, *dst;
+ size_t size = 0;
+
+ for (av = argv; *av != NULL; av++)
+ size += strlen(*av) + 1;
+ if (size == 0 || (cmnd = reallocarray(NULL, size, 2)) == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (!gc_add(GC_PTR, cmnd))
+ exit(EXIT_FAILURE);
+
+ for (dst = cmnd, av = argv; *av != NULL; av++) {
+ for (src = *av; *src != '\0'; src++) {
+ /* quote potential meta characters */
+ if (!isalnum((unsigned char)*src) && *src != '_' && *src != '-' && *src != '$')
+ *dst++ = '\\';
+ *dst++ = *src;
+ }
+ *dst++ = ' ';
+ }
+ if (cmnd != dst)
+ dst--; /* replace last space with a NUL */
+ *dst = '\0';
+
+ ac += 2; /* -c cmnd */
+ }
+
+ av = reallocarray(NULL, (size_t)ac + 1, sizeof(char *));
+ if (av == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (!gc_add(GC_PTR, av))
+ exit(EXIT_FAILURE);
+
+ av[0] = (char *)shell; /* plugin may override shell */
+ if (cmnd != NULL) {
+ av[1] = (char *)"-c";
+ av[2] = cmnd;
+ }
+ av[ac] = NULL;
+
+ argv = av;
+ argc = ac;
+ }
+
+ /*
+ * For sudoedit we need to rewrite argv
+ */
+ if (mode == MODE_EDIT) {
+#if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID)
+ char **av;
+ int ac;
+
+ av = reallocarray(NULL, (size_t)argc + 2, sizeof(char *));
+ if (av == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (!gc_add(GC_PTR, av))
+ exit(EXIT_FAILURE);
+
+ /* Must have the command in argv[0]. */
+ av[0] = (char *)"sudoedit";
+ for (ac = 0; argv[ac] != NULL; ac++) {
+ av[ac + 1] = argv[ac];
+ }
+ av[++ac] = NULL;
+
+ argv = av;
+ argc = ac;
+#else
+ sudo_fatalx("%s", U_("sudoedit is not supported on this platform"));
+#endif
+ }
+
+ *settingsp = sudo_settings;
+ *env_addp = extra_env.envp;
+ *nargc = argc;
+ *nargv = argv;
+ *list_userp = list_user;
+ debug_return_uint(mode | flags);
+}
+
+/*
+ * Display usage message.
+ * The actual usage strings are in sudo_usage.h for configure substitution.
+ */
+static void
+display_usage(FILE *fp)
+{
+ const char * const **uvecs = sudo_usage;
+ const char * const *uvec;
+ size_t i;
+ int indent;
+
+ /*
+ * Use usage vectors appropriate to the progname.
+ */
+ if (strcmp(getprogname(), "sudoedit") == 0)
+ uvecs = sudoedit_usage;
+
+ indent = (int)strlen(getprogname()) + 8;
+ while ((uvec = *uvecs) != NULL) {
+ (void)fprintf(fp, "usage: %s %s\n", getprogname(), uvec[0]);
+ for (i = 1; uvec[i] != NULL; i++) {
+ (void)fprintf(fp, "%*s%s\n", indent, "", uvec[i]);
+ }
+ uvecs++;
+ }
+}
+
+/*
+ * Display usage message and exit.
+ */
+sudo_noreturn void
+usage(void)
+{
+ display_usage(stderr);
+ exit(EXIT_FAILURE);
+}
+
+/*
+ * Tell which options are mutually exclusive and exit.
+ */
+static void
+usage_excl(void)
+{
+ debug_decl(usage_excl, SUDO_DEBUG_ARGS);
+
+ sudo_warnx("%s",
+ U_("Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"));
+ usage();
+}
+
+/*
+ * Tell which options are mutually exclusive and exit.
+ */
+static void
+usage_excl_ticket(void)
+{
+ debug_decl(usage_excl_ticket, SUDO_DEBUG_ARGS);
+
+ sudo_warnx("%s",
+ U_("Only one of the -K, -k or -N options may be specified"));
+ usage();
+}
+
+static int
+help_out(const char * restrict buf)
+{
+ return fputs(buf, stdout);
+}
+
+sudo_noreturn static void
+help(void)
+{
+ struct sudo_lbuf lbuf;
+ const int indent = 32;
+ const char *pname = getprogname();
+ bool sudoedit = false;
+ debug_decl(help, SUDO_DEBUG_ARGS);
+
+ if (strcmp(pname, "sudoedit") == 0) {
+ sudoedit = true;
+ (void)printf(_("%s - edit files as another user\n\n"), pname);
+ } else {
+ (void)printf(_("%s - execute a command as another user\n\n"), pname);
+ }
+ display_usage(stdout);
+
+ sudo_lbuf_init(&lbuf, help_out, indent, NULL, 80);
+ sudo_lbuf_append(&lbuf, "%s", _("\nOptions:\n"));
+ sudo_lbuf_append(&lbuf, " -A, --askpass %s\n",
+ _("use a helper program for password prompting"));
+#ifdef HAVE_BSD_AUTH_H
+ sudo_lbuf_append(&lbuf, " -a, --auth-type=type %s\n",
+ _("use specified BSD authentication type"));
+#endif
+ if (!sudoedit) {
+ sudo_lbuf_append(&lbuf, " -b, --background %s\n",
+ _("run command in the background"));
+ }
+ sudo_lbuf_append(&lbuf, " -B, --bell %s\n",
+ _("ring bell when prompting"));
+ sudo_lbuf_append(&lbuf, " -C, --close-from=num %s\n",
+ _("close all file descriptors >= num"));
+#ifdef HAVE_LOGIN_CAP_H
+ sudo_lbuf_append(&lbuf, " -c, --login-class=class %s\n",
+ _("run command with the specified BSD login class"));
+#endif
+ sudo_lbuf_append(&lbuf, " -D, --chdir=directory %s\n",
+ _("change the working directory before running command"));
+ if (!sudoedit) {
+ sudo_lbuf_append(&lbuf, " -E, --preserve-env %s\n",
+ _("preserve user environment when running command"));
+ sudo_lbuf_append(&lbuf, " --preserve-env=list %s\n",
+ _("preserve specific environment variables"));
+ sudo_lbuf_append(&lbuf, " -e, --edit %s\n",
+ _("edit files instead of running a command"));
+ }
+ sudo_lbuf_append(&lbuf, " -g, --group=group %s\n",
+ _("run command as the specified group name or ID"));
+ if (!sudoedit) {
+ sudo_lbuf_append(&lbuf, " -H, --set-home %s\n",
+ _("set HOME variable to target user's home dir"));
+ }
+ sudo_lbuf_append(&lbuf, " -h, --help %s\n",
+ _("display help message and exit"));
+ sudo_lbuf_append(&lbuf, " -h, --host=host %s\n",
+ _("run command on host (if supported by plugin)"));
+ if (!sudoedit) {
+ sudo_lbuf_append(&lbuf, " -i, --login %s\n",
+ _("run login shell as the target user; a command may also be specified"));
+ sudo_lbuf_append(&lbuf, " -K, --remove-timestamp %s\n",
+ _("remove timestamp file completely"));
+ }
+ sudo_lbuf_append(&lbuf, " -k, --reset-timestamp %s\n",
+ _("invalidate timestamp file"));
+ if (!sudoedit) {
+ sudo_lbuf_append(&lbuf, " -l, --list %s\n",
+ _("list user's privileges or check a specific command; use twice for longer format"));
+ }
+ sudo_lbuf_append(&lbuf, " -n, --non-interactive %s\n",
+ _("non-interactive mode, no prompts are used"));
+ if (!sudoedit) {
+ sudo_lbuf_append(&lbuf, " -P, --preserve-groups %s\n",
+ _("preserve group vector instead of setting to target's"));
+ }
+ sudo_lbuf_append(&lbuf, " -p, --prompt=prompt %s\n",
+ _("use the specified password prompt"));
+ sudo_lbuf_append(&lbuf, " -R, --chroot=directory %s\n",
+ _("change the root directory before running command"));
+#ifdef HAVE_SELINUX
+ sudo_lbuf_append(&lbuf, " -r, --role=role %s\n",
+ _("create SELinux security context with specified role"));
+#endif
+ sudo_lbuf_append(&lbuf, " -S, --stdin %s\n",
+ _("read password from standard input"));
+ if (!sudoedit) {
+ sudo_lbuf_append(&lbuf, " -s, --shell %s\n",
+ _("run shell as the target user; a command may also be specified"));
+ }
+#ifdef HAVE_SELINUX
+ sudo_lbuf_append(&lbuf, " -t, --type=type %s\n",
+ _("create SELinux security context with specified type"));
+#endif
+ sudo_lbuf_append(&lbuf, " -T, --command-timeout=timeout %s\n",
+ _("terminate command after the specified time limit"));
+ if (!sudoedit) {
+ sudo_lbuf_append(&lbuf, " -U, --other-user=user %s\n",
+ _("in list mode, display privileges for user"));
+ }
+ sudo_lbuf_append(&lbuf, " -u, --user=user %s\n",
+ _("run command (or edit file) as specified user name or ID"));
+ sudo_lbuf_append(&lbuf, " -V, --version %s\n",
+ _("display version information and exit"));
+ if (!sudoedit) {
+ sudo_lbuf_append(&lbuf, " -v, --validate %s\n",
+ _("update user's timestamp without running a command"));
+ }
+ sudo_lbuf_append(&lbuf, " -- %s\n",
+ _("stop processing command line arguments"));
+ sudo_lbuf_print(&lbuf);
+ sudo_lbuf_destroy(&lbuf);
+ sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, 0);
+ exit(EXIT_SUCCESS);
+}
diff --git a/src/preload.c b/src/preload.c
new file mode 100644
index 0000000..e18cc95
--- /dev/null
+++ b/src/preload.c
@@ -0,0 +1,77 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010, 2011, 2013 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_GSS_KRB5_CCACHE_NAME
+# if defined(HAVE_GSSAPI_GSSAPI_KRB5_H)
+# include <gssapi/gssapi.h>
+# include <gssapi/gssapi_krb5.h>
+# elif defined(HAVE_GSSAPI_GSSAPI_H)
+# include <gssapi/gssapi.h>
+# else
+# include <gssapi.h>
+# endif
+#endif
+
+#include <sudo.h>
+#include <sudo_dso.h>
+#include <sudo_plugin.h>
+
+#ifdef STATIC_SUDOERS_PLUGIN
+
+extern struct policy_plugin sudoers_policy;
+extern struct io_plugin sudoers_io;
+extern struct audit_plugin sudoers_audit;
+
+static struct sudo_preload_symbol sudo_rtld_default_symbols[] = {
+# ifdef HAVE_GSS_KRB5_CCACHE_NAME
+ { "gss_krb5_ccache_name", (void *)&gss_krb5_ccache_name},
+# endif
+ { (const char *)0, (void *)0 }
+};
+
+/* XXX - can we autogenerate these? */
+static struct sudo_preload_symbol sudo_sudoers_plugin_symbols[] = {
+ { "sudoers_policy", (void *)&sudoers_policy },
+ { "sudoers_io", (void *)&sudoers_io },
+ { "sudoers_audit", (void *)&sudoers_audit },
+ { (const char *)0, (void *)0 }
+};
+
+/*
+ * Statically compiled symbols indexed by handle.
+ */
+static struct sudo_preload_table sudo_preload_table[] = {
+ { (char *)0, SUDO_DSO_DEFAULT, sudo_rtld_default_symbols },
+ { _PATH_SUDOERS_PLUGIN, &sudo_sudoers_plugin_symbols, sudo_sudoers_plugin_symbols },
+ { (char *)0, (void *)0, (struct sudo_preload_symbol *)0 }
+};
+
+void
+preload_static_symbols(void)
+{
+ sudo_dso_preload_table(sudo_preload_table);
+}
+
+#endif /* STATIC_SUDOERS_PLUGIN */
diff --git a/src/preserve_fds.c b/src/preserve_fds.c
new file mode 100644
index 0000000..ebe4797
--- /dev/null
+++ b/src/preserve_fds.c
@@ -0,0 +1,216 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#include <sudo.h>
+
+/*
+ * Add an fd to preserve.
+ */
+int
+add_preserved_fd(struct preserved_fd_list *pfds, int fd)
+{
+ struct preserved_fd *pfd, *pfd_new;
+ debug_decl(add_preserved_fd, SUDO_DEBUG_UTIL);
+
+ pfd_new = malloc(sizeof(*pfd));
+ if (pfd_new == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ pfd_new->lowfd = fd;
+ pfd_new->highfd = fd;
+ pfd_new->flags = fcntl(fd, F_GETFD);
+ if (pfd_new->flags == -1) {
+ free(pfd_new);
+ debug_return_int(-1);
+ }
+
+ TAILQ_FOREACH(pfd, pfds, entries) {
+ if (fd == pfd->highfd) {
+ /* already preserved */
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "fd %d already preserved", fd);
+ free(pfd_new);
+ pfd_new = NULL;
+ break;
+ }
+ if (fd < pfd->highfd) {
+ TAILQ_INSERT_BEFORE(pfd, pfd_new, entries);
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "preserving fd %d", fd);
+ pfd_new = NULL;
+ break;
+ }
+ }
+ if (pfd_new != NULL) {
+ TAILQ_INSERT_TAIL(pfds, pfd_new, entries);
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "preserving fd %d", fd);
+ }
+
+ debug_return_int(0);
+}
+
+/*
+ * Close all descriptors, startfd and higher except those listed
+ * in pfds.
+ */
+void
+closefrom_except(int startfd, struct preserved_fd_list *pfds)
+{
+ int fd, lastfd = -1;
+ struct preserved_fd *pfd, *pfd_next;
+ unsigned char *fdbits;
+ debug_decl(closefrom_except, SUDO_DEBUG_UTIL);
+
+ /* First, relocate preserved fds to be as contiguous as possible. */
+ TAILQ_FOREACH_REVERSE_SAFE(pfd, pfds, preserved_fd_list, entries, pfd_next) {
+ if (pfd->highfd < startfd)
+ continue;
+ fd = dup(pfd->highfd);
+ if (fd == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "dup %d", pfd->highfd);
+ if (errno == EBADF) {
+ TAILQ_REMOVE(pfds, pfd, entries);
+ continue;
+ }
+ /* NOTE: still need to adjust lastfd below with unchanged lowfd. */
+ } else if (fd < pfd->highfd) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "dup %d -> %d", pfd->highfd, pfd->lowfd);
+ sudo_debug_update_fd(pfd->highfd, pfd->lowfd);
+ pfd->lowfd = fd;
+ fd = pfd->highfd;
+ }
+ if (fd != -1)
+ (void) close(fd);
+
+ if (pfd->lowfd > lastfd)
+ lastfd = pfd->lowfd; /* highest (relocated) preserved fd */
+ }
+
+ if (lastfd == -1) {
+ /* No fds to preserve. */
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "closefrom(%d)", startfd);
+ closefrom(startfd);
+ debug_return;
+ }
+
+ /* Create bitmap of preserved (relocated) fds. */
+ fdbits = calloc((size_t)(lastfd + NBBY) / NBBY, 1);
+ if (fdbits == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ TAILQ_FOREACH(pfd, pfds, entries) {
+ sudo_setbit(fdbits, pfd->lowfd);
+ }
+
+ /*
+ * Close any unpreserved fds [startfd,lastfd]
+ */
+ for (fd = startfd; fd <= lastfd; fd++) {
+ if (!sudo_isset(fdbits, fd)) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "closing fd %d", fd);
+#ifdef __APPLE__
+ /* Avoid potential libdispatch crash when we close its fds. */
+ (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
+#else
+ (void) close(fd);
+#endif
+ }
+ }
+ free(fdbits);
+
+ /* Let closefrom() do the rest for us. */
+ if (lastfd + 1 > startfd)
+ startfd = lastfd + 1;
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "closefrom(%d)", startfd);
+ closefrom(startfd);
+
+ /* Restore preserved fds and set flags. */
+ TAILQ_FOREACH_REVERSE(pfd, pfds, preserved_fd_list, entries) {
+ if (pfd->lowfd != pfd->highfd) {
+ if (dup2(pfd->lowfd, pfd->highfd) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "dup2(%d, %d): %s", pfd->lowfd, pfd->highfd,
+ strerror(errno));
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "dup2(%d, %d)", pfd->lowfd, pfd->highfd);
+ }
+ if (fcntl(pfd->highfd, F_SETFD, pfd->flags) == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "fcntl(%d, F_SETFD, %d): %s", pfd->highfd,
+ pfd->flags, strerror(errno));
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
+ "fcntl(%d, F_SETFD, %d)", pfd->highfd, pfd->flags);
+ }
+ sudo_debug_update_fd(pfd->lowfd, pfd->highfd);
+ (void) close(pfd->lowfd);
+ pfd->lowfd = pfd->highfd;
+ }
+ }
+ debug_return;
+}
+
+/*
+ * Parse a comma-separated list of fds and add them to preserved_fds.
+ */
+void
+parse_preserved_fds(struct preserved_fd_list *pfds, const char *fdstr)
+{
+ const char *cp = fdstr;
+ long lval;
+ char *ep;
+ debug_decl(parse_preserved_fds, SUDO_DEBUG_UTIL);
+
+ do {
+ errno = 0;
+ lval = strtol(cp, &ep, 10);
+ if (ep == cp || (*ep != ',' && *ep != '\0')) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to parse fd string %s", cp);
+ break;
+ }
+ if ((errno == ERANGE && lval == LONG_MAX) || lval < 0 || lval > INT_MAX) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "range error parsing fd string %s", cp);
+ } else {
+ add_preserved_fd(pfds, (int)lval);
+ }
+ cp = ep + 1;
+ } while (*ep != '\0');
+
+ debug_return;
+}
diff --git a/src/regress/intercept/test_ptrace.c b/src/regress/intercept/test_ptrace.c
new file mode 100644
index 0000000..30b73e7
--- /dev/null
+++ b/src/regress/intercept/test_ptrace.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+/*
+ * Test program to exercise seccomp(2) and ptrace(2) intercept code.
+ *
+ * Usage: test_ptrace [-d 1-3] [command]
+ */
+
+/* Ignore architecture restrictions and define this unilaterally. */
+#define HAVE_PTRACE_INTERCEPT
+#include "exec_ptrace.c"
+
+static sig_atomic_t got_sigchld;
+static int debug;
+int sudo_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+static void
+handler(int signo)
+{
+ if (signo == SIGCHLD)
+ got_sigchld = 1;
+}
+
+void
+intercept_closure_reset(struct intercept_closure *closure)
+{
+ memset(closure, 0, sizeof(*closure));
+}
+
+bool
+intercept_check_policy(const char *command, int argc, char **argv, int envc,
+ char **envp, const char *runcwd, int *oldcwd, void *v)
+{
+ struct intercept_closure *closure = v;
+ struct stat sb1, sb2;
+ bool is_denied;
+ debug_decl(intercept_check_policy, SUDO_DEBUG_EXEC);
+
+ /* Fake policy decisions. */
+ is_denied = stat(command, &sb1) == 0 && stat("/usr/bin/who", &sb2) == 0 &&
+ sb1.st_ino == sb2.st_ino && sb1.st_dev == sb2.st_dev;
+ if (is_denied) {
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "denied %s", command);
+ closure->state = POLICY_REJECT;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "allowed %s", command);
+ closure->state = POLICY_TEST;
+ }
+ *oldcwd = -1;
+
+ debug_return_bool(true);
+}
+
+static void
+init_debug_files(struct sudo_conf_debug_file_list *file_list,
+ struct sudo_debug_file *file)
+{
+ debug_decl(init_debug_files, SUDO_DEBUG_EXEC);
+
+ TAILQ_INIT(file_list);
+ switch (debug) {
+ case 0:
+ debug_return;
+ case 1:
+ file->debug_flags = (char *)"exec@diag";
+ break;
+ case 2:
+ file->debug_flags = (char *)"exec@info";
+ break;
+ default:
+ file->debug_flags = (char *)"exec@debug";
+ break;
+ }
+ file->debug_file = (char *)"/dev/stderr";
+ TAILQ_INSERT_HEAD(file_list, file, entries);
+
+ debug_return;
+}
+
+int
+sudo_sigaction(int signo, struct sigaction *sa, struct sigaction *osa)
+{
+ return sigaction(signo, sa, osa);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct sudo_conf_debug_file_list debug_files;
+ struct sudo_debug_file debug_file;
+ const char *base, *shell = _PATH_SUDO_BSHELL;
+ struct intercept_closure closure = { 0 };
+ const char *errstr;
+ sigset_t blocked, empty;
+ struct sigaction sa;
+ pid_t child, my_pid, pid, my_pgrp;
+ int ch, status;
+ debug_decl_vars(main, SUDO_DEBUG_MAIN);
+
+ initprogname(argc > 0 ? argv[0] : "test_ptrace");
+
+ if (!have_seccomp_action("trap"))
+ sudo_fatalx("SECCOMP_MODE_FILTER not available in this kernel");
+
+ while ((ch = getopt(argc, argv, "d:")) != -1) {
+ switch (ch) {
+ case 'd':
+ debug = sudo_strtonum(optarg, 1, INT_MAX, &errstr);
+ if (errstr != NULL)
+ sudo_fatalx(U_("%s: %s"), optarg, U_(errstr));
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-d 1-3] [command]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0)
+ shell = argv[0];
+ base = strrchr(shell, '/');
+ base = base ? base + 1 : shell;
+
+ /* Set debug level based on the debug flag. */
+ init_debug_files(&debug_files, &debug_file);
+ sudo_debug_instance = sudo_debug_register(getprogname(),
+ NULL, NULL, &debug_files, -1);
+ if (sudo_debug_instance == SUDO_DEBUG_INSTANCE_ERROR)
+ return EXIT_FAILURE;
+
+ /* Block SIGCHLD and SIGUSR during critical section. */
+ sigemptyset(&empty);
+ sigemptyset(&blocked);
+ sigaddset(&blocked, SIGCHLD);
+ sigaddset(&blocked, SIGUSR1);
+ sigprocmask(SIG_BLOCK, &blocked, NULL);
+
+ /* Signal handler sets a flag for SIGCHLD, nothing for SIGUSR1. */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = handler;
+ sigaction(SIGCHLD, &sa, NULL);
+ sigaction(SIGUSR1, &sa, NULL);
+
+ /* Fork a shell. */
+ my_pid = getpid();
+ my_pgrp = getpgrp();
+ child = fork();
+ switch (child) {
+ case -1:
+ sudo_fatal("fork");
+ case 0:
+ /* child */
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1)
+ sudo_fatal("%s", "unable to set no_new_privs bit");
+ if (!set_exec_filter())
+ _exit(EXIT_FAILURE);
+
+ /* Suspend child until tracer seizes control and sends SIGUSR1. */
+ sigsuspend(&empty);
+ execl(shell, base, NULL);
+ sudo_fatal("execl");
+ default:
+ /* Parent attaches to child and allows it to continue. */
+ if (exec_ptrace_seize(child) == -1)
+ return EXIT_FAILURE;
+ break;
+ }
+
+ /* Wait for SIGCHLD. */
+ for (;;) {
+ sigsuspend(&empty);
+ if (!got_sigchld)
+ continue;
+ got_sigchld = 0;
+
+ for (;;) {
+ do {
+ pid = waitpid(-1, &status, __WALL|WNOHANG);
+ } while (pid == -1 && errno == EINTR);
+ if (pid <= 0) {
+ if (pid == -1 && errno != ECHILD)
+ sudo_fatal("waitpid");
+ /* No child to wait for. */
+ break;
+ }
+
+ if (WIFEXITED(status)) {
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "%d: exited %d",
+ (int)pid, WEXITSTATUS(status));
+ if (pid == child)
+ return WEXITSTATUS(status);
+ } else if (WIFSIGNALED(status)) {
+ sudo_debug_printf(SUDO_DEBUG_DIAG, "%d: killed by signal %d",
+ (int)pid, WTERMSIG(status));
+ if (pid == child)
+ return WTERMSIG(status) | 128;
+ } else if (WIFSTOPPED(status)) {
+ if (exec_ptrace_stopped(pid, status, &closure)) {
+ if (pid == child) {
+ sudo_suspend_parent(WSTOPSIG(status), my_pid,
+ my_pgrp, child, NULL, NULL);
+ if (kill(child, SIGCONT) != 0)
+ sudo_warn("kill(%d, SIGCONT)", (int)child);
+ }
+ }
+ } else {
+ sudo_fatalx("%d: unknown status 0x%x", (int)pid, status);
+ }
+ }
+ }
+}
diff --git a/src/regress/net_ifs/check_net_ifs.c b/src/regress/net_ifs/check_net_ifs.c
new file mode 100644
index 0000000..60adcfa
--- /dev/null
+++ b/src/regress/net_ifs/check_net_ifs.c
@@ -0,0 +1,87 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+
+#include <sudo_compat.h>
+#include <sudo_util.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+extern int get_net_ifs(char **addrinfo);
+
+int
+main(int argc, char *argv[])
+{
+ int ch, ninterfaces, errors = 0, ntests = 1;
+ char *interfaces = NULL;
+ bool verbose = false;
+
+ initprogname(argc > 0 ? argv[0] : "check_net_ifs");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ verbose = true;
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+
+ ninterfaces = get_net_ifs(&interfaces);
+ switch (ninterfaces) {
+ case -1:
+ printf("FAIL: unable to get network interfaces\n");
+ errors++;
+ break;
+ case 0:
+ /* no interfaces or STUB_LOAD_INTERFACES defined. */
+ if (verbose)
+ printf("OK: (0 interfaces)\n");
+ break;
+ default:
+ if (verbose) {
+ printf("OK: (%d interface%s, %s)\n", ninterfaces,
+ ninterfaces > 1 ? "s" : "", interfaces);
+ }
+ break;
+ }
+ free(interfaces);
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+ return errors;
+}
diff --git a/src/regress/noexec/check_noexec.c b/src/regress/noexec/check_noexec.c
new file mode 100644
index 0000000..a5f7ff4
--- /dev/null
+++ b/src/regress/noexec/check_noexec.c
@@ -0,0 +1,232 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2016, 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <string.h>
+#ifdef HAVE_WORDEXP_H
+# include <wordexp.h>
+#endif
+#include <signal.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_util.h>
+#include <sudo_queue.h>
+#include <sudo_exec.h>
+
+static bool verbose;
+
+sudo_dso_public int main(int argc, char *argv[], char *envp[]);
+
+static bool
+report_status(int status, const char *what)
+{
+ bool ret = false;
+
+ /* system() returns -1 for exec failure. */
+ if (status == -1) {
+ if (verbose)
+ printf("%s: OK (%s)\n", getprogname(), what);
+ return true;
+ }
+
+ /* check exit value, expecting 127 for failure */
+ if (WIFEXITED(status)) {
+ int exitval = WEXITSTATUS(status);
+ if (exitval == 127) {
+ if (verbose)
+ printf("%s: OK (%s)\n", getprogname(), what);
+ ret = true;
+ } else {
+ printf("%s: FAIL (%s) [%d]\n", getprogname(), what, exitval);
+ }
+ } else if (WIFSIGNALED(status)) {
+ printf("%s: FAIL (%s) [signal %d]\n", getprogname(), what,
+ WTERMSIG(status));
+ } else {
+ /* should not happen */
+ printf("%s: FAIL (%s) [status %d]\n", getprogname(), what, status);
+ }
+
+ return ret;
+}
+
+static int
+try_execl(void)
+{
+ pid_t child, pid;
+ int status;
+
+ child = fork();
+ switch (child) {
+ case -1:
+ sudo_fatal_nodebug("fork");
+ case 0:
+ /* child */
+ /* Try to exec /bin/true, else exit with value 127. */
+ execl("/bin/true", "true", (char *)0);
+ _exit(127);
+ default:
+ /* parent */
+ do {
+ pid = waitpid(child, &status, 0);
+ } while (pid == -1 && errno == EINTR);
+ if (pid == -1)
+ sudo_fatal_nodebug("waitpid");
+
+ if (report_status(status, "execl"))
+ return 0;
+ return 1;
+ }
+}
+
+static int
+try_system(void)
+{
+ int status;
+
+ /* Try to run /bin/true, system() returns 127 on exec failure. */
+ status = system("/bin/true > /dev/null 2>&1");
+
+ if (report_status(status, "system"))
+ return 0;
+ return 1;
+}
+
+#ifdef HAVE_WORDEXP_H
+static int
+try_wordexp(void)
+{
+ wordexp_t we;
+ int rc, ret = 1;
+
+ /*
+ * sudo_noexec.so prevents command substitution via the WRDE_NOCMD flag
+ * where possible.
+ */
+ rc = wordexp("$(/bin/echo foo)", &we, 0);
+ switch (rc) {
+ case -1:
+ /* sudo's wordexp() wrapper returns -1 if RTLD_NEXT is not supported. */
+ case 127:
+ /* Solaris 10 wordexp() returns 127 for execve() failure. */
+#ifdef WRDE_ERRNO
+ case WRDE_ERRNO:
+ /* Solaris 11 wordexp() returns WRDE_ERRNO for execve() failure. */
+#endif
+ if (verbose)
+ printf("%s: OK (wordexp) [%d]\n", getprogname(), rc);
+ ret = 0;
+ break;
+ case WRDE_SYNTAX:
+ /* FreeBSD returns WRDE_SYNTAX if it can't write to the shell process */
+ if (verbose)
+ printf("%s: OK (wordexp) [WRDE_SYNTAX]\n", getprogname());
+ ret = 0;
+ break;
+ case WRDE_CMDSUB:
+ if (verbose)
+ printf("%s: OK (wordexp) [WRDE_CMDSUB]\n", getprogname());
+ ret = 0;
+ break;
+ case 0:
+ /*
+ * On HP-UX 11.00 we don't seem to be able to add WRDE_NOCMD
+ * but the execve() wrapper prevents the command substitution.
+ */
+ if (we.we_wordc == 0) {
+ if (verbose)
+ printf("%s: OK (wordexp) [%d]\n", getprogname(), rc);
+ wordfree(&we);
+ ret = 0;
+ break;
+ }
+ wordfree(&we);
+ FALLTHROUGH;
+ default:
+ printf("%s: FAIL (wordexp) [%d]\n", getprogname(), rc);
+ break;
+ }
+ return ret;
+}
+#endif
+
+sudo_noreturn static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-v] rexec | /path/to/sudo_noexec.so\n",
+ getprogname());
+ exit(EXIT_FAILURE);
+}
+
+int
+main(int argc, char *argv[], char *envp[])
+{
+ int ch, errors = 0, ntests = 0;
+
+ initprogname(argc > 0 ? argv[0] : "check_noexec");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ verbose = true;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ if (argc - optind != 1)
+ usage();
+
+ /* Disable execution for post-exec and re-exec ourself. */
+ if (strcmp(argv[optind], "rexec") != 0) {
+ const char *noexec = argv[optind];
+ argv[optind] = (char *)"rexec";
+ execve(argv[0], argv, disable_execute(envp, noexec));
+ sudo_fatalx_nodebug("execve");
+ }
+
+ ntests++;
+ errors += try_execl();
+ ntests++;
+ errors += try_system();
+#ifdef HAVE_WORDEXP_H
+ ntests++;
+ errors += try_wordexp();
+#endif
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+ return errors;
+}
diff --git a/src/regress/ttyname/check_ttyname.c b/src/regress/ttyname/check_ttyname.c
new file mode 100644
index 0000000..715423d
--- /dev/null
+++ b/src/regress/ttyname/check_ttyname.c
@@ -0,0 +1,122 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2013-2020, 2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+
+#include <sudo_compat.h>
+#include <sudo_fatal.h>
+#include <sudo_util.h>
+#include <sudo_debug.h>
+
+sudo_dso_public int main(int argc, char *argv[]);
+
+int sudo_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
+extern char *get_process_ttyname(char *name, size_t namelen);
+
+static int
+match_ttys(const char *tty1, const char *tty2)
+{
+ struct stat sb1, sb2;
+
+ if (tty1 != NULL && tty2 != NULL) {
+ if (strcmp(tty1, tty2) == 0)
+ return 0;
+ /* Could be the same device with a different name. */
+ if (stat(tty1, &sb1) == 0 && S_ISCHR(sb1.st_mode) &&
+ stat(tty2, &sb2) == 0 && S_ISCHR(sb2.st_mode)) {
+ if (sb1.st_rdev == sb2.st_rdev)
+ return 0;
+ }
+ } else if (tty1 == NULL && tty2 == NULL) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int
+main(int argc, char *argv[])
+{
+ char *tty_libc = NULL, *tty_sudo = NULL;
+ char pathbuf[PATH_MAX];
+ bool verbose = false;
+ int ch, errors = 0, ntests = 1;
+
+ initprogname(argc > 0 ? argv[0] : "check_ttyname");
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ verbose = true;
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", getprogname());
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* Lookup tty name using kernel info if possible. */
+ if (get_process_ttyname(pathbuf, sizeof(pathbuf)) != NULL)
+ tty_sudo = pathbuf;
+
+#if defined(HAVE_KINFO_PROC2_NETBSD) || \
+ defined(HAVE_KINFO_PROC_OPENBSD) || \
+ defined(HAVE_KINFO_PROC_FREEBSD) || \
+ defined(HAVE_KINFO_PROC_DFLY) || \
+ defined(HAVE_KINFO_PROC_44BSD) || \
+ defined(HAVE__TTYNAME_DEV) || defined(HAVE_STRUCT_PSINFO_PR_TTYDEV) || \
+ defined(HAVE_PSTAT_GETPROC) || defined(__linux__)
+
+ /* Lookup tty name attached to stdin via libc. */
+ tty_libc = ttyname(STDIN_FILENO);
+#endif
+
+ /* Compare libc and kernel ttys. */
+ if (match_ttys(tty_libc, tty_sudo) == 0) {
+ if (verbose)
+ printf("%s: OK (%s)\n", getprogname(), tty_sudo ? tty_sudo : "none");
+ } else if (tty_libc == NULL) {
+ if (verbose)
+ printf("%s: SKIP (%s)\n", getprogname(), tty_sudo ? tty_sudo : "none");
+ ntests = 0;
+ } else {
+ printf("%s: FAIL %s (sudo) vs. %s (libc)\n", getprogname(),
+ tty_sudo ? tty_sudo : "none", tty_libc ? tty_libc : "none");
+ errors++;
+ }
+
+ if (ntests != 0) {
+ printf("%s: %d tests run, %d errors, %d%% success rate\n",
+ getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);
+ }
+ return errors;
+}
diff --git a/src/selinux.c b/src/selinux.c
new file mode 100644
index 0000000..74bc571
--- /dev/null
+++ b/src/selinux.c
@@ -0,0 +1,515 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ * Copyright (c) 2008 Dan Walsh <dwalsh@redhat.com>
+ *
+ * Borrowed heavily from newrole source code
+ * Authors:
+ * Anthony Colatrella
+ * Tim Fraser
+ * Steve Grubb <sgrubb@redhat.com>
+ * Darrel Goeddel <DGoeddel@trustedcs.com>
+ * Michael Thompson <mcthomps@us.ibm.com>
+ * Dan Walsh <dwalsh@redhat.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_SELINUX
+
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include <selinux/selinux.h> /* for is_selinux_enabled() */
+#include <selinux/context.h> /* for context-mangling functions */
+#include <selinux/get_default_type.h>
+#include <selinux/get_context_list.h>
+
+#ifdef HAVE_LINUX_AUDIT
+# include <libaudit.h>
+#endif
+
+#include <sudo.h>
+#include <sudo_exec.h>
+
+static struct selinux_state {
+ char * old_context;
+ char * new_context;
+ char * tty_con_raw;
+ char * new_tty_con_raw;
+ const char *ttyn;
+ int ttyfd;
+ int enforcing;
+} se_state;
+
+int
+selinux_audit_role_change(void)
+{
+#ifdef HAVE_LINUX_AUDIT
+ int au_fd, rc = -1;
+ char *message;
+ debug_decl(selinux_audit_role_change, SUDO_DEBUG_SELINUX);
+
+ au_fd = audit_open();
+ if (au_fd == -1) {
+ /* Kernel may not have audit support. */
+ if (errno != EINVAL && errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT
+)
+ sudo_fatal("%s", U_("unable to open audit system"));
+ } else {
+ /* audit role change using the same format as newrole(1) */
+ rc = asprintf(&message, "newrole: old-context=%s new-context=%s",
+ se_state.old_context, se_state.new_context ? se_state.new_context : "?");
+ if (rc == -1)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ rc = audit_log_user_message(au_fd, AUDIT_USER_ROLE_CHANGE,
+ message, NULL, NULL, se_state.ttyn, se_state.new_context ? 1 : 0);
+ if (rc <= 0)
+ sudo_warn("%s", U_("unable to send audit message"));
+ free(message);
+ close(au_fd);
+ }
+
+ debug_return_int(rc);
+#else
+ return 0;
+#endif /* HAVE_LINUX_AUDIT */
+}
+
+/*
+ * This function attempts to revert the relabeling done to the tty.
+ * fd - referencing the opened ttyn
+ * ttyn - name of tty to restore
+ *
+ * Returns 0 on success and -1 on failure.
+ */
+int
+selinux_restore_tty(void)
+{
+ int ret = -1;
+ char * chk_tty_con_raw = NULL;
+ debug_decl(selinux_restore_tty, SUDO_DEBUG_SELINUX);
+
+ if (se_state.ttyfd == -1 || se_state.new_tty_con_raw == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: no tty, skip relabel",
+ __func__);
+ debug_return_int(0);
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: %s -> %s",
+ __func__, se_state.new_tty_con_raw, se_state.tty_con_raw);
+
+ /* Verify that the tty still has the context set by sudo. */
+ if (fgetfilecon_raw(se_state.ttyfd, &chk_tty_con_raw) == -1) {
+ sudo_warn(U_("unable to fgetfilecon %s"), se_state.ttyn);
+ goto skip_relabel;
+ }
+
+ if (strcmp(chk_tty_con_raw, se_state.new_tty_con_raw) != 0) {
+ sudo_warnx(U_("%s changed labels"), se_state.ttyn);
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: not restoring tty label, expected %s, have %s",
+ __func__, se_state.new_tty_con_raw, chk_tty_con_raw);
+ goto skip_relabel;
+ }
+
+ if (fsetfilecon_raw(se_state.ttyfd, se_state.tty_con_raw) == -1) {
+ sudo_warn(U_("unable to restore context for %s"), se_state.ttyn);
+ goto skip_relabel;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: successfully set tty label to %s",
+ __func__, se_state.tty_con_raw);
+ ret = 0;
+
+skip_relabel:
+ if (se_state.ttyfd != -1) {
+ close(se_state.ttyfd);
+ se_state.ttyfd = -1;
+ }
+ freecon(chk_tty_con_raw);
+ debug_return_int(ret);
+}
+
+/*
+ * This function attempts to relabel the tty. If this function fails, then
+ * the contexts are free'd and -1 is returned. On success, 0 is returned
+ * and tty_con_raw and new_tty_con_raw are set.
+ *
+ * This function will not fail if it can not relabel the tty when selinux is
+ * in permissive mode.
+ */
+int
+selinux_relabel_tty(const char *ttyn, int ptyfd)
+{
+ char * tty_con = NULL;
+ char * new_tty_con = NULL;
+ struct stat sb;
+ int fd;
+ debug_decl(relabel_tty, SUDO_DEBUG_SELINUX);
+
+ se_state.ttyfd = ptyfd;
+
+ /* It is perfectly legal to have no tty. */
+ if (ptyfd == -1 && ttyn == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: no tty, skip relabel",
+ __func__);
+ debug_return_int(0);
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: relabeling tty %s", __func__, ttyn);
+
+ /* If sudo is not allocating a pty for the command, open current tty. */
+ if (ptyfd == -1) {
+ se_state.ttyfd = open(ttyn, O_RDWR|O_NOCTTY|O_NONBLOCK);
+ if (se_state.ttyfd == -1 || fstat(se_state.ttyfd, &sb) == -1) {
+ sudo_warn(U_("unable to open %s, not relabeling tty"), ttyn);
+ goto bad;
+ }
+ if (!S_ISCHR(sb.st_mode)) {
+ sudo_warn(U_("%s is not a character device, not relabeling tty"),
+ ttyn);
+ goto bad;
+ }
+ (void)fcntl(se_state.ttyfd, F_SETFL,
+ fcntl(se_state.ttyfd, F_GETFL, 0) & ~O_NONBLOCK);
+ }
+
+ if (fgetfilecon(se_state.ttyfd, &tty_con) == -1) {
+ sudo_warn("%s", U_("unable to get current tty context, not relabeling tty"));
+ goto bad;
+ }
+
+ if (tty_con != NULL) {
+ security_class_t tclass = string_to_security_class("chr_file");
+ if (tclass == 0) {
+ sudo_warn("%s", U_("unknown security class \"chr_file\", not relabeling tty"));
+ goto bad;
+ }
+ if (security_compute_relabel(se_state.new_context, tty_con,
+ tclass, &new_tty_con) == -1) {
+ sudo_warn("%s", U_("unable to get new tty context, not relabeling tty"));
+ goto bad;
+ }
+ }
+
+ if (new_tty_con != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: tty context %s -> %s",
+ __func__, tty_con, new_tty_con);
+ if (fsetfilecon(se_state.ttyfd, new_tty_con) == -1) {
+ sudo_warn("%s", U_("unable to set new tty context"));
+ goto bad;
+ }
+ }
+
+ if (ptyfd != -1) {
+ int oflags, flags = 0;
+
+ /* Reopen pty that was relabeled, std{in,out,err} are reset later. */
+ se_state.ttyfd = open(ttyn, O_RDWR|O_NOCTTY, 0);
+ if (se_state.ttyfd == -1 || fstat(se_state.ttyfd, &sb) == -1) {
+ sudo_warn(U_("unable to open %s"), ttyn);
+ goto bad;
+ }
+ if (!S_ISCHR(sb.st_mode)) {
+ sudo_warn(U_("%s is not a character device, not relabeling tty"),
+ ttyn);
+ goto bad;
+ }
+ /* Preserve O_NONBLOCK and the close-on-exec flags. */
+ if ((oflags = fcntl(ptyfd, F_GETFL)) == -1) {
+ sudo_warn("F_GETFL");
+ goto bad;
+ }
+ if (ISSET(oflags, O_NONBLOCK))
+ flags |= O_NONBLOCK;
+ if ((oflags = fcntl(ptyfd, F_GETFD)) == -1) {
+ sudo_warn("F_GETFD");
+ goto bad;
+ }
+ if (ISSET(oflags, FD_CLOEXEC))
+ flags |= O_CLOEXEC;
+ if (dup3(se_state.ttyfd, ptyfd, flags) == -1) {
+ sudo_warn("dup3");
+ goto bad;
+ }
+ } else {
+ /* Re-open tty to get new label and reset std{in,out,err} */
+ close(se_state.ttyfd);
+ se_state.ttyfd = open(ttyn, O_RDWR|O_NOCTTY|O_NONBLOCK);
+ if (se_state.ttyfd == -1 || fstat(se_state.ttyfd, &sb) == -1) {
+ sudo_warn(U_("unable to open %s"), ttyn);
+ goto bad;
+ }
+ if (!S_ISCHR(sb.st_mode)) {
+ sudo_warn(U_("%s is not a character device, not relabeling tty"),
+ ttyn);
+ goto bad;
+ }
+ (void)fcntl(se_state.ttyfd, F_SETFL,
+ fcntl(se_state.ttyfd, F_GETFL, 0) & ~O_NONBLOCK);
+ for (fd = STDIN_FILENO; fd <= STDERR_FILENO; fd++) {
+ if (sudo_isatty(fd, &sb) && dup2(se_state.ttyfd, fd) == -1) {
+ sudo_warn("dup2");
+ goto bad;
+ }
+ }
+ }
+ /* Retain se_state.ttyfd so we can restore label when command finishes. */
+ (void)fcntl(se_state.ttyfd, F_SETFD, FD_CLOEXEC);
+
+ se_state.ttyn = ttyn;
+ if (selinux_trans_to_raw_context(tty_con, &se_state.tty_con_raw) == -1)
+ goto bad;
+ if (selinux_trans_to_raw_context(new_tty_con, &se_state.new_tty_con_raw) == -1)
+ goto bad;
+ freecon(tty_con);
+ freecon(new_tty_con);
+ debug_return_int(0);
+
+bad:
+ if (se_state.ttyfd != -1 && se_state.ttyfd != ptyfd) {
+ close(se_state.ttyfd);
+ se_state.ttyfd = -1;
+ }
+ freecon(se_state.tty_con_raw);
+ se_state.tty_con_raw = NULL;
+ freecon(se_state.new_tty_con_raw);
+ se_state.new_tty_con_raw = NULL;
+ freecon(tty_con);
+ freecon(new_tty_con);
+ debug_return_int(se_state.enforcing ? -1 : 0);
+}
+
+/*
+ * Determine the new security context based on the old context and the
+ * specified role and type.
+ * Returns 0 on success, and -1 on failure.
+ */
+static int
+get_exec_context(const char *role, const char *type)
+{
+ char *new_context = NULL;
+ context_t context = NULL;
+ char *typebuf = NULL;
+ int ret = -1;
+ debug_decl(get_exec_context, SUDO_DEBUG_SELINUX);
+
+ if (role == NULL) {
+ sudo_warnx(U_("you must specify a role for type %s"), type);
+ errno = EINVAL;
+ goto done;
+ }
+ if (type == NULL) {
+ if (get_default_type(role, &typebuf)) {
+ sudo_warnx(U_("unable to get default type for role %s"), role);
+ errno = EINVAL;
+ goto done;
+ }
+ type = typebuf;
+ }
+
+ /*
+ * Expand old_context into a context_t so that we can extract and modify
+ * its components easily.
+ */
+ if ((context = context_new(se_state.old_context)) == NULL) {
+ sudo_warn("%s", U_("failed to get new context"));
+ goto done;
+ }
+
+ /*
+ * Replace the role and type in "context" with the role and
+ * type we will be running the command as.
+ */
+ if (context_role_set(context, role)) {
+ sudo_warn(U_("failed to set new role %s"), role);
+ goto done;
+ }
+ if (context_type_set(context, type)) {
+ sudo_warn(U_("failed to set new type %s"), type);
+ goto done;
+ }
+
+ /*
+ * Convert "context" back into a string and verify it.
+ */
+ if ((new_context = strdup(context_str(context))) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ if (security_check_context(new_context) == -1) {
+ sudo_warnx(U_("%s is not a valid context"), new_context);
+ errno = EINVAL;
+ goto done;
+ }
+
+ se_state.new_context = new_context;
+ new_context = NULL;
+ ret = 0;
+
+done:
+ free(typebuf);
+ context_free(context);
+ freecon(new_context);
+ debug_return_int(ret);
+}
+
+/*
+ * Determine the exec and tty contexts the command will run in.
+ * Returns 0 on success and -1 on failure.
+ */
+int
+selinux_getexeccon(const char *role, const char *type)
+{
+ int ret = -1;
+ debug_decl(selinux_getexeccon, SUDO_DEBUG_SELINUX);
+
+ /* Store the caller's SID in old_context. */
+ if (getprevcon(&se_state.old_context)) {
+ sudo_warn("%s", U_("failed to get old context"));
+ goto done;
+ }
+
+ se_state.enforcing = security_getenforce();
+ if (se_state.enforcing == -1) {
+ sudo_warn("%s", U_("unable to determine enforcing mode."));
+ goto done;
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: old context %s", __func__,
+ se_state.old_context);
+ ret = get_exec_context(role, type);
+ if (ret == -1) {
+ /* Audit role change failure (success is logged later). */
+ selinux_audit_role_change();
+ goto done;
+ }
+ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: new context %s", __func__,
+ se_state.new_context);
+
+done:
+ debug_return_int(ret);
+}
+
+int
+selinux_setexeccon(void)
+{
+ debug_decl(selinux_setexeccon, SUDO_DEBUG_SELINUX);
+
+ if (setexeccon(se_state.new_context)) {
+ sudo_warn(U_("unable to set exec context to %s"), se_state.new_context);
+ if (se_state.enforcing)
+ debug_return_int(-1);
+ }
+
+#ifdef HAVE_SETKEYCREATECON
+ if (setkeycreatecon(se_state.new_context)) {
+ sudo_warn(U_("unable to set key creation context to %s"), se_state.new_context);
+ if (se_state.enforcing)
+ debug_return_int(-1);
+ }
+#endif /* HAVE_SETKEYCREATECON */
+
+ debug_return_int(0);
+}
+
+void
+selinux_execve(int fd, const char *path, char *const argv[], char *envp[],
+ const char *rundir, unsigned int flags)
+{
+ char **nargv;
+ const char *sesh;
+ int argc, len, nargc, serrno;
+ debug_decl(selinux_execve, SUDO_DEBUG_SELINUX);
+
+ sesh = sudo_conf_sesh_path();
+ if (sesh == NULL) {
+ sudo_warnx("internal error: sesh path not set");
+ errno = EINVAL;
+ debug_return;
+ }
+
+ /* Set SELinux exec and keycreate contexts. */
+ if (selinux_setexeccon() == -1)
+ debug_return;
+
+ /*
+ * Build new argv with sesh as argv[0].
+ */
+ for (argc = 0; argv[argc] != NULL; argc++)
+ continue;
+ if (argc == 0) {
+ errno = EINVAL;
+ debug_return;
+ }
+ nargv = reallocarray(NULL, 5 + argc + 1, sizeof(char *));
+ if (nargv == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return;
+ }
+ if (*argv[0] == '-')
+ nargv[0] = (char *)"-sesh";
+ else
+ nargv[0] = (char *)"sesh";
+ nargc = 1;
+ if (ISSET(flags, CD_RBAC_SET_CWD)) {
+ const char *prefix = ISSET(flags, CD_CWD_OPTIONAL) ? "+" : "";
+ if (rundir == NULL) {
+ sudo_warnx("internal error: sesh rundir not set");
+ errno = EINVAL;
+ debug_return;
+ }
+ len = asprintf(&nargv[nargc++], "--directory=%s%s", prefix, rundir);
+ if (len == -1) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return;
+ }
+ }
+ if (fd != -1) {
+ len = asprintf(&nargv[nargc++], "--execfd=%d", fd);
+ if (len == -1) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return;
+ }
+ }
+ if (ISSET(flags, CD_NOEXEC)) {
+ CLR(flags, CD_NOEXEC);
+ nargv[nargc++] = (char *)"--noexec";
+ }
+ nargv[nargc++] = (char *)"--";
+ nargv[nargc++] = (char *)path;
+ memcpy(&nargv[nargc], &argv[1], argc * sizeof(char *)); /* copies NULL */
+
+ sudo_execve(-1, sesh, nargv, envp, -1, flags);
+ serrno = errno;
+ free(nargv);
+ errno = serrno;
+ debug_return;
+}
+
+#endif /* HAVE_SELINUX */
diff --git a/src/sesh.c b/src/sesh.c
new file mode 100644
index 0000000..44faa11
--- /dev/null
+++ b/src/sesh.c
@@ -0,0 +1,489 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2008, 2010-2018, 2020-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <time.h>
+#include <unistd.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#ifdef HAVE_GETOPT_LONG
+# include <getopt.h>
+# else
+# include <compat/getopt.h>
+#endif /* HAVE_GETOPT_LONG */
+
+#include <sudo.h>
+#include <sudo_exec.h>
+#include <sudo_edit.h>
+
+enum sesh_mode {
+ SESH_RUN_COMMAND,
+ SESH_EDIT_CREATE,
+ SESH_EDIT_INSTALL
+};
+
+static const char short_opts[] = "+cd:e:ihnw:";
+static struct option long_opts[] = {
+ { "edit-create", no_argument, NULL, 'c' },
+ { "directory", required_argument, NULL, 'd' },
+ { "execfd", required_argument, NULL, 'e' },
+ { "edit-install", no_argument, NULL, 'i' },
+ { "no-dereference", no_argument, NULL, 'h' },
+ { "noexec", no_argument, NULL, 'n' },
+ { "edit-checkdir", required_argument, NULL, 'w' },
+ { NULL, no_argument, NULL, '\0' },
+};
+
+sudo_dso_public int main(int argc, char *argv[], char *envp[]);
+
+static int sesh_sudoedit(enum sesh_mode mode, int flags, char *user, int argc,
+ char *argv[]);
+
+sudo_noreturn void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: %s [-n] [-d directory] [-e fd] command [...]\n"
+ " %s [-cih] [-w uid:gids] file [...]\n",
+ getprogname(), getprogname());
+ exit(EXIT_FAILURE);
+}
+
+/*
+ * Exit codes defined in sudo_exec.h:
+ * SESH_SUCCESS (0) ... successful operation
+ * SESH_ERR_FAILURE (1) ... unspecified error
+ * SESH_ERR_INVALID (30) ... invalid -e arg value
+ * SESH_ERR_BAD_PATHS (31) ... odd number of paths
+ * SESH_ERR_NO_FILES (32) ... copy error, no files copied
+ * SESH_ERR_SOME_FILES (33) ... copy error, no files copied
+ */
+int
+main(int argc, char *argv[], char *envp[])
+{
+ enum sesh_mode mode = SESH_RUN_COMMAND;
+ const char *errstr, *rundir = NULL;
+ unsigned int flags = CD_SUDOEDIT_FOLLOW;
+ char *edit_user = NULL;
+ int ch, ret, fd = -1;
+ debug_decl(main, SUDO_DEBUG_MAIN);
+
+ initprogname(argc > 0 ? argv[0] : "sesh");
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE_NAME, LOCALEDIR);
+ textdomain(PACKAGE_NAME);
+
+ while ((ch = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
+ switch (ch) {
+ case 'c':
+ if (mode != SESH_RUN_COMMAND) {
+ sudo_warnx("%s",
+ U_("Only one of the -c or -i options may be specified"));
+ usage();
+ }
+ mode = SESH_EDIT_CREATE;
+ break;
+ case 'd':
+ rundir = optarg;
+ if (*rundir == '+') {
+ SET(flags, CD_CWD_OPTIONAL);
+ rundir++;
+ }
+ break;
+ case 'e':
+ fd = sudo_strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr != NULL)
+ sudo_fatalx(U_("invalid file descriptor number: %s"), optarg);
+ break;
+ case 'i':
+ if (mode != SESH_RUN_COMMAND) {
+ sudo_warnx("%s",
+ U_("Only one of the -c or -i options may be specified"));
+ usage();
+ }
+ mode = SESH_EDIT_INSTALL;
+ break;
+ case 'h':
+ CLR(flags, CD_SUDOEDIT_FOLLOW);
+ break;
+ case 'n':
+ SET(flags, CD_NOEXEC);
+ break;
+ case 'w':
+ SET(flags, CD_SUDOEDIT_CHECKDIR);
+ edit_user = optarg;
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc == 0)
+ usage();
+
+ /* Read sudo.conf and initialize the debug subsystem. */
+ if (sudo_conf_read(NULL, SUDO_CONF_DEBUG) == -1)
+ return EXIT_FAILURE;
+ sudo_debug_register(getprogname(), NULL, NULL,
+ sudo_conf_debug_files(getprogname()), -1);
+
+ if (mode != SESH_RUN_COMMAND) {
+ if (rundir != NULL) {
+ sudo_warnx(U_("The -%c option may not be used in edit mode."), 'd');
+ usage();
+ }
+ if (fd != -1) {
+ sudo_warnx(U_("The -%c option may not be used in edit mode."), 'e');
+ usage();
+ }
+ if (ISSET(flags, CD_NOEXEC)) {
+ sudo_warnx(U_("The -%c option may not be used in edit mode."), 'n');
+ usage();
+ }
+ ret = sesh_sudoedit(mode, flags, edit_user, argc, argv);
+ } else {
+ bool login_shell;
+ char *cmnd;
+
+ if (!ISSET(flags, CD_SUDOEDIT_FOLLOW)) {
+ sudo_warnx(U_("The -%c option may only be used in edit mode."),
+ 'h');
+ usage();
+ }
+ if (edit_user != NULL) {
+ sudo_warnx(U_("The -%c option may only be used in edit mode."),
+ 'w');
+ usage();
+ }
+
+ /* If the first char of argv[0] is '-', we are running a login shell. */
+ login_shell = argv[0][0] == '-';
+
+ /* We must change the directory in sesh after the context changes. */
+ if (rundir != NULL && chdir(rundir) == -1) {
+ sudo_warnx(U_("unable to change directory to %s"), rundir);
+ if (!ISSET(flags, CD_CWD_OPTIONAL))
+ return EXIT_FAILURE;
+ }
+
+ /* Make a copy of the command to execute. */
+ if ((cmnd = strdup(argv[0])) == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ /* If invoked as a login shell, modify argv[0] accordingly. */
+ if (login_shell) {
+ char *cp = strrchr(argv[0], '/');
+ if (cp != NULL) {
+ *cp = '-';
+ argv[0] = cp;
+ }
+ }
+ sudo_execve(fd, cmnd, argv, envp, -1, flags);
+ sudo_warn(U_("unable to execute %s"), cmnd);
+ ret = SESH_ERR_FAILURE;
+ }
+ sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, ret);
+ _exit(ret);
+}
+
+/*
+ * Destructively parse a string in the format:
+ * uid:gid:groups,...
+ *
+ * On success, fills in ud and returns true, else false.
+ */
+static bool
+parse_user(char *userstr, struct sudo_cred *cred)
+{
+ char *cp, *ep;
+ const char *errstr;
+ debug_decl(parse_user, SUDO_DEBUG_EDIT);
+
+ /* UID */
+ cp = userstr;
+ if ((ep = strchr(cp, ':')) == NULL) {
+ sudo_warnx(U_("%s: %s"), cp, U_("invalid value"));
+ debug_return_bool(false);
+ }
+ *ep++ = '\0';
+ cred->uid = cred->euid = sudo_strtoid(cp, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), cp, errstr);
+ debug_return_bool(false);
+ }
+
+ /* GID */
+ cp = ep;
+ if ((ep = strchr(cp, ':')) == NULL) {
+ sudo_warnx(U_("%s: %s"), cp, U_("invalid value"));
+ debug_return_bool(false);
+ }
+ *ep++ = '\0';
+ cred->gid = cred->egid = sudo_strtoid(cp, &errstr);
+ if (errstr != NULL) {
+ sudo_warnx(U_("%s: %s"), cp, errstr);
+ debug_return_bool(false);
+ }
+
+ /* group vector */
+ cp = ep;
+ cred->ngroups = sudo_parse_gids(cp, NULL, &cred->groups);
+ if (cred->ngroups == -1)
+ debug_return_bool(false);
+
+ debug_return_bool(true);
+}
+
+static int
+sesh_edit_create_tfiles(int edit_flags, struct sudo_cred *user_cred,
+ struct sudo_cred *run_cred, int argc, char *argv[])
+{
+ int i, fd_src = -1, fd_dst = -1;
+ struct timespec times[2];
+ struct stat sb;
+ debug_decl(sesh_edit_create_tfiles, SUDO_DEBUG_EDIT);
+
+ for (i = 0; i < argc - 1; i += 2) {
+ char *path_src = argv[i];
+ const char *path_dst = argv[i + 1];
+
+ /*
+ * Try to open the source file for reading.
+ * If it doesn't exist, we'll create an empty destination file.
+ */
+ fd_src = sudo_edit_open(path_src, O_RDONLY,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, edit_flags, user_cred, run_cred);
+ if (fd_src == -1) {
+ if (errno != ENOENT) {
+ if (errno == ELOOP) {
+ sudo_warnx(U_("%s: editing symbolic links is not "
+ "permitted"), path_src);
+ } else if (errno == EISDIR) {
+ sudo_warnx(U_("%s: editing files in a writable directory "
+ "is not permitted"), path_src);
+ } else {
+ sudo_warn("%s", path_src);
+ }
+ goto cleanup;
+ }
+ /* New file, verify parent dir exists and is not writable. */
+ if (!sudo_edit_parent_valid(path_src, edit_flags, user_cred, run_cred))
+ goto cleanup;
+ }
+ if (fd_src == -1) {
+ /* New file. */
+ memset(&sb, 0, sizeof(sb));
+ } else if (fstat(fd_src, &sb) == -1 || !S_ISREG(sb.st_mode)) {
+ sudo_warnx(U_("%s: not a regular file"), path_src);
+ goto cleanup;
+ }
+
+ /*
+ * Create temporary file using O_EXCL to ensure that temporary
+ * files are created by us and that we do not open any symlinks.
+ */
+ fd_dst = open(path_dst, O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
+ if (fd_dst == -1) {
+ sudo_warn("%s", path_dst);
+ goto cleanup;
+ }
+
+ if (fd_src != -1) {
+ if (sudo_copy_file(path_src, fd_src, -1, path_dst, fd_dst, -1) == -1)
+ goto cleanup;
+ close(fd_src);
+ }
+
+ /* Make mtime on temp file match src (sb filled in above). */
+ mtim_get(&sb, times[0]);
+ times[1].tv_sec = times[0].tv_sec;
+ times[1].tv_nsec = times[0].tv_nsec;
+ if (futimens(fd_dst, times) == -1) {
+ if (utimensat(AT_FDCWD, path_dst, times, 0) == -1)
+ sudo_warn("%s", path_dst);
+ }
+ close(fd_dst);
+ fd_dst = -1;
+ }
+ debug_return_int(SESH_SUCCESS);
+
+cleanup:
+ /* Remove temporary files. */
+ for (i = 0; i < argc - 1; i += 2)
+ unlink(argv[i + 1]);
+ if (fd_src != -1)
+ close(fd_src);
+ if (fd_dst != -1)
+ close(fd_dst);
+ debug_return_int(SESH_ERR_NO_FILES);
+}
+
+static int
+sesh_edit_copy_tfiles(int edit_flags, struct sudo_cred *user_cred,
+ struct sudo_cred *run_cred, int argc, char *argv[])
+{
+ int i, ret = SESH_SUCCESS;
+ int fd_src = -1, fd_dst = -1;
+ debug_decl(sesh_edit_copy_tfiles, SUDO_DEBUG_EDIT);
+
+ for (i = 0; i < argc - 1; i += 2) {
+ const char *path_src = argv[i];
+ char *path_dst = argv[i + 1];
+ off_t len_src, len_dst;
+ struct stat sb;
+
+ /* Open temporary file for reading. */
+ if (fd_src != -1)
+ close(fd_src);
+ fd_src = open(path_src, O_RDONLY|O_NONBLOCK|O_NOFOLLOW);
+ if (fd_src == -1) {
+ sudo_warn("%s", path_src);
+ ret = SESH_ERR_SOME_FILES;
+ continue;
+ }
+ /* Make sure the temporary file is safe and has the proper owner. */
+ if (!sudo_check_temp_file(fd_src, path_src, run_cred->uid, &sb)) {
+ sudo_warnx(U_("contents of edit session left in %s"), path_src);
+ ret = SESH_ERR_SOME_FILES;
+ continue;
+ }
+ (void) fcntl(fd_src, F_SETFL, fcntl(fd_src, F_GETFL, 0) & ~O_NONBLOCK);
+
+ /* Create destination file. */
+ if (fd_dst != -1)
+ close(fd_dst);
+ fd_dst = sudo_edit_open(path_dst, O_WRONLY|O_CREAT,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, edit_flags, user_cred, run_cred);
+ if (fd_dst == -1) {
+ if (errno == ELOOP) {
+ sudo_warnx(U_("%s: editing symbolic links is not "
+ "permitted"), path_dst);
+ } else if (errno == EISDIR) {
+ sudo_warnx(U_("%s: editing files in a writable directory "
+ "is not permitted"), path_dst);
+ } else {
+ sudo_warn("%s", path_dst);
+ }
+ sudo_warnx(U_("contents of edit session left in %s"), path_src);
+ ret = SESH_ERR_SOME_FILES;
+ continue;
+ }
+
+ /* sudo_check_temp_file() filled in sb for us. */
+ len_src = sb.st_size;
+ if (fstat(fd_dst, &sb) != 0) {
+ sudo_warn("%s", path_dst);
+ sudo_warnx(U_("contents of edit session left in %s"), path_src);
+ ret = SESH_ERR_SOME_FILES;
+ continue;
+ }
+ len_dst = sb.st_size;
+
+ if (sudo_copy_file(path_src, fd_src, len_src, path_dst, fd_dst,
+ len_dst) == -1) {
+ sudo_warnx(U_("contents of edit session left in %s"), path_src);
+ ret = SESH_ERR_SOME_FILES;
+ continue;
+ }
+ unlink(path_src);
+ }
+ if (fd_src != -1)
+ close(fd_src);
+ if (fd_dst != -1)
+ close(fd_dst);
+
+ debug_return_int(ret);
+}
+
+static int
+sesh_sudoedit(enum sesh_mode mode, int flags, char *user,
+ int argc, char *argv[])
+{
+ struct sudo_cred user_cred, run_cred;
+ int ret;
+ debug_decl(sesh_sudoedit, SUDO_DEBUG_EDIT);
+
+ memset(&user_cred, 0, sizeof(user_cred));
+ memset(&run_cred, 0, sizeof(run_cred));
+
+ /* Parse user for -w option, "uid:gid:gid1,gid2,..." */
+ if (user != NULL && !parse_user(user, &user_cred))
+ debug_return_int(SESH_ERR_FAILURE);
+
+ /* No files specified, nothing to do. */
+ if (argc == 0)
+ debug_return_int(SESH_SUCCESS);
+
+ /* Odd number of paths specified. */
+ if (argc & 1)
+ debug_return_int(SESH_ERR_BAD_PATHS);
+
+ /* Masquerade as sudoedit so the user gets consistent error messages. */
+ setprogname("sudoedit");
+
+ /*
+ * sudoedit runs us with the effective user-ID and group-ID of
+ * the target user as well as with the target user's group list.
+ */
+ run_cred.uid = run_cred.euid = geteuid();
+ run_cred.gid = run_cred.egid = getegid();
+ run_cred.ngroups = getgroups(0, NULL); // -V575
+ if (run_cred.ngroups > 0) {
+ run_cred.groups = reallocarray(NULL, run_cred.ngroups,
+ sizeof(GETGROUPS_T));
+ if (run_cred.groups == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ debug_return_int(SESH_ERR_FAILURE);
+ }
+ run_cred.ngroups = getgroups(run_cred.ngroups, run_cred.groups);
+ if (run_cred.ngroups < 0) {
+ sudo_warn("%s", U_("unable to get group list"));
+ free(run_cred.groups);
+ debug_return_int(SESH_ERR_FAILURE);
+ }
+ } else {
+ run_cred.ngroups = 0;
+ run_cred.groups = NULL;
+ }
+
+ ret = mode == SESH_EDIT_CREATE ?
+ sesh_edit_create_tfiles(flags, &user_cred, &run_cred, argc, argv) :
+ sesh_edit_copy_tfiles(flags, &user_cred, &run_cred, argc, argv);
+ debug_return_int(ret);
+}
diff --git a/src/signal.c b/src/signal.c
new file mode 100644
index 0000000..59cb5f4
--- /dev/null
+++ b/src/signal.c
@@ -0,0 +1,196 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2016 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <sudo.h>
+#include <sudo_exec.h>
+
+static struct signal_state {
+ int signo;
+ int restore;
+ struct sigaction sa;
+} saved_signals[] = {
+ { SIGALRM }, /* SAVED_SIGALRM */
+ { SIGCHLD }, /* SAVED_SIGCHLD */
+ { SIGCONT }, /* SAVED_SIGCONT */
+ { SIGHUP }, /* SAVED_SIGHUP */
+ { SIGINT }, /* SAVED_SIGINT */
+ { SIGPIPE }, /* SAVED_SIGPIPE */
+ { SIGQUIT }, /* SAVED_SIGQUIT */
+ { SIGTERM }, /* SAVED_SIGTERM */
+ { SIGTSTP }, /* SAVED_SIGTSTP */
+ { SIGTTIN }, /* SAVED_SIGTTIN */
+ { SIGTTOU }, /* SAVED_SIGTTOU */
+ { SIGUSR1 }, /* SAVED_SIGUSR1 */
+ { SIGUSR2 }, /* SAVED_SIGUSR2 */
+ { -1 }
+};
+
+static sig_atomic_t pending_signals[NSIG];
+
+static void
+sudo_handler(int signo)
+{
+ /* Mark signal as pending. */
+ pending_signals[signo] = 1;
+}
+
+bool
+signal_pending(int signo)
+{
+ return pending_signals[signo] == 1;
+}
+
+/*
+ * Save signal handler state so it can be restored before exec.
+ */
+void
+save_signals(void)
+{
+ struct signal_state *ss;
+ debug_decl(save_signals, SUDO_DEBUG_MAIN);
+
+ for (ss = saved_signals; ss->signo != -1; ss++) {
+ if (sigaction(ss->signo, NULL, &ss->sa) != 0)
+ sudo_warn(U_("unable to save handler for signal %d"), ss->signo);
+ }
+
+ debug_return;
+}
+
+/*
+ * Restore signal handlers to initial state for exec.
+ */
+void
+restore_signals(void)
+{
+ struct signal_state *ss;
+ debug_decl(restore_signals, SUDO_DEBUG_MAIN);
+
+ for (ss = saved_signals; ss->signo != -1; ss++) {
+ if (ss->restore) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "restoring handler for signal %d: %s", ss->signo,
+ ss->sa.sa_handler == SIG_IGN ? "SIG_IGN" :
+ ss->sa.sa_handler == SIG_DFL ? "SIG_DFL" : "???");
+ if (sigaction(ss->signo, &ss->sa, NULL) != 0) {
+ sudo_warn(U_("unable to restore handler for signal %d"),
+ ss->signo);
+ }
+ }
+ }
+
+ debug_return;
+}
+
+/*
+ * Trap tty-generated (and other) signals so we can't be killed before
+ * calling the policy close function. The signal pipe will be drained
+ * in sudo_execute() before running the command and new handlers will
+ * be installed in the parent.
+ */
+void
+init_signals(void)
+{
+ struct sigaction sa;
+ struct signal_state *ss;
+ debug_decl(init_signals, SUDO_DEBUG_MAIN);
+
+ memset(&sa, 0, sizeof(sa));
+ sigfillset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = sudo_handler;
+
+ for (ss = saved_signals; ss->signo > 0; ss++) {
+ switch (ss->signo) {
+ case SIGCONT:
+ case SIGPIPE:
+ case SIGTTIN:
+ case SIGTTOU:
+ /* Don't install these until exec time. */
+ break;
+ case SIGCHLD:
+ /* Sudo needs to be able to catch SIGCHLD. */
+ if (ss->sa.sa_handler == SIG_IGN) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "will restore signal %d on exec", SIGCHLD);
+ ss->restore = true;
+ }
+ if (sigaction(SIGCHLD, &sa, NULL) != 0) {
+ sudo_warn(U_("unable to set handler for signal %d"),
+ SIGCHLD);
+ }
+ break;
+ default:
+ if (ss->sa.sa_handler != SIG_IGN) {
+ if (sigaction(ss->signo, &sa, NULL) != 0) {
+ sudo_warn(U_("unable to set handler for signal %d"),
+ ss->signo);
+ }
+ }
+ break;
+ }
+ }
+ /* Ignore SIGPIPE until exec. */
+ if (saved_signals[SAVED_SIGPIPE].sa.sa_handler != SIG_IGN) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "will restore signal %d on exec", SIGPIPE);
+ saved_signals[SAVED_SIGPIPE].restore = true;
+ sa.sa_handler = SIG_IGN;
+ if (sigaction(SIGPIPE, &sa, NULL) != 0)
+ sudo_warn(U_("unable to set handler for signal %d"), SIGPIPE);
+ }
+
+ debug_return;
+}
+
+/*
+ * Like sigaction() but sets restore flag in saved_signals[]
+ * if needed.
+ */
+int
+sudo_sigaction(int signo, struct sigaction *sa, struct sigaction *osa)
+{
+ struct signal_state *ss;
+ int ret;
+ debug_decl(sudo_sigaction, SUDO_DEBUG_MAIN);
+
+ for (ss = saved_signals; ss->signo > 0; ss++) {
+ if (ss->signo == signo) {
+ /* If signal was or now is ignored, restore old handler on exec. */
+ if (ss->sa.sa_handler == SIG_IGN || sa->sa_handler == SIG_IGN) {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "will restore signal %d on exec", signo);
+ ss->restore = true;
+ }
+ break;
+ }
+ }
+ ret = sigaction(signo, sa, osa);
+
+ debug_return_int(ret);
+}
diff --git a/src/solaris.c b/src/solaris.c
new file mode 100644
index 0000000..49cc6eb
--- /dev/null
+++ b/src/solaris.c
@@ -0,0 +1,117 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#ifdef HAVE_PROJECT_H
+# include <project.h>
+# include <sys/task.h>
+# include <errno.h>
+# include <pwd.h>
+#endif
+
+#include <sudo.h>
+#include <sudo_dso.h>
+
+int
+os_init(int argc, char *argv[], char *envp[])
+{
+ /*
+ * Solaris 11 is unable to load the per-locale shared objects
+ * without this. We must keep the handle open for it to work.
+ * This bug was fixed in Solaris 11 Update 1.
+ */
+ void *handle = sudo_dso_load("/usr/lib/locale/common/methods_unicode.so.3",
+ SUDO_DSO_LAZY|SUDO_DSO_GLOBAL);
+ (void)&handle;
+
+ return os_init_common(argc, argv, envp);
+}
+
+#ifdef HAVE_PROJECT_H
+void
+set_project(struct passwd *pw)
+{
+ struct project proj;
+ char buf[PROJECT_BUFSZ];
+ int errval;
+ debug_decl(set_project, SUDO_DEBUG_UTIL);
+
+ /*
+ * Collect the default project for the user and settaskid
+ */
+ setprojent();
+ if (getdefaultproj(pw->pw_name, &proj, buf, sizeof(buf)) != NULL) {
+ errval = setproject(proj.pj_name, pw->pw_name, TASK_NORMAL);
+ switch(errval) {
+ case 0:
+ break;
+ case SETPROJ_ERR_TASK:
+ switch (errno) {
+ case EAGAIN:
+ sudo_warnx("%s", U_("resource control limit has been reached"));
+ break;
+ case ESRCH:
+ sudo_warnx(U_("user \"%s\" is not a member of project \"%s\""),
+ pw->pw_name, proj.pj_name);
+ break;
+ case EACCES:
+ sudo_warnx("%s", U_("the invoking task is final"));
+ break;
+ default:
+ sudo_warnx(U_("could not join project \"%s\""), proj.pj_name);
+ break;
+ }
+ break;
+ case SETPROJ_ERR_POOL:
+ switch (errno) {
+ case EACCES:
+ sudo_warnx(U_("no resource pool accepting default bindings "
+ "exists for project \"%s\""), proj.pj_name);
+ break;
+ case ESRCH:
+ sudo_warnx(U_("specified resource pool does not exist for "
+ "project \"%s\""), proj.pj_name);
+ break;
+ default:
+ sudo_warnx(U_("could not bind to default resource pool for "
+ "project \"%s\""), proj.pj_name);
+ break;
+ }
+ break;
+ default:
+ if (errval <= 0) {
+ sudo_warnx(U_("setproject failed for project \"%s\""), proj.pj_name);
+ } else {
+ sudo_warnx(U_("warning, resource control assignment failed for "
+ "project \"%s\""), proj.pj_name);
+ }
+ break;
+ }
+ } else {
+ sudo_warn("getdefaultproj");
+ }
+ endprojent();
+ debug_return;
+}
+#endif /* HAVE_PROJECT_H */
diff --git a/src/sudo.c b/src/sudo.c
new file mode 100644
index 0000000..9d929e4
--- /dev/null
+++ b/src/sudo.c
@@ -0,0 +1,2255 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#ifdef __TANDEM
+# include <floss.h>
+#endif
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+#ifdef __linux__
+# include <sys/prctl.h>
+#endif
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <grp.h>
+#include <pwd.h>
+#include <time.h>
+#ifdef HAVE_SELINUX
+# include <selinux/selinux.h> /* for is_selinux_enabled() */
+#endif
+#ifdef HAVE_SETAUTHDB
+# include <usersec.h>
+#endif /* HAVE_SETAUTHDB */
+#if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS)
+# ifdef __hpux
+# undef MAXINT
+# include <hpsecurity.h>
+# else
+# include <sys/security.h>
+# endif /* __hpux */
+# include <prot.h>
+#endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
+
+#include <sudo.h>
+#include <sudo_plugin.h>
+#include <sudo_plugin_int.h>
+
+/*
+ * Local variables
+ */
+struct plugin_container policy_plugin;
+struct plugin_container_list io_plugins = TAILQ_HEAD_INITIALIZER(io_plugins);
+struct plugin_container_list audit_plugins = TAILQ_HEAD_INITIALIZER(audit_plugins);
+struct plugin_container_list approval_plugins = TAILQ_HEAD_INITIALIZER(approval_plugins);
+int sudo_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
+static struct sudo_event_base *sudo_event_base;
+
+struct sudo_gc_entry {
+ SLIST_ENTRY(sudo_gc_entry) entries;
+ enum sudo_gc_types type;
+ union {
+ char **vec;
+ void *ptr;
+ } u;
+};
+SLIST_HEAD(sudo_gc_list, sudo_gc_entry);
+#ifdef NO_LEAKS
+static struct sudo_gc_list sudo_gc_list = SLIST_HEAD_INITIALIZER(sudo_gc_list);
+#endif
+
+/*
+ * Local functions
+ */
+static void fix_fds(void);
+static void sudo_check_suid(const char *path);
+static char **get_user_info(struct user_details *);
+static void command_info_to_details(char * const info[],
+ struct command_details *details);
+static void gc_init(void);
+
+/* Policy plugin convenience functions. */
+static void policy_open(void);
+static void policy_close(const char *cmnd, int exit_status, int error);
+static int policy_show_version(int verbose);
+static bool policy_check(int argc, char * const argv[], char *env_add[],
+ char **command_info[], char **run_argv[], char **run_envp[]);
+static void policy_list(int argc, char * const argv[],
+ int verbose, const char *user);
+static void policy_validate(char * const argv[]);
+static void policy_invalidate(int unlinkit);
+
+/* I/O log plugin convenience functions. */
+static bool iolog_open(char * const command_info[], int run_argc,
+ char * const run_argv[], char * const run_envp[]);
+static void iolog_close(int exit_status, int error);
+static void iolog_show_version(int verbose, int argc, char * const argv[],
+ char * const envp[]);
+static void unlink_plugin(struct plugin_container_list *plugin_list, struct plugin_container *plugin);
+static void free_plugin_container(struct plugin_container *plugin, bool ioplugin);
+
+/* Audit plugin convenience functions (some are public). */
+static void audit_open(void);
+static void audit_close(int exit_status, int error);
+static void audit_show_version(int verbose);
+
+/* Approval plugin convenience functions (some are public). */
+static void approval_show_version(int verbose);
+
+sudo_dso_public int main(int argc, char *argv[], char *envp[]);
+
+static struct sudo_settings *sudo_settings;
+static char * const *user_info, * const *submit_argv, * const *submit_envp;
+static int submit_optind;
+
+int
+main(int argc, char *argv[], char *envp[])
+{
+ struct command_details command_details;
+ struct user_details user_details;
+ unsigned int sudo_mode;
+ int nargc, status = 0;
+ char **nargv, **env_add;
+ char **command_info = NULL, **argv_out = NULL, **run_envp = NULL;
+ const char * const allowed_prognames[] = { "sudo", "sudoedit", NULL };
+ const char *list_user;
+ sigset_t mask;
+ debug_decl_vars(main, SUDO_DEBUG_MAIN);
+
+ /* Only allow "sudo" or "sudoedit" as the program name. */
+ initprogname2(argc > 0 ? argv[0] : "sudo", allowed_prognames);
+
+ /* Crank resource limits to unlimited. */
+ unlimit_sudo();
+
+ /* Make sure fds 0-2 are open and do OS-specific initialization. */
+ fix_fds();
+ os_init(argc, argv, envp);
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE_NAME, LOCALEDIR);
+ textdomain(PACKAGE_NAME);
+
+ (void) tzset();
+
+ /* Must be done before we do any password lookups */
+#if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS)
+ (void) set_auth_parameters(argc, argv);
+# ifdef HAVE_INITPRIVS
+ initprivs();
+# endif
+#endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */
+
+ /* Initialize the debug subsystem. */
+ if (sudo_conf_read(NULL, SUDO_CONF_DEBUG) == -1)
+ return EXIT_FAILURE;
+ sudo_debug_instance = sudo_debug_register(getprogname(),
+ NULL, NULL, sudo_conf_debug_files(getprogname()), -1);
+ if (sudo_debug_instance == SUDO_DEBUG_INSTANCE_ERROR)
+ return EXIT_FAILURE;
+
+ /* Make sure we are setuid root. */
+ sudo_check_suid(argc > 0 ? argv[0] : "sudo");
+
+ /* Save original signal state and setup default signal handlers. */
+ save_signals();
+ init_signals();
+
+ /* Reset signal mask to the default value (unblock). */
+ (void) sigemptyset(&mask);
+ (void) sigprocmask(SIG_SETMASK, &mask, NULL);
+
+ /* Parse the rest of sudo.conf. */
+ sudo_conf_read(NULL, SUDO_CONF_ALL & ~SUDO_CONF_DEBUG);
+
+ /* Fill in user_info with user name, uid, cwd, etc. */
+ if ((user_info = get_user_info(&user_details)) == NULL)
+ return EXIT_FAILURE; /* get_user_info printed error message */
+
+ /* Disable core dumps if not enabled in sudo.conf. */
+ if (sudo_conf_disable_coredump())
+ disable_coredump();
+
+ /* Parse command line arguments, preserving the original argv/envp. */
+ submit_argv = argv;
+ submit_envp = envp;
+ sudo_mode = parse_args(argc, argv, user_details.shell, &submit_optind,
+ &nargc, &nargv, &sudo_settings, &env_add, &list_user);
+ sudo_debug_printf(SUDO_DEBUG_DEBUG, "sudo_mode 0x%x", sudo_mode);
+
+ /* Print sudo version early, in case of plugin init failure. */
+ if (ISSET(sudo_mode, MODE_VERSION)) {
+ printf(_("Sudo version %s\n"), PACKAGE_VERSION);
+ if (user_details.cred.uid == ROOT_UID)
+ (void) printf(_("Configure options: %s\n"), CONFIGURE_ARGS);
+ }
+
+ /* Use conversation function for sudo_(warn|fatal)x? for plugins. */
+ sudo_warn_set_conversation(sudo_conversation);
+
+ /* Load plugins. */
+ if (!sudo_load_plugins())
+ sudo_fatalx("%s", U_("fatal error, unable to load plugins"));
+
+ /* Allocate event base so plugin can use it. */
+ if ((sudo_event_base = sudo_ev_base_alloc()) == NULL)
+ sudo_fatalx("%s", U_("unable to allocate memory"));
+
+ /* Open policy and audit plugins. */
+ /* XXX - audit policy_open errors */
+ audit_open();
+ policy_open();
+
+ switch (sudo_mode & MODE_MASK) {
+ case MODE_VERSION:
+ policy_show_version(!user_details.cred.uid);
+ iolog_show_version(!user_details.cred.uid, nargc, nargv,
+ submit_envp);
+ approval_show_version(!user_details.cred.uid);
+ audit_show_version(!user_details.cred.uid);
+ break;
+ case MODE_VALIDATE:
+ case MODE_VALIDATE|MODE_INVALIDATE:
+ policy_validate(nargv);
+ break;
+ case MODE_KILL:
+ case MODE_INVALIDATE:
+ policy_invalidate(sudo_mode == MODE_KILL);
+ break;
+ case MODE_CHECK:
+ case MODE_CHECK|MODE_INVALIDATE:
+ case MODE_LIST:
+ case MODE_LIST|MODE_INVALIDATE:
+ policy_list(nargc, nargv, ISSET(sudo_mode, MODE_LONG_LIST),
+ list_user);
+ break;
+ case MODE_EDIT:
+ case MODE_RUN:
+ if (!policy_check(nargc, nargv, env_add, &command_info, &argv_out,
+ &run_envp))
+ goto access_denied;
+
+ /* Reset nargv/nargc based on argv_out. */
+ /* XXX - leaks old nargv in shell mode */
+ for (nargv = argv_out, nargc = 0; nargv[nargc] != NULL; nargc++)
+ continue;
+ if (nargc == 0)
+ sudo_fatalx("%s",
+ U_("plugin did not return a command to execute"));
+
+ /* Approval plugins run after policy plugin accepts the command. */
+ if (!approval_check(command_info, nargv, run_envp))
+ goto access_denied;
+
+ /* Open I/O plugin once policy and approval plugins succeed. */
+ if (!iolog_open(command_info, nargc, nargv, run_envp))
+ goto access_denied;
+
+ /* Audit the accept event on behalf of the sudo front-end. */
+ if (!audit_accept("sudo", SUDO_FRONT_END, command_info,
+ nargv, run_envp))
+ goto access_denied;
+
+ /* Setup command details and run command/edit. */
+ command_info_to_details(command_info, &command_details);
+ if (command_details.utmp_user == NULL)
+ command_details.utmp_user = user_details.username;
+ command_details.submitcwd = user_details.cwd;
+ command_details.tty = user_details.tty;
+ command_details.argv = nargv;
+ command_details.argc = nargc;
+ command_details.envp = run_envp;
+ if (ISSET(sudo_mode, MODE_LOGIN_SHELL))
+ SET(command_details.flags, CD_LOGIN_SHELL);
+ if (ISSET(sudo_mode, MODE_BACKGROUND))
+ SET(command_details.flags, CD_BACKGROUND);
+ if (ISSET(command_details.flags, CD_SUDOEDIT)) {
+ status = sudo_edit(&command_details, &user_details);
+ } else {
+ status = run_command(&command_details, &user_details);
+ }
+ /* The close method was called by sudo_edit/run_command. */
+ break;
+ default:
+ sudo_fatalx(U_("unexpected sudo mode 0x%x"), sudo_mode);
+ }
+
+ /*
+ * If the command was terminated by a signal, sudo needs to terminated
+ * the same way. Otherwise, the shell may ignore a keyboard-generated
+ * signal. However, we want to avoid having sudo dump core itself.
+ */
+ if (WIFSIGNALED(status)) {
+ struct sigaction sa;
+
+ /* Make sure sudo doesn't dump core itself. */
+ disable_coredump();
+
+ /* Re-send the signal to the main sudo process. */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = SIG_DFL;
+ sigaction(WTERMSIG(status), &sa, NULL);
+ sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys,
+ WTERMSIG(status) | 128);
+ kill(getpid(), WTERMSIG(status));
+ }
+ sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys,
+ WEXITSTATUS(status));
+ return WEXITSTATUS(status);
+
+access_denied:
+ /* Policy/approval failure, close policy and audit plugins before exit. */
+ if (policy_plugin.u.policy->version >= SUDO_API_MKVERSION(1, 15))
+ policy_close(NULL, 0, EACCES);
+ audit_close(SUDO_PLUGIN_NO_STATUS, 0);
+ sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys,
+ EXIT_FAILURE);
+ return EXIT_FAILURE;
+}
+
+int
+os_init_common(int argc, char *argv[], char *envp[])
+{
+#ifdef STATIC_SUDOERS_PLUGIN
+ preload_static_symbols();
+#endif
+ gc_init();
+ return 0;
+}
+
+/*
+ * Ensure that stdin, stdout and stderr are open; set to /dev/null if not.
+ * Some operating systems do this automatically in the kernel or libc.
+ */
+static void
+fix_fds(void)
+{
+ int miss[3];
+ debug_decl(fix_fds, SUDO_DEBUG_UTIL);
+
+ /*
+ * stdin, stdout and stderr must be open; set them to /dev/null
+ * if they are closed.
+ */
+ miss[STDIN_FILENO] = fcntl(STDIN_FILENO, F_GETFL, 0) == -1;
+ miss[STDOUT_FILENO] = fcntl(STDOUT_FILENO, F_GETFL, 0) == -1;
+ miss[STDERR_FILENO] = fcntl(STDERR_FILENO, F_GETFL, 0) == -1;
+ if (miss[STDIN_FILENO] || miss[STDOUT_FILENO] || miss[STDERR_FILENO]) {
+ int devnull =
+ open(_PATH_DEVNULL, O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if (devnull == -1)
+ sudo_fatal(U_("unable to open %s"), _PATH_DEVNULL);
+ if (miss[STDIN_FILENO] && dup2(devnull, STDIN_FILENO) == -1)
+ sudo_fatal("dup2");
+ if (miss[STDOUT_FILENO] && dup2(devnull, STDOUT_FILENO) == -1)
+ sudo_fatal("dup2");
+ if (miss[STDERR_FILENO] && dup2(devnull, STDERR_FILENO) == -1)
+ sudo_fatal("dup2");
+ if (devnull > STDERR_FILENO)
+ close(devnull);
+ }
+ debug_return;
+}
+
+/*
+ * Allocate space for groups and fill in using sudo_getgrouplist2()
+ * for when we cannot (or don't want to) use getgroups().
+ * Returns 0 on success and -1 on failure.
+ */
+static int
+fill_group_list(const char *user, struct sudo_cred *cred)
+{
+ int ret = -1;
+ debug_decl(fill_group_list, SUDO_DEBUG_UTIL);
+
+ /*
+ * If user specified a max number of groups, use it, otherwise let
+ * sudo_getgrouplist2() allocate the group vector.
+ */
+ cred->ngroups = sudo_conf_max_groups();
+ if (cred->ngroups > 0) {
+ cred->groups =
+ reallocarray(NULL, (size_t)cred->ngroups, sizeof(GETGROUPS_T));
+ if (cred->groups != NULL) {
+ /* Clamp to max_groups if insufficient space for all groups. */
+ if (sudo_getgrouplist2(user, cred->gid, &cred->groups,
+ &cred->ngroups) == -1) {
+ cred->ngroups = sudo_conf_max_groups();
+ }
+ ret = 0;
+ }
+ } else {
+ cred->groups = NULL;
+ ret = sudo_getgrouplist2(user, cred->gid, &cred->groups,
+ &cred->ngroups);
+ }
+ if (ret == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: %s: unable to get groups via sudo_getgrouplist2()",
+ __func__, user);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: %s: got %d groups via sudo_getgrouplist2()",
+ __func__, user, cred->ngroups);
+ }
+ debug_return_int(ret);
+}
+
+static char *
+get_user_groups(const char *user, struct sudo_cred *cred)
+{
+ char *cp, *gid_list = NULL;
+ size_t glsize;
+ int i, len, group_source;
+ debug_decl(get_user_groups, SUDO_DEBUG_UTIL);
+
+ cred->groups = NULL;
+ group_source = sudo_conf_group_source();
+ if (group_source != GROUP_SOURCE_DYNAMIC) {
+ long maxgroups = sysconf(_SC_NGROUPS_MAX);
+ if (maxgroups < 0)
+ maxgroups = NGROUPS_MAX;
+
+ /* Note that macOS may return ngroups > NGROUPS_MAX. */
+ cred->ngroups = getgroups(0, NULL); // -V575
+ if (cred->ngroups > 0) {
+ /* Use groups from kernel if not at limit or source is static. */
+ if (cred->ngroups != maxgroups || group_source == GROUP_SOURCE_STATIC) {
+ cred->groups = reallocarray(NULL, (size_t)cred->ngroups,
+ sizeof(GETGROUPS_T));
+ if (cred->groups == NULL)
+ goto done;
+ cred->ngroups = getgroups(cred->ngroups, cred->groups);
+ if (cred->ngroups < 0) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
+ "%s: unable to get %d groups via getgroups()",
+ __func__, cred->ngroups);
+ free(cred->groups);
+ cred->groups = NULL;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_INFO,
+ "%s: got %d groups via getgroups()",
+ __func__, cred->ngroups);
+ }
+ }
+ }
+ }
+ if (cred->groups == NULL) {
+ /*
+ * Query group database if kernel list is too small or disabled.
+ * Typically, this is because NFS can only support up to 16 groups.
+ */
+ if (fill_group_list(user, cred) == -1)
+ goto done;
+ }
+
+ /*
+ * Format group list as a comma-separated string of gids.
+ */
+ glsize = sizeof("groups=") - 1 +
+ ((size_t)cred->ngroups * (STRLEN_MAX_UNSIGNED(gid_t) + 1));
+ if ((gid_list = malloc(glsize)) == NULL)
+ goto done;
+ memcpy(gid_list, "groups=", sizeof("groups=") - 1);
+ cp = gid_list + sizeof("groups=") - 1;
+ glsize -= (size_t)(cp - gid_list);
+ for (i = 0; i < cred->ngroups; i++) {
+ len = snprintf(cp, glsize, "%s%u", i ? "," : "",
+ (unsigned int)cred->groups[i]);
+ if (len < 0 || (size_t)len >= glsize)
+ sudo_fatalx(U_("internal error, %s overflow"), __func__);
+ cp += len;
+ glsize -= (size_t)len;
+ }
+done:
+ debug_return_str(gid_list);
+}
+
+/*
+ * Return user information as an array of name=value pairs.
+ * and fill in struct user_details (which shares the same strings).
+ */
+static char **
+get_user_info(struct user_details *ud)
+{
+ char *cp, **info, path[PATH_MAX];
+ size_t info_max = 32 + RLIM_NLIMITS;
+ size_t i = 0, n;
+ mode_t mask;
+ struct passwd *pw;
+ int ttyfd;
+ debug_decl(get_user_info, SUDO_DEBUG_UTIL);
+
+ /*
+ * On BSD systems you can set a hint to keep the password and
+ * group databases open instead of having to open and close
+ * them all the time. Since sudo does a lot of password and
+ * group lookups, keeping the file open can speed things up.
+ */
+#ifdef HAVE_SETPASSENT
+ setpassent(1);
+#endif /* HAVE_SETPASSENT */
+#ifdef HAVE_SETGROUPENT
+ setgroupent(1);
+#endif /* HAVE_SETGROUPENT */
+
+ memset(ud, 0, sizeof(*ud));
+
+ /* XXX - bound check number of entries */
+ info = reallocarray(NULL, info_max, sizeof(char *));
+ if (info == NULL)
+ goto oom;
+
+ ud->pid = getpid();
+ ud->ppid = getppid();
+ ud->pgid = getpgid(0);
+ ttyfd = open(_PATH_TTY, O_RDWR);
+ sudo_get_ttysize(ttyfd, &ud->ts_rows, &ud->ts_cols);
+ if (ttyfd != -1) {
+ if ((ud->tcpgid = tcgetpgrp(ttyfd)) == -1)
+ ud->tcpgid = 0;
+ close(ttyfd);
+ }
+ if ((ud->sid = getsid(0)) == -1)
+ ud->sid = 0;
+
+ ud->cred.uid = getuid();
+ ud->cred.euid = geteuid();
+ ud->cred.gid = getgid();
+ ud->cred.egid = getegid();
+
+ /* Store cred for use by sudo_askpass(). */
+ sudo_askpass_cred(&ud->cred);
+
+#ifdef HAVE_SETAUTHDB
+ aix_setauthdb(IDtouser(ud->cred.uid), NULL);
+#endif
+ pw = getpwuid(ud->cred.uid);
+#ifdef HAVE_SETAUTHDB
+ aix_restoreauthdb();
+#endif
+ if (pw == NULL)
+ sudo_fatalx(U_("you do not exist in the %s database"), "passwd");
+
+ info[i] = sudo_new_key_val("user", pw->pw_name);
+ if (info[i] == NULL)
+ goto oom;
+ ud->username = info[i] + sizeof("user=") - 1;
+
+ /* Stash user's shell for use with the -s flag; don't pass to plugin. */
+ if ((ud->shell = getenv("SHELL")) == NULL || ud->shell[0] == '\0') {
+ ud->shell = pw->pw_shell[0] ? pw->pw_shell : _PATH_SUDO_BSHELL;
+ }
+ if ((cp = strdup(ud->shell)) == NULL)
+ goto oom;
+ if (!gc_add(GC_PTR, cp))
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ ud->shell = cp;
+
+ if (asprintf(&info[++i], "pid=%d", (int)ud->pid) == -1)
+ goto oom;
+ if (asprintf(&info[++i], "ppid=%d", (int)ud->ppid) == -1)
+ goto oom;
+ if (asprintf(&info[++i], "pgid=%d", (int)ud->pgid) == -1)
+ goto oom;
+ if (asprintf(&info[++i], "tcpgid=%d", (int)ud->tcpgid) == -1)
+ goto oom;
+ if (asprintf(&info[++i], "sid=%d", (int)ud->sid) == -1)
+ goto oom;
+ if (asprintf(&info[++i], "uid=%u", (unsigned int)ud->cred.uid) == -1)
+ goto oom;
+ if (asprintf(&info[++i], "euid=%u", (unsigned int)ud->cred.euid) == -1)
+ goto oom;
+ if (asprintf(&info[++i], "gid=%u", (unsigned int)ud->cred.gid) == -1)
+ goto oom;
+ if (asprintf(&info[++i], "egid=%u", (unsigned int)ud->cred.egid) == -1)
+ goto oom;
+
+ if ((cp = get_user_groups(ud->username, &ud->cred)) == NULL)
+ goto oom;
+ info[++i] = cp;
+ if (!gc_add(GC_PTR, ud->cred.groups))
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ mask = umask(0);
+ umask(mask);
+ if (asprintf(&info[++i], "umask=0%o", (unsigned int)mask) == -1)
+ goto oom;
+
+ if (getcwd(path, sizeof(path)) != NULL) {
+ info[++i] = sudo_new_key_val("cwd", path);
+ if (info[i] == NULL)
+ goto oom;
+ ud->cwd = info[i] + sizeof("cwd=") - 1;
+ }
+
+ if (get_process_ttyname(path, sizeof(path)) != NULL) {
+ info[++i] = sudo_new_key_val("tty", path);
+ if (info[i] == NULL)
+ goto oom;
+ ud->tty = info[i] + sizeof("tty=") - 1;
+ } else {
+ /* tty may not always be present */
+ if (errno != ENOENT)
+ sudo_warn("%s", U_("unable to determine tty"));
+ }
+
+ cp = sudo_gethostname();
+ info[++i] = sudo_new_key_val("host", cp ? cp : "localhost");
+ free(cp);
+ if (info[i] == NULL)
+ goto oom;
+ ud->host = info[i] + sizeof("host=") - 1;
+
+ if (asprintf(&info[++i], "lines=%d", ud->ts_rows) == -1)
+ goto oom;
+ if (asprintf(&info[++i], "cols=%d", ud->ts_cols) == -1)
+ goto oom;
+
+ n = serialize_rlimits(&info[i + 1], info_max - (i + 1));
+ if (n == (size_t)-1)
+ goto oom;
+ i += n;
+
+ info[++i] = NULL;
+
+ /* Add to list of vectors to be garbage collected at exit. */
+ if (!gc_add(GC_VECTOR, info))
+ goto bad;
+
+ debug_return_ptr(info);
+oom:
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+bad:
+ while (i)
+ free(info[--i]);
+ free(info);
+ debug_return_ptr(NULL);
+}
+
+/*
+ * Convert a command_info array into a command_details structure.
+ */
+static void
+command_info_to_details(char * const info[], struct command_details *details)
+{
+ const char *errstr;
+ char *cp;
+ id_t id;
+ size_t i;
+ debug_decl(command_info_to_details, SUDO_DEBUG_PCOMM);
+
+ memset(details, 0, sizeof(*details));
+ details->info = info;
+ details->closefrom = -1;
+ details->execfd = -1;
+ details->flags = CD_SUDOEDIT_CHECKDIR | CD_SET_GROUPS;
+ TAILQ_INIT(&details->preserved_fds);
+
+#define SET_STRING(s, n) \
+ if (strncmp(s, info[i], sizeof(s) - 1) == 0 && info[i][sizeof(s) - 1]) { \
+ details->n = info[i] + sizeof(s) - 1; \
+ break; \
+ }
+#define SET_FLAG(s, n) \
+ if (strncmp(s, info[i], sizeof(s) - 1) == 0) { \
+ switch (sudo_strtobool(info[i] + sizeof(s) - 1)) { \
+ case true: \
+ SET(details->flags, n); \
+ break; \
+ case false: \
+ CLR(details->flags, n); \
+ break; \
+ default: \
+ sudo_debug_printf(SUDO_DEBUG_ERROR, \
+ "invalid boolean value for %s", info[i]); \
+ break; \
+ } \
+ break; \
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_INFO, "command info from plugin:");
+ for (i = 0; info[i] != NULL; i++) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, " %zu: %s", i, info[i]);
+ switch (info[i][0]) {
+ case 'a':
+ SET_STRING("apparmor_profile=", apparmor_profile);
+ break;
+ case 'c':
+ SET_STRING("chroot=", chroot)
+ SET_STRING("command=", command)
+ SET_STRING("cwd=", runcwd)
+ SET_FLAG("cwd_optional=", CD_CWD_OPTIONAL)
+ if (strncmp("closefrom=", info[i], sizeof("closefrom=") - 1) == 0) {
+ cp = info[i] + sizeof("closefrom=") - 1;
+ details->closefrom =
+ (int)sudo_strtonum(cp, 0, INT_MAX, &errstr);
+ if (errstr != NULL)
+ sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
+ break;
+ }
+ break;
+ case 'e':
+ SET_FLAG("exec_background=", CD_EXEC_BG)
+ if (strncmp("execfd=", info[i], sizeof("execfd=") - 1) == 0) {
+ cp = info[i] + sizeof("execfd=") - 1;
+ details->execfd =
+ (int)sudo_strtonum(cp, 0, INT_MAX, &errstr);
+ if (errstr != NULL)
+ sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
+#ifdef HAVE_FEXECVE
+ /* Must keep fd open during exec. */
+ add_preserved_fd(&details->preserved_fds, details->execfd);
+ SET(details->flags, CD_FEXECVE);
+#else
+ /* Plugin thinks we support fexecve() but we don't. */
+ (void)fcntl(details->execfd, F_SETFD, FD_CLOEXEC);
+ details->execfd = -1;
+#endif
+ break;
+ }
+ break;
+ case 'i':
+ SET_FLAG("intercept=", CD_INTERCEPT)
+ SET_FLAG("intercept_verify=", CD_INTERCEPT_VERIFY)
+ break;
+ case 'l':
+ SET_STRING("login_class=", login_class)
+ SET_FLAG("log_subcmds=", CD_LOG_SUBCMDS)
+ break;
+ case 'n':
+ if (strncmp("nice=", info[i], sizeof("nice=") - 1) == 0) {
+ cp = info[i] + sizeof("nice=") - 1;
+ details->priority = (int)sudo_strtonum(cp, INT_MIN, INT_MAX,
+ &errstr);
+ if (errstr != NULL)
+ sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
+ SET(details->flags, CD_SET_PRIORITY);
+ break;
+ }
+ SET_FLAG("noexec=", CD_NOEXEC)
+ break;
+ case 'p':
+ SET_FLAG("preserve_groups=", CD_PRESERVE_GROUPS)
+ if (strncmp("preserve_fds=", info[i], sizeof("preserve_fds=") - 1) == 0) {
+ parse_preserved_fds(&details->preserved_fds,
+ info[i] + sizeof("preserve_fds=") - 1);
+ break;
+ }
+ break;
+ case 'r':
+ if (strncmp("rlimit_", info[i], sizeof("rlimit_") - 1) == 0) {
+ parse_policy_rlimit(info[i] + sizeof("rlimit_") - 1);
+ break;
+ }
+ if (strncmp("runas_egid=", info[i], sizeof("runas_egid=") - 1) == 0) {
+ cp = info[i] + sizeof("runas_egid=") - 1;
+ id = sudo_strtoid(cp, &errstr);
+ if (errstr != NULL)
+ sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
+ details->cred.egid = (gid_t)id;
+ SET(details->flags, CD_SET_EGID);
+ break;
+ }
+ if (strncmp("runas_euid=", info[i], sizeof("runas_euid=") - 1) == 0) {
+ cp = info[i] + sizeof("runas_euid=") - 1;
+ id = sudo_strtoid(cp, &errstr);
+ if (errstr != NULL)
+ sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
+ details->cred.euid = (uid_t)id;
+ SET(details->flags, CD_SET_EUID);
+ break;
+ }
+ if (strncmp("runas_gid=", info[i], sizeof("runas_gid=") - 1) == 0) {
+ cp = info[i] + sizeof("runas_gid=") - 1;
+ id = sudo_strtoid(cp, &errstr);
+ if (errstr != NULL)
+ sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
+ details->cred.gid = (gid_t)id;
+ SET(details->flags, CD_SET_GID);
+ break;
+ }
+ if (strncmp("runas_groups=", info[i], sizeof("runas_groups=") - 1) == 0) {
+ cp = info[i] + sizeof("runas_groups=") - 1;
+ details->cred.ngroups = sudo_parse_gids(cp, NULL,
+ &details->cred.groups);
+ /* sudo_parse_gids() will print a warning on error. */
+ if (details->cred.ngroups == -1)
+ exit(EXIT_FAILURE); /* XXX */
+ if (!gc_add(GC_PTR, details->cred.groups)) {
+ sudo_fatalx(U_("%s: %s"), __func__,
+ U_("unable to allocate memory"));
+ }
+ break;
+ }
+ if (strncmp("runas_uid=", info[i], sizeof("runas_uid=") - 1) == 0) {
+ cp = info[i] + sizeof("runas_uid=") - 1;
+ id = sudo_strtoid(cp, &errstr);
+ if (errstr != NULL)
+ sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
+ details->cred.uid = (uid_t)id;
+ SET(details->flags, CD_SET_UID);
+ break;
+ }
+#ifdef HAVE_PRIV_SET
+ if (strncmp("runas_privs=", info[i], sizeof("runas_privs=") - 1) == 0) {
+ const char *endp;
+ cp = info[i] + sizeof("runas_privs=") - 1;
+ if (*cp != '\0') {
+ details->privs = priv_str_to_set(cp, ",", &endp);
+ if (details->privs == NULL)
+ sudo_warn("invalid runas_privs %s", endp);
+ }
+ break;
+ }
+ if (strncmp("runas_limitprivs=", info[i], sizeof("runas_limitprivs=") - 1) == 0) {
+ const char *endp;
+ cp = info[i] + sizeof("runas_limitprivs=") - 1;
+ if (*cp != '\0') {
+ details->limitprivs = priv_str_to_set(cp, ",", &endp);
+ if (details->limitprivs == NULL)
+ sudo_warn("invalid runas_limitprivs %s", endp);
+ }
+ break;
+ }
+#endif /* HAVE_PRIV_SET */
+ SET_STRING("runas_user=", runas_user)
+ break;
+ case 's':
+ SET_STRING("selinux_role=", selinux_role)
+ SET_STRING("selinux_type=", selinux_type)
+ SET_FLAG("set_utmp=", CD_SET_UTMP)
+ SET_FLAG("sudoedit=", CD_SUDOEDIT)
+ SET_FLAG("sudoedit_checkdir=", CD_SUDOEDIT_CHECKDIR)
+ SET_FLAG("sudoedit_follow=", CD_SUDOEDIT_FOLLOW)
+ if (strncmp("sudoedit_nfiles=", info[i], sizeof("sudoedit_nfiles=") - 1) == 0) {
+ cp = info[i] + sizeof("sudoedit_nfiles=") - 1;
+ details->nfiles = (int)sudo_strtonum(cp, 1, INT_MAX,
+ &errstr);
+ if (errstr != NULL)
+ sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
+ break;
+ }
+ break;
+ case 't':
+ if (strncmp("timeout=", info[i], sizeof("timeout=") - 1) == 0) {
+ cp = info[i] + sizeof("timeout=") - 1;
+ details->timeout =
+ (unsigned int)sudo_strtonum(cp, 0, UINT_MAX, &errstr);
+ if (errstr != NULL)
+ sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
+ SET(details->flags, CD_SET_TIMEOUT);
+ break;
+ }
+ break;
+ case 'u':
+ if (strncmp("umask=", info[i], sizeof("umask=") - 1) == 0) {
+ cp = info[i] + sizeof("umask=") - 1;
+ details->umask = sudo_strtomode(cp, &errstr);
+ if (errstr != NULL)
+ sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
+ SET(details->flags, CD_SET_UMASK);
+ break;
+ }
+ SET_FLAG("umask_override=", CD_OVERRIDE_UMASK)
+ SET_FLAG("use_ptrace=", CD_USE_PTRACE)
+ SET_FLAG("use_pty=", CD_USE_PTY)
+ SET_STRING("utmp_user=", utmp_user)
+ break;
+ }
+ }
+
+ /* Only use ptrace(2) for intercept/log_subcmds if supported. */
+ exec_ptrace_fix_flags(details);
+
+ if (!ISSET(details->flags, CD_SET_EUID))
+ details->cred.euid = details->cred.uid;
+ if (!ISSET(details->flags, CD_SET_EGID))
+ details->cred.egid = details->cred.gid;
+ if (!ISSET(details->flags, CD_SET_UMASK))
+ CLR(details->flags, CD_OVERRIDE_UMASK);
+
+#ifdef HAVE_SETAUTHDB
+ aix_setauthdb(IDtouser(details->cred.euid), NULL);
+#endif
+ if (details->runas_user != NULL)
+ details->pw = getpwnam(details->runas_user);
+ if (details->pw == NULL)
+ details->pw = getpwuid(details->cred.euid);
+#ifdef HAVE_SETAUTHDB
+ aix_restoreauthdb();
+#endif
+ if (details->pw != NULL && (details->pw = pw_dup(details->pw)) == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ if (!gc_add(GC_PTR, details->pw))
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+#ifdef HAVE_SELINUX
+ if (details->selinux_role != NULL && is_selinux_enabled() > 0) {
+ SET(details->flags, CD_RBAC_ENABLED);
+ if (selinux_getexeccon(details->selinux_role, details->selinux_type) != 0)
+ exit(EXIT_FAILURE);
+ }
+#endif
+
+#ifdef HAVE_APPARMOR
+ if (details->apparmor_profile != NULL && apparmor_is_enabled()) {
+ if (apparmor_prepare(details->apparmor_profile) != 0)
+ exit(EXIT_FAILURE);
+ }
+#endif
+
+ debug_return;
+}
+
+static void
+sudo_check_suid(const char *sudo)
+{
+ char pathbuf[PATH_MAX];
+ struct stat sb;
+ bool qualified;
+ debug_decl(sudo_check_suid, SUDO_DEBUG_PCOMM);
+
+ if (geteuid() != ROOT_UID) {
+#if defined(__linux__) && defined(PR_GET_NO_NEW_PRIVS)
+ /* The no_new_privs flag disables set-user-ID at execve(2) time. */
+ if (prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) == 1) {
+ sudo_warnx("%s", U_("The \"no new privileges\" flag is set, which "
+ "prevents sudo from running as root."));
+ sudo_warnx("%s", U_("If sudo is running in a container, you may need"
+ " to adjust the container configuration to disable the flag."));
+ exit(EXIT_FAILURE);
+ }
+#endif /* __linux__ && PR_GET_NO_NEW_PRIVS */
+
+ /* Search for sudo binary in PATH if not fully qualified. */
+ qualified = strchr(sudo, '/') != NULL;
+ if (!qualified) {
+ char *path = getenv_unhooked("PATH");
+ if (path != NULL) {
+ const char *cp, *ep;
+ const char *pathend = path + strlen(path);
+
+ for (cp = sudo_strsplit(path, pathend, ":", &ep); cp != NULL;
+ cp = sudo_strsplit(NULL, pathend, ":", &ep)) {
+
+ int len = snprintf(pathbuf, sizeof(pathbuf), "%.*s/%s",
+ (int)(ep - cp), cp, sudo);
+ if (len < 0 || len >= ssizeof(pathbuf))
+ continue;
+ if (access(pathbuf, X_OK) == 0) {
+ sudo = pathbuf;
+ qualified = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (qualified && stat(sudo, &sb) == 0) {
+ /* Try to determine why sudo was not running as root. */
+ if (sb.st_uid != ROOT_UID || !ISSET(sb.st_mode, S_ISUID)) {
+ sudo_fatalx(
+ U_("%s must be owned by uid %d and have the setuid bit set"),
+ sudo, ROOT_UID);
+ } else {
+ sudo_fatalx(U_("effective uid is not %d, is %s on a file system "
+ "with the 'nosuid' option set or an NFS file system without"
+ " root privileges?"), ROOT_UID, sudo);
+ }
+ } else {
+ sudo_fatalx(
+ U_("effective uid is not %d, is sudo installed setuid root?"),
+ ROOT_UID);
+ }
+ }
+ debug_return;
+}
+
+bool
+set_user_groups(struct command_details *details)
+{
+ bool ret = false;
+ debug_decl(set_user_groups, SUDO_DEBUG_EXEC);
+
+ if (!ISSET(details->flags, CD_PRESERVE_GROUPS)) {
+ if (details->cred.ngroups >= 0) {
+ if (sudo_setgroups(details->cred.ngroups, details->cred.groups) < 0) {
+ sudo_warn("%s", U_("unable to set supplementary group IDs"));
+ goto done;
+ }
+ }
+ }
+#ifdef HAVE_SETEUID
+ if (ISSET(details->flags, CD_SET_EGID) && setegid(details->cred.egid)) {
+ sudo_warn(U_("unable to set effective gid to runas gid %u"),
+ (unsigned int)details->cred.egid);
+ goto done;
+ }
+#endif
+ if (ISSET(details->flags, CD_SET_GID) && setgid(details->cred.gid)) {
+ sudo_warn(U_("unable to set gid to runas gid %u"),
+ (unsigned int)details->cred.gid);
+ goto done;
+ }
+ ret = true;
+
+done:
+ CLR(details->flags, CD_SET_GROUPS);
+ debug_return_bool(ret);
+}
+
+/*
+ * Run the command and wait for it to complete.
+ * Returns wait status suitable for use with the wait(2) macros.
+ */
+int
+run_command(struct command_details *command_details,
+ const struct user_details *user_details)
+{
+ struct command_status cstat;
+ int status = W_EXITCODE(1, 0);
+ debug_decl(run_command, SUDO_DEBUG_EXEC);
+
+ cstat.type = CMD_INVALID;
+ cstat.val = 0;
+
+ if (command_details->command == NULL) {
+ sudo_warnx("%s", U_("command not set by the security policy"));
+ debug_return_int(status);
+ }
+ if (command_details->argv == NULL) {
+ sudo_warnx("%s", U_("argv not set by the security policy"));
+ debug_return_int(status);
+ }
+ if (command_details->envp == NULL) {
+ sudo_warnx("%s", U_("envp not set by the security policy"));
+ debug_return_int(status);
+ }
+
+ sudo_execute(command_details, user_details, sudo_event_base, &cstat);
+
+ switch (cstat.type) {
+ case CMD_ERRNO:
+ /* exec_setup() or execve() returned an error. */
+ iolog_close(0, cstat.val);
+ policy_close(command_details->command, 0, cstat.val);
+ audit_close(SUDO_PLUGIN_EXEC_ERROR, cstat.val);
+ break;
+ case CMD_WSTATUS:
+ /* Command ran, exited or was killed. */
+ status = cstat.val;
+ iolog_close(status, 0);
+ policy_close(command_details->command, status, 0);
+ audit_close(SUDO_PLUGIN_WAIT_STATUS, cstat.val);
+ break;
+ default:
+ /* TODO: handle front end error conditions. */
+ sudo_warnx(U_("unexpected child termination condition: %d"), cstat.type);
+ break;
+ }
+ debug_return_int(status);
+}
+
+/*
+ * Format struct sudo_settings as name=value pairs for the plugin
+ * to consume. Returns a NULL-terminated plugin-style array of pairs.
+ */
+static char **
+format_plugin_settings(struct plugin_container *plugin)
+{
+ size_t plugin_settings_size;
+ struct sudo_debug_file *debug_file;
+ struct sudo_settings *setting;
+ char **plugin_settings;
+ size_t i = 0;
+ debug_decl(format_plugin_settings, SUDO_DEBUG_PCOMM);
+
+ /* We update the ticket entry by default. */
+ if (sudo_settings[ARG_IGNORE_TICKET].value == NULL &&
+ sudo_settings[ARG_UPDATE_TICKET].value == NULL) {
+ sudo_settings[ARG_UPDATE_TICKET].value = "true";
+ }
+
+ /* Determine sudo_settings array size (including plugin_path and NULL) */
+ plugin_settings_size = 2;
+ for (setting = sudo_settings; setting->name != NULL; setting++)
+ plugin_settings_size++;
+ if (plugin->debug_files != NULL) {
+ TAILQ_FOREACH(debug_file, plugin->debug_files, entries)
+ plugin_settings_size++;
+ }
+
+ /* Allocate and fill in. */
+ plugin_settings = reallocarray(NULL, plugin_settings_size, sizeof(char *));
+ if (plugin_settings == NULL)
+ goto bad;
+ plugin_settings[i] = sudo_new_key_val("plugin_path", plugin->path);
+ if (plugin_settings[i] == NULL)
+ goto bad;
+ for (setting = sudo_settings; setting->name != NULL; setting++) {
+ if (setting->value != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_INFO, "settings: %s=%s",
+ setting->name, setting->value);
+ plugin_settings[++i] =
+ sudo_new_key_val(setting->name, setting->value);
+ if (plugin_settings[i] == NULL)
+ goto bad;
+ }
+ }
+ if (plugin->debug_files != NULL) {
+ TAILQ_FOREACH(debug_file, plugin->debug_files, entries) {
+ /* XXX - quote filename? */
+ if (asprintf(&plugin_settings[++i], "debug_flags=%s %s",
+ debug_file->debug_file, debug_file->debug_flags) == -1)
+ goto bad;
+ }
+ }
+ plugin_settings[++i] = NULL;
+
+ /* Add to list of vectors to be garbage collected at exit. */
+ if (!gc_add(GC_VECTOR, plugin_settings))
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ debug_return_ptr(plugin_settings);
+bad:
+ while (i)
+ free(plugin_settings[--i]);
+ free(plugin_settings);
+ debug_return_ptr(NULL);
+}
+
+static void
+policy_open(void)
+{
+ char **plugin_settings;
+ const char *errstr = NULL;
+ int ok;
+ debug_decl(policy_open, SUDO_DEBUG_PCOMM);
+
+ /* Convert struct sudo_settings to plugin_settings[] */
+ plugin_settings = format_plugin_settings(&policy_plugin);
+ if (plugin_settings == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ /*
+ * Backward compatibility for older API versions
+ */
+ sudo_debug_set_active_instance(SUDO_DEBUG_INSTANCE_INITIALIZER);
+ switch (policy_plugin.u.generic->version) {
+ case SUDO_API_MKVERSION(1, 0):
+ case SUDO_API_MKVERSION(1, 1):
+ ok = policy_plugin.u.policy_1_0->open(policy_plugin.u.io_1_0->version,
+ sudo_conversation_1_7, sudo_conversation_printf, plugin_settings,
+ user_info, submit_envp);
+ break;
+ default:
+ ok = policy_plugin.u.policy->open(SUDO_API_VERSION, sudo_conversation,
+ sudo_conversation_printf, plugin_settings, user_info, submit_envp,
+ policy_plugin.options, &errstr);
+ }
+
+ /* Stash plugin debug instance ID if set in open() function. */
+ policy_plugin.debug_instance = sudo_debug_get_active_instance();
+ sudo_debug_set_active_instance(sudo_debug_instance);
+
+ if (ok != 1) {
+ if (ok == -2)
+ usage();
+ /* XXX - audit */
+ sudo_fatalx("%s", U_("unable to initialize policy plugin"));
+ }
+
+ debug_return;
+}
+
+static void
+policy_close(const char *cmnd, int exit_status, int error_code)
+{
+ debug_decl(policy_close, SUDO_DEBUG_PCOMM);
+
+ if (error_code != 0) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s: calling policy close with errno %d",
+ policy_plugin.name, error_code);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s: calling policy close with wait status %d",
+ policy_plugin.name, exit_status);
+ }
+ if (policy_plugin.u.policy->close != NULL) {
+ sudo_debug_set_active_instance(policy_plugin.debug_instance);
+ policy_plugin.u.policy->close(exit_status, error_code);
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ } else if (error_code != 0) {
+ if (cmnd != NULL) {
+ errno = error_code;
+ sudo_warn(U_("unable to execute %s"), cmnd);
+ }
+ }
+
+ debug_return;
+}
+
+static int
+policy_show_version(int verbose)
+{
+ int ret = true;
+ debug_decl(policy_show_version, SUDO_DEBUG_PCOMM);
+
+ sudo_debug_set_active_instance(policy_plugin.debug_instance);
+ if (policy_plugin.u.policy->show_version != NULL)
+ ret = policy_plugin.u.policy->show_version(verbose);
+ if (policy_plugin.u.policy->version >= SUDO_API_MKVERSION(1, 15)) {
+ if (policy_plugin.u.policy->close != NULL)
+ policy_plugin.u.policy->close(0, 0);
+ }
+ sudo_debug_set_active_instance(sudo_debug_instance);
+
+ debug_return_int(ret);
+}
+
+static bool
+policy_check(int argc, char * const argv[], char *env_add[],
+ char **command_info[], char **run_argv[], char **run_envp[])
+{
+ const char *errstr = NULL;
+ int ok;
+ debug_decl(policy_check, SUDO_DEBUG_PCOMM);
+
+ if (policy_plugin.u.policy->check_policy == NULL) {
+ sudo_fatalx(U_("policy plugin %s is missing the \"check_policy\" method"),
+ policy_plugin.name);
+ }
+ sudo_debug_set_active_instance(policy_plugin.debug_instance);
+ ok = policy_plugin.u.policy->check_policy(argc, argv, env_add,
+ command_info, run_argv, run_envp, &errstr);
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "policy plugin returns %d (%s)",
+ ok, errstr ? errstr : "");
+
+ /* On success, the close method will be called by sudo_edit/run_command. */
+ if (ok != 1) {
+ switch (ok) {
+ case 0:
+ audit_reject(policy_plugin.name, SUDO_POLICY_PLUGIN,
+ errstr ? errstr : _("command rejected by policy"),
+ *command_info);
+ break;
+ case -1:
+ audit_error(policy_plugin.name, SUDO_POLICY_PLUGIN,
+ errstr ? errstr : _("policy plugin error"),
+ *command_info);
+ break;
+ case -2:
+ usage();
+ /* NOTREACHED */
+ }
+ debug_return_bool(false);
+ }
+ debug_return_bool(audit_accept(policy_plugin.name, SUDO_POLICY_PLUGIN,
+ *command_info, *run_argv, *run_envp));
+}
+
+sudo_noreturn static void
+policy_list(int argc, char * const argv[], int verbose, const char *user)
+{
+ const char *errstr = NULL;
+ /* TODO: add list_user */
+ const char * const command_info[] = {
+ "command=list",
+ NULL
+ };
+ int ok;
+ debug_decl(policy_list, SUDO_DEBUG_PCOMM);
+
+ if (policy_plugin.u.policy->list == NULL) {
+ sudo_fatalx(U_("policy plugin %s does not support listing privileges"),
+ policy_plugin.name);
+ }
+ sudo_debug_set_active_instance(policy_plugin.debug_instance);
+ ok = policy_plugin.u.policy->list(argc, argv, verbose, user, &errstr);
+ sudo_debug_set_active_instance(sudo_debug_instance);
+
+ switch (ok) {
+ case 1:
+ audit_accept(policy_plugin.name, SUDO_POLICY_PLUGIN,
+ (char **)command_info, argv, submit_envp);
+ break;
+ case 0:
+ audit_reject(policy_plugin.name, SUDO_POLICY_PLUGIN,
+ errstr ? errstr : _("command rejected by policy"),
+ (char **)command_info);
+ break;
+ default:
+ audit_error(policy_plugin.name, SUDO_POLICY_PLUGIN,
+ errstr ? errstr : _("policy plugin error"),
+ (char **)command_info);
+ break;
+ }
+
+ /* Policy must be closed after auditing to avoid use after free. */
+ if (policy_plugin.u.policy->version >= SUDO_API_MKVERSION(1, 15))
+ policy_close(NULL, 0, 0);
+ audit_close(SUDO_PLUGIN_NO_STATUS, 0);
+
+ exit(ok != 1);
+}
+
+sudo_noreturn static void
+policy_validate(char * const argv[])
+{
+ const char *errstr = NULL;
+ const char * const command_info[] = {
+ "command=validate",
+ NULL
+ };
+ int ok = 0;
+ debug_decl(policy_validate, SUDO_DEBUG_PCOMM);
+
+ if (policy_plugin.u.policy->validate == NULL) {
+ sudo_fatalx(U_("policy plugin %s does not support the -v option"),
+ policy_plugin.name);
+ }
+ sudo_debug_set_active_instance(policy_plugin.debug_instance);
+ ok = policy_plugin.u.policy->validate(&errstr);
+ sudo_debug_set_active_instance(sudo_debug_instance);
+
+ switch (ok) {
+ case 1:
+ audit_accept(policy_plugin.name, SUDO_POLICY_PLUGIN,
+ (char **)command_info, argv, submit_envp);
+ break;
+ case 0:
+ audit_reject(policy_plugin.name, SUDO_POLICY_PLUGIN,
+ errstr ? errstr : _("command rejected by policy"),
+ (char **)command_info);
+ break;
+ default:
+ audit_error(policy_plugin.name, SUDO_POLICY_PLUGIN,
+ errstr ? errstr : _("policy plugin error"),
+ (char **)command_info);
+ break;
+ }
+
+ /* Policy must be closed after auditing to avoid use after free. */
+ if (policy_plugin.u.policy->version >= SUDO_API_MKVERSION(1, 15))
+ policy_close(NULL, 0, 0);
+ audit_close(SUDO_PLUGIN_NO_STATUS, 0);
+
+ exit(ok != 1);
+}
+
+sudo_noreturn static void
+policy_invalidate(int unlinkit)
+{
+ debug_decl(policy_invalidate, SUDO_DEBUG_PCOMM);
+
+ if (policy_plugin.u.policy->invalidate == NULL) {
+ sudo_fatalx(U_("policy plugin %s does not support the -k/-K options"),
+ policy_plugin.name);
+ }
+ sudo_debug_set_active_instance(policy_plugin.debug_instance);
+ policy_plugin.u.policy->invalidate(unlinkit);
+ if (policy_plugin.u.policy->version >= SUDO_API_MKVERSION(1, 15)) {
+ if (policy_plugin.u.policy->close != NULL)
+ policy_plugin.u.policy->close(0, 0);
+ }
+ sudo_debug_set_active_instance(sudo_debug_instance);
+
+ audit_close(SUDO_PLUGIN_NO_STATUS, 0);
+
+ exit(EXIT_SUCCESS);
+}
+
+int
+policy_init_session(struct command_details *details)
+{
+ const char *errstr = NULL;
+ int ret = true;
+ debug_decl(policy_init_session, SUDO_DEBUG_PCOMM);
+
+ /*
+ * We set groups, including supplementary group vector,
+ * as part of the session setup. This allows for dynamic
+ * groups to be set via pam_group(8) in pam_setcred(3).
+ */
+ if (ISSET(details->flags, CD_SET_GROUPS)) {
+ /* set_user_groups() prints error message on failure. */
+ if (!set_user_groups(details))
+ goto done;
+ }
+
+ /* Session setup may override sudoers umask so set it first. */
+ if (ISSET(details->flags, CD_SET_UMASK))
+ (void) umask(details->umask);
+
+ if (policy_plugin.u.policy->init_session) {
+ /*
+ * Backward compatibility for older API versions
+ */
+ sudo_debug_set_active_instance(policy_plugin.debug_instance);
+ switch (policy_plugin.u.generic->version) {
+ case SUDO_API_MKVERSION(1, 0):
+ case SUDO_API_MKVERSION(1, 1):
+ ret = policy_plugin.u.policy_1_0->init_session(details->pw);
+ break;
+ default:
+ ret = policy_plugin.u.policy->init_session(details->pw,
+ &details->envp, &errstr);
+ }
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ if (ret != 1) {
+ audit_error(policy_plugin.name, SUDO_POLICY_PLUGIN,
+ errstr ? errstr : _("policy plugin error"),
+ details->info);
+ }
+ }
+
+done:
+ debug_return_int(ret);
+}
+
+static int
+iolog_open_int(struct plugin_container *plugin, char * const command_info[],
+ int argc, char * const argv[], char * const run_envp[], const char **errstr)
+{
+ char **plugin_settings;
+ int ret;
+ debug_decl(iolog_open_int, SUDO_DEBUG_PCOMM);
+
+ /* Convert struct sudo_settings to plugin_settings[] */
+ plugin_settings = format_plugin_settings(plugin);
+ if (plugin_settings == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(-1);
+ }
+
+ /*
+ * Backward compatibility for older API versions
+ */
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ switch (plugin->u.generic->version) {
+ case SUDO_API_MKVERSION(1, 0):
+ ret = plugin->u.io_1_0->open(plugin->u.io_1_0->version,
+ sudo_conversation_1_7, sudo_conversation_printf, plugin_settings,
+ user_info, argc, argv, run_envp);
+ break;
+ case SUDO_API_MKVERSION(1, 1):
+ ret = plugin->u.io_1_1->open(plugin->u.io_1_1->version,
+ sudo_conversation_1_7, sudo_conversation_printf, plugin_settings,
+ user_info, command_info, argc, argv, run_envp);
+ break;
+ default:
+ ret = plugin->u.io->open(SUDO_API_VERSION, sudo_conversation,
+ sudo_conversation_printf, plugin_settings, user_info, command_info,
+ argc, argv, run_envp, plugin->options, errstr);
+ }
+
+ /* Stash plugin debug instance ID if set in open() function. */
+ plugin->debug_instance = sudo_debug_get_active_instance();
+ sudo_debug_set_active_instance(sudo_debug_instance);
+
+ debug_return_int(ret);
+}
+
+static bool
+iolog_open(char * const command_info[], int argc, char * const argv[],
+ char * const run_envp[])
+{
+ struct plugin_container *plugin, *next;
+ const char *errstr = NULL;
+ debug_decl(iolog_open, SUDO_DEBUG_PCOMM);
+
+ TAILQ_FOREACH_SAFE(plugin, &io_plugins, entries, next) {
+ int ok = iolog_open_int(plugin, command_info, argc, argv, run_envp,
+ &errstr);
+ switch (ok) {
+ case 1:
+ break;
+ case 0:
+ /* I/O plugin asked to be disabled, remove and free. */
+ unlink_plugin(&io_plugins, plugin);
+ break;
+ case -2:
+ usage();
+ /* NOTREACHED */
+ default:
+ sudo_warnx(U_("error initializing I/O plugin %s"),
+ plugin->name);
+ audit_error(plugin->name, SUDO_IO_PLUGIN,
+ errstr ? errstr : _("error initializing I/O plugin"),
+ command_info);
+ debug_return_bool(false);
+ }
+ }
+
+ debug_return_bool(true);
+}
+
+static void
+iolog_close(int exit_status, int error_code)
+{
+ struct plugin_container *plugin;
+ debug_decl(iolog_close, SUDO_DEBUG_PCOMM);
+
+ TAILQ_FOREACH(plugin, &io_plugins, entries) {
+ if (plugin->u.io->close != NULL) {
+ if (error_code != 0) {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s: calling I/O close with errno %d",
+ plugin->name, error_code);
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "%s: calling I/O close with wait status %d",
+ plugin->name, exit_status);
+ }
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ plugin->u.io->close(exit_status, error_code);
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ }
+ }
+
+ debug_return;
+}
+
+static void
+iolog_show_version(int verbose, int argc, char * const argv[],
+ char * const envp[])
+{
+ const char *errstr = NULL;
+ struct plugin_container *plugin;
+ debug_decl(iolog_show_version, SUDO_DEBUG_PCOMM);
+
+ TAILQ_FOREACH(plugin, &io_plugins, entries) {
+ int ok = iolog_open_int(plugin, NULL, argc, argv, envp, &errstr);
+ if (ok != -1) {
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ if (plugin->u.io->show_version != NULL) {
+ /* Return value of show_version currently ignored. */
+ plugin->u.io->show_version(verbose);
+ }
+ if (plugin->u.io->version >= SUDO_API_MKVERSION(1, 15)) {
+ if (plugin->u.io->close != NULL)
+ plugin->u.io->close(0, 0);
+ }
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ }
+ }
+
+ debug_return;
+}
+
+/*
+ * Remove the specified plugin from the plugins list.
+ * Deregisters any hooks before unlinking, then frees the container.
+ */
+static void
+unlink_plugin(struct plugin_container_list *plugin_list,
+ struct plugin_container *plugin)
+{
+ void (*deregister_hooks)(int , int (*)(struct sudo_hook *)) = NULL;
+ debug_decl(unlink_plugin, SUDO_DEBUG_PCOMM);
+
+ /* Deregister hooks, if any. */
+ if (plugin->u.generic->version >= SUDO_API_MKVERSION(1, 2)) {
+ switch (plugin->u.generic->type) {
+ case SUDO_IO_PLUGIN:
+ deregister_hooks = plugin->u.io->deregister_hooks;
+ break;
+ case SUDO_AUDIT_PLUGIN:
+ deregister_hooks = plugin->u.audit->deregister_hooks;
+ break;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: unsupported plugin type %d", __func__,
+ plugin->u.generic->type);
+ break;
+ }
+ }
+ if (deregister_hooks != NULL) {
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ deregister_hooks(SUDO_HOOK_VERSION, deregister_hook);
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ }
+
+ /* Remove from plugin list and free. */
+ TAILQ_REMOVE(plugin_list, plugin, entries);
+ free_plugin_container(plugin, true);
+
+ debug_return;
+}
+
+static int
+audit_open_int(struct plugin_container *plugin, const char **errstr)
+{
+ char **plugin_settings;
+ int ret;
+ debug_decl(audit_open_int, SUDO_DEBUG_PCOMM);
+
+ /* Convert struct sudo_settings to plugin_settings[] */
+ plugin_settings = format_plugin_settings(plugin);
+ if (plugin_settings == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(-1);
+ }
+
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ ret = plugin->u.audit->open(SUDO_API_VERSION, sudo_conversation,
+ sudo_conversation_printf, plugin_settings, user_info,
+ submit_optind, submit_argv, submit_envp, plugin->options, errstr);
+
+ /* Stash plugin debug instance ID if set in open() function. */
+ plugin->debug_instance = sudo_debug_get_active_instance();
+ sudo_debug_set_active_instance(sudo_debug_instance);
+
+ debug_return_int(ret);
+}
+
+static void
+audit_open(void)
+{
+ struct plugin_container *plugin, *next;
+ const char *errstr = NULL;
+ debug_decl(audit_open, SUDO_DEBUG_PCOMM);
+
+ TAILQ_FOREACH_SAFE(plugin, &audit_plugins, entries, next) {
+ int ok = audit_open_int(plugin, &errstr);
+ switch (ok) {
+ case 1:
+ break;
+ case 0:
+ /* Audit plugin asked to be disabled, remove and free. */
+ unlink_plugin(&audit_plugins, plugin);
+ break;
+ case -2:
+ usage();
+ /* NOTREACHED */
+ default:
+ /* TODO: pass error message to other audit plugins */
+ sudo_fatalx(U_("error initializing audit plugin %s"),
+ plugin->name);
+ }
+ }
+
+ debug_return;
+}
+
+static void
+audit_close(int status_type, int status)
+{
+ struct plugin_container *plugin;
+ debug_decl(audit_close, SUDO_DEBUG_PCOMM);
+
+ TAILQ_FOREACH(plugin, &audit_plugins, entries) {
+ if (plugin->u.audit->close != NULL) {
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ plugin->u.audit->close(status_type, status);
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ }
+ }
+
+ debug_return;
+}
+
+static void
+audit_show_version(int verbose)
+{
+ struct plugin_container *plugin;
+ debug_decl(audit_show_version, SUDO_DEBUG_PCOMM);
+
+ TAILQ_FOREACH(plugin, &audit_plugins, entries) {
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ if (plugin->u.audit->show_version != NULL) {
+ /* Return value of show_version currently ignored. */
+ plugin->u.audit->show_version(verbose);
+ }
+ if (plugin->u.audit->close != NULL)
+ plugin->u.audit->close(SUDO_PLUGIN_NO_STATUS, 0);
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ }
+
+ debug_return;
+}
+
+/*
+ * Error from plugin or front-end.
+ * The error will not be sent to plugin source, if specified.
+ */
+static bool
+audit_error2(struct plugin_container *source, const char *plugin_name,
+ unsigned int plugin_type, const char *audit_msg, char * const command_info[])
+{
+ struct plugin_container *plugin;
+ const char *errstr = NULL;
+ bool ret = true;
+ int ok;
+ debug_decl(audit_error2, SUDO_DEBUG_PCOMM);
+
+ TAILQ_FOREACH(plugin, &audit_plugins, entries) {
+ if (plugin->u.audit->error == NULL)
+ continue;
+
+ /* Avoid a loop if the audit plugin itself has an error. */
+ if (plugin == source)
+ continue;
+
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ ok = plugin->u.audit->error(plugin_name, plugin_type,
+ audit_msg, command_info, &errstr);
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ if (ok != 1) {
+ /*
+ * Don't propagate the error to other audit plugins.
+ * It is not worth the trouble to avoid potential loops.
+ */
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: plugin %s error failed, ret %d", __func__,
+ plugin->name, ok);
+ sudo_warnx(U_("%s: unable to log error event%s%s"),
+ plugin->name, errstr ? ": " : "", errstr ? errstr : "");
+ ret = false;
+ }
+ }
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Command accepted by policy.
+ * See command_info[] for additional info.
+ * XXX - actual environment may be updated by policy_init_session().
+ */
+bool
+audit_accept(const char *plugin_name, unsigned int plugin_type,
+ char * const command_info[], char * const run_argv[],
+ char * const run_envp[])
+{
+ struct plugin_container *plugin;
+ const char *errstr = NULL;
+ int ok;
+ debug_decl(audit_accept, SUDO_DEBUG_PCOMM);
+
+ TAILQ_FOREACH(plugin, &audit_plugins, entries) {
+ if (plugin->u.audit->accept == NULL)
+ continue;
+
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ ok = plugin->u.audit->accept(plugin_name, plugin_type,
+ command_info, run_argv, run_envp, &errstr);
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ if (ok != 1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: plugin %s accept failed, ret %d", __func__,
+ plugin->name, ok);
+ sudo_warnx(U_("%s: unable to log accept event%s%s"),
+ plugin->name, errstr ? ": " : "", errstr ? errstr : "");
+
+ /* Notify other audit plugins and return. */
+ audit_error2(plugin, plugin->name, SUDO_AUDIT_PLUGIN,
+ errstr ? errstr : _("audit plugin error"), command_info);
+ debug_return_bool(false);
+ }
+ }
+
+ debug_return_bool(true);
+}
+
+/*
+ * Command rejected by policy or I/O plugin.
+ */
+bool
+audit_reject(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[])
+{
+ struct plugin_container *plugin;
+ const char *errstr = NULL;
+ bool ret = true;
+ int ok;
+ debug_decl(audit_reject, SUDO_DEBUG_PCOMM);
+
+ TAILQ_FOREACH(plugin, &audit_plugins, entries) {
+ if (plugin->u.audit->reject == NULL)
+ continue;
+
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ ok = plugin->u.audit->reject(plugin_name, plugin_type,
+ audit_msg, command_info, &errstr);
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ if (ok != 1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR,
+ "%s: plugin %s reject failed, ret %d", __func__,
+ plugin->name, ok);
+ sudo_warnx(U_("%s: unable to log reject event%s%s"),
+ plugin->name, errstr ? ": " : "", errstr ? errstr : "");
+
+ /* Notify other audit plugins. */
+ audit_error2(plugin, plugin->name, SUDO_AUDIT_PLUGIN,
+ errstr ? errstr : _("audit plugin error"), command_info);
+
+ ret = false;
+ break;
+ }
+ }
+
+ debug_return_bool(ret);
+}
+
+/*
+ * Error from plugin or front-end.
+ */
+bool
+audit_error(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[])
+{
+ return audit_error2(NULL, plugin_name, plugin_type, audit_msg,
+ command_info);
+}
+
+static int
+approval_open_int(struct plugin_container *plugin)
+{
+ char **plugin_settings;
+ const char *errstr = NULL;
+ int ret;
+ debug_decl(approval_open_int, SUDO_DEBUG_PCOMM);
+
+ /* Convert struct sudo_settings to plugin_settings[] */
+ plugin_settings = format_plugin_settings(plugin);
+ if (plugin_settings == NULL)
+ sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+
+ sudo_debug_set_active_instance(SUDO_DEBUG_INSTANCE_INITIALIZER);
+ ret = plugin->u.approval->open(SUDO_API_VERSION, sudo_conversation,
+ sudo_conversation_printf, plugin_settings, user_info, submit_optind,
+ submit_argv, submit_envp, plugin->options, &errstr);
+
+ /* Stash plugin debug instance ID if set in open() function. */
+ plugin->debug_instance = sudo_debug_get_active_instance();
+ sudo_debug_set_active_instance(sudo_debug_instance);
+
+ switch (ret) {
+ case 1:
+ break;
+ case 0:
+ /* approval plugin asked to be disabled, remove and free. */
+ unlink_plugin(&approval_plugins, plugin);
+ break;
+ case -2:
+ usage();
+ /* NOTREACHED */
+ default:
+ /* XXX - audit */
+ sudo_fatalx(U_("error initializing approval plugin %s"),
+ plugin->name);
+ }
+
+ debug_return_int(ret);
+}
+
+static void
+approval_show_version(int verbose)
+{
+ struct plugin_container *plugin, *next;
+ int ok;
+ debug_decl(approval_show_version, SUDO_DEBUG_PCOMM);
+
+ /*
+ * Approval plugin us only open for the life of the show_version() call.
+ */
+ TAILQ_FOREACH_SAFE(plugin, &approval_plugins, entries, next) {
+ if (plugin->u.approval->show_version == NULL)
+ continue;
+
+ ok = approval_open_int(plugin);
+ if (ok == 1) {
+ /* Return value of show_version currently ignored. */
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ plugin->u.approval->show_version(verbose);
+ if (plugin->u.approval->close != NULL)
+ plugin->u.approval->close();
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ }
+ }
+
+ debug_return;
+}
+
+/*
+ * Run approval checks (there may be more than one).
+ * This is a "one-shot" plugin that has no open/close and is only
+ * called if the policy plugin accepts the command first.
+ */
+bool
+approval_check(char * const command_info[], char * const run_argv[],
+ char * const run_envp[])
+{
+ struct plugin_container *plugin, *next;
+ const char *errstr = NULL;
+ int ok;
+ debug_decl(approval_check, SUDO_DEBUG_PCOMM);
+
+ /*
+ * Approval plugin is only open for the life of the check() call.
+ */
+ TAILQ_FOREACH_SAFE(plugin, &approval_plugins, entries, next) {
+ if (plugin->u.approval->check == NULL)
+ continue;
+
+ ok = approval_open_int(plugin);
+ if (ok != 1)
+ continue;
+
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ ok = plugin->u.approval->check(command_info, run_argv, run_envp,
+ &errstr);
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ sudo_debug_printf(SUDO_DEBUG_INFO, "approval plugin %s returns %d (%s)",
+ plugin->name, ok, errstr ? errstr : "");
+
+ switch (ok) {
+ case 0:
+ audit_reject(plugin->name, SUDO_APPROVAL_PLUGIN,
+ errstr ? errstr : _("command rejected by approver"),
+ command_info);
+ break;
+ case 1:
+ if (!audit_accept(plugin->name, SUDO_APPROVAL_PLUGIN, command_info,
+ run_argv, run_envp))
+ ok = -1;
+ break;
+ case -1:
+ audit_error(plugin->name, SUDO_APPROVAL_PLUGIN,
+ errstr ? errstr : _("approval plugin error"),
+ command_info);
+ break;
+ case -2:
+ usage();
+ }
+
+ /* Close approval plugin now that errstr has been consumed. */
+ if (plugin->u.approval->close != NULL) {
+ sudo_debug_set_active_instance(plugin->debug_instance);
+ plugin->u.approval->close();
+ sudo_debug_set_active_instance(sudo_debug_instance);
+ }
+
+ if (ok != 1)
+ debug_return_bool(false);
+ }
+
+ debug_return_bool(true);
+}
+
+static void
+plugin_event_callback(int fd, int what, void *v)
+{
+ struct sudo_plugin_event_int *ev_int = v;
+ int old_instance;
+ debug_decl(plugin_event_callback, SUDO_DEBUG_PCOMM);
+
+ /* Run the real callback using the plugin's debug instance. */
+ old_instance = sudo_debug_set_active_instance(ev_int->debug_instance);
+ ev_int->callback(fd, what, ev_int->closure);
+ sudo_debug_set_active_instance(old_instance);
+
+ debug_return;
+}
+
+/*
+ * Fill in a previously allocated struct sudo_plugin_event.
+ */
+static int
+plugin_event_set(struct sudo_plugin_event *pev, int fd, int events,
+ sudo_ev_callback_t callback, void *closure)
+{
+ struct sudo_plugin_event_int *ev_int;
+ debug_decl(plugin_event_set, SUDO_DEBUG_PCOMM);
+
+ ev_int = __containerof(pev, struct sudo_plugin_event_int, public);
+ if (sudo_ev_set(&ev_int->private, fd, events, plugin_event_callback, ev_int) == -1)
+ debug_return_int(-1);
+
+ /* Stash active instance so we can restore it when callback runs. */
+ ev_int->debug_instance = sudo_debug_get_active_instance();
+
+ /* Actual user-specified callback and closure. */
+ ev_int->callback = callback;
+ ev_int->closure = closure;
+
+ /* Plugin can only operate on the main event loop. */
+ ev_int->private.base = sudo_event_base;
+
+ debug_return_int(1);
+}
+
+/*
+ * Add a struct sudo_plugin_event to the main event loop.
+ */
+static int
+plugin_event_add(struct sudo_plugin_event *pev, struct timespec *timo)
+{
+ struct sudo_plugin_event_int *ev_int;
+ debug_decl(plugin_event_add, SUDO_DEBUG_PCOMM);
+
+ ev_int = __containerof(pev, struct sudo_plugin_event_int, public);
+ if (sudo_ev_add(NULL, &ev_int->private, timo, 0) == -1)
+ debug_return_int(-1);
+ debug_return_int(1);
+}
+
+/*
+ * Delete a struct sudo_plugin_event from the main event loop.
+ */
+static int
+plugin_event_del(struct sudo_plugin_event *pev)
+{
+ struct sudo_plugin_event_int *ev_int;
+ debug_decl(plugin_event_del, SUDO_DEBUG_PCOMM);
+
+ ev_int = __containerof(pev, struct sudo_plugin_event_int, public);
+ if (sudo_ev_del(NULL, &ev_int->private) == -1)
+ debug_return_int(-1);
+ debug_return_int(1);
+}
+
+/*
+ * Get the amount of time remaining in a timeout event.
+ */
+static int
+plugin_event_pending(struct sudo_plugin_event *pev, int events,
+ struct timespec *ts)
+{
+ struct sudo_plugin_event_int *ev_int;
+ debug_decl(plugin_event_pending, SUDO_DEBUG_PCOMM);
+
+ ev_int = __containerof(pev, struct sudo_plugin_event_int, public);
+ debug_return_int(sudo_ev_pending(&ev_int->private, events, ts));
+}
+
+/*
+ * Get the file descriptor associated with an event.
+ */
+static int
+plugin_event_fd(struct sudo_plugin_event *pev)
+{
+ struct sudo_plugin_event_int *ev_int;
+ debug_decl(plugin_event_fd, SUDO_DEBUG_PCOMM);
+
+ ev_int = __containerof(pev, struct sudo_plugin_event_int, public);
+ debug_return_int(sudo_ev_get_fd(&ev_int->private));
+}
+
+/*
+ * Break out of the event loop, killing the command if it is running.
+ */
+static void
+plugin_event_loopbreak(struct sudo_plugin_event *pev)
+{
+ struct sudo_plugin_event_int *ev_int;
+ debug_decl(plugin_event_loopbreak, SUDO_DEBUG_PCOMM);
+
+ ev_int = __containerof(pev, struct sudo_plugin_event_int, public);
+ sudo_ev_loopbreak(ev_int->private.base);
+ debug_return;
+}
+
+/*
+ * Reset the event base of a struct sudo_plugin_event.
+ * The event is removed from the old base (if any) first.
+ * A NULL base can be used to set the default sudo event base.
+ */
+static void
+plugin_event_setbase(struct sudo_plugin_event *pev, void *base)
+{
+ struct sudo_plugin_event_int *ev_int;
+ debug_decl(plugin_event_setbase, SUDO_DEBUG_PCOMM);
+
+ ev_int = __containerof(pev, struct sudo_plugin_event_int, public);
+ if (ev_int->private.base != NULL)
+ sudo_ev_del(ev_int->private.base, &ev_int->private);
+ ev_int->private.base = base ? base : sudo_event_base;
+ debug_return;
+}
+
+/*
+ * Free a struct sudo_plugin_event allocated by plugin_event_alloc().
+ */
+static void
+plugin_event_free(struct sudo_plugin_event *pev)
+{
+ struct sudo_plugin_event_int *ev_int;
+ debug_decl(plugin_event_free, SUDO_DEBUG_PCOMM);
+
+ /* The private field is first so sudo_ev_free() can free the struct. */
+ ev_int = __containerof(pev, struct sudo_plugin_event_int, public);
+ sudo_ev_free(&ev_int->private);
+
+ debug_return;
+}
+
+/*
+ * Allocate a struct sudo_plugin_event and fill in the public fields.
+ */
+struct sudo_plugin_event *
+sudo_plugin_event_alloc(void)
+{
+ struct sudo_plugin_event_int *ev_int;
+ debug_decl(plugin_event_alloc, SUDO_DEBUG_PCOMM);
+
+ if ((ev_int = malloc(sizeof(*ev_int))) == NULL)
+ debug_return_ptr(NULL);
+
+ /* Init public fields. */
+ ev_int->public.set = plugin_event_set;
+ ev_int->public.add = plugin_event_add;
+ ev_int->public.del = plugin_event_del;
+ ev_int->public.fd = plugin_event_fd;
+ ev_int->public.pending = plugin_event_pending;
+ ev_int->public.setbase = plugin_event_setbase;
+ ev_int->public.loopbreak = plugin_event_loopbreak;
+ ev_int->public.free = plugin_event_free;
+
+ /* Debug instance to use with the callback. */
+ ev_int->debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
+
+ /* Clear private portion in case caller tries to use us uninitialized. */
+ memset(&ev_int->private, 0, sizeof(ev_int->private));
+
+ debug_return_ptr(&ev_int->public);
+}
+
+static void
+free_plugin_container(struct plugin_container *plugin, bool ioplugin)
+{
+ debug_decl(free_plugin_container, SUDO_DEBUG_PLUGIN);
+
+ free(plugin->path);
+ free(plugin->name);
+ if (plugin->options != NULL) {
+ int i = 0;
+ while (plugin->options[i] != NULL)
+ free(plugin->options[i++]);
+ free(plugin->options);
+ }
+ if (ioplugin)
+ free(plugin);
+
+ debug_return;
+}
+
+bool
+gc_add(enum sudo_gc_types type, void *v)
+{
+#ifdef NO_LEAKS
+ struct sudo_gc_entry *gc;
+ debug_decl(gc_add, SUDO_DEBUG_MAIN);
+
+ if (v == NULL)
+ debug_return_bool(false);
+
+ gc = calloc(1, sizeof(*gc));
+ if (gc == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ switch (type) {
+ case GC_PTR:
+ gc->u.ptr = v;
+ break;
+ case GC_VECTOR:
+ gc->u.vec = v;
+ break;
+ default:
+ free(gc);
+ sudo_warnx("unexpected garbage type %d", type);
+ debug_return_bool(false);
+ }
+ gc->type = type;
+ SLIST_INSERT_HEAD(&sudo_gc_list, gc, entries);
+ debug_return_bool(true);
+#else
+ return true;
+#endif /* NO_LEAKS */
+}
+
+#ifdef NO_LEAKS
+static void
+gc_run(void)
+{
+ struct plugin_container *plugin;
+ struct sudo_gc_entry *gc;
+ char **cur;
+ debug_decl(gc_run, SUDO_DEBUG_MAIN);
+
+ /* Collect garbage. */
+ while ((gc = SLIST_FIRST(&sudo_gc_list))) {
+ SLIST_REMOVE_HEAD(&sudo_gc_list, entries);
+ switch (gc->type) {
+ case GC_PTR:
+ free(gc->u.ptr);
+ free(gc);
+ break;
+ case GC_VECTOR:
+ for (cur = gc->u.vec; *cur != NULL; cur++)
+ free(*cur);
+ free(gc->u.vec);
+ free(gc);
+ break;
+ default:
+ sudo_warnx("unexpected garbage type %d", gc->type);
+ }
+ }
+
+ /* Free plugin structs. */
+ free_plugin_container(&policy_plugin, false);
+ while ((plugin = TAILQ_FIRST(&io_plugins))) {
+ TAILQ_REMOVE(&io_plugins, plugin, entries);
+ free_plugin_container(plugin, true);
+ }
+
+ debug_return;
+}
+#endif /* NO_LEAKS */
+
+static void
+gc_init(void)
+{
+#ifdef NO_LEAKS
+ atexit(gc_run);
+#endif
+}
diff --git a/src/sudo.h b/src/sudo.h
new file mode 100644
index 0000000..5156cc3
--- /dev/null
+++ b/src/sudo.h
@@ -0,0 +1,352 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1993-1996, 1998-2005, 2007-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#ifndef SUDO_SUDO_H
+#define SUDO_SUDO_H
+
+#include <limits.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#ifdef HAVE_PRIV_SET
+# include <priv.h>
+#endif
+
+#include <pathnames.h>
+#include <sudo_compat.h>
+#include <sudo_conf.h>
+#include <sudo_debug.h>
+#include <sudo_event.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_queue.h>
+#include <sudo_util.h>
+
+/* Enable asserts() to avoid static analyzer false positives. */
+#if !(defined(SUDO_DEVEL) || defined(__clang_analyzer__) || defined(__COVERITY__))
+# define NDEBUG
+#endif
+
+/*
+ * Various modes sudo can be in (based on arguments) in hex
+ */
+#define MODE_RUN 0x00000001U
+#define MODE_EDIT 0x00000002U
+#define MODE_VALIDATE 0x00000004U
+#define MODE_INVALIDATE 0x00000008U
+#define MODE_KILL 0x00000010U
+#define MODE_VERSION 0x00000020U
+#define MODE_HELP 0x00000040U
+#define MODE_LIST 0x00000080U
+#define MODE_CHECK 0x00000100U
+#define MODE_MASK 0x0000ffffU
+
+/* Mode flags */
+/* XXX - prune this */
+#define MODE_BACKGROUND 0x00010000U
+#define MODE_SHELL 0x00020000U
+#define MODE_LOGIN_SHELL 0x00040000U
+#define MODE_IMPLIED_SHELL 0x00080000U
+#define MODE_RESET_HOME 0x00100000U
+#define MODE_PRESERVE_GROUPS 0x00200000U
+#define MODE_PRESERVE_ENV 0x00400000U
+#define MODE_NONINTERACTIVE 0x00800000U
+#define MODE_LONG_LIST 0x01000000U
+
+/* Indexes into sudo_settings[] args, must match parse_args.c. */
+#define ARG_BSDAUTH_TYPE 0
+#define ARG_LOGIN_CLASS 1
+#define ARG_PRESERVE_ENVIRONMENT 2
+#define ARG_RUNAS_GROUP 3
+#define ARG_SET_HOME 4
+#define ARG_USER_SHELL 5
+#define ARG_LOGIN_SHELL 6
+#define ARG_IGNORE_TICKET 7
+#define ARG_UPDATE_TICKET 8
+#define ARG_PROMPT 9
+#define ARG_SELINUX_ROLE 10
+#define ARG_SELINUX_TYPE 11
+#define ARG_RUNAS_USER 12
+#define ARG_PROGNAME 13
+#define ARG_IMPLIED_SHELL 14
+#define ARG_PRESERVE_GROUPS 15
+#define ARG_NONINTERACTIVE 16
+#define ARG_SUDOEDIT 17
+#define ARG_CLOSEFROM 18
+#define ARG_NET_ADDRS 19
+#define ARG_MAX_GROUPS 20
+#define ARG_PLUGIN_DIR 21
+#define ARG_REMOTE_HOST 22
+#define ARG_TIMEOUT 23
+#define ARG_CHROOT 24
+#define ARG_CWD 25
+#define ARG_ASKPASS 26
+#define ARG_INTERCEPT_SETID 27
+#define ARG_INTERCEPT_PTRACE 28
+#define ARG_APPARMOR_PROFILE 29
+
+/*
+ * Flags for tgetpass()
+ */
+#define TGP_NOECHO 0x00U /* turn echo off reading pw (default) */
+#define TGP_ECHO 0x01U /* leave echo on when reading passwd */
+#define TGP_STDIN 0x02U /* read from stdin, not /dev/tty */
+#define TGP_ASKPASS 0x04U /* read from askpass helper program */
+#define TGP_MASK 0x08U /* mask user input when reading */
+#define TGP_NOECHO_TRY 0x10U /* turn off echo if possible */
+#define TGP_BELL 0x20U /* bell on password prompt */
+
+/* name/value pairs for command line settings. */
+struct sudo_settings {
+ const char *name;
+ const char *value;
+};
+
+/* Sudo user credentials */
+struct sudo_cred {
+ uid_t uid;
+ uid_t euid;
+ uid_t gid;
+ uid_t egid;
+ int ngroups;
+ GETGROUPS_T *groups;
+};
+
+struct user_details {
+ struct sudo_cred cred;
+ pid_t pid;
+ pid_t ppid;
+ pid_t pgid;
+ pid_t tcpgid;
+ pid_t sid;
+ const char *username;
+ const char *cwd;
+ const char *tty;
+ const char *host;
+ const char *shell;
+ int ts_rows;
+ int ts_cols;
+};
+
+#define CD_SET_UID 0x00000001U
+#define CD_SET_EUID 0x00000002U
+#define CD_SET_GID 0x00000004U
+#define CD_SET_EGID 0x00000008U
+#define CD_PRESERVE_GROUPS 0x00000010U
+#define CD_INTERCEPT 0x00000020U
+#define CD_NOEXEC 0x00000040U
+#define CD_SET_PRIORITY 0x00000080U
+#define CD_SET_UMASK 0x00000100U
+#define CD_SET_TIMEOUT 0x00000200U
+#define CD_SUDOEDIT 0x00000400U
+#define CD_BACKGROUND 0x00000800U
+#define CD_RBAC_ENABLED 0x00001000U
+#define CD_USE_PTY 0x00002000U
+#define CD_SET_UTMP 0x00004000U
+#define CD_EXEC_BG 0x00008000U
+#define CD_SUDOEDIT_FOLLOW 0x00010000U
+#define CD_SUDOEDIT_CHECKDIR 0x00020000U
+#define CD_SET_GROUPS 0x00040000U
+#define CD_LOGIN_SHELL 0x00080000U
+#define CD_OVERRIDE_UMASK 0x00100000U
+#define CD_LOG_SUBCMDS 0x00200000U
+#define CD_USE_PTRACE 0x00400000U
+#define CD_FEXECVE 0x00800000U
+#define CD_INTERCEPT_VERIFY 0x01000000U
+#define CD_RBAC_SET_CWD 0x02000000U
+#define CD_CWD_OPTIONAL 0x04000000U
+
+struct preserved_fd {
+ TAILQ_ENTRY(preserved_fd) entries;
+ int lowfd;
+ int highfd;
+ int flags;
+};
+TAILQ_HEAD(preserved_fd_list, preserved_fd);
+
+struct command_details {
+ struct sudo_cred cred;
+ mode_t umask;
+ int argc;
+ int priority;
+ unsigned int timeout;
+ int closefrom;
+ unsigned int flags;
+ int execfd;
+ int nfiles;
+ struct preserved_fd_list preserved_fds;
+ struct passwd *pw;
+ const char *command;
+ const char *runas_user;
+ const char *runcwd;
+ const char *submitcwd;
+ const char *login_class;
+ const char *chroot;
+ const char *selinux_role;
+ const char *selinux_type;
+ const char *apparmor_profile;
+ const char *utmp_user;
+ const char *tty;
+ char **argv;
+ char **envp;
+#ifdef HAVE_PRIV_SET
+ priv_set_t *privs;
+ priv_set_t *limitprivs;
+#endif
+ char * const *info;
+};
+
+/* Status passed between parent and child via socketpair */
+struct command_status {
+#define CMD_INVALID 0
+#define CMD_ERRNO 1
+#define CMD_WSTATUS 2
+#define CMD_SIGNO 3
+#define CMD_PID 4
+ int type;
+ int val;
+};
+
+/* Garbage collector data types. */
+enum sudo_gc_types {
+ GC_UNKNOWN,
+ GC_VECTOR,
+ GC_PTR
+};
+
+/* For fatal() and fatalx() (XXX - needed?) */
+void cleanup(int);
+
+/* tgetpass.c */
+char *tgetpass(const char *prompt, int timeout, unsigned int flags,
+ struct sudo_conv_callback *callback);
+const struct sudo_cred *sudo_askpass_cred(const struct sudo_cred *cred);
+
+/* exec.c */
+int sudo_execute(struct command_details *details, const struct user_details *ud, struct sudo_event_base *evbase, struct command_status *cstat);
+
+/* parse_args.c */
+unsigned int parse_args(int argc, char **argv, const char *shell,
+ int *old_optind, int *nargc, char ***nargv,
+ struct sudo_settings **settingsp, char ***env_addp, const char **list_user);
+extern unsigned int tgetpass_flags;
+
+/* get_pty.c */
+char *get_pty(int *leader, int *follower, uid_t uid);
+
+/* sudo.c */
+int policy_init_session(struct command_details *details);
+int run_command(struct command_details *command_details, const struct user_details *user_details);
+int os_init_common(int argc, char *argv[], char *envp[]);
+bool gc_add(enum sudo_gc_types type, void *v);
+bool set_user_groups(struct command_details *details);
+struct sudo_plugin_event *sudo_plugin_event_alloc(void);
+bool audit_accept(const char *plugin_name, unsigned int plugin_type,
+ char * const command_info[], char * const run_argv[],
+ char * const run_envp[]);
+bool audit_reject(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[]);
+bool audit_error(const char *plugin_name, unsigned int plugin_type,
+ const char *audit_msg, char * const command_info[]);
+bool approval_check(char * const command_info[], char * const run_argv[],
+ char * const run_envp[]);
+extern int sudo_debug_instance;
+
+/* sudo_edit.c */
+int sudo_edit(struct command_details *command_details, const struct user_details *user_details);
+
+/* parse_args.c */
+sudo_noreturn void usage(void);
+
+/* openbsd.c */
+int os_init_openbsd(int argc, char *argv[], char *envp[]);
+
+/* selinux.c */
+int selinux_audit_role_change(void);
+int selinux_getexeccon(const char *role, const char *type);
+int selinux_relabel_tty(const char *ttyn, int ttyfd);
+int selinux_restore_tty(void);
+int selinux_setexeccon(void);
+void selinux_execve(int fd, const char *path, char *const argv[],
+ char *envp[], const char *rundir, unsigned int flags);
+
+/* apparmor.c */
+int apparmor_is_enabled(void);
+int apparmor_prepare(const char* new_profile);
+
+/* solaris.c */
+void set_project(struct passwd *);
+int os_init_solaris(int argc, char *argv[], char *envp[]);
+
+/* hooks.c */
+/* XXX - move to sudo_plugin_int.h? */
+struct sudo_hook;
+int register_hook(struct sudo_hook *hook);
+int deregister_hook(struct sudo_hook *hook);
+int process_hooks_getenv(const char *name, char **val);
+int process_hooks_setenv(const char *name, const char *value, int overwrite);
+int process_hooks_putenv(char *string);
+int process_hooks_unsetenv(const char *name);
+
+/* env_hooks.c */
+char *getenv_unhooked(const char *name);
+
+/* interfaces.c */
+int get_net_ifs(char **addrinfo);
+
+char *get_process_ttyname(char *name, size_t namelen);
+
+/* signal.c */
+struct sigaction;
+int sudo_sigaction(int signo, struct sigaction *sa, struct sigaction *osa);
+void init_signals(void);
+void restore_signals(void);
+void save_signals(void);
+bool signal_pending(int signo);
+
+/* preload.c */
+void preload_static_symbols(void);
+
+/* preserve_fds.c */
+int add_preserved_fd(struct preserved_fd_list *pfds, int fd);
+void closefrom_except(int startfd, struct preserved_fd_list *pfds);
+void parse_preserved_fds(struct preserved_fd_list *pfds, const char *fdstr);
+
+/* limits.c */
+void disable_coredump(void);
+void restore_limits(void);
+void restore_nproc(void);
+void set_policy_rlimits(void);
+void unlimit_nproc(void);
+void unlimit_sudo(void);
+size_t serialize_rlimits(char **info, size_t info_max);
+bool parse_policy_rlimit(const char *str);
+
+/* exec_ptrace.c */
+void exec_ptrace_fix_flags(struct command_details *details);
+bool exec_ptrace_intercept_supported(void);
+bool exec_ptrace_subcmds_supported(void);
+
+#endif /* SUDO_SUDO_H */
diff --git a/src/sudo_edit.c b/src/sudo_edit.c
new file mode 100644
index 0000000..b7f7ca5
--- /dev/null
+++ b/src/sudo_edit.c
@@ -0,0 +1,796 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2004-2008, 2010-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <signal.h>
+#include <fcntl.h>
+
+#include <sudo.h>
+#include <sudo_edit.h>
+#include <sudo_exec.h>
+
+#if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID)
+
+/*
+ * Editor temporary file name along with original name, mtime and size.
+ */
+struct tempfile {
+ char *tfile;
+ char *ofile;
+ off_t osize;
+ struct timespec omtim;
+};
+
+static char edit_tmpdir[MAX(sizeof(_PATH_VARTMP), sizeof(_PATH_TMP))];
+
+/*
+ * Find our temporary directory, one of /var/tmp, /usr/tmp, or /tmp
+ * Returns true on success, else false;
+ */
+static bool
+set_tmpdir(const struct sudo_cred *user_cred)
+{
+ const char *tdir = NULL;
+ const char *tmpdirs[] = {
+ _PATH_VARTMP,
+#ifdef _PATH_USRTMP
+ _PATH_USRTMP,
+#endif
+ _PATH_TMP
+ };
+ struct sudo_cred saved_cred;
+ size_t i;
+ size_t len;
+ int dfd;
+ debug_decl(set_tmpdir, SUDO_DEBUG_EDIT);
+
+ /* Stash old credentials. */
+ saved_cred.uid = getuid();
+ saved_cred.euid = geteuid();
+ saved_cred.gid = getgid();
+ saved_cred.egid = getegid();
+ saved_cred.ngroups = getgroups(0, NULL); // -V575
+ if (saved_cred.ngroups > 0) {
+ saved_cred.groups =
+ reallocarray(NULL, (size_t)saved_cred.ngroups, sizeof(GETGROUPS_T));
+ if (saved_cred.groups == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_bool(false);
+ }
+ saved_cred.ngroups = getgroups(saved_cred.ngroups, saved_cred.groups);
+ if (saved_cred.ngroups < 0) {
+ sudo_warn("%s", U_("unable to get group list"));
+ free(saved_cred.groups);
+ debug_return_bool(false);
+ }
+ } else {
+ saved_cred.ngroups = 0;
+ saved_cred.groups = NULL;
+ }
+
+ for (i = 0; tdir == NULL && i < nitems(tmpdirs); i++) {
+ if ((dfd = open(tmpdirs[i], O_RDONLY)) != -1) {
+ if (dir_is_writable(dfd, user_cred, &saved_cred) == true)
+ tdir = tmpdirs[i];
+ close(dfd);
+ }
+ }
+ free(saved_cred.groups);
+
+ if (tdir == NULL) {
+ sudo_warnx("%s", U_("no writable temporary directory found"));
+ debug_return_bool(false);
+ }
+
+ len = strlcpy(edit_tmpdir, tdir, sizeof(edit_tmpdir));
+ if (len >= sizeof(edit_tmpdir)) {
+ errno = ENAMETOOLONG;
+ sudo_warn("%s", tdir);
+ debug_return_bool(false);
+ }
+ while (len > 0 && edit_tmpdir[--len] == '/')
+ edit_tmpdir[len] = '\0';
+ debug_return_bool(true);
+}
+
+/*
+ * Construct a temporary file name for file and return an
+ * open file descriptor. The temporary file name is stored
+ * in tfile which the caller is responsible for freeing.
+ */
+static int
+sudo_edit_mktemp(const char *ofile, char **tfile)
+{
+ const char *base, *suff;
+ int len, tfd;
+ debug_decl(sudo_edit_mktemp, SUDO_DEBUG_EDIT);
+
+ base = sudo_basename(ofile);
+ suff = strrchr(base, '.');
+ if (suff != NULL) {
+ len = asprintf(tfile, "%s/%.*sXXXXXXXX%s", edit_tmpdir,
+ (int)(size_t)(suff - base), base, suff);
+ } else {
+ len = asprintf(tfile, "%s/%s.XXXXXXXX", edit_tmpdir, base);
+ }
+ if (len == -1) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ debug_return_int(-1);
+ }
+ tfd = mkstemps(*tfile, suff ? (int)strlen(suff) : 0);
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "%s -> %s, fd %d", ofile, *tfile, tfd);
+ debug_return_int(tfd);
+}
+
+/*
+ * Create temporary copies of files[] and store the temporary path name
+ * along with the original name, size and mtime in tf.
+ * Returns the number of files copied (which may be less than nfiles)
+ * or -1 if a fatal error occurred.
+ */
+static int
+sudo_edit_create_tfiles(const struct command_details *command_details,
+ const struct sudo_cred *user_cred, struct tempfile *tf, char *files[],
+ int nfiles)
+{
+ int i, j, tfd, ofd, rc;
+ struct timespec times[2];
+ struct stat sb;
+ debug_decl(sudo_edit_create_tfiles, SUDO_DEBUG_EDIT);
+
+ /*
+ * For each file specified by the user, make a temporary version
+ * and copy the contents of the original to it.
+ */
+ for (i = 0, j = 0; i < nfiles; i++) {
+ rc = -1;
+ switch_user(command_details->cred.euid, command_details->cred.egid,
+ command_details->cred.ngroups, command_details->cred.groups);
+ ofd = sudo_edit_open(files[i], O_RDONLY,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, command_details->flags,
+ user_cred, &command_details->cred);
+ if (ofd != -1 || errno == ENOENT) {
+ if (ofd != -1) {
+ rc = fstat(ofd, &sb);
+ } else {
+ /* New file, verify parent dir exists and is not writable. */
+ memset(&sb, 0, sizeof(sb));
+ if (sudo_edit_parent_valid(files[i], command_details->flags, user_cred, &command_details->cred))
+ rc = 0;
+ }
+ }
+ switch_user(ROOT_UID, user_cred->egid, user_cred->ngroups, user_cred->groups);
+ if (ofd != -1 && !S_ISREG(sb.st_mode)) {
+ sudo_warnx(U_("%s: not a regular file"), files[i]);
+ close(ofd);
+ continue;
+ }
+ if (rc == -1) {
+ /* open() or fstat() error. */
+ if (ofd == -1 && errno == ELOOP) {
+ sudo_warnx(U_("%s: editing symbolic links is not permitted"),
+ files[i]);
+ } else if (ofd == -1 && errno == EISDIR) {
+ sudo_warnx(U_("%s: editing files in a writable directory is not permitted"),
+ files[i]);
+ } else {
+ sudo_warn("%s", files[i]);
+ }
+ if (ofd != -1)
+ close(ofd);
+ continue;
+ }
+ tf[j].ofile = files[i];
+ tf[j].osize = sb.st_size; // -V614
+ mtim_get(&sb, tf[j].omtim);
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "seteuid(%u)", (unsigned int)user_cred->uid);
+ if (seteuid(user_cred->uid) != 0)
+ sudo_fatal("seteuid(%u)", (unsigned int)user_cred->uid);
+ tfd = sudo_edit_mktemp(tf[j].ofile, &tf[j].tfile);
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "seteuid(%u)", ROOT_UID);
+ if (seteuid(ROOT_UID) != 0)
+ sudo_fatal("seteuid(ROOT_UID)");
+ if (tfd == -1) {
+ sudo_warn("mkstemps");
+ if (ofd != -1)
+ close(ofd);
+ debug_return_int(-1);
+ }
+ if (ofd != -1) {
+ if (sudo_copy_file(tf[j].ofile, ofd, tf[j].osize, tf[j].tfile, tfd, -1) == -1) {
+ close(ofd);
+ close(tfd);
+ debug_return_int(-1);
+ }
+ close(ofd);
+ }
+ /*
+ * We always update the stashed mtime because the time
+ * resolution of the filesystem the temporary file is on may
+ * not match that of the filesystem where the file to be edited
+ * resides. It is OK if futimens() fails since we only use the
+ * info to determine whether or not a file has been modified.
+ */
+ times[0].tv_sec = times[1].tv_sec = tf[j].omtim.tv_sec;
+ times[0].tv_nsec = times[1].tv_nsec = tf[j].omtim.tv_nsec;
+ if (futimens(tfd, times) == -1) {
+ if (utimensat(AT_FDCWD, tf[j].tfile, times, 0) == -1)
+ sudo_warn("%s", tf[j].tfile);
+ }
+ rc = fstat(tfd, &sb);
+ if (!rc)
+ mtim_get(&sb, tf[j].omtim);
+ close(tfd);
+ j++;
+ }
+ debug_return_int(j);
+}
+
+/*
+ * Copy the temporary files specified in tf to the originals.
+ * Returns the number of copy errors or 0 if completely successful.
+ */
+static int
+sudo_edit_copy_tfiles(const struct command_details *command_details,
+ const struct sudo_cred *user_cred, struct tempfile *tf,
+ int nfiles, struct timespec *times)
+{
+ int i, tfd, ofd, errors = 0;
+ struct timespec ts;
+ struct stat sb;
+ mode_t oldmask;
+ debug_decl(sudo_edit_copy_tfiles, SUDO_DEBUG_EDIT);
+
+ /* Copy contents of temp files to real ones. */
+ for (i = 0; i < nfiles; i++) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "seteuid(%u)", (unsigned int)user_cred->uid);
+ if (seteuid(user_cred->uid) != 0)
+ sudo_fatal("seteuid(%u)", (unsigned int)user_cred->uid);
+ tfd = sudo_edit_open(tf[i].tfile, O_RDONLY,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 0, user_cred, NULL);
+ if (seteuid(ROOT_UID) != 0)
+ sudo_fatal("seteuid(ROOT_UID)");
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "seteuid(%u)", ROOT_UID);
+ if (tfd == -1 || !sudo_check_temp_file(tfd, tf[i].tfile, user_cred->uid, &sb)) {
+ sudo_warnx(U_("%s left unmodified"), tf[i].ofile);
+ if (tfd != -1)
+ close(tfd);
+ errors++;
+ continue;
+ }
+ mtim_get(&sb, ts);
+ if (tf[i].osize == sb.st_size && sudo_timespeccmp(&tf[i].omtim, &ts, ==)) {
+ /*
+ * If mtime and size match but the user spent no measurable
+ * time in the editor we can't tell if the file was changed.
+ */
+ if (sudo_timespeccmp(&times[0], &times[1], !=)) {
+ sudo_warnx(U_("%s unchanged"), tf[i].ofile);
+ unlink(tf[i].tfile);
+ close(tfd);
+ continue;
+ }
+ }
+ switch_user(command_details->cred.euid, command_details->cred.egid,
+ command_details->cred.ngroups, command_details->cred.groups);
+ oldmask = umask(command_details->umask);
+ ofd = sudo_edit_open(tf[i].ofile, O_WRONLY|O_CREAT,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, command_details->flags,
+ user_cred, &command_details->cred);
+ umask(oldmask);
+ switch_user(ROOT_UID, user_cred->egid, user_cred->ngroups, user_cred->groups);
+ if (ofd == -1) {
+ sudo_warn(U_("unable to write to %s"), tf[i].ofile);
+ goto bad;
+ }
+
+ /* Overwrite the old file with the new contents. */
+ if (sudo_copy_file(tf[i].tfile, tfd, sb.st_size, tf[i].ofile, ofd,
+ tf[i].osize) == 0) {
+ /* success, remove temporary file. */
+ unlink(tf[i].tfile);
+ } else {
+bad:
+ sudo_warnx(U_("contents of edit session left in %s"), tf[i].tfile);
+ errors++;
+ }
+
+ if (ofd != -1)
+ close(ofd);
+ close(tfd);
+ }
+ debug_return_int(errors);
+}
+
+#ifdef HAVE_SELINUX
+static int
+selinux_run_helper(uid_t uid, gid_t gid, int ngroups, GETGROUPS_T *groups,
+ char *const argv[], char *const envp[])
+{
+ int status, ret = SESH_ERR_FAILURE;
+ const char *sesh;
+ pid_t child, pid;
+ debug_decl(selinux_run_helper, SUDO_DEBUG_EDIT);
+
+ sesh = sudo_conf_sesh_path();
+ if (sesh == NULL) {
+ sudo_warnx("internal error: sesh path not set");
+ debug_return_int(-1);
+ }
+
+ child = sudo_debug_fork();
+ switch (child) {
+ case -1:
+ sudo_warn("%s", U_("unable to fork"));
+ break;
+ case 0:
+ /* child runs sesh in new context */
+ if (selinux_setexeccon() == 0) {
+ switch_user(uid, gid, ngroups, groups);
+ execve(sesh, argv, envp);
+ }
+ _exit(SESH_ERR_FAILURE);
+ default:
+ /* parent waits */
+ do {
+ pid = waitpid(child, &status, 0);
+ } while (pid == -1 && errno == EINTR);
+
+ ret = WIFSIGNALED(status) ? SESH_ERR_KILLED : WEXITSTATUS(status);
+ }
+
+ debug_return_int(ret);
+}
+
+static char *
+selinux_fmt_sudo_user(const struct sudo_cred *user_cred)
+{
+ char *cp, *user_str;
+ size_t user_size;
+ int i, len;
+ debug_decl(selinux_fmt_sudo_user, SUDO_DEBUG_EDIT);
+
+ user_size = (STRLEN_MAX_UNSIGNED(uid_t) + 1) * (2 + user_cred->ngroups);
+ if ((user_str = malloc(user_size)) == NULL)
+ debug_return_ptr(NULL);
+
+ /* UID:GID: */
+ len = snprintf(user_str, user_size, "%u:%u:",
+ (unsigned int)user_cred->uid, (unsigned int)user_cred->gid);
+ if (len < 0 || (size_t)len >= user_size)
+ sudo_fatalx(U_("internal error, %s overflow"), __func__);
+
+ /* Supplementary GIDs */
+ cp = user_str + len;
+ for (i = 0; i < user_cred->ngroups; i++) {
+ len = snprintf(cp, user_size - (cp - user_str), "%s%u",
+ i ? "," : "", (unsigned int)user_cred->groups[i]);
+ if (len < 0 || (size_t)len >= user_size - (cp - user_str))
+ sudo_fatalx(U_("internal error, %s overflow"), __func__);
+ cp += len;
+ }
+
+ debug_return_ptr(user_str);
+}
+
+static int
+selinux_edit_create_tfiles(const struct command_details *command_details,
+ const struct sudo_cred *user_cred, struct tempfile *tf,
+ char *files[], int nfiles)
+{
+ const char **sesh_args, **sesh_ap;
+ char *user_str = NULL;
+ int i, error, sesh_nargs, ret = -1;
+ struct stat sb;
+ debug_decl(selinux_edit_create_tfiles, SUDO_DEBUG_EDIT);
+
+ if (nfiles < 1)
+ debug_return_int(0);
+
+ sesh_nargs = 6 + (nfiles * 2) + 1;
+ sesh_args = sesh_ap = reallocarray(NULL, sesh_nargs, sizeof(char *));
+ if (sesh_args == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ *sesh_ap++ = "sesh";
+ *sesh_ap++ = "--edit-create";
+ if (!ISSET(command_details->flags, CD_SUDOEDIT_FOLLOW))
+ *sesh_ap++ = "--no-dereference";
+ if (ISSET(command_details->flags, CD_SUDOEDIT_CHECKDIR)) {
+ if ((user_str = selinux_fmt_sudo_user(user_cred)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ *sesh_ap++ = "--edit-checkdir";
+ *sesh_ap++ = user_str;
+ }
+ *sesh_ap++ = "--";
+
+ for (i = 0; i < nfiles; i++) {
+ char *tfile, *ofile = files[i];
+ int tfd;
+ *sesh_ap++ = ofile;
+ tf[i].ofile = ofile;
+ if (stat(ofile, &sb) == -1)
+ memset(&sb, 0, sizeof(sb)); /* new file */
+ tf[i].osize = sb.st_size;
+ mtim_get(&sb, tf[i].omtim);
+ /*
+ * The temp file must be created by the sesh helper,
+ * which uses O_EXCL | O_NOFOLLOW to make this safe.
+ */
+ tfd = sudo_edit_mktemp(ofile, &tfile);
+ if (tfd == -1) {
+ sudo_warn("mkstemps");
+ free(tfile);
+ goto done;
+ }
+ /* Helper will re-create temp file with proper security context. */
+ close(tfd);
+ unlink(tfile);
+ *sesh_ap++ = tfile;
+ tf[i].tfile = tfile;
+ }
+ *sesh_ap = NULL;
+
+ /* Run sesh -c [-h] [-w userstr] <o1> <t1> ... <on> <tn> */
+ error = selinux_run_helper(command_details->cred.uid,
+ command_details->cred.gid, command_details->cred.ngroups,
+ command_details->cred.groups, (char **)sesh_args, command_details->envp);
+ switch (error) {
+ case SESH_SUCCESS:
+ break;
+ case SESH_ERR_BAD_PATHS:
+ sudo_fatalx("%s", U_("sesh: internal error: odd number of paths"));
+ case SESH_ERR_NO_FILES:
+ sudo_fatalx("%s", U_("sesh: unable to create temporary files"));
+ case SESH_ERR_KILLED:
+ sudo_fatalx("%s", U_("sesh: killed by a signal"));
+ default:
+ sudo_warnx(U_("sesh: unknown error %d"), error);
+ goto done;
+ }
+
+ for (i = 0; i < nfiles; i++) {
+ int tfd = open(tf[i].tfile, O_RDONLY|O_NONBLOCK|O_NOFOLLOW);
+ if (tfd == -1) {
+ sudo_warn(U_("unable to open %s"), tf[i].tfile);
+ goto done;
+ }
+ if (!sudo_check_temp_file(tfd, tf[i].tfile, command_details->cred.uid, NULL)) {
+ close(tfd);
+ goto done;
+ }
+ if (fchown(tfd, user_cred->uid, user_cred->gid) != 0) {
+ sudo_warn("unable to chown(%s) to %d:%d for editing",
+ tf[i].tfile, user_cred->uid, user_cred->gid);
+ close(tfd);
+ goto done;
+ }
+ close(tfd);
+ }
+ ret = nfiles;
+
+done:
+ /* Contents of tf will be freed by caller. */
+ free(sesh_args);
+ free(user_str);
+
+ debug_return_int(ret);
+}
+
+static int
+selinux_edit_copy_tfiles(const struct command_details *command_details,
+ const struct sudo_cred *user_cred, struct tempfile *tf,
+ int nfiles, struct timespec *times)
+{
+ const char **sesh_args, **sesh_ap;
+ char *user_str = NULL;
+ bool run_helper = false;
+ int i, error, sesh_nargs, ret = 1;
+ int tfd = -1;
+ struct timespec ts;
+ struct stat sb;
+ debug_decl(selinux_edit_copy_tfiles, SUDO_DEBUG_EDIT);
+
+ if (nfiles < 1)
+ debug_return_int(0);
+
+ sesh_nargs = 5 + (nfiles * 2) + 1;
+ sesh_args = sesh_ap = reallocarray(NULL, sesh_nargs, sizeof(char *));
+ if (sesh_args == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ *sesh_ap++ = "sesh";
+ *sesh_ap++ = "--edit-install";
+ if (ISSET(command_details->flags, CD_SUDOEDIT_CHECKDIR)) {
+ if ((user_str = selinux_fmt_sudo_user(user_cred)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ *sesh_ap++ = "--edit-checkdir";
+ *sesh_ap++ = user_str;
+ }
+ *sesh_ap++ = "--";
+
+ for (i = 0; i < nfiles; i++) {
+ if (tfd != -1)
+ close(tfd);
+ if ((tfd = open(tf[i].tfile, O_RDONLY|O_NONBLOCK|O_NOFOLLOW)) == -1) {
+ sudo_warn(U_("unable to open %s"), tf[i].tfile);
+ continue;
+ }
+ if (!sudo_check_temp_file(tfd, tf[i].tfile, user_cred->uid, &sb))
+ continue;
+ mtim_get(&sb, ts);
+ if (tf[i].osize == sb.st_size && sudo_timespeccmp(&tf[i].omtim, &ts, ==)) {
+ /*
+ * If mtime and size match but the user spent no measurable
+ * time in the editor we can't tell if the file was changed.
+ */
+ if (sudo_timespeccmp(&times[0], &times[1], !=)) {
+ sudo_warnx(U_("%s unchanged"), tf[i].ofile);
+ unlink(tf[i].tfile);
+ continue;
+ }
+ }
+ run_helper = true;
+ *sesh_ap++ = tf[i].tfile;
+ *sesh_ap++ = tf[i].ofile;
+ if (fchown(tfd, command_details->cred.uid, command_details->cred.gid) != 0) {
+ sudo_warn("unable to chown(%s) back to %d:%d", tf[i].tfile,
+ command_details->cred.uid, command_details->cred.gid);
+ }
+ }
+ *sesh_ap = NULL;
+
+ if (!run_helper)
+ goto done;
+
+ /* Run sesh -i <t1> <o1> ... <tn> <on> */
+ error = selinux_run_helper(command_details->cred.uid,
+ command_details->cred.gid, command_details->cred.ngroups,
+ command_details->cred.groups, (char **)sesh_args, command_details->envp);
+ switch (error) {
+ case SESH_SUCCESS:
+ ret = 0;
+ break;
+ case SESH_ERR_NO_FILES:
+ sudo_warnx("%s",
+ U_("unable to copy temporary files back to their original location"));
+ break;
+ case SESH_ERR_SOME_FILES:
+ sudo_warnx("%s",
+ U_("unable to copy some of the temporary files back to their original location"));
+ break;
+ case SESH_ERR_KILLED:
+ sudo_warnx("%s", U_("sesh: killed by a signal"));
+ break;
+ default:
+ sudo_warnx(U_("sesh: unknown error %d"), error);
+ break;
+ }
+
+done:
+ if (tfd != -1)
+ close(tfd);
+ /* Contents of tf will be freed by caller. */
+ free(sesh_args);
+ free(user_str);
+
+ debug_return_int(ret);
+}
+#endif /* HAVE_SELINUX */
+
+/*
+ * Wrapper to allow users to edit privileged files with their own uid.
+ * Returns the wait status of the command on success and a wait status
+ * of 1 on failure.
+ */
+int
+sudo_edit(struct command_details *command_details,
+ const struct user_details *user_details)
+{
+ struct command_details saved_command_details;
+ const struct sudo_cred *user_cred = &user_details->cred;
+ char **nargv = NULL, **files = NULL;
+ int nfiles = command_details->nfiles;
+ int errors, i, ac, nargc, ret;
+ int editor_argc = 0;
+ struct timespec times[2];
+ struct tempfile *tf = NULL;
+ debug_decl(sudo_edit, SUDO_DEBUG_EDIT);
+
+ /*
+ * Set real, effective and saved uids to root.
+ * We will change the euid as needed below.
+ */
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "setuid(%u)", ROOT_UID);
+ if (setuid(ROOT_UID) != 0) {
+ sudo_warn(U_("unable to change uid to root (%u)"), ROOT_UID);
+ goto cleanup;
+ }
+
+ /* Find a temporary directory writable by the user. */
+ if (!set_tmpdir(user_cred))
+ goto cleanup;
+
+ if (nfiles > 0) {
+ /*
+ * The plugin specified the number of files to edit, use it.
+ */
+ editor_argc = command_details->argc - nfiles;
+ if (editor_argc < 2 || strcmp(command_details->argv[editor_argc - 1], "--") != 0) {
+ sudo_warnx("%s", U_("plugin error: invalid file list for sudoedit"));
+ goto cleanup;
+ }
+
+ /* We don't include the "--" when running the user's editor. */
+ files = &command_details->argv[editor_argc--];
+ } else {
+ /*
+ * Compute the number of files to edit by looking for the "--"
+ * option which separate the editor from the files.
+ */
+ for (i = 0; command_details->argv[i] != NULL; i++) {
+ if (strcmp(command_details->argv[i], "--") == 0) {
+ editor_argc = i;
+ files = &command_details->argv[i + 1];
+ nfiles = command_details->argc - (i + 1);
+ break;
+ }
+ }
+ }
+ if (nfiles == 0) {
+ sudo_warnx("%s", U_("plugin error: missing file list for sudoedit"));
+ goto cleanup;
+ }
+
+ /* Copy editor files to temporaries. */
+ tf = calloc((size_t)nfiles, sizeof(*tf));
+ if (tf == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto cleanup;
+ }
+#ifdef HAVE_SELINUX
+ if (ISSET(command_details->flags, CD_RBAC_ENABLED))
+ nfiles = selinux_edit_create_tfiles(command_details, user_cred, tf, files, nfiles);
+ else
+#endif
+ nfiles = sudo_edit_create_tfiles(command_details, user_cred, tf, files, nfiles);
+ if (nfiles <= 0)
+ goto cleanup;
+
+ /*
+ * Allocate space for the new argument vector and fill it in.
+ * We concatenate the editor with its args and the file list
+ * to create a new argv.
+ */
+ nargc = editor_argc + nfiles;
+ nargv = reallocarray(NULL, (size_t)nargc + 1, sizeof(char *));
+ if (nargv == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto cleanup;
+ }
+ for (ac = 0; ac < editor_argc; ac++)
+ nargv[ac] = command_details->argv[ac];
+ for (i = 0; i < nfiles && ac < nargc; )
+ nargv[ac++] = tf[i++].tfile;
+ nargv[ac] = NULL;
+
+ /*
+ * Run the editor with the invoking user's creds and drop setuid.
+ * Keep track of the time spent in the editor to distinguish between
+ * a user editing a file and a program doing it.
+ * XXX - should run editor with user's context
+ */
+ if (sudo_gettime_real(&times[0]) == -1) {
+ sudo_warn("%s", U_("unable to read the clock"));
+ goto cleanup;
+ }
+#ifdef HAVE_SELINUX
+ if (ISSET(command_details->flags, CD_RBAC_ENABLED))
+ selinux_audit_role_change();
+#endif
+ memcpy(&saved_command_details, command_details, sizeof(struct command_details));
+ command_details->cred = *user_cred;
+ command_details->cred.euid = user_cred->uid;
+ command_details->cred.egid = user_cred->gid;
+ command_details->argc = nargc;
+ command_details->argv = nargv;
+ ret = run_command(command_details, user_details);
+ if (sudo_gettime_real(&times[1]) == -1) {
+ sudo_warn("%s", U_("unable to read the clock"));
+ goto cleanup;
+ }
+
+ /* Restore saved command_details. */
+ command_details->cred = saved_command_details.cred;
+ command_details->argc = saved_command_details.argc;
+ command_details->argv = saved_command_details.argv;
+
+ /* Copy contents of temp files to real ones. */
+#ifdef HAVE_SELINUX
+ if (ISSET(command_details->flags, CD_RBAC_ENABLED))
+ errors = selinux_edit_copy_tfiles(command_details, user_cred, tf, nfiles, times);
+ else
+#endif
+ errors = sudo_edit_copy_tfiles(command_details, user_cred, tf, nfiles, times);
+ if (errors) {
+ /* Preserve the edited temporary files. */
+ ret = W_EXITCODE(1, 0);
+ }
+
+ for (i = 0; i < nfiles; i++)
+ free(tf[i].tfile);
+ free(tf);
+ free(nargv);
+ debug_return_int(ret);
+
+cleanup:
+ /* Clean up temp files and return. */
+ if (tf != NULL) {
+ for (i = 0; i < nfiles; i++) {
+ if (tf[i].tfile != NULL)
+ unlink(tf[i].tfile);
+ free(tf[i].tfile);
+ }
+ }
+ free(tf);
+ free(nargv);
+ debug_return_int(W_EXITCODE(1, 0));
+}
+
+#else /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */
+
+/*
+ * Must have the ability to change the effective uid to use sudoedit.
+ */
+int
+sudo_edit(const struct command_details *command_details, const struct sudo_cred *user_cred)
+{
+ debug_decl(sudo_edit, SUDO_DEBUG_EDIT);
+ debug_return_int(W_EXITCODE(1, 0));
+}
+
+#endif /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */
diff --git a/src/sudo_edit.h b/src/sudo_edit.h
new file mode 100644
index 0000000..3209b9f
--- /dev/null
+++ b/src/sudo_edit.h
@@ -0,0 +1,55 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_EDIT_H
+#define SUDO_EDIT_H
+
+/*
+ * Directory open flags for use with openat(2).
+ * Use O_SEARCH/O_PATH and/or O_DIRECTORY where possible.
+ */
+#if defined(O_SEARCH)
+# if defined(O_DIRECTORY)
+# define DIR_OPEN_FLAGS (O_SEARCH|O_DIRECTORY)
+# else
+# define DIR_OPEN_FLAGS (O_SEARCH)
+# endif
+#elif defined(O_PATH)
+# if defined(O_DIRECTORY)
+# define DIR_OPEN_FLAGS (O_PATH|O_DIRECTORY)
+# else
+# define DIR_OPEN_FLAGS (O_PATH)
+# endif
+#elif defined(O_DIRECTORY)
+# define DIR_OPEN_FLAGS (O_RDONLY|O_DIRECTORY)
+#else
+# define DIR_OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
+#endif
+
+/* copy_file.c */
+int sudo_copy_file(const char *src, int src_fd, off_t src_len, const char *dst, int dst_fd, off_t dst_len);
+bool sudo_check_temp_file(int tfd, const char *tname, uid_t uid, struct stat *sb);
+
+/* edit_open.c */
+struct sudo_cred;
+void switch_user(uid_t euid, gid_t egid, int ngroups, GETGROUPS_T *groups);
+int sudo_edit_open(char *path, int oflags, mode_t mode, unsigned int sflags, const struct sudo_cred *user_cred, const struct sudo_cred *cur_cred);
+int dir_is_writable(int dfd, const struct sudo_cred *user_cred, const struct sudo_cred *cur_cred);
+bool sudo_edit_parent_valid(char *path, unsigned int sflags, const struct sudo_cred *user_cred, const struct sudo_cred *cur_cred);
+
+#endif /* SUDO_EDIT_H */
diff --git a/src/sudo_exec.h b/src/sudo_exec.h
new file mode 100644
index 0000000..7dbda8a
--- /dev/null
+++ b/src/sudo_exec.h
@@ -0,0 +1,236 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2017, 2020-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_EXEC_H
+#define SUDO_EXEC_H
+
+/*
+ * Older systems may not support MSG_WAITALL but it shouldn't really be needed.
+ */
+#ifndef MSG_WAITALL
+# define MSG_WAITALL 0
+#endif
+
+/*
+ * Linux-specific wait flag used with ptrace(2).
+ */
+#ifndef __WALL
+# define __WALL 0
+#endif
+
+/*
+ * Some older systems support siginfo but predate SI_USER.
+ */
+#ifdef SI_USER
+# define USER_SIGNALED(_info) ((_info) != NULL && (_info)->si_code == SI_USER)
+#else
+# define USER_SIGNALED(_info) ((_info) != NULL && (_info)->si_code <= 0)
+#endif
+
+struct user_details;
+struct command_details;
+struct command_status;
+struct sudo_event_base;
+struct stat;
+
+/*
+ * Closure passed to I/O event callbacks.
+ */
+struct exec_closure {
+ struct command_details *details;
+ struct sudo_event_base *evbase;
+ struct sudo_event *backchannel_event;
+ struct sudo_event *fwdchannel_event;
+ struct sudo_event *sigint_event;
+ struct sudo_event *sigquit_event;
+ struct sudo_event *sigtstp_event;
+ struct sudo_event *sigterm_event;
+ struct sudo_event *sighup_event;
+ struct sudo_event *sigalrm_event;
+ struct sudo_event *sigpipe_event;
+ struct sudo_event *sigusr1_event;
+ struct sudo_event *sigusr2_event;
+ struct sudo_event *sigchld_event;
+ struct sudo_event *sigcont_event;
+ struct sudo_event *siginfo_event;
+ struct sudo_event *sigwinch_event;
+ struct command_status *cstat;
+ char *ptyname;
+ void *intercept;
+ pid_t sudo_pid;
+ pid_t monitor_pid;
+ pid_t cmnd_pid;
+ pid_t ppgrp;
+ int rows;
+ int cols;
+ bool foreground;
+ bool term_raw;
+};
+
+/*
+ * I/O buffer with associated read/write events and a logging action.
+ * Used to, e.g. pass data from the pty to the user's terminal
+ * and any I/O logging plugins.
+ */
+struct io_buffer;
+typedef bool (*sudo_io_action_t)(const char *, unsigned int, struct io_buffer *);
+struct io_buffer {
+ SLIST_ENTRY(io_buffer) entries;
+ struct exec_closure *ec;
+ struct sudo_event *revent;
+ struct sudo_event *wevent;
+ sudo_io_action_t action;
+ unsigned int len; /* buffer length (how much produced) */
+ unsigned int off; /* write position (how much already consumed) */
+ char buf[64 * 1024];
+};
+SLIST_HEAD(io_buffer_list, io_buffer);
+
+/*
+ * Indices into io_fds[] when logging I/O.
+ */
+#define SFD_STDIN 0
+#define SFD_STDOUT 1
+#define SFD_STDERR 2
+#define SFD_LEADER 3
+#define SFD_FOLLOWER 4
+#define SFD_USERTTY 5
+
+/* Evaluates to true if the event has /dev/tty as its fd. */
+#define USERTTY_EVENT(_ev) (sudo_ev_get_fd((_ev)) == io_fds[SFD_USERTTY])
+
+/*
+ * Special values to indicate whether continuing in foreground or background.
+ */
+#define SIGCONT_FG -2
+#define SIGCONT_BG -3
+
+/*
+ * Positions in saved_signals[]
+ */
+#define SAVED_SIGALRM 0
+#define SAVED_SIGCHLD 1
+#define SAVED_SIGCONT 2
+#define SAVED_SIGHUP 3
+#define SAVED_SIGINT 4
+#define SAVED_SIGPIPE 5
+#define SAVED_SIGQUIT 6
+#define SAVED_SIGTERM 7
+#define SAVED_SIGTSTP 8
+#define SAVED_SIGTTIN 9
+#define SAVED_SIGTTOU 10
+#define SAVED_SIGUSR1 11
+#define SAVED_SIGUSR2 12
+
+/*
+ * Error codes for sesh
+ */
+#define SESH_SUCCESS 0 /* successful operation */
+#define SESH_ERR_FAILURE 1 /* unspecified error */
+#define SESH_ERR_KILLED 2 /* killed by a signal */
+#define SESH_ERR_INVALID 30 /* invalid -e arg value */
+#define SESH_ERR_BAD_PATHS 31 /* odd number of paths */
+#define SESH_ERR_NO_FILES 32 /* copy error, no files copied */
+#define SESH_ERR_SOME_FILES 33 /* copy error, some files copied */
+
+#define INTERCEPT_FD_MIN 64 /* minimum fd so shell won't close it */
+#define MESSAGE_SIZE_MAX 2097152 /* 2Mib max intercept message size */
+
+union sudo_token_un {
+ unsigned char u8[16];
+ unsigned int u32[4];
+ unsigned long long u64[2];
+};
+
+#define sudo_token_isset(_t) ((_t).u64[0] || (_t).u64[1])
+
+/*
+ * Use ptrace-based intercept (using seccomp) on Linux if possible.
+ * On MIPS we can't change the syscall return and only support log_subcmds.
+ */
+#if defined(_PATH_SUDO_INTERCEPT) && defined(__linux__)
+# if defined(HAVE_DECL_SECCOMP_MODE_FILTER) && HAVE_DECL_SECCOMP_MODE_FILTER
+# if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || defined(__arm__) || defined(__mips__) || defined(__powerpc__) || (defined(__riscv) && __riscv_xlen == 64) || defined(__s390__)
+# ifndef HAVE_PTRACE_INTERCEPT
+# define HAVE_PTRACE_INTERCEPT 1
+# endif /* HAVE_PTRACE_INTERCEPT */
+# endif /* __amd64__ || __i386__ || __aarch64__ || __riscv || __s390__ */
+# endif /* HAVE_DECL_SECCOMP_MODE_FILTER */
+#endif /* _PATH_SUDO_INTERCEPT && __linux__ */
+
+/* exec.c */
+struct stat;
+void exec_cmnd(struct command_details *details, sigset_t *mask, int intercept_fd, int errfd);
+void terminate_command(pid_t pid, bool use_pgrp);
+bool sudo_terminated(struct command_status *cstat);
+void free_exec_closure(struct exec_closure *ec);
+bool fd_matches_tty(int fd, struct stat *tty_sb, struct stat *fd_sb);
+
+/* exec_common.c */
+int sudo_execve(int fd, const char *path, char *const argv[], char *envp[], int intercept_fd, unsigned int flags);
+char **disable_execute(char *envp[], const char *dso);
+char **enable_monitor(char *envp[], const char *dso);
+
+/* exec_intercept.c */
+void *intercept_setup(int fd, struct sudo_event_base *evbase, const struct command_details *details);
+void intercept_cleanup(struct exec_closure *ec);
+
+/* exec_iolog.c */
+bool log_ttyin(const char *buf, unsigned int n, struct io_buffer *iob);
+bool log_stdin(const char *buf, unsigned int n, struct io_buffer *iob);
+bool log_ttyout(const char *buf, unsigned int n, struct io_buffer *iob);
+bool log_stdout(const char *buf, unsigned int n, struct io_buffer *iob);
+bool log_stderr(const char *buf, unsigned int n, struct io_buffer *iob);
+void log_suspend(void *v, int signo);
+void log_winchange(struct exec_closure *ec, unsigned int rows, unsigned int cols);
+void io_buf_new(int rfd, int wfd, bool (*action)(const char *, unsigned int, struct io_buffer *), void (*read_cb)(int fd, int what, void *v), void (*write_cb)(int fd, int what, void *v), struct exec_closure *ec);
+int safe_close(int fd);
+void ev_free_by_fd(struct sudo_event_base *evbase, int fd);
+void free_io_bufs(void);
+void add_io_events(struct exec_closure *ec);
+void del_io_events(bool nonblocking);
+void init_ttyblock(void);
+
+/* exec_nopty.c */
+void exec_nopty(struct command_details *details, const struct user_details *user_details, struct sudo_event_base *evbase, struct command_status *cstat);
+
+/* exec_pty.c */
+bool exec_pty(struct command_details *details, const struct user_details *user_details, struct sudo_event_base *evbase, struct command_status *cstat);
+extern int io_fds[6];
+
+/* exec_monitor.c */
+int exec_monitor(struct command_details *details, sigset_t *omask, bool foreground, int backchannel, int intercept_fd);
+
+/* utmp.c */
+bool utmp_login(const char *from_line, const char *to_line, int ttyfd,
+ const char *user);
+bool utmp_logout(const char *line, int status);
+
+/* exec_preload.c */
+char **sudo_preload_dso(char *const envp[], const char *dso_file, int intercept_fd);
+char **sudo_preload_dso_mmap(char *const envp[], const char *dso_file, int intercept_fd);
+
+/* exec_ptrace.c */
+bool exec_ptrace_stopped(pid_t pid, int status, void *intercept);
+bool set_exec_filter(void);
+int exec_ptrace_seize(pid_t child);
+
+/* suspend_parent.c */
+void sudo_suspend_parent(int signo, pid_t my_pid, pid_t my_pgrp, pid_t cmnd_pid, void *closure, void (*callback)(void *, int));
+
+#endif /* SUDO_EXEC_H */
diff --git a/src/sudo_intercept.c b/src/sudo_intercept.c
new file mode 100644
index 0000000..4eeb71c
--- /dev/null
+++ b/src/sudo_intercept.c
@@ -0,0 +1,595 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+#include <signal.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#if defined(HAVE_SHL_LOAD)
+# include <dl.h>
+#elif defined(HAVE_DLOPEN)
+# include <dlfcn.h>
+#endif
+#ifdef HAVE_CRT_EXTERNS_H
+# include <crt_externs.h>
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_debug.h>
+#include <sudo_util.h>
+#include <pathnames.h>
+
+/* execl flavors */
+#define SUDO_EXECL 0x0
+#define SUDO_EXECLE 0x1
+#define SUDO_EXECLP 0x2
+
+#ifdef HAVE__NSGETENVIRON
+# define environ (*_NSGetEnviron())
+#else
+extern char **environ;
+#endif
+
+extern bool command_allowed(const char *cmnd, char * const argv[], char * const envp[], char **ncmnd, char ***nargv, char ***nenvp);
+
+typedef int (*sudo_fn_execve_t)(const char *, char *const *, char *const *);
+
+static void
+free_vector(char **vec)
+{
+ char **cur;
+ debug_decl(free_vector, SUDO_DEBUG_EXEC);
+
+ if (vec != NULL) {
+ for (cur = vec; *cur != NULL; cur++) {
+ sudo_mmap_free(*cur);
+ }
+ sudo_mmap_free(vec);
+ }
+
+ debug_return;
+}
+
+static char **
+copy_vector(char * const *src)
+{
+ char **copy;
+ size_t i, len = 0;
+ debug_decl(copy_vector, SUDO_DEBUG_EXEC);
+
+ if (src != NULL) {
+ while (src[len] != NULL)
+ len++;
+ }
+ copy = sudo_mmap_allocarray(len + 1, sizeof(char *));
+ if (copy == NULL) {
+ debug_return_ptr(NULL);
+ }
+ for (i = 0; i < len; i++) {
+ copy[i] = sudo_mmap_strdup(src[i]);
+ if (copy[i] == NULL) {
+ free_vector(copy);
+ debug_return_ptr(NULL);
+ }
+ }
+ copy[i] = NULL;
+
+ debug_return_ptr(copy);
+}
+
+/*
+ * We do PATH resolution here rather than in the policy because we
+ * want to use the PATH in the current environment.
+ */
+static bool
+resolve_path(const char *cmnd, char *out_cmnd, size_t out_size)
+{
+ struct stat sb;
+ int errval = ENOENT;
+ char path[PATH_MAX];
+ char **p, *cp, *endp;
+ int dirlen, len;
+ debug_decl(resolve_path, SUDO_DEBUG_EXEC);
+
+ for (p = environ; (cp = *p) != NULL; p++) {
+ if (strncmp(cp, "PATH=", sizeof("PATH=") - 1) == 0) {
+ cp += sizeof("PATH=") - 1;
+ break;
+ }
+ }
+ if (cp == NULL) {
+ errno = ENOENT;
+ debug_return_bool(false);
+ }
+
+ endp = cp + strlen(cp);
+ while (cp < endp) {
+ char *colon = strchr(cp, ':');
+ dirlen = colon ? (int)(colon - cp) : (int)(endp - cp);
+ if (dirlen == 0) {
+ /* empty PATH component is the same as "." */
+ len = snprintf(path, sizeof(path), "./%s", cmnd);
+ } else {
+ len = snprintf(path, sizeof(path), "%.*s/%s", dirlen, cp, cmnd);
+ }
+ cp = colon ? colon + 1 : endp;
+ if (len >= ssizeof(path)) {
+ /* skip too long path */
+ errval = ENAMETOOLONG;
+ continue;
+ }
+
+ if (stat(path, &sb) == 0) {
+ if (!S_ISREG(sb.st_mode))
+ continue;
+ if (strlcpy(out_cmnd, path, out_size) >= out_size) {
+ errval = ENAMETOOLONG;
+ break;
+ }
+ debug_return_bool(true);
+ }
+ switch (errno) {
+ case EACCES:
+ errval = EACCES;
+ break;
+ case ELOOP:
+ case ENOTDIR:
+ case ENOENT:
+ break;
+ default:
+ debug_return_bool(false);
+ }
+ }
+ errno = errval;
+ debug_return_bool(false);
+}
+
+static int
+exec_wrapper(const char *cmnd, char * const argv[], char * const envp[],
+ bool is_execvp)
+{
+ char *cmnd_copy = NULL, **argv_copy = NULL, **envp_copy = NULL;
+ char *ncmnd = NULL, **nargv = NULL, **nenvp = NULL;
+ char cmnd_buf[PATH_MAX];
+ void *fn = NULL;
+ debug_decl(exec_wrapper, SUDO_DEBUG_EXEC);
+
+ if (cmnd == NULL) {
+ errno = EINVAL;
+ debug_return_int(-1);
+ }
+
+ /* Only check PATH for the command for execlp/execvp/execvpe. */
+ if (strchr(cmnd, '/') == NULL) {
+ if (!is_execvp) {
+ errno = ENOENT;
+ goto bad;
+ }
+ if (!resolve_path(cmnd, cmnd_buf, sizeof(cmnd_buf))) {
+ goto bad;
+ }
+ cmnd = cmnd_buf;
+ } else {
+ struct stat sb;
+
+ /* Absolute or relative path name. */
+ if (stat(cmnd, &sb) == -1) {
+ /* Leave errno unchanged. */
+ goto bad;
+ } else if (!S_ISREG(sb.st_mode)) {
+ errno = EACCES;
+ goto bad;
+ }
+ }
+
+ /*
+ * Make copies of cmnd, argv, and envp.
+ */
+ cmnd_copy = sudo_mmap_strdup(cmnd);
+ if (cmnd_copy == NULL) {
+ debug_return_int(-1);
+ }
+ sudo_mmap_protect(cmnd_copy);
+ cmnd = cmnd_copy;
+
+ argv_copy = copy_vector(argv);
+ if (argv_copy == NULL) {
+ goto bad;
+ }
+ sudo_mmap_protect(argv_copy);
+ argv = argv_copy;
+
+ envp_copy = copy_vector(envp);
+ if (envp_copy == NULL) {
+ goto bad;
+ }
+ sudo_mmap_protect(envp_copy);
+ envp = envp_copy;
+
+# if defined(HAVE___INTERPOSE)
+ fn = execve;
+# elif defined(HAVE_DLOPEN)
+ fn = dlsym(RTLD_NEXT, "execve");
+# elif defined(HAVE_SHL_LOAD)
+ fn = sudo_shl_get_next("execve", TYPE_PROCEDURE);
+# endif
+ if (fn == NULL) {
+ errno = EACCES;
+ goto bad;
+ }
+
+ if (command_allowed(cmnd, argv, envp, &ncmnd, &nargv, &nenvp)) {
+ /* Execute the command using the "real" execve() function. */
+ ((sudo_fn_execve_t)fn)(ncmnd, nargv, nenvp);
+
+ /* Fall back to exec via shell for execvp and friends. */
+ if (errno == ENOEXEC && is_execvp) {
+ int argc;
+ const char **shargv;
+
+ for (argc = 0; argv[argc] != NULL; argc++)
+ continue;
+ shargv = sudo_mmap_allocarray((size_t)argc + 2, sizeof(char *));
+ if (shargv == NULL)
+ goto bad;
+ shargv[0] = "sh";
+ shargv[1] = ncmnd;
+ memcpy(shargv + 2, nargv + 1, (size_t)argc * sizeof(char *));
+ ((sudo_fn_execve_t)fn)(_PATH_SUDO_BSHELL, (char **)shargv, nenvp);
+ sudo_mmap_free(shargv);
+ }
+ } else {
+ errno = EACCES;
+ }
+
+bad:
+ sudo_mmap_free(cmnd_copy);
+ if (ncmnd != cmnd_copy)
+ sudo_mmap_free(ncmnd);
+ free_vector(argv_copy);
+ if (nargv != argv_copy)
+ free_vector(nargv);
+ free_vector(envp_copy);
+ /* Leaks allocated preload vars. */
+ if (nenvp != envp_copy)
+ sudo_mmap_free(nenvp);
+
+ debug_return_int(-1);
+}
+
+static int
+execl_wrapper(int type, const char *name, const char *arg, va_list ap)
+{
+ char * const *envp = environ;
+ char **argv;
+ int argc = 1;
+ va_list ap2;
+ debug_decl(execl_wrapper, SUDO_DEBUG_EXEC);
+
+ if (name == NULL || arg == NULL) {
+ errno = EINVAL;
+ debug_return_int(-1);
+ }
+
+ va_copy(ap2, ap);
+ while (va_arg(ap2, char *) != NULL)
+ argc++;
+ va_end(ap2);
+ argv = sudo_mmap_allocarray((size_t)argc + 1, sizeof(char *));
+ if (argv == NULL)
+ debug_return_int(-1);
+
+ argc = 0;
+ argv[argc++] = (char *)arg;
+ while ((argv[argc] = va_arg(ap, char *)) != NULL)
+ argc++;
+ if (type == SUDO_EXECLE)
+ envp = va_arg(ap, char **);
+
+ exec_wrapper(name, argv, envp, type == SUDO_EXECLP);
+ sudo_mmap_free(argv);
+
+ debug_return_int(-1);
+}
+
+static int
+system_wrapper(const char *cmnd)
+{
+ const char * const argv[] = { "sh", "-c", cmnd, NULL };
+ const char shell[] = _PATH_SUDO_BSHELL;
+ struct sigaction saveint, savequit, sa;
+ sigset_t mask, omask;
+ pid_t child;
+ int status;
+ debug_decl(system_wrapper, SUDO_DEBUG_EXEC);
+
+ /* Special case for NULL command, just check whether shell exists. */
+ if (cmnd == NULL)
+ debug_return_int(access(shell, X_OK) == 0);
+
+ /* First, block signals to avoid potential race conditions. */
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGCHLD);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGQUIT);
+ if (sigprocmask(SIG_BLOCK, &mask, &omask) == -1)
+ debug_return_int(-1);
+
+ switch (child = fork()) {
+ case -1:
+ /* error */
+ (void)sigprocmask(SIG_SETMASK, &omask, NULL);
+ debug_return_int(-1);
+ case 0:
+ /* child */
+ if (sigprocmask(SIG_SETMASK, &omask, NULL) != -1)
+ exec_wrapper(shell, (char **)argv, environ, false);
+ _exit(127);
+ default:
+ /* parent */
+ break;
+ }
+
+ /* We must ignore SIGINT and SIGQUIT until the command finishes. */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = SIG_IGN;
+ (void)sigaction(SIGINT, &sa, &saveint);
+ (void)sigaction(SIGQUIT, &sa, &savequit);
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGQUIT);
+ (void)sigprocmask(SIG_UNBLOCK, &mask, NULL);
+
+ for (;;) {
+ if (waitpid(child, &status, 0) == -1) {
+ if (errno == EINTR)
+ continue;
+ status = -1;
+ }
+ break;
+ }
+
+ /* Restore signal mask and handlers. */
+ (void)sigprocmask(SIG_SETMASK, &omask, NULL);
+ (void)sigaction(SIGINT, &saveint, NULL);
+ (void)sigaction(SIGQUIT, &savequit, NULL);
+
+ debug_return_int(status);
+}
+
+#ifdef HAVE___INTERPOSE
+/*
+ * Mac OS X 10.4 and above has support for library symbol interposition.
+ * There is a good explanation of this in the Mac OS X Internals book.
+ */
+typedef struct interpose_s {
+ void *new_func;
+ void *orig_func;
+} interpose_t;
+
+static int
+my_system(const char *cmnd)
+{
+ return system_wrapper(cmnd);
+}
+
+static int
+my_execve(const char *cmnd, char * const argv[], char * const envp[])
+{
+ return exec_wrapper(cmnd, argv, envp, false);
+}
+
+static int
+my_execv(const char *cmnd, char * const argv[])
+{
+ return exec_wrapper(cmnd, argv, environ, false);
+}
+
+#ifdef HAVE_EXECVPE
+static int
+my_execvpe(const char *cmnd, char * const argv[], char * const envp[])
+{
+ return exec_wrapper(cmnd, argv, envp, true);
+}
+#endif
+
+static int
+my_execvp(const char *cmnd, char * const argv[])
+{
+ return exec_wrapper(cmnd, argv, environ, true);
+}
+
+static int
+my_execl(const char *name, const char *arg, ...)
+{
+ va_list ap;
+
+ va_start(ap, arg);
+ execl_wrapper(SUDO_EXECL, name, arg, ap);
+ va_end(ap);
+
+ return -1;
+}
+
+static int
+my_execle(const char *name, const char *arg, ...)
+{
+ va_list ap;
+
+ va_start(ap, arg);
+ execl_wrapper(SUDO_EXECLE, name, arg, ap);
+ va_end(ap);
+
+ return -1;
+}
+
+static int
+my_execlp(const char *name, const char *arg, ...)
+{
+ va_list ap;
+
+ va_start(ap, arg);
+ execl_wrapper(SUDO_EXECLP, name, arg, ap);
+ va_end(ap);
+
+ return -1;
+}
+
+/* Magic to tell dyld to do symbol interposition. */
+__attribute__((__used__)) static const interpose_t interposers[]
+__attribute__((__section__("__DATA,__interpose"))) = {
+ { (void *)my_system, (void *)system },
+ { (void *)my_execl, (void *)execl },
+ { (void *)my_execle, (void *)execle },
+ { (void *)my_execlp, (void *)execlp },
+ { (void *)my_execv, (void *)execv },
+ { (void *)my_execve, (void *)execve },
+ { (void *)my_execvp, (void *)execvp },
+#ifdef HAVE_EXECVPE
+ { (void *)my_execvpe, (void *)execvpe }
+#endif
+};
+
+#else /* HAVE___INTERPOSE */
+
+# if defined(HAVE_SHL_LOAD)
+static void *
+sudo_shl_get_next(const char *symbol, short type)
+{
+ const char *name, *myname;
+ struct shl_descriptor *desc;
+ void *fn = NULL;
+ int idx = 0;
+ debug_decl(sudo_shl_get_next, SUDO_DEBUG_EXEC);
+
+ /* Search for symbol but skip this shared object. */
+ /* XXX - could be set to a different path in sudo.conf */
+ myname = sudo_basename(_PATH_SUDO_INTERCEPT);
+ while (shl_get(idx++, &desc) == 0) {
+ name = sudo_basename(desc->filename);
+ if (strcmp(name, myname) == 0)
+ continue;
+ if (shl_findsym(&desc->handle, symbol, type, &fn) == 0)
+ break;
+ }
+
+ debug_return_ptr(fn);
+}
+# endif /* HAVE_SHL_LOAD */
+
+sudo_dso_public int system(const char *cmnd);
+sudo_dso_public int execve(const char *cmnd, char * const argv[], char * const envp[]);
+sudo_dso_public int execv(const char *cmnd, char * const argv[]);
+#ifdef HAVE_EXECVPE
+sudo_dso_public int execvpe(const char *cmnd, char * const argv[], char * const envp[]);
+#endif
+sudo_dso_public int execvp(const char *cmnd, char * const argv[]);
+sudo_dso_public int execl(const char *name, const char *arg, ...);
+sudo_dso_public int execle(const char *name, const char *arg, ...);
+sudo_dso_public int execlp(const char *name, const char *arg, ...);
+
+int
+system(const char *cmnd)
+{
+ return system_wrapper(cmnd);
+}
+
+int
+execve(const char *cmnd, char * const argv[], char * const envp[])
+{
+ return exec_wrapper(cmnd, argv, envp, false);
+}
+
+int
+execv(const char *cmnd, char * const argv[])
+{
+ return execve(cmnd, argv, environ);
+}
+
+#ifdef HAVE_EXECVPE
+int
+execvpe(const char *cmnd, char * const argv[], char * const envp[])
+{
+ return exec_wrapper(cmnd, argv, envp, true);
+}
+#endif
+
+int
+execvp(const char *cmnd, char * const argv[])
+{
+ return exec_wrapper(cmnd, argv, environ, true);
+}
+
+int
+execl(const char *name, const char *arg, ...)
+{
+ va_list ap;
+
+ va_start(ap, arg);
+ execl_wrapper(SUDO_EXECL, name, arg, ap);
+ va_end(ap);
+
+ return -1;
+}
+
+int
+execle(const char *name, const char *arg, ...)
+{
+ va_list ap;
+
+ va_start(ap, arg);
+ execl_wrapper(SUDO_EXECLE, name, arg, ap);
+ va_end(ap);
+
+ return -1;
+}
+
+int
+execlp(const char *name, const char *arg, ...)
+{
+ va_list ap;
+
+ va_start(ap, arg);
+ execl_wrapper(SUDO_EXECLP, name, arg, ap);
+ va_end(ap);
+
+ return -1;
+}
+#endif /* HAVE___INTERPOSE) */
diff --git a/src/sudo_intercept_common.c b/src/sudo_intercept_common.c
new file mode 100644
index 0000000..730614e
--- /dev/null
+++ b/src/sudo_intercept_common.c
@@ -0,0 +1,509 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2021-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# include <compat/stdbool.h>
+#endif /* HAVE_STDBOOL_H */
+#ifdef HAVE_CRT_EXTERNS_H
+# include <crt_externs.h>
+#endif
+
+#include <sudo_compat.h>
+#include <sudo_conf.h>
+#include <sudo_debug.h>
+#include <sudo_exec.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_util.h>
+#include <intercept.pb-c.h>
+
+#ifdef HAVE__NSGETENVIRON
+# define environ (*_NSGetEnviron())
+#else
+extern char **environ;
+#endif
+
+static union sudo_token_un intercept_token;
+static in_port_t intercept_port;
+static bool log_only;
+
+/* Send entire request to sudo (blocking). */
+static bool
+send_req(int sock, const void *buf, size_t len)
+{
+ const uint8_t *cp = buf;
+ ssize_t nwritten;
+ debug_decl(send_req, SUDO_DEBUG_EXEC);
+
+ do {
+ nwritten = send(sock, cp, len, 0);
+ if (nwritten == -1) {
+ if (errno == EINTR)
+ continue;
+ debug_return_bool(false);
+ }
+ len -= (size_t)nwritten;
+ cp += nwritten;
+ } while (len > 0);
+
+ debug_return_bool(true);
+}
+
+static bool
+send_client_hello(int sock)
+{
+ InterceptRequest msg = INTERCEPT_REQUEST__INIT;
+ InterceptHello hello = INTERCEPT_HELLO__INIT;
+ uint8_t *buf = NULL;
+ uint32_t msg_len;
+ size_t len;
+ bool ret = false;
+ debug_decl(send_client_hello, SUDO_DEBUG_EXEC);
+
+ /* Setup client hello. */
+ hello.pid = getpid();
+ msg.type_case = INTERCEPT_REQUEST__TYPE_HELLO;
+ msg.u.hello = &hello;
+
+ len = intercept_request__get_packed_size(&msg);
+ if (len > MESSAGE_SIZE_MAX) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "InterceptRequest too large: %zu", len);
+ goto done;
+ }
+ /* Wire message size is used for length encoding, precedes message. */
+ msg_len = len & 0xffffffff;
+ len += sizeof(msg_len);
+
+ if ((buf = sudo_mmap_alloc(len)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ memcpy(buf, &msg_len, sizeof(msg_len));
+ intercept_request__pack(&msg, buf + sizeof(msg_len));
+
+ ret = send_req(sock, buf, len);
+
+done:
+ sudo_mmap_free(buf);
+ debug_return_bool(ret);
+}
+
+/*
+ * Receive InterceptResponse from sudo over fd.
+ */
+static InterceptResponse *
+recv_intercept_response(int fd)
+{
+ InterceptResponse *res = NULL;
+ ssize_t nread;
+ uint32_t rem, res_len;
+ uint8_t *cp, *buf = NULL;
+ debug_decl(recv_intercept_response, SUDO_DEBUG_EXEC);
+
+ /* Read message size (uint32_t in host byte order). */
+ for (;;) {
+ nread = recv(fd, &res_len, sizeof(res_len), 0);
+ if (nread == ssizeof(res_len))
+ break;
+ switch (nread) {
+ case 0:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unexpected EOF reading response size");
+ break;
+ case -1:
+ if (errno == EINTR)
+ continue;
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "error reading response size");
+ break;
+ default:
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "error reading response size: short read");
+ break;
+ }
+ goto done;
+ }
+ if (res_len > MESSAGE_SIZE_MAX) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "InterceptResponse too large: %u", res_len);
+ goto done;
+ }
+
+ /* Read response from sudo (blocking). */
+ if ((buf = sudo_mmap_alloc(res_len)) == NULL) {
+ goto done;
+ }
+ cp = buf;
+ rem = res_len;
+ do {
+ nread = recv(fd, cp, rem, 0);
+ switch (nread) {
+ case 0:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unexpected EOF reading response");
+ goto done;
+ case -1:
+ if (errno == EINTR)
+ continue;
+ sudo_debug_printf(
+ SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "error reading response");
+ goto done;
+ default:
+ rem -= (uint32_t)nread;
+ cp += nread;
+ break;
+ }
+ } while (rem > 0);
+ res = intercept_response__unpack(NULL, res_len, buf);
+ if (res == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to unpack %s size %u", "InterceptResponse", res_len);
+ goto done;
+ }
+
+done:
+ sudo_mmap_free(buf);
+ debug_return_ptr(res);
+}
+
+/*
+ * Look up SUDO_INTERCEPT_FD in the environment.
+ * This function is run when the shared library is loaded.
+ */
+__attribute__((constructor)) static void
+sudo_interposer_init(void)
+{
+ InterceptResponse *res = NULL;
+ static bool initialized;
+ int flags, fd = -1;
+ char **p;
+ debug_decl(sudo_interposer_init, SUDO_DEBUG_EXEC);
+
+ if (initialized)
+ debug_return;
+ initialized = true;
+
+ /* Read debug and path section of sudo.conf and init debugging. */
+ if (sudo_conf_read(NULL, SUDO_CONF_DEBUG|SUDO_CONF_PATHS) != -1) {
+ sudo_debug_register("sudo_intercept.so", NULL, NULL,
+ sudo_conf_debug_files("sudo_intercept.so"), INTERCEPT_FD_MIN);
+ }
+ sudo_debug_enter(__func__, __FILE__, __LINE__, sudo_debug_subsys);
+
+ /*
+ * Missing SUDO_INTERCEPT_FD will result in execve() failure.
+ * Note that we cannot use getenv(3) here on Linux at least.
+ */
+ for (p = environ; *p != NULL; p++) {
+ if (strncmp(*p, "SUDO_INTERCEPT_FD=", sizeof("SUDO_INTERCEPT_FD=") -1) == 0) {
+ const char *fdstr = *p + sizeof("SUDO_INTERCEPT_FD=") - 1;
+ const char *errstr;
+
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, "%s", *p);
+
+ fd = (int)sudo_strtonum(fdstr, 0, INT_MAX, &errstr);
+ if (errstr != NULL) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "invalid SUDO_INTERCEPT_FD: %s: %s", fdstr, errstr);
+ goto done;
+ }
+ }
+ }
+ if (fd == -1) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "SUDO_INTERCEPT_FD not found in environment");
+ goto done;
+ }
+
+ /*
+ * We don't want to use non-blocking I/O.
+ */
+ flags = fcntl(fd, F_GETFL, 0);
+ if (flags != -1)
+ (void)fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
+
+ /*
+ * Send InterceptHello message to over the fd.
+ */
+ if (!send_client_hello(fd))
+ goto done;
+
+ res = recv_intercept_response(fd);
+ if (res != NULL) {
+ if (res->type_case == INTERCEPT_RESPONSE__TYPE_HELLO_RESP) {
+ intercept_token.u64[0] = res->u.hello_resp->token_lo;
+ intercept_token.u64[1] = res->u.hello_resp->token_hi;
+ intercept_port = (in_port_t)res->u.hello_resp->portno;
+ log_only = res->u.hello_resp->log_only;
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unexpected type_case value %d in %s from %s",
+ res->type_case, "InterceptResponse", "sudo");
+ }
+ intercept_response__free_unpacked(res, NULL);
+ }
+
+done:
+ if (fd != -1)
+ close(fd);
+
+ debug_return;
+}
+
+static bool
+send_policy_check_req(int sock, const char *cmnd, char * const argv[],
+ char * const envp[])
+{
+ InterceptRequest msg = INTERCEPT_REQUEST__INIT;
+ PolicyCheckRequest req = POLICY_CHECK_REQUEST__INIT;
+ char cwdbuf[PATH_MAX];
+ char *empty[1] = { NULL };
+ uint8_t *buf = NULL;
+ bool ret = false;
+ uint32_t msg_len;
+ size_t len;
+ debug_decl(fmt_policy_check_req, SUDO_DEBUG_EXEC);
+
+ /* Send token first (out of band) to initiate connection. */
+ if (!send_req(sock, &intercept_token, sizeof(intercept_token))) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unable to send token back to sudo");
+ goto done;
+ }
+
+ /* Setup policy check request. */
+ req.intercept_fd = sock;
+ req.command = (char *)cmnd;
+ req.argv = argv ? (char **)argv : empty;
+ for (req.n_argv = 0; req.argv[req.n_argv] != NULL; req.n_argv++)
+ continue;
+ req.envp = envp ? (char **)envp : empty;
+ for (req.n_envp = 0; req.envp[req.n_envp] != NULL; req.n_envp++)
+ continue;
+ if (getcwd(cwdbuf, sizeof(cwdbuf)) != NULL) {
+ req.cwd = cwdbuf;
+ }
+ msg.type_case = INTERCEPT_REQUEST__TYPE_POLICY_CHECK_REQ;
+ msg.u.policy_check_req = &req;
+
+ len = intercept_request__get_packed_size(&msg);
+ if (len > MESSAGE_SIZE_MAX) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "InterceptRequest too large: %zu", len);
+ goto done;
+ }
+ /* Wire message size is used for length encoding, precedes message. */
+ msg_len = len & 0xffffffff;
+ len += sizeof(msg_len);
+
+ if ((buf = sudo_mmap_alloc(len)) == NULL) {
+ sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+ goto done;
+ }
+ memcpy(buf, &msg_len, sizeof(msg_len));
+ intercept_request__pack(&msg, buf + sizeof(msg_len));
+
+ ret = send_req(sock, buf, len);
+
+done:
+ sudo_mmap_free(buf);
+ debug_return_bool(ret);
+}
+
+/*
+ * Connect back to sudo process at localhost:intercept_port
+ */
+static int
+intercept_connect(void)
+{
+ int sock = -1;
+ int on = 1;
+ struct sockaddr_in sin4;
+ debug_decl(intercept_connect, SUDO_DEBUG_EXEC);
+
+ if (intercept_port == 0) {
+ sudo_warnx("%s", U_("intercept port not set"));
+ goto done;
+ }
+
+ memset(&sin4, 0, sizeof(sin4));
+ sin4.sin_family = AF_INET;
+ sin4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ sin4.sin_port = htons(intercept_port);
+
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock == -1) {
+ sudo_warn("socket");
+ goto done;
+ }
+
+ /* Send data immediately, we need low latency IPC. */
+ (void)setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
+
+ if (connect(sock, (struct sockaddr *)&sin4, sizeof(sin4)) == -1) {
+ sudo_warn("connect");
+ close(sock);
+ sock = -1;
+ goto done;
+ }
+
+done:
+ debug_return_int(sock);
+}
+
+/* Called from sudo_intercept.c */
+bool command_allowed(const char *cmnd, char * const argv[], char * const envp[], char **ncmndp, char ***nargvp, char ***nenvpp);
+
+bool
+command_allowed(const char *cmnd, char * const argv[],
+ char * const envp[], char **ncmndp, char ***nargvp, char ***nenvpp)
+{
+ char *ncmnd = NULL, **nargv = NULL, **nenvp = NULL;
+ InterceptResponse *res = NULL;
+ bool ret = false;
+ size_t idx, len = 0;
+ int sock;
+ debug_decl(command_allowed, SUDO_DEBUG_EXEC);
+
+ if (sudo_debug_needed(SUDO_DEBUG_INFO)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "req_command: %s", cmnd);
+ if (argv != NULL) {
+ for (idx = 0; argv[idx] != NULL; idx++) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "req_argv[%zu]: %s", idx, argv[idx]);
+ }
+ }
+ }
+
+ sock = intercept_connect();
+ if (sock == -1)
+ goto done;
+
+ if (!send_policy_check_req(sock, cmnd, argv, envp))
+ goto done;
+
+ if (log_only) {
+ /* Just logging, no policy check. */
+ nenvp = sudo_preload_dso_mmap(envp, sudo_conf_intercept_path(), sock);
+ if (nenvp == NULL)
+ goto oom;
+ *ncmndp = (char *)cmnd; /* safe */
+ *nargvp = (char **)argv; /* safe */
+ *nenvpp = nenvp;
+ ret = true;
+ goto done;
+ }
+
+ res = recv_intercept_response(sock);
+ if (res == NULL)
+ goto done;
+
+ switch (res->type_case) {
+ case INTERCEPT_RESPONSE__TYPE_ACCEPT_MSG:
+ if (sudo_debug_needed(SUDO_DEBUG_INFO)) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "run_command: %s", res->u.accept_msg->run_command);
+ for (idx = 0; idx < res->u.accept_msg->n_run_argv; idx++) {
+ sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
+ "run_argv[%zu]: %s", idx, res->u.accept_msg->run_argv[idx]);
+ }
+ }
+ ncmnd = sudo_mmap_strdup(res->u.accept_msg->run_command);
+ if (ncmnd == NULL)
+ goto oom;
+ nargv = sudo_mmap_allocarray(res->u.accept_msg->n_run_argv + 1,
+ sizeof(char *));
+ if (nargv == NULL)
+ goto oom;
+ for (len = 0; len < res->u.accept_msg->n_run_argv; len++) {
+ nargv[len] = sudo_mmap_strdup(res->u.accept_msg->run_argv[len]);
+ if (nargv[len] == NULL)
+ goto oom;
+ }
+ nargv[len] = NULL;
+ nenvp = sudo_preload_dso_mmap(envp, sudo_conf_intercept_path(), sock);
+ if (nenvp == NULL)
+ goto oom;
+ *ncmndp = ncmnd;
+ *nargvp = nargv;
+ *nenvpp = nenvp;
+ ret = true;
+ goto done;
+ case INTERCEPT_RESPONSE__TYPE_REJECT_MSG:
+ /* Policy module displayed reject message but we are in raw mode. */
+ fputc('\r', stderr);
+ goto done;
+ case INTERCEPT_RESPONSE__TYPE_ERROR_MSG:
+ /* Policy module may display error message but we are in raw mode. */
+ fputc('\r', stderr);
+ sudo_warnx("%s", res->u.error_msg->error_message);
+ goto done;
+ default:
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "unexpected type_case value %d in %s from %s",
+ res->type_case, "InterceptResponse", "sudo");
+ goto done;
+ }
+
+oom:
+ sudo_mmap_free(ncmnd);
+ while (len > 0)
+ sudo_mmap_free(nargv[--len]);
+ sudo_mmap_free(nargv);
+
+done:
+ /* Keep socket open for ctor when we execute the command. */
+ if (!ret && sock != -1)
+ close(sock);
+ intercept_response__free_unpacked(res, NULL);
+
+ debug_return_bool(ret);
+}
diff --git a/src/sudo_noexec.c b/src/sudo_noexec.c
new file mode 100644
index 0000000..6ba74d5
--- /dev/null
+++ b/src/sudo_noexec.c
@@ -0,0 +1,251 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2004-2005, 2010-2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+
+#if defined(HAVE_DECL_SECCOMP_MODE_FILTER) && HAVE_DECL_SECCOMP_MODE_FILTER
+# include <sys/prctl.h>
+# include <asm/unistd.h>
+# include <linux/filter.h>
+# include <linux/seccomp.h>
+#endif
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#ifdef HAVE_SPAWN_H
+#include <spawn.h>
+#endif
+#include <string.h>
+#ifdef HAVE_WORDEXP_H
+#include <wordexp.h>
+#endif
+#if defined(HAVE_SHL_LOAD)
+# include <dl.h>
+#elif defined(HAVE_DLOPEN)
+# include <dlfcn.h>
+#endif
+
+#include <sudo_compat.h>
+#include <pathnames.h>
+
+#ifdef HAVE___INTERPOSE
+/*
+ * Mac OS X 10.4 and above has support for library symbol interposition.
+ * There is a good explanation of this in the Mac OS X Internals book.
+ */
+typedef struct interpose_s {
+ void *new_func;
+ void *orig_func;
+} interpose_t;
+
+# define FN_NAME(fn) fake_ ## fn
+# define INTERPOSE(fn) \
+ __attribute__((__used__)) static const interpose_t interpose_ ## fn \
+ __attribute__((__section__("__DATA,__interpose"))) = \
+ { (void *)fake_ ## fn, (void *)fn };
+#else
+# define FN_NAME(fn) fn
+# define INTERPOSE(fn)
+#endif
+
+/*
+ * Replacements for the exec(3) family of syscalls. It is not enough to
+ * just replace execve(2) since many C libraries do not call the public
+ * execve(2) interface. Note that it is still possible to access the real
+ * syscalls via the syscall(2) interface, but that is rarely done.
+ */
+
+#define EXEC_REPL_BODY \
+{ \
+ errno = EACCES; \
+ return -1; \
+}
+
+#define EXEC_REPL1(fn, t1) \
+sudo_dso_public int FN_NAME(fn)(t1 a1); \
+int FN_NAME(fn)(t1 a1) \
+EXEC_REPL_BODY \
+INTERPOSE(fn)
+
+#define EXEC_REPL2(fn, t1, t2) \
+sudo_dso_public int FN_NAME(fn)(t1 a1, t2 a2); \
+int FN_NAME(fn)(t1 a1, t2 a2) \
+EXEC_REPL_BODY \
+INTERPOSE(fn)
+
+#define EXEC_REPL3(fn, t1, t2, t3) \
+sudo_dso_public int FN_NAME(fn)(t1 a1, t2 a2, t3 a3); \
+int FN_NAME(fn)(t1 a1, t2 a2, t3 a3) \
+EXEC_REPL_BODY \
+INTERPOSE(fn)
+
+#define EXEC_REPL6(fn, t1, t2, t3, t4, t5, t6) \
+sudo_dso_public int FN_NAME(fn)(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6); \
+int FN_NAME(fn)(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) \
+EXEC_REPL_BODY \
+INTERPOSE(fn)
+
+#define EXEC_REPL_VA(fn, t1, t2) \
+sudo_dso_public int FN_NAME(fn)(t1 a1, t2 a2, ...); \
+int FN_NAME(fn)(t1 a1, t2 a2, ...) \
+EXEC_REPL_BODY \
+INTERPOSE(fn)
+
+/*
+ * Standard exec(3) family of functions.
+ */
+EXEC_REPL_VA(execl, const char *, const char *)
+EXEC_REPL_VA(execle, const char *, const char *)
+EXEC_REPL_VA(execlp, const char *, const char *)
+EXEC_REPL2(execv, const char *, char * const *)
+EXEC_REPL2(execvp, const char *, char * const *)
+EXEC_REPL3(execve, const char *, char * const *, char * const *)
+
+/*
+ * Non-standard exec(3) functions and corresponding private versions.
+ */
+#ifdef HAVE_EXECVP
+EXEC_REPL3(execvP, const char *, const char *, char * const *)
+#endif
+#ifdef HAVE_EXECVPE
+EXEC_REPL3(execvpe, const char *, char * const *, char * const *)
+#endif
+#ifdef HAVE_EXECT
+EXEC_REPL3(exect, const char *, char * const *, char * const *)
+#endif
+
+/*
+ * Not all systems support fexecve(2), posix_spawn(2) and posix_spawnp(2).
+ */
+#ifdef HAVE_FEXECVE
+EXEC_REPL3(fexecve, int , char * const *, char * const *)
+#endif
+#ifdef HAVE_POSIX_SPAWN
+EXEC_REPL6(posix_spawn, pid_t *, const char *, const posix_spawn_file_actions_t *, const posix_spawnattr_t *, char * const *, char * const *)
+#endif
+#ifdef HAVE_POSIX_SPAWNP
+EXEC_REPL6(posix_spawnp, pid_t *, const char *, const posix_spawn_file_actions_t *, const posix_spawnattr_t *, char * const *, char * const *)
+#endif
+
+/*
+ * system(3) and popen(3).
+ * We can't use a wrapper for popen since it returns FILE *, not int.
+ */
+EXEC_REPL1(system, const char *)
+
+sudo_dso_public FILE *FN_NAME(popen)(const char *c, const char *t);
+FILE *FN_NAME(popen)(const char *c, const char *t)
+{
+ errno = EACCES;
+ return NULL;
+}
+INTERPOSE(popen)
+
+#if defined(HAVE_WORDEXP) && (defined(RTLD_NEXT) || defined(HAVE_SHL_LOAD) || defined(HAVE___INTERPOSE))
+/*
+ * We can't use a wrapper for wordexp(3) since we still want to call
+ * the real wordexp(3) but with WRDE_NOCMD added to the flags argument.
+ */
+typedef int (*sudo_fn_wordexp_t)(const char *, wordexp_t *, int);
+
+sudo_dso_public int FN_NAME(wordexp)(const char *words, wordexp_t *we, int flags);
+int FN_NAME(wordexp)(const char *words, wordexp_t *we, int flags)
+{
+#if defined(HAVE___INTERPOSE)
+ return wordexp(words, we, flags | WRDE_NOCMD);
+#else
+# if defined(HAVE_DLOPEN)
+ void *fn = dlsym(RTLD_NEXT, "wordexp");
+# elif defined(HAVE_SHL_LOAD)
+ const char *name, *myname = _PATH_SUDO_NOEXEC;
+ struct shl_descriptor *desc;
+ void *fn = NULL;
+ int idx = 0;
+
+ /* Search for wordexp() but skip this shared object. */
+ myname = sudo_basename(myname);
+ while (shl_get(idx++, &desc) == 0) {
+ name = sudo_basename(desc->filename);
+ if (strcmp(name, myname) == 0)
+ continue;
+ if (shl_findsym(&desc->handle, "wordexp", TYPE_PROCEDURE, &fn) == 0)
+ break;
+ }
+# else
+ void *fn = NULL;
+# endif
+ if (fn == NULL) {
+ errno = EACCES;
+ return -1;
+ }
+ return ((sudo_fn_wordexp_t)fn)(words, we, flags | WRDE_NOCMD);
+#endif /* HAVE___INTERPOSE */
+}
+INTERPOSE(wordexp)
+#endif /* HAVE_WORDEXP && (RTLD_NEXT || HAVE_SHL_LOAD || HAVE___INTERPOSE) */
+
+/*
+ * On Linux we can use a seccomp() filter to disable exec.
+ */
+#if defined(HAVE_DECL_SECCOMP_MODE_FILTER) && HAVE_DECL_SECCOMP_MODE_FILTER
+
+/* Older systems may not support execveat(2). */
+#ifndef __NR_execveat
+# define __NR_execveat -1
+#endif
+
+static void noexec_ctor(void) __attribute__((constructor));
+
+static void
+noexec_ctor(void)
+{
+ struct sock_filter exec_filter[] = {
+ /* Load syscall number into the accumulator */
+ BPF_STMT(BPF_LD | BPF_ABS, offsetof(struct seccomp_data, nr)),
+ /* Jump to deny for execve/execveat */
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_execve, 2, 0),
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_execveat, 1, 0),
+ /* Allow non-matching syscalls */
+ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+ /* Deny execve/execveat syscall */
+ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (EACCES & SECCOMP_RET_DATA))
+ };
+ const struct sock_fprog exec_fprog = {
+ nitems(exec_filter),
+ exec_filter
+ };
+
+ /*
+ * SECCOMP_MODE_FILTER will fail unless the process has
+ * CAP_SYS_ADMIN or the no_new_privs bit is set.
+ */
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == 0)
+ (void)prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &exec_fprog);
+}
+#endif /* HAVE_DECL_SECCOMP_MODE_FILTER */
diff --git a/src/sudo_plugin_int.h b/src/sudo_plugin_int.h
new file mode 100644
index 0000000..0dd58c9
--- /dev/null
+++ b/src/sudo_plugin_int.h
@@ -0,0 +1,133 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2010-2020 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_PLUGIN_INT_H
+#define SUDO_PLUGIN_INT_H
+
+/*
+ * All plugin structures start with a type and a version.
+ */
+struct generic_plugin {
+ unsigned int type;
+ unsigned int version;
+ /* the rest depends on the type... */
+};
+
+typedef int (*sudo_conv_1_7_t)(int num_msgs,
+ const struct sudo_conv_message msgs[], struct sudo_conv_reply replies[]);
+
+/*
+ * Backwards-compatible structures for API bumps.
+ */
+struct policy_plugin_1_0 {
+ unsigned int type;
+ unsigned int version;
+ int (*open)(unsigned int version, sudo_conv_1_7_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], char * const user_env[]);
+ void (*close)(int exit_status, int error); /* wait status or error */
+ int (*show_version)(int verbose);
+ int (*check_policy)(int argc, char * const argv[],
+ char *env_add[], char **command_info[],
+ char **argv_out[], char **user_env_out[]);
+ int (*list)(int argc, char * const argv[], int verbose,
+ const char *user);
+ int (*validate)(void);
+ void (*invalidate)(int rmcred);
+ int (*init_session)(struct passwd *pwd);
+};
+struct io_plugin_1_0 {
+ unsigned int type;
+ unsigned int version;
+ int (*open)(unsigned int version, sudo_conv_1_7_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], int argc, char * const argv[],
+ char * const user_env[]);
+ void (*close)(int exit_status, int error);
+ int (*show_version)(int verbose);
+ int (*log_ttyin)(const char *buf, unsigned int len);
+ int (*log_ttyout)(const char *buf, unsigned int len);
+ int (*log_stdin)(const char *buf, unsigned int len);
+ int (*log_stdout)(const char *buf, unsigned int len);
+ int (*log_stderr)(const char *buf, unsigned int len);
+};
+struct io_plugin_1_1 {
+ unsigned int type;
+ unsigned int version;
+ int (*open)(unsigned int version, sudo_conv_1_7_t conversation,
+ sudo_printf_t sudo_plugin_printf, char * const settings[],
+ char * const user_info[], char * const command_info[],
+ int argc, char * const argv[], char * const user_env[]);
+ void (*close)(int exit_status, int error); /* wait status or error */
+ int (*show_version)(int verbose);
+ int (*log_ttyin)(const char *buf, unsigned int len);
+ int (*log_ttyout)(const char *buf, unsigned int len);
+ int (*log_stdin)(const char *buf, unsigned int len);
+ int (*log_stdout)(const char *buf, unsigned int len);
+ int (*log_stderr)(const char *buf, unsigned int len);
+};
+
+/*
+ * Sudo plugin internals.
+ */
+struct plugin_container {
+ TAILQ_ENTRY(plugin_container) entries;
+ struct sudo_conf_debug_file_list *debug_files;
+ char *name;
+ char *path;
+ char **options;
+ void *handle;
+ int debug_instance;
+ union {
+ struct generic_plugin *generic;
+ struct policy_plugin *policy;
+ struct policy_plugin_1_0 *policy_1_0;
+ struct io_plugin *io;
+ struct io_plugin_1_0 *io_1_0;
+ struct io_plugin_1_1 *io_1_1;
+ struct audit_plugin *audit;
+ struct approval_plugin *approval;
+ } u;
+};
+TAILQ_HEAD(plugin_container_list, plugin_container);
+
+/*
+ * Private implementation of struct sudo_plugin_event.
+ */
+struct sudo_plugin_event_int {
+ struct sudo_event private; /* must be first */
+ int debug_instance; /* plugin's debug instance */
+ void *closure; /* actual user closure */
+ sudo_ev_callback_t callback; /* actual user callback */
+ struct sudo_plugin_event public; /* user-visible portion */
+};
+
+extern struct plugin_container policy_plugin;
+extern struct plugin_container_list io_plugins;
+extern struct plugin_container_list audit_plugins;
+extern struct plugin_container_list approval_plugins;
+
+int sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[], struct sudo_conv_callback *callback);
+int sudo_conversation_1_7(int num_msgs, const struct sudo_conv_message msgs[],
+ struct sudo_conv_reply replies[]);
+int sudo_conversation_printf(int msg_type, const char * restrict fmt, ...);
+
+bool sudo_load_plugins(void);
+
+#endif /* SUDO_PLUGIN_INT_H */
diff --git a/src/sudo_usage.h.in b/src/sudo_usage.h.in
new file mode 100644
index 0000000..6b186f4
--- /dev/null
+++ b/src/sudo_usage.h.in
@@ -0,0 +1,78 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2007-2010, 2013, 2015, 2017, 2020-2023
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef SUDO_USAGE_H
+#define SUDO_USAGE_H
+
+/*
+ * Usage strings for sudo. These are here because we
+ * need to be able to substitute values from configure.
+ */
+static const char *sudo_usage1[] = {
+ "-h | -K | -k | -V",
+ NULL
+};
+static const char *sudo_usage2[] = {
+ "-v [-ABkNnS] @BSDAUTH_USAGE@[-g group] [-h host] [-p prompt] [-u user]",
+ NULL
+};
+static const char *sudo_usage3[] = {
+ "-l [-ABkNnS] @BSDAUTH_USAGE@[-g group] [-h host] [-p prompt] [-U user]",
+ "[-u user] [command [arg ...]]",
+ NULL
+};
+static const char *sudo_usage4[] = {
+ "[-ABbEHkNnPS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C num] @LOGINCAP_USAGE@[-D directory]",
+ "[-g group] [-h host] [-p prompt] [-R directory] [-T timeout]",
+ "[-u user] [VAR=value] [-i | -s] [command [arg ...]]",
+ NULL
+};
+static const char *sudo_usage5[] = {
+ "-e [-ABkNnS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C num] @LOGINCAP_USAGE@[-D directory]",
+ "[-g group] [-h host] [-p prompt] [-R directory] [-T timeout]",
+ "[-u user] file ...",
+ NULL
+};
+static const char * const *sudo_usage[] = {
+ sudo_usage1,
+ sudo_usage2,
+ sudo_usage3,
+ sudo_usage4,
+ sudo_usage5,
+ NULL
+};
+
+static const char *sudoedit_usage1[] = {
+ "-h | -V",
+ NULL
+};
+static const char *sudoedit_usage2[] = {
+ /* Same as sudo_usage5 but no -e flag. */
+ "[-ABkNnS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C num] @LOGINCAP_USAGE@[-D directory]",
+ "[-g group] [-h host] [-p prompt] [-R directory] [-T timeout]",
+ "[-u user] file ...",
+ NULL
+};
+static const char * const *sudoedit_usage[] = {
+ sudoedit_usage1,
+ sudoedit_usage2,
+ NULL
+};
+
+#endif /* SUDO_USAGE_H */
diff --git a/src/suspend_parent.c b/src/suspend_parent.c
new file mode 100644
index 0000000..af6957f
--- /dev/null
+++ b/src/suspend_parent.c
@@ -0,0 +1,170 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2009-2023 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include <pathnames.h>
+#include <sudo_debug.h>
+#include <sudo_fatal.h>
+#include <sudo_gettext.h>
+#include <sudo_exec.h>
+
+static volatile sig_atomic_t got_sigttou;
+
+/*
+ * SIGTTOU signal handler for tcsetpgrp_nobg() that just sets a flag.
+ */
+static void
+sigttou(int signo)
+{
+ got_sigttou = 1;
+}
+
+/*
+ * Like tcsetpgrp() but restarts on EINTR _except_ for SIGTTOU.
+ * Returns 0 on success or -1 on failure, setting errno.
+ * Sets got_sigttou on failure if interrupted by SIGTTOU.
+ */
+static int
+tcsetpgrp_nobg(int fd, pid_t pgrp_id)
+{
+ struct sigaction sa, osa;
+ int rc;
+ debug_decl(tcsetpgrp_nobg, SUDO_DEBUG_UTIL);
+
+ /*
+ * If we receive SIGTTOU from tcsetpgrp() it means we are
+ * not in the foreground process group.
+ * This avoid a TOCTOU race compared to using tcgetpgrp().
+ */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0; /* do not restart syscalls */
+ sa.sa_handler = sigttou;
+ got_sigttou = 0;
+ (void)sigaction(SIGTTOU, &sa, &osa);
+ do {
+ rc = tcsetpgrp(fd, pgrp_id);
+ } while (rc != 0 && errno == EINTR && !got_sigttou);
+ (void)sigaction(SIGTTOU, &osa, NULL);
+
+ debug_return_int(rc);
+}
+
+/*
+ * Suspend the main process in response to an interactive child process
+ * being suspended.
+ */
+void
+sudo_suspend_parent(int signo, pid_t my_pid, pid_t my_pgrp, pid_t cmnd_pid,
+ void *closure, void (*callback)(void *, int))
+{
+ struct sigaction sa, osa;
+ pid_t saved_pgrp = -1;
+ int fd;
+ debug_decl(sudo_suspend_parent, SUDO_DEBUG_EXEC);
+
+ /*
+ * Save the controlling terminal's process group so we can restore
+ * it after we resume, if needed. Most well-behaved shells change
+ * the pgrp back to its original value before suspending so we must
+ * not try to restore in that case, lest we race with the command
+ * upon resume, potentially stopping sudo with SIGTTOU while the
+ * command continues to run.
+ */
+ fd = open(_PATH_TTY, O_RDWR);
+ if (fd != -1) {
+ saved_pgrp = tcgetpgrp(fd);
+ if (saved_pgrp == -1) {
+ close(fd);
+ fd = -1;
+ }
+ }
+
+ if (saved_pgrp != -1) {
+ /*
+ * Command was stopped trying to access the controlling
+ * terminal. If the command has a different pgrp and we
+ * own the controlling terminal, give it to the command's
+ * pgrp and let it continue.
+ */
+ if (signo == SIGTTOU || signo == SIGTTIN) {
+ if (saved_pgrp == my_pgrp) {
+ pid_t cmnd_pgrp = getpgid(cmnd_pid);
+ if (cmnd_pgrp != my_pgrp) {
+ if (tcsetpgrp_nobg(fd, cmnd_pgrp) == 0) {
+ if (killpg(cmnd_pgrp, SIGCONT) != 0)
+ sudo_warn("kill(%d, SIGCONT)", (int)cmnd_pgrp);
+ close(fd);
+ debug_return;
+ }
+ }
+ }
+ }
+ }
+
+ /* Run callback before we suspend. */
+ if (callback != NULL)
+ callback(closure, signo);
+
+ if (signo == SIGTSTP) {
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = SIG_DFL;
+ if (sigaction(SIGTSTP, &sa, &osa) != 0)
+ sudo_warn(U_("unable to set handler for signal %d"), SIGTSTP);
+ }
+ if (kill(my_pid, signo) != 0)
+ sudo_warn("kill(%d, %d)", (int)my_pid, signo);
+ if (signo == SIGTSTP) {
+ if (sigaction(SIGTSTP, &osa, NULL) != 0)
+ sudo_warn(U_("unable to restore handler for signal %d"), SIGTSTP);
+ }
+
+ /* Run callback on resume. */
+ if (callback != NULL)
+ callback(closure, SIGCONT);
+
+ if (saved_pgrp != -1) {
+ /*
+ * On resume, restore foreground process group, if different.
+ * Otherwise, we cannot resume some shells (pdksh).
+ *
+ * It is possible that we are no longer the foreground process,
+ * use tcsetpgrp_nobg() to prevent sudo from receiving SIGTTOU.
+ */
+ if (saved_pgrp != my_pgrp)
+ tcsetpgrp_nobg(fd, saved_pgrp);
+ close(fd);
+ }
+
+ debug_return;
+}
diff --git a/src/tgetpass.c b/src/tgetpass.c
new file mode 100644
index 0000000..c9bc644
--- /dev/null
+++ b/src/tgetpass.c
@@ -0,0 +1,466 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 1996, 1998-2005, 2007-2021
+ * Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#ifdef __TANDEM
+# include <floss.h>
+#endif
+
+#include <config.h>
+
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+
+#include <sudo.h>
+#include <sudo_plugin.h>
+
+enum tgetpass_errval {
+ TGP_ERRVAL_NOERROR,
+ TGP_ERRVAL_TIMEOUT,
+ TGP_ERRVAL_NOPASSWORD,
+ TGP_ERRVAL_READERROR
+};
+
+static volatile sig_atomic_t signo[NSIG];
+
+static void tgetpass_handler(int);
+static char *getln(int, char *, size_t, bool, enum tgetpass_errval *);
+static char *sudo_askpass(const char *, const char *);
+
+static int
+suspend(int sig, struct sudo_conv_callback *callback)
+{
+ int ret = 0;
+ debug_decl(suspend, SUDO_DEBUG_CONV);
+
+ if (callback != NULL && SUDO_API_VERSION_GET_MAJOR(callback->version) != SUDO_CONV_CALLBACK_VERSION_MAJOR) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
+ "callback major version mismatch, expected %u, got %u",
+ SUDO_CONV_CALLBACK_VERSION_MAJOR,
+ SUDO_API_VERSION_GET_MAJOR(callback->version));
+ callback = NULL;
+ }
+
+ if (callback != NULL && callback->on_suspend != NULL) {
+ if (callback->on_suspend(sig, callback->closure) == -1)
+ ret = -1;
+ }
+ kill(getpid(), sig);
+ if (callback != NULL && callback->on_resume != NULL) {
+ if (callback->on_resume(sig, callback->closure) == -1)
+ ret = -1;
+ }
+ debug_return_int(ret);
+}
+
+static void
+tgetpass_display_error(enum tgetpass_errval errval)
+{
+ debug_decl(tgetpass_display_error, SUDO_DEBUG_CONV);
+
+ switch (errval) {
+ case TGP_ERRVAL_NOERROR:
+ break;
+ case TGP_ERRVAL_TIMEOUT:
+ sudo_warnx("%s", U_("timed out reading password"));
+ break;
+ case TGP_ERRVAL_NOPASSWORD:
+ sudo_warnx("%s", U_("no password was provided"));
+ break;
+ case TGP_ERRVAL_READERROR:
+ sudo_warn("%s", U_("unable to read password"));
+ break;
+ }
+ debug_return;
+}
+
+/*
+ * Like getpass(3) but with timeout and echo flags.
+ */
+char *
+tgetpass(const char *prompt, int timeout, unsigned int flags,
+ struct sudo_conv_callback *callback)
+{
+ struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm;
+ struct sigaction savetstp, savettin, savettou;
+ char *pass;
+ static const char *askpass;
+ static char buf[SUDO_CONV_REPL_MAX + 1];
+ int i, input, output, save_errno, ttyfd;
+ bool feedback, need_restart, neednl;
+ enum tgetpass_errval errval;
+ debug_decl(tgetpass, SUDO_DEBUG_CONV);
+
+ (void) fflush(stdout);
+
+ if (askpass == NULL) {
+ askpass = getenv_unhooked("SUDO_ASKPASS");
+ if (askpass == NULL || *askpass == '\0')
+ askpass = sudo_conf_askpass_path();
+ }
+
+restart:
+ /* Try to open /dev/tty if we are going to be using it for I/O. */
+ ttyfd = -1;
+ if (!ISSET(flags, TGP_STDIN|TGP_ASKPASS)) {
+ /* If no tty present and we need to disable echo, try askpass. */
+ ttyfd = open(_PATH_TTY, O_RDWR);
+ if (ttyfd == -1 && !ISSET(flags, TGP_ECHO|TGP_NOECHO_TRY)) {
+ if (askpass == NULL || getenv_unhooked("DISPLAY") == NULL) {
+ sudo_warnx("%s",
+ U_("a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper"));
+ debug_return_str(NULL);
+ }
+ SET(flags, TGP_ASKPASS);
+ }
+ }
+
+ /* If using a helper program to get the password, run it instead. */
+ if (ISSET(flags, TGP_ASKPASS)) {
+ if (askpass == NULL || *askpass == '\0')
+ sudo_fatalx("%s",
+ U_("no askpass program specified, try setting SUDO_ASKPASS"));
+ debug_return_str_masked(sudo_askpass(askpass, prompt));
+ }
+
+ /* Reset state. */
+ for (i = 0; i < NSIG; i++)
+ signo[i] = 0;
+ pass = NULL;
+ save_errno = 0;
+ neednl = false;
+ need_restart = false;
+ feedback = false;
+
+ /* Use tty for reading/writing if available else use stdin/stderr. */
+ if (ttyfd == -1) {
+ input = STDIN_FILENO;
+ output = STDERR_FILENO;
+ /* Don't try to mask password if /dev/tty is not available. */
+ CLR(flags, TGP_MASK);
+ } else {
+ input = ttyfd;
+ output = ttyfd;
+ }
+
+ /*
+ * If we are using a tty but are not the foreground pgrp this will
+ * return EINTR. We send ourself SIGTTOU bracketed by callbacks.
+ */
+ if (!ISSET(flags, TGP_ECHO)) {
+ for (;;) {
+ if (ISSET(flags, TGP_MASK))
+ neednl = feedback = sudo_term_cbreak(input);
+ else
+ neednl = sudo_term_noecho(input);
+ if (neednl || errno != EINTR)
+ break;
+ /* Received SIGTTOU, suspend the process. */
+ if (suspend(SIGTTOU, callback) == -1) {
+ if (ttyfd != -1)
+ (void) close(ttyfd);
+ debug_return_ptr(NULL);
+ }
+ }
+ }
+
+ /*
+ * Catch signals that would otherwise cause the user to end
+ * up with echo turned off in the shell.
+ */
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0; /* don't restart system calls */
+ sa.sa_handler = tgetpass_handler;
+ (void) sigaction(SIGALRM, &sa, &savealrm);
+ (void) sigaction(SIGINT, &sa, &saveint);
+ (void) sigaction(SIGHUP, &sa, &savehup);
+ (void) sigaction(SIGQUIT, &sa, &savequit);
+ (void) sigaction(SIGTERM, &sa, &saveterm);
+ (void) sigaction(SIGTSTP, &sa, &savetstp);
+ (void) sigaction(SIGTTIN, &sa, &savettin);
+ (void) sigaction(SIGTTOU, &sa, &savettou);
+
+ if (ISSET(flags, TGP_BELL) && output != STDERR_FILENO) {
+ /* Ring the bell if requested and there is a tty. */
+ if (write(output, "\a", 1) == -1)
+ goto restore;
+ }
+ if (prompt) {
+ if (write(output, prompt, strlen(prompt)) == -1)
+ goto restore;
+ }
+
+ if (timeout > 0)
+ alarm((unsigned int)timeout);
+ pass = getln(input, buf, sizeof(buf), feedback, &errval);
+ alarm(0);
+ save_errno = errno;
+
+ if (neednl || pass == NULL) {
+ if (write(output, "\n", 1) == -1)
+ goto restore;
+ }
+ tgetpass_display_error(errval);
+
+restore:
+ /* Restore old signal handlers. */
+ (void) sigaction(SIGALRM, &savealrm, NULL);
+ (void) sigaction(SIGINT, &saveint, NULL);
+ (void) sigaction(SIGHUP, &savehup, NULL);
+ (void) sigaction(SIGQUIT, &savequit, NULL);
+ (void) sigaction(SIGTERM, &saveterm, NULL);
+ (void) sigaction(SIGTSTP, &savetstp, NULL);
+ (void) sigaction(SIGTTIN, &savettin, NULL);
+ (void) sigaction(SIGTTOU, &savettou, NULL);
+
+ /* Restore old tty settings. */
+ if (!ISSET(flags, TGP_ECHO)) {
+ /* Restore old tty settings if possible. */
+ if (!sudo_term_restore(input, true))
+ sudo_warn("%s", U_("unable to restore terminal settings"));
+ }
+ if (ttyfd != -1)
+ (void) close(ttyfd);
+
+ /*
+ * If we were interrupted by a signal, resend it to ourselves
+ * now that we have restored the signal handlers.
+ */
+ for (i = 0; i < NSIG; i++) {
+ if (signo[i]) {
+ switch (i) {
+ case SIGALRM:
+ break;
+ case SIGTSTP:
+ case SIGTTIN:
+ case SIGTTOU:
+ if (suspend(i, callback) == 0)
+ need_restart = true;
+ break;
+ default:
+ kill(getpid(), i);
+ break;
+ }
+ }
+ }
+ if (need_restart)
+ goto restart;
+
+ if (save_errno)
+ errno = save_errno;
+
+ debug_return_str_masked(pass);
+}
+
+/*
+ * Fork a child and exec sudo-askpass to get the password from the user.
+ */
+static char *
+sudo_askpass(const char *askpass, const char *prompt)
+{
+ static char buf[SUDO_CONV_REPL_MAX + 1], *pass;
+ const struct sudo_cred *cred = sudo_askpass_cred(NULL);
+ sigset_t chldmask;
+ enum tgetpass_errval errval;
+ int pfd[2], status;
+ pid_t child;
+ debug_decl(sudo_askpass, SUDO_DEBUG_CONV);
+
+ /* Block SIGCHLD for the duration since we call waitpid() below. */
+ sigemptyset(&chldmask);
+ sigaddset(&chldmask, SIGCHLD);
+ (void)sigprocmask(SIG_BLOCK, &chldmask, NULL);
+
+ if (pipe2(pfd, O_CLOEXEC) == -1)
+ sudo_fatal("%s", U_("unable to create pipe"));
+
+ child = sudo_debug_fork();
+ if (child == -1)
+ sudo_fatal("%s", U_("unable to fork"));
+
+ if (child == 0) {
+ /* child, set stdout to write side of the pipe */
+ if (dup3(pfd[1], STDOUT_FILENO, 0) == -1) {
+ sudo_warn("dup3");
+ _exit(255);
+ }
+ if (setuid(ROOT_UID) == -1)
+ sudo_warn("setuid(%d)", ROOT_UID);
+ /* Close fds before uid change to prevent prlimit sabotage on Linux. */
+ closefrom(STDERR_FILENO + 1);
+ /* Run the askpass program with the user's original resource limits. */
+ restore_limits();
+ /* But avoid a setuid() failure on Linux due to RLIMIT_NPROC. */
+ unlimit_nproc();
+ if (setgid(cred->gid)) {
+ sudo_warn(U_("unable to set gid to %u"), (unsigned int)cred->gid);
+ _exit(255);
+ }
+ if (cred->ngroups != -1) {
+ if (sudo_setgroups(cred->ngroups, cred->groups) == -1) {
+ sudo_warn("%s", U_("unable to set supplementary group IDs"));
+ _exit(255);
+ }
+ }
+ if (setuid(cred->uid)) {
+ sudo_warn(U_("unable to set uid to %u"), (unsigned int)cred->uid);
+ _exit(255);
+ }
+ restore_nproc();
+ execl(askpass, askpass, prompt, (char *)NULL);
+ sudo_warn(U_("unable to run %s"), askpass);
+ _exit(255);
+ }
+
+ /* Get response from child (askpass). */
+ (void) close(pfd[1]);
+ pass = getln(pfd[0], buf, sizeof(buf), 0, &errval);
+ (void) close(pfd[0]);
+
+ tgetpass_display_error(errval);
+
+ /* Wait for child to exit. */
+ for (;;) {
+ pid_t rv = waitpid(child, &status, 0);
+ if (rv == -1 && errno != EINTR)
+ break;
+ if (rv != -1 && !WIFSTOPPED(status))
+ break;
+ }
+
+ if (pass == NULL)
+ errno = EINTR; /* make cancel button simulate ^C */
+
+ /* Unblock SIGCHLD. */
+ (void)sigprocmask(SIG_UNBLOCK, &chldmask, NULL);
+
+ debug_return_str_masked(pass);
+}
+
+extern int sudo_term_eof, sudo_term_erase, sudo_term_kill;
+
+static char *
+getln(int fd, char *buf, size_t bufsiz, bool feedback,
+ enum tgetpass_errval *errval)
+{
+ size_t left = bufsiz;
+ ssize_t nr = -1;
+ char *cp = buf;
+ char c = '\0';
+ debug_decl(getln, SUDO_DEBUG_CONV);
+
+ *errval = TGP_ERRVAL_NOERROR;
+
+ if (left == 0) {
+ *errval = TGP_ERRVAL_READERROR;
+ errno = EINVAL;
+ debug_return_str(NULL);
+ }
+
+ while (--left) {
+ nr = read(fd, &c, 1);
+ if (nr != 1 || c == '\n' || c == '\r')
+ break;
+ if (feedback) {
+ if (c == sudo_term_eof) {
+ nr = 0;
+ break;
+ } else if (c == sudo_term_kill) {
+ while (cp > buf) {
+ if (write(fd, "\b \b", 3) == -1)
+ break;
+ cp--;
+ }
+ cp = buf;
+ left = bufsiz;
+ continue;
+ } else if (c == sudo_term_erase) {
+ if (cp > buf) {
+ ignore_result(write(fd, "\b \b", 3));
+ cp--;
+ left++;
+ }
+ continue;
+ }
+ ignore_result(write(fd, "*", 1));
+ }
+ *cp++ = c;
+ }
+ *cp = '\0';
+ if (feedback) {
+ /* erase stars */
+ while (cp > buf) {
+ if (write(fd, "\b \b", 3) == -1)
+ break;
+ --cp;
+ }
+ }
+
+ switch (nr) {
+ case -1:
+ /* Read error */
+ if (errno == EINTR) {
+ if (signo[SIGALRM] == 1)
+ *errval = TGP_ERRVAL_TIMEOUT;
+ } else {
+ *errval = TGP_ERRVAL_READERROR;
+ }
+ debug_return_str(NULL);
+ case 0:
+ /* EOF is only an error if no bytes were read. */
+ if (left == bufsiz - 1) {
+ *errval = TGP_ERRVAL_NOPASSWORD;
+ debug_return_str(NULL);
+ }
+ FALLTHROUGH;
+ default:
+ debug_return_str_masked(buf);
+ }
+}
+
+static void
+tgetpass_handler(int s)
+{
+ signo[s] = 1;
+}
+
+const struct sudo_cred *
+sudo_askpass_cred(const struct sudo_cred *cred)
+{
+ static const struct sudo_cred *saved_cred;
+
+ if (cred != NULL)
+ saved_cred = cred;
+ return saved_cred;
+}
diff --git a/src/ttyname.c b/src/ttyname.c
new file mode 100644
index 0000000..45f8c21
--- /dev/null
+++ b/src/ttyname.c
@@ -0,0 +1,378 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2012-2022 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+/* Large files not supported by procfs.h on Solaris. */
+#if defined(HAVE_STRUCT_PSINFO_PR_TTYDEV)
+# undef _FILE_OFFSET_BITS
+# undef _LARGE_FILES
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined(MAJOR_IN_MKDEV)
+# include <sys/mkdev.h>
+#elif defined(MAJOR_IN_SYSMACROS)
+# include <sys/sysmacros.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <dirent.h>
+#if defined(HAVE_KINFO_PROC2_NETBSD) || defined (HAVE_KINFO_PROC_OPENBSD) || defined(HAVE_KINFO_PROC_44BSD)
+# include <sys/sysctl.h>
+#elif defined(HAVE_KINFO_PROC_FREEBSD) || defined(HAVE_KINFO_PROC_DFLY)
+# include <sys/param.h>
+# include <sys/sysctl.h>
+# include <sys/user.h>
+#endif
+#if defined(HAVE_PROCFS_H)
+# include <procfs.h>
+#elif defined(HAVE_SYS_PROCFS_H)
+# include <sys/procfs.h>
+#endif
+#ifdef HAVE_PSTAT_GETPROC
+# include <sys/pstat.h>
+#endif
+
+#include <sudo.h>
+
+/*
+ * How to access the tty device number in struct kinfo_proc.
+ */
+#if defined(HAVE_KINFO_PROC2_NETBSD)
+# define SUDO_KERN_PROC KERN_PROC2
+# define sudo_kinfo_proc kinfo_proc2
+# define sudo_kp_tdev p_tdev
+# define sudo_kp_namelen 6
+#elif defined(HAVE_KINFO_PROC_OPENBSD)
+# define SUDO_KERN_PROC KERN_PROC
+# define sudo_kinfo_proc kinfo_proc
+# define sudo_kp_tdev p_tdev
+# define sudo_kp_namelen 6
+#elif defined(HAVE_KINFO_PROC_FREEBSD)
+# define SUDO_KERN_PROC KERN_PROC
+# define sudo_kinfo_proc kinfo_proc
+# define sudo_kp_tdev ki_tdev
+# define sudo_kp_namelen 4
+#elif defined(HAVE_KINFO_PROC_DFLY)
+# define SUDO_KERN_PROC KERN_PROC
+# define sudo_kinfo_proc kinfo_proc
+# define sudo_kp_tdev kp_tdev
+# define sudo_kp_namelen 4
+#elif defined(HAVE_KINFO_PROC_44BSD)
+# define SUDO_KERN_PROC KERN_PROC
+# define sudo_kinfo_proc kinfo_proc
+# define sudo_kp_tdev kp_eproc.e_tdev
+# define sudo_kp_namelen 4
+#endif
+
+#if defined(sudo_kp_tdev)
+/*
+ * Store the name of the tty to which the process is attached in name.
+ * Returns name on success and NULL on failure, setting errno.
+ */
+char *
+get_process_ttyname(char *name, size_t namelen)
+{
+ struct sudo_kinfo_proc *ki_proc = NULL;
+ size_t size = sizeof(*ki_proc);
+ int mib[6], rc, serrno = errno;
+ char *ret = NULL;
+ debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL);
+
+ /*
+ * Lookup controlling tty for this process via sysctl.
+ * This will work even if std{in,out,err} are redirected.
+ */
+ mib[0] = CTL_KERN;
+ mib[1] = SUDO_KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = (int)getpid();
+ mib[4] = sizeof(*ki_proc);
+ mib[5] = 1;
+ for (;;) {
+ struct sudo_kinfo_proc *kp;
+
+ size += size / 10;
+ if ((kp = realloc(ki_proc, size)) == NULL) {
+ rc = -1;
+ break; /* really out of memory. */
+ }
+ ki_proc = kp;
+ rc = sysctl(mib, sudo_kp_namelen, ki_proc, &size, NULL, 0);
+ if (rc != -1 || errno != ENOMEM)
+ break;
+ }
+ errno = ENOENT;
+ if (rc != -1) {
+ if ((dev_t)ki_proc->sudo_kp_tdev != (dev_t)-1) {
+ errno = serrno;
+ ret = sudo_ttyname_dev((dev_t)ki_proc->sudo_kp_tdev, name, namelen);
+ if (ret == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to map device number %lu to name",
+ (unsigned long)ki_proc->sudo_kp_tdev);
+ }
+ }
+ } else {
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to resolve tty via KERN_PROC");
+ }
+ free(ki_proc);
+
+ debug_return_str(ret);
+}
+#elif defined(HAVE_STRUCT_PSINFO_PR_TTYDEV)
+/*
+ * Store the name of the tty to which the process is attached in name.
+ * Returns name on success and NULL on failure, setting errno.
+ */
+char *
+get_process_ttyname(char *name, size_t namelen)
+{
+ char path[PATH_MAX], *ret = NULL;
+ struct psinfo psinfo;
+ ssize_t nread;
+ int fd, serrno = errno;
+ debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL);
+
+ /* Try to determine the tty from pr_ttydev in /proc/pid/psinfo. */
+ (void)snprintf(path, sizeof(path), "/proc/%u/psinfo", (unsigned int)getpid());
+ if ((fd = open(path, O_RDONLY, 0)) != -1) {
+ nread = read(fd, &psinfo, sizeof(psinfo));
+ close(fd);
+ if (nread == (ssize_t)sizeof(psinfo)) {
+ dev_t rdev = (dev_t)psinfo.pr_ttydev;
+#if defined(_AIX) && defined(DEVNO64)
+ if ((psinfo.pr_ttydev & DEVNO64) && sizeof(dev_t) == 4)
+ rdev = makedev(major64(psinfo.pr_ttydev), minor64(psinfo.pr_ttydev));
+#endif
+ if (rdev != (dev_t)-1) {
+ errno = serrno;
+ ret = sudo_ttyname_dev(rdev, name, namelen);
+ goto done;
+ }
+ }
+ } else {
+ struct stat sb;
+ int i;
+
+ /* Missing /proc/pid/psinfo file. */
+ for (i = STDIN_FILENO; i <= STDERR_FILENO; i++) {
+ if (sudo_isatty(i, &sb)) {
+ ret = sudo_ttyname_dev(sb.st_rdev, name, namelen);
+ goto done;
+ }
+ }
+ }
+ errno = ENOENT;
+
+done:
+ if (ret == NULL)
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to resolve tty via %s", path);
+
+ debug_return_str(ret);
+}
+#elif defined(__linux__)
+/*
+ * Store the name of the tty to which the process is attached in name.
+ * Returns name on success and NULL on failure, setting errno.
+ */
+char *
+get_process_ttyname(char *name, size_t namelen)
+{
+ const char path[] = "/proc/self/stat";
+ char *cp, buf[1024];
+ char *ret = NULL;
+ int serrno = errno;
+ pid_t ppid = 0;
+ ssize_t nread;
+ int fd;
+ debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL);
+
+ /*
+ * Try to determine the tty from tty_nr in /proc/self/stat.
+ * Ignore /proc/self/stat if it contains embedded NUL bytes.
+ */
+ if ((fd = open(path, O_RDONLY | O_NOFOLLOW)) != -1) {
+ cp = buf;
+ while ((nread = read(fd, cp, sizeof(buf) - (size_t)(cp - buf))) != 0) {
+ if (nread == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ break;
+ }
+ cp += nread;
+ if (cp >= buf + sizeof(buf))
+ break;
+ }
+ if (nread == 0 && memchr(buf, '\0', (size_t)(cp - buf)) == NULL) {
+ /*
+ * Field 7 is the tty dev (0 if no tty).
+ * Since the process name at field 2 "(comm)" may include
+ * whitespace (including newlines), start at the last ')' found.
+ */
+ *cp = '\0';
+ cp = strrchr(buf, ')');
+ if (cp != NULL) {
+ char *ep = cp;
+ const char *errstr;
+ int field = 1;
+
+ while (*++ep != '\0') {
+ if (*ep == ' ') {
+ *ep = '\0';
+ field++;
+ if (field == 7) {
+ int tty_nr = (int)sudo_strtonum(cp, INT_MIN,
+ INT_MAX, &errstr);
+ if (errstr) {
+ sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
+ "%s: tty device %s: %s", path, cp, errstr);
+ }
+ if (tty_nr != 0) {
+ /*
+ * Avoid sign extension when assigning tdev.
+ * tty_nr in /proc/self/stat is printed as a
+ * signed int but the actual device number is an
+ * unsigned int and dev_t is unsigned long long.
+ */
+ dev_t tdev = (unsigned int)tty_nr;
+ errno = serrno;
+ ret = sudo_ttyname_dev(tdev, name, namelen);
+ goto done;
+ }
+ break;
+ }
+ if (field == 3) {
+ ppid =
+ (int)sudo_strtonum(cp, INT_MIN, INT_MAX, NULL);
+ }
+ cp = ep + 1;
+ }
+ }
+ }
+ }
+ }
+ if (ppid == 0) {
+ struct stat sb;
+ int i;
+
+ /* No parent pid found, /proc/self/stat is missing or corrupt. */
+ for (i = STDIN_FILENO; i <= STDERR_FILENO; i++) {
+ if (sudo_isatty(i, &sb)) {
+ ret = sudo_ttyname_dev(sb.st_rdev, name, namelen);
+ goto done;
+ }
+ }
+ }
+ errno = ENOENT;
+
+done:
+ if (fd != -1)
+ close(fd);
+ if (ret == NULL)
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to resolve tty via %s", path);
+
+ debug_return_str(ret);
+}
+#elif defined(HAVE_PSTAT_GETPROC)
+/*
+ * Store the name of the tty to which the process is attached in name.
+ * Returns name on success and NULL on failure, setting errno.
+ */
+char *
+get_process_ttyname(char *name, size_t namelen)
+{
+ struct pst_status pst;
+ char *ret = NULL;
+ int rc, serrno = errno;
+ debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL);
+
+ /*
+ * Determine the tty from psdev in struct pst_status.
+ * EOVERFLOW is not a fatal error for the fields we use.
+ * See the "EOVERFLOW Error" section of pstat_getvminfo(3).
+ */
+ rc = pstat_getproc(&pst, sizeof(pst), 0, getpid());
+ if (rc != -1 || errno == EOVERFLOW) {
+ if (pst.pst_term.psd_major != -1 && pst.pst_term.psd_minor != -1) {
+ errno = serrno;
+ ret = sudo_ttyname_dev(makedev(pst.pst_term.psd_major,
+ pst.pst_term.psd_minor), name, namelen);
+ goto done;
+ }
+ }
+ errno = ENOENT;
+
+done:
+ if (ret == NULL)
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to resolve tty via pstat");
+
+ debug_return_str(ret);
+}
+#else
+/*
+ * Store the name of the tty to which the process is attached in name.
+ * Returns name on success and NULL on failure, setting errno.
+ */
+char *
+get_process_ttyname(char *name, size_t namelen)
+{
+ struct stat sb;
+ char *tty;
+ int i;
+ debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL);
+
+ for (i = STDIN_FILENO; i <= STDERR_FILENO; i++) {
+ /* Only call ttyname() on a character special device. */
+ if (fstat(i, &sb) == -1 || !S_ISCHR(sb.st_mode))
+ continue;
+ if ((tty = ttyname(i)) == NULL)
+ continue;
+
+ if (strlcpy(name, tty, namelen) >= namelen) {
+ errno = ENAMETOOLONG;
+ sudo_debug_printf(
+ SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to store tty from ttyname");
+ debug_return_str(NULL);
+ }
+ debug_return_str(name);
+ }
+
+ sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
+ "unable to resolve tty via ttyname");
+ errno = ENOENT;
+ debug_return_str(NULL);
+}
+#endif
diff --git a/src/utmp.c b/src/utmp.c
new file mode 100644
index 0000000..7ce683d
--- /dev/null
+++ b/src/utmp.c
@@ -0,0 +1,385 @@
+/*
+ * SPDX-License-Identifier: ISC
+ *
+ * Copyright (c) 2011-2018 Todd C. Miller <Todd.Miller@sudo.ws>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is an open source non-commercial project. Dear PVS-Studio, please check it.
+ * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+ */
+
+#include <config.h>
+
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#if defined(HAVE_UTMPS_H)
+# include <utmps.h>
+#elif defined(HAVE_UTMPX_H)
+# include <utmpx.h>
+#else
+# include <utmp.h>
+#endif /* HAVE_UTMPS_H */
+#ifdef HAVE_GETTTYENT
+# include <ttyent.h>
+#endif
+#include <fcntl.h>
+#include <signal.h>
+
+#include <sudo.h>
+#include <sudo_exec.h>
+
+/*
+ * GCC 8 warns about strncpy() where the size field is the size of the buffer.
+ * However, strings in utmp may not be NUL terminated so this usage is correct.
+ */
+#if __GNUC_PREREQ__(8, 0)
+# pragma GCC diagnostic ignored "-Wstringop-truncation"
+#endif
+
+/*
+ * Simplify handling of different utmp types.
+ */
+#if defined(HAVE_GETUTSID)
+# define sudo_getutline(u) GETUTSLINE(u)
+# define sudo_pututline(u) PUTUTSLINE(u)
+# define sudo_setutent() SETUTSENT()
+# define sudo_endutent() ENDUTSENT()
+#elif defined(HAVE_GETUTXID)
+# define sudo_getutline(u) getutxline(u)
+# define sudo_pututline(u) pututxline(u)
+# define sudo_setutent() setutxent()
+# define sudo_endutent() endutxent()
+#elif defined(HAVE_GETUTID)
+# define sudo_getutline(u) getutline(u)
+# define sudo_pututline(u) pututline(u)
+# define sudo_setutent() setutent()
+# define sudo_endutent() endutent()
+#endif
+
+#if defined(HAVE_GETUTSID)
+typedef struct utmps sudo_utmp_t;
+#elif defined(HAVE_GETUTXID)
+typedef struct utmpx sudo_utmp_t;
+#else
+typedef struct utmp sudo_utmp_t;
+/* Older systems have ut_name, not ut_user */
+# if !defined(HAVE_STRUCT_UTMP_UT_USER) && !defined(ut_user)
+# define ut_user ut_name
+# endif
+#endif
+
+/* HP-UX has __e_termination and __e_exit, others may lack the __ */
+#if defined(HAVE_STRUCT_UTMP_UT_EXIT_E_TERMINATION)
+# undef __e_termination
+# define __e_termination e_termination
+# undef __e_exit
+# define __e_exit e_exit
+#endif
+
+#if defined(HAVE_STRUCT_UTMP_UT_ID)
+/*
+ * Create ut_id from the new ut_line and the old ut_id.
+ */
+static void
+utmp_setid(sudo_utmp_t *old, sudo_utmp_t *new)
+{
+ const char *line = new->ut_line;
+ size_t idlen;
+ debug_decl(utmp_setid, SUDO_DEBUG_UTMP);
+
+ /* Skip over "tty" in the id if old entry did too. */
+ if (old != NULL) {
+ /* cppcheck-suppress uninitdata */
+ if (strncmp(line, "tty", 3) == 0) {
+ idlen = MIN(sizeof(old->ut_id), 3);
+ if (strncmp(old->ut_id, "tty", idlen) != 0)
+ line += 3;
+ }
+ }
+
+ /* Store as much as will fit, skipping parts of the beginning as needed. */
+ /* cppcheck-suppress uninitdata */
+ idlen = strlen(line);
+ if (idlen > sizeof(new->ut_id)) {
+ line += idlen - sizeof(new->ut_id);
+ idlen = sizeof(new->ut_id);
+ }
+ strncpy(new->ut_id, line, idlen);
+
+ debug_return;
+}
+#endif /* HAVE_STRUCT_UTMP_UT_ID */
+
+/*
+ * Store time in utmp structure.
+ */
+static void
+utmp_settime(sudo_utmp_t *ut)
+{
+ struct timeval tv;
+ debug_decl(utmp_settime, SUDO_DEBUG_UTMP);
+
+ if (gettimeofday(&tv, NULL) == 0) {
+#if defined(HAVE_STRUCT_UTMP_UT_TV)
+ ut->ut_tv.tv_sec = tv.tv_sec;
+ ut->ut_tv.tv_usec = tv.tv_usec;
+#else
+ ut->ut_time = tv.tv_sec;
+#endif
+ }
+
+ debug_return;
+}
+
+/*
+ * Fill in a utmp entry, using an old entry as a template if there is one.
+ */
+static void
+utmp_fill(const char *line, const char *user, sudo_utmp_t *ut_old,
+ sudo_utmp_t *ut_new)
+{
+ debug_decl(utmp_file, SUDO_DEBUG_UTMP);
+
+ if (ut_old == NULL) {
+ memset(ut_new, 0, sizeof(*ut_new));
+ } else if (ut_old != ut_new) {
+ memcpy(ut_new, ut_old, sizeof(*ut_new));
+ }
+ strncpy(ut_new->ut_user, user, sizeof(ut_new->ut_user));
+ strncpy(ut_new->ut_line, line, sizeof(ut_new->ut_line));
+#if defined(HAVE_STRUCT_UTMP_UT_ID)
+ utmp_setid(ut_old, ut_new);
+#endif
+#if defined(HAVE_STRUCT_UTMP_UT_PID)
+ ut_new->ut_pid = getpid();
+#endif
+ utmp_settime(ut_new);
+#if defined(HAVE_STRUCT_UTMP_UT_TYPE)
+ ut_new->ut_type = USER_PROCESS;
+#endif
+ debug_return;
+}
+
+/*
+ * There are two basic utmp file types:
+ *
+ * POSIX: sequential access with new entries appended to the end.
+ * Manipulated via {get,put}[sx]?utent()
+ *
+ * Legacy: sparse file indexed by ttyslot() * sizeof(struct utmp)
+ */
+#if defined(HAVE_GETUTSID) || defined(HAVE_GETUTXID) || defined(HAVE_GETUTID)
+bool
+utmp_login(const char *from_line, const char *to_line, int ttyfd,
+ const char *user)
+{
+ sudo_utmp_t utbuf, *ut_old = NULL;
+ bool ret = false;
+ debug_decl(utmp_login, SUDO_DEBUG_UTMP);
+
+ /* Strip off /dev/ prefix from line as needed. */
+ if (strncmp(to_line, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
+ to_line += sizeof(_PATH_DEV) - 1;
+ sudo_setutent();
+ if (from_line != NULL) {
+ if (strncmp(from_line, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
+ from_line += sizeof(_PATH_DEV) - 1;
+
+ /* Lookup old line. */
+ memset(&utbuf, 0, sizeof(utbuf));
+ strncpy(utbuf.ut_line, from_line, sizeof(utbuf.ut_line));
+ ut_old = sudo_getutline(&utbuf);
+ sudo_setutent();
+ }
+ utmp_fill(to_line, user, ut_old, &utbuf);
+ if (sudo_pututline(&utbuf) != NULL)
+ ret = true;
+ sudo_endutent();
+
+ debug_return_bool(ret);
+}
+
+bool
+utmp_logout(const char *line, int status)
+{
+ bool ret = false;
+ sudo_utmp_t *ut, utbuf;
+ debug_decl(utmp_logout, SUDO_DEBUG_UTMP);
+
+ /* Strip off /dev/ prefix from line as needed. */
+ if (strncmp(line, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
+ line += sizeof(_PATH_DEV) - 1;
+
+ memset(&utbuf, 0, sizeof(utbuf));
+ strncpy(utbuf.ut_line, line, sizeof(utbuf.ut_line));
+ if ((ut = sudo_getutline(&utbuf)) != NULL) {
+ memset(ut->ut_user, 0, sizeof(ut->ut_user));
+# if defined(HAVE_STRUCT_UTMP_UT_TYPE)
+ ut->ut_type = DEAD_PROCESS;
+# endif
+# if defined(HAVE_STRUCT_UTMP_UT_EXIT)
+ ut->ut_exit.__e_termination = WIFSIGNALED(status) ? WTERMSIG(status) : 0;
+ ut->ut_exit.__e_exit = WIFEXITED(status) ? WEXITSTATUS(status) : 0;
+# endif
+ utmp_settime(ut);
+ if (sudo_pututline(ut) != NULL)
+ ret = true;
+ }
+ debug_return_bool(ret);
+}
+
+#else /* !HAVE_GETUTSID && !HAVE_GETUTXID && !HAVE_GETUTID */
+
+/*
+ * Find the slot for the specified line (tty name and file descriptor).
+ * Returns a slot suitable for seeking into utmp on success or <= 0 on error.
+ * If getttyent() is available we can use that to compute the slot.
+ */
+# ifdef HAVE_GETTTYENT
+static int
+utmp_slot(const char *line, int ttyfd)
+{
+ int slot = 1;
+ struct ttyent *tty;
+ debug_decl(utmp_slot, SUDO_DEBUG_UTMP);
+
+ setttyent();
+ while ((tty = getttyent()) != NULL) {
+ if (strcmp(line, tty->ty_name) == 0)
+ break;
+ slot++;
+ }
+ endttyent();
+ debug_return_int(tty ? slot : 0);
+}
+# elif defined(HAVE_TTYSLOT)
+static int
+utmp_slot(const char *line, int ttyfd)
+{
+ int sfd, slot;
+ debug_decl(utmp_slot, SUDO_DEBUG_UTMP);
+
+ /*
+ * Temporarily point stdin to the tty since ttyslot()
+ * doesn't take an argument.
+ */
+ if ((sfd = dup(STDIN_FILENO)) == -1)
+ sudo_fatal("%s", U_("unable to save stdin"));
+ if (dup2(ttyfd, STDIN_FILENO) == -1)
+ sudo_fatal("%s", U_("unable to dup2 stdin"));
+ slot = ttyslot();
+ if (dup2(sfd, STDIN_FILENO) == -1)
+ sudo_fatal("%s", U_("unable to restore stdin"));
+ close(sfd);
+
+ debug_return_int(slot);
+}
+# else /* !HAVE_TTYSLOT */
+static int
+utmp_slot(const char *line, int ttyfd)
+{
+ return -1;
+}
+# endif /* HAVE_GETTTYENT */
+
+bool
+utmp_login(const char *from_line, const char *to_line, int ttyfd,
+ const char *user)
+{
+ sudo_utmp_t utbuf, *ut_old = NULL;
+ bool ret = false;
+ int slot;
+ FILE *fp;
+ debug_decl(utmp_login, SUDO_DEBUG_UTMP);
+
+ /* Strip off /dev/ prefix from line as needed. */
+ if (strncmp(to_line, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
+ to_line += sizeof(_PATH_DEV) - 1;
+
+ /* Find slot for new entry. */
+ slot = utmp_slot(to_line, ttyfd);
+ if (slot <= 0)
+ goto done;
+
+ if ((fp = fopen(_PATH_UTMP, "r+")) == NULL)
+ goto done;
+
+ if (from_line != NULL) {
+ if (strncmp(from_line, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
+ from_line += sizeof(_PATH_DEV) - 1;
+
+ /* Lookup old line. */
+ while (fread(&utbuf, sizeof(utbuf), 1, fp) == 1) {
+# ifdef HAVE_STRUCT_UTMP_UT_ID
+ if (utbuf.ut_type != LOGIN_PROCESS && utbuf.ut_type != USER_PROCESS)
+ continue;
+# endif
+ if (utbuf.ut_user[0] &&
+ !strncmp(utbuf.ut_line, from_line, sizeof(utbuf.ut_line))) {
+ ut_old = &utbuf;
+ break;
+ }
+ }
+ }
+ utmp_fill(to_line, user, ut_old, &utbuf);
+ if (fseeko(fp, slot * (off_t)sizeof(utbuf), SEEK_SET) == 0) {
+ if (fwrite(&utbuf, sizeof(utbuf), 1, fp) == 1)
+ ret = true;
+ }
+ fclose(fp);
+
+done:
+ debug_return_bool(ret);
+}
+
+bool
+utmp_logout(const char *line, int status)
+{
+ sudo_utmp_t utbuf;
+ bool ret = false;
+ FILE *fp;
+ debug_decl(utmp_logout, SUDO_DEBUG_UTMP);
+
+ if ((fp = fopen(_PATH_UTMP, "r+")) == NULL)
+ debug_return_int(ret);
+
+ /* Strip off /dev/ prefix from line as needed. */
+ if (strncmp(line, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
+ line += sizeof(_PATH_DEV) - 1;
+
+ while (fread(&utbuf, sizeof(utbuf), 1, fp) == 1) {
+ if (!strncmp(utbuf.ut_line, line, sizeof(utbuf.ut_line))) {
+ memset(utbuf.ut_user, 0, sizeof(utbuf.ut_user));
+# if defined(HAVE_STRUCT_UTMP_UT_TYPE)
+ utbuf.ut_type = DEAD_PROCESS;
+# endif
+ utmp_settime(&utbuf);
+ /* Back up and overwrite record. */
+ if (fseeko(fp, (off_t)0 - (off_t)sizeof(utbuf), SEEK_CUR) == 0) {
+ if (fwrite(&utbuf, sizeof(utbuf), 1, fp) == 1)
+ ret = true;
+ }
+ break;
+ }
+ }
+ fclose(fp);
+
+ debug_return_bool(ret);
+}
+#endif /* HAVE_GETUTSID || HAVE_GETUTXID || HAVE_GETUTID */